Initial commit of llgo third_party.

llvm-svn: 222858
GitOrigin-RevId: 594c10de22daf423311b4a4c72d74740b9a21ad1
diff --git a/third_party/go.tools/AUTHORS b/third_party/go.tools/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/third_party/go.tools/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/third_party/go.tools/CONTRIBUTORS b/third_party/go.tools/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/third_party/go.tools/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/third_party/go.tools/LICENSE b/third_party/go.tools/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/third_party/go.tools/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/go.tools/PATENTS b/third_party/go.tools/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/third_party/go.tools/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go.  This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation.  If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/third_party/go.tools/README b/third_party/go.tools/README
new file mode 100644
index 0000000..916ae2e
--- /dev/null
+++ b/third_party/go.tools/README
@@ -0,0 +1,10 @@
+This subrepository holds the source for various packages and tools that support
+the Go programming language.
+
+Some of the tools, godoc and vet for example, are included in binary Go distributions.
+Others, including the Go oracle and the test coverage tool, can be fetched with "go get".
+
+Packages include a type-checker for Go and an implementation of the
+Static Single Assignment form (SSA) representation for Go programs.
+
+To submit changes to this repository, see http://golang.org/doc/contribute.html.
diff --git a/third_party/go.tools/astutil/enclosing.go b/third_party/go.tools/astutil/enclosing.go
new file mode 100644
index 0000000..2de739e
--- /dev/null
+++ b/third_party/go.tools/astutil/enclosing.go
@@ -0,0 +1,625 @@
+// Copyright 2013 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 astutil
+
+// This file defines utilities for working with source positions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+)
+
+// PathEnclosingInterval returns the node that encloses the source
+// interval [start, end), and all its ancestors up to the AST root.
+//
+// The definition of "enclosing" used by this function considers
+// additional whitespace abutting a node to be enclosed by it.
+// In this example:
+//
+//              z := x + y // add them
+//                   <-A->
+//                  <----B----->
+//
+// the ast.BinaryExpr(+) node is considered to enclose interval B
+// even though its [Pos()..End()) is actually only interval A.
+// This behaviour makes user interfaces more tolerant of imperfect
+// input.
+//
+// This function treats tokens as nodes, though they are not included
+// in the result. e.g. PathEnclosingInterval("+") returns the
+// enclosing ast.BinaryExpr("x + y").
+//
+// If start==end, the 1-char interval following start is used instead.
+//
+// The 'exact' result is true if the interval contains only path[0]
+// and perhaps some adjacent whitespace.  It is false if the interval
+// overlaps multiple children of path[0], or if it contains only
+// interior whitespace of path[0].
+// In this example:
+//
+//              z := x + y // add them
+//                <--C-->     <---E-->
+//                  ^
+//                  D
+//
+// intervals C, D and E are inexact.  C is contained by the
+// z-assignment statement, because it spans three of its children (:=,
+// x, +).  So too is the 1-char interval D, because it contains only
+// interior whitespace of the assignment.  E is considered interior
+// whitespace of the BlockStmt containing the assignment.
+//
+// Precondition: [start, end) both lie within the same file as root.
+// TODO(adonovan): return (nil, false) in this case and remove precond.
+// Requires FileSet; see loader.tokenFileContainsPos.
+//
+// Postcondition: path is never nil; it always contains at least 'root'.
+//
+func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Node, exact bool) {
+	// fmt.Printf("EnclosingInterval %d %d\n", start, end) // debugging
+
+	// Precondition: node.[Pos..End) and adjoining whitespace contain [start, end).
+	var visit func(node ast.Node) bool
+	visit = func(node ast.Node) bool {
+		path = append(path, node)
+
+		nodePos := node.Pos()
+		nodeEnd := node.End()
+
+		// fmt.Printf("visit(%T, %d, %d)\n", node, nodePos, nodeEnd) // debugging
+
+		// Intersect [start, end) with interval of node.
+		if start < nodePos {
+			start = nodePos
+		}
+		if end > nodeEnd {
+			end = nodeEnd
+		}
+
+		// Find sole child that contains [start, end).
+		children := childrenOf(node)
+		l := len(children)
+		for i, child := range children {
+			// [childPos, childEnd) is unaugmented interval of child.
+			childPos := child.Pos()
+			childEnd := child.End()
+
+			// [augPos, augEnd) is whitespace-augmented interval of child.
+			augPos := childPos
+			augEnd := childEnd
+			if i > 0 {
+				augPos = children[i-1].End() // start of preceding whitespace
+			}
+			if i < l-1 {
+				nextChildPos := children[i+1].Pos()
+				// Does [start, end) lie between child and next child?
+				if start >= augEnd && end <= nextChildPos {
+					return false // inexact match
+				}
+				augEnd = nextChildPos // end of following whitespace
+			}
+
+			// fmt.Printf("\tchild %d: [%d..%d)\tcontains interval [%d..%d)?\n",
+			// 	i, augPos, augEnd, start, end) // debugging
+
+			// Does augmented child strictly contain [start, end)?
+			if augPos <= start && end <= augEnd {
+				_, isToken := child.(tokenNode)
+				return isToken || visit(child)
+			}
+
+			// Does [start, end) overlap multiple children?
+			// i.e. left-augmented child contains start
+			// but LR-augmented child does not contain end.
+			if start < childEnd && end > augEnd {
+				break
+			}
+		}
+
+		// No single child contained [start, end),
+		// so node is the result.  Is it exact?
+
+		// (It's tempting to put this condition before the
+		// child loop, but it gives the wrong result in the
+		// case where a node (e.g. ExprStmt) and its sole
+		// child have equal intervals.)
+		if start == nodePos && end == nodeEnd {
+			return true // exact match
+		}
+
+		return false // inexact: overlaps multiple children
+	}
+
+	if start > end {
+		start, end = end, start
+	}
+
+	if start < root.End() && end > root.Pos() {
+		if start == end {
+			end = start + 1 // empty interval => interval of size 1
+		}
+		exact = visit(root)
+
+		// Reverse the path:
+		for i, l := 0, len(path); i < l/2; i++ {
+			path[i], path[l-1-i] = path[l-1-i], path[i]
+		}
+	} else {
+		// Selection lies within whitespace preceding the
+		// first (or following the last) declaration in the file.
+		// The result nonetheless always includes the ast.File.
+		path = append(path, root)
+	}
+
+	return
+}
+
+// tokenNode is a dummy implementation of ast.Node for a single token.
+// They are used transiently by PathEnclosingInterval but never escape
+// this package.
+//
+type tokenNode struct {
+	pos token.Pos
+	end token.Pos
+}
+
+func (n tokenNode) Pos() token.Pos {
+	return n.pos
+}
+
+func (n tokenNode) End() token.Pos {
+	return n.end
+}
+
+func tok(pos token.Pos, len int) ast.Node {
+	return tokenNode{pos, pos + token.Pos(len)}
+}
+
+// childrenOf returns the direct non-nil children of ast.Node n.
+// It may include fake ast.Node implementations for bare tokens.
+// it is not safe to call (e.g.) ast.Walk on such nodes.
+//
+func childrenOf(n ast.Node) []ast.Node {
+	var children []ast.Node
+
+	// First add nodes for all true subtrees.
+	ast.Inspect(n, func(node ast.Node) bool {
+		if node == n { // push n
+			return true // recur
+		}
+		if node != nil { // push child
+			children = append(children, node)
+		}
+		return false // no recursion
+	})
+
+	// Then add fake Nodes for bare tokens.
+	switch n := n.(type) {
+	case *ast.ArrayType:
+		children = append(children,
+			tok(n.Lbrack, len("[")),
+			tok(n.Elt.End(), len("]")))
+
+	case *ast.AssignStmt:
+		children = append(children,
+			tok(n.TokPos, len(n.Tok.String())))
+
+	case *ast.BasicLit:
+		children = append(children,
+			tok(n.ValuePos, len(n.Value)))
+
+	case *ast.BinaryExpr:
+		children = append(children, tok(n.OpPos, len(n.Op.String())))
+
+	case *ast.BlockStmt:
+		children = append(children,
+			tok(n.Lbrace, len("{")),
+			tok(n.Rbrace, len("}")))
+
+	case *ast.BranchStmt:
+		children = append(children,
+			tok(n.TokPos, len(n.Tok.String())))
+
+	case *ast.CallExpr:
+		children = append(children,
+			tok(n.Lparen, len("(")),
+			tok(n.Rparen, len(")")))
+		if n.Ellipsis != 0 {
+			children = append(children, tok(n.Ellipsis, len("...")))
+		}
+
+	case *ast.CaseClause:
+		if n.List == nil {
+			children = append(children,
+				tok(n.Case, len("default")))
+		} else {
+			children = append(children,
+				tok(n.Case, len("case")))
+		}
+		children = append(children, tok(n.Colon, len(":")))
+
+	case *ast.ChanType:
+		switch n.Dir {
+		case ast.RECV:
+			children = append(children, tok(n.Begin, len("<-chan")))
+		case ast.SEND:
+			children = append(children, tok(n.Begin, len("chan<-")))
+		case ast.RECV | ast.SEND:
+			children = append(children, tok(n.Begin, len("chan")))
+		}
+
+	case *ast.CommClause:
+		if n.Comm == nil {
+			children = append(children,
+				tok(n.Case, len("default")))
+		} else {
+			children = append(children,
+				tok(n.Case, len("case")))
+		}
+		children = append(children, tok(n.Colon, len(":")))
+
+	case *ast.Comment:
+		// nop
+
+	case *ast.CommentGroup:
+		// nop
+
+	case *ast.CompositeLit:
+		children = append(children,
+			tok(n.Lbrace, len("{")),
+			tok(n.Rbrace, len("{")))
+
+	case *ast.DeclStmt:
+		// nop
+
+	case *ast.DeferStmt:
+		children = append(children,
+			tok(n.Defer, len("defer")))
+
+	case *ast.Ellipsis:
+		children = append(children,
+			tok(n.Ellipsis, len("...")))
+
+	case *ast.EmptyStmt:
+		// nop
+
+	case *ast.ExprStmt:
+		// nop
+
+	case *ast.Field:
+		// TODO(adonovan): Field.{Doc,Comment,Tag}?
+
+	case *ast.FieldList:
+		children = append(children,
+			tok(n.Opening, len("(")),
+			tok(n.Closing, len(")")))
+
+	case *ast.File:
+		// TODO test: Doc
+		children = append(children,
+			tok(n.Package, len("package")))
+
+	case *ast.ForStmt:
+		children = append(children,
+			tok(n.For, len("for")))
+
+	case *ast.FuncDecl:
+		// TODO(adonovan): FuncDecl.Comment?
+
+		// Uniquely, FuncDecl breaks the invariant that
+		// preorder traversal yields tokens in lexical order:
+		// in fact, FuncDecl.Recv precedes FuncDecl.Type.Func.
+		//
+		// As a workaround, we inline the case for FuncType
+		// here and order things correctly.
+		//
+		children = nil // discard ast.Walk(FuncDecl) info subtrees
+		children = append(children, tok(n.Type.Func, len("func")))
+		if n.Recv != nil {
+			children = append(children, n.Recv)
+		}
+		children = append(children, n.Name)
+		if n.Type.Params != nil {
+			children = append(children, n.Type.Params)
+		}
+		if n.Type.Results != nil {
+			children = append(children, n.Type.Results)
+		}
+		if n.Body != nil {
+			children = append(children, n.Body)
+		}
+
+	case *ast.FuncLit:
+		// nop
+
+	case *ast.FuncType:
+		if n.Func != 0 {
+			children = append(children,
+				tok(n.Func, len("func")))
+		}
+
+	case *ast.GenDecl:
+		children = append(children,
+			tok(n.TokPos, len(n.Tok.String())))
+		if n.Lparen != 0 {
+			children = append(children,
+				tok(n.Lparen, len("(")),
+				tok(n.Rparen, len(")")))
+		}
+
+	case *ast.GoStmt:
+		children = append(children,
+			tok(n.Go, len("go")))
+
+	case *ast.Ident:
+		children = append(children,
+			tok(n.NamePos, len(n.Name)))
+
+	case *ast.IfStmt:
+		children = append(children,
+			tok(n.If, len("if")))
+
+	case *ast.ImportSpec:
+		// TODO(adonovan): ImportSpec.{Doc,EndPos}?
+
+	case *ast.IncDecStmt:
+		children = append(children,
+			tok(n.TokPos, len(n.Tok.String())))
+
+	case *ast.IndexExpr:
+		children = append(children,
+			tok(n.Lbrack, len("{")),
+			tok(n.Rbrack, len("}")))
+
+	case *ast.InterfaceType:
+		children = append(children,
+			tok(n.Interface, len("interface")))
+
+	case *ast.KeyValueExpr:
+		children = append(children,
+			tok(n.Colon, len(":")))
+
+	case *ast.LabeledStmt:
+		children = append(children,
+			tok(n.Colon, len(":")))
+
+	case *ast.MapType:
+		children = append(children,
+			tok(n.Map, len("map")))
+
+	case *ast.ParenExpr:
+		children = append(children,
+			tok(n.Lparen, len("(")),
+			tok(n.Rparen, len(")")))
+
+	case *ast.RangeStmt:
+		children = append(children,
+			tok(n.For, len("for")),
+			tok(n.TokPos, len(n.Tok.String())))
+
+	case *ast.ReturnStmt:
+		children = append(children,
+			tok(n.Return, len("return")))
+
+	case *ast.SelectStmt:
+		children = append(children,
+			tok(n.Select, len("select")))
+
+	case *ast.SelectorExpr:
+		// nop
+
+	case *ast.SendStmt:
+		children = append(children,
+			tok(n.Arrow, len("<-")))
+
+	case *ast.SliceExpr:
+		children = append(children,
+			tok(n.Lbrack, len("[")),
+			tok(n.Rbrack, len("]")))
+
+	case *ast.StarExpr:
+		children = append(children, tok(n.Star, len("*")))
+
+	case *ast.StructType:
+		children = append(children, tok(n.Struct, len("struct")))
+
+	case *ast.SwitchStmt:
+		children = append(children, tok(n.Switch, len("switch")))
+
+	case *ast.TypeAssertExpr:
+		children = append(children,
+			tok(n.Lparen-1, len(".")),
+			tok(n.Lparen, len("(")),
+			tok(n.Rparen, len(")")))
+
+	case *ast.TypeSpec:
+		// TODO(adonovan): TypeSpec.{Doc,Comment}?
+
+	case *ast.TypeSwitchStmt:
+		children = append(children, tok(n.Switch, len("switch")))
+
+	case *ast.UnaryExpr:
+		children = append(children, tok(n.OpPos, len(n.Op.String())))
+
+	case *ast.ValueSpec:
+		// TODO(adonovan): ValueSpec.{Doc,Comment}?
+
+	default:
+		// Includes *ast.BadDecl, *ast.BadExpr, *ast.BadStmt.
+		panic(fmt.Sprintf("unexpected node type %T", n))
+	}
+
+	// TODO(adonovan): opt: merge the logic of ast.Inspect() into
+	// the switch above so we can make interleaved callbacks for
+	// both Nodes and Tokens in the right order and avoid the need
+	// to sort.
+	sort.Sort(byPos(children))
+
+	return children
+}
+
+type byPos []ast.Node
+
+func (sl byPos) Len() int {
+	return len(sl)
+}
+func (sl byPos) Less(i, j int) bool {
+	return sl[i].Pos() < sl[j].Pos()
+}
+func (sl byPos) Swap(i, j int) {
+	sl[i], sl[j] = sl[j], sl[i]
+}
+
+// NodeDescription returns a description of the concrete type of n suitable
+// for a user interface.
+//
+// TODO(adonovan): in some cases (e.g. Field, FieldList, Ident,
+// StarExpr) we could be much more specific given the path to the AST
+// root.  Perhaps we should do that.
+//
+func NodeDescription(n ast.Node) string {
+	switch n := n.(type) {
+	case *ast.ArrayType:
+		return "array type"
+	case *ast.AssignStmt:
+		return "assignment"
+	case *ast.BadDecl:
+		return "bad declaration"
+	case *ast.BadExpr:
+		return "bad expression"
+	case *ast.BadStmt:
+		return "bad statement"
+	case *ast.BasicLit:
+		return "basic literal"
+	case *ast.BinaryExpr:
+		return fmt.Sprintf("binary %s operation", n.Op)
+	case *ast.BlockStmt:
+		return "block"
+	case *ast.BranchStmt:
+		switch n.Tok {
+		case token.BREAK:
+			return "break statement"
+		case token.CONTINUE:
+			return "continue statement"
+		case token.GOTO:
+			return "goto statement"
+		case token.FALLTHROUGH:
+			return "fall-through statement"
+		}
+	case *ast.CallExpr:
+		return "function call (or conversion)"
+	case *ast.CaseClause:
+		return "case clause"
+	case *ast.ChanType:
+		return "channel type"
+	case *ast.CommClause:
+		return "communication clause"
+	case *ast.Comment:
+		return "comment"
+	case *ast.CommentGroup:
+		return "comment group"
+	case *ast.CompositeLit:
+		return "composite literal"
+	case *ast.DeclStmt:
+		return NodeDescription(n.Decl) + " statement"
+	case *ast.DeferStmt:
+		return "defer statement"
+	case *ast.Ellipsis:
+		return "ellipsis"
+	case *ast.EmptyStmt:
+		return "empty statement"
+	case *ast.ExprStmt:
+		return "expression statement"
+	case *ast.Field:
+		// Can be any of these:
+		// struct {x, y int}  -- struct field(s)
+		// struct {T}         -- anon struct field
+		// interface {I}      -- interface embedding
+		// interface {f()}    -- interface method
+		// func (A) func(B) C -- receiver, param(s), result(s)
+		return "field/method/parameter"
+	case *ast.FieldList:
+		return "field/method/parameter list"
+	case *ast.File:
+		return "source file"
+	case *ast.ForStmt:
+		return "for loop"
+	case *ast.FuncDecl:
+		return "function declaration"
+	case *ast.FuncLit:
+		return "function literal"
+	case *ast.FuncType:
+		return "function type"
+	case *ast.GenDecl:
+		switch n.Tok {
+		case token.IMPORT:
+			return "import declaration"
+		case token.CONST:
+			return "constant declaration"
+		case token.TYPE:
+			return "type declaration"
+		case token.VAR:
+			return "variable declaration"
+		}
+	case *ast.GoStmt:
+		return "go statement"
+	case *ast.Ident:
+		return "identifier"
+	case *ast.IfStmt:
+		return "if statement"
+	case *ast.ImportSpec:
+		return "import specification"
+	case *ast.IncDecStmt:
+		if n.Tok == token.INC {
+			return "increment statement"
+		}
+		return "decrement statement"
+	case *ast.IndexExpr:
+		return "index expression"
+	case *ast.InterfaceType:
+		return "interface type"
+	case *ast.KeyValueExpr:
+		return "key/value association"
+	case *ast.LabeledStmt:
+		return "statement label"
+	case *ast.MapType:
+		return "map type"
+	case *ast.Package:
+		return "package"
+	case *ast.ParenExpr:
+		return "parenthesized " + NodeDescription(n.X)
+	case *ast.RangeStmt:
+		return "range loop"
+	case *ast.ReturnStmt:
+		return "return statement"
+	case *ast.SelectStmt:
+		return "select statement"
+	case *ast.SelectorExpr:
+		return "selector"
+	case *ast.SendStmt:
+		return "channel send"
+	case *ast.SliceExpr:
+		return "slice expression"
+	case *ast.StarExpr:
+		return "*-operation" // load/store expr or pointer type
+	case *ast.StructType:
+		return "struct type"
+	case *ast.SwitchStmt:
+		return "switch statement"
+	case *ast.TypeAssertExpr:
+		return "type assertion"
+	case *ast.TypeSpec:
+		return "type specification"
+	case *ast.TypeSwitchStmt:
+		return "type switch"
+	case *ast.UnaryExpr:
+		return fmt.Sprintf("unary %s operation", n.Op)
+	case *ast.ValueSpec:
+		return "value specification"
+
+	}
+	panic(fmt.Sprintf("unexpected node type: %T", n))
+}
diff --git a/third_party/go.tools/astutil/enclosing_test.go b/third_party/go.tools/astutil/enclosing_test.go
new file mode 100644
index 0000000..f155303
--- /dev/null
+++ b/third_party/go.tools/astutil/enclosing_test.go
@@ -0,0 +1,195 @@
+// Copyright 2013 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 astutil_test
+
+// This file defines tests of PathEnclosingInterval.
+
+// TODO(adonovan): exhaustive tests that run over the whole input
+// tree, not just handcrafted examples.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+)
+
+// pathToString returns a string containing the concrete types of the
+// nodes in path.
+func pathToString(path []ast.Node) string {
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "[")
+	for i, n := range path {
+		if i > 0 {
+			fmt.Fprint(&buf, " ")
+		}
+		fmt.Fprint(&buf, strings.TrimPrefix(fmt.Sprintf("%T", n), "*ast."))
+	}
+	fmt.Fprint(&buf, "]")
+	return buf.String()
+}
+
+// findInterval parses input and returns the [start, end) positions of
+// the first occurrence of substr in input.  f==nil indicates failure;
+// an error has already been reported in that case.
+//
+func findInterval(t *testing.T, fset *token.FileSet, input, substr string) (f *ast.File, start, end token.Pos) {
+	f, err := parser.ParseFile(fset, "<input>", input, 0)
+	if err != nil {
+		t.Errorf("parse error: %s", err)
+		return
+	}
+
+	i := strings.Index(input, substr)
+	if i < 0 {
+		t.Errorf("%q is not a substring of input", substr)
+		f = nil
+		return
+	}
+
+	filePos := fset.File(f.Package)
+	return f, filePos.Pos(i), filePos.Pos(i + len(substr))
+}
+
+// Common input for following tests.
+const input = `
+// Hello.
+package main
+import "fmt"
+func f() {}
+func main() {
+	z := (x + y) // add them
+        f() // NB: ExprStmt and its CallExpr have same Pos/End
+}
+`
+
+func TestPathEnclosingInterval_Exact(t *testing.T) {
+	// For the exact tests, we check that a substring is mapped to
+	// the canonical string for the node it denotes.
+	tests := []struct {
+		substr string // first occurrence of this string indicates interval
+		node   string // complete text of expected containing node
+	}{
+		{"package",
+			input[11 : len(input)-1]},
+		{"\npack",
+			input[11 : len(input)-1]},
+		{"main",
+			"main"},
+		{"import",
+			"import \"fmt\""},
+		{"\"fmt\"",
+			"\"fmt\""},
+		{"\nfunc f() {}\n",
+			"func f() {}"},
+		{"x ",
+			"x"},
+		{" y",
+			"y"},
+		{"z",
+			"z"},
+		{" + ",
+			"x + y"},
+		{" :=",
+			"z := (x + y)"},
+		{"x + y",
+			"x + y"},
+		{"(x + y)",
+			"(x + y)"},
+		{" (x + y) ",
+			"(x + y)"},
+		{" (x + y) // add",
+			"(x + y)"},
+		{"func",
+			"func f() {}"},
+		{"func f() {}",
+			"func f() {}"},
+		{"\nfun",
+			"func f() {}"},
+		{" f",
+			"f"},
+	}
+	for _, test := range tests {
+		f, start, end := findInterval(t, new(token.FileSet), input, test.substr)
+		if f == nil {
+			continue
+		}
+
+		path, exact := astutil.PathEnclosingInterval(f, start, end)
+		if !exact {
+			t.Errorf("PathEnclosingInterval(%q) not exact", test.substr)
+			continue
+		}
+
+		if len(path) == 0 {
+			if test.node != "" {
+				t.Errorf("PathEnclosingInterval(%q).path: got [], want %q",
+					test.substr, test.node)
+			}
+			continue
+		}
+
+		if got := input[path[0].Pos():path[0].End()]; got != test.node {
+			t.Errorf("PathEnclosingInterval(%q): got %q, want %q (path was %s)",
+				test.substr, got, test.node, pathToString(path))
+			continue
+		}
+	}
+}
+
+func TestPathEnclosingInterval_Paths(t *testing.T) {
+	// For these tests, we check only the path of the enclosing
+	// node, but not its complete text because it's often quite
+	// large when !exact.
+	tests := []struct {
+		substr string // first occurrence of this string indicates interval
+		path   string // the pathToString(),exact of the expected path
+	}{
+		{"// add",
+			"[BlockStmt FuncDecl File],false"},
+		{"(x + y",
+			"[ParenExpr AssignStmt BlockStmt FuncDecl File],false"},
+		{"x +",
+			"[BinaryExpr ParenExpr AssignStmt BlockStmt FuncDecl File],false"},
+		{"z := (x",
+			"[AssignStmt BlockStmt FuncDecl File],false"},
+		{"func f",
+			"[FuncDecl File],false"},
+		{"func f()",
+			"[FuncDecl File],false"},
+		{" f()",
+			"[FuncDecl File],false"},
+		{"() {}",
+			"[FuncDecl File],false"},
+		{"// Hello",
+			"[File],false"},
+		{" f",
+			"[Ident FuncDecl File],true"},
+		{"func ",
+			"[FuncDecl File],true"},
+		{"mai",
+			"[Ident File],true"},
+		{"f() // NB",
+			"[CallExpr ExprStmt BlockStmt FuncDecl File],true"},
+	}
+	for _, test := range tests {
+		f, start, end := findInterval(t, new(token.FileSet), input, test.substr)
+		if f == nil {
+			continue
+		}
+
+		path, exact := astutil.PathEnclosingInterval(f, start, end)
+		if got := fmt.Sprintf("%s,%v", pathToString(path), exact); got != test.path {
+			t.Errorf("PathEnclosingInterval(%q): got %q, want %q",
+				test.substr, got, test.path)
+			continue
+		}
+	}
+}
diff --git a/third_party/go.tools/astutil/imports.go b/third_party/go.tools/astutil/imports.go
new file mode 100644
index 0000000..27262d3
--- /dev/null
+++ b/third_party/go.tools/astutil/imports.go
@@ -0,0 +1,371 @@
+// Copyright 2013 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 astutil contains common utilities for working with the Go AST.
+package astutil
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"log"
+	"strconv"
+	"strings"
+)
+
+// AddImport adds the import path to the file f, if absent.
+func AddImport(fset *token.FileSet, f *ast.File, ipath string) (added bool) {
+	return AddNamedImport(fset, f, "", ipath)
+}
+
+// AddNamedImport adds the import path to the file f, if absent.
+// If name is not empty, it is used to rename the import.
+//
+// For example, calling
+//	AddNamedImport(fset, f, "pathpkg", "path")
+// adds
+//	import pathpkg "path"
+func AddNamedImport(fset *token.FileSet, f *ast.File, name, ipath string) (added bool) {
+	if imports(f, ipath) {
+		return false
+	}
+
+	newImport := &ast.ImportSpec{
+		Path: &ast.BasicLit{
+			Kind:  token.STRING,
+			Value: strconv.Quote(ipath),
+		},
+	}
+	if name != "" {
+		newImport.Name = &ast.Ident{Name: name}
+	}
+
+	// Find an import decl to add to.
+	var (
+		bestMatch  = -1
+		lastImport = -1
+		impDecl    *ast.GenDecl
+		impIndex   = -1
+		hasImports = false
+	)
+	for i, decl := range f.Decls {
+		gen, ok := decl.(*ast.GenDecl)
+		if ok && gen.Tok == token.IMPORT {
+			hasImports = true
+			lastImport = i
+			// Do not add to import "C", to avoid disrupting the
+			// association with its doc comment, breaking cgo.
+			if declImports(gen, "C") {
+				continue
+			}
+
+			// Compute longest shared prefix with imports in this block.
+			for j, spec := range gen.Specs {
+				impspec := spec.(*ast.ImportSpec)
+				n := matchLen(importPath(impspec), ipath)
+				if n > bestMatch {
+					bestMatch = n
+					impDecl = gen
+					impIndex = j
+				}
+			}
+		}
+	}
+
+	// If no import decl found, add one after the last import.
+	if impDecl == nil {
+		// TODO(bradfitz): remove this hack. See comment below on
+		// addImportViaSourceModification.
+		if !hasImports {
+			f2, err := addImportViaSourceModification(fset, f, name, ipath)
+			if err == nil {
+				*f = *f2
+				return true
+			}
+			log.Printf("addImportViaSourceModification error: %v", err)
+		}
+
+		// TODO(bradfitz): fix above and resume using this old code:
+		impDecl = &ast.GenDecl{
+			Tok: token.IMPORT,
+		}
+		f.Decls = append(f.Decls, nil)
+		copy(f.Decls[lastImport+2:], f.Decls[lastImport+1:])
+		f.Decls[lastImport+1] = impDecl
+	}
+
+	// Ensure the import decl has parentheses, if needed.
+	if len(impDecl.Specs) > 0 && !impDecl.Lparen.IsValid() {
+		impDecl.Lparen = impDecl.Pos()
+	}
+
+	insertAt := impIndex + 1
+	if insertAt == 0 {
+		insertAt = len(impDecl.Specs)
+	}
+	impDecl.Specs = append(impDecl.Specs, nil)
+	copy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:])
+	impDecl.Specs[insertAt] = newImport
+	if insertAt > 0 {
+		// Assign same position as the previous import,
+		// so that the sorter sees it as being in the same block.
+		prev := impDecl.Specs[insertAt-1]
+		newImport.Path.ValuePos = prev.Pos()
+		newImport.EndPos = prev.Pos()
+	}
+	if len(impDecl.Specs) > 1 && impDecl.Lparen == 0 {
+		// set Lparen to something not zero, so the printer prints
+		// the full block rather just the first ImportSpec.
+		impDecl.Lparen = 1
+	}
+
+	f.Imports = append(f.Imports, newImport)
+	return true
+}
+
+// DeleteImport deletes the import path from the file f, if present.
+func DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool) {
+	var delspecs []*ast.ImportSpec
+
+	// Find the import nodes that import path, if any.
+	for i := 0; i < len(f.Decls); i++ {
+		decl := f.Decls[i]
+		gen, ok := decl.(*ast.GenDecl)
+		if !ok || gen.Tok != token.IMPORT {
+			continue
+		}
+		for j := 0; j < len(gen.Specs); j++ {
+			spec := gen.Specs[j]
+			impspec := spec.(*ast.ImportSpec)
+			if importPath(impspec) != path {
+				continue
+			}
+
+			// We found an import spec that imports path.
+			// Delete it.
+			delspecs = append(delspecs, impspec)
+			deleted = true
+			copy(gen.Specs[j:], gen.Specs[j+1:])
+			gen.Specs = gen.Specs[:len(gen.Specs)-1]
+
+			// If this was the last import spec in this decl,
+			// delete the decl, too.
+			if len(gen.Specs) == 0 {
+				copy(f.Decls[i:], f.Decls[i+1:])
+				f.Decls = f.Decls[:len(f.Decls)-1]
+				i--
+				break
+			} else if len(gen.Specs) == 1 {
+				gen.Lparen = token.NoPos // drop parens
+			}
+			if j > 0 {
+				lastImpspec := gen.Specs[j-1].(*ast.ImportSpec)
+				lastLine := fset.Position(lastImpspec.Path.ValuePos).Line
+				line := fset.Position(impspec.Path.ValuePos).Line
+
+				// We deleted an entry but now there may be
+				// a blank line-sized hole where the import was.
+				if line-lastLine > 1 {
+					// There was a blank line immediately preceding the deleted import,
+					// so there's no need to close the hole.
+					// Do nothing.
+				} else {
+					// There was no blank line. Close the hole.
+					fset.File(gen.Rparen).MergeLine(line)
+				}
+			}
+			j--
+		}
+	}
+
+	// Delete them from f.Imports.
+	for i := 0; i < len(f.Imports); i++ {
+		imp := f.Imports[i]
+		for j, del := range delspecs {
+			if imp == del {
+				copy(f.Imports[i:], f.Imports[i+1:])
+				f.Imports = f.Imports[:len(f.Imports)-1]
+				copy(delspecs[j:], delspecs[j+1:])
+				delspecs = delspecs[:len(delspecs)-1]
+				i--
+				break
+			}
+		}
+	}
+
+	if len(delspecs) > 0 {
+		panic(fmt.Sprintf("deleted specs from Decls but not Imports: %v", delspecs))
+	}
+
+	return
+}
+
+// RewriteImport rewrites any import of path oldPath to path newPath.
+func RewriteImport(fset *token.FileSet, f *ast.File, oldPath, newPath string) (rewrote bool) {
+	for _, imp := range f.Imports {
+		if importPath(imp) == oldPath {
+			rewrote = true
+			// record old End, because the default is to compute
+			// it using the length of imp.Path.Value.
+			imp.EndPos = imp.End()
+			imp.Path.Value = strconv.Quote(newPath)
+		}
+	}
+	return
+}
+
+// UsesImport reports whether a given import is used.
+func UsesImport(f *ast.File, path string) (used bool) {
+	spec := importSpec(f, path)
+	if spec == nil {
+		return
+	}
+
+	name := spec.Name.String()
+	switch name {
+	case "<nil>":
+		// If the package name is not explicitly specified,
+		// make an educated guess. This is not guaranteed to be correct.
+		lastSlash := strings.LastIndex(path, "/")
+		if lastSlash == -1 {
+			name = path
+		} else {
+			name = path[lastSlash+1:]
+		}
+	case "_", ".":
+		// Not sure if this import is used - err on the side of caution.
+		return true
+	}
+
+	ast.Walk(visitFn(func(n ast.Node) {
+		sel, ok := n.(*ast.SelectorExpr)
+		if ok && isTopName(sel.X, name) {
+			used = true
+		}
+	}), f)
+
+	return
+}
+
+type visitFn func(node ast.Node)
+
+func (fn visitFn) Visit(node ast.Node) ast.Visitor {
+	fn(node)
+	return fn
+}
+
+// imports returns true if f imports path.
+func imports(f *ast.File, path string) bool {
+	return importSpec(f, path) != nil
+}
+
+// importSpec returns the import spec if f imports path,
+// or nil otherwise.
+func importSpec(f *ast.File, path string) *ast.ImportSpec {
+	for _, s := range f.Imports {
+		if importPath(s) == path {
+			return s
+		}
+	}
+	return nil
+}
+
+// importPath returns the unquoted import path of s,
+// or "" if the path is not properly quoted.
+func importPath(s *ast.ImportSpec) string {
+	t, err := strconv.Unquote(s.Path.Value)
+	if err == nil {
+		return t
+	}
+	return ""
+}
+
+// declImports reports whether gen contains an import of path.
+func declImports(gen *ast.GenDecl, path string) bool {
+	if gen.Tok != token.IMPORT {
+		return false
+	}
+	for _, spec := range gen.Specs {
+		impspec := spec.(*ast.ImportSpec)
+		if importPath(impspec) == path {
+			return true
+		}
+	}
+	return false
+}
+
+// matchLen returns the length of the longest prefix shared by x and y.
+func matchLen(x, y string) int {
+	i := 0
+	for i < len(x) && i < len(y) && x[i] == y[i] {
+		i++
+	}
+	return i
+}
+
+// isTopName returns true if n is a top-level unresolved identifier with the given name.
+func isTopName(n ast.Expr, name string) bool {
+	id, ok := n.(*ast.Ident)
+	return ok && id.Name == name && id.Obj == nil
+}
+
+// Imports returns the file imports grouped by paragraph.
+func Imports(fset *token.FileSet, f *ast.File) [][]*ast.ImportSpec {
+	var groups [][]*ast.ImportSpec
+
+	for _, decl := range f.Decls {
+		genDecl, ok := decl.(*ast.GenDecl)
+		if !ok || genDecl.Tok != token.IMPORT {
+			break
+		}
+
+		group := []*ast.ImportSpec{}
+
+		var lastLine int
+		for _, spec := range genDecl.Specs {
+			importSpec := spec.(*ast.ImportSpec)
+			pos := importSpec.Path.ValuePos
+			line := fset.Position(pos).Line
+			if lastLine > 0 && pos > 0 && line-lastLine > 1 {
+				groups = append(groups, group)
+				group = []*ast.ImportSpec{}
+			}
+			group = append(group, importSpec)
+			lastLine = line
+		}
+		groups = append(groups, group)
+	}
+
+	return groups
+}
+
+// NOTE(bradfitz): this is a bit of a hack for golang.org/issue/6884
+// because we can't get the comment positions correct. Instead of modifying
+// the AST, we print it, modify the text, and re-parse it. Gross.
+func addImportViaSourceModification(fset *token.FileSet, f *ast.File, name, ipath string) (*ast.File, error) {
+	var buf bytes.Buffer
+	if err := format.Node(&buf, fset, f); err != nil {
+		return nil, fmt.Errorf("Error formatting ast.File node: %v", err)
+	}
+	var out bytes.Buffer
+	sc := bufio.NewScanner(bytes.NewReader(buf.Bytes()))
+	didAdd := false
+	for sc.Scan() {
+		ln := sc.Text()
+		out.WriteString(ln)
+		out.WriteByte('\n')
+		if !didAdd && strings.HasPrefix(ln, "package ") {
+			fmt.Fprintf(&out, "\nimport %s %q\n\n", name, ipath)
+			didAdd = true
+		}
+	}
+	if err := sc.Err(); err != nil {
+		return nil, err
+	}
+	return parser.ParseFile(fset, "", out.Bytes(), parser.ParseComments)
+}
diff --git a/third_party/go.tools/astutil/imports_test.go b/third_party/go.tools/astutil/imports_test.go
new file mode 100644
index 0000000..3621972
--- /dev/null
+++ b/third_party/go.tools/astutil/imports_test.go
@@ -0,0 +1,757 @@
+// Copyright 2013 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 astutil
+
+import (
+	"bytes"
+	"go/ast"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"reflect"
+	"strconv"
+	"testing"
+)
+
+var fset = token.NewFileSet()
+
+func parse(t *testing.T, name, in string) *ast.File {
+	file, err := parser.ParseFile(fset, name, in, parser.ParseComments)
+	if err != nil {
+		t.Fatalf("%s parse: %v", name, err)
+	}
+	return file
+}
+
+func print(t *testing.T, name string, f *ast.File) string {
+	var buf bytes.Buffer
+	if err := format.Node(&buf, fset, f); err != nil {
+		t.Fatalf("%s gofmt: %v", name, err)
+	}
+	return string(buf.Bytes())
+}
+
+type test struct {
+	name       string
+	renamedPkg string
+	pkg        string
+	in         string
+	out        string
+	broken     bool // known broken
+}
+
+var addTests = []test{
+	{
+		name: "leave os alone",
+		pkg:  "os",
+		in: `package main
+
+import (
+	"os"
+)
+`,
+		out: `package main
+
+import (
+	"os"
+)
+`,
+	},
+	{
+		name: "import.1",
+		pkg:  "os",
+		in: `package main
+`,
+		out: `package main
+
+import "os"
+`,
+	},
+	{
+		name: "import.2",
+		pkg:  "os",
+		in: `package main
+
+// Comment
+import "C"
+`,
+		out: `package main
+
+// Comment
+import "C"
+import "os"
+`,
+	},
+	{
+		name: "import.3",
+		pkg:  "os",
+		in: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"utf8"
+)
+`,
+		out: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+	},
+	{
+		name: "import.17",
+		pkg:  "x/y/z",
+		in: `package main
+
+// Comment
+import "C"
+
+import (
+	"a"
+	"b"
+
+	"x/w"
+
+	"d/f"
+)
+`,
+		out: `package main
+
+// Comment
+import "C"
+
+import (
+	"a"
+	"b"
+
+	"x/w"
+	"x/y/z"
+
+	"d/f"
+)
+`,
+	},
+	{
+		name: "import into singular block",
+		pkg:  "bytes",
+		in: `package main
+
+import "os"
+
+`,
+		out: `package main
+
+import (
+	"bytes"
+	"os"
+)
+`,
+	},
+	{
+		name:       "",
+		renamedPkg: "fmtpkg",
+		pkg:        "fmt",
+		in: `package main
+
+import "os"
+
+`,
+		out: `package main
+
+import (
+	fmtpkg "fmt"
+	"os"
+)
+`,
+	},
+	{
+		name: "struct comment",
+		pkg:  "time",
+		in: `package main
+
+// This is a comment before a struct.
+type T struct {
+	t  time.Time
+}
+`,
+		out: `package main
+
+import "time"
+
+// This is a comment before a struct.
+type T struct {
+	t time.Time
+}
+`,
+	},
+}
+
+func TestAddImport(t *testing.T) {
+	for _, test := range addTests {
+		file := parse(t, test.name, test.in)
+		var before bytes.Buffer
+		ast.Fprint(&before, fset, file, nil)
+		AddNamedImport(fset, file, test.renamedPkg, test.pkg)
+		if got := print(t, test.name, file); got != test.out {
+			if test.broken {
+				t.Logf("%s is known broken:\ngot: %s\nwant: %s", test.name, got, test.out)
+			} else {
+				t.Errorf("%s:\ngot: %s\nwant: %s", test.name, got, test.out)
+			}
+			var after bytes.Buffer
+			ast.Fprint(&after, fset, file, nil)
+
+			t.Logf("AST before:\n%s\nAST after:\n%s\n", before.String(), after.String())
+		}
+	}
+}
+
+func TestDoubleAddImport(t *testing.T) {
+	file := parse(t, "doubleimport", "package main\n")
+	AddImport(fset, file, "os")
+	AddImport(fset, file, "bytes")
+	want := `package main
+
+import (
+	"bytes"
+	"os"
+)
+`
+	if got := print(t, "doubleimport", file); got != want {
+		t.Errorf("got: %s\nwant: %s", got, want)
+	}
+}
+
+var deleteTests = []test{
+	{
+		name: "import.4",
+		pkg:  "os",
+		in: `package main
+
+import (
+	"os"
+)
+`,
+		out: `package main
+`,
+	},
+	{
+		name: "import.5",
+		pkg:  "os",
+		in: `package main
+
+// Comment
+import "C"
+import "os"
+`,
+		out: `package main
+
+// Comment
+import "C"
+`,
+	},
+	{
+		name: "import.6",
+		pkg:  "os",
+		in: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		out: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"utf8"
+)
+`,
+	},
+	{
+		name: "import.7",
+		pkg:  "io",
+		in: `package main
+
+import (
+	"io"   // a
+	"os"   // b
+	"utf8" // c
+)
+`,
+		out: `package main
+
+import (
+	// a
+	"os"   // b
+	"utf8" // c
+)
+`,
+	},
+	{
+		name: "import.8",
+		pkg:  "os",
+		in: `package main
+
+import (
+	"io"   // a
+	"os"   // b
+	"utf8" // c
+)
+`,
+		out: `package main
+
+import (
+	"io" // a
+	// b
+	"utf8" // c
+)
+`,
+	},
+	{
+		name: "import.9",
+		pkg:  "utf8",
+		in: `package main
+
+import (
+	"io"   // a
+	"os"   // b
+	"utf8" // c
+)
+`,
+		out: `package main
+
+import (
+	"io" // a
+	"os" // b
+	// c
+)
+`,
+	},
+	{
+		name: "import.10",
+		pkg:  "io",
+		in: `package main
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		out: `package main
+
+import (
+	"os"
+	"utf8"
+)
+`,
+	},
+	{
+		name: "import.11",
+		pkg:  "os",
+		in: `package main
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		out: `package main
+
+import (
+	"io"
+	"utf8"
+)
+`,
+	},
+	{
+		name: "import.12",
+		pkg:  "utf8",
+		in: `package main
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		out: `package main
+
+import (
+	"io"
+	"os"
+)
+`,
+	},
+	{
+		name: "handle.raw.quote.imports",
+		pkg:  "os",
+		in:   "package main\n\nimport `os`",
+		out: `package main
+`,
+	},
+	{
+		name: "import.13",
+		pkg:  "io",
+		in: `package main
+
+import (
+	"fmt"
+
+	"io"
+	"os"
+	"utf8"
+
+	"go/format"
+)
+`,
+		out: `package main
+
+import (
+	"fmt"
+
+	"os"
+	"utf8"
+
+	"go/format"
+)
+`,
+	},
+	{
+		name: "import.14",
+		pkg:  "io",
+		in: `package main
+
+import (
+	"fmt" // a
+
+	"io"   // b
+	"os"   // c
+	"utf8" // d
+
+	"go/format" // e
+)
+`,
+		out: `package main
+
+import (
+	"fmt" // a
+
+	// b
+	"os"   // c
+	"utf8" // d
+
+	"go/format" // e
+)
+`,
+	},
+	{
+		name: "import.15",
+		pkg:  "double",
+		in: `package main
+
+import (
+	"double"
+	"double"
+)
+`,
+		out: `package main
+`,
+	},
+	{
+		name: "import.16",
+		pkg:  "bubble",
+		in: `package main
+
+import (
+	"toil"
+	"bubble"
+	"bubble"
+	"trouble"
+)
+`,
+		out: `package main
+
+import (
+	"toil"
+	"trouble"
+)
+`,
+	},
+	{
+		name: "import.17",
+		pkg:  "quad",
+		in: `package main
+
+import (
+	"quad"
+	"quad"
+)
+
+import (
+	"quad"
+	"quad"
+)
+`,
+		out: `package main
+`,
+	},
+}
+
+func TestDeleteImport(t *testing.T) {
+	for _, test := range deleteTests {
+		file := parse(t, test.name, test.in)
+		DeleteImport(fset, file, test.pkg)
+		if got := print(t, test.name, file); got != test.out {
+			t.Errorf("%s:\ngot: %s\nwant: %s", test.name, got, test.out)
+		}
+	}
+}
+
+type rewriteTest struct {
+	name   string
+	srcPkg string
+	dstPkg string
+	in     string
+	out    string
+}
+
+var rewriteTests = []rewriteTest{
+	{
+		name:   "import.13",
+		srcPkg: "utf8",
+		dstPkg: "encoding/utf8",
+		in: `package main
+
+import (
+	"io"
+	"os"
+	"utf8" // thanks ken
+)
+`,
+		out: `package main
+
+import (
+	"encoding/utf8" // thanks ken
+	"io"
+	"os"
+)
+`,
+	},
+	{
+		name:   "import.14",
+		srcPkg: "asn1",
+		dstPkg: "encoding/asn1",
+		in: `package main
+
+import (
+	"asn1"
+	"crypto"
+	"crypto/rsa"
+	_ "crypto/sha1"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"time"
+)
+
+var x = 1
+`,
+		out: `package main
+
+import (
+	"crypto"
+	"crypto/rsa"
+	_ "crypto/sha1"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"time"
+)
+
+var x = 1
+`,
+	},
+	{
+		name:   "import.15",
+		srcPkg: "url",
+		dstPkg: "net/url",
+		in: `package main
+
+import (
+	"bufio"
+	"net"
+	"path"
+	"url"
+)
+
+var x = 1 // comment on x, not on url
+`,
+		out: `package main
+
+import (
+	"bufio"
+	"net"
+	"net/url"
+	"path"
+)
+
+var x = 1 // comment on x, not on url
+`,
+	},
+	{
+		name:   "import.16",
+		srcPkg: "http",
+		dstPkg: "net/http",
+		in: `package main
+
+import (
+	"flag"
+	"http"
+	"log"
+	"text/template"
+)
+
+var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
+`,
+		out: `package main
+
+import (
+	"flag"
+	"log"
+	"net/http"
+	"text/template"
+)
+
+var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
+`,
+	},
+}
+
+func TestRewriteImport(t *testing.T) {
+	for _, test := range rewriteTests {
+		file := parse(t, test.name, test.in)
+		RewriteImport(fset, file, test.srcPkg, test.dstPkg)
+		if got := print(t, test.name, file); got != test.out {
+			t.Errorf("%s:\ngot: %s\nwant: %s", test.name, got, test.out)
+		}
+	}
+}
+
+var importsTests = []struct {
+	name string
+	in   string
+	want [][]string
+}{
+	{
+		name: "no packages",
+		in: `package foo
+`,
+		want: nil,
+	},
+	{
+		name: "one group",
+		in: `package foo
+
+import (
+	"fmt"
+	"testing"
+)
+`,
+		want: [][]string{{"fmt", "testing"}},
+	},
+	{
+		name: "four groups",
+		in: `package foo
+
+import "C"
+import (
+	"fmt"
+	"testing"
+
+	"appengine"
+
+	"myproject/mylib1"
+	"myproject/mylib2"
+)
+`,
+		want: [][]string{
+			{"C"},
+			{"fmt", "testing"},
+			{"appengine"},
+			{"myproject/mylib1", "myproject/mylib2"},
+		},
+	},
+	{
+		name: "multiple factored groups",
+		in: `package foo
+
+import (
+	"fmt"
+	"testing"
+
+	"appengine"
+)
+import (
+	"reflect"
+
+	"bytes"
+)
+`,
+		want: [][]string{
+			{"fmt", "testing"},
+			{"appengine"},
+			{"reflect"},
+			{"bytes"},
+		},
+	},
+}
+
+func unquote(s string) string {
+	res, err := strconv.Unquote(s)
+	if err != nil {
+		return "could_not_unquote"
+	}
+	return res
+}
+
+func TestImports(t *testing.T) {
+	fset := token.NewFileSet()
+	for _, test := range importsTests {
+		f, err := parser.ParseFile(fset, "test.go", test.in, 0)
+		if err != nil {
+			t.Errorf("%s: %v", test.name, err)
+			continue
+		}
+		var got [][]string
+		for _, block := range Imports(fset, f) {
+			var b []string
+			for _, spec := range block {
+				b = append(b, unquote(spec.Path.Value))
+			}
+			got = append(got, b)
+		}
+		if !reflect.DeepEqual(got, test.want) {
+			t.Errorf("Imports(%s)=%v, want %v", test.name, got, test.want)
+		}
+	}
+}
diff --git a/third_party/go.tools/blog/atom/atom.go b/third_party/go.tools/blog/atom/atom.go
new file mode 100644
index 0000000..bc114dd
--- /dev/null
+++ b/third_party/go.tools/blog/atom/atom.go
@@ -0,0 +1,57 @@
+// 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.
+
+// Adapted from encoding/xml/read_test.go.
+
+// Package atom defines XML data structures for an Atom feed.
+package atom
+
+import (
+	"encoding/xml"
+	"time"
+)
+
+type Feed struct {
+	XMLName xml.Name `xml:"http://www.w3.org/2005/Atom feed"`
+	Title   string   `xml:"title"`
+	ID      string   `xml:"id"`
+	Link    []Link   `xml:"link"`
+	Updated TimeStr  `xml:"updated"`
+	Author  *Person  `xml:"author"`
+	Entry   []*Entry `xml:"entry"`
+}
+
+type Entry struct {
+	Title     string  `xml:"title"`
+	ID        string  `xml:"id"`
+	Link      []Link  `xml:"link"`
+	Published TimeStr `xml:"published"`
+	Updated   TimeStr `xml:"updated"`
+	Author    *Person `xml:"author"`
+	Summary   *Text   `xml:"summary"`
+	Content   *Text   `xml:"content"`
+}
+
+type Link struct {
+	Rel  string `xml:"rel,attr"`
+	Href string `xml:"href,attr"`
+}
+
+type Person struct {
+	Name     string `xml:"name"`
+	URI      string `xml:"uri,omitempty"`
+	Email    string `xml:"email,omitempty"`
+	InnerXML string `xml:",innerxml"`
+}
+
+type Text struct {
+	Type string `xml:"type,attr"`
+	Body string `xml:",chardata"`
+}
+
+type TimeStr string
+
+func Time(t time.Time) TimeStr {
+	return TimeStr(t.Format("2006-01-02T15:04:05-07:00"))
+}
diff --git a/third_party/go.tools/blog/blog.go b/third_party/go.tools/blog/blog.go
new file mode 100644
index 0000000..54d3a42
--- /dev/null
+++ b/third_party/go.tools/blog/blog.go
@@ -0,0 +1,424 @@
+// Copyright 2013 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 blog implements a web server for articles written in present format.
+package blog
+
+import (
+	"bytes"
+	"encoding/json"
+	"encoding/xml"
+	"fmt"
+	"html/template"
+	"log"
+	"net/http"
+	"os"
+	"path/filepath"
+	"regexp"
+	"sort"
+	"strings"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/blog/atom"
+	"llvm.org/llgo/third_party/go.tools/present"
+)
+
+var validJSONPFunc = regexp.MustCompile(`(?i)^[a-z_][a-z0-9_.]*$`)
+
+// Config specifies Server configuration values.
+type Config struct {
+	ContentPath  string // Relative or absolute location of article files and related content.
+	TemplatePath string // Relative or absolute location of template files.
+
+	BaseURL  string // Absolute base URL (for permalinks; no trailing slash).
+	BasePath string // Base URL path relative to server root (no trailing slash).
+	GodocURL string // The base URL of godoc (for menu bar; no trailing slash).
+	Hostname string // Server host name, used for rendering ATOM feeds.
+
+	HomeArticles int    // Articles to display on the home page.
+	FeedArticles int    // Articles to include in Atom and JSON feeds.
+	FeedTitle    string // The title of the Atom XML feed
+
+	PlayEnabled bool
+}
+
+// Doc represents an article adorned with presentation data.
+type Doc struct {
+	*present.Doc
+	Permalink string        // Canonical URL for this document.
+	Path      string        // Path relative to server root (including base).
+	HTML      template.HTML // rendered article
+
+	Related      []*Doc
+	Newer, Older *Doc
+}
+
+// Server implements an http.Handler that serves blog articles.
+type Server struct {
+	cfg      Config
+	docs     []*Doc
+	tags     []string
+	docPaths map[string]*Doc // key is path without BasePath.
+	docTags  map[string][]*Doc
+	template struct {
+		home, index, article, doc *template.Template
+	}
+	atomFeed []byte // pre-rendered Atom feed
+	jsonFeed []byte // pre-rendered JSON feed
+	content  http.Handler
+}
+
+// NewServer constructs a new Server using the specified config.
+func NewServer(cfg Config) (*Server, error) {
+	present.PlayEnabled = cfg.PlayEnabled
+
+	root := filepath.Join(cfg.TemplatePath, "root.tmpl")
+	parse := func(name string) (*template.Template, error) {
+		t := template.New("").Funcs(funcMap)
+		return t.ParseFiles(root, filepath.Join(cfg.TemplatePath, name))
+	}
+
+	s := &Server{cfg: cfg}
+
+	// Parse templates.
+	var err error
+	s.template.home, err = parse("home.tmpl")
+	if err != nil {
+		return nil, err
+	}
+	s.template.index, err = parse("index.tmpl")
+	if err != nil {
+		return nil, err
+	}
+	s.template.article, err = parse("article.tmpl")
+	if err != nil {
+		return nil, err
+	}
+	p := present.Template().Funcs(funcMap)
+	s.template.doc, err = p.ParseFiles(filepath.Join(cfg.TemplatePath, "doc.tmpl"))
+	if err != nil {
+		return nil, err
+	}
+
+	// Load content.
+	err = s.loadDocs(filepath.Clean(cfg.ContentPath))
+	if err != nil {
+		return nil, err
+	}
+
+	err = s.renderAtomFeed()
+	if err != nil {
+		return nil, err
+	}
+
+	err = s.renderJSONFeed()
+	if err != nil {
+		return nil, err
+	}
+
+	// Set up content file server.
+	s.content = http.StripPrefix(s.cfg.BasePath, http.FileServer(http.Dir(cfg.ContentPath)))
+
+	return s, nil
+}
+
+var funcMap = template.FuncMap{
+	"sectioned": sectioned,
+	"authors":   authors,
+}
+
+// sectioned returns true if the provided Doc contains more than one section.
+// This is used to control whether to display the table of contents and headings.
+func sectioned(d *present.Doc) bool {
+	return len(d.Sections) > 1
+}
+
+// authors returns a comma-separated list of author names.
+func authors(authors []present.Author) string {
+	var b bytes.Buffer
+	last := len(authors) - 1
+	for i, a := range authors {
+		if i > 0 {
+			if i == last {
+				b.WriteString(" and ")
+			} else {
+				b.WriteString(", ")
+			}
+		}
+		b.WriteString(authorName(a))
+	}
+	return b.String()
+}
+
+// authorName returns the first line of the Author text: the author's name.
+func authorName(a present.Author) string {
+	el := a.TextElem()
+	if len(el) == 0 {
+		return ""
+	}
+	text, ok := el[0].(present.Text)
+	if !ok || len(text.Lines) == 0 {
+		return ""
+	}
+	return text.Lines[0]
+}
+
+// loadDocs reads all content from the provided file system root, renders all
+// the articles it finds, adds them to the Server's docs field, computes the
+// denormalized docPaths, docTags, and tags fields, and populates the various
+// helper fields (Next, Previous, Related) for each Doc.
+func (s *Server) loadDocs(root string) error {
+	// Read content into docs field.
+	const ext = ".article"
+	fn := func(p string, info os.FileInfo, err error) error {
+		if filepath.Ext(p) != ext {
+			return nil
+		}
+		f, err := os.Open(p)
+		if err != nil {
+			return err
+		}
+		defer f.Close()
+		d, err := present.Parse(f, p, 0)
+		if err != nil {
+			return err
+		}
+		html := new(bytes.Buffer)
+		err = d.Render(html, s.template.doc)
+		if err != nil {
+			return err
+		}
+		p = p[len(root) : len(p)-len(ext)] // trim root and extension
+		p = filepath.ToSlash(p)
+		s.docs = append(s.docs, &Doc{
+			Doc:       d,
+			Path:      s.cfg.BasePath + p,
+			Permalink: s.cfg.BaseURL + p,
+			HTML:      template.HTML(html.String()),
+		})
+		return nil
+	}
+	err := filepath.Walk(root, fn)
+	if err != nil {
+		return err
+	}
+	sort.Sort(docsByTime(s.docs))
+
+	// Pull out doc paths and tags and put in reverse-associating maps.
+	s.docPaths = make(map[string]*Doc)
+	s.docTags = make(map[string][]*Doc)
+	for _, d := range s.docs {
+		s.docPaths[strings.TrimPrefix(d.Path, s.cfg.BasePath)] = d
+		for _, t := range d.Tags {
+			s.docTags[t] = append(s.docTags[t], d)
+		}
+	}
+
+	// Pull out unique sorted list of tags.
+	for t := range s.docTags {
+		s.tags = append(s.tags, t)
+	}
+	sort.Strings(s.tags)
+
+	// Set up presentation-related fields, Newer, Older, and Related.
+	for _, doc := range s.docs {
+		// Newer, Older: docs adjacent to doc
+		for i := range s.docs {
+			if s.docs[i] != doc {
+				continue
+			}
+			if i > 0 {
+				doc.Newer = s.docs[i-1]
+			}
+			if i+1 < len(s.docs) {
+				doc.Older = s.docs[i+1]
+			}
+			break
+		}
+
+		// Related: all docs that share tags with doc.
+		related := make(map[*Doc]bool)
+		for _, t := range doc.Tags {
+			for _, d := range s.docTags[t] {
+				if d != doc {
+					related[d] = true
+				}
+			}
+		}
+		for d := range related {
+			doc.Related = append(doc.Related, d)
+		}
+		sort.Sort(docsByTime(doc.Related))
+	}
+
+	return nil
+}
+
+// renderAtomFeed generates an XML Atom feed and stores it in the Server's
+// atomFeed field.
+func (s *Server) renderAtomFeed() error {
+	var updated time.Time
+	if len(s.docs) > 0 {
+		updated = s.docs[0].Time
+	}
+	feed := atom.Feed{
+		Title:   s.cfg.FeedTitle,
+		ID:      "tag:" + s.cfg.Hostname + ",2013:" + s.cfg.Hostname,
+		Updated: atom.Time(updated),
+		Link: []atom.Link{{
+			Rel:  "self",
+			Href: s.cfg.BaseURL + "/feed.atom",
+		}},
+	}
+	for i, doc := range s.docs {
+		if i >= s.cfg.FeedArticles {
+			break
+		}
+		e := &atom.Entry{
+			Title: doc.Title,
+			ID:    feed.ID + doc.Path,
+			Link: []atom.Link{{
+				Rel:  "alternate",
+				Href: doc.Permalink,
+			}},
+			Published: atom.Time(doc.Time),
+			Updated:   atom.Time(doc.Time),
+			Summary: &atom.Text{
+				Type: "html",
+				Body: summary(doc),
+			},
+			Content: &atom.Text{
+				Type: "html",
+				Body: string(doc.HTML),
+			},
+			Author: &atom.Person{
+				Name: authors(doc.Authors),
+			},
+		}
+		feed.Entry = append(feed.Entry, e)
+	}
+	data, err := xml.Marshal(&feed)
+	if err != nil {
+		return err
+	}
+	s.atomFeed = data
+	return nil
+}
+
+type jsonItem struct {
+	Title   string
+	Link    string
+	Time    time.Time
+	Summary string
+	Content string
+	Author  string
+}
+
+// renderJSONFeed generates a JSON feed and stores it in the Server's jsonFeed
+// field.
+func (s *Server) renderJSONFeed() error {
+	var feed []jsonItem
+	for i, doc := range s.docs {
+		if i >= s.cfg.FeedArticles {
+			break
+		}
+		item := jsonItem{
+			Title:   doc.Title,
+			Link:    doc.Permalink,
+			Time:    doc.Time,
+			Summary: summary(doc),
+			Content: string(doc.HTML),
+			Author:  authors(doc.Authors),
+		}
+		feed = append(feed, item)
+	}
+	data, err := json.Marshal(feed)
+	if err != nil {
+		return err
+	}
+	s.jsonFeed = data
+	return nil
+}
+
+// summary returns the first paragraph of text from the provided Doc.
+func summary(d *Doc) string {
+	if len(d.Sections) == 0 {
+		return ""
+	}
+	for _, elem := range d.Sections[0].Elem {
+		text, ok := elem.(present.Text)
+		if !ok || text.Pre {
+			// skip everything but non-text elements
+			continue
+		}
+		var buf bytes.Buffer
+		for _, s := range text.Lines {
+			buf.WriteString(string(present.Style(s)))
+			buf.WriteByte('\n')
+		}
+		return buf.String()
+	}
+	return ""
+}
+
+// rootData encapsulates data destined for the root template.
+type rootData struct {
+	Doc      *Doc
+	BasePath string
+	GodocURL string
+	Data     interface{}
+}
+
+// ServeHTTP serves the front, index, and article pages
+// as well as the ATOM and JSON feeds.
+func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	var (
+		d = rootData{BasePath: s.cfg.BasePath, GodocURL: s.cfg.GodocURL}
+		t *template.Template
+	)
+	switch p := strings.TrimPrefix(r.URL.Path, s.cfg.BasePath); p {
+	case "/":
+		d.Data = s.docs
+		if len(s.docs) > s.cfg.HomeArticles {
+			d.Data = s.docs[:s.cfg.HomeArticles]
+		}
+		t = s.template.home
+	case "/index":
+		d.Data = s.docs
+		t = s.template.index
+	case "/feed.atom", "/feeds/posts/default":
+		w.Header().Set("Content-type", "application/atom+xml; charset=utf-8")
+		w.Write(s.atomFeed)
+		return
+	case "/.json":
+		if p := r.FormValue("jsonp"); validJSONPFunc.MatchString(p) {
+			w.Header().Set("Content-type", "application/javascript; charset=utf-8")
+			fmt.Fprintf(w, "%v(%s)", p, s.jsonFeed)
+			return
+		}
+		w.Header().Set("Content-type", "application/json; charset=utf-8")
+		w.Write(s.jsonFeed)
+		return
+	default:
+		doc, ok := s.docPaths[p]
+		if !ok {
+			// Not a doc; try to just serve static content.
+			s.content.ServeHTTP(w, r)
+			return
+		}
+		d.Doc = doc
+		t = s.template.article
+	}
+	err := t.ExecuteTemplate(w, "root", d)
+	if err != nil {
+		log.Println(err)
+	}
+}
+
+// docsByTime implements sort.Interface, sorting Docs by their Time field.
+type docsByTime []*Doc
+
+func (s docsByTime) Len() int           { return len(s) }
+func (s docsByTime) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s docsByTime) Less(i, j int) bool { return s[i].Time.After(s[j].Time) }
diff --git a/third_party/go.tools/cmd/benchcmp/benchcmp.go b/third_party/go.tools/cmd/benchcmp/benchcmp.go
new file mode 100644
index 0000000..9bfe2e3
--- /dev/null
+++ b/third_party/go.tools/cmd/benchcmp/benchcmp.go
@@ -0,0 +1,161 @@
+// Copyright 2014 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 (
+	"flag"
+	"fmt"
+	"os"
+	"sort"
+	"strconv"
+	"text/tabwriter"
+)
+
+var (
+	changedOnly = flag.Bool("changed", false, "show only benchmarks that have changed")
+	magSort     = flag.Bool("mag", false, "sort benchmarks by magnitude of change")
+	best        = flag.Bool("best", false, "compare best times from old and new")
+)
+
+const usageFooter = `
+Each input file should be from:
+	go test -run=NONE -bench=. > [old,new].txt
+
+Benchcmp compares old and new for each benchmark.
+
+If -test.benchmem=true is added to the "go test" command
+benchcmp will also compare memory allocations.
+`
+
+func main() {
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, "usage: %s old.txt new.txt\n\n", os.Args[0])
+		flag.PrintDefaults()
+		fmt.Fprint(os.Stderr, usageFooter)
+		os.Exit(2)
+	}
+	flag.Parse()
+	if flag.NArg() != 2 {
+		flag.Usage()
+	}
+
+	before := parseFile(flag.Arg(0))
+	after := parseFile(flag.Arg(1))
+
+	cmps, warnings := Correlate(before, after)
+
+	for _, warn := range warnings {
+		fmt.Fprintln(os.Stderr, warn)
+	}
+
+	if len(cmps) == 0 {
+		fatal("benchcmp: no repeated benchmarks")
+	}
+
+	w := new(tabwriter.Writer)
+	w.Init(os.Stdout, 0, 0, 5, ' ', 0)
+	defer w.Flush()
+
+	var header bool // Has the header has been displayed yet for a given block?
+
+	if *magSort {
+		sort.Sort(ByDeltaNsOp(cmps))
+	} else {
+		sort.Sort(ByParseOrder(cmps))
+	}
+	for _, cmp := range cmps {
+		if !cmp.Measured(NsOp) {
+			continue
+		}
+		if delta := cmp.DeltaNsOp(); !*changedOnly || delta.Changed() {
+			if !header {
+				fmt.Fprint(w, "benchmark\told ns/op\tnew ns/op\tdelta\n")
+				header = true
+			}
+			fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", cmp.Name(), formatNs(cmp.Before.NsOp), formatNs(cmp.After.NsOp), delta.Percent())
+		}
+	}
+
+	header = false
+	if *magSort {
+		sort.Sort(ByDeltaMbS(cmps))
+	}
+	for _, cmp := range cmps {
+		if !cmp.Measured(MbS) {
+			continue
+		}
+		if delta := cmp.DeltaMbS(); !*changedOnly || delta.Changed() {
+			if !header {
+				fmt.Fprint(w, "\nbenchmark\told MB/s\tnew MB/s\tspeedup\n")
+				header = true
+			}
+			fmt.Fprintf(w, "%s\t%.2f\t%.2f\t%s\n", cmp.Name(), cmp.Before.MbS, cmp.After.MbS, delta.Multiple())
+		}
+	}
+
+	header = false
+	if *magSort {
+		sort.Sort(ByDeltaAllocsOp(cmps))
+	}
+	for _, cmp := range cmps {
+		if !cmp.Measured(AllocsOp) {
+			continue
+		}
+		if delta := cmp.DeltaAllocsOp(); !*changedOnly || delta.Changed() {
+			if !header {
+				fmt.Fprint(w, "\nbenchmark\told allocs\tnew allocs\tdelta\n")
+				header = true
+			}
+			fmt.Fprintf(w, "%s\t%d\t%d\t%s\n", cmp.Name(), cmp.Before.AllocsOp, cmp.After.AllocsOp, delta.Percent())
+		}
+	}
+
+	header = false
+	if *magSort {
+		sort.Sort(ByDeltaBOp(cmps))
+	}
+	for _, cmp := range cmps {
+		if !cmp.Measured(BOp) {
+			continue
+		}
+		if delta := cmp.DeltaBOp(); !*changedOnly || delta.Changed() {
+			if !header {
+				fmt.Fprint(w, "\nbenchmark\told bytes\tnew bytes\tdelta\n")
+				header = true
+			}
+			fmt.Fprintf(w, "%s\t%d\t%d\t%s\n", cmp.Name(), cmp.Before.BOp, cmp.After.BOp, cmp.DeltaBOp().Percent())
+		}
+	}
+}
+
+func fatal(msg interface{}) {
+	fmt.Fprintln(os.Stderr, msg)
+	os.Exit(1)
+}
+
+func parseFile(path string) BenchSet {
+	f, err := os.Open(path)
+	if err != nil {
+		fatal(err)
+	}
+	bb, err := ParseBenchSet(f)
+	if err != nil {
+		fatal(err)
+	}
+	return bb
+}
+
+// formatNs formats ns measurements to expose a useful amount of
+// precision. It mirrors the ns precision logic of testing.B.
+func formatNs(ns float64) string {
+	prec := 0
+	switch {
+	case ns < 10:
+		prec = 2
+	case ns < 100:
+		prec = 1
+	}
+	return strconv.FormatFloat(ns, 'f', prec, 64)
+}
diff --git a/third_party/go.tools/cmd/benchcmp/compare.go b/third_party/go.tools/cmd/benchcmp/compare.go
new file mode 100644
index 0000000..9ebe426
--- /dev/null
+++ b/third_party/go.tools/cmd/benchcmp/compare.go
@@ -0,0 +1,148 @@
+// Copyright 2014 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 (
+	"fmt"
+	"math"
+)
+
+// BenchCmp is a pair of benchmarks.
+type BenchCmp struct {
+	Before *Bench
+	After  *Bench
+}
+
+// Correlate correlates benchmarks from two BenchSets.
+func Correlate(before, after BenchSet) (cmps []BenchCmp, warnings []string) {
+	cmps = make([]BenchCmp, 0, len(after))
+	for name, beforebb := range before {
+		afterbb := after[name]
+		if len(beforebb) != len(afterbb) {
+			warnings = append(warnings, fmt.Sprintf("ignoring %s: before has %d instances, after has %d", name, len(beforebb), len(afterbb)))
+			continue
+		}
+		for i, beforeb := range beforebb {
+			afterb := afterbb[i]
+			cmps = append(cmps, BenchCmp{beforeb, afterb})
+		}
+	}
+	return
+}
+
+func (c BenchCmp) Name() string           { return c.Before.Name }
+func (c BenchCmp) String() string         { return fmt.Sprintf("<%s, %s>", c.Before, c.After) }
+func (c BenchCmp) Measured(flag int) bool { return c.Before.Measured&c.After.Measured&flag != 0 }
+func (c BenchCmp) DeltaNsOp() Delta       { return Delta{c.Before.NsOp, c.After.NsOp} }
+func (c BenchCmp) DeltaMbS() Delta        { return Delta{c.Before.MbS, c.After.MbS} }
+func (c BenchCmp) DeltaBOp() Delta        { return Delta{float64(c.Before.BOp), float64(c.After.BOp)} }
+func (c BenchCmp) DeltaAllocsOp() Delta {
+	return Delta{float64(c.Before.AllocsOp), float64(c.After.AllocsOp)}
+}
+
+// Delta is the before and after value for a benchmark measurement.
+// Both must be non-negative.
+type Delta struct {
+	Before float64
+	After  float64
+}
+
+// mag calculates the magnitude of a change, regardless of the direction of
+// the change. mag is intended for sorting and has no independent meaning.
+func (d Delta) mag() float64 {
+	switch {
+	case d.Before != 0 && d.After != 0 && d.Before >= d.After:
+		return d.After / d.Before
+	case d.Before != 0 && d.After != 0 && d.Before < d.After:
+		return d.Before / d.After
+	case d.Before == 0 && d.After == 0:
+		return 1
+	default:
+		// 0 -> 1 or 1 -> 0
+		// These are significant changes and worth surfacing.
+		return math.Inf(1)
+	}
+}
+
+// Changed reports whether the benchmark quantities are different.
+func (d Delta) Changed() bool { return d.Before != d.After }
+
+// Float64 returns After / Before. If Before is 0, Float64 returns
+// 1 if After is also 0, and +Inf otherwise.
+func (d Delta) Float64() float64 {
+	switch {
+	case d.Before != 0:
+		return d.After / d.Before
+	case d.After == 0:
+		return 1
+	default:
+		return math.Inf(1)
+	}
+}
+
+// Percent formats a Delta as a percent change, ranging from -100% up.
+func (d Delta) Percent() string {
+	return fmt.Sprintf("%+.2f%%", 100*d.Float64()-100)
+}
+
+// Multiple formats a Delta as a multiplier, ranging from 0.00x up.
+func (d Delta) Multiple() string {
+	return fmt.Sprintf("%.2fx", d.Float64())
+}
+
+func (d Delta) String() string {
+	return fmt.Sprintf("Δ(%f, %f)", d.Before, d.After)
+}
+
+// ByParseOrder sorts BenchCmps to match the order in
+// which the Before benchmarks were presented to Parse.
+type ByParseOrder []BenchCmp
+
+func (x ByParseOrder) Len() int           { return len(x) }
+func (x ByParseOrder) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x ByParseOrder) Less(i, j int) bool { return x[i].Before.ord < x[j].Before.ord }
+
+// lessByDelta provides lexicographic ordering:
+//   * largest delta by magnitude
+//   * alphabetic by name
+func lessByDelta(i, j BenchCmp, calcDelta func(BenchCmp) Delta) bool {
+	iDelta, jDelta := calcDelta(i).mag(), calcDelta(j).mag()
+	if iDelta != jDelta {
+		return iDelta < jDelta
+	}
+	return i.Name() < j.Name()
+}
+
+// ByDeltaNsOp sorts BenchCmps lexicographically by change
+// in ns/op, descending, then by benchmark name.
+type ByDeltaNsOp []BenchCmp
+
+func (x ByDeltaNsOp) Len() int           { return len(x) }
+func (x ByDeltaNsOp) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x ByDeltaNsOp) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaNsOp) }
+
+// ByDeltaMbS sorts BenchCmps lexicographically by change
+// in MB/s, descending, then by benchmark name.
+type ByDeltaMbS []BenchCmp
+
+func (x ByDeltaMbS) Len() int           { return len(x) }
+func (x ByDeltaMbS) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x ByDeltaMbS) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaMbS) }
+
+// ByDeltaBOp sorts BenchCmps lexicographically by change
+// in B/op, descending, then by benchmark name.
+type ByDeltaBOp []BenchCmp
+
+func (x ByDeltaBOp) Len() int           { return len(x) }
+func (x ByDeltaBOp) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x ByDeltaBOp) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaBOp) }
+
+// ByDeltaAllocsOp sorts BenchCmps lexicographically by change
+// in allocs/op, descending, then by benchmark name.
+type ByDeltaAllocsOp []BenchCmp
+
+func (x ByDeltaAllocsOp) Len() int           { return len(x) }
+func (x ByDeltaAllocsOp) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x ByDeltaAllocsOp) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaAllocsOp) }
diff --git a/third_party/go.tools/cmd/benchcmp/compare_test.go b/third_party/go.tools/cmd/benchcmp/compare_test.go
new file mode 100644
index 0000000..5baca66
--- /dev/null
+++ b/third_party/go.tools/cmd/benchcmp/compare_test.go
@@ -0,0 +1,131 @@
+// Copyright 2014 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 (
+	"math"
+	"reflect"
+	"sort"
+	"testing"
+)
+
+func TestDelta(t *testing.T) {
+	cases := []struct {
+		before  float64
+		after   float64
+		mag     float64
+		f       float64
+		changed bool
+		pct     string
+		mult    string
+	}{
+		{before: 1, after: 1, mag: 1, f: 1, changed: false, pct: "+0.00%", mult: "1.00x"},
+		{before: 1, after: 2, mag: 0.5, f: 2, changed: true, pct: "+100.00%", mult: "2.00x"},
+		{before: 2, after: 1, mag: 0.5, f: 0.5, changed: true, pct: "-50.00%", mult: "0.50x"},
+		{before: 0, after: 0, mag: 1, f: 1, changed: false, pct: "+0.00%", mult: "1.00x"},
+		{before: 1, after: 0, mag: math.Inf(1), f: 0, changed: true, pct: "-100.00%", mult: "0.00x"},
+		{before: 0, after: 1, mag: math.Inf(1), f: math.Inf(1), changed: true, pct: "+Inf%", mult: "+Infx"},
+	}
+	for _, tt := range cases {
+		d := Delta{tt.before, tt.after}
+		if want, have := tt.mag, d.mag(); want != have {
+			t.Errorf("%s.mag(): want %f have %f", d, want, have)
+		}
+		if want, have := tt.f, d.Float64(); want != have {
+			t.Errorf("%s.Float64(): want %f have %f", d, want, have)
+		}
+		if want, have := tt.changed, d.Changed(); want != have {
+			t.Errorf("%s.Changed(): want %t have %t", d, want, have)
+		}
+		if want, have := tt.pct, d.Percent(); want != have {
+			t.Errorf("%s.Percent(): want %q have %q", d, want, have)
+		}
+		if want, have := tt.mult, d.Multiple(); want != have {
+			t.Errorf("%s.Multiple(): want %q have %q", d, want, have)
+		}
+	}
+}
+
+func TestCorrelate(t *testing.T) {
+	// Benches that are going to be successfully correlated get N thus:
+	//   0x<counter><num benches><b = before | a = after>
+	// Read this: "<counter> of <num benches>, from <before|after>".
+	before := BenchSet{
+		"BenchmarkOneEach":   []*Bench{{Name: "BenchmarkOneEach", N: 0x11b}},
+		"BenchmarkOneToNone": []*Bench{{Name: "BenchmarkOneToNone"}},
+		"BenchmarkOneToTwo":  []*Bench{{Name: "BenchmarkOneToTwo"}},
+		"BenchmarkTwoToOne": []*Bench{
+			{Name: "BenchmarkTwoToOne"},
+			{Name: "BenchmarkTwoToOne"},
+		},
+		"BenchmarkTwoEach": []*Bench{
+			{Name: "BenchmarkTwoEach", N: 0x12b},
+			{Name: "BenchmarkTwoEach", N: 0x22b},
+		},
+	}
+
+	after := BenchSet{
+		"BenchmarkOneEach":   []*Bench{{Name: "BenchmarkOneEach", N: 0x11a}},
+		"BenchmarkNoneToOne": []*Bench{{Name: "BenchmarkNoneToOne"}},
+		"BenchmarkTwoToOne":  []*Bench{{Name: "BenchmarkTwoToOne"}},
+		"BenchmarkOneToTwo": []*Bench{
+			{Name: "BenchmarkOneToTwo"},
+			{Name: "BenchmarkOneToTwo"},
+		},
+		"BenchmarkTwoEach": []*Bench{
+			{Name: "BenchmarkTwoEach", N: 0x12a},
+			{Name: "BenchmarkTwoEach", N: 0x22a},
+		},
+	}
+
+	pairs, errs := Correlate(before, after)
+
+	// Fail to match: BenchmarkOneToNone, BenchmarkOneToTwo, BenchmarkTwoToOne.
+	// Correlate does not notice BenchmarkNoneToOne.
+	if len(errs) != 3 {
+		t.Errorf("Correlated expected 4 errors, got %d: %v", len(errs), errs)
+	}
+
+	// Want three correlated pairs: one BenchmarkOneEach, two BenchmarkTwoEach.
+	if len(pairs) != 3 {
+		t.Fatalf("Correlated expected 3 pairs, got %v", pairs)
+	}
+
+	for _, pair := range pairs {
+		if pair.Before.N&0xF != 0xb {
+			t.Errorf("unexpected Before in pair %s", pair)
+		}
+		if pair.After.N&0xF != 0xa {
+			t.Errorf("unexpected After in pair %s", pair)
+		}
+		if pair.Before.N>>4 != pair.After.N>>4 {
+			t.Errorf("mismatched pair %s", pair)
+		}
+	}
+}
+
+func TestBenchCmpSorting(t *testing.T) {
+	c := []BenchCmp{
+		{&Bench{Name: "BenchmarkMuchFaster", NsOp: 10, ord: 3}, &Bench{Name: "BenchmarkMuchFaster", NsOp: 1}},
+		{&Bench{Name: "BenchmarkSameB", NsOp: 5, ord: 1}, &Bench{Name: "BenchmarkSameB", NsOp: 5}},
+		{&Bench{Name: "BenchmarkSameA", NsOp: 5, ord: 2}, &Bench{Name: "BenchmarkSameA", NsOp: 5}},
+		{&Bench{Name: "BenchmarkSlower", NsOp: 10, ord: 0}, &Bench{Name: "BenchmarkSlower", NsOp: 11}},
+	}
+
+	// Test just one magnitude-based sort order; they are symmetric.
+	sort.Sort(ByDeltaNsOp(c))
+	want := []string{"BenchmarkMuchFaster", "BenchmarkSlower", "BenchmarkSameA", "BenchmarkSameB"}
+	have := []string{c[0].Name(), c[1].Name(), c[2].Name(), c[3].Name()}
+	if !reflect.DeepEqual(want, have) {
+		t.Errorf("ByDeltaNsOp incorrect sorting: want %v have %v", want, have)
+	}
+
+	sort.Sort(ByParseOrder(c))
+	want = []string{"BenchmarkSlower", "BenchmarkSameB", "BenchmarkSameA", "BenchmarkMuchFaster"}
+	have = []string{c[0].Name(), c[1].Name(), c[2].Name(), c[3].Name()}
+	if !reflect.DeepEqual(want, have) {
+		t.Errorf("ByParseOrder incorrect sorting: want %v have %v", want, have)
+	}
+}
diff --git a/third_party/go.tools/cmd/benchcmp/doc.go b/third_party/go.tools/cmd/benchcmp/doc.go
new file mode 100644
index 0000000..b0714b9
--- /dev/null
+++ b/third_party/go.tools/cmd/benchcmp/doc.go
@@ -0,0 +1,37 @@
+// Copyright 2014 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.
+
+/*
+
+The benchcmp command displays performance changes between benchmarks.
+
+Benchcmp parses the output of two 'go test' benchmark runs,
+correlates the results per benchmark, and displays the deltas.
+
+To measure the performance impact of a change, use 'go test'
+to run benchmarks before and after the change:
+
+	go test -run=NONE -bench=. ./... > old.txt
+	# make changes
+	go test -run=NONE -bench=. ./... > new.txt
+
+Then feed the benchmark results to benchcmp:
+
+	benchcmp old.txt new.txt
+
+Benchcmp will summarize and display the performance changes,
+in a format like this:
+
+	$ benchcmp old.txt new.txt
+	benchmark           old ns/op     new ns/op     delta
+	BenchmarkConcat     523           68.6          -86.88%
+
+	benchmark           old allocs     new allocs     delta
+	BenchmarkConcat     3              1              -66.67%
+
+	benchmark           old bytes     new bytes     delta
+	BenchmarkConcat     80            48            -40.00%
+
+*/
+package main
diff --git a/third_party/go.tools/cmd/benchcmp/parse.go b/third_party/go.tools/cmd/benchcmp/parse.go
new file mode 100644
index 0000000..f1df681
--- /dev/null
+++ b/third_party/go.tools/cmd/benchcmp/parse.go
@@ -0,0 +1,135 @@
+// Copyright 2014 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 (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"strconv"
+	"strings"
+)
+
+// Flags used by Bench.Measured to indicate
+// which measurements a Bench contains.
+const (
+	NsOp = 1 << iota
+	MbS
+	BOp
+	AllocsOp
+)
+
+// Bench is one run of a single benchmark.
+type Bench struct {
+	Name     string  // benchmark name
+	N        int     // number of iterations
+	NsOp     float64 // nanoseconds per iteration
+	MbS      float64 // MB processed per second
+	BOp      uint64  // bytes allocated per iteration
+	AllocsOp uint64  // allocs per iteration
+	Measured int     // which measurements were recorded
+	ord      int     // ordinal position within a benchmark run, used for sorting
+}
+
+// ParseLine extracts a Bench from a single line of testing.B output.
+func ParseLine(line string) (*Bench, error) {
+	fields := strings.Fields(line)
+
+	// Two required, positional fields: Name and iterations.
+	if len(fields) < 2 {
+		return nil, fmt.Errorf("two fields required, have %d", len(fields))
+	}
+	if !strings.HasPrefix(fields[0], "Benchmark") {
+		return nil, fmt.Errorf(`first field does not start with "Benchmark`)
+	}
+	n, err := strconv.Atoi(fields[1])
+	if err != nil {
+		return nil, err
+	}
+	b := &Bench{Name: fields[0], N: n}
+
+	// Parse any remaining pairs of fields; we've parsed one pair already.
+	for i := 1; i < len(fields)/2; i++ {
+		b.parseMeasurement(fields[i*2], fields[i*2+1])
+	}
+	return b, nil
+}
+
+func (b *Bench) parseMeasurement(quant string, unit string) {
+	switch unit {
+	case "ns/op":
+		if f, err := strconv.ParseFloat(quant, 64); err == nil {
+			b.NsOp = f
+			b.Measured |= NsOp
+		}
+	case "MB/s":
+		if f, err := strconv.ParseFloat(quant, 64); err == nil {
+			b.MbS = f
+			b.Measured |= MbS
+		}
+	case "B/op":
+		if i, err := strconv.ParseUint(quant, 10, 64); err == nil {
+			b.BOp = i
+			b.Measured |= BOp
+		}
+	case "allocs/op":
+		if i, err := strconv.ParseUint(quant, 10, 64); err == nil {
+			b.AllocsOp = i
+			b.Measured |= AllocsOp
+		}
+	}
+}
+
+func (b *Bench) String() string {
+	buf := new(bytes.Buffer)
+	fmt.Fprintf(buf, "%s %d", b.Name, b.N)
+	if b.Measured&NsOp != 0 {
+		fmt.Fprintf(buf, " %.2f ns/op", b.NsOp)
+	}
+	if b.Measured&MbS != 0 {
+		fmt.Fprintf(buf, " %.2f MB/s", b.MbS)
+	}
+	if b.Measured&BOp != 0 {
+		fmt.Fprintf(buf, " %d B/op", b.BOp)
+	}
+	if b.Measured&AllocsOp != 0 {
+		fmt.Fprintf(buf, " %d allocs/op", b.AllocsOp)
+	}
+	return buf.String()
+}
+
+// BenchSet is a collection of benchmarks from one
+// testing.B run, keyed by name to facilitate comparison.
+type BenchSet map[string][]*Bench
+
+// Parse extracts a BenchSet from testing.B output. Parse
+// preserves the order of benchmarks that have identical names.
+func ParseBenchSet(r io.Reader) (BenchSet, error) {
+	bb := make(BenchSet)
+	scan := bufio.NewScanner(r)
+	ord := 0
+	for scan.Scan() {
+		if b, err := ParseLine(scan.Text()); err == nil {
+			b.ord = ord
+			ord++
+			old := bb[b.Name]
+			if *best && old != nil {
+				if old[0].NsOp < b.NsOp {
+					continue
+				}
+				b.ord = old[0].ord
+				bb[b.Name] = old[:0]
+			}
+			bb[b.Name] = append(bb[b.Name], b)
+		}
+	}
+
+	if err := scan.Err(); err != nil {
+		return nil, err
+	}
+
+	return bb, nil
+}
diff --git a/third_party/go.tools/cmd/benchcmp/parse_test.go b/third_party/go.tools/cmd/benchcmp/parse_test.go
new file mode 100644
index 0000000..a59b20c
--- /dev/null
+++ b/third_party/go.tools/cmd/benchcmp/parse_test.go
@@ -0,0 +1,194 @@
+// Copyright 2014 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 (
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func TestParseLine(t *testing.T) {
+	cases := []struct {
+		line string
+		want *Bench
+		err  bool // expect an error
+	}{
+		{
+			line: "BenchmarkEncrypt	100000000	        19.6 ns/op",
+			want: &Bench{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsOp: 19.6,
+				Measured: NsOp,
+			},
+		},
+		{
+			line: "BenchmarkEncrypt	100000000	        19.6 ns/op	 817.77 MB/s",
+			want: &Bench{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsOp: 19.6, MbS: 817.77,
+				Measured: NsOp | MbS,
+			},
+		},
+		{
+			line: "BenchmarkEncrypt	100000000	        19.6 ns/op	 817.77",
+			want: &Bench{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsOp: 19.6,
+				Measured: NsOp,
+			},
+		},
+		{
+			line: "BenchmarkEncrypt	100000000	        19.6 ns/op	 817.77 MB/s	       5 allocs/op",
+			want: &Bench{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsOp: 19.6, MbS: 817.77, AllocsOp: 5,
+				Measured: NsOp | MbS | AllocsOp,
+			},
+		},
+		{
+			line: "BenchmarkEncrypt	100000000	        19.6 ns/op	 817.77 MB/s	       3 B/op	       5 allocs/op",
+			want: &Bench{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsOp: 19.6, MbS: 817.77, BOp: 3, AllocsOp: 5,
+				Measured: NsOp | MbS | BOp | AllocsOp,
+			},
+		},
+		// error handling cases
+		{
+			line: "BenchPress	100	        19.6 ns/op", // non-benchmark
+			err: true,
+		},
+		{
+			line: "BenchmarkEncrypt	lots	        19.6 ns/op", // non-int iterations
+			err: true,
+		},
+		{
+			line: "BenchmarkBridge	100000000	        19.6 smoots", // unknown unit
+			want: &Bench{
+				Name: "BenchmarkBridge",
+				N:    100000000,
+			},
+		},
+		{
+			line: "PASS",
+			err:  true,
+		},
+	}
+
+	for _, tt := range cases {
+		have, err := ParseLine(tt.line)
+		if tt.err && err == nil {
+			t.Errorf("parsing line %q should have failed", tt.line)
+			continue
+		}
+		if !reflect.DeepEqual(have, tt.want) {
+			t.Errorf("parsed line %q incorrectly, want %v have %v", tt.line, tt.want, have)
+		}
+	}
+}
+
+func TestParseBenchSet(t *testing.T) {
+	// Test two things:
+	// 1. The noise that can accompany testing.B output gets ignored.
+	// 2. Benchmarks with the same name have their order preserved.
+	in := `
+		?   	crypto	[no test files]
+		PASS
+				pem_decrypt_test.go:17: test 4. %!s(x509.PEMCipher=5)
+			... [output truncated]
+
+		BenchmarkEncrypt	100000000	        19.6 ns/op
+		BenchmarkEncrypt	 5000000	       517 ns/op
+		=== RUN TestChunk
+		--- PASS: TestChunk (0.00 seconds)
+		--- SKIP: TestLinuxSendfile (0.00 seconds)
+			fs_test.go:716: skipping; linux-only test
+		BenchmarkReadRequestApachebench	 1000000	      2960 ns/op	  27.70 MB/s	     839 B/op	       9 allocs/op
+		BenchmarkClientServerParallel64	   50000	     59192 ns/op	    7028 B/op	      60 allocs/op
+		ok  	net/http	95.783s
+	`
+
+	want := BenchSet{
+		"BenchmarkReadRequestApachebench": []*Bench{
+			{
+				Name: "BenchmarkReadRequestApachebench",
+				N:    1000000, NsOp: 2960, MbS: 27.70, BOp: 839, AllocsOp: 9,
+				Measured: NsOp | MbS | BOp | AllocsOp,
+				ord:      2,
+			},
+		},
+		"BenchmarkClientServerParallel64": []*Bench{
+			{
+				Name: "BenchmarkClientServerParallel64",
+				N:    50000, NsOp: 59192, BOp: 7028, AllocsOp: 60,
+				Measured: NsOp | BOp | AllocsOp,
+				ord:      3,
+			},
+		},
+		"BenchmarkEncrypt": []*Bench{
+			{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsOp: 19.6,
+				Measured: NsOp,
+				ord:      0,
+			},
+			{
+				Name: "BenchmarkEncrypt",
+				N:    5000000, NsOp: 517,
+				Measured: NsOp,
+				ord:      1,
+			},
+		},
+	}
+
+	have, err := ParseBenchSet(strings.NewReader(in))
+	if err != nil {
+		t.Fatalf("unexpected err during ParseBenchSet: %v", err)
+	}
+	if !reflect.DeepEqual(want, have) {
+		t.Errorf("parsed bench set incorrectly, want %v have %v", want, have)
+	}
+}
+
+func TestParseBenchSetBest(t *testing.T) {
+	// Test that -best mode takes best ns/op.
+	*best = true
+	defer func() {
+		*best = false
+	}()
+
+	in := `
+		Benchmark1 10 100 ns/op
+		Benchmark2 10 60 ns/op
+		Benchmark2 10 500 ns/op
+		Benchmark1 10 50 ns/op
+	`
+
+	want := BenchSet{
+		"Benchmark1": []*Bench{
+			{
+				Name: "Benchmark1",
+				N:    10, NsOp: 50, Measured: NsOp,
+				ord: 0,
+			},
+		},
+		"Benchmark2": []*Bench{
+			{
+				Name: "Benchmark2",
+				N:    10, NsOp: 60, Measured: NsOp,
+				ord: 1,
+			},
+		},
+	}
+
+	have, err := ParseBenchSet(strings.NewReader(in))
+	if err != nil {
+		t.Fatalf("unexpected err during ParseBenchSet: %v", err)
+	}
+	if !reflect.DeepEqual(want, have) {
+		t.Errorf("parsed bench set incorrectly, want %v have %v", want, have)
+	}
+}
diff --git a/third_party/go.tools/cmd/callgraph/main.go b/third_party/go.tools/cmd/callgraph/main.go
new file mode 100644
index 0000000..b060715
--- /dev/null
+++ b/third_party/go.tools/cmd/callgraph/main.go
@@ -0,0 +1,310 @@
+// Copyright 2014 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.
+
+// callgraph: a tool for reporting the call graph of a Go program.
+// See Usage for details, or run with -help.
+package main
+
+// TODO(adonovan):
+//
+// Features:
+// - restrict graph to a single package
+// - output
+//   - functions reachable from root (use digraph tool?)
+//   - unreachable functions (use digraph tool?)
+//   - dynamic (runtime) types
+//   - indexed output (numbered nodes)
+//   - JSON output
+//   - additional template fields:
+//     callee file/line/col
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/build"
+	"go/token"
+	"io"
+	"os"
+	"runtime"
+	"text/template"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/callgraph/rta"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/pointer"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+)
+
+var algoFlag = flag.String("algo", "rta",
+	`Call graph construction algorithm, one of "rta" or "pta"`)
+
+var testFlag = flag.Bool("test", false,
+	"Loads test code (*_test.go) for imported packages")
+
+var formatFlag = flag.String("format",
+	"{{.Caller}}\t--{{.Dynamic}}-{{.Line}}:{{.Column}}-->\t{{.Callee}}",
+	"A template expression specifying how to format an edge")
+
+const Usage = `callgraph: display the the call graph of a Go program.
+
+Usage:
+
+  callgraph [-algo=rta|pta] [-test] [-format=...] <args>...
+
+Flags:
+
+-algo      Specifies the call-graph construction algorithm.  One of:
+           "rta": Rapid Type Analysis  (simple and fast)
+           "pta": inclusion-based Points-To Analysis (slower but more precise)
+
+-test      Include the package's tests in the analysis.
+
+-format    Specifies the format in which each call graph edge is displayed.
+           One of:
+           "digraph":   output suitable for input to
+                        golang.org/x/tools/cmd/digraph.
+           "graphviz":  output in AT&T GraphViz (.dot) format.
+
+           All other values are interpreted using text/template syntax.
+           The default value is:
+
+            {{.Caller}}\t--{{.Dynamic}}-{{.Line}}:{{.Column}}-->\t{{.Callee}}
+
+           The structure passed to the template is (effectively):
+
+                   type Edge struct {
+                           Caller      *ssa.Function // calling function
+                           Callee      *ssa.Function // called function
+
+                           // Call site:
+                           Filename    string // containing file
+                           Offset      int    // offset within file of '('
+                           Line        int    // line number
+                           Column      int    // column number of call
+                           Dynamic     string // "static" or "dynamic"
+                           Description string // e.g. "static method call"
+                   }
+
+           Caller and Callee are *ssa.Function values, which print as
+           "(*sync/atomic.Mutex).Lock", but other attributes may be
+           derived from them, e.g. Caller.Pkg.Object.Path yields the
+           import path of the enclosing package.  Consult the go/ssa
+           API documentation for details.
+
+` + loader.FromArgsUsage + `
+
+Examples:
+
+  Show the call graph of the trivial web server application:
+
+    callgraph -format digraph $GOROOT/src/net/http/triv.go
+
+  Same, but show only the packages of each function:
+
+    callgraph -format '{{.Caller.Pkg.Object.Path}} -> {{.Callee.Pkg.Object.Path}}' \
+      $GOROOT/src/net/http/triv.go | sort | uniq
+
+  Show functions that make dynamic calls into the 'fmt' test package,
+  using the pointer analysis algorithm:
+
+    callgraph -format='{{.Caller}} -{{.Dynamic}}-> {{.Callee}}' -test -algo=pta fmt |
+      sed -ne 's/-dynamic-/--/p' |
+      sed -ne 's/-->.*fmt_test.*$//p' | sort | uniq
+
+  Show all functions directly called by the callgraph tool's main function:
+
+    callgraph -format=digraph golang.org/x/tools/cmd/callgraph |
+      digraph succs golang.org/x/tools/cmd/callgraph.main
+`
+
+func init() {
+	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
+	// For small machines, use at least 4 threads.
+	if os.Getenv("GOMAXPROCS") == "" {
+		n := runtime.NumCPU()
+		if n < 4 {
+			n = 4
+		}
+		runtime.GOMAXPROCS(n)
+	}
+}
+
+func main() {
+	flag.Parse()
+	if err := doCallgraph(&build.Default, *algoFlag, *formatFlag, *testFlag, flag.Args()); err != nil {
+		fmt.Fprintf(os.Stderr, "callgraph: %s\n", err)
+		os.Exit(1)
+	}
+}
+
+var stdout io.Writer = os.Stdout
+
+func doCallgraph(ctxt *build.Context, algo, format string, tests bool, args []string) error {
+	conf := loader.Config{
+		Build:         ctxt,
+		SourceImports: true,
+	}
+
+	if len(args) == 0 {
+		fmt.Fprintln(os.Stderr, Usage)
+		return nil
+	}
+
+	// Use the initial packages from the command line.
+	args, err := conf.FromArgs(args, tests)
+	if err != nil {
+		return err
+	}
+
+	// Load, parse and type-check the whole program.
+	iprog, err := conf.Load()
+	if err != nil {
+		return err
+	}
+
+	// Create and build SSA-form program representation.
+	prog := ssa.Create(iprog, 0)
+	prog.BuildAll()
+
+	// Determine the main package.
+	// TODO(adonovan): allow independent control over tests, mains
+	// and libraries.
+	// TODO(adonovan): put this logic in a library; we keep reinventing it.
+	var main *ssa.Package
+	pkgs := prog.AllPackages()
+	if tests {
+		// If -test, use all packages' tests.
+		if len(pkgs) > 0 {
+			main = prog.CreateTestMainPackage(pkgs...)
+		}
+		if main == nil {
+			return fmt.Errorf("no tests")
+		}
+	} else {
+		// Otherwise, use main.main.
+		for _, pkg := range pkgs {
+			if pkg.Object.Name() == "main" {
+				main = pkg
+				if main.Func("main") == nil {
+					return fmt.Errorf("no func main() in main package")
+				}
+				break
+			}
+		}
+		if main == nil {
+			return fmt.Errorf("no main package")
+		}
+	}
+
+	// Invariant: main package has a main() function.
+
+	// -- call graph construction ------------------------------------------
+
+	var cg *callgraph.Graph
+
+	switch algo {
+	case "pta":
+		config := &pointer.Config{
+			Mains:          []*ssa.Package{main},
+			BuildCallGraph: true,
+		}
+		ptares, err := pointer.Analyze(config)
+		if err != nil {
+			return err // internal error in pointer analysis
+		}
+		cg = ptares.CallGraph
+
+	case "rta":
+		roots := []*ssa.Function{
+			main.Func("init"),
+			main.Func("main"),
+		}
+		rtares := rta.Analyze(roots, true)
+		cg = rtares.CallGraph
+
+		// NB: RTA gives us Reachable and RuntimeTypes too.
+
+	default:
+		return fmt.Errorf("unknown algorithm: %s", algo)
+	}
+
+	cg.DeleteSyntheticNodes()
+
+	// -- output------------------------------------------------------------
+
+	var before, after string
+
+	// Pre-canned formats.
+	switch format {
+	case "digraph":
+		format = `{{printf "%q %q" .Caller .Callee}}`
+
+	case "graphviz":
+		before = "digraph callgraph {\n"
+		after = "}\n"
+		format = `  {{printf "%q" .Caller}} -> {{printf "%q" .Callee}}"`
+	}
+
+	tmpl, err := template.New("-format").Parse(format)
+	if err != nil {
+		return fmt.Errorf("invalid -format template: %v", err)
+	}
+
+	// Allocate these once, outside the traversal.
+	var buf bytes.Buffer
+	data := Edge{fset: prog.Fset}
+
+	fmt.Fprint(stdout, before)
+	if err := callgraph.GraphVisitEdges(cg, func(edge *callgraph.Edge) error {
+		data.position.Offset = -1
+		data.edge = edge
+		data.Caller = edge.Caller.Func
+		data.Callee = edge.Callee.Func
+
+		buf.Reset()
+		if err := tmpl.Execute(&buf, &data); err != nil {
+			return err
+		}
+		stdout.Write(buf.Bytes())
+		if len := buf.Len(); len == 0 || buf.Bytes()[len-1] != '\n' {
+			fmt.Fprintln(stdout)
+		}
+		return nil
+	}); err != nil {
+		return err
+	}
+	fmt.Fprint(stdout, after)
+	return nil
+}
+
+type Edge struct {
+	Caller *ssa.Function
+	Callee *ssa.Function
+
+	edge     *callgraph.Edge
+	fset     *token.FileSet
+	position token.Position // initialized lazily
+}
+
+func (e *Edge) pos() *token.Position {
+	if e.position.Offset == -1 {
+		e.position = e.fset.Position(e.edge.Pos()) // called lazily
+	}
+	return &e.position
+}
+
+func (e *Edge) Filename() string { return e.pos().Filename }
+func (e *Edge) Column() int      { return e.pos().Column }
+func (e *Edge) Line() int        { return e.pos().Line }
+func (e *Edge) Offset() int      { return e.pos().Offset }
+
+func (e *Edge) Dynamic() string {
+	if e.edge.Site != nil && e.edge.Site.Common().StaticCallee() == nil {
+		return "dynamic"
+	}
+	return "static"
+}
+
+func (e *Edge) Description() string { return e.edge.Description() }
diff --git a/third_party/go.tools/cmd/callgraph/main_test.go b/third_party/go.tools/cmd/callgraph/main_test.go
new file mode 100644
index 0000000..93ccb61
--- /dev/null
+++ b/third_party/go.tools/cmd/callgraph/main_test.go
@@ -0,0 +1,73 @@
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"go/build"
+	"reflect"
+	"sort"
+	"strings"
+	"testing"
+)
+
+func TestCallgraph(t *testing.T) {
+	ctxt := build.Default // copy
+	ctxt.GOPATH = "testdata"
+
+	const format = "{{.Caller}} --> {{.Callee}}"
+
+	for _, test := range []struct {
+		algo, format string
+		tests        bool
+		want         []string
+	}{
+		{"rta", format, false, []string{
+			// rta imprecisely shows cross product of {main,main2} x {C,D}
+			`pkg.main --> (pkg.C).f`,
+			`pkg.main --> (pkg.D).f`,
+			`pkg.main --> pkg.main2`,
+			`pkg.main2 --> (pkg.C).f`,
+			`pkg.main2 --> (pkg.D).f`,
+		}},
+		{"pta", format, false, []string{
+			// pta distinguishes main->C, main2->D.  Also has a root node.
+			`<root> --> pkg.init`,
+			`<root> --> pkg.main`,
+			`pkg.main --> (pkg.C).f`,
+			`pkg.main --> pkg.main2`,
+			`pkg.main2 --> (pkg.D).f`,
+		}},
+		// tests: main is not called.
+		{"rta", format, true, []string{
+			`pkg.Example --> (pkg.C).f`,
+			`testmain.init --> pkg.init`,
+		}},
+		{"pta", format, true, []string{
+			`<root> --> pkg.Example`,
+			`<root> --> testmain.init`,
+			`pkg.Example --> (pkg.C).f`,
+			`testmain.init --> pkg.init`,
+		}},
+	} {
+		stdout = new(bytes.Buffer)
+		if err := doCallgraph(&ctxt, test.algo, test.format, test.tests, []string{"pkg"}); err != nil {
+			t.Error(err)
+			continue
+		}
+
+		got := sortedLines(fmt.Sprint(stdout))
+		if !reflect.DeepEqual(got, test.want) {
+			t.Errorf("callgraph(%q, %q, %t):\ngot:\n%s\nwant:\n%s",
+				test.algo, test.format, test.tests,
+				strings.Join(got, "\n"),
+				strings.Join(test.want, "\n"))
+		}
+	}
+}
+
+func sortedLines(s string) []string {
+	s = strings.TrimSpace(s)
+	lines := strings.Split(s, "\n")
+	sort.Strings(lines)
+	return lines
+}
diff --git a/third_party/go.tools/cmd/callgraph/testdata/src/pkg/pkg.go b/third_party/go.tools/cmd/callgraph/testdata/src/pkg/pkg.go
new file mode 100644
index 0000000..b81c97f
--- /dev/null
+++ b/third_party/go.tools/cmd/callgraph/testdata/src/pkg/pkg.go
@@ -0,0 +1,25 @@
+package main
+
+type I interface {
+	f()
+}
+
+type C int
+
+func (C) f() {}
+
+type D int
+
+func (D) f() {}
+
+func main() {
+	var i I = C(0)
+	i.f() // dynamic call
+
+	main2()
+}
+
+func main2() {
+	var i I = D(0)
+	i.f() // dynamic call
+}
diff --git a/third_party/go.tools/cmd/callgraph/testdata/src/pkg/pkg_test.go b/third_party/go.tools/cmd/callgraph/testdata/src/pkg/pkg_test.go
new file mode 100644
index 0000000..d624757
--- /dev/null
+++ b/third_party/go.tools/cmd/callgraph/testdata/src/pkg/pkg_test.go
@@ -0,0 +1,7 @@
+package main
+
+// Don't import "testing", it adds a lot of callgraph edges.
+
+func Example() {
+	C(0).f()
+}
diff --git a/third_party/go.tools/cmd/cover/cover.go b/third_party/go.tools/cmd/cover/cover.go
new file mode 100644
index 0000000..3aaf246
--- /dev/null
+++ b/third_party/go.tools/cmd/cover/cover.go
@@ -0,0 +1,652 @@
+// Copyright 2013 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 (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"sort"
+	"strconv"
+)
+
+const usageMessage = "" +
+	`Usage of 'go tool cover':
+Given a coverage profile produced by 'go test':
+	go test -coverprofile=c.out
+
+Open a web browser displaying annotated source code:
+	go tool cover -html=c.out
+
+Write out an HTML file instead of launching a web browser:
+	go tool cover -html=c.out -o coverage.html
+
+Display coverage percentages to stdout for each function:
+	go tool cover -func=c.out
+
+Finally, to generate modified source code with coverage annotations
+(what go test -cover does):
+	go tool cover -mode=set -var=CoverageVariableName program.go
+`
+
+func usage() {
+	fmt.Fprintln(os.Stderr, usageMessage)
+	fmt.Fprintln(os.Stderr, "Flags:")
+	flag.PrintDefaults()
+	fmt.Fprintln(os.Stderr, "\n  Only one of -html, -func, or -mode may be set.")
+	os.Exit(2)
+}
+
+var (
+	mode    = flag.String("mode", "", "coverage mode: set, count, atomic")
+	varVar  = flag.String("var", "GoCover", "name of coverage variable to generate")
+	output  = flag.String("o", "", "file for output; default: stdout")
+	htmlOut = flag.String("html", "", "generate HTML representation of coverage profile")
+	funcOut = flag.String("func", "", "output coverage profile information for each function")
+)
+
+var profile string // The profile to read; the value of -html or -func
+
+var counterStmt func(*File, ast.Expr) ast.Stmt
+
+const (
+	atomicPackagePath = "sync/atomic"
+	atomicPackageName = "_cover_atomic_"
+)
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+
+	// Usage information when no arguments.
+	if flag.NFlag() == 0 && flag.NArg() == 0 {
+		flag.Usage()
+	}
+
+	err := parseFlags()
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		fmt.Fprintln(os.Stderr, `For usage information, run "go tool cover -help"`)
+		os.Exit(2)
+	}
+
+	// Generate coverage-annotated source.
+	if *mode != "" {
+		annotate(flag.Arg(0))
+		return
+	}
+
+	// Output HTML or function coverage information.
+	if *htmlOut != "" {
+		err = htmlOutput(profile, *output)
+	} else {
+		err = funcOutput(profile, *output)
+	}
+
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "cover: %v\n", err)
+		os.Exit(2)
+	}
+}
+
+// parseFlags sets the profile and counterStmt globals and performs validations.
+func parseFlags() error {
+	profile = *htmlOut
+	if *funcOut != "" {
+		if profile != "" {
+			return fmt.Errorf("too many options")
+		}
+		profile = *funcOut
+	}
+
+	// Must either display a profile or rewrite Go source.
+	if (profile == "") == (*mode == "") {
+		return fmt.Errorf("too many options")
+	}
+
+	if *mode != "" {
+		switch *mode {
+		case "set":
+			counterStmt = setCounterStmt
+		case "count":
+			counterStmt = incCounterStmt
+		case "atomic":
+			counterStmt = atomicCounterStmt
+		default:
+			return fmt.Errorf("unknown -mode %v", *mode)
+		}
+
+		if flag.NArg() == 0 {
+			return fmt.Errorf("missing source file")
+		} else if flag.NArg() == 1 {
+			return nil
+		}
+	} else if flag.NArg() == 0 {
+		return nil
+	}
+	return fmt.Errorf("too many arguments")
+}
+
+// Block represents the information about a basic block to be recorded in the analysis.
+// Note: Our definition of basic block is based on control structures; we don't break
+// apart && and ||. We could but it doesn't seem important enough to bother.
+type Block struct {
+	startByte token.Pos
+	endByte   token.Pos
+	numStmt   int
+}
+
+// File is a wrapper for the state of a file used in the parser.
+// The basic parse tree walker is a method of this type.
+type File struct {
+	fset      *token.FileSet
+	name      string // Name of file.
+	astFile   *ast.File
+	blocks    []Block
+	atomicPkg string // Package name for "sync/atomic" in this file.
+}
+
+// Visit implements the ast.Visitor interface.
+func (f *File) Visit(node ast.Node) ast.Visitor {
+	switch n := node.(type) {
+	case *ast.BlockStmt:
+		// If it's a switch or select, the body is a list of case clauses; don't tag the block itself.
+		if len(n.List) > 0 {
+			switch n.List[0].(type) {
+			case *ast.CaseClause: // switch
+				for _, n := range n.List {
+					clause := n.(*ast.CaseClause)
+					clause.Body = f.addCounters(clause.Pos(), clause.End(), clause.Body, false)
+				}
+				return f
+			case *ast.CommClause: // select
+				for _, n := range n.List {
+					clause := n.(*ast.CommClause)
+					clause.Body = f.addCounters(clause.Pos(), clause.End(), clause.Body, false)
+				}
+				return f
+			}
+		}
+		n.List = f.addCounters(n.Lbrace, n.Rbrace+1, n.List, true) // +1 to step past closing brace.
+	case *ast.IfStmt:
+		ast.Walk(f, n.Body)
+		if n.Else == nil {
+			return nil
+		}
+		// The elses are special, because if we have
+		//	if x {
+		//	} else if y {
+		//	}
+		// we want to cover the "if y". To do this, we need a place to drop the counter,
+		// so we add a hidden block:
+		//	if x {
+		//	} else {
+		//		if y {
+		//		}
+		//	}
+		switch stmt := n.Else.(type) {
+		case *ast.IfStmt:
+			block := &ast.BlockStmt{
+				Lbrace: n.Body.End(), // Start at end of the "if" block so the covered part looks like it starts at the "else".
+				List:   []ast.Stmt{stmt},
+				Rbrace: stmt.End(),
+			}
+			n.Else = block
+		case *ast.BlockStmt:
+			stmt.Lbrace = n.Body.End() // Start at end of the "if" block so the covered part looks like it starts at the "else".
+		default:
+			panic("unexpected node type in if")
+		}
+		ast.Walk(f, n.Else)
+		return nil
+	case *ast.SelectStmt:
+		// Don't annotate an empty select - creates a syntax error.
+		if n.Body == nil || len(n.Body.List) == 0 {
+			return nil
+		}
+	case *ast.SwitchStmt:
+		// Don't annotate an empty switch - creates a syntax error.
+		if n.Body == nil || len(n.Body.List) == 0 {
+			return nil
+		}
+	}
+	return f
+}
+
+// unquote returns the unquoted string.
+func unquote(s string) string {
+	t, err := strconv.Unquote(s)
+	if err != nil {
+		log.Fatalf("cover: improperly quoted string %q\n", s)
+	}
+	return t
+}
+
+// addImport adds an import for the specified path, if one does not already exist, and returns
+// the local package name.
+func (f *File) addImport(path string) string {
+	// Does the package already import it?
+	for _, s := range f.astFile.Imports {
+		if unquote(s.Path.Value) == path {
+			if s.Name != nil {
+				return s.Name.Name
+			}
+			return filepath.Base(path)
+		}
+	}
+	newImport := &ast.ImportSpec{
+		Name: ast.NewIdent(atomicPackageName),
+		Path: &ast.BasicLit{
+			Kind:  token.STRING,
+			Value: fmt.Sprintf("%q", path),
+		},
+	}
+	impDecl := &ast.GenDecl{
+		Tok: token.IMPORT,
+		Specs: []ast.Spec{
+			newImport,
+		},
+	}
+	// Make the new import the first Decl in the file.
+	astFile := f.astFile
+	astFile.Decls = append(astFile.Decls, nil)
+	copy(astFile.Decls[1:], astFile.Decls[0:])
+	astFile.Decls[0] = impDecl
+	astFile.Imports = append(astFile.Imports, newImport)
+
+	// Now refer to the package, just in case it ends up unused.
+	// That is, append to the end of the file the declaration
+	//	var _ = _cover_atomic_.AddUint32
+	reference := &ast.GenDecl{
+		Tok: token.VAR,
+		Specs: []ast.Spec{
+			&ast.ValueSpec{
+				Names: []*ast.Ident{
+					ast.NewIdent("_"),
+				},
+				Values: []ast.Expr{
+					&ast.SelectorExpr{
+						X:   ast.NewIdent(atomicPackageName),
+						Sel: ast.NewIdent("AddUint32"),
+					},
+				},
+			},
+		},
+	}
+	astFile.Decls = append(astFile.Decls, reference)
+	return atomicPackageName
+}
+
+var slashslash = []byte("//")
+
+// initialComments returns the prefix of content containing only
+// whitespace and line comments.  Any +build directives must appear
+// within this region.  This approach is more reliable than using
+// go/printer to print a modified AST containing comments.
+//
+func initialComments(content []byte) []byte {
+	// Derived from go/build.Context.shouldBuild.
+	end := 0
+	p := content
+	for len(p) > 0 {
+		line := p
+		if i := bytes.IndexByte(line, '\n'); i >= 0 {
+			line, p = line[:i], p[i+1:]
+		} else {
+			p = p[len(p):]
+		}
+		line = bytes.TrimSpace(line)
+		if len(line) == 0 { // Blank line.
+			end = len(content) - len(p)
+			continue
+		}
+		if !bytes.HasPrefix(line, slashslash) { // Not comment line.
+			break
+		}
+	}
+	return content[:end]
+}
+
+func annotate(name string) {
+	fset := token.NewFileSet()
+	content, err := ioutil.ReadFile(name)
+	if err != nil {
+		log.Fatalf("cover: %s: %s", name, err)
+	}
+	parsedFile, err := parser.ParseFile(fset, name, content, 0)
+	if err != nil {
+		log.Fatalf("cover: %s: %s", name, err)
+	}
+
+	file := &File{
+		fset:    fset,
+		name:    name,
+		astFile: parsedFile,
+	}
+	if *mode == "atomic" {
+		file.atomicPkg = file.addImport(atomicPackagePath)
+	}
+	ast.Walk(file, file.astFile)
+	fd := os.Stdout
+	if *output != "" {
+		var err error
+		fd, err = os.Create(*output)
+		if err != nil {
+			log.Fatalf("cover: %s", err)
+		}
+	}
+	fd.Write(initialComments(content)) // Retain '// +build' directives.
+	file.print(fd)
+	// After printing the source tree, add some declarations for the counters etc.
+	// We could do this by adding to the tree, but it's easier just to print the text.
+	file.addVariables(fd)
+}
+
+func (f *File) print(w io.Writer) {
+	printer.Fprint(w, f.fset, f.astFile)
+}
+
+// intLiteral returns an ast.BasicLit representing the integer value.
+func (f *File) intLiteral(i int) *ast.BasicLit {
+	node := &ast.BasicLit{
+		Kind:  token.INT,
+		Value: fmt.Sprint(i),
+	}
+	return node
+}
+
+// index returns an ast.BasicLit representing the number of counters present.
+func (f *File) index() *ast.BasicLit {
+	return f.intLiteral(len(f.blocks))
+}
+
+// setCounterStmt returns the expression: __count[23] = 1.
+func setCounterStmt(f *File, counter ast.Expr) ast.Stmt {
+	return &ast.AssignStmt{
+		Lhs: []ast.Expr{counter},
+		Tok: token.ASSIGN,
+		Rhs: []ast.Expr{f.intLiteral(1)},
+	}
+}
+
+// incCounterStmt returns the expression: __count[23]++.
+func incCounterStmt(f *File, counter ast.Expr) ast.Stmt {
+	return &ast.IncDecStmt{
+		X:   counter,
+		Tok: token.INC,
+	}
+}
+
+// atomicCounterStmt returns the expression: atomic.AddUint32(&__count[23], 1)
+func atomicCounterStmt(f *File, counter ast.Expr) ast.Stmt {
+	return &ast.ExprStmt{
+		X: &ast.CallExpr{
+			Fun: &ast.SelectorExpr{
+				X:   ast.NewIdent(f.atomicPkg),
+				Sel: ast.NewIdent("AddUint32"),
+			},
+			Args: []ast.Expr{&ast.UnaryExpr{
+				Op: token.AND,
+				X:  counter,
+			},
+				f.intLiteral(1),
+			},
+		},
+	}
+}
+
+// newCounter creates a new counter expression of the appropriate form.
+func (f *File) newCounter(start, end token.Pos, numStmt int) ast.Stmt {
+	counter := &ast.IndexExpr{
+		X: &ast.SelectorExpr{
+			X:   ast.NewIdent(*varVar),
+			Sel: ast.NewIdent("Count"),
+		},
+		Index: f.index(),
+	}
+	stmt := counterStmt(f, counter)
+	f.blocks = append(f.blocks, Block{start, end, numStmt})
+	return stmt
+}
+
+// addCounters takes a list of statements and adds counters to the beginning of
+// each basic block at the top level of that list. For instance, given
+//
+//	S1
+//	if cond {
+//		S2
+// 	}
+//	S3
+//
+// counters will be added before S1 and before S3. The block containing S2
+// will be visited in a separate call.
+// TODO: Nested simple blocks get unnecessary (but correct) counters
+func (f *File) addCounters(pos, blockEnd token.Pos, list []ast.Stmt, extendToClosingBrace bool) []ast.Stmt {
+	// Special case: make sure we add a counter to an empty block. Can't do this below
+	// or we will add a counter to an empty statement list after, say, a return statement.
+	if len(list) == 0 {
+		return []ast.Stmt{f.newCounter(pos, blockEnd, 0)}
+	}
+	// We have a block (statement list), but it may have several basic blocks due to the
+	// appearance of statements that affect the flow of control.
+	var newList []ast.Stmt
+	for {
+		// Find first statement that affects flow of control (break, continue, if, etc.).
+		// It will be the last statement of this basic block.
+		var last int
+		end := blockEnd
+		for last = 0; last < len(list); last++ {
+			end = f.statementBoundary(list[last])
+			if f.endsBasicSourceBlock(list[last]) {
+				extendToClosingBrace = false // Block is broken up now.
+				last++
+				break
+			}
+		}
+		if extendToClosingBrace {
+			end = blockEnd
+		}
+		if pos != end { // Can have no source to cover if e.g. blocks abut.
+			newList = append(newList, f.newCounter(pos, end, last))
+		}
+		newList = append(newList, list[0:last]...)
+		list = list[last:]
+		if len(list) == 0 {
+			break
+		}
+		pos = list[0].Pos()
+	}
+	return newList
+}
+
+// hasFuncLiteral reports the existence and position of the first func literal
+// in the node, if any. If a func literal appears, it usually marks the termination
+// of a basic block because the function body is itself a block.
+// Therefore we draw a line at the start of the body of the first function literal we find.
+// TODO: what if there's more than one? Probably doesn't matter much.
+func hasFuncLiteral(n ast.Node) (bool, token.Pos) {
+	var literal funcLitFinder
+	ast.Walk(&literal, n)
+	return literal.found(), token.Pos(literal)
+}
+
+// statementBoundary finds the location in s that terminates the current basic
+// block in the source.
+func (f *File) statementBoundary(s ast.Stmt) token.Pos {
+	// Control flow statements are easy.
+	switch s := s.(type) {
+	case *ast.BlockStmt:
+		// Treat blocks like basic blocks to avoid overlapping counters.
+		return s.Lbrace
+	case *ast.IfStmt:
+		return s.Body.Lbrace
+	case *ast.ForStmt:
+		return s.Body.Lbrace
+	case *ast.LabeledStmt:
+		return f.statementBoundary(s.Stmt)
+	case *ast.RangeStmt:
+		// Ranges might loop over things with function literals.: for _ = range []func(){ ... } {.
+		// TODO: There are a few other such possibilities, but they're extremely unlikely.
+		found, pos := hasFuncLiteral(s.X)
+		if found {
+			return pos
+		}
+		return s.Body.Lbrace
+	case *ast.SwitchStmt:
+		return s.Body.Lbrace
+	case *ast.SelectStmt:
+		return s.Body.Lbrace
+	case *ast.TypeSwitchStmt:
+		return s.Body.Lbrace
+	}
+	// If not a control flow statement, it is a declaration, expression, call, etc. and it may have a function literal.
+	// If it does, that's tricky because we want to exclude the body of the function from this block.
+	// Draw a line at the start of the body of the first function literal we find.
+	// TODO: what if there's more than one? Probably doesn't matter much.
+	found, pos := hasFuncLiteral(s)
+	if found {
+		return pos
+	}
+	return s.End()
+}
+
+// endsBasicSourceBlock reports whether s changes the flow of control: break, if, etc.,
+// or if it's just problematic, for instance contains a function literal, which will complicate
+// accounting due to the block-within-an expression.
+func (f *File) endsBasicSourceBlock(s ast.Stmt) bool {
+	switch s := s.(type) {
+	case *ast.BlockStmt:
+		// Treat blocks like basic blocks to avoid overlapping counters.
+		return true
+	case *ast.BranchStmt:
+		return true
+	case *ast.ForStmt:
+		return true
+	case *ast.IfStmt:
+		return true
+	case *ast.LabeledStmt:
+		return f.endsBasicSourceBlock(s.Stmt)
+	case *ast.RangeStmt:
+		return true
+	case *ast.SwitchStmt:
+		return true
+	case *ast.SelectStmt:
+		return true
+	case *ast.TypeSwitchStmt:
+		return true
+	}
+	found, _ := hasFuncLiteral(s)
+	return found
+}
+
+// funcLitFinder implements the ast.Visitor pattern to find the location of any
+// function literal in a subtree.
+type funcLitFinder token.Pos
+
+func (f *funcLitFinder) Visit(node ast.Node) (w ast.Visitor) {
+	if f.found() {
+		return nil // Prune search.
+	}
+	switch n := node.(type) {
+	case *ast.FuncLit:
+		*f = funcLitFinder(n.Body.Lbrace)
+		return nil // Prune search.
+	}
+	return f
+}
+
+func (f *funcLitFinder) found() bool {
+	return token.Pos(*f) != token.NoPos
+}
+
+// Sort interface for []block1; used for self-check in addVariables.
+
+type block1 struct {
+	Block
+	index int
+}
+
+type blockSlice []block1
+
+func (b blockSlice) Len() int           { return len(b) }
+func (b blockSlice) Less(i, j int) bool { return b[i].startByte < b[j].startByte }
+func (b blockSlice) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
+
+// offset translates a token position into a 0-indexed byte offset.
+func (f *File) offset(pos token.Pos) int {
+	return f.fset.Position(pos).Offset
+}
+
+// addVariables adds to the end of the file the declarations to set up the counter and position variables.
+func (f *File) addVariables(w io.Writer) {
+	// Self-check: Verify that the instrumented basic blocks are disjoint.
+	t := make([]block1, len(f.blocks))
+	for i := range f.blocks {
+		t[i].Block = f.blocks[i]
+		t[i].index = i
+	}
+	sort.Sort(blockSlice(t))
+	for i := 1; i < len(t); i++ {
+		if t[i-1].endByte > t[i].startByte {
+			fmt.Fprintf(os.Stderr, "cover: internal error: block %d overlaps block %d\n", t[i-1].index, t[i].index)
+			// Note: error message is in byte positions, not token positions.
+			fmt.Fprintf(os.Stderr, "\t%s:#%d,#%d %s:#%d,#%d\n",
+				f.name, f.offset(t[i-1].startByte), f.offset(t[i-1].endByte),
+				f.name, f.offset(t[i].startByte), f.offset(t[i].endByte))
+		}
+	}
+
+	// Declare the coverage struct as a package-level variable.
+	fmt.Fprintf(w, "\nvar %s = struct {\n", *varVar)
+	fmt.Fprintf(w, "\tCount     [%d]uint32\n", len(f.blocks))
+	fmt.Fprintf(w, "\tPos       [3 * %d]uint32\n", len(f.blocks))
+	fmt.Fprintf(w, "\tNumStmt   [%d]uint16\n", len(f.blocks))
+	fmt.Fprintf(w, "} {\n")
+
+	// Initialize the position array field.
+	fmt.Fprintf(w, "\tPos: [3 * %d]uint32{\n", len(f.blocks))
+
+	// A nice long list of positions. Each position is encoded as follows to reduce size:
+	// - 32-bit starting line number
+	// - 32-bit ending line number
+	// - (16 bit ending column number << 16) | (16-bit starting column number).
+	for i, block := range f.blocks {
+		start := f.fset.Position(block.startByte)
+		end := f.fset.Position(block.endByte)
+		fmt.Fprintf(w, "\t\t%d, %d, %#x, // [%d]\n", start.Line, end.Line, (end.Column&0xFFFF)<<16|(start.Column&0xFFFF), i)
+	}
+
+	// Close the position array.
+	fmt.Fprintf(w, "\t},\n")
+
+	// Initialize the position array field.
+	fmt.Fprintf(w, "\tNumStmt: [%d]uint16{\n", len(f.blocks))
+
+	// A nice long list of statements-per-block, so we can give a conventional
+	// valuation of "percent covered". To save space, it's a 16-bit number, so we
+	// clamp it if it overflows - won't matter in practice.
+	for i, block := range f.blocks {
+		n := block.numStmt
+		if n > 1<<16-1 {
+			n = 1<<16 - 1
+		}
+		fmt.Fprintf(w, "\t\t%d, // %d\n", n, i)
+	}
+
+	// Close the statements-per-block array.
+	fmt.Fprintf(w, "\t},\n")
+
+	// Close the struct initialization.
+	fmt.Fprintf(w, "}\n")
+}
diff --git a/third_party/go.tools/cmd/cover/cover_test.go b/third_party/go.tools/cmd/cover/cover_test.go
new file mode 100644
index 0000000..82c1ce5
--- /dev/null
+++ b/third_party/go.tools/cmd/cover/cover_test.go
@@ -0,0 +1,87 @@
+// Copyright 2013 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_test
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"testing"
+)
+
+const (
+	// Data directory, also the package directory for the test.
+	testdata = "testdata"
+
+	// Binaries we compile.
+	testcover = "./testcover.exe"
+)
+
+var (
+	// Files we use.
+	testMain    = filepath.Join(testdata, "main.go")
+	testTest    = filepath.Join(testdata, "test.go")
+	coverInput  = filepath.Join(testdata, "test_line.go")
+	coverOutput = filepath.Join(testdata, "test_cover.go")
+)
+
+var debug = false // Keeps the rewritten files around if set.
+
+// Run this shell script, but do it in Go so it can be run by "go test".
+//
+//	replace the word LINE with the line number < testdata/test.go > testdata/test_line.go
+// 	go build -o ./testcover
+// 	./testcover -mode=count -var=CoverTest -o ./testdata/test_cover.go testdata/test_line.go
+//	go run ./testdata/main.go ./testdata/test.go
+//
+func TestCover(t *testing.T) {
+	// Read in the test file (testTest) and write it, with LINEs specified, to coverInput.
+	file, err := ioutil.ReadFile(testTest)
+	if err != nil {
+		t.Fatal(err)
+	}
+	lines := bytes.Split(file, []byte("\n"))
+	for i, line := range lines {
+		lines[i] = bytes.Replace(line, []byte("LINE"), []byte(fmt.Sprint(i+1)), -1)
+	}
+	err = ioutil.WriteFile(coverInput, bytes.Join(lines, []byte("\n")), 0666)
+
+	// defer removal of test_line.go
+	if !debug {
+		defer os.Remove(coverInput)
+	}
+
+	// go build -o testcover
+	cmd := exec.Command("go", "build", "-o", testcover)
+	run(cmd, t)
+
+	// defer removal of testcover
+	defer os.Remove(testcover)
+
+	// ./testcover -mode=count -var=coverTest -o ./testdata/test_cover.go testdata/test_line.go
+	cmd = exec.Command(testcover, "-mode=count", "-var=coverTest", "-o", coverOutput, coverInput)
+	run(cmd, t)
+
+	// defer removal of ./testdata/test_cover.go
+	if !debug {
+		defer os.Remove(coverOutput)
+	}
+
+	// go run ./testdata/main.go ./testdata/test.go
+	cmd = exec.Command("go", "run", testMain, coverOutput)
+	run(cmd, t)
+}
+
+func run(c *exec.Cmd, t *testing.T) {
+	c.Stdout = os.Stdout
+	c.Stderr = os.Stderr
+	err := c.Run()
+	if err != nil {
+		t.Fatal(err)
+	}
+}
diff --git a/third_party/go.tools/cmd/cover/doc.go b/third_party/go.tools/cmd/cover/doc.go
new file mode 100644
index 0000000..636d7e0
--- /dev/null
+++ b/third_party/go.tools/cmd/cover/doc.go
@@ -0,0 +1,21 @@
+// Copyright 2013 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.
+
+/*
+Cover is a program for analyzing the coverage profiles generated by
+'go test -coverprofile=cover.out'.
+
+Cover is also used by 'go test -cover' to rewrite the source code with
+annotations to track which parts of each function are executed.
+It operates on one Go source file at a time, computing approximate
+basic block information by studying the source. It is thus more portable
+than binary-rewriting coverage tools, but also a little less capable.
+For instance, it does not probe inside && and || expressions, and can
+be mildly confused by single statements with multiple function literals.
+
+For usage information, please see:
+	go help testflag
+	go tool cover -help
+*/
+package main
diff --git a/third_party/go.tools/cmd/cover/func.go b/third_party/go.tools/cmd/cover/func.go
new file mode 100644
index 0000000..3c2be7b
--- /dev/null
+++ b/third_party/go.tools/cmd/cover/func.go
@@ -0,0 +1,166 @@
+// Copyright 2013 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.
+
+// This file implements the visitor that computes the (line, column)-(line-column) range for each function.
+
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"text/tabwriter"
+
+	"llvm.org/llgo/third_party/go.tools/cover"
+)
+
+// funcOutput takes two file names as arguments, a coverage profile to read as input and an output
+// file to write ("" means to write to standard output). The function reads the profile and produces
+// as output the coverage data broken down by function, like this:
+//
+//	fmt/format.go:30:	init			100.0%
+//	fmt/format.go:57:	clearflags		100.0%
+//	...
+//	fmt/scan.go:1046:	doScan			100.0%
+//	fmt/scan.go:1075:	advance			96.2%
+//	fmt/scan.go:1119:	doScanf			96.8%
+//	total:		(statements)			91.9%
+
+func funcOutput(profile, outputFile string) error {
+	profiles, err := cover.ParseProfiles(profile)
+	if err != nil {
+		return err
+	}
+
+	var out *bufio.Writer
+	if outputFile == "" {
+		out = bufio.NewWriter(os.Stdout)
+	} else {
+		fd, err := os.Create(outputFile)
+		if err != nil {
+			return err
+		}
+		defer fd.Close()
+		out = bufio.NewWriter(fd)
+	}
+	defer out.Flush()
+
+	tabber := tabwriter.NewWriter(out, 1, 8, 1, '\t', 0)
+	defer tabber.Flush()
+
+	var total, covered int64
+	for _, profile := range profiles {
+		fn := profile.FileName
+		file, err := findFile(fn)
+		if err != nil {
+			return err
+		}
+		funcs, err := findFuncs(file)
+		if err != nil {
+			return err
+		}
+		// Now match up functions and profile blocks.
+		for _, f := range funcs {
+			c, t := f.coverage(profile)
+			fmt.Fprintf(tabber, "%s:%d:\t%s\t%.1f%%\n", fn, f.startLine, f.name, 100.0*float64(c)/float64(t))
+			total += t
+			covered += c
+		}
+	}
+	fmt.Fprintf(tabber, "total:\t(statements)\t%.1f%%\n", 100.0*float64(covered)/float64(total))
+
+	return nil
+}
+
+// findFuncs parses the file and returns a slice of FuncExtent descriptors.
+func findFuncs(name string) ([]*FuncExtent, error) {
+	fset := token.NewFileSet()
+	parsedFile, err := parser.ParseFile(fset, name, nil, 0)
+	if err != nil {
+		return nil, err
+	}
+	visitor := &FuncVisitor{
+		fset:    fset,
+		name:    name,
+		astFile: parsedFile,
+	}
+	ast.Walk(visitor, visitor.astFile)
+	return visitor.funcs, nil
+}
+
+// FuncExtent describes a function's extent in the source by file and position.
+type FuncExtent struct {
+	name      string
+	startLine int
+	startCol  int
+	endLine   int
+	endCol    int
+}
+
+// FuncVisitor implements the visitor that builds the function position list for a file.
+type FuncVisitor struct {
+	fset    *token.FileSet
+	name    string // Name of file.
+	astFile *ast.File
+	funcs   []*FuncExtent
+}
+
+// Visit implements the ast.Visitor interface.
+func (v *FuncVisitor) Visit(node ast.Node) ast.Visitor {
+	switch n := node.(type) {
+	case *ast.FuncDecl:
+		start := v.fset.Position(n.Pos())
+		end := v.fset.Position(n.End())
+		fe := &FuncExtent{
+			name:      n.Name.Name,
+			startLine: start.Line,
+			startCol:  start.Column,
+			endLine:   end.Line,
+			endCol:    end.Column,
+		}
+		v.funcs = append(v.funcs, fe)
+	}
+	return v
+}
+
+// coverage returns the fraction of the statements in the function that were covered, as a numerator and denominator.
+func (f *FuncExtent) coverage(profile *cover.Profile) (num, den int64) {
+	// We could avoid making this n^2 overall by doing a single scan and annotating the functions,
+	// but the sizes of the data structures is never very large and the scan is almost instantaneous.
+	var covered, total int64
+	// The blocks are sorted, so we can stop counting as soon as we reach the end of the relevant block.
+	for _, b := range profile.Blocks {
+		if b.StartLine > f.endLine || (b.StartLine == f.endLine && b.StartCol >= f.endCol) {
+			// Past the end of the function.
+			break
+		}
+		if b.EndLine < f.startLine || (b.EndLine == f.startLine && b.EndCol <= f.startCol) {
+			// Before the beginning of the function
+			continue
+		}
+		total += int64(b.NumStmt)
+		if b.Count > 0 {
+			covered += int64(b.NumStmt)
+		}
+	}
+	if total == 0 {
+		total = 1 // Avoid zero denominator.
+	}
+	return covered, total
+}
+
+// findFile finds the location of the named file in GOROOT, GOPATH etc.
+func findFile(file string) (string, error) {
+	dir, file := filepath.Split(file)
+	pkg, err := build.Import(dir, ".", build.FindOnly)
+	if err != nil {
+		return "", fmt.Errorf("can't find %q: %v", file, err)
+	}
+	return filepath.Join(pkg.Dir, file), nil
+}
diff --git a/third_party/go.tools/cmd/cover/html.go b/third_party/go.tools/cmd/cover/html.go
new file mode 100644
index 0000000..361308d
--- /dev/null
+++ b/third_party/go.tools/cmd/cover/html.go
@@ -0,0 +1,281 @@
+// Copyright 2013 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 (
+	"bufio"
+	"bytes"
+	"fmt"
+	"html/template"
+	"io"
+	"io/ioutil"
+	"math"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+
+	"llvm.org/llgo/third_party/go.tools/cover"
+)
+
+// htmlOutput reads the profile data from profile and generates an HTML
+// coverage report, writing it to outfile. If outfile is empty,
+// it writes the report to a temporary file and opens it in a web browser.
+func htmlOutput(profile, outfile string) error {
+	profiles, err := cover.ParseProfiles(profile)
+	if err != nil {
+		return err
+	}
+
+	var d templateData
+
+	for _, profile := range profiles {
+		fn := profile.FileName
+		if profile.Mode == "set" {
+			d.Set = true
+		}
+		file, err := findFile(fn)
+		if err != nil {
+			return err
+		}
+		src, err := ioutil.ReadFile(file)
+		if err != nil {
+			return fmt.Errorf("can't read %q: %v", fn, err)
+		}
+		var buf bytes.Buffer
+		err = htmlGen(&buf, src, profile.Boundaries(src))
+		if err != nil {
+			return err
+		}
+		d.Files = append(d.Files, &templateFile{
+			Name:     fn,
+			Body:     template.HTML(buf.String()),
+			Coverage: percentCovered(profile),
+		})
+	}
+
+	var out *os.File
+	if outfile == "" {
+		var dir string
+		dir, err = ioutil.TempDir("", "cover")
+		if err != nil {
+			return err
+		}
+		out, err = os.Create(filepath.Join(dir, "coverage.html"))
+	} else {
+		out, err = os.Create(outfile)
+	}
+	err = htmlTemplate.Execute(out, d)
+	if err == nil {
+		err = out.Close()
+	}
+	if err != nil {
+		return err
+	}
+
+	if outfile == "" {
+		if !startBrowser("file://" + out.Name()) {
+			fmt.Fprintf(os.Stderr, "HTML output written to %s\n", out.Name())
+		}
+	}
+
+	return nil
+}
+
+// percentCovered returns, as a percentage, the fraction of the statements in
+// the profile covered by the test run.
+// In effect, it reports the coverage of a given source file.
+func percentCovered(p *cover.Profile) float64 {
+	var total, covered int64
+	for _, b := range p.Blocks {
+		total += int64(b.NumStmt)
+		if b.Count > 0 {
+			covered += int64(b.NumStmt)
+		}
+	}
+	if total == 0 {
+		return 0
+	}
+	return float64(covered) / float64(total) * 100
+}
+
+// htmlGen generates an HTML coverage report with the provided filename,
+// source code, and tokens, and writes it to the given Writer.
+func htmlGen(w io.Writer, src []byte, boundaries []cover.Boundary) error {
+	dst := bufio.NewWriter(w)
+	for i := range src {
+		for len(boundaries) > 0 && boundaries[0].Offset == i {
+			b := boundaries[0]
+			if b.Start {
+				n := 0
+				if b.Count > 0 {
+					n = int(math.Floor(b.Norm*9)) + 1
+				}
+				fmt.Fprintf(dst, `<span class="cov%v" title="%v">`, n, b.Count)
+			} else {
+				dst.WriteString("</span>")
+			}
+			boundaries = boundaries[1:]
+		}
+		switch b := src[i]; b {
+		case '>':
+			dst.WriteString("&gt;")
+		case '<':
+			dst.WriteString("&lt;")
+		case '&':
+			dst.WriteString("&amp;")
+		case '\t':
+			dst.WriteString("        ")
+		default:
+			dst.WriteByte(b)
+		}
+	}
+	return dst.Flush()
+}
+
+// startBrowser tries to open the URL in a browser
+// and reports whether it succeeds.
+func startBrowser(url string) bool {
+	// try to start the browser
+	var args []string
+	switch runtime.GOOS {
+	case "darwin":
+		args = []string{"open"}
+	case "windows":
+		args = []string{"cmd", "/c", "start"}
+	default:
+		args = []string{"xdg-open"}
+	}
+	cmd := exec.Command(args[0], append(args[1:], url)...)
+	return cmd.Start() == nil
+}
+
+// rgb returns an rgb value for the specified coverage value
+// between 0 (no coverage) and 10 (max coverage).
+func rgb(n int) string {
+	if n == 0 {
+		return "rgb(192, 0, 0)" // Red
+	}
+	// Gradient from gray to green.
+	r := 128 - 12*(n-1)
+	g := 128 + 12*(n-1)
+	b := 128 + 3*(n-1)
+	return fmt.Sprintf("rgb(%v, %v, %v)", r, g, b)
+}
+
+// colors generates the CSS rules for coverage colors.
+func colors() template.CSS {
+	var buf bytes.Buffer
+	for i := 0; i < 11; i++ {
+		fmt.Fprintf(&buf, ".cov%v { color: %v }\n", i, rgb(i))
+	}
+	return template.CSS(buf.String())
+}
+
+var htmlTemplate = template.Must(template.New("html").Funcs(template.FuncMap{
+	"colors": colors,
+}).Parse(tmplHTML))
+
+type templateData struct {
+	Files []*templateFile
+	Set   bool
+}
+
+type templateFile struct {
+	Name     string
+	Body     template.HTML
+	Coverage float64
+}
+
+const tmplHTML = `
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<style>
+			body {
+				background: black;
+				color: rgb(80, 80, 80);
+			}
+			body, pre, #legend span {
+				font-family: Menlo, monospace;
+				font-weight: bold;
+			}
+			#topbar {
+				background: black;
+				position: fixed;
+				top: 0; left: 0; right: 0;
+				height: 42px;
+				border-bottom: 1px solid rgb(80, 80, 80);
+			}
+			#content {
+				margin-top: 50px;
+			}
+			#nav, #legend {
+				float: left;
+				margin-left: 10px;
+			}
+			#legend {
+				margin-top: 12px;
+			}
+			#nav {
+				margin-top: 10px;
+			}
+			#legend span {
+				margin: 0 5px;
+			}
+			{{colors}}
+		</style>
+	</head>
+	<body>
+		<div id="topbar">
+			<div id="nav">
+				<select id="files">
+				{{range $i, $f := .Files}}
+				<option value="file{{$i}}">{{$f.Name}} ({{printf "%.1f" $f.Coverage}}%)</option>
+				{{end}}
+				</select>
+			</div>
+			<div id="legend">
+				<span>not tracked</span>
+			{{if .Set}}
+				<span class="cov0">not covered</span>
+				<span class="cov8">covered</span>
+			{{else}}
+				<span class="cov0">no coverage</span>
+				<span class="cov1">low coverage</span>
+				<span class="cov2">*</span>
+				<span class="cov3">*</span>
+				<span class="cov4">*</span>
+				<span class="cov5">*</span>
+				<span class="cov6">*</span>
+				<span class="cov7">*</span>
+				<span class="cov8">*</span>
+				<span class="cov9">*</span>
+				<span class="cov10">high coverage</span>
+			{{end}}
+			</div>
+		</div>
+		<div id="content">
+		{{range $i, $f := .Files}}
+		<pre class="file" id="file{{$i}}" {{if $i}}style="display: none"{{end}}>{{$f.Body}}</pre>
+		{{end}}
+		</div>
+	</body>
+	<script>
+	(function() {
+		var files = document.getElementById('files');
+		var visible = document.getElementById('file0');
+		files.addEventListener('change', onChange, false);
+		function onChange() {
+			visible.style.display = 'none';
+			visible = document.getElementById(files.value);
+			visible.style.display = 'block';
+			window.scrollTo(0, 0);
+		}
+	})();
+	</script>
+</html>
+`
diff --git a/third_party/go.tools/cmd/cover/testdata/main.go b/third_party/go.tools/cmd/cover/testdata/main.go
new file mode 100644
index 0000000..c704b15
--- /dev/null
+++ b/third_party/go.tools/cmd/cover/testdata/main.go
@@ -0,0 +1,93 @@
+// Copyright 2013 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.
+
+// Test runner for coverage test. This file is not coverage-annotated; test.go is.
+// It knows the coverage counter is called "coverTest".
+
+package main
+
+import (
+	"fmt"
+	"os"
+)
+
+func main() {
+	testAll()
+	verify()
+}
+
+type block struct {
+	count uint32
+	line  uint32
+}
+
+var counters = make(map[block]bool)
+
+// check records the location and expected value for a counter.
+func check(line, count uint32) {
+	b := block{
+		count,
+		line,
+	}
+	counters[b] = true
+}
+
+// checkVal is a version of check that returns its extra argument,
+// so it can be used in conditionals.
+func checkVal(line, count uint32, val int) int {
+	b := block{
+		count,
+		line,
+	}
+	counters[b] = true
+	return val
+}
+
+var PASS = true
+
+// verify checks the expected counts against the actual. It runs after the test has completed.
+func verify() {
+	for b := range counters {
+		got, index := count(b.line)
+		if b.count == anything && got != 0 {
+			got = anything
+		}
+		if got != b.count {
+			fmt.Fprintf(os.Stderr, "test_go:%d expected count %d got %d [counter %d]\n", b.line, b.count, got, index)
+			PASS = false
+		}
+	}
+	if !PASS {
+		fmt.Fprintf(os.Stderr, "FAIL\n")
+		os.Exit(2)
+	}
+}
+
+// count returns the count and index for the counter at the specified line.
+func count(line uint32) (uint32, int) {
+	// Linear search is fine. Choose perfect fit over approximate.
+	// We can have a closing brace for a range on the same line as a condition for an "else if"
+	// and we don't want that brace to steal the count for the condition on the "if".
+	// Therefore we test for a perfect (lo==line && hi==line) match, but if we can't
+	// find that we take the first imperfect match.
+	index := -1
+	indexLo := uint32(1e9)
+	for i := range coverTest.Count {
+		lo, hi := coverTest.Pos[3*i], coverTest.Pos[3*i+1]
+		if lo == line && line == hi {
+			return coverTest.Count[i], i
+		}
+		// Choose the earliest match (the counters are in unpredictable order).
+		if lo <= line && line <= hi && indexLo > lo {
+			index = i
+			indexLo = lo
+		}
+	}
+	if index == -1 {
+		fmt.Fprintln(os.Stderr, "cover_test: no counter for line", line)
+		PASS = false
+		return 0, 0
+	}
+	return coverTest.Count[index], index
+}
diff --git a/third_party/go.tools/cmd/cover/testdata/test.go b/third_party/go.tools/cmd/cover/testdata/test.go
new file mode 100644
index 0000000..80b1f6b
--- /dev/null
+++ b/third_party/go.tools/cmd/cover/testdata/test.go
@@ -0,0 +1,177 @@
+// Copyright 2013 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.
+
+// This program is processed by the cover command, and then testAll is called.
+// The test driver in main.go can then compare the coverage statistics with expectation.
+
+// The word LINE is replaced by the line number in this file. When the file is executed,
+// the coverage processing has changed the line numbers, so we can't use runtime.Caller.
+
+package main
+
+const anything = 1e9 // Just some unlikely value that means "we got here, don't care how often"
+
+func testAll() {
+	testSimple()
+	testBlockRun()
+	testIf()
+	testFor()
+	testRange()
+	testSwitch()
+	testTypeSwitch()
+	testSelect1()
+	testSelect2()
+}
+
+func testSimple() {
+	check(LINE, 1)
+}
+
+func testIf() {
+	if true {
+		check(LINE, 1)
+	} else {
+		check(LINE, 0)
+	}
+	if false {
+		check(LINE, 0)
+	} else {
+		check(LINE, 1)
+	}
+	for i := 0; i < 3; i++ {
+		if checkVal(LINE, 3, i) <= 2 {
+			check(LINE, 3)
+		}
+		if checkVal(LINE, 3, i) <= 1 {
+			check(LINE, 2)
+		}
+		if checkVal(LINE, 3, i) <= 0 {
+			check(LINE, 1)
+		}
+	}
+	for i := 0; i < 3; i++ {
+		if checkVal(LINE, 3, i) <= 1 {
+			check(LINE, 2)
+		} else {
+			check(LINE, 1)
+		}
+	}
+	for i := 0; i < 3; i++ {
+		if checkVal(LINE, 3, i) <= 0 {
+			check(LINE, 1)
+		} else if checkVal(LINE, 2, i) <= 1 {
+			check(LINE, 1)
+		} else if checkVal(LINE, 1, i) <= 2 {
+			check(LINE, 1)
+		} else if checkVal(LINE, 0, i) <= 3 {
+			check(LINE, 0)
+		}
+	}
+}
+
+func testFor() {
+	for i := 0; i < 10; i++ {
+		check(LINE, 10)
+	}
+}
+
+func testRange() {
+	for _, f := range []func(){
+		func() { check(LINE, 1) },
+	} {
+		f()
+		check(LINE, 1)
+	}
+}
+
+func testBlockRun() {
+	check(LINE, 1)
+	{
+		check(LINE, 1)
+	}
+	{
+		check(LINE, 1)
+	}
+	check(LINE, 1)
+	{
+		check(LINE, 1)
+	}
+	{
+		check(LINE, 1)
+	}
+	check(LINE, 1)
+}
+
+func testSwitch() {
+	for i := 0; i < 5; i++ {
+		switch i {
+		case 0:
+			check(LINE, 1)
+		case 1:
+			check(LINE, 1)
+		case 2:
+			check(LINE, 1)
+		default:
+			check(LINE, 2)
+		}
+	}
+}
+
+func testTypeSwitch() {
+	var x = []interface{}{1, 2.0, "hi"}
+	for _, v := range x {
+		switch v.(type) {
+		case int:
+			check(LINE, 1)
+		case float64:
+			check(LINE, 1)
+		case string:
+			check(LINE, 1)
+		case complex128:
+			check(LINE, 0)
+		default:
+			check(LINE, 0)
+		}
+	}
+}
+
+func testSelect1() {
+	c := make(chan int)
+	go func() {
+		for i := 0; i < 1000; i++ {
+			c <- i
+		}
+	}()
+	for {
+		select {
+		case <-c:
+			check(LINE, anything)
+		case <-c:
+			check(LINE, anything)
+		default:
+			check(LINE, 1)
+			return
+		}
+	}
+}
+
+func testSelect2() {
+	c1 := make(chan int, 1000)
+	c2 := make(chan int, 1000)
+	for i := 0; i < 1000; i++ {
+		c1 <- i
+		c2 <- i
+	}
+	for {
+		select {
+		case <-c1:
+			check(LINE, 1000)
+		case <-c2:
+			check(LINE, 1000)
+		default:
+			check(LINE, 1)
+			return
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/digraph/digraph.go b/third_party/go.tools/cmd/digraph/digraph.go
new file mode 100644
index 0000000..89855a9
--- /dev/null
+++ b/third_party/go.tools/cmd/digraph/digraph.go
@@ -0,0 +1,540 @@
+// The digraph command performs queries over unlabelled directed graphs
+// represented in text form.  It is intended to integrate nicely with
+// typical UNIX command pipelines.
+//
+// Since directed graphs (import graphs, reference graphs, call graphs,
+// etc) often arise during software tool development and debugging, this
+// command is included in the go.tools repository.
+//
+// TODO(adonovan):
+// - support input files other than stdin
+// - suport alternative formats (AT&T GraphViz, CSV, etc),
+//   a comment syntax, etc.
+// - allow queries to nest, like Blaze query language.
+//
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"sort"
+	"strconv"
+	"unicode"
+	"unicode/utf8"
+)
+
+const Usage = `digraph: queries over directed graphs in text form.
+
+Graph format:
+
+  Each line contains zero or more words.  Words are separated by
+  unquoted whitespace; words may contain Go-style double-quoted portions,
+  allowing spaces and other characters to be expressed.
+
+  Each field declares a node, and if there are more than one,
+  an edge from the first to each subsequent one.
+  The graph is provided on the standard input.
+
+  For instance, the following (acyclic) graph specifies a partial order
+  among the subtasks of getting dressed:
+
+	% cat clothes.txt
+	socks shoes
+	"boxer shorts" pants
+	pants belt shoes
+	shirt tie sweater
+	sweater jacket
+	hat
+
+  The line "shirt tie sweater" indicates the two edges shirt -> tie and
+  shirt -> sweater, not shirt -> tie -> sweater.
+
+Supported queries:
+
+  nodes
+	the set of all nodes
+  degree
+	the in-degree and out-degree of each node.
+  preds <label> ...
+	the set of immediate predecessors of the specified nodes
+  succs <label> ...
+	the set of immediate successors of the specified nodes
+  forward <label> ...
+	the set of nodes transitively reachable from the specified nodes
+  reverse <label> ...
+	the set of nodes that transitively reach the specified nodes
+  somepath <label> <label>
+	the list of nodes on some arbitrary path from the first node to the second
+  allpaths <label> <label>
+	the set of nodes on all paths from the first node to the second
+  sccs
+	all strongly connected components (one per line)
+  scc <label>
+	the set of nodes nodes strongly connected to the specified one
+
+Example usage:
+
+   Show the transitive closure of imports of the digraph tool itself:
+   % go list -f '{{.ImportPath}}{{.Imports}}' ... | tr '[]' '  ' |
+         digraph forward golang.org/x/tools/cmd/digraph
+
+   Show which clothes (see above) must be donned before a jacket:
+   %  digraph reverse jacket <clothes.txt
+
+`
+
+func main() {
+	flag.Parse()
+
+	args := flag.Args()
+	if len(args) == 0 {
+		fmt.Println(Usage)
+		return
+	}
+
+	if err := digraph(args[0], args[1:]); err != nil {
+		fmt.Fprintf(os.Stderr, "digraph: %s\n", err)
+		os.Exit(1)
+	}
+}
+
+type nodelist []string
+
+func (l nodelist) println(sep string) {
+	for i, label := range l {
+		if i > 0 {
+			fmt.Fprint(stdout, sep)
+		}
+		fmt.Fprint(stdout, label)
+	}
+	fmt.Fprintln(stdout)
+}
+
+type nodeset map[string]bool
+
+func (s nodeset) sort() nodelist {
+	labels := make(nodelist, len(s))
+	var i int
+	for label := range s {
+		labels[i] = label
+		i++
+	}
+	sort.Strings(labels)
+	return labels
+}
+
+func (s nodeset) addAll(x nodeset) {
+	for label := range x {
+		s[label] = true
+	}
+}
+
+// A graph maps nodes to the non-nil set of their immediate successors.
+type graph map[string]nodeset
+
+func (g graph) addNode(label string) nodeset {
+	edges := g[label]
+	if edges == nil {
+		edges = make(nodeset)
+		g[label] = edges
+	}
+	return edges
+}
+
+func (g graph) addEdges(from string, to ...string) {
+	edges := g.addNode(from)
+	for _, to := range to {
+		g.addNode(to)
+		edges[to] = true
+	}
+}
+
+func (g graph) reachableFrom(roots nodeset) nodeset {
+	seen := make(nodeset)
+	var visit func(label string)
+	visit = func(label string) {
+		if !seen[label] {
+			seen[label] = true
+			for e := range g[label] {
+				visit(e)
+			}
+		}
+	}
+	for root := range roots {
+		visit(root)
+	}
+	return seen
+}
+
+func (g graph) transpose() graph {
+	rev := make(graph)
+	for label, edges := range g {
+		rev.addNode(label)
+		for succ := range edges {
+			rev.addEdges(succ, label)
+		}
+	}
+	return rev
+}
+
+func (g graph) sccs() []nodeset {
+	// Kosaraju's algorithm---Tarjan is overkill here.
+
+	// Forward pass.
+	S := make(nodelist, 0, len(g)) // postorder stack
+	seen := make(nodeset)
+	var visit func(label string)
+	visit = func(label string) {
+		if !seen[label] {
+			seen[label] = true
+			for e := range g[label] {
+				visit(e)
+			}
+			S = append(S, label)
+		}
+	}
+	for label := range g {
+		visit(label)
+	}
+
+	// Reverse pass.
+	rev := g.transpose()
+	var scc nodeset
+	seen = make(nodeset)
+	var rvisit func(label string)
+	rvisit = func(label string) {
+		if !seen[label] {
+			seen[label] = true
+			scc[label] = true
+			for e := range rev[label] {
+				rvisit(e)
+			}
+		}
+	}
+	var sccs []nodeset
+	for len(S) > 0 {
+		top := S[len(S)-1]
+		S = S[:len(S)-1] // pop
+		if !seen[top] {
+			scc = make(nodeset)
+			rvisit(top)
+			sccs = append(sccs, scc)
+		}
+	}
+	return sccs
+}
+
+func parse(rd io.Reader) (graph, error) {
+	g := make(graph)
+
+	var linenum int
+	in := bufio.NewScanner(rd)
+	for in.Scan() {
+		linenum++
+		// Split into words, honoring double-quotes per Go spec.
+		words, err := split(in.Text())
+		if err != nil {
+			return nil, fmt.Errorf("at line %d: %v", linenum, err)
+		}
+		if len(words) > 0 {
+			g.addEdges(words[0], words[1:]...)
+		}
+	}
+	if err := in.Err(); err != nil {
+		return nil, err
+	}
+	return g, nil
+}
+
+var stdin io.Reader = os.Stdin
+var stdout io.Writer = os.Stdout
+
+func digraph(cmd string, args []string) error {
+	// Parse the input graph.
+	g, err := parse(stdin)
+	if err != nil {
+		return err
+	}
+
+	// Parse the command line.
+	switch cmd {
+	case "nodes":
+		if len(args) != 0 {
+			return fmt.Errorf("usage: digraph nodes")
+		}
+		nodes := make(nodeset)
+		for label := range g {
+			nodes[label] = true
+		}
+		nodes.sort().println("\n")
+
+	case "degree":
+		if len(args) != 0 {
+			return fmt.Errorf("usage: digraph degree")
+		}
+		nodes := make(nodeset)
+		for label := range g {
+			nodes[label] = true
+		}
+		rev := g.transpose()
+		for _, label := range nodes.sort() {
+			fmt.Fprintf(stdout, "%d\t%d\t%s\n", len(rev[label]), len(g[label]), label)
+		}
+
+	case "succs", "preds":
+		if len(args) == 0 {
+			return fmt.Errorf("usage: digraph %s <label> ...", cmd)
+		}
+		g := g
+		if cmd == "preds" {
+			g = g.transpose()
+		}
+		result := make(nodeset)
+		for _, root := range args {
+			edges := g[root]
+			if edges == nil {
+				return fmt.Errorf("no such node %q", root)
+			}
+			result.addAll(edges)
+		}
+		result.sort().println("\n")
+
+	case "forward", "reverse":
+		if len(args) == 0 {
+			return fmt.Errorf("usage: digraph %s <label> ...", cmd)
+		}
+		roots := make(nodeset)
+		for _, root := range args {
+			if g[root] == nil {
+				return fmt.Errorf("no such node %q", root)
+			}
+			roots[root] = true
+		}
+		g := g
+		if cmd == "reverse" {
+			g = g.transpose()
+		}
+		g.reachableFrom(roots).sort().println("\n")
+
+	case "somepath":
+		if len(args) != 2 {
+			return fmt.Errorf("usage: digraph somepath <from> <to>")
+		}
+		from, to := args[0], args[1]
+		if g[from] == nil {
+			return fmt.Errorf("no such 'from' node %q", from)
+		}
+		if g[to] == nil {
+			return fmt.Errorf("no such 'to' node %q", to)
+		}
+
+		seen := make(nodeset)
+		var visit func(path nodelist, label string) bool
+		visit = func(path nodelist, label string) bool {
+			if !seen[label] {
+				seen[label] = true
+				if label == to {
+					append(path, label).println("\n")
+					return true // unwind
+				}
+				for e := range g[label] {
+					if visit(append(path, label), e) {
+						return true
+					}
+				}
+			}
+			return false
+		}
+		if !visit(make(nodelist, 0, 100), from) {
+			return fmt.Errorf("no path from %q to %q", args[0], args[1])
+		}
+
+	case "allpaths":
+		if len(args) != 2 {
+			return fmt.Errorf("usage: digraph allpaths <from> <to>")
+		}
+		from, to := args[0], args[1]
+		if g[from] == nil {
+			return fmt.Errorf("no such 'from' node %q", from)
+		}
+		if g[to] == nil {
+			return fmt.Errorf("no such 'to' node %q", to)
+		}
+
+		seen := make(nodeset) // value of seen[x] indicates whether x is on some path to 'to'
+		var visit func(label string) bool
+		visit = func(label string) bool {
+			reachesTo, ok := seen[label]
+			if !ok {
+				reachesTo = label == to
+
+				seen[label] = reachesTo
+				for e := range g[label] {
+					if visit(e) {
+						reachesTo = true
+					}
+				}
+				seen[label] = reachesTo
+			}
+			return reachesTo
+		}
+		if !visit(from) {
+			return fmt.Errorf("no path from %q to %q", from, to)
+		}
+		for label, reachesTo := range seen {
+			if !reachesTo {
+				delete(seen, label)
+			}
+		}
+		seen.sort().println("\n")
+
+	case "sccs":
+		if len(args) != 0 {
+			return fmt.Errorf("usage: digraph sccs")
+		}
+		for _, scc := range g.sccs() {
+			scc.sort().println(" ")
+		}
+
+	case "scc":
+		if len(args) != 1 {
+			return fmt.Errorf("usage: digraph scc <label>")
+		}
+		label := args[0]
+		if g[label] == nil {
+			return fmt.Errorf("no such node %q", label)
+		}
+		for _, scc := range g.sccs() {
+			if scc[label] {
+				scc.sort().println("\n")
+				break
+			}
+		}
+
+	default:
+		return fmt.Errorf("no such command %q", cmd)
+	}
+
+	return nil
+}
+
+// -- Utilities --------------------------------------------------------
+
+// split splits a line into words, which are generally separated by
+// spaces, but Go-style double-quoted string literals are also supported.
+// (This approximates the behaviour of the Bourne shell.)
+//
+//   `one "two three"` -> ["one" "two three"]
+//   `a"\n"b` -> ["a\nb"]
+//
+func split(line string) ([]string, error) {
+	var (
+		words   []string
+		inWord  bool
+		current bytes.Buffer
+	)
+
+	for len(line) > 0 {
+		r, size := utf8.DecodeRuneInString(line)
+		if unicode.IsSpace(r) {
+			if inWord {
+				words = append(words, current.String())
+				current.Reset()
+				inWord = false
+			}
+		} else if r == '"' {
+			var ok bool
+			size, ok = quotedLength(line)
+			if !ok {
+				return nil, errors.New("invalid quotation")
+			}
+			s, err := strconv.Unquote(line[:size])
+			if err != nil {
+				return nil, err
+			}
+			current.WriteString(s)
+			inWord = true
+		} else {
+			current.WriteRune(r)
+			inWord = true
+		}
+		line = line[size:]
+	}
+	if inWord {
+		words = append(words, current.String())
+	}
+	return words, nil
+}
+
+// quotedLength returns the length in bytes of the prefix of input that
+// contain a possibly-valid double-quoted Go string literal.
+//
+// On success, n is at least two (""); input[:n] may be passed to
+// strconv.Unquote to interpret its value, and input[n:] contains the
+// rest of the input.
+//
+// On failure, quotedLength returns false, and the entire input can be
+// passed to strconv.Unquote if an informative error message is desired.
+//
+// quotedLength does not and need not detect all errors, such as
+// invalid hex or octal escape sequences, since it assumes
+// strconv.Unquote will be applied to the prefix.  It guarantees only
+// that if there is a prefix of input containing a valid string literal,
+// its length is returned.
+//
+// TODO(adonovan): move this into a strconv-like utility package.
+//
+func quotedLength(input string) (n int, ok bool) {
+	var offset int
+
+	// next returns the rune at offset, or -1 on EOF.
+	// offset advances to just after that rune.
+	next := func() rune {
+		if offset < len(input) {
+			r, size := utf8.DecodeRuneInString(input[offset:])
+			offset += size
+			return r
+		}
+		return -1
+	}
+
+	if next() != '"' {
+		return // error: not a quotation
+	}
+
+	for {
+		r := next()
+		if r == '\n' || r < 0 {
+			return // error: string literal not terminated
+		}
+		if r == '"' {
+			return offset, true // success
+		}
+		if r == '\\' {
+			var skip int
+			switch next() {
+			case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"':
+				skip = 0
+			case '0', '1', '2', '3', '4', '5', '6', '7':
+				skip = 2
+			case 'x':
+				skip = 2
+			case 'u':
+				skip = 4
+			case 'U':
+				skip = 8
+			default:
+				return // error: invalid escape
+			}
+
+			for i := 0; i < skip; i++ {
+				next()
+			}
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/digraph/digraph_test.go b/third_party/go.tools/cmd/digraph/digraph_test.go
new file mode 100644
index 0000000..0c90304
--- /dev/null
+++ b/third_party/go.tools/cmd/digraph/digraph_test.go
@@ -0,0 +1,121 @@
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func TestDigraph(t *testing.T) {
+	const g1 = `
+socks shoes
+shorts pants
+pants belt shoes
+shirt tie sweater
+sweater jacket
+hat
+`
+
+	const g2 = `
+a b c
+b d
+c d
+d c
+`
+
+	for _, test := range []struct {
+		input string
+		cmd   string
+		args  []string
+		want  string
+	}{
+		{g1, "nodes", nil, "belt\nhat\njacket\npants\nshirt\nshoes\nshorts\nsocks\nsweater\ntie\n"},
+		{g1, "reverse", []string{"jacket"}, "jacket\nshirt\nsweater\n"},
+		{g1, "forward", []string{"socks"}, "shoes\nsocks\n"},
+		{g1, "forward", []string{"socks", "sweater"}, "jacket\nshoes\nsocks\nsweater\n"},
+
+		{g2, "allpaths", []string{"a", "d"}, "a\nb\nc\nd\n"},
+
+		{g2, "sccs", nil, "a\nb\nc d\n"},
+		{g2, "scc", []string{"d"}, "c\nd\n"},
+		{g2, "succs", []string{"a"}, "b\nc\n"},
+		{g2, "preds", []string{"c"}, "a\nd\n"},
+		{g2, "preds", []string{"c", "d"}, "a\nb\nc\nd\n"},
+	} {
+		stdin = strings.NewReader(test.input)
+		stdout = new(bytes.Buffer)
+		if err := digraph(test.cmd, test.args); err != nil {
+			t.Error(err)
+			continue
+		}
+
+		got := stdout.(fmt.Stringer).String()
+		if got != test.want {
+			t.Errorf("digraph(%s, %s) = %q, want %q", test.cmd, test.args, got, test.want)
+		}
+	}
+
+	// TODO(adonovan):
+	// - test somepath (it's nondeterministic).
+	// - test errors
+}
+
+func TestSplit(t *testing.T) {
+	for _, test := range []struct {
+		line string
+		want []string
+	}{
+		{`one "2a 2b" three`, []string{"one", "2a 2b", "three"}},
+		{`one tw"\n\x0a\u000a\012"o three`, []string{"one", "tw\n\n\n\no", "three"}},
+	} {
+		got, err := split(test.line)
+		if err != nil {
+			t.Errorf("split(%s) failed: %v", test.line, err)
+		}
+		if !reflect.DeepEqual(got, test.want) {
+			t.Errorf("split(%s) = %v, want %v", test.line, got, test.want)
+		}
+	}
+}
+
+func TestQuotedLength(t *testing.T) {
+	for _, test := range []struct {
+		input string
+		want  int
+	}{
+		{`"abc"`, 5},
+		{`"abc"def`, 5},
+		{`"abc\"d"ef`, 8}, // "abc\"d" is consumed, ef is residue
+		{`"\012\n\x0a\u000a\U0000000a"`, 28},
+		{"\"\xff\"", 3}, // bad UTF-8 is ok
+		{`"\xff"`, 6},   // hex escape for bad UTF-8 is ok
+	} {
+		got, ok := quotedLength(test.input)
+		if !ok {
+			got = 0
+		}
+		if got != test.want {
+			t.Errorf("quotedLength(%s) = %d, want %d", test.input, got, test.want)
+		}
+	}
+
+	// errors
+	for _, input := range []string{
+		``,            // not a quotation
+		`a`,           // not a quotation
+		`'a'`,         // not a quotation
+		`"a`,          // not terminated
+		`"\0"`,        // short octal escape
+		`"\x1"`,       // short hex escape
+		`"\u000"`,     // short \u escape
+		`"\U0000000"`, // short \U escape
+		`"\k"`,        // invalid escape
+		"\"ab\nc\"",   // newline
+	} {
+		if n, ok := quotedLength(input); ok {
+			t.Errorf("quotedLength(%s) = %d, want !ok", input, n)
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/eg/eg.go b/third_party/go.tools/cmd/eg/eg.go
new file mode 100644
index 0000000..81869d5
--- /dev/null
+++ b/third_party/go.tools/cmd/eg/eg.go
@@ -0,0 +1,142 @@
+// The eg command performs example-based refactoring.
+// For documentation, run the command, or see Help in
+// code.google.com/p/go.tools/refactor/eg.
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"os"
+	"os/exec"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/refactor/eg"
+)
+
+var (
+	beforeeditFlag = flag.String("beforeedit", "", "A command to exec before each file is edited (e.g. chmod, checkout).  Whitespace delimits argument words.  The string '{}' is replaced by the file name.")
+	helpFlag       = flag.Bool("help", false, "show detailed help message")
+	templateFlag   = flag.String("t", "", "template.go file specifying the refactoring")
+	transitiveFlag = flag.Bool("transitive", false, "apply refactoring to all dependencies too")
+	writeFlag      = flag.Bool("w", false, "rewrite input files in place (by default, the results are printed to standard output)")
+	verboseFlag    = flag.Bool("v", false, "show verbose matcher diagnostics")
+)
+
+const usage = `eg: an example-based refactoring tool.
+
+Usage: eg -t template.go [-w] [-transitive] <args>...
+-t template.go	specifies the template file (use -help to see explanation)
+-w          	causes files to be re-written in place.
+-transitive 	causes all dependencies to be refactored too.
+` + loader.FromArgsUsage
+
+func main() {
+	if err := doMain(); err != nil {
+		fmt.Fprintf(os.Stderr, "eg: %s\n", err)
+		os.Exit(1)
+	}
+}
+
+func doMain() error {
+	flag.Parse()
+	args := flag.Args()
+
+	if *helpFlag {
+		fmt.Fprint(os.Stderr, eg.Help)
+		os.Exit(2)
+	}
+
+	if *templateFlag == "" {
+		return fmt.Errorf("no -t template.go file specified")
+	}
+
+	conf := loader.Config{
+		Fset:          token.NewFileSet(),
+		ParserMode:    parser.ParseComments,
+		SourceImports: true,
+	}
+
+	// The first Created package is the template.
+	if err := conf.CreateFromFilenames("template", *templateFlag); err != nil {
+		return err //  e.g. "foo.go:1: syntax error"
+	}
+
+	if len(args) == 0 {
+		fmt.Fprint(os.Stderr, usage)
+		os.Exit(1)
+	}
+
+	if _, err := conf.FromArgs(args, true); err != nil {
+		return err
+	}
+
+	// Load, parse and type-check the whole program.
+	iprog, err := conf.Load()
+	if err != nil {
+		return err
+	}
+
+	// Analyze the template.
+	template := iprog.Created[0]
+	xform, err := eg.NewTransformer(iprog.Fset, template, *verboseFlag)
+	if err != nil {
+		return err
+	}
+
+	// Apply it to the input packages.
+	var pkgs []*loader.PackageInfo
+	if *transitiveFlag {
+		for _, info := range iprog.AllPackages {
+			pkgs = append(pkgs, info)
+		}
+	} else {
+		pkgs = iprog.InitialPackages()
+	}
+	var hadErrors bool
+	for _, pkg := range pkgs {
+		if pkg == template {
+			continue
+		}
+		for _, file := range pkg.Files {
+			n := xform.Transform(&pkg.Info, pkg.Pkg, file)
+			if n == 0 {
+				continue
+			}
+			filename := iprog.Fset.File(file.Pos()).Name()
+			fmt.Fprintf(os.Stderr, "=== %s (%d matches)\n", filename, n)
+			if *writeFlag {
+				// Run the before-edit command (e.g. "chmod +w",  "checkout") if any.
+				if *beforeeditFlag != "" {
+					args := strings.Fields(*beforeeditFlag)
+					// Replace "{}" with the filename, like find(1).
+					for i := range args {
+						if i > 0 {
+							args[i] = strings.Replace(args[i], "{}", filename, -1)
+						}
+					}
+					cmd := exec.Command(args[0], args[1:]...)
+					cmd.Stdout = os.Stdout
+					cmd.Stderr = os.Stderr
+					if err := cmd.Run(); err != nil {
+						fmt.Fprintf(os.Stderr, "Warning: edit hook %q failed (%s)\n",
+							args, err)
+					}
+				}
+				if err := eg.WriteAST(iprog.Fset, filename, file); err != nil {
+					fmt.Fprintf(os.Stderr, "eg: %s\n", err)
+					hadErrors = true
+				}
+			} else {
+				printer.Fprint(os.Stdout, iprog.Fset, file)
+			}
+		}
+	}
+	if hadErrors {
+		os.Exit(1)
+	}
+	return nil
+}
diff --git a/third_party/go.tools/cmd/godex/doc.go b/third_party/go.tools/cmd/godex/doc.go
new file mode 100644
index 0000000..90268e2
--- /dev/null
+++ b/third_party/go.tools/cmd/godex/doc.go
@@ -0,0 +1,69 @@
+// Copyright 2014 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.
+
+// The godex command prints (dumps) exported information of packages
+// or selected package objects.
+//
+// In contrast to godoc, godex extracts this information from compiled
+// object files. Hence the exported data is truly what a compiler will
+// see, at the cost of missing commentary.
+//
+// Usage: godex [flags] {path[.name]}
+//
+// Each argument must be a (possibly partial) package path, optionally
+// followed by a dot and the name of a package object:
+//
+//	godex math
+//	godex math.Sin
+//	godex math.Sin fmt.Printf
+//	godex go/types
+//
+// godex automatically tries all possible package path prefixes if only a
+// partial package path is given. For instance, for the path "go/types",
+// godex prepends "golang.org/x/tools".
+//
+// The prefixes are computed by searching the directories specified by
+// the GOROOT and GOPATH environment variables (and by excluding the
+// build OS- and architecture-specific directory names from the path).
+// The search order is depth-first and alphabetic; for a partial path
+// "foo", a package "a/foo" is found before "b/foo".
+//
+// Absolute and relative paths may be provided, which disable automatic
+// prefix generation:
+//
+//	godex $GOROOT/pkg/darwin_amd64/sort
+//	godex ./sort
+//
+// All but the last path element may contain dots; a dot in the last path
+// element separates the package path from the package object name. If the
+// last path element contains a dot, terminate the argument with another
+// dot (indicating an empty object name). For instance, the path for a
+// package foo.bar would be specified as in:
+//
+//	godex foo.bar.
+//
+// The flags are:
+//
+//	-s=""
+//		only consider packages from src, where src is one of the supported compilers
+//	-v=false
+//		verbose mode
+//
+// The following sources (-s arguments) are supported:
+//
+//	gc
+//		gc-generated object files
+//	gccgo
+//		gccgo-generated object files
+//	gccgo-new
+//		gccgo-generated object files using a condensed format (experimental)
+//	source
+//		(uncompiled) source code (not yet implemented)
+//
+// If no -s argument is provided, godex will try to find a matching source.
+//
+package main
+
+// BUG(gri): support for -s=source is not yet implemented
+// BUG(gri): gccgo-importing appears to have occasional problems stalling godex; try -s=gc as work-around
diff --git a/third_party/go.tools/cmd/godex/gc.go b/third_party/go.tools/cmd/godex/gc.go
new file mode 100644
index 0000000..2bffb8e
--- /dev/null
+++ b/third_party/go.tools/cmd/godex/gc.go
@@ -0,0 +1,15 @@
+// Copyright 2014 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.
+
+// This file implements access to gc-generated export data.
+
+package main
+
+import (
+	"llvm.org/llgo/third_party/go.tools/go/gcimporter"
+)
+
+func init() {
+	register("gc", gcimporter.Import)
+}
diff --git a/third_party/go.tools/cmd/godex/gccgo.go b/third_party/go.tools/cmd/godex/gccgo.go
new file mode 100644
index 0000000..49fd5a8
--- /dev/null
+++ b/third_party/go.tools/cmd/godex/gccgo.go
@@ -0,0 +1,40 @@
+// Copyright 2014 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.
+
+// This file implements access to gccgo-generated export data.
+
+package main
+
+import (
+	"llvm.org/llgo/third_party/go.tools/go/gccgoimporter"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var (
+	initmap = make(map[*types.Package]gccgoimporter.InitData)
+)
+
+func init() {
+	incpaths := []string{"/"}
+
+	// importer for default gccgo
+	var inst gccgoimporter.GccgoInstallation
+	inst.InitFromDriver("gccgo")
+	register("gccgo", inst.GetImporter(incpaths, initmap))
+}
+
+// Print the extra gccgo compiler data for this package, if it exists.
+func (p *printer) printGccgoExtra(pkg *types.Package) {
+	if initdata, ok := initmap[pkg]; ok {
+		p.printf("/*\npriority %d\n", initdata.Priority)
+
+		p.printDecl("init", len(initdata.Inits), func() {
+			for _, init := range initdata.Inits {
+				p.printf("%s %s %d\n", init.Name, init.InitFunc, init.Priority)
+			}
+		})
+
+		p.print("*/\n")
+	}
+}
diff --git a/third_party/go.tools/cmd/godex/godex.go b/third_party/go.tools/cmd/godex/godex.go
new file mode 100644
index 0000000..e35016c
--- /dev/null
+++ b/third_party/go.tools/cmd/godex/godex.go
@@ -0,0 +1,207 @@
+// Copyright 2014 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 (
+	"errors"
+	"flag"
+	"fmt"
+	"go/build"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var (
+	source  = flag.String("s", "", "only consider packages from src, where src is one of the supported compilers")
+	verbose = flag.Bool("v", false, "verbose mode")
+)
+
+// lists of registered sources and corresponding importers
+var (
+	sources      []string
+	importers    []types.Importer
+	importFailed = errors.New("import failed")
+)
+
+// map of imported packages
+var packages = make(map[string]*types.Package)
+
+func usage() {
+	fmt.Fprintln(os.Stderr, "usage: godex [flags] {path|qualifiedIdent}")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func report(msg string) {
+	fmt.Fprintln(os.Stderr, "error: "+msg)
+	os.Exit(2)
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+
+	if flag.NArg() == 0 {
+		report("no package name, path, or file provided")
+	}
+
+	imp := tryImports
+	if *source != "" {
+		imp = lookup(*source)
+		if imp == nil {
+			report("source (-s argument) must be one of: " + strings.Join(sources, ", "))
+		}
+	}
+
+	for _, arg := range flag.Args() {
+		path, name := splitPathIdent(arg)
+		logf("\tprocessing %q: path = %q, name = %s\n", arg, path, name)
+
+		// generate possible package path prefixes
+		// (at the moment we do this for each argument - should probably cache the generated prefixes)
+		prefixes := make(chan string)
+		go genPrefixes(prefixes, !filepath.IsAbs(path) && !build.IsLocalImport(path))
+
+		// import package
+		pkg, err := tryPrefixes(packages, prefixes, path, imp)
+		if err != nil {
+			logf("\t=> ignoring %q: %s\n", path, err)
+			continue
+		}
+
+		// filter objects if needed
+		var filter func(types.Object) bool
+		if name != "" {
+			filter = func(obj types.Object) bool {
+				// TODO(gri) perhaps use regular expression matching here?
+				return obj.Name() == name
+			}
+		}
+
+		// print contents
+		print(os.Stdout, pkg, filter)
+	}
+}
+
+func logf(format string, args ...interface{}) {
+	if *verbose {
+		fmt.Fprintf(os.Stderr, format, args...)
+	}
+}
+
+// splitPathIdent splits a path.name argument into its components.
+// All but the last path element may contain dots.
+func splitPathIdent(arg string) (path, name string) {
+	if i := strings.LastIndex(arg, "."); i >= 0 {
+		if j := strings.LastIndex(arg, "/"); j < i {
+			// '.' is not part of path
+			path = arg[:i]
+			name = arg[i+1:]
+			return
+		}
+	}
+	path = arg
+	return
+}
+
+// tryPrefixes tries to import the package given by (the possibly partial) path using the given importer imp
+// by prepending all possible prefixes to path. It returns with the first package that it could import, or
+// with an error.
+func tryPrefixes(packages map[string]*types.Package, prefixes chan string, path string, imp types.Importer) (pkg *types.Package, err error) {
+	for prefix := range prefixes {
+		actual := path
+		if prefix == "" {
+			// don't use filepath.Join as it will sanitize the path and remove
+			// a leading dot and then the path is not recognized as a relative
+			// package path by the importers anymore
+			logf("\ttrying no prefix\n")
+		} else {
+			actual = filepath.Join(prefix, path)
+			logf("\ttrying prefix %q\n", prefix)
+		}
+		pkg, err = imp(packages, actual)
+		if err == nil {
+			break
+		}
+		logf("\t=> importing %q failed: %s\n", actual, err)
+	}
+	return
+}
+
+// tryImports is an importer that tries all registered importers
+// successively until one of them succeeds or all of them failed.
+func tryImports(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
+	for i, imp := range importers {
+		logf("\t\ttrying %s import\n", sources[i])
+		pkg, err = imp(packages, path)
+		if err == nil {
+			break
+		}
+		logf("\t\t=> %s import failed: %s\n", sources[i], err)
+	}
+	return
+}
+
+// protect protects an importer imp from panics and returns the protected importer.
+func protect(imp types.Importer) types.Importer {
+	return func(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
+		defer func() {
+			if recover() != nil {
+				pkg = nil
+				err = importFailed
+			}
+		}()
+		return imp(packages, path)
+	}
+}
+
+// register registers an importer imp for a given source src.
+func register(src string, imp types.Importer) {
+	if lookup(src) != nil {
+		panic(src + " importer already registered")
+	}
+	sources = append(sources, src)
+	importers = append(importers, protect(imp))
+}
+
+// lookup returns the importer imp for a given source src.
+func lookup(src string) types.Importer {
+	for i, s := range sources {
+		if s == src {
+			return importers[i]
+		}
+	}
+	return nil
+}
+
+func genPrefixes(out chan string, all bool) {
+	out <- ""
+	if all {
+		platform := build.Default.GOOS + "_" + build.Default.GOARCH
+		dirnames := append([]string{build.Default.GOROOT}, filepath.SplitList(build.Default.GOPATH)...)
+		for _, dirname := range dirnames {
+			walkDir(filepath.Join(dirname, "pkg", platform), "", out)
+		}
+	}
+	close(out)
+}
+
+func walkDir(dirname, prefix string, out chan string) {
+	fiList, err := ioutil.ReadDir(dirname)
+	if err != nil {
+		return
+	}
+	for _, fi := range fiList {
+		if fi.IsDir() && !strings.HasPrefix(fi.Name(), ".") {
+			prefix := filepath.Join(prefix, fi.Name())
+			out <- prefix
+			walkDir(filepath.Join(dirname, fi.Name()), prefix, out)
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/godex/print.go b/third_party/go.tools/cmd/godex/print.go
new file mode 100644
index 0000000..33c44fc
--- /dev/null
+++ b/third_party/go.tools/cmd/godex/print.go
@@ -0,0 +1,368 @@
+// Copyright 2014 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 (
+	"bytes"
+	"fmt"
+	"go/token"
+	"io"
+	"math/big"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// TODO(gri) use tabwriter for alignment?
+
+func print(w io.Writer, pkg *types.Package, filter func(types.Object) bool) {
+	var p printer
+	p.pkg = pkg
+	p.printPackage(pkg, filter)
+	p.printGccgoExtra(pkg)
+	io.Copy(w, &p.buf)
+}
+
+type printer struct {
+	pkg    *types.Package
+	buf    bytes.Buffer
+	indent int  // current indentation level
+	last   byte // last byte written
+}
+
+func (p *printer) print(s string) {
+	// Write the string one byte at a time. We care about the presence of
+	// newlines for indentation which we will see even in the presence of
+	// (non-corrupted) Unicode; no need to read one rune at a time.
+	for i := 0; i < len(s); i++ {
+		ch := s[i]
+		if ch != '\n' && p.last == '\n' {
+			// Note: This could lead to a range overflow for very large
+			// indentations, but it's extremely unlikely to happen for
+			// non-pathological code.
+			p.buf.WriteString("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"[:p.indent])
+		}
+		p.buf.WriteByte(ch)
+		p.last = ch
+	}
+}
+
+func (p *printer) printf(format string, args ...interface{}) {
+	p.print(fmt.Sprintf(format, args...))
+}
+
+// methodsFor returns the named type and corresponding methods if the type
+// denoted by obj is not an interface and has methods. Otherwise it returns
+// the zero value.
+func methodsFor(obj *types.TypeName) (*types.Named, []*types.Selection) {
+	named, _ := obj.Type().(*types.Named)
+	if named == nil {
+		// A type name's type can also be the
+		// exported basic type unsafe.Pointer.
+		return nil, nil
+	}
+	if _, ok := named.Underlying().(*types.Interface); ok {
+		// ignore interfaces
+		return nil, nil
+	}
+	methods := combinedMethodSet(named)
+	if len(methods) == 0 {
+		return nil, nil
+	}
+	return named, methods
+}
+
+func (p *printer) printPackage(pkg *types.Package, filter func(types.Object) bool) {
+	// collect objects by kind
+	var (
+		consts   []*types.Const
+		typem    []*types.Named    // non-interface types with methods
+		typez    []*types.TypeName // interfaces or types without methods
+		vars     []*types.Var
+		funcs    []*types.Func
+		builtins []*types.Builtin
+		methods  = make(map[*types.Named][]*types.Selection) // method sets for named types
+	)
+	scope := pkg.Scope()
+	for _, name := range scope.Names() {
+		obj := scope.Lookup(name)
+		if obj.Exported() {
+			// collect top-level exported and possibly filtered objects
+			if filter == nil || filter(obj) {
+				switch obj := obj.(type) {
+				case *types.Const:
+					consts = append(consts, obj)
+				case *types.TypeName:
+					// group into types with methods and types without
+					if named, m := methodsFor(obj); named != nil {
+						typem = append(typem, named)
+						methods[named] = m
+					} else {
+						typez = append(typez, obj)
+					}
+				case *types.Var:
+					vars = append(vars, obj)
+				case *types.Func:
+					funcs = append(funcs, obj)
+				case *types.Builtin:
+					// for unsafe.Sizeof, etc.
+					builtins = append(builtins, obj)
+				}
+			}
+		} else if filter == nil {
+			// no filtering: collect top-level unexported types with methods
+			if obj, _ := obj.(*types.TypeName); obj != nil {
+				// see case *types.TypeName above
+				if named, m := methodsFor(obj); named != nil {
+					typem = append(typem, named)
+					methods[named] = m
+				}
+			}
+		}
+	}
+
+	p.printf("package %s  // %q\n", pkg.Name(), pkg.Path())
+
+	p.printDecl("const", len(consts), func() {
+		for _, obj := range consts {
+			p.printObj(obj)
+			p.print("\n")
+		}
+	})
+
+	p.printDecl("var", len(vars), func() {
+		for _, obj := range vars {
+			p.printObj(obj)
+			p.print("\n")
+		}
+	})
+
+	p.printDecl("type", len(typez), func() {
+		for _, obj := range typez {
+			p.printf("%s ", obj.Name())
+			p.writeType(p.pkg, obj.Type().Underlying())
+			p.print("\n")
+		}
+	})
+
+	// non-interface types with methods
+	for _, named := range typem {
+		first := true
+		if obj := named.Obj(); obj.Exported() {
+			if first {
+				p.print("\n")
+				first = false
+			}
+			p.printf("type %s ", obj.Name())
+			p.writeType(p.pkg, named.Underlying())
+			p.print("\n")
+		}
+		for _, m := range methods[named] {
+			if obj := m.Obj(); obj.Exported() {
+				if first {
+					p.print("\n")
+					first = false
+				}
+				p.printFunc(m.Recv(), obj.(*types.Func))
+				p.print("\n")
+			}
+		}
+	}
+
+	if len(funcs) > 0 {
+		p.print("\n")
+		for _, obj := range funcs {
+			p.printFunc(nil, obj)
+			p.print("\n")
+		}
+	}
+
+	// TODO(gri) better handling of builtins (package unsafe only)
+	if len(builtins) > 0 {
+		p.print("\n")
+		for _, obj := range builtins {
+			p.printf("func %s() // builtin\n", obj.Name())
+		}
+	}
+
+	p.print("\n")
+}
+
+func (p *printer) printDecl(keyword string, n int, printGroup func()) {
+	switch n {
+	case 0:
+		// nothing to do
+	case 1:
+		p.printf("\n%s ", keyword)
+		printGroup()
+	default:
+		p.printf("\n%s (\n", keyword)
+		p.indent++
+		printGroup()
+		p.indent--
+		p.print(")\n")
+	}
+}
+
+// absInt returns the absolute value of v as a *big.Int.
+// v must be a numeric value.
+func absInt(v exact.Value) *big.Int {
+	// compute big-endian representation of v
+	b := exact.Bytes(v) // little-endian
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+	return new(big.Int).SetBytes(b)
+}
+
+var (
+	one = big.NewRat(1, 1)
+	ten = big.NewRat(10, 1)
+)
+
+// floatString returns the string representation for a
+// numeric value v in normalized floating-point format.
+func floatString(v exact.Value) string {
+	if exact.Sign(v) == 0 {
+		return "0.0"
+	}
+	// x != 0
+
+	// convert |v| into a big.Rat x
+	x := new(big.Rat).SetFrac(absInt(exact.Num(v)), absInt(exact.Denom(v)))
+
+	// normalize x and determine exponent e
+	// (This is not very efficient, but also not speed-critical.)
+	var e int
+	for x.Cmp(ten) >= 0 {
+		x.Quo(x, ten)
+		e++
+	}
+	for x.Cmp(one) < 0 {
+		x.Mul(x, ten)
+		e--
+	}
+
+	// TODO(gri) Values such as 1/2 are easier to read in form 0.5
+	// rather than 5.0e-1. Similarly, 1.0e1 is easier to read as
+	// 10.0. Fine-tune best exponent range for readability.
+
+	s := x.FloatString(100) // good-enough precision
+
+	// trim trailing 0's
+	i := len(s)
+	for i > 0 && s[i-1] == '0' {
+		i--
+	}
+	s = s[:i]
+
+	// add a 0 if the number ends in decimal point
+	if len(s) > 0 && s[len(s)-1] == '.' {
+		s += "0"
+	}
+
+	// add exponent and sign
+	if e != 0 {
+		s += fmt.Sprintf("e%+d", e)
+	}
+	if exact.Sign(v) < 0 {
+		s = "-" + s
+	}
+
+	// TODO(gri) If v is a "small" fraction (i.e., numerator and denominator
+	// are just a small number of decimal digits), add the exact fraction as
+	// a comment. For instance: 3.3333...e-1 /* = 1/3 */
+
+	return s
+}
+
+// valString returns the string representation for the value v.
+// Setting floatFmt forces an integer value to be formatted in
+// normalized floating-point format.
+// TODO(gri) Move this code into package exact.
+func valString(v exact.Value, floatFmt bool) string {
+	switch v.Kind() {
+	case exact.Int:
+		if floatFmt {
+			return floatString(v)
+		}
+	case exact.Float:
+		return floatString(v)
+	case exact.Complex:
+		re := exact.Real(v)
+		im := exact.Imag(v)
+		var s string
+		if exact.Sign(re) != 0 {
+			s = floatString(re)
+			if exact.Sign(im) >= 0 {
+				s += " + "
+			} else {
+				s += " - "
+				im = exact.UnaryOp(token.SUB, im, 0) // negate im
+			}
+		}
+		// im != 0, otherwise v would be exact.Int or exact.Float
+		return s + floatString(im) + "i"
+	}
+	return v.String()
+}
+
+func (p *printer) printObj(obj types.Object) {
+	p.print(obj.Name())
+
+	typ, basic := obj.Type().Underlying().(*types.Basic)
+	if basic && typ.Info()&types.IsUntyped != 0 {
+		// don't write untyped types
+	} else {
+		p.print(" ")
+		p.writeType(p.pkg, obj.Type())
+	}
+
+	if obj, ok := obj.(*types.Const); ok {
+		floatFmt := basic && typ.Info()&(types.IsFloat|types.IsComplex) != 0
+		p.print(" = ")
+		p.print(valString(obj.Val(), floatFmt))
+	}
+}
+
+func (p *printer) printFunc(recvType types.Type, obj *types.Func) {
+	p.print("func ")
+	sig := obj.Type().(*types.Signature)
+	if recvType != nil {
+		p.print("(")
+		p.writeType(p.pkg, recvType)
+		p.print(") ")
+	}
+	p.print(obj.Name())
+	p.writeSignature(p.pkg, sig)
+}
+
+// combinedMethodSet returns the method set for a named type T
+// merged with all the methods of *T that have different names than
+// the methods of T.
+//
+// combinedMethodSet is analogous to types/typeutil.IntuitiveMethodSet
+// but doesn't require a MethodSetCache.
+// TODO(gri) If this functionality doesn't change over time, consider
+// just calling IntuitiveMethodSet eventually.
+func combinedMethodSet(T *types.Named) []*types.Selection {
+	// method set for T
+	mset := types.NewMethodSet(T)
+	var res []*types.Selection
+	for i, n := 0, mset.Len(); i < n; i++ {
+		res = append(res, mset.At(i))
+	}
+
+	// add all *T methods with names different from T methods
+	pmset := types.NewMethodSet(types.NewPointer(T))
+	for i, n := 0, pmset.Len(); i < n; i++ {
+		pm := pmset.At(i)
+		if obj := pm.Obj(); mset.Lookup(obj.Pkg(), obj.Name()) == nil {
+			res = append(res, pm)
+		}
+	}
+
+	return res
+}
diff --git a/third_party/go.tools/cmd/godex/source.go b/third_party/go.tools/cmd/godex/source.go
new file mode 100644
index 0000000..bd5d4c6
--- /dev/null
+++ b/third_party/go.tools/cmd/godex/source.go
@@ -0,0 +1,19 @@
+// Copyright 2014 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.
+
+// This file implements access to export data from source.
+
+package main
+
+import (
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func init() {
+	register("source", sourceImporter)
+}
+
+func sourceImporter(packages map[string]*types.Package, path string) (*types.Package, error) {
+	panic("unimplemented")
+}
diff --git a/third_party/go.tools/cmd/godex/writetype.go b/third_party/go.tools/cmd/godex/writetype.go
new file mode 100644
index 0000000..9c59729
--- /dev/null
+++ b/third_party/go.tools/cmd/godex/writetype.go
@@ -0,0 +1,242 @@
+// Copyright 2014 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.
+
+// This file implements writing of types. The functionality is lifted
+// directly from go/types, but now contains various modifications for
+// nicer output.
+//
+// TODO(gri) back-port once we have a fixed interface and once the
+// go/types API is not frozen anymore for the 1.3 release; and remove
+// this implementation if possible.
+
+package main
+
+import "llvm.org/llgo/third_party/go.tools/go/types"
+
+func (p *printer) writeType(this *types.Package, typ types.Type) {
+	p.writeTypeInternal(this, typ, make([]types.Type, 8))
+}
+
+// From go/types - leave for now to ease back-porting this code.
+const GcCompatibilityMode = false
+
+func (p *printer) writeTypeInternal(this *types.Package, typ types.Type, visited []types.Type) {
+	// Theoretically, this is a quadratic lookup algorithm, but in
+	// practice deeply nested composite types with unnamed component
+	// types are uncommon. This code is likely more efficient than
+	// using a map.
+	for _, t := range visited {
+		if t == typ {
+			p.printf("○%T", typ) // cycle to typ
+			return
+		}
+	}
+	visited = append(visited, typ)
+
+	switch t := typ.(type) {
+	case nil:
+		p.print("<nil>")
+
+	case *types.Basic:
+		if t.Kind() == types.UnsafePointer {
+			p.print("unsafe.")
+		}
+		if GcCompatibilityMode {
+			// forget the alias names
+			switch t.Kind() {
+			case types.Byte:
+				t = types.Typ[types.Uint8]
+			case types.Rune:
+				t = types.Typ[types.Int32]
+			}
+		}
+		p.print(t.Name())
+
+	case *types.Array:
+		p.printf("[%d]", t.Len())
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Slice:
+		p.print("[]")
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Struct:
+		n := t.NumFields()
+		if n == 0 {
+			p.print("struct{}")
+			return
+		}
+
+		p.print("struct {\n")
+		p.indent++
+		for i := 0; i < n; i++ {
+			f := t.Field(i)
+			if !f.Anonymous() {
+				p.printf("%s ", f.Name())
+			}
+			p.writeTypeInternal(this, f.Type(), visited)
+			if tag := t.Tag(i); tag != "" {
+				p.printf(" %q", tag)
+			}
+			p.print("\n")
+		}
+		p.indent--
+		p.print("}")
+
+	case *types.Pointer:
+		p.print("*")
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Tuple:
+		p.writeTuple(this, t, false, visited)
+
+	case *types.Signature:
+		p.print("func")
+		p.writeSignatureInternal(this, t, visited)
+
+	case *types.Interface:
+		// We write the source-level methods and embedded types rather
+		// than the actual method set since resolved method signatures
+		// may have non-printable cycles if parameters have anonymous
+		// interface types that (directly or indirectly) embed the
+		// current interface. For instance, consider the result type
+		// of m:
+		//
+		//     type T interface{
+		//         m() interface{ T }
+		//     }
+		//
+		n := t.NumMethods()
+		if n == 0 {
+			p.print("interface{}")
+			return
+		}
+
+		p.print("interface {\n")
+		p.indent++
+		if GcCompatibilityMode {
+			// print flattened interface
+			// (useful to compare against gc-generated interfaces)
+			for i := 0; i < n; i++ {
+				m := t.Method(i)
+				p.print(m.Name())
+				p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
+				p.print("\n")
+			}
+		} else {
+			// print explicit interface methods and embedded types
+			for i, n := 0, t.NumExplicitMethods(); i < n; i++ {
+				m := t.ExplicitMethod(i)
+				p.print(m.Name())
+				p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
+				p.print("\n")
+			}
+			for i, n := 0, t.NumEmbeddeds(); i < n; i++ {
+				typ := t.Embedded(i)
+				p.writeTypeInternal(this, typ, visited)
+				p.print("\n")
+			}
+		}
+		p.indent--
+		p.print("}")
+
+	case *types.Map:
+		p.print("map[")
+		p.writeTypeInternal(this, t.Key(), visited)
+		p.print("]")
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Chan:
+		var s string
+		var parens bool
+		switch t.Dir() {
+		case types.SendRecv:
+			s = "chan "
+			// chan (<-chan T) requires parentheses
+			if c, _ := t.Elem().(*types.Chan); c != nil && c.Dir() == types.RecvOnly {
+				parens = true
+			}
+		case types.SendOnly:
+			s = "chan<- "
+		case types.RecvOnly:
+			s = "<-chan "
+		default:
+			panic("unreachable")
+		}
+		p.print(s)
+		if parens {
+			p.print("(")
+		}
+		p.writeTypeInternal(this, t.Elem(), visited)
+		if parens {
+			p.print(")")
+		}
+
+	case *types.Named:
+		s := "<Named w/o object>"
+		if obj := t.Obj(); obj != nil {
+			if pkg := obj.Pkg(); pkg != nil {
+				if pkg != this {
+					p.print(pkg.Path())
+					p.print(".")
+				}
+				// TODO(gri): function-local named types should be displayed
+				// differently from named types at package level to avoid
+				// ambiguity.
+			}
+			s = obj.Name()
+		}
+		p.print(s)
+
+	default:
+		// For externally defined implementations of Type.
+		p.print(t.String())
+	}
+}
+
+func (p *printer) writeTuple(this *types.Package, tup *types.Tuple, variadic bool, visited []types.Type) {
+	p.print("(")
+	for i, n := 0, tup.Len(); i < n; i++ {
+		if i > 0 {
+			p.print(", ")
+		}
+		v := tup.At(i)
+		if name := v.Name(); name != "" {
+			p.print(name)
+			p.print(" ")
+		}
+		typ := v.Type()
+		if variadic && i == n-1 {
+			p.print("...")
+			typ = typ.(*types.Slice).Elem()
+		}
+		p.writeTypeInternal(this, typ, visited)
+	}
+	p.print(")")
+}
+
+func (p *printer) writeSignature(this *types.Package, sig *types.Signature) {
+	p.writeSignatureInternal(this, sig, make([]types.Type, 8))
+}
+
+func (p *printer) writeSignatureInternal(this *types.Package, sig *types.Signature, visited []types.Type) {
+	p.writeTuple(this, sig.Params(), sig.Variadic(), visited)
+
+	res := sig.Results()
+	n := res.Len()
+	if n == 0 {
+		// no result
+		return
+	}
+
+	p.print(" ")
+	if n == 1 && res.At(0).Name() == "" {
+		// single unnamed result
+		p.writeTypeInternal(this, res.At(0).Type(), visited)
+		return
+	}
+
+	// multiple or named result(s)
+	p.writeTuple(this, res, false, visited)
+}
diff --git a/third_party/go.tools/cmd/godoc/README.godoc-app b/third_party/go.tools/cmd/godoc/README.godoc-app
new file mode 100644
index 0000000..50a0516
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/README.godoc-app
@@ -0,0 +1,56 @@
+godoc on appengine
+------------------
+
+Prerequisites
+-------------
+
+* Go appengine SDK
+  https://developers.google.com/appengine/downloads#Google_App_Engine_SDK_for_Go
+
+* Go sources at tip under $GOROOT
+
+* Godoc sources at tip inside $GOPATH
+  (go get -d golang.org/x/tools/cmd/godoc)
+
+
+Directory structure
+-------------------
+
+* Let $APPDIR be the directory containing the app engine files.
+  (e.g., $APPDIR=$HOME/godoc-app)
+
+* $APPDIR contains the following entries (this may change depending on
+  app-engine release and version of godoc):
+
+	app.yaml
+	golang.org/x/tools/cmd/godoc
+	godoc.zip
+	index.split.*
+
+* The app.yaml file is set up per app engine documentation.
+  For instance:
+
+	application: godoc-app
+	version: 1
+	runtime: go
+	api_version: go1
+
+	handlers:
+	- url: /.*
+	  script: _go_app
+
+
+Configuring and running godoc
+-----------------------------
+
+To configure godoc, run
+
+	bash setup-godoc-app.bash
+
+to prepare an $APPDIR as described above. See the script for details on usage.
+
+To run godoc locally, using the App Engine development server, run
+
+	<path to go_appengine>/dev_appserver.py $APPDIR
+
+godoc should come up at http://localhost:8080 .
diff --git a/third_party/go.tools/cmd/godoc/appinit.go b/third_party/go.tools/cmd/godoc/appinit.go
new file mode 100644
index 0000000..989c79e
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/appinit.go
@@ -0,0 +1,64 @@
+// 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.
+
+// +build appengine
+
+package main
+
+// This file replaces main.go when running godoc under app-engine.
+// See README.godoc-app for details.
+
+import (
+	"archive/zip"
+	"log"
+	"path"
+
+	"llvm.org/llgo/third_party/go.tools/godoc"
+	"llvm.org/llgo/third_party/go.tools/godoc/static"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs/mapfs"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs/zipfs"
+)
+
+func init() {
+	playEnabled = true
+
+	log.Println("initializing godoc ...")
+	log.Printf(".zip file   = %s", zipFilename)
+	log.Printf(".zip GOROOT = %s", zipGoroot)
+	log.Printf("index files = %s", indexFilenames)
+
+	goroot := path.Join("/", zipGoroot) // fsHttp paths are relative to '/'
+
+	// read .zip file and set up file systems
+	const zipfile = zipFilename
+	rc, err := zip.OpenReader(zipfile)
+	if err != nil {
+		log.Fatalf("%s: %s\n", zipfile, err)
+	}
+	// rc is never closed (app running forever)
+	fs.Bind("/", zipfs.New(rc, zipFilename), goroot, vfs.BindReplace)
+	fs.Bind("/lib/godoc", mapfs.New(static.Files), "/", vfs.BindReplace)
+
+	corpus := godoc.NewCorpus(fs)
+	corpus.Verbose = false
+	corpus.MaxResults = 10000 // matches flag default in main.go
+	corpus.IndexEnabled = true
+	corpus.IndexFiles = indexFilenames
+	if err := corpus.Init(); err != nil {
+		log.Fatal(err)
+	}
+	go corpus.RunIndexer()
+
+	pres = godoc.NewPresentation(corpus)
+	pres.TabWidth = 8
+	pres.ShowPlayground = true
+	pres.ShowExamples = true
+	pres.DeclLinks = true
+
+	readTemplates(pres, true)
+	registerHandlers(pres)
+
+	log.Println("godoc initialization complete")
+}
diff --git a/third_party/go.tools/cmd/godoc/blog.go b/third_party/go.tools/cmd/godoc/blog.go
new file mode 100644
index 0000000..c7d161b
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/blog.go
@@ -0,0 +1,81 @@
+// Copyright 2013 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 (
+	"fmt"
+	"go/build"
+	"log"
+	"net/http"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"sync"
+
+	"llvm.org/llgo/third_party/go.tools/blog"
+	"llvm.org/llgo/third_party/go.tools/godoc/redirect"
+)
+
+const (
+	blogRepo = "golang.org/x/blog"
+	blogURL  = "http://blog.golang.org/"
+	blogPath = "/blog/"
+)
+
+var (
+	blogServer   http.Handler // set by blogInit
+	blogInitOnce sync.Once
+	playEnabled  bool
+)
+
+func init() {
+	// Initialize blog only when first accessed.
+	http.HandleFunc(blogPath, func(w http.ResponseWriter, r *http.Request) {
+		blogInitOnce.Do(blogInit)
+		blogServer.ServeHTTP(w, r)
+	})
+}
+
+func blogInit() {
+	// Binary distributions will include the blog content in "/blog".
+	root := filepath.Join(runtime.GOROOT(), "blog")
+
+	// Prefer content from go.blog repository if present.
+	if pkg, err := build.Import(blogRepo, "", build.FindOnly); err == nil {
+		root = pkg.Dir
+	}
+
+	// If content is not available fall back to redirect.
+	if fi, err := os.Stat(root); err != nil || !fi.IsDir() {
+		fmt.Fprintf(os.Stderr, "Blog content not available locally. "+
+			"To install, run \n\tgo get %v\n", blogRepo)
+		blogServer = http.HandlerFunc(blogRedirectHandler)
+		return
+	}
+
+	s, err := blog.NewServer(blog.Config{
+		BaseURL:      blogPath,
+		BasePath:     strings.TrimSuffix(blogPath, "/"),
+		ContentPath:  filepath.Join(root, "content"),
+		TemplatePath: filepath.Join(root, "template"),
+		HomeArticles: 5,
+		PlayEnabled:  playEnabled,
+	})
+	if err != nil {
+		log.Fatal(err)
+	}
+	blogServer = s
+}
+
+func blogRedirectHandler(w http.ResponseWriter, r *http.Request) {
+	if r.URL.Path == blogPath {
+		http.Redirect(w, r, blogURL, http.StatusFound)
+		return
+	}
+	blogPrefixHandler.ServeHTTP(w, r)
+}
+
+var blogPrefixHandler = redirect.PrefixHandler(blogPath, blogURL)
diff --git a/third_party/go.tools/cmd/godoc/codewalk.go b/third_party/go.tools/cmd/godoc/codewalk.go
new file mode 100644
index 0000000..0221b13
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/codewalk.go
@@ -0,0 +1,523 @@
+// Copyright 2010 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.
+
+// The /doc/codewalk/ tree is synthesized from codewalk descriptions,
+// files named $GOROOT/doc/codewalk/*.xml.
+// For an example and a description of the format, see
+// http://golang.org/doc/codewalk/codewalk or run godoc -http=:6060
+// and see http://localhost:6060/doc/codewalk/codewalk .
+// That page is itself a codewalk; the source code for it is
+// $GOROOT/doc/codewalk/codewalk.xml.
+
+package main
+
+import (
+	"bytes"
+	"encoding/xml"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	pathpkg "path"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"text/template"
+	"unicode/utf8"
+
+	"llvm.org/llgo/third_party/go.tools/godoc"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+var codewalkHTML, codewalkdirHTML *template.Template
+
+// Handler for /doc/codewalk/ and below.
+func codewalk(w http.ResponseWriter, r *http.Request) {
+	relpath := r.URL.Path[len("/doc/codewalk/"):]
+	abspath := r.URL.Path
+
+	r.ParseForm()
+	if f := r.FormValue("fileprint"); f != "" {
+		codewalkFileprint(w, r, f)
+		return
+	}
+
+	// If directory exists, serve list of code walks.
+	dir, err := fs.Lstat(abspath)
+	if err == nil && dir.IsDir() {
+		codewalkDir(w, r, relpath, abspath)
+		return
+	}
+
+	// If file exists, serve using standard file server.
+	if err == nil {
+		pres.ServeFile(w, r)
+		return
+	}
+
+	// Otherwise append .xml and hope to find
+	// a codewalk description, but before trim
+	// the trailing /.
+	abspath = strings.TrimRight(abspath, "/")
+	cw, err := loadCodewalk(abspath + ".xml")
+	if err != nil {
+		log.Print(err)
+		pres.ServeError(w, r, relpath, err)
+		return
+	}
+
+	// Canonicalize the path and redirect if changed
+	if redir(w, r) {
+		return
+	}
+
+	pres.ServePage(w, godoc.Page{
+		Title:    "Codewalk: " + cw.Title,
+		Tabtitle: cw.Title,
+		Body:     applyTemplate(codewalkHTML, "codewalk", cw),
+	})
+}
+
+func redir(w http.ResponseWriter, r *http.Request) (redirected bool) {
+	canonical := pathpkg.Clean(r.URL.Path)
+	if !strings.HasSuffix(canonical, "/") {
+		canonical += "/"
+	}
+	if r.URL.Path != canonical {
+		url := *r.URL
+		url.Path = canonical
+		http.Redirect(w, r, url.String(), http.StatusMovedPermanently)
+		redirected = true
+	}
+	return
+}
+
+func applyTemplate(t *template.Template, name string, data interface{}) []byte {
+	var buf bytes.Buffer
+	if err := t.Execute(&buf, data); err != nil {
+		log.Printf("%s.Execute: %s", name, err)
+	}
+	return buf.Bytes()
+}
+
+// A Codewalk represents a single codewalk read from an XML file.
+type Codewalk struct {
+	Title string      `xml:"title,attr"`
+	File  []string    `xml:"file"`
+	Step  []*Codestep `xml:"step"`
+}
+
+// A Codestep is a single step in a codewalk.
+type Codestep struct {
+	// Filled in from XML
+	Src   string `xml:"src,attr"`
+	Title string `xml:"title,attr"`
+	XML   string `xml:",innerxml"`
+
+	// Derived from Src; not in XML.
+	Err    error
+	File   string
+	Lo     int
+	LoByte int
+	Hi     int
+	HiByte int
+	Data   []byte
+}
+
+// String method for printing in template.
+// Formats file address nicely.
+func (st *Codestep) String() string {
+	s := st.File
+	if st.Lo != 0 || st.Hi != 0 {
+		s += fmt.Sprintf(":%d", st.Lo)
+		if st.Lo != st.Hi {
+			s += fmt.Sprintf(",%d", st.Hi)
+		}
+	}
+	return s
+}
+
+// loadCodewalk reads a codewalk from the named XML file.
+func loadCodewalk(filename string) (*Codewalk, error) {
+	f, err := fs.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	cw := new(Codewalk)
+	d := xml.NewDecoder(f)
+	d.Entity = xml.HTMLEntity
+	err = d.Decode(cw)
+	if err != nil {
+		return nil, &os.PathError{Op: "parsing", Path: filename, Err: err}
+	}
+
+	// Compute file list, evaluate line numbers for addresses.
+	m := make(map[string]bool)
+	for _, st := range cw.Step {
+		i := strings.Index(st.Src, ":")
+		if i < 0 {
+			i = len(st.Src)
+		}
+		filename := st.Src[0:i]
+		data, err := vfs.ReadFile(fs, filename)
+		if err != nil {
+			st.Err = err
+			continue
+		}
+		if i < len(st.Src) {
+			lo, hi, err := addrToByteRange(st.Src[i+1:], 0, data)
+			if err != nil {
+				st.Err = err
+				continue
+			}
+			// Expand match to line boundaries.
+			for lo > 0 && data[lo-1] != '\n' {
+				lo--
+			}
+			for hi < len(data) && (hi == 0 || data[hi-1] != '\n') {
+				hi++
+			}
+			st.Lo = byteToLine(data, lo)
+			st.Hi = byteToLine(data, hi-1)
+		}
+		st.Data = data
+		st.File = filename
+		m[filename] = true
+	}
+
+	// Make list of files
+	cw.File = make([]string, len(m))
+	i := 0
+	for f := range m {
+		cw.File[i] = f
+		i++
+	}
+	sort.Strings(cw.File)
+
+	return cw, nil
+}
+
+// codewalkDir serves the codewalk directory listing.
+// It scans the directory for subdirectories or files named *.xml
+// and prepares a table.
+func codewalkDir(w http.ResponseWriter, r *http.Request, relpath, abspath string) {
+	type elem struct {
+		Name  string
+		Title string
+	}
+
+	dir, err := fs.ReadDir(abspath)
+	if err != nil {
+		log.Print(err)
+		pres.ServeError(w, r, relpath, err)
+		return
+	}
+	var v []interface{}
+	for _, fi := range dir {
+		name := fi.Name()
+		if fi.IsDir() {
+			v = append(v, &elem{name + "/", ""})
+		} else if strings.HasSuffix(name, ".xml") {
+			cw, err := loadCodewalk(abspath + "/" + name)
+			if err != nil {
+				continue
+			}
+			v = append(v, &elem{name[0 : len(name)-len(".xml")], cw.Title})
+		}
+	}
+
+	pres.ServePage(w, godoc.Page{
+		Title: "Codewalks",
+		Body:  applyTemplate(codewalkdirHTML, "codewalkdir", v),
+	})
+}
+
+// codewalkFileprint serves requests with ?fileprint=f&lo=lo&hi=hi.
+// The filename f has already been retrieved and is passed as an argument.
+// Lo and hi are the numbers of the first and last line to highlight
+// in the response.  This format is used for the middle window pane
+// of the codewalk pages.  It is a separate iframe and does not get
+// the usual godoc HTML wrapper.
+func codewalkFileprint(w http.ResponseWriter, r *http.Request, f string) {
+	abspath := f
+	data, err := vfs.ReadFile(fs, abspath)
+	if err != nil {
+		log.Print(err)
+		pres.ServeError(w, r, f, err)
+		return
+	}
+	lo, _ := strconv.Atoi(r.FormValue("lo"))
+	hi, _ := strconv.Atoi(r.FormValue("hi"))
+	if hi < lo {
+		hi = lo
+	}
+	lo = lineToByte(data, lo)
+	hi = lineToByte(data, hi+1)
+
+	// Put the mark 4 lines before lo, so that the iframe
+	// shows a few lines of context before the highlighted
+	// section.
+	n := 4
+	mark := lo
+	for ; mark > 0 && n > 0; mark-- {
+		if data[mark-1] == '\n' {
+			if n--; n == 0 {
+				break
+			}
+		}
+	}
+
+	io.WriteString(w, `<style type="text/css">@import "/doc/codewalk/codewalk.css";</style><pre>`)
+	template.HTMLEscape(w, data[0:mark])
+	io.WriteString(w, "<a name='mark'></a>")
+	template.HTMLEscape(w, data[mark:lo])
+	if lo < hi {
+		io.WriteString(w, "<div class='codewalkhighlight'>")
+		template.HTMLEscape(w, data[lo:hi])
+		io.WriteString(w, "</div>")
+	}
+	template.HTMLEscape(w, data[hi:])
+	io.WriteString(w, "</pre>")
+}
+
+// addrToByte evaluates the given address starting at offset start in data.
+// It returns the lo and hi byte offset of the matched region within data.
+// See http://plan9.bell-labs.com/sys/doc/sam/sam.html Table II
+// for details on the syntax.
+func addrToByteRange(addr string, start int, data []byte) (lo, hi int, err error) {
+	var (
+		dir        byte
+		prevc      byte
+		charOffset bool
+	)
+	lo = start
+	hi = start
+	for addr != "" && err == nil {
+		c := addr[0]
+		switch c {
+		default:
+			err = errors.New("invalid address syntax near " + string(c))
+		case ',':
+			if len(addr) == 1 {
+				hi = len(data)
+			} else {
+				_, hi, err = addrToByteRange(addr[1:], hi, data)
+			}
+			return
+
+		case '+', '-':
+			if prevc == '+' || prevc == '-' {
+				lo, hi, err = addrNumber(data, lo, hi, prevc, 1, charOffset)
+			}
+			dir = c
+
+		case '$':
+			lo = len(data)
+			hi = len(data)
+			if len(addr) > 1 {
+				dir = '+'
+			}
+
+		case '#':
+			charOffset = true
+
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			var i int
+			for i = 1; i < len(addr); i++ {
+				if addr[i] < '0' || addr[i] > '9' {
+					break
+				}
+			}
+			var n int
+			n, err = strconv.Atoi(addr[0:i])
+			if err != nil {
+				break
+			}
+			lo, hi, err = addrNumber(data, lo, hi, dir, n, charOffset)
+			dir = 0
+			charOffset = false
+			prevc = c
+			addr = addr[i:]
+			continue
+
+		case '/':
+			var i, j int
+		Regexp:
+			for i = 1; i < len(addr); i++ {
+				switch addr[i] {
+				case '\\':
+					i++
+				case '/':
+					j = i + 1
+					break Regexp
+				}
+			}
+			if j == 0 {
+				j = i
+			}
+			pattern := addr[1:i]
+			lo, hi, err = addrRegexp(data, lo, hi, dir, pattern)
+			prevc = c
+			addr = addr[j:]
+			continue
+		}
+		prevc = c
+		addr = addr[1:]
+	}
+
+	if err == nil && dir != 0 {
+		lo, hi, err = addrNumber(data, lo, hi, dir, 1, charOffset)
+	}
+	if err != nil {
+		return 0, 0, err
+	}
+	return lo, hi, nil
+}
+
+// addrNumber applies the given dir, n, and charOffset to the address lo, hi.
+// dir is '+' or '-', n is the count, and charOffset is true if the syntax
+// used was #n.  Applying +n (or +#n) means to advance n lines
+// (or characters) after hi.  Applying -n (or -#n) means to back up n lines
+// (or characters) before lo.
+// The return value is the new lo, hi.
+func addrNumber(data []byte, lo, hi int, dir byte, n int, charOffset bool) (int, int, error) {
+	switch dir {
+	case 0:
+		lo = 0
+		hi = 0
+		fallthrough
+
+	case '+':
+		if charOffset {
+			pos := hi
+			for ; n > 0 && pos < len(data); n-- {
+				_, size := utf8.DecodeRune(data[pos:])
+				pos += size
+			}
+			if n == 0 {
+				return pos, pos, nil
+			}
+			break
+		}
+		// find next beginning of line
+		if hi > 0 {
+			for hi < len(data) && data[hi-1] != '\n' {
+				hi++
+			}
+		}
+		lo = hi
+		if n == 0 {
+			return lo, hi, nil
+		}
+		for ; hi < len(data); hi++ {
+			if data[hi] != '\n' {
+				continue
+			}
+			switch n--; n {
+			case 1:
+				lo = hi + 1
+			case 0:
+				return lo, hi + 1, nil
+			}
+		}
+
+	case '-':
+		if charOffset {
+			// Scan backward for bytes that are not UTF-8 continuation bytes.
+			pos := lo
+			for ; pos > 0 && n > 0; pos-- {
+				if data[pos]&0xc0 != 0x80 {
+					n--
+				}
+			}
+			if n == 0 {
+				return pos, pos, nil
+			}
+			break
+		}
+		// find earlier beginning of line
+		for lo > 0 && data[lo-1] != '\n' {
+			lo--
+		}
+		hi = lo
+		if n == 0 {
+			return lo, hi, nil
+		}
+		for ; lo >= 0; lo-- {
+			if lo > 0 && data[lo-1] != '\n' {
+				continue
+			}
+			switch n--; n {
+			case 1:
+				hi = lo
+			case 0:
+				return lo, hi, nil
+			}
+		}
+	}
+
+	return 0, 0, errors.New("address out of range")
+}
+
+// addrRegexp searches for pattern in the given direction starting at lo, hi.
+// The direction dir is '+' (search forward from hi) or '-' (search backward from lo).
+// Backward searches are unimplemented.
+func addrRegexp(data []byte, lo, hi int, dir byte, pattern string) (int, int, error) {
+	re, err := regexp.Compile(pattern)
+	if err != nil {
+		return 0, 0, err
+	}
+	if dir == '-' {
+		// Could implement reverse search using binary search
+		// through file, but that seems like overkill.
+		return 0, 0, errors.New("reverse search not implemented")
+	}
+	m := re.FindIndex(data[hi:])
+	if len(m) > 0 {
+		m[0] += hi
+		m[1] += hi
+	} else if hi > 0 {
+		// No match.  Wrap to beginning of data.
+		m = re.FindIndex(data)
+	}
+	if len(m) == 0 {
+		return 0, 0, errors.New("no match for " + pattern)
+	}
+	return m[0], m[1], nil
+}
+
+// lineToByte returns the byte index of the first byte of line n.
+// Line numbers begin at 1.
+func lineToByte(data []byte, n int) int {
+	if n <= 1 {
+		return 0
+	}
+	n--
+	for i, c := range data {
+		if c == '\n' {
+			if n--; n == 0 {
+				return i + 1
+			}
+		}
+	}
+	return len(data)
+}
+
+// byteToLine returns the number of the line containing the byte at index i.
+func byteToLine(data []byte, i int) int {
+	l := 1
+	for j, c := range data {
+		if j == i {
+			return l
+		}
+		if c == '\n' {
+			l++
+		}
+	}
+	return l
+}
diff --git a/third_party/go.tools/cmd/godoc/dl.go b/third_party/go.tools/cmd/godoc/dl.go
new file mode 100644
index 0000000..bd73831
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/dl.go
@@ -0,0 +1,14 @@
+// Copyright 2014 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 "net/http"
+
+// Register a redirect handler for /dl/ to the golang.org download page.
+// This file will not be included when deploying godoc to golang.org.
+
+func init() {
+	http.Handle("/dl/", http.RedirectHandler("http://golang.org/dl/", http.StatusFound))
+}
diff --git a/third_party/go.tools/cmd/godoc/doc.go b/third_party/go.tools/cmd/godoc/doc.go
new file mode 100644
index 0000000..88ff201
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/doc.go
@@ -0,0 +1,144 @@
+// 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.
+
+/*
+
+Godoc extracts and generates documentation for Go programs.
+
+It has two modes.
+
+Without the -http flag, it runs in command-line mode and prints plain text
+documentation to standard output and exits. If both a library package and
+a command with the same name exists, using the prefix cmd/ will force
+documentation on the command rather than the library package. If the -src
+flag is specified, godoc prints the exported interface of a package in Go
+source form, or the implementation of a specific exported language entity:
+
+	godoc fmt                # documentation for package fmt
+	godoc fmt Printf         # documentation for fmt.Printf
+	godoc cmd/go             # force documentation for the go command
+	godoc -src fmt           # fmt package interface in Go source form
+	godoc -src fmt Printf    # implementation of fmt.Printf
+
+In command-line mode, the -q flag enables search queries against a godoc running
+as a webserver. If no explicit server address is specified with the -server flag,
+godoc first tries localhost:6060 and then http://golang.org.
+
+	godoc -q Reader
+	godoc -q math.Sin
+	godoc -server=:6060 -q sin
+
+With the -http flag, it runs as a web server and presents the documentation as a
+web page.
+
+	godoc -http=:6060
+
+Usage:
+	godoc [flag] package [name ...]
+
+The flags are:
+	-v
+		verbose mode
+	-q
+		arguments are considered search queries: a legal query is a
+		single identifier (such as ToLower) or a qualified identifier
+		(such as math.Sin)
+	-src
+		print (exported) source in command-line mode
+	-tabwidth=4
+		width of tabs in units of spaces
+	-timestamps=true
+		show timestamps with directory listings
+	-index
+		enable identifier and full text search index
+		(no search box is shown if -index is not set)
+	-index_files=""
+		glob pattern specifying index files; if not empty,
+		the index is read from these files in sorted order
+	-index_throttle=0.75
+		index throttle value; a value of 0 means no time is allocated
+		to the indexer (the indexer will never finish), a value of 1.0
+		means that index creation is running at full throttle (other
+		goroutines may get no time while the index is built)
+	-links=true:
+		link identifiers to their declarations
+	-write_index=false
+		write index to a file; the file name must be specified with
+		-index_files
+	-maxresults=10000
+		maximum number of full text search results shown
+		(no full text index is built if maxresults <= 0)
+	-notes="BUG"
+		regular expression matching note markers to show
+		(e.g., "BUG|TODO", ".*")
+	-html
+		print HTML in command-line mode
+	-goroot=$GOROOT
+		Go root directory
+	-http=addr
+		HTTP service address (e.g., '127.0.0.1:6060' or just ':6060')
+	-server=addr
+		webserver address for command line searches
+	-analysis=type,pointer
+		comma-separated list of analyses to perform
+    		"type": display identifier resolution, type info, method sets,
+			'implements', and static callees
+		"pointer" display channel peers, callers and dynamic callees
+			(significantly slower)
+		See http://golang.org/lib/godoc/analysis/help.html for details.
+	-templates=""
+		directory containing alternate template files; if set,
+		the directory may provide alternative template files
+		for the files in $GOROOT/lib/godoc
+	-url=path
+		print to standard output the data that would be served by
+		an HTTP request for path
+	-zip=""
+		zip file providing the file system to serve; disabled if empty
+
+By default, godoc looks at the packages it finds via $GOROOT and $GOPATH (if set).
+This behavior can be altered by providing an alternative $GOROOT with the -goroot
+flag.
+
+When godoc runs as a web server and -index is set, a search index is maintained.
+The index is created at startup.
+
+The index contains both identifier and full text search information (searchable
+via regular expressions). The maximum number of full text search results shown
+can be set with the -maxresults flag; if set to 0, no full text results are
+shown, and only an identifier index but no full text search index is created.
+
+The presentation mode of web pages served by godoc can be controlled with the
+"m" URL parameter; it accepts a comma-separated list of flag names as value:
+
+	all	show documentation for all declarations, not just the exported ones
+	methods	show all embedded methods, not just those of unexported anonymous fields
+	src	show the original source code rather then the extracted documentation
+	text	present the page in textual (command-line) form rather than HTML
+	flat	present flat (not indented) directory listings using full paths
+
+For instance, http://golang.org/pkg/math/big/?m=all,text shows the documentation
+for all (not just the exported) declarations of package big, in textual form (as
+it would appear when using godoc from the command line: "godoc -src math/big .*").
+
+By default, godoc serves files from the file system of the underlying OS.
+Instead, a .zip file may be provided via the -zip flag, which contains
+the file system to serve. The file paths stored in the .zip file must use
+slash ('/') as path separator; and they must be unrooted. $GOROOT (or -goroot)
+must be set to the .zip file directory path containing the Go root directory.
+For instance, for a .zip file created by the command:
+
+	zip go.zip $HOME/go
+
+one may run godoc as follows:
+
+	godoc -http=:6060 -zip=go.zip -goroot=$HOME/go
+
+Godoc documentation is converted to HTML or to text using the go/doc package;
+see http://golang.org/pkg/go/doc/#ToHTML for the exact rules.
+See "Godoc: documenting Go code" for how to write good comments for godoc:
+http://golang.org/doc/articles/godoc_documenting_go_code.html
+
+*/
+package main
diff --git a/third_party/go.tools/cmd/godoc/godoc_test.go b/third_party/go.tools/cmd/godoc/godoc_test.go
new file mode 100644
index 0000000..946c1ec
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/godoc_test.go
@@ -0,0 +1,357 @@
+// Copyright 2013 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_test
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+var godocTests = []struct {
+	args      []string
+	matches   []string // regular expressions
+	dontmatch []string // regular expressions
+}{
+	{
+		args: []string{"fmt"},
+		matches: []string{
+			`import "fmt"`,
+			`Package fmt implements formatted I/O`,
+		},
+	},
+	{
+		args: []string{"io", "WriteString"},
+		matches: []string{
+			`func WriteString\(`,
+			`WriteString writes the contents of the string s to w`,
+		},
+	},
+	{
+		args: []string{"nonexistingpkg"},
+		matches: []string{
+			`no such file or directory|does not exist|cannot find the file`,
+		},
+	},
+	{
+		args: []string{"fmt", "NonexistentSymbol"},
+		matches: []string{
+			`No match found\.`,
+		},
+	},
+	{
+		args: []string{"-src", "syscall", "Open"},
+		matches: []string{
+			`func Open\(`,
+		},
+		dontmatch: []string{
+			`No match found\.`,
+		},
+	},
+}
+
+// buildGodoc builds the godoc executable.
+// It returns its path, and a cleanup function.
+//
+// TODO(adonovan): opt: do this at most once, and do the cleanup
+// exactly once.  How though?  There's no atexit.
+func buildGodoc(t *testing.T) (bin string, cleanup func()) {
+	tmp, err := ioutil.TempDir("", "godoc-regtest-")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	bin = filepath.Join(tmp, "godoc")
+	if runtime.GOOS == "windows" {
+		bin += ".exe"
+	}
+	cmd := exec.Command("go", "build", "-o", bin)
+	if err := cmd.Run(); err != nil {
+		t.Fatalf("Building godoc: %v", err)
+	}
+
+	return bin, func() { os.RemoveAll(tmp) }
+}
+
+// Basic regression test for godoc command-line tool.
+func TestCLI(t *testing.T) {
+	bin, cleanup := buildGodoc(t)
+	defer cleanup()
+	for _, test := range godocTests {
+		cmd := exec.Command(bin, test.args...)
+		cmd.Args[0] = "godoc"
+		out, err := cmd.CombinedOutput()
+		if err != nil {
+			t.Errorf("Running with args %#v: %v", test.args, err)
+			continue
+		}
+		for _, pat := range test.matches {
+			re := regexp.MustCompile(pat)
+			if !re.Match(out) {
+				t.Errorf("godoc %v =\n%s\nwanted /%v/", strings.Join(test.args, " "), out, pat)
+			}
+		}
+		for _, pat := range test.dontmatch {
+			re := regexp.MustCompile(pat)
+			if re.Match(out) {
+				t.Errorf("godoc %v =\n%s\ndid not want /%v/", strings.Join(test.args, " "), out, pat)
+			}
+		}
+	}
+}
+
+func serverAddress(t *testing.T) string {
+	ln, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		ln, err = net.Listen("tcp6", "[::1]:0")
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln.Close()
+	return ln.Addr().String()
+}
+
+func waitForServer(t *testing.T, address string) {
+	// Poll every 50ms for a total of 5s.
+	for i := 0; i < 100; i++ {
+		time.Sleep(50 * time.Millisecond)
+		conn, err := net.Dial("tcp", address)
+		if err != nil {
+			continue
+		}
+		conn.Close()
+		return
+	}
+	t.Fatalf("Server %q failed to respond in 5 seconds", address)
+}
+
+func killAndWait(cmd *exec.Cmd) {
+	cmd.Process.Kill()
+	cmd.Wait()
+}
+
+// Basic integration test for godoc HTTP interface.
+func TestWeb(t *testing.T) {
+	bin, cleanup := buildGodoc(t)
+	defer cleanup()
+	addr := serverAddress(t)
+	cmd := exec.Command(bin, fmt.Sprintf("-http=%s", addr))
+	cmd.Stdout = os.Stderr
+	cmd.Stderr = os.Stderr
+	cmd.Args[0] = "godoc"
+	if err := cmd.Start(); err != nil {
+		t.Fatalf("failed to start godoc: %s", err)
+	}
+	defer killAndWait(cmd)
+	waitForServer(t, addr)
+	tests := []struct {
+		path      string
+		match     []string
+		dontmatch []string
+	}{
+		{
+			path:  "/",
+			match: []string{"Go is an open source programming language"},
+		},
+		{
+			path:  "/pkg/fmt/",
+			match: []string{"Package fmt implements formatted I/O"},
+		},
+		{
+			path:  "/src/fmt/",
+			match: []string{"scan_test.go"},
+		},
+		{
+			path:  "/src/fmt/print.go",
+			match: []string{"// Println formats using"},
+		},
+		{
+			path: "/pkg",
+			match: []string{
+				"Standard library",
+				"Package fmt implements formatted I/O",
+			},
+			dontmatch: []string{
+				"internal/syscall",
+				"cmd/gc",
+			},
+		},
+		{
+			path: "/pkg/?m=all",
+			match: []string{
+				"Standard library",
+				"Package fmt implements formatted I/O",
+				"internal/syscall",
+			},
+			dontmatch: []string{
+				"cmd/gc",
+			},
+		},
+	}
+	for _, test := range tests {
+		url := fmt.Sprintf("http://%s%s", addr, test.path)
+		resp, err := http.Get(url)
+		if err != nil {
+			t.Errorf("GET %s failed: %s", url, err)
+			continue
+		}
+		body, err := ioutil.ReadAll(resp.Body)
+		resp.Body.Close()
+		if err != nil {
+			t.Errorf("GET %s: failed to read body: %s (response: %v)", url, err, resp)
+		}
+		isErr := false
+		for _, substr := range test.match {
+			if !bytes.Contains(body, []byte(substr)) {
+				t.Errorf("GET %s: wanted substring %q in body", url, substr)
+				isErr = true
+			}
+		}
+		for _, substr := range test.dontmatch {
+			if bytes.Contains(body, []byte(substr)) {
+				t.Errorf("GET %s: didn't want substring %q in body", url, substr)
+				isErr = true
+			}
+		}
+		if isErr {
+			t.Errorf("GET %s: got:\n%s", url, body)
+		}
+	}
+}
+
+// Basic integration test for godoc -analysis=type (via HTTP interface).
+func TestTypeAnalysis(t *testing.T) {
+	// Write a fake GOROOT/GOPATH.
+	tmpdir, err := ioutil.TempDir("", "godoc-analysis")
+	if err != nil {
+		t.Fatalf("ioutil.TempDir failed: %s", err)
+	}
+	defer os.RemoveAll(tmpdir)
+	for _, f := range []struct{ file, content string }{
+		{"goroot/src/lib/lib.go", `
+package lib
+type T struct{}
+const C = 3
+var V T
+func (T) F() int { return C }
+`},
+		{"gopath/src/app/main.go", `
+package main
+import "lib"
+func main() { print(lib.V) }
+`},
+	} {
+		file := filepath.Join(tmpdir, f.file)
+		if err := os.MkdirAll(filepath.Dir(file), 0755); err != nil {
+			t.Fatalf("MkdirAll(%s) failed: %s", filepath.Dir(file), err)
+		}
+		if err := ioutil.WriteFile(file, []byte(f.content), 0644); err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	// Start the server.
+	bin, cleanup := buildGodoc(t)
+	defer cleanup()
+	addr := serverAddress(t)
+	cmd := exec.Command(bin, fmt.Sprintf("-http=%s", addr), "-analysis=type")
+	cmd.Env = append(cmd.Env, fmt.Sprintf("GOROOT=%s", filepath.Join(tmpdir, "goroot")))
+	cmd.Env = append(cmd.Env, fmt.Sprintf("GOPATH=%s", filepath.Join(tmpdir, "gopath")))
+	for _, e := range os.Environ() {
+		if strings.HasPrefix(e, "GOROOT=") || strings.HasPrefix(e, "GOPATH=") {
+			continue
+		}
+		cmd.Env = append(cmd.Env, e)
+	}
+	cmd.Stdout = os.Stderr
+	stderr, err := cmd.StderrPipe()
+	if err != nil {
+		t.Fatal(err)
+	}
+	cmd.Args[0] = "godoc"
+	if err := cmd.Start(); err != nil {
+		t.Fatalf("failed to start godoc: %s", err)
+	}
+	defer killAndWait(cmd)
+	waitForServer(t, addr)
+
+	// Wait for type analysis to complete.
+	reader := bufio.NewReader(stderr)
+	for {
+		s, err := reader.ReadString('\n')
+		if err != nil {
+			t.Fatal(err)
+		}
+		fmt.Fprint(os.Stderr, s)
+		if strings.Contains(s, "Type analysis complete.") {
+			break
+		}
+	}
+	go io.Copy(os.Stderr, reader)
+
+	t0 := time.Now()
+
+	// Make an HTTP request and check for a regular expression match.
+	// The patterns are very crude checks that basic type information
+	// has been annotated onto the source view.
+tryagain:
+	for _, test := range []struct{ url, pattern string }{
+		{"/src/lib/lib.go", "L2.*package .*Package docs for lib.*/lib"},
+		{"/src/lib/lib.go", "L3.*type .*type info for T.*struct"},
+		{"/src/lib/lib.go", "L5.*var V .*type T struct"},
+		{"/src/lib/lib.go", "L6.*func .*type T struct.*T.*return .*const C untyped int.*C"},
+
+		{"/src/app/main.go", "L2.*package .*Package docs for app"},
+		{"/src/app/main.go", "L3.*import .*Package docs for lib.*lib"},
+		{"/src/app/main.go", "L4.*func main.*package lib.*lib.*var lib.V lib.T.*V"},
+	} {
+		url := fmt.Sprintf("http://%s%s", addr, test.url)
+		resp, err := http.Get(url)
+		if err != nil {
+			t.Errorf("GET %s failed: %s", url, err)
+			continue
+		}
+		body, err := ioutil.ReadAll(resp.Body)
+		resp.Body.Close()
+		if err != nil {
+			t.Errorf("GET %s: failed to read body: %s (response: %v)", url, err, resp)
+			continue
+		}
+
+		if !bytes.Contains(body, []byte("Static analysis features")) {
+			// Type analysis results usually become available within
+			// ~4ms after godoc startup (for this input on my machine).
+			if elapsed := time.Since(t0); elapsed > 500*time.Millisecond {
+				t.Fatalf("type analysis results still unavailable after %s", elapsed)
+			}
+			time.Sleep(10 * time.Millisecond)
+			goto tryagain
+		}
+
+		match, err := regexp.Match(test.pattern, body)
+		if err != nil {
+			t.Errorf("regexp.Match(%q) failed: %s", test.pattern, err)
+			continue
+		}
+		if !match {
+			// This is a really ugly failure message.
+			t.Errorf("GET %s: body doesn't match %q, got:\n%s",
+				url, test.pattern, string(body))
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/godoc/handlers.go b/third_party/go.tools/cmd/godoc/handlers.go
new file mode 100644
index 0000000..2a16158
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/handlers.go
@@ -0,0 +1,83 @@
+// Copyright 2010 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.
+
+// The /doc/codewalk/ tree is synthesized from codewalk descriptions,
+// files named $GOROOT/doc/codewalk/*.xml.
+// For an example and a description of the format, see
+// http://golang.org/doc/codewalk/codewalk or run godoc -http=:6060
+// and see http://localhost:6060/doc/codewalk/codewalk .
+// That page is itself a codewalk; the source code for it is
+// $GOROOT/doc/codewalk/codewalk.xml.
+
+package main
+
+import (
+	"log"
+	"net/http"
+	"text/template"
+
+	"llvm.org/llgo/third_party/go.tools/godoc"
+	"llvm.org/llgo/third_party/go.tools/godoc/redirect"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+var (
+	pres *godoc.Presentation
+	fs   = vfs.NameSpace{}
+)
+
+func registerHandlers(pres *godoc.Presentation) {
+	if pres == nil {
+		panic("nil Presentation")
+	}
+	http.HandleFunc("/doc/codewalk/", codewalk)
+	http.Handle("/doc/play/", pres.FileServer())
+	http.Handle("/robots.txt", pres.FileServer())
+	http.Handle("/", pres)
+	http.Handle("/pkg/C/", redirect.Handler("/cmd/cgo/"))
+	redirect.Register(nil)
+}
+
+func readTemplate(name string) *template.Template {
+	if pres == nil {
+		panic("no global Presentation set yet")
+	}
+	path := "lib/godoc/" + name
+
+	// use underlying file system fs to read the template file
+	// (cannot use template ParseFile functions directly)
+	data, err := vfs.ReadFile(fs, path)
+	if err != nil {
+		log.Fatal("readTemplate: ", err)
+	}
+	// be explicit with errors (for app engine use)
+	t, err := template.New(name).Funcs(pres.FuncMap()).Parse(string(data))
+	if err != nil {
+		log.Fatal("readTemplate: ", err)
+	}
+	return t
+}
+
+func readTemplates(p *godoc.Presentation, html bool) {
+	p.PackageText = readTemplate("package.txt")
+	p.SearchText = readTemplate("search.txt")
+
+	if html || p.HTMLMode {
+		codewalkHTML = readTemplate("codewalk.html")
+		codewalkdirHTML = readTemplate("codewalkdir.html")
+		p.CallGraphHTML = readTemplate("callgraph.html")
+		p.DirlistHTML = readTemplate("dirlist.html")
+		p.ErrorHTML = readTemplate("error.html")
+		p.ExampleHTML = readTemplate("example.html")
+		p.GodocHTML = readTemplate("godoc.html")
+		p.ImplementsHTML = readTemplate("implements.html")
+		p.MethodSetHTML = readTemplate("methodset.html")
+		p.PackageHTML = readTemplate("package.html")
+		p.SearchHTML = readTemplate("search.html")
+		p.SearchDocHTML = readTemplate("searchdoc.html")
+		p.SearchCodeHTML = readTemplate("searchcode.html")
+		p.SearchTxtHTML = readTemplate("searchtxt.html")
+		p.SearchDescXML = readTemplate("opensearch.xml")
+	}
+}
diff --git a/third_party/go.tools/cmd/godoc/main.go b/third_party/go.tools/cmd/godoc/main.go
new file mode 100644
index 0000000..11ea86b
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/main.go
@@ -0,0 +1,327 @@
+// 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.
+
+// godoc: Go Documentation Server
+
+// Web server tree:
+//
+//	http://godoc/		main landing page
+//	http://godoc/doc/	serve from $GOROOT/doc - spec, mem, etc.
+//	http://godoc/src/	serve files from $GOROOT/src; .go gets pretty-printed
+//	http://godoc/cmd/	serve documentation about commands
+//	http://godoc/pkg/	serve documentation about packages
+//				(idea is if you say import "compress/zlib", you go to
+//				http://godoc/pkg/compress/zlib)
+//
+// Command-line interface:
+//
+//	godoc packagepath [name ...]
+//
+//	godoc compress/zlib
+//		- prints doc for package compress/zlib
+//	godoc crypto/block Cipher NewCMAC
+//		- prints doc for Cipher and NewCMAC in package crypto/block
+
+// +build !appengine
+
+package main
+
+import (
+	"archive/zip"
+	_ "expvar" // to serve /debug/vars
+	"flag"
+	"fmt"
+	"go/build"
+	"log"
+	"net/http"
+	"net/http/httptest"
+	_ "net/http/pprof" // to serve /debug/pprof/*
+	"net/url"
+	"os"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/godoc"
+	"llvm.org/llgo/third_party/go.tools/godoc/analysis"
+	"llvm.org/llgo/third_party/go.tools/godoc/static"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs/gatefs"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs/mapfs"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs/zipfs"
+)
+
+const (
+	defaultAddr = ":6060" // default webserver address
+	toolsPath   = "llvm.org/llgo/third_party/go.tools/cmd/"
+)
+
+var (
+	// file system to serve
+	// (with e.g.: zip -r go.zip $GOROOT -i \*.go -i \*.html -i \*.css -i \*.js -i \*.txt -i \*.c -i \*.h -i \*.s -i \*.png -i \*.jpg -i \*.sh -i favicon.ico)
+	zipfile = flag.String("zip", "", "zip file providing the file system to serve; disabled if empty")
+
+	// file-based index
+	writeIndex = flag.Bool("write_index", false, "write index to a file; the file name must be specified with -index_files")
+
+	analysisFlag = flag.String("analysis", "", `comma-separated list of analyses to perform (supported: type, pointer). See http://golang.org/lib/godoc/analysis/help.html`)
+
+	// network
+	httpAddr   = flag.String("http", "", "HTTP service address (e.g., '"+defaultAddr+"')")
+	serverAddr = flag.String("server", "", "webserver address for command line searches")
+
+	// layout control
+	html    = flag.Bool("html", false, "print HTML in command-line mode")
+	srcMode = flag.Bool("src", false, "print (exported) source in command-line mode")
+	urlFlag = flag.String("url", "", "print HTML for named URL")
+
+	// command-line searches
+	query = flag.Bool("q", false, "arguments are considered search queries")
+
+	verbose = flag.Bool("v", false, "verbose mode")
+
+	// file system roots
+	// TODO(gri) consider the invariant that goroot always end in '/'
+	goroot = flag.String("goroot", runtime.GOROOT(), "Go root directory")
+
+	// layout control
+	tabWidth       = flag.Int("tabwidth", 4, "tab width")
+	showTimestamps = flag.Bool("timestamps", false, "show timestamps with directory listings")
+	templateDir    = flag.String("templates", "", "directory containing alternate template files")
+	showPlayground = flag.Bool("play", false, "enable playground in web interface")
+	showExamples   = flag.Bool("ex", false, "show examples in command line mode")
+	declLinks      = flag.Bool("links", true, "link identifiers to their declarations")
+
+	// search index
+	indexEnabled = flag.Bool("index", false, "enable search index")
+	indexFiles   = flag.String("index_files", "", "glob pattern specifying index files;"+
+		"if not empty, the index is read from these files in sorted order")
+	maxResults    = flag.Int("maxresults", 10000, "maximum number of full text search results shown")
+	indexThrottle = flag.Float64("index_throttle", 0.75, "index throttle value; 0.0 = no time allocated, 1.0 = full throttle")
+
+	// source code notes
+	notesRx = flag.String("notes", "BUG", "regular expression matching note markers to show")
+)
+
+func usage() {
+	fmt.Fprintf(os.Stderr,
+		"usage: godoc package [name ...]\n"+
+			"	godoc -http="+defaultAddr+"\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func loggingHandler(h http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+		log.Printf("%s\t%s", req.RemoteAddr, req.URL)
+		h.ServeHTTP(w, req)
+	})
+}
+
+func handleURLFlag() {
+	// Try up to 10 fetches, following redirects.
+	urlstr := *urlFlag
+	for i := 0; i < 10; i++ {
+		// Prepare request.
+		u, err := url.Parse(urlstr)
+		if err != nil {
+			log.Fatal(err)
+		}
+		req := &http.Request{
+			URL: u,
+		}
+
+		// Invoke default HTTP handler to serve request
+		// to our buffering httpWriter.
+		w := httptest.NewRecorder()
+		http.DefaultServeMux.ServeHTTP(w, req)
+
+		// Return data, error, or follow redirect.
+		switch w.Code {
+		case 200: // ok
+			os.Stdout.Write(w.Body.Bytes())
+			return
+		case 301, 302, 303, 307: // redirect
+			redirect := w.HeaderMap.Get("Location")
+			if redirect == "" {
+				log.Fatalf("HTTP %d without Location header", w.Code)
+			}
+			urlstr = redirect
+		default:
+			log.Fatalf("HTTP error %d", w.Code)
+		}
+	}
+	log.Fatalf("too many redirects")
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+
+	playEnabled = *showPlayground
+
+	// Check usage: either server and no args, command line and args, or index creation mode
+	if (*httpAddr != "" || *urlFlag != "") != (flag.NArg() == 0) && !*writeIndex {
+		usage()
+	}
+
+	var fsGate chan bool
+	fsGate = make(chan bool, 20)
+
+	// Determine file system to use.
+	if *zipfile == "" {
+		// use file system of underlying OS
+		rootfs := gatefs.New(vfs.OS(*goroot), fsGate)
+		fs.Bind("/", rootfs, "/", vfs.BindReplace)
+	} else {
+		// use file system specified via .zip file (path separator must be '/')
+		rc, err := zip.OpenReader(*zipfile)
+		if err != nil {
+			log.Fatalf("%s: %s\n", *zipfile, err)
+		}
+		defer rc.Close() // be nice (e.g., -writeIndex mode)
+		fs.Bind("/", zipfs.New(rc, *zipfile), *goroot, vfs.BindReplace)
+	}
+	if *templateDir != "" {
+		fs.Bind("/lib/godoc", vfs.OS(*templateDir), "/", vfs.BindBefore)
+	} else {
+		fs.Bind("/lib/godoc", mapfs.New(static.Files), "/", vfs.BindReplace)
+	}
+
+	// Bind $GOPATH trees into Go root.
+	for _, p := range filepath.SplitList(build.Default.GOPATH) {
+		fs.Bind("/src", gatefs.New(vfs.OS(p), fsGate), "/src", vfs.BindAfter)
+	}
+
+	httpMode := *httpAddr != ""
+
+	var typeAnalysis, pointerAnalysis bool
+	if *analysisFlag != "" {
+		for _, a := range strings.Split(*analysisFlag, ",") {
+			switch a {
+			case "type":
+				typeAnalysis = true
+			case "pointer":
+				pointerAnalysis = true
+			default:
+				log.Fatalf("unknown analysis: %s", a)
+			}
+		}
+	}
+
+	corpus := godoc.NewCorpus(fs)
+	corpus.Verbose = *verbose
+	corpus.MaxResults = *maxResults
+	corpus.IndexEnabled = *indexEnabled && httpMode
+	if *maxResults == 0 {
+		corpus.IndexFullText = false
+	}
+	corpus.IndexFiles = *indexFiles
+	corpus.IndexThrottle = *indexThrottle
+	if *writeIndex {
+		corpus.IndexThrottle = 1.0
+		corpus.IndexEnabled = true
+	}
+	if *writeIndex || httpMode || *urlFlag != "" {
+		if err := corpus.Init(); err != nil {
+			log.Fatal(err)
+		}
+	}
+
+	pres = godoc.NewPresentation(corpus)
+	pres.TabWidth = *tabWidth
+	pres.ShowTimestamps = *showTimestamps
+	pres.ShowPlayground = *showPlayground
+	pres.ShowExamples = *showExamples
+	pres.DeclLinks = *declLinks
+	pres.SrcMode = *srcMode
+	pres.HTMLMode = *html
+	if *notesRx != "" {
+		pres.NotesRx = regexp.MustCompile(*notesRx)
+	}
+
+	readTemplates(pres, httpMode || *urlFlag != "")
+	registerHandlers(pres)
+
+	if *writeIndex {
+		// Write search index and exit.
+		if *indexFiles == "" {
+			log.Fatal("no index file specified")
+		}
+
+		log.Println("initialize file systems")
+		*verbose = true // want to see what happens
+
+		corpus.UpdateIndex()
+
+		log.Println("writing index file", *indexFiles)
+		f, err := os.Create(*indexFiles)
+		if err != nil {
+			log.Fatal(err)
+		}
+		index, _ := corpus.CurrentIndex()
+		_, err = index.WriteTo(f)
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		log.Println("done")
+		return
+	}
+
+	// Print content that would be served at the URL *urlFlag.
+	if *urlFlag != "" {
+		handleURLFlag()
+		return
+	}
+
+	if httpMode {
+		// HTTP server mode.
+		var handler http.Handler = http.DefaultServeMux
+		if *verbose {
+			log.Printf("Go Documentation Server")
+			log.Printf("version = %s", runtime.Version())
+			log.Printf("address = %s", *httpAddr)
+			log.Printf("goroot = %s", *goroot)
+			log.Printf("tabwidth = %d", *tabWidth)
+			switch {
+			case !*indexEnabled:
+				log.Print("search index disabled")
+			case *maxResults > 0:
+				log.Printf("full text index enabled (maxresults = %d)", *maxResults)
+			default:
+				log.Print("identifier search index enabled")
+			}
+			fs.Fprint(os.Stderr)
+			handler = loggingHandler(handler)
+		}
+
+		// Initialize search index.
+		if *indexEnabled {
+			go corpus.RunIndexer()
+		}
+
+		// Start type/pointer analysis.
+		if typeAnalysis || pointerAnalysis {
+			go analysis.Run(pointerAnalysis, &corpus.Analysis)
+		}
+
+		// Start http server.
+		if err := http.ListenAndServe(*httpAddr, handler); err != nil {
+			log.Fatalf("ListenAndServe %s: %v", *httpAddr, err)
+		}
+
+		return
+	}
+
+	if *query {
+		handleRemoteSearch()
+		return
+	}
+
+	if err := godoc.CommandLine(os.Stdout, fs, pres, flag.Args()); err != nil {
+		log.Print(err)
+	}
+}
diff --git a/third_party/go.tools/cmd/godoc/play.go b/third_party/go.tools/cmd/godoc/play.go
new file mode 100644
index 0000000..7fbdd10
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/play.go
@@ -0,0 +1,44 @@
+// 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 main
+
+import (
+	"encoding/json"
+	"fmt"
+	"go/format"
+	"net/http"
+
+	// This package registers "/compile" and "/share" handlers
+	// that redirect to the golang.org playground.
+	_ "llvm.org/llgo/third_party/go.tools/playground"
+)
+
+func init() {
+	http.HandleFunc("/fmt", fmtHandler)
+}
+
+type fmtResponse struct {
+	Body  string
+	Error string
+}
+
+// fmtHandler takes a Go program in its "body" form value, formats it with
+// standard gofmt formatting, and writes a fmtResponse as a JSON object.
+func fmtHandler(w http.ResponseWriter, r *http.Request) {
+	resp := new(fmtResponse)
+	body, err := format.Source([]byte(r.FormValue("body")))
+	if err != nil {
+		resp.Error = err.Error()
+	} else {
+		resp.Body = string(body)
+	}
+	json.NewEncoder(w).Encode(resp)
+}
+
+// disabledHandler serves a 501 "Not Implemented" response.
+func disabledHandler(w http.ResponseWriter, r *http.Request) {
+	w.WriteHeader(http.StatusNotImplemented)
+	fmt.Fprint(w, "This functionality is not available via local godoc.")
+}
diff --git a/third_party/go.tools/cmd/godoc/remotesearch.go b/third_party/go.tools/cmd/godoc/remotesearch.go
new file mode 100644
index 0000000..f01d5c7
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/remotesearch.go
@@ -0,0 +1,72 @@
+// 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.
+
+// +build !appengine
+
+package main
+
+import (
+	"errors"
+	"flag"
+	"io"
+	"log"
+	"net/http"
+	"net/url"
+	"os"
+)
+
+func handleRemoteSearch() {
+	// Command-line queries.
+	for i := 0; i < flag.NArg(); i++ {
+		res, err := remoteSearch(flag.Arg(i))
+		if err != nil {
+			log.Fatalf("remoteSearch: %s", err)
+		}
+		io.Copy(os.Stdout, res.Body)
+	}
+	return
+}
+
+// remoteSearchURL returns the search URL for a given query as needed by
+// remoteSearch. If html is set, an html result is requested; otherwise
+// the result is in textual form.
+// Adjust this function as necessary if modeNames or FormValue parameters
+// change.
+func remoteSearchURL(query string, html bool) string {
+	s := "/search?m=text&q="
+	if html {
+		s = "/search?q="
+	}
+	return s + url.QueryEscape(query)
+}
+
+func remoteSearch(query string) (res *http.Response, err error) {
+	// list of addresses to try
+	var addrs []string
+	if *serverAddr != "" {
+		// explicit server address - only try this one
+		addrs = []string{*serverAddr}
+	} else {
+		addrs = []string{
+			defaultAddr,
+			"golang.org",
+		}
+	}
+
+	// remote search
+	search := remoteSearchURL(query, *html)
+	for _, addr := range addrs {
+		url := "http://" + addr + search
+		res, err = http.Get(url)
+		if err == nil && res.StatusCode == http.StatusOK {
+			break
+		}
+	}
+
+	if err == nil && res.StatusCode != http.StatusOK {
+		err = errors.New(res.Status)
+	}
+
+	return
+}
diff --git a/third_party/go.tools/cmd/godoc/setup-godoc-app.bash b/third_party/go.tools/cmd/godoc/setup-godoc-app.bash
new file mode 100755
index 0000000..284df8b
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/setup-godoc-app.bash
@@ -0,0 +1,134 @@
+#!/usr/bin/env bash
+
+# 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.
+
+# This script creates a complete godoc app in $APPDIR.
+# It copies the cmd/godoc and src/go/... sources from GOROOT,
+# synthesizes an app.yaml file, and creates the .zip, index, and
+# configuration files.
+#
+# If an argument is provided it is assumed to be the app-engine godoc directory.
+# Without an argument, $APPDIR is used instead. If GOROOT is not set, "go env"
+# is consulted to find the $GOROOT.
+#
+# The script creates a .zip file representing the $GOROOT file system
+# and computes the correspondig search index files. These files are then
+# copied to $APPDIR. A corresponding godoc configuration file is created
+# in $APPDIR/appconfig.go.
+
+ZIPFILE=godoc.zip
+INDEXFILE=godoc.index
+SPLITFILES=index.split.
+GODOC=golang.org/x/tools/cmd/godoc
+CONFIGFILE=$GODOC/appconfig.go
+
+error() {
+	echo "error: $1"
+	exit 2
+}
+
+getArgs() {
+	if [ -z $APPENGINE_SDK ]; then
+		error "APPENGINE_SDK environment variable not set"
+	fi
+	if [ ! -x $APPENGINE_SDK/go ]; then
+		error "couldn't find go comment in $APPENGINE_SDK"
+	fi
+	if [ -z $GOROOT ]; then
+		GOROOT=$(go env GOROOT)
+		echo "GOROOT not set explicitly, using go env value instead"
+	fi
+	if [ -z $APPDIR ]; then
+		if [ $# == 0 ]; then
+			error "APPDIR not set, and no argument provided"
+		fi
+		APPDIR=$1
+		echo "APPDIR not set, using argument instead"
+	fi
+	
+	# safety checks
+	if [ ! -d $GOROOT ]; then
+		error "$GOROOT is not a directory"
+	fi
+	if [ -e $APPDIR ]; then
+		error "$APPDIR exists; check and remove it before trying again"
+	fi
+
+	# reporting
+	echo "GOROOT = $GOROOT"
+	echo "APPDIR = $APPDIR"
+}
+
+fetchGodoc() {
+	echo "*** Fetching godoc (if not already in GOPATH)"
+	unset GOBIN
+	go=$APPENGINE_SDK/go
+	$go get -d -tags appengine $GODOC
+	mkdir -p $APPDIR/$GODOC
+	cp $(find $($go list -f '{{.Dir}}' $GODOC) -type f -depth 1) $APPDIR/$GODOC/
+}
+
+makeAppYaml() {
+	echo "*** make $APPDIR/app.yaml"
+	cat > $APPDIR/app.yaml <<EOF
+application: godoc
+version: 1
+runtime: go
+api_version: go1
+
+handlers:
+- url: /.*
+  script: _go_app
+EOF
+}
+
+makeZipfile() {
+	echo "*** make $APPDIR/$ZIPFILE"
+	zip -q -r $APPDIR/$ZIPFILE $GOROOT/*
+}
+
+makeIndexfile() {
+	echo "*** make $APPDIR/$INDEXFILE"
+	GOPATH= godoc -write_index -index_files=$APPDIR/$INDEXFILE -zip=$APPDIR/$ZIPFILE
+}
+
+splitIndexfile() {
+	echo "*** split $APPDIR/$INDEXFILE"
+	split -b8m $APPDIR/$INDEXFILE $APPDIR/$SPLITFILES
+}
+
+makeConfigfile() {
+	echo "*** make $APPDIR/$CONFIGFILE"
+	cat > $APPDIR/$CONFIGFILE <<EOF
+package main
+
+// GENERATED FILE - DO NOT MODIFY BY HAND.
+// (generated by $GOROOT/src/cmd/godoc/setup-godoc-app.bash)
+
+const (
+	// .zip filename
+	zipFilename = "$ZIPFILE"
+
+	// goroot directory in .zip file
+	zipGoroot = "$GOROOT"
+
+	// glob pattern describing search index files
+	// (if empty, the index is built at run-time)
+	indexFilenames = "$SPLITFILES*"
+)
+EOF
+}
+
+getArgs "$@"
+set -e
+mkdir $APPDIR
+fetchGodoc
+makeAppYaml
+makeZipfile
+makeIndexfile
+splitIndexfile
+makeConfigfile
+
+echo "*** setup complete"
diff --git a/third_party/go.tools/cmd/godoc/x.go b/third_party/go.tools/cmd/godoc/x.go
new file mode 100644
index 0000000..ed7c8d8
--- /dev/null
+++ b/third_party/go.tools/cmd/godoc/x.go
@@ -0,0 +1,68 @@
+// Copyright 2013 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.
+
+// This file contains the handlers that serve go-import redirects for Go
+// sub-repositories. It specifies the mapping from import paths like
+// "golang.org/x/tools" to the actual repository locations.
+
+package main
+
+import (
+	"html/template"
+	"log"
+	"net/http"
+	"strings"
+)
+
+const xPrefix = "/x/"
+
+var xMap = map[string]string{
+	"benchmarks": "https://code.google.com/p/go.benchmarks",
+	"blog":       "https://code.google.com/p/go.blog",
+	"codereview": "https://code.google.com/p/go.codereview",
+	"crypto":     "https://code.google.com/p/go.crypto",
+	"exp":        "https://code.google.com/p/go.exp",
+	"image":      "https://code.google.com/p/go.image",
+	"mobile":     "https://code.google.com/p/go.mobile",
+	"net":        "https://code.google.com/p/go.net",
+	"sys":        "https://code.google.com/p/go.sys",
+	"talks":      "https://code.google.com/p/go.talks",
+	"text":       "https://code.google.com/p/go.text",
+	"tools":      "https://code.google.com/p/go.tools",
+}
+
+func init() {
+	http.HandleFunc(xPrefix, xHandler)
+}
+
+func xHandler(w http.ResponseWriter, r *http.Request) {
+	head, tail := strings.TrimPrefix(r.URL.Path, xPrefix), ""
+	if i := strings.Index(head, "/"); i != -1 {
+		head, tail = head[:i], head[i:]
+	}
+	repo, ok := xMap[head]
+	if !ok {
+		http.NotFound(w, r)
+		return
+	}
+	data := struct {
+		Prefix, Head, Tail, Repo string
+	}{xPrefix, head, tail, repo}
+	if err := xTemplate.Execute(w, data); err != nil {
+		log.Println("xHandler:", err)
+	}
+}
+
+var xTemplate = template.Must(template.New("x").Parse(`<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<meta name="go-import" content="golang.org{{.Prefix}}{{.Head}} hg {{.Repo}}">
+<meta http-equiv="refresh" content="0; url=https://godoc.org/golang.org{{.Prefix}}{{.Head}}{{.Tail}}">
+</head>
+<body>
+Nothing to see here; <a href="https://godoc.org/golang.org{{.Prefix}}{{.Head}}{{.Tail}}">move along</a>.
+</body>
+</html>
+`))
diff --git a/third_party/go.tools/cmd/goimports/doc.go b/third_party/go.tools/cmd/goimports/doc.go
new file mode 100644
index 0000000..a64ad93
--- /dev/null
+++ b/third_party/go.tools/cmd/goimports/doc.go
@@ -0,0 +1,33 @@
+/*
+
+Command goimports updates your Go import lines,
+adding missing ones and removing unreferenced ones.
+
+     $ go get golang.org/x/tools/cmd/goimports
+
+It's a drop-in replacement for your editor's gofmt-on-save hook.
+It has the same command-line interface as gofmt and formats
+your code in the same way.
+
+For emacs, make sure you have the latest go-mode.el:
+   https://github.com/dominikh/go-mode.el
+Then in your .emacs file:
+   (setq gofmt-command "goimports")
+   (add-to-list 'load-path "/home/you/somewhere/emacs/")
+   (require 'go-mode-load)
+   (add-hook 'before-save-hook 'gofmt-before-save)
+
+For vim, set "gofmt_command" to "goimports":
+    https://code.google.com/p/go/source/detail?r=39c724dd7f252
+    https://code.google.com/p/go/source/browse#hg%2Fmisc%2Fvim
+    etc
+
+For GoSublime, follow the steps described here:
+    http://michaelwhatcott.com/gosublime-goimports/
+
+For other editors, you probably know what to do.
+
+Happy hacking!
+
+*/
+package main
diff --git a/third_party/go.tools/cmd/goimports/goimports.go b/third_party/go.tools/cmd/goimports/goimports.go
new file mode 100644
index 0000000..f4f40d4
--- /dev/null
+++ b/third_party/go.tools/cmd/goimports/goimports.go
@@ -0,0 +1,195 @@
+// Copyright 2013 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 (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/scanner"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/imports"
+)
+
+var (
+	// main operation modes
+	list   = flag.Bool("l", false, "list files whose formatting differs from goimport's")
+	write  = flag.Bool("w", false, "write result to (source) file instead of stdout")
+	doDiff = flag.Bool("d", false, "display diffs instead of rewriting files")
+
+	options = &imports.Options{
+		TabWidth:  8,
+		TabIndent: true,
+		Comments:  true,
+		Fragment:  true,
+	}
+	exitCode = 0
+)
+
+func init() {
+	flag.BoolVar(&options.AllErrors, "e", false, "report all errors (not just the first 10 on different lines)")
+}
+
+func report(err error) {
+	scanner.PrintError(os.Stderr, err)
+	exitCode = 2
+}
+
+func usage() {
+	fmt.Fprintf(os.Stderr, "usage: goimports [flags] [path ...]\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func isGoFile(f os.FileInfo) bool {
+	// ignore non-Go files
+	name := f.Name()
+	return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
+}
+
+func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error {
+	opt := options
+	if stdin {
+		nopt := *options
+		nopt.Fragment = true
+		opt = &nopt
+	}
+
+	if in == nil {
+		f, err := os.Open(filename)
+		if err != nil {
+			return err
+		}
+		defer f.Close()
+		in = f
+	}
+
+	src, err := ioutil.ReadAll(in)
+	if err != nil {
+		return err
+	}
+
+	res, err := imports.Process(filename, src, opt)
+	if err != nil {
+		return err
+	}
+
+	if !bytes.Equal(src, res) {
+		// formatting has changed
+		if *list {
+			fmt.Fprintln(out, filename)
+		}
+		if *write {
+			err = ioutil.WriteFile(filename, res, 0)
+			if err != nil {
+				return err
+			}
+		}
+		if *doDiff {
+			data, err := diff(src, res)
+			if err != nil {
+				return fmt.Errorf("computing diff: %s", err)
+			}
+			fmt.Printf("diff %s gofmt/%s\n", filename, filename)
+			out.Write(data)
+		}
+	}
+
+	if !*list && !*write && !*doDiff {
+		_, err = out.Write(res)
+	}
+
+	return err
+}
+
+func visitFile(path string, f os.FileInfo, err error) error {
+	if err == nil && isGoFile(f) {
+		err = processFile(path, nil, os.Stdout, false)
+	}
+	if err != nil {
+		report(err)
+	}
+	return nil
+}
+
+func walkDir(path string) {
+	filepath.Walk(path, visitFile)
+}
+
+func main() {
+	runtime.GOMAXPROCS(runtime.NumCPU())
+
+	// call gofmtMain in a separate function
+	// so that it can use defer and have them
+	// run before the exit.
+	gofmtMain()
+	os.Exit(exitCode)
+}
+
+func gofmtMain() {
+	flag.Usage = usage
+	flag.Parse()
+
+	if options.TabWidth < 0 {
+		fmt.Fprintf(os.Stderr, "negative tabwidth %d\n", options.TabWidth)
+		exitCode = 2
+		return
+	}
+
+	if flag.NArg() == 0 {
+		if err := processFile("<standard input>", os.Stdin, os.Stdout, true); err != nil {
+			report(err)
+		}
+		return
+	}
+
+	for i := 0; i < flag.NArg(); i++ {
+		path := flag.Arg(i)
+		switch dir, err := os.Stat(path); {
+		case err != nil:
+			report(err)
+		case dir.IsDir():
+			walkDir(path)
+		default:
+			if err := processFile(path, nil, os.Stdout, false); err != nil {
+				report(err)
+			}
+		}
+	}
+}
+
+func diff(b1, b2 []byte) (data []byte, err error) {
+	f1, err := ioutil.TempFile("", "gofmt")
+	if err != nil {
+		return
+	}
+	defer os.Remove(f1.Name())
+	defer f1.Close()
+
+	f2, err := ioutil.TempFile("", "gofmt")
+	if err != nil {
+		return
+	}
+	defer os.Remove(f2.Name())
+	defer f2.Close()
+
+	f1.Write(b1)
+	f2.Write(b2)
+
+	data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
+	if len(data) > 0 {
+		// diff exits with a non-zero status when the files don't match.
+		// Ignore that failure as long as we get output.
+		err = nil
+	}
+	return
+}
diff --git a/third_party/go.tools/cmd/gorename/main.go b/third_party/go.tools/cmd/gorename/main.go
new file mode 100644
index 0000000..48abb58
--- /dev/null
+++ b/third_party/go.tools/cmd/gorename/main.go
@@ -0,0 +1,138 @@
+// The gorename command performs precise type-safe renaming of
+// identifiers in Go source code.  See the -help message or Usage
+// constant for details.
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/build"
+	"os"
+	"runtime"
+
+	"llvm.org/llgo/third_party/go.tools/refactor/rename"
+)
+
+var (
+	offsetFlag = flag.String("offset", "", "file and byte offset of identifier to be renamed, e.g. 'file.go:#123'.  For use by editors.")
+	fromFlag   = flag.String("from", "", "identifier to be renamed; see -help for formats")
+	toFlag     = flag.String("to", "", "new name for identifier")
+	helpFlag   = flag.Bool("help", false, "show usage message")
+)
+
+func init() {
+	flag.BoolVar(&rename.Force, "force", false, "proceed, even if conflicts were reported")
+	flag.BoolVar(&rename.DryRun, "dryrun", false, "show the change, but do not apply it")
+	flag.BoolVar(&rename.Verbose, "v", false, "print verbose information")
+
+	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
+	// For small machines, use at least 4 threads.
+	if os.Getenv("GOMAXPROCS") == "" {
+		n := runtime.NumCPU()
+		if n < 4 {
+			n = 4
+		}
+		runtime.GOMAXPROCS(n)
+	}
+}
+
+const Usage = `gorename: precise type-safe renaming of identifiers in Go source code.
+
+Usage:
+
+ gorename (-from <spec> | -offset <file>:#<byte-offset>) -to <name> [-force]
+
+You must specify the object (named entity) to rename using the -offset
+or -from flag.  Exactly one must be specified.
+
+Flags:
+
+-offset    specifies the filename and byte offset of an identifier to rename.
+           This form is intended for use by text editors.
+
+-from      specifies the object to rename using a query notation;
+           This form is intended for interactive use at the command line.
+` + rename.FromFlagUsage + `
+
+-to        the new name.
+
+-force     causes the renaming to proceed even if conflicts were reported.
+           The resulting program may be ill-formed, or experience a change
+           in behaviour.
+
+           WARNING: this flag may even cause the renaming tool to crash.
+           (In due course this bug will be fixed by moving certain
+           analyses into the type-checker.)
+
+-dryrun    causes the tool to report conflicts but not update any files.
+
+-v         enables verbose logging.
+
+gorename automatically computes the set of packages that might be
+affected.  For a local renaming, this is just the package specified by
+-from or -offset, but for a potentially exported name, gorename scans
+the workspace ($GOROOT and $GOPATH).
+
+gorename rejects any renaming that would create a conflict at the point
+of declaration, or a reference conflict (ambiguity or shadowing), or
+anything else that could cause the resulting program not to compile.
+Currently, it also rejects any method renaming that would change the
+assignability relation between types and interfaces.
+
+
+Examples:
+
+% gorename -offset file.go:#123 -to foo
+
+  Rename the object whose identifier is at byte offset 123 within file file.go.
+
+% gorename -from '"bytes".Buffer.Len' -to Size
+
+  Rename the "Len" method of the *bytes.Buffer type to "Size".
+
+---- TODO ----
+
+Correctness:
+- handle dot imports correctly
+- document limitations (reflection, 'implements' guesswork).
+- sketch a proof of exhaustiveness.
+
+Features:
+- support running on packages specified as *.go files on the command line
+- support running on programs containing errors (loader.Config.AllowErrors)
+- allow users to specify a scope other than "global" (to avoid being
+  stuck by neglected packages in $GOPATH that don't build).
+- support renaming the package clause (no object)
+- support renaming an import path (no ident or object)
+  (requires filesystem + SCM updates).
+- detect and reject edits to autogenerated files (cgo, protobufs)
+  and optionally $GOROOT packages.
+- report all conflicts, or at least all qualitatively distinct ones.
+  Sometimes we stop to avoid redundancy, but
+  it may give a disproportionate sense of safety in -force mode.
+- support renaming all instances of a pattern, e.g.
+  all receiver vars of a given type,
+  all local variables of a given type,
+  all PkgNames for a given package.
+- emit JSON output for other editors and tools.
+`
+
+func main() {
+	flag.Parse()
+	if len(flag.Args()) > 0 {
+		fmt.Fprintln(os.Stderr, "gorename: surplus arguments.")
+		os.Exit(1)
+	}
+
+	if *helpFlag || (*offsetFlag == "" && *fromFlag == "" && *toFlag == "") {
+		fmt.Println(Usage)
+		return
+	}
+
+	if err := rename.Main(&build.Default, *offsetFlag, *fromFlag, *toFlag); err != nil {
+		if err != rename.ConflictError {
+			fmt.Fprintf(os.Stderr, "gorename: %s\n", err)
+		}
+		os.Exit(1)
+	}
+}
diff --git a/third_party/go.tools/cmd/gotype/doc.go b/third_party/go.tools/cmd/gotype/doc.go
new file mode 100644
index 0000000..e689378
--- /dev/null
+++ b/third_party/go.tools/cmd/gotype/doc.go
@@ -0,0 +1,62 @@
+// 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.
+
+/*
+The gotype command does syntactic and semantic analysis of Go files
+and packages like the front-end of a Go compiler. Errors are reported
+if the analysis fails; otherwise gotype is quiet (unless -v is set).
+
+Without a list of paths, gotype reads from standard input, which
+must provide a single Go source file defining a complete package.
+
+If a single path is specified that is a directory, gotype checks
+the Go files in that directory; they must all belong to the same
+package.
+
+Otherwise, each path must be the filename of Go file belonging to
+the same package.
+
+Usage:
+	gotype [flags] [path...]
+
+The flags are:
+	-a
+		use all (incl. _test.go) files when processing a directory
+	-e
+		report all errors (not just the first 10)
+	-v
+		verbose mode
+	-gccgo
+		use gccimporter instead of gcimporter
+
+Debugging flags:
+	-seq
+		parse sequentially, rather than in parallel
+	-ast
+		print AST (forces -seq)
+	-trace
+		print parse trace (forces -seq)
+	-comments
+		parse comments (ignored unless -ast or -trace is provided)
+
+Examples:
+
+To check the files a.go, b.go, and c.go:
+
+	gotype a.go b.go c.go
+
+To check an entire package in the directory dir and print the processed files:
+
+	gotype -v dir
+
+To check an entire package including tests in the local directory:
+
+	gotype -a .
+
+To verify the output of a pipe:
+
+	echo "package foo" | gotype
+
+*/
+package main
diff --git a/third_party/go.tools/cmd/gotype/gotype.go b/third_party/go.tools/cmd/gotype/gotype.go
new file mode 100644
index 0000000..7c5eed7
--- /dev/null
+++ b/third_party/go.tools/cmd/gotype/gotype.go
@@ -0,0 +1,262 @@
+// 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.
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"runtime"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/go/gccgoimporter"
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var (
+	// main operation modes
+	allFiles  = flag.Bool("a", false, "use all (incl. _test.go) files when processing a directory")
+	allErrors = flag.Bool("e", false, "report all errors (not just the first 10)")
+	verbose   = flag.Bool("v", false, "verbose mode")
+	gccgo     = flag.Bool("gccgo", false, "use gccgoimporter instead of gcimporter")
+
+	// debugging support
+	sequential    = flag.Bool("seq", false, "parse sequentially, rather than in parallel")
+	printAST      = flag.Bool("ast", false, "print AST (forces -seq)")
+	printTrace    = flag.Bool("trace", false, "print parse trace (forces -seq)")
+	parseComments = flag.Bool("comments", false, "parse comments (ignored unless -ast or -trace is provided)")
+)
+
+var (
+	fset       = token.NewFileSet()
+	errorCount = 0
+	parserMode parser.Mode
+	sizes      types.Sizes
+)
+
+func initParserMode() {
+	if *allErrors {
+		parserMode |= parser.AllErrors
+	}
+	if *printTrace {
+		parserMode |= parser.Trace
+	}
+	if *parseComments && (*printAST || *printTrace) {
+		parserMode |= parser.ParseComments
+	}
+}
+
+func initSizes() {
+	wordSize := 8
+	maxAlign := 8
+	switch build.Default.GOARCH {
+	case "386", "arm":
+		wordSize = 4
+		maxAlign = 4
+		// add more cases as needed
+	}
+	sizes = &types.StdSizes{WordSize: int64(wordSize), MaxAlign: int64(maxAlign)}
+}
+
+func usage() {
+	fmt.Fprintln(os.Stderr, "usage: gotype [flags] [path ...]")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func report(err error) {
+	scanner.PrintError(os.Stderr, err)
+	if list, ok := err.(scanner.ErrorList); ok {
+		errorCount += len(list)
+		return
+	}
+	errorCount++
+}
+
+// parse may be called concurrently
+func parse(filename string, src interface{}) (*ast.File, error) {
+	if *verbose {
+		fmt.Println(filename)
+	}
+	file, err := parser.ParseFile(fset, filename, src, parserMode) // ok to access fset concurrently
+	if *printAST {
+		ast.Print(fset, file)
+	}
+	return file, err
+}
+
+func parseStdin() (*ast.File, error) {
+	src, err := ioutil.ReadAll(os.Stdin)
+	if err != nil {
+		return nil, err
+	}
+	return parse("<standard input>", src)
+}
+
+func parseFiles(filenames []string) ([]*ast.File, error) {
+	files := make([]*ast.File, len(filenames))
+
+	if *sequential {
+		for i, filename := range filenames {
+			var err error
+			files[i], err = parse(filename, nil)
+			if err != nil {
+				return nil, err // leave unfinished goroutines hanging
+			}
+		}
+	} else {
+		type parseResult struct {
+			file *ast.File
+			err  error
+		}
+
+		out := make(chan parseResult)
+		for _, filename := range filenames {
+			go func(filename string) {
+				file, err := parse(filename, nil)
+				out <- parseResult{file, err}
+			}(filename)
+		}
+
+		for i := range filenames {
+			res := <-out
+			if res.err != nil {
+				return nil, res.err // leave unfinished goroutines hanging
+			}
+			files[i] = res.file
+		}
+	}
+
+	return files, nil
+}
+
+func parseDir(dirname string) ([]*ast.File, error) {
+	ctxt := build.Default
+	pkginfo, err := ctxt.ImportDir(dirname, 0)
+	if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
+		return nil, err
+	}
+	filenames := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
+	if *allFiles {
+		filenames = append(filenames, pkginfo.TestGoFiles...)
+	}
+
+	// complete file names
+	for i, filename := range filenames {
+		filenames[i] = filepath.Join(dirname, filename)
+	}
+
+	return parseFiles(filenames)
+}
+
+func getPkgFiles(args []string) ([]*ast.File, error) {
+	if len(args) == 0 {
+		// stdin
+		file, err := parseStdin()
+		if err != nil {
+			return nil, err
+		}
+		return []*ast.File{file}, nil
+	}
+
+	if len(args) == 1 {
+		// possibly a directory
+		path := args[0]
+		info, err := os.Stat(path)
+		if err != nil {
+			return nil, err
+		}
+		if info.IsDir() {
+			return parseDir(path)
+		}
+	}
+
+	// list of files
+	return parseFiles(args)
+}
+
+func checkPkgFiles(files []*ast.File) {
+	type bailout struct{}
+	conf := types.Config{
+		FakeImportC: true,
+		Error: func(err error) {
+			if !*allErrors && errorCount >= 10 {
+				panic(bailout{})
+			}
+			report(err)
+		},
+		Sizes: sizes,
+	}
+	if *gccgo {
+		var inst gccgoimporter.GccgoInstallation
+		inst.InitFromDriver("gccgo")
+		conf.Import = inst.GetImporter(nil, nil)
+	}
+
+	defer func() {
+		switch p := recover().(type) {
+		case nil, bailout:
+			// normal return or early exit
+		default:
+			// re-panic
+			panic(p)
+		}
+	}()
+
+	const path = "pkg" // any non-empty string will do for now
+	conf.Check(path, fset, files, nil)
+}
+
+func printStats(d time.Duration) {
+	fileCount := 0
+	lineCount := 0
+	fset.Iterate(func(f *token.File) bool {
+		fileCount++
+		lineCount += f.LineCount()
+		return true
+	})
+
+	fmt.Printf(
+		"%s (%d files, %d lines, %d lines/s)\n",
+		d, fileCount, lineCount, int64(float64(lineCount)/d.Seconds()),
+	)
+}
+
+func main() {
+	runtime.GOMAXPROCS(runtime.NumCPU()) // remove this once runtime is smarter
+
+	flag.Usage = usage
+	flag.Parse()
+	if *printAST || *printTrace {
+		*sequential = true
+	}
+	initParserMode()
+	initSizes()
+
+	start := time.Now()
+
+	files, err := getPkgFiles(flag.Args())
+	if err != nil {
+		report(err)
+		os.Exit(2)
+	}
+
+	checkPkgFiles(files)
+	if errorCount > 0 {
+		os.Exit(2)
+	}
+
+	if *verbose {
+		printStats(time.Since(start))
+	}
+}
diff --git a/third_party/go.tools/cmd/html2article/conv.go b/third_party/go.tools/cmd/html2article/conv.go
new file mode 100644
index 0000000..ae14a25
--- /dev/null
+++ b/third_party/go.tools/cmd/html2article/conv.go
@@ -0,0 +1,366 @@
+// Copyright 2013 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.
+
+// This program takes an HTML file and outputs a corresponding article file in
+// present format. See: golang.org/x/tools/present
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"net/url"
+	"os"
+	"regexp"
+	"strings"
+
+	"golang.org/x/net/html"
+	"golang.org/x/net/html/atom"
+)
+
+func main() {
+	flag.Parse()
+
+	err := convert(os.Stdout, os.Stdin)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+func convert(w io.Writer, r io.Reader) error {
+	root, err := html.Parse(r)
+	if err != nil {
+		return err
+	}
+
+	style := find(root, isTag(atom.Style))
+	parseStyles(style)
+
+	body := find(root, isTag(atom.Body))
+	if body == nil {
+		return errors.New("couldn't find body")
+	}
+	article := limitNewlineRuns(makeHeadings(strings.TrimSpace(text(body))))
+	_, err = fmt.Fprintf(w, "Title\n\n%s", article)
+	return err
+}
+
+type Style string
+
+const (
+	Bold   Style = "*"
+	Italic Style = "_"
+	Code   Style = "`"
+)
+
+var cssRules = make(map[string]Style)
+
+func parseStyles(style *html.Node) {
+	if style == nil || style.FirstChild == nil {
+		log.Println("couldn't find styles")
+		return
+	}
+	s := bufio.NewScanner(strings.NewReader(style.FirstChild.Data))
+
+	findRule := func(b []byte, atEOF bool) (advance int, token []byte, err error) {
+		if i := bytes.Index(b, []byte("{")); i >= 0 {
+			token = bytes.TrimSpace(b[:i])
+			advance = i
+		}
+		return
+	}
+	findBody := func(b []byte, atEOF bool) (advance int, token []byte, err error) {
+		if len(b) == 0 {
+			return
+		}
+		if b[0] != '{' {
+			err = fmt.Errorf("expected {, got %c", b[0])
+			return
+		}
+		if i := bytes.Index(b, []byte("}")); i < 0 {
+			err = fmt.Errorf("can't find closing }")
+			return
+		} else {
+			token = b[1:i]
+			advance = i + 1
+		}
+		return
+	}
+
+	s.Split(findRule)
+	for s.Scan() {
+		rule := s.Text()
+		s.Split(findBody)
+		if !s.Scan() {
+			break
+		}
+		b := strings.ToLower(s.Text())
+		switch {
+		case strings.Contains(b, "italic"):
+			cssRules[rule] = Italic
+		case strings.Contains(b, "bold"):
+			cssRules[rule] = Bold
+		case strings.Contains(b, "Consolas") || strings.Contains(b, "Courier New"):
+			cssRules[rule] = Code
+		}
+		s.Split(findRule)
+	}
+	if err := s.Err(); err != nil {
+		log.Println(err)
+	}
+}
+
+var newlineRun = regexp.MustCompile(`\n\n+`)
+
+func limitNewlineRuns(s string) string {
+	return newlineRun.ReplaceAllString(s, "\n\n")
+}
+
+func makeHeadings(body string) string {
+	buf := new(bytes.Buffer)
+	lines := strings.Split(body, "\n")
+	for i, s := range lines {
+		if i == 0 && !isBoldTitle(s) {
+			buf.WriteString("* Introduction\n\n")
+		}
+		if isBoldTitle(s) {
+			s = strings.TrimSpace(strings.Replace(s, "*", " ", -1))
+			s = "* " + s
+		}
+		buf.WriteString(s)
+		buf.WriteByte('\n')
+	}
+	return buf.String()
+}
+
+func isBoldTitle(s string) bool {
+	return !strings.Contains(s, " ") &&
+		strings.HasPrefix(s, "*") &&
+		strings.HasSuffix(s, "*")
+}
+
+func indent(buf *bytes.Buffer, s string) {
+	for _, l := range strings.Split(s, "\n") {
+		if l != "" {
+			buf.WriteByte('\t')
+			buf.WriteString(l)
+		}
+		buf.WriteByte('\n')
+	}
+}
+
+func unwrap(buf *bytes.Buffer, s string) {
+	var cont bool
+	for _, l := range strings.Split(s, "\n") {
+		l = strings.TrimSpace(l)
+		if len(l) == 0 {
+			if cont {
+				buf.WriteByte('\n')
+				buf.WriteByte('\n')
+			}
+			cont = false
+		} else {
+			if cont {
+				buf.WriteByte(' ')
+			}
+			buf.WriteString(l)
+			cont = true
+		}
+	}
+}
+
+func text(n *html.Node) string {
+	var buf bytes.Buffer
+	walk(n, func(n *html.Node) bool {
+		switch n.Type {
+		case html.TextNode:
+			buf.WriteString(n.Data)
+			return false
+		case html.ElementNode:
+			// no-op
+		default:
+			return true
+		}
+		a := n.DataAtom
+		if a == atom.Span {
+			switch {
+			case hasStyle(Code)(n):
+				a = atom.Code
+			case hasStyle(Bold)(n):
+				a = atom.B
+			case hasStyle(Italic)(n):
+				a = atom.I
+			}
+		}
+		switch a {
+		case atom.Br:
+			buf.WriteByte('\n')
+		case atom.P:
+			unwrap(&buf, childText(n))
+			buf.WriteString("\n\n")
+		case atom.Li:
+			buf.WriteString("- ")
+			unwrap(&buf, childText(n))
+			buf.WriteByte('\n')
+		case atom.Pre:
+			indent(&buf, childText(n))
+			buf.WriteByte('\n')
+		case atom.A:
+			href, text := attr(n, "href"), childText(n)
+			// Skip links with no text.
+			if strings.TrimSpace(text) == "" {
+				break
+			}
+			// Don't emit empty links.
+			if strings.TrimSpace(href) == "" {
+				buf.WriteString(text)
+				break
+			}
+			// Use original url for Google Docs redirections.
+			if u, err := url.Parse(href); err != nil {
+				log.Println("parsing url %q: %v", href, err)
+			} else if u.Host == "www.google.com" && u.Path == "/url" {
+				href = u.Query().Get("q")
+			}
+			fmt.Fprintf(&buf, "[[%s][%s]]", href, text)
+		case atom.Code:
+			buf.WriteString(highlight(n, "`"))
+		case atom.B:
+			buf.WriteString(highlight(n, "*"))
+		case atom.I:
+			buf.WriteString(highlight(n, "_"))
+		case atom.Img:
+			src := attr(n, "src")
+			fmt.Fprintf(&buf, ".image %s\n", src)
+		case atom.Iframe:
+			src, w, h := attr(n, "src"), attr(n, "width"), attr(n, "height")
+			fmt.Fprintf(&buf, "\n.iframe %s %s %s\n", src, h, w)
+		case atom.Param:
+			if attr(n, "name") == "movie" {
+				// Old style YouTube embed.
+				u := attr(n, "value")
+				u = strings.Replace(u, "/v/", "/embed/", 1)
+				if i := strings.Index(u, "&"); i >= 0 {
+					u = u[:i]
+				}
+				fmt.Fprintf(&buf, "\n.iframe %s 540 304\n", u)
+			}
+		case atom.Title:
+		default:
+			return true
+		}
+		return false
+	})
+	return buf.String()
+}
+
+func childText(node *html.Node) string {
+	var buf bytes.Buffer
+	for n := node.FirstChild; n != nil; n = n.NextSibling {
+		fmt.Fprint(&buf, text(n))
+	}
+	return buf.String()
+}
+
+func highlight(node *html.Node, char string) string {
+	t := strings.Replace(childText(node), " ", char, -1)
+	return fmt.Sprintf("%s%s%s", char, t, char)
+}
+
+type selector func(*html.Node) bool
+
+func isTag(a atom.Atom) selector {
+	return func(n *html.Node) bool {
+		return n.DataAtom == a
+	}
+}
+
+func hasClass(name string) selector {
+	return func(n *html.Node) bool {
+		for _, a := range n.Attr {
+			if a.Key == "class" {
+				for _, c := range strings.Fields(a.Val) {
+					if c == name {
+						return true
+					}
+				}
+			}
+		}
+		return false
+	}
+}
+
+func hasStyle(s Style) selector {
+	return func(n *html.Node) bool {
+		for rule, s2 := range cssRules {
+			if s2 != s {
+				continue
+			}
+			if strings.HasPrefix(rule, ".") && hasClass(rule[1:])(n) {
+				return true
+			}
+			if n.DataAtom.String() == rule {
+				return true
+			}
+		}
+		return false
+	}
+}
+
+func hasAttr(key, val string) selector {
+	return func(n *html.Node) bool {
+		for _, a := range n.Attr {
+			if a.Key == key && a.Val == val {
+				return true
+			}
+		}
+		return false
+	}
+}
+
+func attr(node *html.Node, key string) (value string) {
+	for _, attr := range node.Attr {
+		if attr.Key == key {
+			return attr.Val
+		}
+	}
+	return ""
+}
+
+func findAll(node *html.Node, fn selector) (nodes []*html.Node) {
+	walk(node, func(n *html.Node) bool {
+		if fn(n) {
+			nodes = append(nodes, n)
+		}
+		return true
+	})
+	return
+}
+
+func find(n *html.Node, fn selector) *html.Node {
+	var result *html.Node
+	walk(n, func(n *html.Node) bool {
+		if result != nil {
+			return false
+		}
+		if fn(n) {
+			result = n
+			return false
+		}
+		return true
+	})
+	return result
+}
+
+func walk(n *html.Node, fn selector) {
+	if fn(n) {
+		for c := n.FirstChild; c != nil; c = c.NextSibling {
+			walk(c, fn)
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/oracle/emacs-test.bash b/third_party/go.tools/cmd/oracle/emacs-test.bash
new file mode 100755
index 0000000..8c39091
--- /dev/null
+++ b/third_party/go.tools/cmd/oracle/emacs-test.bash
@@ -0,0 +1,50 @@
+#!/bin/bash
+#
+# Simple test of Go oracle/Emacs integration.
+# Requires that GOROOT and GOPATH are set.
+# Side effect: builds and installs oracle in $GOROOT.
+
+set -eu
+
+[ -z "$GOROOT" ] && { echo "Error: GOROOT is unset." >&2; exit 1; }
+[ -z "$GOPATH" ] && { echo "Error: GOPATH is unset." >&2; exit 1; }
+
+log=/tmp/$(basename $0)-$$.log
+thisdir=$(dirname $0)
+
+function die() {
+  echo "Error: $@."
+  cat $log
+  exit 1
+} >&2
+
+trap "rm -f $log" EXIT
+
+# Build and install oracle.
+go get golang.org/x/tools/cmd/oracle || die "'go get' failed"
+mv -f $GOPATH/bin/oracle $GOROOT/bin/
+$GOROOT/bin/oracle >$log 2>&1 || true # (prints usage and exits 1)
+grep -q "Run.*help" $log || die "$GOROOT/bin/oracle not installed"
+
+
+# Run Emacs, set the scope to the oracle tool itself,
+# load ./main.go, and describe the "fmt" import.
+emacs --batch --no-splash --no-window-system --no-init \
+    --load $GOROOT/misc/emacs/go-mode.el \
+    --load $thisdir/oracle.el \
+    --eval '
+(progn
+  (setq go-oracle-scope "golang.org/x/tools/cmd/oracle")
+  (find-file "'$thisdir'/main.go")
+  (search-forward "\"fmt\"")
+  (backward-char)
+  (go-oracle-describe)
+  (princ (with-current-buffer "*go-oracle*"
+                              (buffer-substring-no-properties (point-min) (point-max))))
+  (kill-emacs 0))
+' main.go >$log 2>&1 || die "emacs command failed"
+
+# Check that Println is mentioned.
+grep -q "fmt/print.go.*func  Println" $log || die "didn't find expected lines in log; got:"
+
+echo "PASS"
diff --git a/third_party/go.tools/cmd/oracle/main.go b/third_party/go.tools/cmd/oracle/main.go
new file mode 100644
index 0000000..1db35c9
--- /dev/null
+++ b/third_party/go.tools/cmd/oracle/main.go
@@ -0,0 +1,193 @@
+// Copyright 2013 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.
+
+// oracle: a tool for answering questions about Go source code.
+// http://golang.org/s/oracle-design
+// http://golang.org/s/oracle-user-manual
+//
+// Run with -help flag or help subcommand for usage information.
+//
+package main
+
+import (
+	"bufio"
+	"encoding/json"
+	"encoding/xml"
+	"flag"
+	"fmt"
+	"go/build"
+	"io"
+	"log"
+	"os"
+	"runtime"
+	"runtime/pprof"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/oracle"
+)
+
+var posFlag = flag.String("pos", "",
+	"Filename and byte offset or extent of a syntax element about which to query, "+
+		"e.g. foo.go:#123,#456, bar.go:#123.")
+
+var ptalogFlag = flag.String("ptalog", "",
+	"Location of the points-to analysis log file, or empty to disable logging.")
+
+var formatFlag = flag.String("format", "plain", "Output format.  One of {plain,json,xml}.")
+
+// TODO(adonovan): flip this flag after PTA presolver is implemented.
+var reflectFlag = flag.Bool("reflect", false, "Analyze reflection soundly (slow).")
+
+const useHelp = "Run 'oracle -help' for more information.\n"
+
+const helpMessage = `Go source code oracle.
+Usage: oracle [<flag> ...] <mode> <args> ...
+
+The -format flag controls the output format:
+	plain	an editor-friendly format in which every line of output
+		is of the form "pos: text", where pos is "-" if unknown.
+	json	structured data in JSON syntax.
+	xml	structured data in XML syntax.
+
+The -pos flag is required in all modes except 'callgraph'.
+
+The mode argument determines the query to perform:
+
+	callees	  	show possible targets of selected function call
+	callers	  	show possible callers of selected function
+	callgraph 	show complete callgraph of program
+	callstack 	show path from callgraph root to selected function
+	describe  	describe selected syntax: definition, methods, etc
+	freevars  	show free variables of selection
+	implements	show 'implements' relation for selected type
+	peers     	show send/receive corresponding to selected channel op
+	referrers 	show all refs to entity denoted by selected identifier
+	what		show basic information about the selected syntax node
+
+The user manual is available here:  http://golang.org/s/oracle-user-manual
+
+Examples:
+
+Describe the syntax at offset 530 in this file (an import spec):
+% oracle -pos=src/golang.org/x/tools/cmd/oracle/main.go:#530 describe \
+   golang.org/x/tools/cmd/oracle
+
+Print the callgraph of the trivial web-server in JSON format:
+% oracle -format=json $GOROOT/src/net/http/triv.go callgraph
+` + loader.FromArgsUsage
+
+var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
+
+func init() {
+	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
+	// For small machines, use at least 4 threads.
+	if os.Getenv("GOMAXPROCS") == "" {
+		n := runtime.NumCPU()
+		if n < 4 {
+			n = 4
+		}
+		runtime.GOMAXPROCS(n)
+	}
+}
+
+func printHelp() {
+	fmt.Fprintln(os.Stderr, helpMessage)
+	fmt.Fprintln(os.Stderr, "Flags:")
+	flag.PrintDefaults()
+}
+
+func main() {
+	// Don't print full help unless -help was requested.
+	// Just gently remind users that it's there.
+	flag.Usage = func() { fmt.Fprint(os.Stderr, useHelp) }
+	flag.CommandLine.Init(os.Args[0], flag.ContinueOnError) // hack
+	if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
+		// (err has already been printed)
+		if err == flag.ErrHelp {
+			printHelp()
+		}
+		os.Exit(2)
+	}
+
+	args := flag.Args()
+	if len(args) == 0 || args[0] == "" {
+		fmt.Fprint(os.Stderr, "oracle: a mode argument is required.\n"+useHelp)
+		os.Exit(2)
+	}
+
+	mode := args[0]
+	args = args[1:]
+	if mode == "help" {
+		printHelp()
+		os.Exit(2)
+	}
+
+	if len(args) == 0 && mode != "what" {
+		fmt.Fprint(os.Stderr, "oracle: no package arguments.\n"+useHelp)
+		os.Exit(2)
+	}
+
+	// Set up points-to analysis log file.
+	var ptalog io.Writer
+	if *ptalogFlag != "" {
+		if f, err := os.Create(*ptalogFlag); err != nil {
+			log.Fatalf("Failed to create PTA log file: %s", err)
+		} else {
+			buf := bufio.NewWriter(f)
+			ptalog = buf
+			defer func() {
+				buf.Flush()
+				f.Close()
+			}()
+		}
+	}
+
+	// Profiling support.
+	if *cpuprofile != "" {
+		f, err := os.Create(*cpuprofile)
+		if err != nil {
+			log.Fatal(err)
+		}
+		pprof.StartCPUProfile(f)
+		defer pprof.StopCPUProfile()
+	}
+
+	// -format flag
+	switch *formatFlag {
+	case "json", "plain", "xml":
+		// ok
+	default:
+		fmt.Fprintf(os.Stderr, "oracle: illegal -format value: %q.\n"+useHelp, *formatFlag)
+		os.Exit(2)
+	}
+
+	// Ask the oracle.
+	res, err := oracle.Query(args, mode, *posFlag, ptalog, &build.Default, *reflectFlag)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "oracle: %s.\n", err)
+		os.Exit(1)
+	}
+
+	// Print the result.
+	switch *formatFlag {
+	case "json":
+		b, err := json.MarshalIndent(res.Serial(), "", "\t")
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "oracle: JSON error: %s.\n", err)
+			os.Exit(1)
+		}
+		os.Stdout.Write(b)
+
+	case "xml":
+		b, err := xml.MarshalIndent(res.Serial(), "", "\t")
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "oracle: XML error: %s.\n", err)
+			os.Exit(1)
+		}
+		os.Stdout.Write(b)
+
+	case "plain":
+		res.WriteTo(os.Stdout)
+	}
+}
diff --git a/third_party/go.tools/cmd/oracle/oracle.el b/third_party/go.tools/cmd/oracle/oracle.el
new file mode 100644
index 0000000..35cd892
--- /dev/null
+++ b/third_party/go.tools/cmd/oracle/oracle.el
@@ -0,0 +1,223 @@
+;;;
+;;; Integration of the Go 'oracle' analysis tool into Emacs.
+;;;
+;;; To install the Go oracle, run:
+;;; % export GOROOT=... GOPATH=...
+;;; % go get golang.org/x/tools/cmd/oracle
+;;; % mv $GOPATH/bin/oracle $GOROOT/bin/
+;;;
+;;; Load this file into Emacs and set go-oracle-scope to your
+;;; configuration. Then, find a file of Go source code, enable
+;;; go-oracle-mode, select an expression of interest, and press `C-c C-o d'
+;;; (for "describe") or run one of the other go-oracle-xxx commands.
+;;;
+;;; TODO(adonovan): simplify installation and configuration by making
+;;; oracle a subcommand of 'go tool'.
+
+(require 'compile)
+(require 'go-mode)
+(require 'cl)
+
+(defgroup go-oracle nil
+  "Options specific to the Go oracle."
+  :group 'go)
+
+(defcustom go-oracle-command (concat (car (go-root-and-paths)) "/bin/oracle")
+  "The Go oracle command; the default is $GOROOT/bin/oracle."
+  :type 'string
+  :group 'go-oracle)
+
+(defcustom go-oracle-scope ""
+  "The scope of the analysis.  See `go-oracle-set-scope'."
+  :type 'string
+  :group 'go-oracle)
+
+(defvar go-oracle--scope-history
+  nil
+  "History of values supplied to `go-oracle-set-scope'.")
+
+;; TODO(adonovan): I'd like to get rid of this separate mode since it
+;; makes it harder to use the oracle.
+(defvar go-oracle-mode-map
+  (let ((m (make-sparse-keymap)))
+    (define-key m (kbd "C-c C-o t") #'go-oracle-describe) ; t for type
+    (define-key m (kbd "C-c C-o f") #'go-oracle-freevars)
+    (define-key m (kbd "C-c C-o g") #'go-oracle-callgraph)
+    (define-key m (kbd "C-c C-o i") #'go-oracle-implements)
+    (define-key m (kbd "C-c C-o c") #'go-oracle-peers)  ; c for channel
+    (define-key m (kbd "C-c C-o r") #'go-oracle-referrers)
+    (define-key m (kbd "C-c C-o d") #'go-oracle-definition)
+    (define-key m (kbd "C-c C-o p") #'go-oracle-pointsto)
+    (define-key m (kbd "C-c C-o s") #'go-oracle-callstack)
+    (define-key m (kbd "C-c C-o <") #'go-oracle-callers)
+    (define-key m (kbd "C-c C-o >") #'go-oracle-callees)
+    m))
+
+;; TODO(dominikh): Rethink set-scope some. Setting it to a file is
+;; painful because it doesn't use find-file, and variables/~ aren't
+;; expanded. Setting it to an import path is somewhat painful because
+;; it doesn't make use of go-mode's import path completion. One option
+;; would be having two different functions, but then we can't
+;; automatically call it when no scope has been set. Also it wouldn't
+;; easily allow specifying more than one file/package.
+(defun go-oracle-set-scope ()
+  "Set the scope for the Go oracle, prompting the user to edit the
+previous scope.
+
+The scope specifies a set of arguments, separated by spaces.
+It may be:
+1) a set of packages whose main() functions will be analyzed.
+2) a list of *.go filenames; they will treated like as a single
+   package (see #3).
+3) a single package whose main() function and/or Test* functions
+   will be analyzed.
+
+In the common case, this is similar to the argument(s) you would
+specify to 'go build'."
+  (interactive)
+  (let ((scope (read-from-minibuffer "Go oracle scope: "
+                                     go-oracle-scope
+                                     nil
+                                     nil
+                                     'go-oracle--scope-history)))
+    (if (string-equal "" scope)
+        (error "You must specify a non-empty scope for the Go oracle"))
+    (setq go-oracle-scope scope)))
+
+(defun go-oracle--run (mode)
+  "Run the Go oracle in the specified MODE, passing it the
+selected region of the current buffer.  Process the output to
+replace each file name with a small hyperlink.  Display the
+result."
+  (if (not buffer-file-name)
+      (error "Cannot use oracle on a buffer without a file name"))
+  ;; It's not sufficient to save a modified buffer since if
+  ;; gofmt-before-save is on the before-save-hook, saving will
+  ;; disturb the selected region.
+  (if (buffer-modified-p)
+      (error "Please save the buffer before invoking go-oracle"))
+  (if (string-equal "" go-oracle-scope)
+      (go-oracle-set-scope))
+  (let* ((filename (file-truename buffer-file-name))
+         (posflag (if (use-region-p)
+                      (format "-pos=%s:#%d,#%d"
+                              filename
+                              (1- (go--position-bytes (region-beginning)))
+                              (1- (go--position-bytes (region-end))))
+                    (format "-pos=%s:#%d"
+                            filename
+                            (1- (position-bytes (point))))))
+         ;; This would be simpler if we could just run 'go tool oracle'.
+         (env-vars (go-root-and-paths))
+         (goroot-env (concat "GOROOT=" (car env-vars)))
+         (gopath-env (concat "GOPATH=" (mapconcat #'identity (cdr env-vars) ":"))))
+    (with-current-buffer (get-buffer-create "*go-oracle*")
+      (setq buffer-read-only nil)
+      (erase-buffer)
+      (insert "Go Oracle\n")
+      (let ((args (append (list go-oracle-command nil t nil posflag mode)
+                          (split-string go-oracle-scope " " t))))
+        ;; Log the command to *Messages*, for debugging.
+        (message "Command: %s:" args)
+        (message nil) ; clears/shrinks minibuffer
+
+        (message "Running oracle...")
+        ;; Use dynamic binding to modify/restore the environment
+        (let ((process-environment (list* goroot-env gopath-env process-environment)))
+            (apply #'call-process args)))
+      (insert "\n")
+      (compilation-mode)
+      (setq compilation-error-screen-columns nil)
+
+      ;; Hide the file/line info to save space.
+      ;; Replace each with a little widget.
+      ;; compilation-mode + this loop = slooow.
+      ;; TODO(adonovan): have oracle give us JSON
+      ;; and we'll do the markup directly.
+      (let ((buffer-read-only nil)
+            (p 1))
+        (while (not (null p))
+          (let ((np (compilation-next-single-property-change p 'compilation-message)))
+            ;; TODO(adonovan): this can be verbose in the *Messages* buffer.
+            ;; (message "Post-processing link (%d%%)" (/ (* p 100) (point-max)))
+            (if np
+                (when (equal (line-number-at-pos p) (line-number-at-pos np))
+                  ;; np is (typically) the space following ":"; consume it too.
+                  (put-text-property p np 'display "▶")
+                  (goto-char np)
+                  (insert " ")))
+            (setq p np)))
+        (message nil))
+
+      (let ((w (display-buffer (current-buffer))))
+        (balance-windows)
+        (shrink-window-if-larger-than-buffer w)
+        (set-window-point w (point-min))))))
+
+(defun go-oracle-callees ()
+  "Show possible callees of the function call at the current point."
+  (interactive)
+  (go-oracle--run "callees"))
+
+(defun go-oracle-callers ()
+  "Show the set of callers of the function containing the current point."
+  (interactive)
+  (go-oracle--run "callers"))
+
+(defun go-oracle-callgraph ()
+  "Show the callgraph of the current program."
+  (interactive)
+  (go-oracle--run "callgraph"))
+
+(defun go-oracle-callstack ()
+  "Show an arbitrary path from a root of the call graph to the
+function containing the current point."
+  (interactive)
+  (go-oracle--run "callstack"))
+
+(defun go-oracle-definition ()
+  "Show the definition of the selected identifier."
+  (interactive)
+  (go-oracle--run "definition"))
+
+(defun go-oracle-describe ()
+  "Describe the selected syntax, its kind, type and methods."
+  (interactive)
+  (go-oracle--run "describe"))
+
+(defun go-oracle-pointsto ()
+  "Show what the selected expression points to."
+  (interactive)
+  (go-oracle--run "pointsto"))
+
+(defun go-oracle-implements ()
+  "Describe the 'implements' relation for types in the package
+containing the current point."
+  (interactive)
+  (go-oracle--run "implements"))
+
+(defun go-oracle-freevars ()
+  "Enumerate the free variables of the current selection."
+  (interactive)
+  (go-oracle--run "freevars"))
+
+(defun go-oracle-peers ()
+  "Enumerate the set of possible corresponding sends/receives for
+this channel receive/send operation."
+  (interactive)
+  (go-oracle--run "peers"))
+
+(defun go-oracle-referrers ()
+  "Enumerate all references to the object denoted by the selected
+identifier."
+  (interactive)
+  (go-oracle--run "referrers"))
+
+;; TODO(dominikh): better docstring
+(define-minor-mode go-oracle-mode "Oracle minor mode for go-mode
+
+Keys specific to go-oracle-mode:
+\\{go-oracle-mode-map}"
+  nil " oracle" go-oracle-mode-map)
+
+(provide 'go-oracle)
diff --git a/third_party/go.tools/cmd/oracle/oracle.vim b/third_party/go.tools/cmd/oracle/oracle.vim
new file mode 100644
index 0000000..cadda78
--- /dev/null
+++ b/third_party/go.tools/cmd/oracle/oracle.vim
@@ -0,0 +1,107 @@
+" -*- text -*-
+"  oracle.vim -- Vim integration for the Go oracle.
+"
+"  Load with (e.g.)  :source oracle.vim
+"  Call with (e.g.)  :GoOracleDescribe
+"  while cursor or selection is over syntax of interest.
+"  Run :copen to show the quick-fix file.
+"
+" This is an absolutely rudimentary integration of the Go Oracle into
+" Vim's quickfix mechanism and it needs a number of usability
+" improvements before it can be practically useful to Vim users.
+" Voluntary contributions welcomed!
+"
+" TODO(adonovan):
+" - reject buffers with no filename.
+" - hide all filenames in quickfix buffer.
+
+" Get the path to the Go oracle executable.
+func! s:go_oracle_bin()
+  let [ext, sep] = (has('win32') || has('win64') ? ['.exe', ';'] : ['', ':'])
+  let go_oracle = globpath(join(split($GOPATH, sep), ','), '/bin/oracle' . ext)
+  if go_oracle == ''
+    let go_oracle = globpath($GOROOT, '/bin/oracle' . ext)
+  endif
+  return go_oracle
+endfunction
+
+let s:go_oracle = s:go_oracle_bin()
+
+func! s:qflist(output)
+  let qflist = []
+  " Parse GNU-style 'file:line.col-line.col: message' format.
+  let mx = '^\(\a:[\\/][^:]\+\|[^:]\+\):\(\d\+\):\(\d\+\):\(.*\)$'
+  for line in split(a:output, "\n")
+    let ml = matchlist(line, mx)
+    " Ignore non-match lines or warnings
+    if ml == [] || ml[4] =~ '^ warning:'
+      continue
+    endif
+    let item = {
+    \  'filename': ml[1],
+    \  'text': ml[4],
+    \  'lnum': ml[2],
+    \  'col': ml[3],
+    \}
+    let bnr = bufnr(fnameescape(ml[1]))
+    if bnr != -1
+      let item['bufnr'] = bnr
+    endif
+    call add(qflist, item)
+  endfor
+  call setqflist(qflist)
+  cwindow
+endfun
+
+func! s:getpos(l, c)
+  if &encoding != 'utf-8'
+    let buf = a:l == 1 ? '' : (join(getline(1, a:l-1), "\n") . "\n")
+    let buf .= a:c == 1 ? '' : getline('.')[:a:c-2]
+    return len(iconv(buf, &encoding, 'utf-8'))
+  endif
+  return line2byte(a:l) + (a:c-2)
+endfun
+
+func! s:RunOracle(mode, selected) range abort
+  let fname = expand('%:p')
+  let sname = get(g:, 'go_oracle_scope_file', fname)
+  if a:selected != -1
+    let pos1 = s:getpos(line("'<"), col("'<"))
+    let pos2 = s:getpos(line("'>"), col("'>"))
+    let cmd = printf('%s -pos=%s:#%d,#%d %s %s',
+      \  s:go_oracle,
+      \  shellescape(fname), pos1, pos2, a:mode, shellescape(sname))
+  else
+    let pos = s:getpos(line('.'), col('.'))
+    let cmd = printf('%s -pos=%s:#%d %s %s',
+      \  s:go_oracle,
+      \  shellescape(fname), pos, a:mode, shellescape(sname))
+  endif
+  call s:qflist(system(cmd))
+endfun
+
+" Describe the expression at the current point.
+command! -range=% GoOracleDescribe
+  \ call s:RunOracle('describe', <count>)
+
+" Show possible callees of the function call at the current point.
+command! -range=% GoOracleCallees
+  \ call s:RunOracle('callees', <count>)
+
+" Show the set of callers of the function containing the current point.
+command! -range=% GoOracleCallers
+  \ call s:RunOracle('callers', <count>)
+
+" Show the callgraph of the current program.
+command! -range=% GoOracleCallgraph
+  \ call s:RunOracle('callgraph', <count>)
+
+" Describe the 'implements' relation for types in the
+" package containing the current point.
+command! -range=% GoOracleImplements
+  \ call s:RunOracle('implements', <count>)
+
+" Enumerate the set of possible corresponding sends/receives for
+" this channel receive/send operation.
+command! -range=% GoOracleChannelPeers
+  \ call s:RunOracle('peers', <count>)
diff --git a/third_party/go.tools/cmd/present/appengine.go b/third_party/go.tools/cmd/present/appengine.go
new file mode 100644
index 0000000..81dc21f
--- /dev/null
+++ b/third_party/go.tools/cmd/present/appengine.go
@@ -0,0 +1,30 @@
+// 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.
+
+// +build appengine
+
+package main
+
+import (
+	"mime"
+
+	"llvm.org/llgo/third_party/go.tools/present"
+
+	_ "llvm.org/llgo/third_party/go.tools/playground"
+)
+
+var basePath = "./present/"
+
+func init() {
+	initTemplates(basePath)
+	playScript(basePath, "HTTPTransport")
+	present.PlayEnabled = true
+
+	// App Engine has no /etc/mime.types
+	mime.AddExtensionType(".svg", "image/svg+xml")
+}
+
+func playable(c present.Code) bool {
+	return present.PlayEnabled && c.Play && c.Ext == ".go"
+}
diff --git a/third_party/go.tools/cmd/present/dir.go b/third_party/go.tools/cmd/present/dir.go
new file mode 100644
index 0000000..e8d1db9
--- /dev/null
+++ b/third_party/go.tools/cmd/present/dir.go
@@ -0,0 +1,213 @@
+// 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 main
+
+import (
+	"html/template"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	"path/filepath"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/present"
+)
+
+func init() {
+	http.HandleFunc("/", dirHandler)
+}
+
+// dirHandler serves a directory listing for the requested path, rooted at basePath.
+func dirHandler(w http.ResponseWriter, r *http.Request) {
+	if r.URL.Path == "/favicon.ico" {
+		http.Error(w, "not found", 404)
+		return
+	}
+	const base = "."
+	name := filepath.Join(base, r.URL.Path)
+	if isDoc(name) {
+		err := renderDoc(w, name)
+		if err != nil {
+			log.Println(err)
+			http.Error(w, err.Error(), 500)
+		}
+		return
+	}
+	if isDir, err := dirList(w, name); err != nil {
+		log.Println(err)
+		http.Error(w, err.Error(), 500)
+		return
+	} else if isDir {
+		return
+	}
+	http.FileServer(http.Dir(base)).ServeHTTP(w, r)
+}
+
+func isDoc(path string) bool {
+	_, ok := contentTemplate[filepath.Ext(path)]
+	return ok
+}
+
+var (
+	// dirListTemplate holds the front page template.
+	dirListTemplate *template.Template
+
+	// contentTemplate maps the presentable file extensions to the
+	// template to be executed.
+	contentTemplate map[string]*template.Template
+)
+
+func initTemplates(base string) error {
+	// Locate the template file.
+	actionTmpl := filepath.Join(base, "templates/action.tmpl")
+
+	contentTemplate = make(map[string]*template.Template)
+
+	for ext, contentTmpl := range map[string]string{
+		".slide":   "slides.tmpl",
+		".article": "article.tmpl",
+	} {
+		contentTmpl = filepath.Join(base, "templates", contentTmpl)
+
+		// Read and parse the input.
+		tmpl := present.Template()
+		tmpl = tmpl.Funcs(template.FuncMap{"playable": playable})
+		if _, err := tmpl.ParseFiles(actionTmpl, contentTmpl); err != nil {
+			return err
+		}
+		contentTemplate[ext] = tmpl
+	}
+
+	var err error
+	dirListTemplate, err = template.ParseFiles(filepath.Join(base, "templates/dir.tmpl"))
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// renderDoc reads the present file, gets its template representation,
+// and executes the template, sending output to w.
+func renderDoc(w io.Writer, docFile string) error {
+	// Read the input and build the doc structure.
+	doc, err := parse(docFile, 0)
+	if err != nil {
+		return err
+	}
+
+	// Find which template should be executed.
+	tmpl := contentTemplate[filepath.Ext(docFile)]
+
+	// Execute the template.
+	return doc.Render(w, tmpl)
+}
+
+func parse(name string, mode present.ParseMode) (*present.Doc, error) {
+	f, err := os.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	return present.Parse(f, name, 0)
+}
+
+// dirList scans the given path and writes a directory listing to w.
+// It parses the first part of each .slide file it encounters to display the
+// presentation title in the listing.
+// If the given path is not a directory, it returns (isDir == false, err == nil)
+// and writes nothing to w.
+func dirList(w io.Writer, name string) (isDir bool, err error) {
+	f, err := os.Open(name)
+	if err != nil {
+		return false, err
+	}
+	defer f.Close()
+	fi, err := f.Stat()
+	if err != nil {
+		return false, err
+	}
+	if isDir = fi.IsDir(); !isDir {
+		return false, nil
+	}
+	fis, err := f.Readdir(0)
+	if err != nil {
+		return false, err
+	}
+	d := &dirListData{Path: name}
+	for _, fi := range fis {
+		// skip the pkg directory
+		if name == "." && fi.Name() == "pkg" {
+			continue
+		}
+		e := dirEntry{
+			Name: fi.Name(),
+			Path: filepath.ToSlash(filepath.Join(name, fi.Name())),
+		}
+		if fi.IsDir() && showDir(e.Name) {
+			d.Dirs = append(d.Dirs, e)
+			continue
+		}
+		if isDoc(e.Name) {
+			if p, err := parse(e.Path, present.TitlesOnly); err != nil {
+				log.Println(err)
+			} else {
+				e.Title = p.Title
+			}
+			switch filepath.Ext(e.Path) {
+			case ".article":
+				d.Articles = append(d.Articles, e)
+			case ".slide":
+				d.Slides = append(d.Slides, e)
+			}
+		} else if showFile(e.Name) {
+			d.Other = append(d.Other, e)
+		}
+	}
+	if d.Path == "." {
+		d.Path = ""
+	}
+	sort.Sort(d.Dirs)
+	sort.Sort(d.Slides)
+	sort.Sort(d.Articles)
+	sort.Sort(d.Other)
+	return true, dirListTemplate.Execute(w, d)
+}
+
+// showFile reports whether the given file should be displayed in the list.
+func showFile(n string) bool {
+	switch filepath.Ext(n) {
+	case ".pdf":
+	case ".html":
+	case ".go":
+	default:
+		return isDoc(n)
+	}
+	return true
+}
+
+// showDir reports whether the given directory should be displayed in the list.
+func showDir(n string) bool {
+	if len(n) > 0 && (n[0] == '.' || n[0] == '_') || n == "present" {
+		return false
+	}
+	return true
+}
+
+type dirListData struct {
+	Path                          string
+	Dirs, Slides, Articles, Other dirEntrySlice
+}
+
+type dirEntry struct {
+	Name, Path, Title string
+}
+
+type dirEntrySlice []dirEntry
+
+func (s dirEntrySlice) Len() int           { return len(s) }
+func (s dirEntrySlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s dirEntrySlice) Less(i, j int) bool { return s[i].Name < s[j].Name }
diff --git a/third_party/go.tools/cmd/present/doc.go b/third_party/go.tools/cmd/present/doc.go
new file mode 100644
index 0000000..1b81c31
--- /dev/null
+++ b/third_party/go.tools/cmd/present/doc.go
@@ -0,0 +1,31 @@
+// 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.
+
+/*
+Present displays slide presentations and articles. It runs a web server that
+presents slide and article files from the current directory.
+
+It may be run as a stand-alone command or an App Engine app.
+Instructions for deployment to App Engine are in the README of the
+golang.org/x/tools repository.
+
+Usage of present:
+  -base="": base path for slide template and static resources
+  -http="127.0.0.1:3999": HTTP service address (e.g., '127.0.0.1:3999')
+  -nacl=false: use Native Client environment playground (prevents non-Go code execution)
+  -orighost="": host component of web origin URL (e.g., 'localhost')
+  -play=true: enable playground (permit execution of arbitrary user code)
+
+The setup of the Go version of NaCl is documented at:
+https://code.google.com/p/go-wiki/wiki/NativeClient
+
+Input files are named foo.extension, where "extension" defines the format of
+the generated output. The supported formats are:
+	.slide        // HTML5 slide presentation
+	.article      // article format, such as a blog post
+
+The present file format is documented by the present package:
+http://godoc.org/golang.org/x/tools/present
+*/
+package main
diff --git a/third_party/go.tools/cmd/present/local.go b/third_party/go.tools/cmd/present/local.go
new file mode 100644
index 0000000..32fef41
--- /dev/null
+++ b/third_party/go.tools/cmd/present/local.go
@@ -0,0 +1,145 @@
+// Copyright 2013 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.
+
+// +build !appengine
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/build"
+	"log"
+	"net"
+	"net/http"
+	"net/url"
+	"os"
+	"runtime"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/playground/socket"
+	"llvm.org/llgo/third_party/go.tools/present"
+)
+
+const basePkg = "llvm.org/llgo/third_party/go.tools/cmd/present"
+
+var basePath string
+
+func main() {
+	httpAddr := flag.String("http", "127.0.0.1:3999", "HTTP service address (e.g., '127.0.0.1:3999')")
+	originHost := flag.String("orighost", "", "host component of web origin URL (e.g., 'localhost')")
+	flag.StringVar(&basePath, "base", "", "base path for slide template and static resources")
+	flag.BoolVar(&present.PlayEnabled, "play", true, "enable playground (permit execution of arbitrary user code)")
+	nativeClient := flag.Bool("nacl", false, "use Native Client environment playground (prevents non-Go code execution)")
+	flag.Parse()
+
+	if basePath == "" {
+		p, err := build.Default.Import(basePkg, "", build.FindOnly)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Couldn't find gopresent files: %v\n", err)
+			fmt.Fprintf(os.Stderr, basePathMessage, basePkg)
+			os.Exit(1)
+		}
+		basePath = p.Dir
+	}
+	err := initTemplates(basePath)
+	if err != nil {
+		log.Fatalf("Failed to parse templates: %v", err)
+	}
+
+	ln, err := net.Listen("tcp", *httpAddr)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer ln.Close()
+
+	_, port, err := net.SplitHostPort(ln.Addr().String())
+	if err != nil {
+		log.Fatal(err)
+	}
+	origin := &url.URL{Scheme: "http"}
+	if *originHost != "" {
+		origin.Host = net.JoinHostPort(*originHost, port)
+	} else if ln.Addr().(*net.TCPAddr).IP.IsUnspecified() {
+		name, _ := os.Hostname()
+		origin.Host = net.JoinHostPort(name, port)
+	} else {
+		reqHost, reqPort, err := net.SplitHostPort(*httpAddr)
+		if err != nil {
+			log.Fatal(err)
+		}
+		if reqPort == "0" {
+			origin.Host = net.JoinHostPort(reqHost, port)
+		} else {
+			origin.Host = *httpAddr
+		}
+	}
+
+	if present.PlayEnabled {
+		if *nativeClient {
+			socket.RunScripts = false
+			socket.Environ = func() []string {
+				if runtime.GOARCH == "amd64" {
+					return environ("GOOS=nacl", "GOARCH=amd64p32")
+				}
+				return environ("GOOS=nacl")
+			}
+		}
+		playScript(basePath, "SocketTransport")
+		http.Handle("/socket", socket.NewHandler(origin))
+	}
+	http.Handle("/static/", http.FileServer(http.Dir(basePath)))
+
+	if !ln.Addr().(*net.TCPAddr).IP.IsLoopback() &&
+		present.PlayEnabled && !*nativeClient {
+		log.Print(localhostWarning)
+	}
+
+	log.Printf("Open your web browser and visit %s", origin.String())
+	log.Fatal(http.Serve(ln, nil))
+}
+
+func playable(c present.Code) bool {
+	return present.PlayEnabled && c.Play
+}
+
+func environ(vars ...string) []string {
+	env := os.Environ()
+	for _, r := range vars {
+		k := strings.SplitAfter(r, "=")[0]
+		var found bool
+		for i, v := range env {
+			if strings.HasPrefix(v, k) {
+				env[i] = r
+				found = true
+			}
+		}
+		if !found {
+			env = append(env, r)
+		}
+	}
+	return env
+}
+
+const basePathMessage = `
+By default, gopresent locates the slide template files and associated
+static content by looking for a %q package
+in your Go workspaces (GOPATH).
+
+You may use the -base flag to specify an alternate location.
+`
+
+const localhostWarning = `
+WARNING!  WARNING!  WARNING!
+
+The present server appears to be listening on an address that is not localhost.
+Anyone with access to this address and port will have access to this machine as
+the user running present.
+
+To avoid this message, listen on localhost or run with -play=false.
+
+If you don't understand this message, hit Control-C to terminate this process.
+
+WARNING!  WARNING!  WARNING!
+`
diff --git a/third_party/go.tools/cmd/present/play.go b/third_party/go.tools/cmd/present/play.go
new file mode 100644
index 0000000..9613503
--- /dev/null
+++ b/third_party/go.tools/cmd/present/play.go
@@ -0,0 +1,43 @@
+// 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 main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"path/filepath"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/static"
+)
+
+var scripts = []string{"jquery.js", "jquery-ui.js", "playground.js", "play.js"}
+
+// playScript registers an HTTP handler at /play.js that serves all the
+// scripts specified by the variable above, and appends a line that
+// initializes the playground with the specified transport.
+func playScript(root, transport string) {
+	modTime := time.Now()
+	var buf bytes.Buffer
+	for _, p := range scripts {
+		if s, ok := static.Files[p]; ok {
+			buf.WriteString(s)
+			continue
+		}
+		b, err := ioutil.ReadFile(filepath.Join(root, "static", p))
+		if err != nil {
+			panic(err)
+		}
+		buf.Write(b)
+	}
+	fmt.Fprintf(&buf, "\ninitPlayground(new %v());\n", transport)
+	b := buf.Bytes()
+	http.HandleFunc("/play.js", func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-type", "application/javascript")
+		http.ServeContent(w, r, "", modTime, bytes.NewReader(b))
+	})
+}
diff --git a/third_party/go.tools/cmd/present/static/article.css b/third_party/go.tools/cmd/present/static/article.css
new file mode 100644
index 0000000..e6ab1e8
--- /dev/null
+++ b/third_party/go.tools/cmd/present/static/article.css
@@ -0,0 +1,136 @@
+body {
+	margin: 0;
+	font-family: Helvetica, Arial, sans-serif;
+	font-size: 16px;
+}
+pre,
+code {
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+pre {
+	line-height: 18px;
+	margin: 0;
+	padding: 0;
+}
+a {
+	color: #375EAB;
+	text-decoration: none;
+}
+a:hover {
+	text-decoration: underline;
+}
+p, ul, ol {
+	margin: 20px;
+}
+
+h1, h2, h3, h4 {
+	margin: 20px 0;
+	padding: 0;
+	color: #375EAB;
+	font-weight: bold;
+}
+h1 {
+	font-size: 24px;
+}
+h2 {
+	font-size: 20px;
+	background: #E0EBF5;
+	padding: 2px 5px;
+}
+h3 {
+	font-size: 20px;
+}
+h3, h4 {
+	margin: 20px 5px;
+}
+h4 {
+	font-size: 16px;
+}
+
+div#heading {
+	float: left;
+	margin: 0 0 10px 0;
+	padding: 21px 0;
+	font-size: 20px;
+	font-weight: normal;
+}
+
+div#topbar {
+	background: #E0EBF5;
+	height: 64px;
+	overflow: hidden;
+}
+
+body {
+	text-align: center;
+}
+div#page {
+	width: 100%;
+}
+div#page > .container,
+div#topbar > .container {
+	text-align: left;
+	margin-left: auto;
+	margin-right: auto;
+	padding: 0 20px;
+	width: 900px;
+}
+div#page.wide > .container,
+div#topbar.wide > .container {
+	width: auto;
+}
+
+div#footer {
+	text-align: center;
+	color: #666;
+	font-size: 14px;
+	margin: 40px 0;
+}
+
+.author p {
+	margin: 20, 0, 0, 0px;
+}
+
+div.code,
+div.output {
+	margin: 20px;
+	padding: 10px;
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+div.code { background: #e9e9e9; }
+div.output { background: black; }
+div.output .stdout { color: #e6e6e6; }
+div.output .stderr { color: rgb(244, 74, 63); }
+div.output .system { color: rgb(255, 209, 77) }
+
+.buttons {
+	margin-left: 20px;
+}
+div.output .buttons {
+	margin-left: 0;
+	margin-bottom: 10px;
+}
+
+#toc {
+	float: right;
+	margin: 0px 10px;
+	padding: 10px;
+	border: 1px solid #e5ecf9; 
+	background-color: white;
+	max-width: 33%;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+#toc ul, #toc a {
+	list-style-type: none;
+	padding-left: 10px;
+	color: black;
+	margin: 0px;
+}
diff --git a/third_party/go.tools/cmd/present/static/dir.css b/third_party/go.tools/cmd/present/static/dir.css
new file mode 100644
index 0000000..97587e6
--- /dev/null
+++ b/third_party/go.tools/cmd/present/static/dir.css
@@ -0,0 +1,186 @@
+/* copied from $GOROOT/doc/style.css */
+
+body {
+	margin: 0;
+	font-family: Helvetica, Arial, sans-serif;
+	font-size: 16px;
+}
+pre,
+code {
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+pre {
+	line-height: 18px;
+}
+pre .comment {
+	color: #375EAB;
+}
+pre .highlight,
+pre .highlight-comment,
+pre .selection-highlight,
+pre .selection-highlight-comment {
+	background: #FFFF00;
+}
+pre .selection,
+pre .selection-comment {
+	background: #FF9632;
+}
+pre .ln {
+	color: #999;
+}
+body {
+	color: #222;
+}
+a,
+.exampleHeading .text {
+	color: #375EAB;
+	text-decoration: none;
+}
+a:hover,
+.exampleHeading .text:hover {
+	text-decoration: underline;
+}
+p,
+pre,
+ul,
+ol {
+	margin: 20px;
+}
+pre {
+	background: #e9e9e9;
+	padding: 10px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+h1,
+h2,
+h3,
+h4,
+.rootHeading {
+	margin: 20px 0;
+	padding: 0;
+	color: #375EAB;
+	font-weight: bold;
+}
+h1 {
+	font-size: 24px;
+}
+h2 {
+	font-size: 20px;
+	background: #E0EBF5;
+	padding: 2px 5px;
+}
+h3 {
+	font-size: 20px;
+}
+h3,
+h4 {
+	margin: 20px 5px;
+}
+h4 {
+	font-size: 16px;
+}
+
+dl {
+	margin: 20px;
+}
+dd {
+	margin: 2px 20px;
+}
+dl,
+dd {
+	font-size: 14px;
+}
+div#nav table td {
+	vertical-align: top;
+}
+
+div#heading {
+	float: left;
+	margin: 0 0 10px 0;
+	padding: 21px 0;
+	font-size: 20px;
+	font-weight: normal;
+}
+div#heading a {
+	color: #222;
+	text-decoration: none;
+}
+
+div#topbar {
+	background: #E0EBF5;
+	height: 64px;
+}
+
+body {
+	text-align: center;
+}
+div#page,
+div#topbar > .container {
+	clear: both;
+	text-align: left;
+	margin-left: auto;
+	margin-right: auto;
+	padding: 0 20px;
+	width: 900px;
+}
+div#page.wide,
+div#topbar > .wide {
+	width: auto;
+}
+div#plusone {
+	float: right;
+}
+
+div#footer {
+	color: #666;
+	font-size: 14px;
+	margin: 40px 0;
+}
+
+div#menu > a,
+div#menu > input {
+	padding: 10px;
+
+	text-decoration: none;
+	font-size: 16px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+div#menu > a,
+div#menu > input {
+	border: 1px solid #375EAB;
+}
+div#menu > a {
+	color: white;
+	background: #375EAB;
+}
+
+div#menu {
+	float: right;
+	min-width: 590px;
+	padding: 10px 0;
+	text-align: right;
+}
+div#menu > a {
+	margin-right: 5px;
+	margin-bottom: 10px;
+
+	padding: 10px;
+}
+div#menu > input {
+	position: relative;
+	top: 1px;
+	width: 60px;
+	background: white;
+	color: #222;
+}
+div#menu > input.inactive {
+	color: #999;
+}
diff --git a/third_party/go.tools/cmd/present/static/dir.js b/third_party/go.tools/cmd/present/static/dir.js
new file mode 100644
index 0000000..5b0c37e
--- /dev/null
+++ b/third_party/go.tools/cmd/present/static/dir.js
@@ -0,0 +1,41 @@
+// 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.
+
+// copied from $GOROOT/doc/godocs.js
+
+function bindEvent(el, e, fn) {
+  if (el.addEventListener){
+    el.addEventListener(e, fn, false);
+  } else if (el.attachEvent){
+    el.attachEvent('on'+e, fn);
+  }
+}
+
+function godocs_bindSearchEvents() {
+  var search = document.getElementById('search');
+  if (!search) {
+    // no search box (index disabled)
+    return;
+  }
+  function clearInactive() {
+    if (search.className == "inactive") {
+      search.value = "";
+      search.className = "";
+    }
+  }
+  function restoreInactive() {
+    if (search.value !== "") {
+      return;
+    }
+    if (search.type != "search") {
+      search.value = search.getAttribute("placeholder");
+    }
+    search.className = "inactive";
+  }
+  restoreInactive();
+  bindEvent(search, 'focus', clearInactive);
+  bindEvent(search, 'blur', restoreInactive);
+}
+
+bindEvent(window, 'load', godocs_bindSearchEvents);
diff --git a/third_party/go.tools/cmd/present/static/favicon.ico b/third_party/go.tools/cmd/present/static/favicon.ico
new file mode 100644
index 0000000..48854ff
--- /dev/null
+++ b/third_party/go.tools/cmd/present/static/favicon.ico
Binary files differ
diff --git a/third_party/go.tools/cmd/present/static/jquery-ui.js b/third_party/go.tools/cmd/present/static/jquery-ui.js
new file mode 100644
index 0000000..f391938
--- /dev/null
+++ b/third_party/go.tools/cmd/present/static/jquery-ui.js
@@ -0,0 +1,6 @@
+/*! jQuery UI - v1.10.2 - 2013-03-20
+* http://jqueryui.com
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.resizable.js
+* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
+
+(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("<div class='ui-resizable-handle "+a+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidth<e.width,a=i(e.height)&&t.maxHeight&&t.maxHeight<e.height,o=i(e.width)&&t.minWidth&&t.minWidth>e.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);
\ No newline at end of file
diff --git a/third_party/go.tools/cmd/present/static/print.css b/third_party/go.tools/cmd/present/static/print.css
new file mode 100644
index 0000000..6c58257
--- /dev/null
+++ b/third_party/go.tools/cmd/present/static/print.css
@@ -0,0 +1,51 @@
+/* set page layout */
+@page {
+  size: A4 landscape;
+}
+
+body { 
+  display: block !important;
+}
+
+.slides {
+  left: 0;
+  top: 0;
+}
+
+.slides > article {
+  position: relative;
+
+  left: 0;
+  top: 0;
+
+  margin: 0 !important;
+  page-break-inside: avoid;
+
+  text-shadow: none; /* disable shadow */
+
+  display: block !important;
+  transform: translate(0) !important;
+  -o-transform: translate(0) !important;
+  -moz-transform: translate(0) !important;
+  -webkit-transform: translate3d(0, 0, 0) !important;
+}
+
+div.code {
+  background: rgb(240, 240, 240);
+}
+
+/* hide click areas */
+.slide-area, #prev-slide-area, #next-slide-area {
+  display: none;
+}
+
+/* add explicit links */
+a:link:after, a:visited:after {
+ content: " (" attr(href) ") ";
+ font-size: 50%;
+}
+
+/* white background */
+body {
+  background: rgb(255,255,255) !important;
+}
diff --git a/third_party/go.tools/cmd/present/static/slides.js b/third_party/go.tools/cmd/present/static/slides.js
new file mode 100644
index 0000000..ee54c94
--- /dev/null
+++ b/third_party/go.tools/cmd/present/static/slides.js
@@ -0,0 +1,518 @@
+// 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.
+
+var PERMANENT_URL_PREFIX = '/static/';
+
+var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next'];
+
+var PM_TOUCH_SENSITIVITY = 15;
+
+var curSlide;
+
+/* ---------------------------------------------------------------------- */
+/* classList polyfill by Eli Grey
+ * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
+
+if (typeof document !== "undefined" && !("classList" in document.createElement("a"))) {
+
+(function (view) {
+
+var
+    classListProp = "classList"
+  , protoProp = "prototype"
+  , elemCtrProto = (view.HTMLElement || view.Element)[protoProp]
+  , objCtr = Object
+    strTrim = String[protoProp].trim || function () {
+    return this.replace(/^\s+|\s+$/g, "");
+  }
+  , arrIndexOf = Array[protoProp].indexOf || function (item) {
+    for (var i = 0, len = this.length; i < len; i++) {
+      if (i in this && this[i] === item) {
+        return i;
+      }
+    }
+    return -1;
+  }
+  // Vendors: please allow content code to instantiate DOMExceptions
+  , DOMEx = function (type, message) {
+    this.name = type;
+    this.code = DOMException[type];
+    this.message = message;
+  }
+  , checkTokenAndGetIndex = function (classList, token) {
+    if (token === "") {
+      throw new DOMEx(
+          "SYNTAX_ERR"
+        , "An invalid or illegal string was specified"
+      );
+    }
+    if (/\s/.test(token)) {
+      throw new DOMEx(
+          "INVALID_CHARACTER_ERR"
+        , "String contains an invalid character"
+      );
+    }
+    return arrIndexOf.call(classList, token);
+  }
+  , ClassList = function (elem) {
+    var
+        trimmedClasses = strTrim.call(elem.className)
+      , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
+    ;
+    for (var i = 0, len = classes.length; i < len; i++) {
+      this.push(classes[i]);
+    }
+    this._updateClassName = function () {
+      elem.className = this.toString();
+    };
+  }
+  , classListProto = ClassList[protoProp] = []
+  , classListGetter = function () {
+    return new ClassList(this);
+  }
+;
+// Most DOMException implementations don't allow calling DOMException's toString()
+// on non-DOMExceptions. Error's toString() is sufficient here.
+DOMEx[protoProp] = Error[protoProp];
+classListProto.item = function (i) {
+  return this[i] || null;
+};
+classListProto.contains = function (token) {
+  token += "";
+  return checkTokenAndGetIndex(this, token) !== -1;
+};
+classListProto.add = function (token) {
+  token += "";
+  if (checkTokenAndGetIndex(this, token) === -1) {
+    this.push(token);
+    this._updateClassName();
+  }
+};
+classListProto.remove = function (token) {
+  token += "";
+  var index = checkTokenAndGetIndex(this, token);
+  if (index !== -1) {
+    this.splice(index, 1);
+    this._updateClassName();
+  }
+};
+classListProto.toggle = function (token) {
+  token += "";
+  if (checkTokenAndGetIndex(this, token) === -1) {
+    this.add(token);
+  } else {
+    this.remove(token);
+  }
+};
+classListProto.toString = function () {
+  return this.join(" ");
+};
+
+if (objCtr.defineProperty) {
+  var classListPropDesc = {
+      get: classListGetter
+    , enumerable: true
+    , configurable: true
+  };
+  try {
+    objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+  } catch (ex) { // IE 8 doesn't support enumerable:true
+    if (ex.number === -0x7FF5EC54) {
+      classListPropDesc.enumerable = false;
+      objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+    }
+  }
+} else if (objCtr[protoProp].__defineGetter__) {
+  elemCtrProto.__defineGetter__(classListProp, classListGetter);
+}
+
+}(self));
+
+}
+/* ---------------------------------------------------------------------- */
+
+/* Slide movement */
+
+function getSlideEl(no) {
+  if ((no < 0) || (no >= slideEls.length)) {
+    return null;
+  } else {
+    return slideEls[no];
+  }
+};
+
+function updateSlideClass(slideNo, className) {
+  var el = getSlideEl(slideNo);
+
+  if (!el) {
+    return;
+  }
+
+  if (className) {
+    el.classList.add(className);
+  }
+
+  for (var i in SLIDE_CLASSES) {
+    if (className != SLIDE_CLASSES[i]) {
+      el.classList.remove(SLIDE_CLASSES[i]);
+    }
+  }
+};
+
+function updateSlides() {
+  if (window.trackPageview) window.trackPageview();
+
+  for (var i = 0; i < slideEls.length; i++) {
+    switch (i) {
+      case curSlide - 2:
+        updateSlideClass(i, 'far-past');
+        break;
+      case curSlide - 1:
+        updateSlideClass(i, 'past');
+        break;
+      case curSlide:
+        updateSlideClass(i, 'current');
+        break;
+      case curSlide + 1:
+        updateSlideClass(i, 'next');
+        break;
+      case curSlide + 2:
+        updateSlideClass(i, 'far-next');
+        break;
+      default:
+        updateSlideClass(i);
+        break;
+    }
+  }
+
+  triggerLeaveEvent(curSlide - 1);
+  triggerEnterEvent(curSlide);
+
+  window.setTimeout(function() {
+    // Hide after the slide
+    disableSlideFrames(curSlide - 2);
+  }, 301);
+
+  enableSlideFrames(curSlide - 1);
+  enableSlideFrames(curSlide + 2);
+
+  updateHash();
+};
+
+function prevSlide() {
+  if (curSlide > 0) {
+    curSlide--;
+
+    updateSlides();
+  }
+};
+
+function nextSlide() {
+  if (curSlide < slideEls.length - 1) {
+    curSlide++;
+
+    updateSlides();
+  }
+};
+
+/* Slide events */
+
+function triggerEnterEvent(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var onEnter = el.getAttribute('onslideenter');
+  if (onEnter) {
+    new Function(onEnter).call(el);
+  }
+
+  var evt = document.createEvent('Event');
+  evt.initEvent('slideenter', true, true);
+  evt.slideNumber = no + 1; // Make it readable
+
+  el.dispatchEvent(evt);
+};
+
+function triggerLeaveEvent(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var onLeave = el.getAttribute('onslideleave');
+  if (onLeave) {
+    new Function(onLeave).call(el);
+  }
+
+  var evt = document.createEvent('Event');
+  evt.initEvent('slideleave', true, true);
+  evt.slideNumber = no + 1; // Make it readable
+
+  el.dispatchEvent(evt);
+};
+
+/* Touch events */
+
+function handleTouchStart(event) {
+  if (event.touches.length == 1) {
+    touchDX = 0;
+    touchDY = 0;
+
+    touchStartX = event.touches[0].pageX;
+    touchStartY = event.touches[0].pageY;
+
+    document.body.addEventListener('touchmove', handleTouchMove, true);
+    document.body.addEventListener('touchend', handleTouchEnd, true);
+  }
+};
+
+function handleTouchMove(event) {
+  if (event.touches.length > 1) {
+    cancelTouch();
+  } else {
+    touchDX = event.touches[0].pageX - touchStartX;
+    touchDY = event.touches[0].pageY - touchStartY;
+    event.preventDefault();
+  }
+};
+
+function handleTouchEnd(event) {
+  var dx = Math.abs(touchDX);
+  var dy = Math.abs(touchDY);
+
+  if ((dx > PM_TOUCH_SENSITIVITY) && (dy < (dx * 2 / 3))) {
+    if (touchDX > 0) {
+      prevSlide();
+    } else {
+      nextSlide();
+    }
+  }
+
+  cancelTouch();
+};
+
+function cancelTouch() {
+  document.body.removeEventListener('touchmove', handleTouchMove, true);
+  document.body.removeEventListener('touchend', handleTouchEnd, true);
+};
+
+/* Preloading frames */
+
+function disableSlideFrames(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var frames = el.getElementsByTagName('iframe');
+  for (var i = 0, frame; frame = frames[i]; i++) {
+    disableFrame(frame);
+  }
+};
+
+function enableSlideFrames(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var frames = el.getElementsByTagName('iframe');
+  for (var i = 0, frame; frame = frames[i]; i++) {
+    enableFrame(frame);
+  }
+};
+
+function disableFrame(frame) {
+  frame.src = 'about:blank';
+};
+
+function enableFrame(frame) {
+  var src = frame._src;
+
+  if (frame.src != src && src != 'about:blank') {
+    frame.src = src;
+  }
+};
+
+function setupFrames() {
+  var frames = document.querySelectorAll('iframe');
+  for (var i = 0, frame; frame = frames[i]; i++) {
+    frame._src = frame.src;
+    disableFrame(frame);
+  }
+
+  enableSlideFrames(curSlide);
+  enableSlideFrames(curSlide + 1);
+  enableSlideFrames(curSlide + 2);
+};
+
+function setupInteraction() {
+  /* Clicking and tapping */
+
+  var el = document.createElement('div');
+  el.className = 'slide-area';
+  el.id = 'prev-slide-area';
+  el.addEventListener('click', prevSlide, false);
+  document.querySelector('section.slides').appendChild(el);
+
+  var el = document.createElement('div');
+  el.className = 'slide-area';
+  el.id = 'next-slide-area';
+  el.addEventListener('click', nextSlide, false);
+  document.querySelector('section.slides').appendChild(el);
+
+  /* Swiping */
+
+  document.body.addEventListener('touchstart', handleTouchStart, false);
+}
+
+/* Hash functions */
+
+function getCurSlideFromHash() {
+  var slideNo = parseInt(location.hash.substr(1));
+
+  if (slideNo) {
+    curSlide = slideNo - 1;
+  } else {
+    curSlide = 0;
+  }
+};
+
+function updateHash() {
+  location.replace('#' + (curSlide + 1));
+};
+
+/* Event listeners */
+
+function handleBodyKeyDown(event) {
+  // If we're in a code element, only handle pgup/down.
+  var inCode = event.target.classList.contains("code");
+
+  switch (event.keyCode) {
+    case 39: // right arrow
+    case 13: // Enter
+    case 32: // space
+      if (inCode) break;
+    case 34: // PgDn
+      nextSlide();
+      event.preventDefault();
+      break;
+
+    case 37: // left arrow
+    case 8: // Backspace
+      if (inCode) break;
+    case 33: // PgUp
+      prevSlide();
+      event.preventDefault();
+      break;
+
+    case 40: // down arrow
+      if (inCode) break;
+      nextSlide();
+      event.preventDefault();
+      break;
+
+    case 38: // up arrow
+      if (inCode) break;
+      prevSlide();
+      event.preventDefault();
+      break;
+  }
+};
+
+function addEventListeners() {
+  document.addEventListener('keydown', handleBodyKeyDown, false);
+};
+
+/* Initialization */
+
+function addFontStyle() {
+  var el = document.createElement('link');
+  el.rel = 'stylesheet';
+  el.type = 'text/css';
+  el.href = '//fonts.googleapis.com/css?family=' +
+            'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono';
+
+  document.body.appendChild(el);
+};
+
+function addGeneralStyle() {
+  var el = document.createElement('link');
+  el.rel = 'stylesheet';
+  el.type = 'text/css';
+  el.href = PERMANENT_URL_PREFIX + 'styles.css';
+  document.body.appendChild(el);
+
+  var el = document.createElement('meta');
+  el.name = 'viewport';
+  el.content = 'width=1100,height=750';
+  document.querySelector('head').appendChild(el);
+
+  var el = document.createElement('meta');
+  el.name = 'apple-mobile-web-app-capable';
+  el.content = 'yes';
+  document.querySelector('head').appendChild(el);
+};
+
+function addPrintStyle() {
+  var el = document.createElement('link');
+  el.rel = 'stylesheet';
+  el.type = 'text/css';
+  el.media = "print";
+  el.href = PERMANENT_URL_PREFIX + 'print.css';
+  document.body.appendChild(el);
+};
+
+function handleDomLoaded() {
+  slideEls = document.querySelectorAll('section.slides > article');
+
+  setupFrames();
+
+  addFontStyle();
+  addGeneralStyle();
+  addPrintStyle();
+  addEventListeners();
+
+  updateSlides();
+
+  setupInteraction();
+
+  document.body.classList.add('loaded');
+};
+
+function initialize() {
+  getCurSlideFromHash();
+
+  if (window['_DEBUG']) {
+    PERMANENT_URL_PREFIX = '../';
+  }
+
+  if (window['_DCL']) {
+    handleDomLoaded();
+  } else {
+    document.addEventListener('DOMContentLoaded', handleDomLoaded, false);
+  }
+}
+
+// If ?debug exists then load the script relative instead of absolute
+if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {
+  document.addEventListener('DOMContentLoaded', function() {
+    // Avoid missing the DomContentLoaded event
+    window['_DCL'] = true
+  }, false);
+
+  window['_DEBUG'] = true;
+  var script = document.createElement('script');
+  script.type = 'text/javascript';
+  script.src = '../slides.js';
+  var s = document.getElementsByTagName('script')[0];
+  s.parentNode.insertBefore(script, s);
+
+  // Remove this script
+  s.parentNode.removeChild(s);
+} else {
+  initialize();
+}
diff --git a/third_party/go.tools/cmd/present/static/styles.css b/third_party/go.tools/cmd/present/static/styles.css
new file mode 100644
index 0000000..b3d829a
--- /dev/null
+++ b/third_party/go.tools/cmd/present/static/styles.css
@@ -0,0 +1,461 @@
+/* Framework */
+
+html {
+  height: 100%;
+}
+
+body {
+  margin: 0;
+  padding: 0;
+
+  display: block !important;
+
+  height: 100%;
+  min-height: 740px;
+
+  overflow-x: hidden;
+  overflow-y: auto;
+
+  background: rgb(215, 215, 215);
+  background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
+  background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
+  background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
+  background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgb(240, 240, 240)), to(rgb(190, 190, 190)));
+
+  -webkit-font-smoothing: antialiased;
+}
+
+.slides {
+  width: 100%;
+  height: 100%;
+  left: 0;
+  top: 0;
+
+  position: absolute;
+
+  -webkit-transform: translate3d(0, 0, 0);
+}
+
+.slides > article {
+  display: block;
+
+  position: absolute;
+  overflow: hidden;
+
+  width: 900px;
+  height: 700px;
+
+  left: 50%;
+  top: 50%;
+
+  margin-left: -450px;
+  margin-top: -350px;
+
+  padding: 40px 60px;
+
+  box-sizing: border-box;
+  -o-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  -webkit-box-sizing: border-box;
+
+  border-radius: 10px;
+  -o-border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+
+  background-color: white;
+
+  border: 1px solid rgba(0, 0, 0, .3);
+
+  transition: transform .3s ease-out;
+  -o-transition: -o-transform .3s ease-out;
+  -moz-transition: -moz-transform .3s ease-out;
+  -webkit-transition: -webkit-transform .3s ease-out;
+}
+.slides.layout-widescreen > article {
+  margin-left: -550px;
+  width: 1100px;
+}
+.slides.layout-faux-widescreen > article {
+  margin-left: -550px;
+  width: 1100px;
+
+  padding: 40px 160px;
+}
+
+.slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
+.slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
+  background-position-x: 0, 840px;
+}
+
+/* Clickable/tappable areas */
+
+.slide-area {
+  z-index: 1000;
+
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 150px;
+  height: 700px;
+
+  left: 50%;
+  top: 50%;
+
+  cursor: pointer;
+  margin-top: -350px;
+
+  tap-highlight-color: transparent;
+  -o-tap-highlight-color: transparent;
+  -moz-tap-highlight-color: transparent;
+  -webkit-tap-highlight-color: transparent;
+}
+#prev-slide-area {
+  margin-left: -550px;
+}
+#next-slide-area {
+  margin-left: 400px;
+}
+.slides.layout-widescreen #prev-slide-area,
+.slides.layout-faux-widescreen #prev-slide-area {
+  margin-left: -650px;
+}
+.slides.layout-widescreen #next-slide-area,
+.slides.layout-faux-widescreen #next-slide-area {
+  margin-left: 500px;
+}
+
+/* Slides */
+
+.slides > article {
+  display: none;
+}
+.slides > article.far-past {
+  display: block;
+  transform: translate(-2040px);
+  -o-transform: translate(-2040px);
+  -moz-transform: translate(-2040px);
+  -webkit-transform: translate3d(-2040px, 0, 0);
+}
+.slides > article.past {
+  display: block;
+  transform: translate(-1020px);
+  -o-transform: translate(-1020px);
+  -moz-transform: translate(-1020px);
+  -webkit-transform: translate3d(-1020px, 0, 0);
+}
+.slides > article.current {
+  display: block;
+  transform: translate(0);
+  -o-transform: translate(0);
+  -moz-transform: translate(0);
+  -webkit-transform: translate3d(0, 0, 0);
+}
+.slides > article.next {
+  display: block;
+  transform: translate(1020px);
+  -o-transform: translate(1020px);
+  -moz-transform: translate(1020px);
+  -webkit-transform: translate3d(1020px, 0, 0);
+}
+.slides > article.far-next {
+  display: block;
+  transform: translate(2040px);
+  -o-transform: translate(2040px);
+  -moz-transform: translate(2040px);
+  -webkit-transform: translate3d(2040px, 0, 0);
+}
+
+.slides.layout-widescreen > article.far-past,
+.slides.layout-faux-widescreen > article.far-past {
+  display: block;
+  transform: translate(-2260px);
+  -o-transform: translate(-2260px);
+  -moz-transform: translate(-2260px);
+  -webkit-transform: translate3d(-2260px, 0, 0);
+}
+.slides.layout-widescreen > article.past,
+.slides.layout-faux-widescreen > article.past {
+  display: block;
+  transform: translate(-1130px);
+  -o-transform: translate(-1130px);
+  -moz-transform: translate(-1130px);
+  -webkit-transform: translate3d(-1130px, 0, 0);
+}
+.slides.layout-widescreen > article.current,
+.slides.layout-faux-widescreen > article.current {
+  display: block;
+  transform: translate(0);
+  -o-transform: translate(0);
+  -moz-transform: translate(0);
+  -webkit-transform: translate3d(0, 0, 0);
+}
+.slides.layout-widescreen > article.next,
+.slides.layout-faux-widescreen > article.next {
+  display: block;
+  transform: translate(1130px);
+  -o-transform: translate(1130px);
+  -moz-transform: translate(1130px);
+  -webkit-transform: translate3d(1130px, 0, 0);
+}
+.slides.layout-widescreen > article.far-next,
+.slides.layout-faux-widescreen > article.far-next {
+  display: block;
+  transform: translate(2260px);
+  -o-transform: translate(2260px);
+  -moz-transform: translate(2260px);
+  -webkit-transform: translate3d(2260px, 0, 0);
+}
+
+/* Styles for slides */
+
+.slides > article {
+  font-family: 'Open Sans', Arial, sans-serif;
+
+  color: black;
+  text-shadow: 0 1px 1px rgba(0, 0, 0, .1);
+
+  font-size: 26px;
+  line-height: 36px;
+
+  letter-spacing: -1px;
+}
+
+b {
+  font-weight: 600;
+}
+
+a {
+  color: rgb(0, 102, 204);
+  text-decoration: none;
+}
+a:visited {
+  color: rgba(0, 102, 204, .75);
+}
+a:hover {
+  color: black;
+}
+
+p {
+  margin: 0;
+  padding: 0;
+
+  margin-top: 20px;
+}
+p:first-child {
+  margin-top: 0;
+}
+
+h1 {
+  font-size: 60px;
+  line-height: 60px;
+
+  padding: 0;
+  margin: 0;
+  margin-top: 200px;
+  margin-bottom: 5px;
+  padding-right: 40px;
+
+  font-weight: 600;
+
+  letter-spacing: -3px;
+
+  color: rgb(51, 51, 51);
+}
+
+h2 {
+  font-size: 45px;
+  line-height: 45px;
+
+  position: absolute;
+  bottom: 150px;
+
+  padding: 0;
+  margin: 0;
+  padding-right: 40px;
+
+  font-weight: 600;
+
+  letter-spacing: -2px;
+
+  color: rgb(51, 51, 51);
+}
+
+h3 {
+  font-size: 30px;
+  line-height: 36px;
+
+  padding: 0;
+  margin: 0;
+  padding-right: 40px;
+
+  font-weight: 600;
+
+  letter-spacing: -1px;
+
+  color: rgb(51, 51, 51);
+}
+
+ul {
+  margin: 0;
+  padding: 0;
+  margin-top: 20px;
+  margin-left: 1.5em;
+}
+li {
+  padding: 0;
+  margin: 0 0 .5em 0;
+}
+
+div.code {
+  padding: 5px 10px;
+  margin-top: 20px;
+  margin-bottom: 20px;
+  overflow: hidden;
+
+  background: rgb(240, 240, 240);
+  border: 1px solid rgb(224, 224, 224);
+}
+pre {
+  margin: 0;
+  padding: 0;
+
+  font-family: 'Droid Sans Mono', 'Courier New', monospace;
+  font-size: 18px;
+  line-height: 24px;
+  letter-spacing: -1px;
+
+  color: black;
+}
+
+code {
+  font-size: 95%;
+  font-family: 'Droid Sans Mono', 'Courier New', monospace;
+
+  color: black;
+}
+
+article > .image {
+  	text-align: center;
+    margin-top: 40px;
+}
+
+table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-top: 40px;
+}
+th {
+  font-weight: 600;
+  text-align: left;
+}
+td,
+th {
+  border: 1px solid rgb(224, 224, 224);
+  padding: 5px 10px;
+  vertical-align: top;
+}
+
+p.link {
+  margin-left: 20px;
+}
+
+/* Code */
+div.code {
+  outline: 0px solid transparent;
+}
+div.playground {
+  position: relative;
+}
+div.output {
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  right: 40px;
+  bottom: 40px;
+  background: #202020;
+  padding: 5px 10px;
+  z-index: 2;
+
+  border-radius: 10px;
+  -o-border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+
+}
+div.output pre {
+  margin: 0;
+  padding: 0;
+  background: none;
+  border: none;
+  width: 100%;
+  height: 100%;
+  overflow: auto;
+}
+div.output .stdout, div.output pre {
+  color: #e6e6e6;
+}
+div.output .stderr, div.output .error {
+  color: rgb(255, 200, 200);
+}
+div.output .system, div.output .exit {
+  color: rgb(255, 230, 120)
+}
+.buttons {
+  position: relative;
+  float: right;
+  top: -60px;
+  right: 10px;
+}
+div.output .buttons {
+  position: absolute;
+  float: none;
+  top: auto;
+  right: 5px;
+  bottom: 5px;
+}
+
+/* Presenter details */
+.presenter {
+	margin-top: 20px;
+}
+.presenter p,
+.presenter .link {
+	margin: 0;
+	font-size: 28px;
+	line-height: 1.2em;
+}
+
+/* Output resize details */
+.ui-resizable-handle {
+  position: absolute;
+}
+.ui-resizable-n {
+  cursor: n-resize;
+  height: 7px;
+  width: 100%;
+  top: -5px;
+  left: 0;
+}
+.ui-resizable-w {
+  cursor: w-resize;
+  width: 7px;
+  left: -5px;
+  top: 0;
+  height: 100%;
+}
+.ui-resizable-nw {
+  cursor: nw-resize;
+  width: 9px;
+  height: 9px;
+  left: -5px;
+  top: -5px;
+}
+iframe {
+  border: none;
+}
+figcaption {
+  color: #666;
+  text-align: center;
+  font-size: 0.75em;
+}
\ No newline at end of file
diff --git a/third_party/go.tools/cmd/present/templates/action.tmpl b/third_party/go.tools/cmd/present/templates/action.tmpl
new file mode 100644
index 0000000..2893058
--- /dev/null
+++ b/third_party/go.tools/cmd/present/templates/action.tmpl
@@ -0,0 +1,48 @@
+{/*
+This is the action template.
+It determines how the formatting actions are rendered.
+*/}
+
+{{define "section"}}
+  <h{{len .Number}} id="TOC_{{.FormattedNumber}}">{{.FormattedNumber}} {{.Title}}</h{{len .Number}}>
+  {{range .Elem}}{{elem $.Template .}}{{end}}
+{{end}}
+
+{{define "list"}}
+  <ul>
+  {{range .Bullet}}
+    <li>{{style .}}</li>
+  {{end}}
+  </ul>
+{{end}}
+
+{{define "text"}}
+  {{if .Pre}}
+  <div class="code"><pre>{{range .Lines}}{{.}}{{end}}</pre></div>
+  {{else}}
+  <p>
+    {{range $i, $l := .Lines}}{{if $i}}{{template "newline"}}
+    {{end}}{{style $l}}{{end}}
+  </p>
+  {{end}}
+{{end}}
+
+{{define "code"}}
+  <div class="code{{if playable .}} playground{{end}}" contenteditable="true" spellcheck="false">{{.Text}}</div>
+{{end}}
+
+{{define "image"}}
+<div class="image">
+  <img src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}}>
+</div>
+{{end}}
+
+{{define "iframe"}}
+<iframe src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}}></iframe>
+{{end}}
+
+{{define "link"}}<p class="link"><a href="{{.URL}}" target="_blank">{{style .Label}}</a></p>{{end}}
+
+{{define "html"}}{{.HTML}}{{end}}
+
+{{define "caption"}}<figcaption>{{style .Text}}</figcaption>{{end}}
\ No newline at end of file
diff --git a/third_party/go.tools/cmd/present/templates/article.tmpl b/third_party/go.tools/cmd/present/templates/article.tmpl
new file mode 100644
index 0000000..40d1c93
--- /dev/null
+++ b/third_party/go.tools/cmd/present/templates/article.tmpl
@@ -0,0 +1,58 @@
+{/* This is the article template. It defines how articles are formatted. */}
+
+{{define "root"}}
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>{{.Title}}</title>
+    <link type="text/css" rel="stylesheet" href="/static/article.css">
+    <meta charset='utf-8'>
+  </head>
+
+  <body>
+    <div id="topbar" class="wide">
+      <div class="container">
+        <div id="heading">{{.Title}}
+          {{with .Subtitle}}{{.}}{{end}}
+        </div>
+      </div>
+    </div>
+    <div id="page" class="wide">
+      <div class="container">
+        {{with .Sections}}
+          <div id="toc">
+            {{template "TOC" .}}
+          </div>
+        {{end}}
+
+        {{range .Sections}}
+          {{elem $.Template .}}
+        {{end}}{{/* of Section block */}}
+
+        {{if .Authors}}
+          <h2>Authors</h2>
+          {{range .Authors}}
+            <div class="author">
+              {{range .Elem}}{{elem $.Template .}}{{end}}
+            </div>
+          {{end}}
+        {{end}}
+      </div>
+    </div>
+    <script src='/play.js'></script>
+  </body>
+</html>
+{{end}}
+
+{{define "TOC"}}
+  <ul>
+  {{range .}}
+    <li><a href="#TOC_{{.FormattedNumber}}">{{.Title}}</a></li>
+    {{with .Sections}}{{template "TOC" .}}{{end}}
+  {{end}}
+  </ul>
+{{end}}
+
+{{define "newline"}}
+{{/* No automatic line break. Paragraphs are free-form. */}}
+{{end}}
diff --git a/third_party/go.tools/cmd/present/templates/dir.tmpl b/third_party/go.tools/cmd/present/templates/dir.tmpl
new file mode 100644
index 0000000..aa83868
--- /dev/null
+++ b/third_party/go.tools/cmd/present/templates/dir.tmpl
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Talks - The Go Programming Language</title>
+  <link type="text/css" rel="stylesheet" href="/static/dir.css">
+  <script src="/static/dir.js"></script>
+</head>
+<body>
+
+<div id="topbar"><div class="container">
+
+<form method="GET" action="http://golang.org/search">
+<div id="menu">
+<a href="http://golang.org/doc/">Documents</a>
+<a href="http://golang.org/ref/">References</a>
+<a href="http://golang.org/pkg/">Packages</a>
+<a href="http://golang.org/project/">The Project</a>
+<a href="http://golang.org/help/">Help</a>
+<input type="text" id="search" name="q" class="inactive" value="Search">
+</div>
+<div id="heading"><a href="/">The Go Programming Language</a></div>
+</form>
+
+</div></div>
+
+<div id="page">
+
+  <h1>Go talks</h1>
+
+  {{with .Path}}<h2>{{.}}</h2>{{end}}
+
+  {{with .Articles}}
+  <h4>Articles:</h4>
+  <dl>
+  {{range .}}
+  <dd><a href="/{{.Path}}">{{.Name}}</a>: {{.Title}}</dd>
+  {{end}}
+  </dl>
+  {{end}}
+
+  {{with .Slides}}
+  <h4>Slide decks:</h4>
+  <dl>
+  {{range .}}
+  <dd><a href="/{{.Path}}">{{.Name}}</a>: {{.Title}}</dd>
+  {{end}}
+  </dl>
+  {{end}}
+
+  {{with .Other}}
+  <h4>Files:</h4>
+  <dl>
+  {{range .}}
+  <dd><a href="/{{.Path}}">{{.Name}}</a></dd>
+  {{end}}
+  </dl>
+  {{end}}
+
+  {{with .Dirs}}
+  <h4>Sub-directories:</h4>
+  <dl>
+  {{range .}}
+  <dd><a href="/{{.Path}}">{{.Name}}</a></dd>
+  {{end}}
+  </dl>
+  {{end}}
+
+</div>
+
+<div id="footer">
+Except as <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
+the content of this page is licensed under the
+Creative Commons Attribution 3.0 License,
+and code is licensed under a <a href="http://golang.org/LICENSE">BSD license</a>.<br>
+<a href="http://golang.org/doc/tos.html">Terms of Service</a> |
+<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
+</div>
+
+</body>
+</html>
diff --git a/third_party/go.tools/cmd/present/templates/slides.tmpl b/third_party/go.tools/cmd/present/templates/slides.tmpl
new file mode 100644
index 0000000..d2abfa1
--- /dev/null
+++ b/third_party/go.tools/cmd/present/templates/slides.tmpl
@@ -0,0 +1,58 @@
+{/* This is the slide template. It defines how presentations are formatted. */}
+
+{{define "root"}}
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>{{.Title}}</title>
+    <meta charset='utf-8'>
+    <script src='/static/slides.js'></script>
+  </head>
+
+  <body style='display: none'>
+
+    <section class='slides layout-widescreen'>
+      
+      <article>
+        <h1>{{.Title}}</h1>
+        {{with .Subtitle}}<h3>{{.}}</h3>{{end}}
+        {{if not .Time.IsZero}}<h3>{{.Time.Format "2 January 2006"}}</h3>{{end}}
+        {{range .Authors}}
+          <div class="presenter">
+            {{range .TextElem}}{{elem $.Template .}}{{end}}
+          </div>
+        {{end}}
+      </article>
+      
+  {{range $i, $s := .Sections}}
+  <!-- start of slide {{$s.Number}} -->
+      <article>
+      {{if $s.Elem}}
+        <h3>{{$s.Title}}</h3>
+        {{range $s.Elem}}{{elem $.Template .}}{{end}}
+      {{else}}
+        <h2>{{$s.Title}}</h2>
+      {{end}}
+      </article>
+  <!-- end of slide {{$i}} -->
+  {{end}}{{/* of Slide block */}}
+
+      <article>
+        <h3>Thank you</h1>
+        {{range .Authors}}
+          <div class="presenter">
+            {{range .Elem}}{{elem $.Template .}}{{end}}
+          </div>
+        {{end}}
+      </article>
+
+  </body>
+  {{if .PlayEnabled}}
+  <script src='/play.js'></script>
+  {{end}}
+</html>
+{{end}}
+
+{{define "newline"}}
+<br>
+{{end}}
diff --git a/third_party/go.tools/cmd/ssadump/main.go b/third_party/go.tools/cmd/ssadump/main.go
new file mode 100644
index 0000000..1b02788
--- /dev/null
+++ b/third_party/go.tools/cmd/ssadump/main.go
@@ -0,0 +1,213 @@
+// Copyright 2013 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.
+
+// ssadump: a tool for displaying and interpreting the SSA form of Go programs.
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/build"
+	"os"
+	"runtime"
+	"runtime/pprof"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/ssa/interp"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var buildFlag = flag.String("build", "", `Options controlling the SSA builder.
+The value is a sequence of zero or more of these letters:
+C	perform sanity [C]hecking of the SSA form.
+D	include [D]ebug info for every function.
+P	print [P]ackage inventory.
+F	print [F]unction SSA code.
+S	log [S]ource locations as SSA builder progresses.
+G	use binary object files from gc to provide imports (no code).
+L	build distinct packages seria[L]ly instead of in parallel.
+N	build [N]aive SSA form: don't replace local loads/stores with registers.
+I	build bare [I]nit functions: no init guards or calls to dependent inits.
+`)
+
+var testFlag = flag.Bool("test", false, "Loads test code (*_test.go) for imported packages.")
+
+var runFlag = flag.Bool("run", false, "Invokes the SSA interpreter on the program.")
+
+var interpFlag = flag.String("interp", "", `Options controlling the SSA test interpreter.
+The value is a sequence of zero or more more of these letters:
+R	disable [R]ecover() from panic; show interpreter crash instead.
+T	[T]race execution of the program.  Best for single-threaded programs!
+`)
+
+const usage = `SSA builder and interpreter.
+Usage: ssadump [<flag> ...] <args> ...
+Use -help flag to display options.
+
+Examples:
+% ssadump -build=FPG hello.go            # quickly dump SSA form of a single package
+% ssadump -run -interp=T hello.go        # interpret a program, with tracing
+% ssadump -run -test unicode -- -test.v  # interpret the unicode package's tests, verbosely
+` + loader.FromArgsUsage +
+	`
+When -run is specified, ssadump will run the program.
+The entry point depends on the -test flag:
+if clear, it runs the first package named main.
+if set, it runs the tests of each package.
+`
+
+var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
+
+func init() {
+	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
+	// For small machines, use at least 4 threads.
+	if os.Getenv("GOMAXPROCS") == "" {
+		n := runtime.NumCPU()
+		if n < 4 {
+			n = 4
+		}
+		runtime.GOMAXPROCS(n)
+	}
+}
+
+func main() {
+	if err := doMain(); err != nil {
+		fmt.Fprintf(os.Stderr, "ssadump: %s\n", err)
+		os.Exit(1)
+	}
+}
+
+func doMain() error {
+	flag.Parse()
+	args := flag.Args()
+
+	conf := loader.Config{
+		Build:         &build.Default,
+		SourceImports: true,
+	}
+	// TODO(adonovan): make go/types choose its default Sizes from
+	// build.Default or a specified *build.Context.
+	var wordSize int64 = 8
+	switch conf.Build.GOARCH {
+	case "386", "arm":
+		wordSize = 4
+	}
+	conf.TypeChecker.Sizes = &types.StdSizes{
+		MaxAlign: 8,
+		WordSize: wordSize,
+	}
+
+	var mode ssa.BuilderMode
+	for _, c := range *buildFlag {
+		switch c {
+		case 'D':
+			mode |= ssa.GlobalDebug
+		case 'P':
+			mode |= ssa.PrintPackages
+		case 'F':
+			mode |= ssa.PrintFunctions
+		case 'S':
+			mode |= ssa.LogSource | ssa.BuildSerially
+		case 'C':
+			mode |= ssa.SanityCheckFunctions
+		case 'N':
+			mode |= ssa.NaiveForm
+		case 'G':
+			conf.SourceImports = false
+		case 'L':
+			mode |= ssa.BuildSerially
+		case 'I':
+			mode |= ssa.BareInits
+		default:
+			return fmt.Errorf("unknown -build option: '%c'", c)
+		}
+	}
+
+	var interpMode interp.Mode
+	for _, c := range *interpFlag {
+		switch c {
+		case 'T':
+			interpMode |= interp.EnableTracing
+		case 'R':
+			interpMode |= interp.DisableRecover
+		default:
+			return fmt.Errorf("unknown -interp option: '%c'", c)
+		}
+	}
+
+	if len(args) == 0 {
+		fmt.Fprint(os.Stderr, usage)
+		os.Exit(1)
+	}
+
+	// Profiling support.
+	if *cpuprofile != "" {
+		f, err := os.Create(*cpuprofile)
+		if err != nil {
+			fmt.Fprintln(os.Stderr, err)
+			os.Exit(1)
+		}
+		pprof.StartCPUProfile(f)
+		defer pprof.StopCPUProfile()
+	}
+
+	// Use the initial packages from the command line.
+	args, err := conf.FromArgs(args, *testFlag)
+	if err != nil {
+		return err
+	}
+
+	// The interpreter needs the runtime package.
+	if *runFlag {
+		conf.Import("runtime")
+	}
+
+	// Load, parse and type-check the whole program.
+	iprog, err := conf.Load()
+	if err != nil {
+		return err
+	}
+
+	// Create and build SSA-form program representation.
+	prog := ssa.Create(iprog, mode)
+	prog.BuildAll()
+
+	// Run the interpreter.
+	if *runFlag {
+		var main *ssa.Package
+		pkgs := prog.AllPackages()
+		if *testFlag {
+			// If -test, run all packages' tests.
+			if len(pkgs) > 0 {
+				main = prog.CreateTestMainPackage(pkgs...)
+			}
+			if main == nil {
+				return fmt.Errorf("no tests")
+			}
+		} else {
+			// Otherwise, run main.main.
+			for _, pkg := range pkgs {
+				if pkg.Object.Name() == "main" {
+					main = pkg
+					if main.Func("main") == nil {
+						return fmt.Errorf("no func main() in main package")
+					}
+					break
+				}
+			}
+			if main == nil {
+				return fmt.Errorf("no main package")
+			}
+		}
+
+		if runtime.GOARCH != build.Default.GOARCH {
+			return fmt.Errorf("cross-interpretation is not yet supported (target has GOARCH %s, interpreter has %s)",
+				build.Default.GOARCH, runtime.GOARCH)
+		}
+
+		interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Object.Path(), args)
+	}
+	return nil
+}
diff --git a/third_party/go.tools/cmd/stringer/endtoend_test.go b/third_party/go.tools/cmd/stringer/endtoend_test.go
new file mode 100644
index 0000000..ae2cc0a
--- /dev/null
+++ b/third_party/go.tools/cmd/stringer/endtoend_test.go
@@ -0,0 +1,99 @@
+// Copyright 2014 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 (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"testing"
+)
+
+// This file contains a test that compiles and runs each program in testdata
+// after generating the string method for its type. The rule is that for testdata/x.go
+// we run stringer -type X and then compile and run the program. The resulting
+// binary panics if the String method for X is not correct, including for error cases.
+
+func TestEndToEnd(t *testing.T) {
+	dir, err := ioutil.TempDir("", "stringer")
+	defer os.RemoveAll(dir)
+	// Create stringer in temporary directory.
+	stringer := filepath.Join(dir, "stringer.exe")
+	err = run("go", "build", "-o", stringer, "stringer.go")
+	if err != nil {
+		t.Fatalf("building stringer: %s", err)
+	}
+	// Read the testdata directory.
+	fd, err := os.Open("testdata")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer fd.Close()
+	names, err := fd.Readdirnames(-1)
+	if err != nil {
+		t.Fatalf("Readdirnames: %s", err)
+	}
+	// Generate, compile, and run the test programs.
+	for _, name := range names {
+		if !strings.HasSuffix(name, ".go") {
+			t.Errorf("%s is not a Go file", name)
+			continue
+		}
+		// Names are known to be ASCII and long enough.
+		typeName := fmt.Sprintf("%c%s", name[0]+'A'-'a', name[1:len(name)-len(".go")])
+		stringerCompileAndRun(t, dir, stringer, typeName, name)
+	}
+}
+
+// stringerCompileAndRun runs stringer for the named file and compiles and
+// runs the target binary in directory dir. That binary will panic if the String method is incorrect.
+func stringerCompileAndRun(t *testing.T, dir, stringer, typeName, fileName string) {
+	t.Logf("run: %s %s\n", fileName, typeName)
+	source := filepath.Join(dir, fileName)
+	err := copy(source, filepath.Join("testdata", fileName))
+	if err != nil {
+		t.Fatalf("copying file to temporary directory: %s", err)
+	}
+	stringSource := filepath.Join(dir, typeName+"_string.go")
+	// Run stringer in temporary directory.
+	err = run(stringer, "-type", typeName, "-output", stringSource, source)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Run the binary in the temporary directory.
+	err = run("go", "run", stringSource, source)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+// copy copies the from file to the to file.
+func copy(to, from string) error {
+	toFd, err := os.Create(to)
+	if err != nil {
+		return err
+	}
+	defer toFd.Close()
+	fromFd, err := os.Open(from)
+	if err != nil {
+		return err
+	}
+	defer fromFd.Close()
+	_, err = io.Copy(toFd, fromFd)
+	return err
+}
+
+// run runs a single command and returns an error if it does not succeed.
+// os/exec should have this function, to be honest.
+func run(name string, arg ...string) error {
+	cmd := exec.Command(name, arg...)
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	return cmd.Run()
+}
diff --git a/third_party/go.tools/cmd/stringer/golden_test.go b/third_party/go.tools/cmd/stringer/golden_test.go
new file mode 100644
index 0000000..f0db09f
--- /dev/null
+++ b/third_party/go.tools/cmd/stringer/golden_test.go
@@ -0,0 +1,289 @@
+// Copyright 2014 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.
+
+// This file contains simple golden tests for various examples.
+// Besides validating the results when the implementation changes,
+// it provides a way to look at the generated code without having
+// to execute the print statements in one's head.
+
+package main
+
+import (
+	"strings"
+	"testing"
+)
+
+// Golden represents a test case.
+type Golden struct {
+	name   string
+	input  string // input; the package clause is provided when running the test.
+	output string // exected output.
+}
+
+var golden = []Golden{
+	{"day", day_in, day_out},
+	{"offset", offset_in, offset_out},
+	{"gap", gap_in, gap_out},
+	{"num", num_in, num_out},
+	{"unum", unum_in, unum_out},
+	{"prime", prime_in, prime_out},
+}
+
+// Each example starts with "type XXX [u]int", with a single space separating them.
+
+// Simple test: enumeration of type int starting at 0.
+const day_in = `type Day int
+const (
+	Monday Day = iota
+	Tuesday
+	Wednesday
+	Thursday
+	Friday
+	Saturday
+	Sunday
+)
+`
+
+const day_out = `
+const _Day_name = "MondayTuesdayWednesdayThursdayFridaySaturdaySunday"
+
+var _Day_index = [...]uint8{6, 13, 22, 30, 36, 44, 50}
+
+func (i Day) String() string {
+	if i < 0 || i >= Day(len(_Day_index)) {
+		return fmt.Sprintf("Day(%d)", i)
+	}
+	hi := _Day_index[i]
+	lo := uint8(0)
+	if i > 0 {
+		lo = _Day_index[i-1]
+	}
+	return _Day_name[lo:hi]
+}
+`
+
+// Enumeration with an offset.
+// Also includes a duplicate.
+const offset_in = `type Number int
+const (
+	_ Number = iota
+	One
+	Two
+	Three
+	AnotherOne = One  // Duplicate; note that AnotherOne doesn't appear below.
+)
+`
+
+const offset_out = `
+const _Number_name = "OneTwoThree"
+
+var _Number_index = [...]uint8{3, 6, 11}
+
+func (i Number) String() string {
+	i -= 1
+	if i < 0 || i >= Number(len(_Number_index)) {
+		return fmt.Sprintf("Number(%d)", i+1)
+	}
+	hi := _Number_index[i]
+	lo := uint8(0)
+	if i > 0 {
+		lo = _Number_index[i-1]
+	}
+	return _Number_name[lo:hi]
+}
+`
+
+// Gaps and an offset.
+const gap_in = `type Gap int
+const (
+	Two Gap = 2
+	Three Gap = 3
+	Five Gap = 5
+	Six Gap = 6
+	Seven Gap = 7
+	Eight Gap = 8
+	Nine Gap = 9
+	Eleven Gap = 11
+)
+`
+
+const gap_out = `
+const (
+	_Gap_name_0 = "TwoThree"
+	_Gap_name_1 = "FiveSixSevenEightNine"
+	_Gap_name_2 = "Eleven"
+)
+
+var (
+	_Gap_index_0 = [...]uint8{3, 8}
+	_Gap_index_1 = [...]uint8{4, 7, 12, 17, 21}
+	_Gap_index_2 = [...]uint8{6}
+)
+
+func (i Gap) String() string {
+	switch {
+	case 2 <= i && i <= 3:
+		i -= 2
+		lo := uint8(0)
+		if i > 0 {
+			lo = _Gap_index_0[i-1]
+		}
+		return _Gap_name_0[lo:_Gap_index_0[i]]
+	case 5 <= i && i <= 9:
+		i -= 5
+		lo := uint8(0)
+		if i > 0 {
+			lo = _Gap_index_1[i-1]
+		}
+		return _Gap_name_1[lo:_Gap_index_1[i]]
+	case i == 11:
+		return _Gap_name_2
+	default:
+		return fmt.Sprintf("Gap(%d)", i)
+	}
+}
+`
+
+// Signed integers spanning zero.
+const num_in = `type Num int
+const (
+	m_2 Num = -2 + iota
+	m_1
+	m0
+	m1
+	m2
+)
+`
+
+const num_out = `
+const _Num_name = "m_2m_1m0m1m2"
+
+var _Num_index = [...]uint8{3, 6, 8, 10, 12}
+
+func (i Num) String() string {
+	i -= -2
+	if i < 0 || i >= Num(len(_Num_index)) {
+		return fmt.Sprintf("Num(%d)", i+-2)
+	}
+	hi := _Num_index[i]
+	lo := uint8(0)
+	if i > 0 {
+		lo = _Num_index[i-1]
+	}
+	return _Num_name[lo:hi]
+}
+`
+
+// Unsigned integers spanning zero.
+const unum_in = `type Unum uint
+const (
+	m_2 Unum = iota + 253
+	m_1
+)
+
+const (
+	m0 Unum = iota
+	m1
+	m2
+)
+`
+
+const unum_out = `
+const (
+	_Unum_name_0 = "m0m1m2"
+	_Unum_name_1 = "m_2m_1"
+)
+
+var (
+	_Unum_index_0 = [...]uint8{2, 4, 6}
+	_Unum_index_1 = [...]uint8{3, 6}
+)
+
+func (i Unum) String() string {
+	switch {
+	case 0 <= i && i <= 2:
+		lo := uint8(0)
+		if i > 0 {
+			lo = _Unum_index_0[i-1]
+		}
+		return _Unum_name_0[lo:_Unum_index_0[i]]
+	case 253 <= i && i <= 254:
+		i -= 253
+		lo := uint8(0)
+		if i > 0 {
+			lo = _Unum_index_1[i-1]
+		}
+		return _Unum_name_1[lo:_Unum_index_1[i]]
+	default:
+		return fmt.Sprintf("Unum(%d)", i)
+	}
+}
+`
+
+// Enough gaps to trigger a map implementation of the method.
+// Also includes a duplicate to test that it doesn't cause problems
+const prime_in = `type Prime int
+const (
+	p2 Prime = 2
+	p3 Prime = 3
+	p5 Prime = 5
+	p7 Prime = 7
+	p77 Prime = 7 // Duplicate; note that p77 doesn't appear below.
+	p11 Prime = 11
+	p13 Prime = 13
+	p17 Prime = 17
+	p19 Prime = 19
+	p23 Prime = 23
+	p29 Prime = 29
+	p37 Prime = 31
+	p41 Prime = 41
+	p43 Prime = 43
+)
+`
+
+const prime_out = `
+const _Prime_name = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
+
+var _Prime_map = map[Prime]string{
+	2:  _Prime_name[0:2],
+	3:  _Prime_name[2:4],
+	5:  _Prime_name[4:6],
+	7:  _Prime_name[6:8],
+	11: _Prime_name[8:11],
+	13: _Prime_name[11:14],
+	17: _Prime_name[14:17],
+	19: _Prime_name[17:20],
+	23: _Prime_name[20:23],
+	29: _Prime_name[23:26],
+	31: _Prime_name[26:29],
+	41: _Prime_name[29:32],
+	43: _Prime_name[32:35],
+}
+
+func (i Prime) String() string {
+	if str, ok := _Prime_map[i]; ok {
+		return str
+	}
+	return fmt.Sprintf("Prime(%d)", i)
+}
+`
+
+func TestGolden(t *testing.T) {
+	for _, test := range golden {
+		var g Generator
+		input := "package test\n" + test.input
+		file := test.name + ".go"
+		g.parsePackage(".", []string{file}, input)
+		// Extract the name and type of the constant from the first line.
+		tokens := strings.SplitN(test.input, " ", 3)
+		if len(tokens) != 3 {
+			t.Fatalf("%s: need type declaration on first line", test.name)
+		}
+		g.generate(tokens[1])
+		got := string(g.format())
+		if got != test.output {
+			t.Errorf("%s: got\n====\n%s====\nexpected\n====%s", test.name, got, test.output)
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/stringer/stringer.go b/third_party/go.tools/cmd/stringer/stringer.go
new file mode 100644
index 0000000..760b1b1
--- /dev/null
+++ b/third_party/go.tools/cmd/stringer/stringer.go
@@ -0,0 +1,652 @@
+// Copyright 2014 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.
+
+// Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer
+// interface. Given the name of a (signed or unsigned) integer type T that has constants
+// defined, stringer will create a new self-contained Go source file implementing
+//	func (t T) String() string
+// The file is created in the same package and directory as the package that defines T.
+// It has helpful defaults designed for use with go generate.
+//
+// Stringer works best with constants that are consecutive values such as created using iota,
+// but creates good code regardless. In the future it might also provide custom support for
+// constant sets that are bit patterns.
+//
+// For example, given this snippet,
+//
+//	package painkiller
+//
+//	type Pill int
+//
+//	const (
+//		Placebo Pill = iota
+//		Aspirin
+//		Ibuprofen
+//		Paracetamol
+//		Acetaminophen = Paracetamol
+//	)
+//
+// running this command
+//
+//	stringer -type=Pill
+//
+// in the same directory will create the file pill_string.go, in package painkiller,
+// containing a definition of
+//
+//	func (Pill) String() string
+//
+// That method will translate the value of a Pill constant to the string representation
+// of the respective constant name, so that the call fmt.Print(painkiller.Aspirin) will
+// print the string "Aspirin".
+//
+// Typically this process would be run using go generate, like this:
+//
+//	//go:generate stringer -type=Pill
+//
+// If multiple constants have the same value, the lexically first matching name will
+// be used (in the example, Acetaminophen will print as "Paracetamol").
+//
+// With no arguments, it processes the package in the current directory.
+// Otherwise, the arguments must name a single directory holding a Go package
+// or a set of Go source files that represent a single Go package.
+//
+// The -type flag accepts a comma-separated list of types so a single run can
+// generate methods for multiple types. The default output file is t_string.go,
+// where t is the lower-cased name of the first type listed. It can be overridden
+// with the -output flag.
+//
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+)
+
+var (
+	typeNames = flag.String("type", "", "comma-separated list of type names; must be set")
+	output    = flag.String("output", "", "output file name; default srcdir/<type>_string.go")
+)
+
+// Usage is a replacement usage function for the flags package.
+func Usage() {
+	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
+	fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T [directory]\n")
+	fmt.Fprintf(os.Stderr, "\tstringer [flags[ -type T files... # Must be a single package\n")
+	fmt.Fprintf(os.Stderr, "For more information, see:\n")
+	fmt.Fprintf(os.Stderr, "\thttp://godoc.org/golang.org/x/tools/cmd/stringer\n")
+	fmt.Fprintf(os.Stderr, "Flags:\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func main() {
+	log.SetFlags(0)
+	log.SetPrefix("stringer: ")
+	flag.Usage = Usage
+	flag.Parse()
+	if len(*typeNames) == 0 {
+		flag.Usage()
+		os.Exit(2)
+	}
+	types := strings.Split(*typeNames, ",")
+
+	// We accept either one directory or a list of files. Which do we have?
+	args := flag.Args()
+	if len(args) == 0 {
+		// Default: process whole package in current directory.
+		args = []string{"."}
+	}
+
+	// Parse the package once.
+	var (
+		dir string
+		g   Generator
+	)
+	if len(args) == 1 && isDirectory(args[0]) {
+		dir = args[0]
+		g.parsePackageDir(args[0])
+	} else {
+		dir = filepath.Dir(args[0])
+		g.parsePackageFiles(args)
+	}
+
+	// Print the header and package clause.
+	g.Printf("// generated by stringer %s; DO NOT EDIT\n", strings.Join(os.Args[1:], " "))
+	g.Printf("\n")
+	g.Printf("package %s", g.pkg.name)
+	g.Printf("\n")
+	g.Printf("import \"fmt\"\n") // Used by all methods.
+
+	// Run generate for each type.
+	for _, typeName := range types {
+		g.generate(typeName)
+	}
+
+	// Format the output.
+	src := g.format()
+
+	// Write to file.
+	outputName := *output
+	if outputName == "" {
+		baseName := fmt.Sprintf("%s_string.go", types[0])
+		outputName = filepath.Join(dir, strings.ToLower(baseName))
+	}
+	err := ioutil.WriteFile(outputName, src, 0644)
+	if err != nil {
+		log.Fatalf("writing output: %s", err)
+	}
+}
+
+// isDirectory reports whether the named file is a directory.
+func isDirectory(name string) bool {
+	info, err := os.Stat(name)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return info.IsDir()
+}
+
+// Generator holds the state of the analysis. Primarily used to buffer
+// the output for format.Source.
+type Generator struct {
+	buf bytes.Buffer // Accumulated output.
+	pkg *Package     // Package we are scanning.
+}
+
+func (g *Generator) Printf(format string, args ...interface{}) {
+	fmt.Fprintf(&g.buf, format, args...)
+}
+
+// File holds a single parsed file and associated data.
+type File struct {
+	pkg  *Package  // Package to which this file belongs.
+	file *ast.File // Parsed AST.
+	// These fields are reset for each type being generated.
+	typeName string  // Name of the constant type.
+	values   []Value // Accumulator for constant values of that type.
+}
+
+type Package struct {
+	dir      string
+	name     string
+	defs     map[*ast.Ident]types.Object
+	files    []*File
+	typesPkg *types.Package
+}
+
+// parsePackageDir parses the package residing in the directory.
+func (g *Generator) parsePackageDir(directory string) {
+	pkg, err := build.Default.ImportDir(directory, 0)
+	if err != nil {
+		log.Fatalf("cannot process directory %s: %s", directory, err)
+	}
+	var names []string
+	names = append(names, pkg.GoFiles...)
+	names = append(names, pkg.CgoFiles...)
+	// TODO: Need to think about constants in test files. Maybe write type_string_test.go
+	// in a separate pass? For later.
+	// names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
+	names = append(names, pkg.SFiles...)
+	names = prefixDirectory(directory, names)
+	g.parsePackage(directory, names, nil)
+}
+
+// parsePackageFiles parses the package occupying the named files.
+func (g *Generator) parsePackageFiles(names []string) {
+	g.parsePackage(".", names, nil)
+}
+
+// prefixDirectory places the directory name on the beginning of each name in the list.
+func prefixDirectory(directory string, names []string) []string {
+	if directory == "." {
+		return names
+	}
+	ret := make([]string, len(names))
+	for i, name := range names {
+		ret[i] = filepath.Join(directory, name)
+	}
+	return ret
+}
+
+// parsePackage analyzes the single package constructed from the named files.
+// If text is non-nil, it is a string to be used instead of the content of the file,
+// to be used for testing. parsePackage exits if there is an error.
+func (g *Generator) parsePackage(directory string, names []string, text interface{}) {
+	var files []*File
+	var astFiles []*ast.File
+	g.pkg = new(Package)
+	fs := token.NewFileSet()
+	for _, name := range names {
+		if !strings.HasSuffix(name, ".go") {
+			continue
+		}
+		parsedFile, err := parser.ParseFile(fs, name, text, 0)
+		if err != nil {
+			log.Fatalf("parsing package: %s: %s", name, err)
+		}
+		astFiles = append(astFiles, parsedFile)
+		files = append(files, &File{
+			file: parsedFile,
+			pkg:  g.pkg,
+		})
+	}
+	if len(astFiles) == 0 {
+		log.Fatalf("%s: no buildable Go files", directory)
+	}
+	g.pkg.name = astFiles[0].Name.Name
+	g.pkg.files = files
+	g.pkg.dir = directory
+	// Type check the package.
+	g.pkg.check(fs, astFiles)
+}
+
+// check type-checks the package. The package must be OK to proceed.
+func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) {
+	pkg.defs = make(map[*ast.Ident]types.Object)
+	var config types.Config
+	info := &types.Info{
+		Defs: pkg.defs,
+	}
+	typesPkg, err := config.Check(pkg.dir, fs, astFiles, info)
+	if err != nil {
+		log.Fatalf("checking package: %s", err)
+	}
+	pkg.typesPkg = typesPkg
+}
+
+// generate produces the String method for the named type.
+func (g *Generator) generate(typeName string) {
+	values := make([]Value, 0, 100)
+	for _, file := range g.pkg.files {
+		// Set the state for this run of the walker.
+		file.typeName = typeName
+		file.values = nil
+		if file.file != nil {
+			ast.Inspect(file.file, file.genDecl)
+			values = append(values, file.values...)
+		}
+	}
+
+	if len(values) == 0 {
+		log.Fatalf("no values defined for type %s", typeName)
+	}
+	runs := splitIntoRuns(values)
+	// The decision of which pattern to use depends on the number of
+	// runs in the numbers. If there's only one, it's easy. For more than
+	// one, there's a tradeoff between complexity and size of the data
+	// and code vs. the simplicity of a map. A map takes more space,
+	// but so does the code. The decision here (crossover at 10) is
+	// arbitrary, but considers that for large numbers of runs the cost
+	// of the linear scan in the switch might become important, and
+	// rather than use yet another algorithm such as binary search,
+	// we punt and use a map. In any case, the likelihood of a map
+	// being necessary for any realistic example other than bitmasks
+	// is very low. And bitmasks probably deserve their own analysis,
+	// to be done some other day.
+	switch {
+	case len(runs) == 1:
+		g.buildOneRun(runs, typeName)
+	case len(runs) <= 10:
+		g.buildMultipleRuns(runs, typeName)
+	default:
+		g.buildMap(runs, typeName)
+	}
+}
+
+// splitIntoRuns breaks the values into runs of contiguous sequences.
+// For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}.
+// The input slice is known to be non-empty.
+func splitIntoRuns(values []Value) [][]Value {
+	// We use stable sort so the lexically first name is chosen for equal elements.
+	sort.Stable(byValue(values))
+	// Remove duplicates. Stable sort has put the one we want to print first,
+	// so use that one. The String method won't care about which named constant
+	// was the argument, so the first name for the given value is the only one to keep.
+	// We need to do this because identical values would cause the switch or map
+	// to fail to compile.
+	j := 1
+	for i := 1; i < len(values); i++ {
+		if values[i].value != values[i-1].value {
+			values[j] = values[i]
+			j++
+		}
+	}
+	values = values[:j]
+	runs := make([][]Value, 0, 10)
+	for len(values) > 0 {
+		// One contiguous sequence per outer loop.
+		i := 1
+		for i < len(values) && values[i].value == values[i-1].value+1 {
+			i++
+		}
+		runs = append(runs, values[:i])
+		values = values[i:]
+	}
+	return runs
+}
+
+// format returns the gofmt-ed contents of the Generator's buffer.
+func (g *Generator) format() []byte {
+	src, err := format.Source(g.buf.Bytes())
+	if err != nil {
+		// Should never happen, but can arise when developing this code.
+		// The user can compile the output to see the error.
+		log.Printf("warning: internal error: invalid Go generated: %s", err)
+		log.Printf("warning: compile the package to analyze the error")
+		return g.buf.Bytes()
+	}
+	return src
+}
+
+// Value represents a declared constant.
+type Value struct {
+	name string // The name of the constant.
+	// The value is stored as a bit pattern alone. The boolean tells us
+	// whether to interpret it as an int64 or a uint64; the only place
+	// this matters is when sorting.
+	// Much of the time the str field is all we need; it is printed
+	// by Value.String.
+	value  uint64 // Will be converted to int64 when needed.
+	signed bool   // Whether the constant is a signed type.
+	str    string // The string representation given by the "go/exact" package.
+}
+
+func (v *Value) String() string {
+	return v.str
+}
+
+// byValue lets us sort the constants into increasing order.
+// We take care in the Less method to sort in signed or unsigned order,
+// as appropriate.
+type byValue []Value
+
+func (b byValue) Len() int      { return len(b) }
+func (b byValue) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b byValue) Less(i, j int) bool {
+	if b[i].signed {
+		return int64(b[i].value) < int64(b[j].value)
+	}
+	return b[i].value < b[j].value
+}
+
+// genDecl processes one declaration clause.
+func (f *File) genDecl(node ast.Node) bool {
+	decl, ok := node.(*ast.GenDecl)
+	if !ok || decl.Tok != token.CONST {
+		// We only care about const declarations.
+		return true
+	}
+	// The name of the type of the constants we are declaring.
+	// Can change if this is a multi-element declaration.
+	typ := ""
+	// Loop over the elements of the declaration. Each element is a ValueSpec:
+	// a list of names possibly followed by a type, possibly followed by values.
+	// If the type and value are both missing, we carry down the type (and value,
+	// but the "go/types" package takes care of that).
+	for _, spec := range decl.Specs {
+		vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST.
+		if vspec.Type == nil && len(vspec.Values) > 0 {
+			// "X = 1". With no type but a value, the constant is untyped.
+			// Skip this vspec and reset the remembered type.
+			typ = ""
+			continue
+		}
+		if vspec.Type != nil {
+			// "X T". We have a type. Remember it.
+			ident, ok := vspec.Type.(*ast.Ident)
+			if !ok {
+				continue
+			}
+			typ = ident.Name
+		}
+		if typ != f.typeName {
+			// This is not the type we're looking for.
+			continue
+		}
+		// We now have a list of names (from one line of source code) all being
+		// declared with the desired type.
+		// Grab their names and actual values and store them in f.values.
+		for _, name := range vspec.Names {
+			if name.Name == "_" {
+				continue
+			}
+			// This dance lets the type checker find the values for us. It's a
+			// bit tricky: look up the object declared by the name, find its
+			// types.Const, and extract its value.
+			obj, ok := f.pkg.defs[name]
+			if !ok {
+				log.Fatalf("no value for constant %s", name)
+			}
+			info := obj.Type().Underlying().(*types.Basic).Info()
+			if info&types.IsInteger == 0 {
+				log.Fatalf("can't handle non-integer constant type %s", typ)
+			}
+			value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST.
+			if value.Kind() != exact.Int {
+				log.Fatalf("can't happen: constant is not an integer %s", name)
+			}
+			i64, isInt := exact.Int64Val(value)
+			u64, isUint := exact.Uint64Val(value)
+			if !isInt && !isUint {
+				log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String())
+			}
+			if !isInt {
+				u64 = uint64(i64)
+			}
+			v := Value{
+				name:   name.Name,
+				value:  u64,
+				signed: info&types.IsUnsigned == 0,
+				str:    value.String(),
+			}
+			f.values = append(f.values, v)
+		}
+	}
+	return false
+}
+
+// Helpers
+
+// usize returns the number of bits of the smallest unsigned integer
+// type that will hold n. Used to create the smallest possible slice of
+// integers to use as indexes into the concatenated strings.
+func usize(n int) int {
+	switch {
+	case n < 1<<8:
+		return 8
+	case n < 1<<16:
+		return 16
+	default:
+		// 2^32 is enough constants for anyone.
+		return 32
+	}
+}
+
+// declareIndexAndNameVars declares the index slices and concatenated names
+// strings representing the runs of values.
+func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {
+	var indexes, names []string
+	for i, run := range runs {
+		index, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
+		indexes = append(indexes, index)
+		names = append(names, name)
+	}
+	g.Printf("const (\n")
+	for _, name := range names {
+		g.Printf("\t%s\n", name)
+	}
+	g.Printf(")\n\n")
+	g.Printf("var (")
+	for _, index := range indexes {
+		g.Printf("\t%s\n", index)
+	}
+	g.Printf(")\n\n")
+}
+
+// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars
+func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) {
+	index, name := g.createIndexAndNameDecl(run, typeName, "")
+	g.Printf("const %s\n", name)
+	g.Printf("var %s\n", index)
+}
+
+// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var".
+func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) {
+	b := new(bytes.Buffer)
+	indexes := make([]int, len(run))
+	for i := range run {
+		b.WriteString(run[i].name)
+		indexes[i] = b.Len()
+	}
+	nameConst := fmt.Sprintf("_%s_name%s = %q", typeName, suffix, b.String())
+	nameLen := b.Len()
+	b.Reset()
+	fmt.Fprintf(b, "_%s_index%s = [...]uint%d{", typeName, suffix, usize(nameLen))
+	for i, v := range indexes {
+		if i > 0 {
+			fmt.Fprintf(b, ", ")
+		}
+		fmt.Fprintf(b, "%d", v)
+	}
+	fmt.Fprintf(b, "}")
+	return b.String(), nameConst
+}
+
+// declareNameVars declares the concatenated names string representing all the values in the runs.
+func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) {
+	g.Printf("const _%s_name%s = \"", typeName, suffix)
+	for _, run := range runs {
+		for i := range run {
+			g.Printf("%s", run[i].name)
+		}
+	}
+	g.Printf("\"\n")
+}
+
+// buildOneRun generates the variables and String method for a single run of contiguous values.
+func (g *Generator) buildOneRun(runs [][]Value, typeName string) {
+	values := runs[0]
+	g.Printf("\n")
+	g.declareIndexAndNameVar(values, typeName)
+	// The generated code is simple enough to write as a Printf format.
+	lessThanZero := ""
+	if values[0].signed {
+		lessThanZero = "i < 0 || "
+	}
+	if values[0].value == 0 { // Signed or unsigned, 0 is still 0.
+		g.Printf(stringOneRun, typeName, usize(len(values)), lessThanZero)
+	} else {
+		g.Printf(stringOneRunWithOffset, typeName, values[0].String(), usize(len(values)), lessThanZero)
+	}
+}
+
+// Arguments to format are:
+//	[1]: type name
+//	[2]: size of index element (8 for uint8 etc.)
+//	[3]: less than zero check (for signed types)
+const stringOneRun = `func (i %[1]s) String() string {
+	if %[3]si >= %[1]s(len(_%[1]s_index)) {
+		return fmt.Sprintf("%[1]s(%%d)", i)
+	}
+	hi := _%[1]s_index[i]
+	lo := uint%[2]d(0)
+	if i > 0 {
+		lo = _%[1]s_index[i-1]
+	}
+	return _%[1]s_name[lo:hi]
+}
+`
+
+// Arguments to format are:
+//	[1]: type name
+//	[2]: lowest defined value for type, as a string
+//	[3]: size of index element (8 for uint8 etc.)
+//	[4]: less than zero check (for signed types)
+/*
+ */
+const stringOneRunWithOffset = `func (i %[1]s) String() string {
+	i -= %[2]s
+	if %[4]si >= %[1]s(len(_%[1]s_index)) {
+		return fmt.Sprintf("%[1]s(%%d)", i + %[2]s)
+	}
+	hi := _%[1]s_index[i]
+	lo := uint%[3]d(0)
+	if i > 0 {
+		lo = _%[1]s_index[i-1]
+	}
+	return _%[1]s_name[lo : hi]
+}
+`
+
+// buildMultipleRuns generates the variables and String method for multiple runs of contiguous values.
+// For this pattern, a single Printf format won't do.
+func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) {
+	g.Printf("\n")
+	g.declareIndexAndNameVars(runs, typeName)
+	g.Printf("func (i %s) String() string {\n", typeName)
+	g.Printf("\tswitch {\n")
+	for i, values := range runs {
+		if len(values) == 1 {
+			g.Printf("\tcase i == %s:\n", &values[0])
+			g.Printf("\t\treturn _%s_name_%d\n", typeName, i)
+			continue
+		}
+		g.Printf("\tcase %s <= i && i <= %s:\n", &values[0], &values[len(values)-1])
+		if values[0].value != 0 {
+			g.Printf("\t\ti -= %s\n", &values[0])
+		}
+		g.Printf("\t\tlo := uint%d(0)\n", usize(len(values)))
+		g.Printf("\t\tif i > 0 {\n")
+		g.Printf("\t\t\tlo = _%s_index_%d[i-1]\n", typeName, i)
+		g.Printf("\t\t}\n")
+		g.Printf("\t\treturn _%s_name_%d[lo:_%s_index_%d[i]]\n", typeName, i, typeName, i)
+	}
+	g.Printf("\tdefault:\n")
+	g.Printf("\t\treturn fmt.Sprintf(\"%s(%%d)\", i)\n", typeName)
+	g.Printf("\t}\n")
+	g.Printf("}\n")
+}
+
+// buildMap handles the case where the space is so sparse a map is a reasonable fallback.
+// It's a rare situation but has simple code.
+func (g *Generator) buildMap(runs [][]Value, typeName string) {
+	g.Printf("\n")
+	g.declareNameVars(runs, typeName, "")
+	g.Printf("\nvar _%s_map = map[%s]string{\n", typeName, typeName)
+	n := 0
+	for _, values := range runs {
+		for _, value := range values {
+			g.Printf("\t%s: _%s_name[%d:%d],\n", &value, typeName, n, n+len(value.name))
+			n += len(value.name)
+		}
+	}
+	g.Printf("}\n\n")
+	g.Printf(stringMap, typeName)
+}
+
+// Argument to format is the type name.
+const stringMap = `func (i %[1]s) String() string {
+	if str, ok := _%[1]s_map[i]; ok {
+		return str
+	}
+	return fmt.Sprintf("%[1]s(%%d)", i)
+}
+`
diff --git a/third_party/go.tools/cmd/stringer/testdata/day.go b/third_party/go.tools/cmd/stringer/testdata/day.go
new file mode 100644
index 0000000..35fa8dc
--- /dev/null
+++ b/third_party/go.tools/cmd/stringer/testdata/day.go
@@ -0,0 +1,39 @@
+// Copyright 2014 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.
+
+// Simple test: enumeration of type int starting at 0.
+
+package main
+
+import "fmt"
+
+type Day int
+
+const (
+	Monday Day = iota
+	Tuesday
+	Wednesday
+	Thursday
+	Friday
+	Saturday
+	Sunday
+)
+
+func main() {
+	ck(Monday, "Monday")
+	ck(Tuesday, "Tuesday")
+	ck(Wednesday, "Wednesday")
+	ck(Thursday, "Thursday")
+	ck(Friday, "Friday")
+	ck(Saturday, "Saturday")
+	ck(Sunday, "Sunday")
+	ck(-127, "Day(-127)")
+	ck(127, "Day(127)")
+}
+
+func ck(day Day, str string) {
+	if fmt.Sprint(day) != str {
+		panic("day.go: " + str)
+	}
+}
diff --git a/third_party/go.tools/cmd/stringer/testdata/gap.go b/third_party/go.tools/cmd/stringer/testdata/gap.go
new file mode 100644
index 0000000..bc8a90c
--- /dev/null
+++ b/third_party/go.tools/cmd/stringer/testdata/gap.go
@@ -0,0 +1,44 @@
+// Copyright 2014 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.
+
+// Gaps and an offset.
+
+package main
+
+import "fmt"
+
+type Gap int
+
+const (
+	Two    Gap = 2
+	Three  Gap = 3
+	Five   Gap = 5
+	Six    Gap = 6
+	Seven  Gap = 7
+	Eight  Gap = 8
+	Nine   Gap = 9
+	Eleven Gap = 11
+)
+
+func main() {
+	ck(0, "Gap(0)")
+	ck(1, "Gap(1)")
+	ck(Two, "Two")
+	ck(Three, "Three")
+	ck(4, "Gap(4)")
+	ck(Five, "Five")
+	ck(Six, "Six")
+	ck(Seven, "Seven")
+	ck(Eight, "Eight")
+	ck(Nine, "Nine")
+	ck(10, "Gap(10)")
+	ck(Eleven, "Eleven")
+	ck(12, "Gap(12)")
+}
+
+func ck(gap Gap, str string) {
+	if fmt.Sprint(gap) != str {
+		panic("gap.go: " + str)
+	}
+}
diff --git a/third_party/go.tools/cmd/stringer/testdata/num.go b/third_party/go.tools/cmd/stringer/testdata/num.go
new file mode 100644
index 0000000..0d5ab10
--- /dev/null
+++ b/third_party/go.tools/cmd/stringer/testdata/num.go
@@ -0,0 +1,35 @@
+// Copyright 2014 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.
+
+// Signed integers spanning zero.
+
+package main
+
+import "fmt"
+
+type Num int
+
+const (
+	m_2 Num = -2 + iota
+	m_1
+	m0
+	m1
+	m2
+)
+
+func main() {
+	ck(-3, "Num(-3)")
+	ck(m_2, "m_2")
+	ck(m_1, "m_1")
+	ck(m0, "m0")
+	ck(m1, "m1")
+	ck(m2, "m2")
+	ck(3, "Num(3)")
+}
+
+func ck(num Num, str string) {
+	if fmt.Sprint(num) != str {
+		panic("num.go: " + str)
+	}
+}
diff --git a/third_party/go.tools/cmd/stringer/testdata/number.go b/third_party/go.tools/cmd/stringer/testdata/number.go
new file mode 100644
index 0000000..7f1c824
--- /dev/null
+++ b/third_party/go.tools/cmd/stringer/testdata/number.go
@@ -0,0 +1,34 @@
+// Copyright 2014 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.
+
+// Enumeration with an offset.
+// Also includes a duplicate.
+
+package main
+
+import "fmt"
+
+type Number int
+
+const (
+	_ Number = iota
+	One
+	Two
+	Three
+	AnotherOne = One // Duplicate; note that AnotherOne doesn't appear below.
+)
+
+func main() {
+	ck(One, "One")
+	ck(Two, "Two")
+	ck(Three, "Three")
+	ck(AnotherOne, "One")
+	ck(127, "Number(127)")
+}
+
+func ck(num Number, str string) {
+	if fmt.Sprint(num) != str {
+		panic("number.go: " + str)
+	}
+}
diff --git a/third_party/go.tools/cmd/stringer/testdata/prime.go b/third_party/go.tools/cmd/stringer/testdata/prime.go
new file mode 100644
index 0000000..f551a1a
--- /dev/null
+++ b/third_party/go.tools/cmd/stringer/testdata/prime.go
@@ -0,0 +1,56 @@
+// Copyright 2014 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.
+
+// Enough gaps to trigger a map implementation of the method.
+// Also includes a duplicate to test that it doesn't cause problems
+
+package main
+
+import "fmt"
+
+type Prime int
+
+const (
+	p2  Prime = 2
+	p3  Prime = 3
+	p5  Prime = 5
+	p7  Prime = 7
+	p77 Prime = 7 // Duplicate; note that p77 doesn't appear below.
+	p11 Prime = 11
+	p13 Prime = 13
+	p17 Prime = 17
+	p19 Prime = 19
+	p23 Prime = 23
+	p29 Prime = 29
+	p37 Prime = 31
+	p41 Prime = 41
+	p43 Prime = 43
+)
+
+func main() {
+	ck(0, "Prime(0)")
+	ck(1, "Prime(1)")
+	ck(p2, "p2")
+	ck(p3, "p3")
+	ck(4, "Prime(4)")
+	ck(p5, "p5")
+	ck(p7, "p7")
+	ck(p77, "p7")
+	ck(p11, "p11")
+	ck(p13, "p13")
+	ck(p17, "p17")
+	ck(p19, "p19")
+	ck(p23, "p23")
+	ck(p29, "p29")
+	ck(p37, "p37")
+	ck(p41, "p41")
+	ck(p43, "p43")
+	ck(44, "Prime(44)")
+}
+
+func ck(prime Prime, str string) {
+	if fmt.Sprint(prime) != str {
+		panic("prime.go: " + str)
+	}
+}
diff --git a/third_party/go.tools/cmd/stringer/testdata/unum.go b/third_party/go.tools/cmd/stringer/testdata/unum.go
new file mode 100644
index 0000000..2f8508f
--- /dev/null
+++ b/third_party/go.tools/cmd/stringer/testdata/unum.go
@@ -0,0 +1,38 @@
+// Copyright 2014 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.
+
+// Unsigned integers spanning zero.
+
+package main
+
+import "fmt"
+
+type Unum uint8
+
+const (
+	m_2 Unum = iota + 253
+	m_1
+)
+
+const (
+	m0 Unum = iota
+	m1
+	m2
+)
+
+func main() {
+	ck(^Unum(0)-3, "Unum(252)")
+	ck(m_2, "m_2")
+	ck(m_1, "m_1")
+	ck(m0, "m0")
+	ck(m1, "m1")
+	ck(m2, "m2")
+	ck(3, "Unum(3)")
+}
+
+func ck(unum Unum, str string) {
+	if fmt.Sprint(unum) != str {
+		panic("unum.go: " + str)
+	}
+}
diff --git a/third_party/go.tools/cmd/stringer/util_test.go b/third_party/go.tools/cmd/stringer/util_test.go
new file mode 100644
index 0000000..1aeba6e
--- /dev/null
+++ b/third_party/go.tools/cmd/stringer/util_test.go
@@ -0,0 +1,77 @@
+// Copyright 2014 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.
+
+// This file contains tests for some of the internal functions.
+
+package main
+
+import (
+	"fmt"
+	"testing"
+)
+
+// Helpers to save typing in the test cases.
+type u []uint64
+type uu [][]uint64
+
+type SplitTest struct {
+	input  u
+	output uu
+	signed bool
+}
+
+var (
+	m2  = uint64(2)
+	m1  = uint64(1)
+	m0  = uint64(0)
+	m_1 = ^uint64(0)     // -1 when signed.
+	m_2 = ^uint64(0) - 1 // -2 when signed.
+)
+
+var splitTests = []SplitTest{
+	// No need for a test for the empty case; that's picked off before splitIntoRuns.
+	// Single value.
+	{u{1}, uu{u{1}}, false},
+	// Out of order.
+	{u{3, 2, 1}, uu{u{1, 2, 3}}, true},
+	// Out of order.
+	{u{3, 2, 1}, uu{u{1, 2, 3}}, false},
+	// A gap at the beginning.
+	{u{1, 33, 32, 31}, uu{u{1}, u{31, 32, 33}}, true},
+	// A gap in the middle, in mixed order.
+	{u{33, 7, 32, 31, 9, 8}, uu{u{7, 8, 9}, u{31, 32, 33}}, true},
+	// Gaps throughout
+	{u{33, 44, 1, 32, 45, 31}, uu{u{1}, u{31, 32, 33}, u{44, 45}}, true},
+	// Unsigned values spanning 0.
+	{u{m1, m0, m_1, m2, m_2}, uu{u{m0, m1, m2}, u{m_2, m_1}}, false},
+	// Signed values spanning 0
+	{u{m1, m0, m_1, m2, m_2}, uu{u{m_2, m_1, m0, m1, m2}}, true},
+}
+
+func TestSplitIntoRuns(t *testing.T) {
+Outer:
+	for n, test := range splitTests {
+		values := make([]Value, len(test.input))
+		for i, v := range test.input {
+			values[i] = Value{"", v, test.signed, fmt.Sprint(v)}
+		}
+		runs := splitIntoRuns(values)
+		if len(runs) != len(test.output) {
+			t.Errorf("#%d: %v: got %d runs; expected %d", n, test.input, len(runs), len(test.output))
+			continue
+		}
+		for i, run := range runs {
+			if len(run) != len(test.output[i]) {
+				t.Errorf("#%d: got %v; expected %v", n, runs, test.output)
+				continue Outer
+			}
+			for j, v := range run {
+				if v.value != test.output[i][j] {
+					t.Errorf("#%d: got %v; expected %v", n, runs, test.output)
+					continue Outer
+				}
+			}
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/asmdecl.go b/third_party/go.tools/cmd/vet/asmdecl.go
new file mode 100644
index 0000000..954ffbd
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/asmdecl.go
@@ -0,0 +1,650 @@
+// Copyright 2013 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.
+
+// Identify mismatches between assembly files and Go func declarations.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+// 'kind' is a kind of assembly variable.
+// The kinds 1, 2, 4, 8 stand for values of that size.
+type asmKind int
+
+// These special kinds are not valid sizes.
+const (
+	asmString asmKind = 100 + iota
+	asmSlice
+	asmInterface
+	asmEmptyInterface
+)
+
+// An asmArch describes assembly parameters for an architecture
+type asmArch struct {
+	name      string
+	ptrSize   int
+	intSize   int
+	maxAlign  int
+	bigEndian bool
+	stack     string
+	lr        bool
+}
+
+// An asmFunc describes the expected variables for a function on a given architecture.
+type asmFunc struct {
+	arch        *asmArch
+	size        int // size of all arguments
+	vars        map[string]*asmVar
+	varByOffset map[int]*asmVar
+}
+
+// An asmVar describes a single assembly variable.
+type asmVar struct {
+	name  string
+	kind  asmKind
+	typ   string
+	off   int
+	size  int
+	inner []*asmVar
+}
+
+var (
+	asmArch386       = asmArch{"386", 4, 4, 4, false, "SP", false}
+	asmArchArm       = asmArch{"arm", 4, 4, 4, false, "R13", true}
+	asmArchAmd64     = asmArch{"amd64", 8, 8, 8, false, "SP", false}
+	asmArchAmd64p32  = asmArch{"amd64p32", 4, 4, 8, false, "SP", false}
+	asmArchPower64   = asmArch{"power64", 8, 8, 8, true, "R1", true}
+	asmArchPower64LE = asmArch{"power64le", 8, 8, 8, false, "R1", true}
+
+	arches = []*asmArch{
+		&asmArch386,
+		&asmArchArm,
+		&asmArchAmd64,
+		&asmArchAmd64p32,
+		&asmArchPower64,
+		&asmArchPower64LE,
+	}
+)
+
+var (
+	re           = regexp.MustCompile
+	asmPlusBuild = re(`//\s+\+build\s+([^\n]+)`)
+	asmTEXT      = re(`\bTEXT\b.*·([^\(]+)\(SB\)(?:\s*,\s*([0-9A-Z|+]+))?(?:\s*,\s*\$(-?[0-9]+)(?:-([0-9]+))?)?`)
+	asmDATA      = re(`\b(DATA|GLOBL)\b`)
+	asmNamedFP   = re(`([a-zA-Z0-9_\xFF-\x{10FFFF}]+)(?:\+([0-9]+))\(FP\)`)
+	asmUnnamedFP = re(`[^+\-0-9]](([0-9]+)\(FP\))`)
+	asmSP        = re(`[^+\-0-9](([0-9]+)\(([A-Z0-9]+)\))`)
+	asmOpcode    = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`)
+	power64Suff  = re(`([BHWD])(ZU|Z|U|BR)?$`)
+)
+
+func asmCheck(pkg *Package) {
+	if !vet("asmdecl") {
+		return
+	}
+
+	// No work if no assembly files.
+	if !pkg.hasFileWithSuffix(".s") {
+		return
+	}
+
+	// Gather declarations. knownFunc[name][arch] is func description.
+	knownFunc := make(map[string]map[string]*asmFunc)
+
+	for _, f := range pkg.files {
+		if f.file != nil {
+			for _, decl := range f.file.Decls {
+				if decl, ok := decl.(*ast.FuncDecl); ok && decl.Body == nil {
+					knownFunc[decl.Name.Name] = f.asmParseDecl(decl)
+				}
+			}
+		}
+	}
+
+	for _, f := range pkg.files {
+		if !strings.HasSuffix(f.name, ".s") {
+			continue
+		}
+		Println("Checking file", f.name)
+
+		// Determine architecture from file name if possible.
+		var arch string
+		var archDef *asmArch
+		for _, a := range arches {
+			if strings.HasSuffix(f.name, "_"+a.name+".s") {
+				arch = a.name
+				archDef = a
+				break
+			}
+		}
+
+		lines := strings.SplitAfter(string(f.content), "\n")
+		var (
+			fn                 *asmFunc
+			fnName             string
+			localSize, argSize int
+			wroteSP            bool
+			haveRetArg         bool
+			retLine            []int
+		)
+
+		flushRet := func() {
+			if fn != nil && fn.vars["ret"] != nil && !haveRetArg && len(retLine) > 0 {
+				v := fn.vars["ret"]
+				for _, line := range retLine {
+					f.Badf(token.NoPos, "%s:%d: [%s] %s: RET without writing to %d-byte ret+%d(FP)", f.name, line, arch, fnName, v.size, v.off)
+				}
+			}
+			retLine = nil
+		}
+		for lineno, line := range lines {
+			lineno++
+
+			badf := func(format string, args ...interface{}) {
+				f.Badf(token.NoPos, "%s:%d: [%s] %s: %s", f.name, lineno, arch, fnName, fmt.Sprintf(format, args...))
+			}
+
+			if arch == "" {
+				// Determine architecture from +build line if possible.
+				if m := asmPlusBuild.FindStringSubmatch(line); m != nil {
+				Fields:
+					for _, fld := range strings.Fields(m[1]) {
+						for _, a := range arches {
+							if a.name == fld {
+								arch = a.name
+								archDef = a
+								break Fields
+							}
+						}
+					}
+				}
+			}
+
+			if m := asmTEXT.FindStringSubmatch(line); m != nil {
+				flushRet()
+				if arch == "" {
+					f.Warnf(token.NoPos, "%s: cannot determine architecture for assembly file", f.name)
+					return
+				}
+				fnName = m[1]
+				fn = knownFunc[m[1]][arch]
+				if fn != nil {
+					size, _ := strconv.Atoi(m[4])
+					if size != fn.size && (m[2] != "7" && !strings.Contains(m[2], "NOSPLIT") || size != 0) {
+						badf("wrong argument size %d; expected $...-%d", size, fn.size)
+					}
+				}
+				localSize, _ = strconv.Atoi(m[3])
+				localSize += archDef.intSize
+				if archDef.lr {
+					// Account for caller's saved LR
+					localSize += archDef.intSize
+				}
+				argSize, _ = strconv.Atoi(m[4])
+				wroteSP = false
+				haveRetArg = false
+				continue
+			} else if strings.Contains(line, "TEXT") && strings.Contains(line, "SB") {
+				// function, but not visible from Go (didn't match asmTEXT), so stop checking
+				flushRet()
+				fn = nil
+				fnName = ""
+				continue
+			}
+
+			if strings.Contains(line, "RET") {
+				retLine = append(retLine, lineno)
+			}
+
+			if fnName == "" {
+				continue
+			}
+
+			if asmDATA.FindStringSubmatch(line) != nil {
+				fn = nil
+			}
+
+			if archDef == nil {
+				continue
+			}
+
+			if strings.Contains(line, ", "+archDef.stack) || strings.Contains(line, ",\t"+archDef.stack) {
+				wroteSP = true
+				continue
+			}
+
+			for _, m := range asmSP.FindAllStringSubmatch(line, -1) {
+				if m[3] != archDef.stack || wroteSP {
+					continue
+				}
+				off := 0
+				if m[1] != "" {
+					off, _ = strconv.Atoi(m[2])
+				}
+				if off >= localSize {
+					if fn != nil {
+						v := fn.varByOffset[off-localSize]
+						if v != nil {
+							badf("%s should be %s+%d(FP)", m[1], v.name, off-localSize)
+							continue
+						}
+					}
+					if off >= localSize+argSize {
+						badf("use of %s points beyond argument frame", m[1])
+						continue
+					}
+					badf("use of %s to access argument frame", m[1])
+				}
+			}
+
+			if fn == nil {
+				continue
+			}
+
+			for _, m := range asmUnnamedFP.FindAllStringSubmatch(line, -1) {
+				badf("use of unnamed argument %s", m[1])
+			}
+
+			for _, m := range asmNamedFP.FindAllStringSubmatch(line, -1) {
+				name := m[1]
+				off := 0
+				if m[2] != "" {
+					off, _ = strconv.Atoi(m[2])
+				}
+				if name == "ret" || strings.HasPrefix(name, "ret_") {
+					haveRetArg = true
+				}
+				v := fn.vars[name]
+				if v == nil {
+					// Allow argframe+0(FP).
+					if name == "argframe" && off == 0 {
+						continue
+					}
+					v = fn.varByOffset[off]
+					if v != nil {
+						badf("unknown variable %s; offset %d is %s+%d(FP)", name, off, v.name, v.off)
+					} else {
+						badf("unknown variable %s", name)
+					}
+					continue
+				}
+				asmCheckVar(badf, fn, line, m[0], off, v)
+			}
+		}
+		flushRet()
+	}
+}
+
+// asmParseDecl parses a function decl for expected assembly variables.
+func (f *File) asmParseDecl(decl *ast.FuncDecl) map[string]*asmFunc {
+	var (
+		arch   *asmArch
+		fn     *asmFunc
+		offset int
+		failed bool
+	)
+
+	addVar := func(outer string, v asmVar) {
+		if vo := fn.vars[outer]; vo != nil {
+			vo.inner = append(vo.inner, &v)
+		}
+		fn.vars[v.name] = &v
+		for i := 0; i < v.size; i++ {
+			fn.varByOffset[v.off+i] = &v
+		}
+	}
+
+	addParams := func(list []*ast.Field) {
+		for i, fld := range list {
+			// Determine alignment, size, and kind of type in declaration.
+			var align, size int
+			var kind asmKind
+			names := fld.Names
+			typ := f.gofmt(fld.Type)
+			switch t := fld.Type.(type) {
+			default:
+				switch typ {
+				default:
+					f.Warnf(fld.Type.Pos(), "unknown assembly argument type %s", typ)
+					failed = true
+					return
+				case "int8", "uint8", "byte", "bool":
+					size = 1
+				case "int16", "uint16":
+					size = 2
+				case "int32", "uint32", "float32":
+					size = 4
+				case "int64", "uint64", "float64":
+					align = arch.maxAlign
+					size = 8
+				case "int", "uint":
+					size = arch.intSize
+				case "uintptr", "iword", "Word", "Errno", "unsafe.Pointer":
+					size = arch.ptrSize
+				case "string", "ErrorString":
+					size = arch.ptrSize * 2
+					align = arch.ptrSize
+					kind = asmString
+				}
+			case *ast.ChanType, *ast.FuncType, *ast.MapType, *ast.StarExpr:
+				size = arch.ptrSize
+			case *ast.InterfaceType:
+				align = arch.ptrSize
+				size = 2 * arch.ptrSize
+				if len(t.Methods.List) > 0 {
+					kind = asmInterface
+				} else {
+					kind = asmEmptyInterface
+				}
+			case *ast.ArrayType:
+				if t.Len == nil {
+					size = arch.ptrSize + 2*arch.intSize
+					align = arch.ptrSize
+					kind = asmSlice
+					break
+				}
+				f.Warnf(fld.Type.Pos(), "unsupported assembly argument type %s", typ)
+				failed = true
+			case *ast.StructType:
+				f.Warnf(fld.Type.Pos(), "unsupported assembly argument type %s", typ)
+				failed = true
+			}
+			if align == 0 {
+				align = size
+			}
+			if kind == 0 {
+				kind = asmKind(size)
+			}
+			offset += -offset & (align - 1)
+
+			// Create variable for each name being declared with this type.
+			if len(names) == 0 {
+				name := "unnamed"
+				if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 && &list[0] == &decl.Type.Results.List[0] && i == 0 {
+					// Assume assembly will refer to single unnamed result as r.
+					name = "ret"
+				}
+				names = []*ast.Ident{{Name: name}}
+			}
+			for _, id := range names {
+				name := id.Name
+				addVar("", asmVar{
+					name: name,
+					kind: kind,
+					typ:  typ,
+					off:  offset,
+					size: size,
+				})
+				switch kind {
+				case 8:
+					if arch.ptrSize == 4 {
+						w1, w2 := "lo", "hi"
+						if arch.bigEndian {
+							w1, w2 = w2, w1
+						}
+						addVar(name, asmVar{
+							name: name + "_" + w1,
+							kind: 4,
+							typ:  "half " + typ,
+							off:  offset,
+							size: 4,
+						})
+						addVar(name, asmVar{
+							name: name + "_" + w2,
+							kind: 4,
+							typ:  "half " + typ,
+							off:  offset + 4,
+							size: 4,
+						})
+					}
+
+				case asmEmptyInterface:
+					addVar(name, asmVar{
+						name: name + "_type",
+						kind: asmKind(arch.ptrSize),
+						typ:  "interface type",
+						off:  offset,
+						size: arch.ptrSize,
+					})
+					addVar(name, asmVar{
+						name: name + "_data",
+						kind: asmKind(arch.ptrSize),
+						typ:  "interface data",
+						off:  offset + arch.ptrSize,
+						size: arch.ptrSize,
+					})
+
+				case asmInterface:
+					addVar(name, asmVar{
+						name: name + "_itable",
+						kind: asmKind(arch.ptrSize),
+						typ:  "interface itable",
+						off:  offset,
+						size: arch.ptrSize,
+					})
+					addVar(name, asmVar{
+						name: name + "_data",
+						kind: asmKind(arch.ptrSize),
+						typ:  "interface data",
+						off:  offset + arch.ptrSize,
+						size: arch.ptrSize,
+					})
+
+				case asmSlice:
+					addVar(name, asmVar{
+						name: name + "_base",
+						kind: asmKind(arch.ptrSize),
+						typ:  "slice base",
+						off:  offset,
+						size: arch.ptrSize,
+					})
+					addVar(name, asmVar{
+						name: name + "_len",
+						kind: asmKind(arch.intSize),
+						typ:  "slice len",
+						off:  offset + arch.ptrSize,
+						size: arch.intSize,
+					})
+					addVar(name, asmVar{
+						name: name + "_cap",
+						kind: asmKind(arch.intSize),
+						typ:  "slice cap",
+						off:  offset + arch.ptrSize + arch.intSize,
+						size: arch.intSize,
+					})
+
+				case asmString:
+					addVar(name, asmVar{
+						name: name + "_base",
+						kind: asmKind(arch.ptrSize),
+						typ:  "string base",
+						off:  offset,
+						size: arch.ptrSize,
+					})
+					addVar(name, asmVar{
+						name: name + "_len",
+						kind: asmKind(arch.intSize),
+						typ:  "string len",
+						off:  offset + arch.ptrSize,
+						size: arch.intSize,
+					})
+				}
+				offset += size
+			}
+		}
+	}
+
+	m := make(map[string]*asmFunc)
+	for _, arch = range arches {
+		fn = &asmFunc{
+			arch:        arch,
+			vars:        make(map[string]*asmVar),
+			varByOffset: make(map[int]*asmVar),
+		}
+		offset = 0
+		addParams(decl.Type.Params.List)
+		if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 {
+			offset += -offset & (arch.maxAlign - 1)
+			addParams(decl.Type.Results.List)
+		}
+		fn.size = offset
+		m[arch.name] = fn
+	}
+
+	if failed {
+		return nil
+	}
+	return m
+}
+
+// asmCheckVar checks a single variable reference.
+func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr string, off int, v *asmVar) {
+	m := asmOpcode.FindStringSubmatch(line)
+	if m == nil {
+		if !strings.HasPrefix(strings.TrimSpace(line), "//") {
+			badf("cannot find assembly opcode")
+		}
+		return
+	}
+
+	// Determine operand sizes from instruction.
+	// Typically the suffix suffices, but there are exceptions.
+	var src, dst, kind asmKind
+	op := m[1]
+	switch fn.arch.name + "." + op {
+	case "386.FMOVLP":
+		src, dst = 8, 4
+	case "arm.MOVD":
+		src = 8
+	case "arm.MOVW":
+		src = 4
+	case "arm.MOVH", "arm.MOVHU":
+		src = 2
+	case "arm.MOVB", "arm.MOVBU":
+		src = 1
+	// LEA* opcodes don't really read the second arg.
+	// They just take the address of it.
+	case "386.LEAL":
+		dst = 4
+	case "amd64.LEAQ":
+		dst = 8
+	case "amd64p32.LEAL":
+		dst = 4
+	default:
+		switch fn.arch.name {
+		case "386", "amd64":
+			if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "D") || strings.HasSuffix(op, "DP")) {
+				// FMOVDP, FXCHD, etc
+				src = 8
+				break
+			}
+			if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "F") || strings.HasSuffix(op, "FP")) {
+				// FMOVFP, FXCHF, etc
+				src = 4
+				break
+			}
+			if strings.HasSuffix(op, "SD") {
+				// MOVSD, SQRTSD, etc
+				src = 8
+				break
+			}
+			if strings.HasSuffix(op, "SS") {
+				// MOVSS, SQRTSS, etc
+				src = 4
+				break
+			}
+			if strings.HasPrefix(op, "SET") {
+				// SETEQ, etc
+				src = 1
+				break
+			}
+			switch op[len(op)-1] {
+			case 'B':
+				src = 1
+			case 'W':
+				src = 2
+			case 'L':
+				src = 4
+			case 'D', 'Q':
+				src = 8
+			}
+		case "power64", "power64le":
+			// Strip standard suffixes to reveal size letter.
+			m := power64Suff.FindStringSubmatch(op)
+			if m != nil {
+				switch m[1][0] {
+				case 'B':
+					src = 1
+				case 'H':
+					src = 2
+				case 'W':
+					src = 4
+				case 'D':
+					src = 8
+				}
+			}
+		}
+	}
+	if dst == 0 {
+		dst = src
+	}
+
+	// Determine whether the match we're holding
+	// is the first or second argument.
+	if strings.Index(line, expr) > strings.Index(line, ",") {
+		kind = dst
+	} else {
+		kind = src
+	}
+
+	vk := v.kind
+	vt := v.typ
+	switch vk {
+	case asmInterface, asmEmptyInterface, asmString, asmSlice:
+		// allow reference to first word (pointer)
+		vk = v.inner[0].kind
+		vt = v.inner[0].typ
+	}
+
+	if off != v.off {
+		var inner bytes.Buffer
+		for i, vi := range v.inner {
+			if len(v.inner) > 1 {
+				fmt.Fprintf(&inner, ",")
+			}
+			fmt.Fprintf(&inner, " ")
+			if i == len(v.inner)-1 {
+				fmt.Fprintf(&inner, "or ")
+			}
+			fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
+		}
+		badf("invalid offset %s; expected %s+%d(FP)%s", expr, v.name, v.off, inner.String())
+		return
+	}
+	if kind != 0 && kind != vk {
+		var inner bytes.Buffer
+		if len(v.inner) > 0 {
+			fmt.Fprintf(&inner, " containing")
+			for i, vi := range v.inner {
+				if i > 0 && len(v.inner) > 2 {
+					fmt.Fprintf(&inner, ",")
+				}
+				fmt.Fprintf(&inner, " ")
+				if i > 0 && i == len(v.inner)-1 {
+					fmt.Fprintf(&inner, "and ")
+				}
+				fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
+			}
+		}
+		badf("invalid %s of %s; %s is %d-byte value%s", op, expr, vt, vk, inner.String())
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/assign.go b/third_party/go.tools/cmd/vet/assign.go
new file mode 100644
index 0000000..54c1ae1
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/assign.go
@@ -0,0 +1,49 @@
+// Copyright 2013 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.
+
+/*
+This file contains the code to check for useless assignments.
+*/
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+	"reflect"
+)
+
+func init() {
+	register("assign",
+		"check for useless assignments",
+		checkAssignStmt,
+		assignStmt)
+}
+
+// TODO: should also check for assignments to struct fields inside methods
+// that are on T instead of *T.
+
+// checkAssignStmt checks for assignments of the form "<expr> = <expr>".
+// These are almost always useless, and even when they aren't they are usually a mistake.
+func checkAssignStmt(f *File, node ast.Node) {
+	stmt := node.(*ast.AssignStmt)
+	if stmt.Tok != token.ASSIGN {
+		return // ignore :=
+	}
+	if len(stmt.Lhs) != len(stmt.Rhs) {
+		// If LHS and RHS have different cardinality, they can't be the same.
+		return
+	}
+	for i, lhs := range stmt.Lhs {
+		rhs := stmt.Rhs[i]
+		if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) {
+			continue // short-circuit the heavy-weight gofmt check
+		}
+		le := f.gofmt(lhs)
+		re := f.gofmt(rhs)
+		if le == re {
+			f.Badf(stmt.Pos(), "self-assignment of %s to %s", re, le)
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/atomic.go b/third_party/go.tools/cmd/vet/atomic.go
new file mode 100644
index 0000000..c084f13
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/atomic.go
@@ -0,0 +1,66 @@
+// Copyright 2013 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 (
+	"go/ast"
+	"go/token"
+)
+
+func init() {
+	register("atomic",
+		"check for common mistaken usages of the sync/atomic package",
+		checkAtomicAssignment,
+		assignStmt)
+}
+
+// checkAtomicAssignment walks the assignment statement checking for common
+// mistaken usage of atomic package, such as: x = atomic.AddUint64(&x, 1)
+func checkAtomicAssignment(f *File, node ast.Node) {
+	n := node.(*ast.AssignStmt)
+	if len(n.Lhs) != len(n.Rhs) {
+		return
+	}
+
+	for i, right := range n.Rhs {
+		call, ok := right.(*ast.CallExpr)
+		if !ok {
+			continue
+		}
+		sel, ok := call.Fun.(*ast.SelectorExpr)
+		if !ok {
+			continue
+		}
+		pkg, ok := sel.X.(*ast.Ident)
+		if !ok || pkg.Name != "atomic" {
+			continue
+		}
+
+		switch sel.Sel.Name {
+		case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr":
+			f.checkAtomicAddAssignment(n.Lhs[i], call)
+		}
+	}
+}
+
+// checkAtomicAddAssignment walks the atomic.Add* method calls checking for assigning the return value
+// to the same variable being used in the operation
+func (f *File) checkAtomicAddAssignment(left ast.Expr, call *ast.CallExpr) {
+	if len(call.Args) != 2 {
+		return
+	}
+	arg := call.Args[0]
+	broken := false
+
+	if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND {
+		broken = f.gofmt(left) == f.gofmt(uarg.X)
+	} else if star, ok := left.(*ast.StarExpr); ok {
+		broken = f.gofmt(star.X) == f.gofmt(arg)
+	}
+
+	if broken {
+		f.Bad(left.Pos(), "direct assignment to atomic value")
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/bool.go b/third_party/go.tools/cmd/vet/bool.go
new file mode 100644
index 0000000..e28c258
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/bool.go
@@ -0,0 +1,185 @@
+// Copyright 2014 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.
+
+// This file contains boolean condition tests.
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+func init() {
+	register("bool",
+		"check for mistakes involving boolean operators",
+		checkBool,
+		binaryExpr)
+}
+
+func checkBool(f *File, n ast.Node) {
+	e := n.(*ast.BinaryExpr)
+
+	var op boolOp
+	switch e.Op {
+	case token.LOR:
+		op = or
+	case token.LAND:
+		op = and
+	default:
+		return
+	}
+
+	comm := op.commutativeSets(e)
+	for _, exprs := range comm {
+		op.checkRedundant(f, exprs)
+		op.checkSuspect(f, exprs)
+	}
+}
+
+type boolOp struct {
+	name  string
+	tok   token.Token // token corresponding to this operator
+	badEq token.Token // token corresponding to the equality test that should not be used with this operator
+}
+
+var (
+	or  = boolOp{"or", token.LOR, token.NEQ}
+	and = boolOp{"and", token.LAND, token.EQL}
+)
+
+// commutativeSets returns all side effect free sets of
+// expressions in e that are connected by op.
+// For example, given 'a || b || f() || c || d' with the or op,
+// commutativeSets returns {{b, a}, {d, c}}.
+func (op boolOp) commutativeSets(e *ast.BinaryExpr) [][]ast.Expr {
+	exprs := op.split(e)
+
+	// Partition the slice of expressions into commutative sets.
+	i := 0
+	var sets [][]ast.Expr
+	for j := 0; j <= len(exprs); j++ {
+		if j == len(exprs) || hasSideEffects(exprs[j]) {
+			if i < j {
+				sets = append(sets, exprs[i:j])
+			}
+			i = j + 1
+		}
+	}
+
+	return sets
+}
+
+// checkRedundant checks for expressions of the form
+//   e && e
+//   e || e
+// Exprs must contain only side effect free expressions.
+func (op boolOp) checkRedundant(f *File, exprs []ast.Expr) {
+	seen := make(map[string]bool)
+	for _, e := range exprs {
+		efmt := f.gofmt(e)
+		if seen[efmt] {
+			f.Badf(e.Pos(), "redundant %s: %s %s %s", op.name, efmt, op.tok, efmt)
+		} else {
+			seen[efmt] = true
+		}
+	}
+}
+
+// checkSuspect checks for expressions of the form
+//   x != c1 || x != c2
+//   x == c1 && x == c2
+// where c1 and c2 are constant expressions.
+// If c1 and c2 are the same then it's redundant;
+// if c1 and c2 are different then it's always true or always false.
+// Exprs must contain only side effect free expressions.
+func (op boolOp) checkSuspect(f *File, exprs []ast.Expr) {
+	// seen maps from expressions 'x' to equality expressions 'x != c'.
+	seen := make(map[string]string)
+
+	for _, e := range exprs {
+		bin, ok := e.(*ast.BinaryExpr)
+		if !ok || bin.Op != op.badEq {
+			continue
+		}
+
+		// In order to avoid false positives, restrict to cases
+		// in which one of the operands is constant. We're then
+		// interested in the other operand.
+		// In the rare case in which both operands are constant
+		// (e.g. runtime.GOOS and "windows"), we'll only catch
+		// mistakes if the LHS is repeated, which is how most
+		// code is written.
+		var x ast.Expr
+		switch {
+		case f.pkg.types[bin.Y].Value != nil:
+			x = bin.X
+		case f.pkg.types[bin.X].Value != nil:
+			x = bin.Y
+		default:
+			continue
+		}
+
+		// e is of the form 'x != c' or 'x == c'.
+		xfmt := f.gofmt(x)
+		efmt := f.gofmt(e)
+		if prev, found := seen[xfmt]; found {
+			// checkRedundant handles the case in which efmt == prev.
+			if efmt != prev {
+				f.Badf(e.Pos(), "suspect %s: %s %s %s", op.name, efmt, op.tok, prev)
+			}
+		} else {
+			seen[xfmt] = efmt
+		}
+	}
+}
+
+// hasSideEffects reports whether evaluation of e has side effects.
+func hasSideEffects(e ast.Expr) bool {
+	safe := true
+	ast.Inspect(e, func(node ast.Node) bool {
+		switch n := node.(type) {
+		// Using CallExpr here will catch conversions
+		// as well as function and method invocations.
+		// We'll live with the false negatives for now.
+		case *ast.CallExpr:
+			safe = false
+			return false
+		case *ast.UnaryExpr:
+			if n.Op == token.ARROW {
+				safe = false
+				return false
+			}
+		}
+		return true
+	})
+	return !safe
+}
+
+// split returns a slice of all subexpressions in e that are connected by op.
+// For example, given 'a || (b || c) || d' with the or op,
+// split returns []{d, c, b, a}.
+func (op boolOp) split(e ast.Expr) (exprs []ast.Expr) {
+	for {
+		e = unparen(e)
+		if b, ok := e.(*ast.BinaryExpr); ok && b.Op == op.tok {
+			exprs = append(exprs, op.split(b.Y)...)
+			e = b.X
+		} else {
+			exprs = append(exprs, e)
+			break
+		}
+	}
+	return
+}
+
+func unparen(e ast.Expr) ast.Expr {
+	for {
+		p, ok := e.(*ast.ParenExpr)
+		if !ok {
+			return e
+		}
+		e = p.X
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/buildtag.go b/third_party/go.tools/cmd/vet/buildtag.go
new file mode 100644
index 0000000..2d86edf
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/buildtag.go
@@ -0,0 +1,91 @@
+// Copyright 2013 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 (
+	"bytes"
+	"fmt"
+	"os"
+	"strings"
+	"unicode"
+)
+
+var (
+	nl         = []byte("\n")
+	slashSlash = []byte("//")
+	plusBuild  = []byte("+build")
+)
+
+// checkBuildTag checks that build tags are in the correct location and well-formed.
+func checkBuildTag(name string, data []byte) {
+	if !vet("buildtags") {
+		return
+	}
+	lines := bytes.SplitAfter(data, nl)
+
+	// Determine cutpoint where +build comments are no longer valid.
+	// They are valid in leading // comments in the file followed by
+	// a blank line.
+	var cutoff int
+	for i, line := range lines {
+		line = bytes.TrimSpace(line)
+		if len(line) == 0 {
+			cutoff = i
+			continue
+		}
+		if bytes.HasPrefix(line, slashSlash) {
+			continue
+		}
+		break
+	}
+
+	for i, line := range lines {
+		line = bytes.TrimSpace(line)
+		if !bytes.HasPrefix(line, slashSlash) {
+			continue
+		}
+		text := bytes.TrimSpace(line[2:])
+		if bytes.HasPrefix(text, plusBuild) {
+			fields := bytes.Fields(text)
+			if !bytes.Equal(fields[0], plusBuild) {
+				// Comment is something like +buildasdf not +build.
+				fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1)
+				continue
+			}
+			if i >= cutoff {
+				fmt.Fprintf(os.Stderr, "%s:%d: +build comment must appear before package clause and be followed by a blank line\n", name, i+1)
+				setExit(1)
+				continue
+			}
+			// Check arguments.
+		Args:
+			for _, arg := range fields[1:] {
+				for _, elem := range strings.Split(string(arg), ",") {
+					if strings.HasPrefix(elem, "!!") {
+						fmt.Fprintf(os.Stderr, "%s:%d: invalid double negative in build constraint: %s\n", name, i+1, arg)
+						setExit(1)
+						break Args
+					}
+					if strings.HasPrefix(elem, "!") {
+						elem = elem[1:]
+					}
+					for _, c := range elem {
+						if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
+							fmt.Fprintf(os.Stderr, "%s:%d: invalid non-alphanumeric build constraint: %s\n", name, i+1, arg)
+							setExit(1)
+							break Args
+						}
+					}
+				}
+			}
+			continue
+		}
+		// Comment with +build but not at beginning.
+		if bytes.Contains(line, plusBuild) && i < cutoff {
+			fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1)
+			continue
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/composite.go b/third_party/go.tools/cmd/vet/composite.go
new file mode 100644
index 0000000..6fad102
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/composite.go
@@ -0,0 +1,125 @@
+// 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.
+
+// This file contains the test for unkeyed struct literals.
+
+package main
+
+import (
+	"flag"
+	"go/ast"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/cmd/vet/whitelist"
+)
+
+var compositeWhiteList = flag.Bool("compositewhitelist", true, "use composite white list; for testing only")
+
+func init() {
+	register("composites",
+		"check that composite literals used field-keyed elements",
+		checkUnkeyedLiteral,
+		compositeLit)
+}
+
+// checkUnkeyedLiteral checks if a composite literal is a struct literal with
+// unkeyed fields.
+func checkUnkeyedLiteral(f *File, node ast.Node) {
+	c := node.(*ast.CompositeLit)
+	typ := c.Type
+	for {
+		if typ1, ok := c.Type.(*ast.ParenExpr); ok {
+			typ = typ1
+			continue
+		}
+		break
+	}
+
+	switch typ.(type) {
+	case *ast.ArrayType:
+		return
+	case *ast.MapType:
+		return
+	case *ast.StructType:
+		return // a literal struct type does not need to use keys
+	case *ast.Ident:
+		// A simple type name like t or T does not need keys either,
+		// since it is almost certainly declared in the current package.
+		// (The exception is names being used via import . "pkg", but
+		// those are already breaking the Go 1 compatibility promise,
+		// so not reporting potential additional breakage seems okay.)
+		return
+	}
+
+	// Otherwise the type is a selector like pkg.Name.
+	// We only care if pkg.Name is a struct, not if it's a map, array, or slice.
+	isStruct, typeString := f.pkg.isStruct(c)
+	if !isStruct {
+		return
+	}
+
+	if typeString == "" { // isStruct doesn't know
+		typeString = f.gofmt(typ)
+	}
+
+	// It's a struct, or we can't tell it's not a struct because we don't have types.
+
+	// Check if the CompositeLit contains an unkeyed field.
+	allKeyValue := true
+	for _, e := range c.Elts {
+		if _, ok := e.(*ast.KeyValueExpr); !ok {
+			allKeyValue = false
+			break
+		}
+	}
+	if allKeyValue {
+		return
+	}
+
+	// Check that the CompositeLit's type has the form pkg.Typ.
+	s, ok := c.Type.(*ast.SelectorExpr)
+	if !ok {
+		return
+	}
+	pkg, ok := s.X.(*ast.Ident)
+	if !ok {
+		return
+	}
+
+	// Convert the package name to an import path, and compare to a whitelist.
+	path := pkgPath(f, pkg.Name)
+	if path == "" {
+		f.Badf(c.Pos(), "unresolvable package for %s.%s literal", pkg.Name, s.Sel.Name)
+		return
+	}
+	typeName := path + "." + s.Sel.Name
+	if *compositeWhiteList && whitelist.UnkeyedLiteral[typeName] {
+		return
+	}
+
+	f.Bad(c.Pos(), typeString+" composite literal uses unkeyed fields")
+}
+
+// pkgPath returns the import path "image/png" for the package name "png".
+//
+// This is based purely on syntax and convention, and not on the imported
+// package's contents. It will be incorrect if a package name differs from the
+// leaf element of the import path, or if the package was a dot import.
+func pkgPath(f *File, pkgName string) (path string) {
+	for _, x := range f.file.Imports {
+		s := strings.Trim(x.Path.Value, `"`)
+		if x.Name != nil {
+			// Catch `import pkgName "foo/bar"`.
+			if x.Name.Name == pkgName {
+				return s
+			}
+		} else {
+			// Catch `import "pkgName"` or `import "foo/bar/pkgName"`.
+			if s == pkgName || strings.HasSuffix(s, "/"+pkgName) {
+				return s
+			}
+		}
+	}
+	return ""
+}
diff --git a/third_party/go.tools/cmd/vet/copylock.go b/third_party/go.tools/cmd/vet/copylock.go
new file mode 100644
index 0000000..ea0d2a6
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/copylock.go
@@ -0,0 +1,155 @@
+// Copyright 2013 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.
+
+// This file contains the code to check that locks are not passed by value.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func init() {
+	register("copylocks",
+		"check that locks are not passed by value",
+		checkCopyLocks,
+		funcDecl, rangeStmt)
+}
+
+// checkCopyLocks checks whether node might
+// inadvertently copy a lock.
+func checkCopyLocks(f *File, node ast.Node) {
+	switch node := node.(type) {
+	case *ast.RangeStmt:
+		checkCopyLocksRange(f, node)
+	case *ast.FuncDecl:
+		checkCopyLocksFunc(f, node)
+	}
+}
+
+// checkCopyLocksFunc checks whether a function might
+// inadvertently copy a lock, by checking whether
+// its receiver, parameters, or return values
+// are locks.
+func checkCopyLocksFunc(f *File, d *ast.FuncDecl) {
+	if d.Recv != nil && len(d.Recv.List) > 0 {
+		expr := d.Recv.List[0].Type
+		if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
+			f.Badf(expr.Pos(), "%s passes Lock by value: %v", d.Name.Name, path)
+		}
+	}
+
+	if d.Type.Params != nil {
+		for _, field := range d.Type.Params.List {
+			expr := field.Type
+			if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
+				f.Badf(expr.Pos(), "%s passes Lock by value: %v", d.Name.Name, path)
+			}
+		}
+	}
+
+	if d.Type.Results != nil {
+		for _, field := range d.Type.Results.List {
+			expr := field.Type
+			if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
+				f.Badf(expr.Pos(), "%s returns Lock by value: %v", d.Name.Name, path)
+			}
+		}
+	}
+}
+
+// checkCopyLocksRange checks whether a range statement
+// might inadvertently copy a lock by checking whether
+// any of the range variables are locks.
+func checkCopyLocksRange(f *File, r *ast.RangeStmt) {
+	checkCopyLocksRangeVar(f, r.Tok, r.Key)
+	checkCopyLocksRangeVar(f, r.Tok, r.Value)
+}
+
+func checkCopyLocksRangeVar(f *File, rtok token.Token, e ast.Expr) {
+	if e == nil {
+		return
+	}
+	id, isId := e.(*ast.Ident)
+	if isId && id.Name == "_" {
+		return
+	}
+
+	var typ types.Type
+	if rtok == token.DEFINE {
+		if !isId {
+			return
+		}
+		obj := f.pkg.defs[id]
+		if obj == nil {
+			return
+		}
+		typ = obj.Type()
+	} else {
+		typ = f.pkg.types[e].Type
+	}
+
+	if typ == nil {
+		return
+	}
+	if path := lockPath(f.pkg.typesPkg, typ); path != nil {
+		f.Badf(e.Pos(), "range var %s copies Lock: %v", f.gofmt(e), path)
+	}
+}
+
+type typePath []types.Type
+
+// String pretty-prints a typePath.
+func (path typePath) String() string {
+	n := len(path)
+	var buf bytes.Buffer
+	for i := range path {
+		if i > 0 {
+			fmt.Fprint(&buf, " contains ")
+		}
+		// The human-readable path is in reverse order, outermost to innermost.
+		fmt.Fprint(&buf, path[n-i-1].String())
+	}
+	return buf.String()
+}
+
+// lockPath returns a typePath describing the location of a lock value
+// contained in typ. If there is no contained lock, it returns nil.
+func lockPath(tpkg *types.Package, typ types.Type) typePath {
+	if typ == nil {
+		return nil
+	}
+
+	// We're only interested in the case in which the underlying
+	// type is a struct. (Interfaces and pointers are safe to copy.)
+	styp, ok := typ.Underlying().(*types.Struct)
+	if !ok {
+		return nil
+	}
+
+	// We're looking for cases in which a reference to this type
+	// can be locked, but a value cannot. This differentiates
+	// embedded interfaces from embedded values.
+	if plock := types.NewMethodSet(types.NewPointer(typ)).Lookup(tpkg, "Lock"); plock != nil {
+		if lock := types.NewMethodSet(typ).Lookup(tpkg, "Lock"); lock == nil {
+			return []types.Type{typ}
+		}
+	}
+
+	nfields := styp.NumFields()
+	for i := 0; i < nfields; i++ {
+		ftyp := styp.Field(i).Type()
+		subpath := lockPath(tpkg, ftyp)
+		if subpath != nil {
+			return append(subpath, typ)
+		}
+	}
+
+	return nil
+}
diff --git a/third_party/go.tools/cmd/vet/deadcode.go b/third_party/go.tools/cmd/vet/deadcode.go
new file mode 100644
index 0000000..3b306c2
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/deadcode.go
@@ -0,0 +1,296 @@
+// Copyright 2013 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.
+
+// Check for syntactically unreachable code.
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+func init() {
+	register("unreachable",
+		"check for unreachable code",
+		checkUnreachable,
+		funcDecl, funcLit)
+}
+
+type deadState struct {
+	f           *File
+	hasBreak    map[ast.Stmt]bool
+	hasGoto     map[string]bool
+	labels      map[string]ast.Stmt
+	breakTarget ast.Stmt
+
+	reachable bool
+}
+
+// checkUnreachable checks a function body for dead code.
+func checkUnreachable(f *File, node ast.Node) {
+	var body *ast.BlockStmt
+	switch n := node.(type) {
+	case *ast.FuncDecl:
+		body = n.Body
+	case *ast.FuncLit:
+		body = n.Body
+	}
+	if body == nil {
+		return
+	}
+
+	d := &deadState{
+		f:        f,
+		hasBreak: make(map[ast.Stmt]bool),
+		hasGoto:  make(map[string]bool),
+		labels:   make(map[string]ast.Stmt),
+	}
+
+	d.findLabels(body)
+
+	d.reachable = true
+	d.findDead(body)
+}
+
+// findLabels gathers information about the labels defined and used by stmt
+// and about which statements break, whether a label is involved or not.
+func (d *deadState) findLabels(stmt ast.Stmt) {
+	switch x := stmt.(type) {
+	default:
+		d.f.Warnf(x.Pos(), "internal error in findLabels: unexpected statement %T", x)
+
+	case *ast.AssignStmt,
+		*ast.BadStmt,
+		*ast.DeclStmt,
+		*ast.DeferStmt,
+		*ast.EmptyStmt,
+		*ast.ExprStmt,
+		*ast.GoStmt,
+		*ast.IncDecStmt,
+		*ast.ReturnStmt,
+		*ast.SendStmt:
+		// no statements inside
+
+	case *ast.BlockStmt:
+		for _, stmt := range x.List {
+			d.findLabels(stmt)
+		}
+
+	case *ast.BranchStmt:
+		switch x.Tok {
+		case token.GOTO:
+			if x.Label != nil {
+				d.hasGoto[x.Label.Name] = true
+			}
+
+		case token.BREAK:
+			stmt := d.breakTarget
+			if x.Label != nil {
+				stmt = d.labels[x.Label.Name]
+			}
+			if stmt != nil {
+				d.hasBreak[stmt] = true
+			}
+		}
+
+	case *ast.IfStmt:
+		d.findLabels(x.Body)
+		if x.Else != nil {
+			d.findLabels(x.Else)
+		}
+
+	case *ast.LabeledStmt:
+		d.labels[x.Label.Name] = x.Stmt
+		d.findLabels(x.Stmt)
+
+	// These cases are all the same, but the x.Body only works
+	// when the specific type of x is known, so the cases cannot
+	// be merged.
+	case *ast.ForStmt:
+		outer := d.breakTarget
+		d.breakTarget = x
+		d.findLabels(x.Body)
+		d.breakTarget = outer
+
+	case *ast.RangeStmt:
+		outer := d.breakTarget
+		d.breakTarget = x
+		d.findLabels(x.Body)
+		d.breakTarget = outer
+
+	case *ast.SelectStmt:
+		outer := d.breakTarget
+		d.breakTarget = x
+		d.findLabels(x.Body)
+		d.breakTarget = outer
+
+	case *ast.SwitchStmt:
+		outer := d.breakTarget
+		d.breakTarget = x
+		d.findLabels(x.Body)
+		d.breakTarget = outer
+
+	case *ast.TypeSwitchStmt:
+		outer := d.breakTarget
+		d.breakTarget = x
+		d.findLabels(x.Body)
+		d.breakTarget = outer
+
+	case *ast.CommClause:
+		for _, stmt := range x.Body {
+			d.findLabels(stmt)
+		}
+
+	case *ast.CaseClause:
+		for _, stmt := range x.Body {
+			d.findLabels(stmt)
+		}
+	}
+}
+
+// findDead walks the statement looking for dead code.
+// If d.reachable is false on entry, stmt itself is dead.
+// When findDead returns, d.reachable tells whether the
+// statement following stmt is reachable.
+func (d *deadState) findDead(stmt ast.Stmt) {
+	// Is this a labeled goto target?
+	// If so, assume it is reachable due to the goto.
+	// This is slightly conservative, in that we don't
+	// check that the goto is reachable, so
+	//	L: goto L
+	// will not provoke a warning.
+	// But it's good enough.
+	if x, isLabel := stmt.(*ast.LabeledStmt); isLabel && d.hasGoto[x.Label.Name] {
+		d.reachable = true
+	}
+
+	if !d.reachable {
+		switch stmt.(type) {
+		case *ast.EmptyStmt:
+			// do not warn about unreachable empty statements
+		default:
+			d.f.Bad(stmt.Pos(), "unreachable code")
+			d.reachable = true // silence error about next statement
+		}
+	}
+
+	switch x := stmt.(type) {
+	default:
+		d.f.Warnf(x.Pos(), "internal error in findDead: unexpected statement %T", x)
+
+	case *ast.AssignStmt,
+		*ast.BadStmt,
+		*ast.DeclStmt,
+		*ast.DeferStmt,
+		*ast.EmptyStmt,
+		*ast.GoStmt,
+		*ast.IncDecStmt,
+		*ast.SendStmt:
+		// no control flow
+
+	case *ast.BlockStmt:
+		for _, stmt := range x.List {
+			d.findDead(stmt)
+		}
+
+	case *ast.BranchStmt:
+		switch x.Tok {
+		case token.BREAK, token.GOTO, token.FALLTHROUGH:
+			d.reachable = false
+		case token.CONTINUE:
+			// NOTE: We accept "continue" statements as terminating.
+			// They are not necessary in the spec definition of terminating,
+			// because a continue statement cannot be the final statement
+			// before a return. But for the more general problem of syntactically
+			// identifying dead code, continue redirects control flow just
+			// like the other terminating statements.
+			d.reachable = false
+		}
+
+	case *ast.ExprStmt:
+		// Call to panic?
+		call, ok := x.X.(*ast.CallExpr)
+		if ok {
+			name, ok := call.Fun.(*ast.Ident)
+			if ok && name.Name == "panic" && name.Obj == nil {
+				d.reachable = false
+			}
+		}
+
+	case *ast.ForStmt:
+		d.findDead(x.Body)
+		d.reachable = x.Cond != nil || d.hasBreak[x]
+
+	case *ast.IfStmt:
+		d.findDead(x.Body)
+		if x.Else != nil {
+			r := d.reachable
+			d.reachable = true
+			d.findDead(x.Else)
+			d.reachable = d.reachable || r
+		} else {
+			// might not have executed if statement
+			d.reachable = true
+		}
+
+	case *ast.LabeledStmt:
+		d.findDead(x.Stmt)
+
+	case *ast.RangeStmt:
+		d.findDead(x.Body)
+		d.reachable = true
+
+	case *ast.ReturnStmt:
+		d.reachable = false
+
+	case *ast.SelectStmt:
+		// NOTE: Unlike switch and type switch below, we don't care
+		// whether a select has a default, because a select without a
+		// default blocks until one of the cases can run. That's different
+		// from a switch without a default, which behaves like it has
+		// a default with an empty body.
+		anyReachable := false
+		for _, comm := range x.Body.List {
+			d.reachable = true
+			for _, stmt := range comm.(*ast.CommClause).Body {
+				d.findDead(stmt)
+			}
+			anyReachable = anyReachable || d.reachable
+		}
+		d.reachable = anyReachable || d.hasBreak[x]
+
+	case *ast.SwitchStmt:
+		anyReachable := false
+		hasDefault := false
+		for _, cas := range x.Body.List {
+			cc := cas.(*ast.CaseClause)
+			if cc.List == nil {
+				hasDefault = true
+			}
+			d.reachable = true
+			for _, stmt := range cc.Body {
+				d.findDead(stmt)
+			}
+			anyReachable = anyReachable || d.reachable
+		}
+		d.reachable = anyReachable || d.hasBreak[x] || !hasDefault
+
+	case *ast.TypeSwitchStmt:
+		anyReachable := false
+		hasDefault := false
+		for _, cas := range x.Body.List {
+			cc := cas.(*ast.CaseClause)
+			if cc.List == nil {
+				hasDefault = true
+			}
+			d.reachable = true
+			for _, stmt := range cc.Body {
+				d.findDead(stmt)
+			}
+			anyReachable = anyReachable || d.reachable
+		}
+		d.reachable = anyReachable || d.hasBreak[x] || !hasDefault
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/doc.go b/third_party/go.tools/cmd/vet/doc.go
new file mode 100644
index 0000000..e90a8b8
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/doc.go
@@ -0,0 +1,182 @@
+// Copyright 2010 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.
+
+/*
+
+Vet examines Go source code and reports suspicious constructs, such as Printf
+calls whose arguments do not align with the format string. Vet uses heuristics
+that do not guarantee all reports are genuine problems, but it can find errors
+not caught by the compilers.
+
+It can be invoked three ways:
+
+By package, from the go tool:
+	go vet package/path/name
+vets the package whose path is provided.
+
+By files:
+	go tool vet source/directory/*.go
+vets the files named, all of which must be in the same package.
+
+By directory:
+	go tool vet source/directory
+recursively descends the directory, vetting each file in isolation.
+Package-level type-checking is disabled, so the vetting is weaker.
+
+Vet's exit code is 2 for erroneous invocation of the tool, 1 if a
+problem was reported, and 0 otherwise. Note that the tool does not
+check every possible problem and depends on unreliable heuristics
+so it should be used as guidance only, not as a firm indicator of
+program correctness.
+
+By default all checks are performed. If any flags are explicitly set
+to true, only those tests are run. Conversely, if any flag is
+explicitly set to false, only those tests are disabled.
+Thus -printf=true runs the printf check, -printf=false runs all checks
+except the printf check.
+
+Available checks:
+
+Printf family
+
+Flag: -printf
+
+Suspicious calls to functions in the Printf family, including any functions
+with these names, disregarding case:
+	Print Printf Println
+	Fprint Fprintf Fprintln
+	Sprint Sprintf Sprintln
+	Error Errorf
+	Fatal Fatalf
+	Log Logf
+	Panic Panicf Panicln
+If the function name ends with an 'f', the function is assumed to take
+a format descriptor string in the manner of fmt.Printf. If not, vet
+complains about arguments that look like format descriptor strings.
+
+It also checks for errors such as using a Writer as the first argument of
+Printf.
+
+Methods
+
+Flag: -methods
+
+Non-standard signatures for methods with familiar names, including:
+	Format GobEncode GobDecode MarshalJSON MarshalXML
+	Peek ReadByte ReadFrom ReadRune Scan Seek
+	UnmarshalJSON UnreadByte UnreadRune WriteByte
+	WriteTo
+
+Struct tags
+
+Flag: -structtags
+
+Struct tags that do not follow the format understood by reflect.StructTag.Get.
+Well-known encoding struct tags (json, xml) used with unexported fields.
+
+Unkeyed composite literals
+
+Flag: -composites
+
+Composite struct literals that do not use the field-keyed syntax.
+
+Assembly declarations
+
+Flag: -asmdecl
+
+Mismatches between assembly files and Go function declarations.
+
+Useless assignments
+
+Flag: -assign
+
+Check for useless assignments.
+
+Atomic mistakes
+
+Flag: -atomic
+
+Common mistaken usages of the sync/atomic package.
+
+Boolean conditions
+
+Flag: -bool
+
+Mistakes involving boolean operators.
+
+Build tags
+
+Flag: -buildtags
+
+Badly formed or misplaced +build tags.
+
+Copying locks
+
+Flag: -copylocks
+
+Locks that are erroneously passed by value.
+
+Nil function comparison
+
+Flag: -nilfunc
+
+Comparisons between functions and nil.
+
+Range loop variables
+
+Flag: -rangeloops
+
+Incorrect uses of range loop variables in closures.
+
+Unreachable code
+
+Flag: -unreachable
+
+Unreachable code.
+
+Shadowed variables
+
+Flag: -shadow=false (experimental; must be set explicitly)
+
+Variables that may have been unintentionally shadowed.
+
+Misuse of unsafe Pointers
+
+Flag: -unsafeptr
+
+Likely incorrect uses of unsafe.Pointer to convert integers to pointers.
+A conversion from uintptr to unsafe.Pointer is invalid if it implies that
+there is a uintptr-typed word in memory that holds a pointer value,
+because that word will be invisible to stack copying and to the garbage
+collector.
+
+Shifts
+
+Flag: -shift
+
+Shifts equal to or longer than the variable's length.
+
+Other flags
+
+These flags configure the behavior of vet:
+
+	-all (default true)
+		Check everything; disabled if any explicit check is requested.
+	-v
+		Verbose mode
+	-printfuncs
+		A comma-separated list of print-like functions to supplement
+		the standard list.  Each entry is in the form Name:N where N
+		is the zero-based argument position of the first argument
+		involved in the print: either the format or the first print
+		argument for non-formatted prints.  For example,
+		if you have Warn and Warnf functions that take an
+		io.Writer as their first argument, like Fprintf,
+			-printfuncs=Warn:1,Warnf:1
+	-shadowstrict
+		Whether to be strict about shadowing; can be noisy.
+	-test
+		For testing only: sets -all and -shadow.
+*/
+package main
diff --git a/third_party/go.tools/cmd/vet/main.go b/third_party/go.tools/cmd/vet/main.go
new file mode 100644
index 0000000..63832e5
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/main.go
@@ -0,0 +1,493 @@
+// Copyright 2010 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.
+
+// Vet is a simple checker for static errors in Go source code.
+// See doc.go for more information.
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// TODO: Need a flag to set build tags when parsing the package.
+
+var verbose = flag.Bool("v", false, "verbose")
+var testFlag = flag.Bool("test", false, "for testing only: sets -all and -shadow")
+var exitCode = 0
+
+// "all" is here only for the appearance of backwards compatibility.
+// It has no effect; the triState flags do the work.
+var all = flag.Bool("all", true, "check everything; disabled if any explicit check is requested")
+
+// Flags to control which individual checks to perform.
+var report = map[string]*triState{
+	// Only unusual checks are written here.
+	// Most checks that operate during the AST walk are added by register.
+	"asmdecl":   triStateFlag("asmdecl", unset, "check assembly against Go declarations"),
+	"buildtags": triStateFlag("buildtags", unset, "check that +build tags are valid"),
+}
+
+// experimental records the flags enabling experimental features. These must be
+// requested explicitly; they are not enabled by -all.
+var experimental = map[string]bool{}
+
+// setTrueCount record how many flags are explicitly set to true.
+var setTrueCount int
+
+// A triState is a boolean that knows whether it has been set to either true or false.
+// It is used to identify if a flag appears; the standard boolean flag cannot
+// distinguish missing from unset. It also satisfies flag.Value.
+type triState int
+
+const (
+	unset triState = iota
+	setTrue
+	setFalse
+)
+
+func triStateFlag(name string, value triState, usage string) *triState {
+	flag.Var(&value, name, usage)
+	return &value
+}
+
+// triState implements flag.Value, flag.Getter, and flag.boolFlag.
+// They work like boolean flags: we can say vet -printf as well as vet -printf=true
+func (ts *triState) Get() interface{} {
+	return *ts == setTrue
+}
+
+func (ts triState) isTrue() bool {
+	return ts == setTrue
+}
+
+func (ts *triState) Set(value string) error {
+	b, err := strconv.ParseBool(value)
+	if err != nil {
+		return err
+	}
+	if b {
+		*ts = setTrue
+		setTrueCount++
+	} else {
+		*ts = setFalse
+	}
+	return nil
+}
+
+func (ts *triState) String() string {
+	switch *ts {
+	case unset:
+		return "unset"
+	case setTrue:
+		return "true"
+	case setFalse:
+		return "false"
+	}
+	panic("not reached")
+}
+
+func (ts triState) IsBoolFlag() bool {
+	return true
+}
+
+// vet tells whether to report errors for the named check, a flag name.
+func vet(name string) bool {
+	if *testFlag {
+		return true
+	}
+	return report[name].isTrue()
+}
+
+// setExit sets the value for os.Exit when it is called, later.  It
+// remembers the highest value.
+func setExit(err int) {
+	if err > exitCode {
+		exitCode = err
+	}
+}
+
+var (
+	// Each of these vars has a corresponding case in (*File).Visit.
+	assignStmt    *ast.AssignStmt
+	binaryExpr    *ast.BinaryExpr
+	callExpr      *ast.CallExpr
+	compositeLit  *ast.CompositeLit
+	field         *ast.Field
+	funcDecl      *ast.FuncDecl
+	funcLit       *ast.FuncLit
+	genDecl       *ast.GenDecl
+	interfaceType *ast.InterfaceType
+	rangeStmt     *ast.RangeStmt
+
+	// checkers is a two-level map.
+	// The outer level is keyed by a nil pointer, one of the AST vars above.
+	// The inner level is keyed by checker name.
+	checkers = make(map[ast.Node]map[string]func(*File, ast.Node))
+)
+
+func register(name, usage string, fn func(*File, ast.Node), types ...ast.Node) {
+	report[name] = triStateFlag(name, unset, usage)
+	for _, typ := range types {
+		m := checkers[typ]
+		if m == nil {
+			m = make(map[string]func(*File, ast.Node))
+			checkers[typ] = m
+		}
+		m[name] = fn
+	}
+}
+
+// Usage is a replacement usage function for the flags package.
+func Usage() {
+	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
+	fmt.Fprintf(os.Stderr, "\tvet [flags] directory...\n")
+	fmt.Fprintf(os.Stderr, "\tvet [flags] files... # Must be a single package\n")
+	fmt.Fprintf(os.Stderr, "For more information run\n")
+	fmt.Fprintf(os.Stderr, "\tgodoc golang.org/x/tools/cmd/vet\n\n")
+	fmt.Fprintf(os.Stderr, "Flags:\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+// File is a wrapper for the state of a file used in the parser.
+// The parse tree walkers are all methods of this type.
+type File struct {
+	pkg     *Package
+	fset    *token.FileSet
+	name    string
+	content []byte
+	file    *ast.File
+	b       bytes.Buffer // for use by methods
+
+	// The objects that are receivers of a "String() string" method.
+	// This is used by the recursiveStringer method in print.go.
+	stringers map[*ast.Object]bool
+
+	// Registered checkers to run.
+	checkers map[ast.Node][]func(*File, ast.Node)
+}
+
+func main() {
+	flag.Usage = Usage
+	flag.Parse()
+
+	// If any flag is set, we run only those checks requested.
+	// If no flags are set true, set all the non-experimental ones not explicitly set (in effect, set the "-all" flag).
+	if setTrueCount == 0 {
+		for name, setting := range report {
+			if *setting == unset && !experimental[name] {
+				*setting = setTrue
+			}
+		}
+	}
+
+	if *printfuncs != "" {
+		for _, name := range strings.Split(*printfuncs, ",") {
+			if len(name) == 0 {
+				flag.Usage()
+			}
+			skip := 0
+			if colon := strings.LastIndex(name, ":"); colon > 0 {
+				var err error
+				skip, err = strconv.Atoi(name[colon+1:])
+				if err != nil {
+					errorf(`illegal format for "Func:N" argument %q; %s`, name, err)
+				}
+				name = name[:colon]
+			}
+			name = strings.ToLower(name)
+			if name[len(name)-1] == 'f' {
+				printfList[name] = skip
+			} else {
+				printList[name] = skip
+			}
+		}
+	}
+
+	if flag.NArg() == 0 {
+		Usage()
+	}
+	dirs := false
+	files := false
+	for _, name := range flag.Args() {
+		// Is it a directory?
+		fi, err := os.Stat(name)
+		if err != nil {
+			warnf("error walking tree: %s", err)
+			continue
+		}
+		if fi.IsDir() {
+			dirs = true
+		} else {
+			files = true
+		}
+	}
+	if dirs && files {
+		Usage()
+	}
+	if dirs {
+		for _, name := range flag.Args() {
+			walkDir(name)
+		}
+		os.Exit(exitCode)
+	}
+	if !doPackage(".", flag.Args()) {
+		warnf("no files checked")
+	}
+	os.Exit(exitCode)
+}
+
+// prefixDirectory places the directory name on the beginning of each name in the list.
+func prefixDirectory(directory string, names []string) {
+	if directory != "." {
+		for i, name := range names {
+			names[i] = filepath.Join(directory, name)
+		}
+	}
+}
+
+// doPackageDir analyzes the single package found in the directory, if there is one,
+// plus a test package, if there is one.
+func doPackageDir(directory string) {
+	pkg, err := build.Default.ImportDir(directory, 0)
+	if err != nil {
+		// If it's just that there are no go source files, that's fine.
+		if _, nogo := err.(*build.NoGoError); nogo {
+			return
+		}
+		// Non-fatal: we are doing a recursive walk and there may be other directories.
+		warnf("cannot process directory %s: %s", directory, err)
+		return
+	}
+	var names []string
+	names = append(names, pkg.GoFiles...)
+	names = append(names, pkg.CgoFiles...)
+	names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
+	names = append(names, pkg.SFiles...)
+	prefixDirectory(directory, names)
+	doPackage(directory, names)
+	// Is there also a "foo_test" package? If so, do that one as well.
+	if len(pkg.XTestGoFiles) > 0 {
+		names = pkg.XTestGoFiles
+		prefixDirectory(directory, names)
+		doPackage(directory, names)
+	}
+}
+
+type Package struct {
+	path     string
+	defs     map[*ast.Ident]types.Object
+	uses     map[*ast.Ident]types.Object
+	types    map[ast.Expr]types.TypeAndValue
+	spans    map[types.Object]Span
+	files    []*File
+	typesPkg *types.Package
+}
+
+// doPackage analyzes the single package constructed from the named files.
+// It returns whether any files were checked.
+func doPackage(directory string, names []string) bool {
+	var files []*File
+	var astFiles []*ast.File
+	fs := token.NewFileSet()
+	for _, name := range names {
+		data, err := ioutil.ReadFile(name)
+		if err != nil {
+			// Warn but continue to next package.
+			warnf("%s: %s", name, err)
+			return false
+		}
+		checkBuildTag(name, data)
+		var parsedFile *ast.File
+		if strings.HasSuffix(name, ".go") {
+			parsedFile, err = parser.ParseFile(fs, name, data, 0)
+			if err != nil {
+				warnf("%s: %s", name, err)
+				return false
+			}
+			astFiles = append(astFiles, parsedFile)
+		}
+		files = append(files, &File{fset: fs, content: data, name: name, file: parsedFile})
+	}
+	if len(astFiles) == 0 {
+		return false
+	}
+	pkg := new(Package)
+	pkg.path = astFiles[0].Name.Name
+	pkg.files = files
+	// Type check the package.
+	err := pkg.check(fs, astFiles)
+	if err != nil && *verbose {
+		warnf("%s", err)
+	}
+
+	// Check.
+	chk := make(map[ast.Node][]func(*File, ast.Node))
+	for typ, set := range checkers {
+		for name, fn := range set {
+			if vet(name) {
+				chk[typ] = append(chk[typ], fn)
+			}
+		}
+	}
+	for _, file := range files {
+		file.pkg = pkg
+		file.checkers = chk
+		if file.file != nil {
+			file.walkFile(file.name, file.file)
+		}
+	}
+	asmCheck(pkg)
+	return true
+}
+
+func visit(path string, f os.FileInfo, err error) error {
+	if err != nil {
+		warnf("walk error: %s", err)
+		return err
+	}
+	// One package per directory. Ignore the files themselves.
+	if !f.IsDir() {
+		return nil
+	}
+	doPackageDir(path)
+	return nil
+}
+
+func (pkg *Package) hasFileWithSuffix(suffix string) bool {
+	for _, f := range pkg.files {
+		if strings.HasSuffix(f.name, suffix) {
+			return true
+		}
+	}
+	return false
+}
+
+// walkDir recursively walks the tree looking for Go packages.
+func walkDir(root string) {
+	filepath.Walk(root, visit)
+}
+
+// errorf formats the error to standard error, adding program
+// identification and a newline, and exits.
+func errorf(format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, "vet: "+format+"\n", args...)
+	os.Exit(2)
+}
+
+// warnf formats the error to standard error, adding program
+// identification and a newline, but does not exit.
+func warnf(format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, "vet: "+format+"\n", args...)
+	setExit(1)
+}
+
+// Println is fmt.Println guarded by -v.
+func Println(args ...interface{}) {
+	if !*verbose {
+		return
+	}
+	fmt.Println(args...)
+}
+
+// Printf is fmt.Printf guarded by -v.
+func Printf(format string, args ...interface{}) {
+	if !*verbose {
+		return
+	}
+	fmt.Printf(format+"\n", args...)
+}
+
+// Bad reports an error and sets the exit code..
+func (f *File) Bad(pos token.Pos, args ...interface{}) {
+	f.Warn(pos, args...)
+	setExit(1)
+}
+
+// Badf reports a formatted error and sets the exit code.
+func (f *File) Badf(pos token.Pos, format string, args ...interface{}) {
+	f.Warnf(pos, format, args...)
+	setExit(1)
+}
+
+// loc returns a formatted representation of the position.
+func (f *File) loc(pos token.Pos) string {
+	if pos == token.NoPos {
+		return ""
+	}
+	// Do not print columns. Because the pos often points to the start of an
+	// expression instead of the inner part with the actual error, the
+	// precision can mislead.
+	posn := f.fset.Position(pos)
+	return fmt.Sprintf("%s:%d: ", posn.Filename, posn.Line)
+}
+
+// Warn reports an error but does not set the exit code.
+func (f *File) Warn(pos token.Pos, args ...interface{}) {
+	fmt.Fprint(os.Stderr, f.loc(pos)+fmt.Sprintln(args...))
+}
+
+// Warnf reports a formatted error but does not set the exit code.
+func (f *File) Warnf(pos token.Pos, format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, f.loc(pos)+format+"\n", args...)
+}
+
+// walkFile walks the file's tree.
+func (f *File) walkFile(name string, file *ast.File) {
+	Println("Checking file", name)
+	ast.Walk(f, file)
+}
+
+// Visit implements the ast.Visitor interface.
+func (f *File) Visit(node ast.Node) ast.Visitor {
+	var key ast.Node
+	switch node.(type) {
+	case *ast.AssignStmt:
+		key = assignStmt
+	case *ast.BinaryExpr:
+		key = binaryExpr
+	case *ast.CallExpr:
+		key = callExpr
+	case *ast.CompositeLit:
+		key = compositeLit
+	case *ast.Field:
+		key = field
+	case *ast.FuncDecl:
+		key = funcDecl
+	case *ast.FuncLit:
+		key = funcLit
+	case *ast.GenDecl:
+		key = genDecl
+	case *ast.InterfaceType:
+		key = interfaceType
+	case *ast.RangeStmt:
+		key = rangeStmt
+	}
+	for _, fn := range f.checkers[key] {
+		fn(f, node)
+	}
+	return f
+}
+
+// gofmt returns a string representation of the expression.
+func (f *File) gofmt(x ast.Expr) string {
+	f.b.Reset()
+	printer.Fprint(&f.b, f.fset, x)
+	return f.b.String()
+}
diff --git a/third_party/go.tools/cmd/vet/method.go b/third_party/go.tools/cmd/vet/method.go
new file mode 100644
index 0000000..00949df
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/method.go
@@ -0,0 +1,182 @@
+// Copyright 2010 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.
+
+// This file contains the code to check canonical methods.
+
+package main
+
+import (
+	"fmt"
+	"go/ast"
+	"go/printer"
+	"strings"
+)
+
+func init() {
+	register("methods",
+		"check that canonically named methods are canonically defined",
+		checkCanonicalMethod,
+		funcDecl, interfaceType)
+}
+
+type MethodSig struct {
+	args    []string
+	results []string
+}
+
+// canonicalMethods lists the input and output types for Go methods
+// that are checked using dynamic interface checks.  Because the
+// checks are dynamic, such methods would not cause a compile error
+// if they have the wrong signature: instead the dynamic check would
+// fail, sometimes mysteriously.  If a method is found with a name listed
+// here but not the input/output types listed here, vet complains.
+//
+// A few of the canonical methods have very common names.
+// For example, a type might implement a Scan method that
+// has nothing to do with fmt.Scanner, but we still want to check
+// the methods that are intended to implement fmt.Scanner.
+// To do that, the arguments that have a = prefix are treated as
+// signals that the canonical meaning is intended: if a Scan
+// method doesn't have a fmt.ScanState as its first argument,
+// we let it go.  But if it does have a fmt.ScanState, then the
+// rest has to match.
+var canonicalMethods = map[string]MethodSig{
+	// "Flush": {{}, {"error"}}, // http.Flusher and jpeg.writer conflict
+	"Format":        {[]string{"=fmt.State", "rune"}, []string{}},                      // fmt.Formatter
+	"GobDecode":     {[]string{"[]byte"}, []string{"error"}},                           // gob.GobDecoder
+	"GobEncode":     {[]string{}, []string{"[]byte", "error"}},                         // gob.GobEncoder
+	"MarshalJSON":   {[]string{}, []string{"[]byte", "error"}},                         // json.Marshaler
+	"MarshalXML":    {[]string{"*xml.Encoder", "xml.StartElement"}, []string{"error"}}, // xml.Marshaler
+	"Peek":          {[]string{"=int"}, []string{"[]byte", "error"}},                   // image.reader (matching bufio.Reader)
+	"ReadByte":      {[]string{}, []string{"byte", "error"}},                           // io.ByteReader
+	"ReadFrom":      {[]string{"=io.Reader"}, []string{"int64", "error"}},              // io.ReaderFrom
+	"ReadRune":      {[]string{}, []string{"rune", "int", "error"}},                    // io.RuneReader
+	"Scan":          {[]string{"=fmt.ScanState", "rune"}, []string{"error"}},           // fmt.Scanner
+	"Seek":          {[]string{"=int64", "int"}, []string{"int64", "error"}},           // io.Seeker
+	"UnmarshalJSON": {[]string{"[]byte"}, []string{"error"}},                           // json.Unmarshaler
+	"UnmarshalXML":  {[]string{"*xml.Decoder", "xml.StartElement"}, []string{"error"}}, // xml.Unmarshaler
+	"UnreadByte":    {[]string{}, []string{"error"}},
+	"UnreadRune":    {[]string{}, []string{"error"}},
+	"WriteByte":     {[]string{"byte"}, []string{"error"}},                // jpeg.writer (matching bufio.Writer)
+	"WriteTo":       {[]string{"=io.Writer"}, []string{"int64", "error"}}, // io.WriterTo
+}
+
+func checkCanonicalMethod(f *File, node ast.Node) {
+	switch n := node.(type) {
+	case *ast.FuncDecl:
+		if n.Recv != nil {
+			canonicalMethod(f, n.Name, n.Type)
+		}
+	case *ast.InterfaceType:
+		for _, field := range n.Methods.List {
+			for _, id := range field.Names {
+				canonicalMethod(f, id, field.Type.(*ast.FuncType))
+			}
+		}
+	}
+}
+
+func canonicalMethod(f *File, id *ast.Ident, t *ast.FuncType) {
+	// Expected input/output.
+	expect, ok := canonicalMethods[id.Name]
+	if !ok {
+		return
+	}
+
+	// Actual input/output
+	args := typeFlatten(t.Params.List)
+	var results []ast.Expr
+	if t.Results != nil {
+		results = typeFlatten(t.Results.List)
+	}
+
+	// Do the =s (if any) all match?
+	if !f.matchParams(expect.args, args, "=") || !f.matchParams(expect.results, results, "=") {
+		return
+	}
+
+	// Everything must match.
+	if !f.matchParams(expect.args, args, "") || !f.matchParams(expect.results, results, "") {
+		expectFmt := id.Name + "(" + argjoin(expect.args) + ")"
+		if len(expect.results) == 1 {
+			expectFmt += " " + argjoin(expect.results)
+		} else if len(expect.results) > 1 {
+			expectFmt += " (" + argjoin(expect.results) + ")"
+		}
+
+		f.b.Reset()
+		if err := printer.Fprint(&f.b, f.fset, t); err != nil {
+			fmt.Fprintf(&f.b, "<%s>", err)
+		}
+		actual := f.b.String()
+		actual = strings.TrimPrefix(actual, "func")
+		actual = id.Name + actual
+
+		f.Badf(id.Pos(), "method %s should have signature %s", actual, expectFmt)
+	}
+}
+
+func argjoin(x []string) string {
+	y := make([]string, len(x))
+	for i, s := range x {
+		if s[0] == '=' {
+			s = s[1:]
+		}
+		y[i] = s
+	}
+	return strings.Join(y, ", ")
+}
+
+// Turn parameter list into slice of types
+// (in the ast, types are Exprs).
+// Have to handle f(int, bool) and f(x, y, z int)
+// so not a simple 1-to-1 conversion.
+func typeFlatten(l []*ast.Field) []ast.Expr {
+	var t []ast.Expr
+	for _, f := range l {
+		if len(f.Names) == 0 {
+			t = append(t, f.Type)
+			continue
+		}
+		for _ = range f.Names {
+			t = append(t, f.Type)
+		}
+	}
+	return t
+}
+
+// Does each type in expect with the given prefix match the corresponding type in actual?
+func (f *File) matchParams(expect []string, actual []ast.Expr, prefix string) bool {
+	for i, x := range expect {
+		if !strings.HasPrefix(x, prefix) {
+			continue
+		}
+		if i >= len(actual) {
+			return false
+		}
+		if !f.matchParamType(x, actual[i]) {
+			return false
+		}
+	}
+	if prefix == "" && len(actual) > len(expect) {
+		return false
+	}
+	return true
+}
+
+// Does this one type match?
+func (f *File) matchParamType(expect string, actual ast.Expr) bool {
+	if strings.HasPrefix(expect, "=") {
+		expect = expect[1:]
+	}
+	// Strip package name if we're in that package.
+	if n := len(f.file.Name.Name); len(expect) > n && expect[:n] == f.file.Name.Name && expect[n] == '.' {
+		expect = expect[n+1:]
+	}
+
+	// Overkill but easy.
+	f.b.Reset()
+	printer.Fprint(&f.b, f.fset, actual)
+	return f.b.String() == expect
+}
diff --git a/third_party/go.tools/cmd/vet/nilfunc.go b/third_party/go.tools/cmd/vet/nilfunc.go
new file mode 100644
index 0000000..0ed874f
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/nilfunc.go
@@ -0,0 +1,68 @@
+// Copyright 2013 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.
+
+/*
+This file contains the code to check for useless function comparisons.
+A useless comparison is one like f == nil as opposed to f() == nil.
+*/
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func init() {
+	register("nilfunc",
+		"check for comparisons between functions and nil",
+		checkNilFuncComparison,
+		binaryExpr)
+}
+
+func checkNilFuncComparison(f *File, node ast.Node) {
+	e := node.(*ast.BinaryExpr)
+
+	// Only want == or != comparisons.
+	if e.Op != token.EQL && e.Op != token.NEQ {
+		return
+	}
+
+	// Only want comparisons with a nil identifier on one side.
+	var e2 ast.Expr
+	switch {
+	case f.isNil(e.X):
+		e2 = e.Y
+	case f.isNil(e.Y):
+		e2 = e.X
+	default:
+		return
+	}
+
+	// Only want identifiers or selector expressions.
+	var obj types.Object
+	switch v := e2.(type) {
+	case *ast.Ident:
+		obj = f.pkg.uses[v]
+	case *ast.SelectorExpr:
+		obj = f.pkg.uses[v.Sel]
+	default:
+		return
+	}
+
+	// Only want functions.
+	if _, ok := obj.(*types.Func); !ok {
+		return
+	}
+
+	f.Badf(e.Pos(), "comparison of function %v %v nil is always %v", obj.Name(), e.Op, e.Op == token.NEQ)
+}
+
+// isNil reports whether the provided expression is the built-in nil
+// identifier.
+func (f *File) isNil(e ast.Expr) bool {
+	return f.pkg.types[e].Type == types.Typ[types.UntypedNil]
+}
diff --git a/third_party/go.tools/cmd/vet/print.go b/third_party/go.tools/cmd/vet/print.go
new file mode 100644
index 0000000..572f615
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/print.go
@@ -0,0 +1,557 @@
+// Copyright 2010 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.
+
+// This file contains the printf-checker.
+
+package main
+
+import (
+	"bytes"
+	"flag"
+	"go/ast"
+	"go/token"
+	"strconv"
+	"strings"
+	"unicode/utf8"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")
+
+func init() {
+	register("printf",
+		"check printf-like invocations",
+		checkFmtPrintfCall,
+		funcDecl, callExpr)
+}
+
+// printfList records the formatted-print functions. The value is the location
+// of the format parameter. Names are lower-cased so the lookup is
+// case insensitive.
+var printfList = map[string]int{
+	"errorf":  0,
+	"fatalf":  0,
+	"fprintf": 1,
+	"logf":    0,
+	"panicf":  0,
+	"printf":  0,
+	"sprintf": 0,
+}
+
+// printList records the unformatted-print functions. The value is the location
+// of the first parameter to be printed.  Names are lower-cased so the lookup is
+// case insensitive.
+var printList = map[string]int{
+	"error":  0,
+	"fatal":  0,
+	"fprint": 1, "fprintln": 1,
+	"log":   0,
+	"panic": 0, "panicln": 0,
+	"print": 0, "println": 0,
+	"sprint": 0, "sprintln": 0,
+}
+
+// checkCall triggers the print-specific checks if the call invokes a print function.
+func checkFmtPrintfCall(f *File, node ast.Node) {
+	if d, ok := node.(*ast.FuncDecl); ok && isStringer(f, d) {
+		// Remember we saw this.
+		if f.stringers == nil {
+			f.stringers = make(map[*ast.Object]bool)
+		}
+		if l := d.Recv.List; len(l) == 1 {
+			if n := l[0].Names; len(n) == 1 {
+				f.stringers[n[0].Obj] = true
+			}
+		}
+		return
+	}
+
+	call, ok := node.(*ast.CallExpr)
+	if !ok {
+		return
+	}
+	var Name string
+	switch x := call.Fun.(type) {
+	case *ast.Ident:
+		Name = x.Name
+	case *ast.SelectorExpr:
+		Name = x.Sel.Name
+	default:
+		return
+	}
+
+	name := strings.ToLower(Name)
+	if skip, ok := printfList[name]; ok {
+		f.checkPrintf(call, Name, skip)
+		return
+	}
+	if skip, ok := printList[name]; ok {
+		f.checkPrint(call, Name, skip)
+		return
+	}
+}
+
+// isStringer returns true if the provided declaration is a "String() string"
+// method, an implementation of fmt.Stringer.
+func isStringer(f *File, d *ast.FuncDecl) bool {
+	return d.Recv != nil && d.Name.Name == "String" && d.Type.Results != nil &&
+		len(d.Type.Params.List) == 0 && len(d.Type.Results.List) == 1 &&
+		f.pkg.types[d.Type.Results.List[0].Type].Type == types.Typ[types.String]
+}
+
+// formatState holds the parsed representation of a printf directive such as "%3.*[4]d".
+// It is constructed by parsePrintfVerb.
+type formatState struct {
+	verb     rune   // the format verb: 'd' for "%d"
+	format   string // the full format directive from % through verb, "%.3d".
+	name     string // Printf, Sprintf etc.
+	flags    []byte // the list of # + etc.
+	argNums  []int  // the successive argument numbers that are consumed, adjusted to refer to actual arg in call
+	indexed  bool   // whether an indexing expression appears: %[1]d.
+	firstArg int    // Index of first argument after the format in the Printf call.
+	// Used only during parse.
+	file         *File
+	call         *ast.CallExpr
+	argNum       int  // Which argument we're expecting to format now.
+	indexPending bool // Whether we have an indexed argument that has not resolved.
+	nbytes       int  // number of bytes of the format string consumed.
+}
+
+// checkPrintf checks a call to a formatted print routine such as Printf.
+// call.Args[formatIndex] is (well, should be) the format argument.
+func (f *File) checkPrintf(call *ast.CallExpr, name string, formatIndex int) {
+	if formatIndex >= len(call.Args) {
+		f.Bad(call.Pos(), "too few arguments in call to", name)
+		return
+	}
+	lit := f.pkg.types[call.Args[formatIndex]].Value
+	if lit == nil {
+		if *verbose {
+			f.Warn(call.Pos(), "can't check non-constant format in call to", name)
+		}
+		return
+	}
+	if lit.Kind() != exact.String {
+		f.Badf(call.Pos(), "constant %v not a string in call to %s", lit, name)
+		return
+	}
+	format := exact.StringVal(lit)
+	firstArg := formatIndex + 1 // Arguments are immediately after format string.
+	if !strings.Contains(format, "%") {
+		if len(call.Args) > firstArg {
+			f.Badf(call.Pos(), "no formatting directive in %s call", name)
+		}
+		return
+	}
+	// Hard part: check formats against args.
+	argNum := firstArg
+	indexed := false
+	for i, w := 0, 0; i < len(format); i += w {
+		w = 1
+		if format[i] == '%' {
+			state := f.parsePrintfVerb(call, name, format[i:], firstArg, argNum)
+			if state == nil {
+				return
+			}
+			w = len(state.format)
+			if state.indexed {
+				indexed = true
+			}
+			if !f.okPrintfArg(call, state) { // One error per format is enough.
+				return
+			}
+			if len(state.argNums) > 0 {
+				// Continue with the next sequential argument.
+				argNum = state.argNums[len(state.argNums)-1] + 1
+			}
+		}
+	}
+	// Dotdotdot is hard.
+	if call.Ellipsis.IsValid() && argNum >= len(call.Args)-1 {
+		return
+	}
+	// If the arguments were direct indexed, we assume the programmer knows what's up.
+	// Otherwise, there should be no leftover arguments.
+	if !indexed && argNum != len(call.Args) {
+		expect := argNum - firstArg
+		numArgs := len(call.Args) - firstArg
+		f.Badf(call.Pos(), "wrong number of args for format in %s call: %d needed but %d args", name, expect, numArgs)
+	}
+}
+
+// parseFlags accepts any printf flags.
+func (s *formatState) parseFlags() {
+	for s.nbytes < len(s.format) {
+		switch c := s.format[s.nbytes]; c {
+		case '#', '0', '+', '-', ' ':
+			s.flags = append(s.flags, c)
+			s.nbytes++
+		default:
+			return
+		}
+	}
+}
+
+// scanNum advances through a decimal number if present.
+func (s *formatState) scanNum() {
+	for ; s.nbytes < len(s.format); s.nbytes++ {
+		c := s.format[s.nbytes]
+		if c < '0' || '9' < c {
+			return
+		}
+	}
+}
+
+// parseIndex scans an index expression. It returns false if there is a syntax error.
+func (s *formatState) parseIndex() bool {
+	if s.nbytes == len(s.format) || s.format[s.nbytes] != '[' {
+		return true
+	}
+	// Argument index present.
+	s.indexed = true
+	s.nbytes++ // skip '['
+	start := s.nbytes
+	s.scanNum()
+	if s.nbytes == len(s.format) || s.nbytes == start || s.format[s.nbytes] != ']' {
+		s.file.Badf(s.call.Pos(), "illegal syntax for printf argument index")
+		return false
+	}
+	arg32, err := strconv.ParseInt(s.format[start:s.nbytes], 10, 32)
+	if err != nil {
+		s.file.Badf(s.call.Pos(), "illegal syntax for printf argument index: %s", err)
+		return false
+	}
+	s.nbytes++ // skip ']'
+	arg := int(arg32)
+	arg += s.firstArg - 1 // We want to zero-index the actual arguments.
+	s.argNum = arg
+	s.indexPending = true
+	return true
+}
+
+// parseNum scans a width or precision (or *). It returns false if there's a bad index expression.
+func (s *formatState) parseNum() bool {
+	if s.nbytes < len(s.format) && s.format[s.nbytes] == '*' {
+		if s.indexPending { // Absorb it.
+			s.indexPending = false
+		}
+		s.nbytes++
+		s.argNums = append(s.argNums, s.argNum)
+		s.argNum++
+	} else {
+		s.scanNum()
+	}
+	return true
+}
+
+// parsePrecision scans for a precision. It returns false if there's a bad index expression.
+func (s *formatState) parsePrecision() bool {
+	// If there's a period, there may be a precision.
+	if s.nbytes < len(s.format) && s.format[s.nbytes] == '.' {
+		s.flags = append(s.flags, '.') // Treat precision as a flag.
+		s.nbytes++
+		if !s.parseIndex() {
+			return false
+		}
+		if !s.parseNum() {
+			return false
+		}
+	}
+	return true
+}
+
+// parsePrintfVerb looks the formatting directive that begins the format string
+// and returns a formatState that encodes what the directive wants, without looking
+// at the actual arguments present in the call. The result is nil if there is an error.
+func (f *File) parsePrintfVerb(call *ast.CallExpr, name, format string, firstArg, argNum int) *formatState {
+	state := &formatState{
+		format:   format,
+		name:     name,
+		flags:    make([]byte, 0, 5),
+		argNum:   argNum,
+		argNums:  make([]int, 0, 1),
+		nbytes:   1, // There's guaranteed to be a percent sign.
+		indexed:  false,
+		firstArg: firstArg,
+		file:     f,
+		call:     call,
+	}
+	// There may be flags.
+	state.parseFlags()
+	indexPending := false
+	// There may be an index.
+	if !state.parseIndex() {
+		return nil
+	}
+	// There may be a width.
+	if !state.parseNum() {
+		return nil
+	}
+	// There may be a precision.
+	if !state.parsePrecision() {
+		return nil
+	}
+	// Now a verb, possibly prefixed by an index (which we may already have).
+	if !indexPending && !state.parseIndex() {
+		return nil
+	}
+	if state.nbytes == len(state.format) {
+		f.Badf(call.Pos(), "missing verb at end of format string in %s call", name)
+		return nil
+	}
+	verb, w := utf8.DecodeRuneInString(state.format[state.nbytes:])
+	state.verb = verb
+	state.nbytes += w
+	if verb != '%' {
+		state.argNums = append(state.argNums, state.argNum)
+	}
+	state.format = state.format[:state.nbytes]
+	return state
+}
+
+// printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask.
+type printfArgType int
+
+const (
+	argBool printfArgType = 1 << iota
+	argInt
+	argRune
+	argString
+	argFloat
+	argComplex
+	argPointer
+	anyType printfArgType = ^0
+)
+
+type printVerb struct {
+	verb  rune   // User may provide verb through Formatter; could be a rune.
+	flags string // known flags are all ASCII
+	typ   printfArgType
+}
+
+// Common flag sets for printf verbs.
+const (
+	noFlag       = ""
+	numFlag      = " -+.0"
+	sharpNumFlag = " -+.0#"
+	allFlags     = " -+.0#"
+)
+
+// printVerbs identifies which flags are known to printf for each verb.
+// TODO: A type that implements Formatter may do what it wants, and vet
+// will complain incorrectly.
+var printVerbs = []printVerb{
+	// '-' is a width modifier, always valid.
+	// '.' is a precision for float, max width for strings.
+	// '+' is required sign for numbers, Go format for %v.
+	// '#' is alternate format for several verbs.
+	// ' ' is spacer for numbers
+	{'%', noFlag, 0},
+	{'b', numFlag, argInt | argFloat | argComplex},
+	{'c', "-", argRune | argInt},
+	{'d', numFlag, argInt},
+	{'e', numFlag, argFloat | argComplex},
+	{'E', numFlag, argFloat | argComplex},
+	{'f', numFlag, argFloat | argComplex},
+	{'F', numFlag, argFloat | argComplex},
+	{'g', numFlag, argFloat | argComplex},
+	{'G', numFlag, argFloat | argComplex},
+	{'o', sharpNumFlag, argInt},
+	{'p', "-#", argPointer},
+	{'q', " -+.0#", argRune | argInt | argString},
+	{'s', " -+.0", argString},
+	{'t', "-", argBool},
+	{'T', "-", anyType},
+	{'U', "-#", argRune | argInt},
+	{'v', allFlags, anyType},
+	{'x', sharpNumFlag, argRune | argInt | argString},
+	{'X', sharpNumFlag, argRune | argInt | argString},
+}
+
+// okPrintfArg compares the formatState to the arguments actually present,
+// reporting any discrepancies it can discern. If the final argument is ellipsissed,
+// there's little it can do for that.
+func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) {
+	var v printVerb
+	found := false
+	// Linear scan is fast enough for a small list.
+	for _, v = range printVerbs {
+		if v.verb == state.verb {
+			found = true
+			break
+		}
+	}
+	if !found {
+		f.Badf(call.Pos(), "unrecognized printf verb %q", state.verb)
+		return false
+	}
+	for _, flag := range state.flags {
+		if !strings.ContainsRune(v.flags, rune(flag)) {
+			f.Badf(call.Pos(), "unrecognized printf flag for verb %q: %q", state.verb, flag)
+			return false
+		}
+	}
+	// Verb is good. If len(state.argNums)>trueArgs, we have something like %.*s and all
+	// but the final arg must be an integer.
+	trueArgs := 1
+	if state.verb == '%' {
+		trueArgs = 0
+	}
+	nargs := len(state.argNums)
+	for i := 0; i < nargs-trueArgs; i++ {
+		argNum := state.argNums[i]
+		if !f.argCanBeChecked(call, i, true, state) {
+			return
+		}
+		arg := call.Args[argNum]
+		if !f.matchArgType(argInt, nil, arg) {
+			f.Badf(call.Pos(), "arg %s for * in printf format not of type int", f.gofmt(arg))
+			return false
+		}
+	}
+	if state.verb == '%' {
+		return true
+	}
+	argNum := state.argNums[len(state.argNums)-1]
+	if !f.argCanBeChecked(call, len(state.argNums)-1, false, state) {
+		return false
+	}
+	arg := call.Args[argNum]
+	if !f.matchArgType(v.typ, nil, arg) {
+		typeString := ""
+		if typ := f.pkg.types[arg].Type; typ != nil {
+			typeString = typ.String()
+		}
+		f.Badf(call.Pos(), "arg %s for printf verb %%%c of wrong type: %s", f.gofmt(arg), state.verb, typeString)
+		return false
+	}
+	if v.typ&argString != 0 && v.verb != 'T' && !bytes.Contains(state.flags, []byte{'#'}) && f.recursiveStringer(arg) {
+		f.Badf(call.Pos(), "arg %s for printf causes recursive call to String method", f.gofmt(arg))
+		return false
+	}
+	return true
+}
+
+// recursiveStringer reports whether the provided argument is r or &r for the
+// fmt.Stringer receiver identifier r.
+func (f *File) recursiveStringer(e ast.Expr) bool {
+	if len(f.stringers) == 0 {
+		return false
+	}
+	var obj *ast.Object
+	switch e := e.(type) {
+	case *ast.Ident:
+		obj = e.Obj
+	case *ast.UnaryExpr:
+		if id, ok := e.X.(*ast.Ident); ok && e.Op == token.AND {
+			obj = id.Obj
+		}
+	}
+
+	// It's unlikely to be a recursive stringer if it has a Format method.
+	if typ := f.pkg.types[e].Type; typ != nil {
+		// Not a perfect match; see issue 6259.
+		if f.hasMethod(typ, "Format") {
+			return false
+		}
+	}
+
+	// We compare the underlying Object, which checks that the identifier
+	// is the one we declared as the receiver for the String method in
+	// which this printf appears.
+	return f.stringers[obj]
+}
+
+// argCanBeChecked reports whether the specified argument is statically present;
+// it may be beyond the list of arguments or in a terminal slice... argument, which
+// means we can't see it.
+func (f *File) argCanBeChecked(call *ast.CallExpr, formatArg int, isStar bool, state *formatState) bool {
+	argNum := state.argNums[formatArg]
+	if argNum < 0 {
+		// Shouldn't happen, so catch it with prejudice.
+		panic("negative arg num")
+	}
+	if argNum < len(call.Args)-1 {
+		return true // Always OK.
+	}
+	if call.Ellipsis.IsValid() {
+		return false // We just can't tell; there could be many more arguments.
+	}
+	if argNum < len(call.Args) {
+		return true
+	}
+	// There are bad indexes in the format or there are fewer arguments than the format needs.
+	// This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi".
+	arg := argNum - state.firstArg + 1 // People think of arguments as 1-indexed.
+	f.Badf(call.Pos(), `missing argument for %s("%s"): format reads arg %d, have only %d args`, state.name, state.format, arg, len(call.Args)-state.firstArg)
+	return false
+}
+
+// checkPrint checks a call to an unformatted print routine such as Println.
+// call.Args[firstArg] is the first argument to be printed.
+func (f *File) checkPrint(call *ast.CallExpr, name string, firstArg int) {
+	isLn := strings.HasSuffix(name, "ln")
+	isF := strings.HasPrefix(name, "F")
+	args := call.Args
+	if name == "Log" && len(args) > 0 {
+		// Special case: Don't complain about math.Log or cmplx.Log.
+		// Not strictly necessary because the only complaint likely is for Log("%d")
+		// but it feels wrong to check that math.Log is a good print function.
+		if sel, ok := args[0].(*ast.SelectorExpr); ok {
+			if x, ok := sel.X.(*ast.Ident); ok {
+				if x.Name == "math" || x.Name == "cmplx" {
+					return
+				}
+			}
+		}
+	}
+	// check for Println(os.Stderr, ...)
+	if firstArg == 0 && !isF && len(args) > 0 {
+		if sel, ok := args[0].(*ast.SelectorExpr); ok {
+			if x, ok := sel.X.(*ast.Ident); ok {
+				if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
+					f.Badf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name)
+				}
+			}
+		}
+	}
+	if len(args) <= firstArg {
+		// If we have a call to a method called Error that satisfies the Error interface,
+		// then it's ok. Otherwise it's something like (*T).Error from the testing package
+		// and we need to check it.
+		if name == "Error" && f.isErrorMethodCall(call) {
+			return
+		}
+		// If it's an Error call now, it's probably for printing errors.
+		if !isLn {
+			// Check the signature to be sure: there are niladic functions called "error".
+			if firstArg != 0 || f.numArgsInSignature(call) != firstArg {
+				f.Badf(call.Pos(), "no args in %s call", name)
+			}
+		}
+		return
+	}
+	arg := args[firstArg]
+	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
+		if strings.Contains(lit.Value, "%") {
+			f.Badf(call.Pos(), "possible formatting directive in %s call", name)
+		}
+	}
+	if isLn {
+		// The last item, if a string, should not have a newline.
+		arg = args[len(call.Args)-1]
+		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
+			if strings.HasSuffix(lit.Value, `\n"`) {
+				f.Badf(call.Pos(), "%s call ends with newline", name)
+			}
+		}
+	}
+	for _, arg := range args {
+		if f.recursiveStringer(arg) {
+			f.Badf(call.Pos(), "arg %s for print causes recursive call to String method", f.gofmt(arg))
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/rangeloop.go b/third_party/go.tools/cmd/vet/rangeloop.go
new file mode 100644
index 0000000..96e2ca8
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/rangeloop.go
@@ -0,0 +1,70 @@
+// 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.
+
+/*
+This file contains the code to check range loop variables bound inside function
+literals that are deferred or launched in new goroutines. We only check
+instances where the defer or go statement is the last statement in the loop
+body, as otherwise we would need whole program analysis.
+
+For example:
+
+	for i, v := range s {
+		go func() {
+			println(i, v) // not what you might expect
+		}()
+	}
+
+See: http://golang.org/doc/go_faq.html#closures_and_goroutines
+*/
+
+package main
+
+import "go/ast"
+
+func init() {
+	register("rangeloops",
+		"check that range loop variables are used correctly",
+		checkRangeLoop,
+		rangeStmt)
+}
+
+// checkRangeLoop walks the body of the provided range statement, checking if
+// its index or value variables are used unsafely inside goroutines or deferred
+// function literals.
+func checkRangeLoop(f *File, node ast.Node) {
+	n := node.(*ast.RangeStmt)
+	key, _ := n.Key.(*ast.Ident)
+	val, _ := n.Value.(*ast.Ident)
+	if key == nil && val == nil {
+		return
+	}
+	sl := n.Body.List
+	if len(sl) == 0 {
+		return
+	}
+	var last *ast.CallExpr
+	switch s := sl[len(sl)-1].(type) {
+	case *ast.GoStmt:
+		last = s.Call
+	case *ast.DeferStmt:
+		last = s.Call
+	default:
+		return
+	}
+	lit, ok := last.Fun.(*ast.FuncLit)
+	if !ok {
+		return
+	}
+	ast.Inspect(lit.Body, func(n ast.Node) bool {
+		id, ok := n.(*ast.Ident)
+		if !ok || id.Obj == nil {
+			return true
+		}
+		if key != nil && id.Obj == key.Obj || val != nil && id.Obj == val.Obj {
+			f.Bad(id.Pos(), "range variable", id.Name, "captured by func literal")
+		}
+		return true
+	})
+}
diff --git a/third_party/go.tools/cmd/vet/shadow.go b/third_party/go.tools/cmd/vet/shadow.go
new file mode 100644
index 0000000..1ba360a
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/shadow.go
@@ -0,0 +1,245 @@
+// Copyright 2013 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.
+
+/*
+This file contains the code to check for shadowed variables.
+A shadowed variable is a variable declared in an inner scope
+with the same name and type as a variable in an outer scope,
+and where the outer variable is mentioned after the inner one
+is declared.
+
+(This definition can be refined; the module generates too many
+false positives and is not yet enabled by default.)
+
+For example:
+
+	func BadRead(f *os.File, buf []byte) error {
+		var err error
+		for {
+			n, err := f.Read(buf) // shadows the function variable 'err'
+			if err != nil {
+				break // causes return of wrong value
+			}
+			foo(buf)
+		}
+		return err
+	}
+
+*/
+
+package main
+
+import (
+	"flag"
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var strictShadowing = flag.Bool("shadowstrict", false, "whether to be strict about shadowing; can be noisy")
+
+func init() {
+	register("shadow",
+		"check for shadowed variables (experimental; must be set explicitly)",
+		checkShadow,
+		assignStmt, genDecl)
+	experimental["shadow"] = true
+}
+
+func checkShadow(f *File, node ast.Node) {
+	switch n := node.(type) {
+	case *ast.AssignStmt:
+		checkShadowAssignment(f, n)
+	case *ast.GenDecl:
+		checkShadowDecl(f, n)
+	}
+}
+
+// Span stores the minimum range of byte positions in the file in which a
+// given variable (types.Object) is mentioned. It is lexically defined: it spans
+// from the beginning of its first mention to the end of its last mention.
+// A variable is considered shadowed (if *strictShadowing is off) only if the
+// shadowing variable is declared within the span of the shadowed variable.
+// In other words, if a variable is shadowed but not used after the shadowed
+// variable is declared, it is inconsequential and not worth complaining about.
+// This simple check dramatically reduces the nuisance rate for the shadowing
+// check, at least until something cleverer comes along.
+//
+// One wrinkle: A "naked return" is a silent use of a variable that the Span
+// will not capture, but the compilers catch naked returns of shadowed
+// variables so we don't need to.
+//
+// Cases this gets wrong (TODO):
+// - If a for loop's continuation statement mentions a variable redeclared in
+// the block, we should complain about it but don't.
+// - A variable declared inside a function literal can falsely be identified
+// as shadowing a variable in the outer function.
+//
+type Span struct {
+	min token.Pos
+	max token.Pos
+}
+
+// contains reports whether the position is inside the span.
+func (s Span) contains(pos token.Pos) bool {
+	return s.min <= pos && pos < s.max
+}
+
+// growSpan expands the span for the object to contain the instance represented
+// by the identifier.
+func (pkg *Package) growSpan(ident *ast.Ident, obj types.Object) {
+	if *strictShadowing {
+		return // No need
+	}
+	pos := ident.Pos()
+	end := ident.End()
+	span, ok := pkg.spans[obj]
+	if ok {
+		if span.min > pos {
+			span.min = pos
+		}
+		if span.max < end {
+			span.max = end
+		}
+	} else {
+		span = Span{pos, end}
+	}
+	pkg.spans[obj] = span
+}
+
+// checkShadowAssignment checks for shadowing in a short variable declaration.
+func checkShadowAssignment(f *File, a *ast.AssignStmt) {
+	if a.Tok != token.DEFINE {
+		return
+	}
+	if f.idiomaticShortRedecl(a) {
+		return
+	}
+	for _, expr := range a.Lhs {
+		ident, ok := expr.(*ast.Ident)
+		if !ok {
+			f.Badf(expr.Pos(), "invalid AST: short variable declaration of non-identifier")
+			return
+		}
+		checkShadowing(f, ident)
+	}
+}
+
+// idiomaticShortRedecl reports whether this short declaration can be ignored for
+// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.
+func (f *File) idiomaticShortRedecl(a *ast.AssignStmt) bool {
+	// Don't complain about deliberate redeclarations of the form
+	//	i := i
+	// Such constructs are idiomatic in range loops to create a new variable
+	// for each iteration. Another example is
+	//	switch n := n.(type)
+	if len(a.Rhs) != len(a.Lhs) {
+		return false
+	}
+	// We know it's an assignment, so the LHS must be all identifiers. (We check anyway.)
+	for i, expr := range a.Lhs {
+		lhs, ok := expr.(*ast.Ident)
+		if !ok {
+			f.Badf(expr.Pos(), "invalid AST: short variable declaration of non-identifier")
+			return true // Don't do any more processing.
+		}
+		switch rhs := a.Rhs[i].(type) {
+		case *ast.Ident:
+			if lhs.Name != rhs.Name {
+				return false
+			}
+		case *ast.TypeAssertExpr:
+			if id, ok := rhs.X.(*ast.Ident); ok {
+				if lhs.Name != id.Name {
+					return false
+				}
+			}
+		}
+	}
+	return true
+}
+
+// idiomaticRedecl reports whether this declaration spec can be ignored for
+// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.
+func (f *File) idiomaticRedecl(d *ast.ValueSpec) bool {
+	// Don't complain about deliberate redeclarations of the form
+	//	var i, j = i, j
+	if len(d.Names) != len(d.Values) {
+		return false
+	}
+	for i, lhs := range d.Names {
+		if rhs, ok := d.Values[i].(*ast.Ident); ok {
+			if lhs.Name != rhs.Name {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+// checkShadowDecl checks for shadowing in a general variable declaration.
+func checkShadowDecl(f *File, d *ast.GenDecl) {
+	if d.Tok != token.VAR {
+		return
+	}
+	for _, spec := range d.Specs {
+		valueSpec, ok := spec.(*ast.ValueSpec)
+		if !ok {
+			f.Badf(spec.Pos(), "invalid AST: var GenDecl not ValueSpec")
+			return
+		}
+		// Don't complain about deliberate redeclarations of the form
+		//	var i = i
+		if f.idiomaticRedecl(valueSpec) {
+			return
+		}
+		for _, ident := range valueSpec.Names {
+			checkShadowing(f, ident)
+		}
+	}
+}
+
+// checkShadowing checks whether the identifier shadows an identifier in an outer scope.
+func checkShadowing(f *File, ident *ast.Ident) {
+	if ident.Name == "_" {
+		// Can't shadow the blank identifier.
+		return
+	}
+	obj := f.pkg.defs[ident]
+	if obj == nil {
+		return
+	}
+	// obj.Parent.Parent is the surrounding scope. If we can find another declaration
+	// starting from there, we have a shadowed identifier.
+	_, shadowed := obj.Parent().Parent().LookupParent(obj.Name())
+	if shadowed == nil {
+		return
+	}
+	// Don't complain if it's shadowing a universe-declared identifier; that's fine.
+	if shadowed.Parent() == types.Universe {
+		return
+	}
+	if *strictShadowing {
+		// The shadowed identifier must appear before this one to be an instance of shadowing.
+		if shadowed.Pos() > ident.Pos() {
+			return
+		}
+	} else {
+		// Don't complain if the span of validity of the shadowed identifier doesn't include
+		// the shadowing identifier.
+		span, ok := f.pkg.spans[shadowed]
+		if !ok {
+			f.Badf(ident.Pos(), "internal error: no range for %s", ident.Name)
+			return
+		}
+		if !span.contains(ident.Pos()) {
+			return
+		}
+	}
+	// Don't complain if the types differ: that implies the programmer really wants two different things.
+	if types.Identical(obj.Type(), shadowed.Type()) {
+		f.Badf(ident.Pos(), "declaration of %s shadows declaration at %s", obj.Name(), f.loc(shadowed.Pos()))
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/shift.go b/third_party/go.tools/cmd/vet/shift.go
new file mode 100644
index 0000000..c6c07e0
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/shift.go
@@ -0,0 +1,83 @@
+// Copyright 2014 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.
+
+/*
+This file contains the code to check for suspicious shifts.
+*/
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func init() {
+	register("shift",
+		"check for useless shifts",
+		checkShift,
+		binaryExpr, assignStmt)
+}
+
+func checkShift(f *File, node ast.Node) {
+	switch node := node.(type) {
+	case *ast.BinaryExpr:
+		if node.Op == token.SHL || node.Op == token.SHR {
+			checkLongShift(f, node, node.X, node.Y)
+		}
+	case *ast.AssignStmt:
+		if len(node.Lhs) != 1 || len(node.Rhs) != 1 {
+			return
+		}
+		if node.Tok == token.SHL_ASSIGN || node.Tok == token.SHR_ASSIGN {
+			checkLongShift(f, node, node.Lhs[0], node.Rhs[0])
+		}
+	}
+}
+
+// checkLongShift checks if shift or shift-assign operations shift by more than
+// the length of the underlying variable.
+func checkLongShift(f *File, node ast.Node, x, y ast.Expr) {
+	v := f.pkg.types[y].Value
+	if v == nil {
+		return
+	}
+	amt, ok := exact.Int64Val(v)
+	if !ok {
+		return
+	}
+	t := f.pkg.types[x].Type
+	if t == nil {
+		return
+	}
+	b, ok := t.Underlying().(*types.Basic)
+	if !ok {
+		return
+	}
+	var size int64
+	var msg string
+	switch b.Kind() {
+	case types.Uint8, types.Int8:
+		size = 8
+	case types.Uint16, types.Int16:
+		size = 16
+	case types.Uint32, types.Int32:
+		size = 32
+	case types.Uint64, types.Int64:
+		size = 64
+	case types.Int, types.Uint, types.Uintptr:
+		// These types may be as small as 32 bits, but no smaller.
+		size = 32
+		msg = "might be "
+	default:
+		return
+	}
+	if amt >= size {
+		ident := f.gofmt(x)
+		f.Badf(node.Pos(), "%s %stoo small for shift of %d", ident, msg, amt)
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/structtag.go b/third_party/go.tools/cmd/vet/structtag.go
new file mode 100644
index 0000000..5da3904
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/structtag.go
@@ -0,0 +1,62 @@
+// Copyright 2010 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.
+
+// This file contains the test for canonical struct tags.
+
+package main
+
+import (
+	"go/ast"
+	"reflect"
+	"strconv"
+)
+
+func init() {
+	register("structtags",
+		"check that struct field tags have canonical format and apply to exported fields as needed",
+		checkCanonicalFieldTag,
+		field)
+}
+
+// checkCanonicalFieldTag checks a struct field tag.
+func checkCanonicalFieldTag(f *File, node ast.Node) {
+	field := node.(*ast.Field)
+	if field.Tag == nil {
+		return
+	}
+
+	tag, err := strconv.Unquote(field.Tag.Value)
+	if err != nil {
+		f.Badf(field.Pos(), "unable to read struct tag %s", field.Tag.Value)
+		return
+	}
+
+	// Check tag for validity by appending
+	// new key:value to end and checking that
+	// the tag parsing code can find it.
+	st := reflect.StructTag(tag + ` _gofix:"_magic"`)
+	if st.Get("_gofix") != "_magic" {
+		f.Badf(field.Pos(), "struct field tag %s not compatible with reflect.StructTag.Get", field.Tag.Value)
+		return
+	}
+
+	// Check for use of json or xml tags with unexported fields.
+
+	// Embedded struct. Nothing to do for now, but that
+	// may change, depending on what happens with issue 7363.
+	if len(field.Names) == 0 {
+		return
+	}
+
+	if field.Names[0].IsExported() {
+		return
+	}
+
+	for _, enc := range [...]string{"json", "xml"} {
+		if st.Get(enc) != "" {
+			f.Badf(field.Pos(), "struct field %s has %s tag but is not exported", field.Names[0].Name, enc)
+			return
+		}
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/asm.go b/third_party/go.tools/cmd/vet/testdata/asm.go
new file mode 100644
index 0000000..9a3d531
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/asm.go
@@ -0,0 +1,33 @@
+// Copyright 2010 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.
+
+// +build ignore
+
+// This file contains declarations to test the assembly in test_asm.s.
+
+package testdata
+
+func arg1(x int8, y uint8)
+func arg2(x int16, y uint16)
+func arg4(x int32, y uint32)
+func arg8(x int64, y uint64)
+func argint(x int, y uint)
+func argptr(x *byte, y *byte, c chan int, m map[int]int, f func())
+func argstring(x, y string)
+func argslice(x, y []string)
+func argiface(x interface{}, y interface {
+	m()
+})
+func returnint() int
+func returnbyte(x int) byte
+func returnnamed(x byte) (r1 int, r2 int16, r3 string, r4 byte)
+func returnintmissing() int
+func leaf(x, y int) int
+
+func noprof(x int)
+func dupok(x int)
+func nosplit(x int)
+func rodata(x int)
+func noptr(x int)
+func wrapper(x int)
diff --git a/third_party/go.tools/cmd/vet/testdata/asm1.s b/third_party/go.tools/cmd/vet/testdata/asm1.s
new file mode 100644
index 0000000..62f423c
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/asm1.s
@@ -0,0 +1,254 @@
+// Copyright 2013 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.
+
+// +build amd64
+// +build vet_test
+
+TEXT ·arg1(SB),0,$0-2
+	MOVB	x+0(FP), AX
+	// MOVB x+0(FP), AX // commented out instructions used to panic
+	MOVB	y+1(FP), BX
+	MOVW	x+0(FP), AX // ERROR "\[amd64\] arg1: invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+	MOVW	y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int8 is 1-byte value"
+	MOVL	y+1(FP), AX // ERROR "invalid MOVL of y\+1\(FP\); uint8 is 1-byte value"
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int8 is 1-byte value"
+	MOVQ	y+1(FP), AX // ERROR "invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value"
+	MOVB	x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+	MOVB	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+	TESTB	x+0(FP), AX
+	TESTB	y+1(FP), BX
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int8 is 1-byte value"
+	TESTW	y+1(FP), AX // ERROR "invalid TESTW of y\+1\(FP\); uint8 is 1-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int8 is 1-byte value"
+	TESTL	y+1(FP), AX // ERROR "invalid TESTL of y\+1\(FP\); uint8 is 1-byte value"
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int8 is 1-byte value"
+	TESTQ	y+1(FP), AX // ERROR "invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value"
+	TESTB	x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+	TESTB	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+	MOVB	8(SP), AX // ERROR "8\(SP\) should be x\+0\(FP\)"
+	MOVB	9(SP), AX // ERROR "9\(SP\) should be y\+1\(FP\)"
+	MOVB	10(SP), AX // ERROR "use of 10\(SP\) points beyond argument frame"
+	RET
+
+TEXT ·arg2(SB),0,$0-4
+	MOVB	x+0(FP), AX // ERROR "arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+	MOVB	y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+	MOVW	x+0(FP), AX
+	MOVW	y+2(FP), BX
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int16 is 2-byte value"
+	MOVL	y+2(FP), AX // ERROR "invalid MOVL of y\+2\(FP\); uint16 is 2-byte value"
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int16 is 2-byte value"
+	MOVQ	y+2(FP), AX // ERROR "invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value"
+	MOVW	x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+	MOVW	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int16 is 2-byte value"
+	TESTB	y+2(FP), AX // ERROR "invalid TESTB of y\+2\(FP\); uint16 is 2-byte value"
+	TESTW	x+0(FP), AX
+	TESTW	y+2(FP), BX
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int16 is 2-byte value"
+	TESTL	y+2(FP), AX // ERROR "invalid TESTL of y\+2\(FP\); uint16 is 2-byte value"
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int16 is 2-byte value"
+	TESTQ	y+2(FP), AX // ERROR "invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value"
+	TESTW	x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+	TESTW	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+	RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int32 is 4-byte value"
+	MOVW	y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint32 is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVL	y+4(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int32 is 4-byte value"
+	MOVQ	y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value"
+	MOVL	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVL	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int32 is 4-byte value"
+	TESTB	y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint32 is 4-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int32 is 4-byte value"
+	TESTW	y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint32 is 4-byte value"
+	TESTL	x+0(FP), AX
+	TESTL	y+4(FP), AX
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int32 is 4-byte value"
+	TESTQ	y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value"
+	TESTL	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	TESTL	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+	MOVB	y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int64 is 8-byte value"
+	MOVL	y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint64 is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVQ	y+8(FP), AX
+	MOVQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int64 is 8-byte value"
+	TESTB	y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint64 is 8-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int64 is 8-byte value"
+	TESTW	y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint64 is 8-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int64 is 8-byte value"
+	TESTL	y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint64 is 8-byte value"
+	TESTQ	x+0(FP), AX
+	TESTQ	y+8(FP), AX
+	TESTQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 8-byte value"
+	MOVB	y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint is 8-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int is 8-byte value"
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int is 8-byte value"
+	MOVL	y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVQ	y+8(FP), AX
+	MOVQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int is 8-byte value"
+	TESTB	y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint is 8-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int is 8-byte value"
+	TESTW	y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint is 8-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int is 8-byte value"
+	TESTL	y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint is 8-byte value"
+	TESTQ	x+0(FP), AX
+	TESTQ	y+8(FP), AX
+	TESTQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-40"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 8-byte value"
+	MOVB	y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); \*byte is 8-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 8-byte value"
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); \*byte is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); \*byte is 8-byte value"
+	MOVL	y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); \*byte is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVQ	y+8(FP), AX
+	MOVQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); \*byte is 8-byte value"
+	TESTB	y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); \*byte is 8-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); \*byte is 8-byte value"
+	TESTW	y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); \*byte is 8-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); \*byte is 8-byte value"
+	TESTL	y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); \*byte is 8-byte value"
+	TESTQ	x+0(FP), AX
+	TESTQ	y+8(FP), AX
+	TESTQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	MOVL	c+16(FP), AX // ERROR "invalid MOVL of c\+16\(FP\); chan int is 8-byte value"
+	MOVL	m+24(FP), AX // ERROR "invalid MOVL of m\+24\(FP\); map\[int\]int is 8-byte value"
+	MOVL	f+32(FP), AX // ERROR "invalid MOVL of f\+32\(FP\); func\(\) is 8-byte value"
+	RET
+
+TEXT ·argstring(SB),0,$32 // ERROR "wrong argument size 0; expected \$\.\.\.-32"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); string base is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); string base is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVW	x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 8-byte value"
+	MOVL	x_base+0(FP), AX // ERROR "invalid MOVL of x_base\+0\(FP\); string base is 8-byte value"
+	MOVQ	x_base+0(FP), AX
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVL	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVW	x_len+8(FP), AX // ERROR "invalid MOVW of x_len\+8\(FP\); string len is 8-byte value"
+	MOVL	x_len+8(FP), AX // ERROR "invalid MOVL of x_len\+8\(FP\); string len is 8-byte value"
+	MOVQ	x_len+8(FP), AX
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+16\(FP\)"
+	MOVQ	y_len+8(FP), AX // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)"
+	RET
+
+TEXT ·argslice(SB),0,$48 // ERROR "wrong argument size 0; expected \$\.\.\.-48"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); slice base is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); slice base is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVW	x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value"
+	MOVL	x_base+0(FP), AX // ERROR "invalid MOVL of x_base\+0\(FP\); slice base is 8-byte value"
+	MOVQ	x_base+0(FP), AX
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVL	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVW	x_len+8(FP), AX // ERROR "invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value"
+	MOVL	x_len+8(FP), AX // ERROR "invalid MOVL of x_len\+8\(FP\); slice len is 8-byte value"
+	MOVQ	x_len+8(FP), AX
+	MOVW	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+	MOVL	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+	MOVQ	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+	MOVW	x_cap+16(FP), AX // ERROR "invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value"
+	MOVL	x_cap+16(FP), AX // ERROR "invalid MOVL of x_cap\+16\(FP\); slice cap is 8-byte value"
+	MOVQ	x_cap+16(FP), AX
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+24\(FP\)"
+	MOVQ	y_len+8(FP), AX // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)"
+	MOVQ	y_cap+16(FP), AX // ERROR "invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)"
+	RET
+
+TEXT ·argiface(SB),0,$0-32
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); interface type is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); interface type is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVW	x_type+0(FP), AX // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value"
+	MOVL	x_type+0(FP), AX // ERROR "invalid MOVL of x_type\+0\(FP\); interface type is 8-byte value"
+	MOVQ	x_type+0(FP), AX
+	MOVQ	x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+	MOVQ	x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+	MOVW	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+	MOVL	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+	MOVQ	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+	MOVW	x_data+8(FP), AX // ERROR "invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value"
+	MOVL	x_data+8(FP), AX // ERROR "invalid MOVL of x_data\+8\(FP\); interface data is 8-byte value"
+	MOVQ	x_data+8(FP), AX
+	MOVW	y+16(FP), AX // ERROR "invalid MOVW of y\+16\(FP\); interface itable is 8-byte value"
+	MOVL	y+16(FP), AX // ERROR "invalid MOVL of y\+16\(FP\); interface itable is 8-byte value"
+	MOVQ	y+16(FP), AX
+	MOVW	y_itable+16(FP), AX // ERROR "invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value"
+	MOVL	y_itable+16(FP), AX // ERROR "invalid MOVL of y_itable\+16\(FP\); interface itable is 8-byte value"
+	MOVQ	y_itable+16(FP), AX
+	MOVQ	y_type+16(FP), AX // ERROR "unknown variable y_type; offset 16 is y_itable\+16\(FP\)"
+	MOVW	y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+	MOVL	y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+	MOVQ	y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+	MOVW	y_data+24(FP), AX // ERROR "invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value"
+	MOVL	y_data+24(FP), AX // ERROR "invalid MOVL of y_data\+24\(FP\); interface data is 8-byte value"
+	MOVQ	y_data+24(FP), AX
+	RET
+
+TEXT ·returnint(SB),0,$0-8
+	MOVB	AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 8-byte value"
+	MOVW	AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 8-byte value"
+	MOVL	AX, ret+0(FP) // ERROR "invalid MOVL of ret\+0\(FP\); int is 8-byte value"
+	MOVQ	AX, ret+0(FP)
+	MOVQ	AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+	MOVQ	AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+	RET
+
+TEXT ·returnbyte(SB),0,$0-9
+	MOVQ	x+0(FP), AX
+	MOVB	AX, ret+8(FP)
+	MOVW	AX, ret+8(FP) // ERROR "invalid MOVW of ret\+8\(FP\); byte is 1-byte value"
+	MOVL	AX, ret+8(FP) // ERROR "invalid MOVL of ret\+8\(FP\); byte is 1-byte value"
+	MOVQ	AX, ret+8(FP) // ERROR "invalid MOVQ of ret\+8\(FP\); byte is 1-byte value"
+	MOVB	AX, ret+7(FP) // ERROR "invalid offset ret\+7\(FP\); expected ret\+8\(FP\)"
+	RET
+
+TEXT ·returnnamed(SB),0,$0-41
+	MOVB	x+0(FP), AX
+	MOVQ	AX, r1+8(FP)
+	MOVW	AX, r2+16(FP)
+	MOVQ	AX, r3+24(FP)
+	MOVQ	AX, r3_base+24(FP)
+	MOVQ	AX, r3_len+32(FP)
+	MOVB	AX, r4+40(FP)
+	MOVL	AX, r1+8(FP) // ERROR "invalid MOVL of r1\+8\(FP\); int is 8-byte value"
+	RET
+
+TEXT ·returnintmissing(SB),0,$0-8
+	RET // ERROR "RET without writing to 8-byte ret\+0\(FP\)"
diff --git a/third_party/go.tools/cmd/vet/testdata/asm2.s b/third_party/go.tools/cmd/vet/testdata/asm2.s
new file mode 100644
index 0000000..c33c02a
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/asm2.s
@@ -0,0 +1,257 @@
+// Copyright 2013 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.
+
+// +build 386
+// +build vet_test
+
+TEXT ·arg1(SB),0,$0-2
+	MOVB	x+0(FP), AX
+	MOVB	y+1(FP), BX
+	MOVW	x+0(FP), AX // ERROR "\[386\] arg1: invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+	MOVW	y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int8 is 1-byte value"
+	MOVL	y+1(FP), AX // ERROR "invalid MOVL of y\+1\(FP\); uint8 is 1-byte value"
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int8 is 1-byte value"
+	MOVQ	y+1(FP), AX // ERROR "invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value"
+	MOVB	x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+	MOVB	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+	TESTB	x+0(FP), AX
+	TESTB	y+1(FP), BX
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int8 is 1-byte value"
+	TESTW	y+1(FP), AX // ERROR "invalid TESTW of y\+1\(FP\); uint8 is 1-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int8 is 1-byte value"
+	TESTL	y+1(FP), AX // ERROR "invalid TESTL of y\+1\(FP\); uint8 is 1-byte value"
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int8 is 1-byte value"
+	TESTQ	y+1(FP), AX // ERROR "invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value"
+	TESTB	x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+	TESTB	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+	MOVB	4(SP), AX // ERROR "4\(SP\) should be x\+0\(FP\)"
+	MOVB	5(SP), AX // ERROR "5\(SP\) should be y\+1\(FP\)"
+	MOVB	6(SP), AX // ERROR "use of 6\(SP\) points beyond argument frame"
+	RET
+
+TEXT ·arg2(SB),0,$0-4
+	MOVB	x+0(FP), AX // ERROR "arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+	MOVB	y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+	MOVW	x+0(FP), AX
+	MOVW	y+2(FP), BX
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int16 is 2-byte value"
+	MOVL	y+2(FP), AX // ERROR "invalid MOVL of y\+2\(FP\); uint16 is 2-byte value"
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int16 is 2-byte value"
+	MOVQ	y+2(FP), AX // ERROR "invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value"
+	MOVW	x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+	MOVW	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int16 is 2-byte value"
+	TESTB	y+2(FP), AX // ERROR "invalid TESTB of y\+2\(FP\); uint16 is 2-byte value"
+	TESTW	x+0(FP), AX
+	TESTW	y+2(FP), BX
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int16 is 2-byte value"
+	TESTL	y+2(FP), AX // ERROR "invalid TESTL of y\+2\(FP\); uint16 is 2-byte value"
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int16 is 2-byte value"
+	TESTQ	y+2(FP), AX // ERROR "invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value"
+	TESTW	x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+	TESTW	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+	RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int32 is 4-byte value"
+	MOVW	y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint32 is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVL	y+4(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int32 is 4-byte value"
+	MOVQ	y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value"
+	MOVL	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVL	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int32 is 4-byte value"
+	TESTB	y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint32 is 4-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int32 is 4-byte value"
+	TESTW	y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint32 is 4-byte value"
+	TESTL	x+0(FP), AX
+	TESTL	y+4(FP), AX
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int32 is 4-byte value"
+	TESTQ	y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value"
+	TESTL	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	TESTL	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+	MOVB	y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+	MOVL	x_lo+0(FP), AX
+	MOVL	x_hi+4(FP), AX
+	MOVL	y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+	MOVL	y_lo+8(FP), AX
+	MOVL	y_hi+12(FP), AX
+	MOVQ	x+0(FP), AX
+	MOVQ	y+8(FP), AX
+	MOVQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int64 is 8-byte value"
+	TESTB	y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint64 is 8-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int64 is 8-byte value"
+	TESTW	y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint64 is 8-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+	TESTL	y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+	TESTQ	x+0(FP), AX
+	TESTQ	y+8(FP), AX
+	TESTQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int is 4-byte value"
+	MOVW	y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVL	y+4(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int is 4-byte value"
+	MOVQ	y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint is 4-byte value"
+	MOVQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int is 4-byte value"
+	TESTB	y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint is 4-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int is 4-byte value"
+	TESTW	y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint is 4-byte value"
+	TESTL	x+0(FP), AX
+	TESTL	y+4(FP), AX
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int is 4-byte value"
+	TESTQ	y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint is 4-byte value"
+	TESTQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 4-byte value"
+	MOVW	y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); \*byte is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVL	y+4(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); \*byte is 4-byte value"
+	MOVQ	y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); \*byte is 4-byte value"
+	MOVQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); \*byte is 4-byte value"
+	TESTB	y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); \*byte is 4-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); \*byte is 4-byte value"
+	TESTW	y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); \*byte is 4-byte value"
+	TESTL	x+0(FP), AX
+	TESTL	y+4(FP), AX
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); \*byte is 4-byte value"
+	TESTQ	y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); \*byte is 4-byte value"
+	TESTQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	MOVW	c+8(FP), AX // ERROR "invalid MOVW of c\+8\(FP\); chan int is 4-byte value"
+	MOVW	m+12(FP), AX // ERROR "invalid MOVW of m\+12\(FP\); map\[int\]int is 4-byte value"
+	MOVW	f+16(FP), AX // ERROR "invalid MOVW of f\+16\(FP\); func\(\) is 4-byte value"
+	RET
+
+TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); string base is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); string base is 4-byte value"
+	MOVW	x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 4-byte value"
+	MOVL	x_base+0(FP), AX
+	MOVQ	x_base+0(FP), AX // ERROR "invalid MOVQ of x_base\+0\(FP\); string base is 4-byte value"
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVL	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVW	x_len+4(FP), AX // ERROR "invalid MOVW of x_len\+4\(FP\); string len is 4-byte value"
+	MOVL	x_len+4(FP), AX
+	MOVQ	x_len+4(FP), AX // ERROR "invalid MOVQ of x_len\+4\(FP\); string len is 4-byte value"
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
+	MOVQ	y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
+	RET
+
+TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); slice base is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); slice base is 4-byte value"
+	MOVW	x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 4-byte value"
+	MOVL	x_base+0(FP), AX
+	MOVQ	x_base+0(FP), AX // ERROR "invalid MOVQ of x_base\+0\(FP\); slice base is 4-byte value"
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVL	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVW	x_len+4(FP), AX // ERROR "invalid MOVW of x_len\+4\(FP\); slice len is 4-byte value"
+	MOVL	x_len+4(FP), AX
+	MOVQ	x_len+4(FP), AX // ERROR "invalid MOVQ of x_len\+4\(FP\); slice len is 4-byte value"
+	MOVW	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVL	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVQ	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVW	x_cap+8(FP), AX // ERROR "invalid MOVW of x_cap\+8\(FP\); slice cap is 4-byte value"
+	MOVL	x_cap+8(FP), AX
+	MOVQ	x_cap+8(FP), AX // ERROR "invalid MOVQ of x_cap\+8\(FP\); slice cap is 4-byte value"
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
+	MOVQ	y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
+	MOVQ	y_cap+8(FP), AX // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
+	RET
+
+TEXT ·argiface(SB),0,$0-16
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); interface type is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); interface type is 4-byte value"
+	MOVW	x_type+0(FP), AX // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 4-byte value"
+	MOVL	x_type+0(FP), AX
+	MOVQ	x_type+0(FP), AX // ERROR "invalid MOVQ of x_type\+0\(FP\); interface type is 4-byte value"
+	MOVQ	x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+	MOVQ	x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+	MOVW	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVL	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVQ	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVW	x_data+4(FP), AX // ERROR "invalid MOVW of x_data\+4\(FP\); interface data is 4-byte value"
+	MOVL	x_data+4(FP), AX
+	MOVQ	x_data+4(FP), AX // ERROR "invalid MOVQ of x_data\+4\(FP\); interface data is 4-byte value"
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); interface itable is 4-byte value"
+	MOVL	y+8(FP), AX
+	MOVQ	y+8(FP), AX // ERROR "invalid MOVQ of y\+8\(FP\); interface itable is 4-byte value"
+	MOVW	y_itable+8(FP), AX // ERROR "invalid MOVW of y_itable\+8\(FP\); interface itable is 4-byte value"
+	MOVL	y_itable+8(FP), AX
+	MOVQ	y_itable+8(FP), AX // ERROR "invalid MOVQ of y_itable\+8\(FP\); interface itable is 4-byte value"
+	MOVQ	y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
+	MOVW	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVL	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVQ	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVW	y_data+12(FP), AX // ERROR "invalid MOVW of y_data\+12\(FP\); interface data is 4-byte value"
+	MOVL	y_data+12(FP), AX
+	MOVQ	y_data+12(FP), AX // ERROR "invalid MOVQ of y_data\+12\(FP\); interface data is 4-byte value"
+	RET
+
+TEXT ·returnint(SB),0,$0-4
+	MOVB	AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 4-byte value"
+	MOVW	AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 4-byte value"
+	MOVL	AX, ret+0(FP)
+	MOVQ	AX, ret+0(FP) // ERROR "invalid MOVQ of ret\+0\(FP\); int is 4-byte value"
+	MOVQ	AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+	MOVQ	AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+	RET
+
+TEXT ·returnbyte(SB),0,$0-5
+	MOVL	x+0(FP), AX
+	MOVB	AX, ret+4(FP)
+	MOVW	AX, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
+	MOVL	AX, ret+4(FP) // ERROR "invalid MOVL of ret\+4\(FP\); byte is 1-byte value"
+	MOVQ	AX, ret+4(FP) // ERROR "invalid MOVQ of ret\+4\(FP\); byte is 1-byte value"
+	MOVB	AX, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
+	RET
+
+TEXT ·returnnamed(SB),0,$0-21
+	MOVB	x+0(FP), AX
+	MOVL	AX, r1+4(FP)
+	MOVW	AX, r2+8(FP)
+	MOVL	AX, r3+12(FP)
+	MOVL	AX, r3_base+12(FP)
+	MOVL	AX, r3_len+16(FP)
+	MOVB	AX, r4+20(FP)
+	MOVQ	AX, r1+4(FP) // ERROR "invalid MOVQ of r1\+4\(FP\); int is 4-byte value"
+	RET
+
+TEXT ·returnintmissing(SB),0,$0-4
+	RET // ERROR "RET without writing to 4-byte ret\+0\(FP\)"
diff --git a/third_party/go.tools/cmd/vet/testdata/asm3.s b/third_party/go.tools/cmd/vet/testdata/asm3.s
new file mode 100644
index 0000000..3d69356
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/asm3.s
@@ -0,0 +1,178 @@
+// Copyright 2013 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.
+
+// +build arm
+// +build vet_test
+
+TEXT ·arg1(SB),0,$0-2
+	MOVB	x+0(FP), AX
+	MOVB	y+1(FP), BX
+	MOVH	x+0(FP), AX // ERROR "\[arm\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value"
+	MOVH	y+1(FP), AX // ERROR "invalid MOVH of y\+1\(FP\); uint8 is 1-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+	MOVW	y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+	MOVB	x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+	MOVB	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+	MOVB	8(R13), AX // ERROR "8\(R13\) should be x\+0\(FP\)"
+	MOVB	9(R13), AX // ERROR "9\(R13\) should be y\+1\(FP\)"
+	MOVB	10(R13), AX // ERROR "use of 10\(R13\) points beyond argument frame"
+	RET
+
+TEXT ·arg2(SB),0,$0-4
+	MOVB	x+0(FP), AX // ERROR "arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+	MOVB	y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+	MOVH	x+0(FP), AX
+	MOVH	y+2(FP), BX
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int16 is 2-byte value"
+	MOVW	y+2(FP), AX // ERROR "invalid MOVW of y\+2\(FP\); uint16 is 2-byte value"
+	MOVH	x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+	MOVH	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+	RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int32 is 4-byte value"
+	MOVH	y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); uint32 is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVW	y+4(FP), AX
+	MOVW	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVW	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+	MOVB	y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int64 is 8-byte value"
+	MOVH	y+8(FP), AX // ERROR "invalid MOVH of y\+8\(FP\); uint64 is 8-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+	MOVW	x_lo+0(FP), AX
+	MOVW	x_hi+4(FP), AX
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+	MOVW	y_lo+8(FP), AX
+	MOVW	y_hi+12(FP), AX
+	MOVQ	x+0(FP), AX
+	MOVQ	y+8(FP), AX
+	MOVQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int is 4-byte value"
+	MOVH	y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); uint is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVW	y+4(FP), AX
+	MOVQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); \*byte is 4-byte value"
+	MOVH	y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); \*byte is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVW	y+4(FP), AX
+	MOVQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	MOVH	c+8(FP), AX // ERROR "invalid MOVH of c\+8\(FP\); chan int is 4-byte value"
+	MOVH	m+12(FP), AX // ERROR "invalid MOVH of m\+12\(FP\); map\[int\]int is 4-byte value"
+	MOVH	f+16(FP), AX // ERROR "invalid MOVH of f\+16\(FP\); func\(\) is 4-byte value"
+	RET
+
+TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); string base is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVH	x_base+0(FP), AX // ERROR "invalid MOVH of x_base\+0\(FP\); string base is 4-byte value"
+	MOVW	x_base+0(FP), AX
+	MOVH	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVH	x_len+4(FP), AX // ERROR "invalid MOVH of x_len\+4\(FP\); string len is 4-byte value"
+	MOVW	x_len+4(FP), AX
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
+	MOVQ	y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
+	RET
+
+TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); slice base is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVH	x_base+0(FP), AX // ERROR "invalid MOVH of x_base\+0\(FP\); slice base is 4-byte value"
+	MOVW	x_base+0(FP), AX
+	MOVH	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVH	x_len+4(FP), AX // ERROR "invalid MOVH of x_len\+4\(FP\); slice len is 4-byte value"
+	MOVW	x_len+4(FP), AX
+	MOVH	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVW	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVQ	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVH	x_cap+8(FP), AX // ERROR "invalid MOVH of x_cap\+8\(FP\); slice cap is 4-byte value"
+	MOVW	x_cap+8(FP), AX
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
+	MOVQ	y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
+	MOVQ	y_cap+8(FP), AX // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
+	RET
+
+TEXT ·argiface(SB),0,$0-16
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); interface type is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVH	x_type+0(FP), AX // ERROR "invalid MOVH of x_type\+0\(FP\); interface type is 4-byte value"
+	MOVW	x_type+0(FP), AX
+	MOVQ	x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+	MOVQ	x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+	MOVH	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVW	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVQ	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVH	x_data+4(FP), AX // ERROR "invalid MOVH of x_data\+4\(FP\); interface data is 4-byte value"
+	MOVW	x_data+4(FP), AX
+	MOVH	y+8(FP), AX // ERROR "invalid MOVH of y\+8\(FP\); interface itable is 4-byte value"
+	MOVW	y+8(FP), AX
+	MOVH	y_itable+8(FP), AX // ERROR "invalid MOVH of y_itable\+8\(FP\); interface itable is 4-byte value"
+	MOVW	y_itable+8(FP), AX
+	MOVQ	y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
+	MOVH	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVW	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVQ	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVH	y_data+12(FP), AX // ERROR "invalid MOVH of y_data\+12\(FP\); interface data is 4-byte value"
+	MOVW	y_data+12(FP), AX
+	RET
+
+TEXT ·returnint(SB),0,$0-4
+	MOVB	AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 4-byte value"
+	MOVH	AX, ret+0(FP) // ERROR "invalid MOVH of ret\+0\(FP\); int is 4-byte value"
+	MOVW	AX, ret+0(FP)
+	MOVQ	AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+	MOVQ	AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+	RET
+
+TEXT ·returnbyte(SB),0,$0-5
+	MOVW	x+0(FP), AX
+	MOVB	AX, ret+4(FP)
+	MOVH	AX, ret+4(FP) // ERROR "invalid MOVH of ret\+4\(FP\); byte is 1-byte value"
+	MOVW	AX, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
+	MOVB	AX, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
+	RET
+
+TEXT ·returnnamed(SB),0,$0-21
+	MOVB	x+0(FP), AX
+	MOVW	AX, r1+4(FP)
+	MOVH	AX, r2+8(FP)
+	MOVW	AX, r3+12(FP)
+	MOVW	AX, r3_base+12(FP)
+	MOVW	AX, r3_len+16(FP)
+	MOVB	AX, r4+20(FP)
+	MOVB	AX, r1+4(FP) // ERROR "invalid MOVB of r1\+4\(FP\); int is 4-byte value"
+	RET
+
+TEXT ·returnintmissing(SB),0,$0-4
+	RET // ERROR "RET without writing to 4-byte ret\+0\(FP\)"
+
+TEXT ·leaf(SB),0,$-4-12
+	MOVW	x+0(FP), AX
+	MOVW	y+4(FP), AX
+	MOVW	AX, ret+8(FP)
+	RET
diff --git a/third_party/go.tools/cmd/vet/testdata/asm4.s b/third_party/go.tools/cmd/vet/testdata/asm4.s
new file mode 100644
index 0000000..044b050
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/asm4.s
@@ -0,0 +1,26 @@
+// Copyright 2013 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.
+
+// +build amd64
+// +build vet_test
+
+// Test cases for symbolic NOSPLIT etc. on TEXT symbols.
+
+TEXT ·noprof(SB),NOPROF,$0-8
+	RET
+
+TEXT ·dupok(SB),DUPOK,$0-8
+	RET
+
+TEXT ·nosplit(SB),NOSPLIT,$0
+	RET
+
+TEXT ·rodata(SB),RODATA,$0-8
+	RET
+
+TEXT ·noptr(SB),NOPTR|NOSPLIT,$0
+	RET
+
+TEXT ·wrapper(SB),WRAPPER,$0-8
+	RET
diff --git a/third_party/go.tools/cmd/vet/testdata/assign.go b/third_party/go.tools/cmd/vet/testdata/assign.go
new file mode 100644
index 0000000..32ba868
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/assign.go
@@ -0,0 +1,18 @@
+// Copyright 2013 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.
+
+// This file contains tests for the useless-assignment checker.
+
+package testdata
+
+type ST struct {
+	x int
+}
+
+func (s *ST) SetX(x int) {
+	// Accidental self-assignment; it should be "s.x = x"
+	x = x // ERROR "self-assignment of x to x"
+	// Another mistake
+	s.x = s.x // ERROR "self-assignment of s.x to s.x"
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/atomic.go b/third_party/go.tools/cmd/vet/testdata/atomic.go
new file mode 100644
index 0000000..1ba261d
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/atomic.go
@@ -0,0 +1,43 @@
+// Copyright 2013 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.
+
+// This file contains tests for the atomic checker.
+
+package testdata
+
+import (
+	"sync/atomic"
+)
+
+type Counter uint64
+
+func AtomicTests() {
+	x := uint64(1)
+	x = atomic.AddUint64(&x, 1)        // ERROR "direct assignment to atomic value"
+	_, x = 10, atomic.AddUint64(&x, 1) // ERROR "direct assignment to atomic value"
+	x, _ = atomic.AddUint64(&x, 1), 10 // ERROR "direct assignment to atomic value"
+
+	y := &x
+	*y = atomic.AddUint64(y, 1) // ERROR "direct assignment to atomic value"
+
+	var su struct{ Counter uint64 }
+	su.Counter = atomic.AddUint64(&su.Counter, 1) // ERROR "direct assignment to atomic value"
+	z1 := atomic.AddUint64(&su.Counter, 1)
+	_ = z1 // Avoid err "z declared and not used"
+
+	var sp struct{ Counter *uint64 }
+	*sp.Counter = atomic.AddUint64(sp.Counter, 1) // ERROR "direct assignment to atomic value"
+	z2 := atomic.AddUint64(sp.Counter, 1)
+	_ = z2 // Avoid err "z declared and not used"
+
+	au := []uint64{10, 20}
+	au[0] = atomic.AddUint64(&au[0], 1) // ERROR "direct assignment to atomic value"
+	au[1] = atomic.AddUint64(&au[0], 1)
+
+	ap := []*uint64{&au[0], &au[1]}
+	*ap[0] = atomic.AddUint64(ap[0], 1) // ERROR "direct assignment to atomic value"
+	*ap[1] = atomic.AddUint64(ap[0], 1)
+
+	x = atomic.AddUint64() // Used to make vet crash; now silently ignored.
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/bool.go b/third_party/go.tools/cmd/vet/testdata/bool.go
new file mode 100644
index 0000000..af6cc01
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/bool.go
@@ -0,0 +1,113 @@
+// Copyright 2014 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.
+
+// This file contains tests for the bool checker.
+
+package testdata
+
+import "io"
+
+func RatherStupidConditions() {
+	var f, g func() int
+	if f() == 0 || f() == 0 { // OK f might have side effects
+	}
+	if v, w := f(), g(); v == w || v == w { // ERROR "redundant or: v == w || v == w"
+	}
+	_ = f == nil || f == nil // ERROR "redundant or: f == nil || f == nil"
+
+	_ = i == byte(1) || i == byte(1) // TODO conversions are treated as if they may have side effects
+
+	var c chan int
+	_ = 0 == <-c || 0 == <-c                                  // OK subsequent receives may yield different values
+	for i, j := <-c, <-c; i == j || i == j; i, j = <-c, <-c { // ERROR "redundant or: i == j || i == j"
+	}
+
+	var i, j, k int
+	_ = i+1 == 1 || i+1 == 1         // ERROR "redundant or: i\+1 == 1 || i\+1 == 1"
+	_ = i == 1 || j+1 == i || i == 1 // ERROR "redundant or: i == 1 || i == 1"
+
+	_ = i == 1 || i == 1 || f() == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || f() == 1 || i == 1 // OK f may alter i as a side effect
+	_ = f() == 1 || i == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
+
+	// Test partition edge cases
+	_ = f() == 1 || i == 1 || i == 1 || j == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = f() == 1 || j == 1 || i == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || f() == 1 || i == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || i == 1 || f() == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || i == 1 || j == 1 || f() == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = j == 1 || i == 1 || i == 1 || f() == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || f() == 1 || f() == 1 || i == 1
+
+	_ = i == 1 || (i == 1 || i == 2)             // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || (f() == 1 || i == 1)           // OK f may alter i as a side effect
+	_ = i == 1 || (i == 1 || f() == 1)           // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || (i == 2 || (i == 1 || i == 3)) // ERROR "redundant or: i == 1 || i == 1"
+
+	var a, b bool
+	_ = i == 1 || (a || (i == 1 || b)) // ERROR "redundant or: i == 1 || i == 1"
+
+	// Check that all redundant ors are flagged
+	_ = j == 0 ||
+		i == 1 ||
+		f() == 1 ||
+		j == 0 || // ERROR "redundant or: j == 0 || j == 0"
+		i == 1 || // ERROR "redundant or: i == 1 || i == 1"
+		i == 1 || // ERROR "redundant or: i == 1 || i == 1"
+		i == 1 ||
+		j == 0 ||
+		k == 0
+
+	_ = i == 1*2*3 || i == 1*2*3 // ERROR "redundant or: i == 1\*2\*3 || i == 1\*2\*3"
+
+	// These test that redundant, suspect expressions do not trigger multiple errors.
+	_ = i != 0 || i != 0 // ERROR "redundant or: i != 0 || i != 0"
+	_ = i == 0 && i == 0 // ERROR "redundant and: i == 0 && i == 0"
+
+	// and is dual to or; check the basics and
+	// let the or tests pull the rest of the weight.
+	_ = 0 != <-c && 0 != <-c         // OK subsequent receives may yield different values
+	_ = f() != 0 && f() != 0         // OK f might have side effects
+	_ = f != nil && f != nil         // ERROR "redundant and: f != nil && f != nil"
+	_ = i != 1 && i != 1 && f() != 1 // ERROR "redundant and: i != 1 && i != 1"
+	_ = i != 1 && f() != 1 && i != 1 // OK f may alter i as a side effect
+	_ = f() != 1 && i != 1 && i != 1 // ERROR "redundant and: i != 1 && i != 1"
+}
+
+func RoyallySuspectConditions() {
+	var i, j int
+
+	_ = i == 0 || i == 1 // OK
+	_ = i != 0 || i != 1 // ERROR "suspect or: i != 0 || i != 1"
+	_ = i != 0 || 1 != i // ERROR "suspect or: i != 0 || 1 != i"
+	_ = 0 != i || 1 != i // ERROR "suspect or: 0 != i || 1 != i"
+	_ = 0 != i || i != 1 // ERROR "suspect or: 0 != i || i != 1"
+
+	_ = (0 != i) || i != 1 // ERROR "suspect or: 0 != i || i != 1"
+
+	_ = i+3 != 7 || j+5 == 0 || i+3 != 9 // ERROR "suspect or: i\+3 != 7 || i\+3 != 9"
+
+	_ = i != 0 || j == 0 || i != 1 // ERROR "suspect or: i != 0 || i != 1"
+
+	_ = i != 0 || i != 1<<4 // ERROR "suspect or: i != 0 || i != 1<<4"
+
+	_ = i != 0 || j != 0
+	_ = 0 != i || 0 != j
+
+	var s string
+	_ = s != "one" || s != "the other" // ERROR "suspect or: s != .one. || s != .the other."
+
+	_ = "et" != "alii" || "et" != "cetera"         // ERROR "suspect or: .et. != .alii. || .et. != .cetera."
+	_ = "me gustas" != "tu" || "le gustas" != "tu" // OK we could catch this case, but it's not worth the code
+
+	var err error
+	_ = err != nil || err != io.EOF // TODO catch this case?
+
+	// Sanity check and.
+	_ = i != 0 && i != 1 // OK
+	_ = i == 0 && i == 1 // ERROR "suspect and: i == 0 && i == 1"
+	_ = i == 0 && 1 == i // ERROR "suspect and: i == 0 && 1 == i"
+	_ = 0 == i && 1 == i // ERROR "suspect and: 0 == i && 1 == i"
+	_ = 0 == i && i == 1 // ERROR "suspect and: 0 == i && i == 1"
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/buildtag.go b/third_party/go.tools/cmd/vet/testdata/buildtag.go
new file mode 100644
index 0000000..eb36fd3
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/buildtag.go
@@ -0,0 +1,14 @@
+// Copyright 2013 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.
+
+// This file contains tests for the buildtag checker.
+
+// +builder // ERROR "possible malformed \+build comment"
+// +build !ignore
+
+package testdata
+
+// +build toolate // ERROR "build comment must appear before package clause and be followed by a blank line"
+
+var _ = 3
diff --git a/third_party/go.tools/cmd/vet/testdata/buildtag_bad.go b/third_party/go.tools/cmd/vet/testdata/buildtag_bad.go
new file mode 100644
index 0000000..fbe10cf
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/buildtag_bad.go
@@ -0,0 +1,15 @@
+// This file contains misplaced or malformed build constraints.
+// The Go tool will skip it, because the constraints are invalid.
+// It serves only to test the tag checker during make test.
+
+// Mention +build // ERROR "possible malformed \+build comment"
+
+// +build !!bang // ERROR "invalid double negative in build constraint"
+// +build @#$ // ERROR "invalid non-alphanumeric build constraint"
+
+// +build toolate // ERROR "build comment must appear before package clause and be followed by a blank line"
+package bad
+
+// This is package 'bad' rather than 'main' so the erroneous build
+// tag doesn't end up looking like a package doc for the vet command
+// when examined by godoc.
diff --git a/third_party/go.tools/cmd/vet/testdata/composite.go b/third_party/go.tools/cmd/vet/testdata/composite.go
new file mode 100644
index 0000000..69e7d7c
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/composite.go
@@ -0,0 +1,63 @@
+// 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.
+
+// This file contains tests for the untagged struct literal checker.
+
+// This file contains the test for untagged struct literals.
+
+package testdata
+
+import (
+	"flag"
+	"go/scanner"
+)
+
+var Okay1 = []string{
+	"Name",
+	"Usage",
+	"DefValue",
+}
+
+var Okay2 = map[string]bool{
+	"Name":     true,
+	"Usage":    true,
+	"DefValue": true,
+}
+
+var Okay3 = struct {
+	X string
+	Y string
+	Z string
+}{
+	"Name",
+	"Usage",
+	"DefValue",
+}
+
+type MyStruct struct {
+	X string
+	Y string
+	Z string
+}
+
+var Okay4 = MyStruct{
+	"Name",
+	"Usage",
+	"DefValue",
+}
+
+// Testing is awkward because we need to reference things from a separate package
+// to trigger the warnings.
+
+var BadStructLiteralUsedInTests = flag.Flag{ // ERROR "unkeyed fields"
+	"Name",
+	"Usage",
+	nil, // Value
+	"DefValue",
+}
+
+// Used to test the check for slices and arrays: If that test is disabled and
+// vet is run with --compositewhitelist=false, this line triggers an error.
+// Clumsy but sufficient.
+var scannerErrorListTest = scanner.ErrorList{nil, nil}
diff --git a/third_party/go.tools/cmd/vet/testdata/copylock_func.go b/third_party/go.tools/cmd/vet/testdata/copylock_func.go
new file mode 100644
index 0000000..108c044
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/copylock_func.go
@@ -0,0 +1,90 @@
+// Copyright 2013 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.
+
+// This file contains tests for the copylock checker's
+// function declaration analysis.
+
+package testdata
+
+import "sync"
+
+func OkFunc(*sync.Mutex) {}
+func BadFunc(sync.Mutex) {} // ERROR "BadFunc passes Lock by value: sync.Mutex"
+func OkRet() *sync.Mutex {}
+func BadRet() sync.Mutex {} // ERROR "BadRet returns Lock by value: sync.Mutex"
+
+type EmbeddedRWMutex struct {
+	sync.RWMutex
+}
+
+func (*EmbeddedRWMutex) OkMeth() {}
+func (EmbeddedRWMutex) BadMeth() {} // ERROR "BadMeth passes Lock by value: testdata.EmbeddedRWMutex"
+func OkFunc(e *EmbeddedRWMutex)  {}
+func BadFunc(EmbeddedRWMutex)    {} // ERROR "BadFunc passes Lock by value: testdata.EmbeddedRWMutex"
+func OkRet() *EmbeddedRWMutex    {}
+func BadRet() EmbeddedRWMutex    {} // ERROR "BadRet returns Lock by value: testdata.EmbeddedRWMutex"
+
+type FieldMutex struct {
+	s sync.Mutex
+}
+
+func (*FieldMutex) OkMeth()   {}
+func (FieldMutex) BadMeth()   {} // ERROR "BadMeth passes Lock by value: testdata.FieldMutex contains sync.Mutex"
+func OkFunc(*FieldMutex)      {}
+func BadFunc(FieldMutex, int) {} // ERROR "BadFunc passes Lock by value: testdata.FieldMutex contains sync.Mutex"
+
+type L0 struct {
+	L1
+}
+
+type L1 struct {
+	l L2
+}
+
+type L2 struct {
+	sync.Mutex
+}
+
+func (*L0) Ok() {}
+func (L0) Bad() {} // ERROR "Bad passes Lock by value: testdata.L0 contains testdata.L1 contains testdata.L2"
+
+type EmbeddedMutexPointer struct {
+	s *sync.Mutex // safe to copy this pointer
+}
+
+func (*EmbeddedMutexPointer) Ok()      {}
+func (EmbeddedMutexPointer) AlsoOk()   {}
+func StillOk(EmbeddedMutexPointer)     {}
+func LookinGood() EmbeddedMutexPointer {}
+
+type EmbeddedLocker struct {
+	sync.Locker // safe to copy interface values
+}
+
+func (*EmbeddedLocker) Ok()    {}
+func (EmbeddedLocker) AlsoOk() {}
+
+type CustomLock struct{}
+
+func (*CustomLock) Lock()   {}
+func (*CustomLock) Unlock() {}
+
+func Ok(*CustomLock) {}
+func Bad(CustomLock) {} // ERROR "Bad passes Lock by value: testdata.CustomLock"
+
+// TODO: Unfortunate cases
+
+// Non-ideal error message:
+// Since we're looking for Lock methods, sync.Once's underlying
+// sync.Mutex gets called out, but without any reference to the sync.Once.
+type LocalOnce sync.Once
+
+func (LocalOnce) Bad() {} // ERROR "Bad passes Lock by value: testdata.LocalOnce contains sync.Mutex"
+
+// False negative:
+// LocalMutex doesn't have a Lock method.
+// Nevertheless, it is probably a bad idea to pass it by value.
+type LocalMutex sync.Mutex
+
+func (LocalMutex) Bad() {} // WANTED: An error here :(
diff --git a/third_party/go.tools/cmd/vet/testdata/copylock_range.go b/third_party/go.tools/cmd/vet/testdata/copylock_range.go
new file mode 100644
index 0000000..f95b025
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/copylock_range.go
@@ -0,0 +1,67 @@
+// Copyright 2014 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.
+
+// This file contains tests for the copylock checker's
+// range statement analysis.
+
+package testdata
+
+import "sync"
+
+func rangeMutex() {
+	var mu sync.Mutex
+	var i int
+
+	var s []sync.Mutex
+	for range s {
+	}
+	for i = range s {
+	}
+	for i := range s {
+	}
+	for i, _ = range s {
+	}
+	for i, _ := range s {
+	}
+	for _, mu = range s { // ERROR "range var mu copies Lock: sync.Mutex"
+	}
+	for _, m := range s { // ERROR "range var m copies Lock: sync.Mutex"
+	}
+	for i, mu = range s { // ERROR "range var mu copies Lock: sync.Mutex"
+	}
+	for i, m := range s { // ERROR "range var m copies Lock: sync.Mutex"
+	}
+
+	var a [3]sync.Mutex
+	for _, m := range a { // ERROR "range var m copies Lock: sync.Mutex"
+	}
+
+	var m map[sync.Mutex]sync.Mutex
+	for k := range m { // ERROR "range var k copies Lock: sync.Mutex"
+	}
+	for mu, _ = range m { // ERROR "range var mu copies Lock: sync.Mutex"
+	}
+	for k, _ := range m { // ERROR "range var k copies Lock: sync.Mutex"
+	}
+	for _, mu = range m { // ERROR "range var mu copies Lock: sync.Mutex"
+	}
+	for _, v := range m { // ERROR "range var v copies Lock: sync.Mutex"
+	}
+
+	var c chan sync.Mutex
+	for range c {
+	}
+	for mu = range c { // ERROR "range var mu copies Lock: sync.Mutex"
+	}
+	for v := range c { // ERROR "range var v copies Lock: sync.Mutex"
+	}
+
+	// Test non-idents in range variables
+	var t struct {
+		i  int
+		mu sync.Mutex
+	}
+	for t.i, t.mu = range s { // ERROR "range var t.mu copies Lock: sync.Mutex"
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/deadcode.go b/third_party/go.tools/cmd/vet/testdata/deadcode.go
new file mode 100644
index 0000000..5370bc3
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/deadcode.go
@@ -0,0 +1,2125 @@
+// Copyright 2013 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.
+
+// +build ignore
+
+// This file contains tests for the dead code checker.
+
+package testdata
+
+type T int
+
+var x interface{}
+var c chan int
+
+func external() int // ok
+
+func _() int {
+}
+
+func _() int {
+	print(1)
+}
+
+func _() int {
+	print(1)
+	return 2
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	goto L
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	panic(2)
+	println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+func _() int {
+	var panic = func(int) {}
+	print(1)
+	panic(2)
+	println() // ok
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+		println() // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+		println() // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	return 2
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+L:
+	print(1)
+	goto L
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	panic(2)
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 2 {
+		panic(3)
+	} else {
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x != nil {
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 1 {
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	for {
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	for {
+		for {
+			break
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	for {
+		for {
+			break
+			println() // ERROR "unreachable code"
+		}
+	}
+}
+
+func _() int {
+	for {
+		for {
+			continue
+			println() // ERROR "unreachable code"
+		}
+	}
+}
+
+func _() int {
+	for {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	for {
+		break
+	}
+	println() // ok
+}
+
+func _() int {
+	for {
+		for {
+		}
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	for {
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	for x == nil {
+	}
+	println() // ok
+}
+
+func _() int {
+	for x == nil {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	for x == nil {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	for true {
+	}
+	println() // ok
+}
+
+func _() int {
+	for true {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	for true {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	case c <- 1:
+		print(2)
+		goto L
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	default:
+		select {}
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		select {}
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		goto L // ERROR "unreachable code"
+	case c <- 1:
+		print(2)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		print(2)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	default:
+		break
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		break L
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(1)
+		panic("abc")
+	default:
+		select {}
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 2:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		break L // ERROR "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		break // ERROR "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case float64:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		break L // ERROR "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		break // ERROR "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+func _() int {
+	println() // ok
+}
+
+func _() int {
+	return 2
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	goto L
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	panic(2)
+	println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+func _() int {
+	var panic = func(int) {}
+	panic(2)
+	println() // ok
+}
+
+func _() int {
+	{
+		return 2
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	{
+		return 2
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	{
+		goto L
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+L:
+	{
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	{
+		panic(2)
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	{
+		panic(2)
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	return 2
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	goto L
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	panic(2)
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		return 2
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	{
+		goto L
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		panic(2)
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		return 2
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	{
+		goto L
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		panic(2)
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+// again, with func literals
+
+var _ = func() int {
+}
+
+var _ = func() int {
+	print(1)
+}
+
+var _ = func() int {
+	print(1)
+	return 2
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	goto L
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	panic(2)
+	println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+var _ = func() int {
+	var panic = func(int) {}
+	print(1)
+	panic(2)
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+		println() // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+		println() // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	return 2
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+L:
+	print(1)
+	goto L
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	panic(2)
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 2 {
+		panic(3)
+	} else {
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+var _ = func() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x != nil {
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 1 {
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	for {
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	for {
+		for {
+			break
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	for {
+		for {
+			break
+			println() // ERROR "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+	for {
+		for {
+			continue
+			println() // ERROR "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+	for {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	for {
+		break
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for {
+		for {
+		}
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	for {
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	for x == nil {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for x == nil {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for x == nil {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	for true {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for true {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for true {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	case c <- 1:
+		print(2)
+		goto L
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	default:
+		select {}
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		select {}
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		goto L // ERROR "unreachable code"
+	case c <- 1:
+		print(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		print(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	default:
+		break
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		break L
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(1)
+		panic("abc")
+	default:
+		select {}
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 2:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		break L // ERROR "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		break // ERROR "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case float64:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		break L // ERROR "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		break // ERROR "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+var _ = func() int {
+	println() // ok
+}
+
+var _ = func() int {
+	return 2
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	goto L
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	panic(2)
+	println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+var _ = func() int {
+	var panic = func(int) {}
+	panic(2)
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		return 2
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	{
+		return 2
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	{
+		panic(2)
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	{
+		panic(2)
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	return 2
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	goto L
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	panic(2)
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		return 2
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		panic(2)
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		return 2
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		panic(2)
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() {
+	// goto without label used to panic
+	goto
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/method.go b/third_party/go.tools/cmd/vet/testdata/method.go
new file mode 100644
index 0000000..52b500d
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/method.go
@@ -0,0 +1,22 @@
+// Copyright 2010 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.
+
+// This file contains tests for the canonical method checker.
+
+// This file contains the code to check canonical methods.
+
+package testdata
+
+import (
+	"fmt"
+)
+
+type MethodTest int
+
+func (t *MethodTest) Scan(x fmt.ScanState, c byte) { // ERROR "should have signature Scan"
+}
+
+type MethodTestInterface interface {
+	ReadByte() byte // ERROR "should have signature ReadByte"
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/nilfunc.go b/third_party/go.tools/cmd/vet/testdata/nilfunc.go
new file mode 100644
index 0000000..2ce7bc8
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/nilfunc.go
@@ -0,0 +1,35 @@
+// Copyright 2013 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 testdata
+
+func F() {}
+
+type T struct {
+	F func()
+}
+
+func (T) M() {}
+
+var Fv = F
+
+func Comparison() {
+	var t T
+	var fn func()
+	if fn == nil || Fv == nil || t.F == nil {
+		// no error; these func vars or fields may be nil
+	}
+	if F == nil { // ERROR "comparison of function F == nil is always false"
+		panic("can't happen")
+	}
+	if t.M == nil { // ERROR "comparison of function M == nil is always false"
+		panic("can't happen")
+	}
+	if F != nil { // ERROR "comparison of function F != nil is always true"
+		if t.M != nil { // ERROR "comparison of function M != nil is always true"
+			return
+		}
+	}
+	panic("can't happen")
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/print.go b/third_party/go.tools/cmd/vet/testdata/print.go
new file mode 100644
index 0000000..3875ac5
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/print.go
@@ -0,0 +1,340 @@
+// Copyright 2010 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.
+
+// This file contains tests for the printf checker.
+
+package testdata
+
+import (
+	"fmt"
+	"math"
+	"os"
+	"unsafe" // just for test case printing unsafe.Pointer
+)
+
+func UnsafePointerPrintfTest() {
+	var up unsafe.Pointer
+	fmt.Printf("%p, %x %X", up, up, up)
+}
+
+// Error methods that do not satisfy the Error interface and should be checked.
+type errorTest1 int
+
+func (errorTest1) Error(...interface{}) string {
+	return "hi"
+}
+
+type errorTest2 int // Analogous to testing's *T type.
+func (errorTest2) Error(...interface{}) {
+}
+
+type errorTest3 int
+
+func (errorTest3) Error() { // No return value.
+}
+
+type errorTest4 int
+
+func (errorTest4) Error() int { // Different return type.
+	return 3
+}
+
+type errorTest5 int
+
+func (errorTest5) error() { // niladic; don't complain if no args (was bug)
+}
+
+// This function never executes, but it serves as a simple test for the program.
+// Test with make test.
+func PrintfTests() {
+	var b bool
+	var i int
+	var r rune
+	var s string
+	var x float64
+	var p *int
+	var imap map[int]int
+	var fslice []float64
+	var c complex64
+	// Some good format/argtypes
+	fmt.Printf("")
+	fmt.Printf("%b %b %b", 3, i, x)
+	fmt.Printf("%c %c %c %c", 3, i, 'x', r)
+	fmt.Printf("%d %d %d", 3, i, imap)
+	fmt.Printf("%e %e %e %e", 3e9, x, fslice, c)
+	fmt.Printf("%E %E %E %E", 3e9, x, fslice, c)
+	fmt.Printf("%f %f %f %f", 3e9, x, fslice, c)
+	fmt.Printf("%F %F %F %F", 3e9, x, fslice, c)
+	fmt.Printf("%g %g %g %g", 3e9, x, fslice, c)
+	fmt.Printf("%G %G %G %G", 3e9, x, fslice, c)
+	fmt.Printf("%b %b %b %b", 3e9, x, fslice, c)
+	fmt.Printf("%o %o", 3, i)
+	fmt.Printf("%p %p", p, nil)
+	fmt.Printf("%q %q %q %q", 3, i, 'x', r)
+	fmt.Printf("%s %s %s", "hi", s, []byte{65})
+	fmt.Printf("%t %t", true, b)
+	fmt.Printf("%T %T", 3, i)
+	fmt.Printf("%U %U", 3, i)
+	fmt.Printf("%v %v", 3, i)
+	fmt.Printf("%x %x %x %x", 3, i, "hi", s)
+	fmt.Printf("%X %X %X %X", 3, i, "hi", s)
+	fmt.Printf("%.*s %d %g", 3, "hi", 23, 2.3)
+	fmt.Printf("%s", &stringerv)
+	fmt.Printf("%v", &stringerv)
+	fmt.Printf("%T", &stringerv)
+	fmt.Printf("%v", notstringerv)
+	fmt.Printf("%T", notstringerv)
+	fmt.Printf("%q", stringerarrayv)
+	fmt.Printf("%v", stringerarrayv)
+	fmt.Printf("%s", stringerarrayv)
+	fmt.Printf("%v", notstringerarrayv)
+	fmt.Printf("%T", notstringerarrayv)
+	fmt.Printf("%d", new(Formatter))
+	fmt.Printf("%*%", 2)               // Ridiculous but allowed.
+	fmt.Printf("%s", interface{}(nil)) // Nothing useful we can say.
+
+	fmt.Printf("%g", 1+2i)
+	// Some bad format/argTypes
+	fmt.Printf("%b", "hi")                     // ERROR "arg .hi. for printf verb %b of wrong type"
+	fmt.Printf("%t", c)                        // ERROR "arg c for printf verb %t of wrong type"
+	fmt.Printf("%t", 1+2i)                     // ERROR "arg 1 \+ 2i for printf verb %t of wrong type"
+	fmt.Printf("%c", 2.3)                      // ERROR "arg 2.3 for printf verb %c of wrong type"
+	fmt.Printf("%d", 2.3)                      // ERROR "arg 2.3 for printf verb %d of wrong type"
+	fmt.Printf("%e", "hi")                     // ERROR "arg .hi. for printf verb %e of wrong type"
+	fmt.Printf("%E", true)                     // ERROR "arg true for printf verb %E of wrong type"
+	fmt.Printf("%f", "hi")                     // ERROR "arg .hi. for printf verb %f of wrong type"
+	fmt.Printf("%F", 'x')                      // ERROR "arg 'x' for printf verb %F of wrong type"
+	fmt.Printf("%g", "hi")                     // ERROR "arg .hi. for printf verb %g of wrong type"
+	fmt.Printf("%g", imap)                     // ERROR "arg imap for printf verb %g of wrong type"
+	fmt.Printf("%G", i)                        // ERROR "arg i for printf verb %G of wrong type"
+	fmt.Printf("%o", x)                        // ERROR "arg x for printf verb %o of wrong type"
+	fmt.Printf("%p", 23)                       // ERROR "arg 23 for printf verb %p of wrong type"
+	fmt.Printf("%q", x)                        // ERROR "arg x for printf verb %q of wrong type"
+	fmt.Printf("%s", b)                        // ERROR "arg b for printf verb %s of wrong type"
+	fmt.Printf("%s", byte(65))                 // ERROR "arg byte\(65\) for printf verb %s of wrong type"
+	fmt.Printf("%t", 23)                       // ERROR "arg 23 for printf verb %t of wrong type"
+	fmt.Printf("%U", x)                        // ERROR "arg x for printf verb %U of wrong type"
+	fmt.Printf("%x", nil)                      // ERROR "arg nil for printf verb %x of wrong type"
+	fmt.Printf("%X", 2.3)                      // ERROR "arg 2.3 for printf verb %X of wrong type"
+	fmt.Printf("%s", stringerv)                // ERROR "arg stringerv for printf verb %s of wrong type"
+	fmt.Printf("%t", stringerv)                // ERROR "arg stringerv for printf verb %t of wrong type"
+	fmt.Printf("%q", notstringerv)             // ERROR "arg notstringerv for printf verb %q of wrong type"
+	fmt.Printf("%t", notstringerv)             // ERROR "arg notstringerv for printf verb %t of wrong type"
+	fmt.Printf("%t", stringerarrayv)           // ERROR "arg stringerarrayv for printf verb %t of wrong type"
+	fmt.Printf("%t", notstringerarrayv)        // ERROR "arg notstringerarrayv for printf verb %t of wrong type"
+	fmt.Printf("%q", notstringerarrayv)        // ERROR "arg notstringerarrayv for printf verb %q of wrong type"
+	fmt.Printf("%d", Formatter(true))          // correct (the type is responsible for formatting)
+	fmt.Printf("%s", nonemptyinterface)        // correct (the dynamic type of nonemptyinterface may be a stringer)
+	fmt.Printf("%.*s %d %g", 3, "hi", 23, 'x') // ERROR "arg 'x' for printf verb %g of wrong type"
+	fmt.Println()                              // not an error
+	fmt.Println("%s", "hi")                    // ERROR "possible formatting directive in Println call"
+	fmt.Printf("%s", "hi", 3)                  // ERROR "wrong number of args for format in Printf call"
+	fmt.Sprintf("%"+("s"), "hi", 3)            // ERROR "wrong number of args for format in Sprintf call"
+	fmt.Printf("%s%%%d", "hi", 3)              // correct
+	fmt.Printf("%08s", "woo")                  // correct
+	fmt.Printf("% 8s", "woo")                  // correct
+	fmt.Printf("%.*d", 3, 3)                   // correct
+	fmt.Printf("%.*d", 3, 3, 3, 3)             // ERROR "wrong number of args for format in Printf call.*4 args"
+	fmt.Printf("%.*d", "hi", 3)                // ERROR "arg .hi. for \* in printf format not of type int"
+	fmt.Printf("%.*d", i, 3)                   // correct
+	fmt.Printf("%.*d", s, 3)                   // ERROR "arg s for \* in printf format not of type int"
+	fmt.Printf("%*%", 0.22)                    // ERROR "arg 0.22 for \* in printf format not of type int"
+	fmt.Printf("%q %q", multi()...)            // ok
+	fmt.Printf("%#q", `blah`)                  // ok
+	printf("now is the time", "buddy")         // ERROR "no formatting directive"
+	Printf("now is the time", "buddy")         // ERROR "no formatting directive"
+	Printf("hi")                               // ok
+	const format = "%s %s\n"
+	Printf(format, "hi", "there")
+	Printf(format, "hi")              // ERROR "missing argument for Printf..%s..: format reads arg 2, have only 1"
+	Printf("%s %d %.3v %q", "str", 4) // ERROR "missing argument for Printf..%.3v..: format reads arg 3, have only 2"
+	f := new(stringer)
+	f.Warn(0, "%s", "hello", 3)  // ERROR "possible formatting directive in Warn call"
+	f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args for format in Warnf call"
+	f.Warnf(0, "%r", "hello")    // ERROR "unrecognized printf verb"
+	f.Warnf(0, "%#s", "hello")   // ERROR "unrecognized printf flag"
+	Printf("d%", 2)              // ERROR "missing verb at end of format string in Printf call"
+	Printf("%d", percentDV)
+	Printf("%d", &percentDV)
+	Printf("%d", notPercentDV)  // ERROR "arg notPercentDV for printf verb %d of wrong type"
+	Printf("%d", &notPercentDV) // ERROR "arg &notPercentDV for printf verb %d of wrong type"
+	Printf("%p", &notPercentDV) // Works regardless: we print it as a pointer.
+	Printf("%s", percentSV)
+	Printf("%s", &percentSV)
+	// Good argument reorderings.
+	Printf("%[1]d", 3)
+	Printf("%[1]*d", 3, 1)
+	Printf("%[2]*[1]d", 1, 3)
+	Printf("%[2]*.[1]*[3]d", 2, 3, 4)
+	fmt.Fprintf(os.Stderr, "%[2]*.[1]*[3]d", 2, 3, 4) // Use Fprintf to make sure we count arguments correctly.
+	// Bad argument reorderings.
+	Printf("%[xd", 3)                    // ERROR "illegal syntax for printf argument index"
+	Printf("%[x]d", 3)                   // ERROR "illegal syntax for printf argument index"
+	Printf("%[3]*s", "hi", 2)            // ERROR "missing argument for Printf.* reads arg 3, have only 2"
+	fmt.Sprintf("%[3]d", 2)              // ERROR "missing argument for Sprintf.* reads arg 3, have only 1"
+	Printf("%[2]*.[1]*[3]d", 2, "hi", 4) // ERROR "arg .hi. for \* in printf format not of type int"
+	// Something that satisfies the error interface.
+	var e error
+	fmt.Println(e.Error()) // ok
+	// Something that looks like an error interface but isn't, such as the (*T).Error method
+	// in the testing package.
+	var et1 errorTest1
+	fmt.Println(et1.Error())        // ERROR "no args in Error call"
+	fmt.Println(et1.Error("hi"))    // ok
+	fmt.Println(et1.Error("%d", 3)) // ERROR "possible formatting directive in Error call"
+	var et2 errorTest2
+	et2.Error()        // ERROR "no args in Error call"
+	et2.Error("hi")    // ok, not an error method.
+	et2.Error("%d", 3) // ERROR "possible formatting directive in Error call"
+	var et3 errorTest3
+	et3.Error() // ok, not an error method.
+	var et4 errorTest4
+	et4.Error() // ok, not an error method.
+	var et5 errorTest5
+	et5.error() // ok, not an error method.
+	// Bug: used to recur forever.
+	Printf("%p %x", recursiveStructV, recursiveStructV.next)
+	Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next)
+	Printf("%p %x", recursiveSliceV, recursiveSliceV)
+	Printf("%p %x", recursiveMapV, recursiveMapV)
+	// Special handling for Log.
+	math.Log(3)  // OK
+	Log(3)       // OK
+	Log("%d", 3) // ERROR "possible formatting directive in Log call"
+	Logf("%d", 3)
+	Logf("%d", "hi") // ERROR "arg .hi. for printf verb %d of wrong type: untyped string"
+
+}
+
+// Printf is used by the test so we must declare it.
+func Printf(format string, args ...interface{}) {
+	panic("don't call - testing only")
+}
+
+// printf is used by the test so we must declare it.
+func printf(format string, args ...interface{}) {
+	panic("don't call - testing only")
+}
+
+// multi is used by the test.
+func multi() []interface{} {
+	panic("don't call - testing only")
+}
+
+type stringer float64
+
+var stringerv stringer
+
+func (*stringer) String() string {
+	return "string"
+}
+
+func (*stringer) Warn(int, ...interface{}) string {
+	return "warn"
+}
+
+func (*stringer) Warnf(int, string, ...interface{}) string {
+	return "warnf"
+}
+
+type notstringer struct {
+	f float64
+}
+
+var notstringerv notstringer
+
+type stringerarray [4]float64
+
+func (stringerarray) String() string {
+	return "string"
+}
+
+var stringerarrayv stringerarray
+
+type notstringerarray [4]float64
+
+var notstringerarrayv notstringerarray
+
+var nonemptyinterface = interface {
+	f()
+}(nil)
+
+// A data type we can print with "%d".
+type percentDStruct struct {
+	a int
+	b []byte
+	c *float64
+}
+
+var percentDV percentDStruct
+
+// A data type we cannot print correctly with "%d".
+type notPercentDStruct struct {
+	a int
+	b []byte
+	c bool
+}
+
+var notPercentDV notPercentDStruct
+
+// A data type we can print with "%s".
+type percentSStruct struct {
+	a string
+	b []byte
+	c stringerarray
+}
+
+var percentSV percentSStruct
+
+type recursiveStringer int
+
+func (s recursiveStringer) String() string {
+	fmt.Sprintf("%d", s)
+	fmt.Sprintf("%#v", s)
+	fmt.Sprintf("%v", s)   // ERROR "arg s for printf causes recursive call to String method"
+	fmt.Sprintf("%v", &s)  // ERROR "arg &s for printf causes recursive call to String method"
+	fmt.Sprintf("%T", s)   // ok; does not recursively call String
+	return fmt.Sprintln(s) // ERROR "arg s for print causes recursive call to String method"
+}
+
+type recursivePtrStringer int
+
+func (p *recursivePtrStringer) String() string {
+	fmt.Sprintf("%v", *p)
+	return fmt.Sprintln(p) // ERROR "arg p for print causes recursive call to String method"
+}
+
+type Formatter bool
+
+func (*Formatter) Format(fmt.State, rune) {
+}
+
+type RecursiveSlice []RecursiveSlice
+
+var recursiveSliceV = &RecursiveSlice{}
+
+type RecursiveMap map[int]RecursiveMap
+
+var recursiveMapV = make(RecursiveMap)
+
+type RecursiveStruct struct {
+	next *RecursiveStruct
+}
+
+var recursiveStructV = &RecursiveStruct{}
+
+type RecursiveStruct1 struct {
+	next *Recursive2Struct
+}
+
+type RecursiveStruct2 struct {
+	next *Recursive1Struct
+}
+
+var recursiveStruct1V = &RecursiveStruct1{}
+
+// Fix for issue 7149: Missing return type on String method caused fault.
+func (int) String() {
+	return ""
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/rangeloop.go b/third_party/go.tools/cmd/vet/testdata/rangeloop.go
new file mode 100644
index 0000000..37b5940
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/rangeloop.go
@@ -0,0 +1,59 @@
+// 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.
+
+// This file contains tests for the rangeloop checker.
+
+package testdata
+
+func RangeLoopTests() {
+	var s []int
+	for i, v := range s {
+		go func() {
+			println(i) // ERROR "range variable i captured by func literal"
+			println(v) // ERROR "range variable v captured by func literal"
+		}()
+	}
+	for i, v := range s {
+		defer func() {
+			println(i) // ERROR "range variable i captured by func literal"
+			println(v) // ERROR "range variable v captured by func literal"
+		}()
+	}
+	for i := range s {
+		go func() {
+			println(i) // ERROR "range variable i captured by func literal"
+		}()
+	}
+	for _, v := range s {
+		go func() {
+			println(v) // ERROR "range variable v captured by func literal"
+		}()
+	}
+	for i, v := range s {
+		go func() {
+			println(i, v)
+		}()
+		println("unfortunately, we don't catch the error above because of this statement")
+	}
+	for i, v := range s {
+		go func(i, v int) {
+			println(i, v)
+		}(i, v)
+	}
+	for i, v := range s {
+		i, v := i, v
+		go func() {
+			println(i, v)
+		}()
+	}
+	// If the key of the range statement is not an identifier
+	// the code should not panic (it used to).
+	var x [2]int
+	var f int
+	for x[0], f = range s {
+		go func() {
+			_ = f // ERROR "range variable f captured by func literal"
+		}()
+	}
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/shadow.go b/third_party/go.tools/cmd/vet/testdata/shadow.go
new file mode 100644
index 0000000..34a6806
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/shadow.go
@@ -0,0 +1,54 @@
+// Copyright 2013 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.
+
+// This file contains tests for the shadowed variable checker.
+// Some of these errors are caught by the compiler (shadowed return parameters for example)
+// but are nonetheless useful tests.
+
+package testdata
+
+import "os"
+
+func ShadowRead(f *os.File, buf []byte) (err error) {
+	var x int
+	if f != nil {
+		err := 3 // OK - different type.
+		_ = err
+	}
+	if f != nil {
+		_, err := f.Read(buf) // ERROR "declaration of err shadows declaration at testdata/shadow.go:13"
+		if err != nil {
+			return err
+		}
+		i := 3 // OK
+		_ = i
+	}
+	if f != nil {
+		var _, err = f.Read(buf) // ERROR "declaration of err shadows declaration at testdata/shadow.go:13"
+		if err != nil {
+			return err
+		}
+	}
+	for i := 0; i < 10; i++ {
+		i := i // OK: obviously intentional idiomatic redeclaration
+		go func() {
+			println(i)
+		}()
+	}
+	var shadowTemp interface{}
+	switch shadowTemp := shadowTemp.(type) { // OK: obviously intentional idiomatic redeclaration
+	case int:
+		println("OK")
+		_ = shadowTemp
+	}
+	if shadowTemp := shadowTemp; true { // OK: obviously intentional idiomatic redeclaration
+		var f *os.File // OK because f is not mentioned later in the function.
+		// The declaration of x is a shadow because x is mentioned below.
+		var x int // ERROR "declaration of x shadows declaration at testdata/shadow.go:14"
+		_, _, _ = x, f, shadowTemp
+	}
+	// Use a couple of variables to trigger shadowing errors.
+	_, _ = err, x
+	return
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/shift.go b/third_party/go.tools/cmd/vet/testdata/shift.go
new file mode 100644
index 0000000..6624f09
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/shift.go
@@ -0,0 +1,78 @@
+// Copyright 2014 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.
+
+// This file contains tests for the suspicious shift checker.
+
+package testdata
+
+func ShiftTest() {
+	var i8 int8
+	_ = i8 << 7
+	_ = (i8 + 1) << 8 // ERROR "\(i8 \+ 1\) too small for shift of 8"
+	_ = i8 << (7 + 1) // ERROR "i8 too small for shift of 8"
+	_ = i8 >> 8       // ERROR "i8 too small for shift of 8"
+	i8 <<= 8          // ERROR "i8 too small for shift of 8"
+	i8 >>= 8          // ERROR "i8 too small for shift of 8"
+	var i16 int16
+	_ = i16 << 15
+	_ = i16 << 16 // ERROR "i16 too small for shift of 16"
+	_ = i16 >> 16 // ERROR "i16 too small for shift of 16"
+	i16 <<= 16    // ERROR "i16 too small for shift of 16"
+	i16 >>= 16    // ERROR "i16 too small for shift of 16"
+	var i32 int32
+	_ = i32 << 31
+	_ = i32 << 32 // ERROR "i32 too small for shift of 32"
+	_ = i32 >> 32 // ERROR "i32 too small for shift of 32"
+	i32 <<= 32    // ERROR "i32 too small for shift of 32"
+	i32 >>= 32    // ERROR "i32 too small for shift of 32"
+	var i64 int64
+	_ = i64 << 63
+	_ = i64 << 64 // ERROR "i64 too small for shift of 64"
+	_ = i64 >> 64 // ERROR "i64 too small for shift of 64"
+	i64 <<= 64    // ERROR "i64 too small for shift of 64"
+	i64 >>= 64    // ERROR "i64 too small for shift of 64"
+	var u8 uint8
+	_ = u8 << 7
+	_ = u8 << 8 // ERROR "u8 too small for shift of 8"
+	_ = u8 >> 8 // ERROR "u8 too small for shift of 8"
+	u8 <<= 8    // ERROR "u8 too small for shift of 8"
+	u8 >>= 8    // ERROR "u8 too small for shift of 8"
+	var u16 uint16
+	_ = u16 << 15
+	_ = u16 << 16 // ERROR "u16 too small for shift of 16"
+	_ = u16 >> 16 // ERROR "u16 too small for shift of 16"
+	u16 <<= 16    // ERROR "u16 too small for shift of 16"
+	u16 >>= 16    // ERROR "u16 too small for shift of 16"
+	var u32 uint32
+	_ = u32 << 31
+	_ = u32 << 32 // ERROR "u32 too small for shift of 32"
+	_ = u32 >> 32 // ERROR "u32 too small for shift of 32"
+	u32 <<= 32    // ERROR "u32 too small for shift of 32"
+	u32 >>= 32    // ERROR "u32 too small for shift of 32"
+	var u64 uint64
+	_ = u64 << 63
+	_ = u64 << 64  // ERROR "u64 too small for shift of 64"
+	_ = u64 >> 64  // ERROR "u64 too small for shift of 64"
+	u64 <<= 64     // ERROR "u64 too small for shift of 64"
+	u64 >>= 64     // ERROR "u64 too small for shift of 64"
+	_ = u64 << u64 // Non-constant shifts should succeed.
+	var i int
+	_ = i << 31
+	_ = i << 32 // ERROR "i might be too small for shift of 32"
+	_ = i >> 32 // ERROR "i might be too small for shift of 32"
+	i <<= 32    // ERROR "i might be too small for shift of 32"
+	i >>= 32    // ERROR "i might be too small for shift of 32"
+	var u uint
+	_ = u << 31
+	_ = u << 32 // ERROR "u might be too small for shift of 32"
+	_ = u >> 32 // ERROR "u might be too small for shift of 32"
+	u <<= 32    // ERROR "u might be too small for shift of 32"
+	u >>= 32    // ERROR "u might be too small for shift of 32"
+	var p uintptr
+	_ = p << 31
+	_ = p << 32 // ERROR "p might be too small for shift of 32"
+	_ = p >> 32 // ERROR "p might be too small for shift of 32"
+	p <<= 32    // ERROR "p might be too small for shift of 32"
+	p >>= 32    // ERROR "p might be too small for shift of 32"
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/structtag.go b/third_party/go.tools/cmd/vet/testdata/structtag.go
new file mode 100644
index 0000000..55462e5
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/structtag.go
@@ -0,0 +1,27 @@
+// Copyright 2010 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.
+
+// This file contains tests for the structtag checker.
+
+// This file contains the test for canonical struct tags.
+
+package testdata
+
+type StructTagTest struct {
+	X int "hello" // ERROR "not compatible with reflect.StructTag.Get"
+}
+
+type UnexportedEncodingTagTest struct {
+	x int `json:"xx"` // ERROR "struct field x has json tag but is not exported"
+	y int `xml:"yy"`  // ERROR "struct field y has xml tag but is not exported"
+	z int
+	A int `json:"aa" xml:"bb"`
+}
+
+type unexp struct{}
+
+type JSONEmbeddedField struct {
+	UnexportedEncodingTagTest `is:"embedded"`
+	unexp                     `is:"embedded,notexported" json:"unexp"` // OK for now, see issue 7363
+}
diff --git a/third_party/go.tools/cmd/vet/testdata/unsafeptr.go b/third_party/go.tools/cmd/vet/testdata/unsafeptr.go
new file mode 100644
index 0000000..8f64030
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/testdata/unsafeptr.go
@@ -0,0 +1,61 @@
+// Copyright 2014 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 testdata
+
+import (
+	"reflect"
+	"unsafe"
+)
+
+func f() {
+	var x unsafe.Pointer
+	var y uintptr
+	x = unsafe.Pointer(y) // ERROR "possible misuse of unsafe.Pointer"
+	y = uintptr(x)
+
+	// only allowed pointer arithmetic is ptr +/- num.
+	// num+ptr is technically okay but still flagged: write ptr+num instead.
+	x = unsafe.Pointer(uintptr(x) + 1)
+	x = unsafe.Pointer(1 + uintptr(x))          // ERROR "possible misuse of unsafe.Pointer"
+	x = unsafe.Pointer(uintptr(x) + uintptr(x)) // ERROR "possible misuse of unsafe.Pointer"
+	x = unsafe.Pointer(uintptr(x) - 1)
+	x = unsafe.Pointer(1 - uintptr(x)) // ERROR "possible misuse of unsafe.Pointer"
+
+	// certain uses of reflect are okay
+	var v reflect.Value
+	x = unsafe.Pointer(v.Pointer())
+	x = unsafe.Pointer(v.UnsafeAddr())
+	var s1 *reflect.StringHeader
+	x = unsafe.Pointer(s1.Data)
+	var s2 *reflect.SliceHeader
+	x = unsafe.Pointer(s2.Data)
+	var s3 reflect.StringHeader
+	x = unsafe.Pointer(s3.Data) // ERROR "possible misuse of unsafe.Pointer"
+	var s4 reflect.SliceHeader
+	x = unsafe.Pointer(s4.Data) // ERROR "possible misuse of unsafe.Pointer"
+
+	// but only in reflect
+	var vv V
+	x = unsafe.Pointer(vv.Pointer())    // ERROR "possible misuse of unsafe.Pointer"
+	x = unsafe.Pointer(vv.UnsafeAddr()) // ERROR "possible misuse of unsafe.Pointer"
+	var ss1 *StringHeader
+	x = unsafe.Pointer(ss1.Data) // ERROR "possible misuse of unsafe.Pointer"
+	var ss2 *SliceHeader
+	x = unsafe.Pointer(ss2.Data) // ERROR "possible misuse of unsafe.Pointer"
+
+}
+
+type V interface {
+	Pointer() uintptr
+	UnsafeAddr() uintptr
+}
+
+type StringHeader struct {
+	Data uintptr
+}
+
+type SliceHeader struct {
+	Data uintptr
+}
diff --git a/third_party/go.tools/cmd/vet/types.go b/third_party/go.tools/cmd/vet/types.go
new file mode 100644
index 0000000..6128199
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/types.go
@@ -0,0 +1,362 @@
+// Copyright 2010 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.
+
+// This file contains the pieces of the tool that use typechecking from the go/types package.
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// imports is the canonical map of imported packages we need for typechecking.
+// It is created during initialization.
+var imports = make(map[string]*types.Package)
+
+var (
+	stringerMethodType = types.New("func() string")
+	errorType          = types.New("error").Underlying().(*types.Interface)
+	stringerType       = types.New("interface{ String() string }").(*types.Interface)
+	formatterType      *types.Interface
+)
+
+func init() {
+	typ := importType("fmt", "Formatter")
+	if typ != nil {
+		formatterType = typ.Underlying().(*types.Interface)
+	}
+}
+
+// importType returns the type denoted by the qualified identifier
+// path.name, and adds the respective package to the imports map
+// as a side effect.
+func importType(path, name string) types.Type {
+	pkg, err := types.DefaultImport(imports, path)
+	if err != nil {
+		warnf("import failed: %v", err)
+		return nil
+	}
+	if obj, ok := pkg.Scope().Lookup(name).(*types.TypeName); ok {
+		return obj.Type()
+	}
+	warnf("invalid type name %q", name)
+	return nil
+}
+
+func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
+	pkg.defs = make(map[*ast.Ident]types.Object)
+	pkg.uses = make(map[*ast.Ident]types.Object)
+	pkg.spans = make(map[types.Object]Span)
+	pkg.types = make(map[ast.Expr]types.TypeAndValue)
+	config := types.Config{
+		// We provide the same packages map for all imports to ensure
+		// that everybody sees identical packages for the given paths.
+		Packages: imports,
+		// By providing a Config with our own error function, it will continue
+		// past the first error. There is no need for that function to do anything.
+		Error: func(error) {},
+	}
+	info := &types.Info{
+		Types: pkg.types,
+		Defs:  pkg.defs,
+		Uses:  pkg.uses,
+	}
+	typesPkg, err := config.Check(pkg.path, fs, astFiles, info)
+	pkg.typesPkg = typesPkg
+	// update spans
+	for id, obj := range pkg.defs {
+		pkg.growSpan(id, obj)
+	}
+	for id, obj := range pkg.uses {
+		pkg.growSpan(id, obj)
+	}
+	return err
+}
+
+// isStruct reports whether the composite literal c is a struct.
+// If it is not (probably a struct), it returns a printable form of the type.
+func (pkg *Package) isStruct(c *ast.CompositeLit) (bool, string) {
+	// Check that the CompositeLit's type is a slice or array (which needs no field keys), if possible.
+	typ := pkg.types[c].Type
+	// If it's a named type, pull out the underlying type. If it's not, the Underlying
+	// method returns the type itself.
+	actual := typ
+	if actual != nil {
+		actual = actual.Underlying()
+	}
+	if actual == nil {
+		// No type information available. Assume true, so we do the check.
+		return true, ""
+	}
+	switch actual.(type) {
+	case *types.Struct:
+		return true, typ.String()
+	default:
+		return false, ""
+	}
+}
+
+// matchArgType reports an error if printf verb t is not appropriate
+// for operand arg.
+//
+// typ is used only for recursive calls; external callers must supply nil.
+//
+// (Recursion arises from the compound types {map,chan,slice} which
+// may be printed with %d etc. if that is appropriate for their element
+// types.)
+func (f *File) matchArgType(t printfArgType, typ types.Type, arg ast.Expr) bool {
+	return f.matchArgTypeInternal(t, typ, arg, make(map[types.Type]bool))
+}
+
+// matchArgTypeInternal is the internal version of matchArgType. It carries a map
+// remembering what types are in progress so we don't recur when faced with recursive
+// types or mutually recursive types.
+func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Expr, inProgress map[types.Type]bool) bool {
+	// %v, %T accept any argument type.
+	if t == anyType {
+		return true
+	}
+	if typ == nil {
+		// external call
+		typ = f.pkg.types[arg].Type
+		if typ == nil {
+			return true // probably a type check problem
+		}
+	}
+	// If the type implements fmt.Formatter, we have nothing to check.
+	// But (see issue 6259) that's not easy to verify, so instead we see
+	// if its method set contains a Format function. We could do better,
+	// even now, but we don't need to be 100% accurate. Wait for 6259 to
+	// be fixed instead. TODO.
+	if f.hasMethod(typ, "Format") {
+		return true
+	}
+	// If we can use a string, might arg (dynamically) implement the Stringer or Error interface?
+	if t&argString != 0 {
+		if types.AssertableTo(errorType, typ) || types.AssertableTo(stringerType, typ) {
+			return true
+		}
+	}
+
+	typ = typ.Underlying()
+	if inProgress[typ] {
+		// We're already looking at this type. The call that started it will take care of it.
+		return true
+	}
+	inProgress[typ] = true
+
+	switch typ := typ.(type) {
+	case *types.Signature:
+		return t&argPointer != 0
+
+	case *types.Map:
+		// Recur: map[int]int matches %d.
+		return t&argPointer != 0 ||
+			(f.matchArgTypeInternal(t, typ.Key(), arg, inProgress) && f.matchArgTypeInternal(t, typ.Elem(), arg, inProgress))
+
+	case *types.Chan:
+		return t&argPointer != 0
+
+	case *types.Array:
+		// Same as slice.
+		if types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && t&argString != 0 {
+			return true // %s matches []byte
+		}
+		// Recur: []int matches %d.
+		return t&argPointer != 0 || f.matchArgTypeInternal(t, typ.Elem().Underlying(), arg, inProgress)
+
+	case *types.Slice:
+		// Same as array.
+		if types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && t&argString != 0 {
+			return true // %s matches []byte
+		}
+		// Recur: []int matches %d. But watch out for
+		//	type T []T
+		// If the element is a pointer type (type T[]*T), it's handled fine by the Pointer case below.
+		return t&argPointer != 0 || f.matchArgTypeInternal(t, typ.Elem(), arg, inProgress)
+
+	case *types.Pointer:
+		// Ugly, but dealing with an edge case: a known pointer to an invalid type,
+		// probably something from a failed import.
+		if typ.Elem().String() == "invalid type" {
+			if *verbose {
+				f.Warnf(arg.Pos(), "printf argument %v is pointer to invalid or unknown type", f.gofmt(arg))
+			}
+			return true // special case
+		}
+		// If it's actually a pointer with %p, it prints as one.
+		if t == argPointer {
+			return true
+		}
+		// If it's pointer to struct, that's equivalent in our analysis to whether we can print the struct.
+		if str, ok := typ.Elem().Underlying().(*types.Struct); ok {
+			return f.matchStructArgType(t, str, arg, inProgress)
+		}
+		// The rest can print with %p as pointers, or as integers with %x etc.
+		return t&(argInt|argPointer) != 0
+
+	case *types.Struct:
+		return f.matchStructArgType(t, typ, arg, inProgress)
+
+	case *types.Interface:
+		// If the static type of the argument is empty interface, there's little we can do.
+		// Example:
+		//	func f(x interface{}) { fmt.Printf("%s", x) }
+		// Whether x is valid for %s depends on the type of the argument to f. One day
+		// we will be able to do better. For now, we assume that empty interface is OK
+		// but non-empty interfaces, with Stringer and Error handled above, are errors.
+		return typ.NumMethods() == 0
+
+	case *types.Basic:
+		switch typ.Kind() {
+		case types.UntypedBool,
+			types.Bool:
+			return t&argBool != 0
+
+		case types.UntypedInt,
+			types.Int,
+			types.Int8,
+			types.Int16,
+			types.Int32,
+			types.Int64,
+			types.Uint,
+			types.Uint8,
+			types.Uint16,
+			types.Uint32,
+			types.Uint64,
+			types.Uintptr:
+			return t&argInt != 0
+
+		case types.UntypedFloat,
+			types.Float32,
+			types.Float64:
+			return t&argFloat != 0
+
+		case types.UntypedComplex,
+			types.Complex64,
+			types.Complex128:
+			return t&argComplex != 0
+
+		case types.UntypedString,
+			types.String:
+			return t&argString != 0
+
+		case types.UnsafePointer:
+			return t&(argPointer|argInt) != 0
+
+		case types.UntypedRune:
+			return t&(argInt|argRune) != 0
+
+		case types.UntypedNil:
+			return t&argPointer != 0 // TODO?
+
+		case types.Invalid:
+			if *verbose {
+				f.Warnf(arg.Pos(), "printf argument %v has invalid or unknown type", f.gofmt(arg))
+			}
+			return true // Probably a type check problem.
+		}
+		panic("unreachable")
+	}
+
+	return false
+}
+
+// hasBasicType reports whether x's type is a types.Basic with the given kind.
+func (f *File) hasBasicType(x ast.Expr, kind types.BasicKind) bool {
+	t := f.pkg.types[x].Type
+	if t != nil {
+		t = t.Underlying()
+	}
+	b, ok := t.(*types.Basic)
+	return ok && b.Kind() == kind
+}
+
+// matchStructArgType reports whether all the elements of the struct match the expected
+// type. For instance, with "%d" all the elements must be printable with the "%d" format.
+func (f *File) matchStructArgType(t printfArgType, typ *types.Struct, arg ast.Expr, inProgress map[types.Type]bool) bool {
+	for i := 0; i < typ.NumFields(); i++ {
+		if !f.matchArgTypeInternal(t, typ.Field(i).Type(), arg, inProgress) {
+			return false
+		}
+	}
+	return true
+}
+
+// numArgsInSignature tells how many formal arguments the function type
+// being called has.
+func (f *File) numArgsInSignature(call *ast.CallExpr) int {
+	// Check the type of the function or method declaration
+	typ := f.pkg.types[call.Fun].Type
+	if typ == nil {
+		return 0
+	}
+	// The type must be a signature, but be sure for safety.
+	sig, ok := typ.(*types.Signature)
+	if !ok {
+		return 0
+	}
+	return sig.Params().Len()
+}
+
+// isErrorMethodCall reports whether the call is of a method with signature
+//	func Error() string
+// where "string" is the universe's string type. We know the method is called "Error".
+func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
+	typ := f.pkg.types[call].Type
+	if typ != nil {
+		// We know it's called "Error", so just check the function signature.
+		return types.Identical(f.pkg.types[call.Fun].Type, stringerMethodType)
+	}
+	// Without types, we can still check by hand.
+	// Is it a selector expression? Otherwise it's a function call, not a method call.
+	sel, ok := call.Fun.(*ast.SelectorExpr)
+	if !ok {
+		return false
+	}
+	// The package is type-checked, so if there are no arguments, we're done.
+	if len(call.Args) > 0 {
+		return false
+	}
+	// Check the type of the method declaration
+	typ = f.pkg.types[sel].Type
+	if typ == nil {
+		return false
+	}
+	// The type must be a signature, but be sure for safety.
+	sig, ok := typ.(*types.Signature)
+	if !ok {
+		return false
+	}
+	// There must be a receiver for it to be a method call. Otherwise it is
+	// a function, not something that satisfies the error interface.
+	if sig.Recv() == nil {
+		return false
+	}
+	// There must be no arguments. Already verified by type checking, but be thorough.
+	if sig.Params().Len() > 0 {
+		return false
+	}
+	// Finally the real questions.
+	// There must be one result.
+	if sig.Results().Len() != 1 {
+		return false
+	}
+	// It must have return type "string" from the universe.
+	return sig.Results().At(0).Type() == types.Typ[types.String]
+}
+
+// hasMethod reports whether the type contains a method with the given name.
+// It is part of the workaround for Formatters and should be deleted when
+// that workaround is no longer necessary.
+// TODO: This could be better once issue 6259 is fixed.
+func (f *File) hasMethod(typ types.Type, name string) bool {
+	// assume we have an addressable variable of type typ
+	obj, _, _ := types.LookupFieldOrMethod(typ, true, f.pkg.typesPkg, name)
+	_, ok := obj.(*types.Func)
+	return ok
+}
diff --git a/third_party/go.tools/cmd/vet/unsafeptr.go b/third_party/go.tools/cmd/vet/unsafeptr.go
new file mode 100644
index 0000000..3e133fe
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/unsafeptr.go
@@ -0,0 +1,98 @@
+// Copyright 2014 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.
+
+// Check for invalid uintptr -> unsafe.Pointer conversions.
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func init() {
+	register("unsafeptr",
+		"check for misuse of unsafe.Pointer",
+		checkUnsafePointer,
+		callExpr)
+}
+
+func checkUnsafePointer(f *File, node ast.Node) {
+	x := node.(*ast.CallExpr)
+	if len(x.Args) != 1 {
+		return
+	}
+	if f.hasBasicType(x.Fun, types.UnsafePointer) && f.hasBasicType(x.Args[0], types.Uintptr) && !f.isSafeUintptr(x.Args[0]) {
+		f.Badf(x.Pos(), "possible misuse of unsafe.Pointer")
+	}
+}
+
+// isSafeUintptr reports whether x - already known to be a uintptr -
+// is safe to convert to unsafe.Pointer. It is safe if x is itself derived
+// directly from an unsafe.Pointer via conversion and pointer arithmetic
+// or if x is the result of reflect.Value.Pointer or reflect.Value.UnsafeAddr
+// or obtained from the Data field of a *reflect.SliceHeader or *reflect.StringHeader.
+func (f *File) isSafeUintptr(x ast.Expr) bool {
+	switch x := x.(type) {
+	case *ast.ParenExpr:
+		return f.isSafeUintptr(x.X)
+
+	case *ast.SelectorExpr:
+		switch x.Sel.Name {
+		case "Data":
+			// reflect.SliceHeader and reflect.StringHeader are okay,
+			// but only if they are pointing at a real slice or string.
+			// It's not okay to do:
+			//	var x SliceHeader
+			//	x.Data = uintptr(unsafe.Pointer(...))
+			//	... use x ...
+			//	p := unsafe.Pointer(x.Data)
+			// because in the middle the garbage collector doesn't
+			// see x.Data as a pointer and so x.Data may be dangling
+			// by the time we get to the conversion at the end.
+			// For now approximate by saying that *Header is okay
+			// but Header is not.
+			pt, ok := f.pkg.types[x.X].Type.(*types.Pointer)
+			if ok {
+				t, ok := pt.Elem().(*types.Named)
+				if ok && t.Obj().Pkg().Path() == "reflect" {
+					switch t.Obj().Name() {
+					case "StringHeader", "SliceHeader":
+						return true
+					}
+				}
+			}
+		}
+
+	case *ast.CallExpr:
+		switch len(x.Args) {
+		case 0:
+			// maybe call to reflect.Value.Pointer or reflect.Value.UnsafeAddr.
+			sel, ok := x.Fun.(*ast.SelectorExpr)
+			if !ok {
+				break
+			}
+			switch sel.Sel.Name {
+			case "Pointer", "UnsafeAddr":
+				t, ok := f.pkg.types[sel.X].Type.(*types.Named)
+				if ok && t.Obj().Pkg().Path() == "reflect" && t.Obj().Name() == "Value" {
+					return true
+				}
+			}
+
+		case 1:
+			// maybe conversion of uintptr to unsafe.Pointer
+			return f.hasBasicType(x.Fun, types.Uintptr) && f.hasBasicType(x.Args[0], types.UnsafePointer)
+		}
+
+	case *ast.BinaryExpr:
+		switch x.Op {
+		case token.ADD, token.SUB:
+			return f.isSafeUintptr(x.X) && !f.isSafeUintptr(x.Y)
+		}
+	}
+	return false
+}
diff --git a/third_party/go.tools/cmd/vet/vet_test.go b/third_party/go.tools/cmd/vet/vet_test.go
new file mode 100644
index 0000000..65fefb9
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/vet_test.go
@@ -0,0 +1,74 @@
+// Copyright 2013 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_test
+
+import (
+	"bytes"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"testing"
+)
+
+const (
+	dataDir = "testdata"
+	binary  = "testvet"
+)
+
+// Run this shell script, but do it in Go so it can be run by "go test".
+// 	go build -o testvet
+// 	$(GOROOT)/test/errchk ./testvet -shadow -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s
+// 	rm testvet
+//
+func TestVet(t *testing.T) {
+	// Plan 9 and Windows systems can't be guaranteed to have Perl and so can't run errchk.
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skip("skipping test; no Perl on %q", runtime.GOOS)
+	}
+
+	// go build
+	cmd := exec.Command("go", "build", "-o", binary)
+	run(cmd, t)
+
+	// defer removal of vet
+	defer os.Remove(binary)
+
+	// errchk ./testvet
+	gos, err := filepath.Glob(filepath.Join(dataDir, "*.go"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	asms, err := filepath.Glob(filepath.Join(dataDir, "*.s"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	files := append(gos, asms...)
+	errchk := filepath.Join(runtime.GOROOT(), "test", "errchk")
+	flags := []string{
+		"./" + binary,
+		"-printfuncs=Warn:1,Warnf:1",
+		"-test", // TODO: Delete once -shadow is part of -all.
+	}
+	cmd = exec.Command(errchk, append(flags, files...)...)
+	if !run(cmd, t) {
+		t.Fatal("vet command failed")
+	}
+}
+
+func run(c *exec.Cmd, t *testing.T) bool {
+	output, err := c.CombinedOutput()
+	os.Stderr.Write(output)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Errchk delights by not returning non-zero status if it finds errors, so we look at the output.
+	// It prints "BUG" if there is a failure.
+	if !c.ProcessState.Success() {
+		return false
+	}
+	return !bytes.Contains(output, []byte("BUG"))
+}
diff --git a/third_party/go.tools/cmd/vet/whitelist/whitelist.go b/third_party/go.tools/cmd/vet/whitelist/whitelist.go
new file mode 100644
index 0000000..975c9e3
--- /dev/null
+++ b/third_party/go.tools/cmd/vet/whitelist/whitelist.go
@@ -0,0 +1,52 @@
+// Copyright 2013 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 whitelist defines exceptions for the vet tool.
+package whitelist
+
+// UnkeyedLiteral are types that are actually slices, but
+// syntactically, we cannot tell whether the Typ in pkg.Typ{1, 2, 3}
+// is a slice or a struct, so we whitelist all the standard package
+// library's exported slice types.
+var UnkeyedLiteral = map[string]bool{
+	/*
+		find $GOROOT/src -type f | grep -v _test.go | xargs grep '^type.*\[\]' | \
+			grep -v ' map\[' | sed 's,/[^/]*go.type,,' | sed 's,.*src/,,' | \
+			sed 's, ,.,' |  sed 's, .*,,' | grep -v '\.[a-z]' | \
+			sort | awk '{ print "\"" $0 "\": true," }'
+	*/
+	"crypto/x509/pkix.RDNSequence":                  true,
+	"crypto/x509/pkix.RelativeDistinguishedNameSET": true,
+	"database/sql.RawBytes":                         true,
+	"debug/macho.LoadBytes":                         true,
+	"encoding/asn1.ObjectIdentifier":                true,
+	"encoding/asn1.RawContent":                      true,
+	"encoding/json.RawMessage":                      true,
+	"encoding/xml.CharData":                         true,
+	"encoding/xml.Comment":                          true,
+	"encoding/xml.Directive":                        true,
+	"go/scanner.ErrorList":                          true,
+	"image/color.Palette":                           true,
+	"net.HardwareAddr":                              true,
+	"net.IP":                                        true,
+	"net.IPMask":                                    true,
+	"sort.Float64Slice":                             true,
+	"sort.IntSlice":                                 true,
+	"sort.StringSlice":                              true,
+	"unicode.SpecialCase":                           true,
+
+	// These image and image/color struct types are frozen. We will never add fields to them.
+	"image/color.Alpha16": true,
+	"image/color.Alpha":   true,
+	"image/color.Gray16":  true,
+	"image/color.Gray":    true,
+	"image/color.NRGBA64": true,
+	"image/color.NRGBA":   true,
+	"image/color.RGBA64":  true,
+	"image/color.RGBA":    true,
+	"image/color.YCbCr":   true,
+	"image.Point":         true,
+	"image.Rectangle":     true,
+	"image.Uniform":       true,
+}
diff --git a/third_party/go.tools/codereview.cfg b/third_party/go.tools/codereview.cfg
new file mode 100644
index 0000000..43dbf3c
--- /dev/null
+++ b/third_party/go.tools/codereview.cfg
@@ -0,0 +1,2 @@
+defaultcc: golang-codereviews@googlegroups.com
+contributors: http://go.googlecode.com/hg/CONTRIBUTORS
diff --git a/third_party/go.tools/container/intsets/sparse.go b/third_party/go.tools/container/intsets/sparse.go
new file mode 100644
index 0000000..0ba7cb2
--- /dev/null
+++ b/third_party/go.tools/container/intsets/sparse.go
@@ -0,0 +1,806 @@
+// Copyright 2014 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 intsets provides Sparse, a compact and fast representation
+// for sparse sets of int values.
+//
+// The time complexity of the operations Len, Insert, Remove and Has
+// is in O(n) but in practice those methods are faster and more
+// space-efficient than equivalent operations on sets based on the Go
+// map type.  The IsEmpty, Min, Max, Clear and TakeMin operations
+// require constant time.
+//
+package intsets
+
+// TODO(adonovan):
+// - Add SymmetricDifference(x, y *Sparse), i.e. x ∆ y.
+// - Add SubsetOf (x∖y=∅) and Intersects (x∩y≠∅) predicates.
+// - Add InsertAll(...int), RemoveAll(...int)
+// - Add 'bool changed' results for {Intersection,Difference}With too.
+//
+// TODO(adonovan): implement Dense, a dense bit vector with a similar API.
+// The space usage would be proportional to Max(), not Len(), and the
+// implementation would be based upon big.Int.
+//
+// TODO(adonovan): experiment with making the root block indirect (nil
+// iff IsEmpty).  This would reduce the memory usage when empty and
+// might simplify the aliasing invariants.
+//
+// TODO(adonovan): opt: make UnionWith and Difference faster.
+// These are the hot-spots for go/pointer.
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// A Sparse is a set of int values.
+// Sparse operations (even queries) are not concurrency-safe.
+//
+// The zero value for Sparse is a valid empty set.
+//
+// Sparse sets must be copied using the Copy method, not by assigning
+// a Sparse value.
+//
+type Sparse struct {
+	// An uninitialized Sparse represents an empty set.
+	// An empty set may also be represented by
+	//  root.next == root.prev == &root.
+	// In a non-empty set, root.next points to the first block and
+	// root.prev to the last.
+	// root.offset and root.bits are unused.
+	root block
+}
+
+type word uintptr
+
+const (
+	_m            = ^word(0)
+	bitsPerWord   = 8 << (_m>>8&1 + _m>>16&1 + _m>>32&1)
+	bitsPerBlock  = 256 // optimal value for go/pointer solver performance
+	wordsPerBlock = bitsPerBlock / bitsPerWord
+)
+
+// Limit values of implementation-specific int type.
+const (
+	MaxInt = int(^uint(0) >> 1)
+	MinInt = -MaxInt - 1
+)
+
+// -- block ------------------------------------------------------------
+
+// A set is represented as a circular doubly-linked list of blocks,
+// each containing an offset and a bit array of fixed size
+// bitsPerBlock; the blocks are ordered by increasing offset.
+//
+// The set contains an element x iff the block whose offset is x - (x
+// mod bitsPerBlock) has the bit (x mod bitsPerBlock) set, where mod
+// is the Euclidean remainder.
+//
+// A block may only be empty transiently.
+//
+type block struct {
+	offset     int                 // offset mod bitsPerBlock == 0
+	bits       [wordsPerBlock]word // contains at least one set bit
+	next, prev *block              // doubly-linked list of blocks
+}
+
+// wordMask returns the word index (in block.bits)
+// and single-bit mask for the block's ith bit.
+func wordMask(i uint) (w uint, mask word) {
+	w = i / bitsPerWord
+	mask = 1 << (i % bitsPerWord)
+	return
+}
+
+// insert sets the block b's ith bit and
+// returns true if it was not already set.
+//
+func (b *block) insert(i uint) bool {
+	w, mask := wordMask(i)
+	if b.bits[w]&mask == 0 {
+		b.bits[w] |= mask
+		return true
+	}
+	return false
+}
+
+// remove clears the block's ith bit and
+// returns true if the bit was previously set.
+// NB: may leave the block empty.
+//
+func (b *block) remove(i uint) bool {
+	w, mask := wordMask(i)
+	if b.bits[w]&mask != 0 {
+		b.bits[w] &^= mask
+		return true
+	}
+	return false
+}
+
+// has reports whether the block's ith bit is set.
+func (b *block) has(i uint) bool {
+	w, mask := wordMask(i)
+	return b.bits[w]&mask != 0
+}
+
+// empty reports whether b.len()==0, but more efficiently.
+func (b *block) empty() bool {
+	for _, w := range b.bits {
+		if w != 0 {
+			return false
+		}
+	}
+	return true
+}
+
+// len returns the number of set bits in block b.
+func (b *block) len() int {
+	var l int
+	for _, w := range b.bits {
+		l += popcount(w)
+	}
+	return l
+}
+
+// max returns the maximum element of the block.
+// The block must not be empty.
+//
+func (b *block) max() int {
+	bi := b.offset + bitsPerBlock
+	// Decrement bi by number of high zeros in last.bits.
+	for i := len(b.bits) - 1; i >= 0; i-- {
+		if w := b.bits[i]; w != 0 {
+			return bi - nlz(w) - 1
+		}
+		bi -= bitsPerWord
+	}
+	panic("BUG: empty block")
+}
+
+// min returns the minimum element of the block,
+// and also removes it if take is set.
+// The block must not be initially empty.
+// NB: may leave the block empty.
+//
+func (b *block) min(take bool) int {
+	for i, w := range b.bits {
+		if w != 0 {
+			tz := ntz(w)
+			if take {
+				b.bits[i] = w &^ (1 << uint(tz))
+			}
+			return b.offset + int(i*bitsPerWord) + tz
+		}
+	}
+	panic("BUG: empty block")
+}
+
+// forEach calls f for each element of block b.
+// f must not mutate b's enclosing Sparse.
+func (b *block) forEach(f func(int)) {
+	for i, w := range b.bits {
+		offset := b.offset + i*bitsPerWord
+		for bi := 0; w != 0 && bi < bitsPerWord; bi++ {
+			if w&1 != 0 {
+				f(offset)
+			}
+			offset++
+			w >>= 1
+		}
+	}
+}
+
+// offsetAndBitIndex returns the offset of the block that would
+// contain x and the bit index of x within that block.
+//
+func offsetAndBitIndex(x int) (int, uint) {
+	mod := x % bitsPerBlock
+	if mod < 0 {
+		// Euclidean (non-negative) remainder
+		mod += bitsPerBlock
+	}
+	return x - mod, uint(mod)
+}
+
+// -- Sparse --------------------------------------------------------------
+
+// start returns the root's next block, which is the root block
+// (if s.IsEmpty()) or the first true block otherwise.
+// start has the side effect of ensuring that s is properly
+// initialized.
+//
+func (s *Sparse) start() *block {
+	root := &s.root
+	if root.next == nil {
+		root.next = root
+		root.prev = root
+	} else if root.next.prev != root {
+		// Copying a Sparse x leads to pernicious corruption: the
+		// new Sparse y shares the old linked list, but iteration
+		// on y will never encounter &y.root so it goes into a
+		// loop.  Fail fast before this occurs.
+		panic("A Sparse has been copied without (*Sparse).Copy()")
+	}
+
+	return root.next
+}
+
+// IsEmpty reports whether the set s is empty.
+func (s *Sparse) IsEmpty() bool {
+	return s.start() == &s.root
+}
+
+// Len returns the number of elements in the set s.
+func (s *Sparse) Len() int {
+	var l int
+	for b := s.start(); b != &s.root; b = b.next {
+		l += b.len()
+	}
+	return l
+}
+
+// Max returns the maximum element of the set s, or MinInt if s is empty.
+func (s *Sparse) Max() int {
+	if s.IsEmpty() {
+		return MinInt
+	}
+	return s.root.prev.max()
+}
+
+// Min returns the minimum element of the set s, or MaxInt if s is empty.
+func (s *Sparse) Min() int {
+	if s.IsEmpty() {
+		return MaxInt
+	}
+	return s.root.next.min(false)
+}
+
+// block returns the block that would contain offset,
+// or nil if s contains no such block.
+//
+func (s *Sparse) block(offset int) *block {
+	b := s.start()
+	for b != &s.root && b.offset <= offset {
+		if b.offset == offset {
+			return b
+		}
+		b = b.next
+	}
+	return nil
+}
+
+// Insert adds x to the set s, and reports whether the set grew.
+func (s *Sparse) Insert(x int) bool {
+	offset, i := offsetAndBitIndex(x)
+	b := s.start()
+	for b != &s.root && b.offset <= offset {
+		if b.offset == offset {
+			return b.insert(i)
+		}
+		b = b.next
+	}
+
+	// Insert new block before b.
+	new := &block{offset: offset}
+	new.next = b
+	new.prev = b.prev
+	new.prev.next = new
+	new.next.prev = new
+	return new.insert(i)
+}
+
+func (s *Sparse) removeBlock(b *block) {
+	b.prev.next = b.next
+	b.next.prev = b.prev
+}
+
+// Remove removes x from the set s, and reports whether the set shrank.
+func (s *Sparse) Remove(x int) bool {
+	offset, i := offsetAndBitIndex(x)
+	if b := s.block(offset); b != nil {
+		if !b.remove(i) {
+			return false
+		}
+		if b.empty() {
+			s.removeBlock(b)
+		}
+		return true
+	}
+	return false
+}
+
+// Clear removes all elements from the set s.
+func (s *Sparse) Clear() {
+	s.root.next = &s.root
+	s.root.prev = &s.root
+}
+
+// If set s is non-empty, TakeMin sets *p to the minimum element of
+// the set s, removes that element from the set and returns true.
+// Otherwise, it returns false and *p is undefined.
+//
+// This method may be used for iteration over a worklist like so:
+//
+// 	var x int
+// 	for worklist.TakeMin(&x) { use(x) }
+//
+func (s *Sparse) TakeMin(p *int) bool {
+	head := s.start()
+	if head == &s.root {
+		return false
+	}
+	*p = head.min(true)
+	if head.empty() {
+		s.removeBlock(head)
+	}
+	return true
+}
+
+// Has reports whether x is an element of the set s.
+func (s *Sparse) Has(x int) bool {
+	offset, i := offsetAndBitIndex(x)
+	if b := s.block(offset); b != nil {
+		return b.has(i)
+	}
+	return false
+}
+
+// forEach applies function f to each element of the set s in order.
+//
+// f must not mutate s.  Consequently, forEach is not safe to expose
+// to clients.  In any case, using "range s.AppendTo()" allows more
+// natural control flow with continue/break/return.
+//
+func (s *Sparse) forEach(f func(int)) {
+	for b := s.start(); b != &s.root; b = b.next {
+		b.forEach(f)
+	}
+}
+
+// Copy sets s to the value of x.
+func (s *Sparse) Copy(x *Sparse) {
+	if s == x {
+		return
+	}
+
+	xb := x.start()
+	sb := s.start()
+	for xb != &x.root {
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		sb.offset = xb.offset
+		sb.bits = xb.bits
+		xb = xb.next
+		sb = sb.next
+	}
+	s.discardTail(sb)
+}
+
+// insertBlockBefore returns a new block, inserting it before next.
+func (s *Sparse) insertBlockBefore(next *block) *block {
+	b := new(block)
+	b.next = next
+	b.prev = next.prev
+	b.prev.next = b
+	next.prev = b
+	return b
+}
+
+// discardTail removes block b and all its successors from s.
+func (s *Sparse) discardTail(b *block) {
+	if b != &s.root {
+		b.prev.next = &s.root
+		s.root.prev = b.prev
+	}
+}
+
+// IntersectionWith sets s to the intersection s ∩ x.
+func (s *Sparse) IntersectionWith(x *Sparse) {
+	if s == x {
+		return
+	}
+
+	xb := x.start()
+	sb := s.start()
+	for xb != &x.root && sb != &s.root {
+		switch {
+		case xb.offset < sb.offset:
+			xb = xb.next
+
+		case xb.offset > sb.offset:
+			sb = sb.next
+			s.removeBlock(sb.prev)
+
+		default:
+			var sum word
+			for i := range sb.bits {
+				r := xb.bits[i] & sb.bits[i]
+				sb.bits[i] = r
+				sum |= r
+			}
+			if sum != 0 {
+				sb = sb.next
+			} else {
+				// sb will be overwritten or removed
+			}
+
+			xb = xb.next
+		}
+	}
+
+	s.discardTail(sb)
+}
+
+// Intersection sets s to the intersection x ∩ y.
+func (s *Sparse) Intersection(x, y *Sparse) {
+	switch {
+	case s == x:
+		s.IntersectionWith(y)
+		return
+	case s == y:
+		s.IntersectionWith(x)
+		return
+	case x == y:
+		s.Copy(x)
+		return
+	}
+
+	xb := x.start()
+	yb := y.start()
+	sb := s.start()
+	for xb != &x.root && yb != &y.root {
+		switch {
+		case xb.offset < yb.offset:
+			xb = xb.next
+			continue
+		case xb.offset > yb.offset:
+			yb = yb.next
+			continue
+		}
+
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		sb.offset = xb.offset
+
+		var sum word
+		for i := range sb.bits {
+			r := xb.bits[i] & yb.bits[i]
+			sb.bits[i] = r
+			sum |= r
+		}
+		if sum != 0 {
+			sb = sb.next
+		} else {
+			// sb will be overwritten or removed
+		}
+
+		xb = xb.next
+		yb = yb.next
+	}
+
+	s.discardTail(sb)
+}
+
+// UnionWith sets s to the union s ∪ x, and reports whether s grew.
+func (s *Sparse) UnionWith(x *Sparse) bool {
+	if s == x {
+		return false
+	}
+
+	var changed bool
+	xb := x.start()
+	sb := s.start()
+	for xb != &x.root {
+		if sb != &s.root && sb.offset == xb.offset {
+			for i := range xb.bits {
+				if sb.bits[i] != xb.bits[i] {
+					sb.bits[i] |= xb.bits[i]
+					changed = true
+				}
+			}
+			xb = xb.next
+		} else if sb == &s.root || sb.offset > xb.offset {
+			sb = s.insertBlockBefore(sb)
+			sb.offset = xb.offset
+			sb.bits = xb.bits
+			changed = true
+
+			xb = xb.next
+		}
+		sb = sb.next
+	}
+	return changed
+}
+
+// Union sets s to the union x ∪ y.
+func (s *Sparse) Union(x, y *Sparse) {
+	switch {
+	case x == y:
+		s.Copy(x)
+		return
+	case s == x:
+		s.UnionWith(y)
+		return
+	case s == y:
+		s.UnionWith(x)
+		return
+	}
+
+	xb := x.start()
+	yb := y.start()
+	sb := s.start()
+	for xb != &x.root || yb != &y.root {
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		switch {
+		case yb == &y.root || (xb != &x.root && xb.offset < yb.offset):
+			sb.offset = xb.offset
+			sb.bits = xb.bits
+			xb = xb.next
+
+		case xb == &x.root || (yb != &y.root && yb.offset < xb.offset):
+			sb.offset = yb.offset
+			sb.bits = yb.bits
+			yb = yb.next
+
+		default:
+			sb.offset = xb.offset
+			for i := range xb.bits {
+				sb.bits[i] = xb.bits[i] | yb.bits[i]
+			}
+			xb = xb.next
+			yb = yb.next
+		}
+		sb = sb.next
+	}
+
+	s.discardTail(sb)
+}
+
+// DifferenceWith sets s to the difference s ∖ x.
+func (s *Sparse) DifferenceWith(x *Sparse) {
+	if s == x {
+		s.Clear()
+		return
+	}
+
+	xb := x.start()
+	sb := s.start()
+	for xb != &x.root && sb != &s.root {
+		switch {
+		case xb.offset > sb.offset:
+			sb = sb.next
+
+		case xb.offset < sb.offset:
+			xb = xb.next
+
+		default:
+			var sum word
+			for i := range sb.bits {
+				r := sb.bits[i] & ^xb.bits[i]
+				sb.bits[i] = r
+				sum |= r
+			}
+			sb = sb.next
+			xb = xb.next
+
+			if sum == 0 {
+				s.removeBlock(sb.prev)
+			}
+		}
+	}
+}
+
+// Difference sets s to the difference x ∖ y.
+func (s *Sparse) Difference(x, y *Sparse) {
+	switch {
+	case x == y:
+		s.Clear()
+		return
+	case s == x:
+		s.DifferenceWith(y)
+		return
+	case s == y:
+		var y2 Sparse
+		y2.Copy(y)
+		s.Difference(x, &y2)
+		return
+	}
+
+	xb := x.start()
+	yb := y.start()
+	sb := s.start()
+	for xb != &x.root && yb != &y.root {
+		if xb.offset > yb.offset {
+			// y has block, x has none
+			yb = yb.next
+			continue
+		}
+
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		sb.offset = xb.offset
+
+		switch {
+		case xb.offset < yb.offset:
+			// x has block, y has none
+			sb.bits = xb.bits
+
+			sb = sb.next
+
+		default:
+			// x and y have corresponding blocks
+			var sum word
+			for i := range sb.bits {
+				r := xb.bits[i] & ^yb.bits[i]
+				sb.bits[i] = r
+				sum |= r
+			}
+			if sum != 0 {
+				sb = sb.next
+			} else {
+				// sb will be overwritten or removed
+			}
+
+			yb = yb.next
+		}
+		xb = xb.next
+	}
+
+	for xb != &x.root {
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		sb.offset = xb.offset
+		sb.bits = xb.bits
+		sb = sb.next
+
+		xb = xb.next
+	}
+
+	s.discardTail(sb)
+}
+
+// Equals reports whether the sets s and t have the same elements.
+func (s *Sparse) Equals(t *Sparse) bool {
+	if s == t {
+		return true
+	}
+	sb := s.start()
+	tb := t.start()
+	for {
+		switch {
+		case sb == &s.root && tb == &t.root:
+			return true
+		case sb == &s.root || tb == &t.root:
+			return false
+		case sb.offset != tb.offset:
+			return false
+		case sb.bits != tb.bits:
+			return false
+		}
+
+		sb = sb.next
+		tb = tb.next
+	}
+}
+
+// String returns a human-readable description of the set s.
+func (s *Sparse) String() string {
+	var buf bytes.Buffer
+	buf.WriteByte('{')
+	s.forEach(func(x int) {
+		if buf.Len() > 1 {
+			buf.WriteByte(' ')
+		}
+		fmt.Fprintf(&buf, "%d", x)
+	})
+	buf.WriteByte('}')
+	return buf.String()
+}
+
+// BitString returns the set as a string of 1s and 0s denoting the sum
+// of the i'th powers of 2, for each i in s.  A radix point, always
+// preceded by a digit, appears if the sum is non-integral.
+//
+// Examples:
+//              {}.BitString() =      "0"
+//           {4,5}.BitString() = "110000"
+//            {-3}.BitString() =      "0.001"
+//      {-3,0,4,5}.BitString() = "110001.001"
+//
+func (s *Sparse) BitString() string {
+	if s.IsEmpty() {
+		return "0"
+	}
+
+	min, max := s.Min(), s.Max()
+	var nbytes int
+	if max > 0 {
+		nbytes = max
+	}
+	nbytes++ // zero bit
+	radix := nbytes
+	if min < 0 {
+		nbytes += len(".") - min
+	}
+
+	b := make([]byte, nbytes)
+	for i := range b {
+		b[i] = '0'
+	}
+	if radix < nbytes {
+		b[radix] = '.'
+	}
+	s.forEach(func(x int) {
+		if x >= 0 {
+			x += len(".")
+		}
+		b[radix-x] = '1'
+	})
+	return string(b)
+}
+
+// GoString returns a string showing the internal representation of
+// the set s.
+//
+func (s *Sparse) GoString() string {
+	var buf bytes.Buffer
+	for b := s.start(); b != &s.root; b = b.next {
+		fmt.Fprintf(&buf, "block %p {offset=%d next=%p prev=%p",
+			b, b.offset, b.next, b.prev)
+		for _, w := range b.bits {
+			fmt.Fprintf(&buf, " 0%016x", w)
+		}
+		fmt.Fprintf(&buf, "}\n")
+	}
+	return buf.String()
+}
+
+// AppendTo returns the result of appending the elements of s to slice
+// in order.
+func (s *Sparse) AppendTo(slice []int) []int {
+	s.forEach(func(x int) {
+		slice = append(slice, x)
+	})
+	return slice
+}
+
+// -- Testing/debugging ------------------------------------------------
+
+// check returns an error if the representation invariants of s are violated.
+func (s *Sparse) check() error {
+	if !s.root.empty() {
+		return fmt.Errorf("non-empty root block")
+	}
+	if s.root.offset != 0 {
+		return fmt.Errorf("root block has non-zero offset %d", s.root.offset)
+	}
+	for b := s.start(); b != &s.root; b = b.next {
+		if b.offset%bitsPerBlock != 0 {
+			return fmt.Errorf("bad offset modulo: %d", b.offset)
+		}
+		if b.empty() {
+			return fmt.Errorf("empty block")
+		}
+		if b.prev.next != b {
+			return fmt.Errorf("bad prev.next link")
+		}
+		if b.next.prev != b {
+			return fmt.Errorf("bad next.prev link")
+		}
+		if b.prev != &s.root {
+			if b.offset <= b.prev.offset {
+				return fmt.Errorf("bad offset order: b.offset=%d, prev.offset=%d",
+					b.offset, b.prev.offset)
+			}
+		}
+	}
+	return nil
+}
diff --git a/third_party/go.tools/container/intsets/sparse_test.go b/third_party/go.tools/container/intsets/sparse_test.go
new file mode 100644
index 0000000..da915ff
--- /dev/null
+++ b/third_party/go.tools/container/intsets/sparse_test.go
@@ -0,0 +1,521 @@
+// Copyright 2014 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 intsets_test
+
+import (
+	"fmt"
+	"log"
+	"math/rand"
+	"sort"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/container/intsets"
+)
+
+func TestBasics(t *testing.T) {
+	var s intsets.Sparse
+	if len := s.Len(); len != 0 {
+		t.Errorf("Len({}): got %d, want 0", len)
+	}
+	if s := s.String(); s != "{}" {
+		t.Errorf("String({}): got %q, want \"{}\"", s)
+	}
+	if s.Has(3) {
+		t.Errorf("Has(3): got true, want false")
+	}
+	if err := s.Check(); err != nil {
+		t.Error(err)
+	}
+
+	if !s.Insert(3) {
+		t.Errorf("Insert(3): got false, want true")
+	}
+	if max := s.Max(); max != 3 {
+		t.Errorf("Max: got %d, want 3", max)
+	}
+
+	if !s.Insert(435) {
+		t.Errorf("Insert(435): got false, want true")
+	}
+	if s := s.String(); s != "{3 435}" {
+		t.Errorf("String({3 435}): got %q, want \"{3 435}\"", s)
+	}
+	if max := s.Max(); max != 435 {
+		t.Errorf("Max: got %d, want 435", max)
+	}
+	if len := s.Len(); len != 2 {
+		t.Errorf("Len: got %d, want 2", len)
+	}
+
+	if !s.Remove(435) {
+		t.Errorf("Remove(435): got false, want true")
+	}
+	if s := s.String(); s != "{3}" {
+		t.Errorf("String({3}): got %q, want \"{3}\"", s)
+	}
+}
+
+// Insert, Len, IsEmpty, Hash, Clear, AppendTo.
+func TestMoreBasics(t *testing.T) {
+	var set intsets.Sparse
+	set.Insert(456)
+	set.Insert(123)
+	set.Insert(789)
+	if set.Len() != 3 {
+		t.Errorf("%s.Len: got %d, want 3", set, set.Len())
+	}
+	if set.IsEmpty() {
+		t.Errorf("%s.IsEmpty: got true", set)
+	}
+	if !set.Has(123) {
+		t.Errorf("%s.Has(123): got false", set)
+	}
+	if set.Has(1234) {
+		t.Errorf("%s.Has(1234): got true", set)
+	}
+	got := set.AppendTo([]int{-1})
+	if want := []int{-1, 123, 456, 789}; fmt.Sprint(got) != fmt.Sprint(want) {
+		t.Errorf("%s.AppendTo: got %v, want %v", got, want)
+	}
+
+	set.Clear()
+
+	if set.Len() != 0 {
+		t.Errorf("Clear: got %d, want 0", set.Len())
+	}
+	if !set.IsEmpty() {
+		t.Errorf("IsEmpty: got false")
+	}
+	if set.Has(123) {
+		t.Errorf("%s.Has: got false", set)
+	}
+}
+
+func TestTakeMin(t *testing.T) {
+	var set intsets.Sparse
+	set.Insert(456)
+	set.Insert(123)
+	set.Insert(789)
+	set.Insert(-123)
+	var got int
+	for i, want := range []int{-123, 123, 456, 789} {
+		if !set.TakeMin(&got) || got != want {
+			t.Errorf("TakeMin #%d: got %d, want %d", i, got, want)
+		}
+	}
+	if set.TakeMin(&got) {
+		t.Errorf("%s.TakeMin returned true", set, got)
+	}
+	if err := set.Check(); err != nil {
+		t.Fatalf("check: %s: %#v", err, &set)
+	}
+}
+
+func TestMinAndMax(t *testing.T) {
+	values := []int{0, 456, 123, 789, -123} // elt 0 => empty set
+	wantMax := []int{intsets.MinInt, 456, 456, 789, 789}
+	wantMin := []int{intsets.MaxInt, 456, 123, 123, -123}
+
+	var set intsets.Sparse
+	for i, x := range values {
+		if i != 0 {
+			set.Insert(x)
+		}
+		if got, want := set.Min(), wantMin[i]; got != want {
+			t.Errorf("Min #%d: got %d, want %d", i, got, want)
+		}
+		if got, want := set.Max(), wantMax[i]; got != want {
+			t.Errorf("Max #%d: got %d, want %d", i, got, want)
+		}
+	}
+
+	set.Insert(intsets.MinInt)
+	if got, want := set.Min(), intsets.MinInt; got != want {
+		t.Errorf("Min: got %d, want %d", got, want)
+	}
+
+	set.Insert(intsets.MaxInt)
+	if got, want := set.Max(), intsets.MaxInt; got != want {
+		t.Errorf("Max: got %d, want %d", got, want)
+	}
+}
+
+func TestEquals(t *testing.T) {
+	var setX intsets.Sparse
+	setX.Insert(456)
+	setX.Insert(123)
+	setX.Insert(789)
+
+	if !setX.Equals(&setX) {
+		t.Errorf("Equals(%s, %s): got false", &setX, &setX)
+	}
+
+	var setY intsets.Sparse
+	setY.Insert(789)
+	setY.Insert(456)
+	setY.Insert(123)
+
+	if !setX.Equals(&setY) {
+		t.Errorf("Equals(%s, %s): got false", &setX, &setY)
+	}
+
+	setY.Insert(1)
+	if setX.Equals(&setY) {
+		t.Errorf("Equals(%s, %s): got true", &setX, &setY)
+	}
+
+	var empty intsets.Sparse
+	if setX.Equals(&empty) {
+		t.Errorf("Equals(%s, %s): got true", &setX, &empty)
+	}
+
+	// Edge case: some block (with offset=0) appears in X but not Y.
+	setY.Remove(123)
+	if setX.Equals(&setY) {
+		t.Errorf("Equals(%s, %s): got true", &setX, &setY)
+	}
+}
+
+// A pset is a parallel implementation of a set using both an intsets.Sparse
+// and a built-in hash map.
+type pset struct {
+	hash map[int]bool
+	bits intsets.Sparse
+}
+
+func makePset() *pset {
+	return &pset{hash: make(map[int]bool)}
+}
+
+func (set *pset) add(n int) {
+	prev := len(set.hash)
+	set.hash[n] = true
+	grewA := len(set.hash) > prev
+
+	grewB := set.bits.Insert(n)
+
+	if grewA != grewB {
+		panic(fmt.Sprintf("add(%d): grewA=%t grewB=%t", n, grewA, grewB))
+	}
+}
+
+func (set *pset) remove(n int) {
+	prev := len(set.hash)
+	delete(set.hash, n)
+	shrankA := len(set.hash) < prev
+
+	shrankB := set.bits.Remove(n)
+
+	if shrankA != shrankB {
+		panic(fmt.Sprintf("remove(%d): shrankA=%t shrankB=%t", n, shrankA, shrankB))
+	}
+}
+
+func (set *pset) check(t *testing.T, msg string) {
+	var eltsA []int
+	for elt := range set.hash {
+		eltsA = append(eltsA, int(elt))
+	}
+	sort.Ints(eltsA)
+
+	eltsB := set.bits.AppendTo(nil)
+
+	if a, b := fmt.Sprint(eltsA), fmt.Sprint(eltsB); a != b {
+		t.Errorf("check(%s): hash=%s bits=%s (%s)", msg, a, b, &set.bits)
+	}
+
+	if err := set.bits.Check(); err != nil {
+		t.Fatalf("Check(%s): %s: %#v", msg, err, &set.bits)
+	}
+}
+
+// randomPset returns a parallel set of random size and elements.
+func randomPset(prng *rand.Rand, maxSize int) *pset {
+	set := makePset()
+	size := int(prng.Int()) % maxSize
+	for i := 0; i < size; i++ {
+		// TODO(adonovan): benchmark how performance varies
+		// with this sparsity parameter.
+		n := int(prng.Int()) % 10000
+		set.add(n)
+	}
+	return set
+}
+
+// TestRandomMutations performs the same random adds/removes on two
+// set implementations and ensures that they compute the same result.
+func TestRandomMutations(t *testing.T) {
+	const debug = false
+
+	set := makePset()
+	prng := rand.New(rand.NewSource(0))
+	for i := 0; i < 10000; i++ {
+		n := int(prng.Int())%2000 - 1000
+		if i%2 == 0 {
+			if debug {
+				log.Printf("add %d", n)
+			}
+			set.add(n)
+		} else {
+			if debug {
+				log.Printf("remove %d", n)
+			}
+			set.remove(n)
+		}
+		if debug {
+			set.check(t, "post mutation")
+		}
+	}
+	set.check(t, "final")
+	if debug {
+		log.Print(&set.bits)
+	}
+}
+
+// TestSetOperations exercises classic set operations: ∩ , ∪, \.
+func TestSetOperations(t *testing.T) {
+	prng := rand.New(rand.NewSource(0))
+
+	// Use random sets of sizes from 0 to about 1000.
+	// For each operator, we test variations such as
+	// Z.op(X, Y), Z.op(X, Z) and Z.op(Z, Y) to exercise
+	// the degenerate cases of each method implementation.
+	for i := uint(0); i < 12; i++ {
+		X := randomPset(prng, 1<<i)
+		Y := randomPset(prng, 1<<i)
+
+		// TODO(adonovan): minimise dependencies between stanzas below.
+
+		// Copy(X)
+		C := makePset()
+		C.bits.Copy(&Y.bits) // no effect on result
+		C.bits.Copy(&X.bits)
+		C.hash = X.hash
+		C.check(t, "C.Copy(X)")
+		C.bits.Copy(&C.bits)
+		C.check(t, "C.Copy(C)")
+
+		// U.Union(X, Y)
+		U := makePset()
+		U.bits.Union(&X.bits, &Y.bits)
+		for n := range X.hash {
+			U.hash[n] = true
+		}
+		for n := range Y.hash {
+			U.hash[n] = true
+		}
+		U.check(t, "U.Union(X, Y)")
+
+		// U.Union(X, X)
+		U.bits.Union(&X.bits, &X.bits)
+		U.hash = X.hash
+		U.check(t, "U.Union(X, X)")
+
+		// U.Union(U, Y)
+		U = makePset()
+		U.bits.Copy(&X.bits)
+		U.bits.Union(&U.bits, &Y.bits)
+		for n := range X.hash {
+			U.hash[n] = true
+		}
+		for n := range Y.hash {
+			U.hash[n] = true
+		}
+		U.check(t, "U.Union(U, Y)")
+
+		// U.Union(X, U)
+		U.bits.Copy(&Y.bits)
+		U.bits.Union(&X.bits, &U.bits)
+		U.check(t, "U.Union(X, U)")
+
+		// U.UnionWith(U)
+		U.bits.UnionWith(&U.bits)
+		U.check(t, "U.UnionWith(U)")
+
+		// I.Intersection(X, Y)
+		I := makePset()
+		I.bits.Intersection(&X.bits, &Y.bits)
+		for n := range X.hash {
+			if Y.hash[n] {
+				I.hash[n] = true
+			}
+		}
+		I.check(t, "I.Intersection(X, Y)")
+
+		// I.Intersection(X, X)
+		I.bits.Intersection(&X.bits, &X.bits)
+		I.hash = X.hash
+		I.check(t, "I.Intersection(X, X)")
+
+		// I.Intersection(I, X)
+		I.bits.Intersection(&I.bits, &X.bits)
+		I.check(t, "I.Intersection(I, X)")
+
+		// I.Intersection(X, I)
+		I.bits.Intersection(&X.bits, &I.bits)
+		I.check(t, "I.Intersection(X, I)")
+
+		// I.Intersection(I, I)
+		I.bits.Intersection(&I.bits, &I.bits)
+		I.check(t, "I.Intersection(I, I)")
+
+		// D.Difference(X, Y)
+		D := makePset()
+		D.bits.Difference(&X.bits, &Y.bits)
+		for n := range X.hash {
+			if !Y.hash[n] {
+				D.hash[n] = true
+			}
+		}
+		D.check(t, "D.Difference(X, Y)")
+
+		// D.Difference(D, Y)
+		D.bits.Copy(&X.bits)
+		D.bits.Difference(&D.bits, &Y.bits)
+		D.check(t, "D.Difference(D, Y)")
+
+		// D.Difference(Y, D)
+		D.bits.Copy(&X.bits)
+		D.bits.Difference(&Y.bits, &D.bits)
+		D.hash = make(map[int]bool)
+		for n := range Y.hash {
+			if !X.hash[n] {
+				D.hash[n] = true
+			}
+		}
+		D.check(t, "D.Difference(Y, D)")
+
+		// D.Difference(X, X)
+		D.bits.Difference(&X.bits, &X.bits)
+		D.hash = nil
+		D.check(t, "D.Difference(X, X)")
+
+		// D.DifferenceWith(D)
+		D.bits.Copy(&X.bits)
+		D.bits.DifferenceWith(&D.bits)
+		D.check(t, "D.DifferenceWith(D)")
+	}
+}
+
+func TestIntersectionWith(t *testing.T) {
+	// Edge cases: the pairs (1,1), (1000,2000), (8000,4000)
+	// exercise the <, >, == cases in IntersectionWith that the
+	// TestSetOperations data is too dense to cover.
+	var X, Y intsets.Sparse
+	X.Insert(1)
+	X.Insert(1000)
+	X.Insert(8000)
+	Y.Insert(1)
+	Y.Insert(2000)
+	Y.Insert(4000)
+	X.IntersectionWith(&Y)
+	if got, want := X.String(), "{1}"; got != want {
+		t.Errorf("IntersectionWith: got %s, want %s", got, want)
+	}
+}
+
+func TestBitString(t *testing.T) {
+	for _, test := range []struct {
+		input []int
+		want  string
+	}{
+		{nil, "0"},
+		{[]int{0}, "1"},
+		{[]int{0, 4, 5}, "110001"},
+		{[]int{0, 7, 177}, "1" + strings.Repeat("0", 169) + "10000001"},
+		{[]int{-3, 0, 4, 5}, "110001.001"},
+		{[]int{-3}, "0.001"},
+	} {
+		var set intsets.Sparse
+		for _, x := range test.input {
+			set.Insert(x)
+		}
+		if got := set.BitString(); got != test.want {
+			t.Errorf("BitString(%s) = %s, want %s", set.String(), got, test.want)
+		}
+	}
+}
+
+func TestFailFastOnShallowCopy(t *testing.T) {
+	var x intsets.Sparse
+	x.Insert(1)
+
+	y := x // shallow copy (breaks representation invariants)
+	defer func() {
+		got := fmt.Sprint(recover())
+		want := "A Sparse has been copied without (*Sparse).Copy()"
+		if got != want {
+			t.Errorf("shallow copy: recover() = %q, want %q", got, want)
+		}
+	}()
+	y.String() // panics
+	t.Error("didn't panic as expected")
+}
+
+// -- Benchmarks -------------------------------------------------------
+
+// TODO(adonovan):
+// - Add benchmarks of each method.
+// - Gather set distributions from pointer analysis.
+// - Measure memory usage.
+
+func BenchmarkSparseBitVector(b *testing.B) {
+	prng := rand.New(rand.NewSource(0))
+	for tries := 0; tries < b.N; tries++ {
+		var x, y, z intsets.Sparse
+		for i := 0; i < 1000; i++ {
+			n := int(prng.Int()) % 100000
+			if i%2 == 0 {
+				x.Insert(n)
+			} else {
+				y.Insert(n)
+			}
+		}
+		z.Union(&x, &y)
+		z.Difference(&x, &y)
+	}
+}
+
+func BenchmarkHashTable(b *testing.B) {
+	prng := rand.New(rand.NewSource(0))
+	for tries := 0; tries < b.N; tries++ {
+		x, y, z := make(map[int]bool), make(map[int]bool), make(map[int]bool)
+		for i := 0; i < 1000; i++ {
+			n := int(prng.Int()) % 100000
+			if i%2 == 0 {
+				x[n] = true
+			} else {
+				y[n] = true
+			}
+		}
+		// union
+		for n := range x {
+			z[n] = true
+		}
+		for n := range y {
+			z[n] = true
+		}
+		// difference
+		z = make(map[int]bool)
+		for n := range y {
+			if !x[n] {
+				z[n] = true
+			}
+		}
+	}
+}
+
+func BenchmarkAppendTo(b *testing.B) {
+	prng := rand.New(rand.NewSource(0))
+	var x intsets.Sparse
+	for i := 0; i < 1000; i++ {
+		x.Insert(int(prng.Int()) % 10000)
+	}
+	var space [1000]int
+	for tries := 0; tries < b.N; tries++ {
+		x.AppendTo(space[:0])
+	}
+}
diff --git a/third_party/go.tools/container/intsets/util.go b/third_party/go.tools/container/intsets/util.go
new file mode 100644
index 0000000..76e682c
--- /dev/null
+++ b/third_party/go.tools/container/intsets/util.go
@@ -0,0 +1,75 @@
+// Copyright 2013 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 intsets
+
+var a [1 << 8]byte
+
+func init() {
+	for i := range a {
+		var n byte
+		for x := i; x != 0; x >>= 1 {
+			if x&1 != 0 {
+				n++
+			}
+		}
+		a[i] = n
+	}
+}
+
+// popcount returns the population count (number of set bits) of x.
+func popcount(x word) int {
+	return int(a[byte(x>>(0*8))] +
+		a[byte(x>>(1*8))] +
+		a[byte(x>>(2*8))] +
+		a[byte(x>>(3*8))] +
+		a[byte(x>>(4*8))] +
+		a[byte(x>>(5*8))] +
+		a[byte(x>>(6*8))] +
+		a[byte(x>>(7*8))])
+}
+
+// nlz returns the number of leading zeros of x.
+// From Hacker's Delight, fig 5.11.
+func nlz(x word) int {
+	x |= (x >> 1)
+	x |= (x >> 2)
+	x |= (x >> 4)
+	x |= (x >> 8)
+	x |= (x >> 16)
+	x |= (x >> 32)
+	return popcount(^x)
+}
+
+// ntz returns the number of trailing zeros of x.
+// From Hacker's Delight, fig 5.13.
+func ntz(x word) int {
+	if x == 0 {
+		return bitsPerWord
+	}
+	n := 1
+	if bitsPerWord == 64 {
+		if (x & 0xffffffff) == 0 {
+			n = n + 32
+			x = x >> 32
+		}
+	}
+	if (x & 0x0000ffff) == 0 {
+		n = n + 16
+		x = x >> 16
+	}
+	if (x & 0x000000ff) == 0 {
+		n = n + 8
+		x = x >> 8
+	}
+	if (x & 0x0000000f) == 0 {
+		n = n + 4
+		x = x >> 4
+	}
+	if (x & 0x00000003) == 0 {
+		n = n + 2
+		x = x >> 2
+	}
+	return n - int(x&1)
+}
diff --git a/third_party/go.tools/container/intsets/util_test.go b/third_party/go.tools/container/intsets/util_test.go
new file mode 100644
index 0000000..92a4bc5
--- /dev/null
+++ b/third_party/go.tools/container/intsets/util_test.go
@@ -0,0 +1,25 @@
+// Copyright 2014 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 intsets
+
+import "testing"
+
+func TestNLZ(t *testing.T) {
+	// Test the platform-specific edge case.
+	// NB: v must be a var (not const) so that the word() conversion is dynamic.
+	// Otherwise the compiler will report an error.
+	v := uint64(0x0000801000000000)
+	n := nlz(word(v))
+	want := 32 // (on 32-bit)
+	if bitsPerWord == 64 {
+		want = 16
+	}
+	if n != want {
+		t.Errorf("%d-bit nlz(%d) = %d, want %d", bitsPerWord, v, n, want)
+	}
+}
+
+// Backdoor for testing.
+func (s *Sparse) Check() error { return s.check() }
diff --git a/third_party/go.tools/cover/profile.go b/third_party/go.tools/cover/profile.go
new file mode 100644
index 0000000..1cbd739
--- /dev/null
+++ b/third_party/go.tools/cover/profile.go
@@ -0,0 +1,190 @@
+// Copyright 2013 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 cover provides support for parsing coverage profiles
+// generated by "go test -coverprofile=cover.out".
+package cover
+
+import (
+	"bufio"
+	"fmt"
+	"math"
+	"os"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+// Profile represents the profiling data for a specific file.
+type Profile struct {
+	FileName string
+	Mode     string
+	Blocks   []ProfileBlock
+}
+
+// ProfileBlock represents a single block of profiling data.
+type ProfileBlock struct {
+	StartLine, StartCol int
+	EndLine, EndCol     int
+	NumStmt, Count      int
+}
+
+type byFileName []*Profile
+
+func (p byFileName) Len() int           { return len(p) }
+func (p byFileName) Less(i, j int) bool { return p[i].FileName < p[j].FileName }
+func (p byFileName) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// ParseProfiles parses profile data in the specified file and returns a
+// Profile for each source file described therein.
+func ParseProfiles(fileName string) ([]*Profile, error) {
+	pf, err := os.Open(fileName)
+	if err != nil {
+		return nil, err
+	}
+	defer pf.Close()
+
+	files := make(map[string]*Profile)
+	buf := bufio.NewReader(pf)
+	// First line is "mode: foo", where foo is "set", "count", or "atomic".
+	// Rest of file is in the format
+	//	encoding/base64/base64.go:34.44,37.40 3 1
+	// where the fields are: name.go:line.column,line.column numberOfStatements count
+	s := bufio.NewScanner(buf)
+	mode := ""
+	for s.Scan() {
+		line := s.Text()
+		if mode == "" {
+			const p = "mode: "
+			if !strings.HasPrefix(line, p) || line == p {
+				return nil, fmt.Errorf("bad mode line: %v", line)
+			}
+			mode = line[len(p):]
+			continue
+		}
+		m := lineRe.FindStringSubmatch(line)
+		if m == nil {
+			return nil, fmt.Errorf("line %q doesn't match expected format: %v", m, lineRe)
+		}
+		fn := m[1]
+		p := files[fn]
+		if p == nil {
+			p = &Profile{
+				FileName: fn,
+				Mode:     mode,
+			}
+			files[fn] = p
+		}
+		p.Blocks = append(p.Blocks, ProfileBlock{
+			StartLine: toInt(m[2]),
+			StartCol:  toInt(m[3]),
+			EndLine:   toInt(m[4]),
+			EndCol:    toInt(m[5]),
+			NumStmt:   toInt(m[6]),
+			Count:     toInt(m[7]),
+		})
+	}
+	if err := s.Err(); err != nil {
+		return nil, err
+	}
+	for _, p := range files {
+		sort.Sort(blocksByStart(p.Blocks))
+	}
+	// Generate a sorted slice.
+	profiles := make([]*Profile, 0, len(files))
+	for _, profile := range files {
+		profiles = append(profiles, profile)
+	}
+	sort.Sort(byFileName(profiles))
+	return profiles, nil
+}
+
+type blocksByStart []ProfileBlock
+
+func (b blocksByStart) Len() int      { return len(b) }
+func (b blocksByStart) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b blocksByStart) Less(i, j int) bool {
+	bi, bj := b[i], b[j]
+	return bi.StartLine < bj.StartLine || bi.StartLine == bj.StartLine && bi.StartCol < bj.StartCol
+}
+
+var lineRe = regexp.MustCompile(`^(.+):([0-9]+).([0-9]+),([0-9]+).([0-9]+) ([0-9]+) ([0-9]+)$`)
+
+func toInt(s string) int {
+	i, err := strconv.Atoi(s)
+	if err != nil {
+		panic(err)
+	}
+	return i
+}
+
+// Boundary represents the position in a source file of the beginning or end of a
+// block as reported by the coverage profile. In HTML mode, it will correspond to
+// the opening or closing of a <span> tag and will be used to colorize the source
+type Boundary struct {
+	Offset int     // Location as a byte offset in the source file.
+	Start  bool    // Is this the start of a block?
+	Count  int     // Event count from the cover profile.
+	Norm   float64 // Count normalized to [0..1].
+}
+
+// Boundaries returns a Profile as a set of Boundary objects within the provided src.
+func (p *Profile) Boundaries(src []byte) (boundaries []Boundary) {
+	// Find maximum count.
+	max := 0
+	for _, b := range p.Blocks {
+		if b.Count > max {
+			max = b.Count
+		}
+	}
+	// Divisor for normalization.
+	divisor := math.Log(float64(max))
+
+	// boundary returns a Boundary, populating the Norm field with a normalized Count.
+	boundary := func(offset int, start bool, count int) Boundary {
+		b := Boundary{Offset: offset, Start: start, Count: count}
+		if !start || count == 0 {
+			return b
+		}
+		if max <= 1 {
+			b.Norm = 0.8 // Profile is in"set" mode; we want a heat map. Use cov8 in the CSS.
+		} else if count > 0 {
+			b.Norm = math.Log(float64(count)) / divisor
+		}
+		return b
+	}
+
+	line, col := 1, 2 // TODO: Why is this 2?
+	for si, bi := 0, 0; si < len(src) && bi < len(p.Blocks); {
+		b := p.Blocks[bi]
+		if b.StartLine == line && b.StartCol == col {
+			boundaries = append(boundaries, boundary(si, true, b.Count))
+		}
+		if b.EndLine == line && b.EndCol == col {
+			boundaries = append(boundaries, boundary(si, false, 0))
+			bi++
+			continue // Don't advance through src; maybe the next block starts here.
+		}
+		if src[si] == '\n' {
+			line++
+			col = 0
+		}
+		col++
+		si++
+	}
+	sort.Sort(boundariesByPos(boundaries))
+	return
+}
+
+type boundariesByPos []Boundary
+
+func (b boundariesByPos) Len() int      { return len(b) }
+func (b boundariesByPos) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b boundariesByPos) Less(i, j int) bool {
+	if b[i].Offset == b[j].Offset {
+		return !b[i].Start && b[j].Start
+	}
+	return b[i].Offset < b[j].Offset
+}
diff --git a/third_party/go.tools/dashboard/README b/third_party/go.tools/dashboard/README
new file mode 100644
index 0000000..1224450
--- /dev/null
+++ b/third_party/go.tools/dashboard/README
@@ -0,0 +1,32 @@
+// 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.
+
+The files in this directory constitute the continuous builder:
+
+app/:     an AppEngine server. The code that runs http://build.golang.org/
+builder/: gobuilder, a Go continuous build client
+coordinator/: daemon that runs on CoreOS on Google Compute Engine and manages
+          builds (using the builder in single-shot mode) in Docker containers.
+env/:     configuration files describing the environment of builders.
+          Many builders are still configured ad-hoc.
+watcher/: a daemon that watches for new commits to the Go repository and
+          its sub-repositories, and notifies the dashboard of those commits.
+
+If you wish to run a Go builder, please email golang-dev@googlegroups.com
+
+To run a builder:
+
+* Write the key ~gobuild/.gobuildkey 
+  You need to get it from someone who knows the key.
+  You may also use a filename of the form .gobuildkey-$BUILDER if you
+  wish to run builders for multiple targets.
+
+* Append your username and password googlecode.com credentials from
+    https://code.google.com/hosting/settings
+  to the buildkey file in the format "Username\nPassword\n".
+  (This is for uploading tarballs to the project downloads section,
+   and is an optional step.)
+
+* Build and run gobuilder (see its documentation for command-line options).
+
diff --git a/third_party/go.tools/dashboard/app/app.yaml b/third_party/go.tools/dashboard/app/app.yaml
new file mode 100644
index 0000000..8424cd0
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/app.yaml
@@ -0,0 +1,21 @@
+# Update with
+#	google_appengine/appcfg.py [-V test-build] update .
+#
+# Using -V test-build will run as test-build.golang.org.
+
+application: golang-org
+version: build
+runtime: go
+api_version: go1
+
+handlers:
+- url: /static
+  static_dir: static
+- url: /(|gccgo/)log/.+
+  script: _go_app
+- url: /(|gccgo/)(|commit|packages|result|perf-result|tag|todo|perf|perfdetail|perfgraph|updatebenchmark)
+  script: _go_app
+- url: /(|gccgo/)(init|buildtest|key|perflearn|_ah/queue/go/delay)
+  script: _go_app
+  login: admin
+
diff --git a/third_party/go.tools/dashboard/app/build/build.go b/third_party/go.tools/dashboard/app/build/build.go
new file mode 100644
index 0000000..90ca344
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/build.go
@@ -0,0 +1,911 @@
+// 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.
+
+// +build appengine
+
+package build
+
+import (
+	"bytes"
+	"compress/gzip"
+	"crypto/sha1"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+
+	"appengine"
+	"appengine/datastore"
+
+	"cache"
+)
+
+const (
+	maxDatastoreStringLen = 500
+	PerfRunLength         = 1024
+)
+
+// A Package describes a package that is listed on the dashboard.
+type Package struct {
+	Kind    string // "subrepo", "external", or empty for the main Go tree
+	Name    string
+	Path    string // (empty for the main Go tree)
+	NextNum int    // Num of the next head Commit
+}
+
+func (p *Package) String() string {
+	return fmt.Sprintf("%s: %q", p.Path, p.Name)
+}
+
+func (p *Package) Key(c appengine.Context) *datastore.Key {
+	key := p.Path
+	if key == "" {
+		key = "go"
+	}
+	return datastore.NewKey(c, "Package", key, 0, nil)
+}
+
+// LastCommit returns the most recent Commit for this Package.
+func (p *Package) LastCommit(c appengine.Context) (*Commit, error) {
+	var commits []*Commit
+	_, err := datastore.NewQuery("Commit").
+		Ancestor(p.Key(c)).
+		Order("-Time").
+		Limit(1).
+		GetAll(c, &commits)
+	if err != nil {
+		return nil, err
+	}
+	if len(commits) != 1 {
+		return nil, datastore.ErrNoSuchEntity
+	}
+	return commits[0], nil
+}
+
+// GetPackage fetches a Package by path from the datastore.
+func GetPackage(c appengine.Context, path string) (*Package, error) {
+	p := &Package{Path: path}
+	err := datastore.Get(c, p.Key(c), p)
+	if err == datastore.ErrNoSuchEntity {
+		return nil, fmt.Errorf("package %q not found", path)
+	}
+	return p, err
+}
+
+// A Commit describes an individual commit in a package.
+//
+// Each Commit entity is a descendant of its associated Package entity.
+// In other words, all Commits with the same PackagePath belong to the same
+// datastore entity group.
+type Commit struct {
+	PackagePath string // (empty for main repo commits)
+	Hash        string
+	ParentHash  string
+	Num         int // Internal monotonic counter unique to this package.
+
+	User              string
+	Desc              string `datastore:",noindex"`
+	Time              time.Time
+	NeedsBenchmarking bool
+	TryPatch          bool
+
+	// ResultData is the Data string of each build Result for this Commit.
+	// For non-Go commits, only the Results for the current Go tip, weekly,
+	// and release Tags are stored here. This is purely de-normalized data.
+	// The complete data set is stored in Result entities.
+	ResultData []string `datastore:",noindex"`
+
+	// PerfResults holds a set of “builder|benchmark” tuples denoting
+	// what benchmarks have been executed on the commit.
+	PerfResults []string `datastore:",noindex"`
+
+	FailNotificationSent bool
+}
+
+func (com *Commit) Key(c appengine.Context) *datastore.Key {
+	if com.Hash == "" {
+		panic("tried Key on Commit with empty Hash")
+	}
+	p := Package{Path: com.PackagePath}
+	key := com.PackagePath + "|" + com.Hash
+	return datastore.NewKey(c, "Commit", key, 0, p.Key(c))
+}
+
+func (c *Commit) Valid() error {
+	if !validHash(c.Hash) {
+		return errors.New("invalid Hash")
+	}
+	if c.ParentHash != "" && !validHash(c.ParentHash) { // empty is OK
+		return errors.New("invalid ParentHash")
+	}
+	return nil
+}
+
+func putCommit(c appengine.Context, com *Commit) error {
+	if err := com.Valid(); err != nil {
+		return fmt.Errorf("putting Commit: %v", err)
+	}
+	if com.Num == 0 && com.ParentHash != "0000" { // 0000 is used in tests
+		return fmt.Errorf("putting Commit: invalid Num (must be > 0)")
+	}
+	if _, err := datastore.Put(c, com.Key(c), com); err != nil {
+		return fmt.Errorf("putting Commit: %v", err)
+	}
+	return nil
+}
+
+// each result line is approx 105 bytes. This constant is a tradeoff between
+// build history and the AppEngine datastore limit of 1mb.
+const maxResults = 1000
+
+// AddResult adds the denormalized Result data to the Commit's Result field.
+// It must be called from inside a datastore transaction.
+func (com *Commit) AddResult(c appengine.Context, r *Result) error {
+	if err := datastore.Get(c, com.Key(c), com); err != nil {
+		return fmt.Errorf("getting Commit: %v", err)
+	}
+
+	var resultExists bool
+	for i, s := range com.ResultData {
+		// if there already exists result data for this builder at com, overwrite it.
+		if strings.HasPrefix(s, r.Builder+"|") && strings.HasSuffix(s, "|"+r.GoHash) {
+			resultExists = true
+			com.ResultData[i] = r.Data()
+		}
+	}
+	if !resultExists {
+		// otherwise, add the new result data for this builder.
+		com.ResultData = trim(append(com.ResultData, r.Data()), maxResults)
+	}
+	return putCommit(c, com)
+}
+
+// AddPerfResult remembers that the builder has run the benchmark on the commit.
+// It must be called from inside a datastore transaction.
+func (com *Commit) AddPerfResult(c appengine.Context, builder, benchmark string) error {
+	if err := datastore.Get(c, com.Key(c), com); err != nil {
+		return fmt.Errorf("getting Commit: %v", err)
+	}
+	if !com.NeedsBenchmarking {
+		return fmt.Errorf("trying to add perf result to Commit(%v) that does not require benchmarking", com.Hash)
+	}
+	s := builder + "|" + benchmark
+	for _, v := range com.PerfResults {
+		if v == s {
+			return nil
+		}
+	}
+	com.PerfResults = append(com.PerfResults, s)
+	return putCommit(c, com)
+}
+
+func trim(s []string, n int) []string {
+	l := min(len(s), n)
+	return s[len(s)-l:]
+}
+
+func min(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}
+
+// Result returns the build Result for this Commit for the given builder/goHash.
+func (c *Commit) Result(builder, goHash string) *Result {
+	for _, r := range c.ResultData {
+		p := strings.SplitN(r, "|", 4)
+		if len(p) != 4 || p[0] != builder || p[3] != goHash {
+			continue
+		}
+		return partsToHash(c, p)
+	}
+	return nil
+}
+
+// Results returns the build Results for this Commit.
+func (c *Commit) Results() (results []*Result) {
+	for _, r := range c.ResultData {
+		p := strings.SplitN(r, "|", 4)
+		if len(p) != 4 {
+			continue
+		}
+		results = append(results, partsToHash(c, p))
+	}
+	return
+}
+
+func (c *Commit) ResultGoHashes() []string {
+	// For the main repo, just return the empty string
+	// (there's no corresponding main repo hash for a main repo Commit).
+	// This function is only really useful for sub-repos.
+	if c.PackagePath == "" {
+		return []string{""}
+	}
+	var hashes []string
+	for _, r := range c.ResultData {
+		p := strings.SplitN(r, "|", 4)
+		if len(p) != 4 {
+			continue
+		}
+		// Append only new results (use linear scan to preserve order).
+		if !contains(hashes, p[3]) {
+			hashes = append(hashes, p[3])
+		}
+	}
+	// Return results in reverse order (newest first).
+	reverse(hashes)
+	return hashes
+}
+
+func contains(t []string, s string) bool {
+	for _, s2 := range t {
+		if s2 == s {
+			return true
+		}
+	}
+	return false
+}
+
+func reverse(s []string) {
+	for i := 0; i < len(s)/2; i++ {
+		j := len(s) - i - 1
+		s[i], s[j] = s[j], s[i]
+	}
+}
+
+// A CommitRun provides summary information for commits [StartCommitNum, StartCommitNum + PerfRunLength).
+// Descendant of Package.
+type CommitRun struct {
+	PackagePath       string // (empty for main repo commits)
+	StartCommitNum    int
+	Hash              []string    `datastore:",noindex"`
+	User              []string    `datastore:",noindex"`
+	Desc              []string    `datastore:",noindex"` // Only first line.
+	Time              []time.Time `datastore:",noindex"`
+	NeedsBenchmarking []bool      `datastore:",noindex"`
+}
+
+func (cr *CommitRun) Key(c appengine.Context) *datastore.Key {
+	p := Package{Path: cr.PackagePath}
+	key := strconv.Itoa(cr.StartCommitNum)
+	return datastore.NewKey(c, "CommitRun", key, 0, p.Key(c))
+}
+
+// GetCommitRun loads and returns CommitRun that contains information
+// for commit commitNum.
+func GetCommitRun(c appengine.Context, commitNum int) (*CommitRun, error) {
+	cr := &CommitRun{StartCommitNum: commitNum / PerfRunLength * PerfRunLength}
+	err := datastore.Get(c, cr.Key(c), cr)
+	if err != nil && err != datastore.ErrNoSuchEntity {
+		return nil, fmt.Errorf("getting CommitRun: %v", err)
+	}
+	if len(cr.Hash) != PerfRunLength {
+		cr.Hash = make([]string, PerfRunLength)
+		cr.User = make([]string, PerfRunLength)
+		cr.Desc = make([]string, PerfRunLength)
+		cr.Time = make([]time.Time, PerfRunLength)
+		cr.NeedsBenchmarking = make([]bool, PerfRunLength)
+	}
+	return cr, nil
+}
+
+func (cr *CommitRun) AddCommit(c appengine.Context, com *Commit) error {
+	if com.Num < cr.StartCommitNum || com.Num >= cr.StartCommitNum+PerfRunLength {
+		return fmt.Errorf("AddCommit: commit num %v out of range [%v, %v)",
+			com.Num, cr.StartCommitNum, cr.StartCommitNum+PerfRunLength)
+	}
+	i := com.Num - cr.StartCommitNum
+	// Be careful with string lengths,
+	// we need to fit 1024 commits into 1 MB.
+	cr.Hash[i] = com.Hash
+	cr.User[i] = shortDesc(com.User)
+	cr.Desc[i] = shortDesc(com.Desc)
+	cr.Time[i] = com.Time
+	cr.NeedsBenchmarking[i] = com.NeedsBenchmarking
+	if _, err := datastore.Put(c, cr.Key(c), cr); err != nil {
+		return fmt.Errorf("putting CommitRun: %v", err)
+	}
+	return nil
+}
+
+// GetCommits returns [startCommitNum, startCommitNum+n) commits.
+// Commits information is partial (obtained from CommitRun),
+// do not store them back into datastore.
+func GetCommits(c appengine.Context, startCommitNum, n int) ([]*Commit, error) {
+	if startCommitNum < 0 || n <= 0 {
+		return nil, fmt.Errorf("GetCommits: invalid args (%v, %v)", startCommitNum, n)
+	}
+
+	p := &Package{}
+	t := datastore.NewQuery("CommitRun").
+		Ancestor(p.Key(c)).
+		Filter("StartCommitNum >=", startCommitNum/PerfRunLength*PerfRunLength).
+		Order("StartCommitNum").
+		Limit(100).
+		Run(c)
+
+	res := make([]*Commit, n)
+	for {
+		cr := new(CommitRun)
+		_, err := t.Next(cr)
+		if err == datastore.Done {
+			break
+		}
+		if err != nil {
+			return nil, err
+		}
+		if cr.StartCommitNum >= startCommitNum+n {
+			break
+		}
+		// Calculate start index for copying.
+		i := 0
+		if cr.StartCommitNum < startCommitNum {
+			i = startCommitNum - cr.StartCommitNum
+		}
+		// Calculate end index for copying.
+		e := PerfRunLength
+		if cr.StartCommitNum+e > startCommitNum+n {
+			e = startCommitNum + n - cr.StartCommitNum
+		}
+		for ; i < e; i++ {
+			com := new(Commit)
+			com.Hash = cr.Hash[i]
+			com.User = cr.User[i]
+			com.Desc = cr.Desc[i]
+			com.Time = cr.Time[i]
+			com.NeedsBenchmarking = cr.NeedsBenchmarking[i]
+			res[cr.StartCommitNum-startCommitNum+i] = com
+		}
+		if e != PerfRunLength {
+			break
+		}
+	}
+	return res, nil
+}
+
+// partsToHash converts a Commit and ResultData substrings to a Result.
+func partsToHash(c *Commit, p []string) *Result {
+	return &Result{
+		Builder:     p[0],
+		Hash:        c.Hash,
+		PackagePath: c.PackagePath,
+		GoHash:      p[3],
+		OK:          p[1] == "true",
+		LogHash:     p[2],
+	}
+}
+
+// A Result describes a build result for a Commit on an OS/architecture.
+//
+// Each Result entity is a descendant of its associated Package entity.
+type Result struct {
+	PackagePath string // (empty for Go commits)
+	Builder     string // "os-arch[-note]"
+	Hash        string
+
+	// The Go Commit this was built against (empty for Go commits).
+	GoHash string
+
+	OK      bool
+	Log     string `datastore:"-"`        // for JSON unmarshaling only
+	LogHash string `datastore:",noindex"` // Key to the Log record.
+
+	RunTime int64 // time to build+test in nanoseconds
+}
+
+func (r *Result) Key(c appengine.Context) *datastore.Key {
+	p := Package{Path: r.PackagePath}
+	key := r.Builder + "|" + r.PackagePath + "|" + r.Hash + "|" + r.GoHash
+	return datastore.NewKey(c, "Result", key, 0, p.Key(c))
+}
+
+func (r *Result) Valid() error {
+	if !validHash(r.Hash) {
+		return errors.New("invalid Hash")
+	}
+	if r.PackagePath != "" && !validHash(r.GoHash) {
+		return errors.New("invalid GoHash")
+	}
+	return nil
+}
+
+// Data returns the Result in string format
+// to be stored in Commit's ResultData field.
+func (r *Result) Data() string {
+	return fmt.Sprintf("%v|%v|%v|%v", r.Builder, r.OK, r.LogHash, r.GoHash)
+}
+
+// A PerfResult describes all benchmarking result for a Commit.
+// Descendant of Package.
+type PerfResult struct {
+	PackagePath string
+	CommitHash  string
+	CommitNum   int
+	Data        []string `datastore:",noindex"` // "builder|benchmark|ok|metric1=val1|metric2=val2|file:log=hash|file:cpuprof=hash"
+
+	// Local cache with parsed Data.
+	// Maps builder->benchmark->ParsedPerfResult.
+	parsedData map[string]map[string]*ParsedPerfResult
+}
+
+type ParsedPerfResult struct {
+	OK        bool
+	Metrics   map[string]uint64
+	Artifacts map[string]string
+}
+
+func (r *PerfResult) Key(c appengine.Context) *datastore.Key {
+	p := Package{Path: r.PackagePath}
+	key := r.CommitHash
+	return datastore.NewKey(c, "PerfResult", key, 0, p.Key(c))
+}
+
+// AddResult add the benchmarking result to r.
+// Existing result for the same builder/benchmark is replaced if already exists.
+// Returns whether the result was already present.
+func (r *PerfResult) AddResult(req *PerfRequest) bool {
+	present := false
+	str := fmt.Sprintf("%v|%v|", req.Builder, req.Benchmark)
+	for i, s := range r.Data {
+		if strings.HasPrefix(s, str) {
+			present = true
+			last := len(r.Data) - 1
+			r.Data[i] = r.Data[last]
+			r.Data = r.Data[:last]
+			break
+		}
+	}
+	ok := "ok"
+	if !req.OK {
+		ok = "false"
+	}
+	str += ok
+	for _, m := range req.Metrics {
+		str += fmt.Sprintf("|%v=%v", m.Type, m.Val)
+	}
+	for _, a := range req.Artifacts {
+		str += fmt.Sprintf("|file:%v=%v", a.Type, a.Body)
+	}
+	r.Data = append(r.Data, str)
+	r.parsedData = nil
+	return present
+}
+
+func (r *PerfResult) ParseData() map[string]map[string]*ParsedPerfResult {
+	if r.parsedData != nil {
+		return r.parsedData
+	}
+	res := make(map[string]map[string]*ParsedPerfResult)
+	for _, str := range r.Data {
+		ss := strings.Split(str, "|")
+		builder := ss[0]
+		bench := ss[1]
+		ok := ss[2]
+		m := res[builder]
+		if m == nil {
+			m = make(map[string]*ParsedPerfResult)
+			res[builder] = m
+		}
+		var p ParsedPerfResult
+		p.OK = ok == "ok"
+		p.Metrics = make(map[string]uint64)
+		p.Artifacts = make(map[string]string)
+		for _, entry := range ss[3:] {
+			if strings.HasPrefix(entry, "file:") {
+				ss1 := strings.Split(entry[len("file:"):], "=")
+				p.Artifacts[ss1[0]] = ss1[1]
+			} else {
+				ss1 := strings.Split(entry, "=")
+				val, _ := strconv.ParseUint(ss1[1], 10, 64)
+				p.Metrics[ss1[0]] = val
+			}
+		}
+		m[bench] = &p
+	}
+	r.parsedData = res
+	return res
+}
+
+// A PerfMetricRun entity holds a set of metric values for builder/benchmark/metric
+// for commits [StartCommitNum, StartCommitNum + PerfRunLength).
+// Descendant of Package.
+type PerfMetricRun struct {
+	PackagePath    string
+	Builder        string
+	Benchmark      string
+	Metric         string // e.g. realtime, cputime, gc-pause
+	StartCommitNum int
+	Vals           []int64 `datastore:",noindex"`
+}
+
+func (m *PerfMetricRun) Key(c appengine.Context) *datastore.Key {
+	p := Package{Path: m.PackagePath}
+	key := m.Builder + "|" + m.Benchmark + "|" + m.Metric + "|" + strconv.Itoa(m.StartCommitNum)
+	return datastore.NewKey(c, "PerfMetricRun", key, 0, p.Key(c))
+}
+
+// GetPerfMetricRun loads and returns PerfMetricRun that contains information
+// for commit commitNum.
+func GetPerfMetricRun(c appengine.Context, builder, benchmark, metric string, commitNum int) (*PerfMetricRun, error) {
+	startCommitNum := commitNum / PerfRunLength * PerfRunLength
+	m := &PerfMetricRun{Builder: builder, Benchmark: benchmark, Metric: metric, StartCommitNum: startCommitNum}
+	err := datastore.Get(c, m.Key(c), m)
+	if err != nil && err != datastore.ErrNoSuchEntity {
+		return nil, fmt.Errorf("getting PerfMetricRun: %v", err)
+	}
+	if len(m.Vals) != PerfRunLength {
+		m.Vals = make([]int64, PerfRunLength)
+	}
+	return m, nil
+}
+
+func (m *PerfMetricRun) AddMetric(c appengine.Context, commitNum int, v uint64) error {
+	if commitNum < m.StartCommitNum || commitNum >= m.StartCommitNum+PerfRunLength {
+		return fmt.Errorf("AddMetric: CommitNum %v out of range [%v, %v)",
+			commitNum, m.StartCommitNum, m.StartCommitNum+PerfRunLength)
+	}
+	m.Vals[commitNum-m.StartCommitNum] = int64(v)
+	if _, err := datastore.Put(c, m.Key(c), m); err != nil {
+		return fmt.Errorf("putting PerfMetricRun: %v", err)
+	}
+	return nil
+}
+
+// GetPerfMetricsForCommits returns perf metrics for builder/benchmark/metric
+// and commits [startCommitNum, startCommitNum+n).
+func GetPerfMetricsForCommits(c appengine.Context, builder, benchmark, metric string, startCommitNum, n int) ([]uint64, error) {
+	if startCommitNum < 0 || n <= 0 {
+		return nil, fmt.Errorf("GetPerfMetricsForCommits: invalid args (%v, %v)", startCommitNum, n)
+	}
+
+	p := &Package{}
+	t := datastore.NewQuery("PerfMetricRun").
+		Ancestor(p.Key(c)).
+		Filter("Builder =", builder).
+		Filter("Benchmark =", benchmark).
+		Filter("Metric =", metric).
+		Filter("StartCommitNum >=", startCommitNum/PerfRunLength*PerfRunLength).
+		Order("StartCommitNum").
+		Limit(100).
+		Run(c)
+
+	res := make([]uint64, n)
+	for {
+		metrics := new(PerfMetricRun)
+		_, err := t.Next(metrics)
+		if err == datastore.Done {
+			break
+		}
+		if err != nil {
+			return nil, err
+		}
+		if metrics.StartCommitNum >= startCommitNum+n {
+			break
+		}
+		// Calculate start index for copying.
+		i := 0
+		if metrics.StartCommitNum < startCommitNum {
+			i = startCommitNum - metrics.StartCommitNum
+		}
+		// Calculate end index for copying.
+		e := PerfRunLength
+		if metrics.StartCommitNum+e > startCommitNum+n {
+			e = startCommitNum + n - metrics.StartCommitNum
+		}
+		for ; i < e; i++ {
+			res[metrics.StartCommitNum-startCommitNum+i] = uint64(metrics.Vals[i])
+		}
+		if e != PerfRunLength {
+			break
+		}
+	}
+	return res, nil
+}
+
+// PerfConfig holds read-mostly configuration related to benchmarking.
+// There is only one PerfConfig entity.
+type PerfConfig struct {
+	BuilderBench []string `datastore:",noindex"` // "builder|benchmark" pairs
+	BuilderProcs []string `datastore:",noindex"` // "builder|proc" pairs
+	BenchMetric  []string `datastore:",noindex"` // "benchmark|metric" pairs
+	NoiseLevels  []string `datastore:",noindex"` // "builder|benchmark|metric1=noise1|metric2=noise2"
+
+	// Local cache of "builder|benchmark|metric" -> noise.
+	noise map[string]float64
+}
+
+func PerfConfigKey(c appengine.Context) *datastore.Key {
+	p := Package{}
+	return datastore.NewKey(c, "PerfConfig", "PerfConfig", 0, p.Key(c))
+}
+
+const perfConfigCacheKey = "perf-config"
+
+func GetPerfConfig(c appengine.Context, r *http.Request) (*PerfConfig, error) {
+	pc := new(PerfConfig)
+	now := cache.Now(c)
+	if cache.Get(r, now, perfConfigCacheKey, pc) {
+		return pc, nil
+	}
+	err := datastore.Get(c, PerfConfigKey(c), pc)
+	if err != nil && err != datastore.ErrNoSuchEntity {
+		return nil, fmt.Errorf("GetPerfConfig: %v", err)
+	}
+	cache.Set(r, now, perfConfigCacheKey, pc)
+	return pc, nil
+}
+
+func (pc *PerfConfig) NoiseLevel(builder, benchmark, metric string) float64 {
+	if pc.noise == nil {
+		pc.noise = make(map[string]float64)
+		for _, str := range pc.NoiseLevels {
+			split := strings.Split(str, "|")
+			builderBench := split[0] + "|" + split[1]
+			for _, entry := range split[2:] {
+				metricValue := strings.Split(entry, "=")
+				noise, _ := strconv.ParseFloat(metricValue[1], 64)
+				pc.noise[builderBench+"|"+metricValue[0]] = noise
+			}
+		}
+	}
+	me := fmt.Sprintf("%v|%v|%v", builder, benchmark, metric)
+	n := pc.noise[me]
+	if n == 0 {
+		// Use a very conservative value
+		// until we have learned the real noise level.
+		n = 200
+	}
+	return n
+}
+
+// UpdatePerfConfig updates the PerfConfig entity with results of benchmarking.
+// Returns whether it's a benchmark that we have not yet seem on the builder.
+func UpdatePerfConfig(c appengine.Context, r *http.Request, req *PerfRequest) (newBenchmark bool, err error) {
+	pc, err := GetPerfConfig(c, r)
+	if err != nil {
+		return false, err
+	}
+
+	modified := false
+	add := func(arr *[]string, str string) {
+		for _, s := range *arr {
+			if s == str {
+				return
+			}
+		}
+		*arr = append(*arr, str)
+		modified = true
+		return
+	}
+
+	BenchProcs := strings.Split(req.Benchmark, "-")
+	benchmark := BenchProcs[0]
+	procs := "1"
+	if len(BenchProcs) > 1 {
+		procs = BenchProcs[1]
+	}
+
+	add(&pc.BuilderBench, req.Builder+"|"+benchmark)
+	newBenchmark = modified
+	add(&pc.BuilderProcs, req.Builder+"|"+procs)
+	for _, m := range req.Metrics {
+		add(&pc.BenchMetric, benchmark+"|"+m.Type)
+	}
+
+	if modified {
+		if _, err := datastore.Put(c, PerfConfigKey(c), pc); err != nil {
+			return false, fmt.Errorf("putting PerfConfig: %v", err)
+		}
+		cache.Tick(c)
+	}
+	return newBenchmark, nil
+}
+
+type MetricList []string
+
+func (l MetricList) Len() int {
+	return len(l)
+}
+
+func (l MetricList) Less(i, j int) bool {
+	bi := strings.HasPrefix(l[i], "build-") || strings.HasPrefix(l[i], "binary-")
+	bj := strings.HasPrefix(l[j], "build-") || strings.HasPrefix(l[j], "binary-")
+	if bi == bj {
+		return l[i] < l[j]
+	}
+	return !bi
+}
+
+func (l MetricList) Swap(i, j int) {
+	l[i], l[j] = l[j], l[i]
+}
+
+func collectList(all []string, idx int, second string) (res []string) {
+	m := make(map[string]bool)
+	for _, str := range all {
+		ss := strings.Split(str, "|")
+		v := ss[idx]
+		v2 := ss[1-idx]
+		if (second == "" || second == v2) && !m[v] {
+			m[v] = true
+			res = append(res, v)
+		}
+	}
+	sort.Sort(MetricList(res))
+	return res
+}
+
+func (pc *PerfConfig) BuildersForBenchmark(bench string) []string {
+	return collectList(pc.BuilderBench, 0, bench)
+}
+
+func (pc *PerfConfig) BenchmarksForBuilder(builder string) []string {
+	return collectList(pc.BuilderBench, 1, builder)
+}
+
+func (pc *PerfConfig) MetricsForBenchmark(bench string) []string {
+	return collectList(pc.BenchMetric, 1, bench)
+}
+
+func (pc *PerfConfig) BenchmarkProcList() (res []string) {
+	bl := pc.BenchmarksForBuilder("")
+	pl := pc.ProcList("")
+	for _, b := range bl {
+		for _, p := range pl {
+			res = append(res, fmt.Sprintf("%v-%v", b, p))
+		}
+	}
+	return res
+}
+
+func (pc *PerfConfig) ProcList(builder string) []int {
+	ss := collectList(pc.BuilderProcs, 1, builder)
+	var procs []int
+	for _, s := range ss {
+		p, _ := strconv.ParseInt(s, 10, 32)
+		procs = append(procs, int(p))
+	}
+	sort.Ints(procs)
+	return procs
+}
+
+// A PerfTodo contains outstanding commits for benchmarking for a builder.
+// Descendant of Package.
+type PerfTodo struct {
+	PackagePath string // (empty for main repo commits)
+	Builder     string
+	CommitNums  []int `datastore:",noindex"` // LIFO queue of commits to benchmark.
+}
+
+func (todo *PerfTodo) Key(c appengine.Context) *datastore.Key {
+	p := Package{Path: todo.PackagePath}
+	key := todo.Builder
+	return datastore.NewKey(c, "PerfTodo", key, 0, p.Key(c))
+}
+
+// AddCommitToPerfTodo adds the commit to all existing PerfTodo entities.
+func AddCommitToPerfTodo(c appengine.Context, com *Commit) error {
+	var todos []*PerfTodo
+	_, err := datastore.NewQuery("PerfTodo").
+		Ancestor((&Package{}).Key(c)).
+		GetAll(c, &todos)
+	if err != nil {
+		return fmt.Errorf("fetching PerfTodo's: %v", err)
+	}
+	for _, todo := range todos {
+		todo.CommitNums = append(todo.CommitNums, com.Num)
+		_, err = datastore.Put(c, todo.Key(c), todo)
+		if err != nil {
+			return fmt.Errorf("updating PerfTodo: %v", err)
+		}
+	}
+	return nil
+}
+
+// A Log is a gzip-compressed log file stored under the SHA1 hash of the
+// uncompressed log text.
+type Log struct {
+	CompressedLog []byte
+}
+
+func (l *Log) Text() ([]byte, error) {
+	d, err := gzip.NewReader(bytes.NewBuffer(l.CompressedLog))
+	if err != nil {
+		return nil, fmt.Errorf("reading log data: %v", err)
+	}
+	b, err := ioutil.ReadAll(d)
+	if err != nil {
+		return nil, fmt.Errorf("reading log data: %v", err)
+	}
+	return b, nil
+}
+
+func PutLog(c appengine.Context, text string) (hash string, err error) {
+	h := sha1.New()
+	io.WriteString(h, text)
+	b := new(bytes.Buffer)
+	z, _ := gzip.NewWriterLevel(b, gzip.BestCompression)
+	io.WriteString(z, text)
+	z.Close()
+	hash = fmt.Sprintf("%x", h.Sum(nil))
+	key := datastore.NewKey(c, "Log", hash, 0, nil)
+	_, err = datastore.Put(c, key, &Log{b.Bytes()})
+	return
+}
+
+// A Tag is used to keep track of the most recent Go weekly and release tags.
+// Typically there will be one Tag entity for each kind of hg tag.
+type Tag struct {
+	Kind string // "weekly", "release", or "tip"
+	Name string // the tag itself (for example: "release.r60")
+	Hash string
+}
+
+func (t *Tag) Key(c appengine.Context) *datastore.Key {
+	p := &Package{}
+	return datastore.NewKey(c, "Tag", t.Kind, 0, p.Key(c))
+}
+
+func (t *Tag) Valid() error {
+	if t.Kind != "weekly" && t.Kind != "release" && t.Kind != "tip" {
+		return errors.New("invalid Kind")
+	}
+	if !validHash(t.Hash) {
+		return errors.New("invalid Hash")
+	}
+	return nil
+}
+
+// Commit returns the Commit that corresponds with this Tag.
+func (t *Tag) Commit(c appengine.Context) (*Commit, error) {
+	com := &Commit{Hash: t.Hash}
+	err := datastore.Get(c, com.Key(c), com)
+	return com, err
+}
+
+// GetTag fetches a Tag by name from the datastore.
+func GetTag(c appengine.Context, tag string) (*Tag, error) {
+	t := &Tag{Kind: tag}
+	if err := datastore.Get(c, t.Key(c), t); err != nil {
+		if err == datastore.ErrNoSuchEntity {
+			return nil, errors.New("tag not found: " + tag)
+		}
+		return nil, err
+	}
+	if err := t.Valid(); err != nil {
+		return nil, err
+	}
+	return t, nil
+}
+
+// Packages returns packages of the specified kind.
+// Kind must be one of "external" or "subrepo".
+func Packages(c appengine.Context, kind string) ([]*Package, error) {
+	switch kind {
+	case "external", "subrepo":
+	default:
+		return nil, errors.New(`kind must be one of "external" or "subrepo"`)
+	}
+	var pkgs []*Package
+	q := datastore.NewQuery("Package").Filter("Kind=", kind)
+	for t := q.Run(c); ; {
+		pkg := new(Package)
+		_, err := t.Next(pkg)
+		if err == datastore.Done {
+			break
+		} else if err != nil {
+			return nil, err
+		}
+		if pkg.Path != "" {
+			pkgs = append(pkgs, pkg)
+		}
+	}
+	return pkgs, nil
+}
diff --git a/third_party/go.tools/dashboard/app/build/dash.go b/third_party/go.tools/dashboard/app/build/dash.go
new file mode 100644
index 0000000..52ca74d
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/dash.go
@@ -0,0 +1,118 @@
+// Copyright 2013 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.
+
+// +build appengine
+
+package build
+
+import (
+	"net/http"
+	"strings"
+
+	"appengine"
+)
+
+// Dashboard describes a unique build dashboard.
+type Dashboard struct {
+	Name     string     // This dashboard's name and namespace
+	RelPath  string     // The relative url path
+	Packages []*Package // The project's packages to build
+}
+
+// dashboardForRequest returns the appropriate dashboard for a given URL path.
+func dashboardForRequest(r *http.Request) *Dashboard {
+	if strings.HasPrefix(r.URL.Path, gccgoDash.RelPath) {
+		return gccgoDash
+	}
+	return goDash
+}
+
+// Context returns a namespaced context for this dashboard, or panics if it
+// fails to create a new context.
+func (d *Dashboard) Context(c appengine.Context) appengine.Context {
+	// No namespace needed for the original Go dashboard.
+	if d.Name == "Go" {
+		return c
+	}
+	n, err := appengine.Namespace(c, d.Name)
+	if err != nil {
+		panic(err)
+	}
+	return n
+}
+
+// the currently known dashboards.
+var dashboards = []*Dashboard{goDash, gccgoDash}
+
+// goDash is the dashboard for the main go repository.
+var goDash = &Dashboard{
+	Name:     "Go",
+	RelPath:  "/",
+	Packages: goPackages,
+}
+
+// goPackages is a list of all of the packages built by the main go repository.
+var goPackages = []*Package{
+	{
+		Kind: "go",
+		Name: "Go",
+	},
+	{
+		Kind: "subrepo",
+		Name: "go.blog",
+		Path: "code.google.com/p/go.blog",
+	},
+	{
+		Kind: "subrepo",
+		Name: "go.codereview",
+		Path: "code.google.com/p/go.codereview",
+	},
+	{
+		Kind: "subrepo",
+		Name: "go.crypto",
+		Path: "code.google.com/p/go.crypto",
+	},
+	{
+		Kind: "subrepo",
+		Name: "go.exp",
+		Path: "code.google.com/p/go.exp",
+	},
+	{
+		Kind: "subrepo",
+		Name: "go.image",
+		Path: "code.google.com/p/go.image",
+	},
+	{
+		Kind: "subrepo",
+		Name: "go.net",
+		Path: "code.google.com/p/go.net",
+	},
+	{
+		Kind: "subrepo",
+		Name: "go.sys",
+		Path: "code.google.com/p/go.sys",
+	},
+	{
+		Kind: "subrepo",
+		Name: "go.talks",
+		Path: "code.google.com/p/go.talks",
+	},
+	{
+		Kind: "subrepo",
+		Name: "go.tools",
+		Path: "code.google.com/p/go.tools",
+	},
+}
+
+// gccgoDash is the dashboard for gccgo.
+var gccgoDash = &Dashboard{
+	Name:    "Gccgo",
+	RelPath: "/gccgo/",
+	Packages: []*Package{
+		{
+			Kind: "gccgo",
+			Name: "Gccgo",
+		},
+	},
+}
diff --git a/third_party/go.tools/dashboard/app/build/handler.go b/third_party/go.tools/dashboard/app/build/handler.go
new file mode 100644
index 0000000..5d06815
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/handler.go
@@ -0,0 +1,906 @@
+// 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.
+
+// +build appengine
+
+package build
+
+import (
+	"bytes"
+	"crypto/hmac"
+	"crypto/md5"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strconv"
+	"strings"
+	"unicode/utf8"
+
+	"appengine"
+	"appengine/datastore"
+
+	"cache"
+	"key"
+)
+
+const commitsPerPage = 30
+const watcherVersion = 2
+
+// commitHandler retrieves commit data or records a new commit.
+//
+// For GET requests it returns a Commit value for the specified
+// packagePath and hash.
+//
+// For POST requests it reads a JSON-encoded Commit value from the request
+// body and creates a new Commit entity. It also updates the "tip" Tag for
+// each new commit at tip.
+//
+// This handler is used by a gobuilder process in -commit mode.
+func commitHandler(r *http.Request) (interface{}, error) {
+	c := contextForRequest(r)
+	com := new(Commit)
+
+	if r.Method == "GET" {
+		com.PackagePath = r.FormValue("packagePath")
+		com.Hash = r.FormValue("hash")
+		err := datastore.Get(c, com.Key(c), com)
+		if com.Num == 0 && com.Desc == "" {
+			// Perf builder might have written an incomplete Commit.
+			// Pretend it doesn't exist, so that we can get complete details.
+			err = datastore.ErrNoSuchEntity
+		}
+		if err != nil {
+			if err == datastore.ErrNoSuchEntity {
+				// This error string is special.
+				// The commit watcher expects it.
+				// Do not change it.
+				return nil, errors.New("Commit not found")
+			}
+			return nil, fmt.Errorf("getting Commit: %v", err)
+		}
+		if com.Num == 0 {
+			// Corrupt state which shouldn't happen but does.
+			// Return an error so builders' commit loops will
+			// be willing to retry submitting this commit.
+			return nil, errors.New("in datastore with zero Num")
+		}
+		if com.Desc == "" || com.User == "" {
+			// Also shouldn't happen, but at least happened
+			// once on a single commit when trying to fix data
+			// in the datastore viewer UI?
+			return nil, errors.New("missing field")
+		}
+		// Strip potentially large and unnecessary fields.
+		com.ResultData = nil
+		com.PerfResults = nil
+		return com, nil
+	}
+	if r.Method != "POST" {
+		return nil, errBadMethod(r.Method)
+	}
+	if !isMasterKey(c, r.FormValue("key")) {
+		return nil, errors.New("can only POST commits with master key")
+	}
+
+	// For now, the commit watcher doesn't support gccgo,
+	// so only do this check for Go commits.
+	// TODO(adg,cmang): remove this check when gccgo is supported.
+	if dashboardForRequest(r) == goDash {
+		v, _ := strconv.Atoi(r.FormValue("version"))
+		if v != watcherVersion {
+			return nil, fmt.Errorf("rejecting POST from commit watcher; need version %v", watcherVersion)
+		}
+	}
+
+	// POST request
+	body, err := ioutil.ReadAll(r.Body)
+	r.Body.Close()
+	if err != nil {
+		return nil, fmt.Errorf("reading Body: %v", err)
+	}
+	if !bytes.Contains(body, needsBenchmarkingBytes) {
+		c.Warningf("old builder detected at %v", r.RemoteAddr)
+		return nil, fmt.Errorf("rejecting old builder request, body does not contain %s: %q", needsBenchmarkingBytes, body)
+	}
+	if err := json.Unmarshal(body, com); err != nil {
+		return nil, fmt.Errorf("unmarshaling body %q: %v", body, err)
+	}
+	com.Desc = limitStringLength(com.Desc, maxDatastoreStringLen)
+	if err := com.Valid(); err != nil {
+		return nil, fmt.Errorf("validating Commit: %v", err)
+	}
+	defer cache.Tick(c)
+	tx := func(c appengine.Context) error {
+		return addCommit(c, com)
+	}
+	return nil, datastore.RunInTransaction(c, tx, nil)
+}
+
+var needsBenchmarkingBytes = []byte(`"NeedsBenchmarking"`)
+
+// addCommit adds the Commit entity to the datastore and updates the tip Tag.
+// It must be run inside a datastore transaction.
+func addCommit(c appengine.Context, com *Commit) error {
+	var ec Commit // existing commit
+	isUpdate := false
+	err := datastore.Get(c, com.Key(c), &ec)
+	if err != nil && err != datastore.ErrNoSuchEntity {
+		return fmt.Errorf("getting Commit: %v", err)
+	}
+	if err == nil {
+		// Commit already in the datastore. Any fields different?
+		// If not, don't do anything.
+		changes := (com.Num != 0 && com.Num != ec.Num) ||
+			com.ParentHash != ec.ParentHash ||
+			com.Desc != ec.Desc ||
+			com.User != ec.User ||
+			!com.Time.Equal(ec.Time)
+		if !changes {
+			return nil
+		}
+		ec.ParentHash = com.ParentHash
+		ec.Desc = com.Desc
+		ec.User = com.User
+		if !com.Time.IsZero() {
+			ec.Time = com.Time
+		}
+		if com.Num != 0 {
+			ec.Num = com.Num
+		}
+		isUpdate = true
+		com = &ec
+	}
+	p, err := GetPackage(c, com.PackagePath)
+	if err != nil {
+		return fmt.Errorf("GetPackage: %v", err)
+	}
+	if com.Num == 0 {
+		// get the next commit number
+		com.Num = p.NextNum
+		p.NextNum++
+		if _, err := datastore.Put(c, p.Key(c), p); err != nil {
+			return fmt.Errorf("putting Package: %v", err)
+		}
+	} else if com.Num >= p.NextNum {
+		p.NextNum = com.Num + 1
+		if _, err := datastore.Put(c, p.Key(c), p); err != nil {
+			return fmt.Errorf("putting Package: %v", err)
+		}
+	}
+	// if this isn't the first Commit test the parent commit exists.
+	// The all zeros are returned by hg's p1node template for parentless commits.
+	if com.ParentHash != "" && com.ParentHash != "0000000000000000000000000000000000000000" && com.ParentHash != "0000" {
+		n, err := datastore.NewQuery("Commit").
+			Filter("Hash =", com.ParentHash).
+			Ancestor(p.Key(c)).
+			Count(c)
+		if err != nil {
+			return fmt.Errorf("testing for parent Commit: %v", err)
+		}
+		if n == 0 {
+			return errors.New("parent commit not found")
+		}
+	}
+	// update the tip Tag if this is the Go repo and this isn't on a release branch
+	if p.Path == "" && !strings.HasPrefix(com.Desc, "[") && !isUpdate {
+		t := &Tag{Kind: "tip", Hash: com.Hash}
+		if _, err = datastore.Put(c, t.Key(c), t); err != nil {
+			return fmt.Errorf("putting Tag: %v", err)
+		}
+	}
+	// put the Commit
+	if err = putCommit(c, com); err != nil {
+		return err
+	}
+	if com.NeedsBenchmarking {
+		// add to CommitRun
+		cr, err := GetCommitRun(c, com.Num)
+		if err != nil {
+			return err
+		}
+		if err = cr.AddCommit(c, com); err != nil {
+			return err
+		}
+		// create PerfResult
+		res := &PerfResult{CommitHash: com.Hash, CommitNum: com.Num}
+		if _, err := datastore.Put(c, res.Key(c), res); err != nil {
+			return fmt.Errorf("putting PerfResult: %v", err)
+		}
+		// Update perf todo if necessary.
+		if err = AddCommitToPerfTodo(c, com); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// tagHandler records a new tag. It reads a JSON-encoded Tag value from the
+// request body and updates the Tag entity for the Kind of tag provided.
+//
+// This handler is used by a gobuilder process in -commit mode.
+func tagHandler(r *http.Request) (interface{}, error) {
+	if r.Method != "POST" {
+		return nil, errBadMethod(r.Method)
+	}
+
+	t := new(Tag)
+	defer r.Body.Close()
+	if err := json.NewDecoder(r.Body).Decode(t); err != nil {
+		return nil, err
+	}
+	if err := t.Valid(); err != nil {
+		return nil, err
+	}
+	c := contextForRequest(r)
+	defer cache.Tick(c)
+	_, err := datastore.Put(c, t.Key(c), t)
+	return nil, err
+}
+
+// Todo is a todoHandler response.
+type Todo struct {
+	Kind string // "build-go-commit" or "build-package"
+	Data interface{}
+}
+
+// todoHandler returns the next action to be performed by a builder.
+// It expects "builder" and "kind" query parameters and returns a *Todo value.
+// Multiple "kind" parameters may be specified.
+func todoHandler(r *http.Request) (interface{}, error) {
+	c := contextForRequest(r)
+	now := cache.Now(c)
+	key := "build-todo-" + r.Form.Encode()
+	var todo *Todo
+	if cache.Get(r, now, key, &todo) {
+		return todo, nil
+	}
+	var err error
+	builder := r.FormValue("builder")
+	for _, kind := range r.Form["kind"] {
+		var com *Commit
+		switch kind {
+		case "build-go-commit":
+			com, err = buildTodo(c, builder, "", "")
+			if com != nil {
+				com.PerfResults = []string{}
+			}
+		case "build-package":
+			packagePath := r.FormValue("packagePath")
+			goHash := r.FormValue("goHash")
+			com, err = buildTodo(c, builder, packagePath, goHash)
+			if com != nil {
+				com.PerfResults = []string{}
+			}
+		case "benchmark-go-commit":
+			com, err = perfTodo(c, builder)
+		}
+		if com != nil || err != nil {
+			if com != nil {
+				// ResultData can be large and not needed on builder.
+				com.ResultData = []string{}
+			}
+			todo = &Todo{Kind: kind, Data: com}
+			break
+		}
+	}
+	if err == nil {
+		cache.Set(r, now, key, todo)
+	}
+	return todo, err
+}
+
+// buildTodo returns the next Commit to be built (or nil if none available).
+//
+// If packagePath and goHash are empty, it scans the first 20 Go Commits in
+// Num-descending order and returns the first one it finds that doesn't have a
+// Result for this builder.
+//
+// If provided with non-empty packagePath and goHash args, it scans the first
+// 20 Commits in Num-descending order for the specified packagePath and
+// returns the first that doesn't have a Result for this builder and goHash.
+func buildTodo(c appengine.Context, builder, packagePath, goHash string) (*Commit, error) {
+	p, err := GetPackage(c, packagePath)
+	if err != nil {
+		return nil, err
+	}
+
+	t := datastore.NewQuery("Commit").
+		Ancestor(p.Key(c)).
+		Limit(commitsPerPage).
+		Order("-Num").
+		Run(c)
+	for {
+		com := new(Commit)
+		if _, err := t.Next(com); err == datastore.Done {
+			break
+		} else if err != nil {
+			return nil, err
+		}
+		if com.Result(builder, goHash) == nil {
+			return com, nil
+		}
+	}
+
+	// Nothing left to do if this is a package (not the Go tree).
+	if packagePath != "" {
+		return nil, nil
+	}
+
+	// If there are no Go tree commits left to build,
+	// see if there are any subrepo commits that need to be built at tip.
+	// If so, ask the builder to build a go tree at the tip commit.
+	// TODO(adg): do the same for "weekly" and "release" tags.
+
+	tag, err := GetTag(c, "tip")
+	if err != nil {
+		return nil, err
+	}
+
+	// Check that this Go commit builds OK for this builder.
+	// If not, don't re-build as the subrepos will never get built anyway.
+	com, err := tag.Commit(c)
+	if err != nil {
+		return nil, err
+	}
+	if r := com.Result(builder, ""); r != nil && !r.OK {
+		return nil, nil
+	}
+
+	pkgs, err := Packages(c, "subrepo")
+	if err != nil {
+		return nil, err
+	}
+	for _, pkg := range pkgs {
+		com, err := pkg.LastCommit(c)
+		if err != nil {
+			c.Warningf("%v: no Commit found: %v", pkg, err)
+			continue
+		}
+		if com.Result(builder, tag.Hash) == nil {
+			return tag.Commit(c)
+		}
+	}
+
+	return nil, nil
+}
+
+// perfTodo returns the next Commit to be benchmarked (or nil if none available).
+func perfTodo(c appengine.Context, builder string) (*Commit, error) {
+	p := &Package{}
+	todo := &PerfTodo{Builder: builder}
+	err := datastore.Get(c, todo.Key(c), todo)
+	if err != nil && err != datastore.ErrNoSuchEntity {
+		return nil, fmt.Errorf("fetching PerfTodo: %v", err)
+	}
+	if err == datastore.ErrNoSuchEntity {
+		todo, err = buildPerfTodo(c, builder)
+		if err != nil {
+			return nil, err
+		}
+	}
+	if len(todo.CommitNums) == 0 {
+		return nil, nil
+	}
+
+	// Have commit to benchmark, fetch it.
+	num := todo.CommitNums[len(todo.CommitNums)-1]
+	t := datastore.NewQuery("Commit").
+		Ancestor(p.Key(c)).
+		Filter("Num =", num).
+		Limit(1).
+		Run(c)
+	com := new(Commit)
+	if _, err := t.Next(com); err != nil {
+		return nil, err
+	}
+	if !com.NeedsBenchmarking {
+		return nil, fmt.Errorf("commit from perf todo queue is not intended for benchmarking")
+	}
+
+	// Remove benchmarks from other builders.
+	var benchs []string
+	for _, b := range com.PerfResults {
+		bb := strings.Split(b, "|")
+		if bb[0] == builder && bb[1] != "meta-done" {
+			benchs = append(benchs, bb[1])
+		}
+	}
+	com.PerfResults = benchs
+
+	return com, nil
+}
+
+// buildPerfTodo creates PerfTodo for the builder with all commits. In a transaction.
+func buildPerfTodo(c appengine.Context, builder string) (*PerfTodo, error) {
+	todo := &PerfTodo{Builder: builder}
+	tx := func(c appengine.Context) error {
+		err := datastore.Get(c, todo.Key(c), todo)
+		if err != nil && err != datastore.ErrNoSuchEntity {
+			return fmt.Errorf("fetching PerfTodo: %v", err)
+		}
+		if err == nil {
+			return nil
+		}
+		t := datastore.NewQuery("CommitRun").
+			Ancestor((&Package{}).Key(c)).
+			Order("-StartCommitNum").
+			Run(c)
+		var nums []int
+		var releaseNums []int
+	loop:
+		for {
+			cr := new(CommitRun)
+			if _, err := t.Next(cr); err == datastore.Done {
+				break
+			} else if err != nil {
+				return fmt.Errorf("scanning commit runs for perf todo: %v", err)
+			}
+			for i := len(cr.Hash) - 1; i >= 0; i-- {
+				if !cr.NeedsBenchmarking[i] || cr.Hash[i] == "" {
+					continue // There's nothing to see here. Move along.
+				}
+				num := cr.StartCommitNum + i
+				for k, v := range knownTags {
+					// Releases are benchmarked first, because they are important (and there are few of them).
+					if cr.Hash[i] == v {
+						releaseNums = append(releaseNums, num)
+						if k == "go1" {
+							break loop // Point of no benchmark: test/bench/shootout: update timing.log to Go 1.
+						}
+					}
+				}
+				nums = append(nums, num)
+			}
+		}
+		todo.CommitNums = orderPerfTodo(nums)
+		todo.CommitNums = append(todo.CommitNums, releaseNums...)
+		if _, err = datastore.Put(c, todo.Key(c), todo); err != nil {
+			return fmt.Errorf("putting PerfTodo: %v", err)
+		}
+		return nil
+	}
+	return todo, datastore.RunInTransaction(c, tx, nil)
+}
+
+func removeCommitFromPerfTodo(c appengine.Context, builder string, num int) error {
+	todo := &PerfTodo{Builder: builder}
+	err := datastore.Get(c, todo.Key(c), todo)
+	if err != nil && err != datastore.ErrNoSuchEntity {
+		return fmt.Errorf("fetching PerfTodo: %v", err)
+	}
+	if err == datastore.ErrNoSuchEntity {
+		return nil
+	}
+	for i := len(todo.CommitNums) - 1; i >= 0; i-- {
+		if todo.CommitNums[i] == num {
+			for ; i < len(todo.CommitNums)-1; i++ {
+				todo.CommitNums[i] = todo.CommitNums[i+1]
+			}
+			todo.CommitNums = todo.CommitNums[:i]
+			_, err = datastore.Put(c, todo.Key(c), todo)
+			if err != nil {
+				return fmt.Errorf("putting PerfTodo: %v", err)
+			}
+			break
+		}
+	}
+	return nil
+}
+
+// packagesHandler returns a list of the non-Go Packages monitored
+// by the dashboard.
+func packagesHandler(r *http.Request) (interface{}, error) {
+	kind := r.FormValue("kind")
+	c := contextForRequest(r)
+	now := cache.Now(c)
+	key := "build-packages-" + kind
+	var p []*Package
+	if cache.Get(r, now, key, &p) {
+		return p, nil
+	}
+	p, err := Packages(c, kind)
+	if err != nil {
+		return nil, err
+	}
+	cache.Set(r, now, key, p)
+	return p, nil
+}
+
+// resultHandler records a build result.
+// It reads a JSON-encoded Result value from the request body,
+// creates a new Result entity, and updates the relevant Commit entity.
+// If the Log field is not empty, resultHandler creates a new Log entity
+// and updates the LogHash field before putting the Commit entity.
+func resultHandler(r *http.Request) (interface{}, error) {
+	if r.Method != "POST" {
+		return nil, errBadMethod(r.Method)
+	}
+
+	c := contextForRequest(r)
+	res := new(Result)
+	defer r.Body.Close()
+	if err := json.NewDecoder(r.Body).Decode(res); err != nil {
+		return nil, fmt.Errorf("decoding Body: %v", err)
+	}
+	if err := res.Valid(); err != nil {
+		return nil, fmt.Errorf("validating Result: %v", err)
+	}
+	defer cache.Tick(c)
+	// store the Log text if supplied
+	if len(res.Log) > 0 {
+		hash, err := PutLog(c, res.Log)
+		if err != nil {
+			return nil, fmt.Errorf("putting Log: %v", err)
+		}
+		res.LogHash = hash
+	}
+	tx := func(c appengine.Context) error {
+		// check Package exists
+		if _, err := GetPackage(c, res.PackagePath); err != nil {
+			return fmt.Errorf("GetPackage: %v", err)
+		}
+		// put Result
+		if _, err := datastore.Put(c, res.Key(c), res); err != nil {
+			return fmt.Errorf("putting Result: %v", err)
+		}
+		// add Result to Commit
+		com := &Commit{PackagePath: res.PackagePath, Hash: res.Hash}
+		if err := com.AddResult(c, res); err != nil {
+			return fmt.Errorf("AddResult: %v", err)
+		}
+		// Send build failure notifications, if necessary.
+		// Note this must run after the call AddResult, which
+		// populates the Commit's ResultData field.
+		return notifyOnFailure(c, com, res.Builder)
+	}
+	return nil, datastore.RunInTransaction(c, tx, nil)
+}
+
+// perf-result request payload
+type PerfRequest struct {
+	Builder   string
+	Benchmark string
+	Hash      string
+	OK        bool
+	Metrics   []PerfMetric
+	Artifacts []PerfArtifact
+}
+
+type PerfMetric struct {
+	Type string
+	Val  uint64
+}
+
+type PerfArtifact struct {
+	Type string
+	Body string
+}
+
+// perfResultHandler records a becnhmarking result.
+func perfResultHandler(r *http.Request) (interface{}, error) {
+	defer r.Body.Close()
+	if r.Method != "POST" {
+		return nil, errBadMethod(r.Method)
+	}
+
+	req := new(PerfRequest)
+	if err := json.NewDecoder(r.Body).Decode(req); err != nil {
+		return nil, fmt.Errorf("decoding Body: %v", err)
+	}
+
+	c := contextForRequest(r)
+	defer cache.Tick(c)
+
+	// store the text files if supplied
+	for i, a := range req.Artifacts {
+		hash, err := PutLog(c, a.Body)
+		if err != nil {
+			return nil, fmt.Errorf("putting Log: %v", err)
+		}
+		req.Artifacts[i].Body = hash
+	}
+	tx := func(c appengine.Context) error {
+		return addPerfResult(c, r, req)
+	}
+	return nil, datastore.RunInTransaction(c, tx, nil)
+}
+
+// addPerfResult creates PerfResult and updates Commit, PerfTodo,
+// PerfMetricRun and PerfConfig.
+// MUST be called from inside a transaction.
+func addPerfResult(c appengine.Context, r *http.Request, req *PerfRequest) error {
+	// check Package exists
+	p, err := GetPackage(c, "")
+	if err != nil {
+		return fmt.Errorf("GetPackage: %v", err)
+	}
+	// add result to Commit
+	com := &Commit{Hash: req.Hash}
+	if err := com.AddPerfResult(c, req.Builder, req.Benchmark); err != nil {
+		return fmt.Errorf("AddPerfResult: %v", err)
+	}
+
+	// add the result to PerfResult
+	res := &PerfResult{CommitHash: req.Hash}
+	if err := datastore.Get(c, res.Key(c), res); err != nil {
+		return fmt.Errorf("getting PerfResult: %v", err)
+	}
+	present := res.AddResult(req)
+	if _, err := datastore.Put(c, res.Key(c), res); err != nil {
+		return fmt.Errorf("putting PerfResult: %v", err)
+	}
+
+	// Meta-done denotes that there are no benchmarks left.
+	if req.Benchmark == "meta-done" {
+		// Don't send duplicate emails for the same commit/builder.
+		// And don't send emails about too old commits.
+		if !present && com.Num >= p.NextNum-commitsPerPage {
+			if err := checkPerfChanges(c, r, com, req.Builder, res); err != nil {
+				return err
+			}
+		}
+		if err := removeCommitFromPerfTodo(c, req.Builder, com.Num); err != nil {
+			return nil
+		}
+		return nil
+	}
+
+	// update PerfConfig
+	newBenchmark, err := UpdatePerfConfig(c, r, req)
+	if err != nil {
+		return fmt.Errorf("updating PerfConfig: %v", err)
+	}
+	if newBenchmark {
+		// If this is a new benchmark on the builder, delete PerfTodo.
+		// It will be recreated later with all commits again.
+		todo := &PerfTodo{Builder: req.Builder}
+		err = datastore.Delete(c, todo.Key(c))
+		if err != nil && err != datastore.ErrNoSuchEntity {
+			return fmt.Errorf("deleting PerfTodo: %v", err)
+		}
+	}
+
+	// add perf metrics
+	for _, metric := range req.Metrics {
+		m, err := GetPerfMetricRun(c, req.Builder, req.Benchmark, metric.Type, com.Num)
+		if err != nil {
+			return fmt.Errorf("GetPerfMetrics: %v", err)
+		}
+		if err = m.AddMetric(c, com.Num, metric.Val); err != nil {
+			return fmt.Errorf("AddMetric: %v", err)
+		}
+	}
+
+	return nil
+}
+
+// MUST be called from inside a transaction.
+func checkPerfChanges(c appengine.Context, r *http.Request, com *Commit, builder string, res *PerfResult) error {
+	pc, err := GetPerfConfig(c, r)
+	if err != nil {
+		return err
+	}
+
+	results := res.ParseData()[builder]
+	rcNewer := MakePerfResultCache(c, com, true)
+	rcOlder := MakePerfResultCache(c, com, false)
+
+	// Check whether we need to send failure notification email.
+	if results["meta-done"].OK {
+		// This one is successful, see if the next is failed.
+		nextRes, err := rcNewer.Next(com.Num)
+		if err != nil {
+			return err
+		}
+		if nextRes != nil && isPerfFailed(nextRes, builder) {
+			sendPerfFailMail(c, builder, nextRes)
+		}
+	} else {
+		// This one is failed, see if the previous is successful.
+		prevRes, err := rcOlder.Next(com.Num)
+		if err != nil {
+			return err
+		}
+		if prevRes != nil && !isPerfFailed(prevRes, builder) {
+			sendPerfFailMail(c, builder, res)
+		}
+	}
+
+	// Now see if there are any performance changes.
+	// Find the previous and the next results for performance comparison.
+	prevRes, err := rcOlder.NextForComparison(com.Num, builder)
+	if err != nil {
+		return err
+	}
+	nextRes, err := rcNewer.NextForComparison(com.Num, builder)
+	if err != nil {
+		return err
+	}
+	if results["meta-done"].OK {
+		// This one is successful, compare with a previous one.
+		if prevRes != nil {
+			if err := comparePerfResults(c, pc, builder, prevRes, res); err != nil {
+				return err
+			}
+		}
+		// Compare a next one with the current.
+		if nextRes != nil {
+			if err := comparePerfResults(c, pc, builder, res, nextRes); err != nil {
+				return err
+			}
+		}
+	} else {
+		// This one is failed, compare a previous one with a next one.
+		if prevRes != nil && nextRes != nil {
+			if err := comparePerfResults(c, pc, builder, prevRes, nextRes); err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func comparePerfResults(c appengine.Context, pc *PerfConfig, builder string, prevRes, res *PerfResult) error {
+	changes := significantPerfChanges(pc, builder, prevRes, res)
+	if len(changes) == 0 {
+		return nil
+	}
+	com := &Commit{Hash: res.CommitHash}
+	if err := datastore.Get(c, com.Key(c), com); err != nil {
+		return fmt.Errorf("getting commit %v: %v", com.Hash, err)
+	}
+	sendPerfMailLater.Call(c, com, prevRes.CommitHash, builder, changes) // add task to queue
+	return nil
+}
+
+// logHandler displays log text for a given hash.
+// It handles paths like "/log/hash".
+func logHandler(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-type", "text/plain; charset=utf-8")
+	c := contextForRequest(r)
+	hash := r.URL.Path[strings.LastIndex(r.URL.Path, "/")+1:]
+	key := datastore.NewKey(c, "Log", hash, 0, nil)
+	l := new(Log)
+	if err := datastore.Get(c, key, l); err != nil {
+		logErr(w, r, err)
+		return
+	}
+	b, err := l.Text()
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+	w.Write(b)
+}
+
+type dashHandler func(*http.Request) (interface{}, error)
+
+type dashResponse struct {
+	Response interface{}
+	Error    string
+}
+
+// errBadMethod is returned by a dashHandler when
+// the request has an unsuitable method.
+type errBadMethod string
+
+func (e errBadMethod) Error() string {
+	return "bad method: " + string(e)
+}
+
+// AuthHandler wraps a http.HandlerFunc with a handler that validates the
+// supplied key and builder query parameters.
+func AuthHandler(h dashHandler) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		c := contextForRequest(r)
+
+		// Put the URL Query values into r.Form to avoid parsing the
+		// request body when calling r.FormValue.
+		r.Form = r.URL.Query()
+
+		var err error
+		var resp interface{}
+
+		// Validate key query parameter for POST requests only.
+		key := r.FormValue("key")
+		builder := r.FormValue("builder")
+		if r.Method == "POST" && !validKey(c, key, builder) {
+			err = fmt.Errorf("invalid key %q for builder %q", key, builder)
+		}
+
+		// Call the original HandlerFunc and return the response.
+		if err == nil {
+			resp, err = h(r)
+		}
+
+		// Write JSON response.
+		dashResp := &dashResponse{Response: resp}
+		if err != nil {
+			c.Errorf("%v", err)
+			dashResp.Error = err.Error()
+		}
+		w.Header().Set("Content-Type", "application/json")
+		if err = json.NewEncoder(w).Encode(dashResp); err != nil {
+			c.Criticalf("encoding response: %v", err)
+		}
+	}
+}
+
+func keyHandler(w http.ResponseWriter, r *http.Request) {
+	builder := r.FormValue("builder")
+	if builder == "" {
+		logErr(w, r, errors.New("must supply builder in query string"))
+		return
+	}
+	c := contextForRequest(r)
+	fmt.Fprint(w, builderKey(c, builder))
+}
+
+func init() {
+	for _, d := range dashboards {
+		// admin handlers
+		http.HandleFunc(d.RelPath+"init", initHandler)
+		http.HandleFunc(d.RelPath+"key", keyHandler)
+
+		// authenticated handlers
+		http.HandleFunc(d.RelPath+"commit", AuthHandler(commitHandler))
+		http.HandleFunc(d.RelPath+"packages", AuthHandler(packagesHandler))
+		http.HandleFunc(d.RelPath+"result", AuthHandler(resultHandler))
+		http.HandleFunc(d.RelPath+"perf-result", AuthHandler(perfResultHandler))
+		http.HandleFunc(d.RelPath+"tag", AuthHandler(tagHandler))
+		http.HandleFunc(d.RelPath+"todo", AuthHandler(todoHandler))
+
+		// public handlers
+		http.HandleFunc(d.RelPath+"log/", logHandler)
+	}
+}
+
+func validHash(hash string) bool {
+	// TODO(adg): correctly validate a hash
+	return hash != ""
+}
+
+func validKey(c appengine.Context, key, builder string) bool {
+	return isMasterKey(c, key) || key == builderKey(c, builder)
+}
+
+func isMasterKey(c appengine.Context, k string) bool {
+	return appengine.IsDevAppServer() || k == key.Secret(c)
+}
+
+func builderKey(c appengine.Context, builder string) string {
+	h := hmac.New(md5.New, []byte(key.Secret(c)))
+	h.Write([]byte(builder))
+	return fmt.Sprintf("%x", h.Sum(nil))
+}
+
+func logErr(w http.ResponseWriter, r *http.Request, err error) {
+	contextForRequest(r).Errorf("Error: %v", err)
+	w.WriteHeader(http.StatusInternalServerError)
+	fmt.Fprint(w, "Error: ", err)
+}
+
+func contextForRequest(r *http.Request) appengine.Context {
+	return dashboardForRequest(r).Context(appengine.NewContext(r))
+}
+
+// limitStringLength essentially does return s[:max],
+// but it ensures that we dot not split UTF-8 rune in half.
+// Otherwise appengine python scripts will break badly.
+func limitStringLength(s string, max int) string {
+	if len(s) <= max {
+		return s
+	}
+	for {
+		s = s[:max]
+		r, size := utf8.DecodeLastRuneInString(s)
+		if r != utf8.RuneError || size != 1 {
+			return s
+		}
+		max--
+	}
+}
diff --git a/third_party/go.tools/dashboard/app/build/init.go b/third_party/go.tools/dashboard/app/build/init.go
new file mode 100644
index 0000000..e7d63ed
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/init.go
@@ -0,0 +1,46 @@
+// 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.
+
+// +build appengine
+
+package build
+
+import (
+	"fmt"
+	"net/http"
+
+	"appengine"
+	"appengine/datastore"
+
+	"cache"
+	"key"
+)
+
+func initHandler(w http.ResponseWriter, r *http.Request) {
+	d := dashboardForRequest(r)
+	c := d.Context(appengine.NewContext(r))
+	defer cache.Tick(c)
+	for _, p := range d.Packages {
+		err := datastore.Get(c, p.Key(c), new(Package))
+		if _, ok := err.(*datastore.ErrFieldMismatch); ok {
+			// Some fields have been removed, so it's okay to ignore this error.
+			err = nil
+		}
+		if err == nil {
+			continue
+		} else if err != datastore.ErrNoSuchEntity {
+			logErr(w, r, err)
+			return
+		}
+		if _, err := datastore.Put(c, p.Key(c), p); err != nil {
+			logErr(w, r, err)
+			return
+		}
+	}
+
+	// Create secret key.
+	key.Secret(c)
+
+	fmt.Fprint(w, "OK")
+}
diff --git a/third_party/go.tools/dashboard/app/build/notify.go b/third_party/go.tools/dashboard/app/build/notify.go
new file mode 100644
index 0000000..1a71dd2
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/notify.go
@@ -0,0 +1,378 @@
+// 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.
+
+// +build appengine
+
+package build
+
+import (
+	"bytes"
+	"encoding/gob"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"regexp"
+	"runtime"
+	"sort"
+	"text/template"
+
+	"appengine"
+	"appengine/datastore"
+	"appengine/delay"
+	"appengine/mail"
+	"appengine/urlfetch"
+)
+
+const (
+	mailFrom   = "builder@golang.org" // use this for sending any mail
+	failMailTo = "golang-dev@googlegroups.com"
+	domain     = "build.golang.org"
+	gobotBase  = "http://research.swtch.com/gobot_codereview"
+)
+
+// ignoreFailure is a set of builders that we don't email about because
+// they are not yet production-ready.
+var ignoreFailure = map[string]bool{
+	"dragonfly-386":         true,
+	"dragonfly-amd64":       true,
+	"freebsd-arm":           true,
+	"netbsd-amd64-bsiegert": true,
+	"netbsd-arm-rpi":        true,
+	"plan9-amd64-aram":      true,
+}
+
+// notifyOnFailure checks whether the supplied Commit or the subsequent
+// Commit (if present) breaks the build for this builder.
+// If either of those commits break the build an email notification is sent
+// from a delayed task. (We use a task because this way the mail won't be
+// sent if the enclosing datastore transaction fails.)
+//
+// This must be run in a datastore transaction, and the provided *Commit must
+// have been retrieved from the datastore within that transaction.
+func notifyOnFailure(c appengine.Context, com *Commit, builder string) error {
+	if ignoreFailure[builder] {
+		return nil
+	}
+
+	// TODO(adg): implement notifications for packages
+	if com.PackagePath != "" {
+		return nil
+	}
+
+	p := &Package{Path: com.PackagePath}
+	var broken *Commit
+	cr := com.Result(builder, "")
+	if cr == nil {
+		return fmt.Errorf("no result for %s/%s", com.Hash, builder)
+	}
+	q := datastore.NewQuery("Commit").Ancestor(p.Key(c))
+	if cr.OK {
+		// This commit is OK. Notify if next Commit is broken.
+		next := new(Commit)
+		q = q.Filter("ParentHash=", com.Hash)
+		if err := firstMatch(c, q, next); err != nil {
+			if err == datastore.ErrNoSuchEntity {
+				// OK at tip, no notification necessary.
+				return nil
+			}
+			return err
+		}
+		if nr := next.Result(builder, ""); nr != nil && !nr.OK {
+			c.Debugf("commit ok: %#v\nresult: %#v", com, cr)
+			c.Debugf("next commit broken: %#v\nnext result:%#v", next, nr)
+			broken = next
+		}
+	} else {
+		// This commit is broken. Notify if the previous Commit is OK.
+		prev := new(Commit)
+		q = q.Filter("Hash=", com.ParentHash)
+		if err := firstMatch(c, q, prev); err != nil {
+			if err == datastore.ErrNoSuchEntity {
+				// No previous result, let the backfill of
+				// this result trigger the notification.
+				return nil
+			}
+			return err
+		}
+		if pr := prev.Result(builder, ""); pr != nil && pr.OK {
+			c.Debugf("commit broken: %#v\nresult: %#v", com, cr)
+			c.Debugf("previous commit ok: %#v\nprevious result:%#v", prev, pr)
+			broken = com
+		}
+	}
+	if broken == nil {
+		return nil
+	}
+	r := broken.Result(builder, "")
+	if r == nil {
+		return fmt.Errorf("finding result for %q: %+v", builder, com)
+	}
+	return commonNotify(c, broken, builder, r.LogHash)
+}
+
+// firstMatch executes the query q and loads the first entity into v.
+func firstMatch(c appengine.Context, q *datastore.Query, v interface{}) error {
+	t := q.Limit(1).Run(c)
+	_, err := t.Next(v)
+	if err == datastore.Done {
+		err = datastore.ErrNoSuchEntity
+	}
+	return err
+}
+
+var notifyLater = delay.Func("notify", notify)
+
+// notify tries to update the CL for the given Commit with a failure message.
+// If it doesn't succeed, it sends a failure email to golang-dev.
+func notify(c appengine.Context, com *Commit, builder, logHash string) {
+	v := url.Values{"brokebuild": {builder}, "log": {logHash}}
+	if !updateCL(c, com, v) {
+		// Send a mail notification if the CL can't be found.
+		sendFailMail(c, com, builder, logHash)
+	}
+}
+
+// updateCL tells gobot to update the CL for the given Commit with
+// the provided query values.
+func updateCL(c appengine.Context, com *Commit, v url.Values) bool {
+	cl, err := lookupCL(c, com)
+	if err != nil {
+		c.Errorf("could not find CL for %v: %v", com.Hash, err)
+		return false
+	}
+	u := fmt.Sprintf("%v?cl=%v&%s", gobotBase, cl, v.Encode())
+	r, err := urlfetch.Client(c).Post(u, "text/plain", nil)
+	if err != nil {
+		c.Errorf("could not update CL %v: %v", cl, err)
+		return false
+	}
+	r.Body.Close()
+	if r.StatusCode != http.StatusOK {
+		c.Errorf("could not update CL %v: %v", cl, r.Status)
+		return false
+	}
+	return true
+}
+
+var clURL = regexp.MustCompile(`https://codereview.appspot.com/([0-9]+)`)
+
+// lookupCL consults code.google.com for the full change description for the
+// provided Commit, and returns the relevant CL number.
+func lookupCL(c appengine.Context, com *Commit) (string, error) {
+	url := "https://code.google.com/p/go/source/detail?r=" + com.Hash
+	r, err := urlfetch.Client(c).Get(url)
+	if err != nil {
+		return "", err
+	}
+	defer r.Body.Close()
+	if r.StatusCode != http.StatusOK {
+		return "", fmt.Errorf("retrieving %v: %v", url, r.Status)
+	}
+	b, err := ioutil.ReadAll(r.Body)
+	if err != nil {
+		return "", err
+	}
+	m := clURL.FindAllSubmatch(b, -1)
+	if m == nil {
+		return "", errors.New("no CL URL found on changeset page")
+	}
+	// Return the last visible codereview URL on the page,
+	// in case the change description refers to another CL.
+	return string(m[len(m)-1][1]), nil
+}
+
+var sendFailMailTmpl = template.Must(template.New("notify.txt").
+	Funcs(template.FuncMap(tmplFuncs)).
+	ParseFiles("build/notify.txt"))
+
+func init() {
+	gob.Register(&Commit{}) // for delay
+}
+
+var (
+	sendPerfMailLater = delay.Func("sendPerfMail", sendPerfMailFunc)
+	sendPerfMailTmpl  = template.Must(
+		template.New("perf_notify.txt").
+			Funcs(template.FuncMap(tmplFuncs)).
+			ParseFiles("build/perf_notify.txt"),
+	)
+)
+
+// MUST be called from inside a transaction.
+func sendPerfFailMail(c appengine.Context, builder string, res *PerfResult) error {
+	com := &Commit{Hash: res.CommitHash}
+	if err := datastore.Get(c, com.Key(c), com); err != nil {
+		return err
+	}
+	logHash := ""
+	parsed := res.ParseData()
+	for _, data := range parsed[builder] {
+		if !data.OK {
+			logHash = data.Artifacts["log"]
+			break
+		}
+	}
+	if logHash == "" {
+		return fmt.Errorf("can not find failed result for commit %v on builder %v", com.Hash, builder)
+	}
+	return commonNotify(c, com, builder, logHash)
+}
+
+// commonNotify MUST!!! be called from within a transaction inside which
+// the provided Commit entity was retrieved from the datastore.
+func commonNotify(c appengine.Context, com *Commit, builder, logHash string) error {
+	if com.Num == 0 || com.Desc == "" {
+		stk := make([]byte, 10000)
+		n := runtime.Stack(stk, false)
+		stk = stk[:n]
+		c.Errorf("refusing to notify with com=%+v\n%s", *com, string(stk))
+		return fmt.Errorf("misuse of commonNotify")
+	}
+	if com.FailNotificationSent {
+		return nil
+	}
+	c.Infof("%s is broken commit; notifying", com.Hash)
+	notifyLater.Call(c, com, builder, logHash) // add task to queue
+	com.FailNotificationSent = true
+	return putCommit(c, com)
+}
+
+// sendFailMail sends a mail notification that the build failed on the
+// provided commit and builder.
+func sendFailMail(c appengine.Context, com *Commit, builder, logHash string) {
+	// get Log
+	k := datastore.NewKey(c, "Log", logHash, 0, nil)
+	l := new(Log)
+	if err := datastore.Get(c, k, l); err != nil {
+		c.Errorf("finding Log record %v: %v", logHash, err)
+		return
+	}
+	logText, err := l.Text()
+	if err != nil {
+		c.Errorf("unpacking Log record %v: %v", logHash, err)
+		return
+	}
+
+	// prepare mail message
+	var body bytes.Buffer
+	err = sendFailMailTmpl.Execute(&body, map[string]interface{}{
+		"Builder": builder, "Commit": com, "LogHash": logHash, "LogText": logText,
+		"Hostname": domain,
+	})
+	if err != nil {
+		c.Errorf("rendering mail template: %v", err)
+		return
+	}
+	subject := fmt.Sprintf("%s broken by %s", builder, shortDesc(com.Desc))
+	msg := &mail.Message{
+		Sender:  mailFrom,
+		To:      []string{failMailTo},
+		ReplyTo: failMailTo,
+		Subject: subject,
+		Body:    body.String(),
+	}
+
+	// send mail
+	if err := mail.Send(c, msg); err != nil {
+		c.Errorf("sending mail: %v", err)
+	}
+}
+
+type PerfChangeBenchmark struct {
+	Name    string
+	Metrics []*PerfChangeMetric
+}
+
+type PerfChangeMetric struct {
+	Name  string
+	Old   uint64
+	New   uint64
+	Delta float64
+}
+
+type PerfChangeBenchmarkSlice []*PerfChangeBenchmark
+
+func (l PerfChangeBenchmarkSlice) Len() int      { return len(l) }
+func (l PerfChangeBenchmarkSlice) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l PerfChangeBenchmarkSlice) Less(i, j int) bool {
+	b1, p1 := splitBench(l[i].Name)
+	b2, p2 := splitBench(l[j].Name)
+	if b1 != b2 {
+		return b1 < b2
+	}
+	return p1 < p2
+}
+
+type PerfChangeMetricSlice []*PerfChangeMetric
+
+func (l PerfChangeMetricSlice) Len() int           { return len(l) }
+func (l PerfChangeMetricSlice) Swap(i, j int)      { l[i], l[j] = l[j], l[i] }
+func (l PerfChangeMetricSlice) Less(i, j int) bool { return l[i].Name < l[j].Name }
+
+func sendPerfMailFunc(c appengine.Context, com *Commit, prevCommitHash, builder string, changes []*PerfChange) {
+	// Sort the changes into the right order.
+	var benchmarks []*PerfChangeBenchmark
+	for _, ch := range changes {
+		// Find the benchmark.
+		var b *PerfChangeBenchmark
+		for _, b1 := range benchmarks {
+			if b1.Name == ch.Bench {
+				b = b1
+				break
+			}
+		}
+		if b == nil {
+			b = &PerfChangeBenchmark{Name: ch.Bench}
+			benchmarks = append(benchmarks, b)
+		}
+		b.Metrics = append(b.Metrics, &PerfChangeMetric{Name: ch.Metric, Old: ch.Old, New: ch.New, Delta: ch.Diff})
+	}
+	for _, b := range benchmarks {
+		sort.Sort(PerfChangeMetricSlice(b.Metrics))
+	}
+	sort.Sort(PerfChangeBenchmarkSlice(benchmarks))
+
+	u := fmt.Sprintf("http://%v/perfdetail?commit=%v&commit0=%v&kind=builder&builder=%v", domain, com.Hash, prevCommitHash, builder)
+
+	// Prepare mail message (without Commit, for updateCL).
+	var body bytes.Buffer
+	err := sendPerfMailTmpl.Execute(&body, map[string]interface{}{
+		"Builder": builder, "Hostname": domain, "Url": u, "Benchmarks": benchmarks,
+	})
+	if err != nil {
+		c.Errorf("rendering perf mail template: %v", err)
+		return
+	}
+
+	// First, try to update the CL.
+	v := url.Values{"textmsg": {body.String()}}
+	if updateCL(c, com, v) {
+		return
+	}
+
+	// Otherwise, send mail (with Commit, for independent mail message).
+	body.Reset()
+	err = sendPerfMailTmpl.Execute(&body, map[string]interface{}{
+		"Builder": builder, "Commit": com, "Hostname": domain, "Url": u, "Benchmarks": benchmarks,
+	})
+	if err != nil {
+		c.Errorf("rendering perf mail template: %v", err)
+		return
+	}
+	subject := fmt.Sprintf("Perf changes on %s by %s", builder, shortDesc(com.Desc))
+	msg := &mail.Message{
+		Sender:  mailFrom,
+		To:      []string{failMailTo},
+		ReplyTo: failMailTo,
+		Subject: subject,
+		Body:    body.String(),
+	}
+
+	// send mail
+	if err := mail.Send(c, msg); err != nil {
+		c.Errorf("sending mail: %v", err)
+	}
+}
diff --git a/third_party/go.tools/dashboard/app/build/notify.txt b/third_party/go.tools/dashboard/app/build/notify.txt
new file mode 100644
index 0000000..514191f
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/notify.txt
@@ -0,0 +1,9 @@
+Change {{shortHash .Commit.Hash}} broke the {{.Builder}} build:
+http://{{.Hostname}}/log/{{.LogHash}}
+
+{{.Commit.Desc}}
+
+http://code.google.com/p/go/source/detail?r={{shortHash .Commit.Hash}}
+
+$ tail -200 < log
+{{printf "%s" .LogText | tail 200}}
diff --git a/third_party/go.tools/dashboard/app/build/perf.go b/third_party/go.tools/dashboard/app/build/perf.go
new file mode 100644
index 0000000..2c16e60
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/perf.go
@@ -0,0 +1,312 @@
+// Copyright 2014 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.
+
+// +build appengine
+
+package build
+
+import (
+	"fmt"
+	"sort"
+	"strconv"
+	"strings"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+var knownTags = map[string]string{
+	"go1":   "0051c7442fed9c888de6617fa9239a913904d96e",
+	"go1.1": "d29da2ced72ba2cf48ed6a8f1ec4abc01e4c5bf1",
+	"go1.2": "b1edf8faa5d6cbc50c6515785df9df9c19296564",
+	"go1.3": "f153208c0a0e306bfca14f71ef11f09859ccabc8",
+}
+
+var lastRelease = "go1.3"
+
+func splitBench(benchProcs string) (string, int) {
+	ss := strings.Split(benchProcs, "-")
+	procs, _ := strconv.Atoi(ss[1])
+	return ss[0], procs
+}
+
+func dashPerfCommits(c appengine.Context, page int) ([]*Commit, error) {
+	q := datastore.NewQuery("Commit").
+		Ancestor((&Package{}).Key(c)).
+		Order("-Num").
+		Filter("NeedsBenchmarking =", true).
+		Limit(commitsPerPage).
+		Offset(page * commitsPerPage)
+	var commits []*Commit
+	_, err := q.GetAll(c, &commits)
+	if err == nil && len(commits) == 0 {
+		err = fmt.Errorf("no commits")
+	}
+	return commits, err
+}
+
+func perfChangeStyle(pc *PerfConfig, v float64, builder, benchmark, metric string) string {
+	noise := pc.NoiseLevel(builder, benchmark, metric)
+	if isNoise(v, noise) {
+		return "noise"
+	}
+	if v > 0 {
+		return "bad"
+	}
+	return "good"
+}
+
+func isNoise(diff, noise float64) bool {
+	rnoise := -100 * noise / (noise + 100)
+	return diff < noise && diff > rnoise
+}
+
+func perfDiff(old, new uint64) float64 {
+	return 100*float64(new)/float64(old) - 100
+}
+
+func isPerfFailed(res *PerfResult, builder string) bool {
+	data := res.ParseData()[builder]
+	return data != nil && data["meta-done"] != nil && !data["meta-done"].OK
+}
+
+// PerfResultCache caches a set of PerfResults so that it's easy to access them
+// without lots of duplicate accesses to datastore.
+// It allows to iterate over newer or older results for some base commit.
+type PerfResultCache struct {
+	c       appengine.Context
+	newer   bool
+	iter    *datastore.Iterator
+	results map[int]*PerfResult
+}
+
+func MakePerfResultCache(c appengine.Context, com *Commit, newer bool) *PerfResultCache {
+	p := &Package{}
+	q := datastore.NewQuery("PerfResult").Ancestor(p.Key(c)).Limit(100)
+	if newer {
+		q = q.Filter("CommitNum >=", com.Num).Order("CommitNum")
+	} else {
+		q = q.Filter("CommitNum <=", com.Num).Order("-CommitNum")
+	}
+	rc := &PerfResultCache{c: c, newer: newer, iter: q.Run(c), results: make(map[int]*PerfResult)}
+	return rc
+}
+
+func (rc *PerfResultCache) Get(commitNum int) *PerfResult {
+	rc.Next(commitNum) // fetch the commit, if necessary
+	return rc.results[commitNum]
+}
+
+// Next returns the next PerfResult for the commit commitNum.
+// It does not care whether the result has any data, failed or whatever.
+func (rc *PerfResultCache) Next(commitNum int) (*PerfResult, error) {
+	// See if we have next result in the cache.
+	next := -1
+	for ci := range rc.results {
+		if rc.newer {
+			if ci > commitNum && (next == -1 || ci < next) {
+				next = ci
+			}
+		} else {
+			if ci < commitNum && (next == -1 || ci > next) {
+				next = ci
+			}
+		}
+	}
+	if next != -1 {
+		return rc.results[next], nil
+	}
+	// Fetch next result from datastore.
+	res := new(PerfResult)
+	_, err := rc.iter.Next(res)
+	if err == datastore.Done {
+		return nil, nil
+	}
+	if err != nil {
+		return nil, fmt.Errorf("fetching perf results: %v", err)
+	}
+	if (rc.newer && res.CommitNum < commitNum) || (!rc.newer && res.CommitNum > commitNum) {
+		rc.c.Errorf("PerfResultCache.Next: bad commit num")
+	}
+	rc.results[res.CommitNum] = res
+	return res, nil
+}
+
+// NextForComparison returns PerfResult which we need to use for performance comprison.
+// It skips failed results, but does not skip results with no data.
+func (rc *PerfResultCache) NextForComparison(commitNum int, builder string) (*PerfResult, error) {
+	for {
+		res, err := rc.Next(commitNum)
+		if err != nil {
+			return nil, err
+		}
+		if res == nil {
+			return nil, nil
+		}
+		if res.CommitNum == commitNum {
+			continue
+		}
+		parsed := res.ParseData()
+		if builder != "" {
+			// Comparing for a particular builder.
+			// This is used in perf_changes and in email notifications.
+			b := parsed[builder]
+			if b == nil || b["meta-done"] == nil {
+				// No results yet, must not do the comparison.
+				return nil, nil
+			}
+			if b["meta-done"].OK {
+				// Have complete results, compare.
+				return res, nil
+			}
+		} else {
+			// Comparing for all builders, find a result with at least
+			// one successful meta-done.
+			// This is used in perf_detail.
+			for _, benchs := range parsed {
+				if data := benchs["meta-done"]; data != nil && data.OK {
+					return res, nil
+				}
+			}
+		}
+		// Failed, try next result.
+		commitNum = res.CommitNum
+	}
+}
+
+type PerfChange struct {
+	Builder string
+	Bench   string
+	Metric  string
+	Old     uint64
+	New     uint64
+	Diff    float64
+}
+
+func significantPerfChanges(pc *PerfConfig, builder string, prevRes, res *PerfResult) (changes []*PerfChange) {
+	// First, collect all significant changes.
+	for builder1, benchmarks1 := range res.ParseData() {
+		if builder != "" && builder != builder1 {
+			// This is not the builder you're looking for, Luke.
+			continue
+		}
+		benchmarks0 := prevRes.ParseData()[builder1]
+		if benchmarks0 == nil {
+			continue
+		}
+		for benchmark, data1 := range benchmarks1 {
+			data0 := benchmarks0[benchmark]
+			if data0 == nil {
+				continue
+			}
+			for metric, val := range data1.Metrics {
+				val0 := data0.Metrics[metric]
+				if val0 == 0 {
+					continue
+				}
+				diff := perfDiff(val0, val)
+				noise := pc.NoiseLevel(builder, benchmark, metric)
+				if isNoise(diff, noise) {
+					continue
+				}
+				ch := &PerfChange{Builder: builder, Bench: benchmark, Metric: metric, Old: val0, New: val, Diff: diff}
+				changes = append(changes, ch)
+			}
+		}
+	}
+	// Then, strip non-repeatable changes (flakes).
+	// The hypothesis is that a real change must show up with the majority of GOMAXPROCS values.
+	majority := len(pc.ProcList(builder))/2 + 1
+	cnt := make(map[string]int)
+	for _, ch := range changes {
+		b, _ := splitBench(ch.Bench)
+		name := b + "|" + ch.Metric
+		if ch.Diff < 0 {
+			name += "--"
+		}
+		cnt[name] = cnt[name] + 1
+	}
+	for i := 0; i < len(changes); i++ {
+		ch := changes[i]
+		b, _ := splitBench(ch.Bench)
+		name := b + "|" + ch.Metric
+		if cnt[name] >= majority {
+			continue
+		}
+		if cnt[name+"--"] >= majority {
+			continue
+		}
+		// Remove flake.
+		last := len(changes) - 1
+		changes[i] = changes[last]
+		changes = changes[:last]
+		i--
+	}
+	return changes
+}
+
+// orderPerfTodo reorders commit nums for benchmarking todo.
+// The resulting order is somewhat tricky. We want 2 things:
+// 1. benchmark sequentially backwards (this provides information about most
+// recent changes, and allows to estimate noise levels)
+// 2. benchmark old commits in "scatter" order (this allows to quickly gather
+// brief information about thousands of old commits)
+// So this function interleaves the two orders.
+func orderPerfTodo(nums []int) []int {
+	sort.Ints(nums)
+	n := len(nums)
+	pow2 := uint32(0) // next power-of-two that is >= n
+	npow2 := 0
+	for npow2 <= n {
+		pow2++
+		npow2 = 1 << pow2
+	}
+	res := make([]int, n)
+	resPos := n - 1            // result array is filled backwards
+	present := make([]bool, n) // denotes values that already present in result array
+	for i0, i1 := n-1, 0; i0 >= 0 || i1 < npow2; {
+		// i0 represents "benchmark sequentially backwards" sequence
+		// find the next commit that is not yet present and add it
+		for cnt := 0; cnt < 2; cnt++ {
+			for ; i0 >= 0; i0-- {
+				if !present[i0] {
+					present[i0] = true
+					res[resPos] = nums[i0]
+					resPos--
+					i0--
+					break
+				}
+			}
+		}
+		// i1 represents "scatter order" sequence
+		// find the next commit that is not yet present and add it
+		for ; i1 < npow2; i1++ {
+			// do the "recursive split-ordering" trick
+			idx := 0 // bitwise reverse of i1
+			for j := uint32(0); j <= pow2; j++ {
+				if (i1 & (1 << j)) != 0 {
+					idx = idx | (1 << (pow2 - j - 1))
+				}
+			}
+			if idx < n && !present[idx] {
+				present[idx] = true
+				res[resPos] = nums[idx]
+				resPos--
+				i1++
+				break
+			}
+		}
+	}
+	// The above can't possibly be correct. Do dump check.
+	res2 := make([]int, n)
+	copy(res2, res)
+	sort.Ints(res2)
+	for i := range res2 {
+		if res2[i] != nums[i] {
+			panic(fmt.Sprintf("diff at %v: expect %v, want %v\nwas: %v\n become: %v",
+				i, nums[i], res2[i], nums, res2))
+		}
+	}
+	return res
+}
diff --git a/third_party/go.tools/dashboard/app/build/perf_changes.go b/third_party/go.tools/dashboard/app/build/perf_changes.go
new file mode 100644
index 0000000..4abbf1a
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/perf_changes.go
@@ -0,0 +1,282 @@
+// Copyright 2013 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.
+
+// +build appengine
+
+package build
+
+import (
+	"bytes"
+	"fmt"
+	"html/template"
+	"net/http"
+	"sort"
+	"strconv"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+func init() {
+	http.HandleFunc("/perf", perfChangesHandler)
+}
+
+// perfSummaryHandler draws the main benchmarking page.
+func perfChangesHandler(w http.ResponseWriter, r *http.Request) {
+	d := dashboardForRequest(r)
+	c := d.Context(appengine.NewContext(r))
+
+	page, _ := strconv.Atoi(r.FormValue("page"))
+	if page < 0 {
+		page = 0
+	}
+
+	pc, err := GetPerfConfig(c, r)
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	commits, err := dashPerfCommits(c, page)
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	// Fetch PerfResult's for the commits.
+	var uiCommits []*perfChangesCommit
+	rc := MakePerfResultCache(c, commits[0], false)
+
+	// But first compare tip with the last release.
+	if page == 0 {
+		res0 := &PerfResult{CommitHash: knownTags[lastRelease]}
+		if err := datastore.Get(c, res0.Key(c), res0); err != nil && err != datastore.ErrNoSuchEntity {
+			logErr(w, r, fmt.Errorf("getting PerfResult: %v", err))
+			return
+		}
+		if err != datastore.ErrNoSuchEntity {
+			uiCom, err := handleOneCommit(pc, commits[0], rc, res0)
+			if err != nil {
+				logErr(w, r, err)
+				return
+			}
+			uiCom.IsSummary = true
+			uiCom.ParentHash = lastRelease
+			uiCommits = append(uiCommits, uiCom)
+		}
+	}
+
+	for _, com := range commits {
+		uiCom, err := handleOneCommit(pc, com, rc, nil)
+		if err != nil {
+			logErr(w, r, err)
+			return
+		}
+		uiCommits = append(uiCommits, uiCom)
+	}
+
+	p := &Pagination{}
+	if len(commits) == commitsPerPage {
+		p.Next = page + 1
+	}
+	if page > 0 {
+		p.Prev = page - 1
+		p.HasPrev = true
+	}
+
+	data := &perfChangesData{d, p, uiCommits}
+
+	var buf bytes.Buffer
+	if err := perfChangesTemplate.Execute(&buf, data); err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	buf.WriteTo(w)
+}
+
+func handleOneCommit(pc *PerfConfig, com *Commit, rc *PerfResultCache, baseRes *PerfResult) (*perfChangesCommit, error) {
+	uiCom := new(perfChangesCommit)
+	uiCom.Commit = com
+	res1 := rc.Get(com.Num)
+	for builder, benchmarks1 := range res1.ParseData() {
+		for benchmark, data1 := range benchmarks1 {
+			if benchmark != "meta-done" || !data1.OK {
+				uiCom.NumResults++
+			}
+			if !data1.OK {
+				v := new(perfChangesChange)
+				v.diff = 10000
+				v.Style = "fail"
+				v.Builder = builder
+				v.Link = fmt.Sprintf("log/%v", data1.Artifacts["log"])
+				v.Val = builder
+				v.Hint = builder
+				if benchmark != "meta-done" {
+					v.Hint += "/" + benchmark
+				}
+				m := findMetric(uiCom, "failure")
+				m.BadChanges = append(m.BadChanges, v)
+			}
+		}
+		res0 := baseRes
+		if res0 == nil {
+			var err error
+			res0, err = rc.NextForComparison(com.Num, builder)
+			if err != nil {
+				return nil, err
+			}
+			if res0 == nil {
+				continue
+			}
+		}
+		changes := significantPerfChanges(pc, builder, res0, res1)
+		changes = dedupPerfChanges(changes)
+		for _, ch := range changes {
+			v := new(perfChangesChange)
+			v.Builder = builder
+			v.Benchmark, v.Procs = splitBench(ch.Bench)
+			v.diff = ch.Diff
+			v.Val = fmt.Sprintf("%+.2f%%", ch.Diff)
+			v.Hint = fmt.Sprintf("%v/%v", builder, ch.Bench)
+			v.Link = fmt.Sprintf("perfdetail?commit=%v&commit0=%v&builder=%v&benchmark=%v", com.Hash, res0.CommitHash, builder, v.Benchmark)
+			m := findMetric(uiCom, ch.Metric)
+			if v.diff > 0 {
+				v.Style = "bad"
+				m.BadChanges = append(m.BadChanges, v)
+			} else {
+				v.Style = "good"
+				m.GoodChanges = append(m.GoodChanges, v)
+			}
+		}
+	}
+
+	// Sort metrics and changes.
+	for _, m := range uiCom.Metrics {
+		sort.Sort(m.GoodChanges)
+		sort.Sort(m.BadChanges)
+	}
+	sort.Sort(uiCom.Metrics)
+	// Need at least one metric for UI.
+	if len(uiCom.Metrics) == 0 {
+		uiCom.Metrics = append(uiCom.Metrics, &perfChangesMetric{})
+	}
+	uiCom.Metrics[0].First = true
+	return uiCom, nil
+}
+
+// Find builder-procs with the maximum absolute diff for every benchmark-metric, drop the rest.
+func dedupPerfChanges(changes []*PerfChange) (deduped []*PerfChange) {
+	maxDiff := make(map[string]float64)
+	maxBench := make(map[string]string)
+	// First, find the maximum.
+	for _, ch := range changes {
+		bench, _ := splitBench(ch.Bench)
+		k := bench + "|" + ch.Metric
+		v := ch.Diff
+		if v < 0 {
+			v = -v
+		}
+		if maxDiff[k] < v {
+			maxDiff[k] = v
+			maxBench[k] = ch.Builder + "|" + ch.Bench
+		}
+	}
+	// Then, remove the rest.
+	for _, ch := range changes {
+		bench, _ := splitBench(ch.Bench)
+		k := bench + "|" + ch.Metric
+		if maxBench[k] == ch.Builder+"|"+ch.Bench {
+			deduped = append(deduped, ch)
+		}
+	}
+	return
+}
+
+func findMetric(c *perfChangesCommit, metric string) *perfChangesMetric {
+	for _, m := range c.Metrics {
+		if m.Name == metric {
+			return m
+		}
+	}
+	m := new(perfChangesMetric)
+	m.Name = metric
+	c.Metrics = append(c.Metrics, m)
+	return m
+}
+
+type uiPerfConfig struct {
+	Builders    []uiPerfConfigElem
+	Benchmarks  []uiPerfConfigElem
+	Metrics     []uiPerfConfigElem
+	Procs       []uiPerfConfigElem
+	CommitsFrom []uiPerfConfigElem
+	CommitsTo   []uiPerfConfigElem
+}
+
+type uiPerfConfigElem struct {
+	Name     string
+	Selected bool
+}
+
+var perfChangesTemplate = template.Must(
+	template.New("perf_changes.html").Funcs(tmplFuncs).ParseFiles("build/perf_changes.html"),
+)
+
+type perfChangesData struct {
+	Dashboard  *Dashboard
+	Pagination *Pagination
+	Commits    []*perfChangesCommit
+}
+
+type perfChangesCommit struct {
+	*Commit
+	IsSummary  bool
+	NumResults int
+	Metrics    perfChangesMetricSlice
+}
+
+type perfChangesMetric struct {
+	Name        string
+	First       bool
+	BadChanges  perfChangesChangeSlice
+	GoodChanges perfChangesChangeSlice
+}
+
+type perfChangesChange struct {
+	Builder   string
+	Benchmark string
+	Link      string
+	Hint      string
+	Style     string
+	Val       string
+	Procs     int
+	diff      float64
+}
+
+type perfChangesMetricSlice []*perfChangesMetric
+
+func (l perfChangesMetricSlice) Len() int      { return len(l) }
+func (l perfChangesMetricSlice) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l perfChangesMetricSlice) Less(i, j int) bool {
+	if l[i].Name == "failure" || l[j].Name == "failure" {
+		return l[i].Name == "failure"
+	}
+	return l[i].Name < l[j].Name
+}
+
+type perfChangesChangeSlice []*perfChangesChange
+
+func (l perfChangesChangeSlice) Len() int      { return len(l) }
+func (l perfChangesChangeSlice) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l perfChangesChangeSlice) Less(i, j int) bool {
+	vi, vj := l[i].diff, l[j].diff
+	if vi > 0 && vj > 0 {
+		return vi > vj
+	} else if vi < 0 && vj < 0 {
+		return vi < vj
+	} else {
+		panic("comparing positive and negative diff")
+	}
+}
diff --git a/third_party/go.tools/dashboard/app/build/perf_changes.html b/third_party/go.tools/dashboard/app/build/perf_changes.html
new file mode 100644
index 0000000..24f0534
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/perf_changes.html
@@ -0,0 +1,89 @@
+<!doctype html>
+<html>
+<head>
+    <title>{{$.Dashboard.Name}} Dashboard</title>
+    <link rel="stylesheet" href="/static/style.css"/>
+</head>
+<body>
+   <header id="topbar">   
+    <h1>Go Dashboard</h1>
+    <nav>
+      <a href="{{$.Dashboard.RelPath}}">Test</a>
+      <a href="{{$.Dashboard.RelPath}}perf">Perf</a>
+      <a href="{{$.Dashboard.RelPath}}perfgraph">Graphs</a>
+    </nav>
+    <div class="clear"></div>
+  </header>
+ 
+  <div class="page">
+    <div class="build-container">
+      <table class="build">
+        <colgroup class="col-hash"></colgroup>
+        <colgroup class="col-numresults"></colgroup>
+        <colgroup class="col-metric"></colgroup>
+        <colgroup class="col-result"></colgroup>
+        <colgroup class="col-result"></colgroup>
+        <colgroup class="col-user"></colgroup>
+        <colgroup class="col-time"></colgroup>
+        <colgroup class="col-desc"></colgroup>
+       <tbody>
+        {{range $c := $.Commits}}
+          {{range $m := $c.Metrics}}
+            {{if $m.First}}
+              <tr class="row-commit">
+                {{if $c.IsSummary}}
+                  <td class="hash">tip vs {{$c.ParentHash}}</td>
+                {{else}}
+                  <td class="hash"><a href="{{repoURL $.Dashboard.Name $c.Hash ""}}">{{shortHash $c.Hash}}</a></td>
+                {{end}}
+                <td class="numresults">{{$c.NumResults}}</td>
+            {{else}}
+              <tr>
+                <td class="user">&nbsp;</td>
+                <td class="numresults">&nbsp;</td>
+            {{end}}
+              <td>{{$m.Name}}</td>
+              <td>
+                {{range $ch := $m.BadChanges}}
+                  <a class="{{$ch.Style}}" href="{{$ch.Link}}" title="{{$ch.Hint}}">{{$ch.Val}}</a> &nbsp;
+                {{end}}
+              </td>
+              <td>
+                {{range $ch := $m.GoodChanges}}
+                  <a class="{{$ch.Style}}" href="{{$ch.Link}}" title="{{$ch.Hint}}">{{$ch.Val}}</a> &nbsp;
+                {{end}}
+              </td>
+            {{if $m.First}}
+              <td class="user" title="{{$c.User}}">{{shortUser $c.User}}</td>
+              <td class="time">{{$c.Time.Format "Mon 02 Jan 15:04"}}</td>
+              <td class="desc" title="{{$c.Desc}}">{{shortDesc $c.Desc}}</td>
+            {{else}}
+              <td class="user">&nbsp;</td>
+              <td class="time">&nbsp;</td>
+              <td class="desc">&nbsp;</td>
+            {{end}}
+              </tr>
+          {{end}}
+          {{if $c.IsSummary}}
+            <tr class="row-commit"><td>---</td></tr>
+          {{end}}
+        {{end}}
+      </tbody>
+    </table>
+
+    {{with $.Pagination}}
+    <div class="paginate">
+      <nav>
+        <a {{if .HasPrev}}href="?page={{.Prev}}"{{else}}class="inactive"{{end}}>newer</a>
+        <a {{if .Next}}href="?page={{.Next}}"{{else}}class="inactive"{{end}}>older</a>
+        <a {{if .HasPrev}}href="?"{{else}}class="inactive"{{end}}>latest</a>
+        <a href="https://code.google.com/p/go-wiki/wiki/PerfDashboard">Help</a>
+      </nav>
+    </div>
+    {{end}}
+
+  </div>
+  <div class="clear"></div>
+</div>
+</body>
+</html>
diff --git a/third_party/go.tools/dashboard/app/build/perf_detail.go b/third_party/go.tools/dashboard/app/build/perf_detail.go
new file mode 100644
index 0000000..f8d9bfd
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/perf_detail.go
@@ -0,0 +1,221 @@
+// Copyright 2013 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.
+
+// +build appengine
+
+package build
+
+import (
+	"bytes"
+	"fmt"
+	"html/template"
+	"net/http"
+	"sort"
+	"strconv"
+	"strings"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+func init() {
+	for _, d := range dashboards {
+		http.HandleFunc(d.RelPath+"perfdetail", perfDetailUIHandler)
+	}
+}
+
+func perfDetailUIHandler(w http.ResponseWriter, r *http.Request) {
+	d := dashboardForRequest(r)
+	c := d.Context(appengine.NewContext(r))
+	pc, err := GetPerfConfig(c, r)
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	kind := r.FormValue("kind")
+	builder := r.FormValue("builder")
+	benchmark := r.FormValue("benchmark")
+	if kind == "" {
+		kind = "benchmark"
+	}
+	if kind != "benchmark" && kind != "builder" {
+		logErr(w, r, fmt.Errorf("unknown kind %s", kind))
+		return
+	}
+
+	// Fetch the new commit.
+	com1 := new(Commit)
+	com1.Hash = r.FormValue("commit")
+	if hash, ok := knownTags[com1.Hash]; ok {
+		com1.Hash = hash
+	}
+	if err := datastore.Get(c, com1.Key(c), com1); err != nil {
+		logErr(w, r, fmt.Errorf("failed to fetch commit %s: %v", com1.Hash, err))
+		return
+	}
+	// Fetch the associated perf result.
+	ress1 := &PerfResult{CommitHash: com1.Hash}
+	if err := datastore.Get(c, ress1.Key(c), ress1); err != nil {
+		logErr(w, r, fmt.Errorf("failed to fetch perf result %s: %v", com1.Hash, err))
+		return
+	}
+
+	// Fetch the old commit.
+	var ress0 *PerfResult
+	com0 := new(Commit)
+	com0.Hash = r.FormValue("commit0")
+	if hash, ok := knownTags[com0.Hash]; ok {
+		com0.Hash = hash
+	}
+	if com0.Hash != "" {
+		// Have an exact commit hash, fetch directly.
+		if err := datastore.Get(c, com0.Key(c), com0); err != nil {
+			logErr(w, r, fmt.Errorf("failed to fetch commit %s: %v", com0.Hash, err))
+			return
+		}
+		ress0 = &PerfResult{CommitHash: com0.Hash}
+		if err := datastore.Get(c, ress0.Key(c), ress0); err != nil {
+			logErr(w, r, fmt.Errorf("failed to fetch perf result for %s: %v", com0.Hash, err))
+			return
+		}
+	} else {
+		// Don't have the commit hash, find the previous commit to compare.
+		rc := MakePerfResultCache(c, com1, false)
+		ress0, err = rc.NextForComparison(com1.Num, "")
+		if err != nil {
+			logErr(w, r, err)
+			return
+		}
+		if ress0 == nil {
+			logErr(w, r, fmt.Errorf("no previous commit with results"))
+			return
+		}
+		// Now that we know the right result, fetch the commit.
+		com0.Hash = ress0.CommitHash
+		if err := datastore.Get(c, com0.Key(c), com0); err != nil {
+			logErr(w, r, fmt.Errorf("failed to fetch commit %s: %v", com0.Hash, err))
+			return
+		}
+	}
+
+	res0 := ress0.ParseData()
+	res1 := ress1.ParseData()
+	var benchmarks []*uiPerfDetailBenchmark
+	var list []string
+	if kind == "builder" {
+		list = pc.BenchmarksForBuilder(builder)
+	} else {
+		list = pc.BuildersForBenchmark(benchmark)
+	}
+	for _, other := range list {
+		if kind == "builder" {
+			benchmark = other
+		} else {
+			builder = other
+		}
+		var procs []*uiPerfDetailProcs
+		allProcs := pc.ProcList(builder)
+		for _, p := range allProcs {
+			BenchProcs := fmt.Sprintf("%v-%v", benchmark, p)
+			if res0[builder] == nil || res0[builder][BenchProcs] == nil {
+				continue
+			}
+			pp := &uiPerfDetailProcs{Procs: p}
+			for metric, val := range res0[builder][BenchProcs].Metrics {
+				var pm uiPerfDetailMetric
+				pm.Name = metric
+				pm.Val0 = fmt.Sprintf("%v", val)
+				val1 := uint64(0)
+				if res1[builder] != nil && res1[builder][BenchProcs] != nil {
+					val1 = res1[builder][BenchProcs].Metrics[metric]
+				}
+				pm.Val1 = fmt.Sprintf("%v", val1)
+				v0 := val
+				v1 := val1
+				valf := perfDiff(v0, v1)
+				pm.Delta = fmt.Sprintf("%+.2f%%", valf)
+				pm.Style = perfChangeStyle(pc, valf, builder, BenchProcs, pm.Name)
+				pp.Metrics = append(pp.Metrics, pm)
+			}
+			sort.Sort(pp.Metrics)
+			for artifact, hash := range res0[builder][BenchProcs].Artifacts {
+				var pm uiPerfDetailMetric
+				pm.Val0 = fmt.Sprintf("%v", artifact)
+				pm.Link0 = fmt.Sprintf("log/%v", hash)
+				pm.Val1 = fmt.Sprintf("%v", artifact)
+				if res1[builder] != nil && res1[builder][BenchProcs] != nil && res1[builder][BenchProcs].Artifacts[artifact] != "" {
+					pm.Link1 = fmt.Sprintf("log/%v", res1[builder][BenchProcs].Artifacts[artifact])
+				}
+				pp.Metrics = append(pp.Metrics, pm)
+			}
+			procs = append(procs, pp)
+		}
+		benchmarks = append(benchmarks, &uiPerfDetailBenchmark{other, procs})
+	}
+
+	cfg := new(uiPerfConfig)
+	for _, v := range pc.BuildersForBenchmark("") {
+		cfg.Builders = append(cfg.Builders, uiPerfConfigElem{v, v == builder})
+	}
+	for _, v := range pc.BenchmarksForBuilder("") {
+		cfg.Benchmarks = append(cfg.Benchmarks, uiPerfConfigElem{v, v == benchmark})
+	}
+
+	data := &uiPerfDetailTemplateData{d, cfg, kind == "builder", com0, com1, benchmarks}
+
+	var buf bytes.Buffer
+	if err := uiPerfDetailTemplate.Execute(&buf, data); err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	buf.WriteTo(w)
+}
+
+func perfResultSplit(s string) (builder string, benchmark string, procs int) {
+	s1 := strings.Split(s, "|")
+	s2 := strings.Split(s1[1], "-")
+	procs, _ = strconv.Atoi(s2[1])
+	return s1[0], s2[0], procs
+}
+
+type uiPerfDetailTemplateData struct {
+	Dashboard   *Dashboard
+	Config      *uiPerfConfig
+	KindBuilder bool
+	Commit0     *Commit
+	Commit1     *Commit
+	Benchmarks  []*uiPerfDetailBenchmark
+}
+
+type uiPerfDetailBenchmark struct {
+	Name  string
+	Procs []*uiPerfDetailProcs
+}
+
+type uiPerfDetailProcs struct {
+	Procs   int
+	Metrics uiPerfDetailMetrics
+}
+
+type uiPerfDetailMetric struct {
+	Name  string
+	Val0  string
+	Val1  string
+	Link0 string
+	Link1 string
+	Delta string
+	Style string
+}
+
+type uiPerfDetailMetrics []uiPerfDetailMetric
+
+func (l uiPerfDetailMetrics) Len() int           { return len(l) }
+func (l uiPerfDetailMetrics) Swap(i, j int)      { l[i], l[j] = l[j], l[i] }
+func (l uiPerfDetailMetrics) Less(i, j int) bool { return l[i].Name < l[j].Name }
+
+var uiPerfDetailTemplate = template.Must(
+	template.New("perf_detail.html").Funcs(tmplFuncs).ParseFiles("build/perf_detail.html"),
+)
diff --git a/third_party/go.tools/dashboard/app/build/perf_detail.html b/third_party/go.tools/dashboard/app/build/perf_detail.html
new file mode 100644
index 0000000..18b3028
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/perf_detail.html
@@ -0,0 +1,101 @@
+<!doctype html>
+<html>
+<head>
+    <title>{{$.Dashboard.Name}} Dashboard</title>
+    <link rel="stylesheet" href="/static/style.css"/>
+    <script type="text/javascript">
+      function kindBuilder() {
+        document.getElementById('checkBuilder').checked = true;
+        document.getElementById('controlBuilder').style.display='inline';
+        document.getElementById('controlBenchmark').style.display='none';
+      }
+      function kindBenchmark() {
+        document.getElementById('checkBenchmark').checked = true;
+        document.getElementById('controlBenchmark').style.display='inline';
+        document.getElementById('controlBuilder').style.display='none';
+      }
+      window.onload = {{if $.KindBuilder}} kindBuilder {{else}} kindBenchmark {{end}};
+    </script>
+</head>
+<body>
+  <header id="topbar">
+    <h1>Go Dashboard</h1>
+    <nav>
+        <a href="{{$.Dashboard.RelPath}}">Test</a>
+        <a href="{{$.Dashboard.RelPath}}perf">Perf</a>
+        <a href="{{$.Dashboard.RelPath}}perfgraph">Graphs</a>
+    </nav>
+    <div class="clear"></div>
+  </header>
+ 
+  <div class="page">
+    <div class="diff-container">
+      <div class="diff-meta">
+        <form>
+          <div><b>New: </b><input type="edit" name="commit" value="{{$.Commit1.Hash}}" /> {{shortUser $.Commit1.User}} {{$.Commit1.Time.Format "Mon 02 Jan 15:04"}} {{shortDesc $.Commit1.Desc}} </div>
+          <div><b>Old: </b><input type="edit" name="commit0" value="{{$.Commit0.Hash}}" /> {{shortUser $.Commit0.User}} {{$.Commit0.Time.Format "Mon 02 Jan 15:04"}} {{shortDesc $.Commit0.Desc}} </div>
+          <div>
+            <input id="checkBuilder" type="radio" name="kind" value="builder" required onclick="kindBuilder()">builder</input>
+            <input id="checkBenchmark" type="radio" name="kind" value="benchmark" required onclick="kindBenchmark()">benchmark</input>
+            <select id="controlBuilder" name="builder">
+              {{range $.Config.Builders}}
+                <option {{if .Selected}}selected{{end}}>{{.Name}}</option>
+              {{end}}
+            </select>
+            <select id="controlBenchmark" name="benchmark">
+              {{range $.Config.Benchmarks}}
+                <option {{if .Selected}}selected{{end}}>{{.Name}}</option>
+              {{end}}
+            </select>
+            <input type="submit" value="Refresh" />
+            <a href="https://code.google.com/p/go-wiki/wiki/PerfDashboard">Help</a>
+          </div>
+        </form>
+      </div>
+      <p></p>
+
+    {{range $b := $.Benchmarks}}
+      <div class="diff-benchmark">
+      <h2>{{$b.Name}}</h2>
+      {{range $p := $b.Procs}}
+      <div class="diff">
+        <h1>GOMAXPROCS={{$p.Procs}}</h1>
+        <table>
+          <thead>
+            <tr>
+              <th>Metric</th>
+              <th>old</th>
+              <th>new</th>
+              <th>delta</th>
+            </tr>
+          </thead>
+          <tbody>
+            {{range $m := $p.Metrics}}
+            <tr>
+              <td class="metric">{{$m.Name}}</td>
+              {{if $m.Link0}}
+                <td><a href="{{$.Dashboard.RelPath}}{{$m.Link0}}">{{$m.Val0}}</td>
+              {{else}}
+                <td>{{$m.Val0}}</td>
+              {{end}}
+              {{if $m.Link1}}
+                <td><a href="{{$.Dashboard.RelPath}}{{$m.Link1}}">{{$m.Val1}}</td>
+              {{else}}
+                <td>{{$m.Val1}}</td>
+              {{end}}
+              <td class="result"><span class="{{$m.Style}}">{{$m.Delta}}</span></td>
+            </tr>
+            {{end}}
+          </tbody>
+        </table>
+      </div>
+      {{end}}
+      </div>
+    {{end}}
+
+      <div class="clear"></div>
+    </div>
+    <div class="clear"></div>
+  </div>
+</body>
+</html>
diff --git a/third_party/go.tools/dashboard/app/build/perf_graph.go b/third_party/go.tools/dashboard/app/build/perf_graph.go
new file mode 100644
index 0000000..81eb5e1
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/perf_graph.go
@@ -0,0 +1,270 @@
+// Copyright 2013 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.
+
+// +build appengine
+
+package build
+
+import (
+	"bytes"
+	"fmt"
+	"html/template"
+	"net/http"
+	"strconv"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+func init() {
+	for _, d := range dashboards {
+		http.HandleFunc(d.RelPath+"perfgraph", perfGraphHandler)
+	}
+}
+
+func perfGraphHandler(w http.ResponseWriter, r *http.Request) {
+	d := dashboardForRequest(r)
+	c := d.Context(appengine.NewContext(r))
+	pc, err := GetPerfConfig(c, r)
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+	allBuilders := pc.BuildersForBenchmark("")
+	allBenchmarks := pc.BenchmarksForBuilder("")
+	allMetrics := pc.MetricsForBenchmark("")
+	allProcs := pc.ProcList("")
+	r.ParseForm()
+	selBuilders := r.Form["builder"]
+	selBenchmarks := r.Form["benchmark"]
+	selMetrics := r.Form["metric"]
+	selProcs := r.Form["procs"]
+	if len(selBuilders) == 0 {
+		selBuilders = append(selBuilders, allBuilders[0])
+	}
+	if len(selBenchmarks) == 0 {
+		selBenchmarks = append(selBenchmarks, "json")
+	}
+	if len(selMetrics) == 0 {
+		selMetrics = append(selMetrics, "time")
+	}
+	if len(selProcs) == 0 {
+		selProcs = append(selProcs, "1")
+	}
+	commitFrom := r.FormValue("commit-from")
+	if commitFrom == "" {
+		commitFrom = lastRelease
+	}
+	commitTo := r.FormValue("commit-to")
+	if commitTo == "" {
+		commitTo = "tip"
+	}
+	// TODO(dvyukov): validate input
+
+	// Figure out start and end commit from commitFrom/commitTo.
+	startCommitNum := 0
+	endCommitNum := 0
+	{
+		comFrom := &Commit{Hash: knownTags[commitFrom]}
+		if err := datastore.Get(c, comFrom.Key(c), comFrom); err != nil {
+			logErr(w, r, err)
+			return
+		}
+		startCommitNum = comFrom.Num
+
+	retry:
+		if commitTo == "tip" {
+			p, err := GetPackage(c, "")
+			if err != nil {
+				logErr(w, r, err)
+				return
+			}
+			endCommitNum = p.NextNum
+		} else {
+			comTo := &Commit{Hash: knownTags[commitTo]}
+			if err := datastore.Get(c, comTo.Key(c), comTo); err != nil {
+				logErr(w, r, err)
+				return
+			}
+			endCommitNum = comTo.Num + 1
+		}
+		if endCommitNum <= startCommitNum {
+			// User probably selected from:go1.3 to:go1.2. Fix go1.2 to tip.
+			if commitTo == "tip" {
+				logErr(w, r, fmt.Errorf("no commits to display (%v-%v)", commitFrom, commitTo))
+				return
+			}
+			commitTo = "tip"
+			goto retry
+		}
+	}
+	commitsToDisplay := endCommitNum - startCommitNum
+
+	present := func(set []string, s string) bool {
+		for _, s1 := range set {
+			if s1 == s {
+				return true
+			}
+		}
+		return false
+	}
+
+	cfg := &uiPerfConfig{}
+	for _, v := range allBuilders {
+		cfg.Builders = append(cfg.Builders, uiPerfConfigElem{v, present(selBuilders, v)})
+	}
+	for _, v := range allBenchmarks {
+		cfg.Benchmarks = append(cfg.Benchmarks, uiPerfConfigElem{v, present(selBenchmarks, v)})
+	}
+	for _, v := range allMetrics {
+		cfg.Metrics = append(cfg.Metrics, uiPerfConfigElem{v, present(selMetrics, v)})
+	}
+	for _, v := range allProcs {
+		cfg.Procs = append(cfg.Procs, uiPerfConfigElem{strconv.Itoa(v), present(selProcs, strconv.Itoa(v))})
+	}
+	for k := range knownTags {
+		cfg.CommitsFrom = append(cfg.CommitsFrom, uiPerfConfigElem{k, commitFrom == k})
+	}
+	for k := range knownTags {
+		cfg.CommitsTo = append(cfg.CommitsTo, uiPerfConfigElem{k, commitTo == k})
+	}
+	cfg.CommitsTo = append(cfg.CommitsTo, uiPerfConfigElem{"tip", commitTo == "tip"})
+
+	var vals [][]float64
+	var hints [][]string
+	var annotations [][]string
+	var certainty [][]bool
+	var headers []string
+	commits2, err := GetCommits(c, startCommitNum, commitsToDisplay)
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+	for _, builder := range selBuilders {
+		for _, metric := range selMetrics {
+			for _, benchmark := range selBenchmarks {
+				for _, procs := range selProcs {
+					benchProcs := fmt.Sprintf("%v-%v", benchmark, procs)
+					vv, err := GetPerfMetricsForCommits(c, builder, benchProcs, metric, startCommitNum, commitsToDisplay)
+					if err != nil {
+						logErr(w, r, err)
+						return
+					}
+					hasdata := false
+					for _, v := range vv {
+						if v != 0 {
+							hasdata = true
+						}
+					}
+					if hasdata {
+						noise := pc.NoiseLevel(builder, benchProcs, metric)
+						descBuilder := "/" + builder
+						descBenchmark := "/" + benchProcs
+						descMetric := "/" + metric
+						if len(selBuilders) == 1 {
+							descBuilder = ""
+						}
+						if len(selBenchmarks) == 1 && len(selProcs) == 1 {
+							descBenchmark = ""
+						}
+						if len(selMetrics) == 1 && (len(selBuilders) > 1 || len(selBenchmarks) > 1 || len(selProcs) > 1) {
+							descMetric = ""
+						}
+						desc := fmt.Sprintf("%v%v%v", descBuilder, descBenchmark, descMetric)[1:]
+						hh := make([]string, commitsToDisplay)
+						ann := make([]string, commitsToDisplay)
+						valf := make([]float64, commitsToDisplay)
+						cert := make([]bool, commitsToDisplay)
+						firstval := uint64(0)
+						lastval := uint64(0)
+						for i, v := range vv {
+							cert[i] = true
+							if v == 0 {
+								if lastval == 0 {
+									continue
+								}
+								cert[i] = false
+								v = lastval
+							}
+							if firstval == 0 {
+								firstval = v
+							}
+							valf[i] = float64(v) / float64(firstval)
+							if cert[i] {
+								d := ""
+								if lastval != 0 {
+									diff := perfDiff(lastval, v)
+									d = fmt.Sprintf(" (%+.02f%%)", diff)
+									if !isNoise(diff, noise) {
+										ann[i] = fmt.Sprintf("%+.02f%%", diff)
+									}
+								}
+								hh[i] = fmt.Sprintf("%v%v", v, d)
+							} else {
+								hh[i] = "NO DATA"
+							}
+							lastval = v
+						}
+						vals = append(vals, valf)
+						hints = append(hints, hh)
+						annotations = append(annotations, ann)
+						certainty = append(certainty, cert)
+						headers = append(headers, desc)
+					}
+				}
+			}
+		}
+	}
+
+	var commits []perfGraphCommit
+	if len(vals) != 0 && len(vals[0]) != 0 {
+		idx := 0
+		for i := range vals[0] {
+			com := commits2[i]
+			if com == nil || !com.NeedsBenchmarking {
+				continue
+			}
+			c := perfGraphCommit{Id: idx, Name: fmt.Sprintf("%v (%v)", com.Desc, com.Time.Format("Jan 2, 2006 1:04"))}
+			idx++
+			for j := range vals {
+				c.Vals = append(c.Vals, perfGraphValue{float64(vals[j][i]), certainty[j][i], hints[j][i], annotations[j][i]})
+			}
+			commits = append(commits, c)
+		}
+	}
+
+	data := &perfGraphData{d, cfg, headers, commits}
+
+	var buf bytes.Buffer
+	if err := perfGraphTemplate.Execute(&buf, data); err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	buf.WriteTo(w)
+}
+
+var perfGraphTemplate = template.Must(
+	template.New("perf_graph.html").ParseFiles("build/perf_graph.html"),
+)
+
+type perfGraphData struct {
+	Dashboard *Dashboard
+	Config    *uiPerfConfig
+	Headers   []string
+	Commits   []perfGraphCommit
+}
+
+type perfGraphCommit struct {
+	Id   int
+	Name string
+	Vals []perfGraphValue
+}
+
+type perfGraphValue struct {
+	Val       float64
+	Certainty bool
+	Hint      string
+	Ann       string
+}
diff --git a/third_party/go.tools/dashboard/app/build/perf_graph.html b/third_party/go.tools/dashboard/app/build/perf_graph.html
new file mode 100644
index 0000000..da1c0d0
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/perf_graph.html
@@ -0,0 +1,120 @@
+<!doctype html>
+<html>
+  <head>
+    <title>{{$.Dashboard.Name}} Dashboard</title>
+    <link rel="stylesheet" href="/static/style.css"/>
+    <style>
+      .graph-container { background: #eee; }
+    </style>
+
+    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+    <script type="text/javascript">
+      google.load("visualization", "1", {packages:["corechart"]});
+      google.setOnLoadCallback(drawCharts);
+      function drawCharts() {
+        var data = new google.visualization.DataTable();
+        data.addColumn({type: 'number', label: 'Commit'});
+        data.addColumn({type: 'number'});
+        data.addColumn({type: 'string', role: 'tooltip'});
+        {{range $.Headers}}
+          data.addColumn({type: 'number', label: '{{.}}'});
+          data.addColumn({type: 'boolean', role: 'certainty'});
+          data.addColumn({type: 'string', role: 'tooltip'});
+          data.addColumn({type: 'string', role: 'annotation'});
+        {{end}}
+        data.addRows([
+        {{range $.Commits}}
+          [ {{.Id}}, 1, "{{.Name}}",
+            {{range .Vals}}
+              {{if .Val}}
+                {{.Val}}, {{.Certainty}}, '{{.Hint}}', '{{.Ann}}',
+              {{else}}
+                ,,,,
+              {{end}}
+            {{end}}
+          ],
+        {{end}}
+      ]);
+      new google.visualization.LineChart(document.getElementById('graph_div')).
+        draw(data, {
+          width: "100%",
+          height: 700,
+          legend: {position: "bottom"},
+          focusTarget: "category",
+          hAxis: {textPosition: "none"},
+          chartArea: {left: "10%", top: "5%", width: "85%", height:"80%"},
+          explorer: {axis: 'horizontal', maxZoomIn: 0, maxZoomOut: 1, zoomDelta: 1.2, keepInBounds: true}
+        })
+      }
+    </script>
+</head>
+<body>
+ 
+   <header id="topbar">   
+    <h1>Go Dashboard</h1>
+    <nav>
+        <a href="{{$.Dashboard.RelPath}}">Test</a>
+        <a href="{{$.Dashboard.RelPath}}perf">Perf</a>
+        <a href="{{$.Dashboard.RelPath}}perfgraph">Graphs</a>
+    </nav>
+    <div class="clear"></div>
+  </header>
+ 
+  <div class="page">
+    <div id="graph_div" class="main-content graph-container">
+    </div>
+
+    <aside>
+      <form>
+        <div class="panel">
+          <h1>Builders</h1>
+            {{range $.Config.Builders}}
+              <input type="checkbox" name="builder" value="{{.Name}}" {{if .Selected}}checked{{end}}>{{.Name}}</input><br>
+            {{end}}
+        </div>
+
+        <div class="panel">
+          <h1>Benchmarks</h1>
+            {{range $.Config.Benchmarks}}
+              <input type="checkbox" name="benchmark" value="{{.Name}}" {{if .Selected}}checked{{end}}>{{.Name}}</input><br>
+            {{end}}
+        </div>
+
+        <div class="panel">
+          <h1>Procs</h1>
+            {{range $.Config.Procs}}
+              <input type="checkbox" name="procs" value="{{.Name}}" {{if .Selected}}checked{{end}}>{{.Name}}</input><br>
+            {{end}}
+        </div>
+
+        <div class="panel">
+          <h1>Metrics</h1>
+            {{range $.Config.Metrics}}
+              <input type="checkbox" name="metric" value="{{.Name}}" {{if .Selected}}checked{{end}}>{{.Name}}</input><br>
+            {{end}}
+        </div>
+
+        <div class="panel">
+          <h1>Commits</h1>
+          <b>From:</b>
+          <select required name="commit-from">
+            {{range $.Config.CommitsFrom}}
+              <option {{if .Selected}}selected{{end}}>{{.Name}}</option>
+            {{end}}
+          </select>
+          <b>To:</b>
+          <select required name="commit-to">
+            {{range $.Config.CommitsTo}}
+              <option {{if .Selected}}selected{{end}}>{{.Name}}</option>
+            {{end}}
+          </select>
+        </div>
+
+	<input class="button" type="submit" value="Refresh" name="refresh"/>
+        <a href="https://code.google.com/p/go-wiki/wiki/PerfDashboard">Help</a>
+      </form>
+    </aside>
+    <div class="clear"></div>
+  </div>
+</body>
+</html>
diff --git a/third_party/go.tools/dashboard/app/build/perf_learn.go b/third_party/go.tools/dashboard/app/build/perf_learn.go
new file mode 100644
index 0000000..683ba60
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/perf_learn.go
@@ -0,0 +1,186 @@
+// Copyright 2013 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.
+
+// +build appengine
+
+package build
+
+import (
+	"bytes"
+	"fmt"
+	"html/template"
+	"net/http"
+	"sort"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+func init() {
+	http.HandleFunc("/perflearn", perfLearnHandler)
+}
+
+const (
+	learnPercentile       = 0.95
+	learnSignalMultiplier = 1.1
+	learnMinSignal        = 0.5
+)
+
+func perfLearnHandler(w http.ResponseWriter, r *http.Request) {
+	d := dashboardForRequest(r)
+	c := d.Context(appengine.NewContext(r))
+
+	pc, err := GetPerfConfig(c, r)
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	p, err := GetPackage(c, "")
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	update := r.FormValue("update") != ""
+	noise := make(map[string]string)
+
+	data := &perfLearnData{}
+
+	commits, err := GetCommits(c, 0, p.NextNum)
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	for _, builder := range pc.BuildersForBenchmark("") {
+		for _, benchmark := range pc.BenchmarksForBuilder(builder) {
+			for _, metric := range pc.MetricsForBenchmark(benchmark) {
+				for _, procs := range pc.ProcList(builder) {
+					values, err := GetPerfMetricsForCommits(c, builder, fmt.Sprintf("%v-%v", benchmark, procs), metric, 0, p.NextNum)
+					if err != nil {
+						logErr(w, r, err)
+						return
+					}
+					var dd []float64
+					last := uint64(0)
+					for i, v := range values {
+						if v == 0 {
+							if com := commits[i]; com == nil || com.NeedsBenchmarking {
+								last = 0
+							}
+							continue
+						}
+						if last != 0 {
+							v1 := v
+							if v1 < last {
+								v1, last = last, v1
+							}
+							diff := float64(v1)/float64(last)*100 - 100
+							dd = append(dd, diff)
+						}
+						last = v
+					}
+					if len(dd) == 0 {
+						continue
+					}
+					sort.Float64s(dd)
+
+					baseIdx := int(float64(len(dd)) * learnPercentile)
+					baseVal := dd[baseIdx]
+					signalVal := baseVal * learnSignalMultiplier
+					if signalVal < learnMinSignal {
+						signalVal = learnMinSignal
+					}
+					signalIdx := -1
+					noiseNum := 0
+					signalNum := 0
+
+					var diffs []*perfLearnDiff
+					for i, d := range dd {
+						if d > 3*signalVal {
+							d = 3 * signalVal
+						}
+						diffs = append(diffs, &perfLearnDiff{Num: i, Val: d})
+						if signalIdx == -1 && d >= signalVal {
+							signalIdx = i
+						}
+						if d < signalVal {
+							noiseNum++
+						} else {
+							signalNum++
+						}
+					}
+					diffs[baseIdx].Hint = "95%"
+					if signalIdx != -1 {
+						diffs[signalIdx].Hint = "signal"
+					}
+					diffs = diffs[len(diffs)*4/5:]
+					name := fmt.Sprintf("%v/%v-%v/%v", builder, benchmark, procs, metric)
+					data.Entries = append(data.Entries, &perfLearnEntry{len(data.Entries), name, baseVal, noiseNum, signalVal, signalNum, diffs})
+
+					if len(dd) >= 100 || r.FormValue("force") != "" {
+						nname := fmt.Sprintf("%v|%v-%v", builder, benchmark, procs)
+						n := noise[nname] + fmt.Sprintf("|%v=%.2f", metric, signalVal)
+						noise[nname] = n
+					}
+				}
+			}
+		}
+	}
+
+	if update {
+		var noiseLevels []string
+		for k, v := range noise {
+			noiseLevels = append(noiseLevels, k+v)
+		}
+		tx := func(c appengine.Context) error {
+			pc, err := GetPerfConfig(c, r)
+			if err != nil {
+				return err
+			}
+			pc.NoiseLevels = noiseLevels
+			if _, err := datastore.Put(c, PerfConfigKey(c), pc); err != nil {
+				return fmt.Errorf("putting PerfConfig: %v", err)
+			}
+			return nil
+		}
+		if err := datastore.RunInTransaction(c, tx, nil); err != nil {
+			logErr(w, r, err)
+			return
+		}
+	}
+
+	var buf bytes.Buffer
+	if err := perfLearnTemplate.Execute(&buf, data); err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	buf.WriteTo(w)
+}
+
+var perfLearnTemplate = template.Must(
+	template.New("perf_learn.html").Funcs(tmplFuncs).ParseFiles("build/perf_learn.html"),
+)
+
+type perfLearnData struct {
+	Entries []*perfLearnEntry
+}
+
+type perfLearnEntry struct {
+	Num       int
+	Name      string
+	BaseVal   float64
+	NoiseNum  int
+	SignalVal float64
+	SignalNum int
+	Diffs     []*perfLearnDiff
+}
+
+type perfLearnDiff struct {
+	Num  int
+	Val  float64
+	Hint string
+}
diff --git a/third_party/go.tools/dashboard/app/build/perf_learn.html b/third_party/go.tools/dashboard/app/build/perf_learn.html
new file mode 100644
index 0000000..294e957
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/perf_learn.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<html>
+  <head>
+    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+    <script type="text/javascript">
+      google.load("visualization", "1", {packages:["corechart"]});
+      google.setOnLoadCallback(drawCharts);
+      function drawCharts() {
+        {
+        {{range $ent := $.Entries}}
+          var data = new google.visualization.DataTable();
+          data.addColumn('number', 'idx');
+          data.addColumn('number', '95%');
+          data.addColumn({type: 'boolean', role: 'certainty'});
+          data.addColumn('number', 'signal');
+          data.addColumn({type: 'boolean', role: 'certainty'});
+          data.addColumn('number', 'diff');
+          data.addColumn({type: 'string', role: 'annotation'});
+          data.addRows([
+            {{range .Diffs}} [{{.Num}}, {{$ent.BaseVal}}, false, {{$ent.SignalVal}}, false, {{.Val}}, '{{.Hint}}'], {{end}}
+          ]);
+          new google.visualization.LineChart(document.getElementById('graph{{.Num}}')).
+            draw(data, {
+              width: 600,
+              height: 200,
+              legend: {position: "none"},
+              vAxis: {minValue: 0},
+              chartArea: {left: "10%", top: "1%", width: "90%", height:"95%"}
+            }
+          )
+        {{end}}
+        }
+      }
+    </script>
+  </head>
+
+  <body>
+    {{range $.Entries}}
+      <p>
+        {{.Name}}: base={{printf "%.2f[%d]" .BaseVal .NoiseNum}} signal={{printf "%.2f[%d]" .SignalVal .SignalNum}}
+        <div id="graph{{.Num}}" width="100px" height="100px"> </div>
+      </p>
+    {{end}}
+  </body>
+</html>
diff --git a/third_party/go.tools/dashboard/app/build/perf_notify.txt b/third_party/go.tools/dashboard/app/build/perf_notify.txt
new file mode 100644
index 0000000..c5e8ebe
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/perf_notify.txt
@@ -0,0 +1,13 @@
+{{if .Commit}}Change {{shortHash .Commit.Hash}} caused perf changes on {{.Builder}}:
+
+{{.Commit.Desc}}
+
+http://code.google.com/p/go/source/detail?r={{shortHash .Commit.Hash}}
+{{else}}This changed caused perf changes on {{.Builder}}:
+{{end}}
+{{range $b := .Benchmarks}}
+{{printf "%-16s %12s %12s %10s" $b.Name "old" "new" "delta"}}
+{{range $m := $b.Metrics}}{{printf "%-16s %12v %12v %+10.2f" $m.Name $m.Old $m.New $m.Delta}}
+{{end}}{{end}}
+{{.Url}}
+
diff --git a/third_party/go.tools/dashboard/app/build/test.go b/third_party/go.tools/dashboard/app/build/test.go
new file mode 100644
index 0000000..34a1c39
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/test.go
@@ -0,0 +1,378 @@
+// 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.
+
+// +build appengine
+
+package build
+
+// TODO(adg): test authentication
+// TODO(adg): refactor to use appengine/aetest instead
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"net/url"
+	"strings"
+	"time"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+func init() {
+	http.HandleFunc("/buildtest", testHandler)
+}
+
+var testEntityKinds = []string{
+	"Package",
+	"Commit",
+	"CommitRun",
+	"Result",
+	"PerfResult",
+	"PerfMetricRun",
+	"PerfConfig",
+	"PerfTodo",
+	"Log",
+}
+
+const testPkg = "golang.org/x/test"
+
+var testPackage = &Package{Name: "Test", Kind: "subrepo", Path: testPkg}
+
+var testPackages = []*Package{
+	{Name: "Go", Path: ""},
+	testPackage,
+}
+
+var tCommitTime = time.Now().Add(-time.Hour * 24 * 7)
+
+func tCommit(hash, parentHash, path string, bench bool) *Commit {
+	tCommitTime.Add(time.Hour) // each commit should have a different time
+	return &Commit{
+		PackagePath:       path,
+		Hash:              hash,
+		ParentHash:        parentHash,
+		Time:              tCommitTime,
+		User:              "adg",
+		Desc:              "change description " + hash,
+		NeedsBenchmarking: bench,
+	}
+}
+
+var testRequests = []struct {
+	path string
+	vals url.Values
+	req  interface{}
+	res  interface{}
+}{
+	// Packages
+	{"/packages", url.Values{"kind": {"subrepo"}}, nil, []*Package{testPackage}},
+
+	// Go repo
+	{"/commit", nil, tCommit("0001", "0000", "", true), nil},
+	{"/commit", nil, tCommit("0002", "0001", "", false), nil},
+	{"/commit", nil, tCommit("0003", "0002", "", true), nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0002", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+
+	// Other builders, to test the UI.
+	{"/result", nil, &Result{Builder: "linux-amd64", Hash: "0001", OK: true}, nil},
+	{"/result", nil, &Result{Builder: "linux-amd64-race", Hash: "0001", OK: true}, nil},
+	{"/result", nil, &Result{Builder: "netbsd-386", Hash: "0001", OK: true}, nil},
+	{"/result", nil, &Result{Builder: "plan9-386", Hash: "0001", OK: true}, nil},
+	{"/result", nil, &Result{Builder: "windows-386", Hash: "0001", OK: true}, nil},
+	{"/result", nil, &Result{Builder: "windows-amd64", Hash: "0001", OK: true}, nil},
+	{"/result", nil, &Result{Builder: "windows-amd64-race", Hash: "0001", OK: true}, nil},
+	{"/result", nil, &Result{Builder: "linux-amd64-temp", Hash: "0001", OK: true}, nil},
+
+	// multiple builders
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/result", nil, &Result{Builder: "linux-amd64", Hash: "0003", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0002"}}},
+
+	// branches
+	{"/commit", nil, tCommit("0004", "0003", "", false), nil},
+	{"/commit", nil, tCommit("0005", "0002", "", false), nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0005"}}},
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0005", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0004"}}},
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0004", OK: false}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+
+	// logs
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0003", OK: false, Log: "test"}, nil},
+	{"/log/a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", nil, nil, "test"},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, nil},
+
+	// repeat failure (shouldn't re-send mail)
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0003", OK: false, Log: "test"}, nil},
+
+	// non-Go repos
+	{"/commit", nil, tCommit("1001", "0000", testPkg, false), nil},
+	{"/commit", nil, tCommit("1002", "1001", testPkg, false), nil},
+	{"/commit", nil, tCommit("1003", "1002", testPkg, false), nil},
+	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1003"}}},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1003", GoHash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1002"}}},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1002", GoHash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1001"}}},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1001", GoHash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, nil},
+	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0002"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1003"}}},
+
+	// re-build Go revision for stale subrepos
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0005"}}},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1001", GoHash: "0005", OK: false, Log: "boo"}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, nil},
+
+	// benchmarks
+	// build-go-commit must have precedence over benchmark-go-commit
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0005"}}},
+	// drain build-go-commit todo
+	{"/result", nil, &Result{Builder: "linux-amd64", Hash: "0005", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0004"}}},
+	{"/result", nil, &Result{Builder: "linux-amd64", Hash: "0004", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0002"}}},
+	{"/result", nil, &Result{Builder: "linux-amd64", Hash: "0002", OK: true}, nil},
+	// drain sub-repo todos
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-amd64", Hash: "1001", GoHash: "0005", OK: false}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-amd64", Hash: "1002", GoHash: "0005", OK: false}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-amd64", Hash: "1003", GoHash: "0005", OK: false}, nil},
+	// now we must get benchmark todo
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0003", PerfResults: []string{}}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "http", Hash: "0003", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0003", PerfResults: []string{"http"}}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "json", Hash: "0003", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0003", PerfResults: []string{"http", "json"}}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "meta-done", Hash: "0003", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0001", PerfResults: []string{}}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "http", Hash: "0001", OK: true}, nil},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "meta-done", Hash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, nil},
+	// create new commit, it must appear in todo
+	{"/commit", nil, tCommit("0006", "0005", "", true), nil},
+	// drain build-go-commit todo
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0006"}}},
+	{"/result", nil, &Result{Builder: "linux-amd64", Hash: "0006", OK: true}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-amd64", Hash: "1003", GoHash: "0006", OK: false}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-amd64", Hash: "1002", GoHash: "0006", OK: false}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-amd64", Hash: "1001", GoHash: "0006", OK: false}, nil},
+	// now we must get benchmark todo
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0006", PerfResults: []string{}}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "http", Hash: "0006", OK: true}, nil},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "meta-done", Hash: "0006", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, nil},
+	// create new benchmark, all commits must re-appear in todo
+	{"/commit", nil, tCommit("0007", "0006", "", true), nil},
+	// drain build-go-commit todo
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0007"}}},
+	{"/result", nil, &Result{Builder: "linux-amd64", Hash: "0007", OK: true}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-amd64", Hash: "1003", GoHash: "0007", OK: false}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-amd64", Hash: "1002", GoHash: "0007", OK: false}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-amd64", Hash: "1001", GoHash: "0007", OK: false}, nil},
+	// now we must get benchmark todo
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0007", PerfResults: []string{}}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "bson", Hash: "0007", OK: true}, nil},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "meta-done", Hash: "0007", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0007", PerfResults: []string{"bson"}}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "meta-done", Hash: "0007", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0006", PerfResults: []string{"http"}}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "meta-done", Hash: "0006", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0001", PerfResults: []string{"http"}}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "meta-done", Hash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0003", PerfResults: []string{"http", "json"}}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-amd64", Benchmark: "meta-done", Hash: "0003", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-amd64"}}, nil, nil},
+	// attach second builder
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0007"}}},
+	// drain build-go-commit todo
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0007", OK: true}, nil},
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0006", OK: true}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1003", GoHash: "0007", OK: false}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1002", GoHash: "0007", OK: false}, nil},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1001", GoHash: "0007", OK: false}, nil},
+	// now we must get benchmark todo
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0007"}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-386", Benchmark: "meta-done", Hash: "0007", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0006"}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-386", Benchmark: "meta-done", Hash: "0006", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0001"}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-386", Benchmark: "meta-done", Hash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "benchmark-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/perf-result", nil, &PerfRequest{Builder: "linux-386", Benchmark: "meta-done", Hash: "0003", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit", "benchmark-go-commit"}, "builder": {"linux-386"}}, nil, nil},
+}
+
+func testHandler(w http.ResponseWriter, r *http.Request) {
+	if !appengine.IsDevAppServer() {
+		fmt.Fprint(w, "These tests must be run under the dev_appserver.")
+		return
+	}
+	c := appengine.NewContext(r)
+	if err := nukeEntities(c, testEntityKinds); err != nil {
+		logErr(w, r, err)
+		return
+	}
+	if r.FormValue("nukeonly") != "" {
+		fmt.Fprint(w, "OK")
+		return
+	}
+
+	for _, p := range testPackages {
+		if _, err := datastore.Put(c, p.Key(c), p); err != nil {
+			logErr(w, r, err)
+			return
+		}
+	}
+
+	origReq := *r
+	defer func() {
+		// HACK: We need to clobber the original request (see below)
+		// so make sure we fix it before exiting the handler.
+		*r = origReq
+	}()
+	for i, t := range testRequests {
+		c.Infof("running test %d %s vals='%q' req='%q' res='%q'", i, t.path, t.vals, t.req, t.res)
+		errorf := func(format string, args ...interface{}) {
+			fmt.Fprintf(w, "%d %s: ", i, t.path)
+			fmt.Fprintf(w, format, args...)
+			fmt.Fprintln(w)
+		}
+		var body io.ReadWriter
+		if t.req != nil {
+			body = new(bytes.Buffer)
+			json.NewEncoder(body).Encode(t.req)
+		}
+		url := "http://" + domain + t.path
+		if t.vals != nil {
+			url += "?" + t.vals.Encode() + "&version=2"
+		} else {
+			url += "?version=2"
+		}
+		req, err := http.NewRequest("POST", url, body)
+		if err != nil {
+			logErr(w, r, err)
+			return
+		}
+		if t.req != nil {
+			req.Method = "POST"
+		}
+		req.Header = origReq.Header
+		rec := httptest.NewRecorder()
+
+		// Make the request
+		*r = *req // HACK: App Engine uses the request pointer
+		// as a map key to resolve Contexts.
+		http.DefaultServeMux.ServeHTTP(rec, r)
+
+		if rec.Code != 0 && rec.Code != 200 {
+			errorf(rec.Body.String())
+			return
+		}
+		c.Infof("response='%v'", rec.Body.String())
+		resp := new(dashResponse)
+
+		// If we're expecting a *Todo value,
+		// prime the Response field with a Todo and a Commit inside it.
+		if t.path == "/todo" {
+			resp.Response = &Todo{Data: &Commit{}}
+		}
+
+		if strings.HasPrefix(t.path, "/log/") {
+			resp.Response = rec.Body.String()
+		} else {
+			err := json.NewDecoder(rec.Body).Decode(resp)
+			if err != nil {
+				errorf("decoding response: %v", err)
+				return
+			}
+		}
+		if e, ok := t.res.(string); ok {
+			g, ok := resp.Response.(string)
+			if !ok {
+				errorf("Response not string: %T", resp.Response)
+				return
+			}
+			if g != e {
+				errorf("response mismatch: got %q want %q", g, e)
+				return
+			}
+		}
+		if e, ok := t.res.(*Todo); ok {
+			g, ok := resp.Response.(*Todo)
+			if !ok {
+				errorf("Response not *Todo: %T", resp.Response)
+				return
+			}
+			if e.Data == nil && g.Data != nil {
+				errorf("Response.Data should be nil, got: %v", g.Data)
+				return
+			}
+			if g.Data == nil {
+				errorf("Response.Data is nil, want: %v", e.Data)
+				return
+			}
+			gd, ok := g.Data.(*Commit)
+			if !ok {
+				errorf("Response.Data not *Commit: %T", g.Data)
+				return
+			}
+			if g.Kind != e.Kind {
+				errorf("kind don't match: got %q, want %q", g.Kind, e.Kind)
+				return
+			}
+			ed := e.Data.(*Commit)
+			if ed.Hash != gd.Hash {
+				errorf("hashes don't match: got %q, want %q", gd.Hash, ed.Hash)
+				return
+			}
+			if len(gd.PerfResults) != len(ed.PerfResults) {
+				errorf("result data len don't match: got %v, want %v", len(gd.PerfResults), len(ed.PerfResults))
+				return
+			}
+			for i := range gd.PerfResults {
+				if gd.PerfResults[i] != ed.PerfResults[i] {
+					errorf("result data %v don't match: got %v, want %v", i, gd.PerfResults[i], ed.PerfResults[i])
+					return
+				}
+			}
+		}
+		if t.res == nil && resp.Response != nil {
+			errorf("response mismatch: got %q expected <nil>", resp.Response)
+			return
+		}
+	}
+	fmt.Fprint(w, "PASS\nYou should see only one mail notification (for 0003/linux-386) in the dev_appserver logs.")
+}
+
+func nukeEntities(c appengine.Context, kinds []string) error {
+	if !appengine.IsDevAppServer() {
+		return errors.New("can't nuke production data")
+	}
+	var keys []*datastore.Key
+	for _, kind := range kinds {
+		q := datastore.NewQuery(kind).KeysOnly()
+		for t := q.Run(c); ; {
+			k, err := t.Next(nil)
+			if err == datastore.Done {
+				break
+			}
+			if err != nil {
+				return err
+			}
+			keys = append(keys, k)
+		}
+	}
+	return datastore.DeleteMulti(c, keys)
+}
diff --git a/third_party/go.tools/dashboard/app/build/ui.go b/third_party/go.tools/dashboard/app/build/ui.go
new file mode 100644
index 0000000..c2cf7c5
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/ui.go
@@ -0,0 +1,460 @@
+// 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.
+
+// TODO(adg): packages at weekly/release
+// TODO(adg): some means to register new packages
+
+// +build appengine
+
+package build
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"html/template"
+	"net/http"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+
+	"cache"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+func init() {
+	for _, d := range dashboards {
+		http.HandleFunc(d.RelPath, uiHandler)
+	}
+}
+
+// uiHandler draws the build status page.
+func uiHandler(w http.ResponseWriter, r *http.Request) {
+	d := dashboardForRequest(r)
+	c := d.Context(appengine.NewContext(r))
+	now := cache.Now(c)
+	key := "build-ui"
+
+	page, _ := strconv.Atoi(r.FormValue("page"))
+	if page < 0 {
+		page = 0
+	}
+	key += fmt.Sprintf("-page%v", page)
+
+	branch := r.FormValue("branch")
+	if branch != "" {
+		key += "-branch-" + branch
+	}
+
+	repo := r.FormValue("repo")
+	if repo != "" {
+		key += "-repo-" + repo
+	}
+
+	var b []byte
+	if cache.Get(r, now, key, &b) {
+		w.Write(b)
+		return
+	}
+
+	pkg := &Package{} // empty package is the main repository
+	if repo != "" {
+		var err error
+		pkg, err = GetPackage(c, repo)
+		if err != nil {
+			logErr(w, r, err)
+			return
+		}
+	}
+	commits, err := dashCommits(c, pkg, page, branch)
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+	builders := commitBuilders(commits)
+
+	var tipState *TagState
+	if pkg.Kind == "" && page == 0 && (branch == "" || branch == "default") {
+		// only show sub-repo state on first page of normal repo view
+		tipState, err = TagStateByName(c, "tip")
+		if err != nil {
+			logErr(w, r, err)
+			return
+		}
+	}
+
+	p := &Pagination{}
+	if len(commits) == commitsPerPage {
+		p.Next = page + 1
+	}
+	if page > 0 {
+		p.Prev = page - 1
+		p.HasPrev = true
+	}
+	data := &uiTemplateData{d, pkg, commits, builders, tipState, p, branch}
+
+	var buf bytes.Buffer
+	if err := uiTemplate.Execute(&buf, data); err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	cache.Set(r, now, key, buf.Bytes())
+
+	buf.WriteTo(w)
+}
+
+type Pagination struct {
+	Next, Prev int
+	HasPrev    bool
+}
+
+// dashCommits gets a slice of the latest Commits to the current dashboard.
+// If page > 0 it paginates by commitsPerPage.
+func dashCommits(c appengine.Context, pkg *Package, page int, branch string) ([]*Commit, error) {
+	offset := page * commitsPerPage
+	q := datastore.NewQuery("Commit").
+		Ancestor(pkg.Key(c)).
+		Order("-Num")
+
+	var commits []*Commit
+	if branch == "" {
+		_, err := q.Limit(commitsPerPage).Offset(offset).
+			GetAll(c, &commits)
+		return commits, err
+	}
+
+	// Look for commits on a specific branch.
+	for t, n := q.Run(c), 0; len(commits) < commitsPerPage && n < 1000; {
+		var c Commit
+		_, err := t.Next(&c)
+		if err == datastore.Done {
+			break
+		}
+		if err != nil {
+			return nil, err
+		}
+		if !isBranchCommit(&c, branch) {
+			continue
+		}
+		if n >= offset {
+			commits = append(commits, &c)
+		}
+		n++
+	}
+	return commits, nil
+}
+
+// isBranchCommit reports whether the given commit is on the specified branch.
+// It does so by examining the commit description, so there will be some bad
+// matches where the branch commits do not begin with the "[branch]" prefix.
+func isBranchCommit(c *Commit, b string) bool {
+	d := strings.TrimSpace(c.Desc)
+	if b == "default" {
+		return !strings.HasPrefix(d, "[")
+	}
+	return strings.HasPrefix(d, "["+b+"]")
+}
+
+// commitBuilders returns the names of the builders that provided
+// Results for the provided commits.
+func commitBuilders(commits []*Commit) []string {
+	builders := make(map[string]bool)
+	for _, commit := range commits {
+		for _, r := range commit.Results() {
+			builders[r.Builder] = true
+		}
+	}
+	k := keys(builders)
+	sort.Sort(builderOrder(k))
+	return k
+}
+
+func keys(m map[string]bool) (s []string) {
+	for k := range m {
+		s = append(s, k)
+	}
+	sort.Strings(s)
+	return
+}
+
+// builderOrder implements sort.Interface, sorting builder names
+// ("darwin-amd64", etc) first by builderPriority and then alphabetically.
+type builderOrder []string
+
+func (s builderOrder) Len() int      { return len(s) }
+func (s builderOrder) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s builderOrder) Less(i, j int) bool {
+	pi, pj := builderPriority(s[i]), builderPriority(s[j])
+	if pi == pj {
+		return s[i] < s[j]
+	}
+	return pi < pj
+}
+
+func builderPriority(builder string) (p int) {
+	// Put -temp builders at the end, always.
+	if strings.HasSuffix(builder, "-temp") {
+		defer func() { p += 20 }()
+	}
+	// Group race builders together.
+	if isRace(builder) {
+		return 1
+	}
+	// If the OS has a specified priority, use it.
+	if p, ok := osPriority[builderOS(builder)]; ok {
+		return p
+	}
+	// The rest.
+	return 10
+}
+
+func isRace(s string) bool {
+	return strings.Contains(s, "-race-") || strings.HasSuffix(s, "-race")
+}
+
+func unsupported(builder string) bool {
+	if strings.HasSuffix(builder, "-temp") {
+		return true
+	}
+	return unsupportedOS(builderOS(builder))
+}
+
+func unsupportedOS(os string) bool {
+	if os == "race" {
+		return false
+	}
+	p, ok := osPriority[os]
+	return !ok || p > 0
+}
+
+// Priorities for specific operating systems.
+var osPriority = map[string]int{
+	"darwin":  0,
+	"freebsd": 0,
+	"linux":   0,
+	"windows": 0,
+	// race == 1
+	"openbsd":   2,
+	"netbsd":    3,
+	"dragonfly": 4,
+}
+
+// TagState represents the state of all Packages at a Tag.
+type TagState struct {
+	Tag      *Commit
+	Packages []*PackageState
+}
+
+// PackageState represents the state of a Package at a Tag.
+type PackageState struct {
+	Package *Package
+	Commit  *Commit
+}
+
+// TagStateByName fetches the results for all Go subrepos at the specified Tag.
+func TagStateByName(c appengine.Context, name string) (*TagState, error) {
+	tag, err := GetTag(c, name)
+	if err != nil {
+		return nil, err
+	}
+	pkgs, err := Packages(c, "subrepo")
+	if err != nil {
+		return nil, err
+	}
+	var st TagState
+	for _, pkg := range pkgs {
+		com, err := pkg.LastCommit(c)
+		if err != nil {
+			c.Warningf("%v: no Commit found: %v", pkg, err)
+			continue
+		}
+		st.Packages = append(st.Packages, &PackageState{pkg, com})
+	}
+	st.Tag, err = tag.Commit(c)
+	if err != nil {
+		return nil, err
+	}
+	return &st, nil
+}
+
+type uiTemplateData struct {
+	Dashboard  *Dashboard
+	Package    *Package
+	Commits    []*Commit
+	Builders   []string
+	TipState   *TagState
+	Pagination *Pagination
+	Branch     string
+}
+
+var uiTemplate = template.Must(
+	template.New("ui.html").Funcs(tmplFuncs).ParseFiles("build/ui.html"),
+)
+
+var tmplFuncs = template.FuncMap{
+	"buildDashboards":   buildDashboards,
+	"builderOS":         builderOS,
+	"builderSpans":      builderSpans,
+	"builderSubheading": builderSubheading,
+	"builderTitle":      builderTitle,
+	"repoURL":           repoURL,
+	"shortDesc":         shortDesc,
+	"shortHash":         shortHash,
+	"shortUser":         shortUser,
+	"tail":              tail,
+	"unsupported":       unsupported,
+}
+
+func splitDash(s string) (string, string) {
+	i := strings.Index(s, "-")
+	if i >= 0 {
+		return s[:i], s[i+1:]
+	}
+	return s, ""
+}
+
+// builderOS returns the os tag for a builder string
+func builderOS(s string) string {
+	os, _ := splitDash(s)
+	return os
+}
+
+// builderOSOrRace returns the builder OS or, if it is a race builder, "race".
+func builderOSOrRace(s string) string {
+	if isRace(s) {
+		return "race"
+	}
+	return builderOS(s)
+}
+
+// builderArch returns the arch tag for a builder string
+func builderArch(s string) string {
+	_, arch := splitDash(s)
+	arch, _ = splitDash(arch) // chop third part
+	return arch
+}
+
+// builderSubheading returns a short arch tag for a builder string
+// or, if it is a race builder, the builder OS.
+func builderSubheading(s string) string {
+	if isRace(s) {
+		return builderOS(s)
+	}
+	arch := builderArch(s)
+	switch arch {
+	case "amd64":
+		return "x64"
+	}
+	return arch
+}
+
+// builderArchChar returns the architecture letter for a builder string
+func builderArchChar(s string) string {
+	arch := builderArch(s)
+	switch arch {
+	case "386":
+		return "8"
+	case "amd64":
+		return "6"
+	case "arm":
+		return "5"
+	}
+	return arch
+}
+
+type builderSpan struct {
+	N           int
+	OS          string
+	Unsupported bool
+}
+
+// builderSpans creates a list of tags showing
+// the builder's operating system names, spanning
+// the appropriate number of columns.
+func builderSpans(s []string) []builderSpan {
+	var sp []builderSpan
+	for len(s) > 0 {
+		i := 1
+		os := builderOSOrRace(s[0])
+		u := unsupportedOS(os) || strings.HasSuffix(s[0], "-temp")
+		for i < len(s) && builderOSOrRace(s[i]) == os {
+			i++
+		}
+		sp = append(sp, builderSpan{i, os, u})
+		s = s[i:]
+	}
+	return sp
+}
+
+// builderTitle formats "linux-amd64-foo" as "linux amd64 foo".
+func builderTitle(s string) string {
+	return strings.Replace(s, "-", " ", -1)
+}
+
+// buildDashboards returns the known public dashboards.
+func buildDashboards() []*Dashboard {
+	return dashboards
+}
+
+// shortDesc returns the first line of a description.
+func shortDesc(desc string) string {
+	if i := strings.Index(desc, "\n"); i != -1 {
+		desc = desc[:i]
+	}
+	return limitStringLength(desc, 100)
+}
+
+// shortHash returns a short version of a hash.
+func shortHash(hash string) string {
+	if len(hash) > 12 {
+		hash = hash[:12]
+	}
+	return hash
+}
+
+// shortUser returns a shortened version of a user string.
+func shortUser(user string) string {
+	if i, j := strings.Index(user, "<"), strings.Index(user, ">"); 0 <= i && i < j {
+		user = user[i+1 : j]
+	}
+	if i := strings.Index(user, "@"); i >= 0 {
+		return user[:i]
+	}
+	return user
+}
+
+// repoRe matches Google Code repositories and subrepositories (without paths).
+var repoRe = regexp.MustCompile(`^code\.google\.com/p/([a-z0-9\-]+)(\.[a-z0-9\-]+)?$`)
+
+// repoURL returns the URL of a change at a Google Code repository or subrepo.
+func repoURL(dashboard, hash, packagePath string) (string, error) {
+	if packagePath == "" {
+		if dashboard == "Gccgo" {
+			return "https://code.google.com/p/gofrontend/source/detail?r=" + hash, nil
+		}
+		return "https://code.google.com/p/go/source/detail?r=" + hash, nil
+	}
+	m := repoRe.FindStringSubmatch(packagePath)
+	if m == nil {
+		return "", errors.New("unrecognized package: " + packagePath)
+	}
+	url := "https://code.google.com/p/" + m[1] + "/source/detail?r=" + hash
+	if len(m) > 2 {
+		url += "&repo=" + m[2][1:]
+	}
+	return url, nil
+}
+
+// tail returns the trailing n lines of s.
+func tail(n int, s string) string {
+	lines := strings.Split(s, "\n")
+	if len(lines) < n {
+		return s
+	}
+	return strings.Join(lines[len(lines)-n:], "\n")
+}
diff --git a/third_party/go.tools/dashboard/app/build/ui.html b/third_party/go.tools/dashboard/app/build/ui.html
new file mode 100644
index 0000000..6ae268c
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/ui.html
@@ -0,0 +1,210 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <title>{{$.Dashboard.Name}} Build Dashboard</title>
+    <link rel="stylesheet" href="/static/style.css"/>
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
+    <script>
+    var showUnsupported = window.location.hash.substr(1) != "short";
+    function redraw() {
+        showUnsupported = !$("#showshort").prop('checked');
+        $('.unsupported')[showUnsupported?'show':'hide']();
+        window.location.hash = showUnsupported?'':'short';
+    }
+    $(document).ready(function() {
+        $("#showshort").attr('checked', !showUnsupported).change(redraw);
+        redraw();
+    })
+    </script>
+  </head>
+
+  <body>
+    <header id="topbar">
+      <h1>Go Dashboard</h1>
+      <nav>
+        <a href="{{$.Dashboard.RelPath}}">Test</a>
+        <a href="{{$.Dashboard.RelPath}}perf">Perf</a>
+        <a href="{{$.Dashboard.RelPath}}perfgraph">Graphs</a>
+      </nav>
+      <div class="clear"></div>
+    </header>
+
+    <nav class="dashboards">
+      {{range buildDashboards}}
+        <a href="{{.RelPath}}">{{.Name}}</a>
+      {{end}}
+      <label>
+        <input type=checkbox id="showshort">
+        show only <a href="http://golang.org/wiki/PortingPolicy">first-class ports</a>
+      </label>
+    </nav>
+    {{with $.Package.Name}}<h2>{{.}}</h2>{{end}}
+
+  <div class="page">
+
+    {{if $.Commits}}
+
+    <table class="build">
+      <colgroup class="col-hash" {{if $.Package.Path}}span="2"{{end}}></colgroup>
+    {{range $.Builders | builderSpans}}
+      <colgroup class="col-result{{if .Unsupported}} unsupported{{end}}" span="{{.N}}"></colgroup>
+    {{end}}
+      <colgroup class="col-user"></colgroup>
+      <colgroup class="col-time"></colgroup>
+      <colgroup class="col-desc"></colgroup>
+      <tr>
+        <!-- extra row to make alternating colors use dark for first result -->
+      </tr>
+      <tr>
+    {{if $.Package.Path}}
+        <th colspan="2">revision</th>
+    {{else}}
+        <th>&nbsp;</th>
+    {{end}}
+    {{range $.Builders | builderSpans}}
+        <th {{if .Unsupported}}class="unsupported"{{end}} colspan="{{.N}}">{{.OS}}</th>
+    {{end}}
+        <th></th>
+        <th></th>
+        <th></th>
+      </tr>
+      <tr>
+    {{if $.Package.Path}}
+        <th class="result arch">repo</th>
+        <th class="result arch">{{$.Dashboard.Name}}</th>
+    {{else}}
+        <th>&nbsp;</th>
+    {{end}}
+    {{range $.Builders}}
+        <th class="result arch{{if (unsupported .)}} unsupported{{end}}" title="{{.}}">{{builderSubheading .}}</th>
+    {{end}}
+        <th></th>
+        <th></th>
+        <th></th>
+      </tr>
+    {{range $c := $.Commits}}
+      {{range $i, $h := $c.ResultGoHashes}}
+        <tr class="commit">
+        {{if $i}}
+          <td>&nbsp;</td>
+        {{else}}
+          <td class="hash"><a href="{{repoURL $.Dashboard.Name $c.Hash $.Package.Path}}">{{shortHash $c.Hash}}</a></td>
+        {{end}}
+        {{if $h}} 
+          <td class="hash"><a href="{{repoURL $.Dashboard.Name $h ""}}">{{shortHash $h}}</a></td>
+        {{end}}
+          {{range $.Builders}}
+            <td class="result{{if (unsupported .)}} unsupported{{end}}">
+              {{with $c.Result . $h}}
+                {{if .OK}}
+                  <span class="ok">ok</span>
+                {{else}}
+                  <a href="{{$.Dashboard.RelPath}}log/{{.LogHash}}" class="fail">fail</a>
+                {{end}}
+              {{else}}
+                &nbsp;
+              {{end}}
+            </td>
+          {{end}}
+        {{if $i}}
+          <td>&nbsp;</td>
+          <td>&nbsp;</td>
+          <td>&nbsp;</td>
+        {{else}}
+          <td class="user" title="{{$c.User}}">{{shortUser $c.User}}</td>
+          <td class="time">{{$c.Time.Format "Mon 02 Jan 15:04"}}</td>
+          <td class="desc" title="{{$c.Desc}}">{{shortDesc $c.Desc}}</td>
+        {{end}}
+        </tr>
+      {{end}}
+    {{end}}
+    </table>
+
+    {{with $.Pagination}}
+    <div class="paginate">
+      <nav>
+        <a {{if .HasPrev}}href="?{{with $.Package.Path}}repo={{.}}&{{end}}page={{.Prev}}{{with $.Branch}}&branch={{.}}{{end}}"{{else}}class="inactive"{{end}}>newer</a>
+        <a {{if .Next}}href="?{{with $.Package.Path}}repo={{.}}&{{end}}page={{.Next}}{{with $.Branch}}&branch={{.}}{{end}}"{{else}}class="inactive"{{end}}>older</a>
+        <a {{if .HasPrev}}href=".{{with $.Branch}}?branch={{.}}{{end}}"{{else}}class="inactive"{{end}}>latest</a>
+      </nav>
+    </div>
+    {{end}}
+
+  {{else}}
+    <p>No commits to display. Hm.</p>
+  {{end}}
+
+  {{with $.TipState}}
+    {{$goHash := .Tag.Hash}}
+    {{if .Packages}}
+      <h2>
+        Sub-repositories at tip
+        <small>(<a href="{{repoURL $.Dashboard.Name .Tag.Hash ""}}">{{shortHash .Tag.Hash}}</a>)</small>
+      </h2>
+
+      <table class="build">
+      <colgroup class="col-package"></colgroup>
+      <colgroup class="col-hash"></colgroup>
+      {{range $.Builders | builderSpans}}
+        <colgroup class="col-result{{if .Unsupported}} unsupported{{end}}" span="{{.N}}"></colgroup>
+      {{end}}
+      <colgroup class="col-user"></colgroup>
+      <colgroup class="col-time"></colgroup>
+      <colgroup class="col-desc"></colgroup>
+      <tr>
+        <!-- extra row to make alternating colors use dark for first result -->
+      </tr>
+      <tr>
+        <th></th>
+        <th></th>
+        {{range $.Builders | builderSpans}}
+          <th {{if .Unsupported}}class="unsupported"{{end}} colspan="{{.N}}">{{.OS}}</th>
+        {{end}}
+        <th></th>
+        <th></th>
+        <th></th>
+      </tr>
+      <tr>
+        <th></th>
+        <th></th>
+        {{range $.Builders}}
+          <th class="result arch{{if (unsupported .)}} unsupported{{end}}" title="{{.}}">{{builderSubheading .}}</th>
+        {{end}}
+        <th></th>
+        <th></th>
+        <th></th>
+      </tr>
+    {{range $pkg := .Packages}}
+      <tr class="commit">
+        <td><a title="{{.Package.Path}}" href="?repo={{.Package.Path}}">{{.Package.Name}}</a></td>
+        <td class="hash">
+          {{$h := $pkg.Commit.Hash}}
+          <a href="{{repoURL $.Dashboard.Name $h $pkg.Commit.PackagePath}}">{{shortHash $h}}</a>
+        </td>
+        {{range $.Builders}}
+          <td class="result{{if (unsupported .)}} unsupported{{end}}">
+            {{with $pkg.Commit.Result . $goHash}}
+              {{if .OK}}
+                <span class="ok">ok</span>
+              {{else}}
+                <a href="{{$.Dashboard.RelPath}}log/{{.LogHash}}" class="fail">fail</a>
+              {{end}}
+            {{else}}
+              &nbsp;
+            {{end}}
+          </td>
+        {{end}}
+        {{with $pkg.Commit}}
+          <td class="user" title="{{.User}}">{{shortUser .User}}</td>
+          <td class="time">{{.Time.Format "Mon 02 Jan 15:04"}}</td>
+          <td class="desc" title="{{.Desc}}">{{shortDesc .Desc}}</td>
+        {{end}}
+      </tr>
+    {{end}}
+    </table>
+   {{end}}
+  {{end}}
+
+  </div>
+  </body>
+</html>
diff --git a/third_party/go.tools/dashboard/app/build/update.go b/third_party/go.tools/dashboard/app/build/update.go
new file mode 100644
index 0000000..1d22cc9
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/build/update.go
@@ -0,0 +1,117 @@
+// 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.
+
+// +build appengine
+
+package build
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+func init() {
+	http.HandleFunc("/updatebenchmark", updateBenchmark)
+}
+
+func updateBenchmark(w http.ResponseWriter, r *http.Request) {
+	if !appengine.IsDevAppServer() {
+		fmt.Fprint(w, "Update must not run on real server.")
+		return
+	}
+
+	if r.Method != "POST" {
+		fmt.Fprintf(w, "bad request method")
+		return
+	}
+
+	c := contextForRequest(r)
+	if !validKey(c, r.FormValue("key"), r.FormValue("builder")) {
+		fmt.Fprintf(w, "bad builder/key")
+		return
+	}
+
+	defer r.Body.Close()
+	var hashes []string
+	if err := json.NewDecoder(r.Body).Decode(&hashes); err != nil {
+		fmt.Fprintf(w, "failed to decode request: %v", err)
+		return
+	}
+
+	ncommit := 0
+	nrun := 0
+	tx := func(c appengine.Context) error {
+		var cr *CommitRun
+		for _, hash := range hashes {
+			// Update Commit.
+			com := &Commit{Hash: hash}
+			err := datastore.Get(c, com.Key(c), com)
+			if err != nil && err != datastore.ErrNoSuchEntity {
+				return fmt.Errorf("fetching Commit: %v", err)
+			}
+			if err == datastore.ErrNoSuchEntity {
+				continue
+			}
+			com.NeedsBenchmarking = true
+			com.PerfResults = nil
+			if err := putCommit(c, com); err != nil {
+				return err
+			}
+			ncommit++
+
+			// create PerfResult
+			res := &PerfResult{CommitHash: com.Hash, CommitNum: com.Num}
+			err = datastore.Get(c, res.Key(c), res)
+			if err != nil && err != datastore.ErrNoSuchEntity {
+				return fmt.Errorf("fetching PerfResult: %v", err)
+			}
+			if err == datastore.ErrNoSuchEntity {
+				if _, err := datastore.Put(c, res.Key(c), res); err != nil {
+					return fmt.Errorf("putting PerfResult: %v", err)
+				}
+			}
+
+			// Update CommitRun.
+			if cr != nil && cr.StartCommitNum != com.Num/PerfRunLength*PerfRunLength {
+				if _, err := datastore.Put(c, cr.Key(c), cr); err != nil {
+					return fmt.Errorf("putting CommitRun: %v", err)
+				}
+				nrun++
+				cr = nil
+			}
+			if cr == nil {
+				var err error
+				cr, err = GetCommitRun(c, com.Num)
+				if err != nil {
+					return fmt.Errorf("getting CommitRun: %v", err)
+				}
+			}
+			if com.Num < cr.StartCommitNum || com.Num >= cr.StartCommitNum+PerfRunLength {
+				return fmt.Errorf("commit num %v out of range [%v, %v)", com.Num, cr.StartCommitNum, cr.StartCommitNum+PerfRunLength)
+			}
+			idx := com.Num - cr.StartCommitNum
+			cr.Hash[idx] = com.Hash
+			cr.User[idx] = shortDesc(com.User)
+			cr.Desc[idx] = shortDesc(com.Desc)
+			cr.Time[idx] = com.Time
+			cr.NeedsBenchmarking[idx] = com.NeedsBenchmarking
+		}
+		if cr != nil {
+			if _, err := datastore.Put(c, cr.Key(c), cr); err != nil {
+				return fmt.Errorf("putting CommitRun: %v", err)
+			}
+			nrun++
+		}
+		return nil
+	}
+	if err := datastore.RunInTransaction(c, tx, nil); err != nil {
+		fmt.Fprintf(w, "failed to execute tx: %v", err)
+		return
+	}
+	fmt.Fprintf(w, "OK (updated %v commits and %v commit runs)", ncommit, nrun)
+}
diff --git a/third_party/go.tools/dashboard/app/cache/cache.go b/third_party/go.tools/dashboard/app/cache/cache.go
new file mode 100644
index 0000000..4b57614
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/cache/cache.go
@@ -0,0 +1,86 @@
+// 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.
+
+// +build appengine
+
+package cache
+
+import (
+	"fmt"
+	"net/http"
+	"time"
+
+	"appengine"
+	"appengine/memcache"
+)
+
+// TimeKey specifies the memcache entity that keeps the logical datastore time.
+var TimeKey = "cachetime"
+
+const (
+	nocache = "nocache"
+	expiry  = 600 // 10 minutes
+)
+
+func newTime() uint64 { return uint64(time.Now().Unix()) << 32 }
+
+// Now returns the current logical datastore time to use for cache lookups.
+func Now(c appengine.Context) uint64 {
+	t, err := memcache.Increment(c, TimeKey, 0, newTime())
+	if err != nil {
+		c.Errorf("cache.Now: %v", err)
+		return 0
+	}
+	return t
+}
+
+// Tick sets the current logical datastore time to a never-before-used time
+// and returns that time. It should be called to invalidate the cache.
+func Tick(c appengine.Context) uint64 {
+	t, err := memcache.Increment(c, TimeKey, 1, newTime())
+	if err != nil {
+		c.Errorf("cache.Tick: %v", err)
+		return 0
+	}
+	return t
+}
+
+// Get fetches data for name at time now from memcache and unmarshals it into
+// value. It reports whether it found the cache record and logs any errors to
+// the admin console.
+func Get(r *http.Request, now uint64, name string, value interface{}) bool {
+	if now == 0 || r.FormValue(nocache) != "" {
+		return false
+	}
+	c := appengine.NewContext(r)
+	key := fmt.Sprintf("%s.%d", name, now)
+	_, err := memcache.JSON.Get(c, key, value)
+	if err == nil {
+		c.Debugf("cache hit %q", key)
+		return true
+	}
+	c.Debugf("cache miss %q", key)
+	if err != memcache.ErrCacheMiss {
+		c.Errorf("get cache %q: %v", key, err)
+	}
+	return false
+}
+
+// Set puts value into memcache under name at time now.
+// It logs any errors to the admin console.
+func Set(r *http.Request, now uint64, name string, value interface{}) {
+	if now == 0 || r.FormValue(nocache) != "" {
+		return
+	}
+	c := appengine.NewContext(r)
+	key := fmt.Sprintf("%s.%d", name, now)
+	err := memcache.JSON.Set(c, &memcache.Item{
+		Key:        key,
+		Object:     value,
+		Expiration: expiry,
+	})
+	if err != nil {
+		c.Errorf("set cache %q: %v", key, err)
+	}
+}
diff --git a/third_party/go.tools/dashboard/app/cron.yaml b/third_party/go.tools/dashboard/app/cron.yaml
new file mode 100644
index 0000000..4118f9e
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/cron.yaml
@@ -0,0 +1,5 @@
+cron:
+- description: updates noise level for benchmarking results
+  url: /perflearn?update=1
+  schedule: every 24 hours
+  
diff --git a/third_party/go.tools/dashboard/app/index.yaml b/third_party/go.tools/dashboard/app/index.yaml
new file mode 100644
index 0000000..670a667
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/index.yaml
@@ -0,0 +1,54 @@
+indexes:
+
+- kind: Commit
+  ancestor: yes
+  properties:
+  - name: Num
+    direction: desc
+
+- kind: Commit
+  ancestor: yes
+  properties:
+  - name: Time
+    direction: desc
+    
+- kind: Commit
+  ancestor: yes
+  properties:
+  - name: NeedsBenchmarking
+  - name: Num
+    direction: desc
+
+- kind: CommitRun
+  ancestor: yes
+  properties:
+  - name: StartCommitNum
+    direction: desc
+
+- kind: PerfResult
+  ancestor: yes
+  properties:
+  - name: CommitNum
+    direction: desc
+
+- kind: PerfResult   
+  ancestor: yes
+  properties:
+  - name: CommitNum
+    direction: asc
+
+- kind: CommitRun
+  ancestor: yes
+  properties:
+  - name: StartCommitNum
+    direction: asc
+
+- kind: PerfMetricRun
+  ancestor: yes
+  properties:
+  - name: Builder
+  - name: Benchmark
+  - name: Metric
+  - name: StartCommitNum
+    direction: asc
+
diff --git a/third_party/go.tools/dashboard/app/key/key.go b/third_party/go.tools/dashboard/app/key/key.go
new file mode 100644
index 0000000..e52554f
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/key/key.go
@@ -0,0 +1,64 @@
+// 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.
+
+// +build appengine
+
+package key
+
+import (
+	"sync"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+var theKey struct {
+	sync.RWMutex
+	builderKey
+}
+
+type builderKey struct {
+	Secret string
+}
+
+func (k *builderKey) Key(c appengine.Context) *datastore.Key {
+	return datastore.NewKey(c, "BuilderKey", "root", 0, nil)
+}
+
+func Secret(c appengine.Context) string {
+	// check with rlock
+	theKey.RLock()
+	k := theKey.Secret
+	theKey.RUnlock()
+	if k != "" {
+		return k
+	}
+
+	// prepare to fill; check with lock and keep lock
+	theKey.Lock()
+	defer theKey.Unlock()
+	if theKey.Secret != "" {
+		return theKey.Secret
+	}
+
+	// fill
+	if err := datastore.Get(c, theKey.Key(c), &theKey.builderKey); err != nil {
+		if err == datastore.ErrNoSuchEntity {
+			// If the key is not stored in datastore, write it.
+			// This only happens at the beginning of a new deployment.
+			// The code is left here for SDK use and in case a fresh
+			// deployment is ever needed.  "gophers rule" is not the
+			// real key.
+			if !appengine.IsDevAppServer() {
+				panic("lost key from datastore")
+			}
+			theKey.Secret = "gophers rule"
+			datastore.Put(c, theKey.Key(c), &theKey.builderKey)
+			return theKey.Secret
+		}
+		panic("cannot load builder key: " + err.Error())
+	}
+
+	return theKey.Secret
+}
diff --git a/third_party/go.tools/dashboard/app/static/status_alert.gif b/third_party/go.tools/dashboard/app/static/status_alert.gif
new file mode 100644
index 0000000..495d9d2
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/static/status_alert.gif
Binary files differ
diff --git a/third_party/go.tools/dashboard/app/static/status_good.gif b/third_party/go.tools/dashboard/app/static/status_good.gif
new file mode 100644
index 0000000..ef9c5a8
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/static/status_good.gif
Binary files differ
diff --git a/third_party/go.tools/dashboard/app/static/style.css b/third_party/go.tools/dashboard/app/static/style.css
new file mode 100644
index 0000000..ddf2129
--- /dev/null
+++ b/third_party/go.tools/dashboard/app/static/style.css
@@ -0,0 +1,308 @@
+* { box-sizing: border-box; }
+
+      .dashboards {
+        padding: 0.5em;
+      }
+      .dashboards a {
+        padding: 0.5em;
+        background: #eee;
+        color: blue;
+      }
+
+body {
+  margin: 0;
+  font-family: sans-serif;
+  padding: 0; margin: 0;
+  color: #222;
+}
+ 
+.container {
+  max-width: 900px;
+  margin: 0 auto;
+}
+ 
+p, pre, ul, ol { margin: 20px; }
+ 
+h1, h2, h3, h4 {
+  margin: 20px 0;
+  padding: 0;
+  color: #375EAB;
+  font-weight: bold;
+}
+ 
+h1 { font-size: 24px; }
+h2 { font-size: 20px; }
+h3 { font-size: 20px; }
+h4 { font-size: 16px; }
+ 
+h2 { background: #E0EBF5; padding: 2px 5px; }
+h3, h4 { margin: 20px 5px; }
+ 
+dl, dd { font-size: 14px; }
+dl { margin: 20px; }
+dd { margin: 2px 20px; }
+ 
+.clear {
+  clear: both;
+}
+ 
+.button {
+  padding: 10px;
+  
+  color: #222;
+  border: 1px solid #375EAB;
+  background: #E0EBF5;
+  
+  border-radius: 5px;
+  
+  cursor: pointer;
+  
+  margin-left: 60px;
+}
+ 
+/* navigation bar */
+ 
+#topbar {
+  padding: 10px 10px;
+  background: #E0EBF5;
+}
+ 
+#topbar a {
+  color: #222;
+}
+#topbar h1 {
+  float: left;
+  margin: 0;
+  padding-top: 5px;
+}
+ 
+#topbar nav { 
+  float: left;
+  margin-left: 20px;
+}
+#topbar nav a {
+  display: inline-block;
+  padding: 10px;
+  
+  margin: 0;
+  margin-right: 5px;
+ 
+  color: white;
+  background: #375EAB;
+    
+  text-decoration: none;
+  font-size: 16px;
+    
+  border: 1px solid #375EAB;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+}
+ 
+.page {
+  margin-top: 20px;
+}
+ 
+/* settings panels */
+aside {
+  margin-top: 5px;
+}
+ 
+.panel {
+  border: 1px solid #aaa;
+  border-radius: 5px;
+  margin-bottom: 5px;
+}
+ 
+.panel h1 {
+  font-size: 16px;
+  margin: 0;
+  padding: 2px 8px;
+}
+ 
+.panel select {
+  padding: 5px;
+  border: 0;
+  width: 100%;
+}
+ 
+/* results table */
+ 
+table {
+  margin: 5px;
+  border-collapse: collapse;
+  font-size: 11px;
+}
+ 
+table td, table th, table td, table th {
+  vertical-align: top;
+  padding: 2px 6px;
+}
+ 
+table tr:nth-child(2n+1) {
+  background: #F4F4F4;
+}
+ 
+table thead tr {
+  background: #fff !important;
+}
+ 
+/* build results */
+ 
+.build td, .build th, .packages td, .packages th {
+  vertical-align: top;
+  padding: 2px 4px;
+  font-size: 10pt;
+}
+      
+.build .hash {
+  font-family: monospace;
+  font-size: 9pt;
+}
+ 
+.build .result {
+  text-align: center;
+  width: 2em;
+}
+ 
+.build .col-hash, .build .col-result, .build .col-metric, .build .col-numresults {
+  border-right: 1px solid #ccc;
+}
+
+.build .row-commit {
+  border-top: 2px solid #ccc;
+}
+
+.build .arch {
+  font-size: 83%;
+  font-weight: normal;
+}
+
+.build .time {
+  color: #666;
+}
+
+.build .ok {
+  font-size: 83%;
+}
+
+.build .desc, .build .time, .build .user {
+  white-space: nowrap;
+}
+ 
+.build .desc {
+  text-align: left;
+  max-width: 470px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+ 
+.good   { text-decoration: none; color: #000000; border: 2px solid #00E700}
+.bad    { text-decoration: none; text-shadow: 1px 1px 0 #000000; color: #FFFFFF; background: #E70000;}
+.noise  { text-decoration: none; color: #888; }
+.fail   { color: #C00; }
+
+/* pagination */
+ 
+.paginate nav {
+  padding: 0.5em;
+  margin: 10px 0;
+}
+ 
+.paginate nav a {
+  padding: 0.5em;
+  background: #E0EBF5;
+  color: blue;
+
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+}
+ 
+.paginate nav a.inactive {
+  color: #888;
+  cursor: default;
+  text-decoration: none;
+}
+
+/* diffs */
+ 
+.diff-meta {
+  font-family: monospace;
+  margin-bottom: 10px;
+}
+ 
+.diff-container {
+  padding: 10px;
+}
+ 
+.diff table .metric {
+  font-weight: bold;
+}
+ 
+.diff {
+  border: 1px solid #aaa;
+  border-radius: 5px;
+  margin-bottom: 5px;
+  margin-right: 10px;
+  float: left;
+}
+ 
+.diff h1 {
+  font-size: 16px;
+  margin: 0;
+  padding: 2px 8px;
+}
+
+.diff-benchmark {
+  clear: both;
+  padding-top: 5px;
+}
+
+/* positioning elements */
+ 
+.page {
+  position: relative;
+  width: 100%;
+}
+ 
+aside {
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  width: 200px;
+}
+ 
+.main-content {
+  position: absolute;
+  top: 0;
+  left: 210px;
+  right: 5px;
+  min-height: 200px;
+  overflow: hidden;
+}
+ 
+@media only screen and (max-width: 900px) {
+  aside {
+    position: relative;
+    display: block;
+    width: auto;
+  }
+ 
+  .main-content {
+    position: static;
+    padding: 0;
+  }
+  
+  aside .panel {
+    float: left;
+    width: auto;
+    margin-right: 5px;
+  }
+  aside .button {
+    float: left;
+    margin: 0;
+  }
+}
+
diff --git a/third_party/go.tools/dashboard/builder/bench.go b/third_party/go.tools/dashboard/builder/bench.go
new file mode 100644
index 0000000..fb99aac
--- /dev/null
+++ b/third_party/go.tools/dashboard/builder/bench.go
@@ -0,0 +1,256 @@
+// Copyright 2013 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 (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+// benchHash benchmarks a single commit.
+func (b *Builder) benchHash(hash string, benchs []string) error {
+	if *verbose {
+		log.Println(b.name, "benchmarking", hash)
+	}
+
+	res := &PerfResult{Hash: hash, Benchmark: "meta-done"}
+
+	// Create place in which to do work.
+	workpath := filepath.Join(*buildroot, b.name+"-"+hash[:12])
+	// Prepare a workpath if we don't have one we can reuse.
+	update := false
+	if b.lastWorkpath != workpath {
+		if err := os.Mkdir(workpath, mkdirPerm); err != nil {
+			return err
+		}
+		buildLog, _, err := b.buildRepoOnHash(workpath, hash, makeCmd)
+		if err != nil {
+			removePath(workpath)
+			// record failure
+			res.Artifacts = append(res.Artifacts, PerfArtifact{"log", buildLog})
+			return b.recordPerfResult(res)
+		}
+		b.lastWorkpath = workpath
+		update = true
+	}
+
+	// Build the benchmark binary.
+	benchBin, buildLog, err := b.buildBenchmark(workpath, update)
+	if err != nil {
+		// record failure
+		res.Artifacts = append(res.Artifacts, PerfArtifact{"log", buildLog})
+		return b.recordPerfResult(res)
+	}
+
+	benchmark, procs, affinity, last := chooseBenchmark(benchBin, benchs)
+	if benchmark != "" {
+		res.Benchmark = fmt.Sprintf("%v-%v", benchmark, procs)
+		res.Metrics, res.Artifacts, res.OK = b.executeBenchmark(workpath, hash, benchBin, benchmark, procs, affinity)
+		if err = b.recordPerfResult(res); err != nil {
+			return fmt.Errorf("recordResult: %s", err)
+		}
+	}
+
+	if last {
+		// All benchmarks have beed executed, don't need workpath anymore.
+		removePath(b.lastWorkpath)
+		b.lastWorkpath = ""
+		// Notify the app.
+		res = &PerfResult{Hash: hash, Benchmark: "meta-done", OK: true}
+		if err = b.recordPerfResult(res); err != nil {
+			return fmt.Errorf("recordResult: %s", err)
+		}
+	}
+
+	return nil
+}
+
+// buildBenchmark builds the benchmark binary.
+func (b *Builder) buildBenchmark(workpath string, update bool) (benchBin, log string, err error) {
+	goroot := filepath.Join(workpath, "go")
+	gobin := filepath.Join(goroot, "bin", "go") + exeExt
+	gopath := filepath.Join(*buildroot, "gopath")
+	env := append([]string{
+		"GOROOT=" + goroot,
+		"GOPATH=" + gopath},
+		b.envv()...)
+	// First, download without installing.
+	args := []string{"get", "-d"}
+	if update {
+		args = append(args, "-u")
+	}
+	args = append(args, *benchPath)
+	var buildlog bytes.Buffer
+	runOpts := []runOpt{runTimeout(*buildTimeout), runEnv(env), allOutput(&buildlog), runDir(workpath)}
+	err = run(exec.Command(gobin, args...), runOpts...)
+	if err != nil {
+		fmt.Fprintf(&buildlog, "go get -d %s failed: %s", *benchPath, err)
+		return "", buildlog.String(), err
+	}
+	// Then, build into workpath.
+	benchBin = filepath.Join(workpath, "benchbin") + exeExt
+	args = []string{"build", "-o", benchBin, *benchPath}
+	buildlog.Reset()
+	err = run(exec.Command(gobin, args...), runOpts...)
+	if err != nil {
+		fmt.Fprintf(&buildlog, "go build %s failed: %s", *benchPath, err)
+		return "", buildlog.String(), err
+	}
+	return benchBin, "", nil
+}
+
+// chooseBenchmark chooses the next benchmark to run
+// based on the list of available benchmarks, already executed benchmarks
+// and -benchcpu list.
+func chooseBenchmark(benchBin string, doneBenchs []string) (bench string, procs, affinity int, last bool) {
+	var out bytes.Buffer
+	err := run(exec.Command(benchBin), allOutput(&out))
+	if err != nil {
+		log.Printf("Failed to query benchmark list: %v\n%s", err, out)
+		last = true
+		return
+	}
+	outStr := out.String()
+	nlIdx := strings.Index(outStr, "\n")
+	if nlIdx < 0 {
+		log.Printf("Failed to parse benchmark list (no new line): %s", outStr)
+		last = true
+		return
+	}
+	localBenchs := strings.Split(outStr[:nlIdx], ",")
+	benchsMap := make(map[string]bool)
+	for _, b := range doneBenchs {
+		benchsMap[b] = true
+	}
+	cnt := 0
+	// We want to run all benchmarks with GOMAXPROCS=1 first.
+	for i, procs1 := range benchCPU {
+		for _, bench1 := range localBenchs {
+			if benchsMap[fmt.Sprintf("%v-%v", bench1, procs1)] {
+				continue
+			}
+			cnt++
+			if cnt == 1 {
+				bench = bench1
+				procs = procs1
+				if i < len(benchAffinity) {
+					affinity = benchAffinity[i]
+				}
+			}
+		}
+	}
+	last = cnt <= 1
+	return
+}
+
+// executeBenchmark runs a single benchmark and parses its output.
+func (b *Builder) executeBenchmark(workpath, hash, benchBin, bench string, procs, affinity int) (metrics []PerfMetric, artifacts []PerfArtifact, ok bool) {
+	// Benchmarks runs mutually exclusive with other activities.
+	benchMutex.RUnlock()
+	defer benchMutex.RLock()
+	benchMutex.Lock()
+	defer benchMutex.Unlock()
+
+	log.Printf("%v executing benchmark %v-%v on %v", b.name, bench, procs, hash)
+
+	// The benchmark executes 'go build'/'go tool',
+	// so we need properly setup env.
+	env := append([]string{
+		"GOROOT=" + filepath.Join(workpath, "go"),
+		"PATH=" + filepath.Join(workpath, "go", "bin") + string(os.PathListSeparator) + os.Getenv("PATH"),
+		"GODEBUG=gctrace=1", // since Go1.2
+		"GOGCTRACE=1",       // before Go1.2
+		fmt.Sprintf("GOMAXPROCS=%v", procs)},
+		b.envv()...)
+	args := []string{
+		"-bench", bench,
+		"-benchmem", strconv.Itoa(*benchMem),
+		"-benchtime", benchTime.String(),
+		"-benchnum", strconv.Itoa(*benchNum),
+		"-tmpdir", workpath}
+	if affinity != 0 {
+		args = append(args, "-affinity", strconv.Itoa(affinity))
+	}
+	benchlog := new(bytes.Buffer)
+	err := run(exec.Command(benchBin, args...), runEnv(env), allOutput(benchlog), runDir(workpath))
+	if strip := benchlog.Len() - 512<<10; strip > 0 {
+		// Leave the last 512K, that part contains metrics.
+		benchlog = bytes.NewBuffer(benchlog.Bytes()[strip:])
+	}
+	artifacts = []PerfArtifact{{Type: "log", Body: benchlog.String()}}
+	if err != nil {
+		if err != nil {
+			log.Printf("Failed to execute benchmark '%v': %v", bench, err)
+			ok = false
+		}
+		return
+	}
+
+	metrics1, artifacts1, err := parseBenchmarkOutput(benchlog)
+	if err != nil {
+		log.Printf("Failed to parse benchmark output: %v", err)
+		ok = false
+		return
+	}
+	metrics = metrics1
+	artifacts = append(artifacts, artifacts1...)
+	ok = true
+	return
+}
+
+// parseBenchmarkOutput fetches metrics and artifacts from benchmark output.
+func parseBenchmarkOutput(out io.Reader) (metrics []PerfMetric, artifacts []PerfArtifact, err error) {
+	s := bufio.NewScanner(out)
+	metricRe := regexp.MustCompile("^GOPERF-METRIC:([a-z,0-9,-]+)=([0-9]+)$")
+	fileRe := regexp.MustCompile("^GOPERF-FILE:([a-z,0-9,-]+)=(.+)$")
+	for s.Scan() {
+		ln := s.Text()
+		if ss := metricRe.FindStringSubmatch(ln); ss != nil {
+			var v uint64
+			v, err = strconv.ParseUint(ss[2], 10, 64)
+			if err != nil {
+				err = fmt.Errorf("Failed to parse metric '%v=%v': %v", ss[1], ss[2], err)
+				return
+			}
+			metrics = append(metrics, PerfMetric{Type: ss[1], Val: v})
+		} else if ss := fileRe.FindStringSubmatch(ln); ss != nil {
+			var buf []byte
+			buf, err = ioutil.ReadFile(ss[2])
+			if err != nil {
+				err = fmt.Errorf("Failed to read file '%v': %v", ss[2], err)
+				return
+			}
+			artifacts = append(artifacts, PerfArtifact{ss[1], string(buf)})
+		}
+	}
+	return
+}
+
+// needsBenchmarking determines whether the commit needs benchmarking.
+func needsBenchmarking(log *HgLog) bool {
+	// Do not benchmark branch commits, they are usually not interesting
+	// and fall out of the trunk succession.
+	if log.Branch != "" {
+		return false
+	}
+	// Do not benchmark commits that do not touch source files (e.g. CONTRIBUTORS).
+	for _, f := range strings.Split(log.Files, " ") {
+		if (strings.HasPrefix(f, "include") || strings.HasPrefix(f, "src")) &&
+			!strings.HasSuffix(f, "_test.go") && !strings.Contains(f, "testdata") {
+			return true
+		}
+	}
+	return false
+}
diff --git a/third_party/go.tools/dashboard/builder/doc.go b/third_party/go.tools/dashboard/builder/doc.go
new file mode 100644
index 0000000..5192861
--- /dev/null
+++ b/third_party/go.tools/dashboard/builder/doc.go
@@ -0,0 +1,58 @@
+// Copyright 2010 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.
+
+/*
+
+Go Builder is a continuous build client for the Go project.
+It integrates with the Go Dashboard AppEngine application.
+
+Go Builder is intended to run continuously as a background process.
+
+It periodically pulls updates from the Go Mercurial repository.
+
+When a newer revision is found, Go Builder creates a clone of the repository,
+runs all.bash, and reports build success or failure to the Go Dashboard.
+
+For a release revision (a change description that matches "release.YYYY-MM-DD"),
+Go Builder will create a tar.gz archive of the GOROOT and deliver it to the
+Go Google Code project's downloads section.
+
+Usage:
+
+  gobuilder goos-goarch...
+
+  Several goos-goarch combinations can be provided, and the builder will
+  build them in serial.
+
+Optional flags:
+
+  -dashboard="godashboard.appspot.com": Go Dashboard Host
+    The location of the Go Dashboard application to which Go Builder will
+    report its results.
+
+  -release: Build and deliver binary release archive
+
+  -rev=N: Build revision N and exit
+
+  -cmd="./all.bash": Build command (specify absolute or relative to go/src)
+
+  -v: Verbose logging
+
+  -external: External package builder mode (will not report Go build
+     state to dashboard or issue releases)
+
+The key file should be located at $HOME/.gobuildkey or, for a builder-specific
+key, $HOME/.gobuildkey-$BUILDER (eg, $HOME/.gobuildkey-linux-amd64).
+
+The build key file is a text file of the format:
+
+  godashboard-key
+  googlecode-username
+  googlecode-password
+
+If the Google Code credentials are not provided the archival step
+will be skipped.
+
+*/
+package main
diff --git a/third_party/go.tools/dashboard/builder/env.go b/third_party/go.tools/dashboard/builder/env.go
new file mode 100644
index 0000000..c4b095b
--- /dev/null
+++ b/third_party/go.tools/dashboard/builder/env.go
@@ -0,0 +1,281 @@
+// Copyright 2013 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 (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/vcs"
+)
+
+// builderEnv represents the environment that a Builder will run tests in.
+type builderEnv interface {
+	// setup sets up the builder environment and returns the directory to run the buildCmd in.
+	setup(repo *Repo, workpath, hash string, envv []string) (string, error)
+}
+
+// goEnv represents the builderEnv for the main Go repo.
+type goEnv struct {
+	goos, goarch string
+}
+
+func (b *Builder) envv() []string {
+	if runtime.GOOS == "windows" {
+		return b.envvWindows()
+	}
+
+	var e []string
+	if *buildTool == "go" {
+		e = []string{
+			"GOOS=" + b.goos,
+			"GOARCH=" + b.goarch,
+			"GOROOT_FINAL=/usr/local/go",
+		}
+		switch b.goos {
+		case "android", "nacl":
+			// Cross compile.
+		default:
+			// If we are building, for example, linux/386 on a linux/amd64 machine we want to
+			// make sure that the whole build is done as a if this were compiled on a real
+			// linux/386 machine. In other words, we want to not do a cross compilation build.
+			// To do this we set GOHOSTOS and GOHOSTARCH to override the detection in make.bash.
+			//
+			// The exception to this rule is when we are doing nacl/android builds. These are by
+			// definition always cross compilation, and we have support built into cmd/go to be
+			// able to handle this case.
+			e = append(e, "GOHOSTOS="+b.goos, "GOHOSTARCH="+b.goarch)
+		}
+	}
+
+	for _, k := range extraEnv() {
+		if s, ok := getenvOk(k); ok {
+			e = append(e, k+"="+s)
+		}
+	}
+	return e
+}
+
+func (b *Builder) envvWindows() []string {
+	var start map[string]string
+	if *buildTool == "go" {
+		start = map[string]string{
+			"GOOS":         b.goos,
+			"GOHOSTOS":     b.goos,
+			"GOARCH":       b.goarch,
+			"GOHOSTARCH":   b.goarch,
+			"GOROOT_FINAL": `c:\go`,
+			"GOBUILDEXIT":  "1", // exit all.bat with completion status.
+		}
+	}
+
+	for _, name := range extraEnv() {
+		if s, ok := getenvOk(name); ok {
+			start[name] = s
+		}
+	}
+	if b.goos == "windows" {
+		switch b.goarch {
+		case "amd64":
+			start["PATH"] = `c:\TDM-GCC-64\bin;` + start["PATH"]
+		case "386":
+			start["PATH"] = `c:\TDM-GCC-32\bin;` + start["PATH"]
+		}
+	}
+	skip := map[string]bool{
+		"GOBIN":   true,
+		"GOPATH":  true,
+		"GOROOT":  true,
+		"INCLUDE": true,
+		"LIB":     true,
+	}
+	var e []string
+	for name, v := range start {
+		e = append(e, name+"="+v)
+		skip[name] = true
+	}
+	for _, kv := range os.Environ() {
+		s := strings.SplitN(kv, "=", 2)
+		name := strings.ToUpper(s[0])
+		switch {
+		case name == "":
+			// variables, like "=C:=C:\", just copy them
+			e = append(e, kv)
+		case !skip[name]:
+			e = append(e, kv)
+			skip[name] = true
+		}
+	}
+	return e
+}
+
+// setup for a goEnv clones the main go repo to workpath/go at the provided hash
+// and returns the path workpath/go/src, the location of all go build scripts.
+func (env *goEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
+	goworkpath := filepath.Join(workpath, "go")
+	if err := repo.Export(goworkpath, hash); err != nil {
+		return "", fmt.Errorf("error exporting repository: %s", err)
+	}
+	// Write out VERSION file if it does not already exist.
+	vFile := filepath.Join(goworkpath, "VERSION")
+	if _, err := os.Stat(vFile); os.IsNotExist(err) {
+		if err := ioutil.WriteFile(vFile, []byte(hash), 0644); err != nil {
+			return "", fmt.Errorf("error writing VERSION file: %s", err)
+		}
+	}
+	return filepath.Join(goworkpath, "src"), nil
+}
+
+// gccgoEnv represents the builderEnv for the gccgo compiler.
+type gccgoEnv struct{}
+
+// setup for a gccgoEnv clones the gofrontend repo to workpath/go at the hash
+// and clones the latest GCC branch to repo.Path/gcc. The gccgo sources are
+// replaced with the updated sources in the gofrontend repo and gcc gets
+// gets configured and built in workpath/gcc-objdir. The path to
+// workpath/gcc-objdir is returned.
+func (env *gccgoEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
+	gccpath := filepath.Join(repo.Path, "gcc")
+
+	// get a handle to Git vcs.Cmd for pulling down GCC from the mirror.
+	git := vcs.ByCmd("git")
+
+	// only pull down gcc if we don't have a local copy.
+	if _, err := os.Stat(gccpath); err != nil {
+		if err := timeout(*cmdTimeout, func() error {
+			// pull down a working copy of GCC.
+			return git.Create(gccpath, *gccPath)
+		}); err != nil {
+			return "", err
+		}
+	}
+
+	if err := git.Download(gccpath); err != nil {
+		return "", err
+	}
+
+	// get the modified files for this commit.
+
+	var buf bytes.Buffer
+	if err := run(exec.Command("hg", "status", "--no-status", "--change", hash),
+		allOutput(&buf), runDir(repo.Path), runEnv(envv)); err != nil {
+		return "", fmt.Errorf("Failed to find the modified files for %s: %s", hash, err)
+	}
+	modifiedFiles := strings.Split(buf.String(), "\n")
+	var isMirrored bool
+	for _, f := range modifiedFiles {
+		if strings.HasPrefix(f, "go/") || strings.HasPrefix(f, "libgo/") {
+			isMirrored = true
+			break
+		}
+	}
+
+	// use git log to find the corresponding commit to sync to in the gcc mirror.
+	// If the files modified in the gofrontend are mirrored to gcc, we expect a
+	// commit with a similar description in the gcc mirror. If the files modified are
+	// not mirrored, e.g. in support/, we can sync to the most recent gcc commit that
+	// occurred before those files were modified to verify gccgo's status at that point.
+	logCmd := []string{
+		"log",
+		"-1",
+		"--format=%H",
+	}
+	var errMsg string
+	if isMirrored {
+		commitDesc, err := repo.Master.VCS.LogAtRev(repo.Path, hash, "{desc|firstline|escape}")
+		if err != nil {
+			return "", err
+		}
+
+		quotedDesc := regexp.QuoteMeta(string(commitDesc))
+		logCmd = append(logCmd, "--grep", quotedDesc, "--regexp-ignore-case", "--extended-regexp")
+		errMsg = fmt.Sprintf("Failed to find a commit with a similar description to '%s'", string(commitDesc))
+	} else {
+		commitDate, err := repo.Master.VCS.LogAtRev(repo.Path, hash, "{date|rfc3339date}")
+		if err != nil {
+			return "", err
+		}
+
+		logCmd = append(logCmd, "--before", string(commitDate))
+		errMsg = fmt.Sprintf("Failed to find a commit before '%s'", string(commitDate))
+	}
+
+	buf.Reset()
+	if err := run(exec.Command("git", logCmd...), runEnv(envv), allOutput(&buf), runDir(gccpath)); err != nil {
+		return "", fmt.Errorf("%s: %s", errMsg, err)
+	}
+	gccRev := buf.String()
+	if gccRev == "" {
+		return "", fmt.Errorf(errMsg)
+	}
+
+	// checkout gccRev
+	// TODO(cmang): Fix this to work in parallel mode.
+	if err := run(exec.Command("git", "reset", "--hard", strings.TrimSpace(gccRev)), runEnv(envv), runDir(gccpath)); err != nil {
+		return "", fmt.Errorf("Failed to checkout commit at revision %s: %s", gccRev, err)
+	}
+
+	// make objdir to work in
+	gccobjdir := filepath.Join(workpath, "gcc-objdir")
+	if err := os.Mkdir(gccobjdir, mkdirPerm); err != nil {
+		return "", err
+	}
+
+	// configure GCC with substituted gofrontend and libgo
+	if err := run(exec.Command(filepath.Join(gccpath, "configure"),
+		"--enable-languages=c,c++,go",
+		"--disable-bootstrap",
+		"--disable-multilib",
+	), runEnv(envv), runDir(gccobjdir)); err != nil {
+		return "", fmt.Errorf("Failed to configure GCC: %v", err)
+	}
+
+	// build gcc
+	if err := run(exec.Command("make"), runTimeout(*buildTimeout), runEnv(envv), runDir(gccobjdir)); err != nil {
+		return "", fmt.Errorf("Failed to build GCC: %s", err)
+	}
+
+	return gccobjdir, nil
+}
+
+func getenvOk(k string) (v string, ok bool) {
+	v = os.Getenv(k)
+	if v != "" {
+		return v, true
+	}
+	keq := k + "="
+	for _, kv := range os.Environ() {
+		if kv == keq {
+			return "", true
+		}
+	}
+	return "", false
+}
+
+// extraEnv returns environment variables that need to be copied from
+// the gobuilder's environment to the envv of its subprocesses.
+func extraEnv() []string {
+	extra := []string{
+		"GOARM",
+		"GO386",
+		"CGO_ENABLED",
+		"CC",
+		"CC_FOR_TARGET",
+		"PATH",
+		"TMPDIR",
+		"USER",
+	}
+	if runtime.GOOS == "plan9" {
+		extra = append(extra, "objtype", "cputype", "path")
+	}
+	return extra
+}
diff --git a/third_party/go.tools/dashboard/builder/exec.go b/third_party/go.tools/dashboard/builder/exec.go
new file mode 100644
index 0000000..c40301f
--- /dev/null
+++ b/third_party/go.tools/dashboard/builder/exec.go
@@ -0,0 +1,98 @@
+// 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.
+
+package main
+
+import (
+	"fmt"
+	"io"
+	"log"
+	"os/exec"
+	"time"
+)
+
+// run runs a command with optional arguments.
+func run(cmd *exec.Cmd, opts ...runOpt) error {
+	a := runArgs{cmd, *cmdTimeout}
+	for _, opt := range opts {
+		opt.modArgs(&a)
+	}
+	if *verbose {
+		log.Printf("running %v", a.cmd.Args)
+	}
+	if err := cmd.Start(); err != nil {
+		return err
+	}
+	err := timeout(a.timeout, cmd.Wait)
+	if _, ok := err.(timeoutError); ok {
+		cmd.Process.Kill()
+	}
+	return err
+}
+
+// Zero or more runOpts can be passed to run to modify the command
+// before it's run.
+type runOpt interface {
+	modArgs(*runArgs)
+}
+
+// allOutput sends both stdout and stderr to w.
+func allOutput(w io.Writer) optFunc {
+	return func(a *runArgs) {
+		a.cmd.Stdout = w
+		a.cmd.Stderr = w
+	}
+}
+
+func runTimeout(timeout time.Duration) optFunc {
+	return func(a *runArgs) {
+		a.timeout = timeout
+	}
+}
+
+func runDir(dir string) optFunc {
+	return func(a *runArgs) {
+		a.cmd.Dir = dir
+	}
+}
+
+func runEnv(env []string) optFunc {
+	return func(a *runArgs) {
+		a.cmd.Env = env
+	}
+}
+
+// timeout runs f and returns its error value, or if the function does not
+// complete before the provided duration it returns a timeout error.
+func timeout(d time.Duration, f func() error) error {
+	errc := make(chan error, 1)
+	go func() {
+		errc <- f()
+	}()
+	t := time.NewTimer(d)
+	defer t.Stop()
+	select {
+	case <-t.C:
+		return timeoutError(d)
+	case err := <-errc:
+		return err
+	}
+}
+
+type timeoutError time.Duration
+
+func (e timeoutError) Error() string {
+	return fmt.Sprintf("timed out after %v", time.Duration(e))
+}
+
+// optFunc implements runOpt with a function, like http.HandlerFunc.
+type optFunc func(*runArgs)
+
+func (f optFunc) modArgs(a *runArgs) { f(a) }
+
+// internal detail to exec.go:
+type runArgs struct {
+	cmd     *exec.Cmd
+	timeout time.Duration
+}
diff --git a/third_party/go.tools/dashboard/builder/filemutex_flock.go b/third_party/go.tools/dashboard/builder/filemutex_flock.go
new file mode 100644
index 0000000..68851b8
--- /dev/null
+++ b/third_party/go.tools/dashboard/builder/filemutex_flock.go
@@ -0,0 +1,66 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package main
+
+import (
+	"sync"
+	"syscall"
+)
+
+// FileMutex is similar to sync.RWMutex, but also synchronizes across processes.
+// This implementation is based on flock syscall.
+type FileMutex struct {
+	mu sync.RWMutex
+	fd int
+}
+
+func MakeFileMutex(filename string) *FileMutex {
+	if filename == "" {
+		return &FileMutex{fd: -1}
+	}
+	fd, err := syscall.Open(filename, syscall.O_CREAT|syscall.O_RDONLY, mkdirPerm)
+	if err != nil {
+		panic(err)
+	}
+	return &FileMutex{fd: fd}
+}
+
+func (m *FileMutex) Lock() {
+	m.mu.Lock()
+	if m.fd != -1 {
+		if err := syscall.Flock(m.fd, syscall.LOCK_EX); err != nil {
+			panic(err)
+		}
+	}
+}
+
+func (m *FileMutex) Unlock() {
+	if m.fd != -1 {
+		if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil {
+			panic(err)
+		}
+	}
+	m.mu.Unlock()
+}
+
+func (m *FileMutex) RLock() {
+	m.mu.RLock()
+	if m.fd != -1 {
+		if err := syscall.Flock(m.fd, syscall.LOCK_SH); err != nil {
+			panic(err)
+		}
+	}
+}
+
+func (m *FileMutex) RUnlock() {
+	if m.fd != -1 {
+		if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil {
+			panic(err)
+		}
+	}
+	m.mu.RUnlock()
+}
diff --git a/third_party/go.tools/dashboard/builder/filemutex_local.go b/third_party/go.tools/dashboard/builder/filemutex_local.go
new file mode 100644
index 0000000..68cfb62
--- /dev/null
+++ b/third_party/go.tools/dashboard/builder/filemutex_local.go
@@ -0,0 +1,27 @@
+// Copyright 2013 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.
+
+// +build nacl plan9 solaris
+
+package main
+
+import (
+	"log"
+	"sync"
+)
+
+// FileMutex is similar to sync.RWMutex, but also synchronizes across processes.
+// This implementation is a fallback that does not actually provide inter-process synchronization.
+type FileMutex struct {
+	sync.RWMutex
+}
+
+func MakeFileMutex(filename string) *FileMutex {
+	return &FileMutex{}
+}
+
+func init() {
+	log.Printf("WARNING: using fake file mutex." +
+		" Don't run more than one of these at once!!!")
+}
diff --git a/third_party/go.tools/dashboard/builder/filemutex_windows.go b/third_party/go.tools/dashboard/builder/filemutex_windows.go
new file mode 100644
index 0000000..1f058b2
--- /dev/null
+++ b/third_party/go.tools/dashboard/builder/filemutex_windows.go
@@ -0,0 +1,105 @@
+// Copyright 2013 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 (
+	"sync"
+	"syscall"
+	"unsafe"
+)
+
+var (
+	modkernel32      = syscall.NewLazyDLL("kernel32.dll")
+	procLockFileEx   = modkernel32.NewProc("LockFileEx")
+	procUnlockFileEx = modkernel32.NewProc("UnlockFileEx")
+)
+
+const (
+	INVALID_FILE_HANDLE     = ^syscall.Handle(0)
+	LOCKFILE_EXCLUSIVE_LOCK = 2
+)
+
+func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
+	r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)))
+	if r1 == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func unlockFileEx(h syscall.Handle, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
+	r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(h), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+// FileMutex is similar to sync.RWMutex, but also synchronizes across processes.
+// This implementation is based on flock syscall.
+type FileMutex struct {
+	mu sync.RWMutex
+	fd syscall.Handle
+}
+
+func MakeFileMutex(filename string) *FileMutex {
+	if filename == "" {
+		return &FileMutex{fd: INVALID_FILE_HANDLE}
+	}
+	fd, err := syscall.CreateFile(&(syscall.StringToUTF16(filename)[0]), syscall.GENERIC_READ|syscall.GENERIC_WRITE,
+		syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, nil, syscall.OPEN_ALWAYS, syscall.FILE_ATTRIBUTE_NORMAL, 0)
+	if err != nil {
+		panic(err)
+	}
+	return &FileMutex{fd: fd}
+}
+
+func (m *FileMutex) Lock() {
+	m.mu.Lock()
+	if m.fd != INVALID_FILE_HANDLE {
+		var ol syscall.Overlapped
+		if err := lockFileEx(m.fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ol); err != nil {
+			panic(err)
+		}
+	}
+}
+
+func (m *FileMutex) Unlock() {
+	if m.fd != INVALID_FILE_HANDLE {
+		var ol syscall.Overlapped
+		if err := unlockFileEx(m.fd, 0, 1, 0, &ol); err != nil {
+			panic(err)
+		}
+	}
+	m.mu.Unlock()
+}
+
+func (m *FileMutex) RLock() {
+	m.mu.RLock()
+	if m.fd != INVALID_FILE_HANDLE {
+		var ol syscall.Overlapped
+		if err := lockFileEx(m.fd, 0, 0, 1, 0, &ol); err != nil {
+			panic(err)
+		}
+	}
+}
+
+func (m *FileMutex) RUnlock() {
+	if m.fd != INVALID_FILE_HANDLE {
+		var ol syscall.Overlapped
+		if err := unlockFileEx(m.fd, 0, 1, 0, &ol); err != nil {
+			panic(err)
+		}
+	}
+	m.mu.RUnlock()
+}
diff --git a/third_party/go.tools/dashboard/builder/http.go b/third_party/go.tools/dashboard/builder/http.go
new file mode 100644
index 0000000..3fbad3a
--- /dev/null
+++ b/third_party/go.tools/dashboard/builder/http.go
@@ -0,0 +1,219 @@
+// 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.
+
+package main
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"net/url"
+	"time"
+)
+
+type obj map[string]interface{}
+
+// dash runs the given method and command on the dashboard.
+// If args is non-nil it is encoded as the URL query string.
+// If req is non-nil it is JSON-encoded and passed as the body of the HTTP POST.
+// If resp is non-nil the server's response is decoded into the value pointed
+// to by resp (resp must be a pointer).
+func dash(meth, cmd string, args url.Values, req, resp interface{}) error {
+	var r *http.Response
+	var err error
+	if *verbose {
+		log.Println("dash <-", meth, cmd, args, req)
+	}
+	cmd = *dashboard + "/" + cmd
+	if len(args) > 0 {
+		cmd += "?" + args.Encode()
+	}
+	switch meth {
+	case "GET":
+		if req != nil {
+			log.Panicf("%s to %s with req", meth, cmd)
+		}
+		r, err = http.Get(cmd)
+	case "POST":
+		var body io.Reader
+		if req != nil {
+			b, err := json.Marshal(req)
+			if err != nil {
+				return err
+			}
+			body = bytes.NewBuffer(b)
+		}
+		r, err = http.Post(cmd, "text/json", body)
+	default:
+		log.Panicf("%s: invalid method %q", cmd, meth)
+		panic("invalid method: " + meth)
+	}
+	if err != nil {
+		return err
+	}
+	defer r.Body.Close()
+	if r.StatusCode != http.StatusOK {
+		return fmt.Errorf("bad http response: %v", r.Status)
+	}
+	body := new(bytes.Buffer)
+	if _, err := body.ReadFrom(r.Body); err != nil {
+		return err
+	}
+
+	// Read JSON-encoded Response into provided resp
+	// and return an error if present.
+	var result = struct {
+		Response interface{}
+		Error    string
+	}{
+		// Put the provided resp in here as it can be a pointer to
+		// some value we should unmarshal into.
+		Response: resp,
+	}
+	if err = json.Unmarshal(body.Bytes(), &result); err != nil {
+		log.Printf("json unmarshal %#q: %s\n", body.Bytes(), err)
+		return err
+	}
+	if *verbose {
+		log.Println("dash ->", result)
+	}
+	if result.Error != "" {
+		return errors.New(result.Error)
+	}
+
+	return nil
+}
+
+// todo returns the next hash to build or benchmark.
+func (b *Builder) todo(kinds []string, pkg, goHash string) (kind, rev string, benchs []string, err error) {
+	args := url.Values{
+		"builder":     {b.name},
+		"packagePath": {pkg},
+		"goHash":      {goHash},
+	}
+	for _, k := range kinds {
+		args.Add("kind", k)
+	}
+	var resp *struct {
+		Kind string
+		Data struct {
+			Hash        string
+			PerfResults []string
+		}
+	}
+	if err = dash("GET", "todo", args, nil, &resp); err != nil {
+		return
+	}
+	if resp == nil {
+		return
+	}
+	if *verbose {
+		fmt.Printf("dash resp: %+v\n", *resp)
+	}
+	for _, k := range kinds {
+		if k == resp.Kind {
+			return resp.Kind, resp.Data.Hash, resp.Data.PerfResults, nil
+		}
+	}
+	err = fmt.Errorf("expecting Kinds %q, got %q", kinds, resp.Kind)
+	return
+}
+
+// recordResult sends build results to the dashboard
+func (b *Builder) recordResult(ok bool, pkg, hash, goHash, buildLog string, runTime time.Duration) error {
+	if !*report {
+		return nil
+	}
+	req := obj{
+		"Builder":     b.name,
+		"PackagePath": pkg,
+		"Hash":        hash,
+		"GoHash":      goHash,
+		"OK":          ok,
+		"Log":         buildLog,
+		"RunTime":     runTime,
+	}
+	args := url.Values{"key": {b.key}, "builder": {b.name}}
+	return dash("POST", "result", args, req, nil)
+}
+
+// Result of running a single benchmark on a single commit.
+type PerfResult struct {
+	Builder   string
+	Benchmark string
+	Hash      string
+	OK        bool
+	Metrics   []PerfMetric
+	Artifacts []PerfArtifact
+}
+
+type PerfMetric struct {
+	Type string
+	Val  uint64
+}
+
+type PerfArtifact struct {
+	Type string
+	Body string
+}
+
+// recordPerfResult sends benchmarking results to the dashboard
+func (b *Builder) recordPerfResult(req *PerfResult) error {
+	if !*report {
+		return nil
+	}
+	req.Builder = b.name
+	args := url.Values{"key": {b.key}, "builder": {b.name}}
+	return dash("POST", "perf-result", args, req, nil)
+}
+
+func postCommit(key, pkg string, l *HgLog) error {
+	if !*report {
+		return nil
+	}
+	t, err := time.Parse(time.RFC3339, l.Date)
+	if err != nil {
+		return fmt.Errorf("parsing %q: %v", l.Date, t)
+	}
+	return dash("POST", "commit", url.Values{"key": {key}}, obj{
+		"PackagePath":       pkg,
+		"Hash":              l.Hash,
+		"ParentHash":        l.Parent,
+		"Time":              t.Format(time.RFC3339),
+		"User":              l.Author,
+		"Desc":              l.Desc,
+		"NeedsBenchmarking": l.bench,
+	}, nil)
+}
+
+func dashboardCommit(pkg, hash string) bool {
+	err := dash("GET", "commit", url.Values{
+		"packagePath": {pkg},
+		"hash":        {hash},
+	}, nil, nil)
+	return err == nil
+}
+
+func dashboardPackages(kind string) []string {
+	args := url.Values{"kind": []string{kind}}
+	var resp []struct {
+		Path string
+	}
+	if err := dash("GET", "packages", args, nil, &resp); err != nil {
+		log.Println("dashboardPackages:", err)
+		return nil
+	}
+	if *verbose {
+		fmt.Printf("dash resp: %+v\n", resp)
+	}
+	var pkgs []string
+	for _, r := range resp {
+		pkgs = append(pkgs, r.Path)
+	}
+	return pkgs
+}
diff --git a/third_party/go.tools/dashboard/builder/main.go b/third_party/go.tools/dashboard/builder/main.go
new file mode 100644
index 0000000..6635fc5
--- /dev/null
+++ b/third_party/go.tools/dashboard/builder/main.go
@@ -0,0 +1,831 @@
+// 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.
+
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/http"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/go/vcs"
+)
+
+const (
+	codeProject          = "go"
+	codePyScript         = "misc/dashboard/googlecode_upload.py"
+	gofrontendImportPath = "code.google.com/p/gofrontend"
+	mkdirPerm            = 0750
+	waitInterval         = 30 * time.Second // time to wait before checking for new revs
+	pkgBuildInterval     = 24 * time.Hour   // rebuild packages every 24 hours
+)
+
+type Builder struct {
+	goroot       *Repo
+	name         string
+	goos, goarch string
+	key          string
+	env          builderEnv
+	// Last benchmarking workpath. We reuse it, if do successive benchmarks on the same commit.
+	lastWorkpath string
+}
+
+var (
+	doBuild        = flag.Bool("build", true, "Build and test packages")
+	doBench        = flag.Bool("bench", false, "Run benchmarks")
+	buildroot      = flag.String("buildroot", defaultBuildRoot(), "Directory under which to build")
+	dashboard      = flag.String("dashboard", "https://build.golang.org", "Dashboard app base path")
+	buildRelease   = flag.Bool("release", false, "Build and upload binary release archives")
+	buildRevision  = flag.String("rev", "", "Build specified revision and exit")
+	buildCmd       = flag.String("cmd", filepath.Join(".", allCmd), "Build command (specify relative to go/src/)")
+	buildTool      = flag.String("tool", "go", "Tool to build.")
+	gcPath         = flag.String("gcpath", "code.google.com/p/go", "Path to download gc from")
+	gccPath        = flag.String("gccpath", "https://github.com/mirrors/gcc.git", "Path to download gcc from")
+	benchPath      = flag.String("benchpath", "golang.org/x/benchmarks/bench", "Path to download benchmarks from")
+	failAll        = flag.Bool("fail", false, "fail all builds")
+	parallel       = flag.Bool("parallel", false, "Build multiple targets in parallel")
+	buildTimeout   = flag.Duration("buildTimeout", 60*time.Minute, "Maximum time to wait for builds and tests")
+	cmdTimeout     = flag.Duration("cmdTimeout", 10*time.Minute, "Maximum time to wait for an external command")
+	commitInterval = flag.Duration("commitInterval", 1*time.Minute, "Time to wait between polling for new commits (0 disables commit poller)")
+	commitWatch    = flag.Bool("commitWatch", false, "run the commit watch loop only (do no builds)")
+	benchNum       = flag.Int("benchnum", 5, "Run each benchmark that many times")
+	benchTime      = flag.Duration("benchtime", 5*time.Second, "Benchmarking time for a single benchmark run")
+	benchMem       = flag.Int("benchmem", 64, "Approx RSS value to aim at in benchmarks, in MB")
+	fileLock       = flag.String("filelock", "", "File to lock around benchmaring (synchronizes several builders)")
+	verbose        = flag.Bool("v", false, "verbose")
+	report         = flag.Bool("report", true, "whether to report results to the dashboard")
+)
+
+var (
+	binaryTagRe = regexp.MustCompile(`^(release\.r|weekly\.)[0-9\-.]+`)
+	releaseRe   = regexp.MustCompile(`^release\.r[0-9\-.]+`)
+	allCmd      = "all" + suffix
+	makeCmd     = "make" + suffix
+	raceCmd     = "race" + suffix
+	cleanCmd    = "clean" + suffix
+	suffix      = defaultSuffix()
+	exeExt      = defaultExeExt()
+
+	benchCPU      = CpuList([]int{1})
+	benchAffinity = CpuList([]int{})
+	benchMutex    *FileMutex // Isolates benchmarks from other activities
+)
+
+// CpuList is used as flag.Value for -benchcpu flag.
+type CpuList []int
+
+func (cl *CpuList) String() string {
+	str := ""
+	for _, cpu := range *cl {
+		if str == "" {
+			str = strconv.Itoa(cpu)
+		} else {
+			str += fmt.Sprintf(",%v", cpu)
+		}
+	}
+	return str
+}
+
+func (cl *CpuList) Set(str string) error {
+	*cl = []int{}
+	for _, val := range strings.Split(str, ",") {
+		val = strings.TrimSpace(val)
+		if val == "" {
+			continue
+		}
+		cpu, err := strconv.Atoi(val)
+		if err != nil || cpu <= 0 {
+			return fmt.Errorf("%v is a bad value for GOMAXPROCS", val)
+		}
+		*cl = append(*cl, cpu)
+	}
+	if len(*cl) == 0 {
+		*cl = append(*cl, 1)
+	}
+	return nil
+}
+
+func main() {
+	flag.Var(&benchCPU, "benchcpu", "Comma-delimited list of GOMAXPROCS values for benchmarking")
+	flag.Var(&benchAffinity, "benchaffinity", "Comma-delimited list of affinity values for benchmarking")
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, "usage: %s goos-goarch...\n", os.Args[0])
+		flag.PrintDefaults()
+		os.Exit(2)
+	}
+	flag.Parse()
+	if len(flag.Args()) == 0 && !*commitWatch {
+		flag.Usage()
+	}
+
+	vcs.ShowCmd = *verbose
+	vcs.Verbose = *verbose
+
+	benchMutex = MakeFileMutex(*fileLock)
+
+	rr, err := repoForTool()
+	if err != nil {
+		log.Fatal("Error finding repository:", err)
+	}
+	rootPath := filepath.Join(*buildroot, "goroot")
+	goroot := &Repo{
+		Path:   rootPath,
+		Master: rr,
+	}
+
+	// set up work environment, use existing environment if possible
+	if goroot.Exists() || *failAll {
+		log.Print("Found old workspace, will use it")
+	} else {
+		if err := os.RemoveAll(*buildroot); err != nil {
+			log.Fatalf("Error removing build root (%s): %s", *buildroot, err)
+		}
+		if err := os.Mkdir(*buildroot, mkdirPerm); err != nil {
+			log.Fatalf("Error making build root (%s): %s", *buildroot, err)
+		}
+		var err error
+		goroot, err = RemoteRepo(goroot.Master.Root, rootPath)
+		if err != nil {
+			log.Fatalf("Error creating repository with url (%s): %s", goroot.Master.Root, err)
+		}
+
+		goroot, err = goroot.Clone(goroot.Path, "tip")
+		if err != nil {
+			log.Fatal("Error cloning repository:", err)
+		}
+	}
+
+	// set up builders
+	builders := make([]*Builder, len(flag.Args()))
+	for i, name := range flag.Args() {
+		b, err := NewBuilder(goroot, name)
+		if err != nil {
+			log.Fatal(err)
+		}
+		builders[i] = b
+	}
+
+	if *failAll {
+		failMode(builders)
+		return
+	}
+
+	// if specified, build revision and return
+	if *buildRevision != "" {
+		hash, err := goroot.FullHash(*buildRevision)
+		if err != nil {
+			log.Fatal("Error finding revision: ", err)
+		}
+		var exitErr error
+		for _, b := range builders {
+			if err := b.buildHash(hash); err != nil {
+				log.Println(err)
+				exitErr = err
+			}
+		}
+		if exitErr != nil && !*report {
+			// This mode (-report=false) is used for
+			// testing Docker images, making sure the
+			// environment is correctly configured. For
+			// testing, we want a non-zero exit status, as
+			// returned by log.Fatal:
+			log.Fatal("Build error.")
+		}
+		return
+	}
+
+	if !*doBuild && !*doBench {
+		fmt.Fprintf(os.Stderr, "Nothing to do, exiting (specify either -build or -bench or both)\n")
+		os.Exit(2)
+	}
+
+	// Start commit watcher.
+	if *commitWatch {
+		commitWatcher(goroot)
+		return
+	}
+
+	// go continuous build mode
+	// check for new commits and build them
+	benchMutex.RLock()
+	for {
+		built := false
+		t := time.Now()
+		if *parallel {
+			done := make(chan bool)
+			for _, b := range builders {
+				go func(b *Builder) {
+					done <- b.buildOrBench()
+				}(b)
+			}
+			for _ = range builders {
+				built = <-done || built
+			}
+		} else {
+			for _, b := range builders {
+				built = b.buildOrBench() || built
+			}
+		}
+		// sleep if there was nothing to build
+		benchMutex.RUnlock()
+		if !built {
+			time.Sleep(waitInterval)
+		}
+		benchMutex.RLock()
+		// sleep if we're looping too fast.
+		dt := time.Now().Sub(t)
+		if dt < waitInterval {
+			time.Sleep(waitInterval - dt)
+		}
+	}
+}
+
+// go continuous fail mode
+// check for new commits and FAIL them
+func failMode(builders []*Builder) {
+	for {
+		built := false
+		for _, b := range builders {
+			built = b.failBuild() || built
+		}
+		// stop if there was nothing to fail
+		if !built {
+			break
+		}
+	}
+}
+
+func NewBuilder(goroot *Repo, name string) (*Builder, error) {
+	b := &Builder{
+		goroot: goroot,
+		name:   name,
+	}
+
+	// get builderEnv for this tool
+	var err error
+	if b.env, err = b.builderEnv(name); err != nil {
+		return nil, err
+	}
+	if *report {
+		err = b.setKey()
+	}
+	return b, err
+}
+
+func (b *Builder) setKey() error {
+	// read keys from keyfile
+	fn := ""
+	switch runtime.GOOS {
+	case "plan9":
+		fn = os.Getenv("home")
+	case "windows":
+		fn = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
+	default:
+		fn = os.Getenv("HOME")
+	}
+	fn = filepath.Join(fn, ".gobuildkey")
+	if s := fn + "-" + b.name; isFile(s) { // builder-specific file
+		fn = s
+	}
+	c, err := ioutil.ReadFile(fn)
+	if err != nil {
+		// If the on-disk file doesn't exist, also try the
+		// Google Compute Engine metadata.
+		if v := gceProjectMetadata("buildkey-" + b.name); v != "" {
+			b.key = v
+			return nil
+		}
+		return fmt.Errorf("readKeys %s (%s): %s", b.name, fn, err)
+	}
+	b.key = string(bytes.TrimSpace(bytes.SplitN(c, []byte("\n"), 2)[0]))
+	return nil
+}
+
+func gceProjectMetadata(attr string) string {
+	client := &http.Client{
+		Transport: &http.Transport{
+			Dial: (&net.Dialer{
+				Timeout:   750 * time.Millisecond,
+				KeepAlive: 30 * time.Second,
+			}).Dial,
+			ResponseHeaderTimeout: 750 * time.Millisecond,
+		},
+	}
+	req, _ := http.NewRequest("GET", "http://metadata.google.internal/computeMetadata/v1/project/attributes/"+attr, nil)
+	req.Header.Set("Metadata-Flavor", "Google")
+	res, err := client.Do(req)
+	if err != nil {
+		return ""
+	}
+	defer res.Body.Close()
+	if res.StatusCode != 200 {
+		return ""
+	}
+	slurp, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		return ""
+	}
+	return string(bytes.TrimSpace(slurp))
+}
+
+// builderEnv returns the builderEnv for this buildTool.
+func (b *Builder) builderEnv(name string) (builderEnv, error) {
+	// get goos/goarch from builder string
+	s := strings.SplitN(b.name, "-", 3)
+	if len(s) < 2 {
+		return nil, fmt.Errorf("unsupported builder form: %s", name)
+	}
+	b.goos = s[0]
+	b.goarch = s[1]
+
+	switch *buildTool {
+	case "go":
+		return &goEnv{
+			goos:   s[0],
+			goarch: s[1],
+		}, nil
+	case "gccgo":
+		return &gccgoEnv{}, nil
+	default:
+		return nil, fmt.Errorf("unsupported build tool: %s", *buildTool)
+	}
+}
+
+// buildCmd returns the build command to invoke.
+// Builders which contain the string '-race' in their
+// name will override *buildCmd and return raceCmd.
+func (b *Builder) buildCmd() string {
+	if strings.Contains(b.name, "-race") {
+		return raceCmd
+	}
+	return *buildCmd
+}
+
+// buildOrBench checks for a new commit for this builder
+// and builds or benchmarks it if one is found.
+// It returns true if a build/benchmark was attempted.
+func (b *Builder) buildOrBench() bool {
+	var kinds []string
+	if *doBuild {
+		kinds = append(kinds, "build-go-commit")
+	}
+	if *doBench {
+		kinds = append(kinds, "benchmark-go-commit")
+	}
+	kind, hash, benchs, err := b.todo(kinds, "", "")
+	if err != nil {
+		log.Println(err)
+		return false
+	}
+	if hash == "" {
+		return false
+	}
+	switch kind {
+	case "build-go-commit":
+		if err := b.buildHash(hash); err != nil {
+			log.Println(err)
+		}
+		return true
+	case "benchmark-go-commit":
+		if err := b.benchHash(hash, benchs); err != nil {
+			log.Println(err)
+		}
+		return true
+	default:
+		log.Printf("Unknown todo kind %v", kind)
+		return false
+	}
+}
+
+func (b *Builder) buildHash(hash string) error {
+	log.Println(b.name, "building", hash)
+
+	// create place in which to do work
+	workpath := filepath.Join(*buildroot, b.name+"-"+hash[:12])
+	if err := os.Mkdir(workpath, mkdirPerm); err != nil {
+		if err2 := removePath(workpath); err2 != nil {
+			return err
+		}
+		if err := os.Mkdir(workpath, mkdirPerm); err != nil {
+			return err
+		}
+	}
+	defer removePath(workpath)
+
+	buildLog, runTime, err := b.buildRepoOnHash(workpath, hash, b.buildCmd())
+	if err != nil {
+		// record failure
+		return b.recordResult(false, "", hash, "", buildLog, runTime)
+	}
+
+	// record success
+	if err = b.recordResult(true, "", hash, "", "", runTime); err != nil {
+		return fmt.Errorf("recordResult: %s", err)
+	}
+
+	// build sub-repositories
+	goRoot := filepath.Join(workpath, *buildTool)
+	goPath := workpath
+	b.buildSubrepos(goRoot, goPath, hash)
+
+	return nil
+}
+
+// buildRepoOnHash clones repo into workpath and builds it.
+func (b *Builder) buildRepoOnHash(workpath, hash, cmd string) (buildLog string, runTime time.Duration, err error) {
+	// Delete the previous workdir, if necessary
+	// (benchmarking code can execute several benchmarks in the same workpath).
+	if b.lastWorkpath != "" {
+		if b.lastWorkpath == workpath {
+			panic("workpath already exists: " + workpath)
+		}
+		removePath(b.lastWorkpath)
+		b.lastWorkpath = ""
+	}
+
+	// pull before cloning to ensure we have the revision
+	if err = b.goroot.Pull(); err != nil {
+		buildLog = err.Error()
+		return
+	}
+
+	// set up builder's environment.
+	srcDir, err := b.env.setup(b.goroot, workpath, hash, b.envv())
+	if err != nil {
+		buildLog = err.Error()
+		return
+	}
+
+	// build
+	var buildbuf bytes.Buffer
+	logfile := filepath.Join(workpath, "build.log")
+	f, err := os.Create(logfile)
+	if err != nil {
+		return err.Error(), 0, err
+	}
+	defer f.Close()
+	w := io.MultiWriter(f, &buildbuf)
+
+	// go's build command is a script relative to the srcDir, whereas
+	// gccgo's build command is usually "make check-go" in the srcDir.
+	if *buildTool == "go" {
+		if !filepath.IsAbs(cmd) {
+			cmd = filepath.Join(srcDir, cmd)
+		}
+	}
+
+	// naive splitting of command from its arguments:
+	args := strings.Split(cmd, " ")
+	c := exec.Command(args[0], args[1:]...)
+	c.Dir = srcDir
+	c.Env = b.envv()
+	if *verbose {
+		c.Stdout = io.MultiWriter(os.Stdout, w)
+		c.Stderr = io.MultiWriter(os.Stderr, w)
+	} else {
+		c.Stdout = w
+		c.Stderr = w
+	}
+
+	startTime := time.Now()
+	err = run(c, runTimeout(*buildTimeout))
+	runTime = time.Since(startTime)
+	if err != nil {
+		fmt.Fprintf(w, "Build complete, duration %v. Result: error: %v\n", runTime, err)
+	} else {
+		fmt.Fprintf(w, "Build complete, duration %v. Result: success\n", runTime)
+	}
+	return buildbuf.String(), runTime, err
+}
+
+// failBuild checks for a new commit for this builder
+// and fails it if one is found.
+// It returns true if a build was "attempted".
+func (b *Builder) failBuild() bool {
+	_, hash, _, err := b.todo([]string{"build-go-commit"}, "", "")
+	if err != nil {
+		log.Println(err)
+		return false
+	}
+	if hash == "" {
+		return false
+	}
+
+	log.Printf("fail %s %s\n", b.name, hash)
+
+	if err := b.recordResult(false, "", hash, "", "auto-fail mode run by "+os.Getenv("USER"), 0); err != nil {
+		log.Print(err)
+	}
+	return true
+}
+
+func (b *Builder) buildSubrepos(goRoot, goPath, goHash string) {
+	for _, pkg := range dashboardPackages("subrepo") {
+		// get the latest todo for this package
+		_, hash, _, err := b.todo([]string{"build-package"}, pkg, goHash)
+		if err != nil {
+			log.Printf("buildSubrepos %s: %v", pkg, err)
+			continue
+		}
+		if hash == "" {
+			continue
+		}
+
+		// build the package
+		if *verbose {
+			log.Printf("buildSubrepos %s: building %q", pkg, hash)
+		}
+		buildLog, err := b.buildSubrepo(goRoot, goPath, pkg, hash)
+		if err != nil {
+			if buildLog == "" {
+				buildLog = err.Error()
+			}
+			log.Printf("buildSubrepos %s: %v", pkg, err)
+		}
+
+		// record the result
+		err = b.recordResult(err == nil, pkg, hash, goHash, buildLog, 0)
+		if err != nil {
+			log.Printf("buildSubrepos %s: %v", pkg, err)
+		}
+	}
+}
+
+// buildSubrepo fetches the given package, updates it to the specified hash,
+// and runs 'go test -short pkg/...'. It returns the build log and any error.
+func (b *Builder) buildSubrepo(goRoot, goPath, pkg, hash string) (string, error) {
+	goTool := filepath.Join(goRoot, "bin", "go") + exeExt
+	env := append(b.envv(), "GOROOT="+goRoot, "GOPATH="+goPath)
+
+	// add $GOROOT/bin and $GOPATH/bin to PATH
+	for i, e := range env {
+		const p = "PATH="
+		if !strings.HasPrefix(e, p) {
+			continue
+		}
+		sep := string(os.PathListSeparator)
+		env[i] = p + filepath.Join(goRoot, "bin") + sep + filepath.Join(goPath, "bin") + sep + e[len(p):]
+	}
+
+	// HACK: check out to new sub-repo location instead of old location.
+	pkg = strings.Replace(pkg, "code.google.com/p/go.", "golang.org/x/", 1)
+
+	// fetch package and dependencies
+	var outbuf bytes.Buffer
+	err := run(exec.Command(goTool, "get", "-d", pkg+"/..."), runEnv(env), allOutput(&outbuf), runDir(goPath))
+	if err != nil {
+		return outbuf.String(), err
+	}
+	outbuf.Reset()
+
+	// hg update to the specified hash
+	pkgmaster, err := vcs.RepoRootForImportPath(pkg, *verbose)
+	if err != nil {
+		return "", fmt.Errorf("Error finding subrepo (%s): %s", pkg, err)
+	}
+	repo := &Repo{
+		Path:   filepath.Join(goPath, "src", pkg),
+		Master: pkgmaster,
+	}
+	if err := repo.UpdateTo(hash); err != nil {
+		return "", err
+	}
+
+	// test the package
+	err = run(exec.Command(goTool, "test", "-short", pkg+"/..."),
+		runTimeout(*buildTimeout), runEnv(env), allOutput(&outbuf), runDir(goPath))
+	return outbuf.String(), err
+}
+
+// repoForTool returns the correct RepoRoot for the buildTool, or an error if
+// the tool is unknown.
+func repoForTool() (*vcs.RepoRoot, error) {
+	switch *buildTool {
+	case "go":
+		return vcs.RepoRootForImportPath(*gcPath, *verbose)
+	case "gccgo":
+		return vcs.RepoRootForImportPath(gofrontendImportPath, *verbose)
+	default:
+		return nil, fmt.Errorf("unknown build tool: %s", *buildTool)
+	}
+}
+
+func isDirectory(name string) bool {
+	s, err := os.Stat(name)
+	return err == nil && s.IsDir()
+}
+
+func isFile(name string) bool {
+	s, err := os.Stat(name)
+	return err == nil && !s.IsDir()
+}
+
+// commitWatcher polls hg for new commits and tells the dashboard about them.
+func commitWatcher(goroot *Repo) {
+	if *commitInterval == 0 {
+		log.Printf("commitInterval is 0; disabling commitWatcher")
+		return
+	}
+	if !*report {
+		log.Printf("-report is false; disabling commitWatcher")
+		return
+	}
+	// Create builder just to get master key.
+	b, err := NewBuilder(goroot, "mercurial-commit")
+	if err != nil {
+		log.Fatal(err)
+	}
+	key := b.key
+
+	benchMutex.RLock()
+	for {
+		if *verbose {
+			log.Printf("poll...")
+		}
+		// Main Go repository.
+		commitPoll(goroot, "", key)
+		// Go sub-repositories.
+		for _, pkg := range dashboardPackages("subrepo") {
+			pkgmaster, err := vcs.RepoRootForImportPath(pkg, *verbose)
+			if err != nil {
+				log.Printf("Error finding subrepo (%s): %s", pkg, err)
+				continue
+			}
+			pkgroot := &Repo{
+				Path:   filepath.Join(*buildroot, pkg),
+				Master: pkgmaster,
+			}
+			commitPoll(pkgroot, pkg, key)
+		}
+		benchMutex.RUnlock()
+		if *verbose {
+			log.Printf("sleep...")
+		}
+		time.Sleep(*commitInterval)
+		benchMutex.RLock()
+	}
+}
+
+// logByHash is a cache of all Mercurial revisions we know about,
+// indexed by full hash.
+var logByHash = map[string]*HgLog{}
+
+// commitPoll pulls any new revisions from the hg server
+// and tells the server about them.
+func commitPoll(repo *Repo, pkg, key string) {
+	pkgPath := filepath.Join(*buildroot, repo.Master.Root)
+	if !repo.Exists() {
+		var err error
+		repo, err = RemoteRepo(pkg, pkgPath)
+		if err != nil {
+			log.Printf("Error cloning package (%s): %s", pkg, err)
+			return
+		}
+
+		path := repo.Path
+		repo, err = repo.Clone(path, "tip")
+		if err != nil {
+			log.Printf("%s: hg clone failed: %v", pkg, err)
+			if err := os.RemoveAll(path); err != nil {
+				log.Printf("%s: %v", pkg, err)
+			}
+		}
+		return
+	}
+
+	logs, err := repo.Log() // repo.Log calls repo.Pull internally
+	if err != nil {
+		log.Printf("hg log: %v", err)
+		return
+	}
+
+	// Pass 1.  Fill in parents and add new log entries to logByHash.
+	// Empty parent means take parent from next log entry.
+	// Non-empty parent has form 1234:hashhashhash; we want full hash.
+	for i := range logs {
+		l := &logs[i]
+		if l.Parent == "" && i+1 < len(logs) {
+			l.Parent = logs[i+1].Hash
+		} else if l.Parent != "" {
+			l.Parent, _ = repo.FullHash(l.Parent)
+		}
+		if *verbose {
+			log.Printf("hg log %s: %s < %s\n", pkg, l.Hash, l.Parent)
+		}
+		if logByHash[l.Hash] == nil {
+			l.bench = needsBenchmarking(l)
+			// These fields are needed only for needsBenchmarking, do not waste memory.
+			l.Branch = ""
+			l.Files = ""
+			// Make copy to avoid pinning entire slice when only one entry is new.
+			t := *l
+			logByHash[t.Hash] = &t
+		}
+	}
+
+	for _, l := range logs {
+		addCommit(pkg, l.Hash, key)
+	}
+}
+
+// addCommit adds the commit with the named hash to the dashboard.
+// key is the secret key for authentication to the dashboard.
+// It avoids duplicate effort.
+func addCommit(pkg, hash, key string) bool {
+	l := logByHash[hash]
+	if l == nil {
+		return false
+	}
+	if l.added {
+		return true
+	}
+
+	// Check for already added, perhaps in an earlier run.
+	if dashboardCommit(pkg, hash) {
+		log.Printf("%s already on dashboard\n", hash)
+		// Record that this hash is on the dashboard,
+		// as must be all its parents.
+		for l != nil {
+			l.added = true
+			l = logByHash[l.Parent]
+		}
+		return true
+	}
+
+	// Create parent first, to maintain some semblance of order.
+	if l.Parent != "" {
+		if !addCommit(pkg, l.Parent, key) {
+			return false
+		}
+	}
+
+	// Create commit.
+	if err := postCommit(key, pkg, l); err != nil {
+		log.Printf("failed to add %s to dashboard: %v", hash, err)
+		return false
+	}
+	l.added = true
+	return true
+}
+
+// defaultSuffix returns file extension used for command files in
+// current os environment.
+func defaultSuffix() string {
+	switch runtime.GOOS {
+	case "windows":
+		return ".bat"
+	case "plan9":
+		return ".rc"
+	default:
+		return ".bash"
+	}
+}
+
+func defaultExeExt() string {
+	switch runtime.GOOS {
+	case "windows":
+		return ".exe"
+	default:
+		return ""
+	}
+}
+
+// defaultBuildRoot returns default buildroot directory.
+func defaultBuildRoot() string {
+	var d string
+	if runtime.GOOS == "windows" {
+		// will use c:\, otherwise absolute paths become too long
+		// during builder run, see http://golang.org/issue/3358.
+		d = `c:\`
+	} else {
+		d = os.TempDir()
+	}
+	return filepath.Join(d, "gobuilder")
+}
+
+// removePath is a more robust version of os.RemoveAll.
+// On windows, if remove fails (which can happen if test/benchmark timeouts
+// and keeps some files open) it tries to rename the dir.
+func removePath(path string) error {
+	if err := os.RemoveAll(path); err != nil {
+		if runtime.GOOS == "windows" {
+			err = os.Rename(path, filepath.Clean(path)+"_remove_me")
+		}
+		return err
+	}
+	return nil
+}
diff --git a/third_party/go.tools/dashboard/builder/vcs.go b/third_party/go.tools/dashboard/builder/vcs.go
new file mode 100644
index 0000000..e7bfc7b
--- /dev/null
+++ b/third_party/go.tools/dashboard/builder/vcs.go
@@ -0,0 +1,212 @@
+// Copyright 2013 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 (
+	"bytes"
+	"encoding/xml"
+	"fmt"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"sync"
+
+	"llvm.org/llgo/third_party/go.tools/go/vcs"
+)
+
+// Repo represents a mercurial repository.
+type Repo struct {
+	Path   string
+	Master *vcs.RepoRoot
+	sync.Mutex
+}
+
+// RemoteRepo constructs a *Repo representing a remote repository.
+func RemoteRepo(url, path string) (*Repo, error) {
+	rr, err := vcs.RepoRootForImportPath(url, *verbose)
+	if err != nil {
+		return nil, err
+	}
+	return &Repo{
+		Path:   path,
+		Master: rr,
+	}, nil
+}
+
+// Clone clones the current Repo to a new destination
+// returning a new *Repo if successful.
+func (r *Repo) Clone(path, rev string) (*Repo, error) {
+	r.Lock()
+	defer r.Unlock()
+
+	err := timeout(*cmdTimeout, func() error {
+		downloadPath := r.Path
+		if !r.Exists() {
+			downloadPath = r.Master.Repo
+		}
+
+		err := r.Master.VCS.CreateAtRev(path, downloadPath, rev)
+		if err != nil {
+			return err
+		}
+		return r.Master.VCS.TagSync(path, "")
+	})
+	if err != nil {
+		return nil, err
+	}
+	return &Repo{
+		Path:   path,
+		Master: r.Master,
+	}, nil
+}
+
+// Export exports the current Repo at revision rev to a new destination.
+func (r *Repo) Export(path, rev string) error {
+	r.Lock()
+	defer r.Unlock()
+
+	downloadPath := r.Path
+	if !r.Exists() {
+		_, err := r.Clone(path, rev)
+		return err
+	}
+
+	cmd := exec.Command(r.Master.VCS.Cmd, "archive", "-t", "files", "-r", rev, path)
+	cmd.Dir = downloadPath
+	if err := run(cmd); err != nil {
+		return fmt.Errorf("executing %v: %v", cmd.Args, err)
+	}
+	return nil
+}
+
+// UpdateTo updates the working copy of this Repo to the
+// supplied revision.
+func (r *Repo) UpdateTo(hash string) error {
+	r.Lock()
+	defer r.Unlock()
+
+	return timeout(*cmdTimeout, func() error {
+		return r.Master.VCS.TagSync(r.Path, hash)
+	})
+}
+
+// Exists reports whether this Repo represents a valid Mecurial repository.
+func (r *Repo) Exists() bool {
+	fi, err := os.Stat(filepath.Join(r.Path, "."+r.Master.VCS.Cmd))
+	if err != nil {
+		return false
+	}
+	return fi.IsDir()
+}
+
+// Pull pulls changes from the default path, that is, the path
+// this Repo was cloned from.
+func (r *Repo) Pull() error {
+	r.Lock()
+	defer r.Unlock()
+
+	return timeout(*cmdTimeout, func() error {
+		return r.Master.VCS.Download(r.Path)
+	})
+}
+
+// Log returns the changelog for this repository.
+func (r *Repo) Log() ([]HgLog, error) {
+	if err := r.Pull(); err != nil {
+		return nil, err
+	}
+	r.Lock()
+	defer r.Unlock()
+
+	var logStruct struct {
+		Log []HgLog
+	}
+	err := timeout(*cmdTimeout, func() error {
+		data, err := r.Master.VCS.Log(r.Path, xmlLogTemplate)
+		if err != nil {
+			return err
+		}
+
+		// We have a commit with description that contains 0x1b byte.
+		// Mercurial does not escape it, but xml.Unmarshal does not accept it.
+		data = bytes.Replace(data, []byte{0x1b}, []byte{'?'}, -1)
+
+		err = xml.Unmarshal([]byte("<Top>"+string(data)+"</Top>"), &logStruct)
+		if err != nil {
+			return fmt.Errorf("unmarshal %s log: %v", r.Master.VCS, err)
+		}
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+	for i, log := range logStruct.Log {
+		// Let's pretend there can be only one parent.
+		if log.Parent != "" && strings.Contains(log.Parent, " ") {
+			logStruct.Log[i].Parent = strings.Split(log.Parent, " ")[0]
+		}
+	}
+	return logStruct.Log, nil
+}
+
+// FullHash returns the full hash for the given Mercurial revision.
+func (r *Repo) FullHash(rev string) (string, error) {
+	r.Lock()
+	defer r.Unlock()
+
+	var hash string
+	err := timeout(*cmdTimeout, func() error {
+		data, err := r.Master.VCS.LogAtRev(r.Path, rev, "{node}")
+		if err != nil {
+			return err
+		}
+
+		s := strings.TrimSpace(string(data))
+		if s == "" {
+			return fmt.Errorf("cannot find revision")
+		}
+		if len(s) != 40 {
+			return fmt.Errorf("%s returned invalid hash: %s", r.Master.VCS, s)
+		}
+		hash = s
+		return nil
+	})
+	if err != nil {
+		return "", err
+	}
+	return hash, nil
+}
+
+// HgLog represents a single Mercurial revision.
+type HgLog struct {
+	Hash   string
+	Author string
+	Date   string
+	Desc   string
+	Parent string
+	Branch string
+	Files  string
+
+	// Internal metadata
+	added bool
+	bench bool // needs to be benchmarked?
+}
+
+// xmlLogTemplate is a template to pass to Mercurial to make
+// hg log print the log in valid XML for parsing with xml.Unmarshal.
+// Can not escape branches and files, because it crashes python with:
+// AttributeError: 'NoneType' object has no attribute 'replace'
+const xmlLogTemplate = `
+        <Log>
+        <Hash>{node|escape}</Hash>
+        <Parent>{p1node}</Parent>
+        <Author>{author|escape}</Author>
+        <Date>{date|rfc3339date}</Date>
+        <Desc>{desc|escape}</Desc>
+        <Branch>{branches}</Branch>
+        <Files>{files}</Files>
+        </Log>
+`
diff --git a/third_party/go.tools/dashboard/coordinator/Makefile b/third_party/go.tools/dashboard/coordinator/Makefile
new file mode 100644
index 0000000..ec1d88b
--- /dev/null
+++ b/third_party/go.tools/dashboard/coordinator/Makefile
@@ -0,0 +1,6 @@
+coordinator: main.go
+	GOOS=linux go build -o coordinator .
+
+upload: coordinator
+	cat coordinator | (cd buildongce && go run create.go --write_object=go-builder-data/coordinator)
+
diff --git a/third_party/go.tools/dashboard/coordinator/buildongce/create.go b/third_party/go.tools/dashboard/coordinator/buildongce/create.go
new file mode 100644
index 0000000..d4f0cd6
--- /dev/null
+++ b/third_party/go.tools/dashboard/coordinator/buildongce/create.go
@@ -0,0 +1,306 @@
+// Copyright 2014 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 (
+	"bufio"
+	"bytes"
+	"encoding/json"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"os"
+	"strings"
+	"time"
+
+	"code.google.com/p/goauth2/oauth"
+	compute "code.google.com/p/google-api-go-client/compute/v1"
+)
+
+var (
+	proj      = flag.String("project", "symbolic-datum-552", "name of Project")
+	zone      = flag.String("zone", "us-central1-a", "GCE zone")
+	mach      = flag.String("machinetype", "n1-standard-16", "Machine type")
+	instName  = flag.String("instance_name", "go-builder-1", "Name of VM instance.")
+	sshPub    = flag.String("ssh_public_key", "", "ssh public key file to authorize. Can modify later in Google's web UI anyway.")
+	staticIP  = flag.String("static_ip", "", "Static IP to use. If empty, automatic.")
+	reuseDisk = flag.Bool("reuse_disk", true, "Whether disk images should be reused between shutdowns/restarts.")
+
+	writeObject = flag.String("write_object", "", "If non-empty, a VM isn't created and the flag value is Google Cloud Storage bucket/object to write. The contents from stdin.")
+)
+
+func readFile(v string) string {
+	slurp, err := ioutil.ReadFile(v)
+	if err != nil {
+		log.Fatalf("Error reading %s: %v", v, err)
+	}
+	return strings.TrimSpace(string(slurp))
+}
+
+var config = &oauth.Config{
+	// The client-id and secret should be for an "Installed Application" when using
+	// the CLI. Later we'll use a web application with a callback.
+	ClientId:     readFile("client-id.dat"),
+	ClientSecret: readFile("client-secret.dat"),
+	Scope: strings.Join([]string{
+		compute.DevstorageFull_controlScope,
+		compute.ComputeScope,
+		"https://www.googleapis.com/auth/sqlservice",
+		"https://www.googleapis.com/auth/sqlservice.admin",
+	}, " "),
+	AuthURL:     "https://accounts.google.com/o/oauth2/auth",
+	TokenURL:    "https://accounts.google.com/o/oauth2/token",
+	RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
+}
+
+const baseConfig = `#cloud-config
+coreos:
+  units:
+    - name: gobuild.service
+      command: start
+      content: |
+        [Unit]
+        Description=Go Builders
+        After=docker.service
+        Requires=docker.service
+        
+        [Service]
+        ExecStartPre=/bin/bash -c 'mkdir -p /opt/bin && curl -s -o /opt/bin/coordinator http://storage.googleapis.com/go-builder-data/coordinator && chmod +x /opt/bin/coordinator'
+        ExecStart=/opt/bin/coordinator
+        RestartSec=10s
+        Restart=always
+        Type=simple
+        
+        [Install]
+        WantedBy=multi-user.target
+`
+
+func main() {
+	flag.Parse()
+	if *proj == "" {
+		log.Fatalf("Missing --project flag")
+	}
+	prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
+	machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach
+
+	tr := &oauth.Transport{
+		Config: config,
+	}
+
+	tokenCache := oauth.CacheFile("token.dat")
+	token, err := tokenCache.Token()
+	if err != nil {
+		if *writeObject != "" {
+			log.Fatalf("Can't use --write_object without a valid token.dat file already cached.")
+		}
+		log.Printf("Error getting token from %s: %v", string(tokenCache), err)
+		log.Printf("Get auth code from %v", config.AuthCodeURL("my-state"))
+		fmt.Print("\nEnter auth code: ")
+		sc := bufio.NewScanner(os.Stdin)
+		sc.Scan()
+		authCode := strings.TrimSpace(sc.Text())
+		token, err = tr.Exchange(authCode)
+		if err != nil {
+			log.Fatalf("Error exchanging auth code for a token: %v", err)
+		}
+		tokenCache.PutToken(token)
+	}
+
+	tr.Token = token
+	oauthClient := &http.Client{Transport: tr}
+	if *writeObject != "" {
+		writeCloudStorageObject(oauthClient)
+		return
+	}
+
+	computeService, _ := compute.New(oauthClient)
+
+	natIP := *staticIP
+	if natIP == "" {
+		// Try to find it by name.
+		aggAddrList, err := computeService.Addresses.AggregatedList(*proj).Do()
+		if err != nil {
+			log.Fatal(err)
+		}
+		// http://godoc.org/code.google.com/p/google-api-go-client/compute/v1#AddressAggregatedList
+	IPLoop:
+		for _, asl := range aggAddrList.Items {
+			for _, addr := range asl.Addresses {
+				if addr.Name == *instName+"-ip" && addr.Status == "RESERVED" {
+					natIP = addr.Address
+					break IPLoop
+				}
+			}
+		}
+	}
+
+	cloudConfig := baseConfig
+	if *sshPub != "" {
+		key := strings.TrimSpace(readFile(*sshPub))
+		cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n    - %s\n", key)
+	}
+	if os.Getenv("USER") == "bradfitz" {
+		cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n    - %s\n", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwks9dwWKlRC+73gRbvYtVg0vdCwDSuIlyt4z6xa/YU/jTDynM4R4W10hm2tPjy8iR1k8XhDv4/qdxe6m07NjG/By1tkmGpm1mGwho4Pr5kbAAy/Qg+NLCSdAYnnE00FQEcFOC15GFVMOW2AzDGKisReohwH9eIzHPzdYQNPRWXE= bradfitz@papag.bradfitz.com")
+	}
+	const maxCloudConfig = 32 << 10 // per compute API docs
+	if len(cloudConfig) > maxCloudConfig {
+		log.Fatalf("cloud config length of %d bytes is over %d byte limit", len(cloudConfig), maxCloudConfig)
+	}
+
+	instance := &compute.Instance{
+		Name:        *instName,
+		Description: "Go Builder",
+		MachineType: machType,
+		Disks:       []*compute.AttachedDisk{instanceDisk(computeService)},
+		Tags: &compute.Tags{
+			Items: []string{"http-server", "https-server"},
+		},
+		Metadata: &compute.Metadata{
+			Items: []*compute.MetadataItems{
+				{
+					Key:   "user-data",
+					Value: cloudConfig,
+				},
+			},
+		},
+		NetworkInterfaces: []*compute.NetworkInterface{
+			&compute.NetworkInterface{
+				AccessConfigs: []*compute.AccessConfig{
+					&compute.AccessConfig{
+						Type:  "ONE_TO_ONE_NAT",
+						Name:  "External NAT",
+						NatIP: natIP,
+					},
+				},
+				Network: prefix + "/global/networks/default",
+			},
+		},
+		ServiceAccounts: []*compute.ServiceAccount{
+			{
+				Email: "default",
+				Scopes: []string{
+					compute.DevstorageFull_controlScope,
+					compute.ComputeScope,
+				},
+			},
+		},
+	}
+
+	log.Printf("Creating instance...")
+	op, err := computeService.Instances.Insert(*proj, *zone, instance).Do()
+	if err != nil {
+		log.Fatalf("Failed to create instance: %v", err)
+	}
+	opName := op.Name
+	log.Printf("Created. Waiting on operation %v", opName)
+OpLoop:
+	for {
+		time.Sleep(2 * time.Second)
+		op, err := computeService.ZoneOperations.Get(*proj, *zone, opName).Do()
+		if err != nil {
+			log.Fatalf("Failed to get op %s: %v", opName, err)
+		}
+		switch op.Status {
+		case "PENDING", "RUNNING":
+			log.Printf("Waiting on operation %v", opName)
+			continue
+		case "DONE":
+			if op.Error != nil {
+				for _, operr := range op.Error.Errors {
+					log.Printf("Error: %+v", operr)
+				}
+				log.Fatalf("Failed to start.")
+			}
+			log.Printf("Success. %+v", op)
+			break OpLoop
+		default:
+			log.Fatalf("Unknown status %q: %+v", op.Status, op)
+		}
+	}
+
+	inst, err := computeService.Instances.Get(*proj, *zone, *instName).Do()
+	if err != nil {
+		log.Fatalf("Error getting instance after creation: %v", err)
+	}
+	ij, _ := json.MarshalIndent(inst, "", "    ")
+	log.Printf("Instance: %s", ij)
+}
+
+func instanceDisk(svc *compute.Service) *compute.AttachedDisk {
+	const imageURL = "https://www.googleapis.com/compute/v1/projects/coreos-cloud/global/images/coreos-alpha-402-2-0-v20140807"
+	diskName := *instName + "-coreos-stateless-pd"
+
+	if *reuseDisk {
+		dl, err := svc.Disks.List(*proj, *zone).Do()
+		if err != nil {
+			log.Fatalf("Error listing disks: %v", err)
+		}
+		for _, disk := range dl.Items {
+			if disk.Name != diskName {
+				continue
+			}
+			return &compute.AttachedDisk{
+				AutoDelete: false,
+				Boot:       true,
+				DeviceName: diskName,
+				Type:       "PERSISTENT",
+				Source:     disk.SelfLink,
+				Mode:       "READ_WRITE",
+
+				// The GCP web UI's "Show REST API" link includes a
+				// "zone" parameter, but it's not in the API
+				// description. But it wants this form (disk.Zone, a
+				// full zone URL, not *zone):
+				// Zone: disk.Zone,
+				// ... but it seems to work without it.  Keep this
+				// comment here until I file a bug with the GCP
+				// people.
+			}
+		}
+	}
+
+	return &compute.AttachedDisk{
+		AutoDelete: !*reuseDisk,
+		Boot:       true,
+		Type:       "PERSISTENT",
+		InitializeParams: &compute.AttachedDiskInitializeParams{
+			DiskName:    diskName,
+			SourceImage: imageURL,
+			DiskSizeGb:  50,
+		},
+	}
+}
+
+func writeCloudStorageObject(httpClient *http.Client) {
+	content := os.Stdin
+	const maxSlurp = 1 << 20
+	var buf bytes.Buffer
+	n, err := io.CopyN(&buf, content, maxSlurp)
+	if err != nil && err != io.EOF {
+		log.Fatalf("Error reading from stdin: %v, %v", n, err)
+	}
+	contentType := http.DetectContentType(buf.Bytes())
+
+	req, err := http.NewRequest("PUT", "https://storage.googleapis.com/"+*writeObject, io.MultiReader(&buf, content))
+	if err != nil {
+		log.Fatal(err)
+	}
+	req.Header.Set("x-goog-api-version", "2")
+	req.Header.Set("x-goog-acl", "public-read")
+	req.Header.Set("Content-Type", contentType)
+	res, err := httpClient.Do(req)
+	if err != nil {
+		log.Fatal(err)
+	}
+	if res.StatusCode != 200 {
+		res.Write(os.Stderr)
+		log.Fatalf("Failed.")
+	}
+	log.Printf("Success.")
+	os.Exit(0)
+}
diff --git a/third_party/go.tools/dashboard/coordinator/main.go b/third_party/go.tools/dashboard/coordinator/main.go
new file mode 100644
index 0000000..a855000
--- /dev/null
+++ b/third_party/go.tools/dashboard/coordinator/main.go
@@ -0,0 +1,458 @@
+// Copyright 2014 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.
+
+// The coordinator runs on GCE and coordinates builds in Docker containers.
+package main
+
+import (
+	"bytes"
+	"crypto/hmac"
+	"crypto/md5"
+	"encoding/json"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"os"
+	"os/exec"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+)
+
+var (
+	masterKeyFile = flag.String("masterkey", "", "Path to builder master key. Else fetched using GCE project attribute 'builder-master-key'.")
+	maxBuilds     = flag.Int("maxbuilds", 6, "Max concurrent builds")
+
+	// Debug flags:
+	addTemp = flag.Bool("temp", false, "Append -temp to all builders.")
+	just    = flag.String("just", "", "If non-empty, run single build in the foreground. Requires rev.")
+	rev     = flag.String("rev", "", "Revision to build.")
+)
+
+var (
+	startTime = time.Now()
+	builders  = map[string]buildConfig{} // populated once at startup
+	donec     = make(chan builderRev)    // reports of finished builders
+
+	statusMu sync.Mutex
+	status   = map[builderRev]*buildStatus{}
+)
+
+type imageInfo struct {
+	url string // of tar file
+
+	mu      sync.Mutex
+	lastMod string
+}
+
+var images = map[string]*imageInfo{
+	"gobuilders/linux-x86-base":  {url: "https://storage.googleapis.com/go-builder-data/docker-linux.base.tar.gz"},
+	"gobuilders/linux-x86-clang": {url: "https://storage.googleapis.com/go-builder-data/docker-linux.clang.tar.gz"},
+	"gobuilders/linux-x86-gccgo": {url: "https://storage.googleapis.com/go-builder-data/docker-linux.gccgo.tar.gz"},
+	"gobuilders/linux-x86-nacl":  {url: "https://storage.googleapis.com/go-builder-data/docker-linux.nacl.tar.gz"},
+	"gobuilders/linux-x86-sid":   {url: "https://storage.googleapis.com/go-builder-data/docker-linux.sid.tar.gz"},
+}
+
+type buildConfig struct {
+	name    string   // "linux-amd64-race"
+	image   string   // Docker image to use to build
+	cmd     string   // optional -cmd flag (relative to go/src/)
+	env     []string // extra environment ("key=value") pairs
+	dashURL string   // url of the build dashboard
+	tool    string   // the tool this configuration is for
+}
+
+func main() {
+	flag.Parse()
+	addBuilder(buildConfig{name: "linux-386"})
+	addBuilder(buildConfig{name: "linux-386-387", env: []string{"GO386=387"}})
+	addBuilder(buildConfig{name: "linux-amd64"})
+	addBuilder(buildConfig{name: "linux-amd64-nocgo", env: []string{"CGO_ENABLED=0", "USER=root"}})
+	addBuilder(buildConfig{name: "linux-amd64-noopt", env: []string{"GO_GCFLAGS=-N -l"}})
+	addBuilder(buildConfig{name: "linux-amd64-race"})
+	addBuilder(buildConfig{name: "nacl-386"})
+	addBuilder(buildConfig{name: "nacl-amd64p32"})
+	addBuilder(buildConfig{
+		name:    "linux-amd64-gccgo",
+		image:   "gobuilders/linux-x86-gccgo",
+		cmd:     "make RUNTESTFLAGS=\"--target_board=unix/-m64\" check-go -j16",
+		dashURL: "https://build.golang.org/gccgo",
+		tool:    "gccgo",
+	})
+	addBuilder(buildConfig{
+		name:    "linux-386-gccgo",
+		image:   "gobuilders/linux-x86-gccgo",
+		cmd:     "make RUNTESTFLAGS=\"--target_board=unix/-m32\" check-go -j16",
+		dashURL: "https://build.golang.org/gccgo",
+		tool:    "gccgo",
+	})
+	addBuilder(buildConfig{name: "linux-386-sid", image: "gobuilders/linux-x86-sid"})
+	addBuilder(buildConfig{name: "linux-amd64-sid", image: "gobuilders/linux-x86-sid"})
+	addBuilder(buildConfig{name: "linux-386-clang", image: "gobuilders/linux-x86-clang"})
+	addBuilder(buildConfig{name: "linux-amd64-clang", image: "gobuilders/linux-x86-clang"})
+
+	if (*just != "") != (*rev != "") {
+		log.Fatalf("--just and --rev must be used together")
+	}
+	if *just != "" {
+		conf, ok := builders[*just]
+		if !ok {
+			log.Fatalf("unknown builder %q", *just)
+		}
+		cmd := exec.Command("docker", append([]string{"run"}, conf.dockerRunArgs(*rev)...)...)
+		cmd.Stdout = os.Stdout
+		cmd.Stderr = os.Stderr
+		if err := cmd.Run(); err != nil {
+			log.Fatalf("Build failed: %v", err)
+		}
+		return
+	}
+
+	http.HandleFunc("/", handleStatus)
+	http.HandleFunc("/logs", handleLogs)
+	go http.ListenAndServe(":80", nil)
+
+	workc := make(chan builderRev)
+	for name, builder := range builders {
+		go findWorkLoop(name, builder.dashURL, workc)
+	}
+
+	ticker := time.NewTicker(1 * time.Minute)
+	for {
+		select {
+		case work := <-workc:
+			log.Printf("workc received %+v; len(status) = %v, maxBuilds = %v; cur = %p", work, len(status), *maxBuilds, status[work])
+			mayBuild := mayBuildRev(work)
+			if mayBuild {
+				out, _ := exec.Command("docker", "ps").Output()
+				numBuilds := bytes.Count(out, []byte("\n")) - 1
+				log.Printf("num current docker builds: %d", numBuilds)
+				if numBuilds > *maxBuilds {
+					mayBuild = false
+				}
+			}
+			if mayBuild {
+				if st, err := startBuilding(builders[work.name], work.rev); err == nil {
+					setStatus(work, st)
+					log.Printf("%v now building in %v", work, st.container)
+				} else {
+					log.Printf("Error starting to build %v: %v", work, err)
+				}
+			}
+		case done := <-donec:
+			log.Printf("%v done", done)
+			setStatus(done, nil)
+		case <-ticker.C:
+			if numCurrentBuilds() == 0 && time.Now().After(startTime.Add(10*time.Minute)) {
+				// TODO: halt the whole machine to kill the VM or something
+			}
+		}
+	}
+}
+
+func numCurrentBuilds() int {
+	statusMu.Lock()
+	defer statusMu.Unlock()
+	return len(status)
+}
+
+func mayBuildRev(work builderRev) bool {
+	statusMu.Lock()
+	defer statusMu.Unlock()
+	return len(status) < *maxBuilds && status[work] == nil
+}
+
+func setStatus(work builderRev, st *buildStatus) {
+	statusMu.Lock()
+	defer statusMu.Unlock()
+	if st == nil {
+		delete(status, work)
+	} else {
+		status[work] = st
+	}
+}
+
+func getStatus(work builderRev) *buildStatus {
+	statusMu.Lock()
+	defer statusMu.Unlock()
+	return status[work]
+}
+
+type byAge []*buildStatus
+
+func (s byAge) Len() int           { return len(s) }
+func (s byAge) Less(i, j int) bool { return s[i].start.Before(s[j].start) }
+func (s byAge) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+
+func handleStatus(w http.ResponseWriter, r *http.Request) {
+	var active []*buildStatus
+	statusMu.Lock()
+	for _, st := range status {
+		active = append(active, st)
+	}
+	statusMu.Unlock()
+
+	fmt.Fprintf(w, "<html><body><h1>Go build coordinator</h1>%d of max %d builds running:<p><pre>", len(status), *maxBuilds)
+	sort.Sort(byAge(active))
+	for _, st := range active {
+		fmt.Fprintf(w, "%-22s hg %s in container <a href='/logs?name=%s&rev=%s'>%s</a>, %v ago\n", st.name, st.rev, st.name, st.rev,
+			st.container, time.Now().Sub(st.start))
+	}
+	fmt.Fprintf(w, "</pre></body></html>")
+}
+
+func handleLogs(w http.ResponseWriter, r *http.Request) {
+	st := getStatus(builderRev{r.FormValue("name"), r.FormValue("rev")})
+	if st == nil {
+		fmt.Fprintf(w, "<html><body><h1>not building</h1>")
+		return
+	}
+	out, err := exec.Command("docker", "logs", st.container).CombinedOutput()
+	if err != nil {
+		log.Print(err)
+		http.Error(w, "Error fetching logs. Already finished?", 500)
+		return
+	}
+	key := builderKey(st.name)
+	logs := strings.Replace(string(out), key, "BUILDERKEY", -1)
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	io.WriteString(w, logs)
+}
+
+func findWorkLoop(builderName, dashURL string, work chan<- builderRev) {
+	// TODO: make this better
+	for {
+		rev, err := findWork(builderName, dashURL)
+		if err != nil {
+			log.Printf("Finding work for %s: %v", builderName, err)
+		} else if rev != "" {
+			work <- builderRev{builderName, rev}
+		}
+		time.Sleep(60 * time.Second)
+	}
+}
+
+func findWork(builderName, dashURL string) (rev string, err error) {
+	var jres struct {
+		Response struct {
+			Kind string
+			Data struct {
+				Hash        string
+				PerfResults []string
+			}
+		}
+	}
+	res, err := http.Get(dashURL + "/todo?builder=" + builderName + "&kind=build-go-commit")
+	if err != nil {
+		return
+	}
+	defer res.Body.Close()
+	if res.StatusCode != 200 {
+		return "", fmt.Errorf("unexpected http status %d", res.StatusCode)
+	}
+	err = json.NewDecoder(res.Body).Decode(&jres)
+	if jres.Response.Kind == "build-go-commit" {
+		rev = jres.Response.Data.Hash
+	}
+	return rev, err
+}
+
+type builderRev struct {
+	name, rev string
+}
+
+// returns the part after "docker run"
+func (conf buildConfig) dockerRunArgs(rev string) (args []string) {
+	if key := builderKey(conf.name); key != "" {
+		tmpKey := "/tmp/" + conf.name + ".buildkey"
+		if _, err := os.Stat(tmpKey); err != nil {
+			if err := ioutil.WriteFile(tmpKey, []byte(key), 0600); err != nil {
+				log.Fatal(err)
+			}
+		}
+		// Images may look for .gobuildkey in / or /root, so provide both.
+		// TODO(adg): fix images that look in the wrong place.
+		args = append(args, "-v", tmpKey+":/.gobuildkey")
+		args = append(args, "-v", tmpKey+":/root/.gobuildkey")
+	}
+	for _, pair := range conf.env {
+		args = append(args, "-e", pair)
+	}
+	args = append(args,
+		conf.image,
+		"/usr/local/bin/builder",
+		"-rev="+rev,
+		"-dashboard="+conf.dashURL,
+		"-tool="+conf.tool,
+		"-buildroot=/",
+		"-v",
+	)
+	if conf.cmd != "" {
+		args = append(args, "-cmd", conf.cmd)
+	}
+	args = append(args, conf.name)
+	return
+}
+
+func addBuilder(c buildConfig) {
+	if c.name == "" {
+		panic("empty name")
+	}
+	if *addTemp {
+		c.name += "-temp"
+	}
+	if _, dup := builders[c.name]; dup {
+		panic("dup name")
+	}
+	if c.dashURL == "" {
+		c.dashURL = "https://build.golang.org"
+	}
+	if c.tool == "" {
+		c.tool = "go"
+	}
+
+	if strings.HasPrefix(c.name, "nacl-") {
+		if c.image == "" {
+			c.image = "gobuilders/linux-x86-nacl"
+		}
+		if c.cmd == "" {
+			c.cmd = "/usr/local/bin/build-command.pl"
+		}
+	}
+	if strings.HasPrefix(c.name, "linux-") && c.image == "" {
+		c.image = "gobuilders/linux-x86-base"
+	}
+	if c.image == "" {
+		panic("empty image")
+	}
+	builders[c.name] = c
+}
+
+func condUpdateImage(img string) error {
+	ii := images[img]
+	if ii == nil {
+		log.Fatalf("Image %q not described.", img)
+	}
+	ii.mu.Lock()
+	defer ii.mu.Unlock()
+	res, err := http.Head(ii.url)
+	if err != nil {
+		return fmt.Errorf("Error checking %s: %v", ii.url, err)
+	}
+	if res.StatusCode != 200 {
+		return fmt.Errorf("Error checking %s: %v", ii.url, res.Status)
+	}
+	if res.Header.Get("Last-Modified") == ii.lastMod {
+		return nil
+	}
+
+	res, err = http.Get(ii.url)
+	if err != nil || res.StatusCode != 200 {
+		return fmt.Errorf("Get after Head failed for %s: %v, %v", ii.url, err, res)
+	}
+	defer res.Body.Close()
+
+	log.Printf("Running: docker load of %s\n", ii.url)
+	cmd := exec.Command("docker", "load")
+	cmd.Stdin = res.Body
+
+	var out bytes.Buffer
+	cmd.Stdout = &out
+	cmd.Stderr = &out
+
+	if cmd.Run(); err != nil {
+		log.Printf("Failed to pull latest %s from %s and pipe into docker load: %v, %s", img, ii.url, err, out.Bytes())
+		return err
+	}
+	ii.lastMod = res.Header.Get("Last-Modified")
+	return nil
+}
+
+func startBuilding(conf buildConfig, rev string) (*buildStatus, error) {
+	if err := condUpdateImage(conf.image); err != nil {
+		log.Printf("Failed to setup container for %v %v: %v", conf.name, rev, err)
+		return nil, err
+	}
+
+	cmd := exec.Command("docker", append([]string{"run", "-d"}, conf.dockerRunArgs(rev)...)...)
+	all, err := cmd.CombinedOutput()
+	log.Printf("Docker run for %v %v = err:%v, output:%s", conf.name, rev, err, all)
+	if err != nil {
+		return nil, err
+	}
+	container := strings.TrimSpace(string(all))
+	go func() {
+		all, err := exec.Command("docker", "wait", container).CombinedOutput()
+		log.Printf("docker wait %s/%s: %v, %s", container, rev, err, strings.TrimSpace(string(all)))
+		donec <- builderRev{conf.name, rev}
+		exec.Command("docker", "rm", container).Run()
+	}()
+	return &buildStatus{
+		builderRev: builderRev{
+			name: conf.name,
+			rev:  rev,
+		},
+		container: container,
+		start:     time.Now(),
+	}, nil
+}
+
+type buildStatus struct {
+	builderRev
+	container string
+	start     time.Time
+
+	mu sync.Mutex
+	// ...
+}
+
+func builderKey(builder string) string {
+	master := masterKey()
+	if len(master) == 0 {
+		return ""
+	}
+	h := hmac.New(md5.New, master)
+	io.WriteString(h, builder)
+	return fmt.Sprintf("%x", h.Sum(nil))
+}
+
+func masterKey() []byte {
+	keyOnce.Do(loadKey)
+	return masterKeyCache
+}
+
+var (
+	keyOnce        sync.Once
+	masterKeyCache []byte
+)
+
+func loadKey() {
+	if *masterKeyFile != "" {
+		b, err := ioutil.ReadFile(*masterKeyFile)
+		if err != nil {
+			log.Fatal(err)
+		}
+		masterKeyCache = bytes.TrimSpace(b)
+		return
+	}
+	req, _ := http.NewRequest("GET", "http://metadata.google.internal/computeMetadata/v1/project/attributes/builder-master-key", nil)
+	req.Header.Set("Metadata-Flavor", "Google")
+	res, err := http.DefaultClient.Do(req)
+	if err != nil {
+		log.Fatal("No builder master key available")
+	}
+	defer res.Body.Close()
+	if res.StatusCode != 200 {
+		log.Fatalf("No builder-master-key project attribute available.")
+	}
+	slurp, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		log.Fatal(err)
+	}
+	masterKeyCache = bytes.TrimSpace(slurp)
+}
diff --git a/third_party/go.tools/dashboard/env/linux-x86-base/Dockerfile b/third_party/go.tools/dashboard/env/linux-x86-base/Dockerfile
new file mode 100644
index 0000000..37e1a08
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-base/Dockerfile
@@ -0,0 +1,16 @@
+# Copyright 2014 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.
+
+# Base builder image: gobuilders/linux-x86-base
+
+FROM debian:wheezy
+MAINTAINER golang-dev <golang-dev@googlegroups.com>
+
+ENV DEBIAN_FRONTEND noninteractive
+
+ADD /scripts/install-apt-deps.sh /scripts/
+RUN /scripts/install-apt-deps.sh
+
+ADD /scripts/build-go-builder.sh /scripts/
+RUN GO_REV=8c27884843c3 BUILDER_REV=ced78bfefcb3 /scripts/build-go-builder.sh && test -f /usr/local/bin/builder
diff --git a/third_party/go.tools/dashboard/env/linux-x86-base/Makefile b/third_party/go.tools/dashboard/env/linux-x86-base/Makefile
new file mode 100644
index 0000000..d94baf6
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-base/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2014 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.
+
+docker: Dockerfile
+	docker build -t gobuilders/linux-x86-base .
+
+docker-linux.base.tar.gz: docker
+	docker save gobuilders/linux-x86-base | gzip | (cd ../../coordinator/buildongce && go run create.go --write_object=go-builder-data/docker-linux.base.tar.gz)
+
+check: docker
+	docker run gobuilders/linux-x86-base /usr/local/bin/builder -rev=8c27884843c3 -buildroot=/ -v -report=false linux-amd64-temp
diff --git a/third_party/go.tools/dashboard/env/linux-x86-base/README b/third_party/go.tools/dashboard/env/linux-x86-base/README
new file mode 100644
index 0000000..a511909
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-base/README
@@ -0,0 +1,11 @@
+For now, you can at least do a single build of a single revision:
+
+$ export BUILD=linux-amd64-temp
+$ docker run \
+     -v $HOME/keys/$BUILD.buildkey:/.gobuildkey \
+     gobuilders/linux-x86-base \
+     /usr/local/bin/builder -rev=50ac9eded6ad -buildroot=/ -v $BUILD
+
+TODO(bradfitz): automate with CoreOS + GCE, ala:
+    https://github.com/bradfitz/camlistore/blob/master/misc/gce/create.go
+
diff --git a/third_party/go.tools/dashboard/env/linux-x86-base/scripts/build-go-builder.sh b/third_party/go.tools/dashboard/env/linux-x86-base/scripts/build-go-builder.sh
new file mode 100755
index 0000000..097ac17
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-base/scripts/build-go-builder.sh
@@ -0,0 +1,20 @@
+set -ex
+
+export GOPATH=/gopath
+export GOROOT=/goroot
+PREFIX=/usr/local
+: ${GO_REV:?"need to be set to the golang repo revision used to build the builder."}
+: ${BUILDER_REV:?"need to be set to the go.tools repo revision for the builder."}
+
+mkdir -p $GOROOT
+curl -s https://storage.googleapis.com/gobuilder/go-snap.tar.gz | tar x --no-same-owner -zv -C $GOROOT
+(cd $GOROOT/src && hg pull -r $GO_REV -u && find && ./make.bash)
+
+GO_TOOLS=$GOPATH/src/golang.org/x/tools
+mkdir -p $GO_TOOLS
+curl -s https://storage.googleapis.com/gobuilder/go.tools-snap.tar.gz | tar x --no-same-owner -zv -C $GO_TOOLS
+
+mkdir -p $PREFIX/bin
+(cd $GO_TOOLS && hg pull -r $BUILDER_REV -u && GOBIN=$PREFIX/bin /goroot/bin/go install golang.org/x/tools/dashboard/builder)
+
+rm -fR $GOROOT/bin $GOROOT/pkg $GOPATH
diff --git a/third_party/go.tools/dashboard/env/linux-x86-base/scripts/install-apt-deps.sh b/third_party/go.tools/dashboard/env/linux-x86-base/scripts/install-apt-deps.sh
new file mode 100755
index 0000000..839f4ad
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-base/scripts/install-apt-deps.sh
@@ -0,0 +1,17 @@
+set -ex
+
+apt-get update
+# For running curl to get the hg starter tarballs (faster than hg clone).
+apt-get install -y --no-install-recommends curl ca-certificates
+# Optionally used by some net/http tests:
+apt-get install -y --no-install-recommends strace 
+# For building Go's bootstrap 'dist' prog
+apt-get install -y --no-install-recommends gcc libc6-dev
+# For 32-bit builds:
+# TODO(bradfitz): move these into a 386 image that derives from this one.
+apt-get install -y --no-install-recommends libc6-dev-i386 gcc-multilib
+# For interacting with the Go source & subrepos:
+apt-get install -y --no-install-recommends mercurial git-core
+
+apt-get clean
+rm -fr /var/lib/apt/lists
diff --git a/third_party/go.tools/dashboard/env/linux-x86-clang/Dockerfile b/third_party/go.tools/dashboard/env/linux-x86-clang/Dockerfile
new file mode 100644
index 0000000..02ef66e
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-clang/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2014 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.
+
+# gobuilders/linux-x86-clang for building with clang instead of gcc.
+
+FROM debian:wheezy
+MAINTAINER golang-dev <golang-dev@googlegroups.com>
+
+ENV DEBIAN_FRONTEND noninteractive
+
+ADD /sources/clang-deps.list /etc/apt/sources.list.d/
+
+ADD /scripts/install-apt-deps.sh /scripts/
+RUN /scripts/install-apt-deps.sh
+
+ADD /scripts/build-go-builder.sh /scripts/
+RUN GO_REV=8c27884843c3 BUILDER_REV=ced78bfefcb3 /scripts/build-go-builder.sh && test -f /usr/local/bin/builder
+
+ENV CC /usr/bin/clang
diff --git a/third_party/go.tools/dashboard/env/linux-x86-clang/Makefile b/third_party/go.tools/dashboard/env/linux-x86-clang/Makefile
new file mode 100644
index 0000000..5e1ed0f
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-clang/Makefile
@@ -0,0 +1,15 @@
+# Copyright 2014 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.
+
+docker: Dockerfile
+	docker build -t gobuilders/linux-x86-clang .
+
+docker-linux.clang.tar.gz: docker
+	docker save gobuilders/linux-x86-clang | gzip | (cd ../../coordinator/buildongce && go run create.go --write_object=go-builder-data/docker-linux.clang.tar.gz)
+
+check: docker
+	docker run gobuilders/linux-x86-clang /usr/local/bin/builder -rev=8c27884843c3 -buildroot=/ -v -report=false linux-amd64-temp
+
+check32: docker
+	docker run gobuilders/linux-x86-clang /usr/local/bin/builder -rev=8c27884843c3 -buildroot=/ -v -report=false linux-386-temp
diff --git a/third_party/go.tools/dashboard/env/linux-x86-clang/scripts/build-go-builder.sh b/third_party/go.tools/dashboard/env/linux-x86-clang/scripts/build-go-builder.sh
new file mode 100755
index 0000000..097ac17
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-clang/scripts/build-go-builder.sh
@@ -0,0 +1,20 @@
+set -ex
+
+export GOPATH=/gopath
+export GOROOT=/goroot
+PREFIX=/usr/local
+: ${GO_REV:?"need to be set to the golang repo revision used to build the builder."}
+: ${BUILDER_REV:?"need to be set to the go.tools repo revision for the builder."}
+
+mkdir -p $GOROOT
+curl -s https://storage.googleapis.com/gobuilder/go-snap.tar.gz | tar x --no-same-owner -zv -C $GOROOT
+(cd $GOROOT/src && hg pull -r $GO_REV -u && find && ./make.bash)
+
+GO_TOOLS=$GOPATH/src/golang.org/x/tools
+mkdir -p $GO_TOOLS
+curl -s https://storage.googleapis.com/gobuilder/go.tools-snap.tar.gz | tar x --no-same-owner -zv -C $GO_TOOLS
+
+mkdir -p $PREFIX/bin
+(cd $GO_TOOLS && hg pull -r $BUILDER_REV -u && GOBIN=$PREFIX/bin /goroot/bin/go install golang.org/x/tools/dashboard/builder)
+
+rm -fR $GOROOT/bin $GOROOT/pkg $GOPATH
diff --git a/third_party/go.tools/dashboard/env/linux-x86-clang/scripts/install-apt-deps.sh b/third_party/go.tools/dashboard/env/linux-x86-clang/scripts/install-apt-deps.sh
new file mode 100755
index 0000000..1382dd6
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-clang/scripts/install-apt-deps.sh
@@ -0,0 +1,21 @@
+set -ex
+
+apt-get update
+# For running curl to get the hg starter tarballs (faster than hg clone).
+apt-get install -y --no-install-recommends curl ca-certificates
+# Optionally used by some net/http tests:
+apt-get install -y --no-install-recommends strace 
+# For building Go's bootstrap 'dist' prog
+apt-get install -y --no-install-recommends wget
+wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | apt-key add -
+apt-get update
+apt-get install -y --no-install-recommends clang-3.5
+# TODO(cmang): move these into a 386 image that derives from this one.
+apt-get install -y --no-install-recommends libc6-dev-i386 gcc-multilib
+# Remove gcc binary so it doesn't interfere with clang
+rm -f /usr/bin/gcc
+# For interacting with the Go source & subrepos:
+apt-get install -y --no-install-recommends mercurial git-core
+
+apt-get clean
+rm -fr /var/lib/apt/lists
diff --git a/third_party/go.tools/dashboard/env/linux-x86-clang/sources/clang-deps.list b/third_party/go.tools/dashboard/env/linux-x86-clang/sources/clang-deps.list
new file mode 100644
index 0000000..eb3e244
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-clang/sources/clang-deps.list
@@ -0,0 +1,3 @@
+# The debian sources for stable clang builds, taken from http://llvm.org/apt/
+deb http://llvm.org/apt/wheezy/ llvm-toolchain-wheezy main
+deb-src http://llvm.org/apt/wheezy/ llvm-toolchain-wheezy main
\ No newline at end of file
diff --git a/third_party/go.tools/dashboard/env/linux-x86-gccgo/Dockerfile b/third_party/go.tools/dashboard/env/linux-x86-gccgo/Dockerfile
new file mode 100644
index 0000000..2ccd0d9
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-gccgo/Dockerfile
@@ -0,0 +1,19 @@
+# Copyright 2014 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.
+
+# gobuilders/linux-x86-gccgo for 32- and 64-bit gccgo.
+
+FROM debian:wheezy
+MAINTAINER golang-dev <golang-dev@googlegroups.com>
+
+ENV DEBIAN_FRONTEND noninteractive
+
+ADD /scripts/install-apt-deps.sh /scripts/
+RUN /scripts/install-apt-deps.sh
+
+ADD /scripts/install-gold.sh /scripts/
+RUN /scripts/install-gold.sh
+
+ADD /scripts/install-gccgo-builder.sh /scripts/
+RUN /scripts/install-gccgo-builder.sh && test -f /usr/local/bin/builder
\ No newline at end of file
diff --git a/third_party/go.tools/dashboard/env/linux-x86-gccgo/Makefile b/third_party/go.tools/dashboard/env/linux-x86-gccgo/Makefile
new file mode 100644
index 0000000..9d5143f
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-gccgo/Makefile
@@ -0,0 +1,15 @@
+# Copyright 2014 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.
+
+docker: Dockerfile
+	docker build -t gobuilders/linux-x86-gccgo .
+
+docker-linux.gccgo.tar.gz: docker
+	docker save gobuilders/linux-x86-gccgo | gzip | (cd ../../coordinator/buildongce && go run create.go --write_object=go-builder-data/docker-linux.gccgo.tar.gz)
+
+check: docker
+	docker run gobuilders/linux-x86-gccgo /usr/local/bin/builder -tool="gccgo" -rev=b9151e911a54 -v -cmd='make RUNTESTFLAGS="--target_board=unix/-m64" check-go' -report=false linux-amd64-gccgo-temp
+
+check32: docker
+	docker run gobuilders/linux-x86-gccgo /usr/local/bin/builder -tool="gccgo" -rev=b9151e911a54 -v -cmd='make RUNTESTFLAGS="--target_board=unix/-m32" check-go' -report=false linux-386-gccgo-temp
diff --git a/third_party/go.tools/dashboard/env/linux-x86-gccgo/README b/third_party/go.tools/dashboard/env/linux-x86-gccgo/README
new file mode 100644
index 0000000..65180bc
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-gccgo/README
@@ -0,0 +1,6 @@
+$ export BUILD=linux-amd64-gccgo
+$ export BUILDREV=b9151e911a54
+$ docker run \
+    -v $HOME/keys/$BUILD.buildkey:/.gobuildkey \
+    gobuilders/linux-x86-gccgo \
+    /usr/local/bin/builder -tool=gccgo -dashboard='https://build.golang.org/gccgo' -rev=$BUILDREV -buildroot=/gccgo -v -cmd='make check-go -kj' $BUILD
diff --git a/third_party/go.tools/dashboard/env/linux-x86-gccgo/scripts/install-apt-deps.sh b/third_party/go.tools/dashboard/env/linux-x86-gccgo/scripts/install-apt-deps.sh
new file mode 100755
index 0000000..90dbac1
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-gccgo/scripts/install-apt-deps.sh
@@ -0,0 +1,20 @@
+set -ex
+
+apt-get update
+# For running curl to get the gccgo builder binary.
+apt-get install -y --no-install-recommends curl ca-certificates
+# Optionally used by some net/http tests:
+apt-get install -y --no-install-recommends strace
+# For using numeric libraries within GCC.
+apt-get install -y --no-install-recommends libgmp10-dev libmpc-dev libmpfr-dev
+# For building binutils and gcc from source.
+apt-get install -y --no-install-recommends make g++ flex bison
+# Same as above, but for 32-bit builds as well.
+apt-get install -y --no-install-recommends libc6-dev-i386 g++-multilib
+# For running the extended gccgo testsuite
+apt-get install -y --no-install-recommends dejagnu
+# For interacting with the gccgo source and git mirror:
+apt-get install -y --no-install-recommends mercurial git-core
+
+apt-get clean
+rm -rf /var/lib/apt/lists
diff --git a/third_party/go.tools/dashboard/env/linux-x86-gccgo/scripts/install-gccgo-builder.sh b/third_party/go.tools/dashboard/env/linux-x86-gccgo/scripts/install-gccgo-builder.sh
new file mode 100755
index 0000000..fd3785d
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-gccgo/scripts/install-gccgo-builder.sh
@@ -0,0 +1,7 @@
+set -ex
+
+# Installs a version of the go.tools dashboard builder that runs the gccgo build
+# command assuming there are 16 cores available to speed up build times.
+# TODO(cmang): There should be an option in the builder to specify this.
+
+curl -o /usr/local/bin/builder http://storage.googleapis.com/go-builder-data/gccgo_builder && chmod +x /usr/local/bin/builder
diff --git a/third_party/go.tools/dashboard/env/linux-x86-gccgo/scripts/install-gold.sh b/third_party/go.tools/dashboard/env/linux-x86-gccgo/scripts/install-gold.sh
new file mode 100755
index 0000000..77f96ac
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-gccgo/scripts/install-gold.sh
@@ -0,0 +1,9 @@
+set -ex
+
+# gccgo uses the Gold linker from binutils.
+export BINUTILS_VERSION=binutils-2.24
+mkdir -p binutils-objdir
+curl -s http://ftp.gnu.org/gnu/binutils/$BINUTILS_VERSION.tar.gz | tar x --no-same-owner -zv
+(cd binutils-objdir && ../$BINUTILS_VERSION/configure --enable-gold --enable-plugins --prefix=/opt/gold && make -sj && make install -sj)
+
+rm -rf binutils*
\ No newline at end of file
diff --git a/third_party/go.tools/dashboard/env/linux-x86-nacl/Dockerfile b/third_party/go.tools/dashboard/env/linux-x86-nacl/Dockerfile
new file mode 100644
index 0000000..68a8df5
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-nacl/Dockerfile
@@ -0,0 +1,27 @@
+# Copyright 2014 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.
+
+# gobuilders/linux-x86-nacl for 32- and 64-bit nacl.
+#
+# We need more modern libc than Debian stable as used in base, so we're
+# using Ubuntu LTS here.
+#
+# TODO(bradfitz): make both be Ubuntu? But we also want Debian, Fedora, 
+# etc coverage., so deal with unifying these later, once there's a plan
+# or a generator for them and the other builders are turned down.
+
+FROM ubuntu:trusty
+MAINTAINER golang-dev <golang-dev@googlegroups.com>
+
+ENV DEBIAN_FRONTEND noninteractive
+
+ADD /scripts/install-apt-deps.sh /scripts/
+RUN /scripts/install-apt-deps.sh
+
+ADD /scripts/build-go-builder.sh /scripts/
+RUN GO_REV=8c27884843c3 BUILDER_REV=ced78bfefcb3 /scripts/build-go-builder.sh && test -f /usr/local/bin/builder
+
+ADD build-command.pl /usr/local/bin/
+
+ENV PATH /usr/local/bin:$GOROOT/bin:$PATH
diff --git a/third_party/go.tools/dashboard/env/linux-x86-nacl/Makefile b/third_party/go.tools/dashboard/env/linux-x86-nacl/Makefile
new file mode 100644
index 0000000..3c2b7e3
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-nacl/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2014 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.
+
+docker: Dockerfile
+	docker build -t gobuilders/linux-x86-nacl .
+
+upload: docker
+	docker save gobuilders/linux-x86-nacl | gzip | (cd ../../coordinator/buildongce && go run create.go --write_object=go-builder-data/docker-linux.nacl.tar.gz)
+
+check: docker
+	docker run gobuilders/linux-x86-nacl /usr/local/bin/builder -rev=8c27884843c3 -buildroot=/ -v -cmd=/usr/local/bin/build-command.pl -report=false nacl-amd64p32-temp
diff --git a/third_party/go.tools/dashboard/env/linux-x86-nacl/README b/third_party/go.tools/dashboard/env/linux-x86-nacl/README
new file mode 100644
index 0000000..5862ee1
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-nacl/README
@@ -0,0 +1,6 @@
+$ export BUILD=nacl-amd64p32-temp
+$ export BUILDREV=59b1bb4bf045 
+$ docker run \
+     -v $HOME/keys/$BUILD.buildkey:/.gobuildkey \
+     gobuilders/linux-x86-nacl \
+     /usr/local/bin/builder -rev=$BUILDREV -buildroot=/ -v -cmd=/usr/local/bin/build-command.pl $BUILD
diff --git a/third_party/go.tools/dashboard/env/linux-x86-nacl/build-command.pl b/third_party/go.tools/dashboard/env/linux-x86-nacl/build-command.pl
new file mode 100755
index 0000000..0eb9edb
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-nacl/build-command.pl
@@ -0,0 +1,13 @@
+#!/usr/bin/perl
+
+use strict;
+
+if ($ENV{GOOS} eq "nacl") {
+    delete $ENV{GOROOT_FINAL};
+    exec("./nacltest.bash", @ARGV);
+    die "Failed to run nacltest.bash: $!\n";
+}
+
+exec("./all.bash", @ARGV);
+die "Failed to run all.bash: $!\n";
+
diff --git a/third_party/go.tools/dashboard/env/linux-x86-nacl/scripts/build-go-builder.sh b/third_party/go.tools/dashboard/env/linux-x86-nacl/scripts/build-go-builder.sh
new file mode 100755
index 0000000..10bf847
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-nacl/scripts/build-go-builder.sh
@@ -0,0 +1,26 @@
+set -ex
+
+export GOPATH=/gopath
+export GOROOT=/goroot
+PREFIX=/usr/local
+: ${GO_REV:?"need to be set to the golang repo revision used to build the builder."}
+: ${BUILDER_REV:?"need to be set to the go.tools repo revision for the builder."}
+
+mkdir -p $GOROOT
+curl -s https://storage.googleapis.com/gobuilder/go-snap.tar.gz | tar x --no-same-owner -zv -C $GOROOT
+(cd $GOROOT/src && hg pull -r $GO_REV -u && find && ./make.bash)
+
+GO_TOOLS=$GOPATH/src/golang.org/x/tools
+mkdir -p $GO_TOOLS
+curl -s https://storage.googleapis.com/gobuilder/go.tools-snap.tar.gz | tar x --no-same-owner -zv -C $GO_TOOLS
+
+mkdir -p $PREFIX/bin
+(cd $GO_TOOLS && hg pull -r $BUILDER_REV -u && GOBIN=$PREFIX/bin /goroot/bin/go install golang.org/x/tools/dashboard/builder)
+
+rm -fR $GOROOT/bin $GOROOT/pkg $GOPATH
+
+(cd /usr/local/bin && curl -s -O https://storage.googleapis.com/gobuilder/sel_ldr_x86_32 && chmod +x sel_ldr_x86_32)
+(cd /usr/local/bin && curl -s -O https://storage.googleapis.com/gobuilder/sel_ldr_x86_64 && chmod +x sel_ldr_x86_64)
+
+ln -s $GOROOT/misc/nacl/go_nacl_386_exec /usr/local/bin/
+ln -s $GOROOT/misc/nacl/go_nacl_amd64p32_exec /usr/local/bin/
diff --git a/third_party/go.tools/dashboard/env/linux-x86-nacl/scripts/install-apt-deps.sh b/third_party/go.tools/dashboard/env/linux-x86-nacl/scripts/install-apt-deps.sh
new file mode 100755
index 0000000..f518646
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-nacl/scripts/install-apt-deps.sh
@@ -0,0 +1,14 @@
+set -ex
+
+apt-get update
+# For running curl to get the hg starter tarballs (faster than hg clone).
+apt-get install -y --no-install-recommends curl ca-certificates
+# For building Go's bootstrap 'dist' prog
+apt-get install -y --no-install-recommends gcc libc6-dev
+# For interacting with the Go source & subrepos:
+apt-get install -y --no-install-recommends mercurial git-core
+# For 32-bit nacl:
+apt-get install -y --no-install-recommends libc6-i386 libc6-dev-i386 lib32stdc++6 gcc-multilib
+
+apt-get clean
+rm -fr /var/lib/apt/lists
diff --git a/third_party/go.tools/dashboard/env/linux-x86-sid/Dockerfile b/third_party/go.tools/dashboard/env/linux-x86-sid/Dockerfile
new file mode 100644
index 0000000..057e93a
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-sid/Dockerfile
@@ -0,0 +1,14 @@
+# Copyright 2014 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.
+
+FROM debian:sid
+MAINTAINER golang-dev <golang-dev@googlegroups.com>
+
+ENV DEBIAN_FRONTEND noninteractive
+
+ADD /scripts/install-apt-deps.sh /scripts/
+RUN /scripts/install-apt-deps.sh
+
+ADD /scripts/build-go-builder.sh /scripts/
+RUN GO_REV=8c27884843c3 BUILDER_REV=ced78bfefcb3 /scripts/build-go-builder.sh && test -f /usr/local/bin/builder
diff --git a/third_party/go.tools/dashboard/env/linux-x86-sid/Makefile b/third_party/go.tools/dashboard/env/linux-x86-sid/Makefile
new file mode 100644
index 0000000..e636e49
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-sid/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2014 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.
+
+docker: Dockerfile
+	docker build -t gobuilders/linux-x86-sid .
+
+docker-linux.sid.tar.gz: docker
+	docker save gobuilders/linux-x86-sid | gzip | (cd ../../coordinator/buildongce && go run create.go --write_object=go-builder-data/docker-linux.sid.tar.gz)
+
+check: docker
+	docker run gobuilders/linux-x86-sid /usr/local/bin/builder -rev=8c27884843c3 -buildroot=/ -v -report=false linux-amd64-sid
diff --git a/third_party/go.tools/dashboard/env/linux-x86-sid/scripts/build-go-builder.sh b/third_party/go.tools/dashboard/env/linux-x86-sid/scripts/build-go-builder.sh
new file mode 100755
index 0000000..097ac17
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-sid/scripts/build-go-builder.sh
@@ -0,0 +1,20 @@
+set -ex
+
+export GOPATH=/gopath
+export GOROOT=/goroot
+PREFIX=/usr/local
+: ${GO_REV:?"need to be set to the golang repo revision used to build the builder."}
+: ${BUILDER_REV:?"need to be set to the go.tools repo revision for the builder."}
+
+mkdir -p $GOROOT
+curl -s https://storage.googleapis.com/gobuilder/go-snap.tar.gz | tar x --no-same-owner -zv -C $GOROOT
+(cd $GOROOT/src && hg pull -r $GO_REV -u && find && ./make.bash)
+
+GO_TOOLS=$GOPATH/src/golang.org/x/tools
+mkdir -p $GO_TOOLS
+curl -s https://storage.googleapis.com/gobuilder/go.tools-snap.tar.gz | tar x --no-same-owner -zv -C $GO_TOOLS
+
+mkdir -p $PREFIX/bin
+(cd $GO_TOOLS && hg pull -r $BUILDER_REV -u && GOBIN=$PREFIX/bin /goroot/bin/go install golang.org/x/tools/dashboard/builder)
+
+rm -fR $GOROOT/bin $GOROOT/pkg $GOPATH
diff --git a/third_party/go.tools/dashboard/env/linux-x86-sid/scripts/install-apt-deps.sh b/third_party/go.tools/dashboard/env/linux-x86-sid/scripts/install-apt-deps.sh
new file mode 100755
index 0000000..839f4ad
--- /dev/null
+++ b/third_party/go.tools/dashboard/env/linux-x86-sid/scripts/install-apt-deps.sh
@@ -0,0 +1,17 @@
+set -ex
+
+apt-get update
+# For running curl to get the hg starter tarballs (faster than hg clone).
+apt-get install -y --no-install-recommends curl ca-certificates
+# Optionally used by some net/http tests:
+apt-get install -y --no-install-recommends strace 
+# For building Go's bootstrap 'dist' prog
+apt-get install -y --no-install-recommends gcc libc6-dev
+# For 32-bit builds:
+# TODO(bradfitz): move these into a 386 image that derives from this one.
+apt-get install -y --no-install-recommends libc6-dev-i386 gcc-multilib
+# For interacting with the Go source & subrepos:
+apt-get install -y --no-install-recommends mercurial git-core
+
+apt-get clean
+rm -fr /var/lib/apt/lists
diff --git a/third_party/go.tools/dashboard/updater/updater.go b/third_party/go.tools/dashboard/updater/updater.go
new file mode 100644
index 0000000..0601611
--- /dev/null
+++ b/third_party/go.tools/dashboard/updater/updater.go
@@ -0,0 +1,128 @@
+// Copyright 2013 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 (
+	"bytes"
+	"encoding/json"
+	"encoding/xml"
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"os"
+	"os/exec"
+	"strings"
+)
+
+var (
+	builder   = flag.String("builder", "", "builder name")
+	key       = flag.String("key", "", "builder key")
+	gopath    = flag.String("gopath", "", "path to go repo")
+	dashboard = flag.String("dashboard", "build.golang.org", "Go Dashboard Host")
+	batch     = flag.Int("batch", 100, "upload batch size")
+)
+
+// Do not benchmark beyond this commit.
+// There is little sense in benchmarking till first commit,
+// and the benchmark won't build anyway.
+const Go1Commit = "0051c7442fed" // test/bench/shootout: update timing.log to Go 1.
+
+// HgLog represents a single Mercurial revision.
+type HgLog struct {
+	Hash   string
+	Branch string
+	Files  string
+}
+
+func main() {
+	flag.Parse()
+	logs := hgLog()
+	var hashes []string
+	ngo1 := 0
+	for i := range logs {
+		if strings.HasPrefix(logs[i].Hash, Go1Commit) {
+			break
+		}
+		if needsBenchmarking(&logs[i]) {
+			hashes = append(hashes, logs[i].Hash)
+		}
+		ngo1++
+	}
+	fmt.Printf("found %v commits, %v after Go1, %v need benchmarking\n", len(logs), ngo1, len(hashes))
+	for i := 0; i < len(hashes); i += *batch {
+		j := i + *batch
+		if j > len(hashes) {
+			j = len(hashes)
+		}
+		fmt.Printf("sending %v-%v... ", i, j)
+		res := postCommits(hashes[i:j])
+		fmt.Printf("%s\n", res)
+	}
+}
+
+func hgLog() []HgLog {
+	var out bytes.Buffer
+	cmd := exec.Command("hg", "log", "--encoding=utf-8", "--template", xmlLogTemplate)
+	cmd.Dir = *gopath
+	cmd.Stdout = &out
+	cmd.Stderr = os.Stderr
+	err := cmd.Run()
+	if err != nil {
+		fmt.Printf("failed to execute 'hg log': %v\n", err)
+		os.Exit(1)
+	}
+	var top struct{ Log []HgLog }
+	err = xml.Unmarshal([]byte("<Top>"+out.String()+"</Top>"), &top)
+	if err != nil {
+		fmt.Printf("failed to parse log: %v\n", err)
+		os.Exit(1)
+	}
+	return top.Log
+}
+
+func needsBenchmarking(log *HgLog) bool {
+	if log.Branch != "" {
+		return false
+	}
+	for _, f := range strings.Split(log.Files, " ") {
+		if (strings.HasPrefix(f, "include") || strings.HasPrefix(f, "src")) &&
+			!strings.HasSuffix(f, "_test.go") && !strings.Contains(f, "testdata") {
+			return true
+		}
+	}
+	return false
+}
+
+func postCommits(hashes []string) string {
+	args := url.Values{"builder": {*builder}, "key": {*key}}
+	cmd := fmt.Sprintf("http://%v/updatebenchmark?%v", *dashboard, args.Encode())
+	b, err := json.Marshal(hashes)
+	if err != nil {
+		return fmt.Sprintf("failed to encode request: %v\n", err)
+	}
+	r, err := http.Post(cmd, "text/json", bytes.NewReader(b))
+	if err != nil {
+		return fmt.Sprintf("failed to send http request: %v\n", err)
+	}
+	defer r.Body.Close()
+	if r.StatusCode != http.StatusOK {
+		return fmt.Sprintf("http request failed: %v\n", r.Status)
+	}
+	resp, err := ioutil.ReadAll(r.Body)
+	if err != nil {
+		return fmt.Sprintf("failed to read http response: %v\n", err)
+	}
+	return string(resp)
+}
+
+const xmlLogTemplate = `
+        <Log>
+        <Hash>{node|escape}</Hash>
+        <Branch>{branches}</Branch>
+        <Files>{files}</Files>
+        </Log>
+`
diff --git a/third_party/go.tools/dashboard/watcher/watcher.go b/third_party/go.tools/dashboard/watcher/watcher.go
new file mode 100644
index 0000000..7c145f5
--- /dev/null
+++ b/third_party/go.tools/dashboard/watcher/watcher.go
@@ -0,0 +1,589 @@
+// Copyright 2014 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.
+
+// Command watcher watches the specified repository for new commits
+// and reports them to the build dashboard.
+package main
+
+import (
+	"bytes"
+	"encoding/json"
+	"encoding/xml"
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"net/url"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"time"
+)
+
+var (
+	repoURL      = flag.String("repo", "https://code.google.com/p/go", "Repository URL")
+	dashboard    = flag.String("dash", "https://build.golang.org/", "Dashboard URL (must end in /)")
+	keyFile      = flag.String("key", defaultKeyFile, "Build dashboard key file")
+	pollInterval = flag.Duration("poll", 10*time.Second, "Remote repo poll interval")
+)
+
+var (
+	defaultKeyFile = filepath.Join(homeDir(), ".gobuildkey")
+	dashboardKey   = ""
+)
+
+// The first main repo commit on the dashboard; ignore commits before this.
+// This is for the main Go repo only.
+const dashboardStart = "2f970046e1ba96f32de62f5639b7141cda2e977c"
+
+func main() {
+	flag.Parse()
+
+	err := run()
+	fmt.Fprintln(os.Stderr, err)
+	os.Exit(1)
+}
+
+// run is a little wrapper so we can use defer and return to signal
+// errors. It should only return a non-nil error.
+func run() error {
+	if !strings.HasSuffix(*dashboard, "/") {
+		return errors.New("dashboard URL (-dashboard) must end in /")
+	}
+	if err := checkHgVersion(); err != nil {
+		return err
+	}
+
+	if k, err := readKey(); err != nil {
+		return err
+	} else {
+		dashboardKey = k
+	}
+
+	dir, err := ioutil.TempDir("", "watcher")
+	if err != nil {
+		return err
+	}
+	defer os.RemoveAll(dir)
+
+	errc := make(chan error)
+
+	go func() {
+		r, err := NewRepo(dir, *repoURL, "")
+		if err != nil {
+			errc <- err
+			return
+		}
+		errc <- r.Watch()
+	}()
+
+	subrepos, err := subrepoList()
+	if err != nil {
+		return err
+	}
+	for _, path := range subrepos {
+		go func(path string) {
+			url := "https://" + path
+			r, err := NewRepo(dir, url, path)
+			if err != nil {
+				errc <- err
+				return
+			}
+			errc <- r.Watch()
+		}(path)
+	}
+
+	// Must be non-nil.
+	return <-errc
+}
+
+// Repo represents a repository to be watched.
+type Repo struct {
+	root     string             // on-disk location of the hg repo
+	path     string             // base import path for repo (blank for main repo)
+	commits  map[string]*Commit // keyed by full commit hash (40 lowercase hex digits)
+	branches map[string]*Branch // keyed by branch name, eg "release-branch.go1.3" (or empty for default)
+}
+
+// NewRepo checks out a new instance of the Mercurial repository
+// specified by url to a new directory inside dir.
+// The path argument is the base import path of the repository,
+// and should be empty for the main Go repo.
+func NewRepo(dir, url, path string) (*Repo, error) {
+	r := &Repo{
+		path: path,
+		root: filepath.Join(dir, filepath.Base(path)),
+	}
+
+	r.logf("cloning %v", url)
+	cmd := exec.Command("hg", "clone", url, r.root)
+	if out, err := cmd.CombinedOutput(); err != nil {
+		return nil, fmt.Errorf("%v\n\n%s", err, out)
+	}
+
+	r.logf("loading commit log")
+	if err := r.loadCommits(); err != nil {
+		return nil, err
+	}
+	if err := r.findBranches(); err != nil {
+		return nil, err
+	}
+
+	r.logf("found %v branches among %v commits\n", len(r.branches), len(r.commits))
+	return r, nil
+}
+
+// Watch continuously runs "hg pull" in the repo, checks for
+// new commits, and posts any new commits to the dashboard.
+// It only returns a non-nil error.
+func (r *Repo) Watch() error {
+	for {
+		if err := hgPull(r.root); err != nil {
+			return err
+		}
+		if err := r.update(); err != nil {
+			return err
+		}
+		for _, b := range r.branches {
+			if err := r.postNewCommits(b); err != nil {
+				return err
+			}
+		}
+		time.Sleep(*pollInterval)
+	}
+}
+
+func (r *Repo) logf(format string, args ...interface{}) {
+	p := "go"
+	if r.path != "" {
+		p = path.Base(r.path)
+	}
+	log.Printf(p+": "+format, args...)
+}
+
+// postNewCommits looks for unseen commits on the specified branch and
+// posts them to the dashboard.
+func (r *Repo) postNewCommits(b *Branch) error {
+	if b.Head == b.LastSeen {
+		return nil
+	}
+	c := b.LastSeen
+	if c == nil {
+		// Haven't seen any: find the commit that this branch forked from.
+		for c := b.Head; c.Branch == b.Name; c = c.parent {
+		}
+	}
+	// Add unseen commits on this branch, working forward from last seen.
+	for c.children != nil {
+		// Find the next commit on this branch.
+		var next *Commit
+		for _, c2 := range c.children {
+			if c2.Branch != b.Name {
+				continue
+			}
+			if next != nil {
+				// Shouldn't happen, but be paranoid.
+				return fmt.Errorf("found multiple children of %v on branch %q: %v and %v", c, b.Name, next, c2)
+			}
+			next = c2
+		}
+		if next == nil {
+			// No more children on this branch, bail.
+			break
+		}
+		// Found it.
+		c = next
+
+		if err := r.postCommit(c); err != nil {
+			return err
+		}
+		b.LastSeen = c
+	}
+	return nil
+}
+
+// postCommit sends a commit to the build dashboard.
+func (r *Repo) postCommit(c *Commit) error {
+	r.logf("sending commit to dashboard: %v", c)
+
+	t, err := time.Parse(time.RFC3339, c.Date)
+	if err != nil {
+		return err
+	}
+	dc := struct {
+		PackagePath string // (empty for main repo commits)
+		Hash        string
+		ParentHash  string
+
+		User string
+		Desc string
+		Time time.Time
+
+		NeedsBenchmarking bool
+	}{
+		PackagePath: r.path,
+		Hash:        c.Hash,
+		ParentHash:  c.Parent,
+
+		User: c.Author,
+		Desc: c.Desc,
+		Time: t,
+
+		NeedsBenchmarking: c.NeedsBenchmarking(),
+	}
+	b, err := json.Marshal(dc)
+	if err != nil {
+		return err
+	}
+
+	u := *dashboard + "commit?version=2&key=" + dashboardKey
+	resp, err := http.Post(u, "text/json", bytes.NewReader(b))
+	if err != nil {
+		return err
+	}
+	if resp.StatusCode != 200 {
+		return fmt.Errorf("status: %v", resp.Status)
+	}
+	return nil
+}
+
+// loadCommits runs "hg log" and populates the Repo's commit map.
+func (r *Repo) loadCommits() error {
+	log, err := hgLog(r.root)
+	if err != nil {
+		return err
+	}
+	r.commits = make(map[string]*Commit)
+	for _, c := range log {
+		r.commits[c.Hash] = c
+	}
+	for _, c := range r.commits {
+		if p, ok := r.commits[c.Parent]; ok {
+			c.parent = p
+			p.children = append(p.children, c)
+		}
+	}
+	return nil
+}
+
+// findBranches finds branch heads in the Repo's commit map
+// and populates its branch map.
+func (r *Repo) findBranches() error {
+	r.branches = make(map[string]*Branch)
+	for _, c := range r.commits {
+		if c.children == nil {
+			if !validHead(c) {
+				continue
+			}
+			seen, err := r.lastSeen(c.Hash)
+			if err != nil {
+				return err
+			}
+			b := &Branch{Name: c.Branch, Head: c, LastSeen: seen}
+			r.branches[c.Branch] = b
+			r.logf("found branch: %v", b)
+		}
+	}
+	return nil
+}
+
+// validHead reports whether the specified commit should be considered a branch
+// head. It considers pre-go1 branches and certain specific commits as invalid.
+func validHead(c *Commit) bool {
+	// Pre Go-1 releases branches are irrelevant.
+	if strings.HasPrefix(c.Branch, "release-branch.r") {
+		return false
+	}
+	// Not sure why these revisions have no child commits,
+	// but they're old so let's just ignore them.
+	if c.Hash == "b59f4ff1b51094314f735a4d57a2b8f06cfadf15" ||
+		c.Hash == "fc75f13840b896e82b9fa6165cf705fbacaf019c" {
+		return false
+	}
+	// All other branches are valid.
+	return true
+}
+
+// update runs "hg pull" in the specified reporoot,
+// looks for new commits and branches,
+// and updates the comits and branches maps.
+func (r *Repo) update() error {
+	// TODO(adg): detect new branches with "hg branches".
+
+	// Check each branch for new commits.
+	for _, b := range r.branches {
+
+		// Find all commits on this branch from known head.
+		// The logic of this function assumes that "hg log $HASH:"
+		// returns hashes in the order they were committed (parent first).
+		bname := b.Name
+		if bname == "" {
+			bname = "default"
+		}
+		log, err := hgLog(r.root, "-r", b.Head.Hash+":", "-b", bname)
+		if err != nil {
+			return err
+		}
+
+		// Add unknown commits to r.commits, and update branch head.
+		for _, c := range log {
+			// Ignore if we already know this commit.
+			if _, ok := r.commits[c.Hash]; ok {
+				continue
+			}
+			r.logf("found new commit %v", c)
+
+			// Sanity check that we're looking at a commit on this branch.
+			if c.Branch != b.Name {
+				return fmt.Errorf("hg log gave us a commit from wrong branch: want %q, got %q", b.Name, c.Branch)
+			}
+
+			// Find parent commit.
+			p, ok := r.commits[c.Parent]
+			if !ok {
+				return fmt.Errorf("can't find parent hash %q for %v", c.Parent, c)
+			}
+
+			// Link parent and child Commits.
+			c.parent = p
+			p.children = append(p.children, c)
+
+			// Update branch head.
+			b.Head = c
+
+			// Add new commit to map.
+			r.commits[c.Hash] = c
+		}
+	}
+
+	return nil
+}
+
+// lastSeen finds the most recent commit the dashboard has seen,
+// starting at the specified head. If the dashboard hasn't seen
+// any of the commits from head to the beginning, it returns nil.
+func (r *Repo) lastSeen(head string) (*Commit, error) {
+	h, ok := r.commits[head]
+	if !ok {
+		return nil, fmt.Errorf("lastSeen: can't find %q in commits", head)
+	}
+
+	var s []*Commit
+	for c := h; c != nil; c = c.parent {
+		s = append(s, c)
+		if r.path == "" && c.Hash == dashboardStart {
+			break
+		}
+	}
+
+	for _, c := range s {
+		v := url.Values{"hash": {c.Hash}, "packagePath": {r.path}}
+		u := *dashboard + "commit?" + v.Encode()
+		r, err := http.Get(u)
+		if err != nil {
+			return nil, err
+		}
+		var resp struct {
+			Error string
+		}
+		err = json.NewDecoder(r.Body).Decode(&resp)
+		r.Body.Close()
+		if err != nil {
+			return nil, err
+		}
+		switch resp.Error {
+		case "":
+			// Found one.
+			return c, nil
+		case "Commit not found":
+			// Commit not found, keep looking for earlier commits.
+			continue
+		default:
+			return nil, fmt.Errorf("dashboard: %v", resp.Error)
+		}
+	}
+
+	// Dashboard saw no commits.
+	return nil, nil
+}
+
+// hgLog runs "hg log" with the supplied arguments
+// and parses the output into Commit values.
+func hgLog(dir string, args ...string) ([]*Commit, error) {
+	args = append([]string{"log", "--template", xmlLogTemplate}, args...)
+	cmd := exec.Command("hg", args...)
+	cmd.Dir = dir
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		return nil, err
+	}
+
+	// We have a commit with description that contains 0x1b byte.
+	// Mercurial does not escape it, but xml.Unmarshal does not accept it.
+	out = bytes.Replace(out, []byte{0x1b}, []byte{'?'}, -1)
+
+	xr := io.MultiReader(
+		strings.NewReader("<Top>"),
+		bytes.NewReader(out),
+		strings.NewReader("</Top>"),
+	)
+	var logStruct struct {
+		Log []*Commit
+	}
+	err = xml.NewDecoder(xr).Decode(&logStruct)
+	if err != nil {
+		return nil, err
+	}
+	return logStruct.Log, nil
+}
+
+// hgPull runs "hg pull" in the specified directory.
+// It tries three times, just in case it failed because of a transient error.
+func hgPull(dir string) error {
+	var err error
+	for tries := 0; tries < 3; tries++ {
+		time.Sleep(time.Duration(tries) * 5 * time.Second) // Linear back-off.
+		cmd := exec.Command("hg", "pull")
+		cmd.Dir = dir
+		if out, e := cmd.CombinedOutput(); err != nil {
+			e = fmt.Errorf("%v\n\n%s", e, out)
+			log.Printf("hg pull error %v: %v", dir, e)
+			if err == nil {
+				err = e
+			}
+			continue
+		}
+		return nil
+	}
+	return err
+}
+
+// Branch represents a Mercurial branch.
+type Branch struct {
+	Name     string
+	Head     *Commit
+	LastSeen *Commit // the last commit posted to the dashboard
+}
+
+func (b *Branch) String() string {
+	return fmt.Sprintf("%q(Head: %v LastSeen: %v)", b.Name, b.Head, b.LastSeen)
+}
+
+// Commit represents a single Mercurial revision.
+type Commit struct {
+	Hash   string
+	Author string
+	Date   string
+	Desc   string // Plain text, first linefeed-terminated line is a short description.
+	Parent string
+	Branch string
+	Files  string
+
+	// For walking the graph.
+	parent   *Commit
+	children []*Commit
+}
+
+func (c *Commit) String() string {
+	return fmt.Sprintf("%v(%q)", c.Hash, strings.SplitN(c.Desc, "\n", 2)[0])
+}
+
+// NeedsBenchmarking reports whether the Commit needs benchmarking.
+func (c *Commit) NeedsBenchmarking() bool {
+	// Do not benchmark branch commits, they are usually not interesting
+	// and fall out of the trunk succession.
+	if c.Branch != "" {
+		return false
+	}
+	// Do not benchmark commits that do not touch source files (e.g. CONTRIBUTORS).
+	for _, f := range strings.Split(c.Files, " ") {
+		if (strings.HasPrefix(f, "include") || strings.HasPrefix(f, "src")) &&
+			!strings.HasSuffix(f, "_test.go") && !strings.Contains(f, "testdata") {
+			return true
+		}
+	}
+	return false
+}
+
+// xmlLogTemplate is a template to pass to Mercurial to make
+// hg log print the log in valid XML for parsing with xml.Unmarshal.
+// Can not escape branches and files, because it crashes python with:
+// AttributeError: 'NoneType' object has no attribute 'replace'
+const xmlLogTemplate = `
+        <Log>
+        <Hash>{node|escape}</Hash>
+        <Parent>{p1node}</Parent>
+        <Author>{author|escape}</Author>
+        <Date>{date|rfc3339date}</Date>
+        <Desc>{desc|escape}</Desc>
+        <Branch>{branches}</Branch>
+        <Files>{files}</Files>
+        </Log>
+`
+
+func homeDir() string {
+	switch runtime.GOOS {
+	case "plan9":
+		return os.Getenv("home")
+	case "windows":
+		return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
+	}
+	return os.Getenv("HOME")
+}
+
+func readKey() (string, error) {
+	c, err := ioutil.ReadFile(*keyFile)
+	if err != nil {
+		return "", err
+	}
+	return string(bytes.TrimSpace(bytes.SplitN(c, []byte("\n"), 2)[0])), nil
+}
+
+// subrepoList fetches a list of sub-repositories from the dashboard
+// and returns them as a slice of base import paths.
+// Eg, []string{"golang.org/x/tools", "golang.org/x/net"}.
+func subrepoList() ([]string, error) {
+	r, err := http.Get(*dashboard + "packages?kind=subrepo")
+	if err != nil {
+		return nil, err
+	}
+	var resp struct {
+		Response []struct {
+			Path string
+		}
+		Error string
+	}
+	err = json.NewDecoder(r.Body).Decode(&resp)
+	r.Body.Close()
+	if err != nil {
+		return nil, err
+	}
+	if resp.Error != "" {
+		return nil, errors.New(resp.Error)
+	}
+	var pkgs []string
+	for _, r := range resp.Response {
+		pkgs = append(pkgs, r.Path)
+	}
+	return pkgs, nil
+}
+
+// checkHgVersion checks whether the installed version of hg supports the
+// template features we need. (May not be precise.)
+func checkHgVersion() error {
+	out, err := exec.Command("hg", "help", "templates").CombinedOutput()
+	if err != nil {
+		return fmt.Errorf("error running hg help templates: %v\n\n%s", err, out)
+	}
+	if !bytes.Contains(out, []byte("p1node")) {
+		return errors.New("installed hg doesn't support 'p1node' template keyword; please upgrade")
+	}
+	return nil
+}
diff --git a/third_party/go.tools/go/buildutil/allpackages.go b/third_party/go.tools/go/buildutil/allpackages.go
new file mode 100644
index 0000000..1da5560
--- /dev/null
+++ b/third_party/go.tools/go/buildutil/allpackages.go
@@ -0,0 +1,111 @@
+// Copyright 2014 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 buildutil provides utilities related to the go/build
+// package in the standard library.
+//
+// All I/O is done via the build.Context file system interface, which must
+// be concurrency-safe.
+package buildutil
+
+import (
+	"go/build"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+	"sync"
+)
+
+// AllPackages returns the import path of each Go package in any source
+// directory of the specified build context (e.g. $GOROOT or an element
+// of $GOPATH).  Errors are ignored.  The results are sorted.
+//
+// The result may include import paths for directories that contain no
+// *.go files, such as "archive" (in $GOROOT/src).
+//
+// All I/O is done via the build.Context file system interface,
+// which must be concurrency-safe.
+//
+func AllPackages(ctxt *build.Context) []string {
+	var list []string
+	var mu sync.Mutex
+	ForEachPackage(ctxt, func(pkg string, _ error) {
+		mu.Lock()
+		list = append(list, pkg)
+		mu.Unlock()
+	})
+	sort.Strings(list)
+	return list
+}
+
+// ForEachPackage calls the found function with the import path of
+// each Go package it finds in any source directory of the specified
+// build context (e.g. $GOROOT or an element of $GOPATH).
+//
+// If the package directory exists but could not be read, the second
+// argument to the found function provides the error.
+//
+// The found function and the build.Context file system interface
+// accessors must be concurrency safe.
+//
+func ForEachPackage(ctxt *build.Context, found func(importPath string, err error)) {
+	// We use a counting semaphore to limit
+	// the number of parallel calls to ReadDir.
+	sema := make(chan bool, 20)
+
+	var wg sync.WaitGroup
+	for _, root := range ctxt.SrcDirs() {
+		root := root
+		wg.Add(1)
+		go func() {
+			allPackages(ctxt, sema, root, found)
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+
+func allPackages(ctxt *build.Context, sema chan bool, root string, found func(string, error)) {
+	root = filepath.Clean(root) + string(os.PathSeparator)
+
+	var wg sync.WaitGroup
+
+	var walkDir func(dir string)
+	walkDir = func(dir string) {
+		// Avoid .foo, _foo, and testdata directory trees.
+		base := filepath.Base(dir)
+		if base == "" || base[0] == '.' || base[0] == '_' || base == "testdata" {
+			return
+		}
+
+		pkg := filepath.ToSlash(strings.TrimPrefix(dir, root))
+
+		// Prune search if we encounter any of these import paths.
+		switch pkg {
+		case "builtin":
+			return
+		}
+
+		sema <- true
+		files, err := ReadDir(ctxt, dir)
+		<-sema
+		if pkg != "" || err != nil {
+			found(pkg, err)
+		}
+		for _, fi := range files {
+			fi := fi
+			if fi.IsDir() {
+				wg.Add(1)
+				go func() {
+					walkDir(filepath.Join(dir, fi.Name()))
+					wg.Done()
+				}()
+			}
+		}
+	}
+
+	walkDir(root)
+	wg.Wait()
+}
diff --git a/third_party/go.tools/go/buildutil/allpackages_test.go b/third_party/go.tools/go/buildutil/allpackages_test.go
new file mode 100644
index 0000000..db6529e
--- /dev/null
+++ b/third_party/go.tools/go/buildutil/allpackages_test.go
@@ -0,0 +1,32 @@
+// Copyright 2014 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 buildutil_test
+
+import (
+	"go/build"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/buildutil"
+)
+
+func TestAllPackages(t *testing.T) {
+	all := buildutil.AllPackages(&build.Default)
+
+	set := make(map[string]bool)
+	for _, pkg := range all {
+		set[pkg] = true
+	}
+
+	const wantAtLeast = 250
+	if len(all) < wantAtLeast {
+		t.Errorf("Found only %d packages, want at least %d", len(all), wantAtLeast)
+	}
+
+	for _, want := range []string{"fmt", "crypto/sha256", "llvm.org/llgo/third_party/go.tools/go/buildutil"} {
+		if !set[want] {
+			t.Errorf("Package %q not found; got %s", want, all)
+		}
+	}
+}
diff --git a/third_party/go.tools/go/buildutil/util.go b/third_party/go.tools/go/buildutil/util.go
new file mode 100644
index 0000000..60eeae2
--- /dev/null
+++ b/third_party/go.tools/go/buildutil/util.go
@@ -0,0 +1,158 @@
+// Copyright 2014 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 buildutil
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+)
+
+// ParseFile behaves like parser.ParseFile,
+// but uses the build context's file system interface, if any.
+//
+// If file is not absolute (as defined by IsAbsPath), the (dir, file)
+// components are joined using JoinPath; dir must be absolute.
+//
+// The displayPath function, if provided, is used to transform the
+// filename that will be attached to the ASTs.
+//
+// TODO(adonovan): call this from go/loader.parseFiles when the tree thaws.
+//
+func ParseFile(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, file string, mode parser.Mode) (*ast.File, error) {
+	if !IsAbsPath(ctxt, file) {
+		file = JoinPath(ctxt, dir, file)
+	}
+	rd, err := OpenFile(ctxt, file)
+	if err != nil {
+		return nil, err
+	}
+	defer rd.Close() // ignore error
+	if displayPath != nil {
+		file = displayPath(file)
+	}
+	return parser.ParseFile(fset, file, rd, mode)
+}
+
+// ContainingPackage returns the package containing filename.
+//
+// If filename is not absolute, it is interpreted relative to working directory dir.
+// All I/O is via the build context's file system interface, if any.
+//
+// The '...Files []string' fields of the resulting build.Package are not
+// populated (build.FindOnly mode).
+//
+// TODO(adonovan): call this from oracle when the tree thaws.
+//
+func ContainingPackage(ctxt *build.Context, dir, filename string) (*build.Package, error) {
+	if !IsAbsPath(ctxt, filename) {
+		filename = JoinPath(ctxt, dir, filename)
+	}
+
+	// We must not assume the file tree uses
+	// "/" always,
+	// `\` always,
+	// or os.PathSeparator (which varies by platform),
+	// but to make any progress, we are forced to assume that
+	// paths will not use `\` unless the PathSeparator
+	// is also `\`, thus we can rely on filepath.ToSlash for some sanity.
+
+	dirSlash := path.Dir(filepath.ToSlash(filename)) + "/"
+
+	// We assume that no source root (GOPATH[i] or GOROOT) contains any other.
+	for _, srcdir := range ctxt.SrcDirs() {
+		srcdirSlash := filepath.ToSlash(srcdir) + "/"
+		if strings.HasPrefix(dirSlash, srcdirSlash) {
+			importPath := dirSlash[len(srcdirSlash) : len(dirSlash)-len("/")]
+			return ctxt.Import(importPath, dir, build.FindOnly)
+		}
+	}
+
+	return nil, fmt.Errorf("can't find package containing %s", filename)
+}
+
+// -- Effective methods of file system interface -------------------------
+
+// (go/build.Context defines these as methods, but does not export them.)
+
+// TODO(adonovan): HasSubdir?
+
+// FileExists returns true if the specified file exists,
+// using the build context's file system interface.
+func FileExists(ctxt *build.Context, path string) bool {
+	if ctxt.OpenFile != nil {
+		r, err := ctxt.OpenFile(path)
+		if err != nil {
+			return false
+		}
+		r.Close() // ignore error
+		return true
+	}
+	_, err := os.Stat(path)
+	return err == nil
+}
+
+// OpenFile behaves like os.Open,
+// but uses the build context's file system interface, if any.
+func OpenFile(ctxt *build.Context, path string) (io.ReadCloser, error) {
+	if ctxt.OpenFile != nil {
+		return ctxt.OpenFile(path)
+	}
+	return os.Open(path)
+}
+
+// IsAbsPath behaves like filepath.IsAbs,
+// but uses the build context's file system interface, if any.
+func IsAbsPath(ctxt *build.Context, path string) bool {
+	if ctxt.IsAbsPath != nil {
+		return ctxt.IsAbsPath(path)
+	}
+	return filepath.IsAbs(path)
+}
+
+// JoinPath behaves like filepath.Join,
+// but uses the build context's file system interface, if any.
+func JoinPath(ctxt *build.Context, path ...string) string {
+	if ctxt.JoinPath != nil {
+		return ctxt.JoinPath(path...)
+	}
+	return filepath.Join(path...)
+}
+
+// IsDir behaves like os.Stat plus IsDir,
+// but uses the build context's file system interface, if any.
+func IsDir(ctxt *build.Context, path string) bool {
+	if ctxt.IsDir != nil {
+		return ctxt.IsDir(path)
+	}
+	fi, err := os.Stat(path)
+	return err == nil && fi.IsDir()
+}
+
+// ReadDir behaves like ioutil.ReadDir,
+// but uses the build context's file system interface, if any.
+func ReadDir(ctxt *build.Context, path string) ([]os.FileInfo, error) {
+	if ctxt.ReadDir != nil {
+		return ctxt.ReadDir(path)
+	}
+	return ioutil.ReadDir(path)
+}
+
+// SplitPathList behaves like filepath.SplitList,
+// but uses the build context's file system interface, if any.
+func SplitPathList(ctxt *build.Context, s string) []string {
+	if ctxt.SplitPathList != nil {
+		return ctxt.SplitPathList(s)
+	}
+	return filepath.SplitList(s)
+}
diff --git a/third_party/go.tools/go/buildutil/util_test.go b/third_party/go.tools/go/buildutil/util_test.go
new file mode 100644
index 0000000..586bd61
--- /dev/null
+++ b/third_party/go.tools/go/buildutil/util_test.go
@@ -0,0 +1,41 @@
+// Copyright 2014 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 buildutil_test
+
+import (
+	"go/build"
+	"os"
+	"path/filepath"
+	"runtime"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/buildutil"
+)
+
+func TestContainingPackage(t *testing.T) {
+	// unvirtualized:
+	goroot := runtime.GOROOT()
+	gopath := filepath.SplitList(os.Getenv("GOPATH"))[0]
+
+	for _, test := range [][2]string{
+		{goroot + "/src/fmt/print.go", "fmt"},
+		{goroot + "/src/encoding/json/foo.go", "encoding/json"},
+		{goroot + "/src/encoding/missing/foo.go", "(not found)"},
+		{gopath + "/src/golang.org/x/tools/go/buildutil/util_test.go",
+			"llvm.org/llgo/third_party/go.tools/go/buildutil"},
+	} {
+		file, want := test[0], test[1]
+		bp, err := buildutil.ContainingPackage(&build.Default, ".", file)
+		got := bp.ImportPath
+		if err != nil {
+			got = "(not found)"
+		}
+		if got != want {
+			t.Errorf("ContainingPackage(%q) = %s, want %s", file, got, want)
+		}
+	}
+
+	// TODO(adonovan): test on virtualized GOPATH too.
+}
diff --git a/third_party/go.tools/go/callgraph/callgraph.go b/third_party/go.tools/go/callgraph/callgraph.go
new file mode 100644
index 0000000..52a9836
--- /dev/null
+++ b/third_party/go.tools/go/callgraph/callgraph.go
@@ -0,0 +1,123 @@
+// Copyright 2013 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 callgraph defines the call graph and various algorithms
+and utilities to operate on it.
+
+A call graph is a labelled directed graph whose nodes represent
+functions and whose edge labels represent syntactic function call
+sites.  The presence of a labelled edge (caller, site, callee)
+indicates that caller may call callee at the specified call site.
+
+A call graph is a multigraph: it may contain multiple edges (caller,
+*, callee) connecting the same pair of nodes, so long as the edges
+differ by label; this occurs when one function calls another function
+from multiple call sites.  Also, it may contain multiple edges
+(caller, site, *) that differ only by callee; this indicates a
+polymorphic call.
+
+A SOUND call graph is one that overapproximates the dynamic calling
+behaviors of the program in all possible executions.  One call graph
+is more PRECISE than another if it is a smaller overapproximation of
+the dynamic behavior.
+
+All call graphs have a synthetic root node which is responsible for
+calling main() and init().
+
+Calls to built-in functions (e.g. panic, println) are not represented
+in the call graph; they are treated like built-in operators of the
+language.
+
+*/
+package callgraph
+
+// TODO(adonovan): add a function to eliminate wrappers from the
+// callgraph, preserving topology.
+// More generally, we could eliminate "uninteresting" nodes such as
+// nodes from packages we don't care about.
+
+import (
+	"fmt"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+)
+
+// A Graph represents a call graph.
+//
+// A graph may contain nodes that are not reachable from the root.
+// If the call graph is sound, such nodes indicate unreachable
+// functions.
+//
+type Graph struct {
+	Root  *Node                   // the distinguished root node
+	Nodes map[*ssa.Function]*Node // all nodes by function
+}
+
+// New returns a new Graph with the specified root node.
+func New(root *ssa.Function) *Graph {
+	g := &Graph{Nodes: make(map[*ssa.Function]*Node)}
+	g.Root = g.CreateNode(root)
+	return g
+}
+
+// CreateNode returns the Node for fn, creating it if not present.
+func (g *Graph) CreateNode(fn *ssa.Function) *Node {
+	n, ok := g.Nodes[fn]
+	if !ok {
+		n = &Node{Func: fn, ID: len(g.Nodes)}
+		g.Nodes[fn] = n
+	}
+	return n
+}
+
+// A Node represents a node in a call graph.
+type Node struct {
+	Func *ssa.Function // the function this node represents
+	ID   int           // 0-based sequence number
+	In   []*Edge       // unordered set of incoming call edges (n.In[*].Callee == n)
+	Out  []*Edge       // unordered set of outgoing call edges (n.Out[*].Caller == n)
+}
+
+func (n *Node) String() string {
+	return fmt.Sprintf("n%d:%s", n.ID, n.Func)
+}
+
+// A Edge represents an edge in the call graph.
+//
+// Site is nil for edges originating in synthetic or intrinsic
+// functions, e.g. reflect.Call or the root of the call graph.
+type Edge struct {
+	Caller *Node
+	Site   ssa.CallInstruction
+	Callee *Node
+}
+
+func (e Edge) String() string {
+	return fmt.Sprintf("%s --> %s", e.Caller, e.Callee)
+}
+
+func (e Edge) Description() string {
+	if e.Site == nil {
+		return "synthetic call"
+	}
+	return e.Site.Common().Description()
+}
+
+func (e Edge) Pos() token.Pos {
+	if e.Site == nil {
+		return token.NoPos
+	}
+	return e.Site.Pos()
+}
+
+// AddEdge adds the edge (caller, site, callee) to the call graph.
+// Elimination of duplicate edges is the caller's responsibility.
+func AddEdge(caller *Node, site ssa.CallInstruction, callee *Node) {
+	e := &Edge{caller, site, callee}
+	callee.In = append(callee.In, e)
+	caller.Out = append(caller.Out, e)
+}
diff --git a/third_party/go.tools/go/callgraph/rta/rta.go b/third_party/go.tools/go/callgraph/rta/rta.go
new file mode 100644
index 0000000..1427db2
--- /dev/null
+++ b/third_party/go.tools/go/callgraph/rta/rta.go
@@ -0,0 +1,459 @@
+// Copyright 2013 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.
+
+// This package provides Rapid Type Analysis (RTA) for Go, a fast
+// algorithm for call graph construction and discovery of reachable code
+// (and hence dead code) and runtime types.  The algorithm was first
+// described in:
+//
+// David F. Bacon and Peter F. Sweeney. 1996.
+// Fast static analysis of C++ virtual function calls. (OOPSLA '96)
+// http://doi.acm.org/10.1145/236337.236371
+//
+// The algorithm uses dynamic programming to tabulate the cross-product
+// of the set of known "address taken" functions with the set of known
+// dynamic calls of the same type.  As each new address-taken function
+// is discovered, call graph edges are added from each known callsite,
+// and as each new call site is discovered, call graph edges are added
+// from it to each known address-taken function.
+//
+// A similar approach is used for dynamic calls via interfaces: it
+// tabulates the cross-product of the set of known "runtime types",
+// i.e. types that may appear in an interface value, or be derived from
+// one via reflection, with the set of known "invoke"-mode dynamic
+// calls.  As each new "runtime type" is discovered, call edges are
+// added from the known call sites, and as each new call site is
+// discovered, call graph edges are added to each compatible
+// method.
+//
+// In addition, we must consider all exported methods of any runtime type
+// as reachable, since they may be called via reflection.
+//
+// Each time a newly added call edge causes a new function to become
+// reachable, the code of that function is analyzed for more call sites,
+// address-taken functions, and runtime types.  The process continues
+// until a fixed point is achieved.
+//
+// The resulting call graph is less precise than one produced by pointer
+// analysis, but the algorithm is much faster.  For example, running the
+// cmd/callgraph tool on its own source takes ~2.1s for RTA and ~5.4s
+// for points-to analysis.
+//
+package rta
+
+// TODO(adonovan): test it by connecting it to the interpreter and
+// replacing all "unreachable" functions by a special intrinsic, and
+// ensure that that intrinsic is never called.
+
+import (
+	"fmt"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+// A Result holds the results of Rapid Type Analysis, which includes the
+// set of reachable functions/methods, runtime types, and the call graph.
+//
+type Result struct {
+	// CallGraph is the discovered callgraph.
+	// It does not include edges for calls made via reflection.
+	CallGraph *callgraph.Graph
+
+	// Reachable contains the set of reachable functions and methods.
+	// This includes exported methods of runtime types, since
+	// they may be accessed via reflection.
+	// The value indicates whether the function is address-taken.
+	//
+	// (We wrap the bool in a struct to avoid inadvertent use of
+	// "if Reachable[f] {" to test for set membership.)
+	Reachable map[*ssa.Function]struct{ AddrTaken bool }
+
+	// RuntimeTypes contains the set of types that are needed at
+	// runtime, for interfaces or reflection.
+	//
+	// The value indicates whether the type is inaccessible to reflection.
+	// Consider:
+	// 	type A struct{B}
+	// 	fmt.Println(new(A))
+	// Types *A, A and B are accessible to reflection, but the unnamed
+	// type struct{B} is not.
+	RuntimeTypes typeutil.Map
+}
+
+// Working state of the RTA algorithm.
+type rta struct {
+	result *Result
+
+	prog *ssa.Program
+
+	worklist []*ssa.Function // list of functions to visit
+
+	// addrTakenFuncsBySig contains all address-taken *Functions, grouped by signature.
+	// Keys are *types.Signature, values are map[*ssa.Function]bool sets.
+	addrTakenFuncsBySig typeutil.Map
+
+	// dynCallSites contains all dynamic "call"-mode call sites, grouped by signature.
+	// Keys are *types.Signature, values are unordered []ssa.CallInstruction.
+	dynCallSites typeutil.Map
+
+	// invokeSites contains all "invoke"-mode call sites, grouped by interface.
+	// Keys are *types.Interface (never *types.Named),
+	// Values are unordered []ssa.CallInstruction sets.
+	invokeSites typeutil.Map
+
+	// The following two maps together define the subset of the
+	// m:n "implements" relation needed by the algorithm.
+
+	// concreteTypes maps each concrete type to the set of interfaces that it implements.
+	// Keys are types.Type, values are unordered []*types.Interface.
+	// Only concrete types used as MakeInterface operands are included.
+	concreteTypes typeutil.Map
+
+	// interfaceTypes maps each interface type to
+	// the set of concrete types that implement it.
+	// Keys are *types.Interface, values are unordered []types.Type.
+	// Only interfaces used in "invoke"-mode CallInstructions are included.
+	interfaceTypes typeutil.Map
+}
+
+// addReachable marks a function as potentially callable at run-time,
+// and ensures that it gets processed.
+func (r *rta) addReachable(f *ssa.Function, addrTaken bool) {
+	reachable := r.result.Reachable
+	n := len(reachable)
+	v := reachable[f]
+	if addrTaken {
+		v.AddrTaken = true
+	}
+	reachable[f] = v
+	if len(reachable) > n {
+		// First time seeing f.  Add it to the worklist.
+		r.worklist = append(r.worklist, f)
+	}
+}
+
+// addEdge adds the specified call graph edge, and marks it reachable.
+// addrTaken indicates whether to mark the callee as "address-taken".
+func (r *rta) addEdge(site ssa.CallInstruction, callee *ssa.Function, addrTaken bool) {
+	r.addReachable(callee, addrTaken)
+
+	if g := r.result.CallGraph; g != nil {
+		if site.Parent() == nil {
+			panic(site)
+		}
+		from := g.CreateNode(site.Parent())
+		to := g.CreateNode(callee)
+		callgraph.AddEdge(from, site, to)
+	}
+}
+
+// ---------- addrTakenFuncs × dynCallSites ----------
+
+// visitAddrTakenFunc is called each time we encounter an address-taken function f.
+func (r *rta) visitAddrTakenFunc(f *ssa.Function) {
+	// Create two-level map (Signature -> Function -> bool).
+	S := f.Signature
+	funcs, _ := r.addrTakenFuncsBySig.At(S).(map[*ssa.Function]bool)
+	if funcs == nil {
+		funcs = make(map[*ssa.Function]bool)
+		r.addrTakenFuncsBySig.Set(S, funcs)
+	}
+	if !funcs[f] {
+		// First time seeing f.
+		funcs[f] = true
+
+		// If we've seen any dyncalls of this type, mark it reachable,
+		// and add call graph edges.
+		sites, _ := r.dynCallSites.At(S).([]ssa.CallInstruction)
+		for _, site := range sites {
+			r.addEdge(site, f, true)
+		}
+	}
+}
+
+// visitDynCall is called each time we encounter a dynamic "call"-mode call.
+func (r *rta) visitDynCall(site ssa.CallInstruction) {
+	S := site.Common().Signature()
+
+	// Record the call site.
+	sites, _ := r.dynCallSites.At(S).([]ssa.CallInstruction)
+	r.dynCallSites.Set(S, append(sites, site))
+
+	// For each function of signature S that we know is address-taken,
+	// mark it reachable.  We'll add the callgraph edges later.
+	funcs, _ := r.addrTakenFuncsBySig.At(S).(map[*ssa.Function]bool)
+	for g := range funcs {
+		r.addEdge(site, g, true)
+	}
+}
+
+// ---------- concrete types × invoke sites ----------
+
+// addInvokeEdge is called for each new pair (site, C) in the matrix.
+func (r *rta) addInvokeEdge(site ssa.CallInstruction, C types.Type) {
+	// Ascertain the concrete method of C to be called.
+	imethod := site.Common().Method
+	cmethod := r.prog.Method(r.prog.MethodSets.MethodSet(C).Lookup(imethod.Pkg(), imethod.Name()))
+	r.addEdge(site, cmethod, true)
+}
+
+// visitInvoke is called each time the algorithm encounters an "invoke"-mode call.
+func (r *rta) visitInvoke(site ssa.CallInstruction) {
+	I := site.Common().Value.Type().Underlying().(*types.Interface)
+
+	// Record the invoke site.
+	sites, _ := r.invokeSites.At(I).([]ssa.CallInstruction)
+	r.invokeSites.Set(I, append(sites, site))
+
+	// Add callgraph edge for each existing
+	// address-taken concrete type implementing I.
+	for _, C := range r.implementations(I) {
+		r.addInvokeEdge(site, C)
+	}
+}
+
+// ---------- main algorithm ----------
+
+// visitFunc processes function f.
+func (r *rta) visitFunc(f *ssa.Function) {
+	var space [32]*ssa.Value // preallocate space for common case
+
+	for _, b := range f.Blocks {
+		for _, instr := range b.Instrs {
+			rands := instr.Operands(space[:0])
+
+			switch instr := instr.(type) {
+			case ssa.CallInstruction:
+				call := instr.Common()
+				if call.IsInvoke() {
+					r.visitInvoke(instr)
+				} else if g := call.StaticCallee(); g != nil {
+					r.addEdge(instr, g, false)
+				} else if _, ok := call.Value.(*ssa.Builtin); !ok {
+					r.visitDynCall(instr)
+				}
+
+				// Ignore the call-position operand when
+				// looking for address-taken Functions.
+				// Hack: assume this is rands[0].
+				rands = rands[1:]
+
+			case *ssa.MakeInterface:
+				r.addRuntimeType(instr.X.Type(), false)
+			}
+
+			// Process all address-taken functions.
+			for _, op := range rands {
+				if g, ok := (*op).(*ssa.Function); ok {
+					r.visitAddrTakenFunc(g)
+				}
+			}
+		}
+	}
+}
+
+// Analyze performs Rapid Type Analysis, starting at the specified root
+// functions.  It returns nil if no roots were specified.
+//
+// If buildCallGraph is true, Result.CallGraph will contain a call
+// graph; otherwise, only the other fields (reachable functions) are
+// populated.
+//
+func Analyze(roots []*ssa.Function, buildCallGraph bool) *Result {
+	if len(roots) == 0 {
+		return nil
+	}
+
+	r := &rta{
+		result: &Result{Reachable: make(map[*ssa.Function]struct{ AddrTaken bool })},
+		prog:   roots[0].Prog,
+	}
+
+	if buildCallGraph {
+		// TODO(adonovan): change callgraph API to eliminate the
+		// notion of a distinguished root node.  Some callgraphs
+		// have many roots, or none.
+		r.result.CallGraph = callgraph.New(roots[0])
+	}
+
+	hasher := typeutil.MakeHasher()
+	r.result.RuntimeTypes.SetHasher(hasher)
+	r.addrTakenFuncsBySig.SetHasher(hasher)
+	r.dynCallSites.SetHasher(hasher)
+	r.invokeSites.SetHasher(hasher)
+	r.concreteTypes.SetHasher(hasher)
+	r.interfaceTypes.SetHasher(hasher)
+
+	// Visit functions, processing their instructions, and adding
+	// new functions to the worklist, until a fixed point is
+	// reached.
+	var shadow []*ssa.Function // for efficiency, we double-buffer the worklist
+	r.worklist = append(r.worklist, roots...)
+	for len(r.worklist) > 0 {
+		shadow, r.worklist = r.worklist, shadow[:0]
+		for _, f := range shadow {
+			r.visitFunc(f)
+		}
+	}
+	return r.result
+}
+
+// interfaces(C) returns all currently known interfaces implemented by C.
+func (r *rta) interfaces(C types.Type) []*types.Interface {
+	// Ascertain set of interfaces C implements
+	// and update 'implements' relation.
+	var ifaces []*types.Interface
+	r.interfaceTypes.Iterate(func(I types.Type, concs interface{}) {
+		if I := I.(*types.Interface); types.Implements(C, I) {
+			concs, _ := concs.([]types.Type)
+			r.interfaceTypes.Set(I, append(concs, C))
+			ifaces = append(ifaces, I)
+		}
+	})
+	r.concreteTypes.Set(C, ifaces)
+	return ifaces
+}
+
+// implementations(I) returns all currently known concrete types that implement I.
+func (r *rta) implementations(I *types.Interface) []types.Type {
+	var concs []types.Type
+	if v := r.interfaceTypes.At(I); v != nil {
+		concs = v.([]types.Type)
+	} else {
+		// First time seeing this interface.
+		// Update the 'implements' relation.
+		r.concreteTypes.Iterate(func(C types.Type, ifaces interface{}) {
+			if types.Implements(C, I) {
+				ifaces, _ := ifaces.([]*types.Interface)
+				r.concreteTypes.Set(C, append(ifaces, I))
+				concs = append(concs, C)
+			}
+		})
+		r.interfaceTypes.Set(I, concs)
+	}
+	return concs
+}
+
+// addRuntimeType is called for each concrete type that can be the
+// dynamic type of some interface or reflect.Value.
+// Adapted from needMethods in go/ssa/builder.go
+//
+func (r *rta) addRuntimeType(T types.Type, skip bool) {
+	if prev, ok := r.result.RuntimeTypes.At(T).(bool); ok {
+		if skip && !prev {
+			r.result.RuntimeTypes.Set(T, skip)
+		}
+		return
+	}
+	r.result.RuntimeTypes.Set(T, skip)
+
+	mset := r.prog.MethodSets.MethodSet(T)
+
+	if _, ok := T.Underlying().(*types.Interface); !ok {
+		// T is a new concrete type.
+		for i, n := 0, mset.Len(); i < n; i++ {
+			sel := mset.At(i)
+			m := sel.Obj()
+
+			if m.Exported() {
+				// Exported methods are always potentially callable via reflection.
+				r.addReachable(r.prog.Method(sel), true)
+			}
+		}
+
+		// Add callgraph edge for each existing dynamic
+		// "invoke"-mode call via that interface.
+		for _, I := range r.interfaces(T) {
+			sites, _ := r.invokeSites.At(I).([]ssa.CallInstruction)
+			for _, site := range sites {
+				r.addInvokeEdge(site, T)
+			}
+		}
+	}
+
+	// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+	// Recursive case: skip => don't call makeMethods(T).
+	// Each package maintains its own set of types it has visited.
+
+	var n *types.Named
+	switch T := T.(type) {
+	case *types.Named:
+		n = T
+	case *types.Pointer:
+		n, _ = T.Elem().(*types.Named)
+	}
+	if n != nil {
+		owner := n.Obj().Pkg()
+		if owner == nil {
+			return // built-in error type
+		}
+	}
+
+	// Recursion over signatures of each exported method.
+	for i := 0; i < mset.Len(); i++ {
+		if mset.At(i).Obj().Exported() {
+			sig := mset.At(i).Type().(*types.Signature)
+			r.addRuntimeType(sig.Params(), true)  // skip the Tuple itself
+			r.addRuntimeType(sig.Results(), true) // skip the Tuple itself
+		}
+	}
+
+	switch t := T.(type) {
+	case *types.Basic:
+		// nop
+
+	case *types.Interface:
+		// nop---handled by recursion over method set.
+
+	case *types.Pointer:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Slice:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Chan:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Map:
+		r.addRuntimeType(t.Key(), false)
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Signature:
+		if t.Recv() != nil {
+			panic(fmt.Sprintf("Signature %s has Recv %s", t, t.Recv()))
+		}
+		r.addRuntimeType(t.Params(), true)  // skip the Tuple itself
+		r.addRuntimeType(t.Results(), true) // skip the Tuple itself
+
+	case *types.Named:
+		// A pointer-to-named type can be derived from a named
+		// type via reflection.  It may have methods too.
+		r.addRuntimeType(types.NewPointer(T), false)
+
+		// Consider 'type T struct{S}' where S has methods.
+		// Reflection provides no way to get from T to struct{S},
+		// only to S, so the method set of struct{S} is unwanted,
+		// so set 'skip' flag during recursion.
+		r.addRuntimeType(t.Underlying(), true)
+
+	case *types.Array:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Struct:
+		for i, n := 0, t.NumFields(); i < n; i++ {
+			r.addRuntimeType(t.Field(i).Type(), false)
+		}
+
+	case *types.Tuple:
+		for i, n := 0, t.Len(); i < n; i++ {
+			r.addRuntimeType(t.At(i).Type(), false)
+		}
+
+	default:
+		panic(T)
+	}
+}
diff --git a/third_party/go.tools/go/callgraph/rta/rta_test.go b/third_party/go.tools/go/callgraph/rta/rta_test.go
new file mode 100644
index 0000000..bbfa011
--- /dev/null
+++ b/third_party/go.tools/go/callgraph/rta/rta_test.go
@@ -0,0 +1,135 @@
+// Copyright 2014 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 rta_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"sort"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/callgraph/rta"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var inputs = []string{
+	"testdata/func.go",
+	"testdata/rtype.go",
+	"testdata/iface.go",
+}
+
+func expectation(f *ast.File) (string, token.Pos) {
+	for _, c := range f.Comments {
+		text := strings.TrimSpace(c.Text())
+		if t := strings.TrimPrefix(text, "WANT:\n"); t != text {
+			return t, c.Pos()
+		}
+	}
+	return "", token.NoPos
+}
+
+// TestRTA runs RTA on each file in inputs, prints the results, and
+// compares it with the golden results embedded in the WANT comment at
+// the end of the file.
+//
+// The results string consists of two parts: the set of dynamic call
+// edges, "f --> g", one per line, and the set of reachable functions,
+// one per line.  Each set is sorted.
+//
+func TestRTA(t *testing.T) {
+	for _, filename := range inputs {
+		content, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Errorf("couldn't read file '%s': %s", filename, err)
+			continue
+		}
+
+		conf := loader.Config{
+			SourceImports: true,
+			ParserMode:    parser.ParseComments,
+		}
+		f, err := conf.ParseFile(filename, content)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		want, pos := expectation(f)
+		if pos == token.NoPos {
+			t.Errorf("No WANT: comment in %s", filename)
+			continue
+		}
+
+		conf.CreateFromFiles("main", f)
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		prog := ssa.Create(iprog, 0)
+		mainPkg := prog.Package(iprog.Created[0].Pkg)
+		prog.BuildAll()
+
+		res := rta.Analyze([]*ssa.Function{
+			mainPkg.Func("main"),
+			mainPkg.Func("init"),
+		}, true)
+
+		if got := printResult(res, mainPkg.Object); got != want {
+			t.Errorf("%s: got:\n%s\nwant:\n%s",
+				prog.Fset.Position(pos), got, want)
+		}
+	}
+}
+
+func printResult(res *rta.Result, from *types.Package) string {
+	var buf bytes.Buffer
+
+	writeSorted := func(ss []string) {
+		sort.Strings(ss)
+		for _, s := range ss {
+			fmt.Fprintf(&buf, "  %s\n", s)
+		}
+	}
+
+	buf.WriteString("Dynamic calls\n")
+	var edges []string
+	callgraph.GraphVisitEdges(res.CallGraph, func(e *callgraph.Edge) error {
+		if strings.Contains(e.Description(), "dynamic") {
+			edges = append(edges, fmt.Sprintf("%s --> %s",
+				e.Caller.Func.RelString(from),
+				e.Callee.Func.RelString(from)))
+		}
+		return nil
+	})
+	writeSorted(edges)
+
+	buf.WriteString("Reachable functions\n")
+	var reachable []string
+	for f := range res.Reachable {
+		reachable = append(reachable, f.RelString(from))
+	}
+	writeSorted(reachable)
+
+	buf.WriteString("Reflect types\n")
+	var rtypes []string
+	res.RuntimeTypes.Iterate(func(key types.Type, value interface{}) {
+		if value == false { // accessible to reflection
+			rtypes = append(rtypes, types.TypeString(from, key))
+		}
+	})
+	writeSorted(rtypes)
+
+	return strings.TrimSpace(buf.String())
+}
diff --git a/third_party/go.tools/go/callgraph/rta/testdata/func.go b/third_party/go.tools/go/callgraph/rta/testdata/func.go
new file mode 100644
index 0000000..968c73d
--- /dev/null
+++ b/third_party/go.tools/go/callgraph/rta/testdata/func.go
@@ -0,0 +1,37 @@
+//+build ignore
+
+package main
+
+// Test of dynamic function calls.
+// No interfaces, so no runtime/reflect types.
+
+func A1() {
+	A2(0)
+}
+
+func A2(int) {} // not address-taken
+
+func B() {} // unreachable
+
+var (
+	C = func(int) {}
+	D = func(int) {}
+)
+
+func main() {
+	A1()
+
+	pfn := C
+	pfn(0) // calls C and D but not A2 (same sig but not address-taken)
+}
+
+// WANT:
+// Dynamic calls
+//   main --> init$1
+//   main --> init$2
+// Reachable functions
+//   A1
+//   A2
+//   init$1
+//   init$2
+// Reflect types
diff --git a/third_party/go.tools/go/callgraph/rta/testdata/iface.go b/third_party/go.tools/go/callgraph/rta/testdata/iface.go
new file mode 100644
index 0000000..c3ee570
--- /dev/null
+++ b/third_party/go.tools/go/callgraph/rta/testdata/iface.go
@@ -0,0 +1,79 @@
+//+build ignore
+
+package main
+
+// Test of interface calls.
+
+func use(interface{})
+
+type A byte // instantiated but not a reflect type
+
+func (A) f() {} // called directly
+func (A) F() {} // unreachable
+
+type B int // a reflect type
+
+func (*B) f() {} // reachable via interface invoke
+func (*B) F() {} // reachable: exported method of reflect type
+
+type B2 int // a reflect type, and *B2 also
+
+func (B2) f() {} // reachable via interface invoke
+func (B2) g() {} // reachable: exported method of reflect type
+
+type C string // not instantiated
+
+func (C) f() {} // unreachable
+func (C) F() {} // unreachable
+
+type D uint // instantiated only in dead code
+
+func (D) f() {} // unreachable
+func (D) F() {} // unreachable
+
+func main() {
+	A(0).f()
+
+	use(new(B))
+	use(B2(0))
+
+	var i interface {
+		f()
+	}
+	i.f() // calls (*B).f, (*B2).f and (B2.f)
+
+	live()
+}
+
+func live() {
+	var j interface {
+		f()
+		g()
+	}
+	j.f() // calls (B2).f and (*B2).f but not (*B).f (no g method).
+}
+
+func dead() {
+	use(D(0))
+}
+
+// WANT:
+// Dynamic calls
+//   live --> (*B2).f
+//   live --> (B2).f
+//   main --> (*B).f
+//   main --> (*B2).f
+//   main --> (B2).f
+// Reachable functions
+//   (*B).F
+//   (*B).f
+//   (*B2).f
+//   (A).f
+//   (B2).f
+//   live
+//   use
+// Reflect types
+//   *B
+//   *B2
+//   B
+//   B2
diff --git a/third_party/go.tools/go/callgraph/rta/testdata/rtype.go b/third_party/go.tools/go/callgraph/rta/testdata/rtype.go
new file mode 100644
index 0000000..85414e5
--- /dev/null
+++ b/third_party/go.tools/go/callgraph/rta/testdata/rtype.go
@@ -0,0 +1,35 @@
+//+build ignore
+
+package main
+
+// Test of runtime types (types for which descriptors are needed).
+
+func use(interface{})
+
+type A byte // neither A nor byte are runtime types
+
+type B struct{ x uint } // B and uint are runtime types, but not the struct
+
+func main() {
+	var x int // not a runtime type
+	print(x)
+
+	var y string // runtime type due to interface conversion
+	use(y)
+
+	use(struct{ uint64 }{}) // struct is a runtime type
+
+	use(new(B)) // *B is a runtime type
+}
+
+// WANT:
+// Dynamic calls
+// Reachable functions
+//   use
+// Reflect types
+//   *B
+//   B
+//   string
+//   struct{uint64}
+//   uint
+//   uint64
diff --git a/third_party/go.tools/go/callgraph/util.go b/third_party/go.tools/go/callgraph/util.go
new file mode 100644
index 0000000..1d3448e
--- /dev/null
+++ b/third_party/go.tools/go/callgraph/util.go
@@ -0,0 +1,181 @@
+// Copyright 2013 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 callgraph
+
+import "llvm.org/llgo/third_party/go.tools/go/ssa"
+
+// This file provides various utilities over call graphs, such as
+// visitation and path search.
+
+// CalleesOf returns a new set containing all direct callees of the
+// caller node.
+//
+func CalleesOf(caller *Node) map[*Node]bool {
+	callees := make(map[*Node]bool)
+	for _, e := range caller.Out {
+		callees[e.Callee] = true
+	}
+	return callees
+}
+
+// GraphVisitEdges visits all the edges in graph g in depth-first order.
+// The edge function is called for each edge in postorder.  If it
+// returns non-nil, visitation stops and GraphVisitEdges returns that
+// value.
+//
+func GraphVisitEdges(g *Graph, edge func(*Edge) error) error {
+	seen := make(map[*Node]bool)
+	var visit func(n *Node) error
+	visit = func(n *Node) error {
+		if !seen[n] {
+			seen[n] = true
+			for _, e := range n.Out {
+				if err := visit(e.Callee); err != nil {
+					return err
+				}
+				if err := edge(e); err != nil {
+					return err
+				}
+			}
+		}
+		return nil
+	}
+	for _, n := range g.Nodes {
+		if err := visit(n); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// PathSearch finds an arbitrary path starting at node start and
+// ending at some node for which isEnd() returns true.  On success,
+// PathSearch returns the path as an ordered list of edges; on
+// failure, it returns nil.
+//
+func PathSearch(start *Node, isEnd func(*Node) bool) []*Edge {
+	stack := make([]*Edge, 0, 32)
+	seen := make(map[*Node]bool)
+	var search func(n *Node) []*Edge
+	search = func(n *Node) []*Edge {
+		if !seen[n] {
+			seen[n] = true
+			if isEnd(n) {
+				return stack
+			}
+			for _, e := range n.Out {
+				stack = append(stack, e) // push
+				if found := search(e.Callee); found != nil {
+					return found
+				}
+				stack = stack[:len(stack)-1] // pop
+			}
+		}
+		return nil
+	}
+	return search(start)
+}
+
+// DeleteSyntheticNodes removes from call graph g all nodes for
+// synthetic functions (except g.Root and package initializers),
+// preserving the topology.  In effect, calls to synthetic wrappers
+// are "inlined".
+//
+func (g *Graph) DeleteSyntheticNodes() {
+	// Measurements on the standard library and go.tools show that
+	// resulting graph has ~15% fewer nodes and 4-8% fewer edges
+	// than the input.
+	//
+	// Inlining a wrapper of in-degree m, out-degree n adds m*n
+	// and removes m+n edges.  Since most wrappers are monomorphic
+	// (n=1) this results in a slight reduction.  Polymorphic
+	// wrappers (n>1), e.g. from embedding an interface value
+	// inside a struct to satisfy some interface, cause an
+	// increase in the graph, but they seem to be uncommon.
+
+	// Hash all existing edges to avoid creating duplicates.
+	edges := make(map[Edge]bool)
+	for _, cgn := range g.Nodes {
+		for _, e := range cgn.Out {
+			edges[*e] = true
+		}
+	}
+	for fn, cgn := range g.Nodes {
+		if cgn == g.Root || fn.Synthetic == "" || isInit(cgn.Func) {
+			continue // keep
+		}
+		for _, eIn := range cgn.In {
+			for _, eOut := range cgn.Out {
+				newEdge := Edge{eIn.Caller, eIn.Site, eOut.Callee}
+				if edges[newEdge] {
+					continue // don't add duplicate
+				}
+				AddEdge(eIn.Caller, eIn.Site, eOut.Callee)
+				edges[newEdge] = true
+			}
+		}
+		g.DeleteNode(cgn)
+	}
+}
+
+func isInit(fn *ssa.Function) bool {
+	return fn.Pkg != nil && fn.Pkg.Func("init") == fn
+}
+
+// DeleteNode removes node n and its edges from the graph g.
+// (NB: not efficient for batch deletion.)
+func (g *Graph) DeleteNode(n *Node) {
+	n.deleteIns()
+	n.deleteOuts()
+	delete(g.Nodes, n.Func)
+}
+
+// deleteIns deletes all incoming edges to n.
+func (n *Node) deleteIns() {
+	for _, e := range n.In {
+		removeOutEdge(e)
+	}
+	n.In = nil
+}
+
+// deleteOuts deletes all outgoing edges from n.
+func (n *Node) deleteOuts() {
+	for _, e := range n.Out {
+		removeInEdge(e)
+	}
+	n.Out = nil
+}
+
+// removeOutEdge removes edge.Caller's outgoing edge 'edge'.
+func removeOutEdge(edge *Edge) {
+	caller := edge.Caller
+	n := len(caller.Out)
+	for i, e := range caller.Out {
+		if e == edge {
+			// Replace it with the final element and shrink the slice.
+			caller.Out[i] = caller.Out[n-1]
+			caller.Out[n-1] = nil // aid GC
+			caller.Out = caller.Out[:n-1]
+			return
+		}
+	}
+	panic("edge not found: " + edge.String())
+}
+
+// removeInEdge removes edge.Callee's incoming edge 'edge'.
+func removeInEdge(edge *Edge) {
+	caller := edge.Callee
+	n := len(caller.In)
+	for i, e := range caller.In {
+		if e == edge {
+			// Replace it with the final element and shrink the slice.
+			caller.In[i] = caller.In[n-1]
+			caller.In[n-1] = nil // aid GC
+			caller.In = caller.In[:n-1]
+			return
+		}
+	}
+	panic("edge not found: " + edge.String())
+}
diff --git a/third_party/go.tools/go/exact/exact.go b/third_party/go.tools/go/exact/exact.go
new file mode 100644
index 0000000..06d5918
--- /dev/null
+++ b/third_party/go.tools/go/exact/exact.go
@@ -0,0 +1,918 @@
+// Copyright 2013 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 exact implements Values representing untyped
+// Go constants and the corresponding operations. Values
+// and operations have unlimited precision.
+//
+// A special Unknown value may be used when a value
+// is unknown due to an error. Operations on unknown
+// values produce unknown values unless specified
+// otherwise.
+//
+package exact
+
+import (
+	"fmt"
+	"go/token"
+	"math/big"
+	"strconv"
+)
+
+// Kind specifies the kind of value represented by a Value.
+type Kind int
+
+// Implementation note: Kinds must be enumerated in
+// order of increasing "complexity" (used by match).
+
+const (
+	// unknown values
+	Unknown Kind = iota
+
+	// non-numeric values
+	Bool
+	String
+
+	// numeric values
+	Int
+	Float
+	Complex
+)
+
+// A Value represents a mathematically exact value of a given Kind.
+type Value interface {
+	// Kind returns the value kind; it is always the smallest
+	// kind in which the value can be represented exactly.
+	Kind() Kind
+
+	// String returns a human-readable form of the value.
+	String() string
+
+	// Prevent external implementations.
+	implementsValue()
+}
+
+// ----------------------------------------------------------------------------
+// Implementations
+
+type (
+	unknownVal struct{}
+	boolVal    bool
+	stringVal  string
+	int64Val   int64
+	intVal     struct{ val *big.Int }
+	floatVal   struct{ val *big.Rat }
+	complexVal struct{ re, im *big.Rat }
+)
+
+func (unknownVal) Kind() Kind { return Unknown }
+func (boolVal) Kind() Kind    { return Bool }
+func (stringVal) Kind() Kind  { return String }
+func (int64Val) Kind() Kind   { return Int }
+func (intVal) Kind() Kind     { return Int }
+func (floatVal) Kind() Kind   { return Float }
+func (complexVal) Kind() Kind { return Complex }
+
+func (unknownVal) String() string   { return "unknown" }
+func (x boolVal) String() string    { return fmt.Sprintf("%v", bool(x)) }
+func (x stringVal) String() string  { return strconv.Quote(string(x)) }
+func (x int64Val) String() string   { return strconv.FormatInt(int64(x), 10) }
+func (x intVal) String() string     { return x.val.String() }
+func (x floatVal) String() string   { return x.val.String() }
+func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
+
+func (unknownVal) implementsValue() {}
+func (boolVal) implementsValue()    {}
+func (stringVal) implementsValue()  {}
+func (int64Val) implementsValue()   {}
+func (intVal) implementsValue()     {}
+func (floatVal) implementsValue()   {}
+func (complexVal) implementsValue() {}
+
+// int64 bounds
+var (
+	minInt64 = big.NewInt(-1 << 63)
+	maxInt64 = big.NewInt(1<<63 - 1)
+)
+
+func normInt(x *big.Int) Value {
+	if minInt64.Cmp(x) <= 0 && x.Cmp(maxInt64) <= 0 {
+		return int64Val(x.Int64())
+	}
+	return intVal{x}
+}
+
+func normFloat(x *big.Rat) Value {
+	if x.IsInt() {
+		return normInt(x.Num())
+	}
+	return floatVal{x}
+}
+
+func normComplex(re, im *big.Rat) Value {
+	if im.Sign() == 0 {
+		return normFloat(re)
+	}
+	return complexVal{re, im}
+}
+
+// ----------------------------------------------------------------------------
+// Factories
+
+// MakeUnknown returns the Unknown value.
+func MakeUnknown() Value { return unknownVal{} }
+
+// MakeBool returns the Bool value for x.
+func MakeBool(b bool) Value { return boolVal(b) }
+
+// MakeString returns the String value for x.
+func MakeString(s string) Value { return stringVal(s) }
+
+// MakeInt64 returns the Int value for x.
+func MakeInt64(x int64) Value { return int64Val(x) }
+
+// MakeUint64 returns the Int value for x.
+func MakeUint64(x uint64) Value { return normInt(new(big.Int).SetUint64(x)) }
+
+// MakeFloat64 returns the numeric value for x.
+// If x is not finite, the result is unknown.
+func MakeFloat64(x float64) Value {
+	if f := new(big.Rat).SetFloat64(x); f != nil {
+		return normFloat(f)
+	}
+	return unknownVal{}
+}
+
+// MakeFromLiteral returns the corresponding integer, floating-point,
+// imaginary, character, or string value for a Go literal string. The
+// result is nil if the literal string is invalid.
+func MakeFromLiteral(lit string, tok token.Token) Value {
+	switch tok {
+	case token.INT:
+		if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
+			return int64Val(x)
+		}
+		if x, ok := new(big.Int).SetString(lit, 0); ok {
+			return intVal{x}
+		}
+
+	case token.FLOAT:
+		if x, ok := new(big.Rat).SetString(lit); ok {
+			return normFloat(x)
+		}
+
+	case token.IMAG:
+		if n := len(lit); n > 0 && lit[n-1] == 'i' {
+			if im, ok := new(big.Rat).SetString(lit[0 : n-1]); ok {
+				return normComplex(big.NewRat(0, 1), im)
+			}
+		}
+
+	case token.CHAR:
+		if n := len(lit); n >= 2 {
+			if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil {
+				return int64Val(code)
+			}
+		}
+
+	case token.STRING:
+		if s, err := strconv.Unquote(lit); err == nil {
+			return stringVal(s)
+		}
+	}
+
+	return nil
+}
+
+// ----------------------------------------------------------------------------
+// Accessors
+//
+// For unknown arguments the result is the zero value for the respective
+// accessor type, except for Sign, where the result is 1.
+
+// BoolVal returns the Go boolean value of x, which must be a Bool or an Unknown.
+// If x is Unknown, the result is false.
+func BoolVal(x Value) bool {
+	switch x := x.(type) {
+	case boolVal:
+		return bool(x)
+	case unknownVal:
+		return false
+	}
+	panic(fmt.Sprintf("%v not a Bool", x))
+}
+
+// StringVal returns the Go string value of x, which must be a String or an Unknown.
+// If x is Unknown, the result is "".
+func StringVal(x Value) string {
+	switch x := x.(type) {
+	case stringVal:
+		return string(x)
+	case unknownVal:
+		return ""
+	}
+	panic(fmt.Sprintf("%v not a String", x))
+}
+
+// Int64Val returns the Go int64 value of x and whether the result is exact;
+// x must be an Int or an Unknown. If the result is not exact, its value is undefined.
+// If x is Unknown, the result is (0, false).
+func Int64Val(x Value) (int64, bool) {
+	switch x := x.(type) {
+	case int64Val:
+		return int64(x), true
+	case intVal:
+		return x.val.Int64(), x.val.BitLen() <= 63
+	case unknownVal:
+		return 0, false
+	}
+	panic(fmt.Sprintf("%v not an Int", x))
+}
+
+// Uint64Val returns the Go uint64 value of x and whether the result is exact;
+// x must be an Int or an Unknown. If the result is not exact, its value is undefined.
+// If x is Unknown, the result is (0, false).
+func Uint64Val(x Value) (uint64, bool) {
+	switch x := x.(type) {
+	case int64Val:
+		return uint64(x), x >= 0
+	case intVal:
+		return x.val.Uint64(), x.val.Sign() >= 0 && x.val.BitLen() <= 64
+	case unknownVal:
+		return 0, false
+	}
+	panic(fmt.Sprintf("%v not an Int", x))
+}
+
+// Float32Val is like Float64Val but for float32 instead of float64.
+func Float32Val(x Value) (float32, bool) {
+	switch x := x.(type) {
+	case int64Val:
+		f := float32(x)
+		return f, int64Val(f) == x
+	case intVal:
+		return ratToFloat32(new(big.Rat).SetFrac(x.val, int1))
+	case floatVal:
+		return ratToFloat32(x.val)
+	case unknownVal:
+		return 0, false
+	}
+	panic(fmt.Sprintf("%v not a Float", x))
+}
+
+// Float64Val returns the nearest Go float64 value of x and whether the result is exact;
+// x must be numeric but not Complex, or Unknown. For values too small (too close to 0)
+// to represent as float64, Float64Val silently underflows to 0. The result sign always
+// matches the sign of x, even for 0.
+// If x is Unknown, the result is (0, false).
+func Float64Val(x Value) (float64, bool) {
+	switch x := x.(type) {
+	case int64Val:
+		f := float64(int64(x))
+		return f, int64Val(f) == x
+	case intVal:
+		return new(big.Rat).SetFrac(x.val, int1).Float64()
+	case floatVal:
+		return x.val.Float64()
+	case unknownVal:
+		return 0, false
+	}
+	panic(fmt.Sprintf("%v not a Float", x))
+}
+
+// BitLen returns the number of bits required to represent
+// the absolute value x in binary representation; x must be an Int or an Unknown.
+// If x is Unknown, the result is 0.
+func BitLen(x Value) int {
+	switch x := x.(type) {
+	case int64Val:
+		return new(big.Int).SetInt64(int64(x)).BitLen()
+	case intVal:
+		return x.val.BitLen()
+	case unknownVal:
+		return 0
+	}
+	panic(fmt.Sprintf("%v not an Int", x))
+}
+
+// Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0;
+// x must be numeric or Unknown. For complex values x, the sign is 0 if x == 0,
+// otherwise it is != 0. If x is Unknown, the result is 1.
+func Sign(x Value) int {
+	switch x := x.(type) {
+	case int64Val:
+		switch {
+		case x < 0:
+			return -1
+		case x > 0:
+			return 1
+		}
+		return 0
+	case intVal:
+		return x.val.Sign()
+	case floatVal:
+		return x.val.Sign()
+	case complexVal:
+		return x.re.Sign() | x.im.Sign()
+	case unknownVal:
+		return 1 // avoid spurious division by zero errors
+	}
+	panic(fmt.Sprintf("%v not numeric", x))
+}
+
+// ----------------------------------------------------------------------------
+// Support for serializing/deserializing integers
+
+const (
+	// Compute the size of a Word in bytes.
+	_m       = ^big.Word(0)
+	_log     = _m>>8&1 + _m>>16&1 + _m>>32&1
+	wordSize = 1 << _log
+)
+
+// Bytes returns the bytes for the absolute value of x in little-
+// endian binary representation; x must be an Int.
+func Bytes(x Value) []byte {
+	var val *big.Int
+	switch x := x.(type) {
+	case int64Val:
+		val = new(big.Int).SetInt64(int64(x))
+	case intVal:
+		val = x.val
+	default:
+		panic(fmt.Sprintf("%v not an Int", x))
+	}
+
+	words := val.Bits()
+	bytes := make([]byte, len(words)*wordSize)
+
+	i := 0
+	for _, w := range words {
+		for j := 0; j < wordSize; j++ {
+			bytes[i] = byte(w)
+			w >>= 8
+			i++
+		}
+	}
+	// remove leading 0's
+	for i > 0 && bytes[i-1] == 0 {
+		i--
+	}
+
+	return bytes[:i]
+}
+
+// MakeFromBytes returns the Int value given the bytes of its little-endian
+// binary representation. An empty byte slice argument represents 0.
+func MakeFromBytes(bytes []byte) Value {
+	words := make([]big.Word, (len(bytes)+(wordSize-1))/wordSize)
+
+	i := 0
+	var w big.Word
+	var s uint
+	for _, b := range bytes {
+		w |= big.Word(b) << s
+		if s += 8; s == wordSize*8 {
+			words[i] = w
+			i++
+			w = 0
+			s = 0
+		}
+	}
+	// store last word
+	if i < len(words) {
+		words[i] = w
+		i++
+	}
+	// remove leading 0's
+	for i > 0 && words[i-1] == 0 {
+		i--
+	}
+
+	return normInt(new(big.Int).SetBits(words[:i]))
+}
+
+// ----------------------------------------------------------------------------
+// Support for disassembling fractions
+
+// Num returns the numerator of x; x must be Int, Float, or Unknown.
+// If x is Unknown, the result is Unknown, otherwise it is an Int
+// with the same sign as x.
+func Num(x Value) Value {
+	switch x := x.(type) {
+	case unknownVal, int64Val, intVal:
+		return x
+	case floatVal:
+		return normInt(x.val.Num())
+	}
+	panic(fmt.Sprintf("%v not Int or Float", x))
+}
+
+// Denom returns the denominator of x; x must be Int, Float, or Unknown.
+// If x is Unknown, the result is Unknown, otherwise it is an Int >= 1.
+func Denom(x Value) Value {
+	switch x := x.(type) {
+	case unknownVal:
+		return x
+	case int64Val, intVal:
+		return int64Val(1)
+	case floatVal:
+		return normInt(x.val.Denom())
+	}
+	panic(fmt.Sprintf("%v not Int or Float", x))
+}
+
+// ----------------------------------------------------------------------------
+// Support for assembling/disassembling complex numbers
+
+// MakeImag returns the numeric value x*i (possibly 0);
+// x must be Int, Float, or Unknown.
+// If x is Unknown, the result is Unknown.
+func MakeImag(x Value) Value {
+	var im *big.Rat
+	switch x := x.(type) {
+	case unknownVal:
+		return x
+	case int64Val:
+		im = big.NewRat(int64(x), 1)
+	case intVal:
+		im = new(big.Rat).SetFrac(x.val, int1)
+	case floatVal:
+		im = x.val
+	default:
+		panic(fmt.Sprintf("%v not Int or Float", x))
+	}
+	return normComplex(rat0, im)
+}
+
+// Real returns the real part of x, which must be a numeric or unknown value.
+// If x is Unknown, the result is Unknown.
+func Real(x Value) Value {
+	switch x := x.(type) {
+	case unknownVal, int64Val, intVal, floatVal:
+		return x
+	case complexVal:
+		return normFloat(x.re)
+	}
+	panic(fmt.Sprintf("%v not numeric", x))
+}
+
+// Imag returns the imaginary part of x, which must be a numeric or unknown value.
+// If x is Unknown, the result is Unknown.
+func Imag(x Value) Value {
+	switch x := x.(type) {
+	case unknownVal:
+		return x
+	case int64Val, intVal, floatVal:
+		return int64Val(0)
+	case complexVal:
+		return normFloat(x.im)
+	}
+	panic(fmt.Sprintf("%v not numeric", x))
+}
+
+// ----------------------------------------------------------------------------
+// Operations
+
+// is32bit reports whether x can be represented using 32 bits.
+func is32bit(x int64) bool {
+	const s = 32
+	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+}
+
+// is63bit reports whether x can be represented using 63 bits.
+func is63bit(x int64) bool {
+	const s = 63
+	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+}
+
+// UnaryOp returns the result of the unary expression op y.
+// The operation must be defined for the operand.
+// If size >= 0 it specifies the ^ (xor) result size in bytes.
+// If y is Unknown, the result is Unknown.
+//
+func UnaryOp(op token.Token, y Value, size int) Value {
+	switch op {
+	case token.ADD:
+		switch y.(type) {
+		case unknownVal, int64Val, intVal, floatVal, complexVal:
+			return y
+		}
+
+	case token.SUB:
+		switch y := y.(type) {
+		case unknownVal:
+			return y
+		case int64Val:
+			if z := -y; z != y {
+				return z // no overflow
+			}
+			return normInt(new(big.Int).Neg(big.NewInt(int64(y))))
+		case intVal:
+			return normInt(new(big.Int).Neg(y.val))
+		case floatVal:
+			return normFloat(new(big.Rat).Neg(y.val))
+		case complexVal:
+			return normComplex(new(big.Rat).Neg(y.re), new(big.Rat).Neg(y.im))
+		}
+
+	case token.XOR:
+		var z big.Int
+		switch y := y.(type) {
+		case unknownVal:
+			return y
+		case int64Val:
+			z.Not(big.NewInt(int64(y)))
+		case intVal:
+			z.Not(y.val)
+		default:
+			goto Error
+		}
+		// For unsigned types, the result will be negative and
+		// thus "too large": We must limit the result size to
+		// the type's size.
+		if size >= 0 {
+			s := uint(size) * 8
+			z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), s)) // z &^= (-1)<<s
+		}
+		return normInt(&z)
+
+	case token.NOT:
+		switch y := y.(type) {
+		case unknownVal:
+			return y
+		case boolVal:
+			return !y
+		}
+	}
+
+Error:
+	panic(fmt.Sprintf("invalid unary operation %s%v", op, y))
+}
+
+var (
+	int1 = big.NewInt(1)
+	rat0 = big.NewRat(0, 1)
+)
+
+func ord(x Value) int {
+	switch x.(type) {
+	default:
+		return 0
+	case int64Val:
+		return 1
+	case intVal:
+		return 2
+	case floatVal:
+		return 3
+	case complexVal:
+		return 4
+	}
+}
+
+// match returns the matching representation (same type) with the
+// smallest complexity for two values x and y. If one of them is
+// numeric, both of them must be numeric. If one of them is Unknown,
+// both results are Unknown.
+//
+func match(x, y Value) (_, _ Value) {
+	if ord(x) > ord(y) {
+		y, x = match(y, x)
+		return x, y
+	}
+	// ord(x) <= ord(y)
+
+	switch x := x.(type) {
+	case unknownVal:
+		return x, x
+
+	case boolVal, stringVal, complexVal:
+		return x, y
+
+	case int64Val:
+		switch y := y.(type) {
+		case int64Val:
+			return x, y
+		case intVal:
+			return intVal{big.NewInt(int64(x))}, y
+		case floatVal:
+			return floatVal{big.NewRat(int64(x), 1)}, y
+		case complexVal:
+			return complexVal{big.NewRat(int64(x), 1), rat0}, y
+		}
+
+	case intVal:
+		switch y := y.(type) {
+		case intVal:
+			return x, y
+		case floatVal:
+			return floatVal{new(big.Rat).SetFrac(x.val, int1)}, y
+		case complexVal:
+			return complexVal{new(big.Rat).SetFrac(x.val, int1), rat0}, y
+		}
+
+	case floatVal:
+		switch y := y.(type) {
+		case floatVal:
+			return x, y
+		case complexVal:
+			return complexVal{x.val, rat0}, y
+		}
+	}
+
+	panic("unreachable")
+}
+
+// BinaryOp returns the result of the binary expression x op y.
+// The operation must be defined for the operands. If one of the
+// operands is Unknown, the result is Unknown.
+// To force integer division of Int operands, use op == token.QUO_ASSIGN
+// instead of token.QUO; the result is guaranteed to be Int in this case.
+// Division by zero leads to a run-time panic.
+//
+func BinaryOp(x Value, op token.Token, y Value) Value {
+	x, y = match(x, y)
+
+	switch x := x.(type) {
+	case unknownVal:
+		return x
+
+	case boolVal:
+		y := y.(boolVal)
+		switch op {
+		case token.LAND:
+			return x && y
+		case token.LOR:
+			return x || y
+		}
+
+	case int64Val:
+		a := int64(x)
+		b := int64(y.(int64Val))
+		var c int64
+		switch op {
+		case token.ADD:
+			if !is63bit(a) || !is63bit(b) {
+				return normInt(new(big.Int).Add(big.NewInt(a), big.NewInt(b)))
+			}
+			c = a + b
+		case token.SUB:
+			if !is63bit(a) || !is63bit(b) {
+				return normInt(new(big.Int).Sub(big.NewInt(a), big.NewInt(b)))
+			}
+			c = a - b
+		case token.MUL:
+			if !is32bit(a) || !is32bit(b) {
+				return normInt(new(big.Int).Mul(big.NewInt(a), big.NewInt(b)))
+			}
+			c = a * b
+		case token.QUO:
+			return normFloat(new(big.Rat).SetFrac(big.NewInt(a), big.NewInt(b)))
+		case token.QUO_ASSIGN: // force integer division
+			c = a / b
+		case token.REM:
+			c = a % b
+		case token.AND:
+			c = a & b
+		case token.OR:
+			c = a | b
+		case token.XOR:
+			c = a ^ b
+		case token.AND_NOT:
+			c = a &^ b
+		default:
+			goto Error
+		}
+		return int64Val(c)
+
+	case intVal:
+		a := x.val
+		b := y.(intVal).val
+		var c big.Int
+		switch op {
+		case token.ADD:
+			c.Add(a, b)
+		case token.SUB:
+			c.Sub(a, b)
+		case token.MUL:
+			c.Mul(a, b)
+		case token.QUO:
+			return normFloat(new(big.Rat).SetFrac(a, b))
+		case token.QUO_ASSIGN: // force integer division
+			c.Quo(a, b)
+		case token.REM:
+			c.Rem(a, b)
+		case token.AND:
+			c.And(a, b)
+		case token.OR:
+			c.Or(a, b)
+		case token.XOR:
+			c.Xor(a, b)
+		case token.AND_NOT:
+			c.AndNot(a, b)
+		default:
+			goto Error
+		}
+		return normInt(&c)
+
+	case floatVal:
+		a := x.val
+		b := y.(floatVal).val
+		var c big.Rat
+		switch op {
+		case token.ADD:
+			c.Add(a, b)
+		case token.SUB:
+			c.Sub(a, b)
+		case token.MUL:
+			c.Mul(a, b)
+		case token.QUO:
+			c.Quo(a, b)
+		default:
+			goto Error
+		}
+		return normFloat(&c)
+
+	case complexVal:
+		y := y.(complexVal)
+		a, b := x.re, x.im
+		c, d := y.re, y.im
+		var re, im big.Rat
+		switch op {
+		case token.ADD:
+			// (a+c) + i(b+d)
+			re.Add(a, c)
+			im.Add(b, d)
+		case token.SUB:
+			// (a-c) + i(b-d)
+			re.Sub(a, c)
+			im.Sub(b, d)
+		case token.MUL:
+			// (ac-bd) + i(bc+ad)
+			var ac, bd, bc, ad big.Rat
+			ac.Mul(a, c)
+			bd.Mul(b, d)
+			bc.Mul(b, c)
+			ad.Mul(a, d)
+			re.Sub(&ac, &bd)
+			im.Add(&bc, &ad)
+		case token.QUO:
+			// (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
+			var ac, bd, bc, ad, s, cc, dd big.Rat
+			ac.Mul(a, c)
+			bd.Mul(b, d)
+			bc.Mul(b, c)
+			ad.Mul(a, d)
+			cc.Mul(c, c)
+			dd.Mul(d, d)
+			s.Add(&cc, &dd)
+			re.Add(&ac, &bd)
+			re.Quo(&re, &s)
+			im.Sub(&bc, &ad)
+			im.Quo(&im, &s)
+		default:
+			goto Error
+		}
+		return normComplex(&re, &im)
+
+	case stringVal:
+		if op == token.ADD {
+			return x + y.(stringVal)
+		}
+	}
+
+Error:
+	panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y))
+}
+
+// Shift returns the result of the shift expression x op s
+// with op == token.SHL or token.SHR (<< or >>). x must be
+// an Int or an Unknown. If x is Unknown, the result is x.
+//
+func Shift(x Value, op token.Token, s uint) Value {
+	switch x := x.(type) {
+	case unknownVal:
+		return x
+
+	case int64Val:
+		if s == 0 {
+			return x
+		}
+		switch op {
+		case token.SHL:
+			z := big.NewInt(int64(x))
+			return normInt(z.Lsh(z, s))
+		case token.SHR:
+			return x >> s
+		}
+
+	case intVal:
+		if s == 0 {
+			return x
+		}
+		var z big.Int
+		switch op {
+		case token.SHL:
+			return normInt(z.Lsh(x.val, s))
+		case token.SHR:
+			return normInt(z.Rsh(x.val, s))
+		}
+	}
+
+	panic(fmt.Sprintf("invalid shift %v %s %d", x, op, s))
+}
+
+func cmpZero(x int, op token.Token) bool {
+	switch op {
+	case token.EQL:
+		return x == 0
+	case token.NEQ:
+		return x != 0
+	case token.LSS:
+		return x < 0
+	case token.LEQ:
+		return x <= 0
+	case token.GTR:
+		return x > 0
+	case token.GEQ:
+		return x >= 0
+	}
+	panic("unreachable")
+}
+
+// Compare returns the result of the comparison x op y.
+// The comparison must be defined for the operands.
+// If one of the operands is Unknown, the result is
+// false.
+//
+func Compare(x Value, op token.Token, y Value) bool {
+	x, y = match(x, y)
+
+	switch x := x.(type) {
+	case unknownVal:
+		return false
+
+	case boolVal:
+		y := y.(boolVal)
+		switch op {
+		case token.EQL:
+			return x == y
+		case token.NEQ:
+			return x != y
+		}
+
+	case int64Val:
+		y := y.(int64Val)
+		switch op {
+		case token.EQL:
+			return x == y
+		case token.NEQ:
+			return x != y
+		case token.LSS:
+			return x < y
+		case token.LEQ:
+			return x <= y
+		case token.GTR:
+			return x > y
+		case token.GEQ:
+			return x >= y
+		}
+
+	case intVal:
+		return cmpZero(x.val.Cmp(y.(intVal).val), op)
+
+	case floatVal:
+		return cmpZero(x.val.Cmp(y.(floatVal).val), op)
+
+	case complexVal:
+		y := y.(complexVal)
+		re := x.re.Cmp(y.re)
+		im := x.im.Cmp(y.im)
+		switch op {
+		case token.EQL:
+			return re == 0 && im == 0
+		case token.NEQ:
+			return re != 0 || im != 0
+		}
+
+	case stringVal:
+		y := y.(stringVal)
+		switch op {
+		case token.EQL:
+			return x == y
+		case token.NEQ:
+			return x != y
+		case token.LSS:
+			return x < y
+		case token.LEQ:
+			return x <= y
+		case token.GTR:
+			return x > y
+		case token.GEQ:
+			return x >= y
+		}
+	}
+
+	panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y))
+}
diff --git a/third_party/go.tools/go/exact/exact_test.go b/third_party/go.tools/go/exact/exact_test.go
new file mode 100644
index 0000000..c517970
--- /dev/null
+++ b/third_party/go.tools/go/exact/exact_test.go
@@ -0,0 +1,348 @@
+// Copyright 2013 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 exact
+
+import (
+	"go/token"
+	"strings"
+	"testing"
+)
+
+// TODO(gri) expand this test framework
+
+var opTests = []string{
+	// unary operations
+	`+ 0 = 0`,
+	`+ ? = ?`,
+	`- 1 = -1`,
+	`- ? = ?`,
+	`^ 0 = -1`,
+	`^ ? = ?`,
+
+	`! true = false`,
+	`! false = true`,
+	`! ? = ?`,
+
+	// etc.
+
+	// binary operations
+	`"" + "" = ""`,
+	`"foo" + "" = "foo"`,
+	`"" + "bar" = "bar"`,
+	`"foo" + "bar" = "foobar"`,
+
+	`0 + 0 = 0`,
+	`0 + 0.1 = 0.1`,
+	`0 + 0.1i = 0.1i`,
+	`0.1 + 0.9 = 1`,
+	`1e100 + 1e100 = 2e100`,
+	`? + 0 = ?`,
+	`0 + ? = ?`,
+
+	`0 - 0 = 0`,
+	`0 - 0.1 = -0.1`,
+	`0 - 0.1i = -0.1i`,
+	`1e100 - 1e100 = 0`,
+	`? - 0 = ?`,
+	`0 - ? = ?`,
+
+	`0 * 0 = 0`,
+	`1 * 0.1 = 0.1`,
+	`1 * 0.1i = 0.1i`,
+	`1i * 1i = -1`,
+	`? * 0 = ?`,
+	`0 * ? = ?`,
+
+	`0 / 0 = "division_by_zero"`,
+	`10 / 2 = 5`,
+	`5 / 3 = 5/3`,
+	`5i / 3i = 5/3`,
+	`? / 0 = ?`,
+	`0 / ? = ?`,
+
+	`0 % 0 = "runtime_error:_integer_divide_by_zero"`, // TODO(gri) should be the same as for /
+	`10 % 3 = 1`,
+	`? % 0 = ?`,
+	`0 % ? = ?`,
+
+	`0 & 0 = 0`,
+	`12345 & 0 = 0`,
+	`0xff & 0xf = 0xf`,
+	`? & 0 = ?`,
+	`0 & ? = ?`,
+
+	`0 | 0 = 0`,
+	`12345 | 0 = 12345`,
+	`0xb | 0xa0 = 0xab`,
+	`? | 0 = ?`,
+	`0 | ? = ?`,
+
+	`0 ^ 0 = 0`,
+	`1 ^ -1 = -2`,
+	`? ^ 0 = ?`,
+	`0 ^ ? = ?`,
+
+	`0 &^ 0 = 0`,
+	`0xf &^ 1 = 0xe`,
+	`1 &^ 0xf = 0`,
+	// etc.
+
+	// shifts
+	`0 << 0 = 0`,
+	`1 << 10 = 1024`,
+	`0 >> 0 = 0`,
+	`1024 >> 10 == 1`,
+	`? << 0 == ?`,
+	`? >> 10 == ?`,
+	// etc.
+
+	// comparisons
+	`false == false = true`,
+	`false == true = false`,
+	`true == false = false`,
+	`true == true = true`,
+
+	`false != false = false`,
+	`false != true = true`,
+	`true != false = true`,
+	`true != true = false`,
+
+	`"foo" == "bar" = false`,
+	`"foo" != "bar" = true`,
+	`"foo" < "bar" = false`,
+	`"foo" <= "bar" = false`,
+	`"foo" > "bar" = true`,
+	`"foo" >= "bar" = true`,
+
+	`0 == 0 = true`,
+	`0 != 0 = false`,
+	`0 < 10 = true`,
+	`10 <= 10 = true`,
+	`0 > 10 = false`,
+	`10 >= 10 = true`,
+
+	`1/123456789 == 1/123456789 == true`,
+	`1/123456789 != 1/123456789 == false`,
+	`1/123456789 < 1/123456788 == true`,
+	`1/123456788 <= 1/123456789 == false`,
+	`0.11 > 0.11 = false`,
+	`0.11 >= 0.11 = true`,
+
+	`? == 0 = false`,
+	`? != 0 = false`,
+	`? < 10 = false`,
+	`? <= 10 = false`,
+	`? > 10 = false`,
+	`? >= 10 = false`,
+
+	`0 == ? = false`,
+	`0 != ? = false`,
+	`0 < ? = false`,
+	`10 <= ? = false`,
+	`0 > ? = false`,
+	`10 >= ? = false`,
+
+	// etc.
+}
+
+func TestOps(t *testing.T) {
+	for _, test := range opTests {
+		a := strings.Split(test, " ")
+		i := 0 // operator index
+
+		var x, x0 Value
+		switch len(a) {
+		case 4:
+			// unary operation
+		case 5:
+			// binary operation
+			x, x0 = val(a[0]), val(a[0])
+			i = 1
+		default:
+			t.Errorf("invalid test case: %s", test)
+			continue
+		}
+
+		op, ok := optab[a[i]]
+		if !ok {
+			panic("missing optab entry for " + a[i])
+		}
+
+		y, y0 := val(a[i+1]), val(a[i+1])
+
+		got := doOp(x, op, y)
+		want := val(a[i+3])
+		if !eql(got, want) {
+			t.Errorf("%s: got %s; want %s", test, got, want)
+		}
+		if x0 != nil && !eql(x, x0) {
+			t.Errorf("%s: x changed to %s", test, x)
+		}
+		if !eql(y, y0) {
+			t.Errorf("%s: y changed to %s", test, y)
+		}
+	}
+}
+
+func eql(x, y Value) bool {
+	_, ux := x.(unknownVal)
+	_, uy := y.(unknownVal)
+	if ux || uy {
+		return ux == uy
+	}
+	return Compare(x, token.EQL, y)
+}
+
+// ----------------------------------------------------------------------------
+// Support functions
+
+func val(lit string) Value {
+	if len(lit) == 0 {
+		return MakeUnknown()
+	}
+
+	switch lit {
+	case "?":
+		return MakeUnknown()
+	case "true":
+		return MakeBool(true)
+	case "false":
+		return MakeBool(false)
+	}
+
+	tok := token.INT
+	switch first, last := lit[0], lit[len(lit)-1]; {
+	case first == '"' || first == '`':
+		tok = token.STRING
+		lit = strings.Replace(lit, "_", " ", -1)
+	case first == '\'':
+		tok = token.CHAR
+	case last == 'i':
+		tok = token.IMAG
+	default:
+		if !strings.HasPrefix(lit, "0x") && strings.ContainsAny(lit, "./Ee") {
+			tok = token.FLOAT
+		}
+	}
+
+	return MakeFromLiteral(lit, tok)
+}
+
+var optab = map[string]token.Token{
+	"!": token.NOT,
+
+	"+": token.ADD,
+	"-": token.SUB,
+	"*": token.MUL,
+	"/": token.QUO,
+	"%": token.REM,
+
+	"<<": token.SHL,
+	">>": token.SHR,
+
+	"&":  token.AND,
+	"|":  token.OR,
+	"^":  token.XOR,
+	"&^": token.AND_NOT,
+
+	"==": token.EQL,
+	"!=": token.NEQ,
+	"<":  token.LSS,
+	"<=": token.LEQ,
+	">":  token.GTR,
+	">=": token.GEQ,
+}
+
+func panicHandler(v *Value) {
+	switch p := recover().(type) {
+	case nil:
+		// nothing to do
+	case string:
+		*v = MakeString(p)
+	case error:
+		*v = MakeString(p.Error())
+	default:
+		panic(p)
+	}
+}
+
+func doOp(x Value, op token.Token, y Value) (z Value) {
+	defer panicHandler(&z)
+
+	if x == nil {
+		return UnaryOp(op, y, -1)
+	}
+
+	switch op {
+	case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ:
+		return MakeBool(Compare(x, op, y))
+	case token.SHL, token.SHR:
+		s, _ := Int64Val(y)
+		return Shift(x, op, uint(s))
+	default:
+		return BinaryOp(x, op, y)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Other tests
+
+var fracTests = []string{
+	"0 0 1",
+	"1 1 1",
+	"-1 -1 1",
+	"1.2 6 5",
+	"-0.991 -991 1000",
+	"1e100 1e100 1",
+}
+
+func TestFractions(t *testing.T) {
+	for _, test := range fracTests {
+		a := strings.Split(test, " ")
+		if len(a) != 3 {
+			t.Errorf("invalid test case: %s", test)
+			continue
+		}
+
+		x := val(a[0])
+		n := val(a[1])
+		d := val(a[2])
+
+		if got := Num(x); !eql(got, n) {
+			t.Errorf("%s: got num = %s; want %s", test, got, n)
+		}
+
+		if got := Denom(x); !eql(got, d) {
+			t.Errorf("%s: got denom = %s; want %s", test, got, d)
+		}
+	}
+}
+
+var bytesTests = []string{
+	"0",
+	"1",
+	"123456789",
+	"123456789012345678901234567890123456789012345678901234567890",
+}
+
+func TestBytes(t *testing.T) {
+	for _, test := range bytesTests {
+		x := val(test)
+		bytes := Bytes(x)
+
+		// special case 0
+		if Sign(x) == 0 && len(bytes) != 0 {
+			t.Errorf("%s: got %v; want empty byte slice", test, bytes)
+		}
+
+		if n := len(bytes); n > 0 && bytes[n-1] == 0 {
+			t.Errorf("%s: got %v; want no leading 0 byte", test, bytes)
+		}
+
+		if got := MakeFromBytes(bytes); !eql(got, x) {
+			t.Errorf("%s: got %s; want %s (bytes = %v)", test, got, x, bytes)
+		}
+	}
+}
diff --git a/third_party/go.tools/go/exact/go13.go b/third_party/go.tools/go/exact/go13.go
new file mode 100644
index 0000000..b330a10
--- /dev/null
+++ b/third_party/go.tools/go/exact/go13.go
@@ -0,0 +1,23 @@
+// Copyright 2014 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 exact
+
+import (
+	"math"
+	"math/big"
+)
+
+func ratToFloat32(x *big.Rat) (float32, bool) {
+	// Before 1.4, there's no Rat.Float32.
+	// Emulate it, albeit at the cost of
+	// imprecision in corner cases.
+	x64, exact := x.Float64()
+	x32 := float32(x64)
+	if math.IsInf(float64(x32), 0) {
+		exact = false
+	}
+	return x32, exact
+}
diff --git a/third_party/go.tools/go/gccgoimporter/gccgoinstallation.go b/third_party/go.tools/go/gccgoimporter/gccgoinstallation.go
new file mode 100644
index 0000000..68608e9
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/gccgoinstallation.go
@@ -0,0 +1,95 @@
+// Copyright 2013 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 gccgoimporter
+
+import (
+	"bufio"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// Information about a specific installation of gccgo.
+type GccgoInstallation struct {
+	// Version of gcc (e.g. 4.8.0).
+	GccVersion string
+
+	// Target triple (e.g. x86_64-unknown-linux-gnu).
+	TargetTriple string
+
+	// Built-in library paths used by this installation.
+	LibPaths []string
+}
+
+// Ask the driver at the given path for information for this GccgoInstallation.
+func (inst *GccgoInstallation) InitFromDriver(gccgoPath string) (err error) {
+	cmd := exec.Command(gccgoPath, "-###", "-S", "-x", "go", "-")
+	stderr, err := cmd.StderrPipe()
+	if err != nil {
+		return
+	}
+
+	err = cmd.Start()
+	if err != nil {
+		return
+	}
+
+	scanner := bufio.NewScanner(stderr)
+	for scanner.Scan() {
+		line := scanner.Text()
+		switch {
+		case strings.HasPrefix(line, "Target: "):
+			inst.TargetTriple = line[8:]
+
+		case line[0] == ' ':
+			args := strings.Fields(line)
+			for _, arg := range args[1:] {
+				if strings.HasPrefix(arg, "-L") {
+					inst.LibPaths = append(inst.LibPaths, arg[2:])
+				}
+			}
+		}
+	}
+
+	stdout, err := exec.Command(gccgoPath, "-dumpversion").Output()
+	if err != nil {
+		return
+	}
+	inst.GccVersion = strings.TrimSpace(string(stdout))
+
+	return
+}
+
+// Return the list of export search paths for this GccgoInstallation.
+func (inst *GccgoInstallation) SearchPaths() (paths []string) {
+	for _, lpath := range inst.LibPaths {
+		spath := filepath.Join(lpath, "go", inst.GccVersion)
+		fi, err := os.Stat(spath)
+		if err != nil || !fi.IsDir() {
+			continue
+		}
+		paths = append(paths, spath)
+
+		spath = filepath.Join(spath, inst.TargetTriple)
+		fi, err = os.Stat(spath)
+		if err != nil || !fi.IsDir() {
+			continue
+		}
+		paths = append(paths, spath)
+	}
+
+	paths = append(paths, inst.LibPaths...)
+
+	return
+}
+
+// Return an importer that searches incpaths followed by the gcc installation's
+// built-in search paths and the current directory.
+func (inst *GccgoInstallation) GetImporter(incpaths []string, initmap map[*types.Package]InitData) types.Importer {
+	return GetImporter(append(append(incpaths, inst.SearchPaths()...), "."), initmap)
+}
diff --git a/third_party/go.tools/go/gccgoimporter/gccgoinstallation_test.go b/third_party/go.tools/go/gccgoimporter/gccgoinstallation_test.go
new file mode 100644
index 0000000..6d1a4be
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/gccgoinstallation_test.go
@@ -0,0 +1,194 @@
+// Copyright 2013 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 gccgoimporter
+
+import (
+	"runtime"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var importablePackages = [...]string{
+	"archive/tar",
+	"archive/zip",
+	"bufio",
+	"bytes",
+	"compress/bzip2",
+	"compress/flate",
+	"compress/gzip",
+	"compress/lzw",
+	"compress/zlib",
+	"container/heap",
+	"container/list",
+	"container/ring",
+	"crypto/aes",
+	"crypto/cipher",
+	"crypto/des",
+	"crypto/dsa",
+	"crypto/ecdsa",
+	"crypto/elliptic",
+	"crypto",
+	"crypto/hmac",
+	"crypto/md5",
+	"crypto/rand",
+	"crypto/rc4",
+	"crypto/rsa",
+	"crypto/sha1",
+	"crypto/sha256",
+	"crypto/sha512",
+	"crypto/subtle",
+	"crypto/tls",
+	"crypto/x509",
+	"crypto/x509/pkix",
+	"database/sql/driver",
+	"database/sql",
+	"debug/dwarf",
+	"debug/elf",
+	"debug/gosym",
+	"debug/macho",
+	"debug/pe",
+	"encoding/ascii85",
+	"encoding/asn1",
+	"encoding/base32",
+	"encoding/base64",
+	"encoding/binary",
+	"encoding/csv",
+	"encoding/gob",
+	"encoding",
+	"encoding/hex",
+	"encoding/json",
+	"encoding/pem",
+	"encoding/xml",
+	"errors",
+	"exp/proxy",
+	"exp/terminal",
+	"expvar",
+	"flag",
+	"fmt",
+	"go/ast",
+	"go/build",
+	"go/doc",
+	"go/format",
+	"go/parser",
+	"go/printer",
+	"go/scanner",
+	"go/token",
+	"hash/adler32",
+	"hash/crc32",
+	"hash/crc64",
+	"hash/fnv",
+	"hash",
+	"html",
+	"html/template",
+	"image/color",
+	"image/color/palette",
+	"image/draw",
+	"image/gif",
+	"image",
+	"image/jpeg",
+	"image/png",
+	"index/suffixarray",
+	"io",
+	"io/ioutil",
+	"log",
+	"log/syslog",
+	"math/big",
+	"math/cmplx",
+	"math",
+	"math/rand",
+	"mime",
+	"mime/multipart",
+	"net",
+	"net/http/cgi",
+	"net/http/cookiejar",
+	"net/http/fcgi",
+	"net/http",
+	"net/http/httptest",
+	"net/http/httputil",
+	"net/http/pprof",
+	"net/mail",
+	"net/rpc",
+	"net/rpc/jsonrpc",
+	"net/smtp",
+	"net/textproto",
+	"net/url",
+	"old/regexp",
+	"old/template",
+	"os/exec",
+	"os",
+	"os/signal",
+	"os/user",
+	"path/filepath",
+	"path",
+	"reflect",
+	"regexp",
+	"regexp/syntax",
+	"runtime/debug",
+	"runtime",
+	"runtime/pprof",
+	"sort",
+	"strconv",
+	"strings",
+	"sync/atomic",
+	"sync",
+	"syscall",
+	"testing",
+	"testing/iotest",
+	"testing/quick",
+	"text/scanner",
+	"text/tabwriter",
+	"text/template",
+	"text/template/parse",
+	"time",
+	"unicode",
+	"unicode/utf16",
+	"unicode/utf8",
+}
+
+func TestInstallationImporter(t *testing.T) {
+	// This test relies on gccgo being around, which it most likely will be if we
+	// were compiled with gccgo.
+	if runtime.Compiler != "gccgo" {
+		t.Skip("This test needs gccgo")
+		return
+	}
+
+	var inst GccgoInstallation
+	err := inst.InitFromDriver("gccgo")
+	if err != nil {
+		t.Fatal(err)
+	}
+	imp := inst.GetImporter(nil, nil)
+
+	// Ensure we don't regress the number of packages we can parse. First import
+	// all packages into the same map and then each individually.
+	pkgMap := make(map[string]*types.Package)
+	for _, pkg := range importablePackages {
+		_, err = imp(pkgMap, pkg)
+		if err != nil {
+			t.Error(err)
+		}
+	}
+
+	for _, pkg := range importablePackages {
+		_, err = imp(make(map[string]*types.Package), pkg)
+		if err != nil {
+			t.Error(err)
+		}
+	}
+
+	// Test for certain specific entities in the imported data.
+	for _, test := range [...]importerTest{
+		{pkgpath: "io", name: "Reader", want: "type Reader interface{Read(p []uint8) (n int, err error)}"},
+		{pkgpath: "io", name: "ReadWriter", want: "type ReadWriter interface{Reader; Writer}"},
+		{pkgpath: "math", name: "Pi", want: "const Pi untyped float"},
+		{pkgpath: "math", name: "Sin", want: "func Sin(x float64) float64"},
+		{pkgpath: "sort", name: "Ints", want: "func Ints(a []int)"},
+		{pkgpath: "unsafe", name: "Pointer", want: "type Pointer unsafe.Pointer"},
+	} {
+		runImporterTest(t, imp, nil, &test)
+	}
+}
diff --git a/third_party/go.tools/go/gccgoimporter/importer.go b/third_party/go.tools/go/gccgoimporter/importer.go
new file mode 100644
index 0000000..cf5bcf0
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/importer.go
@@ -0,0 +1,199 @@
+// Copyright 2013 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 gccgoimporter implements Import for gccgo-generated object files.
+package gccgoimporter
+
+import (
+	"bytes"
+	"debug/elf"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/importer"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// A PackageInit describes an imported package that needs initialization.
+type PackageInit struct {
+	Name     string // short package name
+	InitFunc string // name of init function
+	Priority int    // priority of init function, see InitData.Priority
+}
+
+// The gccgo-specific init data for a package.
+type InitData struct {
+	// Initialization priority of this package relative to other packages.
+	// This is based on the maximum depth of the package's dependency graph;
+	// it is guaranteed to be greater than that of its dependencies.
+	Priority int
+
+	// The list of packages which this package depends on to be initialized,
+	// including itself if needed. This is the subset of the transitive closure of
+	// the package's dependencies that need initialization.
+	Inits []PackageInit
+}
+
+// Locate the file from which to read export data.
+// This is intended to replicate the logic in gofrontend.
+func findExportFile(searchpaths []string, pkgpath string) (string, error) {
+	for _, spath := range searchpaths {
+		pkgfullpath := filepath.Join(spath, pkgpath)
+		pkgdir, name := filepath.Split(pkgfullpath)
+
+		for _, filepath := range [...]string{
+			pkgfullpath,
+			pkgfullpath + ".gox",
+			pkgdir + "lib" + name + ".so",
+			pkgdir + "lib" + name + ".a",
+			pkgfullpath + ".o",
+		} {
+			fi, err := os.Stat(filepath)
+			if err == nil && !fi.IsDir() {
+				return filepath, nil
+			}
+		}
+	}
+
+	return "", fmt.Errorf("%s: could not find export data (tried %s)", pkgpath, strings.Join(searchpaths, ":"))
+}
+
+const (
+	gccgov1Magic    = "v1;\n"
+	goimporterMagic = "\n$$ "
+	archiveMagic    = "!<ar"
+)
+
+// Opens the export data file at the given path. If this is an ELF file,
+// searches for and opens the .go_export section. If this is an archive,
+// reads the export data from the first member, which is assumed to be an ELF file.
+// This is intended to replicate the logic in gofrontend.
+func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
+	f, err := os.Open(fpath)
+	if err != nil {
+		return
+	}
+	closer = f
+	defer func() {
+		if err != nil && closer != nil {
+			f.Close()
+		}
+	}()
+
+	var magic [4]byte
+	_, err = f.ReadAt(magic[:], 0)
+	if err != nil {
+		return
+	}
+
+	var elfreader io.ReaderAt
+	switch string(magic[:]) {
+	case gccgov1Magic, goimporterMagic:
+		// Raw export data.
+		reader = f
+		return
+
+	case archiveMagic:
+		// TODO(pcc): Read the archive directly instead of using "ar".
+		f.Close()
+		closer = nil
+
+		cmd := exec.Command("ar", "p", fpath)
+		var out []byte
+		out, err = cmd.Output()
+		if err != nil {
+			return
+		}
+
+		elfreader = bytes.NewReader(out)
+
+	default:
+		elfreader = f
+	}
+
+	ef, err := elf.NewFile(elfreader)
+	if err != nil {
+		return
+	}
+
+	sec := ef.Section(".go_export")
+	if sec == nil {
+		err = fmt.Errorf("%s: .go_export section not found", fpath)
+		return
+	}
+
+	reader = sec.Open()
+	return
+}
+
+func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) types.Importer {
+	return func(imports map[string]*types.Package, pkgpath string) (pkg *types.Package, err error) {
+		if pkgpath == "unsafe" {
+			return types.Unsafe, nil
+		}
+
+		fpath, err := findExportFile(searchpaths, pkgpath)
+		if err != nil {
+			return
+		}
+
+		reader, closer, err := openExportFile(fpath)
+		if err != nil {
+			return
+		}
+		if closer != nil {
+			defer closer.Close()
+		}
+
+		var magic [4]byte
+		_, err = reader.Read(magic[:])
+		if err != nil {
+			return
+		}
+		_, err = reader.Seek(0, 0)
+		if err != nil {
+			return
+		}
+
+		switch string(magic[:]) {
+		case gccgov1Magic:
+			var p parser
+			p.init(fpath, reader, imports)
+			pkg = p.parsePackage()
+			if initmap != nil {
+				initmap[pkg] = p.initdata
+			}
+
+		case goimporterMagic:
+			var data []byte
+			data, err = ioutil.ReadAll(reader)
+			if err != nil {
+				return
+			}
+			var n int
+			n, pkg, err = importer.ImportData(imports, data)
+			if err != nil {
+				return
+			}
+
+			if initmap != nil {
+				suffixreader := bytes.NewReader(data[n:])
+				var p parser
+				p.init(fpath, suffixreader, nil)
+				p.parseInitData()
+				initmap[pkg] = p.initdata
+			}
+
+		default:
+			err = fmt.Errorf("unrecognized magic string: %q", string(magic[:]))
+		}
+
+		return
+	}
+}
diff --git a/third_party/go.tools/go/gccgoimporter/importer_test.go b/third_party/go.tools/go/gccgoimporter/importer_test.go
new file mode 100644
index 0000000..7edac89
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/importer_test.go
@@ -0,0 +1,166 @@
+// Copyright 2013 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 gccgoimporter
+
+import (
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+type importerTest struct {
+	pkgpath, name, want, wantval string
+	wantinits                    []string
+}
+
+func runImporterTest(t *testing.T, imp types.Importer, initmap map[*types.Package]InitData, test *importerTest) {
+	pkg, err := imp(make(map[string]*types.Package), test.pkgpath)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	if test.name != "" {
+		obj := pkg.Scope().Lookup(test.name)
+		if obj == nil {
+			t.Errorf("%s: object not found", test.name)
+			return
+		}
+
+		got := types.ObjectString(pkg, obj)
+		if got != test.want {
+			t.Errorf("%s: got %q; want %q", test.name, got, test.want)
+		}
+
+		if test.wantval != "" {
+			gotval := obj.(*types.Const).Val().String()
+			if gotval != test.wantval {
+				t.Errorf("%s: got val %q; want val %q", test.name, gotval, test.wantval)
+			}
+		}
+	}
+
+	if len(test.wantinits) > 0 {
+		initdata := initmap[pkg]
+		found := false
+		// Check that the package's own init function has the package's priority
+		for _, pkginit := range initdata.Inits {
+			if pkginit.InitFunc == test.wantinits[0] {
+				if initdata.Priority != pkginit.Priority {
+					t.Errorf("%s: got self priority %d; want %d", test.pkgpath, pkginit.Priority, initdata.Priority)
+				}
+				found = true
+				break
+			}
+		}
+
+		if !found {
+			t.Errorf("%s: could not find expected function %q", test.pkgpath, test.wantinits[0])
+		}
+
+		// Each init function in the list other than the first one is a
+		// dependency of the function immediately before it. Check that
+		// the init functions appear in descending priority order.
+		priority := initdata.Priority
+		for _, wantdepinit := range test.wantinits[1:] {
+			found = false
+			for _, pkginit := range initdata.Inits {
+				if pkginit.InitFunc == wantdepinit {
+					if priority <= pkginit.Priority {
+						t.Errorf("%s: got dep priority %d; want less than %d", test.pkgpath, pkginit.Priority, priority)
+					}
+					found = true
+					priority = pkginit.Priority
+					break
+				}
+			}
+
+			if !found {
+				t.Errorf("%s: could not find expected function %q", test.pkgpath, wantdepinit)
+			}
+		}
+	}
+}
+
+var importerTests = [...]importerTest{
+	{pkgpath: "pointer", name: "Int8Ptr", want: "type Int8Ptr *int8"},
+	{pkgpath: "complexnums", name: "NN", want: "const NN untyped complex", wantval: "(-1/1 + -1/1i)"},
+	{pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1/1 + 1/1i)"},
+	{pkgpath: "complexnums", name: "PN", want: "const PN untyped complex", wantval: "(1/1 + -1/1i)"},
+	{pkgpath: "complexnums", name: "PP", want: "const PP untyped complex", wantval: "(1/1 + 1/1i)"},
+	{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}},
+}
+
+func TestGoxImporter(t *testing.T) {
+	initmap := make(map[*types.Package]InitData)
+	imp := GetImporter([]string{"testdata"}, initmap)
+
+	for _, test := range importerTests {
+		runImporterTest(t, imp, initmap, &test)
+	}
+}
+
+func TestObjImporter(t *testing.T) {
+	// This test relies on gccgo being around, which it most likely will be if we
+	// were compiled with gccgo.
+	if runtime.Compiler != "gccgo" {
+		t.Skip("This test needs gccgo")
+		return
+	}
+
+	tmpdir, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Fatal(err)
+	}
+	initmap := make(map[*types.Package]InitData)
+	imp := GetImporter([]string{tmpdir}, initmap)
+
+	artmpdir, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Fatal(err)
+	}
+	arinitmap := make(map[*types.Package]InitData)
+	arimp := GetImporter([]string{artmpdir}, arinitmap)
+
+	for _, test := range importerTests {
+		gofile := filepath.Join("testdata", test.pkgpath+".go")
+		ofile := filepath.Join(tmpdir, test.pkgpath+".o")
+		afile := filepath.Join(artmpdir, "lib"+test.pkgpath+".a")
+
+		cmd := exec.Command("gccgo", "-fgo-pkgpath="+test.pkgpath, "-c", "-o", ofile, gofile)
+		out, err := cmd.CombinedOutput()
+		if err != nil {
+			t.Logf("%s", out)
+			t.Fatalf("gccgo %s failed: %s", gofile, err)
+		}
+
+		runImporterTest(t, imp, initmap, &test)
+
+		cmd = exec.Command("ar", "cr", afile, ofile)
+		out, err = cmd.CombinedOutput()
+		if err != nil {
+			t.Logf("%s", out)
+			t.Fatalf("ar cr %s %s failed: %s", afile, ofile, err)
+		}
+
+		runImporterTest(t, arimp, arinitmap, &test)
+
+		if err = os.Remove(ofile); err != nil {
+			t.Fatal(err)
+		}
+		if err = os.Remove(afile); err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	if err = os.Remove(tmpdir); err != nil {
+		t.Fatal(err)
+	}
+}
diff --git a/third_party/go.tools/go/gccgoimporter/parser.go b/third_party/go.tools/go/gccgoimporter/parser.go
new file mode 100644
index 0000000..0eb88c4
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/parser.go
@@ -0,0 +1,856 @@
+// Copyright 2013 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 gccgoimporter
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"go/token"
+	"io"
+	"strconv"
+	"strings"
+	"text/scanner"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+type parser struct {
+	scanner  scanner.Scanner
+	tok      rune                      // current token
+	lit      string                    // literal string; only valid for Ident, Int, String tokens
+	pkgpath  string                    // package path of imported package
+	pkgname  string                    // name of imported package
+	pkg      *types.Package            // reference to imported package
+	imports  map[string]*types.Package // package path -> package object
+	typeMap  map[int]types.Type        // type number -> type
+	initdata InitData                  // package init priority data
+}
+
+func (p *parser) init(filename string, src io.Reader, imports map[string]*types.Package) {
+	p.scanner.Init(src)
+	p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
+	p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+	p.scanner.Whitespace = 1<<'\t' | 1<<'\n' | 1<<' '
+	p.scanner.Filename = filename // for good error messages
+	p.next()
+	p.imports = imports
+	p.typeMap = make(map[int]types.Type)
+}
+
+type importError struct {
+	pos scanner.Position
+	err error
+}
+
+func (e importError) Error() string {
+	return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
+}
+
+func (p *parser) error(err interface{}) {
+	if s, ok := err.(string); ok {
+		err = errors.New(s)
+	}
+	// panic with a runtime.Error if err is not an error
+	panic(importError{p.scanner.Pos(), err.(error)})
+}
+
+func (p *parser) errorf(format string, args ...interface{}) {
+	p.error(fmt.Errorf(format, args...))
+}
+
+func (p *parser) expect(tok rune) string {
+	lit := p.lit
+	if p.tok != tok {
+		p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
+	}
+	p.next()
+	return lit
+}
+
+func (p *parser) expectKeyword(keyword string) {
+	lit := p.expect(scanner.Ident)
+	if lit != keyword {
+		p.errorf("expected keyword %s, got %q", keyword, lit)
+	}
+}
+
+func (p *parser) parseString() string {
+	str, err := strconv.Unquote(p.expect(scanner.String))
+	if err != nil {
+		p.error(err)
+	}
+	return str
+}
+
+// unquotedString     = { unquotedStringChar } .
+// unquotedStringChar = <neither a whitespace nor a ';' char> .
+func (p *parser) parseUnquotedString() string {
+	if p.tok == scanner.EOF {
+		p.error("unexpected EOF")
+	}
+	var buf bytes.Buffer
+	buf.WriteString(p.scanner.TokenText())
+	// This loop needs to examine each character before deciding whether to consume it. If we see a semicolon,
+	// we need to let it be consumed by p.next().
+	for ch := p.scanner.Peek(); ch != ';' && ch != scanner.EOF && p.scanner.Whitespace&(1<<uint(ch)) == 0; ch = p.scanner.Peek() {
+		buf.WriteRune(ch)
+		p.scanner.Next()
+	}
+	p.next()
+	return buf.String()
+}
+
+func (p *parser) next() {
+	p.tok = p.scanner.Scan()
+	switch p.tok {
+	case scanner.Ident, scanner.Int, scanner.Float, scanner.String, '·':
+		p.lit = p.scanner.TokenText()
+	default:
+		p.lit = ""
+	}
+}
+
+func (p *parser) parseQualifiedName() (path, name string) {
+	return p.parseQualifiedNameStr(p.parseString())
+}
+
+func (p *parser) parseUnquotedQualifiedName() (path, name string) {
+	return p.parseQualifiedNameStr(p.parseUnquotedString())
+}
+
+// qualifiedName = [ ["."] unquotedString "." ] unquotedString .
+//
+// The above production uses greedy matching.
+func (p *parser) parseQualifiedNameStr(unquotedName string) (pkgpath, name string) {
+	parts := strings.Split(unquotedName, ".")
+	if parts[0] == "" {
+		parts = parts[1:]
+	}
+
+	switch len(parts) {
+	case 0:
+		p.errorf("malformed qualified name: %q", unquotedName)
+	case 1:
+		// unqualified name
+		pkgpath = p.pkgpath
+		name = parts[0]
+	default:
+		// qualified name, which may contain periods
+		pkgpath = strings.Join(parts[0:len(parts)-1], ".")
+		name = parts[len(parts)-1]
+	}
+
+	return
+}
+
+// getPkg returns the package for a given path. If the package is
+// not found but we have a package name, create the package and
+// add it to the p.imports map.
+//
+func (p *parser) getPkg(pkgpath, name string) *types.Package {
+	// package unsafe is not in the imports map - handle explicitly
+	if pkgpath == "unsafe" {
+		return types.Unsafe
+	}
+	pkg := p.imports[pkgpath]
+	if pkg == nil && name != "" {
+		pkg = types.NewPackage(pkgpath, name)
+		p.imports[pkgpath] = pkg
+	}
+	return pkg
+}
+
+// parseExportedName is like parseQualifiedName, but
+// the package path is resolved to an imported *types.Package.
+//
+// ExportedName = string [string] .
+func (p *parser) parseExportedName() (pkg *types.Package, name string) {
+	path, name := p.parseQualifiedName()
+	var pkgname string
+	if p.tok == scanner.String {
+		pkgname = p.parseString()
+	}
+	pkg = p.getPkg(path, pkgname)
+	if pkg == nil {
+		p.errorf("package %s (path = %q) not found", name, path)
+	}
+	return
+}
+
+// Name = QualifiedName | "?" .
+func (p *parser) parseName() string {
+	if p.tok == '?' {
+		// Anonymous.
+		p.next()
+		return ""
+	}
+	// The package path is redundant for us. Don't try to parse it.
+	_, name := p.parseUnquotedQualifiedName()
+	return name
+}
+
+func deref(typ types.Type) types.Type {
+	if p, _ := typ.(*types.Pointer); p != nil {
+		typ = p.Elem()
+	}
+	return typ
+}
+
+// Field = Name Type [string] .
+func (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) {
+	name := p.parseName()
+	typ := p.parseType(pkg)
+	anon := false
+	if name == "" {
+		anon = true
+		switch typ := deref(typ).(type) {
+		case *types.Basic:
+			name = typ.Name()
+		case *types.Named:
+			name = typ.Obj().Name()
+		default:
+			p.error("anonymous field expected")
+		}
+	}
+	field = types.NewField(token.NoPos, pkg, name, typ, anon)
+	if p.tok == scanner.String {
+		tag = p.parseString()
+	}
+	return
+}
+
+// Param = Name ["..."] Type .
+func (p *parser) parseParam(pkg *types.Package) (param *types.Var, isVariadic bool) {
+	name := p.parseName()
+	if p.tok == '.' {
+		p.next()
+		p.expect('.')
+		p.expect('.')
+		isVariadic = true
+	}
+	typ := p.parseType(pkg)
+	if isVariadic {
+		typ = types.NewSlice(typ)
+	}
+	param = types.NewParam(token.NoPos, pkg, name, typ)
+	return
+}
+
+// Var = Name Type .
+func (p *parser) parseVar(pkg *types.Package) *types.Var {
+	name := p.parseName()
+	return types.NewVar(token.NoPos, pkg, name, p.parseType(pkg))
+}
+
+// ConstValue     = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) .
+// FloatOrComplex = float ["i" | ("+"|"-") float "i"] .
+func (p *parser) parseConstValue() (val exact.Value, typ types.Type) {
+	switch p.tok {
+	case scanner.String:
+		str := p.parseString()
+		val = exact.MakeString(str)
+		typ = types.Typ[types.UntypedString]
+		return
+
+	case scanner.Ident:
+		b := false
+		switch p.lit {
+		case "false":
+		case "true":
+			b = true
+
+		default:
+			p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+		}
+
+		p.next()
+		val = exact.MakeBool(b)
+		typ = types.Typ[types.UntypedBool]
+		return
+	}
+
+	sign := ""
+	if p.tok == '-' {
+		p.next()
+		sign = "-"
+	}
+
+	switch p.tok {
+	case scanner.Int:
+		val = exact.MakeFromLiteral(sign+p.lit, token.INT)
+		if val == nil {
+			p.error("could not parse integer literal")
+		}
+
+		p.next()
+		if p.tok == '\'' {
+			p.next()
+			typ = types.Typ[types.UntypedRune]
+		} else {
+			typ = types.Typ[types.UntypedInt]
+		}
+
+	case scanner.Float:
+		re := sign + p.lit
+		p.next()
+
+		var im string
+		switch p.tok {
+		case '+':
+			p.next()
+			im = p.expect(scanner.Float)
+
+		case '-':
+			p.next()
+			im = "-" + p.expect(scanner.Float)
+
+		case scanner.Ident:
+			// re is in fact the imaginary component. Expect "i" below.
+			im = re
+			re = "0"
+
+		default:
+			val = exact.MakeFromLiteral(re, token.FLOAT)
+			if val == nil {
+				p.error("could not parse float literal")
+			}
+			typ = types.Typ[types.UntypedFloat]
+			return
+		}
+
+		p.expectKeyword("i")
+		reval := exact.MakeFromLiteral(re, token.FLOAT)
+		if reval == nil {
+			p.error("could not parse real component of complex literal")
+		}
+		imval := exact.MakeFromLiteral(im+"i", token.IMAG)
+		if imval == nil {
+			p.error("could not parse imag component of complex literal")
+		}
+		val = exact.BinaryOp(reval, token.ADD, imval)
+		typ = types.Typ[types.UntypedComplex]
+
+	default:
+		p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+	}
+
+	return
+}
+
+// Const = Name [Type] "=" ConstValue .
+func (p *parser) parseConst(pkg *types.Package) *types.Const {
+	name := p.parseName()
+	var typ types.Type
+	if p.tok == '<' {
+		typ = p.parseType(pkg)
+	}
+	p.expect('=')
+	val, vtyp := p.parseConstValue()
+	if typ == nil {
+		typ = vtyp
+	}
+	return types.NewConst(token.NoPos, pkg, name, typ, val)
+}
+
+// TypeName = ExportedName .
+func (p *parser) parseTypeName() *types.TypeName {
+	pkg, name := p.parseExportedName()
+	scope := pkg.Scope()
+	if obj := scope.Lookup(name); obj != nil {
+		return obj.(*types.TypeName)
+	}
+	obj := types.NewTypeName(token.NoPos, pkg, name, nil)
+	// a named type may be referred to before the underlying type
+	// is known - set it up
+	types.NewNamed(obj, nil, nil)
+	scope.Insert(obj)
+	return obj
+}
+
+// NamedType = TypeName Type { Method } .
+// Method    = "func" "(" Param ")" Name ParamList ResultList ";" .
+func (p *parser) parseNamedType(n int) types.Type {
+	obj := p.parseTypeName()
+
+	pkg := obj.Pkg()
+	typ := obj.Type()
+	p.typeMap[n] = typ
+
+	nt, ok := typ.(*types.Named)
+	if !ok {
+		// This can happen for unsafe.Pointer, which is a TypeName holding a Basic type.
+		pt := p.parseType(pkg)
+		if pt != typ {
+			p.error("unexpected underlying type for non-named TypeName")
+		}
+		return typ
+	}
+
+	underlying := p.parseType(pkg)
+	if nt.Underlying() == nil {
+		nt.SetUnderlying(underlying.Underlying())
+	}
+
+	for p.tok == scanner.Ident {
+		// collect associated methods
+		p.expectKeyword("func")
+		p.expect('(')
+		receiver, _ := p.parseParam(pkg)
+		p.expect(')')
+		name := p.parseName()
+		params, isVariadic := p.parseParamList(pkg)
+		results := p.parseResultList(pkg)
+		p.expect(';')
+
+		sig := types.NewSignature(pkg.Scope(), receiver, params, results, isVariadic)
+		nt.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
+	}
+
+	return nt
+}
+
+func (p *parser) parseInt() int64 {
+	lit := p.expect(scanner.Int)
+	n, err := strconv.ParseInt(lit, 10, 0)
+	if err != nil {
+		p.error(err)
+	}
+	return n
+}
+
+// ArrayOrSliceType = "[" [ int ] "]" Type .
+func (p *parser) parseArrayOrSliceType(pkg *types.Package) types.Type {
+	p.expect('[')
+	if p.tok == ']' {
+		p.next()
+		return types.NewSlice(p.parseType(pkg))
+	}
+
+	n := p.parseInt()
+	p.expect(']')
+	return types.NewArray(p.parseType(pkg), n)
+}
+
+// MapType = "map" "[" Type "]" Type .
+func (p *parser) parseMapType(pkg *types.Package) types.Type {
+	p.expectKeyword("map")
+	p.expect('[')
+	key := p.parseType(pkg)
+	p.expect(']')
+	elem := p.parseType(pkg)
+	return types.NewMap(key, elem)
+}
+
+// ChanType = "chan" ["<-" | "-<"] Type .
+func (p *parser) parseChanType(pkg *types.Package) types.Type {
+	p.expectKeyword("chan")
+	dir := types.SendRecv
+	switch p.tok {
+	case '-':
+		p.next()
+		p.expect('<')
+		dir = types.SendOnly
+
+	case '<':
+		// don't consume '<' if it belongs to Type
+		if p.scanner.Peek() == '-' {
+			p.next()
+			p.expect('-')
+			dir = types.RecvOnly
+		}
+	}
+
+	return types.NewChan(dir, p.parseType(pkg))
+}
+
+// StructType = "struct" "{" { Field } "}" .
+func (p *parser) parseStructType(pkg *types.Package) types.Type {
+	p.expectKeyword("struct")
+
+	var fields []*types.Var
+	var tags []string
+
+	p.expect('{')
+	for p.tok != '}' && p.tok != scanner.EOF {
+		field, tag := p.parseField(pkg)
+		p.expect(';')
+		fields = append(fields, field)
+		tags = append(tags, tag)
+	}
+	p.expect('}')
+
+	return types.NewStruct(fields, tags)
+}
+
+// ParamList = "(" [ { Parameter "," } Parameter ] ")" .
+func (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) {
+	var list []*types.Var
+	isVariadic := false
+
+	p.expect('(')
+	for p.tok != ')' && p.tok != scanner.EOF {
+		if len(list) > 0 {
+			p.expect(',')
+		}
+		par, variadic := p.parseParam(pkg)
+		list = append(list, par)
+		if variadic {
+			if isVariadic {
+				p.error("... not on final argument")
+			}
+			isVariadic = true
+		}
+	}
+	p.expect(')')
+
+	return types.NewTuple(list...), isVariadic
+}
+
+// ResultList = Type | ParamList .
+func (p *parser) parseResultList(pkg *types.Package) *types.Tuple {
+	switch p.tok {
+	case '<':
+		return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseType(pkg)))
+
+	case '(':
+		params, _ := p.parseParamList(pkg)
+		return params
+
+	default:
+		return nil
+	}
+}
+
+// FunctionType = ParamList ResultList .
+func (p *parser) parseFunctionType(pkg *types.Package) *types.Signature {
+	params, isVariadic := p.parseParamList(pkg)
+	results := p.parseResultList(pkg)
+	return types.NewSignature(pkg.Scope(), nil, params, results, isVariadic)
+}
+
+// Func = Name FunctionType .
+func (p *parser) parseFunc(pkg *types.Package) *types.Func {
+	name := p.parseName()
+	if strings.ContainsRune(name, '$') {
+		// This is a Type$equal or Type$hash function, which we don't want to parse,
+		// except for the types.
+		p.discardDirectiveWhileParsingTypes(pkg)
+		return nil
+	}
+	return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg))
+}
+
+// InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
+func (p *parser) parseInterfaceType(pkg *types.Package) types.Type {
+	p.expectKeyword("interface")
+
+	var methods []*types.Func
+	var typs []*types.Named
+
+	p.expect('{')
+	for p.tok != '}' && p.tok != scanner.EOF {
+		if p.tok == '?' {
+			p.next()
+			typs = append(typs, p.parseType(pkg).(*types.Named))
+		} else {
+			method := p.parseFunc(pkg)
+			methods = append(methods, method)
+		}
+		p.expect(';')
+	}
+	p.expect('}')
+
+	return types.NewInterface(methods, typs)
+}
+
+// PointerType = "*" ("any" | Type) .
+func (p *parser) parsePointerType(pkg *types.Package) types.Type {
+	p.expect('*')
+	if p.tok == scanner.Ident {
+		p.expectKeyword("any")
+		return types.Typ[types.UnsafePointer]
+	}
+	return types.NewPointer(p.parseType(pkg))
+}
+
+// TypeDefinition = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .
+func (p *parser) parseTypeDefinition(pkg *types.Package, n int) types.Type {
+	var t types.Type
+	switch p.tok {
+	case scanner.String:
+		t = p.parseNamedType(n)
+
+	case scanner.Ident:
+		switch p.lit {
+		case "map":
+			t = p.parseMapType(pkg)
+
+		case "chan":
+			t = p.parseChanType(pkg)
+
+		case "struct":
+			t = p.parseStructType(pkg)
+
+		case "interface":
+			t = p.parseInterfaceType(pkg)
+		}
+
+	case '*':
+		t = p.parsePointerType(pkg)
+
+	case '[':
+		t = p.parseArrayOrSliceType(pkg)
+
+	case '(':
+		t = p.parseFunctionType(pkg)
+	}
+
+	p.typeMap[n] = t
+	return t
+}
+
+const (
+	// From gofrontend/go/export.h
+	// Note that these values are negative in the gofrontend and have been made positive
+	// in the gccgoimporter.
+	gccgoBuiltinINT8       = 1
+	gccgoBuiltinINT16      = 2
+	gccgoBuiltinINT32      = 3
+	gccgoBuiltinINT64      = 4
+	gccgoBuiltinUINT8      = 5
+	gccgoBuiltinUINT16     = 6
+	gccgoBuiltinUINT32     = 7
+	gccgoBuiltinUINT64     = 8
+	gccgoBuiltinFLOAT32    = 9
+	gccgoBuiltinFLOAT64    = 10
+	gccgoBuiltinINT        = 11
+	gccgoBuiltinUINT       = 12
+	gccgoBuiltinUINTPTR    = 13
+	gccgoBuiltinBOOL       = 15
+	gccgoBuiltinSTRING     = 16
+	gccgoBuiltinCOMPLEX64  = 17
+	gccgoBuiltinCOMPLEX128 = 18
+	gccgoBuiltinERROR      = 19
+	gccgoBuiltinBYTE       = 20
+	gccgoBuiltinRUNE       = 21
+)
+
+func lookupBuiltinType(typ int) types.Type {
+	return [...]types.Type{
+		gccgoBuiltinINT8:       types.Typ[types.Int8],
+		gccgoBuiltinINT16:      types.Typ[types.Int16],
+		gccgoBuiltinINT32:      types.Typ[types.Int32],
+		gccgoBuiltinINT64:      types.Typ[types.Int64],
+		gccgoBuiltinUINT8:      types.Typ[types.Uint8],
+		gccgoBuiltinUINT16:     types.Typ[types.Uint16],
+		gccgoBuiltinUINT32:     types.Typ[types.Uint32],
+		gccgoBuiltinUINT64:     types.Typ[types.Uint64],
+		gccgoBuiltinFLOAT32:    types.Typ[types.Float32],
+		gccgoBuiltinFLOAT64:    types.Typ[types.Float64],
+		gccgoBuiltinINT:        types.Typ[types.Int],
+		gccgoBuiltinUINT:       types.Typ[types.Uint],
+		gccgoBuiltinUINTPTR:    types.Typ[types.Uintptr],
+		gccgoBuiltinBOOL:       types.Typ[types.Bool],
+		gccgoBuiltinSTRING:     types.Typ[types.String],
+		gccgoBuiltinCOMPLEX64:  types.Typ[types.Complex64],
+		gccgoBuiltinCOMPLEX128: types.Typ[types.Complex128],
+		gccgoBuiltinERROR:      types.Universe.Lookup("error").Type(),
+		gccgoBuiltinBYTE:       types.Typ[types.Byte],
+		gccgoBuiltinRUNE:       types.Typ[types.Rune],
+	}[typ]
+}
+
+// Type = "<" "type" ( "-" int | int [ TypeDefinition ] ) ">" .
+func (p *parser) parseType(pkg *types.Package) (t types.Type) {
+	p.expect('<')
+	p.expectKeyword("type")
+
+	switch p.tok {
+	case scanner.Int:
+		n := p.parseInt()
+
+		if p.tok == '>' {
+			t = p.typeMap[int(n)]
+		} else {
+			t = p.parseTypeDefinition(pkg, int(n))
+		}
+
+	case '-':
+		p.next()
+		n := p.parseInt()
+		t = lookupBuiltinType(int(n))
+
+	default:
+		p.errorf("expected type number, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+		return nil
+	}
+
+	p.expect('>')
+	return
+}
+
+// PackageInit = unquotedString unquotedString int .
+func (p *parser) parsePackageInit() PackageInit {
+	name := p.parseUnquotedString()
+	initfunc := p.parseUnquotedString()
+	priority := int(p.parseInt())
+	return PackageInit{Name: name, InitFunc: initfunc, Priority: priority}
+}
+
+// Throw away tokens until we see a ';'. If we see a '<', attempt to parse as a type.
+func (p *parser) discardDirectiveWhileParsingTypes(pkg *types.Package) {
+	for {
+		switch p.tok {
+		case ';':
+			return
+		case '<':
+			p.parseType(p.pkg)
+		case scanner.EOF:
+			p.error("unexpected EOF")
+		default:
+			p.next()
+		}
+	}
+}
+
+// Create the package if we have parsed both the package path and package name.
+func (p *parser) maybeCreatePackage() {
+	if p.pkgname != "" && p.pkgpath != "" {
+		p.pkg = p.getPkg(p.pkgpath, p.pkgname)
+	}
+}
+
+// InitDataDirective = "v1" ";" |
+//                     "priority" int ";" |
+//                     "init" { PackageInit } ";" |
+//                     "checksum" unquotedString ";" .
+func (p *parser) parseInitDataDirective() {
+	if p.tok != scanner.Ident {
+		// unexpected token kind; panic
+		p.expect(scanner.Ident)
+	}
+
+	switch p.lit {
+	case "v1":
+		p.next()
+		p.expect(';')
+
+	case "priority":
+		p.next()
+		p.initdata.Priority = int(p.parseInt())
+		p.expect(';')
+
+	case "init":
+		p.next()
+		for p.tok != ';' && p.tok != scanner.EOF {
+			p.initdata.Inits = append(p.initdata.Inits, p.parsePackageInit())
+		}
+		p.expect(';')
+
+	case "checksum":
+		// Don't let the scanner try to parse the checksum as a number.
+		defer func(mode uint) {
+			p.scanner.Mode = mode
+		}(p.scanner.Mode)
+		p.scanner.Mode &^= scanner.ScanInts | scanner.ScanFloats
+		p.next()
+		p.parseUnquotedString()
+		p.expect(';')
+
+	default:
+		p.errorf("unexpected identifier: %q", p.lit)
+	}
+}
+
+// Directive = InitDataDirective |
+//             "package" unquotedString ";" |
+//             "pkgpath" unquotedString ";" |
+//             "import" unquotedString unquotedString string ";" |
+//             "func" Func ";" |
+//             "type" Type ";" |
+//             "var" Var ";" |
+//             "const" Const ";" .
+func (p *parser) parseDirective() {
+	if p.tok != scanner.Ident {
+		// unexpected token kind; panic
+		p.expect(scanner.Ident)
+	}
+
+	switch p.lit {
+	case "v1", "priority", "init", "checksum":
+		p.parseInitDataDirective()
+
+	case "package":
+		p.next()
+		p.pkgname = p.parseUnquotedString()
+		p.maybeCreatePackage()
+		p.expect(';')
+
+	case "pkgpath":
+		p.next()
+		p.pkgpath = p.parseUnquotedString()
+		p.maybeCreatePackage()
+		p.expect(';')
+
+	case "import":
+		p.next()
+		pkgname := p.parseUnquotedString()
+		pkgpath := p.parseUnquotedString()
+		p.getPkg(pkgpath, pkgname)
+		p.parseString()
+		p.expect(';')
+
+	case "func":
+		p.next()
+		fun := p.parseFunc(p.pkg)
+		if fun != nil {
+			p.pkg.Scope().Insert(fun)
+		}
+		p.expect(';')
+
+	case "type":
+		p.next()
+		p.parseType(p.pkg)
+		p.expect(';')
+
+	case "var":
+		p.next()
+		v := p.parseVar(p.pkg)
+		p.pkg.Scope().Insert(v)
+		p.expect(';')
+
+	case "const":
+		p.next()
+		c := p.parseConst(p.pkg)
+		p.pkg.Scope().Insert(c)
+		p.expect(';')
+
+	default:
+		p.errorf("unexpected identifier: %q", p.lit)
+	}
+}
+
+// Package = { Directive } .
+func (p *parser) parsePackage() *types.Package {
+	for p.tok != scanner.EOF {
+		p.parseDirective()
+	}
+	for _, typ := range p.typeMap {
+		if it, ok := typ.(*types.Interface); ok {
+			it.Complete()
+		}
+	}
+	p.pkg.MarkComplete()
+	return p.pkg
+}
+
+// InitData = { InitDataDirective } .
+func (p *parser) parseInitData() {
+	for p.tok != scanner.EOF {
+		p.parseInitDataDirective()
+	}
+}
diff --git a/third_party/go.tools/go/gccgoimporter/parser_test.go b/third_party/go.tools/go/gccgoimporter/parser_test.go
new file mode 100644
index 0000000..2f5e449
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/parser_test.go
@@ -0,0 +1,73 @@
+// Copyright 2013 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 gccgoimporter
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+	"text/scanner"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var typeParserTests = []struct {
+	id, typ, want, underlying, methods string
+}{
+	{id: "foo", typ: "<type -1>", want: "int8"},
+	{id: "foo", typ: "<type 1 *<type -19>>", want: "*error"},
+	{id: "foo", typ: "<type 1 *any>", want: "unsafe.Pointer"},
+	{id: "foo", typ: "<type 1 \"Bar\" <type 2 *<type 1>>>", want: "foo.Bar", underlying: "*foo.Bar"},
+	{id: "foo", typ: "<type 1 \"bar.Foo\" \"bar\" <type -1> func (? <type 1>) M (); >", want: "bar.Foo", underlying: "int8", methods: "func (bar.Foo).M()"},
+	{id: "foo", typ: "<type 1 \".bar.foo\" \"bar\" <type -1>>", want: "bar.foo", underlying: "int8"},
+	{id: "foo", typ: "<type 1 []<type -1>>", want: "[]int8"},
+	{id: "foo", typ: "<type 1 [42]<type -1>>", want: "[42]int8"},
+	{id: "foo", typ: "<type 1 map [<type -1>] <type -2>>", want: "map[int8]int16"},
+	{id: "foo", typ: "<type 1 chan <type -1>>", want: "chan int8"},
+	{id: "foo", typ: "<type 1 chan <- <type -1>>", want: "<-chan int8"},
+	{id: "foo", typ: "<type 1 chan -< <type -1>>", want: "chan<- int8"},
+	{id: "foo", typ: "<type 1 struct { I8 <type -1>; I16 <type -2> \"i16\"; }>", want: "struct{I8 int8; I16 int16 \"i16\"}"},
+	{id: "foo", typ: "<type 1 interface { Foo (a <type -1>, b <type -2>) <type -1>; Bar (? <type -2>, ? ...<type -1>) (? <type -2>, ? <type -1>); Baz (); }>", want: "interface{Bar(int16, ...int8) (int16, int8); Baz(); Foo(a int8, b int16) int8}"},
+	{id: "foo", typ: "<type 1 (? <type -1>) <type -2>>", want: "func(int8) int16"},
+}
+
+func TestTypeParser(t *testing.T) {
+	for _, test := range typeParserTests {
+		var p parser
+		p.init("test.gox", strings.NewReader(test.typ), make(map[string]*types.Package))
+		p.pkgname = test.id
+		p.pkgpath = test.id
+		p.maybeCreatePackage()
+		typ := p.parseType(p.pkg)
+
+		if p.tok != scanner.EOF {
+			t.Errorf("expected full parse, stopped at %q", p.lit)
+		}
+
+		got := typ.String()
+		if got != test.want {
+			t.Errorf("got type %q, expected %q", got, test.want)
+		}
+
+		if test.underlying != "" {
+			underlying := typ.Underlying().String()
+			if underlying != test.underlying {
+				t.Errorf("got underlying type %q, expected %q", underlying, test.underlying)
+			}
+		}
+
+		if test.methods != "" {
+			nt := typ.(*types.Named)
+			var buf bytes.Buffer
+			for i := 0; i != nt.NumMethods(); i++ {
+				buf.WriteString(nt.Method(i).String())
+			}
+			methods := buf.String()
+			if methods != test.methods {
+				t.Errorf("got methods %q, expected %q", methods, test.methods)
+			}
+		}
+	}
+}
diff --git a/third_party/go.tools/go/gccgoimporter/testdata/complexnums.go b/third_party/go.tools/go/gccgoimporter/testdata/complexnums.go
new file mode 100644
index 0000000..a51b6b0
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/testdata/complexnums.go
@@ -0,0 +1,6 @@
+package complexnums
+
+const NN = -1 - 1i
+const NP = -1 + 1i
+const PN = 1 - 1i
+const PP = 1 + 1i
diff --git a/third_party/go.tools/go/gccgoimporter/testdata/complexnums.gox b/third_party/go.tools/go/gccgoimporter/testdata/complexnums.gox
new file mode 100644
index 0000000..b66524f
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/testdata/complexnums.gox
@@ -0,0 +1,8 @@
+v1;
+package complexnums;
+pkgpath complexnums;
+priority 1;
+const NN = -0.1E1-0.1E1i ;
+const NP = -0.1E1+0.1E1i ;
+const PN = 0.1E1-0.1E1i ;
+const PP = 0.1E1+0.1E1i ;
diff --git a/third_party/go.tools/go/gccgoimporter/testdata/imports.go b/third_party/go.tools/go/gccgoimporter/testdata/imports.go
new file mode 100644
index 0000000..7907316
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/testdata/imports.go
@@ -0,0 +1,5 @@
+package imports
+
+import "fmt"
+
+var Hello = fmt.Sprintf("Hello, world")
diff --git a/third_party/go.tools/go/gccgoimporter/testdata/imports.gox b/third_party/go.tools/go/gccgoimporter/testdata/imports.gox
new file mode 100644
index 0000000..958a4f5
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/testdata/imports.gox
@@ -0,0 +1,7 @@
+v1;
+package imports;
+pkgpath imports;
+priority 7;
+import fmt fmt "fmt";
+init imports imports..import 7 math math..import 1 runtime runtime..import 1 strconv strconv..import 2 io io..import 3 reflect reflect..import 3 syscall syscall..import 3 time time..import 4 os os..import 5 fmt fmt..import 6;
+var Hello <type -16>;
diff --git a/third_party/go.tools/go/gccgoimporter/testdata/pointer.go b/third_party/go.tools/go/gccgoimporter/testdata/pointer.go
new file mode 100644
index 0000000..4ebc671
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/testdata/pointer.go
@@ -0,0 +1,3 @@
+package pointer
+
+type Int8Ptr *int8
diff --git a/third_party/go.tools/go/gccgoimporter/testdata/pointer.gox b/third_party/go.tools/go/gccgoimporter/testdata/pointer.gox
new file mode 100644
index 0000000..d96ebbd
--- /dev/null
+++ b/third_party/go.tools/go/gccgoimporter/testdata/pointer.gox
@@ -0,0 +1,4 @@
+v1;
+package pointer;
+pkgpath pointer;
+type <type 1 "Int8Ptr" <type 2 *<type -1>>>;
diff --git a/third_party/go.tools/go/gcimporter/exportdata.go b/third_party/go.tools/go/gcimporter/exportdata.go
new file mode 100644
index 0000000..657742b
--- /dev/null
+++ b/third_party/go.tools/go/gcimporter/exportdata.go
@@ -0,0 +1,108 @@
+// 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.
+
+// This file implements FindExportData.
+
+package gcimporter
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+	"strconv"
+	"strings"
+)
+
+func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
+	// See $GOROOT/include/ar.h.
+	hdr := make([]byte, 16+12+6+6+8+10+2)
+	_, err = io.ReadFull(r, hdr)
+	if err != nil {
+		return
+	}
+	// leave for debugging
+	if false {
+		fmt.Printf("header: %s", hdr)
+	}
+	s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
+	size, err = strconv.Atoi(s)
+	if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
+		err = errors.New("invalid archive header")
+		return
+	}
+	name = strings.TrimSpace(string(hdr[:16]))
+	return
+}
+
+// FindExportData positions the reader r at the beginning of the
+// export data section of an underlying GC-created object/archive
+// file by reading from it. The reader must be positioned at the
+// start of the file before calling this function.
+//
+func FindExportData(r *bufio.Reader) (err error) {
+	// Read first line to make sure this is an object file.
+	line, err := r.ReadSlice('\n')
+	if err != nil {
+		return
+	}
+	if string(line) == "!<arch>\n" {
+		// Archive file. Scan to __.PKGDEF.
+		var name string
+		var size int
+		if name, size, err = readGopackHeader(r); err != nil {
+			return
+		}
+
+		// Optional leading __.GOSYMDEF or __.SYMDEF.
+		// Read and discard.
+		if name == "__.SYMDEF" || name == "__.GOSYMDEF" {
+			const block = 4096
+			tmp := make([]byte, block)
+			for size > 0 {
+				n := size
+				if n > block {
+					n = block
+				}
+				if _, err = io.ReadFull(r, tmp[:n]); err != nil {
+					return
+				}
+				size -= n
+			}
+
+			if name, size, err = readGopackHeader(r); err != nil {
+				return
+			}
+		}
+
+		// First real entry should be __.PKGDEF.
+		if name != "__.PKGDEF" {
+			err = errors.New("go archive is missing __.PKGDEF")
+			return
+		}
+
+		// Read first line of __.PKGDEF data, so that line
+		// is once again the first line of the input.
+		if line, err = r.ReadSlice('\n'); err != nil {
+			return
+		}
+	}
+
+	// Now at __.PKGDEF in archive or still at beginning of file.
+	// Either way, line should begin with "go object ".
+	if !strings.HasPrefix(string(line), "go object ") {
+		err = errors.New("not a go object file")
+		return
+	}
+
+	// Skip over object header to export data.
+	// Begins after first line with $$.
+	for line[0] != '$' {
+		if line, err = r.ReadSlice('\n'); err != nil {
+			return
+		}
+	}
+
+	return
+}
diff --git a/third_party/go.tools/go/gcimporter/gcimporter.go b/third_party/go.tools/go/gcimporter/gcimporter.go
new file mode 100644
index 0000000..45668a0
--- /dev/null
+++ b/third_party/go.tools/go/gcimporter/gcimporter.go
@@ -0,0 +1,961 @@
+// 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.
+
+// Package gcimporter implements Import for gc-generated object files.
+// Importing this package installs Import as go/types.DefaultImport.
+package gcimporter
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"go/build"
+	"go/token"
+	"io"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"text/scanner"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// debugging/development support
+const debug = false
+
+func init() {
+	types.DefaultImport = Import
+}
+
+var pkgExts = [...]string{".a", ".5", ".6", ".8"}
+
+// FindPkg returns the filename and unique package id for an import
+// path based on package information provided by build.Import (using
+// the build.Default build.Context).
+// If no file was found, an empty filename is returned.
+//
+func FindPkg(path, srcDir string) (filename, id string) {
+	if len(path) == 0 {
+		return
+	}
+
+	id = path
+	var noext string
+	switch {
+	default:
+		// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
+		// Don't require the source files to be present.
+		bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
+		if bp.PkgObj == "" {
+			return
+		}
+		noext = strings.TrimSuffix(bp.PkgObj, ".a")
+
+	case build.IsLocalImport(path):
+		// "./x" -> "/this/directory/x.ext", "/this/directory/x"
+		noext = filepath.Join(srcDir, path)
+		id = noext
+
+	case filepath.IsAbs(path):
+		// for completeness only - go/build.Import
+		// does not support absolute imports
+		// "/x" -> "/x.ext", "/x"
+		noext = path
+	}
+
+	// try extensions
+	for _, ext := range pkgExts {
+		filename = noext + ext
+		if f, err := os.Stat(filename); err == nil && !f.IsDir() {
+			return
+		}
+	}
+
+	filename = "" // not found
+	return
+}
+
+// ImportData imports a package by reading the gc-generated export data,
+// adds the corresponding package object to the imports map indexed by id,
+// and returns the object.
+//
+// The imports map must contains all packages already imported. The data
+// reader position must be the beginning of the export data section. The
+// filename is only used in error messages.
+//
+// If imports[id] contains the completely imported package, that package
+// can be used directly, and there is no need to call this function (but
+// there is also no harm but for extra time used).
+//
+func ImportData(imports map[string]*types.Package, filename, id string, data io.Reader) (pkg *types.Package, err error) {
+	// support for parser error handling
+	defer func() {
+		switch r := recover().(type) {
+		case nil:
+			// nothing to do
+		case importError:
+			err = r
+		default:
+			panic(r) // internal error
+		}
+	}()
+
+	var p parser
+	p.init(filename, id, data, imports)
+	pkg = p.parseExport()
+
+	return
+}
+
+// Import imports a gc-generated package given its import path, adds the
+// corresponding package object to the imports map, and returns the object.
+// Local import paths are interpreted relative to the current working directory.
+// The imports map must contains all packages already imported.
+//
+func Import(imports map[string]*types.Package, path string) (pkg *types.Package, err error) {
+	if path == "unsafe" {
+		return types.Unsafe, nil
+	}
+
+	srcDir := "."
+	if build.IsLocalImport(path) {
+		srcDir, err = os.Getwd()
+		if err != nil {
+			return
+		}
+	}
+
+	filename, id := FindPkg(path, srcDir)
+	if filename == "" {
+		err = fmt.Errorf("can't find import: %s", id)
+		return
+	}
+
+	// no need to re-import if the package was imported completely before
+	if pkg = imports[id]; pkg != nil && pkg.Complete() {
+		return
+	}
+
+	// open file
+	f, err := os.Open(filename)
+	if err != nil {
+		return
+	}
+	defer func() {
+		f.Close()
+		if err != nil {
+			// add file name to error
+			err = fmt.Errorf("reading export data: %s: %v", filename, err)
+		}
+	}()
+
+	buf := bufio.NewReader(f)
+	if err = FindExportData(buf); err != nil {
+		return
+	}
+
+	pkg, err = ImportData(imports, filename, id, buf)
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Parser
+
+// TODO(gri) Imported objects don't have position information.
+//           Ideally use the debug table line info; alternatively
+//           create some fake position (or the position of the
+//           import). That way error messages referring to imported
+//           objects can print meaningful information.
+
+// parser parses the exports inside a gc compiler-produced
+// object/archive file and populates its scope with the results.
+type parser struct {
+	scanner scanner.Scanner
+	tok     rune                      // current token
+	lit     string                    // literal string; only valid for Ident, Int, String tokens
+	id      string                    // package id of imported package
+	imports map[string]*types.Package // package id -> package object
+}
+
+func (p *parser) init(filename, id string, src io.Reader, imports map[string]*types.Package) {
+	p.scanner.Init(src)
+	p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
+	p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+	p.scanner.Whitespace = 1<<'\t' | 1<<' '
+	p.scanner.Filename = filename // for good error messages
+	p.next()
+	p.id = id
+	p.imports = imports
+	if debug {
+		// check consistency of imports map
+		for _, pkg := range imports {
+			if pkg.Name() == "" {
+				fmt.Printf("no package name for %s\n", pkg.Path())
+			}
+		}
+	}
+}
+
+func (p *parser) next() {
+	p.tok = p.scanner.Scan()
+	switch p.tok {
+	case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·':
+		p.lit = p.scanner.TokenText()
+	default:
+		p.lit = ""
+	}
+	if debug {
+		fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
+	}
+}
+
+func declTypeName(pkg *types.Package, name string) *types.TypeName {
+	scope := pkg.Scope()
+	if obj := scope.Lookup(name); obj != nil {
+		return obj.(*types.TypeName)
+	}
+	obj := types.NewTypeName(token.NoPos, pkg, name, nil)
+	// a named type may be referred to before the underlying type
+	// is known - set it up
+	types.NewNamed(obj, nil, nil)
+	scope.Insert(obj)
+	return obj
+}
+
+// ----------------------------------------------------------------------------
+// Error handling
+
+// Internal errors are boxed as importErrors.
+type importError struct {
+	pos scanner.Position
+	err error
+}
+
+func (e importError) Error() string {
+	return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
+}
+
+func (p *parser) error(err interface{}) {
+	if s, ok := err.(string); ok {
+		err = errors.New(s)
+	}
+	// panic with a runtime.Error if err is not an error
+	panic(importError{p.scanner.Pos(), err.(error)})
+}
+
+func (p *parser) errorf(format string, args ...interface{}) {
+	p.error(fmt.Sprintf(format, args...))
+}
+
+func (p *parser) expect(tok rune) string {
+	lit := p.lit
+	if p.tok != tok {
+		p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
+	}
+	p.next()
+	return lit
+}
+
+func (p *parser) expectSpecial(tok string) {
+	sep := 'x' // not white space
+	i := 0
+	for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
+		sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+		p.next()
+		i++
+	}
+	if i < len(tok) {
+		p.errorf("expected %q, got %q", tok, tok[0:i])
+	}
+}
+
+func (p *parser) expectKeyword(keyword string) {
+	lit := p.expect(scanner.Ident)
+	if lit != keyword {
+		p.errorf("expected keyword %s, got %q", keyword, lit)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Qualified and unqualified names
+
+// PackageId = string_lit .
+//
+func (p *parser) parsePackageId() string {
+	id, err := strconv.Unquote(p.expect(scanner.String))
+	if err != nil {
+		p.error(err)
+	}
+	// id == "" stands for the imported package id
+	// (only known at time of package installation)
+	if id == "" {
+		id = p.id
+	}
+	return id
+}
+
+// PackageName = ident .
+//
+func (p *parser) parsePackageName() string {
+	return p.expect(scanner.Ident)
+}
+
+// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
+func (p *parser) parseDotIdent() string {
+	ident := ""
+	if p.tok != scanner.Int {
+		sep := 'x' // not white space
+		for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
+			ident += p.lit
+			sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+			p.next()
+		}
+	}
+	if ident == "" {
+		p.expect(scanner.Ident) // use expect() for error handling
+	}
+	return ident
+}
+
+// QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) .
+//
+func (p *parser) parseQualifiedName() (id, name string) {
+	p.expect('@')
+	id = p.parsePackageId()
+	p.expect('.')
+	// Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields.
+	if p.tok == '?' {
+		p.next()
+	} else {
+		name = p.parseDotIdent()
+	}
+	return
+}
+
+// getPkg returns the package for a given id. If the package is
+// not found but we have a package name, create the package and
+// add it to the p.imports map.
+//
+func (p *parser) getPkg(id, name string) *types.Package {
+	// package unsafe is not in the imports map - handle explicitly
+	if id == "unsafe" {
+		return types.Unsafe
+	}
+	pkg := p.imports[id]
+	if pkg == nil && name != "" {
+		pkg = types.NewPackage(id, name)
+		p.imports[id] = pkg
+	}
+	return pkg
+}
+
+// parseExportedName is like parseQualifiedName, but
+// the package id is resolved to an imported *types.Package.
+//
+func (p *parser) parseExportedName() (pkg *types.Package, name string) {
+	id, name := p.parseQualifiedName()
+	pkg = p.getPkg(id, "")
+	if pkg == nil {
+		p.errorf("%s package not found", id)
+	}
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+// BasicType = identifier .
+//
+func (p *parser) parseBasicType() types.Type {
+	id := p.expect(scanner.Ident)
+	obj := types.Universe.Lookup(id)
+	if obj, ok := obj.(*types.TypeName); ok {
+		return obj.Type()
+	}
+	p.errorf("not a basic type: %s", id)
+	return nil
+}
+
+// ArrayType = "[" int_lit "]" Type .
+//
+func (p *parser) parseArrayType() types.Type {
+	// "[" already consumed and lookahead known not to be "]"
+	lit := p.expect(scanner.Int)
+	p.expect(']')
+	elem := p.parseType()
+	n, err := strconv.ParseInt(lit, 10, 64)
+	if err != nil {
+		p.error(err)
+	}
+	return types.NewArray(elem, n)
+}
+
+// MapType = "map" "[" Type "]" Type .
+//
+func (p *parser) parseMapType() types.Type {
+	p.expectKeyword("map")
+	p.expect('[')
+	key := p.parseType()
+	p.expect(']')
+	elem := p.parseType()
+	return types.NewMap(key, elem)
+}
+
+// Name = identifier | "?" | QualifiedName .
+//
+// If materializePkg is set, the returned package is guaranteed to be set.
+// For fully qualified names, the returned package may be a fake package
+// (without name, scope, and not in the p.imports map), created for the
+// sole purpose of providing a package path. Fake packages are created
+// when the package id is not found in the p.imports map; in that case
+// we cannot create a real package because we don't have a package name.
+// For non-qualified names, the returned package is the imported package.
+//
+func (p *parser) parseName(materializePkg bool) (pkg *types.Package, name string) {
+	switch p.tok {
+	case scanner.Ident:
+		pkg = p.imports[p.id]
+		name = p.lit
+		p.next()
+	case '?':
+		// anonymous
+		pkg = p.imports[p.id]
+		p.next()
+	case '@':
+		// exported name prefixed with package path
+		var id string
+		id, name = p.parseQualifiedName()
+		if materializePkg {
+			// we don't have a package name - if the package
+			// doesn't exist yet, create a fake package instead
+			pkg = p.getPkg(id, "")
+			if pkg == nil {
+				pkg = types.NewPackage(id, "")
+			}
+		}
+	default:
+		p.error("name expected")
+	}
+	return
+}
+
+func deref(typ types.Type) types.Type {
+	if p, _ := typ.(*types.Pointer); p != nil {
+		return p.Elem()
+	}
+	return typ
+}
+
+// Field = Name Type [ string_lit ] .
+//
+func (p *parser) parseField() (*types.Var, string) {
+	pkg, name := p.parseName(true)
+	typ := p.parseType()
+	anonymous := false
+	if name == "" {
+		// anonymous field - typ must be T or *T and T must be a type name
+		switch typ := deref(typ).(type) {
+		case *types.Basic: // basic types are named types
+			pkg = nil
+			name = typ.Name()
+		case *types.Named:
+			name = typ.Obj().Name()
+		default:
+			p.errorf("anonymous field expected")
+		}
+		anonymous = true
+	}
+	tag := ""
+	if p.tok == scanner.String {
+		s := p.expect(scanner.String)
+		var err error
+		tag, err = strconv.Unquote(s)
+		if err != nil {
+			p.errorf("invalid struct tag %s: %s", s, err)
+		}
+	}
+	return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag
+}
+
+// StructType = "struct" "{" [ FieldList ] "}" .
+// FieldList  = Field { ";" Field } .
+//
+func (p *parser) parseStructType() types.Type {
+	var fields []*types.Var
+	var tags []string
+
+	p.expectKeyword("struct")
+	p.expect('{')
+	for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ {
+		if i > 0 {
+			p.expect(';')
+		}
+		fld, tag := p.parseField()
+		if tag != "" && tags == nil {
+			tags = make([]string, i)
+		}
+		if tags != nil {
+			tags = append(tags, tag)
+		}
+		fields = append(fields, fld)
+	}
+	p.expect('}')
+
+	return types.NewStruct(fields, tags)
+}
+
+// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
+//
+func (p *parser) parseParameter() (par *types.Var, isVariadic bool) {
+	_, name := p.parseName(false)
+	// remove gc-specific parameter numbering
+	if i := strings.Index(name, "·"); i >= 0 {
+		name = name[:i]
+	}
+	if p.tok == '.' {
+		p.expectSpecial("...")
+		isVariadic = true
+	}
+	typ := p.parseType()
+	if isVariadic {
+		typ = types.NewSlice(typ)
+	}
+	// ignore argument tag (e.g. "noescape")
+	if p.tok == scanner.String {
+		p.next()
+	}
+	// TODO(gri) should we provide a package?
+	par = types.NewVar(token.NoPos, nil, name, typ)
+	return
+}
+
+// Parameters    = "(" [ ParameterList ] ")" .
+// ParameterList = { Parameter "," } Parameter .
+//
+func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) {
+	p.expect('(')
+	for p.tok != ')' && p.tok != scanner.EOF {
+		if len(list) > 0 {
+			p.expect(',')
+		}
+		par, variadic := p.parseParameter()
+		list = append(list, par)
+		if variadic {
+			if isVariadic {
+				p.error("... not on final argument")
+			}
+			isVariadic = true
+		}
+	}
+	p.expect(')')
+
+	return
+}
+
+// Signature = Parameters [ Result ] .
+// Result    = Type | Parameters .
+//
+func (p *parser) parseSignature(recv *types.Var) *types.Signature {
+	params, isVariadic := p.parseParameters()
+
+	// optional result type
+	var results []*types.Var
+	if p.tok == '(' {
+		var variadic bool
+		results, variadic = p.parseParameters()
+		if variadic {
+			p.error("... not permitted on result type")
+		}
+	}
+
+	return types.NewSignature(nil, recv, types.NewTuple(params...), types.NewTuple(results...), isVariadic)
+}
+
+// InterfaceType = "interface" "{" [ MethodList ] "}" .
+// MethodList    = Method { ";" Method } .
+// Method        = Name Signature .
+//
+// The methods of embedded interfaces are always "inlined"
+// by the compiler and thus embedded interfaces are never
+// visible in the export data.
+//
+func (p *parser) parseInterfaceType() types.Type {
+	var methods []*types.Func
+
+	p.expectKeyword("interface")
+	p.expect('{')
+	for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ {
+		if i > 0 {
+			p.expect(';')
+		}
+		pkg, name := p.parseName(true)
+		sig := p.parseSignature(nil)
+		methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig))
+	}
+	p.expect('}')
+
+	// Complete requires the type's embedded interfaces to be fully defined,
+	// but we do not define any
+	return types.NewInterface(methods, nil).Complete()
+}
+
+// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
+//
+func (p *parser) parseChanType() types.Type {
+	dir := types.SendRecv
+	if p.tok == scanner.Ident {
+		p.expectKeyword("chan")
+		if p.tok == '<' {
+			p.expectSpecial("<-")
+			dir = types.SendOnly
+		}
+	} else {
+		p.expectSpecial("<-")
+		p.expectKeyword("chan")
+		dir = types.RecvOnly
+	}
+	elem := p.parseType()
+	return types.NewChan(dir, elem)
+}
+
+// Type =
+//	BasicType | TypeName | ArrayType | SliceType | StructType |
+//      PointerType | FuncType | InterfaceType | MapType | ChanType |
+//      "(" Type ")" .
+//
+// BasicType   = ident .
+// TypeName    = ExportedName .
+// SliceType   = "[" "]" Type .
+// PointerType = "*" Type .
+// FuncType    = "func" Signature .
+//
+func (p *parser) parseType() types.Type {
+	switch p.tok {
+	case scanner.Ident:
+		switch p.lit {
+		default:
+			return p.parseBasicType()
+		case "struct":
+			return p.parseStructType()
+		case "func":
+			// FuncType
+			p.next()
+			return p.parseSignature(nil)
+		case "interface":
+			return p.parseInterfaceType()
+		case "map":
+			return p.parseMapType()
+		case "chan":
+			return p.parseChanType()
+		}
+	case '@':
+		// TypeName
+		pkg, name := p.parseExportedName()
+		return declTypeName(pkg, name).Type()
+	case '[':
+		p.next() // look ahead
+		if p.tok == ']' {
+			// SliceType
+			p.next()
+			return types.NewSlice(p.parseType())
+		}
+		return p.parseArrayType()
+	case '*':
+		// PointerType
+		p.next()
+		return types.NewPointer(p.parseType())
+	case '<':
+		return p.parseChanType()
+	case '(':
+		// "(" Type ")"
+		p.next()
+		typ := p.parseType()
+		p.expect(')')
+		return typ
+	}
+	p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+	return nil
+}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+// ImportDecl = "import" PackageName PackageId .
+//
+func (p *parser) parseImportDecl() {
+	p.expectKeyword("import")
+	name := p.parsePackageName()
+	p.getPkg(p.parsePackageId(), name)
+}
+
+// int_lit = [ "+" | "-" ] { "0" ... "9" } .
+//
+func (p *parser) parseInt() string {
+	s := ""
+	switch p.tok {
+	case '-':
+		s = "-"
+		p.next()
+	case '+':
+		p.next()
+	}
+	return s + p.expect(scanner.Int)
+}
+
+// number = int_lit [ "p" int_lit ] .
+//
+func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) {
+	// mantissa
+	mant := exact.MakeFromLiteral(p.parseInt(), token.INT)
+	if mant == nil {
+		panic("invalid mantissa")
+	}
+
+	if p.lit == "p" {
+		// exponent (base 2)
+		p.next()
+		exp, err := strconv.ParseInt(p.parseInt(), 10, 0)
+		if err != nil {
+			p.error(err)
+		}
+		if exp < 0 {
+			denom := exact.MakeInt64(1)
+			denom = exact.Shift(denom, token.SHL, uint(-exp))
+			typ = types.Typ[types.UntypedFloat]
+			val = exact.BinaryOp(mant, token.QUO, denom)
+			return
+		}
+		if exp > 0 {
+			mant = exact.Shift(mant, token.SHL, uint(exp))
+		}
+		typ = types.Typ[types.UntypedFloat]
+		val = mant
+		return
+	}
+
+	typ = types.Typ[types.UntypedInt]
+	val = mant
+	return
+}
+
+// ConstDecl   = "const" ExportedName [ Type ] "=" Literal .
+// Literal     = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit .
+// bool_lit    = "true" | "false" .
+// complex_lit = "(" float_lit "+" float_lit "i" ")" .
+// rune_lit    = "(" int_lit "+" int_lit ")" .
+// string_lit  = `"` { unicode_char } `"` .
+//
+func (p *parser) parseConstDecl() {
+	p.expectKeyword("const")
+	pkg, name := p.parseExportedName()
+
+	var typ0 types.Type
+	if p.tok != '=' {
+		typ0 = p.parseType()
+	}
+
+	p.expect('=')
+	var typ types.Type
+	var val exact.Value
+	switch p.tok {
+	case scanner.Ident:
+		// bool_lit
+		if p.lit != "true" && p.lit != "false" {
+			p.error("expected true or false")
+		}
+		typ = types.Typ[types.UntypedBool]
+		val = exact.MakeBool(p.lit == "true")
+		p.next()
+
+	case '-', scanner.Int:
+		// int_lit
+		typ, val = p.parseNumber()
+
+	case '(':
+		// complex_lit or rune_lit
+		p.next()
+		if p.tok == scanner.Char {
+			p.next()
+			p.expect('+')
+			typ = types.Typ[types.UntypedRune]
+			_, val = p.parseNumber()
+			p.expect(')')
+			break
+		}
+		_, re := p.parseNumber()
+		p.expect('+')
+		_, im := p.parseNumber()
+		p.expectKeyword("i")
+		p.expect(')')
+		typ = types.Typ[types.UntypedComplex]
+		val = exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
+
+	case scanner.Char:
+		// rune_lit
+		typ = types.Typ[types.UntypedRune]
+		val = exact.MakeFromLiteral(p.lit, token.CHAR)
+		p.next()
+
+	case scanner.String:
+		// string_lit
+		typ = types.Typ[types.UntypedString]
+		val = exact.MakeFromLiteral(p.lit, token.STRING)
+		p.next()
+
+	default:
+		p.errorf("expected literal got %s", scanner.TokenString(p.tok))
+	}
+
+	if typ0 == nil {
+		typ0 = typ
+	}
+
+	pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val))
+}
+
+// TypeDecl = "type" ExportedName Type .
+//
+func (p *parser) parseTypeDecl() {
+	p.expectKeyword("type")
+	pkg, name := p.parseExportedName()
+	obj := declTypeName(pkg, name)
+
+	// The type object may have been imported before and thus already
+	// have a type associated with it. We still need to parse the type
+	// structure, but throw it away if the object already has a type.
+	// This ensures that all imports refer to the same type object for
+	// a given type declaration.
+	typ := p.parseType()
+
+	if name := obj.Type().(*types.Named); name.Underlying() == nil {
+		name.SetUnderlying(typ)
+	}
+}
+
+// VarDecl = "var" ExportedName Type .
+//
+func (p *parser) parseVarDecl() {
+	p.expectKeyword("var")
+	pkg, name := p.parseExportedName()
+	typ := p.parseType()
+	pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ))
+}
+
+// Func = Signature [ Body ] .
+// Body = "{" ... "}" .
+//
+func (p *parser) parseFunc(recv *types.Var) *types.Signature {
+	sig := p.parseSignature(recv)
+	if p.tok == '{' {
+		p.next()
+		for i := 1; i > 0; p.next() {
+			switch p.tok {
+			case '{':
+				i++
+			case '}':
+				i--
+			}
+		}
+	}
+	return sig
+}
+
+// MethodDecl = "func" Receiver Name Func .
+// Receiver   = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
+//
+func (p *parser) parseMethodDecl() {
+	// "func" already consumed
+	p.expect('(')
+	recv, _ := p.parseParameter() // receiver
+	p.expect(')')
+
+	// determine receiver base type object
+	base := deref(recv.Type()).(*types.Named)
+
+	// parse method name, signature, and possibly inlined body
+	_, name := p.parseName(true)
+	sig := p.parseFunc(recv)
+
+	// methods always belong to the same package as the base type object
+	pkg := base.Obj().Pkg()
+
+	// add method to type unless type was imported before
+	// and method exists already
+	// TODO(gri) This leads to a quadratic algorithm - ok for now because method counts are small.
+	base.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
+}
+
+// FuncDecl = "func" ExportedName Func .
+//
+func (p *parser) parseFuncDecl() {
+	// "func" already consumed
+	pkg, name := p.parseExportedName()
+	typ := p.parseFunc(nil)
+	pkg.Scope().Insert(types.NewFunc(token.NoPos, pkg, name, typ))
+}
+
+// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
+//
+func (p *parser) parseDecl() {
+	if p.tok == scanner.Ident {
+		switch p.lit {
+		case "import":
+			p.parseImportDecl()
+		case "const":
+			p.parseConstDecl()
+		case "type":
+			p.parseTypeDecl()
+		case "var":
+			p.parseVarDecl()
+		case "func":
+			p.next() // look ahead
+			if p.tok == '(' {
+				p.parseMethodDecl()
+			} else {
+				p.parseFuncDecl()
+			}
+		}
+	}
+	p.expect('\n')
+}
+
+// ----------------------------------------------------------------------------
+// Export
+
+// Export        = "PackageClause { Decl } "$$" .
+// PackageClause = "package" PackageName [ "safe" ] "\n" .
+//
+func (p *parser) parseExport() *types.Package {
+	p.expectKeyword("package")
+	name := p.parsePackageName()
+	if p.tok == scanner.Ident && p.lit == "safe" {
+		// package was compiled with -u option - ignore
+		p.next()
+	}
+	p.expect('\n')
+
+	pkg := p.getPkg(p.id, name)
+
+	for p.tok != '$' && p.tok != scanner.EOF {
+		p.parseDecl()
+	}
+
+	if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
+		// don't call next()/expect() since reading past the
+		// export data may cause scanner errors (e.g. NUL chars)
+		p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
+	}
+
+	if n := p.scanner.ErrorCount; n != 0 {
+		p.errorf("expected no scanner errors, got %d", n)
+	}
+
+	// package was imported completely and without errors
+	pkg.MarkComplete()
+
+	return pkg
+}
diff --git a/third_party/go.tools/go/gcimporter/gcimporter_test.go b/third_party/go.tools/go/gcimporter/gcimporter_test.go
new file mode 100644
index 0000000..7c77502
--- /dev/null
+++ b/third_party/go.tools/go/gcimporter/gcimporter_test.go
@@ -0,0 +1,216 @@
+// 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.
+
+package gcimporter
+
+import (
+	"go/build"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var gcPath string // Go compiler path
+
+func init() {
+	// determine compiler
+	var gc string
+	switch runtime.GOARCH {
+	case "386":
+		gc = "8g"
+	case "amd64":
+		gc = "6g"
+	case "arm":
+		gc = "5g"
+	default:
+		gcPath = "unknown-GOARCH-compiler"
+		return
+	}
+	gcPath = filepath.Join(build.ToolDir, gc)
+}
+
+func compile(t *testing.T, dirname, filename string) string {
+	cmd := exec.Command(gcPath, filename)
+	cmd.Dir = dirname
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Logf("%s", out)
+		t.Fatalf("%s %s failed: %s", gcPath, filename, err)
+	}
+	archCh, _ := build.ArchChar(runtime.GOARCH)
+	// filename should end with ".go"
+	return filepath.Join(dirname, filename[:len(filename)-2]+archCh)
+}
+
+// Use the same global imports map for all tests. The effect is
+// as if all tested packages were imported into a single package.
+var imports = make(map[string]*types.Package)
+
+func testPath(t *testing.T, path string) bool {
+	t0 := time.Now()
+	_, err := Import(imports, path)
+	if err != nil {
+		t.Errorf("testPath(%s): %s", path, err)
+		return false
+	}
+	t.Logf("testPath(%s): %v", path, time.Since(t0))
+	return true
+}
+
+const maxTime = 30 * time.Second
+
+func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
+	dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
+	list, err := ioutil.ReadDir(dirname)
+	if err != nil {
+		t.Fatalf("testDir(%s): %s", dirname, err)
+	}
+	for _, f := range list {
+		if time.Now().After(endTime) {
+			t.Log("testing time used up")
+			return
+		}
+		switch {
+		case !f.IsDir():
+			// try extensions
+			for _, ext := range pkgExts {
+				if strings.HasSuffix(f.Name(), ext) {
+					name := f.Name()[0 : len(f.Name())-len(ext)] // remove extension
+					if testPath(t, filepath.Join(dir, name)) {
+						nimports++
+					}
+				}
+			}
+		case f.IsDir():
+			nimports += testDir(t, filepath.Join(dir, f.Name()), endTime)
+		}
+	}
+	return
+}
+
+func TestImport(t *testing.T) {
+	// This package does not handle gccgo export data.
+	if runtime.Compiler == "gccgo" {
+		return
+	}
+
+	// On cross-compile builds, the path will not exist.
+	// Need to use GOHOSTOS, which is not available.
+	if _, err := os.Stat(gcPath); err != nil {
+		t.Skipf("skipping test: %v", err)
+	}
+
+	if outFn := compile(t, "testdata", "exports.go"); outFn != "" {
+		defer os.Remove(outFn)
+	}
+
+	nimports := 0
+	if testPath(t, "./testdata/exports") {
+		nimports++
+	}
+	nimports += testDir(t, "", time.Now().Add(maxTime)) // installed packages
+	t.Logf("tested %d imports", nimports)
+}
+
+var importedObjectTests = []struct {
+	name string
+	want string
+}{
+	{"unsafe.Pointer", "type Pointer unsafe.Pointer"},
+	{"math.Pi", "const Pi untyped float"},
+	{"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"},
+	{"io.ReadWriter", "type ReadWriter interface{Read(p []byte) (n int, err error); Write(p []byte) (n int, err error)}"},
+	{"math.Sin", "func Sin(x float64) float64"},
+	// TODO(gri) add more tests
+}
+
+func TestImportedTypes(t *testing.T) {
+	// This package does not handle gccgo export data.
+	if runtime.Compiler == "gccgo" {
+		return
+	}
+	for _, test := range importedObjectTests {
+		s := strings.Split(test.name, ".")
+		if len(s) != 2 {
+			t.Fatal("inconsistent test data")
+		}
+		importPath := s[0]
+		objName := s[1]
+
+		pkg, err := Import(imports, importPath)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		obj := pkg.Scope().Lookup(objName)
+		if obj == nil {
+			t.Errorf("%s: object not found", test.name)
+			continue
+		}
+
+		got := types.ObjectString(pkg, obj)
+		if got != test.want {
+			t.Errorf("%s: got %q; want %q", test.name, got, test.want)
+		}
+	}
+}
+
+func TestIssue5815(t *testing.T) {
+	// This package does not handle gccgo export data.
+	if runtime.Compiler == "gccgo" {
+		return
+	}
+
+	pkg, err := Import(make(map[string]*types.Package), "strings")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	scope := pkg.Scope()
+	for _, name := range scope.Names() {
+		obj := scope.Lookup(name)
+		if obj.Pkg() == nil {
+			t.Errorf("no pkg for %s", obj)
+		}
+		if tname, _ := obj.(*types.TypeName); tname != nil {
+			named := tname.Type().(*types.Named)
+			for i := 0; i < named.NumMethods(); i++ {
+				m := named.Method(i)
+				if m.Pkg() == nil {
+					t.Errorf("no pkg for %s", m)
+				}
+			}
+		}
+	}
+}
+
+// Smoke test to ensure that imported methods get the correct package.
+func TestCorrectMethodPackage(t *testing.T) {
+	// This package does not handle gccgo export data.
+	if runtime.Compiler == "gccgo" {
+		return
+	}
+
+	imports := make(map[string]*types.Package)
+	_, err := Import(imports, "net/http")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	mutex := imports["sync"].Scope().Lookup("Mutex").(*types.TypeName).Type()
+	mset := types.NewMethodSet(types.NewPointer(mutex)) // methods of *sync.Mutex
+	sel := mset.Lookup(nil, "Lock")
+	lock := sel.Obj().(*types.Func)
+	if got, want := lock.Pkg().Path(), "sync"; got != want {
+		t.Errorf("got package path %q; want %q", got, want)
+	}
+}
diff --git a/third_party/go.tools/go/gcimporter/testdata/exports.go b/third_party/go.tools/go/gcimporter/testdata/exports.go
new file mode 100644
index 0000000..8ee28b0
--- /dev/null
+++ b/third_party/go.tools/go/gcimporter/testdata/exports.go
@@ -0,0 +1,89 @@
+// 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.
+
+// This file is used to generate an object file which
+// serves as test file for gcimporter_test.go.
+
+package exports
+
+import (
+	"go/ast"
+)
+
+// Issue 3682: Correctly read dotted identifiers from export data.
+const init1 = 0
+
+func init() {}
+
+const (
+	C0 int = 0
+	C1     = 3.14159265
+	C2     = 2.718281828i
+	C3     = -123.456e-789
+	C4     = +123.456E+789
+	C5     = 1234i
+	C6     = "foo\n"
+	C7     = `bar\n`
+)
+
+type (
+	T1  int
+	T2  [10]int
+	T3  []int
+	T4  *int
+	T5  chan int
+	T6a chan<- int
+	T6b chan (<-chan int)
+	T6c chan<- (chan int)
+	T7  <-chan *ast.File
+	T8  struct{}
+	T9  struct {
+		a    int
+		b, c float32
+		d    []string `go:"tag"`
+	}
+	T10 struct {
+		T8
+		T9
+		_ *T10
+	}
+	T11 map[int]string
+	T12 interface{}
+	T13 interface {
+		m1()
+		m2(int) float32
+	}
+	T14 interface {
+		T12
+		T13
+		m3(x ...struct{}) []T9
+	}
+	T15 func()
+	T16 func(int)
+	T17 func(x int)
+	T18 func() float32
+	T19 func() (x float32)
+	T20 func(...interface{})
+	T21 struct{ next *T21 }
+	T22 struct{ link *T23 }
+	T23 struct{ link *T22 }
+	T24 *T24
+	T25 *T26
+	T26 *T27
+	T27 *T25
+	T28 func(T28) T28
+)
+
+var (
+	V0 int
+	V1 = -991.0
+)
+
+func F1()         {}
+func F2(x int)    {}
+func F3() int     { return 0 }
+func F4() float32 { return 0 }
+func F5(a, b, c int, u, v, w struct{ x, y T1 }, more ...interface{}) (p, q, r chan<- T10)
+
+func (p *T1) M1()
diff --git a/third_party/go.tools/go/importer/export.go b/third_party/go.tools/go/importer/export.go
new file mode 100644
index 0000000..aae4480
--- /dev/null
+++ b/third_party/go.tools/go/importer/export.go
@@ -0,0 +1,462 @@
+// Copyright 2013 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 importer
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"go/ast"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// debugging support
+const (
+	debug = false // emit debugging data
+	trace = false // print emitted data
+)
+
+// format returns a byte indicating the low-level encoding/decoding format
+// (debug vs product).
+func format() byte {
+	if debug {
+		return 'd'
+	}
+	return 'p'
+}
+
+// ExportData serializes the interface (exported package objects)
+// of package pkg and returns the corresponding data. The export
+// format is described elsewhere (TODO).
+func ExportData(pkg *types.Package) []byte {
+	p := exporter{
+		data:     append([]byte(magic), format()),
+		pkgIndex: make(map[*types.Package]int),
+		typIndex: make(map[types.Type]int),
+	}
+
+	// populate typIndex with predeclared types
+	for _, t := range predeclared {
+		p.typIndex[t] = len(p.typIndex)
+	}
+
+	if trace {
+		p.tracef("export %s\n", pkg.Name())
+		defer p.tracef("\n")
+	}
+
+	p.string(version)
+
+	p.pkg(pkg)
+
+	// collect exported objects from package scope
+	var list []types.Object
+	scope := pkg.Scope()
+	for _, name := range scope.Names() {
+		if exported(name) {
+			list = append(list, scope.Lookup(name))
+		}
+	}
+
+	// write objects
+	p.int(len(list))
+	for _, obj := range list {
+		p.obj(obj)
+	}
+
+	return p.data
+}
+
+type exporter struct {
+	data     []byte
+	pkgIndex map[*types.Package]int
+	typIndex map[types.Type]int
+
+	// tracing support
+	indent string
+}
+
+func (p *exporter) pkg(pkg *types.Package) {
+	if trace {
+		p.tracef("package { ")
+		defer p.tracef("} ")
+	}
+
+	if pkg == nil {
+		panic("unexpected nil pkg")
+	}
+
+	// if the package was seen before, write its index (>= 0)
+	if i, ok := p.pkgIndex[pkg]; ok {
+		p.int(i)
+		return
+	}
+	p.pkgIndex[pkg] = len(p.pkgIndex)
+
+	// otherwise, write the package tag (< 0) and package data
+	p.int(packageTag)
+	p.string(pkg.Name())
+	p.string(pkg.Path())
+}
+
+func (p *exporter) obj(obj types.Object) {
+	if trace {
+		p.tracef("object %s {\n", obj.Name())
+		defer p.tracef("}\n")
+	}
+
+	switch obj := obj.(type) {
+	case *types.Const:
+		p.int(constTag)
+		p.string(obj.Name())
+		p.typ(obj.Type())
+		p.value(obj.Val())
+	case *types.TypeName:
+		p.int(typeTag)
+		// name is written by corresponding named type
+		p.typ(obj.Type().(*types.Named))
+	case *types.Var:
+		p.int(varTag)
+		p.string(obj.Name())
+		p.typ(obj.Type())
+	case *types.Func:
+		p.int(funcTag)
+		p.string(obj.Name())
+		p.typ(obj.Type())
+	default:
+		panic(fmt.Sprintf("unexpected object type %T", obj))
+	}
+}
+
+func (p *exporter) value(x exact.Value) {
+	if trace {
+		p.tracef("value { ")
+		defer p.tracef("} ")
+	}
+
+	switch kind := x.Kind(); kind {
+	case exact.Bool:
+		tag := falseTag
+		if exact.BoolVal(x) {
+			tag = trueTag
+		}
+		p.int(tag)
+	case exact.Int:
+		if i, ok := exact.Int64Val(x); ok {
+			p.int(int64Tag)
+			p.int64(i)
+			return
+		}
+		p.int(floatTag)
+		p.float(x)
+	case exact.Float:
+		p.int(fractionTag)
+		p.fraction(x)
+	case exact.Complex:
+		p.int(complexTag)
+		p.fraction(exact.Real(x))
+		p.fraction(exact.Imag(x))
+	case exact.String:
+		p.int(stringTag)
+		p.string(exact.StringVal(x))
+	default:
+		panic(fmt.Sprintf("unexpected value kind %d", kind))
+	}
+}
+
+func (p *exporter) float(x exact.Value) {
+	sign := exact.Sign(x)
+	p.int(sign)
+	if sign == 0 {
+		return
+	}
+
+	p.ufloat(x)
+}
+
+func (p *exporter) fraction(x exact.Value) {
+	sign := exact.Sign(x)
+	p.int(sign)
+	if sign == 0 {
+		return
+	}
+
+	p.ufloat(exact.Num(x))
+	p.ufloat(exact.Denom(x))
+}
+
+// ufloat writes abs(x) in form of a binary exponent
+// followed by its mantissa bytes; x must be != 0.
+func (p *exporter) ufloat(x exact.Value) {
+	mant := exact.Bytes(x)
+	exp8 := -1
+	for i, b := range mant {
+		if b != 0 {
+			exp8 = i
+			break
+		}
+	}
+	if exp8 < 0 {
+		panic(fmt.Sprintf("%s has no mantissa", x))
+	}
+	p.int(exp8 * 8)
+	p.bytes(mant[exp8:])
+}
+
+func (p *exporter) typ(typ types.Type) {
+	if trace {
+		p.tracef("type {\n")
+		defer p.tracef("}\n")
+	}
+
+	// if the type was seen before, write its index (>= 0)
+	if i, ok := p.typIndex[typ]; ok {
+		p.int(i)
+		return
+	}
+	p.typIndex[typ] = len(p.typIndex)
+
+	// otherwise, write the type tag (< 0) and type data
+	switch t := typ.(type) {
+	case *types.Array:
+		p.int(arrayTag)
+		p.int64(t.Len())
+		p.typ(t.Elem())
+
+	case *types.Slice:
+		p.int(sliceTag)
+		p.typ(t.Elem())
+
+	case *types.Struct:
+		p.int(structTag)
+		n := t.NumFields()
+		p.int(n)
+		for i := 0; i < n; i++ {
+			p.field(t.Field(i))
+			p.string(t.Tag(i))
+		}
+
+	case *types.Pointer:
+		p.int(pointerTag)
+		p.typ(t.Elem())
+
+	case *types.Signature:
+		p.int(signatureTag)
+		p.signature(t)
+
+	case *types.Interface:
+		p.int(interfaceTag)
+
+		// write embedded interfaces
+		m := t.NumEmbeddeds()
+		p.int(m)
+		for i := 0; i < m; i++ {
+			p.typ(t.Embedded(i))
+		}
+
+		// write methods
+		n := t.NumExplicitMethods()
+		p.int(n)
+		for i := 0; i < n; i++ {
+			m := t.ExplicitMethod(i)
+			p.qualifiedName(m.Pkg(), m.Name())
+			p.typ(m.Type())
+		}
+
+	case *types.Map:
+		p.int(mapTag)
+		p.typ(t.Key())
+		p.typ(t.Elem())
+
+	case *types.Chan:
+		p.int(chanTag)
+		p.int(int(t.Dir()))
+		p.typ(t.Elem())
+
+	case *types.Named:
+		p.int(namedTag)
+
+		// write type object
+		obj := t.Obj()
+		p.string(obj.Name())
+		p.pkg(obj.Pkg())
+
+		// write underlying type
+		p.typ(t.Underlying())
+
+		// write associated methods
+		n := t.NumMethods()
+		p.int(n)
+		for i := 0; i < n; i++ {
+			m := t.Method(i)
+			p.string(m.Name())
+			p.typ(m.Type())
+		}
+
+	default:
+		panic("unreachable")
+	}
+}
+
+func (p *exporter) field(f *types.Var) {
+	// anonymous fields have "" name
+	name := ""
+	if !f.Anonymous() {
+		name = f.Name()
+	}
+
+	// qualifiedName will always emit the field package for
+	// anonymous fields because "" is not an exported name.
+	p.qualifiedName(f.Pkg(), name)
+	p.typ(f.Type())
+}
+
+func (p *exporter) qualifiedName(pkg *types.Package, name string) {
+	p.string(name)
+	// exported names don't need package
+	if !exported(name) {
+		if pkg == nil {
+			panic(fmt.Sprintf("nil package for unexported qualified name %s", name))
+		}
+		p.pkg(pkg)
+	}
+}
+
+func (p *exporter) signature(sig *types.Signature) {
+	// We need the receiver information (T vs *T)
+	// for methods associated with named types.
+	// We do not record interface receiver types in the
+	// export data because 1) the importer can derive them
+	// from the interface type and 2) they create cycles
+	// in the type graph.
+	if recv := sig.Recv(); recv != nil {
+		if _, ok := recv.Type().Underlying().(*types.Interface); !ok {
+			// 1-element tuple
+			p.int(1)
+			p.param(recv)
+		} else {
+			// 0-element tuple
+			p.int(0)
+		}
+	} else {
+		// 0-element tuple
+		p.int(0)
+	}
+	p.tuple(sig.Params())
+	p.tuple(sig.Results())
+	if sig.Variadic() {
+		p.int(1)
+	} else {
+		p.int(0)
+	}
+}
+
+func (p *exporter) param(v *types.Var) {
+	p.string(v.Name())
+	p.typ(v.Type())
+}
+
+func (p *exporter) tuple(t *types.Tuple) {
+	n := t.Len()
+	p.int(n)
+	for i := 0; i < n; i++ {
+		p.param(t.At(i))
+	}
+}
+
+// ----------------------------------------------------------------------------
+// encoders
+
+func (p *exporter) string(s string) {
+	p.bytes([]byte(s)) // (could be inlined if extra allocation matters)
+}
+
+func (p *exporter) int(x int) {
+	p.int64(int64(x))
+}
+
+func (p *exporter) int64(x int64) {
+	if debug {
+		p.marker('i')
+	}
+
+	if trace {
+		p.tracef("%d ", x)
+	}
+
+	p.rawInt64(x)
+}
+
+func (p *exporter) bytes(b []byte) {
+	if debug {
+		p.marker('b')
+	}
+
+	if trace {
+		p.tracef("%q ", b)
+	}
+
+	p.rawInt64(int64(len(b)))
+	if len(b) > 0 {
+		p.data = append(p.data, b...)
+	}
+}
+
+// marker emits a marker byte and position information which makes
+// it easy for a reader to detect if it is "out of sync". Used for
+// debug format only.
+func (p *exporter) marker(m byte) {
+	if debug {
+		p.data = append(p.data, m)
+		p.rawInt64(int64(len(p.data)))
+	}
+}
+
+// rawInt64 should only be used by low-level encoders
+func (p *exporter) rawInt64(x int64) {
+	var tmp [binary.MaxVarintLen64]byte
+	n := binary.PutVarint(tmp[:], x)
+	p.data = append(p.data, tmp[:n]...)
+}
+
+// utility functions
+
+func (p *exporter) tracef(format string, args ...interface{}) {
+	// rewrite format string to take care of indentation
+	const indent = ".  "
+	if strings.IndexAny(format, "{}\n") >= 0 {
+		var buf bytes.Buffer
+		for i := 0; i < len(format); i++ {
+			// no need to deal with runes
+			ch := format[i]
+			switch ch {
+			case '{':
+				p.indent += indent
+			case '}':
+				p.indent = p.indent[:len(p.indent)-len(indent)]
+				if i+1 < len(format) && format[i+1] == '\n' {
+					buf.WriteByte('\n')
+					buf.WriteString(p.indent)
+					buf.WriteString("} ")
+					i++
+					continue
+				}
+			}
+			buf.WriteByte(ch)
+			if ch == '\n' {
+				buf.WriteString(p.indent)
+			}
+		}
+		format = buf.String()
+	}
+	fmt.Printf(format, args...)
+}
+
+func exported(name string) bool {
+	return ast.IsExported(name)
+}
diff --git a/third_party/go.tools/go/importer/import.go b/third_party/go.tools/go/importer/import.go
new file mode 100644
index 0000000..0372c9c
--- /dev/null
+++ b/third_party/go.tools/go/importer/import.go
@@ -0,0 +1,456 @@
+// Copyright 2013 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.
+
+// This implementation is loosely based on the algorithm described
+// in: "On the linearization of graphs and writing symbol files",
+// by R. Griesemer, Technical Report 156, ETH Zürich, 1991.
+
+// package importer implements an exporter and importer for Go export data.
+package importer
+
+import (
+	"encoding/binary"
+	"fmt"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// ImportData imports a package from the serialized package data
+// and returns the number of bytes consumed and a reference to the package.
+// If data is obviously malformed, an error is returned but in
+// general it is not recommended to call ImportData on untrusted
+// data.
+func ImportData(imports map[string]*types.Package, data []byte) (int, *types.Package, error) {
+	datalen := len(data)
+
+	// check magic string
+	var s string
+	if len(data) >= len(magic) {
+		s = string(data[:len(magic)])
+		data = data[len(magic):]
+	}
+	if s != magic {
+		return 0, nil, fmt.Errorf("incorrect magic string: got %q; want %q", s, magic)
+	}
+
+	// check low-level encoding format
+	var m byte = 'm' // missing format
+	if len(data) > 0 {
+		m = data[0]
+		data = data[1:]
+	}
+	if m != format() {
+		return 0, nil, fmt.Errorf("incorrect low-level encoding format: got %c; want %c", m, format())
+	}
+
+	p := importer{
+		data:    data,
+		datalen: datalen,
+		imports: imports,
+	}
+
+	// populate typList with predeclared types
+	for _, t := range predeclared {
+		p.typList = append(p.typList, t)
+	}
+
+	if v := p.string(); v != version {
+		return 0, nil, fmt.Errorf("unknown version: got %s; want %s", v, version)
+	}
+
+	pkg := p.pkg()
+	if debug && p.pkgList[0] != pkg {
+		panic("imported packaged not found in pkgList[0]")
+	}
+
+	// read objects
+	n := p.int()
+	for i := 0; i < n; i++ {
+		p.obj(pkg)
+	}
+
+	// complete interfaces
+	for _, typ := range p.typList {
+		if it, ok := typ.(*types.Interface); ok {
+			it.Complete()
+		}
+	}
+
+	// package was imported completely and without errors
+	pkg.MarkComplete()
+
+	return p.consumed(), pkg, nil
+}
+
+type importer struct {
+	data    []byte
+	datalen int
+	imports map[string]*types.Package
+	pkgList []*types.Package
+	typList []types.Type
+}
+
+func (p *importer) pkg() *types.Package {
+	// if the package was seen before, i is its index (>= 0)
+	i := p.int()
+	if i >= 0 {
+		return p.pkgList[i]
+	}
+
+	// otherwise, i is the package tag (< 0)
+	if i != packageTag {
+		panic(fmt.Sprintf("unexpected package tag %d", i))
+	}
+
+	// read package data
+	name := p.string()
+	path := p.string()
+
+	// if the package was imported before, use that one; otherwise create a new one
+	pkg := p.imports[path]
+	if pkg == nil {
+		pkg = types.NewPackage(path, name)
+		p.imports[path] = pkg
+	}
+	p.pkgList = append(p.pkgList, pkg)
+
+	return pkg
+}
+
+func (p *importer) obj(pkg *types.Package) {
+	var obj types.Object
+	switch tag := p.int(); tag {
+	case constTag:
+		obj = types.NewConst(token.NoPos, pkg, p.string(), p.typ(), p.value())
+	case typeTag:
+		// type object is added to scope via respective named type
+		_ = p.typ().(*types.Named)
+		return
+	case varTag:
+		obj = types.NewVar(token.NoPos, pkg, p.string(), p.typ())
+	case funcTag:
+		obj = types.NewFunc(token.NoPos, pkg, p.string(), p.typ().(*types.Signature))
+	default:
+		panic(fmt.Sprintf("unexpected object tag %d", tag))
+	}
+
+	if alt := pkg.Scope().Insert(obj); alt != nil {
+		panic(fmt.Sprintf("%s already declared", alt.Name()))
+	}
+}
+
+func (p *importer) value() exact.Value {
+	switch kind := exact.Kind(p.int()); kind {
+	case falseTag:
+		return exact.MakeBool(false)
+	case trueTag:
+		return exact.MakeBool(true)
+	case int64Tag:
+		return exact.MakeInt64(p.int64())
+	case floatTag:
+		return p.float()
+	case fractionTag:
+		return p.fraction()
+	case complexTag:
+		re := p.fraction()
+		im := p.fraction()
+		return exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
+	case stringTag:
+		return exact.MakeString(p.string())
+	default:
+		panic(fmt.Sprintf("unexpected value kind %d", kind))
+	}
+}
+
+func (p *importer) float() exact.Value {
+	sign := p.int()
+	if sign == 0 {
+		return exact.MakeInt64(0)
+	}
+
+	x := p.ufloat()
+	if sign < 0 {
+		x = exact.UnaryOp(token.SUB, x, 0)
+	}
+	return x
+}
+
+func (p *importer) fraction() exact.Value {
+	sign := p.int()
+	if sign == 0 {
+		return exact.MakeInt64(0)
+	}
+
+	x := exact.BinaryOp(p.ufloat(), token.QUO, p.ufloat())
+	if sign < 0 {
+		x = exact.UnaryOp(token.SUB, x, 0)
+	}
+	return x
+}
+
+func (p *importer) ufloat() exact.Value {
+	exp := p.int()
+	x := exact.MakeFromBytes(p.bytes())
+	switch {
+	case exp < 0:
+		d := exact.Shift(exact.MakeInt64(1), token.SHL, uint(-exp))
+		x = exact.BinaryOp(x, token.QUO, d)
+	case exp > 0:
+		x = exact.Shift(x, token.SHL, uint(exp))
+	}
+	return x
+}
+
+func (p *importer) record(t types.Type) {
+	p.typList = append(p.typList, t)
+}
+
+func (p *importer) typ() types.Type {
+	// if the type was seen before, i is its index (>= 0)
+	i := p.int()
+	if i >= 0 {
+		return p.typList[i]
+	}
+
+	// otherwise, i is the type tag (< 0)
+	switch i {
+	case arrayTag:
+		t := new(types.Array)
+		p.record(t)
+
+		n := p.int64()
+		*t = *types.NewArray(p.typ(), n)
+		return t
+
+	case sliceTag:
+		t := new(types.Slice)
+		p.record(t)
+
+		*t = *types.NewSlice(p.typ())
+		return t
+
+	case structTag:
+		t := new(types.Struct)
+		p.record(t)
+
+		n := p.int()
+		fields := make([]*types.Var, n)
+		tags := make([]string, n)
+		for i := range fields {
+			fields[i] = p.field()
+			tags[i] = p.string()
+		}
+		*t = *types.NewStruct(fields, tags)
+		return t
+
+	case pointerTag:
+		t := new(types.Pointer)
+		p.record(t)
+
+		*t = *types.NewPointer(p.typ())
+		return t
+
+	case signatureTag:
+		t := new(types.Signature)
+		p.record(t)
+
+		*t = *p.signature()
+		return t
+
+	case interfaceTag:
+		// Create a dummy entry in the type list. This is safe because we
+		// cannot expect the interface type to appear in a cycle, as any
+		// such cycle must contain a named type which would have been
+		// first defined earlier.
+		n := len(p.typList)
+		p.record(nil)
+
+		// read embedded interfaces
+		embeddeds := make([]*types.Named, p.int())
+		for i := range embeddeds {
+			embeddeds[i] = p.typ().(*types.Named)
+		}
+
+		// read methods
+		methods := make([]*types.Func, p.int())
+		for i := range methods {
+			pkg, name := p.qualifiedName()
+			methods[i] = types.NewFunc(token.NoPos, pkg, name, p.typ().(*types.Signature))
+		}
+
+		t := types.NewInterface(methods, embeddeds)
+		p.typList[n] = t
+		return t
+
+	case mapTag:
+		t := new(types.Map)
+		p.record(t)
+
+		*t = *types.NewMap(p.typ(), p.typ())
+		return t
+
+	case chanTag:
+		t := new(types.Chan)
+		p.record(t)
+
+		*t = *types.NewChan(types.ChanDir(p.int()), p.typ())
+		return t
+
+	case namedTag:
+		// read type object
+		name := p.string()
+		pkg := p.pkg()
+		scope := pkg.Scope()
+		obj := scope.Lookup(name)
+
+		// if the object doesn't exist yet, create and insert it
+		if obj == nil {
+			obj = types.NewTypeName(token.NoPos, pkg, name, nil)
+			scope.Insert(obj)
+		}
+
+		// associate new named type with obj if it doesn't exist yet
+		t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
+
+		// but record the existing type, if any
+		t := obj.Type().(*types.Named)
+		p.record(t)
+
+		// read underlying type
+		t0.SetUnderlying(p.typ())
+
+		// read associated methods
+		for i, n := 0, p.int(); i < n; i++ {
+			t0.AddMethod(types.NewFunc(token.NoPos, pkg, p.string(), p.typ().(*types.Signature)))
+		}
+
+		return t
+
+	default:
+		panic(fmt.Sprintf("unexpected type tag %d", i))
+	}
+}
+
+func deref(typ types.Type) types.Type {
+	if p, _ := typ.(*types.Pointer); p != nil {
+		return p.Elem()
+	}
+	return typ
+}
+
+func (p *importer) field() *types.Var {
+	pkg, name := p.qualifiedName()
+	typ := p.typ()
+
+	anonymous := false
+	if name == "" {
+		// anonymous field - typ must be T or *T and T must be a type name
+		switch typ := deref(typ).(type) {
+		case *types.Basic: // basic types are named types
+			pkg = nil
+			name = typ.Name()
+		case *types.Named:
+			obj := typ.Obj()
+			name = obj.Name()
+			// correct the field package for anonymous fields
+			if exported(name) {
+				pkg = p.pkgList[0]
+			}
+		default:
+			panic("anonymous field expected")
+		}
+		anonymous = true
+	}
+
+	return types.NewField(token.NoPos, pkg, name, typ, anonymous)
+}
+
+func (p *importer) qualifiedName() (*types.Package, string) {
+	name := p.string()
+	pkg := p.pkgList[0] // exported names assume current package
+	if !exported(name) {
+		pkg = p.pkg()
+	}
+	return pkg, name
+}
+
+func (p *importer) signature() *types.Signature {
+	var recv *types.Var
+	if p.int() != 0 {
+		recv = p.param()
+	}
+	return types.NewSignature(nil, recv, p.tuple(), p.tuple(), p.int() != 0)
+}
+
+func (p *importer) param() *types.Var {
+	return types.NewVar(token.NoPos, nil, p.string(), p.typ())
+}
+
+func (p *importer) tuple() *types.Tuple {
+	vars := make([]*types.Var, p.int())
+	for i := range vars {
+		vars[i] = p.param()
+	}
+	return types.NewTuple(vars...)
+}
+
+// ----------------------------------------------------------------------------
+// decoders
+
+func (p *importer) string() string {
+	return string(p.bytes())
+}
+
+func (p *importer) int() int {
+	return int(p.int64())
+}
+
+func (p *importer) int64() int64 {
+	if debug {
+		p.marker('i')
+	}
+
+	return p.rawInt64()
+}
+
+// Note: bytes() returns the respective byte slice w/o copy.
+func (p *importer) bytes() []byte {
+	if debug {
+		p.marker('b')
+	}
+
+	var b []byte
+	if n := int(p.rawInt64()); n > 0 {
+		b = p.data[:n]
+		p.data = p.data[n:]
+	}
+	return b
+}
+
+func (p *importer) marker(want byte) {
+	if debug {
+		if got := p.data[0]; got != want {
+			panic(fmt.Sprintf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.consumed()))
+		}
+		p.data = p.data[1:]
+
+		pos := p.consumed()
+		if n := int(p.rawInt64()); n != pos {
+			panic(fmt.Sprintf("incorrect position: got %d; want %d", n, pos))
+		}
+	}
+}
+
+// rawInt64 should only be used by low-level decoders
+func (p *importer) rawInt64() int64 {
+	i, n := binary.Varint(p.data)
+	p.data = p.data[n:]
+	return i
+}
+
+func (p *importer) consumed() int {
+	return p.datalen - len(p.data)
+}
diff --git a/third_party/go.tools/go/importer/import_test.go b/third_party/go.tools/go/importer/import_test.go
new file mode 100644
index 0000000..66ba07e
--- /dev/null
+++ b/third_party/go.tools/go/importer/import_test.go
@@ -0,0 +1,382 @@
+// Copyright 2013 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 importer
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strconv"
+	"testing"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var fset = token.NewFileSet()
+
+var tests = []string{
+	`package p`,
+
+	// consts
+	`package p; const X = true`,
+	`package p; const X, y, Z = true, false, 0 != 0`,
+	`package p; const ( A float32 = 1<<iota; B; C; D)`,
+	`package p; const X = "foo"`,
+	`package p; const X string = "foo"`,
+	`package p; const X = 0`,
+	`package p; const X = -42`,
+	`package p; const X = 3.14159265`,
+	`package p; const X = -1e-10`,
+	`package p; const X = 1.2 + 2.3i`,
+	`package p; const X = -1i`,
+	`package p; import "math"; const Pi = math.Pi`,
+	`package p; import m "math"; const Pi = m.Pi`,
+
+	// types
+	`package p; type T int`,
+	`package p; type T [10]int`,
+	`package p; type T []int`,
+	`package p; type T struct{}`,
+	`package p; type T struct{x int}`,
+	`package p; type T *int`,
+	`package p; type T func()`,
+	`package p; type T *T`,
+	`package p; type T interface{}`,
+	`package p; type T interface{ foo() }`,
+	`package p; type T interface{ m() T }`,
+	// TODO(gri) disabled for now - import/export works but
+	// types.Type.String() used in the test cannot handle cases
+	// like this yet
+	// `package p; type T interface{ m() interface{T} }`,
+	`package p; type T map[string]bool`,
+	`package p; type T chan int`,
+	`package p; type T <-chan complex64`,
+	`package p; type T chan<- map[int]string`,
+	// test case for issue 8177
+	`package p; type T1 interface { F(T2) }; type T2 interface { T1 }`,
+
+	// vars
+	`package p; var X int`,
+	`package p; var X, Y, Z struct{f int "tag"}`,
+
+	// funcs
+	`package p; func F()`,
+	`package p; func F(x int, y struct{}) bool`,
+	`package p; type T int; func (*T) F(x int, y struct{}) T`,
+
+	// selected special cases
+	`package p; type T int`,
+	`package p; type T uint8`,
+	`package p; type T byte`,
+	`package p; type T error`,
+	`package p; import "net/http"; type T http.Client`,
+	`package p; import "net/http"; type ( T1 http.Client; T2 struct { http.Client } )`,
+	`package p; import "unsafe"; type ( T1 unsafe.Pointer; T2 unsafe.Pointer )`,
+	`package p; import "unsafe"; type T struct { p unsafe.Pointer }`,
+}
+
+func TestImportSrc(t *testing.T) {
+	for _, src := range tests {
+		pkg, err := pkgForSource(src)
+		if err != nil {
+			t.Errorf("typecheck failed: %s", err)
+			continue
+		}
+		testExportImport(t, pkg, "")
+	}
+}
+
+func TestImportStdLib(t *testing.T) {
+	start := time.Now()
+
+	libs, err := stdLibs()
+	if err != nil {
+		t.Fatalf("could not compute list of std libraries: %s", err)
+	}
+	if len(libs) < 100 {
+		t.Fatalf("only %d std libraries found - something's not right", len(libs))
+	}
+
+	// make sure printed go/types types and gc-imported types
+	// can be compared reasonably well
+	types.GcCompatibilityMode = true
+
+	var totSize, totGcSize int
+	for _, lib := range libs {
+		// limit run time for short tests
+		if testing.Short() && time.Since(start) >= 750*time.Millisecond {
+			return
+		}
+
+		pkg, err := pkgForPath(lib)
+		switch err := err.(type) {
+		case nil:
+			// ok
+		case *build.NoGoError:
+			// no Go files - ignore
+			continue
+		default:
+			t.Errorf("typecheck failed: %s", err)
+			continue
+		}
+
+		size, gcsize := testExportImport(t, pkg, lib)
+		if gcsize == 0 {
+			// if gc import didn't happen, assume same size
+			// (and avoid division by zero below)
+			gcsize = size
+		}
+
+		if testing.Verbose() {
+			fmt.Printf("%s\t%d\t%d\t%d%%\n", lib, size, gcsize, int(float64(size)*100/float64(gcsize)))
+		}
+		totSize += size
+		totGcSize += gcsize
+	}
+
+	if testing.Verbose() {
+		fmt.Printf("\n%d\t%d\t%d%%\n", totSize, totGcSize, int(float64(totSize)*100/float64(totGcSize)))
+	}
+
+	types.GcCompatibilityMode = false
+}
+
+func testExportImport(t *testing.T, pkg0 *types.Package, path string) (size, gcsize int) {
+	data := ExportData(pkg0)
+	size = len(data)
+
+	imports := make(map[string]*types.Package)
+	n, pkg1, err := ImportData(imports, data)
+	if err != nil {
+		t.Errorf("package %s: import failed: %s", pkg0.Name(), err)
+		return
+	}
+	if n != size {
+		t.Errorf("package %s: not all input data consumed", pkg0.Name())
+		return
+	}
+
+	s0 := pkgString(pkg0)
+	s1 := pkgString(pkg1)
+	if s1 != s0 {
+		t.Errorf("package %s: \nimport got:\n%s\nwant:\n%s\n", pkg0.Name(), s1, s0)
+	}
+
+	// If we have a standard library, compare also against the gcimported package.
+	if path == "" {
+		return // not std library
+	}
+
+	gcdata, err := gcExportData(path)
+	if err != nil {
+		if pkg0.Name() == "main" {
+			return // no export data present for main package
+		}
+		t.Errorf("package %s: couldn't get export data: %s", pkg0.Name(), err)
+	}
+	gcsize = len(gcdata)
+
+	imports = make(map[string]*types.Package)
+	pkg2, err := gcImportData(imports, gcdata, path)
+	if err != nil {
+		t.Errorf("package %s: gcimport failed: %s", pkg0.Name(), err)
+		return
+	}
+
+	s2 := pkgString(pkg2)
+	if s2 != s0 {
+		t.Errorf("package %s: \ngcimport got:\n%s\nwant:\n%s\n", pkg0.Name(), s2, s0)
+	}
+
+	return
+}
+
+func pkgForSource(src string) (*types.Package, error) {
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		return nil, err
+	}
+	return typecheck("import-test", f)
+}
+
+func pkgForPath(path string) (*types.Package, error) {
+	// collect filenames
+	ctxt := build.Default
+	pkginfo, err := ctxt.Import(path, "", 0)
+	if err != nil {
+		return nil, err
+	}
+	filenames := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
+
+	// parse files
+	files := make([]*ast.File, len(filenames))
+	for i, filename := range filenames {
+		var err error
+		files[i], err = parser.ParseFile(fset, filepath.Join(pkginfo.Dir, filename), nil, 0)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return typecheck(path, files...)
+}
+
+var defaultConf = types.Config{
+	// we only care about exports and thus can ignore function bodies
+	IgnoreFuncBodies: true,
+	// work around C imports if possible
+	FakeImportC: true,
+	// strconv exports IntSize as a constant. The type-checker must
+	// use the same word size otherwise the result of the type-checker
+	// and gc imports is different. We don't care about alignment
+	// since none of the tests have exported constants depending
+	// on alignment (see also issue 8366).
+	Sizes: &types.StdSizes{WordSize: strconv.IntSize / 8, MaxAlign: 8},
+}
+
+func typecheck(path string, files ...*ast.File) (*types.Package, error) {
+	return defaultConf.Check(path, fset, files, nil)
+}
+
+// pkgString returns a string representation of a package's exported interface.
+func pkgString(pkg *types.Package) string {
+	var buf bytes.Buffer
+
+	fmt.Fprintf(&buf, "package %s\n", pkg.Name())
+
+	scope := pkg.Scope()
+	for _, name := range scope.Names() {
+		if exported(name) {
+			obj := scope.Lookup(name)
+			buf.WriteString(obj.String())
+
+			switch obj := obj.(type) {
+			case *types.Const:
+				// For now only print constant values if they are not float
+				// or complex. This permits comparing go/types results with
+				// gc-generated gcimported package interfaces.
+				info := obj.Type().Underlying().(*types.Basic).Info()
+				if info&types.IsFloat == 0 && info&types.IsComplex == 0 {
+					fmt.Fprintf(&buf, " = %s", obj.Val())
+				}
+
+			case *types.TypeName:
+				// Print associated methods.
+				// Basic types (e.g., unsafe.Pointer) have *types.Basic
+				// type rather than *types.Named; so we need to check.
+				if typ, _ := obj.Type().(*types.Named); typ != nil {
+					if n := typ.NumMethods(); n > 0 {
+						// Sort methods by name so that we get the
+						// same order independent of whether the
+						// methods got imported or coming directly
+						// for the source.
+						// TODO(gri) This should probably be done
+						// in go/types.
+						list := make([]*types.Func, n)
+						for i := 0; i < n; i++ {
+							list[i] = typ.Method(i)
+						}
+						sort.Sort(byName(list))
+
+						buf.WriteString("\nmethods (\n")
+						for _, m := range list {
+							fmt.Fprintf(&buf, "\t%s\n", m)
+						}
+						buf.WriteString(")")
+					}
+				}
+			}
+			buf.WriteByte('\n')
+		}
+	}
+
+	return buf.String()
+}
+
+var stdLibRoot = filepath.Join(runtime.GOROOT(), "src") + string(filepath.Separator)
+
+// The following std libraries are excluded from the stdLibs list.
+var excluded = map[string]bool{
+	"builtin": true, // contains type declarations with cycles
+	"unsafe":  true, // contains fake declarations
+}
+
+// stdLibs returns the list of standard library package paths.
+func stdLibs() (list []string, err error) {
+	err = filepath.Walk(stdLibRoot, func(path string, info os.FileInfo, err error) error {
+		if err == nil && info.IsDir() {
+			// testdata directories don't contain importable libraries
+			if info.Name() == "testdata" {
+				return filepath.SkipDir
+			}
+			pkgPath := path[len(stdLibRoot):] // remove stdLibRoot
+			if len(pkgPath) > 0 && !excluded[pkgPath] {
+				list = append(list, pkgPath)
+			}
+		}
+		return nil
+	})
+	return
+}
+
+type byName []*types.Func
+
+func (a byName) Len() int           { return len(a) }
+func (a byName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a byName) Less(i, j int) bool { return a[i].Name() < a[j].Name() }
+
+// gcExportData returns the gc-generated export data for the given path.
+// It is based on a trimmed-down version of gcimporter.Import which does
+// not do the actual import, does not handle package unsafe, and assumes
+// that path is a correct standard library package path (no canonicalization,
+// or handling of local import paths).
+func gcExportData(path string) ([]byte, error) {
+	filename, id := gcimporter.FindPkg(path, "")
+	if filename == "" {
+		return nil, fmt.Errorf("can't find import: %s", path)
+	}
+	if id != path {
+		panic("path should be canonicalized")
+	}
+
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	buf := bufio.NewReader(f)
+	if err = gcimporter.FindExportData(buf); err != nil {
+		return nil, err
+	}
+
+	var data []byte
+	for {
+		line, err := buf.ReadBytes('\n')
+		if err != nil {
+			return nil, err
+		}
+		data = append(data, line...)
+		// export data ends in "$$\n"
+		if len(line) == 3 && line[0] == '$' && line[1] == '$' {
+			return data, nil
+		}
+	}
+}
+
+func gcImportData(imports map[string]*types.Package, data []byte, path string) (*types.Package, error) {
+	filename := fmt.Sprintf("<filename for %s>", path) // so we have a decent error message if necessary
+	return gcimporter.ImportData(imports, filename, path, bufio.NewReader(bytes.NewBuffer(data)))
+}
diff --git a/third_party/go.tools/go/importer/predefined.go b/third_party/go.tools/go/importer/predefined.go
new file mode 100644
index 0000000..9ce1334
--- /dev/null
+++ b/third_party/go.tools/go/importer/predefined.go
@@ -0,0 +1,83 @@
+// Copyright 2014 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 importer
+
+import "llvm.org/llgo/third_party/go.tools/go/types"
+
+const (
+	magic   = "\n$$ exports $$\n"
+	version = "v0"
+)
+
+// Tags. Must be < 0.
+const (
+	// Packages
+	packageTag = -(iota + 1)
+
+	// Objects
+	constTag
+	typeTag
+	varTag
+	funcTag
+
+	// Types
+	arrayTag
+	sliceTag
+	structTag
+	pointerTag
+	signatureTag
+	interfaceTag
+	mapTag
+	chanTag
+	namedTag
+
+	// Values
+	falseTag
+	trueTag
+	int64Tag
+	floatTag
+	fractionTag
+	complexTag
+	stringTag
+)
+
+var predeclared = []types.Type{
+	// basic types
+	types.Typ[types.Bool],
+	types.Typ[types.Int],
+	types.Typ[types.Int8],
+	types.Typ[types.Int16],
+	types.Typ[types.Int32],
+	types.Typ[types.Int64],
+	types.Typ[types.Uint],
+	types.Typ[types.Uint8],
+	types.Typ[types.Uint16],
+	types.Typ[types.Uint32],
+	types.Typ[types.Uint64],
+	types.Typ[types.Uintptr],
+	types.Typ[types.Float32],
+	types.Typ[types.Float64],
+	types.Typ[types.Complex64],
+	types.Typ[types.Complex128],
+	types.Typ[types.String],
+
+	// untyped types
+	types.Typ[types.UntypedBool],
+	types.Typ[types.UntypedInt],
+	types.Typ[types.UntypedRune],
+	types.Typ[types.UntypedFloat],
+	types.Typ[types.UntypedComplex],
+	types.Typ[types.UntypedString],
+	types.Typ[types.UntypedNil],
+
+	// package unsafe
+	types.Typ[types.UnsafePointer],
+
+	// aliases
+	types.UniverseByte,
+	types.UniverseRune,
+
+	types.Universe.Lookup("error").Type(),
+}
diff --git a/third_party/go.tools/go/loader/cgo.go b/third_party/go.tools/go/loader/cgo.go
new file mode 100644
index 0000000..299e725
--- /dev/null
+++ b/third_party/go.tools/go/loader/cgo.go
@@ -0,0 +1,199 @@
+package loader
+
+// This file handles cgo preprocessing of files containing `import "C"`.
+//
+// DESIGN
+//
+// The approach taken is to run the cgo processor on the package's
+// CgoFiles and parse the output, faking the filenames of the
+// resulting ASTs so that the synthetic file containing the C types is
+// called "C" (e.g. "~/go/src/net/C") and the preprocessed files
+// have their original names (e.g. "~/go/src/net/cgo_unix.go"),
+// not the names of the actual temporary files.
+//
+// The advantage of this approach is its fidelity to 'go build'.  The
+// downside is that the token.Position.Offset for each AST node is
+// incorrect, being an offset within the temporary file.  Line numbers
+// should still be correct because of the //line comments.
+//
+// The logic of this file is mostly plundered from the 'go build'
+// tool, which also invokes the cgo preprocessor.
+//
+//
+// REJECTED ALTERNATIVE
+//
+// An alternative approach that we explored is to extend go/types'
+// Importer mechanism to provide the identity of the importing package
+// so that each time `import "C"` appears it resolves to a different
+// synthetic package containing just the objects needed in that case.
+// The loader would invoke cgo but parse only the cgo_types.go file
+// defining the package-level objects, discarding the other files
+// resulting from preprocessing.
+//
+// The benefit of this approach would have been that source-level
+// syntax information would correspond exactly to the original cgo
+// file, with no preprocessing involved, making source tools like
+// godoc, oracle, and eg happy.  However, the approach was rejected
+// due to the additional complexity it would impose on go/types.  (It
+// made for a beautiful demo, though.)
+//
+// cgo files, despite their *.go extension, are not legal Go source
+// files per the specification since they may refer to unexported
+// members of package "C" such as C.int.  Also, a function such as
+// C.getpwent has in effect two types, one matching its C type and one
+// which additionally returns (errno C.int).  The cgo preprocessor
+// uses name mangling to distinguish these two functions in the
+// processed code, but go/types would need to duplicate this logic in
+// its handling of function calls, analogous to the treatment of map
+// lookups in which y=m[k] and y,ok=m[k] are both legal.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"strings"
+)
+
+// processCgoFiles invokes the cgo preprocessor on bp.CgoFiles, parses
+// the output and returns the resulting ASTs.
+//
+func processCgoFiles(bp *build.Package, fset *token.FileSet, DisplayPath func(path string) string, mode parser.Mode) ([]*ast.File, error) {
+	tmpdir, err := ioutil.TempDir("", strings.Replace(bp.ImportPath, "/", "_", -1)+"_C")
+	if err != nil {
+		return nil, err
+	}
+	defer os.RemoveAll(tmpdir)
+
+	pkgdir := bp.Dir
+	if DisplayPath != nil {
+		pkgdir = DisplayPath(pkgdir)
+	}
+
+	cgoFiles, cgoDisplayFiles, err := runCgo(bp, pkgdir, tmpdir)
+	if err != nil {
+		return nil, err
+	}
+	var files []*ast.File
+	for i := range cgoFiles {
+		rd, err := os.Open(cgoFiles[i])
+		if err != nil {
+			return nil, err
+		}
+		defer rd.Close()
+		display := filepath.Join(bp.Dir, cgoDisplayFiles[i])
+		f, err := parser.ParseFile(fset, display, rd, mode)
+		if err != nil {
+			return nil, err
+		}
+		files = append(files, f)
+	}
+	return files, nil
+}
+
+var cgoRe = regexp.MustCompile(`[/\\:]`)
+
+// runCgo invokes the cgo preprocessor on bp.CgoFiles and returns two
+// lists of files: the resulting processed files (in temporary
+// directory tmpdir) and the corresponding names of the unprocessed files.
+//
+// runCgo is adapted from (*builder).cgo in
+// $GOROOT/src/cmd/go/build.go, but these features are unsupported:
+// pkg-config, Objective C, CGOPKGPATH, CGO_FLAGS.
+//
+func runCgo(bp *build.Package, pkgdir, tmpdir string) (files, displayFiles []string, err error) {
+	cgoCPPFLAGS, _, _, _ := cflags(bp, true)
+	_, cgoexeCFLAGS, _, _ := cflags(bp, false)
+
+	if len(bp.CgoPkgConfig) > 0 {
+		return nil, nil, fmt.Errorf("cgo pkg-config not supported")
+	}
+
+	// Allows including _cgo_export.h from .[ch] files in the package.
+	cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", tmpdir)
+
+	// _cgo_gotypes.go (displayed "C") contains the type definitions.
+	files = append(files, filepath.Join(tmpdir, "_cgo_gotypes.go"))
+	displayFiles = append(displayFiles, "C")
+	for _, fn := range bp.CgoFiles {
+		// "foo.cgo1.go" (displayed "foo.go") is the processed Go source.
+		f := cgoRe.ReplaceAllString(fn[:len(fn)-len("go")], "_")
+		files = append(files, filepath.Join(tmpdir, f+"cgo1.go"))
+		displayFiles = append(displayFiles, fn)
+	}
+
+	var cgoflags []string
+	if bp.Goroot && bp.ImportPath == "runtime/cgo" {
+		cgoflags = append(cgoflags, "-import_runtime_cgo=false")
+	}
+	if bp.Goroot && bp.ImportPath == "runtime/race" || bp.ImportPath == "runtime/cgo" {
+		cgoflags = append(cgoflags, "-import_syscall=false")
+	}
+
+	args := stringList(
+		"go", "tool", "cgo", "-objdir", tmpdir, cgoflags, "--",
+		cgoCPPFLAGS, cgoexeCFLAGS, bp.CgoFiles,
+	)
+	if false {
+		log.Printf("Running cgo for package %q: %s (dir=%s)", bp.ImportPath, args, pkgdir)
+	}
+	cmd := exec.Command(args[0], args[1:]...)
+	cmd.Dir = pkgdir
+	cmd.Stdout = os.Stderr
+	cmd.Stderr = os.Stderr
+	if err := cmd.Run(); err != nil {
+		return nil, nil, fmt.Errorf("cgo failed: %s: %s", args, err)
+	}
+
+	return files, displayFiles, nil
+}
+
+// -- unmodified from 'go build' ---------------------------------------
+
+// Return the flags to use when invoking the C or C++ compilers, or cgo.
+func cflags(p *build.Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) {
+	var defaults string
+	if def {
+		defaults = "-g -O2"
+	}
+
+	cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
+	cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
+	cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
+	ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
+	return
+}
+
+// envList returns the value of the given environment variable broken
+// into fields, using the default value when the variable is empty.
+func envList(key, def string) []string {
+	v := os.Getenv(key)
+	if v == "" {
+		v = def
+	}
+	return strings.Fields(v)
+}
+
+// stringList's arguments should be a sequence of string or []string values.
+// stringList flattens them into a single []string.
+func stringList(args ...interface{}) []string {
+	var x []string
+	for _, arg := range args {
+		switch arg := arg.(type) {
+		case []string:
+			x = append(x, arg...)
+		case string:
+			x = append(x, arg)
+		default:
+			panic("stringList: invalid argument")
+		}
+	}
+	return x
+}
diff --git a/third_party/go.tools/go/loader/loader.go b/third_party/go.tools/go/loader/loader.go
new file mode 100644
index 0000000..e439f7b
--- /dev/null
+++ b/third_party/go.tools/go/loader/loader.go
@@ -0,0 +1,856 @@
+// Copyright 2013 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 loader loads, parses and type-checks packages of Go code
+// plus their transitive closure, and retains both the ASTs and the
+// derived facts.
+//
+// THIS INTERFACE IS EXPERIMENTAL AND IS LIKELY TO CHANGE.
+//
+// The package defines two primary types: Config, which specifies a
+// set of initial packages to load and various other options; and
+// Program, which is the result of successfully loading the packages
+// specified by a configuration.
+//
+// The configuration can be set directly, but *Config provides various
+// convenience methods to simplify the common cases, each of which can
+// be called any number of times.  Finally, these are followed by a
+// call to Load() to actually load and type-check the program.
+//
+//      var conf loader.Config
+//
+//      // Use the command-line arguments to specify
+//      // a set of initial packages to load from source.
+//      // See FromArgsUsage for help.
+//      rest, err := conf.FromArgs(os.Args[1:], wantTests)
+//
+//      // Parse the specified files and create an ad-hoc package with path "foo".
+//      // All files must have the same 'package' declaration.
+//      err := conf.CreateFromFilenames("foo", "foo.go", "bar.go")
+//
+//      // Create an ad-hoc package with path "foo" from
+//      // the specified already-parsed files.
+//      // All ASTs must have the same 'package' declaration.
+//      err := conf.CreateFromFiles("foo", parsedFiles)
+//
+//      // Add "runtime" to the set of packages to be loaded.
+//      conf.Import("runtime")
+//
+//      // Adds "fmt" and "fmt_test" to the set of packages
+//      // to be loaded.  "fmt" will include *_test.go files.
+//      err := conf.ImportWithTests("fmt")
+//
+//      // Finally, load all the packages specified by the configuration.
+//      prog, err := conf.Load()
+//
+//
+// CONCEPTS AND TERMINOLOGY
+//
+// An AD-HOC package is one specified as a set of source files on the
+// command line.  In the simplest case, it may consist of a single file
+// such as $GOROOT/src/net/http/triv.go.
+//
+// EXTERNAL TEST packages are those comprised of a set of *_test.go
+// files all with the same 'package foo_test' declaration, all in the
+// same directory.  (go/build.Package calls these files XTestFiles.)
+//
+// An IMPORTABLE package is one that can be referred to by some import
+// spec.  The Path() of each importable package is unique within a
+// Program.
+//
+// Ad-hoc packages and external test packages are NON-IMPORTABLE.  The
+// Path() of an ad-hoc package is inferred from the package
+// declarations of its files and is therefore not a unique package key.
+// For example, Config.CreatePkgs may specify two initial ad-hoc
+// packages both called "main".
+//
+// An AUGMENTED package is an importable package P plus all the
+// *_test.go files with same 'package foo' declaration as P.
+// (go/build.Package calls these files TestFiles.)
+//
+// The INITIAL packages are those specified in the configuration.  A
+// DEPENDENCY is a package loaded to satisfy an import in an initial
+// package or another dependency.
+//
+package loader
+
+// 'go test', in-package test files, and import cycles
+// ---------------------------------------------------
+//
+// An external test package may depend upon members of the augmented
+// package that are not in the unaugmented package, such as functions
+// that expose internals.  (See bufio/export_test.go for an example.)
+// So, the loader must ensure that for each external test package
+// it loads, it also augments the corresponding non-test package.
+//
+// The import graph over n unaugmented packages must be acyclic; the
+// import graph over n-1 unaugmented packages plus one augmented
+// package must also be acyclic.  ('go test' relies on this.)  But the
+// import graph over n augmented packages may contain cycles.
+//
+// First, all the (unaugmented) non-test packages and their
+// dependencies are imported in the usual way; the loader reports an
+// error if it detects an import cycle.
+//
+// Then, each package P for which testing is desired is augmented by
+// the list P' of its in-package test files, by calling
+// (*types.Checker).Files.  This arrangement ensures that P' may
+// reference definitions within P, but P may not reference definitions
+// within P'.  Furthermore, P' may import any other package, including
+// ones that depend upon P, without an import cycle error.
+//
+// Consider two packages A and B, both of which have lists of
+// in-package test files we'll call A' and B', and which have the
+// following import graph edges:
+//    B  imports A
+//    B' imports A
+//    A' imports B
+// This last edge would be expected to create an error were it not
+// for the special type-checking discipline above.
+// Cycles of size greater than two are possible.  For example:
+//   compress/bzip2/bzip2_test.go (package bzip2)  imports "io/ioutil"
+//   io/ioutil/tempfile_test.go   (package ioutil) imports "regexp"
+//   regexp/exec_test.go          (package regexp) imports "compress/bzip2"
+
+// TODO(adonovan):
+// - (*Config).ParseFile is very handy, but feels like feature creep.
+//   (*Config).CreateFromFiles has a nasty precondition.
+// - s/path/importPath/g to avoid ambiguity with other meanings of
+//   "path": a file name, a colon-separated directory list.
+// - cache the calls to build.Import so we don't do it three times per
+//   test package.
+// - Thorough overhaul of package documentation.
+// - Certain errors (e.g. parse error in x_test.go files, or failure to
+//   import an initial package) still cause Load() to fail hard.
+//   Fix that.  (It's tricky because of the way x_test files are parsed
+//   eagerly.)
+
+import (
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+	"llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// Config specifies the configuration for a program to load.
+// The zero value for Config is a ready-to-use default configuration.
+type Config struct {
+	// Fset is the file set for the parser to use when loading the
+	// program.  If nil, it will be lazily initialized by any
+	// method of Config.
+	Fset *token.FileSet
+
+	// ParserMode specifies the mode to be used by the parser when
+	// loading source packages.
+	ParserMode parser.Mode
+
+	// TypeChecker contains options relating to the type checker.
+	//
+	// The supplied IgnoreFuncBodies is not used; the effective
+	// value comes from the TypeCheckFuncBodies func below.
+	//
+	// TypeChecker.Packages is lazily initialized during Load.
+	TypeChecker types.Config
+
+	// TypeCheckFuncBodies is a predicate over package import
+	// paths.  A package for which the predicate is false will
+	// have its package-level declarations type checked, but not
+	// its function bodies; this can be used to quickly load
+	// dependencies from source.  If nil, all func bodies are type
+	// checked.
+	TypeCheckFuncBodies func(string) bool
+
+	// SourceImports determines whether to satisfy dependencies by
+	// loading Go source code.
+	//
+	// If true, the entire program---the initial packages and
+	// their transitive closure of dependencies---will be loaded,
+	// parsed and type-checked.  This is required for
+	// whole-program analyses such as pointer analysis.
+	//
+	// If false, the TypeChecker.Import mechanism will be used
+	// instead.  Since that typically supplies only the types of
+	// package-level declarations and values of constants, but no
+	// code, it will not yield a whole program.  It is intended
+	// for analyses that perform modular analysis of a
+	// single package, e.g. traditional compilation.
+	//
+	// The initial packages (CreatePkgs and ImportPkgs) are always
+	// loaded from Go source, regardless of this flag's setting.
+	SourceImports bool
+
+	// If Build is non-nil, it is used to locate source packages.
+	// Otherwise &build.Default is used.
+	//
+	// By default, cgo is invoked to preprocess Go files that
+	// import the fake package "C".  This behaviour can be
+	// disabled by setting CGO_ENABLED=0 in the environment prior
+	// to startup, or by setting Build.CgoEnabled=false.
+	Build *build.Context
+
+	// If DisplayPath is non-nil, it is used to transform each
+	// file name obtained from Build.Import().  This can be used
+	// to prevent a virtualized build.Config's file names from
+	// leaking into the user interface.
+	DisplayPath func(path string) string
+
+	// If AllowErrors is true, Load will return a Program even
+	// if some of the its packages contained I/O, parser or type
+	// errors; such errors are accessible via PackageInfo.Errors.  If
+	// false, Load will fail if any package had an error.
+	AllowErrors bool
+
+	// CreatePkgs specifies a list of non-importable initial
+	// packages to create.  Each element specifies a list of
+	// parsed files to be type-checked into a new package, and a
+	// path for that package.  If the path is "", the package's
+	// name will be used instead.  The path needn't be globally
+	// unique.
+	//
+	// The resulting packages will appear in the corresponding
+	// elements of the Program.Created slice.
+	CreatePkgs []CreatePkg
+
+	// ImportPkgs specifies a set of initial packages to load from
+	// source.  The map keys are package import paths, used to
+	// locate the package relative to $GOROOT.  The corresponding
+	// values indicate whether to augment the package by *_test.go
+	// files in a second pass.
+	ImportPkgs map[string]bool
+}
+
+type CreatePkg struct {
+	Path  string
+	Files []*ast.File
+}
+
+// A Program is a Go program loaded from source or binary
+// as specified by a Config.
+type Program struct {
+	Fset *token.FileSet // the file set for this program
+
+	// Created[i] contains the initial package whose ASTs were
+	// supplied by Config.CreatePkgs[i].
+	Created []*PackageInfo
+
+	// Imported contains the initially imported packages,
+	// as specified by Config.ImportPkgs.
+	Imported map[string]*PackageInfo
+
+	// ImportMap is the canonical mapping of import paths to
+	// packages used by the type-checker (Config.TypeChecker.Packages).
+	// It contains all Imported initial packages, but not Created
+	// ones, and all imported dependencies.
+	ImportMap map[string]*types.Package
+
+	// AllPackages contains the PackageInfo of every package
+	// encountered by Load: all initial packages and all
+	// dependencies, including incomplete ones.
+	AllPackages map[*types.Package]*PackageInfo
+}
+
+// PackageInfo holds the ASTs and facts derived by the type-checker
+// for a single package.
+//
+// Not mutated once exposed via the API.
+//
+type PackageInfo struct {
+	Pkg                   *types.Package
+	Importable            bool        // true if 'import "Pkg.Path()"' would resolve to this
+	TransitivelyErrorFree bool        // true if Pkg and all its dependencies are free of errors
+	Files                 []*ast.File // syntax trees for the package's files
+	Errors                []error     // non-nil if the package had errors
+	types.Info                        // type-checker deductions.
+
+	checker   *types.Checker // transient type-checker state
+	errorFunc func(error)
+}
+
+func (info *PackageInfo) String() string { return info.Pkg.Path() }
+
+func (info *PackageInfo) appendError(err error) {
+	if info.errorFunc != nil {
+		info.errorFunc(err)
+	} else {
+		fmt.Fprintln(os.Stderr, err)
+	}
+	info.Errors = append(info.Errors, err)
+}
+
+func (conf *Config) fset() *token.FileSet {
+	if conf.Fset == nil {
+		conf.Fset = token.NewFileSet()
+	}
+	return conf.Fset
+}
+
+// ParseFile is a convenience function that invokes the parser using
+// the Config's FileSet, which is initialized if nil.
+//
+func (conf *Config) ParseFile(filename string, src interface{}) (*ast.File, error) {
+	// TODO(adonovan): use conf.build() etc like parseFiles does.
+	return parser.ParseFile(conf.fset(), filename, src, conf.ParserMode)
+}
+
+// FromArgsUsage is a partial usage message that applications calling
+// FromArgs may wish to include in their -help output.
+const FromArgsUsage = `
+<args> is a list of arguments denoting a set of initial packages.
+It may take one of two forms:
+
+1. A list of *.go source files.
+
+   All of the specified files are loaded, parsed and type-checked
+   as a single package.  All the files must belong to the same directory.
+
+2. A list of import paths, each denoting a package.
+
+   The package's directory is found relative to the $GOROOT and
+   $GOPATH using similar logic to 'go build', and the *.go files in
+   that directory are loaded, parsed and type-checked as a single
+   package.
+
+   In addition, all *_test.go files in the directory are then loaded
+   and parsed.  Those files whose package declaration equals that of
+   the non-*_test.go files are included in the primary package.  Test
+   files whose package declaration ends with "_test" are type-checked
+   as another package, the 'external' test package, so that a single
+   import path may denote two packages.  (Whether this behaviour is
+   enabled is tool-specific, and may depend on additional flags.)
+
+   Due to current limitations in the type-checker, only the first
+   import path of the command line will contribute any tests.
+
+A '--' argument terminates the list of packages.
+`
+
+// FromArgs interprets args as a set of initial packages to load from
+// source and updates the configuration.  It returns the list of
+// unconsumed arguments.
+//
+// It is intended for use in command-line interfaces that require a
+// set of initial packages to be specified; see FromArgsUsage message
+// for details.
+//
+func (conf *Config) FromArgs(args []string, xtest bool) (rest []string, err error) {
+	for i, arg := range args {
+		if arg == "--" {
+			rest = args[i+1:]
+			args = args[:i]
+			break // consume "--" and return the remaining args
+		}
+	}
+
+	if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
+		// Assume args is a list of a *.go files
+		// denoting a single ad-hoc package.
+		for _, arg := range args {
+			if !strings.HasSuffix(arg, ".go") {
+				return nil, fmt.Errorf("named files must be .go files: %s", arg)
+			}
+		}
+		err = conf.CreateFromFilenames("", args...)
+	} else {
+		// Assume args are directories each denoting a
+		// package and (perhaps) an external test, iff xtest.
+		for _, arg := range args {
+			if xtest {
+				err = conf.ImportWithTests(arg)
+				if err != nil {
+					break
+				}
+			} else {
+				conf.Import(arg)
+			}
+		}
+	}
+
+	return
+}
+
+// CreateFromFilenames is a convenience function that parses the
+// specified *.go files and adds a package entry for them to
+// conf.CreatePkgs.
+//
+// It fails if any file could not be loaded or parsed.
+//
+func (conf *Config) CreateFromFilenames(path string, filenames ...string) error {
+	files, errs := parseFiles(conf.fset(), conf.build(), nil, ".", filenames, conf.ParserMode)
+	if len(errs) > 0 {
+		return errs[0]
+	}
+	conf.CreateFromFiles(path, files...)
+	return nil
+}
+
+// CreateFromFiles is a convenience function that adds a CreatePkgs
+// entry to create package of the specified path and parsed files.
+//
+// Precondition: conf.Fset is non-nil and was the fileset used to parse
+// the files.  (e.g. the files came from conf.ParseFile().)
+//
+func (conf *Config) CreateFromFiles(path string, files ...*ast.File) {
+	if conf.Fset == nil {
+		panic("nil Fset")
+	}
+	conf.CreatePkgs = append(conf.CreatePkgs, CreatePkg{path, files})
+}
+
+// ImportWithTests is a convenience function that adds path to
+// ImportPkgs, the set of initial source packages located relative to
+// $GOPATH.  The package will be augmented by any *_test.go files in
+// its directory that contain a "package x" (not "package x_test")
+// declaration.
+//
+// In addition, if any *_test.go files contain a "package x_test"
+// declaration, an additional package comprising just those files will
+// be added to CreatePkgs.
+//
+func (conf *Config) ImportWithTests(path string) error {
+	if path == "unsafe" {
+		return nil // ignore; not a real package
+	}
+	conf.Import(path)
+
+	// Load the external test package.
+	bp, err := conf.findSourcePackage(path)
+	if err != nil {
+		return err // package not found
+	}
+	xtestFiles, errs := conf.parsePackageFiles(bp, 'x')
+	if len(errs) > 0 {
+		// TODO(adonovan): fix: parse errors in x_test.go files
+		// cause FromArgs() to fail completely.
+		return errs[0] // I/O or parse error
+	}
+	if len(xtestFiles) > 0 {
+		conf.CreateFromFiles(path+"_test", xtestFiles...)
+	}
+
+	// Mark the non-xtest package for augmentation with
+	// in-package *_test.go files when we import it below.
+	conf.ImportPkgs[path] = true
+	return nil
+}
+
+// Import is a convenience function that adds path to ImportPkgs, the
+// set of initial packages that will be imported from source.
+//
+func (conf *Config) Import(path string) {
+	if path == "unsafe" {
+		return // ignore; not a real package
+	}
+	if conf.ImportPkgs == nil {
+		conf.ImportPkgs = make(map[string]bool)
+	}
+	// Subtle: adds value 'false' unless value is already true.
+	conf.ImportPkgs[path] = conf.ImportPkgs[path] // unaugmented source package
+}
+
+// PathEnclosingInterval returns the PackageInfo and ast.Node that
+// contain source interval [start, end), and all the node's ancestors
+// up to the AST root.  It searches all ast.Files of all packages in prog.
+// exact is defined as for astutil.PathEnclosingInterval.
+//
+// The zero value is returned if not found.
+//
+func (prog *Program) PathEnclosingInterval(start, end token.Pos) (pkg *PackageInfo, path []ast.Node, exact bool) {
+	for _, info := range prog.AllPackages {
+		for _, f := range info.Files {
+			if !tokenFileContainsPos(prog.Fset.File(f.Pos()), start) {
+				continue
+			}
+			if path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil {
+				return info, path, exact
+			}
+		}
+	}
+	return nil, nil, false
+}
+
+// InitialPackages returns a new slice containing the set of initial
+// packages (Created + Imported) in unspecified order.
+//
+func (prog *Program) InitialPackages() []*PackageInfo {
+	infos := make([]*PackageInfo, 0, len(prog.Created)+len(prog.Imported))
+	infos = append(infos, prog.Created...)
+	for _, info := range prog.Imported {
+		infos = append(infos, info)
+	}
+	return infos
+}
+
+// ---------- Implementation ----------
+
+// importer holds the working state of the algorithm.
+type importer struct {
+	conf     *Config                // the client configuration
+	prog     *Program               // resulting program
+	imported map[string]*importInfo // all imported packages (incl. failures) by import path
+}
+
+// importInfo tracks the success or failure of a single import.
+type importInfo struct {
+	info *PackageInfo // results of typechecking (including errors)
+	err  error        // reason for failure to make a package
+}
+
+// Load creates the initial packages specified by conf.{Create,Import}Pkgs,
+// loading their dependencies packages as needed.
+//
+// On success, Load returns a Program containing a PackageInfo for
+// each package.  On failure, it returns an error.
+//
+// If AllowErrors is true, Load will return a Program even if some
+// packages contained I/O, parser or type errors, or if dependencies
+// were missing.  (Such errors are accessible via PackageInfo.Errors.  If
+// false, Load will fail if any package had an error.
+//
+// It is an error if no packages were loaded.
+//
+func (conf *Config) Load() (*Program, error) {
+	// Initialize by setting the conf's copy, so all copies of
+	// TypeChecker agree on the identity of the map.
+	if conf.TypeChecker.Packages == nil {
+		conf.TypeChecker.Packages = make(map[string]*types.Package)
+	}
+
+	// Create a simple default error handler for parse/type errors.
+	if conf.TypeChecker.Error == nil {
+		conf.TypeChecker.Error = func(e error) { fmt.Fprintln(os.Stderr, e) }
+	}
+
+	prog := &Program{
+		Fset:        conf.fset(),
+		Imported:    make(map[string]*PackageInfo),
+		ImportMap:   conf.TypeChecker.Packages,
+		AllPackages: make(map[*types.Package]*PackageInfo),
+	}
+
+	imp := importer{
+		conf:     conf,
+		prog:     prog,
+		imported: make(map[string]*importInfo),
+	}
+
+	for path := range conf.ImportPkgs {
+		info, err := imp.importPackage(path)
+		if err != nil {
+			return nil, err // failed to create package
+		}
+		prog.Imported[path] = info
+	}
+
+	// Now augment those packages that need it.
+	for path, augment := range conf.ImportPkgs {
+		if augment {
+			// Find and create the actual package.
+			bp, err := conf.findSourcePackage(path)
+			if err != nil {
+				// "Can't happen" because of previous loop.
+				return nil, err // package not found
+			}
+
+			info := imp.imported[path].info // must be non-nil, see above
+			files, errs := imp.conf.parsePackageFiles(bp, 't')
+			for _, err := range errs {
+				info.appendError(err)
+			}
+			typeCheckFiles(info, files...)
+		}
+	}
+
+	for _, create := range conf.CreatePkgs {
+		path := create.Path
+		if create.Path == "" && len(create.Files) > 0 {
+			path = create.Files[0].Name.Name
+		}
+		info := imp.newPackageInfo(path)
+		typeCheckFiles(info, create.Files...)
+		prog.Created = append(prog.Created, info)
+	}
+
+	if len(prog.Imported)+len(prog.Created) == 0 {
+		return nil, errors.New("no initial packages were specified")
+	}
+
+	// Create infos for indirectly imported packages.
+	// e.g. incomplete packages without syntax, loaded from export data.
+	for _, obj := range prog.ImportMap {
+		info := prog.AllPackages[obj]
+		if info == nil {
+			prog.AllPackages[obj] = &PackageInfo{Pkg: obj, Importable: true}
+		} else {
+			// finished
+			info.checker = nil
+			info.errorFunc = nil
+		}
+	}
+
+	if !conf.AllowErrors {
+		// Report errors in indirectly imported packages.
+		var errpkgs []string
+		for _, info := range prog.AllPackages {
+			if len(info.Errors) > 0 {
+				errpkgs = append(errpkgs, info.Pkg.Path())
+			}
+		}
+		if errpkgs != nil {
+			var more string
+			if len(errpkgs) > 3 {
+				more = fmt.Sprintf(" and %d more", len(errpkgs)-3)
+				errpkgs = errpkgs[:3]
+			}
+			return nil, fmt.Errorf("couldn't load packages due to errors: %s%s",
+				strings.Join(errpkgs, ", "), more)
+		}
+	}
+
+	markErrorFreePackages(prog.AllPackages)
+
+	return prog, nil
+}
+
+// markErrorFreePackages sets the TransitivelyErrorFree flag on all
+// applicable packages.
+func markErrorFreePackages(allPackages map[*types.Package]*PackageInfo) {
+	// Build the transpose of the import graph.
+	importedBy := make(map[*types.Package]map[*types.Package]bool)
+	for P := range allPackages {
+		for _, Q := range P.Imports() {
+			clients, ok := importedBy[Q]
+			if !ok {
+				clients = make(map[*types.Package]bool)
+				importedBy[Q] = clients
+			}
+			clients[P] = true
+		}
+	}
+
+	// Find all packages reachable from some error package.
+	reachable := make(map[*types.Package]bool)
+	var visit func(*types.Package)
+	visit = func(p *types.Package) {
+		if !reachable[p] {
+			reachable[p] = true
+			for q := range importedBy[p] {
+				visit(q)
+			}
+		}
+	}
+	for _, info := range allPackages {
+		if len(info.Errors) > 0 {
+			visit(info.Pkg)
+		}
+	}
+
+	// Mark the others as "transitively error-free".
+	for _, info := range allPackages {
+		if !reachable[info.Pkg] {
+			info.TransitivelyErrorFree = true
+		}
+	}
+}
+
+// build returns the effective build context.
+func (conf *Config) build() *build.Context {
+	if conf.Build != nil {
+		return conf.Build
+	}
+	return &build.Default
+}
+
+// findSourcePackage locates the specified (possibly empty) package
+// using go/build logic.  It returns an error if not found.
+//
+func (conf *Config) findSourcePackage(path string) (*build.Package, error) {
+	// Import(srcDir="") disables local imports, e.g. import "./foo".
+	bp, err := conf.build().Import(path, "", 0)
+	if _, ok := err.(*build.NoGoError); ok {
+		return bp, nil // empty directory is not an error
+	}
+	return bp, err
+}
+
+// parsePackageFiles enumerates the files belonging to package path,
+// then loads, parses and returns them, plus a list of I/O or parse
+// errors that were encountered.
+//
+// 'which' indicates which files to include:
+//    'g': include non-test *.go source files (GoFiles + processed CgoFiles)
+//    't': include in-package *_test.go source files (TestGoFiles)
+//    'x': include external *_test.go source files. (XTestGoFiles)
+//
+func (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.File, []error) {
+	var filenames []string
+	switch which {
+	case 'g':
+		filenames = bp.GoFiles
+	case 't':
+		filenames = bp.TestGoFiles
+	case 'x':
+		filenames = bp.XTestGoFiles
+	default:
+		panic(which)
+	}
+
+	files, errs := parseFiles(conf.fset(), conf.build(), conf.DisplayPath, bp.Dir, filenames, conf.ParserMode)
+
+	// Preprocess CgoFiles and parse the outputs (sequentially).
+	if which == 'g' && bp.CgoFiles != nil {
+		cgofiles, err := processCgoFiles(bp, conf.fset(), conf.DisplayPath, conf.ParserMode)
+		if err != nil {
+			errs = append(errs, err)
+		} else {
+			files = append(files, cgofiles...)
+		}
+	}
+
+	return files, errs
+}
+
+// doImport imports the package denoted by path.
+// It implements the types.Importer signature.
+//
+// imports is the type-checker's package canonicalization map.
+//
+// It returns an error if a package could not be created
+// (e.g. go/build or parse error), but type errors are reported via
+// the types.Config.Error callback (the first of which is also saved
+// in the package's PackageInfo).
+//
+// Idempotent.
+//
+func (imp *importer) doImport(imports map[string]*types.Package, path string) (*types.Package, error) {
+	// Package unsafe is handled specially, and has no PackageInfo.
+	if path == "unsafe" {
+		return types.Unsafe, nil
+	}
+
+	info, err := imp.importPackage(path)
+	if err != nil {
+		return nil, err
+	}
+
+	// Update the type checker's package map on success.
+	imports[path] = info.Pkg
+
+	return info.Pkg, nil
+}
+
+// importPackage imports the package with the given import path, plus
+// its dependencies.
+//
+// On success, it returns a PackageInfo, possibly containing errors.
+// importPackage returns an error if it couldn't even create the package.
+//
+// Precondition: path != "unsafe".
+//
+func (imp *importer) importPackage(path string) (*PackageInfo, error) {
+	ii, ok := imp.imported[path]
+	if !ok {
+		// In preorder, initialize the map entry to a cycle
+		// error in case importPackage(path) is called again
+		// before the import is completed.
+		ii = &importInfo{err: fmt.Errorf("import cycle in package %s", path)}
+		imp.imported[path] = ii
+
+		// Find and create the actual package.
+		if _, ok := imp.conf.ImportPkgs[path]; ok || imp.conf.SourceImports {
+			ii.info, ii.err = imp.importFromSource(path)
+		} else {
+			ii.info, ii.err = imp.importFromBinary(path)
+		}
+		if ii.info != nil {
+			ii.info.Importable = true
+		}
+	}
+
+	return ii.info, ii.err
+}
+
+// importFromBinary implements package loading from the client-supplied
+// external source, e.g. object files from the gc compiler.
+//
+func (imp *importer) importFromBinary(path string) (*PackageInfo, error) {
+	// Determine the caller's effective Import function.
+	importfn := imp.conf.TypeChecker.Import
+	if importfn == nil {
+		importfn = gcimporter.Import
+	}
+	pkg, err := importfn(imp.conf.TypeChecker.Packages, path)
+	if err != nil {
+		return nil, err
+	}
+	info := &PackageInfo{Pkg: pkg}
+	imp.prog.AllPackages[pkg] = info
+	return info, nil
+}
+
+// importFromSource implements package loading by parsing Go source files
+// located by go/build.
+//
+func (imp *importer) importFromSource(path string) (*PackageInfo, error) {
+	bp, err := imp.conf.findSourcePackage(path)
+	if err != nil {
+		return nil, err // package not found
+	}
+	// Type-check the package.
+	info := imp.newPackageInfo(path)
+	files, errs := imp.conf.parsePackageFiles(bp, 'g')
+	for _, err := range errs {
+		info.appendError(err)
+	}
+	typeCheckFiles(info, files...)
+	return info, nil
+}
+
+// typeCheckFiles adds the specified files to info and type-checks them.
+// The order of files determines the package initialization order.
+// It may be called multiple times.
+//
+// Errors are stored in the info.Errors field.
+func typeCheckFiles(info *PackageInfo, files ...*ast.File) {
+	info.Files = append(info.Files, files...)
+
+	// Ignore the returned (first) error since we already collect them all.
+	_ = info.checker.Files(files)
+}
+
+func (imp *importer) newPackageInfo(path string) *PackageInfo {
+	pkg := types.NewPackage(path, "")
+	info := &PackageInfo{
+		Pkg: pkg,
+		Info: types.Info{
+			Types:      make(map[ast.Expr]types.TypeAndValue),
+			Defs:       make(map[*ast.Ident]types.Object),
+			Uses:       make(map[*ast.Ident]types.Object),
+			Implicits:  make(map[ast.Node]types.Object),
+			Scopes:     make(map[ast.Node]*types.Scope),
+			Selections: make(map[*ast.SelectorExpr]*types.Selection),
+		},
+		errorFunc: imp.conf.TypeChecker.Error,
+	}
+
+	// Copy the types.Config so we can vary it across PackageInfos.
+	tc := imp.conf.TypeChecker
+	tc.IgnoreFuncBodies = false
+	if f := imp.conf.TypeCheckFuncBodies; f != nil {
+		tc.IgnoreFuncBodies = !f(path)
+	}
+	tc.Import = imp.doImport    // doImport wraps the user's importfn, effectively
+	tc.Error = info.appendError // appendError wraps the user's Error function
+
+	info.checker = types.NewChecker(&tc, imp.conf.fset(), pkg, &info.Info)
+	imp.prog.AllPackages[pkg] = info
+	return info
+}
diff --git a/third_party/go.tools/go/loader/loader_test.go b/third_party/go.tools/go/loader/loader_test.go
new file mode 100644
index 0000000..d510aba
--- /dev/null
+++ b/third_party/go.tools/go/loader/loader_test.go
@@ -0,0 +1,259 @@
+// Copyright 2013 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 loader_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/build"
+	"io"
+	"io/ioutil"
+	"os"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+)
+
+func loadFromArgs(args []string) (prog *loader.Program, rest []string, err error) {
+	conf := &loader.Config{}
+	rest, err = conf.FromArgs(args, true)
+	if err == nil {
+		prog, err = conf.Load()
+	}
+	return
+}
+
+func TestLoadFromArgs(t *testing.T) {
+	// Failed load: bad first import path causes parsePackageFiles to fail.
+	args := []string{"nosuchpkg", "errors"}
+	if _, _, err := loadFromArgs(args); err == nil {
+		t.Errorf("loadFromArgs(%q) succeeded, want failure", args)
+	} else {
+		// cannot find package: ok.
+	}
+
+	// Failed load: bad second import path proceeds to doImport0, which fails.
+	args = []string{"errors", "nosuchpkg"}
+	if _, _, err := loadFromArgs(args); err == nil {
+		t.Errorf("loadFromArgs(%q) succeeded, want failure", args)
+	} else {
+		// cannot find package: ok
+	}
+
+	// Successful load.
+	args = []string{"fmt", "errors", "--", "surplus"}
+	prog, rest, err := loadFromArgs(args)
+	if err != nil {
+		t.Fatalf("loadFromArgs(%q) failed: %s", args, err)
+	}
+	if got, want := fmt.Sprint(rest), "[surplus]"; got != want {
+		t.Errorf("loadFromArgs(%q) rest: got %s, want %s", args, got, want)
+	}
+	// Check list of Created packages.
+	var pkgnames []string
+	for _, info := range prog.Created {
+		pkgnames = append(pkgnames, info.Pkg.Path())
+	}
+	// All import paths may contribute tests.
+	if got, want := fmt.Sprint(pkgnames), "[fmt_test errors_test]"; got != want {
+		t.Errorf("Created: got %s, want %s", got, want)
+	}
+
+	// Check set of Imported packages.
+	pkgnames = nil
+	for path := range prog.Imported {
+		pkgnames = append(pkgnames, path)
+	}
+	sort.Strings(pkgnames)
+	// All import paths may contribute tests.
+	if got, want := fmt.Sprint(pkgnames), "[errors fmt]"; got != want {
+		t.Errorf("Loaded: got %s, want %s", got, want)
+	}
+
+	// Check set of transitive packages.
+	// There are >30 and the set may grow over time, so only check a few.
+	all := map[string]struct{}{}
+	for _, info := range prog.AllPackages {
+		all[info.Pkg.Path()] = struct{}{}
+	}
+	want := []string{"strings", "time", "runtime", "testing", "unicode"}
+	for _, w := range want {
+		if _, ok := all[w]; !ok {
+			t.Errorf("AllPackages: want element %s, got set %v", w, all)
+		}
+	}
+}
+
+func TestLoadFromArgsSource(t *testing.T) {
+	// mixture of *.go/non-go.
+	args := []string{"testdata/a.go", "fmt"}
+	prog, _, err := loadFromArgs(args)
+	if err == nil {
+		t.Errorf("loadFromArgs(%q) succeeded, want failure", args)
+	} else {
+		// "named files must be .go files: fmt": ok
+	}
+
+	// successful load
+	args = []string{"testdata/a.go", "testdata/b.go"}
+	prog, _, err = loadFromArgs(args)
+	if err != nil {
+		t.Fatalf("loadFromArgs(%q) failed: %s", args, err)
+	}
+	if len(prog.Created) != 1 {
+		t.Errorf("loadFromArgs(%q): got %d items, want 1", len(prog.Created))
+	}
+	if len(prog.Created) > 0 {
+		path := prog.Created[0].Pkg.Path()
+		if path != "P" {
+			t.Errorf("loadFromArgs(%q): got %v, want [P]", prog.Created, path)
+		}
+	}
+}
+
+type fakeFileInfo struct{}
+
+func (fakeFileInfo) Name() string       { return "x.go" }
+func (fakeFileInfo) Sys() interface{}   { return nil }
+func (fakeFileInfo) ModTime() time.Time { return time.Time{} }
+func (fakeFileInfo) IsDir() bool        { return false }
+func (fakeFileInfo) Size() int64        { return 0 }
+func (fakeFileInfo) Mode() os.FileMode  { return 0644 }
+
+var justXgo = [1]os.FileInfo{fakeFileInfo{}} // ["x.go"]
+
+func fakeContext(pkgs map[string]string) *build.Context {
+	ctxt := build.Default // copy
+	ctxt.GOROOT = "/go"
+	ctxt.GOPATH = ""
+	ctxt.IsDir = func(path string) bool { return true }
+	ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) { return justXgo[:], nil }
+	ctxt.OpenFile = func(path string) (io.ReadCloser, error) {
+		path = path[len("/go/src/"):]
+		return ioutil.NopCloser(bytes.NewBufferString(pkgs[path[0:1]])), nil
+	}
+	return &ctxt
+}
+
+func TestTransitivelyErrorFreeFlag(t *testing.T) {
+	// Create an minimal custom build.Context
+	// that fakes the following packages:
+	//
+	// a --> b --> c!   c has an error
+	//   \              d and e are transitively error-free.
+	//    e --> d
+	//
+	// Each package [a-e] consists of one file, x.go.
+	pkgs := map[string]string{
+		"a": `package a; import (_ "b"; _ "e")`,
+		"b": `package b; import _ "c"`,
+		"c": `package c; func f() { _ = int(false) }`, // type error within function body
+		"d": `package d;`,
+		"e": `package e; import _ "d"`,
+	}
+	conf := loader.Config{
+		AllowErrors:   true,
+		SourceImports: true,
+		Build:         fakeContext(pkgs),
+	}
+	conf.Import("a")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed: %s", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned nil *Program")
+	}
+
+	for pkg, info := range prog.AllPackages {
+		var wantErr, wantTEF bool
+		switch pkg.Path() {
+		case "a", "b":
+		case "c":
+			wantErr = true
+		case "d", "e":
+			wantTEF = true
+		default:
+			t.Errorf("unexpected package: %q", pkg.Path())
+			continue
+		}
+
+		if (info.Errors != nil) != wantErr {
+			if wantErr {
+				t.Errorf("Package %q.Error = nil, want error", pkg.Path())
+			} else {
+				t.Errorf("Package %q has unexpected Errors: %v",
+					pkg.Path(), info.Errors)
+			}
+		}
+
+		if info.TransitivelyErrorFree != wantTEF {
+			t.Errorf("Package %q.TransitivelyErrorFree=%t, want %t",
+				pkg.Path(), info.TransitivelyErrorFree, wantTEF)
+		}
+	}
+}
+
+// Test that both syntax (scan/parse) and type errors are both recorded
+// (in PackageInfo.Errors) and reported (via Config.TypeChecker.Error).
+func TestErrorReporting(t *testing.T) {
+	pkgs := map[string]string{
+		"a": `package a; import _ "b"; var x int = false`,
+		"b": `package b; 'syntax error!`,
+	}
+	conf := loader.Config{
+		AllowErrors:   true,
+		SourceImports: true,
+		Build:         fakeContext(pkgs),
+	}
+	var allErrors []error
+	conf.TypeChecker.Error = func(err error) {
+		allErrors = append(allErrors, err)
+	}
+	conf.Import("a")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed: %s", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned nil *Program")
+	}
+
+	hasError := func(errors []error, substr string) bool {
+		for _, err := range errors {
+			if strings.Contains(err.Error(), substr) {
+				return true
+			}
+		}
+		return false
+	}
+
+	// TODO(adonovan): test keys of ImportMap.
+
+	// Check errors recorded in each PackageInfo.
+	for pkg, info := range prog.AllPackages {
+		switch pkg.Path() {
+		case "a":
+			if !hasError(info.Errors, "cannot convert false") {
+				t.Errorf("a.Errors = %v, want bool conversion (type) error", info.Errors)
+			}
+		case "b":
+			if !hasError(info.Errors, "rune literal not terminated") {
+				t.Errorf("b.Errors = %v, want unterminated literal (syntax) error", info.Errors)
+			}
+		}
+	}
+
+	// Check errors reported via error handler.
+	if !hasError(allErrors, "cannot convert false") ||
+		!hasError(allErrors, "rune literal not terminated") {
+		t.Errorf("allErrors = %v, want both syntax and type errors", allErrors)
+	}
+}
diff --git a/third_party/go.tools/go/loader/source_test.go b/third_party/go.tools/go/loader/source_test.go
new file mode 100644
index 0000000..d7ebd06
--- /dev/null
+++ b/third_party/go.tools/go/loader/source_test.go
@@ -0,0 +1,126 @@
+// Copyright 2013 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 loader_test
+
+// This file defines tests of source utilities.
+
+import (
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+)
+
+// findInterval parses input and returns the [start, end) positions of
+// the first occurrence of substr in input.  f==nil indicates failure;
+// an error has already been reported in that case.
+//
+func findInterval(t *testing.T, fset *token.FileSet, input, substr string) (f *ast.File, start, end token.Pos) {
+	f, err := parser.ParseFile(fset, "<input>", input, 0)
+	if err != nil {
+		t.Errorf("parse error: %s", err)
+		return
+	}
+
+	i := strings.Index(input, substr)
+	if i < 0 {
+		t.Errorf("%q is not a substring of input", substr)
+		f = nil
+		return
+	}
+
+	filePos := fset.File(f.Package)
+	return f, filePos.Pos(i), filePos.Pos(i + len(substr))
+}
+
+func TestEnclosingFunction(t *testing.T) {
+	tests := []struct {
+		input  string // the input file
+		substr string // first occurrence of this string denotes interval
+		fn     string // name of expected containing function
+	}{
+		// We use distinctive numbers as syntactic landmarks.
+
+		// Ordinary function:
+		{`package main
+		  func f() { println(1003) }`,
+			"100", "main.f"},
+		// Methods:
+		{`package main
+                  type T int
+		  func (t T) f() { println(200) }`,
+			"200", "(main.T).f"},
+		// Function literal:
+		{`package main
+		  func f() { println(func() { print(300) }) }`,
+			"300", "main.f$1"},
+		// Doubly nested
+		{`package main
+		  func f() { println(func() { print(func() { print(350) })})}`,
+			"350", "main.f$1$1"},
+		// Implicit init for package-level var initializer.
+		{"package main; var a = 400", "400", "main.init"},
+		// No code for constants:
+		{"package main; const a = 500", "500", "(none)"},
+		// Explicit init()
+		{"package main; func init() { println(600) }", "600", "main.init#1"},
+		// Multiple explicit init functions:
+		{`package main
+		  func init() { println("foo") }
+		  func init() { println(800) }`,
+			"800", "main.init#2"},
+		// init() containing FuncLit.
+		{`package main
+		  func init() { println(func(){print(900)}) }`,
+			"900", "main.init#1$1"},
+	}
+	for _, test := range tests {
+		conf := loader.Config{Fset: token.NewFileSet()}
+		f, start, end := findInterval(t, conf.Fset, test.input, test.substr)
+		if f == nil {
+			continue
+		}
+		path, exact := astutil.PathEnclosingInterval(f, start, end)
+		if !exact {
+			t.Errorf("EnclosingFunction(%q) not exact", test.substr)
+			continue
+		}
+
+		conf.CreateFromFiles("main", f)
+
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		prog := ssa.Create(iprog, 0)
+		pkg := prog.Package(iprog.Created[0].Pkg)
+		pkg.Build()
+
+		name := "(none)"
+		fn := ssa.EnclosingFunction(pkg, path)
+		if fn != nil {
+			name = fn.String()
+		}
+
+		if name != test.fn {
+			t.Errorf("EnclosingFunction(%q in %q) got %s, want %s",
+				test.substr, test.input, name, test.fn)
+			continue
+		}
+
+		// While we're here: test HasEnclosingFunction.
+		if has := ssa.HasEnclosingFunction(pkg, path); has != (fn != nil) {
+			t.Errorf("HasEnclosingFunction(%q in %q) got %v, want %v",
+				test.substr, test.input, has, fn != nil)
+			continue
+		}
+	}
+}
diff --git a/third_party/go.tools/go/loader/stdlib_test.go b/third_party/go.tools/go/loader/stdlib_test.go
new file mode 100644
index 0000000..f797488
--- /dev/null
+++ b/third_party/go.tools/go/loader/stdlib_test.go
@@ -0,0 +1,193 @@
+// Copyright 2013 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 loader_test
+
+// This file enumerates all packages beneath $GOROOT, loads them, plus
+// their external tests if any, runs the type checker on them, and
+// prints some summary information.
+//
+// Run test with GOMAXPROCS=8.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/token"
+	"io/ioutil"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/go/buildutil"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func TestStdlib(t *testing.T) {
+	runtime.GC()
+	t0 := time.Now()
+	var memstats runtime.MemStats
+	runtime.ReadMemStats(&memstats)
+	alloc := memstats.Alloc
+
+	// Load, parse and type-check the program.
+	ctxt := build.Default // copy
+	ctxt.GOPATH = ""      // disable GOPATH
+	conf := loader.Config{Build: &ctxt}
+	for _, path := range buildutil.AllPackages(conf.Build) {
+		if err := conf.ImportWithTests(path); err != nil {
+			t.Error(err)
+		}
+	}
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+
+	t1 := time.Now()
+	runtime.GC()
+	runtime.ReadMemStats(&memstats)
+
+	numPkgs := len(prog.AllPackages)
+	if want := 205; numPkgs < want {
+		t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
+	}
+
+	// Dump package members.
+	if false {
+		for pkg := range prog.AllPackages {
+			fmt.Printf("Package %s:\n", pkg.Path())
+			scope := pkg.Scope()
+			for _, name := range scope.Names() {
+				if ast.IsExported(name) {
+					fmt.Printf("\t%s\n", types.ObjectString(pkg, scope.Lookup(name)))
+				}
+			}
+			fmt.Println()
+		}
+	}
+
+	// Check that Test functions for io/ioutil, regexp and
+	// compress/bzip2 are all simultaneously present.
+	// (The apparent cycle formed when augmenting all three of
+	// these packages by their tests was the original motivation
+	// for reporting b/7114.)
+	//
+	// compress/bzip2.TestBitReader in bzip2_test.go    imports io/ioutil
+	// io/ioutil.TestTempFile       in tempfile_test.go imports regexp
+	// regexp.TestRE2Search         in exec_test.go     imports compress/bzip2
+	for _, test := range []struct{ pkg, fn string }{
+		{"io/ioutil", "TestTempFile"},
+		{"regexp", "TestRE2Search"},
+		{"compress/bzip2", "TestBitReader"},
+	} {
+		info := prog.Imported[test.pkg]
+		if info == nil {
+			t.Errorf("failed to load package %q", test.pkg)
+			continue
+		}
+		obj, _ := info.Pkg.Scope().Lookup(test.fn).(*types.Func)
+		if obj == nil {
+			t.Errorf("package %q has no func %q", test.pkg, test.fn)
+			continue
+		}
+	}
+
+	// Dump some statistics.
+
+	// determine line count
+	var lineCount int
+	prog.Fset.Iterate(func(f *token.File) bool {
+		lineCount += f.LineCount()
+		return true
+	})
+
+	t.Log("GOMAXPROCS:           ", runtime.GOMAXPROCS(0))
+	t.Log("#Source lines:        ", lineCount)
+	t.Log("Load/parse/typecheck: ", t1.Sub(t0))
+	t.Log("#MB:                  ", int64(memstats.Alloc-alloc)/1000000)
+}
+
+func TestCgoOption(t *testing.T) {
+	switch runtime.GOOS {
+	// On these systems, the net and os/user packages don't use cgo.
+	case "plan9", "solaris", "windows":
+		return
+	}
+	// In nocgo builds (e.g. linux-amd64-nocgo),
+	// there is no "runtime/cgo" package,
+	// so cgo-generated Go files will have a failing import.
+	if !build.Default.CgoEnabled {
+		return
+	}
+	// Test that we can load cgo-using packages with
+	// CGO_ENABLED=[01], which causes go/build to select pure
+	// Go/native implementations, respectively, based on build
+	// tags.
+	//
+	// Each entry specifies a package-level object and the generic
+	// file expected to define it when cgo is disabled.
+	// When cgo is enabled, the exact file is not specified (since
+	// it varies by platform), but must differ from the generic one.
+	//
+	// The test also loads the actual file to verify that the
+	// object is indeed defined at that location.
+	for _, test := range []struct {
+		pkg, name, genericFile string
+	}{
+		{"net", "cgoLookupHost", "cgo_stub.go"},
+		{"os/user", "lookupId", "lookup_stubs.go"},
+	} {
+		ctxt := build.Default
+		for _, ctxt.CgoEnabled = range []bool{false, true} {
+			conf := loader.Config{Build: &ctxt}
+			conf.Import(test.pkg)
+			prog, err := conf.Load()
+			if err != nil {
+				t.Errorf("Load failed: %v", err)
+				continue
+			}
+			info := prog.Imported[test.pkg]
+			if info == nil {
+				t.Errorf("package %s not found", test.pkg)
+				continue
+			}
+			obj := info.Pkg.Scope().Lookup(test.name)
+			if obj == nil {
+				t.Errorf("no object %s.%s", test.pkg, test.name)
+				continue
+			}
+			posn := prog.Fset.Position(obj.Pos())
+			t.Logf("%s: %s (CgoEnabled=%t)", posn, obj, ctxt.CgoEnabled)
+
+			gotFile := filepath.Base(posn.Filename)
+			filesMatch := gotFile == test.genericFile
+
+			if ctxt.CgoEnabled && filesMatch {
+				t.Errorf("CGO_ENABLED=1: %s found in %s, want native file",
+					obj, gotFile)
+			} else if !ctxt.CgoEnabled && !filesMatch {
+				t.Errorf("CGO_ENABLED=0: %s found in %s, want %s",
+					obj, gotFile, test.genericFile)
+			}
+
+			// Load the file and check the object is declared at the right place.
+			b, err := ioutil.ReadFile(posn.Filename)
+			if err != nil {
+				t.Errorf("can't read %s: %s", posn.Filename, err)
+				continue
+			}
+			line := string(bytes.Split(b, []byte("\n"))[posn.Line-1])
+			ident := line[posn.Column-1:]
+			if !strings.HasPrefix(ident, test.name) {
+				t.Errorf("%s: %s not declared here (looking at %q)", posn, obj, ident)
+			}
+		}
+	}
+}
diff --git a/third_party/go.tools/go/loader/testdata/a.go b/third_party/go.tools/go/loader/testdata/a.go
new file mode 100644
index 0000000..bae3955
--- /dev/null
+++ b/third_party/go.tools/go/loader/testdata/a.go
@@ -0,0 +1 @@
+package P
diff --git a/third_party/go.tools/go/loader/testdata/b.go b/third_party/go.tools/go/loader/testdata/b.go
new file mode 100644
index 0000000..bae3955
--- /dev/null
+++ b/third_party/go.tools/go/loader/testdata/b.go
@@ -0,0 +1 @@
+package P
diff --git a/third_party/go.tools/go/loader/util.go b/third_party/go.tools/go/loader/util.go
new file mode 100644
index 0000000..467a74c
--- /dev/null
+++ b/third_party/go.tools/go/loader/util.go
@@ -0,0 +1,96 @@
+// Copyright 2013 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 loader
+
+import (
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io"
+	"os"
+	"path/filepath"
+	"sync"
+)
+
+// parseFiles parses the Go source files within directory dir and
+// returns the ASTs of the ones that could be at least partially parsed,
+// along with a list of I/O and parse errors encountered.
+//
+// I/O is done via ctxt, which may specify a virtual file system.
+// displayPath is used to transform the filenames attached to the ASTs.
+//
+func parseFiles(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, files []string, mode parser.Mode) ([]*ast.File, []error) {
+	if displayPath == nil {
+		displayPath = func(path string) string { return path }
+	}
+	isAbs := filepath.IsAbs
+	if ctxt.IsAbsPath != nil {
+		isAbs = ctxt.IsAbsPath
+	}
+	joinPath := filepath.Join
+	if ctxt.JoinPath != nil {
+		joinPath = ctxt.JoinPath
+	}
+	var wg sync.WaitGroup
+	n := len(files)
+	parsed := make([]*ast.File, n)
+	errors := make([]error, n)
+	for i, file := range files {
+		if !isAbs(file) {
+			file = joinPath(dir, file)
+		}
+		wg.Add(1)
+		go func(i int, file string) {
+			defer wg.Done()
+			var rd io.ReadCloser
+			var err error
+			if ctxt.OpenFile != nil {
+				rd, err = ctxt.OpenFile(file)
+			} else {
+				rd, err = os.Open(file)
+			}
+			if err != nil {
+				errors[i] = err // open failed
+				return
+			}
+
+			// ParseFile may return both an AST and an error.
+			parsed[i], errors[i] = parser.ParseFile(fset, displayPath(file), rd, mode)
+			rd.Close()
+		}(i, file)
+	}
+	wg.Wait()
+
+	// Eliminate nils, preserving order.
+	var o int
+	for _, f := range parsed {
+		if f != nil {
+			parsed[o] = f
+			o++
+		}
+	}
+	parsed = parsed[:o]
+
+	o = 0
+	for _, err := range errors {
+		if err != nil {
+			errors[o] = err
+			o++
+		}
+	}
+	errors = errors[:o]
+
+	return parsed, errors
+}
+
+// ---------- Internal helpers ----------
+
+// TODO(adonovan): make this a method: func (*token.File) Contains(token.Pos)
+func tokenFileContainsPos(f *token.File, pos token.Pos) bool {
+	p := int(pos)
+	base := f.Base()
+	return base <= p && p < base+f.Size()
+}
diff --git a/third_party/go.tools/go/pointer/TODO b/third_party/go.tools/go/pointer/TODO
new file mode 100644
index 0000000..f95e706
--- /dev/null
+++ b/third_party/go.tools/go/pointer/TODO
@@ -0,0 +1,33 @@
+-*- text -*-
+
+Pointer analysis to-do list
+===========================
+
+CONSTRAINT GENERATION:
+- support reflection:
+  - a couple of operators are missing
+  - reflect.Values may contain lvalues (CanAddr)
+- implement native intrinsics.  These vary by platform.
+- add to pts(a.panic) a label representing all runtime panics, e.g.
+  runtime.{TypeAssertionError,errorString,errorCString}.
+
+OPTIMISATIONS
+- pre-solver: 
+  pointer equivalence: extend HVN to HRU
+  location equivalence
+- solver: HCD, LCD.
+- experiment with map+slice worklist in lieu of bitset.
+  It may have faster insert.
+
+MISC:
+- Test on all platforms.  
+  Currently we assume these go/build tags: linux, amd64, !cgo.
+
+MAINTAINABILITY
+- Think about ways to make debugging this code easier.  PTA logs
+  routinely exceed a million lines and require training to read.
+
+BUGS: 
+- There's a crash bug in stdlib_test + reflection, rVCallConstraint.
+
+
diff --git a/third_party/go.tools/go/pointer/analysis.go b/third_party/go.tools/go/pointer/analysis.go
new file mode 100644
index 0000000..a89b39f
--- /dev/null
+++ b/third_party/go.tools/go/pointer/analysis.go
@@ -0,0 +1,447 @@
+// Copyright 2013 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 pointer
+
+// This file defines the main datatypes and Analyze function of the pointer analysis.
+
+import (
+	"fmt"
+	"go/token"
+	"io"
+	"os"
+	"reflect"
+	"runtime"
+	"runtime/debug"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+const (
+	// optimization options; enable all when committing
+	optRenumber = true // enable renumbering optimization (makes logs hard to read)
+	optHVN      = true // enable pointer equivalence via Hash-Value Numbering
+
+	// debugging options; disable all when committing
+	debugHVN           = false // enable assertions in HVN
+	debugHVNVerbose    = false // enable extra HVN logging
+	debugHVNCrossCheck = false // run solver with/without HVN and compare (caveats below)
+	debugTimers        = false // show running time of each phase
+)
+
+// object.flags bitmask values.
+const (
+	otTagged   = 1 << iota // type-tagged object
+	otIndirect             // type-tagged object with indirect payload
+	otFunction             // function object
+)
+
+// An object represents a contiguous block of memory to which some
+// (generalized) pointer may point.
+//
+// (Note: most variables called 'obj' are not *objects but nodeids
+// such that a.nodes[obj].obj != nil.)
+//
+type object struct {
+	// flags is a bitset of the node type (ot*) flags defined above.
+	flags uint32
+
+	// Number of following nodes belonging to the same "object"
+	// allocation.  Zero for all other nodes.
+	size uint32
+
+	// data describes this object; it has one of these types:
+	//
+	// ssa.Value	for an object allocated by an SSA operation.
+	// types.Type	for an rtype instance object or *rtype-tagged object.
+	// string	for an instrinsic object, e.g. the array behind os.Args.
+	// nil		for an object allocated by an instrinsic.
+	//		(cgn provides the identity of the intrinsic.)
+	data interface{}
+
+	// The call-graph node (=context) in which this object was allocated.
+	// May be nil for global objects: Global, Const, some Functions.
+	cgn *cgnode
+}
+
+// nodeid denotes a node.
+// It is an index within analysis.nodes.
+// We use small integers, not *node pointers, for many reasons:
+// - they are smaller on 64-bit systems.
+// - sets of them can be represented compactly in bitvectors or BDDs.
+// - order matters; a field offset can be computed by simple addition.
+type nodeid uint32
+
+// A node is an equivalence class of memory locations.
+// Nodes may be pointers, pointed-to locations, neither, or both.
+//
+// Nodes that are pointed-to locations ("labels") have an enclosing
+// object (see analysis.enclosingObject).
+//
+type node struct {
+	// If non-nil, this node is the start of an object
+	// (addressable memory location).
+	// The following obj.size nodes implicitly belong to the object;
+	// they locate their object by scanning back.
+	obj *object
+
+	// The type of the field denoted by this node.  Non-aggregate,
+	// unless this is an tagged.T node (i.e. the thing
+	// pointed to by an interface) in which case typ is that type.
+	typ types.Type
+
+	// subelement indicates which directly embedded subelement of
+	// an object of aggregate type (struct, tuple, array) this is.
+	subelement *fieldInfo // e.g. ".a.b[*].c"
+
+	// Solver state for the canonical node of this pointer-
+	// equivalence class.  Each node is created with its own state
+	// but they become shared after HVN.
+	solve *solverState
+}
+
+// An analysis instance holds the state of a single pointer analysis problem.
+type analysis struct {
+	config      *Config                     // the client's control/observer interface
+	prog        *ssa.Program                // the program being analyzed
+	log         io.Writer                   // log stream; nil to disable
+	panicNode   nodeid                      // sink for panic, source for recover
+	nodes       []*node                     // indexed by nodeid
+	flattenMemo map[types.Type][]*fieldInfo // memoization of flatten()
+	trackTypes  map[types.Type]bool         // memoization of shouldTrack()
+	constraints []constraint                // set of constraints
+	cgnodes     []*cgnode                   // all cgnodes
+	genq        []*cgnode                   // queue of functions to generate constraints for
+	intrinsics  map[*ssa.Function]intrinsic // non-nil values are summaries for intrinsic fns
+	globalval   map[ssa.Value]nodeid        // node for each global ssa.Value
+	globalobj   map[ssa.Value]nodeid        // maps v to sole member of pts(v), if singleton
+	localval    map[ssa.Value]nodeid        // node for each local ssa.Value
+	localobj    map[ssa.Value]nodeid        // maps v to sole member of pts(v), if singleton
+	atFuncs     map[*ssa.Function]bool      // address-taken functions (for presolver)
+	mapValues   []nodeid                    // values of makemap objects (indirect in HVN)
+	work        nodeset                     // solver's worklist
+	result      *Result                     // results of the analysis
+	track       track                       // pointerlike types whose aliasing we track
+	deltaSpace  []int                       // working space for iterating over PTS deltas
+
+	// Reflection & intrinsics:
+	hasher              typeutil.Hasher // cache of type hashes
+	reflectValueObj     types.Object    // type symbol for reflect.Value (if present)
+	reflectValueCall    *ssa.Function   // (reflect.Value).Call
+	reflectRtypeObj     types.Object    // *types.TypeName for reflect.rtype (if present)
+	reflectRtypePtr     *types.Pointer  // *reflect.rtype
+	reflectType         *types.Named    // reflect.Type
+	rtypes              typeutil.Map    // nodeid of canonical *rtype-tagged object for type T
+	reflectZeros        typeutil.Map    // nodeid of canonical T-tagged object for zero value
+	runtimeSetFinalizer *ssa.Function   // runtime.SetFinalizer
+}
+
+// enclosingObj returns the first node of the addressable memory
+// object that encloses node id.  Panic ensues if that node does not
+// belong to any object.
+func (a *analysis) enclosingObj(id nodeid) nodeid {
+	// Find previous node with obj != nil.
+	for i := id; i >= 0; i-- {
+		n := a.nodes[i]
+		if obj := n.obj; obj != nil {
+			if i+nodeid(obj.size) <= id {
+				break // out of bounds
+			}
+			return i
+		}
+	}
+	panic("node has no enclosing object")
+}
+
+// labelFor returns the Label for node id.
+// Panic ensues if that node is not addressable.
+func (a *analysis) labelFor(id nodeid) *Label {
+	return &Label{
+		obj:        a.nodes[a.enclosingObj(id)].obj,
+		subelement: a.nodes[id].subelement,
+	}
+}
+
+func (a *analysis) warnf(pos token.Pos, format string, args ...interface{}) {
+	msg := fmt.Sprintf(format, args...)
+	if a.log != nil {
+		fmt.Fprintf(a.log, "%s: warning: %s\n", a.prog.Fset.Position(pos), msg)
+	}
+	a.result.Warnings = append(a.result.Warnings, Warning{pos, msg})
+}
+
+// computeTrackBits sets a.track to the necessary 'track' bits for the pointer queries.
+func (a *analysis) computeTrackBits() {
+	var queryTypes []types.Type
+	for v := range a.config.Queries {
+		queryTypes = append(queryTypes, v.Type())
+	}
+	for v := range a.config.IndirectQueries {
+		queryTypes = append(queryTypes, mustDeref(v.Type()))
+	}
+	for _, t := range queryTypes {
+		switch t.Underlying().(type) {
+		case *types.Chan:
+			a.track |= trackChan
+		case *types.Map:
+			a.track |= trackMap
+		case *types.Pointer:
+			a.track |= trackPtr
+		case *types.Slice:
+			a.track |= trackSlice
+		case *types.Interface:
+			a.track = trackAll
+			return
+		}
+		if rVObj := a.reflectValueObj; rVObj != nil && types.Identical(t, rVObj.Type()) {
+			a.track = trackAll
+			return
+		}
+	}
+}
+
+// Analyze runs the pointer analysis with the scope and options
+// specified by config, and returns the (synthetic) root of the callgraph.
+//
+// Pointer analysis of a transitively closed well-typed program should
+// always succeed.  An error can occur only due to an internal bug.
+//
+func Analyze(config *Config) (result *Result, err error) {
+	if config.Mains == nil {
+		return nil, fmt.Errorf("no main/test packages to analyze (check $GOROOT/$GOPATH)")
+	}
+	defer func() {
+		if p := recover(); p != nil {
+			err = fmt.Errorf("internal error in pointer analysis: %v (please report this bug)", p)
+			fmt.Fprintln(os.Stderr, "Internal panic in pointer analysis:")
+			debug.PrintStack()
+		}
+	}()
+
+	a := &analysis{
+		config:      config,
+		log:         config.Log,
+		prog:        config.prog(),
+		globalval:   make(map[ssa.Value]nodeid),
+		globalobj:   make(map[ssa.Value]nodeid),
+		flattenMemo: make(map[types.Type][]*fieldInfo),
+		trackTypes:  make(map[types.Type]bool),
+		atFuncs:     make(map[*ssa.Function]bool),
+		hasher:      typeutil.MakeHasher(),
+		intrinsics:  make(map[*ssa.Function]intrinsic),
+		result: &Result{
+			Queries:         make(map[ssa.Value]Pointer),
+			IndirectQueries: make(map[ssa.Value]Pointer),
+		},
+		deltaSpace: make([]int, 0, 100),
+	}
+
+	if false {
+		a.log = os.Stderr // for debugging crashes; extremely verbose
+	}
+
+	if a.log != nil {
+		fmt.Fprintln(a.log, "==== Starting analysis")
+	}
+
+	// Pointer analysis requires a complete program for soundness.
+	// Check to prevent accidental misconfiguration.
+	for _, pkg := range a.prog.AllPackages() {
+		// (This only checks that the package scope is complete,
+		// not that func bodies exist, but it's a good signal.)
+		if !pkg.Object.Complete() {
+			return nil, fmt.Errorf(`pointer analysis requires a complete program yet package %q was incomplete (set loader.Config.SourceImports during loading)`, pkg.Object.Path())
+		}
+	}
+
+	if reflect := a.prog.ImportedPackage("reflect"); reflect != nil {
+		rV := reflect.Object.Scope().Lookup("Value")
+		a.reflectValueObj = rV
+		a.reflectValueCall = a.prog.LookupMethod(rV.Type(), nil, "Call")
+		a.reflectType = reflect.Object.Scope().Lookup("Type").Type().(*types.Named)
+		a.reflectRtypeObj = reflect.Object.Scope().Lookup("rtype")
+		a.reflectRtypePtr = types.NewPointer(a.reflectRtypeObj.Type())
+
+		// Override flattening of reflect.Value, treating it like a basic type.
+		tReflectValue := a.reflectValueObj.Type()
+		a.flattenMemo[tReflectValue] = []*fieldInfo{{typ: tReflectValue}}
+
+		// Override shouldTrack of reflect.Value and *reflect.rtype.
+		// Always track pointers of these types.
+		a.trackTypes[tReflectValue] = true
+		a.trackTypes[a.reflectRtypePtr] = true
+
+		a.rtypes.SetHasher(a.hasher)
+		a.reflectZeros.SetHasher(a.hasher)
+	}
+	if runtime := a.prog.ImportedPackage("runtime"); runtime != nil {
+		a.runtimeSetFinalizer = runtime.Func("SetFinalizer")
+	}
+	a.computeTrackBits()
+
+	a.generate()
+	a.showCounts()
+
+	if optRenumber {
+		a.renumber()
+	}
+
+	N := len(a.nodes) // excludes solver-created nodes
+
+	if optHVN {
+		if debugHVNCrossCheck {
+			// Cross-check: run the solver once without
+			// optimization, once with, and compare the
+			// solutions.
+			savedConstraints := a.constraints
+
+			a.solve()
+			a.dumpSolution("A.pts", N)
+
+			// Restore.
+			a.constraints = savedConstraints
+			for _, n := range a.nodes {
+				n.solve = new(solverState)
+			}
+			a.nodes = a.nodes[:N]
+
+			// rtypes is effectively part of the solver state.
+			a.rtypes = typeutil.Map{}
+			a.rtypes.SetHasher(a.hasher)
+		}
+
+		a.hvn()
+	}
+
+	if debugHVNCrossCheck {
+		runtime.GC()
+		runtime.GC()
+	}
+
+	a.solve()
+
+	// Compare solutions.
+	if optHVN && debugHVNCrossCheck {
+		a.dumpSolution("B.pts", N)
+
+		if !diff("A.pts", "B.pts") {
+			return nil, fmt.Errorf("internal error: optimization changed solution")
+		}
+	}
+
+	// Create callgraph.Nodes in deterministic order.
+	if cg := a.result.CallGraph; cg != nil {
+		for _, caller := range a.cgnodes {
+			cg.CreateNode(caller.fn)
+		}
+	}
+
+	// Add dynamic edges to call graph.
+	var space [100]int
+	for _, caller := range a.cgnodes {
+		for _, site := range caller.sites {
+			for _, callee := range a.nodes[site.targets].solve.pts.AppendTo(space[:0]) {
+				a.callEdge(caller, site, nodeid(callee))
+			}
+		}
+	}
+
+	return a.result, nil
+}
+
+// callEdge is called for each edge in the callgraph.
+// calleeid is the callee's object node (has otFunction flag).
+//
+func (a *analysis) callEdge(caller *cgnode, site *callsite, calleeid nodeid) {
+	obj := a.nodes[calleeid].obj
+	if obj.flags&otFunction == 0 {
+		panic(fmt.Sprintf("callEdge %s -> n%d: not a function object", site, calleeid))
+	}
+	callee := obj.cgn
+
+	if cg := a.result.CallGraph; cg != nil {
+		// TODO(adonovan): opt: I would expect duplicate edges
+		// (to wrappers) to arise due to the elimination of
+		// context information, but I haven't observed any.
+		// Understand this better.
+		callgraph.AddEdge(cg.CreateNode(caller.fn), site.instr, cg.CreateNode(callee.fn))
+	}
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\tcall edge %s -> %s\n", site, callee)
+	}
+
+	// Warn about calls to non-intrinsic external functions.
+	// TODO(adonovan): de-dup these messages.
+	if fn := callee.fn; fn.Blocks == nil && a.findIntrinsic(fn) == nil {
+		a.warnf(site.pos(), "unsound call to unknown intrinsic: %s", fn)
+		a.warnf(fn.Pos(), " (declared here)")
+	}
+}
+
+// dumpSolution writes the PTS solution to the specified file.
+//
+// It only dumps the nodes that existed before solving.  The order in
+// which solver-created nodes are created depends on pre-solver
+// optimization, so we can't include them in the cross-check.
+//
+func (a *analysis) dumpSolution(filename string, N int) {
+	f, err := os.Create(filename)
+	if err != nil {
+		panic(err)
+	}
+	for id, n := range a.nodes[:N] {
+		if _, err := fmt.Fprintf(f, "pts(n%d) = {", id); err != nil {
+			panic(err)
+		}
+		var sep string
+		for _, l := range n.solve.pts.AppendTo(a.deltaSpace) {
+			if l >= N {
+				break
+			}
+			fmt.Fprintf(f, "%s%d", sep, l)
+			sep = " "
+		}
+		fmt.Fprintf(f, "} : %s\n", n.typ)
+	}
+	if err := f.Close(); err != nil {
+		panic(err)
+	}
+}
+
+// showCounts logs the size of the constraint system.  A typical
+// optimized distribution is 65% copy, 13% load, 11% addr, 5%
+// offsetAddr, 4% store, 2% others.
+//
+func (a *analysis) showCounts() {
+	if a.log != nil {
+		counts := make(map[reflect.Type]int)
+		for _, c := range a.constraints {
+			counts[reflect.TypeOf(c)]++
+		}
+		fmt.Fprintf(a.log, "# constraints:\t%d\n", len(a.constraints))
+		var lines []string
+		for t, n := range counts {
+			line := fmt.Sprintf("%7d  (%2d%%)\t%s", n, 100*n/len(a.constraints), t)
+			lines = append(lines, line)
+		}
+		sort.Sort(sort.Reverse(sort.StringSlice(lines)))
+		for _, line := range lines {
+			fmt.Fprintf(a.log, "\t%s\n", line)
+		}
+
+		fmt.Fprintf(a.log, "# nodes:\t%d\n", len(a.nodes))
+
+		// Show number of pointer equivalence classes.
+		m := make(map[*solverState]bool)
+		for _, n := range a.nodes {
+			m[n.solve] = true
+		}
+		fmt.Fprintf(a.log, "# ptsets:\t%d\n", len(m))
+	}
+}
diff --git a/third_party/go.tools/go/pointer/api.go b/third_party/go.tools/go/pointer/api.go
new file mode 100644
index 0000000..cd46762
--- /dev/null
+++ b/third_party/go.tools/go/pointer/api.go
@@ -0,0 +1,239 @@
+// Copyright 2013 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 pointer
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"io"
+
+	"llvm.org/llgo/third_party/go.tools/container/intsets"
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+// A Config formulates a pointer analysis problem for Analyze().
+type Config struct {
+	// Mains contains the set of 'main' packages to analyze
+	// Clients must provide the analysis with at least one
+	// package defining a main() function.
+	Mains []*ssa.Package
+
+	// Reflection determines whether to handle reflection
+	// operators soundly, which is currently rather slow since it
+	// causes constraint to be generated during solving
+	// proportional to the number of constraint variables, which
+	// has not yet been reduced by presolver optimisation.
+	Reflection bool
+
+	// BuildCallGraph determines whether to construct a callgraph.
+	// If enabled, the graph will be available in Result.CallGraph.
+	BuildCallGraph bool
+
+	// The client populates Queries[v] or IndirectQueries[v]
+	// for each ssa.Value v of interest, to request that the
+	// points-to sets pts(v) or pts(*v) be computed.  If the
+	// client needs both points-to sets, v may appear in both
+	// maps.
+	//
+	// (IndirectQueries is typically used for Values corresponding
+	// to source-level lvalues, e.g. an *ssa.Global.)
+	//
+	// The analysis populates the corresponding
+	// Result.{Indirect,}Queries map when it creates the pointer
+	// variable for v or *v.  Upon completion the client can
+	// inspect that map for the results.
+	//
+	// TODO(adonovan): this API doesn't scale well for batch tools
+	// that want to dump the entire solution.  Perhaps optionally
+	// populate a map[*ssa.DebugRef]Pointer in the Result, one
+	// entry per source expression.
+	//
+	Queries         map[ssa.Value]struct{}
+	IndirectQueries map[ssa.Value]struct{}
+
+	// If Log is non-nil, log messages are written to it.
+	// Logging is extremely verbose.
+	Log io.Writer
+}
+
+type track uint32
+
+const (
+	trackChan  track = 1 << iota // track 'chan' references
+	trackMap                     // track 'map' references
+	trackPtr                     // track regular pointers
+	trackSlice                   // track slice references
+
+	trackAll = ^track(0)
+)
+
+// AddQuery adds v to Config.Queries.
+// Precondition: CanPoint(v.Type()).
+// TODO(adonovan): consider returning a new Pointer for this query,
+// which will be initialized during analysis.  That avoids the needs
+// for the corresponding ssa.Value-keyed maps in Config and Result.
+func (c *Config) AddQuery(v ssa.Value) {
+	if !CanPoint(v.Type()) {
+		panic(fmt.Sprintf("%s is not a pointer-like value: %s", v, v.Type()))
+	}
+	if c.Queries == nil {
+		c.Queries = make(map[ssa.Value]struct{})
+	}
+	c.Queries[v] = struct{}{}
+}
+
+// AddQuery adds v to Config.IndirectQueries.
+// Precondition: CanPoint(v.Type().Underlying().(*types.Pointer).Elem()).
+func (c *Config) AddIndirectQuery(v ssa.Value) {
+	if c.IndirectQueries == nil {
+		c.IndirectQueries = make(map[ssa.Value]struct{})
+	}
+	if !CanPoint(mustDeref(v.Type())) {
+		panic(fmt.Sprintf("%s is not the address of a pointer-like value: %s", v, v.Type()))
+	}
+	c.IndirectQueries[v] = struct{}{}
+}
+
+func (c *Config) prog() *ssa.Program {
+	for _, main := range c.Mains {
+		return main.Prog
+	}
+	panic("empty scope")
+}
+
+type Warning struct {
+	Pos     token.Pos
+	Message string
+}
+
+// A Result contains the results of a pointer analysis.
+//
+// See Config for how to request the various Result components.
+//
+type Result struct {
+	CallGraph       *callgraph.Graph      // discovered call graph
+	Queries         map[ssa.Value]Pointer // pts(v) for each v in Config.Queries.
+	IndirectQueries map[ssa.Value]Pointer // pts(*v) for each v in Config.IndirectQueries.
+	Warnings        []Warning             // warnings of unsoundness
+}
+
+// A Pointer is an equivalence class of pointer-like values.
+//
+// A Pointer doesn't have a unique type because pointers of distinct
+// types may alias the same object.
+//
+type Pointer struct {
+	a *analysis
+	n nodeid
+}
+
+// A PointsToSet is a set of labels (locations or allocations).
+type PointsToSet struct {
+	a   *analysis // may be nil if pts is nil
+	pts *nodeset
+}
+
+func (s PointsToSet) String() string {
+	var buf bytes.Buffer
+	buf.WriteByte('[')
+	if s.pts != nil {
+		var space [50]int
+		for i, l := range s.pts.AppendTo(space[:0]) {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			buf.WriteString(s.a.labelFor(nodeid(l)).String())
+		}
+	}
+	buf.WriteByte(']')
+	return buf.String()
+}
+
+// PointsTo returns the set of labels that this points-to set
+// contains.
+func (s PointsToSet) Labels() []*Label {
+	var labels []*Label
+	if s.pts != nil {
+		var space [50]int
+		for _, l := range s.pts.AppendTo(space[:0]) {
+			labels = append(labels, s.a.labelFor(nodeid(l)))
+		}
+	}
+	return labels
+}
+
+// If this PointsToSet came from a Pointer of interface kind
+// or a reflect.Value, DynamicTypes returns the set of dynamic
+// types that it may contain.  (For an interface, they will
+// always be concrete types.)
+//
+// The result is a mapping whose keys are the dynamic types to which
+// it may point.  For each pointer-like key type, the corresponding
+// map value is the PointsToSet for pointers of that type.
+//
+// The result is empty unless CanHaveDynamicTypes(T).
+//
+func (s PointsToSet) DynamicTypes() *typeutil.Map {
+	var tmap typeutil.Map
+	tmap.SetHasher(s.a.hasher)
+	if s.pts != nil {
+		var space [50]int
+		for _, x := range s.pts.AppendTo(space[:0]) {
+			ifaceObjId := nodeid(x)
+			if !s.a.isTaggedObject(ifaceObjId) {
+				continue // !CanHaveDynamicTypes(tDyn)
+			}
+			tDyn, v, indirect := s.a.taggedValue(ifaceObjId)
+			if indirect {
+				panic("indirect tagged object") // implement later
+			}
+			pts, ok := tmap.At(tDyn).(PointsToSet)
+			if !ok {
+				pts = PointsToSet{s.a, new(nodeset)}
+				tmap.Set(tDyn, pts)
+			}
+			pts.pts.addAll(&s.a.nodes[v].solve.pts)
+		}
+	}
+	return &tmap
+}
+
+// Intersects reports whether this points-to set and the
+// argument points-to set contain common members.
+func (x PointsToSet) Intersects(y PointsToSet) bool {
+	if x.pts == nil || y.pts == nil {
+		return false
+	}
+	// This takes Θ(|x|+|y|) time.
+	var z intsets.Sparse
+	z.Intersection(&x.pts.Sparse, &y.pts.Sparse)
+	return !z.IsEmpty()
+}
+
+func (p Pointer) String() string {
+	return fmt.Sprintf("n%d", p.n)
+}
+
+// PointsTo returns the points-to set of this pointer.
+func (p Pointer) PointsTo() PointsToSet {
+	if p.n == 0 {
+		return PointsToSet{}
+	}
+	return PointsToSet{p.a, &p.a.nodes[p.n].solve.pts}
+}
+
+// MayAlias reports whether the receiver pointer may alias
+// the argument pointer.
+func (p Pointer) MayAlias(q Pointer) bool {
+	return p.PointsTo().Intersects(q.PointsTo())
+}
+
+// DynamicTypes returns p.PointsTo().DynamicTypes().
+func (p Pointer) DynamicTypes() *typeutil.Map {
+	return p.PointsTo().DynamicTypes()
+}
diff --git a/third_party/go.tools/go/pointer/callgraph.go b/third_party/go.tools/go/pointer/callgraph.go
new file mode 100644
index 0000000..a2bd95e
--- /dev/null
+++ b/third_party/go.tools/go/pointer/callgraph.go
@@ -0,0 +1,61 @@
+// Copyright 2013 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 pointer
+
+// This file defines the internal (context-sensitive) call graph.
+
+import (
+	"fmt"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+)
+
+type cgnode struct {
+	fn         *ssa.Function
+	obj        nodeid      // start of this contour's object block
+	sites      []*callsite // ordered list of callsites within this function
+	callersite *callsite   // where called from, if known; nil for shared contours
+}
+
+// contour returns a description of this node's contour.
+func (n *cgnode) contour() string {
+	if n.callersite == nil {
+		return "shared contour"
+	}
+	if n.callersite.instr != nil {
+		return fmt.Sprintf("as called from %s", n.callersite.instr.Parent())
+	}
+	return fmt.Sprintf("as called from intrinsic (targets=n%d)", n.callersite.targets)
+}
+
+func (n *cgnode) String() string {
+	return fmt.Sprintf("cg%d:%s", n.obj, n.fn)
+}
+
+// A callsite represents a single call site within a cgnode;
+// it is implicitly context-sensitive.
+// callsites never represent calls to built-ins;
+// they are handled as intrinsics.
+//
+type callsite struct {
+	targets nodeid              // pts(·) contains objects for dynamically called functions
+	instr   ssa.CallInstruction // the call instruction; nil for synthetic/intrinsic
+}
+
+func (c *callsite) String() string {
+	if c.instr != nil {
+		return c.instr.Common().Description()
+	}
+	return "synthetic function call"
+}
+
+// pos returns the source position of this callsite, or token.NoPos if implicit.
+func (c *callsite) pos() token.Pos {
+	if c.instr != nil {
+		return c.instr.Pos()
+	}
+	return token.NoPos
+}
diff --git a/third_party/go.tools/go/pointer/constraint.go b/third_party/go.tools/go/pointer/constraint.go
new file mode 100644
index 0000000..6b685cb
--- /dev/null
+++ b/third_party/go.tools/go/pointer/constraint.go
@@ -0,0 +1,151 @@
+// Copyright 2013 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 pointer
+
+import (
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+type constraint interface {
+	// For a complex constraint, returns the nodeid of the pointer
+	// to which it is attached.   For addr and copy, returns dst.
+	ptr() nodeid
+
+	// renumber replaces each nodeid n in the constraint by mapping[n].
+	renumber(mapping []nodeid)
+
+	// presolve is a hook for constraint-specific behaviour during
+	// pre-solver optimization.  Typical implementations mark as
+	// indirect the set of nodes to which the solver will add copy
+	// edges or PTS labels.
+	presolve(h *hvn)
+
+	// solve is called for complex constraints when the pts for
+	// the node to which they are attached has changed.
+	solve(a *analysis, delta *nodeset)
+
+	String() string
+}
+
+// dst = &src
+// pts(dst) ⊇ {src}
+// A base constraint used to initialize the solver's pt sets
+type addrConstraint struct {
+	dst nodeid // (ptr)
+	src nodeid
+}
+
+func (c *addrConstraint) ptr() nodeid { return c.dst }
+func (c *addrConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src
+// A simple constraint represented directly as a copyTo graph edge.
+type copyConstraint struct {
+	dst nodeid // (ptr)
+	src nodeid
+}
+
+func (c *copyConstraint) ptr() nodeid { return c.dst }
+func (c *copyConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src[offset]
+// A complex constraint attached to src (the pointer)
+type loadConstraint struct {
+	offset uint32
+	dst    nodeid
+	src    nodeid // (ptr)
+}
+
+func (c *loadConstraint) ptr() nodeid { return c.src }
+func (c *loadConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst[offset] = src
+// A complex constraint attached to dst (the pointer)
+type storeConstraint struct {
+	offset uint32
+	dst    nodeid // (ptr)
+	src    nodeid
+}
+
+func (c *storeConstraint) ptr() nodeid { return c.dst }
+func (c *storeConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = &src.f  or  dst = &src[0]
+// A complex constraint attached to dst (the pointer)
+type offsetAddrConstraint struct {
+	offset uint32
+	dst    nodeid
+	src    nodeid // (ptr)
+}
+
+func (c *offsetAddrConstraint) ptr() nodeid { return c.src }
+func (c *offsetAddrConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src.(typ)  where typ is an interface
+// A complex constraint attached to src (the interface).
+// No representation change: pts(dst) and pts(src) contains tagged objects.
+type typeFilterConstraint struct {
+	typ types.Type // an interface type
+	dst nodeid
+	src nodeid // (ptr)
+}
+
+func (c *typeFilterConstraint) ptr() nodeid { return c.src }
+func (c *typeFilterConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src.(typ)  where typ is a concrete type
+// A complex constraint attached to src (the interface).
+//
+// If exact, only tagged objects identical to typ are untagged.
+// If !exact, tagged objects assignable to typ are untagged too.
+// The latter is needed for various reflect operators, e.g. Send.
+//
+// This entails a representation change:
+// pts(src) contains tagged objects,
+// pts(dst) contains their payloads.
+type untagConstraint struct {
+	typ   types.Type // a concrete type
+	dst   nodeid
+	src   nodeid // (ptr)
+	exact bool
+}
+
+func (c *untagConstraint) ptr() nodeid { return c.src }
+func (c *untagConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// src.method(params...)
+// A complex constraint attached to iface.
+type invokeConstraint struct {
+	method *types.Func // the abstract method
+	iface  nodeid      // (ptr) the interface
+	params nodeid      // the start of the identity/params/results block
+}
+
+func (c *invokeConstraint) ptr() nodeid { return c.iface }
+func (c *invokeConstraint) renumber(mapping []nodeid) {
+	c.iface = mapping[c.iface]
+	c.params = mapping[c.params]
+}
diff --git a/third_party/go.tools/go/pointer/doc.go b/third_party/go.tools/go/pointer/doc.go
new file mode 100644
index 0000000..00bf2a4
--- /dev/null
+++ b/third_party/go.tools/go/pointer/doc.go
@@ -0,0 +1,610 @@
+// Copyright 2013 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 pointer implements Andersen's analysis, an inclusion-based
+pointer analysis algorithm first described in (Andersen, 1994).
+
+A pointer analysis relates every pointer expression in a whole program
+to the set of memory locations to which it might point.  This
+information can be used to construct a call graph of the program that
+precisely represents the destinations of dynamic function and method
+calls.  It can also be used to determine, for example, which pairs of
+channel operations operate on the same channel.
+
+The package allows the client to request a set of expressions of
+interest for which the points-to information will be returned once the
+analysis is complete.  In addition, the client may request that a
+callgraph is constructed.  The example program in example_test.go
+demonstrates both of these features.  Clients should not request more
+information than they need since it may increase the cost of the
+analysis significantly.
+
+
+CLASSIFICATION
+
+Our algorithm is INCLUSION-BASED: the points-to sets for x and y will
+be related by pts(y) ⊇ pts(x) if the program contains the statement
+y = x.
+
+It is FLOW-INSENSITIVE: it ignores all control flow constructs and the
+order of statements in a program.  It is therefore a "MAY ALIAS"
+analysis: its facts are of the form "P may/may not point to L",
+not "P must point to L".
+
+It is FIELD-SENSITIVE: it builds separate points-to sets for distinct
+fields, such as x and y in struct { x, y *int }.
+
+It is mostly CONTEXT-INSENSITIVE: most functions are analyzed once,
+so values can flow in at one call to the function and return out at
+another.  Only some smaller functions are analyzed with consideration
+of their calling context.
+
+It has a CONTEXT-SENSITIVE HEAP: objects are named by both allocation
+site and context, so the objects returned by two distinct calls to f:
+   func f() *T { return new(T) }
+are distinguished up to the limits of the calling context.
+
+It is a WHOLE PROGRAM analysis: it requires SSA-form IR for the
+complete Go program and summaries for native code.
+
+See the (Hind, PASTE'01) survey paper for an explanation of these terms.
+
+
+SOUNDNESS
+
+The analysis is fully sound when invoked on pure Go programs that do not
+use reflection or unsafe.Pointer conversions.  In other words, if there
+is any possible execution of the program in which pointer P may point to
+object O, the analysis will report that fact.
+
+
+REFLECTION
+
+By default, the "reflect" library is ignored by the analysis, as if all
+its functions were no-ops, but if the client enables the Reflection flag,
+the analysis will make a reasonable attempt to model the effects of
+calls into this library.  However, this comes at a significant
+performance cost, and not all features of that library are yet
+implemented.  In addition, some simplifying approximations must be made
+to ensure that the analysis terminates; for example, reflection can be
+used to construct an infinite set of types and values of those types,
+but the analysis arbitrarily bounds the depth of such types.
+
+Most but not all reflection operations are supported.
+In particular, addressable reflect.Values are not yet implemented, so
+operations such as (reflect.Value).Set have no analytic effect.
+
+
+UNSAFE POINTER CONVERSIONS
+
+The pointer analysis makes no attempt to understand aliasing between the
+operand x and result y of an unsafe.Pointer conversion:
+   y = (*T)(unsafe.Pointer(x))
+It is as if the conversion allocated an entirely new object:
+   y = new(T)
+
+
+NATIVE CODE
+
+The analysis cannot model the aliasing effects of functions written in
+languages other than Go, such as runtime intrinsics in C or assembly, or
+code accessed via cgo.  The result is as if such functions are no-ops.
+However, various important intrinsics are understood by the analysis,
+along with built-ins such as append.
+
+The analysis currently provides no way for users to specify the aliasing
+effects of native code.
+
+------------------------------------------------------------------------
+
+IMPLEMENTATION
+
+The remaining documentation is intended for package maintainers and
+pointer analysis specialists.  Maintainers should have a solid
+understanding of the referenced papers (especially those by H&L and PKH)
+before making making significant changes.
+
+The implementation is similar to that described in (Pearce et al,
+PASTE'04).  Unlike many algorithms which interleave constraint
+generation and solving, constructing the callgraph as they go, this
+implementation for the most part observes a phase ordering (generation
+before solving), with only simple (copy) constraints being generated
+during solving.  (The exception is reflection, which creates various
+constraints during solving as new types flow to reflect.Value
+operations.)  This improves the traction of presolver optimisations,
+but imposes certain restrictions, e.g. potential context sensitivity
+is limited since all variants must be created a priori.
+
+
+TERMINOLOGY
+
+A type is said to be "pointer-like" if it is a reference to an object.
+Pointer-like types include pointers and also interfaces, maps, channels,
+functions and slices.
+
+We occasionally use C's x->f notation to distinguish the case where x
+is a struct pointer from x.f where is a struct value.
+
+Pointer analysis literature (and our comments) often uses the notation
+dst=*src+offset to mean something different than what it means in Go.
+It means: for each node index p in pts(src), the node index p+offset is
+in pts(dst).  Similarly *dst+offset=src is used for store constraints
+and dst=src+offset for offset-address constraints.
+
+
+NODES
+
+Nodes are the key datastructure of the analysis, and have a dual role:
+they represent both constraint variables (equivalence classes of
+pointers) and members of points-to sets (things that can be pointed
+at, i.e. "labels").
+
+Nodes are naturally numbered.  The numbering enables compact
+representations of sets of nodes such as bitvectors (or BDDs); and the
+ordering enables a very cheap way to group related nodes together.  For
+example, passing n parameters consists of generating n parallel
+constraints from caller+i to callee+i for 0<=i<n.
+
+The zero nodeid means "not a pointer".  For simplicity, we generate flow
+constraints even for non-pointer types such as int.  The pointer
+equivalence (PE) presolver optimization detects which variables cannot
+point to anything; this includes not only all variables of non-pointer
+types (such as int) but also variables of pointer-like types if they are
+always nil, or are parameters to a function that is never called.
+
+Each node represents a scalar part of a value or object.
+Aggregate types (structs, tuples, arrays) are recursively flattened
+out into a sequential list of scalar component types, and all the
+elements of an array are represented by a single node.  (The
+flattening of a basic type is a list containing a single node.)
+
+Nodes are connected into a graph with various kinds of labelled edges:
+simple edges (or copy constraints) represent value flow.  Complex
+edges (load, store, etc) trigger the creation of new simple edges
+during the solving phase.
+
+
+OBJECTS
+
+Conceptually, an "object" is a contiguous sequence of nodes denoting
+an addressable location: something that a pointer can point to.  The
+first node of an object has a non-nil obj field containing information
+about the allocation: its size, context, and ssa.Value.
+
+Objects include:
+   - functions and globals;
+   - variable allocations in the stack frame or heap;
+   - maps, channels and slices created by calls to make();
+   - allocations to construct an interface;
+   - allocations caused by conversions, e.g. []byte(str).
+   - arrays allocated by calls to append();
+
+Many objects have no Go types.  For example, the func, map and chan type
+kinds in Go are all varieties of pointers, but their respective objects
+are actual functions (executable code), maps (hash tables), and channels
+(synchronized queues).  Given the way we model interfaces, they too are
+pointers to "tagged" objects with no Go type.  And an *ssa.Global denotes
+the address of a global variable, but the object for a Global is the
+actual data.  So, the types of an ssa.Value that creates an object is
+"off by one indirection": a pointer to the object.
+
+The individual nodes of an object are sometimes referred to as "labels".
+
+For uniformity, all objects have a non-zero number of fields, even those
+of the empty type struct{}.  (All arrays are treated as if of length 1,
+so there are no empty arrays.  The empty tuple is never address-taken,
+so is never an object.)
+
+
+TAGGED OBJECTS
+
+An tagged object has the following layout:
+
+    T          -- obj.flags ⊇ {otTagged}
+    v
+    ...
+
+The T node's typ field is the dynamic type of the "payload": the value
+v which follows, flattened out.  The T node's obj has the otTagged
+flag.
+
+Tagged objects are needed when generalizing across types: interfaces,
+reflect.Values, reflect.Types.  Each of these three types is modelled
+as a pointer that exclusively points to tagged objects.
+
+Tagged objects may be indirect (obj.flags ⊇ {otIndirect}) meaning that
+the value v is not of type T but *T; this is used only for
+reflect.Values that represent lvalues.  (These are not implemented yet.)
+
+
+ANALYSIS ABSTRACTION OF EACH TYPE
+
+Variables of the following "scalar" types may be represented by a
+single node: basic types, pointers, channels, maps, slices, 'func'
+pointers, interfaces.
+
+Pointers
+  Nothing to say here, oddly.
+
+Basic types (bool, string, numbers, unsafe.Pointer)
+  Currently all fields in the flattening of a type, including
+  non-pointer basic types such as int, are represented in objects and
+  values.  Though non-pointer nodes within values are uninteresting,
+  non-pointer nodes in objects may be useful (if address-taken)
+  because they permit the analysis to deduce, in this example,
+
+     var s struct{ ...; x int; ... }
+     p := &s.x
+
+  that p points to s.x.  If we ignored such object fields, we could only
+  say that p points somewhere within s.
+
+  All other basic types are ignored.  Expressions of these types have
+  zero nodeid, and fields of these types within aggregate other types
+  are omitted.
+
+  unsafe.Pointers are not modelled as pointers, so a conversion of an
+  unsafe.Pointer to *T is (unsoundly) treated equivalent to new(T).
+
+Channels
+  An expression of type 'chan T' is a kind of pointer that points
+  exclusively to channel objects, i.e. objects created by MakeChan (or
+  reflection).
+
+  'chan T' is treated like *T.
+  *ssa.MakeChan is treated as equivalent to new(T).
+  *ssa.Send and receive (*ssa.UnOp(ARROW)) and are equivalent to store
+   and load.
+
+Maps
+  An expression of type 'map[K]V' is a kind of pointer that points
+  exclusively to map objects, i.e. objects created by MakeMap (or
+  reflection).
+
+  map K[V] is treated like *M where M = struct{k K; v V}.
+  *ssa.MakeMap is equivalent to new(M).
+  *ssa.MapUpdate is equivalent to *y=x where *y and x have type M.
+  *ssa.Lookup is equivalent to y=x.v where x has type *M.
+
+Slices
+  A slice []T, which dynamically resembles a struct{array *T, len, cap int},
+  is treated as if it were just a *T pointer; the len and cap fields are
+  ignored.
+
+  *ssa.MakeSlice is treated like new([1]T): an allocation of a
+   singleton array.
+  *ssa.Index on a slice is equivalent to a load.
+  *ssa.IndexAddr on a slice returns the address of the sole element of the
+  slice, i.e. the same address.
+  *ssa.Slice is treated as a simple copy.
+
+Functions
+  An expression of type 'func...' is a kind of pointer that points
+  exclusively to function objects.
+
+  A function object has the following layout:
+
+     identity         -- typ:*types.Signature; obj.flags ⊇ {otFunction}
+     params_0         -- (the receiver, if a method)
+     ...
+     params_n-1
+     results_0
+     ...
+     results_m-1
+
+  There may be multiple function objects for the same *ssa.Function
+  due to context-sensitive treatment of some functions.
+
+  The first node is the function's identity node.
+  Associated with every callsite is a special "targets" variable,
+  whose pts() contains the identity node of each function to which
+  the call may dispatch.  Identity words are not otherwise used during
+  the analysis, but we construct the call graph from the pts()
+  solution for such nodes.
+
+  The following block of contiguous nodes represents the flattened-out
+  types of the parameters ("P-block") and results ("R-block") of the
+  function object.
+
+  The treatment of free variables of closures (*ssa.FreeVar) is like
+  that of global variables; it is not context-sensitive.
+  *ssa.MakeClosure instructions create copy edges to Captures.
+
+  A Go value of type 'func' (i.e. a pointer to one or more functions)
+  is a pointer whose pts() contains function objects.  The valueNode()
+  for an *ssa.Function returns a singleton for that function.
+
+Interfaces
+  An expression of type 'interface{...}' is a kind of pointer that
+  points exclusively to tagged objects.  All tagged objects pointed to
+  by an interface are direct (the otIndirect flag is clear) and
+  concrete (the tag type T is not itself an interface type).  The
+  associated ssa.Value for an interface's tagged objects may be an
+  *ssa.MakeInterface instruction, or nil if the tagged object was
+  created by an instrinsic (e.g. reflection).
+
+  Constructing an interface value causes generation of constraints for
+  all of the concrete type's methods; we can't tell a priori which
+  ones may be called.
+
+  TypeAssert y = x.(T) is implemented by a dynamic constraint
+  triggered by each tagged object O added to pts(x): a typeFilter
+  constraint if T is an interface type, or an untag constraint if T is
+  a concrete type.  A typeFilter tests whether O.typ implements T; if
+  so, O is added to pts(y).  An untagFilter tests whether O.typ is
+  assignable to T,and if so, a copy edge O.v -> y is added.
+
+  ChangeInterface is a simple copy because the representation of
+  tagged objects is independent of the interface type (in contrast
+  to the "method tables" approach used by the gc runtime).
+
+  y := Invoke x.m(...) is implemented by allocating contiguous P/R
+  blocks for the callsite and adding a dynamic rule triggered by each
+  tagged object added to pts(x).  The rule adds param/results copy
+  edges to/from each discovered concrete method.
+
+  (Q. Why do we model an interface as a pointer to a pair of type and
+  value, rather than as a pair of a pointer to type and a pointer to
+  value?
+  A. Control-flow joins would merge interfaces ({T1}, {V1}) and ({T2},
+  {V2}) to make ({T1,T2}, {V1,V2}), leading to the infeasible and
+  type-unsafe combination (T1,V2).  Treating the value and its concrete
+  type as inseparable makes the analysis type-safe.)
+
+reflect.Value
+  A reflect.Value is modelled very similar to an interface{}, i.e. as
+  a pointer exclusively to tagged objects, but with two generalizations.
+
+  1) a reflect.Value that represents an lvalue points to an indirect
+     (obj.flags ⊇ {otIndirect}) tagged object, which has a similar
+     layout to an tagged object except that the value is a pointer to
+     the dynamic type.  Indirect tagged objects preserve the correct
+     aliasing so that mutations made by (reflect.Value).Set can be
+     observed.
+
+     Indirect objects only arise when an lvalue is derived from an
+     rvalue by indirection, e.g. the following code:
+
+        type S struct { X T }
+        var s S
+        var i interface{} = &s    // i points to a *S-tagged object (from MakeInterface)
+        v1 := reflect.ValueOf(i)  // v1 points to same *S-tagged object as i
+        v2 := v1.Elem()           // v2 points to an indirect S-tagged object, pointing to s
+        v3 := v2.FieldByName("X") // v3 points to an indirect int-tagged object, pointing to s.X
+        v3.Set(y)                 // pts(s.X) ⊇ pts(y)
+
+     Whether indirect or not, the concrete type of the tagged object
+     corresponds to the user-visible dynamic type, and the existence
+     of a pointer is an implementation detail.
+
+     (NB: indirect tagged objects are not yet implemented)
+
+  2) The dynamic type tag of a tagged object pointed to by a
+     reflect.Value may be an interface type; it need not be concrete.
+
+     This arises in code such as this:
+        tEface := reflect.TypeOf(new(interface{}).Elem() // interface{}
+        eface := reflect.Zero(tEface)
+     pts(eface) is a singleton containing an interface{}-tagged
+     object.  That tagged object's payload is an interface{} value,
+     i.e. the pts of the payload contains only concrete-tagged
+     objects, although in this example it's the zero interface{} value,
+     so its pts is empty.
+
+reflect.Type
+  Just as in the real "reflect" library, we represent a reflect.Type
+  as an interface whose sole implementation is the concrete type,
+  *reflect.rtype.  (This choice is forced on us by go/types: clients
+  cannot fabricate types with arbitrary method sets.)
+
+  rtype instances are canonical: there is at most one per dynamic
+  type.  (rtypes are in fact large structs but since identity is all
+  that matters, we represent them by a single node.)
+
+  The payload of each *rtype-tagged object is an *rtype pointer that
+  points to exactly one such canonical rtype object.  We exploit this
+  by setting the node.typ of the payload to the dynamic type, not
+  '*rtype'.  This saves us an indirection in each resolution rule.  As
+  an optimisation, *rtype-tagged objects are canonicalized too.
+
+
+Aggregate types:
+
+Aggregate types are treated as if all directly contained
+aggregates are recursively flattened out.
+
+Structs
+  *ssa.Field y = x.f creates a simple edge to y from x's node at f's offset.
+
+  *ssa.FieldAddr y = &x->f requires a dynamic closure rule to create
+   simple edges for each struct discovered in pts(x).
+
+  The nodes of a struct consist of a special 'identity' node (whose
+  type is that of the struct itself), followed by the nodes for all
+  the struct's fields, recursively flattened out.  A pointer to the
+  struct is a pointer to its identity node.  That node allows us to
+  distinguish a pointer to a struct from a pointer to its first field.
+
+  Field offsets are logical field offsets (plus one for the identity
+  node), so the sizes of the fields can be ignored by the analysis.
+
+  (The identity node is non-traditional but enables the distiction
+  described above, which is valuable for code comprehension tools.
+  Typical pointer analyses for C, whose purpose is compiler
+  optimization, must soundly model unsafe.Pointer (void*) conversions,
+  and this requires fidelity to the actual memory layout using physical
+  field offsets.)
+
+  *ssa.Field y = x.f creates a simple edge to y from x's node at f's offset.
+
+  *ssa.FieldAddr y = &x->f requires a dynamic closure rule to create
+   simple edges for each struct discovered in pts(x).
+
+Arrays
+  We model an array by an identity node (whose type is that of the
+  array itself) followed by a node representing all the elements of
+  the array; the analysis does not distinguish elements with different
+  indices.  Effectively, an array is treated like struct{elem T}, a
+  load y=x[i] like y=x.elem, and a store x[i]=y like x.elem=y; the
+  index i is ignored.
+
+  A pointer to an array is pointer to its identity node.  (A slice is
+  also a pointer to an array's identity node.)  The identity node
+  allows us to distinguish a pointer to an array from a pointer to one
+  of its elements, but it is rather costly because it introduces more
+  offset constraints into the system.  Furthermore, sound treatment of
+  unsafe.Pointer would require us to dispense with this node.
+
+  Arrays may be allocated by Alloc, by make([]T), by calls to append,
+  and via reflection.
+
+Tuples (T, ...)
+  Tuples are treated like structs with naturally numbered fields.
+  *ssa.Extract is analogous to *ssa.Field.
+
+  However, tuples have no identity field since by construction, they
+  cannot be address-taken.
+
+
+FUNCTION CALLS
+
+  There are three kinds of function call:
+  (1) static "call"-mode calls of functions.
+  (2) dynamic "call"-mode calls of functions.
+  (3) dynamic "invoke"-mode calls of interface methods.
+  Cases 1 and 2 apply equally to methods and standalone functions.
+
+  Static calls.
+    A static call consists three steps:
+    - finding the function object of the callee;
+    - creating copy edges from the actual parameter value nodes to the
+      P-block in the function object (this includes the receiver if
+      the callee is a method);
+    - creating copy edges from the R-block in the function object to
+      the value nodes for the result of the call.
+
+    A static function call is little more than two struct value copies
+    between the P/R blocks of caller and callee:
+
+       callee.P = caller.P
+       caller.R = callee.R
+
+    Context sensitivity
+
+      Static calls (alone) may be treated context sensitively,
+      i.e. each callsite may cause a distinct re-analysis of the
+      callee, improving precision.  Our current context-sensitivity
+      policy treats all intrinsics and getter/setter methods in this
+      manner since such functions are small and seem like an obvious
+      source of spurious confluences, though this has not yet been
+      evaluated.
+
+  Dynamic function calls
+
+    Dynamic calls work in a similar manner except that the creation of
+    copy edges occurs dynamically, in a similar fashion to a pair of
+    struct copies in which the callee is indirect:
+
+       callee->P = caller.P
+       caller.R = callee->R
+
+    (Recall that the function object's P- and R-blocks are contiguous.)
+
+  Interface method invocation
+
+    For invoke-mode calls, we create a params/results block for the
+    callsite and attach a dynamic closure rule to the interface.  For
+    each new tagged object that flows to the interface, we look up
+    the concrete method, find its function object, and connect its P/R
+    blocks to the callsite's P/R blocks, adding copy edges to the graph
+    during solving.
+
+  Recording call targets
+
+    The analysis notifies its clients of each callsite it encounters,
+    passing a CallSite interface.  Among other things, the CallSite
+    contains a synthetic constraint variable ("targets") whose
+    points-to solution includes the set of all function objects to
+    which the call may dispatch.
+
+    It is via this mechanism that the callgraph is made available.
+    Clients may also elect to be notified of callgraph edges directly;
+    internally this just iterates all "targets" variables' pts(·)s.
+
+
+PRESOLVER
+
+We implement Hash-Value Numbering (HVN), a pre-solver constraint
+optimization described in Hardekopf & Lin, SAS'07.  This is documented
+in more detail in hvn.go.  We intend to add its cousins HR and HU in
+future.
+
+
+SOLVER
+
+The solver is currently a naive Andersen-style implementation; it does
+not perform online cycle detection, though we plan to add solver
+optimisations such as Hybrid- and Lazy- Cycle Detection from (Hardekopf
+& Lin, PLDI'07).
+
+It uses difference propagation (Pearce et al, SQC'04) to avoid
+redundant re-triggering of closure rules for values already seen.
+
+Points-to sets are represented using sparse bit vectors (similar to
+those used in LLVM and gcc), which are more space- and time-efficient
+than sets based on Go's built-in map type or dense bit vectors.
+
+Nodes are permuted prior to solving so that object nodes (which may
+appear in points-to sets) are lower numbered than non-object (var)
+nodes.  This improves the density of the set over which the PTSs
+range, and thus the efficiency of the representation.
+
+Partly thanks to avoiding map iteration, the execution of the solver is
+100% deterministic, a great help during debugging.
+
+
+FURTHER READING
+
+Andersen, L. O. 1994. Program analysis and specialization for the C
+programming language. Ph.D. dissertation. DIKU, University of
+Copenhagen.
+
+David J. Pearce, Paul H. J. Kelly, and Chris Hankin. 2004.  Efficient
+field-sensitive pointer analysis for C. In Proceedings of the 5th ACM
+SIGPLAN-SIGSOFT workshop on Program analysis for software tools and
+engineering (PASTE '04). ACM, New York, NY, USA, 37-42.
+http://doi.acm.org/10.1145/996821.996835
+
+David J. Pearce, Paul H. J. Kelly, and Chris Hankin. 2004. Online
+Cycle Detection and Difference Propagation: Applications to Pointer
+Analysis. Software Quality Control 12, 4 (December 2004), 311-337.
+http://dx.doi.org/10.1023/B:SQJO.0000039791.93071.a2
+
+David Grove and Craig Chambers. 2001. A framework for call graph
+construction algorithms. ACM Trans. Program. Lang. Syst. 23, 6
+(November 2001), 685-746.
+http://doi.acm.org/10.1145/506315.506316
+
+Ben Hardekopf and Calvin Lin. 2007. The ant and the grasshopper: fast
+and accurate pointer analysis for millions of lines of code. In
+Proceedings of the 2007 ACM SIGPLAN conference on Programming language
+design and implementation (PLDI '07). ACM, New York, NY, USA, 290-299.
+http://doi.acm.org/10.1145/1250734.1250767
+
+Ben Hardekopf and Calvin Lin. 2007. Exploiting pointer and location
+equivalence to optimize pointer analysis. In Proceedings of the 14th
+international conference on Static Analysis (SAS'07), Hanne Riis
+Nielson and Gilberto Filé (Eds.). Springer-Verlag, Berlin, Heidelberg,
+265-280.
+
+Atanas Rountev and Satish Chandra. 2000. Off-line variable substitution
+for scaling points-to analysis. In Proceedings of the ACM SIGPLAN 2000
+conference on Programming language design and implementation (PLDI '00).
+ACM, New York, NY, USA, 47-56. DOI=10.1145/349299.349310
+http://doi.acm.org/10.1145/349299.349310
+
+*/
+package pointer
diff --git a/third_party/go.tools/go/pointer/example_test.go b/third_party/go.tools/go/pointer/example_test.go
new file mode 100644
index 0000000..98a61fd
--- /dev/null
+++ b/third_party/go.tools/go/pointer/example_test.go
@@ -0,0 +1,125 @@
+// Copyright 2013 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 pointer_test
+
+import (
+	"fmt"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/pointer"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+)
+
+// This program demonstrates how to use the pointer analysis to
+// obtain a conservative call-graph of a Go program.
+// It also shows how to compute the points-to set of a variable,
+// in this case, (C).f's ch parameter.
+//
+func Example() {
+	const myprog = `
+package main
+
+import "fmt"
+
+type I interface {
+	f(map[string]int)
+}
+
+type C struct{}
+
+func (C) f(m map[string]int) {
+	fmt.Println("C.f()")
+}
+
+func main() {
+	var i I = C{}
+	x := map[string]int{"one":1}
+	i.f(x) // dynamic method call
+}
+`
+	// Construct a loader.
+	conf := loader.Config{SourceImports: true}
+
+	// Parse the input file.
+	file, err := conf.ParseFile("myprog.go", myprog)
+	if err != nil {
+		fmt.Print(err) // parse error
+		return
+	}
+
+	// Create single-file main package and import its dependencies.
+	conf.CreateFromFiles("main", file)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		fmt.Print(err) // type error in some package
+		return
+	}
+
+	// Create SSA-form program representation.
+	prog := ssa.Create(iprog, 0)
+	mainPkg := prog.Package(iprog.Created[0].Pkg)
+
+	// Build SSA code for bodies of all functions in the whole program.
+	prog.BuildAll()
+
+	// Configure the pointer analysis to build a call-graph.
+	config := &pointer.Config{
+		Mains:          []*ssa.Package{mainPkg},
+		BuildCallGraph: true,
+	}
+
+	// Query points-to set of (C).f's parameter m, a map.
+	C := mainPkg.Type("C").Type()
+	Cfm := prog.LookupMethod(C, mainPkg.Object, "f").Params[1]
+	config.AddQuery(Cfm)
+
+	// Run the pointer analysis.
+	result, err := pointer.Analyze(config)
+	if err != nil {
+		panic(err) // internal error in pointer analysis
+	}
+
+	// Find edges originating from the main package.
+	// By converting to strings, we de-duplicate nodes
+	// representing the same function due to context sensitivity.
+	var edges []string
+	callgraph.GraphVisitEdges(result.CallGraph, func(edge *callgraph.Edge) error {
+		caller := edge.Caller.Func
+		if caller.Pkg == mainPkg {
+			edges = append(edges, fmt.Sprint(caller, " --> ", edge.Callee.Func))
+		}
+		return nil
+	})
+
+	// Print the edges in sorted order.
+	sort.Strings(edges)
+	for _, edge := range edges {
+		fmt.Println(edge)
+	}
+	fmt.Println()
+
+	// Print the labels of (C).f(m)'s points-to set.
+	fmt.Println("m may point to:")
+	var labels []string
+	for _, l := range result.Queries[Cfm].PointsTo().Labels() {
+		label := fmt.Sprintf("  %s: %s", prog.Fset.Position(l.Pos()), l)
+		labels = append(labels, label)
+	}
+	sort.Strings(labels)
+	for _, label := range labels {
+		fmt.Println(label)
+	}
+
+	// Output:
+	// (main.C).f --> fmt.Println
+	// main.init --> fmt.init
+	// main.main --> (main.C).f
+	//
+	// m may point to:
+	//   myprog.go:18:21: makemap
+}
diff --git a/third_party/go.tools/go/pointer/gen.go b/third_party/go.tools/go/pointer/gen.go
new file mode 100644
index 0000000..1f78111
--- /dev/null
+++ b/third_party/go.tools/go/pointer/gen.go
@@ -0,0 +1,1290 @@
+// Copyright 2013 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 pointer
+
+// This file defines the constraint generation phase.
+
+// TODO(adonovan): move the constraint definitions and the store() etc
+// functions which add them (and are also used by the solver) into a
+// new file, constraints.go.
+
+import (
+	"fmt"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var (
+	tEface     = types.NewInterface(nil, nil).Complete()
+	tInvalid   = types.Typ[types.Invalid]
+	tUnsafePtr = types.Typ[types.UnsafePointer]
+)
+
+// ---------- Node creation ----------
+
+// nextNode returns the index of the next unused node.
+func (a *analysis) nextNode() nodeid {
+	return nodeid(len(a.nodes))
+}
+
+// addNodes creates nodes for all scalar elements in type typ, and
+// returns the id of the first one, or zero if the type was
+// analytically uninteresting.
+//
+// comment explains the origin of the nodes, as a debugging aid.
+//
+func (a *analysis) addNodes(typ types.Type, comment string) nodeid {
+	id := a.nextNode()
+	for _, fi := range a.flatten(typ) {
+		a.addOneNode(fi.typ, comment, fi)
+	}
+	if id == a.nextNode() {
+		return 0 // type contained no pointers
+	}
+	return id
+}
+
+// addOneNode creates a single node with type typ, and returns its id.
+//
+// typ should generally be scalar (except for tagged.T nodes
+// and struct/array identity nodes).  Use addNodes for non-scalar types.
+//
+// comment explains the origin of the nodes, as a debugging aid.
+// subelement indicates the subelement, e.g. ".a.b[*].c".
+//
+func (a *analysis) addOneNode(typ types.Type, comment string, subelement *fieldInfo) nodeid {
+	id := a.nextNode()
+	a.nodes = append(a.nodes, &node{typ: typ, subelement: subelement, solve: new(solverState)})
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\tcreate n%d %s for %s%s\n",
+			id, typ, comment, subelement.path())
+	}
+	return id
+}
+
+// setValueNode associates node id with the value v.
+// cgn identifies the context iff v is a local variable.
+//
+func (a *analysis) setValueNode(v ssa.Value, id nodeid, cgn *cgnode) {
+	if cgn != nil {
+		a.localval[v] = id
+	} else {
+		a.globalval[v] = id
+	}
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\tval[%s] = n%d  (%T)\n", v.Name(), id, v)
+	}
+
+	// Due to context-sensitivity, we may encounter the same Value
+	// in many contexts. We merge them to a canonical node, since
+	// that's what all clients want.
+
+	// Record the (v, id) relation if the client has queried pts(v).
+	if _, ok := a.config.Queries[v]; ok {
+		t := v.Type()
+		ptr, ok := a.result.Queries[v]
+		if !ok {
+			// First time?  Create the canonical query node.
+			ptr = Pointer{a, a.addNodes(t, "query")}
+			a.result.Queries[v] = ptr
+		}
+		a.result.Queries[v] = ptr
+		a.copy(ptr.n, id, a.sizeof(t))
+	}
+
+	// Record the (*v, id) relation if the client has queried pts(*v).
+	if _, ok := a.config.IndirectQueries[v]; ok {
+		t := v.Type()
+		ptr, ok := a.result.IndirectQueries[v]
+		if !ok {
+			// First time? Create the canonical indirect query node.
+			ptr = Pointer{a, a.addNodes(v.Type(), "query.indirect")}
+			a.result.IndirectQueries[v] = ptr
+		}
+		a.genLoad(cgn, ptr.n, v, 0, a.sizeof(t))
+	}
+}
+
+// endObject marks the end of a sequence of calls to addNodes denoting
+// a single object allocation.
+//
+// obj is the start node of the object, from a prior call to nextNode.
+// Its size, flags and optional data will be updated.
+//
+func (a *analysis) endObject(obj nodeid, cgn *cgnode, data interface{}) *object {
+	// Ensure object is non-empty by padding;
+	// the pad will be the object node.
+	size := uint32(a.nextNode() - obj)
+	if size == 0 {
+		a.addOneNode(tInvalid, "padding", nil)
+	}
+	objNode := a.nodes[obj]
+	o := &object{
+		size: size, // excludes padding
+		cgn:  cgn,
+		data: data,
+	}
+	objNode.obj = o
+
+	return o
+}
+
+// makeFunctionObject creates and returns a new function object
+// (contour) for fn, and returns the id of its first node.  It also
+// enqueues fn for subsequent constraint generation.
+//
+// For a context-sensitive contour, callersite identifies the sole
+// callsite; for shared contours, caller is nil.
+//
+func (a *analysis) makeFunctionObject(fn *ssa.Function, callersite *callsite) nodeid {
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t---- makeFunctionObject %s\n", fn)
+	}
+
+	// obj is the function object (identity, params, results).
+	obj := a.nextNode()
+	cgn := a.makeCGNode(fn, obj, callersite)
+	sig := fn.Signature
+	a.addOneNode(sig, "func.cgnode", nil) // (scalar with Signature type)
+	if recv := sig.Recv(); recv != nil {
+		a.addNodes(recv.Type(), "func.recv")
+	}
+	a.addNodes(sig.Params(), "func.params")
+	a.addNodes(sig.Results(), "func.results")
+	a.endObject(obj, cgn, fn).flags |= otFunction
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t----\n")
+	}
+
+	// Queue it up for constraint processing.
+	a.genq = append(a.genq, cgn)
+
+	return obj
+}
+
+// makeTagged creates a tagged object of type typ.
+func (a *analysis) makeTagged(typ types.Type, cgn *cgnode, data interface{}) nodeid {
+	obj := a.addOneNode(typ, "tagged.T", nil) // NB: type may be non-scalar!
+	a.addNodes(typ, "tagged.v")
+	a.endObject(obj, cgn, data).flags |= otTagged
+	return obj
+}
+
+// makeRtype returns the canonical tagged object of type *rtype whose
+// payload points to the sole rtype object for T.
+//
+// TODO(adonovan): move to reflect.go; it's part of the solver really.
+//
+func (a *analysis) makeRtype(T types.Type) nodeid {
+	if v := a.rtypes.At(T); v != nil {
+		return v.(nodeid)
+	}
+
+	// Create the object for the reflect.rtype itself, which is
+	// ordinarily a large struct but here a single node will do.
+	obj := a.nextNode()
+	a.addOneNode(T, "reflect.rtype", nil)
+	a.endObject(obj, nil, T)
+
+	id := a.makeTagged(a.reflectRtypePtr, nil, T)
+	a.nodes[id+1].typ = T // trick (each *rtype tagged object is a singleton)
+	a.addressOf(a.reflectRtypePtr, id+1, obj)
+
+	a.rtypes.Set(T, id)
+	return id
+}
+
+// rtypeValue returns the type of the *reflect.rtype-tagged object obj.
+func (a *analysis) rtypeTaggedValue(obj nodeid) types.Type {
+	tDyn, t, _ := a.taggedValue(obj)
+	if tDyn != a.reflectRtypePtr {
+		panic(fmt.Sprintf("not a *reflect.rtype-tagged object: obj=n%d tag=%v payload=n%d", obj, tDyn, t))
+	}
+	return a.nodes[t].typ
+}
+
+// valueNode returns the id of the value node for v, creating it (and
+// the association) as needed.  It may return zero for uninteresting
+// values containing no pointers.
+//
+func (a *analysis) valueNode(v ssa.Value) nodeid {
+	// Value nodes for locals are created en masse by genFunc.
+	if id, ok := a.localval[v]; ok {
+		return id
+	}
+
+	// Value nodes for globals are created on demand.
+	id, ok := a.globalval[v]
+	if !ok {
+		var comment string
+		if a.log != nil {
+			comment = v.String()
+		}
+		id = a.addNodes(v.Type(), comment)
+		if obj := a.objectNode(nil, v); obj != 0 {
+			a.addressOf(v.Type(), id, obj)
+		}
+		a.setValueNode(v, id, nil)
+	}
+	return id
+}
+
+// valueOffsetNode ascertains the node for tuple/struct value v,
+// then returns the node for its subfield #index.
+//
+func (a *analysis) valueOffsetNode(v ssa.Value, index int) nodeid {
+	id := a.valueNode(v)
+	if id == 0 {
+		panic(fmt.Sprintf("cannot offset within n0: %s = %s", v.Name(), v))
+	}
+	return id + nodeid(a.offsetOf(v.Type(), index))
+}
+
+// isTaggedObject reports whether object obj is a tagged object.
+func (a *analysis) isTaggedObject(obj nodeid) bool {
+	return a.nodes[obj].obj.flags&otTagged != 0
+}
+
+// taggedValue returns the dynamic type tag, the (first node of the)
+// payload, and the indirect flag of the tagged object starting at id.
+// Panic ensues if !isTaggedObject(id).
+//
+func (a *analysis) taggedValue(obj nodeid) (tDyn types.Type, v nodeid, indirect bool) {
+	n := a.nodes[obj]
+	flags := n.obj.flags
+	if flags&otTagged == 0 {
+		panic(fmt.Sprintf("not a tagged object: n%d", obj))
+	}
+	return n.typ, obj + 1, flags&otIndirect != 0
+}
+
+// funcParams returns the first node of the params (P) block of the
+// function whose object node (obj.flags&otFunction) is id.
+//
+func (a *analysis) funcParams(id nodeid) nodeid {
+	n := a.nodes[id]
+	if n.obj == nil || n.obj.flags&otFunction == 0 {
+		panic(fmt.Sprintf("funcParams(n%d): not a function object block", id))
+	}
+	return id + 1
+}
+
+// funcResults returns the first node of the results (R) block of the
+// function whose object node (obj.flags&otFunction) is id.
+//
+func (a *analysis) funcResults(id nodeid) nodeid {
+	n := a.nodes[id]
+	if n.obj == nil || n.obj.flags&otFunction == 0 {
+		panic(fmt.Sprintf("funcResults(n%d): not a function object block", id))
+	}
+	sig := n.typ.(*types.Signature)
+	id += 1 + nodeid(a.sizeof(sig.Params()))
+	if sig.Recv() != nil {
+		id += nodeid(a.sizeof(sig.Recv().Type()))
+	}
+	return id
+}
+
+// ---------- Constraint creation ----------
+
+// copy creates a constraint of the form dst = src.
+// sizeof is the width (in logical fields) of the copied type.
+//
+func (a *analysis) copy(dst, src nodeid, sizeof uint32) {
+	if src == dst || sizeof == 0 {
+		return // trivial
+	}
+	if src == 0 || dst == 0 {
+		panic(fmt.Sprintf("ill-typed copy dst=n%d src=n%d", dst, src))
+	}
+	for i := uint32(0); i < sizeof; i++ {
+		a.addConstraint(&copyConstraint{dst, src})
+		src++
+		dst++
+	}
+}
+
+// addressOf creates a constraint of the form id = &obj.
+// T is the type of the address.
+func (a *analysis) addressOf(T types.Type, id, obj nodeid) {
+	if id == 0 {
+		panic("addressOf: zero id")
+	}
+	if obj == 0 {
+		panic("addressOf: zero obj")
+	}
+	if a.shouldTrack(T) {
+		a.addConstraint(&addrConstraint{id, obj})
+	}
+}
+
+// load creates a load constraint of the form dst = src[offset].
+// offset is the pointer offset in logical fields.
+// sizeof is the width (in logical fields) of the loaded type.
+//
+func (a *analysis) load(dst, src nodeid, offset, sizeof uint32) {
+	if dst == 0 {
+		return // load of non-pointerlike value
+	}
+	if src == 0 && dst == 0 {
+		return // non-pointerlike operation
+	}
+	if src == 0 || dst == 0 {
+		panic(fmt.Sprintf("ill-typed load dst=n%d src=n%d", dst, src))
+	}
+	for i := uint32(0); i < sizeof; i++ {
+		a.addConstraint(&loadConstraint{offset, dst, src})
+		offset++
+		dst++
+	}
+}
+
+// store creates a store constraint of the form dst[offset] = src.
+// offset is the pointer offset in logical fields.
+// sizeof is the width (in logical fields) of the stored type.
+//
+func (a *analysis) store(dst, src nodeid, offset uint32, sizeof uint32) {
+	if src == 0 {
+		return // store of non-pointerlike value
+	}
+	if src == 0 && dst == 0 {
+		return // non-pointerlike operation
+	}
+	if src == 0 || dst == 0 {
+		panic(fmt.Sprintf("ill-typed store dst=n%d src=n%d", dst, src))
+	}
+	for i := uint32(0); i < sizeof; i++ {
+		a.addConstraint(&storeConstraint{offset, dst, src})
+		offset++
+		src++
+	}
+}
+
+// offsetAddr creates an offsetAddr constraint of the form dst = &src.#offset.
+// offset is the field offset in logical fields.
+// T is the type of the address.
+//
+func (a *analysis) offsetAddr(T types.Type, dst, src nodeid, offset uint32) {
+	if !a.shouldTrack(T) {
+		return
+	}
+	if offset == 0 {
+		// Simplify  dst = &src->f0
+		//       to  dst = src
+		// (NB: this optimisation is defeated by the identity
+		// field prepended to struct and array objects.)
+		a.copy(dst, src, 1)
+	} else {
+		a.addConstraint(&offsetAddrConstraint{offset, dst, src})
+	}
+}
+
+// typeAssert creates a typeFilter or untag constraint of the form dst = src.(T):
+// typeFilter for an interface, untag for a concrete type.
+// The exact flag is specified as for untagConstraint.
+//
+func (a *analysis) typeAssert(T types.Type, dst, src nodeid, exact bool) {
+	if isInterface(T) {
+		a.addConstraint(&typeFilterConstraint{T, dst, src})
+	} else {
+		a.addConstraint(&untagConstraint{T, dst, src, exact})
+	}
+}
+
+// addConstraint adds c to the constraint set.
+func (a *analysis) addConstraint(c constraint) {
+	a.constraints = append(a.constraints, c)
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t%s\n", c)
+	}
+}
+
+// copyElems generates load/store constraints for *dst = *src,
+// where src and dst are slices or *arrays.
+//
+func (a *analysis) copyElems(cgn *cgnode, typ types.Type, dst, src ssa.Value) {
+	tmp := a.addNodes(typ, "copy")
+	sz := a.sizeof(typ)
+	a.genLoad(cgn, tmp, src, 1, sz)
+	a.genStore(cgn, dst, tmp, 1, sz)
+}
+
+// ---------- Constraint generation ----------
+
+// genConv generates constraints for the conversion operation conv.
+func (a *analysis) genConv(conv *ssa.Convert, cgn *cgnode) {
+	res := a.valueNode(conv)
+	if res == 0 {
+		return // result is non-pointerlike
+	}
+
+	tSrc := conv.X.Type()
+	tDst := conv.Type()
+
+	switch utSrc := tSrc.Underlying().(type) {
+	case *types.Slice:
+		// []byte/[]rune -> string?
+		return
+
+	case *types.Pointer:
+		// *T -> unsafe.Pointer?
+		if tDst.Underlying() == tUnsafePtr {
+			return // we don't model unsafe aliasing (unsound)
+		}
+
+	case *types.Basic:
+		switch tDst.Underlying().(type) {
+		case *types.Pointer:
+			// Treat unsafe.Pointer->*T conversions like
+			// new(T) and create an unaliased object.
+			if utSrc == tUnsafePtr {
+				obj := a.addNodes(mustDeref(tDst), "unsafe.Pointer conversion")
+				a.endObject(obj, cgn, conv)
+				a.addressOf(tDst, res, obj)
+				return
+			}
+
+		case *types.Slice:
+			// string -> []byte/[]rune (or named aliases)?
+			if utSrc.Info()&types.IsString != 0 {
+				obj := a.addNodes(sliceToArray(tDst), "convert")
+				a.endObject(obj, cgn, conv)
+				a.addressOf(tDst, res, obj)
+				return
+			}
+
+		case *types.Basic:
+			// All basic-to-basic type conversions are no-ops.
+			// This includes uintptr<->unsafe.Pointer conversions,
+			// which we (unsoundly) ignore.
+			return
+		}
+	}
+
+	panic(fmt.Sprintf("illegal *ssa.Convert %s -> %s: %s", tSrc, tDst, conv.Parent()))
+}
+
+// genAppend generates constraints for a call to append.
+func (a *analysis) genAppend(instr *ssa.Call, cgn *cgnode) {
+	// Consider z = append(x, y).   y is optional.
+	// This may allocate a new [1]T array; call its object w.
+	// We get the following constraints:
+	// 	z = x
+	// 	z = &w
+	//     *z = *y
+
+	x := instr.Call.Args[0]
+
+	z := instr
+	a.copy(a.valueNode(z), a.valueNode(x), 1) // z = x
+
+	if len(instr.Call.Args) == 1 {
+		return // no allocation for z = append(x) or _ = append(x).
+	}
+
+	// TODO(adonovan): test append([]byte, ...string) []byte.
+
+	y := instr.Call.Args[1]
+	tArray := sliceToArray(instr.Call.Args[0].Type())
+
+	var w nodeid
+	w = a.nextNode()
+	a.addNodes(tArray, "append")
+	a.endObject(w, cgn, instr)
+
+	a.copyElems(cgn, tArray.Elem(), z, y)        // *z = *y
+	a.addressOf(instr.Type(), a.valueNode(z), w) //  z = &w
+}
+
+// genBuiltinCall generates contraints for a call to a built-in.
+func (a *analysis) genBuiltinCall(instr ssa.CallInstruction, cgn *cgnode) {
+	call := instr.Common()
+	switch call.Value.(*ssa.Builtin).Name() {
+	case "append":
+		// Safe cast: append cannot appear in a go or defer statement.
+		a.genAppend(instr.(*ssa.Call), cgn)
+
+	case "copy":
+		tElem := call.Args[0].Type().Underlying().(*types.Slice).Elem()
+		a.copyElems(cgn, tElem, call.Args[0], call.Args[1])
+
+	case "panic":
+		a.copy(a.panicNode, a.valueNode(call.Args[0]), 1)
+
+	case "recover":
+		if v := instr.Value(); v != nil {
+			a.copy(a.valueNode(v), a.panicNode, 1)
+		}
+
+	case "print":
+		// In the tests, the probe might be the sole reference
+		// to its arg, so make sure we create nodes for it.
+		a.valueNode(call.Args[0])
+
+	case "ssa:wrapnilchk":
+		a.copy(a.valueNode(instr.Value()), a.valueNode(call.Args[0]), 1)
+
+	default:
+		// No-ops: close len cap real imag complex print println delete.
+	}
+}
+
+// shouldUseContext defines the context-sensitivity policy.  It
+// returns true if we should analyse all static calls to fn anew.
+//
+// Obviously this interface rather limits how much freedom we have to
+// choose a policy.  The current policy, rather arbitrarily, is true
+// for intrinsics and accessor methods (actually: short, single-block,
+// call-free functions).  This is just a starting point.
+//
+func (a *analysis) shouldUseContext(fn *ssa.Function) bool {
+	if a.findIntrinsic(fn) != nil {
+		return true // treat intrinsics context-sensitively
+	}
+	if len(fn.Blocks) != 1 {
+		return false // too expensive
+	}
+	blk := fn.Blocks[0]
+	if len(blk.Instrs) > 10 {
+		return false // too expensive
+	}
+	if fn.Synthetic != "" && (fn.Pkg == nil || fn != fn.Pkg.Func("init")) {
+		return true // treat synthetic wrappers context-sensitively
+	}
+	for _, instr := range blk.Instrs {
+		switch instr := instr.(type) {
+		case ssa.CallInstruction:
+			// Disallow function calls (except to built-ins)
+			// because of the danger of unbounded recursion.
+			if _, ok := instr.Common().Value.(*ssa.Builtin); !ok {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+// genStaticCall generates constraints for a statically dispatched function call.
+func (a *analysis) genStaticCall(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	fn := call.StaticCallee()
+
+	// Special cases for inlined intrinsics.
+	switch fn {
+	case a.runtimeSetFinalizer:
+		// Inline SetFinalizer so the call appears direct.
+		site.targets = a.addOneNode(tInvalid, "SetFinalizer.targets", nil)
+		a.addConstraint(&runtimeSetFinalizerConstraint{
+			targets: site.targets,
+			x:       a.valueNode(call.Args[0]),
+			f:       a.valueNode(call.Args[1]),
+		})
+		return
+
+	case a.reflectValueCall:
+		// Inline (reflect.Value).Call so the call appears direct.
+		dotdotdot := false
+		ret := reflectCallImpl(a, caller, site, a.valueNode(call.Args[0]), a.valueNode(call.Args[1]), dotdotdot)
+		if result != 0 {
+			a.addressOf(fn.Signature.Results().At(0).Type(), result, ret)
+		}
+		return
+	}
+
+	// Ascertain the context (contour/cgnode) for a particular call.
+	var obj nodeid
+	if a.shouldUseContext(fn) {
+		obj = a.makeFunctionObject(fn, site) // new contour
+	} else {
+		obj = a.objectNode(nil, fn) // shared contour
+	}
+	a.callEdge(caller, site, obj)
+
+	sig := call.Signature()
+
+	// Copy receiver, if any.
+	params := a.funcParams(obj)
+	args := call.Args
+	if sig.Recv() != nil {
+		sz := a.sizeof(sig.Recv().Type())
+		a.copy(params, a.valueNode(args[0]), sz)
+		params += nodeid(sz)
+		args = args[1:]
+	}
+
+	// Copy actual parameters into formal params block.
+	// Must loop, since the actuals aren't contiguous.
+	for i, arg := range args {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.copy(params, a.valueNode(arg), sz)
+		params += nodeid(sz)
+	}
+
+	// Copy formal results block to actual result.
+	if result != 0 {
+		a.copy(result, a.funcResults(obj), a.sizeof(sig.Results()))
+	}
+}
+
+// genDynamicCall generates constraints for a dynamic function call.
+func (a *analysis) genDynamicCall(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	// pts(targets) will be the set of possible call targets.
+	site.targets = a.valueNode(call.Value)
+
+	// We add dynamic closure rules that store the arguments into
+	// the P-block and load the results from the R-block of each
+	// function discovered in pts(targets).
+
+	sig := call.Signature()
+	var offset uint32 = 1 // P/R block starts at offset 1
+	for i, arg := range call.Args {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.genStore(caller, call.Value, a.valueNode(arg), offset, sz)
+		offset += sz
+	}
+	if result != 0 {
+		a.genLoad(caller, result, call.Value, offset, a.sizeof(sig.Results()))
+	}
+}
+
+// genInvoke generates constraints for a dynamic method invocation.
+func (a *analysis) genInvoke(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	if call.Value.Type() == a.reflectType {
+		a.genInvokeReflectType(caller, site, call, result)
+		return
+	}
+
+	sig := call.Signature()
+
+	// Allocate a contiguous targets/params/results block for this call.
+	block := a.nextNode()
+	// pts(targets) will be the set of possible call targets
+	site.targets = a.addOneNode(sig, "invoke.targets", nil)
+	p := a.addNodes(sig.Params(), "invoke.params")
+	r := a.addNodes(sig.Results(), "invoke.results")
+
+	// Copy the actual parameters into the call's params block.
+	for i, n := 0, sig.Params().Len(); i < n; i++ {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.copy(p, a.valueNode(call.Args[i]), sz)
+		p += nodeid(sz)
+	}
+	// Copy the call's results block to the actual results.
+	if result != 0 {
+		a.copy(result, r, a.sizeof(sig.Results()))
+	}
+
+	// We add a dynamic invoke constraint that will connect the
+	// caller's and the callee's P/R blocks for each discovered
+	// call target.
+	a.addConstraint(&invokeConstraint{call.Method, a.valueNode(call.Value), block})
+}
+
+// genInvokeReflectType is a specialization of genInvoke where the
+// receiver type is a reflect.Type, under the assumption that there
+// can be at most one implementation of this interface, *reflect.rtype.
+//
+// (Though this may appear to be an instance of a pattern---method
+// calls on interfaces known to have exactly one implementation---in
+// practice it occurs rarely, so we special case for reflect.Type.)
+//
+// In effect we treat this:
+//    var rt reflect.Type = ...
+//    rt.F()
+// as this:
+//    rt.(*reflect.rtype).F()
+//
+func (a *analysis) genInvokeReflectType(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	// Unpack receiver into rtype
+	rtype := a.addOneNode(a.reflectRtypePtr, "rtype.recv", nil)
+	recv := a.valueNode(call.Value)
+	a.typeAssert(a.reflectRtypePtr, rtype, recv, true)
+
+	// Look up the concrete method.
+	fn := a.prog.LookupMethod(a.reflectRtypePtr, call.Method.Pkg(), call.Method.Name())
+
+	obj := a.makeFunctionObject(fn, site) // new contour for this call
+	a.callEdge(caller, site, obj)
+
+	// From now on, it's essentially a static call, but little is
+	// gained by factoring together the code for both cases.
+
+	sig := fn.Signature // concrete method
+	targets := a.addOneNode(sig, "call.targets", nil)
+	a.addressOf(sig, targets, obj) // (a singleton)
+
+	// Copy receiver.
+	params := a.funcParams(obj)
+	a.copy(params, rtype, 1)
+	params++
+
+	// Copy actual parameters into formal P-block.
+	// Must loop, since the actuals aren't contiguous.
+	for i, arg := range call.Args {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.copy(params, a.valueNode(arg), sz)
+		params += nodeid(sz)
+	}
+
+	// Copy formal R-block to actual R-block.
+	if result != 0 {
+		a.copy(result, a.funcResults(obj), a.sizeof(sig.Results()))
+	}
+}
+
+// genCall generates constraints for call instruction instr.
+func (a *analysis) genCall(caller *cgnode, instr ssa.CallInstruction) {
+	call := instr.Common()
+
+	// Intrinsic implementations of built-in functions.
+	if _, ok := call.Value.(*ssa.Builtin); ok {
+		a.genBuiltinCall(instr, caller)
+		return
+	}
+
+	var result nodeid
+	if v := instr.Value(); v != nil {
+		result = a.valueNode(v)
+	}
+
+	site := &callsite{instr: instr}
+	if call.StaticCallee() != nil {
+		a.genStaticCall(caller, site, call, result)
+	} else if call.IsInvoke() {
+		a.genInvoke(caller, site, call, result)
+	} else {
+		a.genDynamicCall(caller, site, call, result)
+	}
+
+	caller.sites = append(caller.sites, site)
+
+	if a.log != nil {
+		// TODO(adonovan): debug: improve log message.
+		fmt.Fprintf(a.log, "\t%s to targets %s from %s\n", site, site.targets, caller)
+	}
+}
+
+// objectNode returns the object to which v points, if known.
+// In other words, if the points-to set of v is a singleton, it
+// returns the sole label, zero otherwise.
+//
+// We exploit this information to make the generated constraints less
+// dynamic.  For example, a complex load constraint can be replaced by
+// a simple copy constraint when the sole destination is known a priori.
+//
+// Some SSA instructions always have singletons points-to sets:
+// 	Alloc, Function, Global, MakeChan, MakeClosure,  MakeInterface,  MakeMap,  MakeSlice.
+// Others may be singletons depending on their operands:
+// 	FreeVar, Const, Convert, FieldAddr, IndexAddr, Slice.
+//
+// Idempotent.  Objects are created as needed, possibly via recursion
+// down the SSA value graph, e.g IndexAddr(FieldAddr(Alloc))).
+//
+func (a *analysis) objectNode(cgn *cgnode, v ssa.Value) nodeid {
+	switch v.(type) {
+	case *ssa.Global, *ssa.Function, *ssa.Const, *ssa.FreeVar:
+		// Global object.
+		obj, ok := a.globalobj[v]
+		if !ok {
+			switch v := v.(type) {
+			case *ssa.Global:
+				obj = a.nextNode()
+				a.addNodes(mustDeref(v.Type()), "global")
+				a.endObject(obj, nil, v)
+
+			case *ssa.Function:
+				obj = a.makeFunctionObject(v, nil)
+
+			case *ssa.Const:
+				// not addressable
+
+			case *ssa.FreeVar:
+				// not addressable
+			}
+
+			if a.log != nil {
+				fmt.Fprintf(a.log, "\tglobalobj[%s] = n%d\n", v, obj)
+			}
+			a.globalobj[v] = obj
+		}
+		return obj
+	}
+
+	// Local object.
+	obj, ok := a.localobj[v]
+	if !ok {
+		switch v := v.(type) {
+		case *ssa.Alloc:
+			obj = a.nextNode()
+			a.addNodes(mustDeref(v.Type()), "alloc")
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeSlice:
+			obj = a.nextNode()
+			a.addNodes(sliceToArray(v.Type()), "makeslice")
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeChan:
+			obj = a.nextNode()
+			a.addNodes(v.Type().Underlying().(*types.Chan).Elem(), "makechan")
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeMap:
+			obj = a.nextNode()
+			tmap := v.Type().Underlying().(*types.Map)
+			a.addNodes(tmap.Key(), "makemap.key")
+			elem := a.addNodes(tmap.Elem(), "makemap.value")
+
+			// To update the value field, MapUpdate
+			// generates store-with-offset constraints which
+			// the presolver can't model, so we must mark
+			// those nodes indirect.
+			for id, end := elem, elem+nodeid(a.sizeof(tmap.Elem())); id < end; id++ {
+				a.mapValues = append(a.mapValues, id)
+			}
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeInterface:
+			tConc := v.X.Type()
+			obj = a.makeTagged(tConc, cgn, v)
+
+			// Copy the value into it, if nontrivial.
+			if x := a.valueNode(v.X); x != 0 {
+				a.copy(obj+1, x, a.sizeof(tConc))
+			}
+
+		case *ssa.FieldAddr:
+			if xobj := a.objectNode(cgn, v.X); xobj != 0 {
+				obj = xobj + nodeid(a.offsetOf(mustDeref(v.X.Type()), v.Field))
+			}
+
+		case *ssa.IndexAddr:
+			if xobj := a.objectNode(cgn, v.X); xobj != 0 {
+				obj = xobj + 1
+			}
+
+		case *ssa.Slice:
+			obj = a.objectNode(cgn, v.X)
+
+		case *ssa.Convert:
+			// TODO(adonovan): opt: handle these cases too:
+			// - unsafe.Pointer->*T conversion acts like Alloc
+			// - string->[]byte/[]rune conversion acts like MakeSlice
+		}
+
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\tlocalobj[%s] = n%d\n", v.Name(), obj)
+		}
+		a.localobj[v] = obj
+	}
+	return obj
+}
+
+// genLoad generates constraints for result = *(ptr + val).
+func (a *analysis) genLoad(cgn *cgnode, result nodeid, ptr ssa.Value, offset, sizeof uint32) {
+	if obj := a.objectNode(cgn, ptr); obj != 0 {
+		// Pre-apply loadConstraint.solve().
+		a.copy(result, obj+nodeid(offset), sizeof)
+	} else {
+		a.load(result, a.valueNode(ptr), offset, sizeof)
+	}
+}
+
+// genOffsetAddr generates constraints for a 'v=ptr.field' (FieldAddr)
+// or 'v=ptr[*]' (IndexAddr) instruction v.
+func (a *analysis) genOffsetAddr(cgn *cgnode, v ssa.Value, ptr nodeid, offset uint32) {
+	dst := a.valueNode(v)
+	if obj := a.objectNode(cgn, v); obj != 0 {
+		// Pre-apply offsetAddrConstraint.solve().
+		a.addressOf(v.Type(), dst, obj)
+	} else {
+		a.offsetAddr(v.Type(), dst, ptr, offset)
+	}
+}
+
+// genStore generates constraints for *(ptr + offset) = val.
+func (a *analysis) genStore(cgn *cgnode, ptr ssa.Value, val nodeid, offset, sizeof uint32) {
+	if obj := a.objectNode(cgn, ptr); obj != 0 {
+		// Pre-apply storeConstraint.solve().
+		a.copy(obj+nodeid(offset), val, sizeof)
+	} else {
+		a.store(a.valueNode(ptr), val, offset, sizeof)
+	}
+}
+
+// genInstr generates constraints for instruction instr in context cgn.
+func (a *analysis) genInstr(cgn *cgnode, instr ssa.Instruction) {
+	if a.log != nil {
+		var prefix string
+		if val, ok := instr.(ssa.Value); ok {
+			prefix = val.Name() + " = "
+		}
+		fmt.Fprintf(a.log, "; %s%s\n", prefix, instr)
+	}
+
+	switch instr := instr.(type) {
+	case *ssa.DebugRef:
+		// no-op.
+
+	case *ssa.UnOp:
+		switch instr.Op {
+		case token.ARROW: // <-x
+			// We can ignore instr.CommaOk because the node we're
+			// altering is always at zero offset relative to instr
+			tElem := instr.X.Type().Underlying().(*types.Chan).Elem()
+			a.genLoad(cgn, a.valueNode(instr), instr.X, 0, a.sizeof(tElem))
+
+		case token.MUL: // *x
+			a.genLoad(cgn, a.valueNode(instr), instr.X, 0, a.sizeof(instr.Type()))
+
+		default:
+			// NOT, SUB, XOR: no-op.
+		}
+
+	case *ssa.BinOp:
+		// All no-ops.
+
+	case ssa.CallInstruction: // *ssa.Call, *ssa.Go, *ssa.Defer
+		a.genCall(cgn, instr)
+
+	case *ssa.ChangeType:
+		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
+
+	case *ssa.Convert:
+		a.genConv(instr, cgn)
+
+	case *ssa.Extract:
+		a.copy(a.valueNode(instr),
+			a.valueOffsetNode(instr.Tuple, instr.Index),
+			a.sizeof(instr.Type()))
+
+	case *ssa.FieldAddr:
+		a.genOffsetAddr(cgn, instr, a.valueNode(instr.X),
+			a.offsetOf(mustDeref(instr.X.Type()), instr.Field))
+
+	case *ssa.IndexAddr:
+		a.genOffsetAddr(cgn, instr, a.valueNode(instr.X), 1)
+
+	case *ssa.Field:
+		a.copy(a.valueNode(instr),
+			a.valueOffsetNode(instr.X, instr.Field),
+			a.sizeof(instr.Type()))
+
+	case *ssa.Index:
+		a.copy(a.valueNode(instr), 1+a.valueNode(instr.X), a.sizeof(instr.Type()))
+
+	case *ssa.Select:
+		recv := a.valueOffsetNode(instr, 2) // instr : (index, recvOk, recv0, ... recv_n-1)
+		for _, st := range instr.States {
+			elemSize := a.sizeof(st.Chan.Type().Underlying().(*types.Chan).Elem())
+			switch st.Dir {
+			case types.RecvOnly:
+				a.genLoad(cgn, recv, st.Chan, 0, elemSize)
+				recv += nodeid(elemSize)
+
+			case types.SendOnly:
+				a.genStore(cgn, st.Chan, a.valueNode(st.Send), 0, elemSize)
+			}
+		}
+
+	case *ssa.Return:
+		results := a.funcResults(cgn.obj)
+		for _, r := range instr.Results {
+			sz := a.sizeof(r.Type())
+			a.copy(results, a.valueNode(r), sz)
+			results += nodeid(sz)
+		}
+
+	case *ssa.Send:
+		a.genStore(cgn, instr.Chan, a.valueNode(instr.X), 0, a.sizeof(instr.X.Type()))
+
+	case *ssa.Store:
+		a.genStore(cgn, instr.Addr, a.valueNode(instr.Val), 0, a.sizeof(instr.Val.Type()))
+
+	case *ssa.Alloc, *ssa.MakeSlice, *ssa.MakeChan, *ssa.MakeMap, *ssa.MakeInterface:
+		v := instr.(ssa.Value)
+		a.addressOf(v.Type(), a.valueNode(v), a.objectNode(cgn, v))
+
+	case *ssa.ChangeInterface:
+		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
+
+	case *ssa.TypeAssert:
+		a.typeAssert(instr.AssertedType, a.valueNode(instr), a.valueNode(instr.X), true)
+
+	case *ssa.Slice:
+		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
+
+	case *ssa.If, *ssa.Jump:
+		// no-op.
+
+	case *ssa.Phi:
+		sz := a.sizeof(instr.Type())
+		for _, e := range instr.Edges {
+			a.copy(a.valueNode(instr), a.valueNode(e), sz)
+		}
+
+	case *ssa.MakeClosure:
+		fn := instr.Fn.(*ssa.Function)
+		a.copy(a.valueNode(instr), a.valueNode(fn), 1)
+		// Free variables are treated like global variables.
+		for i, b := range instr.Bindings {
+			a.copy(a.valueNode(fn.FreeVars[i]), a.valueNode(b), a.sizeof(b.Type()))
+		}
+
+	case *ssa.RunDefers:
+		// The analysis is flow insensitive, so we just "call"
+		// defers as we encounter them.
+
+	case *ssa.Range:
+		// Do nothing.  Next{Iter: *ssa.Range} handles this case.
+
+	case *ssa.Next:
+		if !instr.IsString { // map
+			// Assumes that Next is always directly applied to a Range result.
+			theMap := instr.Iter.(*ssa.Range).X
+			tMap := theMap.Type().Underlying().(*types.Map)
+			ksize := a.sizeof(tMap.Key())
+			vsize := a.sizeof(tMap.Elem())
+
+			// Load from the map's (k,v) into the tuple's (ok, k, v).
+			a.genLoad(cgn, a.valueNode(instr)+1, theMap, 0, ksize+vsize)
+		}
+
+	case *ssa.Lookup:
+		if tMap, ok := instr.X.Type().Underlying().(*types.Map); ok {
+			// CommaOk can be ignored: field 0 is a no-op.
+			ksize := a.sizeof(tMap.Key())
+			vsize := a.sizeof(tMap.Elem())
+			a.genLoad(cgn, a.valueNode(instr), instr.X, ksize, vsize)
+		}
+
+	case *ssa.MapUpdate:
+		tmap := instr.Map.Type().Underlying().(*types.Map)
+		ksize := a.sizeof(tmap.Key())
+		vsize := a.sizeof(tmap.Elem())
+		a.genStore(cgn, instr.Map, a.valueNode(instr.Key), 0, ksize)
+		a.genStore(cgn, instr.Map, a.valueNode(instr.Value), ksize, vsize)
+
+	case *ssa.Panic:
+		a.copy(a.panicNode, a.valueNode(instr.X), 1)
+
+	default:
+		panic(fmt.Sprintf("unimplemented: %T", instr))
+	}
+}
+
+func (a *analysis) makeCGNode(fn *ssa.Function, obj nodeid, callersite *callsite) *cgnode {
+	cgn := &cgnode{fn: fn, obj: obj, callersite: callersite}
+	a.cgnodes = append(a.cgnodes, cgn)
+	return cgn
+}
+
+// genRootCalls generates the synthetic root of the callgraph and the
+// initial calls from it to the analysis scope, such as main, a test
+// or a library.
+//
+func (a *analysis) genRootCalls() *cgnode {
+	r := a.prog.NewFunction("<root>", new(types.Signature), "root of callgraph")
+	root := a.makeCGNode(r, 0, nil)
+
+	// TODO(adonovan): make an ssa utility to construct an actual
+	// root function so we don't need to special-case site-less
+	// call edges.
+
+	// For each main package, call main.init(), main.main().
+	for _, mainPkg := range a.config.Mains {
+		main := mainPkg.Func("main")
+		if main == nil {
+			panic(fmt.Sprintf("%s has no main function", mainPkg))
+		}
+
+		targets := a.addOneNode(main.Signature, "root.targets", nil)
+		site := &callsite{targets: targets}
+		root.sites = append(root.sites, site)
+		for _, fn := range [2]*ssa.Function{mainPkg.Func("init"), main} {
+			if a.log != nil {
+				fmt.Fprintf(a.log, "\troot call to %s:\n", fn)
+			}
+			a.copy(targets, a.valueNode(fn), 1)
+		}
+	}
+
+	return root
+}
+
+// genFunc generates constraints for function fn.
+func (a *analysis) genFunc(cgn *cgnode) {
+	fn := cgn.fn
+
+	impl := a.findIntrinsic(fn)
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Generating constraints for %s, %s\n", cgn, cgn.contour())
+
+		// Hack: don't display body if intrinsic.
+		if impl != nil {
+			fn2 := *cgn.fn // copy
+			fn2.Locals = nil
+			fn2.Blocks = nil
+			fn2.WriteTo(a.log)
+		} else {
+			cgn.fn.WriteTo(a.log)
+		}
+	}
+
+	if impl != nil {
+		impl(a, cgn)
+		return
+	}
+
+	if fn.Blocks == nil {
+		// External function with no intrinsic treatment.
+		// We'll warn about calls to such functions at the end.
+		return
+	}
+
+	if a.log != nil {
+		fmt.Fprintln(a.log, "; Creating nodes for local values")
+	}
+
+	a.localval = make(map[ssa.Value]nodeid)
+	a.localobj = make(map[ssa.Value]nodeid)
+
+	// The value nodes for the params are in the func object block.
+	params := a.funcParams(cgn.obj)
+	for _, p := range fn.Params {
+		a.setValueNode(p, params, cgn)
+		params += nodeid(a.sizeof(p.Type()))
+	}
+
+	// Free variables have global cardinality:
+	// the outer function sets them with MakeClosure;
+	// the inner function accesses them with FreeVar.
+	//
+	// TODO(adonovan): treat free vars context-sensitively.
+
+	// Create value nodes for all value instructions
+	// since SSA may contain forward references.
+	var space [10]*ssa.Value
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			switch instr := instr.(type) {
+			case *ssa.Range:
+				// do nothing: it has a funky type,
+				// and *ssa.Next does all the work.
+
+			case ssa.Value:
+				var comment string
+				if a.log != nil {
+					comment = instr.Name()
+				}
+				id := a.addNodes(instr.Type(), comment)
+				a.setValueNode(instr, id, cgn)
+			}
+
+			// Record all address-taken functions (for presolver).
+			rands := instr.Operands(space[:0])
+			if call, ok := instr.(ssa.CallInstruction); ok && !call.Common().IsInvoke() {
+				// Skip CallCommon.Value in "call" mode.
+				// TODO(adonovan): fix: relies on unspecified ordering.  Specify it.
+				rands = rands[1:]
+			}
+			for _, rand := range rands {
+				if atf, ok := (*rand).(*ssa.Function); ok {
+					a.atFuncs[atf] = true
+				}
+			}
+		}
+	}
+
+	// Generate constraints for instructions.
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			a.genInstr(cgn, instr)
+		}
+	}
+
+	a.localval = nil
+	a.localobj = nil
+}
+
+// genMethodsOf generates nodes and constraints for all methods of type T.
+func (a *analysis) genMethodsOf(T types.Type) {
+	itf := isInterface(T)
+
+	// TODO(adonovan): can we skip this entirely if itf is true?
+	// I think so, but the answer may depend on reflection.
+	mset := a.prog.MethodSets.MethodSet(T)
+	for i, n := 0, mset.Len(); i < n; i++ {
+		m := a.prog.Method(mset.At(i))
+		a.valueNode(m)
+
+		if !itf {
+			// Methods of concrete types are address-taken functions.
+			a.atFuncs[m] = true
+		}
+	}
+}
+
+// generate generates offline constraints for the entire program.
+func (a *analysis) generate() {
+	start("Constraint generation")
+	if a.log != nil {
+		fmt.Fprintln(a.log, "==== Generating constraints")
+	}
+
+	// Create a dummy node since we use the nodeid 0 for
+	// non-pointerlike variables.
+	a.addNodes(tInvalid, "(zero)")
+
+	// Create the global node for panic values.
+	a.panicNode = a.addNodes(tEface, "panic")
+
+	// Create nodes and constraints for all methods of reflect.rtype.
+	// (Shared contours are used by dynamic calls to reflect.Type
+	// methods---typically just String().)
+	if rtype := a.reflectRtypePtr; rtype != nil {
+		a.genMethodsOf(rtype)
+	}
+
+	root := a.genRootCalls()
+
+	if a.config.BuildCallGraph {
+		a.result.CallGraph = callgraph.New(root.fn)
+	}
+
+	// Create nodes and constraints for all methods of all types
+	// that are dynamically accessible via reflection or interfaces.
+	for _, T := range a.prog.TypesWithMethodSets() {
+		a.genMethodsOf(T)
+	}
+
+	// Generate constraints for entire program.
+	for len(a.genq) > 0 {
+		cgn := a.genq[0]
+		a.genq = a.genq[1:]
+		a.genFunc(cgn)
+	}
+
+	// The runtime magically allocates os.Args; so should we.
+	if os := a.prog.ImportedPackage("os"); os != nil {
+		// In effect:  os.Args = new([1]string)[:]
+		T := types.NewSlice(types.Typ[types.String])
+		obj := a.addNodes(sliceToArray(T), "<command-line args>")
+		a.endObject(obj, nil, "<command-line args>")
+		a.addressOf(T, a.objectNode(nil, os.Var("Args")), obj)
+	}
+
+	// Discard generation state, to avoid confusion after node renumbering.
+	a.panicNode = 0
+	a.globalval = nil
+	a.localval = nil
+	a.localobj = nil
+
+	stop("Constraint generation")
+}
diff --git a/third_party/go.tools/go/pointer/hvn.go b/third_party/go.tools/go/pointer/hvn.go
new file mode 100644
index 0000000..84422a2
--- /dev/null
+++ b/third_party/go.tools/go/pointer/hvn.go
@@ -0,0 +1,969 @@
+package pointer
+
+// This file implements Hash-Value Numbering (HVN), a pre-solver
+// constraint optimization described in Hardekopf & Lin, SAS'07 (see
+// doc.go) that analyses the graph topology to determine which sets of
+// variables are "pointer equivalent" (PE), i.e. must have identical
+// points-to sets in the solution.
+//
+// A separate ("offline") graph is constructed.  Its nodes are those of
+// the main-graph, plus an additional node *X for each pointer node X.
+// With this graph we can reason about the unknown points-to set of
+// dereferenced pointers.  (We do not generalize this to represent
+// unknown fields x->f, perhaps because such fields would be numerous,
+// though it might be worth an experiment.)
+//
+// Nodes whose points-to relations are not entirely captured by the
+// graph are marked as "indirect": the *X nodes, the parameters of
+// address-taken functions (which includes all functions in method
+// sets), or nodes updated by the solver rules for reflection, etc.
+//
+// All addr (y=&x) nodes are initially assigned a pointer-equivalence
+// (PE) label equal to x's nodeid in the main graph.  (These are the
+// only PE labels that are less than len(a.nodes).)
+//
+// All offsetAddr (y=&x.f) constraints are initially assigned a PE
+// label; such labels are memoized, keyed by (x, f), so that equivalent
+// nodes y as assigned the same label.
+//
+// Then we process each strongly connected component (SCC) of the graph
+// in topological order, assigning it a PE label based on the set P of
+// PE labels that flow to it from its immediate dependencies.
+//
+// If any node in P is "indirect", the entire SCC is assigned a fresh PE
+// label.  Otherwise:
+//
+// |P|=0  if P is empty, all nodes in the SCC are non-pointers (e.g.
+//        uninitialized variables, or formal params of dead functions)
+//        and the SCC is assigned the PE label of zero.
+//
+// |P|=1  if P is a singleton, the SCC is assigned the same label as the
+//        sole element of P.
+//
+// |P|>1  if P contains multiple labels, a unique label representing P is
+//        invented and recorded in an hash table, so that other
+//        equivalent SCCs may also be assigned this label, akin to
+//        conventional hash-value numbering in a compiler.
+//
+// Finally, a renumbering is computed such that each node is replaced by
+// the lowest-numbered node with the same PE label.  All constraints are
+// renumbered, and any resulting duplicates are eliminated.
+//
+// The only nodes that are not renumbered are the objects x in addr
+// (y=&x) constraints, since the ids of these nodes (and fields derived
+// from them via offsetAddr rules) are the elements of all points-to
+// sets, so they must remain as they are if we want the same solution.
+//
+// The solverStates (node.solve) for nodes in the same equivalence class
+// are linked together so that all nodes in the class have the same
+// solution.  This avoids the need to renumber nodeids buried in
+// Queries, cgnodes, etc (like (*analysis).renumber() does) since only
+// the solution is needed.
+//
+// The result of HVN is that the number of distinct nodes and
+// constraints is reduced, but the solution is identical (almost---see
+// CROSS-CHECK below).  In particular, both linear and cyclic chains of
+// copies are each replaced by a single node.
+//
+// Nodes and constraints created "online" (e.g. while solving reflection
+// constraints) are not subject to this optimization.
+//
+// PERFORMANCE
+//
+// In two benchmarks (oracle and godoc), HVN eliminates about two thirds
+// of nodes, the majority accounted for by non-pointers: nodes of
+// non-pointer type, pointers that remain nil, formal parameters of dead
+// functions, nodes of untracked types, etc.  It also reduces the number
+// of constraints, also by about two thirds, and the solving time by
+// 30--42%, although we must pay about 15% for the running time of HVN
+// itself.  The benefit is greater for larger applications.
+//
+// There are many possible optimizations to improve the performance:
+// * Use fewer than 1:1 onodes to main graph nodes: many of the onodes
+//   we create are not needed.
+// * HU (HVN with Union---see paper): coalesce "union" peLabels when
+//   their expanded-out sets are equal.
+// * HR (HVN with deReference---see paper): this will require that we
+//   apply HVN until fixed point, which may need more bookkeeping of the
+//   correspondance of main nodes to onodes.
+// * Location Equivalence (see paper): have points-to sets contain not
+//   locations but location-equivalence class labels, each representing
+//   a set of locations.
+// * HVN with field-sensitive ref: model each of the fields of a
+//   pointer-to-struct.
+//
+// CROSS-CHECK
+//
+// To verify the soundness of the optimization, when the
+// debugHVNCrossCheck option is enabled, we run the solver twice, once
+// before and once after running HVN, dumping the solution to disk, and
+// then we compare the results.  If they are not identical, the analysis
+// panics.
+//
+// The solution dumped to disk includes only the N*N submatrix of the
+// complete solution where N is the number of nodes after generation.
+// In other words, we ignore pointer variables and objects created by
+// the solver itself, since their numbering depends on the solver order,
+// which is affected by the optimization.  In any case, that's the only
+// part the client cares about.
+//
+// The cross-check is too strict and may fail spuriously.  Although the
+// H&L paper describing HVN states that the solutions obtained should be
+// identical, this is not the case in practice because HVN can collapse
+// cycles involving *p even when pts(p)={}.  Consider this example
+// distilled from testdata/hello.go:
+//
+//	var x T
+//	func f(p **T) {
+//		t0 = *p
+//		...
+//		t1 = φ(t0, &x)
+//		*p = t1
+//	}
+//
+// If f is dead code, we get:
+// 	unoptimized:  pts(p)={} pts(t0)={} pts(t1)={&x}
+// 	optimized:    pts(p)={} pts(t0)=pts(t1)=pts(*p)={&x}
+//
+// It's hard to argue that this is a bug: the result is sound and the
+// loss of precision is inconsequential---f is dead code, after all.
+// But unfortunately it limits the usefulness of the cross-check since
+// failures must be carefully analyzed.  Ben Hardekopf suggests (in
+// personal correspondence) some approaches to mitigating it:
+//
+// 	If there is a node with an HVN points-to set that is a superset
+// 	of the NORM points-to set, then either it's a bug or it's a
+// 	result of this issue. If it's a result of this issue, then in
+// 	the offline constraint graph there should be a REF node inside
+// 	some cycle that reaches this node, and in the NORM solution the
+// 	pointer being dereferenced by that REF node should be the empty
+// 	set. If that isn't true then this is a bug. If it is true, then
+// 	you can further check that in the NORM solution the "extra"
+// 	points-to info in the HVN solution does in fact come from that
+// 	purported cycle (if it doesn't, then this is still a bug). If
+// 	you're doing the further check then you'll need to do it for
+// 	each "extra" points-to element in the HVN points-to set.
+//
+// 	There are probably ways to optimize these checks by taking
+// 	advantage of graph properties. For example, extraneous points-to
+// 	info will flow through the graph and end up in many
+// 	nodes. Rather than checking every node with extra info, you
+// 	could probably work out the "origin point" of the extra info and
+// 	just check there. Note that the check in the first bullet is
+// 	looking for soundness bugs, while the check in the second bullet
+// 	is looking for precision bugs; depending on your needs, you may
+// 	care more about one than the other.
+//
+// which we should evaluate.  The cross-check is nonetheless invaluable
+// for all but one of the programs in the pointer_test suite.
+
+import (
+	"fmt"
+	"io"
+	"reflect"
+
+	"llvm.org/llgo/third_party/go.tools/container/intsets"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// A peLabel is a pointer-equivalence label: two nodes with the same
+// peLabel have identical points-to solutions.
+//
+// The numbers are allocated consecutively like so:
+// 	0	not a pointer
+//	1..N-1	addrConstraints (equals the constraint's .src field, hence sparse)
+//	...	offsetAddr constraints
+//	...	SCCs (with indirect nodes or multiple inputs)
+//
+// Each PE label denotes a set of pointers containing a single addr, a
+// single offsetAddr, or some set of other PE labels.
+//
+type peLabel int
+
+type hvn struct {
+	a        *analysis
+	N        int                // len(a.nodes) immediately after constraint generation
+	log      io.Writer          // (optional) log of HVN lemmas
+	onodes   []*onode           // nodes of the offline graph
+	label    peLabel            // the next available PE label
+	hvnLabel map[string]peLabel // hash-value numbering (PE label) for each set of onodeids
+	stack    []onodeid          // DFS stack
+	index    int32              // next onode.index, from Tarjan's SCC algorithm
+
+	// For each distinct offsetAddrConstraint (src, offset) pair,
+	// offsetAddrLabels records a unique PE label >= N.
+	offsetAddrLabels map[offsetAddr]peLabel
+}
+
+// The index of an node in the offline graph.
+// (Currently the first N align with the main nodes,
+// but this may change with HRU.)
+type onodeid uint32
+
+// An onode is a node in the offline constraint graph.
+// (Where ambiguous, members of analysis.nodes are referred to as
+// "main graph" nodes.)
+//
+// Edges in the offline constraint graph (edges and implicit) point to
+// the source, i.e. against the flow of values: they are dependencies.
+// Implicit edges are used for SCC computation, but not for gathering
+// incoming labels.
+//
+type onode struct {
+	rep onodeid // index of representative of SCC in offline constraint graph
+
+	edges    intsets.Sparse // constraint edges X-->Y (this onode is X)
+	implicit intsets.Sparse // implicit edges *X-->*Y (this onode is X)
+	peLabels intsets.Sparse // set of peLabels are pointer-equivalent to this one
+	indirect bool           // node has points-to relations not represented in graph
+
+	// Tarjan's SCC algorithm
+	index, lowlink int32 // Tarjan numbering
+	scc            int32 // -ve => on stack; 0 => unvisited; +ve => node is root of a found SCC
+}
+
+type offsetAddr struct {
+	ptr    nodeid
+	offset uint32
+}
+
+// nextLabel issues the next unused pointer-equivalence label.
+func (h *hvn) nextLabel() peLabel {
+	h.label++
+	return h.label
+}
+
+// ref(X) returns the index of the onode for *X.
+func (h *hvn) ref(id onodeid) onodeid {
+	return id + onodeid(len(h.a.nodes))
+}
+
+// hvn computes pointer-equivalence labels (peLabels) using the Hash-based
+// Value Numbering (HVN) algorithm described in Hardekopf & Lin, SAS'07.
+//
+func (a *analysis) hvn() {
+	start("HVN")
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Pointer equivalence optimization\n\n")
+	}
+
+	h := hvn{
+		a:                a,
+		N:                len(a.nodes),
+		log:              a.log,
+		hvnLabel:         make(map[string]peLabel),
+		offsetAddrLabels: make(map[offsetAddr]peLabel),
+	}
+
+	if h.log != nil {
+		fmt.Fprintf(h.log, "\nCreating offline graph nodes...\n")
+	}
+
+	// Create offline nodes.  The first N nodes correspond to main
+	// graph nodes; the next N are their corresponding ref() nodes.
+	h.onodes = make([]*onode, 2*h.N)
+	for id := range a.nodes {
+		id := onodeid(id)
+		h.onodes[id] = &onode{}
+		h.onodes[h.ref(id)] = &onode{indirect: true}
+	}
+
+	// Each node initially represents just itself.
+	for id, o := range h.onodes {
+		o.rep = onodeid(id)
+	}
+
+	h.markIndirectNodes()
+
+	// Reserve the first N PE labels for addrConstraints.
+	h.label = peLabel(h.N)
+
+	// Add offline constraint edges.
+	if h.log != nil {
+		fmt.Fprintf(h.log, "\nAdding offline graph edges...\n")
+	}
+	for _, c := range a.constraints {
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "; %s\n", c)
+		}
+		c.presolve(&h)
+	}
+
+	// Find and collapse SCCs.
+	if h.log != nil {
+		fmt.Fprintf(h.log, "\nFinding SCCs...\n")
+	}
+	h.index = 1
+	for id, o := range h.onodes {
+		if id > 0 && o.index == 0 {
+			// Start depth-first search at each unvisited node.
+			h.visit(onodeid(id))
+		}
+	}
+
+	// Dump the solution
+	// (NB: somewhat redundant with logging from simplify().)
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\nPointer equivalences:\n")
+		for id, o := range h.onodes {
+			if id == 0 {
+				continue
+			}
+			if id == int(h.N) {
+				fmt.Fprintf(h.log, "---\n")
+			}
+			fmt.Fprintf(h.log, "o%d\t", id)
+			if o.rep != onodeid(id) {
+				fmt.Fprintf(h.log, "rep=o%d", o.rep)
+			} else {
+				fmt.Fprintf(h.log, "p%d", o.peLabels.Min())
+				if o.indirect {
+					fmt.Fprint(h.log, " indirect")
+				}
+			}
+			fmt.Fprintln(h.log)
+		}
+	}
+
+	// Simplify the main constraint graph
+	h.simplify()
+
+	a.showCounts()
+
+	stop("HVN")
+}
+
+// ---- constraint-specific rules ----
+
+// dst := &src
+func (c *addrConstraint) presolve(h *hvn) {
+	// Each object (src) is an initial PE label.
+	label := peLabel(c.src) // label < N
+	if debugHVNVerbose && h.log != nil {
+		// duplicate log messages are possible
+		fmt.Fprintf(h.log, "\tcreate p%d: {&n%d}\n", label, c.src)
+	}
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+
+	// Assign dst this label.
+	h.onodes[odst].peLabels.Insert(int(label))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d has p%d\n", odst, label)
+	}
+
+	h.addImplicitEdge(h.ref(odst), osrc) // *dst ~~> src.
+}
+
+// dst = src
+func (c *copyConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+	h.addEdge(odst, osrc)                       //  dst -->  src
+	h.addImplicitEdge(h.ref(odst), h.ref(osrc)) // *dst ~~> *src
+}
+
+// dst = *src + offset
+func (c *loadConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+	if c.offset == 0 {
+		h.addEdge(odst, h.ref(osrc)) // dst --> *src
+	} else {
+		// We don't interpret load-with-offset, e.g. results
+		// of map value lookup, R-block of dynamic call, slice
+		// copy/append, reflection.
+		h.markIndirect(odst, "load with offset")
+	}
+}
+
+// *dst + offset = src
+func (c *storeConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+	if c.offset == 0 {
+		h.onodes[h.ref(odst)].edges.Insert(int(osrc)) // *dst --> src
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\to%d --> o%d\n", h.ref(odst), osrc)
+		}
+	} else {
+		// We don't interpret store-with-offset.
+		// See discussion of soundness at markIndirectNodes.
+	}
+}
+
+// dst = &src.offset
+func (c *offsetAddrConstraint) presolve(h *hvn) {
+	// Give each distinct (addr, offset) pair a fresh PE label.
+	// The cache performs CSE, effectively.
+	key := offsetAddr{c.src, c.offset}
+	label, ok := h.offsetAddrLabels[key]
+	if !ok {
+		label = h.nextLabel()
+		h.offsetAddrLabels[key] = label
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\tcreate p%d: {&n%d.#%d}\n",
+				label, c.src, c.offset)
+		}
+	}
+
+	// Assign dst this label.
+	h.onodes[c.dst].peLabels.Insert(int(label))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d has p%d\n", c.dst, label)
+	}
+}
+
+// dst = src.(typ)  where typ is an interface
+func (c *typeFilterConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.dst), "typeFilter result")
+}
+
+// dst = src.(typ)  where typ is concrete
+func (c *untagConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	for end := odst + onodeid(h.a.sizeof(c.typ)); odst < end; odst++ {
+		h.markIndirect(odst, "untag result")
+	}
+}
+
+// dst = src.method(c.params...)
+func (c *invokeConstraint) presolve(h *hvn) {
+	// All methods are address-taken functions, so
+	// their formal P-blocks were already marked indirect.
+
+	// Mark the caller's targets node as indirect.
+	sig := c.method.Type().(*types.Signature)
+	id := c.params
+	h.markIndirect(onodeid(c.params), "invoke targets node")
+	id++
+
+	id += nodeid(h.a.sizeof(sig.Params()))
+
+	// Mark the caller's R-block as indirect.
+	end := id + nodeid(h.a.sizeof(sig.Results()))
+	for id < end {
+		h.markIndirect(onodeid(id), "invoke R-block")
+		id++
+	}
+}
+
+// markIndirectNodes marks as indirect nodes whose points-to relations
+// are not entirely captured by the offline graph, including:
+//
+//    (a) All address-taken nodes (including the following nodes within
+//        the same object).  This is described in the paper.
+//
+// The most subtle cause of indirect nodes is the generation of
+// store-with-offset constraints since the offline graph doesn't
+// represent them.  A global audit of constraint generation reveals the
+// following uses of store-with-offset:
+//
+//    (b) genDynamicCall, for P-blocks of dynamically called functions,
+//        to which dynamic copy edges will be added to them during
+//        solving: from storeConstraint for standalone functions,
+//        and from invokeConstraint for methods.
+//        All such P-blocks must be marked indirect.
+//    (c) MakeUpdate, to update the value part of a map object.
+//        All MakeMap objects's value parts must be marked indirect.
+//    (d) copyElems, to update the destination array.
+//        All array elements must be marked indirect.
+//
+// Not all indirect marking happens here.  ref() nodes are marked
+// indirect at construction, and each constraint's presolve() method may
+// mark additional nodes.
+//
+func (h *hvn) markIndirectNodes() {
+	// (a) all address-taken nodes, plus all nodes following them
+	//     within the same object, since these may be indirectly
+	//     stored or address-taken.
+	for _, c := range h.a.constraints {
+		if c, ok := c.(*addrConstraint); ok {
+			start := h.a.enclosingObj(c.src)
+			end := start + nodeid(h.a.nodes[start].obj.size)
+			for id := c.src; id < end; id++ {
+				h.markIndirect(onodeid(id), "A-T object")
+			}
+		}
+	}
+
+	// (b) P-blocks of all address-taken functions.
+	for id := 0; id < h.N; id++ {
+		obj := h.a.nodes[id].obj
+
+		// TODO(adonovan): opt: if obj.cgn.fn is a method and
+		// obj.cgn is not its shared contour, this is an
+		// "inlined" static method call.  We needn't consider it
+		// address-taken since no invokeConstraint will affect it.
+
+		if obj != nil && obj.flags&otFunction != 0 && h.a.atFuncs[obj.cgn.fn] {
+			// address-taken function
+			if debugHVNVerbose && h.log != nil {
+				fmt.Fprintf(h.log, "n%d is address-taken: %s\n", id, obj.cgn.fn)
+			}
+			h.markIndirect(onodeid(id), "A-T func identity")
+			id++
+			sig := obj.cgn.fn.Signature
+			psize := h.a.sizeof(sig.Params())
+			if sig.Recv() != nil {
+				psize += h.a.sizeof(sig.Recv().Type())
+			}
+			for end := id + int(psize); id < end; id++ {
+				h.markIndirect(onodeid(id), "A-T func P-block")
+			}
+			id--
+			continue
+		}
+	}
+
+	// (c) all map objects' value fields.
+	for _, id := range h.a.mapValues {
+		h.markIndirect(onodeid(id), "makemap.value")
+	}
+
+	// (d) all array element objects.
+	// TODO(adonovan): opt: can we do better?
+	for id := 0; id < h.N; id++ {
+		// Identity node for an object of array type?
+		if tArray, ok := h.a.nodes[id].typ.(*types.Array); ok {
+			// Mark the array element nodes indirect.
+			// (Skip past the identity field.)
+			for _ = range h.a.flatten(tArray.Elem()) {
+				id++
+				h.markIndirect(onodeid(id), "array elem")
+			}
+		}
+	}
+}
+
+func (h *hvn) markIndirect(oid onodeid, comment string) {
+	h.onodes[oid].indirect = true
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d is indirect: %s\n", oid, comment)
+	}
+}
+
+// Adds an edge dst-->src.
+// Note the unusual convention: edges are dependency (contraflow) edges.
+func (h *hvn) addEdge(odst, osrc onodeid) {
+	h.onodes[odst].edges.Insert(int(osrc))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d --> o%d\n", odst, osrc)
+	}
+}
+
+func (h *hvn) addImplicitEdge(odst, osrc onodeid) {
+	h.onodes[odst].implicit.Insert(int(osrc))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d ~~> o%d\n", odst, osrc)
+	}
+}
+
+// visit implements the depth-first search of Tarjan's SCC algorithm.
+// Precondition: x is canonical.
+func (h *hvn) visit(x onodeid) {
+	h.checkCanonical(x)
+	xo := h.onodes[x]
+	xo.index = h.index
+	xo.lowlink = h.index
+	h.index++
+
+	h.stack = append(h.stack, x) // push
+	assert(xo.scc == 0, "node revisited")
+	xo.scc = -1
+
+	var deps []int
+	deps = xo.edges.AppendTo(deps)
+	deps = xo.implicit.AppendTo(deps)
+
+	for _, y := range deps {
+		// Loop invariant: x is canonical.
+
+		y := h.find(onodeid(y))
+
+		if x == y {
+			continue // nodes already coalesced
+		}
+
+		xo := h.onodes[x]
+		yo := h.onodes[y]
+
+		switch {
+		case yo.scc > 0:
+			// y is already a collapsed SCC
+
+		case yo.scc < 0:
+			// y is on the stack, and thus in the current SCC.
+			if yo.index < xo.lowlink {
+				xo.lowlink = yo.index
+			}
+
+		default:
+			// y is unvisited; visit it now.
+			h.visit(y)
+			// Note: x and y are now non-canonical.
+
+			x = h.find(onodeid(x))
+
+			if yo.lowlink < xo.lowlink {
+				xo.lowlink = yo.lowlink
+			}
+		}
+	}
+	h.checkCanonical(x)
+
+	// Is x the root of an SCC?
+	if xo.lowlink == xo.index {
+		// Coalesce all nodes in the SCC.
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "scc o%d\n", x)
+		}
+		for {
+			// Pop y from stack.
+			i := len(h.stack) - 1
+			y := h.stack[i]
+			h.stack = h.stack[:i]
+
+			h.checkCanonical(x)
+			xo := h.onodes[x]
+			h.checkCanonical(y)
+			yo := h.onodes[y]
+
+			if xo == yo {
+				// SCC is complete.
+				xo.scc = 1
+				h.labelSCC(x)
+				break
+			}
+			h.coalesce(x, y)
+		}
+	}
+}
+
+// Precondition: x is canonical.
+func (h *hvn) labelSCC(x onodeid) {
+	h.checkCanonical(x)
+	xo := h.onodes[x]
+	xpe := &xo.peLabels
+
+	// All indirect nodes get new labels.
+	if xo.indirect {
+		label := h.nextLabel()
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\tcreate p%d: indirect SCC\n", label)
+			fmt.Fprintf(h.log, "\to%d has p%d\n", x, label)
+		}
+
+		// Remove pre-labeling, in case a direct pre-labeled node was
+		// merged with an indirect one.
+		xpe.Clear()
+		xpe.Insert(int(label))
+
+		return
+	}
+
+	// Invariant: all peLabels sets are non-empty.
+	// Those that are logically empty contain zero as their sole element.
+	// No other sets contains zero.
+
+	// Find all labels coming in to the coalesced SCC node.
+	for _, y := range xo.edges.AppendTo(nil) {
+		y := h.find(onodeid(y))
+		if y == x {
+			continue // already coalesced
+		}
+		ype := &h.onodes[y].peLabels
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\tedge from o%d = %s\n", y, ype)
+		}
+
+		if ype.IsEmpty() {
+			if debugHVNVerbose && h.log != nil {
+				fmt.Fprintf(h.log, "\tnode has no PE label\n")
+			}
+		}
+		assert(!ype.IsEmpty(), "incoming node has no PE label")
+
+		if ype.Has(0) {
+			// {0} represents a non-pointer.
+			assert(ype.Len() == 1, "PE set contains {0, ...}")
+		} else {
+			xpe.UnionWith(ype)
+		}
+	}
+
+	switch xpe.Len() {
+	case 0:
+		// SCC has no incoming non-zero PE labels: it is a non-pointer.
+		xpe.Insert(0)
+
+	case 1:
+		// already a singleton
+
+	default:
+		// SCC has multiple incoming non-zero PE labels.
+		// Find the canonical label representing this set.
+		// We use String() as a fingerprint consistent with Equals().
+		key := xpe.String()
+		label, ok := h.hvnLabel[key]
+		if !ok {
+			label = h.nextLabel()
+			if debugHVNVerbose && h.log != nil {
+				fmt.Fprintf(h.log, "\tcreate p%d: union %s\n", label, xpe.String())
+			}
+			h.hvnLabel[key] = label
+		}
+		xpe.Clear()
+		xpe.Insert(int(label))
+	}
+
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d has p%d\n", x, xpe.Min())
+	}
+}
+
+// coalesce combines two nodes in the offline constraint graph.
+// Precondition: x and y are canonical.
+func (h *hvn) coalesce(x, y onodeid) {
+	xo := h.onodes[x]
+	yo := h.onodes[y]
+
+	// x becomes y's canonical representative.
+	yo.rep = x
+
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\tcoalesce o%d into o%d\n", y, x)
+	}
+
+	// x accumulates y's edges.
+	xo.edges.UnionWith(&yo.edges)
+	yo.edges.Clear()
+
+	// x accumulates y's implicit edges.
+	xo.implicit.UnionWith(&yo.implicit)
+	yo.implicit.Clear()
+
+	// x accumulates y's pointer-equivalence labels.
+	xo.peLabels.UnionWith(&yo.peLabels)
+	yo.peLabels.Clear()
+
+	// x accumulates y's indirect flag.
+	if yo.indirect {
+		xo.indirect = true
+	}
+}
+
+// simplify computes a degenerate renumbering of nodeids from the PE
+// labels assigned by the hvn, and uses it to simplify the main
+// constraint graph, eliminating non-pointer nodes and duplicate
+// constraints.
+//
+func (h *hvn) simplify() {
+	// canon maps each peLabel to its canonical main node.
+	canon := make([]nodeid, h.label)
+	for i := range canon {
+		canon[i] = nodeid(h.N) // indicates "unset"
+	}
+
+	// mapping maps each main node index to the index of the canonical node.
+	mapping := make([]nodeid, len(h.a.nodes))
+
+	for id := range h.a.nodes {
+		id := nodeid(id)
+		if id == 0 {
+			canon[0] = 0
+			mapping[0] = 0
+			continue
+		}
+		oid := h.find(onodeid(id))
+		peLabels := &h.onodes[oid].peLabels
+		assert(peLabels.Len() == 1, "PE class is not a singleton")
+		label := peLabel(peLabels.Min())
+
+		canonId := canon[label]
+		if canonId == nodeid(h.N) {
+			// id becomes the representative of the PE label.
+			canonId = id
+			canon[label] = canonId
+
+			if h.a.log != nil {
+				fmt.Fprintf(h.a.log, "\tpts(n%d) is canonical : \t(%s)\n",
+					id, h.a.nodes[id].typ)
+			}
+
+		} else {
+			// Link the solver states for the two nodes.
+			assert(h.a.nodes[canonId].solve != nil, "missing solver state")
+			h.a.nodes[id].solve = h.a.nodes[canonId].solve
+
+			if h.a.log != nil {
+				// TODO(adonovan): debug: reorganize the log so it prints
+				// one line:
+				// 	pe y = x1, ..., xn
+				// for each canonical y.  Requires allocation.
+				fmt.Fprintf(h.a.log, "\tpts(n%d) = pts(n%d) : %s\n",
+					id, canonId, h.a.nodes[id].typ)
+			}
+		}
+
+		mapping[id] = canonId
+	}
+
+	// Renumber the constraints, eliminate duplicates, and eliminate
+	// any containing non-pointers (n0).
+	addrs := make(map[addrConstraint]bool)
+	copys := make(map[copyConstraint]bool)
+	loads := make(map[loadConstraint]bool)
+	stores := make(map[storeConstraint]bool)
+	offsetAddrs := make(map[offsetAddrConstraint]bool)
+	untags := make(map[untagConstraint]bool)
+	typeFilters := make(map[typeFilterConstraint]bool)
+	invokes := make(map[invokeConstraint]bool)
+
+	nbefore := len(h.a.constraints)
+	cc := h.a.constraints[:0] // in-situ compaction
+	for _, c := range h.a.constraints {
+		// Renumber.
+		switch c := c.(type) {
+		case *addrConstraint:
+			// Don't renumber c.src since it is the label of
+			// an addressable object and will appear in PT sets.
+			c.dst = mapping[c.dst]
+		default:
+			c.renumber(mapping)
+		}
+
+		if c.ptr() == 0 {
+			continue // skip: constraint attached to non-pointer
+		}
+
+		var dup bool
+		switch c := c.(type) {
+		case *addrConstraint:
+			_, dup = addrs[*c]
+			addrs[*c] = true
+
+		case *copyConstraint:
+			if c.src == c.dst {
+				continue // skip degenerate copies
+			}
+			if c.src == 0 {
+				continue // skip copy from non-pointer
+			}
+			_, dup = copys[*c]
+			copys[*c] = true
+
+		case *loadConstraint:
+			if c.src == 0 {
+				continue // skip load from non-pointer
+			}
+			_, dup = loads[*c]
+			loads[*c] = true
+
+		case *storeConstraint:
+			if c.src == 0 {
+				continue // skip store from non-pointer
+			}
+			_, dup = stores[*c]
+			stores[*c] = true
+
+		case *offsetAddrConstraint:
+			if c.src == 0 {
+				continue // skip offset from non-pointer
+			}
+			_, dup = offsetAddrs[*c]
+			offsetAddrs[*c] = true
+
+		case *untagConstraint:
+			if c.src == 0 {
+				continue // skip untag of non-pointer
+			}
+			_, dup = untags[*c]
+			untags[*c] = true
+
+		case *typeFilterConstraint:
+			if c.src == 0 {
+				continue // skip filter of non-pointer
+			}
+			_, dup = typeFilters[*c]
+			typeFilters[*c] = true
+
+		case *invokeConstraint:
+			if c.params == 0 {
+				panic("non-pointer invoke.params")
+			}
+			if c.iface == 0 {
+				continue // skip invoke on non-pointer
+			}
+			_, dup = invokes[*c]
+			invokes[*c] = true
+
+		default:
+			// We don't bother de-duping advanced constraints
+			// (e.g. reflection) since they are uncommon.
+
+			// Eliminate constraints containing non-pointer nodeids.
+			//
+			// We use reflection to find the fields to avoid
+			// adding yet another method to constraint.
+			//
+			// TODO(adonovan): experiment with a constraint
+			// method that returns a slice of pointers to
+			// nodeids fields to enable uniform iteration;
+			// the renumber() method could be removed and
+			// implemented using the new one.
+			//
+			// TODO(adonovan): opt: this is unsound since
+			// some constraints still have an effect if one
+			// of the operands is zero: rVCall, rVMapIndex,
+			// rvSetMapIndex.  Handle them specially.
+			rtNodeid := reflect.TypeOf(nodeid(0))
+			x := reflect.ValueOf(c).Elem()
+			for i, nf := 0, x.NumField(); i < nf; i++ {
+				f := x.Field(i)
+				if f.Type() == rtNodeid {
+					if f.Uint() == 0 {
+						dup = true // skip it
+						break
+					}
+				}
+			}
+		}
+		if dup {
+			continue // skip duplicates
+		}
+
+		cc = append(cc, c)
+	}
+	h.a.constraints = cc
+
+	if h.log != nil {
+		fmt.Fprintf(h.log, "#constraints: was %d, now %d\n", nbefore, len(h.a.constraints))
+	}
+}
+
+// find returns the canonical onodeid for x.
+// (The onodes form a disjoint set forest.)
+func (h *hvn) find(x onodeid) onodeid {
+	// TODO(adonovan): opt: this is a CPU hotspot.  Try "union by rank".
+	xo := h.onodes[x]
+	rep := xo.rep
+	if rep != x {
+		rep = h.find(rep) // simple path compression
+		xo.rep = rep
+	}
+	return rep
+}
+
+func (h *hvn) checkCanonical(x onodeid) {
+	if debugHVN {
+		assert(x == h.find(x), "not canonical")
+	}
+}
+
+func assert(p bool, msg string) {
+	if debugHVN && !p {
+		panic("assertion failed: " + msg)
+	}
+}
diff --git a/third_party/go.tools/go/pointer/intrinsics.go b/third_party/go.tools/go/pointer/intrinsics.go
new file mode 100644
index 0000000..866cd0b
--- /dev/null
+++ b/third_party/go.tools/go/pointer/intrinsics.go
@@ -0,0 +1,380 @@
+// Copyright 2013 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 pointer
+
+// This package defines the treatment of intrinsics, i.e. library
+// functions requiring special analytical treatment.
+//
+// Most of these are C or assembly functions, but even some Go
+// functions require may special treatment if the analysis completely
+// replaces the implementation of an API such as reflection.
+
+// TODO(adonovan): support a means of writing analytic summaries in
+// the target code, so that users can summarise the effects of their
+// own C functions using a snippet of Go.
+
+import (
+	"fmt"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// Instances of 'intrinsic' generate analysis constraints for calls to
+// intrinsic functions.
+// Implementations may exploit information from the calling site
+// via cgn.callersite; for shared contours this is nil.
+type intrinsic func(a *analysis, cgn *cgnode)
+
+// Initialized in explicit init() to defeat (spurious) initialization
+// cycle error.
+var intrinsicsByName = make(map[string]intrinsic)
+
+func init() {
+	// Key strings are from Function.String().
+	// That little dot ۰ is an Arabic zero numeral (U+06F0),
+	// categories [Nd].
+	for name, fn := range map[string]intrinsic{
+		// Other packages.
+		"bytes.Equal":                           ext۰NoEffect,
+		"bytes.IndexByte":                       ext۰NoEffect,
+		"crypto/aes.decryptBlockAsm":            ext۰NoEffect,
+		"crypto/aes.encryptBlockAsm":            ext۰NoEffect,
+		"crypto/aes.expandKeyAsm":               ext۰NoEffect,
+		"crypto/aes.hasAsm":                     ext۰NoEffect,
+		"crypto/md5.block":                      ext۰NoEffect,
+		"crypto/rc4.xorKeyStream":               ext۰NoEffect,
+		"crypto/sha1.block":                     ext۰NoEffect,
+		"crypto/sha256.block":                   ext۰NoEffect,
+		"hash/crc32.castagnoliSSE42":            ext۰NoEffect,
+		"hash/crc32.haveSSE42":                  ext۰NoEffect,
+		"math.Abs":                              ext۰NoEffect,
+		"math.Acos":                             ext۰NoEffect,
+		"math.Asin":                             ext۰NoEffect,
+		"math.Atan":                             ext۰NoEffect,
+		"math.Atan2":                            ext۰NoEffect,
+		"math.Ceil":                             ext۰NoEffect,
+		"math.Cos":                              ext۰NoEffect,
+		"math.Dim":                              ext۰NoEffect,
+		"math.Exp":                              ext۰NoEffect,
+		"math.Exp2":                             ext۰NoEffect,
+		"math.Expm1":                            ext۰NoEffect,
+		"math.Float32bits":                      ext۰NoEffect,
+		"math.Float32frombits":                  ext۰NoEffect,
+		"math.Float64bits":                      ext۰NoEffect,
+		"math.Float64frombits":                  ext۰NoEffect,
+		"math.Floor":                            ext۰NoEffect,
+		"math.Frexp":                            ext۰NoEffect,
+		"math.Hypot":                            ext۰NoEffect,
+		"math.Ldexp":                            ext۰NoEffect,
+		"math.Log":                              ext۰NoEffect,
+		"math.Log10":                            ext۰NoEffect,
+		"math.Log1p":                            ext۰NoEffect,
+		"math.Log2":                             ext۰NoEffect,
+		"math.Max":                              ext۰NoEffect,
+		"math.Min":                              ext۰NoEffect,
+		"math.Mod":                              ext۰NoEffect,
+		"math.Modf":                             ext۰NoEffect,
+		"math.Remainder":                        ext۰NoEffect,
+		"math.Sin":                              ext۰NoEffect,
+		"math.Sincos":                           ext۰NoEffect,
+		"math.Sqrt":                             ext۰NoEffect,
+		"math.Tan":                              ext۰NoEffect,
+		"math.Trunc":                            ext۰NoEffect,
+		"math/big.addMulVVW":                    ext۰NoEffect,
+		"math/big.addVV":                        ext۰NoEffect,
+		"math/big.addVW":                        ext۰NoEffect,
+		"math/big.bitLen":                       ext۰NoEffect,
+		"math/big.divWVW":                       ext۰NoEffect,
+		"math/big.divWW":                        ext۰NoEffect,
+		"math/big.mulAddVWW":                    ext۰NoEffect,
+		"math/big.mulWW":                        ext۰NoEffect,
+		"math/big.shlVU":                        ext۰NoEffect,
+		"math/big.shrVU":                        ext۰NoEffect,
+		"math/big.subVV":                        ext۰NoEffect,
+		"math/big.subVW":                        ext۰NoEffect,
+		"net.runtime_Semacquire":                ext۰NoEffect,
+		"net.runtime_Semrelease":                ext۰NoEffect,
+		"net.runtime_pollClose":                 ext۰NoEffect,
+		"net.runtime_pollOpen":                  ext۰NoEffect,
+		"net.runtime_pollReset":                 ext۰NoEffect,
+		"net.runtime_pollServerInit":            ext۰NoEffect,
+		"net.runtime_pollSetDeadline":           ext۰NoEffect,
+		"net.runtime_pollUnblock":               ext۰NoEffect,
+		"net.runtime_pollWait":                  ext۰NoEffect,
+		"net.runtime_pollWaitCanceled":          ext۰NoEffect,
+		"os.epipecheck":                         ext۰NoEffect,
+		"runtime.BlockProfile":                  ext۰NoEffect,
+		"runtime.Breakpoint":                    ext۰NoEffect,
+		"runtime.CPUProfile":                    ext۰NoEffect, // good enough
+		"runtime.Caller":                        ext۰NoEffect,
+		"runtime.Callers":                       ext۰NoEffect, // good enough
+		"runtime.FuncForPC":                     ext۰NoEffect,
+		"runtime.GC":                            ext۰NoEffect,
+		"runtime.GOMAXPROCS":                    ext۰NoEffect,
+		"runtime.Goexit":                        ext۰NoEffect,
+		"runtime.GoroutineProfile":              ext۰NoEffect,
+		"runtime.Gosched":                       ext۰NoEffect,
+		"runtime.MemProfile":                    ext۰NoEffect,
+		"runtime.NumCPU":                        ext۰NoEffect,
+		"runtime.NumGoroutine":                  ext۰NoEffect,
+		"runtime.ReadMemStats":                  ext۰NoEffect,
+		"runtime.SetBlockProfileRate":           ext۰NoEffect,
+		"runtime.SetCPUProfileRate":             ext۰NoEffect,
+		"runtime.SetFinalizer":                  ext۰runtime۰SetFinalizer,
+		"runtime.Stack":                         ext۰NoEffect,
+		"runtime.ThreadCreateProfile":           ext۰NoEffect,
+		"runtime.cstringToGo":                   ext۰NoEffect,
+		"runtime.funcentry_go":                  ext۰NoEffect,
+		"runtime.funcline_go":                   ext۰NoEffect,
+		"runtime.funcname_go":                   ext۰NoEffect,
+		"runtime.getgoroot":                     ext۰NoEffect,
+		"runtime/pprof.runtime_cyclesPerSecond": ext۰NoEffect,
+		"strings.IndexByte":                     ext۰NoEffect,
+		"sync.runtime_Semacquire":               ext۰NoEffect,
+		"sync.runtime_Semrelease":               ext۰NoEffect,
+		"sync.runtime_Syncsemacquire":           ext۰NoEffect,
+		"sync.runtime_Syncsemcheck":             ext۰NoEffect,
+		"sync.runtime_Syncsemrelease":           ext۰NoEffect,
+		"sync.runtime_procPin":                  ext۰NoEffect,
+		"sync.runtime_procUnpin":                ext۰NoEffect,
+		"sync.runtime_registerPool":             ext۰NoEffect,
+		"sync/atomic.AddInt32":                  ext۰NoEffect,
+		"sync/atomic.AddInt64":                  ext۰NoEffect,
+		"sync/atomic.AddUint32":                 ext۰NoEffect,
+		"sync/atomic.AddUint64":                 ext۰NoEffect,
+		"sync/atomic.AddUintptr":                ext۰NoEffect,
+		"sync/atomic.CompareAndSwapInt32":       ext۰NoEffect,
+		"sync/atomic.CompareAndSwapUint32":      ext۰NoEffect,
+		"sync/atomic.CompareAndSwapUint64":      ext۰NoEffect,
+		"sync/atomic.CompareAndSwapUintptr":     ext۰NoEffect,
+		"sync/atomic.LoadInt32":                 ext۰NoEffect,
+		"sync/atomic.LoadInt64":                 ext۰NoEffect,
+		"sync/atomic.LoadPointer":               ext۰NoEffect, // ignore unsafe.Pointers
+		"sync/atomic.LoadUint32":                ext۰NoEffect,
+		"sync/atomic.LoadUint64":                ext۰NoEffect,
+		"sync/atomic.LoadUintptr":               ext۰NoEffect,
+		"sync/atomic.StoreInt32":                ext۰NoEffect,
+		"sync/atomic.StorePointer":              ext۰NoEffect, // ignore unsafe.Pointers
+		"sync/atomic.StoreUint32":               ext۰NoEffect,
+		"sync/atomic.StoreUintptr":              ext۰NoEffect,
+		"syscall.Close":                         ext۰NoEffect,
+		"syscall.Exit":                          ext۰NoEffect,
+		"syscall.Getpid":                        ext۰NoEffect,
+		"syscall.Getwd":                         ext۰NoEffect,
+		"syscall.Kill":                          ext۰NoEffect,
+		"syscall.RawSyscall":                    ext۰NoEffect,
+		"syscall.RawSyscall6":                   ext۰NoEffect,
+		"syscall.Syscall":                       ext۰NoEffect,
+		"syscall.Syscall6":                      ext۰NoEffect,
+		"syscall.runtime_AfterFork":             ext۰NoEffect,
+		"syscall.runtime_BeforeFork":            ext۰NoEffect,
+		"syscall.setenv_c":                      ext۰NoEffect,
+		"time.Sleep":                            ext۰NoEffect,
+		"time.now":                              ext۰NoEffect,
+		"time.startTimer":                       ext۰time۰startTimer,
+		"time.stopTimer":                        ext۰NoEffect,
+	} {
+		intrinsicsByName[name] = fn
+	}
+}
+
+// findIntrinsic returns the constraint generation function for an
+// intrinsic function fn, or nil if the function should be handled normally.
+//
+func (a *analysis) findIntrinsic(fn *ssa.Function) intrinsic {
+	// Consult the *Function-keyed cache.
+	// A cached nil indicates a normal non-intrinsic function.
+	impl, ok := a.intrinsics[fn]
+	if !ok {
+		impl = intrinsicsByName[fn.String()] // may be nil
+
+		if a.isReflect(fn) {
+			if !a.config.Reflection {
+				impl = ext۰NoEffect // reflection disabled
+			} else if impl == nil {
+				// Ensure all "reflect" code is treated intrinsically.
+				impl = ext۰NotYetImplemented
+			}
+		}
+
+		a.intrinsics[fn] = impl
+	}
+	return impl
+}
+
+// isReflect reports whether fn belongs to the "reflect" package.
+func (a *analysis) isReflect(fn *ssa.Function) bool {
+	if a.reflectValueObj == nil {
+		return false // "reflect" package not loaded
+	}
+	reflectPackage := a.reflectValueObj.Pkg()
+	if fn.Pkg != nil && fn.Pkg.Object == reflectPackage {
+		return true
+	}
+	// Synthetic wrappers have a nil Pkg, so they slip through the
+	// previous check.  Check the receiver package.
+	// TODO(adonovan): should synthetic wrappers have a non-nil Pkg?
+	if recv := fn.Signature.Recv(); recv != nil {
+		if named, ok := deref(recv.Type()).(*types.Named); ok {
+			if named.Obj().Pkg() == reflectPackage {
+				return true // e.g. wrapper of (reflect.Value).f
+			}
+		}
+	}
+	return false
+}
+
+// A trivial intrinsic suitable for any function that does not:
+// 1) induce aliases between its arguments or any global variables;
+// 2) call any functions; or
+// 3) create any labels.
+//
+// Many intrinsics (such as CompareAndSwapInt32) have a fourth kind of
+// effect: loading or storing through a pointer.  Though these could
+// be significant, we deliberately ignore them because they are
+// generally not worth the effort.
+//
+// We sometimes violate condition #3 if the function creates only
+// non-function labels, as the control-flow graph is still sound.
+//
+func ext۰NoEffect(a *analysis, cgn *cgnode) {}
+
+func ext۰NotYetImplemented(a *analysis, cgn *cgnode) {
+	fn := cgn.fn
+	a.warnf(fn.Pos(), "unsound: intrinsic treatment of %s not yet implemented", fn)
+}
+
+// ---------- func runtime.SetFinalizer(x, f interface{}) ----------
+
+// runtime.SetFinalizer(x, f)
+type runtimeSetFinalizerConstraint struct {
+	targets nodeid // (indirect)
+	f       nodeid // (ptr)
+	x       nodeid
+}
+
+func (c *runtimeSetFinalizerConstraint) ptr() nodeid { return c.f }
+func (c *runtimeSetFinalizerConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.targets), "SetFinalizer.targets")
+}
+func (c *runtimeSetFinalizerConstraint) renumber(mapping []nodeid) {
+	c.targets = mapping[c.targets]
+	c.f = mapping[c.f]
+	c.x = mapping[c.x]
+}
+
+func (c *runtimeSetFinalizerConstraint) String() string {
+	return fmt.Sprintf("runtime.SetFinalizer(n%d, n%d)", c.x, c.f)
+}
+
+func (c *runtimeSetFinalizerConstraint) solve(a *analysis, delta *nodeset) {
+	for _, fObj := range delta.AppendTo(a.deltaSpace) {
+		tDyn, f, indirect := a.taggedValue(nodeid(fObj))
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSig, ok := tDyn.Underlying().(*types.Signature)
+		if !ok {
+			continue // not a function
+		}
+		if tSig.Recv() != nil {
+			panic(tSig)
+		}
+		if tSig.Params().Len() != 1 {
+			continue //  not a unary function
+		}
+
+		// Extract x to tmp.
+		tx := tSig.Params().At(0).Type()
+		tmp := a.addNodes(tx, "SetFinalizer.tmp")
+		a.typeAssert(tx, tmp, c.x, false)
+
+		// Call f(tmp).
+		a.store(f, tmp, 1, a.sizeof(tx))
+
+		// Add dynamic call target.
+		if a.onlineCopy(c.targets, f) {
+			a.addWork(c.targets)
+		}
+	}
+}
+
+func ext۰runtime۰SetFinalizer(a *analysis, cgn *cgnode) {
+	// This is the shared contour, used for dynamic calls.
+	targets := a.addOneNode(tInvalid, "SetFinalizer.targets", nil)
+	cgn.sites = append(cgn.sites, &callsite{targets: targets})
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&runtimeSetFinalizerConstraint{
+		targets: targets,
+		x:       params,
+		f:       params + 1,
+	})
+}
+
+// ---------- func time.startTimer(t *runtimeTimer) ----------
+
+// time.StartTimer(t)
+type timeStartTimerConstraint struct {
+	targets nodeid // (indirect)
+	t       nodeid // (ptr)
+}
+
+func (c *timeStartTimerConstraint) ptr() nodeid { return c.t }
+func (c *timeStartTimerConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.targets), "StartTimer.targets")
+}
+func (c *timeStartTimerConstraint) renumber(mapping []nodeid) {
+	c.targets = mapping[c.targets]
+	c.t = mapping[c.t]
+}
+
+func (c *timeStartTimerConstraint) String() string {
+	return fmt.Sprintf("time.startTimer(n%d)", c.t)
+}
+
+func (c *timeStartTimerConstraint) solve(a *analysis, delta *nodeset) {
+	for _, tObj := range delta.AppendTo(a.deltaSpace) {
+		t := nodeid(tObj)
+
+		// We model startTimer as if it was defined thus:
+		// 	func startTimer(t *runtimeTimer) { t.f(t.arg) }
+
+		// We hard-code the field offsets of time.runtimeTimer:
+		// type runtimeTimer struct {
+		//  0     __identity__
+		//  1    i      int32
+		//  2    when   int64
+		//  3    period int64
+		//  4    f      func(int64, interface{})
+		//  5    arg    interface{}
+		// }
+		f := t + 4
+		arg := t + 5
+
+		// store t.arg to t.f.params[0]
+		// (offset 1 => skip identity)
+		a.store(f, arg, 1, 1)
+
+		// Add dynamic call target.
+		if a.onlineCopy(c.targets, f) {
+			a.addWork(c.targets)
+		}
+	}
+}
+
+func ext۰time۰startTimer(a *analysis, cgn *cgnode) {
+	// This is the shared contour, used for dynamic calls.
+	targets := a.addOneNode(tInvalid, "startTimer.targets", nil)
+	cgn.sites = append(cgn.sites, &callsite{targets: targets})
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&timeStartTimerConstraint{
+		targets: targets,
+		t:       params,
+	})
+}
diff --git a/third_party/go.tools/go/pointer/labels.go b/third_party/go.tools/go/pointer/labels.go
new file mode 100644
index 0000000..aaa8397
--- /dev/null
+++ b/third_party/go.tools/go/pointer/labels.go
@@ -0,0 +1,152 @@
+// Copyright 2013 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 pointer
+
+import (
+	"fmt"
+	"go/token"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// A Label is an entity that may be pointed to by a pointer, map,
+// channel, 'func', slice or interface.
+//
+// Labels include:
+//      - functions
+//      - globals
+//      - tagged objects, representing interfaces and reflect.Values
+//      - arrays created by conversions (e.g. []byte("foo"), []byte(s))
+//      - stack- and heap-allocated variables (including composite literals)
+//      - channels, maps and arrays created by make()
+//      - intrinsic or reflective operations that allocate (e.g. append, reflect.New)
+//      - intrinsic objects, e.g. the initial array behind os.Args.
+//      - and their subelements, e.g. "alloc.y[*].z"
+//
+// Labels are so varied that they defy good generalizations;
+// some have no value, no callgraph node, or no position.
+// Many objects have types that are inexpressible in Go:
+// maps, channels, functions, tagged objects.
+//
+// At most one of Value() or ReflectType() may return non-nil.
+//
+type Label struct {
+	obj        *object    // the addressable memory location containing this label
+	subelement *fieldInfo // subelement path within obj, e.g. ".a.b[*].c"
+}
+
+// Value returns the ssa.Value that allocated this label's object, if any.
+func (l Label) Value() ssa.Value {
+	val, _ := l.obj.data.(ssa.Value)
+	return val
+}
+
+// ReflectType returns the type represented by this label if it is an
+// reflect.rtype instance object or *reflect.rtype-tagged object.
+//
+func (l Label) ReflectType() types.Type {
+	rtype, _ := l.obj.data.(types.Type)
+	return rtype
+}
+
+// Path returns the path to the subelement of the object containing
+// this label.  For example, ".x[*].y".
+//
+func (l Label) Path() string {
+	return l.subelement.path()
+}
+
+// Pos returns the position of this label, if known, zero otherwise.
+func (l Label) Pos() token.Pos {
+	switch data := l.obj.data.(type) {
+	case ssa.Value:
+		return data.Pos()
+	case types.Type:
+		if nt, ok := deref(data).(*types.Named); ok {
+			return nt.Obj().Pos()
+		}
+	}
+	if cgn := l.obj.cgn; cgn != nil {
+		return cgn.fn.Pos()
+	}
+	return token.NoPos
+}
+
+// String returns the printed form of this label.
+//
+// Examples:                                    Object type:
+//      x                                       (a variable)
+//      (sync.Mutex).Lock                       (a function)
+//      convert                                 (array created by conversion)
+//      makemap                                 (map allocated via make)
+//      makechan                                (channel allocated via make)
+//      makeinterface                           (tagged object allocated by makeinterface)
+//      <alloc in reflect.Zero>                 (allocation in instrinsic)
+//      sync.Mutex                              (a reflect.rtype instance)
+//      <command-line arguments>                (an intrinsic object)
+//
+// Labels within compound objects have subelement paths:
+//      x.y[*].z                                (a struct variable, x)
+//      append.y[*].z                           (array allocated by append)
+//      makeslice.y[*].z                        (array allocated via make)
+//
+// TODO(adonovan): expose func LabelString(*types.Package, Label).
+//
+func (l Label) String() string {
+	var s string
+	switch v := l.obj.data.(type) {
+	case types.Type:
+		return v.String()
+
+	case string:
+		s = v // an intrinsic object (e.g. os.Args[*])
+
+	case nil:
+		if l.obj.cgn != nil {
+			// allocation by intrinsic or reflective operation
+			s = fmt.Sprintf("<alloc in %s>", l.obj.cgn.fn)
+		} else {
+			s = "<unknown>" // should be unreachable
+		}
+
+	case *ssa.Function:
+		s = v.String()
+
+	case *ssa.Global:
+		s = v.String()
+
+	case *ssa.Const:
+		s = v.Name()
+
+	case *ssa.Alloc:
+		s = v.Comment
+		if s == "" {
+			s = "alloc"
+		}
+
+	case *ssa.Call:
+		// Currently only calls to append can allocate objects.
+		if v.Call.Value.(*ssa.Builtin).Object().Name() != "append" {
+			panic("unhandled *ssa.Call label: " + v.Name())
+		}
+		s = "append"
+
+	case *ssa.MakeMap, *ssa.MakeChan, *ssa.MakeSlice, *ssa.Convert:
+		s = strings.ToLower(strings.TrimPrefix(fmt.Sprintf("%T", v), "*ssa."))
+
+	case *ssa.MakeInterface:
+		// MakeInterface is usually implicit in Go source (so
+		// Pos()==0), and tagged objects may be allocated
+		// synthetically (so no *MakeInterface data).
+		s = "makeinterface:" + v.X.Type().String()
+
+	default:
+		panic(fmt.Sprintf("unhandled object data type: %T", v))
+	}
+
+	return s + l.subelement.path()
+}
diff --git a/third_party/go.tools/go/pointer/opt.go b/third_party/go.tools/go/pointer/opt.go
new file mode 100644
index 0000000..2620cc0
--- /dev/null
+++ b/third_party/go.tools/go/pointer/opt.go
@@ -0,0 +1,125 @@
+// Copyright 2013 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 pointer
+
+// This file implements renumbering, a pre-solver optimization to
+// improve the efficiency of the solver's points-to set representation.
+//
+// TODO(adonovan): rename file "renumber.go"
+
+import "fmt"
+
+// renumber permutes a.nodes so that all nodes within an addressable
+// object appear before all non-addressable nodes, maintaining the
+// order of nodes within the same object (as required by offsetAddr).
+//
+// renumber must update every nodeid in the analysis (constraints,
+// Pointers, callgraph, etc) to reflect the new ordering.
+//
+// This is an optimisation to increase the locality and efficiency of
+// sparse representations of points-to sets.  (Typically only about
+// 20% of nodes are within an object.)
+//
+// NB: nodes added during solving (e.g. for reflection, SetFinalizer)
+// will be appended to the end.
+//
+// Renumbering makes the PTA log inscrutable.  To aid debugging, later
+// phases (e.g. HVN) must not rely on it having occurred.
+//
+func (a *analysis) renumber() {
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Renumbering\n\n")
+	}
+
+	N := nodeid(len(a.nodes))
+	newNodes := make([]*node, N, N)
+	renumbering := make([]nodeid, N, N) // maps old to new
+
+	var i, j nodeid
+
+	// The zero node is special.
+	newNodes[j] = a.nodes[i]
+	renumbering[i] = j
+	i++
+	j++
+
+	// Pass 1: object nodes.
+	for i < N {
+		obj := a.nodes[i].obj
+		if obj == nil {
+			i++
+			continue
+		}
+
+		end := i + nodeid(obj.size)
+		for i < end {
+			newNodes[j] = a.nodes[i]
+			renumbering[i] = j
+			i++
+			j++
+		}
+	}
+	nobj := j
+
+	// Pass 2: non-object nodes.
+	for i = 1; i < N; {
+		obj := a.nodes[i].obj
+		if obj != nil {
+			i += nodeid(obj.size)
+			continue
+		}
+
+		newNodes[j] = a.nodes[i]
+		renumbering[i] = j
+		i++
+		j++
+	}
+
+	if j != N {
+		panic(fmt.Sprintf("internal error: j=%d, N=%d", j, N))
+	}
+
+	// Log the remapping table.
+	if a.log != nil {
+		fmt.Fprintf(a.log, "Renumbering nodes to improve density:\n")
+		fmt.Fprintf(a.log, "(%d object nodes of %d total)\n", nobj, N)
+		for old, new := range renumbering {
+			fmt.Fprintf(a.log, "\tn%d -> n%d\n", old, new)
+		}
+	}
+
+	// Now renumber all existing nodeids to use the new node permutation.
+	// It is critical that all reachable nodeids are accounted for!
+
+	// Renumber nodeids in queried Pointers.
+	for v, ptr := range a.result.Queries {
+		ptr.n = renumbering[ptr.n]
+		a.result.Queries[v] = ptr
+	}
+	for v, ptr := range a.result.IndirectQueries {
+		ptr.n = renumbering[ptr.n]
+		a.result.IndirectQueries[v] = ptr
+	}
+
+	// Renumber nodeids in global objects.
+	for v, id := range a.globalobj {
+		a.globalobj[v] = renumbering[id]
+	}
+
+	// Renumber nodeids in constraints.
+	for _, c := range a.constraints {
+		c.renumber(renumbering)
+	}
+
+	// Renumber nodeids in the call graph.
+	for _, cgn := range a.cgnodes {
+		cgn.obj = renumbering[cgn.obj]
+		for _, site := range cgn.sites {
+			site.targets = renumbering[site.targets]
+		}
+	}
+
+	a.nodes = newNodes
+}
diff --git a/third_party/go.tools/go/pointer/pointer_test.go b/third_party/go.tools/go/pointer/pointer_test.go
new file mode 100644
index 0000000..d64d762
--- /dev/null
+++ b/third_party/go.tools/go/pointer/pointer_test.go
@@ -0,0 +1,579 @@
+// Copyright 2013 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 pointer_test
+
+// This test uses 'expectation' comments embedded within testdata/*.go
+// files to specify the expected pointer analysis behaviour.
+// See below for grammar.
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"regexp"
+	"strconv"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/pointer"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/ssa/ssautil"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+var inputs = []string{
+	"testdata/a_test.go",
+	"testdata/another.go",
+	"testdata/arrayreflect.go",
+	"testdata/arrays.go",
+	"testdata/channels.go",
+	"testdata/chanreflect.go",
+	"testdata/context.go",
+	"testdata/conv.go",
+	"testdata/finalizer.go",
+	"testdata/flow.go",
+	"testdata/fmtexcerpt.go",
+	"testdata/func.go",
+	"testdata/funcreflect.go",
+	"testdata/hello.go", // NB: causes spurious failure of HVN cross-check
+	"testdata/interfaces.go",
+	"testdata/issue9002.go",
+	"testdata/mapreflect.go",
+	"testdata/maps.go",
+	"testdata/panic.go",
+	"testdata/recur.go",
+	"testdata/reflect.go",
+	"testdata/rtti.go",
+	"testdata/structreflect.go",
+	"testdata/structs.go",
+	"testdata/timer.go",
+}
+
+// Expectation grammar:
+//
+// @calls f -> g
+//
+//   A 'calls' expectation asserts that edge (f, g) appears in the
+//   callgraph.  f and g are notated as per Function.String(), which
+//   may contain spaces (e.g. promoted method in anon struct).
+//
+// @pointsto a | b | c
+//
+//   A 'pointsto' expectation asserts that the points-to set of its
+//   operand contains exactly the set of labels {a,b,c} notated as per
+//   labelString.
+//
+//   A 'pointsto' expectation must appear on the same line as a
+//   print(x) statement; the expectation's operand is x.
+//
+//   If one of the strings is "...", the expectation asserts that the
+//   points-to set at least the other labels.
+//
+//   We use '|' because label names may contain spaces, e.g.  methods
+//   of anonymous structs.
+//
+//   From a theoretical perspective, concrete types in interfaces are
+//   labels too, but they are represented differently and so have a
+//   different expectation, @types, below.
+//
+// @types t | u | v
+//
+//   A 'types' expectation asserts that the set of possible dynamic
+//   types of its interface operand is exactly {t,u,v}, notated per
+//   go/types.Type.String(). In other words, it asserts that the type
+//   component of the interface may point to that set of concrete type
+//   literals.  It also works for reflect.Value, though the types
+//   needn't be concrete in that case.
+//
+//   A 'types' expectation must appear on the same line as a
+//   print(x) statement; the expectation's operand is x.
+//
+//   If one of the strings is "...", the expectation asserts that the
+//   interface's type may point to at least the other types.
+//
+//   We use '|' because type names may contain spaces.
+//
+// @warning "regexp"
+//
+//   A 'warning' expectation asserts that the analysis issues a
+//   warning that matches the regular expression within the string
+//   literal.
+//
+// @line id
+//
+//   A line directive associates the name "id" with the current
+//   file:line.  The string form of labels will use this id instead of
+//   a file:line, making @pointsto expectations more robust against
+//   perturbations in the source file.
+//   (NB, anon functions still include line numbers.)
+//
+type expectation struct {
+	kind     string // "pointsto" | "types" | "calls" | "warning"
+	filename string
+	linenum  int // source line number, 1-based
+	args     []string
+	types    []types.Type // for types
+}
+
+func (e *expectation) String() string {
+	return fmt.Sprintf("@%s[%s]", e.kind, strings.Join(e.args, " | "))
+}
+
+func (e *expectation) errorf(format string, args ...interface{}) {
+	fmt.Printf("%s:%d: ", e.filename, e.linenum)
+	fmt.Printf(format, args...)
+	fmt.Println()
+}
+
+func (e *expectation) needsProbe() bool {
+	return e.kind == "pointsto" || e.kind == "types"
+}
+
+// Find probe (call to print(x)) of same source file/line as expectation.
+func findProbe(prog *ssa.Program, probes map[*ssa.CallCommon]bool, queries map[ssa.Value]pointer.Pointer, e *expectation) (site *ssa.CallCommon, pts pointer.PointsToSet) {
+	for call := range probes {
+		pos := prog.Fset.Position(call.Pos())
+		if pos.Line == e.linenum && pos.Filename == e.filename {
+			// TODO(adonovan): send this to test log (display only on failure).
+			// fmt.Printf("%s:%d: info: found probe for %s: %s\n",
+			// 	e.filename, e.linenum, e, p.arg0) // debugging
+			return call, queries[call.Args[0]].PointsTo()
+		}
+	}
+	return // e.g. analysis didn't reach this call
+}
+
+func doOneInput(input, filename string) bool {
+	conf := loader.Config{SourceImports: true}
+
+	// Parsing.
+	f, err := conf.ParseFile(filename, input)
+	if err != nil {
+		fmt.Println(err)
+		return false
+	}
+
+	// Create single-file main package and import its dependencies.
+	conf.CreateFromFiles("main", f)
+	iprog, err := conf.Load()
+	if err != nil {
+		fmt.Println(err)
+		return false
+	}
+	mainPkgInfo := iprog.Created[0].Pkg
+
+	// SSA creation + building.
+	prog := ssa.Create(iprog, ssa.SanityCheckFunctions)
+	prog.BuildAll()
+
+	mainpkg := prog.Package(mainPkgInfo)
+	ptrmain := mainpkg // main package for the pointer analysis
+	if mainpkg.Func("main") == nil {
+		// No main function; assume it's a test.
+		ptrmain = prog.CreateTestMainPackage(mainpkg)
+	}
+
+	// Find all calls to the built-in print(x).  Analytically,
+	// print is a no-op, but it's a convenient hook for testing
+	// the PTS of an expression, so our tests use it.
+	probes := make(map[*ssa.CallCommon]bool)
+	for fn := range ssautil.AllFunctions(prog) {
+		if fn.Pkg == mainpkg {
+			for _, b := range fn.Blocks {
+				for _, instr := range b.Instrs {
+					if instr, ok := instr.(ssa.CallInstruction); ok {
+						if b, ok := instr.Common().Value.(*ssa.Builtin); ok && b.Name() == "print" {
+							probes[instr.Common()] = true
+						}
+					}
+				}
+			}
+		}
+	}
+
+	ok := true
+
+	lineMapping := make(map[string]string) // maps "file:line" to @line tag
+
+	// Parse expectations in this input.
+	var exps []*expectation
+	re := regexp.MustCompile("// *@([a-z]*) *(.*)$")
+	lines := strings.Split(input, "\n")
+	for linenum, line := range lines {
+		linenum++ // make it 1-based
+		if matches := re.FindAllStringSubmatch(line, -1); matches != nil {
+			match := matches[0]
+			kind, rest := match[1], match[2]
+			e := &expectation{kind: kind, filename: filename, linenum: linenum}
+
+			if kind == "line" {
+				if rest == "" {
+					ok = false
+					e.errorf("@%s expectation requires identifier", kind)
+				} else {
+					lineMapping[fmt.Sprintf("%s:%d", filename, linenum)] = rest
+				}
+				continue
+			}
+
+			if e.needsProbe() && !strings.Contains(line, "print(") {
+				ok = false
+				e.errorf("@%s expectation must follow call to print(x)", kind)
+				continue
+			}
+
+			switch kind {
+			case "pointsto":
+				e.args = split(rest, "|")
+
+			case "types":
+				for _, typstr := range split(rest, "|") {
+					var t types.Type = types.Typ[types.Invalid] // means "..."
+					if typstr != "..." {
+						texpr, err := parser.ParseExpr(typstr)
+						if err != nil {
+							ok = false
+							// Don't print err since its location is bad.
+							e.errorf("'%s' is not a valid type", typstr)
+							continue
+						}
+						mainFileScope := mainpkg.Object.Scope().Child(0)
+						t, _, err = types.EvalNode(prog.Fset, texpr, mainpkg.Object, mainFileScope)
+						if err != nil {
+							ok = false
+							// Don't print err since its location is bad.
+							e.errorf("'%s' is not a valid type: %s", typstr, err)
+							continue
+						}
+					}
+					e.types = append(e.types, t)
+				}
+
+			case "calls":
+				e.args = split(rest, "->")
+				// TODO(adonovan): eagerly reject the
+				// expectation if fn doesn't denote
+				// existing function, rather than fail
+				// the expectation after analysis.
+				if len(e.args) != 2 {
+					ok = false
+					e.errorf("@calls expectation wants 'caller -> callee' arguments")
+					continue
+				}
+
+			case "warning":
+				lit, err := strconv.Unquote(strings.TrimSpace(rest))
+				if err != nil {
+					ok = false
+					e.errorf("couldn't parse @warning operand: %s", err.Error())
+					continue
+				}
+				e.args = append(e.args, lit)
+
+			default:
+				ok = false
+				e.errorf("unknown expectation kind: %s", e)
+				continue
+			}
+			exps = append(exps, e)
+		}
+	}
+
+	var log bytes.Buffer
+	fmt.Fprintf(&log, "Input: %s\n", filename)
+
+	// Run the analysis.
+	config := &pointer.Config{
+		Reflection:     true,
+		BuildCallGraph: true,
+		Mains:          []*ssa.Package{ptrmain},
+		Log:            &log,
+	}
+	for probe := range probes {
+		v := probe.Args[0]
+		if pointer.CanPoint(v.Type()) {
+			config.AddQuery(v)
+		}
+	}
+
+	// Print the log is there was an error or a panic.
+	complete := false
+	defer func() {
+		if !complete || !ok {
+			log.WriteTo(os.Stderr)
+		}
+	}()
+
+	result, err := pointer.Analyze(config)
+	if err != nil {
+		panic(err) // internal error in pointer analysis
+	}
+
+	// Check the expectations.
+	for _, e := range exps {
+		var call *ssa.CallCommon
+		var pts pointer.PointsToSet
+		var tProbe types.Type
+		if e.needsProbe() {
+			if call, pts = findProbe(prog, probes, result.Queries, e); call == nil {
+				ok = false
+				e.errorf("unreachable print() statement has expectation %s", e)
+				continue
+			}
+			tProbe = call.Args[0].Type()
+			if !pointer.CanPoint(tProbe) {
+				ok = false
+				e.errorf("expectation on non-pointerlike operand: %s", tProbe)
+				continue
+			}
+		}
+
+		switch e.kind {
+		case "pointsto":
+			if !checkPointsToExpectation(e, pts, lineMapping, prog) {
+				ok = false
+			}
+
+		case "types":
+			if !checkTypesExpectation(e, pts, tProbe) {
+				ok = false
+			}
+
+		case "calls":
+			if !checkCallsExpectation(prog, e, result.CallGraph) {
+				ok = false
+			}
+
+		case "warning":
+			if !checkWarningExpectation(prog, e, result.Warnings) {
+				ok = false
+			}
+		}
+	}
+
+	complete = true
+
+	// ok = false // debugging: uncomment to always see log
+
+	return ok
+}
+
+func labelString(l *pointer.Label, lineMapping map[string]string, prog *ssa.Program) string {
+	// Functions and Globals need no pos suffix,
+	// nor do allocations in intrinsic operations
+	// (for which we'll print the function name).
+	switch l.Value().(type) {
+	case nil, *ssa.Function, *ssa.Global:
+		return l.String()
+	}
+
+	str := l.String()
+	if pos := l.Pos(); pos != token.NoPos {
+		// Append the position, using a @line tag instead of a line number, if defined.
+		posn := prog.Fset.Position(pos)
+		s := fmt.Sprintf("%s:%d", posn.Filename, posn.Line)
+		if tag, ok := lineMapping[s]; ok {
+			return fmt.Sprintf("%s@%s:%d", str, tag, posn.Column)
+		}
+		str = fmt.Sprintf("%s@%s", str, posn)
+	}
+	return str
+}
+
+func checkPointsToExpectation(e *expectation, pts pointer.PointsToSet, lineMapping map[string]string, prog *ssa.Program) bool {
+	expected := make(map[string]int)
+	surplus := make(map[string]int)
+	exact := true
+	for _, g := range e.args {
+		if g == "..." {
+			exact = false
+			continue
+		}
+		expected[g]++
+	}
+	// Find the set of labels that the probe's
+	// argument (x in print(x)) may point to.
+	for _, label := range pts.Labels() {
+		name := labelString(label, lineMapping, prog)
+		if expected[name] > 0 {
+			expected[name]--
+		} else if exact {
+			surplus[name]++
+		}
+	}
+	// Report multiset difference:
+	ok := true
+	for _, count := range expected {
+		if count > 0 {
+			ok = false
+			e.errorf("value does not alias these expected labels: %s", join(expected))
+			break
+		}
+	}
+	for _, count := range surplus {
+		if count > 0 {
+			ok = false
+			e.errorf("value may additionally alias these labels: %s", join(surplus))
+			break
+		}
+	}
+	return ok
+}
+
+func checkTypesExpectation(e *expectation, pts pointer.PointsToSet, typ types.Type) bool {
+	var expected typeutil.Map
+	var surplus typeutil.Map
+	exact := true
+	for _, g := range e.types {
+		if g == types.Typ[types.Invalid] {
+			exact = false
+			continue
+		}
+		expected.Set(g, struct{}{})
+	}
+
+	if !pointer.CanHaveDynamicTypes(typ) {
+		e.errorf("@types expectation requires an interface- or reflect.Value-typed operand, got %s", typ)
+		return false
+	}
+
+	// Find the set of types that the probe's
+	// argument (x in print(x)) may contain.
+	for _, T := range pts.DynamicTypes().Keys() {
+		if expected.At(T) != nil {
+			expected.Delete(T)
+		} else if exact {
+			surplus.Set(T, struct{}{})
+		}
+	}
+	// Report set difference:
+	ok := true
+	if expected.Len() > 0 {
+		ok = false
+		e.errorf("interface cannot contain these types: %s", expected.KeysString())
+	}
+	if surplus.Len() > 0 {
+		ok = false
+		e.errorf("interface may additionally contain these types: %s", surplus.KeysString())
+	}
+	return ok
+}
+
+var errOK = errors.New("OK")
+
+func checkCallsExpectation(prog *ssa.Program, e *expectation, cg *callgraph.Graph) bool {
+	found := make(map[string]int)
+	err := callgraph.GraphVisitEdges(cg, func(edge *callgraph.Edge) error {
+		// Name-based matching is inefficient but it allows us to
+		// match functions whose names that would not appear in an
+		// index ("<root>") or which are not unique ("func@1.2").
+		if edge.Caller.Func.String() == e.args[0] {
+			calleeStr := edge.Callee.Func.String()
+			if calleeStr == e.args[1] {
+				return errOK // expectation satisified; stop the search
+			}
+			found[calleeStr]++
+		}
+		return nil
+	})
+	if err == errOK {
+		return true
+	}
+	if len(found) == 0 {
+		e.errorf("didn't find any calls from %s", e.args[0])
+	}
+	e.errorf("found no call from %s to %s, but only to %s",
+		e.args[0], e.args[1], join(found))
+	return false
+}
+
+func checkWarningExpectation(prog *ssa.Program, e *expectation, warnings []pointer.Warning) bool {
+	// TODO(adonovan): check the position part of the warning too?
+	re, err := regexp.Compile(e.args[0])
+	if err != nil {
+		e.errorf("invalid regular expression in @warning expectation: %s", err.Error())
+		return false
+	}
+
+	if len(warnings) == 0 {
+		e.errorf("@warning %s expectation, but no warnings", strconv.Quote(e.args[0]))
+		return false
+	}
+
+	for _, w := range warnings {
+		if re.MatchString(w.Message) {
+			return true
+		}
+	}
+
+	e.errorf("@warning %s expectation not satised; found these warnings though:", strconv.Quote(e.args[0]))
+	for _, w := range warnings {
+		fmt.Printf("%s: warning: %s\n", prog.Fset.Position(w.Pos), w.Message)
+	}
+	return false
+}
+
+func TestInput(t *testing.T) {
+	ok := true
+
+	wd, err := os.Getwd()
+	if err != nil {
+		t.Errorf("os.Getwd: %s", err)
+		return
+	}
+
+	// 'go test' does a chdir so that relative paths in
+	// diagnostics no longer make sense relative to the invoking
+	// shell's cwd.  We print a special marker so that Emacs can
+	// make sense of them.
+	fmt.Fprintf(os.Stderr, "Entering directory `%s'\n", wd)
+
+	for _, filename := range inputs {
+		content, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Errorf("couldn't read file '%s': %s", filename, err)
+			continue
+		}
+
+		if !doOneInput(string(content), filename) {
+			ok = false
+		}
+	}
+	if !ok {
+		t.Fail()
+	}
+}
+
+// join joins the elements of multiset with " | "s.
+func join(set map[string]int) string {
+	var buf bytes.Buffer
+	sep := ""
+	for name, count := range set {
+		for i := 0; i < count; i++ {
+			buf.WriteString(sep)
+			sep = " | "
+			buf.WriteString(name)
+		}
+	}
+	return buf.String()
+}
+
+// split returns the list of sep-delimited non-empty strings in s.
+func split(s, sep string) (r []string) {
+	for _, elem := range strings.Split(s, sep) {
+		elem = strings.TrimSpace(elem)
+		if elem != "" {
+			r = append(r, elem)
+		}
+	}
+	return
+}
diff --git a/third_party/go.tools/go/pointer/print.go b/third_party/go.tools/go/pointer/print.go
new file mode 100644
index 0000000..4f2f4c7
--- /dev/null
+++ b/third_party/go.tools/go/pointer/print.go
@@ -0,0 +1,43 @@
+// Copyright 2013 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 pointer
+
+import "fmt"
+
+func (c *addrConstraint) String() string {
+	return fmt.Sprintf("addr n%d <- {&n%d}", c.dst, c.src)
+}
+
+func (c *copyConstraint) String() string {
+	return fmt.Sprintf("copy n%d <- n%d", c.dst, c.src)
+}
+
+func (c *loadConstraint) String() string {
+	return fmt.Sprintf("load n%d <- n%d[%d]", c.dst, c.src, c.offset)
+}
+
+func (c *storeConstraint) String() string {
+	return fmt.Sprintf("store n%d[%d] <- n%d", c.dst, c.offset, c.src)
+}
+
+func (c *offsetAddrConstraint) String() string {
+	return fmt.Sprintf("offsetAddr n%d <- n%d.#%d", c.dst, c.src, c.offset)
+}
+
+func (c *typeFilterConstraint) String() string {
+	return fmt.Sprintf("typeFilter n%d <- n%d.(%s)", c.dst, c.src, c.typ)
+}
+
+func (c *untagConstraint) String() string {
+	return fmt.Sprintf("untag n%d <- n%d.(%s)", c.dst, c.src, c.typ)
+}
+
+func (c *invokeConstraint) String() string {
+	return fmt.Sprintf("invoke n%d.%s(n%d ...)", c.iface, c.method.Name(), c.params)
+}
+
+func (n nodeid) String() string {
+	return fmt.Sprintf("n%d", n)
+}
diff --git a/third_party/go.tools/go/pointer/reflect.go b/third_party/go.tools/go/pointer/reflect.go
new file mode 100644
index 0000000..8a07575
--- /dev/null
+++ b/third_party/go.tools/go/pointer/reflect.go
@@ -0,0 +1,1971 @@
+package pointer
+
+// This file implements the generation and resolution rules for
+// constraints arising from the use of reflection in the target
+// program.  See doc.go for explanation of the representation.
+//
+// For consistency, the names of all parameters match those of the
+// actual functions in the "reflect" package.
+//
+// To avoid proliferation of equivalent labels, intrinsics should
+// memoize as much as possible, like TypeOf and Zero do for their
+// tagged objects.
+//
+// TODO(adonovan): this file is rather subtle.  Explain how we derive
+// the implementation of each reflect operator from its spec,
+// including the subtleties of reflect.flag{Addr,RO,Indir}.
+// [Hint: our implementation is as if reflect.flagIndir was always
+// true, i.e. reflect.Values are pointers to tagged objects, there is
+// no inline allocation optimization; and indirect tagged objects (not
+// yet implemented) correspond to reflect.Values with
+// reflect.flagAddr.]
+// A picture would help too.
+//
+// TODO(adonovan): try factoring up the common parts of the majority of
+// these constraints that are single input, single output.
+
+import (
+	"fmt"
+	"reflect"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func init() {
+	for name, fn := range map[string]intrinsic{
+		// reflect.Value methods.
+		"(reflect.Value).Addr":            ext۰reflect۰Value۰Addr,
+		"(reflect.Value).Bool":            ext۰NoEffect,
+		"(reflect.Value).Bytes":           ext۰reflect۰Value۰Bytes,
+		"(reflect.Value).Call":            ext۰reflect۰Value۰Call,
+		"(reflect.Value).CallSlice":       ext۰reflect۰Value۰CallSlice,
+		"(reflect.Value).CanAddr":         ext۰NoEffect,
+		"(reflect.Value).CanInterface":    ext۰NoEffect,
+		"(reflect.Value).CanSet":          ext۰NoEffect,
+		"(reflect.Value).Cap":             ext۰NoEffect,
+		"(reflect.Value).Close":           ext۰NoEffect,
+		"(reflect.Value).Complex":         ext۰NoEffect,
+		"(reflect.Value).Convert":         ext۰reflect۰Value۰Convert,
+		"(reflect.Value).Elem":            ext۰reflect۰Value۰Elem,
+		"(reflect.Value).Field":           ext۰reflect۰Value۰Field,
+		"(reflect.Value).FieldByIndex":    ext۰reflect۰Value۰FieldByIndex,
+		"(reflect.Value).FieldByName":     ext۰reflect۰Value۰FieldByName,
+		"(reflect.Value).FieldByNameFunc": ext۰reflect۰Value۰FieldByNameFunc,
+		"(reflect.Value).Float":           ext۰NoEffect,
+		"(reflect.Value).Index":           ext۰reflect۰Value۰Index,
+		"(reflect.Value).Int":             ext۰NoEffect,
+		"(reflect.Value).Interface":       ext۰reflect۰Value۰Interface,
+		"(reflect.Value).InterfaceData":   ext۰NoEffect,
+		"(reflect.Value).IsNil":           ext۰NoEffect,
+		"(reflect.Value).IsValid":         ext۰NoEffect,
+		"(reflect.Value).Kind":            ext۰NoEffect,
+		"(reflect.Value).Len":             ext۰NoEffect,
+		"(reflect.Value).MapIndex":        ext۰reflect۰Value۰MapIndex,
+		"(reflect.Value).MapKeys":         ext۰reflect۰Value۰MapKeys,
+		"(reflect.Value).Method":          ext۰reflect۰Value۰Method,
+		"(reflect.Value).MethodByName":    ext۰reflect۰Value۰MethodByName,
+		"(reflect.Value).NumField":        ext۰NoEffect,
+		"(reflect.Value).NumMethod":       ext۰NoEffect,
+		"(reflect.Value).OverflowComplex": ext۰NoEffect,
+		"(reflect.Value).OverflowFloat":   ext۰NoEffect,
+		"(reflect.Value).OverflowInt":     ext۰NoEffect,
+		"(reflect.Value).OverflowUint":    ext۰NoEffect,
+		"(reflect.Value).Pointer":         ext۰NoEffect,
+		"(reflect.Value).Recv":            ext۰reflect۰Value۰Recv,
+		"(reflect.Value).Send":            ext۰reflect۰Value۰Send,
+		"(reflect.Value).Set":             ext۰reflect۰Value۰Set,
+		"(reflect.Value).SetBool":         ext۰NoEffect,
+		"(reflect.Value).SetBytes":        ext۰reflect۰Value۰SetBytes,
+		"(reflect.Value).SetComplex":      ext۰NoEffect,
+		"(reflect.Value).SetFloat":        ext۰NoEffect,
+		"(reflect.Value).SetInt":          ext۰NoEffect,
+		"(reflect.Value).SetLen":          ext۰NoEffect,
+		"(reflect.Value).SetMapIndex":     ext۰reflect۰Value۰SetMapIndex,
+		"(reflect.Value).SetPointer":      ext۰reflect۰Value۰SetPointer,
+		"(reflect.Value).SetString":       ext۰NoEffect,
+		"(reflect.Value).SetUint":         ext۰NoEffect,
+		"(reflect.Value).Slice":           ext۰reflect۰Value۰Slice,
+		"(reflect.Value).String":          ext۰NoEffect,
+		"(reflect.Value).TryRecv":         ext۰reflect۰Value۰Recv,
+		"(reflect.Value).TrySend":         ext۰reflect۰Value۰Send,
+		"(reflect.Value).Type":            ext۰NoEffect,
+		"(reflect.Value).Uint":            ext۰NoEffect,
+		"(reflect.Value).UnsafeAddr":      ext۰NoEffect,
+
+		// Standalone reflect.* functions.
+		"reflect.Append":      ext۰reflect۰Append,
+		"reflect.AppendSlice": ext۰reflect۰AppendSlice,
+		"reflect.Copy":        ext۰reflect۰Copy,
+		"reflect.ChanOf":      ext۰reflect۰ChanOf,
+		"reflect.DeepEqual":   ext۰NoEffect,
+		"reflect.Indirect":    ext۰reflect۰Indirect,
+		"reflect.MakeChan":    ext۰reflect۰MakeChan,
+		"reflect.MakeFunc":    ext۰reflect۰MakeFunc,
+		"reflect.MakeMap":     ext۰reflect۰MakeMap,
+		"reflect.MakeSlice":   ext۰reflect۰MakeSlice,
+		"reflect.MapOf":       ext۰reflect۰MapOf,
+		"reflect.New":         ext۰reflect۰New,
+		"reflect.NewAt":       ext۰reflect۰NewAt,
+		"reflect.PtrTo":       ext۰reflect۰PtrTo,
+		"reflect.Select":      ext۰reflect۰Select,
+		"reflect.SliceOf":     ext۰reflect۰SliceOf,
+		"reflect.TypeOf":      ext۰reflect۰TypeOf,
+		"reflect.ValueOf":     ext۰reflect۰ValueOf,
+		"reflect.Zero":        ext۰reflect۰Zero,
+		"reflect.init":        ext۰NoEffect,
+
+		// *reflect.rtype methods
+		"(*reflect.rtype).Align":           ext۰NoEffect,
+		"(*reflect.rtype).AssignableTo":    ext۰NoEffect,
+		"(*reflect.rtype).Bits":            ext۰NoEffect,
+		"(*reflect.rtype).ChanDir":         ext۰NoEffect,
+		"(*reflect.rtype).ConvertibleTo":   ext۰NoEffect,
+		"(*reflect.rtype).Elem":            ext۰reflect۰rtype۰Elem,
+		"(*reflect.rtype).Field":           ext۰reflect۰rtype۰Field,
+		"(*reflect.rtype).FieldAlign":      ext۰NoEffect,
+		"(*reflect.rtype).FieldByIndex":    ext۰reflect۰rtype۰FieldByIndex,
+		"(*reflect.rtype).FieldByName":     ext۰reflect۰rtype۰FieldByName,
+		"(*reflect.rtype).FieldByNameFunc": ext۰reflect۰rtype۰FieldByNameFunc,
+		"(*reflect.rtype).Implements":      ext۰NoEffect,
+		"(*reflect.rtype).In":              ext۰reflect۰rtype۰In,
+		"(*reflect.rtype).IsVariadic":      ext۰NoEffect,
+		"(*reflect.rtype).Key":             ext۰reflect۰rtype۰Key,
+		"(*reflect.rtype).Kind":            ext۰NoEffect,
+		"(*reflect.rtype).Len":             ext۰NoEffect,
+		"(*reflect.rtype).Method":          ext۰reflect۰rtype۰Method,
+		"(*reflect.rtype).MethodByName":    ext۰reflect۰rtype۰MethodByName,
+		"(*reflect.rtype).Name":            ext۰NoEffect,
+		"(*reflect.rtype).NumField":        ext۰NoEffect,
+		"(*reflect.rtype).NumIn":           ext۰NoEffect,
+		"(*reflect.rtype).NumMethod":       ext۰NoEffect,
+		"(*reflect.rtype).NumOut":          ext۰NoEffect,
+		"(*reflect.rtype).Out":             ext۰reflect۰rtype۰Out,
+		"(*reflect.rtype).PkgPath":         ext۰NoEffect,
+		"(*reflect.rtype).Size":            ext۰NoEffect,
+		"(*reflect.rtype).String":          ext۰NoEffect,
+	} {
+		intrinsicsByName[name] = fn
+	}
+}
+
+// -------------------- (reflect.Value) --------------------
+
+func ext۰reflect۰Value۰Addr(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Bytes() Value ----------
+
+// result = v.Bytes()
+type rVBytesConstraint struct {
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVBytesConstraint) ptr() nodeid { return c.v }
+func (c *rVBytesConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVBytes.result")
+}
+func (c *rVBytesConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVBytesConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Bytes()", c.result, c.v)
+}
+
+func (c *rVBytesConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, slice, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSlice, ok := tDyn.Underlying().(*types.Slice)
+		if ok && types.Identical(tSlice.Elem(), types.Typ[types.Uint8]) {
+			if a.onlineCopy(c.result, slice) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Bytes(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVBytesConstraint{
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).Call(in []Value) []Value ----------
+
+// result = v.Call(in)
+type rVCallConstraint struct {
+	cgn       *cgnode
+	targets   nodeid // (indirect)
+	v         nodeid // (ptr)
+	arg       nodeid // = in[*]
+	result    nodeid // (indirect)
+	dotdotdot bool   // interpret last arg as a "..." slice
+}
+
+func (c *rVCallConstraint) ptr() nodeid { return c.v }
+func (c *rVCallConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.targets), "rVCall.targets")
+	h.markIndirect(onodeid(c.result), "rVCall.result")
+}
+func (c *rVCallConstraint) renumber(mapping []nodeid) {
+	c.targets = mapping[c.targets]
+	c.v = mapping[c.v]
+	c.arg = mapping[c.arg]
+	c.result = mapping[c.result]
+}
+
+func (c *rVCallConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Call(n%d)", c.result, c.v, c.arg)
+}
+
+func (c *rVCallConstraint) solve(a *analysis, delta *nodeset) {
+	if c.targets == 0 {
+		panic("no targets")
+	}
+
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, fn, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSig, ok := tDyn.Underlying().(*types.Signature)
+		if !ok {
+			continue // not a function
+		}
+		if tSig.Recv() != nil {
+			panic(tSig) // TODO(adonovan): rethink when we implement Method()
+		}
+
+		// Add dynamic call target.
+		if a.onlineCopy(c.targets, fn) {
+			a.addWork(c.targets)
+			// TODO(adonovan): is 'else continue' a sound optimisation here?
+		}
+
+		// Allocate a P/R block.
+		tParams := tSig.Params()
+		tResults := tSig.Results()
+		params := a.addNodes(tParams, "rVCall.params")
+		results := a.addNodes(tResults, "rVCall.results")
+
+		// Make a dynamic call to 'fn'.
+		a.store(fn, params, 1, a.sizeof(tParams))
+		a.load(results, fn, 1+a.sizeof(tParams), a.sizeof(tResults))
+
+		// Populate P by type-asserting each actual arg (all merged in c.arg).
+		for i, n := 0, tParams.Len(); i < n; i++ {
+			T := tParams.At(i).Type()
+			a.typeAssert(T, params, c.arg, false)
+			params += nodeid(a.sizeof(T))
+		}
+
+		// Use R by tagging and copying each actual result to c.result.
+		for i, n := 0, tResults.Len(); i < n; i++ {
+			T := tResults.At(i).Type()
+			// Convert from an arbitrary type to a reflect.Value
+			// (like MakeInterface followed by reflect.ValueOf).
+			if isInterface(T) {
+				// (don't tag)
+				if a.onlineCopy(c.result, results) {
+					changed = true
+				}
+			} else {
+				obj := a.makeTagged(T, c.cgn, nil)
+				a.onlineCopyN(obj+1, results, a.sizeof(T))
+				if a.addLabel(c.result, obj) { // (true)
+					changed = true
+				}
+			}
+			results += nodeid(a.sizeof(T))
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+// Common code for direct (inlined) and indirect calls to (reflect.Value).Call.
+func reflectCallImpl(a *analysis, cgn *cgnode, site *callsite, recv, arg nodeid, dotdotdot bool) nodeid {
+	// Allocate []reflect.Value array for the result.
+	ret := a.nextNode()
+	a.addNodes(types.NewArray(a.reflectValueObj.Type(), 1), "rVCall.ret")
+	a.endObject(ret, cgn, nil)
+
+	// pts(targets) will be the set of possible call targets.
+	site.targets = a.addOneNode(tInvalid, "rvCall.targets", nil)
+
+	// All arguments are merged since they arrive in a slice.
+	argelts := a.addOneNode(a.reflectValueObj.Type(), "rVCall.args", nil)
+	a.load(argelts, arg, 1, 1) // slice elements
+
+	a.addConstraint(&rVCallConstraint{
+		cgn:       cgn,
+		targets:   site.targets,
+		v:         recv,
+		arg:       argelts,
+		result:    ret + 1, // results go into elements of ret
+		dotdotdot: dotdotdot,
+	})
+	return ret
+}
+
+func reflectCall(a *analysis, cgn *cgnode, dotdotdot bool) {
+	// This is the shared contour implementation of (reflect.Value).Call
+	// and CallSlice, as used by indirect calls (rare).
+	// Direct calls are inlined in gen.go, eliding the
+	// intermediate cgnode for Call.
+	site := new(callsite)
+	cgn.sites = append(cgn.sites, site)
+	recv := a.funcParams(cgn.obj)
+	arg := recv + 1
+	ret := reflectCallImpl(a, cgn, site, recv, arg, dotdotdot)
+	a.addressOf(cgn.fn.Signature.Results().At(0).Type(), a.funcResults(cgn.obj), ret)
+}
+
+func ext۰reflect۰Value۰Call(a *analysis, cgn *cgnode) {
+	reflectCall(a, cgn, false)
+}
+
+func ext۰reflect۰Value۰CallSlice(a *analysis, cgn *cgnode) {
+	// TODO(adonovan): implement.  Also, inline direct calls in gen.go too.
+	if false {
+		reflectCall(a, cgn, true)
+	}
+}
+
+func ext۰reflect۰Value۰Convert(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Elem() Value ----------
+
+// result = v.Elem()
+type rVElemConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVElemConstraint) ptr() nodeid { return c.v }
+func (c *rVElemConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVElem.result")
+}
+func (c *rVElemConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVElemConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Elem()", c.result, c.v)
+}
+
+func (c *rVElemConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		switch t := tDyn.Underlying().(type) {
+		case *types.Interface:
+			if a.onlineCopy(c.result, payload) {
+				changed = true
+			}
+
+		case *types.Pointer:
+			obj := a.makeTagged(t.Elem(), c.cgn, nil)
+			a.load(obj+1, payload, 0, a.sizeof(t.Elem()))
+			if a.addLabel(c.result, obj) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Elem(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVElemConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰Value۰Field(a *analysis, cgn *cgnode)           {} // TODO(adonovan)
+func ext۰reflect۰Value۰FieldByIndex(a *analysis, cgn *cgnode)    {} // TODO(adonovan)
+func ext۰reflect۰Value۰FieldByName(a *analysis, cgn *cgnode)     {} // TODO(adonovan)
+func ext۰reflect۰Value۰FieldByNameFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Index() Value ----------
+
+// result = v.Index()
+type rVIndexConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVIndexConstraint) ptr() nodeid { return c.v }
+func (c *rVIndexConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVIndex.result")
+}
+func (c *rVIndexConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVIndexConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Index()", c.result, c.v)
+}
+
+func (c *rVIndexConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		var res nodeid
+		switch t := tDyn.Underlying().(type) {
+		case *types.Array:
+			res = a.makeTagged(t.Elem(), c.cgn, nil)
+			a.onlineCopyN(res+1, payload+1, a.sizeof(t.Elem()))
+
+		case *types.Slice:
+			res = a.makeTagged(t.Elem(), c.cgn, nil)
+			a.load(res+1, payload, 1, a.sizeof(t.Elem()))
+
+		case *types.Basic:
+			if t.Kind() == types.String {
+				res = a.makeTagged(types.Typ[types.Rune], c.cgn, nil)
+			}
+		}
+		if res != 0 && a.addLabel(c.result, res) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Index(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVIndexConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).Interface() Value ----------
+
+// result = v.Interface()
+type rVInterfaceConstraint struct {
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVInterfaceConstraint) ptr() nodeid { return c.v }
+func (c *rVInterfaceConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVInterface.result")
+}
+func (c *rVInterfaceConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVInterfaceConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Interface()", c.result, c.v)
+}
+
+func (c *rVInterfaceConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		if isInterface(tDyn) {
+			if a.onlineCopy(c.result, payload) {
+				a.addWork(c.result)
+			}
+		} else {
+			if a.addLabel(c.result, vObj) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Interface(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVInterfaceConstraint{
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).MapIndex(Value) Value ----------
+
+// result = v.MapIndex(_)
+type rVMapIndexConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVMapIndexConstraint) ptr() nodeid { return c.v }
+func (c *rVMapIndexConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVMapIndex.result")
+}
+func (c *rVMapIndexConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVMapIndexConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.MapIndex(_)", c.result, c.v)
+}
+
+func (c *rVMapIndexConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, m, indirect := a.taggedValue(vObj)
+		tMap, _ := tDyn.Underlying().(*types.Map)
+		if tMap == nil {
+			continue // not a map
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		obj := a.makeTagged(tMap.Elem(), c.cgn, nil)
+		a.load(obj+1, m, a.sizeof(tMap.Key()), a.sizeof(tMap.Elem()))
+		if a.addLabel(c.result, obj) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰MapIndex(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVMapIndexConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).MapKeys() []Value ----------
+
+// result = v.MapKeys()
+type rVMapKeysConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVMapKeysConstraint) ptr() nodeid { return c.v }
+func (c *rVMapKeysConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVMapKeys.result")
+}
+func (c *rVMapKeysConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVMapKeysConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.MapKeys()", c.result, c.v)
+}
+
+func (c *rVMapKeysConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, m, indirect := a.taggedValue(vObj)
+		tMap, _ := tDyn.Underlying().(*types.Map)
+		if tMap == nil {
+			continue // not a map
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		kObj := a.makeTagged(tMap.Key(), c.cgn, nil)
+		a.load(kObj+1, m, 0, a.sizeof(tMap.Key()))
+		if a.addLabel(c.result, kObj) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰MapKeys(a *analysis, cgn *cgnode) {
+	// Allocate an array for the result.
+	obj := a.nextNode()
+	T := types.NewSlice(a.reflectValueObj.Type())
+	a.addNodes(sliceToArray(T), "reflect.MapKeys result")
+	a.endObject(obj, cgn, nil)
+	a.addressOf(T, a.funcResults(cgn.obj), obj)
+
+	a.addConstraint(&rVMapKeysConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: obj + 1, // result is stored in array elems
+	})
+}
+
+func ext۰reflect۰Value۰Method(a *analysis, cgn *cgnode)       {} // TODO(adonovan)
+func ext۰reflect۰Value۰MethodByName(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Recv(Value) Value ----------
+
+// result, _ = v.Recv()
+type rVRecvConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVRecvConstraint) ptr() nodeid { return c.v }
+func (c *rVRecvConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVRecv.result")
+}
+func (c *rVRecvConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVRecvConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Recv()", c.result, c.v)
+}
+
+func (c *rVRecvConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, ch, indirect := a.taggedValue(vObj)
+		tChan, _ := tDyn.Underlying().(*types.Chan)
+		if tChan == nil {
+			continue // not a channel
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tElem := tChan.Elem()
+		elemObj := a.makeTagged(tElem, c.cgn, nil)
+		a.load(elemObj+1, ch, 0, a.sizeof(tElem))
+		if a.addLabel(c.result, elemObj) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Recv(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVRecvConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).Send(Value) ----------
+
+// v.Send(x)
+type rVSendConstraint struct {
+	cgn *cgnode
+	v   nodeid // (ptr)
+	x   nodeid
+}
+
+func (c *rVSendConstraint) ptr() nodeid   { return c.v }
+func (c *rVSendConstraint) presolve(*hvn) {}
+func (c *rVSendConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.x = mapping[c.x]
+}
+
+func (c *rVSendConstraint) String() string {
+	return fmt.Sprintf("reflect n%d.Send(n%d)", c.v, c.x)
+}
+
+func (c *rVSendConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, ch, indirect := a.taggedValue(vObj)
+		tChan, _ := tDyn.Underlying().(*types.Chan)
+		if tChan == nil {
+			continue // not a channel
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		// Extract x's payload to xtmp, then store to channel.
+		tElem := tChan.Elem()
+		xtmp := a.addNodes(tElem, "Send.xtmp")
+		a.typeAssert(tElem, xtmp, c.x, false)
+		a.store(ch, xtmp, 0, a.sizeof(tElem))
+	}
+}
+
+func ext۰reflect۰Value۰Send(a *analysis, cgn *cgnode) {
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&rVSendConstraint{
+		cgn: cgn,
+		v:   params,
+		x:   params + 1,
+	})
+}
+
+func ext۰reflect۰Value۰Set(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).SetBytes(x []byte) ----------
+
+// v.SetBytes(x)
+type rVSetBytesConstraint struct {
+	cgn *cgnode
+	v   nodeid // (ptr)
+	x   nodeid
+}
+
+func (c *rVSetBytesConstraint) ptr() nodeid   { return c.v }
+func (c *rVSetBytesConstraint) presolve(*hvn) {}
+func (c *rVSetBytesConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.x = mapping[c.x]
+}
+
+func (c *rVSetBytesConstraint) String() string {
+	return fmt.Sprintf("reflect n%d.SetBytes(n%d)", c.v, c.x)
+}
+
+func (c *rVSetBytesConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, slice, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSlice, ok := tDyn.Underlying().(*types.Slice)
+		if ok && types.Identical(tSlice.Elem(), types.Typ[types.Uint8]) {
+			if a.onlineCopy(slice, c.x) {
+				a.addWork(slice)
+			}
+		}
+	}
+}
+
+func ext۰reflect۰Value۰SetBytes(a *analysis, cgn *cgnode) {
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&rVSetBytesConstraint{
+		cgn: cgn,
+		v:   params,
+		x:   params + 1,
+	})
+}
+
+// ---------- func (Value).SetMapIndex(k Value, v Value) ----------
+
+// v.SetMapIndex(key, val)
+type rVSetMapIndexConstraint struct {
+	cgn *cgnode
+	v   nodeid // (ptr)
+	key nodeid
+	val nodeid
+}
+
+func (c *rVSetMapIndexConstraint) ptr() nodeid   { return c.v }
+func (c *rVSetMapIndexConstraint) presolve(*hvn) {}
+func (c *rVSetMapIndexConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.key = mapping[c.key]
+	c.val = mapping[c.val]
+}
+
+func (c *rVSetMapIndexConstraint) String() string {
+	return fmt.Sprintf("reflect n%d.SetMapIndex(n%d, n%d)", c.v, c.key, c.val)
+}
+
+func (c *rVSetMapIndexConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, m, indirect := a.taggedValue(vObj)
+		tMap, _ := tDyn.Underlying().(*types.Map)
+		if tMap == nil {
+			continue // not a map
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		keysize := a.sizeof(tMap.Key())
+
+		// Extract key's payload to keytmp, then store to map key.
+		keytmp := a.addNodes(tMap.Key(), "SetMapIndex.keytmp")
+		a.typeAssert(tMap.Key(), keytmp, c.key, false)
+		a.store(m, keytmp, 0, keysize)
+
+		// Extract val's payload to vtmp, then store to map value.
+		valtmp := a.addNodes(tMap.Elem(), "SetMapIndex.valtmp")
+		a.typeAssert(tMap.Elem(), valtmp, c.val, false)
+		a.store(m, valtmp, keysize, a.sizeof(tMap.Elem()))
+	}
+}
+
+func ext۰reflect۰Value۰SetMapIndex(a *analysis, cgn *cgnode) {
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&rVSetMapIndexConstraint{
+		cgn: cgn,
+		v:   params,
+		key: params + 1,
+		val: params + 2,
+	})
+}
+
+func ext۰reflect۰Value۰SetPointer(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Slice(v Value, i, j int) Value ----------
+
+// result = v.Slice(_, _)
+type rVSliceConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVSliceConstraint) ptr() nodeid { return c.v }
+func (c *rVSliceConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVSlice.result")
+}
+func (c *rVSliceConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVSliceConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Slice(_, _)", c.result, c.v)
+}
+
+func (c *rVSliceConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		var res nodeid
+		switch t := tDyn.Underlying().(type) {
+		case *types.Pointer:
+			if tArr, ok := t.Elem().Underlying().(*types.Array); ok {
+				// pointer to array
+				res = a.makeTagged(types.NewSlice(tArr.Elem()), c.cgn, nil)
+				if a.onlineCopy(res+1, payload) {
+					a.addWork(res + 1)
+				}
+			}
+
+		case *types.Array:
+			// TODO(adonovan): implement addressable
+			// arrays when we do indirect tagged objects.
+
+		case *types.Slice:
+			res = vObj
+
+		case *types.Basic:
+			if t == types.Typ[types.String] {
+				res = vObj
+			}
+		}
+
+		if res != 0 && a.addLabel(c.result, res) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Slice(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVSliceConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// -------------------- Standalone reflect functions --------------------
+
+func ext۰reflect۰Append(a *analysis, cgn *cgnode)      {} // TODO(adonovan)
+func ext۰reflect۰AppendSlice(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+func ext۰reflect۰Copy(a *analysis, cgn *cgnode)        {} // TODO(adonovan)
+
+// ---------- func ChanOf(ChanDir, Type) Type ----------
+
+// result = ChanOf(dir, t)
+type reflectChanOfConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+	dirs   []types.ChanDir
+}
+
+func (c *reflectChanOfConstraint) ptr() nodeid { return c.t }
+func (c *reflectChanOfConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectChanOf.result")
+}
+func (c *reflectChanOfConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectChanOfConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.ChanOf(n%d)", c.result, c.t)
+}
+
+func (c *reflectChanOfConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.rtypeTaggedValue(tObj)
+
+		if typeTooHigh(T) {
+			continue
+		}
+
+		for _, dir := range c.dirs {
+			if a.addLabel(c.result, a.makeRtype(types.NewChan(dir, T))) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+// dirMap maps reflect.ChanDir to the set of channel types generated by ChanOf.
+var dirMap = [...][]types.ChanDir{
+	0:               {types.SendOnly, types.RecvOnly, types.SendRecv}, // unknown
+	reflect.RecvDir: {types.RecvOnly},
+	reflect.SendDir: {types.SendOnly},
+	reflect.BothDir: {types.SendRecv},
+}
+
+func ext۰reflect۰ChanOf(a *analysis, cgn *cgnode) {
+	// If we have access to the callsite,
+	// and the channel argument is a constant (as is usual),
+	// only generate the requested direction.
+	var dir reflect.ChanDir // unknown
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			v, _ := exact.Int64Val(c.Value)
+			if 0 <= v && v <= int64(reflect.BothDir) {
+				dir = reflect.ChanDir(v)
+			}
+		}
+	}
+
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&reflectChanOfConstraint{
+		cgn:    cgn,
+		t:      params + 1,
+		result: a.funcResults(cgn.obj),
+		dirs:   dirMap[dir],
+	})
+}
+
+// ---------- func Indirect(v Value) Value ----------
+
+// result = Indirect(v)
+type reflectIndirectConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectIndirectConstraint) ptr() nodeid { return c.v }
+func (c *reflectIndirectConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectIndirect.result")
+}
+func (c *reflectIndirectConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectIndirectConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.Indirect(n%d)", c.result, c.v)
+}
+
+func (c *reflectIndirectConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, _, _ := a.taggedValue(vObj)
+		var res nodeid
+		if tPtr, ok := tDyn.Underlying().(*types.Pointer); ok {
+			// load the payload of the pointer's tagged object
+			// into a new tagged object
+			res = a.makeTagged(tPtr.Elem(), c.cgn, nil)
+			a.load(res+1, vObj+1, 0, a.sizeof(tPtr.Elem()))
+		} else {
+			res = vObj
+		}
+
+		if a.addLabel(c.result, res) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Indirect(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectIndirectConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func MakeChan(Type) Value ----------
+
+// result = MakeChan(typ)
+type reflectMakeChanConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectMakeChanConstraint) ptr() nodeid { return c.typ }
+func (c *reflectMakeChanConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectMakeChan.result")
+}
+func (c *reflectMakeChanConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectMakeChanConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.MakeChan(n%d)", c.result, c.typ)
+}
+
+func (c *reflectMakeChanConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+		tChan, ok := T.Underlying().(*types.Chan)
+		if !ok || tChan.Dir() != types.SendRecv {
+			continue // not a bidirectional channel type
+		}
+
+		obj := a.nextNode()
+		a.addNodes(tChan.Elem(), "reflect.MakeChan.value")
+		a.endObject(obj, c.cgn, nil)
+
+		// put its address in a new T-tagged object
+		id := a.makeTagged(T, c.cgn, nil)
+		a.addLabel(id+1, obj)
+
+		// flow the T-tagged object to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰MakeChan(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectMakeChanConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰MakeFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func MakeMap(Type) Value ----------
+
+// result = MakeMap(typ)
+type reflectMakeMapConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectMakeMapConstraint) ptr() nodeid { return c.typ }
+func (c *reflectMakeMapConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectMakeMap.result")
+}
+func (c *reflectMakeMapConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectMakeMapConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.MakeMap(n%d)", c.result, c.typ)
+}
+
+func (c *reflectMakeMapConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+		tMap, ok := T.Underlying().(*types.Map)
+		if !ok {
+			continue // not a map type
+		}
+
+		mapObj := a.nextNode()
+		a.addNodes(tMap.Key(), "reflect.MakeMap.key")
+		a.addNodes(tMap.Elem(), "reflect.MakeMap.value")
+		a.endObject(mapObj, c.cgn, nil)
+
+		// put its address in a new T-tagged object
+		id := a.makeTagged(T, c.cgn, nil)
+		a.addLabel(id+1, mapObj)
+
+		// flow the T-tagged object to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰MakeMap(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectMakeMapConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func MakeSlice(Type) Value ----------
+
+// result = MakeSlice(typ)
+type reflectMakeSliceConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectMakeSliceConstraint) ptr() nodeid { return c.typ }
+func (c *reflectMakeSliceConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectMakeSlice.result")
+}
+func (c *reflectMakeSliceConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectMakeSliceConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.MakeSlice(n%d)", c.result, c.typ)
+}
+
+func (c *reflectMakeSliceConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+		if _, ok := T.Underlying().(*types.Slice); !ok {
+			continue // not a slice type
+		}
+
+		obj := a.nextNode()
+		a.addNodes(sliceToArray(T), "reflect.MakeSlice")
+		a.endObject(obj, c.cgn, nil)
+
+		// put its address in a new T-tagged object
+		id := a.makeTagged(T, c.cgn, nil)
+		a.addLabel(id+1, obj)
+
+		// flow the T-tagged object to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰MakeSlice(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectMakeSliceConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰MapOf(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func New(Type) Value ----------
+
+// result = New(typ)
+type reflectNewConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectNewConstraint) ptr() nodeid { return c.typ }
+func (c *reflectNewConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectNew.result")
+}
+func (c *reflectNewConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectNewConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.New(n%d)", c.result, c.typ)
+}
+
+func (c *reflectNewConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+
+		// allocate new T object
+		newObj := a.nextNode()
+		a.addNodes(T, "reflect.New")
+		a.endObject(newObj, c.cgn, nil)
+
+		// put its address in a new *T-tagged object
+		id := a.makeTagged(types.NewPointer(T), c.cgn, nil)
+		a.addLabel(id+1, newObj)
+
+		// flow the pointer to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰New(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectNewConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰NewAt(a *analysis, cgn *cgnode) {
+	ext۰reflect۰New(a, cgn)
+
+	// TODO(adonovan): also report dynamic calls to unsound intrinsics.
+	if site := cgn.callersite; site != nil {
+		a.warnf(site.pos(), "unsound: %s contains a reflect.NewAt() call", site.instr.Parent())
+	}
+}
+
+// ---------- func PtrTo(Type) Type ----------
+
+// result = PtrTo(t)
+type reflectPtrToConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectPtrToConstraint) ptr() nodeid { return c.t }
+func (c *reflectPtrToConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectPtrTo.result")
+}
+func (c *reflectPtrToConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectPtrToConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.PtrTo(n%d)", c.result, c.t)
+}
+
+func (c *reflectPtrToConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.rtypeTaggedValue(tObj)
+
+		if typeTooHigh(T) {
+			continue
+		}
+
+		if a.addLabel(c.result, a.makeRtype(types.NewPointer(T))) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰PtrTo(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectPtrToConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰Select(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func SliceOf(Type) Type ----------
+
+// result = SliceOf(t)
+type reflectSliceOfConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectSliceOfConstraint) ptr() nodeid { return c.t }
+func (c *reflectSliceOfConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectSliceOf.result")
+}
+func (c *reflectSliceOfConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectSliceOfConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.SliceOf(n%d)", c.result, c.t)
+}
+
+func (c *reflectSliceOfConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.rtypeTaggedValue(tObj)
+
+		if typeTooHigh(T) {
+			continue
+		}
+
+		if a.addLabel(c.result, a.makeRtype(types.NewSlice(T))) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰SliceOf(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectSliceOfConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func TypeOf(v Value) Type ----------
+
+// result = TypeOf(i)
+type reflectTypeOfConstraint struct {
+	cgn    *cgnode
+	i      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectTypeOfConstraint) ptr() nodeid { return c.i }
+func (c *reflectTypeOfConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectTypeOf.result")
+}
+func (c *reflectTypeOfConstraint) renumber(mapping []nodeid) {
+	c.i = mapping[c.i]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectTypeOfConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.TypeOf(n%d)", c.result, c.i)
+}
+
+func (c *reflectTypeOfConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		iObj := nodeid(x)
+		tDyn, _, _ := a.taggedValue(iObj)
+		if a.addLabel(c.result, a.makeRtype(tDyn)) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰TypeOf(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectTypeOfConstraint{
+		cgn:    cgn,
+		i:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func ValueOf(interface{}) Value ----------
+
+func ext۰reflect۰ValueOf(a *analysis, cgn *cgnode) {
+	// TODO(adonovan): when we start creating indirect tagged
+	// objects, we'll need to handle them specially here since
+	// they must never appear in the PTS of an interface{}.
+	a.copy(a.funcResults(cgn.obj), a.funcParams(cgn.obj), 1)
+}
+
+// ---------- func Zero(Type) Value ----------
+
+// result = Zero(typ)
+type reflectZeroConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectZeroConstraint) ptr() nodeid { return c.typ }
+func (c *reflectZeroConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectZero.result")
+}
+func (c *reflectZeroConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectZeroConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.Zero(n%d)", c.result, c.typ)
+}
+
+func (c *reflectZeroConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+
+		// TODO(adonovan): if T is an interface type, we need
+		// to create an indirect tagged object containing
+		// new(T).  To avoid updates of such shared values,
+		// we'll need another flag on indirect tagged objects
+		// that marks whether they are addressable or
+		// readonly, just like the reflect package does.
+
+		// memoize using a.reflectZeros[T]
+		var id nodeid
+		if z := a.reflectZeros.At(T); false && z != nil {
+			id = z.(nodeid)
+		} else {
+			id = a.makeTagged(T, c.cgn, nil)
+			a.reflectZeros.Set(T, id)
+		}
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Zero(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectZeroConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// -------------------- (*reflect.rtype) methods --------------------
+
+// ---------- func (*rtype) Elem() Type ----------
+
+// result = Elem(t)
+type rtypeElemConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeElemConstraint) ptr() nodeid { return c.t }
+func (c *rtypeElemConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rtypeElem.result")
+}
+func (c *rtypeElemConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeElemConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).Elem(n%d)", c.result, c.t)
+}
+
+func (c *rtypeElemConstraint) solve(a *analysis, delta *nodeset) {
+	// Implemented by *types.{Map,Chan,Array,Slice,Pointer}.
+	type hasElem interface {
+		Elem() types.Type
+	}
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		if tHasElem, ok := T.Underlying().(hasElem); ok {
+			if a.addLabel(c.result, a.makeRtype(tHasElem.Elem())) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰rtype۰Elem(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rtypeElemConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (*rtype) Field(int) StructField ----------
+// ---------- func (*rtype) FieldByName(string) (StructField, bool) ----------
+
+// result = FieldByName(t, name)
+// result = Field(t, _)
+type rtypeFieldByNameConstraint struct {
+	cgn    *cgnode
+	name   string // name of field; "" for unknown
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeFieldByNameConstraint) ptr() nodeid { return c.t }
+func (c *rtypeFieldByNameConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result+3), "rtypeFieldByName.result.Type")
+}
+func (c *rtypeFieldByNameConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeFieldByNameConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).FieldByName(n%d, %q)", c.result, c.t, c.name)
+}
+
+func (c *rtypeFieldByNameConstraint) solve(a *analysis, delta *nodeset) {
+	// type StructField struct {
+	// 0	__identity__
+	// 1	Name      string
+	// 2	PkgPath   string
+	// 3	Type      Type
+	// 4	Tag       StructTag
+	// 5	Offset    uintptr
+	// 6	Index     []int
+	// 7	Anonymous bool
+	// }
+
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		tStruct, ok := T.Underlying().(*types.Struct)
+		if !ok {
+			continue // not a struct type
+		}
+
+		n := tStruct.NumFields()
+		for i := 0; i < n; i++ {
+			f := tStruct.Field(i)
+			if c.name == "" || c.name == f.Name() {
+
+				// a.offsetOf(Type) is 3.
+				if id := c.result + 3; a.addLabel(id, a.makeRtype(f.Type())) {
+					a.addWork(id)
+				}
+				// TODO(adonovan): StructField.Index should be non-nil.
+			}
+		}
+	}
+}
+
+func ext۰reflect۰rtype۰FieldByName(a *analysis, cgn *cgnode) {
+	// If we have access to the callsite,
+	// and the argument is a string constant,
+	// return only that field.
+	var name string
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			name = exact.StringVal(c.Value)
+		}
+	}
+
+	a.addConstraint(&rtypeFieldByNameConstraint{
+		cgn:    cgn,
+		name:   name,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰rtype۰Field(a *analysis, cgn *cgnode) {
+	// No-one ever calls Field with a constant argument,
+	// so we don't specialize that case.
+	a.addConstraint(&rtypeFieldByNameConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰rtype۰FieldByIndex(a *analysis, cgn *cgnode)    {} // TODO(adonovan)
+func ext۰reflect۰rtype۰FieldByNameFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (*rtype) In/Out(i int) Type ----------
+
+// result = In/Out(t, i)
+type rtypeInOutConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+	out    bool
+	i      int // -ve if not a constant
+}
+
+func (c *rtypeInOutConstraint) ptr() nodeid { return c.t }
+func (c *rtypeInOutConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rtypeInOut.result")
+}
+func (c *rtypeInOutConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeInOutConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).InOut(n%d, %d)", c.result, c.t, c.i)
+}
+
+func (c *rtypeInOutConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		sig, ok := T.Underlying().(*types.Signature)
+		if !ok {
+			continue // not a func type
+		}
+
+		tuple := sig.Params()
+		if c.out {
+			tuple = sig.Results()
+		}
+		for i, n := 0, tuple.Len(); i < n; i++ {
+			if c.i < 0 || c.i == i {
+				if a.addLabel(c.result, a.makeRtype(tuple.At(i).Type())) {
+					changed = true
+				}
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰rtype۰InOut(a *analysis, cgn *cgnode, out bool) {
+	// If we have access to the callsite,
+	// and the argument is an int constant,
+	// return only that parameter.
+	index := -1
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			v, _ := exact.Int64Val(c.Value)
+			index = int(v)
+		}
+	}
+	a.addConstraint(&rtypeInOutConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+		out:    out,
+		i:      index,
+	})
+}
+
+func ext۰reflect۰rtype۰In(a *analysis, cgn *cgnode) {
+	ext۰reflect۰rtype۰InOut(a, cgn, false)
+}
+
+func ext۰reflect۰rtype۰Out(a *analysis, cgn *cgnode) {
+	ext۰reflect۰rtype۰InOut(a, cgn, true)
+}
+
+// ---------- func (*rtype) Key() Type ----------
+
+// result = Key(t)
+type rtypeKeyConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeKeyConstraint) ptr() nodeid { return c.t }
+func (c *rtypeKeyConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rtypeKey.result")
+}
+func (c *rtypeKeyConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeKeyConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).Key(n%d)", c.result, c.t)
+}
+
+func (c *rtypeKeyConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		if tMap, ok := T.Underlying().(*types.Map); ok {
+			if a.addLabel(c.result, a.makeRtype(tMap.Key())) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰rtype۰Key(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rtypeKeyConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (*rtype) Method(int) (Method, bool) ----------
+// ---------- func (*rtype) MethodByName(string) (Method, bool) ----------
+
+// result = MethodByName(t, name)
+// result = Method(t, _)
+type rtypeMethodByNameConstraint struct {
+	cgn    *cgnode
+	name   string // name of method; "" for unknown
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeMethodByNameConstraint) ptr() nodeid { return c.t }
+func (c *rtypeMethodByNameConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result+3), "rtypeMethodByName.result.Type")
+	h.markIndirect(onodeid(c.result+4), "rtypeMethodByName.result.Func")
+}
+func (c *rtypeMethodByNameConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeMethodByNameConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).MethodByName(n%d, %q)", c.result, c.t, c.name)
+}
+
+// changeRecv returns sig with Recv prepended to Params().
+func changeRecv(sig *types.Signature) *types.Signature {
+	params := sig.Params()
+	n := params.Len()
+	p2 := make([]*types.Var, n+1)
+	p2[0] = sig.Recv()
+	for i := 0; i < n; i++ {
+		p2[i+1] = params.At(i)
+	}
+	return types.NewSignature(nil, nil, types.NewTuple(p2...), sig.Results(), sig.Variadic())
+}
+
+func (c *rtypeMethodByNameConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+
+		isIface := isInterface(T)
+
+		// We don't use Lookup(c.name) when c.name != "" to avoid
+		// ambiguity: >1 unexported methods could match.
+		mset := a.prog.MethodSets.MethodSet(T)
+		for i, n := 0, mset.Len(); i < n; i++ {
+			sel := mset.At(i)
+			if c.name == "" || c.name == sel.Obj().Name() {
+				// type Method struct {
+				// 0     __identity__
+				// 1	Name    string
+				// 2	PkgPath string
+				// 3	Type    Type
+				// 4	Func    Value
+				// 5	Index   int
+				// }
+
+				var sig *types.Signature
+				var fn *ssa.Function
+				if isIface {
+					sig = sel.Type().(*types.Signature)
+				} else {
+					fn = a.prog.Method(sel)
+					// move receiver to params[0]
+					sig = changeRecv(fn.Signature)
+				}
+
+				// a.offsetOf(Type) is 3.
+				if id := c.result + 3; a.addLabel(id, a.makeRtype(sig)) {
+					a.addWork(id)
+				}
+				if fn != nil {
+					// a.offsetOf(Func) is 4.
+					if id := c.result + 4; a.addLabel(id, a.objectNode(nil, fn)) {
+						a.addWork(id)
+					}
+				}
+			}
+		}
+	}
+}
+
+func ext۰reflect۰rtype۰MethodByName(a *analysis, cgn *cgnode) {
+	// If we have access to the callsite,
+	// and the argument is a string constant,
+	// return only that method.
+	var name string
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			name = exact.StringVal(c.Value)
+		}
+	}
+
+	a.addConstraint(&rtypeMethodByNameConstraint{
+		cgn:    cgn,
+		name:   name,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰rtype۰Method(a *analysis, cgn *cgnode) {
+	// No-one ever calls Method with a constant argument,
+	// so we don't specialize that case.
+	a.addConstraint(&rtypeMethodByNameConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// typeHeight returns the "height" of the type, which is roughly
+// speaking the number of chan, map, pointer and slice type constructors
+// at the root of T; these are the four type kinds that can be created
+// via reflection.  Chan and map constructors are counted as double the
+// height of slice and pointer constructors since they are less often
+// deeply nested.
+//
+// The solver rules for type constructors must somehow bound the set of
+// types they create to ensure termination of the algorithm in cases
+// where the output of a type constructor flows to its input, e.g.
+//
+// 	func f(t reflect.Type) {
+// 		f(reflect.PtrTo(t))
+// 	}
+//
+// It does this by limiting the type height to k, but this still leaves
+// a potentially exponential (4^k) number of of types that may be
+// enumerated in pathological cases.
+//
+func typeHeight(T types.Type) int {
+	switch T := T.(type) {
+	case *types.Chan:
+		return 2 + typeHeight(T.Elem())
+	case *types.Map:
+		k := typeHeight(T.Key())
+		v := typeHeight(T.Elem())
+		if v > k {
+			k = v // max(k, v)
+		}
+		return 2 + k
+	case *types.Slice:
+		return 1 + typeHeight(T.Elem())
+	case *types.Pointer:
+		return 1 + typeHeight(T.Elem())
+	}
+	return 0
+}
+
+func typeTooHigh(T types.Type) bool {
+	return typeHeight(T) > 3
+}
diff --git a/third_party/go.tools/go/pointer/solve.go b/third_party/go.tools/go/pointer/solve.go
new file mode 100644
index 0000000..81d24da
--- /dev/null
+++ b/third_party/go.tools/go/pointer/solve.go
@@ -0,0 +1,371 @@
+// Copyright 2013 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 pointer
+
+// This file defines a naive Andersen-style solver for the inclusion
+// constraint system.
+
+import (
+	"fmt"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+type solverState struct {
+	complex []constraint // complex constraints attached to this node
+	copyTo  nodeset      // simple copy constraint edges
+	pts     nodeset      // points-to set of this node
+	prevPTS nodeset      // pts(n) in previous iteration (for difference propagation)
+}
+
+func (a *analysis) solve() {
+	start("Solving")
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Solving constraints\n\n")
+	}
+
+	// Solver main loop.
+	var delta nodeset
+	for {
+		// Add new constraints to the graph:
+		// static constraints from SSA on round 1,
+		// dynamic constraints from reflection thereafter.
+		a.processNewConstraints()
+
+		var x int
+		if !a.work.TakeMin(&x) {
+			break // empty
+		}
+		id := nodeid(x)
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\tnode n%d\n", id)
+		}
+
+		n := a.nodes[id]
+
+		// Difference propagation.
+		delta.Difference(&n.solve.pts.Sparse, &n.solve.prevPTS.Sparse)
+		if delta.IsEmpty() {
+			continue
+		}
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\t\tpts(n%d : %s) = %s + %s\n",
+				id, n.typ, &delta, &n.solve.prevPTS)
+		}
+		n.solve.prevPTS.Copy(&n.solve.pts.Sparse)
+
+		// Apply all resolution rules attached to n.
+		a.solveConstraints(n, &delta)
+
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\t\tpts(n%d) = %s\n", id, &n.solve.pts)
+		}
+	}
+
+	if !a.nodes[0].solve.pts.IsEmpty() {
+		panic(fmt.Sprintf("pts(0) is nonempty: %s", &a.nodes[0].solve.pts))
+	}
+
+	// Release working state (but keep final PTS).
+	for _, n := range a.nodes {
+		n.solve.complex = nil
+		n.solve.copyTo.Clear()
+		n.solve.prevPTS.Clear()
+	}
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "Solver done\n")
+
+		// Dump solution.
+		for i, n := range a.nodes {
+			if !n.solve.pts.IsEmpty() {
+				fmt.Fprintf(a.log, "pts(n%d) = %s : %s\n", i, &n.solve.pts, n.typ)
+			}
+		}
+	}
+	stop("Solving")
+}
+
+// processNewConstraints takes the new constraints from a.constraints
+// and adds them to the graph, ensuring
+// that new constraints are applied to pre-existing labels and
+// that pre-existing constraints are applied to new labels.
+//
+func (a *analysis) processNewConstraints() {
+	// Take the slice of new constraints.
+	// (May grow during call to solveConstraints.)
+	constraints := a.constraints
+	a.constraints = nil
+
+	// Initialize points-to sets from addr-of (base) constraints.
+	for _, c := range constraints {
+		if c, ok := c.(*addrConstraint); ok {
+			dst := a.nodes[c.dst]
+			dst.solve.pts.add(c.src)
+
+			// Populate the worklist with nodes that point to
+			// something initially (due to addrConstraints) and
+			// have other constraints attached.
+			// (A no-op in round 1.)
+			if !dst.solve.copyTo.IsEmpty() || len(dst.solve.complex) > 0 {
+				a.addWork(c.dst)
+			}
+		}
+	}
+
+	// Attach simple (copy) and complex constraints to nodes.
+	var stale nodeset
+	for _, c := range constraints {
+		var id nodeid
+		switch c := c.(type) {
+		case *addrConstraint:
+			// base constraints handled in previous loop
+			continue
+		case *copyConstraint:
+			// simple (copy) constraint
+			id = c.src
+			a.nodes[id].solve.copyTo.add(c.dst)
+		default:
+			// complex constraint
+			id = c.ptr()
+			solve := a.nodes[id].solve
+			solve.complex = append(solve.complex, c)
+		}
+
+		if n := a.nodes[id]; !n.solve.pts.IsEmpty() {
+			if !n.solve.prevPTS.IsEmpty() {
+				stale.add(id)
+			}
+			a.addWork(id)
+		}
+	}
+	// Apply new constraints to pre-existing PTS labels.
+	var space [50]int
+	for _, id := range stale.AppendTo(space[:0]) {
+		n := a.nodes[nodeid(id)]
+		a.solveConstraints(n, &n.solve.prevPTS)
+	}
+}
+
+// solveConstraints applies each resolution rule attached to node n to
+// the set of labels delta.  It may generate new constraints in
+// a.constraints.
+//
+func (a *analysis) solveConstraints(n *node, delta *nodeset) {
+	if delta.IsEmpty() {
+		return
+	}
+
+	// Process complex constraints dependent on n.
+	for _, c := range n.solve.complex {
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\t\tconstraint %s\n", c)
+		}
+		c.solve(a, delta)
+	}
+
+	// Process copy constraints.
+	var copySeen nodeset
+	for _, x := range n.solve.copyTo.AppendTo(a.deltaSpace) {
+		mid := nodeid(x)
+		if copySeen.add(mid) {
+			if a.nodes[mid].solve.pts.addAll(delta) {
+				a.addWork(mid)
+			}
+		}
+	}
+}
+
+// addLabel adds label to the points-to set of ptr and reports whether the set grew.
+func (a *analysis) addLabel(ptr, label nodeid) bool {
+	b := a.nodes[ptr].solve.pts.add(label)
+	if b && a.log != nil {
+		fmt.Fprintf(a.log, "\t\tpts(n%d) += n%d\n", ptr, label)
+	}
+	return b
+}
+
+func (a *analysis) addWork(id nodeid) {
+	a.work.Insert(int(id))
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t\twork: n%d\n", id)
+	}
+}
+
+// onlineCopy adds a copy edge.  It is called online, i.e. during
+// solving, so it adds edges and pts members directly rather than by
+// instantiating a 'constraint'.
+//
+// The size of the copy is implicitly 1.
+// It returns true if pts(dst) changed.
+//
+func (a *analysis) onlineCopy(dst, src nodeid) bool {
+	if dst != src {
+		if nsrc := a.nodes[src]; nsrc.solve.copyTo.add(dst) {
+			if a.log != nil {
+				fmt.Fprintf(a.log, "\t\t\tdynamic copy n%d <- n%d\n", dst, src)
+			}
+			// TODO(adonovan): most calls to onlineCopy
+			// are followed by addWork, possibly batched
+			// via a 'changed' flag; see if there's a
+			// noticeable penalty to calling addWork here.
+			return a.nodes[dst].solve.pts.addAll(&nsrc.solve.pts)
+		}
+	}
+	return false
+}
+
+// Returns sizeof.
+// Implicitly adds nodes to worklist.
+//
+// TODO(adonovan): now that we support a.copy() during solving, we
+// could eliminate onlineCopyN, but it's much slower.  Investigate.
+//
+func (a *analysis) onlineCopyN(dst, src nodeid, sizeof uint32) uint32 {
+	for i := uint32(0); i < sizeof; i++ {
+		if a.onlineCopy(dst, src) {
+			a.addWork(dst)
+		}
+		src++
+		dst++
+	}
+	return sizeof
+}
+
+func (c *loadConstraint) solve(a *analysis, delta *nodeset) {
+	var changed bool
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		k := nodeid(x)
+		koff := k + nodeid(c.offset)
+		if a.onlineCopy(c.dst, koff) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.dst)
+	}
+}
+
+func (c *storeConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		k := nodeid(x)
+		koff := k + nodeid(c.offset)
+		if a.onlineCopy(koff, c.src) {
+			a.addWork(koff)
+		}
+	}
+}
+
+func (c *offsetAddrConstraint) solve(a *analysis, delta *nodeset) {
+	dst := a.nodes[c.dst]
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		k := nodeid(x)
+		if dst.solve.pts.add(k + nodeid(c.offset)) {
+			a.addWork(c.dst)
+		}
+	}
+}
+
+func (c *typeFilterConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		ifaceObj := nodeid(x)
+		tDyn, _, indirect := a.taggedValue(ifaceObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		if types.AssignableTo(tDyn, c.typ) {
+			if a.addLabel(c.dst, ifaceObj) {
+				a.addWork(c.dst)
+			}
+		}
+	}
+}
+
+func (c *untagConstraint) solve(a *analysis, delta *nodeset) {
+	predicate := types.AssignableTo
+	if c.exact {
+		predicate = types.Identical
+	}
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		ifaceObj := nodeid(x)
+		tDyn, v, indirect := a.taggedValue(ifaceObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		if predicate(tDyn, c.typ) {
+			// Copy payload sans tag to dst.
+			//
+			// TODO(adonovan): opt: if tDyn is
+			// nonpointerlike we can skip this entire
+			// constraint, perhaps.  We only care about
+			// pointers among the fields.
+			a.onlineCopyN(c.dst, v, a.sizeof(tDyn))
+		}
+	}
+}
+
+func (c *invokeConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		ifaceObj := nodeid(x)
+		tDyn, v, indirect := a.taggedValue(ifaceObj)
+		if indirect {
+			// TODO(adonovan): we may need to implement this if
+			// we ever apply invokeConstraints to reflect.Value PTSs,
+			// e.g. for (reflect.Value).Call.
+			panic("indirect tagged object")
+		}
+
+		// Look up the concrete method.
+		fn := a.prog.LookupMethod(tDyn, c.method.Pkg(), c.method.Name())
+		if fn == nil {
+			panic(fmt.Sprintf("n%d: no ssa.Function for %s", c.iface, c.method))
+		}
+		sig := fn.Signature
+
+		fnObj := a.globalobj[fn] // dynamic calls use shared contour
+		if fnObj == 0 {
+			// a.objectNode(fn) was not called during gen phase.
+			panic(fmt.Sprintf("a.globalobj[%s]==nil", fn))
+		}
+
+		// Make callsite's fn variable point to identity of
+		// concrete method.  (There's no need to add it to
+		// worklist since it never has attached constraints.)
+		a.addLabel(c.params, fnObj)
+
+		// Extract value and connect to method's receiver.
+		// Copy payload to method's receiver param (arg0).
+		arg0 := a.funcParams(fnObj)
+		recvSize := a.sizeof(sig.Recv().Type())
+		a.onlineCopyN(arg0, v, recvSize)
+
+		src := c.params + 1 // skip past identity
+		dst := arg0 + nodeid(recvSize)
+
+		// Copy caller's argument block to method formal parameters.
+		paramsSize := a.sizeof(sig.Params())
+		a.onlineCopyN(dst, src, paramsSize)
+		src += nodeid(paramsSize)
+		dst += nodeid(paramsSize)
+
+		// Copy method results to caller's result block.
+		resultsSize := a.sizeof(sig.Results())
+		a.onlineCopyN(src, dst, resultsSize)
+	}
+}
+
+func (c *addrConstraint) solve(a *analysis, delta *nodeset) {
+	panic("addr is not a complex constraint")
+}
+
+func (c *copyConstraint) solve(a *analysis, delta *nodeset) {
+	panic("copy is not a complex constraint")
+}
diff --git a/third_party/go.tools/go/pointer/stdlib_test.go b/third_party/go.tools/go/pointer/stdlib_test.go
new file mode 100644
index 0000000..028b733
--- /dev/null
+++ b/third_party/go.tools/go/pointer/stdlib_test.go
@@ -0,0 +1,108 @@
+// Copyright 2014 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 pointer
+
+// This file runs the pointer analysis on all packages and tests beneath
+// $GOROOT.  It provides a "smoke test" that the analysis doesn't crash
+// on a large input, and a benchmark for performance measurement.
+//
+// Because it is relatively slow, the --stdlib flag must be enabled for
+// this test to run:
+//    % go test -v golang.org/x/tools/go/pointer --stdlib
+
+import (
+	"flag"
+	"go/build"
+	"go/token"
+	"testing"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/go/buildutil"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/ssa/ssautil"
+)
+
+var runStdlibTest = flag.Bool("stdlib", false, "Run the (slow) stdlib test")
+
+func TestStdlib(t *testing.T) {
+	if !*runStdlibTest {
+		t.Skip("skipping (slow) stdlib test (use --stdlib)")
+	}
+
+	// Load, parse and type-check the program.
+	ctxt := build.Default // copy
+	ctxt.GOPATH = ""      // disable GOPATH
+	conf := loader.Config{
+		SourceImports: true,
+		Build:         &ctxt,
+	}
+	if _, err := conf.FromArgs(buildutil.AllPackages(conf.Build), true); err != nil {
+		t.Errorf("FromArgs failed: %v", err)
+		return
+	}
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+
+	// Create SSA packages.
+	prog := ssa.Create(iprog, 0)
+	prog.BuildAll()
+
+	numPkgs := len(prog.AllPackages())
+	if want := 240; numPkgs < want {
+		t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
+	}
+
+	// Determine the set of packages/tests to analyze.
+	var testPkgs []*ssa.Package
+	for _, info := range iprog.InitialPackages() {
+		testPkgs = append(testPkgs, prog.Package(info.Pkg))
+	}
+	testmain := prog.CreateTestMainPackage(testPkgs...)
+	if testmain == nil {
+		t.Fatal("analysis scope has tests")
+	}
+
+	// Run the analysis.
+	config := &Config{
+		Reflection:     false, // TODO(adonovan): fix remaining bug in rVCallConstraint, then enable.
+		BuildCallGraph: true,
+		Mains:          []*ssa.Package{testmain},
+	}
+	// TODO(adonovan): add some query values (affects track bits).
+
+	t0 := time.Now()
+
+	result, err := Analyze(config)
+	if err != nil {
+		t.Fatal(err) // internal error in pointer analysis
+	}
+	_ = result // TODO(adonovan): measure something
+
+	t1 := time.Now()
+
+	// Dump some statistics.
+	allFuncs := ssautil.AllFunctions(prog)
+	var numInstrs int
+	for fn := range allFuncs {
+		for _, b := range fn.Blocks {
+			numInstrs += len(b.Instrs)
+		}
+	}
+
+	// determine line count
+	var lineCount int
+	prog.Fset.Iterate(func(f *token.File) bool {
+		lineCount += f.LineCount()
+		return true
+	})
+
+	t.Log("#Source lines:          ", lineCount)
+	t.Log("#Instructions:          ", numInstrs)
+	t.Log("Pointer analysis:       ", t1.Sub(t0))
+}
diff --git a/third_party/go.tools/go/pointer/testdata/a_test.go b/third_party/go.tools/go/pointer/testdata/a_test.go
new file mode 100644
index 0000000..3baa9ac
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/a_test.go
@@ -0,0 +1,42 @@
+// +build ignore
+
+package a
+
+// This test exercises the synthesis of testmain packages for tests.
+// The test framework doesn't directly let us perform negative
+// assertions (i.e. that TestingQuux isn't called, or that its
+// parameter's PTS is empty) so this test is rather roundabout.
+
+import "testing"
+
+func log(f func(*testing.T)) {
+	// The PTS of f is the set of called tests.  TestingQuux is not present.
+	print(f) // @pointsto main.Test | main.TestFoo
+}
+
+func Test(t *testing.T) {
+	// Don't assert @pointsto(t) since its label contains a fragile line number.
+	log(Test)
+}
+
+func TestFoo(t *testing.T) {
+	// Don't assert @pointsto(t) since its label contains a fragile line number.
+	log(TestFoo)
+}
+
+func TestingQuux(t *testing.T) {
+	// We can't assert @pointsto(t) since this is dead code.
+	log(TestingQuux)
+}
+
+func BenchmarkFoo(b *testing.B) {
+}
+
+func ExampleBar() {
+}
+
+// Excludes TestingQuux.
+// @calls testing.tRunner -> main.Test
+// @calls testing.tRunner -> main.TestFoo
+// @calls testing.runExample -> main.ExampleBar
+// @calls (*testing.B).runN -> main.BenchmarkFoo
diff --git a/third_party/go.tools/go/pointer/testdata/another.go b/third_party/go.tools/go/pointer/testdata/another.go
new file mode 100644
index 0000000..443c94d
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/another.go
@@ -0,0 +1,34 @@
+// +build ignore
+
+package main
+
+var unknown bool
+
+type S string
+
+func incr(x int) int { return x + 1 }
+
+func main() {
+	var i interface{}
+	i = 1
+	if unknown {
+		i = S("foo")
+	}
+	if unknown {
+		i = (func(int, int))(nil) // NB type compares equal to that below.
+	}
+	// Look, the test harness can handle equal-but-not-String-equal
+	// types because we parse types and using a typemap.
+	if unknown {
+		i = (func(x int, y int))(nil)
+	}
+	if unknown {
+		i = incr
+	}
+	print(i) // @types int | S | func(int, int) | func(int) int
+
+	// NB, an interface may never directly alias any global
+	// labels, even though it may contain pointers that do.
+	print(i)                 // @pointsto makeinterface:func(x int) int | makeinterface:func(x int, y int) | makeinterface:func(int, int) | makeinterface:int | makeinterface:main.S
+	print(i.(func(int) int)) // @pointsto main.incr
+}
diff --git a/third_party/go.tools/go/pointer/testdata/arrayreflect.go b/third_party/go.tools/go/pointer/testdata/arrayreflect.go
new file mode 100644
index 0000000..2b23674
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/arrayreflect.go
@@ -0,0 +1,191 @@
+// +build ignore
+
+package main
+
+// Test of arrays & slices with reflection.
+
+import "reflect"
+
+var a, b int
+
+type S string
+
+func reflectValueSlice() {
+	// reflect.Value contains a slice.
+	slice := make([]*int, 10) // @line slice
+	slice[0] = &a
+	rvsl := reflect.ValueOf(slice).Slice(0, 0)
+	print(rvsl.Interface())              // @types []*int
+	print(rvsl.Interface().([]*int))     // @pointsto makeslice@slice:15
+	print(rvsl.Interface().([]*int)[42]) // @pointsto main.a
+
+	// reflect.Value contains an array (non-addressable).
+	array := [10]*int{&a} // @line array
+	rvarray := reflect.ValueOf(array).Slice(0, 0)
+	print(rvarray.Interface())              // @types
+	print(rvarray.Interface().([]*int))     // @pointsto
+	print(rvarray.Interface().([]*int)[42]) // @pointsto
+
+	// reflect.Value contains a pointer-to-array
+	rvparray := reflect.ValueOf(&array).Slice(0, 0)
+	print(rvparray.Interface())              // @types []*int
+	print(rvparray.Interface().([]*int))     // @pointsto array@array:2
+	print(rvparray.Interface().([]*int)[42]) // @pointsto main.a
+
+	// reflect.Value contains a string.
+	rvstring := reflect.ValueOf("hi").Slice(0, 0)
+	print(rvstring.Interface()) // @types string
+
+	// reflect.Value contains a (named) string type.
+	rvS := reflect.ValueOf(S("hi")).Slice(0, 0)
+	print(rvS.Interface()) // @types S
+
+	// reflect.Value contains a non-array pointer.
+	rvptr := reflect.ValueOf(new(int)).Slice(0, 0)
+	print(rvptr.Interface()) // @types
+
+	// reflect.Value contains a non-string basic type.
+	rvint := reflect.ValueOf(3).Slice(0, 0)
+	print(rvint.Interface()) // @types
+}
+
+func reflectValueBytes() {
+	sl1 := make([]byte, 0) // @line ar5sl1
+	sl2 := make([]byte, 0) // @line ar5sl2
+
+	rvsl1 := reflect.ValueOf(sl1)
+	print(rvsl1.Interface())          // @types []byte
+	print(rvsl1.Interface().([]byte)) // @pointsto makeslice@ar5sl1:13
+	print(rvsl1.Bytes())              // @pointsto makeslice@ar5sl1:13
+
+	rvsl2 := reflect.ValueOf(123)
+	rvsl2.SetBytes(sl2)
+	print(rvsl2.Interface())          // @types int
+	print(rvsl2.Interface().([]byte)) // @pointsto
+	print(rvsl2.Bytes())              // @pointsto
+
+	rvsl3 := reflect.ValueOf([]byte(nil))
+	rvsl3.SetBytes(sl2)
+	print(rvsl3.Interface())          // @types []byte
+	print(rvsl3.Interface().([]byte)) // @pointsto makeslice@ar5sl2:13
+	print(rvsl3.Bytes())              // @pointsto makeslice@ar5sl2:13
+}
+
+func reflectValueIndex() {
+	slice := []*int{&a} // @line ar6slice
+	rv1 := reflect.ValueOf(slice)
+	print(rv1.Index(42).Interface())        // @types *int
+	print(rv1.Index(42).Interface().(*int)) // @pointsto main.a
+
+	array := [10]*int{&a}
+	rv2 := reflect.ValueOf(array)
+	print(rv2.Index(42).Interface())        // @types *int
+	print(rv2.Index(42).Interface().(*int)) // @pointsto main.a
+
+	rv3 := reflect.ValueOf("string")
+	print(rv3.Index(42).Interface()) // @types rune
+
+	rv4 := reflect.ValueOf(&array)
+	print(rv4.Index(42).Interface()) // @types
+
+	rv5 := reflect.ValueOf(3)
+	print(rv5.Index(42).Interface()) // @types
+}
+
+func reflectValueElem() {
+	// Interface.
+	var iface interface{} = &a
+	rv1 := reflect.ValueOf(&iface).Elem()
+	print(rv1.Interface())               // @types *int
+	print(rv1.Interface().(*int))        // @pointsto main.a
+	print(rv1.Elem().Interface())        // @types *int
+	print(rv1.Elem().Interface().(*int)) // @pointsto main.a
+
+	print(reflect.ValueOf(new(interface{})).Elem().Elem()) // @types
+
+	// Pointer.
+	ptr := &a
+	rv2 := reflect.ValueOf(&ptr)
+	print(rv2.Elem().Interface())        // @types *int
+	print(rv2.Elem().Interface().(*int)) // @pointsto main.a
+
+	// No other type works with (rV).Elem, not even those that
+	// work with (rT).Elem: slice, array, map, chan.
+
+	rv3 := reflect.ValueOf([]*int{&a})
+	print(rv3.Elem().Interface()) // @types
+
+	rv4 := reflect.ValueOf([10]*int{&a})
+	print(rv4.Elem().Interface()) // @types
+
+	rv5 := reflect.ValueOf(map[*int]*int{&a: &b})
+	print(rv5.Elem().Interface()) // @types
+
+	ch := make(chan *int)
+	ch <- &a
+	rv6 := reflect.ValueOf(ch)
+	print(rv6.Elem().Interface()) // @types
+
+	rv7 := reflect.ValueOf(3)
+	print(rv7.Elem().Interface()) // @types
+}
+
+func reflectTypeElem() {
+	rt1 := reflect.TypeOf(make([]*int, 0))
+	print(reflect.Zero(rt1.Elem())) // @types *int
+
+	rt2 := reflect.TypeOf([10]*int{})
+	print(reflect.Zero(rt2.Elem())) // @types *int
+
+	rt3 := reflect.TypeOf(map[*int]*int{})
+	print(reflect.Zero(rt3.Elem())) // @types *int
+
+	rt4 := reflect.TypeOf(make(chan *int))
+	print(reflect.Zero(rt4.Elem())) // @types *int
+
+	ptr := &a
+	rt5 := reflect.TypeOf(&ptr)
+	print(reflect.Zero(rt5.Elem())) // @types *int
+
+	rt6 := reflect.TypeOf(3)
+	print(reflect.Zero(rt6.Elem())) // @types
+}
+
+func reflectPtrTo() {
+	tInt := reflect.TypeOf(3)
+	tPtrInt := reflect.PtrTo(tInt)
+	print(reflect.Zero(tPtrInt)) // @types *int
+	tPtrPtrInt := reflect.PtrTo(tPtrInt)
+	print(reflect.Zero(tPtrPtrInt)) // @types **int
+}
+
+func reflectSliceOf() {
+	tInt := reflect.TypeOf(3)
+	tSliceInt := reflect.SliceOf(tInt)
+	print(reflect.Zero(tSliceInt)) // @types []int
+}
+
+type T struct{ x int }
+
+func reflectMakeSlice() {
+	rt := []reflect.Type{
+		reflect.TypeOf(3),
+		reflect.TypeOf([]int{}),
+		reflect.TypeOf([]T{}),
+	}[0]
+	sl := reflect.MakeSlice(rt, 0, 0)
+	print(sl)                         // @types []int | []T
+	print(sl)                         // @pointsto <alloc in reflect.MakeSlice> | <alloc in reflect.MakeSlice>
+	print(&sl.Interface().([]T)[0].x) // @pointsto <alloc in reflect.MakeSlice>[*].x
+}
+
+func main() {
+	reflectValueSlice()
+	reflectValueBytes()
+	reflectValueIndex()
+	reflectValueElem()
+	reflectTypeElem()
+	reflectPtrTo()
+	reflectSliceOf()
+	reflectMakeSlice()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/arrays.go b/third_party/go.tools/go/pointer/testdata/arrays.go
new file mode 100644
index 0000000..e57a15b
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/arrays.go
@@ -0,0 +1,97 @@
+// +build ignore
+
+package main
+
+var unknown bool // defeat dead-code elimination
+
+var a, b int
+
+func array1() {
+	sliceA := make([]*int, 10) // @line a1make
+	sliceA[0] = &a
+
+	var sliceB []*int
+	sliceB = append(sliceB, &b) // @line a1append
+
+	print(sliceA)    // @pointsto makeslice@a1make:16
+	print(sliceA[0]) // @pointsto main.a
+
+	print(sliceB)      // @pointsto append@a1append:17
+	print(sliceB[100]) // @pointsto main.b
+}
+
+func array2() {
+	sliceA := make([]*int, 10) // @line a2make
+	sliceA[0] = &a
+
+	sliceB := sliceA[:]
+
+	print(sliceA)    // @pointsto makeslice@a2make:16
+	print(sliceA[0]) // @pointsto main.a
+
+	print(sliceB)    // @pointsto makeslice@a2make:16
+	print(sliceB[0]) // @pointsto main.a
+}
+
+func array3() {
+	a := []interface{}{"", 1}
+	b := []interface{}{true, func() {}}
+	print(a[0]) // @types string | int
+	print(b[0]) // @types bool | func()
+}
+
+// Test of append, copy, slice.
+func array4() {
+	var s2 struct { // @line a4L0
+		a [3]int
+		b struct{ c, d int }
+	}
+	var sl1 = make([]*int, 10) // @line a4make
+	var someint int            // @line a4L1
+	sl1[1] = &someint
+	sl2 := append(sl1, &s2.a[1]) // @line a4append1
+	print(sl1)                   // @pointsto makeslice@a4make:16
+	print(sl2)                   // @pointsto append@a4append1:15 | makeslice@a4make:16
+	print(sl1[0])                // @pointsto someint@a4L1:6 | s2.a[*]@a4L0:6
+	print(sl2[0])                // @pointsto someint@a4L1:6 | s2.a[*]@a4L0:6
+
+	// In z=append(x,y) we should observe flow from y[*] to x[*].
+	var sl3 = make([]*int, 10) // @line a4L2
+	_ = append(sl3, &s2.a[1])
+	print(sl3)    // @pointsto makeslice@a4L2:16
+	print(sl3[0]) // @pointsto s2.a[*]@a4L0:6
+
+	var sl4 = []*int{&a} // @line a4L3
+	sl4a := append(sl4)  // @line a4L4
+	print(sl4a)          // @pointsto slicelit@a4L3:18 | append@a4L4:16
+	print(&sl4a[0])      // @pointsto slicelit[*]@a4L3:18 | append[*]@a4L4:16
+	print(sl4a[0])       // @pointsto main.a
+
+	var sl5 = []*int{&b} // @line a4L5
+	copy(sl5, sl4)
+	print(sl5)     // @pointsto slicelit@a4L5:18
+	print(&sl5[0]) // @pointsto slicelit[*]@a4L5:18
+	print(sl5[0])  // @pointsto main.b | main.a
+
+	var sl6 = sl5[:0]
+	print(sl6)     // @pointsto slicelit@a4L5:18
+	print(&sl6[0]) // @pointsto slicelit[*]@a4L5:18
+	print(sl6[0])  // @pointsto main.b | main.a
+}
+
+func array5() {
+	var arr [2]*int
+	arr[0] = &a
+	arr[1] = &b
+
+	var n int
+	print(arr[n]) // @pointsto main.a | main.b
+}
+
+func main() {
+	array1()
+	array2()
+	array3()
+	array4()
+	array5()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/channels.go b/third_party/go.tools/go/pointer/testdata/channels.go
new file mode 100644
index 0000000..76eb5f8
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/channels.go
@@ -0,0 +1,118 @@
+// +build ignore
+
+package main
+
+func incr(x int) int { return x + 1 }
+
+func decr(x int) int { return x - 1 }
+
+var unknown bool // defeat dead-code elimination
+
+func chan1() {
+	chA := make(chan func(int) int, 0) // @line c1makeA
+	chB := make(chan func(int) int, 0) // @line c1makeB
+	chA <- incr
+	chB <- decr
+	chB <- func(int) int { return 1 }
+
+	print(chA)   // @pointsto makechan@c1makeA:13
+	print(<-chA) // @pointsto main.incr
+
+	print(chB)   // @pointsto makechan@c1makeB:13
+	print(<-chB) // @pointsto main.decr | main.chan1$1
+}
+
+func chan2() {
+	chA := make(chan func(int) int, 0) // @line c2makeA
+	chB := make(chan func(int) int, 0) // @line c2makeB
+	chA <- incr
+	chB <- decr
+	chB <- func(int) int { return 1 }
+
+	// Channels flow together.
+	// Labelsets remain distinct but elements are merged.
+	chAB := chA
+	if unknown {
+		chAB = chB
+	}
+
+	print(chA)   // @pointsto makechan@c2makeA:13
+	print(<-chA) // @pointsto main.incr
+
+	print(chB)   // @pointsto makechan@c2makeB:13
+	print(<-chB) // @pointsto main.decr | main.chan2$1
+
+	print(chAB)   // @pointsto makechan@c2makeA:13 | makechan@c2makeB:13
+	print(<-chAB) // @pointsto main.incr | main.decr | main.chan2$1
+
+	(<-chA)(3)
+}
+
+// @calls main.chan2 -> main.incr
+
+func chan3() {
+	chA := make(chan func(int) int, 0) // @line c3makeA
+	chB := make(chan func(int) int, 0) // @line c3makeB
+	chA <- incr
+	chB <- decr
+	chB <- func(int) int { return 1 }
+	print(chA)   // @pointsto makechan@c3makeA:13
+	print(<-chA) // @pointsto main.incr
+	print(chB)   // @pointsto makechan@c3makeB:13
+	print(<-chB) // @pointsto main.decr | main.chan3$1
+
+	(<-chA)(3)
+}
+
+// @calls main.chan3 -> main.incr
+
+func chan4() {
+	chA := make(chan func(int) int, 0) // @line c4makeA
+	chB := make(chan func(int) int, 0) // @line c4makeB
+
+	select {
+	case chA <- incr:
+	case chB <- decr:
+	case a := <-chA:
+		print(a) // @pointsto main.incr
+	case b := <-chB:
+		print(b) // @pointsto main.decr
+	default:
+		print(chA) // @pointsto makechan@c4makeA:13
+		print(chB) // @pointsto makechan@c4makeB:13
+	}
+
+	for k := range chA {
+		print(k) // @pointsto main.incr
+	}
+	// Exercise constraint generation (regtest for a crash).
+	for _ = range chA {
+	}
+}
+
+// Multi-word channel value in select with multiple receive cases.
+// (Regtest for a crash.)
+func chan5() {
+	type T struct {
+		x *int
+		y interface{}
+	}
+	ch := make(chan T)
+	ch <- T{new(int), incr} // @line ch5new
+	select {
+	case a := <-ch:
+		print(a.x) // @pointsto new@ch5new:13
+		print(a.y) // @types func(x int) int
+	case b := <-ch:
+		print(b.x) // @pointsto new@ch5new:13
+		print(b.y) // @types func(x int) int
+	}
+}
+
+func main() {
+	chan1()
+	chan2()
+	chan3()
+	chan4()
+	chan5()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/chanreflect.go b/third_party/go.tools/go/pointer/testdata/chanreflect.go
new file mode 100644
index 0000000..7d22efe
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/chanreflect.go
@@ -0,0 +1,85 @@
+// +build ignore
+
+package main
+
+import "reflect"
+
+// Test of channels with reflection.
+
+var a, b int
+
+func chanreflect1() {
+	ch := make(chan *int, 0) // @line cr1make
+	crv := reflect.ValueOf(ch)
+	crv.Send(reflect.ValueOf(&a))
+	print(crv.Interface())             // @types chan *int
+	print(crv.Interface().(chan *int)) // @pointsto makechan@cr1make:12
+	print(<-ch)                        // @pointsto main.a
+}
+
+func chanreflect1i() {
+	// Exercises reflect.Value conversions to/from interfaces:
+	// a different code path than for concrete types.
+	ch := make(chan interface{}, 0)
+	reflect.ValueOf(ch).Send(reflect.ValueOf(&a))
+	v := <-ch
+	print(v)        // @types *int
+	print(v.(*int)) // @pointsto main.a
+}
+
+func chanreflect2() {
+	ch := make(chan *int, 0)
+	ch <- &b
+	crv := reflect.ValueOf(ch)
+	r, _ := crv.Recv()
+	print(r.Interface())        // @types *int
+	print(r.Interface().(*int)) // @pointsto main.b
+}
+
+func chanOfRecv() {
+	// MakeChan(<-chan) is a no-op.
+	t := reflect.ChanOf(reflect.RecvDir, reflect.TypeOf(&a))
+	print(reflect.Zero(t).Interface())                      // @types <-chan *int
+	print(reflect.MakeChan(t, 0).Interface().(<-chan *int)) // @pointsto
+	print(reflect.MakeChan(t, 0).Interface().(chan *int))   // @pointsto
+}
+
+func chanOfSend() {
+	// MakeChan(chan<-) is a no-op.
+	t := reflect.ChanOf(reflect.SendDir, reflect.TypeOf(&a))
+	print(reflect.Zero(t).Interface())                      // @types chan<- *int
+	print(reflect.MakeChan(t, 0).Interface().(chan<- *int)) // @pointsto
+	print(reflect.MakeChan(t, 0).Interface().(chan *int))   // @pointsto
+}
+
+func chanOfBoth() {
+	t := reflect.ChanOf(reflect.BothDir, reflect.TypeOf(&a))
+	print(reflect.Zero(t).Interface()) // @types chan *int
+	ch := reflect.MakeChan(t, 0)
+	print(ch.Interface().(chan *int)) // @pointsto <alloc in reflect.MakeChan>
+	ch.Send(reflect.ValueOf(&b))
+	ch.Interface().(chan *int) <- &a
+	r, _ := ch.Recv()
+	print(r.Interface().(*int))         // @pointsto main.a | main.b
+	print(<-ch.Interface().(chan *int)) // @pointsto main.a | main.b
+}
+
+var unknownDir reflect.ChanDir // not a constant
+
+func chanOfUnknown() {
+	// Unknown channel direction: assume all three.
+	// MakeChan only works on the bi-di channel type.
+	t := reflect.ChanOf(unknownDir, reflect.TypeOf(&a))
+	print(reflect.Zero(t).Interface())        // @types <-chan *int | chan<- *int | chan *int
+	print(reflect.MakeChan(t, 0).Interface()) // @types chan *int
+}
+
+func main() {
+	chanreflect1()
+	chanreflect1i()
+	chanreflect2()
+	chanOfRecv()
+	chanOfSend()
+	chanOfBoth()
+	chanOfUnknown()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/chanreflect1.go b/third_party/go.tools/go/pointer/testdata/chanreflect1.go
new file mode 100644
index 0000000..c5e2587
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/chanreflect1.go
@@ -0,0 +1,35 @@
+// +build ignore
+
+package main
+
+import "reflect"
+
+//
+// This test is very sensitive to line-number perturbations!
+
+// Test of channels with reflection.
+
+var a, b int
+
+func chanreflect1() {
+	ch := make(chan *int, 0)
+	crv := reflect.ValueOf(ch)
+	crv.Send(reflect.ValueOf(&a))
+	print(crv.Interface())             // @types chan *int
+	print(crv.Interface().(chan *int)) // @pointsto makechan@testdata/chanreflect.go:15:12
+	print(<-ch)                        // @pointsto main.a
+}
+
+func chanreflect2() {
+	ch := make(chan *int, 0)
+	ch <- &b
+	crv := reflect.ValueOf(ch)
+	r, _ := crv.Recv()
+	print(r.Interface())        // @types *int
+	print(r.Interface().(*int)) // @pointsto main.b
+}
+
+func main() {
+	chanreflect1()
+	chanreflect2()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/context.go b/third_party/go.tools/go/pointer/testdata/context.go
new file mode 100644
index 0000000..ed616e7
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/context.go
@@ -0,0 +1,48 @@
+// +build ignore
+
+package main
+
+// Test of context-sensitive treatment of certain function calls,
+// e.g. static calls to simple accessor methods.
+
+var a, b int
+
+type T struct{ x *int }
+
+func (t *T) SetX(x *int) { t.x = x }
+func (t *T) GetX() *int  { return t.x }
+
+func context1() {
+	var t1, t2 T
+	t1.SetX(&a)
+	t2.SetX(&b)
+	print(t1.GetX()) // @pointsto main.a
+	print(t2.GetX()) // @pointsto main.b
+}
+
+func context2() {
+	id := func(x *int) *int {
+		print(x) // @pointsto main.a | main.b
+		return x
+	}
+	print(id(&a)) // @pointsto main.a
+	print(id(&b)) // @pointsto main.b
+
+	// Same again, but anon func has free vars.
+	var c int // @line context2c
+	id2 := func(x *int) (*int, *int) {
+		print(x) // @pointsto main.a | main.b
+		return x, &c
+	}
+	p, q := id2(&a)
+	print(p) // @pointsto main.a
+	print(q) // @pointsto c@context2c:6
+	r, s := id2(&b)
+	print(r) // @pointsto main.b
+	print(s) // @pointsto c@context2c:6
+}
+
+func main() {
+	context1()
+	context2()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/conv.go b/third_party/go.tools/go/pointer/testdata/conv.go
new file mode 100644
index 0000000..692f0ce
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/conv.go
@@ -0,0 +1,63 @@
+// +build ignore
+
+package main
+
+import "unsafe"
+
+var a int
+
+func conv1() {
+	// Conversions of channel direction.
+	ch := make(chan int)    // @line c1make
+	print((<-chan int)(ch)) // @pointsto makechan@c1make:12
+	print((chan<- int)(ch)) // @pointsto makechan@c1make:12
+}
+
+func conv2() {
+	// string -> []byte/[]rune conversion
+	s := "foo"
+	ba := []byte(s) // @line c2ba
+	ra := []rune(s) // @line c2ra
+	print(ba)       // @pointsto convert@c2ba:14
+	print(ra)       // @pointsto convert@c2ra:14
+}
+
+func conv3() {
+	// Conversion of same underlying types.
+	type PI *int
+	pi := PI(&a)
+	print(pi) // @pointsto main.a
+
+	pint := (*int)(pi)
+	print(pint) // @pointsto main.a
+
+	// Conversions between pointers to identical base types.
+	var y *PI = &pi
+	var x **int = (**int)(y)
+	print(*x) // @pointsto main.a
+	print(*y) // @pointsto main.a
+	y = (*PI)(x)
+	print(*y) // @pointsto main.a
+}
+
+func conv4() {
+	// Handling of unsafe.Pointer conversion is unsound:
+	// we lose the alias to main.a and get something like new(int) instead.
+	p := (*int)(unsafe.Pointer(&a)) // @line c2p
+	print(p)                        // @pointsto convert@c2p:13
+}
+
+// Regression test for b/8231.
+func conv5() {
+	type P unsafe.Pointer
+	var i *struct{}
+	_ = P(i)
+}
+
+func main() {
+	conv1()
+	conv2()
+	conv3()
+	conv4()
+	conv5()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/finalizer.go b/third_party/go.tools/go/pointer/testdata/finalizer.go
new file mode 100644
index 0000000..97f25c9
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/finalizer.go
@@ -0,0 +1,89 @@
+package main
+
+import "runtime"
+
+func final1a(x *int) int {
+	print(x) // @pointsto new@newint:10
+	return *x
+}
+
+func final1b(x *bool) {
+	print(x) // @pointsto
+}
+
+func runtimeSetFinalizer1() {
+	x := new(int)                    // @line newint
+	runtime.SetFinalizer(x, final1a) // ok: final1a's result is ignored
+	runtime.SetFinalizer(x, final1b) // param type mismatch: no effect
+}
+
+// @calls main.runtimeSetFinalizer1 -> main.final1a
+// @calls main.runtimeSetFinalizer1 -> main.final1b
+
+func final2a(x *bool) {
+	print(x) // @pointsto new@newbool1:10 | new@newbool2:10
+}
+
+func final2b(x *bool) {
+	print(x) // @pointsto new@newbool1:10 | new@newbool2:10
+}
+
+func runtimeSetFinalizer2() {
+	x := new(bool) // @line newbool1
+	f := final2a
+	if unknown {
+		x = new(bool) // @line newbool2
+		f = final2b
+	}
+	runtime.SetFinalizer(x, f)
+}
+
+// @calls main.runtimeSetFinalizer2 -> main.final2a
+// @calls main.runtimeSetFinalizer2 -> main.final2b
+
+type T int
+
+func (t *T) finalize() {
+	print(t) // @pointsto new@final3:10
+}
+
+func runtimeSetFinalizer3() {
+	x := new(T) // @line final3
+	runtime.SetFinalizer(x, (*T).finalize)
+}
+
+// @calls main.runtimeSetFinalizer3 -> (*main.T).finalize$thunk
+
+// I hope I never live to see this code in the wild.
+var setFinalizer = runtime.SetFinalizer
+
+func final4(x *int) {
+	print(x) // @pointsto new@finalIndirect:10
+}
+
+func runtimeSetFinalizerIndirect() {
+	// In an indirect call, the shared contour for SetFinalizer is
+	// used, i.e. the call is not inlined and appears in the call graph.
+	x := new(int) // @line finalIndirect
+	setFinalizer(x, final4)
+}
+
+// Exercise the elimination of SetFinalizer
+// constraints with non-pointer operands.
+func runtimeSetFinalizerNonpointer() {
+	runtime.SetFinalizer(nil, (*T).finalize) // x is a non-pointer
+	runtime.SetFinalizer((*T).finalize, nil) // f is a non-pointer
+}
+
+// @calls main.runtimeSetFinalizerIndirect -> runtime.SetFinalizer
+// @calls runtime.SetFinalizer -> main.final4
+
+func main() {
+	runtimeSetFinalizer1()
+	runtimeSetFinalizer2()
+	runtimeSetFinalizer3()
+	runtimeSetFinalizerIndirect()
+	runtimeSetFinalizerNonpointer()
+}
+
+var unknown bool // defeat dead-code elimination
diff --git a/third_party/go.tools/go/pointer/testdata/flow.go b/third_party/go.tools/go/pointer/testdata/flow.go
new file mode 100644
index 0000000..6fb599e
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/flow.go
@@ -0,0 +1,63 @@
+// +build ignore
+
+package main
+
+// Demonstration of directionality of flow edges.
+
+func f1() {}
+func f2() {}
+
+var somepred bool
+
+// Tracking functions.
+func flow1() {
+	s := f1
+	p := f2
+	q := p
+	r := q
+	if somepred {
+		r = s
+	}
+	print(s) // @pointsto main.f1
+	print(p) // @pointsto main.f2
+	print(q) // @pointsto main.f2
+	print(r) // @pointsto main.f1 | main.f2
+}
+
+// Tracking concrete types in interfaces.
+func flow2() {
+	var s interface{} = 1
+	var p interface{} = "foo"
+	q := p
+	r := q
+	if somepred {
+		r = s
+	}
+	print(s) // @types int
+	print(p) // @types string
+	print(q) // @types string
+	print(r) // @types int | string
+}
+
+var g1, g2 int
+
+// Tracking addresses of globals.
+func flow3() {
+	s := &g1
+	p := &g2
+	q := p
+	r := q
+	if somepred {
+		r = s
+	}
+	print(s) // @pointsto main.g1
+	print(p) // @pointsto main.g2
+	print(q) // @pointsto main.g2
+	print(r) // @pointsto main.g2 | main.g1
+}
+
+func main() {
+	flow1()
+	flow2()
+	flow3()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/fmtexcerpt.go b/third_party/go.tools/go/pointer/testdata/fmtexcerpt.go
new file mode 100644
index 0000000..ee2a0e7
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/fmtexcerpt.go
@@ -0,0 +1,42 @@
+// +build ignore
+
+// This is a slice of the fmt package.
+
+package main
+
+type pp struct {
+	field interface{}
+}
+
+func newPrinter() *pp {
+	return new(pp)
+}
+
+func Fprintln(a ...interface{}) {
+	p := newPrinter()
+	p.doPrint(a, true, true)
+}
+
+func Println(a ...interface{}) {
+	Fprintln(a...)
+}
+
+func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
+	print(a[0]) // @types S | string
+	stringer := a[0].(interface {
+		String() string
+	})
+
+	stringer.String()
+	print(stringer) // @types S
+}
+
+type S int
+
+func (S) String() string { return "" }
+
+func main() {
+	Println("Hello, World!", S(0))
+}
+
+// @calls (*main.pp).doPrint -> (main.S).String
diff --git a/third_party/go.tools/go/pointer/testdata/func.go b/third_party/go.tools/go/pointer/testdata/func.go
new file mode 100644
index 0000000..2155f8e
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/func.go
@@ -0,0 +1,205 @@
+// +build ignore
+
+package main
+
+var a, b, c int
+
+var unknown bool // defeat dead-code elimination
+
+func func1() {
+	var h int // @line f1h
+	f := func(x *int) *int {
+		if unknown {
+			return &b
+		}
+		return x
+	}
+
+	// FV(g) = {f, h}
+	g := func(x *int) *int {
+		if unknown {
+			return &h
+		}
+		return f(x)
+	}
+
+	print(g(&a)) // @pointsto main.a | main.b | h@f1h:6
+	print(f(&a)) // @pointsto main.a | main.b
+	print(&a)    // @pointsto main.a
+}
+
+// @calls main.func1 -> main.func1$2
+// @calls main.func1 -> main.func1$1
+// @calls main.func1$2 ->  main.func1$1
+
+func func2() {
+	var x, y *int
+	defer func() {
+		x = &a
+	}()
+	go func() {
+		y = &b
+	}()
+	print(x) // @pointsto main.a
+	print(y) // @pointsto main.b
+}
+
+func func3() {
+	x, y := func() (x, y *int) {
+		x = &a
+		y = &b
+		if unknown {
+			return nil, &c
+		}
+		return
+	}()
+	print(x) // @pointsto main.a
+	print(y) // @pointsto main.b | main.c
+}
+
+func swap(x, y *int) (*int, *int) { // @line swap
+	print(&x) // @pointsto x@swap:11
+	print(x)  // @pointsto makeslice[*]@func4make:11
+	print(&y) // @pointsto y@swap:14
+	print(y)  // @pointsto j@f4j:5
+	return y, x
+}
+
+func func4() {
+	a := make([]int, 10) // @line func4make
+	i, j := 123, 456     // @line f4j
+	_ = i
+	p, q := swap(&a[3], &j)
+	print(p) // @pointsto j@f4j:5
+	print(q) // @pointsto makeslice[*]@func4make:11
+
+	f := &b
+	print(f) // @pointsto main.b
+}
+
+type T int
+
+func (t *T) f(x *int) *int {
+	print(t) // @pointsto main.a
+	print(x) // @pointsto main.c
+	return &b
+}
+
+func (t *T) g(x *int) *int {
+	print(t) // @pointsto main.a
+	print(x) // @pointsto main.b
+	return &c
+}
+
+func (t *T) h(x *int) *int {
+	print(t) // @pointsto main.a
+	print(x) // @pointsto main.b
+	return &c
+}
+
+var h func(*T, *int) *int
+
+func func5() {
+	// Static call of method.
+	t := (*T)(&a)
+	print(t.f(&c)) // @pointsto main.b
+
+	// Static call of method as function
+	print((*T).g(t, &b)) // @pointsto main.c
+
+	// Dynamic call (not invoke) of method.
+	h = (*T).h
+	print(h(t, &b)) // @pointsto main.c
+}
+
+// @calls main.func5 -> (*main.T).f
+// @calls main.func5 -> (*main.T).g$thunk
+// @calls main.func5 -> (*main.T).h$thunk
+
+func func6() {
+	A := &a
+	f := func() *int {
+		return A // (free variable)
+	}
+	print(f()) // @pointsto main.a
+}
+
+// @calls main.func6 -> main.func6$1
+
+type I interface {
+	f()
+}
+
+type D struct{}
+
+func (D) f() {}
+
+func func7() {
+	var i I = D{}
+	imethodClosure := i.f
+	imethodClosure()
+	// @calls main.func7 -> (main.I).f$bound
+	// @calls (main.I).f$bound -> (main.D).f
+
+	var d D
+	cmethodClosure := d.f
+	cmethodClosure()
+	// @calls main.func7 -> (main.D).f$bound
+	// @calls (main.D).f$bound ->(main.D).f
+
+	methodExpr := D.f
+	methodExpr(d)
+	// @calls main.func7 -> (main.D).f$thunk
+}
+
+func func8(x ...int) {
+	print(&x[0]) // @pointsto varargs[*]@varargs:15
+}
+
+type E struct {
+	x1, x2, x3, x4, x5 *int
+}
+
+func (e E) f() {}
+
+func func9() {
+	// Regression test for bug reported by Jon Valdes on golang-dev, Jun 19 2014.
+	// The receiver of a bound method closure may be of a multi-node type, E.
+	// valueNode was reserving only a single node for it, so the
+	// nodes used by the immediately following constraints
+	// (e.g. param 'i') would get clobbered.
+
+	var e E
+	e.x1 = &a
+	e.x2 = &a
+	e.x3 = &a
+	e.x4 = &a
+	e.x5 = &a
+
+	_ = e.f // form a closure---must reserve sizeof(E) nodes
+
+	func(i I) {
+		i.f() // must not crash the solver
+	}(new(D))
+
+	print(e.x1) // @pointsto main.a
+	print(e.x2) // @pointsto main.a
+	print(e.x3) // @pointsto main.a
+	print(e.x4) // @pointsto main.a
+	print(e.x5) // @pointsto main.a
+}
+
+func main() {
+	func1()
+	func2()
+	func3()
+	func4()
+	func5()
+	func6()
+	func7()
+	func8(1, 2, 3) // @line varargs
+	func9()
+}
+
+// @calls <root> -> main.main
+// @calls <root> -> main.init
diff --git a/third_party/go.tools/go/pointer/testdata/funcreflect.go b/third_party/go.tools/go/pointer/testdata/funcreflect.go
new file mode 100644
index 0000000..a0a9a5f
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/funcreflect.go
@@ -0,0 +1,130 @@
+// +build ignore
+
+package main
+
+import "reflect"
+
+var zero, a, b int
+var false2 bool
+
+func f(p *int, q hasF) *int {
+	print(p)      // @pointsto main.a
+	print(q)      // @types *T
+	print(q.(*T)) // @pointsto new@newT1:22
+	return &b
+}
+
+func g(p *bool) (*int, *bool, hasF) {
+	return &b, p, new(T) // @line newT2
+}
+
+func reflectValueCall() {
+	rvf := reflect.ValueOf(f)
+	res := rvf.Call([]reflect.Value{
+		// argument order is not significant:
+		reflect.ValueOf(new(T)), // @line newT1
+		reflect.ValueOf(&a),
+	})
+	print(res[0].Interface())        // @types *int
+	print(res[0].Interface().(*int)) // @pointsto main.b
+}
+
+// @calls main.reflectValueCall -> main.f
+
+func reflectValueCallIndirect() {
+	rvf := reflect.ValueOf(g)
+	call := rvf.Call // kids, don't try this at home
+
+	// Indirect call uses shared contour.
+	//
+	// Also notice that argument position doesn't matter, and args
+	// of inappropriate type (e.g. 'a') are ignored.
+	res := call([]reflect.Value{
+		reflect.ValueOf(&a),
+		reflect.ValueOf(&false2),
+	})
+	res0 := res[0].Interface()
+	print(res0)         // @types *int | *bool | *T
+	print(res0.(*int))  // @pointsto main.b
+	print(res0.(*bool)) // @pointsto main.false2
+	print(res0.(hasF))  // @types *T
+	print(res0.(*T))    // @pointsto new@newT2:19
+}
+
+// @calls main.reflectValueCallIndirect -> (reflect.Value).Call$bound
+// @calls (reflect.Value).Call$bound -> main.g
+
+func reflectTypeInOut() {
+	var f func(float64, bool) (string, int)
+	print(reflect.Zero(reflect.TypeOf(f).In(0)).Interface())    // @types float64
+	print(reflect.Zero(reflect.TypeOf(f).In(1)).Interface())    // @types bool
+	print(reflect.Zero(reflect.TypeOf(f).In(-1)).Interface())   // @types float64 | bool
+	print(reflect.Zero(reflect.TypeOf(f).In(zero)).Interface()) // @types float64 | bool
+
+	print(reflect.Zero(reflect.TypeOf(f).Out(0)).Interface()) // @types string
+	print(reflect.Zero(reflect.TypeOf(f).Out(1)).Interface()) // @types int
+	print(reflect.Zero(reflect.TypeOf(f).Out(2)).Interface()) // @types
+
+	print(reflect.Zero(reflect.TypeOf(3).Out(0)).Interface()) // @types
+}
+
+type hasF interface {
+	F()
+}
+
+type T struct{}
+
+func (T) F()    {}
+func (T) g(int) {}
+
+type U struct{}
+
+func (U) F(int)    {}
+func (U) g(string) {}
+
+type I interface {
+	f()
+}
+
+var nonconst string
+
+func reflectTypeMethodByName() {
+	TU := reflect.TypeOf([]interface{}{T{}, U{}}[0])
+	print(reflect.Zero(TU)) // @types T | U
+
+	F, _ := TU.MethodByName("F")
+	print(reflect.Zero(F.Type)) // @types func(T) | func(U, int)
+	print(F.Func)               // @pointsto (main.T).F | (main.U).F
+
+	g, _ := TU.MethodByName("g")
+	print(reflect.Zero(g.Type)) // @types func(T, int) | func(U, string)
+	print(g.Func)               // @pointsto (main.T).g | (main.U).g
+
+	// Non-literal method names are treated less precisely.
+	U := reflect.TypeOf(U{})
+	X, _ := U.MethodByName(nonconst)
+	print(reflect.Zero(X.Type)) // @types func(U, int) | func(U, string)
+	print(X.Func)               // @pointsto (main.U).F | (main.U).g
+
+	// Interface methods.
+	rThasF := reflect.TypeOf(new(hasF)).Elem()
+	print(reflect.Zero(rThasF)) // @types hasF
+	F2, _ := rThasF.MethodByName("F")
+	print(reflect.Zero(F2.Type)) // @types func()
+	print(F2.Func)               // @pointsto
+
+}
+
+func reflectTypeMethod() {
+	m := reflect.TypeOf(T{}).Method(0)
+	print(reflect.Zero(m.Type)) // @types func(T) | func(T, int)
+	print(m.Func)               // @pointsto (main.T).F | (main.T).g
+}
+
+func main() {
+	reflectValueCall()
+	reflectValueCallIndirect()
+	reflectTypeInOut()
+	reflectTypeMethodByName()
+	reflectTypeMethod()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/hello.go b/third_party/go.tools/go/pointer/testdata/hello.go
new file mode 100644
index 0000000..b81784b
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/hello.go
@@ -0,0 +1,27 @@
+// +build ignore
+
+package main
+
+import (
+	"fmt"
+	"os"
+)
+
+type S int
+
+var theS S
+
+func (s *S) String() string {
+	print(s) // @pointsto main.theS
+	return ""
+}
+
+func main() {
+	// os.Args is considered intrinsically allocated,
+	// but may also be set explicitly (e.g. on Windows), hence '...'.
+	print(os.Args) // @pointsto <command-line args> | ...
+	fmt.Println("Hello, World!", &theS)
+}
+
+// @calls main.main               -> fmt.Println
+// @calls (*fmt.pp).handleMethods -> (*main.S).String
diff --git a/third_party/go.tools/go/pointer/testdata/interfaces.go b/third_party/go.tools/go/pointer/testdata/interfaces.go
new file mode 100644
index 0000000..91c0fa9
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/interfaces.go
@@ -0,0 +1,152 @@
+// +build ignore
+
+package main
+
+type I interface {
+	f()
+}
+
+type C int
+
+func (*C) f() {}
+
+type D struct{ ptr *int }
+
+func (D) f() {}
+
+type E struct{}
+
+func (*E) f() {}
+
+var a, b int
+
+var unknown bool // defeat dead-code elimination
+
+func interface1() {
+	var i interface{} = &a
+	var j interface{} = D{&b}
+	k := j
+	if unknown {
+		k = i
+	}
+
+	print(i) // @types *int
+	print(j) // @types D
+	print(k) // @types *int | D
+
+	print(i.(*int)) // @pointsto main.a
+	print(j.(*int)) // @pointsto
+	print(k.(*int)) // @pointsto main.a
+
+	print(i.(D).ptr) // @pointsto
+	print(j.(D).ptr) // @pointsto main.b
+	print(k.(D).ptr) // @pointsto main.b
+}
+
+func interface2() {
+	var i I = (*C)(&a)
+	var j I = D{&a}
+	k := j
+	if unknown {
+		k = i
+	}
+
+	print(i) // @types *C
+	print(j) // @types D
+	print(k) // @types *C | D
+	print(k) // @pointsto makeinterface:main.D | makeinterface:*main.C
+
+	k.f()
+	// @calls main.interface2 -> (*main.C).f
+	// @calls main.interface2 -> (main.D).f
+
+	print(i.(*C))    // @pointsto main.a
+	print(j.(D).ptr) // @pointsto main.a
+	print(k.(*C))    // @pointsto main.a
+
+	switch x := k.(type) {
+	case *C:
+		print(x) // @pointsto main.a
+	case D:
+		print(x.ptr) // @pointsto main.a
+	case *E:
+		print(x) // @pointsto
+	}
+}
+
+func interface3() {
+	// There should be no backflow of concrete types from the type-switch to x.
+	var x interface{} = 0
+	print(x) // @types int
+	switch x.(type) {
+	case int:
+	case string:
+	}
+}
+
+func interface4() {
+	var i interface{} = D{&a}
+	if unknown {
+		i = 123
+	}
+
+	print(i) // @types int | D
+
+	j := i.(I)       // interface narrowing type-assertion
+	print(j)         // @types D
+	print(j.(D).ptr) // @pointsto main.a
+
+	var l interface{} = j // interface widening assignment.
+	print(l)              // @types D
+	print(l.(D).ptr)      // @pointsto main.a
+
+	m := j.(interface{}) // interface widening type-assertion.
+	print(m)             // @types D
+	print(m.(D).ptr)     // @pointsto main.a
+}
+
+// Interface method calls and value flow:
+
+type J interface {
+	f(*int) *int
+}
+
+type P struct {
+	x int
+}
+
+func (p *P) f(pi *int) *int {
+	print(p)  // @pointsto p@i5p:6
+	print(pi) // @pointsto i@i5i:6
+	return &p.x
+}
+
+func interface5() {
+	var p P // @line i5p
+	var j J = &p
+	var i int      // @line i5i
+	print(j.f(&i)) // @pointsto p.x@i5p:6
+	print(&i)      // @pointsto i@i5i:6
+
+	print(j) // @pointsto makeinterface:*main.P
+}
+
+// @calls main.interface5 -> (*main.P).f
+
+func interface6() {
+	f := I.f
+	print(f) // @pointsto (main.I).f$thunk
+	f(new(struct{ D }))
+}
+
+// @calls main.interface6 -> (main.I).f$thunk
+// @calls (main.I).f$thunk -> (*struct{main.D}).f
+
+func main() {
+	interface1()
+	interface2()
+	interface3()
+	interface4()
+	interface5()
+	interface6()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/issue9002.go b/third_party/go.tools/go/pointer/testdata/issue9002.go
new file mode 100644
index 0000000..b7c2c61
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/issue9002.go
@@ -0,0 +1,17 @@
+package main
+
+func main() {
+	// Regression test for golang issue 9002.
+	//
+	// The two-result "value,ok" receive operation generated a
+	// too-wide constraint loading (value int, ok bool), not bool,
+	// from the channel.
+	//
+	// This bug manifested itself in an out-of-bounds array access
+	// when the makechan object was the highest-numbered node, as in
+	// this program.
+	//
+	// In more realistic programs it silently resulted in bogus
+	// constraints.
+	_, _ = <-make(chan int)
+}
diff --git a/third_party/go.tools/go/pointer/testdata/mapreflect.go b/third_party/go.tools/go/pointer/testdata/mapreflect.go
new file mode 100644
index 0000000..bc5e7e6
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/mapreflect.go
@@ -0,0 +1,117 @@
+// +build ignore
+
+package main
+
+// Test of maps with reflection.
+
+import "reflect"
+
+var a int
+var b bool
+
+func reflectMapKeysIndex() {
+	m := make(map[*int]*bool) // @line mr1make
+	m[&a] = &b
+
+	mrv := reflect.ValueOf(m)
+	print(mrv.Interface())                  // @types map[*int]*bool
+	print(mrv.Interface().(map[*int]*bool)) // @pointsto makemap@mr1make:11
+	print(mrv)                              // @pointsto makeinterface:map[*int]*bool
+	print(mrv)                              // @types map[*int]*bool
+
+	keys := mrv.MapKeys()
+	print(keys) // @pointsto <alloc in (reflect.Value).MapKeys>
+	for _, k := range keys {
+		print(k)                    // @pointsto <alloc in (reflect.Value).MapKeys>
+		print(k)                    // @types *int
+		print(k.Interface())        // @types *int
+		print(k.Interface().(*int)) // @pointsto main.a
+
+		v := mrv.MapIndex(k)
+		print(v.Interface())         // @types *bool
+		print(v.Interface().(*bool)) // @pointsto main.b
+	}
+}
+
+func reflectSetMapIndex() {
+	m := make(map[*int]*bool)
+	mrv := reflect.ValueOf(m)
+	mrv.SetMapIndex(reflect.ValueOf(&a), reflect.ValueOf(&b))
+
+	print(m[nil]) // @pointsto main.b
+
+	for _, k := range mrv.MapKeys() {
+		print(k.Interface())        // @types *int
+		print(k.Interface().(*int)) // @pointsto main.a
+	}
+
+	tmap := reflect.TypeOf(m)
+	// types.EvalNode won't let us refer to non-exported types:
+	// print(tmap) // #@types *reflect.rtype
+	print(tmap) // @pointsto map[*int]*bool
+
+	zmap := reflect.Zero(tmap)
+	print(zmap)             // @pointsto <alloc in reflect.Zero>
+	print(zmap.Interface()) // @pointsto <alloc in reflect.Zero>
+
+	print(tmap.Key())                            // @pointsto *int
+	print(tmap.Elem())                           // @pointsto *bool
+	print(reflect.Zero(tmap.Key()))              // @pointsto <alloc in reflect.Zero>
+	print(reflect.Zero(tmap.Key()).Interface())  // @pointsto <alloc in reflect.Zero>
+	print(reflect.Zero(tmap.Key()).Interface())  // @types *int
+	print(reflect.Zero(tmap.Elem()))             // @pointsto <alloc in reflect.Zero>
+	print(reflect.Zero(tmap.Elem()).Interface()) // @pointsto <alloc in reflect.Zero>
+	print(reflect.Zero(tmap.Elem()).Interface()) // @types *bool
+}
+
+func reflectSetMapIndexInterface() {
+	// Exercises reflect.Value conversions to/from interfaces:
+	// a different code path than for concrete types.
+	m := make(map[interface{}]interface{})
+	reflect.ValueOf(m).SetMapIndex(reflect.ValueOf(&a), reflect.ValueOf(&b))
+	for k, v := range m {
+		print(k)         // @types *int
+		print(k.(*int))  // @pointsto main.a
+		print(v)         // @types *bool
+		print(v.(*bool)) // @pointsto main.b
+	}
+}
+
+func reflectSetMapIndexAssignable() {
+	// SetMapIndex performs implicit assignability conversions.
+	type I *int
+	type J *int
+
+	str := reflect.ValueOf("")
+
+	// *int is assignable to I.
+	m1 := make(map[string]I)
+	reflect.ValueOf(m1).SetMapIndex(str, reflect.ValueOf(new(int))) // @line int
+	print(m1[""])                                                   // @pointsto new@int:58
+
+	// I is assignable to I.
+	m2 := make(map[string]I)
+	reflect.ValueOf(m2).SetMapIndex(str, reflect.ValueOf(I(new(int)))) // @line I
+	print(m2[""])                                                      // @pointsto new@I:60
+
+	// J is not assignable to I.
+	m3 := make(map[string]I)
+	reflect.ValueOf(m3).SetMapIndex(str, reflect.ValueOf(J(new(int))))
+	print(m3[""]) // @pointsto
+}
+
+func reflectMakeMap() {
+	t := reflect.TypeOf(map[*int]*bool(nil))
+	v := reflect.MakeMap(t)
+	print(v) // @types map[*int]*bool
+	print(v) // @pointsto <alloc in reflect.MakeMap>
+}
+
+func main() {
+	reflectMapKeysIndex()
+	reflectSetMapIndex()
+	reflectSetMapIndexInterface()
+	reflectSetMapIndexAssignable()
+	reflectMakeMap()
+	// TODO(adonovan): reflect.MapOf(Type)
+}
diff --git a/third_party/go.tools/go/pointer/testdata/maps.go b/third_party/go.tools/go/pointer/testdata/maps.go
new file mode 100644
index 0000000..6f3751d
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/maps.go
@@ -0,0 +1,51 @@
+// +build ignore
+
+package main
+
+// Test of maps.
+
+var a, b, c int
+
+func maps1() {
+	m1 := map[*int]*int{&a: &b} // @line m1m1
+	m2 := make(map[*int]*int)   // @line m1m2
+	m2[&b] = &a
+
+	print(m1[nil]) // @pointsto main.b | main.c
+	print(m2[nil]) // @pointsto main.a
+
+	print(m1) // @pointsto makemap@m1m1:21
+	print(m2) // @pointsto makemap@m1m2:12
+
+	m1[&b] = &c
+
+	for k, v := range m1 {
+		print(k) // @pointsto main.a | main.b
+		print(v) // @pointsto main.b | main.c
+	}
+
+	for k, v := range m2 {
+		print(k) // @pointsto main.b
+		print(v) // @pointsto main.a
+	}
+
+	// Lookup doesn't create any aliases.
+	print(m2[&c]) // @pointsto main.a
+	if _, ok := m2[&a]; ok {
+		print(m2[&c]) // @pointsto main.a
+	}
+}
+
+func maps2() {
+	m1 := map[*int]*int{&a: &b}
+	m2 := map[*int]*int{&b: &c}
+	_ = []map[*int]*int{m1, m2} // (no spurious merging of m1, m2)
+
+	print(m1[nil]) // @pointsto main.b
+	print(m2[nil]) // @pointsto main.c
+}
+
+func main() {
+	maps1()
+	maps2()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/panic.go b/third_party/go.tools/go/pointer/testdata/panic.go
new file mode 100644
index 0000000..ee8a766
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/panic.go
@@ -0,0 +1,36 @@
+// +build ignore
+
+package main
+
+// Test of value flow from panic() to recover().
+// We model them as stores/loads of a global location.
+// We ignore concrete panic types originating from the runtime.
+
+var someval int
+
+type myPanic struct{}
+
+func f(int) {}
+
+func g() string { return "" }
+
+func deadcode() {
+	panic(123) // not reached
+}
+
+func main() {
+	switch someval {
+	case 0:
+		panic("oops")
+	case 1:
+		panic(myPanic{})
+	case 2:
+		panic(f)
+	case 3:
+		panic(g)
+	}
+	ex := recover()
+	print(ex)                 // @types myPanic | string | func(int) | func() string
+	print(ex.(func(int)))     // @pointsto main.f
+	print(ex.(func() string)) // @pointsto main.g
+}
diff --git a/third_party/go.tools/go/pointer/testdata/recur.go b/third_party/go.tools/go/pointer/testdata/recur.go
new file mode 100644
index 0000000..4c7229d
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/recur.go
@@ -0,0 +1,11 @@
+// +build ignore
+
+package main
+
+// Analysis abstraction of recursive calls is finite.
+
+func main() {
+	main()
+}
+
+// @calls main.main -> main.main
diff --git a/third_party/go.tools/go/pointer/testdata/reflect.go b/third_party/go.tools/go/pointer/testdata/reflect.go
new file mode 100644
index 0000000..6b8d0f2
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/reflect.go
@@ -0,0 +1,115 @@
+// +build ignore
+
+package main
+
+import "reflect"
+import "unsafe"
+
+var a, b int
+var unknown bool
+
+func reflectIndirect() {
+	ptr := &a
+	// Pointer:
+	print(reflect.Indirect(reflect.ValueOf(&ptr)).Interface().(*int)) // @pointsto main.a
+	// Non-pointer:
+	print(reflect.Indirect(reflect.ValueOf([]*int{ptr})).Interface().([]*int)[0]) // @pointsto main.a
+}
+
+func reflectNewAt() {
+	var x [8]byte
+	print(reflect.NewAt(reflect.TypeOf(3), unsafe.Pointer(&x)).Interface()) // @types *int
+}
+
+// @warning "unsound: main.reflectNewAt contains a reflect.NewAt.. call"
+
+func reflectTypeOf() {
+	t := reflect.TypeOf(3)
+	if unknown {
+		t = reflect.TypeOf("foo")
+	}
+	// TODO(adonovan): make types.Eval let us refer to unexported types.
+	print(t)                             // #@types *reflect.rtype
+	print(reflect.Zero(t).Interface())   // @types int | string
+	newint := reflect.New(t).Interface() // @line rtonew
+	print(newint)                        // @types *int | *string
+	print(newint.(*int))                 // @pointsto <alloc in reflect.New>
+	print(newint.(*string))              // @pointsto <alloc in reflect.New>
+}
+
+func reflectTypeElem() {
+	print(reflect.Zero(reflect.TypeOf(&a).Elem()).Interface())                       // @types int
+	print(reflect.Zero(reflect.TypeOf([]string{}).Elem()).Interface())               // @types string
+	print(reflect.Zero(reflect.TypeOf(make(chan bool)).Elem()).Interface())          // @types bool
+	print(reflect.Zero(reflect.TypeOf(make(map[string]float64)).Elem()).Interface()) // @types float64
+	print(reflect.Zero(reflect.TypeOf([3]complex64{}).Elem()).Interface())           // @types complex64
+	print(reflect.Zero(reflect.TypeOf(3).Elem()).Interface())                        // @types
+	print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem()))                     // @types interface{}
+	print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem()).Interface())         // @types
+}
+
+// reflect.Values within reflect.Values.
+func metareflection() {
+	// "box" a *int twice, unbox it twice.
+	v0 := reflect.ValueOf(&a)
+	print(v0)                              // @types *int
+	v1 := reflect.ValueOf(v0)              // box
+	print(v1)                              // @types reflect.Value
+	v2 := reflect.ValueOf(v1)              // box
+	print(v2)                              // @types reflect.Value
+	v1a := v2.Interface().(reflect.Value)  // unbox
+	print(v1a)                             // @types reflect.Value
+	v0a := v1a.Interface().(reflect.Value) // unbox
+	print(v0a)                             // @types *int
+	print(v0a.Interface().(*int))          // @pointsto main.a
+
+	// "box" an interface{} lvalue twice, unbox it twice.
+	var iface interface{} = 3
+	x0 := reflect.ValueOf(&iface).Elem()
+	print(x0)                              // @types interface{}
+	x1 := reflect.ValueOf(x0)              // box
+	print(x1)                              // @types reflect.Value
+	x2 := reflect.ValueOf(x1)              // box
+	print(x2)                              // @types reflect.Value
+	x1a := x2.Interface().(reflect.Value)  // unbox
+	print(x1a)                             // @types reflect.Value
+	x0a := x1a.Interface().(reflect.Value) // unbox
+	print(x0a)                             // @types interface{}
+	print(x0a.Interface())                 // @types int
+}
+
+type T struct{}
+
+// When the output of a type constructor flows to its input, we must
+// bound the set of types created to ensure termination of the algorithm.
+func typeCycle() {
+	t := reflect.TypeOf(0)
+	u := reflect.TypeOf("")
+	v := reflect.TypeOf(T{})
+	for unknown {
+		t = reflect.PtrTo(t)
+		t = reflect.SliceOf(t)
+
+		u = reflect.SliceOf(u)
+
+		if unknown {
+			v = reflect.ChanOf(reflect.BothDir, v)
+		} else {
+			v = reflect.PtrTo(v)
+		}
+	}
+
+	// Type height is bounded to about 4 map/slice/chan/pointer constructors.
+	print(reflect.Zero(t).Interface()) // @types int | []*int | []*[]*int
+	print(reflect.Zero(u).Interface()) // @types string | []string | [][]string | [][][]string | [][][][]string
+	print(reflect.Zero(v).Interface()) // @types T | *T | **T | ***T | ****T | chan T | *chan T | **chan T | chan *T | *chan *T | chan **T | chan ***T | chan chan T | chan *chan T | chan chan *T
+}
+
+func main() {
+	reflectIndirect()
+	reflectNewAt()
+	reflectTypeOf()
+	reflectTypeElem()
+	metareflection()
+	typeCycle()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/rtti.go b/third_party/go.tools/go/pointer/testdata/rtti.go
new file mode 100644
index 0000000..826936d
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/rtti.go
@@ -0,0 +1,29 @@
+package main
+
+// Regression test for oracle crash
+// https://code.google.com/p/go/issues/detail?id=6605
+//
+// Using reflection, methods may be called on types that are not the
+// operand of any ssa.MakeInterface instruction.  In this example,
+// (Y).F is called by deriving the type Y from *Y.  Prior to the fix,
+// no RTTI (or method set) for type Y was included in the program, so
+// the F() call would crash.
+
+import "reflect"
+
+var a int
+
+type X struct{}
+
+func (X) F() *int {
+	return &a
+}
+
+type I interface {
+	F() *int
+}
+
+func main() {
+	type Y struct{ X }
+	print(reflect.Indirect(reflect.ValueOf(new(Y))).Interface().(I).F()) // @pointsto main.a
+}
diff --git a/third_party/go.tools/go/pointer/testdata/structreflect.go b/third_party/go.tools/go/pointer/testdata/structreflect.go
new file mode 100644
index 0000000..9fb49f5
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/structreflect.go
@@ -0,0 +1,45 @@
+// +build ignore
+
+package main
+
+import "reflect"
+
+type A struct {
+	f *int
+	g interface{}
+	h bool
+}
+
+var dyn string
+
+func reflectTypeFieldByName() {
+	f, _ := reflect.TypeOf(A{}).FieldByName("f")
+	print(f.Type) // @pointsto *int
+
+	g, _ := reflect.TypeOf(A{}).FieldByName("g")
+	print(g.Type)               // @pointsto interface{}
+	print(reflect.Zero(g.Type)) // @pointsto <alloc in reflect.Zero>
+	print(reflect.Zero(g.Type)) // @types interface{}
+
+	print(reflect.Zero(g.Type).Interface()) // @pointsto
+	print(reflect.Zero(g.Type).Interface()) // @types
+
+	h, _ := reflect.TypeOf(A{}).FieldByName("h")
+	print(h.Type) // @pointsto bool
+
+	missing, _ := reflect.TypeOf(A{}).FieldByName("missing")
+	print(missing.Type) // @pointsto
+
+	dyn, _ := reflect.TypeOf(A{}).FieldByName(dyn)
+	print(dyn.Type) // @pointsto *int | bool | interface{}
+}
+
+func reflectTypeField() {
+	fld := reflect.TypeOf(A{}).Field(0)
+	print(fld.Type) // @pointsto *int | bool | interface{}
+}
+
+func main() {
+	reflectTypeFieldByName()
+	reflectTypeField()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/structs.go b/third_party/go.tools/go/pointer/testdata/structs.go
new file mode 100644
index 0000000..9036d60
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/structs.go
@@ -0,0 +1,100 @@
+// +build ignore
+
+package main
+
+var unknown bool // defeat dead-code elimination
+
+var p, q int
+
+type A struct {
+	f *int
+	g interface{}
+}
+
+func (a A) m1() {
+	print(a.f) // @pointsto main.p
+}
+
+func (a *A) m2() {
+	print(a)   // @pointsto complit.A@struct1s:9
+	print(a.f) // @pointsto main.p
+}
+
+type B struct {
+	h *int
+	A
+}
+
+func structs1() {
+	b := &B{ // @line struct1s
+		h: &q,
+	}
+	b.f = &p
+	b.g = b
+
+	print(b.h) // @pointsto main.q
+	print(b.f) // @pointsto main.p
+	print(b.g) // @types *B
+
+	ptr := &b.f
+	print(*ptr) // @pointsto main.p
+
+	b.m1()
+	b.m2()
+}
+
+// @calls main.structs1 -> (main.A).m1
+// @calls main.structs1 -> (*main.A).m2
+// @calls (*main.B).m1 -> (main.A).m1
+// @calls (*main.B).m2 -> (*main.A).m2
+
+type T struct {
+	x int
+	y int
+}
+
+type S struct {
+	a [3]T
+	b *[3]T
+	c [3]*T
+}
+
+func structs2() {
+	var s S          // @line s2s
+	print(&s)        // @pointsto s@s2s:6
+	print(&s.a)      // @pointsto s.a@s2s:6
+	print(&s.a[0])   // @pointsto s.a[*]@s2s:6
+	print(&s.a[0].x) // @pointsto s.a[*].x@s2s:6
+	print(&s.a[0].y) // @pointsto s.a[*].y@s2s:6
+	print(&s.b)      // @pointsto s.b@s2s:6
+	print(&s.b[0])   // @pointsto
+	print(&s.b[0].x) // @pointsto
+	print(&s.b[0].y) // @pointsto
+	print(&s.c)      // @pointsto s.c@s2s:6
+	print(&s.c[0])   // @pointsto s.c[*]@s2s:6
+	print(&s.c[0].x) // @pointsto
+	print(&s.c[0].y) // @pointsto
+
+	var s2 S          // @line s2s2
+	s2.b = new([3]T)  // @line s2s2b
+	print(s2.b)       // @pointsto new@s2s2b:12
+	print(&s2.b)      // @pointsto s2.b@s2s2:6
+	print(&s2.b[0])   // @pointsto new[*]@s2s2b:12
+	print(&s2.b[0].x) // @pointsto new[*].x@s2s2b:12
+	print(&s2.b[0].y) // @pointsto new[*].y@s2s2b:12
+	print(&s2.c[0].x) // @pointsto
+	print(&s2.c[0].y) // @pointsto
+
+	var s3 S          // @line s2s3
+	s3.c[2] = new(T)  // @line s2s3c
+	print(&s3.c)      // @pointsto s3.c@s2s3:6
+	print(s3.c[1])    // @pointsto new@s2s3c:15
+	print(&s3.c[1])   // @pointsto s3.c[*]@s2s3:6
+	print(&s3.c[1].x) // @pointsto new.x@s2s3c:15
+	print(&s3.c[1].y) // @pointsto new.y@s2s3c:15
+}
+
+func main() {
+	structs1()
+	structs2()
+}
diff --git a/third_party/go.tools/go/pointer/testdata/timer.go b/third_party/go.tools/go/pointer/testdata/timer.go
new file mode 100644
index 0000000..465d081
--- /dev/null
+++ b/third_party/go.tools/go/pointer/testdata/timer.go
@@ -0,0 +1,24 @@
+// +build ignore
+
+package main
+
+import "time"
+
+func after() {}
+
+func main() {
+	// @calls time.startTimer -> time.sendTime
+	ticker := time.NewTicker(1)
+	<-ticker.C
+
+	// @calls time.startTimer -> time.sendTime
+	timer := time.NewTimer(time.Second)
+	<-timer.C
+
+	// @calls time.startTimer -> time.goFunc
+	// @calls time.goFunc -> main.after
+	timer = time.AfterFunc(time.Second, after)
+	<-timer.C
+}
+
+// @calls time.sendTime -> time.Now
diff --git a/third_party/go.tools/go/pointer/util.go b/third_party/go.tools/go/pointer/util.go
new file mode 100644
index 0000000..56637f2
--- /dev/null
+++ b/third_party/go.tools/go/pointer/util.go
@@ -0,0 +1,318 @@
+// Copyright 2013 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 pointer
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"os"
+	"os/exec"
+	"runtime"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/container/intsets"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// CanPoint reports whether the type T is pointerlike,
+// for the purposes of this analysis.
+func CanPoint(T types.Type) bool {
+	switch T := T.(type) {
+	case *types.Named:
+		if obj := T.Obj(); obj.Name() == "Value" && obj.Pkg().Path() == "reflect" {
+			return true // treat reflect.Value like interface{}
+		}
+		return CanPoint(T.Underlying())
+
+	case *types.Pointer, *types.Interface, *types.Map, *types.Chan, *types.Signature, *types.Slice:
+		return true
+	}
+
+	return false // array struct tuple builtin basic
+}
+
+// CanHaveDynamicTypes reports whether the type T can "hold" dynamic types,
+// i.e. is an interface (incl. reflect.Type) or a reflect.Value.
+//
+func CanHaveDynamicTypes(T types.Type) bool {
+	switch T := T.(type) {
+	case *types.Named:
+		if obj := T.Obj(); obj.Name() == "Value" && obj.Pkg().Path() == "reflect" {
+			return true // reflect.Value
+		}
+		return CanHaveDynamicTypes(T.Underlying())
+	case *types.Interface:
+		return true
+	}
+	return false
+}
+
+// isInterface reports whether T is an interface type.
+func isInterface(T types.Type) bool {
+	_, ok := T.Underlying().(*types.Interface)
+	return ok
+}
+
+// mustDeref returns the element type of its argument, which must be a
+// pointer; panic ensues otherwise.
+func mustDeref(typ types.Type) types.Type {
+	return typ.Underlying().(*types.Pointer).Elem()
+}
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// A fieldInfo describes one subelement (node) of the flattening-out
+// of a type T: the subelement's type and its path from the root of T.
+//
+// For example, for this type:
+//     type line struct{ points []struct{x, y int} }
+// flatten() of the inner struct yields the following []fieldInfo:
+//    struct{ x, y int }                      ""
+//    int                                     ".x"
+//    int                                     ".y"
+// and flatten(line) yields:
+//    struct{ points []struct{x, y int} }     ""
+//    struct{ x, y int }                      ".points[*]"
+//    int                                     ".points[*].x
+//    int                                     ".points[*].y"
+//
+type fieldInfo struct {
+	typ types.Type
+
+	// op and tail describe the path to the element (e.g. ".a#2.b[*].c").
+	op   interface{} // *Array: true; *Tuple: int; *Struct: *types.Var; *Named: nil
+	tail *fieldInfo
+}
+
+// path returns a user-friendly string describing the subelement path.
+//
+func (fi *fieldInfo) path() string {
+	var buf bytes.Buffer
+	for p := fi; p != nil; p = p.tail {
+		switch op := p.op.(type) {
+		case bool:
+			fmt.Fprintf(&buf, "[*]")
+		case int:
+			fmt.Fprintf(&buf, "#%d", op)
+		case *types.Var:
+			fmt.Fprintf(&buf, ".%s", op.Name())
+		}
+	}
+	return buf.String()
+}
+
+// flatten returns a list of directly contained fields in the preorder
+// traversal of the type tree of t.  The resulting elements are all
+// scalars (basic types or pointerlike types), except for struct/array
+// "identity" nodes, whose type is that of the aggregate.
+//
+// reflect.Value is considered pointerlike, similar to interface{}.
+//
+// Callers must not mutate the result.
+//
+func (a *analysis) flatten(t types.Type) []*fieldInfo {
+	fl, ok := a.flattenMemo[t]
+	if !ok {
+		switch t := t.(type) {
+		case *types.Named:
+			u := t.Underlying()
+			if isInterface(u) {
+				// Debuggability hack: don't remove
+				// the named type from interfaces as
+				// they're very verbose.
+				fl = append(fl, &fieldInfo{typ: t})
+			} else {
+				fl = a.flatten(u)
+			}
+
+		case *types.Basic,
+			*types.Signature,
+			*types.Chan,
+			*types.Map,
+			*types.Interface,
+			*types.Slice,
+			*types.Pointer:
+			fl = append(fl, &fieldInfo{typ: t})
+
+		case *types.Array:
+			fl = append(fl, &fieldInfo{typ: t}) // identity node
+			for _, fi := range a.flatten(t.Elem()) {
+				fl = append(fl, &fieldInfo{typ: fi.typ, op: true, tail: fi})
+			}
+
+		case *types.Struct:
+			fl = append(fl, &fieldInfo{typ: t}) // identity node
+			for i, n := 0, t.NumFields(); i < n; i++ {
+				f := t.Field(i)
+				for _, fi := range a.flatten(f.Type()) {
+					fl = append(fl, &fieldInfo{typ: fi.typ, op: f, tail: fi})
+				}
+			}
+
+		case *types.Tuple:
+			// No identity node: tuples are never address-taken.
+			n := t.Len()
+			if n == 1 {
+				// Don't add a fieldInfo link for singletons,
+				// e.g. in params/results.
+				fl = append(fl, a.flatten(t.At(0).Type())...)
+			} else {
+				for i := 0; i < n; i++ {
+					f := t.At(i)
+					for _, fi := range a.flatten(f.Type()) {
+						fl = append(fl, &fieldInfo{typ: fi.typ, op: i, tail: fi})
+					}
+				}
+			}
+
+		default:
+			panic(t)
+		}
+
+		a.flattenMemo[t] = fl
+	}
+
+	return fl
+}
+
+// sizeof returns the number of pointerlike abstractions (nodes) in the type t.
+func (a *analysis) sizeof(t types.Type) uint32 {
+	return uint32(len(a.flatten(t)))
+}
+
+// shouldTrack reports whether object type T contains (recursively)
+// any fields whose addresses should be tracked.
+func (a *analysis) shouldTrack(T types.Type) bool {
+	if a.track == trackAll {
+		return true // fast path
+	}
+	track, ok := a.trackTypes[T]
+	if !ok {
+		a.trackTypes[T] = true // break cycles conservatively
+		// NB: reflect.Value, reflect.Type are pre-populated to true.
+		for _, fi := range a.flatten(T) {
+			switch ft := fi.typ.Underlying().(type) {
+			case *types.Interface, *types.Signature:
+				track = true // needed for callgraph
+			case *types.Basic:
+				// no-op
+			case *types.Chan:
+				track = a.track&trackChan != 0 || a.shouldTrack(ft.Elem())
+			case *types.Map:
+				track = a.track&trackMap != 0 || a.shouldTrack(ft.Key()) || a.shouldTrack(ft.Elem())
+			case *types.Slice:
+				track = a.track&trackSlice != 0 || a.shouldTrack(ft.Elem())
+			case *types.Pointer:
+				track = a.track&trackPtr != 0 || a.shouldTrack(ft.Elem())
+			case *types.Array, *types.Struct:
+				// No need to look at field types since they will follow (flattened).
+			default:
+				// Includes *types.Tuple, which are never address-taken.
+				panic(ft)
+			}
+			if track {
+				break
+			}
+		}
+		a.trackTypes[T] = track
+		if !track && a.log != nil {
+			fmt.Fprintf(a.log, "\ttype not tracked: %s\n", T)
+		}
+	}
+	return track
+}
+
+// offsetOf returns the (abstract) offset of field index within struct
+// or tuple typ.
+func (a *analysis) offsetOf(typ types.Type, index int) uint32 {
+	var offset uint32
+	switch t := typ.Underlying().(type) {
+	case *types.Tuple:
+		for i := 0; i < index; i++ {
+			offset += a.sizeof(t.At(i).Type())
+		}
+	case *types.Struct:
+		offset++ // the node for the struct itself
+		for i := 0; i < index; i++ {
+			offset += a.sizeof(t.Field(i).Type())
+		}
+	default:
+		panic(fmt.Sprintf("offsetOf(%s : %T)", typ, typ))
+	}
+	return offset
+}
+
+// sliceToArray returns the type representing the arrays to which
+// slice type slice points.
+func sliceToArray(slice types.Type) *types.Array {
+	return types.NewArray(slice.Underlying().(*types.Slice).Elem(), 1)
+}
+
+// Node set -------------------------------------------------------------------
+
+type nodeset struct {
+	intsets.Sparse
+}
+
+func (ns *nodeset) String() string {
+	var buf bytes.Buffer
+	buf.WriteRune('{')
+	var space [50]int
+	for i, n := range ns.AppendTo(space[:0]) {
+		if i > 0 {
+			buf.WriteString(", ")
+		}
+		buf.WriteRune('n')
+		fmt.Fprintf(&buf, "%d", n)
+	}
+	buf.WriteRune('}')
+	return buf.String()
+}
+
+func (ns *nodeset) add(n nodeid) bool {
+	return ns.Sparse.Insert(int(n))
+}
+
+func (x *nodeset) addAll(y *nodeset) bool {
+	return x.UnionWith(&y.Sparse)
+}
+
+// Profiling & debugging -------------------------------------------------------
+
+var timers = make(map[string]time.Time)
+
+func start(name string) {
+	if debugTimers {
+		timers[name] = time.Now()
+		log.Printf("%s...\n", name)
+	}
+}
+
+func stop(name string) {
+	if debugTimers {
+		log.Printf("%s took %s\n", name, time.Since(timers[name]))
+	}
+}
+
+// diff runs the command "diff a b" and reports its success.
+func diff(a, b string) bool {
+	var cmd *exec.Cmd
+	switch runtime.GOOS {
+	case "plan9":
+		cmd = exec.Command("/bin/diff", "-c", a, b)
+	default:
+		cmd = exec.Command("/usr/bin/diff", "-u", a, b)
+	}
+	cmd.Stdout = os.Stderr
+	cmd.Stderr = os.Stderr
+	return cmd.Run() == nil
+}
diff --git a/third_party/go.tools/go/ssa/blockopt.go b/third_party/go.tools/go/ssa/blockopt.go
new file mode 100644
index 0000000..e79260a
--- /dev/null
+++ b/third_party/go.tools/go/ssa/blockopt.go
@@ -0,0 +1,187 @@
+// Copyright 2013 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 ssa
+
+// Simple block optimizations to simplify the control flow graph.
+
+// TODO(adonovan): opt: instead of creating several "unreachable" blocks
+// per function in the Builder, reuse a single one (e.g. at Blocks[1])
+// to reduce garbage.
+
+import (
+	"fmt"
+	"os"
+)
+
+// If true, perform sanity checking and show progress at each
+// successive iteration of optimizeBlocks.  Very verbose.
+const debugBlockOpt = false
+
+// markReachable sets Index=-1 for all blocks reachable from b.
+func markReachable(b *BasicBlock) {
+	b.Index = -1
+	for _, succ := range b.Succs {
+		if succ.Index == 0 {
+			markReachable(succ)
+		}
+	}
+}
+
+// deleteUnreachableBlocks marks all reachable blocks of f and
+// eliminates (nils) all others, including possibly cyclic subgraphs.
+//
+func deleteUnreachableBlocks(f *Function) {
+	const white, black = 0, -1
+	// We borrow b.Index temporarily as the mark bit.
+	for _, b := range f.Blocks {
+		b.Index = white
+	}
+	markReachable(f.Blocks[0])
+	if f.Recover != nil {
+		markReachable(f.Recover)
+	}
+	for i, b := range f.Blocks {
+		if b.Index == white {
+			for _, c := range b.Succs {
+				if c.Index == black {
+					c.removePred(b) // delete white->black edge
+				}
+			}
+			if debugBlockOpt {
+				fmt.Fprintln(os.Stderr, "unreachable", b)
+			}
+			f.Blocks[i] = nil // delete b
+		}
+	}
+	f.removeNilBlocks()
+}
+
+// jumpThreading attempts to apply simple jump-threading to block b,
+// in which a->b->c become a->c if b is just a Jump.
+// The result is true if the optimization was applied.
+//
+func jumpThreading(f *Function, b *BasicBlock) bool {
+	if b.Index == 0 {
+		return false // don't apply to entry block
+	}
+	if b.Instrs == nil {
+		return false
+	}
+	if _, ok := b.Instrs[0].(*Jump); !ok {
+		return false // not just a jump
+	}
+	c := b.Succs[0]
+	if c == b {
+		return false // don't apply to degenerate jump-to-self.
+	}
+	if c.hasPhi() {
+		return false // not sound without more effort
+	}
+	for j, a := range b.Preds {
+		a.replaceSucc(b, c)
+
+		// If a now has two edges to c, replace its degenerate If by Jump.
+		if len(a.Succs) == 2 && a.Succs[0] == c && a.Succs[1] == c {
+			jump := new(Jump)
+			jump.setBlock(a)
+			a.Instrs[len(a.Instrs)-1] = jump
+			a.Succs = a.Succs[:1]
+			c.removePred(b)
+		} else {
+			if j == 0 {
+				c.replacePred(b, a)
+			} else {
+				c.Preds = append(c.Preds, a)
+			}
+		}
+
+		if debugBlockOpt {
+			fmt.Fprintln(os.Stderr, "jumpThreading", a, b, c)
+		}
+	}
+	f.Blocks[b.Index] = nil // delete b
+	return true
+}
+
+// fuseBlocks attempts to apply the block fusion optimization to block
+// a, in which a->b becomes ab if len(a.Succs)==len(b.Preds)==1.
+// The result is true if the optimization was applied.
+//
+func fuseBlocks(f *Function, a *BasicBlock) bool {
+	if len(a.Succs) != 1 {
+		return false
+	}
+	b := a.Succs[0]
+	if len(b.Preds) != 1 {
+		return false
+	}
+
+	// Degenerate &&/|| ops may result in a straight-line CFG
+	// containing φ-nodes. (Ideally we'd replace such them with
+	// their sole operand but that requires Referrers, built later.)
+	if b.hasPhi() {
+		return false // not sound without further effort
+	}
+
+	// Eliminate jump at end of A, then copy all of B across.
+	a.Instrs = append(a.Instrs[:len(a.Instrs)-1], b.Instrs...)
+	for _, instr := range b.Instrs {
+		instr.setBlock(a)
+	}
+
+	// A inherits B's successors
+	a.Succs = append(a.succs2[:0], b.Succs...)
+
+	// Fix up Preds links of all successors of B.
+	for _, c := range b.Succs {
+		c.replacePred(b, a)
+	}
+
+	if debugBlockOpt {
+		fmt.Fprintln(os.Stderr, "fuseBlocks", a, b)
+	}
+
+	f.Blocks[b.Index] = nil // delete b
+	return true
+}
+
+// optimizeBlocks() performs some simple block optimizations on a
+// completed function: dead block elimination, block fusion, jump
+// threading.
+//
+func optimizeBlocks(f *Function) {
+	deleteUnreachableBlocks(f)
+
+	// Loop until no further progress.
+	changed := true
+	for changed {
+		changed = false
+
+		if debugBlockOpt {
+			f.WriteTo(os.Stderr)
+			mustSanityCheck(f, nil)
+		}
+
+		for _, b := range f.Blocks {
+			// f.Blocks will temporarily contain nils to indicate
+			// deleted blocks; we remove them at the end.
+			if b == nil {
+				continue
+			}
+
+			// Fuse blocks.  b->c becomes bc.
+			if fuseBlocks(f, b) {
+				changed = true
+			}
+
+			// a->b->c becomes a->c if b contains only a Jump.
+			if jumpThreading(f, b) {
+				changed = true
+				continue // (b was disconnected)
+			}
+		}
+	}
+	f.removeNilBlocks()
+}
diff --git a/third_party/go.tools/go/ssa/builder.go b/third_party/go.tools/go/ssa/builder.go
new file mode 100644
index 0000000..4ca5e0e
--- /dev/null
+++ b/third_party/go.tools/go/ssa/builder.go
@@ -0,0 +1,2410 @@
+// Copyright 2013 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 ssa
+
+// This file implements the BUILD phase of SSA construction.
+//
+// SSA construction has two phases, CREATE and BUILD.  In the CREATE phase
+// (create.go), all packages are constructed and type-checked and
+// definitions of all package members are created, method-sets are
+// computed, and wrapper methods are synthesized.
+// ssa.Packages are created in arbitrary order.
+//
+// In the BUILD phase (builder.go), the builder traverses the AST of
+// each Go source function and generates SSA instructions for the
+// function body.  Initializer expressions for package-level variables
+// are emitted to the package's init() function in the order specified
+// by go/types.Info.InitOrder, then code for each function in the
+// package is generated in lexical order.
+// The BUILD phases for distinct packages are independent and are
+// executed in parallel.
+//
+// TODO(adonovan): indeed, building functions is now embarrassingly parallel.
+// Audit for concurrency then benchmark using more goroutines.
+//
+// The builder's and Program's indices (maps) are populated and
+// mutated during the CREATE phase, but during the BUILD phase they
+// remain constant.  The sole exception is Prog.methodSets and its
+// related maps, which are protected by a dedicated mutex.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"sync"
+	"sync/atomic"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+type opaqueType struct {
+	types.Type
+	name string
+}
+
+func (t *opaqueType) String() string { return t.name }
+
+var (
+	varOk    = newVar("ok", tBool)
+	varIndex = newVar("index", tInt)
+
+	// Type constants.
+	tBool       = types.Typ[types.Bool]
+	tByte       = types.Typ[types.Byte]
+	tInt        = types.Typ[types.Int]
+	tInvalid    = types.Typ[types.Invalid]
+	tString     = types.Typ[types.String]
+	tUntypedNil = types.Typ[types.UntypedNil]
+	tRangeIter  = &opaqueType{nil, "iter"} // the type of all "range" iterators
+	tEface      = new(types.Interface)
+
+	// SSA Value constants.
+	vZero = intConst(0)
+	vOne  = intConst(1)
+	vTrue = NewConst(exact.MakeBool(true), tBool)
+)
+
+// builder holds state associated with the package currently being built.
+// Its methods contain all the logic for AST-to-SSA conversion.
+type builder struct{}
+
+// cond emits to fn code to evaluate boolean condition e and jump
+// to t or f depending on its value, performing various simplifications.
+//
+// Postcondition: fn.currentBlock is nil.
+//
+func (b *builder) cond(fn *Function, e ast.Expr, t, f *BasicBlock) {
+	switch e := e.(type) {
+	case *ast.ParenExpr:
+		b.cond(fn, e.X, t, f)
+		return
+
+	case *ast.BinaryExpr:
+		switch e.Op {
+		case token.LAND:
+			ltrue := fn.newBasicBlock("cond.true")
+			b.cond(fn, e.X, ltrue, f)
+			fn.currentBlock = ltrue
+			b.cond(fn, e.Y, t, f)
+			return
+
+		case token.LOR:
+			lfalse := fn.newBasicBlock("cond.false")
+			b.cond(fn, e.X, t, lfalse)
+			fn.currentBlock = lfalse
+			b.cond(fn, e.Y, t, f)
+			return
+		}
+
+	case *ast.UnaryExpr:
+		if e.Op == token.NOT {
+			b.cond(fn, e.X, f, t)
+			return
+		}
+	}
+
+	// A traditional compiler would simplify "if false" (etc) here
+	// but we do not, for better fidelity to the source code.
+	//
+	// The value of a constant condition may be platform-specific,
+	// and may cause blocks that are reachable in some configuration
+	// to be hidden from subsequent analyses such as bug-finding tools.
+	emitIf(fn, b.expr(fn, e), t, f)
+}
+
+// logicalBinop emits code to fn to evaluate e, a &&- or
+// ||-expression whose reified boolean value is wanted.
+// The value is returned.
+//
+func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value {
+	rhs := fn.newBasicBlock("binop.rhs")
+	done := fn.newBasicBlock("binop.done")
+
+	// T(e) = T(e.X) = T(e.Y) after untyped constants have been
+	// eliminated.
+	// TODO(adonovan): not true; MyBool==MyBool yields UntypedBool.
+	t := fn.Pkg.typeOf(e)
+
+	var short Value // value of the short-circuit path
+	switch e.Op {
+	case token.LAND:
+		b.cond(fn, e.X, rhs, done)
+		short = NewConst(exact.MakeBool(false), t)
+
+	case token.LOR:
+		b.cond(fn, e.X, done, rhs)
+		short = NewConst(exact.MakeBool(true), t)
+	}
+
+	// Is rhs unreachable?
+	if rhs.Preds == nil {
+		// Simplify false&&y to false, true||y to true.
+		fn.currentBlock = done
+		return short
+	}
+
+	// Is done unreachable?
+	if done.Preds == nil {
+		// Simplify true&&y (or false||y) to y.
+		fn.currentBlock = rhs
+		return b.expr(fn, e.Y)
+	}
+
+	// All edges from e.X to done carry the short-circuit value.
+	var edges []Value
+	for _ = range done.Preds {
+		edges = append(edges, short)
+	}
+
+	// The edge from e.Y to done carries the value of e.Y.
+	fn.currentBlock = rhs
+	edges = append(edges, b.expr(fn, e.Y))
+	emitJump(fn, done)
+	fn.currentBlock = done
+
+	phi := &Phi{Edges: edges, Comment: e.Op.String()}
+	phi.pos = e.OpPos
+	phi.typ = t
+	return done.emit(phi)
+}
+
+// exprN lowers a multi-result expression e to SSA form, emitting code
+// to fn and returning a single Value whose type is a *types.Tuple.
+// The caller must access the components via Extract.
+//
+// Multi-result expressions include CallExprs in a multi-value
+// assignment or return statement, and "value,ok" uses of
+// TypeAssertExpr, IndexExpr (when X is a map), and UnaryExpr (when Op
+// is token.ARROW).
+//
+func (b *builder) exprN(fn *Function, e ast.Expr) Value {
+	typ := fn.Pkg.typeOf(e).(*types.Tuple)
+	switch e := e.(type) {
+	case *ast.ParenExpr:
+		return b.exprN(fn, e.X)
+
+	case *ast.CallExpr:
+		// Currently, no built-in function nor type conversion
+		// has multiple results, so we can avoid some of the
+		// cases for single-valued CallExpr.
+		var c Call
+		b.setCall(fn, e, &c.Call)
+		c.typ = typ
+		return fn.emit(&c)
+
+	case *ast.IndexExpr:
+		mapt := fn.Pkg.typeOf(e.X).Underlying().(*types.Map)
+		lookup := &Lookup{
+			X:       b.expr(fn, e.X),
+			Index:   emitConv(fn, b.expr(fn, e.Index), mapt.Key()),
+			CommaOk: true,
+		}
+		lookup.setType(typ)
+		lookup.setPos(e.Lbrack)
+		return fn.emit(lookup)
+
+	case *ast.TypeAssertExpr:
+		return emitTypeTest(fn, b.expr(fn, e.X), typ.At(0).Type(), e.Lparen)
+
+	case *ast.UnaryExpr: // must be receive <-
+		unop := &UnOp{
+			Op:      token.ARROW,
+			X:       b.expr(fn, e.X),
+			CommaOk: true,
+		}
+		unop.setType(typ)
+		unop.setPos(e.OpPos)
+		return fn.emit(unop)
+	}
+	panic(fmt.Sprintf("exprN(%T) in %s", e, fn))
+}
+
+// builtin emits to fn SSA instructions to implement a call to the
+// built-in function obj with the specified arguments
+// and return type.  It returns the value defined by the result.
+//
+// The result is nil if no special handling was required; in this case
+// the caller should treat this like an ordinary library function
+// call.
+//
+func (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value {
+	switch obj.Name() {
+	case "make":
+		switch typ.Underlying().(type) {
+		case *types.Slice:
+			n := b.expr(fn, args[1])
+			m := n
+			if len(args) == 3 {
+				m = b.expr(fn, args[2])
+			}
+			v := &MakeSlice{
+				Len: n,
+				Cap: m,
+			}
+			v.setPos(pos)
+			v.setType(typ)
+			return fn.emit(v)
+
+		case *types.Map:
+			var res Value
+			if len(args) == 2 {
+				res = b.expr(fn, args[1])
+			}
+			v := &MakeMap{Reserve: res}
+			v.setPos(pos)
+			v.setType(typ)
+			return fn.emit(v)
+
+		case *types.Chan:
+			var sz Value = vZero
+			if len(args) == 2 {
+				sz = b.expr(fn, args[1])
+			}
+			v := &MakeChan{Size: sz}
+			v.setPos(pos)
+			v.setType(typ)
+			return fn.emit(v)
+		}
+
+	case "new":
+		alloc := emitNew(fn, deref(typ), pos)
+		alloc.Comment = "new"
+		return alloc
+
+	case "len", "cap":
+		// Special case: len or cap of an array or *array is
+		// based on the type, not the value which may be nil.
+		// We must still evaluate the value, though.  (If it
+		// was side-effect free, the whole call would have
+		// been constant-folded.)
+		t := deref(fn.Pkg.typeOf(args[0])).Underlying()
+		if at, ok := t.(*types.Array); ok {
+			b.expr(fn, args[0]) // for effects only
+			return intConst(at.Len())
+		}
+		// Otherwise treat as normal.
+
+	case "panic":
+		fn.emit(&Panic{
+			X:   emitConv(fn, b.expr(fn, args[0]), tEface),
+			pos: pos,
+		})
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+		return vTrue // any non-nil Value will do
+	}
+	return nil // treat all others as a regular function call
+}
+
+// addr lowers a single-result addressable expression e to SSA form,
+// emitting code to fn and returning the location (an lvalue) defined
+// by the expression.
+//
+// If escaping is true, addr marks the base variable of the
+// addressable expression e as being a potentially escaping pointer
+// value.  For example, in this code:
+//
+//   a := A{
+//     b: [1]B{B{c: 1}}
+//   }
+//   return &a.b[0].c
+//
+// the application of & causes a.b[0].c to have its address taken,
+// which means that ultimately the local variable a must be
+// heap-allocated.  This is a simple but very conservative escape
+// analysis.
+//
+// Operations forming potentially escaping pointers include:
+// - &x, including when implicit in method call or composite literals.
+// - a[:] iff a is an array (not *array)
+// - references to variables in lexically enclosing functions.
+//
+func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
+	switch e := e.(type) {
+	case *ast.Ident:
+		if isBlankIdent(e) {
+			return blank{}
+		}
+		obj := fn.Pkg.objectOf(e)
+		v := fn.Prog.packageLevelValue(obj) // var (address)
+		if v == nil {
+			v = fn.lookup(obj, escaping)
+		}
+		return &address{addr: v, expr: e}
+
+	case *ast.CompositeLit:
+		t := deref(fn.Pkg.typeOf(e))
+		var v *Alloc
+		if escaping {
+			v = emitNew(fn, t, e.Lbrace)
+		} else {
+			v = fn.addLocal(t, e.Lbrace)
+		}
+		v.Comment = "complit"
+		b.compLit(fn, v, e, true) // initialize in place
+		return &address{addr: v, expr: e}
+
+	case *ast.ParenExpr:
+		return b.addr(fn, e.X, escaping)
+
+	case *ast.SelectorExpr:
+		sel, ok := fn.Pkg.info.Selections[e]
+		if !ok {
+			// qualified identifier
+			return b.addr(fn, e.Sel, escaping)
+		}
+		if sel.Kind() != types.FieldVal {
+			panic(sel)
+		}
+		wantAddr := true
+		v := b.receiver(fn, e.X, wantAddr, escaping, sel)
+		last := len(sel.Index()) - 1
+		return &address{
+			addr: emitFieldSelection(fn, v, sel.Index()[last], true, e.Sel),
+			expr: e.Sel,
+		}
+
+	case *ast.IndexExpr:
+		var x Value
+		var et types.Type
+		switch t := fn.Pkg.typeOf(e.X).Underlying().(type) {
+		case *types.Array:
+			x = b.addr(fn, e.X, escaping).address(fn)
+			et = types.NewPointer(t.Elem())
+		case *types.Pointer: // *array
+			x = b.expr(fn, e.X)
+			et = types.NewPointer(t.Elem().Underlying().(*types.Array).Elem())
+		case *types.Slice:
+			x = b.expr(fn, e.X)
+			et = types.NewPointer(t.Elem())
+		case *types.Map:
+			return &element{
+				m:   b.expr(fn, e.X),
+				k:   emitConv(fn, b.expr(fn, e.Index), t.Key()),
+				t:   t.Elem(),
+				pos: e.Lbrack,
+			}
+		default:
+			panic("unexpected container type in IndexExpr: " + t.String())
+		}
+		v := &IndexAddr{
+			X:     x,
+			Index: emitConv(fn, b.expr(fn, e.Index), tInt),
+		}
+		v.setPos(e.Lbrack)
+		v.setType(et)
+		return &address{addr: fn.emit(v), expr: e}
+
+	case *ast.StarExpr:
+		return &address{addr: b.expr(fn, e.X), starPos: e.Star, expr: e}
+	}
+
+	panic(fmt.Sprintf("unexpected address expression: %T", e))
+}
+
+// exprInPlace emits to fn code to initialize the lvalue loc with the
+// value of expression e. If isZero is true, exprInPlace assumes that loc
+// holds the zero value for its type.
+//
+// This is equivalent to loc.store(fn, b.expr(fn, e)) but may
+// generate better code in some cases, e.g. for composite literals
+// in an addressable location.
+//
+func (b *builder) exprInPlace(fn *Function, loc lvalue, e ast.Expr, isZero bool) {
+	if e, ok := unparen(e).(*ast.CompositeLit); ok {
+		// A CompositeLit never evaluates to a pointer,
+		// so if the type of the location is a pointer,
+		// an &-operation is implied.
+		if _, ok := loc.(blank); !ok { // avoid calling blank.typ()
+			if isPointer(loc.typ()) {
+				ptr := b.addr(fn, e, true).address(fn)
+				loc.store(fn, ptr) // copy address
+				return
+			}
+		}
+
+		if _, ok := loc.(*address); ok {
+			if isInterface(loc.typ()) {
+				// e.g. var x interface{} = T{...}
+				// Can't in-place initialize an interface value.
+				// Fall back to copying.
+			} else {
+				addr := loc.address(fn)
+				b.compLit(fn, addr, e, isZero) // in place
+				emitDebugRef(fn, e, addr, true)
+				return
+			}
+		}
+	}
+	loc.store(fn, b.expr(fn, e)) // copy value
+}
+
+// expr lowers a single-result expression e to SSA form, emitting code
+// to fn and returning the Value defined by the expression.
+//
+func (b *builder) expr(fn *Function, e ast.Expr) Value {
+	e = unparen(e)
+
+	tv := fn.Pkg.info.Types[e]
+
+	// Is expression a constant?
+	if tv.Value != nil {
+		return NewConst(tv.Value, tv.Type)
+	}
+
+	var v Value
+	if tv.Addressable() {
+		// Prefer pointer arithmetic ({Index,Field}Addr) followed
+		// by Load over subelement extraction (e.g. Index, Field),
+		// to avoid large copies.
+		v = b.addr(fn, e, false).load(fn)
+	} else {
+		v = b.expr0(fn, e, tv)
+	}
+	if fn.debugInfo() {
+		emitDebugRef(fn, e, v, false)
+	}
+	return v
+}
+
+func (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value {
+	switch e := e.(type) {
+	case *ast.BasicLit:
+		panic("non-constant BasicLit") // unreachable
+
+	case *ast.FuncLit:
+		fn2 := &Function{
+			name:      fmt.Sprintf("%s$%d", fn.Name(), 1+len(fn.AnonFuncs)),
+			Signature: fn.Pkg.typeOf(e.Type).Underlying().(*types.Signature),
+			pos:       e.Type.Func,
+			parent:    fn,
+			Pkg:       fn.Pkg,
+			Prog:      fn.Prog,
+			syntax:    e,
+		}
+		fn.AnonFuncs = append(fn.AnonFuncs, fn2)
+		b.buildFunction(fn2)
+		if fn2.FreeVars == nil {
+			return fn2
+		}
+		v := &MakeClosure{Fn: fn2}
+		v.setType(tv.Type)
+		for _, fv := range fn2.FreeVars {
+			v.Bindings = append(v.Bindings, fv.outer)
+			fv.outer = nil
+		}
+		return fn.emit(v)
+
+	case *ast.TypeAssertExpr: // single-result form only
+		return emitTypeAssert(fn, b.expr(fn, e.X), tv.Type, e.Lparen)
+
+	case *ast.CallExpr:
+		if fn.Pkg.info.Types[e.Fun].IsType() {
+			// Explicit type conversion, e.g. string(x) or big.Int(x)
+			x := b.expr(fn, e.Args[0])
+			y := emitConv(fn, x, tv.Type)
+			if y != x {
+				switch y := y.(type) {
+				case *Convert:
+					y.pos = e.Lparen
+				case *ChangeType:
+					y.pos = e.Lparen
+				case *MakeInterface:
+					y.pos = e.Lparen
+				}
+			}
+			return y
+		}
+		// Call to "intrinsic" built-ins, e.g. new, make, panic.
+		if id, ok := unparen(e.Fun).(*ast.Ident); ok {
+			if obj, ok := fn.Pkg.info.Uses[id].(*types.Builtin); ok {
+				if v := b.builtin(fn, obj, e.Args, tv.Type, e.Lparen); v != nil {
+					return v
+				}
+			}
+		}
+		// Regular function call.
+		var v Call
+		b.setCall(fn, e, &v.Call)
+		v.setType(tv.Type)
+		return fn.emit(&v)
+
+	case *ast.UnaryExpr:
+		switch e.Op {
+		case token.AND: // &X --- potentially escaping.
+			addr := b.addr(fn, e.X, true)
+			if _, ok := unparen(e.X).(*ast.StarExpr); ok {
+				// &*p must panic if p is nil (http://golang.org/s/go12nil).
+				// For simplicity, we'll just (suboptimally) rely
+				// on the side effects of a load.
+				// TODO(adonovan): emit dedicated nilcheck.
+				addr.load(fn)
+			}
+			return addr.address(fn)
+		case token.ADD:
+			return b.expr(fn, e.X)
+		case token.NOT, token.ARROW, token.SUB, token.XOR: // ! <- - ^
+			v := &UnOp{
+				Op: e.Op,
+				X:  b.expr(fn, e.X),
+			}
+			v.setPos(e.OpPos)
+			v.setType(tv.Type)
+			return fn.emit(v)
+		default:
+			panic(e.Op)
+		}
+
+	case *ast.BinaryExpr:
+		switch e.Op {
+		case token.LAND, token.LOR:
+			return b.logicalBinop(fn, e)
+		case token.SHL, token.SHR:
+			fallthrough
+		case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
+			return emitArith(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), tv.Type, e.OpPos)
+
+		case token.EQL, token.NEQ, token.GTR, token.LSS, token.LEQ, token.GEQ:
+			cmp := emitCompare(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), e.OpPos)
+			// The type of x==y may be UntypedBool.
+			return emitConv(fn, cmp, DefaultType(tv.Type))
+		default:
+			panic("illegal op in BinaryExpr: " + e.Op.String())
+		}
+
+	case *ast.SliceExpr:
+		var low, high, max Value
+		var x Value
+		switch fn.Pkg.typeOf(e.X).Underlying().(type) {
+		case *types.Array:
+			// Potentially escaping.
+			x = b.addr(fn, e.X, true).address(fn)
+		case *types.Basic, *types.Slice, *types.Pointer: // *array
+			x = b.expr(fn, e.X)
+		default:
+			unreachable()
+		}
+		if e.High != nil {
+			high = b.expr(fn, e.High)
+		}
+		if e.Low != nil {
+			low = b.expr(fn, e.Low)
+		}
+		if e.Slice3 {
+			max = b.expr(fn, e.Max)
+		}
+		v := &Slice{
+			X:    x,
+			Low:  low,
+			High: high,
+			Max:  max,
+		}
+		v.setPos(e.Lbrack)
+		v.setType(tv.Type)
+		return fn.emit(v)
+
+	case *ast.Ident:
+		obj := fn.Pkg.info.Uses[e]
+		// Universal built-in or nil?
+		switch obj := obj.(type) {
+		case *types.Builtin:
+			return &Builtin{name: obj.Name(), sig: tv.Type.(*types.Signature)}
+		case *types.Nil:
+			return nilConst(tv.Type)
+		}
+		// Package-level func or var?
+		if v := fn.Prog.packageLevelValue(obj); v != nil {
+			if _, ok := obj.(*types.Var); ok {
+				return emitLoad(fn, v) // var (address)
+			}
+			return v // (func)
+		}
+		// Local var.
+		return emitLoad(fn, fn.lookup(obj, false)) // var (address)
+
+	case *ast.SelectorExpr:
+		sel, ok := fn.Pkg.info.Selections[e]
+		if !ok {
+			// qualified identifier
+			return b.expr(fn, e.Sel)
+		}
+		switch sel.Kind() {
+		case types.MethodExpr:
+			// (*T).f or T.f, the method f from the method-set of type T.
+			// The result is a "thunk".
+			return emitConv(fn, makeThunk(fn.Prog, sel), tv.Type)
+
+		case types.MethodVal:
+			// e.f where e is an expression and f is a method.
+			// The result is a "bound".
+			obj := sel.Obj().(*types.Func)
+			rt := recvType(obj)
+			wantAddr := isPointer(rt)
+			escaping := true
+			v := b.receiver(fn, e.X, wantAddr, escaping, sel)
+			if isInterface(rt) {
+				// If v has interface type I,
+				// we must emit a check that v is non-nil.
+				// We use: typeassert v.(I).
+				emitTypeAssert(fn, v, rt, token.NoPos)
+			}
+			c := &MakeClosure{
+				Fn:       makeBound(fn.Prog, obj),
+				Bindings: []Value{v},
+			}
+			c.setPos(e.Sel.Pos())
+			c.setType(tv.Type)
+			return fn.emit(c)
+
+		case types.FieldVal:
+			indices := sel.Index()
+			last := len(indices) - 1
+			v := b.expr(fn, e.X)
+			v = emitImplicitSelections(fn, v, indices[:last])
+			v = emitFieldSelection(fn, v, indices[last], false, e.Sel)
+			return v
+		}
+
+		panic("unexpected expression-relative selector")
+
+	case *ast.IndexExpr:
+		switch t := fn.Pkg.typeOf(e.X).Underlying().(type) {
+		case *types.Array:
+			// Non-addressable array (in a register).
+			v := &Index{
+				X:     b.expr(fn, e.X),
+				Index: emitConv(fn, b.expr(fn, e.Index), tInt),
+			}
+			v.setPos(e.Lbrack)
+			v.setType(t.Elem())
+			return fn.emit(v)
+
+		case *types.Map:
+			// Maps are not addressable.
+			mapt := fn.Pkg.typeOf(e.X).Underlying().(*types.Map)
+			v := &Lookup{
+				X:     b.expr(fn, e.X),
+				Index: emitConv(fn, b.expr(fn, e.Index), mapt.Key()),
+			}
+			v.setPos(e.Lbrack)
+			v.setType(mapt.Elem())
+			return fn.emit(v)
+
+		case *types.Basic: // => string
+			// Strings are not addressable.
+			v := &Lookup{
+				X:     b.expr(fn, e.X),
+				Index: b.expr(fn, e.Index),
+			}
+			v.setPos(e.Lbrack)
+			v.setType(tByte)
+			return fn.emit(v)
+
+		case *types.Slice, *types.Pointer: // *array
+			// Addressable slice/array; use IndexAddr and Load.
+			return b.addr(fn, e, false).load(fn)
+
+		default:
+			panic("unexpected container type in IndexExpr: " + t.String())
+		}
+
+	case *ast.CompositeLit, *ast.StarExpr:
+		// Addressable types (lvalues)
+		return b.addr(fn, e, false).load(fn)
+	}
+
+	panic(fmt.Sprintf("unexpected expr: %T", e))
+}
+
+// stmtList emits to fn code for all statements in list.
+func (b *builder) stmtList(fn *Function, list []ast.Stmt) {
+	for _, s := range list {
+		b.stmt(fn, s)
+	}
+}
+
+// receiver emits to fn code for expression e in the "receiver"
+// position of selection e.f (where f may be a field or a method) and
+// returns the effective receiver after applying the implicit field
+// selections of sel.
+//
+// wantAddr requests that the result is an an address.  If
+// !sel.Indirect(), this may require that e be build in addr() mode; it
+// must thus be addressable.
+//
+// escaping is defined as per builder.addr().
+//
+func (b *builder) receiver(fn *Function, e ast.Expr, wantAddr, escaping bool, sel *types.Selection) Value {
+	var v Value
+	if wantAddr && !sel.Indirect() && !isPointer(fn.Pkg.typeOf(e)) {
+		v = b.addr(fn, e, escaping).address(fn)
+	} else {
+		v = b.expr(fn, e)
+	}
+
+	last := len(sel.Index()) - 1
+	v = emitImplicitSelections(fn, v, sel.Index()[:last])
+	if !wantAddr && isPointer(v.Type()) {
+		v = emitLoad(fn, v)
+	}
+	return v
+}
+
+// setCallFunc populates the function parts of a CallCommon structure
+// (Func, Method, Recv, Args[0]) based on the kind of invocation
+// occurring in e.
+//
+func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
+	c.pos = e.Lparen
+
+	// Is this a method call?
+	if selector, ok := unparen(e.Fun).(*ast.SelectorExpr); ok {
+		sel, ok := fn.Pkg.info.Selections[selector]
+		if ok && sel.Kind() == types.MethodVal {
+			obj := sel.Obj().(*types.Func)
+			wantAddr := isPointer(recvType(obj))
+			escaping := true
+			v := b.receiver(fn, selector.X, wantAddr, escaping, sel)
+			if isInterface(deref(v.Type())) {
+				// Invoke-mode call.
+				c.Value = v
+				c.Method = obj
+			} else {
+				// "Call"-mode call.
+				c.Value = fn.Prog.declaredFunc(obj)
+				c.Args = append(c.Args, v)
+			}
+			return
+		}
+
+		// sel.Kind()==MethodExpr indicates T.f() or (*T).f():
+		// a statically dispatched call to the method f in the
+		// method-set of T or *T.  T may be an interface.
+		//
+		// e.Fun would evaluate to a concrete method, interface
+		// wrapper function, or promotion wrapper.
+		//
+		// For now, we evaluate it in the usual way.
+		//
+		// TODO(adonovan): opt: inline expr() here, to make the
+		// call static and to avoid generation of wrappers.
+		// It's somewhat tricky as it may consume the first
+		// actual parameter if the call is "invoke" mode.
+		//
+		// Examples:
+		//  type T struct{}; func (T) f() {}   // "call" mode
+		//  type T interface { f() }           // "invoke" mode
+		//
+		//  type S struct{ T }
+		//
+		//  var s S
+		//  S.f(s)
+		//  (*S).f(&s)
+		//
+		// Suggested approach:
+		// - consume the first actual parameter expression
+		//   and build it with b.expr().
+		// - apply implicit field selections.
+		// - use MethodVal logic to populate fields of c.
+	}
+
+	// Evaluate the function operand in the usual way.
+	c.Value = b.expr(fn, e.Fun)
+}
+
+// emitCallArgs emits to f code for the actual parameters of call e to
+// a (possibly built-in) function of effective type sig.
+// The argument values are appended to args, which is then returned.
+//
+func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallExpr, args []Value) []Value {
+	// f(x, y, z...): pass slice z straight through.
+	if e.Ellipsis != 0 {
+		for i, arg := range e.Args {
+			v := emitConv(fn, b.expr(fn, arg), sig.Params().At(i).Type())
+			args = append(args, v)
+		}
+		return args
+	}
+
+	offset := len(args) // 1 if call has receiver, 0 otherwise
+
+	// Evaluate actual parameter expressions.
+	//
+	// If this is a chained call of the form f(g()) where g has
+	// multiple return values (MRV), they are flattened out into
+	// args; a suffix of them may end up in a varargs slice.
+	for _, arg := range e.Args {
+		v := b.expr(fn, arg)
+		if ttuple, ok := v.Type().(*types.Tuple); ok { // MRV chain
+			for i, n := 0, ttuple.Len(); i < n; i++ {
+				args = append(args, emitExtract(fn, v, i))
+			}
+		} else {
+			args = append(args, v)
+		}
+	}
+
+	// Actual->formal assignability conversions for normal parameters.
+	np := sig.Params().Len() // number of normal parameters
+	if sig.Variadic() {
+		np--
+	}
+	for i := 0; i < np; i++ {
+		args[offset+i] = emitConv(fn, args[offset+i], sig.Params().At(i).Type())
+	}
+
+	// Actual->formal assignability conversions for variadic parameter,
+	// and construction of slice.
+	if sig.Variadic() {
+		varargs := args[offset+np:]
+		st := sig.Params().At(np).Type().(*types.Slice)
+		vt := st.Elem()
+		if len(varargs) == 0 {
+			args = append(args, nilConst(st))
+		} else {
+			// Replace a suffix of args with a slice containing it.
+			at := types.NewArray(vt, int64(len(varargs)))
+			a := emitNew(fn, at, token.NoPos)
+			a.setPos(e.Rparen)
+			a.Comment = "varargs"
+			for i, arg := range varargs {
+				iaddr := &IndexAddr{
+					X:     a,
+					Index: intConst(int64(i)),
+				}
+				iaddr.setType(types.NewPointer(vt))
+				fn.emit(iaddr)
+				emitStore(fn, iaddr, arg)
+			}
+			s := &Slice{X: a}
+			s.setType(st)
+			args[offset+np] = fn.emit(s)
+			args = args[:offset+np+1]
+		}
+	}
+	return args
+}
+
+// setCall emits to fn code to evaluate all the parameters of a function
+// call e, and populates *c with those values.
+//
+func (b *builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
+	// First deal with the f(...) part and optional receiver.
+	b.setCallFunc(fn, e, c)
+
+	// Then append the other actual parameters.
+	sig, _ := fn.Pkg.typeOf(e.Fun).Underlying().(*types.Signature)
+	if sig == nil {
+		panic(fmt.Sprintf("no signature for call of %s", e.Fun))
+	}
+	c.Args = b.emitCallArgs(fn, sig, e, c.Args)
+}
+
+// assignOp emits to fn code to perform loc += incr or loc -= incr.
+func (b *builder) assignOp(fn *Function, loc lvalue, incr Value, op token.Token) {
+	oldv := loc.load(fn)
+	loc.store(fn, emitArith(fn, op, oldv, emitConv(fn, incr, oldv.Type()), loc.typ(), token.NoPos))
+}
+
+// localValueSpec emits to fn code to define all of the vars in the
+// function-local ValueSpec, spec.
+//
+func (b *builder) localValueSpec(fn *Function, spec *ast.ValueSpec) {
+	switch {
+	case len(spec.Values) == len(spec.Names):
+		// e.g. var x, y = 0, 1
+		// 1:1 assignment
+		for i, id := range spec.Names {
+			if !isBlankIdent(id) {
+				fn.addLocalForIdent(id)
+			}
+			lval := b.addr(fn, id, false) // non-escaping
+			b.exprInPlace(fn, lval, spec.Values[i], true)
+		}
+
+	case len(spec.Values) == 0:
+		// e.g. var x, y int
+		// Locals are implicitly zero-initialized.
+		for _, id := range spec.Names {
+			if !isBlankIdent(id) {
+				lhs := fn.addLocalForIdent(id)
+				if fn.debugInfo() {
+					emitDebugRef(fn, id, lhs, true)
+				}
+			}
+		}
+
+	default:
+		// e.g. var x, y = pos()
+		tuple := b.exprN(fn, spec.Values[0])
+		for i, id := range spec.Names {
+			if !isBlankIdent(id) {
+				fn.addLocalForIdent(id)
+				lhs := b.addr(fn, id, false) // non-escaping
+				lhs.store(fn, emitExtract(fn, tuple, i))
+			}
+		}
+	}
+}
+
+// assignStmt emits code to fn for a parallel assignment of rhss to lhss.
+// isDef is true if this is a short variable declaration (:=).
+//
+// Note the similarity with localValueSpec.
+//
+func (b *builder) assignStmt(fn *Function, lhss, rhss []ast.Expr, isDef bool) {
+	// Side effects of all LHSs and RHSs must occur in left-to-right order.
+	var lvals []lvalue
+	for _, lhs := range lhss {
+		var lval lvalue = blank{}
+		if !isBlankIdent(lhs) {
+			if isDef {
+				if obj := fn.Pkg.info.Defs[lhs.(*ast.Ident)]; obj != nil {
+					fn.addNamedLocal(obj)
+				}
+			}
+			lval = b.addr(fn, lhs, false) // non-escaping
+		}
+		lvals = append(lvals, lval)
+	}
+	if len(lhss) == len(rhss) {
+		// e.g. x, y = f(), g()
+		if len(lhss) == 1 {
+			// x = type{...}
+			// Optimization: in-place construction
+			// of composite literals.
+			b.exprInPlace(fn, lvals[0], rhss[0], false)
+		} else {
+			// Parallel assignment.  All reads must occur
+			// before all updates, precluding exprInPlace.
+			var rvals []Value
+			for _, rval := range rhss {
+				rvals = append(rvals, b.expr(fn, rval))
+			}
+			for i, lval := range lvals {
+				lval.store(fn, rvals[i])
+			}
+		}
+	} else {
+		// e.g. x, y = pos()
+		tuple := b.exprN(fn, rhss[0])
+		for i, lval := range lvals {
+			lval.store(fn, emitExtract(fn, tuple, i))
+		}
+	}
+}
+
+// arrayLen returns the length of the array whose composite literal elements are elts.
+func (b *builder) arrayLen(fn *Function, elts []ast.Expr) int64 {
+	var max int64 = -1
+	var i int64 = -1
+	for _, e := range elts {
+		if kv, ok := e.(*ast.KeyValueExpr); ok {
+			i = b.expr(fn, kv.Key).(*Const).Int64()
+		} else {
+			i++
+		}
+		if i > max {
+			max = i
+		}
+	}
+	return max + 1
+}
+
+// compLit emits to fn code to initialize a composite literal e at
+// address addr with type typ, typically allocated by Alloc.
+// Nested composite literals are recursively initialized in place
+// where possible. If isZero is true, compLit assumes that addr
+// holds the zero value for typ.
+//
+// A CompositeLit may have pointer type only in the recursive (nested)
+// case when the type name is implicit.  e.g. in []*T{{}}, the inner
+// literal has type *T behaves like &T{}.
+// In that case, addr must hold a T, not a *T.
+//
+func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero bool) {
+	typ := deref(fn.Pkg.typeOf(e))
+	switch t := typ.Underlying().(type) {
+	case *types.Struct:
+		if !isZero && len(e.Elts) != t.NumFields() {
+			emitMemClear(fn, addr)
+			isZero = true
+		}
+		for i, e := range e.Elts {
+			fieldIndex := i
+			if kv, ok := e.(*ast.KeyValueExpr); ok {
+				fname := kv.Key.(*ast.Ident).Name
+				for i, n := 0, t.NumFields(); i < n; i++ {
+					sf := t.Field(i)
+					if sf.Name() == fname {
+						fieldIndex = i
+						e = kv.Value
+						break
+					}
+				}
+			}
+			sf := t.Field(fieldIndex)
+			faddr := &FieldAddr{
+				X:     addr,
+				Field: fieldIndex,
+			}
+			faddr.setType(types.NewPointer(sf.Type()))
+			fn.emit(faddr)
+			b.exprInPlace(fn, &address{addr: faddr, expr: e}, e, isZero)
+		}
+
+	case *types.Array, *types.Slice:
+		var at *types.Array
+		var array Value
+		switch t := t.(type) {
+		case *types.Slice:
+			at = types.NewArray(t.Elem(), b.arrayLen(fn, e.Elts))
+			alloc := emitNew(fn, at, e.Lbrace)
+			alloc.Comment = "slicelit"
+			array = alloc
+			isZero = true
+		case *types.Array:
+			at = t
+			array = addr
+		}
+
+		if !isZero && int64(len(e.Elts)) != at.Len() {
+			emitMemClear(fn, array)
+			isZero = true
+		}
+
+		var idx *Const
+		for _, e := range e.Elts {
+			if kv, ok := e.(*ast.KeyValueExpr); ok {
+				idx = b.expr(fn, kv.Key).(*Const)
+				e = kv.Value
+			} else {
+				var idxval int64
+				if idx != nil {
+					idxval = idx.Int64() + 1
+				}
+				idx = intConst(idxval)
+			}
+			iaddr := &IndexAddr{
+				X:     array,
+				Index: idx,
+			}
+			iaddr.setType(types.NewPointer(at.Elem()))
+			fn.emit(iaddr)
+			b.exprInPlace(fn, &address{addr: iaddr, expr: e}, e, isZero)
+		}
+		if t != at { // slice
+			s := &Slice{X: array}
+			s.setPos(e.Lbrace)
+			s.setType(typ)
+			emitStore(fn, addr, fn.emit(s))
+		}
+
+	case *types.Map:
+		m := &MakeMap{Reserve: intConst(int64(len(e.Elts)))}
+		m.setPos(e.Lbrace)
+		m.setType(typ)
+		emitStore(fn, addr, fn.emit(m))
+		for _, e := range e.Elts {
+			e := e.(*ast.KeyValueExpr)
+			loc := &element{
+				m:   m,
+				k:   emitConv(fn, b.expr(fn, e.Key), t.Key()),
+				t:   t.Elem(),
+				pos: e.Colon,
+			}
+			b.exprInPlace(fn, loc, e.Value, true)
+		}
+
+	default:
+		panic("unexpected CompositeLit type: " + t.String())
+	}
+}
+
+// switchStmt emits to fn code for the switch statement s, optionally
+// labelled by label.
+//
+func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) {
+	// We treat SwitchStmt like a sequential if-else chain.
+	// Multiway dispatch can be recovered later by ssautil.Switches()
+	// to those cases that are free of side effects.
+	if s.Init != nil {
+		b.stmt(fn, s.Init)
+	}
+	var tag Value = vTrue
+	if s.Tag != nil {
+		tag = b.expr(fn, s.Tag)
+	}
+	done := fn.newBasicBlock("switch.done")
+	if label != nil {
+		label._break = done
+	}
+	// We pull the default case (if present) down to the end.
+	// But each fallthrough label must point to the next
+	// body block in source order, so we preallocate a
+	// body block (fallthru) for the next case.
+	// Unfortunately this makes for a confusing block order.
+	var dfltBody *[]ast.Stmt
+	var dfltFallthrough *BasicBlock
+	var fallthru, dfltBlock *BasicBlock
+	ncases := len(s.Body.List)
+	for i, clause := range s.Body.List {
+		body := fallthru
+		if body == nil {
+			body = fn.newBasicBlock("switch.body") // first case only
+		}
+
+		// Preallocate body block for the next case.
+		fallthru = done
+		if i+1 < ncases {
+			fallthru = fn.newBasicBlock("switch.body")
+		}
+
+		cc := clause.(*ast.CaseClause)
+		if cc.List == nil {
+			// Default case.
+			dfltBody = &cc.Body
+			dfltFallthrough = fallthru
+			dfltBlock = body
+			continue
+		}
+
+		var nextCond *BasicBlock
+		for _, cond := range cc.List {
+			nextCond = fn.newBasicBlock("switch.next")
+			// TODO(adonovan): opt: when tag==vTrue, we'd
+			// get better code if we use b.cond(cond)
+			// instead of BinOp(EQL, tag, b.expr(cond))
+			// followed by If.  Don't forget conversions
+			// though.
+			cond := emitCompare(fn, token.EQL, tag, b.expr(fn, cond), token.NoPos)
+			emitIf(fn, cond, body, nextCond)
+			fn.currentBlock = nextCond
+		}
+		fn.currentBlock = body
+		fn.targets = &targets{
+			tail:         fn.targets,
+			_break:       done,
+			_fallthrough: fallthru,
+		}
+		b.stmtList(fn, cc.Body)
+		fn.targets = fn.targets.tail
+		emitJump(fn, done)
+		fn.currentBlock = nextCond
+	}
+	if dfltBlock != nil {
+		emitJump(fn, dfltBlock)
+		fn.currentBlock = dfltBlock
+		fn.targets = &targets{
+			tail:         fn.targets,
+			_break:       done,
+			_fallthrough: dfltFallthrough,
+		}
+		b.stmtList(fn, *dfltBody)
+		fn.targets = fn.targets.tail
+	}
+	emitJump(fn, done)
+	fn.currentBlock = done
+}
+
+// typeSwitchStmt emits to fn code for the type switch statement s, optionally
+// labelled by label.
+//
+func (b *builder) typeSwitchStmt(fn *Function, s *ast.TypeSwitchStmt, label *lblock) {
+	// We treat TypeSwitchStmt like a sequential if-else chain.
+	// Multiway dispatch can be recovered later by ssautil.Switches().
+
+	// Typeswitch lowering:
+	//
+	// var x X
+	// switch y := x.(type) {
+	// case T1, T2: S1                  // >1 	(y := x)
+	// case nil:    SN                  // nil 	(y := x)
+	// default:     SD                  // 0 types 	(y := x)
+	// case T3:     S3                  // 1 type 	(y := x.(T3))
+	// }
+	//
+	//      ...s.Init...
+	// 	x := eval x
+	// .caseT1:
+	// 	t1, ok1 := typeswitch,ok x <T1>
+	// 	if ok1 then goto S1 else goto .caseT2
+	// .caseT2:
+	// 	t2, ok2 := typeswitch,ok x <T2>
+	// 	if ok2 then goto S1 else goto .caseNil
+	// .S1:
+	//      y := x
+	// 	...S1...
+	// 	goto done
+	// .caseNil:
+	// 	if t2, ok2 := typeswitch,ok x <T2>
+	// 	if x == nil then goto SN else goto .caseT3
+	// .SN:
+	//      y := x
+	// 	...SN...
+	// 	goto done
+	// .caseT3:
+	// 	t3, ok3 := typeswitch,ok x <T3>
+	// 	if ok3 then goto S3 else goto default
+	// .S3:
+	//      y := t3
+	// 	...S3...
+	// 	goto done
+	// .default:
+	//      y := x
+	// 	...SD...
+	// 	goto done
+	// .done:
+
+	if s.Init != nil {
+		b.stmt(fn, s.Init)
+	}
+
+	var x Value
+	switch ass := s.Assign.(type) {
+	case *ast.ExprStmt: // x.(type)
+		x = b.expr(fn, unparen(ass.X).(*ast.TypeAssertExpr).X)
+	case *ast.AssignStmt: // y := x.(type)
+		x = b.expr(fn, unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)
+	}
+
+	done := fn.newBasicBlock("typeswitch.done")
+	if label != nil {
+		label._break = done
+	}
+	var default_ *ast.CaseClause
+	for _, clause := range s.Body.List {
+		cc := clause.(*ast.CaseClause)
+		if cc.List == nil {
+			default_ = cc
+			continue
+		}
+		body := fn.newBasicBlock("typeswitch.body")
+		var next *BasicBlock
+		var casetype types.Type
+		var ti Value // ti, ok := typeassert,ok x <Ti>
+		for _, cond := range cc.List {
+			next = fn.newBasicBlock("typeswitch.next")
+			casetype = fn.Pkg.typeOf(cond)
+			var condv Value
+			if casetype == tUntypedNil {
+				condv = emitCompare(fn, token.EQL, x, nilConst(x.Type()), token.NoPos)
+				ti = x
+			} else {
+				yok := emitTypeTest(fn, x, casetype, cc.Case)
+				ti = emitExtract(fn, yok, 0)
+				condv = emitExtract(fn, yok, 1)
+			}
+			emitIf(fn, condv, body, next)
+			fn.currentBlock = next
+		}
+		if len(cc.List) != 1 {
+			ti = x
+		}
+		fn.currentBlock = body
+		b.typeCaseBody(fn, cc, ti, done)
+		fn.currentBlock = next
+	}
+	if default_ != nil {
+		b.typeCaseBody(fn, default_, x, done)
+	} else {
+		emitJump(fn, done)
+	}
+	fn.currentBlock = done
+}
+
+func (b *builder) typeCaseBody(fn *Function, cc *ast.CaseClause, x Value, done *BasicBlock) {
+	if obj := fn.Pkg.info.Implicits[cc]; obj != nil {
+		// In a switch y := x.(type), each case clause
+		// implicitly declares a distinct object y.
+		// In a single-type case, y has that type.
+		// In multi-type cases, 'case nil' and default,
+		// y has the same type as the interface operand.
+		emitStore(fn, fn.addNamedLocal(obj), x)
+	}
+	fn.targets = &targets{
+		tail:   fn.targets,
+		_break: done,
+	}
+	b.stmtList(fn, cc.Body)
+	fn.targets = fn.targets.tail
+	emitJump(fn, done)
+}
+
+// selectStmt emits to fn code for the select statement s, optionally
+// labelled by label.
+//
+func (b *builder) selectStmt(fn *Function, s *ast.SelectStmt, label *lblock) {
+	// A blocking select of a single case degenerates to a
+	// simple send or receive.
+	// TODO(adonovan): opt: is this optimization worth its weight?
+	if len(s.Body.List) == 1 {
+		clause := s.Body.List[0].(*ast.CommClause)
+		if clause.Comm != nil {
+			b.stmt(fn, clause.Comm)
+			done := fn.newBasicBlock("select.done")
+			if label != nil {
+				label._break = done
+			}
+			fn.targets = &targets{
+				tail:   fn.targets,
+				_break: done,
+			}
+			b.stmtList(fn, clause.Body)
+			fn.targets = fn.targets.tail
+			emitJump(fn, done)
+			fn.currentBlock = done
+			return
+		}
+	}
+
+	// First evaluate all channels in all cases, and find
+	// the directions of each state.
+	var states []*SelectState
+	blocking := true
+	debugInfo := fn.debugInfo()
+	for _, clause := range s.Body.List {
+		var st *SelectState
+		switch comm := clause.(*ast.CommClause).Comm.(type) {
+		case nil: // default case
+			blocking = false
+			continue
+
+		case *ast.SendStmt: // ch<- i
+			ch := b.expr(fn, comm.Chan)
+			st = &SelectState{
+				Dir:  types.SendOnly,
+				Chan: ch,
+				Send: emitConv(fn, b.expr(fn, comm.Value),
+					ch.Type().Underlying().(*types.Chan).Elem()),
+				Pos: comm.Arrow,
+			}
+			if debugInfo {
+				st.DebugNode = comm
+			}
+
+		case *ast.AssignStmt: // x := <-ch
+			recv := unparen(comm.Rhs[0]).(*ast.UnaryExpr)
+			st = &SelectState{
+				Dir:  types.RecvOnly,
+				Chan: b.expr(fn, recv.X),
+				Pos:  recv.OpPos,
+			}
+			if debugInfo {
+				st.DebugNode = recv
+			}
+
+		case *ast.ExprStmt: // <-ch
+			recv := unparen(comm.X).(*ast.UnaryExpr)
+			st = &SelectState{
+				Dir:  types.RecvOnly,
+				Chan: b.expr(fn, recv.X),
+				Pos:  recv.OpPos,
+			}
+			if debugInfo {
+				st.DebugNode = recv
+			}
+		}
+		states = append(states, st)
+	}
+
+	// We dispatch on the (fair) result of Select using a
+	// sequential if-else chain, in effect:
+	//
+	// idx, recvOk, r0...r_n-1 := select(...)
+	// if idx == 0 {  // receive on channel 0  (first receive => r0)
+	//     x, ok := r0, recvOk
+	//     ...state0...
+	// } else if v == 1 {   // send on channel 1
+	//     ...state1...
+	// } else {
+	//     ...default...
+	// }
+	sel := &Select{
+		States:   states,
+		Blocking: blocking,
+	}
+	sel.setPos(s.Select)
+	var vars []*types.Var
+	vars = append(vars, varIndex, varOk)
+	for _, st := range states {
+		if st.Dir == types.RecvOnly {
+			tElem := st.Chan.Type().Underlying().(*types.Chan).Elem()
+			vars = append(vars, anonVar(tElem))
+		}
+	}
+	sel.setType(types.NewTuple(vars...))
+
+	fn.emit(sel)
+	idx := emitExtract(fn, sel, 0)
+
+	done := fn.newBasicBlock("select.done")
+	if label != nil {
+		label._break = done
+	}
+
+	var defaultBody *[]ast.Stmt
+	state := 0
+	r := 2 // index in 'sel' tuple of value; increments if st.Dir==RECV
+	for _, cc := range s.Body.List {
+		clause := cc.(*ast.CommClause)
+		if clause.Comm == nil {
+			defaultBody = &clause.Body
+			continue
+		}
+		body := fn.newBasicBlock("select.body")
+		next := fn.newBasicBlock("select.next")
+		emitIf(fn, emitCompare(fn, token.EQL, idx, intConst(int64(state)), token.NoPos), body, next)
+		fn.currentBlock = body
+		fn.targets = &targets{
+			tail:   fn.targets,
+			_break: done,
+		}
+		switch comm := clause.Comm.(type) {
+		case *ast.ExprStmt: // <-ch
+			if debugInfo {
+				v := emitExtract(fn, sel, r)
+				emitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false)
+			}
+			r++
+
+		case *ast.AssignStmt: // x := <-states[state].Chan
+			if comm.Tok == token.DEFINE {
+				fn.addLocalForIdent(comm.Lhs[0].(*ast.Ident))
+			}
+			x := b.addr(fn, comm.Lhs[0], false) // non-escaping
+			v := emitExtract(fn, sel, r)
+			if debugInfo {
+				emitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false)
+			}
+			x.store(fn, v)
+
+			if len(comm.Lhs) == 2 { // x, ok := ...
+				if comm.Tok == token.DEFINE {
+					fn.addLocalForIdent(comm.Lhs[1].(*ast.Ident))
+				}
+				ok := b.addr(fn, comm.Lhs[1], false) // non-escaping
+				ok.store(fn, emitExtract(fn, sel, 1))
+			}
+			r++
+		}
+		b.stmtList(fn, clause.Body)
+		fn.targets = fn.targets.tail
+		emitJump(fn, done)
+		fn.currentBlock = next
+		state++
+	}
+	if defaultBody != nil {
+		fn.targets = &targets{
+			tail:   fn.targets,
+			_break: done,
+		}
+		b.stmtList(fn, *defaultBody)
+		fn.targets = fn.targets.tail
+	} else {
+		// A blocking select must match some case.
+		// (This should really be a runtime.errorString, not a string.)
+		fn.emit(&Panic{
+			X: emitConv(fn, stringConst("blocking select matched no case"), tEface),
+		})
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+	}
+	emitJump(fn, done)
+	fn.currentBlock = done
+}
+
+// forStmt emits to fn code for the for statement s, optionally
+// labelled by label.
+//
+func (b *builder) forStmt(fn *Function, s *ast.ForStmt, label *lblock) {
+	//	...init...
+	//      jump loop
+	// loop:
+	//      if cond goto body else done
+	// body:
+	//      ...body...
+	//      jump post
+	// post:				 (target of continue)
+	//      ...post...
+	//      jump loop
+	// done:                                 (target of break)
+	if s.Init != nil {
+		b.stmt(fn, s.Init)
+	}
+	body := fn.newBasicBlock("for.body")
+	done := fn.newBasicBlock("for.done") // target of 'break'
+	loop := body                         // target of back-edge
+	if s.Cond != nil {
+		loop = fn.newBasicBlock("for.loop")
+	}
+	cont := loop // target of 'continue'
+	if s.Post != nil {
+		cont = fn.newBasicBlock("for.post")
+	}
+	if label != nil {
+		label._break = done
+		label._continue = cont
+	}
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+	if loop != body {
+		b.cond(fn, s.Cond, body, done)
+		fn.currentBlock = body
+	}
+	fn.targets = &targets{
+		tail:      fn.targets,
+		_break:    done,
+		_continue: cont,
+	}
+	b.stmt(fn, s.Body)
+	fn.targets = fn.targets.tail
+	emitJump(fn, cont)
+
+	if s.Post != nil {
+		fn.currentBlock = cont
+		b.stmt(fn, s.Post)
+		emitJump(fn, loop) // back-edge
+	}
+	fn.currentBlock = done
+}
+
+// rangeIndexed emits to fn the header for an integer-indexed loop
+// over array, *array or slice value x.
+// The v result is defined only if tv is non-nil.
+//
+func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type) (k, v Value, loop, done *BasicBlock) {
+	//
+	//      length = len(x)
+	//      index = -1
+	// loop:                                   (target of continue)
+	//      index++
+	// 	if index < length goto body else done
+	// body:
+	//      k = index
+	//      v = x[index]
+	//      ...body...
+	// 	jump loop
+	// done:                                   (target of break)
+
+	// Determine number of iterations.
+	var length Value
+	if arr, ok := deref(x.Type()).Underlying().(*types.Array); ok {
+		// For array or *array, the number of iterations is
+		// known statically thanks to the type.  We avoid a
+		// data dependence upon x, permitting later dead-code
+		// elimination if x is pure, static unrolling, etc.
+		// Ranging over a nil *array may have >0 iterations.
+		// We still generate code for x, in case it has effects.
+		length = intConst(arr.Len())
+	} else {
+		// length = len(x).
+		var c Call
+		c.Call.Value = makeLen(x.Type())
+		c.Call.Args = []Value{x}
+		c.setType(tInt)
+		length = fn.emit(&c)
+	}
+
+	index := fn.addLocal(tInt, token.NoPos)
+	emitStore(fn, index, intConst(-1))
+
+	loop = fn.newBasicBlock("rangeindex.loop")
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+
+	incr := &BinOp{
+		Op: token.ADD,
+		X:  emitLoad(fn, index),
+		Y:  vOne,
+	}
+	incr.setType(tInt)
+	emitStore(fn, index, fn.emit(incr))
+
+	body := fn.newBasicBlock("rangeindex.body")
+	done = fn.newBasicBlock("rangeindex.done")
+	emitIf(fn, emitCompare(fn, token.LSS, incr, length, token.NoPos), body, done)
+	fn.currentBlock = body
+
+	k = emitLoad(fn, index)
+	if tv != nil {
+		switch t := x.Type().Underlying().(type) {
+		case *types.Array:
+			instr := &Index{
+				X:     x,
+				Index: k,
+			}
+			instr.setType(t.Elem())
+			v = fn.emit(instr)
+
+		case *types.Pointer: // *array
+			instr := &IndexAddr{
+				X:     x,
+				Index: k,
+			}
+			instr.setType(types.NewPointer(t.Elem().Underlying().(*types.Array).Elem()))
+			v = emitLoad(fn, fn.emit(instr))
+
+		case *types.Slice:
+			instr := &IndexAddr{
+				X:     x,
+				Index: k,
+			}
+			instr.setType(types.NewPointer(t.Elem()))
+			v = emitLoad(fn, fn.emit(instr))
+
+		default:
+			panic("rangeIndexed x:" + t.String())
+		}
+	}
+	return
+}
+
+// rangeIter emits to fn the header for a loop using
+// Range/Next/Extract to iterate over map or string value x.
+// tk and tv are the types of the key/value results k and v, or nil
+// if the respective component is not wanted.
+//
+func (b *builder) rangeIter(fn *Function, x Value, tk, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
+	//
+	//	it = range x
+	// loop:                                   (target of continue)
+	//	okv = next it                      (ok, key, value)
+	//  	ok = extract okv #0
+	// 	if ok goto body else done
+	// body:
+	// 	k = extract okv #1
+	// 	v = extract okv #2
+	//      ...body...
+	// 	jump loop
+	// done:                                   (target of break)
+	//
+
+	if tk == nil {
+		tk = tInvalid
+	}
+	if tv == nil {
+		tv = tInvalid
+	}
+
+	rng := &Range{X: x}
+	rng.setPos(pos)
+	rng.setType(tRangeIter)
+	it := fn.emit(rng)
+
+	loop = fn.newBasicBlock("rangeiter.loop")
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+
+	_, isString := x.Type().Underlying().(*types.Basic)
+
+	okv := &Next{
+		Iter:     it,
+		IsString: isString,
+	}
+	okv.setType(types.NewTuple(
+		varOk,
+		newVar("k", tk),
+		newVar("v", tv),
+	))
+	fn.emit(okv)
+
+	body := fn.newBasicBlock("rangeiter.body")
+	done = fn.newBasicBlock("rangeiter.done")
+	emitIf(fn, emitExtract(fn, okv, 0), body, done)
+	fn.currentBlock = body
+
+	if tk != tInvalid {
+		k = emitExtract(fn, okv, 1)
+	}
+	if tv != tInvalid {
+		v = emitExtract(fn, okv, 2)
+	}
+	return
+}
+
+// rangeChan emits to fn the header for a loop that receives from
+// channel x until it fails.
+// tk is the channel's element type, or nil if the k result is
+// not wanted
+// pos is the position of the '=' or ':=' token.
+//
+func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {
+	//
+	// loop:                                   (target of continue)
+	//      ko = <-x                           (key, ok)
+	//      ok = extract ko #1
+	//      if ok goto body else done
+	// body:
+	//      k = extract ko #0
+	//      ...
+	//      goto loop
+	// done:                                   (target of break)
+
+	loop = fn.newBasicBlock("rangechan.loop")
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+	recv := &UnOp{
+		Op:      token.ARROW,
+		X:       x,
+		CommaOk: true,
+	}
+	recv.setPos(pos)
+	recv.setType(types.NewTuple(
+		newVar("k", x.Type().Underlying().(*types.Chan).Elem()),
+		varOk,
+	))
+	ko := fn.emit(recv)
+	body := fn.newBasicBlock("rangechan.body")
+	done = fn.newBasicBlock("rangechan.done")
+	emitIf(fn, emitExtract(fn, ko, 1), body, done)
+	fn.currentBlock = body
+	if tk != nil {
+		k = emitExtract(fn, ko, 0)
+	}
+	return
+}
+
+// rangeStmt emits to fn code for the range statement s, optionally
+// labelled by label.
+//
+func (b *builder) rangeStmt(fn *Function, s *ast.RangeStmt, label *lblock) {
+	var tk, tv types.Type
+	if s.Key != nil && !isBlankIdent(s.Key) {
+		tk = fn.Pkg.typeOf(s.Key)
+	}
+	if s.Value != nil && !isBlankIdent(s.Value) {
+		tv = fn.Pkg.typeOf(s.Value)
+	}
+
+	// If iteration variables are defined (:=), this
+	// occurs once outside the loop.
+	//
+	// Unlike a short variable declaration, a RangeStmt
+	// using := never redeclares an existing variable; it
+	// always creates a new one.
+	if s.Tok == token.DEFINE {
+		if tk != nil {
+			fn.addLocalForIdent(s.Key.(*ast.Ident))
+		}
+		if tv != nil {
+			fn.addLocalForIdent(s.Value.(*ast.Ident))
+		}
+	}
+
+	x := b.expr(fn, s.X)
+
+	var k, v Value
+	var loop, done *BasicBlock
+	switch rt := x.Type().Underlying().(type) {
+	case *types.Slice, *types.Array, *types.Pointer: // *array
+		k, v, loop, done = b.rangeIndexed(fn, x, tv)
+
+	case *types.Chan:
+		k, loop, done = b.rangeChan(fn, x, tk, s.TokPos)
+
+	case *types.Map, *types.Basic: // string
+		k, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For)
+
+	default:
+		panic("Cannot range over: " + rt.String())
+	}
+
+	// Evaluate both LHS expressions before we update either.
+	var kl, vl lvalue
+	if tk != nil {
+		kl = b.addr(fn, s.Key, false) // non-escaping
+	}
+	if tv != nil {
+		vl = b.addr(fn, s.Value, false) // non-escaping
+	}
+	if tk != nil {
+		kl.store(fn, k)
+	}
+	if tv != nil {
+		vl.store(fn, v)
+	}
+
+	if label != nil {
+		label._break = done
+		label._continue = loop
+	}
+
+	fn.targets = &targets{
+		tail:      fn.targets,
+		_break:    done,
+		_continue: loop,
+	}
+	b.stmt(fn, s.Body)
+	fn.targets = fn.targets.tail
+	emitJump(fn, loop) // back-edge
+	fn.currentBlock = done
+}
+
+// stmt lowers statement s to SSA form, emitting code to fn.
+func (b *builder) stmt(fn *Function, _s ast.Stmt) {
+	// The label of the current statement.  If non-nil, its _goto
+	// target is always set; its _break and _continue are set only
+	// within the body of switch/typeswitch/select/for/range.
+	// It is effectively an additional default-nil parameter of stmt().
+	var label *lblock
+start:
+	switch s := _s.(type) {
+	case *ast.EmptyStmt:
+		// ignore.  (Usually removed by gofmt.)
+
+	case *ast.DeclStmt: // Con, Var or Typ
+		d := s.Decl.(*ast.GenDecl)
+		if d.Tok == token.VAR {
+			for _, spec := range d.Specs {
+				if vs, ok := spec.(*ast.ValueSpec); ok {
+					b.localValueSpec(fn, vs)
+				}
+			}
+		}
+
+	case *ast.LabeledStmt:
+		label = fn.labelledBlock(s.Label)
+		emitJump(fn, label._goto)
+		fn.currentBlock = label._goto
+		_s = s.Stmt
+		goto start // effectively: tailcall stmt(fn, s.Stmt, label)
+
+	case *ast.ExprStmt:
+		b.expr(fn, s.X)
+
+	case *ast.SendStmt:
+		fn.emit(&Send{
+			Chan: b.expr(fn, s.Chan),
+			X: emitConv(fn, b.expr(fn, s.Value),
+				fn.Pkg.typeOf(s.Chan).Underlying().(*types.Chan).Elem()),
+			pos: s.Arrow,
+		})
+
+	case *ast.IncDecStmt:
+		op := token.ADD
+		if s.Tok == token.DEC {
+			op = token.SUB
+		}
+		loc := b.addr(fn, s.X, false)
+		b.assignOp(fn, loc, NewConst(exact.MakeInt64(1), loc.typ()), op)
+
+	case *ast.AssignStmt:
+		switch s.Tok {
+		case token.ASSIGN, token.DEFINE:
+			b.assignStmt(fn, s.Lhs, s.Rhs, s.Tok == token.DEFINE)
+
+		default: // +=, etc.
+			op := s.Tok + token.ADD - token.ADD_ASSIGN
+			b.assignOp(fn, b.addr(fn, s.Lhs[0], false), b.expr(fn, s.Rhs[0]), op)
+		}
+
+	case *ast.GoStmt:
+		// The "intrinsics" new/make/len/cap are forbidden here.
+		// panic is treated like an ordinary function call.
+		v := Go{pos: s.Go}
+		b.setCall(fn, s.Call, &v.Call)
+		fn.emit(&v)
+
+	case *ast.DeferStmt:
+		// The "intrinsics" new/make/len/cap are forbidden here.
+		// panic is treated like an ordinary function call.
+		v := Defer{pos: s.Defer}
+		b.setCall(fn, s.Call, &v.Call)
+		fn.emit(&v)
+
+		// A deferred call can cause recovery from panic,
+		// and control resumes at the Recover block.
+		createRecoverBlock(fn)
+
+	case *ast.ReturnStmt:
+		var results []Value
+		if len(s.Results) == 1 && fn.Signature.Results().Len() > 1 {
+			// Return of one expression in a multi-valued function.
+			tuple := b.exprN(fn, s.Results[0])
+			ttuple := tuple.Type().(*types.Tuple)
+			for i, n := 0, ttuple.Len(); i < n; i++ {
+				results = append(results,
+					emitConv(fn, emitExtract(fn, tuple, i),
+						fn.Signature.Results().At(i).Type()))
+			}
+		} else {
+			// 1:1 return, or no-arg return in non-void function.
+			for i, r := range s.Results {
+				v := emitConv(fn, b.expr(fn, r), fn.Signature.Results().At(i).Type())
+				results = append(results, v)
+			}
+		}
+		if fn.namedResults != nil {
+			// Function has named result parameters (NRPs).
+			// Perform parallel assignment of return operands to NRPs.
+			for i, r := range results {
+				emitStore(fn, fn.namedResults[i], r)
+			}
+		}
+		// Run function calls deferred in this
+		// function when explicitly returning from it.
+		fn.emit(new(RunDefers))
+		if fn.namedResults != nil {
+			// Reload NRPs to form the result tuple.
+			results = results[:0]
+			for _, r := range fn.namedResults {
+				results = append(results, emitLoad(fn, r))
+			}
+		}
+		fn.emit(&Return{Results: results, pos: s.Return})
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+
+	case *ast.BranchStmt:
+		var block *BasicBlock
+		switch s.Tok {
+		case token.BREAK:
+			if s.Label != nil {
+				block = fn.labelledBlock(s.Label)._break
+			} else {
+				for t := fn.targets; t != nil && block == nil; t = t.tail {
+					block = t._break
+				}
+			}
+
+		case token.CONTINUE:
+			if s.Label != nil {
+				block = fn.labelledBlock(s.Label)._continue
+			} else {
+				for t := fn.targets; t != nil && block == nil; t = t.tail {
+					block = t._continue
+				}
+			}
+
+		case token.FALLTHROUGH:
+			for t := fn.targets; t != nil && block == nil; t = t.tail {
+				block = t._fallthrough
+			}
+
+		case token.GOTO:
+			block = fn.labelledBlock(s.Label)._goto
+		}
+		emitJump(fn, block)
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+
+	case *ast.BlockStmt:
+		b.stmtList(fn, s.List)
+
+	case *ast.IfStmt:
+		if s.Init != nil {
+			b.stmt(fn, s.Init)
+		}
+		then := fn.newBasicBlock("if.then")
+		done := fn.newBasicBlock("if.done")
+		els := done
+		if s.Else != nil {
+			els = fn.newBasicBlock("if.else")
+		}
+		b.cond(fn, s.Cond, then, els)
+		fn.currentBlock = then
+		b.stmt(fn, s.Body)
+		emitJump(fn, done)
+
+		if s.Else != nil {
+			fn.currentBlock = els
+			b.stmt(fn, s.Else)
+			emitJump(fn, done)
+		}
+
+		fn.currentBlock = done
+
+	case *ast.SwitchStmt:
+		b.switchStmt(fn, s, label)
+
+	case *ast.TypeSwitchStmt:
+		b.typeSwitchStmt(fn, s, label)
+
+	case *ast.SelectStmt:
+		b.selectStmt(fn, s, label)
+
+	case *ast.ForStmt:
+		b.forStmt(fn, s, label)
+
+	case *ast.RangeStmt:
+		b.rangeStmt(fn, s, label)
+
+	default:
+		panic(fmt.Sprintf("unexpected statement kind: %T", s))
+	}
+}
+
+// buildFunction builds SSA code for the body of function fn.  Idempotent.
+func (b *builder) buildFunction(fn *Function) {
+	if fn.Blocks != nil {
+		return // building already started
+	}
+
+	var recvField *ast.FieldList
+	var body *ast.BlockStmt
+	var functype *ast.FuncType
+	switch n := fn.syntax.(type) {
+	case nil:
+		return // not a Go source function.  (Synthetic, or from object file.)
+	case *ast.FuncDecl:
+		functype = n.Type
+		recvField = n.Recv
+		body = n.Body
+	case *ast.FuncLit:
+		functype = n.Type
+		body = n.Body
+	default:
+		panic(n)
+	}
+
+	if body == nil {
+		// External function.
+		if fn.Params == nil {
+			// This condition ensures we add a non-empty
+			// params list once only, but we may attempt
+			// the degenerate empty case repeatedly.
+			// TODO(adonovan): opt: don't do that.
+
+			// We set Function.Params even though there is no body
+			// code to reference them.  This simplifies clients.
+			if recv := fn.Signature.Recv(); recv != nil {
+				fn.addParamObj(recv)
+			}
+			params := fn.Signature.Params()
+			for i, n := 0, params.Len(); i < n; i++ {
+				fn.addParamObj(params.At(i))
+			}
+		}
+		return
+	}
+	if fn.Prog.mode&LogSource != 0 {
+		defer logStack("build function %s @ %s", fn, fn.Prog.Fset.Position(fn.pos))()
+	}
+	fn.startBody()
+	fn.createSyntacticParams(recvField, functype)
+	b.stmt(fn, body)
+	if cb := fn.currentBlock; cb != nil && (cb == fn.Blocks[0] || cb == fn.Recover || cb.Preds != nil) {
+		// Control fell off the end of the function's body block.
+		//
+		// Block optimizations eliminate the current block, if
+		// unreachable.  It is a builder invariant that
+		// if this no-arg return is ill-typed for
+		// fn.Signature.Results, this block must be
+		// unreachable.  The sanity checker checks this.
+		fn.emit(new(RunDefers))
+		fn.emit(new(Return))
+	}
+	fn.finishBody()
+}
+
+// buildFuncDecl builds SSA code for the function or method declared
+// by decl in package pkg.
+//
+func (b *builder) buildFuncDecl(pkg *Package, decl *ast.FuncDecl) {
+	id := decl.Name
+	if isBlankIdent(id) {
+		return // discard
+	}
+	var fn *Function
+	if decl.Recv == nil && id.Name == "init" {
+		pkg.ninit++
+		fn = &Function{
+			name:      fmt.Sprintf("init#%d", pkg.ninit),
+			Signature: new(types.Signature),
+			pos:       decl.Name.NamePos,
+			Pkg:       pkg,
+			Prog:      pkg.Prog,
+			syntax:    decl,
+		}
+
+		var v Call
+		v.Call.Value = fn
+		v.setType(types.NewTuple())
+		pkg.init.emit(&v)
+	} else {
+		fn = pkg.values[pkg.info.Defs[id]].(*Function)
+	}
+	b.buildFunction(fn)
+}
+
+// BuildAll calls Package.Build() for each package in prog.
+// Building occurs in parallel unless the BuildSerially mode flag was set.
+//
+// BuildAll is idempotent and thread-safe.
+//
+func (prog *Program) BuildAll() {
+	var wg sync.WaitGroup
+	for _, p := range prog.packages {
+		if prog.mode&BuildSerially != 0 {
+			p.Build()
+		} else {
+			wg.Add(1)
+			go func(p *Package) {
+				p.Build()
+				wg.Done()
+			}(p)
+		}
+	}
+	wg.Wait()
+}
+
+// Build builds SSA code for all functions and vars in package p.
+//
+// Precondition: CreatePackage must have been called for all of p's
+// direct imports (and hence its direct imports must have been
+// error-free).
+//
+// Build is idempotent and thread-safe.
+//
+func (p *Package) Build() {
+	if !atomic.CompareAndSwapInt32(&p.started, 0, 1) {
+		return // already started
+	}
+	if p.info == nil {
+		return // synthetic package, e.g. "testmain"
+	}
+	if len(p.info.Files) == 0 {
+		p.info = nil
+		return // package loaded from export data
+	}
+
+	// Ensure we have runtime type info for all exported members.
+	// TODO(adonovan): ideally belongs in memberFromObject, but
+	// that would require package creation in topological order.
+	for name, mem := range p.Members {
+		if ast.IsExported(name) {
+			p.needMethodsOf(mem.Type())
+		}
+	}
+	if p.Prog.mode&LogSource != 0 {
+		defer logStack("build %s", p)()
+	}
+	init := p.init
+	init.startBody()
+
+	var done *BasicBlock
+
+	if p.Prog.mode&BareInits == 0 {
+		// Make init() skip if package is already initialized.
+		initguard := p.Var("init$guard")
+		doinit := init.newBasicBlock("init.start")
+		done = init.newBasicBlock("init.done")
+		emitIf(init, emitLoad(init, initguard), done, doinit)
+		init.currentBlock = doinit
+		emitStore(init, initguard, vTrue)
+
+		// Call the init() function of each package we import.
+		for _, pkg := range p.info.Pkg.Imports() {
+			prereq := p.Prog.packages[pkg]
+			if prereq == nil {
+				panic(fmt.Sprintf("Package(%q).Build(): unsatisfied import: Program.CreatePackage(%q) was not called", p.Object.Path(), pkg.Path()))
+			}
+			var v Call
+			v.Call.Value = prereq.init
+			v.Call.pos = init.pos
+			v.setType(types.NewTuple())
+			init.emit(&v)
+		}
+	}
+
+	var b builder
+
+	// Initialize package-level vars in correct order.
+	for _, varinit := range p.info.InitOrder {
+		if init.Prog.mode&LogSource != 0 {
+			fmt.Fprintf(os.Stderr, "build global initializer %v @ %s\n",
+				varinit.Lhs, p.Prog.Fset.Position(varinit.Rhs.Pos()))
+		}
+		if len(varinit.Lhs) == 1 {
+			// 1:1 initialization: var x, y = a(), b()
+			var lval lvalue
+			if v := varinit.Lhs[0]; v.Name() != "_" {
+				lval = &address{addr: p.values[v].(*Global)}
+			} else {
+				lval = blank{}
+			}
+			b.exprInPlace(init, lval, varinit.Rhs, true)
+		} else {
+			// n:1 initialization: var x, y :=  f()
+			tuple := b.exprN(init, varinit.Rhs)
+			for i, v := range varinit.Lhs {
+				if v.Name() == "_" {
+					continue
+				}
+				emitStore(init, p.values[v].(*Global), emitExtract(init, tuple, i))
+			}
+		}
+	}
+
+	// Build all package-level functions, init functions
+	// and methods, including unreachable/blank ones.
+	// We build them in source order, but it's not significant.
+	for _, file := range p.info.Files {
+		for _, decl := range file.Decls {
+			if decl, ok := decl.(*ast.FuncDecl); ok {
+				b.buildFuncDecl(p, decl)
+			}
+		}
+	}
+
+	// Finish up init().
+	if p.Prog.mode&BareInits == 0 {
+		emitJump(init, done)
+		init.currentBlock = done
+	}
+	init.emit(new(Return))
+	init.finishBody()
+
+	p.info = nil // We no longer need ASTs or go/types deductions.
+
+	if p.Prog.mode&SanityCheckFunctions != 0 {
+		sanityCheckPackage(p)
+	}
+}
+
+// Like ObjectOf, but panics instead of returning nil.
+// Only valid during p's create and build phases.
+func (p *Package) objectOf(id *ast.Ident) types.Object {
+	if o := p.info.ObjectOf(id); o != nil {
+		return o
+	}
+	panic(fmt.Sprintf("no types.Object for ast.Ident %s @ %s",
+		id.Name, p.Prog.Fset.Position(id.Pos())))
+}
+
+// Like TypeOf, but panics instead of returning nil.
+// Only valid during p's create and build phases.
+func (p *Package) typeOf(e ast.Expr) types.Type {
+	if T := p.info.TypeOf(e); T != nil {
+		return T
+	}
+	panic(fmt.Sprintf("no type for %T @ %s",
+		e, p.Prog.Fset.Position(e.Pos())))
+}
+
+// needMethodsOf ensures that runtime type information (including the
+// complete method set) is available for the specified type T and all
+// its subcomponents.
+//
+// needMethodsOf must be called for at least every type that is an
+// operand of some MakeInterface instruction, and for the type of
+// every exported package member.
+//
+// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+//
+// Thread-safe.  (Called via emitConv from multiple builder goroutines.)
+//
+// TODO(adonovan): make this faster.  It accounts for 20% of SSA build
+// time.  Do we need to maintain a distinct needRTTI and methodSets per
+// package?  Using just one in the program might be much faster.
+//
+func (p *Package) needMethodsOf(T types.Type) {
+	p.methodsMu.Lock()
+	p.needMethods(T, false)
+	p.methodsMu.Unlock()
+}
+
+// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+// Precondition: the p.methodsMu lock is held.
+// Recursive case: skip => don't call makeMethods(T).
+func (p *Package) needMethods(T types.Type, skip bool) {
+	// Each package maintains its own set of types it has visited.
+	if prevSkip, ok := p.needRTTI.At(T).(bool); ok {
+		// needMethods(T) was previously called
+		if !prevSkip || skip {
+			return // already seen, with same or false 'skip' value
+		}
+	}
+	p.needRTTI.Set(T, skip)
+
+	// Prune the recursion if we find a named or *named type
+	// belonging to another package.
+	var n *types.Named
+	switch T := T.(type) {
+	case *types.Named:
+		n = T
+	case *types.Pointer:
+		n, _ = T.Elem().(*types.Named)
+	}
+	if n != nil {
+		owner := n.Obj().Pkg()
+		if owner == nil {
+			return // built-in error type
+		}
+		if owner != p.Object {
+			return // belongs to another package
+		}
+	}
+
+	// All the actual method sets live in the Program so that
+	// multiple packages can share a single copy in memory of the
+	// symbols that would be compiled into multiple packages (as
+	// weak symbols).
+	if !skip && p.Prog.makeMethods(T) {
+		p.methodSets = append(p.methodSets, T)
+	}
+
+	// Recursion over signatures of each method.
+	tmset := p.Prog.MethodSets.MethodSet(T)
+	for i := 0; i < tmset.Len(); i++ {
+		sig := tmset.At(i).Type().(*types.Signature)
+		p.needMethods(sig.Params(), false)
+		p.needMethods(sig.Results(), false)
+	}
+
+	switch t := T.(type) {
+	case *types.Basic:
+		// nop
+
+	case *types.Interface:
+		// nop---handled by recursion over method set.
+
+	case *types.Pointer:
+		p.needMethods(t.Elem(), false)
+
+	case *types.Slice:
+		p.needMethods(t.Elem(), false)
+
+	case *types.Chan:
+		p.needMethods(t.Elem(), false)
+
+	case *types.Map:
+		p.needMethods(t.Key(), false)
+		p.needMethods(t.Elem(), false)
+
+	case *types.Signature:
+		if t.Recv() != nil {
+			panic(fmt.Sprintf("Signature %s has Recv %s", t, t.Recv()))
+		}
+		p.needMethods(t.Params(), false)
+		p.needMethods(t.Results(), false)
+
+	case *types.Named:
+		// A pointer-to-named type can be derived from a named
+		// type via reflection.  It may have methods too.
+		p.needMethods(types.NewPointer(T), false)
+
+		// Consider 'type T struct{S}' where S has methods.
+		// Reflection provides no way to get from T to struct{S},
+		// only to S, so the method set of struct{S} is unwanted,
+		// so set 'skip' flag during recursion.
+		p.needMethods(t.Underlying(), true)
+
+	case *types.Array:
+		p.needMethods(t.Elem(), false)
+
+	case *types.Struct:
+		for i, n := 0, t.NumFields(); i < n; i++ {
+			p.needMethods(t.Field(i).Type(), false)
+		}
+
+	case *types.Tuple:
+		for i, n := 0, t.Len(); i < n; i++ {
+			p.needMethods(t.At(i).Type(), false)
+		}
+
+	default:
+		panic(T)
+	}
+}
diff --git a/third_party/go.tools/go/ssa/builder_test.go b/third_party/go.tools/go/ssa/builder_test.go
new file mode 100644
index 0000000..2a2b517
--- /dev/null
+++ b/third_party/go.tools/go/ssa/builder_test.go
@@ -0,0 +1,319 @@
+// Copyright 2013 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 ssa_test
+
+import (
+	"bytes"
+	"reflect"
+	"sort"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func isEmpty(f *ssa.Function) bool { return f.Blocks == nil }
+
+// Tests that programs partially loaded from gc object files contain
+// functions with no code for the external portions, but are otherwise ok.
+func TestExternalPackages(t *testing.T) {
+	test := `
+package main
+
+import (
+	"bytes"
+	"io"
+	"testing"
+)
+
+func main() {
+        var t testing.T
+	t.Parallel()    // static call to external declared method
+        t.Fail()        // static call to promoted external declared method
+        testing.Short() // static call to external package-level function
+
+        var w io.Writer = new(bytes.Buffer)
+        w.Write(nil)    // interface invoke of external declared method
+}
+`
+
+	// Create a single-file main package.
+	var conf loader.Config
+	f, err := conf.ParseFile("<input>", test)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	conf.CreateFromFiles("main", f)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	prog := ssa.Create(iprog, ssa.SanityCheckFunctions)
+	mainPkg := prog.Package(iprog.Created[0].Pkg)
+	mainPkg.Build()
+
+	// The main package, its direct and indirect dependencies are loaded.
+	deps := []string{
+		// directly imported dependencies:
+		"bytes", "io", "testing",
+		// indirect dependencies (partial list):
+		"errors", "fmt", "os", "runtime",
+	}
+
+	all := prog.AllPackages()
+	if len(all) <= len(deps) {
+		t.Errorf("unexpected set of loaded packages: %q", all)
+	}
+	for _, path := range deps {
+		pkg := prog.ImportedPackage(path)
+		if pkg == nil {
+			t.Errorf("package not loaded: %q", path)
+			continue
+		}
+
+		// External packages should have no function bodies (except for wrappers).
+		isExt := pkg != mainPkg
+
+		// init()
+		if isExt && !isEmpty(pkg.Func("init")) {
+			t.Errorf("external package %s has non-empty init", pkg)
+		} else if !isExt && isEmpty(pkg.Func("init")) {
+			t.Errorf("main package %s has empty init", pkg)
+		}
+
+		for _, mem := range pkg.Members {
+			switch mem := mem.(type) {
+			case *ssa.Function:
+				// Functions at package level.
+				if isExt && !isEmpty(mem) {
+					t.Errorf("external function %s is non-empty", mem)
+				} else if !isExt && isEmpty(mem) {
+					t.Errorf("function %s is empty", mem)
+				}
+
+			case *ssa.Type:
+				// Methods of named types T.
+				// (In this test, all exported methods belong to *T not T.)
+				if !isExt {
+					t.Fatalf("unexpected name type in main package: %s", mem)
+				}
+				mset := prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))
+				for i, n := 0, mset.Len(); i < n; i++ {
+					m := prog.Method(mset.At(i))
+					// For external types, only synthetic wrappers have code.
+					expExt := !strings.Contains(m.Synthetic, "wrapper")
+					if expExt && !isEmpty(m) {
+						t.Errorf("external method %s is non-empty: %s",
+							m, m.Synthetic)
+					} else if !expExt && isEmpty(m) {
+						t.Errorf("method function %s is empty: %s",
+							m, m.Synthetic)
+					}
+				}
+			}
+		}
+	}
+
+	expectedCallee := []string{
+		"(*testing.T).Parallel",
+		"(*testing.common).Fail",
+		"testing.Short",
+		"N/A",
+	}
+	callNum := 0
+	for _, b := range mainPkg.Func("main").Blocks {
+		for _, instr := range b.Instrs {
+			switch instr := instr.(type) {
+			case ssa.CallInstruction:
+				call := instr.Common()
+				if want := expectedCallee[callNum]; want != "N/A" {
+					got := call.StaticCallee().String()
+					if want != got {
+						t.Errorf("call #%d from main.main: got callee %s, want %s",
+							callNum, got, want)
+					}
+				}
+				callNum++
+			}
+		}
+	}
+	if callNum != 4 {
+		t.Errorf("in main.main: got %d calls, want %d", callNum, 4)
+	}
+}
+
+// TestTypesWithMethodSets tests that Package.TypesWithMethodSets includes all necessary types.
+func TestTypesWithMethodSets(t *testing.T) {
+	tests := []struct {
+		input string
+		want  []string
+	}{
+		// An exported package-level type is needed.
+		{`package A; type T struct{}; func (T) f() {}`,
+			[]string{"*p.T", "p.T"},
+		},
+		// An unexported package-level type is not needed.
+		{`package B; type t struct{}; func (t) f() {}`,
+			nil,
+		},
+		// Subcomponents of type of exported package-level var are needed.
+		{`package C; import "bytes"; var V struct {*bytes.Buffer}`,
+			[]string{"*struct{*bytes.Buffer}", "struct{*bytes.Buffer}"},
+		},
+		// Subcomponents of type of unexported package-level var are not needed.
+		{`package D; import "bytes"; var v struct {*bytes.Buffer}`,
+			nil,
+		},
+		// Subcomponents of type of exported package-level function are needed.
+		{`package E; import "bytes"; func F(struct {*bytes.Buffer}) {}`,
+			[]string{"struct{*bytes.Buffer}"},
+		},
+		// Subcomponents of type of unexported package-level function are not needed.
+		{`package F; import "bytes"; func f(struct {*bytes.Buffer}) {}`,
+			nil,
+		},
+		// Subcomponents of type of exported method of uninstantiated unexported type are not needed.
+		{`package G; import "bytes"; type x struct{}; func (x) G(struct {*bytes.Buffer}) {}; var v x`,
+			nil,
+		},
+		// ...unless used by MakeInterface.
+		{`package G2; import "bytes"; type x struct{}; func (x) G(struct {*bytes.Buffer}) {}; var v interface{} = x{}`,
+			[]string{"*p.x", "p.x", "struct{*bytes.Buffer}"},
+		},
+		// Subcomponents of type of unexported method are not needed.
+		{`package I; import "bytes"; type X struct{}; func (X) G(struct {*bytes.Buffer}) {}`,
+			[]string{"*p.X", "p.X", "struct{*bytes.Buffer}"},
+		},
+		// Local types aren't needed.
+		{`package J; import "bytes"; func f() { type T struct {*bytes.Buffer}; var t T; _ = t }`,
+			nil,
+		},
+		// ...unless used by MakeInterface.
+		{`package K; import "bytes"; func f() { type T struct {*bytes.Buffer}; _ = interface{}(T{}) }`,
+			[]string{"*p.T", "p.T"},
+		},
+		// Types used as operand of MakeInterface are needed.
+		{`package L; import "bytes"; func f() { _ = interface{}(struct{*bytes.Buffer}{}) }`,
+			[]string{"struct{*bytes.Buffer}"},
+		},
+		// MakeInterface is optimized away when storing to a blank.
+		{`package M; import "bytes"; var _ interface{} = struct{*bytes.Buffer}{}`,
+			nil,
+		},
+	}
+	for _, test := range tests {
+		// Create a single-file main package.
+		var conf loader.Config
+		f, err := conf.ParseFile("<input>", test.input)
+		if err != nil {
+			t.Errorf("test %q: %s", test.input[:15], err)
+			continue
+		}
+		conf.CreateFromFiles("p", f)
+
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Errorf("test 'package %s': Load: %s", f.Name.Name, err)
+			continue
+		}
+		prog := ssa.Create(iprog, ssa.SanityCheckFunctions)
+		mainPkg := prog.Package(iprog.Created[0].Pkg)
+		prog.BuildAll()
+
+		var typstrs []string
+		for _, T := range mainPkg.TypesWithMethodSets() {
+			typstrs = append(typstrs, T.String())
+		}
+		sort.Strings(typstrs)
+
+		if !reflect.DeepEqual(typstrs, test.want) {
+			t.Errorf("test 'package %s': got %q, want %q", f.Name.Name, typstrs, test.want)
+		}
+	}
+}
+
+// Tests that synthesized init functions are correctly formed.
+// Bare init functions omit calls to dependent init functions and the use of
+// an init guard. They are useful in cases where the client uses a different
+// calling convention for init functions, or cases where it is easier for a
+// client to analyze bare init functions. Both of these aspects are used by
+// the llgo compiler for simpler integration with gccgo's runtime library,
+// and to simplify the analysis whereby it deduces which stores to globals
+// can be lowered to global initializers.
+func TestInit(t *testing.T) {
+	tests := []struct {
+		mode        ssa.BuilderMode
+		input, want string
+	}{
+		{0, `package A; import _ "errors"; var i int = 42`,
+			`# Name: A.init
+# Package: A
+# Synthetic: package initializer
+func init():
+0:                                                                entry P:0 S:2
+	t0 = *init$guard                                                   bool
+	if t0 goto 2 else 1
+1:                                                           init.start P:1 S:1
+	*init$guard = true:bool
+	t1 = errors.init()                                                   ()
+	*i = 42:int
+	jump 2
+2:                                                            init.done P:2 S:0
+	return
+
+`},
+		{ssa.BareInits, `package B; import _ "errors"; var i int = 42`,
+			`# Name: B.init
+# Package: B
+# Synthetic: package initializer
+func init():
+0:                                                                entry P:0 S:0
+	*i = 42:int
+	return
+
+`},
+	}
+	for _, test := range tests {
+		// Create a single-file main package.
+		var conf loader.Config
+		f, err := conf.ParseFile("<input>", test.input)
+		if err != nil {
+			t.Errorf("test %q: %s", test.input[:15], err)
+			continue
+		}
+		conf.CreateFromFiles(f.Name.Name, f)
+
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Errorf("test 'package %s': Load: %s", f.Name.Name, err)
+			continue
+		}
+		prog := ssa.Create(iprog, test.mode)
+		mainPkg := prog.Package(iprog.Created[0].Pkg)
+		prog.BuildAll()
+		initFunc := mainPkg.Func("init")
+		if initFunc == nil {
+			t.Errorf("test 'package %s': no init function", f.Name.Name)
+			continue
+		}
+
+		var initbuf bytes.Buffer
+		_, err = initFunc.WriteTo(&initbuf)
+		if err != nil {
+			t.Errorf("test 'package %s': WriteTo: %s", f.Name.Name, err)
+			continue
+		}
+
+		if initbuf.String() != test.want {
+			t.Errorf("test 'package %s': got %s, want %s", f.Name.Name, initbuf.String(), test.want)
+		}
+	}
+}
diff --git a/third_party/go.tools/go/ssa/const.go b/third_party/go.tools/go/ssa/const.go
new file mode 100644
index 0000000..cf81e50
--- /dev/null
+++ b/third_party/go.tools/go/ssa/const.go
@@ -0,0 +1,168 @@
+// Copyright 2013 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 ssa
+
+// This file defines the Const SSA value type.
+
+import (
+	"fmt"
+	"go/token"
+	"strconv"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// NewConst returns a new constant of the specified value and type.
+// val must be valid according to the specification of Const.Value.
+//
+func NewConst(val exact.Value, typ types.Type) *Const {
+	return &Const{typ, val}
+}
+
+// intConst returns an 'int' constant that evaluates to i.
+// (i is an int64 in case the host is narrower than the target.)
+func intConst(i int64) *Const {
+	return NewConst(exact.MakeInt64(i), tInt)
+}
+
+// nilConst returns a nil constant of the specified type, which may
+// be any reference type, including interfaces.
+//
+func nilConst(typ types.Type) *Const {
+	return NewConst(nil, typ)
+}
+
+// stringConst returns a 'string' constant that evaluates to s.
+func stringConst(s string) *Const {
+	return NewConst(exact.MakeString(s), tString)
+}
+
+// zeroConst returns a new "zero" constant of the specified type,
+// which must not be an array or struct type: the zero values of
+// aggregates are well-defined but cannot be represented by Const.
+//
+func zeroConst(t types.Type) *Const {
+	switch t := t.(type) {
+	case *types.Basic:
+		switch {
+		case t.Info()&types.IsBoolean != 0:
+			return NewConst(exact.MakeBool(false), t)
+		case t.Info()&types.IsNumeric != 0:
+			return NewConst(exact.MakeInt64(0), t)
+		case t.Info()&types.IsString != 0:
+			return NewConst(exact.MakeString(""), t)
+		case t.Kind() == types.UnsafePointer:
+			fallthrough
+		case t.Kind() == types.UntypedNil:
+			return nilConst(t)
+		default:
+			panic(fmt.Sprint("zeroConst for unexpected type:", t))
+		}
+	case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature:
+		return nilConst(t)
+	case *types.Named:
+		return NewConst(zeroConst(t.Underlying()).Value, t)
+	case *types.Array, *types.Struct, *types.Tuple:
+		panic(fmt.Sprint("zeroConst applied to aggregate:", t))
+	}
+	panic(fmt.Sprint("zeroConst: unexpected ", t))
+}
+
+func (c *Const) RelString(from *types.Package) string {
+	var s string
+	if c.Value == nil {
+		s = "nil"
+	} else if c.Value.Kind() == exact.String {
+		s = exact.StringVal(c.Value)
+		const max = 20
+		// TODO(adonovan): don't cut a rune in half.
+		if len(s) > max {
+			s = s[:max-3] + "..." // abbreviate
+		}
+		s = strconv.Quote(s)
+	} else {
+		s = c.Value.String()
+	}
+	return s + ":" + relType(c.Type(), from)
+}
+
+func (c *Const) Name() string {
+	return c.RelString(nil)
+}
+
+func (c *Const) String() string {
+	return c.Name()
+}
+
+func (c *Const) Type() types.Type {
+	return c.typ
+}
+
+func (c *Const) Referrers() *[]Instruction {
+	return nil
+}
+
+func (c *Const) Parent() *Function { return nil }
+
+func (c *Const) Pos() token.Pos {
+	return token.NoPos
+}
+
+// IsNil returns true if this constant represents a typed or untyped nil value.
+func (c *Const) IsNil() bool {
+	return c.Value == nil
+}
+
+// Int64 returns the numeric value of this constant truncated to fit
+// a signed 64-bit integer.
+//
+func (c *Const) Int64() int64 {
+	switch x := c.Value; x.Kind() {
+	case exact.Int:
+		if i, ok := exact.Int64Val(x); ok {
+			return i
+		}
+		return 0
+	case exact.Float:
+		f, _ := exact.Float64Val(x)
+		return int64(f)
+	}
+	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
+}
+
+// Uint64 returns the numeric value of this constant truncated to fit
+// an unsigned 64-bit integer.
+//
+func (c *Const) Uint64() uint64 {
+	switch x := c.Value; x.Kind() {
+	case exact.Int:
+		if u, ok := exact.Uint64Val(x); ok {
+			return u
+		}
+		return 0
+	case exact.Float:
+		f, _ := exact.Float64Val(x)
+		return uint64(f)
+	}
+	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
+}
+
+// Float64 returns the numeric value of this constant truncated to fit
+// a float64.
+//
+func (c *Const) Float64() float64 {
+	f, _ := exact.Float64Val(c.Value)
+	return f
+}
+
+// Complex128 returns the complex value of this constant truncated to
+// fit a complex128.
+//
+func (c *Const) Complex128() complex128 {
+	re, _ := exact.Float64Val(exact.Real(c.Value))
+	im, _ := exact.Float64Val(exact.Imag(c.Value))
+	return complex(re, im)
+}
diff --git a/third_party/go.tools/go/ssa/create.go b/third_party/go.tools/go/ssa/create.go
new file mode 100644
index 0000000..8356637
--- /dev/null
+++ b/third_party/go.tools/go/ssa/create.go
@@ -0,0 +1,278 @@
+// Copyright 2013 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 ssa
+
+// This file implements the CREATE phase of SSA construction.
+// See builder.go for explanation.
+
+import (
+	"go/ast"
+	"go/token"
+	"os"
+	"sync"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// BuilderMode is a bitmask of options for diagnostics and checking.
+type BuilderMode uint
+
+const (
+	PrintPackages        BuilderMode = 1 << iota // Print package inventory to stdout
+	PrintFunctions                               // Print function SSA code to stdout
+	LogSource                                    // Log source locations as SSA builder progresses
+	SanityCheckFunctions                         // Perform sanity checking of function bodies
+	NaiveForm                                    // Build naïve SSA form: don't replace local loads/stores with registers
+	BuildSerially                                // Build packages serially, not in parallel.
+	GlobalDebug                                  // Enable debug info for all packages
+	BareInits                                    // Build init functions without guards or calls to dependent inits
+)
+
+// Create returns a new SSA Program.  An SSA Package is created for
+// each transitively error-free package of iprog.
+//
+// Code for bodies of functions is not built until Build() is called
+// on the result.
+//
+// mode controls diagnostics and checking during SSA construction.
+//
+func Create(iprog *loader.Program, mode BuilderMode) *Program {
+	prog := &Program{
+		Fset:     iprog.Fset,
+		imported: make(map[string]*Package),
+		packages: make(map[*types.Package]*Package),
+		thunks:   make(map[selectionKey]*Function),
+		bounds:   make(map[*types.Func]*Function),
+		mode:     mode,
+	}
+
+	for _, info := range iprog.AllPackages {
+		// TODO(adonovan): relax this constraint if the
+		// program contains only "soft" errors.
+		if info.TransitivelyErrorFree {
+			prog.CreatePackage(info)
+		}
+	}
+
+	return prog
+}
+
+// memberFromObject populates package pkg with a member for the
+// typechecker object obj.
+//
+// For objects from Go source code, syntax is the associated syntax
+// tree (for funcs and vars only); it will be used during the build
+// phase.
+//
+func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node) {
+	name := obj.Name()
+	switch obj := obj.(type) {
+	case *types.TypeName:
+		pkg.Members[name] = &Type{
+			object: obj,
+			pkg:    pkg,
+		}
+
+	case *types.Const:
+		c := &NamedConst{
+			object: obj,
+			Value:  NewConst(obj.Val(), obj.Type()),
+			pkg:    pkg,
+		}
+		pkg.values[obj] = c.Value
+		pkg.Members[name] = c
+
+	case *types.Var:
+		g := &Global{
+			Pkg:    pkg,
+			name:   name,
+			object: obj,
+			typ:    types.NewPointer(obj.Type()), // address
+			pos:    obj.Pos(),
+		}
+		pkg.values[obj] = g
+		pkg.Members[name] = g
+
+	case *types.Func:
+		fn := &Function{
+			name:      name,
+			object:    obj,
+			Signature: obj.Type().(*types.Signature),
+			syntax:    syntax,
+			pos:       obj.Pos(),
+			Pkg:       pkg,
+			Prog:      pkg.Prog,
+		}
+		if syntax == nil {
+			fn.Synthetic = "loaded from gc object file"
+		}
+
+		pkg.values[obj] = fn
+		if fn.Signature.Recv() == nil {
+			pkg.Members[name] = fn // package-level function
+		}
+
+	default: // (incl. *types.Package)
+		panic("unexpected Object type: " + obj.String())
+	}
+}
+
+// membersFromDecl populates package pkg with members for each
+// typechecker object (var, func, const or type) associated with the
+// specified decl.
+//
+func membersFromDecl(pkg *Package, decl ast.Decl) {
+	switch decl := decl.(type) {
+	case *ast.GenDecl: // import, const, type or var
+		switch decl.Tok {
+		case token.CONST:
+			for _, spec := range decl.Specs {
+				for _, id := range spec.(*ast.ValueSpec).Names {
+					if !isBlankIdent(id) {
+						memberFromObject(pkg, pkg.info.Defs[id], nil)
+					}
+				}
+			}
+
+		case token.VAR:
+			for _, spec := range decl.Specs {
+				for _, id := range spec.(*ast.ValueSpec).Names {
+					if !isBlankIdent(id) {
+						memberFromObject(pkg, pkg.info.Defs[id], spec)
+					}
+				}
+			}
+
+		case token.TYPE:
+			for _, spec := range decl.Specs {
+				id := spec.(*ast.TypeSpec).Name
+				if !isBlankIdent(id) {
+					memberFromObject(pkg, pkg.info.Defs[id], nil)
+				}
+			}
+		}
+
+	case *ast.FuncDecl:
+		id := decl.Name
+		if decl.Recv == nil && id.Name == "init" {
+			return // no object
+		}
+		if !isBlankIdent(id) {
+			memberFromObject(pkg, pkg.info.Defs[id], decl)
+		}
+	}
+}
+
+// CreatePackage constructs and returns an SSA Package from an
+// error-free package described by info, and populates its Members
+// mapping.
+//
+// Repeated calls with the same info return the same Package.
+//
+// The real work of building SSA form for each function is not done
+// until a subsequent call to Package.Build().
+//
+func (prog *Program) CreatePackage(info *loader.PackageInfo) *Package {
+	if p := prog.packages[info.Pkg]; p != nil {
+		return p // already loaded
+	}
+
+	p := &Package{
+		Prog:    prog,
+		Members: make(map[string]Member),
+		values:  make(map[types.Object]Value),
+		Object:  info.Pkg,
+		info:    info, // transient (CREATE and BUILD phases)
+	}
+
+	// Add init() function.
+	p.init = &Function{
+		name:      "init",
+		Signature: new(types.Signature),
+		Synthetic: "package initializer",
+		Pkg:       p,
+		Prog:      prog,
+	}
+	p.Members[p.init.name] = p.init
+
+	// CREATE phase.
+	// Allocate all package members: vars, funcs, consts and types.
+	if len(info.Files) > 0 {
+		// Go source package.
+		for _, file := range info.Files {
+			for _, decl := range file.Decls {
+				membersFromDecl(p, decl)
+			}
+		}
+	} else {
+		// GC-compiled binary package.
+		// No code.
+		// No position information.
+		scope := p.Object.Scope()
+		for _, name := range scope.Names() {
+			obj := scope.Lookup(name)
+			memberFromObject(p, obj, nil)
+			if obj, ok := obj.(*types.TypeName); ok {
+				named := obj.Type().(*types.Named)
+				for i, n := 0, named.NumMethods(); i < n; i++ {
+					memberFromObject(p, named.Method(i), nil)
+				}
+			}
+		}
+	}
+
+	if prog.mode&BareInits == 0 {
+		// Add initializer guard variable.
+		initguard := &Global{
+			Pkg:  p,
+			name: "init$guard",
+			typ:  types.NewPointer(tBool),
+		}
+		p.Members[initguard.Name()] = initguard
+	}
+
+	if prog.mode&GlobalDebug != 0 {
+		p.SetDebugMode(true)
+	}
+
+	if prog.mode&PrintPackages != 0 {
+		printMu.Lock()
+		p.WriteTo(os.Stdout)
+		printMu.Unlock()
+	}
+
+	if info.Importable {
+		prog.imported[info.Pkg.Path()] = p
+	}
+	prog.packages[p.Object] = p
+
+	return p
+}
+
+// printMu serializes printing of Packages/Functions to stdout
+var printMu sync.Mutex
+
+// AllPackages returns a new slice containing all packages in the
+// program prog in unspecified order.
+//
+func (prog *Program) AllPackages() []*Package {
+	pkgs := make([]*Package, 0, len(prog.packages))
+	for _, pkg := range prog.packages {
+		pkgs = append(pkgs, pkg)
+	}
+	return pkgs
+}
+
+// ImportedPackage returns the importable SSA Package whose import
+// path is path, or nil if no such SSA package has been created.
+//
+// Not all packages are importable.  For example, no import
+// declaration can resolve to the x_test package created by 'go test'
+// or the ad-hoc main package created 'go build foo.go'.
+//
+func (prog *Program) ImportedPackage(path string) *Package {
+	return prog.imported[path]
+}
diff --git a/third_party/go.tools/go/ssa/doc.go b/third_party/go.tools/go/ssa/doc.go
new file mode 100644
index 0000000..0b5c33d
--- /dev/null
+++ b/third_party/go.tools/go/ssa/doc.go
@@ -0,0 +1,123 @@
+// Copyright 2013 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 ssa defines a representation of the elements of Go programs
+// (packages, types, functions, variables and constants) using a
+// static single-assignment (SSA) form intermediate representation
+// (IR) for the bodies of functions.
+//
+// THIS INTERFACE IS EXPERIMENTAL AND IS LIKELY TO CHANGE.
+//
+// For an introduction to SSA form, see
+// http://en.wikipedia.org/wiki/Static_single_assignment_form.
+// This page provides a broader reading list:
+// http://www.dcs.gla.ac.uk/~jsinger/ssa.html.
+//
+// The level of abstraction of the SSA form is intentionally close to
+// the source language to facilitate construction of source analysis
+// tools.  It is not intended for machine code generation.
+//
+// All looping, branching and switching constructs are replaced with
+// unstructured control flow.  Higher-level control flow constructs
+// such as multi-way branch can be reconstructed as needed; see
+// ssautil.Switches() for an example.
+//
+// To construct an SSA-form program, call ssa.Create on a
+// loader.Program, a set of type-checked packages created from
+// parsed Go source files.  The resulting ssa.Program contains all the
+// packages and their members, but SSA code is not created for
+// function bodies until a subsequent call to (*Package).Build.
+//
+// The builder initially builds a naive SSA form in which all local
+// variables are addresses of stack locations with explicit loads and
+// stores.  Registerisation of eligible locals and φ-node insertion
+// using dominance and dataflow are then performed as a second pass
+// called "lifting" to improve the accuracy and performance of
+// subsequent analyses; this pass can be skipped by setting the
+// NaiveForm builder flag.
+//
+// The primary interfaces of this package are:
+//
+//    - Member: a named member of a Go package.
+//    - Value: an expression that yields a value.
+//    - Instruction: a statement that consumes values and performs computation.
+//    - Node: a Value or Instruction (emphasizing its membership in the SSA value graph)
+//
+// A computation that yields a result implements both the Value and
+// Instruction interfaces.  The following table shows for each
+// concrete type which of these interfaces it implements.
+//
+//                      Value?          Instruction?    Member?
+//   *Alloc             ✔               ✔
+//   *BinOp             ✔               ✔
+//   *Builtin           ✔
+//   *Call              ✔               ✔
+//   *ChangeInterface   ✔               ✔
+//   *ChangeType        ✔               ✔
+//   *Const             ✔
+//   *Convert           ✔               ✔
+//   *DebugRef                          ✔
+//   *Defer                             ✔
+//   *Extract           ✔               ✔
+//   *Field             ✔               ✔
+//   *FieldAddr         ✔               ✔
+//   *FreeVar           ✔
+//   *Function          ✔                               ✔ (func)
+//   *Global            ✔                               ✔ (var)
+//   *Go                                ✔
+//   *If                                ✔
+//   *Index             ✔               ✔
+//   *IndexAddr         ✔               ✔
+//   *Jump                              ✔
+//   *Lookup            ✔               ✔
+//   *MakeChan          ✔               ✔
+//   *MakeClosure       ✔               ✔
+//   *MakeInterface     ✔               ✔
+//   *MakeMap           ✔               ✔
+//   *MakeSlice         ✔               ✔
+//   *MapUpdate                         ✔
+//   *NamedConst                                        ✔ (const)
+//   *Next              ✔               ✔
+//   *Panic                             ✔
+//   *Parameter         ✔
+//   *Phi               ✔               ✔
+//   *Range             ✔               ✔
+//   *Return                            ✔
+//   *RunDefers                         ✔
+//   *Select            ✔               ✔
+//   *Send                              ✔
+//   *Slice             ✔               ✔
+//   *Store                             ✔
+//   *Type                                              ✔ (type)
+//   *TypeAssert        ✔               ✔
+//   *UnOp              ✔               ✔
+//
+// Other key types in this package include: Program, Package, Function
+// and BasicBlock.
+//
+// The program representation constructed by this package is fully
+// resolved internally, i.e. it does not rely on the names of Values,
+// Packages, Functions, Types or BasicBlocks for the correct
+// interpretation of the program.  Only the identities of objects and
+// the topology of the SSA and type graphs are semantically
+// significant.  (There is one exception: Ids, used to identify field
+// and method names, contain strings.)  Avoidance of name-based
+// operations simplifies the implementation of subsequent passes and
+// can make them very efficient.  Many objects are nonetheless named
+// to aid in debugging, but it is not essential that the names be
+// either accurate or unambiguous.  The public API exposes a number of
+// name-based maps for client convenience.
+//
+// The ssa/ssautil package provides various utilities that depend only
+// on the public API of this package.
+//
+// TODO(adonovan): Consider the exceptional control-flow implications
+// of defer and recover().
+//
+// TODO(adonovan): write a how-to document for all the various cases
+// of trying to determine corresponding elements across the four
+// domains of source locations, ast.Nodes, types.Objects,
+// ssa.Values/Instructions.
+//
+package ssa
diff --git a/third_party/go.tools/go/ssa/dom.go b/third_party/go.tools/go/ssa/dom.go
new file mode 100644
index 0000000..12ef430
--- /dev/null
+++ b/third_party/go.tools/go/ssa/dom.go
@@ -0,0 +1,341 @@
+// Copyright 2013 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 ssa
+
+// This file defines algorithms related to dominance.
+
+// Dominator tree construction ----------------------------------------
+//
+// We use the algorithm described in Lengauer & Tarjan. 1979.  A fast
+// algorithm for finding dominators in a flowgraph.
+// http://doi.acm.org/10.1145/357062.357071
+//
+// We also apply the optimizations to SLT described in Georgiadis et
+// al, Finding Dominators in Practice, JGAA 2006,
+// http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf
+// to avoid the need for buckets of size > 1.
+
+import (
+	"bytes"
+	"fmt"
+	"math/big"
+	"os"
+	"sort"
+)
+
+// Idom returns the block that immediately dominates b:
+// its parent in the dominator tree, if any.
+// Neither the entry node (b.Index==0) nor recover node
+// (b==b.Parent().Recover()) have a parent.
+//
+func (b *BasicBlock) Idom() *BasicBlock { return b.dom.idom }
+
+// Dominees returns the list of blocks that b immediately dominates:
+// its children in the dominator tree.
+//
+func (b *BasicBlock) Dominees() []*BasicBlock { return b.dom.children }
+
+// Dominates reports whether b dominates c.
+func (b *BasicBlock) Dominates(c *BasicBlock) bool {
+	return b.dom.pre <= c.dom.pre && c.dom.post <= b.dom.post
+}
+
+type byDomPreorder []*BasicBlock
+
+func (a byDomPreorder) Len() int           { return len(a) }
+func (a byDomPreorder) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a byDomPreorder) Less(i, j int) bool { return a[i].dom.pre < a[j].dom.pre }
+
+// DomPreorder returns a new slice containing the blocks of f in
+// dominator tree preorder.
+//
+func (f *Function) DomPreorder() []*BasicBlock {
+	n := len(f.Blocks)
+	order := make(byDomPreorder, n, n)
+	copy(order, f.Blocks)
+	sort.Sort(order)
+	return order
+}
+
+// domInfo contains a BasicBlock's dominance information.
+type domInfo struct {
+	idom      *BasicBlock   // immediate dominator (parent in domtree)
+	children  []*BasicBlock // nodes immediately dominated by this one
+	pre, post int32         // pre- and post-order numbering within domtree
+}
+
+// ltState holds the working state for Lengauer-Tarjan algorithm
+// (during which domInfo.pre is repurposed for CFG DFS preorder number).
+type ltState struct {
+	// Each slice is indexed by b.Index.
+	sdom     []*BasicBlock // b's semidominator
+	parent   []*BasicBlock // b's parent in DFS traversal of CFG
+	ancestor []*BasicBlock // b's ancestor with least sdom
+}
+
+// dfs implements the depth-first search part of the LT algorithm.
+func (lt *ltState) dfs(v *BasicBlock, i int32, preorder []*BasicBlock) int32 {
+	preorder[i] = v
+	v.dom.pre = i // For now: DFS preorder of spanning tree of CFG
+	i++
+	lt.sdom[v.Index] = v
+	lt.link(nil, v)
+	for _, w := range v.Succs {
+		if lt.sdom[w.Index] == nil {
+			lt.parent[w.Index] = v
+			i = lt.dfs(w, i, preorder)
+		}
+	}
+	return i
+}
+
+// eval implements the EVAL part of the LT algorithm.
+func (lt *ltState) eval(v *BasicBlock) *BasicBlock {
+	// TODO(adonovan): opt: do path compression per simple LT.
+	u := v
+	for ; lt.ancestor[v.Index] != nil; v = lt.ancestor[v.Index] {
+		if lt.sdom[v.Index].dom.pre < lt.sdom[u.Index].dom.pre {
+			u = v
+		}
+	}
+	return u
+}
+
+// link implements the LINK part of the LT algorithm.
+func (lt *ltState) link(v, w *BasicBlock) {
+	lt.ancestor[w.Index] = v
+}
+
+// buildDomTree computes the dominator tree of f using the LT algorithm.
+// Precondition: all blocks are reachable (e.g. optimizeBlocks has been run).
+//
+func buildDomTree(f *Function) {
+	// The step numbers refer to the original LT paper; the
+	// reordering is due to Georgiadis.
+
+	// Clear any previous domInfo.
+	for _, b := range f.Blocks {
+		b.dom = domInfo{}
+	}
+
+	n := len(f.Blocks)
+	// Allocate space for 5 contiguous [n]*BasicBlock arrays:
+	// sdom, parent, ancestor, preorder, buckets.
+	space := make([]*BasicBlock, 5*n, 5*n)
+	lt := ltState{
+		sdom:     space[0:n],
+		parent:   space[n : 2*n],
+		ancestor: space[2*n : 3*n],
+	}
+
+	// Step 1.  Number vertices by depth-first preorder.
+	preorder := space[3*n : 4*n]
+	root := f.Blocks[0]
+	prenum := lt.dfs(root, 0, preorder)
+	recover := f.Recover
+	if recover != nil {
+		lt.dfs(recover, prenum, preorder)
+	}
+
+	buckets := space[4*n : 5*n]
+	copy(buckets, preorder)
+
+	// In reverse preorder...
+	for i := int32(n) - 1; i > 0; i-- {
+		w := preorder[i]
+
+		// Step 3. Implicitly define the immediate dominator of each node.
+		for v := buckets[i]; v != w; v = buckets[v.dom.pre] {
+			u := lt.eval(v)
+			if lt.sdom[u.Index].dom.pre < i {
+				v.dom.idom = u
+			} else {
+				v.dom.idom = w
+			}
+		}
+
+		// Step 2. Compute the semidominators of all nodes.
+		lt.sdom[w.Index] = lt.parent[w.Index]
+		for _, v := range w.Preds {
+			u := lt.eval(v)
+			if lt.sdom[u.Index].dom.pre < lt.sdom[w.Index].dom.pre {
+				lt.sdom[w.Index] = lt.sdom[u.Index]
+			}
+		}
+
+		lt.link(lt.parent[w.Index], w)
+
+		if lt.parent[w.Index] == lt.sdom[w.Index] {
+			w.dom.idom = lt.parent[w.Index]
+		} else {
+			buckets[i] = buckets[lt.sdom[w.Index].dom.pre]
+			buckets[lt.sdom[w.Index].dom.pre] = w
+		}
+	}
+
+	// The final 'Step 3' is now outside the loop.
+	for v := buckets[0]; v != root; v = buckets[v.dom.pre] {
+		v.dom.idom = root
+	}
+
+	// Step 4. Explicitly define the immediate dominator of each
+	// node, in preorder.
+	for _, w := range preorder[1:] {
+		if w == root || w == recover {
+			w.dom.idom = nil
+		} else {
+			if w.dom.idom != lt.sdom[w.Index] {
+				w.dom.idom = w.dom.idom.dom.idom
+			}
+			// Calculate Children relation as inverse of Idom.
+			w.dom.idom.dom.children = append(w.dom.idom.dom.children, w)
+		}
+	}
+
+	pre, post := numberDomTree(root, 0, 0)
+	if recover != nil {
+		numberDomTree(recover, pre, post)
+	}
+
+	// printDomTreeDot(os.Stderr, f)        // debugging
+	// printDomTreeText(os.Stderr, root, 0) // debugging
+
+	if f.Prog.mode&SanityCheckFunctions != 0 {
+		sanityCheckDomTree(f)
+	}
+}
+
+// numberDomTree sets the pre- and post-order numbers of a depth-first
+// traversal of the dominator tree rooted at v.  These are used to
+// answer dominance queries in constant time.
+//
+func numberDomTree(v *BasicBlock, pre, post int32) (int32, int32) {
+	v.dom.pre = pre
+	pre++
+	for _, child := range v.dom.children {
+		pre, post = numberDomTree(child, pre, post)
+	}
+	v.dom.post = post
+	post++
+	return pre, post
+}
+
+// Testing utilities ----------------------------------------
+
+// sanityCheckDomTree checks the correctness of the dominator tree
+// computed by the LT algorithm by comparing against the dominance
+// relation computed by a naive Kildall-style forward dataflow
+// analysis (Algorithm 10.16 from the "Dragon" book).
+//
+func sanityCheckDomTree(f *Function) {
+	n := len(f.Blocks)
+
+	// D[i] is the set of blocks that dominate f.Blocks[i],
+	// represented as a bit-set of block indices.
+	D := make([]big.Int, n)
+
+	one := big.NewInt(1)
+
+	// all is the set of all blocks; constant.
+	var all big.Int
+	all.Set(one).Lsh(&all, uint(n)).Sub(&all, one)
+
+	// Initialization.
+	for i, b := range f.Blocks {
+		if i == 0 || b == f.Recover {
+			// A root is dominated only by itself.
+			D[i].SetBit(&D[0], 0, 1)
+		} else {
+			// All other blocks are (initially) dominated
+			// by every block.
+			D[i].Set(&all)
+		}
+	}
+
+	// Iteration until fixed point.
+	for changed := true; changed; {
+		changed = false
+		for i, b := range f.Blocks {
+			if i == 0 || b == f.Recover {
+				continue
+			}
+			// Compute intersection across predecessors.
+			var x big.Int
+			x.Set(&all)
+			for _, pred := range b.Preds {
+				x.And(&x, &D[pred.Index])
+			}
+			x.SetBit(&x, i, 1) // a block always dominates itself.
+			if D[i].Cmp(&x) != 0 {
+				D[i].Set(&x)
+				changed = true
+			}
+		}
+	}
+
+	// Check the entire relation.  O(n^2).
+	// The Recover block (if any) must be treated specially so we skip it.
+	ok := true
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			b, c := f.Blocks[i], f.Blocks[j]
+			if c == f.Recover {
+				continue
+			}
+			actual := b.Dominates(c)
+			expected := D[j].Bit(i) == 1
+			if actual != expected {
+				fmt.Fprintf(os.Stderr, "dominates(%s, %s)==%t, want %t\n", b, c, actual, expected)
+				ok = false
+			}
+		}
+	}
+
+	preorder := f.DomPreorder()
+	for _, b := range f.Blocks {
+		if got := preorder[b.dom.pre]; got != b {
+			fmt.Fprintf(os.Stderr, "preorder[%d]==%s, want %s\n", b.dom.pre, got, b)
+			ok = false
+		}
+	}
+
+	if !ok {
+		panic("sanityCheckDomTree failed for " + f.String())
+	}
+
+}
+
+// Printing functions ----------------------------------------
+
+// printDomTree prints the dominator tree as text, using indentation.
+func printDomTreeText(buf *bytes.Buffer, v *BasicBlock, indent int) {
+	fmt.Fprintf(buf, "%*s%s\n", 4*indent, "", v)
+	for _, child := range v.dom.children {
+		printDomTreeText(buf, child, indent+1)
+	}
+}
+
+// printDomTreeDot prints the dominator tree of f in AT&T GraphViz
+// (.dot) format.
+func printDomTreeDot(buf *bytes.Buffer, f *Function) {
+	fmt.Fprintln(buf, "//", f)
+	fmt.Fprintln(buf, "digraph domtree {")
+	for i, b := range f.Blocks {
+		v := b.dom
+		fmt.Fprintf(buf, "\tn%d [label=\"%s (%d, %d)\",shape=\"rectangle\"];\n", v.pre, b, v.pre, v.post)
+		// TODO(adonovan): improve appearance of edges
+		// belonging to both dominator tree and CFG.
+
+		// Dominator tree edge.
+		if i != 0 {
+			fmt.Fprintf(buf, "\tn%d -> n%d [style=\"solid\",weight=100];\n", v.idom.dom.pre, v.pre)
+		}
+		// CFG edges.
+		for _, pred := range b.Preds {
+			fmt.Fprintf(buf, "\tn%d -> n%d [style=\"dotted\",weight=0];\n", pred.dom.pre, v.pre)
+		}
+	}
+	fmt.Fprintln(buf, "}")
+}
diff --git a/third_party/go.tools/go/ssa/emit.go b/third_party/go.tools/go/ssa/emit.go
new file mode 100644
index 0000000..4cc32ea
--- /dev/null
+++ b/third_party/go.tools/go/ssa/emit.go
@@ -0,0 +1,474 @@
+// Copyright 2013 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 ssa
+
+// Helpers for emitting SSA instructions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// emitNew emits to f a new (heap Alloc) instruction allocating an
+// object of type typ.  pos is the optional source location.
+//
+func emitNew(f *Function, typ types.Type, pos token.Pos) *Alloc {
+	v := &Alloc{Heap: true}
+	v.setType(types.NewPointer(typ))
+	v.setPos(pos)
+	f.emit(v)
+	return v
+}
+
+// emitLoad emits to f an instruction to load the address addr into a
+// new temporary, and returns the value so defined.
+//
+func emitLoad(f *Function, addr Value) *UnOp {
+	v := &UnOp{Op: token.MUL, X: addr}
+	v.setType(deref(addr.Type()))
+	f.emit(v)
+	return v
+}
+
+// emitDebugRef emits to f a DebugRef pseudo-instruction associating
+// expression e with value v.
+//
+func emitDebugRef(f *Function, e ast.Expr, v Value, isAddr bool) {
+	if !f.debugInfo() {
+		return // debugging not enabled
+	}
+	if v == nil || e == nil {
+		panic("nil")
+	}
+	var obj types.Object
+	e = unparen(e)
+	if id, ok := e.(*ast.Ident); ok {
+		if isBlankIdent(id) {
+			return
+		}
+		obj = f.Pkg.objectOf(id)
+		switch obj.(type) {
+		case *types.Nil, *types.Const, *types.Builtin:
+			return
+		}
+	}
+	f.emit(&DebugRef{
+		X:      v,
+		Expr:   e,
+		IsAddr: isAddr,
+		object: obj,
+	})
+}
+
+// emitArith emits to f code to compute the binary operation op(x, y)
+// where op is an eager shift, logical or arithmetic operation.
+// (Use emitCompare() for comparisons and Builder.logicalBinop() for
+// non-eager operations.)
+//
+func emitArith(f *Function, op token.Token, x, y Value, t types.Type, pos token.Pos) Value {
+	switch op {
+	case token.SHL, token.SHR:
+		x = emitConv(f, x, t)
+		// y may be signed or an 'untyped' constant.
+		// TODO(adonovan): whence signed values?
+		if b, ok := y.Type().Underlying().(*types.Basic); ok && b.Info()&types.IsUnsigned == 0 {
+			y = emitConv(f, y, types.Typ[types.Uint64])
+		}
+
+	case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
+		x = emitConv(f, x, t)
+		y = emitConv(f, y, t)
+
+	default:
+		panic("illegal op in emitArith: " + op.String())
+
+	}
+	v := &BinOp{
+		Op: op,
+		X:  x,
+		Y:  y,
+	}
+	v.setPos(pos)
+	v.setType(t)
+	return f.emit(v)
+}
+
+// emitCompare emits to f code compute the boolean result of
+// comparison comparison 'x op y'.
+//
+func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value {
+	xt := x.Type().Underlying()
+	yt := y.Type().Underlying()
+
+	// Special case to optimise a tagless SwitchStmt so that
+	// these are equivalent
+	//   switch { case e: ...}
+	//   switch true { case e: ... }
+	//   if e==true { ... }
+	// even in the case when e's type is an interface.
+	// TODO(adonovan): opt: generalise to x==true, false!=y, etc.
+	if x == vTrue && op == token.EQL {
+		if yt, ok := yt.(*types.Basic); ok && yt.Info()&types.IsBoolean != 0 {
+			return y
+		}
+	}
+
+	if types.Identical(xt, yt) {
+		// no conversion necessary
+	} else if _, ok := xt.(*types.Interface); ok {
+		y = emitConv(f, y, x.Type())
+	} else if _, ok := yt.(*types.Interface); ok {
+		x = emitConv(f, x, y.Type())
+	} else if _, ok := x.(*Const); ok {
+		x = emitConv(f, x, y.Type())
+	} else if _, ok := y.(*Const); ok {
+		y = emitConv(f, y, x.Type())
+	} else {
+		// other cases, e.g. channels.  No-op.
+	}
+
+	v := &BinOp{
+		Op: op,
+		X:  x,
+		Y:  y,
+	}
+	v.setPos(pos)
+	v.setType(tBool)
+	return f.emit(v)
+}
+
+// isValuePreserving returns true if a conversion from ut_src to
+// ut_dst is value-preserving, i.e. just a change of type.
+// Precondition: neither argument is a named type.
+//
+func isValuePreserving(ut_src, ut_dst types.Type) bool {
+	// Identical underlying types?
+	if types.Identical(ut_dst, ut_src) {
+		return true
+	}
+
+	switch ut_dst.(type) {
+	case *types.Chan:
+		// Conversion between channel types?
+		_, ok := ut_src.(*types.Chan)
+		return ok
+
+	case *types.Pointer:
+		// Conversion between pointers with identical base types?
+		_, ok := ut_src.(*types.Pointer)
+		return ok
+	}
+	return false
+}
+
+// emitConv emits to f code to convert Value val to exactly type typ,
+// and returns the converted value.  Implicit conversions are required
+// by language assignability rules in assignments, parameter passing,
+// etc.  Conversions cannot fail dynamically.
+//
+func emitConv(f *Function, val Value, typ types.Type) Value {
+	t_src := val.Type()
+
+	// Identical types?  Conversion is a no-op.
+	if types.Identical(t_src, typ) {
+		return val
+	}
+
+	ut_dst := typ.Underlying()
+	ut_src := t_src.Underlying()
+
+	// Just a change of type, but not value or representation?
+	if isValuePreserving(ut_src, ut_dst) {
+		c := &ChangeType{X: val}
+		c.setType(typ)
+		return f.emit(c)
+	}
+
+	// Conversion to, or construction of a value of, an interface type?
+	if _, ok := ut_dst.(*types.Interface); ok {
+		// Assignment from one interface type to another?
+		if _, ok := ut_src.(*types.Interface); ok {
+			c := &ChangeInterface{X: val}
+			c.setType(typ)
+			return f.emit(c)
+		}
+
+		// Untyped nil constant?  Return interface-typed nil constant.
+		if ut_src == tUntypedNil {
+			return nilConst(typ)
+		}
+
+		// Convert (non-nil) "untyped" literals to their default type.
+		if t, ok := ut_src.(*types.Basic); ok && t.Info()&types.IsUntyped != 0 {
+			val = emitConv(f, val, DefaultType(ut_src))
+		}
+
+		f.Pkg.needMethodsOf(val.Type())
+		mi := &MakeInterface{X: val}
+		mi.setType(typ)
+		return f.emit(mi)
+	}
+
+	// Conversion of a compile-time constant value?
+	if c, ok := val.(*Const); ok {
+		if _, ok := ut_dst.(*types.Basic); ok || c.IsNil() {
+			// Conversion of a compile-time constant to
+			// another constant type results in a new
+			// constant of the destination type and
+			// (initially) the same abstract value.
+			// We don't truncate the value yet.
+			return NewConst(c.Value, typ)
+		}
+
+		// We're converting from constant to non-constant type,
+		// e.g. string -> []byte/[]rune.
+	}
+
+	// A representation-changing conversion?
+	// At least one of {ut_src,ut_dst} must be *Basic.
+	// (The other may be []byte or []rune.)
+	_, ok1 := ut_src.(*types.Basic)
+	_, ok2 := ut_dst.(*types.Basic)
+	if ok1 || ok2 {
+		c := &Convert{X: val}
+		c.setType(typ)
+		return f.emit(c)
+	}
+
+	panic(fmt.Sprintf("in %s: cannot convert %s (%s) to %s", f, val, val.Type(), typ))
+}
+
+// emitStore emits to f an instruction to store value val at location
+// addr, applying implicit conversions as required by assignability rules.
+//
+func emitStore(f *Function, addr, val Value) *Store {
+	s := &Store{
+		Addr: addr,
+		Val:  emitConv(f, val, deref(addr.Type())),
+	}
+	f.emit(s)
+	return s
+}
+
+// emitJump emits to f a jump to target, and updates the control-flow graph.
+// Postcondition: f.currentBlock is nil.
+//
+func emitJump(f *Function, target *BasicBlock) {
+	b := f.currentBlock
+	b.emit(new(Jump))
+	addEdge(b, target)
+	f.currentBlock = nil
+}
+
+// emitIf emits to f a conditional jump to tblock or fblock based on
+// cond, and updates the control-flow graph.
+// Postcondition: f.currentBlock is nil.
+//
+func emitIf(f *Function, cond Value, tblock, fblock *BasicBlock) {
+	b := f.currentBlock
+	b.emit(&If{Cond: cond})
+	addEdge(b, tblock)
+	addEdge(b, fblock)
+	f.currentBlock = nil
+}
+
+// emitExtract emits to f an instruction to extract the index'th
+// component of tuple.  It returns the extracted value.
+//
+func emitExtract(f *Function, tuple Value, index int) Value {
+	e := &Extract{Tuple: tuple, Index: index}
+	e.setType(tuple.Type().(*types.Tuple).At(index).Type())
+	return f.emit(e)
+}
+
+// emitTypeAssert emits to f a type assertion value := x.(t) and
+// returns the value.  x.Type() must be an interface.
+//
+func emitTypeAssert(f *Function, x Value, t types.Type, pos token.Pos) Value {
+	a := &TypeAssert{X: x, AssertedType: t}
+	a.setPos(pos)
+	a.setType(t)
+	return f.emit(a)
+}
+
+// emitTypeTest emits to f a type test value,ok := x.(t) and returns
+// a (value, ok) tuple.  x.Type() must be an interface.
+//
+func emitTypeTest(f *Function, x Value, t types.Type, pos token.Pos) Value {
+	a := &TypeAssert{
+		X:            x,
+		AssertedType: t,
+		CommaOk:      true,
+	}
+	a.setPos(pos)
+	a.setType(types.NewTuple(
+		newVar("value", t),
+		varOk,
+	))
+	return f.emit(a)
+}
+
+// emitTailCall emits to f a function call in tail position.  The
+// caller is responsible for all fields of 'call' except its type.
+// Intended for wrapper methods.
+// Precondition: f does/will not use deferred procedure calls.
+// Postcondition: f.currentBlock is nil.
+//
+func emitTailCall(f *Function, call *Call) {
+	tresults := f.Signature.Results()
+	nr := tresults.Len()
+	if nr == 1 {
+		call.typ = tresults.At(0).Type()
+	} else {
+		call.typ = tresults
+	}
+	tuple := f.emit(call)
+	var ret Return
+	switch nr {
+	case 0:
+		// no-op
+	case 1:
+		ret.Results = []Value{tuple}
+	default:
+		for i := 0; i < nr; i++ {
+			v := emitExtract(f, tuple, i)
+			// TODO(adonovan): in principle, this is required:
+			//   v = emitConv(f, o.Type, f.Signature.Results[i].Type)
+			// but in practice emitTailCall is only used when
+			// the types exactly match.
+			ret.Results = append(ret.Results, v)
+		}
+	}
+	f.emit(&ret)
+	f.currentBlock = nil
+}
+
+// emitImplicitSelections emits to f code to apply the sequence of
+// implicit field selections specified by indices to base value v, and
+// returns the selected value.
+//
+// If v is the address of a struct, the result will be the address of
+// a field; if it is the value of a struct, the result will be the
+// value of a field.
+//
+func emitImplicitSelections(f *Function, v Value, indices []int) Value {
+	for _, index := range indices {
+		fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
+
+		if isPointer(v.Type()) {
+			instr := &FieldAddr{
+				X:     v,
+				Field: index,
+			}
+			instr.setType(types.NewPointer(fld.Type()))
+			v = f.emit(instr)
+			// Load the field's value iff indirectly embedded.
+			if isPointer(fld.Type()) {
+				v = emitLoad(f, v)
+			}
+		} else {
+			instr := &Field{
+				X:     v,
+				Field: index,
+			}
+			instr.setType(fld.Type())
+			v = f.emit(instr)
+		}
+	}
+	return v
+}
+
+// emitFieldSelection emits to f code to select the index'th field of v.
+//
+// If wantAddr, the input must be a pointer-to-struct and the result
+// will be the field's address; otherwise the result will be the
+// field's value.
+// Ident id is used for position and debug info.
+//
+func emitFieldSelection(f *Function, v Value, index int, wantAddr bool, id *ast.Ident) Value {
+	fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
+	if isPointer(v.Type()) {
+		instr := &FieldAddr{
+			X:     v,
+			Field: index,
+		}
+		instr.setPos(id.Pos())
+		instr.setType(types.NewPointer(fld.Type()))
+		v = f.emit(instr)
+		// Load the field's value iff we don't want its address.
+		if !wantAddr {
+			v = emitLoad(f, v)
+		}
+	} else {
+		instr := &Field{
+			X:     v,
+			Field: index,
+		}
+		instr.setPos(id.Pos())
+		instr.setType(fld.Type())
+		v = f.emit(instr)
+	}
+	emitDebugRef(f, id, v, wantAddr)
+	return v
+}
+
+// zeroValue emits to f code to produce a zero value of type t,
+// and returns it.
+//
+func zeroValue(f *Function, t types.Type) Value {
+	switch t.Underlying().(type) {
+	case *types.Struct, *types.Array:
+		return emitLoad(f, f.addLocal(t, token.NoPos))
+	default:
+		return zeroConst(t)
+	}
+}
+
+// emitMemClear emits to f code to zero the value pointed to by ptr.
+func emitMemClear(f *Function, ptr Value) {
+	// TODO(adonovan): define and use a 'memclr' intrinsic for aggregate types.
+	emitStore(f, ptr, zeroValue(f, deref(ptr.Type())))
+}
+
+// createRecoverBlock emits to f a block of code to return after a
+// recovered panic, and sets f.Recover to it.
+//
+// If f's result parameters are named, the code loads and returns
+// their current values, otherwise it returns the zero values of their
+// type.
+//
+// Idempotent.
+//
+func createRecoverBlock(f *Function) {
+	if f.Recover != nil {
+		return // already created
+	}
+	saved := f.currentBlock
+
+	f.Recover = f.newBasicBlock("recover")
+	f.currentBlock = f.Recover
+
+	var results []Value
+	if f.namedResults != nil {
+		// Reload NRPs to form value tuple.
+		for _, r := range f.namedResults {
+			results = append(results, emitLoad(f, r))
+		}
+	} else {
+		R := f.Signature.Results()
+		for i, n := 0, R.Len(); i < n; i++ {
+			T := R.At(i).Type()
+
+			// Return zero value of each result type.
+			results = append(results, zeroValue(f, T))
+		}
+	}
+	f.emit(&Return{Results: results})
+
+	f.currentBlock = saved
+}
diff --git a/third_party/go.tools/go/ssa/example_test.go b/third_party/go.tools/go/ssa/example_test.go
new file mode 100644
index 0000000..85eb3af
--- /dev/null
+++ b/third_party/go.tools/go/ssa/example_test.go
@@ -0,0 +1,110 @@
+// Copyright 2013 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 ssa_test
+
+import (
+	"fmt"
+	"os"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+)
+
+// This program demonstrates how to run the SSA builder on a "Hello,
+// World!" program and shows the printed representation of packages,
+// functions and instructions.
+//
+// Within the function listing, the name of each BasicBlock such as
+// ".0.entry" is printed left-aligned, followed by the block's
+// Instructions.
+//
+// For each instruction that defines an SSA virtual register
+// (i.e. implements Value), the type of that value is shown in the
+// right column.
+//
+// Build and run the ssadump.go program if you want a standalone tool
+// with similar functionality. It is located at
+// golang.org/x/tools/cmd/ssadump.
+//
+func Example() {
+	const hello = `
+package main
+
+import "fmt"
+
+const message = "Hello, World!"
+
+func main() {
+	fmt.Println(message)
+}
+`
+	var conf loader.Config
+
+	// Parse the input file.
+	file, err := conf.ParseFile("hello.go", hello)
+	if err != nil {
+		fmt.Print(err) // parse error
+		return
+	}
+
+	// Create single-file main package.
+	conf.CreateFromFiles("main", file)
+
+	// Load the main package and its dependencies.
+	iprog, err := conf.Load()
+	if err != nil {
+		fmt.Print(err) // type error in some package
+		return
+	}
+
+	// Create SSA-form program representation.
+	prog := ssa.Create(iprog, ssa.SanityCheckFunctions)
+	mainPkg := prog.Package(iprog.Created[0].Pkg)
+
+	// Print out the package.
+	mainPkg.WriteTo(os.Stdout)
+
+	// Build SSA code for bodies of functions in mainPkg.
+	mainPkg.Build()
+
+	// Print out the package-level functions.
+	mainPkg.Func("init").WriteTo(os.Stdout)
+	mainPkg.Func("main").WriteTo(os.Stdout)
+
+	// Output:
+	//
+	// package main:
+	//   func  init       func()
+	//   var   init$guard bool
+	//   func  main       func()
+	//   const message    message = "Hello, World!":untyped string
+	//
+	// # Name: main.init
+	// # Package: main
+	// # Synthetic: package initializer
+	// func init():
+	// 0:                                                                entry P:0 S:2
+	// 	t0 = *init$guard                                                   bool
+	// 	if t0 goto 2 else 1
+	// 1:                                                           init.start P:1 S:1
+	// 	*init$guard = true:bool
+	// 	t1 = fmt.init()                                                      ()
+	// 	jump 2
+	// 2:                                                            init.done P:2 S:0
+	// 	return
+	//
+	// # Name: main.main
+	// # Package: main
+	// # Location: hello.go:8:6
+	// func main():
+	// 0:                                                                entry P:0 S:0
+	// 	t0 = new [1]interface{} (varargs)                       *[1]interface{}
+	// 	t1 = &t0[0:int]                                            *interface{}
+	// 	t2 = make interface{} <- string ("Hello, World!":string)    interface{}
+	// 	*t1 = t2
+	// 	t3 = slice t0[:]                                          []interface{}
+	// 	t4 = fmt.Println(t3...)                              (n int, err error)
+	// 	return
+}
diff --git a/third_party/go.tools/go/ssa/func.go b/third_party/go.tools/go/ssa/func.go
new file mode 100644
index 0000000..23eddf4
--- /dev/null
+++ b/third_party/go.tools/go/ssa/func.go
@@ -0,0 +1,687 @@
+// Copyright 2013 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 ssa
+
+// This file implements the Function and BasicBlock types.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"os"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// addEdge adds a control-flow graph edge from from to to.
+func addEdge(from, to *BasicBlock) {
+	from.Succs = append(from.Succs, to)
+	to.Preds = append(to.Preds, from)
+}
+
+// Parent returns the function that contains block b.
+func (b *BasicBlock) Parent() *Function { return b.parent }
+
+// String returns a human-readable label of this block.
+// It is not guaranteed unique within the function.
+//
+func (b *BasicBlock) String() string {
+	return fmt.Sprintf("%d", b.Index)
+}
+
+// emit appends an instruction to the current basic block.
+// If the instruction defines a Value, it is returned.
+//
+func (b *BasicBlock) emit(i Instruction) Value {
+	i.setBlock(b)
+	b.Instrs = append(b.Instrs, i)
+	v, _ := i.(Value)
+	return v
+}
+
+// predIndex returns the i such that b.Preds[i] == c or panics if
+// there is none.
+func (b *BasicBlock) predIndex(c *BasicBlock) int {
+	for i, pred := range b.Preds {
+		if pred == c {
+			return i
+		}
+	}
+	panic(fmt.Sprintf("no edge %s -> %s", c, b))
+}
+
+// hasPhi returns true if b.Instrs contains φ-nodes.
+func (b *BasicBlock) hasPhi() bool {
+	_, ok := b.Instrs[0].(*Phi)
+	return ok
+}
+
+// phis returns the prefix of b.Instrs containing all the block's φ-nodes.
+func (b *BasicBlock) phis() []Instruction {
+	for i, instr := range b.Instrs {
+		if _, ok := instr.(*Phi); !ok {
+			return b.Instrs[:i]
+		}
+	}
+	return nil // unreachable in well-formed blocks
+}
+
+// replacePred replaces all occurrences of p in b's predecessor list with q.
+// Ordinarily there should be at most one.
+//
+func (b *BasicBlock) replacePred(p, q *BasicBlock) {
+	for i, pred := range b.Preds {
+		if pred == p {
+			b.Preds[i] = q
+		}
+	}
+}
+
+// replaceSucc replaces all occurrences of p in b's successor list with q.
+// Ordinarily there should be at most one.
+//
+func (b *BasicBlock) replaceSucc(p, q *BasicBlock) {
+	for i, succ := range b.Succs {
+		if succ == p {
+			b.Succs[i] = q
+		}
+	}
+}
+
+// removePred removes all occurrences of p in b's
+// predecessor list and φ-nodes.
+// Ordinarily there should be at most one.
+//
+func (b *BasicBlock) removePred(p *BasicBlock) {
+	phis := b.phis()
+
+	// We must preserve edge order for φ-nodes.
+	j := 0
+	for i, pred := range b.Preds {
+		if pred != p {
+			b.Preds[j] = b.Preds[i]
+			// Strike out φ-edge too.
+			for _, instr := range phis {
+				phi := instr.(*Phi)
+				phi.Edges[j] = phi.Edges[i]
+			}
+			j++
+		}
+	}
+	// Nil out b.Preds[j:] and φ-edges[j:] to aid GC.
+	for i := j; i < len(b.Preds); i++ {
+		b.Preds[i] = nil
+		for _, instr := range phis {
+			instr.(*Phi).Edges[i] = nil
+		}
+	}
+	b.Preds = b.Preds[:j]
+	for _, instr := range phis {
+		phi := instr.(*Phi)
+		phi.Edges = phi.Edges[:j]
+	}
+}
+
+// Destinations associated with unlabelled for/switch/select stmts.
+// We push/pop one of these as we enter/leave each construct and for
+// each BranchStmt we scan for the innermost target of the right type.
+//
+type targets struct {
+	tail         *targets // rest of stack
+	_break       *BasicBlock
+	_continue    *BasicBlock
+	_fallthrough *BasicBlock
+}
+
+// Destinations associated with a labelled block.
+// We populate these as labels are encountered in forward gotos or
+// labelled statements.
+//
+type lblock struct {
+	_goto     *BasicBlock
+	_break    *BasicBlock
+	_continue *BasicBlock
+}
+
+// labelledBlock returns the branch target associated with the
+// specified label, creating it if needed.
+//
+func (f *Function) labelledBlock(label *ast.Ident) *lblock {
+	lb := f.lblocks[label.Obj]
+	if lb == nil {
+		lb = &lblock{_goto: f.newBasicBlock(label.Name)}
+		if f.lblocks == nil {
+			f.lblocks = make(map[*ast.Object]*lblock)
+		}
+		f.lblocks[label.Obj] = lb
+	}
+	return lb
+}
+
+// addParam adds a (non-escaping) parameter to f.Params of the
+// specified name, type and source position.
+//
+func (f *Function) addParam(name string, typ types.Type, pos token.Pos) *Parameter {
+	v := &Parameter{
+		name:   name,
+		typ:    typ,
+		pos:    pos,
+		parent: f,
+	}
+	f.Params = append(f.Params, v)
+	return v
+}
+
+func (f *Function) addParamObj(obj types.Object) *Parameter {
+	name := obj.Name()
+	if name == "" {
+		name = fmt.Sprintf("arg%d", len(f.Params))
+	}
+	param := f.addParam(name, obj.Type(), obj.Pos())
+	param.object = obj
+	return param
+}
+
+// addSpilledParam declares a parameter that is pre-spilled to the
+// stack; the function body will load/store the spilled location.
+// Subsequent lifting will eliminate spills where possible.
+//
+func (f *Function) addSpilledParam(obj types.Object) {
+	param := f.addParamObj(obj)
+	spill := &Alloc{Comment: obj.Name()}
+	spill.setType(types.NewPointer(obj.Type()))
+	spill.setPos(obj.Pos())
+	f.objects[obj] = spill
+	f.Locals = append(f.Locals, spill)
+	f.emit(spill)
+	f.emit(&Store{Addr: spill, Val: param})
+}
+
+// startBody initializes the function prior to generating SSA code for its body.
+// Precondition: f.Type() already set.
+//
+func (f *Function) startBody() {
+	f.currentBlock = f.newBasicBlock("entry")
+	f.objects = make(map[types.Object]Value) // needed for some synthetics, e.g. init
+}
+
+// createSyntacticParams populates f.Params and generates code (spills
+// and named result locals) for all the parameters declared in the
+// syntax.  In addition it populates the f.objects mapping.
+//
+// Preconditions:
+// f.startBody() was called.
+// Postcondition:
+// len(f.Params) == len(f.Signature.Params) + (f.Signature.Recv() ? 1 : 0)
+//
+func (f *Function) createSyntacticParams(recv *ast.FieldList, functype *ast.FuncType) {
+	// Receiver (at most one inner iteration).
+	if recv != nil {
+		for _, field := range recv.List {
+			for _, n := range field.Names {
+				f.addSpilledParam(f.Pkg.info.Defs[n])
+			}
+			// Anonymous receiver?  No need to spill.
+			if field.Names == nil {
+				f.addParamObj(f.Signature.Recv())
+			}
+		}
+	}
+
+	// Parameters.
+	if functype.Params != nil {
+		n := len(f.Params) // 1 if has recv, 0 otherwise
+		for _, field := range functype.Params.List {
+			for _, n := range field.Names {
+				f.addSpilledParam(f.Pkg.info.Defs[n])
+			}
+			// Anonymous parameter?  No need to spill.
+			if field.Names == nil {
+				f.addParamObj(f.Signature.Params().At(len(f.Params) - n))
+			}
+		}
+	}
+
+	// Named results.
+	if functype.Results != nil {
+		for _, field := range functype.Results.List {
+			// Implicit "var" decl of locals for named results.
+			for _, n := range field.Names {
+				f.namedResults = append(f.namedResults, f.addLocalForIdent(n))
+			}
+		}
+	}
+}
+
+// numberRegisters assigns numbers to all SSA registers
+// (value-defining Instructions) in f, to aid debugging.
+// (Non-Instruction Values are named at construction.)
+//
+func numberRegisters(f *Function) {
+	v := 0
+	for _, b := range f.Blocks {
+		for _, instr := range b.Instrs {
+			switch instr.(type) {
+			case Value:
+				instr.(interface {
+					setNum(int)
+				}).setNum(v)
+				v++
+			}
+		}
+	}
+}
+
+// buildReferrers populates the def/use information in all non-nil
+// Value.Referrers slice.
+// Precondition: all such slices are initially empty.
+func buildReferrers(f *Function) {
+	var rands []*Value
+	for _, b := range f.Blocks {
+		for _, instr := range b.Instrs {
+			rands = instr.Operands(rands[:0]) // recycle storage
+			for _, rand := range rands {
+				if r := *rand; r != nil {
+					if ref := r.Referrers(); ref != nil {
+						*ref = append(*ref, instr)
+					}
+				}
+			}
+		}
+	}
+}
+
+// finishBody() finalizes the function after SSA code generation of its body.
+func (f *Function) finishBody() {
+	f.objects = nil
+	f.currentBlock = nil
+	f.lblocks = nil
+
+	// Don't pin the AST in memory (except in debug mode).
+	if n := f.syntax; n != nil && !f.debugInfo() {
+		f.syntax = extentNode{n.Pos(), n.End()}
+	}
+
+	// Remove from f.Locals any Allocs that escape to the heap.
+	j := 0
+	for _, l := range f.Locals {
+		if !l.Heap {
+			f.Locals[j] = l
+			j++
+		}
+	}
+	// Nil out f.Locals[j:] to aid GC.
+	for i := j; i < len(f.Locals); i++ {
+		f.Locals[i] = nil
+	}
+	f.Locals = f.Locals[:j]
+
+	optimizeBlocks(f)
+
+	buildReferrers(f)
+
+	buildDomTree(f)
+
+	if f.Prog.mode&NaiveForm == 0 {
+		// For debugging pre-state of lifting pass:
+		// numberRegisters(f)
+		// f.WriteTo(os.Stderr)
+		lift(f)
+	}
+
+	f.namedResults = nil // (used by lifting)
+
+	numberRegisters(f)
+
+	if f.Prog.mode&PrintFunctions != 0 {
+		printMu.Lock()
+		f.WriteTo(os.Stdout)
+		printMu.Unlock()
+	}
+
+	if f.Prog.mode&SanityCheckFunctions != 0 {
+		mustSanityCheck(f, nil)
+	}
+}
+
+// removeNilBlocks eliminates nils from f.Blocks and updates each
+// BasicBlock.Index.  Use this after any pass that may delete blocks.
+//
+func (f *Function) removeNilBlocks() {
+	j := 0
+	for _, b := range f.Blocks {
+		if b != nil {
+			b.Index = j
+			f.Blocks[j] = b
+			j++
+		}
+	}
+	// Nil out f.Blocks[j:] to aid GC.
+	for i := j; i < len(f.Blocks); i++ {
+		f.Blocks[i] = nil
+	}
+	f.Blocks = f.Blocks[:j]
+}
+
+// SetDebugMode sets the debug mode for package pkg.  If true, all its
+// functions will include full debug info.  This greatly increases the
+// size of the instruction stream, and causes Functions to depend upon
+// the ASTs, potentially keeping them live in memory for longer.
+//
+func (pkg *Package) SetDebugMode(debug bool) {
+	// TODO(adonovan): do we want ast.File granularity?
+	pkg.debug = debug
+}
+
+// debugInfo reports whether debug info is wanted for this function.
+func (f *Function) debugInfo() bool {
+	return f.Pkg != nil && f.Pkg.debug
+}
+
+// addNamedLocal creates a local variable, adds it to function f and
+// returns it.  Its name and type are taken from obj.  Subsequent
+// calls to f.lookup(obj) will return the same local.
+//
+func (f *Function) addNamedLocal(obj types.Object) *Alloc {
+	l := f.addLocal(obj.Type(), obj.Pos())
+	l.Comment = obj.Name()
+	f.objects[obj] = l
+	return l
+}
+
+func (f *Function) addLocalForIdent(id *ast.Ident) *Alloc {
+	return f.addNamedLocal(f.Pkg.info.Defs[id])
+}
+
+// addLocal creates an anonymous local variable of type typ, adds it
+// to function f and returns it.  pos is the optional source location.
+//
+func (f *Function) addLocal(typ types.Type, pos token.Pos) *Alloc {
+	v := &Alloc{}
+	v.setType(types.NewPointer(typ))
+	v.setPos(pos)
+	f.Locals = append(f.Locals, v)
+	f.emit(v)
+	return v
+}
+
+// lookup returns the address of the named variable identified by obj
+// that is local to function f or one of its enclosing functions.
+// If escaping, the reference comes from a potentially escaping pointer
+// expression and the referent must be heap-allocated.
+//
+func (f *Function) lookup(obj types.Object, escaping bool) Value {
+	if v, ok := f.objects[obj]; ok {
+		if alloc, ok := v.(*Alloc); ok && escaping {
+			alloc.Heap = true
+		}
+		return v // function-local var (address)
+	}
+
+	// Definition must be in an enclosing function;
+	// plumb it through intervening closures.
+	if f.parent == nil {
+		panic("no Value for type.Object " + obj.Name())
+	}
+	outer := f.parent.lookup(obj, true) // escaping
+	v := &FreeVar{
+		name:   obj.Name(),
+		typ:    outer.Type(),
+		pos:    outer.Pos(),
+		outer:  outer,
+		parent: f,
+	}
+	f.objects[obj] = v
+	f.FreeVars = append(f.FreeVars, v)
+	return v
+}
+
+// emit emits the specified instruction to function f.
+func (f *Function) emit(instr Instruction) Value {
+	return f.currentBlock.emit(instr)
+}
+
+// RelString returns the full name of this function, qualified by
+// package name, receiver type, etc.
+//
+// The specific formatting rules are not guaranteed and may change.
+//
+// Examples:
+//      "math.IsNaN"                  // a package-level function
+//      "(*bytes.Buffer).Bytes"       // a declared method or a wrapper
+//      "(*bytes.Buffer).Bytes$thunk" // thunk (func wrapping method; receiver is param 0)
+//      "(*bytes.Buffer).Bytes$bound" // bound (func wrapping method; receiver supplied by closure)
+//      "main.main$1"                 // an anonymous function in main
+//      "main.init#1"                 // a declared init function
+//      "main.init"                   // the synthesized package initializer
+//
+// When these functions are referred to from within the same package
+// (i.e. from == f.Pkg.Object), they are rendered without the package path.
+// For example: "IsNaN", "(*Buffer).Bytes", etc.
+//
+// Invariant: all non-synthetic functions have distinct package-qualified names.
+//
+func (f *Function) RelString(from *types.Package) string {
+	// Anonymous?
+	if f.parent != nil {
+		// An anonymous function's Name() looks like "parentName$1",
+		// but its String() should include the type/package/etc.
+		parent := f.parent.RelString(from)
+		for i, anon := range f.parent.AnonFuncs {
+			if anon == f {
+				return fmt.Sprintf("%s$%d", parent, 1+i)
+			}
+		}
+
+		return f.name // should never happen
+	}
+
+	// Method (declared or wrapper)?
+	if recv := f.Signature.Recv(); recv != nil {
+		return f.relMethod(from, recv.Type())
+	}
+
+	// Thunk?
+	if f.method != nil {
+		return f.relMethod(from, f.method.Recv())
+	}
+
+	// Bound?
+	if len(f.FreeVars) == 1 && strings.HasSuffix(f.name, "$bound") {
+		return f.relMethod(from, f.FreeVars[0].Type())
+	}
+
+	// Package-level function?
+	// Prefix with package name for cross-package references only.
+	if p := f.pkgobj(); p != nil && p != from {
+		return fmt.Sprintf("%s.%s", p.Path(), f.name)
+	}
+
+	// Unknown.
+	return f.name
+}
+
+func (f *Function) relMethod(from *types.Package, recv types.Type) string {
+	return fmt.Sprintf("(%s).%s", relType(recv, from), f.name)
+}
+
+// writeSignature writes to buf the signature sig in declaration syntax.
+func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *types.Signature, params []*Parameter) {
+	buf.WriteString("func ")
+	if recv := sig.Recv(); recv != nil {
+		buf.WriteString("(")
+		if n := params[0].Name(); n != "" {
+			buf.WriteString(n)
+			buf.WriteString(" ")
+		}
+		types.WriteType(buf, from, params[0].Type())
+		buf.WriteString(") ")
+	}
+	buf.WriteString(name)
+	types.WriteSignature(buf, from, sig)
+}
+
+func (f *Function) pkgobj() *types.Package {
+	if f.Pkg != nil {
+		return f.Pkg.Object
+	}
+	return nil
+}
+
+var _ io.WriterTo = (*Function)(nil) // *Function implements io.Writer
+
+func (f *Function) WriteTo(w io.Writer) (int64, error) {
+	var buf bytes.Buffer
+	WriteFunction(&buf, f)
+	n, err := w.Write(buf.Bytes())
+	return int64(n), err
+}
+
+// WriteFunction writes to buf a human-readable "disassembly" of f.
+func WriteFunction(buf *bytes.Buffer, f *Function) {
+	fmt.Fprintf(buf, "# Name: %s\n", f.String())
+	if f.Pkg != nil {
+		fmt.Fprintf(buf, "# Package: %s\n", f.Pkg.Object.Path())
+	}
+	if syn := f.Synthetic; syn != "" {
+		fmt.Fprintln(buf, "# Synthetic:", syn)
+	}
+	if pos := f.Pos(); pos.IsValid() {
+		fmt.Fprintf(buf, "# Location: %s\n", f.Prog.Fset.Position(pos))
+	}
+
+	if f.parent != nil {
+		fmt.Fprintf(buf, "# Parent: %s\n", f.parent.Name())
+	}
+
+	if f.Recover != nil {
+		fmt.Fprintf(buf, "# Recover: %s\n", f.Recover)
+	}
+
+	from := f.pkgobj()
+
+	if f.FreeVars != nil {
+		buf.WriteString("# Free variables:\n")
+		for i, fv := range f.FreeVars {
+			fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, fv.Name(), relType(fv.Type(), from))
+		}
+	}
+
+	if len(f.Locals) > 0 {
+		buf.WriteString("# Locals:\n")
+		for i, l := range f.Locals {
+			fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, l.Name(), relType(deref(l.Type()), from))
+		}
+	}
+	writeSignature(buf, from, f.Name(), f.Signature, f.Params)
+	buf.WriteString(":\n")
+
+	if f.Blocks == nil {
+		buf.WriteString("\t(external)\n")
+	}
+
+	// NB. column calculations are confused by non-ASCII
+	// characters and assume 8-space tabs.
+	const punchcard = 80 // for old time's sake.
+	const tabwidth = 8
+	for _, b := range f.Blocks {
+		if b == nil {
+			// Corrupt CFG.
+			fmt.Fprintf(buf, ".nil:\n")
+			continue
+		}
+		n, _ := fmt.Fprintf(buf, "%d:", b.Index)
+		bmsg := fmt.Sprintf("%s P:%d S:%d", b.Comment, len(b.Preds), len(b.Succs))
+		fmt.Fprintf(buf, "%*s%s\n", punchcard-1-n-len(bmsg), "", bmsg)
+
+		if false { // CFG debugging
+			fmt.Fprintf(buf, "\t# CFG: %s --> %s --> %s\n", b.Preds, b, b.Succs)
+		}
+		for _, instr := range b.Instrs {
+			buf.WriteString("\t")
+			switch v := instr.(type) {
+			case Value:
+				l := punchcard - tabwidth
+				// Left-align the instruction.
+				if name := v.Name(); name != "" {
+					n, _ := fmt.Fprintf(buf, "%s = ", name)
+					l -= n
+				}
+				n, _ := buf.WriteString(instr.String())
+				l -= n
+				// Right-align the type if there's space.
+				if t := v.Type(); t != nil {
+					buf.WriteByte(' ')
+					ts := relType(t, from)
+					l -= len(ts) + len("  ") // (spaces before and after type)
+					if l > 0 {
+						fmt.Fprintf(buf, "%*s", l, "")
+					}
+					buf.WriteString(ts)
+				}
+			case nil:
+				// Be robust against bad transforms.
+				buf.WriteString("<deleted>")
+			default:
+				buf.WriteString(instr.String())
+			}
+			buf.WriteString("\n")
+		}
+	}
+	fmt.Fprintf(buf, "\n")
+}
+
+// newBasicBlock adds to f a new basic block and returns it.  It does
+// not automatically become the current block for subsequent calls to emit.
+// comment is an optional string for more readable debugging output.
+//
+func (f *Function) newBasicBlock(comment string) *BasicBlock {
+	b := &BasicBlock{
+		Index:   len(f.Blocks),
+		Comment: comment,
+		parent:  f,
+	}
+	b.Succs = b.succs2[:0]
+	f.Blocks = append(f.Blocks, b)
+	return b
+}
+
+// NewFunction returns a new synthetic Function instance belonging to
+// prog, with its name and signature fields set as specified.
+//
+// The caller is responsible for initializing the remaining fields of
+// the function object, e.g. Pkg, Params, Blocks.
+//
+// It is practically impossible for clients to construct well-formed
+// SSA functions/packages/programs directly, so we assume this is the
+// job of the Builder alone.  NewFunction exists to provide clients a
+// little flexibility.  For example, analysis tools may wish to
+// construct fake Functions for the root of the callgraph, a fake
+// "reflect" package, etc.
+//
+// TODO(adonovan): think harder about the API here.
+//
+func (prog *Program) NewFunction(name string, sig *types.Signature, provenance string) *Function {
+	return &Function{Prog: prog, name: name, Signature: sig, Synthetic: provenance}
+}
+
+type extentNode [2]token.Pos
+
+func (n extentNode) Pos() token.Pos { return n[0] }
+func (n extentNode) End() token.Pos { return n[1] }
+
+// Syntax returns an ast.Node whose Pos/End methods provide the
+// lexical extent of the function if it was defined by Go source code
+// (f.Synthetic==""), or nil otherwise.
+//
+// If f was built with debug information (see Package.SetDebugRef),
+// the result is the *ast.FuncDecl or *ast.FuncLit that declared the
+// function.  Otherwise, it is an opaque Node providing only position
+// information; this avoids pinning the AST in memory.
+//
+func (f *Function) Syntax() ast.Node { return f.syntax }
diff --git a/third_party/go.tools/go/ssa/interp/external.go b/third_party/go.tools/go/ssa/interp/external.go
new file mode 100644
index 0000000..4f8a6ab
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/external.go
@@ -0,0 +1,482 @@
+// Copyright 2013 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 interp
+
+// Emulated functions that we cannot interpret because they are
+// external or because they use "unsafe" or "reflect" operations.
+
+import (
+	"math"
+	"os"
+	"runtime"
+	"syscall"
+	"time"
+	"unsafe"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+type externalFn func(fr *frame, args []value) value
+
+// TODO(adonovan): fix: reflect.Value abstracts an lvalue or an
+// rvalue; Set() causes mutations that can be observed via aliases.
+// We have not captured that correctly here.
+
+// Key strings are from Function.String().
+var externals map[string]externalFn
+
+func init() {
+	// That little dot ۰ is an Arabic zero numeral (U+06F0), categories [Nd].
+	externals = map[string]externalFn{
+		"(*sync.Pool).Get":                 ext۰sync۰Pool۰Get,
+		"(*sync.Pool).Put":                 ext۰sync۰Pool۰Put,
+		"(reflect.Value).Bool":             ext۰reflect۰Value۰Bool,
+		"(reflect.Value).CanAddr":          ext۰reflect۰Value۰CanAddr,
+		"(reflect.Value).CanInterface":     ext۰reflect۰Value۰CanInterface,
+		"(reflect.Value).Elem":             ext۰reflect۰Value۰Elem,
+		"(reflect.Value).Field":            ext۰reflect۰Value۰Field,
+		"(reflect.Value).Float":            ext۰reflect۰Value۰Float,
+		"(reflect.Value).Index":            ext۰reflect۰Value۰Index,
+		"(reflect.Value).Int":              ext۰reflect۰Value۰Int,
+		"(reflect.Value).Interface":        ext۰reflect۰Value۰Interface,
+		"(reflect.Value).IsNil":            ext۰reflect۰Value۰IsNil,
+		"(reflect.Value).IsValid":          ext۰reflect۰Value۰IsValid,
+		"(reflect.Value).Kind":             ext۰reflect۰Value۰Kind,
+		"(reflect.Value).Len":              ext۰reflect۰Value۰Len,
+		"(reflect.Value).MapIndex":         ext۰reflect۰Value۰MapIndex,
+		"(reflect.Value).MapKeys":          ext۰reflect۰Value۰MapKeys,
+		"(reflect.Value).NumField":         ext۰reflect۰Value۰NumField,
+		"(reflect.Value).NumMethod":        ext۰reflect۰Value۰NumMethod,
+		"(reflect.Value).Pointer":          ext۰reflect۰Value۰Pointer,
+		"(reflect.Value).Set":              ext۰reflect۰Value۰Set,
+		"(reflect.Value).String":           ext۰reflect۰Value۰String,
+		"(reflect.Value).Type":             ext۰reflect۰Value۰Type,
+		"(reflect.Value).Uint":             ext۰reflect۰Value۰Uint,
+		"(reflect.error).Error":            ext۰reflect۰error۰Error,
+		"(reflect.rtype).Bits":             ext۰reflect۰rtype۰Bits,
+		"(reflect.rtype).Elem":             ext۰reflect۰rtype۰Elem,
+		"(reflect.rtype).Field":            ext۰reflect۰rtype۰Field,
+		"(reflect.rtype).Kind":             ext۰reflect۰rtype۰Kind,
+		"(reflect.rtype).NumField":         ext۰reflect۰rtype۰NumField,
+		"(reflect.rtype).NumMethod":        ext۰reflect۰rtype۰NumMethod,
+		"(reflect.rtype).NumOut":           ext۰reflect۰rtype۰NumOut,
+		"(reflect.rtype).Out":              ext۰reflect۰rtype۰Out,
+		"(reflect.rtype).Size":             ext۰reflect۰rtype۰Size,
+		"(reflect.rtype).String":           ext۰reflect۰rtype۰String,
+		"bytes.Equal":                      ext۰bytes۰Equal,
+		"bytes.IndexByte":                  ext۰bytes۰IndexByte,
+		"hash/crc32.haveSSE42":             ext۰crc32۰haveSSE42,
+		"math.Abs":                         ext۰math۰Abs,
+		"math.Exp":                         ext۰math۰Exp,
+		"math.Float32bits":                 ext۰math۰Float32bits,
+		"math.Float32frombits":             ext۰math۰Float32frombits,
+		"math.Float64bits":                 ext۰math۰Float64bits,
+		"math.Float64frombits":             ext۰math۰Float64frombits,
+		"math.Ldexp":                       ext۰math۰Ldexp,
+		"math.Log":                         ext۰math۰Log,
+		"math.Min":                         ext۰math۰Min,
+		"os.runtime_args":                  ext۰os۰runtime_args,
+		"reflect.New":                      ext۰reflect۰New,
+		"reflect.TypeOf":                   ext۰reflect۰TypeOf,
+		"reflect.ValueOf":                  ext۰reflect۰ValueOf,
+		"reflect.init":                     ext۰reflect۰Init,
+		"reflect.valueInterface":           ext۰reflect۰valueInterface,
+		"runtime.Breakpoint":               ext۰runtime۰Breakpoint,
+		"runtime.Caller":                   ext۰runtime۰Caller,
+		"runtime.Callers":                  ext۰runtime۰Callers,
+		"runtime.FuncForPC":                ext۰runtime۰FuncForPC,
+		"runtime.GC":                       ext۰runtime۰GC,
+		"runtime.GOMAXPROCS":               ext۰runtime۰GOMAXPROCS,
+		"runtime.Goexit":                   ext۰runtime۰Goexit,
+		"runtime.Gosched":                  ext۰runtime۰Gosched,
+		"runtime.init":                     ext۰runtime۰init,
+		"runtime.NumCPU":                   ext۰runtime۰NumCPU,
+		"runtime.ReadMemStats":             ext۰runtime۰ReadMemStats,
+		"runtime.SetFinalizer":             ext۰runtime۰SetFinalizer,
+		"(*runtime.Func).Entry":            ext۰runtime۰Func۰Entry,
+		"(*runtime.Func).FileLine":         ext۰runtime۰Func۰FileLine,
+		"(*runtime.Func).Name":             ext۰runtime۰Func۰Name,
+		"runtime.environ":                  ext۰runtime۰environ,
+		"runtime.getgoroot":                ext۰runtime۰getgoroot,
+		"strings.IndexByte":                ext۰strings۰IndexByte,
+		"sync.runtime_Semacquire":          ext۰sync۰runtime_Semacquire,
+		"sync.runtime_Semrelease":          ext۰sync۰runtime_Semrelease,
+		"sync.runtime_Syncsemcheck":        ext۰sync۰runtime_Syncsemcheck,
+		"sync.runtime_registerPoolCleanup": ext۰sync۰runtime_registerPoolCleanup,
+		"sync/atomic.AddInt32":             ext۰atomic۰AddInt32,
+		"sync/atomic.AddUint32":            ext۰atomic۰AddUint32,
+		"sync/atomic.AddUint64":            ext۰atomic۰AddUint64,
+		"sync/atomic.CompareAndSwapInt32":  ext۰atomic۰CompareAndSwapInt32,
+		"sync/atomic.LoadInt32":            ext۰atomic۰LoadInt32,
+		"sync/atomic.LoadUint32":           ext۰atomic۰LoadUint32,
+		"sync/atomic.StoreInt32":           ext۰atomic۰StoreInt32,
+		"sync/atomic.StoreUint32":          ext۰atomic۰StoreUint32,
+		"syscall.Close":                    ext۰syscall۰Close,
+		"syscall.Exit":                     ext۰syscall۰Exit,
+		"syscall.Fstat":                    ext۰syscall۰Fstat,
+		"syscall.Getpid":                   ext۰syscall۰Getpid,
+		"syscall.Getwd":                    ext۰syscall۰Getwd,
+		"syscall.Kill":                     ext۰syscall۰Kill,
+		"syscall.Lstat":                    ext۰syscall۰Lstat,
+		"syscall.Open":                     ext۰syscall۰Open,
+		"syscall.ParseDirent":              ext۰syscall۰ParseDirent,
+		"syscall.RawSyscall":               ext۰syscall۰RawSyscall,
+		"syscall.Read":                     ext۰syscall۰Read,
+		"syscall.ReadDirent":               ext۰syscall۰ReadDirent,
+		"syscall.Stat":                     ext۰syscall۰Stat,
+		"syscall.Write":                    ext۰syscall۰Write,
+		"syscall.runtime_envs":             ext۰runtime۰environ,
+		"time.Sleep":                       ext۰time۰Sleep,
+		"time.now":                         ext۰time۰now,
+	}
+}
+
+// wrapError returns an interpreted 'error' interface value for err.
+func wrapError(err error) value {
+	if err == nil {
+		return iface{}
+	}
+	return iface{t: errorType, v: err.Error()}
+}
+
+func ext۰sync۰Pool۰Get(fr *frame, args []value) value {
+	Pool := fr.i.prog.ImportedPackage("sync").Type("Pool").Object()
+	_, newIndex, _ := types.LookupFieldOrMethod(Pool.Type(), false, Pool.Pkg(), "New")
+
+	if New := (*args[0].(*value)).(structure)[newIndex[0]]; New != nil {
+		return call(fr.i, fr, 0, New, nil)
+	}
+	return nil
+}
+
+func ext۰sync۰Pool۰Put(fr *frame, args []value) value {
+	return nil
+}
+
+func ext۰bytes۰Equal(fr *frame, args []value) value {
+	// func Equal(a, b []byte) bool
+	a := args[0].([]value)
+	b := args[1].([]value)
+	if len(a) != len(b) {
+		return false
+	}
+	for i := range a {
+		if a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func ext۰bytes۰IndexByte(fr *frame, args []value) value {
+	// func IndexByte(s []byte, c byte) int
+	s := args[0].([]value)
+	c := args[1].(byte)
+	for i, b := range s {
+		if b.(byte) == c {
+			return i
+		}
+	}
+	return -1
+}
+
+func ext۰crc32۰haveSSE42(fr *frame, args []value) value {
+	return false
+}
+
+func ext۰math۰Float64frombits(fr *frame, args []value) value {
+	return math.Float64frombits(args[0].(uint64))
+}
+
+func ext۰math۰Float64bits(fr *frame, args []value) value {
+	return math.Float64bits(args[0].(float64))
+}
+
+func ext۰math۰Float32frombits(fr *frame, args []value) value {
+	return math.Float32frombits(args[0].(uint32))
+}
+
+func ext۰math۰Abs(fr *frame, args []value) value {
+	return math.Abs(args[0].(float64))
+}
+
+func ext۰math۰Exp(fr *frame, args []value) value {
+	return math.Exp(args[0].(float64))
+}
+
+func ext۰math۰Float32bits(fr *frame, args []value) value {
+	return math.Float32bits(args[0].(float32))
+}
+
+func ext۰math۰Min(fr *frame, args []value) value {
+	return math.Min(args[0].(float64), args[1].(float64))
+}
+
+func ext۰math۰Ldexp(fr *frame, args []value) value {
+	return math.Ldexp(args[0].(float64), args[1].(int))
+}
+
+func ext۰math۰Log(fr *frame, args []value) value {
+	return math.Log(args[0].(float64))
+}
+
+func ext۰os۰runtime_args(fr *frame, args []value) value {
+	return fr.i.osArgs
+}
+
+func ext۰runtime۰Breakpoint(fr *frame, args []value) value {
+	runtime.Breakpoint()
+	return nil
+}
+
+func ext۰runtime۰Caller(fr *frame, args []value) value {
+	// func Caller(skip int) (pc uintptr, file string, line int, ok bool)
+	skip := 1 + args[0].(int)
+	for i := 0; i < skip; i++ {
+		if fr != nil {
+			fr = fr.caller
+		}
+	}
+	var pc uintptr
+	var file string
+	var line int
+	var ok bool
+	if fr != nil {
+		fn := fr.fn
+		// TODO(adonovan): use pc/posn of current instruction, not start of fn.
+		pc = uintptr(unsafe.Pointer(fn))
+		posn := fn.Prog.Fset.Position(fn.Pos())
+		file = posn.Filename
+		line = posn.Line
+		ok = true
+	}
+	return tuple{pc, file, line, ok}
+}
+
+func ext۰runtime۰Callers(fr *frame, args []value) value {
+	// Callers(skip int, pc []uintptr) int
+	skip := args[0].(int)
+	pc := args[1].([]value)
+	for i := 0; i < skip; i++ {
+		if fr != nil {
+			fr = fr.caller
+		}
+	}
+	i := 0
+	for fr != nil {
+		pc[i] = uintptr(unsafe.Pointer(fr.fn))
+		i++
+		fr = fr.caller
+	}
+	return i
+}
+
+func ext۰runtime۰FuncForPC(fr *frame, args []value) value {
+	// FuncForPC(pc uintptr) *Func
+	pc := args[0].(uintptr)
+	var fn *ssa.Function
+	if pc != 0 {
+		fn = (*ssa.Function)(unsafe.Pointer(pc)) // indeed unsafe!
+	}
+	var Func value
+	Func = structure{fn} // a runtime.Func
+	return &Func
+}
+
+func ext۰runtime۰environ(fr *frame, args []value) value {
+	// This function also implements syscall.runtime_envs.
+	return environ
+}
+
+func ext۰runtime۰getgoroot(fr *frame, args []value) value {
+	return os.Getenv("GOROOT")
+}
+
+func ext۰strings۰IndexByte(fr *frame, args []value) value {
+	// func IndexByte(s string, c byte) int
+	s := args[0].(string)
+	c := args[1].(byte)
+	for i := 0; i < len(s); i++ {
+		if s[i] == c {
+			return i
+		}
+	}
+	return -1
+}
+
+func ext۰sync۰runtime_Syncsemcheck(fr *frame, args []value) value {
+	// TODO(adonovan): fix: implement.
+	return nil
+}
+
+func ext۰sync۰runtime_registerPoolCleanup(fr *frame, args []value) value {
+	return nil
+}
+
+func ext۰sync۰runtime_Semacquire(fr *frame, args []value) value {
+	// TODO(adonovan): fix: implement.
+	return nil
+}
+
+func ext۰sync۰runtime_Semrelease(fr *frame, args []value) value {
+	// TODO(adonovan): fix: implement.
+	return nil
+}
+
+func ext۰runtime۰GOMAXPROCS(fr *frame, args []value) value {
+	return runtime.GOMAXPROCS(args[0].(int))
+}
+
+func ext۰runtime۰Goexit(fr *frame, args []value) value {
+	// TODO(adonovan): don't kill the interpreter's main goroutine.
+	runtime.Goexit()
+	return nil
+}
+
+func ext۰runtime۰GC(fr *frame, args []value) value {
+	runtime.GC()
+	return nil
+}
+
+func ext۰runtime۰Gosched(fr *frame, args []value) value {
+	runtime.Gosched()
+	return nil
+}
+
+func ext۰runtime۰init(fr *frame, args []value) value {
+	return nil
+}
+
+func ext۰runtime۰NumCPU(fr *frame, args []value) value {
+	return runtime.NumCPU()
+}
+
+func ext۰runtime۰ReadMemStats(fr *frame, args []value) value {
+	// TODO(adonovan): populate args[0].(Struct)
+	return nil
+}
+
+func ext۰atomic۰LoadUint32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	return (*args[0].(*value)).(uint32)
+}
+
+func ext۰atomic۰StoreUint32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	*args[0].(*value) = args[1].(uint32)
+	return nil
+}
+
+func ext۰atomic۰LoadInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	return (*args[0].(*value)).(int32)
+}
+
+func ext۰atomic۰StoreInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	*args[0].(*value) = args[1].(int32)
+	return nil
+}
+
+func ext۰atomic۰CompareAndSwapInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	if (*p).(int32) == args[1].(int32) {
+		*p = args[2].(int32)
+		return true
+	}
+	return false
+}
+
+func ext۰atomic۰AddInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	newv := (*p).(int32) + args[1].(int32)
+	*p = newv
+	return newv
+}
+
+func ext۰atomic۰AddUint32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	newv := (*p).(uint32) + args[1].(uint32)
+	*p = newv
+	return newv
+}
+
+func ext۰atomic۰AddUint64(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	newv := (*p).(uint64) + args[1].(uint64)
+	*p = newv
+	return newv
+}
+
+func ext۰runtime۰SetFinalizer(fr *frame, args []value) value {
+	return nil // ignore
+}
+
+// Pretend: type runtime.Func struct { entry *ssa.Function }
+
+func ext۰runtime۰Func۰FileLine(fr *frame, args []value) value {
+	// func (*runtime.Func) FileLine(uintptr) (string, int)
+	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
+	pc := args[1].(uintptr)
+	_ = pc
+	if f != nil {
+		// TODO(adonovan): use position of current instruction, not fn.
+		posn := f.Prog.Fset.Position(f.Pos())
+		return tuple{posn.Filename, posn.Line}
+	}
+	return tuple{"", 0}
+}
+
+func ext۰runtime۰Func۰Name(fr *frame, args []value) value {
+	// func (*runtime.Func) Name() string
+	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
+	if f != nil {
+		return f.String()
+	}
+	return ""
+}
+
+func ext۰runtime۰Func۰Entry(fr *frame, args []value) value {
+	// func (*runtime.Func) Entry() uintptr
+	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
+	return uintptr(unsafe.Pointer(f))
+}
+
+func ext۰time۰now(fr *frame, args []value) value {
+	nano := time.Now().UnixNano()
+	return tuple{int64(nano / 1e9), int32(nano % 1e9)}
+}
+
+func ext۰time۰Sleep(fr *frame, args []value) value {
+	time.Sleep(time.Duration(args[0].(int64)))
+	return nil
+}
+
+func ext۰syscall۰Exit(fr *frame, args []value) value {
+	panic(exitPanic(args[0].(int)))
+}
+
+func ext۰syscall۰Getwd(fr *frame, args []value) value {
+	s, err := syscall.Getwd()
+	return tuple{s, wrapError(err)}
+}
+
+func ext۰syscall۰Getpid(fr *frame, args []value) value {
+	return syscall.Getpid()
+}
+
+func valueToBytes(v value) []byte {
+	in := v.([]value)
+	b := make([]byte, len(in))
+	for i := range in {
+		b[i] = in[i].(byte)
+	}
+	return b
+}
diff --git a/third_party/go.tools/go/ssa/interp/external_darwin.go b/third_party/go.tools/go/ssa/interp/external_darwin.go
new file mode 100644
index 0000000..4974ad6
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/external_darwin.go
@@ -0,0 +1,18 @@
+// Copyright 2014 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.
+
+// +build darwin
+
+package interp
+
+import "syscall"
+
+func init() {
+	externals["syscall.Sysctl"] = ext۰syscall۰Sysctl
+}
+
+func ext۰syscall۰Sysctl(fr *frame, args []value) value {
+	r, err := syscall.Sysctl(args[0].(string))
+	return tuple{r, wrapError(err)}
+}
diff --git a/third_party/go.tools/go/ssa/interp/external_freebsd.go b/third_party/go.tools/go/ssa/interp/external_freebsd.go
new file mode 100644
index 0000000..5203303
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/external_freebsd.go
@@ -0,0 +1,24 @@
+// Copyright 2014 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.
+
+// +build freebsd
+
+package interp
+
+import "syscall"
+
+func init() {
+	externals["syscall.Sysctl"] = ext۰syscall۰Sysctl
+	externals["syscall.SysctlUint32"] = ext۰syscall۰SysctlUint32
+}
+
+func ext۰syscall۰Sysctl(fr *frame, args []value) value {
+	r, err := syscall.Sysctl(args[0].(string))
+	return tuple{r, wrapError(err)}
+}
+
+func ext۰syscall۰SysctlUint32(fr *frame, args []value) value {
+	r, err := syscall.SysctlUint32(args[0].(string))
+	return tuple{r, wrapError(err)}
+}
diff --git a/third_party/go.tools/go/ssa/interp/external_plan9.go b/third_party/go.tools/go/ssa/interp/external_plan9.go
new file mode 100644
index 0000000..05d02d5
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/external_plan9.go
@@ -0,0 +1,47 @@
+// Copyright 2013 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 interp
+
+import "syscall"
+
+func ext۰syscall۰Close(fr *frame, args []value) value {
+	panic("syscall.Close not yet implemented")
+}
+func ext۰syscall۰Fstat(fr *frame, args []value) value {
+	panic("syscall.Fstat not yet implemented")
+}
+func ext۰syscall۰Kill(fr *frame, args []value) value {
+	panic("syscall.Kill not yet implemented")
+}
+func ext۰syscall۰Lstat(fr *frame, args []value) value {
+	panic("syscall.Lstat not yet implemented")
+}
+func ext۰syscall۰Open(fr *frame, args []value) value {
+	panic("syscall.Open not yet implemented")
+}
+func ext۰syscall۰ParseDirent(fr *frame, args []value) value {
+	panic("syscall.ParseDirent not yet implemented")
+}
+func ext۰syscall۰Read(fr *frame, args []value) value {
+	panic("syscall.Read not yet implemented")
+}
+func ext۰syscall۰ReadDirent(fr *frame, args []value) value {
+	panic("syscall.ReadDirent not yet implemented")
+}
+func ext۰syscall۰Stat(fr *frame, args []value) value {
+	panic("syscall.Stat not yet implemented")
+}
+func ext۰syscall۰Write(fr *frame, args []value) value {
+	// func Write(fd int, p []byte) (n int, err error)
+	n, err := write(args[0].(int), valueToBytes(args[1]))
+	return tuple{n, wrapError(err)}
+}
+func ext۰syscall۰RawSyscall(fr *frame, args []value) value {
+	return tuple{^uintptr(0), uintptr(0), uintptr(0)}
+}
+
+func syswrite(fd int, b []byte) (int, error) {
+	return syscall.Write(fd, b)
+}
diff --git a/third_party/go.tools/go/ssa/interp/external_unix.go b/third_party/go.tools/go/ssa/interp/external_unix.go
new file mode 100644
index 0000000..c482eab
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/external_unix.go
@@ -0,0 +1,132 @@
+// Copyright 2013 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.
+
+// +build !windows,!plan9
+
+package interp
+
+import "syscall"
+
+func fillStat(st *syscall.Stat_t, stat structure) {
+	stat[0] = st.Dev
+	stat[1] = st.Ino
+	stat[2] = st.Nlink
+	stat[3] = st.Mode
+	stat[4] = st.Uid
+	stat[5] = st.Gid
+
+	stat[7] = st.Rdev
+	stat[8] = st.Size
+	stat[9] = st.Blksize
+	stat[10] = st.Blocks
+	// TODO(adonovan): fix: copy Timespecs.
+	// stat[11] = st.Atim
+	// stat[12] = st.Mtim
+	// stat[13] = st.Ctim
+}
+
+func ext۰syscall۰Close(fr *frame, args []value) value {
+	// func Close(fd int) (err error)
+	return wrapError(syscall.Close(args[0].(int)))
+}
+
+func ext۰syscall۰Fstat(fr *frame, args []value) value {
+	// func Fstat(fd int, stat *Stat_t) (err error)
+	fd := args[0].(int)
+	stat := (*args[1].(*value)).(structure)
+
+	var st syscall.Stat_t
+	err := syscall.Fstat(fd, &st)
+	fillStat(&st, stat)
+	return wrapError(err)
+}
+
+func ext۰syscall۰ReadDirent(fr *frame, args []value) value {
+	// func ReadDirent(fd int, buf []byte) (n int, err error)
+	fd := args[0].(int)
+	p := args[1].([]value)
+	b := make([]byte, len(p))
+	n, err := syscall.ReadDirent(fd, b)
+	for i := 0; i < n; i++ {
+		p[i] = b[i]
+	}
+	return tuple{n, wrapError(err)}
+}
+
+func ext۰syscall۰Kill(fr *frame, args []value) value {
+	// func Kill(pid int, sig Signal) (err error)
+	return wrapError(syscall.Kill(args[0].(int), syscall.Signal(args[1].(int))))
+}
+
+func ext۰syscall۰Lstat(fr *frame, args []value) value {
+	// func Lstat(name string, stat *Stat_t) (err error)
+	name := args[0].(string)
+	stat := (*args[1].(*value)).(structure)
+
+	var st syscall.Stat_t
+	err := syscall.Lstat(name, &st)
+	fillStat(&st, stat)
+	return wrapError(err)
+}
+
+func ext۰syscall۰Open(fr *frame, args []value) value {
+	// func Open(path string, mode int, perm uint32) (fd int, err error) {
+	path := args[0].(string)
+	mode := args[1].(int)
+	perm := args[2].(uint32)
+	fd, err := syscall.Open(path, mode, perm)
+	return tuple{fd, wrapError(err)}
+}
+
+func ext۰syscall۰ParseDirent(fr *frame, args []value) value {
+	// func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string)
+	max := args[1].(int)
+	var names []string
+	for _, iname := range args[2].([]value) {
+		names = append(names, iname.(string))
+	}
+	consumed, count, newnames := syscall.ParseDirent(valueToBytes(args[0]), max, names)
+	var inewnames []value
+	for _, newname := range newnames {
+		inewnames = append(inewnames, newname)
+	}
+	return tuple{consumed, count, inewnames}
+}
+
+func ext۰syscall۰Read(fr *frame, args []value) value {
+	// func Read(fd int, p []byte) (n int, err error)
+	fd := args[0].(int)
+	p := args[1].([]value)
+	b := make([]byte, len(p))
+	n, err := syscall.Read(fd, b)
+	for i := 0; i < n; i++ {
+		p[i] = b[i]
+	}
+	return tuple{n, wrapError(err)}
+}
+
+func ext۰syscall۰Stat(fr *frame, args []value) value {
+	// func Stat(name string, stat *Stat_t) (err error)
+	name := args[0].(string)
+	stat := (*args[1].(*value)).(structure)
+
+	var st syscall.Stat_t
+	err := syscall.Stat(name, &st)
+	fillStat(&st, stat)
+	return wrapError(err)
+}
+
+func ext۰syscall۰Write(fr *frame, args []value) value {
+	// func Write(fd int, p []byte) (n int, err error)
+	n, err := write(args[0].(int), valueToBytes(args[1]))
+	return tuple{n, wrapError(err)}
+}
+
+func ext۰syscall۰RawSyscall(fr *frame, args []value) value {
+	return tuple{uintptr(0), uintptr(0), uintptr(syscall.ENOSYS)}
+}
+
+func syswrite(fd int, b []byte) (int, error) {
+	return syscall.Write(fd, b)
+}
diff --git a/third_party/go.tools/go/ssa/interp/external_windows.go b/third_party/go.tools/go/ssa/interp/external_windows.go
new file mode 100644
index 0000000..ef28a37
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/external_windows.go
@@ -0,0 +1,44 @@
+// Copyright 2013 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 interp
+
+import "syscall"
+
+func ext۰syscall۰Close(fr *frame, args []value) value {
+	panic("syscall.Close not yet implemented")
+}
+func ext۰syscall۰Fstat(fr *frame, args []value) value {
+	panic("syscall.Fstat not yet implemented")
+}
+func ext۰syscall۰Kill(fr *frame, args []value) value {
+	panic("syscall.Kill not yet implemented")
+}
+func ext۰syscall۰Lstat(fr *frame, args []value) value {
+	panic("syscall.Lstat not yet implemented")
+}
+func ext۰syscall۰Open(fr *frame, args []value) value {
+	panic("syscall.Open not yet implemented")
+}
+func ext۰syscall۰ParseDirent(fr *frame, args []value) value {
+	panic("syscall.ParseDirent not yet implemented")
+}
+func ext۰syscall۰Read(fr *frame, args []value) value {
+	panic("syscall.Read not yet implemented")
+}
+func ext۰syscall۰ReadDirent(fr *frame, args []value) value {
+	panic("syscall.ReadDirent not yet implemented")
+}
+func ext۰syscall۰Stat(fr *frame, args []value) value {
+	panic("syscall.Stat not yet implemented")
+}
+func ext۰syscall۰Write(fr *frame, args []value) value {
+	panic("syscall.Write not yet implemented")
+}
+func ext۰syscall۰RawSyscall(fr *frame, args []value) value {
+	return tuple{uintptr(0), uintptr(0), uintptr(syscall.ENOSYS)}
+}
+func syswrite(fd int, b []byte) (int, error) {
+	panic("syswrite not yet implemented")
+}
diff --git a/third_party/go.tools/go/ssa/interp/interp.go b/third_party/go.tools/go/ssa/interp/interp.go
new file mode 100644
index 0000000..773e7ee
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/interp.go
@@ -0,0 +1,744 @@
+// Copyright 2013 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 ssa/interp defines an interpreter for the SSA
+// representation of Go programs.
+//
+// This interpreter is provided as an adjunct for testing the SSA
+// construction algorithm.  Its purpose is to provide a minimal
+// metacircular implementation of the dynamic semantics of each SSA
+// instruction.  It is not, and will never be, a production-quality Go
+// interpreter.
+//
+// The following is a partial list of Go features that are currently
+// unsupported or incomplete in the interpreter.
+//
+// * Unsafe operations, including all uses of unsafe.Pointer, are
+// impossible to support given the "boxed" value representation we
+// have chosen.
+//
+// * The reflect package is only partially implemented.
+//
+// * "sync/atomic" operations are not currently atomic due to the
+// "boxed" value representation: it is not possible to read, modify
+// and write an interface value atomically.  As a consequence, Mutexes
+// are currently broken.  TODO(adonovan): provide a metacircular
+// implementation of Mutex avoiding the broken atomic primitives.
+//
+// * recover is only partially implemented.  Also, the interpreter
+// makes no attempt to distinguish target panics from interpreter
+// crashes.
+//
+// * map iteration is asymptotically inefficient.
+//
+// * the sizes of the int, uint and uintptr types in the target
+// program are assumed to be the same as those of the interpreter
+// itself.
+//
+// * all values occupy space, even those of types defined by the spec
+// to have zero size, e.g. struct{}.  This can cause asymptotic
+// performance degradation.
+//
+// * os.Exit is implemented using panic, causing deferred functions to
+// run.
+package interp
+
+import (
+	"fmt"
+	"go/token"
+	"os"
+	"reflect"
+	"runtime"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+type continuation int
+
+const (
+	kNext continuation = iota
+	kReturn
+	kJump
+)
+
+// Mode is a bitmask of options affecting the interpreter.
+type Mode uint
+
+const (
+	DisableRecover Mode = 1 << iota // Disable recover() in target programs; show interpreter crash instead.
+	EnableTracing                   // Print a trace of all instructions as they are interpreted.
+)
+
+type methodSet map[string]*ssa.Function
+
+// State shared between all interpreted goroutines.
+type interpreter struct {
+	osArgs             []value              // the value of os.Args
+	prog               *ssa.Program         // the SSA program
+	globals            map[ssa.Value]*value // addresses of global variables (immutable)
+	mode               Mode                 // interpreter options
+	reflectPackage     *ssa.Package         // the fake reflect package
+	errorMethods       methodSet            // the method set of reflect.error, which implements the error interface.
+	rtypeMethods       methodSet            // the method set of rtype, which implements the reflect.Type interface.
+	runtimeErrorString types.Type           // the runtime.errorString type
+	sizes              types.Sizes          // the effective type-sizing function
+}
+
+type deferred struct {
+	fn    value
+	args  []value
+	instr *ssa.Defer
+	tail  *deferred
+}
+
+type frame struct {
+	i                *interpreter
+	caller           *frame
+	fn               *ssa.Function
+	block, prevBlock *ssa.BasicBlock
+	env              map[ssa.Value]value // dynamic values of SSA variables
+	locals           []value
+	defers           *deferred
+	result           value
+	panicking        bool
+	panic            interface{}
+}
+
+func (fr *frame) get(key ssa.Value) value {
+	switch key := key.(type) {
+	case nil:
+		// Hack; simplifies handling of optional attributes
+		// such as ssa.Slice.{Low,High}.
+		return nil
+	case *ssa.Function, *ssa.Builtin:
+		return key
+	case *ssa.Const:
+		return constValue(key)
+	case *ssa.Global:
+		if r, ok := fr.i.globals[key]; ok {
+			return r
+		}
+	}
+	if r, ok := fr.env[key]; ok {
+		return r
+	}
+	panic(fmt.Sprintf("get: no value for %T: %v", key, key.Name()))
+}
+
+// runDefer runs a deferred call d.
+// It always returns normally, but may set or clear fr.panic.
+//
+func (fr *frame) runDefer(d *deferred) {
+	if fr.i.mode&EnableTracing != 0 {
+		fmt.Fprintf(os.Stderr, "%s: invoking deferred function call\n",
+			fr.i.prog.Fset.Position(d.instr.Pos()))
+	}
+	var ok bool
+	defer func() {
+		if !ok {
+			// Deferred call created a new state of panic.
+			fr.panicking = true
+			fr.panic = recover()
+		}
+	}()
+	call(fr.i, fr, d.instr.Pos(), d.fn, d.args)
+	ok = true
+}
+
+// runDefers executes fr's deferred function calls in LIFO order.
+//
+// On entry, fr.panicking indicates a state of panic; if
+// true, fr.panic contains the panic value.
+//
+// On completion, if a deferred call started a panic, or if no
+// deferred call recovered from a previous state of panic, then
+// runDefers itself panics after the last deferred call has run.
+//
+// If there was no initial state of panic, or it was recovered from,
+// runDefers returns normally.
+//
+func (fr *frame) runDefers() {
+	for d := fr.defers; d != nil; d = d.tail {
+		fr.runDefer(d)
+	}
+	fr.defers = nil
+	if fr.panicking {
+		panic(fr.panic) // new panic, or still panicking
+	}
+}
+
+// lookupMethod returns the method set for type typ, which may be one
+// of the interpreter's fake types.
+func lookupMethod(i *interpreter, typ types.Type, meth *types.Func) *ssa.Function {
+	switch typ {
+	case rtypeType:
+		return i.rtypeMethods[meth.Id()]
+	case errorType:
+		return i.errorMethods[meth.Id()]
+	}
+	return i.prog.LookupMethod(typ, meth.Pkg(), meth.Name())
+}
+
+// visitInstr interprets a single ssa.Instruction within the activation
+// record frame.  It returns a continuation value indicating where to
+// read the next instruction from.
+func visitInstr(fr *frame, instr ssa.Instruction) continuation {
+	switch instr := instr.(type) {
+	case *ssa.DebugRef:
+		// no-op
+
+	case *ssa.UnOp:
+		fr.env[instr] = unop(instr, fr.get(instr.X))
+
+	case *ssa.BinOp:
+		fr.env[instr] = binop(instr.Op, instr.X.Type(), fr.get(instr.X), fr.get(instr.Y))
+
+	case *ssa.Call:
+		fn, args := prepareCall(fr, &instr.Call)
+		fr.env[instr] = call(fr.i, fr, instr.Pos(), fn, args)
+
+	case *ssa.ChangeInterface:
+		fr.env[instr] = fr.get(instr.X)
+
+	case *ssa.ChangeType:
+		fr.env[instr] = fr.get(instr.X) // (can't fail)
+
+	case *ssa.Convert:
+		fr.env[instr] = conv(instr.Type(), instr.X.Type(), fr.get(instr.X))
+
+	case *ssa.MakeInterface:
+		fr.env[instr] = iface{t: instr.X.Type(), v: fr.get(instr.X)}
+
+	case *ssa.Extract:
+		fr.env[instr] = fr.get(instr.Tuple).(tuple)[instr.Index]
+
+	case *ssa.Slice:
+		fr.env[instr] = slice(fr.get(instr.X), fr.get(instr.Low), fr.get(instr.High), fr.get(instr.Max))
+
+	case *ssa.Return:
+		switch len(instr.Results) {
+		case 0:
+		case 1:
+			fr.result = fr.get(instr.Results[0])
+		default:
+			var res []value
+			for _, r := range instr.Results {
+				res = append(res, fr.get(r))
+			}
+			fr.result = tuple(res)
+		}
+		fr.block = nil
+		return kReturn
+
+	case *ssa.RunDefers:
+		fr.runDefers()
+
+	case *ssa.Panic:
+		panic(targetPanic{fr.get(instr.X)})
+
+	case *ssa.Send:
+		fr.get(instr.Chan).(chan value) <- copyVal(fr.get(instr.X))
+
+	case *ssa.Store:
+		*fr.get(instr.Addr).(*value) = copyVal(fr.get(instr.Val))
+
+	case *ssa.If:
+		succ := 1
+		if fr.get(instr.Cond).(bool) {
+			succ = 0
+		}
+		fr.prevBlock, fr.block = fr.block, fr.block.Succs[succ]
+		return kJump
+
+	case *ssa.Jump:
+		fr.prevBlock, fr.block = fr.block, fr.block.Succs[0]
+		return kJump
+
+	case *ssa.Defer:
+		fn, args := prepareCall(fr, &instr.Call)
+		fr.defers = &deferred{
+			fn:    fn,
+			args:  args,
+			instr: instr,
+			tail:  fr.defers,
+		}
+
+	case *ssa.Go:
+		fn, args := prepareCall(fr, &instr.Call)
+		go call(fr.i, nil, instr.Pos(), fn, args)
+
+	case *ssa.MakeChan:
+		fr.env[instr] = make(chan value, asInt(fr.get(instr.Size)))
+
+	case *ssa.Alloc:
+		var addr *value
+		if instr.Heap {
+			// new
+			addr = new(value)
+			fr.env[instr] = addr
+		} else {
+			// local
+			addr = fr.env[instr].(*value)
+		}
+		*addr = zero(deref(instr.Type()))
+
+	case *ssa.MakeSlice:
+		slice := make([]value, asInt(fr.get(instr.Cap)))
+		tElt := instr.Type().Underlying().(*types.Slice).Elem()
+		for i := range slice {
+			slice[i] = zero(tElt)
+		}
+		fr.env[instr] = slice[:asInt(fr.get(instr.Len))]
+
+	case *ssa.MakeMap:
+		reserve := 0
+		if instr.Reserve != nil {
+			reserve = asInt(fr.get(instr.Reserve))
+		}
+		fr.env[instr] = makeMap(instr.Type().Underlying().(*types.Map).Key(), reserve)
+
+	case *ssa.Range:
+		fr.env[instr] = rangeIter(fr.get(instr.X), instr.X.Type())
+
+	case *ssa.Next:
+		fr.env[instr] = fr.get(instr.Iter).(iter).next()
+
+	case *ssa.FieldAddr:
+		x := fr.get(instr.X)
+		fr.env[instr] = &(*x.(*value)).(structure)[instr.Field]
+
+	case *ssa.Field:
+		fr.env[instr] = copyVal(fr.get(instr.X).(structure)[instr.Field])
+
+	case *ssa.IndexAddr:
+		x := fr.get(instr.X)
+		idx := fr.get(instr.Index)
+		switch x := x.(type) {
+		case []value:
+			fr.env[instr] = &x[asInt(idx)]
+		case *value: // *array
+			fr.env[instr] = &(*x).(array)[asInt(idx)]
+		default:
+			panic(fmt.Sprintf("unexpected x type in IndexAddr: %T", x))
+		}
+
+	case *ssa.Index:
+		fr.env[instr] = copyVal(fr.get(instr.X).(array)[asInt(fr.get(instr.Index))])
+
+	case *ssa.Lookup:
+		fr.env[instr] = lookup(instr, fr.get(instr.X), fr.get(instr.Index))
+
+	case *ssa.MapUpdate:
+		m := fr.get(instr.Map)
+		key := fr.get(instr.Key)
+		v := fr.get(instr.Value)
+		switch m := m.(type) {
+		case map[value]value:
+			m[key] = v
+		case *hashmap:
+			m.insert(key.(hashable), v)
+		default:
+			panic(fmt.Sprintf("illegal map type: %T", m))
+		}
+
+	case *ssa.TypeAssert:
+		fr.env[instr] = typeAssert(fr.i, instr, fr.get(instr.X).(iface))
+
+	case *ssa.MakeClosure:
+		var bindings []value
+		for _, binding := range instr.Bindings {
+			bindings = append(bindings, fr.get(binding))
+		}
+		fr.env[instr] = &closure{instr.Fn.(*ssa.Function), bindings}
+
+	case *ssa.Phi:
+		for i, pred := range instr.Block().Preds {
+			if fr.prevBlock == pred {
+				fr.env[instr] = fr.get(instr.Edges[i])
+				break
+			}
+		}
+
+	case *ssa.Select:
+		var cases []reflect.SelectCase
+		if !instr.Blocking {
+			cases = append(cases, reflect.SelectCase{
+				Dir: reflect.SelectDefault,
+			})
+		}
+		for _, state := range instr.States {
+			var dir reflect.SelectDir
+			if state.Dir == types.RecvOnly {
+				dir = reflect.SelectRecv
+			} else {
+				dir = reflect.SelectSend
+			}
+			var send reflect.Value
+			if state.Send != nil {
+				send = reflect.ValueOf(fr.get(state.Send))
+			}
+			cases = append(cases, reflect.SelectCase{
+				Dir:  dir,
+				Chan: reflect.ValueOf(fr.get(state.Chan)),
+				Send: send,
+			})
+		}
+		chosen, recv, recvOk := reflect.Select(cases)
+		if !instr.Blocking {
+			chosen-- // default case should have index -1.
+		}
+		r := tuple{chosen, recvOk}
+		for i, st := range instr.States {
+			if st.Dir == types.RecvOnly {
+				var v value
+				if i == chosen && recvOk {
+					// No need to copy since send makes an unaliased copy.
+					v = recv.Interface().(value)
+				} else {
+					v = zero(st.Chan.Type().Underlying().(*types.Chan).Elem())
+				}
+				r = append(r, v)
+			}
+		}
+		fr.env[instr] = r
+
+	default:
+		panic(fmt.Sprintf("unexpected instruction: %T", instr))
+	}
+
+	// if val, ok := instr.(ssa.Value); ok {
+	// 	fmt.Println(toString(fr.env[val])) // debugging
+	// }
+
+	return kNext
+}
+
+// prepareCall determines the function value and argument values for a
+// function call in a Call, Go or Defer instruction, performing
+// interface method lookup if needed.
+//
+func prepareCall(fr *frame, call *ssa.CallCommon) (fn value, args []value) {
+	v := fr.get(call.Value)
+	if call.Method == nil {
+		// Function call.
+		fn = v
+	} else {
+		// Interface method invocation.
+		recv := v.(iface)
+		if recv.t == nil {
+			panic("method invoked on nil interface")
+		}
+		if f := lookupMethod(fr.i, recv.t, call.Method); f == nil {
+			// Unreachable in well-typed programs.
+			panic(fmt.Sprintf("method set for dynamic type %v does not contain %s", recv.t, call.Method))
+		} else {
+			fn = f
+		}
+		args = append(args, copyVal(recv.v))
+	}
+	for _, arg := range call.Args {
+		args = append(args, fr.get(arg))
+	}
+	return
+}
+
+// call interprets a call to a function (function, builtin or closure)
+// fn with arguments args, returning its result.
+// callpos is the position of the callsite.
+//
+func call(i *interpreter, caller *frame, callpos token.Pos, fn value, args []value) value {
+	switch fn := fn.(type) {
+	case *ssa.Function:
+		if fn == nil {
+			panic("call of nil function") // nil of func type
+		}
+		return callSSA(i, caller, callpos, fn, args, nil)
+	case *closure:
+		return callSSA(i, caller, callpos, fn.Fn, args, fn.Env)
+	case *ssa.Builtin:
+		return callBuiltin(caller, callpos, fn, args)
+	}
+	panic(fmt.Sprintf("cannot call %T", fn))
+}
+
+func loc(fset *token.FileSet, pos token.Pos) string {
+	if pos == token.NoPos {
+		return ""
+	}
+	return " at " + fset.Position(pos).String()
+}
+
+// callSSA interprets a call to function fn with arguments args,
+// and lexical environment env, returning its result.
+// callpos is the position of the callsite.
+//
+func callSSA(i *interpreter, caller *frame, callpos token.Pos, fn *ssa.Function, args []value, env []value) value {
+	if i.mode&EnableTracing != 0 {
+		fset := fn.Prog.Fset
+		// TODO(adonovan): fix: loc() lies for external functions.
+		fmt.Fprintf(os.Stderr, "Entering %s%s.\n", fn, loc(fset, fn.Pos()))
+		suffix := ""
+		if caller != nil {
+			suffix = ", resuming " + caller.fn.String() + loc(fset, callpos)
+		}
+		defer fmt.Fprintf(os.Stderr, "Leaving %s%s.\n", fn, suffix)
+	}
+	fr := &frame{
+		i:      i,
+		caller: caller, // for panic/recover
+		fn:     fn,
+	}
+	if fn.Parent() == nil {
+		name := fn.String()
+		if ext := externals[name]; ext != nil {
+			if i.mode&EnableTracing != 0 {
+				fmt.Fprintln(os.Stderr, "\t(external)")
+			}
+			return ext(fr, args)
+		}
+		if fn.Blocks == nil {
+			panic("no code for function: " + name)
+		}
+	}
+	fr.env = make(map[ssa.Value]value)
+	fr.block = fn.Blocks[0]
+	fr.locals = make([]value, len(fn.Locals))
+	for i, l := range fn.Locals {
+		fr.locals[i] = zero(deref(l.Type()))
+		fr.env[l] = &fr.locals[i]
+	}
+	for i, p := range fn.Params {
+		fr.env[p] = args[i]
+	}
+	for i, fv := range fn.FreeVars {
+		fr.env[fv] = env[i]
+	}
+	for fr.block != nil {
+		runFrame(fr)
+	}
+	// Destroy the locals to avoid accidental use after return.
+	for i := range fn.Locals {
+		fr.locals[i] = bad{}
+	}
+	return fr.result
+}
+
+// runFrame executes SSA instructions starting at fr.block and
+// continuing until a return, a panic, or a recovered panic.
+//
+// After a panic, runFrame panics.
+//
+// After a normal return, fr.result contains the result of the call
+// and fr.block is nil.
+//
+// A recovered panic in a function without named return parameters
+// (NRPs) becomes a normal return of the zero value of the function's
+// result type.
+//
+// After a recovered panic in a function with NRPs, fr.result is
+// undefined and fr.block contains the block at which to resume
+// control.
+//
+func runFrame(fr *frame) {
+	defer func() {
+		if fr.block == nil {
+			return // normal return
+		}
+		if fr.i.mode&DisableRecover != 0 {
+			return // let interpreter crash
+		}
+		fr.panicking = true
+		fr.panic = recover()
+		if fr.i.mode&EnableTracing != 0 {
+			fmt.Fprintf(os.Stderr, "Panicking: %T %v.\n", fr.panic, fr.panic)
+		}
+		fr.runDefers()
+		fr.block = fr.fn.Recover
+	}()
+
+	for {
+		if fr.i.mode&EnableTracing != 0 {
+			fmt.Fprintf(os.Stderr, ".%s:\n", fr.block)
+		}
+	block:
+		for _, instr := range fr.block.Instrs {
+			if fr.i.mode&EnableTracing != 0 {
+				if v, ok := instr.(ssa.Value); ok {
+					fmt.Fprintln(os.Stderr, "\t", v.Name(), "=", instr)
+				} else {
+					fmt.Fprintln(os.Stderr, "\t", instr)
+				}
+			}
+			switch visitInstr(fr, instr) {
+			case kReturn:
+				return
+			case kNext:
+				// no-op
+			case kJump:
+				break block
+			}
+		}
+	}
+}
+
+// doRecover implements the recover() built-in.
+func doRecover(caller *frame) value {
+	// recover() must be exactly one level beneath the deferred
+	// function (two levels beneath the panicking function) to
+	// have any effect.  Thus we ignore both "defer recover()" and
+	// "defer f() -> g() -> recover()".
+	if caller.i.mode&DisableRecover == 0 &&
+		caller != nil && !caller.panicking &&
+		caller.caller != nil && caller.caller.panicking {
+		caller.caller.panicking = false
+		p := caller.caller.panic
+		caller.caller.panic = nil
+		switch p := p.(type) {
+		case targetPanic:
+			// The target program explicitly called panic().
+			return p.v
+		case runtime.Error:
+			// The interpreter encountered a runtime error.
+			return iface{caller.i.runtimeErrorString, p.Error()}
+		case string:
+			// The interpreter explicitly called panic().
+			return iface{caller.i.runtimeErrorString, p}
+		default:
+			panic(fmt.Sprintf("unexpected panic type %T in target call to recover()", p))
+		}
+	}
+	return iface{}
+}
+
+// setGlobal sets the value of a system-initialized global variable.
+func setGlobal(i *interpreter, pkg *ssa.Package, name string, v value) {
+	if g, ok := i.globals[pkg.Var(name)]; ok {
+		*g = v
+		return
+	}
+	panic("no global variable: " + pkg.Object.Path() + "." + name)
+}
+
+var environ []value
+
+func init() {
+	for _, s := range os.Environ() {
+		environ = append(environ, s)
+	}
+	environ = append(environ, "GOSSAINTERP=1")
+	environ = append(environ, "GOARCH="+runtime.GOARCH)
+}
+
+// Interpret interprets the Go program whose main package is mainpkg.
+// mode specifies various interpreter options.  filename and args are
+// the initial values of os.Args for the target program.  sizes is the
+// effective type-sizing function for this program.
+//
+// Interpret returns the exit code of the program: 2 for panic (like
+// gc does), or the argument to os.Exit for normal termination.
+//
+// The SSA program must include the "runtime" package.
+//
+func Interpret(mainpkg *ssa.Package, mode Mode, sizes types.Sizes, filename string, args []string) (exitCode int) {
+	i := &interpreter{
+		prog:    mainpkg.Prog,
+		globals: make(map[ssa.Value]*value),
+		mode:    mode,
+		sizes:   sizes,
+	}
+	runtimePkg := i.prog.ImportedPackage("runtime")
+	if runtimePkg == nil {
+		panic("ssa.Program doesn't include runtime package")
+	}
+	i.runtimeErrorString = runtimePkg.Type("errorString").Object().Type()
+
+	initReflect(i)
+
+	i.osArgs = append(i.osArgs, filename)
+	for _, arg := range args {
+		i.osArgs = append(i.osArgs, arg)
+	}
+
+	for _, pkg := range i.prog.AllPackages() {
+		// Initialize global storage.
+		for _, m := range pkg.Members {
+			switch v := m.(type) {
+			case *ssa.Global:
+				cell := zero(deref(v.Type()))
+				i.globals[v] = &cell
+			}
+		}
+
+		// Ad-hoc initialization for magic system variables.
+		switch pkg.Object.Path() {
+		case "syscall":
+			setGlobal(i, pkg, "envs", environ)
+
+		case "runtime":
+			sz := sizes.Sizeof(pkg.Object.Scope().Lookup("MemStats").Type())
+			setGlobal(i, pkg, "sizeof_C_MStats", uintptr(sz))
+
+			// Delete the bodies of almost all "runtime" functions since they're magic.
+			// A missing intrinsic leads to a very clear error.
+			for _, mem := range pkg.Members {
+				if fn, ok := mem.(*ssa.Function); ok {
+					switch fn.Name() {
+					case "GOROOT", "gogetenv":
+						// keep
+					default:
+						fn.Blocks = nil
+					}
+				}
+			}
+		}
+	}
+
+	// Top-level error handler.
+	exitCode = 2
+	defer func() {
+		if exitCode != 2 || i.mode&DisableRecover != 0 {
+			return
+		}
+		switch p := recover().(type) {
+		case exitPanic:
+			exitCode = int(p)
+			return
+		case targetPanic:
+			fmt.Fprintln(os.Stderr, "panic:", toString(p.v))
+		case runtime.Error:
+			fmt.Fprintln(os.Stderr, "panic:", p.Error())
+		case string:
+			fmt.Fprintln(os.Stderr, "panic:", p)
+		default:
+			fmt.Fprintf(os.Stderr, "panic: unexpected type: %T\n", p)
+		}
+
+		// TODO(adonovan): dump panicking interpreter goroutine?
+		// buf := make([]byte, 0x10000)
+		// runtime.Stack(buf, false)
+		// fmt.Fprintln(os.Stderr, string(buf))
+		// (Or dump panicking target goroutine?)
+	}()
+
+	// Run!
+	call(i, nil, token.NoPos, mainpkg.Func("init"), nil)
+	if mainFn := mainpkg.Func("main"); mainFn != nil {
+		call(i, nil, token.NoPos, mainFn, nil)
+		exitCode = 0
+	} else {
+		fmt.Fprintln(os.Stderr, "No main function.")
+		exitCode = 1
+	}
+	return
+}
+
+// deref returns a pointer's element type; otherwise it returns typ.
+// TODO(adonovan): Import from ssa?
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
diff --git a/third_party/go.tools/go/ssa/interp/interp_test.go b/third_party/go.tools/go/ssa/interp/interp_test.go
new file mode 100644
index 0000000..7c30807
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/interp_test.go
@@ -0,0 +1,365 @@
+// Copyright 2013 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.
+
+// +build !windows,!plan9
+
+package interp_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/build"
+	"os"
+	"path/filepath"
+	"strings"
+	"testing"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/ssa/interp"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// Each line contains a space-separated list of $GOROOT/test/
+// filenames comprising the main package of a program.
+// They are ordered quickest-first, roughly.
+//
+// TODO(adonovan): integrate into the $GOROOT/test driver scripts,
+// golden file checking, etc.
+var gorootTestTests = []string{
+	"235.go",
+	"alias1.go",
+	"chancap.go",
+	"func5.go",
+	"func6.go",
+	"func7.go",
+	"func8.go",
+	"helloworld.go",
+	"varinit.go",
+	"escape3.go",
+	"initcomma.go",
+	"cmp.go",
+	"compos.go",
+	"turing.go",
+	"indirect.go",
+	"complit.go",
+	"for.go",
+	"struct0.go",
+	"intcvt.go",
+	"printbig.go",
+	"deferprint.go",
+	"escape.go",
+	"range.go",
+	"const4.go",
+	"float_lit.go",
+	"bigalg.go",
+	"decl.go",
+	"if.go",
+	"named.go",
+	"bigmap.go",
+	"func.go",
+	"reorder2.go",
+	"closure.go",
+	"gc.go",
+	"simassign.go",
+	"iota.go",
+	"nilptr2.go",
+	"goprint.go", // doesn't actually assert anything (cmpout)
+	"utf.go",
+	"method.go",
+	"char_lit.go",
+	"env.go",
+	"int_lit.go",
+	"string_lit.go",
+	"defer.go",
+	"typeswitch.go",
+	"stringrange.go",
+	"reorder.go",
+	"method3.go",
+	"literal.go",
+	"nul1.go", // doesn't actually assert anything (errorcheckoutput)
+	"zerodivide.go",
+	"convert.go",
+	"convT2X.go",
+	"switch.go",
+	"initialize.go",
+	"ddd.go",
+	"blank.go", // partly disabled
+	"map.go",
+	"closedchan.go",
+	"divide.go",
+	"rename.go",
+	"const3.go",
+	"nil.go",
+	"recover.go", // reflection parts disabled
+	"recover1.go",
+	"recover2.go",
+	"recover3.go",
+	"typeswitch1.go",
+	"floatcmp.go",
+	"crlf.go", // doesn't actually assert anything (runoutput)
+	// Slow tests follow.
+	"bom.go", // ~1.7s
+	"gc1.go", // ~1.7s
+	"cmplxdivide.go cmplxdivide1.go", // ~2.4s
+
+	// Working, but not worth enabling:
+	// "append.go",    // works, but slow (15s).
+	// "gc2.go",       // works, but slow, and cheats on the memory check.
+	// "sigchld.go",   // works, but only on POSIX.
+	// "peano.go",     // works only up to n=9, and slow even then.
+	// "stack.go",     // works, but too slow (~30s) by default.
+	// "solitaire.go", // works, but too slow (~30s).
+	// "const.go",     // works but for but one bug: constant folder doesn't consider representations.
+	// "init1.go",     // too slow (80s) and not that interesting. Cheats on ReadMemStats check too.
+	// "rotate.go rotate0.go", // emits source for a test
+	// "rotate.go rotate1.go", // emits source for a test
+	// "rotate.go rotate2.go", // emits source for a test
+	// "rotate.go rotate3.go", // emits source for a test
+	// "64bit.go",             // emits source for a test
+	// "run.go",               // test driver, not a test.
+
+	// Broken.  TODO(adonovan): fix.
+	// copy.go         // very slow; but with N=4 quickly crashes, slice index out of range.
+	// nilptr.go       // interp: V > uintptr not implemented. Slow test, lots of mem
+	// args.go         // works, but requires specific os.Args from the driver.
+	// index.go        // a template, not a real test.
+	// mallocfin.go    // SetFinalizer not implemented.
+
+	// TODO(adonovan): add tests from $GOROOT/test/* subtrees:
+	// bench chan bugs fixedbugs interface ken.
+}
+
+// These are files in go.tools/go/ssa/interp/testdata/.
+var testdataTests = []string{
+	"boundmeth.go",
+	"complit.go",
+	"coverage.go",
+	"defer.go",
+	"fieldprom.go",
+	"ifaceconv.go",
+	"ifaceprom.go",
+	"initorder.go",
+	"methprom.go",
+	"mrvchain.go",
+	"range.go",
+	"recover.go",
+	"static.go",
+	"callstack.go",
+}
+
+// These are files and packages in $GOROOT/src/.
+var gorootSrcTests = []string{
+	"encoding/ascii85",
+	"encoding/csv",
+	"encoding/hex",
+	"encoding/pem",
+	"hash/crc32",
+	// "testing", // TODO(adonovan): implement runtime.Goexit correctly
+	"text/scanner",
+	"unicode",
+
+	// Too slow:
+	// "container/ring",
+	// "hash/adler32",
+
+	// TODO(adonovan): packages with Examples require os.Pipe (unimplemented):
+	// "unicode/utf8",
+	// "log",
+	// "path",
+	// "flag",
+}
+
+type successPredicate func(exitcode int, output string) error
+
+func run(t *testing.T, dir, input string, success successPredicate) bool {
+	fmt.Printf("Input: %s\n", input)
+
+	start := time.Now()
+
+	var inputs []string
+	for _, i := range strings.Split(input, " ") {
+		if strings.HasSuffix(i, ".go") {
+			i = dir + i
+		}
+		inputs = append(inputs, i)
+	}
+
+	conf := loader.Config{SourceImports: true}
+	if _, err := conf.FromArgs(inputs, true); err != nil {
+		t.Errorf("FromArgs(%s) failed: %s", inputs, err)
+		return false
+	}
+
+	conf.Import("runtime")
+
+	// Print a helpful hint if we don't make it to the end.
+	var hint string
+	defer func() {
+		if hint != "" {
+			fmt.Println("FAIL")
+			fmt.Println(hint)
+		} else {
+			fmt.Println("PASS")
+		}
+
+		interp.CapturedOutput = nil
+	}()
+
+	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=CFP %s\n", input)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Errorf("conf.Load(%s) failed: %s", inputs, err)
+		return false
+	}
+
+	prog := ssa.Create(iprog, ssa.SanityCheckFunctions)
+	prog.BuildAll()
+
+	var mainPkg *ssa.Package
+	var initialPkgs []*ssa.Package
+	for _, info := range iprog.InitialPackages() {
+		if info.Pkg.Path() == "runtime" {
+			continue // not an initial package
+		}
+		p := prog.Package(info.Pkg)
+		initialPkgs = append(initialPkgs, p)
+		if mainPkg == nil && p.Func("main") != nil {
+			mainPkg = p
+		}
+	}
+	if mainPkg == nil {
+		testmainPkg := prog.CreateTestMainPackage(initialPkgs...)
+		if testmainPkg == nil {
+			t.Errorf("CreateTestMainPackage(%s) returned nil", mainPkg)
+			return false
+		}
+		if testmainPkg.Func("main") == nil {
+			t.Errorf("synthetic testmain package has no main")
+			return false
+		}
+		mainPkg = testmainPkg
+	}
+
+	var out bytes.Buffer
+	interp.CapturedOutput = &out
+
+	hint = fmt.Sprintf("To trace execution, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=C -run --interp=T %s\n", input)
+	exitCode := interp.Interpret(mainPkg, 0, &types.StdSizes{8, 8}, inputs[0], []string{})
+
+	// The definition of success varies with each file.
+	if err := success(exitCode, out.String()); err != nil {
+		t.Errorf("interp.Interpret(%s) failed: %s", inputs, err)
+		return false
+	}
+
+	hint = "" // call off the hounds
+
+	if false {
+		fmt.Println(input, time.Since(start)) // test profiling
+	}
+
+	return true
+}
+
+const slash = string(os.PathSeparator)
+
+func printFailures(failures []string) {
+	if failures != nil {
+		fmt.Println("The following tests failed:")
+		for _, f := range failures {
+			fmt.Printf("\t%s\n", f)
+		}
+	}
+}
+
+// The "normal" success predicate.
+func exitsZero(exitcode int, _ string) error {
+	if exitcode != 0 {
+		return fmt.Errorf("exit code was %d", exitcode)
+	}
+	return nil
+}
+
+// TestTestdataFiles runs the interpreter on testdata/*.go.
+func TestTestdataFiles(t *testing.T) {
+	var failures []string
+	for _, input := range testdataTests {
+		if !run(t, "testdata"+slash, input, exitsZero) {
+			failures = append(failures, input)
+		}
+	}
+	printFailures(failures)
+}
+
+// TestGorootTest runs the interpreter on $GOROOT/test/*.go.
+func TestGorootTest(t *testing.T) {
+	if testing.Short() {
+		return // too slow (~30s)
+	}
+
+	var failures []string
+
+	// $GOROOT/tests are also considered a failure if they print "BUG".
+	success := func(exitcode int, output string) error {
+		if exitcode != 0 {
+			return fmt.Errorf("exit code was %d", exitcode)
+		}
+		if strings.Contains(output, "BUG") {
+			return fmt.Errorf("exited zero but output contained 'BUG'")
+		}
+		return nil
+	}
+	for _, input := range gorootTestTests {
+		if !run(t, filepath.Join(build.Default.GOROOT, "test")+slash, input, success) {
+			failures = append(failures, input)
+		}
+	}
+	for _, input := range gorootSrcTests {
+		if !run(t, filepath.Join(build.Default.GOROOT, "src")+slash, input, success) {
+			failures = append(failures, input)
+		}
+	}
+	printFailures(failures)
+}
+
+// TestTestmainPackage runs the interpreter on a synthetic "testmain" package.
+func TestTestmainPackage(t *testing.T) {
+	success := func(exitcode int, output string) error {
+		if exitcode == 0 {
+			return fmt.Errorf("unexpected success")
+		}
+		if !strings.Contains(output, "FAIL: TestFoo") {
+			return fmt.Errorf("missing failure log for TestFoo")
+		}
+		if !strings.Contains(output, "FAIL: TestBar") {
+			return fmt.Errorf("missing failure log for TestBar")
+		}
+		// TODO(adonovan): test benchmarks too
+		return nil
+	}
+	run(t, "testdata"+slash, "a_test.go", success)
+}
+
+// CreateTestMainPackage should return nil if there were no tests.
+func TestNullTestmainPackage(t *testing.T) {
+	var conf loader.Config
+	if err := conf.CreateFromFilenames("", "testdata/b_test.go"); err != nil {
+		t.Fatalf("ParseFile failed: %s", err)
+	}
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("CreatePackages failed: %s", err)
+	}
+	prog := ssa.Create(iprog, ssa.SanityCheckFunctions)
+	mainPkg := prog.Package(iprog.Created[0].Pkg)
+	if mainPkg.Func("main") != nil {
+		t.Fatalf("unexpected main function")
+	}
+	if prog.CreateTestMainPackage(mainPkg) != nil {
+		t.Fatalf("CreateTestMainPackage returned non-nil")
+	}
+}
diff --git a/third_party/go.tools/go/ssa/interp/map.go b/third_party/go.tools/go/ssa/interp/map.go
new file mode 100644
index 0000000..ba77f72
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/map.go
@@ -0,0 +1,113 @@
+// Copyright 2013 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 interp
+
+// Custom hashtable atop map.
+// For use when the key's equivalence relation is not consistent with ==.
+
+// The Go specification doesn't address the atomicity of map operations.
+// The FAQ states that an implementation is permitted to crash on
+// concurrent map access.
+
+import (
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+type hashable interface {
+	hash(t types.Type) int
+	eq(t types.Type, x interface{}) bool
+}
+
+type entry struct {
+	key   hashable
+	value value
+	next  *entry
+}
+
+// A hashtable atop the built-in map.  Since each bucket contains
+// exactly one hash value, there's no need to perform hash-equality
+// tests when walking the linked list.  Rehashing is done by the
+// underlying map.
+type hashmap struct {
+	keyType types.Type
+	table   map[int]*entry
+	length  int // number of entries in map
+}
+
+// makeMap returns an empty initialized map of key type kt,
+// preallocating space for reserve elements.
+func makeMap(kt types.Type, reserve int) value {
+	if usesBuiltinMap(kt) {
+		return make(map[value]value, reserve)
+	}
+	return &hashmap{keyType: kt, table: make(map[int]*entry, reserve)}
+}
+
+// delete removes the association for key k, if any.
+func (m *hashmap) delete(k hashable) {
+	if m != nil {
+		hash := k.hash(m.keyType)
+		head := m.table[hash]
+		if head != nil {
+			if k.eq(m.keyType, head.key) {
+				m.table[hash] = head.next
+				m.length--
+				return
+			}
+			prev := head
+			for e := head.next; e != nil; e = e.next {
+				if k.eq(m.keyType, e.key) {
+					prev.next = e.next
+					m.length--
+					return
+				}
+				prev = e
+			}
+		}
+	}
+}
+
+// lookup returns the value associated with key k, if present, or
+// value(nil) otherwise.
+func (m *hashmap) lookup(k hashable) value {
+	if m != nil {
+		hash := k.hash(m.keyType)
+		for e := m.table[hash]; e != nil; e = e.next {
+			if k.eq(m.keyType, e.key) {
+				return e.value
+			}
+		}
+	}
+	return nil
+}
+
+// insert updates the map to associate key k with value v.  If there
+// was already an association for an eq() (though not necessarily ==)
+// k, the previous key remains in the map and its associated value is
+// updated.
+func (m *hashmap) insert(k hashable, v value) {
+	hash := k.hash(m.keyType)
+	head := m.table[hash]
+	for e := head; e != nil; e = e.next {
+		if k.eq(m.keyType, e.key) {
+			e.value = v
+			return
+		}
+	}
+	m.table[hash] = &entry{
+		key:   k,
+		value: v,
+		next:  head,
+	}
+	m.length++
+}
+
+// len returns the number of key/value associations in the map.
+func (m *hashmap) len() int {
+	if m != nil {
+		return m.length
+	}
+	return 0
+}
diff --git a/third_party/go.tools/go/ssa/interp/ops.go b/third_party/go.tools/go/ssa/interp/ops.go
new file mode 100644
index 0000000..fedae64
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/ops.go
@@ -0,0 +1,1396 @@
+// Copyright 2013 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 interp
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"strings"
+	"sync"
+	"unsafe"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// If the target program panics, the interpreter panics with this type.
+type targetPanic struct {
+	v value
+}
+
+func (p targetPanic) String() string {
+	return toString(p.v)
+}
+
+// If the target program calls exit, the interpreter panics with this type.
+type exitPanic int
+
+// constValue returns the value of the constant with the
+// dynamic type tag appropriate for c.Type().
+func constValue(c *ssa.Const) value {
+	if c.IsNil() {
+		return zero(c.Type()) // typed nil
+	}
+
+	if t, ok := c.Type().Underlying().(*types.Basic); ok {
+		// TODO(adonovan): eliminate untyped constants from SSA form.
+		switch t.Kind() {
+		case types.Bool, types.UntypedBool:
+			return exact.BoolVal(c.Value)
+		case types.Int, types.UntypedInt:
+			// Assume sizeof(int) is same on host and target.
+			return int(c.Int64())
+		case types.Int8:
+			return int8(c.Int64())
+		case types.Int16:
+			return int16(c.Int64())
+		case types.Int32, types.UntypedRune:
+			return int32(c.Int64())
+		case types.Int64:
+			return c.Int64()
+		case types.Uint:
+			// Assume sizeof(uint) is same on host and target.
+			return uint(c.Uint64())
+		case types.Uint8:
+			return uint8(c.Uint64())
+		case types.Uint16:
+			return uint16(c.Uint64())
+		case types.Uint32:
+			return uint32(c.Uint64())
+		case types.Uint64:
+			return c.Uint64()
+		case types.Uintptr:
+			// Assume sizeof(uintptr) is same on host and target.
+			return uintptr(c.Uint64())
+		case types.Float32:
+			return float32(c.Float64())
+		case types.Float64, types.UntypedFloat:
+			return c.Float64()
+		case types.Complex64:
+			return complex64(c.Complex128())
+		case types.Complex128, types.UntypedComplex:
+			return c.Complex128()
+		case types.String, types.UntypedString:
+			if c.Value.Kind() == exact.String {
+				return exact.StringVal(c.Value)
+			}
+			return string(rune(c.Int64()))
+		}
+	}
+
+	panic(fmt.Sprintf("constValue: %s", c))
+}
+
+// asInt converts x, which must be an integer, to an int suitable for
+// use as a slice or array index or operand to make().
+func asInt(x value) int {
+	switch x := x.(type) {
+	case int:
+		return x
+	case int8:
+		return int(x)
+	case int16:
+		return int(x)
+	case int32:
+		return int(x)
+	case int64:
+		return int(x)
+	case uint:
+		return int(x)
+	case uint8:
+		return int(x)
+	case uint16:
+		return int(x)
+	case uint32:
+		return int(x)
+	case uint64:
+		return int(x)
+	case uintptr:
+		return int(x)
+	}
+	panic(fmt.Sprintf("cannot convert %T to int", x))
+}
+
+// asUint64 converts x, which must be an unsigned integer, to a uint64
+// suitable for use as a bitwise shift count.
+func asUint64(x value) uint64 {
+	switch x := x.(type) {
+	case uint:
+		return uint64(x)
+	case uint8:
+		return uint64(x)
+	case uint16:
+		return uint64(x)
+	case uint32:
+		return uint64(x)
+	case uint64:
+		return x
+	case uintptr:
+		return uint64(x)
+	}
+	panic(fmt.Sprintf("cannot convert %T to uint64", x))
+}
+
+// zero returns a new "zero" value of the specified type.
+func zero(t types.Type) value {
+	switch t := t.(type) {
+	case *types.Basic:
+		if t.Kind() == types.UntypedNil {
+			panic("untyped nil has no zero value")
+		}
+		if t.Info()&types.IsUntyped != 0 {
+			// TODO(adonovan): make it an invariant that
+			// this is unreachable.  Currently some
+			// constants have 'untyped' types when they
+			// should be defaulted by the typechecker.
+			t = ssa.DefaultType(t).(*types.Basic)
+		}
+		switch t.Kind() {
+		case types.Bool:
+			return false
+		case types.Int:
+			return int(0)
+		case types.Int8:
+			return int8(0)
+		case types.Int16:
+			return int16(0)
+		case types.Int32:
+			return int32(0)
+		case types.Int64:
+			return int64(0)
+		case types.Uint:
+			return uint(0)
+		case types.Uint8:
+			return uint8(0)
+		case types.Uint16:
+			return uint16(0)
+		case types.Uint32:
+			return uint32(0)
+		case types.Uint64:
+			return uint64(0)
+		case types.Uintptr:
+			return uintptr(0)
+		case types.Float32:
+			return float32(0)
+		case types.Float64:
+			return float64(0)
+		case types.Complex64:
+			return complex64(0)
+		case types.Complex128:
+			return complex128(0)
+		case types.String:
+			return ""
+		case types.UnsafePointer:
+			return unsafe.Pointer(nil)
+		default:
+			panic(fmt.Sprint("zero for unexpected type:", t))
+		}
+	case *types.Pointer:
+		return (*value)(nil)
+	case *types.Array:
+		a := make(array, t.Len())
+		for i := range a {
+			a[i] = zero(t.Elem())
+		}
+		return a
+	case *types.Named:
+		return zero(t.Underlying())
+	case *types.Interface:
+		return iface{} // nil type, methodset and value
+	case *types.Slice:
+		return []value(nil)
+	case *types.Struct:
+		s := make(structure, t.NumFields())
+		for i := range s {
+			s[i] = zero(t.Field(i).Type())
+		}
+		return s
+	case *types.Tuple:
+		if t.Len() == 1 {
+			return zero(t.At(0).Type())
+		}
+		s := make(tuple, t.Len())
+		for i := range s {
+			s[i] = zero(t.At(i).Type())
+		}
+		return s
+	case *types.Chan:
+		return chan value(nil)
+	case *types.Map:
+		if usesBuiltinMap(t.Key()) {
+			return map[value]value(nil)
+		}
+		return (*hashmap)(nil)
+	case *types.Signature:
+		return (*ssa.Function)(nil)
+	}
+	panic(fmt.Sprint("zero: unexpected ", t))
+}
+
+// slice returns x[lo:hi:max].  Any of lo, hi and max may be nil.
+func slice(x, lo, hi, max value) value {
+	var Len, Cap int
+	switch x := x.(type) {
+	case string:
+		Len = len(x)
+	case []value:
+		Len = len(x)
+		Cap = cap(x)
+	case *value: // *array
+		a := (*x).(array)
+		Len = len(a)
+		Cap = cap(a)
+	}
+
+	l := 0
+	if lo != nil {
+		l = asInt(lo)
+	}
+
+	h := Len
+	if hi != nil {
+		h = asInt(hi)
+	}
+
+	m := Cap
+	if max != nil {
+		m = asInt(max)
+	}
+
+	switch x := x.(type) {
+	case string:
+		return x[l:h]
+	case []value:
+		return x[l:h:m]
+	case *value: // *array
+		a := (*x).(array)
+		return []value(a)[l:h:m]
+	}
+	panic(fmt.Sprintf("slice: unexpected X type: %T", x))
+}
+
+// lookup returns x[idx] where x is a map or string.
+func lookup(instr *ssa.Lookup, x, idx value) value {
+	switch x := x.(type) { // map or string
+	case map[value]value, *hashmap:
+		var v value
+		var ok bool
+		switch x := x.(type) {
+		case map[value]value:
+			v, ok = x[idx]
+		case *hashmap:
+			v = x.lookup(idx.(hashable))
+			ok = v != nil
+		}
+		if ok {
+			v = copyVal(v)
+		} else {
+			v = zero(instr.X.Type().Underlying().(*types.Map).Elem())
+		}
+		if instr.CommaOk {
+			v = tuple{v, ok}
+		}
+		return v
+	case string:
+		return x[asInt(idx)]
+	}
+	panic(fmt.Sprintf("unexpected x type in Lookup: %T", x))
+}
+
+// binop implements all arithmetic and logical binary operators for
+// numeric datatypes and strings.  Both operands must have identical
+// dynamic type.
+//
+func binop(op token.Token, t types.Type, x, y value) value {
+	switch op {
+	case token.ADD:
+		switch x.(type) {
+		case int:
+			return x.(int) + y.(int)
+		case int8:
+			return x.(int8) + y.(int8)
+		case int16:
+			return x.(int16) + y.(int16)
+		case int32:
+			return x.(int32) + y.(int32)
+		case int64:
+			return x.(int64) + y.(int64)
+		case uint:
+			return x.(uint) + y.(uint)
+		case uint8:
+			return x.(uint8) + y.(uint8)
+		case uint16:
+			return x.(uint16) + y.(uint16)
+		case uint32:
+			return x.(uint32) + y.(uint32)
+		case uint64:
+			return x.(uint64) + y.(uint64)
+		case uintptr:
+			return x.(uintptr) + y.(uintptr)
+		case float32:
+			return x.(float32) + y.(float32)
+		case float64:
+			return x.(float64) + y.(float64)
+		case complex64:
+			return x.(complex64) + y.(complex64)
+		case complex128:
+			return x.(complex128) + y.(complex128)
+		case string:
+			return x.(string) + y.(string)
+		}
+
+	case token.SUB:
+		switch x.(type) {
+		case int:
+			return x.(int) - y.(int)
+		case int8:
+			return x.(int8) - y.(int8)
+		case int16:
+			return x.(int16) - y.(int16)
+		case int32:
+			return x.(int32) - y.(int32)
+		case int64:
+			return x.(int64) - y.(int64)
+		case uint:
+			return x.(uint) - y.(uint)
+		case uint8:
+			return x.(uint8) - y.(uint8)
+		case uint16:
+			return x.(uint16) - y.(uint16)
+		case uint32:
+			return x.(uint32) - y.(uint32)
+		case uint64:
+			return x.(uint64) - y.(uint64)
+		case uintptr:
+			return x.(uintptr) - y.(uintptr)
+		case float32:
+			return x.(float32) - y.(float32)
+		case float64:
+			return x.(float64) - y.(float64)
+		case complex64:
+			return x.(complex64) - y.(complex64)
+		case complex128:
+			return x.(complex128) - y.(complex128)
+		}
+
+	case token.MUL:
+		switch x.(type) {
+		case int:
+			return x.(int) * y.(int)
+		case int8:
+			return x.(int8) * y.(int8)
+		case int16:
+			return x.(int16) * y.(int16)
+		case int32:
+			return x.(int32) * y.(int32)
+		case int64:
+			return x.(int64) * y.(int64)
+		case uint:
+			return x.(uint) * y.(uint)
+		case uint8:
+			return x.(uint8) * y.(uint8)
+		case uint16:
+			return x.(uint16) * y.(uint16)
+		case uint32:
+			return x.(uint32) * y.(uint32)
+		case uint64:
+			return x.(uint64) * y.(uint64)
+		case uintptr:
+			return x.(uintptr) * y.(uintptr)
+		case float32:
+			return x.(float32) * y.(float32)
+		case float64:
+			return x.(float64) * y.(float64)
+		case complex64:
+			return x.(complex64) * y.(complex64)
+		case complex128:
+			return x.(complex128) * y.(complex128)
+		}
+
+	case token.QUO:
+		switch x.(type) {
+		case int:
+			return x.(int) / y.(int)
+		case int8:
+			return x.(int8) / y.(int8)
+		case int16:
+			return x.(int16) / y.(int16)
+		case int32:
+			return x.(int32) / y.(int32)
+		case int64:
+			return x.(int64) / y.(int64)
+		case uint:
+			return x.(uint) / y.(uint)
+		case uint8:
+			return x.(uint8) / y.(uint8)
+		case uint16:
+			return x.(uint16) / y.(uint16)
+		case uint32:
+			return x.(uint32) / y.(uint32)
+		case uint64:
+			return x.(uint64) / y.(uint64)
+		case uintptr:
+			return x.(uintptr) / y.(uintptr)
+		case float32:
+			return x.(float32) / y.(float32)
+		case float64:
+			return x.(float64) / y.(float64)
+		case complex64:
+			return x.(complex64) / y.(complex64)
+		case complex128:
+			return x.(complex128) / y.(complex128)
+		}
+
+	case token.REM:
+		switch x.(type) {
+		case int:
+			return x.(int) % y.(int)
+		case int8:
+			return x.(int8) % y.(int8)
+		case int16:
+			return x.(int16) % y.(int16)
+		case int32:
+			return x.(int32) % y.(int32)
+		case int64:
+			return x.(int64) % y.(int64)
+		case uint:
+			return x.(uint) % y.(uint)
+		case uint8:
+			return x.(uint8) % y.(uint8)
+		case uint16:
+			return x.(uint16) % y.(uint16)
+		case uint32:
+			return x.(uint32) % y.(uint32)
+		case uint64:
+			return x.(uint64) % y.(uint64)
+		case uintptr:
+			return x.(uintptr) % y.(uintptr)
+		}
+
+	case token.AND:
+		switch x.(type) {
+		case int:
+			return x.(int) & y.(int)
+		case int8:
+			return x.(int8) & y.(int8)
+		case int16:
+			return x.(int16) & y.(int16)
+		case int32:
+			return x.(int32) & y.(int32)
+		case int64:
+			return x.(int64) & y.(int64)
+		case uint:
+			return x.(uint) & y.(uint)
+		case uint8:
+			return x.(uint8) & y.(uint8)
+		case uint16:
+			return x.(uint16) & y.(uint16)
+		case uint32:
+			return x.(uint32) & y.(uint32)
+		case uint64:
+			return x.(uint64) & y.(uint64)
+		case uintptr:
+			return x.(uintptr) & y.(uintptr)
+		}
+
+	case token.OR:
+		switch x.(type) {
+		case int:
+			return x.(int) | y.(int)
+		case int8:
+			return x.(int8) | y.(int8)
+		case int16:
+			return x.(int16) | y.(int16)
+		case int32:
+			return x.(int32) | y.(int32)
+		case int64:
+			return x.(int64) | y.(int64)
+		case uint:
+			return x.(uint) | y.(uint)
+		case uint8:
+			return x.(uint8) | y.(uint8)
+		case uint16:
+			return x.(uint16) | y.(uint16)
+		case uint32:
+			return x.(uint32) | y.(uint32)
+		case uint64:
+			return x.(uint64) | y.(uint64)
+		case uintptr:
+			return x.(uintptr) | y.(uintptr)
+		}
+
+	case token.XOR:
+		switch x.(type) {
+		case int:
+			return x.(int) ^ y.(int)
+		case int8:
+			return x.(int8) ^ y.(int8)
+		case int16:
+			return x.(int16) ^ y.(int16)
+		case int32:
+			return x.(int32) ^ y.(int32)
+		case int64:
+			return x.(int64) ^ y.(int64)
+		case uint:
+			return x.(uint) ^ y.(uint)
+		case uint8:
+			return x.(uint8) ^ y.(uint8)
+		case uint16:
+			return x.(uint16) ^ y.(uint16)
+		case uint32:
+			return x.(uint32) ^ y.(uint32)
+		case uint64:
+			return x.(uint64) ^ y.(uint64)
+		case uintptr:
+			return x.(uintptr) ^ y.(uintptr)
+		}
+
+	case token.AND_NOT:
+		switch x.(type) {
+		case int:
+			return x.(int) &^ y.(int)
+		case int8:
+			return x.(int8) &^ y.(int8)
+		case int16:
+			return x.(int16) &^ y.(int16)
+		case int32:
+			return x.(int32) &^ y.(int32)
+		case int64:
+			return x.(int64) &^ y.(int64)
+		case uint:
+			return x.(uint) &^ y.(uint)
+		case uint8:
+			return x.(uint8) &^ y.(uint8)
+		case uint16:
+			return x.(uint16) &^ y.(uint16)
+		case uint32:
+			return x.(uint32) &^ y.(uint32)
+		case uint64:
+			return x.(uint64) &^ y.(uint64)
+		case uintptr:
+			return x.(uintptr) &^ y.(uintptr)
+		}
+
+	case token.SHL:
+		y := asUint64(y)
+		switch x.(type) {
+		case int:
+			return x.(int) << y
+		case int8:
+			return x.(int8) << y
+		case int16:
+			return x.(int16) << y
+		case int32:
+			return x.(int32) << y
+		case int64:
+			return x.(int64) << y
+		case uint:
+			return x.(uint) << y
+		case uint8:
+			return x.(uint8) << y
+		case uint16:
+			return x.(uint16) << y
+		case uint32:
+			return x.(uint32) << y
+		case uint64:
+			return x.(uint64) << y
+		case uintptr:
+			return x.(uintptr) << y
+		}
+
+	case token.SHR:
+		y := asUint64(y)
+		switch x.(type) {
+		case int:
+			return x.(int) >> y
+		case int8:
+			return x.(int8) >> y
+		case int16:
+			return x.(int16) >> y
+		case int32:
+			return x.(int32) >> y
+		case int64:
+			return x.(int64) >> y
+		case uint:
+			return x.(uint) >> y
+		case uint8:
+			return x.(uint8) >> y
+		case uint16:
+			return x.(uint16) >> y
+		case uint32:
+			return x.(uint32) >> y
+		case uint64:
+			return x.(uint64) >> y
+		case uintptr:
+			return x.(uintptr) >> y
+		}
+
+	case token.LSS:
+		switch x.(type) {
+		case int:
+			return x.(int) < y.(int)
+		case int8:
+			return x.(int8) < y.(int8)
+		case int16:
+			return x.(int16) < y.(int16)
+		case int32:
+			return x.(int32) < y.(int32)
+		case int64:
+			return x.(int64) < y.(int64)
+		case uint:
+			return x.(uint) < y.(uint)
+		case uint8:
+			return x.(uint8) < y.(uint8)
+		case uint16:
+			return x.(uint16) < y.(uint16)
+		case uint32:
+			return x.(uint32) < y.(uint32)
+		case uint64:
+			return x.(uint64) < y.(uint64)
+		case uintptr:
+			return x.(uintptr) < y.(uintptr)
+		case float32:
+			return x.(float32) < y.(float32)
+		case float64:
+			return x.(float64) < y.(float64)
+		case string:
+			return x.(string) < y.(string)
+		}
+
+	case token.LEQ:
+		switch x.(type) {
+		case int:
+			return x.(int) <= y.(int)
+		case int8:
+			return x.(int8) <= y.(int8)
+		case int16:
+			return x.(int16) <= y.(int16)
+		case int32:
+			return x.(int32) <= y.(int32)
+		case int64:
+			return x.(int64) <= y.(int64)
+		case uint:
+			return x.(uint) <= y.(uint)
+		case uint8:
+			return x.(uint8) <= y.(uint8)
+		case uint16:
+			return x.(uint16) <= y.(uint16)
+		case uint32:
+			return x.(uint32) <= y.(uint32)
+		case uint64:
+			return x.(uint64) <= y.(uint64)
+		case uintptr:
+			return x.(uintptr) <= y.(uintptr)
+		case float32:
+			return x.(float32) <= y.(float32)
+		case float64:
+			return x.(float64) <= y.(float64)
+		case string:
+			return x.(string) <= y.(string)
+		}
+
+	case token.EQL:
+		return eqnil(t, x, y)
+
+	case token.NEQ:
+		return !eqnil(t, x, y)
+
+	case token.GTR:
+		switch x.(type) {
+		case int:
+			return x.(int) > y.(int)
+		case int8:
+			return x.(int8) > y.(int8)
+		case int16:
+			return x.(int16) > y.(int16)
+		case int32:
+			return x.(int32) > y.(int32)
+		case int64:
+			return x.(int64) > y.(int64)
+		case uint:
+			return x.(uint) > y.(uint)
+		case uint8:
+			return x.(uint8) > y.(uint8)
+		case uint16:
+			return x.(uint16) > y.(uint16)
+		case uint32:
+			return x.(uint32) > y.(uint32)
+		case uint64:
+			return x.(uint64) > y.(uint64)
+		case uintptr:
+			return x.(uintptr) > y.(uintptr)
+		case float32:
+			return x.(float32) > y.(float32)
+		case float64:
+			return x.(float64) > y.(float64)
+		case string:
+			return x.(string) > y.(string)
+		}
+
+	case token.GEQ:
+		switch x.(type) {
+		case int:
+			return x.(int) >= y.(int)
+		case int8:
+			return x.(int8) >= y.(int8)
+		case int16:
+			return x.(int16) >= y.(int16)
+		case int32:
+			return x.(int32) >= y.(int32)
+		case int64:
+			return x.(int64) >= y.(int64)
+		case uint:
+			return x.(uint) >= y.(uint)
+		case uint8:
+			return x.(uint8) >= y.(uint8)
+		case uint16:
+			return x.(uint16) >= y.(uint16)
+		case uint32:
+			return x.(uint32) >= y.(uint32)
+		case uint64:
+			return x.(uint64) >= y.(uint64)
+		case uintptr:
+			return x.(uintptr) >= y.(uintptr)
+		case float32:
+			return x.(float32) >= y.(float32)
+		case float64:
+			return x.(float64) >= y.(float64)
+		case string:
+			return x.(string) >= y.(string)
+		}
+	}
+	panic(fmt.Sprintf("invalid binary op: %T %s %T", x, op, y))
+}
+
+// eqnil returns the comparison x == y using the equivalence relation
+// appropriate for type t.
+// If t is a reference type, at most one of x or y may be a nil value
+// of that type.
+//
+func eqnil(t types.Type, x, y value) bool {
+	switch t.Underlying().(type) {
+	case *types.Map, *types.Signature, *types.Slice:
+		// Since these types don't support comparison,
+		// one of the operands must be a literal nil.
+		switch x := x.(type) {
+		case *hashmap:
+			return (x != nil) == (y.(*hashmap) != nil)
+		case map[value]value:
+			return (x != nil) == (y.(map[value]value) != nil)
+		case *ssa.Function:
+			switch y := y.(type) {
+			case *ssa.Function:
+				return (x != nil) == (y != nil)
+			case *closure:
+				return true
+			}
+		case *closure:
+			return (x != nil) == (y.(*ssa.Function) != nil)
+		case []value:
+			return (x != nil) == (y.([]value) != nil)
+		}
+		panic(fmt.Sprintf("eqnil(%s): illegal dynamic type: %T", t, x))
+	}
+
+	return equals(t, x, y)
+}
+
+func unop(instr *ssa.UnOp, x value) value {
+	switch instr.Op {
+	case token.ARROW: // receive
+		v, ok := <-x.(chan value)
+		if !ok {
+			v = zero(instr.X.Type().Underlying().(*types.Chan).Elem())
+		}
+		if instr.CommaOk {
+			v = tuple{v, ok}
+		}
+		return v
+	case token.SUB:
+		switch x := x.(type) {
+		case int:
+			return -x
+		case int8:
+			return -x
+		case int16:
+			return -x
+		case int32:
+			return -x
+		case int64:
+			return -x
+		case uint:
+			return -x
+		case uint8:
+			return -x
+		case uint16:
+			return -x
+		case uint32:
+			return -x
+		case uint64:
+			return -x
+		case uintptr:
+			return -x
+		case float32:
+			return -x
+		case float64:
+			return -x
+		case complex64:
+			return -x
+		case complex128:
+			return -x
+		}
+	case token.MUL:
+		return copyVal(*x.(*value)) // load
+	case token.NOT:
+		return !x.(bool)
+	case token.XOR:
+		switch x := x.(type) {
+		case int:
+			return ^x
+		case int8:
+			return ^x
+		case int16:
+			return ^x
+		case int32:
+			return ^x
+		case int64:
+			return ^x
+		case uint:
+			return ^x
+		case uint8:
+			return ^x
+		case uint16:
+			return ^x
+		case uint32:
+			return ^x
+		case uint64:
+			return ^x
+		case uintptr:
+			return ^x
+		}
+	}
+	panic(fmt.Sprintf("invalid unary op %s %T", instr.Op, x))
+}
+
+// typeAssert checks whether dynamic type of itf is instr.AssertedType.
+// It returns the extracted value on success, and panics on failure,
+// unless instr.CommaOk, in which case it always returns a "value,ok" tuple.
+//
+func typeAssert(i *interpreter, instr *ssa.TypeAssert, itf iface) value {
+	var v value
+	err := ""
+	if itf.t == nil {
+		err = fmt.Sprintf("interface conversion: interface is nil, not %s", instr.AssertedType)
+
+	} else if idst, ok := instr.AssertedType.Underlying().(*types.Interface); ok {
+		v = itf
+		err = checkInterface(i, idst, itf)
+
+	} else if types.Identical(itf.t, instr.AssertedType) {
+		v = copyVal(itf.v) // extract value
+
+	} else {
+		err = fmt.Sprintf("interface conversion: interface is %s, not %s", itf.t, instr.AssertedType)
+	}
+
+	if err != "" {
+		if !instr.CommaOk {
+			panic(err)
+		}
+		return tuple{zero(instr.AssertedType), false}
+	}
+	if instr.CommaOk {
+		return tuple{v, true}
+	}
+	return v
+}
+
+// If CapturedOutput is non-nil, all writes by the interpreted program
+// to file descriptors 1 and 2 will also be written to CapturedOutput.
+//
+// (The $GOROOT/test system requires that the test be considered a
+// failure if "BUG" appears in the combined stdout/stderr output, even
+// if it exits zero.  This is a global variable shared by all
+// interpreters in the same process.)
+//
+var CapturedOutput *bytes.Buffer
+var capturedOutputMu sync.Mutex
+
+// write writes bytes b to the target program's file descriptor fd.
+// The print/println built-ins and the write() system call funnel
+// through here so they can be captured by the test driver.
+func write(fd int, b []byte) (int, error) {
+	// TODO(adonovan): fix: on Windows, std{out,err} are not 1, 2.
+	if CapturedOutput != nil && (fd == 1 || fd == 2) {
+		capturedOutputMu.Lock()
+		CapturedOutput.Write(b) // ignore errors
+		capturedOutputMu.Unlock()
+	}
+	return syswrite(fd, b)
+}
+
+// callBuiltin interprets a call to builtin fn with arguments args,
+// returning its result.
+func callBuiltin(caller *frame, callpos token.Pos, fn *ssa.Builtin, args []value) value {
+	switch fn.Name() {
+	case "append":
+		if len(args) == 1 {
+			return args[0]
+		}
+		if s, ok := args[1].(string); ok {
+			// append([]byte, ...string) []byte
+			arg0 := args[0].([]value)
+			for i := 0; i < len(s); i++ {
+				arg0 = append(arg0, s[i])
+			}
+			return arg0
+		}
+		// append([]T, ...[]T) []T
+		return append(args[0].([]value), args[1].([]value)...)
+
+	case "copy": // copy([]T, []T) int or copy([]byte, string) int
+		src := args[1]
+		if _, ok := src.(string); ok {
+			params := fn.Type().(*types.Signature).Params()
+			src = conv(params.At(0).Type(), params.At(1).Type(), src)
+		}
+		return copy(args[0].([]value), src.([]value))
+
+	case "close": // close(chan T)
+		close(args[0].(chan value))
+		return nil
+
+	case "delete": // delete(map[K]value, K)
+		switch m := args[0].(type) {
+		case map[value]value:
+			delete(m, args[1])
+		case *hashmap:
+			m.delete(args[1].(hashable))
+		default:
+			panic(fmt.Sprintf("illegal map type: %T", m))
+		}
+		return nil
+
+	case "print", "println": // print(any, ...)
+		ln := fn.Name() == "println"
+		var buf bytes.Buffer
+		for i, arg := range args {
+			if i > 0 && ln {
+				buf.WriteRune(' ')
+			}
+			buf.WriteString(toString(arg))
+		}
+		if ln {
+			buf.WriteRune('\n')
+		}
+		write(1, buf.Bytes())
+		return nil
+
+	case "len":
+		switch x := args[0].(type) {
+		case string:
+			return len(x)
+		case array:
+			return len(x)
+		case *value:
+			return len((*x).(array))
+		case []value:
+			return len(x)
+		case map[value]value:
+			return len(x)
+		case *hashmap:
+			return x.len()
+		case chan value:
+			return len(x)
+		default:
+			panic(fmt.Sprintf("len: illegal operand: %T", x))
+		}
+
+	case "cap":
+		switch x := args[0].(type) {
+		case array:
+			return cap(x)
+		case *value:
+			return cap((*x).(array))
+		case []value:
+			return cap(x)
+		case chan value:
+			return cap(x)
+		default:
+			panic(fmt.Sprintf("cap: illegal operand: %T", x))
+		}
+
+	case "real":
+		switch c := args[0].(type) {
+		case complex64:
+			return real(c)
+		case complex128:
+			return real(c)
+		default:
+			panic(fmt.Sprintf("real: illegal operand: %T", c))
+		}
+
+	case "imag":
+		switch c := args[0].(type) {
+		case complex64:
+			return imag(c)
+		case complex128:
+			return imag(c)
+		default:
+			panic(fmt.Sprintf("imag: illegal operand: %T", c))
+		}
+
+	case "complex":
+		switch f := args[0].(type) {
+		case float32:
+			return complex(f, args[1].(float32))
+		case float64:
+			return complex(f, args[1].(float64))
+		default:
+			panic(fmt.Sprintf("complex: illegal operand: %T", f))
+		}
+
+	case "panic":
+		// ssa.Panic handles most cases; this is only for "go
+		// panic" or "defer panic".
+		panic(targetPanic{args[0]})
+
+	case "recover":
+		return doRecover(caller)
+
+	case "ssa:wrapnilchk":
+		recv := args[0]
+		if recv.(*value) == nil {
+			recvType := args[1]
+			methodName := args[2]
+			panic(fmt.Sprintf("value method (%s).%s called using nil *%s pointer",
+				recvType, methodName, recvType))
+		}
+		return recv
+	}
+
+	panic("unknown built-in: " + fn.Name())
+}
+
+func rangeIter(x value, t types.Type) iter {
+	switch x := x.(type) {
+	case map[value]value:
+		// TODO(adonovan): fix: leaks goroutines and channels
+		// on each incomplete map iteration.  We need to open
+		// up an iteration interface using the
+		// reflect.(Value).MapKeys machinery.
+		it := make(mapIter)
+		go func() {
+			for k, v := range x {
+				it <- [2]value{k, v}
+			}
+			close(it)
+		}()
+		return it
+	case *hashmap:
+		// TODO(adonovan): fix: leaks goroutines and channels
+		// on each incomplete map iteration.  We need to open
+		// up an iteration interface using the
+		// reflect.(Value).MapKeys machinery.
+		it := make(mapIter)
+		go func() {
+			for _, e := range x.table {
+				for e != nil {
+					it <- [2]value{e.key, e.value}
+					e = e.next
+				}
+			}
+			close(it)
+		}()
+		return it
+	case string:
+		return &stringIter{Reader: strings.NewReader(x)}
+	}
+	panic(fmt.Sprintf("cannot range over %T", x))
+}
+
+// widen widens a basic typed value x to the widest type of its
+// category, one of:
+//   bool, int64, uint64, float64, complex128, string.
+// This is inefficient but reduces the size of the cross-product of
+// cases we have to consider.
+//
+func widen(x value) value {
+	switch y := x.(type) {
+	case bool, int64, uint64, float64, complex128, string, unsafe.Pointer:
+		return x
+	case int:
+		return int64(y)
+	case int8:
+		return int64(y)
+	case int16:
+		return int64(y)
+	case int32:
+		return int64(y)
+	case uint:
+		return uint64(y)
+	case uint8:
+		return uint64(y)
+	case uint16:
+		return uint64(y)
+	case uint32:
+		return uint64(y)
+	case uintptr:
+		return uint64(y)
+	case float32:
+		return float64(y)
+	case complex64:
+		return complex128(y)
+	}
+	panic(fmt.Sprintf("cannot widen %T", x))
+}
+
+// conv converts the value x of type t_src to type t_dst and returns
+// the result.
+// Possible cases are described with the ssa.Convert operator.
+//
+func conv(t_dst, t_src types.Type, x value) value {
+	ut_src := t_src.Underlying()
+	ut_dst := t_dst.Underlying()
+
+	// Destination type is not an "untyped" type.
+	if b, ok := ut_dst.(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {
+		panic("oops: conversion to 'untyped' type: " + b.String())
+	}
+
+	// Nor is it an interface type.
+	if _, ok := ut_dst.(*types.Interface); ok {
+		if _, ok := ut_src.(*types.Interface); ok {
+			panic("oops: Convert should be ChangeInterface")
+		} else {
+			panic("oops: Convert should be MakeInterface")
+		}
+	}
+
+	// Remaining conversions:
+	//    + untyped string/number/bool constant to a specific
+	//      representation.
+	//    + conversions between non-complex numeric types.
+	//    + conversions between complex numeric types.
+	//    + integer/[]byte/[]rune -> string.
+	//    + string -> []byte/[]rune.
+	//
+	// All are treated the same: first we extract the value to the
+	// widest representation (int64, uint64, float64, complex128,
+	// or string), then we convert it to the desired type.
+
+	switch ut_src := ut_src.(type) {
+	case *types.Pointer:
+		switch ut_dst := ut_dst.(type) {
+		case *types.Basic:
+			// *value to unsafe.Pointer?
+			if ut_dst.Kind() == types.UnsafePointer {
+				return unsafe.Pointer(x.(*value))
+			}
+		}
+
+	case *types.Slice:
+		// []byte or []rune -> string
+		// TODO(adonovan): fix: type B byte; conv([]B -> string).
+		switch ut_src.Elem().(*types.Basic).Kind() {
+		case types.Byte:
+			x := x.([]value)
+			b := make([]byte, 0, len(x))
+			for i := range x {
+				b = append(b, x[i].(byte))
+			}
+			return string(b)
+
+		case types.Rune:
+			x := x.([]value)
+			r := make([]rune, 0, len(x))
+			for i := range x {
+				r = append(r, x[i].(rune))
+			}
+			return string(r)
+		}
+
+	case *types.Basic:
+		x = widen(x)
+
+		// integer -> string?
+		// TODO(adonovan): fix: test integer -> named alias of string.
+		if ut_src.Info()&types.IsInteger != 0 {
+			if ut_dst, ok := ut_dst.(*types.Basic); ok && ut_dst.Kind() == types.String {
+				return string(asInt(x))
+			}
+		}
+
+		// string -> []rune, []byte or string?
+		if s, ok := x.(string); ok {
+			switch ut_dst := ut_dst.(type) {
+			case *types.Slice:
+				var res []value
+				// TODO(adonovan): fix: test named alias of rune, byte.
+				switch ut_dst.Elem().(*types.Basic).Kind() {
+				case types.Rune:
+					for _, r := range []rune(s) {
+						res = append(res, r)
+					}
+					return res
+				case types.Byte:
+					for _, b := range []byte(s) {
+						res = append(res, b)
+					}
+					return res
+				}
+			case *types.Basic:
+				if ut_dst.Kind() == types.String {
+					return x.(string)
+				}
+			}
+			break // fail: no other conversions for string
+		}
+
+		// unsafe.Pointer -> *value
+		if ut_src.Kind() == types.UnsafePointer {
+			// TODO(adonovan): this is wrong and cannot
+			// really be fixed with the current design.
+			//
+			// return (*value)(x.(unsafe.Pointer))
+			// creates a new pointer of a different
+			// type but the underlying interface value
+			// knows its "true" type and so cannot be
+			// meaningfully used through the new pointer.
+			//
+			// To make this work, the interpreter needs to
+			// simulate the memory layout of a real
+			// compiled implementation.
+			//
+			// To at least preserve type-safety, we'll
+			// just return the zero value of the
+			// destination type.
+			return zero(t_dst)
+		}
+
+		// Conversions between complex numeric types?
+		if ut_src.Info()&types.IsComplex != 0 {
+			switch ut_dst.(*types.Basic).Kind() {
+			case types.Complex64:
+				return complex64(x.(complex128))
+			case types.Complex128:
+				return x.(complex128)
+			}
+			break // fail: no other conversions for complex
+		}
+
+		// Conversions between non-complex numeric types?
+		if ut_src.Info()&types.IsNumeric != 0 {
+			kind := ut_dst.(*types.Basic).Kind()
+			switch x := x.(type) {
+			case int64: // signed integer -> numeric?
+				switch kind {
+				case types.Int:
+					return int(x)
+				case types.Int8:
+					return int8(x)
+				case types.Int16:
+					return int16(x)
+				case types.Int32:
+					return int32(x)
+				case types.Int64:
+					return int64(x)
+				case types.Uint:
+					return uint(x)
+				case types.Uint8:
+					return uint8(x)
+				case types.Uint16:
+					return uint16(x)
+				case types.Uint32:
+					return uint32(x)
+				case types.Uint64:
+					return uint64(x)
+				case types.Uintptr:
+					return uintptr(x)
+				case types.Float32:
+					return float32(x)
+				case types.Float64:
+					return float64(x)
+				}
+
+			case uint64: // unsigned integer -> numeric?
+				switch kind {
+				case types.Int:
+					return int(x)
+				case types.Int8:
+					return int8(x)
+				case types.Int16:
+					return int16(x)
+				case types.Int32:
+					return int32(x)
+				case types.Int64:
+					return int64(x)
+				case types.Uint:
+					return uint(x)
+				case types.Uint8:
+					return uint8(x)
+				case types.Uint16:
+					return uint16(x)
+				case types.Uint32:
+					return uint32(x)
+				case types.Uint64:
+					return uint64(x)
+				case types.Uintptr:
+					return uintptr(x)
+				case types.Float32:
+					return float32(x)
+				case types.Float64:
+					return float64(x)
+				}
+
+			case float64: // floating point -> numeric?
+				switch kind {
+				case types.Int:
+					return int(x)
+				case types.Int8:
+					return int8(x)
+				case types.Int16:
+					return int16(x)
+				case types.Int32:
+					return int32(x)
+				case types.Int64:
+					return int64(x)
+				case types.Uint:
+					return uint(x)
+				case types.Uint8:
+					return uint8(x)
+				case types.Uint16:
+					return uint16(x)
+				case types.Uint32:
+					return uint32(x)
+				case types.Uint64:
+					return uint64(x)
+				case types.Uintptr:
+					return uintptr(x)
+				case types.Float32:
+					return float32(x)
+				case types.Float64:
+					return float64(x)
+				}
+			}
+		}
+	}
+
+	panic(fmt.Sprintf("unsupported conversion: %s  -> %s, dynamic type %T", t_src, t_dst, x))
+}
+
+// checkInterface checks that the method set of x implements the
+// interface itype.
+// On success it returns "", on failure, an error message.
+//
+func checkInterface(i *interpreter, itype *types.Interface, x iface) string {
+	if meth, _ := types.MissingMethod(x.t, itype, true); meth != nil {
+		return fmt.Sprintf("interface conversion: %v is not %v: missing method %s",
+			x.t, itype, meth.Name())
+	}
+	return "" // ok
+}
diff --git a/third_party/go.tools/go/ssa/interp/reflect.go b/third_party/go.tools/go/ssa/interp/reflect.go
new file mode 100644
index 0000000..4acba61
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/reflect.go
@@ -0,0 +1,521 @@
+// Copyright 2013 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 interp
+
+// Emulated "reflect" package.
+//
+// We completely replace the built-in "reflect" package.
+// The only thing clients can depend upon are that reflect.Type is an
+// interface and reflect.Value is an (opaque) struct.
+
+import (
+	"fmt"
+	"go/token"
+	"reflect"
+	"unsafe"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+type opaqueType struct {
+	types.Type
+	name string
+}
+
+func (t *opaqueType) String() string { return t.name }
+
+// A bogus "reflect" type-checker package.  Shared across interpreters.
+var reflectTypesPackage = types.NewPackage("reflect", "reflect")
+
+// rtype is the concrete type the interpreter uses to implement the
+// reflect.Type interface.  Since its type is opaque to the target
+// language, we use a types.Basic.
+//
+// type rtype <opaque>
+var rtypeType = makeNamedType("rtype", &opaqueType{nil, "rtype"})
+
+// error is an (interpreted) named type whose underlying type is string.
+// The interpreter uses it for all implementations of the built-in error
+// interface that it creates.
+// We put it in the "reflect" package for expedience.
+//
+// type error string
+var errorType = makeNamedType("error", &opaqueType{nil, "error"})
+
+func makeNamedType(name string, underlying types.Type) *types.Named {
+	obj := types.NewTypeName(token.NoPos, reflectTypesPackage, name, nil)
+	return types.NewNamed(obj, underlying, nil)
+}
+
+func makeReflectValue(t types.Type, v value) value {
+	return structure{rtype{t}, v}
+}
+
+// Given a reflect.Value, returns its rtype.
+func rV2T(v value) rtype {
+	return v.(structure)[0].(rtype)
+}
+
+// Given a reflect.Value, returns the underlying interpreter value.
+func rV2V(v value) value {
+	return v.(structure)[1]
+}
+
+// makeReflectType boxes up an rtype in a reflect.Type interface.
+func makeReflectType(rt rtype) value {
+	return iface{rtypeType, rt}
+}
+
+func ext۰reflect۰Init(fr *frame, args []value) value {
+	// Signature: func()
+	return nil
+}
+
+func ext۰reflect۰rtype۰Bits(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	rt := args[0].(rtype).t
+	basic, ok := rt.Underlying().(*types.Basic)
+	if !ok {
+		panic(fmt.Sprintf("reflect.Type.Bits(%T): non-basic type", rt))
+	}
+	return int(fr.i.sizes.Sizeof(basic)) * 8
+}
+
+func ext۰reflect۰rtype۰Elem(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) reflect.Type
+	return makeReflectType(rtype{args[0].(rtype).t.Underlying().(interface {
+		Elem() types.Type
+	}).Elem()})
+}
+
+func ext۰reflect۰rtype۰Field(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype, i int) reflect.StructField
+	st := args[0].(rtype).t.Underlying().(*types.Struct)
+	i := args[1].(int)
+	f := st.Field(i)
+	return structure{
+		f.Name(),
+		f.Pkg().Path(),
+		makeReflectType(rtype{f.Type()}),
+		st.Tag(i),
+		0,         // TODO(adonovan): offset
+		[]value{}, // TODO(adonovan): indices
+		f.Anonymous(),
+	}
+}
+
+func ext۰reflect۰rtype۰Kind(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) uint
+	return uint(reflectKind(args[0].(rtype).t))
+}
+
+func ext۰reflect۰rtype۰NumField(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return args[0].(rtype).t.Underlying().(*types.Struct).NumFields()
+}
+
+func ext۰reflect۰rtype۰NumMethod(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return fr.i.prog.MethodSets.MethodSet(args[0].(rtype).t).Len()
+}
+
+func ext۰reflect۰rtype۰NumOut(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return args[0].(rtype).t.(*types.Signature).Results().Len()
+}
+
+func ext۰reflect۰rtype۰Out(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype, i int) int
+	i := args[1].(int)
+	return makeReflectType(rtype{args[0].(rtype).t.(*types.Signature).Results().At(i).Type()})
+}
+
+func ext۰reflect۰rtype۰Size(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) uintptr
+	return uintptr(fr.i.sizes.Sizeof(args[0].(rtype).t))
+}
+
+func ext۰reflect۰rtype۰String(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) string
+	return args[0].(rtype).t.String()
+}
+
+func ext۰reflect۰New(fr *frame, args []value) value {
+	// Signature: func (t reflect.Type) reflect.Value
+	t := args[0].(iface).v.(rtype).t
+	alloc := zero(t)
+	return makeReflectValue(types.NewPointer(t), &alloc)
+}
+
+func ext۰reflect۰TypeOf(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) string
+	return makeReflectType(rtype{args[0].(iface).t})
+}
+
+func ext۰reflect۰ValueOf(fr *frame, args []value) value {
+	// Signature: func (interface{}) reflect.Value
+	itf := args[0].(iface)
+	return makeReflectValue(itf.t, itf.v)
+}
+
+func reflectKind(t types.Type) reflect.Kind {
+	switch t := t.(type) {
+	case *types.Named:
+		return reflectKind(t.Underlying())
+	case *types.Basic:
+		switch t.Kind() {
+		case types.Bool:
+			return reflect.Bool
+		case types.Int:
+			return reflect.Int
+		case types.Int8:
+			return reflect.Int8
+		case types.Int16:
+			return reflect.Int16
+		case types.Int32:
+			return reflect.Int32
+		case types.Int64:
+			return reflect.Int64
+		case types.Uint:
+			return reflect.Uint
+		case types.Uint8:
+			return reflect.Uint8
+		case types.Uint16:
+			return reflect.Uint16
+		case types.Uint32:
+			return reflect.Uint32
+		case types.Uint64:
+			return reflect.Uint64
+		case types.Uintptr:
+			return reflect.Uintptr
+		case types.Float32:
+			return reflect.Float32
+		case types.Float64:
+			return reflect.Float64
+		case types.Complex64:
+			return reflect.Complex64
+		case types.Complex128:
+			return reflect.Complex128
+		case types.String:
+			return reflect.String
+		case types.UnsafePointer:
+			return reflect.UnsafePointer
+		}
+	case *types.Array:
+		return reflect.Array
+	case *types.Chan:
+		return reflect.Chan
+	case *types.Signature:
+		return reflect.Func
+	case *types.Interface:
+		return reflect.Interface
+	case *types.Map:
+		return reflect.Map
+	case *types.Pointer:
+		return reflect.Ptr
+	case *types.Slice:
+		return reflect.Slice
+	case *types.Struct:
+		return reflect.Struct
+	}
+	panic(fmt.Sprint("unexpected type: ", t))
+}
+
+func ext۰reflect۰Value۰Kind(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) uint
+	return uint(reflectKind(rV2T(args[0]).t))
+}
+
+func ext۰reflect۰Value۰String(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) string
+	return toString(rV2V(args[0]))
+}
+
+func ext۰reflect۰Value۰Type(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) reflect.Type
+	return makeReflectType(rV2T(args[0]))
+}
+
+func ext۰reflect۰Value۰Uint(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) uint64
+	switch v := rV2V(args[0]).(type) {
+	case uint:
+		return uint64(v)
+	case uint8:
+		return uint64(v)
+	case uint16:
+		return uint64(v)
+	case uint32:
+		return uint64(v)
+	case uint64:
+		return uint64(v)
+	case uintptr:
+		return uint64(v)
+	}
+	panic("reflect.Value.Uint")
+}
+
+func ext۰reflect۰Value۰Len(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int
+	switch v := rV2V(args[0]).(type) {
+	case string:
+		return len(v)
+	case array:
+		return len(v)
+	case chan value:
+		return cap(v)
+	case []value:
+		return len(v)
+	case *hashmap:
+		return v.len()
+	case map[value]value:
+		return len(v)
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Len(%v)", v))
+	}
+}
+
+func ext۰reflect۰Value۰MapIndex(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) Value
+	tValue := rV2T(args[0]).t.Underlying().(*types.Map).Key()
+	k := rV2V(args[1])
+	switch m := rV2V(args[0]).(type) {
+	case map[value]value:
+		if v, ok := m[k]; ok {
+			return makeReflectValue(tValue, v)
+		}
+
+	case *hashmap:
+		if v := m.lookup(k.(hashable)); v != nil {
+			return makeReflectValue(tValue, v)
+		}
+
+	default:
+		panic(fmt.Sprintf("(reflect.Value).MapIndex(%T, %T)", m, k))
+	}
+	return makeReflectValue(nil, nil)
+}
+
+func ext۰reflect۰Value۰MapKeys(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) []Value
+	var keys []value
+	tKey := rV2T(args[0]).t.Underlying().(*types.Map).Key()
+	switch v := rV2V(args[0]).(type) {
+	case map[value]value:
+		for k := range v {
+			keys = append(keys, makeReflectValue(tKey, k))
+		}
+
+	case *hashmap:
+		for _, e := range v.table {
+			for ; e != nil; e = e.next {
+				keys = append(keys, makeReflectValue(tKey, e.key))
+			}
+		}
+
+	default:
+		panic(fmt.Sprintf("(reflect.Value).MapKeys(%T)", v))
+	}
+	return keys
+}
+
+func ext۰reflect۰Value۰NumField(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int
+	return len(rV2V(args[0]).(structure))
+}
+
+func ext۰reflect۰Value۰NumMethod(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int
+	return fr.i.prog.MethodSets.MethodSet(rV2T(args[0]).t).Len()
+}
+
+func ext۰reflect۰Value۰Pointer(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) uintptr
+	switch v := rV2V(args[0]).(type) {
+	case *value:
+		return uintptr(unsafe.Pointer(v))
+	case chan value:
+		return reflect.ValueOf(v).Pointer()
+	case []value:
+		return reflect.ValueOf(v).Pointer()
+	case *hashmap:
+		return reflect.ValueOf(v.table).Pointer()
+	case map[value]value:
+		return reflect.ValueOf(v).Pointer()
+	case *ssa.Function:
+		return uintptr(unsafe.Pointer(v))
+	case *closure:
+		return uintptr(unsafe.Pointer(v))
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Pointer(%T)", v))
+	}
+}
+
+func ext۰reflect۰Value۰Index(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value, i int) Value
+	i := args[1].(int)
+	t := rV2T(args[0]).t.Underlying()
+	switch v := rV2V(args[0]).(type) {
+	case array:
+		return makeReflectValue(t.(*types.Array).Elem(), v[i])
+	case []value:
+		return makeReflectValue(t.(*types.Slice).Elem(), v[i])
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Index(%T)", v))
+	}
+}
+
+func ext۰reflect۰Value۰Bool(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) bool
+	return rV2V(args[0]).(bool)
+}
+
+func ext۰reflect۰Value۰CanAddr(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) bool
+	// Always false for our representation.
+	return false
+}
+
+func ext۰reflect۰Value۰CanInterface(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) bool
+	// Always true for our representation.
+	return true
+}
+
+func ext۰reflect۰Value۰Elem(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) reflect.Value
+	switch x := rV2V(args[0]).(type) {
+	case iface:
+		return makeReflectValue(x.t, x.v)
+	case *value:
+		return makeReflectValue(rV2T(args[0]).t.Underlying().(*types.Pointer).Elem(), *x)
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Elem(%T)", x))
+	}
+}
+
+func ext۰reflect۰Value۰Field(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value, i int) reflect.Value
+	v := args[0]
+	i := args[1].(int)
+	return makeReflectValue(rV2T(v).t.Underlying().(*types.Struct).Field(i).Type(), rV2V(v).(structure)[i])
+}
+
+func ext۰reflect۰Value۰Float(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) float64
+	switch v := rV2V(args[0]).(type) {
+	case float32:
+		return float64(v)
+	case float64:
+		return float64(v)
+	}
+	panic("reflect.Value.Float")
+}
+
+func ext۰reflect۰Value۰Interface(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) interface{}
+	return ext۰reflect۰valueInterface(fr, args)
+}
+
+func ext۰reflect۰Value۰Int(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int64
+	switch x := rV2V(args[0]).(type) {
+	case int:
+		return int64(x)
+	case int8:
+		return int64(x)
+	case int16:
+		return int64(x)
+	case int32:
+		return int64(x)
+	case int64:
+		return x
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Int(%T)", x))
+	}
+}
+
+func ext۰reflect۰Value۰IsNil(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) bool
+	switch x := rV2V(args[0]).(type) {
+	case *value:
+		return x == nil
+	case chan value:
+		return x == nil
+	case map[value]value:
+		return x == nil
+	case *hashmap:
+		return x == nil
+	case iface:
+		return x.t == nil
+	case []value:
+		return x == nil
+	case *ssa.Function:
+		return x == nil
+	case *ssa.Builtin:
+		return x == nil
+	case *closure:
+		return x == nil
+	default:
+		panic(fmt.Sprintf("reflect.(Value).IsNil(%T)", x))
+	}
+}
+
+func ext۰reflect۰Value۰IsValid(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) bool
+	return rV2V(args[0]) != nil
+}
+
+func ext۰reflect۰Value۰Set(fr *frame, args []value) value {
+	// TODO(adonovan): implement.
+	return nil
+}
+
+func ext۰reflect۰valueInterface(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value, safe bool) interface{}
+	v := args[0].(structure)
+	return iface{rV2T(v).t, rV2V(v)}
+}
+
+func ext۰reflect۰error۰Error(fr *frame, args []value) value {
+	return args[0]
+}
+
+// newMethod creates a new method of the specified name, package and receiver type.
+func newMethod(pkg *ssa.Package, recvType types.Type, name string) *ssa.Function {
+	// TODO(adonovan): fix: hack: currently the only part of Signature
+	// that is needed is the "pointerness" of Recv.Type, and for
+	// now, we'll set it to always be false since we're only
+	// concerned with rtype.  Encapsulate this better.
+	sig := types.NewSignature(nil, types.NewVar(token.NoPos, nil, "recv", recvType), nil, nil, false)
+	fn := pkg.Prog.NewFunction(name, sig, "fake reflect method")
+	fn.Pkg = pkg
+	return fn
+}
+
+func initReflect(i *interpreter) {
+	i.reflectPackage = &ssa.Package{
+		Prog:    i.prog,
+		Object:  reflectTypesPackage,
+		Members: make(map[string]ssa.Member),
+	}
+
+	i.rtypeMethods = methodSet{
+		"Bits":      newMethod(i.reflectPackage, rtypeType, "Bits"),
+		"Elem":      newMethod(i.reflectPackage, rtypeType, "Elem"),
+		"Field":     newMethod(i.reflectPackage, rtypeType, "Field"),
+		"Kind":      newMethod(i.reflectPackage, rtypeType, "Kind"),
+		"NumField":  newMethod(i.reflectPackage, rtypeType, "NumField"),
+		"NumMethod": newMethod(i.reflectPackage, rtypeType, "NumMethod"),
+		"NumOut":    newMethod(i.reflectPackage, rtypeType, "NumOut"),
+		"Out":       newMethod(i.reflectPackage, rtypeType, "Out"),
+		"Size":      newMethod(i.reflectPackage, rtypeType, "Size"),
+		"String":    newMethod(i.reflectPackage, rtypeType, "String"),
+	}
+	i.errorMethods = methodSet{
+		"Error": newMethod(i.reflectPackage, errorType, "Error"),
+	}
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/a_test.go b/third_party/go.tools/go/ssa/interp/testdata/a_test.go
new file mode 100644
index 0000000..844ec5c
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/a_test.go
@@ -0,0 +1,17 @@
+package a
+
+import "testing"
+
+func TestFoo(t *testing.T) {
+	t.Error("foo")
+}
+
+func TestBar(t *testing.T) {
+	t.Error("bar")
+}
+
+func BenchmarkWiz(b *testing.B) {
+	b.Error("wiz")
+}
+
+// Don't test Examples since that testing package needs pipe(2) for that.
diff --git a/third_party/go.tools/go/ssa/interp/testdata/b_test.go b/third_party/go.tools/go/ssa/interp/testdata/b_test.go
new file mode 100644
index 0000000..4a30e96
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/b_test.go
@@ -0,0 +1,11 @@
+package b
+
+import "testing"
+
+func NotATest(t *testing.T) {
+	t.Error("foo")
+}
+
+func NotABenchmark(b *testing.B) {
+	b.Error("wiz")
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/boundmeth.go b/third_party/go.tools/go/ssa/interp/testdata/boundmeth.go
new file mode 100644
index 0000000..255cc60
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/boundmeth.go
@@ -0,0 +1,144 @@
+// Tests of bound method closures.
+
+package main
+
+import "fmt"
+
+func assert(b bool) {
+	if !b {
+		panic("oops")
+	}
+}
+
+type I int
+
+func (i I) add(x int) int {
+	return int(i) + x
+}
+
+func valueReceiver() {
+	var three I = 3
+	assert(three.add(5) == 8)
+	var add3 func(int) int = three.add
+	assert(add3(5) == 8)
+}
+
+type S struct{ x int }
+
+func (s *S) incr() {
+	s.x++
+}
+
+func (s *S) get() int {
+	return s.x
+}
+
+func pointerReceiver() {
+	ps := new(S)
+	incr := ps.incr
+	get := ps.get
+	assert(get() == 0)
+	incr()
+	incr()
+	incr()
+	assert(get() == 3)
+}
+
+func addressibleValuePointerReceiver() {
+	var s S
+	incr := s.incr
+	get := s.get
+	assert(get() == 0)
+	incr()
+	incr()
+	incr()
+	assert(get() == 3)
+}
+
+type S2 struct {
+	S
+}
+
+func promotedReceiver() {
+	var s2 S2
+	incr := s2.incr
+	get := s2.get
+	assert(get() == 0)
+	incr()
+	incr()
+	incr()
+	assert(get() == 3)
+}
+
+func anonStruct() {
+	var s struct{ S }
+	incr := s.incr
+	get := s.get
+	assert(get() == 0)
+	incr()
+	incr()
+	incr()
+	assert(get() == 3)
+}
+
+func typeCheck() {
+	var i interface{}
+	i = (*S).incr
+	_ = i.(func(*S)) // type assertion: receiver type prepended to params
+
+	var s S
+	i = s.incr
+	_ = i.(func()) // type assertion: receiver type disappears
+}
+
+type errString string
+
+func (err errString) Error() string {
+	return string(err)
+}
+
+// Regression test for a builder crash.
+func regress1(x error) func() string {
+	return x.Error
+}
+
+// Regression test for b/7269:
+// taking the value of an interface method performs a nil check.
+func nilInterfaceMethodValue() {
+	err := fmt.Errorf("ok")
+	f := err.Error
+	if got := f(); got != "ok" {
+		panic(got)
+	}
+
+	err = nil
+	if got := f(); got != "ok" {
+		panic(got)
+	}
+
+	defer func() {
+		r := fmt.Sprint(recover())
+		// runtime panic string varies across toolchains
+		if r != "runtime error: interface conversion: interface is nil, not error" &&
+			r != "runtime error: invalid memory address or nil pointer dereference" {
+			panic("want runtime panic from nil interface method value, got " + r)
+		}
+	}()
+	f = err.Error // runtime panic: err is nil
+	panic("unreachable")
+}
+
+func main() {
+	valueReceiver()
+	pointerReceiver()
+	addressibleValuePointerReceiver()
+	promotedReceiver()
+	anonStruct()
+	typeCheck()
+
+	if e := regress1(errString("hi"))(); e != "hi" {
+		panic(e)
+	}
+
+	nilInterfaceMethodValue()
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/callstack.go b/third_party/go.tools/go/ssa/interp/testdata/callstack.go
new file mode 100644
index 0000000..56f3b28
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/callstack.go
@@ -0,0 +1,52 @@
+package main
+
+import (
+	"fmt"
+	"path"
+	"runtime"
+	"strings"
+)
+
+var stack string
+
+func f() {
+	pc := make([]uintptr, 6)
+	pc = pc[:runtime.Callers(1, pc)]
+	for _, f := range pc {
+		Func := runtime.FuncForPC(f)
+		name := Func.Name()
+		if strings.Contains(name, "$") || strings.Contains(name, ".func") {
+			name = "func" // anon funcs vary across toolchains
+		}
+		file, line := Func.FileLine(0)
+		stack += fmt.Sprintf("%s at %s:%d\n", name, path.Base(file), line)
+	}
+}
+
+func g() { f() }
+func h() { g() }
+func i() { func() { h() }() }
+
+// Hack: the 'func' and the call to Caller are on the same line,
+// to paper over differences between toolchains.
+// (The interpreter's location info isn't yet complete.)
+func runtimeCaller0() (uintptr, string, int, bool) { return runtime.Caller(0) }
+
+func main() {
+	i()
+	if stack != `main.f at callstack.go:12
+main.g at callstack.go:26
+main.h at callstack.go:27
+func at callstack.go:28
+main.i at callstack.go:28
+main.main at callstack.go:35
+` {
+		panic("unexpected stack: " + stack)
+	}
+
+	pc, file, line, _ := runtimeCaller0()
+	got := fmt.Sprintf("%s @ %s:%d", runtime.FuncForPC(pc).Name(), path.Base(file), line)
+	if got != "main.runtimeCaller0 @ callstack.go:33" {
+		panic("runtime.Caller: " + got)
+	}
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/complit.go b/third_party/go.tools/go/ssa/interp/testdata/complit.go
new file mode 100644
index 0000000..c44fc00
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/complit.go
@@ -0,0 +1,84 @@
+package main
+
+// Tests of composite literals.
+
+import "fmt"
+
+// Map literals.
+func init() {
+	type M map[int]int
+	m1 := []*M{{1: 1}, &M{2: 2}}
+	want := "map[1:1] map[2:2]"
+	if got := fmt.Sprint(*m1[0], *m1[1]); got != want {
+		panic(got)
+	}
+	m2 := []M{{1: 1}, M{2: 2}}
+	if got := fmt.Sprint(m2[0], m2[1]); got != want {
+		panic(got)
+	}
+}
+
+// Nonliteral keys in composite literal.
+func init() {
+	const zero int = 1
+	var v = []int{1 + zero: 42}
+	if x := fmt.Sprint(v); x != "[0 0 42]" {
+		panic(x)
+	}
+}
+
+// Test for in-place initialization.
+func init() {
+	// struct
+	type S struct {
+		a, b int
+	}
+	s := S{1, 2}
+	s = S{b: 3}
+	if s.a != 0 {
+		panic("s.a != 0")
+	}
+	if s.b != 3 {
+		panic("s.b != 3")
+	}
+	s = S{}
+	if s.a != 0 {
+		panic("s.a != 0")
+	}
+	if s.b != 0 {
+		panic("s.b != 0")
+	}
+
+	// array
+	type A [4]int
+	a := A{2, 4, 6, 8}
+	a = A{1: 6, 2: 4}
+	if a[0] != 0 {
+		panic("a[0] != 0")
+	}
+	if a[1] != 6 {
+		panic("a[1] != 6")
+	}
+	if a[2] != 4 {
+		panic("a[2] != 4")
+	}
+	if a[3] != 0 {
+		panic("a[3] != 0")
+	}
+	a = A{}
+	if a[0] != 0 {
+		panic("a[0] != 0")
+	}
+	if a[1] != 0 {
+		panic("a[1] != 0")
+	}
+	if a[2] != 0 {
+		panic("a[2] != 0")
+	}
+	if a[3] != 0 {
+		panic("a[3] != 0")
+	}
+}
+
+func main() {
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/coverage.go b/third_party/go.tools/go/ssa/interp/testdata/coverage.go
new file mode 100644
index 0000000..ca65643
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/coverage.go
@@ -0,0 +1,496 @@
+// This interpreter test is designed to run very quickly yet provide
+// some coverage of a broad selection of constructs.
+//
+// Validate this file with 'go run' after editing.
+// TODO(adonovan): break this into small files organized by theme.
+
+package main
+
+import (
+	"fmt"
+	"reflect"
+)
+
+func init() {
+	// Call of variadic function with (implicit) empty slice.
+	if x := fmt.Sprint(); x != "" {
+		panic(x)
+	}
+}
+
+type empty interface{}
+
+type I interface {
+	f() int
+}
+
+type T struct{ z int }
+
+func (t T) f() int { return t.z }
+
+func use(interface{}) {}
+
+var counter = 2
+
+// Test initialization, including init blocks containing 'return'.
+// Assertion is in main.
+func init() {
+	counter *= 3
+	return
+	counter *= 3
+}
+
+func init() {
+	counter *= 5
+	return
+	counter *= 5
+}
+
+// Recursion.
+func fib(x int) int {
+	if x < 2 {
+		return x
+	}
+	return fib(x-1) + fib(x-2)
+}
+
+func fibgen(ch chan int) {
+	for x := 0; x < 10; x++ {
+		ch <- fib(x)
+	}
+	close(ch)
+}
+
+// Goroutines and channels.
+func init() {
+	ch := make(chan int)
+	go fibgen(ch)
+	var fibs []int
+	for v := range ch {
+		fibs = append(fibs, v)
+		if len(fibs) == 10 {
+			break
+		}
+	}
+	if x := fmt.Sprint(fibs); x != "[0 1 1 2 3 5 8 13 21 34]" {
+		panic(x)
+	}
+}
+
+// Test of aliasing.
+func init() {
+	type S struct {
+		a, b string
+	}
+
+	s1 := []string{"foo", "bar"}
+	s2 := s1 // creates an alias
+	s2[0] = "wiz"
+	if x := fmt.Sprint(s1, s2); x != "[wiz bar] [wiz bar]" {
+		panic(x)
+	}
+
+	pa1 := &[2]string{"foo", "bar"}
+	pa2 := pa1        // creates an alias
+	(*pa2)[0] = "wiz" // * required to workaround typechecker bug
+	if x := fmt.Sprint(*pa1, *pa2); x != "[wiz bar] [wiz bar]" {
+		panic(x)
+	}
+
+	a1 := [2]string{"foo", "bar"}
+	a2 := a1 // creates a copy
+	a2[0] = "wiz"
+	if x := fmt.Sprint(a1, a2); x != "[foo bar] [wiz bar]" {
+		panic(x)
+	}
+
+	t1 := S{"foo", "bar"}
+	t2 := t1 // copy
+	t2.a = "wiz"
+	if x := fmt.Sprint(t1, t2); x != "{foo bar} {wiz bar}" {
+		panic(x)
+	}
+}
+
+func main() {
+	print() // legal
+
+	if counter != 2*3*5 {
+		panic(counter)
+	}
+
+	// Test builtins (e.g. complex) preserve named argument types.
+	type N complex128
+	var n N
+	n = complex(1.0, 2.0)
+	if n != complex(1.0, 2.0) {
+		panic(n)
+	}
+	if x := reflect.TypeOf(n).String(); x != "main.N" {
+		panic(x)
+	}
+	if real(n) != 1.0 || imag(n) != 2.0 {
+		panic(n)
+	}
+
+	// Channel + select.
+	ch := make(chan int, 1)
+	select {
+	case ch <- 1:
+		// ok
+	default:
+		panic("couldn't send")
+	}
+	if <-ch != 1 {
+		panic("couldn't receive")
+	}
+	// A "receive" select-case that doesn't declare its vars.  (regression test)
+	anint := 0
+	ok := false
+	select {
+	case anint, ok = <-ch:
+	case anint = <-ch:
+	default:
+	}
+	_ = anint
+	_ = ok
+
+	// Anon structs with methods.
+	anon := struct{ T }{T: T{z: 1}}
+	if x := anon.f(); x != 1 {
+		panic(x)
+	}
+	var i I = anon
+	if x := i.f(); x != 1 {
+		panic(x)
+	}
+	// NB. precise output of reflect.Type.String is undefined.
+	if x := reflect.TypeOf(i).String(); x != "struct { main.T }" && x != "struct{main.T}" {
+		panic(x)
+	}
+
+	// fmt.
+	const message = "Hello, World!"
+	if fmt.Sprintf("%s, %s!", "Hello", "World") != message {
+		panic("oops")
+	}
+
+	// Type assertion.
+	type S struct {
+		f int
+	}
+	var e empty = S{f: 42}
+	switch v := e.(type) {
+	case S:
+		if v.f != 42 {
+			panic(v.f)
+		}
+	default:
+		panic(reflect.TypeOf(v))
+	}
+	if i, ok := e.(I); ok {
+		panic(i)
+	}
+
+	// Switch.
+	var x int
+	switch x {
+	case 1:
+		panic(x)
+		fallthrough
+	case 2, 3:
+		panic(x)
+	default:
+		// ok
+	}
+	// empty switch
+	switch {
+	}
+	// empty switch
+	switch {
+	default:
+	}
+	// empty switch
+	switch {
+	default:
+		fallthrough
+	case false:
+	}
+
+	// string -> []rune conversion.
+	use([]rune("foo"))
+
+	// Calls of form x.f().
+	type S2 struct {
+		f func() int
+	}
+	S2{f: func() int { return 1 }}.f() // field is a func value
+	T{}.f()                            // method call
+	i.f()                              // interface method invocation
+	(interface {
+		f() int
+	}(T{})).f() // anon interface method invocation
+
+	// Map lookup.
+	if v, ok := map[string]string{}["foo5"]; v != "" || ok {
+		panic("oops")
+	}
+
+	// Regression test: implicit address-taken struct literal
+	// inside literal map element.
+	_ = map[int]*struct{}{0: {}}
+}
+
+type mybool bool
+
+func (mybool) f() {}
+
+func init() {
+	type mybool bool
+	var b mybool
+	var i interface{} = b || b // result preserves types of operands
+	_ = i.(mybool)
+
+	i = false && b // result preserves type of "typed" operand
+	_ = i.(mybool)
+
+	i = b || true // result preserves type of "typed" operand
+	_ = i.(mybool)
+}
+
+func init() {
+	var x, y int
+	var b mybool = x == y // x==y is an untyped bool
+	b.f()
+}
+
+// Simple closures.
+func init() {
+	b := 3
+	f := func(a int) int {
+		return a + b
+	}
+	b++
+	if x := f(1); x != 5 { // 1+4 == 5
+		panic(x)
+	}
+	b++
+	if x := f(2); x != 7 { // 2+5 == 7
+		panic(x)
+	}
+	if b := f(1) < 16 || f(2) < 17; !b {
+		panic("oops")
+	}
+}
+
+// Shifts.
+func init() {
+	var i int64 = 1
+	var u uint64 = 1 << 32
+	if x := i << uint32(u); x != 1 {
+		panic(x)
+	}
+	if x := i << uint64(u); x != 0 {
+		panic(x)
+	}
+}
+
+// Implicit conversion of delete() key operand.
+func init() {
+	type I interface{}
+	m := make(map[I]bool)
+	m[1] = true
+	m[I(2)] = true
+	if len(m) != 2 {
+		panic(m)
+	}
+	delete(m, I(1))
+	delete(m, 2)
+	if len(m) != 0 {
+		panic(m)
+	}
+}
+
+// An I->I conversion always succeeds.
+func init() {
+	var x I
+	if I(x) != I(nil) {
+		panic("I->I conversion failed")
+	}
+}
+
+// An I->I type-assert fails iff the value is nil.
+func init() {
+	defer func() {
+		r := fmt.Sprint(recover())
+		// Exact error varies by toolchain.
+		if r != "runtime error: interface conversion: interface is nil, not main.I" &&
+			r != "interface conversion: interface is nil, not main.I" {
+			panic("I->I type assertion succeeded for nil value")
+		}
+	}()
+	var x I
+	_ = x.(I)
+}
+
+//////////////////////////////////////////////////////////////////////
+// Variadic bridge methods and interface thunks.
+
+type VT int
+
+var vcount = 0
+
+func (VT) f(x int, y ...string) {
+	vcount++
+	if x != 1 {
+		panic(x)
+	}
+	if len(y) != 2 || y[0] != "foo" || y[1] != "bar" {
+		panic(y)
+	}
+}
+
+type VS struct {
+	VT
+}
+
+type VI interface {
+	f(x int, y ...string)
+}
+
+func init() {
+	foobar := []string{"foo", "bar"}
+	var s VS
+	s.f(1, "foo", "bar")
+	s.f(1, foobar...)
+	if vcount != 2 {
+		panic("s.f not called twice")
+	}
+
+	fn := VI.f
+	fn(s, 1, "foo", "bar")
+	fn(s, 1, foobar...)
+	if vcount != 4 {
+		panic("I.f not called twice")
+	}
+}
+
+// Multiple labels on same statement.
+func multipleLabels() {
+	var trace []int
+	i := 0
+one:
+two:
+	for ; i < 3; i++ {
+		trace = append(trace, i)
+		switch i {
+		case 0:
+			continue two
+		case 1:
+			i++
+			goto one
+		case 2:
+			break two
+		}
+	}
+	if x := fmt.Sprint(trace); x != "[0 1 2]" {
+		panic(x)
+	}
+}
+
+func init() {
+	multipleLabels()
+}
+
+func init() {
+	// Struct equivalence ignores blank fields.
+	type s struct{ x, _, z int }
+	s1 := s{x: 1, z: 3}
+	s2 := s{x: 1, z: 3}
+	if s1 != s2 {
+		panic("not equal")
+	}
+}
+
+func init() {
+	// A slice var can be compared to const []T nil.
+	var i interface{} = []string{"foo"}
+	var j interface{} = []string(nil)
+	if i.([]string) == nil {
+		panic("expected i non-nil")
+	}
+	if j.([]string) != nil {
+		panic("expected j nil")
+	}
+	// But two slices cannot be compared, even if one is nil.
+	defer func() {
+		r := fmt.Sprint(recover())
+		if r != "runtime error: comparing uncomparable type []string" {
+			panic("want panic from slice comparison, got " + r)
+		}
+	}()
+	_ = i == j // interface comparison recurses on types
+}
+
+func init() {
+	// Regression test for SSA renaming bug.
+	var ints []int
+	for _ = range "foo" {
+		var x int
+		x++
+		ints = append(ints, x)
+	}
+	if fmt.Sprint(ints) != "[1 1 1]" {
+		panic(ints)
+	}
+}
+
+// Regression test for issue 6949:
+// []byte("foo") is not a constant since it allocates memory.
+func init() {
+	var r string
+	for i, b := range "ABC" {
+		x := []byte("abc")
+		x[i] = byte(b)
+		r += string(x)
+	}
+	if r != "AbcaBcabC" {
+		panic(r)
+	}
+}
+
+// Test of 3-operand x[lo:hi:max] slice.
+func init() {
+	s := []int{0, 1, 2, 3}
+	lenCapLoHi := func(x []int) [4]int { return [4]int{len(x), cap(x), x[0], x[len(x)-1]} }
+	if got := lenCapLoHi(s[1:3]); got != [4]int{2, 3, 1, 2} {
+		panic(got)
+	}
+	if got := lenCapLoHi(s[1:3:3]); got != [4]int{2, 2, 1, 2} {
+		panic(got)
+	}
+	max := 3
+	if "a"[0] == 'a' {
+		max = 2 // max is non-constant, even in SSA form
+	}
+	if got := lenCapLoHi(s[1:2:max]); got != [4]int{1, 1, 1, 1} {
+		panic(got)
+	}
+}
+
+// Test that a nice error is issue by indirection wrappers.
+func init() {
+	var ptr *T
+	var i I = ptr
+
+	defer func() {
+		r := fmt.Sprint(recover())
+		// Exact error varies by toolchain:
+		if r != "runtime error: value method (main.T).f called using nil *main.T pointer" &&
+			r != "value method main.T.f called using nil *T pointer" {
+			panic("want panic from call with nil receiver, got " + r)
+		}
+	}()
+	i.f()
+	panic("unreachable")
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/defer.go b/third_party/go.tools/go/ssa/interp/testdata/defer.go
new file mode 100644
index 0000000..f5bae6c
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/defer.go
@@ -0,0 +1,53 @@
+package main
+
+// Tests of defer.  (Deferred recover() belongs is recover.go.)
+
+import "fmt"
+
+func deferMutatesResults(noArgReturn bool) (a, b int) {
+	defer func() {
+		if a != 1 || b != 2 {
+			panic(fmt.Sprint(a, b))
+		}
+		a, b = 3, 4
+	}()
+	if noArgReturn {
+		a, b = 1, 2
+		return
+	}
+	return 1, 2
+}
+
+func init() {
+	a, b := deferMutatesResults(true)
+	if a != 3 || b != 4 {
+		panic(fmt.Sprint(a, b))
+	}
+	a, b = deferMutatesResults(false)
+	if a != 3 || b != 4 {
+		panic(fmt.Sprint(a, b))
+	}
+}
+
+// We concatenate init blocks to make a single function, but we must
+// run defers at the end of each block, not the combined function.
+var deferCount = 0
+
+func init() {
+	deferCount = 1
+	defer func() {
+		deferCount++
+	}()
+	// defer runs HERE
+}
+
+func init() {
+	// Strictly speaking the spec says deferCount may be 0 or 2
+	// since the relative order of init blocks is unspecified.
+	if deferCount != 2 {
+		panic(deferCount) // defer call has not run!
+	}
+}
+
+func main() {
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/fieldprom.go b/third_party/go.tools/go/ssa/interp/testdata/fieldprom.go
new file mode 100644
index 0000000..fc276dd
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/fieldprom.go
@@ -0,0 +1,114 @@
+package main
+
+// Tests of field promotion logic.
+
+type A struct {
+	x int
+	y *int
+}
+
+type B struct {
+	p int
+	q *int
+}
+
+type C struct {
+	A
+	*B
+}
+
+type D struct {
+	a int
+	C
+}
+
+func assert(cond bool) {
+	if !cond {
+		panic("failed")
+	}
+}
+
+func f1(c C) {
+	assert(c.x == c.A.x)
+	assert(c.y == c.A.y)
+	assert(&c.x == &c.A.x)
+	assert(&c.y == &c.A.y)
+
+	assert(c.p == c.B.p)
+	assert(c.q == c.B.q)
+	assert(&c.p == &c.B.p)
+	assert(&c.q == &c.B.q)
+
+	c.x = 1
+	*c.y = 1
+	c.p = 1
+	*c.q = 1
+}
+
+func f2(c *C) {
+	assert(c.x == c.A.x)
+	assert(c.y == c.A.y)
+	assert(&c.x == &c.A.x)
+	assert(&c.y == &c.A.y)
+
+	assert(c.p == c.B.p)
+	assert(c.q == c.B.q)
+	assert(&c.p == &c.B.p)
+	assert(&c.q == &c.B.q)
+
+	c.x = 1
+	*c.y = 1
+	c.p = 1
+	*c.q = 1
+}
+
+func f3(d D) {
+	assert(d.x == d.C.A.x)
+	assert(d.y == d.C.A.y)
+	assert(&d.x == &d.C.A.x)
+	assert(&d.y == &d.C.A.y)
+
+	assert(d.p == d.C.B.p)
+	assert(d.q == d.C.B.q)
+	assert(&d.p == &d.C.B.p)
+	assert(&d.q == &d.C.B.q)
+
+	d.x = 1
+	*d.y = 1
+	d.p = 1
+	*d.q = 1
+}
+
+func f4(d *D) {
+	assert(d.x == d.C.A.x)
+	assert(d.y == d.C.A.y)
+	assert(&d.x == &d.C.A.x)
+	assert(&d.y == &d.C.A.y)
+
+	assert(d.p == d.C.B.p)
+	assert(d.q == d.C.B.q)
+	assert(&d.p == &d.C.B.p)
+	assert(&d.q == &d.C.B.q)
+
+	d.x = 1
+	*d.y = 1
+	d.p = 1
+	*d.q = 1
+}
+
+func main() {
+	y := 123
+	c := C{
+		A{x: 42, y: &y},
+		&B{p: 42, q: &y},
+	}
+
+	assert(&c.x == &c.A.x)
+
+	f1(c)
+	f2(&c)
+
+	d := D{C: c}
+	f3(d)
+	f4(&d)
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/ifaceconv.go b/third_party/go.tools/go/ssa/interp/testdata/ifaceconv.go
new file mode 100644
index 0000000..96fc105
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/ifaceconv.go
@@ -0,0 +1,83 @@
+package main
+
+// Tests of interface conversions and type assertions.
+
+type I0 interface {
+}
+type I1 interface {
+	f()
+}
+type I2 interface {
+	f()
+	g()
+}
+
+type C0 struct{}
+type C1 struct{}
+
+func (C1) f() {}
+
+type C2 struct{}
+
+func (C2) f() {}
+func (C2) g() {}
+
+func main() {
+	var i0 I0
+	var i1 I1
+	var i2 I2
+
+	// Nil always causes a type assertion to fail, even to the
+	// same type.
+	if _, ok := i0.(I0); ok {
+		panic("nil i0.(I0) succeeded")
+	}
+	if _, ok := i1.(I1); ok {
+		panic("nil i1.(I1) succeeded")
+	}
+	if _, ok := i2.(I2); ok {
+		panic("nil i2.(I2) succeeded")
+	}
+
+	// Conversions can't fail, even with nil.
+	_ = I0(i0)
+
+	_ = I0(i1)
+	_ = I1(i1)
+
+	_ = I0(i2)
+	_ = I1(i2)
+	_ = I2(i2)
+
+	// Non-nil type assertions pass or fail based on the concrete type.
+	i1 = C1{}
+	if _, ok := i1.(I0); !ok {
+		panic("C1 i1.(I0) failed")
+	}
+	if _, ok := i1.(I1); !ok {
+		panic("C1 i1.(I1) failed")
+	}
+	if _, ok := i1.(I2); ok {
+		panic("C1 i1.(I2) succeeded")
+	}
+
+	i1 = C2{}
+	if _, ok := i1.(I0); !ok {
+		panic("C2 i1.(I0) failed")
+	}
+	if _, ok := i1.(I1); !ok {
+		panic("C2 i1.(I1) failed")
+	}
+	if _, ok := i1.(I2); !ok {
+		panic("C2 i1.(I2) failed")
+	}
+
+	// Conversions can't fail.
+	i1 = C1{}
+	if I0(i1) == nil {
+		panic("C1 I0(i1) was nil")
+	}
+	if I1(i1) == nil {
+		panic("C1 I1(i1) was nil")
+	}
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/ifaceprom.go b/third_party/go.tools/go/ssa/interp/testdata/ifaceprom.go
new file mode 100644
index 0000000..414dc73
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/ifaceprom.go
@@ -0,0 +1,58 @@
+package main
+
+// Test of promotion of methods of an interface embedded within a
+// struct.  In particular, this test exercises that the correct
+// method is called.
+
+type I interface {
+	one() int
+	two() string
+}
+
+type S struct {
+	I
+}
+
+type impl struct{}
+
+func (impl) one() int {
+	return 1
+}
+
+func (impl) two() string {
+	return "two"
+}
+
+func main() {
+	var s S
+	s.I = impl{}
+	if one := s.I.one(); one != 1 {
+		panic(one)
+	}
+	if one := s.one(); one != 1 {
+		panic(one)
+	}
+	closOne := s.I.one
+	if one := closOne(); one != 1 {
+		panic(one)
+	}
+	closOne = s.one
+	if one := closOne(); one != 1 {
+		panic(one)
+	}
+
+	if two := s.I.two(); two != "two" {
+		panic(two)
+	}
+	if two := s.two(); two != "two" {
+		panic(two)
+	}
+	closTwo := s.I.two
+	if two := closTwo(); two != "two" {
+		panic(two)
+	}
+	closTwo = s.two
+	if two := closTwo(); two != "two" {
+		panic(two)
+	}
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/initorder.go b/third_party/go.tools/go/ssa/interp/testdata/initorder.go
new file mode 100644
index 0000000..0f26bed
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/initorder.go
@@ -0,0 +1,67 @@
+package main
+
+import "fmt"
+
+// Test of initialization order of package-level vars.
+
+var counter int
+
+func next() int {
+	c := counter
+	counter++
+	return c
+}
+
+func next2() (x int, y int) {
+	x = next()
+	y = next()
+	return
+}
+
+func makeOrder() int {
+	_, _, _, _ = f, b, d, e
+	return 0
+}
+
+func main() {
+	// Initialization constraints:
+	// - {f,b,c/d,e} < order  (ref graph traversal)
+	// - order < {a}          (lexical order)
+	// - b < c/d < e < f      (lexical order)
+	// Solution: a b c/d e f
+	abcdef := [6]int{a, b, c, d, e, f}
+	if abcdef != [6]int{0, 1, 2, 3, 4, 5} {
+		panic(abcdef)
+	}
+}
+
+var order = makeOrder()
+
+var a, b = next(), next()
+var c, d = next2()
+var e, f = next(), next()
+
+// ------------------------------------------------------------------------
+
+var order2 []string
+
+func create(x int, name string) int {
+	order2 = append(order2, name)
+	return x
+}
+
+var C = create(B+1, "C")
+var A, B = create(1, "A"), create(2, "B")
+
+// Initialization order of package-level value specs.
+func init() {
+	x := fmt.Sprint(order2)
+	// Result varies by toolchain.  This is a spec bug.
+	if x != "[B C A]" && // gc
+		x != "[A B C]" { // go/types
+		panic(x)
+	}
+	if C != 3 {
+		panic(c)
+	}
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/methprom.go b/third_party/go.tools/go/ssa/interp/testdata/methprom.go
new file mode 100644
index 0000000..e8e384c
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/methprom.go
@@ -0,0 +1,93 @@
+package main
+
+// Tests of method promotion logic.
+
+type A struct{ magic int }
+
+func (a A) x() {
+	if a.magic != 1 {
+		panic(a.magic)
+	}
+}
+func (a *A) y() *A {
+	return a
+}
+
+type B struct{ magic int }
+
+func (b B) p() {
+	if b.magic != 2 {
+		panic(b.magic)
+	}
+}
+func (b *B) q() {
+	if b != theC.B {
+		panic("oops")
+	}
+}
+
+type I interface {
+	f()
+}
+
+type impl struct{ magic int }
+
+func (i impl) f() {
+	if i.magic != 3 {
+		panic("oops")
+	}
+}
+
+type C struct {
+	A
+	*B
+	I
+}
+
+func assert(cond bool) {
+	if !cond {
+		panic("failed")
+	}
+}
+
+var theC = C{
+	A: A{1},
+	B: &B{2},
+	I: impl{3},
+}
+
+func addr() *C {
+	return &theC
+}
+
+func value() C {
+	return theC
+}
+
+func main() {
+	// address
+	addr().x()
+	if addr().y() != &theC.A {
+		panic("oops")
+	}
+	addr().p()
+	addr().q()
+	addr().f()
+
+	// addressable value
+	var c C = value()
+	c.x()
+	if c.y() != &c.A {
+		panic("oops")
+	}
+	c.p()
+	c.q()
+	c.f()
+
+	// non-addressable value
+	value().x()
+	// value().y() // not in method set
+	value().p()
+	value().q()
+	value().f()
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/mrvchain.go b/third_party/go.tools/go/ssa/interp/testdata/mrvchain.go
new file mode 100644
index 0000000..70dfd02
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/mrvchain.go
@@ -0,0 +1,75 @@
+// Tests of call chaining f(g()) when g has multiple return values (MRVs).
+// See https://code.google.com/p/go/issues/detail?id=4573.
+
+package main
+
+func assert(actual, expected int) {
+	if actual != expected {
+		panic(actual)
+	}
+}
+
+func g() (int, int) {
+	return 5, 7
+}
+
+func g2() (float64, float64) {
+	return 5, 7
+}
+
+func f1v(x int, v ...int) {
+	assert(x, 5)
+	assert(v[0], 7)
+}
+
+func f2(x, y int) {
+	assert(x, 5)
+	assert(y, 7)
+}
+
+func f2v(x, y int, v ...int) {
+	assert(x, 5)
+	assert(y, 7)
+	assert(len(v), 0)
+}
+
+func complexArgs() (float64, float64) {
+	return 5, 7
+}
+
+func appendArgs() ([]string, string) {
+	return []string{"foo"}, "bar"
+}
+
+func h() (i interface{}, ok bool) {
+	m := map[int]string{1: "hi"}
+	i, ok = m[1] // string->interface{} conversion within multi-valued expression
+	return
+}
+
+func h2() (i interface{}, ok bool) {
+	ch := make(chan string, 1)
+	ch <- "hi"
+	i, ok = <-ch // string->interface{} conversion within multi-valued expression
+	return
+}
+
+func main() {
+	f1v(g())
+	f2(g())
+	f2v(g())
+	if c := complex(complexArgs()); c != 5+7i {
+		panic(c)
+	}
+	if s := append(appendArgs()); len(s) != 2 || s[0] != "foo" || s[1] != "bar" {
+		panic(s)
+	}
+	i, ok := h()
+	if !ok || i.(string) != "hi" {
+		panic(i)
+	}
+	i, ok = h2()
+	if !ok || i.(string) != "hi" {
+		panic(i)
+	}
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/range.go b/third_party/go.tools/go/ssa/interp/testdata/range.go
new file mode 100644
index 0000000..da8a421
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/range.go
@@ -0,0 +1,55 @@
+package main
+
+// Tests of range loops.
+
+import "fmt"
+
+// Range over string.
+func init() {
+	if x := len("Hello, 世界"); x != 13 { // bytes
+		panic(x)
+	}
+	var indices []int
+	var runes []rune
+	for i, r := range "Hello, 世界" {
+		runes = append(runes, r)
+		indices = append(indices, i)
+	}
+	if x := fmt.Sprint(runes); x != "[72 101 108 108 111 44 32 19990 30028]" {
+		panic(x)
+	}
+	if x := fmt.Sprint(indices); x != "[0 1 2 3 4 5 6 7 10]" {
+		panic(x)
+	}
+	s := ""
+	for _, r := range runes {
+		s = fmt.Sprintf("%s%c", s, r)
+	}
+	if s != "Hello, 世界" {
+		panic(s)
+	}
+
+	var x int
+	for range "Hello, 世界" {
+		x++
+	}
+	if x != len(indices) {
+		panic(x)
+	}
+}
+
+// Regression test for range of pointer to named array type.
+func init() {
+	type intarr [3]int
+	ia := intarr{1, 2, 3}
+	var count int
+	for _, x := range &ia {
+		count += x
+	}
+	if count != 6 {
+		panic(count)
+	}
+}
+
+func main() {
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/recover.go b/third_party/go.tools/go/ssa/interp/testdata/recover.go
new file mode 100644
index 0000000..b560052
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/recover.go
@@ -0,0 +1,34 @@
+package main
+
+// Tests of panic/recover.
+
+import "fmt"
+
+func fortyTwo() (r int) {
+	r = 42
+	// The next two statements simulate a 'return' statement.
+	defer func() { recover() }()
+	panic(nil)
+}
+
+func zero() int {
+	defer func() { recover() }()
+	panic(1)
+}
+
+func zeroEmpty() (int, string) {
+	defer func() { recover() }()
+	panic(1)
+}
+
+func main() {
+	if r := fortyTwo(); r != 42 {
+		panic(r)
+	}
+	if r := zero(); r != 0 {
+		panic(r)
+	}
+	if r, s := zeroEmpty(); r != 0 || s != "" {
+		panic(fmt.Sprint(r, s))
+	}
+}
diff --git a/third_party/go.tools/go/ssa/interp/testdata/static.go b/third_party/go.tools/go/ssa/interp/testdata/static.go
new file mode 100644
index 0000000..b115513
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/testdata/static.go
@@ -0,0 +1,58 @@
+package main
+
+// Static tests of SSA builder (via the sanity checker).
+// Dynamic semantics are not exercised.
+
+func init() {
+	// Regression test for issue 6806.
+	ch := make(chan int)
+	select {
+	case n, _ := <-ch:
+		_ = n
+	default:
+		// The default case disables the simplification of
+		// select to a simple receive statement.
+	}
+
+	// value,ok-form receive where TypeOf(ok) is a named boolean.
+	type mybool bool
+	var x int
+	var y mybool
+	select {
+	case x, y = <-ch:
+	default:
+		// The default case disables the simplification of
+		// select to a simple receive statement.
+	}
+	_ = x
+	_ = y
+}
+
+var a int
+
+// Regression test for issue 7840 (covered by SSA sanity checker).
+func bug7840() bool {
+	// This creates a single-predecessor block with a φ-node.
+	return false && a == 0 && a == 0
+}
+
+// A blocking select (sans "default:") cannot fall through.
+// Regression test for issue 7022.
+func bug7022() int {
+	var c1, c2 chan int
+	select {
+	case <-c1:
+		return 123
+	case <-c2:
+		return 456
+	}
+}
+
+// Parens should not prevent intrinsic treatment of built-ins.
+// (Regression test for a crash.)
+func init() {
+	_ = (new)(int)
+	_ = (make)([]int, 0)
+}
+
+func main() {}
diff --git a/third_party/go.tools/go/ssa/interp/value.go b/third_party/go.tools/go/ssa/interp/value.go
new file mode 100644
index 0000000..67717ed
--- /dev/null
+++ b/third_party/go.tools/go/ssa/interp/value.go
@@ -0,0 +1,487 @@
+// Copyright 2013 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 interp
+
+// Values
+//
+// All interpreter values are "boxed" in the empty interface, value.
+// The range of possible dynamic types within value are:
+//
+// - bool
+// - numbers (all built-in int/float/complex types are distinguished)
+// - string
+// - map[value]value --- maps for which  usesBuiltinMap(keyType)
+//   *hashmap        --- maps for which !usesBuiltinMap(keyType)
+// - chan value
+// - []value --- slices
+// - iface --- interfaces.
+// - structure --- structs.  Fields are ordered and accessed by numeric indices.
+// - array --- arrays.
+// - *value --- pointers.  Careful: *value is a distinct type from *array etc.
+// - *ssa.Function \
+//   *ssa.Builtin   } --- functions.  A nil 'func' is always of type *ssa.Function.
+//   *closure      /
+// - tuple --- as returned by Return, Next, "value,ok" modes, etc.
+// - iter --- iterators from 'range' over map or string.
+// - bad --- a poison pill for locals that have gone out of scope.
+// - rtype -- the interpreter's concrete implementation of reflect.Type
+//
+// Note that nil is not on this list.
+//
+// Pay close attention to whether or not the dynamic type is a pointer.
+// The compiler cannot help you since value is an empty interface.
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"strings"
+	"sync"
+	"unsafe"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+type value interface{}
+
+type tuple []value
+
+type array []value
+
+type iface struct {
+	t types.Type // never an "untyped" type
+	v value
+}
+
+type structure []value
+
+// For map, array, *array, slice, string or channel.
+type iter interface {
+	// next returns a Tuple (key, value, ok).
+	// key and value are unaliased, e.g. copies of the sequence element.
+	next() tuple
+}
+
+type closure struct {
+	Fn  *ssa.Function
+	Env []value
+}
+
+type bad struct{}
+
+type rtype struct {
+	t types.Type
+}
+
+// Hash functions and equivalence relation:
+
+// hashString computes the FNV hash of s.
+func hashString(s string) int {
+	var h uint32
+	for i := 0; i < len(s); i++ {
+		h ^= uint32(s[i])
+		h *= 16777619
+	}
+	return int(h)
+}
+
+var (
+	mu     sync.Mutex
+	hasher = typeutil.MakeHasher()
+)
+
+// hashType returns a hash for t such that
+// types.Identical(x, y) => hashType(x) == hashType(y).
+func hashType(t types.Type) int {
+	mu.Lock()
+	h := int(hasher.Hash(t))
+	mu.Unlock()
+	return h
+}
+
+// usesBuiltinMap returns true if the built-in hash function and
+// equivalence relation for type t are consistent with those of the
+// interpreter's representation of type t.  Such types are: all basic
+// types (bool, numbers, string), pointers and channels.
+//
+// usesBuiltinMap returns false for types that require a custom map
+// implementation: interfaces, arrays and structs.
+//
+// Panic ensues if t is an invalid map key type: function, map or slice.
+func usesBuiltinMap(t types.Type) bool {
+	switch t := t.(type) {
+	case *types.Basic, *types.Chan, *types.Pointer:
+		return true
+	case *types.Named:
+		return usesBuiltinMap(t.Underlying())
+	case *types.Interface, *types.Array, *types.Struct:
+		return false
+	}
+	panic(fmt.Sprintf("invalid map key type: %T", t))
+}
+
+func (x array) eq(t types.Type, _y interface{}) bool {
+	y := _y.(array)
+	tElt := t.Underlying().(*types.Array).Elem()
+	for i, xi := range x {
+		if !equals(tElt, xi, y[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+func (x array) hash(t types.Type) int {
+	h := 0
+	tElt := t.Underlying().(*types.Array).Elem()
+	for _, xi := range x {
+		h += hash(tElt, xi)
+	}
+	return h
+}
+
+func (x structure) eq(t types.Type, _y interface{}) bool {
+	y := _y.(structure)
+	tStruct := t.Underlying().(*types.Struct)
+	for i, n := 0, tStruct.NumFields(); i < n; i++ {
+		if f := tStruct.Field(i); !f.Anonymous() {
+			if !equals(f.Type(), x[i], y[i]) {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+func (x structure) hash(t types.Type) int {
+	tStruct := t.Underlying().(*types.Struct)
+	h := 0
+	for i, n := 0, tStruct.NumFields(); i < n; i++ {
+		if f := tStruct.Field(i); !f.Anonymous() {
+			h += hash(f.Type(), x[i])
+		}
+	}
+	return h
+}
+
+// nil-tolerant variant of types.Identical.
+func sameType(x, y types.Type) bool {
+	if x == nil {
+		return y == nil
+	}
+	return y != nil && types.Identical(x, y)
+}
+
+func (x iface) eq(t types.Type, _y interface{}) bool {
+	y := _y.(iface)
+	return sameType(x.t, y.t) && (x.t == nil || equals(x.t, x.v, y.v))
+}
+
+func (x iface) hash(_ types.Type) int {
+	return hashType(x.t)*8581 + hash(x.t, x.v)
+}
+
+func (x rtype) hash(_ types.Type) int {
+	return hashType(x.t)
+}
+
+func (x rtype) eq(_ types.Type, y interface{}) bool {
+	return types.Identical(x.t, y.(rtype).t)
+}
+
+// equals returns true iff x and y are equal according to Go's
+// linguistic equivalence relation for type t.
+// In a well-typed program, the dynamic types of x and y are
+// guaranteed equal.
+func equals(t types.Type, x, y value) bool {
+	switch x := x.(type) {
+	case bool:
+		return x == y.(bool)
+	case int:
+		return x == y.(int)
+	case int8:
+		return x == y.(int8)
+	case int16:
+		return x == y.(int16)
+	case int32:
+		return x == y.(int32)
+	case int64:
+		return x == y.(int64)
+	case uint:
+		return x == y.(uint)
+	case uint8:
+		return x == y.(uint8)
+	case uint16:
+		return x == y.(uint16)
+	case uint32:
+		return x == y.(uint32)
+	case uint64:
+		return x == y.(uint64)
+	case uintptr:
+		return x == y.(uintptr)
+	case float32:
+		return x == y.(float32)
+	case float64:
+		return x == y.(float64)
+	case complex64:
+		return x == y.(complex64)
+	case complex128:
+		return x == y.(complex128)
+	case string:
+		return x == y.(string)
+	case *value:
+		return x == y.(*value)
+	case chan value:
+		return x == y.(chan value)
+	case structure:
+		return x.eq(t, y)
+	case array:
+		return x.eq(t, y)
+	case iface:
+		return x.eq(t, y)
+	case rtype:
+		return x.eq(t, y)
+	}
+
+	// Since map, func and slice don't support comparison, this
+	// case is only reachable if one of x or y is literally nil
+	// (handled in eqnil) or via interface{} values.
+	panic(fmt.Sprintf("comparing uncomparable type %s", t))
+}
+
+// Returns an integer hash of x such that equals(x, y) => hash(x) == hash(y).
+func hash(t types.Type, x value) int {
+	switch x := x.(type) {
+	case bool:
+		if x {
+			return 1
+		}
+		return 0
+	case int:
+		return x
+	case int8:
+		return int(x)
+	case int16:
+		return int(x)
+	case int32:
+		return int(x)
+	case int64:
+		return int(x)
+	case uint:
+		return int(x)
+	case uint8:
+		return int(x)
+	case uint16:
+		return int(x)
+	case uint32:
+		return int(x)
+	case uint64:
+		return int(x)
+	case uintptr:
+		return int(x)
+	case float32:
+		return int(x)
+	case float64:
+		return int(x)
+	case complex64:
+		return int(real(x))
+	case complex128:
+		return int(real(x))
+	case string:
+		return hashString(x)
+	case *value:
+		return int(uintptr(unsafe.Pointer(x)))
+	case chan value:
+		return int(uintptr(reflect.ValueOf(x).Pointer()))
+	case structure:
+		return x.hash(t)
+	case array:
+		return x.hash(t)
+	case iface:
+		return x.hash(t)
+	case rtype:
+		return x.hash(t)
+	}
+	panic(fmt.Sprintf("%T is unhashable", x))
+}
+
+// copyVal returns a copy of value v.
+// TODO(adonovan): add tests of aliasing and mutation.
+func copyVal(v value) value {
+	if v == nil {
+		panic("copyVal(nil)")
+	}
+	switch v := v.(type) {
+	case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128, string, unsafe.Pointer:
+		return v
+	case map[value]value:
+		return v
+	case *hashmap:
+		return v
+	case chan value:
+		return v
+	case *value:
+		return v
+	case *ssa.Function, *ssa.Builtin, *closure:
+		return v
+	case iface:
+		return v
+	case []value:
+		return v
+	case structure:
+		a := make(structure, len(v))
+		copy(a, v)
+		return a
+	case array:
+		a := make(array, len(v))
+		copy(a, v)
+		return a
+	case tuple:
+		break
+	case rtype:
+		return v
+	}
+	panic(fmt.Sprintf("cannot copy %T", v))
+}
+
+// Prints in the style of built-in println.
+// (More or less; in gc println is actually a compiler intrinsic and
+// can distinguish println(1) from println(interface{}(1)).)
+func writeValue(buf *bytes.Buffer, v value) {
+	switch v := v.(type) {
+	case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128, string:
+		fmt.Fprintf(buf, "%v", v)
+
+	case map[value]value:
+		buf.WriteString("map[")
+		sep := ""
+		for k, e := range v {
+			buf.WriteString(sep)
+			sep = " "
+			writeValue(buf, k)
+			buf.WriteString(":")
+			writeValue(buf, e)
+		}
+		buf.WriteString("]")
+
+	case *hashmap:
+		buf.WriteString("map[")
+		sep := " "
+		for _, e := range v.table {
+			for e != nil {
+				buf.WriteString(sep)
+				sep = " "
+				writeValue(buf, e.key)
+				buf.WriteString(":")
+				writeValue(buf, e.value)
+				e = e.next
+			}
+		}
+		buf.WriteString("]")
+
+	case chan value:
+		fmt.Fprintf(buf, "%v", v) // (an address)
+
+	case *value:
+		if v == nil {
+			buf.WriteString("<nil>")
+		} else {
+			fmt.Fprintf(buf, "%p", v)
+		}
+
+	case iface:
+		fmt.Fprintf(buf, "(%s, ", v.t)
+		writeValue(buf, v.v)
+		buf.WriteString(")")
+
+	case structure:
+		buf.WriteString("{")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(" ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString("}")
+
+	case array:
+		buf.WriteString("[")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(" ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString("]")
+
+	case []value:
+		buf.WriteString("[")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(" ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString("]")
+
+	case *ssa.Function, *ssa.Builtin, *closure:
+		fmt.Fprintf(buf, "%p", v) // (an address)
+
+	case rtype:
+		buf.WriteString(v.t.String())
+
+	case tuple:
+		// Unreachable in well-formed Go programs
+		buf.WriteString("(")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString(")")
+
+	default:
+		fmt.Fprintf(buf, "<%T>", v)
+	}
+}
+
+// Implements printing of Go values in the style of built-in println.
+func toString(v value) string {
+	var b bytes.Buffer
+	writeValue(&b, v)
+	return b.String()
+}
+
+// ------------------------------------------------------------------------
+// Iterators
+
+type stringIter struct {
+	*strings.Reader
+	i int
+}
+
+func (it *stringIter) next() tuple {
+	okv := make(tuple, 3)
+	ch, n, err := it.ReadRune()
+	ok := err != io.EOF
+	okv[0] = ok
+	if ok {
+		okv[1] = it.i
+		okv[2] = ch
+	}
+	it.i += n
+	return okv
+}
+
+type mapIter chan [2]value
+
+func (it mapIter) next() tuple {
+	kv, ok := <-it
+	return tuple{ok, kv[0], kv[1]}
+}
diff --git a/third_party/go.tools/go/ssa/lift.go b/third_party/go.tools/go/ssa/lift.go
new file mode 100644
index 0000000..85f162d
--- /dev/null
+++ b/third_party/go.tools/go/ssa/lift.go
@@ -0,0 +1,599 @@
+// Copyright 2013 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 ssa
+
+// This file defines the lifting pass which tries to "lift" Alloc
+// cells (new/local variables) into SSA registers, replacing loads
+// with the dominating stored value, eliminating loads and stores, and
+// inserting φ-nodes as needed.
+
+// Cited papers and resources:
+//
+// Ron Cytron et al. 1991. Efficiently computing SSA form...
+// http://doi.acm.org/10.1145/115372.115320
+//
+// Cooper, Harvey, Kennedy.  2001.  A Simple, Fast Dominance Algorithm.
+// Software Practice and Experience 2001, 4:1-10.
+// http://www.hipersoft.rice.edu/grads/publications/dom14.pdf
+//
+// Daniel Berlin, llvmdev mailing list, 2012.
+// http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-January/046638.html
+// (Be sure to expand the whole thread.)
+
+// TODO(adonovan): opt: there are many optimizations worth evaluating, and
+// the conventional wisdom for SSA construction is that a simple
+// algorithm well engineered often beats those of better asymptotic
+// complexity on all but the most egregious inputs.
+//
+// Danny Berlin suggests that the Cooper et al. algorithm for
+// computing the dominance frontier is superior to Cytron et al.
+// Furthermore he recommends that rather than computing the DF for the
+// whole function then renaming all alloc cells, it may be cheaper to
+// compute the DF for each alloc cell separately and throw it away.
+//
+// Consider exploiting liveness information to avoid creating dead
+// φ-nodes which we then immediately remove.
+//
+// Integrate lifting with scalar replacement of aggregates (SRA) since
+// the two are synergistic.
+//
+// Also see many other "TODO: opt" suggestions in the code.
+
+import (
+	"fmt"
+	"go/token"
+	"math/big"
+	"os"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// If true, perform sanity checking and show diagnostic information at
+// each step of lifting.  Very verbose.
+const debugLifting = false
+
+// domFrontier maps each block to the set of blocks in its dominance
+// frontier.  The outer slice is conceptually a map keyed by
+// Block.Index.  The inner slice is conceptually a set, possibly
+// containing duplicates.
+//
+// TODO(adonovan): opt: measure impact of dups; consider a packed bit
+// representation, e.g. big.Int, and bitwise parallel operations for
+// the union step in the Children loop.
+//
+// domFrontier's methods mutate the slice's elements but not its
+// length, so their receivers needn't be pointers.
+//
+type domFrontier [][]*BasicBlock
+
+func (df domFrontier) add(u, v *BasicBlock) {
+	p := &df[u.Index]
+	*p = append(*p, v)
+}
+
+// build builds the dominance frontier df for the dominator (sub)tree
+// rooted at u, using the Cytron et al. algorithm.
+//
+// TODO(adonovan): opt: consider Berlin approach, computing pruned SSA
+// by pruning the entire IDF computation, rather than merely pruning
+// the DF -> IDF step.
+func (df domFrontier) build(u *BasicBlock) {
+	// Encounter each node u in postorder of dom tree.
+	for _, child := range u.dom.children {
+		df.build(child)
+	}
+	for _, vb := range u.Succs {
+		if v := vb.dom; v.idom != u {
+			df.add(u, vb)
+		}
+	}
+	for _, w := range u.dom.children {
+		for _, vb := range df[w.Index] {
+			// TODO(adonovan): opt: use word-parallel bitwise union.
+			if v := vb.dom; v.idom != u {
+				df.add(u, vb)
+			}
+		}
+	}
+}
+
+func buildDomFrontier(fn *Function) domFrontier {
+	df := make(domFrontier, len(fn.Blocks))
+	df.build(fn.Blocks[0])
+	if fn.Recover != nil {
+		df.build(fn.Recover)
+	}
+	return df
+}
+
+func removeInstr(refs []Instruction, instr Instruction) []Instruction {
+	i := 0
+	for _, ref := range refs {
+		if ref == instr {
+			continue
+		}
+		refs[i] = ref
+		i++
+	}
+	for j := i; j != len(refs); j++ {
+		refs[j] = nil // aid GC
+	}
+	return refs[:i]
+}
+
+// lift attempts to replace local and new Allocs accessed only with
+// load/store by SSA registers, inserting φ-nodes where necessary.
+// The result is a program in classical pruned SSA form.
+//
+// Preconditions:
+// - fn has no dead blocks (blockopt has run).
+// - Def/use info (Operands and Referrers) is up-to-date.
+// - The dominator tree is up-to-date.
+//
+func lift(fn *Function) {
+	// TODO(adonovan): opt: lots of little optimizations may be
+	// worthwhile here, especially if they cause us to avoid
+	// buildDomFrontier.  For example:
+	//
+	// - Alloc never loaded?  Eliminate.
+	// - Alloc never stored?  Replace all loads with a zero constant.
+	// - Alloc stored once?  Replace loads with dominating store;
+	//   don't forget that an Alloc is itself an effective store
+	//   of zero.
+	// - Alloc used only within a single block?
+	//   Use degenerate algorithm avoiding φ-nodes.
+	// - Consider synergy with scalar replacement of aggregates (SRA).
+	//   e.g. *(&x.f) where x is an Alloc.
+	//   Perhaps we'd get better results if we generated this as x.f
+	//   i.e. Field(x, .f) instead of Load(FieldIndex(x, .f)).
+	//   Unclear.
+	//
+	// But we will start with the simplest correct code.
+	df := buildDomFrontier(fn)
+
+	if debugLifting {
+		title := false
+		for i, blocks := range df {
+			if blocks != nil {
+				if !title {
+					fmt.Fprintf(os.Stderr, "Dominance frontier of %s:\n", fn)
+					title = true
+				}
+				fmt.Fprintf(os.Stderr, "\t%s: %s\n", fn.Blocks[i], blocks)
+			}
+		}
+	}
+
+	newPhis := make(newPhiMap)
+
+	// During this pass we will replace some BasicBlock.Instrs
+	// (allocs, loads and stores) with nil, keeping a count in
+	// BasicBlock.gaps.  At the end we will reset Instrs to the
+	// concatenation of all non-dead newPhis and non-nil Instrs
+	// for the block, reusing the original array if space permits.
+
+	// While we're here, we also eliminate 'rundefers'
+	// instructions in functions that contain no 'defer'
+	// instructions.
+	usesDefer := false
+
+	// Determine which allocs we can lift and number them densely.
+	// The renaming phase uses this numbering for compact maps.
+	numAllocs := 0
+	for _, b := range fn.Blocks {
+		b.gaps = 0
+		b.rundefers = 0
+		for _, instr := range b.Instrs {
+			switch instr := instr.(type) {
+			case *Alloc:
+				index := -1
+				if liftAlloc(df, instr, newPhis) {
+					index = numAllocs
+					numAllocs++
+				}
+				instr.index = index
+			case *Defer:
+				usesDefer = true
+			case *RunDefers:
+				b.rundefers++
+			}
+		}
+	}
+
+	// renaming maps an alloc (keyed by index) to its replacement
+	// value.  Initially the renaming contains nil, signifying the
+	// zero constant of the appropriate type; we construct the
+	// Const lazily at most once on each path through the domtree.
+	// TODO(adonovan): opt: cache per-function not per subtree.
+	renaming := make([]Value, numAllocs)
+
+	// Renaming.
+	rename(fn.Blocks[0], renaming, newPhis)
+
+	// Eliminate dead new phis, then prepend the live ones to each block.
+	for _, b := range fn.Blocks {
+
+		// Compress the newPhis slice to eliminate unused phis.
+		// TODO(adonovan): opt: compute liveness to avoid
+		// placing phis in blocks for which the alloc cell is
+		// not live.
+		nps := newPhis[b]
+		j := 0
+		for _, np := range nps {
+			if !phiIsLive(np.phi) {
+				// discard it, first removing it from referrers
+				for _, newval := range np.phi.Edges {
+					if refs := newval.Referrers(); refs != nil {
+						*refs = removeInstr(*refs, np.phi)
+					}
+				}
+				continue
+			}
+			nps[j] = np
+			j++
+		}
+		nps = nps[:j]
+
+		rundefersToKill := b.rundefers
+		if usesDefer {
+			rundefersToKill = 0
+		}
+
+		if j+b.gaps+rundefersToKill == 0 {
+			continue // fast path: no new phis or gaps
+		}
+
+		// Compact nps + non-nil Instrs into a new slice.
+		// TODO(adonovan): opt: compact in situ if there is
+		// sufficient space or slack in the slice.
+		dst := make([]Instruction, len(b.Instrs)+j-b.gaps-rundefersToKill)
+		for i, np := range nps {
+			dst[i] = np.phi
+		}
+		for _, instr := range b.Instrs {
+			if instr == nil {
+				continue
+			}
+			if !usesDefer {
+				if _, ok := instr.(*RunDefers); ok {
+					continue
+				}
+			}
+			dst[j] = instr
+			j++
+		}
+		for i, np := range nps {
+			dst[i] = np.phi
+		}
+		b.Instrs = dst
+	}
+
+	// Remove any fn.Locals that were lifted.
+	j := 0
+	for _, l := range fn.Locals {
+		if l.index < 0 {
+			fn.Locals[j] = l
+			j++
+		}
+	}
+	// Nil out fn.Locals[j:] to aid GC.
+	for i := j; i < len(fn.Locals); i++ {
+		fn.Locals[i] = nil
+	}
+	fn.Locals = fn.Locals[:j]
+}
+
+func phiIsLive(phi *Phi) bool {
+	for _, instr := range *phi.Referrers() {
+		if instr == phi {
+			continue // self-refs don't count
+		}
+		if _, ok := instr.(*DebugRef); ok {
+			continue // debug refs don't count
+		}
+		return true
+	}
+	return false
+}
+
+type blockSet struct{ big.Int } // (inherit methods from Int)
+
+// add adds b to the set and returns true if the set changed.
+func (s *blockSet) add(b *BasicBlock) bool {
+	i := b.Index
+	if s.Bit(i) != 0 {
+		return false
+	}
+	s.SetBit(&s.Int, i, 1)
+	return true
+}
+
+// take removes an arbitrary element from a set s and
+// returns its index, or returns -1 if empty.
+func (s *blockSet) take() int {
+	l := s.BitLen()
+	for i := 0; i < l; i++ {
+		if s.Bit(i) == 1 {
+			s.SetBit(&s.Int, i, 0)
+			return i
+		}
+	}
+	return -1
+}
+
+// newPhi is a pair of a newly introduced φ-node and the lifted Alloc
+// it replaces.
+type newPhi struct {
+	phi   *Phi
+	alloc *Alloc
+}
+
+// newPhiMap records for each basic block, the set of newPhis that
+// must be prepended to the block.
+type newPhiMap map[*BasicBlock][]newPhi
+
+// liftAlloc determines whether alloc can be lifted into registers,
+// and if so, it populates newPhis with all the φ-nodes it may require
+// and returns true.
+//
+func liftAlloc(df domFrontier, alloc *Alloc, newPhis newPhiMap) bool {
+	// Don't lift aggregates into registers, because we don't have
+	// a way to express their zero-constants.
+	switch deref(alloc.Type()).Underlying().(type) {
+	case *types.Array, *types.Struct:
+		return false
+	}
+
+	// Don't lift named return values in functions that defer
+	// calls that may recover from panic.
+	if fn := alloc.Parent(); fn.Recover != nil {
+		for _, nr := range fn.namedResults {
+			if nr == alloc {
+				return false
+			}
+		}
+	}
+
+	// Compute defblocks, the set of blocks containing a
+	// definition of the alloc cell.
+	var defblocks blockSet
+	for _, instr := range *alloc.Referrers() {
+		// Bail out if we discover the alloc is not liftable;
+		// the only operations permitted to use the alloc are
+		// loads/stores into the cell, and DebugRef.
+		switch instr := instr.(type) {
+		case *Store:
+			if instr.Val == alloc {
+				return false // address used as value
+			}
+			if instr.Addr != alloc {
+				panic("Alloc.Referrers is inconsistent")
+			}
+			defblocks.add(instr.Block())
+		case *UnOp:
+			if instr.Op != token.MUL {
+				return false // not a load
+			}
+			if instr.X != alloc {
+				panic("Alloc.Referrers is inconsistent")
+			}
+		case *DebugRef:
+			// ok
+		default:
+			return false // some other instruction
+		}
+	}
+	// The Alloc itself counts as a (zero) definition of the cell.
+	defblocks.add(alloc.Block())
+
+	if debugLifting {
+		fmt.Fprintln(os.Stderr, "\tlifting ", alloc, alloc.Name())
+	}
+
+	fn := alloc.Parent()
+
+	// Φ-insertion.
+	//
+	// What follows is the body of the main loop of the insert-φ
+	// function described by Cytron et al, but instead of using
+	// counter tricks, we just reset the 'hasAlready' and 'work'
+	// sets each iteration.  These are bitmaps so it's pretty cheap.
+	//
+	// TODO(adonovan): opt: recycle slice storage for W,
+	// hasAlready, defBlocks across liftAlloc calls.
+	var hasAlready blockSet
+
+	// Initialize W and work to defblocks.
+	var work blockSet = defblocks // blocks seen
+	var W blockSet                // blocks to do
+	W.Set(&defblocks.Int)
+
+	// Traverse iterated dominance frontier, inserting φ-nodes.
+	for i := W.take(); i != -1; i = W.take() {
+		u := fn.Blocks[i]
+		for _, v := range df[u.Index] {
+			if hasAlready.add(v) {
+				// Create φ-node.
+				// It will be prepended to v.Instrs later, if needed.
+				phi := &Phi{
+					Edges:   make([]Value, len(v.Preds)),
+					Comment: alloc.Comment,
+				}
+				phi.pos = alloc.Pos()
+				phi.setType(deref(alloc.Type()))
+				phi.block = v
+				if debugLifting {
+					fmt.Fprintf(os.Stderr, "\tplace %s = %s at block %s\n", phi.Name(), phi, v)
+				}
+				newPhis[v] = append(newPhis[v], newPhi{phi, alloc})
+
+				if work.add(v) {
+					W.add(v)
+				}
+			}
+		}
+	}
+
+	return true
+}
+
+// replaceAll replaces all intraprocedural uses of x with y,
+// updating x.Referrers and y.Referrers.
+// Precondition: x.Referrers() != nil, i.e. x must be local to some function.
+//
+func replaceAll(x, y Value) {
+	var rands []*Value
+	pxrefs := x.Referrers()
+	pyrefs := y.Referrers()
+	for _, instr := range *pxrefs {
+		rands = instr.Operands(rands[:0]) // recycle storage
+		for _, rand := range rands {
+			if *rand != nil {
+				if *rand == x {
+					*rand = y
+				}
+			}
+		}
+		if pyrefs != nil {
+			*pyrefs = append(*pyrefs, instr) // dups ok
+		}
+	}
+	*pxrefs = nil // x is now unreferenced
+}
+
+// renamed returns the value to which alloc is being renamed,
+// constructing it lazily if it's the implicit zero initialization.
+//
+func renamed(renaming []Value, alloc *Alloc) Value {
+	v := renaming[alloc.index]
+	if v == nil {
+		v = zeroConst(deref(alloc.Type()))
+		renaming[alloc.index] = v
+	}
+	return v
+}
+
+// rename implements the (Cytron et al) SSA renaming algorithm, a
+// preorder traversal of the dominator tree replacing all loads of
+// Alloc cells with the value stored to that cell by the dominating
+// store instruction.  For lifting, we need only consider loads,
+// stores and φ-nodes.
+//
+// renaming is a map from *Alloc (keyed by index number) to its
+// dominating stored value; newPhis[x] is the set of new φ-nodes to be
+// prepended to block x.
+//
+func rename(u *BasicBlock, renaming []Value, newPhis newPhiMap) {
+	// Each φ-node becomes the new name for its associated Alloc.
+	for _, np := range newPhis[u] {
+		phi := np.phi
+		alloc := np.alloc
+		renaming[alloc.index] = phi
+	}
+
+	// Rename loads and stores of allocs.
+	for i, instr := range u.Instrs {
+		switch instr := instr.(type) {
+		case *Alloc:
+			if instr.index >= 0 { // store of zero to Alloc cell
+				// Replace dominated loads by the zero value.
+				renaming[instr.index] = nil
+				if debugLifting {
+					fmt.Fprintf(os.Stderr, "\tkill alloc %s\n", instr)
+				}
+				// Delete the Alloc.
+				u.Instrs[i] = nil
+				u.gaps++
+			}
+
+		case *Store:
+			if alloc, ok := instr.Addr.(*Alloc); ok && alloc.index >= 0 { // store to Alloc cell
+				// Replace dominated loads by the stored value.
+				renaming[alloc.index] = instr.Val
+				if debugLifting {
+					fmt.Fprintf(os.Stderr, "\tkill store %s; new value: %s\n",
+						instr, instr.Val.Name())
+				}
+				// Remove the store from the referrer list of the stored value.
+				if refs := instr.Val.Referrers(); refs != nil {
+					*refs = removeInstr(*refs, instr)
+				}
+				// Delete the Store.
+				u.Instrs[i] = nil
+				u.gaps++
+			}
+
+		case *UnOp:
+			if instr.Op == token.MUL {
+				if alloc, ok := instr.X.(*Alloc); ok && alloc.index >= 0 { // load of Alloc cell
+					newval := renamed(renaming, alloc)
+					if debugLifting {
+						fmt.Fprintf(os.Stderr, "\tupdate load %s = %s with %s\n",
+							instr.Name(), instr, newval.Name())
+					}
+					// Replace all references to
+					// the loaded value by the
+					// dominating stored value.
+					replaceAll(instr, newval)
+					// Delete the Load.
+					u.Instrs[i] = nil
+					u.gaps++
+				}
+			}
+
+		case *DebugRef:
+			if alloc, ok := instr.X.(*Alloc); ok && alloc.index >= 0 { // ref of Alloc cell
+				if instr.IsAddr {
+					instr.X = renamed(renaming, alloc)
+					instr.IsAddr = false
+
+					// Add DebugRef to instr.X's referrers.
+					if refs := instr.X.Referrers(); refs != nil {
+						*refs = append(*refs, instr)
+					}
+				} else {
+					// A source expression denotes the address
+					// of an Alloc that was optimized away.
+					instr.X = nil
+
+					// Delete the DebugRef.
+					u.Instrs[i] = nil
+					u.gaps++
+				}
+			}
+		}
+	}
+
+	// For each φ-node in a CFG successor, rename the edge.
+	for _, v := range u.Succs {
+		phis := newPhis[v]
+		if len(phis) == 0 {
+			continue
+		}
+		i := v.predIndex(u)
+		for _, np := range phis {
+			phi := np.phi
+			alloc := np.alloc
+			newval := renamed(renaming, alloc)
+			if debugLifting {
+				fmt.Fprintf(os.Stderr, "\tsetphi %s edge %s -> %s (#%d) (alloc=%s) := %s\n",
+					phi.Name(), u, v, i, alloc.Name(), newval.Name())
+			}
+			phi.Edges[i] = newval
+			if prefs := newval.Referrers(); prefs != nil {
+				*prefs = append(*prefs, phi)
+			}
+		}
+	}
+
+	// Continue depth-first recursion over domtree, pushing a
+	// fresh copy of the renaming map for each subtree.
+	for _, v := range u.dom.children {
+		// TODO(adonovan): opt: avoid copy on final iteration; use destructive update.
+		r := make([]Value, len(renaming))
+		copy(r, renaming)
+		rename(v, r, newPhis)
+	}
+}
diff --git a/third_party/go.tools/go/ssa/lvalue.go b/third_party/go.tools/go/ssa/lvalue.go
new file mode 100644
index 0000000..9ad8271
--- /dev/null
+++ b/third_party/go.tools/go/ssa/lvalue.go
@@ -0,0 +1,122 @@
+// Copyright 2013 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 ssa
+
+// lvalues are the union of addressable expressions and map-index
+// expressions.
+
+import (
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// An lvalue represents an assignable location that may appear on the
+// left-hand side of an assignment.  This is a generalization of a
+// pointer to permit updates to elements of maps.
+//
+type lvalue interface {
+	store(fn *Function, v Value) // stores v into the location
+	load(fn *Function) Value     // loads the contents of the location
+	address(fn *Function) Value  // address of the location
+	typ() types.Type             // returns the type of the location
+}
+
+// An address is an lvalue represented by a true pointer.
+type address struct {
+	addr    Value
+	starPos token.Pos // source position, if from explicit *addr
+	expr    ast.Expr  // source syntax [debug mode]
+}
+
+func (a *address) load(fn *Function) Value {
+	load := emitLoad(fn, a.addr)
+	load.pos = a.starPos
+	return load
+}
+
+func (a *address) store(fn *Function, v Value) {
+	store := emitStore(fn, a.addr, v)
+	store.pos = a.starPos
+	if a.expr != nil {
+		// store.Val is v, converted for assignability.
+		emitDebugRef(fn, a.expr, store.Val, false)
+	}
+}
+
+func (a *address) address(fn *Function) Value {
+	if a.expr != nil {
+		emitDebugRef(fn, a.expr, a.addr, true)
+	}
+	return a.addr
+}
+
+func (a *address) typ() types.Type {
+	return deref(a.addr.Type())
+}
+
+// An element is an lvalue represented by m[k], the location of an
+// element of a map or string.  These locations are not addressable
+// since pointers cannot be formed from them, but they do support
+// load(), and in the case of maps, store().
+//
+type element struct {
+	m, k Value      // map or string
+	t    types.Type // map element type or string byte type
+	pos  token.Pos  // source position of colon ({k:v}) or lbrack (m[k]=v)
+}
+
+func (e *element) load(fn *Function) Value {
+	l := &Lookup{
+		X:     e.m,
+		Index: e.k,
+	}
+	l.setPos(e.pos)
+	l.setType(e.t)
+	return fn.emit(l)
+}
+
+func (e *element) store(fn *Function, v Value) {
+	up := &MapUpdate{
+		Map:   e.m,
+		Key:   e.k,
+		Value: emitConv(fn, v, e.t),
+	}
+	up.pos = e.pos
+	fn.emit(up)
+}
+
+func (e *element) address(fn *Function) Value {
+	panic("map/string elements are not addressable")
+}
+
+func (e *element) typ() types.Type {
+	return e.t
+}
+
+// A blank is a dummy variable whose name is "_".
+// It is not reified: loads are illegal and stores are ignored.
+//
+type blank struct{}
+
+func (bl blank) load(fn *Function) Value {
+	panic("blank.load is illegal")
+}
+
+func (bl blank) store(fn *Function, v Value) {
+	// no-op
+}
+
+func (bl blank) address(fn *Function) Value {
+	panic("blank var is not addressable")
+}
+
+func (bl blank) typ() types.Type {
+	// This should be the type of the blank Ident; the typechecker
+	// doesn't provide this yet, but fortunately, we don't need it
+	// yet either.
+	panic("blank.typ is unimplemented")
+}
diff --git a/third_party/go.tools/go/ssa/methods.go b/third_party/go.tools/go/ssa/methods.go
new file mode 100644
index 0000000..2a92481
--- /dev/null
+++ b/third_party/go.tools/go/ssa/methods.go
@@ -0,0 +1,197 @@
+// Copyright 2013 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 ssa
+
+// This file defines utilities for population of method sets.
+
+import (
+	"fmt"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// Method returns the Function implementing method sel, building
+// wrapper methods on demand.  It returns nil if sel denotes an
+// abstract (interface) method.
+//
+// Precondition: sel.Kind() == MethodVal.
+//
+// TODO(adonovan): rename this to MethodValue because of the
+// precondition, and for consistency with functions in source.go.
+//
+// Thread-safe.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) Method(sel *types.Selection) *Function {
+	if sel.Kind() != types.MethodVal {
+		panic(fmt.Sprintf("Method(%s) kind != MethodVal", sel))
+	}
+	T := sel.Recv()
+	if isInterface(T) {
+		return nil // abstract method
+	}
+	if prog.mode&LogSource != 0 {
+		defer logStack("Method %s %v", T, sel)()
+	}
+
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+
+	return prog.addMethod(prog.createMethodSet(T), sel)
+}
+
+// LookupMethod returns the implementation of the method of type T
+// identified by (pkg, name).  It returns nil if the method exists but
+// is abstract, and panics if T has no such method.
+//
+func (prog *Program) LookupMethod(T types.Type, pkg *types.Package, name string) *Function {
+	sel := prog.MethodSets.MethodSet(T).Lookup(pkg, name)
+	if sel == nil {
+		panic(fmt.Sprintf("%s has no method %s", T, types.Id(pkg, name)))
+	}
+	return prog.Method(sel)
+}
+
+// makeMethods ensures that all concrete methods of type T are
+// generated.  It is equivalent to calling prog.Method() on all
+// members of T.methodSet(), but acquires fewer locks.
+//
+// It reports whether the type's (concrete) method set is non-empty.
+//
+// Thread-safe.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) makeMethods(T types.Type) bool {
+	if isInterface(T) {
+		return false // abstract method
+	}
+	tmset := prog.MethodSets.MethodSet(T)
+	n := tmset.Len()
+	if n == 0 {
+		return false // empty (common case)
+	}
+
+	if prog.mode&LogSource != 0 {
+		defer logStack("makeMethods %s", T)()
+	}
+
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+
+	mset := prog.createMethodSet(T)
+	if !mset.complete {
+		mset.complete = true
+		for i := 0; i < n; i++ {
+			prog.addMethod(mset, tmset.At(i))
+		}
+	}
+
+	return true
+}
+
+// methodSet contains the (concrete) methods of a non-interface type.
+type methodSet struct {
+	mapping  map[string]*Function // populated lazily
+	complete bool                 // mapping contains all methods
+}
+
+// Precondition: !isInterface(T).
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+func (prog *Program) createMethodSet(T types.Type) *methodSet {
+	mset, ok := prog.methodSets.At(T).(*methodSet)
+	if !ok {
+		mset = &methodSet{mapping: make(map[string]*Function)}
+		prog.methodSets.Set(T, mset)
+	}
+	return mset
+}
+
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+func (prog *Program) addMethod(mset *methodSet, sel *types.Selection) *Function {
+	if sel.Kind() == types.MethodExpr {
+		panic(sel)
+	}
+	id := sel.Obj().Id()
+	fn := mset.mapping[id]
+	if fn == nil {
+		obj := sel.Obj().(*types.Func)
+
+		needsPromotion := len(sel.Index()) > 1
+		needsIndirection := !isPointer(recvType(obj)) && isPointer(sel.Recv())
+		if needsPromotion || needsIndirection {
+			fn = makeWrapper(prog, sel)
+		} else {
+			fn = prog.declaredFunc(obj)
+		}
+		if fn.Signature.Recv() == nil {
+			panic(fn) // missing receiver
+		}
+		mset.mapping[id] = fn
+	}
+	return fn
+}
+
+// TypesWithMethodSets returns a new unordered slice containing all
+// concrete types in the program for which a complete (non-empty)
+// method set is required at run-time.
+//
+// It is the union of pkg.TypesWithMethodSets() for all pkg in
+// prog.AllPackages().
+//
+// Thread-safe.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) TypesWithMethodSets() []types.Type {
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+
+	var res []types.Type
+	prog.methodSets.Iterate(func(T types.Type, v interface{}) {
+		if v.(*methodSet).complete {
+			res = append(res, T)
+		}
+	})
+	return res
+}
+
+// TypesWithMethodSets returns an unordered slice containing the set
+// of all concrete types referenced within package pkg and not
+// belonging to some other package, for which a complete (non-empty)
+// method set is required at run-time.
+//
+// A type belongs to a package if it is a named type or a pointer to a
+// named type, and the name was defined in that package.  All other
+// types belong to no package.
+//
+// A type may appear in the TypesWithMethodSets() set of multiple
+// distinct packages if that type belongs to no package.  Typical
+// compilers emit method sets for such types multiple times (using
+// weak symbols) into each package that references them, with the
+// linker performing duplicate elimination.
+//
+// This set includes the types of all operands of some MakeInterface
+// instruction, the types of all exported members of some package, and
+// all types that are subcomponents, since even types that aren't used
+// directly may be derived via reflection.
+//
+// Callers must not mutate the result.
+//
+func (pkg *Package) TypesWithMethodSets() []types.Type {
+	// pkg.methodsMu not required; concurrent (build) phase is over.
+	return pkg.methodSets
+}
+
+// declaredFunc returns the concrete function/method denoted by obj.
+// Panic ensues if there is none.
+//
+func (prog *Program) declaredFunc(obj *types.Func) *Function {
+	if v := prog.packageLevelValue(obj); v != nil {
+		return v.(*Function)
+	}
+	panic("no concrete method: " + obj.String())
+}
diff --git a/third_party/go.tools/go/ssa/print.go b/third_party/go.tools/go/ssa/print.go
new file mode 100644
index 0000000..13a6887
--- /dev/null
+++ b/third_party/go.tools/go/ssa/print.go
@@ -0,0 +1,427 @@
+// Copyright 2013 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 ssa
+
+// This file implements the String() methods for all Value and
+// Instruction types.
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+// relName returns the name of v relative to i.
+// In most cases, this is identical to v.Name(), but references to
+// Functions (including methods) and Globals use RelString and
+// all types are displayed with relType, so that only cross-package
+// references are package-qualified.
+//
+func relName(v Value, i Instruction) string {
+	var from *types.Package
+	if i != nil {
+		from = i.Parent().pkgobj()
+	}
+	switch v := v.(type) {
+	case Member: // *Function or *Global
+		return v.RelString(from)
+	case *Const:
+		return v.RelString(from)
+	}
+	return v.Name()
+}
+
+func relType(t types.Type, from *types.Package) string {
+	return types.TypeString(from, t)
+}
+
+func relString(m Member, from *types.Package) string {
+	// NB: not all globals have an Object (e.g. init$guard),
+	// so use Package().Object not Object.Package().
+	if obj := m.Package().Object; obj != nil && obj != from {
+		return fmt.Sprintf("%s.%s", obj.Path(), m.Name())
+	}
+	return m.Name()
+}
+
+// Value.String()
+//
+// This method is provided only for debugging.
+// It never appears in disassembly, which uses Value.Name().
+
+func (v *Parameter) String() string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("parameter %s : %s", v.Name(), relType(v.Type(), from))
+}
+
+func (v *FreeVar) String() string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("freevar %s : %s", v.Name(), relType(v.Type(), from))
+}
+
+func (v *Builtin) String() string {
+	return fmt.Sprintf("builtin %s", v.Name())
+}
+
+// Instruction.String()
+
+func (v *Alloc) String() string {
+	op := "local"
+	if v.Heap {
+		op = "new"
+	}
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("%s %s (%s)", op, relType(deref(v.Type()), from), v.Comment)
+}
+
+func (v *Phi) String() string {
+	var b bytes.Buffer
+	b.WriteString("phi [")
+	for i, edge := range v.Edges {
+		if i > 0 {
+			b.WriteString(", ")
+		}
+		// Be robust against malformed CFG.
+		block := -1
+		if v.block != nil && i < len(v.block.Preds) {
+			block = v.block.Preds[i].Index
+		}
+		fmt.Fprintf(&b, "%d: ", block)
+		edgeVal := "<nil>" // be robust
+		if edge != nil {
+			edgeVal = relName(edge, v)
+		}
+		b.WriteString(edgeVal)
+	}
+	b.WriteString("]")
+	if v.Comment != "" {
+		b.WriteString(" #")
+		b.WriteString(v.Comment)
+	}
+	return b.String()
+}
+
+func printCall(v *CallCommon, prefix string, instr Instruction) string {
+	var b bytes.Buffer
+	b.WriteString(prefix)
+	if !v.IsInvoke() {
+		b.WriteString(relName(v.Value, instr))
+	} else {
+		fmt.Fprintf(&b, "invoke %s.%s", relName(v.Value, instr), v.Method.Name())
+	}
+	b.WriteString("(")
+	for i, arg := range v.Args {
+		if i > 0 {
+			b.WriteString(", ")
+		}
+		b.WriteString(relName(arg, instr))
+	}
+	if v.Signature().Variadic() {
+		b.WriteString("...")
+	}
+	b.WriteString(")")
+	return b.String()
+}
+
+func (c *CallCommon) String() string {
+	return printCall(c, "", nil)
+}
+
+func (v *Call) String() string {
+	return printCall(&v.Call, "", v)
+}
+
+func (v *BinOp) String() string {
+	return fmt.Sprintf("%s %s %s", relName(v.X, v), v.Op.String(), relName(v.Y, v))
+}
+
+func (v *UnOp) String() string {
+	return fmt.Sprintf("%s%s%s", v.Op, relName(v.X, v), commaOk(v.CommaOk))
+}
+
+func printConv(prefix string, v, x Value) string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("%s %s <- %s (%s)",
+		prefix,
+		relType(v.Type(), from),
+		relType(x.Type(), from),
+		relName(x, v.(Instruction)))
+}
+
+func (v *ChangeType) String() string      { return printConv("changetype", v, v.X) }
+func (v *Convert) String() string         { return printConv("convert", v, v.X) }
+func (v *ChangeInterface) String() string { return printConv("change interface", v, v.X) }
+func (v *MakeInterface) String() string   { return printConv("make", v, v.X) }
+
+func (v *MakeClosure) String() string {
+	var b bytes.Buffer
+	fmt.Fprintf(&b, "make closure %s", relName(v.Fn, v))
+	if v.Bindings != nil {
+		b.WriteString(" [")
+		for i, c := range v.Bindings {
+			if i > 0 {
+				b.WriteString(", ")
+			}
+			b.WriteString(relName(c, v))
+		}
+		b.WriteString("]")
+	}
+	return b.String()
+}
+
+func (v *MakeSlice) String() string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("make %s %s %s",
+		relType(v.Type(), from),
+		relName(v.Len, v),
+		relName(v.Cap, v))
+}
+
+func (v *Slice) String() string {
+	var b bytes.Buffer
+	b.WriteString("slice ")
+	b.WriteString(relName(v.X, v))
+	b.WriteString("[")
+	if v.Low != nil {
+		b.WriteString(relName(v.Low, v))
+	}
+	b.WriteString(":")
+	if v.High != nil {
+		b.WriteString(relName(v.High, v))
+	}
+	if v.Max != nil {
+		b.WriteString(":")
+		b.WriteString(relName(v.Max, v))
+	}
+	b.WriteString("]")
+	return b.String()
+}
+
+func (v *MakeMap) String() string {
+	res := ""
+	if v.Reserve != nil {
+		res = relName(v.Reserve, v)
+	}
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("make %s %s", relType(v.Type(), from), res)
+}
+
+func (v *MakeChan) String() string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("make %s %s", relType(v.Type(), from), relName(v.Size, v))
+}
+
+func (v *FieldAddr) String() string {
+	st := deref(v.X.Type()).Underlying().(*types.Struct)
+	// Be robust against a bad index.
+	name := "?"
+	if 0 <= v.Field && v.Field < st.NumFields() {
+		name = st.Field(v.Field).Name()
+	}
+	return fmt.Sprintf("&%s.%s [#%d]", relName(v.X, v), name, v.Field)
+}
+
+func (v *Field) String() string {
+	st := v.X.Type().Underlying().(*types.Struct)
+	// Be robust against a bad index.
+	name := "?"
+	if 0 <= v.Field && v.Field < st.NumFields() {
+		name = st.Field(v.Field).Name()
+	}
+	return fmt.Sprintf("%s.%s [#%d]", relName(v.X, v), name, v.Field)
+}
+
+func (v *IndexAddr) String() string {
+	return fmt.Sprintf("&%s[%s]", relName(v.X, v), relName(v.Index, v))
+}
+
+func (v *Index) String() string {
+	return fmt.Sprintf("%s[%s]", relName(v.X, v), relName(v.Index, v))
+}
+
+func (v *Lookup) String() string {
+	return fmt.Sprintf("%s[%s]%s", relName(v.X, v), relName(v.Index, v), commaOk(v.CommaOk))
+}
+
+func (v *Range) String() string {
+	return "range " + relName(v.X, v)
+}
+
+func (v *Next) String() string {
+	return "next " + relName(v.Iter, v)
+}
+
+func (v *TypeAssert) String() string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("typeassert%s %s.(%s)", commaOk(v.CommaOk), relName(v.X, v), relType(v.AssertedType, from))
+}
+
+func (v *Extract) String() string {
+	return fmt.Sprintf("extract %s #%d", relName(v.Tuple, v), v.Index)
+}
+
+func (s *Jump) String() string {
+	// Be robust against malformed CFG.
+	block := -1
+	if s.block != nil && len(s.block.Succs) == 1 {
+		block = s.block.Succs[0].Index
+	}
+	return fmt.Sprintf("jump %d", block)
+}
+
+func (s *If) String() string {
+	// Be robust against malformed CFG.
+	tblock, fblock := -1, -1
+	if s.block != nil && len(s.block.Succs) == 2 {
+		tblock = s.block.Succs[0].Index
+		fblock = s.block.Succs[1].Index
+	}
+	return fmt.Sprintf("if %s goto %d else %d", relName(s.Cond, s), tblock, fblock)
+}
+
+func (s *Go) String() string {
+	return printCall(&s.Call, "go ", s)
+}
+
+func (s *Panic) String() string {
+	return "panic " + relName(s.X, s)
+}
+
+func (s *Return) String() string {
+	var b bytes.Buffer
+	b.WriteString("return")
+	for i, r := range s.Results {
+		if i == 0 {
+			b.WriteString(" ")
+		} else {
+			b.WriteString(", ")
+		}
+		b.WriteString(relName(r, s))
+	}
+	return b.String()
+}
+
+func (*RunDefers) String() string {
+	return "rundefers"
+}
+
+func (s *Send) String() string {
+	return fmt.Sprintf("send %s <- %s", relName(s.Chan, s), relName(s.X, s))
+}
+
+func (s *Defer) String() string {
+	return printCall(&s.Call, "defer ", s)
+}
+
+func (s *Select) String() string {
+	var b bytes.Buffer
+	for i, st := range s.States {
+		if i > 0 {
+			b.WriteString(", ")
+		}
+		if st.Dir == types.RecvOnly {
+			b.WriteString("<-")
+			b.WriteString(relName(st.Chan, s))
+		} else {
+			b.WriteString(relName(st.Chan, s))
+			b.WriteString("<-")
+			b.WriteString(relName(st.Send, s))
+		}
+	}
+	non := ""
+	if !s.Blocking {
+		non = "non"
+	}
+	return fmt.Sprintf("select %sblocking [%s]", non, b.String())
+}
+
+func (s *Store) String() string {
+	return fmt.Sprintf("*%s = %s", relName(s.Addr, s), relName(s.Val, s))
+}
+
+func (s *MapUpdate) String() string {
+	return fmt.Sprintf("%s[%s] = %s", relName(s.Map, s), relName(s.Key, s), relName(s.Value, s))
+}
+
+func (s *DebugRef) String() string {
+	p := s.Parent().Prog.Fset.Position(s.Pos())
+	var descr interface{}
+	if s.object != nil {
+		descr = s.object // e.g. "var x int"
+	} else {
+		descr = reflect.TypeOf(s.Expr) // e.g. "*ast.CallExpr"
+	}
+	var addr string
+	if s.IsAddr {
+		addr = "address of "
+	}
+	return fmt.Sprintf("; %s%s @ %d:%d is %s", addr, descr, p.Line, p.Column, s.X.Name())
+}
+
+func (p *Package) String() string {
+	return "package " + p.Object.Path()
+}
+
+var _ io.WriterTo = (*Package)(nil) // *Package implements io.Writer
+
+func (p *Package) WriteTo(w io.Writer) (int64, error) {
+	var buf bytes.Buffer
+	WritePackage(&buf, p)
+	n, err := w.Write(buf.Bytes())
+	return int64(n), err
+}
+
+// WritePackage writes to buf a human-readable summary of p.
+func WritePackage(buf *bytes.Buffer, p *Package) {
+	fmt.Fprintf(buf, "%s:\n", p)
+
+	var names []string
+	maxname := 0
+	for name := range p.Members {
+		if l := len(name); l > maxname {
+			maxname = l
+		}
+		names = append(names, name)
+	}
+
+	from := p.Object
+	sort.Strings(names)
+	for _, name := range names {
+		switch mem := p.Members[name].(type) {
+		case *NamedConst:
+			fmt.Fprintf(buf, "  const %-*s %s = %s\n",
+				maxname, name, mem.Name(), mem.Value.RelString(from))
+
+		case *Function:
+			fmt.Fprintf(buf, "  func  %-*s %s\n",
+				maxname, name, relType(mem.Type(), from))
+
+		case *Type:
+			fmt.Fprintf(buf, "  type  %-*s %s\n",
+				maxname, name, relType(mem.Type().Underlying(), from))
+			for _, meth := range typeutil.IntuitiveMethodSet(mem.Type(), &p.Prog.MethodSets) {
+				fmt.Fprintf(buf, "    %s\n", types.SelectionString(from, meth))
+			}
+
+		case *Global:
+			fmt.Fprintf(buf, "  var   %-*s %s\n",
+				maxname, name, relType(mem.Type().(*types.Pointer).Elem(), from))
+		}
+	}
+
+	fmt.Fprintf(buf, "\n")
+}
+
+func commaOk(x bool) string {
+	if x {
+		return ",ok"
+	}
+	return ""
+}
diff --git a/third_party/go.tools/go/ssa/sanity.go b/third_party/go.tools/go/ssa/sanity.go
new file mode 100644
index 0000000..c6d2ba1
--- /dev/null
+++ b/third_party/go.tools/go/ssa/sanity.go
@@ -0,0 +1,515 @@
+// Copyright 2013 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 ssa
+
+// An optional pass for sanity-checking invariants of the SSA representation.
+// Currently it checks CFG invariants but little at the instruction level.
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+type sanity struct {
+	reporter io.Writer
+	fn       *Function
+	block    *BasicBlock
+	instrs   map[Instruction]struct{}
+	insane   bool
+}
+
+// sanityCheck performs integrity checking of the SSA representation
+// of the function fn and returns true if it was valid.  Diagnostics
+// are written to reporter if non-nil, os.Stderr otherwise.  Some
+// diagnostics are only warnings and do not imply a negative result.
+//
+// Sanity-checking is intended to facilitate the debugging of code
+// transformation passes.
+//
+func sanityCheck(fn *Function, reporter io.Writer) bool {
+	if reporter == nil {
+		reporter = os.Stderr
+	}
+	return (&sanity{reporter: reporter}).checkFunction(fn)
+}
+
+// mustSanityCheck is like sanityCheck but panics instead of returning
+// a negative result.
+//
+func mustSanityCheck(fn *Function, reporter io.Writer) {
+	if !sanityCheck(fn, reporter) {
+		fn.WriteTo(os.Stderr)
+		panic("SanityCheck failed")
+	}
+}
+
+func (s *sanity) diagnostic(prefix, format string, args ...interface{}) {
+	fmt.Fprintf(s.reporter, "%s: function %s", prefix, s.fn)
+	if s.block != nil {
+		fmt.Fprintf(s.reporter, ", block %s", s.block)
+	}
+	io.WriteString(s.reporter, ": ")
+	fmt.Fprintf(s.reporter, format, args...)
+	io.WriteString(s.reporter, "\n")
+}
+
+func (s *sanity) errorf(format string, args ...interface{}) {
+	s.insane = true
+	s.diagnostic("Error", format, args...)
+}
+
+func (s *sanity) warnf(format string, args ...interface{}) {
+	s.diagnostic("Warning", format, args...)
+}
+
+// findDuplicate returns an arbitrary basic block that appeared more
+// than once in blocks, or nil if all were unique.
+func findDuplicate(blocks []*BasicBlock) *BasicBlock {
+	if len(blocks) < 2 {
+		return nil
+	}
+	if blocks[0] == blocks[1] {
+		return blocks[0]
+	}
+	// Slow path:
+	m := make(map[*BasicBlock]bool)
+	for _, b := range blocks {
+		if m[b] {
+			return b
+		}
+		m[b] = true
+	}
+	return nil
+}
+
+func (s *sanity) checkInstr(idx int, instr Instruction) {
+	switch instr := instr.(type) {
+	case *If, *Jump, *Return, *Panic:
+		s.errorf("control flow instruction not at end of block")
+	case *Phi:
+		if idx == 0 {
+			// It suffices to apply this check to just the first phi node.
+			if dup := findDuplicate(s.block.Preds); dup != nil {
+				s.errorf("phi node in block with duplicate predecessor %s", dup)
+			}
+		} else {
+			prev := s.block.Instrs[idx-1]
+			if _, ok := prev.(*Phi); !ok {
+				s.errorf("Phi instruction follows a non-Phi: %T", prev)
+			}
+		}
+		if ne, np := len(instr.Edges), len(s.block.Preds); ne != np {
+			s.errorf("phi node has %d edges but %d predecessors", ne, np)
+
+		} else {
+			for i, e := range instr.Edges {
+				if e == nil {
+					s.errorf("phi node '%s' has no value for edge #%d from %s", instr.Comment, i, s.block.Preds[i])
+				}
+			}
+		}
+
+	case *Alloc:
+		if !instr.Heap {
+			found := false
+			for _, l := range s.fn.Locals {
+				if l == instr {
+					found = true
+					break
+				}
+			}
+			if !found {
+				s.errorf("local alloc %s = %s does not appear in Function.Locals", instr.Name(), instr)
+			}
+		}
+
+	case *BinOp:
+	case *Call:
+	case *ChangeInterface:
+	case *ChangeType:
+	case *Convert:
+		if _, ok := instr.X.Type().Underlying().(*types.Basic); !ok {
+			if _, ok := instr.Type().Underlying().(*types.Basic); !ok {
+				s.errorf("convert %s -> %s: at least one type must be basic", instr.X.Type(), instr.Type())
+			}
+		}
+
+	case *Defer:
+	case *Extract:
+	case *Field:
+	case *FieldAddr:
+	case *Go:
+	case *Index:
+	case *IndexAddr:
+	case *Lookup:
+	case *MakeChan:
+	case *MakeClosure:
+		numFree := len(instr.Fn.(*Function).FreeVars)
+		numBind := len(instr.Bindings)
+		if numFree != numBind {
+			s.errorf("MakeClosure has %d Bindings for function %s with %d free vars",
+				numBind, instr.Fn, numFree)
+
+		}
+		if recv := instr.Type().(*types.Signature).Recv(); recv != nil {
+			s.errorf("MakeClosure's type includes receiver %s", recv.Type())
+		}
+
+	case *MakeInterface:
+	case *MakeMap:
+	case *MakeSlice:
+	case *MapUpdate:
+	case *Next:
+	case *Range:
+	case *RunDefers:
+	case *Select:
+	case *Send:
+	case *Slice:
+	case *Store:
+	case *TypeAssert:
+	case *UnOp:
+	case *DebugRef:
+		// TODO(adonovan): implement checks.
+	default:
+		panic(fmt.Sprintf("Unknown instruction type: %T", instr))
+	}
+
+	if call, ok := instr.(CallInstruction); ok {
+		if call.Common().Signature() == nil {
+			s.errorf("nil signature: %s", call)
+		}
+	}
+
+	// Check that value-defining instructions have valid types
+	// and a valid referrer list.
+	if v, ok := instr.(Value); ok {
+		t := v.Type()
+		if t == nil {
+			s.errorf("no type: %s = %s", v.Name(), v)
+		} else if t == tRangeIter {
+			// not a proper type; ignore.
+		} else if b, ok := t.Underlying().(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {
+			s.errorf("instruction has 'untyped' result: %s = %s : %s", v.Name(), v, t)
+		}
+		s.checkReferrerList(v)
+	}
+
+	// Untyped constants are legal as instruction Operands(),
+	// for example:
+	//   _ = "foo"[0]
+	// or:
+	//   if wordsize==64 {...}
+
+	// All other non-Instruction Values can be found via their
+	// enclosing Function or Package.
+}
+
+func (s *sanity) checkFinalInstr(idx int, instr Instruction) {
+	switch instr := instr.(type) {
+	case *If:
+		if nsuccs := len(s.block.Succs); nsuccs != 2 {
+			s.errorf("If-terminated block has %d successors; expected 2", nsuccs)
+			return
+		}
+		if s.block.Succs[0] == s.block.Succs[1] {
+			s.errorf("If-instruction has same True, False target blocks: %s", s.block.Succs[0])
+			return
+		}
+
+	case *Jump:
+		if nsuccs := len(s.block.Succs); nsuccs != 1 {
+			s.errorf("Jump-terminated block has %d successors; expected 1", nsuccs)
+			return
+		}
+
+	case *Return:
+		if nsuccs := len(s.block.Succs); nsuccs != 0 {
+			s.errorf("Return-terminated block has %d successors; expected none", nsuccs)
+			return
+		}
+		if na, nf := len(instr.Results), s.fn.Signature.Results().Len(); nf != na {
+			s.errorf("%d-ary return in %d-ary function", na, nf)
+		}
+
+	case *Panic:
+		if nsuccs := len(s.block.Succs); nsuccs != 0 {
+			s.errorf("Panic-terminated block has %d successors; expected none", nsuccs)
+			return
+		}
+
+	default:
+		s.errorf("non-control flow instruction at end of block")
+	}
+}
+
+func (s *sanity) checkBlock(b *BasicBlock, index int) {
+	s.block = b
+
+	if b.Index != index {
+		s.errorf("block has incorrect Index %d", b.Index)
+	}
+	if b.parent != s.fn {
+		s.errorf("block has incorrect parent %s", b.parent)
+	}
+
+	// Check all blocks are reachable.
+	// (The entry block is always implicitly reachable,
+	// as is the Recover block, if any.)
+	if (index > 0 && b != b.parent.Recover) && len(b.Preds) == 0 {
+		s.warnf("unreachable block")
+		if b.Instrs == nil {
+			// Since this block is about to be pruned,
+			// tolerating transient problems in it
+			// simplifies other optimizations.
+			return
+		}
+	}
+
+	// Check predecessor and successor relations are dual,
+	// and that all blocks in CFG belong to same function.
+	for _, a := range b.Preds {
+		found := false
+		for _, bb := range a.Succs {
+			if bb == b {
+				found = true
+				break
+			}
+		}
+		if !found {
+			s.errorf("expected successor edge in predecessor %s; found only: %s", a, a.Succs)
+		}
+		if a.parent != s.fn {
+			s.errorf("predecessor %s belongs to different function %s", a, a.parent)
+		}
+	}
+	for _, c := range b.Succs {
+		found := false
+		for _, bb := range c.Preds {
+			if bb == b {
+				found = true
+				break
+			}
+		}
+		if !found {
+			s.errorf("expected predecessor edge in successor %s; found only: %s", c, c.Preds)
+		}
+		if c.parent != s.fn {
+			s.errorf("successor %s belongs to different function %s", c, c.parent)
+		}
+	}
+
+	// Check each instruction is sane.
+	n := len(b.Instrs)
+	if n == 0 {
+		s.errorf("basic block contains no instructions")
+	}
+	var rands [10]*Value // reuse storage
+	for j, instr := range b.Instrs {
+		if instr == nil {
+			s.errorf("nil instruction at index %d", j)
+			continue
+		}
+		if b2 := instr.Block(); b2 == nil {
+			s.errorf("nil Block() for instruction at index %d", j)
+			continue
+		} else if b2 != b {
+			s.errorf("wrong Block() (%s) for instruction at index %d ", b2, j)
+			continue
+		}
+		if j < n-1 {
+			s.checkInstr(j, instr)
+		} else {
+			s.checkFinalInstr(j, instr)
+		}
+
+		// Check Instruction.Operands.
+	operands:
+		for i, op := range instr.Operands(rands[:0]) {
+			if op == nil {
+				s.errorf("nil operand pointer %d of %s", i, instr)
+				continue
+			}
+			val := *op
+			if val == nil {
+				continue // a nil operand is ok
+			}
+
+			// Check that "untyped" types only appear on constant operands.
+			if _, ok := (*op).(*Const); !ok {
+				if basic, ok := (*op).Type().(*types.Basic); ok {
+					if basic.Info()&types.IsUntyped != 0 {
+						s.errorf("operand #%d of %s is untyped: %s", i, instr, basic)
+					}
+				}
+			}
+
+			// Check that Operands that are also Instructions belong to same function.
+			// TODO(adonovan): also check their block dominates block b.
+			if val, ok := val.(Instruction); ok {
+				if val.Parent() != s.fn {
+					s.errorf("operand %d of %s is an instruction (%s) from function %s", i, instr, val, val.Parent())
+				}
+			}
+
+			// Check that each function-local operand of
+			// instr refers back to instr.  (NB: quadratic)
+			switch val := val.(type) {
+			case *Const, *Global, *Builtin:
+				continue // not local
+			case *Function:
+				if val.parent == nil {
+					continue // only anon functions are local
+				}
+			}
+
+			// TODO(adonovan): check val.Parent() != nil <=> val.Referrers() is defined.
+
+			if refs := val.Referrers(); refs != nil {
+				for _, ref := range *refs {
+					if ref == instr {
+						continue operands
+					}
+				}
+				s.errorf("operand %d of %s (%s) does not refer to us", i, instr, val)
+			} else {
+				s.errorf("operand %d of %s (%s) has no referrers", i, instr, val)
+			}
+		}
+	}
+}
+
+func (s *sanity) checkReferrerList(v Value) {
+	refs := v.Referrers()
+	if refs == nil {
+		s.errorf("%s has missing referrer list", v.Name())
+		return
+	}
+	for i, ref := range *refs {
+		if _, ok := s.instrs[ref]; !ok {
+			s.errorf("%s.Referrers()[%d] = %s is not an instruction belonging to this function", v.Name(), i, ref)
+		}
+	}
+}
+
+func (s *sanity) checkFunction(fn *Function) bool {
+	// TODO(adonovan): check Function invariants:
+	// - check params match signature
+	// - check transient fields are nil
+	// - warn if any fn.Locals do not appear among block instructions.
+	s.fn = fn
+	if fn.Prog == nil {
+		s.errorf("nil Prog")
+	}
+
+	fn.String()               // must not crash
+	fn.RelString(fn.pkgobj()) // must not crash
+
+	// All functions have a package, except delegates (which are
+	// shared across packages, or duplicated as weak symbols in a
+	// separate-compilation model), and error.Error.
+	if fn.Pkg == nil {
+		if strings.HasPrefix(fn.Synthetic, "wrapper ") ||
+			strings.HasPrefix(fn.Synthetic, "bound ") ||
+			strings.HasPrefix(fn.Synthetic, "thunk ") ||
+			strings.HasSuffix(fn.name, "Error") {
+			// ok
+		} else {
+			s.errorf("nil Pkg")
+		}
+	}
+	if src, syn := fn.Synthetic == "", fn.Syntax() != nil; src != syn {
+		s.errorf("got fromSource=%t, hasSyntax=%t; want same values", src, syn)
+	}
+	for i, l := range fn.Locals {
+		if l.Parent() != fn {
+			s.errorf("Local %s at index %d has wrong parent", l.Name(), i)
+		}
+		if l.Heap {
+			s.errorf("Local %s at index %d has Heap flag set", l.Name(), i)
+		}
+	}
+	// Build the set of valid referrers.
+	s.instrs = make(map[Instruction]struct{})
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			s.instrs[instr] = struct{}{}
+		}
+	}
+	for i, p := range fn.Params {
+		if p.Parent() != fn {
+			s.errorf("Param %s at index %d has wrong parent", p.Name(), i)
+		}
+		s.checkReferrerList(p)
+	}
+	for i, fv := range fn.FreeVars {
+		if fv.Parent() != fn {
+			s.errorf("FreeVar %s at index %d has wrong parent", fv.Name(), i)
+		}
+		s.checkReferrerList(fv)
+	}
+
+	if fn.Blocks != nil && len(fn.Blocks) == 0 {
+		// Function _had_ blocks (so it's not external) but
+		// they were "optimized" away, even the entry block.
+		s.errorf("Blocks slice is non-nil but empty")
+	}
+	for i, b := range fn.Blocks {
+		if b == nil {
+			s.warnf("nil *BasicBlock at f.Blocks[%d]", i)
+			continue
+		}
+		s.checkBlock(b, i)
+	}
+	if fn.Recover != nil && fn.Blocks[fn.Recover.Index] != fn.Recover {
+		s.errorf("Recover block is not in Blocks slice")
+	}
+
+	s.block = nil
+	for i, anon := range fn.AnonFuncs {
+		if anon.Parent() != fn {
+			s.errorf("AnonFuncs[%d]=%s but %s.Parent()=%s", i, anon, anon, anon.Parent())
+		}
+	}
+	s.fn = nil
+	return !s.insane
+}
+
+// sanityCheckPackage checks invariants of packages upon creation.
+// It does not require that the package is built.
+// Unlike sanityCheck (for functions), it just panics at the first error.
+func sanityCheckPackage(pkg *Package) {
+	if pkg.Object == nil {
+		panic(fmt.Sprintf("Package %s has no Object", pkg))
+	}
+	pkg.String() // must not crash
+
+	for name, mem := range pkg.Members {
+		if name != mem.Name() {
+			panic(fmt.Sprintf("%s: %T.Name() = %s, want %s",
+				pkg.Object.Path(), mem, mem.Name(), name))
+		}
+		obj := mem.Object()
+		if obj == nil {
+			// This check is sound because fields
+			// {Global,Function}.object have type
+			// types.Object.  (If they were declared as
+			// *types.{Var,Func}, we'd have a non-empty
+			// interface containing a nil pointer.)
+
+			continue // not all members have typechecker objects
+		}
+		if obj.Name() != name {
+			panic(fmt.Sprintf("%s: %T.Object().Name() = %s, want %s",
+				pkg.Object.Path(), mem, obj.Name(), name))
+		}
+		if obj.Pos() != mem.Pos() {
+			panic(fmt.Sprintf("%s Pos=%d obj.Pos=%d", mem, mem.Pos(), obj.Pos()))
+		}
+	}
+}
diff --git a/third_party/go.tools/go/ssa/source.go b/third_party/go.tools/go/ssa/source.go
new file mode 100644
index 0000000..7649735
--- /dev/null
+++ b/third_party/go.tools/go/ssa/source.go
@@ -0,0 +1,294 @@
+// Copyright 2013 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 ssa
+
+// This file defines utilities for working with source positions
+// or source-level named entities ("objects").
+
+// TODO(adonovan): test that {Value,Instruction}.Pos() positions match
+// the originating syntax, as specified.
+
+import (
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// EnclosingFunction returns the function that contains the syntax
+// node denoted by path.
+//
+// Syntax associated with package-level variable specifications is
+// enclosed by the package's init() function.
+//
+// Returns nil if not found; reasons might include:
+//    - the node is not enclosed by any function.
+//    - the node is within an anonymous function (FuncLit) and
+//      its SSA function has not been created yet
+//      (pkg.Build() has not yet been called).
+//
+func EnclosingFunction(pkg *Package, path []ast.Node) *Function {
+	// Start with package-level function...
+	fn := findEnclosingPackageLevelFunction(pkg, path)
+	if fn == nil {
+		return nil // not in any function
+	}
+
+	// ...then walk down the nested anonymous functions.
+	n := len(path)
+outer:
+	for i := range path {
+		if lit, ok := path[n-1-i].(*ast.FuncLit); ok {
+			for _, anon := range fn.AnonFuncs {
+				if anon.Pos() == lit.Type.Func {
+					fn = anon
+					continue outer
+				}
+			}
+			// SSA function not found:
+			// - package not yet built, or maybe
+			// - builder skipped FuncLit in dead block
+			//   (in principle; but currently the Builder
+			//   generates even dead FuncLits).
+			return nil
+		}
+	}
+	return fn
+}
+
+// HasEnclosingFunction returns true if the AST node denoted by path
+// is contained within the declaration of some function or
+// package-level variable.
+//
+// Unlike EnclosingFunction, the behaviour of this function does not
+// depend on whether SSA code for pkg has been built, so it can be
+// used to quickly reject check inputs that will cause
+// EnclosingFunction to fail, prior to SSA building.
+//
+func HasEnclosingFunction(pkg *Package, path []ast.Node) bool {
+	return findEnclosingPackageLevelFunction(pkg, path) != nil
+}
+
+// findEnclosingPackageLevelFunction returns the Function
+// corresponding to the package-level function enclosing path.
+//
+func findEnclosingPackageLevelFunction(pkg *Package, path []ast.Node) *Function {
+	if n := len(path); n >= 2 { // [... {Gen,Func}Decl File]
+		switch decl := path[n-2].(type) {
+		case *ast.GenDecl:
+			if decl.Tok == token.VAR && n >= 3 {
+				// Package-level 'var' initializer.
+				return pkg.init
+			}
+
+		case *ast.FuncDecl:
+			if decl.Recv == nil && decl.Name.Name == "init" {
+				// Explicit init() function.
+				for _, b := range pkg.init.Blocks {
+					for _, instr := range b.Instrs {
+						if instr, ok := instr.(*Call); ok {
+							if callee, ok := instr.Call.Value.(*Function); ok && callee.Pkg == pkg && callee.Pos() == decl.Name.NamePos {
+								return callee
+							}
+						}
+					}
+				}
+				// Hack: return non-nil when SSA is not yet
+				// built so that HasEnclosingFunction works.
+				return pkg.init
+			}
+			// Declared function/method.
+			return findNamedFunc(pkg, decl.Name.NamePos)
+		}
+	}
+	return nil // not in any function
+}
+
+// findNamedFunc returns the named function whose FuncDecl.Ident is at
+// position pos.
+//
+func findNamedFunc(pkg *Package, pos token.Pos) *Function {
+	// Look at all package members and method sets of named types.
+	// Not very efficient.
+	for _, mem := range pkg.Members {
+		switch mem := mem.(type) {
+		case *Function:
+			if mem.Pos() == pos {
+				return mem
+			}
+		case *Type:
+			mset := pkg.Prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))
+			for i, n := 0, mset.Len(); i < n; i++ {
+				// Don't call Program.Method: avoid creating wrappers.
+				obj := mset.At(i).Obj().(*types.Func)
+				if obj.Pos() == pos {
+					return pkg.values[obj].(*Function)
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// ValueForExpr returns the SSA Value that corresponds to non-constant
+// expression e.
+//
+// It returns nil if no value was found, e.g.
+//    - the expression is not lexically contained within f;
+//    - f was not built with debug information; or
+//    - e is a constant expression.  (For efficiency, no debug
+//      information is stored for constants. Use
+//      loader.PackageInfo.ValueOf(e) instead.)
+//    - e is a reference to nil or a built-in function.
+//    - the value was optimised away.
+//
+// If e is an addressable expression used an an lvalue context,
+// value is the address denoted by e, and isAddr is true.
+//
+// The types of e (or &e, if isAddr) and the result are equal
+// (modulo "untyped" bools resulting from comparisons).
+//
+// (Tip: to find the ssa.Value given a source position, use
+// importer.PathEnclosingInterval to locate the ast.Node, then
+// EnclosingFunction to locate the Function, then ValueForExpr to find
+// the ssa.Value.)
+//
+func (f *Function) ValueForExpr(e ast.Expr) (value Value, isAddr bool) {
+	if f.debugInfo() { // (opt)
+		e = unparen(e)
+		for _, b := range f.Blocks {
+			for _, instr := range b.Instrs {
+				if ref, ok := instr.(*DebugRef); ok {
+					if ref.Expr == e {
+						return ref.X, ref.IsAddr
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+// --- Lookup functions for source-level named entities (types.Objects) ---
+
+// Package returns the SSA Package corresponding to the specified
+// type-checker package object.
+// It returns nil if no such SSA package has been created.
+//
+func (prog *Program) Package(obj *types.Package) *Package {
+	return prog.packages[obj]
+}
+
+// packageLevelValue returns the package-level value corresponding to
+// the specified named object, which may be a package-level const
+// (*Const), var (*Global) or func (*Function) of some package in
+// prog.  It returns nil if the object is not found.
+//
+func (prog *Program) packageLevelValue(obj types.Object) Value {
+	if pkg, ok := prog.packages[obj.Pkg()]; ok {
+		return pkg.values[obj]
+	}
+	return nil
+}
+
+// FuncValue returns the concrete Function denoted by the source-level
+// named function obj, or nil if obj denotes an interface method.
+//
+// TODO(adonovan): check the invariant that obj.Type() matches the
+// result's Signature, both in the params/results and in the receiver.
+//
+func (prog *Program) FuncValue(obj *types.Func) *Function {
+	fn, _ := prog.packageLevelValue(obj).(*Function)
+	return fn
+}
+
+// ConstValue returns the SSA Value denoted by the source-level named
+// constant obj.
+//
+func (prog *Program) ConstValue(obj *types.Const) *Const {
+	// TODO(adonovan): opt: share (don't reallocate)
+	// Consts for const objects and constant ast.Exprs.
+
+	// Universal constant? {true,false,nil}
+	if obj.Parent() == types.Universe {
+		return NewConst(obj.Val(), obj.Type())
+	}
+	// Package-level named constant?
+	if v := prog.packageLevelValue(obj); v != nil {
+		return v.(*Const)
+	}
+	return NewConst(obj.Val(), obj.Type())
+}
+
+// VarValue returns the SSA Value that corresponds to a specific
+// identifier denoting the source-level named variable obj.
+//
+// VarValue returns nil if a local variable was not found, perhaps
+// because its package was not built, the debug information was not
+// requested during SSA construction, or the value was optimized away.
+//
+// ref is the path to an ast.Ident (e.g. from PathEnclosingInterval),
+// and that ident must resolve to obj.
+//
+// pkg is the package enclosing the reference.  (A reference to a var
+// always occurs within a function, so we need to know where to find it.)
+//
+// If the identifier is a field selector and its base expression is
+// non-addressable, then VarValue returns the value of that field.
+// For example:
+//    func f() struct {x int}
+//    f().x  // VarValue(x) returns a *Field instruction of type int
+//
+// All other identifiers denote addressable locations (variables).
+// For them, VarValue may return either the variable's address or its
+// value, even when the expression is evaluated only for its value; the
+// situation is reported by isAddr, the second component of the result.
+//
+// If !isAddr, the returned value is the one associated with the
+// specific identifier.  For example,
+//       var x int    // VarValue(x) returns Const 0 here
+//       x = 1        // VarValue(x) returns Const 1 here
+//
+// It is not specified whether the value or the address is returned in
+// any particular case, as it may depend upon optimizations performed
+// during SSA code generation, such as registerization, constant
+// folding, avoidance of materialization of subexpressions, etc.
+//
+func (prog *Program) VarValue(obj *types.Var, pkg *Package, ref []ast.Node) (value Value, isAddr bool) {
+	// All references to a var are local to some function, possibly init.
+	fn := EnclosingFunction(pkg, ref)
+	if fn == nil {
+		return // e.g. def of struct field; SSA not built?
+	}
+
+	id := ref[0].(*ast.Ident)
+
+	// Defining ident of a parameter?
+	if id.Pos() == obj.Pos() {
+		for _, param := range fn.Params {
+			if param.Object() == obj {
+				return param, false
+			}
+		}
+	}
+
+	// Other ident?
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			if dr, ok := instr.(*DebugRef); ok {
+				if dr.Pos() == id.Pos() {
+					return dr.X, dr.IsAddr
+				}
+			}
+		}
+	}
+
+	// Defining ident of package-level var?
+	if v := prog.packageLevelValue(obj); v != nil {
+		return v.(*Global), true
+	}
+
+	return // e.g. debug info not requested, or var optimized away
+}
diff --git a/third_party/go.tools/go/ssa/source_test.go b/third_party/go.tools/go/ssa/source_test.go
new file mode 100644
index 0000000..5b1cb79
--- /dev/null
+++ b/third_party/go.tools/go/ssa/source_test.go
@@ -0,0 +1,276 @@
+// Copyright 2013 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 ssa_test
+
+// This file defines tests of source-level debugging utilities.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"os"
+	"regexp"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func TestObjValueLookup(t *testing.T) {
+	conf := loader.Config{ParserMode: parser.ParseComments}
+	f, err := conf.ParseFile("testdata/objlookup.go", nil)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	conf.CreateFromFiles("main", f)
+
+	// Maps each var Ident (represented "name:linenum") to the
+	// kind of ssa.Value we expect (represented "Constant", "&Alloc").
+	expectations := make(map[string]string)
+
+	// Find all annotations of form x::BinOp, &y::Alloc, etc.
+	re := regexp.MustCompile(`(\b|&)?(\w*)::(\w*)\b`)
+	for _, c := range f.Comments {
+		text := c.Text()
+		pos := conf.Fset.Position(c.Pos())
+		for _, m := range re.FindAllStringSubmatch(text, -1) {
+			key := fmt.Sprintf("%s:%d", m[2], pos.Line)
+			value := m[1] + m[3]
+			expectations[key] = value
+		}
+	}
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	prog := ssa.Create(iprog, 0 /*|ssa.PrintFunctions*/)
+	mainInfo := iprog.Created[0]
+	mainPkg := prog.Package(mainInfo.Pkg)
+	mainPkg.SetDebugMode(true)
+	mainPkg.Build()
+
+	var varIds []*ast.Ident
+	var varObjs []*types.Var
+	for id, obj := range mainInfo.Defs {
+		// Check invariants for func and const objects.
+		switch obj := obj.(type) {
+		case *types.Func:
+			checkFuncValue(t, prog, obj)
+
+		case *types.Const:
+			checkConstValue(t, prog, obj)
+
+		case *types.Var:
+			if id.Name == "_" {
+				continue
+			}
+			varIds = append(varIds, id)
+			varObjs = append(varObjs, obj)
+		}
+	}
+	for id, obj := range mainInfo.Uses {
+		if obj, ok := obj.(*types.Var); ok {
+			varIds = append(varIds, id)
+			varObjs = append(varObjs, obj)
+		}
+	}
+
+	// Check invariants for var objects.
+	// The result varies based on the specific Ident.
+	for i, id := range varIds {
+		obj := varObjs[i]
+		ref, _ := astutil.PathEnclosingInterval(f, id.Pos(), id.Pos())
+		pos := prog.Fset.Position(id.Pos())
+		exp := expectations[fmt.Sprintf("%s:%d", id.Name, pos.Line)]
+		if exp == "" {
+			t.Errorf("%s: no expectation for var ident %s ", pos, id.Name)
+			continue
+		}
+		wantAddr := false
+		if exp[0] == '&' {
+			wantAddr = true
+			exp = exp[1:]
+		}
+		checkVarValue(t, prog, mainPkg, ref, obj, exp, wantAddr)
+	}
+}
+
+func checkFuncValue(t *testing.T, prog *ssa.Program, obj *types.Func) {
+	fn := prog.FuncValue(obj)
+	// fmt.Printf("FuncValue(%s) = %s\n", obj, fn) // debugging
+	if fn == nil {
+		if obj.Name() != "interfaceMethod" {
+			t.Errorf("FuncValue(%s) == nil", obj)
+		}
+		return
+	}
+	if fnobj := fn.Object(); fnobj != obj {
+		t.Errorf("FuncValue(%s).Object() == %s; value was %s",
+			obj, fnobj, fn.Name())
+		return
+	}
+	if !types.Identical(fn.Type(), obj.Type()) {
+		t.Errorf("FuncValue(%s).Type() == %s", obj, fn.Type())
+		return
+	}
+}
+
+func checkConstValue(t *testing.T, prog *ssa.Program, obj *types.Const) {
+	c := prog.ConstValue(obj)
+	// fmt.Printf("ConstValue(%s) = %s\n", obj, c) // debugging
+	if c == nil {
+		t.Errorf("ConstValue(%s) == nil", obj)
+		return
+	}
+	if !types.Identical(c.Type(), obj.Type()) {
+		t.Errorf("ConstValue(%s).Type() == %s", obj, c.Type())
+		return
+	}
+	if obj.Name() != "nil" {
+		if !exact.Compare(c.Value, token.EQL, obj.Val()) {
+			t.Errorf("ConstValue(%s).Value (%s) != %s",
+				obj, c.Value, obj.Val())
+			return
+		}
+	}
+}
+
+func checkVarValue(t *testing.T, prog *ssa.Program, pkg *ssa.Package, ref []ast.Node, obj *types.Var, expKind string, wantAddr bool) {
+	// The prefix of all assertions messages.
+	prefix := fmt.Sprintf("VarValue(%s @ L%d)",
+		obj, prog.Fset.Position(ref[0].Pos()).Line)
+
+	v, gotAddr := prog.VarValue(obj, pkg, ref)
+
+	// Kind is the concrete type of the ssa Value.
+	gotKind := "nil"
+	if v != nil {
+		gotKind = fmt.Sprintf("%T", v)[len("*ssa."):]
+	}
+
+	// fmt.Printf("%s = %v (kind %q; expect %q) wantAddr=%t gotAddr=%t\n", prefix, v, gotKind, expKind, wantAddr, gotAddr) // debugging
+
+	// Check the kinds match.
+	// "nil" indicates expected failure (e.g. optimized away).
+	if expKind != gotKind {
+		t.Errorf("%s concrete type == %s, want %s", prefix, gotKind, expKind)
+	}
+
+	// Check the types match.
+	// If wantAddr, the expected type is the object's address.
+	if v != nil {
+		expType := obj.Type()
+		if wantAddr {
+			expType = types.NewPointer(expType)
+			if !gotAddr {
+				t.Errorf("%s: got value, want address", prefix)
+			}
+		} else if gotAddr {
+			t.Errorf("%s: got address, want value", prefix)
+		}
+		if !types.Identical(v.Type(), expType) {
+			t.Errorf("%s.Type() == %s, want %s", prefix, v.Type(), expType)
+		}
+	}
+}
+
+// Ensure that, in debug mode, we can determine the ssa.Value
+// corresponding to every ast.Expr.
+func TestValueForExpr(t *testing.T) {
+	conf := loader.Config{ParserMode: parser.ParseComments}
+	f, err := conf.ParseFile("testdata/valueforexpr.go", nil)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	conf.CreateFromFiles("main", f)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	mainInfo := iprog.Created[0]
+
+	prog := ssa.Create(iprog, 0)
+	mainPkg := prog.Package(mainInfo.Pkg)
+	mainPkg.SetDebugMode(true)
+	mainPkg.Build()
+
+	if false {
+		// debugging
+		for _, mem := range mainPkg.Members {
+			if fn, ok := mem.(*ssa.Function); ok {
+				fn.WriteTo(os.Stderr)
+			}
+		}
+	}
+
+	// Find the actual AST node for each canonical position.
+	parenExprByPos := make(map[token.Pos]*ast.ParenExpr)
+	ast.Inspect(f, func(n ast.Node) bool {
+		if n != nil {
+			if e, ok := n.(*ast.ParenExpr); ok {
+				parenExprByPos[e.Pos()] = e
+			}
+		}
+		return true
+	})
+
+	// Find all annotations of form /*@kind*/.
+	for _, c := range f.Comments {
+		text := strings.TrimSpace(c.Text())
+		if text == "" || text[0] != '@' {
+			continue
+		}
+		text = text[1:]
+		pos := c.End() + 1
+		position := prog.Fset.Position(pos)
+		var e ast.Expr
+		if target := parenExprByPos[pos]; target == nil {
+			t.Errorf("%s: annotation doesn't precede ParenExpr: %q", position, text)
+			continue
+		} else {
+			e = target.X
+		}
+
+		path, _ := astutil.PathEnclosingInterval(f, pos, pos)
+		if path == nil {
+			t.Errorf("%s: can't find AST path from root to comment: %s", position, text)
+			continue
+		}
+
+		fn := ssa.EnclosingFunction(mainPkg, path)
+		if fn == nil {
+			t.Errorf("%s: can't find enclosing function", position)
+			continue
+		}
+
+		v, gotAddr := fn.ValueForExpr(e) // (may be nil)
+		got := strings.TrimPrefix(fmt.Sprintf("%T", v), "*ssa.")
+		if want := text; got != want {
+			t.Errorf("%s: got value %q, want %q", position, got, want)
+		}
+		if v != nil {
+			T := v.Type()
+			if gotAddr {
+				T = T.Underlying().(*types.Pointer).Elem() // deref
+			}
+			if !types.Identical(T, mainInfo.TypeOf(e)) {
+				t.Errorf("%s: got type %s, want %s", position, mainInfo.TypeOf(e), T)
+			}
+		}
+	}
+}
diff --git a/third_party/go.tools/go/ssa/ssa.go b/third_party/go.tools/go/ssa/ssa.go
new file mode 100644
index 0000000..387ea5f
--- /dev/null
+++ b/third_party/go.tools/go/ssa/ssa.go
@@ -0,0 +1,1688 @@
+// Copyright 2013 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 ssa
+
+// This package defines a high-level intermediate representation for
+// Go programs using static single-assignment (SSA) form.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sync"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+// A Program is a partial or complete Go program converted to SSA form.
+//
+type Program struct {
+	Fset       *token.FileSet              // position information for the files of this Program
+	imported   map[string]*Package         // all importable Packages, keyed by import path
+	packages   map[*types.Package]*Package // all loaded Packages, keyed by object
+	mode       BuilderMode                 // set of mode bits for SSA construction
+	MethodSets types.MethodSetCache        // cache of type-checker's method-sets
+
+	methodsMu  sync.Mutex                 // guards the following maps:
+	methodSets typeutil.Map               // maps type to its concrete methodSet
+	bounds     map[*types.Func]*Function  // bounds for curried x.Method closures
+	thunks     map[selectionKey]*Function // thunks for T.Method expressions
+}
+
+// A Package is a single analyzed Go package containing Members for
+// all package-level functions, variables, constants and types it
+// declares.  These may be accessed directly via Members, or via the
+// type-specific accessor methods Func, Type, Var and Const.
+//
+type Package struct {
+	Prog       *Program               // the owning program
+	Object     *types.Package         // the type checker's package object for this package
+	Members    map[string]Member      // all package members keyed by name
+	methodsMu  sync.Mutex             // guards needRTTI and methodSets
+	methodSets []types.Type           // types whose method sets are included in this package
+	values     map[types.Object]Value // package members (incl. types and methods), keyed by object
+	init       *Function              // Func("init"); the package's init function
+	debug      bool                   // include full debug info in this package.
+
+	// The following fields are set transiently, then cleared
+	// after building.
+	started  int32               // atomically tested and set at start of build phase
+	ninit    int32               // number of init functions
+	info     *loader.PackageInfo // package ASTs and type information
+	needRTTI typeutil.Map        // types for which runtime type info is needed
+}
+
+// A Member is a member of a Go package, implemented by *NamedConst,
+// *Global, *Function, or *Type; they are created by package-level
+// const, var, func and type declarations respectively.
+//
+type Member interface {
+	Name() string                    // declared name of the package member
+	String() string                  // package-qualified name of the package member
+	RelString(*types.Package) string // like String, but relative refs are unqualified
+	Object() types.Object            // typechecker's object for this member, if any
+	Pos() token.Pos                  // position of member's declaration, if known
+	Type() types.Type                // type of the package member
+	Token() token.Token              // token.{VAR,FUNC,CONST,TYPE}
+	Package() *Package               // returns the containing package. (TODO: rename Pkg)
+}
+
+// A Type is a Member of a Package representing a package-level named type.
+//
+// Type() returns a *types.Named.
+//
+type Type struct {
+	object *types.TypeName
+	pkg    *Package
+}
+
+// A NamedConst is a Member of Package representing a package-level
+// named constant value.
+//
+// Pos() returns the position of the declaring ast.ValueSpec.Names[*]
+// identifier.
+//
+// NB: a NamedConst is not a Value; it contains a constant Value, which
+// it augments with the name and position of its 'const' declaration.
+//
+type NamedConst struct {
+	object *types.Const
+	Value  *Const
+	pos    token.Pos
+	pkg    *Package
+}
+
+// A Value is an SSA value that can be referenced by an instruction.
+type Value interface {
+	// Name returns the name of this value, and determines how
+	// this Value appears when used as an operand of an
+	// Instruction.
+	//
+	// This is the same as the source name for Parameters,
+	// Builtins, Functions, FreeVars, Globals.
+	// For constants, it is a representation of the constant's value
+	// and type.  For all other Values this is the name of the
+	// virtual register defined by the instruction.
+	//
+	// The name of an SSA Value is not semantically significant,
+	// and may not even be unique within a function.
+	Name() string
+
+	// If this value is an Instruction, String returns its
+	// disassembled form; otherwise it returns unspecified
+	// human-readable information about the Value, such as its
+	// kind, name and type.
+	String() string
+
+	// Type returns the type of this value.  Many instructions
+	// (e.g. IndexAddr) change their behaviour depending on the
+	// types of their operands.
+	Type() types.Type
+
+	// Parent returns the function to which this Value belongs.
+	// It returns nil for named Functions, Builtin, Const and Global.
+	Parent() *Function
+
+	// Referrers returns the list of instructions that have this
+	// value as one of their operands; it may contain duplicates
+	// if an instruction has a repeated operand.
+	//
+	// Referrers actually returns a pointer through which the
+	// caller may perform mutations to the object's state.
+	//
+	// Referrers is currently only defined if Parent()!=nil,
+	// i.e. for the function-local values FreeVar, Parameter,
+	// Functions (iff anonymous) and all value-defining instructions.
+	// It returns nil for named Functions, Builtin, Const and Global.
+	//
+	// Instruction.Operands contains the inverse of this relation.
+	Referrers() *[]Instruction
+
+	// Pos returns the location of the AST token most closely
+	// associated with the operation that gave rise to this value,
+	// or token.NoPos if it was not explicit in the source.
+	//
+	// For each ast.Node type, a particular token is designated as
+	// the closest location for the expression, e.g. the Lparen
+	// for an *ast.CallExpr.  This permits a compact but
+	// approximate mapping from Values to source positions for use
+	// in diagnostic messages, for example.
+	//
+	// (Do not use this position to determine which Value
+	// corresponds to an ast.Expr; use Function.ValueForExpr
+	// instead.  NB: it requires that the function was built with
+	// debug information.)
+	//
+	Pos() token.Pos
+}
+
+// An Instruction is an SSA instruction that computes a new Value or
+// has some effect.
+//
+// An Instruction that defines a value (e.g. BinOp) also implements
+// the Value interface; an Instruction that only has an effect (e.g. Store)
+// does not.
+//
+type Instruction interface {
+	// String returns the disassembled form of this value.  e.g.
+	//
+	// Examples of Instructions that define a Value:
+	// e.g.  "x + y"     (BinOp)
+	//       "len([])"   (Call)
+	// Note that the name of the Value is not printed.
+	//
+	// Examples of Instructions that do define (are) Values:
+	// e.g.  "return x"  (Return)
+	//       "*y = x"    (Store)
+	//
+	// (This separation is useful for some analyses which
+	// distinguish the operation from the value it
+	// defines. e.g. 'y = local int' is both an allocation of
+	// memory 'local int' and a definition of a pointer y.)
+	String() string
+
+	// Parent returns the function to which this instruction
+	// belongs.
+	Parent() *Function
+
+	// Block returns the basic block to which this instruction
+	// belongs.
+	Block() *BasicBlock
+
+	// setBlock sets the basic block to which this instruction belongs.
+	setBlock(*BasicBlock)
+
+	// Operands returns the operands of this instruction: the
+	// set of Values it references.
+	//
+	// Specifically, it appends their addresses to rands, a
+	// user-provided slice, and returns the resulting slice,
+	// permitting avoidance of memory allocation.
+	//
+	// The operands are appended in undefined order, but the order
+	// is consistent for a given Instruction; the addresses are
+	// always non-nil but may point to a nil Value.  Clients may
+	// store through the pointers, e.g. to effect a value
+	// renaming.
+	//
+	// Value.Referrers is a subset of the inverse of this
+	// relation.  (Referrers are not tracked for all types of
+	// Values.)
+	Operands(rands []*Value) []*Value
+
+	// Pos returns the location of the AST token most closely
+	// associated with the operation that gave rise to this
+	// instruction, or token.NoPos if it was not explicit in the
+	// source.
+	//
+	// For each ast.Node type, a particular token is designated as
+	// the closest location for the expression, e.g. the Go token
+	// for an *ast.GoStmt.  This permits a compact but approximate
+	// mapping from Instructions to source positions for use in
+	// diagnostic messages, for example.
+	//
+	// (Do not use this position to determine which Instruction
+	// corresponds to an ast.Expr; see the notes for Value.Pos.
+	// This position may be used to determine which non-Value
+	// Instruction corresponds to some ast.Stmts, but not all: If
+	// and Jump instructions have no Pos(), for example.)
+	//
+	Pos() token.Pos
+}
+
+// A Node is a node in the SSA value graph.  Every concrete type that
+// implements Node is also either a Value, an Instruction, or both.
+//
+// Node contains the methods common to Value and Instruction, plus the
+// Operands and Referrers methods generalized to return nil for
+// non-Instructions and non-Values, respectively.
+//
+// Node is provided to simplify SSA graph algorithms.  Clients should
+// use the more specific and informative Value or Instruction
+// interfaces where appropriate.
+//
+type Node interface {
+	// Common methods:
+	String() string
+	Pos() token.Pos
+	Parent() *Function
+
+	// Partial methods:
+	Operands(rands []*Value) []*Value // nil for non-Instructions
+	Referrers() *[]Instruction        // nil for non-Values
+}
+
+// Function represents the parameters, results and code of a function
+// or method.
+//
+// If Blocks is nil, this indicates an external function for which no
+// Go source code is available.  In this case, FreeVars and Locals
+// will be nil too.  Clients performing whole-program analysis must
+// handle external functions specially.
+//
+// Blocks contains the function's control-flow graph (CFG).
+// Blocks[0] is the function entry point; block order is not otherwise
+// semantically significant, though it may affect the readability of
+// the disassembly.
+// To iterate over the blocks in dominance order, use DomPreorder().
+//
+// Recover is an optional second entry point to which control resumes
+// after a recovered panic.  The Recover block may contain only a return
+// statement, preceded by a load of the function's named return
+// parameters, if any.
+//
+// A nested function (Parent()!=nil) that refers to one or more
+// lexically enclosing local variables ("free variables") has FreeVar
+// parameters.  Such functions cannot be called directly but require a
+// value created by MakeClosure which, via its Bindings, supplies
+// values for these parameters.
+//
+// If the function is a method (Signature.Recv() != nil) then the first
+// element of Params is the receiver parameter.
+//
+// Pos() returns the declaring ast.FuncLit.Type.Func or the position
+// of the ast.FuncDecl.Name, if the function was explicit in the
+// source.  Synthetic wrappers, for which Synthetic != "", may share
+// the same position as the function they wrap.
+// Syntax.Pos() always returns the position of the declaring "func" token.
+//
+// Type() returns the function's Signature.
+//
+type Function struct {
+	name      string
+	object    types.Object     // a declared *types.Func or one of its wrappers
+	method    *types.Selection // info about provenance of synthetic methods
+	Signature *types.Signature
+	pos       token.Pos
+
+	Synthetic string        // provenance of synthetic function; "" for true source functions
+	syntax    ast.Node      // *ast.Func{Decl,Lit}; replaced with simple ast.Node after build, unless debug mode
+	parent    *Function     // enclosing function if anon; nil if global
+	Pkg       *Package      // enclosing package; nil for shared funcs (wrappers and error.Error)
+	Prog      *Program      // enclosing program
+	Params    []*Parameter  // function parameters; for methods, includes receiver
+	FreeVars  []*FreeVar    // free variables whose values must be supplied by closure
+	Locals    []*Alloc      // local variables of this function
+	Blocks    []*BasicBlock // basic blocks of the function; nil => external
+	Recover   *BasicBlock   // optional; control transfers here after recovered panic
+	AnonFuncs []*Function   // anonymous functions directly beneath this one
+	referrers []Instruction // referring instructions (iff Parent() != nil)
+
+	// The following fields are set transiently during building,
+	// then cleared.
+	currentBlock *BasicBlock             // where to emit code
+	objects      map[types.Object]Value  // addresses of local variables
+	namedResults []*Alloc                // tuple of named results
+	targets      *targets                // linked stack of branch targets
+	lblocks      map[*ast.Object]*lblock // labelled blocks
+}
+
+// An SSA basic block.
+//
+// The final element of Instrs is always an explicit transfer of
+// control (If, Jump, Return or Panic).
+//
+// A block may contain no Instructions only if it is unreachable,
+// i.e. Preds is nil.  Empty blocks are typically pruned.
+//
+// BasicBlocks and their Preds/Succs relation form a (possibly cyclic)
+// graph independent of the SSA Value graph: the control-flow graph or
+// CFG.  It is illegal for multiple edges to exist between the same
+// pair of blocks.
+//
+// Each BasicBlock is also a node in the dominator tree of the CFG.
+// The tree may be navigated using Idom()/Dominees() and queried using
+// Dominates().
+//
+// The order of Preds and Succs is significant (to Phi and If
+// instructions, respectively).
+//
+type BasicBlock struct {
+	Index        int            // index of this block within Parent().Blocks
+	Comment      string         // optional label; no semantic significance
+	parent       *Function      // parent function
+	Instrs       []Instruction  // instructions in order
+	Preds, Succs []*BasicBlock  // predecessors and successors
+	succs2       [2]*BasicBlock // initial space for Succs.
+	dom          domInfo        // dominator tree info
+	gaps         int            // number of nil Instrs (transient).
+	rundefers    int            // number of rundefers (transient)
+}
+
+// Pure values ----------------------------------------
+
+// A FreeVar represents a free variable of the function to which it
+// belongs.
+//
+// FreeVars are used to implement anonymous functions, whose free
+// variables are lexically captured in a closure formed by
+// MakeClosure.  The value of such a free var is an Alloc or another
+// FreeVar and is considered a potentially escaping heap address, with
+// pointer type.
+//
+// FreeVars are also used to implement bound method closures.  Such a
+// free var represents the receiver value and may be of any type that
+// has concrete methods.
+//
+// Pos() returns the position of the value that was captured, which
+// belongs to an enclosing function.
+//
+type FreeVar struct {
+	name      string
+	typ       types.Type
+	pos       token.Pos
+	parent    *Function
+	referrers []Instruction
+
+	// Transiently needed during building.
+	outer Value // the Value captured from the enclosing context.
+}
+
+// A Parameter represents an input parameter of a function.
+//
+type Parameter struct {
+	name      string
+	object    types.Object // a *types.Var; nil for non-source locals
+	typ       types.Type
+	pos       token.Pos
+	parent    *Function
+	referrers []Instruction
+}
+
+// A Const represents the value of a constant expression.
+//
+// The underlying type of a constant may be any boolean, numeric, or
+// string type.  In addition, a Const may represent the nil value of
+// any reference type: interface, map, channel, pointer, slice, or
+// function---but not "untyped nil".
+//
+// All source-level constant expressions are represented by a Const
+// of equal type and value.
+//
+// Value holds the exact value of the constant, independent of its
+// Type(), using the same representation as package go/exact uses for
+// constants, or nil for a typed nil value.
+//
+// Pos() returns token.NoPos.
+//
+// Example printed form:
+// 	42:int
+//	"hello":untyped string
+//	3+4i:MyComplex
+//
+type Const struct {
+	typ   types.Type
+	Value exact.Value
+}
+
+// A Global is a named Value holding the address of a package-level
+// variable.
+//
+// Pos() returns the position of the ast.ValueSpec.Names[*]
+// identifier.
+//
+type Global struct {
+	name   string
+	object types.Object // a *types.Var; may be nil for synthetics e.g. init$guard
+	typ    types.Type
+	pos    token.Pos
+
+	Pkg *Package
+}
+
+// A Builtin represents a specific use of a built-in function, e.g. len.
+//
+// Builtins are immutable values.  Builtins do not have addresses.
+// Builtins can only appear in CallCommon.Func.
+//
+// Name() indicates the function: one of the built-in functions from the
+// Go spec (excluding "make" and "new") or one of these ssa-defined
+// intrinsics:
+//
+//   // wrapnilchk returns ptr if non-nil, panics otherwise.
+//   // (For use in indirection wrappers.)
+//   func ssa:wrapnilchk(ptr *T, recvType, methodName string) *T
+//
+// Object() returns a *types.Builtin for built-ins defined by the spec,
+// nil for others.
+//
+// Type() returns a *types.Signature representing the effective
+// signature of the built-in for this call.
+//
+type Builtin struct {
+	name string
+	sig  *types.Signature
+}
+
+// Value-defining instructions  ----------------------------------------
+
+// The Alloc instruction reserves space for a value of the given type,
+// zero-initializes it, and yields its address.
+//
+// Alloc values are always addresses, and have pointer types, so the
+// type of the allocated space is actually indirect(Type()).
+//
+// If Heap is false, Alloc allocates space in the function's
+// activation record (frame); we refer to an Alloc(Heap=false) as a
+// "local" alloc.  Each local Alloc returns the same address each time
+// it is executed within the same activation; the space is
+// re-initialized to zero.
+//
+// If Heap is true, Alloc allocates space in the heap, and returns; we
+// refer to an Alloc(Heap=true) as a "new" alloc.  Each new Alloc
+// returns a different address each time it is executed.
+//
+// When Alloc is applied to a channel, map or slice type, it returns
+// the address of an uninitialized (nil) reference of that kind; store
+// the result of MakeSlice, MakeMap or MakeChan in that location to
+// instantiate these types.
+//
+// Pos() returns the ast.CompositeLit.Lbrace for a composite literal,
+// or the ast.CallExpr.Rparen for a call to new() or for a call that
+// allocates a varargs slice.
+//
+// Example printed form:
+// 	t0 = local int
+// 	t1 = new int
+//
+type Alloc struct {
+	register
+	Comment string
+	Heap    bool
+	index   int // dense numbering; for lifting
+}
+
+// The Phi instruction represents an SSA φ-node, which combines values
+// that differ across incoming control-flow edges and yields a new
+// value.  Within a block, all φ-nodes must appear before all non-φ
+// nodes.
+//
+// Pos() returns the position of the && or || for short-circuit
+// control-flow joins, or that of the *Alloc for φ-nodes inserted
+// during SSA renaming.
+//
+// Example printed form:
+// 	t2 = phi [0.start: t0, 1.if.then: t1, ...]
+//
+type Phi struct {
+	register
+	Comment string  // a hint as to its purpose
+	Edges   []Value // Edges[i] is value for Block().Preds[i]
+}
+
+// The Call instruction represents a function or method call.
+//
+// The Call instruction yields the function result, if there is
+// exactly one, or a tuple (empty or len>1) whose components are
+// accessed via Extract.
+//
+// See CallCommon for generic function call documentation.
+//
+// Pos() returns the ast.CallExpr.Lparen, if explicit in the source.
+//
+// Example printed form:
+// 	t2 = println(t0, t1)
+// 	t4 = t3()
+// 	t7 = invoke t5.Println(...t6)
+//
+type Call struct {
+	register
+	Call CallCommon
+}
+
+// The BinOp instruction yields the result of binary operation X Op Y.
+//
+// Pos() returns the ast.BinaryExpr.OpPos, if explicit in the source.
+//
+// Example printed form:
+// 	t1 = t0 + 1:int
+//
+type BinOp struct {
+	register
+	// One of:
+	// ADD SUB MUL QUO REM          + - * / %
+	// AND OR XOR SHL SHR AND_NOT   & | ^ << >> &~
+	// EQL LSS GTR NEQ LEQ GEQ      == != < <= < >=
+	Op   token.Token
+	X, Y Value
+}
+
+// The UnOp instruction yields the result of Op X.
+// ARROW is channel receive.
+// MUL is pointer indirection (load).
+// XOR is bitwise complement.
+// SUB is negation.
+// NOT is logical negation.
+//
+// If CommaOk and Op=ARROW, the result is a 2-tuple of the value above
+// and a boolean indicating the success of the receive.  The
+// components of the tuple are accessed using Extract.
+//
+// Pos() returns the ast.UnaryExpr.OpPos or ast.RangeStmt.TokPos (for
+// ranging over a channel), if explicit in the source.
+//
+// Example printed form:
+// 	t0 = *x
+// 	t2 = <-t1,ok
+//
+type UnOp struct {
+	register
+	Op      token.Token // One of: NOT SUB ARROW MUL XOR ! - <- * ^
+	X       Value
+	CommaOk bool
+}
+
+// The ChangeType instruction applies to X a value-preserving type
+// change to Type().
+//
+// Type changes are permitted:
+//    - between a named type and its underlying type.
+//    - between two named types of the same underlying type.
+//    - between (possibly named) pointers to identical base types.
+//    - from a bidirectional channel to a read- or write-channel,
+//      optionally adding/removing a name.
+//
+// This operation cannot fail dynamically.
+//
+// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
+// from an explicit conversion in the source.
+//
+// Example printed form:
+// 	t1 = changetype *int <- IntPtr (t0)
+//
+type ChangeType struct {
+	register
+	X Value
+}
+
+// The Convert instruction yields the conversion of value X to type
+// Type().  One or both of those types is basic (but possibly named).
+//
+// A conversion may change the value and representation of its operand.
+// Conversions are permitted:
+//    - between real numeric types.
+//    - between complex numeric types.
+//    - between string and []byte or []rune.
+//    - between pointers and unsafe.Pointer.
+//    - between unsafe.Pointer and uintptr.
+//    - from (Unicode) integer to (UTF-8) string.
+// A conversion may imply a type name change also.
+//
+// This operation cannot fail dynamically.
+//
+// Conversions of untyped string/number/bool constants to a specific
+// representation are eliminated during SSA construction.
+//
+// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
+// from an explicit conversion in the source.
+//
+// Example printed form:
+// 	t1 = convert []byte <- string (t0)
+//
+type Convert struct {
+	register
+	X Value
+}
+
+// ChangeInterface constructs a value of one interface type from a
+// value of another interface type known to be assignable to it.
+// This operation cannot fail.
+//
+// Pos() returns the ast.CallExpr.Lparen if the instruction arose from
+// an explicit T(e) conversion; the ast.TypeAssertExpr.Lparen if the
+// instruction arose from an explicit e.(T) operation; or token.NoPos
+// otherwise.
+//
+// Example printed form:
+// 	t1 = change interface interface{} <- I (t0)
+//
+type ChangeInterface struct {
+	register
+	X Value
+}
+
+// MakeInterface constructs an instance of an interface type from a
+// value of a concrete type.
+//
+// Use Program.MethodSets.MethodSet(X.Type()) to find the method-set
+// of X, and Program.Method(m) to find the implementation of a method.
+//
+// To construct the zero value of an interface type T, use:
+// 	NewConst(exact.MakeNil(), T, pos)
+//
+// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
+// from an explicit conversion in the source.
+//
+// Example printed form:
+// 	t1 = make interface{} <- int (42:int)
+// 	t2 = make Stringer <- t0
+//
+type MakeInterface struct {
+	register
+	X Value
+}
+
+// The MakeClosure instruction yields a closure value whose code is
+// Fn and whose free variables' values are supplied by Bindings.
+//
+// Type() returns a (possibly named) *types.Signature.
+//
+// Pos() returns the ast.FuncLit.Type.Func for a function literal
+// closure or the ast.SelectorExpr.Sel for a bound method closure.
+//
+// Example printed form:
+// 	t0 = make closure anon@1.2 [x y z]
+// 	t1 = make closure bound$(main.I).add [i]
+//
+type MakeClosure struct {
+	register
+	Fn       Value   // always a *Function
+	Bindings []Value // values for each free variable in Fn.FreeVars
+}
+
+// The MakeMap instruction creates a new hash-table-based map object
+// and yields a value of kind map.
+//
+// Type() returns a (possibly named) *types.Map.
+//
+// Pos() returns the ast.CallExpr.Lparen, if created by make(map), or
+// the ast.CompositeLit.Lbrack if created by a literal.
+//
+// Example printed form:
+// 	t1 = make map[string]int t0
+// 	t1 = make StringIntMap t0
+//
+type MakeMap struct {
+	register
+	Reserve Value // initial space reservation; nil => default
+}
+
+// The MakeChan instruction creates a new channel object and yields a
+// value of kind chan.
+//
+// Type() returns a (possibly named) *types.Chan.
+//
+// Pos() returns the ast.CallExpr.Lparen for the make(chan) that
+// created it.
+//
+// Example printed form:
+// 	t0 = make chan int 0
+// 	t0 = make IntChan 0
+//
+type MakeChan struct {
+	register
+	Size Value // int; size of buffer; zero => synchronous.
+}
+
+// The MakeSlice instruction yields a slice of length Len backed by a
+// newly allocated array of length Cap.
+//
+// Both Len and Cap must be non-nil Values of integer type.
+//
+// (Alloc(types.Array) followed by Slice will not suffice because
+// Alloc can only create arrays of constant length.)
+//
+// Type() returns a (possibly named) *types.Slice.
+//
+// Pos() returns the ast.CallExpr.Lparen for the make([]T) that
+// created it.
+//
+// Example printed form:
+// 	t1 = make []string 1:int t0
+// 	t1 = make StringSlice 1:int t0
+//
+type MakeSlice struct {
+	register
+	Len Value
+	Cap Value
+}
+
+// The Slice instruction yields a slice of an existing string, slice
+// or *array X between optional integer bounds Low and High.
+//
+// Dynamically, this instruction panics if X evaluates to a nil *array
+// pointer.
+//
+// Type() returns string if the type of X was string, otherwise a
+// *types.Slice with the same element type as X.
+//
+// Pos() returns the ast.SliceExpr.Lbrack if created by a x[:] slice
+// operation, the ast.CompositeLit.Lbrace if created by a literal, or
+// NoPos if not explicit in the source (e.g. a variadic argument slice).
+//
+// Example printed form:
+// 	t1 = slice t0[1:]
+//
+type Slice struct {
+	register
+	X              Value // slice, string, or *array
+	Low, High, Max Value // each may be nil
+}
+
+// The FieldAddr instruction yields the address of Field of *struct X.
+//
+// The field is identified by its index within the field list of the
+// struct type of X.
+//
+// Dynamically, this instruction panics if X evaluates to a nil
+// pointer.
+//
+// Type() returns a (possibly named) *types.Pointer.
+//
+// Pos() returns the position of the ast.SelectorExpr.Sel for the
+// field, if explicit in the source.
+//
+// Example printed form:
+// 	t1 = &t0.name [#1]
+//
+type FieldAddr struct {
+	register
+	X     Value // *struct
+	Field int   // index into X.Type().Deref().(*types.Struct).Fields
+}
+
+// The Field instruction yields the Field of struct X.
+//
+// The field is identified by its index within the field list of the
+// struct type of X; by using numeric indices we avoid ambiguity of
+// package-local identifiers and permit compact representations.
+//
+// Pos() returns the position of the ast.SelectorExpr.Sel for the
+// field, if explicit in the source.
+//
+// Example printed form:
+// 	t1 = t0.name [#1]
+//
+type Field struct {
+	register
+	X     Value // struct
+	Field int   // index into X.Type().(*types.Struct).Fields
+}
+
+// The IndexAddr instruction yields the address of the element at
+// index Index of collection X.  Index is an integer expression.
+//
+// The elements of maps and strings are not addressable; use Lookup or
+// MapUpdate instead.
+//
+// Dynamically, this instruction panics if X evaluates to a nil *array
+// pointer.
+//
+// Type() returns a (possibly named) *types.Pointer.
+//
+// Pos() returns the ast.IndexExpr.Lbrack for the index operation, if
+// explicit in the source.
+//
+// Example printed form:
+// 	t2 = &t0[t1]
+//
+type IndexAddr struct {
+	register
+	X     Value // slice or *array,
+	Index Value // numeric index
+}
+
+// The Index instruction yields element Index of array X.
+//
+// Pos() returns the ast.IndexExpr.Lbrack for the index operation, if
+// explicit in the source.
+//
+// Example printed form:
+// 	t2 = t0[t1]
+//
+type Index struct {
+	register
+	X     Value // array
+	Index Value // integer index
+}
+
+// The Lookup instruction yields element Index of collection X, a map
+// or string.  Index is an integer expression if X is a string or the
+// appropriate key type if X is a map.
+//
+// If CommaOk, the result is a 2-tuple of the value above and a
+// boolean indicating the result of a map membership test for the key.
+// The components of the tuple are accessed using Extract.
+//
+// Pos() returns the ast.IndexExpr.Lbrack, if explicit in the source.
+//
+// Example printed form:
+// 	t2 = t0[t1]
+// 	t5 = t3[t4],ok
+//
+type Lookup struct {
+	register
+	X       Value // string or map
+	Index   Value // numeric or key-typed index
+	CommaOk bool  // return a value,ok pair
+}
+
+// SelectState is a helper for Select.
+// It represents one goal state and its corresponding communication.
+//
+type SelectState struct {
+	Dir       types.ChanDir // direction of case (SendOnly or RecvOnly)
+	Chan      Value         // channel to use (for send or receive)
+	Send      Value         // value to send (for send)
+	Pos       token.Pos     // position of token.ARROW
+	DebugNode ast.Node      // ast.SendStmt or ast.UnaryExpr(<-) [debug mode]
+}
+
+// The Select instruction tests whether (or blocks until) one
+// of the specified sent or received states is entered.
+//
+// Let n be the number of States for which Dir==RECV and T_i (0<=i<n)
+// be the element type of each such state's Chan.
+// Select returns an n+2-tuple
+//    (index int, recvOk bool, r_0 T_0, ... r_n-1 T_n-1)
+// The tuple's components, described below, must be accessed via the
+// Extract instruction.
+//
+// If Blocking, select waits until exactly one state holds, i.e. a
+// channel becomes ready for the designated operation of sending or
+// receiving; select chooses one among the ready states
+// pseudorandomly, performs the send or receive operation, and sets
+// 'index' to the index of the chosen channel.
+//
+// If !Blocking, select doesn't block if no states hold; instead it
+// returns immediately with index equal to -1.
+//
+// If the chosen channel was used for a receive, the r_i component is
+// set to the received value, where i is the index of that state among
+// all n receive states; otherwise r_i has the zero value of type T_i.
+// Note that the receive index i is not the same as the state
+// index index.
+//
+// The second component of the triple, recvOk, is a boolean whose value
+// is true iff the selected operation was a receive and the receive
+// successfully yielded a value.
+//
+// Pos() returns the ast.SelectStmt.Select.
+//
+// Example printed form:
+// 	t3 = select nonblocking [<-t0, t1<-t2]
+// 	t4 = select blocking []
+//
+type Select struct {
+	register
+	States   []*SelectState
+	Blocking bool
+}
+
+// The Range instruction yields an iterator over the domain and range
+// of X, which must be a string or map.
+//
+// Elements are accessed via Next.
+//
+// Type() returns an opaque and degenerate "rangeIter" type.
+//
+// Pos() returns the ast.RangeStmt.For.
+//
+// Example printed form:
+// 	t0 = range "hello":string
+//
+type Range struct {
+	register
+	X Value // string or map
+}
+
+// The Next instruction reads and advances the (map or string)
+// iterator Iter and returns a 3-tuple value (ok, k, v).  If the
+// iterator is not exhausted, ok is true and k and v are the next
+// elements of the domain and range, respectively.  Otherwise ok is
+// false and k and v are undefined.
+//
+// Components of the tuple are accessed using Extract.
+//
+// The IsString field distinguishes iterators over strings from those
+// over maps, as the Type() alone is insufficient: consider
+// map[int]rune.
+//
+// Type() returns a *types.Tuple for the triple (ok, k, v).
+// The types of k and/or v may be types.Invalid.
+//
+// Example printed form:
+// 	t1 = next t0
+//
+type Next struct {
+	register
+	Iter     Value
+	IsString bool // true => string iterator; false => map iterator.
+}
+
+// The TypeAssert instruction tests whether interface value X has type
+// AssertedType.
+//
+// If !CommaOk, on success it returns v, the result of the conversion
+// (defined below); on failure it panics.
+//
+// If CommaOk: on success it returns a pair (v, true) where v is the
+// result of the conversion; on failure it returns (z, false) where z
+// is AssertedType's zero value.  The components of the pair must be
+// accessed using the Extract instruction.
+//
+// If AssertedType is a concrete type, TypeAssert checks whether the
+// dynamic type in interface X is equal to it, and if so, the result
+// of the conversion is a copy of the value in the interface.
+//
+// If AssertedType is an interface, TypeAssert checks whether the
+// dynamic type of the interface is assignable to it, and if so, the
+// result of the conversion is a copy of the interface value X.
+// If AssertedType is a superinterface of X.Type(), the operation will
+// fail iff the operand is nil.  (Contrast with ChangeInterface, which
+// performs no nil-check.)
+//
+// Type() reflects the actual type of the result, possibly a
+// 2-types.Tuple; AssertedType is the asserted type.
+//
+// Pos() returns the ast.CallExpr.Lparen if the instruction arose from
+// an explicit T(e) conversion; the ast.TypeAssertExpr.Lparen if the
+// instruction arose from an explicit e.(T) operation; or the
+// ast.CaseClause.Case if the instruction arose from a case of a
+// type-switch statement.
+//
+// Example printed form:
+// 	t1 = typeassert t0.(int)
+// 	t3 = typeassert,ok t2.(T)
+//
+type TypeAssert struct {
+	register
+	X            Value
+	AssertedType types.Type
+	CommaOk      bool
+}
+
+// The Extract instruction yields component Index of Tuple.
+//
+// This is used to access the results of instructions with multiple
+// return values, such as Call, TypeAssert, Next, UnOp(ARROW) and
+// IndexExpr(Map).
+//
+// Example printed form:
+// 	t1 = extract t0 #1
+//
+type Extract struct {
+	register
+	Tuple Value
+	Index int
+}
+
+// Instructions executed for effect.  They do not yield a value. --------------------
+
+// The Jump instruction transfers control to the sole successor of its
+// owning block.
+//
+// A Jump must be the last instruction of its containing BasicBlock.
+//
+// Pos() returns NoPos.
+//
+// Example printed form:
+// 	jump done
+//
+type Jump struct {
+	anInstruction
+}
+
+// The If instruction transfers control to one of the two successors
+// of its owning block, depending on the boolean Cond: the first if
+// true, the second if false.
+//
+// An If instruction must be the last instruction of its containing
+// BasicBlock.
+//
+// Pos() returns NoPos.
+//
+// Example printed form:
+// 	if t0 goto done else body
+//
+type If struct {
+	anInstruction
+	Cond Value
+}
+
+// The Return instruction returns values and control back to the calling
+// function.
+//
+// len(Results) is always equal to the number of results in the
+// function's signature.
+//
+// If len(Results) > 1, Return returns a tuple value with the specified
+// components which the caller must access using Extract instructions.
+//
+// There is no instruction to return a ready-made tuple like those
+// returned by a "value,ok"-mode TypeAssert, Lookup or UnOp(ARROW) or
+// a tail-call to a function with multiple result parameters.
+//
+// Return must be the last instruction of its containing BasicBlock.
+// Such a block has no successors.
+//
+// Pos() returns the ast.ReturnStmt.Return, if explicit in the source.
+//
+// Example printed form:
+// 	return
+// 	return nil:I, 2:int
+//
+type Return struct {
+	anInstruction
+	Results []Value
+	pos     token.Pos
+}
+
+// The RunDefers instruction pops and invokes the entire stack of
+// procedure calls pushed by Defer instructions in this function.
+//
+// It is legal to encounter multiple 'rundefers' instructions in a
+// single control-flow path through a function; this is useful in
+// the combined init() function, for example.
+//
+// Pos() returns NoPos.
+//
+// Example printed form:
+//	rundefers
+//
+type RunDefers struct {
+	anInstruction
+}
+
+// The Panic instruction initiates a panic with value X.
+//
+// A Panic instruction must be the last instruction of its containing
+// BasicBlock, which must have no successors.
+//
+// NB: 'go panic(x)' and 'defer panic(x)' do not use this instruction;
+// they are treated as calls to a built-in function.
+//
+// Pos() returns the ast.CallExpr.Lparen if this panic was explicit
+// in the source.
+//
+// Example printed form:
+// 	panic t0
+//
+type Panic struct {
+	anInstruction
+	X   Value // an interface{}
+	pos token.Pos
+}
+
+// The Go instruction creates a new goroutine and calls the specified
+// function within it.
+//
+// See CallCommon for generic function call documentation.
+//
+// Pos() returns the ast.GoStmt.Go.
+//
+// Example printed form:
+// 	go println(t0, t1)
+// 	go t3()
+// 	go invoke t5.Println(...t6)
+//
+type Go struct {
+	anInstruction
+	Call CallCommon
+	pos  token.Pos
+}
+
+// The Defer instruction pushes the specified call onto a stack of
+// functions to be called by a RunDefers instruction or by a panic.
+//
+// See CallCommon for generic function call documentation.
+//
+// Pos() returns the ast.DeferStmt.Defer.
+//
+// Example printed form:
+// 	defer println(t0, t1)
+// 	defer t3()
+// 	defer invoke t5.Println(...t6)
+//
+type Defer struct {
+	anInstruction
+	Call CallCommon
+	pos  token.Pos
+}
+
+// The Send instruction sends X on channel Chan.
+//
+// Pos() returns the ast.SendStmt.Arrow, if explicit in the source.
+//
+// Example printed form:
+// 	send t0 <- t1
+//
+type Send struct {
+	anInstruction
+	Chan, X Value
+	pos     token.Pos
+}
+
+// The Store instruction stores Val at address Addr.
+// Stores can be of arbitrary types.
+//
+// Pos() returns the ast.StarExpr.Star, if explicit in the source.
+//
+// Example printed form:
+// 	*x = y
+//
+type Store struct {
+	anInstruction
+	Addr Value
+	Val  Value
+	pos  token.Pos
+}
+
+// The MapUpdate instruction updates the association of Map[Key] to
+// Value.
+//
+// Pos() returns the ast.KeyValueExpr.Colon or ast.IndexExpr.Lbrack,
+// if explicit in the source.
+//
+// Example printed form:
+//	t0[t1] = t2
+//
+type MapUpdate struct {
+	anInstruction
+	Map   Value
+	Key   Value
+	Value Value
+	pos   token.Pos
+}
+
+// A DebugRef instruction maps a source-level expression Expr to the
+// SSA value X that represents the value (!IsAddr) or address (IsAddr)
+// of that expression.
+//
+// DebugRef is a pseudo-instruction: it has no dynamic effect.
+//
+// Pos() returns Expr.Pos(), the start position of the source-level
+// expression.  This is not the same as the "designated" token as
+// documented at Value.Pos(). e.g. CallExpr.Pos() does not return the
+// position of the ("designated") Lparen token.
+//
+// If Expr is an *ast.Ident denoting a var or func, Object() returns
+// the object; though this information can be obtained from the type
+// checker, including it here greatly facilitates debugging.
+// For non-Ident expressions, Object() returns nil.
+//
+// DebugRefs are generated only for functions built with debugging
+// enabled; see Package.SetDebugMode() and the GlobalDebug builder
+// mode flag.
+//
+// DebugRefs are not emitted for ast.Idents referring to constants or
+// predeclared identifiers, since they are trivial and numerous.
+// Nor are they emitted for ast.ParenExprs.
+//
+// (By representing these as instructions, rather than out-of-band,
+// consistency is maintained during transformation passes by the
+// ordinary SSA renaming machinery.)
+//
+// Example printed form:
+//      ; *ast.CallExpr @ 102:9 is t5
+//      ; var x float64 @ 109:72 is x
+//      ; address of *ast.CompositeLit @ 216:10 is t0
+//
+type DebugRef struct {
+	anInstruction
+	Expr   ast.Expr     // the referring expression (never *ast.ParenExpr)
+	object types.Object // the identity of the source var/func
+	IsAddr bool         // Expr is addressable and X is the address it denotes
+	X      Value        // the value or address of Expr
+}
+
+// Embeddable mix-ins and helpers for common parts of other structs. -----------
+
+// register is a mix-in embedded by all SSA values that are also
+// instructions, i.e. virtual registers, and provides a uniform
+// implementation of most of the Value interface: Value.Name() is a
+// numbered register (e.g. "t0"); the other methods are field accessors.
+//
+// Temporary names are automatically assigned to each register on
+// completion of building a function in SSA form.
+//
+// Clients must not assume that the 'id' value (and the Name() derived
+// from it) is unique within a function.  As always in this API,
+// semantics are determined only by identity; names exist only to
+// facilitate debugging.
+//
+type register struct {
+	anInstruction
+	num       int        // "name" of virtual register, e.g. "t0".  Not guaranteed unique.
+	typ       types.Type // type of virtual register
+	pos       token.Pos  // position of source expression, or NoPos
+	referrers []Instruction
+}
+
+// anInstruction is a mix-in embedded by all Instructions.
+// It provides the implementations of the Block and setBlock methods.
+type anInstruction struct {
+	block *BasicBlock // the basic block of this instruction
+}
+
+// CallCommon is contained by Go, Defer and Call to hold the
+// common parts of a function or method call.
+//
+// Each CallCommon exists in one of two modes, function call and
+// interface method invocation, or "call" and "invoke" for short.
+//
+// 1. "call" mode: when Method is nil (!IsInvoke), a CallCommon
+// represents an ordinary function call of the value in Value,
+// which may be a *Builtin, a *Function or any other value of kind
+// 'func'.
+//
+// Value may be one of:
+//    (a) a *Function, indicating a statically dispatched call
+//        to a package-level function, an anonymous function, or
+//        a method of a named type.
+//    (b) a *MakeClosure, indicating an immediately applied
+//        function literal with free variables.
+//    (c) a *Builtin, indicating a statically dispatched call
+//        to a built-in function.
+//    (d) any other value, indicating a dynamically dispatched
+//        function call.
+// StaticCallee returns the identity of the callee in cases
+// (a) and (b), nil otherwise.
+//
+// Args contains the arguments to the call.  If Value is a method,
+// Args[0] contains the receiver parameter.
+//
+// Example printed form:
+// 	t2 = println(t0, t1)
+// 	go t3()
+//	defer t5(...t6)
+//
+// 2. "invoke" mode: when Method is non-nil (IsInvoke), a CallCommon
+// represents a dynamically dispatched call to an interface method.
+// In this mode, Value is the interface value and Method is the
+// interface's abstract method.  Note: an abstract method may be
+// shared by multiple interfaces due to embedding; Value.Type()
+// provides the specific interface used for this call.
+//
+// Value is implicitly supplied to the concrete method implementation
+// as the receiver parameter; in other words, Args[0] holds not the
+// receiver but the first true argument.
+//
+// Example printed form:
+// 	t1 = invoke t0.String()
+// 	go invoke t3.Run(t2)
+// 	defer invoke t4.Handle(...t5)
+//
+// For all calls to variadic functions (Signature().Variadic()),
+// the last element of Args is a slice.
+//
+type CallCommon struct {
+	Value  Value       // receiver (invoke mode) or func value (call mode)
+	Method *types.Func // abstract method (invoke mode)
+	Args   []Value     // actual parameters (in static method call, includes receiver)
+	pos    token.Pos   // position of CallExpr.Lparen, iff explicit in source
+}
+
+// IsInvoke returns true if this call has "invoke" (not "call") mode.
+func (c *CallCommon) IsInvoke() bool {
+	return c.Method != nil
+}
+
+func (c *CallCommon) Pos() token.Pos { return c.pos }
+
+// Signature returns the signature of the called function.
+//
+// For an "invoke"-mode call, the signature of the interface method is
+// returned.
+//
+// In either "call" or "invoke" mode, if the callee is a method, its
+// receiver is represented by sig.Recv, not sig.Params().At(0).
+//
+func (c *CallCommon) Signature() *types.Signature {
+	if c.Method != nil {
+		return c.Method.Type().(*types.Signature)
+	}
+	return c.Value.Type().Underlying().(*types.Signature)
+}
+
+// StaticCallee returns the callee if this is a trivially static
+// "call"-mode call to a function.
+func (c *CallCommon) StaticCallee() *Function {
+	switch fn := c.Value.(type) {
+	case *Function:
+		return fn
+	case *MakeClosure:
+		return fn.Fn.(*Function)
+	}
+	return nil
+}
+
+// Description returns a description of the mode of this call suitable
+// for a user interface, e.g. "static method call".
+func (c *CallCommon) Description() string {
+	switch fn := c.Value.(type) {
+	case *Builtin:
+		return "built-in function call"
+	case *MakeClosure:
+		return "static function closure call"
+	case *Function:
+		if fn.Signature.Recv() != nil {
+			return "static method call"
+		}
+		return "static function call"
+	}
+	if c.IsInvoke() {
+		return "dynamic method call" // ("invoke" mode)
+	}
+	return "dynamic function call"
+}
+
+// The CallInstruction interface, implemented by *Go, *Defer and *Call,
+// exposes the common parts of function-calling instructions,
+// yet provides a way back to the Value defined by *Call alone.
+//
+type CallInstruction interface {
+	Instruction
+	Common() *CallCommon // returns the common parts of the call
+	Value() *Call        // returns the result value of the call (*Call) or nil (*Go, *Defer)
+}
+
+func (s *Call) Common() *CallCommon  { return &s.Call }
+func (s *Defer) Common() *CallCommon { return &s.Call }
+func (s *Go) Common() *CallCommon    { return &s.Call }
+
+func (s *Call) Value() *Call  { return s }
+func (s *Defer) Value() *Call { return nil }
+func (s *Go) Value() *Call    { return nil }
+
+func (v *Builtin) Type() types.Type        { return v.sig }
+func (v *Builtin) Name() string            { return v.name }
+func (*Builtin) Referrers() *[]Instruction { return nil }
+func (v *Builtin) Pos() token.Pos          { return token.NoPos }
+func (v *Builtin) Object() types.Object    { return types.Universe.Lookup(v.name) }
+func (v *Builtin) Parent() *Function       { return nil }
+
+func (v *FreeVar) Type() types.Type          { return v.typ }
+func (v *FreeVar) Name() string              { return v.name }
+func (v *FreeVar) Referrers() *[]Instruction { return &v.referrers }
+func (v *FreeVar) Pos() token.Pos            { return v.pos }
+func (v *FreeVar) Parent() *Function         { return v.parent }
+
+func (v *Global) Type() types.Type                     { return v.typ }
+func (v *Global) Name() string                         { return v.name }
+func (v *Global) Parent() *Function                    { return nil }
+func (v *Global) Pos() token.Pos                       { return v.pos }
+func (v *Global) Referrers() *[]Instruction            { return nil }
+func (v *Global) Token() token.Token                   { return token.VAR }
+func (v *Global) Object() types.Object                 { return v.object }
+func (v *Global) String() string                       { return v.RelString(nil) }
+func (v *Global) Package() *Package                    { return v.Pkg }
+func (v *Global) RelString(from *types.Package) string { return relString(v, from) }
+
+func (v *Function) Name() string         { return v.name }
+func (v *Function) Type() types.Type     { return v.Signature }
+func (v *Function) Pos() token.Pos       { return v.pos }
+func (v *Function) Token() token.Token   { return token.FUNC }
+func (v *Function) Object() types.Object { return v.object }
+func (v *Function) String() string       { return v.RelString(nil) }
+func (v *Function) Package() *Package    { return v.Pkg }
+func (v *Function) Parent() *Function    { return v.parent }
+func (v *Function) Referrers() *[]Instruction {
+	if v.parent != nil {
+		return &v.referrers
+	}
+	return nil
+}
+
+func (v *Parameter) Type() types.Type          { return v.typ }
+func (v *Parameter) Name() string              { return v.name }
+func (v *Parameter) Object() types.Object      { return v.object }
+func (v *Parameter) Referrers() *[]Instruction { return &v.referrers }
+func (v *Parameter) Pos() token.Pos            { return v.pos }
+func (v *Parameter) Parent() *Function         { return v.parent }
+
+func (v *Alloc) Type() types.Type          { return v.typ }
+func (v *Alloc) Referrers() *[]Instruction { return &v.referrers }
+func (v *Alloc) Pos() token.Pos            { return v.pos }
+
+func (v *register) Type() types.Type          { return v.typ }
+func (v *register) setType(typ types.Type)    { v.typ = typ }
+func (v *register) Name() string              { return fmt.Sprintf("t%d", v.num) }
+func (v *register) setNum(num int)            { v.num = num }
+func (v *register) Referrers() *[]Instruction { return &v.referrers }
+func (v *register) Pos() token.Pos            { return v.pos }
+func (v *register) setPos(pos token.Pos)      { v.pos = pos }
+
+func (v *anInstruction) Parent() *Function          { return v.block.parent }
+func (v *anInstruction) Block() *BasicBlock         { return v.block }
+func (v *anInstruction) setBlock(block *BasicBlock) { v.block = block }
+func (v *anInstruction) Referrers() *[]Instruction  { return nil }
+
+func (t *Type) Name() string                         { return t.object.Name() }
+func (t *Type) Pos() token.Pos                       { return t.object.Pos() }
+func (t *Type) Type() types.Type                     { return t.object.Type() }
+func (t *Type) Token() token.Token                   { return token.TYPE }
+func (t *Type) Object() types.Object                 { return t.object }
+func (t *Type) String() string                       { return t.RelString(nil) }
+func (t *Type) Package() *Package                    { return t.pkg }
+func (t *Type) RelString(from *types.Package) string { return relString(t, from) }
+
+func (c *NamedConst) Name() string                         { return c.object.Name() }
+func (c *NamedConst) Pos() token.Pos                       { return c.object.Pos() }
+func (c *NamedConst) String() string                       { return c.RelString(nil) }
+func (c *NamedConst) Type() types.Type                     { return c.object.Type() }
+func (c *NamedConst) Token() token.Token                   { return token.CONST }
+func (c *NamedConst) Object() types.Object                 { return c.object }
+func (c *NamedConst) Package() *Package                    { return c.pkg }
+func (c *NamedConst) RelString(from *types.Package) string { return relString(c, from) }
+
+// Func returns the package-level function of the specified name,
+// or nil if not found.
+//
+func (p *Package) Func(name string) (f *Function) {
+	f, _ = p.Members[name].(*Function)
+	return
+}
+
+// Var returns the package-level variable of the specified name,
+// or nil if not found.
+//
+func (p *Package) Var(name string) (g *Global) {
+	g, _ = p.Members[name].(*Global)
+	return
+}
+
+// Const returns the package-level constant of the specified name,
+// or nil if not found.
+//
+func (p *Package) Const(name string) (c *NamedConst) {
+	c, _ = p.Members[name].(*NamedConst)
+	return
+}
+
+// Type returns the package-level type of the specified name,
+// or nil if not found.
+//
+func (p *Package) Type(name string) (t *Type) {
+	t, _ = p.Members[name].(*Type)
+	return
+}
+
+func (v *Call) Pos() token.Pos      { return v.Call.pos }
+func (s *Defer) Pos() token.Pos     { return s.pos }
+func (s *Go) Pos() token.Pos        { return s.pos }
+func (s *MapUpdate) Pos() token.Pos { return s.pos }
+func (s *Panic) Pos() token.Pos     { return s.pos }
+func (s *Return) Pos() token.Pos    { return s.pos }
+func (s *Send) Pos() token.Pos      { return s.pos }
+func (s *Store) Pos() token.Pos     { return s.pos }
+func (s *If) Pos() token.Pos        { return token.NoPos }
+func (s *Jump) Pos() token.Pos      { return token.NoPos }
+func (s *RunDefers) Pos() token.Pos { return token.NoPos }
+func (s *DebugRef) Pos() token.Pos  { return s.Expr.Pos() }
+
+// Operands.
+
+func (v *Alloc) Operands(rands []*Value) []*Value {
+	return rands
+}
+
+func (v *BinOp) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Y)
+}
+
+func (c *CallCommon) Operands(rands []*Value) []*Value {
+	rands = append(rands, &c.Value)
+	for i := range c.Args {
+		rands = append(rands, &c.Args[i])
+	}
+	return rands
+}
+
+func (s *Go) Operands(rands []*Value) []*Value {
+	return s.Call.Operands(rands)
+}
+
+func (s *Call) Operands(rands []*Value) []*Value {
+	return s.Call.Operands(rands)
+}
+
+func (s *Defer) Operands(rands []*Value) []*Value {
+	return s.Call.Operands(rands)
+}
+
+func (v *ChangeInterface) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *ChangeType) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *Convert) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (s *DebugRef) Operands(rands []*Value) []*Value {
+	return append(rands, &s.X)
+}
+
+func (v *Extract) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Tuple)
+}
+
+func (v *Field) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *FieldAddr) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (s *If) Operands(rands []*Value) []*Value {
+	return append(rands, &s.Cond)
+}
+
+func (v *Index) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Index)
+}
+
+func (v *IndexAddr) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Index)
+}
+
+func (*Jump) Operands(rands []*Value) []*Value {
+	return rands
+}
+
+func (v *Lookup) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Index)
+}
+
+func (v *MakeChan) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Size)
+}
+
+func (v *MakeClosure) Operands(rands []*Value) []*Value {
+	rands = append(rands, &v.Fn)
+	for i := range v.Bindings {
+		rands = append(rands, &v.Bindings[i])
+	}
+	return rands
+}
+
+func (v *MakeInterface) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *MakeMap) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Reserve)
+}
+
+func (v *MakeSlice) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Len, &v.Cap)
+}
+
+func (v *MapUpdate) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Map, &v.Key, &v.Value)
+}
+
+func (v *Next) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Iter)
+}
+
+func (s *Panic) Operands(rands []*Value) []*Value {
+	return append(rands, &s.X)
+}
+
+func (v *Phi) Operands(rands []*Value) []*Value {
+	for i := range v.Edges {
+		rands = append(rands, &v.Edges[i])
+	}
+	return rands
+}
+
+func (v *Range) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (s *Return) Operands(rands []*Value) []*Value {
+	for i := range s.Results {
+		rands = append(rands, &s.Results[i])
+	}
+	return rands
+}
+
+func (*RunDefers) Operands(rands []*Value) []*Value {
+	return rands
+}
+
+func (v *Select) Operands(rands []*Value) []*Value {
+	for i := range v.States {
+		rands = append(rands, &v.States[i].Chan, &v.States[i].Send)
+	}
+	return rands
+}
+
+func (s *Send) Operands(rands []*Value) []*Value {
+	return append(rands, &s.Chan, &s.X)
+}
+
+func (v *Slice) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Low, &v.High, &v.Max)
+}
+
+func (s *Store) Operands(rands []*Value) []*Value {
+	return append(rands, &s.Addr, &s.Val)
+}
+
+func (v *TypeAssert) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *UnOp) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+// Non-Instruction Values:
+func (v *Builtin) Operands(rands []*Value) []*Value   { return rands }
+func (v *FreeVar) Operands(rands []*Value) []*Value   { return rands }
+func (v *Const) Operands(rands []*Value) []*Value     { return rands }
+func (v *Function) Operands(rands []*Value) []*Value  { return rands }
+func (v *Global) Operands(rands []*Value) []*Value    { return rands }
+func (v *Parameter) Operands(rands []*Value) []*Value { return rands }
diff --git a/third_party/go.tools/go/ssa/ssautil/switch.go b/third_party/go.tools/go/ssa/ssautil/switch.go
new file mode 100644
index 0000000..5e1065d
--- /dev/null
+++ b/third_party/go.tools/go/ssa/ssautil/switch.go
@@ -0,0 +1,234 @@
+// Copyright 2013 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 ssautil
+
+// This file implements discovery of switch and type-switch constructs
+// from low-level control flow.
+//
+// Many techniques exist for compiling a high-level switch with
+// constant cases to efficient machine code.  The optimal choice will
+// depend on the data type, the specific case values, the code in the
+// body of each case, and the hardware.
+// Some examples:
+// - a lookup table (for a switch that maps constants to constants)
+// - a computed goto
+// - a binary tree
+// - a perfect hash
+// - a two-level switch (to partition constant strings by their first byte).
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// A ConstCase represents a single constant comparison.
+// It is part of a Switch.
+type ConstCase struct {
+	Block *ssa.BasicBlock // block performing the comparison
+	Body  *ssa.BasicBlock // body of the case
+	Value *ssa.Const      // case comparand
+}
+
+// A TypeCase represents a single type assertion.
+// It is part of a Switch.
+type TypeCase struct {
+	Block   *ssa.BasicBlock // block performing the type assert
+	Body    *ssa.BasicBlock // body of the case
+	Type    types.Type      // case type
+	Binding ssa.Value       // value bound by this case
+}
+
+// A Switch is a logical high-level control flow operation
+// (a multiway branch) discovered by analysis of a CFG containing
+// only if/else chains.  It is not part of the ssa.Instruction set.
+//
+// One of ConstCases and TypeCases has length >= 2;
+// the other is nil.
+//
+// In a value switch, the list of cases may contain duplicate constants.
+// A type switch may contain duplicate types, or types assignable
+// to an interface type also in the list.
+// TODO(adonovan): eliminate such duplicates.
+//
+type Switch struct {
+	Start      *ssa.BasicBlock // block containing start of if/else chain
+	X          ssa.Value       // the switch operand
+	ConstCases []ConstCase     // ordered list of constant comparisons
+	TypeCases  []TypeCase      // ordered list of type assertions
+	Default    *ssa.BasicBlock // successor if all comparisons fail
+}
+
+func (sw *Switch) String() string {
+	// We represent each block by the String() of its
+	// first Instruction, e.g. "print(42:int)".
+	var buf bytes.Buffer
+	if sw.ConstCases != nil {
+		fmt.Fprintf(&buf, "switch %s {\n", sw.X.Name())
+		for _, c := range sw.ConstCases {
+			fmt.Fprintf(&buf, "case %s: %s\n", c.Value, c.Body.Instrs[0])
+		}
+	} else {
+		fmt.Fprintf(&buf, "switch %s.(type) {\n", sw.X.Name())
+		for _, c := range sw.TypeCases {
+			fmt.Fprintf(&buf, "case %s %s: %s\n",
+				c.Binding.Name(), c.Type, c.Body.Instrs[0])
+		}
+	}
+	if sw.Default != nil {
+		fmt.Fprintf(&buf, "default: %s\n", sw.Default.Instrs[0])
+	}
+	fmt.Fprintf(&buf, "}")
+	return buf.String()
+}
+
+// Switches examines the control-flow graph of fn and returns the
+// set of inferred value and type switches.  A value switch tests an
+// ssa.Value for equality against two or more compile-time constant
+// values.  Switches involving link-time constants (addresses) are
+// ignored.  A type switch type-asserts an ssa.Value against two or
+// more types.
+//
+// The switches are returned in dominance order.
+//
+// The resulting switches do not necessarily correspond to uses of the
+// 'switch' keyword in the source: for example, a single source-level
+// switch statement with non-constant cases may result in zero, one or
+// many Switches, one per plural sequence of constant cases.
+// Switches may even be inferred from if/else- or goto-based control flow.
+// (In general, the control flow constructs of the source program
+// cannot be faithfully reproduced from the SSA representation.)
+//
+func Switches(fn *ssa.Function) []Switch {
+	// Traverse the CFG in dominance order, so we don't
+	// enter an if/else-chain in the middle.
+	var switches []Switch
+	seen := make(map[*ssa.BasicBlock]bool) // TODO(adonovan): opt: use ssa.blockSet
+	for _, b := range fn.DomPreorder() {
+		if x, k := isComparisonBlock(b); x != nil {
+			// Block b starts a switch.
+			sw := Switch{Start: b, X: x}
+			valueSwitch(&sw, k, seen)
+			if len(sw.ConstCases) > 1 {
+				switches = append(switches, sw)
+			}
+		}
+
+		if y, x, T := isTypeAssertBlock(b); y != nil {
+			// Block b starts a type switch.
+			sw := Switch{Start: b, X: x}
+			typeSwitch(&sw, y, T, seen)
+			if len(sw.TypeCases) > 1 {
+				switches = append(switches, sw)
+			}
+		}
+	}
+	return switches
+}
+
+func valueSwitch(sw *Switch, k *ssa.Const, seen map[*ssa.BasicBlock]bool) {
+	b := sw.Start
+	x := sw.X
+	for x == sw.X {
+		if seen[b] {
+			break
+		}
+		seen[b] = true
+
+		sw.ConstCases = append(sw.ConstCases, ConstCase{
+			Block: b,
+			Body:  b.Succs[0],
+			Value: k,
+		})
+		b = b.Succs[1]
+		if len(b.Instrs) > 2 {
+			// Block b contains not just 'if x == k',
+			// so it may have side effects that
+			// make it unsafe to elide.
+			break
+		}
+		if len(b.Preds) != 1 {
+			// Block b has multiple predecessors,
+			// so it cannot be treated as a case.
+			break
+		}
+		x, k = isComparisonBlock(b)
+	}
+	sw.Default = b
+}
+
+func typeSwitch(sw *Switch, y ssa.Value, T types.Type, seen map[*ssa.BasicBlock]bool) {
+	b := sw.Start
+	x := sw.X
+	for x == sw.X {
+		if seen[b] {
+			break
+		}
+		seen[b] = true
+
+		sw.TypeCases = append(sw.TypeCases, TypeCase{
+			Block:   b,
+			Body:    b.Succs[0],
+			Type:    T,
+			Binding: y,
+		})
+		b = b.Succs[1]
+		if len(b.Instrs) > 4 {
+			// Block b contains not just
+			//  {TypeAssert; Extract #0; Extract #1; If}
+			// so it may have side effects that
+			// make it unsafe to elide.
+			break
+		}
+		if len(b.Preds) != 1 {
+			// Block b has multiple predecessors,
+			// so it cannot be treated as a case.
+			break
+		}
+		y, x, T = isTypeAssertBlock(b)
+	}
+	sw.Default = b
+}
+
+// isComparisonBlock returns the operands (v, k) if a block ends with
+// a comparison v==k, where k is a compile-time constant.
+//
+func isComparisonBlock(b *ssa.BasicBlock) (v ssa.Value, k *ssa.Const) {
+	if n := len(b.Instrs); n >= 2 {
+		if i, ok := b.Instrs[n-1].(*ssa.If); ok {
+			if binop, ok := i.Cond.(*ssa.BinOp); ok && binop.Block() == b && binop.Op == token.EQL {
+				if k, ok := binop.Y.(*ssa.Const); ok {
+					return binop.X, k
+				}
+				if k, ok := binop.X.(*ssa.Const); ok {
+					return binop.Y, k
+				}
+			}
+		}
+	}
+	return
+}
+
+// isTypeAssertBlock returns the operands (y, x, T) if a block ends with
+// a type assertion "if y, ok := x.(T); ok {".
+//
+func isTypeAssertBlock(b *ssa.BasicBlock) (y, x ssa.Value, T types.Type) {
+	if n := len(b.Instrs); n >= 4 {
+		if i, ok := b.Instrs[n-1].(*ssa.If); ok {
+			if ext1, ok := i.Cond.(*ssa.Extract); ok && ext1.Block() == b && ext1.Index == 1 {
+				if ta, ok := ext1.Tuple.(*ssa.TypeAssert); ok && ta.Block() == b {
+					// hack: relies upon instruction ordering.
+					if ext0, ok := b.Instrs[n-3].(*ssa.Extract); ok {
+						return ext0, ta.X, ta.AssertedType
+					}
+				}
+			}
+		}
+	}
+	return
+}
diff --git a/third_party/go.tools/go/ssa/ssautil/switch_test.go b/third_party/go.tools/go/ssa/ssautil/switch_test.go
new file mode 100644
index 0000000..ceb09e6
--- /dev/null
+++ b/third_party/go.tools/go/ssa/ssautil/switch_test.go
@@ -0,0 +1,70 @@
+// Copyright 2013 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 ssautil_test
+
+import (
+	"go/parser"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/ssa/ssautil"
+)
+
+func TestSwitches(t *testing.T) {
+	conf := loader.Config{ParserMode: parser.ParseComments}
+	f, err := conf.ParseFile("testdata/switches.go", nil)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	conf.CreateFromFiles("main", f)
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	prog := ssa.Create(iprog, 0)
+	mainPkg := prog.Package(iprog.Created[0].Pkg)
+	mainPkg.Build()
+
+	for _, mem := range mainPkg.Members {
+		if fn, ok := mem.(*ssa.Function); ok {
+			if fn.Synthetic != "" {
+				continue // e.g. init()
+			}
+			// Each (multi-line) "switch" comment within
+			// this function must match the printed form
+			// of a ConstSwitch.
+			var wantSwitches []string
+			for _, c := range f.Comments {
+				if fn.Syntax().Pos() <= c.Pos() && c.Pos() < fn.Syntax().End() {
+					text := strings.TrimSpace(c.Text())
+					if strings.HasPrefix(text, "switch ") {
+						wantSwitches = append(wantSwitches, text)
+					}
+				}
+			}
+
+			switches := ssautil.Switches(fn)
+			if len(switches) != len(wantSwitches) {
+				t.Errorf("in %s, found %d switches, want %d", fn, len(switches), len(wantSwitches))
+			}
+			for i, sw := range switches {
+				got := sw.String()
+				if i >= len(wantSwitches) {
+					continue
+				}
+				want := wantSwitches[i]
+				if got != want {
+					t.Errorf("in %s, found switch %d: got <<%s>>, want <<%s>>", fn, i, got, want)
+				}
+			}
+		}
+	}
+}
diff --git a/third_party/go.tools/go/ssa/ssautil/testdata/switches.go b/third_party/go.tools/go/ssa/ssautil/testdata/switches.go
new file mode 100644
index 0000000..8ab4c11
--- /dev/null
+++ b/third_party/go.tools/go/ssa/ssautil/testdata/switches.go
@@ -0,0 +1,357 @@
+// +build ignore
+
+package main
+
+// This file is the input to TestSwitches in switch_test.go.
+// Each multiway conditional with constant or type cases (Switch)
+// discovered by Switches is printed, and compared with the
+// comments.
+//
+// The body of each case is printed as the value of its first
+// instruction.
+
+// -------- Value switches --------
+
+func SimpleSwitch(x, y int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(23:int)
+	// case 3:int: print(23:int)
+	// case 4:int: print(3:int)
+	// default: x == y
+	// }
+	switch x {
+	case 1:
+		print(1)
+	case 2, 3:
+		print(23)
+		fallthrough
+	case 4:
+		print(3)
+	default:
+		print(4)
+	case y:
+		print(5)
+	}
+	print(6)
+}
+
+func four() int { return 4 }
+
+// A non-constant case makes a switch "impure", but its pure
+// cases form two separate switches.
+func SwitchWithNonConstantCase(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(23:int)
+	// case 3:int: print(23:int)
+	// default: four()
+	// }
+
+	// switch x {
+	// case 5:int: print(5:int)
+	// case 6:int: print(6:int)
+	// default: print("done":string)
+	// }
+	switch x {
+	case 1:
+		print(1)
+	case 2, 3:
+		print(23)
+	case four():
+		print(3)
+	case 5:
+		print(5)
+	case 6:
+		print(6)
+	}
+	print("done")
+}
+
+// Switches may be found even where the source
+// program doesn't have a switch statement.
+
+func ImplicitSwitches(x, y int) {
+	// switch x {
+	// case 1:int: print(12:int)
+	// case 2:int: print(12:int)
+	// default: x < 5:int
+	// }
+	if x == 1 || 2 == x || x < 5 {
+		print(12)
+	}
+
+	// switch x {
+	// case 3:int: print(34:int)
+	// case 4:int: print(34:int)
+	// default: x == y
+	// }
+	if x == 3 || 4 == x || x == y {
+		print(34)
+	}
+
+	// Not a switch: no consistent variable.
+	if x == 5 || y == 6 {
+		print(56)
+	}
+
+	// Not a switch: only one constant comparison.
+	if x == 7 || x == y {
+		print(78)
+	}
+}
+
+func IfElseBasedSwitch(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(2:int)
+	// default: print("else":string)
+	// }
+	if x == 1 {
+		print(1)
+	} else if x == 2 {
+		print(2)
+	} else {
+		print("else")
+	}
+}
+
+func GotoBasedSwitch(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(2:int)
+	// default: print("else":string)
+	// }
+	if x == 1 {
+		goto L1
+	}
+	if x == 2 {
+		goto L2
+	}
+	print("else")
+L1:
+	print(1)
+	goto end
+L2:
+	print(2)
+end:
+}
+
+func SwitchInAForLoop(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(2:int)
+	// default: print("head":string)
+	// }
+loop:
+	for {
+		print("head")
+		switch x {
+		case 1:
+			print(1)
+			break loop
+		case 2:
+			print(2)
+			break loop
+		}
+	}
+}
+
+// This case is a switch in a for-loop, both constructed using goto.
+// As before, the default case points back to the block containing the
+// switch, but that's ok.
+func SwitchInAForLoopUsingGoto(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(2:int)
+	// default: print("head":string)
+	// }
+loop:
+	print("head")
+	if x == 1 {
+		goto L1
+	}
+	if x == 2 {
+		goto L2
+	}
+	goto loop
+L1:
+	print(1)
+	goto end
+L2:
+	print(2)
+end:
+}
+
+func UnstructuredSwitchInAForLoop(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: x == 1:int
+	// default: print("end":string)
+	// }
+	for {
+		if x == 1 {
+			print(1)
+			return
+		}
+		if x == 2 {
+			continue
+		}
+		break
+	}
+	print("end")
+}
+
+func CaseWithMultiplePreds(x int) {
+	for {
+		if x == 1 {
+			print(1)
+			return
+		}
+	loop:
+		// This block has multiple predecessors,
+		// so can't be treated as a switch case.
+		if x == 2 {
+			goto loop
+		}
+		break
+	}
+	print("end")
+}
+
+func DuplicateConstantsAreNotEliminated(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 1:int: print("1a":string)
+	// case 2:int: print(2:int)
+	// default: return
+	// }
+	if x == 1 {
+		print(1)
+	} else if x == 1 { // duplicate => unreachable
+		print("1a")
+	} else if x == 2 {
+		print(2)
+	}
+}
+
+// Interface values (created by comparisons) are not constants,
+// so ConstSwitch.X is never of interface type.
+func MakeInterfaceIsNotAConstant(x interface{}) {
+	if x == "foo" {
+		print("foo")
+	} else if x == 1 {
+		print(1)
+	}
+}
+
+func ZeroInitializedVarsAreConstants(x int) {
+	// switch x {
+	// case 0:int: print(1:int)
+	// case 2:int: print(2:int)
+	// default: print("end":string)
+	// }
+	var zero int // SSA construction replaces zero with 0
+	if x == zero {
+		print(1)
+	} else if x == 2 {
+		print(2)
+	}
+	print("end")
+}
+
+// -------- Select --------
+
+// NB, potentially fragile reliance on register number.
+func SelectDesugarsToSwitch(ch chan int) {
+	// switch t1 {
+	// case 0:int: extract t0 #2
+	// case 1:int: println(0:int)
+	// case 2:int: println(1:int)
+	// default: println("default":string)
+	// }
+	select {
+	case x := <-ch:
+		println(x)
+	case <-ch:
+		println(0)
+	case ch <- 1:
+		println(1)
+	default:
+		println("default")
+	}
+}
+
+// NB, potentially fragile reliance on register number.
+func NonblockingSelectDefaultCasePanics(ch chan int) {
+	// switch t1 {
+	// case 0:int: extract t0 #2
+	// case 1:int: println(0:int)
+	// case 2:int: println(1:int)
+	// default: make interface{} <- string ("blocking select m...":string)
+	// }
+	select {
+	case x := <-ch:
+		println(x)
+	case <-ch:
+		println(0)
+	case ch <- 1:
+		println(1)
+	}
+}
+
+// -------- Type switches --------
+
+// NB, reliance on fragile register numbering.
+func SimpleTypeSwitch(x interface{}) {
+	// switch x.(type) {
+	// case t3 int: println(x)
+	// case t7 bool: println(x)
+	// case t10 string: println(t10)
+	// default: println(x)
+	// }
+	switch y := x.(type) {
+	case nil:
+		println(y)
+	case int, bool:
+		println(y)
+	case string:
+		println(y)
+	default:
+		println(y)
+	}
+}
+
+// NB, potentially fragile reliance on register number.
+func DuplicateTypesAreNotEliminated(x interface{}) {
+	// switch x.(type) {
+	// case t1 string: println(1:int)
+	// case t5 interface{}: println(t5)
+	// case t9 int: println(3:int)
+	// default: return
+	// }
+	switch y := x.(type) {
+	case string:
+		println(1)
+	case interface{}:
+		println(y)
+	case int:
+		println(3) // unreachable!
+	}
+}
+
+// NB, potentially fragile reliance on register number.
+func AdHocTypeSwitch(x interface{}) {
+	// switch x.(type) {
+	// case t1 int: println(t1)
+	// case t5 string: println(t5)
+	// default: print("default":string)
+	// }
+	if i, ok := x.(int); ok {
+		println(i)
+	} else if s, ok := x.(string); ok {
+		println(s)
+	} else {
+		print("default")
+	}
+}
diff --git a/third_party/go.tools/go/ssa/ssautil/visit.go b/third_party/go.tools/go/ssa/ssautil/visit.go
new file mode 100644
index 0000000..01ad06c
--- /dev/null
+++ b/third_party/go.tools/go/ssa/ssautil/visit.go
@@ -0,0 +1,66 @@
+// Copyright 2013 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 ssautil
+
+import "llvm.org/llgo/third_party/go.tools/go/ssa"
+
+// This file defines utilities for visiting the SSA representation of
+// a Program.
+//
+// TODO(adonovan): test coverage.
+
+// AllFunctions finds and returns the set of functions potentially
+// needed by program prog, as determined by a simple linker-style
+// reachability algorithm starting from the members and method-sets of
+// each package.  The result may include anonymous functions and
+// synthetic wrappers.
+//
+// Precondition: all packages are built.
+//
+func AllFunctions(prog *ssa.Program) map[*ssa.Function]bool {
+	visit := visitor{
+		prog: prog,
+		seen: make(map[*ssa.Function]bool),
+	}
+	visit.program()
+	return visit.seen
+}
+
+type visitor struct {
+	prog *ssa.Program
+	seen map[*ssa.Function]bool
+}
+
+func (visit *visitor) program() {
+	for _, pkg := range visit.prog.AllPackages() {
+		for _, mem := range pkg.Members {
+			if fn, ok := mem.(*ssa.Function); ok {
+				visit.function(fn)
+			}
+		}
+	}
+	for _, T := range visit.prog.TypesWithMethodSets() {
+		mset := visit.prog.MethodSets.MethodSet(T)
+		for i, n := 0, mset.Len(); i < n; i++ {
+			visit.function(visit.prog.Method(mset.At(i)))
+		}
+	}
+}
+
+func (visit *visitor) function(fn *ssa.Function) {
+	if !visit.seen[fn] {
+		visit.seen[fn] = true
+		var buf [10]*ssa.Value // avoid alloc in common case
+		for _, b := range fn.Blocks {
+			for _, instr := range b.Instrs {
+				for _, op := range instr.Operands(buf[:0]) {
+					if fn, ok := (*op).(*ssa.Function); ok {
+						visit.function(fn)
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/third_party/go.tools/go/ssa/stdlib_test.go b/third_party/go.tools/go/ssa/stdlib_test.go
new file mode 100644
index 0000000..4bcf73b
--- /dev/null
+++ b/third_party/go.tools/go/ssa/stdlib_test.go
@@ -0,0 +1,130 @@
+// Copyright 2013 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 ssa_test
+
+// This file runs the SSA builder in sanity-checking mode on all
+// packages beneath $GOROOT and prints some summary information.
+//
+// Run with "go test -cpu=8 to" set GOMAXPROCS.
+
+import (
+	"go/build"
+	"go/token"
+	"runtime"
+	"testing"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/go/buildutil"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/ssa/ssautil"
+)
+
+func bytesAllocated() uint64 {
+	runtime.GC()
+	var stats runtime.MemStats
+	runtime.ReadMemStats(&stats)
+	return stats.Alloc
+}
+
+func TestStdlib(t *testing.T) {
+	// Load, parse and type-check the program.
+	t0 := time.Now()
+	alloc0 := bytesAllocated()
+
+	// Load, parse and type-check the program.
+	ctxt := build.Default // copy
+	ctxt.GOPATH = ""      // disable GOPATH
+	conf := loader.Config{
+		SourceImports: true,
+		Build:         &ctxt,
+	}
+	if _, err := conf.FromArgs(buildutil.AllPackages(conf.Build), true); err != nil {
+		t.Errorf("FromArgs failed: %v", err)
+		return
+	}
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+
+	t1 := time.Now()
+	alloc1 := bytesAllocated()
+
+	// Create SSA packages.
+	var mode ssa.BuilderMode
+	// Comment out these lines during benchmarking.  Approx SSA build costs are noted.
+	mode |= ssa.SanityCheckFunctions // + 2% space, + 4% time
+	mode |= ssa.GlobalDebug          // +30% space, +18% time
+	prog := ssa.Create(iprog, mode)
+
+	t2 := time.Now()
+
+	// Build SSA.
+	prog.BuildAll()
+
+	t3 := time.Now()
+	alloc3 := bytesAllocated()
+
+	numPkgs := len(prog.AllPackages())
+	if want := 140; numPkgs < want {
+		t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
+	}
+
+	// Keep iprog reachable until after we've measured memory usage.
+	if len(iprog.AllPackages) == 0 {
+		print() // unreachable
+	}
+
+	allFuncs := ssautil.AllFunctions(prog)
+
+	// Check that all non-synthetic functions have distinct names.
+	byName := make(map[string]*ssa.Function)
+	for fn := range allFuncs {
+		if fn.Synthetic == "" {
+			str := fn.String()
+			prev := byName[str]
+			byName[str] = fn
+			if prev != nil {
+				t.Errorf("%s: duplicate function named %s",
+					prog.Fset.Position(fn.Pos()), str)
+				t.Errorf("%s:   (previously defined here)",
+					prog.Fset.Position(prev.Pos()))
+			}
+		}
+	}
+
+	// Dump some statistics.
+	var numInstrs int
+	for fn := range allFuncs {
+		for _, b := range fn.Blocks {
+			numInstrs += len(b.Instrs)
+		}
+	}
+
+	// determine line count
+	var lineCount int
+	prog.Fset.Iterate(func(f *token.File) bool {
+		lineCount += f.LineCount()
+		return true
+	})
+
+	// NB: when benchmarking, don't forget to clear the debug +
+	// sanity builder flags for better performance.
+
+	t.Log("GOMAXPROCS:           ", runtime.GOMAXPROCS(0))
+	t.Log("#Source lines:        ", lineCount)
+	t.Log("Load/parse/typecheck: ", t1.Sub(t0))
+	t.Log("SSA create:           ", t2.Sub(t1))
+	t.Log("SSA build:            ", t3.Sub(t2))
+
+	// SSA stats:
+	t.Log("#Packages:            ", numPkgs)
+	t.Log("#Functions:           ", len(allFuncs))
+	t.Log("#Instructions:        ", numInstrs)
+	t.Log("#MB AST+types:        ", int64(alloc1-alloc0)/1e6)
+	t.Log("#MB SSA:              ", int64(alloc3-alloc1)/1e6)
+}
diff --git a/third_party/go.tools/go/ssa/testdata/objlookup.go b/third_party/go.tools/go/ssa/testdata/objlookup.go
new file mode 100644
index 0000000..bd266e4
--- /dev/null
+++ b/third_party/go.tools/go/ssa/testdata/objlookup.go
@@ -0,0 +1,160 @@
+//+build ignore
+
+package main
+
+// This file is the input to TestObjValueLookup in source_test.go,
+// which ensures that each occurrence of an ident defining or
+// referring to a func, var or const object can be mapped to its
+// corresponding SSA Value.
+//
+// For every reference to a var object, we use annotations in comments
+// to denote both the expected SSA Value kind, and whether to expect
+// its value (x) or its address (&x).
+//
+// For const and func objects, the results don't vary by reference and
+// are always values not addresses, so no annotations are needed.  The
+// declaration is enough.
+
+import "fmt"
+import "os"
+
+type J int
+
+func (*J) method() {}
+
+const globalConst = 0
+
+var globalVar int // &globalVar::Global
+
+func globalFunc() {}
+
+type I interface {
+	interfaceMethod()
+}
+
+type S struct {
+	x int // x::nil
+}
+
+func main() {
+	print(globalVar) // globalVar::UnOp
+	globalVar = 1    // globalVar::Const
+
+	var v0 int = 1 // v0::Const (simple local value spec)
+	if v0 > 0 {    // v0::Const
+		v0 = 2 // v0::Const
+	}
+	print(v0) // v0::Phi
+
+	// v1 is captured and thus implicitly address-taken.
+	var v1 int = 1         // v1::Const
+	v1 = 2                 // v1::Const
+	fmt.Println(v1)        // v1::UnOp (load)
+	f := func(param int) { // f::MakeClosure param::Parameter
+		if y := 1; y > 0 { // y::Const
+			print(v1, param) // v1::UnOp (load) param::Parameter
+		}
+		param = 2      // param::Const
+		println(param) // param::Const
+	}
+
+	f(0) // f::MakeClosure
+
+	var v2 int // v2::Const (implicitly zero-initialized local value spec)
+	print(v2)  // v2::Const
+
+	m := make(map[string]int) // m::MakeMap
+
+	// Local value spec with multi-valued RHS:
+	var v3, v4 = m[""] // v3::Extract v4::Extract m::MakeMap
+	print(v3)          // v3::Extract
+	print(v4)          // v4::Extract
+
+	v3++    // v3::BinOp (assign with op)
+	v3 += 2 // v3::BinOp (assign with op)
+
+	v5, v6 := false, "" // v5::Const v6::Const (defining assignment)
+	print(v5)           // v5::Const
+	print(v6)           // v6::Const
+
+	var v7 S    // &v7::Alloc
+	v7.x = 1    // &v7::Alloc &x::FieldAddr
+	print(v7.x) // &v7::Alloc &x::FieldAddr
+
+	var v8 [1]int // &v8::Alloc
+	v8[0] = 0     // &v8::Alloc
+	print(v8[:])  // &v8::Alloc
+	_ = v8[0]     // &v8::Alloc
+	_ = v8[:][0]  // &v8::Alloc
+	v8ptr := &v8  // v8ptr::Alloc &v8::Alloc
+	_ = v8ptr[0]  // v8ptr::Alloc
+	_ = *v8ptr    // v8ptr::Alloc
+
+	v8a := make([]int, 1) // v8a::MakeSlice
+	v8a[0] = 0            // v8a::MakeSlice
+	print(v8a[:])         // v8a::MakeSlice
+
+	v9 := S{} // &v9::Alloc
+
+	v10 := &v9 // v10::Alloc &v9::Alloc
+	_ = v10    // v10::Alloc
+
+	var v11 *J = nil // v11::Const
+	v11.method()     // v11::Const
+
+	var v12 J    // &v12::Alloc
+	v12.method() // &v12::Alloc (implicitly address-taken)
+
+	// NB, in the following, 'method' resolves to the *types.Func
+	// of (*J).method, so it doesn't help us locate the specific
+	// ssa.Values here: a bound-method closure and a promotion
+	// wrapper.
+	_ = v11.method            // v11::Const
+	_ = (*struct{ J }).method // J::nil
+
+	// These vars are not optimised away.
+	if false {
+		v13 := 0     // v13::Const
+		println(v13) // v13::Const
+	}
+
+	switch x := 1; x { // x::Const
+	case v0: // v0::Phi
+	}
+
+	for k, v := range m { // k::Extract v::Extract m::MakeMap
+		_ = k // k::Extract
+		v++   // v::BinOp
+	}
+
+	if y := 0; y > 1 { // y::Const y::Const
+	}
+
+	var i interface{}      // i::Const (nil interface)
+	i = 1                  // i::MakeInterface
+	switch i := i.(type) { // i::MakeInterface i::MakeInterface
+	case int:
+		println(i) // i::Extract
+	}
+
+	ch := make(chan int) // ch::MakeChan
+	select {
+	case x := <-ch: // x::UnOp (receive) ch::MakeChan
+		_ = x // x::UnOp
+	}
+
+	// .Op is an inter-package FieldVal-selection.
+	var err os.PathError // &err::Alloc
+	_ = err.Op           // &err::Alloc &Op::FieldAddr
+	_ = &err.Op          // &err::Alloc &Op::FieldAddr
+
+	// Exercise corner-cases of lvalues vs rvalues.
+	// (Guessing IsAddr from the 'pointerness' won't cut it here.)
+	type N *N
+	var n N    // n::Const
+	n1 := n    // n1::Const n::Const
+	n2 := &n1  // n2::Alloc &n1::Alloc
+	n3 := *n2  // n3::UnOp n2::Alloc
+	n4 := **n3 // n4::UnOp n3::UnOp
+	_ = n4     // n4::UnOp
+}
diff --git a/third_party/go.tools/go/ssa/testdata/valueforexpr.go b/third_party/go.tools/go/ssa/testdata/valueforexpr.go
new file mode 100644
index 0000000..70906ca
--- /dev/null
+++ b/third_party/go.tools/go/ssa/testdata/valueforexpr.go
@@ -0,0 +1,148 @@
+//+build ignore
+
+package main
+
+// This file is the input to TestValueForExpr in source_test.go, which
+// ensures that each expression e immediately following a /*@kind*/(x)
+// annotation, when passed to Function.ValueForExpr(e), returns a
+// non-nil Value of the same type as e and of kind 'kind'.
+
+func f(spilled, unspilled int) {
+	_ = /*@UnOp*/ (spilled)
+	_ = /*@Parameter*/ (unspilled)
+	_ = /*@<nil>*/ (1 + 2) // (constant)
+	i := 0
+	/*@Call*/ (print( /*@BinOp*/ (i + 1)))
+	ch := /*@MakeChan*/ (make(chan int))
+	/*@UnOp*/ (<-ch)
+	x := /*@UnOp*/ (<-ch)
+	_ = x
+	select {
+	case /*@Extract*/ (<-ch):
+	case x := /*@Extract*/ (<-ch):
+		_ = x
+	}
+	defer /*@Function*/ (func() {
+	})()
+	go /*@Function*/ (func() {
+	})()
+	y := 0
+	if true && /*@BinOp*/ (bool(y > 0)) {
+		y = 1
+	}
+	_ = /*@Phi*/ (y)
+	map1 := /*@MakeMap*/ (make(map[string]string))
+	_ = map1
+	_ = /*@MakeSlice*/ (make([]int, 0))
+	_ = /*@MakeClosure*/ (func() { print(spilled) })
+
+	sl := []int{}
+	_ = /*@Slice*/ (sl[:0])
+
+	_ = /*@<nil>*/ (new(int)) // optimized away
+	tmp := /*@Alloc*/ (new(int))
+	_ = tmp
+	var iface interface{}
+	_ = /*@TypeAssert*/ (iface.(int))
+	_ = /*@UnOp*/ (sl[0])
+	_ = /*@IndexAddr*/ (&sl[0])
+	_ = /*@Index*/ ([2]int{}[0])
+	var p *int
+	_ = /*@UnOp*/ (*p)
+
+	_ = /*@UnOp*/ (global)
+	/*@UnOp*/ (global)[""] = ""
+	/*@Global*/ (global) = map[string]string{}
+
+	var local t
+	/*UnOp*/ (local.x) = 1
+
+	// Exercise corner-cases of lvalues vs rvalues.
+	type N *N
+	var n N
+	/*@UnOp*/ (n) = /*@UnOp*/ (n)
+	/*@ChangeType*/ (n) = /*@Alloc*/ (&n)
+	/*@UnOp*/ (n) = /*@UnOp*/ (*n)
+	/*@UnOp*/ (n) = /*@UnOp*/ (**n)
+}
+
+func complit() {
+	// Composite literals.
+	// We get different results for
+	// - composite literal as value (e.g. operand to print)
+	// - composite literal initializer for addressable value
+	// - composite literal value assigned to blank var
+
+	// 1. Slices
+	print( /*@Slice*/ ([]int{}))
+	print( /*@Alloc*/ (&[]int{}))
+	print(& /*@Alloc*/ ([]int{}))
+
+	sl1 := /*@Slice*/ ([]int{})
+	sl2 := /*@Alloc*/ (&[]int{})
+	sl3 := & /*@Alloc*/ ([]int{})
+	_, _, _ = sl1, sl2, sl3
+
+	_ = /*@Slice*/ ([]int{})
+	_ = /*@<nil>*/ (& /*@Slice*/ ([]int{})) // & optimized away
+	_ = & /*@Slice*/ ([]int{})
+
+	// 2. Arrays
+	print( /*@UnOp*/ ([1]int{}))
+	print( /*@Alloc*/ (&[1]int{}))
+	print(& /*@Alloc*/ ([1]int{}))
+
+	arr1 := /*@Alloc*/ ([1]int{})
+	arr2 := /*@Alloc*/ (&[1]int{})
+	arr3 := & /*@Alloc*/ ([1]int{})
+	_, _, _ = arr1, arr2, arr3
+
+	_ = /*@UnOp*/ ([1]int{})
+	_ = /*@Alloc*/ (& /*@Alloc*/ ([1]int{})) // & optimized away
+	_ = & /*@Alloc*/ ([1]int{})
+
+	// 3. Maps
+	type M map[int]int
+	print( /*@MakeMap*/ (M{}))
+	print( /*@Alloc*/ (&M{}))
+	print(& /*@Alloc*/ (M{}))
+
+	m1 := /*@MakeMap*/ (M{})
+	m2 := /*@Alloc*/ (&M{})
+	m3 := & /*@Alloc*/ (M{})
+	_, _, _ = m1, m2, m3
+
+	_ = /*@MakeMap*/ (M{})
+	_ = /*@<nil>*/ (& /*@MakeMap*/ (M{})) // & optimized away
+	_ = & /*@MakeMap*/ (M{})
+
+	// 4. Structs
+	print( /*@UnOp*/ (struct{}{}))
+	print( /*@Alloc*/ (&struct{}{}))
+	print(& /*@Alloc*/ (struct{}{}))
+
+	s1 := /*@Alloc*/ (struct{}{})
+	s2 := /*@Alloc*/ (&struct{}{})
+	s3 := & /*@Alloc*/ (struct{}{})
+	_, _, _ = s1, s2, s3
+
+	_ = /*@UnOp*/ (struct{}{})
+	_ = /*@Alloc*/ (& /*@Alloc*/ (struct{}{}))
+	_ = & /*@Alloc*/ (struct{}{})
+}
+
+type t struct{ x int }
+
+// Ensure we can locate methods of named types.
+func (t) f(param int) {
+	_ = /*@Parameter*/ (param)
+}
+
+// Ensure we can locate init functions.
+func init() {
+	m := /*@MakeMap*/ (make(map[string]string))
+	_ = m
+}
+
+// Ensure we can locate variables in initializer expressions.
+var global = /*@MakeMap*/ (make(map[string]string))
diff --git a/third_party/go.tools/go/ssa/testmain.go b/third_party/go.tools/go/ssa/testmain.go
new file mode 100644
index 0000000..e19c27f
--- /dev/null
+++ b/third_party/go.tools/go/ssa/testmain.go
@@ -0,0 +1,286 @@
+// Copyright 2013 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 ssa
+
+// CreateTestMainPackage synthesizes a main package that runs all the
+// tests of the supplied packages.
+// It is closely coupled to $GOROOT/src/cmd/go/test.go and $GOROOT/src/testing.
+
+import (
+	"go/ast"
+	"go/token"
+	"os"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// FindTests returns the list of packages that define at least one Test,
+// Example or Benchmark function (as defined by "go test"), and the
+// lists of all such functions.
+//
+func FindTests(pkgs []*Package) (testpkgs []*Package, tests, benchmarks, examples []*Function) {
+	if len(pkgs) == 0 {
+		return
+	}
+	prog := pkgs[0].Prog
+
+	// The first two of these may be nil: if the program doesn't import "testing",
+	// it can't contain any tests, but it may yet contain Examples.
+	var testSig *types.Signature                                   // func(*testing.T)
+	var benchmarkSig *types.Signature                              // func(*testing.B)
+	var exampleSig = types.NewSignature(nil, nil, nil, nil, false) // func()
+
+	// Obtain the types from the parameters of testing.Main().
+	if testingPkg := prog.ImportedPackage("testing"); testingPkg != nil {
+		params := testingPkg.Func("Main").Signature.Params()
+		testSig = funcField(params.At(1).Type())
+		benchmarkSig = funcField(params.At(2).Type())
+	}
+
+	seen := make(map[*Package]bool)
+	for _, pkg := range pkgs {
+		if pkg.Prog != prog {
+			panic("wrong Program")
+		}
+
+		// TODO(adonovan): use a stable order, e.g. lexical.
+		for _, mem := range pkg.Members {
+			if f, ok := mem.(*Function); ok &&
+				ast.IsExported(f.Name()) &&
+				strings.HasSuffix(prog.Fset.Position(f.Pos()).Filename, "_test.go") {
+
+				switch {
+				case testSig != nil && isTestSig(f, "Test", testSig):
+					tests = append(tests, f)
+				case benchmarkSig != nil && isTestSig(f, "Benchmark", benchmarkSig):
+					benchmarks = append(benchmarks, f)
+				case isTestSig(f, "Example", exampleSig):
+					examples = append(examples, f)
+				default:
+					continue
+				}
+
+				if !seen[pkg] {
+					seen[pkg] = true
+					testpkgs = append(testpkgs, pkg)
+				}
+			}
+		}
+	}
+	return
+}
+
+// Like isTest, but checks the signature too.
+func isTestSig(f *Function, prefix string, sig *types.Signature) bool {
+	return isTest(f.Name(), prefix) && types.Identical(f.Signature, sig)
+}
+
+// If non-nil, testMainStartBodyHook is called immediately after
+// startBody for main.init and main.main, making it easy for users to
+// add custom imports and initialization steps for proprietary build
+// systems that don't exactly follow 'go test' conventions.
+var testMainStartBodyHook func(*Function)
+
+// CreateTestMainPackage creates and returns a synthetic "main"
+// package that runs all the tests of the supplied packages, similar
+// to the one that would be created by the 'go test' tool.
+//
+// It returns nil if the program contains no tests.
+//
+func (prog *Program) CreateTestMainPackage(pkgs ...*Package) *Package {
+	pkgs, tests, benchmarks, examples := FindTests(pkgs)
+	if len(pkgs) == 0 {
+		return nil
+	}
+
+	testmain := &Package{
+		Prog:    prog,
+		Members: make(map[string]Member),
+		values:  make(map[types.Object]Value),
+		Object:  types.NewPackage("testmain", "testmain"),
+	}
+
+	// Build package's init function.
+	init := &Function{
+		name:      "init",
+		Signature: new(types.Signature),
+		Synthetic: "package initializer",
+		Pkg:       testmain,
+		Prog:      prog,
+	}
+	init.startBody()
+
+	if testMainStartBodyHook != nil {
+		testMainStartBodyHook(init)
+	}
+
+	// Initialize packages to test.
+	for _, pkg := range pkgs {
+		var v Call
+		v.Call.Value = pkg.init
+		v.setType(types.NewTuple())
+		init.emit(&v)
+	}
+	init.emit(new(Return))
+	init.finishBody()
+	testmain.init = init
+	testmain.Object.MarkComplete()
+	testmain.Members[init.name] = init
+
+	main := &Function{
+		name:      "main",
+		Signature: new(types.Signature),
+		Synthetic: "test main function",
+		Prog:      prog,
+		Pkg:       testmain,
+	}
+
+	main.startBody()
+
+	if testMainStartBodyHook != nil {
+		testMainStartBodyHook(main)
+	}
+
+	if testingPkg := prog.ImportedPackage("testing"); testingPkg != nil {
+		testingMain := testingPkg.Func("Main")
+		testingMainParams := testingMain.Signature.Params()
+
+		// The generated code is as if compiled from this:
+		//
+		// func main() {
+		//      match      := func(_, _ string) (bool, error) { return true, nil }
+		//      tests      := []testing.InternalTest{{"TestFoo", TestFoo}, ...}
+		//      benchmarks := []testing.InternalBenchmark{...}
+		//      examples   := []testing.InternalExample{...}
+		// 	testing.Main(match, tests, benchmarks, examples)
+		// }
+
+		matcher := &Function{
+			name:      "matcher",
+			Signature: testingMainParams.At(0).Type().(*types.Signature),
+			Synthetic: "test matcher predicate",
+			parent:    main,
+			Pkg:       testmain,
+			Prog:      prog,
+		}
+		main.AnonFuncs = append(main.AnonFuncs, matcher)
+		matcher.startBody()
+		matcher.emit(&Return{Results: []Value{vTrue, nilConst(types.Universe.Lookup("error").Type())}})
+		matcher.finishBody()
+
+		// Emit call: testing.Main(matcher, tests, benchmarks, examples).
+		var c Call
+		c.Call.Value = testingMain
+		c.Call.Args = []Value{
+			matcher,
+			testMainSlice(main, tests, testingMainParams.At(1).Type()),
+			testMainSlice(main, benchmarks, testingMainParams.At(2).Type()),
+			testMainSlice(main, examples, testingMainParams.At(3).Type()),
+		}
+		emitTailCall(main, &c)
+	} else {
+		// The program does not import "testing", but FindTests
+		// returned non-nil, which must mean there were Examples
+		// but no Tests or Benchmarks.
+		// We'll simply call them from testmain.main; this will
+		// ensure they don't panic, but will not check any
+		// "Output:" comments.
+		for _, eg := range examples {
+			var c Call
+			c.Call.Value = eg
+			c.setType(types.NewTuple())
+			main.emit(&c)
+		}
+		main.emit(&Return{})
+		main.currentBlock = nil
+	}
+
+	main.finishBody()
+
+	testmain.Members["main"] = main
+
+	if prog.mode&PrintPackages != 0 {
+		printMu.Lock()
+		testmain.WriteTo(os.Stdout)
+		printMu.Unlock()
+	}
+
+	if prog.mode&SanityCheckFunctions != 0 {
+		sanityCheckPackage(testmain)
+	}
+
+	prog.packages[testmain.Object] = testmain
+
+	return testmain
+}
+
+// testMainSlice emits to fn code to construct a slice of type slice
+// (one of []testing.Internal{Test,Benchmark,Example}) for all
+// functions in testfuncs.  It returns the slice value.
+//
+func testMainSlice(fn *Function, testfuncs []*Function, slice types.Type) Value {
+	if testfuncs == nil {
+		return nilConst(slice)
+	}
+
+	tElem := slice.(*types.Slice).Elem()
+	tPtrString := types.NewPointer(tString)
+	tPtrElem := types.NewPointer(tElem)
+	tPtrFunc := types.NewPointer(funcField(slice))
+
+	// Emit: array = new [n]testing.InternalTest
+	tArray := types.NewArray(tElem, int64(len(testfuncs)))
+	array := emitNew(fn, tArray, token.NoPos)
+	array.Comment = "test main"
+	for i, testfunc := range testfuncs {
+		// Emit: pitem = &array[i]
+		ia := &IndexAddr{X: array, Index: intConst(int64(i))}
+		ia.setType(tPtrElem)
+		pitem := fn.emit(ia)
+
+		// Emit: pname = &pitem.Name
+		fa := &FieldAddr{X: pitem, Field: 0} // .Name
+		fa.setType(tPtrString)
+		pname := fn.emit(fa)
+
+		// Emit: *pname = "testfunc"
+		emitStore(fn, pname, stringConst(testfunc.Name()))
+
+		// Emit: pfunc = &pitem.F
+		fa = &FieldAddr{X: pitem, Field: 1} // .F
+		fa.setType(tPtrFunc)
+		pfunc := fn.emit(fa)
+
+		// Emit: *pfunc = testfunc
+		emitStore(fn, pfunc, testfunc)
+	}
+
+	// Emit: slice array[:]
+	sl := &Slice{X: array}
+	sl.setType(slice)
+	return fn.emit(sl)
+}
+
+// Given the type of one of the three slice parameters of testing.Main,
+// returns the function type.
+func funcField(slice types.Type) *types.Signature {
+	return slice.(*types.Slice).Elem().Underlying().(*types.Struct).Field(1).Type().(*types.Signature)
+}
+
+// Plundered from $GOROOT/src/cmd/go/test.go
+
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
+// We don't want TesticularCancer.
+func isTest(name, prefix string) bool {
+	if !strings.HasPrefix(name, prefix) {
+		return false
+	}
+	if len(name) == len(prefix) { // "Test" is ok
+		return true
+	}
+	return ast.IsExported(name[len(prefix):])
+}
diff --git a/third_party/go.tools/go/ssa/testmain_test.go b/third_party/go.tools/go/ssa/testmain_test.go
new file mode 100644
index 0000000..41b1df6
--- /dev/null
+++ b/third_party/go.tools/go/ssa/testmain_test.go
@@ -0,0 +1,122 @@
+// Copyright 2014 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 ssa_test
+
+// Tests of FindTests.  CreateTestMainPackage is tested via the interpreter.
+// TODO(adonovan): test the 'pkgs' result from FindTests.
+
+import (
+	"fmt"
+	"sort"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+)
+
+func create(t *testing.T, content string) []*ssa.Package {
+	var conf loader.Config
+	f, err := conf.ParseFile("foo_test.go", content)
+	if err != nil {
+		t.Fatal(err)
+	}
+	conf.CreateFromFiles("foo", f)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// We needn't call Build.
+	return ssa.Create(iprog, ssa.SanityCheckFunctions).AllPackages()
+}
+
+func TestFindTests(t *testing.T) {
+	test := `
+package foo
+
+import "testing"
+
+type T int
+
+// Tests:
+func Test(t *testing.T) {}
+func TestA(t *testing.T) {}
+func TestB(t *testing.T) {}
+
+// Not tests:
+func testC(t *testing.T) {}
+func TestD() {}
+func testE(t *testing.T) int { return 0 }
+func (T) Test(t *testing.T) {}
+
+// Benchmarks:
+func Benchmark(*testing.B) {}
+func BenchmarkA(b *testing.B) {}
+func BenchmarkB(*testing.B) {}
+
+// Not benchmarks:
+func benchmarkC(t *testing.T) {}
+func BenchmarkD() {}
+func benchmarkE(t *testing.T) int { return 0 }
+func (T) Benchmark(t *testing.T) {}
+
+// Examples:
+func Example() {}
+func ExampleA() {}
+
+// Not examples:
+func exampleC() {}
+func ExampleD(t *testing.T) {}
+func exampleE() int { return 0 }
+func (T) Example() {}
+`
+	pkgs := create(t, test)
+	_, tests, benchmarks, examples := ssa.FindTests(pkgs)
+
+	sort.Sort(funcsByPos(tests))
+	if got, want := fmt.Sprint(tests), "[foo.Test foo.TestA foo.TestB]"; got != want {
+		t.Errorf("FindTests.tests = %s, want %s", got, want)
+	}
+
+	sort.Sort(funcsByPos(benchmarks))
+	if got, want := fmt.Sprint(benchmarks), "[foo.Benchmark foo.BenchmarkA foo.BenchmarkB]"; got != want {
+		t.Errorf("FindTests.benchmarks = %s, want %s", got, want)
+	}
+
+	sort.Sort(funcsByPos(examples))
+	if got, want := fmt.Sprint(examples), "[foo.Example foo.ExampleA]"; got != want {
+		t.Errorf("FindTests examples = %s, want %s", got, want)
+	}
+}
+
+func TestFindTestsTesting(t *testing.T) {
+	test := `
+package foo
+
+// foo does not import "testing", but defines Examples.
+
+func Example() {}
+func ExampleA() {}
+`
+	pkgs := create(t, test)
+	_, tests, benchmarks, examples := ssa.FindTests(pkgs)
+	if len(tests) > 0 {
+		t.Errorf("FindTests.tests = %s, want none", tests)
+	}
+	if len(benchmarks) > 0 {
+		t.Errorf("FindTests.benchmarks = %s, want none", benchmarks)
+	}
+	sort.Sort(funcsByPos(examples))
+	if got, want := fmt.Sprint(examples), "[foo.Example foo.ExampleA]"; got != want {
+		t.Errorf("FindTests examples = %s, want %s", got, want)
+	}
+}
+
+type funcsByPos []*ssa.Function
+
+func (p funcsByPos) Len() int           { return len(p) }
+func (p funcsByPos) Less(i, j int) bool { return p[i].Pos() < p[j].Pos() }
+func (p funcsByPos) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
diff --git a/third_party/go.tools/go/ssa/util.go b/third_party/go.tools/go/ssa/util.go
new file mode 100644
index 0000000..d74fa29
--- /dev/null
+++ b/third_party/go.tools/go/ssa/util.go
@@ -0,0 +1,136 @@
+// Copyright 2013 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 ssa
+
+// This file defines a number of miscellaneous utility functions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"os"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func unreachable() {
+	panic("unreachable")
+}
+
+//// AST utilities
+
+// unparen returns e with any enclosing parentheses stripped.
+func unparen(e ast.Expr) ast.Expr {
+	for {
+		p, ok := e.(*ast.ParenExpr)
+		if !ok {
+			break
+		}
+		e = p.X
+	}
+	return e
+}
+
+// isBlankIdent returns true iff e is an Ident with name "_".
+// They have no associated types.Object, and thus no type.
+//
+func isBlankIdent(e ast.Expr) bool {
+	id, ok := e.(*ast.Ident)
+	return ok && id.Name == "_"
+}
+
+//// Type utilities.  Some of these belong in go/types.
+
+// isPointer returns true for types whose underlying type is a pointer.
+func isPointer(typ types.Type) bool {
+	_, ok := typ.Underlying().(*types.Pointer)
+	return ok
+}
+
+// isInterface reports whether T's underlying type is an interface.
+func isInterface(T types.Type) bool {
+	_, ok := T.Underlying().(*types.Interface)
+	return ok
+}
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// recvType returns the receiver type of method obj.
+func recvType(obj *types.Func) types.Type {
+	return obj.Type().(*types.Signature).Recv().Type()
+}
+
+// DefaultType returns the default "typed" type for an "untyped" type;
+// it returns the incoming type for all other types.  The default type
+// for untyped nil is untyped nil.
+//
+// Exported to ssa/interp.
+//
+// TODO(gri): this is a copy of go/types.defaultType; export that function.
+//
+func DefaultType(typ types.Type) types.Type {
+	if t, ok := typ.(*types.Basic); ok {
+		k := t.Kind()
+		switch k {
+		case types.UntypedBool:
+			k = types.Bool
+		case types.UntypedInt:
+			k = types.Int
+		case types.UntypedRune:
+			k = types.Rune
+		case types.UntypedFloat:
+			k = types.Float64
+		case types.UntypedComplex:
+			k = types.Complex128
+		case types.UntypedString:
+			k = types.String
+		}
+		typ = types.Typ[k]
+	}
+	return typ
+}
+
+// logStack prints the formatted "start" message to stderr and
+// returns a closure that prints the corresponding "end" message.
+// Call using 'defer logStack(...)()' to show builder stack on panic.
+// Don't forget trailing parens!
+//
+func logStack(format string, args ...interface{}) func() {
+	msg := fmt.Sprintf(format, args...)
+	io.WriteString(os.Stderr, msg)
+	io.WriteString(os.Stderr, "\n")
+	return func() {
+		io.WriteString(os.Stderr, msg)
+		io.WriteString(os.Stderr, " end\n")
+	}
+}
+
+// newVar creates a 'var' for use in a types.Tuple.
+func newVar(name string, typ types.Type) *types.Var {
+	return types.NewParam(token.NoPos, nil, name, typ)
+}
+
+// anonVar creates an anonymous 'var' for use in a types.Tuple.
+func anonVar(typ types.Type) *types.Var {
+	return newVar("", typ)
+}
+
+var lenResults = types.NewTuple(anonVar(tInt))
+
+// makeLen returns the len builtin specialized to type func(T)int.
+func makeLen(T types.Type) *Builtin {
+	lenParams := types.NewTuple(anonVar(T))
+	return &Builtin{
+		name: "len",
+		sig:  types.NewSignature(nil, nil, lenParams, lenResults, false),
+	}
+}
diff --git a/third_party/go.tools/go/ssa/wrappers.go b/third_party/go.tools/go/ssa/wrappers.go
new file mode 100644
index 0000000..09813be
--- /dev/null
+++ b/third_party/go.tools/go/ssa/wrappers.go
@@ -0,0 +1,287 @@
+// Copyright 2013 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 ssa
+
+// This file defines synthesis of Functions that delegate to declared
+// methods, which come in three kinds:
+//
+// (1) wrappers: methods that wrap declared methods, performing
+//     implicit pointer indirections and embedded field selections.
+//
+// (2) thunks: funcs that wrap declared methods.  Like wrappers,
+//     thunks perform indirections and field selections. The thunks's
+//     first parameter is used as the receiver for the method call.
+//
+// (3) bounds: funcs that wrap declared methods.  The bound's sole
+//     free variable, supplied by a closure, is used as the receiver
+//     for the method call.  No indirections or field selections are
+//     performed since they can be done before the call.
+
+import (
+	"fmt"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// -- wrappers -----------------------------------------------------------
+
+// makeWrapper returns a synthetic method that delegates to the
+// declared method denoted by meth.Obj(), first performing any
+// necessary pointer indirections or field selections implied by meth.
+//
+// The resulting method's receiver type is meth.Recv().
+//
+// This function is versatile but quite subtle!  Consider the
+// following axes of variation when making changes:
+//   - optional receiver indirection
+//   - optional implicit field selections
+//   - meth.Obj() may denote a concrete or an interface method
+//   - the result may be a thunk or a wrapper.
+//
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+//
+func makeWrapper(prog *Program, sel *types.Selection) *Function {
+	obj := sel.Obj().(*types.Func)       // the declared function
+	sig := sel.Type().(*types.Signature) // type of this wrapper
+
+	var recv *types.Var // wrapper's receiver or thunk's params[0]
+	name := obj.Name()
+	var description string
+	var start int // first regular param
+	if sel.Kind() == types.MethodExpr {
+		name += "$thunk"
+		description = "thunk"
+		recv = sig.Params().At(0)
+		start = 1
+	} else {
+		description = "wrapper"
+		recv = sig.Recv()
+	}
+
+	description = fmt.Sprintf("%s for %s", description, sel.Obj())
+	if prog.mode&LogSource != 0 {
+		defer logStack("make %s to (%s)", description, recv.Type())()
+	}
+	fn := &Function{
+		name:      name,
+		method:    sel,
+		object:    obj,
+		Signature: sig,
+		Synthetic: description,
+		Prog:      prog,
+		pos:       obj.Pos(),
+	}
+	fn.startBody()
+	fn.addSpilledParam(recv)
+	createParams(fn, start)
+
+	indices := sel.Index()
+
+	var v Value = fn.Locals[0] // spilled receiver
+	if isPointer(sel.Recv()) {
+		v = emitLoad(fn, v)
+
+		// For simple indirection wrappers, perform an informative nil-check:
+		// "value method (T).f called using nil *T pointer"
+		if len(indices) == 1 && !isPointer(recvType(obj)) {
+			var c Call
+			c.Call.Value = &Builtin{
+				name: "ssa:wrapnilchk",
+				sig: types.NewSignature(nil, nil,
+					types.NewTuple(anonVar(sel.Recv()), anonVar(tString), anonVar(tString)),
+					types.NewTuple(anonVar(sel.Recv())), false),
+			}
+			c.Call.Args = []Value{
+				v,
+				stringConst(deref(sel.Recv()).String()),
+				stringConst(sel.Obj().Name()),
+			}
+			c.setType(v.Type())
+			v = fn.emit(&c)
+		}
+	}
+
+	// Invariant: v is a pointer, either
+	//   value of *A receiver param, or
+	// address of  A spilled receiver.
+
+	// We use pointer arithmetic (FieldAddr possibly followed by
+	// Load) in preference to value extraction (Field possibly
+	// preceded by Load).
+
+	v = emitImplicitSelections(fn, v, indices[:len(indices)-1])
+
+	// Invariant: v is a pointer, either
+	//   value of implicit *C field, or
+	// address of implicit  C field.
+
+	var c Call
+	if r := recvType(obj); !isInterface(r) { // concrete method
+		if !isPointer(r) {
+			v = emitLoad(fn, v)
+		}
+		c.Call.Value = prog.declaredFunc(obj)
+		c.Call.Args = append(c.Call.Args, v)
+	} else {
+		c.Call.Method = obj
+		c.Call.Value = emitLoad(fn, v)
+	}
+	for _, arg := range fn.Params[1:] {
+		c.Call.Args = append(c.Call.Args, arg)
+	}
+	emitTailCall(fn, &c)
+	fn.finishBody()
+	return fn
+}
+
+// createParams creates parameters for wrapper method fn based on its
+// Signature.Params, which do not include the receiver.
+// start is the index of the first regular parameter to use.
+//
+func createParams(fn *Function, start int) {
+	var last *Parameter
+	tparams := fn.Signature.Params()
+	for i, n := start, tparams.Len(); i < n; i++ {
+		last = fn.addParamObj(tparams.At(i))
+	}
+	if fn.Signature.Variadic() {
+		last.typ = types.NewSlice(last.typ)
+	}
+}
+
+// -- bounds -----------------------------------------------------------
+
+// makeBound returns a bound method wrapper (or "bound"), a synthetic
+// function that delegates to a concrete or interface method denoted
+// by obj.  The resulting function has no receiver, but has one free
+// variable which will be used as the method's receiver in the
+// tail-call.
+//
+// Use MakeClosure with such a wrapper to construct a bound method
+// closure.  e.g.:
+//
+//   type T int          or:  type T interface { meth() }
+//   func (t T) meth()
+//   var t T
+//   f := t.meth
+//   f() // calls t.meth()
+//
+// f is a closure of a synthetic wrapper defined as if by:
+//
+//   f := func() { return t.meth() }
+//
+// Unlike makeWrapper, makeBound need perform no indirection or field
+// selections because that can be done before the closure is
+// constructed.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(meth.Prog.methodsMu)
+//
+func makeBound(prog *Program, obj *types.Func) *Function {
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+	fn, ok := prog.bounds[obj]
+	if !ok {
+		description := fmt.Sprintf("bound method wrapper for %s", obj)
+		if prog.mode&LogSource != 0 {
+			defer logStack("%s", description)()
+		}
+		fn = &Function{
+			name:      obj.Name() + "$bound",
+			object:    obj,
+			Signature: changeRecv(obj.Type().(*types.Signature), nil), // drop receiver
+			Synthetic: description,
+			Prog:      prog,
+			pos:       obj.Pos(),
+		}
+
+		fv := &FreeVar{name: "recv", typ: recvType(obj), parent: fn}
+		fn.FreeVars = []*FreeVar{fv}
+		fn.startBody()
+		createParams(fn, 0)
+		var c Call
+
+		if !isInterface(recvType(obj)) { // concrete
+			c.Call.Value = prog.declaredFunc(obj)
+			c.Call.Args = []Value{fv}
+		} else {
+			c.Call.Value = fv
+			c.Call.Method = obj
+		}
+		for _, arg := range fn.Params {
+			c.Call.Args = append(c.Call.Args, arg)
+		}
+		emitTailCall(fn, &c)
+		fn.finishBody()
+
+		prog.bounds[obj] = fn
+	}
+	return fn
+}
+
+// -- thunks -----------------------------------------------------------
+
+// makeThunk returns a thunk, a synthetic function that delegates to a
+// concrete or interface method denoted by sel.Obj().  The resulting
+// function has no receiver, but has an additional (first) regular
+// parameter.
+//
+// Precondition: sel.Kind() == types.MethodExpr.
+//
+//   type T int          or:  type T interface { meth() }
+//   func (t T) meth()
+//   f := T.meth
+//   var t T
+//   f(t) // calls t.meth()
+//
+// f is a synthetic wrapper defined as if by:
+//
+//   f := func(t T) { return t.meth() }
+//
+// TODO(adonovan): opt: currently the stub is created even when used
+// directly in a function call: C.f(i, 0).  This is less efficient
+// than inlining the stub.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(meth.Prog.methodsMu)
+//
+func makeThunk(prog *Program, sel *types.Selection) *Function {
+	if sel.Kind() != types.MethodExpr {
+		panic(sel)
+	}
+
+	// TODO(adonovan): opt: canonicalize the recv Type to avoid
+	// construct unnecessary duplicate thunks.
+	key := selectionKey{
+		kind:     sel.Kind(),
+		recv:     sel.Recv(),
+		obj:      sel.Obj(),
+		index:    fmt.Sprint(sel.Index()),
+		indirect: sel.Indirect(),
+	}
+
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+	fn, ok := prog.thunks[key]
+	if !ok {
+		fn = makeWrapper(prog, sel)
+		if fn.Signature.Recv() != nil {
+			panic(fn) // unexpected receiver
+		}
+		prog.thunks[key] = fn
+	}
+	return fn
+}
+
+func changeRecv(s *types.Signature, recv *types.Var) *types.Signature {
+	return types.NewSignature(nil, recv, s.Params(), s.Results(), s.Variadic())
+}
+
+// selectionKey is like types.Selection but a usable map key.
+type selectionKey struct {
+	kind     types.SelectionKind
+	recv     types.Type
+	obj      types.Object
+	index    string
+	indirect bool
+}
diff --git a/third_party/go.tools/go/types/api.go b/third_party/go.tools/go/types/api.go
new file mode 100644
index 0000000..9ae6502
--- /dev/null
+++ b/third_party/go.tools/go/types/api.go
@@ -0,0 +1,361 @@
+// 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 types declares the data types and implements
+// the algorithms for type-checking of Go packages.
+// Use Check and Config.Check to invoke the type-checker.
+//
+// Type-checking consists of several interdependent phases:
+//
+// Name resolution maps each identifier (ast.Ident) in the program to the
+// language object (Object) it denotes.
+// Use Info.{Defs,Uses,Implicits} for the results of name resolution.
+//
+// Constant folding computes the exact constant value (exact.Value) for
+// every expression (ast.Expr) that is a compile-time constant.
+// Use Info.Types[expr].Value for the results of constant folding.
+//
+// Type inference computes the type (Type) of every expression (ast.Expr)
+// and checks for compliance with the language specification.
+// Use Info.Types[expr].Type for the results of type inference.
+//
+package types
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+// Check type-checks a package and returns the resulting complete package
+// object, or a nil package and the first error. The package is specified
+// by a list of *ast.Files and corresponding file set, and the import path
+// the package is identified with. The clean path must not be empty or dot (".").
+//
+// For more control over type-checking and results, use Config.Check.
+func Check(path string, fset *token.FileSet, files []*ast.File) (*Package, error) {
+	var conf Config
+	pkg, err := conf.Check(path, fset, files, nil)
+	if err != nil {
+		return nil, err
+	}
+	return pkg, nil
+}
+
+// An Error describes a type-checking error; it implements the error interface.
+// A "soft" error is an error that still permits a valid interpretation of a
+// package (such as "unused variable"); "hard" errors may lead to unpredictable
+// behavior if ignored.
+type Error struct {
+	Fset *token.FileSet // file set for interpretation of Pos
+	Pos  token.Pos      // error position
+	Msg  string         // error message
+	Soft bool           // if set, error is "soft"
+}
+
+// Error returns an error string formatted as follows:
+// filename:line:column: message
+func (err Error) Error() string {
+	return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg)
+}
+
+// An importer resolves import paths to Packages.
+// The imports map records packages already known,
+// indexed by package path. The type-checker
+// will invoke Import with Config.Packages.
+// An importer must determine the canonical package path and
+// check imports to see if it is already present in the map.
+// If so, the Importer can return the map entry.  Otherwise,
+// the importer must load the package data for the given path
+// into a new *Package, record it in imports map, and return
+// the package.
+// TODO(gri) Need to be clearer about requirements of completeness.
+type Importer func(map[string]*Package, string) (*Package, error)
+
+// A Config specifies the configuration for type checking.
+// The zero value for Config is a ready-to-use default configuration.
+type Config struct {
+	// If IgnoreFuncBodies is set, function bodies are not
+	// type-checked.
+	IgnoreFuncBodies bool
+
+	// If FakeImportC is set, `import "C"` (for packages requiring Cgo)
+	// declares an empty "C" package and errors are omitted for qualified
+	// identifiers referring to package C (which won't find an object).
+	// This feature is intended for the standard library cmd/api tool.
+	//
+	// Caution: Effects may be unpredictable due to follow-up errors.
+	//          Do not use casually!
+	FakeImportC bool
+
+	// Packages is used to look up (and thus canonicalize) packages by
+	// package path. If Packages is nil, it is set to a new empty map.
+	// During type-checking, imported packages are added to the map.
+	Packages map[string]*Package
+
+	// If Error != nil, it is called with each error found
+	// during type checking; err has dynamic type Error.
+	// Secondary errors (for instance, to enumerate all types
+	// involved in an invalid recursive type declaration) have
+	// error strings that start with a '\t' character.
+	// If Error == nil, type-checking stops with the first
+	// error found.
+	Error func(err error)
+
+	// If Import != nil, it is called for each imported package.
+	// Otherwise, DefaultImport is called.
+	Import Importer
+
+	// If Sizes != nil, it provides the sizing functions for package unsafe.
+	// Otherwise &StdSizes{WordSize: 8, MaxAlign: 8} is used instead.
+	Sizes Sizes
+}
+
+// DefaultImport is the default importer invoked if Config.Import == nil.
+// The declaration:
+//
+//	import _ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+//
+// in a client of go/types will initialize DefaultImport to gcimporter.Import.
+var DefaultImport Importer
+
+// Info holds result type information for a type-checked package.
+// Only the information for which a map is provided is collected.
+// If the package has type errors, the collected information may
+// be incomplete.
+type Info struct {
+	// Types maps expressions to their types, and for constant
+	// expressions, their values. Invalid expressions are omitted.
+	//
+	// For (possibly parenthesized) identifiers denoting built-in
+	// functions, the recorded signatures are call-site specific:
+	// if the call result is not a constant, the recorded type is
+	// an argument-specific signature. Otherwise, the recorded type
+	// is invalid.
+	//
+	// Identifiers on the lhs of declarations (i.e., the identifiers
+	// which are being declared) are collected in the Defs map.
+	// Identifiers denoting packages are collected in the Uses maps.
+	Types map[ast.Expr]TypeAndValue
+
+	// Defs maps identifiers to the objects they define (including
+	// package names, dots "." of dot-imports, and blank "_" identifiers).
+	// For identifiers that do not denote objects (e.g., the package name
+	// in package clauses, or symbolic variables t in t := x.(type) of
+	// type switch headers), the corresponding objects are nil.
+	//
+	// For an anonymous field, Defs returns the field *Var it defines.
+	//
+	// Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
+	Defs map[*ast.Ident]Object
+
+	// Uses maps identifiers to the objects they denote.
+	//
+	// For an anonymous field, Uses returns the *TypeName it denotes.
+	//
+	// Invariant: Uses[id].Pos() != id.Pos()
+	Uses map[*ast.Ident]Object
+
+	// Implicits maps nodes to their implicitly declared objects, if any.
+	// The following node and object types may appear:
+	//
+	//	node               declared object
+	//
+	//	*ast.ImportSpec    *PkgName for dot-imports and imports without renames
+	//	*ast.CaseClause    type-specific *Var for each type switch case clause (incl. default)
+	//      *ast.Field         anonymous struct field or parameter *Var
+	//
+	Implicits map[ast.Node]Object
+
+	// Selections maps selector expressions (excluding qualified identifiers)
+	// to their corresponding selections.
+	Selections map[*ast.SelectorExpr]*Selection
+
+	// Scopes maps ast.Nodes to the scopes they define. Package scopes are not
+	// associated with a specific node but with all files belonging to a package.
+	// Thus, the package scope can be found in the type-checked Package object.
+	// Scopes nest, with the Universe scope being the outermost scope, enclosing
+	// the package scope, which contains (one or more) files scopes, which enclose
+	// function scopes which in turn enclose statement and function literal scopes.
+	// Note that even though package-level functions are declared in the package
+	// scope, the function scopes are embedded in the file scope of the file
+	// containing the function declaration.
+	//
+	// The following node types may appear in Scopes:
+	//
+	//	*ast.File
+	//	*ast.FuncType
+	//	*ast.BlockStmt
+	//	*ast.IfStmt
+	//	*ast.SwitchStmt
+	//	*ast.TypeSwitchStmt
+	//	*ast.CaseClause
+	//	*ast.CommClause
+	//	*ast.ForStmt
+	//	*ast.RangeStmt
+	//
+	Scopes map[ast.Node]*Scope
+
+	// InitOrder is the list of package-level initializers in the order in which
+	// they must be executed. Initializers referring to variables related by an
+	// initialization dependency appear in topological order, the others appear
+	// in source order. Variables without an initialization expression do not
+	// appear in this list.
+	InitOrder []*Initializer
+}
+
+// TypeOf returns the type of expression e, or nil if not found.
+// Precondition: the Types, Uses and Defs maps are populated.
+//
+func (info *Info) TypeOf(e ast.Expr) Type {
+	if t, ok := info.Types[e]; ok {
+		return t.Type
+	}
+	if id, _ := e.(*ast.Ident); id != nil {
+		if obj := info.ObjectOf(id); obj != nil {
+			return obj.Type()
+		}
+	}
+	return nil
+}
+
+// ObjectOf returns the object denoted by the specified id,
+// or nil if not found.
+//
+// If id is an anonymous struct field, ObjectOf returns the field (*Var)
+// it uses, not the type (*TypeName) it defines.
+//
+// Precondition: the Uses and Defs maps are populated.
+//
+func (info *Info) ObjectOf(id *ast.Ident) Object {
+	if obj, _ := info.Defs[id]; obj != nil {
+		return obj
+	}
+	return info.Uses[id]
+}
+
+// TypeAndValue reports the type and value (for constants)
+// of the corresponding expression.
+type TypeAndValue struct {
+	mode  operandMode
+	Type  Type
+	Value exact.Value
+}
+
+// TODO(gri) Consider eliminating the IsVoid predicate. Instead, report
+// "void" values as regular values but with the empty tuple type.
+
+// IsVoid reports whether the corresponding expression
+// is a function call without results.
+func (tv TypeAndValue) IsVoid() bool {
+	return tv.mode == novalue
+}
+
+// IsType reports whether the corresponding expression specifies a type.
+func (tv TypeAndValue) IsType() bool {
+	return tv.mode == typexpr
+}
+
+// IsBuiltin reports whether the corresponding expression denotes
+// a (possibly parenthesized) built-in function.
+func (tv TypeAndValue) IsBuiltin() bool {
+	return tv.mode == builtin
+}
+
+// IsValue reports whether the corresponding expression is a value.
+// Builtins are not considered values. Constant values have a non-
+// nil Value.
+func (tv TypeAndValue) IsValue() bool {
+	switch tv.mode {
+	case constant, variable, mapindex, value, commaok:
+		return true
+	}
+	return false
+}
+
+// IsNil reports whether the corresponding expression denotes the
+// predeclared value nil.
+func (tv TypeAndValue) IsNil() bool {
+	return tv.mode == value && tv.Type == Typ[UntypedNil]
+}
+
+// Addressable reports whether the corresponding expression
+// is addressable (http://golang.org/ref/spec#Address_operators).
+func (tv TypeAndValue) Addressable() bool {
+	return tv.mode == variable
+}
+
+// Assignable reports whether the corresponding expression
+// is assignable to (provided a value of the right type).
+func (tv TypeAndValue) Assignable() bool {
+	return tv.mode == variable || tv.mode == mapindex
+}
+
+// HasOk reports whether the corresponding expression may be
+// used on the lhs of a comma-ok assignment.
+func (tv TypeAndValue) HasOk() bool {
+	return tv.mode == commaok || tv.mode == mapindex
+}
+
+// An Initializer describes a package-level variable, or a list of variables in case
+// of a multi-valued initialization expression, and the corresponding initialization
+// expression.
+type Initializer struct {
+	Lhs []*Var // var Lhs = Rhs
+	Rhs ast.Expr
+}
+
+func (init *Initializer) String() string {
+	var buf bytes.Buffer
+	for i, lhs := range init.Lhs {
+		if i > 0 {
+			buf.WriteString(", ")
+		}
+		buf.WriteString(lhs.Name())
+	}
+	buf.WriteString(" = ")
+	WriteExpr(&buf, init.Rhs)
+	return buf.String()
+}
+
+// Check type-checks a package and returns the resulting package object,
+// the first error if any, and if info != nil, additional type information.
+// The package is marked as complete if no errors occurred, otherwise it is
+// incomplete. See Config.Error for controlling behavior in the presence of
+// errors.
+//
+// The package is specified by a list of *ast.Files and corresponding
+// file set, and the package path the package is identified with.
+// The clean path must not be empty or dot (".").
+func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) {
+	pkg := NewPackage(path, "")
+	return pkg, NewChecker(conf, fset, pkg, info).Files(files)
+}
+
+// AssertableTo reports whether a value of type V can be asserted to have type T.
+func AssertableTo(V *Interface, T Type) bool {
+	m, _ := assertableTo(V, T)
+	return m == nil
+}
+
+// AssignableTo reports whether a value of type V is assignable to a variable of type T.
+func AssignableTo(V, T Type) bool {
+	x := operand{mode: value, typ: V}
+	return x.assignableTo(nil, T) // config not needed for non-constant x
+}
+
+// ConvertibleTo reports whether a value of type V is convertible to a value of type T.
+func ConvertibleTo(V, T Type) bool {
+	x := operand{mode: value, typ: V}
+	return x.convertibleTo(nil, T) // config not needed for non-constant x
+}
+
+// Implements reports whether type V implements interface T.
+func Implements(V Type, T *Interface) bool {
+	f, _ := MissingMethod(V, T, true)
+	return f == nil
+}
diff --git a/third_party/go.tools/go/types/api_test.go b/third_party/go.tools/go/types/api_test.go
new file mode 100644
index 0000000..4502b6b
--- /dev/null
+++ b/third_party/go.tools/go/types/api_test.go
@@ -0,0 +1,936 @@
+// Copyright 2013 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 types_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"strings"
+	"testing"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func pkgFor(path, source string, info *Info) (*Package, error) {
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, path, source, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	var conf Config
+	return conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
+}
+
+func mustTypecheck(t *testing.T, path, source string, info *Info) string {
+	pkg, err := pkgFor(path, source, info)
+	if err != nil {
+		name := path
+		if pkg != nil {
+			name = "package " + pkg.Name()
+		}
+		t.Fatalf("%s: didn't type-check (%s)", name, err)
+	}
+	return pkg.Name()
+}
+
+func TestValuesInfo(t *testing.T) {
+	var tests = []struct {
+		src  string
+		expr string // constant expression
+		typ  string // constant type
+		val  string // constant value
+	}{
+		{`package a0; const _ = false`, `false`, `untyped bool`, `false`},
+		{`package a1; const _ = 0`, `0`, `untyped int`, `0`},
+		{`package a2; const _ = 'A'`, `'A'`, `untyped rune`, `65`},
+		{`package a3; const _ = 0.`, `0.`, `untyped float`, `0`},
+		{`package a4; const _ = 0i`, `0i`, `untyped complex`, `0`},
+		{`package a5; const _ = "foo"`, `"foo"`, `untyped string`, `"foo"`},
+
+		{`package b0; var _ = false`, `false`, `bool`, `false`},
+		{`package b1; var _ = 0`, `0`, `int`, `0`},
+		{`package b2; var _ = 'A'`, `'A'`, `rune`, `65`},
+		{`package b3; var _ = 0.`, `0.`, `float64`, `0`},
+		{`package b4; var _ = 0i`, `0i`, `complex128`, `0`},
+		{`package b5; var _ = "foo"`, `"foo"`, `string`, `"foo"`},
+
+		{`package c0a; var _ = bool(false)`, `false`, `bool`, `false`},
+		{`package c0b; var _ = bool(false)`, `bool(false)`, `bool`, `false`},
+		{`package c0c; type T bool; var _ = T(false)`, `T(false)`, `c0c.T`, `false`},
+
+		{`package c1a; var _ = int(0)`, `0`, `int`, `0`},
+		{`package c1b; var _ = int(0)`, `int(0)`, `int`, `0`},
+		{`package c1c; type T int; var _ = T(0)`, `T(0)`, `c1c.T`, `0`},
+
+		{`package c2a; var _ = rune('A')`, `'A'`, `rune`, `65`},
+		{`package c2b; var _ = rune('A')`, `rune('A')`, `rune`, `65`},
+		{`package c2c; type T rune; var _ = T('A')`, `T('A')`, `c2c.T`, `65`},
+
+		{`package c3a; var _ = float32(0.)`, `0.`, `float32`, `0`},
+		{`package c3b; var _ = float32(0.)`, `float32(0.)`, `float32`, `0`},
+		{`package c3c; type T float32; var _ = T(0.)`, `T(0.)`, `c3c.T`, `0`},
+
+		{`package c4a; var _ = complex64(0i)`, `0i`, `complex64`, `0`},
+		{`package c4b; var _ = complex64(0i)`, `complex64(0i)`, `complex64`, `0`},
+		{`package c4c; type T complex64; var _ = T(0i)`, `T(0i)`, `c4c.T`, `0`},
+
+		{`package c5a; var _ = string("foo")`, `"foo"`, `string`, `"foo"`},
+		{`package c5b; var _ = string("foo")`, `string("foo")`, `string`, `"foo"`},
+		{`package c5c; type T string; var _ = T("foo")`, `T("foo")`, `c5c.T`, `"foo"`},
+
+		{`package d0; var _ = []byte("foo")`, `"foo"`, `string`, `"foo"`},
+		{`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`},
+		{`package d2; var _ = []byte(string("foo"))`, `string("foo")`, `string`, `"foo"`},
+		{`package d3; type T []byte; var _ = T("foo")`, `"foo"`, `string`, `"foo"`},
+
+		{`package e0; const _ = float32( 1e-200)`, `float32(1e-200)`, `float32`, `0`},
+		{`package e1; const _ = float32(-1e-200)`, `float32(-1e-200)`, `float32`, `0`},
+		{`package e2; const _ = float64( 1e-2000)`, `float64(1e-2000)`, `float64`, `0`},
+		{`package e3; const _ = float64(-1e-2000)`, `float64(-1e-2000)`, `float64`, `0`},
+		{`package e4; const _ = complex64( 1e-200)`, `complex64(1e-200)`, `complex64`, `0`},
+		{`package e5; const _ = complex64(-1e-200)`, `complex64(-1e-200)`, `complex64`, `0`},
+		{`package e6; const _ = complex128( 1e-2000)`, `complex128(1e-2000)`, `complex128`, `0`},
+		{`package e7; const _ = complex128(-1e-2000)`, `complex128(-1e-2000)`, `complex128`, `0`},
+
+		{`package f0 ; var _ float32 =  1e-200`, `1e-200`, `float32`, `0`},
+		{`package f1 ; var _ float32 = -1e-200`, `-1e-200`, `float32`, `0`},
+		{`package f2a; var _ float64 =  1e-2000`, `1e-2000`, `float64`, `0`},
+		{`package f3a; var _ float64 = -1e-2000`, `-1e-2000`, `float64`, `0`},
+		{`package f2b; var _         =  1e-2000`, `1e-2000`, `float64`, `0`},
+		{`package f3b; var _         = -1e-2000`, `-1e-2000`, `float64`, `0`},
+		{`package f4 ; var _ complex64  =  1e-200 `, `1e-200`, `complex64`, `0`},
+		{`package f5 ; var _ complex64  = -1e-200 `, `-1e-200`, `complex64`, `0`},
+		{`package f6a; var _ complex128 =  1e-2000i`, `1e-2000i`, `complex128`, `0`},
+		{`package f7a; var _ complex128 = -1e-2000i`, `-1e-2000i`, `complex128`, `0`},
+		{`package f6b; var _            =  1e-2000i`, `1e-2000i`, `complex128`, `0`},
+		{`package f7b; var _            = -1e-2000i`, `-1e-2000i`, `complex128`, `0`},
+	}
+
+	for _, test := range tests {
+		info := Info{
+			Types: make(map[ast.Expr]TypeAndValue),
+		}
+		name := mustTypecheck(t, "ValuesInfo", test.src, &info)
+
+		// look for constant expression
+		var expr ast.Expr
+		for e := range info.Types {
+			if ExprString(e) == test.expr {
+				expr = e
+				break
+			}
+		}
+		if expr == nil {
+			t.Errorf("package %s: no expression found for %s", name, test.expr)
+			continue
+		}
+		tv := info.Types[expr]
+
+		// check that type is correct
+		if got := tv.Type.String(); got != test.typ {
+			t.Errorf("package %s: got type %s; want %s", name, got, test.typ)
+			continue
+		}
+
+		// check that value is correct
+		if got := tv.Value.String(); got != test.val {
+			t.Errorf("package %s: got value %s; want %s", name, got, test.val)
+		}
+	}
+}
+
+func TestTypesInfo(t *testing.T) {
+	var tests = []struct {
+		src  string
+		expr string // expression
+		typ  string // value type
+	}{
+		// single-valued expressions of untyped constants
+		{`package b0; var x interface{} = false`, `false`, `bool`},
+		{`package b1; var x interface{} = 0`, `0`, `int`},
+		{`package b2; var x interface{} = 0.`, `0.`, `float64`},
+		{`package b3; var x interface{} = 0i`, `0i`, `complex128`},
+		{`package b4; var x interface{} = "foo"`, `"foo"`, `string`},
+
+		// comma-ok expressions
+		{`package p0; var x interface{}; var _, _ = x.(int)`,
+			`x.(int)`,
+			`(int, bool)`,
+		},
+		{`package p1; var x interface{}; func _() { _, _ = x.(int) }`,
+			`x.(int)`,
+			`(int, bool)`,
+		},
+		// TODO(gri): uncomment if we accept issue 8189.
+		// {`package p2; type mybool bool; var m map[string]complex128; var b mybool; func _() { _, b = m["foo"] }`,
+		// 	`m["foo"]`,
+		// 	`(complex128, p2.mybool)`,
+		// },
+		// TODO(gri): remove if we accept issue 8189.
+		{`package p2; var m map[string]complex128; var b bool; func _() { _, b = m["foo"] }`,
+			`m["foo"]`,
+			`(complex128, bool)`,
+		},
+		{`package p3; var c chan string; var _, _ = <-c`,
+			`<-c`,
+			`(string, bool)`,
+		},
+
+		// issue 6796
+		{`package issue6796_a; var x interface{}; var _, _ = (x.(int))`,
+			`x.(int)`,
+			`(int, bool)`,
+		},
+		{`package issue6796_b; var c chan string; var _, _ = (<-c)`,
+			`(<-c)`,
+			`(string, bool)`,
+		},
+		{`package issue6796_c; var c chan string; var _, _ = (<-c)`,
+			`<-c`,
+			`(string, bool)`,
+		},
+		{`package issue6796_d; var c chan string; var _, _ = ((<-c))`,
+			`(<-c)`,
+			`(string, bool)`,
+		},
+		{`package issue6796_e; func f(c chan string) { _, _ = ((<-c)) }`,
+			`(<-c)`,
+			`(string, bool)`,
+		},
+
+		// issue 7060
+		{`package issue7060_a; var ( m map[int]string; x, ok = m[0] )`,
+			`m[0]`,
+			`(string, bool)`,
+		},
+		{`package issue7060_b; var ( m map[int]string; x, ok interface{} = m[0] )`,
+			`m[0]`,
+			`(string, bool)`,
+		},
+		{`package issue7060_c; func f(x interface{}, ok bool, m map[int]string) { x, ok = m[0] }`,
+			`m[0]`,
+			`(string, bool)`,
+		},
+		{`package issue7060_d; var ( ch chan string; x, ok = <-ch )`,
+			`<-ch`,
+			`(string, bool)`,
+		},
+		{`package issue7060_e; var ( ch chan string; x, ok interface{} = <-ch )`,
+			`<-ch`,
+			`(string, bool)`,
+		},
+		{`package issue7060_f; func f(x interface{}, ok bool, ch chan string) { x, ok = <-ch }`,
+			`<-ch`,
+			`(string, bool)`,
+		},
+	}
+
+	for _, test := range tests {
+		info := Info{Types: make(map[ast.Expr]TypeAndValue)}
+		name := mustTypecheck(t, "TypesInfo", test.src, &info)
+
+		// look for expression type
+		var typ Type
+		for e, tv := range info.Types {
+			if ExprString(e) == test.expr {
+				typ = tv.Type
+				break
+			}
+		}
+		if typ == nil {
+			t.Errorf("package %s: no type found for %s", name, test.expr)
+			continue
+		}
+
+		// check that type is correct
+		if got := typ.String(); got != test.typ {
+			t.Errorf("package %s: got %s; want %s", name, got, test.typ)
+		}
+	}
+}
+
+func predString(tv TypeAndValue) string {
+	var buf bytes.Buffer
+	pred := func(b bool, s string) {
+		if b {
+			if buf.Len() > 0 {
+				buf.WriteString(", ")
+			}
+			buf.WriteString(s)
+		}
+	}
+
+	pred(tv.IsVoid(), "void")
+	pred(tv.IsType(), "type")
+	pred(tv.IsBuiltin(), "builtin")
+	pred(tv.IsValue() && tv.Value != nil, "const")
+	pred(tv.IsValue() && tv.Value == nil, "value")
+	pred(tv.IsNil(), "nil")
+	pred(tv.Addressable(), "addressable")
+	pred(tv.Assignable(), "assignable")
+	pred(tv.HasOk(), "hasOk")
+
+	if buf.Len() == 0 {
+		return "invalid"
+	}
+	return buf.String()
+}
+
+func TestPredicatesInfo(t *testing.T) {
+	var tests = []struct {
+		src  string
+		expr string
+		pred string
+	}{
+		// void
+		{`package n0; func f() { f() }`, `f()`, `void`},
+
+		// types
+		{`package t0; type _ int`, `int`, `type`},
+		{`package t1; type _ []int`, `[]int`, `type`},
+		{`package t2; type _ func()`, `func()`, `type`},
+
+		// built-ins
+		{`package b0; var _ = len("")`, `len`, `builtin`},
+		{`package b1; var _ = (len)("")`, `(len)`, `builtin`},
+
+		// constants
+		{`package c0; var _ = 42`, `42`, `const`},
+		{`package c1; var _ = "foo" + "bar"`, `"foo" + "bar"`, `const`},
+		{`package c2; const (i = 1i; _ = i)`, `i`, `const`},
+
+		// values
+		{`package v0; var (a, b int; _ = a + b)`, `a + b`, `value`},
+		{`package v1; var _ = &[]int{1}`, `([]int literal)`, `value`},
+		{`package v2; var _ = func(){}`, `(func() literal)`, `value`},
+		{`package v4; func f() { _ = f }`, `f`, `value`},
+		{`package v3; var _ *int = nil`, `nil`, `value, nil`},
+		{`package v3; var _ *int = (nil)`, `(nil)`, `value, nil`},
+
+		// addressable (and thus assignable) operands
+		{`package a0; var (x int; _ = x)`, `x`, `value, addressable, assignable`},
+		{`package a1; var (p *int; _ = *p)`, `*p`, `value, addressable, assignable`},
+		{`package a2; var (s []int; _ = s[0])`, `s[0]`, `value, addressable, assignable`},
+		{`package a3; var (s struct{f int}; _ = s.f)`, `s.f`, `value, addressable, assignable`},
+		{`package a4; var (a [10]int; _ = a[0])`, `a[0]`, `value, addressable, assignable`},
+		{`package a5; func _(x int) { _ = x }`, `x`, `value, addressable, assignable`},
+		{`package a6; func _()(x int) { _ = x; return }`, `x`, `value, addressable, assignable`},
+		{`package a7; type T int; func (x T) _() { _ = x }`, `x`, `value, addressable, assignable`},
+		// composite literals are not addressable
+
+		// assignable but not addressable values
+		{`package s0; var (m map[int]int; _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
+		{`package s1; var (m map[int]int; _, _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
+
+		// hasOk expressions
+		{`package k0; var (ch chan int; _ = <-ch)`, `<-ch`, `value, hasOk`},
+		{`package k1; var (ch chan int; _, _ = <-ch)`, `<-ch`, `value, hasOk`},
+
+		// missing entries
+		// - package names are collected in the Uses map
+		// - identifiers being declared are collected in the Defs map
+		{`package m0; import "os"; func _() { _ = os.Stdout }`, `os`, `<missing>`},
+		{`package m1; import p "os"; func _() { _ = p.Stdout }`, `p`, `<missing>`},
+		{`package m2; const c = 0`, `c`, `<missing>`},
+		{`package m3; type T int`, `T`, `<missing>`},
+		{`package m4; var v int`, `v`, `<missing>`},
+		{`package m5; func f() {}`, `f`, `<missing>`},
+		{`package m6; func _(x int) {}`, `x`, `<missing>`},
+		{`package m6; func _()(x int) { return }`, `x`, `<missing>`},
+		{`package m6; type T int; func (x T) _() {}`, `x`, `<missing>`},
+	}
+
+	for _, test := range tests {
+		info := Info{Types: make(map[ast.Expr]TypeAndValue)}
+		name := mustTypecheck(t, "PredicatesInfo", test.src, &info)
+
+		// look for expression predicates
+		got := "<missing>"
+		for e, tv := range info.Types {
+			//println(name, ExprString(e))
+			if ExprString(e) == test.expr {
+				got = predString(tv)
+				break
+			}
+		}
+
+		if got != test.pred {
+			t.Errorf("package %s: got %s; want %s", name, got, test.pred)
+		}
+	}
+}
+
+func TestScopesInfo(t *testing.T) {
+	var tests = []struct {
+		src    string
+		scopes []string // list of scope descriptors of the form kind:varlist
+	}{
+		{`package p0`, []string{
+			"file:",
+		}},
+		{`package p1; import ( "fmt"; m "math"; _ "os" ); var ( _ = fmt.Println; _ = m.Pi )`, []string{
+			"file:fmt m",
+		}},
+		{`package p2; func _() {}`, []string{
+			"file:", "func:",
+		}},
+		{`package p3; func _(x, y int) {}`, []string{
+			"file:", "func:x y",
+		}},
+		{`package p4; func _(x, y int) { x, z := 1, 2; _ = z }`, []string{
+			"file:", "func:x y z", // redeclaration of x
+		}},
+		{`package p5; func _(x, y int) (u, _ int) { return }`, []string{
+			"file:", "func:u x y",
+		}},
+		{`package p6; func _() { { var x int; _ = x } }`, []string{
+			"file:", "func:", "block:x",
+		}},
+		{`package p7; func _() { if true {} }`, []string{
+			"file:", "func:", "if:", "block:",
+		}},
+		{`package p8; func _() { if x := 0; x < 0 { y := x; _ = y } }`, []string{
+			"file:", "func:", "if:x", "block:y",
+		}},
+		{`package p9; func _() { switch x := 0; x {} }`, []string{
+			"file:", "func:", "switch:x",
+		}},
+		{`package p10; func _() { switch x := 0; x { case 1: y := x; _ = y; default: }}`, []string{
+			"file:", "func:", "switch:x", "case:y", "case:",
+		}},
+		{`package p11; func _(t interface{}) { switch t.(type) {} }`, []string{
+			"file:", "func:t", "type switch:",
+		}},
+		{`package p12; func _(t interface{}) { switch t := t; t.(type) {} }`, []string{
+			"file:", "func:t", "type switch:t",
+		}},
+		{`package p13; func _(t interface{}) { switch x := t.(type) { case int: _ = x } }`, []string{
+			"file:", "func:t", "type switch:", "case:x", // x implicitly declared
+		}},
+		{`package p14; func _() { select{} }`, []string{
+			"file:", "func:",
+		}},
+		{`package p15; func _(c chan int) { select{ case <-c: } }`, []string{
+			"file:", "func:c", "comm:",
+		}},
+		{`package p16; func _(c chan int) { select{ case i := <-c: x := i; _ = x} }`, []string{
+			"file:", "func:c", "comm:i x",
+		}},
+		{`package p17; func _() { for{} }`, []string{
+			"file:", "func:", "for:", "block:",
+		}},
+		{`package p18; func _(n int) { for i := 0; i < n; i++ { _ = i } }`, []string{
+			"file:", "func:n", "for:i", "block:",
+		}},
+		{`package p19; func _(a []int) { for i := range a { _ = i} }`, []string{
+			"file:", "func:a", "range:i", "block:",
+		}},
+		{`package p20; var s int; func _(a []int) { for i, x := range a { s += x; _ = i } }`, []string{
+			"file:", "func:a", "range:i x", "block:",
+		}},
+	}
+
+	for _, test := range tests {
+		info := Info{Scopes: make(map[ast.Node]*Scope)}
+		name := mustTypecheck(t, "ScopesInfo", test.src, &info)
+
+		// number of scopes must match
+		if len(info.Scopes) != len(test.scopes) {
+			t.Errorf("package %s: got %d scopes; want %d", name, len(info.Scopes), len(test.scopes))
+		}
+
+		// scope descriptions must match
+		for node, scope := range info.Scopes {
+			kind := "<unknown node kind>"
+			switch node.(type) {
+			case *ast.File:
+				kind = "file"
+			case *ast.FuncType:
+				kind = "func"
+			case *ast.BlockStmt:
+				kind = "block"
+			case *ast.IfStmt:
+				kind = "if"
+			case *ast.SwitchStmt:
+				kind = "switch"
+			case *ast.TypeSwitchStmt:
+				kind = "type switch"
+			case *ast.CaseClause:
+				kind = "case"
+			case *ast.CommClause:
+				kind = "comm"
+			case *ast.ForStmt:
+				kind = "for"
+			case *ast.RangeStmt:
+				kind = "range"
+			}
+
+			// look for matching scope description
+			desc := kind + ":" + strings.Join(scope.Names(), " ")
+			found := false
+			for _, d := range test.scopes {
+				if desc == d {
+					found = true
+					break
+				}
+			}
+			if !found {
+				t.Errorf("package %s: no matching scope found for %s", name, desc)
+			}
+		}
+	}
+}
+
+func TestInitOrderInfo(t *testing.T) {
+	var tests = []struct {
+		src   string
+		inits []string
+	}{
+		{`package p0; var (x = 1; y = x)`, []string{
+			"x = 1", "y = x",
+		}},
+		{`package p1; var (a = 1; b = 2; c = 3)`, []string{
+			"a = 1", "b = 2", "c = 3",
+		}},
+		{`package p2; var (a, b, c = 1, 2, 3)`, []string{
+			"a = 1", "b = 2", "c = 3",
+		}},
+		{`package p3; var _ = f(); func f() int { return 1 }`, []string{
+			"_ = f()", // blank var
+		}},
+		{`package p4; var (a = 0; x = y; y = z; z = 0)`, []string{
+			"a = 0", "z = 0", "y = z", "x = y",
+		}},
+		{`package p5; var (a, _ = m[0]; m map[int]string)`, []string{
+			"a, _ = m[0]", // blank var
+		}},
+		{`package p6; var a, b = f(); func f() (_, _ int) { return z, z }; var z = 0`, []string{
+			"z = 0", "a, b = f()",
+		}},
+		{`package p7; var (a = func() int { return b }(); b = 1)`, []string{
+			"b = 1", "a = (func() int literal)()",
+		}},
+		{`package p8; var (a, b = func() (_, _ int) { return c, c }(); c = 1)`, []string{
+			"c = 1", "a, b = (func() (_, _ int) literal)()",
+		}},
+		{`package p9; type T struct{}; func (T) m() int { _ = y; return 0 }; var x, y = T.m, 1`, []string{
+			"y = 1", "x = T.m",
+		}},
+		{`package p10; var (d = c + b; a = 0; b = 0; c = 0)`, []string{
+			"a = 0", "b = 0", "c = 0", "d = c + b",
+		}},
+		{`package p11; var (a = e + c; b = d + c; c = 0; d = 0; e = 0)`, []string{
+			"c = 0", "d = 0", "b = d + c", "e = 0", "a = e + c",
+		}},
+		// emit an initializer for n:1 initializations only once (not for each node
+		// on the lhs which may appear in different order in the dependency graph)
+		{`package p12; var (a = x; b = 0; x, y = m[0]; m map[int]int)`, []string{
+			"b = 0", "x, y = m[0]", "a = x",
+		}},
+		// test case from spec section on package initialization
+		{`package p12
+
+		var (
+			a = c + b
+			b = f()
+			c = f()
+			d = 3
+		)
+
+		func f() int {
+			d++
+			return d
+		}`, []string{
+			"d = 3", "b = f()", "c = f()", "a = c + b",
+		}},
+		// test case for issue 7131
+		{`package main
+
+		var counter int
+		func next() int { counter++; return counter }
+
+		var _ = makeOrder()
+		func makeOrder() []int { return []int{f, b, d, e, c, a} }
+
+		var a       = next()
+		var b, c    = next(), next()
+		var d, e, f = next(), next(), next()
+		`, []string{
+			"a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()",
+		}},
+	}
+
+	for _, test := range tests {
+		info := Info{}
+		name := mustTypecheck(t, "InitOrderInfo", test.src, &info)
+
+		// number of initializers must match
+		if len(info.InitOrder) != len(test.inits) {
+			t.Errorf("package %s: got %d initializers; want %d", name, len(info.InitOrder), len(test.inits))
+			continue
+		}
+
+		// initializers must match
+		for i, want := range test.inits {
+			got := info.InitOrder[i].String()
+			if got != want {
+				t.Errorf("package %s, init %d: got %s; want %s", name, i, got, want)
+				continue
+			}
+		}
+	}
+}
+
+func TestMultiFileInitOrder(t *testing.T) {
+	fset := token.NewFileSet()
+	mustParse := func(src string) *ast.File {
+		f, err := parser.ParseFile(fset, "main", src, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		return f
+	}
+
+	fileA := mustParse(`package main; var a = 1`)
+	fileB := mustParse(`package main; var b = 2`)
+
+	// The initialization order must not depend on the parse
+	// order of the files, only on the presentation order to
+	// the type-checker.
+	for _, test := range []struct {
+		files []*ast.File
+		want  string
+	}{
+		{[]*ast.File{fileA, fileB}, "[a = 1 b = 2]"},
+		{[]*ast.File{fileB, fileA}, "[b = 2 a = 1]"},
+	} {
+		var info Info
+		if _, err := new(Config).Check("main", fset, test.files, &info); err != nil {
+			t.Fatal(err)
+		}
+		if got := fmt.Sprint(info.InitOrder); got != test.want {
+			t.Fatalf("got %s; want %s", got, test.want)
+		}
+	}
+}
+
+func TestFiles(t *testing.T) {
+	var sources = []string{
+		"package p; type T struct{}; func (T) m1() {}",
+		"package p; func (T) m2() {}; var x interface{ m1(); m2() } = T{}",
+		"package p; func (T) m3() {}; var y interface{ m1(); m2(); m3() } = T{}",
+		"package p",
+	}
+
+	var conf Config
+	fset := token.NewFileSet()
+	pkg := NewPackage("p", "p")
+	var info Info
+	check := NewChecker(&conf, fset, pkg, &info)
+
+	for i, src := range sources {
+		filename := fmt.Sprintf("sources%d", i)
+		f, err := parser.ParseFile(fset, filename, src, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if err := check.Files([]*ast.File{f}); err != nil {
+			t.Error(err)
+		}
+	}
+
+	// check InitOrder is [x y]
+	var vars []string
+	for _, init := range info.InitOrder {
+		for _, v := range init.Lhs {
+			vars = append(vars, v.Name())
+		}
+	}
+	if got, want := fmt.Sprint(vars), "[x y]"; got != want {
+		t.Errorf("InitOrder == %s, want %s", got, want)
+	}
+}
+
+func TestSelection(t *testing.T) {
+	selections := make(map[*ast.SelectorExpr]*Selection)
+
+	fset := token.NewFileSet()
+	conf := Config{
+		Packages: make(map[string]*Package),
+		Import: func(imports map[string]*Package, path string) (*Package, error) {
+			return imports[path], nil
+		},
+	}
+	makePkg := func(path, src string) {
+		f, err := parser.ParseFile(fset, path+".go", src, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		pkg, err := conf.Check(path, fset, []*ast.File{f}, &Info{Selections: selections})
+		if err != nil {
+			t.Fatal(err)
+		}
+		conf.Packages[path] = pkg
+	}
+
+	const libSrc = `
+package lib
+type T float64
+const C T = 3
+var V T
+func F() {}
+func (T) M() {}
+`
+	const mainSrc = `
+package main
+import "lib"
+
+type A struct {
+	*B
+	C
+}
+
+type B struct {
+	b int
+}
+
+func (B) f(int)
+
+type C struct {
+	c int
+}
+
+func (C) g()
+func (*C) h()
+
+func main() {
+	// qualified identifiers
+	var _ lib.T
+        _ = lib.C
+        _ = lib.F
+        _ = lib.V
+	_ = lib.T.M
+
+	// fields
+	_ = A{}.B
+	_ = new(A).B
+
+	_ = A{}.C
+	_ = new(A).C
+
+	_ = A{}.b
+	_ = new(A).b
+
+	_ = A{}.c
+	_ = new(A).c
+
+	// methods
+        _ = A{}.f
+        _ = new(A).f
+        _ = A{}.g
+        _ = new(A).g
+        _ = new(A).h
+
+        _ = B{}.f
+        _ = new(B).f
+
+        _ = C{}.g
+        _ = new(C).g
+        _ = new(C).h
+
+	// method expressions
+        _ = A.f
+        _ = (*A).f
+        _ = B.f
+        _ = (*B).f
+}`
+
+	wantOut := map[string][2]string{
+		"lib.T.M": {"method expr (lib.T) M(lib.T)", ".[0]"},
+
+		"A{}.B":    {"field (main.A) B *main.B", ".[0]"},
+		"new(A).B": {"field (*main.A) B *main.B", "->[0]"},
+		"A{}.C":    {"field (main.A) C main.C", ".[1]"},
+		"new(A).C": {"field (*main.A) C main.C", "->[1]"},
+		"A{}.b":    {"field (main.A) b int", "->[0 0]"},
+		"new(A).b": {"field (*main.A) b int", "->[0 0]"},
+		"A{}.c":    {"field (main.A) c int", ".[1 0]"},
+		"new(A).c": {"field (*main.A) c int", "->[1 0]"},
+
+		"A{}.f":    {"method (main.A) f(int)", "->[0 0]"},
+		"new(A).f": {"method (*main.A) f(int)", "->[0 0]"},
+		"A{}.g":    {"method (main.A) g()", ".[1 0]"},
+		"new(A).g": {"method (*main.A) g()", "->[1 0]"},
+		"new(A).h": {"method (*main.A) h()", "->[1 1]"}, // TODO(gri) should this report .[1 1] ?
+		"B{}.f":    {"method (main.B) f(int)", ".[0]"},
+		"new(B).f": {"method (*main.B) f(int)", "->[0]"},
+		"C{}.g":    {"method (main.C) g()", ".[0]"},
+		"new(C).g": {"method (*main.C) g()", "->[0]"},
+		"new(C).h": {"method (*main.C) h()", "->[1]"}, // TODO(gri) should this report .[1] ?
+
+		"A.f":    {"method expr (main.A) f(main.A, int)", "->[0 0]"},
+		"(*A).f": {"method expr (*main.A) f(*main.A, int)", "->[0 0]"},
+		"B.f":    {"method expr (main.B) f(main.B, int)", ".[0]"},
+		"(*B).f": {"method expr (*main.B) f(*main.B, int)", "->[0]"},
+	}
+
+	makePkg("lib", libSrc)
+	makePkg("main", mainSrc)
+
+	for e, sel := range selections {
+		sel.String() // assertion: must not panic
+
+		start := fset.Position(e.Pos()).Offset
+		end := fset.Position(e.End()).Offset
+		syntax := mainSrc[start:end] // (all SelectorExprs are in main, not lib)
+
+		direct := "."
+		if sel.Indirect() {
+			direct = "->"
+		}
+		got := [2]string{
+			sel.String(),
+			fmt.Sprintf("%s%v", direct, sel.Index()),
+		}
+		want := wantOut[syntax]
+		if want != got {
+			t.Errorf("%s: got %q; want %q", syntax, got, want)
+		}
+		delete(wantOut, syntax)
+
+		// We must explicitly assert properties of the
+		// Signature's receiver since it doesn't participate
+		// in Identical() or String().
+		sig, _ := sel.Type().(*Signature)
+		if sel.Kind() == MethodVal {
+			got := sig.Recv().Type()
+			want := sel.Recv()
+			if !Identical(got, want) {
+				t.Errorf("%s: Recv() = %s, want %s", got, want)
+			}
+		} else if sig != nil && sig.Recv() != nil {
+			t.Error("%s: signature has receiver %s", sig, sig.Recv().Type())
+		}
+	}
+	// Assert that all wantOut entries were used exactly once.
+	for syntax := range wantOut {
+		t.Errorf("no ast.Selection found with syntax %q", syntax)
+	}
+}
+
+func TestIssue8518(t *testing.T) {
+	fset := token.NewFileSet()
+	conf := Config{
+		Packages: make(map[string]*Package),
+		Error:    func(err error) { t.Log(err) }, // don't exit after first error
+		Import: func(imports map[string]*Package, path string) (*Package, error) {
+			return imports[path], nil
+		},
+	}
+	makePkg := func(path, src string) {
+		f, err := parser.ParseFile(fset, path, src, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		pkg, _ := conf.Check(path, fset, []*ast.File{f}, nil) // errors logged via conf.Error
+		conf.Packages[path] = pkg
+	}
+
+	const libSrc = `
+package a 
+import "missing"
+const C1 = foo
+const C2 = missing.C
+`
+
+	const mainSrc = `
+package main
+import "a"
+var _ = a.C1
+var _ = a.C2
+`
+
+	makePkg("a", libSrc)
+	makePkg("main", mainSrc) // don't crash when type-checking this package
+}
+
+func TestLookupFieldOrMethod(t *testing.T) {
+	// Test cases assume a lookup of the form a.f or x.f, where a stands for an
+	// addressable value, and x for a non-addressable value (even though a variable
+	// for ease of test case writing).
+	var tests = []struct {
+		src      string
+		found    bool
+		index    []int
+		indirect bool
+	}{
+		// field lookups
+		{"var x T; type T struct{}", false, nil, false},
+		{"var x T; type T struct{ f int }", true, []int{0}, false},
+		{"var x T; type T struct{ a, b, f, c int }", true, []int{2}, false},
+
+		// method lookups
+		{"var a T; type T struct{}; func (T) f() {}", true, []int{0}, false},
+		{"var a *T; type T struct{}; func (T) f() {}", true, []int{0}, true},
+		{"var a T; type T struct{}; func (*T) f() {}", true, []int{0}, false},
+		{"var a *T; type T struct{}; func (*T) f() {}", true, []int{0}, true}, // TODO(gri) should this report indirect = false?
+
+		// collisions
+		{"type ( E1 struct{ f int }; E2 struct{ f int }; x struct{ E1; *E2 })", false, []int{1, 0}, false},
+		{"type ( E1 struct{ f int }; E2 struct{}; x struct{ E1; *E2 }); func (E2) f() {}", false, []int{1, 0}, false},
+
+		// outside methodset
+		// (*T).f method exists, but value of type T is not addressable
+		{"var x T; type T struct{}; func (*T) f() {}", false, nil, true},
+	}
+
+	for _, test := range tests {
+		pkg, err := pkgFor("test", "package p;"+test.src, nil)
+		if err != nil {
+			t.Errorf("%s: incorrect test case: %s", test.src, err)
+			continue
+		}
+
+		obj := pkg.Scope().Lookup("a")
+		if obj == nil {
+			if obj = pkg.Scope().Lookup("x"); obj == nil {
+				t.Errorf("%s: incorrect test case - no object a or x", test.src)
+				continue
+			}
+		}
+
+		f, index, indirect := LookupFieldOrMethod(obj.Type(), obj.Name() == "a", pkg, "f")
+		if (f != nil) != test.found {
+			if f == nil {
+				t.Errorf("%s: got no object; want one", test.src)
+			} else {
+				t.Errorf("%s: got object = %v; want none", test.src, f)
+			}
+		}
+		if !sameSlice(index, test.index) {
+			t.Errorf("%s: got index = %v; want %v", test.src, index, test.index)
+		}
+		if indirect != test.indirect {
+			t.Errorf("%s: got indirect = %v; want %v", test.src, indirect, test.indirect)
+		}
+	}
+}
+
+func sameSlice(a, b []int) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i, x := range a {
+		if x != b[i] {
+			return false
+		}
+	}
+	return true
+}
diff --git a/third_party/go.tools/go/types/assignments.go b/third_party/go.tools/go/types/assignments.go
new file mode 100644
index 0000000..7ee1abc
--- /dev/null
+++ b/third_party/go.tools/go/types/assignments.go
@@ -0,0 +1,323 @@
+// Copyright 2013 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.
+
+// This file implements initialization and assignment checks.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// assignment reports whether x can be assigned to a variable of type T,
+// if necessary by attempting to convert untyped values to the appropriate
+// type. If x.mode == invalid upon return, then assignment has already
+// issued an error message and the caller doesn't have to report another.
+// Use T == nil to indicate assignment to an untyped blank identifier.
+//
+// TODO(gri) Should find a better way to handle in-band errors.
+//
+func (check *Checker) assignment(x *operand, T Type) bool {
+	switch x.mode {
+	case invalid:
+		return true // error reported before
+	case constant, variable, mapindex, value, commaok:
+		// ok
+	default:
+		unreachable()
+	}
+
+	// x must be a single value
+	// (tuple types are never named - no need for underlying type)
+	if t, _ := x.typ.(*Tuple); t != nil {
+		assert(t.Len() > 1)
+		check.errorf(x.pos(), "%d-valued expression %s used as single value", t.Len(), x)
+		x.mode = invalid
+		return false
+	}
+
+	if isUntyped(x.typ) {
+		target := T
+		// spec: "If an untyped constant is assigned to a variable of interface
+		// type or the blank identifier, the constant is first converted to type
+		// bool, rune, int, float64, complex128 or string respectively, depending
+		// on whether the value is a boolean, rune, integer, floating-point, complex,
+		// or string constant."
+		if T == nil || isInterface(T) {
+			if T == nil && x.typ == Typ[UntypedNil] {
+				check.errorf(x.pos(), "use of untyped nil")
+				x.mode = invalid
+				return false
+			}
+			target = defaultType(x.typ)
+		}
+		check.convertUntyped(x, target)
+		if x.mode == invalid {
+			return false
+		}
+	}
+
+	// spec: "If a left-hand side is the blank identifier, any typed or
+	// non-constant value except for the predeclared identifier nil may
+	// be assigned to it."
+	return T == nil || x.assignableTo(check.conf, T)
+}
+
+func (check *Checker) initConst(lhs *Const, x *operand) {
+	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
+		if lhs.typ == nil {
+			lhs.typ = Typ[Invalid]
+		}
+		return
+	}
+
+	// rhs must be a constant
+	if x.mode != constant {
+		check.errorf(x.pos(), "%s is not constant", x)
+		if lhs.typ == nil {
+			lhs.typ = Typ[Invalid]
+		}
+		return
+	}
+	assert(isConstType(x.typ))
+
+	// If the lhs doesn't have a type yet, use the type of x.
+	if lhs.typ == nil {
+		lhs.typ = x.typ
+	}
+
+	if !check.assignment(x, lhs.typ) {
+		if x.mode != invalid {
+			check.errorf(x.pos(), "cannot define constant %s (type %s) as %s", lhs.Name(), lhs.typ, x)
+		}
+		return
+	}
+
+	lhs.val = x.val
+}
+
+// If result is set, lhs is a function result parameter and x is a return result.
+func (check *Checker) initVar(lhs *Var, x *operand, result bool) Type {
+	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
+		if lhs.typ == nil {
+			lhs.typ = Typ[Invalid]
+		}
+		return nil
+	}
+
+	// If the lhs doesn't have a type yet, use the type of x.
+	if lhs.typ == nil {
+		typ := x.typ
+		if isUntyped(typ) {
+			// convert untyped types to default types
+			if typ == Typ[UntypedNil] {
+				check.errorf(x.pos(), "use of untyped nil")
+				lhs.typ = Typ[Invalid]
+				return nil
+			}
+			typ = defaultType(typ)
+		}
+		lhs.typ = typ
+	}
+
+	if !check.assignment(x, lhs.typ) {
+		if x.mode != invalid {
+			if result {
+				// don't refer to lhs.name because it may be an anonymous result parameter
+				check.errorf(x.pos(), "cannot return %s as value of type %s", x, lhs.typ)
+			} else {
+				check.errorf(x.pos(), "cannot initialize %s with %s", lhs, x)
+			}
+		}
+		return nil
+	}
+
+	return x.typ
+}
+
+func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
+	if x.mode == invalid || x.typ == Typ[Invalid] {
+		return nil
+	}
+
+	// Determine if the lhs is a (possibly parenthesized) identifier.
+	ident, _ := unparen(lhs).(*ast.Ident)
+
+	// Don't evaluate lhs if it is the blank identifier.
+	if ident != nil && ident.Name == "_" {
+		check.recordDef(ident, nil)
+		if !check.assignment(x, nil) {
+			assert(x.mode == invalid)
+			x.typ = nil
+		}
+		return x.typ
+	}
+
+	// If the lhs is an identifier denoting a variable v, this assignment
+	// is not a 'use' of v. Remember current value of v.used and restore
+	// after evaluating the lhs via check.expr.
+	var v *Var
+	var v_used bool
+	if ident != nil {
+		if _, obj := check.scope.LookupParent(ident.Name); obj != nil {
+			v, _ = obj.(*Var)
+			if v != nil {
+				v_used = v.used
+			}
+		}
+	}
+
+	var z operand
+	check.expr(&z, lhs)
+	if v != nil {
+		v.used = v_used // restore v.used
+	}
+
+	if z.mode == invalid || z.typ == Typ[Invalid] {
+		return nil
+	}
+
+	// spec: "Each left-hand side operand must be addressable, a map index
+	// expression, or the blank identifier. Operands may be parenthesized."
+	switch z.mode {
+	case invalid:
+		return nil
+	case variable, mapindex:
+		// ok
+	default:
+		check.errorf(z.pos(), "cannot assign to %s", &z)
+		return nil
+	}
+
+	if !check.assignment(x, z.typ) {
+		if x.mode != invalid {
+			check.errorf(x.pos(), "cannot assign %s to %s", x, &z)
+		}
+		return nil
+	}
+
+	return x.typ
+}
+
+// If returnPos is valid, initVars is called to type-check the assignment of
+// return expressions, and returnPos is the position of the return statement.
+func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) {
+	l := len(lhs)
+	get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
+	if get == nil || l != r {
+		// invalidate lhs and use rhs
+		for _, obj := range lhs {
+			if obj.typ == nil {
+				obj.typ = Typ[Invalid]
+			}
+		}
+		if get == nil {
+			return // error reported by unpack
+		}
+		check.useGetter(get, r)
+		if returnPos.IsValid() {
+			check.errorf(returnPos, "wrong number of return values (want %d, got %d)", l, r)
+			return
+		}
+		check.errorf(rhs[0].Pos(), "assignment count mismatch (%d vs %d)", l, r)
+		return
+	}
+
+	var x operand
+	if commaOk {
+		var a [2]Type
+		for i := range a {
+			get(&x, i)
+			a[i] = check.initVar(lhs[i], &x, returnPos.IsValid())
+		}
+		check.recordCommaOkTypes(rhs[0], a)
+		return
+	}
+
+	for i, lhs := range lhs {
+		get(&x, i)
+		check.initVar(lhs, &x, returnPos.IsValid())
+	}
+}
+
+func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
+	l := len(lhs)
+	get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2)
+	if get == nil {
+		return // error reported by unpack
+	}
+	if l != r {
+		check.useGetter(get, r)
+		check.errorf(rhs[0].Pos(), "assignment count mismatch (%d vs %d)", l, r)
+		return
+	}
+
+	var x operand
+	if commaOk {
+		var a [2]Type
+		for i := range a {
+			get(&x, i)
+			a[i] = check.assignVar(lhs[i], &x)
+		}
+		check.recordCommaOkTypes(rhs[0], a)
+		return
+	}
+
+	for i, lhs := range lhs {
+		get(&x, i)
+		check.assignVar(lhs, &x)
+	}
+}
+
+func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
+	scope := check.scope
+
+	// collect lhs variables
+	var newVars []*Var
+	var lhsVars = make([]*Var, len(lhs))
+	for i, lhs := range lhs {
+		var obj *Var
+		if ident, _ := lhs.(*ast.Ident); ident != nil {
+			// Use the correct obj if the ident is redeclared. The
+			// variable's scope starts after the declaration; so we
+			// must use Scope.Lookup here and call Scope.Insert
+			// (via check.declare) later.
+			name := ident.Name
+			if alt := scope.Lookup(name); alt != nil {
+				// redeclared object must be a variable
+				if alt, _ := alt.(*Var); alt != nil {
+					obj = alt
+				} else {
+					check.errorf(lhs.Pos(), "cannot assign to %s", lhs)
+				}
+				check.recordUse(ident, alt)
+			} else {
+				// declare new variable, possibly a blank (_) variable
+				obj = NewVar(ident.Pos(), check.pkg, name, nil)
+				if name != "_" {
+					newVars = append(newVars, obj)
+				}
+				check.recordDef(ident, obj)
+			}
+		} else {
+			check.errorf(lhs.Pos(), "cannot declare %s", lhs)
+		}
+		if obj == nil {
+			obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
+		}
+		lhsVars[i] = obj
+	}
+
+	check.initVars(lhsVars, rhs, token.NoPos)
+
+	// declare new variables
+	if len(newVars) > 0 {
+		for _, obj := range newVars {
+			check.declare(scope, nil, obj) // recordObject already called
+		}
+	} else {
+		check.softErrorf(pos, "no new variables on left side of :=")
+	}
+}
diff --git a/third_party/go.tools/go/types/builtins.go b/third_party/go.tools/go/types/builtins.go
new file mode 100644
index 0000000..ce2ba35
--- /dev/null
+++ b/third_party/go.tools/go/types/builtins.go
@@ -0,0 +1,628 @@
+// 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.
+
+// This file implements typechecking of builtin function calls.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+// builtin type-checks a call to the built-in specified by id and
+// returns true if the call is valid, with *x holding the result;
+// but x.expr is not set. If the call is invalid, the result is
+// false, and *x is undefined.
+//
+func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ bool) {
+	// append is the only built-in that permits the use of ... for the last argument
+	bin := predeclaredFuncs[id]
+	if call.Ellipsis.IsValid() && id != _Append {
+		check.invalidOp(call.Ellipsis, "invalid use of ... with built-in %s", bin.name)
+		check.use(call.Args...)
+		return
+	}
+
+	// For len(x) and cap(x) we need to know if x contains any function calls or
+	// receive operations. Save/restore current setting and set hasCallOrRecv to
+	// false for the evaluation of x so that we can check it afterwards.
+	// Note: We must do this _before_ calling unpack because unpack evaluates the
+	//       first argument before we even call arg(x, 0)!
+	if id == _Len || id == _Cap {
+		defer func(b bool) {
+			check.hasCallOrRecv = b
+		}(check.hasCallOrRecv)
+		check.hasCallOrRecv = false
+	}
+
+	// determine actual arguments
+	var arg getter
+	nargs := len(call.Args)
+	switch id {
+	default:
+		// make argument getter
+		arg, nargs, _ = unpack(func(x *operand, i int) { check.expr(x, call.Args[i]) }, nargs, false)
+		if arg == nil {
+			x.mode = invalid
+			return
+		}
+		// evaluate first argument, if present
+		if nargs > 0 {
+			arg(x, 0)
+			if x.mode == invalid {
+				return
+			}
+		}
+	case _Make, _New, _Offsetof, _Trace:
+		// arguments require special handling
+	}
+
+	// check argument count
+	{
+		msg := ""
+		if nargs < bin.nargs {
+			msg = "not enough"
+		} else if !bin.variadic && nargs > bin.nargs {
+			msg = "too many"
+		}
+		if msg != "" {
+			check.invalidOp(call.Rparen, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs)
+			return
+		}
+	}
+
+	switch id {
+	case _Append:
+		// append(s S, x ...T) S, where T is the element type of S
+		// spec: "The variadic function append appends zero or more values x to s of type
+		// S, which must be a slice type, and returns the resulting slice, also of type S.
+		// The values x are passed to a parameter of type ...T where T is the element type
+		// of S and the respective parameter passing rules apply."
+		S := x.typ
+		var T Type
+		if s, _ := S.Underlying().(*Slice); s != nil {
+			T = s.elem
+		} else {
+			check.invalidArg(x.pos(), "%s is not a slice", x)
+			return
+		}
+
+		// remember arguments that have been evaluated already
+		alist := []operand{*x}
+
+		// spec: "As a special case, append also accepts a first argument assignable
+		// to type []byte with a second argument of string type followed by ... .
+		// This form appends the bytes of the string.
+		if nargs == 2 && call.Ellipsis.IsValid() && x.assignableTo(check.conf, NewSlice(UniverseByte)) {
+			arg(x, 1)
+			if x.mode == invalid {
+				return
+			}
+			if isString(x.typ) {
+				if check.Types != nil {
+					sig := makeSig(S, S, x.typ)
+					sig.variadic = true
+					check.recordBuiltinType(call.Fun, sig)
+				}
+				x.mode = value
+				x.typ = S
+				break
+			}
+			alist = append(alist, *x)
+			// fallthrough
+		}
+
+		// check general case by creating custom signature
+		sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature
+		sig.variadic = true
+		check.arguments(x, call, sig, func(x *operand, i int) {
+			// only evaluate arguments that have not been evaluated before
+			if i < len(alist) {
+				*x = alist[i]
+				return
+			}
+			arg(x, i)
+		}, nargs)
+		// ok to continue even if check.arguments reported errors
+
+		x.mode = value
+		x.typ = S
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, sig)
+		}
+
+	case _Cap, _Len:
+		// cap(x)
+		// len(x)
+		mode := invalid
+		var typ Type
+		var val exact.Value
+		switch typ = implicitArrayDeref(x.typ.Underlying()); t := typ.(type) {
+		case *Basic:
+			if isString(t) && id == _Len {
+				if x.mode == constant {
+					mode = constant
+					val = exact.MakeInt64(int64(len(exact.StringVal(x.val))))
+				} else {
+					mode = value
+				}
+			}
+
+		case *Array:
+			mode = value
+			// spec: "The expressions len(s) and cap(s) are constants
+			// if the type of s is an array or pointer to an array and
+			// the expression s does not contain channel receives or
+			// function calls; in this case s is not evaluated."
+			if !check.hasCallOrRecv {
+				mode = constant
+				val = exact.MakeInt64(t.len)
+			}
+
+		case *Slice, *Chan:
+			mode = value
+
+		case *Map:
+			if id == _Len {
+				mode = value
+			}
+		}
+
+		if mode == invalid {
+			check.invalidArg(x.pos(), "%s for %s", x, bin.name)
+			return
+		}
+
+		x.mode = mode
+		x.typ = Typ[Int]
+		x.val = val
+		if check.Types != nil && mode != constant {
+			check.recordBuiltinType(call.Fun, makeSig(x.typ, typ))
+		}
+
+	case _Close:
+		// close(c)
+		c, _ := x.typ.Underlying().(*Chan)
+		if c == nil {
+			check.invalidArg(x.pos(), "%s is not a channel", x)
+			return
+		}
+		if c.dir == RecvOnly {
+			check.invalidArg(x.pos(), "%s must not be a receive-only channel", x)
+			return
+		}
+
+		x.mode = novalue
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(nil, c))
+		}
+
+	case _Complex:
+		// complex(x, y realT) complexT
+		if !check.complexArg(x) {
+			return
+		}
+
+		var y operand
+		arg(&y, 1)
+		if y.mode == invalid {
+			return
+		}
+		if !check.complexArg(&y) {
+			return
+		}
+
+		check.convertUntyped(x, y.typ)
+		if x.mode == invalid {
+			return
+		}
+		check.convertUntyped(&y, x.typ)
+		if y.mode == invalid {
+			return
+		}
+
+		if !Identical(x.typ, y.typ) {
+			check.invalidArg(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
+			return
+		}
+
+		if x.mode == constant && y.mode == constant {
+			x.val = exact.BinaryOp(x.val, token.ADD, exact.MakeImag(y.val))
+		} else {
+			x.mode = value
+		}
+
+		realT := x.typ
+		complexT := Typ[Invalid]
+		switch realT.Underlying().(*Basic).kind {
+		case Float32:
+			complexT = Typ[Complex64]
+		case Float64:
+			complexT = Typ[Complex128]
+		case UntypedInt, UntypedRune, UntypedFloat:
+			if x.mode == constant {
+				realT = defaultType(realT).(*Basic)
+				complexT = Typ[UntypedComplex]
+			} else {
+				// untyped but not constant; probably because one
+				// operand is a non-constant shift of untyped lhs
+				realT = Typ[Float64]
+				complexT = Typ[Complex128]
+			}
+		default:
+			check.invalidArg(x.pos(), "float32 or float64 arguments expected")
+			return
+		}
+
+		x.typ = complexT
+		if check.Types != nil && x.mode != constant {
+			check.recordBuiltinType(call.Fun, makeSig(complexT, realT, realT))
+		}
+
+		if x.mode != constant {
+			// The arguments have now their final types, which at run-
+			// time will be materialized. Update the expression trees.
+			// If the current types are untyped, the materialized type
+			// is the respective default type.
+			// (If the result is constant, the arguments are never
+			// materialized and there is nothing to do.)
+			check.updateExprType(x.expr, realT, true)
+			check.updateExprType(y.expr, realT, true)
+		}
+
+	case _Copy:
+		// copy(x, y []T) int
+		var dst Type
+		if t, _ := x.typ.Underlying().(*Slice); t != nil {
+			dst = t.elem
+		}
+
+		var y operand
+		arg(&y, 1)
+		if y.mode == invalid {
+			return
+		}
+		var src Type
+		switch t := y.typ.Underlying().(type) {
+		case *Basic:
+			if isString(y.typ) {
+				src = UniverseByte
+			}
+		case *Slice:
+			src = t.elem
+		}
+
+		if dst == nil || src == nil {
+			check.invalidArg(x.pos(), "copy expects slice arguments; found %s and %s", x, &y)
+			return
+		}
+
+		if !Identical(dst, src) {
+			check.invalidArg(x.pos(), "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
+			return
+		}
+
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
+		}
+		x.mode = value
+		x.typ = Typ[Int]
+
+	case _Delete:
+		// delete(m, k)
+		m, _ := x.typ.Underlying().(*Map)
+		if m == nil {
+			check.invalidArg(x.pos(), "%s is not a map", x)
+			return
+		}
+		arg(x, 1) // k
+		if x.mode == invalid {
+			return
+		}
+
+		if !x.assignableTo(check.conf, m.key) {
+			check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.key)
+			return
+		}
+
+		x.mode = novalue
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(nil, m, m.key))
+		}
+
+	case _Imag, _Real:
+		// imag(complexT) realT
+		// real(complexT) realT
+		if !isComplex(x.typ) {
+			check.invalidArg(x.pos(), "%s must be a complex number", x)
+			return
+		}
+		if x.mode == constant {
+			if id == _Real {
+				x.val = exact.Real(x.val)
+			} else {
+				x.val = exact.Imag(x.val)
+			}
+		} else {
+			x.mode = value
+		}
+		var k BasicKind
+		switch x.typ.Underlying().(*Basic).kind {
+		case Complex64:
+			k = Float32
+		case Complex128:
+			k = Float64
+		case UntypedComplex:
+			k = UntypedFloat
+		default:
+			unreachable()
+		}
+
+		if check.Types != nil && x.mode != constant {
+			check.recordBuiltinType(call.Fun, makeSig(Typ[k], x.typ))
+		}
+		x.typ = Typ[k]
+
+	case _Make:
+		// make(T, n)
+		// make(T, n, m)
+		// (no argument evaluated yet)
+		arg0 := call.Args[0]
+		T := check.typ(arg0)
+		if T == Typ[Invalid] {
+			return
+		}
+
+		var min int // minimum number of arguments
+		switch T.Underlying().(type) {
+		case *Slice:
+			min = 2
+		case *Map, *Chan:
+			min = 1
+		default:
+			check.invalidArg(arg0.Pos(), "cannot make %s; type must be slice, map, or channel", arg0)
+			return
+		}
+		if nargs < min || min+1 < nargs {
+			check.errorf(call.Pos(), "%s expects %d or %d arguments; found %d", call, min, min+1, nargs)
+			return
+		}
+		var sizes []int64 // constant integer arguments, if any
+		for _, arg := range call.Args[1:] {
+			if s, ok := check.index(arg, -1); ok && s >= 0 {
+				sizes = append(sizes, s)
+			}
+		}
+		if len(sizes) == 2 && sizes[0] > sizes[1] {
+			check.invalidArg(call.Args[1].Pos(), "length and capacity swapped")
+			// safe to continue
+		}
+		x.mode = value
+		x.typ = T
+		if check.Types != nil {
+			params := [...]Type{T, Typ[Int], Typ[Int]}
+			check.recordBuiltinType(call.Fun, makeSig(x.typ, params[:1+len(sizes)]...))
+		}
+
+	case _New:
+		// new(T)
+		// (no argument evaluated yet)
+		T := check.typ(call.Args[0])
+		if T == Typ[Invalid] {
+			return
+		}
+
+		x.mode = value
+		x.typ = &Pointer{base: T}
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
+		}
+
+	case _Panic:
+		// panic(x)
+		T := new(Interface)
+		if !check.assignment(x, T) {
+			assert(x.mode == invalid)
+			return
+		}
+
+		x.mode = novalue
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(nil, T))
+		}
+
+	case _Print, _Println:
+		// print(x, y, ...)
+		// println(x, y, ...)
+		var params []Type
+		if nargs > 0 {
+			params = make([]Type, nargs)
+			for i := 0; i < nargs; i++ {
+				if i > 0 {
+					arg(x, i) // first argument already evaluated
+				}
+				if !check.assignment(x, nil) {
+					assert(x.mode == invalid)
+					return
+				}
+				params[i] = x.typ
+			}
+		}
+
+		x.mode = novalue
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(nil, params...))
+		}
+
+	case _Recover:
+		// recover() interface{}
+		x.mode = value
+		x.typ = new(Interface)
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(x.typ))
+		}
+
+	case _Alignof:
+		// unsafe.Alignof(x T) uintptr
+		if !check.assignment(x, nil) {
+			assert(x.mode == invalid)
+			return
+		}
+
+		x.mode = constant
+		x.val = exact.MakeInt64(check.conf.alignof(x.typ))
+		x.typ = Typ[Uintptr]
+		// result is constant - no need to record signature
+
+	case _Offsetof:
+		// unsafe.Offsetof(x T) uintptr, where x must be a selector
+		// (no argument evaluated yet)
+		arg0 := call.Args[0]
+		selx, _ := unparen(arg0).(*ast.SelectorExpr)
+		if selx == nil {
+			check.invalidArg(arg0.Pos(), "%s is not a selector expression", arg0)
+			check.use(arg0)
+			return
+		}
+
+		check.expr(x, selx.X)
+		if x.mode == invalid {
+			return
+		}
+
+		base := derefStructPtr(x.typ)
+		sel := selx.Sel.Name
+		obj, index, indirect := LookupFieldOrMethod(base, false, check.pkg, sel)
+		switch obj.(type) {
+		case nil:
+			check.invalidArg(x.pos(), "%s has no single field %s", base, sel)
+			return
+		case *Func:
+			// TODO(gri) Using derefStructPtr may result in methods being found
+			// that don't actually exist. An error either way, but the error
+			// message is confusing. See: http://play.golang.org/p/al75v23kUy ,
+			// but go/types reports: "invalid argument: x.m is a method value".
+			check.invalidArg(arg0.Pos(), "%s is a method value", arg0)
+			return
+		}
+		if indirect {
+			check.invalidArg(x.pos(), "field %s is embedded via a pointer in %s", sel, base)
+			return
+		}
+
+		// TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)?
+		check.recordSelection(selx, FieldVal, base, obj, index, false)
+
+		offs := check.conf.offsetof(base, index)
+		x.mode = constant
+		x.val = exact.MakeInt64(offs)
+		x.typ = Typ[Uintptr]
+		// result is constant - no need to record signature
+
+	case _Sizeof:
+		// unsafe.Sizeof(x T) uintptr
+		if !check.assignment(x, nil) {
+			assert(x.mode == invalid)
+			return
+		}
+
+		x.mode = constant
+		x.val = exact.MakeInt64(check.conf.sizeof(x.typ))
+		x.typ = Typ[Uintptr]
+		// result is constant - no need to record signature
+
+	case _Assert:
+		// assert(pred) causes a typechecker error if pred is false.
+		// The result of assert is the value of pred if there is no error.
+		// Note: assert is only available in self-test mode.
+		if x.mode != constant || !isBoolean(x.typ) {
+			check.invalidArg(x.pos(), "%s is not a boolean constant", x)
+			return
+		}
+		if x.val.Kind() != exact.Bool {
+			check.errorf(x.pos(), "internal error: value of %s should be a boolean constant", x)
+			return
+		}
+		if !exact.BoolVal(x.val) {
+			check.errorf(call.Pos(), "%s failed", call)
+			// compile-time assertion failure - safe to continue
+		}
+		// result is constant - no need to record signature
+
+	case _Trace:
+		// trace(x, y, z, ...) dumps the positions, expressions, and
+		// values of its arguments. The result of trace is the value
+		// of the first argument.
+		// Note: trace is only available in self-test mode.
+		// (no argument evaluated yet)
+		if nargs == 0 {
+			check.dump("%s: trace() without arguments", call.Pos())
+			x.mode = novalue
+			break
+		}
+		var t operand
+		x1 := x
+		for _, arg := range call.Args {
+			check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T))
+			check.dump("%s: %s", x1.pos(), x1)
+			x1 = &t // use incoming x only for first argument
+		}
+		// trace is only available in test mode - no need to record signature
+
+	default:
+		unreachable()
+	}
+
+	return true
+}
+
+// makeSig makes a signature for the given argument and result types.
+// Default types are used for untyped arguments, and res may be nil.
+func makeSig(res Type, args ...Type) *Signature {
+	list := make([]*Var, len(args))
+	for i, param := range args {
+		list[i] = NewVar(token.NoPos, nil, "", defaultType(param))
+	}
+	params := NewTuple(list...)
+	var result *Tuple
+	if res != nil {
+		assert(!isUntyped(res))
+		result = NewTuple(NewVar(token.NoPos, nil, "", res))
+	}
+	return &Signature{params: params, results: result}
+}
+
+// implicitArrayDeref returns A if typ is of the form *A and A is an array;
+// otherwise it returns typ.
+//
+func implicitArrayDeref(typ Type) Type {
+	if p, ok := typ.(*Pointer); ok {
+		if a, ok := p.base.Underlying().(*Array); ok {
+			return a
+		}
+	}
+	return typ
+}
+
+// unparen removes any parentheses surrounding an expression and returns
+// the naked expression.
+//
+func unparen(x ast.Expr) ast.Expr {
+	if p, ok := x.(*ast.ParenExpr); ok {
+		return unparen(p.X)
+	}
+	return x
+}
+
+func (check *Checker) complexArg(x *operand) bool {
+	t, _ := x.typ.Underlying().(*Basic)
+	if t != nil && (t.info&IsFloat != 0 || t.kind == UntypedInt || t.kind == UntypedRune) {
+		return true
+	}
+	check.invalidArg(x.pos(), "%s must be a float32, float64, or an untyped non-complex numeric constant", x)
+	return false
+}
diff --git a/third_party/go.tools/go/types/builtins_test.go b/third_party/go.tools/go/types/builtins_test.go
new file mode 100644
index 0000000..d1e9ece
--- /dev/null
+++ b/third_party/go.tools/go/types/builtins_test.go
@@ -0,0 +1,204 @@
+// Copyright 2013 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 types_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"testing"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var builtinCalls = []struct {
+	name, src, sig string
+}{
+	{"append", `var s []int; _ = append(s)`, `func([]int, ...int) []int`},
+	{"append", `var s []int; _ = append(s, 0)`, `func([]int, ...int) []int`},
+	{"append", `var s []int; _ = (append)(s, 0)`, `func([]int, ...int) []int`},
+	{"append", `var s []byte; _ = ((append))(s, 0)`, `func([]byte, ...byte) []byte`},
+	{"append", `var s []byte; _ = append(s, "foo"...)`, `func([]byte, string...) []byte`},
+	{"append", `type T []byte; var s T; var str string; _ = append(s, str...)`, `func(p.T, string...) p.T`},
+	{"append", `type T []byte; type U string; var s T; var str U; _ = append(s, str...)`, `func(p.T, p.U...) p.T`},
+
+	{"cap", `var s [10]int; _ = cap(s)`, `invalid type`},  // constant
+	{"cap", `var s [10]int; _ = cap(&s)`, `invalid type`}, // constant
+	{"cap", `var s []int64; _ = cap(s)`, `func([]int64) int`},
+	{"cap", `var c chan<-bool; _ = cap(c)`, `func(chan<- bool) int`},
+
+	{"len", `_ = len("foo")`, `invalid type`}, // constant
+	{"len", `var s string; _ = len(s)`, `func(string) int`},
+	{"len", `var s [10]int; _ = len(s)`, `invalid type`},  // constant
+	{"len", `var s [10]int; _ = len(&s)`, `invalid type`}, // constant
+	{"len", `var s []int64; _ = len(s)`, `func([]int64) int`},
+	{"len", `var c chan<-bool; _ = len(c)`, `func(chan<- bool) int`},
+	{"len", `var m map[string]float32; _ = len(m)`, `func(map[string]float32) int`},
+
+	{"close", `var c chan int; close(c)`, `func(chan int)`},
+	{"close", `var c chan<- chan string; close(c)`, `func(chan<- chan string)`},
+
+	{"complex", `_ = complex(1, 0)`, `invalid type`}, // constant
+	{"complex", `var re float32; _ = complex(re, 1.0)`, `func(float32, float32) complex64`},
+	{"complex", `var im float64; _ = complex(1, im)`, `func(float64, float64) complex128`},
+	{"complex", `type F32 float32; var re, im F32; _ = complex(re, im)`, `func(p.F32, p.F32) complex64`},
+	{"complex", `type F64 float64; var re, im F64; _ = complex(re, im)`, `func(p.F64, p.F64) complex128`},
+
+	{"copy", `var src, dst []byte; copy(dst, src)`, `func([]byte, []byte) int`},
+	{"copy", `type T [][]int; var src, dst T; _ = copy(dst, src)`, `func(p.T, p.T) int`},
+	{"copy", `var src string; var dst []byte; copy(dst, src)`, `func([]byte, string) int`},
+	{"copy", `type T string; type U []byte; var src T; var dst U; copy(dst, src)`, `func(p.U, p.T) int`},
+	{"copy", `var dst []byte; copy(dst, "hello")`, `func([]byte, string) int`},
+
+	{"delete", `var m map[string]bool; delete(m, "foo")`, `func(map[string]bool, string)`},
+	{"delete", `type (K string; V int); var m map[K]V; delete(m, "foo")`, `func(map[p.K]p.V, p.K)`},
+
+	{"imag", `_ = imag(1i)`, `invalid type`}, // constant
+	{"imag", `var c complex64; _ = imag(c)`, `func(complex64) float32`},
+	{"imag", `var c complex128; _ = imag(c)`, `func(complex128) float64`},
+	{"imag", `type C64 complex64; var c C64; _ = imag(c)`, `func(p.C64) float32`},
+	{"imag", `type C128 complex128; var c C128; _ = imag(c)`, `func(p.C128) float64`},
+
+	{"real", `_ = real(1i)`, `invalid type`}, // constant
+	{"real", `var c complex64; _ = real(c)`, `func(complex64) float32`},
+	{"real", `var c complex128; _ = real(c)`, `func(complex128) float64`},
+	{"real", `type C64 complex64; var c C64; _ = real(c)`, `func(p.C64) float32`},
+	{"real", `type C128 complex128; var c C128; _ = real(c)`, `func(p.C128) float64`},
+
+	{"make", `_ = make([]int, 10)`, `func([]int, int) []int`},
+	{"make", `type T []byte; _ = make(T, 10, 20)`, `func(p.T, int, int) p.T`},
+
+	{"new", `_ = new(int)`, `func(int) *int`},
+	{"new", `type T struct{}; _ = new(T)`, `func(p.T) *p.T`},
+
+	{"panic", `panic(0)`, `func(interface{})`},
+	{"panic", `panic("foo")`, `func(interface{})`},
+
+	{"print", `print()`, `func()`},
+	{"print", `print(0)`, `func(int)`},
+	{"print", `print(1, 2.0, "foo", true)`, `func(int, float64, string, bool)`},
+
+	{"println", `println()`, `func()`},
+	{"println", `println(0)`, `func(int)`},
+	{"println", `println(1, 2.0, "foo", true)`, `func(int, float64, string, bool)`},
+
+	{"recover", `recover()`, `func() interface{}`},
+	{"recover", `_ = recover()`, `func() interface{}`},
+
+	{"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`},                 // constant
+	{"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant
+
+	{"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`},           // constant
+	{"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant
+
+	{"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`},                 // constant
+	{"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant
+
+	{"assert", `assert(true)`, `invalid type`},                                    // constant
+	{"assert", `type B bool; const pred B = 1 < 2; assert(pred)`, `invalid type`}, // constant
+
+	// no tests for trace since it produces output as a side-effect
+}
+
+func TestBuiltinSignatures(t *testing.T) {
+	DefPredeclaredTestFuncs()
+
+	seen := map[string]bool{"trace": true} // no test for trace built-in; add it manually
+	for _, call := range builtinCalls {
+		testBuiltinSignature(t, call.name, call.src, call.sig)
+		seen[call.name] = true
+	}
+
+	// make sure we didn't miss one
+	for _, name := range Universe.Names() {
+		if _, ok := Universe.Lookup(name).(*Builtin); ok && !seen[name] {
+			t.Errorf("missing test for %s", name)
+		}
+	}
+	for _, name := range Unsafe.Scope().Names() {
+		if _, ok := Unsafe.Scope().Lookup(name).(*Builtin); ok && !seen[name] {
+			t.Errorf("missing test for unsafe.%s", name)
+		}
+	}
+}
+
+func testBuiltinSignature(t *testing.T, name, src0, want string) {
+	src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _() { %s }`, src0)
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Errorf("%s: %s", src0, err)
+		return
+	}
+
+	var conf Config
+	uses := make(map[*ast.Ident]Object)
+	types := make(map[ast.Expr]TypeAndValue)
+	_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Uses: uses, Types: types})
+	if err != nil {
+		t.Errorf("%s: %s", src0, err)
+		return
+	}
+
+	// find called function
+	n := 0
+	var fun ast.Expr
+	for x := range types {
+		if call, _ := x.(*ast.CallExpr); call != nil {
+			fun = call.Fun
+			n++
+		}
+	}
+	if n != 1 {
+		t.Errorf("%s: got %d CallExprs; want 1", src0, n)
+		return
+	}
+
+	// check recorded types for fun and descendents (may be parenthesized)
+	for {
+		// the recorded type for the built-in must match the wanted signature
+		typ := types[fun].Type
+		if typ == nil {
+			t.Errorf("%s: no type recorded for %s", src0, ExprString(fun))
+			return
+		}
+		if got := typ.String(); got != want {
+			t.Errorf("%s: got type %s; want %s", src0, got, want)
+			return
+		}
+
+		// called function must be a (possibly parenthesized, qualified)
+		// identifier denoting the expected built-in
+		switch p := fun.(type) {
+		case *ast.Ident:
+			obj := uses[p]
+			if obj == nil {
+				t.Errorf("%s: no object found for %s", src0, p)
+				return
+			}
+			bin, _ := obj.(*Builtin)
+			if bin == nil {
+				t.Errorf("%s: %s does not denote a built-in", src0, p)
+				return
+			}
+			if bin.Name() != name {
+				t.Errorf("%s: got built-in %s; want %s", src0, bin.Name(), name)
+				return
+			}
+			return // we're done
+
+		case *ast.ParenExpr:
+			fun = p.X // unpack
+
+		case *ast.SelectorExpr:
+			// built-in from package unsafe - ignore details
+			return // we're done
+
+		default:
+			t.Errorf("%s: invalid function call", src0)
+			return
+		}
+	}
+}
diff --git a/third_party/go.tools/go/types/call.go b/third_party/go.tools/go/types/call.go
new file mode 100644
index 0000000..a392d91
--- /dev/null
+++ b/third_party/go.tools/go/types/call.go
@@ -0,0 +1,427 @@
+// Copyright 2013 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.
+
+// This file implements typechecking of call and selector expressions.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
+	check.exprOrType(x, e.Fun)
+
+	switch x.mode {
+	case invalid:
+		check.use(e.Args...)
+		x.mode = invalid
+		x.expr = e
+		return statement
+
+	case typexpr:
+		// conversion
+		T := x.typ
+		x.mode = invalid
+		switch n := len(e.Args); n {
+		case 0:
+			check.errorf(e.Rparen, "missing argument in conversion to %s", T)
+		case 1:
+			check.expr(x, e.Args[0])
+			if x.mode != invalid {
+				check.conversion(x, T)
+			}
+		default:
+			check.errorf(e.Args[n-1].Pos(), "too many arguments in conversion to %s", T)
+		}
+		x.expr = e
+		return conversion
+
+	case builtin:
+		id := x.id
+		if !check.builtin(x, e, id) {
+			x.mode = invalid
+		}
+		x.expr = e
+		// a non-constant result implies a function call
+		if x.mode != invalid && x.mode != constant {
+			check.hasCallOrRecv = true
+		}
+		return predeclaredFuncs[id].kind
+
+	default:
+		// function/method call
+		sig, _ := x.typ.Underlying().(*Signature)
+		if sig == nil {
+			check.invalidOp(x.pos(), "cannot call non-function %s", x)
+			x.mode = invalid
+			x.expr = e
+			return statement
+		}
+
+		arg, n, _ := unpack(func(x *operand, i int) { check.expr(x, e.Args[i]) }, len(e.Args), false)
+		if arg == nil {
+			x.mode = invalid
+			x.expr = e
+			return statement
+		}
+
+		check.arguments(x, e, sig, arg, n)
+
+		// determine result
+		switch sig.results.Len() {
+		case 0:
+			x.mode = novalue
+		case 1:
+			x.mode = value
+			x.typ = sig.results.vars[0].typ // unpack tuple
+		default:
+			x.mode = value
+			x.typ = sig.results
+		}
+		x.expr = e
+		check.hasCallOrRecv = true
+
+		return statement
+	}
+}
+
+// use type-checks each argument.
+// Useful to make sure expressions are evaluated
+// (and variables are "used") in the presence of other errors.
+func (check *Checker) use(arg ...ast.Expr) {
+	var x operand
+	for _, e := range arg {
+		check.rawExpr(&x, e, nil)
+	}
+}
+
+// useGetter is like use, but takes a getter instead of a list of expressions.
+// It should be called instead of use if a getter is present to avoid repeated
+// evaluation of the first argument (since the getter was likely obtained via
+// unpack, which may have evaluated the first argument already).
+func (check *Checker) useGetter(get getter, n int) {
+	var x operand
+	for i := 0; i < n; i++ {
+		get(&x, i)
+	}
+}
+
+// A getter sets x as the i'th operand, where 0 <= i < n and n is the total
+// number of operands (context-specific, and maintained elsewhere). A getter
+// type-checks the i'th operand; the details of the actual check are getter-
+// specific.
+type getter func(x *operand, i int)
+
+// unpack takes a getter get and a number of operands n. If n == 1, unpack
+// calls the incoming getter for the first operand. If that operand is
+// invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a
+// function call, or a comma-ok expression and allowCommaOk is set, the result
+// is a new getter and operand count providing access to the function results,
+// or comma-ok values, respectively. The third result value reports if it
+// is indeed the comma-ok case. In all other cases, the incoming getter and
+// operand count are returned unchanged, and the third result value is false.
+//
+// In other words, if there's exactly one operand that - after type-checking
+// by calling get - stands for multiple operands, the resulting getter provides
+// access to those operands instead.
+//
+// If the returned getter is called at most once for a given operand index i
+// (including i == 0), that operand is guaranteed to cause only one call of
+// the incoming getter with that i.
+//
+func unpack(get getter, n int, allowCommaOk bool) (getter, int, bool) {
+	if n == 1 {
+		// possibly result of an n-valued function call or comma,ok value
+		var x0 operand
+		get(&x0, 0)
+		if x0.mode == invalid {
+			return nil, 0, false
+		}
+
+		if t, ok := x0.typ.(*Tuple); ok {
+			// result of an n-valued function call
+			return func(x *operand, i int) {
+				x.mode = value
+				x.expr = x0.expr
+				x.typ = t.At(i).typ
+			}, t.Len(), false
+		}
+
+		if x0.mode == mapindex || x0.mode == commaok {
+			// comma-ok value
+			if allowCommaOk {
+				a := [2]Type{x0.typ, Typ[UntypedBool]}
+				return func(x *operand, i int) {
+					x.mode = value
+					x.expr = x0.expr
+					x.typ = a[i]
+				}, 2, true
+			}
+			x0.mode = value
+		}
+
+		// single value
+		return func(x *operand, i int) {
+			if i != 0 {
+				unreachable()
+			}
+			*x = x0
+		}, 1, false
+	}
+
+	// zero or multiple values
+	return get, n, false
+}
+
+// arguments checks argument passing for the call with the given signature.
+// The arg function provides the operand for the i'th argument.
+func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, arg getter, n int) {
+	passSlice := false
+	if call.Ellipsis.IsValid() {
+		// last argument is of the form x...
+		if sig.variadic {
+			passSlice = true
+		} else {
+			check.errorf(call.Ellipsis, "cannot use ... in call to non-variadic %s", call.Fun)
+			// ok to continue
+		}
+	}
+
+	// evaluate arguments
+	for i := 0; i < n; i++ {
+		arg(x, i)
+		if x.mode != invalid {
+			check.argument(sig, i, x, passSlice && i == n-1)
+		}
+	}
+
+	// check argument count
+	if sig.variadic {
+		// a variadic function accepts an "empty"
+		// last argument: count one extra
+		n++
+	}
+	if n < sig.params.Len() {
+		check.errorf(call.Rparen, "too few arguments in call to %s", call.Fun)
+		// ok to continue
+	}
+}
+
+// argument checks passing of argument x to the i'th parameter of the given signature.
+// If passSlice is set, the argument is followed by ... in the call.
+func (check *Checker) argument(sig *Signature, i int, x *operand, passSlice bool) {
+	n := sig.params.Len()
+
+	// determine parameter type
+	var typ Type
+	switch {
+	case i < n:
+		typ = sig.params.vars[i].typ
+	case sig.variadic:
+		typ = sig.params.vars[n-1].typ
+		if debug {
+			if _, ok := typ.(*Slice); !ok {
+				check.dump("%s: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ)
+			}
+		}
+	default:
+		check.errorf(x.pos(), "too many arguments")
+		return
+	}
+
+	if passSlice {
+		// argument is of the form x...
+		if i != n-1 {
+			check.errorf(x.pos(), "can only use ... with matching parameter")
+			return
+		}
+		if _, ok := x.typ.Underlying().(*Slice); !ok {
+			check.errorf(x.pos(), "cannot use %s as parameter of type %s", x, typ)
+			return
+		}
+	} else if sig.variadic && i >= n-1 {
+		// use the variadic parameter slice's element type
+		typ = typ.(*Slice).elem
+	}
+
+	if !check.assignment(x, typ) && x.mode != invalid {
+		check.errorf(x.pos(), "cannot pass argument %s to parameter of type %s", x, typ)
+	}
+}
+
+func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
+	// these must be declared before the "goto Error" statements
+	var (
+		obj      Object
+		index    []int
+		indirect bool
+	)
+
+	sel := e.Sel.Name
+	// If the identifier refers to a package, handle everything here
+	// so we don't need a "package" mode for operands: package names
+	// can only appear in qualified identifiers which are mapped to
+	// selector expressions.
+	if ident, ok := e.X.(*ast.Ident); ok {
+		_, obj := check.scope.LookupParent(ident.Name)
+		if pkg, _ := obj.(*PkgName); pkg != nil {
+			assert(pkg.pkg == check.pkg)
+			check.recordUse(ident, pkg)
+			pkg.used = true
+			exp := pkg.imported.scope.Lookup(sel)
+			if exp == nil {
+				if !pkg.imported.fake {
+					check.errorf(e.Pos(), "%s not declared by package %s", sel, ident)
+				}
+				goto Error
+			}
+			if !exp.Exported() {
+				check.errorf(e.Pos(), "%s not exported by package %s", sel, ident)
+				// ok to continue
+			}
+			check.recordUse(e.Sel, exp)
+			// Simplified version of the code for *ast.Idents:
+			// - imported objects are always fully initialized
+			switch exp := exp.(type) {
+			case *Const:
+				assert(exp.Val() != nil)
+				x.mode = constant
+				x.typ = exp.typ
+				x.val = exp.val
+			case *TypeName:
+				x.mode = typexpr
+				x.typ = exp.typ
+			case *Var:
+				x.mode = variable
+				x.typ = exp.typ
+			case *Func:
+				x.mode = value
+				x.typ = exp.typ
+			case *Builtin:
+				x.mode = builtin
+				x.typ = exp.typ
+				x.id = exp.id
+			default:
+				unreachable()
+			}
+			x.expr = e
+			return
+		}
+	}
+
+	check.exprOrType(x, e.X)
+	if x.mode == invalid {
+		goto Error
+	}
+
+	obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
+	if obj == nil {
+		switch {
+		case index != nil:
+			// TODO(gri) should provide actual type where the conflict happens
+			check.invalidOp(e.Pos(), "ambiguous selector %s", sel)
+		case indirect:
+			check.invalidOp(e.Pos(), "%s is not in method set of %s", sel, x.typ)
+		default:
+			check.invalidOp(e.Pos(), "%s has no field or method %s", x, sel)
+		}
+		goto Error
+	}
+
+	if x.mode == typexpr {
+		// method expression
+		m, _ := obj.(*Func)
+		if m == nil {
+			check.invalidOp(e.Pos(), "%s has no method %s", x, sel)
+			goto Error
+		}
+
+		check.recordSelection(e, MethodExpr, x.typ, m, index, indirect)
+
+		// the receiver type becomes the type of the first function
+		// argument of the method expression's function type
+		var params []*Var
+		sig := m.typ.(*Signature)
+		if sig.params != nil {
+			params = sig.params.vars
+		}
+		x.mode = value
+		x.typ = &Signature{
+			params:   NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "", x.typ)}, params...)...),
+			results:  sig.results,
+			variadic: sig.variadic,
+		}
+
+		check.addDeclDep(m)
+
+	} else {
+		// regular selector
+		switch obj := obj.(type) {
+		case *Var:
+			check.recordSelection(e, FieldVal, x.typ, obj, index, indirect)
+			if x.mode == variable || indirect {
+				x.mode = variable
+			} else {
+				x.mode = value
+			}
+			x.typ = obj.typ
+
+		case *Func:
+			// TODO(gri) If we needed to take into account the receiver's
+			// addressability, should we report the type &(x.typ) instead?
+			check.recordSelection(e, MethodVal, x.typ, obj, index, indirect)
+
+			if debug {
+				// Verify that LookupFieldOrMethod and MethodSet.Lookup agree.
+				typ := x.typ
+				if x.mode == variable {
+					// If typ is not an (unnamed) pointer or an interface,
+					// use *typ instead, because the method set of *typ
+					// includes the methods of typ.
+					// Variables are addressable, so we can always take their
+					// address.
+					if _, ok := typ.(*Pointer); !ok && !isInterface(typ) {
+						typ = &Pointer{base: typ}
+					}
+				}
+				// If we created a synthetic pointer type above, we will throw
+				// away the method set computed here after use.
+				// TODO(gri) Method set computation should probably always compute
+				// both, the value and the pointer receiver method set and represent
+				// them in a single structure.
+				// TODO(gri) Consider also using a method set cache for the lifetime
+				// of checker once we rely on MethodSet lookup instead of individual
+				// lookup.
+				mset := NewMethodSet(typ)
+				if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj {
+					check.dump("%s: (%s).%v -> %s", e.Pos(), typ, obj.name, m)
+					check.dump("%s\n", mset)
+					panic("method sets and lookup don't agree")
+				}
+			}
+
+			x.mode = value
+
+			// remove receiver
+			sig := *obj.typ.(*Signature)
+			sig.recv = nil
+			x.typ = &sig
+
+			check.addDeclDep(obj)
+
+		default:
+			unreachable()
+		}
+	}
+
+	// everything went well
+	x.expr = e
+	return
+
+Error:
+	x.mode = invalid
+	x.expr = e
+}
diff --git a/third_party/go.tools/go/types/check.go b/third_party/go.tools/go/types/check.go
new file mode 100644
index 0000000..40fa7ff
--- /dev/null
+++ b/third_party/go.tools/go/types/check.go
@@ -0,0 +1,361 @@
+// 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.
+
+// This file implements the Check function, which drives type-checking.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+// debugging/development support
+const (
+	debug = false // leave on during development
+	trace = false // turn on for detailed type resolution traces
+)
+
+// If Strict is set, the type-checker enforces additional
+// rules not specified by the Go 1 spec, but which will
+// catch guaranteed run-time errors if the respective
+// code is executed. In other words, programs passing in
+// Strict mode are Go 1 compliant, but not all Go 1 programs
+// will pass in Strict mode. The additional rules are:
+//
+// - A type assertion x.(T) where T is an interface type
+//   is invalid if any (statically known) method that exists
+//   for both x and T have different signatures.
+//
+const strict = false
+
+// exprInfo stores information about an untyped expression.
+type exprInfo struct {
+	isLhs bool // expression is lhs operand of a shift with delayed type-check
+	mode  operandMode
+	typ   *Basic
+	val   exact.Value // constant value; or nil (if not a constant)
+}
+
+// funcInfo stores the information required for type-checking a function.
+type funcInfo struct {
+	name string    // for debugging/tracing only
+	decl *declInfo // for cycle detection
+	sig  *Signature
+	body *ast.BlockStmt
+}
+
+// A context represents the context within which an object is type-checked.
+type context struct {
+	decl          *declInfo   // package-level declaration whose init expression/function body is checked
+	scope         *Scope      // top-most scope for lookups
+	iota          exact.Value // value of iota in a constant declaration; nil otherwise
+	sig           *Signature  // function signature if inside a function; nil otherwise
+	hasLabel      bool        // set if a function makes use of labels (only ~1% of functions); unused outside functions
+	hasCallOrRecv bool        // set if an expression contains a function call or channel receive operation
+}
+
+// A Checker maintains the state of the type checker.
+// It must be created with NewChecker.
+type Checker struct {
+	// package information
+	// (initialized by NewChecker, valid for the life-time of checker)
+	conf *Config
+	fset *token.FileSet
+	pkg  *Package
+	*Info
+	objMap map[Object]*declInfo // maps package-level object to declaration info
+
+	// information collected during type-checking of a set of package files
+	// (initialized by Files, valid only for the duration of check.Files;
+	// maps and lists are allocated on demand)
+	files            []*ast.File                       // package files
+	unusedDotImports map[*Scope]map[*Package]token.Pos // positions of unused dot-imported packages for each file scope
+
+	firstErr error                 // first error encountered
+	methods  map[string][]*Func    // maps type names to associated methods
+	untyped  map[ast.Expr]exprInfo // map of expressions without final type
+	funcs    []funcInfo            // list of functions to type-check
+	delayed  []func()              // delayed checks requiring fully setup types
+
+	// context within which the current object is type-checked
+	// (valid only for the duration of type-checking a specific object)
+	context
+
+	// debugging
+	indent int // indentation for tracing
+}
+
+// addUnusedImport adds the position of a dot-imported package
+// pkg to the map of dot imports for the given file scope.
+func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, pos token.Pos) {
+	mm := check.unusedDotImports
+	if mm == nil {
+		mm = make(map[*Scope]map[*Package]token.Pos)
+		check.unusedDotImports = mm
+	}
+	m := mm[scope]
+	if m == nil {
+		m = make(map[*Package]token.Pos)
+		mm[scope] = m
+	}
+	m[pkg] = pos
+}
+
+// addDeclDep adds the dependency edge (check.decl -> to) if check.decl exists
+func (check *Checker) addDeclDep(to Object) {
+	from := check.decl
+	if from == nil {
+		return // not in a package-level init expression
+	}
+	if _, found := check.objMap[to]; !found {
+		return // to is not a package-level object
+	}
+	from.addDep(to)
+}
+
+func (check *Checker) assocMethod(tname string, meth *Func) {
+	m := check.methods
+	if m == nil {
+		m = make(map[string][]*Func)
+		check.methods = m
+	}
+	m[tname] = append(m[tname], meth)
+}
+
+func (check *Checker) rememberUntyped(e ast.Expr, lhs bool, mode operandMode, typ *Basic, val exact.Value) {
+	m := check.untyped
+	if m == nil {
+		m = make(map[ast.Expr]exprInfo)
+		check.untyped = m
+	}
+	m[e] = exprInfo{lhs, mode, typ, val}
+}
+
+func (check *Checker) later(name string, decl *declInfo, sig *Signature, body *ast.BlockStmt) {
+	check.funcs = append(check.funcs, funcInfo{name, decl, sig, body})
+}
+
+func (check *Checker) delay(f func()) {
+	check.delayed = append(check.delayed, f)
+}
+
+// NewChecker returns a new Checker instance for a given package.
+// Package files may be added incrementally via checker.Files.
+func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Checker {
+	// make sure we have a configuration
+	if conf == nil {
+		conf = new(Config)
+	}
+
+	// make sure we have a package canonicalization map
+	if conf.Packages == nil {
+		conf.Packages = make(map[string]*Package)
+	}
+
+	// make sure we have an info struct
+	if info == nil {
+		info = new(Info)
+	}
+
+	return &Checker{
+		conf:   conf,
+		fset:   fset,
+		pkg:    pkg,
+		Info:   info,
+		objMap: make(map[Object]*declInfo),
+	}
+}
+
+// initFiles initializes the files-specific portion of checker.
+// The provided files must all belong to the same package.
+func (check *Checker) initFiles(files []*ast.File) {
+	// start with a clean slate (check.Files may be called multiple times)
+	check.files = nil
+	check.unusedDotImports = nil
+
+	check.firstErr = nil
+	check.methods = nil
+	check.untyped = nil
+	check.funcs = nil
+	check.delayed = nil
+
+	// determine package name and collect valid files
+	pkg := check.pkg
+	for _, file := range files {
+		switch name := file.Name.Name; pkg.name {
+		case "":
+			if name != "_" {
+				pkg.name = name
+			} else {
+				check.errorf(file.Name.Pos(), "invalid package name _")
+			}
+			fallthrough
+
+		case name:
+			check.files = append(check.files, file)
+
+		default:
+			check.errorf(file.Package, "package %s; expected %s", name, pkg.name)
+			// ignore this file
+		}
+	}
+}
+
+// A bailout panic is used for early termination.
+type bailout struct{}
+
+func (check *Checker) handleBailout(err *error) {
+	switch p := recover().(type) {
+	case nil, bailout:
+		// normal return or early exit
+		*err = check.firstErr
+	default:
+		// re-panic
+		panic(p)
+	}
+}
+
+// Files checks the provided files as part of the checker's package.
+func (check *Checker) Files(files []*ast.File) (err error) {
+	defer check.handleBailout(&err)
+
+	check.initFiles(files)
+
+	check.collectObjects()
+
+	check.packageObjects(check.resolveOrder())
+
+	check.functionBodies()
+
+	check.initOrder()
+
+	check.unusedImports()
+
+	// perform delayed checks
+	for _, f := range check.delayed {
+		f()
+	}
+
+	check.recordUntyped()
+
+	check.pkg.complete = true
+	return
+}
+
+func (check *Checker) recordUntyped() {
+	if !debug && check.Types == nil {
+		return // nothing to do
+	}
+
+	for x, info := range check.untyped {
+		if debug && isTyped(info.typ) {
+			check.dump("%s: %s (type %s) is typed", x.Pos(), x, info.typ)
+			unreachable()
+		}
+		check.recordTypeAndValue(x, info.mode, info.typ, info.val)
+	}
+}
+
+func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type, val exact.Value) {
+	assert(x != nil)
+	assert(typ != nil)
+	if mode == invalid {
+		return // omit
+	}
+	assert(typ != nil)
+	if mode == constant {
+		assert(val != nil)
+		assert(typ == Typ[Invalid] || isConstType(typ))
+	}
+	if m := check.Types; m != nil {
+		m[x] = TypeAndValue{mode, typ, val}
+	}
+}
+
+func (check *Checker) recordBuiltinType(f ast.Expr, sig *Signature) {
+	// f must be a (possibly parenthesized) identifier denoting a built-in
+	// (built-ins in package unsafe always produce a constant result and
+	// we don't record their signatures, so we don't see qualified idents
+	// here): record the signature for f and possible children.
+	for {
+		check.recordTypeAndValue(f, builtin, sig, nil)
+		switch p := f.(type) {
+		case *ast.Ident:
+			return // we're done
+		case *ast.ParenExpr:
+			f = p.X
+		default:
+			unreachable()
+		}
+	}
+}
+
+func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) {
+	assert(x != nil)
+	if a[0] == nil || a[1] == nil {
+		return
+	}
+	assert(isTyped(a[0]) && isTyped(a[1]) && isBoolean(a[1]))
+	if m := check.Types; m != nil {
+		for {
+			tv := m[x]
+			assert(tv.Type != nil) // should have been recorded already
+			pos := x.Pos()
+			tv.Type = NewTuple(
+				NewVar(pos, check.pkg, "", a[0]),
+				NewVar(pos, check.pkg, "", a[1]),
+			)
+			m[x] = tv
+			// if x is a parenthesized expression (p.X), update p.X
+			p, _ := x.(*ast.ParenExpr)
+			if p == nil {
+				break
+			}
+			x = p.X
+		}
+	}
+}
+
+func (check *Checker) recordDef(id *ast.Ident, obj Object) {
+	assert(id != nil)
+	if m := check.Defs; m != nil {
+		m[id] = obj
+	}
+}
+
+func (check *Checker) recordUse(id *ast.Ident, obj Object) {
+	assert(id != nil)
+	assert(obj != nil)
+	if m := check.Uses; m != nil {
+		m[id] = obj
+	}
+}
+
+func (check *Checker) recordImplicit(node ast.Node, obj Object) {
+	assert(node != nil)
+	assert(obj != nil)
+	if m := check.Implicits; m != nil {
+		m[node] = obj
+	}
+}
+
+func (check *Checker) recordSelection(x *ast.SelectorExpr, kind SelectionKind, recv Type, obj Object, index []int, indirect bool) {
+	assert(obj != nil && (recv == nil || len(index) > 0))
+	check.recordUse(x.Sel, obj)
+	// TODO(gri) Should we also call recordTypeAndValue?
+	if m := check.Selections; m != nil {
+		m[x] = &Selection{kind, recv, obj, index, indirect}
+	}
+}
+
+func (check *Checker) recordScope(node ast.Node, scope *Scope) {
+	assert(node != nil)
+	assert(scope != nil)
+	if m := check.Scopes; m != nil {
+		m[node] = scope
+	}
+}
diff --git a/third_party/go.tools/go/types/check_test.go b/third_party/go.tools/go/types/check_test.go
new file mode 100644
index 0000000..8a9b873
--- /dev/null
+++ b/third_party/go.tools/go/types/check_test.go
@@ -0,0 +1,294 @@
+// 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.
+
+// This file implements a typechecker test harness. The packages specified
+// in tests are typechecked. Error messages reported by the typechecker are
+// compared against the error messages expected in the test files.
+//
+// Expected errors are indicated in the test files by putting a comment
+// of the form /* ERROR "rx" */ immediately following an offending token.
+// The harness will verify that an error matching the regular expression
+// rx is reported at that source position. Consecutive comments may be
+// used to indicate multiple errors for the same token position.
+//
+// For instance, the following test file indicates that a "not declared"
+// error should be reported for the undeclared variable x:
+//
+//	package p
+//	func f() {
+//		_ = x /* ERROR "not declared" */ + 1
+//	}
+
+// TODO(gri) Also collect strict mode errors of the form /* STRICT ... */
+//           and test against strict mode.
+
+package types_test
+
+import (
+	"flag"
+	"go/ast"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"regexp"
+	"strings"
+	"testing"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var (
+	listErrors = flag.Bool("list", false, "list errors")
+	testFiles  = flag.String("files", "", "space-separated list of test files")
+)
+
+// The test filenames do not end in .go so that they are invisible
+// to gofmt since they contain comments that must not change their
+// positions relative to surrounding tokens.
+
+// Each tests entry is list of files belonging to the same package.
+var tests = [][]string{
+	{"testdata/errors.src"},
+	{"testdata/importdecl0a.src", "testdata/importdecl0b.src"},
+	{"testdata/importdecl1a.src", "testdata/importdecl1b.src"},
+	{"testdata/cycles.src"},
+	{"testdata/cycles1.src"},
+	{"testdata/cycles2.src"},
+	{"testdata/cycles3.src"},
+	{"testdata/cycles4.src"},
+	{"testdata/init0.src"},
+	{"testdata/init1.src"},
+	{"testdata/init2.src"},
+	{"testdata/decls0.src"},
+	{"testdata/decls1.src"},
+	{"testdata/decls2a.src", "testdata/decls2b.src"},
+	{"testdata/decls3.src"},
+	{"testdata/const0.src"},
+	{"testdata/const1.src"},
+	{"testdata/constdecl.src"},
+	{"testdata/vardecl.src"},
+	{"testdata/expr0.src"},
+	{"testdata/expr1.src"},
+	{"testdata/expr2.src"},
+	{"testdata/expr3.src"},
+	{"testdata/methodsets.src"},
+	{"testdata/shifts.src"},
+	{"testdata/builtins.src"},
+	{"testdata/conversions.src"},
+	{"testdata/stmt0.src"},
+	{"testdata/stmt1.src"},
+	{"testdata/gotos.src"},
+	{"testdata/labels.src"},
+	{"testdata/issues.src"},
+	{"testdata/blank.src"},
+}
+
+var fset = token.NewFileSet()
+
+// Positioned errors are of the form filename:line:column: message .
+var posMsgRx = regexp.MustCompile(`^(.*:[0-9]+:[0-9]+): *(.*)`)
+
+// splitError splits an error's error message into a position string
+// and the actual error message. If there's no position information,
+// pos is the empty string, and msg is the entire error message.
+//
+func splitError(err error) (pos, msg string) {
+	msg = err.Error()
+	if m := posMsgRx.FindStringSubmatch(msg); len(m) == 3 {
+		pos = m[1]
+		msg = m[2]
+	}
+	return
+}
+
+func parseFiles(t *testing.T, filenames []string) ([]*ast.File, []error) {
+	var files []*ast.File
+	var errlist []error
+	for _, filename := range filenames {
+		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
+		if file == nil {
+			t.Fatalf("%s: %s", filename, err)
+		}
+		files = append(files, file)
+		if err != nil {
+			if list, _ := err.(scanner.ErrorList); len(list) > 0 {
+				for _, err := range list {
+					errlist = append(errlist, err)
+				}
+			} else {
+				errlist = append(errlist, err)
+			}
+		}
+	}
+	return files, errlist
+}
+
+// ERROR comments must start with text `ERROR "rx"` or `ERROR rx` where
+// rx is a regular expression that matches the expected error message.
+// Space around "rx" or rx is ignored. Use the form `ERROR HERE "rx"`
+// for error messages that are located immediately after rather than
+// at a token's position.
+//
+var errRx = regexp.MustCompile(`^ *ERROR *(HERE)? *"?([^"]*)"?`)
+
+// errMap collects the regular expressions of ERROR comments found
+// in files and returns them as a map of error positions to error messages.
+//
+func errMap(t *testing.T, testname string, files []*ast.File) map[string][]string {
+	// map of position strings to lists of error message patterns
+	errmap := make(map[string][]string)
+
+	for _, file := range files {
+		filename := fset.Position(file.Package).Filename
+		src, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Fatalf("%s: could not read %s", testname, filename)
+		}
+
+		var s scanner.Scanner
+		s.Init(fset.AddFile(filename, -1, len(src)), src, nil, scanner.ScanComments)
+		var prev token.Pos // position of last non-comment, non-semicolon token
+		var here token.Pos // position immediately after the token at position prev
+
+	scanFile:
+		for {
+			pos, tok, lit := s.Scan()
+			switch tok {
+			case token.EOF:
+				break scanFile
+			case token.COMMENT:
+				if lit[1] == '*' {
+					lit = lit[:len(lit)-2] // strip trailing */
+				}
+				if s := errRx.FindStringSubmatch(lit[2:]); len(s) == 3 {
+					pos := prev
+					if s[1] == "HERE" {
+						pos = here
+					}
+					p := fset.Position(pos).String()
+					errmap[p] = append(errmap[p], strings.TrimSpace(s[2]))
+				}
+			case token.SEMICOLON:
+				// ignore automatically inserted semicolon
+				if lit == "\n" {
+					continue scanFile
+				}
+				fallthrough
+			default:
+				prev = pos
+				var l int // token length
+				if tok.IsLiteral() {
+					l = len(lit)
+				} else {
+					l = len(tok.String())
+				}
+				here = prev + token.Pos(l)
+			}
+		}
+	}
+
+	return errmap
+}
+
+func eliminate(t *testing.T, errmap map[string][]string, errlist []error) {
+	for _, err := range errlist {
+		pos, gotMsg := splitError(err)
+		list := errmap[pos]
+		index := -1 // list index of matching message, if any
+		// we expect one of the messages in list to match the error at pos
+		for i, wantRx := range list {
+			rx, err := regexp.Compile(wantRx)
+			if err != nil {
+				t.Errorf("%s: %v", pos, err)
+				continue
+			}
+			if rx.MatchString(gotMsg) {
+				index = i
+				break
+			}
+		}
+		if index >= 0 {
+			// eliminate from list
+			if n := len(list) - 1; n > 0 {
+				// not the last entry - swap in last element and shorten list by 1
+				list[index] = list[n]
+				errmap[pos] = list[:n]
+			} else {
+				// last entry - remove list from map
+				delete(errmap, pos)
+			}
+		} else {
+			t.Errorf("%s: no error expected: %q", pos, gotMsg)
+		}
+	}
+}
+
+func checkFiles(t *testing.T, testfiles []string) {
+	// parse files and collect parser errors
+	files, errlist := parseFiles(t, testfiles)
+
+	pkgName := "<no package>"
+	if len(files) > 0 {
+		pkgName = files[0].Name.Name
+	}
+
+	if *listErrors && len(errlist) > 0 {
+		t.Errorf("--- %s:", pkgName)
+		for _, err := range errlist {
+			t.Error(err)
+		}
+	}
+
+	// typecheck and collect typechecker errors
+	var conf Config
+	conf.Error = func(err error) {
+		if *listErrors {
+			t.Error(err)
+			return
+		}
+		// Ignore secondary error messages starting with "\t";
+		// they are clarifying messages for a primary error.
+		if !strings.Contains(err.Error(), ": \t") {
+			errlist = append(errlist, err)
+		}
+	}
+	conf.Check(pkgName, fset, files, nil)
+
+	if *listErrors {
+		return
+	}
+
+	// match and eliminate errors;
+	// we are expecting the following errors
+	errmap := errMap(t, pkgName, files)
+	eliminate(t, errmap, errlist)
+
+	// there should be no expected errors left
+	if len(errmap) > 0 {
+		t.Errorf("--- %s: %d source positions with expected (but not reported) errors:", pkgName, len(errmap))
+		for pos, list := range errmap {
+			for _, rx := range list {
+				t.Errorf("%s: %q", pos, rx)
+			}
+		}
+	}
+}
+
+func TestCheck(t *testing.T) {
+	// Declare builtins for testing.
+	DefPredeclaredTestFuncs()
+
+	// If explicit test files are specified, only check those.
+	if files := *testFiles; files != "" {
+		checkFiles(t, strings.Split(files, " "))
+		return
+	}
+
+	// Otherwise, run all the tests.
+	for _, files := range tests {
+		checkFiles(t, files)
+	}
+}
diff --git a/third_party/go.tools/go/types/conversions.go b/third_party/go.tools/go/types/conversions.go
new file mode 100644
index 0000000..ea308be
--- /dev/null
+++ b/third_party/go.tools/go/types/conversions.go
@@ -0,0 +1,146 @@
+// 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.
+
+// This file implements typechecking of conversions.
+
+package types
+
+import "llvm.org/llgo/third_party/go.tools/go/exact"
+
+// Conversion type-checks the conversion T(x).
+// The result is in x.
+func (check *Checker) conversion(x *operand, T Type) {
+	constArg := x.mode == constant
+
+	var ok bool
+	switch {
+	case constArg && isConstType(T):
+		// constant conversion
+		switch t := T.Underlying().(*Basic); {
+		case representableConst(x.val, check.conf, t.kind, &x.val):
+			ok = true
+		case x.isInteger() && isString(t):
+			codepoint := int64(-1)
+			if i, ok := exact.Int64Val(x.val); ok {
+				codepoint = i
+			}
+			// If codepoint < 0 the absolute value is too large (or unknown) for
+			// conversion. This is the same as converting any other out-of-range
+			// value - let string(codepoint) do the work.
+			x.val = exact.MakeString(string(codepoint))
+			ok = true
+		}
+	case x.convertibleTo(check.conf, T):
+		// non-constant conversion
+		x.mode = value
+		ok = true
+	}
+
+	if !ok {
+		check.errorf(x.pos(), "cannot convert %s to %s", x, T)
+		x.mode = invalid
+		return
+	}
+
+	// The conversion argument types are final. For untyped values the
+	// conversion provides the type, per the spec: "A constant may be
+	// given a type explicitly by a constant declaration or conversion,...".
+	final := x.typ
+	if isUntyped(x.typ) {
+		final = T
+		// - For conversions to interfaces, use the argument's default type.
+		// - For conversions of untyped constants to non-constant types, also
+		//   use the default type (e.g., []byte("foo") should report string
+		//   not []byte as type for the constant "foo").
+		// - Keep untyped nil for untyped nil arguments.
+		if isInterface(T) || constArg && !isConstType(T) {
+			final = defaultType(x.typ)
+		}
+		check.updateExprType(x.expr, final, true)
+	}
+
+	x.typ = T
+}
+
+func (x *operand) convertibleTo(conf *Config, T Type) bool {
+	// "x is assignable to T"
+	if x.assignableTo(conf, T) {
+		return true
+	}
+
+	// "x's type and T have identical underlying types"
+	V := x.typ
+	Vu := V.Underlying()
+	Tu := T.Underlying()
+	if Identical(Vu, Tu) {
+		return true
+	}
+
+	// "x's type and T are unnamed pointer types and their pointer base types have identical underlying types"
+	if V, ok := V.(*Pointer); ok {
+		if T, ok := T.(*Pointer); ok {
+			if Identical(V.base.Underlying(), T.base.Underlying()) {
+				return true
+			}
+		}
+	}
+
+	// "x's type and T are both integer or floating point types"
+	if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) {
+		return true
+	}
+
+	// "x's type and T are both complex types"
+	if isComplex(V) && isComplex(T) {
+		return true
+	}
+
+	// "x is an integer or a slice of bytes or runes and T is a string type"
+	if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) {
+		return true
+	}
+
+	// "x is a string and T is a slice of bytes or runes"
+	if isString(V) && isBytesOrRunes(Tu) {
+		return true
+	}
+
+	// package unsafe:
+	// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
+	if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) {
+		return true
+	}
+	// "and vice versa"
+	if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) {
+		return true
+	}
+
+	return false
+}
+
+func isUintptr(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.kind == Uintptr
+}
+
+func isUnsafePointer(typ Type) bool {
+	// TODO(gri): Is this (typ.Underlying() instead of just typ) correct?
+	//            The spec does not say so, but gc claims it is. See also
+	//            issue 6326.
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.kind == UnsafePointer
+}
+
+func isPointer(typ Type) bool {
+	_, ok := typ.Underlying().(*Pointer)
+	return ok
+}
+
+func isBytesOrRunes(typ Type) bool {
+	if s, ok := typ.(*Slice); ok {
+		t, ok := s.elem.Underlying().(*Basic)
+		return ok && (t.kind == Byte || t.kind == Rune)
+	}
+	return false
+}
diff --git a/third_party/go.tools/go/types/decl.go b/third_party/go.tools/go/types/decl.go
new file mode 100644
index 0000000..68d6f0e
--- /dev/null
+++ b/third_party/go.tools/go/types/decl.go
@@ -0,0 +1,419 @@
+// Copyright 2014 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 types
+
+import (
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+func (check *Checker) reportAltDecl(obj Object) {
+	if pos := obj.Pos(); pos.IsValid() {
+		// We use "other" rather than "previous" here because
+		// the first declaration seen may not be textually
+		// earlier in the source.
+		check.errorf(pos, "\tother declaration of %s", obj.Name()) // secondary error, \t indented
+	}
+}
+
+func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object) {
+	// spec: "The blank identifier, represented by the underscore
+	// character _, may be used in a declaration like any other
+	// identifier but the declaration does not introduce a new
+	// binding."
+	if obj.Name() != "_" {
+		if alt := scope.Insert(obj); alt != nil {
+			check.errorf(obj.Pos(), "%s redeclared in this block", obj.Name())
+			check.reportAltDecl(alt)
+			return
+		}
+	}
+	if id != nil {
+		check.recordDef(id, obj)
+	}
+}
+
+// objDecl type-checks the declaration of obj in its respective (file) context.
+// See check.typ for the details on def and path.
+func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
+	if obj.Type() != nil {
+		return // already checked - nothing to do
+	}
+
+	if trace {
+		check.trace(obj.Pos(), "-- declaring %s", obj.Name())
+		check.indent++
+		defer func() {
+			check.indent--
+			check.trace(obj.Pos(), "=> %s", obj)
+		}()
+	}
+
+	d := check.objMap[obj]
+	if d == nil {
+		check.dump("%s: %s should have been declared", obj.Pos(), obj.Name())
+		unreachable()
+	}
+
+	// save/restore current context and setup object context
+	defer func(ctxt context) {
+		check.context = ctxt
+	}(check.context)
+	check.context = context{
+		scope: d.file,
+	}
+
+	// Const and var declarations must not have initialization
+	// cycles. We track them by remembering the current declaration
+	// in check.decl. Initialization expressions depending on other
+	// consts, vars, or functions, add dependencies to the current
+	// check.decl.
+	switch obj := obj.(type) {
+	case *Const:
+		check.decl = d // new package-level const decl
+		check.constDecl(obj, d.typ, d.init)
+	case *Var:
+		check.decl = d // new package-level var decl
+		check.varDecl(obj, d.lhs, d.typ, d.init)
+	case *TypeName:
+		// invalid recursive types are detected via path
+		check.typeDecl(obj, d.typ, def, path)
+	case *Func:
+		// functions may be recursive - no need to track dependencies
+		check.funcDecl(obj, d)
+	default:
+		unreachable()
+	}
+}
+
+func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
+	assert(obj.typ == nil)
+
+	if obj.visited {
+		obj.typ = Typ[Invalid]
+		return
+	}
+	obj.visited = true
+
+	// use the correct value of iota
+	assert(check.iota == nil)
+	check.iota = obj.val
+	defer func() { check.iota = nil }()
+
+	// provide valid constant value under all circumstances
+	obj.val = exact.MakeUnknown()
+
+	// determine type, if any
+	if typ != nil {
+		t := check.typ(typ)
+		if !isConstType(t) {
+			check.errorf(typ.Pos(), "invalid constant type %s", t)
+			obj.typ = Typ[Invalid]
+			return
+		}
+		obj.typ = t
+	}
+
+	// check initialization
+	var x operand
+	if init != nil {
+		check.expr(&x, init)
+	}
+	check.initConst(obj, &x)
+}
+
+func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
+	assert(obj.typ == nil)
+
+	if obj.visited {
+		obj.typ = Typ[Invalid]
+		return
+	}
+	obj.visited = true
+
+	// var declarations cannot use iota
+	assert(check.iota == nil)
+
+	// determine type, if any
+	if typ != nil {
+		obj.typ = check.typ(typ)
+	}
+
+	// check initialization
+	if init == nil {
+		if typ == nil {
+			// error reported before by arityMatch
+			obj.typ = Typ[Invalid]
+		}
+		return
+	}
+
+	if lhs == nil || len(lhs) == 1 {
+		assert(lhs == nil || lhs[0] == obj)
+		var x operand
+		check.expr(&x, init)
+		check.initVar(obj, &x, false)
+		return
+	}
+
+	if debug {
+		// obj must be one of lhs
+		found := false
+		for _, lhs := range lhs {
+			if obj == lhs {
+				found = true
+				break
+			}
+		}
+		if !found {
+			panic("inconsistent lhs")
+		}
+	}
+	check.initVars(lhs, []ast.Expr{init}, token.NoPos)
+}
+
+// underlying returns the underlying type of typ; possibly by following
+// forward chains of named types. Such chains only exist while named types
+// are incomplete.
+func underlying(typ Type) Type {
+	for {
+		n, _ := typ.(*Named)
+		if n == nil {
+			break
+		}
+		typ = n.underlying
+	}
+	return typ
+}
+
+func (n *Named) setUnderlying(typ Type) {
+	if n != nil {
+		n.underlying = typ
+	}
+}
+
+func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, path []*TypeName) {
+	assert(obj.typ == nil)
+
+	// type declarations cannot use iota
+	assert(check.iota == nil)
+
+	named := &Named{obj: obj}
+	def.setUnderlying(named)
+	obj.typ = named // make sure recursive type declarations terminate
+
+	// determine underlying type of named
+	check.typExpr(typ, named, append(path, obj))
+
+	// The underlying type of named may be itself a named type that is
+	// incomplete:
+	//
+	//	type (
+	//		A B
+	//		B *C
+	//		C A
+	//	)
+	//
+	// The type of C is the (named) type of A which is incomplete,
+	// and which has as its underlying type the named type B.
+	// Determine the (final, unnamed) underlying type by resolving
+	// any forward chain (they always end in an unnamed type).
+	named.underlying = underlying(named.underlying)
+
+	// check and add associated methods
+	// TODO(gri) It's easy to create pathological cases where the
+	// current approach is incorrect: In general we need to know
+	// and add all methods _before_ type-checking the type.
+	// See http://play.golang.org/p/WMpE0q2wK8
+	check.addMethodDecls(obj)
+}
+
+func (check *Checker) addMethodDecls(obj *TypeName) {
+	// get associated methods
+	methods := check.methods[obj.name]
+	if len(methods) == 0 {
+		return // no methods
+	}
+	delete(check.methods, obj.name)
+
+	// use an objset to check for name conflicts
+	var mset objset
+
+	// spec: "If the base type is a struct type, the non-blank method
+	// and field names must be distinct."
+	base := obj.typ.(*Named)
+	if t, _ := base.underlying.(*Struct); t != nil {
+		for _, fld := range t.fields {
+			if fld.name != "_" {
+				assert(mset.insert(fld) == nil)
+			}
+		}
+	}
+
+	// Checker.Files may be called multiple times; additional package files
+	// may add methods to already type-checked types. Add pre-existing methods
+	// so that we can detect redeclarations.
+	for _, m := range base.methods {
+		assert(m.name != "_")
+		assert(mset.insert(m) == nil)
+	}
+
+	// type-check methods
+	for _, m := range methods {
+		// spec: "For a base type, the non-blank names of methods bound
+		// to it must be unique."
+		if m.name != "_" {
+			if alt := mset.insert(m); alt != nil {
+				switch alt.(type) {
+				case *Var:
+					check.errorf(m.pos, "field and method with the same name %s", m.name)
+				case *Func:
+					check.errorf(m.pos, "method %s already declared for %s", m.name, base)
+				default:
+					unreachable()
+				}
+				check.reportAltDecl(alt)
+				continue
+			}
+		}
+		check.objDecl(m, nil, nil)
+		// methods with blank _ names cannot be found - don't keep them
+		if m.name != "_" {
+			base.methods = append(base.methods, m)
+		}
+	}
+}
+
+func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
+	assert(obj.typ == nil)
+
+	// func declarations cannot use iota
+	assert(check.iota == nil)
+
+	sig := new(Signature)
+	obj.typ = sig // guard against cycles
+	fdecl := decl.fdecl
+	check.funcType(sig, fdecl.Recv, fdecl.Type)
+	if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) {
+		check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
+		// ok to continue
+	}
+
+	// function body must be type-checked after global declarations
+	// (functions implemented elsewhere have no body)
+	if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
+		check.later(obj.name, decl, sig, fdecl.Body)
+	}
+}
+
+func (check *Checker) declStmt(decl ast.Decl) {
+	pkg := check.pkg
+
+	switch d := decl.(type) {
+	case *ast.BadDecl:
+		// ignore
+
+	case *ast.GenDecl:
+		var last *ast.ValueSpec // last ValueSpec with type or init exprs seen
+		for iota, spec := range d.Specs {
+			switch s := spec.(type) {
+			case *ast.ValueSpec:
+				switch d.Tok {
+				case token.CONST:
+					// determine which init exprs to use
+					switch {
+					case s.Type != nil || len(s.Values) > 0:
+						last = s
+					case last == nil:
+						last = new(ast.ValueSpec) // make sure last exists
+					}
+
+					// declare all constants
+					lhs := make([]*Const, len(s.Names))
+					for i, name := range s.Names {
+						obj := NewConst(name.Pos(), pkg, name.Name, nil, exact.MakeInt64(int64(iota)))
+						lhs[i] = obj
+
+						var init ast.Expr
+						if i < len(last.Values) {
+							init = last.Values[i]
+						}
+
+						check.constDecl(obj, last.Type, init)
+					}
+
+					check.arityMatch(s, last)
+
+					for i, name := range s.Names {
+						check.declare(check.scope, name, lhs[i])
+					}
+
+				case token.VAR:
+					lhs0 := make([]*Var, len(s.Names))
+					for i, name := range s.Names {
+						lhs0[i] = NewVar(name.Pos(), pkg, name.Name, nil)
+					}
+
+					// initialize all variables
+					for i, obj := range lhs0 {
+						var lhs []*Var
+						var init ast.Expr
+						switch len(s.Values) {
+						case len(s.Names):
+							// lhs and rhs match
+							init = s.Values[i]
+						case 1:
+							// rhs is expected to be a multi-valued expression
+							lhs = lhs0
+							init = s.Values[0]
+						default:
+							if i < len(s.Values) {
+								init = s.Values[i]
+							}
+						}
+						check.varDecl(obj, lhs, s.Type, init)
+						if len(s.Values) == 1 {
+							// If we have a single lhs variable we are done either way.
+							// If we have a single rhs expression, it must be a multi-
+							// valued expression, in which case handling the first lhs
+							// variable will cause all lhs variables to have a type
+							// assigned, and we are done as well.
+							if debug {
+								for _, obj := range lhs0 {
+									assert(obj.typ != nil)
+								}
+							}
+							break
+						}
+					}
+
+					check.arityMatch(s, nil)
+
+					// declare all variables
+					// (only at this point are the variable scopes (parents) set)
+					for i, name := range s.Names {
+						check.declare(check.scope, name, lhs0[i])
+					}
+
+				default:
+					check.invalidAST(s.Pos(), "invalid token %s", d.Tok)
+				}
+
+			case *ast.TypeSpec:
+				obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil)
+				check.declare(check.scope, s.Name, obj)
+				check.typeDecl(obj, s.Type, nil, nil)
+
+			default:
+				check.invalidAST(s.Pos(), "const, type, or var declaration expected")
+			}
+		}
+
+	default:
+		check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
+	}
+}
diff --git a/third_party/go.tools/go/types/errors.go b/third_party/go.tools/go/types/errors.go
new file mode 100644
index 0000000..0a9dd0e
--- /dev/null
+++ b/third_party/go.tools/go/types/errors.go
@@ -0,0 +1,96 @@
+// 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.
+
+// This file implements various error reporters.
+
+package types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"strings"
+)
+
+func assert(p bool) {
+	if !p {
+		panic("assertion failed")
+	}
+}
+
+func unreachable() {
+	panic("unreachable")
+}
+
+func (check *Checker) sprintf(format string, args ...interface{}) string {
+	for i, arg := range args {
+		switch a := arg.(type) {
+		case nil:
+			arg = "<nil>"
+		case operand:
+			panic("internal error: should always pass *operand")
+		case *operand:
+			arg = operandString(check.pkg, a)
+		case token.Pos:
+			arg = check.fset.Position(a).String()
+		case ast.Expr:
+			arg = ExprString(a)
+		case Object:
+			arg = ObjectString(check.pkg, a)
+		case Type:
+			arg = TypeString(check.pkg, a)
+		}
+		args[i] = arg
+	}
+	return fmt.Sprintf(format, args...)
+}
+
+func (check *Checker) trace(pos token.Pos, format string, args ...interface{}) {
+	fmt.Printf("%s:\t%s%s\n",
+		check.fset.Position(pos),
+		strings.Repeat(".  ", check.indent),
+		check.sprintf(format, args...),
+	)
+}
+
+// dump is only needed for debugging
+func (check *Checker) dump(format string, args ...interface{}) {
+	fmt.Println(check.sprintf(format, args...))
+}
+
+func (check *Checker) err(pos token.Pos, msg string, soft bool) {
+	err := Error{check.fset, pos, msg, soft}
+	if check.firstErr == nil {
+		check.firstErr = err
+	}
+	f := check.conf.Error
+	if f == nil {
+		panic(bailout{}) // report only first error
+	}
+	f(err)
+}
+
+func (check *Checker) error(pos token.Pos, msg string) {
+	check.err(pos, msg, false)
+}
+
+func (check *Checker) errorf(pos token.Pos, format string, args ...interface{}) {
+	check.err(pos, check.sprintf(format, args...), false)
+}
+
+func (check *Checker) softErrorf(pos token.Pos, format string, args ...interface{}) {
+	check.err(pos, check.sprintf(format, args...), true)
+}
+
+func (check *Checker) invalidAST(pos token.Pos, format string, args ...interface{}) {
+	check.errorf(pos, "invalid AST: "+format, args...)
+}
+
+func (check *Checker) invalidArg(pos token.Pos, format string, args ...interface{}) {
+	check.errorf(pos, "invalid argument: "+format, args...)
+}
+
+func (check *Checker) invalidOp(pos token.Pos, format string, args ...interface{}) {
+	check.errorf(pos, "invalid operation: "+format, args...)
+}
diff --git a/third_party/go.tools/go/types/eval.go b/third_party/go.tools/go/types/eval.go
new file mode 100644
index 0000000..8ad7e46
--- /dev/null
+++ b/third_party/go.tools/go/types/eval.go
@@ -0,0 +1,109 @@
+// Copyright 2013 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.
+
+// This file implements New, Eval and EvalNode.
+
+package types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+// New is a convenience function to create a new type from a given
+// expression or type literal string evaluated in Universe scope.
+// New(str) is shorthand for Eval(str, nil, nil), but only returns
+// the type result, and panics in case of an error.
+// Position info for objects in the result type is undefined.
+//
+func New(str string) Type {
+	typ, _, err := Eval(str, nil, nil)
+	if err != nil {
+		panic(err)
+	}
+	return typ
+}
+
+// Eval returns the type and, if constant, the value for the
+// expression or type literal string str evaluated in scope.
+// If the expression contains function literals, the function
+// bodies are ignored (though they must be syntactically correct).
+//
+// If pkg == nil, the Universe scope is used and the provided
+// scope is ignored. Otherwise, the scope must belong to the
+// package (either the package scope, or nested within the
+// package scope).
+//
+// An error is returned if the scope is incorrect, the string
+// has syntax errors, or if it cannot be evaluated in the scope.
+// Position info for objects in the result type is undefined.
+//
+// Note: Eval should not be used instead of running Check to compute
+// types and values, but in addition to Check. Eval will re-evaluate
+// its argument each time, and it also does not know about the context
+// in which an expression is used (e.g., an assignment). Thus, top-
+// level untyped constants will return an untyped type rather then the
+// respective context-specific type.
+//
+func Eval(str string, pkg *Package, scope *Scope) (typ Type, val exact.Value, err error) {
+	node, err := parser.ParseExpr(str)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	// Create a file set that looks structurally identical to the
+	// one created by parser.ParseExpr for correct error positions.
+	fset := token.NewFileSet()
+	fset.AddFile("", len(str), fset.Base()).SetLinesForContent([]byte(str))
+
+	return EvalNode(fset, node, pkg, scope)
+}
+
+// EvalNode is like Eval but instead of string it accepts
+// an expression node and respective file set.
+//
+// An error is returned if the scope is incorrect
+// if the node cannot be evaluated in the scope.
+//
+func EvalNode(fset *token.FileSet, node ast.Expr, pkg *Package, scope *Scope) (typ Type, val exact.Value, err error) {
+	// verify package/scope relationship
+	if pkg == nil {
+		scope = Universe
+	} else {
+		s := scope
+		for s != nil && s != pkg.scope {
+			s = s.parent
+		}
+		// s == nil || s == pkg.scope
+		if s == nil {
+			return nil, nil, fmt.Errorf("scope does not belong to package %s", pkg.name)
+		}
+	}
+
+	// initialize checker
+	check := NewChecker(nil, fset, pkg, nil)
+	check.scope = scope
+	defer check.handleBailout(&err)
+
+	// evaluate node
+	var x operand
+	check.exprOrType(&x, node)
+	switch x.mode {
+	case invalid, novalue:
+		fallthrough
+	default:
+		unreachable() // or bailed out with error
+	case constant:
+		val = x.val
+		fallthrough
+	case typexpr, variable, mapindex, value, commaok:
+		typ = x.typ
+	}
+
+	return
+}
diff --git a/third_party/go.tools/go/types/eval_test.go b/third_party/go.tools/go/types/eval_test.go
new file mode 100644
index 0000000..f9cf592
--- /dev/null
+++ b/third_party/go.tools/go/types/eval_test.go
@@ -0,0 +1,148 @@
+// Copyright 2013 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.
+
+// This file contains tests for Eval.
+
+package types_test
+
+import (
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"strings"
+	"testing"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func testEval(t *testing.T, pkg *Package, scope *Scope, str string, typ Type, typStr, valStr string) {
+	gotTyp, gotVal, err := Eval(str, pkg, scope)
+	if err != nil {
+		t.Errorf("Eval(%q) failed: %s", str, err)
+		return
+	}
+	if gotTyp == nil {
+		t.Errorf("Eval(%q) got nil type but no error", str)
+		return
+	}
+
+	// compare types
+	if typ != nil {
+		// we have a type, check identity
+		if !Identical(gotTyp, typ) {
+			t.Errorf("Eval(%q) got type %s, want %s", str, gotTyp, typ)
+			return
+		}
+	} else {
+		// we have a string, compare type string
+		gotStr := gotTyp.String()
+		if gotStr != typStr {
+			t.Errorf("Eval(%q) got type %s, want %s", str, gotStr, typStr)
+			return
+		}
+	}
+
+	// compare values
+	gotStr := ""
+	if gotVal != nil {
+		gotStr = gotVal.String()
+	}
+	if gotStr != valStr {
+		t.Errorf("Eval(%q) got value %s, want %s", str, gotStr, valStr)
+	}
+}
+
+func TestEvalBasic(t *testing.T) {
+	for _, typ := range Typ[Bool : String+1] {
+		testEval(t, nil, nil, typ.Name(), typ, "", "")
+	}
+}
+
+func TestEvalComposite(t *testing.T) {
+	for _, test := range independentTestTypes {
+		testEval(t, nil, nil, test.src, nil, test.str, "")
+	}
+}
+
+func TestEvalArith(t *testing.T) {
+	var tests = []string{
+		`true`,
+		`false == false`,
+		`12345678 + 87654321 == 99999999`,
+		`10 * 20 == 200`,
+		`(1<<1000)*2 >> 100 == 2<<900`,
+		`"foo" + "bar" == "foobar"`,
+		`"abc" <= "bcd"`,
+		`len([10]struct{}{}) == 2*5`,
+	}
+	for _, test := range tests {
+		testEval(t, nil, nil, test, Typ[UntypedBool], "", "true")
+	}
+}
+
+func TestEvalContext(t *testing.T) {
+	src := `
+package p
+import "fmt"
+import m "math"
+const c = 3.0
+type T []int
+func f(a int, s string) float64 {
+	fmt.Println("calling f")
+	_ = m.Pi // use package math
+	const d int = c + 1
+	var x int
+	x = a + len(s)
+	return float64(x)
+}
+`
+	fset := token.NewFileSet()
+	file, err := parser.ParseFile(fset, "p", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pkg, err := Check("p", fset, []*ast.File{file})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pkgScope := pkg.Scope()
+	if n := pkgScope.NumChildren(); n != 1 {
+		t.Fatalf("got %d file scopes, want 1", n)
+	}
+
+	fileScope := pkgScope.Child(0)
+	if n := fileScope.NumChildren(); n != 1 {
+		t.Fatalf("got %d functions scopes, want 1", n)
+	}
+
+	funcScope := fileScope.Child(0)
+
+	var tests = []string{
+		`true => true, untyped bool`,
+		`fmt.Println => , func(a ...interface{}) (n int, err error)`,
+		`c => 3, untyped float`,
+		`T => , p.T`,
+		`a => , int`,
+		`s => , string`,
+		`d => 4, int`,
+		`x => , int`,
+		`d/c => 1, int`,
+		`c/2 => 3/2, untyped float`,
+		`m.Pi < m.E => false, untyped bool`,
+	}
+	for _, test := range tests {
+		str, typ := split(test, ", ")
+		str, val := split(str, "=>")
+		testEval(t, pkg, funcScope, str, nil, typ, val)
+	}
+}
+
+// split splits string s at the first occurrence of s.
+func split(s, sep string) (string, string) {
+	i := strings.Index(s, sep)
+	return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):])
+}
diff --git a/third_party/go.tools/go/types/expr.go b/third_party/go.tools/go/types/expr.go
new file mode 100644
index 0000000..0e19fb9
--- /dev/null
+++ b/third_party/go.tools/go/types/expr.go
@@ -0,0 +1,1474 @@
+// 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.
+
+// This file implements typechecking of expressions.
+
+package types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"math"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+/*
+Basic algorithm:
+
+Expressions are checked recursively, top down. Expression checker functions
+are generally of the form:
+
+  func f(x *operand, e *ast.Expr, ...)
+
+where e is the expression to be checked, and x is the result of the check.
+The check performed by f may fail in which case x.mode == invalid, and
+related error messages will have been issued by f.
+
+If a hint argument is present, it is the composite literal element type
+of an outer composite literal; it is used to type-check composite literal
+elements that have no explicit type specification in the source
+(e.g.: []T{{...}, {...}}, the hint is the type T in this case).
+
+All expressions are checked via rawExpr, which dispatches according
+to expression kind. Upon returning, rawExpr is recording the types and
+constant values for all expressions that have an untyped type (those types
+may change on the way up in the expression tree). Usually these are constants,
+but the results of comparisons or non-constant shifts of untyped constants
+may also be untyped, but not constant.
+
+Untyped expressions may eventually become fully typed (i.e., not untyped),
+typically when the value is assigned to a variable, or is used otherwise.
+The updateExprType method is used to record this final type and update
+the recorded types: the type-checked expression tree is again traversed down,
+and the new type is propagated as needed. Untyped constant expression values
+that become fully typed must now be representable by the full type (constant
+sub-expression trees are left alone except for their roots). This mechanism
+ensures that a client sees the actual (run-time) type an untyped value would
+have. It also permits type-checking of lhs shift operands "as if the shift
+were not present": when updateExprType visits an untyped lhs shift operand
+and assigns it it's final type, that type must be an integer type, and a
+constant lhs must be representable as an integer.
+
+When an expression gets its final type, either on the way out from rawExpr,
+on the way down in updateExprType, or at the end of the type checker run,
+the type (and constant value, if any) is recorded via Info.Types, if present.
+*/
+
+type opPredicates map[token.Token]func(Type) bool
+
+var unaryOpPredicates = opPredicates{
+	token.ADD: isNumeric,
+	token.SUB: isNumeric,
+	token.XOR: isInteger,
+	token.NOT: isBoolean,
+}
+
+func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool {
+	if pred := m[op]; pred != nil {
+		if !pred(x.typ) {
+			check.invalidOp(x.pos(), "operator %s not defined for %s", op, x)
+			return false
+		}
+	} else {
+		check.invalidAST(x.pos(), "unknown operator %s", op)
+		return false
+	}
+	return true
+}
+
+func (check *Checker) unary(x *operand, op token.Token) {
+	switch op {
+	case token.AND:
+		// spec: "As an exception to the addressability
+		// requirement x may also be a composite literal."
+		if _, ok := unparen(x.expr).(*ast.CompositeLit); !ok && x.mode != variable {
+			check.invalidOp(x.pos(), "cannot take address of %s", x)
+			x.mode = invalid
+			return
+		}
+		x.mode = value
+		x.typ = &Pointer{base: x.typ}
+		return
+
+	case token.ARROW:
+		typ, ok := x.typ.Underlying().(*Chan)
+		if !ok {
+			check.invalidOp(x.pos(), "cannot receive from non-channel %s", x)
+			x.mode = invalid
+			return
+		}
+		if typ.dir == SendOnly {
+			check.invalidOp(x.pos(), "cannot receive from send-only channel %s", x)
+			x.mode = invalid
+			return
+		}
+		x.mode = commaok
+		x.typ = typ.elem
+		check.hasCallOrRecv = true
+		return
+	}
+
+	if !check.op(unaryOpPredicates, x, op) {
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant {
+		typ := x.typ.Underlying().(*Basic)
+		size := -1
+		if isUnsigned(typ) {
+			size = int(check.conf.sizeof(typ))
+		}
+		x.val = exact.UnaryOp(op, x.val, size)
+		// Typed constants must be representable in
+		// their type after each constant operation.
+		if isTyped(typ) {
+			check.representable(x, typ)
+		}
+		return
+	}
+
+	x.mode = value
+	// x.typ remains unchanged
+}
+
+func isShift(op token.Token) bool {
+	return op == token.SHL || op == token.SHR
+}
+
+func isComparison(op token.Token) bool {
+	// Note: tokens are not ordered well to make this much easier
+	switch op {
+	case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ:
+		return true
+	}
+	return false
+}
+
+func fitsFloat32(x exact.Value) bool {
+	f32, _ := exact.Float32Val(x)
+	f := float64(f32)
+	return !math.IsInf(f, 0)
+}
+
+func roundFloat32(x exact.Value) exact.Value {
+	f32, _ := exact.Float32Val(x)
+	f := float64(f32)
+	if !math.IsInf(f, 0) {
+		return exact.MakeFloat64(f)
+	}
+	return nil
+}
+
+func fitsFloat64(x exact.Value) bool {
+	f, _ := exact.Float64Val(x)
+	return !math.IsInf(f, 0)
+}
+
+func roundFloat64(x exact.Value) exact.Value {
+	f, _ := exact.Float64Val(x)
+	if !math.IsInf(f, 0) {
+		return exact.MakeFloat64(f)
+	}
+	return nil
+}
+
+// representableConst reports whether x can be represented as
+// value of the given basic type kind and for the configuration
+// provided (only needed for int/uint sizes).
+//
+// If rounded != nil, *rounded is set to the rounded value of x for
+// representable floating-point values; it is left alone otherwise.
+// It is ok to provide the addressof the first argument for rounded.
+func representableConst(x exact.Value, conf *Config, as BasicKind, rounded *exact.Value) bool {
+	switch x.Kind() {
+	case exact.Unknown:
+		return true
+
+	case exact.Bool:
+		return as == Bool || as == UntypedBool
+
+	case exact.Int:
+		if x, ok := exact.Int64Val(x); ok {
+			switch as {
+			case Int:
+				var s = uint(conf.sizeof(Typ[as])) * 8
+				return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1
+			case Int8:
+				const s = 8
+				return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+			case Int16:
+				const s = 16
+				return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+			case Int32:
+				const s = 32
+				return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+			case Int64:
+				return true
+			case Uint, Uintptr:
+				if s := uint(conf.sizeof(Typ[as])) * 8; s < 64 {
+					return 0 <= x && x <= int64(1)<<s-1
+				}
+				return 0 <= x
+			case Uint8:
+				const s = 8
+				return 0 <= x && x <= 1<<s-1
+			case Uint16:
+				const s = 16
+				return 0 <= x && x <= 1<<s-1
+			case Uint32:
+				const s = 32
+				return 0 <= x && x <= 1<<s-1
+			case Uint64:
+				return 0 <= x
+			case Float32, Float64, Complex64, Complex128,
+				UntypedInt, UntypedFloat, UntypedComplex:
+				return true
+			}
+		}
+
+		n := exact.BitLen(x)
+		switch as {
+		case Uint, Uintptr:
+			var s = uint(conf.sizeof(Typ[as])) * 8
+			return exact.Sign(x) >= 0 && n <= int(s)
+		case Uint64:
+			return exact.Sign(x) >= 0 && n <= 64
+		case Float32, Complex64:
+			if rounded == nil {
+				return fitsFloat32(x)
+			}
+			r := roundFloat32(x)
+			if r != nil {
+				*rounded = r
+				return true
+			}
+		case Float64, Complex128:
+			if rounded == nil {
+				return fitsFloat64(x)
+			}
+			r := roundFloat64(x)
+			if r != nil {
+				*rounded = r
+				return true
+			}
+		case UntypedInt, UntypedFloat, UntypedComplex:
+			return true
+		}
+
+	case exact.Float:
+		switch as {
+		case Float32, Complex64:
+			if rounded == nil {
+				return fitsFloat32(x)
+			}
+			r := roundFloat32(x)
+			if r != nil {
+				*rounded = r
+				return true
+			}
+		case Float64, Complex128:
+			if rounded == nil {
+				return fitsFloat64(x)
+			}
+			r := roundFloat64(x)
+			if r != nil {
+				*rounded = r
+				return true
+			}
+		case UntypedFloat, UntypedComplex:
+			return true
+		}
+
+	case exact.Complex:
+		switch as {
+		case Complex64:
+			if rounded == nil {
+				return fitsFloat32(exact.Real(x)) && fitsFloat32(exact.Imag(x))
+			}
+			re := roundFloat32(exact.Real(x))
+			im := roundFloat32(exact.Imag(x))
+			if re != nil && im != nil {
+				*rounded = exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
+				return true
+			}
+		case Complex128:
+			if rounded == nil {
+				return fitsFloat64(exact.Real(x)) && fitsFloat64(exact.Imag(x))
+			}
+			re := roundFloat64(exact.Real(x))
+			im := roundFloat64(exact.Imag(x))
+			if re != nil && im != nil {
+				*rounded = exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
+				return true
+			}
+		case UntypedComplex:
+			return true
+		}
+
+	case exact.String:
+		return as == String || as == UntypedString
+
+	default:
+		unreachable()
+	}
+
+	return false
+}
+
+// representable checks that a constant operand is representable in the given basic type.
+func (check *Checker) representable(x *operand, typ *Basic) {
+	assert(x.mode == constant)
+	if !representableConst(x.val, check.conf, typ.kind, &x.val) {
+		var msg string
+		if isNumeric(x.typ) && isNumeric(typ) {
+			// numeric conversion : error msg
+			//
+			// integer -> integer : overflows
+			// integer -> float   : overflows (actually not possible)
+			// float   -> integer : truncated
+			// float   -> float   : overflows
+			//
+			if !isInteger(x.typ) && isInteger(typ) {
+				msg = "%s truncated to %s"
+			} else {
+				msg = "%s overflows %s"
+			}
+		} else {
+			msg = "cannot convert %s to %s"
+		}
+		check.errorf(x.pos(), msg, x, typ)
+		x.mode = invalid
+	}
+}
+
+// updateExprType updates the type of x to typ and invokes itself
+// recursively for the operands of x, depending on expression kind.
+// If typ is still an untyped and not the final type, updateExprType
+// only updates the recorded untyped type for x and possibly its
+// operands. Otherwise (i.e., typ is not an untyped type anymore,
+// or it is the final type for x), the type and value are recorded.
+// Also, if x is a constant, it must be representable as a value of typ,
+// and if x is the (formerly untyped) lhs operand of a non-constant
+// shift, it must be an integer value.
+//
+func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) {
+	old, found := check.untyped[x]
+	if !found {
+		return // nothing to do
+	}
+
+	// update operands of x if necessary
+	switch x := x.(type) {
+	case *ast.BadExpr,
+		*ast.FuncLit,
+		*ast.CompositeLit,
+		*ast.IndexExpr,
+		*ast.SliceExpr,
+		*ast.TypeAssertExpr,
+		*ast.StarExpr,
+		*ast.KeyValueExpr,
+		*ast.ArrayType,
+		*ast.StructType,
+		*ast.FuncType,
+		*ast.InterfaceType,
+		*ast.MapType,
+		*ast.ChanType:
+		// These expression are never untyped - nothing to do.
+		// The respective sub-expressions got their final types
+		// upon assignment or use.
+		if debug {
+			check.dump("%s: found old type(%s): %s (new: %s)", x.Pos(), x, old.typ, typ)
+			unreachable()
+		}
+		return
+
+	case *ast.CallExpr:
+		// Resulting in an untyped constant (e.g., built-in complex).
+		// The respective calls take care of calling updateExprType
+		// for the arguments if necessary.
+
+	case *ast.Ident, *ast.BasicLit, *ast.SelectorExpr:
+		// An identifier denoting a constant, a constant literal,
+		// or a qualified identifier (imported untyped constant).
+		// No operands to take care of.
+
+	case *ast.ParenExpr:
+		check.updateExprType(x.X, typ, final)
+
+	case *ast.UnaryExpr:
+		// If x is a constant, the operands were constants.
+		// They don't need to be updated since they never
+		// get "materialized" into a typed value; and they
+		// will be processed at the end of the type check.
+		if old.val != nil {
+			break
+		}
+		check.updateExprType(x.X, typ, final)
+
+	case *ast.BinaryExpr:
+		if old.val != nil {
+			break // see comment for unary expressions
+		}
+		if isComparison(x.Op) {
+			// The result type is independent of operand types
+			// and the operand types must have final types.
+		} else if isShift(x.Op) {
+			// The result type depends only on lhs operand.
+			// The rhs type was updated when checking the shift.
+			check.updateExprType(x.X, typ, final)
+		} else {
+			// The operand types match the result type.
+			check.updateExprType(x.X, typ, final)
+			check.updateExprType(x.Y, typ, final)
+		}
+
+	default:
+		unreachable()
+	}
+
+	// If the new type is not final and still untyped, just
+	// update the recorded type.
+	if !final && isUntyped(typ) {
+		old.typ = typ.Underlying().(*Basic)
+		check.untyped[x] = old
+		return
+	}
+
+	// Otherwise we have the final (typed or untyped type).
+	// Remove it from the map of yet untyped expressions.
+	delete(check.untyped, x)
+
+	// If x is the lhs of a shift, its final type must be integer.
+	// We already know from the shift check that it is representable
+	// as an integer if it is a constant.
+	if old.isLhs && !isInteger(typ) {
+		check.invalidOp(x.Pos(), "shifted operand %s (type %s) must be integer", x, typ)
+		return
+	}
+
+	// Everything's fine, record final type and value for x.
+	check.recordTypeAndValue(x, old.mode, typ, old.val)
+}
+
+// updateExprVal updates the value of x to val.
+func (check *Checker) updateExprVal(x ast.Expr, val exact.Value) {
+	if info, ok := check.untyped[x]; ok {
+		info.val = val
+		check.untyped[x] = info
+	}
+}
+
+// convertUntyped attempts to set the type of an untyped value to the target type.
+func (check *Checker) convertUntyped(x *operand, target Type) {
+	if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] {
+		return
+	}
+
+	// TODO(gri) Sloppy code - clean up. This function is central
+	//           to assignment and expression checking.
+
+	if isUntyped(target) {
+		// both x and target are untyped
+		xkind := x.typ.(*Basic).kind
+		tkind := target.(*Basic).kind
+		if isNumeric(x.typ) && isNumeric(target) {
+			if xkind < tkind {
+				x.typ = target
+				check.updateExprType(x.expr, target, false)
+			}
+		} else if xkind != tkind {
+			goto Error
+		}
+		return
+	}
+
+	// typed target
+	switch t := target.Underlying().(type) {
+	case *Basic:
+		if x.mode == constant {
+			check.representable(x, t)
+			if x.mode == invalid {
+				return
+			}
+			// expression value may have been rounded - update if needed
+			// TODO(gri) A floating-point value may silently underflow to
+			// zero. If it was negative, the sign is lost. See issue 6898.
+			check.updateExprVal(x.expr, x.val)
+		} else {
+			// Non-constant untyped values may appear as the
+			// result of comparisons (untyped bool), intermediate
+			// (delayed-checked) rhs operands of shifts, and as
+			// the value nil.
+			switch x.typ.(*Basic).kind {
+			case UntypedBool:
+				if !isBoolean(target) {
+					goto Error
+				}
+			case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex:
+				if !isNumeric(target) {
+					goto Error
+				}
+			case UntypedString:
+				// Non-constant untyped string values are not
+				// permitted by the spec and should not occur.
+				unreachable()
+			case UntypedNil:
+				// Unsafe.Pointer is a basic type that includes nil.
+				if !hasNil(target) {
+					goto Error
+				}
+			default:
+				goto Error
+			}
+		}
+	case *Interface:
+		if !x.isNil() && !t.Empty() /* empty interfaces are ok */ {
+			goto Error
+		}
+		// Update operand types to the default type rather then
+		// the target (interface) type: values must have concrete
+		// dynamic types. If the value is nil, keep it untyped
+		// (this is important for tools such as go vet which need
+		// the dynamic type for argument checking of say, print
+		// functions)
+		if x.isNil() {
+			target = Typ[UntypedNil]
+		} else {
+			// cannot assign untyped values to non-empty interfaces
+			if !t.Empty() {
+				goto Error
+			}
+			target = defaultType(x.typ)
+		}
+	case *Pointer, *Signature, *Slice, *Map, *Chan:
+		if !x.isNil() {
+			goto Error
+		}
+		// keep nil untyped - see comment for interfaces, above
+		target = Typ[UntypedNil]
+	default:
+		goto Error
+	}
+
+	x.typ = target
+	check.updateExprType(x.expr, target, true) // UntypedNils are final
+	return
+
+Error:
+	check.errorf(x.pos(), "cannot convert %s to %s", x, target)
+	x.mode = invalid
+}
+
+func (check *Checker) comparison(x, y *operand, op token.Token) {
+	// spec: "In any comparison, the first operand must be assignable
+	// to the type of the second operand, or vice versa."
+	err := ""
+	if x.assignableTo(check.conf, y.typ) || y.assignableTo(check.conf, x.typ) {
+		defined := false
+		switch op {
+		case token.EQL, token.NEQ:
+			// spec: "The equality operators == and != apply to operands that are comparable."
+			defined = Comparable(x.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ)
+		case token.LSS, token.LEQ, token.GTR, token.GEQ:
+			// spec: The ordering operators <, <=, >, and >= apply to operands that are ordered."
+			defined = isOrdered(x.typ)
+		default:
+			unreachable()
+		}
+		if !defined {
+			typ := x.typ
+			if x.isNil() {
+				typ = y.typ
+			}
+			err = check.sprintf("operator %s not defined for %s", op, typ)
+		}
+	} else {
+		err = check.sprintf("mismatched types %s and %s", x.typ, y.typ)
+	}
+
+	if err != "" {
+		check.errorf(x.pos(), "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant && y.mode == constant {
+		x.val = exact.MakeBool(exact.Compare(x.val, op, y.val))
+		// The operands are never materialized; no need to update
+		// their types.
+	} else {
+		x.mode = value
+		// The operands have now their final types, which at run-
+		// time will be materialized. Update the expression trees.
+		// If the current types are untyped, the materialized type
+		// is the respective default type.
+		check.updateExprType(x.expr, defaultType(x.typ), true)
+		check.updateExprType(y.expr, defaultType(y.typ), true)
+	}
+
+	// spec: "Comparison operators compare two operands and yield
+	//        an untyped boolean value."
+	x.typ = Typ[UntypedBool]
+}
+
+func (check *Checker) shift(x, y *operand, op token.Token) {
+	untypedx := isUntyped(x.typ)
+
+	// The lhs must be of integer type or be representable
+	// as an integer; otherwise the shift has no chance.
+	if !isInteger(x.typ) && (!untypedx || !representableConst(x.val, nil, UntypedInt, nil)) {
+		check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
+		x.mode = invalid
+		return
+	}
+
+	// spec: "The right operand in a shift expression must have unsigned
+	// integer type or be an untyped constant that can be converted to
+	// unsigned integer type."
+	switch {
+	case isInteger(y.typ) && isUnsigned(y.typ):
+		// nothing to do
+	case isUntyped(y.typ):
+		check.convertUntyped(y, Typ[UntypedInt])
+		if y.mode == invalid {
+			x.mode = invalid
+			return
+		}
+	default:
+		check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y)
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant {
+		if y.mode == constant {
+			// rhs must be within reasonable bounds
+			const stupidShift = 1023 - 1 + 52 // so we can express smallestFloat64
+			s, ok := exact.Uint64Val(y.val)
+			if !ok || s > stupidShift {
+				check.invalidOp(y.pos(), "stupid shift count %s", y)
+				x.mode = invalid
+				return
+			}
+			// The lhs is representable as an integer but may not be an integer
+			// (e.g., 2.0, an untyped float) - this can only happen for untyped
+			// non-integer numeric constants. Correct the type so that the shift
+			// result is of integer type.
+			if !isInteger(x.typ) {
+				x.typ = Typ[UntypedInt]
+			}
+			x.val = exact.Shift(x.val, op, uint(s))
+			return
+		}
+
+		// non-constant shift with constant lhs
+		if untypedx {
+			// spec: "If the left operand of a non-constant shift
+			// expression is an untyped constant, the type of the
+			// constant is what it would be if the shift expression
+			// were replaced by its left operand alone.".
+			//
+			// Delay operand checking until we know the final type:
+			// The lhs expression must be in the untyped map, mark
+			// the entry as lhs shift operand.
+			info, found := check.untyped[x.expr]
+			assert(found)
+			info.isLhs = true
+			check.untyped[x.expr] = info
+			// keep x's type
+			x.mode = value
+			return
+		}
+	}
+
+	// constant rhs must be >= 0
+	if y.mode == constant && exact.Sign(y.val) < 0 {
+		check.invalidOp(y.pos(), "shift count %s must not be negative", y)
+	}
+
+	// non-constant shift - lhs must be an integer
+	if !isInteger(x.typ) {
+		check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
+		x.mode = invalid
+		return
+	}
+
+	x.mode = value
+}
+
+var binaryOpPredicates = opPredicates{
+	token.ADD: func(typ Type) bool { return isNumeric(typ) || isString(typ) },
+	token.SUB: isNumeric,
+	token.MUL: isNumeric,
+	token.QUO: isNumeric,
+	token.REM: isInteger,
+
+	token.AND:     isInteger,
+	token.OR:      isInteger,
+	token.XOR:     isInteger,
+	token.AND_NOT: isInteger,
+
+	token.LAND: isBoolean,
+	token.LOR:  isBoolean,
+}
+
+func (check *Checker) binary(x *operand, lhs, rhs ast.Expr, op token.Token) {
+	var y operand
+
+	check.expr(x, lhs)
+	check.expr(&y, rhs)
+
+	if x.mode == invalid {
+		return
+	}
+	if y.mode == invalid {
+		x.mode = invalid
+		x.expr = y.expr
+		return
+	}
+
+	if isShift(op) {
+		check.shift(x, &y, op)
+		return
+	}
+
+	check.convertUntyped(x, y.typ)
+	if x.mode == invalid {
+		return
+	}
+	check.convertUntyped(&y, x.typ)
+	if y.mode == invalid {
+		x.mode = invalid
+		return
+	}
+
+	if isComparison(op) {
+		check.comparison(x, &y, op)
+		return
+	}
+
+	if !Identical(x.typ, y.typ) {
+		// only report an error if we have valid types
+		// (otherwise we had an error reported elsewhere already)
+		if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] {
+			check.invalidOp(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
+		}
+		x.mode = invalid
+		return
+	}
+
+	if !check.op(binaryOpPredicates, x, op) {
+		x.mode = invalid
+		return
+	}
+
+	if (op == token.QUO || op == token.REM) && (x.mode == constant || isInteger(x.typ)) && y.mode == constant && exact.Sign(y.val) == 0 {
+		check.invalidOp(y.pos(), "division by zero")
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant && y.mode == constant {
+		typ := x.typ.Underlying().(*Basic)
+		// force integer division of integer operands
+		if op == token.QUO && isInteger(typ) {
+			op = token.QUO_ASSIGN
+		}
+		x.val = exact.BinaryOp(x.val, op, y.val)
+		// Typed constants must be representable in
+		// their type after each constant operation.
+		if isTyped(typ) {
+			check.representable(x, typ)
+		}
+		return
+	}
+
+	x.mode = value
+	// x.typ is unchanged
+}
+
+// index checks an index expression for validity.
+// If max >= 0, it is the upper bound for index.
+// If index is valid and the result i >= 0, then i is the constant value of index.
+func (check *Checker) index(index ast.Expr, max int64) (i int64, valid bool) {
+	var x operand
+	check.expr(&x, index)
+	if x.mode == invalid {
+		return
+	}
+
+	// an untyped constant must be representable as Int
+	check.convertUntyped(&x, Typ[Int])
+	if x.mode == invalid {
+		return
+	}
+
+	// the index must be of integer type
+	if !isInteger(x.typ) {
+		check.invalidArg(x.pos(), "index %s must be integer", &x)
+		return
+	}
+
+	// a constant index i must be in bounds
+	if x.mode == constant {
+		if exact.Sign(x.val) < 0 {
+			check.invalidArg(x.pos(), "index %s must not be negative", &x)
+			return
+		}
+		i, valid = exact.Int64Val(x.val)
+		if !valid || max >= 0 && i >= max {
+			check.errorf(x.pos(), "index %s is out of bounds", &x)
+			return i, false
+		}
+		// 0 <= i [ && i < max ]
+		return i, true
+	}
+
+	return -1, true
+}
+
+// indexElts checks the elements (elts) of an array or slice composite literal
+// against the literal's element type (typ), and the element indices against
+// the literal length if known (length >= 0). It returns the length of the
+// literal (maximum index value + 1).
+//
+func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64 {
+	visited := make(map[int64]bool, len(elts))
+	var index, max int64
+	for _, e := range elts {
+		// determine and check index
+		validIndex := false
+		eval := e
+		if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+			if i, ok := check.index(kv.Key, length); ok {
+				if i >= 0 {
+					index = i
+					validIndex = true
+				} else {
+					check.errorf(e.Pos(), "index %s must be integer constant", kv.Key)
+				}
+			}
+			eval = kv.Value
+		} else if length >= 0 && index >= length {
+			check.errorf(e.Pos(), "index %d is out of bounds (>= %d)", index, length)
+		} else {
+			validIndex = true
+		}
+
+		// if we have a valid index, check for duplicate entries
+		if validIndex {
+			if visited[index] {
+				check.errorf(e.Pos(), "duplicate index %d in array or slice literal", index)
+			}
+			visited[index] = true
+		}
+		index++
+		if index > max {
+			max = index
+		}
+
+		// check element against composite literal element type
+		var x operand
+		check.exprWithHint(&x, eval, typ)
+		if !check.assignment(&x, typ) && x.mode != invalid {
+			check.errorf(x.pos(), "cannot use %s as %s value in array or slice literal", &x, typ)
+		}
+	}
+	return max
+}
+
+// exprKind describes the kind of an expression; the kind
+// determines if an expression is valid in 'statement context'.
+type exprKind int
+
+const (
+	conversion exprKind = iota
+	expression
+	statement
+)
+
+// rawExpr typechecks expression e and initializes x with the expression
+// value or type. If an error occurred, x.mode is set to invalid.
+// If hint != nil, it is the type of a composite literal element.
+//
+func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind {
+	if trace {
+		check.trace(e.Pos(), "%s", e)
+		check.indent++
+		defer func() {
+			check.indent--
+			check.trace(e.Pos(), "=> %s", x)
+		}()
+	}
+
+	kind := check.exprInternal(x, e, hint)
+
+	// convert x into a user-friendly set of values
+	// TODO(gri) this code can be simplified
+	var typ Type
+	var val exact.Value
+	switch x.mode {
+	case invalid:
+		typ = Typ[Invalid]
+	case novalue:
+		typ = (*Tuple)(nil)
+	case constant:
+		typ = x.typ
+		val = x.val
+	default:
+		typ = x.typ
+	}
+	assert(x.expr != nil && typ != nil)
+
+	if isUntyped(typ) {
+		// delay type and value recording until we know the type
+		// or until the end of type checking
+		check.rememberUntyped(x.expr, false, x.mode, typ.(*Basic), val)
+	} else {
+		check.recordTypeAndValue(e, x.mode, typ, val)
+	}
+
+	return kind
+}
+
+// exprInternal contains the core of type checking of expressions.
+// Must only be called by rawExpr.
+//
+func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
+	// make sure x has a valid state in case of bailout
+	// (was issue 5770)
+	x.mode = invalid
+	x.typ = Typ[Invalid]
+
+	switch e := e.(type) {
+	case *ast.BadExpr:
+		goto Error // error was reported before
+
+	case *ast.Ident:
+		check.ident(x, e, nil, nil)
+
+	case *ast.Ellipsis:
+		// ellipses are handled explicitly where they are legal
+		// (array composite literals and parameter lists)
+		check.error(e.Pos(), "invalid use of '...'")
+		goto Error
+
+	case *ast.BasicLit:
+		x.setConst(e.Kind, e.Value)
+		if x.mode == invalid {
+			check.invalidAST(e.Pos(), "invalid literal %v", e.Value)
+			goto Error
+		}
+
+	case *ast.FuncLit:
+		if sig, ok := check.typ(e.Type).(*Signature); ok {
+			// Anonymous functions are considered part of the
+			// init expression/func declaration which contains
+			// them: use existing package-level declaration info.
+			check.funcBody(check.decl, "", sig, e.Body)
+			x.mode = value
+			x.typ = sig
+		} else {
+			check.invalidAST(e.Pos(), "invalid function literal %s", e)
+			goto Error
+		}
+
+	case *ast.CompositeLit:
+		typ := hint
+		openArray := false
+		if e.Type != nil {
+			// [...]T array types may only appear with composite literals.
+			// Check for them here so we don't have to handle ... in general.
+			typ = nil
+			if atyp, _ := e.Type.(*ast.ArrayType); atyp != nil && atyp.Len != nil {
+				if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip != nil && ellip.Elt == nil {
+					// We have an "open" [...]T array type.
+					// Create a new ArrayType with unknown length (-1)
+					// and finish setting it up after analyzing the literal.
+					typ = &Array{len: -1, elem: check.typ(atyp.Elt)}
+					openArray = true
+				}
+			}
+			if typ == nil {
+				typ = check.typ(e.Type)
+			}
+		}
+		if typ == nil {
+			check.error(e.Pos(), "missing type in composite literal")
+			goto Error
+		}
+
+		switch typ, _ := deref(typ); utyp := typ.Underlying().(type) {
+		case *Struct:
+			if len(e.Elts) == 0 {
+				break
+			}
+			fields := utyp.fields
+			if _, ok := e.Elts[0].(*ast.KeyValueExpr); ok {
+				// all elements must have keys
+				visited := make([]bool, len(fields))
+				for _, e := range e.Elts {
+					kv, _ := e.(*ast.KeyValueExpr)
+					if kv == nil {
+						check.error(e.Pos(), "mixture of field:value and value elements in struct literal")
+						continue
+					}
+					key, _ := kv.Key.(*ast.Ident)
+					if key == nil {
+						check.errorf(kv.Pos(), "invalid field name %s in struct literal", kv.Key)
+						continue
+					}
+					i := fieldIndex(utyp.fields, check.pkg, key.Name)
+					if i < 0 {
+						check.errorf(kv.Pos(), "unknown field %s in struct literal", key.Name)
+						continue
+					}
+					fld := fields[i]
+					check.recordUse(key, fld)
+					// 0 <= i < len(fields)
+					if visited[i] {
+						check.errorf(kv.Pos(), "duplicate field name %s in struct literal", key.Name)
+						continue
+					}
+					visited[i] = true
+					check.expr(x, kv.Value)
+					etyp := fld.typ
+					if !check.assignment(x, etyp) {
+						if x.mode != invalid {
+							check.errorf(x.pos(), "cannot use %s as %s value in struct literal", x, etyp)
+						}
+						continue
+					}
+				}
+			} else {
+				// no element must have a key
+				for i, e := range e.Elts {
+					if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+						check.error(kv.Pos(), "mixture of field:value and value elements in struct literal")
+						continue
+					}
+					check.expr(x, e)
+					if i >= len(fields) {
+						check.error(x.pos(), "too many values in struct literal")
+						break // cannot continue
+					}
+					// i < len(fields)
+					etyp := fields[i].typ
+					if !check.assignment(x, etyp) {
+						if x.mode != invalid {
+							check.errorf(x.pos(), "cannot use %s as %s value in struct literal", x, etyp)
+						}
+						continue
+					}
+				}
+				if len(e.Elts) < len(fields) {
+					check.error(e.Rbrace, "too few values in struct literal")
+					// ok to continue
+				}
+			}
+
+		case *Array:
+			n := check.indexedElts(e.Elts, utyp.elem, utyp.len)
+			// if we have an "open" [...]T array, set the length now that we know it
+			if openArray {
+				utyp.len = n
+			}
+
+		case *Slice:
+			check.indexedElts(e.Elts, utyp.elem, -1)
+
+		case *Map:
+			visited := make(map[interface{}][]Type, len(e.Elts))
+			for _, e := range e.Elts {
+				kv, _ := e.(*ast.KeyValueExpr)
+				if kv == nil {
+					check.error(e.Pos(), "missing key in map literal")
+					continue
+				}
+				check.expr(x, kv.Key)
+				if !check.assignment(x, utyp.key) {
+					if x.mode != invalid {
+						check.errorf(x.pos(), "cannot use %s as %s key in map literal", x, utyp.key)
+					}
+					continue
+				}
+				if x.mode == constant {
+					duplicate := false
+					// if the key is of interface type, the type is also significant when checking for duplicates
+					if _, ok := utyp.key.Underlying().(*Interface); ok {
+						for _, vtyp := range visited[x.val] {
+							if Identical(vtyp, x.typ) {
+								duplicate = true
+								break
+							}
+						}
+						visited[x.val] = append(visited[x.val], x.typ)
+					} else {
+						_, duplicate = visited[x.val]
+						visited[x.val] = nil
+					}
+					if duplicate {
+						check.errorf(x.pos(), "duplicate key %s in map literal", x.val)
+						continue
+					}
+				}
+				check.exprWithHint(x, kv.Value, utyp.elem)
+				if !check.assignment(x, utyp.elem) {
+					if x.mode != invalid {
+						check.errorf(x.pos(), "cannot use %s as %s value in map literal", x, utyp.elem)
+					}
+					continue
+				}
+			}
+
+		default:
+			check.errorf(e.Pos(), "invalid composite literal type %s", typ)
+			goto Error
+		}
+
+		x.mode = value
+		x.typ = typ
+
+	case *ast.ParenExpr:
+		kind := check.rawExpr(x, e.X, nil)
+		x.expr = e
+		return kind
+
+	case *ast.SelectorExpr:
+		check.selector(x, e)
+
+	case *ast.IndexExpr:
+		check.expr(x, e.X)
+		if x.mode == invalid {
+			goto Error
+		}
+
+		valid := false
+		length := int64(-1) // valid if >= 0
+		switch typ := x.typ.Underlying().(type) {
+		case *Basic:
+			if isString(typ) {
+				valid = true
+				if x.mode == constant {
+					length = int64(len(exact.StringVal(x.val)))
+				}
+				// an indexed string always yields a byte value
+				// (not a constant) even if the string and the
+				// index are constant
+				x.mode = value
+				x.typ = UniverseByte // use 'byte' name
+			}
+
+		case *Array:
+			valid = true
+			length = typ.len
+			if x.mode != variable {
+				x.mode = value
+			}
+			x.typ = typ.elem
+
+		case *Pointer:
+			if typ, _ := typ.base.Underlying().(*Array); typ != nil {
+				valid = true
+				length = typ.len
+				x.mode = variable
+				x.typ = typ.elem
+			}
+
+		case *Slice:
+			valid = true
+			x.mode = variable
+			x.typ = typ.elem
+
+		case *Map:
+			var key operand
+			check.expr(&key, e.Index)
+			if !check.assignment(&key, typ.key) {
+				if key.mode != invalid {
+					check.invalidOp(key.pos(), "cannot use %s as map index of type %s", &key, typ.key)
+				}
+				goto Error
+			}
+			x.mode = mapindex
+			x.typ = typ.elem
+			x.expr = e
+			return expression
+		}
+
+		if !valid {
+			check.invalidOp(x.pos(), "cannot index %s", x)
+			goto Error
+		}
+
+		if e.Index == nil {
+			check.invalidAST(e.Pos(), "missing index for %s", x)
+			goto Error
+		}
+
+		check.index(e.Index, length)
+		// ok to continue
+
+	case *ast.SliceExpr:
+		check.expr(x, e.X)
+		if x.mode == invalid {
+			goto Error
+		}
+
+		valid := false
+		length := int64(-1) // valid if >= 0
+		switch typ := x.typ.Underlying().(type) {
+		case *Basic:
+			if isString(typ) {
+				if slice3(e) {
+					check.invalidOp(x.pos(), "3-index slice of string")
+					goto Error
+				}
+				valid = true
+				if x.mode == constant {
+					length = int64(len(exact.StringVal(x.val)))
+				}
+				// spec: "For untyped string operands the result
+				// is a non-constant value of type string."
+				if typ.kind == UntypedString {
+					x.typ = Typ[String]
+				}
+			}
+
+		case *Array:
+			valid = true
+			length = typ.len
+			if x.mode != variable {
+				check.invalidOp(x.pos(), "cannot slice %s (value not addressable)", x)
+				goto Error
+			}
+			x.typ = &Slice{elem: typ.elem}
+
+		case *Pointer:
+			if typ, _ := typ.base.Underlying().(*Array); typ != nil {
+				valid = true
+				length = typ.len
+				x.typ = &Slice{elem: typ.elem}
+			}
+
+		case *Slice:
+			valid = true
+			// x.typ doesn't change
+		}
+
+		if !valid {
+			check.invalidOp(x.pos(), "cannot slice %s", x)
+			goto Error
+		}
+
+		x.mode = value
+
+		// spec: "Only the first index may be omitted; it defaults to 0."
+		if slice3(e) && (e.High == nil || sliceMax(e) == nil) {
+			check.error(e.Rbrack, "2nd and 3rd index required in 3-index slice")
+			goto Error
+		}
+
+		// check indices
+		var ind [3]int64
+		for i, expr := range []ast.Expr{e.Low, e.High, sliceMax(e)} {
+			x := int64(-1)
+			switch {
+			case expr != nil:
+				// The "capacity" is only known statically for strings, arrays,
+				// and pointers to arrays, and it is the same as the length for
+				// those types.
+				max := int64(-1)
+				if length >= 0 {
+					max = length + 1
+				}
+				if t, ok := check.index(expr, max); ok && t >= 0 {
+					x = t
+				}
+			case i == 0:
+				// default is 0 for the first index
+				x = 0
+			case length >= 0:
+				// default is length (== capacity) otherwise
+				x = length
+			}
+			ind[i] = x
+		}
+
+		// constant indices must be in range
+		// (check.index already checks that existing indices >= 0)
+	L:
+		for i, x := range ind[:len(ind)-1] {
+			if x > 0 {
+				for _, y := range ind[i+1:] {
+					if y >= 0 && x > y {
+						check.errorf(e.Rbrack, "invalid slice indices: %d > %d", x, y)
+						break L // only report one error, ok to continue
+					}
+				}
+			}
+		}
+
+	case *ast.TypeAssertExpr:
+		check.expr(x, e.X)
+		if x.mode == invalid {
+			goto Error
+		}
+		xtyp, _ := x.typ.Underlying().(*Interface)
+		if xtyp == nil {
+			check.invalidOp(x.pos(), "%s is not an interface", x)
+			goto Error
+		}
+		// x.(type) expressions are handled explicitly in type switches
+		if e.Type == nil {
+			check.invalidAST(e.Pos(), "use of .(type) outside type switch")
+			goto Error
+		}
+		T := check.typ(e.Type)
+		if T == Typ[Invalid] {
+			goto Error
+		}
+		check.typeAssertion(x.pos(), x, xtyp, T)
+		x.mode = commaok
+		x.typ = T
+
+	case *ast.CallExpr:
+		return check.call(x, e)
+
+	case *ast.StarExpr:
+		check.exprOrType(x, e.X)
+		switch x.mode {
+		case invalid:
+			goto Error
+		case typexpr:
+			x.typ = &Pointer{base: x.typ}
+		default:
+			if typ, ok := x.typ.Underlying().(*Pointer); ok {
+				x.mode = variable
+				x.typ = typ.base
+			} else {
+				check.invalidOp(x.pos(), "cannot indirect %s", x)
+				goto Error
+			}
+		}
+
+	case *ast.UnaryExpr:
+		check.expr(x, e.X)
+		if x.mode == invalid {
+			goto Error
+		}
+		check.unary(x, e.Op)
+		if x.mode == invalid {
+			goto Error
+		}
+		if e.Op == token.ARROW {
+			x.expr = e
+			return statement // receive operations may appear in statement context
+		}
+
+	case *ast.BinaryExpr:
+		check.binary(x, e.X, e.Y, e.Op)
+		if x.mode == invalid {
+			goto Error
+		}
+
+	case *ast.KeyValueExpr:
+		// key:value expressions are handled in composite literals
+		check.invalidAST(e.Pos(), "no key:value expected")
+		goto Error
+
+	case *ast.ArrayType, *ast.StructType, *ast.FuncType,
+		*ast.InterfaceType, *ast.MapType, *ast.ChanType:
+		x.mode = typexpr
+		x.typ = check.typ(e)
+		// Note: rawExpr (caller of exprInternal) will call check.recordTypeAndValue
+		// even though check.typ has already called it. This is fine as both
+		// times the same expression and type are recorded. It is also not a
+		// performance issue because we only reach here for composite literal
+		// types, which are comparatively rare.
+
+	default:
+		panic(fmt.Sprintf("%s: unknown expression type %T", check.fset.Position(e.Pos()), e))
+	}
+
+	// everything went well
+	x.expr = e
+	return expression
+
+Error:
+	x.mode = invalid
+	x.expr = e
+	return statement // avoid follow-up errors
+}
+
+// typeAssertion checks that x.(T) is legal; xtyp must be the type of x.
+func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface, T Type) {
+	method, wrongType := assertableTo(xtyp, T)
+	if method == nil {
+		return
+	}
+
+	var msg string
+	if wrongType {
+		msg = "wrong type for method"
+	} else {
+		msg = "missing method"
+	}
+	check.errorf(pos, "%s cannot have dynamic type %s (%s %s)", x, T, msg, method.name)
+}
+
+// expr typechecks expression e and initializes x with the expression value.
+// If an error occurred, x.mode is set to invalid.
+//
+func (check *Checker) expr(x *operand, e ast.Expr) {
+	check.rawExpr(x, e, nil)
+	var msg string
+	switch x.mode {
+	default:
+		return
+	case novalue:
+		msg = "used as value"
+	case builtin:
+		msg = "must be called"
+	case typexpr:
+		msg = "is not an expression"
+	}
+	check.errorf(x.pos(), "%s %s", x, msg)
+	x.mode = invalid
+}
+
+// exprWithHint typechecks expression e and initializes x with the expression value.
+// If an error occurred, x.mode is set to invalid.
+// If hint != nil, it is the type of a composite literal element.
+//
+func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
+	assert(hint != nil)
+	check.rawExpr(x, e, hint)
+	var msg string
+	switch x.mode {
+	default:
+		return
+	case novalue:
+		msg = "used as value"
+	case builtin:
+		msg = "must be called"
+	case typexpr:
+		msg = "is not an expression"
+	}
+	check.errorf(x.pos(), "%s %s", x, msg)
+	x.mode = invalid
+}
+
+// exprOrType typechecks expression or type e and initializes x with the expression value or type.
+// If an error occurred, x.mode is set to invalid.
+//
+func (check *Checker) exprOrType(x *operand, e ast.Expr) {
+	check.rawExpr(x, e, nil)
+	if x.mode == novalue {
+		check.errorf(x.pos(), "%s used as value or type", x)
+		x.mode = invalid
+	}
+}
diff --git a/third_party/go.tools/go/types/exprstring.go b/third_party/go.tools/go/types/exprstring.go
new file mode 100644
index 0000000..370bdf3
--- /dev/null
+++ b/third_party/go.tools/go/types/exprstring.go
@@ -0,0 +1,220 @@
+// Copyright 2013 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.
+
+// This file implements printing of expressions.
+
+package types
+
+import (
+	"bytes"
+	"go/ast"
+)
+
+// ExprString returns the (possibly simplified) string representation for x.
+func ExprString(x ast.Expr) string {
+	var buf bytes.Buffer
+	WriteExpr(&buf, x)
+	return buf.String()
+}
+
+// WriteExpr writes the (possibly simplified) string representation for x to buf.
+func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
+	// The AST preserves source-level parentheses so there is
+	// no need to introduce them here to correct for different
+	// operator precedences. (This assumes that the AST was
+	// generated by a Go parser.)
+
+	switch x := x.(type) {
+	default:
+		buf.WriteString("(bad expr)") // nil, ast.BadExpr, ast.KeyValueExpr
+
+	case *ast.Ident:
+		buf.WriteString(x.Name)
+
+	case *ast.Ellipsis:
+		buf.WriteString("...")
+		if x.Elt != nil {
+			WriteExpr(buf, x.Elt)
+		}
+
+	case *ast.BasicLit:
+		buf.WriteString(x.Value)
+
+	case *ast.FuncLit:
+		buf.WriteByte('(')
+		WriteExpr(buf, x.Type)
+		buf.WriteString(" literal)") // simplified
+
+	case *ast.CompositeLit:
+		buf.WriteByte('(')
+		WriteExpr(buf, x.Type)
+		buf.WriteString(" literal)") // simplified
+
+	case *ast.ParenExpr:
+		buf.WriteByte('(')
+		WriteExpr(buf, x.X)
+		buf.WriteByte(')')
+
+	case *ast.SelectorExpr:
+		WriteExpr(buf, x.X)
+		buf.WriteByte('.')
+		buf.WriteString(x.Sel.Name)
+
+	case *ast.IndexExpr:
+		WriteExpr(buf, x.X)
+		buf.WriteByte('[')
+		WriteExpr(buf, x.Index)
+		buf.WriteByte(']')
+
+	case *ast.SliceExpr:
+		WriteExpr(buf, x.X)
+		buf.WriteByte('[')
+		if x.Low != nil {
+			WriteExpr(buf, x.Low)
+		}
+		buf.WriteByte(':')
+		if x.High != nil {
+			WriteExpr(buf, x.High)
+		}
+		if x.Slice3 {
+			buf.WriteByte(':')
+			if x.Max != nil {
+				WriteExpr(buf, x.Max)
+			}
+		}
+		buf.WriteByte(']')
+
+	case *ast.TypeAssertExpr:
+		WriteExpr(buf, x.X)
+		buf.WriteString(".(")
+		WriteExpr(buf, x.Type)
+		buf.WriteByte(')')
+
+	case *ast.CallExpr:
+		WriteExpr(buf, x.Fun)
+		buf.WriteByte('(')
+		for i, arg := range x.Args {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			WriteExpr(buf, arg)
+		}
+		if x.Ellipsis.IsValid() {
+			buf.WriteString("...")
+		}
+		buf.WriteByte(')')
+
+	case *ast.StarExpr:
+		buf.WriteByte('*')
+		WriteExpr(buf, x.X)
+
+	case *ast.UnaryExpr:
+		buf.WriteString(x.Op.String())
+		WriteExpr(buf, x.X)
+
+	case *ast.BinaryExpr:
+		WriteExpr(buf, x.X)
+		buf.WriteByte(' ')
+		buf.WriteString(x.Op.String())
+		buf.WriteByte(' ')
+		WriteExpr(buf, x.Y)
+
+	case *ast.ArrayType:
+		buf.WriteByte('[')
+		if x.Len != nil {
+			WriteExpr(buf, x.Len)
+		}
+		buf.WriteByte(']')
+		WriteExpr(buf, x.Elt)
+
+	case *ast.StructType:
+		buf.WriteString("struct{")
+		writeFieldList(buf, x.Fields, "; ", false)
+		buf.WriteByte('}')
+
+	case *ast.FuncType:
+		buf.WriteString("func")
+		writeSigExpr(buf, x)
+
+	case *ast.InterfaceType:
+		buf.WriteString("interface{")
+		writeFieldList(buf, x.Methods, "; ", true)
+		buf.WriteByte('}')
+
+	case *ast.MapType:
+		buf.WriteString("map[")
+		WriteExpr(buf, x.Key)
+		buf.WriteByte(']')
+		WriteExpr(buf, x.Value)
+
+	case *ast.ChanType:
+		var s string
+		switch x.Dir {
+		case ast.SEND:
+			s = "chan<- "
+		case ast.RECV:
+			s = "<-chan "
+		default:
+			s = "chan "
+		}
+		buf.WriteString(s)
+		WriteExpr(buf, x.Value)
+	}
+}
+
+func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) {
+	buf.WriteByte('(')
+	writeFieldList(buf, sig.Params, ", ", false)
+	buf.WriteByte(')')
+
+	res := sig.Results
+	n := res.NumFields()
+	if n == 0 {
+		// no result
+		return
+	}
+
+	buf.WriteByte(' ')
+	if n == 1 && len(res.List[0].Names) == 0 {
+		// single unnamed result
+		WriteExpr(buf, res.List[0].Type)
+		return
+	}
+
+	// multiple or named result(s)
+	buf.WriteByte('(')
+	writeFieldList(buf, res, ", ", false)
+	buf.WriteByte(')')
+}
+
+func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface bool) {
+	for i, f := range fields.List {
+		if i > 0 {
+			buf.WriteString(sep)
+		}
+
+		// field list names
+		for i, name := range f.Names {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			buf.WriteString(name.Name)
+		}
+
+		// types of interface methods consist of signatures only
+		if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface {
+			writeSigExpr(buf, sig)
+			continue
+		}
+
+		// named fields are separated with a blank from the field type
+		if len(f.Names) > 0 {
+			buf.WriteByte(' ')
+		}
+
+		WriteExpr(buf, f.Type)
+
+		// ignore tag
+	}
+}
diff --git a/third_party/go.tools/go/types/exprstring_test.go b/third_party/go.tools/go/types/exprstring_test.go
new file mode 100644
index 0000000..48a6b4c
--- /dev/null
+++ b/third_party/go.tools/go/types/exprstring_test.go
@@ -0,0 +1,94 @@
+// Copyright 2013 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 types_test
+
+import (
+	"go/parser"
+	"testing"
+
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var testExprs = []testEntry{
+	// basic type literals
+	dup("x"),
+	dup("true"),
+	dup("42"),
+	dup("3.1415"),
+	dup("2.71828i"),
+	dup(`'a'`),
+	dup(`"foo"`),
+	dup("`bar`"),
+
+	// func and composite literals
+	{"func(){}", "(func() literal)"},
+	{"func(x int) complex128 {}", "(func(x int) complex128 literal)"},
+	{"[]int{1, 2, 3}", "([]int literal)"},
+
+	// non-type expressions
+	dup("(x)"),
+	dup("x.f"),
+	dup("a[i]"),
+
+	dup("s[:]"),
+	dup("s[i:]"),
+	dup("s[:j]"),
+	dup("s[i:j]"),
+	dup("s[:j:k]"),
+	dup("s[i:j:k]"),
+
+	dup("x.(T)"),
+
+	dup("x.([10]int)"),
+	dup("x.([...]int)"),
+
+	dup("x.(struct{})"),
+	dup("x.(struct{x int; y, z float32; E})"),
+
+	dup("x.(func())"),
+	dup("x.(func(x int))"),
+	dup("x.(func() int)"),
+	dup("x.(func(x, y int, z float32) (r int))"),
+	dup("x.(func(a, b, c int))"),
+	dup("x.(func(x ...T))"),
+
+	dup("x.(interface{})"),
+	dup("x.(interface{m(); n(x int); E})"),
+	dup("x.(interface{m(); n(x int) T; E; F})"),
+
+	dup("x.(map[K]V)"),
+
+	dup("x.(chan E)"),
+	dup("x.(<-chan E)"),
+	dup("x.(chan<- chan int)"),
+	dup("x.(chan<- <-chan int)"),
+	dup("x.(<-chan chan int)"),
+	dup("x.(chan (<-chan int))"),
+
+	dup("f()"),
+	dup("f(x)"),
+	dup("int(x)"),
+	dup("f(x, x + y)"),
+	dup("f(s...)"),
+	dup("f(a, s...)"),
+
+	dup("*x"),
+	dup("&x"),
+	dup("x + y"),
+	dup("x + y << (2 * s)"),
+}
+
+func TestExprString(t *testing.T) {
+	for _, test := range testExprs {
+		x, err := parser.ParseExpr(test.src)
+		if err != nil {
+			t.Errorf("%s: %s", test.src, err)
+			continue
+		}
+		if got := ExprString(x); got != test.str {
+			t.Errorf("%s: got %s, want %s", test.src, got, test.str)
+		}
+	}
+}
diff --git a/third_party/go.tools/go/types/go11.go b/third_party/go.tools/go/types/go11.go
new file mode 100644
index 0000000..cf41cab
--- /dev/null
+++ b/third_party/go.tools/go/types/go11.go
@@ -0,0 +1,17 @@
+// Copyright 2013 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.
+
+// +build !go1.2
+
+package types
+
+import "go/ast"
+
+func slice3(x *ast.SliceExpr) bool {
+	return false
+}
+
+func sliceMax(x *ast.SliceExpr) ast.Expr {
+	return nil
+}
diff --git a/third_party/go.tools/go/types/go12.go b/third_party/go.tools/go/types/go12.go
new file mode 100644
index 0000000..2017442
--- /dev/null
+++ b/third_party/go.tools/go/types/go12.go
@@ -0,0 +1,17 @@
+// Copyright 2013 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.
+
+// +build go1.2
+
+package types
+
+import "go/ast"
+
+func slice3(x *ast.SliceExpr) bool {
+	return x.Slice3
+}
+
+func sliceMax(x *ast.SliceExpr) ast.Expr {
+	return x.Max
+}
diff --git a/third_party/go.tools/go/types/hilbert_test.go b/third_party/go.tools/go/types/hilbert_test.go
new file mode 100644
index 0000000..521223a
--- /dev/null
+++ b/third_party/go.tools/go/types/hilbert_test.go
@@ -0,0 +1,232 @@
+// Copyright 2013 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 types_test
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"testing"
+
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var (
+	H   = flag.Int("H", 5, "Hilbert matrix size")
+	out = flag.String("out", "", "write generated program to out")
+)
+
+func TestHilbert(t *testing.T) {
+	// generate source
+	src := program(*H, *out)
+	if *out != "" {
+		ioutil.WriteFile(*out, src, 0666)
+		return
+	}
+
+	// parse source
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "hilbert.go", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// type-check file
+	DefPredeclaredTestFuncs() // define assert built-in
+	_, err = Check(f.Name.Name, fset, []*ast.File{f})
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func program(n int, out string) []byte {
+	var g gen
+
+	g.p(`// WARNING: GENERATED FILE - DO NOT MODIFY MANUALLY!
+// (To generate, in go/types directory: go test -run=Hilbert -H=%d -out=%q)
+
+// This program tests arbitrary precision constant arithmetic
+// by generating the constant elements of a Hilbert matrix H,
+// its inverse I, and the product P = H*I. The product should
+// be the identity matrix.
+package main
+
+func main() {
+	if !ok {
+		printProduct()
+		return
+	}
+	println("PASS")
+}
+
+`, n, out)
+	g.hilbert(n)
+	g.inverse(n)
+	g.product(n)
+	g.verify(n)
+	g.printProduct(n)
+	g.binomials(2*n - 1)
+	g.factorials(2*n - 1)
+
+	return g.Bytes()
+}
+
+type gen struct {
+	bytes.Buffer
+}
+
+func (g *gen) p(format string, args ...interface{}) {
+	fmt.Fprintf(&g.Buffer, format, args...)
+}
+
+func (g *gen) hilbert(n int) {
+	g.p(`// Hilbert matrix, n = %d
+const (
+`, n)
+	for i := 0; i < n; i++ {
+		g.p("\t")
+		for j := 0; j < n; j++ {
+			if j > 0 {
+				g.p(", ")
+			}
+			g.p("h%d_%d", i, j)
+		}
+		if i == 0 {
+			g.p(" = ")
+			for j := 0; j < n; j++ {
+				if j > 0 {
+					g.p(", ")
+				}
+				g.p("1.0/(iota + %d)", j+1)
+			}
+		}
+		g.p("\n")
+	}
+	g.p(")\n\n")
+}
+
+func (g *gen) inverse(n int) {
+	g.p(`// Inverse Hilbert matrix
+const (
+`)
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			s := "+"
+			if (i+j)&1 != 0 {
+				s = "-"
+			}
+			g.p("\ti%d_%d = %s%d * b%d_%d * b%d_%d * b%d_%d * b%d_%d\n",
+				i, j, s, i+j+1, n+i, n-j-1, n+j, n-i-1, i+j, i, i+j, i)
+		}
+		g.p("\n")
+	}
+	g.p(")\n\n")
+}
+
+func (g *gen) product(n int) {
+	g.p(`// Product matrix
+const (
+`)
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			g.p("\tp%d_%d = ", i, j)
+			for k := 0; k < n; k++ {
+				if k > 0 {
+					g.p(" + ")
+				}
+				g.p("h%d_%d*i%d_%d", i, k, k, j)
+			}
+			g.p("\n")
+		}
+		g.p("\n")
+	}
+	g.p(")\n\n")
+}
+
+func (g *gen) verify(n int) {
+	g.p(`// Verify that product is the identity matrix
+const ok =
+`)
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			if j == 0 {
+				g.p("\t")
+			} else {
+				g.p(" && ")
+			}
+			v := 0
+			if i == j {
+				v = 1
+			}
+			g.p("p%d_%d == %d", i, j, v)
+		}
+		g.p(" &&\n")
+	}
+	g.p("\ttrue\n\n")
+
+	// verify ok at type-check time
+	if *out == "" {
+		g.p("const _ = assert(ok)\n\n")
+	}
+}
+
+func (g *gen) printProduct(n int) {
+	g.p("func printProduct() {\n")
+	for i := 0; i < n; i++ {
+		g.p("\tprintln(")
+		for j := 0; j < n; j++ {
+			if j > 0 {
+				g.p(", ")
+			}
+			g.p("p%d_%d", i, j)
+		}
+		g.p(")\n")
+	}
+	g.p("}\n\n")
+}
+
+func (g *gen) mulRange(a, b int) {
+	if a > b {
+		g.p("1")
+		return
+	}
+	for i := a; i <= b; i++ {
+		if i > a {
+			g.p("*")
+		}
+		g.p("%d", i)
+	}
+}
+
+func (g *gen) binomials(n int) {
+	g.p(`// Binomials
+const (
+`)
+	for j := 0; j <= n; j++ {
+		if j > 0 {
+			g.p("\n")
+		}
+		for k := 0; k <= j; k++ {
+			g.p("\tb%d_%d = f%d / (f%d*f%d)\n", j, k, j, k, j-k)
+		}
+	}
+	g.p(")\n\n")
+}
+
+func (g *gen) factorials(n int) {
+	g.p(`// Factorials
+const (
+	f0 = 1
+	f1 = 1
+`)
+	for i := 2; i <= n; i++ {
+		g.p("\tf%d = f%d * %d\n", i, i-1, i)
+	}
+	g.p(")\n\n")
+}
diff --git a/third_party/go.tools/go/types/initorder.go b/third_party/go.tools/go/types/initorder.go
new file mode 100644
index 0000000..0fd567b
--- /dev/null
+++ b/third_party/go.tools/go/types/initorder.go
@@ -0,0 +1,222 @@
+// Copyright 2014 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 types
+
+import (
+	"container/heap"
+	"fmt"
+)
+
+// initOrder computes the Info.InitOrder for package variables.
+func (check *Checker) initOrder() {
+	// An InitOrder may already have been computed if a package is
+	// built from several calls to (*Checker).Files.  Clear it.
+	check.Info.InitOrder = check.Info.InitOrder[:0]
+
+	// compute the object dependency graph and
+	// initialize a priority queue with the list
+	// of graph nodes
+	pq := nodeQueue(dependencyGraph(check.objMap))
+	heap.Init(&pq)
+
+	const debug = false
+	if debug {
+		fmt.Printf("package %s: object dependency graph\n", check.pkg.Name())
+		for _, n := range pq {
+			for _, o := range n.out {
+				fmt.Printf("\t%s -> %s\n", n.obj.Name(), o.obj.Name())
+			}
+		}
+		fmt.Println()
+		fmt.Printf("package %s: initialization order\n", check.pkg.Name())
+	}
+
+	// determine initialization order by removing the highest priority node
+	// (the one with the fewest dependencies) and its edges from the graph,
+	// repeatedly, until there are no nodes left.
+	// In a valid Go program, those nodes always have zero dependencies (after
+	// removing all incoming dependencies), otherwise there are initialization
+	// cycles.
+	mark := 0
+	emitted := make(map[*declInfo]bool)
+	for len(pq) > 0 {
+		// get the next node
+		n := heap.Pop(&pq).(*objNode)
+
+		// if n still depends on other nodes, we have a cycle
+		if n.in > 0 {
+			mark++ // mark nodes using a different value each time
+			cycle := findPath(n, n, mark)
+			if i := valIndex(cycle); i >= 0 {
+				check.reportCycle(cycle, i)
+			}
+			// ok to continue, but the variable initialization order
+			// will be incorrect at this point since it assumes no
+			// cycle errors
+		}
+
+		// reduce dependency count of all dependent nodes
+		// and update priority queue
+		for _, out := range n.out {
+			out.in--
+			heap.Fix(&pq, out.index)
+		}
+
+		// record the init order for variables with initializers only
+		v, _ := n.obj.(*Var)
+		info := check.objMap[v]
+		if v == nil || !info.hasInitializer() {
+			continue
+		}
+
+		// n:1 variable declarations such as: a, b = f()
+		// introduce a node for each lhs variable (here: a, b);
+		// but they all have the same initializer - emit only
+		// one, for the first variable seen
+		if emitted[info] {
+			continue // initializer already emitted, if any
+		}
+		emitted[info] = true
+
+		infoLhs := info.lhs // possibly nil (see declInfo.lhs field comment)
+		if infoLhs == nil {
+			infoLhs = []*Var{v}
+		}
+		init := &Initializer{infoLhs, info.init}
+		check.Info.InitOrder = append(check.Info.InitOrder, init)
+
+		if debug {
+			fmt.Printf("\t%s\n", init)
+		}
+	}
+
+	if debug {
+		fmt.Println()
+	}
+}
+
+// findPath returns the (reversed) list of nodes z, ... c, b, a,
+// such that there is a path (list of edges) from a to z.
+// If there is no such path, the result is nil.
+// Nodes marked with the value mark are considered "visited";
+// unvisited nodes are marked during the graph search.
+func findPath(a, z *objNode, mark int) []*objNode {
+	if a.mark == mark {
+		return nil // node already seen
+	}
+	a.mark = mark
+
+	for _, n := range a.out {
+		if n == z {
+			return []*objNode{z}
+		}
+		if P := findPath(n, z, mark); P != nil {
+			return append(P, n)
+		}
+	}
+
+	return nil
+}
+
+// valIndex returns the index of the first constant or variable in a,
+// if any; or a value < 0.
+func valIndex(a []*objNode) int {
+	for i, n := range a {
+		switch n.obj.(type) {
+		case *Const, *Var:
+			return i
+		}
+	}
+	return -1
+}
+
+// reportCycle reports an error for the cycle starting at i.
+func (check *Checker) reportCycle(cycle []*objNode, i int) {
+	obj := cycle[i].obj
+	check.errorf(obj.Pos(), "initialization cycle for %s", obj.Name())
+	// print cycle
+	for _ = range cycle {
+		check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
+		i++
+		if i >= len(cycle) {
+			i = 0
+		}
+		obj = cycle[i].obj
+	}
+	check.errorf(obj.Pos(), "\t%s", obj.Name())
+}
+
+// An objNode represents a node in the object dependency graph.
+// Each node b in a.out represents an edge a->b indicating that
+// b depends on a.
+// Nodes may be marked for cycle detection. A node n is marked
+// if n.mark corresponds to the current mark value.
+type objNode struct {
+	obj   Object     // object represented by this node
+	in    int        // number of nodes this node depends on
+	out   []*objNode // list of nodes that depend on this node
+	index int        // node index in list of nodes
+	mark  int        // for cycle detection
+}
+
+// dependencyGraph computes the transposed object dependency graph
+// from the given objMap. The transposed graph is returned as a list
+// of nodes; an edge d->n indicates that node n depends on node d.
+func dependencyGraph(objMap map[Object]*declInfo) []*objNode {
+	// M maps each object to its corresponding node
+	M := make(map[Object]*objNode, len(objMap))
+	for obj := range objMap {
+		M[obj] = &objNode{obj: obj}
+	}
+
+	// G is the graph of nodes n
+	G := make([]*objNode, len(M))
+	i := 0
+	for obj, n := range M {
+		deps := objMap[obj].deps
+		n.in = len(deps)
+		for d := range deps {
+			d := M[d]                // node n depends on node d
+			d.out = append(d.out, n) // add edge d->n
+		}
+
+		G[i] = n
+		n.index = i
+		i++
+	}
+
+	return G
+}
+
+// nodeQueue implements the container/heap interface;
+// a nodeQueue may be used as a priority queue.
+type nodeQueue []*objNode
+
+func (a nodeQueue) Len() int { return len(a) }
+
+func (a nodeQueue) Swap(i, j int) {
+	x, y := a[i], a[j]
+	a[i], a[j] = y, x
+	x.index, y.index = j, i
+}
+
+func (a nodeQueue) Less(i, j int) bool {
+	x, y := a[i], a[j]
+	// nodes are prioritized by number of incoming dependencies (1st key)
+	// and source order (2nd key)
+	return x.in < y.in || x.in == y.in && x.obj.order() < y.obj.order()
+}
+
+func (a *nodeQueue) Push(x interface{}) {
+	panic("unreachable")
+}
+
+func (a *nodeQueue) Pop() interface{} {
+	n := len(*a)
+	x := (*a)[n-1]
+	x.index = -1 // for safety
+	*a = (*a)[:n-1]
+	return x
+}
diff --git a/third_party/go.tools/go/types/issues_test.go b/third_party/go.tools/go/types/issues_test.go
new file mode 100644
index 0000000..02b81fe
--- /dev/null
+++ b/third_party/go.tools/go/types/issues_test.go
@@ -0,0 +1,205 @@
+// Copyright 2013 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.
+
+// This file implements tests for various issues.
+
+package types_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"sort"
+	"strings"
+	"testing"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func TestIssue5770(t *testing.T) {
+	src := `package p; type S struct{T}`
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	_, err = Check(f.Name.Name, fset, []*ast.File{f}) // do not crash
+	want := "undeclared name: T"
+	if err == nil || !strings.Contains(err.Error(), want) {
+		t.Errorf("got: %v; want: %s", err, want)
+	}
+}
+
+func TestIssue5849(t *testing.T) {
+	src := `
+package p
+var (
+	s uint
+	_ = uint8(8)
+	_ = uint16(16) << s
+	_ = uint32(32 << s)
+	_ = uint64(64 << s + s)
+	_ = (interface{})("foo")
+	_ = (interface{})(nil)
+)`
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var conf Config
+	types := make(map[ast.Expr]TypeAndValue)
+	_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	for x, tv := range types {
+		var want Type
+		switch x := x.(type) {
+		case *ast.BasicLit:
+			switch x.Value {
+			case `8`:
+				want = Typ[Uint8]
+			case `16`:
+				want = Typ[Uint16]
+			case `32`:
+				want = Typ[Uint32]
+			case `64`:
+				want = Typ[Uint] // because of "+ s", s is of type uint
+			case `"foo"`:
+				want = Typ[String]
+			}
+		case *ast.Ident:
+			if x.Name == "nil" {
+				want = Typ[UntypedNil]
+			}
+		}
+		if want != nil && !Identical(tv.Type, want) {
+			t.Errorf("got %s; want %s", tv.Type, want)
+		}
+	}
+}
+
+func TestIssue6413(t *testing.T) {
+	src := `
+package p
+func f() int {
+	defer f()
+	go f()
+	return 0
+}
+`
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var conf Config
+	types := make(map[ast.Expr]TypeAndValue)
+	_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	want := Typ[Int]
+	n := 0
+	for x, tv := range types {
+		if _, ok := x.(*ast.CallExpr); ok {
+			if tv.Type != want {
+				t.Errorf("%s: got %s; want %s", fset.Position(x.Pos()), tv.Type, want)
+			}
+			n++
+		}
+	}
+
+	if n != 2 {
+		t.Errorf("got %d CallExprs; want 2", n)
+	}
+}
+
+func TestIssue7245(t *testing.T) {
+	src := `
+package p
+func (T) m() (res bool) { return }
+type T struct{} // receiver type after method declaration
+`
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var conf Config
+	defs := make(map[*ast.Ident]Object)
+	_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	m := f.Decls[0].(*ast.FuncDecl)
+	res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0)
+	res2 := defs[m.Type.Results.List[0].Names[0]].(*Var)
+
+	if res1 != res2 {
+		t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2)
+	}
+}
+
+// This tests that uses of existing vars on the LHS of an assignment
+// are Uses, not Defs; and also that the (illegal) use of a non-var on
+// the LHS of an assignment is a Use nonetheless.
+func TestIssue7827(t *testing.T) {
+	const src = `
+package p
+func _() {
+	const w = 1        // defs w
+        x, y := 2, 3       // defs x, y
+        w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w
+        _, _, _ = x, y, z  // uses x, y, z
+}
+`
+	const want = `L3 defs func p._()
+L4 defs const w untyped int
+L5 defs var x int
+L5 defs var y int
+L6 defs var z int
+L6 uses const w untyped int
+L6 uses var x int
+L7 uses var x int
+L7 uses var y int
+L7 uses var z int`
+
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// don't abort at the first error
+	conf := Config{Error: func(err error) { t.Log(err) }}
+	defs := make(map[*ast.Ident]Object)
+	uses := make(map[*ast.Ident]Object)
+	_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses})
+	if s := fmt.Sprint(err); !strings.HasSuffix(s, "cannot assign to w") {
+		t.Errorf("Check: unexpected error: %s", s)
+	}
+
+	var facts []string
+	for id, obj := range defs {
+		if obj != nil {
+			fact := fmt.Sprintf("L%d defs %s", fset.Position(id.Pos()).Line, obj)
+			facts = append(facts, fact)
+		}
+	}
+	for id, obj := range uses {
+		fact := fmt.Sprintf("L%d uses %s", fset.Position(id.Pos()).Line, obj)
+		facts = append(facts, fact)
+	}
+	sort.Strings(facts)
+
+	got := strings.Join(facts, "\n")
+	if got != want {
+		t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
+	}
+}
diff --git a/third_party/go.tools/go/types/labels.go b/third_party/go.tools/go/types/labels.go
new file mode 100644
index 0000000..d6ffc52
--- /dev/null
+++ b/third_party/go.tools/go/types/labels.go
@@ -0,0 +1,268 @@
+// Copyright 2013 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 types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// labels checks correct label use in body.
+func (check *Checker) labels(body *ast.BlockStmt) {
+	// set of all labels in this body
+	all := NewScope(nil, "label")
+
+	fwdJumps := check.blockBranches(all, nil, nil, body.List)
+
+	// If there are any forward jumps left, no label was found for
+	// the corresponding goto statements. Either those labels were
+	// never defined, or they are inside blocks and not reachable
+	// for the respective gotos.
+	for _, jmp := range fwdJumps {
+		var msg string
+		name := jmp.Label.Name
+		if alt := all.Lookup(name); alt != nil {
+			msg = "goto %s jumps into block"
+			alt.(*Label).used = true // avoid another error
+		} else {
+			msg = "label %s not declared"
+		}
+		check.errorf(jmp.Label.Pos(), msg, name)
+	}
+
+	// spec: "It is illegal to define a label that is never used."
+	for _, obj := range all.elems {
+		if lbl := obj.(*Label); !lbl.used {
+			check.softErrorf(lbl.pos, "label %s declared but not used", lbl.name)
+		}
+	}
+}
+
+// A block tracks label declarations in a block and its enclosing blocks.
+type block struct {
+	parent *block                      // enclosing block
+	lstmt  *ast.LabeledStmt            // labeled statement to which this block belongs, or nil
+	labels map[string]*ast.LabeledStmt // allocated lazily
+}
+
+// insert records a new label declaration for the current block.
+// The label must not have been declared before in any block.
+func (b *block) insert(s *ast.LabeledStmt) {
+	name := s.Label.Name
+	if debug {
+		assert(b.gotoTarget(name) == nil)
+	}
+	labels := b.labels
+	if labels == nil {
+		labels = make(map[string]*ast.LabeledStmt)
+		b.labels = labels
+	}
+	labels[name] = s
+}
+
+// gotoTarget returns the labeled statement in the current
+// or an enclosing block with the given label name, or nil.
+func (b *block) gotoTarget(name string) *ast.LabeledStmt {
+	for s := b; s != nil; s = s.parent {
+		if t := s.labels[name]; t != nil {
+			return t
+		}
+	}
+	return nil
+}
+
+// enclosingTarget returns the innermost enclosing labeled
+// statement with the given label name, or nil.
+func (b *block) enclosingTarget(name string) *ast.LabeledStmt {
+	for s := b; s != nil; s = s.parent {
+		if t := s.lstmt; t != nil && t.Label.Name == name {
+			return t
+		}
+	}
+	return nil
+}
+
+// blockBranches processes a block's statement list and returns the set of outgoing forward jumps.
+// all is the scope of all declared labels, parent the set of labels declared in the immediately
+// enclosing block, and lstmt is the labeled statement this block is associated with (or nil).
+func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.LabeledStmt, list []ast.Stmt) []*ast.BranchStmt {
+	b := &block{parent: parent, lstmt: lstmt}
+
+	var (
+		varDeclPos         token.Pos
+		fwdJumps, badJumps []*ast.BranchStmt
+	)
+
+	// All forward jumps jumping over a variable declaration are possibly
+	// invalid (they may still jump out of the block and be ok).
+	// recordVarDecl records them for the given position.
+	recordVarDecl := func(pos token.Pos) {
+		varDeclPos = pos
+		badJumps = append(badJumps[:0], fwdJumps...) // copy fwdJumps to badJumps
+	}
+
+	jumpsOverVarDecl := func(jmp *ast.BranchStmt) bool {
+		if varDeclPos.IsValid() {
+			for _, bad := range badJumps {
+				if jmp == bad {
+					return true
+				}
+			}
+		}
+		return false
+	}
+
+	blockBranches := func(lstmt *ast.LabeledStmt, list []ast.Stmt) {
+		// Unresolved forward jumps inside the nested block
+		// become forward jumps in the current block.
+		fwdJumps = append(fwdJumps, check.blockBranches(all, b, lstmt, list)...)
+	}
+
+	var stmtBranches func(ast.Stmt)
+	stmtBranches = func(s ast.Stmt) {
+		switch s := s.(type) {
+		case *ast.DeclStmt:
+			if d, _ := s.Decl.(*ast.GenDecl); d != nil && d.Tok == token.VAR {
+				recordVarDecl(d.Pos())
+			}
+
+		case *ast.LabeledStmt:
+			// declare non-blank label
+			if name := s.Label.Name; name != "_" {
+				lbl := NewLabel(s.Label.Pos(), check.pkg, name)
+				if alt := all.Insert(lbl); alt != nil {
+					check.softErrorf(lbl.pos, "label %s already declared", name)
+					check.reportAltDecl(alt)
+					// ok to continue
+				} else {
+					b.insert(s)
+					check.recordDef(s.Label, lbl)
+				}
+				// resolve matching forward jumps and remove them from fwdJumps
+				i := 0
+				for _, jmp := range fwdJumps {
+					if jmp.Label.Name == name {
+						// match
+						lbl.used = true
+						check.recordUse(jmp.Label, lbl)
+						if jumpsOverVarDecl(jmp) {
+							check.softErrorf(
+								jmp.Label.Pos(),
+								"goto %s jumps over variable declaration at line %d",
+								name,
+								check.fset.Position(varDeclPos).Line,
+							)
+							// ok to continue
+						}
+					} else {
+						// no match - record new forward jump
+						fwdJumps[i] = jmp
+						i++
+					}
+				}
+				fwdJumps = fwdJumps[:i]
+				lstmt = s
+			}
+			stmtBranches(s.Stmt)
+
+		case *ast.BranchStmt:
+			if s.Label == nil {
+				return // checked in 1st pass (check.stmt)
+			}
+
+			// determine and validate target
+			name := s.Label.Name
+			switch s.Tok {
+			case token.BREAK:
+				// spec: "If there is a label, it must be that of an enclosing
+				// "for", "switch", or "select" statement, and that is the one
+				// whose execution terminates."
+				valid := false
+				if t := b.enclosingTarget(name); t != nil {
+					switch t.Stmt.(type) {
+					case *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt, *ast.ForStmt, *ast.RangeStmt:
+						valid = true
+					}
+				}
+				if !valid {
+					check.errorf(s.Label.Pos(), "invalid break label %s", name)
+					return
+				}
+
+			case token.CONTINUE:
+				// spec: "If there is a label, it must be that of an enclosing
+				// "for" statement, and that is the one whose execution advances."
+				valid := false
+				if t := b.enclosingTarget(name); t != nil {
+					switch t.Stmt.(type) {
+					case *ast.ForStmt, *ast.RangeStmt:
+						valid = true
+					}
+				}
+				if !valid {
+					check.errorf(s.Label.Pos(), "invalid continue label %s", name)
+					return
+				}
+
+			case token.GOTO:
+				if b.gotoTarget(name) == nil {
+					// label may be declared later - add branch to forward jumps
+					fwdJumps = append(fwdJumps, s)
+					return
+				}
+
+			default:
+				check.invalidAST(s.Pos(), "branch statement: %s %s", s.Tok, name)
+				return
+			}
+
+			// record label use
+			obj := all.Lookup(name)
+			obj.(*Label).used = true
+			check.recordUse(s.Label, obj)
+
+		case *ast.AssignStmt:
+			if s.Tok == token.DEFINE {
+				recordVarDecl(s.Pos())
+			}
+
+		case *ast.BlockStmt:
+			blockBranches(lstmt, s.List)
+
+		case *ast.IfStmt:
+			stmtBranches(s.Body)
+			if s.Else != nil {
+				stmtBranches(s.Else)
+			}
+
+		case *ast.CaseClause:
+			blockBranches(nil, s.Body)
+
+		case *ast.SwitchStmt:
+			stmtBranches(s.Body)
+
+		case *ast.TypeSwitchStmt:
+			stmtBranches(s.Body)
+
+		case *ast.CommClause:
+			blockBranches(nil, s.Body)
+
+		case *ast.SelectStmt:
+			stmtBranches(s.Body)
+
+		case *ast.ForStmt:
+			stmtBranches(s.Body)
+
+		case *ast.RangeStmt:
+			stmtBranches(s.Body)
+		}
+	}
+
+	for _, s := range list {
+		stmtBranches(s)
+	}
+
+	return fwdJumps
+}
diff --git a/third_party/go.tools/go/types/lookup.go b/third_party/go.tools/go/types/lookup.go
new file mode 100644
index 0000000..3caca55
--- /dev/null
+++ b/third_party/go.tools/go/types/lookup.go
@@ -0,0 +1,341 @@
+// Copyright 2013 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.
+
+// This file implements various field and method lookup functions.
+
+package types
+
+// LookupFieldOrMethod looks up a field or method with given package and name
+// in T and returns the corresponding *Var or *Func, an index sequence, and a
+// bool indicating if there were any pointer indirections on the path to the
+// field or method. If addressable is set, T is the type of an addressable
+// variable (only matters for method lookups).
+//
+// The last index entry is the field or method index in the (possibly embedded)
+// type where the entry was found, either:
+//
+//	1) the list of declared methods of a named type; or
+//	2) the list of all methods (method set) of an interface type; or
+//	3) the list of fields of a struct type.
+//
+// The earlier index entries are the indices of the anonymous struct fields
+// traversed to get to the found entry, starting at depth 0.
+//
+// If no entry is found, a nil object is returned. In this case, the returned
+// index and indirect values have the following meaning:
+//
+//	- If index != nil, the index sequence points to an ambiguous entry
+//	(the same name appeared more than once at the same embedding level).
+//
+//	- If indirect is set, a method with a pointer receiver type was found
+//      but there was no pointer on the path from the actual receiver type to
+//	the method's formal receiver base type, nor was the receiver addressable.
+//
+func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+	// Methods cannot be associated to a named pointer type
+	// (spec: "The type denoted by T is called the receiver base type;
+	// it must not be a pointer or interface type and it must be declared
+	// in the same package as the method.").
+	// Thus, if we have a named pointer type, proceed with the underlying
+	// pointer type but discard the result if it is a method since we would
+	// not have found it for T (see also issue 8590).
+	if t, _ := T.(*Named); t != nil {
+		if p, _ := t.underlying.(*Pointer); p != nil {
+			obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name)
+			if _, ok := obj.(*Func); ok {
+				return nil, nil, false
+			}
+			return
+		}
+	}
+
+	return lookupFieldOrMethod(T, addressable, pkg, name)
+}
+
+// TODO(gri) The named type consolidation and seen maps below must be
+//           indexed by unique keys for a given type. Verify that named
+//           types always have only one representation (even when imported
+//           indirectly via different packages.)
+
+func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+	// WARNING: The code in this function is extremely subtle - do not modify casually!
+	//          This function and NewMethodSet should be kept in sync.
+
+	if name == "_" {
+		return // blank fields/methods are never found
+	}
+
+	typ, isPtr := deref(T)
+	named, _ := typ.(*Named)
+
+	// *typ where typ is an interface has no methods.
+	if isPtr {
+		utyp := typ
+		if named != nil {
+			utyp = named.underlying
+		}
+		if _, ok := utyp.(*Interface); ok {
+			return
+		}
+	}
+
+	// Start with typ as single entry at shallowest depth.
+	// If typ is not a named type, insert a nil type instead.
+	current := []embeddedType{{named, nil, isPtr, false}}
+
+	// named types that we have seen already, allocated lazily
+	var seen map[*Named]bool
+
+	// search current depth
+	for len(current) > 0 {
+		var next []embeddedType // embedded types found at current depth
+
+		// look for (pkg, name) in all types at current depth
+		for _, e := range current {
+			// The very first time only, e.typ may be nil.
+			// In this case, we don't have a named type and
+			// we simply continue with the underlying type.
+			if e.typ != nil {
+				if seen[e.typ] {
+					// We have seen this type before, at a more shallow depth
+					// (note that multiples of this type at the current depth
+					// were consolidated before). The type at that depth shadows
+					// this same type at the current depth, so we can ignore
+					// this one.
+					continue
+				}
+				if seen == nil {
+					seen = make(map[*Named]bool)
+				}
+				seen[e.typ] = true
+
+				// look for a matching attached method
+				if i, m := lookupMethod(e.typ.methods, pkg, name); m != nil {
+					// potential match
+					assert(m.typ != nil)
+					index = concat(e.index, i)
+					if obj != nil || e.multiples {
+						return nil, index, false // collision
+					}
+					obj = m
+					indirect = e.indirect
+					continue // we can't have a matching field or interface method
+				}
+
+				// continue with underlying type
+				typ = e.typ.underlying
+			}
+
+			switch t := typ.(type) {
+			case *Struct:
+				// look for a matching field and collect embedded types
+				for i, f := range t.fields {
+					if f.sameId(pkg, name) {
+						assert(f.typ != nil)
+						index = concat(e.index, i)
+						if obj != nil || e.multiples {
+							return nil, index, false // collision
+						}
+						obj = f
+						indirect = e.indirect
+						continue // we can't have a matching interface method
+					}
+					// Collect embedded struct fields for searching the next
+					// lower depth, but only if we have not seen a match yet
+					// (if we have a match it is either the desired field or
+					// we have a name collision on the same depth; in either
+					// case we don't need to look further).
+					// Embedded fields are always of the form T or *T where
+					// T is a named type. If e.typ appeared multiple times at
+					// this depth, f.typ appears multiple times at the next
+					// depth.
+					if obj == nil && f.anonymous {
+						// Ignore embedded basic types - only user-defined
+						// named types can have methods or struct fields.
+						typ, isPtr := deref(f.typ)
+						if t, _ := typ.(*Named); t != nil {
+							next = append(next, embeddedType{t, concat(e.index, i), e.indirect || isPtr, e.multiples})
+						}
+					}
+				}
+
+			case *Interface:
+				// look for a matching method
+				// TODO(gri) t.allMethods is sorted - use binary search
+				if i, m := lookupMethod(t.allMethods, pkg, name); m != nil {
+					assert(m.typ != nil)
+					index = concat(e.index, i)
+					if obj != nil || e.multiples {
+						return nil, index, false // collision
+					}
+					obj = m
+					indirect = e.indirect
+				}
+			}
+		}
+
+		if obj != nil {
+			// found a potential match
+			// spec: "A method call x.m() is valid if the method set of (the type of) x
+			//        contains m and the argument list can be assigned to the parameter
+			//        list of m. If x is addressable and &x's method set contains m, x.m()
+			//        is shorthand for (&x).m()".
+			if f, _ := obj.(*Func); f != nil && ptrRecv(f) && !indirect && !addressable {
+				return nil, nil, true // pointer/addressable receiver required
+			}
+			return
+		}
+
+		current = consolidateMultiples(next)
+	}
+
+	return nil, nil, false // not found
+}
+
+// embeddedType represents an embedded named type
+type embeddedType struct {
+	typ       *Named // nil means use the outer typ variable instead
+	index     []int  // embedded field indices, starting with index at depth 0
+	indirect  bool   // if set, there was a pointer indirection on the path to this field
+	multiples bool   // if set, typ appears multiple times at this depth
+}
+
+// consolidateMultiples collects multiple list entries with the same type
+// into a single entry marked as containing multiples. The result is the
+// consolidated list.
+func consolidateMultiples(list []embeddedType) []embeddedType {
+	if len(list) <= 1 {
+		return list // at most one entry - nothing to do
+	}
+
+	n := 0                       // number of entries w/ unique type
+	prev := make(map[*Named]int) // index at which type was previously seen
+	for _, e := range list {
+		if i, found := prev[e.typ]; found {
+			list[i].multiples = true
+			// ignore this entry
+		} else {
+			prev[e.typ] = n
+			list[n] = e
+			n++
+		}
+	}
+	return list[:n]
+}
+
+// MissingMethod returns (nil, false) if V implements T, otherwise it
+// returns a missing method required by T and whether it is missing or
+// just has the wrong type.
+//
+// For non-interface types V, or if static is set, V implements T if all
+// methods of T are present in V. Otherwise (V is an interface and static
+// is not set), MissingMethod only checks that methods of T which are also
+// present in V have matching types (e.g., for a type assertion x.(T) where
+// x is of interface type V).
+//
+func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool) {
+	// fast path for common case
+	if T.Empty() {
+		return
+	}
+
+	// TODO(gri) Consider using method sets here. Might be more efficient.
+
+	if ityp, _ := V.Underlying().(*Interface); ityp != nil {
+		// TODO(gri) allMethods is sorted - can do this more efficiently
+		for _, m := range T.allMethods {
+			_, obj := lookupMethod(ityp.allMethods, m.pkg, m.name)
+			switch {
+			case obj == nil:
+				if static {
+					return m, false
+				}
+			case !Identical(obj.Type(), m.typ):
+				return m, true
+			}
+		}
+		return
+	}
+
+	// A concrete type implements T if it implements all methods of T.
+	for _, m := range T.allMethods {
+		obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name)
+
+		f, _ := obj.(*Func)
+		if f == nil {
+			return m, false
+		}
+
+		if !Identical(f.typ, m.typ) {
+			return m, true
+		}
+	}
+
+	return
+}
+
+// assertableTo reports whether a value of type V can be asserted to have type T.
+// It returns (nil, false) as affirmative answer. Otherwise it returns a missing
+// method required by V and whether it is missing or just has the wrong type.
+func assertableTo(V *Interface, T Type) (method *Func, wrongType bool) {
+	// no static check is required if T is an interface
+	// spec: "If T is an interface type, x.(T) asserts that the
+	//        dynamic type of x implements the interface T."
+	if _, ok := T.Underlying().(*Interface); ok && !strict {
+		return
+	}
+	return MissingMethod(T, V, false)
+}
+
+// deref dereferences typ if it is a *Pointer and returns its base and true.
+// Otherwise it returns (typ, false).
+func deref(typ Type) (Type, bool) {
+	if p, _ := typ.(*Pointer); p != nil {
+		return p.base, true
+	}
+	return typ, false
+}
+
+// derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a
+// (named or unnamed) struct and returns its base. Otherwise it returns typ.
+func derefStructPtr(typ Type) Type {
+	if p, _ := typ.Underlying().(*Pointer); p != nil {
+		if _, ok := p.base.Underlying().(*Struct); ok {
+			return p.base
+		}
+	}
+	return typ
+}
+
+// concat returns the result of concatenating list and i.
+// The result does not share its underlying array with list.
+func concat(list []int, i int) []int {
+	var t []int
+	t = append(t, list...)
+	return append(t, i)
+}
+
+// fieldIndex returns the index for the field with matching package and name, or a value < 0.
+func fieldIndex(fields []*Var, pkg *Package, name string) int {
+	if name != "_" {
+		for i, f := range fields {
+			if f.sameId(pkg, name) {
+				return i
+			}
+		}
+	}
+	return -1
+}
+
+// lookupMethod returns the index of and method with matching package and name, or (-1, nil).
+func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) {
+	if name != "_" {
+		for i, m := range methods {
+			if m.sameId(pkg, name) {
+				return i, m
+			}
+		}
+	}
+	return -1, nil
+}
diff --git a/third_party/go.tools/go/types/methodset.go b/third_party/go.tools/go/types/methodset.go
new file mode 100644
index 0000000..8aff6f9
--- /dev/null
+++ b/third_party/go.tools/go/types/methodset.go
@@ -0,0 +1,271 @@
+// Copyright 2013 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.
+
+// This file implements method sets.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+	"sort"
+)
+
+// A MethodSet is an ordered set of concrete or abstract (interface) methods;
+// a method is a MethodVal selection, and they are ordered by ascending m.Obj().Id().
+// The zero value for a MethodSet is a ready-to-use empty method set.
+type MethodSet struct {
+	list []*Selection
+}
+
+func (s *MethodSet) String() string {
+	if s.Len() == 0 {
+		return "MethodSet {}"
+	}
+
+	var buf bytes.Buffer
+	fmt.Fprintln(&buf, "MethodSet {")
+	for _, f := range s.list {
+		fmt.Fprintf(&buf, "\t%s\n", f)
+	}
+	fmt.Fprintln(&buf, "}")
+	return buf.String()
+}
+
+// Len returns the number of methods in s.
+func (s *MethodSet) Len() int { return len(s.list) }
+
+// At returns the i'th method in s for 0 <= i < s.Len().
+func (s *MethodSet) At(i int) *Selection { return s.list[i] }
+
+// Lookup returns the method with matching package and name, or nil if not found.
+func (s *MethodSet) Lookup(pkg *Package, name string) *Selection {
+	if s.Len() == 0 {
+		return nil
+	}
+
+	key := Id(pkg, name)
+	i := sort.Search(len(s.list), func(i int) bool {
+		m := s.list[i]
+		return m.obj.Id() >= key
+	})
+	if i < len(s.list) {
+		m := s.list[i]
+		if m.obj.Id() == key {
+			return m
+		}
+	}
+	return nil
+}
+
+// Shared empty method set.
+var emptyMethodSet MethodSet
+
+// NewMethodSet returns the method set for the given type T.  It
+// always returns a non-nil method set, even if it is empty.
+//
+// A MethodSetCache handles repeat queries more efficiently.
+//
+func NewMethodSet(T Type) *MethodSet {
+	// WARNING: The code in this function is extremely subtle - do not modify casually!
+	//          This function and lookupFieldOrMethod should be kept in sync.
+
+	// method set up to the current depth, allocated lazily
+	var base methodSet
+
+	typ, isPtr := deref(T)
+	named, _ := typ.(*Named)
+
+	// *typ where typ is an interface has no methods.
+	if isPtr {
+		utyp := typ
+		if named != nil {
+			utyp = named.underlying
+		}
+		if _, ok := utyp.(*Interface); ok {
+			return &emptyMethodSet
+		}
+	}
+
+	// Start with typ as single entry at shallowest depth.
+	// If typ is not a named type, insert a nil type instead.
+	current := []embeddedType{{named, nil, isPtr, false}}
+
+	// named types that we have seen already, allocated lazily
+	var seen map[*Named]bool
+
+	// collect methods at current depth
+	for len(current) > 0 {
+		var next []embeddedType // embedded types found at current depth
+
+		// field and method sets at current depth, allocated lazily
+		var fset fieldSet
+		var mset methodSet
+
+		for _, e := range current {
+			// The very first time only, e.typ may be nil.
+			// In this case, we don't have a named type and
+			// we simply continue with the underlying type.
+			if e.typ != nil {
+				if seen[e.typ] {
+					// We have seen this type before, at a more shallow depth
+					// (note that multiples of this type at the current depth
+					// were consolidated before). The type at that depth shadows
+					// this same type at the current depth, so we can ignore
+					// this one.
+					continue
+				}
+				if seen == nil {
+					seen = make(map[*Named]bool)
+				}
+				seen[e.typ] = true
+
+				mset = mset.add(e.typ.methods, e.index, e.indirect, e.multiples)
+
+				// continue with underlying type
+				typ = e.typ.underlying
+			}
+
+			switch t := typ.(type) {
+			case *Struct:
+				for i, f := range t.fields {
+					fset = fset.add(f, e.multiples)
+
+					// Embedded fields are always of the form T or *T where
+					// T is a named type. If typ appeared multiple times at
+					// this depth, f.Type appears multiple times at the next
+					// depth.
+					if f.anonymous {
+						// Ignore embedded basic types - only user-defined
+						// named types can have methods or struct fields.
+						typ, isPtr := deref(f.typ)
+						if t, _ := typ.(*Named); t != nil {
+							next = append(next, embeddedType{t, concat(e.index, i), e.indirect || isPtr, e.multiples})
+						}
+					}
+				}
+
+			case *Interface:
+				mset = mset.add(t.allMethods, e.index, true, e.multiples)
+			}
+		}
+
+		// Add methods and collisions at this depth to base if no entries with matching
+		// names exist already.
+		for k, m := range mset {
+			if _, found := base[k]; !found {
+				// Fields collide with methods of the same name at this depth.
+				if _, found := fset[k]; found {
+					m = nil // collision
+				}
+				if base == nil {
+					base = make(methodSet)
+				}
+				base[k] = m
+			}
+		}
+
+		// Multiple fields with matching names collide at this depth and shadow all
+		// entries further down; add them as collisions to base if no entries with
+		// matching names exist already.
+		for k, f := range fset {
+			if f == nil {
+				if _, found := base[k]; !found {
+					if base == nil {
+						base = make(methodSet)
+					}
+					base[k] = nil // collision
+				}
+			}
+		}
+
+		current = consolidateMultiples(next)
+	}
+
+	if len(base) == 0 {
+		return &emptyMethodSet
+	}
+
+	// collect methods
+	var list []*Selection
+	for _, m := range base {
+		if m != nil {
+			m.recv = T
+			list = append(list, m)
+		}
+	}
+	sort.Sort(byUniqueName(list))
+	return &MethodSet{list}
+}
+
+// A fieldSet is a set of fields and name collisions.
+// A collision indicates that multiple fields with the
+// same unique id appeared.
+type fieldSet map[string]*Var // a nil entry indicates a name collision
+
+// Add adds field f to the field set s.
+// If multiples is set, f appears multiple times
+// and is treated as a collision.
+func (s fieldSet) add(f *Var, multiples bool) fieldSet {
+	if s == nil {
+		s = make(fieldSet)
+	}
+	key := f.Id()
+	// if f is not in the set, add it
+	if !multiples {
+		if _, found := s[key]; !found {
+			s[key] = f
+			return s
+		}
+	}
+	s[key] = nil // collision
+	return s
+}
+
+// A methodSet is a set of methods and name collisions.
+// A collision indicates that multiple methods with the
+// same unique id appeared.
+type methodSet map[string]*Selection // a nil entry indicates a name collision
+
+// Add adds all functions in list to the method set s.
+// If multiples is set, every function in list appears multiple times
+// and is treated as a collision.
+func (s methodSet) add(list []*Func, index []int, indirect bool, multiples bool) methodSet {
+	if len(list) == 0 {
+		return s
+	}
+	if s == nil {
+		s = make(methodSet)
+	}
+	for i, f := range list {
+		key := f.Id()
+		// if f is not in the set, add it
+		if !multiples {
+			// TODO(gri) A found method may not be added because it's not in the method set
+			// (!indirect && ptrRecv(f)). A 2nd method on the same level may be in the method
+			// set and may not collide with the first one, thus leading to a false positive.
+			// Is that possible? Investigate.
+			if _, found := s[key]; !found && (indirect || !ptrRecv(f)) {
+				s[key] = &Selection{MethodVal, nil, f, concat(index, i), indirect}
+				continue
+			}
+		}
+		s[key] = nil // collision
+	}
+	return s
+}
+
+// ptrRecv reports whether the receiver is of the form *T.
+// The receiver must exist.
+func ptrRecv(f *Func) bool {
+	_, isPtr := deref(f.typ.(*Signature).recv.typ)
+	return isPtr
+}
+
+// byUniqueName function lists can be sorted by their unique names.
+type byUniqueName []*Selection
+
+func (a byUniqueName) Len() int           { return len(a) }
+func (a byUniqueName) Less(i, j int) bool { return a[i].obj.Id() < a[j].obj.Id() }
+func (a byUniqueName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
diff --git a/third_party/go.tools/go/types/methodsetcache.go b/third_party/go.tools/go/types/methodsetcache.go
new file mode 100644
index 0000000..5a482e9
--- /dev/null
+++ b/third_party/go.tools/go/types/methodsetcache.go
@@ -0,0 +1,69 @@
+// Copyright 2014 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.
+
+// This file implements a cache of method sets.
+
+package types
+
+import "sync"
+
+// A MethodSetCache records the method set of each type T for which
+// MethodSet(T) is called so that repeat queries are fast.
+// The zero value is a ready-to-use cache instance.
+type MethodSetCache struct {
+	mu     sync.Mutex
+	named  map[*Named]struct{ value, pointer *MethodSet } // method sets for named N and *N
+	others map[Type]*MethodSet                            // all other types
+}
+
+// MethodSet returns the method set of type T.  It is thread-safe.
+//
+// If cache is nil, this function is equivalent to NewMethodSet(T).
+// Utility functions can thus expose an optional *MethodSetCache
+// parameter to clients that care about performance.
+//
+func (cache *MethodSetCache) MethodSet(T Type) *MethodSet {
+	if cache == nil {
+		return NewMethodSet(T)
+	}
+	cache.mu.Lock()
+	defer cache.mu.Unlock()
+
+	switch T := T.(type) {
+	case *Named:
+		return cache.lookupNamed(T).value
+
+	case *Pointer:
+		if N, ok := T.Elem().(*Named); ok {
+			return cache.lookupNamed(N).pointer
+		}
+	}
+
+	// all other types
+	// (The map uses pointer equivalence, not type identity.)
+	mset := cache.others[T]
+	if mset == nil {
+		mset = NewMethodSet(T)
+		if cache.others == nil {
+			cache.others = make(map[Type]*MethodSet)
+		}
+		cache.others[T] = mset
+	}
+	return mset
+}
+
+func (cache *MethodSetCache) lookupNamed(named *Named) struct{ value, pointer *MethodSet } {
+	if cache.named == nil {
+		cache.named = make(map[*Named]struct{ value, pointer *MethodSet })
+	}
+	// Avoid recomputing mset(*T) for each distinct Pointer
+	// instance whose underlying type is a named type.
+	msets, ok := cache.named[named]
+	if !ok {
+		msets.value = NewMethodSet(named)
+		msets.pointer = NewMethodSet(NewPointer(named))
+		cache.named[named] = msets
+	}
+	return msets
+}
diff --git a/third_party/go.tools/go/types/object.go b/third_party/go.tools/go/types/object.go
new file mode 100644
index 0000000..e153cd0
--- /dev/null
+++ b/third_party/go.tools/go/types/object.go
@@ -0,0 +1,340 @@
+// Copyright 2013 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 types
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+// TODO(gri) Document factory, accessor methods, and fields. General clean-up.
+
+// An Object describes a named language entity such as a package,
+// constant, type, variable, function (incl. methods), or label.
+// All objects implement the Object interface.
+//
+type Object interface {
+	Parent() *Scope // scope in which this object is declared
+	Pos() token.Pos // position of object identifier in declaration
+	Pkg() *Package  // nil for objects in the Universe scope and labels
+	Name() string   // package local object name
+	Type() Type     // object type
+	Exported() bool // reports whether the name starts with a capital letter
+	Id() string     // object id (see Id below)
+
+	// String returns a human-readable string of the object.
+	String() string
+
+	// order reflects a package-level object's source order: if object
+	// a is before object b in the source, then a.order() < b.order().
+	// order returns a value > 0 for package-level objects; it returns
+	// 0 for all other objects (including objects in file scopes).
+	order() uint32
+
+	// setOrder sets the order number of the object. It must be > 0.
+	setOrder(uint32)
+
+	// setParent sets the parent scope of the object.
+	setParent(*Scope)
+
+	// sameId reports whether obj.Id() and Id(pkg, name) are the same.
+	sameId(pkg *Package, name string) bool
+}
+
+// Id returns name if it is exported, otherwise it
+// returns the name qualified with the package path.
+func Id(pkg *Package, name string) string {
+	if ast.IsExported(name) {
+		return name
+	}
+	// unexported names need the package path for differentiation
+	// (if there's no package, make sure we don't start with '.'
+	// as that may change the order of methods between a setup
+	// inside a package and outside a package - which breaks some
+	// tests)
+	path := "_"
+	// TODO(gri): shouldn't !ast.IsExported(name) => pkg != nil be an precondition?
+	// if pkg == nil {
+	// 	panic("nil package in lookup of unexported name")
+	// }
+	if pkg != nil {
+		path = pkg.path
+		if path == "" {
+			path = "_"
+		}
+	}
+	return path + "." + name
+}
+
+// An object implements the common parts of an Object.
+type object struct {
+	parent *Scope
+	pos    token.Pos
+	pkg    *Package
+	name   string
+	typ    Type
+	order_ uint32
+}
+
+func (obj *object) Parent() *Scope { return obj.parent }
+func (obj *object) Pos() token.Pos { return obj.pos }
+func (obj *object) Pkg() *Package  { return obj.pkg }
+func (obj *object) Name() string   { return obj.name }
+func (obj *object) Type() Type     { return obj.typ }
+func (obj *object) Exported() bool { return ast.IsExported(obj.name) }
+func (obj *object) Id() string     { return Id(obj.pkg, obj.name) }
+func (obj *object) String() string { panic("abstract") }
+func (obj *object) order() uint32  { return obj.order_ }
+
+func (obj *object) setOrder(order uint32)   { assert(order > 0); obj.order_ = order }
+func (obj *object) setParent(parent *Scope) { obj.parent = parent }
+
+func (obj *object) sameId(pkg *Package, name string) bool {
+	// spec:
+	// "Two identifiers are different if they are spelled differently,
+	// or if they appear in different packages and are not exported.
+	// Otherwise, they are the same."
+	if name != obj.name {
+		return false
+	}
+	// obj.Name == name
+	if obj.Exported() {
+		return true
+	}
+	// not exported, so packages must be the same (pkg == nil for
+	// fields in Universe scope; this can only happen for types
+	// introduced via Eval)
+	if pkg == nil || obj.pkg == nil {
+		return pkg == obj.pkg
+	}
+	// pkg != nil && obj.pkg != nil
+	return pkg.path == obj.pkg.path
+}
+
+// A PkgName represents an imported Go package.
+type PkgName struct {
+	object
+	imported *Package
+	used     bool // set if the package was used
+}
+
+func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName {
+	return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0}, imported, false}
+}
+
+// Imported returns the package that was imported.
+// It is distinct from Pkg(), which is the package containing the import statement.
+func (obj *PkgName) Imported() *Package { return obj.imported }
+
+// A Const represents a declared constant.
+type Const struct {
+	object
+	val     exact.Value
+	visited bool // for initialization cycle detection
+}
+
+func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val exact.Value) *Const {
+	return &Const{object{nil, pos, pkg, name, typ, 0}, val, false}
+}
+
+func (obj *Const) Val() exact.Value { return obj.val }
+
+// A TypeName represents a declared type.
+type TypeName struct {
+	object
+}
+
+func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
+	return &TypeName{object{nil, pos, pkg, name, typ, 0}}
+}
+
+// A Variable represents a declared variable (including function parameters and results, and struct fields).
+type Var struct {
+	object
+	anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
+	visited   bool // for initialization cycle detection
+	isField   bool // var is struct field
+	used      bool // set if the variable was used
+}
+
+func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
+	return &Var{object: object{nil, pos, pkg, name, typ, 0}}
+}
+
+func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
+	return &Var{object: object{nil, pos, pkg, name, typ, 0}, used: true} // parameters are always 'used'
+}
+
+func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
+	return &Var{object: object{nil, pos, pkg, name, typ, 0}, anonymous: anonymous, isField: true}
+}
+
+func (obj *Var) Anonymous() bool { return obj.anonymous }
+
+func (obj *Var) IsField() bool { return obj.isField }
+
+// A Func represents a declared function, concrete method, or abstract
+// (interface) method.  Its Type() is always a *Signature.
+// An abstract method may belong to many interfaces due to embedding.
+type Func struct {
+	object
+}
+
+func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
+	// don't store a nil signature
+	var typ Type
+	if sig != nil {
+		typ = sig
+	}
+	return &Func{object{nil, pos, pkg, name, typ, 0}}
+}
+
+// FullName returns the package- or receiver-type-qualified name of
+// function or method obj.
+func (obj *Func) FullName() string {
+	var buf bytes.Buffer
+	writeFuncName(&buf, nil, obj)
+	return buf.String()
+}
+
+func (obj *Func) Scope() *Scope {
+	return obj.typ.(*Signature).scope
+}
+
+// A Label represents a declared label.
+type Label struct {
+	object
+	used bool // set if the label was used
+}
+
+func NewLabel(pos token.Pos, pkg *Package, name string) *Label {
+	return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid]}, false}
+}
+
+// A Builtin represents a built-in function.
+// Builtins don't have a valid type.
+type Builtin struct {
+	object
+	id builtinId
+}
+
+func newBuiltin(id builtinId) *Builtin {
+	return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id}
+}
+
+// Nil represents the predeclared value nil.
+type Nil struct {
+	object
+}
+
+func writeObject(buf *bytes.Buffer, this *Package, obj Object) {
+	typ := obj.Type()
+	switch obj := obj.(type) {
+	case *PkgName:
+		fmt.Fprintf(buf, "package %s", obj.Name())
+		if path := obj.imported.path; path != "" && path != obj.name {
+			fmt.Fprintf(buf, " (%q)", path)
+		}
+		return
+
+	case *Const:
+		buf.WriteString("const")
+
+	case *TypeName:
+		buf.WriteString("type")
+		typ = typ.Underlying()
+
+	case *Var:
+		if obj.isField {
+			buf.WriteString("field")
+		} else {
+			buf.WriteString("var")
+		}
+
+	case *Func:
+		buf.WriteString("func ")
+		writeFuncName(buf, this, obj)
+		if typ != nil {
+			WriteSignature(buf, this, typ.(*Signature))
+		}
+		return
+
+	case *Label:
+		buf.WriteString("label")
+		typ = nil
+
+	case *Builtin:
+		buf.WriteString("builtin")
+		typ = nil
+
+	case *Nil:
+		buf.WriteString("nil")
+		return
+
+	default:
+		panic(fmt.Sprintf("writeObject(%T)", obj))
+	}
+
+	buf.WriteByte(' ')
+
+	// For package-level objects, package-qualify the name,
+	// except for intra-package references (this != nil).
+	if pkg := obj.Pkg(); pkg != nil && this != pkg && pkg.scope.Lookup(obj.Name()) == obj {
+		buf.WriteString(pkg.path)
+		buf.WriteByte('.')
+	}
+	buf.WriteString(obj.Name())
+	if typ != nil {
+		buf.WriteByte(' ')
+		WriteType(buf, this, typ)
+	}
+}
+
+// ObjectString returns the string form of obj.
+// Object and type names are printed package-qualified
+// only if they do not belong to this package.
+//
+func ObjectString(this *Package, obj Object) string {
+	var buf bytes.Buffer
+	writeObject(&buf, this, obj)
+	return buf.String()
+}
+
+func (obj *PkgName) String() string  { return ObjectString(nil, obj) }
+func (obj *Const) String() string    { return ObjectString(nil, obj) }
+func (obj *TypeName) String() string { return ObjectString(nil, obj) }
+func (obj *Var) String() string      { return ObjectString(nil, obj) }
+func (obj *Func) String() string     { return ObjectString(nil, obj) }
+func (obj *Label) String() string    { return ObjectString(nil, obj) }
+func (obj *Builtin) String() string  { return ObjectString(nil, obj) }
+func (obj *Nil) String() string      { return ObjectString(nil, obj) }
+
+func writeFuncName(buf *bytes.Buffer, this *Package, f *Func) {
+	if f.typ != nil {
+		sig := f.typ.(*Signature)
+		if recv := sig.Recv(); recv != nil {
+			buf.WriteByte('(')
+			if _, ok := recv.Type().(*Interface); ok {
+				// gcimporter creates abstract methods of
+				// named interfaces using the interface type
+				// (not the named type) as the receiver.
+				// Don't print it in full.
+				buf.WriteString("interface")
+			} else {
+				WriteType(buf, this, recv.Type())
+			}
+			buf.WriteByte(')')
+			buf.WriteByte('.')
+		} else if f.pkg != nil && f.pkg != this {
+			buf.WriteString(f.pkg.path)
+			buf.WriteByte('.')
+		}
+	}
+	buf.WriteString(f.name)
+}
diff --git a/third_party/go.tools/go/types/objset.go b/third_party/go.tools/go/types/objset.go
new file mode 100644
index 0000000..55eb74a
--- /dev/null
+++ b/third_party/go.tools/go/types/objset.go
@@ -0,0 +1,31 @@
+// Copyright 2013 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.
+
+// This file implements objsets.
+//
+// An objset is similar to a Scope but objset elements
+// are identified by their unique id, instead of their
+// object name.
+
+package types
+
+// An objset is a set of objects identified by their unique id.
+// The zero value for objset is a ready-to-use empty objset.
+type objset map[string]Object // initialized lazily
+
+// insert attempts to insert an object obj into objset s.
+// If s already contains an alternative object alt with
+// the same name, insert leaves s unchanged and returns alt.
+// Otherwise it inserts obj and returns nil.
+func (s *objset) insert(obj Object) Object {
+	id := obj.Id()
+	if alt := (*s)[id]; alt != nil {
+		return alt
+	}
+	if *s == nil {
+		*s = make(map[string]Object)
+	}
+	(*s)[id] = obj
+	return nil
+}
diff --git a/third_party/go.tools/go/types/operand.go b/third_party/go.tools/go/types/operand.go
new file mode 100644
index 0000000..44a2d1d
--- /dev/null
+++ b/third_party/go.tools/go/types/operand.go
@@ -0,0 +1,287 @@
+// 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.
+
+// This file defines operands and associated operations.
+
+package types
+
+import (
+	"bytes"
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+// An operandMode specifies the (addressing) mode of an operand.
+type operandMode byte
+
+const (
+	invalid  operandMode = iota // operand is invalid
+	novalue                     // operand represents no value (result of a function call w/o result)
+	builtin                     // operand is a built-in function
+	typexpr                     // operand is a type
+	constant                    // operand is a constant; the operand's typ is a Basic type
+	variable                    // operand is an addressable variable
+	mapindex                    // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment)
+	value                       // operand is a computed value
+	commaok                     // like value, but operand may be used in a comma,ok expression
+)
+
+var operandModeString = [...]string{
+	invalid:  "invalid operand",
+	novalue:  "no value",
+	builtin:  "built-in",
+	typexpr:  "type",
+	constant: "constant",
+	variable: "variable",
+	mapindex: "map index expression",
+	value:    "value",
+	commaok:  "comma, ok expression",
+}
+
+// An operand represents an intermediate value during type checking.
+// Operands have an (addressing) mode, the expression evaluating to
+// the operand, the operand's type, a value for constants, and an id
+// for built-in functions.
+// The zero value of operand is a ready to use invalid operand.
+//
+type operand struct {
+	mode operandMode
+	expr ast.Expr
+	typ  Type
+	val  exact.Value
+	id   builtinId
+}
+
+// pos returns the position of the expression corresponding to x.
+// If x is invalid the position is token.NoPos.
+//
+func (x *operand) pos() token.Pos {
+	// x.expr may not be set if x is invalid
+	if x.expr == nil {
+		return token.NoPos
+	}
+	return x.expr.Pos()
+}
+
+// Operand string formats
+// (not all "untyped" cases can appear due to the type system,
+// but they fall out naturally here)
+//
+// mode       format
+//
+// invalid    <expr> (               <mode>                    )
+// novalue    <expr> (               <mode>                    )
+// builtin    <expr> (               <mode>                    )
+// typexpr    <expr> (               <mode>                    )
+//
+// constant   <expr> (<untyped kind> <mode>                    )
+// constant   <expr> (               <mode>       of type <typ>)
+// constant   <expr> (<untyped kind> <mode> <val>              )
+// constant   <expr> (               <mode> <val> of type <typ>)
+//
+// variable   <expr> (<untyped kind> <mode>                    )
+// variable   <expr> (               <mode>       of type <typ>)
+//
+// mapindex   <expr> (<untyped kind> <mode>                    )
+// mapindex   <expr> (               <mode>       of type <typ>)
+//
+// value      <expr> (<untyped kind> <mode>                    )
+// value      <expr> (               <mode>       of type <typ>)
+//
+// commaok    <expr> (<untyped kind> <mode>                    )
+// commaok    <expr> (               <mode>       of type <typ>)
+//
+func operandString(this *Package, x *operand) string {
+	var buf bytes.Buffer
+
+	var expr string
+	if x.expr != nil {
+		expr = ExprString(x.expr)
+	} else {
+		switch x.mode {
+		case builtin:
+			expr = predeclaredFuncs[x.id].name
+		case typexpr:
+			expr = TypeString(this, x.typ)
+		case constant:
+			expr = x.val.String()
+		}
+	}
+
+	// <expr> (
+	if expr != "" {
+		buf.WriteString(expr)
+		buf.WriteString(" (")
+	}
+
+	// <untyped kind>
+	hasType := false
+	switch x.mode {
+	case invalid, novalue, builtin, typexpr:
+		// no type
+	default:
+		// has type
+		if isUntyped(x.typ) {
+			buf.WriteString(x.typ.(*Basic).name)
+			buf.WriteByte(' ')
+			break
+		}
+		hasType = true
+	}
+
+	// <mode>
+	buf.WriteString(operandModeString[x.mode])
+
+	// <val>
+	if x.mode == constant {
+		if s := x.val.String(); s != expr {
+			buf.WriteByte(' ')
+			buf.WriteString(s)
+		}
+	}
+
+	// <typ>
+	if hasType {
+		if x.typ != Typ[Invalid] {
+			buf.WriteString(" of type ")
+			WriteType(&buf, this, x.typ)
+		} else {
+			buf.WriteString(" with invalid type")
+		}
+	}
+
+	// )
+	if expr != "" {
+		buf.WriteByte(')')
+	}
+
+	return buf.String()
+}
+
+func (x *operand) String() string {
+	return operandString(nil, x)
+}
+
+// setConst sets x to the untyped constant for literal lit.
+func (x *operand) setConst(tok token.Token, lit string) {
+	val := exact.MakeFromLiteral(lit, tok)
+	if val == nil {
+		// TODO(gri) Should we make it an unknown constant instead?
+		x.mode = invalid
+		return
+	}
+
+	var kind BasicKind
+	switch tok {
+	case token.INT:
+		kind = UntypedInt
+	case token.FLOAT:
+		kind = UntypedFloat
+	case token.IMAG:
+		kind = UntypedComplex
+	case token.CHAR:
+		kind = UntypedRune
+	case token.STRING:
+		kind = UntypedString
+	}
+
+	x.mode = constant
+	x.typ = Typ[kind]
+	x.val = val
+}
+
+// isNil reports whether x is the nil value.
+func (x *operand) isNil() bool {
+	return x.mode == value && x.typ == Typ[UntypedNil]
+}
+
+// TODO(gri) The functions operand.assignableTo, checker.convertUntyped,
+//           checker.representable, and checker.assignment are
+//           overlapping in functionality. Need to simplify and clean up.
+
+// assignableTo reports whether x is assignable to a variable of type T.
+func (x *operand) assignableTo(conf *Config, T Type) bool {
+	if x.mode == invalid || T == Typ[Invalid] {
+		return true // avoid spurious errors
+	}
+
+	V := x.typ
+
+	// x's type is identical to T
+	if Identical(V, T) {
+		return true
+	}
+
+	Vu := V.Underlying()
+	Tu := T.Underlying()
+
+	// T is an interface type and x implements T
+	// (Do this check first as it might succeed early.)
+	if Ti, ok := Tu.(*Interface); ok {
+		if Implements(x.typ, Ti) {
+			return true
+		}
+	}
+
+	// x's type V and T have identical underlying types
+	// and at least one of V or T is not a named type
+	if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) {
+		return true
+	}
+
+	// x is a bidirectional channel value, T is a channel
+	// type, x's type V and T have identical element types,
+	// and at least one of V or T is not a named type
+	if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
+		if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
+			return !isNamed(V) || !isNamed(T)
+		}
+	}
+
+	// x is the predeclared identifier nil and T is a pointer,
+	// function, slice, map, channel, or interface type
+	if x.isNil() {
+		switch t := Tu.(type) {
+		case *Basic:
+			if t.kind == UnsafePointer {
+				return true
+			}
+		case *Pointer, *Signature, *Slice, *Map, *Chan, *Interface:
+			return true
+		}
+		return false
+	}
+
+	// x is an untyped constant representable by a value of type T
+	// TODO(gri) This is borrowing from checker.convertUntyped and
+	//           checker.representable. Need to clean up.
+	if isUntyped(Vu) {
+		switch t := Tu.(type) {
+		case *Basic:
+			if x.mode == constant {
+				return representableConst(x.val, conf, t.kind, nil)
+			}
+			// The result of a comparison is an untyped boolean,
+			// but may not be a constant.
+			if Vb, _ := Vu.(*Basic); Vb != nil {
+				return Vb.kind == UntypedBool && isBoolean(Tu)
+			}
+		case *Interface:
+			return x.isNil() || t.Empty()
+		case *Pointer, *Signature, *Slice, *Map, *Chan:
+			return x.isNil()
+		}
+	}
+
+	return false
+}
+
+// isInteger reports whether x is a (typed or untyped) integer value.
+func (x *operand) isInteger() bool {
+	return x.mode == invalid ||
+		isInteger(x.typ) ||
+		x.mode == constant && representableConst(x.val, nil, UntypedInt, nil) // no *Config required for UntypedInt
+}
diff --git a/third_party/go.tools/go/types/ordering.go b/third_party/go.tools/go/types/ordering.go
new file mode 100644
index 0000000..6bb98f2
--- /dev/null
+++ b/third_party/go.tools/go/types/ordering.go
@@ -0,0 +1,127 @@
+// Copyright 2014 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.
+
+// This file implements resolveOrder.
+
+package types
+
+import (
+	"go/ast"
+	"sort"
+)
+
+// resolveOrder computes the order in which package-level objects
+// must be type-checked.
+//
+// Interface types appear first in the list, sorted topologically
+// by dependencies on embedded interfaces that are also declared
+// in this package, followed by all other objects sorted in source
+// order.
+//
+// TODO(gri) Consider sorting all types by dependencies here, and
+// in the process check _and_ report type cycles. This may simplify
+// the full type-checking phase.
+//
+func (check *Checker) resolveOrder() []Object {
+	var ifaces, others []Object
+
+	// collect interface types with their dependencies, and all other objects
+	for obj := range check.objMap {
+		if ityp := check.interfaceFor(obj); ityp != nil {
+			ifaces = append(ifaces, obj)
+			// determine dependencies on embedded interfaces
+			for _, f := range ityp.Methods.List {
+				if len(f.Names) == 0 {
+					// Embedded interface: The type must be a (possibly
+					// qualified) identifier denoting another interface.
+					// Imported interfaces are already fully resolved,
+					// so we can ignore qualified identifiers.
+					if ident, _ := f.Type.(*ast.Ident); ident != nil {
+						embedded := check.pkg.scope.Lookup(ident.Name)
+						if check.interfaceFor(embedded) != nil {
+							check.objMap[obj].addDep(embedded)
+						}
+					}
+				}
+			}
+		} else {
+			others = append(others, obj)
+		}
+	}
+
+	// final object order
+	var order []Object
+
+	// sort interface types topologically by dependencies,
+	// and in source order if there are no dependencies
+	sort.Sort(inSourceOrder(ifaces))
+	if debug {
+		for _, obj := range ifaces {
+			assert(check.objMap[obj].mark == 0)
+		}
+	}
+	for _, obj := range ifaces {
+		check.appendInPostOrder(&order, obj)
+	}
+
+	// sort everything else in source order
+	sort.Sort(inSourceOrder(others))
+
+	return append(order, others...)
+}
+
+// interfaceFor returns the AST interface denoted by obj, or nil.
+func (check *Checker) interfaceFor(obj Object) *ast.InterfaceType {
+	tname, _ := obj.(*TypeName)
+	if tname == nil {
+		return nil // not a type
+	}
+	d := check.objMap[obj]
+	if d == nil {
+		check.dump("%s: %s should have been declared", obj.Pos(), obj.Name())
+		unreachable()
+	}
+	if d.typ == nil {
+		return nil // invalid AST - ignore (will be handled later)
+	}
+	ityp, _ := d.typ.(*ast.InterfaceType)
+	return ityp
+}
+
+func (check *Checker) appendInPostOrder(order *[]Object, obj Object) {
+	d := check.objMap[obj]
+	if d.mark != 0 {
+		// We've already seen this object; either because it's
+		// already added to order, or because we have a cycle.
+		// In both cases we stop. Cycle errors are reported
+		// when type-checking types.
+		return
+	}
+	d.mark = 1
+
+	for _, obj := range orderedSetObjects(d.deps) {
+		check.appendInPostOrder(order, obj)
+	}
+
+	*order = append(*order, obj)
+}
+
+func orderedSetObjects(set map[Object]bool) []Object {
+	list := make([]Object, len(set))
+	i := 0
+	for obj := range set {
+		// we don't care about the map element value
+		list[i] = obj
+		i++
+	}
+	sort.Sort(inSourceOrder(list))
+	return list
+}
+
+// inSourceOrder implements the sort.Sort interface.
+type inSourceOrder []Object
+
+func (a inSourceOrder) Len() int           { return len(a) }
+func (a inSourceOrder) Less(i, j int) bool { return a[i].order() < a[j].order() }
+func (a inSourceOrder) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
diff --git a/third_party/go.tools/go/types/package.go b/third_party/go.tools/go/types/package.go
new file mode 100644
index 0000000..366ca39
--- /dev/null
+++ b/third_party/go.tools/go/types/package.go
@@ -0,0 +1,58 @@
+// Copyright 2013 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 types
+
+import "fmt"
+
+// A Package describes a Go package.
+type Package struct {
+	path     string
+	name     string
+	scope    *Scope
+	complete bool
+	imports  []*Package
+	fake     bool // scope lookup errors are silently dropped if package is fake (internal use only)
+}
+
+// NewPackage returns a new Package for the given package path and name;
+// the name must not be the blank identifier.
+// The package is not complete and contains no explicit imports.
+func NewPackage(path, name string) *Package {
+	if name == "_" {
+		panic("invalid package name _")
+	}
+	scope := NewScope(Universe, fmt.Sprintf("package %q", path))
+	return &Package{path: path, name: name, scope: scope}
+}
+
+// Path returns the package path.
+func (pkg *Package) Path() string { return pkg.path }
+
+// Name returns the package name.
+func (pkg *Package) Name() string { return pkg.name }
+
+// Scope returns the (complete or incomplete) package scope
+// holding the objects declared at package level (TypeNames,
+// Consts, Vars, and Funcs).
+func (pkg *Package) Scope() *Scope { return pkg.scope }
+
+// A package is complete if its scope contains (at least) all
+// exported objects; otherwise it is incomplete.
+func (pkg *Package) Complete() bool { return pkg.complete }
+
+// MarkComplete marks a package as complete.
+func (pkg *Package) MarkComplete() { pkg.complete = true }
+
+// Imports returns the list of packages explicitly imported by
+// pkg; the list is in source order. Package unsafe is excluded.
+func (pkg *Package) Imports() []*Package { return pkg.imports }
+
+// SetImports sets the list of explicitly imported packages to list.
+// It is the caller's responsibility to make sure list elements are unique.
+func (pkg *Package) SetImports(list []*Package) { pkg.imports = list }
+
+func (pkg *Package) String() string {
+	return fmt.Sprintf("package %s (%q)", pkg.name, pkg.path)
+}
diff --git a/third_party/go.tools/go/types/predicates.go b/third_party/go.tools/go/types/predicates.go
new file mode 100644
index 0000000..2e36a72
--- /dev/null
+++ b/third_party/go.tools/go/types/predicates.go
@@ -0,0 +1,308 @@
+// 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.
+
+// This file implements commonly used type predicates.
+
+package types
+
+import "sort"
+
+func isNamed(typ Type) bool {
+	if _, ok := typ.(*Basic); ok {
+		return ok
+	}
+	_, ok := typ.(*Named)
+	return ok
+}
+
+func isBoolean(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsBoolean != 0
+}
+
+func isInteger(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsInteger != 0
+}
+
+func isUnsigned(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsUnsigned != 0
+}
+
+func isFloat(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsFloat != 0
+}
+
+func isComplex(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsComplex != 0
+}
+
+func isNumeric(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsNumeric != 0
+}
+
+func isString(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsString != 0
+}
+
+func isTyped(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return !ok || t.info&IsUntyped == 0
+}
+
+func isUntyped(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsUntyped != 0
+}
+
+func isOrdered(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsOrdered != 0
+}
+
+func isConstType(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsConstType != 0
+}
+
+func isInterface(typ Type) bool {
+	_, ok := typ.Underlying().(*Interface)
+	return ok
+}
+
+// Comparable reports whether values of type T are comparable.
+func Comparable(T Type) bool {
+	switch t := T.Underlying().(type) {
+	case *Basic:
+		// assume invalid types to be comparable
+		// to avoid follow-up errors
+		return t.kind != UntypedNil
+	case *Pointer, *Interface, *Chan:
+		return true
+	case *Struct:
+		for _, f := range t.fields {
+			if !Comparable(f.typ) {
+				return false
+			}
+		}
+		return true
+	case *Array:
+		return Comparable(t.elem)
+	}
+	return false
+}
+
+// hasNil reports whether a type includes the nil value.
+func hasNil(typ Type) bool {
+	switch t := typ.Underlying().(type) {
+	case *Basic:
+		return t.kind == UnsafePointer
+	case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
+		return true
+	}
+	return false
+}
+
+// Identical reports whether x and y are identical.
+func Identical(x, y Type) bool {
+	return identical(x, y, nil)
+}
+
+// An ifacePair is a node in a stack of interface type pairs compared for identity.
+type ifacePair struct {
+	x, y *Interface
+	prev *ifacePair
+}
+
+func (p *ifacePair) identical(q *ifacePair) bool {
+	return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
+}
+
+func identical(x, y Type, p *ifacePair) bool {
+	if x == y {
+		return true
+	}
+
+	switch x := x.(type) {
+	case *Basic:
+		// Basic types are singletons except for the rune and byte
+		// aliases, thus we cannot solely rely on the x == y check
+		// above.
+		if y, ok := y.(*Basic); ok {
+			return x.kind == y.kind
+		}
+
+	case *Array:
+		// Two array types are identical if they have identical element types
+		// and the same array length.
+		if y, ok := y.(*Array); ok {
+			return x.len == y.len && identical(x.elem, y.elem, p)
+		}
+
+	case *Slice:
+		// Two slice types are identical if they have identical element types.
+		if y, ok := y.(*Slice); ok {
+			return identical(x.elem, y.elem, p)
+		}
+
+	case *Struct:
+		// Two struct types are identical if they have the same sequence of fields,
+		// and if corresponding fields have the same names, and identical types,
+		// and identical tags. Two anonymous fields are considered to have the same
+		// name. Lower-case field names from different packages are always different.
+		if y, ok := y.(*Struct); ok {
+			if x.NumFields() == y.NumFields() {
+				for i, f := range x.fields {
+					g := y.fields[i]
+					if f.anonymous != g.anonymous ||
+						x.Tag(i) != y.Tag(i) ||
+						!f.sameId(g.pkg, g.name) ||
+						!identical(f.typ, g.typ, p) {
+						return false
+					}
+				}
+				return true
+			}
+		}
+
+	case *Pointer:
+		// Two pointer types are identical if they have identical base types.
+		if y, ok := y.(*Pointer); ok {
+			return identical(x.base, y.base, p)
+		}
+
+	case *Tuple:
+		// Two tuples types are identical if they have the same number of elements
+		// and corresponding elements have identical types.
+		if y, ok := y.(*Tuple); ok {
+			if x.Len() == y.Len() {
+				if x != nil {
+					for i, v := range x.vars {
+						w := y.vars[i]
+						if !identical(v.typ, w.typ, p) {
+							return false
+						}
+					}
+				}
+				return true
+			}
+		}
+
+	case *Signature:
+		// Two function types are identical if they have the same number of parameters
+		// and result values, corresponding parameter and result types are identical,
+		// and either both functions are variadic or neither is. Parameter and result
+		// names are not required to match.
+		if y, ok := y.(*Signature); ok {
+			return x.variadic == y.variadic &&
+				identical(x.params, y.params, p) &&
+				identical(x.results, y.results, p)
+		}
+
+	case *Interface:
+		// Two interface types are identical if they have the same set of methods with
+		// the same names and identical function types. Lower-case method names from
+		// different packages are always different. The order of the methods is irrelevant.
+		if y, ok := y.(*Interface); ok {
+			a := x.allMethods
+			b := y.allMethods
+			if len(a) == len(b) {
+				// Interface types are the only types where cycles can occur
+				// that are not "terminated" via named types; and such cycles
+				// can only be created via method parameter types that are
+				// anonymous interfaces (directly or indirectly) embedding
+				// the current interface. Example:
+				//
+				//    type T interface {
+				//        m() interface{T}
+				//    }
+				//
+				// If two such (differently named) interfaces are compared,
+				// endless recursion occurs if the cycle is not detected.
+				//
+				// If x and y were compared before, they must be equal
+				// (if they were not, the recursion would have stopped);
+				// search the ifacePair stack for the same pair.
+				//
+				// This is a quadratic algorithm, but in practice these stacks
+				// are extremely short (bounded by the nesting depth of interface
+				// type declarations that recur via parameter types, an extremely
+				// rare occurrence). An alternative implementation might use a
+				// "visited" map, but that is probably less efficient overall.
+				q := &ifacePair{x, y, p}
+				for p != nil {
+					if p.identical(q) {
+						return true // same pair was compared before
+					}
+					p = p.prev
+				}
+				if debug {
+					assert(sort.IsSorted(byUniqueMethodName(a)))
+					assert(sort.IsSorted(byUniqueMethodName(b)))
+				}
+				for i, f := range a {
+					g := b[i]
+					if f.Id() != g.Id() || !identical(f.typ, g.typ, q) {
+						return false
+					}
+				}
+				return true
+			}
+		}
+
+	case *Map:
+		// Two map types are identical if they have identical key and value types.
+		if y, ok := y.(*Map); ok {
+			return identical(x.key, y.key, p) && identical(x.elem, y.elem, p)
+		}
+
+	case *Chan:
+		// Two channel types are identical if they have identical value types
+		// and the same direction.
+		if y, ok := y.(*Chan); ok {
+			return x.dir == y.dir && identical(x.elem, y.elem, p)
+		}
+
+	case *Named:
+		// Two named types are identical if their type names originate
+		// in the same type declaration.
+		if y, ok := y.(*Named); ok {
+			return x.obj == y.obj
+		}
+
+	default:
+		unreachable()
+	}
+
+	return false
+}
+
+// defaultType returns the default "typed" type for an "untyped" type;
+// it returns the incoming type for all other types. The default type
+// for untyped nil is untyped nil.
+//
+func defaultType(typ Type) Type {
+	if t, ok := typ.(*Basic); ok {
+		switch t.kind {
+		case UntypedBool:
+			return Typ[Bool]
+		case UntypedInt:
+			return Typ[Int]
+		case UntypedRune:
+			return UniverseRune // use 'rune' name
+		case UntypedFloat:
+			return Typ[Float64]
+		case UntypedComplex:
+			return Typ[Complex128]
+		case UntypedString:
+			return Typ[String]
+		}
+	}
+	return typ
+}
diff --git a/third_party/go.tools/go/types/resolver.go b/third_party/go.tools/go/types/resolver.go
new file mode 100644
index 0000000..88eef9e
--- /dev/null
+++ b/third_party/go.tools/go/types/resolver.go
@@ -0,0 +1,446 @@
+// Copyright 2013 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 types
+
+import (
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/token"
+	pathLib "path"
+	"strconv"
+	"strings"
+	"unicode"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+// A declInfo describes a package-level const, type, var, or func declaration.
+type declInfo struct {
+	file  *Scope        // scope of file containing this declaration
+	lhs   []*Var        // lhs of n:1 variable declarations, or nil
+	typ   ast.Expr      // type, or nil
+	init  ast.Expr      // init expression, or nil
+	fdecl *ast.FuncDecl // func declaration, or nil
+
+	deps map[Object]bool // type and init dependencies; lazily allocated
+	mark int             // for dependency analysis
+}
+
+// hasInitializer reports whether the declared object has an initialization
+// expression or function body.
+func (d *declInfo) hasInitializer() bool {
+	return d.init != nil || d.fdecl != nil && d.fdecl.Body != nil
+}
+
+// addDep adds obj as a dependency to d.
+func (d *declInfo) addDep(obj Object) {
+	m := d.deps
+	if m == nil {
+		m = make(map[Object]bool)
+		d.deps = m
+	}
+	m[obj] = true
+}
+
+// arityMatch checks that the lhs and rhs of a const or var decl
+// have the appropriate number of names and init exprs. For const
+// decls, init is the value spec providing the init exprs; for
+// var decls, init is nil (the init exprs are in s in this case).
+func (check *Checker) arityMatch(s, init *ast.ValueSpec) {
+	l := len(s.Names)
+	r := len(s.Values)
+	if init != nil {
+		r = len(init.Values)
+	}
+
+	switch {
+	case init == nil && r == 0:
+		// var decl w/o init expr
+		if s.Type == nil {
+			check.errorf(s.Pos(), "missing type or init expr")
+		}
+	case l < r:
+		if l < len(s.Values) {
+			// init exprs from s
+			n := s.Values[l]
+			check.errorf(n.Pos(), "extra init expr %s", n)
+			// TODO(gri) avoid declared but not used error here
+		} else {
+			// init exprs "inherited"
+			check.errorf(s.Pos(), "extra init expr at %s", init.Pos())
+			// TODO(gri) avoid declared but not used error here
+		}
+	case l > r && (init != nil || r != 1):
+		n := s.Names[r]
+		check.errorf(n.Pos(), "missing init expr for %s", n)
+	}
+}
+
+func validatedImportPath(path string) (string, error) {
+	s, err := strconv.Unquote(path)
+	if err != nil {
+		return "", err
+	}
+	if s == "" {
+		return "", fmt.Errorf("empty string")
+	}
+	const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
+	for _, r := range s {
+		if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
+			return s, fmt.Errorf("invalid character %#U", r)
+		}
+	}
+	return s, nil
+}
+
+// declarePkgObj declares obj in the package scope, records its ident -> obj mapping,
+// and updates check.objMap. The object must not be a function or method.
+func (check *Checker) declarePkgObj(ident *ast.Ident, obj Object, d *declInfo) {
+	assert(ident.Name == obj.Name())
+
+	// spec: "A package-scope or file-scope identifier with name init
+	// may only be declared to be a function with this (func()) signature."
+	if ident.Name == "init" {
+		check.errorf(ident.Pos(), "cannot declare init - must be func")
+		return
+	}
+
+	check.declare(check.pkg.scope, ident, obj)
+	check.objMap[obj] = d
+	obj.setOrder(uint32(len(check.objMap)))
+}
+
+// filename returns a filename suitable for debugging output.
+func (check *Checker) filename(fileNo int) string {
+	file := check.files[fileNo]
+	if pos := file.Pos(); pos.IsValid() {
+		return check.fset.File(pos).Name()
+	}
+	return fmt.Sprintf("file[%d]", fileNo)
+}
+
+// collectObjects collects all file and package objects and inserts them
+// into their respective scopes. It also performs imports and associates
+// methods with receiver base type names.
+func (check *Checker) collectObjects() {
+	pkg := check.pkg
+
+	importer := check.conf.Import
+	if importer == nil {
+		if DefaultImport != nil {
+			importer = DefaultImport
+		} else {
+			// Panic if we encounter an import.
+			importer = func(map[string]*Package, string) (*Package, error) {
+				panic(`no Config.Import or DefaultImport (missing import _ "llvm.org/llgo/third_party/go.tools/go/gcimporter"?)`)
+			}
+		}
+	}
+
+	// pkgImports is the set of packages already imported by any package file seen
+	// so far. Used to avoid duplicate entries in pkg.imports. Allocate and populate
+	// it (pkg.imports may not be empty if we are checking test files incrementally).
+	var pkgImports = make(map[*Package]bool)
+	for _, imp := range pkg.imports {
+		pkgImports[imp] = true
+	}
+
+	for fileNo, file := range check.files {
+		// The package identifier denotes the current package,
+		// but there is no corresponding package object.
+		check.recordDef(file.Name, nil)
+
+		fileScope := NewScope(check.pkg.scope, check.filename(fileNo))
+		check.recordScope(file, fileScope)
+
+		for _, decl := range file.Decls {
+			switch d := decl.(type) {
+			case *ast.BadDecl:
+				// ignore
+
+			case *ast.GenDecl:
+				var last *ast.ValueSpec // last ValueSpec with type or init exprs seen
+				for iota, spec := range d.Specs {
+					switch s := spec.(type) {
+					case *ast.ImportSpec:
+						// import package
+						var imp *Package
+						path, err := validatedImportPath(s.Path.Value)
+						if err != nil {
+							check.errorf(s.Path.Pos(), "invalid import path (%s)", err)
+							continue
+						}
+						if path == "C" && check.conf.FakeImportC {
+							// TODO(gri) shouldn't create a new one each time
+							imp = NewPackage("C", "C")
+							imp.fake = true
+						} else {
+							var err error
+							imp, err = importer(check.conf.Packages, path)
+							if imp == nil && err == nil {
+								err = errors.New("Config.Import returned nil but no error")
+							}
+							if err != nil {
+								check.errorf(s.Path.Pos(), "could not import %s (%s)", path, err)
+								continue
+							}
+						}
+
+						// add package to list of explicit imports
+						// (this functionality is provided as a convenience
+						// for clients; it is not needed for type-checking)
+						if !pkgImports[imp] {
+							pkgImports[imp] = true
+							if imp != Unsafe {
+								pkg.imports = append(pkg.imports, imp)
+							}
+						}
+
+						// local name overrides imported package name
+						name := imp.name
+						if s.Name != nil {
+							name = s.Name.Name
+							if name == "init" {
+								check.errorf(s.Name.Pos(), "cannot declare init - must be func")
+								continue
+							}
+						}
+
+						obj := NewPkgName(s.Pos(), pkg, name, imp)
+						if s.Name != nil {
+							// in a dot-import, the dot represents the package
+							check.recordDef(s.Name, obj)
+						} else {
+							check.recordImplicit(s, obj)
+						}
+
+						// add import to file scope
+						if name == "." {
+							// merge imported scope with file scope
+							for _, obj := range imp.scope.elems {
+								// A package scope may contain non-exported objects,
+								// do not import them!
+								if obj.Exported() {
+									// TODO(gri) When we import a package, we create
+									// a new local package object. We should do the
+									// same for each dot-imported object. That way
+									// they can have correct position information.
+									// (We must not modify their existing position
+									// information because the same package - found
+									// via Config.Packages - may be dot-imported in
+									// another package!)
+									check.declare(fileScope, nil, obj)
+									check.recordImplicit(s, obj)
+								}
+							}
+							// add position to set of dot-import positions for this file
+							// (this is only needed for "imported but not used" errors)
+							check.addUnusedDotImport(fileScope, imp, s.Pos())
+						} else {
+							// declare imported package object in file scope
+							check.declare(fileScope, nil, obj)
+						}
+
+					case *ast.ValueSpec:
+						switch d.Tok {
+						case token.CONST:
+							// determine which initialization expressions to use
+							switch {
+							case s.Type != nil || len(s.Values) > 0:
+								last = s
+							case last == nil:
+								last = new(ast.ValueSpec) // make sure last exists
+							}
+
+							// declare all constants
+							for i, name := range s.Names {
+								obj := NewConst(name.Pos(), pkg, name.Name, nil, exact.MakeInt64(int64(iota)))
+
+								var init ast.Expr
+								if i < len(last.Values) {
+									init = last.Values[i]
+								}
+
+								d := &declInfo{file: fileScope, typ: last.Type, init: init}
+								check.declarePkgObj(name, obj, d)
+							}
+
+							check.arityMatch(s, last)
+
+						case token.VAR:
+							lhs := make([]*Var, len(s.Names))
+							// If there's exactly one rhs initializer, use
+							// the same declInfo d1 for all lhs variables
+							// so that each lhs variable depends on the same
+							// rhs initializer (n:1 var declaration).
+							var d1 *declInfo
+							if len(s.Values) == 1 {
+								// The lhs elements are only set up after the for loop below,
+								// but that's ok because declareVar only collects the declInfo
+								// for a later phase.
+								d1 = &declInfo{file: fileScope, lhs: lhs, typ: s.Type, init: s.Values[0]}
+							}
+
+							// declare all variables
+							for i, name := range s.Names {
+								obj := NewVar(name.Pos(), pkg, name.Name, nil)
+								lhs[i] = obj
+
+								d := d1
+								if d == nil {
+									// individual assignments
+									var init ast.Expr
+									if i < len(s.Values) {
+										init = s.Values[i]
+									}
+									d = &declInfo{file: fileScope, typ: s.Type, init: init}
+								}
+
+								check.declarePkgObj(name, obj, d)
+							}
+
+							check.arityMatch(s, nil)
+
+						default:
+							check.invalidAST(s.Pos(), "invalid token %s", d.Tok)
+						}
+
+					case *ast.TypeSpec:
+						obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil)
+						check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, typ: s.Type})
+
+					default:
+						check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
+					}
+				}
+
+			case *ast.FuncDecl:
+				name := d.Name.Name
+				obj := NewFunc(d.Name.Pos(), pkg, name, nil)
+				if d.Recv == nil {
+					// regular function
+					if name == "init" {
+						// don't declare init functions in the package scope - they are invisible
+						obj.parent = pkg.scope
+						check.recordDef(d.Name, obj)
+						// init functions must have a body
+						if d.Body == nil {
+							check.softErrorf(obj.pos, "missing function body")
+						}
+					} else {
+						check.declare(pkg.scope, d.Name, obj)
+					}
+				} else {
+					// method
+					check.recordDef(d.Name, obj)
+					// Associate method with receiver base type name, if possible.
+					// Ignore methods that have an invalid receiver, or a blank _
+					// receiver name. They will be type-checked later, with regular
+					// functions.
+					if list := d.Recv.List; len(list) > 0 {
+						typ := list[0].Type
+						if ptr, _ := typ.(*ast.StarExpr); ptr != nil {
+							typ = ptr.X
+						}
+						if base, _ := typ.(*ast.Ident); base != nil && base.Name != "_" {
+							check.assocMethod(base.Name, obj)
+						}
+					}
+				}
+				info := &declInfo{file: fileScope, fdecl: d}
+				check.objMap[obj] = info
+				obj.setOrder(uint32(len(check.objMap)))
+
+			default:
+				check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
+			}
+		}
+	}
+
+	// verify that objects in package and file scopes have different names
+	for _, scope := range check.pkg.scope.children /* file scopes */ {
+		for _, obj := range scope.elems {
+			if alt := pkg.scope.Lookup(obj.Name()); alt != nil {
+				if pkg, ok := obj.(*PkgName); ok {
+					check.errorf(alt.Pos(), "%s already declared through import of %s", alt.Name(), pkg.Imported())
+					check.reportAltDecl(pkg)
+				} else {
+					check.errorf(alt.Pos(), "%s already declared through dot-import of %s", alt.Name(), obj.Pkg())
+					// TODO(gri) dot-imported objects don't have a position; reportAltDecl won't print anything
+					check.reportAltDecl(obj)
+				}
+			}
+		}
+	}
+}
+
+// packageObjects typechecks all package objects in objList, but not function bodies.
+func (check *Checker) packageObjects(objList []Object) {
+	// add new methods to already type-checked types (from a prior Checker.Files call)
+	for _, obj := range objList {
+		if obj, _ := obj.(*TypeName); obj != nil && obj.typ != nil {
+			check.addMethodDecls(obj)
+		}
+	}
+
+	// pre-allocate space for type declaration paths so that the underlying array is reused
+	typePath := make([]*TypeName, 0, 8)
+
+	for _, obj := range objList {
+		check.objDecl(obj, nil, typePath)
+	}
+
+	// At this point we may have a non-empty check.methods map; this means that not all
+	// entries were deleted at the end of typeDecl because the respective receiver base
+	// types were not found. In that case, an error was reported when declaring those
+	// methods. We can now safely discard this map.
+	check.methods = nil
+}
+
+// functionBodies typechecks all function bodies.
+func (check *Checker) functionBodies() {
+	for _, f := range check.funcs {
+		check.funcBody(f.decl, f.name, f.sig, f.body)
+	}
+}
+
+// unusedImports checks for unused imports.
+func (check *Checker) unusedImports() {
+	// if function bodies are not checked, packages' uses are likely missing - don't check
+	if check.conf.IgnoreFuncBodies {
+		return
+	}
+
+	// spec: "It is illegal (...) to directly import a package without referring to
+	// any of its exported identifiers. To import a package solely for its side-effects
+	// (initialization), use the blank identifier as explicit package name."
+
+	// check use of regular imported packages
+	for _, scope := range check.pkg.scope.children /* file scopes */ {
+		for _, obj := range scope.elems {
+			if obj, ok := obj.(*PkgName); ok {
+				// Unused "blank imports" are automatically ignored
+				// since _ identifiers are not entered into scopes.
+				if !obj.used {
+					path := obj.imported.path
+					base := pathLib.Base(path)
+					if obj.name == base {
+						check.softErrorf(obj.pos, "%q imported but not used", path)
+					} else {
+						check.softErrorf(obj.pos, "%q imported but not used as %s", path, obj.name)
+					}
+				}
+			}
+		}
+	}
+
+	// check use of dot-imported packages
+	for _, unusedDotImports := range check.unusedDotImports {
+		for pkg, pos := range unusedDotImports {
+			check.softErrorf(pos, "%q imported but not used", pkg.path)
+		}
+	}
+}
diff --git a/third_party/go.tools/go/types/resolver_test.go b/third_party/go.tools/go/types/resolver_test.go
new file mode 100644
index 0000000..d4f621e
--- /dev/null
+++ b/third_party/go.tools/go/types/resolver_test.go
@@ -0,0 +1,187 @@
+// 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.
+
+package types_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"sort"
+	"testing"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var sources = []string{
+	`
+	package p
+	import "fmt"
+	import "math"
+	const pi = math.Pi
+	func sin(x float64) float64 {
+		return math.Sin(x)
+	}
+	var Println = fmt.Println
+	`,
+	`
+	package p
+	import "fmt"
+	type errorStringer struct { fmt.Stringer; error }
+	func f() string {
+		_ = "foo"
+		return fmt.Sprintf("%d", g())
+	}
+	func g() (x int) { return }
+	`,
+	`
+	package p
+	import . "go/parser"
+	import "sync"
+	func h() Mode { return ImportsOnly }
+	var _, x int = 1, 2
+	func init() {}
+	type T struct{ *sync.Mutex; a, b, c int}
+	type I interface{ m() }
+	var _ = T{a: 1, b: 2, c: 3}
+	func (_ T) m() {}
+	func (T) _() {}
+	var i I
+	var _ = i.m
+	func _(s []int) { for i, x := range s { _, _ = i, x } }
+	func _(x interface{}) {
+		switch x := x.(type) {
+		case int:
+			_ = x
+		}
+		switch {} // implicit 'true' tag
+	}
+	`,
+	`
+	package p
+	type S struct{}
+	func (T) _() {}
+	func (T) _() {}
+	`,
+	`
+	package p
+	func _() {
+	L0:
+	L1:
+		goto L0
+		for {
+			goto L1
+		}
+		if true {
+			goto L2
+		}
+	L2:
+	}
+	`,
+}
+
+var pkgnames = []string{
+	"fmt",
+	"math",
+}
+
+func TestResolveIdents(t *testing.T) {
+	// parse package files
+	fset := token.NewFileSet()
+	var files []*ast.File
+	for i, src := range sources {
+		f, err := parser.ParseFile(fset, fmt.Sprintf("sources[%d]", i), src, parser.DeclarationErrors)
+		if err != nil {
+			t.Fatal(err)
+		}
+		files = append(files, f)
+	}
+
+	// resolve and type-check package AST
+	var conf Config
+	uses := make(map[*ast.Ident]Object)
+	defs := make(map[*ast.Ident]Object)
+	_, err := conf.Check("testResolveIdents", fset, files, &Info{Defs: defs, Uses: uses})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// check that all packages were imported
+	for _, name := range pkgnames {
+		if conf.Packages[name] == nil {
+			t.Errorf("package %s not imported", name)
+		}
+	}
+
+	// check that qualified identifiers are resolved
+	for _, f := range files {
+		ast.Inspect(f, func(n ast.Node) bool {
+			if s, ok := n.(*ast.SelectorExpr); ok {
+				if x, ok := s.X.(*ast.Ident); ok {
+					obj := uses[x]
+					if obj == nil {
+						t.Errorf("%s: unresolved qualified identifier %s", fset.Position(x.Pos()), x.Name)
+						return false
+					}
+					if _, ok := obj.(*PkgName); ok && uses[s.Sel] == nil {
+						t.Errorf("%s: unresolved selector %s", fset.Position(s.Sel.Pos()), s.Sel.Name)
+						return false
+					}
+					return false
+				}
+				return false
+			}
+			return true
+		})
+	}
+
+	for id, obj := range uses {
+		if obj == nil {
+			t.Errorf("%s: Uses[%s] == nil", fset.Position(id.Pos()), id.Name)
+		}
+	}
+
+	// check that each identifier in the source is found in uses or defs or both
+	var both []string
+	for _, f := range files {
+		ast.Inspect(f, func(n ast.Node) bool {
+			if x, ok := n.(*ast.Ident); ok {
+				var objects int
+				if _, found := uses[x]; found {
+					objects |= 1
+					delete(uses, x)
+				}
+				if _, found := defs[x]; found {
+					objects |= 2
+					delete(defs, x)
+				}
+				if objects == 0 {
+					t.Errorf("%s: unresolved identifier %s", fset.Position(x.Pos()), x.Name)
+				} else if objects == 3 {
+					both = append(both, x.Name)
+				}
+				return false
+			}
+			return true
+		})
+	}
+
+	// check the expected set of idents that are simultaneously uses and defs
+	sort.Strings(both)
+	if got, want := fmt.Sprint(both), "[Mutex Stringer error]"; got != want {
+		t.Errorf("simultaneous uses/defs = %s, want %s", got, want)
+	}
+
+	// any left-over identifiers didn't exist in the source
+	for x := range uses {
+		t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name)
+	}
+	for x := range defs {
+		t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name)
+	}
+
+	// TODO(gri) add tests to check ImplicitObj callbacks
+}
diff --git a/third_party/go.tools/go/types/return.go b/third_party/go.tools/go/types/return.go
new file mode 100644
index 0000000..df5a482
--- /dev/null
+++ b/third_party/go.tools/go/types/return.go
@@ -0,0 +1,185 @@
+// Copyright 2013 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.
+
+// This file implements isTerminating.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// isTerminating reports if s is a terminating statement.
+// If s is labeled, label is the label name; otherwise s
+// is "".
+func (check *Checker) isTerminating(s ast.Stmt, label string) bool {
+	switch s := s.(type) {
+	default:
+		unreachable()
+
+	case *ast.BadStmt, *ast.DeclStmt, *ast.EmptyStmt, *ast.SendStmt,
+		*ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt, *ast.DeferStmt,
+		*ast.RangeStmt:
+		// no chance
+
+	case *ast.LabeledStmt:
+		return check.isTerminating(s.Stmt, s.Label.Name)
+
+	case *ast.ExprStmt:
+		// the predeclared (possibly parenthesized) panic() function is terminating
+		if call, _ := unparen(s.X).(*ast.CallExpr); call != nil {
+			if id, _ := call.Fun.(*ast.Ident); id != nil {
+				if _, obj := check.scope.LookupParent(id.Name); obj != nil {
+					if b, _ := obj.(*Builtin); b != nil && b.id == _Panic {
+						return true
+					}
+				}
+			}
+		}
+
+	case *ast.ReturnStmt:
+		return true
+
+	case *ast.BranchStmt:
+		if s.Tok == token.GOTO || s.Tok == token.FALLTHROUGH {
+			return true
+		}
+
+	case *ast.BlockStmt:
+		return check.isTerminatingList(s.List, "")
+
+	case *ast.IfStmt:
+		if s.Else != nil &&
+			check.isTerminating(s.Body, "") &&
+			check.isTerminating(s.Else, "") {
+			return true
+		}
+
+	case *ast.SwitchStmt:
+		return check.isTerminatingSwitch(s.Body, label)
+
+	case *ast.TypeSwitchStmt:
+		return check.isTerminatingSwitch(s.Body, label)
+
+	case *ast.SelectStmt:
+		for _, s := range s.Body.List {
+			cc := s.(*ast.CommClause)
+			if !check.isTerminatingList(cc.Body, "") || hasBreakList(cc.Body, label, true) {
+				return false
+			}
+
+		}
+		return true
+
+	case *ast.ForStmt:
+		if s.Cond == nil && !hasBreak(s.Body, label, true) {
+			return true
+		}
+	}
+
+	return false
+}
+
+func (check *Checker) isTerminatingList(list []ast.Stmt, label string) bool {
+	n := len(list)
+	return n > 0 && check.isTerminating(list[n-1], label)
+}
+
+func (check *Checker) isTerminatingSwitch(body *ast.BlockStmt, label string) bool {
+	hasDefault := false
+	for _, s := range body.List {
+		cc := s.(*ast.CaseClause)
+		if cc.List == nil {
+			hasDefault = true
+		}
+		if !check.isTerminatingList(cc.Body, "") || hasBreakList(cc.Body, label, true) {
+			return false
+		}
+	}
+	return hasDefault
+}
+
+// TODO(gri) For nested breakable statements, the current implementation of hasBreak
+//	     will traverse the same subtree repeatedly, once for each label. Replace
+//           with a single-pass label/break matching phase.
+
+// hasBreak reports if s is or contains a break statement
+// referring to the label-ed statement or implicit-ly the
+// closest outer breakable statement.
+func hasBreak(s ast.Stmt, label string, implicit bool) bool {
+	switch s := s.(type) {
+	default:
+		unreachable()
+
+	case *ast.BadStmt, *ast.DeclStmt, *ast.EmptyStmt, *ast.ExprStmt,
+		*ast.SendStmt, *ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt,
+		*ast.DeferStmt, *ast.ReturnStmt:
+		// no chance
+
+	case *ast.LabeledStmt:
+		return hasBreak(s.Stmt, label, implicit)
+
+	case *ast.BranchStmt:
+		if s.Tok == token.BREAK {
+			if s.Label == nil {
+				return implicit
+			}
+			if s.Label.Name == label {
+				return true
+			}
+		}
+
+	case *ast.BlockStmt:
+		return hasBreakList(s.List, label, implicit)
+
+	case *ast.IfStmt:
+		if hasBreak(s.Body, label, implicit) ||
+			s.Else != nil && hasBreak(s.Else, label, implicit) {
+			return true
+		}
+
+	case *ast.CaseClause:
+		return hasBreakList(s.Body, label, implicit)
+
+	case *ast.SwitchStmt:
+		if label != "" && hasBreak(s.Body, label, false) {
+			return true
+		}
+
+	case *ast.TypeSwitchStmt:
+		if label != "" && hasBreak(s.Body, label, false) {
+			return true
+		}
+
+	case *ast.CommClause:
+		return hasBreakList(s.Body, label, implicit)
+
+	case *ast.SelectStmt:
+		if label != "" && hasBreak(s.Body, label, false) {
+			return true
+		}
+
+	case *ast.ForStmt:
+		if label != "" && hasBreak(s.Body, label, false) {
+			return true
+		}
+
+	case *ast.RangeStmt:
+		if label != "" && hasBreak(s.Body, label, false) {
+			return true
+		}
+	}
+
+	return false
+}
+
+func hasBreakList(list []ast.Stmt, label string, implicit bool) bool {
+	for _, s := range list {
+		if hasBreak(s, label, implicit) {
+			return true
+		}
+	}
+	return false
+}
diff --git a/third_party/go.tools/go/types/scope.go b/third_party/go.tools/go/types/scope.go
new file mode 100644
index 0000000..8ab0f64
--- /dev/null
+++ b/third_party/go.tools/go/types/scope.go
@@ -0,0 +1,145 @@
+// Copyright 2013 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.
+
+// This file implements Scopes.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"sort"
+	"strings"
+)
+
+// TODO(gri) Provide scopes with a name or other mechanism so that
+//           objects can use that information for better printing.
+
+// A Scope maintains a set of objects and links to its containing
+// (parent) and contained (children) scopes. Objects may be inserted
+// and looked up by name. The zero value for Scope is a ready-to-use
+// empty scope.
+type Scope struct {
+	parent   *Scope
+	children []*Scope
+	comment  string            // for debugging only
+	elems    map[string]Object // lazily allocated
+}
+
+// NewScope returns a new, empty scope contained in the given parent
+// scope, if any.  The comment is for debugging only.
+func NewScope(parent *Scope, comment string) *Scope {
+	s := &Scope{parent: parent, comment: comment}
+	// don't add children to Universe scope!
+	if parent != nil && parent != Universe {
+		parent.children = append(parent.children, s)
+	}
+	return s
+}
+
+// Parent returns the scope's containing (parent) scope.
+func (s *Scope) Parent() *Scope { return s.parent }
+
+// Len() returns the number of scope elements.
+func (s *Scope) Len() int { return len(s.elems) }
+
+// Names returns the scope's element names in sorted order.
+func (s *Scope) Names() []string {
+	names := make([]string, len(s.elems))
+	i := 0
+	for name := range s.elems {
+		names[i] = name
+		i++
+	}
+	sort.Strings(names)
+	return names
+}
+
+// NumChildren() returns the number of scopes nested in s.
+func (s *Scope) NumChildren() int { return len(s.children) }
+
+// Child returns the i'th child scope for 0 <= i < NumChildren().
+func (s *Scope) Child(i int) *Scope { return s.children[i] }
+
+// Lookup returns the object in scope s with the given name if such an
+// object exists; otherwise the result is nil.
+func (s *Scope) Lookup(name string) Object {
+	return s.elems[name]
+}
+
+// LookupParent follows the parent chain of scopes starting with s until
+// it finds a scope where Lookup(name) returns a non-nil object, and then
+// returns that scope and object. If no such scope exists, the result is (nil, nil).
+//
+// Note that obj.Parent() may be different from the returned scope if the
+// object was inserted into the scope and already had a parent at that
+// time (see Insert, below). This can only happen for dot-imported objects
+// whose scope is the scope of the package that exported them.
+func (s *Scope) LookupParent(name string) (*Scope, Object) {
+	for ; s != nil; s = s.parent {
+		if obj := s.elems[name]; obj != nil {
+			return s, obj
+		}
+	}
+	return nil, nil
+}
+
+// Insert attempts to insert an object obj into scope s.
+// If s already contains an alternative object alt with
+// the same name, Insert leaves s unchanged and returns alt.
+// Otherwise it inserts obj, sets the object's parent scope
+// if not already set, and returns nil.
+func (s *Scope) Insert(obj Object) Object {
+	name := obj.Name()
+	if alt := s.elems[name]; alt != nil {
+		return alt
+	}
+	if s.elems == nil {
+		s.elems = make(map[string]Object)
+	}
+	s.elems[name] = obj
+	if obj.Parent() == nil {
+		obj.setParent(s)
+	}
+	return nil
+}
+
+// WriteTo writes a string representation of the scope to w,
+// with the scope elements sorted by name.
+// The level of indentation is controlled by n >= 0, with
+// n == 0 for no indentation.
+// If recurse is set, it also writes nested (children) scopes.
+func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
+	const ind = ".  "
+	indn := strings.Repeat(ind, n)
+
+	fmt.Fprintf(w, "%s%s scope %p {", indn, s.comment, s)
+	if len(s.elems) == 0 {
+		fmt.Fprintf(w, "}\n")
+		return
+	}
+
+	fmt.Fprintln(w)
+	indn1 := indn + ind
+	for _, name := range s.Names() {
+		fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name])
+	}
+
+	if recurse {
+		for _, s := range s.children {
+			fmt.Fprintln(w)
+			s.WriteTo(w, n+1, recurse)
+		}
+	}
+
+	fmt.Fprintf(w, "%s}", indn)
+}
+
+// String returns a string representation of the scope, for debugging.
+func (s *Scope) String() string {
+	var buf bytes.Buffer
+	s.WriteTo(&buf, 0, false)
+	return buf.String()
+}
diff --git a/third_party/go.tools/go/types/selection.go b/third_party/go.tools/go/types/selection.go
new file mode 100644
index 0000000..1c70165
--- /dev/null
+++ b/third_party/go.tools/go/types/selection.go
@@ -0,0 +1,143 @@
+// Copyright 2013 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.
+
+// This file implements Selections.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// SelectionKind describes the kind of a selector expression x.f
+// (excluding qualified identifiers).
+type SelectionKind int
+
+const (
+	FieldVal   SelectionKind = iota // x.f is a struct field selector
+	MethodVal                       // x.f is a method selector
+	MethodExpr                      // x.f is a method expression
+)
+
+// A Selection describes a selector expression x.f.
+// For the declarations:
+//
+//	type T struct{ x int; E }
+//	type E struct{}
+//	func (e E) m() {}
+//	var p *T
+//
+// the following relations exist:
+//
+//	Selector    Kind          Recv    Obj    Type               Index     Indirect
+//
+//	p.x         FieldVal      T       x      int                {0}       true
+//	p.m         MethodVal     *T      m      func (e *T) m()    {1, 0}    true
+//	T.m         MethodExpr    T       m      func m(_ T)        {1, 0}    false
+//
+type Selection struct {
+	kind     SelectionKind
+	recv     Type   // type of x
+	obj      Object // object denoted by x.f
+	index    []int  // path from x to x.f
+	indirect bool   // set if there was any pointer indirection on the path
+}
+
+// Kind returns the selection kind.
+func (s *Selection) Kind() SelectionKind { return s.kind }
+
+// Recv returns the type of x in x.f.
+func (s *Selection) Recv() Type { return s.recv }
+
+// Obj returns the object denoted by x.f; a *Var for
+// a field selection, and a *Func in all other cases.
+func (s *Selection) Obj() Object { return s.obj }
+
+// Type returns the type of x.f, which may be different from the type of f.
+// See Selection for more information.
+func (s *Selection) Type() Type {
+	switch s.kind {
+	case MethodVal:
+		// The type of x.f is a method with its receiver type set
+		// to the type of x.
+		sig := *s.obj.(*Func).typ.(*Signature)
+		recv := *sig.recv
+		recv.typ = s.recv
+		sig.recv = &recv
+		return &sig
+
+	case MethodExpr:
+		// The type of x.f is a function (without receiver)
+		// and an additional first argument with the same type as x.
+		// TODO(gri) Similar code is already in call.go - factor!
+		// TODO(gri) Compute this eagerly to avoid allocations.
+		sig := *s.obj.(*Func).typ.(*Signature)
+		arg0 := *sig.recv
+		sig.recv = nil
+		arg0.typ = s.recv
+		var params []*Var
+		if sig.params != nil {
+			params = sig.params.vars
+		}
+		sig.params = NewTuple(append([]*Var{&arg0}, params...)...)
+		return &sig
+	}
+
+	// In all other cases, the type of x.f is the type of x.
+	return s.obj.Type()
+}
+
+// Index describes the path from x to f in x.f.
+// The last index entry is the field or method index of the type declaring f;
+// either:
+//
+//	1) the list of declared methods of a named type; or
+//	2) the list of methods of an interface type; or
+//	3) the list of fields of a struct type.
+//
+// The earlier index entries are the indices of the embedded fields implicitly
+// traversed to get from (the type of) x to f, starting at embedding depth 0.
+func (s *Selection) Index() []int { return s.index }
+
+// Indirect reports whether any pointer indirection was required to get from
+// x to f in x.f.
+func (s *Selection) Indirect() bool { return s.indirect }
+
+func (s *Selection) String() string { return SelectionString(nil, s) }
+
+// SelectionString returns the string form of s.
+// Type names are printed package-qualified
+// only if they do not belong to this package.
+//
+// Examples:
+//	"field (T) f int"
+//	"method (T) f(X) Y"
+//	"method expr (T) f(X) Y"
+//
+func SelectionString(this *Package, s *Selection) string {
+	var k string
+	switch s.kind {
+	case FieldVal:
+		k = "field "
+	case MethodVal:
+		k = "method "
+	case MethodExpr:
+		k = "method expr "
+	default:
+		unreachable()
+	}
+	var buf bytes.Buffer
+	buf.WriteString(k)
+	buf.WriteByte('(')
+	WriteType(&buf, this, s.Recv())
+	fmt.Fprintf(&buf, ") %s", s.obj.Name())
+	if T := s.Type(); s.kind == FieldVal {
+		buf.WriteByte(' ')
+		WriteType(&buf, this, T)
+	} else {
+		WriteSignature(&buf, this, T.(*Signature))
+	}
+	return buf.String()
+}
diff --git a/third_party/go.tools/go/types/self_test.go b/third_party/go.tools/go/types/self_test.go
new file mode 100644
index 0000000..54d7636
--- /dev/null
+++ b/third_party/go.tools/go/types/self_test.go
@@ -0,0 +1,101 @@
+// Copyright 2013 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 types_test
+
+import (
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"path/filepath"
+	"testing"
+	"time"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var benchmark = flag.Bool("b", false, "run benchmarks")
+
+func TestSelf(t *testing.T) {
+	fset := token.NewFileSet()
+	files, err := pkgFiles(fset, ".")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	_, err = Check("go/types", fset, files)
+	if err != nil {
+		// Importing go.tools/go/exact doensn't work in the
+		// build dashboard environment. Don't report an error
+		// for now so that the build remains green.
+		// TODO(gri) fix this
+		t.Log(err) // replace w/ t.Fatal eventually
+		return
+	}
+}
+
+func TestBenchmark(t *testing.T) {
+	if !*benchmark {
+		return
+	}
+
+	// We're not using testing's benchmarking mechanism directly
+	// because we want custom output.
+
+	for _, p := range []string{"types", "exact", "gcimporter"} {
+		path := filepath.Join("..", p)
+		runbench(t, path, false)
+		runbench(t, path, true)
+		fmt.Println()
+	}
+}
+
+func runbench(t *testing.T, path string, ignoreFuncBodies bool) {
+	fset := token.NewFileSet()
+	files, err := pkgFiles(fset, path)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	b := testing.Benchmark(func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			conf := Config{IgnoreFuncBodies: ignoreFuncBodies}
+			conf.Check(path, fset, files, nil)
+		}
+	})
+
+	// determine line count
+	lines := 0
+	fset.Iterate(func(f *token.File) bool {
+		lines += f.LineCount()
+		return true
+	})
+
+	d := time.Duration(b.NsPerOp())
+	fmt.Printf(
+		"%s: %s for %d lines (%d lines/s), ignoreFuncBodies = %v\n",
+		filepath.Base(path), d, lines, int64(float64(lines)/d.Seconds()), ignoreFuncBodies,
+	)
+}
+
+func pkgFiles(fset *token.FileSet, path string) ([]*ast.File, error) {
+	filenames, err := pkgFilenames(path) // from stdlib_test.go
+	if err != nil {
+		return nil, err
+	}
+
+	var files []*ast.File
+	for _, filename := range filenames {
+		file, err := parser.ParseFile(fset, filename, nil, 0)
+		if err != nil {
+			return nil, err
+		}
+		files = append(files, file)
+	}
+
+	return files, nil
+}
diff --git a/third_party/go.tools/go/types/sizes.go b/third_party/go.tools/go/types/sizes.go
new file mode 100644
index 0000000..56fb310
--- /dev/null
+++ b/third_party/go.tools/go/types/sizes.go
@@ -0,0 +1,211 @@
+// Copyright 2013 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.
+
+// This file implements Sizes.
+
+package types
+
+// Sizes defines the sizing functions for package unsafe.
+type Sizes interface {
+	// Alignof returns the alignment of a variable of type T.
+	// Alignof must implement the alignment guarantees required by the spec.
+	Alignof(T Type) int64
+
+	// Offsetsof returns the offsets of the given struct fields, in bytes.
+	// Offsetsof must implement the offset guarantees required by the spec.
+	Offsetsof(fields []*Var) []int64
+
+	// Sizeof returns the size of a variable of type T.
+	// Sizeof must implement the size guarantees required by the spec.
+	Sizeof(T Type) int64
+}
+
+// StdSizes is a convenience type for creating commonly used Sizes.
+// It makes the following simplifying assumptions:
+//
+//	- The size of explicitly sized basic types (int16, etc.) is the
+//	  specified size.
+//	- The size of strings and interfaces is 2*WordSize.
+//	- The size of slices is 3*WordSize.
+//	- The size of an array of n elements corresponds to the size of
+//	  a struct of n consecutive fields of the array's element type.
+//      - The size of a struct is the offset of the last field plus that
+//	  field's size. As with all element types, if the struct is used
+//	  in an array its size must first be aligned to a multiple of the
+//	  struct's alignment.
+//	- All other types have size WordSize.
+//	- Arrays and structs are aligned per spec definition; all other
+//	  types are naturally aligned with a maximum alignment MaxAlign.
+//
+// *StdSizes implements Sizes.
+//
+type StdSizes struct {
+	WordSize int64 // word size in bytes - must be >= 4 (32bits)
+	MaxAlign int64 // maximum alignment in bytes - must be >= 1
+}
+
+func (s *StdSizes) Alignof(T Type) int64 {
+	// For arrays and structs, alignment is defined in terms
+	// of alignment of the elements and fields, respectively.
+	switch t := T.Underlying().(type) {
+	case *Array:
+		// spec: "For a variable x of array type: unsafe.Alignof(x)
+		// is the same as unsafe.Alignof(x[0]), but at least 1."
+		return s.Alignof(t.elem)
+	case *Struct:
+		// spec: "For a variable x of struct type: unsafe.Alignof(x)
+		// is the largest of the values unsafe.Alignof(x.f) for each
+		// field f of x, but at least 1."
+		max := int64(1)
+		for _, f := range t.fields {
+			if a := s.Alignof(f.typ); a > max {
+				max = a
+			}
+		}
+		return max
+	}
+	a := s.Sizeof(T) // may be 0
+	// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
+	if a < 1 {
+		return 1
+	}
+	if a > s.MaxAlign {
+		return s.MaxAlign
+	}
+	return a
+}
+
+func (s *StdSizes) Offsetsof(fields []*Var) []int64 {
+	offsets := make([]int64, len(fields))
+	var o int64
+	for i, f := range fields {
+		a := s.Alignof(f.typ)
+		o = align(o, a)
+		offsets[i] = o
+		o += s.Sizeof(f.typ)
+	}
+	return offsets
+}
+
+var basicSizes = [...]byte{
+	Bool:       1,
+	Int8:       1,
+	Int16:      2,
+	Int32:      4,
+	Int64:      8,
+	Uint8:      1,
+	Uint16:     2,
+	Uint32:     4,
+	Uint64:     8,
+	Float32:    4,
+	Float64:    8,
+	Complex64:  8,
+	Complex128: 16,
+}
+
+func (s *StdSizes) Sizeof(T Type) int64 {
+	switch t := T.Underlying().(type) {
+	case *Basic:
+		assert(isTyped(T))
+		k := t.kind
+		if int(k) < len(basicSizes) {
+			if s := basicSizes[k]; s > 0 {
+				return int64(s)
+			}
+		}
+		if k == String {
+			return s.WordSize * 2
+		}
+	case *Array:
+		n := t.len
+		if n == 0 {
+			return 0
+		}
+		a := s.Alignof(t.elem)
+		z := s.Sizeof(t.elem)
+		return align(z, a)*(n-1) + z
+	case *Slice:
+		return s.WordSize * 3
+	case *Struct:
+		n := t.NumFields()
+		if n == 0 {
+			return 0
+		}
+		offsets := t.offsets
+		if t.offsets == nil {
+			// compute offsets on demand
+			offsets = s.Offsetsof(t.fields)
+			t.offsets = offsets
+		}
+		return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
+	case *Interface:
+		return s.WordSize * 2
+	}
+	return s.WordSize // catch-all
+}
+
+// stdSizes is used if Config.Sizes == nil.
+var stdSizes = StdSizes{8, 8}
+
+func (conf *Config) alignof(T Type) int64 {
+	if s := conf.Sizes; s != nil {
+		if a := s.Alignof(T); a >= 1 {
+			return a
+		}
+		panic("Config.Sizes.Alignof returned an alignment < 1")
+	}
+	return stdSizes.Alignof(T)
+}
+
+func (conf *Config) offsetsof(T *Struct) []int64 {
+	offsets := T.offsets
+	if offsets == nil && T.NumFields() > 0 {
+		// compute offsets on demand
+		if s := conf.Sizes; s != nil {
+			offsets = s.Offsetsof(T.fields)
+			// sanity checks
+			if len(offsets) != T.NumFields() {
+				panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
+			}
+			for _, o := range offsets {
+				if o < 0 {
+					panic("Config.Sizes.Offsetsof returned an offset < 0")
+				}
+			}
+		} else {
+			offsets = stdSizes.Offsetsof(T.fields)
+		}
+		T.offsets = offsets
+	}
+	return offsets
+}
+
+// offsetof returns the offset of the field specified via
+// the index sequence relative to typ. All embedded fields
+// must be structs (rather than pointer to structs).
+func (conf *Config) offsetof(typ Type, index []int) int64 {
+	var o int64
+	for _, i := range index {
+		s := typ.Underlying().(*Struct)
+		o += conf.offsetsof(s)[i]
+		typ = s.fields[i].typ
+	}
+	return o
+}
+
+func (conf *Config) sizeof(T Type) int64 {
+	if s := conf.Sizes; s != nil {
+		if z := s.Sizeof(T); z >= 0 {
+			return z
+		}
+		panic("Config.Sizes.Sizeof returned a size < 0")
+	}
+	return stdSizes.Sizeof(T)
+}
+
+// align returns the smallest y >= x such that y % a == 0.
+func align(x, a int64) int64 {
+	y := x + a - 1
+	return y - y%a
+}
diff --git a/third_party/go.tools/go/types/stdlib_test.go b/third_party/go.tools/go/types/stdlib_test.go
new file mode 100644
index 0000000..5642e05
--- /dev/null
+++ b/third_party/go.tools/go/types/stdlib_test.go
@@ -0,0 +1,254 @@
+// Copyright 2013 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.
+
+// This file tests types.Check by using it to
+// typecheck the standard library and tests.
+
+package types_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+var (
+	pkgCount int // number of packages processed
+	start    = time.Now()
+)
+
+func TestStdlib(t *testing.T) {
+	walkDirs(t, filepath.Join(runtime.GOROOT(), "src"))
+	if testing.Verbose() {
+		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
+	}
+}
+
+// firstComment returns the contents of the first comment in
+// the given file, assuming there's one within the first KB.
+func firstComment(filename string) string {
+	f, err := os.Open(filename)
+	if err != nil {
+		return ""
+	}
+	defer f.Close()
+
+	var src [1 << 10]byte // read at most 1KB
+	n, _ := f.Read(src[:])
+
+	var s scanner.Scanner
+	s.Init(fset.AddFile("", fset.Base(), n), src[:n], nil, scanner.ScanComments)
+	for {
+		_, tok, lit := s.Scan()
+		switch tok {
+		case token.COMMENT:
+			// remove trailing */ of multi-line comment
+			if lit[1] == '*' {
+				lit = lit[:len(lit)-2]
+			}
+			return strings.TrimSpace(lit[2:])
+		case token.EOF:
+			return ""
+		}
+	}
+}
+
+func testTestDir(t *testing.T, path string, ignore ...string) {
+	files, err := ioutil.ReadDir(path)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	excluded := make(map[string]bool)
+	for _, filename := range ignore {
+		excluded[filename] = true
+	}
+
+	fset := token.NewFileSet()
+	for _, f := range files {
+		// filter directory contents
+		if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") || excluded[f.Name()] {
+			continue
+		}
+
+		// get per-file instructions
+		expectErrors := false
+		filename := filepath.Join(path, f.Name())
+		if cmd := firstComment(filename); cmd != "" {
+			switch cmd {
+			case "skip", "compiledir":
+				continue // ignore this file
+			case "errorcheck":
+				expectErrors = true
+			}
+		}
+
+		// parse and type-check file
+		file, err := parser.ParseFile(fset, filename, nil, 0)
+		if err == nil {
+			_, err = Check(filename, fset, []*ast.File{file})
+		}
+
+		if expectErrors {
+			if err == nil {
+				t.Errorf("expected errors but found none in %s", filename)
+			}
+		} else {
+			if err != nil {
+				t.Error(err)
+			}
+		}
+	}
+}
+
+func TestStdTest(t *testing.T) {
+	testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
+		"cmplxdivide.go", // also needs file cmplxdivide1.go - ignore
+		"sigchld.go",     // don't work on Windows; testTestDir should consult build tags
+		"float_lit2.go",  // TODO(gri) enable for releases 1.4 and higher
+	)
+}
+
+func TestStdFixed(t *testing.T) {
+	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
+		"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
+		"bug459.go",    // possibly incorrect test - see issue 6703 (pending spec clarification)
+		"issue3924.go", // possibly incorrect test - see issue 6671 (pending spec clarification)
+		"issue6889.go", // gc-specific test
+	)
+}
+
+func TestStdKen(t *testing.T) {
+	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "ken"))
+}
+
+// Package paths of excluded packages.
+var excluded = map[string]bool{
+	"builtin": true,
+}
+
+// typecheck typechecks the given package files.
+func typecheck(t *testing.T, path string, filenames []string) {
+	fset := token.NewFileSet()
+
+	// parse package files
+	var files []*ast.File
+	for _, filename := range filenames {
+		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
+		if err != nil {
+			// the parser error may be a list of individual errors; report them all
+			if list, ok := err.(scanner.ErrorList); ok {
+				for _, err := range list {
+					t.Error(err)
+				}
+				return
+			}
+			t.Error(err)
+			return
+		}
+
+		if testing.Verbose() {
+			if len(files) == 0 {
+				fmt.Println("package", file.Name.Name)
+			}
+			fmt.Println("\t", filename)
+		}
+
+		files = append(files, file)
+	}
+
+	// typecheck package files
+	var conf Config
+	conf.Error = func(err error) { t.Error(err) }
+	info := Info{Uses: make(map[*ast.Ident]Object)}
+	conf.Check(path, fset, files, &info)
+	pkgCount++
+
+	// Perform checks of API invariants.
+
+	// All Objects have a package, except predeclared ones.
+	errorError := Universe.Lookup("error").Type().Underlying().(*Interface).ExplicitMethod(0) // (error).Error
+	for id, obj := range info.Uses {
+		predeclared := obj == Universe.Lookup(obj.Name()) || obj == errorError
+		if predeclared == (obj.Pkg() != nil) {
+			posn := fset.Position(id.Pos())
+			if predeclared {
+				t.Errorf("%s: predeclared object with package: %s", posn, obj)
+			} else {
+				t.Errorf("%s: user-defined object without package: %s", posn, obj)
+			}
+		}
+	}
+}
+
+// pkgFilenames returns the list of package filenames for the given directory.
+func pkgFilenames(dir string) ([]string, error) {
+	ctxt := build.Default
+	ctxt.CgoEnabled = false
+	pkg, err := ctxt.ImportDir(dir, 0)
+	if err != nil {
+		if _, nogo := err.(*build.NoGoError); nogo {
+			return nil, nil // no *.go files, not an error
+		}
+		return nil, err
+	}
+	if excluded[pkg.ImportPath] {
+		return nil, nil
+	}
+	var filenames []string
+	for _, name := range pkg.GoFiles {
+		filenames = append(filenames, filepath.Join(pkg.Dir, name))
+	}
+	for _, name := range pkg.TestGoFiles {
+		filenames = append(filenames, filepath.Join(pkg.Dir, name))
+	}
+	return filenames, nil
+}
+
+// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
+//       necessarily be shorter or clearer after adding the code to
+//       terminate early for -short tests.
+
+func walkDirs(t *testing.T, dir string) {
+	// limit run time for short tests
+	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
+		return
+	}
+
+	fis, err := ioutil.ReadDir(dir)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	// typecheck package in directory
+	files, err := pkgFilenames(dir)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	if files != nil {
+		typecheck(t, dir, files)
+	}
+
+	// traverse subdirectories, but don't walk into testdata
+	for _, fi := range fis {
+		if fi.IsDir() && fi.Name() != "testdata" {
+			walkDirs(t, filepath.Join(dir, fi.Name()))
+		}
+	}
+}
diff --git a/third_party/go.tools/go/types/stmt.go b/third_party/go.tools/go/types/stmt.go
new file mode 100644
index 0000000..229382e
--- /dev/null
+++ b/third_party/go.tools/go/types/stmt.go
@@ -0,0 +1,729 @@
+// 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.
+
+// This file implements typechecking of statements.
+
+package types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt) {
+	if trace {
+		if name == "" {
+			name = "<function literal>"
+		}
+		fmt.Printf("--- %s: %s {\n", name, sig)
+		defer fmt.Println("--- <end>")
+	}
+
+	// save/restore current context and setup function context
+	// (and use 0 indentation at function start)
+	defer func(ctxt context, indent int) {
+		check.context = ctxt
+		check.indent = indent
+	}(check.context, check.indent)
+	check.context = context{
+		decl:  decl,
+		scope: sig.scope,
+		sig:   sig,
+	}
+	check.indent = 0
+
+	check.stmtList(0, body.List)
+
+	if check.hasLabel {
+		check.labels(body)
+	}
+
+	if sig.results.Len() > 0 && !check.isTerminating(body, "") {
+		check.error(body.Rbrace, "missing return")
+	}
+
+	// spec: "Implementation restriction: A compiler may make it illegal to
+	// declare a variable inside a function body if the variable is never used."
+	// (One could check each scope after use, but that distributes this check
+	// over several places because CloseScope is not always called explicitly.)
+	check.usage(sig.scope)
+}
+
+func (check *Checker) usage(scope *Scope) {
+	for _, obj := range scope.elems {
+		if v, _ := obj.(*Var); v != nil && !v.used {
+			check.softErrorf(v.pos, "%s declared but not used", v.name)
+		}
+	}
+	for _, scope := range scope.children {
+		check.usage(scope)
+	}
+}
+
+// stmtContext is a bitset describing which
+// control-flow statements are permissible.
+type stmtContext uint
+
+const (
+	breakOk stmtContext = 1 << iota
+	continueOk
+	fallthroughOk
+)
+
+func (check *Checker) simpleStmt(s ast.Stmt) {
+	if s != nil {
+		check.stmt(0, s)
+	}
+}
+
+func (check *Checker) stmtList(ctxt stmtContext, list []ast.Stmt) {
+	ok := ctxt&fallthroughOk != 0
+	inner := ctxt &^ fallthroughOk
+	for i, s := range list {
+		inner := inner
+		if ok && i+1 == len(list) {
+			inner |= fallthroughOk
+		}
+		check.stmt(inner, s)
+	}
+}
+
+func (check *Checker) multipleDefaults(list []ast.Stmt) {
+	var first ast.Stmt
+	for _, s := range list {
+		var d ast.Stmt
+		switch c := s.(type) {
+		case *ast.CaseClause:
+			if len(c.List) == 0 {
+				d = s
+			}
+		case *ast.CommClause:
+			if c.Comm == nil {
+				d = s
+			}
+		default:
+			check.invalidAST(s.Pos(), "case/communication clause expected")
+		}
+		if d != nil {
+			if first != nil {
+				check.errorf(d.Pos(), "multiple defaults (first at %s)", first.Pos())
+			} else {
+				first = d
+			}
+		}
+	}
+}
+
+func (check *Checker) openScope(s ast.Stmt, comment string) {
+	scope := NewScope(check.scope, comment)
+	check.recordScope(s, scope)
+	check.scope = scope
+}
+
+func (check *Checker) closeScope() {
+	check.scope = check.scope.Parent()
+}
+
+func assignOp(op token.Token) token.Token {
+	// token_test.go verifies the token ordering this function relies on
+	if token.ADD_ASSIGN <= op && op <= token.AND_NOT_ASSIGN {
+		return op + (token.ADD - token.ADD_ASSIGN)
+	}
+	return token.ILLEGAL
+}
+
+func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) {
+	var x operand
+	var msg string
+	switch check.rawExpr(&x, call, nil) {
+	case conversion:
+		msg = "requires function call, not conversion"
+	case expression:
+		msg = "discards result of"
+	case statement:
+		return
+	default:
+		unreachable()
+	}
+	check.errorf(x.pos(), "%s %s %s", keyword, msg, &x)
+}
+
+func (check *Checker) caseValues(x operand /* copy argument (not *operand!) */, values []ast.Expr) {
+	// No duplicate checking for now. See issue 4524.
+	for _, e := range values {
+		var y operand
+		check.expr(&y, e)
+		if y.mode == invalid {
+			return
+		}
+		// TODO(gri) The convertUntyped call pair below appears in other places. Factor!
+		// Order matters: By comparing y against x, error positions are at the case values.
+		check.convertUntyped(&y, x.typ)
+		if y.mode == invalid {
+			return
+		}
+		check.convertUntyped(&x, y.typ)
+		if x.mode == invalid {
+			return
+		}
+		check.comparison(&y, &x, token.EQL)
+	}
+}
+
+func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]token.Pos) (T Type) {
+L:
+	for _, e := range types {
+		T = check.typOrNil(e)
+		if T == Typ[Invalid] {
+			continue
+		}
+		// complain about duplicate types
+		// TODO(gri) use a type hash to avoid quadratic algorithm
+		for t, pos := range seen {
+			if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
+				// talk about "case" rather than "type" because of nil case
+				check.error(e.Pos(), "duplicate case in type switch")
+				check.errorf(pos, "\tprevious case %s", T) // secondary error, \t indented
+				continue L
+			}
+		}
+		seen[T] = e.Pos()
+		if T != nil {
+			check.typeAssertion(e.Pos(), x, xtyp, T)
+		}
+	}
+	return
+}
+
+// stmt typechecks statement s.
+func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
+	// statements cannot use iota in general
+	// (constant declarations set it explicitly)
+	assert(check.iota == nil)
+
+	// statements must end with the same top scope as they started with
+	if debug {
+		defer func(scope *Scope) {
+			// don't check if code is panicking
+			if p := recover(); p != nil {
+				panic(p)
+			}
+			assert(scope == check.scope)
+		}(check.scope)
+	}
+
+	inner := ctxt &^ fallthroughOk
+	switch s := s.(type) {
+	case *ast.BadStmt, *ast.EmptyStmt:
+		// ignore
+
+	case *ast.DeclStmt:
+		check.declStmt(s.Decl)
+
+	case *ast.LabeledStmt:
+		check.hasLabel = true
+		check.stmt(ctxt, s.Stmt)
+
+	case *ast.ExprStmt:
+		// spec: "With the exception of specific built-in functions,
+		// function and method calls and receive operations can appear
+		// in statement context. Such statements may be parenthesized."
+		var x operand
+		kind := check.rawExpr(&x, s.X, nil)
+		var msg string
+		switch x.mode {
+		default:
+			if kind == statement {
+				return
+			}
+			msg = "is not used"
+		case builtin:
+			msg = "must be called"
+		case typexpr:
+			msg = "is not an expression"
+		}
+		check.errorf(x.pos(), "%s %s", &x, msg)
+
+	case *ast.SendStmt:
+		var ch, x operand
+		check.expr(&ch, s.Chan)
+		check.expr(&x, s.Value)
+		if ch.mode == invalid || x.mode == invalid {
+			return
+		}
+		if tch, ok := ch.typ.Underlying().(*Chan); !ok || tch.dir == RecvOnly || !check.assignment(&x, tch.elem) {
+			if x.mode != invalid {
+				check.invalidOp(ch.pos(), "cannot send %s to channel %s", &x, &ch)
+			}
+		}
+
+	case *ast.IncDecStmt:
+		var op token.Token
+		switch s.Tok {
+		case token.INC:
+			op = token.ADD
+		case token.DEC:
+			op = token.SUB
+		default:
+			check.invalidAST(s.TokPos, "unknown inc/dec operation %s", s.Tok)
+			return
+		}
+		var x operand
+		Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position
+		check.binary(&x, s.X, Y, op)
+		if x.mode == invalid {
+			return
+		}
+		check.assignVar(s.X, &x)
+
+	case *ast.AssignStmt:
+		switch s.Tok {
+		case token.ASSIGN, token.DEFINE:
+			if len(s.Lhs) == 0 {
+				check.invalidAST(s.Pos(), "missing lhs in assignment")
+				return
+			}
+			if s.Tok == token.DEFINE {
+				check.shortVarDecl(s.TokPos, s.Lhs, s.Rhs)
+			} else {
+				// regular assignment
+				check.assignVars(s.Lhs, s.Rhs)
+			}
+
+		default:
+			// assignment operations
+			if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
+				check.errorf(s.TokPos, "assignment operation %s requires single-valued expressions", s.Tok)
+				return
+			}
+			op := assignOp(s.Tok)
+			if op == token.ILLEGAL {
+				check.invalidAST(s.TokPos, "unknown assignment operation %s", s.Tok)
+				return
+			}
+			var x operand
+			check.binary(&x, s.Lhs[0], s.Rhs[0], op)
+			if x.mode == invalid {
+				return
+			}
+			check.assignVar(s.Lhs[0], &x)
+		}
+
+	case *ast.GoStmt:
+		check.suspendedCall("go", s.Call)
+
+	case *ast.DeferStmt:
+		check.suspendedCall("defer", s.Call)
+
+	case *ast.ReturnStmt:
+		res := check.sig.results
+		if res.Len() > 0 {
+			// function returns results
+			// (if one, say the first, result parameter is named, all of them are named)
+			if len(s.Results) == 0 && res.vars[0].name != "" {
+				// spec: "Implementation restriction: A compiler may disallow an empty expression
+				// list in a "return" statement if a different entity (constant, type, or variable)
+				// with the same name as a result parameter is in scope at the place of the return."
+				for _, obj := range res.vars {
+					if _, alt := check.scope.LookupParent(obj.name); alt != nil && alt != obj {
+						check.errorf(s.Pos(), "result parameter %s not in scope at return", obj.name)
+						check.errorf(alt.Pos(), "\tinner declaration of %s", obj)
+						// ok to continue
+					}
+				}
+			} else {
+				// return has results or result parameters are unnamed
+				check.initVars(res.vars, s.Results, s.Return)
+			}
+		} else if len(s.Results) > 0 {
+			check.error(s.Results[0].Pos(), "no result values expected")
+			check.use(s.Results...)
+		}
+
+	case *ast.BranchStmt:
+		if s.Label != nil {
+			check.hasLabel = true
+			return // checked in 2nd pass (check.labels)
+		}
+		switch s.Tok {
+		case token.BREAK:
+			if ctxt&breakOk == 0 {
+				check.error(s.Pos(), "break not in for, switch, or select statement")
+			}
+		case token.CONTINUE:
+			if ctxt&continueOk == 0 {
+				check.error(s.Pos(), "continue not in for statement")
+			}
+		case token.FALLTHROUGH:
+			if ctxt&fallthroughOk == 0 {
+				check.error(s.Pos(), "fallthrough statement out of place")
+			}
+		default:
+			check.invalidAST(s.Pos(), "branch statement: %s", s.Tok)
+		}
+
+	case *ast.BlockStmt:
+		check.openScope(s, "block")
+		defer check.closeScope()
+
+		check.stmtList(inner, s.List)
+
+	case *ast.IfStmt:
+		check.openScope(s, "if")
+		defer check.closeScope()
+
+		check.simpleStmt(s.Init)
+		var x operand
+		check.expr(&x, s.Cond)
+		if x.mode != invalid && !isBoolean(x.typ) {
+			check.error(s.Cond.Pos(), "non-boolean condition in if statement")
+		}
+		check.stmt(inner, s.Body)
+		if s.Else != nil {
+			check.stmt(inner, s.Else)
+		}
+
+	case *ast.SwitchStmt:
+		inner |= breakOk
+		check.openScope(s, "switch")
+		defer check.closeScope()
+
+		check.simpleStmt(s.Init)
+		var x operand
+		if s.Tag != nil {
+			check.expr(&x, s.Tag)
+		} else {
+			// spec: "A missing switch expression is
+			// equivalent to the boolean value true."
+			x.mode = constant
+			x.typ = Typ[Bool]
+			x.val = exact.MakeBool(true)
+			x.expr = &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"}
+		}
+
+		check.multipleDefaults(s.Body.List)
+
+		for i, c := range s.Body.List {
+			clause, _ := c.(*ast.CaseClause)
+			if clause == nil {
+				check.invalidAST(c.Pos(), "incorrect expression switch case")
+				continue
+			}
+			if x.mode != invalid {
+				check.caseValues(x, clause.List)
+			}
+			check.openScope(clause, "case")
+			inner := inner
+			if i+1 < len(s.Body.List) {
+				inner |= fallthroughOk
+			}
+			check.stmtList(inner, clause.Body)
+			check.closeScope()
+		}
+
+	case *ast.TypeSwitchStmt:
+		inner |= breakOk
+		check.openScope(s, "type switch")
+		defer check.closeScope()
+
+		check.simpleStmt(s.Init)
+
+		// A type switch guard must be of the form:
+		//
+		//     TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
+		//
+		// The parser is checking syntactic correctness;
+		// remaining syntactic errors are considered AST errors here.
+		// TODO(gri) better factoring of error handling (invalid ASTs)
+		//
+		var lhs *ast.Ident // lhs identifier or nil
+		var rhs ast.Expr
+		switch guard := s.Assign.(type) {
+		case *ast.ExprStmt:
+			rhs = guard.X
+		case *ast.AssignStmt:
+			if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
+				check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+				return
+			}
+
+			lhs, _ = guard.Lhs[0].(*ast.Ident)
+			if lhs == nil {
+				check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+				return
+			}
+			check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause
+
+			rhs = guard.Rhs[0]
+
+		default:
+			check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+			return
+		}
+
+		// rhs must be of the form: expr.(type) and expr must be an interface
+		expr, _ := rhs.(*ast.TypeAssertExpr)
+		if expr == nil || expr.Type != nil {
+			check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+			return
+		}
+		var x operand
+		check.expr(&x, expr.X)
+		if x.mode == invalid {
+			return
+		}
+		xtyp, _ := x.typ.Underlying().(*Interface)
+		if xtyp == nil {
+			check.errorf(x.pos(), "%s is not an interface", &x)
+			return
+		}
+
+		check.multipleDefaults(s.Body.List)
+
+		var lhsVars []*Var               // list of implicitly declared lhs variables
+		seen := make(map[Type]token.Pos) // map of seen types to positions
+		for _, s := range s.Body.List {
+			clause, _ := s.(*ast.CaseClause)
+			if clause == nil {
+				check.invalidAST(s.Pos(), "incorrect type switch case")
+				continue
+			}
+			// Check each type in this type switch case.
+			T := check.caseTypes(&x, xtyp, clause.List, seen)
+			check.openScope(clause, "case")
+			// If lhs exists, declare a corresponding variable in the case-local scope.
+			if lhs != nil {
+				// spec: "The TypeSwitchGuard may include a short variable declaration.
+				// When that form is used, the variable is declared at the beginning of
+				// the implicit block in each clause. In clauses with a case listing
+				// exactly one type, the variable has that type; otherwise, the variable
+				// has the type of the expression in the TypeSwitchGuard."
+				if len(clause.List) != 1 || T == nil {
+					T = x.typ
+				}
+				obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T)
+				check.declare(check.scope, nil, obj)
+				check.recordImplicit(clause, obj)
+				// For the "declared but not used" error, all lhs variables act as
+				// one; i.e., if any one of them is 'used', all of them are 'used'.
+				// Collect them for later analysis.
+				lhsVars = append(lhsVars, obj)
+			}
+			check.stmtList(inner, clause.Body)
+			check.closeScope()
+		}
+
+		// If lhs exists, we must have at least one lhs variable that was used.
+		if lhs != nil {
+			var used bool
+			for _, v := range lhsVars {
+				if v.used {
+					used = true
+				}
+				v.used = true // avoid usage error when checking entire function
+			}
+			if !used {
+				check.softErrorf(lhs.Pos(), "%s declared but not used", lhs.Name)
+			}
+		}
+
+	case *ast.SelectStmt:
+		inner |= breakOk
+
+		check.multipleDefaults(s.Body.List)
+
+		for _, s := range s.Body.List {
+			clause, _ := s.(*ast.CommClause)
+			if clause == nil {
+				continue // error reported before
+			}
+
+			// clause.Comm must be a SendStmt, RecvStmt, or default case
+			valid := false
+			var rhs ast.Expr // rhs of RecvStmt, or nil
+			switch s := clause.Comm.(type) {
+			case nil, *ast.SendStmt:
+				valid = true
+			case *ast.AssignStmt:
+				if len(s.Rhs) == 1 {
+					rhs = s.Rhs[0]
+				}
+			case *ast.ExprStmt:
+				rhs = s.X
+			}
+
+			// if present, rhs must be a receive operation
+			if rhs != nil {
+				if x, _ := unparen(rhs).(*ast.UnaryExpr); x != nil && x.Op == token.ARROW {
+					valid = true
+				}
+			}
+
+			if !valid {
+				check.error(clause.Comm.Pos(), "select case must be send or receive (possibly with assignment)")
+				continue
+			}
+
+			check.openScope(s, "case")
+			defer check.closeScope()
+			if clause.Comm != nil {
+				check.stmt(inner, clause.Comm)
+			}
+			check.stmtList(inner, clause.Body)
+		}
+
+	case *ast.ForStmt:
+		inner |= breakOk | continueOk
+		check.openScope(s, "for")
+		defer check.closeScope()
+
+		check.simpleStmt(s.Init)
+		if s.Cond != nil {
+			var x operand
+			check.expr(&x, s.Cond)
+			if x.mode != invalid && !isBoolean(x.typ) {
+				check.error(s.Cond.Pos(), "non-boolean condition in for statement")
+			}
+		}
+		check.simpleStmt(s.Post)
+		// spec: "The init statement may be a short variable
+		// declaration, but the post statement must not."
+		if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE {
+			check.softErrorf(s.Pos(), "cannot declare in post statement")
+			check.use(s.Lhs...) // avoid follow-up errors
+		}
+		check.stmt(inner, s.Body)
+
+	case *ast.RangeStmt:
+		inner |= breakOk | continueOk
+		check.openScope(s, "for")
+		defer check.closeScope()
+
+		// check expression to iterate over
+		decl := s.Tok == token.DEFINE
+		var x operand
+		check.expr(&x, s.X)
+		if x.mode == invalid {
+			// if we don't have a declaration, we can still check the loop's body
+			// (otherwise we can't because we are missing the declared variables)
+			if !decl {
+				check.stmt(inner, s.Body)
+			}
+			return
+		}
+
+		// determine key/value types
+		var key, val Type
+		switch typ := x.typ.Underlying().(type) {
+		case *Basic:
+			if isString(typ) {
+				key = Typ[Int]
+				val = UniverseRune // use 'rune' name
+			}
+		case *Array:
+			key = Typ[Int]
+			val = typ.elem
+		case *Slice:
+			key = Typ[Int]
+			val = typ.elem
+		case *Pointer:
+			if typ, _ := typ.base.Underlying().(*Array); typ != nil {
+				key = Typ[Int]
+				val = typ.elem
+			}
+		case *Map:
+			key = typ.key
+			val = typ.elem
+		case *Chan:
+			key = typ.elem
+			val = Typ[Invalid]
+			if typ.dir == SendOnly {
+				check.errorf(x.pos(), "cannot range over send-only channel %s", &x)
+				// ok to continue
+			}
+			if s.Value != nil {
+				check.errorf(s.Value.Pos(), "iteration over %s permits only one iteration variable", &x)
+				// ok to continue
+			}
+		}
+
+		if key == nil {
+			check.errorf(x.pos(), "cannot range over %s", &x)
+			// if we don't have a declaration, we can still check the loop's body
+			if !decl {
+				check.stmt(inner, s.Body)
+			}
+			return
+		}
+
+		// check assignment to/declaration of iteration variables
+		// (irregular assignment, cannot easily map to existing assignment checks)
+
+		// lhs expressions and initialization value (rhs) types
+		lhs := [2]ast.Expr{s.Key, s.Value}
+		rhs := [2]Type{key, val}
+
+		if decl {
+			// short variable declaration; variable scope starts after the range clause
+			// (the for loop opens a new scope, so variables on the lhs never redeclare
+			// previously declared variables)
+			var vars []*Var
+			for i, lhs := range lhs {
+				if lhs == nil {
+					continue
+				}
+
+				// determine lhs variable
+				var obj *Var
+				if ident, _ := lhs.(*ast.Ident); ident != nil {
+					// declare new variable
+					name := ident.Name
+					obj = NewVar(ident.Pos(), check.pkg, name, nil)
+					check.recordDef(ident, obj)
+					// _ variables don't count as new variables
+					if name != "_" {
+						vars = append(vars, obj)
+					}
+				} else {
+					check.errorf(lhs.Pos(), "cannot declare %s", lhs)
+					obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
+				}
+
+				// initialize lhs variable
+				x.mode = value
+				x.expr = lhs // we don't have a better rhs expression to use here
+				x.typ = rhs[i]
+				check.initVar(obj, &x, false)
+			}
+
+			// declare variables
+			if len(vars) > 0 {
+				for _, obj := range vars {
+					check.declare(check.scope, nil /* recordDef already called */, obj)
+				}
+			} else {
+				check.error(s.TokPos, "no new variables on left side of :=")
+			}
+		} else {
+			// ordinary assignment
+			for i, lhs := range lhs {
+				if lhs == nil {
+					continue
+				}
+				x.mode = value
+				x.expr = lhs // we don't have a better rhs expression to use here
+				x.typ = rhs[i]
+				check.assignVar(lhs, &x)
+			}
+		}
+
+		check.stmt(inner, s.Body)
+
+	default:
+		check.error(s.Pos(), "invalid statement")
+	}
+}
diff --git a/third_party/go.tools/go/types/testdata/blank.src b/third_party/go.tools/go/types/testdata/blank.src
new file mode 100644
index 0000000..6a2507f
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/blank.src
@@ -0,0 +1,5 @@
+// Copyright 2014 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 _ /* ERROR invalid package name */
diff --git a/third_party/go.tools/go/types/testdata/builtins.src b/third_party/go.tools/go/types/testdata/builtins.src
new file mode 100644
index 0000000..8b405c3
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/builtins.src
@@ -0,0 +1,881 @@
+// 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.
+
+// builtin calls
+
+package builtins
+
+import "unsafe"
+
+func f0() {}
+
+func append1() {
+	var b byte
+	var x int
+	var s []byte
+	_ = append() // ERROR not enough arguments
+	_ = append("foo" /* ERROR not a slice */ )
+	_ = append(nil /* ERROR not a slice */ , s)
+	_ = append(x /* ERROR not a slice */ , s)
+	_ = append(s)
+	append /* ERROR not used */ (s)
+
+	_ = append(s, b)
+	_ = append(s, x /* ERROR cannot pass argument x */ )
+	_ = append(s, s /* ERROR cannot pass argument s */ )
+	_ = append(s /* ERROR can only use ... with matching parameter */ ...)
+	_ = append(s, b, s /* ERROR can only use ... with matching parameter */ ...)
+	_ = append(s, 1, 2, 3)
+	_ = append(s, 1, 2, 3, x /* ERROR cannot pass argument x */ , 5, 6, 6)
+	_ = append(s, 1, 2, s /* ERROR can only use ... with matching parameter */ ...)
+	_ = append([]interface{}(nil), 1, 2, "foo", x, 3.1425, false)
+
+	type S []byte
+	type T string
+	var t T
+	_ = append(s, "foo" /* ERROR cannot convert */ )
+	_ = append(s, "foo"...)
+	_ = append(S(s), "foo" /* ERROR cannot convert */ )
+	_ = append(S(s), "foo"...)
+	_ = append(s, t /* ERROR cannot pass argument t */ )
+	_ = append(s, t...)
+	_ = append(s, T("foo")...)
+	_ = append(S(s), t /* ERROR cannot pass argument t */ )
+	_ = append(S(s), t...)
+	_ = append(S(s), T("foo")...)
+	_ = append([]string{}, t /* ERROR cannot pass argument t */ , "foo")
+	_ = append([]T{}, t, "foo")
+}
+
+// from the spec
+func append2() {
+	s0 := []int{0, 0}
+	s1 := append(s0, 2)                // append a single element     s1 == []int{0, 0, 2}
+	s2 := append(s1, 3, 5, 7)          // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
+	s3 := append(s2, s0...)            // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}
+	s4 := append(s3[3:6], s3[2:]...)   // append overlapping slice    s4 == []int{3, 5, 7, 2, 3, 5, 7, 0, 0}
+
+	var t []interface{}
+	t = append(t, 42, 3.1415, "foo")   //                             t == []interface{}{42, 3.1415, "foo"}
+
+	var b []byte
+	b = append(b, "bar"...)            // append string contents      b == []byte{'b', 'a', 'r' }
+
+	_ = s4
+}
+
+func append3() {
+	f1 := func() (s []int) { return }
+	f2 := func() (s []int, x int) { return }
+	f3 := func() (s []int, x, y int) { return }
+	f5 := func() (s []interface{}, x int, y float32, z string, b bool) { return }
+	ff := func() (int, float32) { return 0, 0 }
+	_ = append(f0 /* ERROR used as value */ ())
+	_ = append(f1())
+	_ = append(f2())
+	_ = append(f3())
+	_ = append(f5())
+	_ = append(ff /* ERROR not a slice */ ()) // TODO(gri) better error message
+}
+
+func cap1() {
+	var a [10]bool
+	var p *[20]int
+	var c chan string
+	_ = cap() // ERROR not enough arguments
+	_ = cap(1, 2) // ERROR too many arguments
+	_ = cap(42 /* ERROR invalid */)
+	const _3 = cap(a)
+	assert(_3 == 10)
+	const _4 = cap(p)
+	assert(_4 == 20)
+	_ = cap(c)
+	cap /* ERROR not used */ (c)
+
+	// issue 4744
+	type T struct{ a [10]int }
+	const _ = cap(((*T)(nil)).a)
+
+	var s [][]byte
+	_ = cap(s)
+	_ = cap(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func cap2() {
+	f1a := func() (a [10]int) { return }
+	f1s := func() (s []int) { return }
+	f2 := func() (s []int, x int) { return }
+	_ = cap(f0 /* ERROR used as value */ ())
+	_ = cap(f1a())
+	_ = cap(f1s())
+	_ = cap(f2()) // ERROR too many arguments
+}
+
+// test cases for issue 7387
+func cap3() {
+	var f = func() int { return 0 }
+	var x = f()
+	const (
+		_ = cap([4]int{})
+		_ = cap([4]int{x})
+		_ = cap /* ERROR not constant */ ([4]int{f()})
+		_ = cap /* ERROR not constant */ ([4]int{cap([]int{})})
+		_ = cap([4]int{cap([4]int{})})
+	)
+	var y float64
+	var z complex128
+	const (
+		_ = cap([4]float64{})
+		_ = cap([4]float64{y})
+		_ = cap([4]float64{real(2i)})
+		_ = cap /* ERROR not constant */ ([4]float64{real(z)})
+	)
+	var ch chan [10]int
+	const (
+		_ = cap /* ERROR not constant */ (<-ch)
+		_ = cap /* ERROR not constant */ ([4]int{(<-ch)[0]})
+	)
+}
+
+func close1() {
+	var c chan int
+	var r <-chan int
+	close() // ERROR not enough arguments
+	close(1, 2) // ERROR too many arguments
+	close(42 /* ERROR not a channel */)
+	close(r /* ERROR receive-only channel */)
+	close(c)
+	_ = close /* ERROR used as value */ (c)
+
+	var s []chan int
+	close(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func close2() {
+	f1 := func() (ch chan int) { return }
+	f2 := func() (ch chan int, x int) { return }
+	close(f0 /* ERROR used as value */ ())
+	close(f1())
+	close(f2()) // ERROR too many arguments
+}
+
+func complex1() {
+	var i32 int32
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	var c128 complex128
+	_ = complex() // ERROR not enough arguments
+	_ = complex(1) // ERROR not enough arguments
+	_ = complex(true /* ERROR invalid argument */ , 0)
+	_ = complex(i32 /* ERROR invalid argument */ , 0)
+	_ = complex("foo" /* ERROR invalid argument */ , 0)
+	_ = complex(c64 /* ERROR invalid argument */ , 0)
+	_ = complex(0, true /* ERROR invalid argument */ )
+	_ = complex(0, i32 /* ERROR invalid argument */ )
+	_ = complex(0, "foo" /* ERROR invalid argument */ )
+	_ = complex(0, c64 /* ERROR invalid argument */ )
+	_ = complex(f32, f32)
+	_ = complex(f32, 1)
+	_ = complex(f32, 1.0)
+	_ = complex(f32, 'a')
+	_ = complex(f64, f64)
+	_ = complex(f64, 1)
+	_ = complex(f64, 1.0)
+	_ = complex(f64, 'a')
+	_ = complex(f32 /* ERROR mismatched types */ , f64)
+	_ = complex(f64 /* ERROR mismatched types */ , f32)
+	_ = complex(1, 1)
+	_ = complex(1, 1.1)
+	_ = complex(1, 'a')
+	complex /* ERROR not used */ (1, 2)
+
+	var _ complex64 = complex(f32, f32)
+	var _ complex64 = complex /* ERROR cannot initialize */ (f64, f64)
+
+	var _ complex128 = complex /* ERROR cannot initialize */ (f32, f32)
+	var _ complex128 = complex(f64, f64)
+
+	// untyped constants
+	const _ int = complex(1, 0)
+	const _ float32 = complex(1, 0)
+	const _ complex64 = complex(1, 0)
+	const _ complex128 = complex(1, 0)
+
+	const _ int = complex /* ERROR int */ (1.1, 0)
+	const _ float32 = complex /* ERROR float32 */ (1, 2)
+
+	// untyped values
+	var s uint
+	_ = complex(1 /* ERROR integer */ <<s, 0)
+	const _ = complex /* ERROR not constant */ (1 /* ERROR integer */ <<s, 0)
+	var _ int = complex /* ERROR cannot initialize */ (1 /* ERROR integer */ <<s, 0)
+
+	// floating-point argument types must be identical
+	type F32 float32
+	type F64 float64
+	var x32 F32
+	var x64 F64
+	c64 = complex(x32, x32)
+	_ = complex(x32 /* ERROR mismatched types */ , f32)
+	_ = complex(f32 /* ERROR mismatched types */ , x32)
+	c128 = complex(x64, x64)
+	_ = c128
+	_ = complex(x64 /* ERROR mismatched types */ , f64)
+	_ = complex(f64 /* ERROR mismatched types */ , x64)
+
+	var t []float32
+	_ = complex(t... /* ERROR invalid use of \.\.\. */ )
+}
+
+func complex2() {
+	f1 := func() (x float32) { return }
+	f2 := func() (x, y float32) { return }
+	f3 := func() (x, y, z float32) { return }
+	_ = complex(f0 /* ERROR used as value */ ())
+	_ = complex(f1()) // ERROR not enough arguments
+	_ = complex(f2())
+	_ = complex(f3()) // ERROR too many arguments
+}
+
+func copy1() {
+	copy() // ERROR not enough arguments
+	copy("foo") // ERROR not enough arguments
+	copy([ /* ERROR copy expects slice arguments */ ...]int{}, []int{})
+	copy([ /* ERROR copy expects slice arguments */ ]int{}, [...]int{})
+	copy([ /* ERROR different element types */ ]int8{}, "foo")
+
+	// spec examples
+	var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
+	var s = make([]int, 6)
+	var b = make([]byte, 5)
+	n1 := copy(s, a[0:])            // n1 == 6, s == []int{0, 1, 2, 3, 4, 5}
+	n2 := copy(s, s[2:])            // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
+	n3 := copy(b, "Hello, World!")  // n3 == 5, b == []byte("Hello")
+	_, _, _ = n1, n2, n3
+
+	var t [][]int
+	copy(t, t)
+	copy(t /* ERROR copy expects slice arguments */ , nil)
+	copy(nil /* ERROR copy expects slice arguments */ , t)
+	copy(nil /* ERROR copy expects slice arguments */ , nil)
+	copy(t... /* ERROR invalid use of \.\.\. */ )
+}
+
+func copy2() {
+	f1 := func() (a []int) { return }
+	f2 := func() (a, b []int) { return }
+	f3 := func() (a, b, c []int) { return }
+	copy(f0 /* ERROR used as value */ ())
+	copy(f1()) // ERROR not enough arguments
+	copy(f2())
+	copy(f3()) // ERROR too many arguments
+}
+
+func delete1() {
+	var m map[string]int
+	var s string
+	delete() // ERROR not enough arguments
+	delete(1) // ERROR not enough arguments
+	delete(1, 2, 3) // ERROR too many arguments
+	delete(m, 0 /* ERROR not assignable */)
+	delete(m, s)
+	_ = delete /* ERROR used as value */ (m, s)
+
+	var t []map[string]string
+	delete(t... /* ERROR invalid use of \.\.\. */ )
+}
+
+func delete2() {
+	f1 := func() (m map[string]int) { return }
+	f2 := func() (m map[string]int, k string) { return }
+	f3 := func() (m map[string]int, k string, x float32) { return }
+	delete(f0 /* ERROR used as value */ ())
+	delete(f1()) // ERROR not enough arguments
+	delete(f2())
+	delete(f3()) // ERROR too many arguments
+}
+
+func imag1() {
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	var c128 complex128
+	_ = imag() // ERROR not enough arguments
+	_ = imag(1, 2) // ERROR too many arguments
+	_ = imag(10 /* ERROR must be a complex number */)
+	_ = imag(2.7182818 /* ERROR must be a complex number */)
+	_ = imag("foo" /* ERROR must be a complex number */)
+	const _5 = imag(1 + 2i)
+	assert(_5 == 2)
+	f32 = _5
+	f64 = _5
+	const _6 = imag(0i)
+	assert(_6 == 0)
+	f32 = imag(c64)
+	f64 = imag(c128)
+	f32 = imag /* ERROR cannot assign */ (c128)
+	f64 = imag /* ERROR cannot assign */ (c64)
+	imag /* ERROR not used */ (c64)
+	_, _ = f32, f64
+
+	// complex type may not be predeclared
+	type C64 complex64
+	type C128 complex128
+	var x64 C64
+	var x128 C128
+	f32 = imag(x64)
+	f64 = imag(x128)
+
+	var s []complex64
+	_ = imag(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func imag2() {
+	f1 := func() (x complex128) { return }
+	f2 := func() (x, y complex128) { return }
+	_ = imag(f0 /* ERROR used as value */ ())
+	_ = imag(f1())
+	_ = imag(f2()) // ERROR too many arguments
+}
+
+func len1() {
+	const c = "foobar"
+	var a [10]bool
+	var p *[20]int
+	var m map[string]complex128
+	_ = len() // ERROR not enough arguments
+	_ = len(1, 2) // ERROR too many arguments
+	_ = len(42 /* ERROR invalid */)
+	const _3 = len(c)
+	assert(_3 == 6)
+	const _4 = len(a)
+	assert(_4 == 10)
+	const _5 = len(p)
+	assert(_5 == 20)
+	_ = len(m)
+	len /* ERROR not used */ (c)
+
+	// esoteric case
+	var t string
+	var hash map[interface{}][]*[10]int
+	const n = len /* ERROR not constant */ (hash[recover()][len(t)])
+	assert(n == 10) // ok because n has unknown value and no error is reported
+	var ch <-chan int
+	const nn = len /* ERROR not constant */ (hash[<-ch][len(t)])
+
+	// issue 4744
+	type T struct{ a [10]int }
+	const _ = len(((*T)(nil)).a)
+
+	var s [][]byte
+	_ = len(s)
+	_ = len(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func len2() {
+	f1 := func() (x []int) { return }
+	f2 := func() (x, y []int) { return }
+	_ = len(f0 /* ERROR used as value */ ())
+	_ = len(f1())
+	_ = len(f2()) // ERROR too many arguments
+}
+
+// test cases for issue 7387
+func len3() {
+	var f = func() int { return 0 }
+	var x = f()
+	const (
+		_ = len([4]int{})
+		_ = len([4]int{x})
+		_ = len /* ERROR not constant */ ([4]int{f()})
+		_ = len /* ERROR not constant */ ([4]int{len([]int{})})
+		_ = len([4]int{len([4]int{})})
+	)
+	var y float64
+	var z complex128
+	const (
+		_ = len([4]float64{})
+		_ = len([4]float64{y})
+		_ = len([4]float64{real(2i)})
+		_ = len /* ERROR not constant */ ([4]float64{real(z)})
+	)
+	var ch chan [10]int
+	const (
+		_ = len /* ERROR not constant */ (<-ch)
+		_ = len /* ERROR not constant */ ([4]int{(<-ch)[0]})
+	)
+}
+
+func make1() {
+	var n int
+	var m float32
+	var s uint
+
+	_ = make() // ERROR not enough arguments
+	_ = make(1 /* ERROR not a type */)
+	_ = make(int /* ERROR cannot make */)
+
+	// slices
+	_ = make/* ERROR arguments */ ([]int)
+	_ = make/* ERROR arguments */ ([]int, 2, 3, 4)
+	_ = make([]int, int /* ERROR not an expression */)
+	_ = make([]int, 10, float32 /* ERROR not an expression */)
+	_ = make([]int, "foo" /* ERROR cannot convert */)
+	_ = make([]int, 10, 2.3 /* ERROR truncated */)
+	_ = make([]int, 5, 10.0)
+	_ = make([]int, 0i)
+	_ = make([]int, 1.0)
+	_ = make([]int, 1.0<<s)
+	_ = make([]int, 1.1 /* ERROR int */ <<s)
+	_ = make([]int, - /* ERROR must not be negative */ 1, 10)
+	_ = make([]int, 0, - /* ERROR must not be negative */ 1)
+	_ = make([]int, - /* ERROR must not be negative */ 1, - /* ERROR must not be negative */ 1)
+	_ = make([]int, 1 /* ERROR overflows */ <<100, 1 /* ERROR overflows */ <<100)
+	_ = make([]int, 10 /* ERROR length and capacity swapped */ , 9)
+	_ = make([]int, 1 /* ERROR overflows */ <<100, 12345)
+	_ = make([]int, m /* ERROR must be integer */ )
+        _ = &make /* ERROR cannot take address */ ([]int, 0)
+
+	// maps
+	_ = make /* ERROR arguments */ (map[int]string, 10, 20)
+	_ = make(map[int]float32, int /* ERROR not an expression */)
+	_ = make(map[int]float32, "foo" /* ERROR cannot convert */)
+	_ = make(map[int]float32, 10)
+	_ = make(map[int]float32, n)
+	_ = make(map[int]float32, int64(n))
+	_ = make(map[string]bool, 10.0)
+	_ = make(map[string]bool, 10.0<<s)
+        _ = &make /* ERROR cannot take address */ (map[string]bool)
+
+	// channels
+	_ = make /* ERROR arguments */ (chan int, 10, 20)
+	_ = make(chan int, int /* ERROR not an expression */)
+	_ = make(chan<- int, "foo" /* ERROR cannot convert */)
+	_ = make(chan int, - /* ERROR must not be negative */ 10)
+	_ = make(<-chan float64, 10)
+	_ = make(chan chan int, n)
+	_ = make(chan string, int64(n))
+	_ = make(chan bool, 10.0)
+	_ = make(chan bool, 10.0<<s)
+        _ = &make /* ERROR cannot take address */ (chan bool)
+
+	make /* ERROR not used */ ([]int, 10)
+
+	var t []int
+	_ = make([]int, t[0], t[1])
+	_ = make([]int, t... /* ERROR invalid use of \.\.\. */ )
+}
+
+func make2() {
+	f1 /* ERROR not used */ := func() (x []int) { return }
+	_ = make(f0 /* ERROR not a type */ ())
+	_ = make(f1 /* ERROR not a type */ ())
+}
+
+func new1() {
+	_ = new() // ERROR not enough arguments
+	_ = new(1, 2) // ERROR too many arguments
+	_ = new("foo" /* ERROR not a type */)
+	p := new(float64)
+	_ = new(struct{ x, y int })
+	q := new(*float64)
+	_ = *p == **q
+	new /* ERROR not used */ (int)
+        _ = &new /* ERROR cannot take address */ (int)
+
+	_ = new(int... /* ERROR invalid use of \.\.\. */ )
+}
+
+func new2() {
+	f1 /* ERROR not used */ := func() (x []int) { return }
+	_ = new(f0 /* ERROR not a type */ ())
+	_ = new(f1 /* ERROR not a type */ ())
+}
+
+func panic1() {
+	panic() // ERROR not enough arguments
+	panic(1, 2) // ERROR too many arguments
+	panic(0)
+	panic("foo")
+	panic(false)
+	panic(1<<10)
+	panic(1 /* ERROR overflows */ <<1000)
+	_ = panic /* ERROR used as value */ (0)
+
+	var s []byte
+	panic(s)
+	panic(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func panic2() {
+	f1 := func() (x int) { return }
+	f2 := func() (x, y int) { return }
+	panic(f0 /* ERROR used as value */ ())
+	panic(f1())
+	panic(f2()) // ERROR too many arguments
+}
+
+func print1() {
+	print()
+	print(1)
+	print(1, 2)
+	print("foo")
+	print(2.718281828)
+	print(false)
+	print(1<<10)
+	print(1 /* ERROR overflows */ <<1000)
+	println(nil /* ERROR untyped nil */ )
+
+	var s []int
+	print(s... /* ERROR invalid use of \.\.\. */ )
+	_ = print /* ERROR used as value */ ()
+}
+
+func print2() {
+	f1 := func() (x int) { return }
+	f2 := func() (x, y int) { return }
+	f3 := func() (x int, y float32, z string) { return }
+	print(f0 /* ERROR used as value */ ())
+	print(f1())
+	print(f2())
+	print(f3())
+}
+
+func println1() {
+	println()
+	println(1)
+	println(1, 2)
+	println("foo")
+	println(2.718281828)
+	println(false)
+	println(1<<10)
+	println(1 /* ERROR overflows */ <<1000)
+	println(nil /* ERROR untyped nil */ )
+
+	var s []int
+	println(s... /* ERROR invalid use of \.\.\. */ )
+	_ = println /* ERROR used as value */ ()
+}
+
+func println2() {
+	f1 := func() (x int) { return }
+	f2 := func() (x, y int) { return }
+	f3 := func() (x int, y float32, z string) { return }
+	println(f0 /* ERROR used as value */ ())
+	println(f1())
+	println(f2())
+	println(f3())
+}
+
+func real1() {
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	var c128 complex128
+	_ = real() // ERROR not enough arguments
+	_ = real(1, 2) // ERROR too many arguments
+	_ = real(10 /* ERROR must be a complex number */)
+	_ = real(2.7182818 /* ERROR must be a complex number */)
+	_ = real("foo" /* ERROR must be a complex number */)
+	const _5 = real(1 + 2i)
+	assert(_5 == 1)
+	f32 = _5
+	f64 = _5
+	const _6 = real(0i)
+	assert(_6 == 0)
+	f32 = real(c64)
+	f64 = real(c128)
+	f32 = real /* ERROR cannot assign */ (c128)
+	f64 = real /* ERROR cannot assign */ (c64)
+	real /* ERROR not used */ (c64)
+
+	// complex type may not be predeclared
+	type C64 complex64
+	type C128 complex128
+	var x64 C64
+	var x128 C128
+	f32 = imag(x64)
+	f64 = imag(x128)
+
+	var s []complex64
+	_ = real(s... /* ERROR invalid use of \.\.\. */ )
+	_, _ = f32, f64
+}
+
+func real2() {
+	f1 := func() (x complex128) { return }
+	f2 := func() (x, y complex128) { return }
+	_ = real(f0 /* ERROR used as value */ ())
+	_ = real(f1())
+	_ = real(f2()) // ERROR too many arguments
+}
+
+func recover1() {
+	_ = recover()
+	_ = recover(10) // ERROR too many arguments
+	recover()
+
+	var s []int
+	recover(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func recover2() {
+	f1 := func() (x int) { return }
+	f2 := func() (x, y int) { return }
+	_ = recover(f0 /* ERROR used as value */ ())
+	_ = recover(f1()) // ERROR too many arguments
+	_ = recover(f2()) // ERROR too many arguments
+}
+
+// assuming types.DefaultPtrSize == 8
+type S0 struct{      // offset
+	a bool       //  0
+	b rune       //  4
+	c *int       //  8
+	d bool       // 16
+	e complex128 // 24
+}                    // 40
+
+type S1 struct{   // offset
+	x float32 //  0
+	y string  //  8
+	z *S1     // 24
+	S0        // 32
+}                 // 72
+
+type S2 struct{ // offset
+	*S1     //  0
+}               //  8
+
+type S3 struct { // offset
+	a int64  //  0
+	b int32  //  8
+}                // 12
+
+type S4 struct { // offset
+	S3       //  0
+	int32    // 12
+}                // 16
+
+type S5 struct {   // offset
+	a [3]int32 //  0
+	b int32    // 12
+}                  // 16
+
+func (S2) m() {}
+
+func Alignof1() {
+	var x int
+	_ = unsafe.Alignof() // ERROR not enough arguments
+	_ = unsafe.Alignof(1, 2) // ERROR too many arguments
+	_ = unsafe.Alignof(int /* ERROR not an expression */)
+	_ = unsafe.Alignof(42)
+	_ = unsafe.Alignof(new(struct{}))
+	_ = unsafe.Alignof(1<<10)
+	_ = unsafe.Alignof(1 /* ERROR overflows */ <<1000)
+	_ = unsafe.Alignof(nil /* ERROR "untyped nil */ )
+	unsafe /* ERROR not used */ .Alignof(x)
+
+	var y S0
+	assert(unsafe.Alignof(y.a) == 1)
+	assert(unsafe.Alignof(y.b) == 4)
+	assert(unsafe.Alignof(y.c) == 8)
+	assert(unsafe.Alignof(y.d) == 1)
+	assert(unsafe.Alignof(y.e) == 8)
+
+	var s []byte
+	_ = unsafe.Alignof(s)
+	_ = unsafe.Alignof(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func Alignof2() {
+	f1 := func() (x int32) { return }
+	f2 := func() (x, y int32) { return }
+	_ = unsafe.Alignof(f0 /* ERROR used as value */ ())
+	assert(unsafe.Alignof(f1()) == 4)
+	_ = unsafe.Alignof(f2()) // ERROR too many arguments
+}
+
+func Offsetof1() {
+	var x struct{ f int }
+	_ = unsafe.Offsetof() // ERROR not enough arguments
+	_ = unsafe.Offsetof(1, 2) // ERROR too many arguments
+	_ = unsafe.Offsetof(int /* ERROR not a selector expression */ )
+	_ = unsafe.Offsetof(x /* ERROR not a selector expression */ )
+	_ = unsafe.Offsetof(nil /* ERROR not a selector expression */ )
+	_ = unsafe.Offsetof(x.f)
+	_ = unsafe.Offsetof((x.f))
+	_ = unsafe.Offsetof((((((((x))).f)))))
+	unsafe /* ERROR not used */ .Offsetof(x.f)
+
+	var y0 S0
+	assert(unsafe.Offsetof(y0.a) == 0)
+	assert(unsafe.Offsetof(y0.b) == 4)
+	assert(unsafe.Offsetof(y0.c) == 8)
+	assert(unsafe.Offsetof(y0.d) == 16)
+	assert(unsafe.Offsetof(y0.e) == 24)
+
+	var y1 S1
+	assert(unsafe.Offsetof(y1.x) == 0)
+	assert(unsafe.Offsetof(y1.y) == 8)
+	assert(unsafe.Offsetof(y1.z) == 24)
+	assert(unsafe.Offsetof(y1.S0) == 32)
+
+	assert(unsafe.Offsetof(y1.S0.a) == 0) // relative to S0
+	assert(unsafe.Offsetof(y1.a) == 32)   // relative to S1
+	assert(unsafe.Offsetof(y1.b) == 36)   // relative to S1
+	assert(unsafe.Offsetof(y1.c) == 40)   // relative to S1
+	assert(unsafe.Offsetof(y1.d) == 48)   // relative to S1
+	assert(unsafe.Offsetof(y1.e) == 56)   // relative to S1
+
+	var y1p *S1
+	assert(unsafe.Offsetof(y1p.S0) == 32)
+
+	type P *S1
+	var p P = y1p
+	assert(unsafe.Offsetof(p.S0) == 32)
+
+	var y2 S2
+	assert(unsafe.Offsetof(y2.S1) == 0)
+	_ = unsafe.Offsetof(y2 /* ERROR embedded via a pointer */ .x)
+	_ = unsafe.Offsetof(y2 /* ERROR method value */ .m)
+
+	var s []byte
+	_ = unsafe.Offsetof(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func Offsetof2() {
+	f1 := func() (x int32) { return }
+	f2 := func() (x, y int32) { return }
+	_ = unsafe.Offsetof(f0 /* ERROR not a selector expression */ ())
+	_ = unsafe.Offsetof(f1 /* ERROR not a selector expression */ ())
+	_ = unsafe.Offsetof(f2 /* ERROR not a selector expression */ ())
+}
+
+func Sizeof1() {
+	var x int
+	_ = unsafe.Sizeof() // ERROR not enough arguments
+	_ = unsafe.Sizeof(1, 2) // ERROR too many arguments
+	_ = unsafe.Sizeof(int /* ERROR not an expression */)
+	_ = unsafe.Sizeof(42)
+	_ = unsafe.Sizeof(new(complex128))
+	_ = unsafe.Sizeof(1<<10)
+	_ = unsafe.Sizeof(1 /* ERROR overflows */ <<1000)
+	_ = unsafe.Sizeof(nil /* ERROR untyped nil */ )
+	unsafe /* ERROR not used */ .Sizeof(x)
+
+	// basic types have size guarantees
+	assert(unsafe.Sizeof(byte(0)) == 1)
+	assert(unsafe.Sizeof(uint8(0)) == 1)
+	assert(unsafe.Sizeof(int8(0)) == 1)
+	assert(unsafe.Sizeof(uint16(0)) == 2)
+	assert(unsafe.Sizeof(int16(0)) == 2)
+	assert(unsafe.Sizeof(uint32(0)) == 4)
+	assert(unsafe.Sizeof(int32(0)) == 4)
+	assert(unsafe.Sizeof(float32(0)) == 4)
+	assert(unsafe.Sizeof(uint64(0)) == 8)
+	assert(unsafe.Sizeof(int64(0)) == 8)
+	assert(unsafe.Sizeof(float64(0)) == 8)
+	assert(unsafe.Sizeof(complex64(0)) == 8)
+	assert(unsafe.Sizeof(complex128(0)) == 16)
+
+	var y0 S0
+	assert(unsafe.Sizeof(y0.a) == 1)
+	assert(unsafe.Sizeof(y0.b) == 4)
+	assert(unsafe.Sizeof(y0.c) == 8)
+	assert(unsafe.Sizeof(y0.d) == 1)
+	assert(unsafe.Sizeof(y0.e) == 16)
+	assert(unsafe.Sizeof(y0) == 40)
+
+	var y1 S1
+	assert(unsafe.Sizeof(y1) == 72)
+
+	var y2 S2
+	assert(unsafe.Sizeof(y2) == 8)
+
+	var y3 S3
+	assert(unsafe.Sizeof(y3) == 12)
+
+	var y4 S4
+	assert(unsafe.Sizeof(y4) == 16)
+
+	var y5 S5
+	assert(unsafe.Sizeof(y5) == 16)
+
+	var a3 [10]S3
+	assert(unsafe.Sizeof(a3) == 156)
+
+	// test case for issue 5670
+	type T struct {
+		a int32
+		_ int32
+		c int32
+	}
+	assert(unsafe.Sizeof(T{}) == 12)
+
+	var s []byte
+	_ = unsafe.Sizeof(s)
+	_ = unsafe.Sizeof(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func Sizeof2() {
+	f1 := func() (x int64) { return }
+	f2 := func() (x, y int64) { return }
+	_ = unsafe.Sizeof(f0 /* ERROR used as value */ ())
+	assert(unsafe.Sizeof(f1()) == 8)
+	_ = unsafe.Sizeof(f2()) // ERROR too many arguments
+}
+
+// self-testing only
+func assert1() {
+	var x int
+	assert() /* ERROR not enough arguments */
+	assert(1, 2) /* ERROR too many arguments */
+	assert("foo" /* ERROR boolean constant */ )
+	assert(x /* ERROR boolean constant */)
+	assert(true)
+	assert /* ERROR failed */ (false)
+	_ = assert(true)
+
+	var s []byte
+	assert(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func assert2() {
+	f1 := func() (x bool) { return }
+	f2 := func() (x bool) { return }
+	assert(f0 /* ERROR used as value */ ())
+	assert(f1 /* ERROR boolean constant */ ())
+	assert(f2 /* ERROR boolean constant */ ())
+}
+
+// self-testing only
+func trace1() {
+	// Uncomment the code below to test trace - will produce console output
+	// _ = trace /* ERROR no value */ ()
+	// _ = trace(1)
+	// _ = trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar")
+
+	var s []byte
+	trace(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func trace2() {
+	f1 := func() (x int) { return }
+	f2 := func() (x int, y string) { return }
+	f3 := func() (x int, y string, z []int) { return }
+	_ = f1
+	_ = f2
+	_ = f3
+	// Uncomment the code below to test trace - will produce console output
+	// trace(f0())
+	// trace(f1())
+	// trace(f2())
+	// trace(f3())
+	// trace(f0(), 1)
+	// trace(f1(), 1, 2)
+	// trace(f2(), 1, 2, 3)
+	// trace(f3(), 1, 2, 3, 4)
+}
diff --git a/third_party/go.tools/go/types/testdata/const0.src b/third_party/go.tools/go/types/testdata/const0.src
new file mode 100644
index 0000000..c4419ab
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/const0.src
@@ -0,0 +1,282 @@
+// 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.
+
+// constant declarations
+
+package const0
+
+// constants declarations must be initialized by constants
+var x = 0
+const c0 = x /* ERROR "not constant" */
+
+// typed constants must have constant types
+const _ interface /* ERROR invalid constant type */ {} = 0
+
+func _ () {
+	const _ interface /* ERROR invalid constant type */ {} = 0
+	for i := 0; i < 10; i++ {} // don't crash with non-nil iota here
+}
+
+// untyped constants
+const (
+	// boolean values
+	ub0 = false
+	ub1 = true
+	ub2 = 2 < 1
+	ub3 = ui1 == uf1
+	ub4 = true /* ERROR "cannot convert" */ == 0
+
+	// integer values
+	ui0 = 0
+	ui1 = 1
+	ui2 = 42
+	ui3 = 3141592653589793238462643383279502884197169399375105820974944592307816406286
+	ui4 = -10
+
+	ui5 = ui0 + ui1
+	ui6 = ui1 - ui1
+	ui7 = ui2 * ui1
+	ui8 = ui3 / ui3
+	ui9 = ui3 % ui3
+
+	ui10 = 1 / 0 /* ERROR "division by zero" */
+	ui11 = ui1 / 0 /* ERROR "division by zero" */
+	ui12 = ui3 / ui0 /* ERROR "division by zero" */
+	ui13 = 1 % 0 /* ERROR "division by zero" */
+	ui14 = ui1 % 0 /* ERROR "division by zero" */
+	ui15 = ui3 % ui0 /* ERROR "division by zero" */
+
+	ui16 = ui2 & ui3
+	ui17 = ui2 | ui3
+	ui18 = ui2 ^ ui3
+	ui19 = 1 /* ERROR "invalid operation" */ % 1.0
+
+	// floating point values
+	uf0 = 0.
+	uf1 = 1.
+	uf2 = 4.2e1
+	uf3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
+	uf4 = 1e-1
+
+	uf5 = uf0 + uf1
+	uf6 = uf1 - uf1
+	uf7 = uf2 * uf1
+	uf8 = uf3 / uf3
+	uf9 = uf3 /* ERROR "not defined" */ % uf3
+
+	uf10 = 1 / 0 /* ERROR "division by zero" */
+	uf11 = uf1 / 0 /* ERROR "division by zero" */
+	uf12 = uf3 / uf0 /* ERROR "division by zero" */
+
+	uf16 = uf2 /* ERROR "not defined" */ & uf3
+	uf17 = uf2 /* ERROR "not defined" */ | uf3
+	uf18 = uf2 /* ERROR "not defined" */ ^ uf3
+
+	// complex values
+	uc0 = 0.i
+	uc1 = 1.i
+	uc2 = 4.2e1i
+	uc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i
+	uc4 = 1e-1i
+
+	uc5 = uc0 + uc1
+	uc6 = uc1 - uc1
+	uc7 = uc2 * uc1
+	uc8 = uc3 / uc3
+	uc9 = uc3 /* ERROR "not defined" */ % uc3
+
+	uc10 = 1 / 0 /* ERROR "division by zero" */
+	uc11 = uc1 / 0 /* ERROR "division by zero" */
+	uc12 = uc3 / uc0 /* ERROR "division by zero" */
+
+	uc16 = uc2 /* ERROR "not defined" */ & uc3
+	uc17 = uc2 /* ERROR "not defined" */ | uc3
+	uc18 = uc2 /* ERROR "not defined" */ ^ uc3
+)
+
+type (
+	mybool bool
+	myint int
+	myfloat float64
+	mycomplex complex128
+)
+
+// typed constants
+const (
+	// boolean values
+	tb0 bool = false
+	tb1 bool = true
+	tb2 mybool = 2 < 1
+	tb3 mybool = ti1 /* ERROR "mismatched types" */ == tf1
+
+	// integer values
+	ti0 int8 = ui0
+	ti1 int32 = ui1
+	ti2 int64 = ui2
+	ti3 myint = ui3 /* ERROR "overflows" */
+	ti4 myint = ui4
+
+	ti5 = ti0 /* ERROR "mismatched types" */ + ti1
+	ti6 = ti1 - ti1
+	ti7 = ti2 /* ERROR "mismatched types" */ * ti1
+	ti8 = ti3 / ti3
+	ti9 = ti3 % ti3
+
+	ti10 = 1 / 0 /* ERROR "division by zero" */
+	ti11 = ti1 / 0 /* ERROR "division by zero" */
+	ti12 = ti3 /* ERROR "mismatched types" */ / ti0
+	ti13 = 1 % 0 /* ERROR "division by zero" */
+	ti14 = ti1 % 0 /* ERROR "division by zero" */
+	ti15 = ti3 /* ERROR "mismatched types" */ % ti0
+
+	ti16 = ti2 /* ERROR "mismatched types" */ & ti3
+	ti17 = ti2 /* ERROR "mismatched types" */ | ti4
+	ti18 = ti2 ^ ti5 // no mismatched types error because the type of ti5 is unknown
+
+	// floating point values
+	tf0 float32 = 0.
+	tf1 float32 = 1.
+	tf2 float64 = 4.2e1
+	tf3 myfloat = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
+	tf4 myfloat = 1e-1
+
+	tf5 = tf0 + tf1
+	tf6 = tf1 - tf1
+	tf7 = tf2 /* ERROR "mismatched types" */ * tf1
+	tf8 = tf3 / tf3
+	tf9 = tf3 /* ERROR "not defined" */ % tf3
+
+	tf10 = 1 / 0 /* ERROR "division by zero" */
+	tf11 = tf1 / 0 /* ERROR "division by zero" */
+	tf12 = tf3 /* ERROR "mismatched types" */ / tf0
+
+	tf16 = tf2 /* ERROR "mismatched types" */ & tf3
+	tf17 = tf2 /* ERROR "mismatched types" */ | tf3
+	tf18 = tf2 /* ERROR "mismatched types" */ ^ tf3
+
+	// complex values
+	tc0 = 0.i
+	tc1 = 1.i
+	tc2 = 4.2e1i
+	tc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i
+	tc4 = 1e-1i
+
+	tc5 = tc0 + tc1
+	tc6 = tc1 - tc1
+	tc7 = tc2 * tc1
+	tc8 = tc3 / tc3
+	tc9 = tc3 /* ERROR "not defined" */ % tc3
+
+	tc10 = 1 / 0 /* ERROR "division by zero" */
+	tc11 = tc1 / 0 /* ERROR "division by zero" */
+	tc12 = tc3 / tc0 /* ERROR "division by zero" */
+
+	tc16 = tc2 /* ERROR "not defined" */ & tc3
+	tc17 = tc2 /* ERROR "not defined" */ | tc3
+	tc18 = tc2 /* ERROR "not defined" */ ^ tc3
+)
+
+// initialization cycles
+const (
+	a /* ERROR "initialization cycle" */ = a
+	b /* ERROR "initialization cycle" */ , c /* ERROR "initialization cycle" */, d, e = e, d, c, b // TODO(gri) should only have one cycle error
+	f float64 = d
+)
+
+// multiple initialization
+const (
+	a1, a2, a3 = 7, 3.1415926, "foo"
+	b1, b2, b3 = b3, b1, 42
+	c1, c2, c3  /* ERROR "missing init expr for c3" */ = 1, 2
+	d1, d2, d3 = 1, 2, 3, 4 /* ERROR "extra init expr 4" */
+	_p0 = assert(a1 == 7)
+	_p1 = assert(a2 == 3.1415926)
+	_p2 = assert(a3 == "foo")
+	_p3 = assert(b1 == 42)
+	_p4 = assert(b2 == 42)
+	_p5 = assert(b3 == 42)
+)
+
+func _() {
+	const (
+		a1, a2, a3 = 7, 3.1415926, "foo"
+		b1, b2, b3 = b3, b1, 42
+		c1, c2, c3  /* ERROR "missing init expr for c3" */ = 1, 2
+		d1, d2, d3 = 1, 2, 3, 4 /* ERROR "extra init expr 4" */
+		_p0 = assert(a1 == 7)
+		_p1 = assert(a2 == 3.1415926)
+		_p2 = assert(a3 == "foo")
+		_p3 = assert(b1 == 42)
+		_p4 = assert(b2 == 42)
+		_p5 = assert(b3 == 42)
+	)
+}
+
+// iota
+const (
+	iota0 = iota
+	iota1 = iota
+	iota2 = iota*2
+	_a0 = assert(iota0 == 0)
+	_a1 = assert(iota1 == 1)
+	_a2 = assert(iota2 == 4)
+	iota6 = iota*3
+
+	iota7
+	iota8
+	_a3 = assert(iota7 == 21)
+	_a4 = assert(iota8 == 24)
+)
+
+const (
+	_b0 = iota
+	_b1 = assert(iota + iota2 == 5)
+	_b2 = len([iota]int{}) // iota may appear in a type!
+	_b3 = assert(_b2 == 2)
+	_b4 = len(A{})
+)
+
+type A [iota /* ERROR "cannot use iota" */ ]int
+
+// constant expressions with operands accross different
+// constant declarations must use the right iota values
+const (
+	_c0 = iota
+	_c1
+	_c2
+	_x = _c2 + _d1 + _e0 // 3
+)
+
+const (
+	_d0 = iota
+	_d1
+)
+
+const (
+	_e0 = iota
+)
+
+var _ = assert(_x == 3)
+
+// special cases
+const (
+	_n0 = nil /* ERROR "not constant" */
+	_n1 = [ /* ERROR "not constant" */ ]int{}
+)
+
+// iotas must not be usable in expressions outside constant declarations
+type _ [iota /* ERROR "iota outside constant decl" */ ]byte
+var _ = iota /* ERROR "iota outside constant decl" */
+func _() {
+	_ = iota /* ERROR "iota outside constant decl" */
+	const _ = iota
+	_ = iota /* ERROR "iota outside constant decl" */
+}
+
+func _() {
+	iota := 123
+	const x = iota /* ERROR "is not constant" */
+	var y = iota
+	_ = y
+}
diff --git a/third_party/go.tools/go/types/testdata/const1.src b/third_party/go.tools/go/types/testdata/const1.src
new file mode 100644
index 0000000..88e9fad
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/const1.src
@@ -0,0 +1,314 @@
+// 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.
+
+// constant conversions
+
+package const1
+
+const(
+	mi = ^int(0)
+	mu = ^uint(0)
+	mp = ^uintptr(0)
+
+	logSizeofInt     = uint(mi>>8&1 + mi>>16&1 + mi>>32&1)
+	logSizeofUint    = uint(mu>>8&1 + mu>>16&1 + mu>>32&1)
+	logSizeofUintptr = uint(mp>>8&1 + mp>>16&1 + mp>>32&1)
+)
+
+const (
+	minInt8 = -1<<(8<<iota - 1)
+	minInt16
+	minInt32
+	minInt64
+	minInt = -1<<(8<<logSizeofInt - 1)
+)
+
+const (
+	maxInt8 = 1<<(8<<iota - 1) - 1
+	maxInt16
+	maxInt32
+	maxInt64
+	maxInt = 1<<(8<<logSizeofInt - 1) - 1
+)
+
+const (
+	maxUint8 = 1<<(8<<iota) - 1
+	maxUint16
+	maxUint32
+	maxUint64
+	maxUint    = 1<<(8<<logSizeofUint) - 1
+	maxUintptr = 1<<(8<<logSizeofUintptr) - 1
+)
+
+const (
+	smallestFloat32 = 1.0 / (1<<(127 - 1 + 23))
+	smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
+)
+
+const (
+	_ = assert(smallestFloat32 > 0)
+	_ = assert(smallestFloat64 > 0)
+)
+
+const (
+	maxFloat32 = 1<<127 * (1<<24 - 1) / (1.0<<23)
+	maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
+)
+
+const (
+	_ int8 = minInt8 /* ERROR "overflows" */ - 1
+	_ int8 = minInt8
+	_ int8 = maxInt8
+	_ int8 = maxInt8 /* ERROR "overflows" */ + 1
+	_ int8 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = int8(minInt8 /* ERROR "cannot convert" */ - 1)
+	_ = int8(minInt8)
+	_ = int8(maxInt8)
+	_ = int8(maxInt8 /* ERROR "cannot convert" */ + 1)
+	_ = int8(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ int16 = minInt16 /* ERROR "overflows" */ - 1
+	_ int16 = minInt16
+	_ int16 = maxInt16
+	_ int16 = maxInt16 /* ERROR "overflows" */ + 1
+	_ int16 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = int16(minInt16 /* ERROR "cannot convert" */ - 1)
+	_ = int16(minInt16)
+	_ = int16(maxInt16)
+	_ = int16(maxInt16 /* ERROR "cannot convert" */ + 1)
+	_ = int16(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ int32 = minInt32 /* ERROR "overflows" */ - 1
+	_ int32 = minInt32
+	_ int32 = maxInt32
+	_ int32 = maxInt32 /* ERROR "overflows" */ + 1
+	_ int32 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = int32(minInt32 /* ERROR "cannot convert" */ - 1)
+	_ = int32(minInt32)
+	_ = int32(maxInt32)
+	_ = int32(maxInt32 /* ERROR "cannot convert" */ + 1)
+	_ = int32(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ int64 = minInt64 /* ERROR "overflows" */ - 1
+	_ int64 = minInt64
+	_ int64 = maxInt64
+	_ int64 = maxInt64 /* ERROR "overflows" */ + 1
+	_ int64 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = int64(minInt64 /* ERROR "cannot convert" */ - 1)
+	_ = int64(minInt64)
+	_ = int64(maxInt64)
+	_ = int64(maxInt64 /* ERROR "cannot convert" */ + 1)
+	_ = int64(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ int = minInt /* ERROR "overflows" */ - 1
+	_ int = minInt
+	_ int = maxInt
+	_ int = maxInt /* ERROR "overflows" */ + 1
+	_ int = smallestFloat64 /* ERROR "truncated" */
+
+	_ = int(minInt /* ERROR "cannot convert" */ - 1)
+	_ = int(minInt)
+	_ = int(maxInt)
+	_ = int(maxInt /* ERROR "cannot convert" */ + 1)
+	_ = int(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uint8 = 0 /* ERROR "overflows" */ - 1
+	_ uint8 = 0
+	_ uint8 = maxUint8
+	_ uint8 = maxUint8 /* ERROR "overflows" */ + 1
+	_ uint8 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uint8(0 /* ERROR "cannot convert" */ - 1)
+	_ = uint8(0)
+	_ = uint8(maxUint8)
+	_ = uint8(maxUint8 /* ERROR "cannot convert" */ + 1)
+	_ = uint8(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uint16 = 0 /* ERROR "overflows" */ - 1
+	_ uint16 = 0
+	_ uint16 = maxUint16
+	_ uint16 = maxUint16 /* ERROR "overflows" */ + 1
+	_ uint16 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uint16(0 /* ERROR "cannot convert" */ - 1)
+	_ = uint16(0)
+	_ = uint16(maxUint16)
+	_ = uint16(maxUint16 /* ERROR "cannot convert" */ + 1)
+	_ = uint16(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uint32 = 0 /* ERROR "overflows" */ - 1
+	_ uint32 = 0
+	_ uint32 = maxUint32
+	_ uint32 = maxUint32 /* ERROR "overflows" */ + 1
+	_ uint32 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uint32(0 /* ERROR "cannot convert" */ - 1)
+	_ = uint32(0)
+	_ = uint32(maxUint32)
+	_ = uint32(maxUint32 /* ERROR "cannot convert" */ + 1)
+	_ = uint32(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uint64 = 0 /* ERROR "overflows" */ - 1
+	_ uint64 = 0
+	_ uint64 = maxUint64
+	_ uint64 = maxUint64 /* ERROR "overflows" */ + 1
+	_ uint64 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uint64(0 /* ERROR "cannot convert" */ - 1)
+	_ = uint64(0)
+	_ = uint64(maxUint64)
+	_ = uint64(maxUint64 /* ERROR "cannot convert" */ + 1)
+	_ = uint64(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uint = 0 /* ERROR "overflows" */ - 1
+	_ uint = 0
+	_ uint = maxUint
+	_ uint = maxUint /* ERROR "overflows" */ + 1
+	_ uint = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uint(0 /* ERROR "cannot convert" */ - 1)
+	_ = uint(0)
+	_ = uint(maxUint)
+	_ = uint(maxUint /* ERROR "cannot convert" */ + 1)
+	_ = uint(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uintptr = 0 /* ERROR "overflows" */ - 1
+	_ uintptr = 0
+	_ uintptr = maxUintptr
+	_ uintptr = maxUintptr /* ERROR "overflows" */ + 1
+	_ uintptr = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uintptr(0 /* ERROR "cannot convert" */ - 1)
+	_ = uintptr(0)
+	_ = uintptr(maxUintptr)
+	_ = uintptr(maxUintptr /* ERROR "cannot convert" */ + 1)
+	_ = uintptr(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ float32 = minInt64
+	_ float64 = minInt64
+	_ complex64 = minInt64
+	_ complex128 = minInt64
+
+	_ = float32(minInt64)
+	_ = float64(minInt64)
+	_ = complex64(minInt64)
+	_ = complex128(minInt64)
+)
+
+const (
+	_ float32 = maxUint64
+	_ float64 = maxUint64
+	_ complex64 = maxUint64
+	_ complex128 = maxUint64
+
+	_ = float32(maxUint64)
+	_ = float64(maxUint64)
+	_ = complex64(maxUint64)
+	_ = complex128(maxUint64)
+)
+
+// TODO(gri) find smaller deltas below
+
+const delta32 = maxFloat32/(1 << 23)
+
+const (
+	_ float32 = - /* ERROR "overflow" */ (maxFloat32 + delta32)
+	_ float32 = -maxFloat32
+	_ float32 = maxFloat32
+	_ float32 = maxFloat32 /* ERROR "overflow" */ + delta32
+
+	_ = float32(- /* ERROR "cannot convert" */ (maxFloat32 + delta32))
+	_ = float32(-maxFloat32)
+	_ = float32(maxFloat32)
+	_ = float32(maxFloat32 /* ERROR "cannot convert" */ + delta32)
+
+	_ = assert(float32(smallestFloat32) == smallestFloat32)
+	_ = assert(float32(smallestFloat32/2) == 0)
+	_ = assert(float32(smallestFloat64) == 0)
+	_ = assert(float32(smallestFloat64/2) == 0)
+)
+
+const delta64 = maxFloat64/(1 << 52)
+
+const (
+	_ float64 = - /* ERROR "overflow" */ (maxFloat64 + delta64)
+	_ float64 = -maxFloat64
+	_ float64 = maxFloat64
+	_ float64 = maxFloat64 /* ERROR "overflow" */ + delta64
+
+	_ = float64(- /* ERROR "cannot convert" */ (maxFloat64 + delta64))
+	_ = float64(-maxFloat64)
+	_ = float64(maxFloat64)
+	_ = float64(maxFloat64 /* ERROR "cannot convert" */ + delta64)
+
+	_ = assert(float64(smallestFloat32) == smallestFloat32)
+	_ = assert(float64(smallestFloat32/2) == smallestFloat32/2)
+	_ = assert(float64(smallestFloat64) == smallestFloat64)
+	_ = assert(float64(smallestFloat64/2) == 0)
+)
+
+const (
+	_ complex64 = - /* ERROR "overflow" */ (maxFloat32 + delta32)
+	_ complex64 = -maxFloat32
+	_ complex64 = maxFloat32
+	_ complex64 = maxFloat32 /* ERROR "overflow" */ + delta32
+
+	_ = complex64(- /* ERROR "cannot convert" */ (maxFloat32 + delta32))
+	_ = complex64(-maxFloat32)
+	_ = complex64(maxFloat32)
+	_ = complex64(maxFloat32 /* ERROR "cannot convert" */ + delta32)
+)
+
+const (
+	_ complex128 = - /* ERROR "overflow" */ (maxFloat64 + delta64)
+	_ complex128 = -maxFloat64
+	_ complex128 = maxFloat64
+	_ complex128 = maxFloat64 /* ERROR "overflow" */ + delta64
+
+	_ = complex128(- /* ERROR "cannot convert" */ (maxFloat64 + delta64))
+	_ = complex128(-maxFloat64)
+	_ = complex128(maxFloat64)
+	_ = complex128(maxFloat64 /* ERROR "cannot convert" */ + delta64)
+)
+
+// Initialization of typed constant and conversion are the same:
+const (
+	f32 = 1 + smallestFloat32
+	x32 float32 = f32
+	y32 = float32(f32)
+	_ = assert(x32 - y32 == 0)
+)
+
+const (
+	f64 = 1 + smallestFloat64
+	x64 float64 = f64
+	y64 = float64(f64)
+	_ = assert(x64 - y64 == 0)
+)
diff --git a/third_party/go.tools/go/types/testdata/constdecl.src b/third_party/go.tools/go/types/testdata/constdecl.src
new file mode 100644
index 0000000..8577cb9
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/constdecl.src
@@ -0,0 +1,94 @@
+// Copyright 2013 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 constdecl
+
+import "math"
+
+var v int
+
+// Const decls must be initialized by constants.
+const _ = v /* ERROR "not constant" */
+const _ = math /* ERROR "not constant" */ .Sin(0)
+const _ = int /* ERROR "not an expression" */
+
+func _() {
+	const _ = v /* ERROR "not constant" */
+	const _ = math /* ERROR "not constant" */ .Sin(0)
+	const _ = int /* ERROR "not an expression" */
+}
+
+// Identifier and expression arity must match.
+const _ /* ERROR "missing init expr for _" */
+const _ = 1, 2 /* ERROR "extra init expr 2" */
+
+const _ /* ERROR "missing init expr for _" */ int
+const _ int = 1, 2 /* ERROR "extra init expr 2" */
+
+const (
+	_ /* ERROR "missing init expr for _" */
+	_ = 1, 2 /* ERROR "extra init expr 2" */
+
+	_ /* ERROR "missing init expr for _" */ int
+	_ int = 1, 2 /* ERROR "extra init expr 2" */
+)
+
+const (
+	_ = 1
+	_
+	_, _ /* ERROR "missing init expr for _" */
+	_
+)
+
+const (
+	_, _ = 1, 2
+	_, _
+	_ /* ERROR "extra init expr at" */
+	_, _
+	_, _, _ /* ERROR "missing init expr for _" */
+	_, _
+)
+
+func _() {
+	const _ /* ERROR "missing init expr for _" */
+	const _ = 1, 2 /* ERROR "extra init expr 2" */
+
+	const _ /* ERROR "missing init expr for _" */ int
+	const _ int = 1, 2 /* ERROR "extra init expr 2" */
+
+	const (
+		_ /* ERROR "missing init expr for _" */
+		_ = 1, 2 /* ERROR "extra init expr 2" */
+
+		_ /* ERROR "missing init expr for _" */ int
+		_ int = 1, 2 /* ERROR "extra init expr 2" */
+	)
+
+	const (
+		_ = 1
+		_
+		_, _ /* ERROR "missing init expr for _" */
+		_
+	)
+
+	const (
+		_, _ = 1, 2
+		_, _
+		_ /* ERROR "extra init expr at" */
+		_, _
+		_, _, _ /* ERROR "missing init expr for _" */
+		_, _
+	)
+}
+
+// Test case for constant with invalid initialization.
+// Caused panic because the constant value was not set up (gri - 7/8/2014).
+func _() {
+	const (
+	    x string = missing /* ERROR "undeclared name" */
+	    y = x + ""
+	)
+}
+
+// TODO(gri) move extra tests from testdata/const0.src into here
diff --git a/third_party/go.tools/go/types/testdata/conversions.src b/third_party/go.tools/go/types/testdata/conversions.src
new file mode 100644
index 0000000..4251424
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/conversions.src
@@ -0,0 +1,88 @@
+// 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.
+
+// conversions
+
+package conversions
+
+import "unsafe"
+
+// argument count
+var (
+	_ = int() /* ERROR "missing argument" */
+	_ = int(1, 2 /* ERROR "too many arguments" */ )
+)
+
+// numeric constant conversions are in const1.src.
+
+func string_conversions() {
+	const A = string(65)
+	assert(A == "A")
+	const E = string(-1)
+	assert(E == "\uFFFD")
+	assert(E == string(1234567890))
+
+	type myint int
+	assert(A == string(myint(65)))
+
+	type mystring string
+	const _ mystring = mystring("foo")
+
+	const _ = string(true /* ERROR "cannot convert" */ )
+	const _ = string(1.2 /* ERROR "cannot convert" */ )
+	const _ = string(nil /* ERROR "cannot convert" */ )
+}
+
+func interface_conversions() {
+	type E interface{}
+
+	type I1 interface{
+		m1()
+	}
+
+	type I2 interface{
+		m1()
+		m2(x int)
+	}
+
+	type I3 interface{
+		m1()
+		m2() int
+	}
+
+	var e E
+	var i1 I1
+	var i2 I2
+	var i3 I3
+
+	_ = E(0)
+	_ = E(nil)
+	_ = E(e)
+	_ = E(i1)
+	_ = E(i2)
+
+	_ = I1(0 /* ERROR "cannot convert" */ )
+	_ = I1(nil)
+	_ = I1(i1)
+	_ = I1(e /* ERROR "cannot convert" */ )
+	_ = I1(i2)
+
+	_ = I2(nil)
+	_ = I2(i1 /* ERROR "cannot convert" */ )
+	_ = I2(i2)
+	_ = I2(i3 /* ERROR "cannot convert" */ )
+
+	_ = I3(nil)
+	_ = I3(i1 /* ERROR "cannot convert" */ )
+	_ = I3(i2 /* ERROR "cannot convert" */ )
+	_ = I3(i3)
+
+	// TODO(gri) add more tests, improve error message
+}
+
+func issue6326() {
+	type T unsafe.Pointer
+	var x T
+	_ = uintptr(x) // see issue 6326
+}
diff --git a/third_party/go.tools/go/types/testdata/cycles.src b/third_party/go.tools/go/types/testdata/cycles.src
new file mode 100644
index 0000000..621d83c
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/cycles.src
@@ -0,0 +1,143 @@
+// Copyright 2013 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 cycles
+
+type (
+	T0 int
+	T1 /* ERROR cycle */ T1
+	T2 *T2
+
+	T3 /* ERROR cycle */ T4
+	T4 T5
+	T5 T3
+
+	T6 T7
+	T7 *T8
+	T8 T6
+
+	// arrays
+	A0 /* ERROR cycle */ [10]A0
+	A1 [10]*A1
+
+	A2 /* ERROR cycle */ [10]A3
+	A3 [10]A4
+	A4 A2
+
+	A5 [10]A6
+	A6 *A5
+
+	// slices
+	L0 []L0
+
+	// structs
+	S0 /* ERROR cycle */ struct{ _ S0 }
+	S1 /* ERROR cycle */ struct{ S1 }
+	S2 struct{ _ *S2 }
+	S3 struct{ *S3 }
+
+	S4 /* ERROR cycle */ struct{ S5 }
+	S5 struct{ S6 }
+	S6 S4
+
+	// pointers
+	P0 *P0
+
+	// functions
+	F0 func(F0)
+	F1 func() F1
+	F2 func(F2) F2
+
+	// interfaces
+	I0 /* ERROR cycle */ interface{ I0 }
+
+	I1 interface{ I2 }
+	I2 interface{ I3 }
+	I3 /* ERROR cycle */ interface{ I1 }
+
+	I4 interface{ f(I4) }
+
+	// testcase for issue 5090
+	I5 interface{ f(I6) }
+	I6 interface{ I5 }
+
+	// maps
+	M0 map[M0 /* ERROR invalid map key */ ]M0
+
+	// channels
+	C0 chan C0
+)
+
+func _() {
+	type (
+		t1 /* ERROR cycle */ t1
+		t2 *t2
+
+		t3 t4 /* ERROR undeclared */
+		t4 t5 /* ERROR undeclared */
+		t5 t3
+
+		// arrays
+		a0 /* ERROR cycle */ [10]a0
+		a1 [10]*a1
+
+		// slices
+		l0 []l0
+
+		// structs
+		s0 /* ERROR cycle */ struct{ _ s0 }
+		s1 /* ERROR cycle */ struct{ s1 }
+		s2 struct{ _ *s2 }
+		s3 struct{ *s3 }
+
+		// pointers
+		p0 *p0
+
+		// functions
+		f0 func(f0)
+		f1 func() f1
+		f2 func(f2) f2
+
+		// interfaces
+		i0 /* ERROR cycle */ interface{ i0 }
+
+		// maps
+		m0 map[m0 /* ERROR invalid map key */ ]m0
+
+		// channels
+		c0 chan c0
+	)
+}
+
+// test cases for issue 6667
+
+type A [10]map[A /* ERROR invalid map key */ ]bool
+
+type S struct {
+	m map[S /* ERROR invalid map key */ ]bool
+}
+
+// test cases for issue 7236
+// (cycle detection must not be dependent on starting point of resolution)
+
+type (
+	P1 *T9
+	T9 /* ERROR cycle */ T9
+
+	T10 /* ERROR cycle */ T10
+	P2 *T10
+)
+
+func (T11) m() {}
+
+type T11 /* ERROR cycle */ struct{ T11 }
+
+type T12 /* ERROR cycle */ struct{ T12 }
+
+func (*T12) m() {}
+
+type (
+	P3 *T13
+	T13 /* ERROR cycle */ T13
+)
\ No newline at end of file
diff --git a/third_party/go.tools/go/types/testdata/cycles1.src b/third_party/go.tools/go/types/testdata/cycles1.src
new file mode 100644
index 0000000..ae2b38e
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/cycles1.src
@@ -0,0 +1,77 @@
+// Copyright 2013 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 p
+
+type (
+	A interface {
+		a() interface {
+			ABC1
+		}
+	}
+	B interface {
+		b() interface {
+			ABC2
+		}
+	}
+	C interface {
+		c() interface {
+			ABC3
+		}
+	}
+
+	AB interface {
+		A
+		B
+	}
+	BC interface {
+		B
+		C
+	}
+
+	ABC1 interface {
+		A
+		B
+		C
+	}
+	ABC2 interface {
+		AB
+		C
+	}
+	ABC3 interface {
+		A
+		BC
+	}
+)
+
+var (
+	x1 ABC1
+	x2 ABC2
+	x3 ABC3
+)
+
+func _() {
+	// all types have the same method set
+	x1 = x2
+	x2 = x1
+
+	x1 = x3
+	x3 = x1
+
+	x2 = x3
+	x3 = x2
+
+	// all methods return the same type again
+	x1 = x1.a()
+	x1 = x1.b()
+	x1 = x1.c()
+
+	x2 = x2.a()
+	x2 = x2.b()
+	x2 = x2.c()
+
+	x3 = x3.a()
+	x3 = x3.b()
+	x3 = x3.c()
+}
diff --git a/third_party/go.tools/go/types/testdata/cycles2.src b/third_party/go.tools/go/types/testdata/cycles2.src
new file mode 100644
index 0000000..345ab56
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/cycles2.src
@@ -0,0 +1,118 @@
+// Copyright 2013 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 p
+
+import "unsafe"
+
+// Test case for issue 5090
+
+type t interface {
+	f(u)
+}
+
+type u interface {
+	t
+}
+
+func _() {
+	var t t
+	var u u
+
+	t.f(t)
+	t.f(u)
+	
+	u.f(t)
+	u.f(u)
+}
+
+
+// Test case for issue 6589.
+
+type A interface {
+	a() interface {
+		AB
+	}
+}
+
+type B interface {
+	a() interface {
+		AB
+	}
+}
+
+type AB interface {
+	a() interface {
+		A
+		B /* ERROR a redeclared */
+	}
+	b() interface {
+		A
+		B /* ERROR a redeclared */
+	}
+}
+
+var x AB
+var y interface {
+	A
+	B /* ERROR a redeclared */
+}
+var _ = x /* ERROR cannot compare */ == y
+
+
+// Test case for issue 6638.
+
+type T interface {
+	m() [T /* ERROR no value */ (nil).m()[0]]int
+}
+
+// Variations of this test case.
+
+type T1 interface {
+	m() [x1 /* ERROR no value */ .m()[0]]int
+}
+
+var x1 T1
+
+type T2 interface {
+	m() [len(x2 /* ERROR no value */ .m())]int
+}
+
+var x2 T2
+
+type T3 interface {
+	m() [unsafe.Sizeof(x3.m)]int
+}
+
+var x3 T3
+
+// The test case below should also report an error for
+// the cast inside the T4 interface (like it does for the
+// variable initialization). The reason why it does not is
+// that inside T4, the method x4.m depends on T4 which is not
+// fully set up yet. The x4.m method happens to have an empty
+// signature which is why the cast is permitted.
+// TODO(gri) Consider marking methods as incomplete and provide
+// a better error message in that case.
+
+type T4 interface {
+	m() [unsafe.Sizeof(cast4(x4.m))]int
+}
+
+var x4 T4
+var _ = cast4(x4 /* ERROR cannot convert */.m)
+
+type cast4 func()
+
+// This test is symmetric to the T4 case: Here the cast is
+// "correct", but it doesn't work inside the T5 interface.
+
+type T5 interface {
+	m() [unsafe.Sizeof(cast5(x5 /* ERROR cannot convert */ .m))]int
+}
+
+var x5 T5
+var _ = cast5(x5.m)
+
+type cast5 func() [0]int
diff --git a/third_party/go.tools/go/types/testdata/cycles3.src b/third_party/go.tools/go/types/testdata/cycles3.src
new file mode 100644
index 0000000..3da4fb5
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/cycles3.src
@@ -0,0 +1,60 @@
+// Copyright 2013 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 p
+
+import "unsafe"
+
+var (
+	_ A = A(nil).a().b().c().d().e().f()
+	_ A = A(nil).b().c().d().e().f()
+	_ A = A(nil).c().d().e().f()
+	_ A = A(nil).d().e().f()
+	_ A = A(nil).e().f()
+	_ A = A(nil).f()
+	_ A = A(nil)
+)
+
+type (
+	A interface {
+		a() B
+		B
+	}
+
+	B interface {
+		b() C
+		C
+	}
+
+	C interface {
+		c() D
+		D
+	}
+
+	D interface {
+		d() E
+		E
+	}
+
+	E interface {
+		e() F
+		F
+	}
+
+	F interface {
+		f() A
+	}
+)
+
+type (
+	U interface {
+		V
+	}
+
+	V interface {
+		v() [unsafe.Sizeof(u)]int
+	}
+)
+
+var u U
diff --git a/third_party/go.tools/go/types/testdata/cycles4.src b/third_party/go.tools/go/types/testdata/cycles4.src
new file mode 100644
index 0000000..445babc
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/cycles4.src
@@ -0,0 +1,110 @@
+// Copyright 2013 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 p
+
+// Check that all methods of T are collected before
+// determining the result type of m (which embeds
+// all methods of T).
+
+type T interface {
+	m() interface {T}
+	E
+}
+
+var _ = T.m(nil).m().e()
+
+type E interface {
+	e() int
+}
+
+// Check that unresolved forward chains are followed
+// (see also comment in resolver.go, checker.typeDecl).
+
+var _ = C.m(nil).m().e()
+
+type A B
+
+type B interface {
+	m() interface{C}
+	E
+}
+
+type C A
+
+// Check that interface type comparison for identity
+// does not recur endlessly.
+
+type T1 interface {
+	m() interface{T1}
+}
+
+type T2 interface {
+	m() interface{T2}
+}
+
+func _(x T1, y T2) {
+	// Checking for assignability of interfaces must check
+	// if all methods of x are present in y, and that they
+	// have identical signatures. The signatures recur via
+	// the result type, which is an interface that embeds
+	// a single method m that refers to the very interface
+	// that contains it. This requires cycle detection in
+	// identity checks for interface types.
+	x = y
+}
+
+type T3 interface {
+	m() interface{T4}
+}
+
+type T4 interface {
+	m() interface{T3}
+}
+
+func _(x T1, y T3) {
+	x = y
+}
+
+// Check that interfaces are type-checked in order of
+// (embedded interface) dependencies (was issue 7158).
+
+var x1 T5 = T7(nil)
+
+type T5 interface {
+	T6
+}
+
+type T6 interface {
+	m() T7
+}
+type T7 interface {
+	T5
+}
+
+// Actual test case from issue 7158.
+
+func wrapNode() Node {
+	return wrapElement()
+}
+
+func wrapElement() Element {
+	return nil
+}
+
+type EventTarget interface {
+	AddEventListener(Event)
+}
+
+type Node interface {
+	EventTarget
+}
+
+type Element interface {
+	Node
+}
+
+type Event interface {
+	Target() Element
+}
diff --git a/third_party/go.tools/go/types/testdata/decls0.src b/third_party/go.tools/go/types/testdata/decls0.src
new file mode 100644
index 0000000..f1df3ea
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/decls0.src
@@ -0,0 +1,206 @@
+// 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.
+
+// type declarations
+
+package decls0
+
+import "unsafe"
+
+const pi = 3.1415
+
+type (
+	N undeclared /* ERROR "undeclared" */
+	B bool
+	I int32
+	A [10]P
+	T struct {
+		x, y P
+	}
+	P *T
+	R (*R)
+	F func(A) I
+	Y interface {
+		f(A) I
+	}
+	S [](((P)))
+	M map[I]F
+	C chan<- I
+
+	// blank types must be typechecked
+	_ pi /* ERROR "not a type" */
+	_ struct{}
+	_ struct{ pi /* ERROR "not a type" */ }
+)
+
+
+// declarations of init
+const _, init /* ERROR "cannot declare init" */ , _ = 0, 1, 2
+type init /* ERROR "cannot declare init" */ struct{}
+var _, init /* ERROR "cannot declare init" */ int
+
+func init() {}
+func init /* ERROR "missing function body" */ ()
+
+func _() { const init = 0 }
+func _() { type init int }
+func _() { var init int; _ = init }
+
+// invalid array types
+type (
+	iA0 [... /* ERROR "invalid use of '...'" */ ]byte
+	iA1 [1 /* ERROR "invalid array length" */ <<100]int
+	iA2 [- /* ERROR "invalid array length" */ 1]complex128
+	iA3 ["foo" /* ERROR "must be integer" */ ]string
+)
+
+
+type (
+	p1 pi /* ERROR "no field or method foo" */ .foo
+	p2 unsafe.Pointer
+)
+
+
+type (
+	Pi pi /* ERROR "not a type" */
+
+	a /* ERROR "illegal cycle" */ a
+	a /* ERROR "redeclared" */ int
+
+	// where the cycle error appears depends on the
+	// order in which declarations are processed
+	// (which depends on the order in which a map
+	// is iterated through)
+	b /* ERROR "illegal cycle" */ c
+	c d
+	d e
+	e b
+
+	t *t
+
+	U V
+	V *W
+	W U
+
+	P1 *S2
+	P2 P1
+
+	S0 struct {
+	}
+	S1 struct {
+		a, b, c int
+		u, v, a /* ERROR "redeclared" */ float32
+	}
+	S2 struct {
+		S0 // anonymous field
+		S0 /* ERROR "redeclared" */ int
+	}
+	S3 struct {
+		x S2
+	}
+	S4/* ERROR "illegal cycle" */ struct {
+		S4
+	}
+	S5 /* ERROR "illegal cycle" */ struct {
+		S6
+	}
+	S6 struct {
+		field S7
+	}
+	S7 struct {
+		S5
+	}
+
+	L1 []L1
+	L2 []int
+
+	A1 [10.0]int
+	A2 /* ERROR "illegal cycle" */ [10]A2
+	A3 /* ERROR "illegal cycle" */ [10]struct {
+		x A4
+	}
+	A4 [10]A3
+
+	F1 func()
+	F2 func(x, y, z float32)
+	F3 func(x, y, x /* ERROR "redeclared" */ float32)
+	F4 func() (x, y, x /* ERROR "redeclared" */ float32)
+	F5 func(x int) (x /* ERROR "redeclared" */ float32)
+	F6 func(x ...int)
+
+	I1 interface{}
+	I2 interface {
+		m1()
+	}
+	I3 interface {
+		m1()
+		m1 /* ERROR "redeclared" */ ()
+	}
+	I4 interface {
+		m1(x, y, x /* ERROR "redeclared" */ float32)
+		m2() (x, y, x /* ERROR "redeclared" */ float32)
+		m3(x int) (x /* ERROR "redeclared" */ float32)
+	}
+	I5 interface {
+		m1(I5)
+	}
+	I6 interface {
+		S0 /* ERROR "not an interface" */
+	}
+	I7 interface {
+		I1
+		I1
+	}
+	I8 /* ERROR "illegal cycle" */ interface {
+		I8
+	}
+	I9 interface {
+		I10
+	}
+	I10 interface {
+		I11
+	}
+	I11 /* ERROR "illegal cycle" */ interface {
+		I9
+	}
+
+	C1 chan int
+	C2 <-chan int
+	C3 chan<- C3
+	C4 chan C5
+	C5 chan C6
+	C6 chan C4
+
+	M1 map[Last]string
+	M2 map[string]M2
+
+	Last int
+)
+
+// cycles in function/method declarations
+// (test cases for issue 5217 and variants)
+func f1(x f1 /* ERROR "not a type" */ ) {}
+func f2(x *f2 /* ERROR "not a type" */ ) {}
+func f3() (x f3 /* ERROR "not a type" */ ) { return }
+func f4() (x *f4 /* ERROR "not a type" */ ) { return }
+
+func (S0) m1(x S0 /* ERROR "field or method" */ .m1) {}
+func (S0) m2(x *S0 /* ERROR "field or method" */ .m2) {}
+func (S0) m3() (x S0 /* ERROR "field or method" */ .m3) { return }
+func (S0) m4() (x *S0 /* ERROR "field or method" */ .m4) { return }
+
+// interfaces may not have any blank methods
+type BlankI interface {
+	_ /* ERROR "invalid method name" */ ()
+	_ /* ERROR "invalid method name" */ (float32) int
+	m()
+}
+
+// non-interface types may have multiple blank methods
+type BlankT struct{}
+
+func (BlankT) _() {}
+func (BlankT) _(int) {}
+func (BlankT) _() int { return 0 }
+func (BlankT) _(int) int { return 0}
diff --git a/third_party/go.tools/go/types/testdata/decls1.src b/third_party/go.tools/go/types/testdata/decls1.src
new file mode 100644
index 0000000..7855e46
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/decls1.src
@@ -0,0 +1,144 @@
+// 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.
+
+// variable declarations
+
+package decls1
+
+import (
+	"math"
+)
+
+// Global variables without initialization
+var (
+	a, b bool
+	c byte
+	d uint8
+	r rune
+	i int
+	j, k, l int
+	x, y float32
+	xx, yy float64
+	u, v complex64
+	uu, vv complex128
+	s, t string
+	array []byte
+	iface interface{}
+	
+	blank _ /* ERROR "cannot use _" */
+)
+
+// Global variables with initialization
+var (
+	s1 = i + j
+	s2 = i /* ERROR "mismatched types" */ + x
+	s3 = c + d
+	s4 = s + t
+	s5 = s /* ERROR "invalid operation" */ / t
+	s6 = array[t1]
+	s7 = array[x /* ERROR "integer" */]
+	s8 = &a
+	s10 = &42 /* ERROR "cannot take address" */
+	s11 = &v
+	s12 = -(u + *t11) / *&v
+	s13 = a /* ERROR "shifted operand" */ << d
+	s14 = i << j /* ERROR "must be unsigned" */ 
+	s18 = math.Pi * 10.0
+	s19 = s1 /* ERROR "cannot call" */ ()
+ 	s20 = f0 /* ERROR "no value" */ ()
+	s21 = f6(1, s1, i)
+	s22 = f6(1, s1, uu /* ERROR "cannot pass argument" */ )
+	
+	t1 int = i + j
+	t2 int = i /* ERROR "mismatched types" */ + x
+	t3 int = c /* ERROR "cannot initialize" */ + d
+	t4 string = s + t
+	t5 string = s /* ERROR "invalid operation" */ / t
+	t6 byte = array[t1]
+	t7 byte = array[x /* ERROR "must be integer" */]
+	t8 *int = & /* ERROR "cannot initialize" */ a
+	t10 *int = &42 /* ERROR "cannot take address" */
+	t11 *complex64 = &v
+	t12 complex64 = -(u + *t11) / *&v
+	t13 int = a /* ERROR "shifted operand" */ << d
+	t14 int = i << j /* ERROR "must be unsigned" */ 
+	t15 math /* ERROR "not in selector" */
+	t16 math /* ERROR "not declared" */ .xxx
+	t17 math /* ERROR "not a type" */ .Pi
+	t18 float64 = math.Pi * 10.0
+	t19 int = t1 /* ERROR "cannot call" */ ()
+	t20 int = f0 /* ERROR "no value" */ ()
+	t21 int = a /* ERROR "cannot initialize" */
+)
+
+// Various more complex expressions
+var (
+	u1 = x /* ERROR "not an interface" */ .(int)
+	u2 = iface.([]int)
+	u3 = iface.(a /* ERROR "not a type" */ )
+	u4, ok = iface.(int)
+	u5, ok2, ok3 = iface /* ERROR "assignment count mismatch" */ .(int)
+)
+
+// Constant expression initializations
+var (
+	v1 = 1 /* ERROR "cannot convert" */ + "foo"
+	v2 = c + 255
+	v3 = c + 256 /* ERROR "overflows" */
+	v4 = r + 2147483647
+	v5 = r + 2147483648 /* ERROR "overflows" */
+	v6 = 42
+	v7 = v6 + 9223372036854775807
+	v8 = v6 + 9223372036854775808 /* ERROR "overflows" */
+	v9 = i + 1 << 10
+	v10 byte = 1024 /* ERROR "overflows" */
+	v11 = xx/yy*yy - xx
+	v12 = true && false
+	v13 = nil /* ERROR "use of untyped nil" */
+)
+
+// Multiple assignment expressions
+var (
+	m1a, m1b = 1, 2
+	m2a, m2b, m2c /* ERROR "missing init expr for m2c" */ = 1, 2
+	m3a, m3b = 1, 2, 3 /* ERROR "extra init expr 3" */
+)
+
+func _() {
+	var (
+		m1a, m1b = 1, 2
+		m2a, m2b, m2c /* ERROR "missing init expr for m2c" */ = 1, 2
+		m3a, m3b = 1, 2, 3 /* ERROR "extra init expr 3" */
+	)
+
+	_, _ = m1a, m1b
+	_, _, _ = m2a, m2b, m2c
+	_, _ = m3a, m3b
+}
+
+// Declaration of parameters and results
+func f0() {}
+func f1(a /* ERROR "not a type" */) {}
+func f2(a, b, c d /* ERROR "not a type" */) {}
+
+func f3() int { return 0 }
+func f4() a /* ERROR "not a type" */ { return 0 }
+func f5() (a, b, c d /* ERROR "not a type" */) { return }
+
+func f6(a, b, c int) complex128 { return 0 }
+
+// Declaration of receivers
+type T struct{}
+
+func (T) m0() {}
+func (*T) m1() {}
+func (x T) m2() {}
+func (x *T) m3() {}
+
+// Initialization functions
+func init() {}
+func /* ERROR "no arguments and no return values" */ init(int) {}
+func /* ERROR "no arguments and no return values" */ init() int { return 0 }
+func /* ERROR "no arguments and no return values" */ init(int) int { return 0 }
+func (T) init(int) int { return 0 }
diff --git a/third_party/go.tools/go/types/testdata/decls2a.src b/third_party/go.tools/go/types/testdata/decls2a.src
new file mode 100644
index 0000000..bdbecd9
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/decls2a.src
@@ -0,0 +1,111 @@
+// 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.
+
+// method declarations
+
+package decls2
+
+import "time"
+import "unsafe"
+
+// T1 declared before its methods.
+type T1 struct{
+	f int
+}
+
+func (T1) m() {}
+func (T1) m /* ERROR "already declared" */ () {}
+func (x *T1) f /* ERROR "field and method" */ () {}
+
+// Conflict between embedded field and method name,
+// with the embedded field being a basic type.
+type T1b struct {
+	int
+}
+
+func (T1b) int /* ERROR "field and method" */ () {}
+
+type T1c struct {
+	time.Time
+}
+
+func (T1c) Time /* ERROR "field and method" */ () int { return 0 }
+
+// Disabled for now: LookupFieldOrMethod will find Pointer even though
+// it's double-declared (it would cost extra in the common case to verify
+// this). But the MethodSet computation will not find it due to the name
+// collision caused by the double-declaration, leading to an internal
+// inconsistency while we are verifying one computation against the other.
+// var _ = T1c{}.Pointer
+
+// T2's method declared before the type.
+func (*T2) f /* ERROR "field and method" */ () {}
+
+type T2 struct {
+	f int
+}
+
+// Methods declared without a declared type.
+func (undeclared /* ERROR "undeclared" */) m() {}
+func (x *undeclared /* ERROR "undeclared" */) m() {}
+
+func (pi /* ERROR "not a type" */) m1() {}
+func (x pi /* ERROR "not a type" */) m2() {}
+func (x *pi /* ERROR "not a type" */ ) m3() {}
+
+// Blank types.
+type _ struct { m int }
+type _ struct { m int }
+
+func (_ /* ERROR "cannot use _" */) m() {}
+func m(_ /* ERROR "cannot use _" */) {}
+
+// Methods with receiver base type declared in another file.
+func (T3) m1() {}
+func (*T3) m2() {}
+func (x T3) m3() {}
+func (x *T3) f /* ERROR "field and method" */ () {}
+
+// Methods of non-struct type.
+type T4 func()
+
+func (self T4) m() func() { return self }
+
+// Methods associated with an interface.
+type T5 interface {
+	m() int
+}
+
+func (T5 /* ERROR "invalid receiver" */ ) m1() {}
+func (T5 /* ERROR "invalid receiver" */ ) m2() {}
+
+// Methods associated with a named pointer type.
+type ptr *int
+func (ptr /* ERROR "invalid receiver" */ ) _() {}
+func (* /* ERROR "invalid receiver" */ ptr) _() {}
+
+// Methods with zero or multiple receivers.
+func ( /* ERROR "missing receiver" */ ) _() {}
+func (T3, * /* ERROR "exactly one receiver" */ T3) _() {}
+func (T3, T3, T3 /* ERROR "exactly one receiver" */ ) _() {}
+func (a, b /* ERROR "exactly one receiver" */ T3) _() {}
+func (a, b, c /* ERROR "exactly one receiver" */ T3) _() {}
+
+// Methods associated with non-local or unnamed types.
+func (int /* ERROR "invalid receiver" */ ) m() {}
+func ([ /* ERROR "invalid receiver" */ ]int) m() {}
+func (time /* ERROR "invalid receiver" */ .Time) m() {}
+func (* /* ERROR "invalid receiver" */ time.Time) m() {}
+func (x /* ERROR "invalid receiver" */ interface{}) m() {}
+
+// Unsafe.Pointer is treated like a pointer when used as receiver type.
+type UP unsafe.Pointer
+func (UP /* ERROR "invalid" */ ) m1() {}
+func (* /* ERROR "invalid" */ UP) m2() {}
+
+// Double declarations across package files
+const c_double = 0
+type t_double int
+var v_double int
+func f_double() {}
diff --git a/third_party/go.tools/go/types/testdata/decls2b.src b/third_party/go.tools/go/types/testdata/decls2b.src
new file mode 100644
index 0000000..e7bc394
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/decls2b.src
@@ -0,0 +1,65 @@
+// 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.
+
+// method declarations
+
+package decls2
+
+import "io"
+
+const pi = 3.1415
+
+func (T1) m /* ERROR "already declared" */ () {}
+func (T2) m(io.Writer) {}
+
+type T3 struct {
+	f *T3
+}
+
+type T6 struct {
+	x int
+}
+
+func (t *T6) m1() int {
+	return t.x
+}
+
+func f() {
+	var t *T6
+	t.m1()
+}
+
+// Double declarations across package files
+const c_double /* ERROR "redeclared" */ = 0
+type t_double  /* ERROR "redeclared" */ int
+var v_double /* ERROR "redeclared" */ int
+func f_double /* ERROR "redeclared" */ () {}
+
+// Blank methods need to be type-checked.
+// Verify by checking that errors are reported.
+func (T /* ERROR "undeclared" */ ) _() {}
+func (T1) _(undeclared /* ERROR "undeclared" */ ) {}
+func (T1) _() int { return "foo" /* ERROR "cannot convert" */ }
+
+// Methods with undeclared receiver type can still be checked.
+// Verify by checking that errors are reported.
+func (Foo /* ERROR "undeclared" */ ) m() {}
+func (Foo /* ERROR "undeclared" */ ) m(undeclared /* ERROR "undeclared" */ ) {}
+func (Foo /* ERROR "undeclared" */ ) m() int { return "foo" /* ERROR "cannot convert" */ }
+
+func (Foo /* ERROR "undeclared" */ ) _() {}
+func (Foo /* ERROR "undeclared" */ ) _(undeclared /* ERROR "undeclared" */ ) {}
+func (Foo /* ERROR "undeclared" */ ) _() int { return "foo" /* ERROR "cannot convert" */ }
+
+// Receiver declarations are regular parameter lists;
+// receiver types may use parentheses, and the list
+// may have a trailing comma.
+type T7 struct {}
+
+func (T7) m1() {}
+func ((T7)) m2() {}
+func ((*T7)) m3() {}
+func (x *(T7),) m4() {}
+func (x (*(T7)),) m5() {}
+func (x ((*((T7)))),) m6() {}
diff --git a/third_party/go.tools/go/types/testdata/decls3.src b/third_party/go.tools/go/types/testdata/decls3.src
new file mode 100644
index 0000000..80d2bc8
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/decls3.src
@@ -0,0 +1,309 @@
+// 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.
+
+// embedded types
+
+package decls3
+
+import "unsafe"
+import "fmt"
+
+// fields with the same name at the same level cancel each other out
+
+func _() {
+	type (
+		T1 struct { X int }
+		T2 struct { X int }
+		T3 struct { T1; T2 } // X is embedded twice at the same level via T1->X, T2->X
+	)
+
+	var t T3
+	_ = t /* ERROR "ambiguous selector" */ .X
+}
+
+func _() {
+	type (
+		T1 struct { X int }
+		T2 struct { T1 }
+		T3 struct { T1 }
+		T4 struct { T2; T3 } // X is embedded twice at the same level via T2->T1->X, T3->T1->X
+	)
+
+	var t T4
+	_ = t /* ERROR "ambiguous selector" */ .X
+}
+
+func issue4355() {
+	type (
+	    T1 struct {X int}
+	    T2 struct {T1}
+	    T3 struct {T2}
+	    T4 struct {T2}
+	    T5 struct {T3; T4} // X is embedded twice at the same level via T3->T2->T1->X, T4->T2->T1->X
+	)	
+
+	var t T5
+	_ = t /* ERROR "ambiguous selector" */ .X
+}
+
+func _() {
+	type State int
+	type A struct{ State }
+	type B struct{ fmt.State }
+	type T struct{ A; B }
+
+	var t T
+	_ = t /* ERROR "ambiguous selector" */ .State
+}
+
+// Embedded fields can be predeclared types.
+
+func _() {
+	type T0 struct{
+		int
+		float32
+		f int
+	}
+	var x T0
+	_ = x.int
+	_ = x.float32
+	_ = x.f
+
+	type T1 struct{
+		T0
+	}
+	var y T1
+	_ = y.int
+	_ = y.float32
+	_ = y.f
+}
+
+// Restrictions on embedded field types.
+
+func _() {
+	type I1 interface{}
+	type I2 interface{}
+	type P1 *int
+	type P2 *int
+	type UP unsafe.Pointer
+
+	type T1 struct {
+		I1
+		* /* ERROR "cannot be a pointer to an interface" */ I2
+		* /* ERROR "cannot be a pointer to an interface" */ error
+		P1 /* ERROR "cannot be a pointer" */
+		* /* ERROR "cannot be a pointer" */ P2
+	}
+
+	// unsafe.Pointers are treated like regular pointers when embedded
+	type T2 struct {
+		unsafe /* ERROR "cannot be unsafe.Pointer" */ .Pointer
+		*/* ERROR "cannot be unsafe.Pointer" */ unsafe.Pointer
+		UP /* ERROR "cannot be unsafe.Pointer" */
+		* /* ERROR "cannot be unsafe.Pointer" */ UP
+	}
+}
+
+// Named types that are pointers.
+
+type S struct{ x int }
+func (*S) m() {}
+type P *S
+
+func _() {
+	var s *S
+	_ = s.x
+	_ = s.m
+
+	var p P
+	_ = p.x
+	_ = p /* ERROR "no field or method" */ .m
+	_ = P /* ERROR "no field or method" */ .m
+}
+
+// Borrowed from the FieldByName test cases in reflect/all_test.go.
+
+type D1 struct {
+	d int
+}
+type D2 struct {
+	d int
+}
+
+type S0 struct {
+	A, B, C int
+	D1
+	D2
+}
+
+type S1 struct {
+	B int
+	S0
+}
+
+type S2 struct {
+	A int
+	*S1
+}
+
+type S1x struct {
+	S1
+}
+
+type S1y struct {
+	S1
+}
+
+type S3 struct {
+	S1x
+	S2
+	D, E int
+	*S1y
+}
+
+type S4 struct {
+	*S4
+	A int
+}
+
+// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
+type S5 struct {
+	S6
+	S7
+	S8
+}
+
+type S6 struct {
+	X int
+}
+
+type S7 S6
+
+type S8 struct {
+	S9
+}
+
+type S9 struct {
+	X int
+	Y int
+}
+
+// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
+type S10 struct {
+	S11
+	S12
+	S13
+}
+
+type S11 struct {
+	S6
+}
+
+type S12 struct {
+	S6
+}
+
+type S13 struct {
+	S8
+}
+
+func _() {
+	_ = struct /* ERROR "no field or method" */ {}{}.Foo
+	_ = S0{}.A
+	_ = S0 /* ERROR "no field or method" */ {}.D
+	_ = S1{}.A
+	_ = S1{}.B
+	_ = S1{}.S0
+	_ = S1{}.C
+	_ = S2{}.A
+	_ = S2{}.S1
+	_ = S2{}.B
+	_ = S2{}.C
+	_ = S2 /* ERROR "no field or method" */ {}.D
+	_ = S3 /* ERROR "ambiguous selector" */ {}.S1
+	_ = S3{}.A
+	_ = S3 /* ERROR "ambiguous selector" */ {}.B
+	_ = S3{}.D
+	_ = S3{}.E
+	_ = S4{}.A
+	_ = S4 /* ERROR "no field or method" */ {}.B
+	_ = S5 /* ERROR "ambiguous selector" */ {}.X
+	_ = S5{}.Y
+	_ = S10 /* ERROR "ambiguous selector" */ {}.X
+	_ = S10{}.Y
+}
+
+// Borrowed from the FieldByName benchmark in reflect/all_test.go.
+
+type R0 struct {
+	*R1
+	*R2
+	*R3
+	*R4
+}
+
+type R1 struct {
+	*R5
+	*R6
+	*R7
+	*R8
+}
+
+type R2 R1
+type R3 R1
+type R4 R1
+
+type R5 struct {
+	*R9
+	*R10
+	*R11
+	*R12
+}
+
+type R6 R5
+type R7 R5
+type R8 R5
+
+type R9 struct {
+	*R13
+	*R14
+	*R15
+	*R16
+}
+
+type R10 R9
+type R11 R9
+type R12 R9
+
+type R13 struct {
+	*R17
+	*R18
+	*R19
+	*R20
+}
+
+type R14 R13
+type R15 R13
+type R16 R13
+
+type R17 struct {
+	*R21
+	*R22
+	*R23
+	*R24
+}
+
+type R18 R17
+type R19 R17
+type R20 R17
+
+type R21 struct {
+	X int
+}
+
+type R22 R21
+type R23 R21
+type R24 R21
+
+var _ = R0 /* ERROR "ambiguous selector" */ {}.X
\ No newline at end of file
diff --git a/third_party/go.tools/go/types/testdata/errors.src b/third_party/go.tools/go/types/testdata/errors.src
new file mode 100644
index 0000000..45bd45a
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/errors.src
@@ -0,0 +1,55 @@
+// Copyright 2013 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 errors
+
+// Testing precise operand formatting in error messages
+// (matching messages are regular expressions, hence the \'s).
+func f(x int, m map[string]int) {
+	// no values
+	_ = f /* ERROR "f\(0, m\) \(no value\) used as value" */ (0, m)
+
+	// built-ins
+	_ = println /* ERROR "println \(built-in\) must be called" */
+
+	// types
+	_ = complex128 /* ERROR "complex128 \(type\) is not an expression" */
+
+	// constants
+	const c1 = 991
+	const c2 float32 = 0.5
+	0 /* ERROR "0 \(untyped int constant\) is not used" */
+	c1 /* ERROR "c1 \(untyped int constant 991\) is not used" */
+	c2 /* ERROR "c2 \(constant 1/2 of type float32\) is not used" */
+	c1 /* ERROR "c1 \+ c2 \(constant 1983/2 of type float32\) is not used" */ + c2
+
+	// variables
+	x /* ERROR "x \(variable of type int\) is not used" */
+
+	// values
+	x /* ERROR "x != x \(untyped bool value\) is not used" */ != x
+	x /* ERROR "x \+ x \(value of type int\) is not used" */ + x
+
+	// value, ok's
+	const s = "foo"
+	m /* ERROR "m\[s\] \(map index expression of type int\) is not used" */ [s]
+}
+
+// Valid ERROR comments can have a variety of forms.
+func _() {
+	0 /* ERROR "0 .* is not used" */
+	0 /* ERROR 0 .* is not used */
+	0 // ERROR "0 .* is not used"
+	0 // ERROR 0 .* is not used
+}
+
+// Don't report spurious errors as a consequence of earlier errors.
+// Add more tests as needed.
+func _() {
+	if err := foo /* ERROR undeclared */ (); err != nil /* no error here */ {}
+}
+
+// Use unqualified names for package-local objects.
+type T struct{}
+var _ int = T /* ERROR value of type T */ {} // use T in error message rather then errors.T
diff --git a/third_party/go.tools/go/types/testdata/expr0.src b/third_party/go.tools/go/types/testdata/expr0.src
new file mode 100644
index 0000000..5afb5d7
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/expr0.src
@@ -0,0 +1,168 @@
+// 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.
+
+// unary expressions
+
+package expr0 
+
+type mybool bool
+
+var (
+	// bool
+	b0 = true
+	b1 bool = b0
+	b2 = !true
+	b3 = !b1
+	b4 bool = !true
+	b5 bool = !b4
+	b6 = +b0 /* ERROR "not defined" */
+	b7 = -b0 /* ERROR "not defined" */
+	b8 = ^b0 /* ERROR "not defined" */
+	b9 = *b0 /* ERROR "cannot indirect" */
+	b10 = &true /* ERROR "cannot take address" */
+	b11 = &b0
+	b12 = <-b0 /* ERROR "cannot receive" */
+	b13 = & & /* ERROR "cannot take address" */ b0
+
+	// int
+	i0 = 1
+	i1 int = i0
+	i2 = +1
+	i3 = +i0
+	i4 int = +1
+	i5 int = +i4
+	i6 = -1
+	i7 = -i0
+	i8 int = -1
+	i9 int = -i4
+	i10 = !i0 /* ERROR "not defined" */
+	i11 = ^1
+	i12 = ^i0
+	i13 int = ^1
+	i14 int = ^i4
+	i15 = *i0 /* ERROR "cannot indirect" */
+	i16 = &i0
+	i17 = *i16
+	i18 = <-i16 /* ERROR "cannot receive" */
+
+	// uint
+	u0 = uint(1)
+	u1 uint = u0
+	u2 = +1
+	u3 = +u0
+	u4 uint = +1
+	u5 uint = +u4
+	u6 = -1
+	u7 = -u0
+	u8 uint = - /* ERROR "overflows" */ 1
+	u9 uint = -u4
+	u10 = !u0 /* ERROR "not defined" */
+	u11 = ^1
+	u12 = ^i0
+	u13 uint = ^ /* ERROR "overflows" */ 1
+	u14 uint = ^u4
+	u15 = *u0 /* ERROR "cannot indirect" */
+	u16 = &u0
+	u17 = *u16
+	u18 = <-u16 /* ERROR "cannot receive" */
+	u19 = ^uint(0)
+
+	// float64
+	f0 = float64(1)
+	f1 float64 = f0
+	f2 = +1
+	f3 = +f0
+	f4 float64 = +1
+	f5 float64 = +f4
+	f6 = -1
+	f7 = -f0
+	f8 float64 = -1
+	f9 float64 = -f4
+	f10 = !f0 /* ERROR "not defined" */
+	f11 = ^1
+	f12 = ^i0
+	f13 float64 = ^1
+	f14 float64 = ^f4 /* ERROR "not defined" */
+	f15 = *f0 /* ERROR "cannot indirect" */
+	f16 = &f0
+	f17 = *u16
+	f18 = <-u16 /* ERROR "cannot receive" */
+
+	// complex128
+	c0 = complex128(1)
+	c1 complex128 = c0
+	c2 = +1
+	c3 = +c0
+	c4 complex128 = +1
+	c5 complex128 = +c4
+	c6 = -1
+	c7 = -c0
+	c8 complex128 = -1
+	c9 complex128 = -c4
+	c10 = !c0 /* ERROR "not defined" */
+	c11 = ^1
+	c12 = ^i0
+	c13 complex128 = ^1
+	c14 complex128 = ^c4 /* ERROR "not defined" */
+	c15 = *c0 /* ERROR "cannot indirect" */
+	c16 = &c0
+	c17 = *u16
+	c18 = <-u16 /* ERROR "cannot receive" */
+
+	// string
+	s0 = "foo"
+	s1 = +"foo" /* ERROR "not defined" */
+	s2 = -s0 /* ERROR "not defined" */
+	s3 = !s0 /* ERROR "not defined" */
+	s4 = ^s0 /* ERROR "not defined" */
+	s5 = *s4
+	s6 = &s4
+	s7 = *s6
+	s8 = <-s7
+
+	// channel
+	ch chan int
+	rc <-chan float64
+	sc chan <- string
+	ch0 = +ch /* ERROR "not defined" */
+	ch1 = -ch /* ERROR "not defined" */
+	ch2 = !ch /* ERROR "not defined" */
+	ch3 = ^ch /* ERROR "not defined" */
+	ch4 = *ch /* ERROR "cannot indirect" */
+	ch5 = &ch
+	ch6 = *ch5
+	ch7 = <-ch
+	ch8 = <-rc
+	ch9 = <-sc /* ERROR "cannot receive" */
+	ch10, ok = <-ch
+	// ok is of type bool
+	ch11, myok = <-ch
+	_ mybool = myok /* ERROR "cannot initialize" */
+)
+
+// address of composite literals
+type T struct{x, y int}
+
+func f() T { return T{} }
+
+var (
+	_ = &T{1, 2}
+	_ = &[...]int{}
+	_ = &[]int{}
+	_ = &[]int{}
+	_ = &map[string]T{}
+	_ = &(T{1, 2})
+	_ = &((((T{1, 2}))))
+	_ = &f /* ERROR "cannot take address" */ ()
+)
+
+// recursive pointer types
+type P *P
+
+var (
+	p1 P = new(P)
+	p2 P = *p1
+	p3 P = &p2
+)
+
diff --git a/third_party/go.tools/go/types/testdata/expr1.src b/third_party/go.tools/go/types/testdata/expr1.src
new file mode 100644
index 0000000..8ef0aed
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/expr1.src
@@ -0,0 +1,7 @@
+// 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.
+
+// binary expressions
+
+package expr1
diff --git a/third_party/go.tools/go/types/testdata/expr2.src b/third_party/go.tools/go/types/testdata/expr2.src
new file mode 100644
index 0000000..31dc5f0
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/expr2.src
@@ -0,0 +1,247 @@
+// 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.
+
+// comparisons
+
+package expr2
+
+func _bool() {
+	const t = true == true
+	const f = true == false
+	_ = t /* ERROR "cannot compare" */ < f
+	_ = 0 /* ERROR "cannot convert" */ == t
+	var b bool
+	var x, y float32
+	b = x < y
+	_ = b
+	_ = struct{b bool}{x < y}
+}
+
+// corner cases
+var (
+	v0 = nil /* ERROR "cannot compare" */ == nil
+)
+
+func arrays() {
+	// basics
+	var a, b [10]int
+	_ = a == b
+	_ = a != b
+	_ = a /* ERROR < not defined */ < b
+	_ = a == nil /* ERROR cannot convert */
+
+	type C [10]int
+	var c C
+	_ = a == c
+
+	type D [10]int
+	var d D
+	_ = c /* ERROR mismatched types */ == d
+
+	var e [10]func() int
+	_ = e /* ERROR == not defined */ == e
+}
+
+func structs() {
+	// basics
+	var s, t struct {
+		x int
+		a [10]float32
+		_ bool
+	}
+	_ = s == t
+	_ = s != t
+	_ = s /* ERROR < not defined */ < t
+	_ = s == nil /* ERROR cannot convert */
+
+	type S struct {
+		x int
+		a [10]float32
+		_ bool
+	}
+	type T struct {
+		x int
+		a [10]float32
+		_ bool
+	}
+	var ss S
+	var tt T
+	_ = s == ss
+	_ = ss /* ERROR mismatched types */ == tt
+
+	var u struct {
+		x int
+		a [10]map[string]int
+	}
+	_ = u /* ERROR cannot compare */ == u
+}
+
+func pointers() {
+	// nil
+	_ = nil /* ERROR == not defined */ == nil
+	_ = nil /* ERROR != not defined */ != nil
+	_ = nil /* ERROR < not defined */ < nil
+	_ = nil /* ERROR <= not defined */ <= nil
+	_ = nil /* ERROR > not defined */ > nil
+	_ = nil /* ERROR >= not defined */ >= nil
+
+	// basics
+	var p, q *int
+	_ = p == q
+	_ = p != q
+
+	_ = p == nil
+	_ = p != nil
+	_ = nil == q
+	_ = nil != q
+
+	_ = p /* ERROR < not defined */ < q
+	_ = p /* ERROR <= not defined */ <= q
+	_ = p /* ERROR > not defined */ > q
+	_ = p /* ERROR >= not defined */ >= q
+
+	// various element types
+	type (
+		S1 struct{}
+		S2 struct{}
+		P1 *S1
+		P2 *S2
+	)
+	var (
+		ps1 *S1
+		ps2 *S2
+		p1 P1
+		p2 P2
+	)
+	_ = ps1 == ps1
+	_ = ps1 /* ERROR mismatched types */ == ps2
+	_ = ps2 /* ERROR mismatched types */ == ps1
+
+	_ = p1 == p1
+	_ = p1 /* ERROR mismatched types */ == p2
+
+	_ = p1 == ps1
+}
+
+func channels() {
+	// basics
+	var c, d chan int
+	_ = c == d
+	_ = c != d
+	_ = c == nil
+	_ = c /* ERROR < not defined */ < d
+
+	// various element types (named types)
+	type (
+		C1 chan int
+		C1r <-chan int
+		C1s chan<- int
+		C2 chan float32
+	)
+	var (
+		c1 C1
+		c1r C1r
+		c1s C1s
+		c1a chan int
+		c2 C2
+	)
+	_ = c1 == c1
+	_ = c1 /* ERROR mismatched types */ == c1r
+	_ = c1 /* ERROR mismatched types */ == c1s
+	_ = c1r /* ERROR mismatched types */ == c1s
+	_ = c1 == c1a
+	_ = c1a == c1
+	_ = c1 /* ERROR mismatched types */ == c2
+	_ = c1a /* ERROR mismatched types */ == c2
+
+	// various element types (unnamed types)
+	var (
+		d1 chan int
+		d1r <-chan int
+		d1s chan<- int
+		d1a chan<- int
+		d2 chan float32
+	)
+	_ = d1 == d1
+	_ = d1 == d1r
+	_ = d1 == d1s
+	_ = d1r /* ERROR mismatched types */ == d1s
+	_ = d1 == d1a
+	_ = d1a == d1
+	_ = d1 /* ERROR mismatched types */ == d2
+	_ = d1a /* ERROR mismatched types */ == d2
+}
+
+// for interfaces test
+type S1 struct{}
+type S11 struct{}
+type S2 struct{}
+func (*S1) m() int
+func (*S11) m() int
+func (*S11) n()
+func (*S2) m() float32
+
+func interfaces() {
+	// basics
+	var i, j interface{ m() int }
+	_ = i == j
+	_ = i != j
+	_ = i == nil
+	_ = i /* ERROR < not defined */ < j
+
+	// various interfaces
+	var ii interface { m() int; n() }
+	var k interface { m() float32 }
+	_ = i == ii
+	_ = i /* ERROR mismatched types */ == k
+
+	// interfaces vs values
+	var s1 S1
+	var s11 S11
+	var s2 S2
+
+	_ = i == 0 /* ERROR cannot convert */
+	_ = i /* ERROR mismatched types */ == s1
+	_ = i == &s1
+	_ = i == &s11
+
+	_ = i /* ERROR mismatched types */ == s2
+	_ = i /* ERROR mismatched types */ == &s2
+}
+
+func slices() {
+	// basics
+	var s []int
+	_ = s == nil
+	_ = s != nil
+	_ = s /* ERROR < not defined */ < nil
+
+	// slices are not otherwise comparable
+	_ = s /* ERROR == not defined */ == s
+	_ = s /* ERROR < not defined */ < s
+}
+
+func maps() {
+	// basics
+	var m map[string]int
+	_ = m == nil
+	_ = m != nil
+	_ = m /* ERROR < not defined */ < nil
+
+	// maps are not otherwise comparable
+	_ = m /* ERROR == not defined */ == m
+	_ = m /* ERROR < not defined */ < m
+}
+
+func funcs() {
+	// basics
+	var f func(int) float32
+	_ = f == nil
+	_ = f != nil
+	_ = f /* ERROR < not defined */ < nil
+
+	// funcs are not otherwise comparable
+	_ = f /* ERROR == not defined */ == f
+	_ = f /* ERROR < not defined */ < f
+}
diff --git a/third_party/go.tools/go/types/testdata/expr3.src b/third_party/go.tools/go/types/testdata/expr3.src
new file mode 100644
index 0000000..50ae7c4
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/expr3.src
@@ -0,0 +1,483 @@
+// 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 expr3
+
+func indexes() {
+	_ = 1 /* ERROR "cannot index" */ [0]
+	_ = indexes /* ERROR "cannot index" */ [0]
+	_ = ( /* ERROR "cannot slice" */ 12 + 3)[1:2]
+
+	var a [10]int
+	_ = a[true /* ERROR "cannot convert" */ ]
+	_ = a["foo" /* ERROR "cannot convert" */ ]
+	_ = a[1.1 /* ERROR "truncated" */ ]
+	_ = a[1.0]
+	_ = a[- /* ERROR "negative" */ 1]
+	_ = a[- /* ERROR "negative" */ 1 :]
+	_ = a[: - /* ERROR "negative" */ 1]
+	_ = a[: /* ERROR "2nd index required" */ : /* ERROR "3rd index required" */ ]
+	_ = a[0: /* ERROR "2nd index required" */ : /* ERROR "3rd index required" */ ]
+	_ = a[0: /* ERROR "2nd index required" */ :10]
+	_ = a[:10:10]
+
+	var a0 int
+	a0 = a[0]
+	_ = a0
+	var a1 int32
+	a1 = a /* ERROR "cannot assign" */ [1] 
+	_ = a1
+
+	_ = a[9]
+	_ = a[10 /* ERROR "index .* out of bounds" */ ]
+	_ = a[1 /* ERROR "overflows" */ <<100]
+	_ = a[10:]
+	_ = a[:10]
+	_ = a[10:10]
+	_ = a[11 /* ERROR "index .* out of bounds" */ :]
+	_ = a[: 11 /* ERROR "index .* out of bounds" */ ]
+	_ = a[: 1 /* ERROR "overflows" */ <<100]
+	_ = a[:10:10]
+	_ = a[:11 /* ERROR "index .* out of bounds" */ :10]
+	_ = a[:10:11 /* ERROR "index .* out of bounds" */ ]
+	_ = a[10:0:10] /* ERROR "invalid slice indices" */
+	_ = a[0:10:0] /* ERROR "invalid slice indices" */
+	_ = a[10:0:0] /* ERROR "invalid slice indices" */
+	_ = &a /* ERROR "cannot take address" */ [:10]
+
+	pa := &a
+	_ = pa[9]
+	_ = pa[10 /* ERROR "index .* out of bounds" */ ]
+	_ = pa[1 /* ERROR "overflows" */ <<100]
+	_ = pa[10:]
+	_ = pa[:10]
+	_ = pa[10:10]
+	_ = pa[11 /* ERROR "index .* out of bounds" */ :]
+	_ = pa[: 11 /* ERROR "index .* out of bounds" */ ]
+	_ = pa[: 1 /* ERROR "overflows" */ <<100]
+	_ = pa[:10:10]
+	_ = pa[:11 /* ERROR "index .* out of bounds" */ :10]
+	_ = pa[:10:11 /* ERROR "index .* out of bounds" */ ]
+	_ = pa[10:0:10] /* ERROR "invalid slice indices" */
+	_ = pa[0:10:0] /* ERROR "invalid slice indices" */
+	_ = pa[10:0:0] /* ERROR "invalid slice indices" */
+	_ = &pa /* ERROR "cannot take address" */ [:10]
+
+	var b [0]int
+	_ = b[0 /* ERROR "index .* out of bounds" */ ]
+	_ = b[:]
+	_ = b[0:]
+	_ = b[:0]
+	_ = b[0:0]
+	_ = b[0:0:0]
+	_ = b[1 /* ERROR "index .* out of bounds" */ :0:0]
+
+	var s []int
+	_ = s[- /* ERROR "negative" */ 1]
+	_ = s[- /* ERROR "negative" */ 1 :]
+	_ = s[: - /* ERROR "negative" */ 1]
+	_ = s[0]
+	_ = s[1:2]
+	_ = s[2:1] /* ERROR "invalid slice indices" */
+	_ = s[2:]
+	_ = s[: 1 /* ERROR "overflows" */ <<100]
+	_ = s[1 /* ERROR "overflows" */ <<100 :]
+	_ = s[1 /* ERROR "overflows" */ <<100 : 1 /* ERROR "overflows" */ <<100]
+	_ = s[: /* ERROR "2nd index required" */ :  /* ERROR "3rd index required" */ ]
+	_ = s[:10:10]
+	_ = s[10:0:10] /* ERROR "invalid slice indices" */
+	_ = s[0:10:0] /* ERROR "invalid slice indices" */
+	_ = s[10:0:0] /* ERROR "invalid slice indices" */
+	_ = &s /* ERROR "cannot take address" */ [:10]
+
+	var m map[string]int
+	_ = m[0 /* ERROR "cannot convert" */ ]
+	_ = m /* ERROR "cannot slice" */ ["foo" : "bar"]
+	_ = m["foo"]
+	// ok is of type bool
+	type mybool bool
+	var ok mybool
+	_, ok = m["bar"]
+	_ = ok
+
+
+	var t string
+	_ = t[- /* ERROR "negative" */ 1]
+	_ = t[- /* ERROR "negative" */ 1 :]
+	_ = t[: - /* ERROR "negative" */ 1]
+	_ = t /* ERROR "3-index slice of string" */ [1:2:3]
+	_ = "foo" /* ERROR "3-index slice of string" */ [1:2:3]
+	var t0 byte
+	t0 = t[0]
+	_ = t0
+	var t1 rune
+	t1 = t /* ERROR "cannot assign" */ [2]
+	_ = t1
+	_ = ("foo" + "bar")[5]
+	_ = ("foo" + "bar")[6 /* ERROR "index .* out of bounds" */ ]
+
+	const c = "foo"
+	_ = c[- /* ERROR "negative" */ 1]
+	_ = c[- /* ERROR "negative" */ 1 :]
+	_ = c[: - /* ERROR "negative" */ 1]
+	var c0 byte
+	c0 = c[0]
+	_ = c0
+	var c2 float32
+	c2 = c /* ERROR "cannot assign" */ [2]
+	_ = c[3 /* ERROR "index .* out of bounds" */ ]
+	_ = ""[0 /* ERROR "index .* out of bounds" */ ]
+	_ = c2
+
+	_ = s[1<<30] // no compile-time error here
+
+	// issue 4913
+	type mystring string
+	var ss string
+	var ms mystring
+	var i, j int
+	ss = "foo"[1:2]
+	ss = "foo"[i:j]
+	ms = "foo" /* ERROR "cannot assign" */ [1:2]
+	ms = "foo" /* ERROR "cannot assign" */ [i:j]
+	_, _ = ss, ms
+}
+
+type T struct {
+	x int
+	y func()
+}
+
+func (*T) m() {}
+
+func method_expressions() {
+	_ = T /* ERROR "no field or method" */ .a
+	_ = T /* ERROR "has no method" */ .x
+	_ = T /* ERROR "not in method set" */ .m
+	_ = (*T).m
+
+	var f func(*T) = T /* ERROR "not in method set" */ .m
+	var g func(*T) = (*T).m
+	_, _ = f, g
+
+	_ = T /* ERROR "has no method" */ .y
+	_ = ( /* ERROR "has no method" */ *T).y
+}
+
+func struct_literals() {
+	type T0 struct {
+		a, b, c int
+	}
+
+	type T1 struct {
+		T0
+		a, b int
+		u float64
+		s string
+	}
+
+	// keyed elements
+	_ = T1{}
+	_ = T1{a: 0, 1 /* ERROR "mixture of .* elements" */ }
+	_ = T1{aa /* ERROR "unknown field" */ : 0}
+	_ = T1{1 /* ERROR "invalid field name" */ : 0}
+	_ = T1{a: 0, s: "foo", u: 0, a /* ERROR "duplicate field" */: 10}
+	_ = T1{a: "foo" /* ERROR "cannot convert" */ }
+	_ = T1{c /* ERROR "unknown field" */ : 0}
+	_ = T1{T0: { /* ERROR "missing type" */ }}
+	_ = T1{T0: T0{}}
+	_ = T1{T0 /* ERROR "invalid field name" */ .a: 0}
+
+	// unkeyed elements
+	_ = T0{1, 2, 3}
+	_ = T0{1, b /* ERROR "mixture" */ : 2, 3}
+	_ = T0{1, 2} /* ERROR "too few values" */
+	_ = T0{1, 2, 3, 4  /* ERROR "too many values" */ }
+	_ = T0{1, "foo" /* ERROR "cannot convert" */, 3.4  /* ERROR "truncated" */}
+
+	// invalid type
+	type P *struct{
+		x int
+	}
+	_ = P /* ERROR "invalid composite literal type" */ {}
+}
+
+func array_literals() {
+	type A0 [0]int
+	_ = A0{}
+	_ = A0{0 /* ERROR "index .* out of bounds" */}
+	_ = A0{0 /* ERROR "index .* out of bounds" */ : 0}
+
+	type A1 [10]int
+	_ = A1{}
+	_ = A1{0, 1, 2}
+	_ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+	_ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /* ERROR "index .* out of bounds" */ }
+	_ = A1{- /* ERROR "negative" */ 1: 0}
+	_ = A1{8: 8, 9}
+	_ = A1{8: 8, 9, 10 /* ERROR "index .* out of bounds" */ }
+	_ = A1{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	_ = A1{5: 5, 6, 7, 3: 3, 4}
+	_ = A1{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
+	_ = A1{10 /* ERROR "index .* out of bounds" */ : 10, 10 /* ERROR "index .* out of bounds" */ : 10}
+	_ = A1{5: 5, 6, 7, 3: 3, 1 /* ERROR "overflows" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
+	_ = A1{5: 5, 6, 7, 4: 4, 1 /* ERROR "overflows" */ <<100: 4}
+	_ = A1{2.0}
+	_ = A1{2.1 /* ERROR "truncated" */ }
+	_ = A1{"foo" /* ERROR "cannot convert" */ }
+
+	// indices must be integer constants
+	i := 1
+	const f = 2.1
+	const s = "foo"
+	_ = A1{i /* ERROR "index i must be integer constant" */ : 0}
+	_ = A1{f /* ERROR "truncated" */ : 0}
+	_ = A1{s /* ERROR "cannot convert" */ : 0}
+
+	a0 := [...]int{}
+	assert(len(a0) == 0)
+	
+	a1 := [...]int{0, 1, 2}
+	assert(len(a1) == 3)
+	var a13 [3]int
+	var a14 [4]int
+	a13 = a1
+	a14 = a1 /* ERROR "cannot assign" */
+	_, _ = a13, a14
+	
+	a2 := [...]int{- /* ERROR "negative" */ 1: 0}
+	_ = a2
+
+	a3 := [...]int{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	assert(len(a3) == 5) // somewhat arbitrary
+
+	a4 := [...]complex128{0, 1, 2, 1<<10-2: -1i, 1i, 400: 10, 12, 14}
+	assert(len(a4) == 1024)
+
+	// from the spec
+	type Point struct { x, y float32 }
+	_ = [...]Point{Point{1.5, -3.5}, Point{0, 0}}
+	_ = [...]Point{{1.5, -3.5}, {0, 0}}
+	_ = [][]int{[]int{1, 2, 3}, []int{4, 5}}
+	_ = [][]int{{1, 2, 3}, {4, 5}}
+	_ = [...]*Point{&Point{1.5, -3.5}, &Point{0, 0}}
+	_ = [...]*Point{{1.5, -3.5}, {0, 0}}
+}
+
+func slice_literals() {
+	type S0 []int
+	_ = S0{}
+	_ = S0{0, 1, 2}
+	_ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+	_ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+	_ = S0{- /* ERROR "negative" */ 1: 0}
+	_ = S0{8: 8, 9}
+	_ = S0{8: 8, 9, 10}
+	_ = S0{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	_ = S0{5: 5, 6, 7, 3: 3, 4}
+	_ = S0{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
+	_ = S0{10: 10, 10 /* ERROR "duplicate index" */ : 10}
+	_ = S0{5: 5, 6, 7, 3: 3, 1 /* ERROR "overflows" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
+	_ = S0{5: 5, 6, 7, 4: 4, 1 /* ERROR "overflows" */ <<100: 4}
+	_ = S0{2.0}
+	_ = S0{2.1 /* ERROR "truncated" */ }
+	_ = S0{"foo" /* ERROR "cannot convert" */ }
+
+	// indices must be resolved correctly
+	const index1 = 1
+	_ = S0{index1: 1}
+	_ = S0{index2: 2}
+	_ = S0{index3 /* ERROR "undeclared name" */ : 3}
+
+	// indices must be integer constants
+	i := 1
+	const f = 2.1
+	const s = "foo"
+	_ = S0{i /* ERROR "index i must be integer constant" */ : 0}
+	_ = S0{f /* ERROR "truncated" */ : 0}
+	_ = S0{s /* ERROR "cannot convert" */ : 0}
+
+}
+
+const index2 int = 2
+
+type N int
+func (N) f() {}
+
+func map_literals() {
+	type M0 map[string]int
+	type M1 map[bool]int
+	type M2 map[*int]int
+
+	_ = M0{}
+	_ = M0{1 /* ERROR "missing key" */ }
+	_ = M0{1 /* ERROR "cannot convert" */ : 2}
+	_ = M0{"foo": "bar" /* ERROR "cannot convert" */ }
+	_ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 }
+
+	_ = map[interface{}]int{2: 1, 2 /* ERROR "duplicate key" */ : 1}
+	_ = map[interface{}]int{int(2): 1, int16(2): 1}
+	_ = map[interface{}]int{int16(2): 1, int16 /* ERROR "duplicate key" */ (2): 1}
+
+	type S string
+
+	_ = map[interface{}]int{"a": 1, "a" /* ERROR "duplicate key" */ : 1}
+	_ = map[interface{}]int{"a": 1, S("a"): 1}
+	_ = map[interface{}]int{S("a"): 1, S /* ERROR "duplicate key" */ ("a"): 1}
+
+	type I interface {
+		f()
+	}
+
+	_ = map[I]int{N(0): 1, N(2): 1}
+	_ = map[I]int{N(2): 1, N /* ERROR "duplicate key" */ (2): 1}
+
+	// map keys must be resolved correctly
+	key1 := "foo"
+	_ = M0{key1: 1}
+	_ = M0{key2: 2}
+	_ = M0{key3 /* ERROR "undeclared name" */ : 2}
+
+	var value int
+	_ = M1{true: 1, false: 0}
+	_ = M2{nil: 0, &value: 1}
+}
+
+var key2 string = "bar"
+
+type I interface {
+	m()
+}
+
+type I2 interface {
+	m(int)
+}
+
+type T1 struct{}
+type T2 struct{}
+
+func (T2) m(int) {}
+
+type mybool bool
+
+func type_asserts() {
+	var x int
+	_ = x /* ERROR "not an interface" */ .(int)
+
+	var e interface{}
+	var ok bool
+	x, ok = e.(int)
+	_ = ok
+
+	// ok value is of type bool
+	var myok mybool
+	_, myok = e.(int)
+	_ = myok
+
+	var t I
+	_ = t /* ERROR "use of .* outside type switch" */ .(type)
+	_ = t /* ERROR "missing method m" */ .(T)
+	_ = t.(*T)
+	_ = t /* ERROR "missing method m" */ .(T1)
+	_ = t /* ERROR "wrong type for method m" */ .(T2)
+	_ = t /* STRICT "wrong type for method m" */ .(I2) // only an error in strict mode (issue 8561)
+
+	// e doesn't statically have an m, but may have one dynamically.
+	_ = e.(I2)
+}
+
+func f0() {}
+func f1(x int) {}
+func f2(u float32, s string) {}
+func fs(s []byte) {}
+func fv(x ...int) {}
+func fi(x ... interface{}) {}
+func (T) fm(x ...int)
+
+func g0() {}
+func g1() int { return 0}
+func g2() (u float32, s string) { return }
+func gs() []byte { return nil }
+
+func _calls() {
+	var x int
+	var y float32
+	var s []int
+
+	f0()
+	_ = f0 /* ERROR "used as value" */ ()
+	f0(g0 /* ERROR "too many arguments" */ )
+
+	f1(0)
+	f1(x)
+	f1(10.0)
+	f1() /* ERROR "too few arguments" */
+	f1(x, y /* ERROR "too many arguments" */ )
+	f1(s /* ERROR "cannot pass" */ )
+	f1(x ... /* ERROR "cannot use ..." */ )
+	f1(g0 /* ERROR "used as value" */ ())
+	f1(g1())
+	// f1(g2()) // TODO(gri) missing position in error message
+
+	f2() /* ERROR "too few arguments" */
+	f2(3.14) /* ERROR "too few arguments" */
+	f2(3.14, "foo")
+	f2(x /* ERROR "cannot pass" */ , "foo")
+	f2(g0 /* ERROR "used as value" */ ())
+	f2(g1 /* ERROR "cannot pass" */ ()) /* ERROR "too few arguments" */
+	f2(g2())
+
+	fs() /* ERROR "too few arguments" */
+	fs(g0 /* ERROR "used as value" */ ())
+	fs(g1 /* ERROR "cannot pass" */ ())
+	fs(g2 /* ERROR "cannot pass" */ /* ERROR "too many arguments" */ ())
+	fs(gs())
+
+	fv()
+	fv(1, 2.0, x)
+	fv(s /* ERROR "cannot pass" */ )
+	fv(s...)
+	fv(x /* ERROR "cannot use" */ ...)
+	fv(1, s /* ERROR "can only use ... with matching parameter" */ ...)
+	fv(gs /* ERROR "cannot pass" */ ())
+	fv(gs /* ERROR "cannot pass" */ ()...)
+
+	var t T
+	t.fm()
+	t.fm(1, 2.0, x)
+	t.fm(s /* ERROR "cannot pass" */ )
+	t.fm(g1())
+	t.fm(1, s /* ERROR "can only use ... with matching parameter" */ ...)
+	t.fm(gs /* ERROR "cannot pass" */ ())
+	t.fm(gs /* ERROR "cannot pass" */ ()...)
+
+	T.fm(t, )
+	T.fm(t, 1, 2.0, x)
+	T.fm(t, s /* ERROR "cannot pass" */ )
+	T.fm(t, g1())
+	T.fm(t, 1, s /* ERROR "can only use ... with matching parameter" */ ...)
+	T.fm(t, gs /* ERROR "cannot pass" */ ())
+	T.fm(t, gs /* ERROR "cannot pass" */ ()...)
+
+	var i interface{ fm(x ...int) } = t
+	i.fm()
+	i.fm(1, 2.0, x)
+	i.fm(s /* ERROR "cannot pass" */ )
+	i.fm(g1())
+	i.fm(1, s /* ERROR "can only use ... with matching parameter" */ ...)
+	i.fm(gs /* ERROR "cannot pass" */ ())
+	i.fm(gs /* ERROR "cannot pass" */ ()...)
+
+	fi()
+	fi(1, 2.0, x, 3.14, "foo")
+	fi(g2())
+	fi(0, g2)
+	fi(0, g2 /* ERROR "2-valued expression" */ ())
+}
+
+func issue6344() {
+	type T []interface{}
+	var x T
+	fi(x...) // ... applies also to named slices
+}
diff --git a/third_party/go.tools/go/types/testdata/gotos.src b/third_party/go.tools/go/types/testdata/gotos.src
new file mode 100644
index 0000000..0c7ee44
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/gotos.src
@@ -0,0 +1,560 @@
+// 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.
+
+// This file is a modified copy of $GOROOT/test/goto.go.
+
+package gotos
+
+var (
+	i, n int
+	x    []int
+	c    chan int
+	m    map[int]int
+	s    string
+)
+
+// goto after declaration okay
+func _() {
+	x := 1
+	goto L
+L:
+	_ = x
+}
+
+// goto before declaration okay
+func _() {
+	goto L
+L:
+	x := 1
+	_ = x
+}
+
+// goto across declaration not okay
+func _() {
+	goto L /* ERROR "goto L jumps over variable declaration at line 36" */
+	x := 1
+	_ = x
+L:
+}
+
+// goto across declaration in inner scope okay
+func _() {
+	goto L
+	{
+		x := 1
+		_ = x
+	}
+L:
+}
+
+// goto across declaration after inner scope not okay
+func _() {
+	goto L /* ERROR "goto L jumps over variable declaration at line 58" */
+	{
+		x := 1
+		_ = x
+	}
+	x := 1
+	_ = x
+L:
+}
+
+// goto across declaration in reverse okay
+func _() {
+L:
+	x := 1
+	_ = x
+	goto L
+}
+
+func _() {
+L: L1:
+	x := 1
+	_ = x
+	goto L
+	goto L1
+}
+
+// error shows first offending variable
+func _() {
+	goto L /* ERROR "goto L jumps over variable declaration at line 84" */
+	x := 1
+	_ = x
+	y := 1
+	_ = y
+L:
+}
+
+// goto not okay even if code path is dead
+func _() {
+	goto L /* ERROR "goto L jumps over variable declaration" */
+	x := 1
+	_ = x
+	y := 1
+	_ = y
+	return
+L:
+}
+
+// goto into outer block okay
+func _() {
+	{
+		goto L
+	}
+L:
+}
+
+func _() {
+	{
+		goto L
+		goto L1
+	}
+L: L1:
+}
+
+// goto backward into outer block okay
+func _() {
+L:
+	{
+		goto L
+	}
+}
+
+func _() {
+L: L1:
+	{
+		goto L
+		goto L1
+	}
+}
+
+// goto into inner block not okay
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	{
+	L:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	goto L1 /* ERROR "goto L1 jumps into block" */
+	{
+	L: L1:
+	}
+}
+
+// goto backward into inner block still not okay
+func _() {
+	{
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	{
+	L: L1:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+	goto L1 /* ERROR "goto L1 jumps into block" */
+}
+
+// error shows first (outermost) offending block
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	{
+		{
+			{
+			L:
+			}
+		}
+	}
+}
+
+// error prefers block diagnostic over declaration diagnostic
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	x := 1
+	_ = x
+	{
+	L:
+	}
+}
+
+// many kinds of blocks, all invalid to jump into or among,
+// but valid to jump out of
+
+// if
+
+func _() {
+L:
+	if true {
+		goto L
+	}
+}
+
+func _() {
+L:
+	if true {
+		goto L
+	} else {
+	}
+}
+
+func _() {
+L:
+	if false {
+	} else {
+		goto L
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	if true {
+	L:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	if true {
+	L:
+	} else {
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	if true {
+	} else {
+	L:
+	}
+}
+
+func _() {
+	if false {
+	L:
+	} else {
+		goto L /* ERROR "goto L jumps into block" */
+	}
+}
+
+func _() {
+	if true {
+		goto L /* ERROR "goto L jumps into block" */
+	} else {
+	L:
+	}
+}
+
+func _() {
+	if true {
+		goto L /* ERROR "goto L jumps into block" */
+	} else if false {
+	L:
+	}
+}
+
+func _() {
+	if true {
+		goto L /* ERROR "goto L jumps into block" */
+	} else if false {
+	L:
+	} else {
+	}
+}
+
+func _() {
+	if true {
+		goto L /* ERROR "goto L jumps into block" */
+	} else if false {
+	} else {
+	L:
+	}
+}
+
+func _() {
+	if true {
+		goto L /* ERROR "goto L jumps into block" */
+	} else {
+		L:
+	}
+}
+
+func _() {
+	if true {
+		L:
+	} else {
+		goto L /* ERROR "goto L jumps into block" */
+	}
+}
+
+// for
+
+func _() {
+	for {
+		goto L
+	}
+L:
+}
+
+func _() {
+	for {
+		goto L
+	L:
+	}
+}
+
+func _() {
+	for {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for {
+		goto L
+	L1:
+	}
+L:
+	goto L1 /* ERROR "goto L1 jumps into block" */
+}
+
+func _() {
+	for i < n {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for i = 0; i < n; i++ {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for i = range x {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for i = range c {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for i = range m {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for i = range s {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+// switch
+
+func _() {
+L:
+	switch i {
+	case 0:
+		goto L
+	}
+}
+
+func _() {
+L:
+	switch i {
+	case 0:
+
+	default:
+		goto L
+	}
+}
+
+func _() {
+	switch i {
+	case 0:
+
+	default:
+	L:
+		goto L
+	}
+}
+
+func _() {
+	switch i {
+	case 0:
+
+	default:
+		goto L
+	L:
+	}
+}
+
+func _() {
+	switch i {
+	case 0:
+		goto L
+	L:
+		;
+	default:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	switch i {
+	case 0:
+	L:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	switch i {
+	case 0:
+	L:
+		;
+	default:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	switch i {
+	case 0:
+	default:
+	L:
+	}
+}
+
+func _() {
+	switch i {
+	default:
+		goto L /* ERROR "goto L jumps into block" */
+	case 0:
+	L:
+	}
+}
+
+func _() {
+	switch i {
+	case 0:
+	L:
+		;
+	default:
+		goto L /* ERROR "goto L jumps into block" */
+	}
+}
+
+// select
+// different from switch.  the statement has no implicit block around it.
+
+func _() {
+L:
+	select {
+	case <-c:
+		goto L
+	}
+}
+
+func _() {
+L:
+	select {
+	case c <- 1:
+
+	default:
+		goto L
+	}
+}
+
+func _() {
+	select {
+	case <-c:
+
+	default:
+	L:
+		goto L
+	}
+}
+
+func _() {
+	select {
+	case c <- 1:
+
+	default:
+		goto L
+	L:
+	}
+}
+
+func _() {
+	select {
+	case <-c:
+		goto L
+	L:
+		;
+	default:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	select {
+	case c <- 1:
+	L:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	select {
+	case c <- 1:
+	L:
+		;
+	default:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	select {
+	case <-c:
+	default:
+	L:
+	}
+}
+
+func _() {
+	select {
+	default:
+		goto L /* ERROR "goto L jumps into block" */
+	case <-c:
+	L:
+	}
+}
+
+func _() {
+	select {
+	case <-c:
+	L:
+		;
+	default:
+		goto L /* ERROR "goto L jumps into block" */
+	}
+}
diff --git a/third_party/go.tools/go/types/testdata/importdecl0a.src b/third_party/go.tools/go/types/testdata/importdecl0a.src
new file mode 100644
index 0000000..463dcd0
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/importdecl0a.src
@@ -0,0 +1,53 @@
+// Copyright 2013 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 importdecl0
+
+import ()
+
+import (
+	// we can have multiple blank imports (was bug)
+	_ "math"
+	_ "net/rpc"
+	init /* ERROR "cannot declare init" */ "fmt"
+	// reflect defines a type "flag" which shows up in the gc export data
+	"reflect"
+	. /* ERROR "imported but not used" */ "reflect"
+)
+
+import "math" /* ERROR "imported but not used" */
+import m /* ERROR "imported but not used as m" */ "math"
+import _ "math"
+
+import (
+	"math/big" /* ERROR "imported but not used" */
+	b /* ERROR "imported but not used" */ "math/big"
+	_ "math/big"
+)
+
+import "fmt"
+import f1 "fmt"
+import f2 "fmt"
+
+// reflect.flag must not be visible in this package
+type flag int
+type _ reflect /* ERROR "not exported" */ .flag
+
+// imported package name may conflict with local objects
+type reflect /* ERROR "reflect already declared" */ int
+
+// dot-imported exported objects may conflict with local objects
+type Value /* ERROR "Value already declared through dot-import of package reflect" */ struct{}
+
+var _ = fmt.Println // use "fmt"
+
+func _() {
+	f1.Println() // use "fmt"
+}
+
+func _() {
+	_ = func() {
+		f2.Println() // use "fmt"
+	}
+}
diff --git a/third_party/go.tools/go/types/testdata/importdecl0b.src b/third_party/go.tools/go/types/testdata/importdecl0b.src
new file mode 100644
index 0000000..6844e70
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/importdecl0b.src
@@ -0,0 +1,33 @@
+// Copyright 2013 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 importdecl0
+
+import "math"
+import m "math"
+
+import . "testing" // declares T in file scope
+import . /* ERROR "imported but not used" */ "unsafe"
+import . "fmt"     // declares Println in file scope
+
+import (
+	// TODO(gri) At the moment, 2 errors are reported because both go/parser
+	// and the type checker report it. Eventually, this test should not be
+	// done by the parser anymore.
+	"" /* ERROR invalid import path */ /* ERROR invalid import path */
+	"a!b" /* ERROR invalid import path */ /* ERROR invalid import path */
+	"abc\xffdef" /* ERROR invalid import path */ /* ERROR invalid import path */
+)
+
+// using "math" in this file doesn't affect its use in other files
+const Pi0 = math.Pi
+const Pi1 = m.Pi
+
+type _ T // use "testing"
+
+func _() func() interface{} {
+	return func() interface{} {
+		return Println // use "fmt"
+	}
+}
diff --git a/third_party/go.tools/go/types/testdata/importdecl1a.src b/third_party/go.tools/go/types/testdata/importdecl1a.src
new file mode 100644
index 0000000..8301820
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/importdecl1a.src
@@ -0,0 +1,11 @@
+// Copyright 2014 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.
+
+// Test case for issue 8969.
+
+package importdecl1
+
+import . "unsafe"
+
+var _ Pointer // use dot-imported package unsafe
diff --git a/third_party/go.tools/go/types/testdata/importdecl1b.src b/third_party/go.tools/go/types/testdata/importdecl1b.src
new file mode 100644
index 0000000..f24bb9a
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/importdecl1b.src
@@ -0,0 +1,7 @@
+// Copyright 2014 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 importdecl1
+
+import . /* ERROR "imported but not used" */ "unsafe"
diff --git a/third_party/go.tools/go/types/testdata/init0.src b/third_party/go.tools/go/types/testdata/init0.src
new file mode 100644
index 0000000..ef0349c
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/init0.src
@@ -0,0 +1,106 @@
+// Copyright 2013 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.
+
+// initialization cycles
+
+package init0
+
+// initialization cycles (we don't know the types)
+const (
+	s0 /* ERROR initialization cycle */ = s0
+
+	x0 /* ERROR initialization cycle */ = y0
+	y0 = x0
+
+	a0 = b0
+	b0 /* ERROR initialization cycle */ = c0
+	c0 = d0
+	d0 = b0
+)
+
+var (
+	s1 /* ERROR initialization cycle */ = s1
+
+	x1 /* ERROR initialization cycle */ = y1
+	y1 = x1
+
+	a1 = b1
+	b1 /* ERROR initialization cycle */ = c1
+	c1 = d1
+	d1 = b1
+)
+
+// initialization cycles (we know the types)
+const (
+	s2 /* ERROR initialization cycle */ int = s2
+
+	x2 /* ERROR initialization cycle */ int = y2
+	y2 = x2
+
+	a2 = b2
+	b2 /* ERROR initialization cycle */ int = c2
+	c2 = d2
+	d2 = b2
+)
+
+var (
+	s3 /* ERROR initialization cycle */ int = s3
+
+	x3 /* ERROR initialization cycle */ int = y3
+	y3 = x3
+
+	a3 = b3
+	b3 /* ERROR initialization cycle */ int = c3
+	c3 = d3
+	d3 = b3
+)
+
+// cycles via struct fields
+
+type S1 struct {
+	f int
+}
+const cx3 S1 /* ERROR invalid constant type */ = S1{cx3.f}
+var vx3 /* ERROR initialization cycle */ S1 = S1{vx3.f}
+
+// cycles via functions
+
+var x4 = x5
+var x5 /* ERROR initialization cycle */ = f1()
+func f1() int { return x5*10 }
+
+var x6, x7 /* ERROR initialization cycle */ = f2()
+var x8 = x7
+func f2() (int, int) { return f3() + f3(), 0 }
+func f3() int { return x8 }
+
+// cycles via closures
+
+var x9 /* ERROR initialization cycle */ = func() int { return x9 }()
+
+var x10 /* ERROR initialization cycle */ = f4()
+
+func f4() int {
+	_ = func() {
+		_ = x10
+	}
+	return 0
+}
+
+// cycles via method expressions
+
+type T1 struct{}
+
+func (T1) m() bool { _ = x11; return false }
+
+var x11 /* ERROR initialization cycle */ = T1.m(T1{})
+
+// cycles via method values
+
+type T2 struct{}
+
+func (T2) m() bool { _ = x12; return false }
+
+var t1 T2
+var x12 /* ERROR initialization cycle */ = t1.m
diff --git a/third_party/go.tools/go/types/testdata/init1.src b/third_party/go.tools/go/types/testdata/init1.src
new file mode 100644
index 0000000..39ca314
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/init1.src
@@ -0,0 +1,97 @@
+// Copyright 2013 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.
+
+// initialization cycles
+
+package init1
+
+// issue 6683 (marked as WorkingAsIntended)
+
+type T0 struct{}
+
+func (T0) m() int { return y0 }
+
+var x0 = T0{}
+
+var y0 /* ERROR initialization cycle */ = x0.m()
+
+type T1 struct{}
+
+func (T1) m() int { return y1 }
+
+var x1 interface {
+	m() int
+} = T1{}
+
+var y1 = x1.m() // no cycle reported, x1 is of interface type
+
+// issue 6703 (modified)
+
+var x2 /* ERROR initialization cycle */ = T2.m
+
+var y2 = x2
+
+type T2 struct{}
+
+func (T2) m() int {
+	_ = y2
+	return 0
+}
+
+var x3 /* ERROR initialization cycle */ = T3.m(T3{}) // <<<< added (T3{})
+
+var y3 = x3
+
+type T3 struct{}
+
+func (T3) m() int {
+	_ = y3
+	return 0
+}
+
+var x4 /* ERROR initialization cycle */ = T4{}.m // <<<< added {}
+
+var y4 = x4
+
+type T4 struct{}
+
+func (T4) m() int {
+	_ = y4
+	return 0
+}
+
+var x5 /* ERROR initialization cycle */ = T5{}.m() // <<<< added ()
+
+var y5 = x5
+
+type T5 struct{}
+
+func (T5) m() int {
+	_ = y5
+	return 0
+}
+
+// issue 4847
+// simplified test case
+
+var x6 = f6
+var y6 /* ERROR initialization cycle */ = f6
+func f6() { _ = y6 }
+
+// full test case
+
+type (
+      E int
+      S int
+)
+
+type matcher func(s *S) E
+
+func matchList(s *S) E { return matcher(matchAnyFn)(s) }
+
+var foo = matcher(matchList)
+
+var matchAny /* ERROR initialization cycle */ = matcher(matchList)
+
+func matchAnyFn(s *S) (err E) { return matchAny(s) }
\ No newline at end of file
diff --git a/third_party/go.tools/go/types/testdata/init2.src b/third_party/go.tools/go/types/testdata/init2.src
new file mode 100644
index 0000000..614db6c
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/init2.src
@@ -0,0 +1,139 @@
+// Copyright 2014 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.
+
+// initialization cycles
+
+package init2
+
+// cycles through functions
+
+func f1() int { _ = x1; return 0 }
+var x1 /* ERROR initialization cycle */ = f1
+
+func f2() int { _ = x2; return 0 }
+var x2 /* ERROR initialization cycle */ = f2()
+
+// cycles through method expressions
+
+type T3 int
+func (T3) m() int { _ = x3; return 0 }
+var x3 /* ERROR initialization cycle */ = T3.m
+
+type T4 int
+func (T4) m() int { _ = x4; return 0 }
+var x4 /* ERROR initialization cycle */ = T4.m(0)
+
+type T3p int
+func (*T3p) m() int { _ = x3p; return 0 }
+var x3p /* ERROR initialization cycle */ = (*T3p).m
+
+type T4p int
+func (*T4p) m() int { _ = x4p; return 0 }
+var x4p /* ERROR initialization cycle */ = (*T4p).m(nil)
+
+// cycles through method expressions of embedded methods
+
+type T5 struct { E5 }
+type E5 int
+func (E5) m() int { _ = x5; return 0 }
+var x5 /* ERROR initialization cycle */ = T5.m
+
+type T6 struct { E6 }
+type E6 int
+func (E6) m() int { _ = x6; return 0 }
+var x6 /* ERROR initialization cycle */ = T6.m(T6{0})
+
+type T5p struct { E5p }
+type E5p int
+func (*E5p) m() int { _ = x5p; return 0 }
+var x5p /* ERROR initialization cycle */ = (*T5p).m
+
+type T6p struct { E6p }
+type E6p int
+func (*E6p) m() int { _ = x6p; return 0 }
+var x6p /* ERROR initialization cycle */ = (*T6p).m(nil)
+
+// cycles through method values
+
+type T7 int
+func (T7) m() int { _ = x7; return 0 }
+var x7 /* ERROR initialization cycle */ = T7(0).m
+
+type T8 int
+func (T8) m() int { _ = x8; return 0 }
+var x8 /* ERROR initialization cycle */ = T8(0).m()
+
+type T7p int
+func (*T7p) m() int { _ = x7p; return 0 }
+var x7p /* ERROR initialization cycle */ = new(T7p).m
+
+type T8p int
+func (*T8p) m() int { _ = x8p; return 0 }
+var x8p /* ERROR initialization cycle */ = new(T8p).m()
+
+type T7v int
+func (T7v) m() int { _ = x7v; return 0 }
+var x7var T7v
+var x7v /* ERROR initialization cycle */ = x7var.m
+
+type T8v int
+func (T8v) m() int { _ = x8v; return 0 }
+var x8var T8v
+var x8v /* ERROR initialization cycle */ = x8var.m()
+
+type T7pv int
+func (*T7pv) m() int { _ = x7pv; return 0 }
+var x7pvar *T7pv
+var x7pv /* ERROR initialization cycle */ = x7pvar.m
+
+type T8pv int
+func (*T8pv) m() int { _ = x8pv; return 0 }
+var x8pvar *T8pv
+var x8pv /* ERROR initialization cycle */ = x8pvar.m()
+
+// cycles through method values of embedded methods
+
+type T9 struct { E9 }
+type E9 int
+func (E9) m() int { _ = x9; return 0 }
+var x9 /* ERROR initialization cycle */ = T9{0}.m
+
+type T10 struct { E10 }
+type E10 int
+func (E10) m() int { _ = x10; return 0 }
+var x10 /* ERROR initialization cycle */ = T10{0}.m()
+
+type T9p struct { E9p }
+type E9p int
+func (*E9p) m() int { _ = x9p; return 0 }
+var x9p /* ERROR initialization cycle */ = new(T9p).m
+
+type T10p struct { E10p }
+type E10p int
+func (*E10p) m() int { _ = x10p; return 0 }
+var x10p /* ERROR initialization cycle */ = new(T10p).m()
+
+type T9v struct { E9v }
+type E9v int
+func (E9v) m() int { _ = x9v; return 0 }
+var x9var T9v
+var x9v /* ERROR initialization cycle */ = x9var.m
+
+type T10v struct { E10v }
+type E10v int
+func (E10v) m() int { _ = x10v; return 0 }
+var x10var T10v
+var x10v /* ERROR initialization cycle */ = x10var.m()
+
+type T9pv struct { E9pv }
+type E9pv int
+func (*E9pv) m() int { _ = x9pv; return 0 }
+var x9pvar *T9pv
+var x9pv /* ERROR initialization cycle */ = x9pvar.m
+
+type T10pv struct { E10pv }
+type E10pv int
+func (*E10pv) m() int { _ = x10pv; return 0 }
+var x10pvar *T10pv
+var x10pv /* ERROR initialization cycle */ = x10pvar.m()
diff --git a/third_party/go.tools/go/types/testdata/issues.src b/third_party/go.tools/go/types/testdata/issues.src
new file mode 100644
index 0000000..58c450f
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/issues.src
@@ -0,0 +1,37 @@
+// Copyright 2014 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 issues
+
+import "fmt"
+
+func issue7035() {
+	type T struct{ X int }
+	_ = func() {
+		fmt.Println() // must refer to imported fmt rather than the fmt below
+	}
+	fmt := new(T)
+	_ = fmt.X
+}
+
+func issue8066() {
+	const (
+		// TODO(gri) Enable test below for releases 1.4 and higher
+		// _ = float32(340282356779733661637539395458142568447)
+		_ = float32(340282356779733661637539395458142568448 /* ERROR cannot convert */ )
+	)
+}
+
+// Check that a missing identifier doesn't lead to a spurious error cascade.
+func issue8799a() {
+	x, ok := missing /* ERROR undeclared */ ()
+	_ = !ok
+	_ = x
+}
+
+func issue8799b(x int, ok bool) {
+	x, ok = missing /* ERROR undeclared */ ()
+	_ = !ok
+	_ = x
+}
diff --git a/third_party/go.tools/go/types/testdata/labels.src b/third_party/go.tools/go/types/testdata/labels.src
new file mode 100644
index 0000000..102ffc7
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/labels.src
@@ -0,0 +1,207 @@
+// 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.
+
+// This file is a modified concatenation of the files
+// $GOROOT/test/label.go and $GOROOT/test/label1.go.
+
+package labels
+
+var x int
+
+func f0() {
+L1 /* ERROR "label L1 declared but not used" */ :
+	for {
+	}
+L2 /* ERROR "label L2 declared but not used" */ :
+	select {
+	}
+L3 /* ERROR "label L3 declared but not used" */ :
+	switch {
+	}
+L4 /* ERROR "label L4 declared but not used" */ :
+	if true {
+	}
+L5 /* ERROR "label L5 declared but not used" */ :
+	f0()
+L6:
+	f0()
+L6 /* ERROR "label L6 already declared" */ :
+	f0()
+	if x == 20 {
+		goto L6
+	}
+
+L7:
+	for {
+		break L7
+		break L8 /* ERROR "invalid break label L8" */
+	}
+
+// A label must be directly associated with a switch, select, or
+// for statement; it cannot be the label of a labeled statement.
+
+L7a /* ERROR "declared but not used" */ : L7b:
+	for {
+		break L7a /* ERROR "invalid break label L7a" */
+		continue L7a /* ERROR "invalid continue label L7a" */
+		continue L7b
+	}
+
+L8:
+	for {
+		if x == 21 {
+			continue L8
+			continue L7 /* ERROR "invalid continue label L7" */
+		}
+	}
+
+L9:
+	switch {
+	case true:
+		break L9
+	defalt /* ERROR "label defalt declared but not used" */ :
+	}
+
+L10:
+	select {
+	default:
+		break L10
+		break L9 /* ERROR "invalid break label L9" */
+	}
+
+	goto L10a
+L10a: L10b:
+	select {
+	default:
+		break L10a /* ERROR "invalid break label L10a" */
+		break L10b
+		continue L10b /* ERROR "invalid continue label L10b" */
+	}
+}
+
+func f1() {
+L1:
+	for {
+		if x == 0 {
+			break L1
+		}
+		if x == 1 {
+			continue L1
+		}
+		goto L1
+	}
+
+L2:
+	select {
+	default:
+		if x == 0 {
+			break L2
+		}
+		if x == 1 {
+			continue L2 /* ERROR "invalid continue label L2" */
+		}
+		goto L2
+	}
+
+L3:
+	switch {
+	case x > 10:
+		if x == 11 {
+			break L3
+		}
+		if x == 12 {
+			continue L3 /* ERROR "invalid continue label L3" */
+		}
+		goto L3
+	}
+
+L4:
+	if true {
+		if x == 13 {
+			break L4 /* ERROR "invalid break label L4" */
+		}
+		if x == 14 {
+			continue L4 /* ERROR "invalid continue label L4" */
+		}
+		if x == 15 {
+			goto L4
+		}
+	}
+
+L5:
+	f1()
+	if x == 16 {
+		break L5 /* ERROR "invalid break label L5" */
+	}
+	if x == 17 {
+		continue L5 /* ERROR "invalid continue label L5" */
+	}
+	if x == 18 {
+		goto L5
+	}
+
+	for {
+		if x == 19 {
+			break L1 /* ERROR "invalid break label L1" */
+		}
+		if x == 20 {
+			continue L1 /* ERROR "invalid continue label L1" */
+		}
+		if x == 21 {
+			goto L1
+		}
+	}
+}
+
+// Additional tests not in the original files.
+
+func f2() {
+L1 /* ERROR "label L1 declared but not used" */ :
+	if x == 0 {
+		for {
+			continue L1 /* ERROR "invalid continue label L1" */
+		}
+	}
+}
+
+func f3() {
+L1:
+L2:
+L3:
+	for {
+		break L1 /* ERROR "invalid break label L1" */
+		break L2 /* ERROR "invalid break label L2" */
+		break L3
+		continue L1 /* ERROR "invalid continue label L1" */
+		continue L2 /* ERROR "invalid continue label L2" */
+		continue L3
+		goto L1
+		goto L2
+		goto L3
+	}
+}
+
+// Blank labels are never declared.
+
+func f4() {
+_:
+_: // multiple blank labels are ok
+	goto _ /* ERROR "label _ not declared" */
+}
+
+func f5() {
+_:
+	for {
+		break _ /* ERROR "invalid break label _" */
+		continue _ /* ERROR "invalid continue label _" */
+	}
+}
+
+func f6() {
+_:
+	switch {
+	default:
+		break _ /* ERROR "invalid break label _" */
+	}
+}
diff --git a/third_party/go.tools/go/types/testdata/methodsets.src b/third_party/go.tools/go/types/testdata/methodsets.src
new file mode 100644
index 0000000..8921146
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/methodsets.src
@@ -0,0 +1,214 @@
+// Copyright 2013 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 methodsets
+
+type T0 struct {}
+
+func (T0) v0() {}
+func (*T0) p0() {}
+
+type T1 struct {} // like T0 with different method names
+
+func (T1) v1() {}
+func (*T1) p1() {}
+
+type T2 interface {
+	v2()
+	p2()
+}
+
+type T3 struct {
+	T0
+	*T1
+	T2
+}
+
+// Method expressions
+func _() {
+	var (
+		_ func(T0) = T0.v0
+		_ = T0 /* ERROR "not in method set" */ .p0
+
+		_ func (*T0) = (*T0).v0
+		_ func (*T0) = (*T0).p0
+
+		// T1 is like T0
+
+		_ func(T2) = T2.v2
+		_ func(T2) = T2.p2
+
+		_ func(T3) = T3.v0
+		_ func(T3) = T3 /* ERROR "not in method set" */ .p0
+		_ func(T3) = T3.v1
+		_ func(T3) = T3.p1
+		_ func(T3) = T3.v2
+		_ func(T3) = T3.p2
+
+		_ func(*T3) = (*T3).v0
+		_ func(*T3) = (*T3).p0
+		_ func(*T3) = (*T3).v1
+		_ func(*T3) = (*T3).p1
+		_ func(*T3) = (*T3).v2
+		_ func(*T3) = (*T3).p2
+	)
+}
+
+// Method values with addressable receivers
+func _() {
+	var (
+		v0 T0
+		_ func() = v0.v0
+		_ func() = v0.p0
+	)
+
+	var (
+		p0 *T0
+		_ func() = p0.v0
+		_ func() = p0.p0
+	)
+
+	// T1 is like T0
+
+	var (
+		v2 T2
+		_ func() = v2.v2
+		_ func() = v2.p2
+	)
+
+	var (
+		v4 T3
+		_ func() = v4.v0
+		_ func() = v4.p0
+		_ func() = v4.v1
+		_ func() = v4.p1
+		_ func() = v4.v2
+		_ func() = v4.p2
+	)
+
+	var (
+		p4 *T3
+		_ func() = p4.v0
+		_ func() = p4.p0
+		_ func() = p4.v1
+		_ func() = p4.p1
+		_ func() = p4.v2
+		_ func() = p4.p2
+	)
+}
+
+// Method calls with addressable receivers
+func _() {
+	var v0 T0
+	v0.v0()
+	v0.p0()
+
+	var p0 *T0
+	p0.v0()
+	p0.p0()
+
+	// T1 is like T0
+
+	var v2 T2
+	v2.v2()
+	v2.p2()
+
+	var v4 T3
+	v4.v0()
+	v4.p0()
+	v4.v1()
+	v4.p1()
+	v4.v2()
+	v4.p2()
+
+	var p4 *T3
+	p4.v0()
+	p4.p0()
+	p4.v1()
+	p4.p1()
+	p4.v2()
+	p4.p2()
+}
+
+// Method values with value receivers
+func _() {
+	var (
+		_ func() = T0{}.v0
+		_ func() = T0 /* ERROR "not in method set" */ {}.p0
+
+		_ func() = (&T0{}).v0
+		_ func() = (&T0{}).p0
+
+		// T1 is like T0
+
+		// no values for T2
+
+		_ func() = T3{}.v0
+		_ func() = T3 /* ERROR "not in method set" */ {}.p0
+		_ func() = T3{}.v1
+		_ func() = T3{}.p1
+		_ func() = T3{}.v2
+		_ func() = T3{}.p2
+
+		_ func() = (&T3{}).v0
+		_ func() = (&T3{}).p0
+		_ func() = (&T3{}).v1
+		_ func() = (&T3{}).p1
+		_ func() = (&T3{}).v2
+		_ func() = (&T3{}).p2
+	)
+}
+
+// Method calls with value receivers
+func _() {
+	T0{}.v0()
+	T0 /* ERROR "not in method set" */ {}.p0()
+
+	(&T0{}).v0()
+	(&T0{}).p0()
+
+	// T1 is like T0
+
+	// no values for T2
+
+	T3{}.v0()
+	T3 /* ERROR "not in method set" */ {}.p0()
+	T3{}.v1()
+	T3{}.p1()
+	T3{}.v2()
+	T3{}.p2()
+
+	(&T3{}).v0()
+	(&T3{}).p0()
+	(&T3{}).v1()
+	(&T3{}).p1()
+	(&T3{}).v2()
+	(&T3{}).p2()
+}
+
+// *T has no methods if T is an interface type
+func issue5918() {
+	var (
+		err error
+		_ = err.Error()
+		_ func() string = err.Error
+		_ func(error) string = error.Error
+
+		perr = &err
+		_ = perr /* ERROR "no field or method" */ .Error()
+		_ func() string = perr /* ERROR "no field or method" */ .Error
+		_ func(*error) string = ( /* ERROR "no field or method" */ *error).Error
+	)
+
+	type T *interface{ m() int }
+	var (
+		x T
+		_ = (*x).m()
+		_ = (*x).m
+
+		_ = x /* ERROR "no field or method" */ .m()
+		_ = x /* ERROR "no field or method" */ .m
+		_ = T /* ERROR "no field or method" */ .m
+	)
+}
diff --git a/third_party/go.tools/go/types/testdata/shifts.src b/third_party/go.tools/go/types/testdata/shifts.src
new file mode 100644
index 0000000..7f8ed06
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/shifts.src
@@ -0,0 +1,321 @@
+// Copyright 2013 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 shifts
+
+func shifts0() {
+	// basic constant shifts
+	const (
+		s = 10
+		_ = 0<<0
+		_ = 1<<s
+		_ = 1<<- /* ERROR "stupid shift" */ 1
+		_ = 1<<1075 /* ERROR "stupid shift" */
+		_ = 2.0<<1
+
+		_ int = 2<<s
+		_ float32 = 2<<s
+		_ complex64 = 2<<s
+
+		_ int = 2.0<<s
+		_ float32 = 2.0<<s
+		_ complex64 = 2.0<<s
+
+		_ int = 'a'<<s
+		_ float32 = 'a'<<s
+		_ complex64 = 'a'<<s
+	)
+}
+
+func shifts1() {
+	// basic non-constant shifts
+	var (
+		i int
+		u uint
+
+		_ = 1<<0
+		_ = 1<<i /* ERROR "must be unsigned" */
+		_ = 1<<u
+		_ = 1<<"foo" /* ERROR "cannot convert" */
+		_ = i<<0
+		_ = i<<- /* ERROR "must not be negative" */ 1
+		_ = 1 /* ERROR "overflows" */ <<100
+
+		_ uint = 1 << 0
+		_ uint = 1 << u
+		_ float32 = 1 /* ERROR "must be integer" */ << u
+	)
+}
+
+func shifts2() {
+	// from the spec
+	var (
+		s uint = 33
+		i = 1<<s           // 1 has type int
+		j int32 = 1<<s     // 1 has type int32; j == 0
+		k = uint64(1<<s)   // 1 has type uint64; k == 1<<33
+		m int = 1.0<<s     // 1.0 has type int
+		n = 1.0<<s != i    // 1.0 has type int; n == false if ints are 32bits in size
+		o = 1<<s == 2<<s   // 1 and 2 have type int; o == true if ints are 32bits in size
+		p = 1<<s == 1<<33  // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
+		u = 1.0 /* ERROR "must be integer" */ <<s         // illegal: 1.0 has type float64, cannot shift
+		u1 = 1.0 /* ERROR "must be integer" */ <<s != 0   // illegal: 1.0 has type float64, cannot shift
+		u2 = 1 /* ERROR "must be integer" */ <<s != 1.0   // illegal: 1 has type float64, cannot shift
+		v float32 = 1 /* ERROR "must be integer" */ <<s   // illegal: 1 has type float32, cannot shift
+		w int64 = 1.0<<33  // 1.0<<33 is a constant shift expression
+	)
+	_, _, _, _, _, _, _, _, _, _, _, _ = i, j, k, m, n, o, p, u, u1, u2, v, w
+}
+
+func shifts3(a int16, b float32) {
+	// random tests
+	var (
+		s uint = 11
+		u = 1 /* ERROR "must be integer" */ <<s + 1.0
+		v complex128 = 1 /* ERROR "must be integer" */ << s + 1.0 /* ERROR "must be integer" */ << s + 1
+	)
+	x := 1.0 /* ERROR "must be integer" */ <<s + 1
+	shifts3(1.0 << s, 1 /* ERROR "must be integer" */ >> s)
+	_, _, _ = u, v, x
+}
+
+func shifts4() {
+	// shifts in comparisons w/ untyped operands
+	var s uint
+
+	_ = 1<<s == 1
+	_ = 1 /* ERROR "integer" */ <<s == 1.
+	_ = 1. /* ERROR "integer" */ <<s == 1
+	_ = 1. /* ERROR "integer" */ <<s == 1.
+
+	_ = 1<<s + 1 == 1
+	_ = 1 /* ERROR "integer" */ <<s + 1 == 1.
+	_ = 1 /* ERROR "integer" */ <<s + 1. == 1
+	_ = 1 /* ERROR "integer" */ <<s + 1. == 1.
+	_ = 1. /* ERROR "integer" */ <<s + 1 == 1
+	_ = 1. /* ERROR "integer" */ <<s + 1 == 1.
+	_ = 1. /* ERROR "integer" */ <<s + 1. == 1
+	_ = 1. /* ERROR "integer" */ <<s + 1. == 1.
+
+	_ = 1<<s == 1<<s
+	_ = 1 /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s
+
+	_ = 1<<s + 1<<s == 1
+	_ = 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1.
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1.
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1.
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1.
+
+	_ = 1<<s + 1<<s == 1<<s + 1<<s
+	_ = 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+}
+
+func shifts5() {
+	// shifts in comparisons w/ typed operands
+	var s uint
+	var x int
+
+	_ = 1<<s == x
+	_ = 1.<<s == x
+	_ = 1.1 /* ERROR "int" */ <<s == x
+
+	_ = 1<<s + x == 1
+	_ = 1<<s + x == 1.
+	_ = 1<<s + x == 1.1 /* ERROR "int" */
+	_ = 1.<<s + x == 1
+	_ = 1.<<s + x == 1.
+	_ = 1.<<s + x == 1.1 /* ERROR "int" */
+	_ = 1.1 /* ERROR "int" */ <<s + x == 1
+	_ = 1.1 /* ERROR "int" */ <<s + x == 1.
+	_ = 1.1 /* ERROR "int" */ <<s + x == 1.1
+
+	_ = 1<<s == x<<s
+	_ = 1.<<s == x<<s
+	_ = 1.1  /* ERROR "int" */ <<s == x<<s
+}
+
+func shifts6() {
+	// shifts as operands in non-arithmetic operations and as arguments
+	var a [10]int
+	var s uint
+
+	_ = a[1<<s]
+	_ = a[1.0]
+	_ = a[1.0<<s]
+
+	_ = make([]int, 1.0)
+	_ = make([]int, 1.0<<s)
+	_ = make([]int, 1.1 /* ERROR "must be integer" */ <<s)
+
+	_ = float32(1)
+	_ = float32(1 /* ERROR "must be integer" */ <<s)
+	_ = float32(1.0)
+	_ = float32(1.0 /* ERROR "must be integer" */ <<s)
+	_ = float32(1.1 /* ERROR "must be integer" */ <<s)
+
+	var b []int
+	_ = append(b, 1<<s)
+	_ = append(b, 1.0<<s)
+	_ = append(b, 1.1 /* ERROR "must be integer" */ <<s)
+
+	_ = append(b, 1<<s)
+	_ = append(b, 1.0<<s) // should fail - see TODO in append code
+	_ = append(b, 1.1 /* ERROR "must be integer" */ <<s)
+
+	_ = complex(1.0 /* ERROR "must be integer" */ <<s, 0)
+	_ = complex(1.1 /* ERROR "must be integer" */ <<s, 0)
+	_ = complex(0, 1.0 /* ERROR "must be integer" */ <<s)
+	_ = complex(0, 1.1 /* ERROR "must be integer" */ <<s)
+
+	// TODO(gri) The delete below is not type-checked correctly yet.
+	// var m1 map[int]string
+	// delete(m1, 1<<s)
+}
+
+func shifts7() {
+	// shifts of shifts
+	var s uint
+	var x int
+	_ = x
+
+	_ = 1<<(1<<s)
+	_ = 1<<(1.<<s)
+	_ = 1. /* ERROR "integer" */ <<(1<<s)
+	_ = 1. /* ERROR "integer" */ <<(1.<<s)
+
+	x = 1<<(1<<s)
+	x = 1<<(1.<<s)
+	x = 1.<<(1<<s)
+	x = 1.<<(1.<<s)
+
+	_ = (1<<s)<<(1<<s)
+	_ = (1<<s)<<(1.<<s)
+	_ = ( /* ERROR "integer" */ 1.<<s)<<(1<<s)
+	_ = ( /* ERROR "integer" */ 1.<<s)<<(1.<<s)
+
+	x = (1<<s)<<(1<<s)
+	x = (1<<s)<<(1.<<s)
+	x = ( /* ERROR "integer" */ 1.<<s)<<(1<<s)
+	x = ( /* ERROR "integer" */ 1.<<s)<<(1.<<s)
+}
+
+func shifts8() {
+	// shift examples from shift discussion: better error messages
+	var s uint
+	_ = 1.0 /* ERROR "shifted operand 1.0 \(type float64\) must be integer" */ <<s == 1
+	_ = 1.0 /* ERROR "shifted operand 1.0 \(type float64\) must be integer" */ <<s == 1.0
+	_ = 1 /* ERROR "shifted operand 1 \(type float64\) must be integer" */ <<s == 1.0
+	_ = 1 /* ERROR "shifted operand 1 \(type float64\) must be integer" */ <<s + 1.0 == 1
+	_ = 1 /* ERROR "shifted operand 1 \(type float64\) must be integer" */ <<s + 1.1 == 1
+	_ = 1 /* ERROR "shifted operand 1 \(type float64\) must be integer" */ <<s + 1 == 1.0
+
+	// additional cases
+	_ = complex(1.0 /* ERROR "shifted operand 1.0 \(type float64\) must be integer" */ <<s, 1)
+	_ = complex(1.0, 1 /* ERROR "shifted operand 1 \(type float64\) must be integer" */ <<s)
+
+	_ = int(1.<<s)
+	_ = int(1.1 /* ERROR "shifted operand .* must be integer" */ <<s)
+	_ = float32(1 /* ERROR "shifted operand .* must be integer" */ <<s)
+	_ = float32(1. /* ERROR "shifted operand .* must be integer" */ <<s)
+	_ = float32(1.1 /* ERROR "shifted operand .* must be integer" */ <<s)
+	// TODO(gri) the error messages for these two are incorrect - disabled for now
+	// _ = complex64(1<<s)
+	// _ = complex64(1.<<s)
+	_ = complex64(1.1 /* ERROR "shifted operand .* must be integer" */ <<s)
+}
+
+func shifts9() {
+	// various originally failing snippets of code from the std library
+	// from src/compress/lzw/reader.go:90
+	{
+		var d struct {
+			bits     uint32
+			width    uint
+		}
+		_ = uint16(d.bits & (1<<d.width - 1))
+	}
+
+	// from src/debug/dwarf/buf.go:116
+	{
+		var ux uint64
+		var bits uint
+		x := int64(ux)
+		if x&(1<<(bits-1)) != 0 {}
+	}
+
+	// from src/encoding/asn1/asn1.go:160
+	{
+		var bytes []byte
+		if bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {}
+	}
+
+	// from src/math/big/rat.go:140
+	{
+		var exp int
+		var mantissa uint64
+		shift := uint64(-1022 - (exp - 1)) // [1..53)
+		_ = mantissa & (1<<shift - 1)
+	}
+
+	// from src/net/interface.go:51
+	{
+		type Flags uint
+		var f Flags
+		var i int
+		if f&(1<<uint(i)) != 0 {}
+	}
+
+	// from src/runtime/softfloat64.go:234
+	{
+		var gm uint64
+		var shift uint
+		_ = gm & (1<<shift - 1)
+	}
+
+	// from src/strconv/atof.go:326
+	{
+		var mant uint64
+		var mantbits uint
+		if mant == 2<<mantbits {}
+	}
+
+	// from src/route_bsd.go:82
+	{
+		var Addrs int32
+		const rtaRtMask = 1
+		var i uint
+		if Addrs&rtaRtMask&(1<<i) == 0 {}
+	}
+
+	// from src/text/scanner/scanner.go:540
+	{
+		var s struct { Whitespace uint64 }
+		var ch rune
+		for s.Whitespace&(1<<uint(ch)) != 0 {}
+	}
+}
+
+func issue5895() {
+	var x = 'a' << 1 // type of x must be rune
+	var _ rune = x
+}
diff --git a/third_party/go.tools/go/types/testdata/stmt0.src b/third_party/go.tools/go/types/testdata/stmt0.src
new file mode 100644
index 0000000..646c418
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/stmt0.src
@@ -0,0 +1,806 @@
+// 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.
+
+// statements
+
+package stmt0
+
+func assignments0() (int, int) {
+	var a, b, c int
+	var ch chan int
+	f0 := func() {}
+	f1 := func() int { return 1 }
+	f2 := func() (int, int) { return 1, 2 }
+	f3 := func() (int, int, int) { return 1, 2, 3 }
+
+	a, b, c = 1, 2, 3
+	a, b, c = 1 /* ERROR "assignment count mismatch" */ , 2
+	a, b, c = 1 /* ERROR "assignment count mismatch" */ , 2, 3, 4
+	_, _, _ = a, b, c
+
+	a = f0 /* ERROR "used as value" */ ()
+	a = f1()
+	a = f2 /* ERROR "assignment count mismatch" */ ()
+	a, b = f2()
+	a, b, c = f2 /* ERROR "assignment count mismatch" */ ()
+	a, b, c = f3()
+	a, b = f3 /* ERROR "assignment count mismatch" */ ()
+
+	a, b, c = <- /* ERROR "assignment count mismatch" */ ch
+
+	return /* ERROR "wrong number of return values" */
+	return /* ERROR "wrong number of return values" */ 1
+	return 1, 2
+	return /* ERROR "wrong number of return values" */ 1, 2, 3
+}
+
+func assignments1() {
+	b, i, f, c, s := false, 1, 1.0, 1i, "foo"
+	b = i /* ERROR "cannot assign" */
+	i = f /* ERROR "cannot assign" */
+	f = c /* ERROR "cannot assign" */
+	c = s /* ERROR "cannot assign" */
+	s = b /* ERROR "cannot assign" */
+
+	v0, v1, v2 := 1 /* ERROR "mismatch" */ , 2, 3, 4
+	_, _, _ = v0, v1, v2
+
+	b = true
+
+	i += 1
+	i += "foo" /* ERROR "cannot convert.*int" */
+
+	f -= 1
+	f /= 0
+	f = float32(0)/0 /* ERROR "division by zero" */
+	f -= "foo" /* ERROR "cannot convert.*float64" */
+
+	c *= 1
+	c /= 0
+
+	s += "bar"
+	s += 1 /* ERROR "cannot convert.*string" */
+
+	var u64 uint64
+	u64 += 1<<u64
+
+	undeclared /* ERROR "undeclared" */ = 991
+
+	// test cases for issue 5800
+	var (
+		_ int = nil /* ERROR "untyped nil value" */
+		_ [10]int = nil /* ERROR "untyped nil value" */
+		_ []byte = nil
+		_ struct{} = nil /* ERROR "untyped nil value" */
+		_ func() = nil
+		_ map[int]string = nil
+		_ chan int = nil
+	)
+
+	// test cases for issue 5500
+	_ = func() (int, bool) {
+		var m map[int]int
+		return /* ERROR "wrong number of return values" */ m[0]
+	}
+
+	g := func(int, bool){}
+	var m map[int]int
+	g(m[0]) /* ERROR "too few arguments" */
+
+	// assignments to _
+	_ = nil /* ERROR "use of untyped nil" */
+	_ = 1 /* ERROR overflow */ <<1000
+	(_) = 0
+}
+
+func assignments2() {
+	type mybool bool
+	var m map[string][]bool
+	var s []bool
+	var b bool
+	var d mybool
+	_ = s
+	_ = b
+	_ = d
+
+	// assignments to map index expressions are ok
+	s, b = m["foo"]
+	_, d = m["bar"]
+	m["foo"] = nil
+	m["foo"] = nil /* ERROR assignment count mismatch */ , false
+	_ = append(m["foo"])
+	_ = append(m["foo"], true)
+
+	var c chan int
+	_, b = <-c
+	_, d = <-c
+	<- /* ERROR cannot assign */ c = 0
+	<-c = 0 /* ERROR assignment count mismatch */ , false
+
+	var x interface{}
+	_, b = x.(int)
+	x /* ERROR cannot assign */ .(int) = 0
+	x.(int) = 0 /* ERROR assignment count mismatch */ , false
+
+	assignments2 /* ERROR used as value */ () = nil
+	int /* ERROR not an expression */ = 0
+}
+
+func issue6487() {
+	type S struct{x int}
+	_ = &S /* ERROR "cannot take address" */ {}.x
+	_ = &( /* ERROR "cannot take address" */ S{}.x)
+	_ = (&S{}).x
+	S /* ERROR "cannot assign" */ {}.x = 0
+	(&S{}).x = 0
+
+	type M map[string]S
+	var m M
+	m /* ERROR "cannot assign" */ ["foo"].x = 0
+	_ = &( /* ERROR "cannot take address" */ m["foo"].x)
+	_ = &m /* ERROR "cannot take address" */ ["foo"].x
+}
+
+func issue6766a() {
+	a, a /* ERROR redeclared */ := 1, 2
+	_ = a
+	a, b, b /* ERROR redeclared */ := 1, 2, 3
+	_ = b
+	c, c /* ERROR redeclared */, b := 1, 2, 3
+	_ = c
+	a, b := /* ERROR no new variables */ 1, 2
+}
+
+func shortVarDecls1() {
+	const c = 0
+	type d int
+	a, b, c /* ERROR "cannot assign" */ , d /* ERROR "cannot assign" */  := 1, "zwei", 3.0, 4
+	var _ int = a // a is of type int
+	var _ string = b // b is of type string
+}
+
+func incdecs() {
+	const c = 3.14
+	c /* ERROR "cannot assign" */ ++
+	s := "foo"
+	s /* ERROR "cannot convert" */ --
+	3.14 /* ERROR "cannot assign" */ ++
+	var (
+		x int
+		y float32
+		z complex128
+	)
+	x++
+	y--
+	z++
+}
+
+func sends() {
+	var ch chan int
+	var rch <-chan int
+	var x int
+	x /* ERROR "cannot send" */ <- x
+	rch /* ERROR "cannot send" */ <- x
+	ch <- "foo" /* ERROR "cannot convert" */
+	ch <- x
+}
+
+func selects() {
+	select {}
+	var (
+		ch chan int
+		sc chan <- bool
+	)
+	select {
+	case <-ch:
+	case (<-ch):
+	case t := <-ch:
+		_ = t
+	case t := (<-ch):
+		_ = t
+	case t, ok := <-ch:
+		_, _ = t, ok
+	case t, ok := (<-ch):
+		_, _ = t, ok
+	case <-sc /* ERROR "cannot receive from send-only channel" */ :
+	}
+	select {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+	select {
+	case a, b := <-ch:
+		_, b = a, b
+	case x /* ERROR send or receive */ :
+	case a /* ERROR send or receive */ := ch:
+	}
+}
+
+func gos() {
+	go 1 /* ERROR HERE "function must be invoked" */
+	go int /* ERROR "go requires function call, not conversion" */ (0)
+	go gos()
+	var c chan int
+	go close(c)
+	go len /* ERROR "go discards result" */ (c)
+}
+
+func defers() {
+	defer 1 /* ERROR HERE "function must be invoked" */
+	defer int /* ERROR "defer requires function call, not conversion" */ (0)
+	defer defers()
+	var c chan int
+	defer close(c)
+	defer len /* ERROR "defer discards result" */ (c)
+}
+
+func breaks() {
+	var x, y int
+
+	break /* ERROR "break" */
+	{
+		break /* ERROR "break" */
+	}
+	if x < y {
+		break /* ERROR "break" */
+	}
+
+	switch x {
+	case 0:
+		break
+	case 1:
+		if x == y {
+			break
+		}
+	default:
+		break
+		break
+	}
+
+	var z interface{}
+	switch z.(type) {
+	case int:
+		break
+	}
+
+	for {
+		break
+	}
+
+	var a []int
+	for _ = range a {
+		break
+	}
+
+	for {
+		if x == y {
+			break
+		}
+	}
+
+	var ch chan int
+	select {
+	case <-ch:
+		break
+	}
+
+	select {
+	case <-ch:
+		if x == y {
+			break
+		}
+	default:
+		break
+	}
+}
+
+func continues() {
+	var x, y int
+
+	continue /* ERROR "continue" */
+	{
+		continue /* ERROR "continue" */
+	}
+
+	if x < y {
+		continue /* ERROR "continue" */
+	}
+
+	switch x {
+	case 0:
+		continue /* ERROR "continue" */
+	}
+
+	var z interface{}
+	switch z.(type) {
+	case int:
+		continue /* ERROR "continue" */
+	}
+
+	var ch chan int
+	select {
+	case <-ch:
+		continue /* ERROR "continue" */
+	}
+
+	for i := 0; i < 10; i++ {
+		continue
+		if x < y {
+			continue
+			break
+		}
+		switch x {
+		case y:
+			continue
+		default:
+			break
+		}
+		select {
+		case <-ch:
+			continue
+		}
+	}
+
+	var a []int
+	for _ = range a {
+		continue
+		if x < y {
+			continue
+			break
+		}
+		switch x {
+		case y:
+			continue
+		default:
+			break
+		}
+		select {
+		case <-ch:
+			continue
+		}
+	}
+}
+
+func returns0() {
+	return
+	return 0 /* ERROR no result values expected */
+}
+
+func returns1(x float64) (int, *float64) {
+	return 0, &x
+	return /* ERROR wrong number of return values */
+	return "foo" /* ERROR "cannot convert" */, x /* ERROR "cannot return" */
+	return /* ERROR wrong number of return values */ 0, &x, 1
+}
+
+func returns2() (a, b int) {
+	return
+	return 1, "foo" /* ERROR cannot convert */
+	return /* ERROR wrong number of return values */ 1, 2, 3
+	{
+		type a int
+		return 1, 2
+		return /* ERROR a not in scope at return */
+	}
+}
+
+func returns3() (_ int) {
+	return
+	{
+		var _ int // blank (_) identifiers never shadow since they are in no scope
+		return
+	}
+}
+
+func switches0() {
+	var x int
+
+	switch x {
+	}
+
+	switch x {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+
+	switch {
+	case 1  /* ERROR "cannot convert" */ :
+	}
+
+	true := "false"
+	_ = true
+	// A tagless switch is equivalent to the bool 
+        // constant true, not the identifier 'true'.
+	switch {
+	case "false" /* ERROR "cannot convert" */:
+	}
+
+	switch int32(x) {
+	case 1, 2:
+	case x /* ERROR "cannot compare" */ :
+	}
+
+	switch x {
+	case 1 /* ERROR "overflows" */ << 100:
+	}
+
+	switch x {
+	case 1:
+	case 1 /* DISABLED "duplicate case" */ :
+	case 2, 3, 4:
+	case 1 /* DISABLED "duplicate case" */ :
+	}
+
+	switch uint64(x) {
+	case 1 /* DISABLED duplicate case */ <<64-1:
+	case 1 /* DISABLED duplicate case */ <<64-1:
+	}
+}
+
+func switches1() {
+	fallthrough /* ERROR "fallthrough statement out of place" */
+
+	var x int
+	switch x {
+	case 0:
+		fallthrough /* ERROR "fallthrough statement out of place" */
+		break
+	case 1:
+		fallthrough
+	case 2:
+	default:
+		fallthrough
+	case 3:
+		fallthrough /* ERROR "fallthrough statement out of place" */
+	}
+
+	var y interface{}
+	switch y.(type) {
+	case int:
+		fallthrough /* ERROR "fallthrough statement out of place" */
+	default:
+	}
+
+	switch x {
+	case 0:
+		if x == 0 {
+			fallthrough /* ERROR "fallthrough statement out of place" */
+		}
+	}
+
+	switch x {
+	case 0:
+		goto L1
+		L1: fallthrough
+	case 1:
+		goto L2
+		goto L3
+		goto L4
+		L2: L3: L4: fallthrough
+	default:
+	}
+
+	switch x {
+	case 0:
+		goto L5
+		L5: fallthrough
+	default:
+		goto L6
+		goto L7
+		goto L8
+		L6: L7: L8: fallthrough /* ERROR "fallthrough statement out of place" */
+	}
+
+	switch x {
+	case 0:
+		{
+			fallthrough /* ERROR "fallthrough statement out of place" */
+		}
+	default:
+	}
+}
+
+type I interface {
+	m()
+}
+
+type I2 interface {
+	m(int)
+}
+
+type T struct{}
+type T1 struct{}
+type T2 struct{}
+
+func (T) m() {}
+func (T2) m(int) {}
+
+func typeswitches() {
+	var i int
+	var x interface{}
+
+	switch x.(type) {}
+	switch (x /* ERROR "outside type switch" */ .(type)) {}
+
+	switch x.(type) {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+
+	switch x /* ERROR "declared but not used" */ := x.(type) {}
+
+	switch x := x.(type) {
+	case int:
+		var y int = x
+		_ = y
+	}
+
+	switch x := i /* ERROR "not an interface" */ .(type) {}
+
+	switch t := x.(type) {
+	case nil:
+		var v bool = t /* ERROR "cannot initialize" */
+		_ = v
+	case int:
+		var v int = t
+		_ = v
+	case float32, complex64:
+		var v float32 = t /* ERROR "cannot initialize" */
+		_ = v
+	default:
+		var v float32 = t /* ERROR "cannot initialize" */
+		_ = v
+	}
+
+	var t I
+	switch t.(type) {
+	case T:
+	case T1 /* ERROR "missing method m" */ :
+	case T2 /* ERROR "wrong type for method m" */ :
+	case I2 /* STRICT "wrong type for method m" */ : // only an error in strict mode (issue 8561)
+	}
+}
+
+// Test that each case clause uses the correct type of the variable
+// declared by the type switch (issue 5504).
+func typeswitch0() {
+	switch y := interface{}(nil).(type) {
+	case int:
+		func() int { return y + 0 }()
+	case float32:
+		func() float32 { return y }()
+	}
+}
+
+// Test correct scope setup.
+// (no redeclaration errors expected in the type switch)
+func typeswitch1() {
+	var t I
+	switch t := t; t := t.(type) {
+	case nil:
+		var _ I = t
+	case T:
+		var _ T = t
+	default:
+		var _ I = t
+	}
+}
+
+// Test correct typeswitch against interface types.
+type A interface { a() }
+type B interface { b() }
+type C interface { a(int) }
+
+func typeswitch2() {
+	switch A(nil).(type) {
+	case A:
+	case B:
+	case C /* STRICT "cannot have dynamic type" */: // only an error in strict mode (issue 8561)
+	}
+}
+
+func typeswitch3(x interface{}) {
+	switch x.(type) {
+	case int:
+	case float64:
+	case int /* ERROR duplicate case */ :
+	}
+
+	switch x.(type) {
+	case nil:
+	case int:
+	case nil /* ERROR duplicate case */ , nil /* ERROR duplicate case */ :
+	}
+
+	type F func(int)
+	switch x.(type) {
+	case nil:
+	case int, func(int):
+	case float32, func /* ERROR duplicate case */ (x int):
+	case F:
+	}
+}
+
+func fors1() {
+	for {}
+	var i string
+	_ = i
+	for i := 0; i < 10; i++ {}
+	for i := 0; i < 10; j /* ERROR cannot declare */ := 0 {}
+}
+
+func rangeloops1() {
+	var (
+		x int
+		a [10]float32
+		b []string
+		p *[10]complex128
+		pp **[10]complex128
+		s string
+		m map[int]bool
+		c chan int
+		sc chan<- int
+		rc <-chan int
+	)
+
+	for range x /* ERROR "cannot range over" */ {}
+	for _ = range x /* ERROR "cannot range over" */ {}
+	for i := range x /* ERROR "cannot range over" */ {}
+
+	for range a {}
+	for i := range a {
+		var ii int
+		ii = i
+		_ = ii
+	}
+	for i, x := range a {
+		var ii int
+		ii = i
+		_ = ii
+		var xx float64
+		xx = x /* ERROR "cannot assign" */
+		_ = xx
+	}
+	var ii int
+	var xx float32
+	for ii, xx = range a {}
+	_, _ = ii, xx
+
+	for range b {}
+	for i := range b {
+		var ii int
+		ii = i
+		_ = ii
+	}
+	for i, x := range b {
+		var ii int
+		ii = i
+		_ = ii
+		var xx string
+		xx = x
+		_ = xx
+	}
+
+	for range s {}
+	for i := range s {
+		var ii int
+		ii = i
+		_ = ii
+	}
+	for i, x := range s {
+		var ii int
+		ii = i
+		_ = ii
+		var xx rune
+		xx = x
+		_ = xx
+	}
+
+	for range p {}
+	for _, x := range p {
+		var xx complex128
+		xx = x
+		_ = xx
+	}
+
+	for range pp /* ERROR "cannot range over" */ {}
+	for _, x := range pp /* ERROR "cannot range over" */ {}
+
+	for range m {}
+	for k := range m {
+		var kk int32
+		kk = k /* ERROR "cannot assign" */
+		_ = kk
+	}
+	for k, v := range m {
+		var kk int
+		kk = k
+		_ = kk
+		if v {}
+	}
+
+	for range c {}
+	for _, _ /* ERROR "only one iteration variable" */ = range c {}
+	for e := range c {
+		var ee int
+		ee = e
+		_ = ee
+	}
+	for _ = range sc /* ERROR "cannot range over send-only channel" */ {}
+	for _ = range rc {}
+
+	// constant strings
+	const cs = "foo"
+	for range cs {}
+	for range "" {}
+	for i, x := range cs { _, _ = i, x }
+	for i, x := range "" {
+		var ii int
+		ii = i
+		_ = ii
+		var xx rune
+		xx = x
+		_ = xx
+	}
+}
+
+func rangeloops2() {
+	type I int
+	type R rune
+
+	var a [10]int
+	var i I
+	_ = i
+	for i /* ERROR cannot assign */ = range a {}
+	for i /* ERROR cannot assign */ = range &a {}
+	for i /* ERROR cannot assign */ = range a[:] {}
+
+	var s string
+	var r R
+	_ = r
+	for i /* ERROR cannot assign */ = range s {}
+	for i /* ERROR cannot assign */ = range "foo" {}
+	for _, r /* ERROR cannot assign */ = range s {}
+	for _, r /* ERROR cannot assign */ = range "foo" {}
+}
+
+func issue6766b() {
+	for _ := /* ERROR no new variables */ range "" {}
+	for a, a /* ERROR redeclared */ := range "" { _ = a }
+	var a int
+	_ = a
+	for a, a /* ERROR redeclared */ := range []int{1, 2, 3} { _ = a }
+}
+
+func labels0() {
+	goto L0
+	goto L1
+	L0:
+	L1:
+	L1 /* ERROR "already declared" */ :
+	if true {
+		goto L2		
+		L2:
+		L0 /* ERROR "already declared" */ :
+	}
+	_ = func() {
+		goto L0
+		goto L1
+		goto L2
+		L0:
+		L1:
+		L2:
+	}
+}
+
+func expression_statements(ch chan int) {
+	expression_statements(ch)
+	<-ch
+	println()
+
+	0 /* ERROR "not used" */
+	1 /* ERROR "not used" */ +2
+	cap /* ERROR "not used" */ (ch)
+	println /* ERROR "must be called" */
+}
diff --git a/third_party/go.tools/go/types/testdata/stmt1.src b/third_party/go.tools/go/types/testdata/stmt1.src
new file mode 100644
index 0000000..a2955e6
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/stmt1.src
@@ -0,0 +1,165 @@
+// Copyright 2013 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.
+
+// terminating statements
+
+package stmt1
+
+func _() {}
+
+func _() int {} /* ERROR "missing return" */
+
+func _() int { panic(0) }
+func _() int { (panic(0)) }
+
+// block statements
+func _(x, y int) (z int) {
+	{
+		return
+	}
+}
+
+func _(x, y int) (z int) {
+	{
+	}
+} /* ERROR "missing return" */
+
+// if statements
+func _(x, y int) (z int) {
+	if x < y { return }
+	return 1
+}
+
+func _(x, y int) (z int) {
+	if x < y { return }
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	if x < y {
+	} else { return 1
+	}
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	if x < y { return
+	} else { return
+	}
+}
+
+// for statements
+func _(x, y int) (z int) {
+	for x < y {
+		return
+	}
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	for {
+		return
+	}
+}
+
+func _(x, y int) (z int) {
+	for {
+		return
+		break
+	}
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	for {
+		for { break }
+		return
+	}
+}
+
+func _(x, y int) (z int) {
+L:	for {
+		for { break L }
+		return
+	}
+} /* ERROR "missing return" */
+
+// switch statements
+func _(x, y int) (z int) {
+	switch x {
+	case 0: return
+	default: return
+	}
+}
+
+func _(x, y int) (z int) {
+	switch x {
+	case 0: return
+	}
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	switch x {
+	case 0: return
+	case 1: break
+	}
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	switch x {
+	case 0: return
+	default:
+		switch y {
+		case 0: break
+		}
+		panic(0)
+	}
+}
+
+func _(x, y int) (z int) {
+L:	switch x {
+	case 0: return
+	default:
+		switch y {
+		case 0: break L
+		}
+		panic(0)
+	}
+} /* ERROR "missing return" */
+
+// select statements
+func _(ch chan int) (z int) {
+	select {}
+} // nice!
+
+func _(ch chan int) (z int) {
+	select {
+	default: break
+	}
+} /* ERROR "missing return" */
+
+func _(ch chan int) (z int) {
+	select {
+	case <-ch: return
+	default: break
+	}
+} /* ERROR "missing return" */
+
+func _(ch chan int) (z int) {
+	select {
+	case <-ch: return
+	default:
+		for i := 0; i < 10; i++ {
+			break
+		}
+		return
+	}
+}
+
+func _(ch chan int) (z int) {
+L:	select {
+	case <-ch: return
+	default:
+		for i := 0; i < 10; i++ {
+			break L
+		}
+		return
+	}
+} /* ERROR "missing return" */
diff --git a/third_party/go.tools/go/types/testdata/vardecl.src b/third_party/go.tools/go/types/testdata/vardecl.src
new file mode 100644
index 0000000..329f4ff
--- /dev/null
+++ b/third_party/go.tools/go/types/testdata/vardecl.src
@@ -0,0 +1,183 @@
+// Copyright 2013 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 vardecl
+
+// Prerequisites.
+import "math"
+func f() {}
+func g() (x, y int) { return }
+var m map[string]int
+
+// Var decls must have a type or an initializer.
+var _ int
+var _, _ int
+
+var _ /* ERROR "missing type or init expr" */
+var _ /* ERROR "missing type or init expr" */, _
+var _ /* ERROR "missing type or init expr" */, _, _
+
+// The initializer must be an expression.
+var _ = int /* ERROR "not an expression" */
+var _ = f /* ERROR "used as value" */ ()
+
+// Identifier and expression arity must match.
+var _, _ = 1, 2
+var _ = 1, 2 /* ERROR "extra init expr 2" */
+var _, _ = 1 /* ERROR "assignment count mismatch" */
+var _, _, _ /* ERROR "missing init expr for _" */ = 1, 2
+
+var _ = g /* ERROR "2-valued expr" */ ()
+var _, _ = g()
+var _, _, _ = g /* ERROR "assignment count mismatch" */ ()
+
+var _ = m["foo"]
+var _, _ = m["foo"]
+var _, _, _ = m  /* ERROR "assignment count mismatch" */ ["foo"]
+
+var _, _ int = 1, 2
+var _ int = 1, 2 /* ERROR "extra init expr 2" */
+var _, _ int = 1 /* ERROR "assignment count mismatch" */
+var _, _, _ /* ERROR "missing init expr for _" */ int = 1, 2
+
+var (
+	_, _ = 1, 2
+	_ = 1, 2 /* ERROR "extra init expr 2" */
+	_, _ = 1 /* ERROR "assignment count mismatch" */
+	_, _, _ /* ERROR "missing init expr for _" */ = 1, 2
+
+	_ = g /* ERROR "2-valued expr" */ ()
+	_, _ = g()
+	_, _, _ = g /* ERROR "assignment count mismatch" */ ()
+
+	_ = m["foo"]
+	_, _ = m["foo"]
+	_, _, _ = m /* ERROR "assignment count mismatch" */ ["foo"]
+
+	_, _ int = 1, 2
+	_ int = 1, 2 /* ERROR "extra init expr 2" */
+	_, _ int = 1 /* ERROR "assignment count mismatch" */
+	_, _, _ /* ERROR "missing init expr for _" */ int = 1, 2
+)
+
+// Variables declared in function bodies must be 'used'.
+type T struct{}
+func (r T) _(a, b, c int) (u, v, w int) {
+	var x1 /* ERROR "declared but not used" */ int
+	var x2 /* ERROR "declared but not used" */ int
+	x1 = 1
+	(x2) = 2
+
+	y1 /* ERROR "declared but not used" */ := 1
+	y2 /* ERROR "declared but not used" */ := 2
+	y1 = 1
+	(y1) = 2
+
+	{
+		var x1 /* ERROR "declared but not used" */ int
+		var x2 /* ERROR "declared but not used" */ int
+		x1 = 1
+		(x2) = 2
+
+		y1 /* ERROR "declared but not used" */ := 1
+		y2 /* ERROR "declared but not used" */ := 2
+		y1 = 1
+		(y1) = 2
+	}
+
+	if x /* ERROR "declared but not used" */ := 0; a < b {}
+
+	switch x /* ERROR "declared but not used" */, y := 0, 1; a {
+	case 0:
+		_ = y
+	case 1:
+		x /* ERROR "declared but not used" */ := 0
+	}
+
+	var t interface{}
+	switch t /* ERROR "declared but not used" */ := t.(type) {}
+
+	switch t /* ERROR "declared but not used" */ := t.(type) {
+	case int:
+	}
+
+	switch t /* ERROR "declared but not used" */ := t.(type) {
+	case int:
+	case float32, complex64:
+		t = nil
+	}
+
+	switch t := t.(type) {
+	case int:
+	case float32, complex64:
+		_ = t
+	}
+
+	switch t := t.(type) {
+	case int:
+	case float32:
+	case string:
+		_ = func() string {
+			return t
+		}
+	}
+
+	switch t := t; t /* ERROR "declared but not used" */ := t.(type) {}
+
+	var z1 /* ERROR "declared but not used" */ int
+	var z2 int
+	_ = func(a, b, c int) (u, v, w int) {
+		z1 = a
+		(z1) = b
+		a = z2
+		return
+	}
+
+	var s []int
+	var i /* ERROR "declared but not used" */ , j int
+	for i, j = range s {
+		_ = j
+	}
+
+	for i, j /* ERROR "declared but not used" */ := range s {
+		_ = func() int {
+			return i
+		}
+	}
+	return
+}
+
+// Invalid (unused) expressions must not lead to spurious "declared but not used errors"
+func _() {
+	var a, b, c int
+	var x, y int
+	x, y = a /* ERROR assignment count mismatch */ , b, c
+	_ = x
+	_ = y
+}
+
+func _() {
+	var x int
+	return x /* ERROR no result values expected */
+	return math /* ERROR no result values expected */ .Sin(0)
+}
+
+func _() int {
+	var x, y int
+	return /* ERROR wrong number of return values */ x, y
+}
+
+// Short variable declarations must declare at least one new non-blank variable.
+func _() {
+	_ := /* ERROR no new variables */ 0
+	_, a := 0, 1
+	_, a := /* ERROR no new variables */ 0, 1
+	_, a, b := 0, 1, 2
+	_, _, _ := /* ERROR no new variables */ 0, 1, 2
+
+	_ = a
+	_ = b
+}
+
+// TODO(gri) consolidate other var decl checks in this file
\ No newline at end of file
diff --git a/third_party/go.tools/go/types/token_test.go b/third_party/go.tools/go/types/token_test.go
new file mode 100644
index 0000000..705bb29
--- /dev/null
+++ b/third_party/go.tools/go/types/token_test.go
@@ -0,0 +1,47 @@
+// Copyright 2013 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.
+
+// This file checks invariants of token.Token ordering that we rely on
+// since package go/token doesn't provide any guarantees at the moment.
+
+package types
+
+import (
+	"go/token"
+	"testing"
+)
+
+var assignOps = map[token.Token]token.Token{
+	token.ADD_ASSIGN:     token.ADD,
+	token.SUB_ASSIGN:     token.SUB,
+	token.MUL_ASSIGN:     token.MUL,
+	token.QUO_ASSIGN:     token.QUO,
+	token.REM_ASSIGN:     token.REM,
+	token.AND_ASSIGN:     token.AND,
+	token.OR_ASSIGN:      token.OR,
+	token.XOR_ASSIGN:     token.XOR,
+	token.SHL_ASSIGN:     token.SHL,
+	token.SHR_ASSIGN:     token.SHR,
+	token.AND_NOT_ASSIGN: token.AND_NOT,
+}
+
+func TestZeroTok(t *testing.T) {
+	// zero value for token.Token must be token.ILLEGAL
+	var zero token.Token
+	if token.ILLEGAL != zero {
+		t.Errorf("%s == %d; want 0", token.ILLEGAL, zero)
+	}
+}
+
+func TestAssignOp(t *testing.T) {
+	// there are fewer than 256 tokens
+	for i := 0; i < 256; i++ {
+		tok := token.Token(i)
+		got := assignOp(tok)
+		want := assignOps[tok]
+		if got != want {
+			t.Errorf("for assignOp(%s): got %s; want %s", tok, got, want)
+		}
+	}
+}
diff --git a/third_party/go.tools/go/types/type.go b/third_party/go.tools/go/types/type.go
new file mode 100644
index 0000000..4b4e5f6
--- /dev/null
+++ b/third_party/go.tools/go/types/type.go
@@ -0,0 +1,452 @@
+// 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.
+
+package types
+
+import "sort"
+
+// TODO(gri) Revisit factory functions - make sure they have all relevant parameters.
+
+// A Type represents a type of Go.
+// All types implement the Type interface.
+type Type interface {
+	// Underlying returns the underlying type of a type.
+	Underlying() Type
+
+	// String returns a string representation of a type.
+	String() string
+}
+
+// BasicKind describes the kind of basic type.
+type BasicKind int
+
+const (
+	Invalid BasicKind = iota // type is invalid
+
+	// predeclared types
+	Bool
+	Int
+	Int8
+	Int16
+	Int32
+	Int64
+	Uint
+	Uint8
+	Uint16
+	Uint32
+	Uint64
+	Uintptr
+	Float32
+	Float64
+	Complex64
+	Complex128
+	String
+	UnsafePointer
+
+	// types for untyped values
+	UntypedBool
+	UntypedInt
+	UntypedRune
+	UntypedFloat
+	UntypedComplex
+	UntypedString
+	UntypedNil
+
+	// aliases
+	Byte = Uint8
+	Rune = Int32
+)
+
+// BasicInfo is a set of flags describing properties of a basic type.
+type BasicInfo int
+
+// Properties of basic types.
+const (
+	IsBoolean BasicInfo = 1 << iota
+	IsInteger
+	IsUnsigned
+	IsFloat
+	IsComplex
+	IsString
+	IsUntyped
+
+	IsOrdered   = IsInteger | IsFloat | IsString
+	IsNumeric   = IsInteger | IsFloat | IsComplex
+	IsConstType = IsBoolean | IsNumeric | IsString
+)
+
+// A Basic represents a basic type.
+type Basic struct {
+	kind BasicKind
+	info BasicInfo
+	name string
+}
+
+// Kind returns the kind of basic type b.
+func (b *Basic) Kind() BasicKind { return b.kind }
+
+// Info returns information about properties of basic type b.
+func (b *Basic) Info() BasicInfo { return b.info }
+
+// Name returns the name of basic type b.
+func (b *Basic) Name() string { return b.name }
+
+// An Array represents an array type.
+type Array struct {
+	len  int64
+	elem Type
+}
+
+// NewArray returns a new array type for the given element type and length.
+func NewArray(elem Type, len int64) *Array { return &Array{len, elem} }
+
+// Len returns the length of array a.
+func (a *Array) Len() int64 { return a.len }
+
+// Elem returns element type of array a.
+func (a *Array) Elem() Type { return a.elem }
+
+// A Slice represents a slice type.
+type Slice struct {
+	elem Type
+}
+
+// NewSlice returns a new slice type for the given element type.
+func NewSlice(elem Type) *Slice { return &Slice{elem} }
+
+// Elem returns the element type of slice s.
+func (s *Slice) Elem() Type { return s.elem }
+
+// A Struct represents a struct type.
+type Struct struct {
+	fields []*Var
+	tags   []string // field tags; nil if there are no tags
+	// TODO(gri) access to offsets is not threadsafe - fix this
+	offsets []int64 // field offsets in bytes, lazily initialized
+}
+
+// NewStruct returns a new struct with the given fields and corresponding field tags.
+// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be
+// only as long as required to hold the tag with the largest index i. Consequently,
+// if no field has a tag, tags may be nil.
+func NewStruct(fields []*Var, tags []string) *Struct {
+	var fset objset
+	for _, f := range fields {
+		if f.name != "_" && fset.insert(f) != nil {
+			panic("multiple fields with the same name")
+		}
+	}
+	if len(tags) > len(fields) {
+		panic("more tags than fields")
+	}
+	return &Struct{fields: fields, tags: tags}
+}
+
+// NumFields returns the number of fields in the struct (including blank and anonymous fields).
+func (s *Struct) NumFields() int { return len(s.fields) }
+
+// Field returns the i'th field for 0 <= i < NumFields().
+func (s *Struct) Field(i int) *Var { return s.fields[i] }
+
+// Tag returns the i'th field tag for 0 <= i < NumFields().
+func (s *Struct) Tag(i int) string {
+	if i < len(s.tags) {
+		return s.tags[i]
+	}
+	return ""
+}
+
+// A Pointer represents a pointer type.
+type Pointer struct {
+	base Type // element type
+}
+
+// NewPointer returns a new pointer type for the given element (base) type.
+func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }
+
+// Elem returns the element type for the given pointer p.
+func (p *Pointer) Elem() Type { return p.base }
+
+// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple.
+// Tuples are used as components of signatures and to represent the type of multiple
+// assignments; they are not first class types of Go.
+type Tuple struct {
+	vars []*Var
+}
+
+// NewTuple returns a new tuple for the given variables.
+func NewTuple(x ...*Var) *Tuple {
+	if len(x) > 0 {
+		return &Tuple{x}
+	}
+	return nil
+}
+
+// Len returns the number variables of tuple t.
+func (t *Tuple) Len() int {
+	if t != nil {
+		return len(t.vars)
+	}
+	return 0
+}
+
+// At returns the i'th variable of tuple t.
+func (t *Tuple) At(i int) *Var { return t.vars[i] }
+
+// A Signature represents a (non-builtin) function or method type.
+type Signature struct {
+	scope    *Scope // function scope, always present
+	recv     *Var   // nil if not a method
+	params   *Tuple // (incoming) parameters from left to right; or nil
+	results  *Tuple // (outgoing) results from left to right; or nil
+	variadic bool   // true if the last parameter's type is of the form ...T (or string, for append built-in only)
+}
+
+// NewSignature returns a new function type for the given receiver, parameters,
+// and results, either of which may be nil. If variadic is set, the function
+// is variadic, it must have at least one parameter, and the last parameter
+// must be of unnamed slice type.
+func NewSignature(scope *Scope, recv *Var, params, results *Tuple, variadic bool) *Signature {
+	// TODO(gri) Should we rely on the correct (non-nil) incoming scope
+	//           or should this function allocate and populate a scope?
+	if variadic {
+		n := params.Len()
+		if n == 0 {
+			panic("types.NewSignature: variadic function must have at least one parameter")
+		}
+		if _, ok := params.At(n - 1).typ.(*Slice); !ok {
+			panic("types.NewSignature: variadic parameter must be of unnamed slice type")
+		}
+	}
+	return &Signature{scope, recv, params, results, variadic}
+}
+
+// Recv returns the receiver of signature s (if a method), or nil if a
+// function.
+//
+// For an abstract method, Recv returns the enclosing interface either
+// as a *Named or an *Interface.  Due to embedding, an interface may
+// contain methods whose receiver type is a different interface.
+func (s *Signature) Recv() *Var { return s.recv }
+
+// Params returns the parameters of signature s, or nil.
+func (s *Signature) Params() *Tuple { return s.params }
+
+// Results returns the results of signature s, or nil.
+func (s *Signature) Results() *Tuple { return s.results }
+
+// Variadic reports whether the signature s is variadic.
+func (s *Signature) Variadic() bool { return s.variadic }
+
+// An Interface represents an interface type.
+type Interface struct {
+	methods   []*Func  // ordered list of explicitly declared methods
+	embeddeds []*Named // ordered list of explicitly embedded types
+
+	allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset)
+}
+
+// NewInterface returns a new interface for the given methods and embedded types.
+func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
+	typ := new(Interface)
+
+	var mset objset
+	for _, m := range methods {
+		if mset.insert(m) != nil {
+			panic("multiple methods with the same name")
+		}
+		// set receiver
+		// TODO(gri) Ideally, we should use a named type here instead of
+		// typ, for less verbose printing of interface method signatures.
+		m.typ.(*Signature).recv = NewVar(m.pos, m.pkg, "", typ)
+	}
+	sort.Sort(byUniqueMethodName(methods))
+
+	if embeddeds == nil {
+		sort.Sort(byUniqueTypeName(embeddeds))
+	}
+
+	typ.methods = methods
+	typ.embeddeds = embeddeds
+	return typ
+}
+
+// NumExplicitMethods returns the number of explicitly declared methods of interface t.
+func (t *Interface) NumExplicitMethods() int { return len(t.methods) }
+
+// ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods().
+// The methods are ordered by their unique Id.
+func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] }
+
+// NumEmbeddeds returns the number of embedded types in interface t.
+func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) }
+
+// Embedded returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds().
+// The types are ordered by the corresponding TypeName's unique Id.
+func (t *Interface) Embedded(i int) *Named { return t.embeddeds[i] }
+
+// NumMethods returns the total number of methods of interface t.
+func (t *Interface) NumMethods() int { return len(t.allMethods) }
+
+// Method returns the i'th method of interface t for 0 <= i < t.NumMethods().
+// The methods are ordered by their unique Id.
+func (t *Interface) Method(i int) *Func { return t.allMethods[i] }
+
+// Empty returns true if t is the empty interface.
+func (t *Interface) Empty() bool { return len(t.allMethods) == 0 }
+
+// Complete computes the interface's method set. It must be called by users of
+// NewInterface after the interface's embedded types are fully defined and
+// before using the interface type in any way other than to form other types.
+// Complete returns the receiver.
+func (t *Interface) Complete() *Interface {
+	if t.allMethods != nil {
+		return t
+	}
+
+	var allMethods []*Func
+	if t.embeddeds == nil {
+		if t.methods == nil {
+			allMethods = make([]*Func, 0, 1)
+		} else {
+			allMethods = t.methods
+		}
+	} else {
+		allMethods = append(allMethods, t.methods...)
+		for _, et := range t.embeddeds {
+			it := et.Underlying().(*Interface)
+			it.Complete()
+			for _, tm := range it.allMethods {
+				// Make a copy of the method and adjust its receiver type.
+				newm := *tm
+				newmtyp := *tm.typ.(*Signature)
+				newm.typ = &newmtyp
+				newmtyp.recv = NewVar(newm.pos, newm.pkg, "", t)
+				allMethods = append(allMethods, &newm)
+			}
+		}
+		sort.Sort(byUniqueMethodName(allMethods))
+	}
+	t.allMethods = allMethods
+
+	return t
+}
+
+// A Map represents a map type.
+type Map struct {
+	key, elem Type
+}
+
+// NewMap returns a new map for the given key and element types.
+func NewMap(key, elem Type) *Map {
+	return &Map{key, elem}
+}
+
+// Key returns the key type of map m.
+func (m *Map) Key() Type { return m.key }
+
+// Elem returns the element type of map m.
+func (m *Map) Elem() Type { return m.elem }
+
+// A Chan represents a channel type.
+type Chan struct {
+	dir  ChanDir
+	elem Type
+}
+
+// A ChanDir value indicates a channel direction.
+type ChanDir int
+
+// The direction of a channel is indicated by one of the following constants.
+const (
+	SendRecv ChanDir = iota
+	SendOnly
+	RecvOnly
+)
+
+// NewChan returns a new channel type for the given direction and element type.
+func NewChan(dir ChanDir, elem Type) *Chan {
+	return &Chan{dir, elem}
+}
+
+// Dir returns the direction of channel c.
+func (c *Chan) Dir() ChanDir { return c.dir }
+
+// Elem returns the element type of channel c.
+func (c *Chan) Elem() Type { return c.elem }
+
+// A Named represents a named type.
+type Named struct {
+	obj        *TypeName // corresponding declared object
+	underlying Type      // possibly a *Named during setup; never a *Named once set up completely
+	methods    []*Func   // methods declared for this type (not the method set of this type)
+}
+
+// NewNamed returns a new named type for the given type name, underlying type, and associated methods.
+// The underlying type must not be a *Named.
+func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
+	if _, ok := underlying.(*Named); ok {
+		panic("types.NewNamed: underlying type must not be *Named")
+	}
+	typ := &Named{obj: obj, underlying: underlying, methods: methods}
+	if obj.typ == nil {
+		obj.typ = typ
+	}
+	return typ
+}
+
+// TypeName returns the type name for the named type t.
+func (t *Named) Obj() *TypeName { return t.obj }
+
+// NumMethods returns the number of explicit methods whose receiver is named type t.
+func (t *Named) NumMethods() int { return len(t.methods) }
+
+// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
+func (t *Named) Method(i int) *Func { return t.methods[i] }
+
+// SetUnderlying sets the underlying type and marks t as complete.
+// TODO(gri) determine if there's a better solution rather than providing this function
+func (t *Named) SetUnderlying(underlying Type) {
+	if underlying == nil {
+		panic("types.Named.SetUnderlying: underlying type must not be nil")
+	}
+	if _, ok := underlying.(*Named); ok {
+		panic("types.Named.SetUnderlying: underlying type must not be *Named")
+	}
+	t.underlying = underlying
+}
+
+// AddMethod adds method m unless it is already in the method list.
+// TODO(gri) find a better solution instead of providing this function
+func (t *Named) AddMethod(m *Func) {
+	if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 {
+		t.methods = append(t.methods, m)
+	}
+}
+
+// Implementations for Type methods.
+
+func (t *Basic) Underlying() Type     { return t }
+func (t *Array) Underlying() Type     { return t }
+func (t *Slice) Underlying() Type     { return t }
+func (t *Struct) Underlying() Type    { return t }
+func (t *Pointer) Underlying() Type   { return t }
+func (t *Tuple) Underlying() Type     { return t }
+func (t *Signature) Underlying() Type { return t }
+func (t *Interface) Underlying() Type { return t }
+func (t *Map) Underlying() Type       { return t }
+func (t *Chan) Underlying() Type      { return t }
+func (t *Named) Underlying() Type     { return t.underlying }
+
+func (t *Basic) String() string     { return TypeString(nil, t) }
+func (t *Array) String() string     { return TypeString(nil, t) }
+func (t *Slice) String() string     { return TypeString(nil, t) }
+func (t *Struct) String() string    { return TypeString(nil, t) }
+func (t *Pointer) String() string   { return TypeString(nil, t) }
+func (t *Tuple) String() string     { return TypeString(nil, t) }
+func (t *Signature) String() string { return TypeString(nil, t) }
+func (t *Interface) String() string { return TypeString(nil, t) }
+func (t *Map) String() string       { return TypeString(nil, t) }
+func (t *Chan) String() string      { return TypeString(nil, t) }
+func (t *Named) String() string     { return TypeString(nil, t) }
diff --git a/third_party/go.tools/go/types/typestring.go b/third_party/go.tools/go/types/typestring.go
new file mode 100644
index 0000000..9a537e8
--- /dev/null
+++ b/third_party/go.tools/go/types/typestring.go
@@ -0,0 +1,266 @@
+// Copyright 2013 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.
+
+// This file implements printing of types.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// If GcCompatibilityMode is set, printing of types is modified
+// to match the representation of some types in the gc compiler:
+//
+//	- byte and rune lose their alias name and simply stand for
+//	  uint8 and int32 respectively
+//	- embedded interfaces get flattened (the embedding info is lost,
+//	  and certain recursive interface types cannot be printed anymore)
+//
+// This makes it easier to compare packages computed with the type-
+// checker vs packages imported from gc export data.
+//
+// Caution: This flag affects all uses of WriteType, globally.
+// It is only provided for testing in conjunction with
+// gc-generated data. It may be removed at any time.
+var GcCompatibilityMode bool
+
+// TypeString returns the string representation of typ.
+// Named types are printed package-qualified if they
+// do not belong to this package.
+func TypeString(this *Package, typ Type) string {
+	var buf bytes.Buffer
+	WriteType(&buf, this, typ)
+	return buf.String()
+}
+
+// WriteType writes the string representation of typ to buf.
+// Named types are printed package-qualified if they
+// do not belong to this package.
+func WriteType(buf *bytes.Buffer, this *Package, typ Type) {
+	writeType(buf, this, typ, make([]Type, 8))
+}
+
+func writeType(buf *bytes.Buffer, this *Package, typ Type, visited []Type) {
+	// Theoretically, this is a quadratic lookup algorithm, but in
+	// practice deeply nested composite types with unnamed component
+	// types are uncommon. This code is likely more efficient than
+	// using a map.
+	for _, t := range visited {
+		if t == typ {
+			fmt.Fprintf(buf, "○%T", typ) // cycle to typ
+			return
+		}
+	}
+	visited = append(visited, typ)
+
+	switch t := typ.(type) {
+	case nil:
+		buf.WriteString("<nil>")
+
+	case *Basic:
+		if t.kind == UnsafePointer {
+			buf.WriteString("unsafe.")
+		}
+		if GcCompatibilityMode {
+			// forget the alias names
+			switch t.kind {
+			case Byte:
+				t = Typ[Uint8]
+			case Rune:
+				t = Typ[Int32]
+			}
+		}
+		buf.WriteString(t.name)
+
+	case *Array:
+		fmt.Fprintf(buf, "[%d]", t.len)
+		writeType(buf, this, t.elem, visited)
+
+	case *Slice:
+		buf.WriteString("[]")
+		writeType(buf, this, t.elem, visited)
+
+	case *Struct:
+		buf.WriteString("struct{")
+		for i, f := range t.fields {
+			if i > 0 {
+				buf.WriteString("; ")
+			}
+			if !f.anonymous {
+				buf.WriteString(f.name)
+				buf.WriteByte(' ')
+			}
+			writeType(buf, this, f.typ, visited)
+			if tag := t.Tag(i); tag != "" {
+				fmt.Fprintf(buf, " %q", tag)
+			}
+		}
+		buf.WriteByte('}')
+
+	case *Pointer:
+		buf.WriteByte('*')
+		writeType(buf, this, t.base, visited)
+
+	case *Tuple:
+		writeTuple(buf, this, t, false, visited)
+
+	case *Signature:
+		buf.WriteString("func")
+		writeSignature(buf, this, t, visited)
+
+	case *Interface:
+		// We write the source-level methods and embedded types rather
+		// than the actual method set since resolved method signatures
+		// may have non-printable cycles if parameters have anonymous
+		// interface types that (directly or indirectly) embed the
+		// current interface. For instance, consider the result type
+		// of m:
+		//
+		//     type T interface{
+		//         m() interface{ T }
+		//     }
+		//
+		buf.WriteString("interface{")
+		if GcCompatibilityMode {
+			// print flattened interface
+			// (useful to compare against gc-generated interfaces)
+			for i, m := range t.allMethods {
+				if i > 0 {
+					buf.WriteString("; ")
+				}
+				buf.WriteString(m.name)
+				writeSignature(buf, this, m.typ.(*Signature), visited)
+			}
+		} else {
+			// print explicit interface methods and embedded types
+			for i, m := range t.methods {
+				if i > 0 {
+					buf.WriteString("; ")
+				}
+				buf.WriteString(m.name)
+				writeSignature(buf, this, m.typ.(*Signature), visited)
+			}
+			for i, typ := range t.embeddeds {
+				if i > 0 || len(t.methods) > 0 {
+					buf.WriteString("; ")
+				}
+				writeType(buf, this, typ, visited)
+			}
+		}
+		buf.WriteByte('}')
+
+	case *Map:
+		buf.WriteString("map[")
+		writeType(buf, this, t.key, visited)
+		buf.WriteByte(']')
+		writeType(buf, this, t.elem, visited)
+
+	case *Chan:
+		var s string
+		var parens bool
+		switch t.dir {
+		case SendRecv:
+			s = "chan "
+			// chan (<-chan T) requires parentheses
+			if c, _ := t.elem.(*Chan); c != nil && c.dir == RecvOnly {
+				parens = true
+			}
+		case SendOnly:
+			s = "chan<- "
+		case RecvOnly:
+			s = "<-chan "
+		default:
+			panic("unreachable")
+		}
+		buf.WriteString(s)
+		if parens {
+			buf.WriteByte('(')
+		}
+		writeType(buf, this, t.elem, visited)
+		if parens {
+			buf.WriteByte(')')
+		}
+
+	case *Named:
+		s := "<Named w/o object>"
+		if obj := t.obj; obj != nil {
+			if pkg := obj.pkg; pkg != nil && pkg != this {
+				buf.WriteString(pkg.path)
+				buf.WriteByte('.')
+			}
+			// TODO(gri): function-local named types should be displayed
+			// differently from named types at package level to avoid
+			// ambiguity.
+			s = obj.name
+		}
+		buf.WriteString(s)
+
+	default:
+		// For externally defined implementations of Type.
+		buf.WriteString(t.String())
+	}
+}
+
+func writeTuple(buf *bytes.Buffer, this *Package, tup *Tuple, variadic bool, visited []Type) {
+	buf.WriteByte('(')
+	if tup != nil {
+		for i, v := range tup.vars {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			if v.name != "" {
+				buf.WriteString(v.name)
+				buf.WriteByte(' ')
+			}
+			typ := v.typ
+			if variadic && i == len(tup.vars)-1 {
+				if s, ok := typ.(*Slice); ok {
+					buf.WriteString("...")
+					typ = s.elem
+				} else {
+					// special case:
+					// append(s, "foo"...) leads to signature func([]byte, string...)
+					if t, ok := typ.Underlying().(*Basic); !ok || t.kind != String {
+						panic("internal error: string type expected")
+					}
+					writeType(buf, this, typ, visited)
+					buf.WriteString("...")
+					continue
+				}
+			}
+			writeType(buf, this, typ, visited)
+		}
+	}
+	buf.WriteByte(')')
+}
+
+// WriteSignature writes the representation of the signature sig to buf,
+// without a leading "func" keyword.
+// Named types are printed package-qualified if they
+// do not belong to this package.
+func WriteSignature(buf *bytes.Buffer, this *Package, sig *Signature) {
+	writeSignature(buf, this, sig, make([]Type, 8))
+}
+
+func writeSignature(buf *bytes.Buffer, this *Package, sig *Signature, visited []Type) {
+	writeTuple(buf, this, sig.params, sig.variadic, visited)
+
+	n := sig.results.Len()
+	if n == 0 {
+		// no result
+		return
+	}
+
+	buf.WriteByte(' ')
+	if n == 1 && sig.results.vars[0].name == "" {
+		// single unnamed result
+		writeType(buf, this, sig.results.vars[0].typ, visited)
+		return
+	}
+
+	// multiple or named result(s)
+	writeTuple(buf, this, sig.results, false, visited)
+}
diff --git a/third_party/go.tools/go/types/typestring_test.go b/third_party/go.tools/go/types/typestring_test.go
new file mode 100644
index 0000000..508dbe6
--- /dev/null
+++ b/third_party/go.tools/go/types/typestring_test.go
@@ -0,0 +1,158 @@
+// 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 types_test
+
+import (
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"testing"
+
+	_ "llvm.org/llgo/third_party/go.tools/go/gcimporter"
+	. "llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+const filename = "<src>"
+
+func makePkg(t *testing.T, src string) (*Package, error) {
+	fset := token.NewFileSet()
+	file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
+	if err != nil {
+		return nil, err
+	}
+	// use the package name as package path
+	return Check(file.Name.Name, fset, []*ast.File{file})
+}
+
+type testEntry struct {
+	src, str string
+}
+
+// dup returns a testEntry where both src and str are the same.
+func dup(s string) testEntry {
+	return testEntry{s, s}
+}
+
+// types that don't depend on any other type declarations
+var independentTestTypes = []testEntry{
+	// basic types
+	dup("int"),
+	dup("float32"),
+	dup("string"),
+
+	// arrays
+	dup("[10]int"),
+
+	// slices
+	dup("[]int"),
+	dup("[][]int"),
+
+	// structs
+	dup("struct{}"),
+	dup("struct{x int}"),
+	{`struct {
+		x, y int
+		z float32 "foo"
+	}`, `struct{x int; y int; z float32 "foo"}`},
+	{`struct {
+		string
+		elems []complex128
+	}`, `struct{string; elems []complex128}`},
+
+	// pointers
+	dup("*int"),
+	dup("***struct{}"),
+	dup("*struct{a int; b float32}"),
+
+	// functions
+	dup("func()"),
+	dup("func(x int)"),
+	{"func(x, y int)", "func(x int, y int)"},
+	{"func(x, y int, z string)", "func(x int, y int, z string)"},
+	dup("func(int)"),
+	{"func(int, string, byte)", "func(int, string, byte)"},
+
+	dup("func() int"),
+	{"func() (string)", "func() string"},
+	dup("func() (u int)"),
+	{"func() (u, v int, w string)", "func() (u int, v int, w string)"},
+
+	dup("func(int) string"),
+	dup("func(x int) string"),
+	dup("func(x int) (u string)"),
+	{"func(x, y int) (u string)", "func(x int, y int) (u string)"},
+
+	dup("func(...int) string"),
+	dup("func(x ...int) string"),
+	dup("func(x ...int) (u string)"),
+	{"func(x, y ...int) (u string)", "func(x int, y ...int) (u string)"},
+
+	// interfaces
+	dup("interface{}"),
+	dup("interface{m()}"),
+	dup(`interface{String() string; m(int) float32}`),
+
+	// maps
+	dup("map[string]int"),
+	{"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"},
+
+	// channels
+	dup("chan<- chan int"),
+	dup("chan<- <-chan int"),
+	dup("<-chan <-chan int"),
+	dup("chan (<-chan int)"),
+	dup("chan<- func()"),
+	dup("<-chan []func() int"),
+}
+
+// types that depend on other type declarations (src in TestTypes)
+var dependentTestTypes = []testEntry{
+	// interfaces
+	dup(`interface{io.Reader; io.Writer}`),
+	dup(`interface{m() int; io.Writer}`),
+	{`interface{m() interface{T}}`, `interface{m() interface{p.T}}`},
+}
+
+func TestTypeString(t *testing.T) {
+	var tests []testEntry
+	tests = append(tests, independentTestTypes...)
+	tests = append(tests, dependentTestTypes...)
+
+	for _, test := range tests {
+		src := `package p; import "io"; type _ io.Writer; type T ` + test.src
+		pkg, err := makePkg(t, src)
+		if err != nil {
+			t.Errorf("%s: %s", src, err)
+			continue
+		}
+		typ := pkg.Scope().Lookup("T").Type().Underlying()
+		if got := typ.String(); got != test.str {
+			t.Errorf("%s: got %s, want %s", test.src, got, test.str)
+		}
+	}
+}
+
+func TestQualifiedTypeString(t *testing.T) {
+	p, _ := pkgFor("p.go", "package p; type T int", nil)
+	q, _ := pkgFor("q.go", "package q", nil)
+
+	pT := p.Scope().Lookup("T").Type()
+	for _, test := range []struct {
+		typ  Type
+		this *Package
+		want string
+	}{
+		{pT, nil, "p.T"},
+		{pT, p, "T"},
+		{pT, q, "p.T"},
+		{NewPointer(pT), p, "*T"},
+		{NewPointer(pT), q, "*p.T"},
+	} {
+		if got := TypeString(test.this, test.typ); got != test.want {
+			t.Errorf("TypeString(%s, %s) = %s, want %s",
+				test.this, test.typ, got, test.want)
+		}
+	}
+}
diff --git a/third_party/go.tools/go/types/typeutil/example_test.go b/third_party/go.tools/go/types/typeutil/example_test.go
new file mode 100644
index 0000000..1eddedb
--- /dev/null
+++ b/third_party/go.tools/go/types/typeutil/example_test.go
@@ -0,0 +1,64 @@
+package typeutil_test
+
+import (
+	"fmt"
+	"sort"
+
+	"go/ast"
+	"go/parser"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+func ExampleMap() {
+	const source = `package P
+
+var X []string
+var Y []string
+
+const p, q = 1.0, 2.0
+
+func f(offset int32) (value byte, ok bool)
+func g(rune) (uint8, bool)
+`
+
+	// Parse and type-check the package.
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "P.go", source, 0)
+	if err != nil {
+		panic(err)
+	}
+	pkg, err := new(types.Config).Check("P", fset, []*ast.File{f}, nil)
+	if err != nil {
+		panic(err)
+	}
+
+	scope := pkg.Scope()
+
+	// Group names of package-level objects by their type.
+	var namesByType typeutil.Map // value is []string
+	for _, name := range scope.Names() {
+		T := scope.Lookup(name).Type()
+
+		names, _ := namesByType.At(T).([]string)
+		names = append(names, name)
+		namesByType.Set(T, names)
+	}
+
+	// Format, sort, and print the map entries.
+	var lines []string
+	namesByType.Iterate(func(T types.Type, names interface{}) {
+		lines = append(lines, fmt.Sprintf("%s   %s", names, T))
+	})
+	sort.Strings(lines)
+	for _, line := range lines {
+		fmt.Println(line)
+	}
+
+	// Output:
+	// [X Y]   []string
+	// [f g]   func(offset int32) (value byte, ok bool)
+	// [p q]   untyped float
+}
diff --git a/third_party/go.tools/go/types/typeutil/imports.go b/third_party/go.tools/go/types/typeutil/imports.go
new file mode 100644
index 0000000..2609f7f
--- /dev/null
+++ b/third_party/go.tools/go/types/typeutil/imports.go
@@ -0,0 +1,27 @@
+package typeutil
+
+import "llvm.org/llgo/third_party/go.tools/go/types"
+
+// Dependencies returns all dependencies of the specified packages.
+//
+// Dependent packages appear in topological order: if package P imports
+// package Q, Q appears earlier than P in the result.
+// The algorithm follows import statements in the order they
+// appear in the source code, so the result is a total order.
+//
+func Dependencies(pkgs ...*types.Package) []*types.Package {
+	var result []*types.Package
+	seen := make(map[*types.Package]bool)
+	var visit func(pkgs []*types.Package)
+	visit = func(pkgs []*types.Package) {
+		for _, p := range pkgs {
+			if !seen[p] {
+				seen[p] = true
+				visit(p.Imports())
+				result = append(result, p)
+			}
+		}
+	}
+	visit(pkgs)
+	return result
+}
diff --git a/third_party/go.tools/go/types/typeutil/imports_test.go b/third_party/go.tools/go/types/typeutil/imports_test.go
new file mode 100644
index 0000000..b0375ca
--- /dev/null
+++ b/third_party/go.tools/go/types/typeutil/imports_test.go
@@ -0,0 +1,75 @@
+package typeutil_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+func TestDependencies(t *testing.T) {
+	packages := make(map[string]*types.Package)
+	conf := types.Config{
+		Packages: packages,
+		Import: func(_ map[string]*types.Package, path string) (*types.Package, error) {
+			return packages[path], nil
+		},
+	}
+	fset := token.NewFileSet()
+
+	// All edges go to the right.
+	//  /--D--B--A
+	// F    \_C_/
+	//  \__E_/
+	for i, content := range []string{
+		`package A`,
+		`package C; import (_ "A")`,
+		`package B; import (_ "A")`,
+		`package E; import (_ "C")`,
+		`package D; import (_ "B"; _ "C")`,
+		`package F; import (_ "D"; _ "E")`,
+	} {
+		f, err := parser.ParseFile(fset, fmt.Sprintf("%d.go", i), content, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		packages[pkg.Path()] = pkg
+	}
+
+	for _, test := range []struct {
+		roots, want string
+	}{
+		{"A", "A"},
+		{"B", "AB"},
+		{"C", "AC"},
+		{"D", "ABCD"},
+		{"E", "ACE"},
+		{"F", "ABCDEF"},
+
+		{"BE", "ABCE"},
+		{"EB", "ACEB"},
+		{"DE", "ABCDE"},
+		{"ED", "ACEBD"},
+		{"EF", "ACEBDF"},
+	} {
+		var pkgs []*types.Package
+		for _, r := range test.roots {
+			pkgs = append(pkgs, conf.Packages[string(r)])
+		}
+		var got string
+		for _, p := range typeutil.Dependencies(pkgs...) {
+			got += p.Path()
+		}
+		if got != test.want {
+			t.Errorf("Dependencies(%q) = %q, want %q", test.roots, got, test.want)
+		}
+	}
+}
diff --git a/third_party/go.tools/go/types/typeutil/map.go b/third_party/go.tools/go/types/typeutil/map.go
new file mode 100644
index 0000000..d144836
--- /dev/null
+++ b/third_party/go.tools/go/types/typeutil/map.go
@@ -0,0 +1,314 @@
+// Copyright 2014 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 typeutil defines various utilities for types, such as Map,
+// a mapping from types.Type to interface{} values.
+package typeutil
+
+import (
+	"bytes"
+	"fmt"
+	"reflect"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// Map is a hash-table-based mapping from types (types.Type) to
+// arbitrary interface{} values.  The concrete types that implement
+// the Type interface are pointers.  Since they are not canonicalized,
+// == cannot be used to check for equivalence, and thus we cannot
+// simply use a Go map.
+//
+// Just as with map[K]V, a nil *Map is a valid empty map.
+//
+// Not thread-safe.
+//
+type Map struct {
+	hasher Hasher             // shared by many Maps
+	table  map[uint32][]entry // maps hash to bucket; entry.key==nil means unused
+	length int                // number of map entries
+}
+
+// entry is an entry (key/value association) in a hash bucket.
+type entry struct {
+	key   types.Type
+	value interface{}
+}
+
+// SetHasher sets the hasher used by Map.
+//
+// All Hashers are functionally equivalent but contain internal state
+// used to cache the results of hashing previously seen types.
+//
+// A single Hasher created by MakeHasher() may be shared among many
+// Maps.  This is recommended if the instances have many keys in
+// common, as it will amortize the cost of hash computation.
+//
+// A Hasher may grow without bound as new types are seen.  Even when a
+// type is deleted from the map, the Hasher never shrinks, since other
+// types in the map may reference the deleted type indirectly.
+//
+// Hashers are not thread-safe, and read-only operations such as
+// Map.Lookup require updates to the hasher, so a full Mutex lock (not a
+// read-lock) is require around all Map operations if a shared
+// hasher is accessed from multiple threads.
+//
+// If SetHasher is not called, the Map will create a private hasher at
+// the first call to Insert.
+//
+func (m *Map) SetHasher(hasher Hasher) {
+	m.hasher = hasher
+}
+
+// Delete removes the entry with the given key, if any.
+// It returns true if the entry was found.
+//
+func (m *Map) Delete(key types.Type) bool {
+	if m != nil && m.table != nil {
+		hash := m.hasher.Hash(key)
+		bucket := m.table[hash]
+		for i, e := range bucket {
+			if e.key != nil && types.Identical(key, e.key) {
+				// We can't compact the bucket as it
+				// would disturb iterators.
+				bucket[i] = entry{}
+				m.length--
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// At returns the map entry for the given key.
+// The result is nil if the entry is not present.
+//
+func (m *Map) At(key types.Type) interface{} {
+	if m != nil && m.table != nil {
+		for _, e := range m.table[m.hasher.Hash(key)] {
+			if e.key != nil && types.Identical(key, e.key) {
+				return e.value
+			}
+		}
+	}
+	return nil
+}
+
+// Set sets the map entry for key to val,
+// and returns the previous entry, if any.
+func (m *Map) Set(key types.Type, value interface{}) (prev interface{}) {
+	if m.table != nil {
+		hash := m.hasher.Hash(key)
+		bucket := m.table[hash]
+		var hole *entry
+		for i, e := range bucket {
+			if e.key == nil {
+				hole = &bucket[i]
+			} else if types.Identical(key, e.key) {
+				prev = e.value
+				bucket[i].value = value
+				return
+			}
+		}
+
+		if hole != nil {
+			*hole = entry{key, value} // overwrite deleted entry
+		} else {
+			m.table[hash] = append(bucket, entry{key, value})
+		}
+	} else {
+		if m.hasher.memo == nil {
+			m.hasher = MakeHasher()
+		}
+		hash := m.hasher.Hash(key)
+		m.table = map[uint32][]entry{hash: {entry{key, value}}}
+	}
+
+	m.length++
+	return
+}
+
+// Len returns the number of map entries.
+func (m *Map) Len() int {
+	if m != nil {
+		return m.length
+	}
+	return 0
+}
+
+// Iterate calls function f on each entry in the map in unspecified order.
+//
+// If f should mutate the map, Iterate provides the same guarantees as
+// Go maps: if f deletes a map entry that Iterate has not yet reached,
+// f will not be invoked for it, but if f inserts a map entry that
+// Iterate has not yet reached, whether or not f will be invoked for
+// it is unspecified.
+//
+func (m *Map) Iterate(f func(key types.Type, value interface{})) {
+	if m != nil {
+		for _, bucket := range m.table {
+			for _, e := range bucket {
+				if e.key != nil {
+					f(e.key, e.value)
+				}
+			}
+		}
+	}
+}
+
+// Keys returns a new slice containing the set of map keys.
+// The order is unspecified.
+func (m *Map) Keys() []types.Type {
+	keys := make([]types.Type, 0, m.Len())
+	m.Iterate(func(key types.Type, _ interface{}) {
+		keys = append(keys, key)
+	})
+	return keys
+}
+
+func (m *Map) toString(values bool) string {
+	if m == nil {
+		return "{}"
+	}
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "{")
+	sep := ""
+	m.Iterate(func(key types.Type, value interface{}) {
+		fmt.Fprint(&buf, sep)
+		sep = ", "
+		fmt.Fprint(&buf, key)
+		if values {
+			fmt.Fprintf(&buf, ": %q", value)
+		}
+	})
+	fmt.Fprint(&buf, "}")
+	return buf.String()
+}
+
+// String returns a string representation of the map's entries.
+// Values are printed using fmt.Sprintf("%v", v).
+// Order is unspecified.
+//
+func (m *Map) String() string {
+	return m.toString(true)
+}
+
+// KeysString returns a string representation of the map's key set.
+// Order is unspecified.
+//
+func (m *Map) KeysString() string {
+	return m.toString(false)
+}
+
+////////////////////////////////////////////////////////////////////////
+// Hasher
+
+// A Hasher maps each type to its hash value.
+// For efficiency, a hasher uses memoization; thus its memory
+// footprint grows monotonically over time.
+// Hashers are not thread-safe.
+// Hashers have reference semantics.
+// Call MakeHasher to create a Hasher.
+type Hasher struct {
+	memo map[types.Type]uint32
+}
+
+// MakeHasher returns a new Hasher instance.
+func MakeHasher() Hasher {
+	return Hasher{make(map[types.Type]uint32)}
+}
+
+// Hash computes a hash value for the given type t such that
+// Identical(t, t') => Hash(t) == Hash(t').
+func (h Hasher) Hash(t types.Type) uint32 {
+	hash, ok := h.memo[t]
+	if !ok {
+		hash = h.hashFor(t)
+		h.memo[t] = hash
+	}
+	return hash
+}
+
+// hashString computes the Fowler–Noll–Vo hash of s.
+func hashString(s string) uint32 {
+	var h uint32
+	for i := 0; i < len(s); i++ {
+		h ^= uint32(s[i])
+		h *= 16777619
+	}
+	return h
+}
+
+// hashFor computes the hash of t.
+func (h Hasher) hashFor(t types.Type) uint32 {
+	// See Identical for rationale.
+	switch t := t.(type) {
+	case *types.Basic:
+		return uint32(t.Kind())
+
+	case *types.Array:
+		return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem())
+
+	case *types.Slice:
+		return 9049 + 2*h.Hash(t.Elem())
+
+	case *types.Struct:
+		var hash uint32 = 9059
+		for i, n := 0, t.NumFields(); i < n; i++ {
+			f := t.Field(i)
+			if f.Anonymous() {
+				hash += 8861
+			}
+			hash += hashString(t.Tag(i))
+			hash += hashString(f.Name()) // (ignore f.Pkg)
+			hash += h.Hash(f.Type())
+		}
+		return hash
+
+	case *types.Pointer:
+		return 9067 + 2*h.Hash(t.Elem())
+
+	case *types.Signature:
+		var hash uint32 = 9091
+		if t.Variadic() {
+			hash *= 8863
+		}
+		return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results())
+
+	case *types.Interface:
+		var hash uint32 = 9103
+		for i, n := 0, t.NumMethods(); i < n; i++ {
+			// See go/types.identicalMethods for rationale.
+			// Method order is not significant.
+			// Ignore m.Pkg().
+			m := t.Method(i)
+			hash += 3*hashString(m.Name()) + 5*h.Hash(m.Type())
+		}
+		return hash
+
+	case *types.Map:
+		return 9109 + 2*h.Hash(t.Key()) + 3*h.Hash(t.Elem())
+
+	case *types.Chan:
+		return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem())
+
+	case *types.Named:
+		// Not safe with a copying GC; objects may move.
+		return uint32(reflect.ValueOf(t.Obj()).Pointer())
+
+	case *types.Tuple:
+		return h.hashTuple(t)
+	}
+	panic(t)
+}
+
+func (h Hasher) hashTuple(tuple *types.Tuple) uint32 {
+	// See go/types.identicalTypes for rationale.
+	n := tuple.Len()
+	var hash uint32 = 9137 + 2*uint32(n)
+	for i := 0; i < n; i++ {
+		hash += 3 * h.Hash(tuple.At(i).Type())
+	}
+	return hash
+}
diff --git a/third_party/go.tools/go/types/typeutil/map_test.go b/third_party/go.tools/go/types/typeutil/map_test.go
new file mode 100644
index 0000000..cd200f5
--- /dev/null
+++ b/third_party/go.tools/go/types/typeutil/map_test.go
@@ -0,0 +1,174 @@
+// Copyright 2014 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 typeutil_test
+
+// TODO(adonovan):
+// - test use of explicit hasher across two maps.
+// - test hashcodes are consistent with equals for a range of types
+//   (e.g. all types generated by type-checking some body of real code).
+
+import (
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+var (
+	tStr      = types.Typ[types.String]             // string
+	tPStr1    = types.NewPointer(tStr)              // *string
+	tPStr2    = types.NewPointer(tStr)              // *string, again
+	tInt      = types.Typ[types.Int]                // int
+	tChanInt1 = types.NewChan(types.RecvOnly, tInt) // <-chan int
+	tChanInt2 = types.NewChan(types.RecvOnly, tInt) // <-chan int, again
+)
+
+func checkEqualButNotIdentical(t *testing.T, x, y types.Type, comment string) {
+	if !types.Identical(x, y) {
+		t.Errorf("%s: not equal: %s, %s", comment, x, y)
+	}
+	if x == y {
+		t.Errorf("%s: identical: %v, %v", comment, x, y)
+	}
+}
+
+func TestAxioms(t *testing.T) {
+	checkEqualButNotIdentical(t, tPStr1, tPStr2, "tPstr{1,2}")
+	checkEqualButNotIdentical(t, tChanInt1, tChanInt2, "tChanInt{1,2}")
+}
+
+func TestMap(t *testing.T) {
+	var tmap *typeutil.Map
+
+	// All methods but Set are safe on on (*T)(nil).
+	tmap.Len()
+	tmap.At(tPStr1)
+	tmap.Delete(tPStr1)
+	tmap.KeysString()
+	tmap.String()
+
+	tmap = new(typeutil.Map)
+
+	// Length of empty map.
+	if l := tmap.Len(); l != 0 {
+		t.Errorf("Len() on empty Map: got %d, want 0", l)
+	}
+	// At of missing key.
+	if v := tmap.At(tPStr1); v != nil {
+		t.Errorf("At() on empty Map: got %v, want nil", v)
+	}
+	// Deletion of missing key.
+	if tmap.Delete(tPStr1) {
+		t.Errorf("Delete() on empty Map: got true, want false")
+	}
+	// Set of new key.
+	if prev := tmap.Set(tPStr1, "*string"); prev != nil {
+		t.Errorf("Set() on empty Map returned non-nil previous value %s", prev)
+	}
+
+	// Now: {*string: "*string"}
+
+	// Length of non-empty map.
+	if l := tmap.Len(); l != 1 {
+		t.Errorf("Len(): got %d, want 1", l)
+	}
+	// At via insertion key.
+	if v := tmap.At(tPStr1); v != "*string" {
+		t.Errorf("At(): got %q, want \"*string\"", v)
+	}
+	// At via equal key.
+	if v := tmap.At(tPStr2); v != "*string" {
+		t.Errorf("At(): got %q, want \"*string\"", v)
+	}
+	// Iteration over sole entry.
+	tmap.Iterate(func(key types.Type, value interface{}) {
+		if key != tPStr1 {
+			t.Errorf("Iterate: key: got %s, want %s", key, tPStr1)
+		}
+		if want := "*string"; value != want {
+			t.Errorf("Iterate: value: got %s, want %s", value, want)
+		}
+	})
+
+	// Setion with key equal to present one.
+	if prev := tmap.Set(tPStr2, "*string again"); prev != "*string" {
+		t.Errorf("Set() previous value: got %s, want \"*string\"", prev)
+	}
+
+	// Setion of another association.
+	if prev := tmap.Set(tChanInt1, "<-chan int"); prev != nil {
+		t.Errorf("Set() previous value: got %s, want nil", prev)
+	}
+
+	// Now: {*string: "*string again", <-chan int: "<-chan int"}
+
+	want1 := "{*string: \"*string again\", <-chan int: \"<-chan int\"}"
+	want2 := "{<-chan int: \"<-chan int\", *string: \"*string again\"}"
+	if s := tmap.String(); s != want1 && s != want2 {
+		t.Errorf("String(): got %s, want %s", s, want1)
+	}
+
+	want1 = "{*string, <-chan int}"
+	want2 = "{<-chan int, *string}"
+	if s := tmap.KeysString(); s != want1 && s != want2 {
+		t.Errorf("KeysString(): got %s, want %s", s, want1)
+	}
+
+	// Keys().
+	I := types.Identical
+	switch k := tmap.Keys(); {
+	case I(k[0], tChanInt1) && I(k[1], tPStr1): // ok
+	case I(k[1], tChanInt1) && I(k[0], tPStr1): // ok
+	default:
+		t.Errorf("Keys(): got %v, want %s", k, want2)
+	}
+
+	if l := tmap.Len(); l != 2 {
+		t.Errorf("Len(): got %d, want 1", l)
+	}
+	// At via original key.
+	if v := tmap.At(tPStr1); v != "*string again" {
+		t.Errorf("At(): got %q, want \"*string again\"", v)
+	}
+	hamming := 1
+	tmap.Iterate(func(key types.Type, value interface{}) {
+		switch {
+		case I(key, tChanInt1):
+			hamming *= 2 // ok
+		case I(key, tPStr1):
+			hamming *= 3 // ok
+		}
+	})
+	if hamming != 6 {
+		t.Errorf("Iterate: hamming: got %d, want %d", hamming, 6)
+	}
+
+	if v := tmap.At(tChanInt2); v != "<-chan int" {
+		t.Errorf("At(): got %q, want \"<-chan int\"", v)
+	}
+	// Deletion with key equal to present one.
+	if !tmap.Delete(tChanInt2) {
+		t.Errorf("Delete() of existing key: got false, want true")
+	}
+
+	// Now: {*string: "*string again"}
+
+	if l := tmap.Len(); l != 1 {
+		t.Errorf("Len(): got %d, want 1", l)
+	}
+	// Deletion again.
+	if !tmap.Delete(tPStr2) {
+		t.Errorf("Delete() of existing key: got false, want true")
+	}
+
+	// Now: {}
+
+	if l := tmap.Len(); l != 0 {
+		t.Errorf("Len(): got %d, want %d", l, 0)
+	}
+	if s := tmap.String(); s != "{}" {
+		t.Errorf("Len(): got %q, want %q", s, "")
+	}
+}
diff --git a/third_party/go.tools/go/types/typeutil/ui.go b/third_party/go.tools/go/types/typeutil/ui.go
new file mode 100644
index 0000000..0eb20fa
--- /dev/null
+++ b/third_party/go.tools/go/types/typeutil/ui.go
@@ -0,0 +1,38 @@
+// Copyright 2014 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 typeutil
+
+// This file defines utilities for user interfaces that display types.
+
+import "llvm.org/llgo/third_party/go.tools/go/types"
+
+// IntuitiveMethodSet returns the intuitive method set of a type, T.
+//
+// The result contains MethodSet(T) and additionally, if T is a
+// concrete type, methods belonging to *T if there is no identically
+// named method on T itself.  This corresponds to user intuition about
+// method sets; this function is intended only for user interfaces.
+//
+// The order of the result is as for types.MethodSet(T).
+//
+func IntuitiveMethodSet(T types.Type, msets *types.MethodSetCache) []*types.Selection {
+	var result []*types.Selection
+	mset := msets.MethodSet(T)
+	if _, ok := T.Underlying().(*types.Interface); ok {
+		for i, n := 0, mset.Len(); i < n; i++ {
+			result = append(result, mset.At(i))
+		}
+	} else {
+		pmset := msets.MethodSet(types.NewPointer(T))
+		for i, n := 0, pmset.Len(); i < n; i++ {
+			meth := pmset.At(i)
+			if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil {
+				meth = m
+			}
+			result = append(result, meth)
+		}
+	}
+	return result
+}
diff --git a/third_party/go.tools/go/types/typexpr.go b/third_party/go.tools/go/types/typexpr.go
new file mode 100644
index 0000000..2470aa7
--- /dev/null
+++ b/third_party/go.tools/go/types/typexpr.go
@@ -0,0 +1,721 @@
+// Copyright 2013 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.
+
+// This file implements type-checking of identifiers and type expressions.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+	"sort"
+	"strconv"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+// ident type-checks identifier e and initializes x with the value or type of e.
+// If an error occurred, x.mode is set to invalid.
+// For the meaning of def and path, see check.typ, below.
+//
+func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeName) {
+	x.mode = invalid
+	x.expr = e
+
+	scope, obj := check.scope.LookupParent(e.Name)
+	if obj == nil {
+		if e.Name == "_" {
+			check.errorf(e.Pos(), "cannot use _ as value or type")
+		} else {
+			check.errorf(e.Pos(), "undeclared name: %s", e.Name)
+		}
+		return
+	}
+	check.recordUse(e, obj)
+
+	check.objDecl(obj, def, path)
+	typ := obj.Type()
+	assert(typ != nil)
+
+	// The object may be dot-imported: If so, remove its package from
+	// the map of unused dot imports for the respective file scope.
+	// (This code is only needed for dot-imports. Without them,
+	// we only have to mark variables, see *Var case below).
+	if pkg := obj.Pkg(); pkg != check.pkg && pkg != nil {
+		delete(check.unusedDotImports[scope], pkg)
+	}
+
+	switch obj := obj.(type) {
+	case *PkgName:
+		check.errorf(e.Pos(), "use of package %s not in selector", obj.name)
+		return
+
+	case *Const:
+		check.addDeclDep(obj)
+		if typ == Typ[Invalid] {
+			return
+		}
+		if obj == universeIota {
+			if check.iota == nil {
+				check.errorf(e.Pos(), "cannot use iota outside constant declaration")
+				return
+			}
+			x.val = check.iota
+		} else {
+			x.val = obj.val
+		}
+		assert(x.val != nil)
+		x.mode = constant
+
+	case *TypeName:
+		x.mode = typexpr
+		// check for cycle
+		// (it's ok to iterate forward because each named type appears at most once in path)
+		for i, prev := range path {
+			if prev == obj {
+				check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name)
+				// print cycle
+				for _, obj := range path[i:] {
+					check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
+				}
+				check.errorf(obj.Pos(), "\t%s", obj.Name())
+				// maintain x.mode == typexpr despite error
+				typ = Typ[Invalid]
+				break
+			}
+		}
+
+	case *Var:
+		if obj.pkg == check.pkg {
+			obj.used = true
+		}
+		check.addDeclDep(obj)
+		if typ == Typ[Invalid] {
+			return
+		}
+		x.mode = variable
+
+	case *Func:
+		check.addDeclDep(obj)
+		x.mode = value
+
+	case *Builtin:
+		x.id = obj.id
+		x.mode = builtin
+
+	case *Nil:
+		x.mode = value
+
+	default:
+		unreachable()
+	}
+
+	x.typ = typ
+}
+
+// typExpr type-checks the type expression e and returns its type, or Typ[Invalid].
+// If def != nil, e is the type specification for the named type def, declared
+// in a type declaration, and def.underlying will be set to the type of e before
+// any components of e are type-checked. Path contains the path of named types
+// referring to this type.
+//
+func (check *Checker) typExpr(e ast.Expr, def *Named, path []*TypeName) (T Type) {
+	if trace {
+		check.trace(e.Pos(), "%s", e)
+		check.indent++
+		defer func() {
+			check.indent--
+			check.trace(e.Pos(), "=> %s", T)
+		}()
+	}
+
+	T = check.typExprInternal(e, def, path)
+	assert(isTyped(T))
+	check.recordTypeAndValue(e, typexpr, T, nil)
+
+	return
+}
+
+func (check *Checker) typ(e ast.Expr) Type {
+	return check.typExpr(e, nil, nil)
+}
+
+// funcType type-checks a function or method type and returns its signature.
+func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) *Signature {
+	scope := NewScope(check.scope, "function")
+	check.recordScope(ftyp, scope)
+
+	recvList, _ := check.collectParams(scope, recvPar, false)
+	params, variadic := check.collectParams(scope, ftyp.Params, true)
+	results, _ := check.collectParams(scope, ftyp.Results, false)
+
+	if recvPar != nil {
+		// recv parameter list present (may be empty)
+		// spec: "The receiver is specified via an extra parameter section preceeding the
+		// method name. That parameter section must declare a single parameter, the receiver."
+		var recv *Var
+		switch len(recvList) {
+		case 0:
+			check.error(recvPar.Pos(), "method is missing receiver")
+			recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
+		default:
+			// more than one receiver
+			check.error(recvList[len(recvList)-1].Pos(), "method must have exactly one receiver")
+			fallthrough // continue with first receiver
+		case 1:
+			recv = recvList[0]
+		}
+		// spec: "The receiver type must be of the form T or *T where T is a type name."
+		// (ignore invalid types - error was reported before)
+		if t, _ := deref(recv.typ); t != Typ[Invalid] {
+			var err string
+			if T, _ := t.(*Named); T != nil {
+				// spec: "The type denoted by T is called the receiver base type; it must not
+				// be a pointer or interface type and it must be declared in the same package
+				// as the method."
+				if T.obj.pkg != check.pkg {
+					err = "type not defined in this package"
+				} else {
+					// TODO(gri) This is not correct if the underlying type is unknown yet.
+					switch u := T.underlying.(type) {
+					case *Basic:
+						// unsafe.Pointer is treated like a regular pointer
+						if u.kind == UnsafePointer {
+							err = "unsafe.Pointer"
+						}
+					case *Pointer, *Interface:
+						err = "pointer or interface type"
+					}
+				}
+			} else {
+				err = "basic or unnamed type"
+			}
+			if err != "" {
+				check.errorf(recv.pos, "invalid receiver %s (%s)", recv.typ, err)
+				// ok to continue
+			}
+		}
+		sig.recv = recv
+	}
+
+	sig.scope = scope
+	sig.params = NewTuple(params...)
+	sig.results = NewTuple(results...)
+	sig.variadic = variadic
+
+	return sig
+}
+
+// typExprInternal drives type checking of types.
+// Must only be called by typExpr.
+//
+func (check *Checker) typExprInternal(e ast.Expr, def *Named, path []*TypeName) Type {
+	switch e := e.(type) {
+	case *ast.BadExpr:
+		// ignore - error reported before
+
+	case *ast.Ident:
+		var x operand
+		check.ident(&x, e, def, path)
+
+		switch x.mode {
+		case typexpr:
+			typ := x.typ
+			def.setUnderlying(typ)
+			return typ
+		case invalid:
+			// ignore - error reported before
+		case novalue:
+			check.errorf(x.pos(), "%s used as type", &x)
+		default:
+			check.errorf(x.pos(), "%s is not a type", &x)
+		}
+
+	case *ast.SelectorExpr:
+		var x operand
+		check.selector(&x, e)
+
+		switch x.mode {
+		case typexpr:
+			typ := x.typ
+			def.setUnderlying(typ)
+			return typ
+		case invalid:
+			// ignore - error reported before
+		case novalue:
+			check.errorf(x.pos(), "%s used as type", &x)
+		default:
+			check.errorf(x.pos(), "%s is not a type", &x)
+		}
+
+	case *ast.ParenExpr:
+		return check.typExpr(e.X, def, path)
+
+	case *ast.ArrayType:
+		if e.Len != nil {
+			typ := new(Array)
+			def.setUnderlying(typ)
+			typ.len = check.arrayLength(e.Len)
+			typ.elem = check.typExpr(e.Elt, nil, path)
+			return typ
+
+		} else {
+			typ := new(Slice)
+			def.setUnderlying(typ)
+			typ.elem = check.typ(e.Elt)
+			return typ
+		}
+
+	case *ast.StructType:
+		typ := new(Struct)
+		def.setUnderlying(typ)
+		check.structType(typ, e, path)
+		return typ
+
+	case *ast.StarExpr:
+		typ := new(Pointer)
+		def.setUnderlying(typ)
+		typ.base = check.typ(e.X)
+		return typ
+
+	case *ast.FuncType:
+		typ := new(Signature)
+		def.setUnderlying(typ)
+		check.funcType(typ, nil, e)
+		return typ
+
+	case *ast.InterfaceType:
+		typ := new(Interface)
+		def.setUnderlying(typ)
+		check.interfaceType(typ, e, def, path)
+		return typ
+
+	case *ast.MapType:
+		typ := new(Map)
+		def.setUnderlying(typ)
+
+		typ.key = check.typ(e.Key)
+		typ.elem = check.typ(e.Value)
+
+		// spec: "The comparison operators == and != must be fully defined
+		// for operands of the key type; thus the key type must not be a
+		// function, map, or slice."
+		//
+		// Delay this check because it requires fully setup types;
+		// it is safe to continue in any case (was issue 6667).
+		check.delay(func() {
+			if !Comparable(typ.key) {
+				check.errorf(e.Key.Pos(), "invalid map key type %s", typ.key)
+			}
+		})
+
+		return typ
+
+	case *ast.ChanType:
+		typ := new(Chan)
+		def.setUnderlying(typ)
+
+		dir := SendRecv
+		switch e.Dir {
+		case ast.SEND | ast.RECV:
+			// nothing to do
+		case ast.SEND:
+			dir = SendOnly
+		case ast.RECV:
+			dir = RecvOnly
+		default:
+			check.invalidAST(e.Pos(), "unknown channel direction %d", e.Dir)
+			// ok to continue
+		}
+
+		typ.dir = dir
+		typ.elem = check.typ(e.Value)
+		return typ
+
+	default:
+		check.errorf(e.Pos(), "%s is not a type", e)
+	}
+
+	typ := Typ[Invalid]
+	def.setUnderlying(typ)
+	return typ
+}
+
+// typeOrNil type-checks the type expression (or nil value) e
+// and returns the typ of e, or nil.
+// If e is neither a type nor nil, typOrNil returns Typ[Invalid].
+//
+func (check *Checker) typOrNil(e ast.Expr) Type {
+	var x operand
+	check.rawExpr(&x, e, nil)
+	switch x.mode {
+	case invalid:
+		// ignore - error reported before
+	case novalue:
+		check.errorf(x.pos(), "%s used as type", &x)
+	case typexpr:
+		return x.typ
+	case value:
+		if x.isNil() {
+			return nil
+		}
+		fallthrough
+	default:
+		check.errorf(x.pos(), "%s is not a type", &x)
+	}
+	return Typ[Invalid]
+}
+
+func (check *Checker) arrayLength(e ast.Expr) int64 {
+	var x operand
+	check.expr(&x, e)
+	if x.mode != constant {
+		if x.mode != invalid {
+			check.errorf(x.pos(), "array length %s must be constant", &x)
+		}
+		return 0
+	}
+	if !x.isInteger() {
+		check.errorf(x.pos(), "array length %s must be integer", &x)
+		return 0
+	}
+	n, ok := exact.Int64Val(x.val)
+	if !ok || n < 0 {
+		check.errorf(x.pos(), "invalid array length %s", &x)
+		return 0
+	}
+	return n
+}
+
+func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {
+	if list == nil {
+		return
+	}
+
+	var named, anonymous bool
+	for i, field := range list.List {
+		ftype := field.Type
+		if t, _ := ftype.(*ast.Ellipsis); t != nil {
+			ftype = t.Elt
+			if variadicOk && i == len(list.List)-1 {
+				variadic = true
+			} else {
+				check.invalidAST(field.Pos(), "... not permitted")
+				// ignore ... and continue
+			}
+		}
+		typ := check.typ(ftype)
+		// The parser ensures that f.Tag is nil and we don't
+		// care if a constructed AST contains a non-nil tag.
+		if len(field.Names) > 0 {
+			// named parameter
+			for _, name := range field.Names {
+				if name.Name == "" {
+					check.invalidAST(name.Pos(), "anonymous parameter")
+					// ok to continue
+				}
+				par := NewParam(name.Pos(), check.pkg, name.Name, typ)
+				check.declare(scope, name, par)
+				params = append(params, par)
+			}
+			named = true
+		} else {
+			// anonymous parameter
+			par := NewParam(ftype.Pos(), check.pkg, "", typ)
+			check.recordImplicit(field, par)
+			params = append(params, par)
+			anonymous = true
+		}
+	}
+
+	if named && anonymous {
+		check.invalidAST(list.Pos(), "list contains both named and anonymous parameters")
+		// ok to continue
+	}
+
+	// For a variadic function, change the last parameter's type from T to []T.
+	if variadic && len(params) > 0 {
+		last := params[len(params)-1]
+		last.typ = &Slice{elem: last.typ}
+	}
+
+	return
+}
+
+func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool {
+	if alt := oset.insert(obj); alt != nil {
+		check.errorf(pos, "%s redeclared", obj.Name())
+		check.reportAltDecl(alt)
+		return false
+	}
+	return true
+}
+
+func (check *Checker) interfaceType(iface *Interface, ityp *ast.InterfaceType, def *Named, path []*TypeName) {
+	// empty interface: common case
+	if ityp.Methods == nil {
+		return
+	}
+
+	// The parser ensures that field tags are nil and we don't
+	// care if a constructed AST contains non-nil tags.
+
+	// use named receiver type if available (for better error messages)
+	var recvTyp Type = iface
+	if def != nil {
+		recvTyp = def
+	}
+
+	// Phase 1: Collect explicitly declared methods, the corresponding
+	//          signature (AST) expressions, and the list of embedded
+	//          type (AST) expressions. Do not resolve signatures or
+	//          embedded types yet to avoid cycles referring to this
+	//          interface.
+
+	var (
+		mset       objset
+		signatures []ast.Expr // list of corresponding method signatures
+		embedded   []ast.Expr // list of embedded types
+	)
+	for _, f := range ityp.Methods.List {
+		if len(f.Names) > 0 {
+			// The parser ensures that there's only one method
+			// and we don't care if a constructed AST has more.
+			name := f.Names[0]
+			pos := name.Pos()
+			// spec: "As with all method sets, in an interface type,
+			// each method must have a unique non-blank name."
+			if name.Name == "_" {
+				check.errorf(pos, "invalid method name _")
+				continue
+			}
+			// Don't type-check signature yet - use an
+			// empty signature now and update it later.
+			// Since we know the receiver, set it up now
+			// (required to avoid crash in ptrRecv; see
+			// e.g. test case for issue 6638).
+			// TODO(gri) Consider marking methods signatures
+			// as incomplete, for better error messages. See
+			// also the T4 and T5 tests in testdata/cycles2.src.
+			sig := new(Signature)
+			sig.recv = NewVar(pos, check.pkg, "", recvTyp)
+			m := NewFunc(pos, check.pkg, name.Name, sig)
+			if check.declareInSet(&mset, pos, m) {
+				iface.methods = append(iface.methods, m)
+				iface.allMethods = append(iface.allMethods, m)
+				signatures = append(signatures, f.Type)
+				check.recordDef(name, m)
+			}
+		} else {
+			// embedded type
+			embedded = append(embedded, f.Type)
+		}
+	}
+
+	// Phase 2: Resolve embedded interfaces. Because an interface must not
+	//          embed itself (directly or indirectly), each embedded interface
+	//          can be fully resolved without depending on any method of this
+	//          interface (if there is a cycle or another error, the embedded
+	//          type resolves to an invalid type and is ignored).
+	//          In particular, the list of methods for each embedded interface
+	//          must be complete (it cannot depend on this interface), and so
+	//          those methods can be added to the list of all methods of this
+	//          interface.
+
+	for _, e := range embedded {
+		pos := e.Pos()
+		typ := check.typExpr(e, nil, path)
+		named, _ := typ.(*Named)
+		if named == nil {
+			if typ != Typ[Invalid] {
+				check.invalidAST(pos, "%s is not named type", typ)
+			}
+			continue
+		}
+		// determine underlying (possibly incomplete) type
+		// by following its forward chain
+		u := underlying(named)
+		embed, _ := u.(*Interface)
+		if embed == nil {
+			if u != Typ[Invalid] {
+				check.errorf(pos, "%s is not an interface", named)
+			}
+			continue
+		}
+		iface.embeddeds = append(iface.embeddeds, named)
+		// collect embedded methods
+		for _, m := range embed.allMethods {
+			if check.declareInSet(&mset, pos, m) {
+				iface.allMethods = append(iface.allMethods, m)
+			}
+		}
+	}
+
+	// Phase 3: At this point all methods have been collected for this interface.
+	//          It is now safe to type-check the signatures of all explicitly
+	//          declared methods, even if they refer to this interface via a cycle
+	//          and embed the methods of this interface in a parameter of interface
+	//          type.
+
+	for i, m := range iface.methods {
+		expr := signatures[i]
+		typ := check.typ(expr)
+		sig, _ := typ.(*Signature)
+		if sig == nil {
+			if typ != Typ[Invalid] {
+				check.invalidAST(expr.Pos(), "%s is not a method signature", typ)
+			}
+			continue // keep method with empty method signature
+		}
+		// update signature, but keep recv that was set up before
+		old := m.typ.(*Signature)
+		sig.recv = old.recv
+		*old = *sig // update signature (don't replace it!)
+	}
+
+	// TODO(gri) The list of explicit methods is only sorted for now to
+	// produce the same Interface as NewInterface. We may be able to
+	// claim source order in the future. Revisit.
+	sort.Sort(byUniqueMethodName(iface.methods))
+
+	// TODO(gri) The list of embedded types is only sorted for now to
+	// produce the same Interface as NewInterface. We may be able to
+	// claim source order in the future. Revisit.
+	sort.Sort(byUniqueTypeName(iface.embeddeds))
+
+	sort.Sort(byUniqueMethodName(iface.allMethods))
+}
+
+// byUniqueTypeName named type lists can be sorted by their unique type names.
+type byUniqueTypeName []*Named
+
+func (a byUniqueTypeName) Len() int           { return len(a) }
+func (a byUniqueTypeName) Less(i, j int) bool { return a[i].obj.Id() < a[j].obj.Id() }
+func (a byUniqueTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+// byUniqueMethodName method lists can be sorted by their unique method names.
+type byUniqueMethodName []*Func
+
+func (a byUniqueMethodName) Len() int           { return len(a) }
+func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() }
+func (a byUniqueMethodName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+func (check *Checker) tag(t *ast.BasicLit) string {
+	if t != nil {
+		if t.Kind == token.STRING {
+			if val, err := strconv.Unquote(t.Value); err == nil {
+				return val
+			}
+		}
+		check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value)
+	}
+	return ""
+}
+
+func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeName) {
+	list := e.Fields
+	if list == nil {
+		return
+	}
+
+	// struct fields and tags
+	var fields []*Var
+	var tags []string
+
+	// for double-declaration checks
+	var fset objset
+
+	// current field typ and tag
+	var typ Type
+	var tag string
+	// anonymous != nil indicates an anonymous field.
+	add := func(field *ast.Field, ident *ast.Ident, anonymous *TypeName, pos token.Pos) {
+		if tag != "" && tags == nil {
+			tags = make([]string, len(fields))
+		}
+		if tags != nil {
+			tags = append(tags, tag)
+		}
+
+		name := ident.Name
+		fld := NewField(pos, check.pkg, name, typ, anonymous != nil)
+		// spec: "Within a struct, non-blank field names must be unique."
+		if name == "_" || check.declareInSet(&fset, pos, fld) {
+			fields = append(fields, fld)
+			check.recordDef(ident, fld)
+		}
+		if anonymous != nil {
+			check.recordUse(ident, anonymous)
+		}
+	}
+
+	for _, f := range list.List {
+		typ = check.typExpr(f.Type, nil, path)
+		tag = check.tag(f.Tag)
+		if len(f.Names) > 0 {
+			// named fields
+			for _, name := range f.Names {
+				add(f, name, nil, name.Pos())
+			}
+		} else {
+			// anonymous field
+			name := anonymousFieldIdent(f.Type)
+			pos := f.Type.Pos()
+			t, isPtr := deref(typ)
+			switch t := t.(type) {
+			case *Basic:
+				if t == Typ[Invalid] {
+					// error was reported before
+					continue
+				}
+				// unsafe.Pointer is treated like a regular pointer
+				if t.kind == UnsafePointer {
+					check.errorf(pos, "anonymous field type cannot be unsafe.Pointer")
+					continue
+				}
+				add(f, name, Universe.Lookup(t.name).(*TypeName), pos)
+
+			case *Named:
+				// spec: "An embedded type must be specified as a type name
+				// T or as a pointer to a non-interface type name *T, and T
+				// itself may not be a pointer type."
+				switch u := t.underlying.(type) {
+				case *Basic:
+					// unsafe.Pointer is treated like a regular pointer
+					if u.kind == UnsafePointer {
+						check.errorf(pos, "anonymous field type cannot be unsafe.Pointer")
+						continue
+					}
+				case *Pointer:
+					check.errorf(pos, "anonymous field type cannot be a pointer")
+					continue
+				case *Interface:
+					if isPtr {
+						check.errorf(pos, "anonymous field type cannot be a pointer to an interface")
+						continue
+					}
+				}
+				add(f, name, t.obj, pos)
+
+			default:
+				check.invalidAST(pos, "anonymous field type %s must be named", typ)
+			}
+		}
+	}
+
+	styp.fields = fields
+	styp.tags = tags
+}
+
+func anonymousFieldIdent(e ast.Expr) *ast.Ident {
+	switch e := e.(type) {
+	case *ast.Ident:
+		return e
+	case *ast.StarExpr:
+		return anonymousFieldIdent(e.X)
+	case *ast.SelectorExpr:
+		return e.Sel
+	}
+	return nil // invalid anonymous field
+}
diff --git a/third_party/go.tools/go/types/universe.go b/third_party/go.tools/go/types/universe.go
new file mode 100644
index 0000000..1ab78b7
--- /dev/null
+++ b/third_party/go.tools/go/types/universe.go
@@ -0,0 +1,224 @@
+// 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.
+
+// This file implements the universe and unsafe package scopes.
+
+package types
+
+import (
+	"go/token"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+)
+
+var (
+	Universe     *Scope
+	Unsafe       *Package
+	universeIota *Const
+	UniverseByte *Basic // uint8 alias, but has name "byte"
+	UniverseRune *Basic // int32 alias, but has name "rune"
+)
+
+var Typ = [...]*Basic{
+	Invalid: {Invalid, 0, "invalid type"},
+
+	Bool:          {Bool, IsBoolean, "bool"},
+	Int:           {Int, IsInteger, "int"},
+	Int8:          {Int8, IsInteger, "int8"},
+	Int16:         {Int16, IsInteger, "int16"},
+	Int32:         {Int32, IsInteger, "int32"},
+	Int64:         {Int64, IsInteger, "int64"},
+	Uint:          {Uint, IsInteger | IsUnsigned, "uint"},
+	Uint8:         {Uint8, IsInteger | IsUnsigned, "uint8"},
+	Uint16:        {Uint16, IsInteger | IsUnsigned, "uint16"},
+	Uint32:        {Uint32, IsInteger | IsUnsigned, "uint32"},
+	Uint64:        {Uint64, IsInteger | IsUnsigned, "uint64"},
+	Uintptr:       {Uintptr, IsInteger | IsUnsigned, "uintptr"},
+	Float32:       {Float32, IsFloat, "float32"},
+	Float64:       {Float64, IsFloat, "float64"},
+	Complex64:     {Complex64, IsComplex, "complex64"},
+	Complex128:    {Complex128, IsComplex, "complex128"},
+	String:        {String, IsString, "string"},
+	UnsafePointer: {UnsafePointer, 0, "Pointer"},
+
+	UntypedBool:    {UntypedBool, IsBoolean | IsUntyped, "untyped bool"},
+	UntypedInt:     {UntypedInt, IsInteger | IsUntyped, "untyped int"},
+	UntypedRune:    {UntypedRune, IsInteger | IsUntyped, "untyped rune"},
+	UntypedFloat:   {UntypedFloat, IsFloat | IsUntyped, "untyped float"},
+	UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, "untyped complex"},
+	UntypedString:  {UntypedString, IsString | IsUntyped, "untyped string"},
+	UntypedNil:     {UntypedNil, IsUntyped, "untyped nil"},
+}
+
+var aliases = [...]*Basic{
+	{Byte, IsInteger | IsUnsigned, "byte"},
+	{Rune, IsInteger, "rune"},
+}
+
+func defPredeclaredTypes() {
+	for _, t := range Typ {
+		def(NewTypeName(token.NoPos, nil, t.name, t))
+	}
+	for _, t := range aliases {
+		def(NewTypeName(token.NoPos, nil, t.name, t))
+	}
+
+	// Error has a nil package in its qualified name since it is in no package
+	res := NewVar(token.NoPos, nil, "", Typ[String])
+	sig := &Signature{results: NewTuple(res)}
+	err := NewFunc(token.NoPos, nil, "Error", sig)
+	typ := &Named{underlying: NewInterface([]*Func{err}, nil).Complete()}
+	sig.recv = NewVar(token.NoPos, nil, "", typ)
+	def(NewTypeName(token.NoPos, nil, "error", typ))
+}
+
+var predeclaredConsts = [...]struct {
+	name string
+	kind BasicKind
+	val  exact.Value
+}{
+	{"true", UntypedBool, exact.MakeBool(true)},
+	{"false", UntypedBool, exact.MakeBool(false)},
+	{"iota", UntypedInt, exact.MakeInt64(0)},
+}
+
+func defPredeclaredConsts() {
+	for _, c := range predeclaredConsts {
+		def(NewConst(token.NoPos, nil, c.name, Typ[c.kind], c.val))
+	}
+}
+
+func defPredeclaredNil() {
+	def(&Nil{object{name: "nil", typ: Typ[UntypedNil]}})
+}
+
+// A builtinId is the id of a builtin function.
+type builtinId int
+
+const (
+	// universe scope
+	_Append builtinId = iota
+	_Cap
+	_Close
+	_Complex
+	_Copy
+	_Delete
+	_Imag
+	_Len
+	_Make
+	_New
+	_Panic
+	_Print
+	_Println
+	_Real
+	_Recover
+
+	// package unsafe
+	_Alignof
+	_Offsetof
+	_Sizeof
+
+	// testing support
+	_Assert
+	_Trace
+)
+
+var predeclaredFuncs = [...]struct {
+	name     string
+	nargs    int
+	variadic bool
+	kind     exprKind
+}{
+	_Append:  {"append", 1, true, expression},
+	_Cap:     {"cap", 1, false, expression},
+	_Close:   {"close", 1, false, statement},
+	_Complex: {"complex", 2, false, expression},
+	_Copy:    {"copy", 2, false, statement},
+	_Delete:  {"delete", 2, false, statement},
+	_Imag:    {"imag", 1, false, expression},
+	_Len:     {"len", 1, false, expression},
+	_Make:    {"make", 1, true, expression},
+	_New:     {"new", 1, false, expression},
+	_Panic:   {"panic", 1, false, statement},
+	_Print:   {"print", 0, true, statement},
+	_Println: {"println", 0, true, statement},
+	_Real:    {"real", 1, false, expression},
+	_Recover: {"recover", 0, false, statement},
+
+	_Alignof:  {"Alignof", 1, false, expression},
+	_Offsetof: {"Offsetof", 1, false, expression},
+	_Sizeof:   {"Sizeof", 1, false, expression},
+
+	_Assert: {"assert", 1, false, statement},
+	_Trace:  {"trace", 0, true, statement},
+}
+
+func defPredeclaredFuncs() {
+	for i := range predeclaredFuncs {
+		id := builtinId(i)
+		if id == _Assert || id == _Trace {
+			continue // only define these in testing environment
+		}
+		def(newBuiltin(id))
+	}
+}
+
+// DefPredeclaredTestFuncs defines the assert and trace built-ins.
+// These built-ins are intended for debugging and testing of this
+// package only.
+func DefPredeclaredTestFuncs() {
+	if Universe.Lookup("assert") != nil {
+		return // already defined
+	}
+	def(newBuiltin(_Assert))
+	def(newBuiltin(_Trace))
+}
+
+func init() {
+	Universe = NewScope(nil, "universe")
+	Unsafe = NewPackage("unsafe", "unsafe")
+	Unsafe.complete = true
+
+	defPredeclaredTypes()
+	defPredeclaredConsts()
+	defPredeclaredNil()
+	defPredeclaredFuncs()
+
+	universeIota = Universe.Lookup("iota").(*Const)
+	UniverseByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
+	UniverseRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
+}
+
+// Objects with names containing blanks are internal and not entered into
+// a scope. Objects with exported names are inserted in the unsafe package
+// scope; other objects are inserted in the universe scope.
+//
+func def(obj Object) {
+	name := obj.Name()
+	if strings.Index(name, " ") >= 0 {
+		return // nothing to do
+	}
+	// fix Obj link for named types
+	if typ, ok := obj.Type().(*Named); ok {
+		typ.obj = obj.(*TypeName)
+	}
+	// exported identifiers go into package unsafe
+	scope := Universe
+	if obj.Exported() {
+		scope = Unsafe.scope
+		// set Pkg field
+		switch obj := obj.(type) {
+		case *TypeName:
+			obj.pkg = Unsafe
+		case *Builtin:
+			obj.pkg = Unsafe
+		default:
+			unreachable()
+		}
+	}
+	if scope.Insert(obj) != nil {
+		panic("internal error: double declaration")
+	}
+}
diff --git a/third_party/go.tools/go/vcs/discovery.go b/third_party/go.tools/go/vcs/discovery.go
new file mode 100644
index 0000000..d5c3fc6
--- /dev/null
+++ b/third_party/go.tools/go/vcs/discovery.go
@@ -0,0 +1,73 @@
+// 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 vcs
+
+import (
+	"encoding/xml"
+	"fmt"
+	"io"
+	"strings"
+)
+
+// charsetReader returns a reader for the given charset. Currently
+// it only supports UTF-8 and ASCII. Otherwise, it returns a meaningful
+// error which is printed by go get, so the user can find why the package
+// wasn't downloaded if the encoding is not supported. Note that, in
+// order to reduce potential errors, ASCII is treated as UTF-8 (i.e. characters
+// greater than 0x7f are not rejected).
+func charsetReader(charset string, input io.Reader) (io.Reader, error) {
+	switch strings.ToLower(charset) {
+	case "ascii":
+		return input, nil
+	default:
+		return nil, fmt.Errorf("can't decode XML document using charset %q", charset)
+	}
+}
+
+// parseMetaGoImports returns meta imports from the HTML in r.
+// Parsing ends at the end of the <head> section or the beginning of the <body>.
+func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) {
+	d := xml.NewDecoder(r)
+	d.CharsetReader = charsetReader
+	d.Strict = false
+	var t xml.Token
+	for {
+		t, err = d.Token()
+		if err != nil {
+			return
+		}
+		if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") {
+			return
+		}
+		if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") {
+			return
+		}
+		e, ok := t.(xml.StartElement)
+		if !ok || !strings.EqualFold(e.Name.Local, "meta") {
+			continue
+		}
+		if attrValue(e.Attr, "name") != "go-import" {
+			continue
+		}
+		if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 {
+			imports = append(imports, metaImport{
+				Prefix:   f[0],
+				VCS:      f[1],
+				RepoRoot: f[2],
+			})
+		}
+	}
+}
+
+// attrValue returns the attribute value for the case-insensitive key
+// `name', or the empty string if nothing is found.
+func attrValue(attrs []xml.Attr, name string) string {
+	for _, a := range attrs {
+		if strings.EqualFold(a.Name.Local, name) {
+			return a.Value
+		}
+	}
+	return ""
+}
diff --git a/third_party/go.tools/go/vcs/env.go b/third_party/go.tools/go/vcs/env.go
new file mode 100644
index 0000000..e846f5b
--- /dev/null
+++ b/third_party/go.tools/go/vcs/env.go
@@ -0,0 +1,39 @@
+// Copyright 2013 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 vcs
+
+import (
+	"os"
+	"strings"
+)
+
+// envForDir returns a copy of the environment
+// suitable for running in the given directory.
+// The environment is the current process's environment
+// but with an updated $PWD, so that an os.Getwd in the
+// child will be faster.
+func envForDir(dir string) []string {
+	env := os.Environ()
+	// Internally we only use rooted paths, so dir is rooted.
+	// Even if dir is not rooted, no harm done.
+	return mergeEnvLists([]string{"PWD=" + dir}, env)
+}
+
+// mergeEnvLists merges the two environment lists such that
+// variables with the same name in "in" replace those in "out".
+func mergeEnvLists(in, out []string) []string {
+NextVar:
+	for _, inkv := range in {
+		k := strings.SplitAfterN(inkv, "=", 2)[0]
+		for i, outkv := range out {
+			if strings.HasPrefix(outkv, k) {
+				out[i] = inkv
+				continue NextVar
+			}
+		}
+		out = append(out, inkv)
+	}
+	return out
+}
diff --git a/third_party/go.tools/go/vcs/http.go b/third_party/go.tools/go/vcs/http.go
new file mode 100644
index 0000000..9618818
--- /dev/null
+++ b/third_party/go.tools/go/vcs/http.go
@@ -0,0 +1,80 @@
+// 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 vcs
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"net/url"
+)
+
+// httpClient is the default HTTP client, but a variable so it can be
+// changed by tests, without modifying http.DefaultClient.
+var httpClient = http.DefaultClient
+
+// httpGET returns the data from an HTTP GET request for the given URL.
+func httpGET(url string) ([]byte, error) {
+	resp, err := httpClient.Get(url)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != 200 {
+		return nil, fmt.Errorf("%s: %s", url, resp.Status)
+	}
+	b, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, fmt.Errorf("%s: %v", url, err)
+	}
+	return b, nil
+}
+
+// httpsOrHTTP returns the body of either the importPath's
+// https resource or, if unavailable, the http resource.
+func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err error) {
+	fetch := func(scheme string) (urlStr string, res *http.Response, err error) {
+		u, err := url.Parse(scheme + "://" + importPath)
+		if err != nil {
+			return "", nil, err
+		}
+		u.RawQuery = "go-get=1"
+		urlStr = u.String()
+		if Verbose {
+			log.Printf("Fetching %s", urlStr)
+		}
+		res, err = httpClient.Get(urlStr)
+		return
+	}
+	closeBody := func(res *http.Response) {
+		if res != nil {
+			res.Body.Close()
+		}
+	}
+	urlStr, res, err := fetch("https")
+	if err != nil || res.StatusCode != 200 {
+		if Verbose {
+			if err != nil {
+				log.Printf("https fetch failed.")
+			} else {
+				log.Printf("ignoring https fetch with status code %d", res.StatusCode)
+			}
+		}
+		closeBody(res)
+		urlStr, res, err = fetch("http")
+	}
+	if err != nil {
+		closeBody(res)
+		return "", nil, err
+	}
+	// Note: accepting a non-200 OK here, so people can serve a
+	// meta import in their http 404 page.
+	if Verbose {
+		log.Printf("Parsing meta tags from %s (status code %d)", urlStr, res.StatusCode)
+	}
+	return urlStr, res.Body, nil
+}
diff --git a/third_party/go.tools/go/vcs/vcs.go b/third_party/go.tools/go/vcs/vcs.go
new file mode 100644
index 0000000..586e1b8
--- /dev/null
+++ b/third_party/go.tools/go/vcs/vcs.go
@@ -0,0 +1,744 @@
+// 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 vcs
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+// Verbose enables verbose operation logging.
+var Verbose bool
+
+// ShowCmd controls whether VCS commands are printed.
+var ShowCmd bool
+
+// A Cmd describes how to use a version control system
+// like Mercurial, Git, or Subversion.
+type Cmd struct {
+	Name string
+	Cmd  string // name of binary to invoke command
+
+	CreateCmd   string // command to download a fresh copy of a repository
+	DownloadCmd string // command to download updates into an existing repository
+
+	TagCmd         []TagCmd // commands to list tags
+	TagLookupCmd   []TagCmd // commands to lookup tags before running tagSyncCmd
+	TagSyncCmd     string   // command to sync to specific tag
+	TagSyncDefault string   // command to sync to default tag
+
+	LogCmd string // command to list repository changelogs in an XML format
+
+	Scheme  []string
+	PingCmd string
+}
+
+// A TagCmd describes a command to list available tags
+// that can be passed to Cmd.TagSyncCmd.
+type TagCmd struct {
+	Cmd     string // command to list tags
+	Pattern string // regexp to extract tags from list
+}
+
+// vcsList lists the known version control systems
+var vcsList = []*Cmd{
+	vcsHg,
+	vcsGit,
+	vcsSvn,
+	vcsBzr,
+}
+
+// ByCmd returns the version control system for the given
+// command name (hg, git, svn, bzr).
+func ByCmd(cmd string) *Cmd {
+	for _, vcs := range vcsList {
+		if vcs.Cmd == cmd {
+			return vcs
+		}
+	}
+	return nil
+}
+
+// vcsHg describes how to use Mercurial.
+var vcsHg = &Cmd{
+	Name: "Mercurial",
+	Cmd:  "hg",
+
+	CreateCmd:   "clone -U {repo} {dir}",
+	DownloadCmd: "pull",
+
+	// We allow both tag and branch names as 'tags'
+	// for selecting a version.  This lets people have
+	// a go.release.r60 branch and a go1 branch
+	// and make changes in both, without constantly
+	// editing .hgtags.
+	TagCmd: []TagCmd{
+		{"tags", `^(\S+)`},
+		{"branches", `^(\S+)`},
+	},
+	TagSyncCmd:     "update -r {tag}",
+	TagSyncDefault: "update default",
+
+	LogCmd: "log --encoding=utf-8 --limit={limit} --template={template}",
+
+	Scheme:  []string{"https", "http", "ssh"},
+	PingCmd: "identify {scheme}://{repo}",
+}
+
+// vcsGit describes how to use Git.
+var vcsGit = &Cmd{
+	Name: "Git",
+	Cmd:  "git",
+
+	CreateCmd:   "clone {repo} {dir}",
+	DownloadCmd: "pull --ff-only",
+
+	TagCmd: []TagCmd{
+		// tags/xxx matches a git tag named xxx
+		// origin/xxx matches a git branch named xxx on the default remote repository
+		{"show-ref", `(?:tags|origin)/(\S+)$`},
+	},
+	TagLookupCmd: []TagCmd{
+		{"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`},
+	},
+	TagSyncCmd:     "checkout {tag}",
+	TagSyncDefault: "checkout master",
+
+	Scheme:  []string{"git", "https", "http", "git+ssh"},
+	PingCmd: "ls-remote {scheme}://{repo}",
+}
+
+// vcsBzr describes how to use Bazaar.
+var vcsBzr = &Cmd{
+	Name: "Bazaar",
+	Cmd:  "bzr",
+
+	CreateCmd: "branch {repo} {dir}",
+
+	// Without --overwrite bzr will not pull tags that changed.
+	// Replace by --overwrite-tags after http://pad.lv/681792 goes in.
+	DownloadCmd: "pull --overwrite",
+
+	TagCmd:         []TagCmd{{"tags", `^(\S+)`}},
+	TagSyncCmd:     "update -r {tag}",
+	TagSyncDefault: "update -r revno:-1",
+
+	Scheme:  []string{"https", "http", "bzr", "bzr+ssh"},
+	PingCmd: "info {scheme}://{repo}",
+}
+
+// vcsSvn describes how to use Subversion.
+var vcsSvn = &Cmd{
+	Name: "Subversion",
+	Cmd:  "svn",
+
+	CreateCmd:   "checkout {repo} {dir}",
+	DownloadCmd: "update",
+
+	// There is no tag command in subversion.
+	// The branch information is all in the path names.
+
+	LogCmd: "log --xml --limit={limit}",
+
+	Scheme:  []string{"https", "http", "svn", "svn+ssh"},
+	PingCmd: "info {scheme}://{repo}",
+}
+
+func (v *Cmd) String() string {
+	return v.Name
+}
+
+// run runs the command line cmd in the given directory.
+// keyval is a list of key, value pairs.  run expands
+// instances of {key} in cmd into value, but only after
+// splitting cmd into individual arguments.
+// If an error occurs, run prints the command line and the
+// command's combined stdout+stderr to standard error.
+// Otherwise run discards the command's output.
+func (v *Cmd) run(dir string, cmd string, keyval ...string) error {
+	_, err := v.run1(dir, cmd, keyval, true)
+	return err
+}
+
+// runVerboseOnly is like run but only generates error output to standard error in verbose mode.
+func (v *Cmd) runVerboseOnly(dir string, cmd string, keyval ...string) error {
+	_, err := v.run1(dir, cmd, keyval, false)
+	return err
+}
+
+// runOutput is like run but returns the output of the command.
+func (v *Cmd) runOutput(dir string, cmd string, keyval ...string) ([]byte, error) {
+	return v.run1(dir, cmd, keyval, true)
+}
+
+// run1 is the generalized implementation of run and runOutput.
+func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([]byte, error) {
+	m := make(map[string]string)
+	for i := 0; i < len(keyval); i += 2 {
+		m[keyval[i]] = keyval[i+1]
+	}
+	args := strings.Fields(cmdline)
+	for i, arg := range args {
+		args[i] = expand(m, arg)
+	}
+
+	_, err := exec.LookPath(v.Cmd)
+	if err != nil {
+		fmt.Fprintf(os.Stderr,
+			"go: missing %s command. See http://golang.org/s/gogetcmd\n",
+			v.Name)
+		return nil, err
+	}
+
+	cmd := exec.Command(v.Cmd, args...)
+	cmd.Dir = dir
+	cmd.Env = envForDir(cmd.Dir)
+	if ShowCmd {
+		fmt.Printf("cd %s\n", dir)
+		fmt.Printf("%s %s\n", v.Cmd, strings.Join(args, " "))
+	}
+	var buf bytes.Buffer
+	cmd.Stdout = &buf
+	cmd.Stderr = &buf
+	err = cmd.Run()
+	out := buf.Bytes()
+	if err != nil {
+		if verbose || Verbose {
+			fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.Cmd, strings.Join(args, " "))
+			os.Stderr.Write(out)
+		}
+		return nil, err
+	}
+	return out, nil
+}
+
+// Ping pings the repo to determine if scheme used is valid.
+// This repo must be pingable with this scheme and VCS.
+func (v *Cmd) Ping(scheme, repo string) error {
+	return v.runVerboseOnly(".", v.PingCmd, "scheme", scheme, "repo", repo)
+}
+
+// Create creates a new copy of repo in dir.
+// The parent of dir must exist; dir must not.
+func (v *Cmd) Create(dir, repo string) error {
+	return v.run(".", v.CreateCmd, "dir", dir, "repo", repo)
+}
+
+// CreateAtRev creates a new copy of repo in dir at revision rev.
+// The parent of dir must exist; dir must not.
+// rev must be a valid revision in repo.
+func (v *Cmd) CreateAtRev(dir, repo, rev string) error {
+	// Append revision flag to CreateCmd
+	createAtRevCmd := v.CreateCmd + " --rev=" + rev
+	return v.run(".", createAtRevCmd, "dir", dir, "repo", repo)
+}
+
+// Download downloads any new changes for the repo in dir.
+// dir must be a valid VCS repo compatible with v.
+func (v *Cmd) Download(dir string) error {
+	return v.run(dir, v.DownloadCmd)
+}
+
+// Tags returns the list of available tags for the repo in dir.
+// dir must be a valid VCS repo compatible with v.
+func (v *Cmd) Tags(dir string) ([]string, error) {
+	var tags []string
+	for _, tc := range v.TagCmd {
+		out, err := v.runOutput(dir, tc.Cmd)
+		if err != nil {
+			return nil, err
+		}
+		re := regexp.MustCompile(`(?m-s)` + tc.Pattern)
+		for _, m := range re.FindAllStringSubmatch(string(out), -1) {
+			tags = append(tags, m[1])
+		}
+	}
+	return tags, nil
+}
+
+// TagSync syncs the repo in dir to the named tag,
+// which either is a tag returned by tags or is v.TagDefault.
+// dir must be a valid VCS repo compatible with v and the tag must exist.
+func (v *Cmd) TagSync(dir, tag string) error {
+	if v.TagSyncCmd == "" {
+		return nil
+	}
+	if tag != "" {
+		for _, tc := range v.TagLookupCmd {
+			out, err := v.runOutput(dir, tc.Cmd, "tag", tag)
+			if err != nil {
+				return err
+			}
+			re := regexp.MustCompile(`(?m-s)` + tc.Pattern)
+			m := re.FindStringSubmatch(string(out))
+			if len(m) > 1 {
+				tag = m[1]
+				break
+			}
+		}
+	}
+	if tag == "" && v.TagSyncDefault != "" {
+		return v.run(dir, v.TagSyncDefault)
+	}
+	return v.run(dir, v.TagSyncCmd, "tag", tag)
+}
+
+// Log logs the changes for the repo in dir.
+// dir must be a valid VCS repo compatible with v.
+func (v *Cmd) Log(dir, logTemplate string) ([]byte, error) {
+	if err := v.Download(dir); err != nil {
+		return []byte{}, err
+	}
+
+	const N = 50 // how many revisions to grab
+	return v.runOutput(dir, v.LogCmd, "limit", strconv.Itoa(N), "template", logTemplate)
+}
+
+// LogAtRev logs the change for repo in dir at the rev revision.
+// dir must be a valid VCS repo compatible with v.
+// rev must be a valid revision for the repo in dir.
+func (v *Cmd) LogAtRev(dir, rev, logTemplate string) ([]byte, error) {
+	if err := v.Download(dir); err != nil {
+		return []byte{}, err
+	}
+
+	// Append revision flag to LogCmd.
+	logAtRevCmd := v.LogCmd + " --rev=" + rev
+	return v.runOutput(dir, logAtRevCmd, "limit", strconv.Itoa(1), "template", logTemplate)
+}
+
+// A vcsPath describes how to convert an import path into a
+// version control system and repository name.
+type vcsPath struct {
+	prefix string                              // prefix this description applies to
+	re     string                              // pattern for import path
+	repo   string                              // repository to use (expand with match of re)
+	vcs    string                              // version control system to use (expand with match of re)
+	check  func(match map[string]string) error // additional checks
+	ping   bool                                // ping for scheme to use to download repo
+
+	regexp *regexp.Regexp // cached compiled form of re
+}
+
+// FromDir inspects dir and its parents to determine the
+// version control system and code repository to use.
+// On return, root is the import path
+// corresponding to the root of the repository
+// (thus root is a prefix of importPath).
+func FromDir(dir, srcRoot string) (vcs *Cmd, root string, err error) {
+	// Clean and double-check that dir is in (a subdirectory of) srcRoot.
+	dir = filepath.Clean(dir)
+	srcRoot = filepath.Clean(srcRoot)
+	if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
+		return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
+	}
+
+	for len(dir) > len(srcRoot) {
+		for _, vcs := range vcsList {
+			if fi, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil && fi.IsDir() {
+				return vcs, dir[len(srcRoot)+1:], nil
+			}
+		}
+
+		// Move to parent.
+		ndir := filepath.Dir(dir)
+		if len(ndir) >= len(dir) {
+			// Shouldn't happen, but just in case, stop.
+			break
+		}
+		dir = ndir
+	}
+
+	return nil, "", fmt.Errorf("directory %q is not using a known version control system", dir)
+}
+
+// RepoRoot represents a version control system, a repo, and a root of
+// where to put it on disk.
+type RepoRoot struct {
+	VCS *Cmd
+
+	// repo is the repository URL, including scheme
+	Repo string
+
+	// root is the import path corresponding to the root of the
+	// repository
+	Root string
+}
+
+// RepoRootForImportPath analyzes importPath to determine the
+// version control system, and code repository to use.
+func RepoRootForImportPath(importPath string, verbose bool) (*RepoRoot, error) {
+	rr, err := RepoRootForImportPathStatic(importPath, "")
+	if err == errUnknownSite {
+		rr, err = RepoRootForImportDynamic(importPath, verbose)
+
+		// RepoRootForImportDynamic returns error detail
+		// that is irrelevant if the user didn't intend to use a
+		// dynamic import in the first place.
+		// Squelch it.
+		if err != nil {
+			if Verbose {
+				log.Printf("import %q: %v", importPath, err)
+			}
+			err = fmt.Errorf("unrecognized import path %q", importPath)
+		}
+	}
+
+	if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.Root, "...") {
+		// Do not allow wildcards in the repo root.
+		rr = nil
+		err = fmt.Errorf("cannot expand ... in %q", importPath)
+	}
+	return rr, err
+}
+
+var errUnknownSite = errors.New("dynamic lookup required to find mapping")
+
+// RepoRootForImportPathStatic attempts to map importPath to a
+// RepoRoot using the commonly-used VCS hosting sites in vcsPaths
+// (github.com/user/dir), or from a fully-qualified importPath already
+// containing its VCS type (foo.com/repo.git/dir)
+//
+// If scheme is non-empty, that scheme is forced.
+func RepoRootForImportPathStatic(importPath, scheme string) (*RepoRoot, error) {
+	if strings.Contains(importPath, "://") {
+		return nil, fmt.Errorf("invalid import path %q", importPath)
+	}
+	for _, srv := range vcsPaths {
+		if !strings.HasPrefix(importPath, srv.prefix) {
+			continue
+		}
+		m := srv.regexp.FindStringSubmatch(importPath)
+		if m == nil {
+			if srv.prefix != "" {
+				return nil, fmt.Errorf("invalid %s import path %q", srv.prefix, importPath)
+			}
+			continue
+		}
+
+		// Build map of named subexpression matches for expand.
+		match := map[string]string{
+			"prefix": srv.prefix,
+			"import": importPath,
+		}
+		for i, name := range srv.regexp.SubexpNames() {
+			if name != "" && match[name] == "" {
+				match[name] = m[i]
+			}
+		}
+		if srv.vcs != "" {
+			match["vcs"] = expand(match, srv.vcs)
+		}
+		if srv.repo != "" {
+			match["repo"] = expand(match, srv.repo)
+		}
+		if srv.check != nil {
+			if err := srv.check(match); err != nil {
+				return nil, err
+			}
+		}
+		vcs := ByCmd(match["vcs"])
+		if vcs == nil {
+			return nil, fmt.Errorf("unknown version control system %q", match["vcs"])
+		}
+		if srv.ping {
+			if scheme != "" {
+				match["repo"] = scheme + "://" + match["repo"]
+			} else {
+				for _, scheme := range vcs.Scheme {
+					if vcs.Ping(scheme, match["repo"]) == nil {
+						match["repo"] = scheme + "://" + match["repo"]
+						break
+					}
+				}
+			}
+		}
+		rr := &RepoRoot{
+			VCS:  vcs,
+			Repo: match["repo"],
+			Root: match["root"],
+		}
+		return rr, nil
+	}
+	return nil, errUnknownSite
+}
+
+// RepoRootForImportDynamic finds a *RepoRoot for a custom domain that's not
+// statically known by RepoRootForImportPathStatic.
+//
+// This handles "vanity import paths" like "name.tld/pkg/foo".
+func RepoRootForImportDynamic(importPath string, verbose bool) (*RepoRoot, error) {
+	slash := strings.Index(importPath, "/")
+	if slash < 0 {
+		return nil, errors.New("import path doesn't contain a slash")
+	}
+	host := importPath[:slash]
+	if !strings.Contains(host, ".") {
+		return nil, errors.New("import path doesn't contain a hostname")
+	}
+	urlStr, body, err := httpsOrHTTP(importPath)
+	if err != nil {
+		return nil, fmt.Errorf("http/https fetch: %v", err)
+	}
+	defer body.Close()
+	imports, err := parseMetaGoImports(body)
+	if err != nil {
+		return nil, fmt.Errorf("parsing %s: %v", importPath, err)
+	}
+	metaImport, err := matchGoImport(imports, importPath)
+	if err != nil {
+		if err != errNoMatch {
+			return nil, fmt.Errorf("parse %s: %v", urlStr, err)
+		}
+		return nil, fmt.Errorf("parse %s: no go-import meta tags", urlStr)
+	}
+	if verbose {
+		log.Printf("get %q: found meta tag %#v at %s", importPath, metaImport, urlStr)
+	}
+	// If the import was "uni.edu/bob/project", which said the
+	// prefix was "uni.edu" and the RepoRoot was "evilroot.com",
+	// make sure we don't trust Bob and check out evilroot.com to
+	// "uni.edu" yet (possibly overwriting/preempting another
+	// non-evil student).  Instead, first verify the root and see
+	// if it matches Bob's claim.
+	if metaImport.Prefix != importPath {
+		if verbose {
+			log.Printf("get %q: verifying non-authoritative meta tag", importPath)
+		}
+		urlStr0 := urlStr
+		urlStr, body, err = httpsOrHTTP(metaImport.Prefix)
+		if err != nil {
+			return nil, fmt.Errorf("fetch %s: %v", urlStr, err)
+		}
+		imports, err := parseMetaGoImports(body)
+		if err != nil {
+			return nil, fmt.Errorf("parsing %s: %v", importPath, err)
+		}
+		if len(imports) == 0 {
+			return nil, fmt.Errorf("fetch %s: no go-import meta tag", urlStr)
+		}
+		metaImport2, err := matchGoImport(imports, importPath)
+		if err != nil || metaImport != metaImport2 {
+			return nil, fmt.Errorf("%s and %s disagree about go-import for %s", urlStr0, urlStr, metaImport.Prefix)
+		}
+	}
+
+	if !strings.Contains(metaImport.RepoRoot, "://") {
+		return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, metaImport.RepoRoot)
+	}
+	rr := &RepoRoot{
+		VCS:  ByCmd(metaImport.VCS),
+		Repo: metaImport.RepoRoot,
+		Root: metaImport.Prefix,
+	}
+	if rr.VCS == nil {
+		return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, metaImport.VCS)
+	}
+	return rr, nil
+}
+
+// metaImport represents the parsed <meta name="go-import"
+// content="prefix vcs reporoot" /> tags from HTML files.
+type metaImport struct {
+	Prefix, VCS, RepoRoot string
+}
+
+// errNoMatch is returned from matchGoImport when there's no applicable match.
+var errNoMatch = errors.New("no import match")
+
+// matchGoImport returns the metaImport from imports matching importPath.
+// An error is returned if there are multiple matches.
+// errNoMatch is returned if none match.
+func matchGoImport(imports []metaImport, importPath string) (_ metaImport, err error) {
+	match := -1
+	for i, im := range imports {
+		if !strings.HasPrefix(importPath, im.Prefix) {
+			continue
+		}
+		if match != -1 {
+			err = fmt.Errorf("multiple meta tags match import path %q", importPath)
+			return
+		}
+		match = i
+	}
+	if match == -1 {
+		err = errNoMatch
+		return
+	}
+	return imports[match], nil
+}
+
+// expand rewrites s to replace {k} with match[k] for each key k in match.
+func expand(match map[string]string, s string) string {
+	for k, v := range match {
+		s = strings.Replace(s, "{"+k+"}", v, -1)
+	}
+	return s
+}
+
+// vcsPaths lists the known vcs paths.
+var vcsPaths = []*vcsPath{
+	// Google Code - new syntax
+	{
+		prefix: "code.google.com/",
+		re:     `^(?P<root>code\.google\.com/[pr]/(?P<project>[a-z0-9\-]+)(\.(?P<subrepo>[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`,
+		repo:   "https://{root}",
+		check:  googleCodeVCS,
+	},
+
+	// Google Code - old syntax
+	{
+		re:    `^(?P<project>[a-z0-9_\-.]+)\.googlecode\.com/(git|hg|svn)(?P<path>/.*)?$`,
+		check: oldGoogleCode,
+	},
+
+	// Github
+	{
+		prefix: "github.com/",
+		re:     `^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
+		vcs:    "git",
+		repo:   "https://{root}",
+		check:  noVCSSuffix,
+	},
+
+	// Bitbucket
+	{
+		prefix: "bitbucket.org/",
+		re:     `^(?P<root>bitbucket\.org/(?P<bitname>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
+		repo:   "https://{root}",
+		check:  bitbucketVCS,
+	},
+
+	// Launchpad
+	{
+		prefix: "launchpad.net/",
+		re:     `^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
+		vcs:    "bzr",
+		repo:   "https://{root}",
+		check:  launchpadVCS,
+	},
+
+	// General syntax for any server.
+	{
+		re:   `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
+		ping: true,
+	},
+}
+
+func init() {
+	// fill in cached regexps.
+	// Doing this eagerly discovers invalid regexp syntax
+	// without having to run a command that needs that regexp.
+	for _, srv := range vcsPaths {
+		srv.regexp = regexp.MustCompile(srv.re)
+	}
+}
+
+// noVCSSuffix checks that the repository name does not
+// end in .foo for any version control system foo.
+// The usual culprit is ".git".
+func noVCSSuffix(match map[string]string) error {
+	repo := match["repo"]
+	for _, vcs := range vcsList {
+		if strings.HasSuffix(repo, "."+vcs.Cmd) {
+			return fmt.Errorf("invalid version control suffix in %s path", match["prefix"])
+		}
+	}
+	return nil
+}
+
+var googleCheckout = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`)
+
+// googleCodeVCS determines the version control system for
+// a code.google.com repository, by scraping the project's
+// /source/checkout page.
+func googleCodeVCS(match map[string]string) error {
+	if err := noVCSSuffix(match); err != nil {
+		return err
+	}
+	data, err := httpGET(expand(match, "https://code.google.com/p/{project}/source/checkout?repo={subrepo}"))
+	if err != nil {
+		return err
+	}
+
+	if m := googleCheckout.FindSubmatch(data); m != nil {
+		if vcs := ByCmd(string(m[1])); vcs != nil {
+			// Subversion requires the old URLs.
+			// TODO: Test.
+			if vcs == vcsSvn {
+				if match["subrepo"] != "" {
+					return fmt.Errorf("sub-repositories not supported in Google Code Subversion projects")
+				}
+				match["repo"] = expand(match, "https://{project}.googlecode.com/svn")
+			}
+			match["vcs"] = vcs.Cmd
+			return nil
+		}
+	}
+
+	return fmt.Errorf("unable to detect version control system for code.google.com/ path")
+}
+
+// oldGoogleCode is invoked for old-style foo.googlecode.com paths.
+// It prints an error giving the equivalent new path.
+func oldGoogleCode(match map[string]string) error {
+	return fmt.Errorf("invalid Google Code import path: use %s instead",
+		expand(match, "code.google.com/p/{project}{path}"))
+}
+
+// bitbucketVCS determines the version control system for a
+// Bitbucket repository, by using the Bitbucket API.
+func bitbucketVCS(match map[string]string) error {
+	if err := noVCSSuffix(match); err != nil {
+		return err
+	}
+
+	var resp struct {
+		SCM string `json:"scm"`
+	}
+	url := expand(match, "https://api.bitbucket.org/1.0/repositories/{bitname}")
+	data, err := httpGET(url)
+	if err != nil {
+		return err
+	}
+	if err := json.Unmarshal(data, &resp); err != nil {
+		return fmt.Errorf("decoding %s: %v", url, err)
+	}
+
+	if ByCmd(resp.SCM) != nil {
+		match["vcs"] = resp.SCM
+		if resp.SCM == "git" {
+			match["repo"] += ".git"
+		}
+		return nil
+	}
+
+	return fmt.Errorf("unable to detect version control system for bitbucket.org/ path")
+}
+
+// launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case,
+// "foo" could be a series name registered in Launchpad with its own branch,
+// and it could also be the name of a directory within the main project
+// branch one level up.
+func launchpadVCS(match map[string]string) error {
+	if match["project"] == "" || match["series"] == "" {
+		return nil
+	}
+	_, err := httpGET(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format"))
+	if err != nil {
+		match["root"] = expand(match, "launchpad.net/{project}")
+		match["repo"] = expand(match, "https://{root}")
+	}
+	return nil
+}
diff --git a/third_party/go.tools/go/vcs/vcs_test.go b/third_party/go.tools/go/vcs/vcs_test.go
new file mode 100644
index 0000000..0b8dd8c
--- /dev/null
+++ b/third_party/go.tools/go/vcs/vcs_test.go
@@ -0,0 +1,86 @@
+// Copyright 2013 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 vcs
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"testing"
+)
+
+// Test that RepoRootForImportPath creates the correct RepoRoot for a given importPath.
+// TODO(cmang): Add tests for SVN and BZR.
+func TestRepoRootForImportPath(t *testing.T) {
+	tests := []struct {
+		path string
+		want *RepoRoot
+	}{
+		{
+			"code.google.com/p/go",
+			&RepoRoot{
+				VCS:  vcsHg,
+				Repo: "https://code.google.com/p/go",
+			},
+		},
+		{
+			"code.google.com/r/go",
+			&RepoRoot{
+				VCS:  vcsHg,
+				Repo: "https://code.google.com/r/go",
+			},
+		},
+		{
+			"github.com/golang/groupcache",
+			&RepoRoot{
+				VCS:  vcsGit,
+				Repo: "https://github.com/golang/groupcache",
+			},
+		},
+	}
+
+	for _, test := range tests {
+		got, err := RepoRootForImportPath(test.path, false)
+		if err != nil {
+			t.Errorf("RepoRootForImport(%q): %v", test.path, err)
+			continue
+		}
+		want := test.want
+		if got.VCS.Name != want.VCS.Name || got.Repo != want.Repo {
+			t.Errorf("RepoRootForImport(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.VCS, got.Repo, want.VCS, want.Repo)
+		}
+	}
+}
+
+// Test that FromDir correctly inspects a given directory and returns the right VCS.
+func TestFromDir(t *testing.T) {
+	type testStruct struct {
+		path string
+		want *Cmd
+	}
+
+	tests := make([]testStruct, len(vcsList))
+	tempDir, err := ioutil.TempDir("", "vcstest")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tempDir)
+
+	for i, vcs := range vcsList {
+		tests[i] = testStruct{
+			filepath.Join(tempDir, vcs.Name, "."+vcs.Cmd),
+			vcs,
+		}
+	}
+
+	for _, test := range tests {
+		os.MkdirAll(test.path, 0755)
+		got, _, _ := FromDir(test.path, tempDir)
+		if got.Name != test.want.Name {
+			t.Errorf("FromDir(%q, %q) = %s, want %s", test.path, tempDir, got, test.want)
+		}
+		os.RemoveAll(test.path)
+	}
+}
diff --git a/third_party/go.tools/godoc/analysis/README b/third_party/go.tools/godoc/analysis/README
new file mode 100644
index 0000000..411af1c
--- /dev/null
+++ b/third_party/go.tools/godoc/analysis/README
@@ -0,0 +1,111 @@
+
+Type and Pointer Analysis to-do list
+====================================
+
+Alan Donovan <adonovan@google.com>
+
+
+Overall design
+--------------
+
+We should re-run the type and pointer analyses periodically,
+as we do with the indexer.
+
+Version skew: how to mitigate the bad effects of stale URLs in old pages?
+We could record the file's length/CRC32/mtime in the go/loader, and
+refuse to decorate it with links unless they match at serving time.
+
+Use the VFS mechanism when (a) enumerating packages and (b) loading
+them.  (Requires planned changes to go/loader.)
+
+Future work: shard this using map/reduce for larger corpora.
+
+Testing: how does one test that a web page "looks right"?
+
+
+Bugs
+----
+
+(*ssa.Program).Create requires transitively error-free packages.  We
+can make this more robust by making the requirement transitively free
+of "hard" errors; soft errors are fine.
+
+Markup of compiler errors is slightly buggy because they overlap with
+other selections (e.g. Idents).  Fix.
+
+
+User Interface
+--------------
+
+CALLGRAPH:
+- Add a search box: given a search node, expand path from each entry
+  point to it.
+- Cause hovering over a given node to highlight that node, and all
+  nodes that are logically identical to it.
+- Initially expand the callgraph trees (but not their toggle divs).
+
+CALLEES:
+- The '(' links are not very discoverable.  Highlight them?
+
+Type info:
+- In the source viewer's lower pane, use a toggle div around the
+  IMPLEMENTS and METHODSETS lists, like we do in the pacakge view.
+  Only expand them initially if short.
+- Include IMPLEMENTS and METHOD SETS information in search index.
+- URLs in IMPLEMENTS/METHOD SETS always link to source, even from the
+  package docs view.  This makes sense for links to non-exported
+  types, but links to exported types and funcs should probably go to
+  other package docs.
+- Suppress toggle divs for empty method sets.
+
+Misc:
+- The [X] button in the lower pane is subject to scrolling.
+- Should the lower pane be floating?  An iframe?
+  When we change document.location by clicking on a link, it will go away.
+  How do we prevent that (a la Gmail's chat windows)?
+- Progress/status: for each file, display its analysis status, one of:
+   - not in analysis scope
+   - type analysis running...
+   - type analysis complete
+     (+ optionally: there were type errors in this file)
+   And if PTA requested:
+   - type analysis complete; PTA not attempted due to type errors
+   - PTA running...
+   - PTA complete
+- Scroll the selection into view, e.g. the vertical center, or better
+  still, under the pointer (assuming we have a mouse).
+
+
+More features
+-------------
+
+Display the REFERRERS relation?  (Useful but potentially large.)
+
+Display the INSTANTIATIONS relation? i.e. given a type T, show the set of
+syntactic constructs that can instantiate it:
+    var x T
+    x := T{...}
+    x = new(T)
+    x = make([]T, n)
+    etc
+    + all INSTANTIATIONS of all S defined as struct{t T} or [n]T
+(Potentially a lot of information.)
+(Add this to oracle too.)
+
+
+Optimisations
+-------------
+
+Each call to addLink takes a (per-file) lock.  The locking is
+fine-grained so server latency isn't terrible, but overall it makes
+the link computation quite slow.  Batch update might be better.
+
+Memory usage is now about 1.5GB for GOROOT + go.tools.  It used to be 700MB.
+
+Optimize for time and space.  The main slowdown is the network I/O
+time caused by an increase in page size of about 3x: about 2x from
+HTML, and 0.7--2.1x from JSON (unindented vs indented).  The JSON
+contains a lot of filenames (e.g. 820 copies of 16 distinct
+filenames).  20% of the HTML is L%d spans (now disabled).  The HTML
+also contains lots of tooltips for long struct/interface types.
+De-dup or just abbreviate?  The actual formatting is very fast.
diff --git a/third_party/go.tools/godoc/analysis/analysis.go b/third_party/go.tools/godoc/analysis/analysis.go
new file mode 100644
index 0000000..c657250
--- /dev/null
+++ b/third_party/go.tools/godoc/analysis/analysis.go
@@ -0,0 +1,617 @@
+// Copyright 2014 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 analysis performs type and pointer analysis
+// and generates mark-up for the Go source view.
+//
+// The Run method populates a Result object by running type and
+// (optionally) pointer analysis.  The Result object is thread-safe
+// and at all times may be accessed by a serving thread, even as it is
+// progressively populated as analysis facts are derived.
+//
+// The Result is a mapping from each godoc file URL
+// (e.g. /src/fmt/print.go) to information about that file.  The
+// information is a list of HTML markup links and a JSON array of
+// structured data values.  Some of the links call client-side
+// JavaScript functions that index this array.
+//
+// The analysis computes mark-up for the following relations:
+//
+// IMPORTS: for each ast.ImportSpec, the package that it denotes.
+//
+// RESOLUTION: for each ast.Ident, its kind and type, and the location
+// of its definition.
+//
+// METHOD SETS, IMPLEMENTS: for each ast.Ident defining a named type,
+// its method-set, the set of interfaces it implements or is
+// implemented by, and its size/align values.
+//
+// CALLERS, CALLEES: for each function declaration ('func' token), its
+// callers, and for each call-site ('(' token), its callees.
+//
+// CALLGRAPH: the package docs include an interactive viewer for the
+// intra-package call graph of "fmt".
+//
+// CHANNEL PEERS: for each channel operation make/<-/close, the set of
+// other channel ops that alias the same channel(s).
+//
+// ERRORS: for each locus of a frontend (scanner/parser/type) error, the
+// location is highlighted in red and hover text provides the compiler
+// error message.
+//
+package analysis
+
+import (
+	"fmt"
+	"go/build"
+	"go/scanner"
+	"go/token"
+	"html"
+	"io"
+	"log"
+	"os"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strings"
+	"sync"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/pointer"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/ssa/ssautil"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// -- links ------------------------------------------------------------
+
+// A Link is an HTML decoration of the bytes [Start, End) of a file.
+// Write is called before/after those bytes to emit the mark-up.
+type Link interface {
+	Start() int
+	End() int
+	Write(w io.Writer, _ int, start bool) // the godoc.LinkWriter signature
+}
+
+// An <a> element.
+type aLink struct {
+	start, end int    // =godoc.Segment
+	title      string // hover text
+	onclick    string // JS code (NB: trusted)
+	href       string // URL     (NB: trusted)
+}
+
+func (a aLink) Start() int { return a.start }
+func (a aLink) End() int   { return a.end }
+func (a aLink) Write(w io.Writer, _ int, start bool) {
+	if start {
+		fmt.Fprintf(w, `<a title='%s'`, html.EscapeString(a.title))
+		if a.onclick != "" {
+			fmt.Fprintf(w, ` onclick='%s'`, html.EscapeString(a.onclick))
+		}
+		if a.href != "" {
+			// TODO(adonovan): I think that in principle, a.href must first be
+			// url.QueryEscape'd, but if I do that, a leading slash becomes "%2F",
+			// which causes the browser to treat the path as relative, not absolute.
+			// WTF?
+			fmt.Fprintf(w, ` href='%s'`, html.EscapeString(a.href))
+		}
+		fmt.Fprintf(w, ">")
+	} else {
+		fmt.Fprintf(w, "</a>")
+	}
+}
+
+// An <a class='error'> element.
+type errorLink struct {
+	start int
+	msg   string
+}
+
+func (e errorLink) Start() int { return e.start }
+func (e errorLink) End() int   { return e.start + 1 }
+
+func (e errorLink) Write(w io.Writer, _ int, start bool) {
+	// <span> causes havoc, not sure why, so use <a>.
+	if start {
+		fmt.Fprintf(w, `<a class='error' title='%s'>`, html.EscapeString(e.msg))
+	} else {
+		fmt.Fprintf(w, "</a>")
+	}
+}
+
+// -- fileInfo ---------------------------------------------------------
+
+// FileInfo holds analysis information for the source file view.
+// Clients must not mutate it.
+type FileInfo struct {
+	Data  []interface{} // JSON serializable values
+	Links []Link        // HTML link markup
+}
+
+// A fileInfo is the server's store of hyperlinks and JSON data for a
+// particular file.
+type fileInfo struct {
+	mu        sync.Mutex
+	data      []interface{} // JSON objects
+	links     []Link
+	sorted    bool
+	hasErrors bool // TODO(adonovan): surface this in the UI
+}
+
+// addLink adds a link to the Go source file fi.
+func (fi *fileInfo) addLink(link Link) {
+	fi.mu.Lock()
+	fi.links = append(fi.links, link)
+	fi.sorted = false
+	if _, ok := link.(errorLink); ok {
+		fi.hasErrors = true
+	}
+	fi.mu.Unlock()
+}
+
+// addData adds the structured value x to the JSON data for the Go
+// source file fi.  Its index is returned.
+func (fi *fileInfo) addData(x interface{}) int {
+	fi.mu.Lock()
+	index := len(fi.data)
+	fi.data = append(fi.data, x)
+	fi.mu.Unlock()
+	return index
+}
+
+// get returns the file info in external form.
+// Callers must not mutate its fields.
+func (fi *fileInfo) get() FileInfo {
+	var r FileInfo
+	// Copy slices, to avoid races.
+	fi.mu.Lock()
+	r.Data = append(r.Data, fi.data...)
+	if !fi.sorted {
+		sort.Sort(linksByStart(fi.links))
+		fi.sorted = true
+	}
+	r.Links = append(r.Links, fi.links...)
+	fi.mu.Unlock()
+	return r
+}
+
+// PackageInfo holds analysis information for the package view.
+// Clients must not mutate it.
+type PackageInfo struct {
+	CallGraph      []*PCGNodeJSON
+	CallGraphIndex map[string]int
+	Types          []*TypeInfoJSON
+}
+
+type pkgInfo struct {
+	mu             sync.Mutex
+	callGraph      []*PCGNodeJSON
+	callGraphIndex map[string]int  // keys are (*ssa.Function).RelString()
+	types          []*TypeInfoJSON // type info for exported types
+}
+
+func (pi *pkgInfo) setCallGraph(callGraph []*PCGNodeJSON, callGraphIndex map[string]int) {
+	pi.mu.Lock()
+	pi.callGraph = callGraph
+	pi.callGraphIndex = callGraphIndex
+	pi.mu.Unlock()
+}
+
+func (pi *pkgInfo) addType(t *TypeInfoJSON) {
+	pi.mu.Lock()
+	pi.types = append(pi.types, t)
+	pi.mu.Unlock()
+}
+
+// get returns the package info in external form.
+// Callers must not mutate its fields.
+func (pi *pkgInfo) get() PackageInfo {
+	var r PackageInfo
+	// Copy slices, to avoid races.
+	pi.mu.Lock()
+	r.CallGraph = append(r.CallGraph, pi.callGraph...)
+	r.CallGraphIndex = pi.callGraphIndex
+	r.Types = append(r.Types, pi.types...)
+	pi.mu.Unlock()
+	return r
+}
+
+// -- Result -----------------------------------------------------------
+
+// Result contains the results of analysis.
+// The result contains a mapping from filenames to a set of HTML links
+// and JavaScript data referenced by the links.
+type Result struct {
+	mu        sync.Mutex           // guards maps (but not their contents)
+	status    string               // global analysis status
+	fileInfos map[string]*fileInfo // keys are godoc file URLs
+	pkgInfos  map[string]*pkgInfo  // keys are import paths
+}
+
+// fileInfo returns the fileInfo for the specified godoc file URL,
+// constructing it as needed.  Thread-safe.
+func (res *Result) fileInfo(url string) *fileInfo {
+	res.mu.Lock()
+	fi, ok := res.fileInfos[url]
+	if !ok {
+		if res.fileInfos == nil {
+			res.fileInfos = make(map[string]*fileInfo)
+		}
+		fi = new(fileInfo)
+		res.fileInfos[url] = fi
+	}
+	res.mu.Unlock()
+	return fi
+}
+
+// Status returns a human-readable description of the current analysis status.
+func (res *Result) Status() string {
+	res.mu.Lock()
+	defer res.mu.Unlock()
+	return res.status
+}
+
+func (res *Result) setStatusf(format string, args ...interface{}) {
+	res.mu.Lock()
+	res.status = fmt.Sprintf(format, args...)
+	log.Printf(format, args...)
+	res.mu.Unlock()
+}
+
+// FileInfo returns new slices containing opaque JSON values and the
+// HTML link markup for the specified godoc file URL.  Thread-safe.
+// Callers must not mutate the elements.
+// It returns "zero" if no data is available.
+//
+func (res *Result) FileInfo(url string) (fi FileInfo) {
+	return res.fileInfo(url).get()
+}
+
+// pkgInfo returns the pkgInfo for the specified import path,
+// constructing it as needed.  Thread-safe.
+func (res *Result) pkgInfo(importPath string) *pkgInfo {
+	res.mu.Lock()
+	pi, ok := res.pkgInfos[importPath]
+	if !ok {
+		if res.pkgInfos == nil {
+			res.pkgInfos = make(map[string]*pkgInfo)
+		}
+		pi = new(pkgInfo)
+		res.pkgInfos[importPath] = pi
+	}
+	res.mu.Unlock()
+	return pi
+}
+
+// PackageInfo returns new slices of JSON values for the callgraph and
+// type info for the specified package.  Thread-safe.
+// Callers must not mutate its fields.
+// PackageInfo returns "zero" if no data is available.
+//
+func (res *Result) PackageInfo(importPath string) PackageInfo {
+	return res.pkgInfo(importPath).get()
+}
+
+// -- analysis ---------------------------------------------------------
+
+type analysis struct {
+	result    *Result
+	prog      *ssa.Program
+	ops       []chanOp       // all channel ops in program
+	allNamed  []*types.Named // all named types in the program
+	ptaConfig pointer.Config
+	path2url  map[string]string // maps openable path to godoc file URL (/src/fmt/print.go)
+	pcgs      map[*ssa.Package]*packageCallGraph
+}
+
+// fileAndOffset returns the file and offset for a given pos.
+func (a *analysis) fileAndOffset(pos token.Pos) (fi *fileInfo, offset int) {
+	return a.fileAndOffsetPosn(a.prog.Fset.Position(pos))
+}
+
+// fileAndOffsetPosn returns the file and offset for a given position.
+func (a *analysis) fileAndOffsetPosn(posn token.Position) (fi *fileInfo, offset int) {
+	url := a.path2url[posn.Filename]
+	return a.result.fileInfo(url), posn.Offset
+}
+
+// posURL returns the URL of the source extent [pos, pos+len).
+func (a *analysis) posURL(pos token.Pos, len int) string {
+	if pos == token.NoPos {
+		return ""
+	}
+	posn := a.prog.Fset.Position(pos)
+	url := a.path2url[posn.Filename]
+	return fmt.Sprintf("%s?s=%d:%d#L%d",
+		url, posn.Offset, posn.Offset+len, posn.Line)
+}
+
+// ----------------------------------------------------------------------
+
+// Run runs program analysis and computes the resulting markup,
+// populating *result in a thread-safe manner, first with type
+// information then later with pointer analysis information if
+// enabled by the pta flag.
+//
+func Run(pta bool, result *Result) {
+	conf := loader.Config{
+		SourceImports: true,
+		AllowErrors:   true,
+	}
+
+	// Silence the default error handler.
+	// Don't print all errors; we'll report just
+	// one per errant package later.
+	conf.TypeChecker.Error = func(e error) {}
+
+	var roots, args []string // roots[i] ends with os.PathSeparator
+
+	// Enumerate packages in $GOROOT.
+	root := filepath.Join(runtime.GOROOT(), "src") + string(os.PathSeparator)
+	roots = append(roots, root)
+	args = allPackages(root)
+	log.Printf("GOROOT=%s: %s\n", root, args)
+
+	// Enumerate packages in $GOPATH.
+	for i, dir := range filepath.SplitList(build.Default.GOPATH) {
+		root := filepath.Join(dir, "src") + string(os.PathSeparator)
+		roots = append(roots, root)
+		pkgs := allPackages(root)
+		log.Printf("GOPATH[%d]=%s: %s\n", i, root, pkgs)
+		args = append(args, pkgs...)
+	}
+
+	// Uncomment to make startup quicker during debugging.
+	//args = []string{"llvm.org/llgo/third_party/go.tools/cmd/godoc"}
+	//args = []string{"fmt"}
+
+	if _, err := conf.FromArgs(args, true); err != nil {
+		// TODO(adonovan): degrade gracefully, not fail totally.
+		// (The crippling case is a parse error in an external test file.)
+		result.setStatusf("Analysis failed: %s.", err) // import error
+		return
+	}
+
+	result.setStatusf("Loading and type-checking packages...")
+	iprog, err := conf.Load()
+	if iprog != nil {
+		// Report only the first error of each package.
+		for _, info := range iprog.AllPackages {
+			for _, err := range info.Errors {
+				fmt.Fprintln(os.Stderr, err)
+				break
+			}
+		}
+		log.Printf("Loaded %d packages.", len(iprog.AllPackages))
+	}
+	if err != nil {
+		result.setStatusf("Loading failed: %s.\n", err)
+		return
+	}
+
+	// Create SSA-form program representation.
+	// Only the transitively error-free packages are used.
+	prog := ssa.Create(iprog, ssa.GlobalDebug)
+
+	// Compute the set of main packages, including testmain.
+	allPackages := prog.AllPackages()
+	var mainPkgs []*ssa.Package
+	if testmain := prog.CreateTestMainPackage(allPackages...); testmain != nil {
+		mainPkgs = append(mainPkgs, testmain)
+	}
+	for _, pkg := range allPackages {
+		if pkg.Object.Name() == "main" && pkg.Func("main") != nil {
+			mainPkgs = append(mainPkgs, pkg)
+		}
+	}
+	log.Print("Transitively error-free main packages: ", mainPkgs)
+
+	// Build SSA code for bodies of all functions in the whole program.
+	result.setStatusf("Constructing SSA form...")
+	prog.BuildAll()
+	log.Print("SSA construction complete")
+
+	a := analysis{
+		result: result,
+		prog:   prog,
+		pcgs:   make(map[*ssa.Package]*packageCallGraph),
+	}
+
+	// Build a mapping from openable filenames to godoc file URLs,
+	// i.e. "/src/" plus path relative to GOROOT/src or GOPATH[i]/src.
+	a.path2url = make(map[string]string)
+	for _, info := range iprog.AllPackages {
+	nextfile:
+		for _, f := range info.Files {
+			if f.Pos() == 0 {
+				continue // e.g. files generated by cgo
+			}
+			abs := iprog.Fset.File(f.Pos()).Name()
+			// Find the root to which this file belongs.
+			for _, root := range roots {
+				rel := strings.TrimPrefix(abs, root)
+				if len(rel) < len(abs) {
+					a.path2url[abs] = "/src/" + filepath.ToSlash(rel)
+					continue nextfile
+				}
+			}
+
+			log.Printf("Can't locate file %s (package %q) beneath any root",
+				abs, info.Pkg.Path())
+		}
+	}
+
+	// Add links for scanner, parser, type-checker errors.
+	// TODO(adonovan): fix: these links can overlap with
+	// identifier markup, causing the renderer to emit some
+	// characters twice.
+	errors := make(map[token.Position][]string)
+	for _, info := range iprog.AllPackages {
+		for _, err := range info.Errors {
+			switch err := err.(type) {
+			case types.Error:
+				posn := a.prog.Fset.Position(err.Pos)
+				errors[posn] = append(errors[posn], err.Msg)
+			case scanner.ErrorList:
+				for _, e := range err {
+					errors[e.Pos] = append(errors[e.Pos], e.Msg)
+				}
+			default:
+				log.Printf("Package %q has error (%T) without position: %v\n",
+					info.Pkg.Path(), err, err)
+			}
+		}
+	}
+	for posn, errs := range errors {
+		fi, offset := a.fileAndOffsetPosn(posn)
+		fi.addLink(errorLink{
+			start: offset,
+			msg:   strings.Join(errs, "\n"),
+		})
+	}
+
+	// ---------- type-based analyses ----------
+
+	// Compute the all-pairs IMPLEMENTS relation.
+	// Collect all named types, even local types
+	// (which can have methods via promotion)
+	// and the built-in "error".
+	errorType := types.Universe.Lookup("error").Type().(*types.Named)
+	a.allNamed = append(a.allNamed, errorType)
+	for _, info := range iprog.AllPackages {
+		for _, obj := range info.Defs {
+			if obj, ok := obj.(*types.TypeName); ok {
+				a.allNamed = append(a.allNamed, obj.Type().(*types.Named))
+			}
+		}
+	}
+	log.Print("Computing implements relation...")
+	facts := computeImplements(&a.prog.MethodSets, a.allNamed)
+
+	// Add the type-based analysis results.
+	log.Print("Extracting type info...")
+	for _, info := range iprog.AllPackages {
+		a.doTypeInfo(info, facts)
+	}
+
+	a.visitInstrs(pta)
+
+	result.setStatusf("Type analysis complete.")
+
+	if pta {
+		a.pointer(mainPkgs)
+	}
+}
+
+// visitInstrs visits all SSA instructions in the program.
+func (a *analysis) visitInstrs(pta bool) {
+	log.Print("Visit instructions...")
+	for fn := range ssautil.AllFunctions(a.prog) {
+		for _, b := range fn.Blocks {
+			for _, instr := range b.Instrs {
+				// CALLEES (static)
+				// (Dynamic calls require pointer analysis.)
+				//
+				// We use the SSA representation to find the static callee,
+				// since in many cases it does better than the
+				// types.Info.{Refs,Selection} information.  For example:
+				//
+				//   defer func(){}()      // static call to anon function
+				//   f := func(){}; f()    // static call to anon function
+				//   f := fmt.Println; f() // static call to named function
+				//
+				// The downside is that we get no static callee information
+				// for packages that (transitively) contain errors.
+				if site, ok := instr.(ssa.CallInstruction); ok {
+					if callee := site.Common().StaticCallee(); callee != nil {
+						// TODO(adonovan): callgraph: elide wrappers.
+						// (Do static calls ever go to wrappers?)
+						if site.Common().Pos() != token.NoPos {
+							a.addCallees(site, []*ssa.Function{callee})
+						}
+					}
+				}
+
+				if !pta {
+					continue
+				}
+
+				// CHANNEL PEERS
+				// Collect send/receive/close instructions in the whole ssa.Program.
+				for _, op := range chanOps(instr) {
+					a.ops = append(a.ops, op)
+					a.ptaConfig.AddQuery(op.ch) // add channel ssa.Value to PTA query
+				}
+			}
+		}
+	}
+	log.Print("Visit instructions complete")
+}
+
+// pointer runs the pointer analysis.
+func (a *analysis) pointer(mainPkgs []*ssa.Package) {
+	// Run the pointer analysis and build the complete callgraph.
+	a.ptaConfig.Mains = mainPkgs
+	a.ptaConfig.BuildCallGraph = true
+	a.ptaConfig.Reflection = false // (for now)
+
+	a.result.setStatusf("Pointer analysis running...")
+
+	ptares, err := pointer.Analyze(&a.ptaConfig)
+	if err != nil {
+		// If this happens, it indicates a bug.
+		a.result.setStatusf("Pointer analysis failed: %s.", err)
+		return
+	}
+	log.Print("Pointer analysis complete.")
+
+	// Add the results of pointer analysis.
+
+	a.result.setStatusf("Computing channel peers...")
+	a.doChannelPeers(ptares.Queries)
+	a.result.setStatusf("Computing dynamic call graph edges...")
+	a.doCallgraph(ptares.CallGraph)
+
+	a.result.setStatusf("Analysis complete.")
+}
+
+type linksByStart []Link
+
+func (a linksByStart) Less(i, j int) bool { return a[i].Start() < a[j].Start() }
+func (a linksByStart) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a linksByStart) Len() int           { return len(a) }
+
+// allPackages returns a new sorted slice of all packages beneath the
+// specified package root directory, e.g. $GOROOT/src or $GOPATH/src.
+// Derived from from go/ssa/stdlib_test.go
+// root must end with os.PathSeparator.
+//
+// TODO(adonovan): use buildutil.AllPackages when the tree thaws.
+func allPackages(root string) []string {
+	var pkgs []string
+	filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
+		if info == nil {
+			return nil // non-existent root directory?
+		}
+		if !info.IsDir() {
+			return nil // not a directory
+		}
+		// Prune the search if we encounter any of these names:
+		base := filepath.Base(path)
+		if base == "testdata" || strings.HasPrefix(base, ".") {
+			return filepath.SkipDir
+		}
+		pkg := filepath.ToSlash(strings.TrimPrefix(path, root))
+		switch pkg {
+		case "builtin":
+			return filepath.SkipDir
+		case "":
+			return nil // ignore root of tree
+		}
+		pkgs = append(pkgs, pkg)
+		return nil
+	})
+	return pkgs
+}
diff --git a/third_party/go.tools/godoc/analysis/callgraph.go b/third_party/go.tools/godoc/analysis/callgraph.go
new file mode 100644
index 0000000..a20c12f
--- /dev/null
+++ b/third_party/go.tools/godoc/analysis/callgraph.go
@@ -0,0 +1,351 @@
+// Copyright 2014 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 analysis
+
+// This file computes the CALLERS and CALLEES relations from the call
+// graph.  CALLERS/CALLEES information is displayed in the lower pane
+// when a "func" token or ast.CallExpr.Lparen is clicked, respectively.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"log"
+	"math/big"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// doCallgraph computes the CALLEES and CALLERS relations.
+func (a *analysis) doCallgraph(cg *callgraph.Graph) {
+	log.Print("Deleting synthetic nodes...")
+	// TODO(adonovan): opt: DeleteSyntheticNodes is asymptotically
+	// inefficient and can be (unpredictably) slow.
+	cg.DeleteSyntheticNodes()
+	log.Print("Synthetic nodes deleted")
+
+	// Populate nodes of package call graphs (PCGs).
+	for _, n := range cg.Nodes {
+		a.pcgAddNode(n.Func)
+	}
+	// Within each PCG, sort funcs by name.
+	for _, pcg := range a.pcgs {
+		pcg.sortNodes()
+	}
+
+	calledFuncs := make(map[ssa.CallInstruction]map[*ssa.Function]bool)
+	callingSites := make(map[*ssa.Function]map[ssa.CallInstruction]bool)
+	for _, n := range cg.Nodes {
+		for _, e := range n.Out {
+			if e.Site == nil {
+				continue // a call from a synthetic node such as <root>
+			}
+
+			// Add (site pos, callee) to calledFuncs.
+			// (Dynamic calls only.)
+			callee := e.Callee.Func
+
+			a.pcgAddEdge(n.Func, callee)
+
+			if callee.Synthetic != "" {
+				continue // call of a package initializer
+			}
+
+			if e.Site.Common().StaticCallee() == nil {
+				// dynamic call
+				// (CALLEES information for static calls
+				// is computed using SSA information.)
+				lparen := e.Site.Common().Pos()
+				if lparen != token.NoPos {
+					fns := calledFuncs[e.Site]
+					if fns == nil {
+						fns = make(map[*ssa.Function]bool)
+						calledFuncs[e.Site] = fns
+					}
+					fns[callee] = true
+				}
+			}
+
+			// Add (callee, site) to callingSites.
+			fns := callingSites[callee]
+			if fns == nil {
+				fns = make(map[ssa.CallInstruction]bool)
+				callingSites[callee] = fns
+			}
+			fns[e.Site] = true
+		}
+	}
+
+	// CALLEES.
+	log.Print("Callees...")
+	for site, fns := range calledFuncs {
+		var funcs funcsByPos
+		for fn := range fns {
+			funcs = append(funcs, fn)
+		}
+		sort.Sort(funcs)
+
+		a.addCallees(site, funcs)
+	}
+
+	// CALLERS
+	log.Print("Callers...")
+	for callee, sites := range callingSites {
+		pos := funcToken(callee)
+		if pos == token.NoPos {
+			log.Printf("CALLERS: skipping %s: no pos", callee)
+			continue
+		}
+
+		var this *types.Package // for relativizing names
+		if callee.Pkg != nil {
+			this = callee.Pkg.Object
+		}
+
+		// Compute sites grouped by parent, with text and URLs.
+		sitesByParent := make(map[*ssa.Function]sitesByPos)
+		for site := range sites {
+			fn := site.Parent()
+			sitesByParent[fn] = append(sitesByParent[fn], site)
+		}
+		var funcs funcsByPos
+		for fn := range sitesByParent {
+			funcs = append(funcs, fn)
+		}
+		sort.Sort(funcs)
+
+		v := callersJSON{
+			Callee:  callee.String(),
+			Callers: []callerJSON{}, // (JS wants non-nil)
+		}
+		for _, fn := range funcs {
+			caller := callerJSON{
+				Func:  prettyFunc(this, fn),
+				Sites: []anchorJSON{}, // (JS wants non-nil)
+			}
+			sites := sitesByParent[fn]
+			sort.Sort(sites)
+			for _, site := range sites {
+				pos := site.Common().Pos()
+				if pos != token.NoPos {
+					caller.Sites = append(caller.Sites, anchorJSON{
+						Text: fmt.Sprintf("%d", a.prog.Fset.Position(pos).Line),
+						Href: a.posURL(pos, len("(")),
+					})
+				}
+			}
+			v.Callers = append(v.Callers, caller)
+		}
+
+		fi, offset := a.fileAndOffset(pos)
+		fi.addLink(aLink{
+			start:   offset,
+			end:     offset + len("func"),
+			title:   fmt.Sprintf("%d callers", len(sites)),
+			onclick: fmt.Sprintf("onClickCallers(%d)", fi.addData(v)),
+		})
+	}
+
+	// PACKAGE CALLGRAPH
+	log.Print("Package call graph...")
+	for pkg, pcg := range a.pcgs {
+		// Maps (*ssa.Function).RelString() to index in JSON CALLGRAPH array.
+		index := make(map[string]int)
+
+		// Treat exported functions (and exported methods of
+		// exported named types) as roots even if they aren't
+		// actually called from outside the package.
+		for i, n := range pcg.nodes {
+			if i == 0 || n.fn.Object() == nil || !n.fn.Object().Exported() {
+				continue
+			}
+			recv := n.fn.Signature.Recv()
+			if recv == nil || deref(recv.Type()).(*types.Named).Obj().Exported() {
+				roots := &pcg.nodes[0].edges
+				roots.SetBit(roots, i, 1)
+			}
+			index[n.fn.RelString(pkg.Object)] = i
+		}
+
+		json := a.pcgJSON(pcg)
+
+		// TODO(adonovan): pkg.Path() is not unique!
+		// It is possible to declare a non-test package called x_test.
+		a.result.pkgInfo(pkg.Object.Path()).setCallGraph(json, index)
+	}
+}
+
+// addCallees adds client data and links for the facts that site calls fns.
+func (a *analysis) addCallees(site ssa.CallInstruction, fns []*ssa.Function) {
+	v := calleesJSON{
+		Descr:   site.Common().Description(),
+		Callees: []anchorJSON{}, // (JS wants non-nil)
+	}
+	var this *types.Package // for relativizing names
+	if p := site.Parent().Package(); p != nil {
+		this = p.Object
+	}
+
+	for _, fn := range fns {
+		v.Callees = append(v.Callees, anchorJSON{
+			Text: prettyFunc(this, fn),
+			Href: a.posURL(funcToken(fn), len("func")),
+		})
+	}
+
+	fi, offset := a.fileAndOffset(site.Common().Pos())
+	fi.addLink(aLink{
+		start:   offset,
+		end:     offset + len("("),
+		title:   fmt.Sprintf("%d callees", len(v.Callees)),
+		onclick: fmt.Sprintf("onClickCallees(%d)", fi.addData(v)),
+	})
+}
+
+// -- utilities --------------------------------------------------------
+
+// stable order within packages but undefined across packages.
+type funcsByPos []*ssa.Function
+
+func (a funcsByPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
+func (a funcsByPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a funcsByPos) Len() int           { return len(a) }
+
+type sitesByPos []ssa.CallInstruction
+
+func (a sitesByPos) Less(i, j int) bool { return a[i].Common().Pos() < a[j].Common().Pos() }
+func (a sitesByPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a sitesByPos) Len() int           { return len(a) }
+
+func funcToken(fn *ssa.Function) token.Pos {
+	switch syntax := fn.Syntax().(type) {
+	case *ast.FuncLit:
+		return syntax.Type.Func
+	case *ast.FuncDecl:
+		return syntax.Type.Func
+	}
+	return token.NoPos
+}
+
+// prettyFunc pretty-prints fn for the user interface.
+// TODO(adonovan): return HTML so we have more markup freedom.
+func prettyFunc(this *types.Package, fn *ssa.Function) string {
+	if fn.Parent() != nil {
+		return fmt.Sprintf("%s in %s",
+			types.TypeString(this, fn.Signature),
+			prettyFunc(this, fn.Parent()))
+	}
+	if fn.Synthetic != "" && fn.Name() == "init" {
+		// (This is the actual initializer, not a declared 'func init').
+		if fn.Pkg.Object == this {
+			return "package initializer"
+		}
+		return fmt.Sprintf("%q package initializer", fn.Pkg.Object.Path())
+	}
+	return fn.RelString(this)
+}
+
+// -- intra-package callgraph ------------------------------------------
+
+// pcgNode represents a node in the package call graph (PCG).
+type pcgNode struct {
+	fn     *ssa.Function
+	pretty string  // cache of prettyFunc(fn)
+	edges  big.Int // set of callee func indices
+}
+
+// A packageCallGraph represents the intra-package edges of the global call graph.
+// The zeroth node indicates "all external functions".
+type packageCallGraph struct {
+	nodeIndex map[*ssa.Function]int // maps func to node index (a small int)
+	nodes     []*pcgNode            // maps node index to node
+}
+
+// sortNodes populates pcg.nodes in name order and updates the nodeIndex.
+func (pcg *packageCallGraph) sortNodes() {
+	nodes := make([]*pcgNode, 0, len(pcg.nodeIndex))
+	nodes = append(nodes, &pcgNode{fn: nil, pretty: "<external>"})
+	for fn := range pcg.nodeIndex {
+		nodes = append(nodes, &pcgNode{
+			fn:     fn,
+			pretty: prettyFunc(fn.Pkg.Object, fn),
+		})
+	}
+	sort.Sort(pcgNodesByPretty(nodes[1:]))
+	for i, n := range nodes {
+		pcg.nodeIndex[n.fn] = i
+	}
+	pcg.nodes = nodes
+}
+
+func (pcg *packageCallGraph) addEdge(caller, callee *ssa.Function) {
+	var callerIndex int
+	if caller.Pkg == callee.Pkg {
+		// intra-package edge
+		callerIndex = pcg.nodeIndex[caller]
+		if callerIndex < 1 {
+			panic(caller)
+		}
+	}
+	edges := &pcg.nodes[callerIndex].edges
+	edges.SetBit(edges, pcg.nodeIndex[callee], 1)
+}
+
+func (a *analysis) pcgAddNode(fn *ssa.Function) {
+	if fn.Pkg == nil {
+		return
+	}
+	pcg, ok := a.pcgs[fn.Pkg]
+	if !ok {
+		pcg = &packageCallGraph{nodeIndex: make(map[*ssa.Function]int)}
+		a.pcgs[fn.Pkg] = pcg
+	}
+	pcg.nodeIndex[fn] = -1
+}
+
+func (a *analysis) pcgAddEdge(caller, callee *ssa.Function) {
+	if callee.Pkg != nil {
+		a.pcgs[callee.Pkg].addEdge(caller, callee)
+	}
+}
+
+// pcgJSON returns a new slice of callgraph JSON values.
+func (a *analysis) pcgJSON(pcg *packageCallGraph) []*PCGNodeJSON {
+	var nodes []*PCGNodeJSON
+	for _, n := range pcg.nodes {
+
+		// TODO(adonovan): why is there no good way to iterate
+		// over the set bits of a big.Int?
+		var callees []int
+		nbits := n.edges.BitLen()
+		for j := 0; j < nbits; j++ {
+			if n.edges.Bit(j) == 1 {
+				callees = append(callees, j)
+			}
+		}
+
+		var pos token.Pos
+		if n.fn != nil {
+			pos = funcToken(n.fn)
+		}
+		nodes = append(nodes, &PCGNodeJSON{
+			Func: anchorJSON{
+				Text: n.pretty,
+				Href: a.posURL(pos, len("func")),
+			},
+			Callees: callees,
+		})
+	}
+	return nodes
+}
+
+type pcgNodesByPretty []*pcgNode
+
+func (a pcgNodesByPretty) Less(i, j int) bool { return a[i].pretty < a[j].pretty }
+func (a pcgNodesByPretty) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a pcgNodesByPretty) Len() int           { return len(a) }
diff --git a/third_party/go.tools/godoc/analysis/implements.go b/third_party/go.tools/godoc/analysis/implements.go
new file mode 100644
index 0000000..f8e2473
--- /dev/null
+++ b/third_party/go.tools/godoc/analysis/implements.go
@@ -0,0 +1,194 @@
+// Copyright 2014 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 analysis
+
+// This file computes the "implements" relation over all pairs of
+// named types in the program.  (The mark-up is done by typeinfo.go.)
+
+// TODO(adonovan): do we want to report implements(C, I) where C and I
+// belong to different packages and at least one is not exported?
+
+import (
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// computeImplements computes the "implements" relation over all pairs
+// of named types in allNamed.
+func computeImplements(cache *types.MethodSetCache, allNamed []*types.Named) map[*types.Named]implementsFacts {
+	// Information about a single type's method set.
+	type msetInfo struct {
+		typ          types.Type
+		mset         *types.MethodSet
+		mask1, mask2 uint64
+	}
+
+	initMsetInfo := func(info *msetInfo, typ types.Type) {
+		info.typ = typ
+		info.mset = cache.MethodSet(typ)
+		for i := 0; i < info.mset.Len(); i++ {
+			name := info.mset.At(i).Obj().Name()
+			info.mask1 |= 1 << methodBit(name[0])
+			info.mask2 |= 1 << methodBit(name[len(name)-1])
+		}
+	}
+
+	// satisfies(T, U) reports whether type T satisfies type U.
+	// U must be an interface.
+	//
+	// Since there are thousands of types (and thus millions of
+	// pairs of types) and types.Assignable(T, U) is relatively
+	// expensive, we compute assignability directly from the
+	// method sets.  (At least one of T and U must be an
+	// interface.)
+	//
+	// We use a trick (thanks gri!) related to a Bloom filter to
+	// quickly reject most tests, which are false.  For each
+	// method set, we precompute a mask, a set of bits, one per
+	// distinct initial byte of each method name.  Thus the mask
+	// for io.ReadWriter would be {'R','W'}.  AssignableTo(T, U)
+	// cannot be true unless mask(T)&mask(U)==mask(U).
+	//
+	// As with a Bloom filter, we can improve precision by testing
+	// additional hashes, e.g. using the last letter of each
+	// method name, so long as the subset mask property holds.
+	//
+	// When analyzing the standard library, there are about 1e6
+	// calls to satisfies(), of which 0.6% return true.  With a
+	// 1-hash filter, 95% of calls avoid the expensive check; with
+	// a 2-hash filter, this grows to 98.2%.
+	satisfies := func(T, U *msetInfo) bool {
+		return T.mask1&U.mask1 == U.mask1 &&
+			T.mask2&U.mask2 == U.mask2 &&
+			containsAllIdsOf(T.mset, U.mset)
+	}
+
+	// Information about a named type N, and perhaps also *N.
+	type namedInfo struct {
+		isInterface bool
+		base        msetInfo // N
+		ptr         msetInfo // *N, iff N !isInterface
+	}
+
+	var infos []namedInfo
+
+	// Precompute the method sets and their masks.
+	for _, N := range allNamed {
+		var info namedInfo
+		initMsetInfo(&info.base, N)
+		_, info.isInterface = N.Underlying().(*types.Interface)
+		if !info.isInterface {
+			initMsetInfo(&info.ptr, types.NewPointer(N))
+		}
+
+		if info.base.mask1|info.ptr.mask1 == 0 {
+			continue // neither N nor *N has methods
+		}
+
+		infos = append(infos, info)
+	}
+
+	facts := make(map[*types.Named]implementsFacts)
+
+	// Test all pairs of distinct named types (T, U).
+	// TODO(adonovan): opt: compute (U, T) at the same time.
+	for t := range infos {
+		T := &infos[t]
+		var to, from, fromPtr []types.Type
+		for u := range infos {
+			if t == u {
+				continue
+			}
+			U := &infos[u]
+			switch {
+			case T.isInterface && U.isInterface:
+				if satisfies(&U.base, &T.base) {
+					to = append(to, U.base.typ)
+				}
+				if satisfies(&T.base, &U.base) {
+					from = append(from, U.base.typ)
+				}
+			case T.isInterface: // U concrete
+				if satisfies(&U.base, &T.base) {
+					to = append(to, U.base.typ)
+				} else if satisfies(&U.ptr, &T.base) {
+					to = append(to, U.ptr.typ)
+				}
+			case U.isInterface: // T concrete
+				if satisfies(&T.base, &U.base) {
+					from = append(from, U.base.typ)
+				} else if satisfies(&T.ptr, &U.base) {
+					fromPtr = append(fromPtr, U.base.typ)
+				}
+			}
+		}
+
+		// Sort types (arbitrarily) to avoid nondeterminism.
+		sort.Sort(typesByString(to))
+		sort.Sort(typesByString(from))
+		sort.Sort(typesByString(fromPtr))
+
+		facts[T.base.typ.(*types.Named)] = implementsFacts{to, from, fromPtr}
+	}
+
+	return facts
+}
+
+type implementsFacts struct {
+	to      []types.Type // named or ptr-to-named types assignable to interface T
+	from    []types.Type // named interfaces assignable from T
+	fromPtr []types.Type // named interfaces assignable only from *T
+}
+
+type typesByString []types.Type
+
+func (p typesByString) Len() int           { return len(p) }
+func (p typesByString) Less(i, j int) bool { return p[i].String() < p[j].String() }
+func (p typesByString) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// methodBit returns the index of x in [a-zA-Z], or 52 if not found.
+func methodBit(x byte) uint64 {
+	switch {
+	case 'a' <= x && x <= 'z':
+		return uint64(x - 'a')
+	case 'A' <= x && x <= 'Z':
+		return uint64(26 + x - 'A')
+	}
+	return 52 // all other bytes
+}
+
+// containsAllIdsOf reports whether the method identifiers of T are a
+// superset of those in U.  If U belongs to an interface type, the
+// result is equal to types.Assignable(T, U), but is cheaper to compute.
+//
+// TODO(gri): make this a method of *types.MethodSet.
+//
+func containsAllIdsOf(T, U *types.MethodSet) bool {
+	t, tlen := 0, T.Len()
+	u, ulen := 0, U.Len()
+	for t < tlen && u < ulen {
+		tMeth := T.At(t).Obj()
+		uMeth := U.At(u).Obj()
+		tId := tMeth.Id()
+		uId := uMeth.Id()
+		if tId > uId {
+			// U has a method T lacks: fail.
+			return false
+		}
+		if tId < uId {
+			// T has a method U lacks: ignore it.
+			t++
+			continue
+		}
+		// U and T both have a method of this Id.  Check types.
+		if !types.Identical(tMeth.Type(), uMeth.Type()) {
+			return false // type mismatch
+		}
+		u++
+		t++
+	}
+	return u == ulen
+}
diff --git a/third_party/go.tools/godoc/analysis/json.go b/third_party/go.tools/godoc/analysis/json.go
new file mode 100644
index 0000000..f897618
--- /dev/null
+++ b/third_party/go.tools/godoc/analysis/json.go
@@ -0,0 +1,69 @@
+// Copyright 2014 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 analysis
+
+// This file defines types used by client-side JavaScript.
+
+type anchorJSON struct {
+	Text string // HTML
+	Href string // URL
+}
+
+type commOpJSON struct {
+	Op anchorJSON
+	Fn string
+}
+
+// JavaScript's onClickComm() expects a commJSON.
+type commJSON struct {
+	Ops []commOpJSON
+}
+
+// Indicates one of these forms of fact about a type T:
+// T "is implemented by <ByKind> type <Other>"  (ByKind != "", e.g. "array")
+// T "implements <Other>"                       (ByKind == "")
+type implFactJSON struct {
+	ByKind string `json:",omitempty"`
+	Other  anchorJSON
+}
+
+// Implements facts are grouped by form, for ease of reading.
+type implGroupJSON struct {
+	Descr string
+	Facts []implFactJSON
+}
+
+// JavaScript's onClickIdent() expects a TypeInfoJSON.
+type TypeInfoJSON struct {
+	Name        string // type name
+	Size, Align int64
+	Methods     []anchorJSON
+	ImplGroups  []implGroupJSON
+}
+
+// JavaScript's onClickCallees() expects a calleesJSON.
+type calleesJSON struct {
+	Descr   string
+	Callees []anchorJSON // markup for called function
+}
+
+type callerJSON struct {
+	Func  string
+	Sites []anchorJSON
+}
+
+// JavaScript's onClickCallers() expects a callersJSON.
+type callersJSON struct {
+	Callee  string
+	Callers []callerJSON
+}
+
+// JavaScript's cgAddChild requires a global array of PCGNodeJSON
+// called CALLGRAPH, representing the intra-package call graph.
+// The first element is special and represents "all external callers".
+type PCGNodeJSON struct {
+	Func    anchorJSON
+	Callees []int // indices within CALLGRAPH of nodes called by this one
+}
diff --git a/third_party/go.tools/godoc/analysis/peers.go b/third_party/go.tools/godoc/analysis/peers.go
new file mode 100644
index 0000000..ee4d538
--- /dev/null
+++ b/third_party/go.tools/godoc/analysis/peers.go
@@ -0,0 +1,154 @@
+// Copyright 2014 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 analysis
+
+// This file computes the channel "peers" relation over all pairs of
+// channel operations in the program.  The peers are displayed in the
+// lower pane when a channel operation (make, <-, close) is clicked.
+
+// TODO(adonovan): handle calls to reflect.{Select,Recv,Send,Close} too,
+// then enable reflection in PTA.
+
+import (
+	"fmt"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/pointer"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func (a *analysis) doChannelPeers(ptsets map[ssa.Value]pointer.Pointer) {
+	addSendRecv := func(j *commJSON, op chanOp) {
+		j.Ops = append(j.Ops, commOpJSON{
+			Op: anchorJSON{
+				Text: op.mode,
+				Href: a.posURL(op.pos, op.len),
+			},
+			Fn: prettyFunc(nil, op.fn),
+		})
+	}
+
+	// Build an undirected bipartite multigraph (binary relation)
+	// of MakeChan ops and send/recv/close ops.
+	//
+	// TODO(adonovan): opt: use channel element types to partition
+	// the O(n^2) problem into subproblems.
+	aliasedOps := make(map[*ssa.MakeChan][]chanOp)
+	opToMakes := make(map[chanOp][]*ssa.MakeChan)
+	for _, op := range a.ops {
+		// Combine the PT sets from all contexts.
+		var makes []*ssa.MakeChan // aliased ops
+		ptr, ok := ptsets[op.ch]
+		if !ok {
+			continue // e.g. channel op in dead code
+		}
+		for _, label := range ptr.PointsTo().Labels() {
+			makechan, ok := label.Value().(*ssa.MakeChan)
+			if !ok {
+				continue // skip intrinsically-created channels for now
+			}
+			if makechan.Pos() == token.NoPos {
+				continue // not possible?
+			}
+			makes = append(makes, makechan)
+			aliasedOps[makechan] = append(aliasedOps[makechan], op)
+		}
+		opToMakes[op] = makes
+	}
+
+	// Now that complete relation is built, build links for ops.
+	for _, op := range a.ops {
+		v := commJSON{
+			Ops: []commOpJSON{}, // (JS wants non-nil)
+		}
+		ops := make(map[chanOp]bool)
+		for _, makechan := range opToMakes[op] {
+			v.Ops = append(v.Ops, commOpJSON{
+				Op: anchorJSON{
+					Text: "made",
+					Href: a.posURL(makechan.Pos()-token.Pos(len("make")),
+						len("make")),
+				},
+				Fn: makechan.Parent().RelString(op.fn.Package().Object),
+			})
+			for _, op := range aliasedOps[makechan] {
+				ops[op] = true
+			}
+		}
+		for op := range ops {
+			addSendRecv(&v, op)
+		}
+
+		// Add links for each aliased op.
+		fi, offset := a.fileAndOffset(op.pos)
+		fi.addLink(aLink{
+			start:   offset,
+			end:     offset + op.len,
+			title:   "show channel ops",
+			onclick: fmt.Sprintf("onClickComm(%d)", fi.addData(v)),
+		})
+	}
+	// Add links for makechan ops themselves.
+	for makechan, ops := range aliasedOps {
+		v := commJSON{
+			Ops: []commOpJSON{}, // (JS wants non-nil)
+		}
+		for _, op := range ops {
+			addSendRecv(&v, op)
+		}
+
+		fi, offset := a.fileAndOffset(makechan.Pos())
+		fi.addLink(aLink{
+			start:   offset - len("make"),
+			end:     offset,
+			title:   "show channel ops",
+			onclick: fmt.Sprintf("onClickComm(%d)", fi.addData(v)),
+		})
+	}
+}
+
+// -- utilities --------------------------------------------------------
+
+// chanOp abstracts an ssa.Send, ssa.Unop(ARROW), close(), or a SelectState.
+// Derived from oracle/peers.go.
+type chanOp struct {
+	ch   ssa.Value
+	mode string // sent|received|closed
+	pos  token.Pos
+	len  int
+	fn   *ssa.Function
+}
+
+// chanOps returns a slice of all the channel operations in the instruction.
+// Derived from oracle/peers.go.
+func chanOps(instr ssa.Instruction) []chanOp {
+	fn := instr.Parent()
+	var ops []chanOp
+	switch instr := instr.(type) {
+	case *ssa.UnOp:
+		if instr.Op == token.ARROW {
+			// TODO(adonovan): don't assume <-ch; could be 'range ch'.
+			ops = append(ops, chanOp{instr.X, "received", instr.Pos(), len("<-"), fn})
+		}
+	case *ssa.Send:
+		ops = append(ops, chanOp{instr.Chan, "sent", instr.Pos(), len("<-"), fn})
+	case *ssa.Select:
+		for _, st := range instr.States {
+			mode := "received"
+			if st.Dir == types.SendOnly {
+				mode = "sent"
+			}
+			ops = append(ops, chanOp{st.Chan, mode, st.Pos, len("<-"), fn})
+		}
+	case ssa.CallInstruction:
+		call := instr.Common()
+		if blt, ok := call.Value.(*ssa.Builtin); ok && blt.Name() == "close" {
+			pos := instr.Common().Pos()
+			ops = append(ops, chanOp{call.Args[0], "closed", pos - token.Pos(len("close")), len("close("), fn})
+		}
+	}
+	return ops
+}
diff --git a/third_party/go.tools/godoc/analysis/typeinfo.go b/third_party/go.tools/godoc/analysis/typeinfo.go
new file mode 100644
index 0000000..a997e04
--- /dev/null
+++ b/third_party/go.tools/godoc/analysis/typeinfo.go
@@ -0,0 +1,234 @@
+// Copyright 2014 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 analysis
+
+// This file computes the markup for information from go/types:
+// IMPORTS, identifier RESOLUTION, METHOD SETS, size/alignment, and
+// the IMPLEMENTS relation.
+//
+// IMPORTS links connect import specs to the documentation for the
+// imported package.
+//
+// RESOLUTION links referring identifiers to their defining
+// identifier, and adds tooltips for kind and type.
+//
+// METHOD SETS, size/alignment, and the IMPLEMENTS relation are
+// displayed in the lower pane when a type's defining identifier is
+// clicked.
+
+import (
+	"fmt"
+	"reflect"
+	"strconv"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+// TODO(adonovan): audit to make sure it's safe on ill-typed packages.
+
+// TODO(adonovan): use same Sizes as loader.Config.
+var sizes = types.StdSizes{8, 8}
+
+func (a *analysis) doTypeInfo(info *loader.PackageInfo, implements map[*types.Named]implementsFacts) {
+	// We must not assume the corresponding SSA packages were
+	// created (i.e. were transitively error-free).
+
+	// IMPORTS
+	for _, f := range info.Files {
+		// Package decl.
+		fi, offset := a.fileAndOffset(f.Name.Pos())
+		fi.addLink(aLink{
+			start: offset,
+			end:   offset + len(f.Name.Name),
+			title: "Package docs for " + info.Pkg.Path(),
+			// TODO(adonovan): fix: we're putting the untrusted Path()
+			// into a trusted field.  What's the appropriate sanitizer?
+			href: "/pkg/" + info.Pkg.Path(),
+		})
+
+		// Import specs.
+		for _, imp := range f.Imports {
+			// Remove quotes.
+			L := int(imp.End()-imp.Path.Pos()) - len(`""`)
+			path, _ := strconv.Unquote(imp.Path.Value)
+			fi, offset := a.fileAndOffset(imp.Path.Pos())
+			fi.addLink(aLink{
+				start: offset + 1,
+				end:   offset + 1 + L,
+				title: "Package docs for " + path,
+				// TODO(adonovan): fix: we're putting the untrusted path
+				// into a trusted field.  What's the appropriate sanitizer?
+				href: "/pkg/" + path,
+			})
+		}
+	}
+
+	// RESOLUTION
+	for id, obj := range info.Uses {
+		// Position of the object definition.
+		pos := obj.Pos()
+		Len := len(obj.Name())
+
+		// Correct the position for non-renaming import specs.
+		//  import "sync/atomic"
+		//          ^^^^^^^^^^^
+		if obj, ok := obj.(*types.PkgName); ok && id.Name == obj.Imported().Name() {
+			// Assume this is a non-renaming import.
+			// NB: not true for degenerate renamings: `import foo "foo"`.
+			pos++
+			Len = len(obj.Imported().Path())
+		}
+
+		if obj.Pkg() == nil {
+			continue // don't mark up built-ins.
+		}
+
+		fi, offset := a.fileAndOffset(id.NamePos)
+		fi.addLink(aLink{
+			start: offset,
+			end:   offset + len(id.Name),
+			title: types.ObjectString(info.Pkg, obj),
+			href:  a.posURL(pos, Len),
+		})
+	}
+
+	// IMPLEMENTS & METHOD SETS
+	for _, obj := range info.Defs {
+		if obj, ok := obj.(*types.TypeName); ok {
+			a.namedType(obj, implements)
+		}
+	}
+}
+
+func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]implementsFacts) {
+	this := obj.Pkg()
+	T := obj.Type().(*types.Named)
+	v := &TypeInfoJSON{
+		Name:    obj.Name(),
+		Size:    sizes.Sizeof(T),
+		Align:   sizes.Alignof(T),
+		Methods: []anchorJSON{}, // (JS wants non-nil)
+	}
+
+	// addFact adds the fact "is implemented by T" (by) or
+	// "implements T" (!by) to group.
+	addFact := func(group *implGroupJSON, T types.Type, by bool) {
+		Tobj := deref(T).(*types.Named).Obj()
+		var byKind string
+		if by {
+			// Show underlying kind of implementing type,
+			// e.g. "slice", "array", "struct".
+			s := reflect.TypeOf(T.Underlying()).String()
+			byKind = strings.ToLower(strings.TrimPrefix(s, "*types."))
+		}
+		group.Facts = append(group.Facts, implFactJSON{
+			ByKind: byKind,
+			Other: anchorJSON{
+				Href: a.posURL(Tobj.Pos(), len(Tobj.Name())),
+				Text: types.TypeString(this, T),
+			},
+		})
+	}
+
+	// IMPLEMENTS
+	if r, ok := implements[T]; ok {
+		if isInterface(T) {
+			// "T is implemented by <conc>" ...
+			// "T is implemented by <iface>"...
+			// "T implements        <iface>"...
+			group := implGroupJSON{
+				Descr: types.TypeString(this, T),
+			}
+			// Show concrete types first; use two passes.
+			for _, sub := range r.to {
+				if !isInterface(sub) {
+					addFact(&group, sub, true)
+				}
+			}
+			for _, sub := range r.to {
+				if isInterface(sub) {
+					addFact(&group, sub, true)
+				}
+			}
+			for _, super := range r.from {
+				addFact(&group, super, false)
+			}
+			v.ImplGroups = append(v.ImplGroups, group)
+		} else {
+			// T is concrete.
+			if r.from != nil {
+				// "T implements <iface>"...
+				group := implGroupJSON{
+					Descr: types.TypeString(this, T),
+				}
+				for _, super := range r.from {
+					addFact(&group, super, false)
+				}
+				v.ImplGroups = append(v.ImplGroups, group)
+			}
+			if r.fromPtr != nil {
+				// "*C implements <iface>"...
+				group := implGroupJSON{
+					Descr: "*" + types.TypeString(this, T),
+				}
+				for _, psuper := range r.fromPtr {
+					addFact(&group, psuper, false)
+				}
+				v.ImplGroups = append(v.ImplGroups, group)
+			}
+		}
+	}
+
+	// METHOD SETS
+	for _, sel := range typeutil.IntuitiveMethodSet(T, &a.prog.MethodSets) {
+		meth := sel.Obj().(*types.Func)
+		pos := meth.Pos() // may be 0 for error.Error
+		v.Methods = append(v.Methods, anchorJSON{
+			Href: a.posURL(pos, len(meth.Name())),
+			Text: types.SelectionString(this, sel),
+		})
+	}
+
+	// Since there can be many specs per decl, we
+	// can't attach the link to the keyword 'type'
+	// (as we do with 'func'); we use the Ident.
+	fi, offset := a.fileAndOffset(obj.Pos())
+	fi.addLink(aLink{
+		start:   offset,
+		end:     offset + len(obj.Name()),
+		title:   fmt.Sprintf("type info for %s", obj.Name()),
+		onclick: fmt.Sprintf("onClickTypeInfo(%d)", fi.addData(v)),
+	})
+
+	// Add info for exported package-level types to the package info.
+	if obj.Exported() && isPackageLevel(obj) {
+		// TODO(adonovan): this.Path() is not unique!
+		// It is possible to declare a non-test package called x_test.
+		a.result.pkgInfo(this.Path()).addType(v)
+	}
+}
+
+// -- utilities --------------------------------------------------------
+
+func isInterface(T types.Type) bool {
+	_, isI := T.Underlying().(*types.Interface)
+	return isI
+}
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// isPackageLevel reports whether obj is a package-level object.
+func isPackageLevel(obj types.Object) bool {
+	return obj.Pkg().Scope().Lookup(obj.Name()) == obj
+}
diff --git a/third_party/go.tools/godoc/cmdline.go b/third_party/go.tools/godoc/cmdline.go
new file mode 100644
index 0000000..ef9773f
--- /dev/null
+++ b/third_party/go.tools/godoc/cmdline.go
@@ -0,0 +1,206 @@
+// Copyright 2013 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 godoc
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"io"
+	"log"
+	"os"
+	pathpkg "path"
+	"path/filepath"
+	"regexp"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+const (
+	target    = "/target"
+	cmdPrefix = "cmd/"
+	srcPrefix = "src/"
+	toolsPath = "llvm.org/llgo/third_party/go.tools/cmd/"
+)
+
+// CommandLine returns godoc results to w.
+// Note that it may add a /target path to fs.
+func CommandLine(w io.Writer, fs vfs.NameSpace, pres *Presentation, args []string) error {
+	path := args[0]
+	srcMode := pres.SrcMode
+	cmdMode := strings.HasPrefix(path, cmdPrefix)
+	if strings.HasPrefix(path, srcPrefix) {
+		path = strings.TrimPrefix(path, srcPrefix)
+		srcMode = true
+	}
+	var abspath, relpath string
+	if cmdMode {
+		path = strings.TrimPrefix(path, cmdPrefix)
+	} else {
+		abspath, relpath = paths(fs, pres, path)
+	}
+
+	var mode PageInfoMode
+	if relpath == builtinPkgPath {
+		// the fake built-in package contains unexported identifiers
+		mode = NoFiltering | NoTypeAssoc
+	}
+	if srcMode {
+		// only filter exports if we don't have explicit command-line filter arguments
+		if len(args) > 1 {
+			mode |= NoFiltering
+		}
+		mode |= ShowSource
+	}
+
+	// First, try as package unless forced as command.
+	var info *PageInfo
+	if !cmdMode {
+		info = pres.GetPkgPageInfo(abspath, relpath, mode)
+	}
+
+	// Second, try as command (if the path is not absolute).
+	var cinfo *PageInfo
+	if !filepath.IsAbs(path) {
+		// First try go.tools/cmd.
+		abspath = pathpkg.Join(pres.PkgFSRoot(), toolsPath+path)
+		cinfo = pres.GetCmdPageInfo(abspath, relpath, mode)
+		if cinfo.IsEmpty() {
+			// Then try $GOROOT/cmd.
+			abspath = pathpkg.Join(pres.CmdFSRoot(), path)
+			cinfo = pres.GetCmdPageInfo(abspath, relpath, mode)
+		}
+	}
+
+	// determine what to use
+	if info == nil || info.IsEmpty() {
+		if cinfo != nil && !cinfo.IsEmpty() {
+			// only cinfo exists - switch to cinfo
+			info = cinfo
+		}
+	} else if cinfo != nil && !cinfo.IsEmpty() {
+		// both info and cinfo exist - use cinfo if info
+		// contains only subdirectory information
+		if info.PAst == nil && info.PDoc == nil {
+			info = cinfo
+		} else if relpath != target {
+			// The above check handles the case where an operating system path
+			// is provided (see documentation for paths below).  In that case,
+			// relpath is set to "/target" (in anticipation of accessing packages there),
+			// and is therefore not expected to match a command.
+			fmt.Fprintf(w, "use 'godoc %s%s' for documentation on the %s command \n\n", cmdPrefix, relpath, relpath)
+		}
+	}
+
+	if info == nil {
+		return fmt.Errorf("%s: no such directory or package", args[0])
+	}
+	if info.Err != nil {
+		return info.Err
+	}
+
+	if info.PDoc != nil && info.PDoc.ImportPath == target {
+		// Replace virtual /target with actual argument from command line.
+		info.PDoc.ImportPath = args[0]
+	}
+
+	// If we have more than one argument, use the remaining arguments for filtering.
+	if len(args) > 1 {
+		info.IsFiltered = true
+		filterInfo(args[1:], info)
+	}
+
+	packageText := pres.PackageText
+	if pres.HTMLMode {
+		packageText = pres.PackageHTML
+	}
+	if err := packageText.Execute(w, info); err != nil {
+		return err
+	}
+	return nil
+}
+
+// paths determines the paths to use.
+//
+// If we are passed an operating system path like . or ./foo or /foo/bar or c:\mysrc,
+// we need to map that path somewhere in the fs name space so that routines
+// like getPageInfo will see it.  We use the arbitrarily-chosen virtual path "/target"
+// for this.  That is, if we get passed a directory like the above, we map that
+// directory so that getPageInfo sees it as /target.
+// Returns the absolute and relative paths.
+func paths(fs vfs.NameSpace, pres *Presentation, path string) (string, string) {
+	if filepath.IsAbs(path) {
+		fs.Bind(target, vfs.OS(path), "/", vfs.BindReplace)
+		return target, target
+	}
+	if build.IsLocalImport(path) {
+		cwd, _ := os.Getwd() // ignore errors
+		path = filepath.Join(cwd, path)
+		fs.Bind(target, vfs.OS(path), "/", vfs.BindReplace)
+		return target, target
+	}
+	if bp, _ := build.Import(path, "", build.FindOnly); bp.Dir != "" && bp.ImportPath != "" {
+		fs.Bind(target, vfs.OS(bp.Dir), "/", vfs.BindReplace)
+		return target, bp.ImportPath
+	}
+	return pathpkg.Join(pres.PkgFSRoot(), path), path
+}
+
+// filterInfo updates info to include only the nodes that match the given
+// filter args.
+func filterInfo(args []string, info *PageInfo) {
+	rx, err := makeRx(args)
+	if err != nil {
+		log.Fatalf("illegal regular expression from %v: %v", args, err)
+	}
+
+	filter := func(s string) bool { return rx.MatchString(s) }
+	switch {
+	case info.PAst != nil:
+		newPAst := map[string]*ast.File{}
+		for name, a := range info.PAst {
+			cmap := ast.NewCommentMap(info.FSet, a, a.Comments)
+			a.Comments = []*ast.CommentGroup{} // remove all comments.
+			ast.FilterFile(a, filter)
+			if len(a.Decls) > 0 {
+				newPAst[name] = a
+			}
+			for _, d := range a.Decls {
+				// add back the comments associated with d only
+				comments := cmap.Filter(d).Comments()
+				a.Comments = append(a.Comments, comments...)
+			}
+		}
+		info.PAst = newPAst // add only matching files.
+	case info.PDoc != nil:
+		info.PDoc.Filter(filter)
+	}
+}
+
+// Does s look like a regular expression?
+func isRegexp(s string) bool {
+	return strings.IndexAny(s, ".(|)*+?^$[]") >= 0
+}
+
+// Make a regular expression of the form
+// names[0]|names[1]|...names[len(names)-1].
+// Returns an error if the regular expression is illegal.
+func makeRx(names []string) (*regexp.Regexp, error) {
+	if len(names) == 0 {
+		return nil, fmt.Errorf("no expression provided")
+	}
+	s := ""
+	for i, name := range names {
+		if i > 0 {
+			s += "|"
+		}
+		if isRegexp(name) {
+			s += name
+		} else {
+			s += "^" + name + "$" // must match exactly
+		}
+	}
+	return regexp.Compile(s)
+}
diff --git a/third_party/go.tools/godoc/cmdline_test.go b/third_party/go.tools/godoc/cmdline_test.go
new file mode 100644
index 0000000..7b10be9
--- /dev/null
+++ b/third_party/go.tools/godoc/cmdline_test.go
@@ -0,0 +1,290 @@
+package godoc
+
+import (
+	"bytes"
+	"go/build"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"reflect"
+	"regexp"
+	"runtime"
+	"testing"
+	"text/template"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs/mapfs"
+)
+
+// setupGoroot creates temporary directory to act as GOROOT when running tests
+// that depend upon the build package.  It updates build.Default to point to the
+// new GOROOT.
+// It returns a function that can be called to reset build.Default and remove
+// the temporary directory.
+func setupGoroot(t *testing.T) (cleanup func()) {
+	var stdLib = map[string]string{
+		"src/fmt/fmt.go": `// Package fmt implements formatted I/O.
+package fmt
+
+type Stringer interface {
+	String() string
+}
+`,
+	}
+	goroot, err := ioutil.TempDir("", "cmdline_test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	origContext := build.Default
+	build.Default = build.Context{
+		GOROOT:   goroot,
+		Compiler: "gc",
+	}
+	for relname, contents := range stdLib {
+		name := filepath.Join(goroot, relname)
+		if err := os.MkdirAll(filepath.Dir(name), 0770); err != nil {
+			t.Fatal(err)
+		}
+		if err := ioutil.WriteFile(name, []byte(contents), 0770); err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	return func() {
+		if err := os.RemoveAll(goroot); err != nil {
+			t.Log(err)
+		}
+		build.Default = origContext
+	}
+}
+
+func TestPaths(t *testing.T) {
+	cleanup := setupGoroot(t)
+	defer cleanup()
+
+	pres := &Presentation{
+		pkgHandler: handlerServer{
+			fsRoot: "/fsroot",
+		},
+	}
+	fs := make(vfs.NameSpace)
+
+	absPath := "/foo/fmt"
+	if runtime.GOOS == "windows" {
+		absPath = `c:\foo\fmt`
+	}
+
+	for _, tc := range []struct {
+		desc   string
+		path   string
+		expAbs string
+		expRel string
+	}{
+		{
+			"Absolute path",
+			absPath,
+			"/target",
+			"/target",
+		},
+		{
+			"Local import",
+			"../foo/fmt",
+			"/target",
+			"/target",
+		},
+		{
+			"Import",
+			"fmt",
+			"/target",
+			"fmt",
+		},
+		{
+			"Default",
+			"unknownpkg",
+			"/fsroot/unknownpkg",
+			"unknownpkg",
+		},
+	} {
+		abs, rel := paths(fs, pres, tc.path)
+		if abs != tc.expAbs || rel != tc.expRel {
+			t.Errorf("%s: paths(%q) = %s,%s; want %s,%s", tc.desc, tc.path, abs, rel, tc.expAbs, tc.expRel)
+		}
+	}
+}
+
+func TestMakeRx(t *testing.T) {
+	for _, tc := range []struct {
+		desc  string
+		names []string
+		exp   string
+	}{
+		{
+			desc:  "empty string",
+			names: []string{""},
+			exp:   `^$`,
+		},
+		{
+			desc:  "simple text",
+			names: []string{"a"},
+			exp:   `^a$`,
+		},
+		{
+			desc:  "two words",
+			names: []string{"foo", "bar"},
+			exp:   `^foo$|^bar$`,
+		},
+		{
+			desc:  "word & non-trivial",
+			names: []string{"foo", `ab?c`},
+			exp:   `^foo$|ab?c`,
+		},
+		{
+			desc:  "bad regexp",
+			names: []string{`(."`},
+			exp:   `(."`,
+		},
+	} {
+		expRE, expErr := regexp.Compile(tc.exp)
+		if re, err := makeRx(tc.names); !reflect.DeepEqual(err, expErr) && !reflect.DeepEqual(re, expRE) {
+			t.Errorf("%s: makeRx(%v) = %q,%q; want %q,%q", tc.desc, tc.names, re, err, expRE, expErr)
+		}
+	}
+}
+
+func TestCommandLine(t *testing.T) {
+	cleanup := setupGoroot(t)
+	defer cleanup()
+	mfs := mapfs.New(map[string]string{
+		"src/bar/bar.go": `// Package bar is an example.
+package bar
+`,
+		"src/foo/foo.go": `// Package foo.
+package foo
+
+// First function is first.
+func First() {
+}
+
+// Second function is second.
+func Second() {
+}
+`,
+		"src/gen/gen.go": `// Package gen
+package gen
+
+//line notgen.go:3
+// F doc //line 1 should appear
+// line 2 should appear
+func F()
+//line foo.go:100`, // no newline on end to check corner cases!
+		"src/vet/vet.go": `// Package vet
+package vet
+`,
+		"src/cmd/go/doc.go": `// The go command
+package main
+`,
+		"src/cmd/gofmt/doc.go": `// The gofmt command
+package main
+`,
+		"src/cmd/vet/vet.go": `// The vet command
+package main
+`,
+	})
+	fs := make(vfs.NameSpace)
+	fs.Bind("/", mfs, "/", vfs.BindReplace)
+	c := NewCorpus(fs)
+	p := &Presentation{Corpus: c}
+	p.cmdHandler = handlerServer{
+		p:       p,
+		c:       c,
+		pattern: "/cmd/",
+		fsRoot:  "/src/cmd",
+	}
+	p.pkgHandler = handlerServer{
+		p:       p,
+		c:       c,
+		pattern: "/pkg/",
+		fsRoot:  "/src",
+		exclude: []string{"/src/cmd"},
+	}
+	p.initFuncMap()
+	p.PackageText = template.Must(template.New("PackageText").Funcs(p.FuncMap()).Parse(`{{$info := .}}{{$filtered := .IsFiltered}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
+{{node $ $ast}}{{end}}{{end}}{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND {{.Doc}}{{else}}PACKAGE {{.Doc}}{{end}}{{with .Funcs}}
+{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}{{end}}{{end}}{{end}}`))
+
+	for _, tc := range []struct {
+		desc string
+		args []string
+		exp  string
+		err  bool
+	}{
+		{
+			desc: "standard package",
+			args: []string{"fmt"},
+			exp:  "PACKAGE Package fmt implements formatted I/O.\n",
+		},
+		{
+			desc: "package",
+			args: []string{"bar"},
+			exp:  "PACKAGE Package bar is an example.\n",
+		},
+		{
+			desc: "package w. filter",
+			args: []string{"foo", "First"},
+			exp:  "PACKAGE \nfunc First()\n    First function is first.\n",
+		},
+		{
+			desc: "package w. bad filter",
+			args: []string{"foo", "DNE"},
+			exp:  "PACKAGE ",
+		},
+		{
+			desc: "source mode",
+			args: []string{"src/bar"},
+			exp:  "bar/bar.go:\n// Package bar is an example.\npackage bar\n",
+		},
+		{
+			desc: "source mode w. filter",
+			args: []string{"src/foo", "Second"},
+			exp:  "// Second function is second.\nfunc Second() {\n}",
+		},
+		{
+			desc: "package w. //line comments",
+			args: []string{"gen", "F"},
+			exp:  "PACKAGE \nfunc F()\n    F doc //line 1 should appear line 2 should appear\n",
+		},
+		{
+			desc: "command",
+			args: []string{"go"},
+			exp:  "COMMAND The go command\n",
+		},
+		{
+			desc: "forced command",
+			args: []string{"cmd/gofmt"},
+			exp:  "COMMAND The gofmt command\n",
+		},
+		{
+			desc: "bad arg",
+			args: []string{"doesnotexist"},
+			err:  true,
+		},
+		{
+			desc: "both command and package",
+			args: []string{"vet"},
+			exp:  "use 'godoc cmd/vet' for documentation on the vet command \n\nPACKAGE Package vet\n",
+		},
+		{
+			desc: "root directory",
+			args: []string{"/"},
+			exp:  "",
+		},
+	} {
+		w := new(bytes.Buffer)
+		err := CommandLine(w, fs, p, tc.args)
+		if got, want := w.String(), tc.exp; got != want || tc.err == (err == nil) {
+			t.Errorf("%s: CommandLine(%v) = %q (%v); want %q (%v)",
+				tc.desc, tc.args, got, err, want, tc.err)
+		}
+	}
+}
diff --git a/third_party/go.tools/godoc/corpus.go b/third_party/go.tools/godoc/corpus.go
new file mode 100644
index 0000000..dfaeb51
--- /dev/null
+++ b/third_party/go.tools/godoc/corpus.go
@@ -0,0 +1,157 @@
+// Copyright 2013 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 godoc
+
+import (
+	"errors"
+	pathpkg "path"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/analysis"
+	"llvm.org/llgo/third_party/go.tools/godoc/util"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+// A Corpus holds all the state related to serving and indexing a
+// collection of Go code.
+//
+// Construct a new Corpus with NewCorpus, then modify options,
+// then call its Init method.
+type Corpus struct {
+	fs vfs.FileSystem
+
+	// Verbose logging.
+	Verbose bool
+
+	// IndexEnabled controls whether indexing is enabled.
+	IndexEnabled bool
+
+	// IndexFiles specifies a glob pattern specifying index files.
+	// If not empty, the index is read from these files in sorted
+	// order.
+	IndexFiles string
+
+	// IndexThrottle specifies the indexing throttle value
+	// between 0.0 and 1.0. At 0.0, the indexer always sleeps.
+	// At 1.0, the indexer never sleeps. Because 0.0 is useless
+	// and redundant with setting IndexEnabled to false, the
+	// zero value for IndexThrottle means 0.9.
+	IndexThrottle float64
+
+	// IndexInterval specifies the time to sleep between reindexing
+	// all the sources.
+	// If zero, a default is used. If negative, the index is only
+	// built once.
+	IndexInterval time.Duration
+
+	// IndexDocs enables indexing of Go documentation.
+	// This will produce search results for exported types, functions,
+	// methods, variables, and constants, and will link to the godoc
+	// documentation for those identifiers.
+	IndexDocs bool
+
+	// IndexGoCode enables indexing of Go source code.
+	// This will produce search results for internal and external identifiers
+	// and will link to both declarations and uses of those identifiers in
+	// source code.
+	IndexGoCode bool
+
+	// IndexFullText enables full-text indexing.
+	// This will provide search results for any matching text in any file that
+	// is indexed, including non-Go files (see whitelisted in index.go).
+	// Regexp searching is supported via full-text indexing.
+	IndexFullText bool
+
+	// MaxResults optionally specifies the maximum results for indexing.
+	MaxResults int
+
+	// SummarizePackage optionally specifies a function to
+	// summarize a package. It exists as an optimization to
+	// avoid reading files to parse package comments.
+	//
+	// If SummarizePackage returns false for ok, the caller
+	// ignores all return values and parses the files in the package
+	// as if SummarizePackage were nil.
+	//
+	// If showList is false, the package is hidden from the
+	// package listing.
+	SummarizePackage func(pkg string) (summary string, showList, ok bool)
+
+	// IndexDirectory optionally specifies a function to determine
+	// whether the provided directory should be indexed.  The dir
+	// will be of the form "/src/cmd/6a", "/doc/play",
+	// "/src/io", etc.
+	// If nil, all directories are indexed if indexing is enabled.
+	IndexDirectory func(dir string) bool
+
+	testDir string // TODO(bradfitz,adg): migrate old godoc flag? looks unused.
+
+	// Send a value on this channel to trigger a metadata refresh.
+	// It is buffered so that if a signal is not lost if sent
+	// during a refresh.
+	refreshMetadataSignal chan bool
+
+	// file system information
+	fsTree      util.RWValue // *Directory tree of packages, updated with each sync (but sync code is removed now)
+	fsModified  util.RWValue // timestamp of last call to invalidateIndex
+	docMetadata util.RWValue // mapping from paths to *Metadata
+
+	// SearchIndex is the search index in use.
+	searchIndex util.RWValue
+
+	// Analysis is the result of type and pointer analysis.
+	Analysis analysis.Result
+}
+
+// NewCorpus returns a new Corpus from a filesystem.
+// The returned corpus has all indexing enabled and MaxResults set to 1000.
+// Change or set any options on Corpus before calling the Corpus.Init method.
+func NewCorpus(fs vfs.FileSystem) *Corpus {
+	c := &Corpus{
+		fs: fs,
+		refreshMetadataSignal: make(chan bool, 1),
+
+		MaxResults:    1000,
+		IndexEnabled:  true,
+		IndexDocs:     true,
+		IndexGoCode:   true,
+		IndexFullText: true,
+	}
+	return c
+}
+
+func (c *Corpus) CurrentIndex() (*Index, time.Time) {
+	v, t := c.searchIndex.Get()
+	idx, _ := v.(*Index)
+	return idx, t
+}
+
+func (c *Corpus) FSModifiedTime() time.Time {
+	_, ts := c.fsModified.Get()
+	return ts
+}
+
+// Init initializes Corpus, once options on Corpus are set.
+// It must be called before any subsequent method calls.
+func (c *Corpus) Init() error {
+	// TODO(bradfitz): do this in a goroutine because newDirectory might block for a long time?
+	// It used to be sometimes done in a goroutine before, at least in HTTP server mode.
+	if err := c.initFSTree(); err != nil {
+		return err
+	}
+	c.updateMetadata()
+	go c.refreshMetadataLoop()
+	return nil
+}
+
+func (c *Corpus) initFSTree() error {
+	dir := c.newDirectory(pathpkg.Join("/", c.testDir), -1)
+	if dir == nil {
+		return errors.New("godoc: corpus fstree is nil")
+	}
+	c.fsTree.Set(dir)
+	c.invalidateIndex()
+	return nil
+}
diff --git a/third_party/go.tools/godoc/dirtrees.go b/third_party/go.tools/godoc/dirtrees.go
new file mode 100644
index 0000000..a55b324
--- /dev/null
+++ b/third_party/go.tools/godoc/dirtrees.go
@@ -0,0 +1,336 @@
+// Copyright 2010 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.
+
+// This file contains the code dealing with package directory trees.
+
+package godoc
+
+import (
+	"bytes"
+	"go/doc"
+	"go/parser"
+	"go/token"
+	"log"
+	"os"
+	pathpkg "path"
+	"strings"
+)
+
+// Conventional name for directories containing test data.
+// Excluded from directory trees.
+//
+const testdataDirName = "testdata"
+
+type Directory struct {
+	Depth    int
+	Path     string       // directory path; includes Name
+	Name     string       // directory name
+	HasPkg   bool         // true if the directory contains at least one package
+	Synopsis string       // package documentation, if any
+	Dirs     []*Directory // subdirectories
+}
+
+func isGoFile(fi os.FileInfo) bool {
+	name := fi.Name()
+	return !fi.IsDir() &&
+		len(name) > 0 && name[0] != '.' && // ignore .files
+		pathpkg.Ext(name) == ".go"
+}
+
+func isPkgFile(fi os.FileInfo) bool {
+	return isGoFile(fi) &&
+		!strings.HasSuffix(fi.Name(), "_test.go") // ignore test files
+}
+
+func isPkgDir(fi os.FileInfo) bool {
+	name := fi.Name()
+	return fi.IsDir() && len(name) > 0 &&
+		name[0] != '_' && name[0] != '.' // ignore _files and .files
+}
+
+type treeBuilder struct {
+	c        *Corpus
+	maxDepth int
+}
+
+func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth int) *Directory {
+	if name == testdataDirName {
+		return nil
+	}
+
+	if depth >= b.maxDepth {
+		// return a dummy directory so that the parent directory
+		// doesn't get discarded just because we reached the max
+		// directory depth
+		return &Directory{
+			Depth: depth,
+			Path:  path,
+			Name:  name,
+		}
+	}
+
+	var synopses [3]string // prioritized package documentation (0 == highest priority)
+
+	show := true // show in package listing
+	hasPkgFiles := false
+	haveSummary := false
+
+	if hook := b.c.SummarizePackage; hook != nil {
+		if summary, show0, ok := hook(strings.TrimPrefix(path, "/src/")); ok {
+			hasPkgFiles = true
+			show = show0
+			synopses[0] = summary
+			haveSummary = true
+		}
+	}
+
+	list, _ := b.c.fs.ReadDir(path)
+
+	// determine number of subdirectories and if there are package files
+	var dirchs []chan *Directory
+
+	for _, d := range list {
+		switch {
+		case isPkgDir(d):
+			ch := make(chan *Directory, 1)
+			dirchs = append(dirchs, ch)
+			go func(d os.FileInfo) {
+				name := d.Name()
+				ch <- b.newDirTree(fset, pathpkg.Join(path, name), name, depth+1)
+			}(d)
+		case !haveSummary && isPkgFile(d):
+			// looks like a package file, but may just be a file ending in ".go";
+			// don't just count it yet (otherwise we may end up with hasPkgFiles even
+			// though the directory doesn't contain any real package files - was bug)
+			// no "optimal" package synopsis yet; continue to collect synopses
+			file, err := b.c.parseFile(fset, pathpkg.Join(path, d.Name()),
+				parser.ParseComments|parser.PackageClauseOnly)
+			if err == nil {
+				hasPkgFiles = true
+				if file.Doc != nil {
+					// prioritize documentation
+					i := -1
+					switch file.Name.Name {
+					case name:
+						i = 0 // normal case: directory name matches package name
+					case "main":
+						i = 1 // directory contains a main package
+					default:
+						i = 2 // none of the above
+					}
+					if 0 <= i && i < len(synopses) && synopses[i] == "" {
+						synopses[i] = doc.Synopsis(file.Doc.Text())
+					}
+				}
+				haveSummary = synopses[0] != ""
+			}
+		}
+	}
+
+	// create subdirectory tree
+	var dirs []*Directory
+	for _, ch := range dirchs {
+		if d := <-ch; d != nil {
+			dirs = append(dirs, d)
+		}
+	}
+
+	// if there are no package files and no subdirectories
+	// containing package files, ignore the directory
+	if !hasPkgFiles && len(dirs) == 0 {
+		return nil
+	}
+
+	// select the highest-priority synopsis for the directory entry, if any
+	synopsis := ""
+	for _, synopsis = range synopses {
+		if synopsis != "" {
+			break
+		}
+	}
+
+	return &Directory{
+		Depth:    depth,
+		Path:     path,
+		Name:     name,
+		HasPkg:   hasPkgFiles && show, // TODO(bradfitz): add proper Hide field?
+		Synopsis: synopsis,
+		Dirs:     dirs,
+	}
+}
+
+// newDirectory creates a new package directory tree with at most maxDepth
+// levels, anchored at root. The result tree is pruned such that it only
+// contains directories that contain package files or that contain
+// subdirectories containing package files (transitively). If a non-nil
+// pathFilter is provided, directory paths additionally must be accepted
+// by the filter (i.e., pathFilter(path) must be true). If a value >= 0 is
+// provided for maxDepth, nodes at larger depths are pruned as well; they
+// are assumed to contain package files even if their contents are not known
+// (i.e., in this case the tree may contain directories w/o any package files).
+//
+func (c *Corpus) newDirectory(root string, maxDepth int) *Directory {
+	// The root could be a symbolic link so use Stat not Lstat.
+	d, err := c.fs.Stat(root)
+	// If we fail here, report detailed error messages; otherwise
+	// is is hard to see why a directory tree was not built.
+	switch {
+	case err != nil:
+		log.Printf("newDirectory(%s): %s", root, err)
+		return nil
+	case root != "/" && !isPkgDir(d):
+		log.Printf("newDirectory(%s): not a package directory", root)
+		return nil
+	case root == "/" && !d.IsDir():
+		log.Printf("newDirectory(%s): not a directory", root)
+		return nil
+	}
+	if maxDepth < 0 {
+		maxDepth = 1e6 // "infinity"
+	}
+	b := treeBuilder{c, maxDepth}
+	// the file set provided is only for local parsing, no position
+	// information escapes and thus we don't need to save the set
+	return b.newDirTree(token.NewFileSet(), root, d.Name(), 0)
+}
+
+func (dir *Directory) writeLeafs(buf *bytes.Buffer) {
+	if dir != nil {
+		if len(dir.Dirs) == 0 {
+			buf.WriteString(dir.Path)
+			buf.WriteByte('\n')
+			return
+		}
+
+		for _, d := range dir.Dirs {
+			d.writeLeafs(buf)
+		}
+	}
+}
+
+func (dir *Directory) walk(c chan<- *Directory, skipRoot bool) {
+	if dir != nil {
+		if !skipRoot {
+			c <- dir
+		}
+		for _, d := range dir.Dirs {
+			d.walk(c, false)
+		}
+	}
+}
+
+func (dir *Directory) iter(skipRoot bool) <-chan *Directory {
+	c := make(chan *Directory)
+	go func() {
+		dir.walk(c, skipRoot)
+		close(c)
+	}()
+	return c
+}
+
+func (dir *Directory) lookupLocal(name string) *Directory {
+	for _, d := range dir.Dirs {
+		if d.Name == name {
+			return d
+		}
+	}
+	return nil
+}
+
+func splitPath(p string) []string {
+	p = strings.TrimPrefix(p, "/")
+	if p == "" {
+		return nil
+	}
+	return strings.Split(p, "/")
+}
+
+// lookup looks for the *Directory for a given path, relative to dir.
+func (dir *Directory) lookup(path string) *Directory {
+	d := splitPath(dir.Path)
+	p := splitPath(path)
+	i := 0
+	for i < len(d) {
+		if i >= len(p) || d[i] != p[i] {
+			return nil
+		}
+		i++
+	}
+	for dir != nil && i < len(p) {
+		dir = dir.lookupLocal(p[i])
+		i++
+	}
+	return dir
+}
+
+// DirEntry describes a directory entry. The Depth and Height values
+// are useful for presenting an entry in an indented fashion.
+//
+type DirEntry struct {
+	Depth    int    // >= 0
+	Height   int    // = DirList.MaxHeight - Depth, > 0
+	Path     string // directory path; includes Name, relative to DirList root
+	Name     string // directory name
+	HasPkg   bool   // true if the directory contains at least one package
+	Synopsis string // package documentation, if any
+}
+
+type DirList struct {
+	MaxHeight int // directory tree height, > 0
+	List      []DirEntry
+}
+
+// listing creates a (linear) directory listing from a directory tree.
+// If skipRoot is set, the root directory itself is excluded from the list.
+// If filter is set, only the directory entries whose paths match the filter
+// are included.
+//
+func (root *Directory) listing(skipRoot bool, filter func(string) bool) *DirList {
+	if root == nil {
+		return nil
+	}
+
+	// determine number of entries n and maximum height
+	n := 0
+	minDepth := 1 << 30 // infinity
+	maxDepth := 0
+	for d := range root.iter(skipRoot) {
+		n++
+		if minDepth > d.Depth {
+			minDepth = d.Depth
+		}
+		if maxDepth < d.Depth {
+			maxDepth = d.Depth
+		}
+	}
+	maxHeight := maxDepth - minDepth + 1
+
+	if n == 0 {
+		return nil
+	}
+
+	// create list
+	list := make([]DirEntry, 0, n)
+	for d := range root.iter(skipRoot) {
+		if filter != nil && !filter(d.Path) {
+			continue
+		}
+		var p DirEntry
+		p.Depth = d.Depth - minDepth
+		p.Height = maxHeight - p.Depth
+		// the path is relative to root.Path - remove the root.Path
+		// prefix (the prefix should always be present but avoid
+		// crashes and check)
+		path := strings.TrimPrefix(d.Path, root.Path)
+		// remove leading separator if any - path must be relative
+		path = strings.TrimPrefix(path, "/")
+		p.Path = path
+		p.Name = d.Name
+		p.HasPkg = d.HasPkg
+		p.Synopsis = d.Synopsis
+		list = append(list, p)
+	}
+
+	return &DirList{maxHeight, list}
+}
diff --git a/third_party/go.tools/godoc/format.go b/third_party/go.tools/godoc/format.go
new file mode 100644
index 0000000..6013238
--- /dev/null
+++ b/third_party/go.tools/godoc/format.go
@@ -0,0 +1,371 @@
+// 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.
+
+// This file implements FormatSelections and FormatText.
+// FormatText is used to HTML-format Go and non-Go source
+// text with line numbers and highlighted sections. It is
+// built on top of FormatSelections, a generic formatter
+// for "selected" text.
+
+package godoc
+
+import (
+	"fmt"
+	"go/scanner"
+	"go/token"
+	"io"
+	"regexp"
+	"strconv"
+	"text/template"
+)
+
+// ----------------------------------------------------------------------------
+// Implementation of FormatSelections
+
+// A Segment describes a text segment [start, end).
+// The zero value of a Segment is a ready-to-use empty segment.
+//
+type Segment struct {
+	start, end int
+}
+
+func (seg *Segment) isEmpty() bool { return seg.start >= seg.end }
+
+// A Selection is an "iterator" function returning a text segment.
+// Repeated calls to a selection return consecutive, non-overlapping,
+// non-empty segments, followed by an infinite sequence of empty
+// segments. The first empty segment marks the end of the selection.
+//
+type Selection func() Segment
+
+// A LinkWriter writes some start or end "tag" to w for the text offset offs.
+// It is called by FormatSelections at the start or end of each link segment.
+//
+type LinkWriter func(w io.Writer, offs int, start bool)
+
+// A SegmentWriter formats a text according to selections and writes it to w.
+// The selections parameter is a bit set indicating which selections provided
+// to FormatSelections overlap with the text segment: If the n'th bit is set
+// in selections, the n'th selection provided to FormatSelections is overlapping
+// with the text.
+//
+type SegmentWriter func(w io.Writer, text []byte, selections int)
+
+// FormatSelections takes a text and writes it to w using link and segment
+// writers lw and sw as follows: lw is invoked for consecutive segment starts
+// and ends as specified through the links selection, and sw is invoked for
+// consecutive segments of text overlapped by the same selections as specified
+// by selections. The link writer lw may be nil, in which case the links
+// Selection is ignored.
+//
+func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection, sw SegmentWriter, selections ...Selection) {
+	// If we have a link writer, make the links
+	// selection the last entry in selections
+	if lw != nil {
+		selections = append(selections, links)
+	}
+
+	// compute the sequence of consecutive segment changes
+	changes := newMerger(selections)
+
+	// The i'th bit in bitset indicates that the text
+	// at the current offset is covered by selections[i].
+	bitset := 0
+	lastOffs := 0
+
+	// Text segments are written in a delayed fashion
+	// such that consecutive segments belonging to the
+	// same selection can be combined (peephole optimization).
+	// last describes the last segment which has not yet been written.
+	var last struct {
+		begin, end int // valid if begin < end
+		bitset     int
+	}
+
+	// flush writes the last delayed text segment
+	flush := func() {
+		if last.begin < last.end {
+			sw(w, text[last.begin:last.end], last.bitset)
+		}
+		last.begin = last.end // invalidate last
+	}
+
+	// segment runs the segment [lastOffs, end) with the selection
+	// indicated by bitset through the segment peephole optimizer.
+	segment := func(end int) {
+		if lastOffs < end { // ignore empty segments
+			if last.end != lastOffs || last.bitset != bitset {
+				// the last segment is not adjacent to or
+				// differs from the new one
+				flush()
+				// start a new segment
+				last.begin = lastOffs
+			}
+			last.end = end
+			last.bitset = bitset
+		}
+	}
+
+	for {
+		// get the next segment change
+		index, offs, start := changes.next()
+		if index < 0 || offs > len(text) {
+			// no more segment changes or the next change
+			// is past the end of the text - we're done
+			break
+		}
+		// determine the kind of segment change
+		if lw != nil && index == len(selections)-1 {
+			// we have a link segment change (see start of this function):
+			// format the previous selection segment, write the
+			// link tag and start a new selection segment
+			segment(offs)
+			flush()
+			lastOffs = offs
+			lw(w, offs, start)
+		} else {
+			// we have a selection change:
+			// format the previous selection segment, determine
+			// the new selection bitset and start a new segment
+			segment(offs)
+			lastOffs = offs
+			mask := 1 << uint(index)
+			if start {
+				bitset |= mask
+			} else {
+				bitset &^= mask
+			}
+		}
+	}
+	segment(len(text))
+	flush()
+}
+
+// A merger merges a slice of Selections and produces a sequence of
+// consecutive segment change events through repeated next() calls.
+//
+type merger struct {
+	selections []Selection
+	segments   []Segment // segments[i] is the next segment of selections[i]
+}
+
+const infinity int = 2e9
+
+func newMerger(selections []Selection) *merger {
+	segments := make([]Segment, len(selections))
+	for i, sel := range selections {
+		segments[i] = Segment{infinity, infinity}
+		if sel != nil {
+			if seg := sel(); !seg.isEmpty() {
+				segments[i] = seg
+			}
+		}
+	}
+	return &merger{selections, segments}
+}
+
+// next returns the next segment change: index specifies the Selection
+// to which the segment belongs, offs is the segment start or end offset
+// as determined by the start value. If there are no more segment changes,
+// next returns an index value < 0.
+//
+func (m *merger) next() (index, offs int, start bool) {
+	// find the next smallest offset where a segment starts or ends
+	offs = infinity
+	index = -1
+	for i, seg := range m.segments {
+		switch {
+		case seg.start < offs:
+			offs = seg.start
+			index = i
+			start = true
+		case seg.end < offs:
+			offs = seg.end
+			index = i
+			start = false
+		}
+	}
+	if index < 0 {
+		// no offset found => all selections merged
+		return
+	}
+	// offset found - it's either the start or end offset but
+	// either way it is ok to consume the start offset: set it
+	// to infinity so it won't be considered in the following
+	// next call
+	m.segments[index].start = infinity
+	if start {
+		return
+	}
+	// end offset found - consume it
+	m.segments[index].end = infinity
+	// advance to the next segment for that selection
+	seg := m.selections[index]()
+	if !seg.isEmpty() {
+		m.segments[index] = seg
+	}
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Implementation of FormatText
+
+// lineSelection returns the line segments for text as a Selection.
+func lineSelection(text []byte) Selection {
+	i, j := 0, 0
+	return func() (seg Segment) {
+		// find next newline, if any
+		for j < len(text) {
+			j++
+			if text[j-1] == '\n' {
+				break
+			}
+		}
+		if i < j {
+			// text[i:j] constitutes a line
+			seg = Segment{i, j}
+			i = j
+		}
+		return
+	}
+}
+
+// tokenSelection returns, as a selection, the sequence of
+// consecutive occurrences of token sel in the Go src text.
+//
+func tokenSelection(src []byte, sel token.Token) Selection {
+	var s scanner.Scanner
+	fset := token.NewFileSet()
+	file := fset.AddFile("", fset.Base(), len(src))
+	s.Init(file, src, nil, scanner.ScanComments)
+	return func() (seg Segment) {
+		for {
+			pos, tok, lit := s.Scan()
+			if tok == token.EOF {
+				break
+			}
+			offs := file.Offset(pos)
+			if tok == sel {
+				seg = Segment{offs, offs + len(lit)}
+				break
+			}
+		}
+		return
+	}
+}
+
+// makeSelection is a helper function to make a Selection from a slice of pairs.
+// Pairs describing empty segments are ignored.
+//
+func makeSelection(matches [][]int) Selection {
+	i := 0
+	return func() Segment {
+		for i < len(matches) {
+			m := matches[i]
+			i++
+			if m[0] < m[1] {
+				// non-empty segment
+				return Segment{m[0], m[1]}
+			}
+		}
+		return Segment{}
+	}
+}
+
+// regexpSelection computes the Selection for the regular expression expr in text.
+func regexpSelection(text []byte, expr string) Selection {
+	var matches [][]int
+	if rx, err := regexp.Compile(expr); err == nil {
+		matches = rx.FindAllIndex(text, -1)
+	}
+	return makeSelection(matches)
+}
+
+var selRx = regexp.MustCompile(`^([0-9]+):([0-9]+)`)
+
+// RangeSelection computes the Selection for a text range described
+// by the argument str; the range description must match the selRx
+// regular expression.
+func RangeSelection(str string) Selection {
+	m := selRx.FindStringSubmatch(str)
+	if len(m) >= 2 {
+		from, _ := strconv.Atoi(m[1])
+		to, _ := strconv.Atoi(m[2])
+		if from < to {
+			return makeSelection([][]int{{from, to}})
+		}
+	}
+	return nil
+}
+
+// Span tags for all the possible selection combinations that may
+// be generated by FormatText. Selections are indicated by a bitset,
+// and the value of the bitset specifies the tag to be used.
+//
+// bit 0: comments
+// bit 1: highlights
+// bit 2: selections
+//
+var startTags = [][]byte{
+	/* 000 */ []byte(``),
+	/* 001 */ []byte(`<span class="comment">`),
+	/* 010 */ []byte(`<span class="highlight">`),
+	/* 011 */ []byte(`<span class="highlight-comment">`),
+	/* 100 */ []byte(`<span class="selection">`),
+	/* 101 */ []byte(`<span class="selection-comment">`),
+	/* 110 */ []byte(`<span class="selection-highlight">`),
+	/* 111 */ []byte(`<span class="selection-highlight-comment">`),
+}
+
+var endTag = []byte(`</span>`)
+
+func selectionTag(w io.Writer, text []byte, selections int) {
+	if selections < len(startTags) {
+		if tag := startTags[selections]; len(tag) > 0 {
+			w.Write(tag)
+			template.HTMLEscape(w, text)
+			w.Write(endTag)
+			return
+		}
+	}
+	template.HTMLEscape(w, text)
+}
+
+// FormatText HTML-escapes text and writes it to w.
+// Consecutive text segments are wrapped in HTML spans (with tags as
+// defined by startTags and endTag) as follows:
+//
+//	- if line >= 0, line number (ln) spans are inserted before each line,
+//	  starting with the value of line
+//	- if the text is Go source, comments get the "comment" span class
+//	- each occurrence of the regular expression pattern gets the "highlight"
+//	  span class
+//	- text segments covered by selection get the "selection" span class
+//
+// Comments, highlights, and selections may overlap arbitrarily; the respective
+// HTML span classes are specified in the startTags variable.
+//
+func FormatText(w io.Writer, text []byte, line int, goSource bool, pattern string, selection Selection) {
+	var comments, highlights Selection
+	if goSource {
+		comments = tokenSelection(text, token.COMMENT)
+	}
+	if pattern != "" {
+		highlights = regexpSelection(text, pattern)
+	}
+	if line >= 0 || comments != nil || highlights != nil || selection != nil {
+		var lineTag LinkWriter
+		if line >= 0 {
+			lineTag = func(w io.Writer, _ int, start bool) {
+				if start {
+					fmt.Fprintf(w, "<span id=\"L%d\" class=\"ln\">%6d</span>\t", line, line)
+					line++
+				}
+			}
+		}
+		FormatSelections(w, text, lineTag, lineSelection(text), selectionTag, comments, highlights, selection)
+	} else {
+		template.HTMLEscape(w, text)
+	}
+}
diff --git a/third_party/go.tools/godoc/godoc.go b/third_party/go.tools/godoc/godoc.go
new file mode 100644
index 0000000..8ec731c
--- /dev/null
+++ b/third_party/go.tools/godoc/godoc.go
@@ -0,0 +1,628 @@
+// Copyright 2013 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 godoc is a work-in-progress (2013-07-17) package to
+// begin splitting up the godoc binary into multiple pieces.
+//
+// This package comment will evolve over time as this package splits
+// into smaller pieces.
+package godoc
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/doc"
+	"go/format"
+	"go/printer"
+	"go/token"
+	htmltemplate "html/template"
+	"io"
+	"log"
+	"os"
+	pathpkg "path"
+	"regexp"
+	"strconv"
+	"strings"
+	"text/template"
+	"time"
+	"unicode"
+	"unicode/utf8"
+)
+
+// Fake relative package path for built-ins. Documentation for all globals
+// (not just exported ones) will be shown for packages in this directory.
+const builtinPkgPath = "builtin"
+
+// FuncMap defines template functions used in godoc templates.
+//
+// Convention: template function names ending in "_html" or "_url" produce
+//             HTML- or URL-escaped strings; all other function results may
+//             require explicit escaping in the template.
+func (p *Presentation) FuncMap() template.FuncMap {
+	p.initFuncMapOnce.Do(p.initFuncMap)
+	return p.funcMap
+}
+
+func (p *Presentation) TemplateFuncs() template.FuncMap {
+	p.initFuncMapOnce.Do(p.initFuncMap)
+	return p.templateFuncs
+}
+
+func (p *Presentation) initFuncMap() {
+	if p.Corpus == nil {
+		panic("nil Presentation.Corpus")
+	}
+	p.templateFuncs = template.FuncMap{
+		"code": p.code,
+	}
+	p.funcMap = template.FuncMap{
+		// various helpers
+		"filename": filenameFunc,
+		"repeat":   strings.Repeat,
+
+		// access to FileInfos (directory listings)
+		"fileInfoName": fileInfoNameFunc,
+		"fileInfoTime": fileInfoTimeFunc,
+
+		// access to search result information
+		"infoKind_html":    infoKind_htmlFunc,
+		"infoLine":         p.infoLineFunc,
+		"infoSnippet_html": p.infoSnippet_htmlFunc,
+
+		// formatting of AST nodes
+		"node":         p.nodeFunc,
+		"node_html":    p.node_htmlFunc,
+		"comment_html": comment_htmlFunc,
+		"comment_text": comment_textFunc,
+		"sanitize":     sanitizeFunc,
+
+		// support for URL attributes
+		"pkgLink":     pkgLinkFunc,
+		"srcLink":     srcLinkFunc,
+		"posLink_url": newPosLink_urlFunc(srcPosLinkFunc),
+		"docLink":     docLinkFunc,
+		"queryLink":   queryLinkFunc,
+
+		// formatting of Examples
+		"example_html":   p.example_htmlFunc,
+		"example_text":   p.example_textFunc,
+		"example_name":   p.example_nameFunc,
+		"example_suffix": p.example_suffixFunc,
+
+		// formatting of analysis information
+		"callgraph_html":  p.callgraph_htmlFunc,
+		"implements_html": p.implements_htmlFunc,
+		"methodset_html":  p.methodset_htmlFunc,
+
+		// formatting of Notes
+		"noteTitle": noteTitle,
+	}
+	if p.URLForSrc != nil {
+		p.funcMap["srcLink"] = p.URLForSrc
+	}
+	if p.URLForSrcPos != nil {
+		p.funcMap["posLink_url"] = newPosLink_urlFunc(p.URLForSrcPos)
+	}
+	if p.URLForSrcQuery != nil {
+		p.funcMap["queryLink"] = p.URLForSrcQuery
+	}
+}
+
+func filenameFunc(path string) string {
+	_, localname := pathpkg.Split(path)
+	return localname
+}
+
+func fileInfoNameFunc(fi os.FileInfo) string {
+	name := fi.Name()
+	if fi.IsDir() {
+		name += "/"
+	}
+	return name
+}
+
+func fileInfoTimeFunc(fi os.FileInfo) string {
+	if t := fi.ModTime(); t.Unix() != 0 {
+		return t.Local().String()
+	}
+	return "" // don't return epoch if time is obviously not set
+}
+
+// The strings in infoKinds must be properly html-escaped.
+var infoKinds = [nKinds]string{
+	PackageClause: "package&nbsp;clause",
+	ImportDecl:    "import&nbsp;decl",
+	ConstDecl:     "const&nbsp;decl",
+	TypeDecl:      "type&nbsp;decl",
+	VarDecl:       "var&nbsp;decl",
+	FuncDecl:      "func&nbsp;decl",
+	MethodDecl:    "method&nbsp;decl",
+	Use:           "use",
+}
+
+func infoKind_htmlFunc(info SpotInfo) string {
+	return infoKinds[info.Kind()] // infoKind entries are html-escaped
+}
+
+func (p *Presentation) infoLineFunc(info SpotInfo) int {
+	line := info.Lori()
+	if info.IsIndex() {
+		index, _ := p.Corpus.searchIndex.Get()
+		if index != nil {
+			line = index.(*Index).Snippet(line).Line
+		} else {
+			// no line information available because
+			// we don't have an index - this should
+			// never happen; be conservative and don't
+			// crash
+			line = 0
+		}
+	}
+	return line
+}
+
+func (p *Presentation) infoSnippet_htmlFunc(info SpotInfo) string {
+	if info.IsIndex() {
+		index, _ := p.Corpus.searchIndex.Get()
+		// Snippet.Text was HTML-escaped when it was generated
+		return index.(*Index).Snippet(info.Lori()).Text
+	}
+	return `<span class="alert">no snippet text available</span>`
+}
+
+func (p *Presentation) nodeFunc(info *PageInfo, node interface{}) string {
+	var buf bytes.Buffer
+	p.writeNode(&buf, info.FSet, node)
+	return buf.String()
+}
+
+func (p *Presentation) node_htmlFunc(info *PageInfo, node interface{}, linkify bool) string {
+	var buf1 bytes.Buffer
+	p.writeNode(&buf1, info.FSet, node)
+
+	var buf2 bytes.Buffer
+	if n, _ := node.(ast.Node); n != nil && linkify && p.DeclLinks {
+		LinkifyText(&buf2, buf1.Bytes(), n)
+	} else {
+		FormatText(&buf2, buf1.Bytes(), -1, true, "", nil)
+	}
+
+	return buf2.String()
+}
+
+func comment_htmlFunc(comment string) string {
+	var buf bytes.Buffer
+	// TODO(gri) Provide list of words (e.g. function parameters)
+	//           to be emphasized by ToHTML.
+	doc.ToHTML(&buf, comment, nil) // does html-escaping
+	return buf.String()
+}
+
+// punchCardWidth is the number of columns of fixed-width
+// characters to assume when wrapping text.  Very few people
+// use terminals or cards smaller than 80 characters, so 80 it is.
+// We do not try to sniff the environment or the tty to adapt to
+// the situation; instead, by using a constant we make sure that
+// godoc always produces the same output regardless of context,
+// a consistency that is lost otherwise.  For example, if we sniffed
+// the environment or tty, then http://golang.org/pkg/math/?m=text
+// would depend on the width of the terminal where godoc started,
+// which is clearly bogus.  More generally, the Unix tools that behave
+// differently when writing to a tty than when writing to a file have
+// a history of causing confusion (compare `ls` and `ls | cat`), and we
+// want to avoid that mistake here.
+const punchCardWidth = 80
+
+func containsOnlySpace(buf []byte) bool {
+	isNotSpace := func(r rune) bool { return !unicode.IsSpace(r) }
+	return bytes.IndexFunc(buf, isNotSpace) == -1
+}
+
+func comment_textFunc(comment, indent, preIndent string) string {
+	var buf bytes.Buffer
+	doc.ToText(&buf, comment, indent, preIndent, punchCardWidth-2*len(indent))
+	if containsOnlySpace(buf.Bytes()) {
+		return ""
+	}
+	return buf.String()
+}
+
+// sanitizeFunc sanitizes the argument src by replacing newlines with
+// blanks, removing extra blanks, and by removing trailing whitespace
+// and commas before closing parentheses.
+func sanitizeFunc(src string) string {
+	buf := make([]byte, len(src))
+	j := 0      // buf index
+	comma := -1 // comma index if >= 0
+	for i := 0; i < len(src); i++ {
+		ch := src[i]
+		switch ch {
+		case '\t', '\n', ' ':
+			// ignore whitespace at the beginning, after a blank, or after opening parentheses
+			if j == 0 {
+				continue
+			}
+			if p := buf[j-1]; p == ' ' || p == '(' || p == '{' || p == '[' {
+				continue
+			}
+			// replace all whitespace with blanks
+			ch = ' '
+		case ',':
+			comma = j
+		case ')', '}', ']':
+			// remove any trailing comma
+			if comma >= 0 {
+				j = comma
+			}
+			// remove any trailing whitespace
+			if j > 0 && buf[j-1] == ' ' {
+				j--
+			}
+		default:
+			comma = -1
+		}
+		buf[j] = ch
+		j++
+	}
+	// remove trailing blank, if any
+	if j > 0 && buf[j-1] == ' ' {
+		j--
+	}
+	return string(buf[:j])
+}
+
+type PageInfo struct {
+	Dirname string // directory containing the package
+	Err     error  // error or nil
+
+	// package info
+	FSet       *token.FileSet         // nil if no package documentation
+	PDoc       *doc.Package           // nil if no package documentation
+	Examples   []*doc.Example         // nil if no example code
+	Notes      map[string][]*doc.Note // nil if no package Notes
+	PAst       map[string]*ast.File   // nil if no AST with package exports
+	IsMain     bool                   // true for package main
+	IsFiltered bool                   // true if results were filtered
+
+	// analysis info
+	TypeInfoIndex  map[string]int  // index of JSON datum for type T (if -analysis=type)
+	AnalysisData   htmltemplate.JS // array of TypeInfoJSON values
+	CallGraph      htmltemplate.JS // array of PCGNodeJSON values    (if -analysis=pointer)
+	CallGraphIndex map[string]int  // maps func name to index in CallGraph
+
+	// directory info
+	Dirs    *DirList  // nil if no directory information
+	DirTime time.Time // directory time stamp
+	DirFlat bool      // if set, show directory in a flat (non-indented) manner
+}
+
+func (info *PageInfo) IsEmpty() bool {
+	return info.Err != nil || info.PAst == nil && info.PDoc == nil && info.Dirs == nil
+}
+
+func pkgLinkFunc(path string) string {
+	// because of the irregular mapping under goroot
+	// we need to correct certain relative paths
+	path = strings.TrimPrefix(path, "/")
+	path = strings.TrimPrefix(path, "src/")
+	path = strings.TrimPrefix(path, "pkg/")
+	return "pkg/" + path
+}
+
+func newPosLink_urlFunc(srcPosLinkFunc func(s string, line, low, high int) string) func(info *PageInfo, n interface{}) string {
+	// n must be an ast.Node or a *doc.Note
+	return func(info *PageInfo, n interface{}) string {
+		var pos, end token.Pos
+
+		switch n := n.(type) {
+		case ast.Node:
+			pos = n.Pos()
+			end = n.End()
+		case *doc.Note:
+			pos = n.Pos
+			end = n.End
+		default:
+			panic(fmt.Sprintf("wrong type for posLink_url template formatter: %T", n))
+		}
+
+		var relpath string
+		var line int
+		var low, high int // selection offset range
+
+		if pos.IsValid() {
+			p := info.FSet.Position(pos)
+			relpath = p.Filename
+			line = p.Line
+			low = p.Offset
+		}
+		if end.IsValid() {
+			high = info.FSet.Position(end).Offset
+		}
+
+		return srcPosLinkFunc(relpath, line, low, high)
+	}
+}
+
+func srcPosLinkFunc(s string, line, low, high int) string {
+	s = srcLinkFunc(s)
+	var buf bytes.Buffer
+	template.HTMLEscape(&buf, []byte(s))
+	// selection ranges are of form "s=low:high"
+	if low < high {
+		fmt.Fprintf(&buf, "?s=%d:%d", low, high) // no need for URL escaping
+		// if we have a selection, position the page
+		// such that the selection is a bit below the top
+		line -= 10
+		if line < 1 {
+			line = 1
+		}
+	}
+	// line id's in html-printed source are of the
+	// form "L%d" where %d stands for the line number
+	if line > 0 {
+		fmt.Fprintf(&buf, "#L%d", line) // no need for URL escaping
+	}
+	return buf.String()
+}
+
+func srcLinkFunc(s string) string {
+	s = pathpkg.Clean("/" + s)
+	if !strings.HasPrefix(s, "/src/") {
+		s = "/src" + s
+	}
+	return s
+}
+
+// queryLinkFunc returns a URL for a line in a source file with a highlighted
+// query term.
+// s is expected to be a path to a source file.
+// query is expected to be a string that has already been appropriately escaped
+// for use in a URL query.
+func queryLinkFunc(s, query string, line int) string {
+	url := pathpkg.Clean("/"+s) + "?h=" + query
+	if line > 0 {
+		url += "#L" + strconv.Itoa(line)
+	}
+	return url
+}
+
+func docLinkFunc(s string, ident string) string {
+	return pathpkg.Clean("/pkg/"+s) + "/#" + ident
+}
+
+func (p *Presentation) example_textFunc(info *PageInfo, funcName, indent string) string {
+	if !p.ShowExamples {
+		return ""
+	}
+
+	var buf bytes.Buffer
+	first := true
+	for _, eg := range info.Examples {
+		name := stripExampleSuffix(eg.Name)
+		if name != funcName {
+			continue
+		}
+
+		if !first {
+			buf.WriteString("\n")
+		}
+		first = false
+
+		// print code
+		cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
+		var buf1 bytes.Buffer
+		p.writeNode(&buf1, info.FSet, cnode)
+		code := buf1.String()
+		// Additional formatting if this is a function body.
+		if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
+			// remove surrounding braces
+			code = code[1 : n-1]
+			// unindent
+			code = strings.Replace(code, "\n    ", "\n", -1)
+		}
+		code = strings.Trim(code, "\n")
+		code = strings.Replace(code, "\n", "\n\t", -1)
+
+		buf.WriteString(indent)
+		buf.WriteString("Example:\n\t")
+		buf.WriteString(code)
+		buf.WriteString("\n")
+	}
+	return buf.String()
+}
+
+func (p *Presentation) example_htmlFunc(info *PageInfo, funcName string) string {
+	var buf bytes.Buffer
+	for _, eg := range info.Examples {
+		name := stripExampleSuffix(eg.Name)
+
+		if name != funcName {
+			continue
+		}
+
+		// print code
+		cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
+		code := p.node_htmlFunc(info, cnode, true)
+		out := eg.Output
+		wholeFile := true
+
+		// Additional formatting if this is a function body.
+		if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
+			wholeFile = false
+			// remove surrounding braces
+			code = code[1 : n-1]
+			// unindent
+			code = strings.Replace(code, "\n    ", "\n", -1)
+			// remove output comment
+			if loc := exampleOutputRx.FindStringIndex(code); loc != nil {
+				code = strings.TrimSpace(code[:loc[0]])
+			}
+		}
+
+		// Write out the playground code in standard Go style
+		// (use tabs, no comment highlight, etc).
+		play := ""
+		if eg.Play != nil && p.ShowPlayground {
+			var buf bytes.Buffer
+			if err := format.Node(&buf, info.FSet, eg.Play); err != nil {
+				log.Print(err)
+			} else {
+				play = buf.String()
+			}
+		}
+
+		// Drop output, as the output comment will appear in the code.
+		if wholeFile && play == "" {
+			out = ""
+		}
+
+		if p.ExampleHTML == nil {
+			out = ""
+			return ""
+		}
+
+		err := p.ExampleHTML.Execute(&buf, struct {
+			Name, Doc, Code, Play, Output string
+		}{eg.Name, eg.Doc, code, play, out})
+		if err != nil {
+			log.Print(err)
+		}
+	}
+	return buf.String()
+}
+
+// example_nameFunc takes an example function name and returns its display
+// name. For example, "Foo_Bar_quux" becomes "Foo.Bar (Quux)".
+func (p *Presentation) example_nameFunc(s string) string {
+	name, suffix := splitExampleName(s)
+	// replace _ with . for method names
+	name = strings.Replace(name, "_", ".", 1)
+	// use "Package" if no name provided
+	if name == "" {
+		name = "Package"
+	}
+	return name + suffix
+}
+
+// example_suffixFunc takes an example function name and returns its suffix in
+// parenthesized form. For example, "Foo_Bar_quux" becomes " (Quux)".
+func (p *Presentation) example_suffixFunc(name string) string {
+	_, suffix := splitExampleName(name)
+	return suffix
+}
+
+// implements_html returns the "> Implements" toggle for a package-level named type.
+// Its contents are populated from JSON data by client-side JS at load time.
+func (p *Presentation) implements_htmlFunc(info *PageInfo, typeName string) string {
+	if p.ImplementsHTML == nil {
+		return ""
+	}
+	index, ok := info.TypeInfoIndex[typeName]
+	if !ok {
+		return ""
+	}
+	var buf bytes.Buffer
+	err := p.ImplementsHTML.Execute(&buf, struct{ Index int }{index})
+	if err != nil {
+		log.Print(err)
+	}
+	return buf.String()
+}
+
+// methodset_html returns the "> Method set" toggle for a package-level named type.
+// Its contents are populated from JSON data by client-side JS at load time.
+func (p *Presentation) methodset_htmlFunc(info *PageInfo, typeName string) string {
+	if p.MethodSetHTML == nil {
+		return ""
+	}
+	index, ok := info.TypeInfoIndex[typeName]
+	if !ok {
+		return ""
+	}
+	var buf bytes.Buffer
+	err := p.MethodSetHTML.Execute(&buf, struct{ Index int }{index})
+	if err != nil {
+		log.Print(err)
+	}
+	return buf.String()
+}
+
+// callgraph_html returns the "> Call graph" toggle for a package-level func.
+// Its contents are populated from JSON data by client-side JS at load time.
+func (p *Presentation) callgraph_htmlFunc(info *PageInfo, recv, name string) string {
+	if p.CallGraphHTML == nil {
+		return ""
+	}
+	if recv != "" {
+		// Format must match (*ssa.Function).RelString().
+		name = fmt.Sprintf("(%s).%s", recv, name)
+	}
+	index, ok := info.CallGraphIndex[name]
+	if !ok {
+		return ""
+	}
+	var buf bytes.Buffer
+	err := p.CallGraphHTML.Execute(&buf, struct{ Index int }{index})
+	if err != nil {
+		log.Print(err)
+	}
+	return buf.String()
+}
+
+func noteTitle(note string) string {
+	return strings.Title(strings.ToLower(note))
+}
+
+func startsWithUppercase(s string) bool {
+	r, _ := utf8.DecodeRuneInString(s)
+	return unicode.IsUpper(r)
+}
+
+var exampleOutputRx = regexp.MustCompile(`(?i)//[[:space:]]*output:`)
+
+// stripExampleSuffix strips lowercase braz in Foo_braz or Foo_Bar_braz from name
+// while keeping uppercase Braz in Foo_Braz.
+func stripExampleSuffix(name string) string {
+	if i := strings.LastIndex(name, "_"); i != -1 {
+		if i < len(name)-1 && !startsWithUppercase(name[i+1:]) {
+			name = name[:i]
+		}
+	}
+	return name
+}
+
+func splitExampleName(s string) (name, suffix string) {
+	i := strings.LastIndex(s, "_")
+	if 0 <= i && i < len(s)-1 && !startsWithUppercase(s[i+1:]) {
+		name = s[:i]
+		suffix = " (" + strings.Title(s[i+1:]) + ")"
+		return
+	}
+	name = s
+	return
+}
+
+// Write an AST node to w.
+func (p *Presentation) writeNode(w io.Writer, fset *token.FileSet, x interface{}) {
+	// convert trailing tabs into spaces using a tconv filter
+	// to ensure a good outcome in most browsers (there may still
+	// be tabs in comments and strings, but converting those into
+	// the right number of spaces is much harder)
+	//
+	// TODO(gri) rethink printer flags - perhaps tconv can be eliminated
+	//           with an another printer mode (which is more efficiently
+	//           implemented in the printer than here with another layer)
+	mode := printer.TabIndent | printer.UseSpaces
+	err := (&printer.Config{Mode: mode, Tabwidth: p.TabWidth}).Fprint(&tconv{p: p, output: w}, fset, x)
+	if err != nil {
+		log.Print(err)
+	}
+}
+
+// WriteNode writes x to w.
+// TODO(bgarcia) Is this method needed? It's just a wrapper for p.writeNode.
+func (p *Presentation) WriteNode(w io.Writer, fset *token.FileSet, x interface{}) {
+	p.writeNode(w, fset, x)
+}
diff --git a/third_party/go.tools/godoc/godoc_test.go b/third_party/go.tools/godoc/godoc_test.go
new file mode 100644
index 0000000..a10a1ab
--- /dev/null
+++ b/third_party/go.tools/godoc/godoc_test.go
@@ -0,0 +1,118 @@
+// Copyright 2013 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 godoc
+
+import (
+	"testing"
+)
+
+func TestPkgLinkFunc(t *testing.T) {
+	for _, tc := range []struct {
+		path string
+		want string
+	}{
+		{"/src/fmt", "pkg/fmt"},
+		{"src/fmt", "pkg/fmt"},
+		{"/fmt", "pkg/fmt"},
+		{"fmt", "pkg/fmt"},
+	} {
+		if got := pkgLinkFunc(tc.path); got != tc.want {
+			t.Errorf("pkgLinkFunc(%v) = %v; want %v", tc.path, got, tc.want)
+		}
+	}
+}
+
+func TestSrcPosLinkFunc(t *testing.T) {
+	for _, tc := range []struct {
+		src  string
+		line int
+		low  int
+		high int
+		want string
+	}{
+		{"/src/fmt/print.go", 42, 30, 50, "/src/fmt/print.go?s=30:50#L32"},
+		{"/src/fmt/print.go", 2, 1, 5, "/src/fmt/print.go?s=1:5#L1"},
+		{"/src/fmt/print.go", 2, 0, 0, "/src/fmt/print.go#L2"},
+		{"/src/fmt/print.go", 0, 0, 0, "/src/fmt/print.go"},
+		{"/src/fmt/print.go", 0, 1, 5, "/src/fmt/print.go?s=1:5#L1"},
+		{"fmt/print.go", 0, 0, 0, "/src/fmt/print.go"},
+		{"fmt/print.go", 0, 1, 5, "/src/fmt/print.go?s=1:5#L1"},
+	} {
+		if got := srcPosLinkFunc(tc.src, tc.line, tc.low, tc.high); got != tc.want {
+			t.Errorf("srcLinkFunc(%v, %v, %v, %v) = %v; want %v", tc.src, tc.line, tc.low, tc.high, got, tc.want)
+		}
+	}
+}
+
+func TestSrcLinkFunc(t *testing.T) {
+	for _, tc := range []struct {
+		src  string
+		want string
+	}{
+		{"/src/fmt/print.go", "/src/fmt/print.go"},
+		{"src/fmt/print.go", "/src/fmt/print.go"},
+		{"/fmt/print.go", "/src/fmt/print.go"},
+		{"fmt/print.go", "/src/fmt/print.go"},
+	} {
+		if got := srcLinkFunc(tc.src); got != tc.want {
+			t.Errorf("srcLinkFunc(%v) = %v; want %v", tc.src, got, tc.want)
+		}
+	}
+}
+
+func TestQueryLinkFunc(t *testing.T) {
+	for _, tc := range []struct {
+		src   string
+		query string
+		line  int
+		want  string
+	}{
+		{"/src/fmt/print.go", "Sprintf", 33, "/src/fmt/print.go?h=Sprintf#L33"},
+		{"/src/fmt/print.go", "Sprintf", 0, "/src/fmt/print.go?h=Sprintf"},
+		{"src/fmt/print.go", "EOF", 33, "/src/fmt/print.go?h=EOF#L33"},
+		{"src/fmt/print.go", "a%3f+%26b", 1, "/src/fmt/print.go?h=a%3f+%26b#L1"},
+	} {
+		if got := queryLinkFunc(tc.src, tc.query, tc.line); got != tc.want {
+			t.Errorf("queryLinkFunc(%v, %v, %v) = %v; want %v", tc.src, tc.query, tc.line, got, tc.want)
+		}
+	}
+}
+
+func TestDocLinkFunc(t *testing.T) {
+	for _, tc := range []struct {
+		src   string
+		ident string
+		want  string
+	}{
+		{"fmt", "Sprintf", "/pkg/fmt/#Sprintf"},
+		{"fmt", "EOF", "/pkg/fmt/#EOF"},
+	} {
+		if got := docLinkFunc(tc.src, tc.ident); got != tc.want {
+			t.Errorf("docLinkFunc(%v, %v) = %v; want %v", tc.src, tc.ident, got, tc.want)
+		}
+	}
+}
+
+func TestSanitizeFunc(t *testing.T) {
+	for _, tc := range []struct {
+		src  string
+		want string
+	}{
+		{},
+		{"foo", "foo"},
+		{"func   f()", "func f()"},
+		{"func f(a int,)", "func f(a int)"},
+		{"func f(a int,\n)", "func f(a int)"},
+		{"func f(\n\ta int,\n\tb int,\n\tc int,\n)", "func f(a int, b int, c int)"},
+		{"  (   a,   b,  c  )  ", "(a, b, c)"},
+		{"(  a,  b, c    int, foo   bar  ,  )", "(a, b, c int, foo bar)"},
+		{"{   a,   b}", "{a, b}"},
+		{"[   a,   b]", "[a, b]"},
+	} {
+		if got := sanitizeFunc(tc.src); got != tc.want {
+			t.Errorf("sanitizeFunc(%v) = %v; want %v", tc.src, got, tc.want)
+		}
+	}
+}
diff --git a/third_party/go.tools/godoc/index.go b/third_party/go.tools/godoc/index.go
new file mode 100644
index 0000000..fae13ec
--- /dev/null
+++ b/third_party/go.tools/godoc/index.go
@@ -0,0 +1,1590 @@
+// 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.
+
+// This file contains the infrastructure to create an
+// identifier and full-text index for a set of Go files.
+//
+// Algorithm for identifier index:
+// - traverse all .go files of the file tree specified by root
+// - for each identifier (word) encountered, collect all occurrences (spots)
+//   into a list; this produces a list of spots for each word
+// - reduce the lists: from a list of spots to a list of FileRuns,
+//   and from a list of FileRuns into a list of PakRuns
+// - make a HitList from the PakRuns
+//
+// Details:
+// - keep two lists per word: one containing package-level declarations
+//   that have snippets, and one containing all other spots
+// - keep the snippets in a separate table indexed by snippet index
+//   and store the snippet index in place of the line number in a SpotInfo
+//   (the line number for spots with snippets is stored in the snippet)
+// - at the end, create lists of alternative spellings for a given
+//   word
+//
+// Algorithm for full text index:
+// - concatenate all source code in a byte buffer (in memory)
+// - add the files to a file set in lockstep as they are added to the byte
+//   buffer such that a byte buffer offset corresponds to the Pos value for
+//   that file location
+// - create a suffix array from the concatenated sources
+//
+// String lookup in full text index:
+// - use the suffix array to lookup a string's offsets - the offsets
+//   correspond to the Pos values relative to the file set
+// - translate the Pos values back into file and line information and
+//   sort the result
+
+package godoc
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/gob"
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/doc"
+	"go/parser"
+	"go/token"
+	"index/suffixarray"
+	"io"
+	"log"
+	"os"
+	pathpkg "path"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+	"unicode"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/util"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+// ----------------------------------------------------------------------------
+// InterfaceSlice is a helper type for sorting interface
+// slices according to some slice-specific sort criteria.
+
+type comparer func(x, y interface{}) bool
+
+type interfaceSlice struct {
+	slice []interface{}
+	less  comparer
+}
+
+// ----------------------------------------------------------------------------
+// RunList
+
+// A RunList is a list of entries that can be sorted according to some
+// criteria. A RunList may be compressed by grouping "runs" of entries
+// which are equal (according to the sort critera) into a new RunList of
+// runs. For instance, a RunList containing pairs (x, y) may be compressed
+// into a RunList containing pair runs (x, {y}) where each run consists of
+// a list of y's with the same x.
+type RunList []interface{}
+
+func (h RunList) sort(less comparer) {
+	sort.Sort(&interfaceSlice{h, less})
+}
+
+func (p *interfaceSlice) Len() int           { return len(p.slice) }
+func (p *interfaceSlice) Less(i, j int) bool { return p.less(p.slice[i], p.slice[j]) }
+func (p *interfaceSlice) Swap(i, j int)      { p.slice[i], p.slice[j] = p.slice[j], p.slice[i] }
+
+// Compress entries which are the same according to a sort criteria
+// (specified by less) into "runs".
+func (h RunList) reduce(less comparer, newRun func(h RunList) interface{}) RunList {
+	if len(h) == 0 {
+		return nil
+	}
+	// len(h) > 0
+
+	// create runs of entries with equal values
+	h.sort(less)
+
+	// for each run, make a new run object and collect them in a new RunList
+	var hh RunList
+	i, x := 0, h[0]
+	for j, y := range h {
+		if less(x, y) {
+			hh = append(hh, newRun(h[i:j]))
+			i, x = j, h[j] // start a new run
+		}
+	}
+	// add final run, if any
+	if i < len(h) {
+		hh = append(hh, newRun(h[i:]))
+	}
+
+	return hh
+}
+
+// ----------------------------------------------------------------------------
+// KindRun
+
+// Debugging support. Disable to see multiple entries per line.
+const removeDuplicates = true
+
+// A KindRun is a run of SpotInfos of the same kind in a given file.
+// The kind (3 bits) is stored in each SpotInfo element; to find the
+// kind of a KindRun, look at any of its elements.
+type KindRun []SpotInfo
+
+// KindRuns are sorted by line number or index. Since the isIndex bit
+// is always the same for all infos in one list we can compare lori's.
+func (k KindRun) Len() int           { return len(k) }
+func (k KindRun) Less(i, j int) bool { return k[i].Lori() < k[j].Lori() }
+func (k KindRun) Swap(i, j int)      { k[i], k[j] = k[j], k[i] }
+
+// FileRun contents are sorted by Kind for the reduction into KindRuns.
+func lessKind(x, y interface{}) bool { return x.(SpotInfo).Kind() < y.(SpotInfo).Kind() }
+
+// newKindRun allocates a new KindRun from the SpotInfo run h.
+func newKindRun(h RunList) interface{} {
+	run := make(KindRun, len(h))
+	for i, x := range h {
+		run[i] = x.(SpotInfo)
+	}
+
+	// Spots were sorted by file and kind to create this run.
+	// Within this run, sort them by line number or index.
+	sort.Sort(run)
+
+	if removeDuplicates {
+		// Since both the lori and kind field must be
+		// same for duplicates, and since the isIndex
+		// bit is always the same for all infos in one
+		// list we can simply compare the entire info.
+		k := 0
+		prev := SpotInfo(1<<32 - 1) // an unlikely value
+		for _, x := range run {
+			if x != prev {
+				run[k] = x
+				k++
+				prev = x
+			}
+		}
+		run = run[0:k]
+	}
+
+	return run
+}
+
+// ----------------------------------------------------------------------------
+// FileRun
+
+// A Pak describes a Go package.
+type Pak struct {
+	Path string // path of directory containing the package
+	Name string // package name as declared by package clause
+}
+
+// Paks are sorted by name (primary key) and by import path (secondary key).
+func (p *Pak) less(q *Pak) bool {
+	return p.Name < q.Name || p.Name == q.Name && p.Path < q.Path
+}
+
+// A File describes a Go file.
+type File struct {
+	Name string // directory-local file name
+	Pak  *Pak   // the package to which the file belongs
+}
+
+// Path returns the file path of f.
+func (f *File) Path() string {
+	return pathpkg.Join(f.Pak.Path, f.Name)
+}
+
+// A Spot describes a single occurrence of a word.
+type Spot struct {
+	File *File
+	Info SpotInfo
+}
+
+// A FileRun is a list of KindRuns belonging to the same file.
+type FileRun struct {
+	File   *File
+	Groups []KindRun
+}
+
+// Spots are sorted by file path for the reduction into FileRuns.
+func lessSpot(x, y interface{}) bool {
+	fx := x.(Spot).File
+	fy := y.(Spot).File
+	// same as "return fx.Path() < fy.Path()" but w/o computing the file path first
+	px := fx.Pak.Path
+	py := fy.Pak.Path
+	return px < py || px == py && fx.Name < fy.Name
+}
+
+// newFileRun allocates a new FileRun from the Spot run h.
+func newFileRun(h RunList) interface{} {
+	file := h[0].(Spot).File
+
+	// reduce the list of Spots into a list of KindRuns
+	h1 := make(RunList, len(h))
+	for i, x := range h {
+		h1[i] = x.(Spot).Info
+	}
+	h2 := h1.reduce(lessKind, newKindRun)
+
+	// create the FileRun
+	groups := make([]KindRun, len(h2))
+	for i, x := range h2 {
+		groups[i] = x.(KindRun)
+	}
+	return &FileRun{file, groups}
+}
+
+// ----------------------------------------------------------------------------
+// PakRun
+
+// A PakRun describes a run of *FileRuns of a package.
+type PakRun struct {
+	Pak   *Pak
+	Files []*FileRun
+}
+
+// Sorting support for files within a PakRun.
+func (p *PakRun) Len() int           { return len(p.Files) }
+func (p *PakRun) Less(i, j int) bool { return p.Files[i].File.Name < p.Files[j].File.Name }
+func (p *PakRun) Swap(i, j int)      { p.Files[i], p.Files[j] = p.Files[j], p.Files[i] }
+
+// FileRuns are sorted by package for the reduction into PakRuns.
+func lessFileRun(x, y interface{}) bool {
+	return x.(*FileRun).File.Pak.less(y.(*FileRun).File.Pak)
+}
+
+// newPakRun allocates a new PakRun from the *FileRun run h.
+func newPakRun(h RunList) interface{} {
+	pak := h[0].(*FileRun).File.Pak
+	files := make([]*FileRun, len(h))
+	for i, x := range h {
+		files[i] = x.(*FileRun)
+	}
+	run := &PakRun{pak, files}
+	sort.Sort(run) // files were sorted by package; sort them by file now
+	return run
+}
+
+// ----------------------------------------------------------------------------
+// HitList
+
+// A HitList describes a list of PakRuns.
+type HitList []*PakRun
+
+// PakRuns are sorted by package.
+func lessPakRun(x, y interface{}) bool { return x.(*PakRun).Pak.less(y.(*PakRun).Pak) }
+
+func reduce(h0 RunList) HitList {
+	// reduce a list of Spots into a list of FileRuns
+	h1 := h0.reduce(lessSpot, newFileRun)
+	// reduce a list of FileRuns into a list of PakRuns
+	h2 := h1.reduce(lessFileRun, newPakRun)
+	// sort the list of PakRuns by package
+	h2.sort(lessPakRun)
+	// create a HitList
+	h := make(HitList, len(h2))
+	for i, p := range h2 {
+		h[i] = p.(*PakRun)
+	}
+	return h
+}
+
+// filter returns a new HitList created by filtering
+// all PakRuns from h that have a matching pakname.
+func (h HitList) filter(pakname string) HitList {
+	var hh HitList
+	for _, p := range h {
+		if p.Pak.Name == pakname {
+			hh = append(hh, p)
+		}
+	}
+	return hh
+}
+
+// ----------------------------------------------------------------------------
+// AltWords
+
+type wordPair struct {
+	canon string // canonical word spelling (all lowercase)
+	alt   string // alternative spelling
+}
+
+// An AltWords describes a list of alternative spellings for a
+// canonical (all lowercase) spelling of a word.
+type AltWords struct {
+	Canon string   // canonical word spelling (all lowercase)
+	Alts  []string // alternative spelling for the same word
+}
+
+// wordPairs are sorted by their canonical spelling.
+func lessWordPair(x, y interface{}) bool { return x.(*wordPair).canon < y.(*wordPair).canon }
+
+// newAltWords allocates a new AltWords from the *wordPair run h.
+func newAltWords(h RunList) interface{} {
+	canon := h[0].(*wordPair).canon
+	alts := make([]string, len(h))
+	for i, x := range h {
+		alts[i] = x.(*wordPair).alt
+	}
+	return &AltWords{canon, alts}
+}
+
+func (a *AltWords) filter(s string) *AltWords {
+	var alts []string
+	for _, w := range a.Alts {
+		if w != s {
+			alts = append(alts, w)
+		}
+	}
+	if len(alts) > 0 {
+		return &AltWords{a.Canon, alts}
+	}
+	return nil
+}
+
+// Ident stores information about external identifiers in order to create
+// links to package documentation.
+type Ident struct {
+	Path    string // e.g. "net/http"
+	Package string // e.g. "http"
+	Name    string // e.g. "NewRequest"
+	Doc     string // e.g. "NewRequest returns a new Request..."
+}
+
+// byImportCount sorts the given slice of Idents by the import
+// counts of the packages to which they belong.
+type byImportCount struct {
+	Idents      []Ident
+	ImportCount map[string]int
+}
+
+func (ic byImportCount) Len() int {
+	return len(ic.Idents)
+}
+
+func (ic byImportCount) Less(i, j int) bool {
+	ri := ic.ImportCount[ic.Idents[i].Path]
+	rj := ic.ImportCount[ic.Idents[j].Path]
+	if ri == rj {
+		return ic.Idents[i].Path < ic.Idents[j].Path
+	}
+	return ri > rj
+}
+
+func (ic byImportCount) Swap(i, j int) {
+	ic.Idents[i], ic.Idents[j] = ic.Idents[j], ic.Idents[i]
+}
+
+func (ic byImportCount) String() string {
+	buf := bytes.NewBuffer([]byte("["))
+	for _, v := range ic.Idents {
+		buf.WriteString(fmt.Sprintf("\n\t%s, %s (%d)", v.Path, v.Name, ic.ImportCount[v.Path]))
+	}
+	buf.WriteString("\n]")
+	return buf.String()
+}
+
+// filter creates a new Ident list where the results match the given
+// package name.
+func (ic byImportCount) filter(pakname string) []Ident {
+	if ic.Idents == nil {
+		return nil
+	}
+	var res []Ident
+	for _, i := range ic.Idents {
+		if i.Package == pakname {
+			res = append(res, i)
+		}
+	}
+	return res
+}
+
+// top returns the top n identifiers.
+func (ic byImportCount) top(n int) []Ident {
+	if len(ic.Idents) > n {
+		return ic.Idents[:n]
+	}
+	return ic.Idents
+}
+
+// ----------------------------------------------------------------------------
+// Indexer
+
+type IndexResult struct {
+	Decls  RunList // package-level declarations (with snippets)
+	Others RunList // all other occurrences
+}
+
+// Statistics provides statistics information for an index.
+type Statistics struct {
+	Bytes int // total size of indexed source files
+	Files int // number of indexed source files
+	Lines int // number of lines (all files)
+	Words int // number of different identifiers
+	Spots int // number of identifier occurrences
+}
+
+// An Indexer maintains the data structures and provides the machinery
+// for indexing .go files under a file tree. It implements the path.Visitor
+// interface for walking file trees, and the ast.Visitor interface for
+// walking Go ASTs.
+type Indexer struct {
+	c          *Corpus
+	fset       *token.FileSet // file set for all indexed files
+	fsOpenGate chan bool      // send pre fs.Open; receive on close
+
+	mu            sync.Mutex              // guards all the following
+	sources       bytes.Buffer            // concatenated sources
+	strings       map[string]string       // interned string
+	packages      map[Pak]*Pak            // interned *Paks
+	words         map[string]*IndexResult // RunLists of Spots
+	snippets      []*Snippet              // indices are stored in SpotInfos
+	current       *token.File             // last file added to file set
+	file          *File                   // AST for current file
+	decl          ast.Decl                // AST for current decl
+	stats         Statistics
+	throttle      *util.Throttle
+	importCount   map[string]int                 // package path ("net/http") => count
+	packagePath   map[string]map[string]bool     // "template" => "text/template" => true
+	exports       map[string]map[string]SpotKind // "net/http" => "ListenAndServe" => FuncDecl
+	curPkgExports map[string]SpotKind
+	idents        map[SpotKind]map[string][]Ident // kind => name => list of Idents
+}
+
+func (x *Indexer) intern(s string) string {
+	if s, ok := x.strings[s]; ok {
+		return s
+	}
+	x.strings[s] = s
+	return s
+}
+
+func (x *Indexer) lookupPackage(path, name string) *Pak {
+	// In the source directory tree, more than one package may
+	// live in the same directory. For the packages map, construct
+	// a key that includes both the directory path and the package
+	// name.
+	key := Pak{Path: x.intern(path), Name: x.intern(name)}
+	pak := x.packages[key]
+	if pak == nil {
+		pak = &key
+		x.packages[key] = pak
+	}
+	return pak
+}
+
+func (x *Indexer) addSnippet(s *Snippet) int {
+	index := len(x.snippets)
+	x.snippets = append(x.snippets, s)
+	return index
+}
+
+func (x *Indexer) visitIdent(kind SpotKind, id *ast.Ident) {
+	if id == nil {
+		return
+	}
+	name := x.intern(id.Name)
+
+	switch kind {
+	case TypeDecl, FuncDecl, ConstDecl, VarDecl:
+		x.curPkgExports[name] = kind
+	}
+
+	lists, found := x.words[name]
+	if !found {
+		lists = new(IndexResult)
+		x.words[name] = lists
+	}
+
+	if kind == Use || x.decl == nil {
+		if x.c.IndexGoCode {
+			// not a declaration or no snippet required
+			info := makeSpotInfo(kind, x.current.Line(id.Pos()), false)
+			lists.Others = append(lists.Others, Spot{x.file, info})
+		}
+	} else {
+		// a declaration with snippet
+		index := x.addSnippet(NewSnippet(x.fset, x.decl, id))
+		info := makeSpotInfo(kind, index, true)
+		lists.Decls = append(lists.Decls, Spot{x.file, info})
+	}
+
+	x.stats.Spots++
+}
+
+func (x *Indexer) visitFieldList(kind SpotKind, flist *ast.FieldList) {
+	for _, f := range flist.List {
+		x.decl = nil // no snippets for fields
+		for _, name := range f.Names {
+			x.visitIdent(kind, name)
+		}
+		ast.Walk(x, f.Type)
+		// ignore tag - not indexed at the moment
+	}
+}
+
+func (x *Indexer) visitSpec(kind SpotKind, spec ast.Spec) {
+	switch n := spec.(type) {
+	case *ast.ImportSpec:
+		x.visitIdent(ImportDecl, n.Name)
+		if n.Path != nil {
+			if imp, err := strconv.Unquote(n.Path.Value); err == nil {
+				x.importCount[x.intern(imp)]++
+			}
+		}
+
+	case *ast.ValueSpec:
+		for _, n := range n.Names {
+			x.visitIdent(kind, n)
+		}
+		ast.Walk(x, n.Type)
+		for _, v := range n.Values {
+			ast.Walk(x, v)
+		}
+
+	case *ast.TypeSpec:
+		x.visitIdent(TypeDecl, n.Name)
+		ast.Walk(x, n.Type)
+	}
+}
+
+func (x *Indexer) visitGenDecl(decl *ast.GenDecl) {
+	kind := VarDecl
+	if decl.Tok == token.CONST {
+		kind = ConstDecl
+	}
+	x.decl = decl
+	for _, s := range decl.Specs {
+		x.visitSpec(kind, s)
+	}
+}
+
+func (x *Indexer) Visit(node ast.Node) ast.Visitor {
+	switch n := node.(type) {
+	case nil:
+		// nothing to do
+
+	case *ast.Ident:
+		x.visitIdent(Use, n)
+
+	case *ast.FieldList:
+		x.visitFieldList(VarDecl, n)
+
+	case *ast.InterfaceType:
+		x.visitFieldList(MethodDecl, n.Methods)
+
+	case *ast.DeclStmt:
+		// local declarations should only be *ast.GenDecls;
+		// ignore incorrect ASTs
+		if decl, ok := n.Decl.(*ast.GenDecl); ok {
+			x.decl = nil // no snippets for local declarations
+			x.visitGenDecl(decl)
+		}
+
+	case *ast.GenDecl:
+		x.decl = n
+		x.visitGenDecl(n)
+
+	case *ast.FuncDecl:
+		kind := FuncDecl
+		if n.Recv != nil {
+			kind = MethodDecl
+			ast.Walk(x, n.Recv)
+		}
+		x.decl = n
+		x.visitIdent(kind, n.Name)
+		ast.Walk(x, n.Type)
+		if n.Body != nil {
+			ast.Walk(x, n.Body)
+		}
+
+	case *ast.File:
+		x.decl = nil
+		x.visitIdent(PackageClause, n.Name)
+		for _, d := range n.Decls {
+			ast.Walk(x, d)
+		}
+
+	default:
+		return x
+	}
+
+	return nil
+}
+
+// addFile adds a file to the index if possible and returns the file set file
+// and the file's AST if it was successfully parsed as a Go file. If addFile
+// failed (that is, if the file was not added), it returns file == nil.
+func (x *Indexer) addFile(f vfs.ReadSeekCloser, filename string, goFile bool) (file *token.File, ast *ast.File) {
+	defer f.Close()
+
+	// The file set's base offset and x.sources size must be in lock-step;
+	// this permits the direct mapping of suffix array lookup results to
+	// to corresponding Pos values.
+	//
+	// When a file is added to the file set, its offset base increases by
+	// the size of the file + 1; and the initial base offset is 1. Add an
+	// extra byte to the sources here.
+	x.sources.WriteByte(0)
+
+	// If the sources length doesn't match the file set base at this point
+	// the file set implementation changed or we have another error.
+	base := x.fset.Base()
+	if x.sources.Len() != base {
+		panic("internal error: file base incorrect")
+	}
+
+	// append file contents (src) to x.sources
+	if _, err := x.sources.ReadFrom(f); err == nil {
+		src := x.sources.Bytes()[base:]
+
+		if goFile {
+			// parse the file and in the process add it to the file set
+			if ast, err = parser.ParseFile(x.fset, filename, src, parser.ParseComments); err == nil {
+				file = x.fset.File(ast.Pos()) // ast.Pos() is inside the file
+				return
+			}
+			// file has parse errors, and the AST may be incorrect -
+			// set lines information explicitly and index as ordinary
+			// text file (cannot fall through to the text case below
+			// because the file has already been added to the file set
+			// by the parser)
+			file = x.fset.File(token.Pos(base)) // token.Pos(base) is inside the file
+			file.SetLinesForContent(src)
+			ast = nil
+			return
+		}
+
+		if util.IsText(src) {
+			// only add the file to the file set (for the full text index)
+			file = x.fset.AddFile(filename, x.fset.Base(), len(src))
+			file.SetLinesForContent(src)
+			return
+		}
+	}
+
+	// discard possibly added data
+	x.sources.Truncate(base - 1) // -1 to remove added byte 0 since no file was added
+	return
+}
+
+// Design note: Using an explicit white list of permitted files for indexing
+// makes sure that the important files are included and massively reduces the
+// number of files to index. The advantage over a blacklist is that unexpected
+// (non-blacklisted) files won't suddenly explode the index.
+
+// Files are whitelisted if they have a file name or extension
+// present as key in whitelisted.
+var whitelisted = map[string]bool{
+	".bash":        true,
+	".c":           true,
+	".cc":          true,
+	".cpp":         true,
+	".cxx":         true,
+	".css":         true,
+	".go":          true,
+	".goc":         true,
+	".h":           true,
+	".hh":          true,
+	".hpp":         true,
+	".hxx":         true,
+	".html":        true,
+	".js":          true,
+	".out":         true,
+	".py":          true,
+	".s":           true,
+	".sh":          true,
+	".txt":         true,
+	".xml":         true,
+	"AUTHORS":      true,
+	"CONTRIBUTORS": true,
+	"LICENSE":      true,
+	"Makefile":     true,
+	"PATENTS":      true,
+	"README":       true,
+}
+
+// isWhitelisted returns true if a file is on the list
+// of "permitted" files for indexing. The filename must
+// be the directory-local name of the file.
+func isWhitelisted(filename string) bool {
+	key := pathpkg.Ext(filename)
+	if key == "" {
+		// file has no extension - use entire filename
+		key = filename
+	}
+	return whitelisted[key]
+}
+
+func (x *Indexer) indexDocs(dirname string, filename string, astFile *ast.File) {
+	pkgName := x.intern(astFile.Name.Name)
+	if pkgName == "main" {
+		return
+	}
+	pkgPath := x.intern(strings.TrimPrefix(strings.TrimPrefix(dirname, "/src/"), "pkg/"))
+	astPkg := ast.Package{
+		Name: pkgName,
+		Files: map[string]*ast.File{
+			filename: astFile,
+		},
+	}
+	var m doc.Mode
+	docPkg := doc.New(&astPkg, dirname, m)
+	addIdent := func(sk SpotKind, name string, docstr string) {
+		if x.idents[sk] == nil {
+			x.idents[sk] = make(map[string][]Ident)
+		}
+		name = x.intern(name)
+		x.idents[sk][name] = append(x.idents[sk][name], Ident{
+			Path:    pkgPath,
+			Package: pkgName,
+			Name:    name,
+			Doc:     doc.Synopsis(docstr),
+		})
+	}
+
+	if x.idents[PackageClause] == nil {
+		x.idents[PackageClause] = make(map[string][]Ident)
+	}
+	// List of words under which the package identifier will be stored.
+	// This includes the package name and the components of the directory
+	// in which it resides.
+	words := strings.Split(pathpkg.Dir(pkgPath), "/")
+	if words[0] == "." {
+		words = []string{}
+	}
+	name := x.intern(docPkg.Name)
+	synopsis := doc.Synopsis(docPkg.Doc)
+	words = append(words, name)
+	pkgIdent := Ident{
+		Path:    pkgPath,
+		Package: pkgName,
+		Name:    name,
+		Doc:     synopsis,
+	}
+	for _, word := range words {
+		word = x.intern(word)
+		found := false
+		pkgs := x.idents[PackageClause][word]
+		for i, p := range pkgs {
+			if p.Path == pkgPath {
+				if docPkg.Doc != "" {
+					p.Doc = synopsis
+					pkgs[i] = p
+				}
+				found = true
+				break
+			}
+		}
+		if !found {
+			x.idents[PackageClause][word] = append(x.idents[PackageClause][word], pkgIdent)
+		}
+	}
+
+	for _, c := range docPkg.Consts {
+		for _, name := range c.Names {
+			addIdent(ConstDecl, name, c.Doc)
+		}
+	}
+	for _, t := range docPkg.Types {
+		addIdent(TypeDecl, t.Name, t.Doc)
+		for _, c := range t.Consts {
+			for _, name := range c.Names {
+				addIdent(ConstDecl, name, c.Doc)
+			}
+		}
+		for _, v := range t.Vars {
+			for _, name := range v.Names {
+				addIdent(VarDecl, name, v.Doc)
+			}
+		}
+		for _, f := range t.Funcs {
+			addIdent(FuncDecl, f.Name, f.Doc)
+		}
+		for _, f := range t.Methods {
+			addIdent(MethodDecl, f.Name, f.Doc)
+			// Change the name of methods to be "<typename>.<methodname>".
+			// They will still be indexed as <methodname>.
+			idents := x.idents[MethodDecl][f.Name]
+			idents[len(idents)-1].Name = x.intern(t.Name + "." + f.Name)
+		}
+	}
+	for _, v := range docPkg.Vars {
+		for _, name := range v.Names {
+			addIdent(VarDecl, name, v.Doc)
+		}
+	}
+	for _, f := range docPkg.Funcs {
+		addIdent(FuncDecl, f.Name, f.Doc)
+	}
+}
+
+func (x *Indexer) indexGoFile(dirname string, filename string, file *token.File, astFile *ast.File) {
+	pkgName := astFile.Name.Name
+
+	if x.c.IndexGoCode {
+		x.current = file
+		pak := x.lookupPackage(dirname, pkgName)
+		x.file = &File{filename, pak}
+		ast.Walk(x, astFile)
+	}
+
+	if x.c.IndexDocs {
+		// Test files are already filtered out in visitFile if IndexGoCode and
+		// IndexFullText are false.  Otherwise, check here.
+		isTestFile := (x.c.IndexGoCode || x.c.IndexFullText) &&
+			(strings.HasSuffix(filename, "_test.go") || strings.HasPrefix(dirname, "/test/"))
+		if !isTestFile {
+			x.indexDocs(dirname, filename, astFile)
+		}
+	}
+
+	ppKey := x.intern(pkgName)
+	if _, ok := x.packagePath[ppKey]; !ok {
+		x.packagePath[ppKey] = make(map[string]bool)
+	}
+	pkgPath := x.intern(strings.TrimPrefix(strings.TrimPrefix(dirname, "/src/"), "pkg/"))
+	x.packagePath[ppKey][pkgPath] = true
+
+	// Merge in exported symbols found walking this file into
+	// the map for that package.
+	if len(x.curPkgExports) > 0 {
+		dest, ok := x.exports[pkgPath]
+		if !ok {
+			dest = make(map[string]SpotKind)
+			x.exports[pkgPath] = dest
+		}
+		for k, v := range x.curPkgExports {
+			dest[k] = v
+		}
+	}
+}
+
+func (x *Indexer) visitFile(dirname string, fi os.FileInfo) {
+	if fi.IsDir() || !x.c.IndexEnabled {
+		return
+	}
+
+	filename := pathpkg.Join(dirname, fi.Name())
+	goFile := isGoFile(fi)
+
+	switch {
+	case x.c.IndexFullText:
+		if !isWhitelisted(fi.Name()) {
+			return
+		}
+	case x.c.IndexGoCode:
+		if !goFile {
+			return
+		}
+	case x.c.IndexDocs:
+		if !goFile ||
+			strings.HasSuffix(fi.Name(), "_test.go") ||
+			strings.HasPrefix(dirname, "/test/") {
+			return
+		}
+	default:
+		// No indexing turned on.
+		return
+	}
+
+	x.fsOpenGate <- true
+	defer func() { <-x.fsOpenGate }()
+
+	// open file
+	f, err := x.c.fs.Open(filename)
+	if err != nil {
+		return
+	}
+
+	x.mu.Lock()
+	defer x.mu.Unlock()
+
+	x.throttle.Throttle()
+
+	x.curPkgExports = make(map[string]SpotKind)
+	file, fast := x.addFile(f, filename, goFile)
+	if file == nil {
+		return // addFile failed
+	}
+
+	if fast != nil {
+		x.indexGoFile(dirname, fi.Name(), file, fast)
+	}
+
+	// update statistics
+	x.stats.Bytes += file.Size()
+	x.stats.Files++
+	x.stats.Lines += file.LineCount()
+}
+
+// indexOptions contains information that affects the contents of an index.
+type indexOptions struct {
+	// Docs provides documentation search results.
+	// It is only consulted if IndexEnabled is true.
+	// The default values is true.
+	Docs bool
+
+	// GoCode provides Go source code search results.
+	// It is only consulted if IndexEnabled is true.
+	// The default values is true.
+	GoCode bool
+
+	// FullText provides search results from all files.
+	// It is only consulted if IndexEnabled is true.
+	// The default values is true.
+	FullText bool
+
+	// MaxResults optionally specifies the maximum results for indexing.
+	// The default is 1000.
+	MaxResults int
+}
+
+// ----------------------------------------------------------------------------
+// Index
+
+type LookupResult struct {
+	Decls  HitList // package-level declarations (with snippets)
+	Others HitList // all other occurrences
+}
+
+type Index struct {
+	fset        *token.FileSet           // file set used during indexing; nil if no textindex
+	suffixes    *suffixarray.Index       // suffixes for concatenated sources; nil if no textindex
+	words       map[string]*LookupResult // maps words to hit lists
+	alts        map[string]*AltWords     // maps canonical(words) to lists of alternative spellings
+	snippets    []*Snippet               // all snippets, indexed by snippet index
+	stats       Statistics
+	importCount map[string]int                 // package path ("net/http") => count
+	packagePath map[string]map[string]bool     // "template" => "text/template" => true
+	exports     map[string]map[string]SpotKind // "net/http" => "ListenAndServe" => FuncDecl
+	idents      map[SpotKind]map[string][]Ident
+	opts        indexOptions
+}
+
+func canonical(w string) string { return strings.ToLower(w) }
+
+// Somewhat arbitrary, but I figure low enough to not hurt disk-based filesystems
+// consuming file descriptors, where some systems have low 256 or 512 limits.
+// Go should have a built-in way to cap fd usage under the ulimit.
+const (
+	maxOpenFiles = 200
+	maxOpenDirs  = 50
+)
+
+func (c *Corpus) throttle() float64 {
+	if c.IndexThrottle <= 0 {
+		return 0.9
+	}
+	if c.IndexThrottle > 1.0 {
+		return 1.0
+	}
+	return c.IndexThrottle
+}
+
+// NewIndex creates a new index for the .go files provided by the corpus.
+func (c *Corpus) NewIndex() *Index {
+	// initialize Indexer
+	// (use some reasonably sized maps to start)
+	x := &Indexer{
+		c:           c,
+		fset:        token.NewFileSet(),
+		fsOpenGate:  make(chan bool, maxOpenFiles),
+		strings:     make(map[string]string),
+		packages:    make(map[Pak]*Pak, 256),
+		words:       make(map[string]*IndexResult, 8192),
+		throttle:    util.NewThrottle(c.throttle(), 100*time.Millisecond), // run at least 0.1s at a time
+		importCount: make(map[string]int),
+		packagePath: make(map[string]map[string]bool),
+		exports:     make(map[string]map[string]SpotKind),
+		idents:      make(map[SpotKind]map[string][]Ident, 4),
+	}
+
+	// index all files in the directories given by dirnames
+	var wg sync.WaitGroup // outstanding ReadDir + visitFile
+	dirGate := make(chan bool, maxOpenDirs)
+	for dirname := range c.fsDirnames() {
+		if c.IndexDirectory != nil && !c.IndexDirectory(dirname) {
+			continue
+		}
+		dirGate <- true
+		wg.Add(1)
+		go func(dirname string) {
+			defer func() { <-dirGate }()
+			defer wg.Done()
+
+			list, err := c.fs.ReadDir(dirname)
+			if err != nil {
+				log.Printf("ReadDir(%q): %v; skipping directory", dirname, err)
+				return // ignore this directory
+			}
+			for _, fi := range list {
+				wg.Add(1)
+				go func(fi os.FileInfo) {
+					defer wg.Done()
+					x.visitFile(dirname, fi)
+				}(fi)
+			}
+		}(dirname)
+	}
+	wg.Wait()
+
+	if !c.IndexFullText {
+		// the file set, the current file, and the sources are
+		// not needed after indexing if no text index is built -
+		// help GC and clear them
+		x.fset = nil
+		x.sources.Reset()
+		x.current = nil // contains reference to fset!
+	}
+
+	// for each word, reduce the RunLists into a LookupResult;
+	// also collect the word with its canonical spelling in a
+	// word list for later computation of alternative spellings
+	words := make(map[string]*LookupResult)
+	var wlist RunList
+	for w, h := range x.words {
+		decls := reduce(h.Decls)
+		others := reduce(h.Others)
+		words[w] = &LookupResult{
+			Decls:  decls,
+			Others: others,
+		}
+		wlist = append(wlist, &wordPair{canonical(w), w})
+		x.throttle.Throttle()
+	}
+	x.stats.Words = len(words)
+
+	// reduce the word list {canonical(w), w} into
+	// a list of AltWords runs {canonical(w), {w}}
+	alist := wlist.reduce(lessWordPair, newAltWords)
+
+	// convert alist into a map of alternative spellings
+	alts := make(map[string]*AltWords)
+	for i := 0; i < len(alist); i++ {
+		a := alist[i].(*AltWords)
+		alts[a.Canon] = a
+	}
+
+	// create text index
+	var suffixes *suffixarray.Index
+	if c.IndexFullText {
+		suffixes = suffixarray.New(x.sources.Bytes())
+	}
+
+	// sort idents by the number of imports of their respective packages
+	for _, idMap := range x.idents {
+		for _, ir := range idMap {
+			sort.Sort(byImportCount{ir, x.importCount})
+		}
+	}
+
+	return &Index{
+		fset:        x.fset,
+		suffixes:    suffixes,
+		words:       words,
+		alts:        alts,
+		snippets:    x.snippets,
+		stats:       x.stats,
+		importCount: x.importCount,
+		packagePath: x.packagePath,
+		exports:     x.exports,
+		idents:      x.idents,
+		opts: indexOptions{
+			Docs:       x.c.IndexDocs,
+			GoCode:     x.c.IndexGoCode,
+			FullText:   x.c.IndexFullText,
+			MaxResults: x.c.MaxResults,
+		},
+	}
+}
+
+var ErrFileIndexVersion = errors.New("file index version out of date")
+
+const fileIndexVersion = 3
+
+// fileIndex is the subset of Index that's gob-encoded for use by
+// Index.Write and Index.Read.
+type fileIndex struct {
+	Version     int
+	Words       map[string]*LookupResult
+	Alts        map[string]*AltWords
+	Snippets    []*Snippet
+	Fulltext    bool
+	Stats       Statistics
+	ImportCount map[string]int
+	PackagePath map[string]map[string]bool
+	Exports     map[string]map[string]SpotKind
+	Idents      map[SpotKind]map[string][]Ident
+	Opts        indexOptions
+}
+
+func (x *fileIndex) Write(w io.Writer) error {
+	return gob.NewEncoder(w).Encode(x)
+}
+
+func (x *fileIndex) Read(r io.Reader) error {
+	return gob.NewDecoder(r).Decode(x)
+}
+
+// WriteTo writes the index x to w.
+func (x *Index) WriteTo(w io.Writer) (n int64, err error) {
+	w = countingWriter{&n, w}
+	fulltext := false
+	if x.suffixes != nil {
+		fulltext = true
+	}
+	fx := fileIndex{
+		Version:     fileIndexVersion,
+		Words:       x.words,
+		Alts:        x.alts,
+		Snippets:    x.snippets,
+		Fulltext:    fulltext,
+		Stats:       x.stats,
+		ImportCount: x.importCount,
+		PackagePath: x.packagePath,
+		Exports:     x.exports,
+		Idents:      x.idents,
+		Opts:        x.opts,
+	}
+	if err := fx.Write(w); err != nil {
+		return 0, err
+	}
+	if fulltext {
+		encode := func(x interface{}) error {
+			return gob.NewEncoder(w).Encode(x)
+		}
+		if err := x.fset.Write(encode); err != nil {
+			return 0, err
+		}
+		if err := x.suffixes.Write(w); err != nil {
+			return 0, err
+		}
+	}
+	return n, nil
+}
+
+// ReadFrom reads the index from r into x; x must not be nil.
+// If r does not also implement io.ByteReader, it will be wrapped in a bufio.Reader.
+// If the index is from an old version, the error is ErrFileIndexVersion.
+func (x *Index) ReadFrom(r io.Reader) (n int64, err error) {
+	// We use the ability to read bytes as a plausible surrogate for buffering.
+	if _, ok := r.(io.ByteReader); !ok {
+		r = bufio.NewReader(r)
+	}
+	r = countingReader{&n, r.(byteReader)}
+	var fx fileIndex
+	if err := fx.Read(r); err != nil {
+		return n, err
+	}
+	if fx.Version != fileIndexVersion {
+		return 0, ErrFileIndexVersion
+	}
+	x.words = fx.Words
+	x.alts = fx.Alts
+	x.snippets = fx.Snippets
+	x.stats = fx.Stats
+	x.importCount = fx.ImportCount
+	x.packagePath = fx.PackagePath
+	x.exports = fx.Exports
+	x.idents = fx.Idents
+	x.opts = fx.Opts
+	if fx.Fulltext {
+		x.fset = token.NewFileSet()
+		decode := func(x interface{}) error {
+			return gob.NewDecoder(r).Decode(x)
+		}
+		if err := x.fset.Read(decode); err != nil {
+			return n, err
+		}
+		x.suffixes = new(suffixarray.Index)
+		if err := x.suffixes.Read(r); err != nil {
+			return n, err
+		}
+	}
+	return n, nil
+}
+
+// Stats returns index statistics.
+func (x *Index) Stats() Statistics {
+	return x.stats
+}
+
+// ImportCount returns a map from import paths to how many times they were seen.
+func (x *Index) ImportCount() map[string]int {
+	return x.importCount
+}
+
+// PackagePath returns a map from short package name to a set
+// of full package path names that use that short package name.
+func (x *Index) PackagePath() map[string]map[string]bool {
+	return x.packagePath
+}
+
+// Exports returns a map from full package path to exported
+// symbol name to its type.
+func (x *Index) Exports() map[string]map[string]SpotKind {
+	return x.exports
+}
+
+// Idents returns a map from identifier type to exported
+// symbol name to the list of identifiers matching that name.
+func (x *Index) Idents() map[SpotKind]map[string][]Ident {
+	return x.idents
+}
+
+func (x *Index) lookupWord(w string) (match *LookupResult, alt *AltWords) {
+	match = x.words[w]
+	alt = x.alts[canonical(w)]
+	// remove current spelling from alternatives
+	// (if there is no match, the alternatives do
+	// not contain the current spelling)
+	if match != nil && alt != nil {
+		alt = alt.filter(w)
+	}
+	return
+}
+
+// isIdentifier reports whether s is a Go identifier.
+func isIdentifier(s string) bool {
+	for i, ch := range s {
+		if unicode.IsLetter(ch) || ch == '_' || i > 0 && unicode.IsDigit(ch) {
+			continue
+		}
+		return false
+	}
+	return len(s) > 0
+}
+
+// For a given query, which is either a single identifier or a qualified
+// identifier, Lookup returns a SearchResult containing packages, a LookupResult, a
+// list of alternative spellings, and identifiers, if any. Any and all results
+// may be nil.  If the query syntax is wrong, an error is reported.
+func (x *Index) Lookup(query string) (*SearchResult, error) {
+	ss := strings.Split(query, ".")
+
+	// check query syntax
+	for _, s := range ss {
+		if !isIdentifier(s) {
+			return nil, errors.New("all query parts must be identifiers")
+		}
+	}
+	rslt := &SearchResult{
+		Query:  query,
+		Idents: make(map[SpotKind][]Ident, 5),
+	}
+	// handle simple and qualified identifiers
+	switch len(ss) {
+	case 1:
+		ident := ss[0]
+		rslt.Hit, rslt.Alt = x.lookupWord(ident)
+		if rslt.Hit != nil {
+			// found a match - filter packages with same name
+			// for the list of packages called ident, if any
+			rslt.Pak = rslt.Hit.Others.filter(ident)
+		}
+		for k, v := range x.idents {
+			const rsltLimit = 50
+			ids := byImportCount{v[ident], x.importCount}
+			rslt.Idents[k] = ids.top(rsltLimit)
+		}
+
+	case 2:
+		pakname, ident := ss[0], ss[1]
+		rslt.Hit, rslt.Alt = x.lookupWord(ident)
+		if rslt.Hit != nil {
+			// found a match - filter by package name
+			// (no paks - package names are not qualified)
+			decls := rslt.Hit.Decls.filter(pakname)
+			others := rslt.Hit.Others.filter(pakname)
+			rslt.Hit = &LookupResult{decls, others}
+		}
+		for k, v := range x.idents {
+			ids := byImportCount{v[ident], x.importCount}
+			rslt.Idents[k] = ids.filter(pakname)
+		}
+
+	default:
+		return nil, errors.New("query is not a (qualified) identifier")
+	}
+
+	return rslt, nil
+}
+
+func (x *Index) Snippet(i int) *Snippet {
+	// handle illegal snippet indices gracefully
+	if 0 <= i && i < len(x.snippets) {
+		return x.snippets[i]
+	}
+	return nil
+}
+
+type positionList []struct {
+	filename string
+	line     int
+}
+
+func (list positionList) Len() int           { return len(list) }
+func (list positionList) Less(i, j int) bool { return list[i].filename < list[j].filename }
+func (list positionList) Swap(i, j int)      { list[i], list[j] = list[j], list[i] }
+
+// unique returns the list sorted and with duplicate entries removed
+func unique(list []int) []int {
+	sort.Ints(list)
+	var last int
+	i := 0
+	for _, x := range list {
+		if i == 0 || x != last {
+			last = x
+			list[i] = x
+			i++
+		}
+	}
+	return list[0:i]
+}
+
+// A FileLines value specifies a file and line numbers within that file.
+type FileLines struct {
+	Filename string
+	Lines    []int
+}
+
+// LookupRegexp returns the number of matches and the matches where a regular
+// expression r is found in the full text index. At most n matches are
+// returned (thus found <= n).
+//
+func (x *Index) LookupRegexp(r *regexp.Regexp, n int) (found int, result []FileLines) {
+	if x.suffixes == nil || n <= 0 {
+		return
+	}
+	// n > 0
+
+	var list positionList
+	// FindAllIndex may returns matches that span across file boundaries.
+	// Such matches are unlikely, buf after eliminating them we may end up
+	// with fewer than n matches. If we don't have enough at the end, redo
+	// the search with an increased value n1, but only if FindAllIndex
+	// returned all the requested matches in the first place (if it
+	// returned fewer than that there cannot be more).
+	for n1 := n; found < n; n1 += n - found {
+		found = 0
+		matches := x.suffixes.FindAllIndex(r, n1)
+		// compute files, exclude matches that span file boundaries,
+		// and map offsets to file-local offsets
+		list = make(positionList, len(matches))
+		for _, m := range matches {
+			// by construction, an offset corresponds to the Pos value
+			// for the file set - use it to get the file and line
+			p := token.Pos(m[0])
+			if file := x.fset.File(p); file != nil {
+				if base := file.Base(); base <= m[1] && m[1] <= base+file.Size() {
+					// match [m[0], m[1]) is within the file boundaries
+					list[found].filename = file.Name()
+					list[found].line = file.Line(p)
+					found++
+				}
+			}
+		}
+		if found == n || len(matches) < n1 {
+			// found all matches or there's no chance to find more
+			break
+		}
+	}
+	list = list[0:found]
+	sort.Sort(list) // sort by filename
+
+	// collect matches belonging to the same file
+	var last string
+	var lines []int
+	addLines := func() {
+		if len(lines) > 0 {
+			// remove duplicate lines
+			result = append(result, FileLines{last, unique(lines)})
+			lines = nil
+		}
+	}
+	for _, m := range list {
+		if m.filename != last {
+			addLines()
+			last = m.filename
+		}
+		lines = append(lines, m.line)
+	}
+	addLines()
+
+	return
+}
+
+// InvalidateIndex should be called whenever any of the file systems
+// under godoc's observation change so that the indexer is kicked on.
+func (c *Corpus) invalidateIndex() {
+	c.fsModified.Set(nil)
+	c.refreshMetadata()
+}
+
+// indexUpToDate() returns true if the search index is not older
+// than any of the file systems under godoc's observation.
+//
+func (c *Corpus) indexUpToDate() bool {
+	_, fsTime := c.fsModified.Get()
+	_, siTime := c.searchIndex.Get()
+	return !fsTime.After(siTime)
+}
+
+// feedDirnames feeds the directory names of all directories
+// under the file system given by root to channel c.
+//
+func (c *Corpus) feedDirnames(ch chan<- string) {
+	if dir, _ := c.fsTree.Get(); dir != nil {
+		for d := range dir.(*Directory).iter(false) {
+			ch <- d.Path
+		}
+	}
+}
+
+// fsDirnames() returns a channel sending all directory names
+// of all the file systems under godoc's observation.
+//
+func (c *Corpus) fsDirnames() <-chan string {
+	ch := make(chan string, 256) // buffered for fewer context switches
+	go func() {
+		c.feedDirnames(ch)
+		close(ch)
+	}()
+	return ch
+}
+
+// CompatibleWith reports whether the Index x is compatible with the corpus
+// indexing options set in c.
+func (x *Index) CompatibleWith(c *Corpus) bool {
+	return x.opts.Docs == c.IndexDocs &&
+		x.opts.GoCode == c.IndexGoCode &&
+		x.opts.FullText == c.IndexFullText &&
+		x.opts.MaxResults == c.MaxResults
+}
+
+func (c *Corpus) readIndex(filenames string) error {
+	matches, err := filepath.Glob(filenames)
+	if err != nil {
+		return err
+	} else if matches == nil {
+		return fmt.Errorf("no index files match %q", filenames)
+	}
+	sort.Strings(matches) // make sure files are in the right order
+	files := make([]io.Reader, 0, len(matches))
+	for _, filename := range matches {
+		f, err := os.Open(filename)
+		if err != nil {
+			return err
+		}
+		defer f.Close()
+		files = append(files, f)
+	}
+	return c.ReadIndexFrom(io.MultiReader(files...))
+}
+
+// ReadIndexFrom sets the current index from the serialized version found in r.
+func (c *Corpus) ReadIndexFrom(r io.Reader) error {
+	x := new(Index)
+	if _, err := x.ReadFrom(r); err != nil {
+		return err
+	}
+	if !x.CompatibleWith(c) {
+		return fmt.Errorf("index file options are incompatible: %v", x.opts)
+	}
+	c.searchIndex.Set(x)
+	return nil
+}
+
+func (c *Corpus) UpdateIndex() {
+	if c.Verbose {
+		log.Printf("updating index...")
+	}
+	start := time.Now()
+	index := c.NewIndex()
+	stop := time.Now()
+	c.searchIndex.Set(index)
+	if c.Verbose {
+		secs := stop.Sub(start).Seconds()
+		stats := index.Stats()
+		log.Printf("index updated (%gs, %d bytes of source, %d files, %d lines, %d unique words, %d spots)",
+			secs, stats.Bytes, stats.Files, stats.Lines, stats.Words, stats.Spots)
+	}
+	memstats := new(runtime.MemStats)
+	runtime.ReadMemStats(memstats)
+	if c.Verbose {
+		log.Printf("before GC: bytes = %d footprint = %d", memstats.HeapAlloc, memstats.Sys)
+	}
+	runtime.GC()
+	runtime.ReadMemStats(memstats)
+	if c.Verbose {
+		log.Printf("after  GC: bytes = %d footprint = %d", memstats.HeapAlloc, memstats.Sys)
+	}
+}
+
+// RunIndexer runs forever, indexing.
+func (c *Corpus) RunIndexer() {
+	// initialize the index from disk if possible
+	if c.IndexFiles != "" {
+		c.initFSTree()
+		if err := c.readIndex(c.IndexFiles); err != nil {
+			log.Printf("error reading index from file %s: %v", c.IndexFiles, err)
+		}
+		return
+	}
+
+	// Repeatedly update the package directory tree and index.
+	// TODO(bgarcia): Use fsnotify to only update when notified of a filesystem change.
+	for {
+		c.initFSTree()
+		c.UpdateIndex()
+		if c.IndexInterval < 0 {
+			return
+		}
+		delay := 5 * time.Minute // by default, reindex every 5 minutes
+		if c.IndexInterval > 0 {
+			delay = c.IndexInterval
+		}
+		time.Sleep(delay)
+	}
+}
+
+type countingWriter struct {
+	n *int64
+	w io.Writer
+}
+
+func (c countingWriter) Write(p []byte) (n int, err error) {
+	n, err = c.w.Write(p)
+	*c.n += int64(n)
+	return
+}
+
+type byteReader interface {
+	io.Reader
+	io.ByteReader
+}
+
+type countingReader struct {
+	n *int64
+	r byteReader
+}
+
+func (c countingReader) Read(p []byte) (n int, err error) {
+	n, err = c.r.Read(p)
+	*c.n += int64(n)
+	return
+}
+
+func (c countingReader) ReadByte() (b byte, err error) {
+	b, err = c.r.ReadByte()
+	*c.n += 1
+	return
+}
diff --git a/third_party/go.tools/godoc/index_test.go b/third_party/go.tools/godoc/index_test.go
new file mode 100644
index 0000000..9774c33
--- /dev/null
+++ b/third_party/go.tools/godoc/index_test.go
@@ -0,0 +1,323 @@
+// Copyright 2013 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 godoc
+
+import (
+	"bytes"
+	"reflect"
+	"sort"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs/mapfs"
+)
+
+func newCorpus(t *testing.T) *Corpus {
+	c := NewCorpus(mapfs.New(map[string]string{
+		"src/foo/foo.go": `// Package foo is an example.
+package foo
+
+import "bar"
+
+const Pi = 3.1415
+
+var Foos []Foo
+
+// Foo is stuff.
+type Foo struct{}
+
+func New() *Foo {
+   return new(Foo)
+}
+`,
+		"src/bar/bar.go": `// Package bar is another example to test races.
+package bar
+`,
+		"src/other/bar/bar.go": `// Package bar is another bar package.
+package bar
+func X() {}
+`,
+		"src/skip/skip.go": `// Package skip should be skipped.
+package skip
+func Skip() {}
+`,
+		"src/bar/readme.txt": `Whitelisted text file.
+`,
+		"src/bar/baz.zzz": `Text file not whitelisted.
+`,
+	}))
+	c.IndexEnabled = true
+	c.IndexDirectory = func(dir string) bool {
+		return !strings.Contains(dir, "skip")
+	}
+
+	if err := c.Init(); err != nil {
+		t.Fatal(err)
+	}
+	return c
+}
+
+func TestIndex(t *testing.T) {
+	for _, docs := range []bool{true, false} {
+		for _, goCode := range []bool{true, false} {
+			for _, fullText := range []bool{true, false} {
+				c := newCorpus(t)
+				c.IndexDocs = docs
+				c.IndexGoCode = goCode
+				c.IndexFullText = fullText
+				c.UpdateIndex()
+				ix, _ := c.CurrentIndex()
+				if ix == nil {
+					t.Fatal("no index")
+				}
+				t.Logf("docs, goCode, fullText = %v,%v,%v", docs, goCode, fullText)
+				testIndex(t, c, ix)
+			}
+		}
+	}
+}
+
+func TestIndexWriteRead(t *testing.T) {
+	type key struct {
+		docs, goCode, fullText bool
+	}
+	type val struct {
+		buf *bytes.Buffer
+		c   *Corpus
+	}
+	m := map[key]val{}
+
+	for _, docs := range []bool{true, false} {
+		for _, goCode := range []bool{true, false} {
+			for _, fullText := range []bool{true, false} {
+				k := key{docs, goCode, fullText}
+				c := newCorpus(t)
+				c.IndexDocs = docs
+				c.IndexGoCode = goCode
+				c.IndexFullText = fullText
+				c.UpdateIndex()
+				ix, _ := c.CurrentIndex()
+				if ix == nil {
+					t.Fatal("no index")
+				}
+				var buf bytes.Buffer
+				nw, err := ix.WriteTo(&buf)
+				if err != nil {
+					t.Fatalf("Index.WriteTo: %v", err)
+				}
+				m[k] = val{bytes.NewBuffer(buf.Bytes()), c}
+				ix2 := new(Index)
+				nr, err := ix2.ReadFrom(&buf)
+				if err != nil {
+					t.Fatalf("Index.ReadFrom: %v", err)
+				}
+				if nr != nw {
+					t.Errorf("Wrote %d bytes to index but read %d", nw, nr)
+				}
+				testIndex(t, c, ix)
+			}
+		}
+	}
+	// Test CompatibleWith
+	for k1, v1 := range m {
+		ix := new(Index)
+		if _, err := ix.ReadFrom(v1.buf); err != nil {
+			t.Fatalf("Index.ReadFrom: %v", err)
+		}
+		for k2, v2 := range m {
+			if got, want := ix.CompatibleWith(v2.c), k1 == k2; got != want {
+				t.Errorf("CompatibleWith = %v; want %v for %v, %v", got, want, k1, k2)
+			}
+		}
+	}
+}
+
+func testIndex(t *testing.T, c *Corpus, ix *Index) {
+	if _, ok := ix.words["Skip"]; ok {
+		t.Errorf("the word Skip was found; expected it to be skipped")
+	}
+	checkStats(t, c, ix)
+	checkImportCount(t, c, ix)
+	checkPackagePath(t, c, ix)
+	checkExports(t, c, ix)
+	checkIdents(t, c, ix)
+}
+
+// checkStats checks the Index's statistics.
+// Some statistics are only set when we're indexing Go code.
+func checkStats(t *testing.T, c *Corpus, ix *Index) {
+	want := Statistics{}
+	if c.IndexFullText {
+		want.Bytes = 314
+		want.Files = 4
+		want.Lines = 21
+	} else if c.IndexDocs || c.IndexGoCode {
+		want.Bytes = 291
+		want.Files = 3
+		want.Lines = 20
+	}
+	if c.IndexGoCode {
+		want.Words = 8
+		want.Spots = 12
+	}
+	if got := ix.Stats(); !reflect.DeepEqual(got, want) {
+		t.Errorf("Stats = %#v; want %#v", got, want)
+	}
+}
+
+// checkImportCount checks the Index's import count map.
+// It is only set when we're indexing Go code.
+func checkImportCount(t *testing.T, c *Corpus, ix *Index) {
+	want := map[string]int{}
+	if c.IndexGoCode {
+		want = map[string]int{
+			"bar": 1,
+		}
+	}
+	if got := ix.ImportCount(); !reflect.DeepEqual(got, want) {
+		t.Errorf("ImportCount = %v; want %v", got, want)
+	}
+}
+
+// checkPackagePath checks the Index's package path map.
+// It is set if at least one of the indexing options is enabled.
+func checkPackagePath(t *testing.T, c *Corpus, ix *Index) {
+	want := map[string]map[string]bool{}
+	if c.IndexDocs || c.IndexGoCode || c.IndexFullText {
+		want = map[string]map[string]bool{
+			"foo": map[string]bool{
+				"foo": true,
+			},
+			"bar": map[string]bool{
+				"bar":       true,
+				"other/bar": true,
+			},
+		}
+	}
+	if got := ix.PackagePath(); !reflect.DeepEqual(got, want) {
+		t.Errorf("PackagePath = %v; want %v", got, want)
+	}
+}
+
+// checkExports checks the Index's exports map.
+// It is only set when we're indexing Go code.
+func checkExports(t *testing.T, c *Corpus, ix *Index) {
+	want := map[string]map[string]SpotKind{}
+	if c.IndexGoCode {
+		want = map[string]map[string]SpotKind{
+			"foo": map[string]SpotKind{
+				"Pi":   ConstDecl,
+				"Foos": VarDecl,
+				"Foo":  TypeDecl,
+				"New":  FuncDecl,
+			},
+			"other/bar": map[string]SpotKind{
+				"X": FuncDecl,
+			},
+		}
+	}
+	if got := ix.Exports(); !reflect.DeepEqual(got, want) {
+		t.Errorf("Exports = %v; want %v", got, want)
+	}
+}
+
+// checkIdents checks the Index's indents map.
+// It is only set when we're indexing documentation.
+func checkIdents(t *testing.T, c *Corpus, ix *Index) {
+	want := map[SpotKind]map[string][]Ident{}
+	if c.IndexDocs {
+		want = map[SpotKind]map[string][]Ident{
+			PackageClause: map[string][]Ident{
+				"bar": []Ident{
+					{"bar", "bar", "bar", "Package bar is another example to test races."},
+					{"other/bar", "bar", "bar", "Package bar is another bar package."},
+				},
+				"foo":   []Ident{{"foo", "foo", "foo", "Package foo is an example."}},
+				"other": []Ident{{"other/bar", "bar", "bar", "Package bar is another bar package."}},
+			},
+			ConstDecl: map[string][]Ident{
+				"Pi": []Ident{{"foo", "foo", "Pi", ""}},
+			},
+			VarDecl: map[string][]Ident{
+				"Foos": []Ident{{"foo", "foo", "Foos", ""}},
+			},
+			TypeDecl: map[string][]Ident{
+				"Foo": []Ident{{"foo", "foo", "Foo", "Foo is stuff."}},
+			},
+			FuncDecl: map[string][]Ident{
+				"New": []Ident{{"foo", "foo", "New", ""}},
+				"X":   []Ident{{"other/bar", "bar", "X", ""}},
+			},
+		}
+	}
+	if got := ix.Idents(); !reflect.DeepEqual(got, want) {
+		t.Errorf("Idents = %v; want %v", got, want)
+	}
+}
+
+func TestIdentResultSort(t *testing.T) {
+	ic := map[string]int{
+		"/a/b/pkg1": 10,
+		"/a/b/pkg2": 2,
+		"/b/d/pkg3": 20,
+	}
+	for _, tc := range []struct {
+		ir  []Ident
+		exp []Ident
+	}{
+		{
+			ir: []Ident{
+				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
+				{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
+				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
+			},
+			exp: []Ident{
+				{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
+				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
+				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
+			},
+		},
+		{
+			ir: []Ident{
+				{"/a/a/pkg1", "pkg1", "MyFunc1", ""},
+				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
+			},
+			exp: []Ident{
+				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
+				{"/a/a/pkg1", "pkg1", "MyFunc1", ""},
+			},
+		},
+	} {
+		if sort.Sort(byImportCount{tc.ir, ic}); !reflect.DeepEqual(tc.ir, tc.exp) {
+			t.Errorf("got: %v, want %v", tc.ir, tc.exp)
+		}
+	}
+}
+
+func TestIdentFilter(t *testing.T) {
+	ic := map[string]int{}
+	for _, tc := range []struct {
+		ir  []Ident
+		pak string
+		exp []Ident
+	}{
+		{
+			ir: []Ident{
+				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
+				{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
+				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
+			},
+			pak: "pkg2",
+			exp: []Ident{
+				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
+			},
+		},
+	} {
+		res := byImportCount{tc.ir, ic}.filter(tc.pak)
+		if !reflect.DeepEqual(res, tc.exp) {
+			t.Errorf("got: %v, want %v", res, tc.exp)
+		}
+	}
+}
diff --git a/third_party/go.tools/godoc/linkify.go b/third_party/go.tools/godoc/linkify.go
new file mode 100644
index 0000000..0a8fb47
--- /dev/null
+++ b/third_party/go.tools/godoc/linkify.go
@@ -0,0 +1,234 @@
+// Copyright 2013 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.
+
+// This file implements LinkifyText which introduces
+// links for identifiers pointing to their declarations.
+// The approach does not cover all cases because godoc
+// doesn't have complete type information, but it's
+// reasonably good for browsing.
+
+package godoc
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"strconv"
+)
+
+// LinkifyText HTML-escapes source text and writes it to w.
+// Identifiers that are in a "use" position (i.e., that are
+// not being declared), are wrapped with HTML links pointing
+// to the respective declaration, if possible. Comments are
+// formatted the same way as with FormatText.
+//
+func LinkifyText(w io.Writer, text []byte, n ast.Node) {
+	links := linksFor(n)
+
+	i := 0     // links index
+	prev := "" // prev HTML tag
+	linkWriter := func(w io.Writer, _ int, start bool) {
+		// end tag
+		if !start {
+			if prev != "" {
+				fmt.Fprintf(w, `</%s>`, prev)
+				prev = ""
+			}
+			return
+		}
+
+		// start tag
+		prev = ""
+		if i < len(links) {
+			switch info := links[i]; {
+			case info.path != "" && info.name == "":
+				// package path
+				fmt.Fprintf(w, `<a href="/pkg/%s/">`, info.path)
+				prev = "a"
+			case info.path != "" && info.name != "":
+				// qualified identifier
+				fmt.Fprintf(w, `<a href="/pkg/%s/#%s">`, info.path, info.name)
+				prev = "a"
+			case info.path == "" && info.name != "":
+				// local identifier
+				if info.mode == identVal {
+					fmt.Fprintf(w, `<span id="%s">`, info.name)
+					prev = "span"
+				} else if ast.IsExported(info.name) {
+					fmt.Fprintf(w, `<a href="#%s">`, info.name)
+					prev = "a"
+				}
+			}
+			i++
+		}
+	}
+
+	idents := tokenSelection(text, token.IDENT)
+	comments := tokenSelection(text, token.COMMENT)
+	FormatSelections(w, text, linkWriter, idents, selectionTag, comments)
+}
+
+// A link describes the (HTML) link information for an identifier.
+// The zero value of a link represents "no link".
+//
+type link struct {
+	mode       identMode
+	path, name string // package path, identifier name
+}
+
+// linksFor returns the list of links for the identifiers used
+// by node in the same order as they appear in the source.
+//
+func linksFor(node ast.Node) (list []link) {
+	modes := identModesFor(node)
+
+	// NOTE: We are expecting ast.Inspect to call the
+	//       callback function in source text order.
+	ast.Inspect(node, func(node ast.Node) bool {
+		switch n := node.(type) {
+		case *ast.Ident:
+			m := modes[n]
+			info := link{mode: m}
+			switch m {
+			case identUse:
+				if n.Obj == nil && predeclared[n.Name] {
+					info.path = builtinPkgPath
+				}
+				info.name = n.Name
+			case identDef:
+				// any declaration expect const or var - empty link
+			case identVal:
+				// const or var declaration
+				info.name = n.Name
+			}
+			list = append(list, info)
+			return false
+		case *ast.SelectorExpr:
+			// Detect qualified identifiers of the form pkg.ident.
+			// If anything fails we return true and collect individual
+			// identifiers instead.
+			if x, _ := n.X.(*ast.Ident); x != nil {
+				// x must be a package for a qualified identifier
+				if obj := x.Obj; obj != nil && obj.Kind == ast.Pkg {
+					if spec, _ := obj.Decl.(*ast.ImportSpec); spec != nil {
+						// spec.Path.Value is the import path
+						if path, err := strconv.Unquote(spec.Path.Value); err == nil {
+							// Register two links, one for the package
+							// and one for the qualified identifier.
+							info := link{path: path}
+							list = append(list, info)
+							info.name = n.Sel.Name
+							list = append(list, info)
+							return false
+						}
+					}
+				}
+			}
+		}
+		return true
+	})
+
+	return
+}
+
+// The identMode describes how an identifier is "used" at its source location.
+type identMode int
+
+const (
+	identUse identMode = iota // identifier is used (must be zero value for identMode)
+	identDef                  // identifier is defined
+	identVal                  // identifier is defined in a const or var declaration
+)
+
+// identModesFor returns a map providing the identMode for each identifier used by node.
+func identModesFor(node ast.Node) map[*ast.Ident]identMode {
+	m := make(map[*ast.Ident]identMode)
+
+	ast.Inspect(node, func(node ast.Node) bool {
+		switch n := node.(type) {
+		case *ast.Field:
+			for _, n := range n.Names {
+				m[n] = identDef
+			}
+		case *ast.ImportSpec:
+			if name := n.Name; name != nil {
+				m[name] = identDef
+			}
+		case *ast.ValueSpec:
+			for _, n := range n.Names {
+				m[n] = identVal
+			}
+		case *ast.TypeSpec:
+			m[n.Name] = identDef
+		case *ast.FuncDecl:
+			m[n.Name] = identDef
+		case *ast.AssignStmt:
+			// Short variable declarations only show up if we apply
+			// this code to all source code (as opposed to exported
+			// declarations only).
+			if n.Tok == token.DEFINE {
+				// Some of the lhs variables may be re-declared,
+				// so technically they are not defs. We don't
+				// care for now.
+				for _, x := range n.Lhs {
+					// Each lhs expression should be an
+					// ident, but we are conservative and check.
+					if n, _ := x.(*ast.Ident); n != nil {
+						m[n] = identVal
+					}
+				}
+			}
+		}
+		return true
+	})
+
+	return m
+}
+
+// The predeclared map represents the set of all predeclared identifiers.
+// TODO(gri) This information is also encoded in similar maps in go/doc,
+//           but not exported. Consider exporting an accessor and using
+//           it instead.
+var predeclared = map[string]bool{
+	"bool":       true,
+	"byte":       true,
+	"complex64":  true,
+	"complex128": true,
+	"error":      true,
+	"float32":    true,
+	"float64":    true,
+	"int":        true,
+	"int8":       true,
+	"int16":      true,
+	"int32":      true,
+	"int64":      true,
+	"rune":       true,
+	"string":     true,
+	"uint":       true,
+	"uint8":      true,
+	"uint16":     true,
+	"uint32":     true,
+	"uint64":     true,
+	"uintptr":    true,
+	"true":       true,
+	"false":      true,
+	"iota":       true,
+	"nil":        true,
+	"append":     true,
+	"cap":        true,
+	"close":      true,
+	"complex":    true,
+	"copy":       true,
+	"delete":     true,
+	"imag":       true,
+	"len":        true,
+	"make":       true,
+	"new":        true,
+	"panic":      true,
+	"print":      true,
+	"println":    true,
+	"real":       true,
+	"recover":    true,
+}
diff --git a/third_party/go.tools/godoc/meta.go b/third_party/go.tools/godoc/meta.go
new file mode 100644
index 0000000..b064594
--- /dev/null
+++ b/third_party/go.tools/godoc/meta.go
@@ -0,0 +1,144 @@
+// 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 godoc
+
+import (
+	"bytes"
+	"encoding/json"
+	"log"
+	pathpkg "path"
+	"strings"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+var (
+	doctype   = []byte("<!DOCTYPE ")
+	jsonStart = []byte("<!--{")
+	jsonEnd   = []byte("}-->")
+)
+
+// ----------------------------------------------------------------------------
+// Documentation Metadata
+
+// TODO(adg): why are some exported and some aren't? -brad
+type Metadata struct {
+	Title    string
+	Subtitle string
+	Template bool   // execute as template
+	Path     string // canonical path for this page
+	filePath string // filesystem path relative to goroot
+}
+
+func (m *Metadata) FilePath() string { return m.filePath }
+
+// extractMetadata extracts the Metadata from a byte slice.
+// It returns the Metadata value and the remaining data.
+// If no metadata is present the original byte slice is returned.
+//
+func extractMetadata(b []byte) (meta Metadata, tail []byte, err error) {
+	tail = b
+	if !bytes.HasPrefix(b, jsonStart) {
+		return
+	}
+	end := bytes.Index(b, jsonEnd)
+	if end < 0 {
+		return
+	}
+	b = b[len(jsonStart)-1 : end+1] // drop leading <!-- and include trailing }
+	if err = json.Unmarshal(b, &meta); err != nil {
+		return
+	}
+	tail = tail[end+len(jsonEnd):]
+	return
+}
+
+// UpdateMetadata scans $GOROOT/doc for HTML files, reads their metadata,
+// and updates the DocMetadata map.
+func (c *Corpus) updateMetadata() {
+	metadata := make(map[string]*Metadata)
+	var scan func(string) // scan is recursive
+	scan = func(dir string) {
+		fis, err := c.fs.ReadDir(dir)
+		if err != nil {
+			log.Println("updateMetadata:", err)
+			return
+		}
+		for _, fi := range fis {
+			name := pathpkg.Join(dir, fi.Name())
+			if fi.IsDir() {
+				scan(name) // recurse
+				continue
+			}
+			if !strings.HasSuffix(name, ".html") {
+				continue
+			}
+			// Extract metadata from the file.
+			b, err := vfs.ReadFile(c.fs, name)
+			if err != nil {
+				log.Printf("updateMetadata %s: %v", name, err)
+				continue
+			}
+			meta, _, err := extractMetadata(b)
+			if err != nil {
+				log.Printf("updateMetadata: %s: %v", name, err)
+				continue
+			}
+			// Store relative filesystem path in Metadata.
+			meta.filePath = name
+			if meta.Path == "" {
+				// If no Path, canonical path is actual path.
+				meta.Path = meta.filePath
+			}
+			// Store under both paths.
+			metadata[meta.Path] = &meta
+			metadata[meta.filePath] = &meta
+		}
+	}
+	scan("/doc")
+	c.docMetadata.Set(metadata)
+}
+
+// MetadataFor returns the *Metadata for a given relative path or nil if none
+// exists.
+//
+func (c *Corpus) MetadataFor(relpath string) *Metadata {
+	if m, _ := c.docMetadata.Get(); m != nil {
+		meta := m.(map[string]*Metadata)
+		// If metadata for this relpath exists, return it.
+		if p := meta[relpath]; p != nil {
+			return p
+		}
+		// Try with or without trailing slash.
+		if strings.HasSuffix(relpath, "/") {
+			relpath = relpath[:len(relpath)-1]
+		} else {
+			relpath = relpath + "/"
+		}
+		return meta[relpath]
+	}
+	return nil
+}
+
+// refreshMetadata sends a signal to update DocMetadata. If a refresh is in
+// progress the metadata will be refreshed again afterward.
+//
+func (c *Corpus) refreshMetadata() {
+	select {
+	case c.refreshMetadataSignal <- true:
+	default:
+	}
+}
+
+// RefreshMetadataLoop runs forever, updating DocMetadata when the underlying
+// file system changes. It should be launched in a goroutine.
+func (c *Corpus) refreshMetadataLoop() {
+	for {
+		<-c.refreshMetadataSignal
+		c.updateMetadata()
+		time.Sleep(10 * time.Second) // at most once every 10 seconds
+	}
+}
diff --git a/third_party/go.tools/godoc/page.go b/third_party/go.tools/godoc/page.go
new file mode 100644
index 0000000..b296b27
--- /dev/null
+++ b/third_party/go.tools/godoc/page.go
@@ -0,0 +1,43 @@
+// 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 godoc
+
+import (
+	"net/http"
+	"runtime"
+)
+
+// Page describes the contents of the top-level godoc webpage.
+type Page struct {
+	Title    string
+	Tabtitle string
+	Subtitle string
+	Query    string
+	Body     []byte
+
+	// filled in by servePage
+	SearchBox  bool
+	Playground bool
+	Version    string
+}
+
+func (p *Presentation) ServePage(w http.ResponseWriter, page Page) {
+	if page.Tabtitle == "" {
+		page.Tabtitle = page.Title
+	}
+	page.SearchBox = p.Corpus.IndexEnabled
+	page.Playground = p.ShowPlayground
+	page.Version = runtime.Version()
+	applyTemplateToResponseWriter(w, p.GodocHTML, page)
+}
+
+func (p *Presentation) ServeError(w http.ResponseWriter, r *http.Request, relpath string, err error) {
+	w.WriteHeader(http.StatusNotFound)
+	p.ServePage(w, Page{
+		Title:    "File " + relpath,
+		Subtitle: relpath,
+		Body:     applyTemplate(p.ErrorHTML, "errorHTML", err), // err may contain an absolute path!
+	})
+}
diff --git a/third_party/go.tools/godoc/parser.go b/third_party/go.tools/godoc/parser.go
new file mode 100644
index 0000000..3213c9a
--- /dev/null
+++ b/third_party/go.tools/godoc/parser.go
@@ -0,0 +1,74 @@
+// 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.
+
+// This file contains support functions for parsing .go files
+// accessed via godoc's file system fs.
+
+package godoc
+
+import (
+	"bytes"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	pathpkg "path"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+var linePrefix = []byte("//line ")
+
+// This function replaces source lines starting with "//line " with a blank line.
+// It does this irrespective of whether the line is truly a line comment or not;
+// e.g., the line may be inside a string, or a /*-style comment; however that is
+// rather unlikely (proper testing would require a full Go scan which we want to
+// avoid for performance).
+func replaceLinePrefixCommentsWithBlankLine(src []byte) {
+	for {
+		i := bytes.Index(src, linePrefix)
+		if i < 0 {
+			break // we're done
+		}
+		// 0 <= i && i+len(linePrefix) <= len(src)
+		if i == 0 || src[i-1] == '\n' {
+			// at beginning of line: blank out line
+			for i < len(src) && src[i] != '\n' {
+				src[i] = ' '
+				i++
+			}
+		} else {
+			// not at beginning of line: skip over prefix
+			i += len(linePrefix)
+		}
+		// i <= len(src)
+		src = src[i:]
+	}
+}
+
+func (c *Corpus) parseFile(fset *token.FileSet, filename string, mode parser.Mode) (*ast.File, error) {
+	src, err := vfs.ReadFile(c.fs, filename)
+	if err != nil {
+		return nil, err
+	}
+
+	// Temporary ad-hoc fix for issue 5247.
+	// TODO(gri) Remove this in favor of a better fix, eventually (see issue 7702).
+	replaceLinePrefixCommentsWithBlankLine(src)
+
+	return parser.ParseFile(fset, filename, src, mode)
+}
+
+func (c *Corpus) parseFiles(fset *token.FileSet, relpath string, abspath string, localnames []string) (map[string]*ast.File, error) {
+	files := make(map[string]*ast.File)
+	for _, f := range localnames {
+		absname := pathpkg.Join(abspath, f)
+		file, err := c.parseFile(fset, absname, parser.ParseComments)
+		if err != nil {
+			return nil, err
+		}
+		files[pathpkg.Join(relpath, f)] = file
+	}
+
+	return files, nil
+}
diff --git a/third_party/go.tools/godoc/pres.go b/third_party/go.tools/godoc/pres.go
new file mode 100644
index 0000000..aef85d6
--- /dev/null
+++ b/third_party/go.tools/godoc/pres.go
@@ -0,0 +1,165 @@
+// Copyright 2013 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 godoc
+
+import (
+	"net/http"
+	"regexp"
+	"sync"
+	"text/template"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs/httpfs"
+)
+
+// SearchResultFunc functions return an HTML body for displaying search results.
+type SearchResultFunc func(p *Presentation, result SearchResult) []byte
+
+// Presentation generates output from a corpus.
+type Presentation struct {
+	Corpus *Corpus
+
+	mux        *http.ServeMux
+	fileServer http.Handler
+	cmdHandler handlerServer
+	pkgHandler handlerServer
+
+	CallGraphHTML,
+	DirlistHTML,
+	ErrorHTML,
+	ExampleHTML,
+	GodocHTML,
+	ImplementsHTML,
+	MethodSetHTML,
+	PackageHTML,
+	PackageText,
+	SearchHTML,
+	SearchDocHTML,
+	SearchCodeHTML,
+	SearchTxtHTML,
+	SearchText,
+	SearchDescXML *template.Template
+
+	// TabWidth optionally specifies the tab width.
+	TabWidth int
+
+	ShowTimestamps bool
+	ShowPlayground bool
+	ShowExamples   bool
+	DeclLinks      bool
+
+	// SrcMode outputs source code instead of documentation in command-line mode.
+	SrcMode bool
+	// HTMLMode outputs HTML instead of plain text in command-line mode.
+	HTMLMode bool
+
+	// NotesRx optionally specifies a regexp to match
+	// notes to render in the output.
+	NotesRx *regexp.Regexp
+
+	// AdjustPageInfoMode optionally specifies a function to
+	// modify the PageInfoMode of a request. The default chosen
+	// value is provided.
+	AdjustPageInfoMode func(req *http.Request, mode PageInfoMode) PageInfoMode
+
+	// URLForSrc optionally specifies a function that takes a source file and
+	// returns a URL for it.
+	// The source file argument has the form /src/<path>/<filename>.
+	URLForSrc func(src string) string
+
+	// URLForSrcPos optionally specifies a function to create a URL given a
+	// source file, a line from the source file (1-based), and low & high offset
+	// positions (0-based, bytes from beginning of file). Ideally, the returned
+	// URL will be for the specified line of the file, while the high & low
+	// positions will be used to highlight a section of the file.
+	// The source file argument has the form /src/<path>/<filename>.
+	URLForSrcPos func(src string, line, low, high int) string
+
+	// URLForSrcQuery optionally specifies a function to create a URL given a
+	// source file, a query string, and a line from the source file (1-based).
+	// The source file argument has the form /src/<path>/<filename>.
+	// The query argument will be escaped for the purposes of embedding in a URL
+	// query parameter.
+	// Ideally, the returned URL will be for the specified line of the file with
+	// the query string highlighted.
+	URLForSrcQuery func(src, query string, line int) string
+
+	// SearchResults optionally specifies a list of functions returning an HTML
+	// body for displaying search results.
+	SearchResults []SearchResultFunc
+
+	initFuncMapOnce sync.Once
+	funcMap         template.FuncMap
+	templateFuncs   template.FuncMap
+}
+
+// NewPresentation returns a new Presentation from a corpus.
+// It sets SearchResults to:
+// [SearchResultDoc SearchResultCode SearchResultTxt].
+func NewPresentation(c *Corpus) *Presentation {
+	if c == nil {
+		panic("nil Corpus")
+	}
+	p := &Presentation{
+		Corpus:     c,
+		mux:        http.NewServeMux(),
+		fileServer: http.FileServer(httpfs.New(c.fs)),
+
+		TabWidth:     4,
+		ShowExamples: true,
+		DeclLinks:    true,
+		SearchResults: []SearchResultFunc{
+			(*Presentation).SearchResultDoc,
+			(*Presentation).SearchResultCode,
+			(*Presentation).SearchResultTxt,
+		},
+	}
+	p.cmdHandler = handlerServer{
+		p:       p,
+		c:       c,
+		pattern: "/cmd/",
+		fsRoot:  "/src/cmd",
+	}
+	p.pkgHandler = handlerServer{
+		p:       p,
+		c:       c,
+		pattern: "/pkg/",
+		fsRoot:  "/src",
+		exclude: []string{"/src/cmd"},
+	}
+	p.cmdHandler.registerWithMux(p.mux)
+	p.pkgHandler.registerWithMux(p.mux)
+	p.mux.HandleFunc("/", p.ServeFile)
+	p.mux.HandleFunc("/search", p.HandleSearch)
+	p.mux.HandleFunc("/opensearch.xml", p.serveSearchDesc)
+	return p
+}
+
+func (p *Presentation) FileServer() http.Handler {
+	return p.fileServer
+}
+
+func (p *Presentation) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	p.mux.ServeHTTP(w, r)
+}
+
+func (p *Presentation) PkgFSRoot() string {
+	return p.pkgHandler.fsRoot
+}
+
+func (p *Presentation) CmdFSRoot() string {
+	return p.cmdHandler.fsRoot
+}
+
+// TODO(bradfitz): move this to be a method on Corpus. Just moving code around for now,
+// but this doesn't feel right.
+func (p *Presentation) GetPkgPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
+	return p.pkgHandler.GetPageInfo(abspath, relpath, mode)
+}
+
+// TODO(bradfitz): move this to be a method on Corpus. Just moving code around for now,
+// but this doesn't feel right.
+func (p *Presentation) GetCmdPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
+	return p.cmdHandler.GetPageInfo(abspath, relpath, mode)
+}
diff --git a/third_party/go.tools/godoc/redirect/redirect.go b/third_party/go.tools/godoc/redirect/redirect.go
new file mode 100644
index 0000000..29e3c4e
--- /dev/null
+++ b/third_party/go.tools/godoc/redirect/redirect.go
@@ -0,0 +1,166 @@
+// Copyright 2013 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 redirect provides hooks to register HTTP handlers that redirect old
+// godoc paths to their new equivalents and assist in accessing the issue
+// tracker, wiki, code review system, etc.
+package redirect
+
+import (
+	"net/http"
+	"regexp"
+)
+
+// Register registers HTTP handlers that redirect old godoc paths to their new
+// equivalents and assist in accessing the issue tracker, wiki, code review
+// system, etc. If mux is nil it uses http.DefaultServeMux.
+func Register(mux *http.ServeMux) {
+	if mux == nil {
+		mux = http.DefaultServeMux
+	}
+	handlePathRedirects(mux, pkgRedirects, "/pkg/")
+	handlePathRedirects(mux, cmdRedirects, "/cmd/")
+	for prefix, redirect := range prefixHelpers {
+		p := "/" + prefix + "/"
+		mux.Handle(p, PrefixHandler(p, redirect))
+	}
+	for path, redirect := range redirects {
+		mux.Handle(path, Handler(redirect))
+	}
+	// NB: /src/pkg (sans trailing slash) is the index of packages.
+	http.HandleFunc("/src/pkg/", srcPkgHandler)
+}
+
+func handlePathRedirects(mux *http.ServeMux, redirects map[string]string, prefix string) {
+	for source, target := range redirects {
+		h := Handler(prefix + target + "/")
+		p := prefix + source
+		mux.Handle(p, h)
+		mux.Handle(p+"/", h)
+	}
+}
+
+// Packages that were renamed between r60 and go1.
+var pkgRedirects = map[string]string{
+	"asn1":              "encoding/asn1",
+	"big":               "math/big",
+	"cmath":             "math/cmplx",
+	"csv":               "encoding/csv",
+	"exec":              "os/exec",
+	"exp/template/html": "html/template",
+	"gob":               "encoding/gob",
+	"http":              "net/http",
+	"http/cgi":          "net/http/cgi",
+	"http/fcgi":         "net/http/fcgi",
+	"http/httptest":     "net/http/httptest",
+	"http/pprof":        "net/http/pprof",
+	"json":              "encoding/json",
+	"mail":              "net/mail",
+	"rand":              "math/rand",
+	"rpc":               "net/rpc",
+	"rpc/jsonrpc":       "net/rpc/jsonrpc",
+	"scanner":           "text/scanner",
+	"smtp":              "net/smtp",
+	"tabwriter":         "text/tabwriter",
+	"template":          "text/template",
+	"template/parse":    "text/template/parse",
+	"url":               "net/url",
+	"utf16":             "unicode/utf16",
+	"utf8":              "unicode/utf8",
+	"xml":               "encoding/xml",
+}
+
+// Commands that were renamed between r60 and go1.
+var cmdRedirects = map[string]string{
+	"gofix":     "fix",
+	"goinstall": "go",
+	"gopack":    "pack",
+	"gotest":    "go",
+	"govet":     "vet",
+	"goyacc":    "yacc",
+}
+
+var redirects = map[string]string{
+	"/blog":       "/blog/",
+	"/build":      "http://build.golang.org",
+	"/change":     "https://code.google.com/p/go/source/list",
+	"/cl":         "https://gocodereview.appspot.com/",
+	"/cmd/godoc/": "http://godoc.org/golang.org/x/tools/cmd/godoc/",
+	"/cmd/vet/":   "http://godoc.org/golang.org/x/tools/cmd/vet/",
+	"/issue":      "https://code.google.com/p/go/issues",
+	"/issue/new":  "https://code.google.com/p/go/issues/entry",
+	"/issues":     "https://code.google.com/p/go/issues",
+	"/play":       "http://play.golang.org",
+
+	// In Go 1.2 the references page is part of /doc/.
+	"/ref": "/doc/#references",
+	// This next rule clobbers /ref/spec and /ref/mem.
+	// TODO(adg): figure out what to do here, if anything.
+	// "/ref/": "/doc/#references",
+
+	// Be nice to people who are looking in the wrong place.
+	"/doc/mem":  "/ref/mem",
+	"/doc/spec": "/ref/spec",
+
+	"/talks": "http://talks.golang.org",
+	"/tour":  "http://tour.golang.org",
+	"/wiki":  "https://code.google.com/p/go-wiki/w/list",
+
+	"/doc/articles/c_go_cgo.html":                    "/blog/c-go-cgo",
+	"/doc/articles/concurrency_patterns.html":        "/blog/go-concurrency-patterns-timing-out-and",
+	"/doc/articles/defer_panic_recover.html":         "/blog/defer-panic-and-recover",
+	"/doc/articles/error_handling.html":              "/blog/error-handling-and-go",
+	"/doc/articles/gobs_of_data.html":                "/blog/gobs-of-data",
+	"/doc/articles/godoc_documenting_go_code.html":   "/blog/godoc-documenting-go-code",
+	"/doc/articles/gos_declaration_syntax.html":      "/blog/gos-declaration-syntax",
+	"/doc/articles/image_draw.html":                  "/blog/go-imagedraw-package",
+	"/doc/articles/image_package.html":               "/blog/go-image-package",
+	"/doc/articles/json_and_go.html":                 "/blog/json-and-go",
+	"/doc/articles/json_rpc_tale_of_interfaces.html": "/blog/json-rpc-tale-of-interfaces",
+	"/doc/articles/laws_of_reflection.html":          "/blog/laws-of-reflection",
+	"/doc/articles/slices_usage_and_internals.html":  "/blog/go-slices-usage-and-internals",
+	"/doc/go_for_cpp_programmers.html":               "https://code.google.com/p/go-wiki/wiki/GoForCPPProgrammers",
+	"/doc/go_tutorial.html":                          "http://tour.golang.org/",
+}
+
+var prefixHelpers = map[string]string{
+	"change": "https://code.google.com/p/go/source/detail?r=",
+	"cl":     "https://codereview.appspot.com/",
+	"issue":  "https://code.google.com/p/go/issues/detail?id=",
+	"play":   "http://play.golang.org/",
+	"talks":  "http://talks.golang.org/",
+	"wiki":   "https://code.google.com/p/go-wiki/wiki/",
+}
+
+func Handler(target string) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		http.Redirect(w, r, target, http.StatusMovedPermanently)
+	})
+}
+
+var validId = regexp.MustCompile(`^[A-Za-z0-9-]*$`)
+
+func PrefixHandler(prefix, baseURL string) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if p := r.URL.Path; p == prefix {
+			// redirect /prefix/ to /prefix
+			http.Redirect(w, r, p[:len(p)-1], http.StatusFound)
+			return
+		}
+		id := r.URL.Path[len(prefix):]
+		if !validId.MatchString(id) {
+			http.Error(w, "Not found", http.StatusNotFound)
+			return
+		}
+		target := baseURL + id
+		http.Redirect(w, r, target, http.StatusFound)
+	})
+}
+
+// Redirect requests from the old "/src/pkg/foo" to the new "/src/foo".
+// See http://golang.org/s/go14nopkg
+func srcPkgHandler(w http.ResponseWriter, r *http.Request) {
+	r.URL.Path = "/src/" + r.URL.Path[len("/src/pkg/"):]
+	http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently)
+}
diff --git a/third_party/go.tools/godoc/search.go b/third_party/go.tools/godoc/search.go
new file mode 100644
index 0000000..e126330
--- /dev/null
+++ b/third_party/go.tools/godoc/search.go
@@ -0,0 +1,138 @@
+// 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 godoc
+
+import (
+	"bytes"
+	"fmt"
+	"net/http"
+	"regexp"
+	"strings"
+)
+
+type SearchResult struct {
+	Query string
+	Alert string // error or warning message
+
+	// identifier matches
+	Pak HitList       // packages matching Query
+	Hit *LookupResult // identifier matches of Query
+	Alt *AltWords     // alternative identifiers to look for
+
+	// textual matches
+	Found    int         // number of textual occurrences found
+	Textual  []FileLines // textual matches of Query
+	Complete bool        // true if all textual occurrences of Query are reported
+	Idents   map[SpotKind][]Ident
+}
+
+func (c *Corpus) Lookup(query string) SearchResult {
+	result := &SearchResult{Query: query}
+
+	index, timestamp := c.CurrentIndex()
+	if index != nil {
+		// identifier search
+		if r, err := index.Lookup(query); err == nil {
+			result = r
+		} else if err != nil && !c.IndexFullText {
+			// ignore the error if full text search is enabled
+			// since the query may be a valid regular expression
+			result.Alert = "Error in query string: " + err.Error()
+			return *result
+		}
+
+		// full text search
+		if c.IndexFullText && query != "" {
+			rx, err := regexp.Compile(query)
+			if err != nil {
+				result.Alert = "Error in query regular expression: " + err.Error()
+				return *result
+			}
+			// If we get maxResults+1 results we know that there are more than
+			// maxResults results and thus the result may be incomplete (to be
+			// precise, we should remove one result from the result set, but
+			// nobody is going to count the results on the result page).
+			result.Found, result.Textual = index.LookupRegexp(rx, c.MaxResults+1)
+			result.Complete = result.Found <= c.MaxResults
+			if !result.Complete {
+				result.Found-- // since we looked for maxResults+1
+			}
+		}
+	}
+
+	// is the result accurate?
+	if c.IndexEnabled {
+		if ts := c.FSModifiedTime(); timestamp.Before(ts) {
+			// The index is older than the latest file system change under godoc's observation.
+			result.Alert = "Indexing in progress: result may be inaccurate"
+		}
+	} else {
+		result.Alert = "Search index disabled: no results available"
+	}
+
+	return *result
+}
+
+// SearchResultDoc optionally specifies a function returning an HTML body
+// displaying search results matching godoc documentation.
+func (p *Presentation) SearchResultDoc(result SearchResult) []byte {
+	return applyTemplate(p.SearchDocHTML, "searchDocHTML", result)
+}
+
+// SearchResultCode optionally specifies a function returning an HTML body
+// displaying search results matching source code.
+func (p *Presentation) SearchResultCode(result SearchResult) []byte {
+	return applyTemplate(p.SearchCodeHTML, "searchCodeHTML", result)
+}
+
+// SearchResultTxt optionally specifies a function returning an HTML body
+// displaying search results of textual matches.
+func (p *Presentation) SearchResultTxt(result SearchResult) []byte {
+	return applyTemplate(p.SearchTxtHTML, "searchTxtHTML", result)
+}
+
+// HandleSearch obtains results for the requested search and returns a page
+// to display them.
+func (p *Presentation) HandleSearch(w http.ResponseWriter, r *http.Request) {
+	query := strings.TrimSpace(r.FormValue("q"))
+	result := p.Corpus.Lookup(query)
+
+	if p.GetPageInfoMode(r)&NoHTML != 0 {
+		p.ServeText(w, applyTemplate(p.SearchText, "searchText", result))
+		return
+	}
+	contents := bytes.Buffer{}
+	for _, f := range p.SearchResults {
+		contents.Write(f(p, result))
+	}
+
+	var title string
+	if haveResults := contents.Len() > 0; haveResults {
+		title = fmt.Sprintf(`Results for query %q`, query)
+		if !p.Corpus.IndexEnabled {
+			result.Alert = ""
+		}
+	} else {
+		title = fmt.Sprintf(`No results found for query %q`, query)
+	}
+
+	body := bytes.NewBuffer(applyTemplate(p.SearchHTML, "searchHTML", result))
+	body.Write(contents.Bytes())
+
+	p.ServePage(w, Page{
+		Title:    title,
+		Tabtitle: query,
+		Query:    query,
+		Body:     body.Bytes(),
+	})
+}
+
+func (p *Presentation) serveSearchDesc(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/opensearchdescription+xml")
+	data := map[string]interface{}{
+		"BaseURL": fmt.Sprintf("http://%s", r.Host),
+	}
+	applyTemplateToResponseWriter(w, p.SearchDescXML, &data)
+}
diff --git a/third_party/go.tools/godoc/server.go b/third_party/go.tools/godoc/server.go
new file mode 100644
index 0000000..9ba695d
--- /dev/null
+++ b/third_party/go.tools/godoc/server.go
@@ -0,0 +1,760 @@
+// Copyright 2013 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 godoc
+
+import (
+	"bytes"
+	"encoding/json"
+	"expvar"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/doc"
+	"go/token"
+	htmlpkg "html"
+	htmltemplate "html/template"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"os"
+	pathpkg "path"
+	"path/filepath"
+	"sort"
+	"strings"
+	"text/template"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/analysis"
+	"llvm.org/llgo/third_party/go.tools/godoc/util"
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+// handlerServer is a migration from an old godoc http Handler type.
+// This should probably merge into something else.
+type handlerServer struct {
+	p       *Presentation
+	c       *Corpus  // copy of p.Corpus
+	pattern string   // url pattern; e.g. "/pkg/"
+	fsRoot  string   // file system root to which the pattern is mapped; e.g. "/src"
+	exclude []string // file system paths to exclude; e.g. "/src/cmd"
+}
+
+func (s *handlerServer) registerWithMux(mux *http.ServeMux) {
+	mux.Handle(s.pattern, s)
+}
+
+// getPageInfo returns the PageInfo for a package directory abspath. If the
+// parameter genAST is set, an AST containing only the package exports is
+// computed (PageInfo.PAst), otherwise package documentation (PageInfo.Doc)
+// is extracted from the AST. If there is no corresponding package in the
+// directory, PageInfo.PAst and PageInfo.PDoc are nil. If there are no sub-
+// directories, PageInfo.Dirs is nil. If an error occurred, PageInfo.Err is
+// set to the respective error but the error is not logged.
+//
+func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
+	info := &PageInfo{Dirname: abspath}
+
+	// Restrict to the package files that would be used when building
+	// the package on this system.  This makes sure that if there are
+	// separate implementations for, say, Windows vs Unix, we don't
+	// jumble them all together.
+	// Note: Uses current binary's GOOS/GOARCH.
+	// To use different pair, such as if we allowed the user to choose,
+	// set ctxt.GOOS and ctxt.GOARCH before calling ctxt.ImportDir.
+	ctxt := build.Default
+	ctxt.IsAbsPath = pathpkg.IsAbs
+	ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) {
+		f, err := h.c.fs.ReadDir(filepath.ToSlash(dir))
+		filtered := make([]os.FileInfo, 0, len(f))
+		for _, i := range f {
+			if mode&NoFiltering != 0 || i.Name() != "internal" {
+				filtered = append(filtered, i)
+			}
+		}
+		return filtered, err
+	}
+	ctxt.OpenFile = func(name string) (r io.ReadCloser, err error) {
+		data, err := vfs.ReadFile(h.c.fs, filepath.ToSlash(name))
+		if err != nil {
+			return nil, err
+		}
+		return ioutil.NopCloser(bytes.NewReader(data)), nil
+	}
+
+	pkginfo, err := ctxt.ImportDir(abspath, 0)
+	// continue if there are no Go source files; we still want the directory info
+	if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
+		info.Err = err
+		return info
+	}
+
+	// collect package files
+	pkgname := pkginfo.Name
+	pkgfiles := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
+	if len(pkgfiles) == 0 {
+		// Commands written in C have no .go files in the build.
+		// Instead, documentation may be found in an ignored file.
+		// The file may be ignored via an explicit +build ignore
+		// constraint (recommended), or by defining the package
+		// documentation (historic).
+		pkgname = "main" // assume package main since pkginfo.Name == ""
+		pkgfiles = pkginfo.IgnoredGoFiles
+	}
+
+	// get package information, if any
+	if len(pkgfiles) > 0 {
+		// build package AST
+		fset := token.NewFileSet()
+		files, err := h.c.parseFiles(fset, relpath, abspath, pkgfiles)
+		if err != nil {
+			info.Err = err
+			return info
+		}
+
+		// ignore any errors - they are due to unresolved identifiers
+		pkg, _ := ast.NewPackage(fset, files, poorMansImporter, nil)
+
+		// extract package documentation
+		info.FSet = fset
+		if mode&ShowSource == 0 {
+			// show extracted documentation
+			var m doc.Mode
+			if mode&NoFiltering != 0 {
+				m |= doc.AllDecls
+			}
+			if mode&AllMethods != 0 {
+				m |= doc.AllMethods
+			}
+			info.PDoc = doc.New(pkg, pathpkg.Clean(relpath), m) // no trailing '/' in importpath
+			if mode&NoTypeAssoc != 0 {
+				for _, t := range info.PDoc.Types {
+					info.PDoc.Consts = append(info.PDoc.Consts, t.Consts...)
+					info.PDoc.Vars = append(info.PDoc.Vars, t.Vars...)
+					info.PDoc.Funcs = append(info.PDoc.Funcs, t.Funcs...)
+					t.Consts = nil
+					t.Vars = nil
+					t.Funcs = nil
+				}
+				// for now we cannot easily sort consts and vars since
+				// go/doc.Value doesn't export the order information
+				sort.Sort(funcsByName(info.PDoc.Funcs))
+			}
+
+			// collect examples
+			testfiles := append(pkginfo.TestGoFiles, pkginfo.XTestGoFiles...)
+			files, err = h.c.parseFiles(fset, relpath, abspath, testfiles)
+			if err != nil {
+				log.Println("parsing examples:", err)
+			}
+			info.Examples = collectExamples(h.c, pkg, files)
+
+			// collect any notes that we want to show
+			if info.PDoc.Notes != nil {
+				// could regexp.Compile only once per godoc, but probably not worth it
+				if rx := h.p.NotesRx; rx != nil {
+					for m, n := range info.PDoc.Notes {
+						if rx.MatchString(m) {
+							if info.Notes == nil {
+								info.Notes = make(map[string][]*doc.Note)
+							}
+							info.Notes[m] = n
+						}
+					}
+				}
+			}
+
+		} else {
+			// show source code
+			// TODO(gri) Consider eliminating export filtering in this mode,
+			//           or perhaps eliminating the mode altogether.
+			if mode&NoFiltering == 0 {
+				packageExports(fset, pkg)
+			}
+			info.PAst = files
+		}
+		info.IsMain = pkgname == "main"
+	}
+
+	// get directory information, if any
+	var dir *Directory
+	var timestamp time.Time
+	if tree, ts := h.c.fsTree.Get(); tree != nil && tree.(*Directory) != nil {
+		// directory tree is present; lookup respective directory
+		// (may still fail if the file system was updated and the
+		// new directory tree has not yet been computed)
+		dir = tree.(*Directory).lookup(abspath)
+		timestamp = ts
+	}
+	if dir == nil {
+		// no directory tree present (too early after startup or
+		// command-line mode); compute one level for this page
+		// note: cannot use path filter here because in general
+		//       it doesn't contain the FSTree path
+		dir = h.c.newDirectory(abspath, 1)
+		timestamp = time.Now()
+	}
+	info.Dirs = dir.listing(true, func(path string) bool { return h.includePath(path, mode) })
+	info.DirTime = timestamp
+	info.DirFlat = mode&FlatDir != 0
+
+	return info
+}
+
+func (h *handlerServer) includePath(path string, mode PageInfoMode) (r bool) {
+	// if the path is under one of the exclusion paths, don't list.
+	for _, e := range h.exclude {
+		if strings.HasPrefix(path, e) {
+			return false
+		}
+	}
+
+	// if the path includes 'internal', don't list unless we are in the NoFiltering mode.
+	if mode&NoFiltering != 0 {
+		return true
+	}
+	if strings.Contains(path, "internal") {
+		for _, c := range strings.Split(filepath.Clean(path), string(os.PathSeparator)) {
+			if c == "internal" {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+type funcsByName []*doc.Func
+
+func (s funcsByName) Len() int           { return len(s) }
+func (s funcsByName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s funcsByName) Less(i, j int) bool { return s[i].Name < s[j].Name }
+
+func (h *handlerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	if redirect(w, r) {
+		return
+	}
+
+	relpath := pathpkg.Clean(r.URL.Path[len(h.pattern):])
+	abspath := pathpkg.Join(h.fsRoot, relpath)
+	mode := h.p.GetPageInfoMode(r)
+	if relpath == builtinPkgPath {
+		mode = NoFiltering | NoTypeAssoc
+	}
+	info := h.GetPageInfo(abspath, relpath, mode)
+	if info.Err != nil {
+		log.Print(info.Err)
+		h.p.ServeError(w, r, relpath, info.Err)
+		return
+	}
+
+	if mode&NoHTML != 0 {
+		h.p.ServeText(w, applyTemplate(h.p.PackageText, "packageText", info))
+		return
+	}
+
+	var tabtitle, title, subtitle string
+	switch {
+	case info.PAst != nil:
+		for _, ast := range info.PAst {
+			tabtitle = ast.Name.Name
+			break
+		}
+	case info.PDoc != nil:
+		tabtitle = info.PDoc.Name
+	default:
+		tabtitle = info.Dirname
+		title = "Directory "
+		if h.p.ShowTimestamps {
+			subtitle = "Last update: " + info.DirTime.String()
+		}
+	}
+	if title == "" {
+		if info.IsMain {
+			// assume that the directory name is the command name
+			_, tabtitle = pathpkg.Split(relpath)
+			title = "Command "
+		} else {
+			title = "Package "
+		}
+	}
+	title += tabtitle
+
+	// special cases for top-level package/command directories
+	switch tabtitle {
+	case "/src":
+		title = "Packages"
+		tabtitle = "Packages"
+	case "/src/cmd":
+		title = "Commands"
+		tabtitle = "Commands"
+	}
+
+	// Emit JSON array for type information.
+	pi := h.c.Analysis.PackageInfo(relpath)
+	info.CallGraphIndex = pi.CallGraphIndex
+	info.CallGraph = htmltemplate.JS(marshalJSON(pi.CallGraph))
+	info.AnalysisData = htmltemplate.JS(marshalJSON(pi.Types))
+	info.TypeInfoIndex = make(map[string]int)
+	for i, ti := range pi.Types {
+		info.TypeInfoIndex[ti.Name] = i
+	}
+
+	h.p.ServePage(w, Page{
+		Title:    title,
+		Tabtitle: tabtitle,
+		Subtitle: subtitle,
+		Body:     applyTemplate(h.p.PackageHTML, "packageHTML", info),
+	})
+}
+
+type PageInfoMode uint
+
+const (
+	NoFiltering PageInfoMode = 1 << iota // do not filter exports
+	AllMethods                           // show all embedded methods
+	ShowSource                           // show source code, do not extract documentation
+	NoHTML                               // show result in textual form, do not generate HTML
+	FlatDir                              // show directory in a flat (non-indented) manner
+	NoTypeAssoc                          // don't associate consts, vars, and factory functions with types
+)
+
+// modeNames defines names for each PageInfoMode flag.
+var modeNames = map[string]PageInfoMode{
+	"all":     NoFiltering,
+	"methods": AllMethods,
+	"src":     ShowSource,
+	"text":    NoHTML,
+	"flat":    FlatDir,
+}
+
+// GetPageInfoMode computes the PageInfoMode flags by analyzing the request
+// URL form value "m". It is value is a comma-separated list of mode names
+// as defined by modeNames (e.g.: m=src,text).
+func (p *Presentation) GetPageInfoMode(r *http.Request) PageInfoMode {
+	var mode PageInfoMode
+	for _, k := range strings.Split(r.FormValue("m"), ",") {
+		if m, found := modeNames[strings.TrimSpace(k)]; found {
+			mode |= m
+		}
+	}
+	if p.AdjustPageInfoMode != nil {
+		mode = p.AdjustPageInfoMode(r, mode)
+	}
+	return mode
+}
+
+// poorMansImporter returns a (dummy) package object named
+// by the last path component of the provided package path
+// (as is the convention for packages). This is sufficient
+// to resolve package identifiers without doing an actual
+// import. It never returns an error.
+//
+func poorMansImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) {
+	pkg := imports[path]
+	if pkg == nil {
+		// note that strings.LastIndex returns -1 if there is no "/"
+		pkg = ast.NewObj(ast.Pkg, path[strings.LastIndex(path, "/")+1:])
+		pkg.Data = ast.NewScope(nil) // required by ast.NewPackage for dot-import
+		imports[path] = pkg
+	}
+	return pkg, nil
+}
+
+// globalNames returns a set of the names declared by all package-level
+// declarations. Method names are returned in the form Receiver_Method.
+func globalNames(pkg *ast.Package) map[string]bool {
+	names := make(map[string]bool)
+	for _, file := range pkg.Files {
+		for _, decl := range file.Decls {
+			addNames(names, decl)
+		}
+	}
+	return names
+}
+
+// collectExamples collects examples for pkg from testfiles.
+func collectExamples(c *Corpus, pkg *ast.Package, testfiles map[string]*ast.File) []*doc.Example {
+	var files []*ast.File
+	for _, f := range testfiles {
+		files = append(files, f)
+	}
+
+	var examples []*doc.Example
+	globals := globalNames(pkg)
+	for _, e := range doc.Examples(files...) {
+		name := stripExampleSuffix(e.Name)
+		if name == "" || globals[name] {
+			examples = append(examples, e)
+		} else if c.Verbose {
+			log.Printf("skipping example 'Example%s' because '%s' is not a known function or type", e.Name, e.Name)
+		}
+	}
+
+	return examples
+}
+
+// addNames adds the names declared by decl to the names set.
+// Method names are added in the form ReceiverTypeName_Method.
+func addNames(names map[string]bool, decl ast.Decl) {
+	switch d := decl.(type) {
+	case *ast.FuncDecl:
+		name := d.Name.Name
+		if d.Recv != nil {
+			var typeName string
+			switch r := d.Recv.List[0].Type.(type) {
+			case *ast.StarExpr:
+				typeName = r.X.(*ast.Ident).Name
+			case *ast.Ident:
+				typeName = r.Name
+			}
+			name = typeName + "_" + name
+		}
+		names[name] = true
+	case *ast.GenDecl:
+		for _, spec := range d.Specs {
+			switch s := spec.(type) {
+			case *ast.TypeSpec:
+				names[s.Name.Name] = true
+			case *ast.ValueSpec:
+				for _, id := range s.Names {
+					names[id.Name] = true
+				}
+			}
+		}
+	}
+}
+
+// packageExports is a local implementation of ast.PackageExports
+// which correctly updates each package file's comment list.
+// (The ast.PackageExports signature is frozen, hence the local
+// implementation).
+//
+func packageExports(fset *token.FileSet, pkg *ast.Package) {
+	for _, src := range pkg.Files {
+		cmap := ast.NewCommentMap(fset, src, src.Comments)
+		ast.FileExports(src)
+		src.Comments = cmap.Filter(src).Comments()
+	}
+}
+
+func applyTemplate(t *template.Template, name string, data interface{}) []byte {
+	var buf bytes.Buffer
+	if err := t.Execute(&buf, data); err != nil {
+		log.Printf("%s.Execute: %s", name, err)
+	}
+	return buf.Bytes()
+}
+
+type writerCapturesErr struct {
+	w   io.Writer
+	err error
+}
+
+func (w *writerCapturesErr) Write(p []byte) (int, error) {
+	n, err := w.w.Write(p)
+	if err != nil {
+		w.err = err
+	}
+	return n, err
+}
+
+var httpErrors *expvar.Map
+
+func init() {
+	httpErrors = expvar.NewMap("httpWriteErrors").Init()
+}
+
+// applyTemplateToResponseWriter uses an http.ResponseWriter as the io.Writer
+// for the call to template.Execute.  It uses an io.Writer wrapper to capture
+// errors from the underlying http.ResponseWriter.  If an error is found, an
+// expvar will be incremented.  Other template errors will be logged.  This is
+// done to keep from polluting log files with error messages due to networking
+// issues, such as client disconnects and http HEAD protocol violations.
+func applyTemplateToResponseWriter(rw http.ResponseWriter, t *template.Template, data interface{}) {
+	w := &writerCapturesErr{w: rw}
+	err := t.Execute(w, data)
+	// There are some cases where template.Execute does not return an error when
+	// rw returns an error, and some where it does.  So check w.err first.
+	if w.err != nil {
+		// For http errors, increment an expvar.
+		httpErrors.Add(w.err.Error(), 1)
+	} else if err != nil {
+		// Log template errors.
+		log.Printf("%s.Execute: %s", t.Name(), err)
+	}
+}
+
+func redirect(w http.ResponseWriter, r *http.Request) (redirected bool) {
+	canonical := pathpkg.Clean(r.URL.Path)
+	if !strings.HasSuffix(canonical, "/") {
+		canonical += "/"
+	}
+	if r.URL.Path != canonical {
+		url := *r.URL
+		url.Path = canonical
+		http.Redirect(w, r, url.String(), http.StatusMovedPermanently)
+		redirected = true
+	}
+	return
+}
+
+func redirectFile(w http.ResponseWriter, r *http.Request) (redirected bool) {
+	c := pathpkg.Clean(r.URL.Path)
+	c = strings.TrimRight(c, "/")
+	if r.URL.Path != c {
+		url := *r.URL
+		url.Path = c
+		http.Redirect(w, r, url.String(), http.StatusMovedPermanently)
+		redirected = true
+	}
+	return
+}
+
+func (p *Presentation) serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, title string) {
+	src, err := vfs.ReadFile(p.Corpus.fs, abspath)
+	if err != nil {
+		log.Printf("ReadFile: %s", err)
+		p.ServeError(w, r, relpath, err)
+		return
+	}
+
+	if r.FormValue("m") == "text" {
+		p.ServeText(w, src)
+		return
+	}
+
+	h := r.FormValue("h")
+	s := RangeSelection(r.FormValue("s"))
+
+	var buf bytes.Buffer
+	if pathpkg.Ext(abspath) == ".go" {
+		// Find markup links for this file (e.g. "/src/fmt/print.go").
+		fi := p.Corpus.Analysis.FileInfo(abspath)
+		buf.WriteString("<script type='text/javascript'>document.ANALYSIS_DATA = ")
+		buf.Write(marshalJSON(fi.Data))
+		buf.WriteString(";</script>\n")
+
+		if status := p.Corpus.Analysis.Status(); status != "" {
+			buf.WriteString("<a href='/lib/godoc/analysis/help.html'>Static analysis features</a> ")
+			// TODO(adonovan): show analysis status at per-file granularity.
+			fmt.Fprintf(&buf, "<span style='color: grey'>[%s]</span><br/>", htmlpkg.EscapeString(status))
+		}
+
+		buf.WriteString("<pre>")
+		formatGoSource(&buf, src, fi.Links, h, s)
+		buf.WriteString("</pre>")
+	} else {
+		buf.WriteString("<pre>")
+		FormatText(&buf, src, 1, false, h, s)
+		buf.WriteString("</pre>")
+	}
+	fmt.Fprintf(&buf, `<p><a href="/%s?m=text">View as plain text</a></p>`, htmlpkg.EscapeString(relpath))
+
+	p.ServePage(w, Page{
+		Title:    title + " " + relpath,
+		Tabtitle: relpath,
+		Body:     buf.Bytes(),
+	})
+}
+
+// formatGoSource HTML-escapes Go source text and writes it to w,
+// decorating it with the specified analysis links.
+//
+func formatGoSource(buf *bytes.Buffer, text []byte, links []analysis.Link, pattern string, selection Selection) {
+	// Emit to a temp buffer so that we can add line anchors at the end.
+	saved, buf := buf, new(bytes.Buffer)
+
+	var i int
+	var link analysis.Link // shared state of the two funcs below
+	segmentIter := func() (seg Segment) {
+		if i < len(links) {
+			link = links[i]
+			i++
+			seg = Segment{link.Start(), link.End()}
+		}
+		return
+	}
+	linkWriter := func(w io.Writer, offs int, start bool) {
+		link.Write(w, offs, start)
+	}
+
+	comments := tokenSelection(text, token.COMMENT)
+	var highlights Selection
+	if pattern != "" {
+		highlights = regexpSelection(text, pattern)
+	}
+
+	FormatSelections(buf, text, linkWriter, segmentIter, selectionTag, comments, highlights, selection)
+
+	// Now copy buf to saved, adding line anchors.
+
+	// The lineSelection mechanism can't be composed with our
+	// linkWriter, so we have to add line spans as another pass.
+	n := 1
+	for _, line := range bytes.Split(buf.Bytes(), []byte("\n")) {
+		fmt.Fprintf(saved, "<span id=\"L%d\" class=\"ln\">%6d</span>\t", n, n)
+		n++
+		saved.Write(line)
+		saved.WriteByte('\n')
+	}
+}
+
+func (p *Presentation) serveDirectory(w http.ResponseWriter, r *http.Request, abspath, relpath string) {
+	if redirect(w, r) {
+		return
+	}
+
+	list, err := p.Corpus.fs.ReadDir(abspath)
+	if err != nil {
+		p.ServeError(w, r, relpath, err)
+		return
+	}
+
+	p.ServePage(w, Page{
+		Title:    "Directory " + relpath,
+		Tabtitle: relpath,
+		Body:     applyTemplate(p.DirlistHTML, "dirlistHTML", list),
+	})
+}
+
+func (p *Presentation) ServeHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath string) {
+	// get HTML body contents
+	src, err := vfs.ReadFile(p.Corpus.fs, abspath)
+	if err != nil {
+		log.Printf("ReadFile: %s", err)
+		p.ServeError(w, r, relpath, err)
+		return
+	}
+
+	// if it begins with "<!DOCTYPE " assume it is standalone
+	// html that doesn't need the template wrapping.
+	if bytes.HasPrefix(src, doctype) {
+		w.Write(src)
+		return
+	}
+
+	// if it begins with a JSON blob, read in the metadata.
+	meta, src, err := extractMetadata(src)
+	if err != nil {
+		log.Printf("decoding metadata %s: %v", relpath, err)
+	}
+
+	// evaluate as template if indicated
+	if meta.Template {
+		tmpl, err := template.New("main").Funcs(p.TemplateFuncs()).Parse(string(src))
+		if err != nil {
+			log.Printf("parsing template %s: %v", relpath, err)
+			p.ServeError(w, r, relpath, err)
+			return
+		}
+		var buf bytes.Buffer
+		if err := tmpl.Execute(&buf, nil); err != nil {
+			log.Printf("executing template %s: %v", relpath, err)
+			p.ServeError(w, r, relpath, err)
+			return
+		}
+		src = buf.Bytes()
+	}
+
+	// if it's the language spec, add tags to EBNF productions
+	if strings.HasSuffix(abspath, "go_spec.html") {
+		var buf bytes.Buffer
+		Linkify(&buf, src)
+		src = buf.Bytes()
+	}
+
+	p.ServePage(w, Page{
+		Title:    meta.Title,
+		Subtitle: meta.Subtitle,
+		Body:     src,
+	})
+}
+
+func (p *Presentation) ServeFile(w http.ResponseWriter, r *http.Request) {
+	p.serveFile(w, r)
+}
+
+func (p *Presentation) serveFile(w http.ResponseWriter, r *http.Request) {
+	relpath := r.URL.Path
+
+	// Check to see if we need to redirect or serve another file.
+	if m := p.Corpus.MetadataFor(relpath); m != nil {
+		if m.Path != relpath {
+			// Redirect to canonical path.
+			http.Redirect(w, r, m.Path, http.StatusMovedPermanently)
+			return
+		}
+		// Serve from the actual filesystem path.
+		relpath = m.filePath
+	}
+
+	abspath := relpath
+	relpath = relpath[1:] // strip leading slash
+
+	switch pathpkg.Ext(relpath) {
+	case ".html":
+		if strings.HasSuffix(relpath, "/index.html") {
+			// We'll show index.html for the directory.
+			// Use the dir/ version as canonical instead of dir/index.html.
+			http.Redirect(w, r, r.URL.Path[0:len(r.URL.Path)-len("index.html")], http.StatusMovedPermanently)
+			return
+		}
+		p.ServeHTMLDoc(w, r, abspath, relpath)
+		return
+
+	case ".go":
+		p.serveTextFile(w, r, abspath, relpath, "Source file")
+		return
+	}
+
+	dir, err := p.Corpus.fs.Lstat(abspath)
+	if err != nil {
+		log.Print(err)
+		p.ServeError(w, r, relpath, err)
+		return
+	}
+
+	if dir != nil && dir.IsDir() {
+		if redirect(w, r) {
+			return
+		}
+		if index := pathpkg.Join(abspath, "index.html"); util.IsTextFile(p.Corpus.fs, index) {
+			p.ServeHTMLDoc(w, r, index, index)
+			return
+		}
+		p.serveDirectory(w, r, abspath, relpath)
+		return
+	}
+
+	if util.IsTextFile(p.Corpus.fs, abspath) {
+		if redirectFile(w, r) {
+			return
+		}
+		p.serveTextFile(w, r, abspath, relpath, "Text file")
+		return
+	}
+
+	p.fileServer.ServeHTTP(w, r)
+}
+
+func (p *Presentation) ServeText(w http.ResponseWriter, text []byte) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	w.Write(text)
+}
+
+func marshalJSON(x interface{}) []byte {
+	var data []byte
+	var err error
+	const indentJSON = false // for easier debugging
+	if indentJSON {
+		data, err = json.MarshalIndent(x, "", "    ")
+	} else {
+		data, err = json.Marshal(x)
+	}
+	if err != nil {
+		panic(fmt.Sprintf("json.Marshal failed: %s", err))
+	}
+	return data
+}
diff --git a/third_party/go.tools/godoc/server_test.go b/third_party/go.tools/godoc/server_test.go
new file mode 100644
index 0000000..9fa411f
--- /dev/null
+++ b/third_party/go.tools/godoc/server_test.go
@@ -0,0 +1,75 @@
+package godoc
+
+import (
+	"errors"
+	"expvar"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+	"text/template"
+)
+
+var (
+	// NOTE: with no plain-text in the template, template.Execute will not
+	// return an error when http.ResponseWriter.Write does return an error.
+	tmpl = template.Must(template.New("test").Parse("{{.Foo}}"))
+)
+
+type withFoo struct {
+	Foo int
+}
+
+type withoutFoo struct {
+}
+
+type errResponseWriter struct {
+}
+
+func (*errResponseWriter) Header() http.Header {
+	return http.Header{}
+}
+
+func (*errResponseWriter) WriteHeader(int) {
+}
+
+func (*errResponseWriter) Write(p []byte) (int, error) {
+	return 0, errors.New("error")
+}
+
+func TestApplyTemplateToResponseWriter(t *testing.T) {
+	for _, tc := range []struct {
+		desc    string
+		rw      http.ResponseWriter
+		data    interface{}
+		expVars int
+	}{
+		{
+			desc:    "no error",
+			rw:      &httptest.ResponseRecorder{},
+			data:    &withFoo{},
+			expVars: 0,
+		},
+		{
+			desc:    "template error",
+			rw:      &httptest.ResponseRecorder{},
+			data:    &withoutFoo{},
+			expVars: 0,
+		},
+		{
+			desc:    "ResponseWriter error",
+			rw:      &errResponseWriter{},
+			data:    &withFoo{},
+			expVars: 1,
+		},
+	} {
+		httpErrors.Init()
+		applyTemplateToResponseWriter(tc.rw, tmpl, tc.data)
+		gotVars := 0
+		httpErrors.Do(func(expvar.KeyValue) {
+			gotVars++
+		})
+		if gotVars != tc.expVars {
+			t.Errorf("applyTemplateToResponseWriter(%q): got %d vars, want %d", tc.desc, gotVars, tc.expVars)
+		}
+	}
+}
diff --git a/third_party/go.tools/godoc/snippet.go b/third_party/go.tools/godoc/snippet.go
new file mode 100644
index 0000000..dd9c822
--- /dev/null
+++ b/third_party/go.tools/godoc/snippet.go
@@ -0,0 +1,123 @@
+// 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.
+
+// This file contains the infrastructure to create a code
+// snippet for search results.
+//
+// Note: At the moment, this only creates HTML snippets.
+
+package godoc
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+)
+
+type Snippet struct {
+	Line int
+	Text string // HTML-escaped
+}
+
+func (p *Presentation) newSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet {
+	// TODO instead of pretty-printing the node, should use the original source instead
+	var buf1 bytes.Buffer
+	p.writeNode(&buf1, fset, decl)
+	// wrap text with <pre> tag
+	var buf2 bytes.Buffer
+	buf2.WriteString("<pre>")
+	FormatText(&buf2, buf1.Bytes(), -1, true, id.Name, nil)
+	buf2.WriteString("</pre>")
+	return &Snippet{fset.Position(id.Pos()).Line, buf2.String()}
+}
+
+func findSpec(list []ast.Spec, id *ast.Ident) ast.Spec {
+	for _, spec := range list {
+		switch s := spec.(type) {
+		case *ast.ImportSpec:
+			if s.Name == id {
+				return s
+			}
+		case *ast.ValueSpec:
+			for _, n := range s.Names {
+				if n == id {
+					return s
+				}
+			}
+		case *ast.TypeSpec:
+			if s.Name == id {
+				return s
+			}
+		}
+	}
+	return nil
+}
+
+func (p *Presentation) genSnippet(fset *token.FileSet, d *ast.GenDecl, id *ast.Ident) *Snippet {
+	s := findSpec(d.Specs, id)
+	if s == nil {
+		return nil //  declaration doesn't contain id - exit gracefully
+	}
+
+	// only use the spec containing the id for the snippet
+	dd := &ast.GenDecl{
+		Doc:    d.Doc,
+		TokPos: d.Pos(),
+		Tok:    d.Tok,
+		Lparen: d.Lparen,
+		Specs:  []ast.Spec{s},
+		Rparen: d.Rparen,
+	}
+
+	return p.newSnippet(fset, dd, id)
+}
+
+func (p *Presentation) funcSnippet(fset *token.FileSet, d *ast.FuncDecl, id *ast.Ident) *Snippet {
+	if d.Name != id {
+		return nil //  declaration doesn't contain id - exit gracefully
+	}
+
+	// only use the function signature for the snippet
+	dd := &ast.FuncDecl{
+		Doc:  d.Doc,
+		Recv: d.Recv,
+		Name: d.Name,
+		Type: d.Type,
+	}
+
+	return p.newSnippet(fset, dd, id)
+}
+
+// NewSnippet creates a text snippet from a declaration decl containing an
+// identifier id. Parts of the declaration not containing the identifier
+// may be removed for a more compact snippet.
+func NewSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet {
+	// TODO(bradfitz, adg): remove this function.  But it's used by indexer, which
+	// doesn't have a *Presentation, and NewSnippet needs a TabWidth.
+	var p Presentation
+	p.TabWidth = 4
+	return p.NewSnippet(fset, decl, id)
+}
+
+// NewSnippet creates a text snippet from a declaration decl containing an
+// identifier id. Parts of the declaration not containing the identifier
+// may be removed for a more compact snippet.
+func (p *Presentation) NewSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet {
+	var s *Snippet
+	switch d := decl.(type) {
+	case *ast.GenDecl:
+		s = p.genSnippet(fset, d, id)
+	case *ast.FuncDecl:
+		s = p.funcSnippet(fset, d, id)
+	}
+
+	// handle failure gracefully
+	if s == nil {
+		var buf bytes.Buffer
+		fmt.Fprintf(&buf, `<span class="alert">could not generate a snippet for <span class="highlight">%s</span></span>`, id.Name)
+		s = &Snippet{fset.Position(id.Pos()).Line, buf.String()}
+	}
+	return s
+}
diff --git a/third_party/go.tools/godoc/spec.go b/third_party/go.tools/godoc/spec.go
new file mode 100644
index 0000000..6d6b9c2
--- /dev/null
+++ b/third_party/go.tools/godoc/spec.go
@@ -0,0 +1,179 @@
+// 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 godoc
+
+// This file contains the mechanism to "linkify" html source
+// text containing EBNF sections (as found in go_spec.html).
+// The result is the input source text with the EBNF sections
+// modified such that identifiers are linked to the respective
+// definitions.
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"text/scanner"
+)
+
+type ebnfParser struct {
+	out     io.Writer // parser output
+	src     []byte    // parser input
+	scanner scanner.Scanner
+	prev    int    // offset of previous token
+	pos     int    // offset of current token
+	tok     rune   // one token look-ahead
+	lit     string // token literal
+}
+
+func (p *ebnfParser) flush() {
+	p.out.Write(p.src[p.prev:p.pos])
+	p.prev = p.pos
+}
+
+func (p *ebnfParser) next() {
+	p.tok = p.scanner.Scan()
+	p.pos = p.scanner.Position.Offset
+	p.lit = p.scanner.TokenText()
+}
+
+func (p *ebnfParser) printf(format string, args ...interface{}) {
+	p.flush()
+	fmt.Fprintf(p.out, format, args...)
+}
+
+func (p *ebnfParser) errorExpected(msg string) {
+	p.printf(`<span class="highlight">error: expected %s, found %s</span>`, msg, scanner.TokenString(p.tok))
+}
+
+func (p *ebnfParser) expect(tok rune) {
+	if p.tok != tok {
+		p.errorExpected(scanner.TokenString(tok))
+	}
+	p.next() // make progress in any case
+}
+
+func (p *ebnfParser) parseIdentifier(def bool) {
+	if p.tok == scanner.Ident {
+		name := p.lit
+		if def {
+			p.printf(`<a id="%s">%s</a>`, name, name)
+		} else {
+			p.printf(`<a href="#%s" class="noline">%s</a>`, name, name)
+		}
+		p.prev += len(name) // skip identifier when printing next time
+		p.next()
+	} else {
+		p.expect(scanner.Ident)
+	}
+}
+
+func (p *ebnfParser) parseTerm() bool {
+	switch p.tok {
+	case scanner.Ident:
+		p.parseIdentifier(false)
+
+	case scanner.String:
+		p.next()
+		const ellipsis = '…' // U+2026, the horizontal ellipsis character
+		if p.tok == ellipsis {
+			p.next()
+			p.expect(scanner.String)
+		}
+
+	case '(':
+		p.next()
+		p.parseExpression()
+		p.expect(')')
+
+	case '[':
+		p.next()
+		p.parseExpression()
+		p.expect(']')
+
+	case '{':
+		p.next()
+		p.parseExpression()
+		p.expect('}')
+
+	default:
+		return false // no term found
+	}
+
+	return true
+}
+
+func (p *ebnfParser) parseSequence() {
+	if !p.parseTerm() {
+		p.errorExpected("term")
+	}
+	for p.parseTerm() {
+	}
+}
+
+func (p *ebnfParser) parseExpression() {
+	for {
+		p.parseSequence()
+		if p.tok != '|' {
+			break
+		}
+		p.next()
+	}
+}
+
+func (p *ebnfParser) parseProduction() {
+	p.parseIdentifier(true)
+	p.expect('=')
+	if p.tok != '.' {
+		p.parseExpression()
+	}
+	p.expect('.')
+}
+
+func (p *ebnfParser) parse(out io.Writer, src []byte) {
+	// initialize ebnfParser
+	p.out = out
+	p.src = src
+	p.scanner.Init(bytes.NewBuffer(src))
+	p.next() // initializes pos, tok, lit
+
+	// process source
+	for p.tok != scanner.EOF {
+		p.parseProduction()
+	}
+	p.flush()
+}
+
+// Markers around EBNF sections
+var (
+	openTag  = []byte(`<pre class="ebnf">`)
+	closeTag = []byte(`</pre>`)
+)
+
+func Linkify(out io.Writer, src []byte) {
+	for len(src) > 0 {
+		// i: beginning of EBNF text (or end of source)
+		i := bytes.Index(src, openTag)
+		if i < 0 {
+			i = len(src) - len(openTag)
+		}
+		i += len(openTag)
+
+		// j: end of EBNF text (or end of source)
+		j := bytes.Index(src[i:], closeTag) // close marker
+		if j < 0 {
+			j = len(src) - i
+		}
+		j += i
+
+		// write text before EBNF
+		out.Write(src[0:i])
+		// process EBNF
+		var p ebnfParser
+		p.parse(out, src[i:j])
+
+		// advance
+		src = src[j:]
+	}
+}
diff --git a/third_party/go.tools/godoc/spot.go b/third_party/go.tools/godoc/spot.go
new file mode 100644
index 0000000..95ffa4b
--- /dev/null
+++ b/third_party/go.tools/godoc/spot.go
@@ -0,0 +1,83 @@
+// Copyright 2013 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 godoc
+
+// ----------------------------------------------------------------------------
+// SpotInfo
+
+// A SpotInfo value describes a particular identifier spot in a given file;
+// It encodes three values: the SpotKind (declaration or use), a line or
+// snippet index "lori", and whether it's a line or index.
+//
+// The following encoding is used:
+//
+//   bits    32   4    1       0
+//   value    [lori|kind|isIndex]
+//
+type SpotInfo uint32
+
+// SpotKind describes whether an identifier is declared (and what kind of
+// declaration) or used.
+type SpotKind uint32
+
+const (
+	PackageClause SpotKind = iota
+	ImportDecl
+	ConstDecl
+	TypeDecl
+	VarDecl
+	FuncDecl
+	MethodDecl
+	Use
+	nKinds
+)
+
+var (
+	// These must match the SpotKind values above.
+	name = []string{
+		"Packages",
+		"Imports",
+		"Constants",
+		"Types",
+		"Variables",
+		"Functions",
+		"Methods",
+		"Uses",
+		"Unknown",
+	}
+)
+
+func (x SpotKind) Name() string { return name[x] }
+
+func init() {
+	// sanity check: if nKinds is too large, the SpotInfo
+	// accessor functions may need to be updated
+	if nKinds > 8 {
+		panic("internal error: nKinds > 8")
+	}
+}
+
+// makeSpotInfo makes a SpotInfo.
+func makeSpotInfo(kind SpotKind, lori int, isIndex bool) SpotInfo {
+	// encode lori: bits [4..32)
+	x := SpotInfo(lori) << 4
+	if int(x>>4) != lori {
+		// lori value doesn't fit - since snippet indices are
+		// most certainly always smaller then 1<<28, this can
+		// only happen for line numbers; give it no line number (= 0)
+		x = 0
+	}
+	// encode kind: bits [1..4)
+	x |= SpotInfo(kind) << 1
+	// encode isIndex: bit 0
+	if isIndex {
+		x |= 1
+	}
+	return x
+}
+
+func (x SpotInfo) Kind() SpotKind { return SpotKind(x >> 1 & 7) }
+func (x SpotInfo) Lori() int      { return int(x >> 4) }
+func (x SpotInfo) IsIndex() bool  { return x&1 != 0 }
diff --git a/third_party/go.tools/godoc/static/analysis/call-eg.png b/third_party/go.tools/godoc/static/analysis/call-eg.png
new file mode 100644
index 0000000..c48bf4d
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/call-eg.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/call3.png b/third_party/go.tools/godoc/static/analysis/call3.png
new file mode 100644
index 0000000..387a38c
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/call3.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/callers1.png b/third_party/go.tools/godoc/static/analysis/callers1.png
new file mode 100644
index 0000000..80fbc62
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/callers1.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/callers2.png b/third_party/go.tools/godoc/static/analysis/callers2.png
new file mode 100644
index 0000000..59a84ed
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/callers2.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/chan1.png b/third_party/go.tools/godoc/static/analysis/chan1.png
new file mode 100644
index 0000000..5eb2811
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/chan1.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/chan2a.png b/third_party/go.tools/godoc/static/analysis/chan2a.png
new file mode 100644
index 0000000..b757504
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/chan2a.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/chan2b.png b/third_party/go.tools/godoc/static/analysis/chan2b.png
new file mode 100644
index 0000000..d197862
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/chan2b.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/error1.png b/third_party/go.tools/godoc/static/analysis/error1.png
new file mode 100644
index 0000000..69550b9
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/error1.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/help.html b/third_party/go.tools/godoc/static/analysis/help.html
new file mode 100644
index 0000000..61f0665
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/help.html
@@ -0,0 +1,265 @@
+<!--{
+        "Title": "Static analysis features of godoc"
+}-->
+
+<style>
+  span.err { 'font-size:120%; color:darkred; background-color: yellow; }
+  img.ss { margin-left: 1in; } /* screenshot */
+  img.dotted { border: thin dotted; }
+</style>
+
+<!-- Images were grabbed from Chrome/Linux at 150% zoom, and are
+     displayed at 66% of natural size.  This allows users to zoom a
+     little before seeing pixels. -->
+
+<p>
+  When invoked with the <code>-analysis</code> flag, godoc performs
+  static analysis on the Go packages it indexes and displays the
+  results in the source and package views.  This document provides a
+  brief tour of these features.
+</p>
+<p>
+  The current status of the analysis features is that of a technology
+  preview; there are many problems and user-interface difficulties
+  which will be addressed in due course.  Some known problems are
+  mentioned in passing, accompanied by a warning triangle, <span
+  style='font-size:120%; color:darkred; background-color:
+  yellow'>⚠</span>.
+
+  Nonetheless, godoc's static analysis may be immediately useful today
+  for small-to-medium sized Go corpora, and it contains several
+  advances over the state of the art in code browsing.
+</p>
+
+<h2>Type analysis features</h2>
+<p>
+  <code>godoc -analysis=type</code> performs static checking similar
+  to that done by a compiler: it detects ill-formed programs, resolves
+  each identifier to the entity it denotes, computes the type of each
+  expression and the method set of each type, and determines which
+  types are assignable to each interface type.
+
+  <b>Type analysis</b> is relatively quick, requiring about 10 seconds for
+  the &gt;200 packages of the standard library, for example.
+</p>
+
+<h3>Compiler errors</h3>
+<p>
+  If any source file contains a compilation error, the source view
+  will highlight the errant location in red.  Hovering over it
+  displays the error message.
+</p>
+<img class="ss" width='811' src='error1.png'><br/>
+<p>
+  <span class='err'>⚠</span> The mark-up for compilation errors may
+  cause duplication of portions of the input.
+</p>
+
+<h3>Identifier resolution</h3>
+<p>
+  In the source view, every referring identifier is annotated with
+  information about the language entity it refers to: a package,
+  constant, variable, type, function or statement label.
+
+  Hovering over the identifier reveals the entity's kind and type
+  (e.g. <code>var x int</code> or <code>func f
+  func(int) string</code>).
+</p>
+<img class="ss" width='652' src='ident-field.png'><br/>
+<br/>
+<img class="ss" width='652' src='ident-func.png'>
+<p>
+  Clicking the link takes you to the entity's definition.
+</p>
+<img class="ss" width='652' src='ident-def.png'><br/>
+
+<h3>Type information: size/alignment, method set, interfaces</h3>
+<p>
+  Clicking on the identifier that defines a named type causes a panel
+  to appear, displaying information about the named type, including
+  its size and alignment in bytes, its <a href='http://golang.org/ref/spec#Method_sets'>method set</a>, and its
+  <i>implements</i> relation: the set of types T that are assignable to
+  or from this type U where at least one of T or U is an interface.
+
+  This example shows information about <code>net/rpc.methodType</code>.
+</p>
+<img class="ss" width='470' src='typeinfo-src.png'>
+<p>
+  The method set includes not only the declared methods of the type,
+  but also any methods "promoted" from anonymous fields of structs,
+  such as <code>sync.Mutex</code> in this example.
+
+  In addition, the receiver type is displayed as <code>*T</code> or
+  <code>T</code> depending on whether it requires the address or just
+  a copy of the receiver value.
+</p>
+<p>
+  The method set and <i>implements</i> relation are also available
+  via the package view.
+</p>
+<img class="ss dotted" width='716' src='typeinfo-pkg.png'>
+
+<h2>Pointer analysis features</h2>
+<p>
+  <code>godoc -analysis=pointer</code> additionally performs a precise
+  whole-program <b>pointer analysis</b>.  In other words, it
+  approximates the set of memory locations to which each
+  reference&mdash;not just vars of kind <code>*T</code>, but also
+  <code>[]T</code>, <code>func</code>, <code>map</code>,
+  <code>chan</code>, and <code>interface</code>&mdash;may refer.  This
+  information reveals the possible destinations of each dynamic call
+  (via a <code>func</code> variable or interface method), and the
+  relationship between send and receive operations on the same
+  channel.
+</p>
+<p>
+  Pointer analysis is slower than type analysis, taking an additional
+  15 seconds or so for the standard libraries and their tests.
+</p>
+
+<h3>Call graph navigation</h3>
+<p>
+  When pointer analysis is complete, the source view annotates the
+  code with <b>callers</b> and <b>callees</b> information: callers
+  information is associated with the <code>func</code> keyword that
+  declares a function, and callees information is associated with the
+  open paren '<span style="color: dark-blue"><code>(</code></span>' of
+  a function call.
+</p>
+<p>
+  In this example, hovering over the declaration of the
+  <code>rot13</code> function (defined in strings/strings_test.go)
+  reveals that it is called in exactly one place.
+</p>
+<img class="ss" width='612' src='callers1.png'>
+<p>
+  Clicking the link navigates to the sole caller.  (If there were
+  multiple callers, a list of choices would be displayed first.)
+</p>
+<img class="ss" width='680' src='callers2.png'>
+<p>
+  Notice that hovering over this call reveals that there are 19
+  possible callees at this site, of which our <code>rot13</code>
+  function was just one: this is a dynamic call through a variable of
+  type <code>func(rune) rune</code>.
+
+  Clicking on the call brings up the list of all 19 potential callees,
+  shown truncated.  Many of them are anonymous functions.
+</p>
+<img class="ss" width='564' src='call3.png'>
+<p>
+  Pointer analysis gives a very precise approximation of the call
+  graph compared to type-based techniques.
+
+  As a case in point, the next example shows the dynamic call inside
+  the <code>testing</code> package responsible for calling all
+  user-defined functions named <code>Example<i>XYZ</i></code>.
+</p>
+<img class="ss" width='361' src='call-eg.png'>
+<p>
+  Recall that all such functions have type <code>func()</code>,
+  i.e. no arguments and no results.  A type-based approximation could
+  only conclude that this call might dispatch to any function matching
+  that type&mdash;and these are very numerous in most
+  programs&mdash;but pointer analysis can track the flow of specific
+  <code>func</code> values through the testing package.
+
+  As an indication of its precision, the result contains only
+  functions whose name starts with <code>Example</code>.
+</p>
+
+<h3>Intra-package call graph</h3>
+<p>
+  The same call graph information is presented in a very different way
+  in the package view.  For each package, an interactive tree view
+  allows exploration of the call graph as it relates to just that
+  package; all functions from other packages are elided.
+
+  The roots of the tree are the external entry points of the package:
+  not only its exported functions, but also any unexported or
+  anonymous functions that are called (dynamically) from outside the
+  package.
+</p>
+<p>
+  This example shows the entry points of the
+  <code>path/filepath</code> package, with the call graph for
+  <code>Glob</code> expanded several levels
+</p>
+<img class="ss dotted" width='501' src='ipcg-pkg.png'>
+<p>
+  Notice that the nodes for Glob and Join appear multiple times: the
+  tree is a partial unrolling of a cyclic graph; the full unrolling
+  is in general infinite.
+</p>
+<p>
+  For each function documented in the package view, another
+  interactive tree view allows exploration of the same graph starting
+  at that function.
+
+  This is a portion of the internal graph of
+  <code>net/http.ListenAndServe</code>.
+</p>
+<img class="ss dotted" width='455' src='ipcg-func.png'>
+
+<h3>Channel peers (send ↔ receive)</h3>
+<p>
+  Because concurrent Go programs use channels to pass not just values
+  but also control between different goroutines, it is natural when
+  reading Go code to want to navigate from a channel send to the
+  corresponding receive so as to understand the sequence of events.
+</p>
+<p>
+  Godoc annotates every channel operation&mdash;make, send, range,
+  receive, close&mdash;with a link to a panel displaying information
+  about other operations that might alias the same channel.
+</p>
+<p>
+  This example, from the tests of <code>net/http</code>, shows a send
+  operation on a <code>chan bool</code>.
+</p>
+<img class="ss" width='811' src='chan1.png'>
+<p>
+  Clicking on the <code>&lt;-</code> send operator reveals that this
+  channel is made at a unique location (line 332) and that there are
+  three receive operations that might read this value.
+
+  It hardly needs pointing out that some channel element types are
+  very widely used (e.g. struct{}, bool, int, interface{}) and that a
+  typical Go program might contain dozens of receive operations on a
+  value of type <code>chan bool</code>; yet the pointer analysis is
+  able to distinguish operations on channels at a much finer precision
+  than based on their type alone.
+</p>
+<p>
+  Notice also that the send occurs in a different (anonymous) function
+  from the outer one containing the <code>make</code> and the receive
+  operations.
+</p>
+<p>
+  Here's another example of send on a different <code>chan
+  bool</code>, also in package <code>net/http</code>:
+</p>
+<img class="ss" width='774' src='chan2a.png'>
+<p>
+  The analysis finds just one receive operation that might receive
+  from this channel, in the test for this feature.
+</p>
+<img class="ss" width='737' src='chan2b.png'>
+
+<h2>Known issues</h2>
+<p>
+  <span class='err'>⚠</span> All analysis results pertain to exactly
+  one configuration (e.g. amd64 linux).  Files that are conditionally
+  compiled based on different platforms or build tags are not visible
+  to the analysis.</br>
+
+  <span class='err'>⚠</span> Files that <code>import "C"</code> require
+  preprocessing by the cgo tool.  The file offsets after preprocessing
+  do not align with the unpreprocessed file, so markup is misaligned.<br/>
+
+  <span class='err'>⚠</span> Files are not periodically re-analyzed.
+  If the files change underneath the running server, the displayed
+  markup is misaligned.</br>
+
+  <span class='err'>⚠</span> Additional issues are listed at <a href='https://code.google.com/p/go/source/browse/godoc/analysis/README?repo=tools'>go.tools/godoc/analysis/README</a>.</br>
+</p>
diff --git a/third_party/go.tools/godoc/static/analysis/ident-def.png b/third_party/go.tools/godoc/static/analysis/ident-def.png
new file mode 100644
index 0000000..b0d9e55
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/ident-def.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/ident-field.png b/third_party/go.tools/godoc/static/analysis/ident-field.png
new file mode 100644
index 0000000..76cbe5a
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/ident-field.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/ident-func.png b/third_party/go.tools/godoc/static/analysis/ident-func.png
new file mode 100644
index 0000000..69670fa
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/ident-func.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/ipcg-func.png b/third_party/go.tools/godoc/static/analysis/ipcg-func.png
new file mode 100644
index 0000000..523318d
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/ipcg-func.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/ipcg-pkg.png b/third_party/go.tools/godoc/static/analysis/ipcg-pkg.png
new file mode 100644
index 0000000..e029068
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/ipcg-pkg.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/typeinfo-pkg.png b/third_party/go.tools/godoc/static/analysis/typeinfo-pkg.png
new file mode 100644
index 0000000..91bd5f7
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/typeinfo-pkg.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/analysis/typeinfo-src.png b/third_party/go.tools/godoc/static/analysis/typeinfo-src.png
new file mode 100644
index 0000000..6e5b147
--- /dev/null
+++ b/third_party/go.tools/godoc/static/analysis/typeinfo-src.png
Binary files differ
diff --git a/third_party/go.tools/godoc/static/callgraph.html b/third_party/go.tools/godoc/static/callgraph.html
new file mode 100644
index 0000000..c56b2ef
--- /dev/null
+++ b/third_party/go.tools/godoc/static/callgraph.html
@@ -0,0 +1,15 @@
+<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Internal call graph</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Internal call graph</span></p>
+		<p>
+		  This viewer shows the portion of the internal call
+		  graph of this package that is reachable from this function.
+		  See the <a href='#pkg-callgraph'>package's call
+		  graph</a> for more information.
+		</p>
+		<ul style="margin-left: 0.5in" id="callgraph-{{.Index}}" class="treeview"></ul>
+	</div>
+</div>
diff --git a/third_party/go.tools/godoc/static/codewalk.html b/third_party/go.tools/godoc/static/codewalk.html
new file mode 100644
index 0000000..0f3d22a
--- /dev/null
+++ b/third_party/go.tools/godoc/static/codewalk.html
@@ -0,0 +1,56 @@
+<!--
+	Copyright 2010 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.
+-->
+
+<style type='text/css'>@import "/doc/codewalk/codewalk.css";</style>
+<script type="text/javascript" src="/doc/codewalk/codewalk.js"></script>
+
+<div id="codewalk-main">
+  <div class="left" id="code-column">
+    <div id='sizer'></div>
+    <div id="code-area">
+      <div id="code-header" align="center">
+        <a id="code-popout-link" href="" target="_blank">
+          <img title="View code in new window" alt="Pop Out Code" src="/doc/codewalk/popout.png" style="display: block; float: right;"/>
+        </a>
+        <select id="code-selector">
+          {{range .File}}
+          <option value="/doc/codewalk/?fileprint=/{{urlquery .}}">{{html .}}</option>
+          {{end}}
+        </select>
+      </div>
+      <div id="code">
+        <iframe class="code-display" name="code-display" id="code-display"></iframe>
+      </div>
+    </div>
+    <div id="code-options" class="setting">
+      <span>code on <a id="set-code-left" class="selected" href="#">left</a> &bull; <a id="set-code-right" href="#">right</a></span>
+      <span>code width <span id="code-column-width">70%</span></span>
+      <span>filepaths <a id="show-filepaths" class="selected" href="#">shown</a> &bull; <a id="hide-filepaths" href="#">hidden</a></span>
+    </div>
+  </div>
+  <div class="right" id="comment-column">
+    <div id="comment-area">
+      {{range .Step}}
+      <div class="comment first last">
+        <a class="comment-link" href="/doc/codewalk/?fileprint=/{{urlquery .File}}&amp;lo={{urlquery .Lo}}&amp;hi={{urlquery .Hi}}#mark" target="code-display"></a>
+        <div class="comment-title">{{html .Title}}</div>
+        <div class="comment-text">
+	{{with .Err}}
+	ERROR LOADING FILE: {{html .}}<br/><br/>
+	{{end}}
+        {{.XML}}
+        </div>
+        <div class="comment-text file-name"><span class="path-file">{{html .}}</span></div>
+      </div>
+      {{end}}
+    </div>
+    <div id="comment-options" class="setting">
+      <a id="prev-comment" href="#"><span class="hotkey">p</span>revious step</a>
+      &bull;
+      <a id="next-comment" href="#"><span class="hotkey">n</span>ext step</a>
+    </div>
+  </div>
+</div>
diff --git a/third_party/go.tools/godoc/static/codewalkdir.html b/third_party/go.tools/godoc/static/codewalkdir.html
new file mode 100644
index 0000000..b7674c6
--- /dev/null
+++ b/third_party/go.tools/godoc/static/codewalkdir.html
@@ -0,0 +1,16 @@
+<!--
+	Copyright 2010 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.
+-->
+
+<table class="layout">
+{{range .}}
+<tr>
+	{{$name_html := html .Name}}
+	<td><a href="{{$name_html}}">{{$name_html}}</a></td>
+	<td width="25">&nbsp;</td>
+	<td>{{html .Title}}</td>
+</tr>
+{{end}}
+</table>
diff --git a/third_party/go.tools/godoc/static/dirlist.html b/third_party/go.tools/godoc/static/dirlist.html
new file mode 100644
index 0000000..a3e1a2f
--- /dev/null
+++ b/third_party/go.tools/godoc/static/dirlist.html
@@ -0,0 +1,31 @@
+<!--
+	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.
+-->
+
+<p>
+<table class="layout">
+<tr>
+	<th align="left">File</th>
+	<td width="25">&nbsp;</td>
+	<th align="right">Bytes</th>
+	<td width="25">&nbsp;</td>
+	<th align="left">Modified</th>
+</tr>
+<tr>
+	<td><a href="..">..</a></td>
+</tr>
+{{range .}}
+<tr>
+	{{$name_html := fileInfoName . | html}}
+	<td align="left"><a href="{{$name_html}}">{{$name_html}}</a></td>
+	<td></td>
+	<td align="right">{{html .Size}}</td>
+	<td></td>
+	<td align="left">{{fileInfoTime . | html}}</td>
+</tr>
+{{end}}
+
+</table>
+</p>
diff --git a/third_party/go.tools/godoc/static/doc.go b/third_party/go.tools/godoc/static/doc.go
new file mode 100644
index 0000000..5ef96ae
--- /dev/null
+++ b/third_party/go.tools/godoc/static/doc.go
@@ -0,0 +1,8 @@
+// Copyright 2013 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 static exports a map of static file content that supports the godoc
+// user interface. The map should be used with the mapfs package, see
+// golang.org/x/tools/godoc/vfs/mapfs.
+package static
diff --git a/third_party/go.tools/godoc/static/error.html b/third_party/go.tools/godoc/static/error.html
new file mode 100644
index 0000000..7573aa2
--- /dev/null
+++ b/third_party/go.tools/godoc/static/error.html
@@ -0,0 +1,9 @@
+<!--
+	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.
+-->
+
+<p>
+<span class="alert" style="font-size:120%">{{html .}}</span>
+</p>
diff --git a/third_party/go.tools/godoc/static/example.html b/third_party/go.tools/godoc/static/example.html
new file mode 100644
index 0000000..cda2a84
--- /dev/null
+++ b/third_party/go.tools/godoc/static/example.html
@@ -0,0 +1,28 @@
+<div id="example_{{.Name}}" class="toggle">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Example{{example_suffix .Name}}</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Example{{example_suffix .Name}}</span></p>
+		{{with .Doc}}<p>{{html .}}</p>{{end}}
+		{{$output := .Output}}
+		{{with .Play}}
+			<div class="play">
+				<div class="input"><textarea class="code">{{html .}}</textarea></div>
+				<div class="output"><pre>{{html $output}}</pre></div>
+				<div class="buttons">
+					<a class="run" title="Run this code [shift-enter]">Run</a>
+					<a class="fmt" title="Format this code">Format</a>
+					<a class="share" title="Share this code">Share</a>
+				</div>
+			</div>
+		{{else}}
+			<p>Code:</p>
+			<pre class="code">{{.Code}}</pre>
+			{{with .Output}}
+			<p>Output:</p>
+			<pre class="output">{{html .}}</pre>
+			{{end}}
+		{{end}}
+	</div>
+</div>
diff --git a/third_party/go.tools/godoc/static/gen.go b/third_party/go.tools/godoc/static/gen.go
new file mode 100644
index 0000000..4226821
--- /dev/null
+++ b/third_party/go.tools/godoc/static/gen.go
@@ -0,0 +1,7 @@
+// Copyright 2014 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 static
+
+//go:generate go run makestatic.go
diff --git a/third_party/go.tools/godoc/static/godoc.html b/third_party/go.tools/godoc/static/godoc.html
new file mode 100644
index 0000000..c851c52
--- /dev/null
+++ b/third_party/go.tools/godoc/static/godoc.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+{{with .Tabtitle}}
+  <title>{{html .}} - The Go Programming Language</title>
+{{else}}
+  <title>The Go Programming Language</title>
+{{end}}
+<link type="text/css" rel="stylesheet" href="/lib/godoc/style.css">
+{{if .SearchBox}}
+<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
+{{end}}
+<link rel="stylesheet" href="/lib/godoc/jquery.treeview.css">
+<script type="text/javascript">window.initFuncs = [];</script>
+</head>
+<body>
+
+<div id='lowframe' style="position: fixed; bottom: 0; left: 0; height: 0; width: 100%; border-top: thin solid grey; background-color: white; overflow: auto;">
+...
+</div><!-- #lowframe -->
+
+<div id="topbar"{{if .Title}} class="wide"{{end}}><div class="container">
+
+<form method="GET" action="/search">
+<div id="menu">
+<a href="/doc/">Documents</a>
+<a href="/pkg/">Packages</a>
+<a href="/project/">The Project</a>
+<a href="/help/">Help</a>
+<a href="/blog/">Blog</a>
+{{if .Playground}}
+<a id="playgroundButton" href="http://play.golang.org/" title="Show Go Playground">Play</a>
+{{end}}
+<input type="text" id="search" name="q" class="inactive" value="Search" placeholder="Search">
+</div>
+<div id="heading"><a href="/">The Go Programming Language</a></div>
+</form>
+
+</div></div>
+
+{{if .Playground}}
+<div id="playground" class="play">
+	<div class="input"><textarea class="code">package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, 世界")
+}</textarea></div>
+	<div class="output"></div>
+	<div class="buttons">
+		<a class="run" title="Run this code [shift-enter]">Run</a>
+		<a class="fmt" title="Format this code">Format</a>
+		<a class="share" title="Share this code">Share</a>
+	</div>
+</div>
+{{end}}
+
+<div id="page"{{if .Title}} class="wide"{{end}}>
+<div class="container">
+
+{{with .Title}}
+  <h1>{{html .}}</h1>
+{{end}}
+{{with .Subtitle}}
+  <h2>{{html .}}</h2>
+{{end}}
+
+{{/* The Table of Contents is automatically inserted in this <div>.
+     Do not delete this <div>. */}}
+<div id="nav"></div>
+
+{{/* Body is HTML-escaped elsewhere */}}
+{{printf "%s" .Body}}
+
+<div id="footer">
+Build version {{html .Version}}.<br>
+Except as <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
+the content of this page is licensed under the
+Creative Commons Attribution 3.0 License,
+and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
+<a href="/doc/tos.html">Terms of Service</a> | 
+<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
+</div>
+
+</div><!-- .container -->
+</div><!-- #page -->
+
+<!-- TODO(adonovan): load these from <head> using "defer" attribute? -->
+<script type="text/javascript" src="/lib/godoc/jquery.js"></script>
+<script type="text/javascript" src="/lib/godoc/jquery.treeview.js"></script>
+<script type="text/javascript" src="/lib/godoc/jquery.treeview.edit.js"></script>
+
+{{if .Playground}}
+<script type="text/javascript" src="/lib/godoc/playground.js"></script>
+{{end}}
+<script type="text/javascript" src="/lib/godoc/godocs.js"></script>
+
+</body>
+</html>
+
diff --git a/third_party/go.tools/godoc/static/godocs.js b/third_party/go.tools/godoc/static/godocs.js
new file mode 100644
index 0000000..9486d2c
--- /dev/null
+++ b/third_party/go.tools/godoc/static/godocs.js
@@ -0,0 +1,505 @@
+// 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.
+
+/* A little code to ease navigation of these documents.
+ *
+ * On window load we:
+ *  + Bind search box hint placeholder show/hide events (bindSearchEvents)
+ *  + Generate a table of contents (generateTOC)
+ *  + Bind foldable sections (bindToggles)
+ *  + Bind links to foldable sections (bindToggleLinks)
+ */
+
+(function() {
+'use strict';
+
+function bindSearchEvents() {
+
+  var search = $('#search');
+  if (search.length === 0) {
+    return; // no search box
+  }
+
+  function clearInactive() {
+    if (search.is('.inactive')) {
+      search.val('');
+      search.removeClass('inactive');
+    }
+  }
+
+  function restoreInactive() {
+    if (search.val() !== '') {
+      return;
+    }
+    search.val(search.attr('placeholder'));
+    search.addClass('inactive');
+  }
+
+  search.on('focus', clearInactive);
+  search.on('blur', restoreInactive);
+
+  restoreInactive();
+}
+
+/* Generates a table of contents: looks for h2 and h3 elements and generates
+ * links. "Decorates" the element with id=="nav" with this table of contents.
+ */
+function generateTOC() {
+  if ($('#manual-nav').length > 0) {
+    return;
+  }
+
+  var nav = $('#nav');
+  if (nav.length === 0) {
+    return;
+  }
+
+  var toc_items = [];
+  $(nav).nextAll('h2, h3').each(function() {
+    var node = this;
+    if (node.id == '')
+      node.id = 'tmp_' + toc_items.length;
+    var link = $('<a/>').attr('href', '#' + node.id).text($(node).text());
+    var item;
+    if ($(node).is('h2')) {
+      item = $('<dt/>');
+    } else { // h3
+      item = $('<dd/>');
+    }
+    item.append(link);
+    toc_items.push(item);
+  });
+  if (toc_items.length <= 1) {
+    return;
+  }
+
+  var dl1 = $('<dl/>');
+  var dl2 = $('<dl/>');
+
+  var split_index = (toc_items.length / 2) + 1;
+  if (split_index < 8) {
+    split_index = toc_items.length;
+  }
+  for (var i = 0; i < split_index; i++) {
+    dl1.append(toc_items[i]);
+  }
+  for (/* keep using i */; i < toc_items.length; i++) {
+    dl2.append(toc_items[i]);
+  }
+
+  var tocTable = $('<table class="unruled"/>').appendTo(nav);
+  var tocBody = $('<tbody/>').appendTo(tocTable);
+  var tocRow = $('<tr/>').appendTo(tocBody);
+
+  // 1st column
+  $('<td class="first"/>').appendTo(tocRow).append(dl1);
+  // 2nd column
+  $('<td/>').appendTo(tocRow).append(dl2);
+}
+
+function bindToggle(el) {
+  $('.toggleButton', el).click(function() {
+    if ($(el).is('.toggle')) {
+      $(el).addClass('toggleVisible').removeClass('toggle');
+    } else {
+      $(el).addClass('toggle').removeClass('toggleVisible');
+    }
+  });
+}
+function bindToggles(selector) {
+  $(selector).each(function(i, el) {
+    bindToggle(el);
+  });
+}
+
+function bindToggleLink(el, prefix) {
+  $(el).click(function() {
+    var href = $(el).attr('href');
+    var i = href.indexOf('#'+prefix);
+    if (i < 0) {
+      return;
+    }
+    var id = '#' + prefix + href.slice(i+1+prefix.length);
+    if ($(id).is('.toggle')) {
+      $(id).find('.toggleButton').first().click();
+    }
+  });
+}
+function bindToggleLinks(selector, prefix) {
+  $(selector).each(function(i, el) {
+    bindToggleLink(el, prefix);
+  });
+}
+
+function setupDropdownPlayground() {
+  if (!$('#page').is('.wide')) {
+    return; // don't show on front page
+  }
+  var button = $('#playgroundButton');
+  var div = $('#playground');
+  var setup = false;
+  button.toggle(function() {
+    button.addClass('active');
+    div.show();
+    if (setup) {
+      return;
+    }
+    setup = true;
+    playground({
+      'codeEl': $('.code', div),
+      'outputEl': $('.output', div),
+      'runEl': $('.run', div),
+      'fmtEl': $('.fmt', div),
+      'shareEl': $('.share', div),
+      'shareRedirect': '//play.golang.org/p/'
+    });
+  },
+  function() {
+    button.removeClass('active');
+    div.hide();
+  });
+  button.show();
+  $('#menu').css('min-width', '+=60');
+}
+
+function setupInlinePlayground() {
+	'use strict';
+	// Set up playground when each element is toggled.
+	$('div.play').each(function (i, el) {
+		// Set up playground for this example.
+		var setup = function() {
+			var code = $('.code', el);
+			playground({
+				'codeEl':   code,
+				'outputEl': $('.output', el),
+				'runEl':    $('.run', el),
+				'fmtEl':    $('.fmt', el),
+				'shareEl':  $('.share', el),
+				'shareRedirect': '//play.golang.org/p/'
+			});
+
+			// Make the code textarea resize to fit content.
+			var resize = function() {
+				code.height(0);
+				var h = code[0].scrollHeight;
+				code.height(h+20); // minimize bouncing.
+				code.closest('.input').height(h);
+			};
+			code.on('keydown', resize);
+			code.on('keyup', resize);
+			code.keyup(); // resize now.
+		};
+		
+		// If example already visible, set up playground now.
+		if ($(el).is(':visible')) {
+			setup();
+			return;
+		}
+
+		// Otherwise, set up playground when example is expanded.
+		var built = false;
+		$(el).closest('.toggle').click(function() {
+			// Only set up once.
+			if (!built) {
+				setup();
+				built = true;
+			}
+		});
+	});
+}
+
+// fixFocus tries to put focus to div#page so that keyboard navigation works.
+function fixFocus() {
+  var page = $('div#page');
+  var topbar = $('div#topbar');
+  page.css('outline', 0); // disable outline when focused
+  page.attr('tabindex', -1); // and set tabindex so that it is focusable
+  $(window).resize(function (evt) {
+    // only focus page when the topbar is at fixed position (that is, it's in
+    // front of page, and keyboard event will go to the former by default.)
+    // by focusing page, keyboard event will go to page so that up/down arrow,
+    // space, etc. will work as expected.
+    if (topbar.css('position') == "fixed")
+      page.focus();
+  }).resize();
+}
+
+function toggleHash() {
+    var hash = $(window.location.hash);
+    if (hash.is('.toggle')) {
+      hash.find('.toggleButton').first().click();
+    }
+}
+
+$(document).ready(function() {
+  bindSearchEvents();
+  generateTOC();
+  bindToggles(".toggle");
+  bindToggles(".toggleVisible");
+  bindToggleLinks(".exampleLink", "example_");
+  bindToggleLinks(".overviewLink", "");
+  bindToggleLinks(".examplesLink", "");
+  bindToggleLinks(".indexLink", "");
+  setupDropdownPlayground();
+  setupInlinePlayground();
+  fixFocus();
+  setupTypeInfo();
+  setupCallgraphs();
+  toggleHash();
+
+  // godoc.html defines window.initFuncs in the <head> tag, and root.html and
+  // codewalk.js push their on-page-ready functions to the list.
+  // We execute those functions here, to avoid loading jQuery until the page
+  // content is loaded.
+  for (var i = 0; i < window.initFuncs.length; i++) window.initFuncs[i]();
+});
+
+// -- analysis ---------------------------------------------------------
+
+// escapeHTML returns HTML for s, with metacharacters quoted.
+// It is safe for use in both elements and attributes
+// (unlike the "set innerText, read innerHTML" trick).
+function escapeHTML(s) {
+    return s.replace(/&/g, '&amp;').
+             replace(/\"/g, '&quot;').
+             replace(/\'/g, '&#39;').
+             replace(/</g, '&lt;').
+             replace(/>/g, '&gt;');
+}
+
+// makeAnchor returns HTML for an <a> element, given an anchorJSON object.
+function makeAnchor(json) {
+  var html = escapeHTML(json.Text);
+  if (json.Href != "") {
+      html = "<a href='" + escapeHTML(json.Href) + "'>" + html + "</a>";
+  }
+  return html;
+}
+
+function showLowFrame(html) {
+  var lowframe = document.getElementById('lowframe');
+  lowframe.style.height = "200px";
+  lowframe.innerHTML = "<p style='text-align: left;'>" + html + "</p>\n" +
+      "<div onclick='hideLowFrame()' style='position: absolute; top: 0; right: 0; cursor: pointer;'>✘</div>"
+};
+
+document.hideLowFrame = function() {
+  var lowframe = document.getElementById('lowframe');
+  lowframe.style.height = "0px";
+}
+
+// onClickCallers is the onclick action for the 'func' tokens of a
+// function declaration.
+document.onClickCallers = function(index) {
+  var data = document.ANALYSIS_DATA[index]
+  if (data.Callers.length == 1 && data.Callers[0].Sites.length == 1) {
+    document.location = data.Callers[0].Sites[0].Href; // jump to sole caller
+    return;
+  }
+
+  var html = "Callers of <code>" + escapeHTML(data.Callee) + "</code>:<br/>\n";
+  for (var i = 0; i < data.Callers.length; i++) {
+    var caller = data.Callers[i];
+    html += "<code>" + escapeHTML(caller.Func) + "</code>";
+    var sites = caller.Sites;
+    if (sites != null && sites.length > 0) {
+      html += " at line ";
+      for (var j = 0; j < sites.length; j++) {
+        if (j > 0) {
+          html += ", ";
+        }
+        html += "<code>" + makeAnchor(sites[j]) + "</code>";
+      }
+    }
+    html += "<br/>\n";
+  }
+  showLowFrame(html);
+};
+
+// onClickCallees is the onclick action for the '(' token of a function call.
+document.onClickCallees = function(index) {
+  var data = document.ANALYSIS_DATA[index]
+  if (data.Callees.length == 1) {
+    document.location = data.Callees[0].Href; // jump to sole callee
+    return;
+  }
+
+  var html = "Callees of this " + escapeHTML(data.Descr) + ":<br/>\n";
+  for (var i = 0; i < data.Callees.length; i++) {
+    html += "<code>" + makeAnchor(data.Callees[i]) + "</code><br/>\n";
+  }
+  showLowFrame(html);
+};
+
+// onClickTypeInfo is the onclick action for identifiers declaring a named type.
+document.onClickTypeInfo = function(index) {
+  var data = document.ANALYSIS_DATA[index];
+  var html = "Type <code>" + data.Name + "</code>: " +
+  "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<small>(size=" + data.Size + ", align=" + data.Align + ")</small><br/>\n";
+  html += implementsHTML(data);
+  html += methodsetHTML(data);
+  showLowFrame(html);
+};
+
+// implementsHTML returns HTML for the implements relation of the
+// specified TypeInfoJSON value.
+function implementsHTML(info) {
+  var html = "";
+  if (info.ImplGroups != null) {
+    for (var i = 0; i < info.ImplGroups.length; i++) {
+      var group = info.ImplGroups[i];
+      var x = "<code>" + escapeHTML(group.Descr) + "</code> ";
+      for (var j = 0; j < group.Facts.length; j++) {
+        var fact = group.Facts[j];
+        var y = "<code>" + makeAnchor(fact.Other) + "</code>";
+        if (fact.ByKind != null) {
+          html += escapeHTML(fact.ByKind) + " type " + y + " implements " + x;
+        } else {
+          html += x + " implements " + y;
+        }
+        html += "<br/>\n";
+      }
+    }
+  }
+  return html;
+}
+
+
+// methodsetHTML returns HTML for the methodset of the specified
+// TypeInfoJSON value.
+function methodsetHTML(info) {
+  var html = "";
+  if (info.Methods != null) {
+    for (var i = 0; i < info.Methods.length; i++) {
+      html += "<code>" + makeAnchor(info.Methods[i]) + "</code><br/>\n";
+    }
+  }
+  return html;
+}
+
+// onClickComm is the onclick action for channel "make" and "<-"
+// send/receive tokens.
+document.onClickComm = function(index) {
+  var ops = document.ANALYSIS_DATA[index].Ops
+  if (ops.length == 1) {
+    document.location = ops[0].Op.Href; // jump to sole element
+    return;
+  }
+
+  var html = "Operations on this channel:<br/>\n";
+  for (var i = 0; i < ops.length; i++) {
+    html += makeAnchor(ops[i].Op) + " by <code>" + escapeHTML(ops[i].Fn) + "</code><br/>\n";
+  }
+  if (ops.length == 0) {
+    html += "(none)<br/>\n";
+  }
+  showLowFrame(html);
+};
+
+$(window).load(function() {
+    // Scroll window so that first selection is visible.
+    // (This means we don't need to emit id='L%d' spans for each line.)
+    // TODO(adonovan): ideally, scroll it so that it's under the pointer,
+    // but I don't know how to get the pointer y coordinate.
+    var elts = document.getElementsByClassName("selection");
+    if (elts.length > 0) {
+	elts[0].scrollIntoView()
+    }
+});
+
+// setupTypeInfo populates the "Implements" and "Method set" toggle for
+// each type in the package doc.
+function setupTypeInfo() {
+  for (var i in document.ANALYSIS_DATA) {
+    var data = document.ANALYSIS_DATA[i];
+
+    var el = document.getElementById("implements-" + i);
+    if (el != null) {
+      // el != null => data is TypeInfoJSON.
+      if (data.ImplGroups != null) {
+        el.innerHTML = implementsHTML(data);
+        el.parentNode.parentNode.style.display = "block";
+      }
+    }
+
+    var el = document.getElementById("methodset-" + i);
+    if (el != null) {
+      // el != null => data is TypeInfoJSON.
+      if (data.Methods != null) {
+        el.innerHTML = methodsetHTML(data);
+        el.parentNode.parentNode.style.display = "block";
+      }
+    }
+  }
+}
+
+function setupCallgraphs() {
+  if (document.CALLGRAPH == null) {
+    return
+  }
+  document.getElementById("pkg-callgraph").style.display = "block";
+
+  var treeviews = document.getElementsByClassName("treeview");
+  for (var i = 0; i < treeviews.length; i++) {
+    var tree = treeviews[i];
+    if (tree.id == null || tree.id.indexOf("callgraph-") != 0) {
+      continue;
+    }
+    var id = tree.id.substring("callgraph-".length);
+    $(tree).treeview({collapsed: true, animated: "fast"});
+    document.cgAddChildren(tree, tree, [id]);
+    tree.parentNode.parentNode.style.display = "block";
+  }
+}
+
+document.cgAddChildren = function(tree, ul, indices) {
+  if (indices != null) {
+    for (var i = 0; i < indices.length; i++) {
+      var li = cgAddChild(tree, ul, document.CALLGRAPH[indices[i]]);
+      if (i == indices.length - 1) {
+        $(li).addClass("last");
+      }
+    }
+  }
+  $(tree).treeview({animated: "fast", add: ul});
+}
+
+// cgAddChild adds an <li> element for document.CALLGRAPH node cgn to
+// the parent <ul> element ul. tree is the tree's root <ul> element.
+function cgAddChild(tree, ul, cgn) {
+   var li = document.createElement("li");
+   ul.appendChild(li);
+   li.className = "closed";
+
+   var code = document.createElement("code");
+
+   if (cgn.Callees != null) {
+     $(li).addClass("expandable");
+
+     // Event handlers and innerHTML updates don't play nicely together,
+     // hence all this explicit DOM manipulation.
+     var hitarea = document.createElement("div");
+     hitarea.className = "hitarea expandable-hitarea";
+     li.appendChild(hitarea);
+
+     li.appendChild(code);
+
+     var childUL = document.createElement("ul");
+     li.appendChild(childUL);
+     childUL.setAttribute('style', "display: none;");
+
+     var onClick = function() {
+       document.cgAddChildren(tree, childUL, cgn.Callees);
+       hitarea.removeEventListener('click', onClick)
+     };
+     hitarea.addEventListener('click', onClick);
+
+   } else {
+     li.appendChild(code);
+   }
+   code.innerHTML += "&nbsp;" + makeAnchor(cgn.Func);
+   return li
+}
+
+})();
diff --git a/third_party/go.tools/godoc/static/images/minus.gif b/third_party/go.tools/godoc/static/images/minus.gif
new file mode 100644
index 0000000..47fb7b7
--- /dev/null
+++ b/third_party/go.tools/godoc/static/images/minus.gif
Binary files differ
diff --git a/third_party/go.tools/godoc/static/images/plus.gif b/third_party/go.tools/godoc/static/images/plus.gif
new file mode 100644
index 0000000..6906621
--- /dev/null
+++ b/third_party/go.tools/godoc/static/images/plus.gif
Binary files differ
diff --git a/third_party/go.tools/godoc/static/images/treeview-black-line.gif b/third_party/go.tools/godoc/static/images/treeview-black-line.gif
new file mode 100644
index 0000000..e549687
--- /dev/null
+++ b/third_party/go.tools/godoc/static/images/treeview-black-line.gif
Binary files differ
diff --git a/third_party/go.tools/godoc/static/images/treeview-black.gif b/third_party/go.tools/godoc/static/images/treeview-black.gif
new file mode 100644
index 0000000..b718d17
--- /dev/null
+++ b/third_party/go.tools/godoc/static/images/treeview-black.gif
Binary files differ
diff --git a/third_party/go.tools/godoc/static/images/treeview-default-line.gif b/third_party/go.tools/godoc/static/images/treeview-default-line.gif
new file mode 100644
index 0000000..37114d3
--- /dev/null
+++ b/third_party/go.tools/godoc/static/images/treeview-default-line.gif
Binary files differ
diff --git a/third_party/go.tools/godoc/static/images/treeview-default.gif b/third_party/go.tools/godoc/static/images/treeview-default.gif
new file mode 100644
index 0000000..76eee60
--- /dev/null
+++ b/third_party/go.tools/godoc/static/images/treeview-default.gif
Binary files differ
diff --git a/third_party/go.tools/godoc/static/images/treeview-gray-line.gif b/third_party/go.tools/godoc/static/images/treeview-gray-line.gif
new file mode 100644
index 0000000..3760044
--- /dev/null
+++ b/third_party/go.tools/godoc/static/images/treeview-gray-line.gif
Binary files differ
diff --git a/third_party/go.tools/godoc/static/images/treeview-gray.gif b/third_party/go.tools/godoc/static/images/treeview-gray.gif
new file mode 100644
index 0000000..cfdf1ab
--- /dev/null
+++ b/third_party/go.tools/godoc/static/images/treeview-gray.gif
Binary files differ
diff --git a/third_party/go.tools/godoc/static/implements.html b/third_party/go.tools/godoc/static/implements.html
new file mode 100644
index 0000000..5f65b86
--- /dev/null
+++ b/third_party/go.tools/godoc/static/implements.html
@@ -0,0 +1,9 @@
+<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Implements</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Implements</span></p>
+		<div style="margin-left: 1in" id='implements-{{.Index}}'>...</div>
+	</div>
+</div>
diff --git a/third_party/go.tools/godoc/static/jquery.js b/third_party/go.tools/godoc/static/jquery.js
new file mode 100644
index 0000000..bc3fbc8
--- /dev/null
+++ b/third_party/go.tools/godoc/static/jquery.js
@@ -0,0 +1,2 @@
+/*! jQuery v1.8.2 jquery.com | jquery.org/license */
+(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(" ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);
\ No newline at end of file
diff --git a/third_party/go.tools/godoc/static/jquery.treeview.css b/third_party/go.tools/godoc/static/jquery.treeview.css
new file mode 100644
index 0000000..ac33361
--- /dev/null
+++ b/third_party/go.tools/godoc/static/jquery.treeview.css
@@ -0,0 +1,76 @@
+/* https://github.com/jzaefferer/jquery-treeview/blob/master/jquery.treeview.css */
+/* License: MIT. */
+.treeview, .treeview ul {
+	padding: 0;
+	margin: 0;
+	list-style: none;
+}
+
+.treeview ul {
+	background-color: white;
+	margin-top: 4px;
+}
+
+.treeview .hitarea {
+	background: url(images/treeview-default.gif) -64px -25px no-repeat;
+	height: 16px;
+	width: 16px;
+	margin-left: -16px;
+	float: left;
+	cursor: pointer;
+}
+/* fix for IE6 */
+* html .hitarea {
+	display: inline;
+	float:none;
+}
+
+.treeview li {
+	margin: 0;
+	padding: 3px 0pt 3px 16px;
+}
+
+.treeview a.selected {
+	background-color: #eee;
+}
+
+#treecontrol { margin: 1em 0; display: none; }
+
+.treeview .hover { color: red; cursor: pointer; }
+
+.treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; }
+.treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }
+
+.treeview .expandable-hitarea { background-position: -80px -3px; }
+
+.treeview li.last { background-position: 0 -1766px }
+.treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(images/treeview-default.gif); }
+.treeview li.lastCollapsable { background-position: 0 -111px }
+.treeview li.lastExpandable { background-position: -32px -67px }
+
+.treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; }
+
+.treeview-red li { background-image: url(images/treeview-red-line.gif); }
+.treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); }
+
+.treeview-black li { background-image: url(images/treeview-black-line.gif); }
+.treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); }
+
+.treeview-gray li { background-image: url(images/treeview-gray-line.gif); }
+.treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); }
+
+.treeview-famfamfam li { background-image: url(images/treeview-famfamfam-line.gif); }
+.treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); }
+
+.treeview .placeholder {
+	background: url(images/ajax-loader.gif) 0 0 no-repeat;
+	height: 16px;
+	width: 16px;
+	display: block;
+}
+
+.filetree li { padding: 3px 0 2px 16px; }
+.filetree span.folder, .filetree span.file { padding: 1px 0 1px 16px; display: block; }
+.filetree span.folder { background: url(images/folder.gif) 0 0 no-repeat; }
+.filetree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }
+.filetree span.file { background: url(images/file.gif) 0 0 no-repeat; }
diff --git a/third_party/go.tools/godoc/static/jquery.treeview.edit.js b/third_party/go.tools/godoc/static/jquery.treeview.edit.js
new file mode 100644
index 0000000..9895b02
--- /dev/null
+++ b/third_party/go.tools/godoc/static/jquery.treeview.edit.js
@@ -0,0 +1,39 @@
+/* https://github.com/jzaefferer/jquery-treeview/blob/master/jquery.treeview.edit.js */
+/* License: MIT. */
+(function($) {
+	var CLASSES = $.treeview.classes;
+	var proxied = $.fn.treeview;
+	$.fn.treeview = function(settings) {
+		settings = $.extend({}, settings);
+		if (settings.add) {
+			return this.trigger("add", [settings.add]);
+		}
+		if (settings.remove) {
+			return this.trigger("remove", [settings.remove]);
+		}
+		return proxied.apply(this, arguments).bind("add", function(event, branches) {
+			$(branches).prev()
+				.removeClass(CLASSES.last)
+				.removeClass(CLASSES.lastCollapsable)
+				.removeClass(CLASSES.lastExpandable)
+			.find(">.hitarea")
+				.removeClass(CLASSES.lastCollapsableHitarea)
+				.removeClass(CLASSES.lastExpandableHitarea);
+			$(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, $(this).data("toggler"));
+		}).bind("remove", function(event, branches) {
+			var prev = $(branches).prev();
+			var parent = $(branches).parent();
+			$(branches).remove();
+			prev.filter(":last-child").addClass(CLASSES.last)
+				.filter("." + CLASSES.expandable).replaceClass(CLASSES.last, CLASSES.lastExpandable).end()
+				.find(">.hitarea").replaceClass(CLASSES.expandableHitarea, CLASSES.lastExpandableHitarea).end()
+				.filter("." + CLASSES.collapsable).replaceClass(CLASSES.last, CLASSES.lastCollapsable).end()
+				.find(">.hitarea").replaceClass(CLASSES.collapsableHitarea, CLASSES.lastCollapsableHitarea);
+			if (parent.is(":not(:has(>))") && parent[0] != this) {
+				parent.parent().removeClass(CLASSES.collapsable).removeClass(CLASSES.expandable)
+				parent.siblings(".hitarea").andSelf().remove();
+			}
+		});
+	};
+	
+})(jQuery);
diff --git a/third_party/go.tools/godoc/static/jquery.treeview.js b/third_party/go.tools/godoc/static/jquery.treeview.js
new file mode 100644
index 0000000..356af23
--- /dev/null
+++ b/third_party/go.tools/godoc/static/jquery.treeview.js
@@ -0,0 +1,256 @@
+/*
+ * Treeview 1.4.1 - jQuery plugin to hide and show branches of a tree
+ * 
+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
+ * http://docs.jquery.com/Plugins/Treeview
+ *
+ * Copyright (c) 2007 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.treeview.js 5759 2008-07-01 07:50:28Z joern.zaefferer $
+ *
+ */
+
+;(function($) {
+
+	// TODO rewrite as a widget, removing all the extra plugins
+	$.extend($.fn, {
+		swapClass: function(c1, c2) {
+			var c1Elements = this.filter('.' + c1);
+			this.filter('.' + c2).removeClass(c2).addClass(c1);
+			c1Elements.removeClass(c1).addClass(c2);
+			return this;
+		},
+		replaceClass: function(c1, c2) {
+			return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
+		},
+		hoverClass: function(className) {
+			className = className || "hover";
+			return this.hover(function() {
+				$(this).addClass(className);
+			}, function() {
+				$(this).removeClass(className);
+			});
+		},
+		heightToggle: function(animated, callback) {
+			animated ?
+				this.animate({ height: "toggle" }, animated, callback) :
+				this.each(function(){
+					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+					if(callback)
+						callback.apply(this, arguments);
+				});
+		},
+		heightHide: function(animated, callback) {
+			if (animated) {
+				this.animate({ height: "hide" }, animated, callback);
+			} else {
+				this.hide();
+				if (callback)
+					this.each(callback);				
+			}
+		},
+		prepareBranches: function(settings) {
+			if (!settings.prerendered) {
+				// mark last tree items
+				this.filter(":last-child:not(ul)").addClass(CLASSES.last);
+				// collapse whole tree, or only those marked as closed, anyway except those marked as open
+				this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
+			}
+			// return all items with sublists
+			return this.filter(":has(>ul)");
+		},
+		applyClasses: function(settings, toggler) {
+			// TODO use event delegation
+			this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) {
+				// don't handle click events on children, eg. checkboxes
+				if ( this == event.target )
+					toggler.apply($(this).next());
+			}).add( $("a", this) ).hoverClass();
+			
+			if (!settings.prerendered) {
+				// handle closed ones first
+				this.filter(":has(>ul:hidden)")
+						.addClass(CLASSES.expandable)
+						.replaceClass(CLASSES.last, CLASSES.lastExpandable);
+						
+				// handle open ones
+				this.not(":has(>ul:hidden)")
+						.addClass(CLASSES.collapsable)
+						.replaceClass(CLASSES.last, CLASSES.lastCollapsable);
+						
+	            // create hitarea if not present
+				var hitarea = this.find("div." + CLASSES.hitarea);
+				if (!hitarea.length)
+					hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea);
+				hitarea.removeClass().addClass(CLASSES.hitarea).each(function() {
+					var classes = "";
+					$.each($(this).parent().attr("class").split(" "), function() {
+						classes += this + "-hitarea ";
+					});
+					$(this).addClass( classes );
+				})
+			}
+			
+			// apply event to hitarea
+			this.find("div." + CLASSES.hitarea).click( toggler );
+		},
+		treeview: function(settings) {
+			
+			settings = $.extend({
+				cookieId: "treeview"
+			}, settings);
+			
+			if ( settings.toggle ) {
+				var callback = settings.toggle;
+				settings.toggle = function() {
+					return callback.apply($(this).parent()[0], arguments);
+				};
+			}
+		
+			// factory for treecontroller
+			function treeController(tree, control) {
+				// factory for click handlers
+				function handler(filter) {
+					return function() {
+						// reuse toggle event handler, applying the elements to toggle
+						// start searching for all hitareas
+						toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
+							// for plain toggle, no filter is provided, otherwise we need to check the parent element
+							return filter ? $(this).parent("." + filter).length : true;
+						}) );
+						return false;
+					};
+				}
+				// click on first element to collapse tree
+				$("a:eq(0)", control).click( handler(CLASSES.collapsable) );
+				// click on second to expand tree
+				$("a:eq(1)", control).click( handler(CLASSES.expandable) );
+				// click on third to toggle tree
+				$("a:eq(2)", control).click( handler() ); 
+			}
+		
+			// handle toggle event
+			function toggler() {
+				$(this)
+					.parent()
+					// swap classes for hitarea
+					.find(">.hitarea")
+						.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+						.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+					.end()
+					// swap classes for parent li
+					.swapClass( CLASSES.collapsable, CLASSES.expandable )
+					.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+					// find child lists
+					.find( ">ul" )
+					// toggle them
+					.heightToggle( settings.animated, settings.toggle );
+				if ( settings.unique ) {
+					$(this).parent()
+						.siblings()
+						// swap classes for hitarea
+						.find(">.hitarea")
+							.replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+							.replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+						.end()
+						.replaceClass( CLASSES.collapsable, CLASSES.expandable )
+						.replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+						.find( ">ul" )
+						.heightHide( settings.animated, settings.toggle );
+				}
+			}
+			this.data("toggler", toggler);
+			
+			function serialize() {
+				function binary(arg) {
+					return arg ? 1 : 0;
+				}
+				var data = [];
+				branches.each(function(i, e) {
+					data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
+				});
+				$.cookie(settings.cookieId, data.join(""), settings.cookieOptions );
+			}
+			
+			function deserialize() {
+				var stored = $.cookie(settings.cookieId);
+				if ( stored ) {
+					var data = stored.split("");
+					branches.each(function(i, e) {
+						$(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
+					});
+				}
+			}
+			
+			// add treeview class to activate styles
+			this.addClass("treeview");
+			
+			// prepare branches and find all tree items with child lists
+			var branches = this.find("li").prepareBranches(settings);
+			
+			switch(settings.persist) {
+			case "cookie":
+				var toggleCallback = settings.toggle;
+				settings.toggle = function() {
+					serialize();
+					if (toggleCallback) {
+						toggleCallback.apply(this, arguments);
+					}
+				};
+				deserialize();
+				break;
+			case "location":
+				var current = this.find("a").filter(function() {
+					return this.href.toLowerCase() == location.href.toLowerCase();
+				});
+				if ( current.length ) {
+					// TODO update the open/closed classes
+					var items = current.addClass("selected").parents("ul, li").add( current.next() ).show();
+					if (settings.prerendered) {
+						// if prerendered is on, replicate the basic class swapping
+						items.filter("li")
+							.swapClass( CLASSES.collapsable, CLASSES.expandable )
+							.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+							.find(">.hitarea")
+								.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+								.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea );
+					}
+				}
+				break;
+			}
+			
+			branches.applyClasses(settings, toggler);
+				
+			// if control option is set, create the treecontroller and show it
+			if ( settings.control ) {
+				treeController(this, settings.control);
+				$(settings.control).show();
+			}
+			
+			return this;
+		}
+	});
+	
+	// classes used by the plugin
+	// need to be styled via external stylesheet, see first example
+	$.treeview = {};
+	var CLASSES = ($.treeview.classes = {
+		open: "open",
+		closed: "closed",
+		expandable: "expandable",
+		expandableHitarea: "expandable-hitarea",
+		lastExpandableHitarea: "lastExpandable-hitarea",
+		collapsable: "collapsable",
+		collapsableHitarea: "collapsable-hitarea",
+		lastCollapsableHitarea: "lastCollapsable-hitarea",
+		lastCollapsable: "lastCollapsable",
+		lastExpandable: "lastExpandable",
+		last: "last",
+		hitarea: "hitarea"
+	});
+	
+})(jQuery);
diff --git a/third_party/go.tools/godoc/static/makestatic.go b/third_party/go.tools/godoc/static/makestatic.go
new file mode 100644
index 0000000..b3b9c5f
--- /dev/null
+++ b/third_party/go.tools/godoc/static/makestatic.go
@@ -0,0 +1,120 @@
+// Copyright 2013 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.
+
+// +build ignore
+
+// Command bake reads a set of files and writes a Go source file to "static.go"
+// that declares a map of string constants containing contents of the input files.
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"unicode/utf8"
+)
+
+var files = []string{
+	"analysis/call3.png",
+	"analysis/call-eg.png",
+	"analysis/callers1.png",
+	"analysis/callers2.png",
+	"analysis/chan1.png",
+	"analysis/chan2a.png",
+	"analysis/chan2b.png",
+	"analysis/error1.png",
+	"analysis/help.html",
+	"analysis/ident-def.png",
+	"analysis/ident-field.png",
+	"analysis/ident-func.png",
+	"analysis/ipcg-func.png",
+	"analysis/ipcg-pkg.png",
+	"analysis/typeinfo-pkg.png",
+	"analysis/typeinfo-src.png",
+	"callgraph.html",
+	"codewalk.html",
+	"codewalkdir.html",
+	"dirlist.html",
+	"error.html",
+	"example.html",
+	"godoc.html",
+	"godocs.js",
+	"images/minus.gif",
+	"images/plus.gif",
+	"images/treeview-black-line.gif",
+	"images/treeview-black.gif",
+	"images/treeview-default-line.gif",
+	"images/treeview-default.gif",
+	"images/treeview-gray-line.gif",
+	"images/treeview-gray.gif",
+	"implements.html",
+	"jquery.js",
+	"jquery.treeview.css",
+	"jquery.treeview.edit.js",
+	"jquery.treeview.js",
+	"methodset.html",
+	"opensearch.xml",
+	"package.html",
+	"package.txt",
+	"play.js",
+	"playground.js",
+	"search.html",
+	"search.txt",
+	"searchcode.html",
+	"searchdoc.html",
+	"searchtxt.html",
+	"style.css",
+}
+
+func main() {
+	if err := bake(); err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+}
+
+func bake() error {
+	f, err := os.Create("static.go")
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+	w := bufio.NewWriter(f)
+	fmt.Fprintf(w, "%v\n\npackage static\n\n", warning)
+	fmt.Fprintf(w, "var Files = map[string]string{\n")
+	for _, fn := range files {
+		b, err := ioutil.ReadFile(fn)
+		if err != nil {
+			return err
+		}
+		fmt.Fprintf(w, "\t%q: ", fn)
+		if utf8.Valid(b) {
+			fmt.Fprintf(w, "`%s`", sanitize(b))
+		} else {
+			fmt.Fprintf(w, "%q", b)
+		}
+		fmt.Fprintln(w, ",\n")
+	}
+	fmt.Fprintln(w, "}")
+	if err := w.Flush(); err != nil {
+		return err
+	}
+	return f.Close()
+}
+
+// sanitize prepares a valid UTF-8 string as a raw string constant.
+func sanitize(b []byte) []byte {
+	// Replace ` with `+"`"+`
+	b = bytes.Replace(b, []byte("`"), []byte("`+\"`\"+`"), -1)
+
+	// Replace BOM with `+"\xEF\xBB\xBF"+`
+	// (A BOM is valid UTF-8 but not permitted in Go source files.
+	// I wouldn't bother handling this, but for some insane reason
+	// jquery.js has a BOM somewhere in the middle.)
+	return bytes.Replace(b, []byte("\xEF\xBB\xBF"), []byte("`+\"\\xEF\\xBB\\xBF\"+`"), -1)
+}
+
+const warning = "// DO NOT EDIT ** This file was generated with the bake tool ** DO NOT EDIT //"
diff --git a/third_party/go.tools/godoc/static/methodset.html b/third_party/go.tools/godoc/static/methodset.html
new file mode 100644
index 0000000..1b339e3
--- /dev/null
+++ b/third_party/go.tools/godoc/static/methodset.html
@@ -0,0 +1,9 @@
+<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Method set</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Method set</span></p>
+		<div style="margin-left: 1in" id='methodset-{{.Index}}'>...</div>
+	</div>
+</div>
diff --git a/third_party/go.tools/godoc/static/opensearch.xml b/third_party/go.tools/godoc/static/opensearch.xml
new file mode 100644
index 0000000..1b652db
--- /dev/null
+++ b/third_party/go.tools/godoc/static/opensearch.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <ShortName>godoc</ShortName>
+  <Description>The Go Programming Language</Description>
+  <Tags>go golang</Tags>
+  <Contact />
+  <Url type="text/html" template="{{.BaseURL}}/search?q={searchTerms}" />
+  <Image height="15" width="16" type="image/x-icon">/favicon.ico</Image>
+  <OutputEncoding>UTF-8</OutputEncoding>
+  <InputEncoding>UTF-8</InputEncoding>
+</OpenSearchDescription>
diff --git a/third_party/go.tools/godoc/static/package.html b/third_party/go.tools/godoc/static/package.html
new file mode 100644
index 0000000..cc69e61
--- /dev/null
+++ b/third_party/go.tools/godoc/static/package.html
@@ -0,0 +1,311 @@
+<!--
+	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.
+-->
+<!--
+	Note: Static (i.e., not template-generated) href and id
+	attributes start with "pkg-" to make it impossible for
+	them to conflict with generated attributes (some of which
+	correspond to Go identifiers).
+-->
+{{with .PDoc}}
+	<script type='text/javascript'>
+	document.ANALYSIS_DATA = {{$.AnalysisData}};
+	document.CALLGRAPH = {{$.CallGraph}};
+	</script>
+
+	{{if $.IsMain}}
+		{{/* command documentation */}}
+		{{comment_html .Doc}}
+	{{else}}
+		{{/* package documentation */}}
+		<div id="short-nav">
+			<dl>
+			<dd><code>import "{{html .ImportPath}}"</code></dd>
+			</dl>
+			<dl>
+			<dd><a href="#pkg-overview" class="overviewLink">Overview</a></dd>
+			<dd><a href="#pkg-index" class="indexLink">Index</a></dd>
+			{{if $.Examples}}
+				<dd><a href="#pkg-examples" class="examplesLink">Examples</a></dd>
+			{{end}}
+			{{if $.Dirs}}
+				<dd><a href="#pkg-subdirectories">Subdirectories</a></dd>
+			{{end}}
+			</dl>
+		</div>
+		<!-- The package's Name is printed as title by the top-level template -->
+		<div id="pkg-overview" class="toggleVisible">
+			<div class="collapsed">
+				<h2 class="toggleButton" title="Click to show Overview section">Overview ▹</h2>
+			</div>
+			<div class="expanded">
+				<h2 class="toggleButton" title="Click to hide Overview section">Overview ▾</h2>
+				{{comment_html .Doc}}
+			</div>
+		</div>
+		{{example_html $ ""}}
+
+		<div id="pkg-index" class="toggleVisible">
+		<div class="collapsed">
+			<h2 class="toggleButton" title="Click to show Index section">Index ▹</h2>
+		</div>
+		<div class="expanded">
+			<h2 class="toggleButton" title="Click to hide Index section">Index ▾</h2>
+
+		<!-- Table of contents for API; must be named manual-nav to turn off auto nav. -->
+			<div id="manual-nav">
+			<dl>
+			{{if .Consts}}
+				<dd><a href="#pkg-constants">Constants</a></dd>
+			{{end}}
+			{{if .Vars}}
+				<dd><a href="#pkg-variables">Variables</a></dd>
+			{{end}}
+			{{range .Funcs}}
+				{{$name_html := html .Name}}
+				<dd><a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+			{{end}}
+			{{range .Types}}
+				{{$tname_html := html .Name}}
+				<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
+				{{range .Funcs}}
+					{{$name_html := html .Name}}
+					<dd>&nbsp; &nbsp; <a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+				{{end}}
+				{{range .Methods}}
+					{{$name_html := html .Name}}
+					<dd>&nbsp; &nbsp; <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+				{{end}}
+			{{end}}
+			{{if $.Notes}}
+				{{range $marker, $item := $.Notes}}
+				<dd><a href="#pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</a></dd>
+				{{end}}
+			{{end}}
+			</dl>
+			</div><!-- #manual-nav -->
+
+		{{if $.Examples}}
+		<div id="pkg-examples">
+			<h4>Examples</h4>
+			<dl>
+			{{range $.Examples}}
+			<dd><a class="exampleLink" href="#example_{{.Name}}">{{example_name .Name}}</a></dd>
+			{{end}}
+			</dl>
+		</div>
+		{{end}}
+
+		{{with .Filenames}}
+			<h4>Package files</h4>
+			<p>
+			<span style="font-size:90%">
+			{{range .}}
+				<a href="{{.|srcLink|html}}">{{.|filename|html}}</a>
+			{{end}}
+			</span>
+			</p>
+		{{end}}
+		</div><!-- .expanded -->
+		</div><!-- #pkg-index -->
+
+		<div id="pkg-callgraph" class="toggle" style="display: none">
+		<div class="collapsed">
+			<h2 class="toggleButton" title="Click to show Internal Call Graph section">Internal call graph ▹</h2>
+		</div> <!-- .expanded -->
+		<div class="expanded">
+			<h2 class="toggleButton" title="Click to hide Internal Call Graph section">Internal call graph ▾</h2>
+			<p>
+			  In the call graph viewer below, each node
+			  is a function belonging to this package
+			  and its children are the functions it
+			  calls&mdash;perhaps dynamically.
+			</p>
+			<p>
+			  The root nodes are the entry points of the
+			  package: functions that may be called from
+			  outside the package.
+			  There may be non-exported or anonymous
+			  functions among them if they are called
+			  dynamically from another package.
+			</p>
+			<p>
+			  Click a node to visit that function's source code.
+			  From there you can visit its callers by
+			  clicking its declaring <code>func</code>
+			  token.
+			</p>
+			<p>
+			  Functions may be omitted if they were
+			  determined to be unreachable in the
+			  particular programs or tests that were
+			  analyzed.
+			</p>
+			<!-- Zero means show all package entry points. -->
+			<ul style="margin-left: 0.5in" id="callgraph-0" class="treeview"></ul>
+		</div>
+		</div> <!-- #pkg-callgraph -->
+
+		{{with .Consts}}
+			<h2 id="pkg-constants">Constants</h2>
+			{{range .}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+		{{end}}
+		{{with .Vars}}
+			<h2 id="pkg-variables">Variables</h2>
+			{{range .}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+		{{end}}
+		{{range .Funcs}}
+			{{/* Name is a string - no need for FSet */}}
+			{{$name_html := html .Name}}
+			<h2 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h2>
+			<pre>{{node_html $ .Decl true}}</pre>
+			{{comment_html .Doc}}
+			{{example_html $ .Name}}
+			{{callgraph_html $ "" .Name}}
+
+		{{end}}
+		{{range .Types}}
+			{{$tname := .Name}}
+			{{$tname_html := html .Name}}
+			<h2 id="{{$tname_html}}">type <a href="{{posLink_url $ .Decl}}">{{$tname_html}}</a></h2>
+			<pre>{{node_html $ .Decl true}}</pre>
+			{{comment_html .Doc}}
+
+			{{range .Consts}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+
+			{{range .Vars}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+
+			{{example_html $ $tname}}
+			{{implements_html $ $tname}}
+			{{methodset_html $ $tname}}
+
+			{{range .Funcs}}
+				{{$name_html := html .Name}}
+				<h3 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+				{{example_html $ .Name}}
+				{{callgraph_html $ "" .Name}}
+			{{end}}
+
+			{{range .Methods}}
+				{{$name_html := html .Name}}
+				<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+				{{$name := printf "%s_%s" $tname .Name}}
+				{{example_html $ $name}}
+				{{callgraph_html $ .Recv .Name}}
+			{{end}}
+		{{end}}
+	{{end}}
+
+	{{with $.Notes}}
+		{{range $marker, $content := .}}
+			<h2 id="pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</h2>
+			<ul style="list-style: none; padding: 0;">
+			{{range .}}
+			<li><a href="{{posLink_url $ .}}">&#x261e;</a> {{html .Body}}</li>
+			{{end}}
+			</ul>
+		{{end}}
+	{{end}}
+{{end}}
+
+{{with .PAst}}
+	{{range $filename, $ast := .}}
+		<a href="{{$filename|srcLink|html}}">{{$filename|filename|html}}</a>:<pre>{{node_html $ $ast false}}</pre>
+	{{end}}
+{{end}}
+
+{{with .Dirs}}
+	{{/* DirList entries are numbers and strings - no need for FSet */}}
+	{{if $.PDoc}}
+		<h2 id="pkg-subdirectories">Subdirectories</h2>
+	{{end}}
+	{{if eq $.Dirname "/src"}}
+		<div id="manual-nav">
+			<dl>
+				<dt><a href="#stdlib">Standard library</a></dt>
+				<dt><a href="#other">Other packages</a></dt>
+				<dd><a href="#subrepo">Sub-repositories</a></dd>
+				<dd><a href="#community">Community</a></dd>
+			</dl>
+		</div>
+		<h2 id="stdlib">Standard library</h2>
+		<img class="gopher" src="/doc/gopher/pkg.png"/>
+	{{end}}
+	<table class="dir">
+	<tr>
+	<th>Name</th>
+	<th>&nbsp;&nbsp;&nbsp;&nbsp;</th>
+	<th style="text-align: left; width: auto">Synopsis</th>
+	</tr>
+	{{if not (or (eq $.Dirname "/src") (eq $.Dirname "/src/cmd") $.DirFlat)}}
+		<tr>
+		<td><a href="..">..</a></td>
+		</tr>
+	{{end}}
+	{{range .List}}
+		{{if $.DirFlat}}
+			{{if .HasPkg}}
+				<tr>
+				<td class="name"><a href="{{html .Path}}/">{{html .Path}}</a></td>
+				<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+				<td style="width: auto">{{html .Synopsis}}</td>
+				</tr>
+			{{end}}
+		{{else}}
+			<tr>
+			<td class="name">{{repeat `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;` .Depth}}<a href="{{html .Path}}/">{{html .Name}}</a></td>
+			<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+			<td style="width: auto">{{html .Synopsis}}</td>
+			</tr>
+		{{end}}
+	{{end}}
+	</table>
+
+	{{if eq $.Dirname "/src"}}
+	<h2 id="other">Other packages</h2>
+
+	<h3 id="subrepo">Sub-repositories</h3>
+	<p>
+	These packages are part of the Go Project but outside the main Go tree.
+	They are developed under looser <a href="/doc/go1compat">compatibility requirements</a> than the Go core.
+	Install them with "<a href="/cmd/go/#hdr-Download_and_install_packages_and_dependencies">go get</a>".
+	</p>
+	<ul>
+		<li><a href="//godoc.org/golang.org/x/crypto">crypto</a> — additional cryptography packages.</li>
+		<li><a href="//godoc.org/golang.org/x/image">image</a> — additional imaging packages.</li>
+		<li><a href="//godoc.org/golang.org/x/net">net</a> — additional networking packages.</li>
+		<li><a href="//godoc.org/golang.org/x/sys">sys</a> — packages for making system calls.</li>
+		<li><a href="//godoc.org/golang.org/x/text">text</a> — packages for working with text.</li>
+		<li><a href="//godoc.org/golang.org/x/tools">tools</a> — godoc, vet, cover, and other tools.</li>
+		<li><a href="//godoc.org/golang.org/x/exp">exp</a> — experimental code (handle with care; may change without warning).</li>
+	</ul>
+
+	<h3 id="community">Community</h3>
+	<p>
+	These services can help you find Open Source packages provided by the community.
+	</p>
+	<ul>
+		<li><a href="//godoc.org">GoDoc</a> - a package index and search engine.</li>
+		<li><a href="http://go-search.org">Go Search</a> - a code search engine.</li>
+		<li><a href="/wiki/Projects">Projects at the Go Wiki</a> - a curated list of Go projects.</li>
+	</ul>
+	{{end}}
+{{end}}
diff --git a/third_party/go.tools/godoc/static/package.txt b/third_party/go.tools/godoc/static/package.txt
new file mode 100644
index 0000000..868d064
--- /dev/null
+++ b/third_party/go.tools/godoc/static/package.txt
@@ -0,0 +1,114 @@
+{{$info := .}}{{$filtered := .IsFiltered}}{{/*
+
+---------------------------------------
+
+*/}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
+{{node $ $ast}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if and $filtered (not (or .PDoc .PAst))}}No match found.
+{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND DOCUMENTATION
+
+{{comment_text .Doc "    " "\t"}}
+{{else}}{{if not $filtered}}PACKAGE DOCUMENTATION
+
+package {{.Name}}
+    import "{{.ImportPath}}"
+
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ "" "    "}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Consts}}{{if not $filtered}}CONSTANTS
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Vars}}{{if not $filtered}}VARIABLES
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Funcs}}{{if not $filtered}}FUNCTIONS
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ .Name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Types}}{{if not $filtered}}TYPES
+
+{{end}}{{range .}}{{$tname := .Name}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{/*
+
+---------------------------------------
+
+*/}}{{if .Consts}}{{range .Consts}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Vars}}{{range .Vars}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{range $name := .Names}}{{example_text $ $name "    "}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Funcs}}{{range .Funcs}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ .Name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Methods}}{{range .Methods}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{$name := printf "%s_%s" $tname .Name}}{{example_text $ $name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if and $filtered (not (or .Consts (or .Vars (or .Funcs .Types))))}}No match found.
+{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with $.Notes}}
+{{range $marker, $content := .}}
+{{$marker}}S
+
+{{range $content}}{{comment_text .Body "   " "\t"}}
+{{end}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if not $filtered}}{{with .Dirs}}SUBDIRECTORIES
+{{if $.DirFlat}}{{range .List}}{{if .HasPkg}}
+	{{.Path}}{{end}}{{end}}
+{{else}}{{range .List}}
+	{{repeat `. ` .Depth}}{{.Name}}{{end}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{/*
+Make sure there is no newline at the end of this file.
+perl -i -pe 'chomp if eof' package.txt
+*/}}
diff --git a/third_party/go.tools/godoc/static/play.js b/third_party/go.tools/godoc/static/play.js
new file mode 100644
index 0000000..7e87460
--- /dev/null
+++ b/third_party/go.tools/godoc/static/play.js
@@ -0,0 +1,103 @@
+// 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.
+
+function initPlayground(transport) {
+	"use strict";
+
+	function text(node) {
+		var s = "";
+		for (var i = 0; i < node.childNodes.length; i++) {
+			var n = node.childNodes[i];
+			if (n.nodeType === 1) {
+				if (n.tagName === "BUTTON") continue
+				if (n.tagName === "SPAN" && n.className === "number") continue;
+				if (n.tagName === "DIV" || n.tagName == "BR") {
+					s += "\n";
+				}
+				s += text(n);
+				continue;
+			}
+			if (n.nodeType === 3) {
+				s += n.nodeValue;
+			}
+		}
+		return s.replace("\xA0", " "); // replace non-breaking spaces
+	}
+
+	function init(code) {
+		var output = document.createElement('div');
+		var outpre = document.createElement('pre');
+		var running;
+
+		if ($ && $(output).resizable) {
+			$(output).resizable({
+				handles: "n,w,nw",
+				minHeight:	27,
+				minWidth:	135,
+				maxHeight: 608,
+				maxWidth:	990
+			});
+		}
+
+		function onKill() {
+			if (running) running.Kill();
+		}
+
+		function onRun(e) {
+			onKill();
+			output.style.display = "block";
+			outpre.innerHTML = "";
+			run1.style.display = "none";
+			var options = {Race: e.shiftKey};
+			running = transport.Run(text(code), PlaygroundOutput(outpre), options);
+		}
+
+		function onClose() {
+			onKill();
+			output.style.display = "none";
+			run1.style.display = "inline-block";
+		}
+
+		var run1 = document.createElement('button');
+		run1.innerHTML = 'Run';
+		run1.className = 'run';
+		run1.addEventListener("click", onRun, false);
+		var run2 = document.createElement('button');
+		run2.className = 'run';
+		run2.innerHTML = 'Run';
+		run2.addEventListener("click", onRun, false);
+		var kill = document.createElement('button');
+		kill.className = 'kill';
+		kill.innerHTML = 'Kill';
+		kill.addEventListener("click", onKill, false);
+		var close = document.createElement('button');
+		close.className = 'close';
+		close.innerHTML = 'Close';
+		close.addEventListener("click", onClose, false);
+
+		var button = document.createElement('div');
+		button.classList.add('buttons');
+		button.appendChild(run1);
+		// Hack to simulate insertAfter
+		code.parentNode.insertBefore(button, code.nextSibling);
+
+		var buttons = document.createElement('div');
+		buttons.classList.add('buttons');
+		buttons.appendChild(run2);
+		buttons.appendChild(kill);
+		buttons.appendChild(close);
+
+		output.classList.add('output');
+		output.appendChild(buttons);
+		output.appendChild(outpre);
+		output.style.display = "none";
+		code.parentNode.insertBefore(output, button.nextSibling);
+	}
+
+	var play = document.querySelectorAll('div.playground');
+	for (var i = 0; i < play.length; i++) {
+		init(play[i]);
+	}
+}
+
diff --git a/third_party/go.tools/godoc/static/playground.js b/third_party/go.tools/godoc/static/playground.js
new file mode 100644
index 0000000..59d4cda
--- /dev/null
+++ b/third_party/go.tools/godoc/static/playground.js
@@ -0,0 +1,433 @@
+// 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.
+
+/*
+In the absence of any formal way to specify interfaces in JavaScript,
+here's a skeleton implementation of a playground transport.
+
+        function Transport() {
+                // Set up any transport state (eg, make a websocket connnection).
+                return {
+                        Run: function(body, output, options) {
+                                // Compile and run the program 'body' with 'options'.
+				// Call the 'output' callback to display program output.
+                                return {
+                                        Kill: function() {
+                                                // Kill the running program.
+                                        }
+                                };
+                        }
+                };
+        }
+
+	// The output callback is called multiple times, and each time it is
+	// passed an object of this form.
+        var write = {
+                Kind: 'string', // 'start', 'stdout', 'stderr', 'end'
+                Body: 'string'  // content of write or end status message
+        }
+
+	// The first call must be of Kind 'start' with no body.
+	// Subsequent calls may be of Kind 'stdout' or 'stderr'
+	// and must have a non-null Body string.
+	// The final call should be of Kind 'end' with an optional
+	// Body string, signifying a failure ("killed", for example).
+
+	// The output callback must be of this form.
+	// See PlaygroundOutput (below) for an implementation.
+        function outputCallback(write) {
+        }
+*/
+
+function HTTPTransport() {
+	'use strict';
+
+	// TODO(adg): support stderr
+
+	function playback(output, events) {
+		var timeout;
+		output({Kind: 'start'});
+		function next() {
+			if (events.length === 0) {
+				output({Kind: 'end'});
+				return;
+			}
+			var e = events.shift();
+			if (e.Delay === 0) {
+				output({Kind: 'stdout', Body: e.Message});
+				next();
+				return;
+			}
+			timeout = setTimeout(function() {
+				output({Kind: 'stdout', Body: e.Message});
+				next();
+			}, e.Delay / 1000000);
+		}
+		next();
+		return {
+			Stop: function() {
+				clearTimeout(timeout);
+			}
+		}
+	}
+
+	function error(output, msg) {
+		output({Kind: 'start'});
+		output({Kind: 'stderr', Body: msg});
+		output({Kind: 'end'});
+	}
+
+	var seq = 0;
+	return {
+		Run: function(body, output, options) {
+			seq++;
+			var cur = seq;
+			var playing;
+			$.ajax('/compile', {
+				type: 'POST',
+				data: {'version': 2, 'body': body},
+				dataType: 'json',
+				success: function(data) {
+					if (seq != cur) return;
+					if (!data) return;
+					if (playing != null) playing.Stop();
+					if (data.Errors) {
+						error(output, data.Errors);
+						return;
+					}
+					playing = playback(output, data.Events);
+				},
+				error: function() {
+					error(output, 'Error communicating with remote server.');
+				}
+			});
+			return {
+				Kill: function() {
+					if (playing != null) playing.Stop();
+					output({Kind: 'end', Body: 'killed'});
+				}
+			};
+		}
+	};
+}
+
+function SocketTransport() {
+	'use strict';
+
+	var id = 0;
+	var outputs = {};
+	var started = {};
+	var websocket = new WebSocket('ws://' + window.location.host + '/socket');
+
+	websocket.onclose = function() {
+		console.log('websocket connection closed');
+	}
+
+	websocket.onmessage = function(e) {
+		var m = JSON.parse(e.data);
+		var output = outputs[m.Id];
+		if (output === null)
+			return;
+		if (!started[m.Id]) {
+			output({Kind: 'start'});
+			started[m.Id] = true;
+		}
+		output({Kind: m.Kind, Body: m.Body});
+	}
+
+	function send(m) {
+		websocket.send(JSON.stringify(m));
+	}
+
+	return {
+		Run: function(body, output, options) {
+			var thisID = id+'';
+			id++;
+			outputs[thisID] = output;
+			send({Id: thisID, Kind: 'run', Body: body, Options: options});
+			return {
+				Kill: function() {
+					send({Id: thisID, Kind: 'kill'});
+				}
+			};
+		}
+	};
+}
+
+function PlaygroundOutput(el) {
+	'use strict';
+
+	return function(write) {
+		if (write.Kind == 'start') {
+			el.innerHTML = '';
+			return;
+		}
+
+		var cl = 'system';
+		if (write.Kind == 'stdout' || write.Kind == 'stderr')
+			cl = write.Kind;
+
+		var m = write.Body;
+		if (write.Kind == 'end') 
+			m = '\nProgram exited' + (m?(': '+m):'.');
+
+		if (m.indexOf('IMAGE:') === 0) {
+			// TODO(adg): buffer all writes before creating image
+			var url = 'data:image/png;base64,' + m.substr(6);
+			var img = document.createElement('img');
+			img.src = url;
+			el.appendChild(img);
+			return;
+		}
+
+		// ^L clears the screen.
+		var s = m.split('\x0c');
+		if (s.length > 1) {
+			el.innerHTML = '';
+			m = s.pop();
+		}
+
+		m = m.replace(/&/g, '&amp;');
+		m = m.replace(/</g, '&lt;');
+		m = m.replace(/>/g, '&gt;');
+
+		var needScroll = (el.scrollTop + el.offsetHeight) == el.scrollHeight;
+
+		var span = document.createElement('span');
+		span.className = cl;
+		span.innerHTML = m;
+		el.appendChild(span);
+
+		if (needScroll)
+			el.scrollTop = el.scrollHeight - el.offsetHeight;
+	}
+}
+
+(function() {
+  function lineHighlight(error) {
+    var regex = /prog.go:([0-9]+)/g;
+    var r = regex.exec(error);
+    while (r) {
+      $(".lines div").eq(r[1]-1).addClass("lineerror");
+      r = regex.exec(error);
+    }
+  }
+  function highlightOutput(wrappedOutput) {
+    return function(write) {
+      if (write.Body) lineHighlight(write.Body);
+      wrappedOutput(write);
+    }
+  }
+  function lineClear() {
+    $(".lineerror").removeClass("lineerror");
+  }
+
+  // opts is an object with these keys
+  //  codeEl - code editor element
+  //  outputEl - program output element
+  //  runEl - run button element
+  //  fmtEl - fmt button element (optional)
+  //  fmtImportEl - fmt "imports" checkbox element (optional)
+  //  shareEl - share button element (optional)
+  //  shareURLEl - share URL text input element (optional)
+  //  shareRedirect - base URL to redirect to on share (optional)
+  //  toysEl - toys select element (optional)
+  //  enableHistory - enable using HTML5 history API (optional)
+  //  transport - playground transport to use (default is HTTPTransport)
+  function playground(opts) {
+    var code = $(opts.codeEl);
+    var transport = opts['transport'] || new HTTPTransport();
+    var running;
+  
+    // autoindent helpers.
+    function insertTabs(n) {
+      // find the selection start and end
+      var start = code[0].selectionStart;
+      var end   = code[0].selectionEnd;
+      // split the textarea content into two, and insert n tabs
+      var v = code[0].value;
+      var u = v.substr(0, start);
+      for (var i=0; i<n; i++) {
+        u += "\t";
+      }
+      u += v.substr(end);
+      // set revised content
+      code[0].value = u;
+      // reset caret position after inserted tabs
+      code[0].selectionStart = start+n;
+      code[0].selectionEnd = start+n;
+    }
+    function autoindent(el) {
+      var curpos = el.selectionStart;
+      var tabs = 0;
+      while (curpos > 0) {
+        curpos--;
+        if (el.value[curpos] == "\t") {
+          tabs++;
+        } else if (tabs > 0 || el.value[curpos] == "\n") {
+          break;
+        }
+      }
+      setTimeout(function() {
+        insertTabs(tabs);
+      }, 1);
+    }
+  
+    function keyHandler(e) {
+      if (e.keyCode == 9 && !e.ctrlKey) { // tab (but not ctrl-tab)
+        insertTabs(1);
+        e.preventDefault();
+        return false;
+      }
+      if (e.keyCode == 13) { // enter
+        if (e.shiftKey) { // +shift
+          run();
+          e.preventDefault();
+          return false;
+        } if (e.ctrlKey) { // +control
+          fmt();
+          e.preventDefault();
+        } else {
+          autoindent(e.target);
+        }
+      }
+      return true;
+    }
+    code.unbind('keydown').bind('keydown', keyHandler);
+    var outdiv = $(opts.outputEl).empty();
+    var output = $('<pre/>').appendTo(outdiv);
+  
+    function body() {
+      return $(opts.codeEl).val();
+    }
+    function setBody(text) {
+      $(opts.codeEl).val(text);
+    }
+    function origin(href) {
+      return (""+href).split("/").slice(0, 3).join("/");
+    }
+  
+    var pushedEmpty = (window.location.pathname == "/");
+    function inputChanged() {
+      if (pushedEmpty) {
+        return;
+      }
+      pushedEmpty = true;
+      $(opts.shareURLEl).hide();
+      window.history.pushState(null, "", "/");
+    }
+    function popState(e) {
+      if (e === null) {
+        return;
+      }
+      if (e && e.state && e.state.code) {
+        setBody(e.state.code);
+      }
+    }
+    var rewriteHistory = false;
+    if (window.history && window.history.pushState && window.addEventListener && opts.enableHistory) {
+      rewriteHistory = true;
+      code[0].addEventListener('input', inputChanged);
+      window.addEventListener('popstate', popState);
+    }
+
+    function setError(error) {
+      if (running) running.Kill();
+      lineClear();
+      lineHighlight(error);
+      output.empty().addClass("error").text(error);
+    }
+    function loading() {
+      lineClear();
+      if (running) running.Kill();
+      output.removeClass("error").text('Waiting for remote server...');
+    }
+    function run() {
+      loading();
+      running = transport.Run(body(), highlightOutput(PlaygroundOutput(output[0])));
+    }
+
+    function fmt() {
+      loading();
+      var data = {"body": body()}; 
+      if ($(opts.fmtImportEl).is(":checked")) {
+        data["imports"] = "true";
+      }
+      $.ajax("/fmt", {
+        data: data,
+        type: "POST",
+        dataType: "json",
+        success: function(data) {
+          if (data.Error) {
+            setError(data.Error);
+          } else {
+            setBody(data.Body);
+            setError("");
+          }
+        }
+      });
+    }
+
+    $(opts.runEl).click(run);
+    $(opts.fmtEl).click(fmt);
+
+    if (opts.shareEl !== null && (opts.shareURLEl !== null || opts.shareRedirect !== null)) {
+      var shareURL;
+      if (opts.shareURLEl) {
+        shareURL = $(opts.shareURLEl).hide();
+      }
+      var sharing = false;
+      $(opts.shareEl).click(function() {
+        if (sharing) return;
+        sharing = true;
+        var sharingData = body();
+        $.ajax("/share", {
+          processData: false,
+          data: sharingData,
+          type: "POST",
+          complete: function(xhr) {
+            sharing = false;
+            if (xhr.status != 200) {
+              alert("Server error; try again.");
+              return;
+            }
+            if (opts.shareRedirect) {
+              window.location = opts.shareRedirect + xhr.responseText;
+            }
+            if (shareURL) {
+              var path = "/p/" + xhr.responseText;
+              var url = origin(window.location) + path;
+              shareURL.show().val(url).focus().select();
+  
+              if (rewriteHistory) {
+                var historyData = {"code": sharingData};
+                window.history.pushState(historyData, "", path);
+                pushedEmpty = false;
+              }
+            }
+          }
+        });
+      });
+    }
+  
+    if (opts.toysEl !== null) {
+      $(opts.toysEl).bind('change', function() {
+        var toy = $(this).val();
+        $.ajax("/doc/play/"+toy, {
+          processData: false,
+          type: "GET",
+          complete: function(xhr) {
+            if (xhr.status != 200) {
+              alert("Server error; try again.");
+              return;
+            }
+            setBody(xhr.responseText);
+          }
+        });
+      });
+    }
+  }
+
+  window.playground = playground;
+})();
diff --git a/third_party/go.tools/godoc/static/search.html b/third_party/go.tools/godoc/static/search.html
new file mode 100644
index 0000000..e0d13b9
--- /dev/null
+++ b/third_party/go.tools/godoc/static/search.html
@@ -0,0 +1,18 @@
+<!--
+	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.
+-->
+{{with .Alert}}
+	<p>
+	<span class="alert" style="font-size:120%">{{html .}}</span>
+	</p>
+{{end}}
+{{with .Alt}}
+	<p>
+	<span class="alert" style="font-size:120%">Did you mean: </span>
+	{{range .Alts}}
+		<a href="search?q={{urlquery .}}" style="font-size:120%">{{html .}}</a>
+	{{end}}
+	</p>
+{{end}}
diff --git a/third_party/go.tools/godoc/static/search.txt b/third_party/go.tools/godoc/static/search.txt
new file mode 100644
index 0000000..15c1941
--- /dev/null
+++ b/third_party/go.tools/godoc/static/search.txt
@@ -0,0 +1,54 @@
+QUERY
+	{{.Query}}
+
+{{with .Alert}}{{.}}
+{{end}}{{/* .Alert */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Alt}}DID YOU MEAN
+
+{{range .Alts}}	{{.}}
+{{end}}
+{{end}}{{/* .Alt */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Pak}}PACKAGE {{$.Query}}
+
+{{range .}}	{{pkgLink .Pak.Path}}
+{{end}}
+{{end}}{{/* .Pak */}}{{/*
+
+---------------------------------------
+
+*/}}{{range $key, $val := .Idents}}{{if $val}}{{$key.Name}}
+{{range $val.Idents}}    {{.Path}}.{{.Name}}
+{{end}}
+{{end}}{{end}}{{/* .Idents */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Hit}}{{with .Decls}}PACKAGE-LEVEL DECLARATIONS
+
+{{range .}}package {{.Pak.Name}}
+{{range $file := .Files}}{{range .Groups}}{{range .}}	{{srcLink $file.File.Path}}:{{infoLine .}}{{end}}
+{{end}}{{end}}{{/* .Files */}}
+{{end}}{{end}}{{/* .Decls */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Others}}LOCAL DECLARATIONS AND USES
+
+{{range .}}package {{.Pak.Name}}
+{{range $file := .Files}}{{range .Groups}}{{range .}}	{{srcLink $file.File.Path}}:{{infoLine .}}
+{{end}}{{end}}{{end}}{{/* .Files */}}
+{{end}}{{end}}{{/* .Others */}}{{end}}{{/* .Hit */}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Textual}}{{if .Complete}}{{.Found}} TEXTUAL OCCURRENCES{{else}}MORE THAN {{.Found}} TEXTUAL OCCURRENCES{{end}}
+
+{{range .Textual}}{{len .Lines}}	{{srcLink .Filename}}
+{{end}}{{if not .Complete}}...	...
+{{end}}{{end}}
diff --git a/third_party/go.tools/godoc/static/searchcode.html b/third_party/go.tools/godoc/static/searchcode.html
new file mode 100644
index 0000000..a032e64
--- /dev/null
+++ b/third_party/go.tools/godoc/static/searchcode.html
@@ -0,0 +1,64 @@
+<!--
+	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.
+-->
+{{$query_url := urlquery .Query}}
+{{if not .Idents}}
+	{{with .Pak}}
+		<h2 id="Packages">Package {{html $.Query}}</h2>
+		<p>
+		<table class="layout">
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<tr><td><a href="/{{$pkg_html}}">{{$pkg_html}}</a></td></tr>
+		{{end}}
+		</table>
+		</p>
+	{{end}}
+{{end}}
+{{with .Hit}}
+	{{with .Decls}}
+		<h2 id="Global">Package-level declarations</h2>
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<h3 id="Global_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
+			{{range .Files}}
+				{{$file := .File.Path}}
+				{{range .Groups}}
+					{{range .}}
+						{{$line := infoLine .}}
+						<a href="{{queryLink $file $query_url $line | html}}">{{$file}}:{{$line}}</a>
+						{{infoSnippet_html .}}
+					{{end}}
+				{{end}}
+			{{end}}
+		{{end}}
+	{{end}}
+	{{with .Others}}
+		<h2 id="Local">Local declarations and uses</h2>
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<h3 id="Local_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
+			{{range .Files}}
+				{{$file := .File.Path}}
+				<a href="{{queryLink $file $query_url 0 | html}}">{{$file}}</a>
+				<table class="layout">
+				{{range .Groups}}
+					<tr>
+					<td width="25"></td>
+					<th align="left" valign="top">{{index . 0 | infoKind_html}}</th>
+					<td align="left" width="4"></td>
+					<td>
+					{{range .}}
+						{{$line := infoLine .}}
+						<a href="{{queryLink $file $query_url $line | html}}">{{$line}}</a>
+					{{end}}
+					</td>
+					</tr>
+				{{end}}
+				</table>
+			{{end}}
+		{{end}}
+	{{end}}
+{{end}}
diff --git a/third_party/go.tools/godoc/static/searchdoc.html b/third_party/go.tools/godoc/static/searchdoc.html
new file mode 100644
index 0000000..679c02c
--- /dev/null
+++ b/third_party/go.tools/godoc/static/searchdoc.html
@@ -0,0 +1,24 @@
+<!--
+	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.
+-->
+{{range $key, $val := .Idents}}
+	{{if $val}}
+		<h2 id="{{$key.Name}}">{{$key.Name}}</h2>
+		{{range $val}}
+			{{$pkg_html := pkgLink .Path | html}}
+			{{if eq "Packages" $key.Name}}
+				<a href="/{{$pkg_html}}">{{html .Path}}</a>
+			{{else}}
+				{{$doc_html := docLink .Path .Name| html}}
+				<a href="/{{$pkg_html}}">{{html .Package}}</a>.<a href="{{$doc_html}}">{{.Name}}</a>
+			{{end}}
+			{{if .Doc}}
+				<p>{{comment_html .Doc}}</p>
+			{{else}}
+				<p><em>No documentation available</em></p>
+			{{end}}
+		{{end}}
+	{{end}}
+{{end}}
diff --git a/third_party/go.tools/godoc/static/searchtxt.html b/third_party/go.tools/godoc/static/searchtxt.html
new file mode 100644
index 0000000..7e4a978
--- /dev/null
+++ b/third_party/go.tools/godoc/static/searchtxt.html
@@ -0,0 +1,42 @@
+<!--
+	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.
+-->
+{{$query_url := urlquery .Query}}
+{{with .Textual}}
+	{{if $.Complete}}
+		<h2 id="Textual">{{html $.Found}} textual occurrences</h2>
+	{{else}}
+		<h2 id="Textual">More than {{html $.Found}} textual occurrences</h2>
+		<p>
+		<span class="alert" style="font-size:120%">Not all files or lines containing "{{html $.Query}}" are shown.</span>
+		</p>
+	{{end}}
+	<p>
+	<table class="layout">
+	{{range .}}
+		{{$file := .Filename}}
+		<tr>
+		<td align="left" valign="top">
+		<a href="{{queryLink $file $query_url 0}}">{{$file}}</a>:
+		</td>
+		<td align="left" width="4"></td>
+		<th align="left" valign="top">{{len .Lines}}</th>
+		<td align="left" width="4"></td>
+		<td align="left">
+		{{range .Lines}}
+			<a href="{{queryLink $file $query_url .}}">{{html .}}</a>
+		{{end}}
+		{{if not $.Complete}}
+			...
+		{{end}}
+		</td>
+		</tr>
+	{{end}}
+	{{if not $.Complete}}
+		<tr><td align="left">...</td></tr>
+	{{end}}
+	</table>
+	</p>
+{{end}}
diff --git a/third_party/go.tools/godoc/static/static.go b/third_party/go.tools/godoc/static/static.go
new file mode 100644
index 0000000..593d433
--- /dev/null
+++ b/third_party/go.tools/godoc/static/static.go
@@ -0,0 +1,3289 @@
+// DO NOT EDIT ** This file was generated with the bake tool ** DO NOT EDIT //
+
+package static
+
+var Files = map[string]string{
+	"analysis/call3.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03N\x00\x00\x01\xea\b\x03\x00\x00\x00\x04l\xeeb\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x04\x06\x03\x06\t\x05\x0e\x10\r\x16\x17\x15$\x18\x0f\x1e\x1d\x17!# #$\"$%#&(%)(\"()'-+\x1f*+),-+-/,41&J-\x1202/241S/\x0e564,7M796<:.:<9!?p=?<B@4@B?DECLH9?JVHIGvD\x13JLIMOLVQ@QRPUWT_ZHY[X,`\xae7]\xaduWG8`\xaa\\^[A`\xa5:b\xab;b\xac<c\xad_a^=d\xae@f\xb0bdaRe\x99lfP\x90^8Ci\xb4egdMj\xafhjgFm\xb1Ol\xb2fj\x90Ip\xb4\xa7c\"}iflnkKr\xb7oqnNu\xba\xb3h\"{s[Xv\xb6tvs\u007fr\u007fZx\xb8ry\x81]{\xbb\\}\xb6y{x_}\xbeX\x80\xbf`\x80\xba\x96xpb\x80\xc0}\u007f|\x89\x80eb\x83\xbd\u007f\x81~\x9a{oe\x85\xc0\x82\x83\x81k\x85\xbb\xa7}fh\x88\xc3m\x88\xbdj\x8aľ~G\x87\x89\x86q\x8c\xc1\x8a\x8c\x89\xbe\x82Y\x96\x8cnt\x8e\xc4z\x8f\xc0\x8f\x91\x8ex\x92\xc8~\x93\xc3x\x95\xc4z\x94ʒ\x94\x91\x80\x95\xc5ӊJz\x98ǂ\x96Ǡ\x96w|\x99ȕ\x97\x94\x83\x98ɂ\x9aė\x99\x96\x86\x9a\xcc\xe4\x8dA\x80\x9d̅\x9dǚ\x9c\x98\x83\xa0Ϝ\x9e\x9b\xa8\x9e\u007f\x88\xa0\xcb\xf3\x915\x8a\xa2̙\xa0\xb5\x9f\xa1\x9e\x8e\xa2Nj\xa3Ρ\xa3\xa0\xfa\x95/\xa2\xa4\xa1\x8e\xa6\xd0\xff\x952\x92\xa6˳\xa6\x82\xa5\xa7\xa4\x91\xa9ԧ\xa9\xa6\x94\xac֙\xacҪ\xac\xa8\xb9\xac\x88\x9e\xaeΛ\xafԭ\xaf\xac\x9d\xb1֢\xb1ѯ\xb1\xae\xa1\xb5ڥ\xb5ճ\xb5\xb2µ\x90\xa3\xb7ݵ\xb7\xb4\xac\xb7Ҫ\xb9ٷ\xb9\xb6\xac\xbcܺ\xbc\xb9\xb1\xbd\u05ef\xbe\xdf˾\x98\xbd\xbf\xbc\xb1\xc0\xe0\xba\xc1\xd6\xc0¾\xb7\xc2\xdd\xc2\xc4\xc1\xb9\xc5\xe0\xbd\xc5\xda\xc4\xc6û\xc7\xe2\xd6ǝ\xbc\xc8\xe3\xbb\xca\xde\xc7\xc9ƿ\xca\xe5\xc6\xca\xda\xc0\xcc\xda\xca\xcc\xc8\xc1\xcc\xe7\xbf\xcf\xe2\xc2\xce\xe9\xcd\xcf\xcc\xc4\xd0\xde\xcb\xcf\xdf\xc8\xd0\xe5\xcf\xd1\xce\xdfѥ\xca\xd1\xe7\xcc\xd3\xe9\xd2\xd4\xd1\xcc\xd5\xdd\xd3\xd3\xde\xce\xd6\xeb\xd6\xd8\xd5\xd0\xd8\xed\xe7ج\xd2\xda\xe2\xcb\xdb\xee\xd5\xd9\xe9\xd9\xd9\xe4\xd7\xdb\xeb\xda\xdc\xd9\xd8\xdc\xec\xd2\xde\xec\xd9\xdd\xed\xdc\xdd\xe7\xdd\xdf\xdc\xd4\xe0\xef\xdb\xdf\xef\xf0\xe0\xb3\xdc\xe1\xe4\xdd\xe1\xf1\xe0\xe2\xdf\xd9\xe5\xf4\xe0\xe5\xe8\xe0\xe4\xf4\xe3\xe5\xe2\xde\xe6\xef\xe7\xe5\xe9\xe5\xe7\xe4\xe6\xe7\xf1\xe0\xe9\xf1\xe4\xe9\xeb\xe7\xe9\xe6\xe3\xec\xf4\xeb\xed\xea\xe6\xee\xf7\xec\xed\xf7\xe8\xf0\xf9\xf0\xf0\xfb\xf0\xf3\xef\xf4\xf2\xf6\xee\xf4\xf6\xf0\xf6\xf8\xf4\xf7\xf3\xf2\xf7\xfa\xf5\xfa\xfd\xf8\xfa\xf7\xfd\xfb\xff\xf7\xfd\xff\xf9\xff\xff\xfe\xff\xfc\x9cx\xeb\xab\x00\x00 \x00IDATx^\xed\x9d\x0fp\x14ׁ\xa7C\x9c\xf3\x83\x89-\x94\x95V\xa7\xb0\x04r\xac8\x14\xd37l\tF\\N\xa0\xd1\xe9N\xb27\xd2q\x0e\x845\xc1+\xbc\xb6N\xb0\x11\xb2\x1d\xd8(K!\x8e\x15\n\xa9S \"\x18\bZ\x82\x10QJ\x12\b,\x84A\x90\n\x10\xe1\"\xe0\x80b\xc9v\xe2\x12Nd\x1bk\x89\xd6\xc4j;\x80\x8d\x8d\xf0\xd4Խ\xd7\xdd3\xf3\xba\xa7{zz\xd4j\x8dF\xbf\xaf\xa8\xa1\xe7\xe9\xbd\xd7\u007f\xa6\xbf\xe9\xee7=\xbf\xf9\x8c?fD\x00\x80\x8aϘIc\x8cY\xd7\x00L4\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:%27\xcc*\x00{\x81N\tKwA\x1aYhV\t\xd8\ntJXfάj|ɬ\x12\xb0\x15Gu\xea\xde_[]w\xa8\x9fM\xde8\xb1\xa7z\xd7\x19m\xa9\xd3\xf4\x15\xa7%͋\xf2\x8c\xa81\xb5ެJ\\q\x82\xec7\xab\x02\xec\xc6I\x9dz\xab\xea\xcft\x9f\xd9U;@\xa7\xebk\x8e_h\xafnה:Mfچ\x82\xa4>\xb3Z2\xf5Sw\x99U\x89+\xdaI\xb3Y\x15`7N\xea\xd4U\xd5M\x1f\a\xaa\xe8A\xe9x5ۉ\xbb\xaa\xfbU\xa5N\xd3G։\xe2\x98\x1c\x16\x1d\xa0\x8d\xb4\x99U\x01v\xe3\xa4N\xa2t\x00\xeae\xfa\xd4\xcb'\"\xb5\xed\xaaR\xa7\xe9\"\xe3\xeb\xfc\xcd\x12\xd0i\fpT'\xca@w\x1dۅw\xc9'\"{\xeaU\xa5\x8e2\x98J$\x96J\xcf6d$el\xa0\xff\x9f\x98BȪ\xae\xdc\xe9I\xf3\x06\xf9\xca}I\x84L\xae\xd5\xeb&H\xd7\xc2TWڼ\xb07\x85\x9a\xb4*\xf6_w\xb2<7\x92\xcc\xd7\xe0\xe7ֿ(\xdd5m\xc1\tZZL\\UKg$=$\xd5\xec\xcdMM_\xba4uj\x1d\x9d\xae\x9d3u\xc6R\xedѴ\xf3\x89|\xf7\xe2\xa7\xf2\x874\xc5b\x13tr\x1egu\uab6a\xaa\xaaa\xfbáZ\xb6\xb7\x0e\xd4\xecR\x95:\xcb\xf1\xe6\xed\xa4\xac\xb9Y\xdai\v\\\xab\xeaW\xb9r\xe9\"\xd5\xd5N\x9b\x91<mi.Q\x0f\x8a\xb577\xbb\xcat\xbbQh\x9a\x9aQ\xd1XF*\xb4\xe5\v\xc9<\xf6\xdf`\xcd:\x99\x1a^S~n\xf5\xe4ᦺ\x05\x93\xa9\x03gj\xa7\x90Բ\x8ad6\xca=83}C\x99+\xa9\xfa!\xdaq\xc1\xe4\xe2\xfau\xa9\x19ꡓ_\xce}\xa6\xa5\xe3\xc0b\xe1]U\xe9`o\xd3\xec\x14\xe77\xe9\x84\xc7Y\x9d\xc4\xde\xeeSu\xb5\xf4e\uebe9\xef\x1d\xe8\xdeSU\xa7*u\x9a\xe0\xc9\xde~i\x14L~\x143Hf\xbf\xde%UR$\x9d\x06\xa6ͣ'\xad\x83ua\xe3\x1a\x17\xd6\\\x90\xfe\xef\xbd ӫ\xf9{pn\x03ul\x96\xb3\xa4O\x8a\\)T\xf2\xdcT:\xb5\x9d\xd0\xe3\xd5\x06r\x8aN֓\x1a\x91\x9d\xc3mW\xb5?\xe0e\"\xed\xcbQ\x1f\x9d\x16\xd2\xe3\xa0\xe3\xc7{\xe0\xb4N\"\xdb\xe5\x1a\xe9c_==$\xb5\xd5\xefQ\x97:LP\xa7\x82Y\xd2\u007f3\v\xd8c\x86K\xffӚ\x88:Փ\xe3\x11\xfeJ\xad\"\x01.\xa8\xff\x10\x9a[\xef\x86yӓ\x89\xb4$.\xb6 e.\xfa\xb0\"Ed\xcbɶӢ郌\xf4\x02U\xfb\u05fc\x85\x1b\x0f\xfcjHs\xae\xf7\xd2\xfe\xaa\x998:9\x8f\x93:)C\xe1'\xaa\xe4g}7\xc4\xdaC\xdaRG\t\xea4g\x81\xf4\u07fc\xd9\xec1c\xb6~\xed\x88:\xad#&\x03\xfd\xcd\xf52\xda\xd1\xeb\xe0\xdc\xdaҦ\xad\xd8՜)\xeb\xc4f%\xe9TAz\xd9a\x93\x1d\x9d2\x14\x1f5w:\\;P^$\xe4\xed\r\xbbvjƵ\x93\xf38\xa9Sm\x93\xf4\xdf\xf1j\xfa ]AHc\xe4|\xa9Ä\x8eNӥ\xff\xa6\xcbG'\x83;s\"\xea\xd4hrt2$8\xb7\x99s\x98\x90\v5:\xbd4y\xdeK'f\xcca\x85\xb9\xd3\xdb%ԧ\x8b\xe7\xb6R\x91\xae\xb5\xcc? j\xc0\xc8\xde\x18\xe0\xa8Nҥ\x89tZw\xa6\x8a\xee\x14\xfd\x92I\\\xa9\xd3\x04u\xaa\x97.H\xb6\xcbO3\x16\xe9\xd7\x0e\xe9t\xa1,̝\xfe\xf4L\xf6\x0eQ\xbcT\xfb\x87\xc0\xb5\x93\x11\xc1\xb9Mc^\xdd\xc8\xd0\xe8\xd4N\xd2\bɔ\x86K\xf6\x13\xe9J\xf3\xf15\xaa\xf6;\x85\x0e\xf6\xdf\xcagE\r\xd0i\fpR\xa7\xae\xaa\xc63\xddg\xea\xd8\xfd\x0f]U\xed\xdd\xc7k\xeb\aԥ\xce\"\x8f\xec\xc9\xfb\\\xee\xe4\x15\xf5+&\xe7R\xadۚgd67k\x15\xa0\xc5ͮ\x82\xe6f\xf9rd\x01\x99\x1a6\xe4\xd0\xf4\xc0\xcc\r\xf5\xc5$\xec\x18\xbb@\x1e\xd9Ӈ\x9f[\x19Y\xb4aM\x06I\xadh릳j\x13\xdb\v\\\xcd\xdd\xe2qWc}\xb32\xb6\xbe\x82,\xaa\xdbS@\xd4\xe3\xf5;\x05\xcf\x0f\x8e\x1cyF\x96\x8a\xa7\x9d\x1c\xd2\x16\x81\xd1\xc6I\x9d\xc4\ue9ba\xea]m\x927\xc7\xebjꏇ\x95:\xc9@\x8at%2E\xbe\x1bcݬ\xa4Y\xd2\xe7N\x93\xa5R\xad\x02\xedr1\x91/\xf0\xaa\xa7\xea\xbc\xf3w-JO\x9e\x1d~\x1fRMj\x84\x8bB~n7*f\xb8R\x17\xd5Lwe\x16\xd3\"ש\xa9\xf4\xb1X<\xe4b\x15\\\x99\xec\xe2Iܟ\x99\x9a2Gs'\xdeO\x97\xef\xccw{W\x86\xd9$\xf6NYt\xa27\xca\xfb\x11\x81M8\xaaS°\x8784j\xd6;\xb5\xb8wp\xb0\xaf}a\f\xc3t{f\x86\r[\x80Q\x06:\xc5@M\xca\xc3fUlbO\x8a2\x11\xd3\xed\xec\xbd'\xc6\xe0έ\t\rt\xb2Nw\xeaR\xa7NM\xdb'Kgy\xe2\xa9\xc91\x0e\x1c\x02G\x81N\xf1MA\xd2\xc3ۛ\xb6?\x9c\xe4\xd4\xe1\x10\x8c\b\xe8\x14\xe7\xd4?\x94\xeeJ\x9f\x17˩\x1ep\x1e\xe8\x04\x80m@\xa7D\xe4G!̪\x02;\x81N\x89\bt\x1a#\xa0S\"\x02\x9d\xc6\b蔈@\xa71\x02:%\"\xd0i\x8c\x80N\x89\bt\x1a#\xa0S\"\x02\x9d\xc6\b蔈(*\xfd\xe3\u007f\xff\xbeJ\xa7\xbe9{D0\x9a8\xaa\x93~\xa82\xe5T\x15>\xf6\xb7H\x87\xf7\x88\xf1\x1fe\x9b\xfeA\xf8{\xcdѩb\xb2\xfa\xbb\x87\xc0f\x9c\xd4I?T\x99\xd2W}(r\x86\x1d\b㈧\xc5\xf8\x8f\xb2M\xee\u007f\f;٫\x9f\xb2N\xbf\x05\xb0\x05'u\xd2\x0fU\xa6\xd47vC'\xab\x84e\xadp0\x9b\xfe\xaf\xfb\xeft\xae\x9dV\xb9\xf0\x9d\x8dQ\xc4I\x9d\fB\x95\xc5S5\x03\xd0\xc9V\x98G\xff\xeb\xbf~\xffG?\xfcяn\f\xaa\xbe\x91ۯ\xc9\x15\x03\xb6\xe2\xa8N\xa2n\xa8r\u007fu\x97\x98@:\x19\xc42\x8b\x91\xf3\x95\xdf\xcdso\xf5z;6欼&\x8a\xd7ʽ\xee\xfc\xa7.\xd2\xe2\u007f\x16\xdc\xfb\xd6{s\x9e\xfa\x8djR\xbc\xe6\x11\x04A:٣\xa5\a6\x16y\x9ex\x9d=\xb9\xb6v\xb1\xf7_\xfee\xb1\xa7\x85\xda\xf4ÿ\xf9\x9f\u007f\xf9\x17\u007f\xf1\xd7\u007f9s\xe6\xd2߬^\xec\xf6>\xf5\xba<\xa3UIN}Wk\"\xe2\xacN\xba\xa1\xca\xf5\x8db\"\xe9d\x14\xcbl\x92\xafܑ-l,\x11\x16\xef\xcc\xdbG\xaf\x8b\x84\xf5\x1d-O\t\xe7D\xf1b\x8b[\xc8߹3\xdfs\x91\x9f\x14\xc5s\x9d\x9d\xf3w\xb2f\xacԻso\xf6j:=T\xe4\xdd\xf7\x83\xf9\x9e\x03O\xec\xa3:\xfd\x93\xfb?L\xce̜\x94\x949{\xd2_}}o\xc7Na\x9f<\x9fC\b8\x1aE\x9c\xd5I/T\xf9\f\xf3+\x81t\x12\rc\x99#\xe7+{\u05ca\x1d\xc2\x11\xf1\x99\xf5\xa2x\xbd\x85\x1e\xa2\x86\x960EĬBv\xb8\xca_\xae\x9e\xa4\xc8:\xd1\xd2\x1cz\xdcY\xeb\xa5S-\x025m\x1f{`\x83\xe4\xee\xfb\xd6\xf8\xfdg>\xf4\u07fb\xef?\xd2\x19\r\xb1.\x19\xddd|\xfdL\xd5\xf8\xc2a\x9dİP\xe5\xfe\xea37n\xdcx\xa96\x912w\x8cb\x99e\f\xf2\x95\xbd-\xe29ᚸu\xadȒ]\x9f(\xcc\x16\x96\xb0⬭\xecq\x1f\xfd\v?)r:=C\x1fvfч\xad9\xf4\xe1e\xaa\xa4\xac\xd3_L\x9a4I\\4i\xd2g\xfe7\x9fb֭\xc98\av\xe2\xa4N\xba\xa1\xca\x17\xaa\x02$ΐ\x93Q,\xb3\x82~\xbe\xb2\xb7C<\xe7\x16%\x9d\xcey\xf3\xb7\x1e\xe9,\x91u\x92\xac\xe9dg~ܤ\xc8\xe9\xc4\xfe\x97t\xda7\x97\x8a֡\x1c\x9d\xfeI\xf8?\u007f\xfd\x97T\xa7\xcf\xfd\xa7\xbf:şT\xb6!~o\x14qR'\xfdP\xe5^Ʃ\x9a^\xedOK\x8cc\x8cb\x99#\xc2tʒu*Z~\x9d\x16\x94\xcb:md\x8f\a\xa4\xa3ShR\xd4\xd3\xe95\xe1\x89\xd7.\x16-\x1f\x92t\xfa\xbe\xfb\xef\xbf\xff?\xa8NS\xfe\x9f\xfb\x1c?\x9b2\x97\xf5\x881\x10-\x8e\xea\xa4\x1b\xaa,\x91`\xd7N\xfa\xb1̑\xf3\x959\x9d\xf2\xcb\xe9\xf3\xa1Ge\x9d\xf2\xd8\x05S\xe1J\xf5\xa4\xa8\xa7\xd39!O\x10J\xd8\b\x9e<P\xfeÿe:\x9d\xf2\xaed\x1fQm\x94\\\x14ǒ\x10J\vF\x8a\x93:\xe9\x87*Snt\x9f\xaa\xe9\x8e\xf2\x17\x9f\xe3\x1e\x83Xf\xd1$_\xf9bξ\xeb-\xee\x8b\xd7\xd7R\x1fv\n\xe5\av>*,\xde\xdbIm\x11\xbe\xder\xa0(\xe7e\x91\x9f\x1c\xea\xec\xec\x9c\xfflg\xe75\xf1\xb5N\xf7\xb3\x9dC\xbf|\xd6\xdd\xf9\x9axn~GG\xe7\xeb\xcc\x1d\xf9c\xdc\u007f\x90t\xea\xea\x98_t\xa0c\xa3 \xff&@\x05i7^\x060R\x9c\xd4\xc9 T\x99\x96\xb3K\xa7D9>\x19\xc42\x8b\x91\xf3\x95\x87聥%[\xf0\xb4\b\xc2jqh_Q\x96w\xed\x81\"\xf7Jv\x86\xf7L\xb6w\xedk\xacNh\xf2\x97\x82\xcc\x01\xf1;\xf4\xd1\xfd+\xf61\xd4w\xc4N7+s/\xbf(\xdfd\xf4\xf7\u007f\xf3\xdf$\x9d\x06_.\xf7f/\x97\xef\xf0kN\n\xfbM\x02`#\x8e\xea\x04\xac\x93\xb5SoR\x8f?x\x9e\xfdû\xef^\xfb\xe5\xea\x9ck\xf2-\xb0\u007f\xf7W\xb2N\xa1*\xdb]\x05\xdaϖ\x81\x9d@\xa78'z\x9d\x8e(?\xe89\xb4\xb8C\xd6\xe9G\xffE\xa3S_:n(\x1f]\xa0S\x9c\x13\xbdN\xe7\xd8\x109\xe5\xa2\xf0+\xe5\\0\xec\xe8\x04F\x19\xe8\x14\u05fc.\x8d4h'\xf5\x19z\xc6\xf3lKG˳\x9e\xf5C\xd0i\x8c\x80Nq\x8d4\xd2\xf0\x9avҀ\xa1#Ox\xdd\xde'\x8e\f\x05\xbe\x8d\xfb\xb7\xd0\xc9a\xa0S\"\x02\x9d\xc6\b蔈@\xa71\x02:%0u\xd0\xc9a\xa0S\xc22\xb8a!\xbb\x05v\xc5!\xf8\xe4\x18\xd0)a\x99\xa3|A㳻\xe0\x93S@\xa7De\x80}}\xf0C\xbf\xff\xde}\v\x13\xe5v\xc8\xf8\a:%*\x03\x84dfޗ\x969{\xd2\xc3\xd0\xc9)\xa0S\xa22\xb8\xe7s\x9f\x9dt\u007fJJJf;\xc2V\x9c\x02:%,3\xa6\x97U\x1f\xba\xd0\xd5\xf5\x12\xbe/\xe8\x18\x8e\xea\xa4\x1b\xaa<P#}\xb5\xbd&\x91\xae\x97\x1bS\x83!\xd1}\xc5iI\xf3TA\x18\xdfQ2\xbdFF`\x16\x05\x84\x90\xa4.\x9d\n'\xc8~\x96\xb1\xa7\xc9\xd9\x03\xa3\x8a\x93:\xe9\x87*\xf7U\x1d\xef\xa6$\xd0w\xdb\xe9\xdaM\r\xc6\x05e\xa6m(HR]\xbc\xbc\xde\xe9\x8e|/kT\x04f\xd1\xddܼA7뫝\xa8\xb3(\x80\x038\xa9\x93~\xa8r_U\xa4؟\xf1N\x1fY\x17\x1e\x11frk\xb8U\xdatu\xd2/\x05\xa3\x8a\x93:\xe9\x87*'\xb6N]D\xe7\xb7A\xa0S\xa2\xe2\xa8N\xa2^\xa8r\xc2\xe9ԗD\xc8d\xe9\xab\xfa\x83\xa9r\x9e\x9e\xf6\v\xe5Y\x1b\x9fQґCpQ˺\xa9\xcbb1qU-\x9d\x91\xf4\x10+\v͂\xa1/N\x13tr\x1egu\xd2\vU\xee\xabj\xdcUUۜ@\x83\xb9\xed\xcdͮ2i\xeax\xf3vR\xd6ܬM\x10d\x19*-K<\x17\xf92.jY?u\xf9L\xed\x14\x92ZV\x91,\x85\x8e\x85f!\xea\xea4\xd8\xdb4;EgDo\x92m\x84\xf7\r\x9c\xd6I/T\xb9\xbf\xaa\xf6D\xf7\x99\xba\xed\t\xe4\x93(&\x05\xf6u\xfd\x93\xbd\xa2\xeb\xa2x\xbdh\xb9\xaa\x90\x8bZ\xd6O]\x16])\xd4\xcb\xdcT\xe5YR$\x9d\x16\xd2c\x9b\xde/\xd0Mz\xdb&\xa0\x93.\x0e\xeb$\x86\x85*\x8b\xe2)&\xd2@MB\x9d\x9a\x98\xe8$\xa5#\a\xf2'e\xb8\xa8e\x83\xd4e\xd1\xc5~K\xa6̥<\x8b\xa8\xd3K\xfb\xabf\xea\x1e\x9d\xcc4\x89\x16褋\x93:\xe9\x86*\ahN\xa8$z\x13\x9dT\xe9\xc8\n\\Բ~\xea\xb2(\x9d\xdeE\xa7\x13\xa5Y\xaf\x14:\x8d.N\xea\xa4\x1f\xaa\xdc(\xefoM\t\xf5\xeb\xb8&:\xa9ґ\xa3ƚN\xba\xa5\xd0itqT'\xddP\xe5z\xe9\xb0\xd4W\x13\f\xb1L\x04Lt\xf2^g\xbfƴ2\xfc/\x11qR\xa7Iҿ\b\u007f\x0f\xef\x1b8\xab\x93~\xa8rw\xd5\xfe\xae\x97ګ\x13\xe7\xe04\xd8\xd6\xdc\xec*hn\xee\x0f\x8c\xec\x85\xed\xd6Y\xc2\x13\xbf\xe8X.\x05%GO7\xed\xb4Ml/p5w\xf3\xb3\x90\xee\x8aX\xd7\xdc\x1c\xf6iC\xbb\xdeOe0E\x9e\xfb\x82,ʫ_\xbb\u007f҃\xdf3\xd2\x05:ł\x93:\x19\x84*\xf76\xd6\xd6ԟ\x8a\xd4n|\xd1.\xa7*\x93*q E\x9a\x98rFS\xa3hgy (9z\x8aiO\xaeSS\xe9c17\v\xe9\x9e=Fد\f\xf4NYt\xa2W{\xbf\x1eS\xe4\x8b\xcfɢ|\xf5\x8bϿ\xfa\xfc\x97~f\xa0\vt\x8a\x05Gu\x02N\xb2g&!\xda_ƙ\x14p\x85\xf2\xb9\x9fӇ\x9f\xffgŏ\xef=8\xe9\xfeo\xbd\xfd\xf6\xf3_\xbe\xef\xbe/\xff:\xa8\xd3\xf7>?\xe9\xfe\xaf\xbd\xcdM<\xff\xe5\xcfMz\xf0\xbb\xd0\xc9\x00\xe8\x94\xc0\xf4\x9e\xd0~\x80\x1c\xae\xd3\xfd\x8aM\x9f\xfbޫ\xcfS\xb5\x1e|\xee\xd5_\u007f\xe5+\x01\x9d\xfe\xf5\xc1\u007f\xa5\a\xb0\xafq\x13\x0f~\xf3\u05ef\xfe\xec\xcb\xd0\xc9\x00\xe84\xa1\xe0u\x92O\xf6\x94S\xba/|\xf7\xed \xbf\xbe?\xa0\xd3\x17\u007f\xa6\x18\x17\x9c\xf8\xec\xcf\xe5:\xd0I\x17\xe84\xa1\xe0ubC\x11\xf7\u007fK\xd1iү\xe5\xff\u007fNO\xe6&M\n\xe8t\x9f|C\x117\xf1\xd5\xfb\xbe\xf2\xad\x9fC'#\xa0ӄ\x82\xd7I\xe2\xb9\xcf\xcb\xffߧ\xe8\xf4ů\xfe\xfc\xedW\x83:MR\x8eE\xa1\x89\xb7\u007f\xf6\xb5/\xdf\xf7M\xe8d\x00t\x9aP\x84\xe9\xf4\xe5\xaf)\x1a)'{\x9f}\x95^(\x05u\xfa\xc27\x95j\xc1\t\xc6\xf3\xf7A'\x03\xa0ӄ\x82\xd7\xe9K?{\xf5\xf9\xaf|\xe1UY\x91\xe7\xeeW\x86\"\xbe\xf9\xea\xcf>\x1f\xd4\xe9\xb9\xfb\xbe\xf5\xebW\x9f\xfb\x127\xf1\xa5\xef\xbd\xfa\xea7\x1f\x84N\x06@\xa7\t\x05\x13I\xb9\nz\xfb\xbb\x9f\xff\xcc\xfd_}5p\xc8\xf9\xee祁\xf2\x9f=8\xe9\xfeo\x06uz\xfb\xb9/~v\xd2\x17\x9f\xe3&\xbe\xf7\xc5I\xf7}\xf9y\xe8d\x00t\x9aPp\xa7y#\x03:\xe9\x02\x9d&\x14\xd0it\x81N\x13\n\xe84\xba@\xa7\t\x05t\x1a]\xa0ӄ\x02:\x8d.\xd0iB\xa1\x1f\xa3\x12\vfs\x9a\x988\xaa\x93n\xa82\xe5\xcc\xfe\x9a\xba\xf6\b\xed\x80Bİf\xdb9A\xf6\x9bU\x01j\x9c\xd4I?TY\x1cl\xacj\xbb\xd0^\xa5\x97\xb3\r\xd4D\fk\xb6\x1d\xc42[\xc6I\x9d\xf4C\x95\xc5\xc6\xean\xa6\x9a\xf6;v \x12\xbaa\xcd6\x83\x1cY\xcb8\xa9\x93~\xa8rw\x95\xf4\xad\xdcQ\xde5\x12\r\xdd\f\n\x9b\x81N\x96qT'Q/T\xb9\xad:\x91~\x8af\x141\vk\xbe\xe8\x16\x84\xad\xbfY[8\xff\x89w\xb9RӰf\xcao\xca\x17\xbb\xbdO\xbd.j@,\xb3e\x9c\xd5I/TyO\xfd\x99]U\xb5\x87\x12*\x04vt0\tk\xbe\xdeҒ_\x94\xedݸv.\x9fBa\x1a\xd6,\x8a\x1d\x9e\xaf\xef\xed\xd8)\xecS\x15\x1a\xc52\x83H8\xab\x93^\xa8r\x9d\x14\xaa\\[\x87cT\x14D\x0e\x1c\x13\x1f\x15J\xae\x89C\xea\xf8>Ӱ\xe6\xeb\xf9O\xb0\x9c\xb2\x16u3\xa3Xf\x10\t\x87u\x12\xc3C\x95\xeb\xa5\xf1\x88\xfe\xc4\nU\x1e-\xcct\xca\n\x8bG2\x0fk\xee\x10~\xa5m$\x1a\xc72\x83H8\xa9\x93~\xa8r\x93<\xf6۴Ǩ\x19\ba\xa6\xd3\xd7\xc3\xcbLÚ\xf7\t\xd7\xc3[I-q\xedd\x15'u\xd2\x0fUn\xaf\x91>\x8clęE\x14\x98\xe9T\xaeShF\x87:+=\x04F\xf6,\xe3\xa8N\xba\xa1\xca}\xd2@y\u007f5n\x8b\x88\x82\xd1\xd0\xe9\x9aw\xe5\x10\xfdo\xe3F\xed\x1f\xa0\x93e\x9c\xd4I?TYl\xafn\xef>U\xbb\vC\x11&\x98\x855\xbf\xfb\x8b\u03a2\x95\x9d\x9d\x16\xc3e)\x1d\xf3\x8b\x0etl\x14\x0eh\xcbuc\x99A$\x9c\xd4\xc9 TY\xec\xdaS\xb3\xab\x1d6\x99a\x16\xd6|Q\x90xʠy\x04^.\xf7f/?\x12V\xac\x1b\xcb\f\"\xe1\xa8N`|\xa1\x17\xcb\f\"\x01\x9d@\x04\xc2c\x99A$\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\xc3Q\x9d\xf4B\x95\ak\xabdjM\x1a\x83\xf8\x80\vv\x06Z\x9c\xd4I7Ty\xa0\xaa\xbd\x9b\xd2^u¬9\x183\x9a\xb8\xafJs\xc1\xce@\x8b\x93:\xe9\x87*\x9fbv\r\xd4⋟q\xcc\xecEf5\x80\x84\x93:\xe9\x87*K\xd4\xe3\xbb\xed\xf1L\x06t\x8a\x0eGu\x12\xf5B\x95\x19R\x12\v\x18+\xba\x16\xa6\xba\xd2\xe6I_\x14ܐ\x91\x94\xb1\x81\xfe_L\\UKg$=\xc4\xde\xfa\x94p\xbe\f\x91\x0fv\xe6*\x14\xb3\xa2\v.2S\xea\xacv\xce\xd4\x19K'j@\x9f\xb3:\xe9\x85*3\xa4$K0F4Mͨh,#\x15t\xb2\xc0\xb5\xaa~\x95+\x97\xbe\xc1\xd5N!\xa9e\x15\xc9\vE\xb1\xffP\xf3\x8c\xcc\xe6\xe6f)\x99\"\x18\xec\xccU薊\xda\n\\\xac\xbc`rq\xfd\xbaԌ\t\x1a1\xe1\xacNz\xa1ʔ\vU\xf8\n\xf5\xd810m\xde\x00\xcbk\xa3W\xb3\xfb\xa5\x1fH\x93\x1f])\xf4E\xc9M\x95\xaa\xa8N\xf6\x02\xe1d\\\x05ɰ2\xa6S=\xa9\x11Y\xa4\xd8vqB\xe2\xb0Nbx\xa82\xa5\xb1.r\x130\x9aԓ@\xa4\x94X0K\xfaof\x01}p\xb1\aI\x11#\x9dB\x15B:-\x9a>\xc8H/\x10'$N\xea\xa4\x1f\xaaL\xa9Ad\xe5\x18\xb2\x8e\x04\u007f\xbdd\xce\x02\xe9\xbfy\xb3E^\x11#\x9dB\x15B\x93\x19ʅ\xd6\x04\r@rR'\xfdPe\x96\x03\xab\x8a\xa0\a\xce\xd2\xc8\x1d\x9d\xa6K\xffM\x97\x8eNZ\x9d\xaa_\x92+\x19鴊M\xe6No\x97\x98\xa0CK\x8e\xea\xa4\x1b\xaa\xcc.\x9dF\xf77^AD\xfa\xd33ٛ[\xf1Rv\xdeǮy\xb6K\x81ͼN\x99\x99\xf4\xb2\x97(\xa7\xe4::%\xad\x10\xc5\x1b\xb3\xd9\xe4~\xb9\xd6\xe3k\xc4\t\x89\x93:\x19\x84*S\xb7\xf0[icI\xd3\x0337\xd4\x17\x13vҐ;yE\xfd\x8aɹ\xd2h]A\x9b\xd8^\xe0\x92~\x93\xad\xccU\xb1'sj7\x1f쬪0'u͚9dJ\xcd\x19Q\\A\x16\xd5\xed) \x13\xf4\x961'u2\nU\xbe\x80\xbbVƖ\xaeE\xe9ɳ\xe5\x17aݬ\xa4Y\xf2\xe7N\x84\xb8NM\xa5\x8f\xc5\xf4\xd9@qJR&\x8bD\x0f\x05;\xab*te&%?\xf4\xb8\\w\u007ffjʜ\xfdF\xb3Jp\x1c\xd5\t\x80\xc4\x06:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x1a7,\"\xa9\xb9g\xcc*\x811\x05:\x8d\x1b\xba\x9bjf\xa6NԈ\xa0q\x82\xa3:\xe9\x85*\xb3\xa4\x9c]ջ\x0ea?\x89\x82&\x82\xacܸ\xc6I\x9dtC\x95ž\xda]R)\xbe\x91kN\x1bi3\xab\x02\xc6\x12'u\xd2\x0fUn\xaec_\xad\x1e\xack6i\r\xa0S\xdc\xe3\xa4N\xfa\xa1ʍr8\xd8\x1e$W\x9a\x03\x9d\xe2\x1cGu\x12\xf5B\x95\xfbj\x9b\xfa\x06\xfb\x9aq\xb2\x17\x05'H\x93Y\x150\x968\xab\x93n\xa8\xf2@#-ݏ\xf4\x95(\x18L\x9d}\xa8{\x82\xe6\x15\x8f\v\x9c\xd5I/Ty\xb0\xb1\x8e\xe5\x1b5\xe2'4\xa2`?!d\x81Y%0f8\xac\x93\x18\x1e\xaa\xdc\\7 \x95\xe2\a\x9e\xcc\xe9O\x9d\xbe\xae\t\x19\x9f\xf1\x8b\x93:\xe9\x87*W\xcb\xf9`R6,\x88L\x1b\xc1\x80M\\\xe3\xa4N\xfa\xa1\xca\xd0)z0\xb2\x17\xe78\xaa\x93n\xa8r\x93t\xb27P\x871+s\xa0S\x9c\xe3\xa4N\xfa\xa1\xca\x03\xdb\xebNu\x9f\xaaێ\xa1=s\xa0S\x9c\xe3\xa4N\x06\xa1ʃm\xbbjv\xb5a`ό\xc1\xee\xf6E.\xfc\xae\\\\\xe3\xa8N`$,$d\xda\x1e\xb3J`L\x81N\xe3\x86\xee\xe384\xc5;\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN@\xcd\xe0\xc0\xc0\xc0`\xf0?`\t\xe8\x04T\x1c\x9aL\bI\xea\xefO\xa2\xffMFX\x9bE\xa0\x13\x90\xd83\xa7W\xfa\xbf\x8eԷ\xb5\x9d\x12\xc5Smm\xf5\xa4Τ\xd1X\xd37'\xce\xee\tvT'\xfdPen\x12\x18\xf3\x1dAh1\xab\x13\x99\rd\xf2v\xa3\xbfU\x902y\xa2\x8e\x04o\xb4\xed\x96u*&\x93G[\xab\x98\u05edb\xf2\x1a\xb3*\x8e\xe2\xa4N\xfa\xa1\xca\xfc$0\xe6\xf5N\xf7N\xb3:\x91\xe9k\x9e]f\xf0\xa7u\x93k\x94\xa9p\x9d\xba\x9b]\xfa͚l{\xcd\f\u05ed\xe3\x9cnq\x88\xfa)\xebLj8\x8a\x93:\xe9\x87*s\x93 \"Y#\xd4I\x14\x17\x18\xe8t\xc1\xb5\"0\x19\xae\x93(\x1a\xe84{\x91nqL\x18\xac\xdb\xf2r\xddb\x8eUq\xf5\x8dJ'u\xd2\x0fU\xe6&ADFO\xa7\x82\xf4\xe0\x9b\x99\x05\x9d2F_\xa7GMu\xeaO/0\xab\xe2 \x8e\xea$\xea\x85*s\x93 \"Y\x1b\x9f\xf1\xe6<\xf5\x1bUYw2\x91I\xe6ޤ\a\xd3\\\x8f\xa7\xa77\x15\xa7d\xb2\x84\xd0E\xe9\xaei\v\xe4\x1f\xb2\xa1:\x15Ӻ\x0f\xb0Q\x87\xda9Sg,\x95-\x1aL\x0e\x1e\x9c\xf4u*~8=eA\x17}룍\x1f\x17\xcb\xe8c]\xbd2\xdf\f\xa9\x06\xd7Y8\xef湷z\xbd\x1d\x1bsV^\x13\xc5k\xe5^w\xfeS\x17i\xf1E\xb7 <5\xe4\x15\x84\x9c\xebܺ\x1d\x11\x04a\xab\xb8\x93>\xb6\xb0I\xc6\xd7Y'C?]\xee)\xdax\x9dMv>\x91\xef^\xfcT\xfe\x90\xdc\xfb\xaa\xa48J\x19qV'\xbdPe>_\x19D\"K\xf8zK\xcb\x12\xcfE\xbel\xb0f\x9dL\r\xff!QS2Y\x9aIRפU0\x05\x1en\xaa[0Y\xcal\xa1:u\xe7N^Ǧ\v&\x17\u05efK͐\x12\x9a۹\xe8s]\x9dH\xc6\xf6\xed\x19I\xa7\xc4\xfeCӊ{\xc5\u07b2\xe4\xe6\xfe\xfeC\xcd32\x9b\x9b\x9b\xa51$\xbe3\x1d:\xb2\x85\x8d%\xc2\xe2\x9dy\xfb\x98.\xeb;Z\x9e\x12\xe85\xd1\xd0/v\n\xbf\x10\u007f:\xf7\xa7\xbf\x12\xb9u\xbbޙ\xff\xec\x1f\xc4?\xfc \xbb\xf3ڵ\xce\u03a2\x95\x9d\x9d\x9d/\xb3>\x9e\x116v\xec\xf3>J\x1d\xfa\xe5\xdcgZ:\x0e,\x16ޕ;?\x14Oq4\xce\xea\xa4\x17\xaa\xccM\x82\x88d\x15\xd17\xe7\xebE\xcbU\x85\xbd\x17dzU\xa5\xe9\xb9T\xa3z\xb1\xe0a\x16\xb9\xc6\u07bff-d\xc5T\xa7\n\x97t\x1aPO\xd8\xd8C\x1b\xd9.?\t%\xcb\xea\xea4\x93\x1e\x00\x06f̡\x93e\xechT \x9f_\x05O\xf6T\x9d\xe9\xe1]+v\bG\xc4g\xd6\xd3\xe5o\xa1\x87\xa8\xa1%\xabY\xf1\xd03˯y\xe5\xb3<n\xddv\xb2\xa3\xd13\xcfH\xc5\xc1\x93\xbd#\xc2\x01\xfax\x8e\r\x00\x1e\xf02\x91\xf6\xe5(G\xa7n\x12Go\xc4\x0e\xeb$\x86\x87*\xf3\x93 \x12Y[\xd9\xe3\x01\xe1\x1aWv\x81\x04Pe-\xa7o\xa7{w\xbf\xb8\x82\xed\xf0\xbd\x1b\xe6MO&\xb3X\xf1\x82\xb2UD>\xa9^4}\x90!_x\xec1\xd3\xe9q\xf6\xb8\x81\xf4\xb1\xb2S\xe2@\xb2\x9cE\x1b\xd4Iՙ\x1e\xde\x16j\xc25q\xebZ:}\xed\xc0\x13\x85\xd9\xc2\x12\xa9\xfc\xfa\xa3yO\xc9Vp\xeb\xf6\xfa\xdc_\x89׳;\xa4\xe2\xa0Nk\v\x87ޥx\xa9e\xafy\v7\x1e\xf8Րb\x13]\"C\x8b\x9d\xc7I\x9d\xf4C\x95Փ\xc0\x18\xf9r\xbdSP\r\x1e7\xd7˨o`H\xdf/\xb6\xb9DI\xa7\xb6\xb4i+v5g\xca:\xa5%ϔ\x0eSb\x86\"\xa1\xf4\x8c\x8f\xef3\x1e\x8ah&l\xb4h\xdeRq\u007f\x8a|b\x19\xd4Iՙ\x1e\xde\x0e\xf1\x9c[\x94t:\xe7\xcd\xdfz\xa4\xb3D\xd6Il\x11:\xe5\t~ݞ\xf8\x17\xb1C9\xf6\x04uZ\xa2\\G=%2!ˋ\x84\xbc\xbd\x8aOm$\x8e\xf6\x1c'u\xd2\x0fU\xe6'A$\xb26\xb2G\xf5\xd1\xc9\x00N\xa7\x99s\xd8\xdb\xd8BY\xa7\xd4S\x17\x92+\xd8T\xee\xf4v\t\xe9\x1c\xb1\x9f\x1b\xba\xd3\xd5i){\xac&쬱>uP9דu\xaa~Iә\x1eL\xa7,Y\xa7\xa2\xe5l8\xa1\\\xd6\xe9u\xef\xd6|\xf9\x12\x88_\xb7#9Cʹ\x9e\xacӁ\xd7\xd8\xd1\xe9\x9c\x04\xfd\xfb\xb9\xadT\xa4k-\xf3\x0f\xc8U\xca\\q\xf4\x11\x8b\xa3:\xe9\x86*s\x93 \"Y^\xba'\x0e\x15\xad4\xab'\xaat\x9aƎ\x1972\x94\x93=Q\xdc\xefb\x87\xa2\xfd\xb2*\x8f\xcb7\x15,\x9a\x1e\x1cE\xd0\xd5)\x9d\x1a983\x93M\x0f\xa6֧(\xafU&-\xe8euԝ](;.j\xe0t\xcag\x82\f=*\xe94\xb4\xfc\a\xe2\xb3%\xd2Q\x86_\xb7\xa1\xc5Gr\xe4s=q%-\xf8\x03\xbb`\xea\x90o\x9b\xd8J\x0fb;\x05\xe9\x8f+\x9f\x95jܘ9O;\xb71\xc4I\x9d\xf4C\x95\xb9I\x10\x91,\xe1\x89_t,\xcfy٬\x1e}\x8bJ\xa9\xe8\xdf\xee:џ\x9b\xd9-\x96\x91E\x1b\xd6d\x90Ԋ\xb6\xfe\xe6\xd9\x05m\x83\xfd\xf3қ\xe8\x1b\xd8\n\xb2\xa8nO\x01\xa9\x95\xeawM\xae\b4\xd5\x1fٛ\xd7\xd64'E\xbe\xc0Z1]9ףDž\x8a=\x99SYuUg\v\xc8T\xcd/I^\xcc\xd9w\xbd\xc5}\xf1\xfaڒש\f\xe5\av>*,\xde\xdby\xbd\xf3;\xde\xd7\xc5\xdfdo켮Y\xb7\xad\x859ʰ\xddά}GJ<\xaf\xb1\xb2\xb9k[\x8e<ä\xda)x~p\x84N\xca\xc6U\x90x\xfa\xc0\xd2I\x9d\fB\x95\xb9I\x10\x89\xa2\x9d\xe5\xd9\u07b5\xaf\x99U\xa3\xef\xd8i\x84\xd4&\x93\xa9u\xecr\xe6F\xc5\fWꢚ\xe9\xae\xcc\r\xec&\xf1\xf6Z\xfa\xb8\x8aVڟ\x99\x9a2g\xbf\xd2b\xd5\x03\x81\v\x90:\xd2\x15\xf8\x82FW@\xa7\x99e\x8b\x92\xd3s\x15ͺ\xc8\xc3JՁ┤L\xf9\xaa\x8b\xef\xacz\xaaf\xe8z(O\x10Z\xb2\x05O\x8b \xac\x16\x87\xf6\x15ey\xd7\x1e(r\xaf젗B\x1bō\x820\xb7C\xb3n/\v땦\xd77\xe6\xcc_)_+v\x94,\xceY\xce\x14\xfa\xe9\xf2\x9d\xf9n\xefJ٦椥b\x1c\xe1\xa8N nY\xeaRԑ>\x9eU\xbe\xa0A\xf4>Z\xefw\x99\x9d\x97\xef!#\xbc\x9a\xb9\x96\xd5aVEa\xbb\xab \xae\xbe\x94\x05\x9d\x80DE\xba<\x900x\xa2-\xf0\x05\x8d\xb6\x13z\xbbj]\xaa\xc9\x0e\\\x93\xf2\xb082Z\x16\xbfkVE\xa6/=\xben(\x87N\xc0\neMb\xa6\xd1]\xe9\nݩKGt\x1d\xbc\xb3c\xa8\xe4\af\x95\xe2\x15\xe8\x04\xa2g\x80d\x14\xa7k\xc6\x19l\xe6\xba\xf0\xf5\u007f\xf6F\xf1Q@|\x02\x9d\x80\x05ʦf\x8e\xf6\x17=\u007f\xe0)y٬N\xdc\x02\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\x8e\x131\xb0y\\\xa79C'\xe04Jn\xb3\xfe\x1f\xc7w\x9a3t\x02#!\x90\xc5l\x85@n\xb3>\\\x9as\xdce&\x9b\xe2\xb4N\xa7\xaa\x94\xbb\x94\xbb\xf7\xd4\xec\xef\x0e\x9b\x04\xd1\x10s\x06\xb1\xedHY\xccV\x17\x87\xfbJ\x15G\x87\xf7H`2\xf8E\xabx\xcbL6\xc5a\x9d\xfa\xaa\x0f\xc9\xdf1\xeb\xaen\xeej\xae\xee\xd6L\x82\xa8\x88=\x83\xd8f\xe4,f\xabq\xcf\xfa:\x1d\xf1\x04\x9d\f\xea\x14o\x99ɦ8\xacS}c\xb7\xa4\xd3\r)i\xe5P\xed\r\xd5$\x88\x96\x983\x88m%\x98\xc5l-\x9fV_'q(8\x15\xd2)\xce2\x93MqV\xa7S5\x03\xb2Ng\xaa\xd9M\xfc\x03\xd5gT\x93 Zb\xce \xb6\x95`\x16\xb3-:\x85\xe0t\x8a\xaf\xccdS\x1cթ\xbf\xbaK\x94uj\x94\xbf\b]ߤ\x9a\x04\x11\xf8g\xc1}`c\x91\xe7\x89\xd7ٓ\xd83\x88et\xb3\x98\x19]\vS]i\xf3\xa4\xc2\r\x19I\x19\x1bD\xf6\x834Sօ\x87*\x8b|\x16\xb3^ܳ\n\xd52p:դ\xc9)q\xd7<\x02w\x01\xc6\xe9\x14_\x99ɦ8\xaaS}\xa3\xa8\xe8\xb4K\x8e&8\xb4G5\t\"p\xb1\xc5-xw\xee͖\xf2Sc\xcf \x96\xd1\xcfb\x16Ŧ\xa9\x19\x15\x8de\xa4\x82N\x16\xb8Vկr\xe5\xd2Ӈ\xda)dښ\xb2i\xeaPe\x91\xcfb\u058b{\xe6Q/\x03\xa7\xd3B\xa2\xe4\x10\x9d\xeb\xec\x9c\x1f<\xc4\xf1:\xc5Uf\xb2)\x9fy\x1c\x00`\x13#8:\x01\x00\xd4@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m\x98\xeb4\xb0f\xf6TW\xfa\xc2C\xe1\u007f\xd9@\x1eV\x1eF\xc0\xbd\x8ai\xae\xf4\xc6\xe0Ӂ{\xf4\xa1\x96,\nU\xa8#\v\xc3\x1a\xf1\xac#\xc5\x11\xffn\x82a\xf7\x9a\x053AZn\xb3E5\xc1\x96\xed\t\xc6\x12S\x9dj\\ʏ\x12\xcf\xfbP\xfb'[^\xfe\n\xd6w{\xe0ن$6\x97\xb8\xd0I\xbd`&\xc8\xcbm\xb6\xa8&ز=\xc1Xb\xa6\xd3RB\x16\x9e\x10?\xe9]\xe5\"\x99\xf74\u007f\xb3\xe5\xe5\x9fE\x96~r/\xd0\xf3=B\xc2t\xea\xdeЬ\xd7.\xc8\bu2\xec^\xb5`&(\xcbm\xb6\xa8&ز=\xc1Xb\xa2S\x13!\xdb\xe5\xa9\xe3\x84\xd4h\xfeh\xcb˟N\xbaBO\xf4t2c\x84:\x19\xa2Z0\x13\x94\xe5\x1e!\xb6lO0\x96D\xd6\xe9^Zh_-&\xd35\u007f\xb5\xe5\xe5O#ݡ'\xf1\xa4\x93j\xc1L\x80N@\"\xb2Nm\x84\f\x04\xa6\xfb6tIE\x8b\xd2]I3W\x89~\xf5\xcb?\xb0t\xba+e\xe1q\xb9*\xff\xa4\xbfx\x9a+yN\x8dꬩ\x97\x96\xa5,d\xd7%s\xa4˲\x80\x0f+\xa4g\xddL'qi\xbakzY\xe8\x82D\xaf\x9bS\vR\xa7λ\xc0t\xaa%\xb3\xe4\xa2\n\xe9ɺ\x0fX\xebU\x1fHE\xdc\x02ג\r\x83\xc5i\x0fd4\xd2\xc9Y\xae\xb4\x9b\xacD(\x00\x00\x1e\xe5IDAT\xa5\xdc\xf5N\xff\n\xb6\xc8g\x82}\a\x16,\xb0wK\xd2jz\x0e\xb6\t,\xb7\xd2Wh\xf5\xb4-\x14\xf8\x99\xe9o\xcfYd\x85\x1f\x8c?\"봊\xccД\x14\x13\x92\x9e\x91F\x1f>P\xbd\xfcǧ\x12\u05ec鄬\xf1k\x9e\xf4&\x93\x94\xd93\by\x88\xeb\xa3\xdeE\xa6\xb2>\xe8\x1e\xb3&\xd7E\xe6\xe5\xd6)\u007fس\x88^\xa9\xe5\x0e0;\xd2HZ\n!\xb3\xee)\xfb\xbb^7U\x84\xa4\xcdrMɤ;\xfa\a.\xd2+\x95\xcd gh\xeb\xa5\xe9$\x99\xb6\x9e\xf9\x89f\x81kIq*Is\x11\xd2XL\x1e\xa0e\x99\xfe\x80N\x87\x92\xc8\xd4ٴ$x\xed\x13X0\x8dN|ϡ6\x81\xe5\x96\xfb\xe2VO\xd3B\x81\x9f\x99\xc1\xf6\x84N\xe3\x93\xc8:- \x05\xea\x826\x92\xc4\x0e:\xa7\xa6\x92\r\xfc\xcb?\x90LV\xd0\xfd\xe5T\ni\xd4<YHVQ%^J&\x87\x82}\xbc4\x99\xac\xa1e\xfb]\xa4\xd6ot\xb2G\xa6wљ\xb9\xc8\x1ee\u007f\xd7\xeb\x86\x10\xaa\xe1\a\xf3\xa4\x83\xdbBY\xe4\x97\xc84\xa9\xf5\f\xfa\xce\xdf\xec\"\xbb4\vL\xff2\xb3\xd7\u007f/\x97\xb8\x1e\xa8\xbfǮ\v/(\xdd\x0fNe\xfd߫ \x0f\x84\x8e\"\xf2\x82it\xe2z\xe6\xdb(\xcb-\xf5\xa5Z=U\v\x05\xbe\xa1\xc1\xf6\xf4\xd7W\x9d\xf2\x83\xf1Gd\x9d\xe6h\xdf$W\x902\xe5\xffb\xfe\xe5_A\x16H\xc5\xfb\xd9\xd1L\xf5d\x9alKun[\xb0\x8f\x85\xca\x1eZGR\xef\x19\xea$\x1dl\x8a\xd9\\\xa4}T\xa7\x9b\\y\xd9>Le\x95\x9a\xe5\v\xbbǙU\xb4u_\xb0\xb5j\x81\x95~{\t\xa9`e\xb3\xd9>.u_F\xe6I\xb52I\xe0@i\xa4S\xa8g\xbe\r\xaf\x93j\xf5T-\x14\xf8\x86\x06\xdb\x13\x8cS\"\xeb\xf4\x10Y\xaa)Q\x86\x8e+\xd8a+\xf4\xf2O#MR\xf1'\x93I\xbf\xfa\xc9Cd\xce\x19\xf5h\xf3\xbd$e\xc8\xec\xdeTzff\xa0\x93|)T͆$\xa4}4\xbc\x1b\u007f2;\xb6\xf8\x95=\xf1^\n\xeb\xf4^\x1a\xdbyk\xc9\xccPk\xd5\x02\xd7\xca箟\x10y\x9e\xb9\xa4Z\xe9~\xa6\xb2ȃ\x83\xa1\xfeuu\xe2z\xe6\xdbp:\xa9WO\xbd,2\xaa\x99\xe9oO0N\x89\xac\xd3\xc3$W[t\xef̮\xb2Eӈ\xea\xe5\xff\x90^\xe5̑p\x91v\xd5\x13\xff\x19z\xa5\x92\x9c\xbb\x87\xbb\x12\x1f D\xb9\x8e\x98\xc3\xce\xe5\xf4u\x92\x8fo{\xd8\xff\xd2\xfe\x1e\xde\xcd\a\x81n\xf6Ho\xfcKٱ\xaa\x9d\xcc\xe6Z+\x03\x03\xdc\x02\xd7\xca\xc7\x05:\x17v\xe5\xef/ UJ\xad\xc0\xa5\x17\x8f\xaeN\\\xcf|\x1bN'\xf5\xeai\x96EB=3\xbd\xed\t\xc6+\x91u\xaa\xe0\x87\"\x8e\xb3=\xa6:\x8d\rbe\xccQ\xbd\xfc\"\tѨzBϬ\n\x92\xe8Ĕ\xe2\xe0\xa5x7\x99\xa2L-`\x9fdE\x1a(\x0f\xe9\x14\xdeM?!\xf2D\xb3\xa4S\x17I\xbbG\xed\xaf\xe5Z\xcb\r\xf9\x05V\xfe\x12\xa6\x13=\\q\x87%\x05]\x9dB=\xab\xdap:\xa9WO\xbd,\x12\xea\x99\xe9nO0^\x89\xacS7\xf7\xd2\xf7\x93\xc9]\xecΛ\xe2\xfa\v\x1fjNN>T\xae\x10$TO\x18\xf7N\xad\x99EB;I\u007f4G\xa70\x9dº\xf9 \xf0Q\xcf~\xf9\xb2d\x069q/i\xca\a~\x8dN\xaa\x056\xd2ɯ]d\x86Z\xa75Z\x9dTm8\x9d\xfa5G\xa70\x9dT\r\xf5\xb7'\x18\xaf\x98\xdc\x151-t\xf1\xb4\x82^Z\xd3\xeb\x01\xf9Z}\xa9\xfa\xe5Oe\xc7!Ʃ\xfe{\xea'\x03\xf2\xa7+\xb5dJ\xf0F\xa2\a\xa2\xb8v\xd2\xea\x14ލ?E\xe9f\x8d\xacS\x05Y\xd1.\xef\xb3\xfc.\xac^`C\x9df(#\xe4M\x0fU\a\xbaW\x16\xacJ\xe9\xec\xe10\x9d\xf86\xfc\xb5\x93j\xf5\xf4t\xe2\x1a\x1amO0N1\xd1i\x17!\xf5\xf2\xd4!B6\xb0\xb3:\xe9\xbc\xff\xc3tvQ\x15z\xf9\x8b\xc9li7o#\xae\x0fTODe\xcf\xed#\x93\x83\x1e\x04\x86\xbev\x91\xe4O\xa2\xd4I\xaf\x9bb\xb9\x9b{\xd3e\x9d\x06ȴ\x15\xf25>\xbf\v\xab\x17\xd8P\xa7\x15\xca\u07be@\x1e\xf2\x93\x90\x17\xac^>\xdd\xfd0-L'\xbe\x8d\xdeȞ\xb4zz:q\r\x8d\xb6'\x18\xa7\x98\xdd\x02\xbb\x90^$\x9f\xf9\xf0^\xef\xe3\x84̹翗,\x8dNߘG؎\x1ez\xf9\xfb\\\xa4\x98\xeeO])\xec`\xa6z\xf2\x10y\x88\xee\xba\x1f.R\x06\x87\x19\x17\xa6\x90\n*ES\x12\x1bX\xd3\xdc\xcb\xe3\"\x8d\x9f\xdc\xd39:\xe9t\xd3\xef\"\x1b\xee\xf9?\xcc\r\xdcT\x91I\x92\x92\xa5\xd3,\xd5\xd1I\xb5\xc0\x86:\xf5'\xb1E\xba\xb7\x8eL\x15\x83\xfd\xcb\vF\xcf\xdd\xe8_\xfa3I\x98N\xaa6\xf2rK\xe5\xaa\xd5\xd3Ӊkh\xb4=\xf1\xb9\xd38\xc5L\xa7O\n\x02\xc3\n\v\xa4\x91\bB\xa6-\x98=9\xa5\x8c\res/\u007f\x93\x8b<0{:\x91\xef:\xe7\x9f\f\xa4\x10\xd7\xccYI$\xad?\xd4g\xfd\x14\x92<;\x9d\xc8\xe7\x91j\x9df\x13\xf6\xa5\b\x9d\x93=\x9dn\x1a]$mv\x12Y\xa8\xe8\xb4'\xe0\x95j\x17V-\xb0\xa1N\xecs֔\xd9t\x1e\xdc\x1d\xe1ʂ\x15\x13\x92\x9cN\x92*\xc2tR\xb5\x91\x97[.\xe7WOO'\xbe\xa1\xd1\xf6\xc4]\x11\xe3\x133\x9d\xfc\xfe3\xc53\x1ep\xa5/R>?m\xcbLu\xcd,\xfb\xe0C\x17\x19T\x9d\x9c\xf4/\x9d\xeeJ\x9a]-\x9f\x8a\xf1O\x06\x96\xcep=@[\xf0]v?\x9c\xeeJ\x97oj\xd3\xe8ԗ\xf9@\xf2~\xbd\xa1\b\xddnrӒ\xe6\xb45*\x16\xd1E\n\\`\xf1\xbb0\xbf\xc0\xc6:\xf9\xfb\x8aӧ\xa4\xe6\xf2\x8b\xa2,ؽ\xdaY\xae\x94ܾ\x13\xe1:\xf1m\xe4\xe5Vʹ\xd5\xd3Չoh\xb0=\xa1\xd3\xf8\xc4\\\xa7\xf1\xc2\x00\xbb\xc1\b\x80\xb1$qt\xaa\xe0\x86\x11\x00\x18\x13\x12D\xa7\xbe\xc1\xc6\a\\\xa1a\x04\x00Ƅ\x04\xd1)\x97\x10\x1c\x9c\xc0\x98\x93 :U'\xa5\xc1&0\xe6$\x88N\x00\xc4\x03\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1bv\xebt\xb6\xe4\xb6Y\x95h\xb8Sr֬\n\x00q\x87\xa9N\x1fm\xc9\xf3\x94\xfb\xccj\x058(4D]7\x12\xbe\x83\xc2A\xb3:V\xb8\xec=oVń\x91\xf7\x10-\x97\xe6\n2^k\x9br3m\xe2yOS\xd8 \xb8\xd9\x1bӋ\x1e\xa1A\xaf\r\xb0\x17S\x9dJ\xbdG7y>6\xab\xa5\xd0*\xbc`V%Z^t\xb7\x9aU\xb1\xc0\xf9쨏vW~\xaf[l\xa1\a\x0e\x83\xce\"V\x18~Ž\xb9\x87\xb2[\xb0v\xa0\xbf\xd9\xd3sX\xf8\x9d\xa6\xf0N\xa5\xa7\x94\xfeWꩼ\xa3\xd7\x06؋\x99Nw\x84V\xbf\xef\xaeI\xa5\x00\xef\xbbw\x9bU\x89\x9e\xbdY7ͪX \xfa7\xfa\x95\xeb\xf5ˣ\xef\x81è\xb3\xc8\x15\xb2\xa4#\xc9\v\x82e\x03\xae\x86\xe9\xe4\xdf]N\xdf\f\xefx\xcam|e\x80!f:\xbd'X8\xc7\xd9\xec\x1d6\xab\x12=\xc3\xde\xcdfUF\x85\xc7\xcc\f\xb0\x82ig\xba\x15d\x9d\xde\xdba\xd9`=\x9d*KO\xfb_X]\t\x9d\x9c \xa2N\xbe\xc5\xf2I\xfc\x0e\xbf\u007f\xab@\xcf\xe3\xdew\vKؤ\xfb؎%\x9e\xd5\xf2\xc1\xe3\xbdo繽\xe5Ҵ/[~\xcd\xder\v\xc2\xde\xf7*\v=\xab?\xe5:\xe3J\x8d:\xf3\xbdP\x92\xbddG@ɽ\x1e\x8d\x9c\x96{P\xf8\xd8C\xd7\xe1$\x9bR/z\x88\x9eՅ\xee\xbc\xf2B\x9f\xff\xbcrٲ\\\xbd\x16\x06=ܩ\\\\\xb8c\xc7\xe2\xec\xd3\\\x0f\x1c\\g\xaa%ӛ\x9b\x8a\xac\xc0u\xce\x1f\xe92\x94\xfb\n\x05!\xc7翻>\xdf]X\xfe\x96\xdf\xffi\x9e\xfbDž\xf9W\xb6\xe5\x94\xdee\x8bӺ%?\xa7\\\xb9d\n\xea\x14\x9a\xdb\xee\xca\xc3O\xfbˏ2\x9d\x82=h\x9b\x01\xbb\x88|tz\xb3\xe7\xa4\xd0\xd0\xd3s\x8b\x9d\x98\xbb\x1b\xfc\xbe\xab\x9b\xb3\xe8k|\xd2-x\x1b\x0e\xe6<\xcdj\\\xc9^~\xf0r\x83 ]\xe7\xbc)\xf4H\xad\x86O\x9f,,\xca.\xdcQ9\xf7\xcf\\_\\\xa9Qg\x9b\x85m/\xb6z\x1fS\xf6\xc9W\x84\xdf\xfaUX\xee!\xc0՞\x9e\xf9\xd2\x1e\xaa\xaa\x1b⍹\x9b\xce^>\x96'|J\xaf[z\x8a\x9e\xa4\xd7-\xff\xaeY\v\xdd\x1e|\x8fz\x0f7\xcc\xf7\x1c[\xdd\xca\xf5\xc0\xc1u\xc6/\x99\xee\xdcTd\xed\x1d\x1e^\xbf\x83\xcd\xe1\xb7\rt#\xbc0\xf7\x857\x99\x9c[\xae\x9c.\x17\xae\xd2m\x9e#\xec(\x15\x16\x1f\xcck\x95\x16\xa7\xb0\xa1\xa1\xd0\xf3\x8e\xd40\xa8Shn\xbb+of\u007f4\xff\x16\xd3)ԃ\xa6\x19\xb0\x8b\xe8O\xf6\xa4\xb7̆,i2\x87\xbe9Wz\xe9\xd4p\xe1j\xfa\x92\xf9NKg\xf9/\n\u007f\n4{L\xa0o\x9da\xd7\\\xa1R\xdd\xce\xceK\x03\x19W\xe5\xc3\x005X\b\xbf\xf8\xb7\xd6\x03\x87Gy\xc3\x0f\xd5\xe58\xece\x1a\x1cΑ,\xe4N\xbfTk\x11\xde\xc3i\x81\xbe\xd3\x1f\x16\xde\xd1\xf6\xc0\x11\xec\x8c[2\xa3\xb9\x85\xc8b\x87\xacriҷ\xa9\xe4N\xa14\xc89|\x92.\x88o\x19\xf3\xd8[I\xb7\xf5y\xff\xa6-\xacn!-\xfe\xb8\xb0D\xaa\x1dЉ\x9b\xdb\xeeJ\xff\xb2-+\xfdL'\xae\au3`\x17\xb1\xe9\xb4)0yIx3T\xf7\xac\xf0~`\xf2\xb1,\xfe\xc0\x14^\xaa\xdb\xd9\xfaG|\x9fR\n7\xcbun\n\xa7G\xd8\x03GP\x86`]\x8e?\xe7\x17n;\xf6\xa6Ov\x81\u05c9_\x8b\xf0\x1ev\xe7Ї?Iҫz\xe0\bv\xc6-\x99\xd1\xdcBdm\xb9zu\x99\xac\x93\u007f\xf8\x1by\xca\xe7\x14w\x0e\xaf~$GXF\xa7\xbc'\xa9*\xc3\xcc\x14ZW:\xc1>,\x0f[\x04t\xe2\xe6F+\xb1\x0f\x1d\xa4k\xa7P\x0f\xeaf\xc0.b\xd3)8\xd9*p\xd7)܅\xf0c\xda\xcb\x01M\xa9ng˔K\t\xe5T\xec\xaa\xf0\xca\b{\xe0\b\xca\x10j\xc6\xf1\xf1\xd1\xf5K\x84\xbc\x83aG'~-\xc2{h\x9d{\x87\xbd\xa1\xbc\xa3\xed\x81#\xd8\x19\xbfd\x06s\v\xc1fq\xe9\xb2\xf2䬲\x19\xaez\vw\x9f\xed)\x95t\xba\xe4\xbf\xea\xf6+:I\x8b\xd5#H\x03\xee\x81W\x80\x9b\x1b\xadtg\xc7mI'\xae\au3`\x17\x16uګ\xd9\u007f/\xf3\xaf\xc7p\xf0\x12\xda\xffط\xfd:\x84Ju;\xab|\xe4\xf7\x12\xca;f\x83;|\x80\xdeZ\x0f\x1c\x11u\xba\xba\x9b\xee\xda\x1f\x9f\xf4\x1cfO\xa4\x1d\xfc\x98tXR\xadEx\x0f\u007f\x16\xca\xff\xfcVQ\x89O\xdb\x03G\xb03nɌ\xe6\x16Bَo\xb1ո\xe9\xdd[\xf8\x11{\xb6\xa4\x84\xbds};\xa0SV@\xa7m\xec\x8f\xc7\x04i[\x05t\xe2\xe6&U\xf2K:q=\xa8\x9b\x01\xbb\x88^'\x0f}A|+5\xfb\xef]o)ۛ\xb6I/\x8e\xff\xdbE\x81wg\xfd\x01\xe2P\xa9ng\x97\xe4k\x9e\xbd\xf2\xfd\x10\xbe%\xe5#\xec\x81'\xa2N\r\xc2%\xf6_\xe9\x16\xe9\xb1\xd4\xef\xbf-\xf7\xa3Z\x8b\xf0\x1e~/\xe4\tB\xe9Ͱ\x1e8\x82\x9dqKf47\xff\xfb\a\xdf\xe7fA\xada\xabX\xb2\u05ffE\xdaƅ\xccm\xdf7\xc2tʣF\f?R*\xb5\b\xe8\xc4͍Ӊ\xebA\xdd\f\xd8E4#{W%IJ\xbc\a\x1bJ\x04\xf7\v\u007f\xbc\xd5\xe3\xde|\xd5\xf7\xe6f7\x1b\xf1\xbb2\xffѣ\x97\xb6\tǤ\xea\xef\xc9w\x06}\xfa[i\xc0*x!%\xa3*\xd5\xefl\xf7\xdcʳg7+wV\xb4\x86\x9d\x88X\xed!\x80\xefw==\xf37\xf7\xf4\xdc\xf5\xab\xea\x86h\x10\xb2\u007fr\x9e6\xbb\"=\xc9j=[\x9a\xfdg\xd5\xdc\xf4{\xf8\xfd\xfc\xcb/\xf6\xdc\xf4\x85\xf5\xc0\xf7\xact\xc6/\x99\xee\xdc\x18O\xcb\xc3\x0f\x81\xbb\"zrv\f\xbf\xb2\xd5{\xd3\xff~ζW|\xb4\xd9\xfa\xc3\r\x8fѓī\u007f\xcci\x1d>\xe9~k\xb8\x92\xa9\x9c%,?y\xac(\xe7O\xf4`\xc9\xee\x8ah\xed\xe9Q\xcd\xed\xa3\xcaR\xb6\xaa\xb7J+?\xe2z\xe0\x9b\x01\x1b\x89\xfc\xb9S\x8et\x06\xee\x96\x06r\xdf+\xf5d\xaf\xfe\xb1 l\xddʊ\xfe-\x9b>n\xa5\xc5\u007fZ_\x98\x1d\xbc_u\xef|v\x9e\xff\x96|\xe2\xae9\xb8\xa8J\r:\xbbT\xba8\xe7I\xe9\xbd\xdb\xdf\xe3\xd9\xe1\xd7`\xb1\x87 o(W\x12G\xfd\xea\xbaA^x\xb2\xa1\xd0\xed-\x95]\xf0m\xcb\xf1<yU=7\xfd\x1e^q\xb32\xf7\x93\xefhz\xe0\bt\xe6\xe7\x96Lwn\x8ccޣRE!@+\x9b\xdc\xe6\xdf&\bs\xaf\xf8}\xadEY\xde\xf5NJ\xdcO\xd2c\xe2\xc9l!\xfb\xa4tm\x94\xb5csN~%Sf\x93\xd2j=?\xb7\x06A\xd8D\x9fn\x11\x84\x86P\x0f\xa5|3`#f'{\xd6\xf0ms\x9f4\xab\x13\x1d\xa7ݛU\x9f\xe1\xc4!\xb7\xb3\xb7\xdc\xfe\xf4ӏ\xdfx:'\xda[\x1aG\x83\xd0\xf5\xaa%bl\x06\"c\xafN\xf4\r\xb0Ж\xa1\xd7;ްA\xb2\xb8\xe3\xac\xf2)\x93/Ou4\x1c~_\xc6\xc6\xfb\xad\"\x11\xa3\x1716\x03\x91\xb1Y\xa7\x89\xc4\xef\xe5!r\xff;\xfcgo~\xff\x93\xca9ד\xba\x8dl'F/bl\x06\"\x03\x9dbƷٳ\xe5\xf4\x95\xd3[<[T\a\xd2?\x9d\x97q\xe4*\xff\xa642bV+\x8c\x18\x9b\x013\xa0S\xec\xf8ί\xcew\xe7\xaf>?\x86\xfb\xa542\xa2\x19B\x8d\x82\x18\x9b\x013\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6a\xb7N\xc8(\a\x13\x18S\x9d\x90Q.3\xf2\x1e\xa2\xe5\xa4t\a\xed⧣\xb9\th\xab\xa0\x93\xdad\xc0\xd1P]+\xb3\xb0Rw\xc2'\xa2\x9bꄌr\x19\v=pĒQ~\xf7\xbc\xf0㞞\x17\x96\xe5}\xa4S_\x83\x947\x18%\x1f\xf7\x94\x04\xea\x1a\xce\xc2\xca\xe2\xe8ԝ\xf0\x89\xe8f:!\xa3<@\xf4=pĔQ~K:\x8a\xdc\xf1D%\x8a\x95oZ\x94\a\xeb\x1a\xcd\xc2\xca\xe2\xe8՝\xe8\x89\xe8f:!\xa3|D\x98v\xa6WA\xde\u007f\xfd\xcb\xcc\xdaJ\x8cD\xa7\xf0YXY\x1c\xbd\xba\x13=\x11=rV\x042\xca\xc7\"\xa3\\\xde\u007foK)\xce\xc1fF[=k\x87\\\xca'\x97si\xe4\xaaׂ괍\xcen\xfe\x1dn\x16l\x19~\xcc\"%\x84\xd3\x06\xcbk\xa5\xeeDOD\x8f&\xc9\b\x19\xe5\xcef\x94\xdf\x12\x8e\r\xdf\xfdݲ%w\xf9fF[=KXr\xf2l\xdeӪ\xe4r.\x8d\\\xb5\x16T\xa7\x9b\x95B\xebU~\x16ï\x14n\xb9\xed\xbf\xfd\x93\x9c\x9e\xbb\x06\xcbk\xa5\xeeDOD\x8f\xfed\x8f\x8f]EF\xf9hf\x94ߒ\xde\xf7\x8bn\xaa\x9b\x19l\xf5,\xefG\xec,ۯJ.\xe7\xd3ȹ\xb5\xa0:\xb5f\x9d\xd7\xcc\xc2\xdf\xc0\x8e0\x9b6\xcbuu\x96\xd7J݉\x9e\x88\x1e\x9bN\x9b\x02\x93\xc8(\x1f\x85\x8c\xf2[\xc2O\xae^\xbd\xb4i\xf1\x1b\xea\x15\xd2\xdf\xeaY[\x02\xa5|r9\x97FέEy\xc3^\xe5\xe5\xe4f\xe1\xbf9\xf7\xdf\xfc\xbe\x1c9\xc3Yoy\xadԝ\xe8\x89\xe8\xb1\xe9\x14\x9cDF\xf9(d\x94+\xd7\xfe\xeb\x8b|\xaaf\xfa[=T\xca%\x97\xf3i\xe4\xdcZ\x94{s\x96<\xed\xd3̂\x16\xef\xf0_\xca\xd1\xd8\xcd\xcd\xd8J݉\x9e\x88nQ'd\x94s=\x8cVF\xb9\xb2\xff\x1e\xa3o\xe6\xfc\n\xe9ou\xb5NY\xb2N|\x1a9\xb7\x16\xe5\xdew\xde\xcfi\xd5̂\x9e\xac\xe5\xf9\x94\xf37\xdd\xe5\xb5Rw\xa2'\xa2G\xaf\x132ʵ=\x8cVF\xb9\xb2\xffn\xca\xf6\xa9VH\u007f\xab\xeb\xeaħ\x91sk\xc1\x06\xca/\xb9\xaf\xaag\xc1\x82\x02\xcf+\xe7o\xba\xcbk\xa5\xeeDOD\x8ffd\x0f\x19\xe5\x8ef\x94˷!\x9c\xad\x946f\xb0\x99\xfeV\xe7J\xf9\xe4\xf2P\x1a9\xb7\x16\x1f\xf7\x94l\xfe\x9d\xefn\xb9\xf7\xcam\xd5,\xe8L\x1e\xc9\xf9\xd4py\xadԝ\xf0\x89\xe8\x91?wBF\xf9\x18d\x94\xcb7ɹ\x97\x1d\xf3\xf1\xcd\xf4\xb7z\xa8t\v\x9f\\\x1eJ#\xe7\xd6\xe2(\x9bx\x83\xf5\xbeW=\v\xff\x9f\x84\xc0QUgy\xadԝ\xf0\x89\xe8f'{\xd6@F\xf9\xb8\xe4nV\xd8\xfb\x80!V\xea\x06\t]T'8\xf6ꄌr\xc73\xca\xed\xe0\xf4\xe2\xe8ߺ\xac\xd4\r\x02\x9d\x80\x19\xf1\x91Q>b\x1a\xae\xf8J\u007fbVI\xc1J]\x1e\xe8\x04̈\x87\x8c\xf2\x913,,\xdf\xea\x8d\xf2l\xd5J]\x8e\t\x94\x88\x0e\x9db'\x0e2\xcam\xa0!\xbbTsϠ1Vꆘ@\x89\xe8\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\xc6\xc8ur.\xbc;:\xd6\x1f\x95\xff\xbf\xb2:\xcf]\xb8yb\xdc\xdb\x02\xe2\x04\v:\x8dyx\xb7!|\xdd7\x84\xdd\xd2\xffW\xe7\x96\x1c\xbb|\xb4(o\x02|g\r\xc4\r\x16t\x1a\xfb\xf0n#Bu}=\xf9\x8aNg\x05\x16ipS\xf9\xda=\x00N`A'Ӽm+\x98vfZ\x81#Tw\xbd\xb0\xde#\xeb\xe4\x93\x0eKz\xe1b\x00\x8c\x16&:\xc5Ux\xb7*o\xdbwt\xb9\xe7\x1b\x87}\x9a\xcen\xdf\xf2\xe7\xec\x0e\xd4\xf7ݹT\xf8\x8d\x98\x8e\x9d\x00\xc4Dd\x9d\xe2+\xbc[5\xe3MY{_ܛ\xb5\xd9\x1fV7\xa8ӛԱl\fE\x00\a\x89\xacS\x9c\x85ws3\xbe$\x85\xd5ɏ\xea\xbaA\x9d|W\xaf\xb4\x16z\xe1\x13p\x8e\xc8:\xc5Yx77\xe3\xcdr$㣛\xc3\xea\x86N\xf6(\x1f\xe7\xebd_\x020J\x98\\;\xc5Wx77\xe3\x12Y\x93\U00092c3a\x8aNw\xe496\xb8q\xf1\x04\x1c#\xb2Nq\x16\xde\xcd\xcdx\xf3#\xacw_ᦰ\xba\xb2N\xbe\x1c\xb9f\x83'\x86\x1c+\x00b#\xb2Nq\x16\xde\xcd\xcd\xf8E\xe9O'\x85\x17\xb5u\x03:屟@\xf2\u007f\\\x18\xfec\x1a\x00\x8c\x16f:\xc5Sx\xb7*\xa3\xbcR\xd8}~\xb7P\xa9\xe9\xecNOO\xf6z)T\xfd\x05\xa1\xfc\xe8\xe5\xd6\xc2<;\u007f\xaf\x1a\x80\xc8D\xd6)\xbe»U\x19\xe5\xbe\xd6e\x9ee\x87}\x9a\xba{\xa5\x1an\xf6+\xac\xbf}\xbap\xfe\x92m\xb6d\xd2\x02\x10\x1d\x16\ue288\x9a\xc4\t\xef\x06\xc0\x12\xa3\xa1S\xe2\x84w\x03`\x89\xd1\xd0)A»\x01\xb0\xcah\xe8\x94\x18\xe1\xdd\x00Xf4tJ\x90\xf0n\x00\xac2*:\x0101\x81N\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00۰[\xa7\xb3%\xb7ͪ\xa8\xb9S\x12K\x88,\x00\xf1\x88\xa9N\x1fm\xc9\xf3\x94G}\xb7\xd0A\xa1!\xea\xba2\xbe\x83\xc2A\xb3:V\x18yd\xfa\xc8{\x88\x96\xb3n\xe5\xae`\xb7\xf9[J\x83\\\xe9E\x8f\xd0`V\x15\x8c\x19\xa6:\x95z\x8fn\xf2D\xfb\xbd\xa5V)\xe5\xcb\"/\xba[ͪX\xc0Bd\xfa\x98\x87\xae\x1f\x14zz\x0e\v\xad==s\x8d\xdfQ\x02\xcd\xeeTzJ\xe9\u007f\xa5\x9eJ|#2~1\xd3\xe9\x8e\xd0\x1a\f\xd43\xe5}7\x1f\xca\x155{\xb3\xec\xfc\x06z\xf4G\xc71\x0f]ou\xb3\x84\xc1\xdf\xf9\xfd\x1e\xe37\x94`\xb3\xdd\xe5\xf4]펧<\xa6M\f\x9c\xc1L\xa7\xf7\x04\vg>\x9b\xbd1}5pػ٬ʨ`%\x06\xdd\x14\xd3\xcet*\xf8\xdeStz\xcf\xd8\xe0`\xb3ݕ\xa5\xa7\xfd/\xac\xae\x84NqLD\x9d|\x8b\xe5S\xfb\x1d,\x82\x9c\x9eǽ\xef\x16\x96h\xd2\xc8\xfd\xef};\xcf\xed-\x97\xa6}\xd9\xf2K\xcde\x89\x1b5\xe3\x82\xc9){=\x1a\r-\xf7\xa0`\x10\x99\xce\x11W\xa1\xeb\fI\xa7h\x9a\xed\xae<\xfc\xb4\xbf\xfc(\xd3\xe9\xee\xfa|wa\xf9[~i![\xb7\xe4甿\x17\xd6/\x18\v\"\x1f\x9d\xde\xec9)4\xf4\xf4\xdc\xf2\xfbo\xf6\xb8\x1b\xfc\xbe\xab\x9b\xb3\xd4i\xe4\xfe+\xd9\xcb\x0f^n\x10\xa4\x93\x957\x85\x1e\xa9\x15\x97%n\xd4,\x14L\xcexE\xf8\xadz\xbe\x96{\b\xa0\x1b\x99\xce\x11_\xa1댠Nf\xcdvW\xde\xcc\xfeh\xfe-\xa6\xd3ya˕\xd3\xe5\xc2Uy!\v\x1b\x1a\n=\xef\x84u\fƀ\xe8O\xf6B1z\\\x1a\xf9p!\x8b\xb3\xf3\x9d\x96.\x8f_\x14\x82_\xb4\r\x85\x98\xeb6\xe3\x82\xc9\x197\x85\xf0\x8b\u007fk=p\x84G\xa6s\xc4]\xe8zP'\xd3f\xbb+\xfd˶\xac\xf43\x9d\x86O\xd2%\xf5-\x93\xde*\xb2\n\xef\xb28\xc1\x12\xbd\xbe\x81\xd3ĦӦ\xc0\xe4%>\x0e\xe2\xac\x10\xcc\xd7\x0f\x85\x98\xeb6\xe3\x82\xc9\x197\x85\xd3~-\xd6z\xe0\b\x8fL爻\xd0\xf5\xa0N\xa6ͨN\xec3\x05\xe9\xda\xe9\xce\xe1Տ\xe4\bRL{\x96t\x82}X\xc0x_<\x10\x9bN\xc1\xc9V\x81\xbbz\t\x9e\xb7\xf0!\xe6\xba\xcd\xf8`r\xbf\xfe\x8f\x9aY\xeb\x81#<\x94\x96'\xdeB׃\x1bʹ\x19\xd5\xe9ΎےNW\xbd\x85\xbb\xcf\xf6\x94\xca:I\v\xdb#\x98\x8d\xd3\x03'\xb0\xa8\xd3^\xcd^}\x99\u007f\x19\x87\xb3\x1a\x02\x93\xa1\x10s\xddf\\09\xa3\xc1\x1d>\x14o\xad\a\x8e\x88:\xc5]\xe8zP'\xd3f\xbb\xe5\xc4[\xa6Ӓ\x12\xf6&\xf6mY\xa7m\xec\xf1\x98\x10\xed\x87\x19`4\x89^'\xf6#\x99\xbe\x95\x9a\xbd\xfa\xae\xb7\x94\xedcۤ\xd7\xd4\xff\xed\xa2\xc0{v\xe8\xadX\xb7\x19\x17LN\xf1-\xd1\xf9\xd5\x18K=\xf0D\xd4)\xeeB׃:\x996\xe3t*d\xf2\xfb\xbe!\xeb\x94GE\x1a~\xa4\xd4\x0f\xe2\x80hF\xf6\xaeJ\x92\x94x\x0f6\x94\b\xee\x17\xfeȧ\x91\xfb\xaf\xcc\u007f\xf4\xe8\xa5m\xca\x0f:\xbf'\xdf/\xa4\xca\x12\xd7o\x16\n&\xf7\xb33F홊\xd5\x1e\x02\xe8G\xa6s\xc4W\xe8:\xe5\xcd\xc3B\xab\x1c\x1dm\xd2\xec\xa3\xcaR\xb6&\xb7J+?\xa2\x15\xd6\x1fnx\x8c\x9e\x0eҖY\xc2\xf2\x93NJr\x90\xb6\x16\x17D\xfe\xdc)G:\x9dwKû\xef\x95z\xb2W\xffX\x10\xb6\xf2i\xe4\xf4\x02}}av\xf0.ֽ\xf3\xd9E\x90*KܠY0\x98\x9c\x9e\xf7{vhgl\xb1\x87 \xfa\x91\xe9\x1c\xf1\x15\xbaN\x0f+\xac\u007f\xcf\xdd(\x9a5\b\xc2&\xfat\x8b 4\xf8}\xadEY\xde\xf5NJ\xdc\xf4\x98\x94\xb5csN~\xa5\xea=\x03\x8c\x19f'{\xd6\xf0ms\x87\x8f\\\x9bpڽ9\xde\u007f\x82)\x9eC\xd7C\u05eb`\xec\xb1W'\xfa\xbeYhq\xc4\xf6\x8e7l\x90,\xee\x88\xe7\xd0u\xe8\x14OجSb\x12ϡ\xeb\xd0)\x9e\x80NQ\x10\xbf\xa1\xeb7\xa5\xf1\x12\xb3Z\xc0)\xa0S4\xc4m\xe8\xba4^\xf2\xbe\x1f\xc4\t\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00۰['d\x94\x83\t\x8c\xa9N\xc8(\x1f=\x90Q\x9eh\x98ꄌ\xf2\xe8@F90\xd7\t\x19\xe5Q\x82\x8cr`\xae\x132ʣĴ3d\x94O\x00\"gE \xa3\x1c\x19\xe5\xc0\x02\xd1$\x19!\xa3\x1c\x19\xe5 *\xa2?\xd9CF92ʁ\t\xb1\xe9\xb4)0\x89\x8c\xf2`\x0f\x81\xceL\xc3\xc6\xd5 \xa3<\x91\x88M\xa7\xe0$2ʃ=\x04:3\r\x1bW\x83\x8c\xf2D¢N\xc8(GF90&z\x9d\x90Q\x8e\x8cr`B4#{\xc8(GF9\x88\x8aȟ;!\xa3\x1c\x19\xe5\xc0\x02f'{\xd6@F\xb9\xe3 \x056\x9e\xb0W'd\x94;\x0et\x8a'l\xd6)1AF9\x88\x0e\xe8\x14\x05\xc8(\a\xd1\x01\x9d\xa2\x01\x19\xe5 *\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6a\xb7N\x963\xca\xf5Ar9\x18\x8f\x98\xea4\xda\x19\xe5\xfa \xb9\\@r\xf98\xc4T\xa7\xd1\xcf(\xd7\a\xc9\xe5H.\x1f\u007f\x98\xe9\xe4DF\xb9>H.Gr\xf9\xb8\xc3L''2\xca\xf5Ar9\x92\xcb\xc7\x1d\x91\xb3\"F\x9cQ\xceuf9w\x1c\xc9\xe5Q4Cry\\\x11M\x92\xd1\b2ʹ\xbe,\xe7\x8e#\xb9<\x8afH.\x8f+\xa2?ً1\xa3\x9c\xc7Z\xee8\x92ˣh\x86\xe4\xf2\xb8\"6\x9d6\x05&\xcd3\xcay\xac\xe5\x8e#\xb9<\x8afH.\x8f+b\xd3)8i\x9eQ\xcec-w\x1c\xc9\xe5Q4Cry\\aQ'\xeb\x19\xe5<\xd6rǑ\\\x1eE3$\x97\xc7\x15\xd1\xeb\x14cF9\x8f\xa5\xdcq$\x97\xfb\xa3h\x86\xe4\xf2\xb8\"\x9a\x91\xbd\x11e\x94\a\xb1\x9a;\x8e\xe4r\xbfy3$\x97\xc7\x17\x91?w\xb2!\xa3<\x88\xc5\xdcq$\x97#\xb9|\xfcav\xb2g\x8dX2\xca\xf5Ar\xf9\x88@6\xec\xd8`\xafN1d\x94\xeb\x83\xe4\xf2\x91\x01\x9d\xc6\x06\x9bu\x9aH \xb9\x1ch\x81N1\x83\xe4r\xa0\x05:\xc5\x0e\x92ˁ\x06\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80mح\x132\xca\xc1\x04\xc6T'd\x94ˌ\xbc\x87hAF\xf9\xf8\xc5T'd\x94\xcbX\xe8\x81\x03\x19\xe5\x13\v3\x9d\x90Q\x1e \xfa\x1e8\x90Q>\xb10\xd3\t\x19\xe5#´3d\x94'\x14\x91\xb3\"\x90Q\x8e\x8cr`\x81h\x92\x8c\x90Q\x8e\x8cr\x10\x15џ\xec!\xa3\\\xdb\x032ʁ\x86\xd8t\xda\x14\x98DF92\xcaA\x88\xd8t\nN\"\xa3\x1c\x19\xe5 \x84E\x9d\x90Q\x8e\x8cr`L\xf4:!\xa3\\\xdb\x032ʁ\x86hF\xf6\x90Q\x8e\x8cr\x10\x15\x91?wBF92ʁ\x05\xccN\xf6\xac\x81\x8c\xf28\x01)\xb0c\x83\xbd:!\xa3\x1c\x19\xe5\x13\x1a\x9bu\x9aH \xa3\x1ch\x81N1\x83\x8cr\xa0\x05:\xc5\x0e2ʁ\x06\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80mح\x132\xca\xc1\x04\xc6T'd\x94ˌ\xbc\x87h9)\xddA\xbb\xf8\xe9h\xee\x12\xda*\xe8\xa46\x19p4T\xd74ڼg\xaeP\xe2\xf3\x9f\x15\x84\xb9\x97\xd5\u007fxgu\xb6\xb7\xf2\x8a\xf7\xb6\x95\x19O LuBF\xb9\x8c\x85\x1e8b\xc9(\xbf{^\xf8qO\xcf\v\xcb\xf2>ҩ\xafA\xca\x1b\x8c\x92\x8f{J\x02uM\xa3͇/\v\x9e\x1e\xffݳ\xc2e\xf5\xf7L.e\xaf<vr\x99 \xfc\xbb\x95\x19O \xcctBFy\x80\xe8{\xe0\x88%\xa3\xdc\u007fKz\xe3\xbf\xe3\x89j\u007f\xb5\xf2U\x8c\xf2`]\xd3h\xf3\xbbB\xe5f\xfa\x82j\xb2[\xee\xe4<M7\xc3p\x91\xf0\xef\xd6f<a0\xd3\t\x19\xe5#´3\xbd\n\xb2N\xfeefm%\xac\xec՜Nf\xd1\xe6w\x85\xcb\xd9\xc3a:\xed\xf6Hߗo\x15\u07b36\xe3\tC\xe4\xac\bd\x94\x8fEF\xb9\xac\xd3m)\xc59\xd8\xcch\xabg\xed\x90K?\xcds\xff\xb80\xffʶ\x9cһ|\\\xb9굠:m\xa3\xb3\x9b\u007f\xc7<\xda\xfc\xae\xf0\xfecg\x15\x9d|G\x97{\xbeq\x98\xadZ\xd1&i\xeewZ}\xa1\x19kz\xd0\xdd:z+\x9f\x90D\x93d\x84\x8crg3\xcao\tdž\xef\xfenْ\xbb|3\xa3\xad\x9e%,9y6\x8f\x96^\xc9\x11v\x94\n\x8b\x0f\xe6\xb5\xf2q媵\xa0:ݬ\x942\x92L\xa3ͩN\xad\xe5\x8aN\x9b\xb2\xf6\xbe\xb87k3]a\x81\xbb\x9e\r\xceXӃ\xce\xd6\xd1]\xf9\x84$\xfa\x93=>v\x15\x19壙Q~K:d\x15\xddT73\xd8\xeaYޏ\xd8Y6\x9d\xf2V\xd2W\xe0\xbc\u007f\xd3\x16u\\9\xb7\x16T\xa7\xd6,\xe9\xf54\x8d6\xa7:ݙ\u007fG\xd2\xe9\x92\x14\xf0\xc7\x1e\xdf\xe7_\x91ЌU=\xe8m\x1d\xa3\x95O<b\xd3iS`\x12\x19壐Q~K\xf8\xc9ի\x976-~C\xbdB\xfa[=kK\xa0\xd4{\x92\xee\xb1\xc3r\x90%\x17WέEy\xc3^\xe5\xe54\x8d6\xa7:\xf9\xcb[%\x9d6\xcb\xdd<\xba\xd9\xef\xe3G[C3V\xf5\xa0\xb7u\x8cV>\xf1\x88M\xa7\xe0$2\xcaG!\xa3\\\x19\x8aX_\xe4S5\xd3\xdf\xea\xa1R\xef%\xffU\xb7\x9c\v\xcbǕskQ\xee\xcdY\xf2\xb44[\xd3hs\xa6\xd3\xd9oH:\x95\xc8\xc1\x86\xe5%\xc1k'\xdf%Ռ\xc3z\xd0n\x1d\xa3\x95O<,ꄌr\xae\x87\xd1\xca(Wt:F\x0f\x12\xfc\n\xe9ou\xb5NY\xb2N|\\9\xb7\x16\xe5\xdew\xdeϑ\x0e0\xa6\xd1\xe6L\xa7\xe1\xec\xcb\xd2\xd1\xe9\x11\xb6\x86\xbe\xc2MldOڲ'\x85\xdb\xfc\x8cU=\xe8m\x1d\xa3\x95O<\xa2\xd7\t\x19\xe5\xda\x1eF+\xa3\\\xd1iS\xb6O\xb5B\xfa[]W'>\xae\x9c[\v6P~\xc9\xcd2gM\xa3͙N\xfeM\x95L\xa7\x17\xa5e8)\xbc\x18\xf8\xdc\xc9WZ\xa8\x9a\xb1\xaa\a\xbd\xadc\xb4\xf2\x89G4#{\xc8(w4\xa3\\\xbe+\xe2l\xa5\xb41\x83\xcd\xf4\xb7:W\xfaǜ\xd6\xe1\x93\uedc6+\xe9.\x1c\x8a+\xe7\xd6\xe2㞒Ϳ\xf3\xdd-\xf7^\xb9m\x1am>|Y8{\xd7\xdf\xe3\x91F\xf6*\x85\xdd\xe7w\v\x92\x80\x97<%/\x9c]\xed~E\xb58\xa1\x1e\f\xb6\x8e\xd1\xca'\x1e\x91?wBF\xf9\x18d\x94\xcb\xf7칗\x1d\xf3\xf1\xcd\xf4\xb7z\xa8t\v=\x16\x9c\xcc\x16\xb2O\xb2K\x94P\\9\xb7\x16G\xd9\xc4\x1b\xac\xf7\xbd\xa6\xd1\xe6W\xe6\n\xc2i\xbf\xaf\xc4+\x9d\xe7\xb5.\xf3,;,\x8b\xf1\xcejO\xde\xd3\xff\xa6^\x9cP\x0f\x06[\xc7h\xe5\x13\x0f\xb3\x93=k \xa3||\x13\xba\xf8\x1d1\t\xb8u\xa2\xc0^\x9d\x90Q\x1e'\x19\xe51b\xa3N\x06['\xc1\xb1Y\xa7\x89D<g\x94Lj\x8d:\x19l\x9d\x04\a:\xc5L\xfcf\x94Lj\xad\xd1\xe6\x06['\xc1\x81N\xb1\x13\xb7\x19\xe51bo\xb4y\xa2m\x9d\xa8\x80N\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m\xfc\u007f\xe7\xbd\xe7\x84\xdaB\xea\xf4\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/call-eg.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\x1e\x00\x00\x01\xc8\b\x03\x00\x00\x006\x92\x13\xd7\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x05\a\x03\n\r\t\r\x12\x14\x0e\x12\x1d\x11\x13\x10\x1b\x1a\x14  \x19\x15\"6\x1f#%!# $%#&(&+)\x1e++$*,*0.\"-/,\x1c0Z120463/6B;8-8:7<>;C@4#Cx@B?AFHDFDKH<MH7\x00f\x00IJH\x00i\x01\x00j\x02LNK8P|0R\x95\am\x06PROYTC\x0fp\vTVS/Z\xa3\x0es\x18,`\xae7]\xad\x15v\x1c[]Zb]K9a\xab\x19y\x1e;b\xac_a^=d\xae@f\xb0*{!bdaBh\xb3efdDi\xb4fheMj\xaf.\x81.Fm\xb1qjROl\xb2Ho\xb3kmj0\x859Jq\xb5Kr\xb7npmMs\xb8;\x86:cr\x8fNu\xba|t]Xv\xb6sur?\x8a>Zx\xb8vxu]{\xbb_}\xbez|y\x84|dX\x80\xbfL\x91K`\x81\xbbb\x80\xc0}\u007f|\u007f\x81~c\x83\xbdN\x95Ue\x85\xbf\u007f\x83\x92W\x95V\x82\x84\x81\x8d\x84fg\x88\xc2m\x87\xbci\x89\xc3j\x8a\xc4[\x9aZ\x87\x89\x86q\x8c\xc1\x8a\x8b\x88\\\x9dc\x96\x8cnt\x8e\xc4v\x90\xc6g\xa0g}\x91\u008f\x91\x8ey\x93ɒ\x94\x91\x80\x95\xc6z\x97Ƃ\x96\xc7s\xa4l\xa1\x96x\x95\x97\x94\x83\x98ɂ\x9aė\x99\x96\u007f\x9d\xcct\xa9v\x86\x9b́\x9eΚ\x9c\x99\x82\xa0Ϩ\x9d\u007f\x9c\x9e\x9b\x88\xa0\xca\u007f\xabz\x8a\xa2̟\xa1\x9e\x9e\xa3\xa5\xa1\xa3\xa0\x8d\xa6Ђ\xb1\x85\xa3\xa5\xa2\xb3\xa7\x83\x91\xa9ԧ\xa9\xa6\x8d\xb5\x8a\x94\xac֙\xacѪ\xac\xa9\xa4\xac\xc0\x9e\xad͍\xb8\x93\x9b\xafԻ\xae\x89\x9d\xb1֯\xb1\xae\x97\xbb\x97\x9f\xb3ء\xb5\xdaµ\x90\xb4\xb6\xb3\xa3\xbf\x9d\xac\xb7Ң\xc0\xa4\xa9\xb9ٷ\xb9\xb6\xac\xbcܺ\xbc\xb9\xa6Ũ\xb1\xbd\u05ef\xbe\u07fd\xbf\xbc̿\x9a\xb1\xc0\xe1\xb8\xc0ձȭ\xc0¿\xb7\xc2ݹ\xc5\xe0\xbd\xc5ڲͷ\xc2\xc6ֻ\xc7\xe2\xd6ǝ\xc6\xc8ż\xc8\xe3\xbf\xca\xe5\xbdм\xc6\xcb\xdb\xca\xcc\xc8\xc1\xcc\xe7\xc2\xcd\xe9\xbf\xcf\xe2\xc7\xce\xe4\xca\xcf\xdf\xce\xd0\xcd\xc8\xd3\xc1\xc8\xd0\xe6\xdfѥ\xca\xd1\xe7\xcb\xd3\xe9\xca\xd8\xcc\xd3\xd5\xd1\xce\xd6\xeb\xd3\xd7\xe0\xd6\xd8\xd4\xd0\xd8\xed\xe7ج\xd5\xdb\xd0\xcb\xdb\xee\xd5\xd9\xe9\xd9\xdb\xd8\xd7\xdb\xeb\xd8\xdc\xec\xd2\xde\xec\xd5\xdf\xda\xd9\xdd\xed\xdc\xdd\xe7\xdd\xdf\xdc\xd7\xe1\xdb\xdb\xdf\xef\xd5\xe1\xef\xf0\xe0\xb3\xdd\xe1\xf1\xe0\xe2\xdf\xde\xe3\xe6\xd9\xe5\xf4\xe0\xe4\xf4\xe3\xe5\xe2\xde\xe6\xef\xe8\xe5\xea\xe5\xe7\xe4\xe6\xe7\xf1\xe0\xe9\xf1\xe3\xe9\xeb\xe7\xe9\xe6\xe3\xec\xf4\xeb\xed\xea\xe6\xee\xf7\xec\xed\xf7\xe8\xf0\xf9\xef\xf0\xfb\xf0\xf3\xef\xf4\xf2\xf6\xef\xf4\xf7\xf4\xf7\xf3\xf2\xf7\xfa\xf5\xfa\xfd\xf8\xfa\xf7\xfd\xfb\xff\xf7\xfd\xff\xf9\xfe\xff\xfe\xff\xfcA\x10\x8d\xd1\x00\x00 \x00IDATx^\xed\x9d\x0ft\x14U\xbe\xe7\awqv+\xfd^\xcc&O\x98\xe51\xd3@vaȆ\x82\x89M\"\x98`^\xc0\x13a} \b\x0e\x88\x99l\x1c=A\x98\xe1\xafg2\xcf3YI\x8eA\xf2@$\x98\xacsL\x00\xb3J\x88\x12\x91\x80\xae\xe6\x80ᨼ#\x90LD\x87\x93\x991\x83о\xc9L\xc4RQD\x12\xfb\xd4\xd9{oUu\xdd[\xa9\xbe71\xe9\xaa\xea\xee\xdf\xe7p\x92ە[\xb7nU}\xba\xeaVu\u007f\xa9\xef\xa9#@\x01\xe2\x9c\xef\x89\x14\xe0!j\x1c\x88u@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\xb8\xa7G_kMeM\x9b\xfe\xa2\xad\xaejG\v\xaf6\xe0\n\xee\xe9QW\xd5z\xaa\xa5\xb2\x05\x17{\x1bʛO\xb5\x94\xb7\v\xe6\x00\x1c\xc75=Z+\xbb\xd0\xcf\xf6\xca\x1e\xf4\xb3\xa1\xb2CQ\xbaʍC\t\xe0\x19\\ӣ\xae\x81\xfc\xaanQ\x94\x8e\xf2V\\\xec\xe1U\a\\\xc15=j\x1a\xb5_u\x8a\xd2\\\xd9+\xa8\f\xb8\x84kz4Uc'\x82U\xbb\xb0\"m5\xe5\xd5MA\xd1,\x80㸦GOU]W\xb0\xa3\xa6|\x87\xa2\xec(\xafn\xedh\xab\xde\x01\xc7\x10\xcf\xe1\x9a\x1e\xca\xf9\xba\xf2\xf2\xf2\xe6\xba\x1a4\f!\xe3Ӟ\xaaf\xd1,\x80Ӹ\xa7\a:\xb3\x9c\xefS\xaa\x9b\x14\xa5\xb1\x86\xbc\xd4\u007f\x01\x1e\xc2==ȩ\xa4\xbd\x1c]ҶT\xf5\xe1rC\x1d\u007f\x06\xc0y\\ӣ\xad\xbc\v\x9dP\xaa\xf1\xf5\xcbyraۣ\xdd\"\x03\xbc\x84kz\xb4\x97\xb7t\xb4Vב˕\x96\xca\x1644\xad\x81\xa1\xa9\xe7pM\x0f\xa5uWU]\xab^n\xaf\xa9\xda\xd5\x02vx\x0f\xf7\xf4\x00b\x00\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x14e\xcd\x1a\xbb\"\xa0\xb8\xa9G8D\xd9[]\xaeQ-\x9a%:\xfc\x9b\u007f\xa3M\x11\xb3Ǐȼ\xfb\xc4\xe0yF\x8f\x12\xb4\x88\xa9gE\xb5\xdc\xc2==\xc2!\xca`yK\a\xa2\xa5\xbcUq\x85\x92)\xef\xdb\x141=\xbf\xf5?qd\xcf\"\xff\x8b\x83g\x1a5\xce\x1e9\xb2\xc7\u007fDT\xcb-\\Ӄ\nQ\xb6ᯌ\x05\xf1\x97\x92\xdd\xe0\xacy\xc48\xcb\x1e<\x14\xe5\x041cѭJTy\r\xf4\x18\x04\x15\xa2\xd4^\xefr\xe9\xdbb\x91\x0f\x1e\x86\x1eO\xfa\xa3\x9b\xd0\x02=\x06C\x85(1\xe4\x9b\xc9npv\xf2F\x9b\xa2\x8e\xa6G\xc9LE\xf9\x85\u07ff\x17U\xf0ߎ\x8b\x93\xf7l\xbcu\xea݃\x06\f{\x17M\xbdu#2\xe9\xc4d\xbf\u007f\xa52\xd3\xef\x9fޫ\xf4\xac\x9c9y\xe6J4z\xe9˜\xfc\xeb\x993_\xdc8}Q\x10\xb7\xf0䚙\xd3W\xea-\x98z\x18-x\x06\xd7\xf4\xa0B\x94\x98]\r\xdc\xda\xd1c\xcd\xe4\xb36E\x9d\x13\xfe\x17\x82g7\xfa\x9fP\x94\xf7\x8fL~\f\xedȒ)h\xfc\xbaw\xb2?\xf3\xb1'\xa7\xae\xb4T.\xf1o|\xe1\xc9\xcc\xdb\xfb\x94\xbe\xd7\x1e\xf3\xbf\xa6\xfcֿ\x17Y\xf1\x82\u007f͋{W\xa2\x97ʋ\xd3\xfd\x1b\xef\xf6g>\x91\xf9$ia\xe6\x13\x8f͜\xaa\rz\xc3z\x84[\xf0\f\xae\xe9A\x85(\x11\xa7p\xde\xc5\r\xceN^cS48\x81/]\xfc%\xa4<\x05\xe9\xa1<6\x85\x14\xa7#\x8fJ2ٺ/\xf8\u007f\xab\xe0]\xbd\x17\xbf(\xb9\xe3\x8f3\x9f\xc0\x85\xe0^|0\xb8\x1d\xab\x94Y\x82\xea\xfc_\xa5\x04/e\xca-h\xcc\xf5\xe7\x99w\x909\r=\x98\x16\xbc\x81kzP!JD\xc3.A\xedh\xf1\v\xf3\x88\xf1\x8bA\a\x0f\xa4Ǔ\xaf\xbd\xb0h\n\x99N\xebQ\x12.\x9a\xac\xbc\xa5\xb7\x0f1\x93\xc8\x14\xbc=S?\xb8\xfcq\xcfݷL\xc7\xe7$%s/\xda\xf5Ae\xe3\xcfp\v\xe44\xb6\xc7\xffg\xfc\xcbЃi\xc1\x1b\xb8\xa7\x87\x19\xa2DT\xb5\xf0\xabF\x8b\xf7\xa7\xac\xb1)\x86!c\x8f?\xfb\xf7\xe02\xad\x87Y4\xb9ݯ\xa1i\xb1W\xdf\xe5\xafe\xceܸ\xf7\xc8\xddD\x8f\x17\x95\xd7&+\xba\x1e\xb8\x05刟\x9c]\f=\xd8\x16<\x81{z\x98!J\xfc?\x03\x9d\xe2W\x8e\x16\x1b\xfdgm\x8aa\xb4\xa1\xe9t\xb2/Ez\x94\xdcr\x82\xf0G\xfc\xe2\xfd\xcc\xc7f\x92\xc2\xedw\xe0\x93\xcbJC\x8f)\n{\xf4 \xff卡\aӂ7pM\x0f*D\x89\x87\x1e\xe7\x05գ\xc3\xfbSJl\x8a&\x9a\x1e\x99\x1bO\xa0q\xc4T\xb4G\xfb\ue22cNjژ\xe11<\xe4\xe8\xbd\xe31e\xcd\xddx\x889\x13\x1f\n\xfan\x1f\xa4G&\xb2&x\xcb\"2\xa7\xa1\a\xdd\x02\x1a\n=\xe1\x81{\xa9\xae\xe9A\x87(\x91+\xee\\\xcd\t\x0e\x1e\xf8\xca\x05\xfd\xbc{e\tڽ\x8b2\x9fx\xe2\x0e\xff\xe4ߞ@\x171%\xaf)'J&\x1fa\xef\x92l\xf4\xffl\xef\xde\x12\xb4\x8b\x83G\xd6d\x9eU\xceN\xdfx\xa4Wy̿r\xcf\x13\xb7\xa3\v\x96\xd7NL\u007f2\xb8w\xf2\x89\xe0\xcf\xf0\x15\xf1\x14\xff\xed{\xf7܊G\xb8\xe4\xae\xe9\x93G\x8e\x9c\xa5[\xc0\xac\xf4\xc2I\xc65=\x98\x10\xe5)wF\xa6\xefO-\xb1)\x9a\xecE\x03\x01\xf4V>qk&\xb2\xe4\xec\xa2)S\xef\xfe\xb5\u07fff\r\x9a:\xf9\xc4T\xf4\xd32Xy\xf1\xee\xcc\xe9\x8b^\xc0G\x01\xbf\u007f#\xda\xd7~t\xec\xe9{\xf2\xd6)\x99+\xf7\xdc:yQ\xa6\u07ffw\xaa\u007f\xea^2\xb6\x98\xb2\xb1d\xfa\xcc\x12\xacW\t=\xe00Z\xc0\xec\xc9ܣ\xb8\x8e{zx\x80_\xfb\xffͦ\xe8\x04\xda\xd0\xd4\xfb$\xb4\x1e\xee}\x92\x0fz\x00\x1c@\x0f \"\xda\xe06\x16\x00=\\\x80\fn=p\xd9*\x06\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x18\x16/\xad\xfaPQ\xceOK\x98\x87\x03\xb8\xa7\a\xf5$ʞ\xa6]\x95\xbb\x9a\xbc\xf7\xb0\xb0Wg\xc8\x1a\x81w\xb4\t\xb5r\xed\xa7\xe8\xd7\xe6\xa4u\xdc\xf9\xe2\a\xf7\xf40\x9fDy\xbe\xba\xa6\xad\xa3mW\xb5;\xdf\x18\xe3\xf0\xf1\xab\xf9\x0f\xbd\x8a8 \xbfB^?#\x1f\xd0\xfeP\x97\xf4\bg\xb68\xc25=\xa8\x10e#y\x0eT\xef\x0e\x97R\x94<\n\u007f\x85\u007f\xfeN\xd3\xe3wY\xbf\xe9\xeb\xeb\xeb\xc5\xdf\x11|\xc0\xe7R\xf0\xc2a\\Ӄ\nQ6h\xa7\xf2\x1a\xb7\x92P\x1c4=>}\xe6c\xf4\xb3\xfd\x1f\xfe\xd3?Κ4q\xe2\ndtϸ;\x05s\xc6\a\xae\xe9A\x85(\xcfW7v\xf5v5V;\x1f\xa3\xfc\xf4\xc0\xaa\xecſ\xc1\xfb^\xf9xӼ\xf9\xbf\xf9ͼ\xec\xe7\x99\n\x9a\x1e\x84^\xdf\u007f\xce\xc8\x18\x93\x9c\x91>\xe6\x81 :|$\xbb\xf3\xedX\x87qM\x0f:D\x19l(//opa{o\x92\u007f\xf3\xca3\xf9\xf7\xa0\xe1構\xf3\x9f\xa9\rd?\xf3\xd03L\x85\xc2M\x1f\u007f\xfc\xcc*R\f\xfe\x87u\xaa\xdavU\x1d\xb8a6\xf2\xb8IJ\x88'߹\xa6\a\x15\xa2\xecm\u0601\x86\xa6;\x1a\x1c\x8f\xe8\xbfD\x86\x9ao\xca\xe8\x88\xf1\xbc\xfc\x0e\x1ez\xbec\xa9Q\x88\xaf[\xf2I1\xf8\x0fcƌQ\xf2ƌ\xb9a\x1d\x1aCwH\xee|{\xdaa\\Ӄ\nQ6\xed\xc0\a\x0e\x17\x86\xa6\x9b\n?\xfd\x1bb\xfe&E\xd96W\xc1CЗ,5\n\x1fz\xf3\xcdM\x9a\x1e\xca\xff\xf9/\xff\x88\xf4\x18;g]{/\xd6c\x87\xb5\xb5x\xc4==\xcc\x10e\xa5\x96gh\xad\x14\xd4\x1fu\x96\xea\xb75\x1eB\a\x8e\x19h\x04\xf2\xca\xe0\xa3\a\x1a{\xbc\xa3\x9fo\xfe\xdf\xff\xf8_H\x8f\xa4\xd6.|\x94k\x96\x1c\x97\xd9\r\xdc\xd3\xc3\fQ\xba\xa6Ǧ\xc27\t\x1f\xe3\x03\xc7C\xbf{g\xf1\xaaO-5\xa8\xa1\xa9\xf2q\xe0\u007fb=\xdaI\xc7\xd7\xf9\xbcw\x17/\n\xb8\xa6\a\x15\xa2l '\x97\xe0\x0e\xc7/l_\x91\xc9uʶZ<\x00)\x90\xe5\xa2\x0f\xf5?\x9cZ\u05ee\x15h=\x94\xf5\xff-\xacG\xdf\xc4YJ\"\xe0\x9a\x1eT\x882\xb8\x83\fMw8\u007f\xe9\xb2mƦ\xe7_ڄ%y3\xf0\xca+\xaf~h\x1c<fKd\uf4fb\xa6\x1f\x87k\xff\uefc6\xf5\xd8,\xb5\fn-\x0eqM\x0f:D\xd9ۼ\xab\xaa\xa6\xd9\xf1\v\x17\xc4+E\xf3\xe6\x16\xe1[\xa2\xaff\xe1AHV\x916\xf8\xa8J+ǿ\xc8g.ԍ\x90\xf0ɥ)y\x85]k\xf1\x87{zx\x8a\x0f\xb3\u007f\xf5\xe1\xdf\xfe\xf6\xf1\x9bks̓\xc5`\xfeU\xd7c\x87\xefN7\\v\x01Ѓ\xf0\xd2\\\xed\xbc\xf2\xe9\xbcW8\xb5vhz\x9c\x1f\x97(\x1f\u0602\x1e\x1aoꗴ\xef\f\xba\xb4\xd5!\x17\xc0x\xec\xf1\x1f\xff{\x82\x1c8\b\xa0\a\xe1\xd3Mٿz\xfe\xd5\xe7\u007f\x95]f\xbd\xb4\xd5\x01=\x86\x8f\xa8\xf1\x18\xe2ӗ\x1e\xca\xcf\xca\u007f\xe8\xa5\bvh\xec0\xef{$\b\xa0\xc70\x00=\x86\x85\xa8\xf1x\x03\xf4\x18\x16\xa2\xc6\xe3\x8b\xdeGoCzܸ\xba)\x81\xfc\x00=\x86\xcc4\xe3\x03}\xb7\x1e\x0e\xe0\x02\xa0\xc7P\t\x8e]\xa7\xaaWUu`\xec\x1c\xcf}g:j\x80\x1eC%(I\x19\x19c\xd32\xd2\xc7\xdc\xe9\xfc\xb7\x1e\xdd\x02\xf4\x18*\xbdM\xe3RS'\xa4\xa6\xa6f\xb48\xff١[\x80\x1eC\xa6\xb7\xa3\xbd\xbd\xfd\x14\xfa\x97\x10\xdf\xf4\xd0\x00=\x86\x01θh9\x97D\xc1==\xa8\x10%U\x04<\x85{z\x98!J\xba\xe8\t\x1a[D5\x12\x05\xd7\xf4\xa0B\x94T\xd1\x1b\xa4\xe7\x89j\xe8\x8c\x19}D\x8bt\x16\xd7\xf4\xa0B\x94ևR\xbaN\xfam\xa2\x1a:c.\x8e6\xa0\x87\x06\x15\xa2\xb4<\x94\xd21Z\x93$\xe9\x81\xf6\x05\xe3\x93g\xe1۠\xd5Ӓ'\xe0\xf8l\x9d\xa4\x91\xae(K\xa4\xa4j\xe5\x94O\x9a\xc8\xd4ES˗MH\x9e\xd5\x01z\xf0\x115\u0383\nQZ\x1eJ\xe9\x18\xc1\x1d\xd5\xe3'\xa4\x8c[\x96'\x9dR\x94;\x93\x96\xd5=\x92\x96ާ\xf445N\xc8hllDC\xe5\x8eƤ\x87\x15\xa5y\x81\x8f\xa9\xdbV\x9d$\xa5=\xbc9e\x0e\xe8\xc1G\xd48\x0f*D\xc9>\x94\xd2Qҥ\f\x9c\xb7\xc7nj*\x05\x87\x9bH\x1f̓\x8b\x0f\xe9\xa1<\xecc\xeb*\xbeTt\xe4X\x90\x06z\xf0\x115΅z\x12%\xf3PJGI\xf7\xe9\x0f\xb1\xcb\x1bߋ\xd1\xfe_\x86\bz\x18u\x15\xdf\x02}\xea\xf0\xf5\x18C\xfeq\xfe\xaex\n\xf7\xf4`\x9eDI\x15\x1d%=]/L\xd2G\x1cs\xc8T{=\x8c\xba\xe6T\xbc\xa7\x9f\xbaI\xdb\xdfڅ\xc7X\xaa`\xbb\xfbA\x8f\xa1A=\x89\x92~(\xa5\xb3\x84E\xc8\x1b\xdfB\xe8\nO\xad\xc4\xc7\n\"\xc2\x03>\xb6.\xab\xc7\xcdOQ\xfb\xfb'\xf7Z\v\x16@\x8f\xa1A\x85(\x99\x87R:Kx\x977h\xa3\x8e\xfbID!#CQ\xbaȄ\xe4Պҗ\xceՃ\xde\xdf/\xdfx\xceR\xb8\xf8\xf8Mcn\xfc%\x9a\xf0\xa3\xb17\xfc\xe8ݰ\x1e\x8f\xff\xfd\x98\xef\xff\xf3E\xaa\x80\xfe>\xe6\xa6\u007f\x01=\f\xa8\x10%\xf3PJ\a\xe9m&\xd7(ڈb\xb5\x94\xb7\xab\xe6N\xa9\x1a\x97\x1f\xf6m\xae\xc9H\xc6\a\xb3ii\xeb\xd6M\x93\x92\xaaڨ\xba\xe8zfA\xb3Ҳ \xa9\xb1êǏ\xef\xb5\x16\x1e\x1f\xfb\xf8\xb9\x97\u007f|\xf1\xe2\xdf=u\xeeݟ\xfc\xd8\xd0\xe3ٿ{\xf6\xdc\xcb?\xf8g\xaapӽ\xef\x9e{\xf6\x87\xa0G\x18*DI?\x94\xd2A\xf0\xbd\f\x84\x1e\xa6n\xc8HM\xcd\xd0n\xbd\x04\x97\xa5&g\x90\xff\xfd\xa7=#9e\xd6\xfd\x92\xb4\x84\xaa\xbb\x04\xfdNjKF?\x97X\xf4\xb09x\xe0#\x82\xc1\xbb7\x1az\xdc\xfc\x1cz\xf9\xc6\xf7\xa9\xc2\rohu@\x8f8¢Ǐ~n-\\\x1c\xf3\xae\xf6\xfb\x8d\x1f\x8eE\xe3UC\x8f\xb1\xda\xf0\x95*\xfc\xd3؟\xfc\xf2\r\xd0#\xbe`\xf5x\xce8f\x84\vh\xff\xebz\xdc\xfcOo\\<\x17\xd6c\xcc\x1b\x86=F\xe1\xe2s\xf7\xfe\xe8\x86{A\x8f\xb8\x82\xd5\xe3\a\xbf\xb4\x16\x90\x16\xfa\xc9\xe5\x06$̳a=n6\x8e.\xe1\x02\xe6\xe5\x1b@\x8f\xb8\x82\xd1\xe3\xd9\xef_\xb4\x14\x10Oݨ\rMo\xba\xf7\xdcs\xdf\x0f\xeb\xf1\xd4\xd8_\xbe{\xee\xa9\x1fP\x85\x1f<~\xee\xdc\xcfo\x02=\xe2\n,\x86>x@G\x02\xe3\x98q\xb3y\xf0\xb8x\xf1_\xfe\x9e\\\xd8>\x87\xaeo\u007f\x1e\xd6\xe3\xe2S7\xdf0\xe6槨\xc2\xe37\x8f\x19\xfb×A\x8f\xb8\"<(\x1d5@\x8f8\x02\xf4\xe0!j<\xee\x01=x\x88\x1a\x8f{@\x0f\x1e\xa2\xc6\xe3\x1eЃ\x87\xa8\xf1\xb8g\xcc\xe8#Z\xa4\xb3\x80\x1e\x00\x87\x98\xd0#OJ]\x00))7\x88\t=:\x1a\xab&\xa6z&\x05\x93H8\xafG\xa3q\x1c訩j\xe8\x18T\x8c@\xa3\xe4\xc2'\xfe\x80\xe3zt\x95\xb7h\x85\x8e\xca\xc6\xf6\xc6\xca\x0eK1\x12͉\xf1\xf4%\xaf\xe1\xb4\x1e\x1d;t=\xfa\xc87\x8f\x9b\xaa\xfb\x98bD@\x0fWpX\x8f\xc6\xf2F=j\xddVI\x1e\xc6P\xd9\xc6\x14#\x02z\xb8\x82\xc3z\x04\x83F\x94\xb6A\xfb\xde^]#S\x8cH\xab\xe4\xc67\x95\x13\x1e\x87\xf5P\xc2I\xeb\x1a-\xd5\xd2T\xc3\x14#қ:\xad\xa9#\x91\xfe\xe3\x15o\xe0\x9a\x1e\xfa\xaf\x96j\xa6\x18\x19\x9c\x8c\x9eͫ\x00D\x01\xd7\xf4\xd0c\xf9\x8d5L1\"=i\xe3\x1fi8\xa5\x00\xce\xe2\x9a\x1e\xfa\x80\x03?\x19\x9d*F\xa4Yr\xfcIs\x80\x8bz\xb4\x95\xe3۠=\xe5mL1\"p\xe5\xe2\n\xae\xe9\xd1GB\x93\x8d\xda}\x8fp1\"\xa0\x87+8\xacG\xb0\xa3\xa3\xaa\xb1\x83\xe4\x9c\xe1\xaei\f\xe0\xb0\x1e-\xe5\x04\xf2\xf1ZGCe\x8d\xf1\x99\x8bY\xb4\xa3\xb7\xa3%\xcf\xe7B~\x1fpX\x8f\xef\xc6\x1cI\x1a\xef\xc2\xff\r\x03Ć\x1e\x1d\xadp\xe8p\x87\x98\xd0\x03p\v\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x83\xf3z\u0605(\xa9\xa9\x80\x97p\\\x0f\xbb\x10%5\x15\xf0\x14N\xeba\x17\xa2\xa4\xa6\x02\xde\xc2a=lC\x94\xd4T\xc0[8\xac\x87m\x88\x92\x9a\nx\v\x87\xf5P\xecB\x94\xd4T\xc0[\xb8\xa6\x87%9\tzx\x12\xd7\xf4\xb0$'A\x0fO\xe2\x9a\x1e\x96\xe4$\xe8\xe1I\\\xd3Ò\x9c\x04=<\x89kzX\x92\x93\xa0\x87'qX\x0f\xfb\x10%5\x15\xf0\x14\x0e\xeba\x1f\xa2\xa4\xa7\x02^\xc2a=\x80\xd8\x02\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\xc3\xf7\xee\a\x80\x88\x8c\xe8\xe8\x01\xc4;\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0eC\xd1#\xb8.=%)\xed\xb6\xa6\xc1\u007fyT\xbaS\xff1\x02\x066\x8f\xf7\x8dk\b\xbf\f\x0e\xa0\x1f\xd5\xd2mf\x85]Ҝ\xc1sQ<\"-\xe3\xfe]@\xc4\xe6-\x1d\x13@\xfa-ꪀQٞ\xa3\xc9\x10\xf4\xa8J\x924f]\xb5\xfeiTVg3n\xbb\xc5x\xf5h2^\x8a'\xf4`;&@뷨\xab\x02Fe{\x8e&b=VHҜV囮\a|Rƀ\xe5o\xa3\xb2:\x93\xa4\x15\xdf\f\x18-\x0fH\xd2 =:\x1em\xb4\x9b/\xcc\b\xf5\x88\xd8<\xd31\x01z\xbfE]\x150*\xdbs4\x11\xea\xd1(I;\xb4R\xab$UY\xfe8*\xab3Nj7_\xd8\xe9!b\x84zD\x84\xe9\x98\x00\xbd\xdf#dT\xb6\xe7h\"\xd2c \xcd\xdc\xf6ˤ\U00056fce\xca\xea\xa4I\x1d\xe6\v/\xe9\xc1tL@\x82\xea\xd1,IA\xa3|\xfeQ\xf2nj\xce\x1b\xe7K\x9e\xf8\x80\xa2\xb2\xab\x13\\1ޗ:\xa7U\xabJ\xbf\xe8Y2>)eZ\x15s\x94\xeeZ2.)u\x0e>\xafO#\xc3\x1ac\xff\xae&\xaf:\xb0\x1eʊq\xbe\xf1\x0f\x98't\xbbf\xdaf\xa7\xa6\xccj\xc7zTK\x13\xb5I\x9bɋG>'s\u007fN&Q\x1d\xae\x96\x1e\xed]\x92曄\x06\x9c\xd5\x13}i+\xa8\xf1B\xcfj\xdc\xe5\xb6p\xdbFnj\xbd\xf5\x88\xb4D\xb5\xb6\x1c\x9e\xc7\xe8\xb7ޖ\xb9z\xd69t\xe8\x85\xd9oω\xd2j\xd5}Dz< M\xb0LY&I\xe3&\xa5\xa1\x1f\x9f3\xabӚ,\xf9&\x8d\x97\xa4u\xaa\xe5EW\x8a\x94\x9a>\x01\rl\xa96꒤\x94t\xd4\x06\xda\x02\xeb\xf2|Ҭ\xbc]\xfa\x1fj\xf2$鶼 ڨh\x11i\xa9\x924q@\xdf\u007fv͔KR\xda$_R\x06ډ\x9f'I]d\xda\x04\xa9\rͽb\x9c\x94\x82\xe7\xfe\xc6\xd2\xe1jiY\xaa\x94擤\x86%\x92\x0fM\xcbP\r=\x9a\x92\xb5.\x85\xafό\x8eY\xf4\xa0[6\xe71\xfa\xad\xb5E\xad\x9ee\x0e\x1dza\x11\xb6gl\xe81[Z\xc0Nh\x96\x92\xf1A\xa1-Ez\x94^\x9d`\x8a\xb4\x1a\xad\u007f[\xaa\xd4`y1Gz\x00\xed\xe2S)\xe6\x86WO%I\xebд\x06\x9fT\xadF:\xb9H\xe3ѡ\xaa9I\xaa\xd1\xf7\x9f]3\x92\x84\xb4\xfa|\x169\xf8ܦ\x89y\n\x9f\x00\xd1\xdc\x13\xd0;\xb3ɇ\xff\xcet\x18\xfdeb\x97:\x90'\xf9|u\x03j\x83$\x9dқ\xefM\xc1\xed\x0fl\x96|\xe6\xbb\\\xeb\x98E\x0f\xaaez\x1e\xbdߤ-f\xf5\x989t\xe8\x19#lO\xb5\xae\xdc<\x90\xb9\x87H\x8fiV\x89WK\x0f뿗ѫ\xb3Z\x9aM&\xd7\xe1\xa3\r\xf3b\xbc\xb6\xf7+\xf3\x9a\xc3mܦo\xf1]R\xea@D=\xc8\xc1`\t^\n\xd9\xe66\xcd,\xd0\xfav\x95\f\x8f\x9a\xb4\x81\xd1\xfd\xd8\x124\xf7ym\xee%\x96\x0e\xeb\xedvI\xd2f<m\x1a\xdeg\xa4\xf9\x87\xf5\xc3R\x06\xb5\x17\xed\xf50[\xa6\xe7\xa1\xf5`V\x8f\x99C\x87\x9e1\xc2\xf6\xf4\b\"=fI+,S\xf4K\xbd\xcd\xe15!?\xc6I\xda\x15\xdd7IR\x0f\xfbb\x964\xad\x8d\xbd:\x1cH\xd6/\t\x06RЙ \x82\x1e\xdaP\xa2\x12\x0fQ\xc96\x1f܌\x9a\x82\xdf\xfb\xaa\xbeeQ[\xedd$}\x9e\x9e;Oe;\\\xad\x9d+\xbf\x91\xb4e\xe6I\x95z\xf3\x13%\xed\xfeWo\xafپ\xad\x1eT\xcb\xf4<\x94\x1e\xec\xea\xb1}\xd1`\x16f\xbf==\x82H\x8f;\xa9\xb5\xd2\x19h۵.\x0f\r,\x16P\xabsU\x92&M#$I-\xcc\v\xb5\r\x9d\xe9S\xf2j\xa8\x91YP\x92\xf4\xf3p\x06>w\xd8\xeb\xa1\x1d\u007fj\xf0o\xb2\xff\x067\xf3\xb9\xd1L\r\x19ٮ\xc0ǒ\x16)\x9d\x9a[\x1f(R\x1d\xae\xd6\u07b7h)x$\x88\x8e?\xe5z-\x9f>t\xa1\xb1Ճj\x99\x9e\x87҃]=K_\b\xec\xc2춧W\x10鱙\x1e\x9a\xb6\xe2-P\x99\x86\a铦1\xab\xa3H&\r\xcc\vt$_\x90\x8c\nI\xcb\xc2C\xb3\x0e)I/\xcd\xc6wRx\x17\xb6\xa6\x1e\x83\x9b\xe9\x91$\xad\xd0H\xf4h\x97\xd2\x06\x90\xcd\xd5\xd4\xdcڌt\x87\xf5\xbf\f\xd2\x03\x1dN\xa8Æ\x8e\xad\x1ef\xcb\xcc<\x94\x1e\xec\xea\xb1}!\xb0\v\xb3ݞ^A\xa4G\a\xb5*=RR;\xbeӼ\xa4\xee\xd4U\xf4\xdbr\xf48\x1f\x9e\x87y\x81\x19h[7I2W\xba'\xfc\xf6\x9a\x16\xf9\xe81H\x8fA\xcd|n\xdcj\xa8Ӯ\x8b'H\xad\x03\xc9I\x9f\xab\x16=\x98\x0eG\xd2C\x95\x84G\x8fuV=\x98y(=\xd8ճу\x99\xd1~{z\x05\x91\x1ehH\x18\xbe\xe7\xb4\x1a\r\xb5\xd0\xf9T\x1b\xbb\xad`W'M?\x9d\xaam=\x03신6\x02\xaf\x96\x92\x8c\xa1Ào\bc\x0f\xab\x1e\x83\x9bQS\xf5f\xd6i]\xdc,\xadn\xd1\xf6\x01\xbdK\xd8\x0eG\xd4c\x82>\\j\x98Ui4\xafw\xac\\?\xbd.\x19\xa4\a=\x0f\xa5\a\xbbzvzP3Fڞ\x1eA\xa8G\x8d$\xd5i\xa5&\t]{)\xba\xf9W\xc7\xe1\xadf\xae\xce\x12)\x9d\xec\xb6f|\xb1F\xbfP\xf4=\xd1E\xedWch_#\xa5|3D=\xec\x9a\xd1/\x06\x06t\x83\x83\xd2\xf8՚\x97\xf4.a;\x1cQ\x8f\xd5\xfaޛ\xad]\xd2\x10\xb4\x8e\xd5i\xa7Wt}dՃ\x9e\x87҃]=;=\xa8\x19#mO\x8f \xd4C\x9d\x83\x06MmW\a\xba\xee\x97\xf0Gr\xc8v|5\xd97K\xc2;\xce\\\x9d.\x9f\xb4\fm\x9f\xf6T|\xa5ü\x98%\xcdB\xbb\xe2j\x1euC\xebT\x92\xb4\x19\xed\xe4\xc6d|\xe1`\xb9w\x9d$5|3`s\xf4\xb0i\xa6\xc7'=:\x80'\xe9\a\xb8\f)9\x85\x1c\xd6-G\x0f\xaa\xc3\x11\xf5\xe8I\xc6]\x1axDJV\xc2\xedk\x1dC\xe7\n\xf4\x97\x9e\fi\x90\x1e\xcc<Z\xbf\xc9tf\xf5\xec\xf4\xa0f\x8c\xb4=c\xe4\xbe\a\x1aH-0\x86\x99\xb3\xc9\xc8T\x92\xc6\xcfNOJyX\x9aĬN\xa3O\xf2Ớ\xe4S]\xfaE0U\xf2M\x9c\x94,\xa5\xf5\x98m\x92ۊ\xe3$\xed\xa2\x99\xd5#]\xc2\x1f\xa2ۜ\\l\x9aiH\x92\xd2ғ\xa5\xdbt=j\fO\x98]\xc2t8\xa2\x1e\xf8\xbeUJz\xaa\x94D}\xabE\xef\xd8\x12t\xc94NJ\xde<H\x0ff\x1e\xad\xdf\xdatz\xf5\xec\xf4\xa0g\x8c\xb4=c\xe3\xae)\xa6m\xc9\x04_\xd28\xe3~TsF\x9ao\xe2ß_\xf5\xa11+}0\xecY6ޗ\x9c^\xa9\x1d\xfa\xe9\x17\xc1\x15\x13|x\x0e\xbaɎ;\xc7\xf9\xd2nӾK\xc1\xeaѕ\xe1K\xa9\xb3\xd1þ\x99\xbc\xb4\xe4i\xcd\r\xba\x15\xa8K\xda;\x8e\xdd%t\x87#\xebA>'I[@wE\xef\xd8@\xf5$_j\xde\xf9\xd6\xc1z\xd0\xf3h\xfd֧S\xabg\xab\a=c\x84\xed\x19;z\xc4\n\xc1A\x9f(\x03#$\x9e\xf4\xd8L\r+\x81Q!n\xf48\xdf\xdb\xe0\xf3\x99\xc3J`T\x88\x1b=\xf0\x00\x1a\x0e\x1e\xa3M\xdc\xe8Q\x99\x9c\x06v\x8c:q\xa3\a\x10\r@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c\xdcУ\xa2BT\x03\xf0\b#\xd5c\x9b,\x1f\xa3^\x9e\xce?\x19\xb1\xaa\xc1_\xe5ݢ*\xa3\xc1\xdb3d\x8d\xfc\x90\xa8*C\x05\x9a%\xfb\xb2\xa8V\x820R=\xaetf\xd5S/O\xe6\x1c\x8fX\u0560,p\x05\xff:\xf3'QE\x13a]\x9b\n\xfd\xefeUt\"v\xcb_\xd9\xcc\x10\x99+\x9d\x9d\a\xe5ߋj%\b#\xd5CU\x03\xb4\x1e\xaa\xf8\x9dzy\xc6N\xf2\xbb\xa8LP\x91BX\u05f6\x82ֳ\xa3\xf25\x9b\xbfq\xe9\x06=tF[\x0f1[\x03_\x92\xdf\xf7\x89v9\x85\xb0\xaem\x05\xadg\x97w\x8a\x95\xb5\x00z\x18\x88\xf4\xb8^V\x98U\xb8\xe1\x02*]Ȓ\xe5\xda\xcbe\v\xb3\xd7~\x8b^]\xdeR\x90\x95\xbf\x1e\x9f%\x02\xbbw.\xcd^\x8bKײe}$\xf2:*ԫ\xf5\xe8\xe7\xeb\xe8\x80r\xb48g\xe9\xce~\xbd\xc1ϲ\xb6\xa3\x9f'\xf5q\xc1*\xce\"\f\xe8\xbatc\x9dk\v\xb3\n\xd6/\f\xb1\x15(\xc2\xe2\xfe\x05\xb5\xbb!T(˹!si\xdf\x16d=]Xxf{n\xe9u4\x82\xca:XQ\x98\xbbA\x1fr\x84\xf5`\xbb\x9e\x80\x88\xf48)W\x9cy}\x83܍\xce\xe5\xaf\x1f[\xb88\xa7pgٌ/й>g\xd5\xfe\xd3\xf5\xf2\x01T# /=v\xbc`\v\xae\xdc\xdd٩\xed\x92\xeb\x9dsk\xbfR\xbf\xaa\xcd\xed\xbc\x8e\xc7z\xdb\xdf:\x98\u007f\x9f\xfe\x1e\xae\xc8\xc2&\xf5\xbf\u05f9\xf8A40\xf8k\xe4E\x84\xa1\xebR\x8d\xfda\xc6\xd6\xe3\xa7\x0f\x15\xc8߲\x15(\x02\xb5\xfd\xfde\xf8L\x16\xfa\xa0^\xfe@=:\xe3\xe8G\xf4\xd2\xce̕w\x96\xca\xf3\xf6\x15\x1cP\xffr,K^\xb8\xaf~a\xf6%2cX\x0f\xb6\xeb\t\x88H\x8f\xfech\a\x87\x96o /\xee\x93\xd1;-\x84&\xf4\x17\xaeE\x9b,\xf4:>\xab\a\xf2\xbfF\xdb1_\xaf\x9f\xad\xbfc+\xf0Ѿl\xab\x8a\xf7\xc7Q\x15oq\xed\x02糬mz\xcd\xf0\xf9\xc0~\x11\f\xe1\xbaTc\a\xf3\xf1!\xe6`n\x88\xa9@\x13\xc0\x87\x94\xf5\xa4\x18\xdaZt\xadp\x1f.QK\x9b_\xa6\xbe%\x9fT\xb7\xe2\xeb\xec\xc0B4\xf9Za\x11\xa9m\xe8\xc1v=\x11\x11\xe9\xa1^;\xb8\xf6\xae\xb9\xf2rR\xbe/\xa0\xbf\xabߖ?\nW\b\xe0\xad[\x1f\xd0_\x19z\x9c\xc9\xeeW\xfb\xb3;Q\xa9\xec\xaeз\x88B\xedfǶ\xac\xcf\xf4\x9a\xe6\x1e\xb5]\x04C\xb8.\xd5\xd8\x17\x85\v\xb7\x1f\xfa(\x14b+\xd0\x04*\xba\xbbu\xeb\xd4\xfe\x9f\x16\xacת\x9aK\x9b\u007f\f\xed\xfa~u7\x9e7@.\xb6\x0fj\xc3XC\x0f\xb6뉈H\x8f\xee\xfc\xc2\xdd\xc7;K\xf5}W\xa4O= \x9b\xe7cr:\x19\xa4Ƿ\x05\xc7\xd5\xe3\x05x\x87,\xd7G\x06d?]\tl5\xe6\v\xefQ\xfbE0\x84\xebҍ];T\xb6T.\xd8\xcf9z\xa0\xbe\xbc}Z\u007fq\\~\x8f\xfc\xa6\x966\xff\xb4ڝ\xa5\xeaz\x90~w\xca\xe4\x02\xd9Ѓ\xe9zB\"\xd2ci\x11\x16a\x8b\xbe\xef\xb6\xe8SO\xcb\xe6}\x06{=\xd4\xed\x1b\xd4-x\x10\x8aނ\u007f\"\x90\xf7\xe5N\xd98xh{\xf4\xf0\x17\x91\x16\xc1\x10\xaeK5ֽ\x1b\x89q\xedX\xf6A\xa6\x02\x8d>4\xbd\x80\x97|e~\xed¯\xf1+jiX\x8f\x80\xa1\a\xb9\xda>$\x93Ӛy\xf4\xa0\xba\x9e\x90\x88\xf4(Ļ+\xf4S}\xdf\x19\xef\xd1\xeb\xf3K\xf1\x9bv;ަ\x11\xf4\xf8 \xf0e\xe0\x03\\8\xad\x9d\xbak\xf1\x99\xffK\xf3ࡖ\x96\xa2\x9d\x86\xfff\xbf\b\x86p]\xaa\xb1z\x99\x1c\x18J+\x98\n\x88\xcf\xf6\xe9\n\xeaz\xccG\xe7\x8dPQ\xadZA\xfaL-\x8dѣ\x00\x0f\xa9\xee*%s\x18z\xd0]OLDz\xd4\xcbe\a\xf7݇\x8e\xe1\xdd\xdf~@\xae\x0f\xb4M\u007f&pϡ\xb7\xb7ˇ\xd5/;\xb3*\xbaC\x1fUdu~\xa9\x86~\x8f\xae\\*:;\xc9;0T\xb8\xb6P;\xd9\xef\x9eQv\xfcx\x05\x19\xe5\xed\x9caޭ\xae\x0f\x1c8^\x9a\xf3E\xc4E0\xbd0\xeaR\x8d\xd5\xcb9\xb5'Q\xf1\f[AU7h\xc3Q\xe3\xaei\xe7ܝ\xfd\xefm˿\xa2~6w\xfb{!ji\u007f\xc9=\xd0\u007f,\xebB\u007fY\xe9\x15<\x8c]u\xec\xf0\xe2\xdcOИ\x06\xdf5=\xd0\xd9\xc9.-A\x11\xe9\x11:\xb08\x90_vxqV\xe9\x05\xed<\xac]\t\xa8\x9f\x94\x15\xe6\x14\x1d'\x9f\xb9\xc8Y\xff\x9e\x83~nS\xff\xa0\x9f\xaa\x0f\x91\x1a\a\x02\a\xf46N\x97\xce\xcb-~[\xc57F\xa8cCh{n\xf6\x83ݜEP\x84\xebR\x8d\x1d}\xb0\xbe0k~\xe9\x19k\x05\xf5p>\xe9\xc0۲\xc1\x81\xd3\xe8\xc7Nu\xbb,\xcf8c.\xad\xb8@\x96\x8f\xe5\xc89\xc7\xc8\xd8\"\xb0\xb3bna\x19\xbea\xb7U\x9f\xab\x8cYZ\x82\"\xd2cTyZ\xb6ޚ\xf0\fý\xf7\x9b 8\xaa\xc7\xd6a\\!\xf6\u007f\xa6\xe1\xd0-K\xd0\xc3\x16G\xf5\x18\x0e\x0f\xea\xc7\xf8\aE\x15G\a\xd0\xc3\x16\xcf\xea\xf1\xc9I\x8dOD\x15G\x83+d\x80-\xaa\x95\x80xV\x0fG!\x03\xec\xc1\x17L\x00\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01ppC\x0f\xc8\xd8\xc6\f#\xd5ct2\xb6C\x99m\xb8\x8cj\xc6\x16M\xc4\xdf^9 \xcbV\xb5\xa3\xd1u\xef0R=\xbe{ƖF4\x9b\xeb\x19\xdb/r\xf6\xe3/\x9c^۟c\xfd\"\xbd\xd9ua'c\x90\x91\xea\xf1\xdd3\xb6\f\x82\xd9\xdc\xcf\xd8.?L~\x1d^>\xa8r\xb8\xeb\xc2N\xc6 \xa3\xad\x87\x18#c;\x1c\xdc\xcf\xd8n\xa9%\xbfjm\xbfH\xaf!\xecd\f\"\xd2#J\x19[u\xa9>0(\xa6g\xb3D]u<\x91\xb1ݭ\xed\xfb\xb2\xdd\xccv0\xbbn\xdfI\xfb\xd0p\f!\xd2#J\x19[5@\xc6\x05E\xf2~z6K\xd4U\xc7\x13\x19\xdb\xc3Ejw\xe1\xef\xd5\xfb\x0e\xb1\xdb!\xdcu\xfbNڇ\x86c\b\x91\x1e\xd1\xca\xd8֣q\\\xa8B>h\x99\x8d\x89\xba\x9a\xb8\x9f\xb1\xed,Pwg\xedV\vp,\x94\r\x02\x87\x93=v\x9d\x8c\x14\x1a\x8e\x15DzD/c\xab\x86\xcaf\x84\x03$a=訫\x89\xfb\x19\xdb/\xe4\xfe\a\xb7\x16_\xd7B~L\x10x\xb0\x1e\xcc\x1aۇ\x86c\x05\x91\x1e\xd1\xcb\xd8\xf6\xaf\xcf2\xaff\xc3z\x90ߝ\xb2\xe5\x1a\xd1\xfd\x8cm(p)\xe7O9\x97\xb2\xb4\xa5\x15QK\x19\xac\a\xb3\xc6LݘC\xa4G\xd42\xb6\xd7\x1f\fP\xf1\xa2\xb0\x1et\xd4\xd5\xc4\x03\x19\xdb\xc5\xfb\v\xd5\xc2\x03\x8b\xc9t&\b\xcc\xeaa\xe9d\xa4\xd0p\xac \xd2#Z\x19\xdbkE\xe4\xccs\xb2\x94\x9d\x8d\x89\xba\x9ax c\xbb\xbex\x8b\xba\xa5x-\x99\xce\x1c\xab\xc2kl\xd7\xc9X\xbf\xdc\x15\xe9\x11\xa5\x8c\xed\xb5\xe5\xf2>|\xe9\xb2\x15\xed\x1ez63\xea\xca\xf6\xc2\xfd\x8c\xed\xce\x19\xfb\xd5\xfd3\xd0\xf1\x90\xde\x0e\xcc\x1a\xdbt2bh8V\x10\xe9\x11\xa5\x8c\xedGYz݅*3\x9b\x19ue\xf0@\xc6\xf6\xad\xec\v\xea%|\x03\x9d\xde\x0e\xcc\x1a\xdbt2bh8V\x10\xe91\xaa\x883\xb6ý\x05;j\xb8\xb6`o\xe3\xa8\x1e⌭\xb9\x97 c\xeb\x05\x1c\xd5C\x8c\xb9\x97 c\xeb\x05<\xa5\a\x1du\x85\x8c\xad\x17\xf0\x94\x1e\xaeE]][\xb0\xd7\xf1\x94\x1e\x80\xd7\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01ppC\x0f\xc8\xd8\xc6\f#\xd5#A2\xb6\x87qC\x05k\xcd/`\xdb\xf2Y\x96\xbc\x94_#\xd6\x18\xa9\x1e\t\x92\xb1\xbd~T\xde\xd7y\xb8x\xc6\x19\xdbY\fB\xdd\x15\x015\xae\x18\xa9\x1e֏\xc2\xc5\xef\xd4\xd8\xcc\xd8^\xc2\xdfl\r\x15/\xb6\xabNQ\x0fzX\x18\xee7%b3cK\xf4P\x0fʂo'%\x9a\x1e\x90\xb1Ֆ\xa6\xe9QV\xc8N5\xb7\x0e:)\x95\x15\xe6n\xd1N.\x90\xb1M\xb4\x8c\xed%\xf9\xad\xfe\xbf\xee\x96\xf7\xb1S\xcd\xc6\xd4\xcbs\x97\x1e>\xbeV\x0e0\x15 c\x9b \x19\xdbK\xe4\xf8T\x16b\xa7R\x8d\x15/\xee\xc7ŀjYc\xc8ت\t\x90\xb1\xbd$\xef\xef>Y\x9c\xfd\x19;\xd5l\xec\x9a\x16f\xa8\rX*@\xc6\x16\xefٸ\xcfؒ\xb1\x87\xe6\x005\xd5l\xac[&\xd9}\xb2\x1d c\x9bp\x19[mh:\xb7\x96\x9dj6\xf6\xb5v\x9e\xdc\x1aP-k\f\x19[5\x012\xb6\x9a\x1e\xf9;/죧R\x8d\x15\x15\"\x1b>\t\x04\xd8نpM\xeeiDz@\xc6V[\xda\x05\x19\x1f\xebJ\xd7W,g\xfb`4\xa6^\xca.\xac\xaf͕\xb3\x8e\xfe\x052\xb6\t\x97\xb1E\x95\xf05\xf8\x85\xc5\x05'\xe9>\x98[\a]\xd9n\xc8]\xb8\xfbh\x96\xbc\x8d\xaa\x00\x19\xdb\xe1\x00\x19\xdbX\xc3Q= c\x1bk8\xaa>o5\x06\x00\x00\t\x1cIDAT\x87\x18\xc8\xd8z\vO\xe9\x01\x19[\xaf\xe1)=\\\x8b\xba\xba\xb6`\xaf\xe3)=\x00\xaf\x01z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c\x04zX\"\xb4\x14_W\x14d\xeb_\xee\xf5|B6Q\x9fB;r\x04zX\"\xb4\x14\xa5\xf9\x87\xb6fk_(\xf7|B6Q\x9fB;r\x84'\x97\b\x9ft_\x93\x0f\x9a\xe9\r\xc1\x1b\xdc\xfd\x84l\x82>\x85v\xe4|W=.\xcbC?*\v\xbf\x8d\x1b\xf5\x84l\x82>\x85v\xe4\x88\xf5ؾU\v\x9f\xa2a\xc8Q\xfd\u007f\xb0\b\xcd\xd3\xc6\x05\xf8\x8b\xeafB\x16M?\xb4*\xfb\xa7\a\xd9\xfd鉄l\x82>\x85v\xe4\x88\xf5\x90W\xbd~ly\xf6%m\x18\xa2\xff\x0f\x16\x1fu\x1e\x93\xeb;;\xc9W\x86\xc3\tY\x9c\xf2\xa8}\xab6\xf0\xbf\x99\xf9=\x91\x90MЧЎ\x1c\xb1\x1eK\xd1\xfb\xa8\u007fq\x91\xca&Z\x98\x93\x8b\x9eR9M\xb2 \xa7e*\xdeDp?!\x9b\xa0O\xa1\x1d9b=\x9e\xc6?\x0f\xe1\x11\xa2H\x8f\nm\xe4w\x8f\xf5\xea\xd1\xfd\x84l\x82>\x85v\xe4\x88\xf5 ۏ\x84OEz\x14k\xef\xf5\xf5E*\x8b\xfb\t\xd9\x04}\n\xed\xc8\x11\xebA§\x87q\xf8\x94\xec\x84Z\xce\xd1\xe3.\xbc\xf9C\v\xc3)k\x1d\xf7\x13\xb2\t\xfa\x14ڑ#\xd6\x03G!C\xf7\xe0\xf0i6\t\xabF\xd6\xe3-r\xbe>&\xbfei\xc2\xfd\x84l\x82>\x85v\xe4\x88\xf5\x90\xd7~p\xba\x98\xa4^\x8b\xf3\xf7\xef+\")R\xedʅ|\xf5\x9fNȖɻO\xee\x96\amQ\xf7\x13\xb2\t\xfa\x14ڑ#\xd4\xe3\x9e\xfa\xb2\x1c=\xf5z\xb94;g\xedӲ\xbc-\x94K\xce\xceY\xf8:\x90NȆ\x0e.\xcf^n\xb9\xef\xa1z !\x9b\xa8O\xa1\x1d9B=b\x02ȸE\x89(\xe9\x01\t\xd9\xf8 Jz@B6>\x88\x92\x1e\x90\x90\x8d\x0f\xa2\xa4\x87\xa3@B6jă\x1e@\xd4\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\x02=\xe2#c\xab\xaa\x17\xd6\x17\xcc}\xf0\xcc\xf2\xf7l\xe6\x18\t\xecҢ\xb1\x1d\\F\xa0G|dl\xd5?e\xad?~t\vy\xf0\xe1\xa8\xc2.M\xb4\x1db\x10\xe1\xc9%.2\xb6k\xf1\x17UC\x15\xa3\xae\x87\xca.mx\a\xbaX\xe0\xbb\xea\x11[\x19ۅ$c{A\x8e»\xdbfiq\x84X\x8fx\xc8ؖ\xcd\xc7\xf9\xca\xd0[\xe4p\x17~\x04\xaf\xf9\x14Z\xd4\xc2!\xfdi\xbcTqHq[ci\xcc\xd3xmZ\xa0\xd68\x86\x10\xeb\x11\x0f\x19\xdb\xcf\n\xe5\xb5\xf5\x1fh;\xc6|\x04\xaf\xd9\x18n!\xbf~\xff\xdc-LqHq\xdb\xf0Ҙ\xa7\xf1\x0en\x81Z\xe3\x18B\xacG<dl\xd5k\xfb\x8a\xb2\xe4\\\\\xa2\x1e\xc1K?\xa37\x90\x8b\xde\xece\xf9lq(q[\xfa\xe4\x12~\"\x9e]\v\xcc\x1a\xc7\nb=\x9e\xc6?c<c\x8b\t\x9d^\x8f\x03Z\xf4#x\xa9g\xf4\x92g j\xebf\x16\x87\x12\xb7\xb5\xd5î\x05f\x8dc\x05\xb1\x1ed\x95c<cۭ\x8d\x03\x8a70\x8fय़\xd1K\xad\x9bY\x1cJ\xdc\xd6V\x0f\xdb\x16\xe85\x8e\x15\xc4z\xc4C\xc6v>y\xa2\xaeZ\xbb\x98y\x04/\xfd\x8c^[=\x86\x12\xb7\xe5\xeb\x11i\x8dc\x05\xb1\x1e\xf1\x90\xb1-\xc0\x0f\x99UCx\x0fS\x8fय़\xd1k\xab\xc7P\xe2\xb6|=\"\xadq\xac \xd6#\x1e2\xb6\x05\xf2\xfc\xfa\xd3\xc7K\xb3\xf1Z\x84\x1f\xc1K5F=\x8d\x97~0\xaf0nK-\xcd\xdc\x0e\xf6-\xb0k\x1c+\b\xf5\x88\x8b\x8cm\xd1\xe1ڥ9\xf9\x1b\xb4ԍ\xf1\b^\xea)\xb4\xd4\xd3x\xe9\a\xf3\n\xe3\xb6\xd4\xd2\xcc\xed`\xdf\x02\xbbƱ\x82P\x8f\x98\x00RrQ\"Jz\xc4s\xc6\xd6\xe1us\x95(\xe9\x11\xcf\x19[\x87\xd7\xcdU\xa2\xa4G<gl\x1d]7\x97\x89\x92\x1e\x8e\x02\x19ۨ\x11\x0fz\x00Q\x03\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\b\xf4\x80\x8c\xed\xc8ѲA\xb1\x89@\x0f\xc8؎\x1c=\x1b\x14\x93\bO.\x90\xb1\x1d9\xf5\t\xa7\adl\x87A<\xeb\x01\x19ۈ\x19\xdbZ\xb2\xea\xc7\xd0\xcfZj噺W\xca\ns\xb7h'\x17\xc8\xd8&X\xc6\xf6\xab\xb2\xe2\xce\xeb\xea\xf5\xf7\x8aˮQ+O\u05fd<w\xe9\xe1\xe3ke\xbc\xcd c\x9bp\x19ۣ\xda%\xc9\U000a3595\x0f\xd7-^\u070f\x17\x81\xb7\x19dlI\xa0(\x912\xb6\x17\xe4P\xff\xd1k\xdf\x06.XVި{M{\x10\x19I\x16B\xc66\xe12\xb6\xa1\xac\v\a\xe4ڿ\xca!\xcb\xca\x1bu\xbbe\xf2\xdcm\xad]\xc8\xd8\xe2UO\xa8\x8c\xed\xd2c\xa5\xc5K\x8f\xe3S\f\xb3\xf2Fݯe\xb2~[qc\x90\xb1M\xbc\x8cm\xd9\xf6\xac\xd3\xf26\xfc\x17f\xe5\xc3u\x8b\xf0\x82?\t\xe0\xc6 c\x9bp\x19[u_\xf6\xdc\xd0\xe2l\xa2Ox\xe5麗\xb2\v\xebks\xc96\x83\x8cm\xc2el\xd5\xee\xdcZu\u007f\x0e\xe9zx噺\x977\xe4.\xdc}4\v5\x06\x19[\xd7p4%\x97HDI\x0f\x87s\xa8\x8e\xea\xe1\xf0\xba\xb9J\x94\xf4p8\x87\xea\xa8\x1e\x0e\xaf\x9b\xabDI\x0fGs\xa8\x90\xb1\x8d\x1aQ\xd2\xc3Q c\x1b5\xe2A\x0f j\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\x81\x1e\x90\xb1Ml\x04z@\xc6v\xa4\bW\xde\xd3\bO.\x90\xb1\x1d\x19\u0095\xf74\xdfU\x0f\xc8\xd8\x0e\x11\xe1\xca{\x1a\xb1\x1e\x90\xb1\xe5=\xc7\xd6h\x8c\xda:\x91\xd6\xcd\xd8:t\u05fd\x8eX\x0f\xc8\xd8r\x9ec\x1bn\x8c\xde:\x11\xd6-\xbcu\xa8\xae{\x1d\xb1\x1e\x90\xb1\x8d\x9c\xb1\xa5\x1a\xa3\xb6\x8e\xfd\xbaQ[\x87\ueeb7\x11\xeb\x01\x19\xdb\xc8\x19[\xba1s\xebد\x1b\xb5u\xe8\xae{\x1b\xb1\x1ed\xd7C\xc6\xd66cK5F\xb7`\xbbn\xd4֡\xbb\xeem\xc4z@\xc66rƖj\x8c\xda:\xf6\xebFm\x1d\xba\xeb\xdeF\xac\adl#gl\xa9ƨ\xadc\xbfn\xd4։'= c\xcb\xc9ؚ\x8dQ['º\x85\xb7\x0e\xd3uo#\xd4\x032\xb6\xbc\x8c\xad٘\xb9u\"\xad\x9b\xb1uBL\u05fd\x8dP\x8f\x98\xc0є\\\"\x11%=\x1cΡ:\xaa\x87\xc3\xeb\xe6*Q\xd2\xc3\xe1\x1c\xaa\xa3z8\xbcn\xae\x12%=\x1c͡B\xc66jDI\x0fG\x81\x8cmԈ\a=\x80\xa8\x01z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c\x04zD\xce\xd8F\x99Q\xcd\xd8\x1e#-\xcd\xdb0\xf8\xc6;\x95\x14\xa6\x8a\x80\x81@\x8f\x88\x19\xdb\xe1DG\x85u\xa3\x9d\xb1\xbd~R~\xba\xb3\xf3\xe8\U00082bedթ\xa40U\x04\f\x84'\x97\b\x9f\x95\x0f':*\xac\x1b\xf5\x8c\xed\x97Z\xd8%ۺ.TR\x98\t\r\x03:\xdfU\x8f\xe1DG\x85u\xa3\x9e\xb1\xd5\xf4P\x97[\x97C}\xa1z8\xa1\xe1\xc4A\xac\x87\x91\xb1\xc5yѧ\xd5z\xf4\xf3uan\x96BX\u05c9\x8c\xad\xa6Ǖ\xc0\xbe\bIa:4<\x84`m\xe2 \xd6\xc3\xc8\xd8\xf6\xbfWXqE\xfd\xaavn\xe7uan\x96BX\u05c9\x8c\xed\x97\xf2\xe1\xfe\xeb\xbf_\xbe\xf4z\xa4\xa40\x1d\x1a\x16\x06k\x13\b\xb1\x1efƶ\x1e\xbf\xc1\xf5`\xa807K!\xac\x1b\xf5\x8c\xed\x97\xe4ذ\x98\xe4\x06\"d\xfd\xc2Ea\xb06\x91\x10\xebafl\xaf\xcc\xf8w54W\xcb5\ns\xb3\x14ºQ\xcf\xd8~)\xd7vw\x9f\xde:\xef\x0f\xaaX\x0fa\xb06\x91\x10\xebA\x86\x00Z|u\xfdN\xf5t\xaee\x8fF\xca\xcdR\b\xebF=c\xab\x0fM\xcb\x16\x87\xc4z\b\x83\xb5\x89\x84X\x0f3c\xab\x9e,\b\x19\xff\xe9\x8007K!\xac\x1b\xf5\x8c\xad\xae\xc7\xe1\xf0\xff308)L\x1d=D\x0f\xafM \xc4z\x98\x19[5Tp2W\u007f?\vs\xb3\x14ºQ\xcf\xd8\xeazl\xcd\tEL\n\x87\x8b\xc2`m\"!\xd6\xc3\xccآ}qW\xae~Y\"\xcc\xcdR\b\xebF;c\xab\xdd5=^&\xefW#$\x85\xa9\xa28X\x9b@\b\xf5\xa02\xb6\xaa\xfa\x89l\x1c\x19\x84\xb9Y\na\xddhgl\xb5\xcf\\\xb2\x96\x1f»\xdf.)L\x87\x86\x87\x10\xacM\x1c\x84z0\\\x0fx\xf3)\xbd\x8e\xa6\xe4\x12\x89\xe1\xe9\xf1\xfa\xbc!\xde?t8\x87\nzD\x89a\xe8Q\u007f&TZ+\xaa\xa4\xe3p\x0e\x15\xf4\x88\x12Cף_^\xb5m\xfeP?>u4\x87\xeap\xc66\x91\x18\xba\x1ej}N\xa9\xf5s\x11o\x00\x19ۨ1\f=\x80\xc4\x03\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\xc3\xff\a'\xa7c\x12\x8d\x96\rF\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/callers1.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xa2\x00\x00\x01.\b\x03\x00\x00\x00\xa3\xcb_?\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x04\a\x03\x06\f\x0f\n\r\t\x10\x12\x0f\x17\x17\x13\x1a\x1a\x14 \x1f\x19!# #$\"%$\x1d$%#&'%'(&+)\x1e()'++$*+)+-*/-!,-+-.,02/52'241574796<9-9;8:;C;=:=?<B@4?@>#CxAB@CDBDFCKH<MH7HIG\x00f\x00\x00h\x00\x00i\x01JLI\x00j\x02MOL\x05m\x05PRO\fo\t\x0fq\vTVSZVD\fr\x17WXV\x11t\x19,`\xae7]\xad\x15v\x1c[]Z\x19y\x1e]_\\d_M:b\xac_`^<c\xad>e\xafac`*{!Ag\xb2ceb)|*dfcfgeghfLi\xafDl\xb0hjgqjR\\k\x88/\x82/jkiHo\xb3/\x858Jq\xb5mol;\x86:pqoUt\xb4>\x89=|t]tvs@\x8b?swzB\x8c@vxu@\x8dG\\{\xbbxzw]~\xb7K\x8fJ{}z\x85}d}\u007f|O\x93N\u007f\x81~c\x83\xbdN\x95Uu\x84\x96\x81\x83\x80W\x95V\x8e\x85gm\x87\xbcZ\x98Y\x87\x89\x86]\x9c\\\x89\x8b\x88\x95\x8bm\\\x9dcs\x8d\xc3d\x9dd\x8c\x8e\x8bf\x9fg{\x90\xc0\x8e\x90\x8d\x90\x92\x8f\u007f\x93\xc4j\xa3jz\x97Ɠ\x95\x92s\xa4l\xa1\x96xq\xa5s\x81\x9a×\x99\x96\x84\x9cƙ\x9b\x98u\xaaw\x9b\x9d\x99~\xaay\x9c\x9e\x9b\xa8\x9e\u007f\x88\xa0˞\xa0\x9d\x80\xad|\xa0\xa2\x9f\xa1\xa3\xa0\xa2\xa4\xa1\x92\xa5ʮ\xa4\x85\x82\xb1\x86\xa4\xa6\xa3\xa5\xa7\xa4\xb4\xa7\x82\xa6\xa8\xa5\x8b\xb3\x88\x95\xa9Ψ\xaa\xa7\x8d\xb5\x8a\x98\xabѩ\xab\xa8\x8e\xb6\x8c\x8d\xb8\x93\xab\xad\xaa\xb9\xad\x88\x9f\xaeέ\xaf\xac\x96\xba\x96\xaf\xb1\xae\xa3\xb2Ҙ\xbc\x98\xb1\xb3\xaf\xb2\xb4\xb1\x9b\xbe\x9bµ\x90\xb4\xb6\xb3\xb5\xb7\xb4\xa3\xbf\x9d\xac\xb7Ң\xc0\xa4\xb7\xb9\xb6\xb8\xba\xb7\xb9\xbb\xb8\xa5ħ\xb1\xbc\u05fb\xbd\xba\xbc\xbe\xbb\xbd\xbf\xbc\xafƫ\xa9ȫ\xb8\xc0տ\xc1\xbe\xce\xc1\x9b\xc1ÿ\xb2ʮ\xc2\xc4\xc1\xbc\xc4ٲ̷\xc4\xc6ú\u0379\xd7Ȝ\xc1\xc8\u07bb\xca\xde\xc7\xc9Ƽϻ\xc9\xcb\xc8\xc0\xcc\xda\xc7\xcb\xdb\xca\xccɿҾ\xcc\xce\xcb\xc4\xcf\xdd\xca\xce\xde\xce\xd0\xcc\xc8\xd3\xc1\xe0Ф\xcf\xd2\xce\xc8\xd6\xc9\xd1\xd3\xd0\xd1\xd2\xdc\xd2\xd4\xd1\xdeէ\xca\xd8\xcc\xd3\xd5\xd2\xcd\xd6\xde\xcc\xda\xce\xd5\xd7\xd4\xe7\u05eb\xd6\xd8\xd5\xd1\xd9\xe1\xd5\xdb\xd1\xd8\xda\xd6\xd8\xd9\xe3\xd3\xdc\xe4\xda\xdc\xd9\xe6ݯ\xd5\xdf\xda\xdc\xdf\xdb\xd7\xe1\xdc\xde\xe0\xdd\xf0\xe0\xb3\xdc\xe1\xe4\xdf\xe1\xde\xe1\xe3\xe0\xe3\xe5\xe1\xe1\xe6\xe8\xe4\xe6\xe3\xe8\xe5\xea\xe5\xe7\xe4\xe6\xe8\xe5\xe4\xe9\xec\xe7\xe9\xe6\xef\xf2\xee\xf7\xf9\xf6\xfe\xff\xfc\xbd\bi5\x00\x00 \x00IDATx^\xed\x9d\x0fp\x13\u05fd\xef\xe1%\xb7\xf7\xf8Y\xba\xbdvjW&\xbevs=n\xb1\xc7\xf6\x98\xa8@\x84\xc3s\x80\x90\xe0\x10\xee\x03'J\xe19\xaf\xb9\x81\xa4\x80\xfb\x9cb\x87ۄ\xbf\xc1m\xd0\x00Uq\xc1<BL\x9d\xa7)\xc5@\xf0\xad\x15p\x9c8&\xb8Ԏi\xeb\xe4\xc6!\xb85\x93\xb9Q\xe2LP:\xb7ʄ\x99e2\xe2ܛy{ή\xa4]\xedY\xadd죕\xfc\xfb\f#\xfdt\xf6\xecٳF\xdf=\u007fvu\xbe3\xbe\x9a8\x18\x00\x80\xa9f\x86\x91\x0ec`T6\x00\x007\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00LM\nI\xb4\xb1\x91\x15\x02@z\xc3]\xa2C.\x8f\x14\xf8\xda\xdd\x1d\xbePjװ^\xfe0\u007f*y\x8e\x11\x12\x1e)))9\x81O\x88\xaf\x8fhw3\xe0\xc3Ғ\xfb5\x89\u007f}zn\xf9?\ai\xf8\xda\xdcW4\x9b\xd50K`\xd0(֯\xfcJ\xe8\x93\xe2\x10\n\x8c\x8f6\xf5$R\a\xf6Y\x18\x92\xc8!\x00\xde\x12\r\xecy\xb5\x85\x06c\xfb\xbc\x97\xbc\xfbƤ\xd4q\xd7\x1b1\xf6\x91x\xaa\xfc*#$\\\xd9Z\U000a6005s%[\xaf\xe0\x84y\xab\xb1\\\x93\xb6f\xee\xd1\xc6\xf2\xcfix\xb6\xfce\xcd\xe6(X%0\xf8\xf8ܹ\xa3%\xbf\v}R\x1cBA\x1cG\x9br\x12\xa9\x03\xfb,\x98\xbcy1\x12'r\b\x80\xb7D=\xa7ǨD\x83\a^\x15__=@/\xc1\xbeVc\x89^)\xdd\xca\b%\x0e\x97\b\xe2k\xb0\xe40\x9e\x00{5\x02\xfb\\,((\xc8\x1f\xe2h#\xb4%\xe8\xf0VX\xa2\xaaC(\x88\xe3hSN\xfcu\xd0;\v\x16+7(>\xc4\u007f\b\x80\xb7D\x87\xdc\x01\x1f\x95\xe8\xf0\x1e\xf2_\x1b\xd8C:\xb8]\xae\xae}\x86\x12m\x8c\xb4\x9c\x8d\xeaFt\xd2%z\xa5$\xb1~\xd8\x04$\x9a\xe8!\xccI\"g\xa1\x92(\x90\x00|%\x1a\xd87\x82%\x89\x9e>F\x13\x8eu\x8a/B\x00\xb7\x18I\xf4\xc3\xd2g\x19\xa1\x8cR\xa2\xe7\x1e]P:\xf7\x9f\x17\xd0\xf4\x13\x8f\x94\u07fbU\xdc\xf4viI\xc9\xf3W\x9e\xba\xbb\xfc\xfb\xea\xcb\xf7է\xe6\xcf\xd9 wSCy\x85\xb9%\x14\xd2P\u007f^^RRz\x82l\xfdqI\xe9K[\xef-\u007f\xf4cU^u\t\x11Xu \xc8\x12U\x1eB\x01\xf3hd\x84\xbd\x17北m\x9d\x13\xd2;\x9aDpn\xe9O\x16\xcc\u007f\xf3\xd99k\x02\xe2\xdf\u007f\xc3\xfc\xd2\x05O\xbc-\x1d\xe2p\xe3\x82;\x9f\xb8\xa2\n\xf5\xce\xf8\xafO\xcd]\xb0u\xeb\xdc9'\x14\x05+\xce\xe2\xc7d\x1fiL\xae\xfeC]\xd90W\xac\xdaU\xfc\x8a\x94\xb5d\xa5\xea\x10\"GW\x96\xaf<\x1a}4@\x05_\x89zNbY\xa2m\xaf҄\xee6i\x83\xa1D\x1bK?f\x842\n\x89^,}\xea\xe5\xd7^\x9a[\x12\xa4\x19\x9f={x\xee\xca \x16N\x9cXp\xef\x9c\x05[\x9f*\xfd\x10\v\x1fJ\x88{\\\x99s\xefK\xaf<ZR\x8e\x95y\xf1\xdb\xe7N\x94\xec=w\x8e6\xd4\x17ϝ+\xdfK\x82?\x9d(-\x99\xbb\xf7\xf0\x9c\r\xea\xbc\xca\x12\"0\xeb@\b\xb5\xa2\x8aC(\xaa\xc3<\x9apn\xce\xf3W\xf1\xd5\xe7\xe7\x9c\x13tNH\xf7h2o\xce)ٺ\xa6d\xee\xcf\xe6\x8a\u007f\x9d\xb3%\x8do\x9ex\xa2\xf4-\xe9\x10\v~\xb6wA\xf9{\xcaP猅\xfb\xe7\x1f}\xbe\xbc\xfc\xa5GUݔ\xc8Y\\=W\xbaW\x1e\x93\xab\xfePo\xceY\xf9\x8b\xd7\xf6\x8a\xff-\x81ߝ\xbbw\u0379s\xe7\xe8\\A\xf8\x10\xa4?\xf4\xfc\xd9\xe7˟\x8a\xda\rP\xc1U\xa2\xc3\xee@H\xa2\xb2&ߐ\xe6\x8e\f%\xfaa\xe9ӌ0\x84B\xa2G\xe7\x92\xef\xe7\xd19A\xf2}\xfc\x15&\xb2\xa0W\xec\x95%\xb4\x15\xc1x\x8d|A\u007f\x04\xe3G\xee\x15w\v\xae$\x02S\xe5U\xf5\xdfBߦ\xf29\xe2\x85᩹꼊\x12\x14\xe8Ձ\xd5\xd1UT\x87\x1eEs4\xdcH\xbe\xb6?$w\x99\xd8'\xa4{\xb4\x10\xf3\x9f\x127\xbcBoT\t'\xc8\x1fj\xe5\x13\xf4\x10w\x8b;\u007f\xbe\xe0!uȬÉ\x12\xb1\xe1=Z\xf2\x1e\x8e\"\xf2\x87\xa2\xfbH\x1d\xfe\xc8n\u0082\xef\x93n\xc9\t:\x9f\xa4\xea\xe8ʇx\xad\xe45\xfazV\xb5\x1b\xa0\x86\xa7D\x03\xfb\x86\x83\xc1\xe0XKP\xfc6\xb5yiRW\x9c\xad\xe8\x8f\xc5\xe6B\x1b\x86PH\xf4\xe3\xf9w\xff\xf8\xa5\xb7\xe9\x1cƆ\xbb\x05\xf1p\xc1\x05\xf4\x1e\xea\xcary\xaf+\xafH\\\xc1\x9f\x97\xbcD\x12\x9e/\x8f\xce˖(ٴW\x9dWY\x82\x02\xbd:\xb0$\x1a\xa9\x0eE{4\xfcf\xb9\x80\x85\xf2sх\x85OH\xf7h!\xe6\x9f\x10\x0f\x1c\xc0\xcf\xfdP\x8c\xffz\xf4\xfbwϡ\xfdM\\No\\\x1d-\xf9\\\x15bV\x1d\x9e\x9b\x83I\x95\xff\x15G\xc1\x96hx\xb7\xb3D\xd9!X\x12m\x94\xeeV\xddߨ\xda\rP\xc3S\xa2\xa3\xae\x10>|Z\xba;\xda\xde)m2\x90\xe8\xd5\xf2FF\x18F\xfar\t%G\xc5\xd7\xcf_\xdap\u007f\xc9\xdc_`\xd2\xceH\xd06c\xe5J\xcd^\x17K\xc8\xf7^\xfaZ\xa8\xf2\xb2%\x1a\xfe\x12F\xf2*KP\xa2S\x878\xa6\x8b\xb4G\x13\a\x93/\xe3\x97iK\xa9sBzG\v1\xff5\xfcV)\xa6\x12}k\xee\x82\xe7^>\xb7fe\xe4P\xe7J.\xaaB̪\xc3\xe1ҿ\x92\xc6.\xceV4\xb2[\x89bT̒\xe8#RE\x9fxH]\x02\xa0\x82\xa7D\x83~\u0090\xdb\xef\x0f\xe2a\x97ط\xc2\x01\x97\xfcȂ\x81D\x9f-\xbd\xc2\b\xc3H_.*\x98\x8b\xa4A\xf8\xfcD\xf9Q\xb1\xd7t\xf7E\xca_I\x16Ƅ\xe2_\xa9\xa41\x9d\xecQ\xe55\x90h$\xaf\xb2\x04\x05zu\x98\x98D\xf1\xb3O\xe0'\xe8\x04\x19\xfb\x84t\x8f\x16\x82H\xb4\\\x92\xe8\xfd\x0f\xd1\xc6V\x92(-\xf3%\xb1}U\x86\x98U\x87\x0fK\xbf\xff\xe1\xdb\xf7>\xa2\xb9U\x12%\xd1\xe7\xa3$\xfa\x9a\xa6\x15}\xe9CEv\xf1\x0fw7}\xbb\xbb\x11\xab\xcf\x18P\xc2S\xa2\x12>\xf9\xbeh\x97\xf8\xday@\xfeo\x8f-Q\x83F\x14\a\xee$\x89\x8dw\x8a_\xb1\xbdtx\x83\xd7<M\xbe!tL\xf6\xfc\xcf\xc8+k\xce\xff\xa1\x05b\xe3{\xa5\\\xfa6)\xf2\x1aHT\x91WQ\x82\x02\xbd:LP\xa2o\x95_-\u007f\x8b\x04\xec\x13\xd2=Z\b\x85D\x17\x90\x9d\x82R\x03\\>W\x94k\xe0\xee5\xea\x10\xb3\xeap\xb1dnIɚ\xa8;]X%Q\xf1:\x11|(J\xa2\xc2\xfc5\xe4\x8a\xf0,\xbd\x00\xac\x11K\xbf\x1a\x1a%ˇ8+MSKcQ\x90\xa8\x0e\xbc%\x1a\xf4\r\xb9}~1\x18\xdb\xd3y\xa9Kz\xbaH\xf0\xf9ܝ\xbeq\xfd\x9d\xb6FZέ\x8cF\x94\xfc/?}\xf6i\xfa\xff\xbd\xb7d\xce\xf3g_n,yS\x8c\x9f+\xfd\xe1\xcb\xff\xda(&\aߢ\x13\x8a\xd1c\xd8\xf7\xca\x17\xec}\xfe\xce\xd2\xd2_\xbd\xa7\xc8+OT\xbeE\xae\x1d\xc2\xefΝ+o<w.@\xe6,\x1b\xdf\xc2\x17\x1bK\xc9\x04f$\xaf\xb2\x84\b\xcc:HO\x17\x1d\xa6\xb5P\x1cB\x81\xce\xd1pp\xfe\xa3\xf3\xa5\xac\xcc\x13b\x1f-\xc2{w\x1e\x16N\x94\xbe'\xfcp\xcd\xc7b\xde\rG\u007f\xb6R\xec\x15\x8b\x92//Yy\xe2\xa5{\xe7\x90?g$d\xd7\xe1\xed\xf2\xd7Ξ\xbb\x1a݈*\xcf⑹\xbf\xf8\xd9C%\xe2\xdfAU\xf57\xcb\xef?z\xf6Yi\xc0\xbe\xb7\xfc\xf0\xcbk\xca?V\x1eBl\xf6K\x9f;\xfb\\\xe9S8\xea\x8c\x01%\xbc%\xea#C\xd1\x034\xea\xd8\xd7.=\xa3\xdb'\rP\x03z\xfb\\%\xd3\xf2\x9aP\xc5ٕ\xe5+ɵ\x18\x9fxd\xef\x82\xd2\xf9kޤ\xa9\xaf\xad\x99;瑳\xd2mD\xcd\x10M\xe4\xca\x13w\u07bd\xf5W\xa5%O+\xf2\nsh^z%\xb8(\xed'~Ǟ&I\uf54b\xafʼ\xea\x12\xc20\xeb@\x9f\xd1%lP\x1dB\x81\xde\xd1\xf0\xe1\xf2\xd0\xcd\x0e\xd6\t\xb1\x8f\x16&(6\x80'攔\x9f ك\x87\xef-\x9f\xbb\xe1\xa5{K\xc5&\xad|k\xe3\x9c\xf9OQEDBv\x1d~GSK\x1fQ]\x88TgqeM\xf9\x9cG\u007f\"\xe6UW\xfdʆ\x05s\x1e\x92\x1e\xf6\x13\x9e\xbd\xb3|\xcd[\xaaC\x88\x95;L\ue2ca\"\x8f:c@\x01o\x89N\x84\x9f\x94\xfc\x89\x11\x027G\xa8?\xab\x0eY\\\x9d\xf3\xf4\xd5`\xf0\xf3\x8b\x1b\xee\x8c\xefq\\`RI\x05\x89¯Ц\x82\xf8%\xfa\xf2\x1c\xa9\x8f\x1b\x9c\xabj\x9f\x01>\xa4\x82D\x81\xa9 ~\x89^,\x95z\xb8\xef\x95*fh\x01^\x80D\xa7'\xd2\xfcLt\xc8&\xd8X\xdex\xe2\xcd\x13\x8d\xac\xc9t`\xca\x01\x89NO\xe8\xfċѡ\x1e\xaf<:\xbft\xfe\xf7\xa1\x9b\x9b\x14@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2)\x87\xe67a@Z\x03\x12M-|\xce<\xb4\xc4(\x13\x90N\x80DٴW\xfa\x8d\xb2ă\xbf\xb2\xdd(KB\x04\x8b\x8b]\xa7njr\x01\xe9\x04w\x892\f#\x02\xde\xd6}\xed\x031\x97L\xfer\xd7\xf2E\x9bn\xc4\xca1A\x965K\xef\x9dUy\x96\x02\xe7h(y\vj\xd2\xdb#1\xb6dl1ʒ\b\x03\xa8\xc3(\v\x90f\xf0\x96(\xc30\"\xe0n\x1f\x1a\xeds\xb7\xc5\xd2h\xfd\x83\xc7w.\xba\x16#\x83H0H\x16\xd7\x12\f\x87j\x9d\xfd\x91\xf8\r\xb4\x9e\xbe\xf7\xa2J\xf7IWQ\x9el2Ӝ\xe1f\xec8!<\x99\xcdFY\x12\xe0\r\xe45\xca\x02\xa4\x19\xbc%\xca0\x8c\xe8l%\xaa\xf2\xef\xeb\xd3\xdf\xeb\x9a\xe38\xbea\xa0\xd0w*\x8a\x8b\x17\xce..^\xab\xfb\xd3p\x99\x8a\x9ap\xe8͗%\xfa\x02:)\xbe\xfa\x90\x8b~\xbadY\xcf\xdaqb4X'\xb1cڋz\x8c\xb2\x00i\x06g\x89\xb2\f#\xdaZ\xe9\xa6N\x8f\xfen\x1f9^\xd7\xdf(!X\x90\xdd>3\xdb^1\xa3\xc1\xc0e\xa4lY(Z\x86\x1eȖ\xc5H\x97e\xe9C\xdd\xf4\x83s\x96\x91\xcc\x13 0\xcbi\x94%~@\xa2\xd3\x0f\xbe\x12e\x1aF\xf8\xa4V\xa6\xfb\x05\x9d\x9d\xae/wPvc\xbc\xcb\xe18\x83?\xadv\xac&a\xf5\xa9ݫ\x17m\xfa\x8c\xe6\xf9\xf4\x99\xe5\xffm\xf3W_\r\xff\xe7W\xffu\xcb=\xd2D\xcf@&B\r#\xab\n\xb2\xaa\x88d\x9b˲\xcbH\x8fӃ$\xcaH\x96q\x1f\xce\r\xb7\x97A\u007fGA\x19U\xb7\x90\xf3$\xa3\x84\x10\x8a\xd4:\x94тG-\xa8\x18\xe3:dq\xad-ʮ\x92Υ\xa52\xbb(ܚ7dE]3\x12.!B\x17Ht\xda\xc1W\xa2\xba\x86\x11\xa4\xe7\xab;\xcaz\u007f\xf0\x8c\xe3\xd0\xe0\xe0_0\xfel\xb0\xfa\x10\xbe\xf1\x87]\xd5\x18_>S\xedx\xf0\xd0\xff[\xfa\f\xc91\xb8xݡ\u007f\x981cF\xb0fƌ[\x9a\xa4o\xb6\xd0z\xa0\xa0('\u007f\xed\n$~\xe9\x9d\xd6\x06O\x83u\x95x\x91\xe8\xf6\x16ٽ^o\xc8\xcf4,\xd1\v\xa2n\xbfq\x89\x86\xfd\xa8K[B\x18E\xaa\xcfki¸\xc7i\x15{\x05\a2\x91\xadi{\xce}$\x8b3\xa3\xce\xd3l+\x93G\xc5\xddѲJ\xb8\x84\xd0~\xe3]\x15\xb9\x93ؾ\x03)\x01W\x89\xea\x1bF\x88_dw\x8c\xbb\x1c\x91\x8e\xae(Q\x8c\x0fU\xd3p\xa9\u0602n{P\x8c\xae\xd7n\xba\x1e\xf4\xfd\xef\u007f\x10%\xfa7K\xb6\xbc\x13n\xb4\xcaм\x005U\xe8\xa0\x13\xa1\x1d\x886ݑ\x8e.VH4\xd8۵=?\x8fjԃ.iJP\x11I\xb5\x92\x89\xdf&+I\xb4\xe6\x8aB^e\xa3\xfb\x93ɦ^tP\xca=\x86\xb4\xfd\x83\xc4J\x90Y\"^Eb\x8c\x06\x80\xf4\x84\xa7Dc\x18F\xe0\x1eW\xf8\x86\a\x03\xb6Dw\x86\xc2\xf3\x8e\xf7E\x8d\x05\\\xa2D3\xfb\xfd\x91neYh\xa6\xc6YLߊ騐-QB \xbf\x8a\xbc\xb5\xa1p]ʘs=\x91T\xa5\xc0\x9c\xa1\xf0\x81B\x81\x90/\x8fAǢ\x94\x96x\t2c\x1d\xaebhE\xa7\x1d<%\xaao\x18!t\x86\x96\xa5gÖh8<\xee\xb8N\x12Z\x89DG\x14\x03\xbf\xb2\n9\xa8\xbc\x87\xbe-\xac\xa4\xa9\f\x89ʺn\xca$\xef=\x91\x9ei\xb8\x04\x15\x91T\xa5\xc0\xc2a\x99<ޕ\x9f\x02\xea\x95'\xa1&^B\x04/\xea\x8dN\x02\xd2\x1c\x9e\x12\xd55\x8c\bxZ|1\xf7\x8c\x92\xe8\xfe(\x89\x9ew\xbcK\x12\xb4\x12\r\x89\xd1YH\xdf\n#\xad\xe8>\xb9\x15\x93$*\xe4J9\x9b\xe8\xccN\xc0\x1a~nA%\xe70\x91T\x9a\xb3!J`+\n\xfb)rϽɢm\xf9\x12+!\x02\xcc\xe8N?xJTBk\x18\xe1?xD\xfc\x12\xc7rd\x8fHt\xd1~\x8co\xd4GI\xf4ڃ\xf5\xa4\x19\xfd\x9f\xba\x12\xf5о\xe6Ai$g\xb7c<\x8e\xa4;=\xa1V4\xaf\x8a\xbc\x06\xf2\xa5f\xab\xe6\x8e\xd0<\x8d\x91D\xb3\x9f\x14+^\x11%\xb0\x0e\xa9\xf0\x8d\x9bi\x96`\xf1\u009b,A\x01Ht\xfa\xc1[\xa2\fÈ\xb1}\aG}>_w\xab\xde>Ҍ\xee\x1f\xe8\xf3\u007f\xf5\x0f\xfe\xf2\xd0:G\xf5\xa9\xcb\u007f\x19\xac\xde\xf5\x87\x1b\xef\xef\xaa&3\xbd\x83\x8bV\x1f?\xbf\xfb\x1fU\x12\x15z\xe8ܭ4\xac\\\x91\xb1\u07b3>c\x05\x8d\x9b\xac\xdb\xdb\xe6e\x93#\x8f{\xbdߨ\xf1\xf6\x88zlAU\xae\x93\xcd\xf9\xf2\xd3E\xefdlה\x10F\x95Zi۲\xb9\x12e\xba\x87}^\x8b\xb3\a\xf7;-^\xb1\x88\xf5\xe8\x81\xd6v'\x92\xa6\xc2v \xc5\xd3L\x13*AA\x1f\xa3\xd3\f\xa47\xbc%\xca0\x8c8&\x0fP\xf5&+\xaf/\xa5\xb7E\xab? \x1f>\xaa_\xb4x\xd3~\x87c\xd7.\x92\xf4\xfeb\xf1u\x97\x98\xfc\xc13\xb5\x8b\xd7\xfd\x1f\x95D\a2\xe8pNj\u0082ͳ\xb3g7Km\xa3P\x97\x9be\xa7C\xba\x06\x9a#sD\f{\x96\xe4[\x8b\x1f\vu,\x1b\xbe\xde\x1d]B\x18U\xea\x88=+\xa7j#Buub\x92e([|\xad\x13\x93;\xec\xb6\\\xbbt\xe7כ\xf5$\x8e\"\xc1\x12\x94\x8cg.\x1b\x187|\xc4\x11H'xKt*ьE'\xcec\x16\xdd6=1\x0eZ\x9c\x93R\xa1\x10mŌI$ \x9d\x01\x89\xb2ّ\x1fé-~\xfc\xb3&\xf5\x87.\x84\xf1\x81\xd8Sk@\x9a\x91\x02\x12u\xc4\xcb?N\xa2D\x01\xc0$\x80D\x01\xc0Ԥ\x80D\xe3f2;\xba\x00`\x12@\xa2\x00`j\xd2G\xa2B\xf32\xf2\x18\xfd\xfan\xd0(\x90N\xa4\x8dD\x83\x95\xa1\x1f\xa3\x1d\x01\x8d\x02iD\xdaHT\xb8u\xf3W_\xfd\xe7W_\xfd\u05edK\xe0\xc7 @\x1a\x916\x12\r d\xb7ߚg\xaf\x98᜔\xe55\x01\xc0\x1c\xa4\x8dD\x05o~n\xee\x1d\xb9\xb9\xb9\xf3ހ\x8e.\x90F\xa4\x8dD\xb1\xe0\xbbt\xe9\xd2\xe8\xa5Kc\xd0\xcf\x05҉\xf4\x91h\xdc\xeb\xe8\x02@*\x91F\x12Mab\xd8SL\xb6\xe5\x04\x90jp\x97(\xc30\xc2\xd7q`Ok\xf74\xee\x9fF\xec)\x18\xfe\x15\x93l9\x01\xa4\x1a\xbc%\xca0\x8c\x18wy\x86dž\x8f\x1c\x98|\x8dθ\x19\x8c\n\x9f<\"\xf6\x14L\xff\x8aɵ\x9c\x00R\r\xde\x12e\x18F\\rQg\x97\xd8\v\x8cM\x88\x19_L\x1c~\x12\x8d\xd8S\xe8\xf8WL\xaa\xe5\x04\x90jp\x96(\xcb0BZ\xa6\xd6\xef\x9a\xfc\x9fA\xa6\x86D\xc3\xf6\x14z\xfe\x15\x93j9\x01\xa4\x1a|%\xca4\x8c \bc\xad\x9eɟ\x8a\xbdI\x89֡\xcc\xe6\xef\xe5\xe7\xde3\xa2)\u061dG۷\xb1\x1cy1\xcd\x1ce3\x97\xa0\x1fDȞB\u05ff\x82a9\x01L#\xf8JT\xc70\xc2\xefr\xb9ܓ?\x14\xbd9\x89\x06\xa9\x85C\xc1概\xec\xa1肗\xa0*\xf2&\xb8\x9b%\xdcJ\t%\xe8\a\x11\xb2\xa7\xa0\xb0\xfc+\x18\x96\x13\xc04\x82\xabDu\r#\xfc\xbe\xa1֩\x98.2\x92!\xfd\xa7\xb3\x8d,\xebi-\b\x90\xa5;+\xa3\v\x1e\xdd,\xa9g|T\"z\x11\x95D\xfc \x14\xf6\x14l\xff\n\xb6\xe5\x040]\xe0)\xd1X\x86\x11b\xdbsRwljB\xf4\xf7\xe27\xf5\x85\x1aS\xa2d\xfcg\xddH\x8aiF:w-GQ\x88\xa8\x85<\x13\xf1\x83hS\xee\xcc\xf2\xaf`[N\x00\xd3\x05\x9e\x12\xd51\x8c\x90\x9f\a\x1apM\xfa`\x94\xe8\xef\xf6\x17'(Q\xb2Ξ\xb4,}\x97f%\xdc\x10^\x8fD\xb4\xa9[\"~\x10=\xca^,˿\x82m9\x01L\x17xJ\x94m\x18\x11l\x91\xa6\x8c.\xec\x9b\x12\x89\xaaT\xf8\xf3\xdbf~\xed_\xbe\xf8\xe2\xb7߹\xf5\x96\xef\xfc9,џ\xff\xfd̿\xfd_$\xe3\x0f\xbe6\x93l\x9by\xdbO\xc5\x0f\xa4\xe5\xb4>F\x8aq\xa1D\xfb\xe0\x89\xf8A(\xec)\xd8\xfe\x15l\xcb\t`\xba\xc0S\xa2\x12\x1aÈ\x03\xc4XP\xec螎\xb9\xdbD\x88\x96\xe8\xcf\xff\xe6\xe7\x9f\xfc\xf6\xbb_|\xf1w/~\xf2\xef\xff\xe3\xbb!\x89\xfe\xfa\xef~\xfd\xc9o\xbf%jt\xc6\xed\xbf\xff\xe2\x8b\xdb~\xf0\xe7\xff\xf8\xf5\xb7\xc5\x0fĬ\xc1\x9aG\x86\x94\x85\xf6\xe8\x82G\xb7(Ə\f\x12\xf2\x83\x88\xd8S\xe8\xf8W0-'\x80\xe9\x02o\x892\f#\xdeq\x9d\x1c\x1e\x1b\x9e\xba颈D\xbf\xf9\xd3H\x83\xfa\xef_\vI\xf4\xf6߈\x1f\u007f\xff\xb7bL\x82[~/m\x9fA\xae$VTֺ\xe7\x8e\\\x8d\x1e\xe5\x19]6\x89\xfaA\xc8\xf6\x14\xfa\xfe\x15Z\xcb\t`\x1a\xc1[\xa2\f\xc3\b\xec\xebl\xdd\xd7\xd63\x05\xb7\xfe\xa2%:\xf3\xcf\xd2\xfb\xef\xbf}\xeb\x8c\x193C\x12\xbdu\xa6\b\xfd\xf8\x1f\xe2\xb6\u007f\xba\xf5\xbb\xffBTJ\x1f]\xb0\xaeu\xe6\xccZ\xa5}\xa6\xc2msi\xd2\xc2$\xec\a!\xd9S\xe8\xfaW0,'\x80i\x04o\x89r%Z\xa2\xb7\xca\x12\xbd\xfd\x9f~\xff\xc5'3B\x12\x9d)\xb7\x9br\xc6\xdf\xfc\xe0;\xb7\xfc $Q\xc50q\n\x89iO1ٖ\x13@\x8a1\xad$z\xbb\xdcѽ\xe5\x93/\xbex1,\xd1o\xfeH%Q\x91\xdf\xde\xc2W\xa2\xb1\xec)\xa6\xc0r\x02H)\xa6\x95D_\xfc\x9a4]t\xdb\x0f>\xf9\xcd\u007f\x0fK\xf4\xc5[\xff\xe5ϟ\xbc\xf8-9\xe3\xb7\xfe\xef'\x9f\xfc\xe86\xce\x12\x05\x00]\xd2^\xa2\xf4\x87e!\x8d\xfe\xf4\xef\xe9M\x97\xdf\xdc6\xf3k?\nK\xf4\x8b\x17o\xbfe\xe6\xed/\xca\x12\xfd\xf9\xed3o\xfd\xf6o\xa9D\xa5\x19\x1e\x00H*i/щB\x1f\xa3G\xc8\x12\xf5\xdc\x10\x00p\x06$\xaa\x03\xbf\x1f\xa3\x01@,@\xa2:\x80D\x01s\x00\x12\xd5\x01$\n\x98\x03\x90\xa8\x0e Q\xc0\x1c\xa4\xb7Do\x06\xa3\xc2\x01\x80\vi-Q\x00H}@\xa2\x80̤\xff\x16\x10\x98\x14@\xa2\x00\xc1\xe7̓~a\x0e\x98\r\x90(\x80\xc9OR\x8b]\xa7a\xb5^S\xc2]\xa2\f\xc3\be*gN\xda\xc2\xc7\xf5\xd7\xe5eUMVg\xefU[_\x9c\xa9\xfey\xb9[\xb4\xe1d\x10\u007f\x1d0\x1e@\x1d\x8cT\xc0\f\xf0\x96(\xc30B\x99\xca\x1bOvxm\xbdyy.gV<?+\xf7őɅX?(e\xa5>Y\xb8%ï\t\xe3$\x10ky\xf0\xf8\xeb@\x9c*\xa2\x97_\x02\xcc\x02o\x892\f#\x14\xa9\xfc\t7\x9b~Ԍ\x83q\x88O\xd4r\xae\xf1Bh/0\x97\xd5d\xa5Vl\xc6\xd9^M\x18\x17AW\xee\xbc\x18\x9b\xe3\xaf\x03Y\xc0\f~/`V8K\x94i\x18\x11IM\"#(ޮ\xf6\xd8\x12T1`\x90\xa7\x13uƙ:\xdb=\x86F4a<\fT\xa0{b\r\x1f\xe3\xaf\x03H\xd4\xcc\xf0\x95(\xdb0\"\x92ʗ@\x16B\x19t\x91\x16\xc1&\xad\x9a\xb9V\xb5\xfdr\xb5ñ\xff\xa3m\x0f/\xda\xf4\xa5z\xc7c\xf9\x19\xd4\xed\x81m\x18A\xe8C}\xf4=\xb0l\x96%\xff\x9e\x90\xa0C\xa9J\xaa\x1a\x96\xcc\x1e\xc8D\x99ê0\x8cn\x1d\x02k3\xf2\xc9EŸ\x0e\xc5r\x06\xbb*UM\x17HԴ\xf0\x95(\xdb0\"\x92ʙ>\xafW\xfe\xd1\xf6\x05\xefA\xd4\xe4\xf5\xaa\x87v\xd7Ϝ\xa9]\xbd\xb8v\xf7\xb6\xbb>\x8d\xda1\xb0>3\uf21ea\x04\xc1g\x93\x8a\xf2\xa0\xefu\xb5ޓѫNU\xb29\xc7\xda'T\xd9ɢb\x8a0\x8c^\x1d\xda\xf22\xd7\xd3n\xb9q\x1d\xacN\xaf\xd7\xdbU\x89\xb6\xa8R\x15\b\xe3]\x15\xb9q\xf5\xf1\x81$\xc0U\xa2l\xc3\bE*\u007f\xb2B\xeb*\xb0;\xba\x8f;\xea\xaf\xe1\x1b״\x1b\x86\xca\xd0c\xfa\x86\x11a\x02\xad\xe4\xab?;\xc6\x1d\xc7-ȅ\x03\xd9ǢB%\xac:ԡ\xb2\x90ьa\x1d\x9a\xfa\xc5a\xab\x13雔.\x11\x9b\xd8x{\xf9\x00wxJ\x94m\x18\xa1L发D\xab\xa3\x1bP\x19wn\x96K\xdf0\"\x82\xbf\xb9\xaa0\a\xcd\xd6ی[Q\xeeZ\xbcc\x96\xa0\x0eU\xb0\xea\xe0\xb6\xe6ʶ\xc1q\xd4Al'\x97!7\xd6e\xac\xc3U\f\xad\xa8i\xe1)Q\xb6a\x842\x95?F\x12]\xc7H\x14\xdb\xd0J\xb4\x90(B\xcf0\"Lo^\xfe\x93m^\xbb\xaeDdz\xd7v~}\xb4\xb0I\x1d\xaaa\xd6\xe1R\x15\xaa\x94\xdaQ\xc3:\x88\n\xad\xb2\x1c\xd1\xdfJ\xf0\xa2\xde\xd8\x19\x80\xa4\xc1S\xa2:\x86\x11\x8aT\xfe\x18I\xf4\x19F\xa28\x12͏\xb3cX\\INs\x99\xaeD\xdbŶツ\x9c\x80:Tì\x03\x1d\x8d>\x19_\xd3\x17\xb0[5\xbd\xe7(`F\u05fc\U00014a04\xc60B\x91ʟ\tH\xb43?^m`\x9cO\x9c#\x82e\xba\x12mC#\xf8\x02Z\x81\x83\x05\x97\x14\xa1:\x8f\x8eDɜ\xee\xacx\xdc\xe4\xfc\x15\xf4n\xabGc{\xa1\x00$j^xK\x94a\x18\xa1L\xe5\x8a\xd0\xe3\xf5\x92\xe9\xce@hF\xb7Gݎ\u007f\xf9\xc7\xc1\xd5\xf5\x83\x83\xd1#\xc1ev\x8d%\xb0.MhY\xf3\xe62dۢ\xa3\x80\xf1욶\x82\"K\xddf\x8b_\x11*2\xe8\xd4AbȾ\f\x1b\x12(F[\xbc\"Nk\x8cL}\xe0\xbdfZxK\x94e\x18\xa1L\xe5\xc9\x1b\x92\xb3\x03ra!\x97\x06\xaa;\x92\x18_vP6\xe9\xec\x1e\x0f\xc1\x1dEV\xdb\x03\xee;,zM\xd8\xe9;lu\x81\x93E\xb9ͪ0\xc2\xcd\xd7\xe1B\xa6<\x9dT\x10#\xd3x沁\xf1d\f4\x00CxK\x140'm\xc5\b~\x8cfN@\xa2\x80\xc4\xf8@2f\xd4\x01C@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00\a\\\xd9\r\xe2kO.\xf7_3\xa5\x01 є\xa0\xbd\xd2\xcf\b͈\xbf\xb2]\x9b\x18\xc8^\x8b\xc60\xbeϦY\xf5\x85\x01\xb3\x84i\fw\x89j\r#\x047]\x16E\xb3\x82\x1d\x10f\vjb\x84\xf1\x93\x88w\xc4Ͳ%C\xebzџ)\xccj\xc7㖍Q\xe9\xa3+\xf2\xb3go\x96\u007f\x1f\xef\xb2\xe7\xe4o$?\x88c\x95\xa0\x0f\xcfsK\n\xbc%\xca0\x8c\b\xb8.\xf8DL\xdd6L\n\x9d\xfdF9th\xcep3\xc2\x04H\xc4;\x02\x1b\xac\xb6=\xf8n\xec\xedؓ\xa9Yl\xb0\xd7\x1a,h\x15\xaf.Q\xebI\x8c|c\xf6v\xcfƜ\xd9t\x8d\x9c\x85\x19u\xed\r\xa8U\xa7\x04)?+1\xa1sKExK\x94a\x18\x11pM\x13K\xae\x8a\x1a\xa3\x1cl.Y\xd63\xc2DH\xc4;b\b\xc5^Tb\x9d\xce:-\x11\x1a\xac\xd1\xff\xa1\xfe\xcc=h(X\x18mo\xb1\xa4\x80\xf4\x9c\x86\xb3I\xe3\xba\xc4\xdaM\xd6gi\xd6)\x81\xc0\xaeY\"疒p\x96(\xcb0b\xdaH\xb4,\x8eeLX8g\x05\x18a\"$\xe2\x1d\xd1c\xb0\x8c\x91\xdeRJ\x11\x02\xb3\x9c\xd1I\x8f\xa1\x85\xe2\xe1\xa2ǘ\xc5\xd2B\x10\xf7U\x90\xa3\xd2\xfe\xfb\x88\xb4\xf2\x03\xa3\x04\xacW\xb3D\xce-%\xe1+Q\xa6aD\xbaIt \x13\xa1\x86\x91U\x05YU\xe4*\xd4R\x99]D\xdc%<\xf2\xf2$ed\x9d\xea\x8c\x16<jAŪ\xbcu\xc8\xe2Z[\x94]\xa5\xf9c\b9OF\x87\xba6\x12:\xc4\xef_\xc1\x16\xc2\xe0\xa6\xda\xea\xe5\x9bjo\xe0ץuZ\x1ct\xdd\xd0\x1b\xa7\xd6-^\xbd\xfb:ƻ\x1c\xd5\xc7w\xd6.\xdd\xf4\x91\x9c\xbd!+z^!8,\xe0e\x9aɢnIF\xceB\xf1ob\t`\xc5fm\tXO\xa2\x89\x9c[J\xc2W\xa2LÈ\x80\xeb\xe4\v\xae\x03\u07b4\x99-\x12Z\x0f\x14\x14\xe5\xe4\xaf]A&1\x9d\x19u\x9ef[Y\x10\a\xba\xbdEv\xaf\xd7+v\x1b|^\x8b\xd8d\xf4\x90\xf5\xbe\x14y\x87\x0fd\"[\xd3\xf6\x9c\xfb\xa2\xcb\xebG]ѡ\x8e\x8d\x84 /L\xaf\xf9S\xc6\xed_\xe1\x1f\x1d=\x82\x8e\x8c\x8e\xaa'\x06\xfe\xed\xae\x9dgΟZ\xee\xf8\x12_\x1b\xa4\xab\x9d\r~@\x92w:v\x9f?\xfe\xe0\xe37\xf0\xe53Վ\xdaC\x87j\x17]\x96\xf2w\xb3\xb4\xa4\x9d,\x92\x11\xf2V\x89=\x8c\x8a=\xc5\x19y\xceВ\xfa\xda\x12\xd85\xc3\t\x9c[\xaa\xc2U\xa2lÈ\x80\xabe`l\xb8\xf5`\xdahT\xfc¡y\xe2\x99Ҷ\x93\xcc\xee\xf4\xa2\x8345\xdcѥN2MVu^l\xcd\x155\xbd\xca\x16]\x98'2ˢ\bY6\x12v\xb9\xa5\xd6]\x8e\xd3ȿBgi\xfb\xe3\x0f\x92\xc6\xfa\xf8\xd2\x1b\xe4C\xb8\xa3\xfb\xba\xe3\x94\xf8\xfa\xae\xe3\x8c\xf8Z\xfd\xb0X\x93k\xb5\xf2\xa2\xdcc\xac\x81\xa0f\xb2H&\xe8\xcc\x12/[\xf9\x19\xb6-\x1d\xcdy\xf9r?^S\x82\xf1\xa2\xfbF疲\xf0\x94(\xdb0\x02\a\x87\x888\x05w\x1a\xad\xe4Z\x16\x9a\xeex\xa0P \xe4ӡ\x95\x8eD\xc3S#Vg$UA[\xe4[\xa9\bY6\x12#\xf2\xc2\xf4\xfas\xb2\x06\xfe\x15\xc1N\x8f\xa7\t5y<\xea\x81ܧ\xb5\x0f\xef>\xf5\xfe\x8d\xeb\xf4CX\xa2\xdb\x1e\xbe\xfe\xa5H\xedN1\xae\xdeOR\x8e;\xa4KƘtIRS\xa8sᨣ\v\x18\x97Y\x89\x80Dz\xe5>\xbd\xa6\x04\x9d\x9a)1\xf2\xe6HUxJ\x94m\x18\x11\xc2ۦ\xb7_\xeaQV\x11\n\xe4K?\xbd\xb6\xebH4\x94W\x95\xaa@1\x04S\x84:V\x16\xb11\xf2\xaf \xb0F|\xd7N=\xb3ڱ\xfc\x97\xeaV\xf4qGd\x01\xd1\xeaC$e\xd0!ݐ\xe9e\xac\xca\xebEm\n\xc3\xe50\x81\x9aLz\x17\xa9\xa6\x98~\\V&%\xb3J0\x98Ȋ\xe7\xdcR\x12\x9e\x12e\x1bF\x84\xd4\xda\x19\xa7\aC*\x10\x16\xe3\x8a\xc2~\x8a?\x9cJo\x05S16X\xd5y\xf5$\x1a\xb061B\xe3\x89U\x06F\xfe\x15\x04\x86\x10\xde\xdd/\x8a\xf3ڙE\xc7\xc9\az\xe0S\x9f\x92V\xf4]\ni9\xabw\x93M\xa7\xe4V\xb4ɢ\x9dw\xae\xb1\t\xd8\x19\xa9\xbe\x8c\xaf,W\xeaN5\xe4\xd0q\xce\x12\xf9z\xc5*\xc1@\xa2\xf1\x9c[J\xc2S\xa2\x12\x1a\xc3\b\x0f\xb5\x04\xf2\xbb/\xc4\xdc-\xa5\bˮC\xba\x17\xbfq3y\xb5\x8b]\xbdq\x9a@\xfas\xc1\x8a8%\x8ak\xee\bj\xc3\tI\xd4ȿ\x82p)G3f<\xe48O\xde\xeaw\xd1\xd7z\x8c?#\x03\xd0\xf3t\x14\x8a\xf7\xffR|\xa9^NƢ\x0f\xd7\xd3\xec\xc1\xe2\x85\xd1%`\xbfe=\xeeGM\x19j\x8bŁYE\x97\x88\xbf)\xb9\xe7IN\xfe\x12}\x94\x97]\x02\xb3f\n\xe29\xb7\x94\x84\xb7D\x19\x86\x11c\xae\x8e\x91\xb1\xbe}\x9etY\f]\xe8\xa1s\xb7Ҩq=z\xa0\xb5݉\xe8e\xa9ɺ\xbdm^69\xe5J͕ۖ(\xd3=\xac\xc8\xeb\xf3Z\x9c=\xb8\xdfi\xf1F\xcfE\xbe\x93\xb1=*\x8ci#\x11\x03#\xff\n\x1d\x0e9\x16\x1fz\xfd\xf5\x9d\x8eA\xfa\xa1\xfa\xf8\xeb\xf5\x8bɡ\xf7ߵ팘J\xa7\x8b\x1c\xebΜZ\xbd\xf4\x03\x9a}\a\xd2>F\xb5\x1d\x8d\xe0\x03\x85A\xab\xea\xc0Dzfy\x88\x95E\xbe\x18o\xb44tl\xb7\x15\atK0b\x82\xe7f~xK\x94e\x181~\xf2\x80\xdb3\x94.\n\xc5\x03\x92\x0f\x85\xdc\x0et\xd8m\xb9v\xe9&\xb0P\x97\x9be\xa77\x05F\xecY9U\x1b\x11\xaaS\xe4\xad\x13\xdf-C\xd9\xe2k]t\x89\r_\xefV\x87\x13\xb5\x910\xf4\xaf`s\xaa\xfePm\xf5\x83\xf5T\xa1\xf8\xfa\ue94b\xea\xa51\xe7\xf9\xfa\xe5K\xebi\x03[\xbd{\xe7\xd2\xdam\u007f\xa1\xa9ެ\xf0}\xdc\bw\x88G\xf4Z<\xea\xf9\xd8\xd0\f4\xedݶ\xce\xce*j\b\xe8\x97`\xc4\x04\xcf\xcd\xfc\xf0\x96(0\x11\x1e\xb3\xb42B\x13!M\x17Q\x0eZ\x9c\xda\xdbg\xe3H\x1c\xcd\x04+\xd1\n\xcd\x16\x06\xcc\x12\xa6/ є`G\xfe8#4\x0f\x11\x89\xfag1\u007f\xa6Bo,\t\xef\xc4\xd3U\xd2)a\xda\x02\x12\x05&\x01E+\nL2 Q\xe0\xa6\xf9l\xb0z\xd7\x1fn\x18\xe5\x02&\x06H\x14\xb8iv9\x1c\x0e\xc6\xc3N\xc0\xa4\x00\x12\x05\x00S\x03\x12\x05\x00S\x03\x12\x05\x00S\x03\x12\x05\x00S\x03\x12\x05\x00S\x03\x12\x05\x00S\x03\x12\x05\x00S3\x9d%Z\x83l\xab\x86\x8d2\x01@r\x99\xce\x12\xf5u\xba\x8bm\x13Z\xf4\x12\x00\xb8\xc1]\xa2Z\xc3\b\x91\xe1c\xee\xd6>\xbd=\xa6\x92.4\x80\x01\xc0\xcc\xf0\x96(\xc30\x02\v']=\xa3\xfd\xaeX?\xa9\x9f*z\r\xd6u\x06\x80d\xc3[\xa2\f\xc3\b|z\x8fؚ\xfa]\xc9\x18\x16\x82D\x01\xb3\xc3Y\xa2,\xc3\b\x9f\x8b\xaeZ\x94\x94A!H\x140;|%\xca4\x8c\xe8\x11\xd5\x1a\xcfO}\xa7\x82\x81\xc8J\xef\x00`J\xf8J\x94i\x18\xd1\xee\x19ns\x1d\xe8N\xcaZ\x18\x82\xad\xb2{,Y\xd7\a\x00\x88\x03\xae\x12e\x1bF\xb4RÈ\x03\xadI\xd1\xe81\x84\xd0=F\x99\x00 y\U00014a0ea\x84g\x0f]\xf5\xda\xdd\x1b{\xef)!`+\xdcѩ\xe7\x12\x02\x00&\x80\xa7Du\f#\xba$\xa7\x88\xaeh\xf7I\x1e\xf4\xa2\x93FY\x00 \xa9\U00014a0eaD\xbf\x9b\x0e\x06O'\xc30\x02ft\x01\xb3\xc3S\xa2\x12\x1a\xc3\b?\xbd\xe9\x12\xd8\xd7\x17s\xb7\xa9\x01$\n\x98\x1d\xde\x12e\x18F\xe0\xbe=}cC-mɘ.2r\x8d\a\x80d\xc3[\xa2,\xc3\b|\xa9\xdd}\xa4\x8f\xbfB\x05_\u007f\x8d5m̜\x814\x85\xb7D\xcd\xc4\x12\x84\n\x921G\x05\x00\t0\x9d%\xea\xeb\x1f\xc3\x00`r\xa6\xb3D\x01 \x05\x00\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x022\xb0>\x8c9\x01\x89\x02\x04\x9f3\x0f-1\xca\x04$\x03\x90( \x12,.v\x9d\x86'\x96M\tw\x89j\f#\x84\x16y\xb5\x94\x031\xf7\x9b\x1aN\xda\xc2k=\xf8\xeb\xf2\xb2\xaa&\xab\xb3\xf7\xaa\xad/\x14n\xb7ng\xa4\x86\xf1\xcf\xcbݢ\r'\x83\xd0Ѿ\x87$\nU\xa9j\x06P\a#\x150\x03\xbc%\xaa5\x8c\x10\\\xfd>\x91>W2\xdcU<\xd9/\x84\xc2yy.gV<\xebm\xfb\xe2\xc8\xe4B\xaePXf\x99\xcdH\r\xf3d\xe1\x96\f\xbf&\x8c\x93@\xac_\xbb\x86\x8ef\xaf\xf0\x8a\x1c\x94\x17:d\xd5\x01\xe37\x90\x97\x91\n\x98\x01\xde\x12e\x18F\xd0\xe3\xf1\xd4\x00\x00\x0f\xb1IDAT\f\xd1U\x8cZ\xbac\xef8E\x84\x9bM?j\xc6\xc18\xc4'j9\xd7e\xd8ؾ\x80B\xd2\x0fd\xac\xc8\b\x15\x1bI\x8dP\xb1\x19g{5a\\\x04]\xb9\xf3bl\x0e\x1d\xad\x8a\x8e1\xabr\xc6T\xa9j`\x81\x18\xf3\xc2Y\xa2,\xc3\bʱ\x17\xf8\xaf\xba\xa0b\x04Ż\xbc\xd9\xd8\x12Ta\xd4\xe2w\xa2\xcep\xd4\x1f^\xf1>\x92\x1aa\xb6{\f\x8dh\xc2x\x18\xa8@\xf7\xc4\x1a>\x86\x8e6NZf7r\xabSՀD\xcd\v_\x892\r#\bîqݝ\xa6\x8c@\x16B\x19t\x04,ؤ\xe1\xdaZ\xd5\xf6\xcb\xd5\x0e\xc7\xfe\x8f\xb6=\xbchӗ\xea\x1d\x8f\xe5g\xac%-\xe3X\x8e<\xccˉ\x96J\x1fꓣ\xa6|\x9cߤI\x8dPհd\xf6@&\xca\x1cV\x85at\xeb\x10X\x9b\x91O.*\xf1ԁ\xe4\xaab\xa4F\xe8\x02\x89\x9a\x16\xbe\x12e\x1aF\x10ZO\xeb\xee3\x85\xf4y\xbdVI>\x17ıZ\x93\u05eb\x1e\xda]?s\xa6v\xf5\xe2\xda\xdd\xdb\xee\xfa4j\xc7\xc0\xfa̼#\xa2\xb2\xdd\xcd\x12\xee\xe8.\x80\xcf\x16*j^\r^fפF\u061cc\xed\x13\xaa\xec=AU\x18F\xaf\x0emy\x99\xebi\xff9\x9e:D\xba\xb9\xcc:\b\xe3]\x15\xb9q\xf5\xf1\x81$\xc0U\xa2l\xc3\bL\x16\xc1Nք\u007fV\xa8\x85cwt\x1fw\xd4_\xc37\xaei7\f\x95\xa1\xc7\xc4>䨄~\x17 \x98\xbd\x1d\xefȎ1v݂\\8\x90},*TªC\x1d*\x1b\x92C\xe3:(\xba\xb9L\x96\x88mp\xbc\xbd|\x80;<%\xaac\x18!r\xb25\xd6~S\x89\x91D\xab\xa3\x1bP\x19wn\x96\v\x8f\xa2\x10\xba\x9e\x13\x03\xa8[\xe8\x8ea\x05ފr\xd7\xe2\x1d\xb3\x04u\xa8\x82U\a\xb75W\x16]\x1cuPtsٛ;\\\xc5Њ\x9a\x16\x9e\x12\xd51\x8c\x10q\xf7\xc5\xd8mJ1\x92\xe8:F\xa2؆V\xa2\x85D\x11^\x8f\x84\xfe<l3UO\xb3\xde\xe6\xf1쵝_\x1f-lR\x87j\x98u\xb8T\x85*\xa5vԸ\x0e\x8an\xae\x1e^\x94\fG\x1d \x1exJT\xc70\x82\xacG\x9f4\xe7##\x89>\xc3H\x14G\xa2\xf9\xf1v\fk\xcaz{{\xcbj\xf46\xb7\x8bm\xdf}\x059\x01u\xa8\x86Y\a:\x1a}2\xbe\xa6O\xea掮\x8d1g\x0e3\xba慧D%4\x86\x11\xa4y\x8d\xef\xbb6\x05L@\xa2\x9d\xf9\xf1jCd\x16\x99$^;Kos\x1b\x1a\xc1\x17\xd0\n\x1c,\xb8\xa4\b\xd5yt$J\xe6tg\xc5c\x1a%ws[Q\x8c\xe7\x1c@\xa2慷DY\x86\x11b\x93\x9a\x94\x9b\xa2B\x8f\xd7kuz\xbd\x81Ќn\x8fzZ\xe7\xcb?\x0e\xae\xae\x1f\x1c\x8c\x1e\t.\xb3\x0f\xe18\x11\x8e\xa1\x8d\x01\x1c؈\x8e\xe9\x9c\xe0xvM[A\x91\xa5n\xb3ů\b\x15\x19t\xea 1d_\xc6LWs\x0f:H\x1e/j\x88%\xd1>\x94\x9c'G\x00cxK\x94i\x181\xcaz\xe0e\xeay#C\x9agqa!\x97\x06\xaa;\x92\x18_vP6\xe9\xec\x1e\a'\xc5B[\xf1\x11\xf1U\xef\xa6\xd2\xe9;lu\x81\x93E\xb9ͪ0\xc2\xcd\xd7\x01\x17\xc9\xd3I\xb1f\x84\xc63\x97\r\x8c\x1b>3\x05$\x03\xde\x12\x05\xccI[1\x82\x1f\xa3\x99\x13\x90( 1>\x00\x0eT\xa6\x04$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\np\xc0\x95\xdd \xbe\xf6\xe4&\xb6L0@\x00\x89\xa6\x04\xed\x95~FhF\xfc\x95\xed\xda\xc4@\xf6Z4\x86\xf1}\xb6x~t\xc8,a\x1a\xc3]\xa2\x1a\xc3\b\xf1?\xf0\xd5\x17\xf6\xbd\xf0jܿ\x92\x9e\x86lAM\x8c0~\xe2\xf7\xaf\xb8y\xb6dh]/\xfa3\x85Y\xedxܲ1*}tE~\xf6\xec\xcd\xf2\xff\xbc˞\x93\xbf\x91\xfc \x8eU\x82><\xcf-)\xf0\x96\xa8\xd60\x02\aZچdž\x8f\xb4\xa4\xbdF;\xfb\x8dr\xe8М\xe1f\x84\t\x10\xbf\u007f\x85\x88\xc1jۃ\xef\xc6ގ=\x99\x9a\xa5\x9az\xad\xc1\x82V\xf1\xea\x12\xb5\x9e\xc4\xc87fo\xf7l̙M\xd7\xc8Y\x98Q\xd7ހZuJ\x90\xf2\xb3\x12\x13:\xb7T\x84\xb7D\x19\x86\x11\xdeV\xd2\xfd\x11Z\x13\xf1JHI*t\x970\x8a\xcd%\xcbzF\x98\b\xf1\xfbW\x88\xdd\x1c\x14{Q\x89u:\xeb\xb4Dh\xb0F\xaff\xe6\xcf܃\x86\x82\x85\xd1\xf6\x16K\n\xc8\xff\xfcp6i\\\x97X\xbb\xc9\xfa,\xcd:%\x10\xd85K\xe4\xdcR\x12\xce\x12e\x19F\x9c\x96\x16\xealO\xcaj\xd7<)\x8bg\x19\x13\x06\xceY\x01F\x98\b\xf1\xfbW`\xdcc\xb0\x8c\x91\xdeRJ\x11\x02\xb3\x9c\xd1I\x8f\xa1\x85\xe2\xe1\xa2ǘ\xc5\x05\xf4\xed\xbe\nrT\xda\u007f\x1f\x91V~`\x94\x80\xf5j\x96ȹ\xa5$|%\xca4\x8c\xf0\xb7t\xf9\x05\xbf\xb7\xc5Գ \t0\x90\x89P\xc3Ȫ\x82\xac*r\x15j\xa9\xcc.\"\xee\x12\x1eyy\x922\xb2NuF\v\x1e\xb5\xa0bU\xde:dq\xad-ʮҴ\x1fBΓѡ\xae\x8d\x84\x0e\xf1\xfbW\xb0\x850\xb8\xa9\xb6z\xf9\xa6\xda\x1b\xf8ui\x9d\x16\a]7\xf4Ʃu\x8bWホ\xf1.G\xf5\xf1\x9d\xb5K7}$goȊ\x9e\x16\n\x0e\vx\x99f\xb2\xa8[\x92\x91\xb3P\xfc\x9bX\x02X\xb1Y[\x02֓h\"疒\xf0\x95(\xdb0B8\xe9r\xb9:\xe2\x99\xecK\t\x84\xd6\x03\x05E9\xf9kW\x90ILgF\x9d\xa7\xd9V\x16āno\x91\xdd\xeb\xf5\x8a\xdd\x06\x9f\xd7\"~\x93z\x9cVU\xde\xe1\x03\x99\xc8ִ=\xe7\xbe\xe8\xf2\"MC8Ա\x91\x10\xe4\x85\xe95\u007fʸ\xfd+\xfc\xa3\xa3GБ\xd1Q\xf5\xe5\xf2\xdf\xee\xday\xe6\xfc\xa9\xe5\x8e/\xf1\xb5A\xba\xda\xd9\xe0\a$y\xa7c\xf7\xf9\xe3\x0f>~\x03_>S\xed\xa8=t\xa8v\xd1e)\u007f7KK\xda\xc9\"\x19!o\x95\xd8è\xd8S\x9c\x91\xe7\f-\xa9\xaf-\x81]3\x9c\xc0\xb9\xa5*\\%\xca6\x8c\x10N\xb6\x0e\xfb\x86[O\xa6\x8dF\xc5/\x1c\x9a'\x9e)m;\xc9\xecN/:HS\xc3\x1d]\xea$\xd3dU\xe7\xc5\xd6\\Qӫlхy\"\xb3,\x8a\x90e#a\x97[j;\xd6\xc3\xc0\xbfBgi\xfb\xe3\x0f\x92\xc6\xfa\xf8\xd2\x1b\xe4C\xb8\xa3\xfb\xba\xe3\x94\xf8\xfa\xae\xe3\x8c\xf8Z\xfd\xb0X\x93k\xb5\xf2\xa2\xdcc\xac\x81\xa0f\xb2H&\xe8\xcc\x12/[\xf9\x19\xb6-\x1d\xcdy\xf9r?^SB\x1c\x8b\xee\x1bzs\xa4(<%\xaac\x18\x11\x9a.J\xa3e\"\xcbB\xd3\x1d\x0f\x14\n\x84|:\xb4ґhxj\xc4ꌤ*h\x8b|+\x15!\xcbFbD^\x98^\u007fN\xd6\xc0\xbf\"\xd8\xe9\xf14\xa1&\x8fG=\x90\xfb\xb4\xf6\xe1ݧ\u07bfq\x9d~\bKt\xdb\xc3\u05ff\x14\xa9\xdd)\xc6\xd5\xfbI\xcaq\x87t\xc9\x18\x93.Ij\nu.\x1cut\x01\xe32+\x11\xf0X\xb6ܧה\xa0S3%F\xde\x1c\xa9\nO\x89\xb2\r#\x82{.\xd0\xf0¾\xf4\xb9\x00\x96U\x84\x02\xf9\xd2O\x17\xd7ӑh(\xaf*U\x81b\b\xa6\bu\xac,\f0\xf0\xaf \xb0F|\xd7N=\xb3ڱ\xfc\x97\xeaV\xf4qGd\x01\xd1\xeaC$e\xd0!ݐ\xe9e\xac\xca\xebEm\n\xc3\xe50\x81\x9aLz\x17\xa9\xa6\x98~\\V&%\xb3J0\x9aȊ\xe3\xdcR\x12\x9e\x12e\x1bF\x04\xf7I\x12\xedO'\x89\x86ĸ\xa2\xb0\x9f\xe2\x0f\xa7\xd2[\xc1T\x8c\rVu^=\x89\x06\xacM\x8c\xd0xb\x95\x85\x81\u007f\x05\x81!\x84w\xf7\x8b\xe2\xbcvf\xd1q\xf2\x81\x1e\xf8ԧ\xa4\x15}\x97BZ\xce\xea\xddd\xd3)\xb9\x15m\xb2h\xe7\x9dkl\x02vF\xaa/\xe3+˕\xbaS\r9t\x9c\xb3D\xbe^\xb1J0\x92h\x1c疒\U00014a04\xc60\xa2S\xee\xe8\xa6\xcd,\xb9Bv\x1dҽ\xf8\x8d\x9bɫ]\xec\xea\x8d\xd3\x04ҟ\vV\xc4)Q\\sGP\x1bNL\xa2\x06\xfe\x15\x84K9\x9a1\xe3!\xc7y\xf2V\xbf\x8b\xbe\xd6c\xfc\x19\x19\x80\x9e\xa7\xa3P\xbc\xff\x97\xe2K\xf5r2\x16}\xb8\x9ef\x0f\x16/\x8c.\x01\xfb-\xebq?j\xcaP[,\x0e\xcc*\xbaD\xfcM\xc9=Or\xf2\x97裼\xec\x12\x985S\x12ǹ\xa5$\xbc%\xca0\x8c\x10\x0e\xb6\x0e\x8d\r\xb5\x1eL\x97\xe9\"\xa1\x87\xce\xddJ\xa3\xc6\xf5\xe8\x81\xd6v'\xa2\x97\xa5&\xeb\xf6\xb6y\xd9\xe4\x94+m[6W\xa2L\xf7\xb0\"\xaf\xcfkq\xf6\xe0~\xa7\xc5\x1b=\x17\xf9N\xc6\xf6\xa80\xa6\x8d\x84>\x86\xfe\x15:\x1cr,>\xf4\xfa\xeb;\x1d\x83\xf4C\xf5\xf1\xd7\xeb\x17\x93C\xef\xbfk\xdb\x191\x95N\x179֝9\xb5z\xe9\a4\xfb\x0e\xa4}\x8cj;\x1a\xc1\a\n\x83VU;x,k\x96\xc7\xeb\xf5:\xf3\xc5x\xa3\xa5\xa1c\xbb\xad8\xa0[\x82\x01\x13=7\xf3\xc3[\xa2,\xc3\b\xa1\xf7\x88\xbb\xad7m\xfe\xb2\x03\x92\x0f\x85\xdc\x0et\xd8m\xb9v\xe9&\xb0P\x97\x9be\xa7&\x81#\xf6\xac\x9c\xaa\x8d\b\xd5)\xf2։\uf5a1l\xf1\xb5.\xbaĆ\xafw\xab\xc3\t\xdaH\x9cDF\xfe\x15lN\xd5\x1f\xaa\xad~\xb0\x9e*\x14_\u07fdtQ\xbd4\xe6<_\xbf|i=m`\xabw\xef\\Z\xbb\xed/4՛\x15\xbe\x8f\x1b\xe1\x0e\xb1\a\xe1\xb5x\xd4\xf3\xb1\xa1\x19hڻm\x9d\x9dU\xd4\x10\xd0/\xc1\x80\x89\x9e\x9b\xf9\xe1-Q`\"<fie\x84&B\x9a.\xa2\x1c\xb48\xb5W\xdbqtD\xecAU\xa2\x15\x9a-\f\x98%L_@\xa2)\xc1\x8e\xfcqFh\x1e\"\x12\xf5\xcfb\xfeL\x85\xdeX\x12މgFP\xa7\x84i\vH\x14\x98\x04\x14\xad(0ɀD\x81\x9b\xe6\xb3\xc1\xea]\u007f\xb8a\x94\v\x98\x18 Q\xe0\xa6\xd9\xe5p8\x18\x0f;\x01\x93\x02H\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\xcdt\x96h\r\xb2\xad\x1a6\xca\x04\x00\xc9e:K\xd4\xd7\xe9.\xb6Mh\xd1K\x00\xe0\x06w\x892\f#\x82\x03m\xfbڒӜu\xa5\xe1Z7@z\xc1[\xa2\fÈ\xa0\xc7\xdd?ڷ\xa7/\xe6~SD\xaf\xc1\xba\xce\x00\x90lxK\x94a\x18qa\x0fY\x85\xe1\x9d=\xc9\xe8r\x82D\x01\xb3\xc3Y\xa2,\xc3\bO\a\xdd\xd4\xd2\x17c\xbf\xa9\x02$\n\x98\x1d\xbe\x12e\x1aF\xc8K\xea\xb6\x1f\xd3\xdfo\xca\x18\x88\xac\xf4\x0e\x00\xa6\x84\xafD\x99\x86\x11\xdd-t\x05@\xf7\x91X{N\x11\x82\xad\xb2{,\x9e\xa5\x00\x00 Ip\x95(\xdb0\"\xe0\xf6\xf8\x05_\xbb+)k\xf2\x1cC\b\xddc\x94\t\x00\x92\aO\x89\xea\x18F`\xbf\xc7\xe5r\xf5x\x92a\x9f\x1e\xb0\x15\xee\xe8\xd4u\t\x01\x80\xe4\xc3S\xa2l\xc3\b\x82\xe0\x0f\xe2\x96Wc\xed;E\xf4\xa2\x93FY\x00 \xa9\xf0\x94(\xdb0\x02K\xbe\x92#\xaed\xb8\xcd\xc1\x8c.`vxJTBc\x181\xec\xf2\x8bb=\x90\x94\xa9U\x90(`vxK\x94a\x18\xf1\x8e덱\v-\x9ed<\xb9`\xe4\xe4\x03\x00I\x87\xb7DY\x86\x11\xfd\xadnO\u007f\x12\xee|\b\xbe\xfe\x1ak2\xba\xd7\x00\x10?\xbc%j&\x96 T\x90\x8cid\x00H\x80\xe9,Q_\xff\x18\x06\x00\x933\x9d%\n\x00)\x00H\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rw\x89\x86\r#0\xee\n\x99DD\xbc#\x00\x00P\xc3[\xa2a\xc3\b\x8c\xc7]\xd2*\x80\n\xef\bs\xd0\xd9o\x94\x03\x00\xb8\xc1[\xa2!\xc3\b\xb1\xe9l\x95%\xaa\xf0\x8e0\a\x155F9\x00\x80\x1b\x9c%\x1a6\x8c\xc0]\xae\xae}\x92D\x15\xde\x11\xe6\xa0l\x99Q\x0e\x00\xe0\x06_\x89F\f#\xb0\x10\b-w\xad\xf0\x8e\xe0\xca@&B\r#\xab\n\xb2\xaa\xc8%\xa2\xa52\xbbhm@l\xe6\x91D\x19\xc6u(\xa3\x05\x8fZP\xb1*o\x1d\xb2\xb8\xd6\x16eW\xa9;旫\x1d\x8e\xfd\x1fm{xѦ/\xd9G\x03\x80\x89\xc1W\xa2\x11\xc3\b\x82,Q\x85w\x04W\x84\xd6\x03\x05E9\xf9kW QmΌ:O\xb3\xad,\x88\x03\xdd\xde\"\xbb\xd7\xeb\x15\xdbt\x9f\xd7҄q\x8fӪ\xca;| \x13ٚ\xb6\xe7ܧ*\xec\xfa\x993\xb5\xab\x17\xd7\xee\xdevק:\x87\x03\x80\t\xc1U\xa2\n\xc3\b\x82,Q\x85w\x04o\xca\xd0<\xb1F\xb4\xedtc\xb2d\xe7A\x9a\x1a\xee\xe8ZE\x89\xe2&\xab:/\xb6抚^e\x8b.\xecqG\xfd5|\xe3Zt2\x00\xdc\x14<%\xaa4\x8c \x84ZQ\x85w\x04gʬrw\xf5\x81B\x81\x90朗l\x89\x86\xf2b\xab3\x92\xaa\xe0\xf1jh@\x81ɇ\xa7D\x95\x86\x11\x84\xd0XT\xe5\x1d\xc1\x95\xb2\x8aP \x8f@\x97\xd0\x0fl\x89\x86\xf2\xaaR\x15<\xbe.:\x05\x00n\x1e\x9e\x12U\x1aF\x10d\x89*\xbd#8\x13\x16\xe3\x8a\xc2~\x8a?\x9cJ\xef\xd3R16X\xd5yu%\xfaLt\n\x00\xdc<<%*\xa1\x19\x8b*\xbc#x\x13\x96]\a\xa2։\x1b7\x93W\xbb\x1d\xe3q\x9a\x90\xfd\xa4X\xbd\n\x90(\x90DxK4l\x18!\xf8|\xeeN\xdf8I\x8bxGpE\xe8\xa1s\xb7\x92u\xe1z\xf4@k\xbb\x13\xd1\xcbG\x93u{ۼlR\x9fJ͕ۖ(\xd3=\xac\xc8\xeb\xf3Z\x9c=\xb8\xdfi\xf1*\x9fY\xfc\U0008f0eb\xeb\a\aa4\nL6\xbc%\x1a6\x8c\xe8\x93F\xa5\xd4\xc9%\xe2\x1d\xc1\x93\x81\f:\xfc\\(}\xea\xb0\xdbr\xed\xd2\x1dZ\xa1.7\xcb\xdeK\xa2\x11{VN\xd5F\x84\xea\x14y\xeb\xc4w\xcbP\xb6\xf8Z\xa7(첃\xb2\t\x03\xc0\xe4\xc2[\xa2\x00\x00$\x04H\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00LM*H\xb4\x06\xd9V%\xe1Ǥ\x00`\x06RA\xa2\xbeNw\xb1-`\x94\v\x00\xd2\x12\xee\x12e\x19F\xa8B&]h v\x06\x00HSxK\x94e\x18\xa1\n\xd9\xf4\xa2\x9e\xd8\x19\x00 M\xe1-Q\x86a\x84*\xd4\x01$\nLW8K\x94e\x18\xa1\f\xf5\x00\x89\x02\xd3\x15\xbe\x12e\x1aF(C=\x06PW\xec\f\x00\x90\xa6\xf0\x95(\xd30\"*d\"\xd8*\xbbǒ\xb0D \x00$\x1b\xae\x12e\x1bFD\x85l\x8e!\x84\xee1\xc8\x03\x00i\bO\x89\xea\x18FD\x85L\x02\xb6\xc2\x1d\x9d\xa3\xb1\xf3\x00@:\xc2S\xa2:\x86\x11Q!\x93^t2v\x06\x00HSxJT\xc70\"*d\x023\xba\xc0t\x85\xa7D%&4\x16\x05\x89\x02\xd3\x15\xde\x12e\x19F(B=z@\xa2\xc04\x85\xb7DY\x86\x11J\xef\b\x16\x82\xaf\xbf\xc6\xca\xdfP\x02\x00\xcc\x00o\x89N\x84%\b\x15\xb4\x1be\x02\x80\xf4$\x15$\xea\xeb\xe7\xee\x9a\x06\x00f!\x15$\n\x00\xd3\x18\x90(\x00\x98\x1a\x90(\x00\x98\x1a\x90(\x00\x98\x1a\x90(\x00\x98\x1a\x90(\x00\x98\x9a\xff\x0f5\x16\x1d\x16\xa8\xc9g\xc2\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/callers2.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xfc\x00\x00\x01\xb0\b\x03\x00\x00\x00#z\x9e\xf7\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x04\x06\x02\a\t\x05\n\v\x15\a\x0e\x10\x0f\x11\x0e\x0e\x12\x1d\x15\x16\x15%\x19\x10'\x1a\f\x1e\x1d\x17\x16\x1e.!# #$\"$%#%'%'(&)(\"()'-+ *+),-+-.,12053'O.\x0f352786<:.9;8=?<B@4#Cxb<\x1aAB@j=\x11DFCLH9\x00f\x00\x00g\x00\x00h\x00\x00i\x01JLI\x00j\x02\x02k\x03\x04l\x050R\x95OPNVQ@\tn\a\fo\tRTQ\x83L\x1d\x0fq\v\vr\x17UVT\x0fs\x18WYV\x11t\x19_ZH,`\xae\x14v\x1b7]\xad>]\xa1Z\\Y\x16w\x1d\\^[\x19y\x1e:b\xac_a^Ya\x8bac`\x9aZ\x1d*{!@f\xb1Ke\x9e(|*dfclfP+\u007f,fheMj\xaf.\x81.Fm\xb1ikh0\x8301\x841/\x859Jq\xb5mol\x89j_oqn;\x86:>\x88<\xb3h\"{s[Vu\xb5sur?\x8a>@\x8b?uwtB\x8c@@\x8dG\\z\xba\xadq?y{xJ\x8fI^~\xb8L\x90K\x94wq\x85}d~\x80}O\x93Nb\x83\xbdN\x95U\x81\x83\x80W\x95V\xa7|e\x8e\x85gm\x87\xbcZ\x98Y[\x9aZ\x87\x89\x86]\x9b\\^\x9d]\xba\x82Z\\\x9ddr\x8d\u008a\x8c\x89\x96\x8cnd\x9ddf\x9ff{\x90\xc0\x8f\x91\x8eh\xa1h\xe3\x83+ЇK\u007f\x93\xc4j\xa3jz\x97Ɠ\x95\x92s\xa4l\xa0\x96wq\xa5s\x81\x9aė\x99\x96\xe4\x8b@u\xa9w\x9a\x9c\x99\x86\x9eȜ\x9e\x9b\xef\x904~\xaby\xa8\x9e\u007f\x9e\xa0\x9d\x80\xad|\xa0\xa2\x9f\xf9\x94.\xa1\xa3\xa0\xa2\xa4\xa1\x81\xb1\x85\xff\x952\x92\xa6ˤ\xa6\xa3\xb3\xa6\x82\xa5\xa7\xa4\x8b\xb2\x88\xa7\xa9\xa6\x8d\xb5\x8a\x8e\xb6\x8c\xaa\xac\xa8\xb9\xac\x88\x8d\xb8\x93\x9e\xaeΕ\xb8\x95\xad\xaf\xac\x97\xba\x96\xaf\xb1\xae\x98\xbb\x98\xa3\xb2қ\xbe\x9a\xb3\xb5\xb2µ\x90\xb5\xb7\xb4\xa3\xbf\x9d\xac\xb7Ң\xc0\xa4\xb7\xb9\xb6\xb9\xbb\xb8\xa5ħ\xb1\xbc\u05fb\xbd\xba\xa7Ʃ˾\x98\xbd\xbf\xbc\xa9ȫ\xb8\xc0կǫ\xbf\xc1\xbe\xc1ÿ\xb2ʮ\xc2\xc4\xc1\xbd\xc5\xda\xc4\xc6òͷ\xb9̸\xd6ǝ\xc7\xc9ƻκ\xbcϻ\xc4\xca\xd9\xc9\xccȾѽ\xc0ӿ\xca\xce\xde\xcd\xcf\xcc\xc4\xd0\xde\xc8\xd3\xc1\xcf\xd1\xce\xdfѥ\xc7\xd6\xc9\xd1\xd4\xd0\xd2\xd3\xdd\xca\xd8\xcb\xd3\xd5\xd2\xce\xd6\xdf\xcc\xda\xce\xe7\u05eb\xd6\xd8\xd4\xd4\xdb\xd0\xd8\xd8\xe3\xd8\xda\xd6\xd3\xdb\xe4\xda\xdc\xd9\xe6ݯ\xd7\xde\xd3\xd5\xdf\xda\xdd\xdd\xe5\xdc\xdf\xdb\xd7\xe1\xdc\xde\xe0\xdd\xf0\xe0\xb3\xdc\xe1\xe4\xdf\xe1\xde\xe1\xe3\xe0\xe3\xe5\xe1\xe1\xe6\xe9\xe4\xe6\xe3\xe8\xe5\xea\xe5\xe7\xe4\xe6\xe8\xe5\xe4\xe9\xeb\xe7\xe9\xe6\xef\xf2\xee\xfe\xff\xfc(t:\\\x00\x00 \x00IDATx^\xed\xbd\x0fp\x14G\x9e\xe7\xbb\xcc{\xbe}ϯ\x84zf$\xf5\xae4b\xef8M\xb4BB\xc7\x19\x9e%`\xd7z\b\x8b\xf3\xc2C\x1b\x02\xc1\x03\x9d\xe1\x16\xc6\xd8\xf3\b\xb3+0\xecB\x888\x9be,\xeel\xe4\x85~\x92\xb5\x1e\x99\x91X\xd9 \xa2ό\xa4\xc0\x9a6 ,\x06#\xd9H0\xd8\xc6\v\xde\x18\xf5\x10\xb6\xc5ȱ\xf66a\"\xda1\xd1\xe4M\xbcʪ\xee\xaa\xcc\xea\xcc\xca\xeeVw\xb6\xd4\xf5\xfb\x04!\x15\xa9\xac\xac\xac\xac\xfev\xfd\xe9\xea\xfa\xfc\xc1\xef\x93\a\x01\x000{\xf9\x03Q\xc2m\x10\xb5\r\x00\xc0\f\x06\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0fd+aQ\x05\xa7\x03\xe1\a\xb2\x92@c\xa1\U00084a12Á\xf0\xf7.\x9e\x14U\x91I\xc2ݙZ\xdc+\xaa2\xa3\x90\xd3\xdfpI\x89w  \xaa\xe5p\xe4\x86?\xd0w\xbc\xbd\xfbB\x10O\x06/\xbc\xd1\xfe\x86>I\x94\xf2\xf8\xd7#kk\xf7=\xb0\xab\x11C\xb3\x92\x8b_e\xbe<\xa5ٮZ\x8b\xfd\x9f\xd9\f\x14\xfaDU\f\xa6\xb6\x15歈\xfb\b4\x89\xee\xb4\xe4\x1c\x14U\x91\x8b`t\x92\xeeo\"\xa3~U\xe9\x13U\x01\xa4\x86\u007f\xd2\xeb\xbb\x11\xb8q\xf2\xb8\x9a\xf3`\xe7I<\xd9\x19\xa4J\xb9\xecn8\xfbR\xed}\x9b\n\xb1L\xd5\xe7-U\u007f-ͫ\x9f\xb2\xa9՚\xd3a\xf3W\x1e\xbe\xfc7DU\f\x96\x16z\x1b\xf3l\xdf\xd9\b\x92\xea\x8eon\xab\xa8Jz\x18\x1ce\x16\x8bFG\xd8\xdf$\xdb%\x19V\xfc\xa2*\x80\xd4\xf0\xdf\xf6\xe2\x03\xb1\xa0\xf7\x06B\xfe\xee\x90:\x19\xea\xf6S\xa5<\xeeW\x9fA\x0f\x12\xcb>BM+\xd4\xccM\xe5\xadh\xb2\xa9s\xdbe\xf7W>q\xef\xc9єҊ\xc2\xf1f?\xc9\xee\xecqe\xe6\x00wa=\xbb\\4:\xa2\xfe&\xdb.\xc1\xb02$\xaa\x02H\r?\xd2B0\x89\xc3>\xa0\x9f\xf8\xf5\x0eP\xa5<>\xab~\x97\xffG\x1eM\xf5K\xbbP\xe7\xf2z\xbb<5\x16ś\xcbd\xb9\xa9\xc4\u007f\xac\x9alw\x82E\x8d\xa2*i\xa1\xacNT\x83\x8d\xa8\xbfɶK\x00\xe1\x8f\x03\xb9\xe1W\t\x05\xba}\xea;\xf8T\xe7\xe0Th\xca\xdf9E\x952\xf9vm\xb5\xc61\x84\x8eTW\x9fC\x9f\xd5Voœ\xb5g\x8fm\xad\xdd\xf7[\xad\xceg/\xac\xadm\x88LGi\xaao\xadC+\xbc8\xfc\xc1\xba\"W\xf1ʫj\xe16en\xeb\x93\xc5\xee\x957\xb5*\xa1\x02\xed\x9d!T\x98\xdbT\\4\xb8\xdd]\x15\xe4\xd4%g\v\xe6)J\xceq\xa4U\xc8\xf5\ue61f\xb7\\{ۚZ\xef.ޱÝ\xdfMt!\xe4V4v\xe0\xba9\x9d\xea\x9e])\xb1̆n\u05f9s\vW\x04\x88\ue82bs\x15e\xcf\xcd\xf5\xf3\U000961f8\xb3u.Ο\xbf#\xfaV\xb1'/\x84(\x12n\x81\x81\u007fyq\xae{E1\xafԧ\xaf\x9aRF--\xbeщ\xe9o\x8a\xda5\x19\x84\xf0\x8b\x91\x1c\xfe)\xaf\xd7ۡ\xbd\xe0B\x03\xead_\xc8R\xca\xe4ӱs\xd5=cc_\"\xf4۱\xda\x1e\xf4`\xecH-B\xb7\xce\xd5V7\xf4\xf4\xac~\x01\xd7\x18\xab}\xb6\xe7J\x8fzn@\xd2T\x1fȟ\xfa^\x00\x87ߧ<9ؽ2g\x18\xa1\x1b\xc7\xe7*\xc5\a\x9b\x8b\xf3\xc6q\x95QeP\xab:X\xa0\xecX\xaa\xb8\x0f\x16\xb6p\xeaR\xb3]\xf6\xfb]\xdae9\\Z\xd8\xdcR\x80wT\xa1\x92\xa2\xd6fW^\xfb\xf2\x16\xb2\x0f\xef\xfb\xbb\x94f\xbf_}\x9d\x06\xfc\xb9\xea<C\x8d.z64\x98_\xd62Ь\xb4\x90\xdd\tu\x1f/\x9e_P\xbcc\xbd\x12\xe0\xcd֘\xb3\xdd\xd7ZX\x16yü`}\xa9'\xdcB,\xc3\xca\xfa7\x06\xbcn\x85\x8e\xa9Y\x1a\xbc\xe0\x9f_\xe5\xf7\xfboPK\x8botb\xfa\x9b\xa2v#\x84&\a\x17\xba\x93:\x86r\x16\x92Ï&\x03\xe3\xdd\xf8\xd2^h\xa0\xfbF\xe0F\xf7@\x88*\xe5a\x1e\xf6\xab\xe1G\xa8\xa7V\x9b\\\xad\xee\xe9_lP\xa7\xbeݴ\xef[\xf5\xe79\xfa\xaa@S=*۶\x10i{\xfen\xdcx\x99\xf6\xb9\xafk\x1e\u07bd\x17/\xc6\xd3>\xe5\xb6^\xb7h\xbd:\xedC\x8dOr뒳!\x94\x17\xb9&\xefr\xab/\xcb\xf5\x85\xeaT\x97\xa2\x1e,\xb4*\xe3Ȃyد\xbdt\x9b]\xf4l\xa1bu\xaf\xa6\xbeʵ# \xa3;\xea\xf2\x95\xa5A\xfd\x84\x889\x9bO\xc1\x17\x06\x87\x95.\xbdv@\x89\xbd\x14\x96X\v\xb1\xb4\x16\xe2m\xd3\xea\xa6\xdf\x1d\xa8R\xe2\xf0\xdc\\\x1a\x8actb\xfb\x9b\x9av#<\xa1\x1e8$p\xb2\xe5Xd\x87\x1f\xe1W\xfa\x80y\xc1\xef\x02Uʃ\x1d\xfe\x97\xa2\x93W\xaa?e̤\x86\xbfE9\xa8\x85\x1fM\xb5.\x9fW\x80\x8f$\xd5W\x8evhݪ\xe0\xb8\xf5\x1a\xe1\xefBCJ\x10\xcf«K\xceF\xbc\f\xf1ɫ\x96\xab&7\xc2I\x8f\xf9\f\x9b\x1d~c6\x9f\xf2\xbeY\xb7\x97\b\xbfqM\x8c9[\xfd\xbc\x10\xa68r\xee\x1c`d8\xb1\x16b\t\x14\xcd\xdb\xe6}?l9>\xa7Jɐ\x92\xd7\xf0\x84\xa3\x13\xdb\xdfԴ\x1b!\xd0\xe7-\x81=\xbf\x18\xa9\xe1\x0f\xe9{\x91\xab\xdep\xb8]\u007fͿ\xdf\x1e&J\xb93\xb2\xc3oL\x9e\xa9\xfe\x961\x93\x9a\xe4\xa9\x1d\x93Z\xf8\x87\v\x8b\x9bN\xfa\xab\xf4@k\xaf\xa0A\x05\u007f\x9c4\x14=\xfc,\xeaC\xc3.m\x16^]r6\xe2eh\xe4\xaa\x05\xbf-\xf4Ż\xe7'f#\xd2etG}їE\xa7\x98\xb3\x95EN\x8c#\xf7\xb0\r+ƛ\xa8Ab-0\bz\xebJ\x94B\xeax\xdaRJ\x86\xd4X\x1a\x8act\x18\xfdMI\xbb&~e8\xa6\f\xb0 3\xfc\xe1N\xfd\x94VM|4\xfc\xa3\xea\xa4Yʝ\xd3\x12\xfeW-\xe1\xbfR}\x8b1S\x93\xfe\x81\x11\x0e\u007f\xc9b\xbc\x1f\xa8\xd3\x03\xbd\x1d\xff\xf4*\xb8$芼\x9c\x88\xf0s꒳\xb1^\x86\x81\x9c\x15\x81\xab\xf3\x17Ǭ\x83%\xfc{,\x19\x1cP\x88ϴ\x8d\ue42f\u007f\xe6l\xeb\xe7\x8djD\xae\x976\xbbb\xf7s\x89\xb5\x10\xcbe|\xa8\x13\xecʣ?\x93\xa7J\xb5E\xb4\a\x8c\xc9(\xc2щ\xedoj\xda5\x81\xab\xfdq 3\xfc\xe8\xb8vוv\x80?\x189\xec\x1f\xa4Jy\x10\xe1\u007f\x15\xa1\a\xcfZ\xc2\u007f\xbfa7\xde\xf5\x1f;F\xcdD\x84\xbf\x18\xbf\x84\xc2\xfa^\xc4U\x88O\"\xe7U\xe9\u007f\x9c\xa7\xbfn\x88\xf0s\xeaR\xb31^\x86\xa3J\xa1\xa2T\xc5~\\i\x86?O\xedHx\xa1%\x83\xc1\xa2*<\x10۵\xb7\x16\xa3;䋞9[\x9f\xa2]\xdeޣ\xdf+\x17.Y\x81bH\xa8\x85\xdb\xcd1\xf7\xd54\xeb\xf7\xc8Um\xe3\x97V\xa9\xa31\xa9\xb7#\b)=:\x8c\xfe\xa6\xa4]\x02\b\u007f\x1cH\r\xffM\xef\x00\xbeʧ]\xf0\xeb\xea\x1e\x0f\x8cww\x85\xa8R6\x91\xab\xfd\xdaݽ\xbb\x1bzz\x9e\xad\xae={\xeb˱\xda#c\x0f>=R\x8b?\x05\x18\xab\xddz\xf6ʱ\xea\xb3\xe4\\S\xf5ڋ\"PU?\xa5\xbe\xb4\xeaZ\x0f\x96)\xee\x96!\xf5\x95\xa3\x94u\xb7\xcfw\xebg\xd77s\xb4\x03\xcd\x1b\xee\x96`W\xee\xd5 \x9e\x85Sל\f\r\xf9\xfd\xaeF\xbf?\x88\xaf\xe07\x0e\xa1\xd1\xc6\\\u007f\x00\x8d\xba\x06|\xfe\x80u\x17\xa4_\xed\x1fҊ\x17\x17\x1e<\xb8X\x99\xdbq\x83\x9c\r\r~\xaf\xc4\xebۮ\xb4\x93\xddQ\x97\x80/x\xeb]d\xcf֤\xd4w\xf76*\x9dZ\x95\x16\xc5\x1a\xddD[X\xa9\xe4[\x87\xbfY\xc9o\xf6\x9dl\x8c|\x00\xc1,mv\xb5\xf4.\xcd\x0fPK\x8bgtb\xfb\x9b\x9av\t.3N\x84\x00\vRÏ\x02\x83\xdd\xed'\x87\xb4\xb3\xdc\xd0\xf0Ɏ\x93\xc3!K)\x8boWk\x1f\xf3\xd7\xfe\x06\xff\xe7\xb3ݵ\xab\xf7\xbdZ]}\xe4\b.\xfa\xb4V\xfdyD-\xfe\xcd\v\r\xab\x9f\xa5o\x04jV\x14|]h\x9b\xa24\xa3p\xcb|Wa}\xc7<\x97\xbaKq\xedh,(Z\x1f\xddY\xec\xf9\x9e\xfa\"\t\xab\xbb\x8f\xe3\x05J~7>\x05\xe6\xd45'\x87s\xf4\xb3e/n[\xc9\x1d\xcfW\u007fnC\x17\\\xb8,\xb7\x8a:\xfd\x8c|\xce?W\xbby\xf1fU^\xc1\xf2&\xb5.9\x9bZ\\W\\\xb0\xf0$\xd9\x1dtU_\x82\xbe{\xe4\xcc\xd6W\xe5v/\xd6\xf6\x96ȟ\xb7\x03YH\xb0\x05Ԟ\x1fs\x8e\xdcY\xd5\\\x9c[TEg\x9f.\rmw\xe7U\r\xd3K\x8bct\x18\xfdMI\xbb$\x93s\xeb\xaeN2\xde\x14\x00\x02\xb9\xe1\x9f\t\x98\xe7\xd5\x1a\xdb]\xd6\xfbC\b\x88\xba\x96٬L\xe6o\x9b\f\x85\x82\xc3uӼ\xcal\xdb\x1d6]\xaeF\xee\x1bg\xdc\xf4*\xd3\xeb\xb7=\xd4褤\xbf:6\xa3\xde[bw1\x13\xc08>\xfc\xa8\xa5\x98\xff\x1d\xda\xf8\xc3\xdf\x1b\xf9<<\xec\x9e\xe6\a\xccv\xdda2U\x94\xe4\x97\xe4\b\xc2\x1d\xee'Eu\xa6\x039:\xa9\xe8o\x14\xdbQ\x9f\xbcʸ\x16\x00\x10@\xf8\xed\x88?\xfc\xa39\xfa\x91\xe7x\x0e\xf1\xb9\xfd\xac!\xe0ޑ\xaa\x9d1\x93t\x8dN\xba\xdau\bN\v\xbf~\xb5(>\x88\xba\xc2\xd9\u008dyOv\rv=\x99\x97\xd6=\xe8l%]\xa3\x93\xaev\x1d\x82\xd3¯]-\xba\x8d₨\x1b\xc7l\xbe\xe5E\xae\xa2\xe5\xd3<\xe8\xcfZ\xd25:\xe9j\xd7\x118-\xfc\x00\x00D\x80\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\xa3\x03\aX\x93\x00\x90\xed\xc8\r?[ץ2\xee\xcd\xd8MZ\xff\xecy\x991\xa9\xf1\x91G\xe7z\xccL1\x1c\xf0x\xfaEuf\x12\xa9\xe9\xef\xc5\xcawDU2@j\xd6M̝R\xcf\x1aQ\x1d\x9aSt\xcf2=|R\xc3\xcf\xd6u\xa9\x04\xdb/t\n\xe6M\x1b{\x17\xdceLj\x84?\x189\xe591\xf2\x81͗^.}\xa8\xff\xbe;R\xdaƯ\x958\xd1vSM\x92\xfd\xe5t\xe7|\x85\x94\x94%H\x82\xeb\x96<\xd7\xf6\x97\x8b\xaa\xd0\xdc\x1b\xd9H\xf6,\xd3\xc3'5\xfcl]\x97\x8ao \x90\xa9\xf0Ox~\u00984\xb8\xe6\xf9 \xa6\x8c\xe4\xff\xd9\x15\x9d*O\xe9\v\xcel7\xb5$\xd9_^wf\xe8\xe32\x12Z\xb7iЖ`\xf8\x11\xdaI\xf5,\xc3\xc3'5\xfc\x1c]\x17\x1a\xef\bf,\xfc\xfb\xcb\xef2&\rD\xe1ߐ\\\x98\x84lHS\xf8\x93\xeco\xba\xba\x93&\x12Z\xb7i0\xdd\xf0g\x18\xb9\xe1Wa躂\xed7Q\xa6\xc2\u007f\xa7\xf4\x10c\xd2$\x12\xfe\xe7=\xa5\xa7\u007f\xb2\xaa\xe2\xa9ϩ?\xbe\x13\xb9&\xb0\x01\xff\xa7\xfc\xb0Y\xe1\xe7\x9b+V\xfd\x84>Yh\xf3\xe0\xf3\xbd~\xf5\xe7Q\xf5\u007f\xa76T\xac;\xa5\xfe\xfe\xa8T\xfd\xff\xc4ޚ\x05O\xabc2\xf2TMi\xe535\x96vI&vU\x96.yF}\x8b\n\xeeZVZ\xb3\xf3#\xadИ\r1\x17L\x90H\u007f\xd9\xdd!\xfb{\xaf\xc2\x139\x85\xa5F\xe7뽕\x8f\x1d>\\i=\xa2et\x9d=\xa8D\v\xd4\xe8\x18cF\x8fd\x14\xaa\x94\xb5n̥\x85\x97\x94\xbe\xf2زK\x87\x16m\tZzv\xe2\xc0c\x8f\ue720&\x119Pw\xf7.[\xb4\x8b{\xd8\xcfiW\v\xff!\xb5\x8f\v\xbeNp\xf8҂\xe4\xf03u]>u\xf7\x9f\xa9\xf0\x1f(\xfd\x9c1i\x12\t\xff?\xf7\x97z*\xdbN<B\xef\x00\x83\x1f\x8c\xac\xda2222\x81\xffS\xeeY\xd3\xff\xce\x12\xad\xc2~ϡ\xf3'*7P\au_=\xb7y$\xa8α\xf9\xb9\xaf\xf01\xc6\xd1\xf3G\xcb\xf7\xaa\xa3\xd0\xdf_\xb3\xea\x91\xc7~\xb2\xd7s\a]\xf7\xec\xed\xbfx\xba\xd2\x13\xa6\xdb%x\xafb\xc3\xeb\x17\xdb<'ԳEρ\xf7\xfawz\xae\xa9\x85\xe6l\xec\x05\x13$\xd2_vw\xc8\xfe\xa2\xeb##\xfa.\x96\x1c\x9dКe\xa7\xda\xca+N?u\x82j\x8d\xd5u\xf6\xa0\x12-PK3ƌ\x1aI\x03\xaa\x94\xb5n쥽\xb7\xc8\xf3\x93\x1fy*_[\x12ӳ\x9a\xd7\xdaj*>!'Ɂ\x9aX\xb4\xea\xf4;Oy\xb8{~v\xbbZ\xf8\xef\xee\xf5\x9c\xd06\\\x02×\x1e$\x87\x9f\xa5뺁\xdf\r2\x14\xfe;\xa5\a\x18\x93\x04\xc6a\u007f\xf9\"\xf5\xadao\xa5\xf5\xef\xc4a\xf4\x92\xaf\xd5W\a\xaep\xde\xf3\x966'\xfd\xe6\xfd\x96~ex\xdd\xcf\x11\xba蹈\xf0\xcf\xf3Z\v\x9e\x1f\x05\xb5\x13\xa2S\x95\xda\xfemQ\x98n\xd7$T\xf3t\b\xe7\xef\x1e\xfe\x81\xdf6\xd7\xedD\xd4l\xec\x05S\xc4\xdf_^w\x8c\xfeb\x16D\x8eb\xcd\xd1\xe9\xf7|\x84\xafj\u007fB\xb5\xc5\xe9:{P\xa9\x16\x8c\xa5\x11cF\x8c$\x01Y\xca^7\xe6Җ\xedU뼃\xf6\x1f\xb0\xf4\xacF]潚\x8d\xd4$\xd1\xd8\xe6Uj\xdd\xf0:\xfea?\xa7]5\xfc'\xca\xcfG+\xc5;|iBv\xf8\x11\xb2꺂\xed7\xc2\xe1p\xa03\x9c\x89\xab\x1fϗ\xdeaL\x12\x98\xe1ߏX\xe7xD\x98\x0eD+\xecz<\xa4\xaeQ\xf8\xb1\xfdT͏<\xa1\xd0[\xf7\xc2\xe5\xea\xc6ݿN+Y\xa3U\xd8P\x1eY\xee\xe7\xcbj\x9e?\xfdQ\xc4X\xc5\n\xffy\xcfG\xc6\xf4ק\x9e~|\x91g\x1d=\x1b{\xc1\x14\xf1\xf7\x97\xd7\x1d\xa3\xbf\x18\xe3\xd5k\x8c\xceˋ\x10\xbet\xfa6\xa2`w\x9d=\xa8T\v\xc6҈1#F\x92\x80,e\xaf\x1bsi\xcb\xfa\xd5m\x1cD\x87\x9fCtϴ\x0f}Oy\ue453fc\xf7<\xa7q\xe1Q\x9b\xf0\xb3\xdb\xdd\xd9v\xd4c~\xbe\x17\xef\xf0\xa5\t\xa9\xe1g\xea\xban{\xa3\xc8\u007f\xde\xe2\xdd\xf2\x03\x8cI\x123\xfcx;نߨ\xb0.r\x8e\xbc\x93\xaa\x19*\xfd\xe4\x84z\x06\xebQӴY\xff\xcb\u038dZ\vƙ\xfd\xbdӻ\xd6x\x96\xbc\xaeM\xb3\xc2\u007f\xc2c\x9c\x96_[Rs\xf8\xed\x91-\xeb\xe8\xd9\xd8\v\xa6\x88\xbf\xbf\xbc\xee\x98\xfdEī\xd7h\xec\x84\xe7k\xbc\x83\xb6\xec\xba8]g\x0e*Ղ\xb14b̈\x91$ K\xd9\xeb\xc6\\ڲ\x8b\xe8Z\xa9\x1a\xba\xe7\x18=C#\x9e\x0f\xc9I\xb3\xb1\xeb\x9e\x11\xc4hL\xdc\xee\xce%\x8f\xac1\xc72\xde\xe1K\x132\xc3\xcf\xd1uMM\xaa\x8cwLf\xe01\xeb\x87<\x13\x8cI\x92\xb8\xc2\u007f\xfa\x0eUa\xef\xe3\x1fj|MW]ӿe\xf3\x9a\xb7\xf1\xc1\xe9\xfeǵ\x82\x9a\xfdF\v\x98\xebx\x0fs\xaf\u007f\xc1)\xba]\x93K\xe6\xees\xcdFmO\xbf\x8e\x9e\x8d\xb3`\x92\xf8\xfb\xcb\xeb\x0e\xf5\xb6\x14\xfb\xea\xbd\xe3y\xfa\xceG\xab6[\xb6%\xbb\xeb\xecA\xa5Z0\x96F\x8e\x999\x92$D){ݸ\xe1/\xd7CJ\xf5L\xbb\xf8{Z\xddw\x13\x93fc_{\xb4a\xb1\xf9\x9c\x9f\xd3\xee\xce\xcaO\xee,2\xce\xe7\xe3\x1d\xbe4!3\xfc\x1c]\x97FF\xce\xf9\xef\x96\xefgLR\x88¿e\x8b:\xaf~FiT\xb8\xa8\x9f=\x1f}\x8d\xae\xfa\xdc\xf3\xa5\x17=\a\xf0\x8b\xf9\xbcV\xa1?r\xce\x1f}y\xb7ig\xb5h\xcb\x01\xba]\x93в-x\xd0\x0e\xa9/\xc6\x1a<Sx\xdd:z6z\xc1w\xda\xe8\xe3b\x8d\xf8\xfb\xcb\xeb\x8e \xfc\x1fz\x96x<[\xac\x9f\x99\xb2\xbb\xce\x1eT\xaa\x05ci䘙#IB\x94\xb2\xd7M\x14~\xaagK\xd4\xfe\x06\x1f\xdfBM\x12\x8dm\xacQO\b&\x16D\x1ac\f5\xa7]\xfcQ\xdf\xf9\xd2k\x91J\xf1\x0e_\x9a\x90\x1a~\xb6\xaeK%\x1c\x18\xef\bp\x95\x91i㰹\xb7?\xcc\xda\xf1G\xee\xf0\xbb\x16\xc27\x8d\xed\xbf\x86>\xdc_:b\xd9.m\xe5'\xde\xfeQ\xc5\xe7t\x85\x97=\xcf\xf5\xbf\xbd\xdfC_\x90B\xafU,\n\xafZ\xa0%l\xaf\xe7\xe5\xf3/{\xf6\xaaK\xb8\xa6]H\xd7v\xa9m\x9e\x8a\xb6\xf3\xeal\xef\x91\xedR\\Z\xb0\xe6\xd4\xf9C\xf8t\xb3ͳ\xeb\xd4k\x1b<\x95\xaf_\xa3f\xa3\x16\xbc\xd3Sq\x0fY\x89\xbf\xbf\xcc\xee\x90\xfd\r}02R\xbe\u007fd$H5\xf6Q\xf9\xa5\xf3#wc\xf6\\\xac\xaes\x06\xd5l\x81\\\x9a9f\xd4H\x12\x18\xa5\xecuc/\xed\x9f\x1e=\x11\xea/\xfd$\xf4ܖ\xcf\xc9AE\xe5\x9e\r\xfd\xa7W-\x9a@Ԥ9P\x9fT<\xd6v\xf4QO\xe9[\xff\x84[\x89\x1djv\xbb\xf7F6\xee\xff \x14ڹ\xec\xd2W\x89\r_z\x90\x1a~\x8e\xaeK-ǧ\xfc\xc7mfL\v_U\xeceL\x12\x98\xf7\xf6\x1fP\u007f\x96~\x82?\x99\xb5\\\x19\b\x1dzt\xc1\x96k\xc8R\xe1\xe2\x96\xcaE\x9b\x8dk\xba\x11\xae/:\x8a^\xaf\xd0\xde\xf4\xc3'\xd6U\xac;\x156\x96\xa0\x9d\xcf\xfe|s[M\xe9\xb2-\xefQ\xed\xd2L\xecz쑍ok\r\xac*\xaf\xdcuzU\xe9\x16z6r\xc1\xa7+<1\r$\xd0_fw\xc8\xfe^\x8f\x8c\xcei\xaa\xb1\x0fJqY\xe9f\xebY+\xa3\xeb\x9cA5[ \x97f\x8e\x195\x92\x04F){ݘK\v\xab\xfb\xd9\xfeG<\x15\xfdx)Ġ\xa2\xf2\x9f\xec_\xb4l\xaf\xf66AL\x12\x035\xb1\xf3њ\xc3o\x95\xea\x8d\xc5\f5\xa7\xddSxu\xae\xeb7#$6|iAn\xf8g\x16\xafx\xfe\x991\x99=\xbc\xed\x89\xdd\U000e76ef*\x0e|\x15\x0e\u07fb\xbe\xeb\xd1d\x97=\xfd\x16R\x01q\x8f`<\xb7\v\xa6j\xa8宼\x93ß\xdd\xdf\xe5\r\xbf\xb5(\x03+\xf5\xb6~_\x00\nWZ\x0f|\xe2e\xfa-\xa4\x82\x84\u009f\xba\xa1\x96\xbb\xf2N\x0e\u007fvs\xb7\x92\u007f\x9fo\xfa\xf80\xf2)\xd5'\x1e\xc6\xd5Ƹ\x98~\v\xa9 \xa1\xf0\xa7n\xa8\xe5\xae<\x84\x1fH%\xe1\xfd\x15\a\xfa\xdf\xeb?P\x91\xf4\xaep\xfa-L\x1f\xfd\x12\x9cuR\x02rW\x1e\xc2\x0f\xa4\x96w\x9eZV\xba\xec\xe9\xe9\x1c\xb5N\xbf\x85\xe9\xa2]\x82\xbbc\x9d\x94\x82̕\x87\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0g\xf9-\xfe\x00\xc0Cn\xf8\x99\xba\xaeP\x87\xf6\x10\xaf\x8e\x14\xdd\x1e\x9d(6\xba.\x93\x03\x12<K\xfb=\x1eOń\xa8V\x8a\xe8\u05feNZ\xb93\xde{\xd7\xd8k\xfcAe\x1c&3\xe9\xa4Fו\x96m\x8c\x12k7ͣ.5\xfcl]W\xd0\xfb~@eR4w\x9a\xb0\xd1uq\xedVi\xf1,}>2rJ\xa0\b\x11\x12\xb7\xe5+\xf8\x8e畑\x91\x9f\xaf\xab\xb4>\xf2K(\xe6\"+\x9c֟c9\xc3H\x8d\xae+-\xdb\x18%\xd6n\x9aG]j\xf8ٺ\xae`\x06\x9e\xdcib\xaf\xeb\xe2٭\xd2\xf4\xa8\x15\x91\x1fHH\xfc\x96/\xfd\xa1\\_WXc\"\x14s\x91\x15\xfaS\xb1\x8bM\x03\xe2/\xe2\xc5A\x9a\xb6qB\xed\xa6wԥ\x86\x9f\xad\xeb\xcal\xf8\xedu]Iڭ\x92e\xda\xe1\x8f_\xab\x15y\"\xdf:\xeb\f\xc2\x16\xc8\n\x97<\x97\xf8\x153\x88\x94\x8d%\x95\xb4\x8c\xba\xdc\xf0\xab\xc4\xea\xba2\x1a~;]\x17\xc7n%\xf6,\x91\x02\xad(\xcf{<?\x8fH\x9d\x89\xd9h\x19\x14\x11~\xc3\v\xc5\x16s1\x9dW\\\xcb\x17\v=\xfcw\x17\xbcF\xf6\x8cӂ\xb9Ɩ\nף\xf6r\xd6\x1aӥQ\xd9\x16\x01i\xe32W\x88vt\t\xc5gL\xd3X\xf9\xa1\x03\xcb\xf4A\xe5\xb4KJ\xb1X-p\xb6\xb1\tǗfL\x9a\x83J\x99\xbbį\x1d\x93dG=~$\x87\x9f\xa5\xeb\nz\a\xde\xf0\x1e\xf7g\xe6z\x9f\x9d\xae\x8bg\xb7\x12y\x96H\x81\x96\x81~\"\xaaI\x9d\x89\xd9(\x19\x14\x11~\xd3\v\xc5\x16s1\x9dW<\xcb\x17\x93\xbb\x9eӡ\xe0\a\xeb\xd6\x04ɞ\xf1Z0\xd6\xd8R\xe1n\xa5~\xac\xc4\\cZ$\x16\x95m\x11\x906.s\x85hG\x97P|\xc6\x14\x94\xe1gn\xf6\xafÃ\xcan\x97\x94b\xb1[`nc\x02\xf6f1'\x89A%\xcd]\xc2\xd7\x0e\xb3\x0f\t\x8dz\x02H\x0e?K\xd7\x15\xf4v^U'\xbb2\x91~\x91\xae\x8be\xb7\xc2\xd8z\x96(ѕ\t\xf1\xe4hB\x1cEx\xa1\xcc\xf0\x13^(\xb6\x98\x8b\xe7\xbc\x12\x1e\xb4\x1b\xdc\xd5\xf6%\xab\xb4\xf7;\xf2\x99ּ\x16\xa2k̬\xc0^c\xa2\x94\x12\x94\x11\x186.r\x85\xccR\xa1\xf8\x8c#(+_\xa3\xb6\x16Z\xb5\x91\xd7.\xb1\xb1\xf8\x8a\xb3\xd8mL\xc0\xde,\xe48\x98\x83J\x98\xbb\xd8\xed\xf2\x1d]I\x8cz\x02\xc8\x0e?BV]\x17\n\x8fk\x93\x1dC\x82\xf9ҁH\xd7Ų[al=K\x94\xe8ʄ\f\xbf)\x8e\"\xbcPf\xf8I\xc9\x14S\xcc\xc5s^%\x12\xfe\xa3\u05ee]<\xa0}j4\xed\xf0\xb3ט(\xa5\x04e\x04\xa6\xfb\x8bX!\xb3T(>\xe3\b\xca\xca_\xc1?\xb5Ae\xb6Kl,\xbe\xe2,v\x1b\x9307\v9\x0eD\xf8\ts\x17\xb3]\xbe\xa3+\x89QO\x00\xa9\xe1g꺢\u007f\xf4\x9fdϔN\x84\xba.\x96\xdd\nc\xefY\"EW&d\xf8-\x93\xba\x17\xca\f?!\x99b\x8b\xb9xΫD¯\xed\xebv\xadB\xf1\xb5`\xfb2䬱YJ\t\xca\b\f\x1b\x17\xb9Bf\xa9P|\xc61\x8d\x99\x83\xcan\x97\xd8X|\xc5Y\xec6&`o\x16r\x92\b\xbfi\xeeb\xb7\xcbwt%3\xea\xf1#3\xfcl]\x17\x1a\xf0i\x93\x83>\xee\x8ciC\xa8\xebb٭0\xb6\x9e%Jte\xa2\xd5=\x1a\x13~\xd3\ve\x86\x9f\x90L\xb1\xc5\\<\xe7\x15\xcb\xf2\xc5&\x12\xfe\xd3\xf8uG\xf4\x8c\xdb\x02\xfd2\xb4T`\xaf1QJ\t\xca\b\x8c\xd74\xb9Bf\xa9P|ƩP\xae}f\x8b\a\x95\xdd.\xb1\xb1\xf8\x8a3\xdb\xf0\xb37\v9\x0e\xe6\xa0\x12\xf2\x1ev\xbb|GW\x12\xa3\x9e\x002\xc3\xcf\xd1u\xf9\xb4]\xfeT\xc7\xfb\xb6\xf3\xa6\x03\xb1\xae\x8be\xb7\xc2\xd8z\x96(ѕI\xc5a\xf5\xfdocL\xf8M/\x94\x19~\xc2\v\xc5\x16s\xf1\x9cW\xa4\xe5\xeb\xcek\x13\x88O\xa4\xd6\xdeG\xc2TϘ\x9e0\x8c\xf12dU`\xaf1QJ\t\xca\b\x8c8\x92+d\x96\n\xc5g\x9c\n\xe5\x8f\xe1s\xfe5[x\xed\x12\x1b\x8b\xd3\x02\x12\x84\x9f\xbdY\xc8q0\aU\x18~\xbe\xa3+\x89QO\x00\xa9\xe1g\xeb\xba\x02\u07be\x9b\x81\xcb\xed\xbe\xa4\xaf[$\x8dHׅ\xb7M\xac\xddJ\xe8Y\xa2DW&\x9b+_\u007fm#\x16<Q\xe2(S\x06\xa5\xdd\xe1wB\xb7S\x99^(\xb6\x98\x8b\xe7\xbc\"-_;=\xcf .!\xed\x0e\xbf\xb7\x9f\xf3\xbcN\xf6\xcc҂Q\xd9XcN\x05\xf6\x1a\x93\xa5\x84lˀv\x95EW\x88rt\t\xc5g\xec\n垧\xaf]ڌ\a\x95\xdd.)\xc5b\xb6\xc0\xde\xc6\x04\xbc\xcdb\xae\xb11\xa8\xa4\xb9K\xf8\xdaa\xf6\x01%2\xea\t 5\xfc\x1c]\xd7\xe4\xc0\xf1\x0e߸\xfc\xec\vu]l\xbb\x95гD\x89\xaeL&\xb6,x\xe4\xa9WԺ\x948ʔA폴\xab\xed\x9e\f/\x14[\xcc\xc5s^\x91\x96\xafӕ6w\x81\xea\xf7\xf6\x97\xaeӪ\x18=\xb3\xb4\x10\xc5\\cN\x05\xf6\x1a\x93\xa5\x84lˀ\xb4q\x99+D9\xba\x84\xe23v\x855m\xbb\x1e\xd1\a\x95\xdd.%\xc5b\xb5\xc0\xde\xc6\x04\xec\xcdB\xae\xb11\xa8\xa4\xb9K\xf8\xdaa\xf6\x01%2\xea\t 7\xfc3\x8bT꺒\xf6,\x95\xb7!@2Io\xac\xf4\x90\xb1\xee89\xfc\xa9\xfc.oҞ%\b\xbf|\x92\xdeX\xe9!c\xddqr\xf8SIҞ%\b\xbf|\x92\xdeX\xe9!c݁\xf0\xa7\x86$=KreP\x80N\x92\x1b+]d\xac;\x10\xfeT\x91\x94gI\xb6\f\n\xd0Ijc\xa5\x8f\fu\a\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\u009f\xd2[\xfc\x01`\xf6 7\xfcL]\x97ʍ\xbe\x8e\xee\xcbv3\xa6\x11{]\xd7\xd7\a\x96,xF\xff\xdeE\"\x9e%\x06\x91\xaf\x94z\x92W-Y|^\xfaӶ\xe3\xab\x1b'|\xd1U\xecʟb\xd6MR\x95\x95\xe8l\xc4f\x89B\xacqr+\x9f6flϤ\x86\x9f\xad\xeb\xc2O\xf1\x1e\xba=\xea\xbd-\x9a==\xd8\xea\xbaЏ\x96\x9c\xda_\xa1\u007f\xd32\x11\xcf\x12\x83\xf0\aڳ:>\xd0\x1ea\x10\xb7V\x8b\xc4\xea\xf3\xd2\x1e\f\x1dg\xdd\xf8\xe0\x8b\xaebW\xfe\xde\xc8FF]n\v\xec5\xe6\xe8\xd0b+X 6K\x14b\x8d\x93[y\x94\xd8f\x89\xbfn*z\x96\x16\xa4\x86\x9f\xad\xebB\x03\xed\x01\xfc\xc6pC0wz\xb0\xd7u\xdd\xf3\x9c@\xc6\xe3Q\xa7\xfd\xb8\x11\xd3\xc9\x11\xbfV\x8b\x86V\xfa\xc4<R\x96\")\xfd\x0f\xf7K\x86\x8c\x95\xdfɬ\xcbi\x81\xbd\xc6<\x1d\x1a\xa3\x02\t\xb5YL\x885Nj\xe5\x13\xda,\x89ԝ~\xcf҂\xd4\xf0\xb3u]\x01\xef\xfb\xc6\xdf\xe4c\xaf\xeb\x9a\xf0L\xebP߂\xb9\xdd\xe3\u007f\xca.M\xe6\xc2\xcf \xa1\xf0\xb3\xd7x\x83(\xfc\xec\xd98\x9be\xda\x11Kd\xb3$Rw\xfa=K\vrï\x12\xab\xeb\x1aj\x0fM\u007f\xa7\x9a,v\xba\xaeP\xa5~\x96\x8e\x8f\ax\xfe&\xa6-\x8aGd\xbbs\xb5Z\x13\xbb*K\x97<\xa3\xbd\x03E\xedV\x84K\x8bhA=N\u07bbl\xd1.\xeba?\xe9\x90\"\xea\n\xacYT\x05\xc3JFڭ8+\xaf\x86\xff\x90\xfa\x87\x05\xf4\x83o\rU\x96P\x03\xc6ѡ\x99k\xc1\x9e\x8d\xdc,\x9c5\xe6\xac<\x01c|\xd9K#ט\xd93\xa2\x05\xb6\u007f\f\x13۳\xf3\xeaܯD\xd4c\x99Br\xf8Y\xba\xae^ߍ\x93\xde\xe3\x17\xe2MPj\xb1\xd3u\xa1\x8fF\xfa=m#\xfa\x93\x1b\xd9\xfe&\xb6\xeb\x89Gd\xbb\xf3\xa4X\xefUlx\xfdb\x9b\a;\x9b\f\xbb\x15\xa1}\"Z@\x13\x8bV\x9d~\xe7)\x8f%\xfc\x84C\x8a\xa8+\xb2fQ\x15\f+\x19e\xcdb\xaf\xbc\x1a\xfe\xbb{=',\xcf#0TYB\r\x18G\x87f\xae\x05g\xa0\x88\xcd\xc2^c\xc4^y\x02\xd6\xf8\xb2\x97F\xae1\xb3gD\vl\xff\x18&\xb6g\xa1\x0fj\x0e\xdcE_\xb5-\x1a\xc9\xcc\v\x1f#9\xfc,]W\xb7\xa6\xeb:ޝ\x89A\x10麨\xe3\xcbX\xcf\x12\xdf\xf5\xc4\xc4\xfe\xb0?T\xf34~\xe0t\xff=\xdanE=9:\xda\xc2\xe6U!\xfc\xe4hK\xf8)7\x95QWh͢$S\x84\x95̰[a\x18\xf2*5\xfc'\xcac\xbe\x84n\xaa\xb2␁\x10\x87\xfdƂiÖ\xfda?{\x8d\x11s\xe5\tx\xe3\xcb\\\x9a\xb9Ɯ\x9eQ-0\xfdc\xccc\x926|\x88\xb1\x97\xf9\xc4xI\xc8\x0e?B1\xba._;~}\x05;\x86E3\xa6\x01\x91\xae\x8b\x1d~ó\xc4w=1\xb1\x0f\xffy\xf3)N\xa4݊\x15\xfe{\xfa#]\x8fZ\xcf\xf9I7\x95\xb14\xa15\x8b\x92L\x11V2ӥ\x85\x98\xf2\xaa\x9dmG\x19\xe7ބ*K\x98+2A\xe6\x82)Ö\xe0\x9c\x9f\xb9ƈ\xb9\xf2\x04\xbc\xf1e\x87\xdf\\cvϨ\x16\x98\xfe1f\xf8?\xf7|\x82B\x8f\xa4ȶ\x9d\x14R\xc3\xcf\xd6u\r\ua7ae\xc1^\xee|iC\xa8\xebb\x87\xdf\xd8\xd8|\xd7\x13\x13\xfb\xf0\x9f\xf0\x18/Q\xd2n\xc5\n\xffu\xcf\b\"J\xa3Pn*siBk\x16S2\x85L\xbb\x15\x86\xa1\xb0ع\xe4\x915\xb1롟\x1fh\xfe1a\xae\x98\t\xa2\r[\xf6\xe1\xe7\xac1s\xe5\tx\xe3\xcb\x0e\xbf\xa8g\xcc1\x13\xf7\f=}\x18]\\\x94\x89\xe3\xdd(2\xc3\xcf\xd1u\x8dvh\xef\t\x033Q\xd7%\b?\xdf\xf5\xc4\xc4\x12~\x8b}\xe9\x12\xb1\xe7'\xecV\xdaҢ\xfb\xf8H\v_{\xb4\x8bv\xd6\v~\x94\x9b\xca<\xed\x15Y\xb3b$S\xac(\xb0\xc2_\xf9ɝE\xb4U\x1aW0TYT\xd7YkL\x96\x9a\xed\xc6\x1a\xb6bf36\v{\x8d\x11s\xe5\tx\xe3\xcb\\\x9a\xb0g1- k]v\xf8ߩ\f\xed\x8f\xf3\x981=\xc8\f?G\xd75\xa5}\xd4\x17l\x97\u007f\x8b\x9fX\xd7%\b?\xedz\xb2\xf7c!r\xbb\xb3\xecK\xa1e[\xf0\x98\x1c:DۭH\x97\x96\xd1\xc2\xc6\x1a\xf5\xa8zb\x81%\xfc\x94\x9bʨ+\xb4f\x91ڧ\x84¯N\x9e/\xb5>\u007f\xd4Teš\x01c\xe9Ш\xb5`\xcffl\x16\xf6\x1a#\xe6\xca\x13\xf0Ɨ\xb94a\xcf\xc8\x16\x8c1\x13\xf6\f\u007fl\xf1Σѣ~\xe1k'\x1dH\r?[ׅ.\xb7_\x0e\x8cw\x9e\x94\u007f\x00$\xd2u闕\xaf\xe1\x03\x13\x8e\xbf\x89r=\xd9\xfa\xb1\xa2w\xf8]\xd3V\x93e_B\x97\x16\xac9u\xfe\x90v:OحL\x97\x16\xe1\xf3\xfa\xa4ⱶ\xa3\x8fF\f[\x06\x84C\x8a\xa8+\xb2f\x11\x15\x88u#\xedV̕\xbf7\xb2q\xff\a\xa1\xd0\xcee\x97\xbe\xa2Z3UYB\r\x98YJ\x0e*\xb1\x16\xecو\xcd\xc2^c\xce\xca\x130Ǘ\xb9\xb48zf\xb4\xc0\xf6\x8fqz\xa6\xf2\xf2\xe3ƅH\xfb\xd7N\x9a\x90\x1a~\x8e\xae\v\xdd\xee\xed8yY~\xf6E\xba\xae\xd0\"턾t\x02\xf1\xfdM\xa4\xeb\xc9֏E\xdf\xdbϲ/\xe1\xcf\xf9\x1f{d\xa3fi'\xecV\xa6K\x8b\xf4yM\xec|\xb4\xe6\xf0[\xa5\\\x87\x14QWd\xcd\"*\x10\xebFڭ\x98+\u007fJ[\x19\xac\xfd:J\xb5f\xaa\xb2\x84\x1a0\xc4ԡ\x11k\xc1\x9c\x8d\xdc,\xec5\xe6\xac<\x01s|\x99K\x8b\xa3gF\vl\xff\x18\xa7gxFs\xf3ٿv҄\xdc\xf0\xcf,R\xa9\xeb\x02\x80\x84\t\x95'\xef\xd9K\x05N\x0e?|\x97\x17\xc8(\xfd\x95q\xde\x1d\x96&\x9c\x1c~\x00\xc8\x1cm\xef\xa1\x1f\xb5\x89*\xa5\x17\b?\x00d\x80\x90g\xc3\xf3\xcb$[y\xad@\xf8\x01 \x13\xb4Ul\x99\x10\xd5I3\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10\xfeYA\xef\xe2I\xea\xffS\x8bm\x9e{\x04\xdfY\x00\xe2Bn\xf8Y\xba\xaeP\xa7W\xe7\xb8`f\xe9lSr\xbaEu\xa6K\xa3\xa2(y7E\xb5Z\x94fkI\xceAfMd\xeb\x1fK\xce\x16\x15\x97K+V\xa0\x15\xd7l@\x06\x91\x1a~\xa6\xae+\xe4\x1d\r\xa8\\\xf6^\x15\xcd.\x9b\x80?ך9\x9d\xc1Qfq2\x04\xfc\xfeVeHP\xa95\xa7#\xa6\xcc7\xb7\x95Q\x13c\xe3\x1fK\xcc\x16%ti\x91\xc4\n\xb4\xe2\x9a\r\xc8 R\xc3\xcf\xd6u\x8dk\x0f\xef\xed\xbc \x989\x13\xb8\xd8\xe1_X\xcf,N\x92aQ\xf8o\xbb\x9a\x18\xa5{\\\x01F\xa9\xc8?F>PJ\x84ХE\xc0\x14h\x89g\x032\x89\xd4\xf0\xb3u]\x1a\xbe7\xe4?\xc9G\f'\xfceu\xcc\xe2$\x11\x86\xbf\xb1\x88\xa52\v\x1652JE\xfe\xb1D\xc2/ti\x110\x05Z\xe2ـL\"7\xfc*\xb1\xba.\xcc\r/}AK\x02\xa1\xc2ܦ\xe2\xa2\xc1\xed\xee*|\x16RW\xe4*^\x89O<n\xccU\x94\x95\xa8XQ\xdc껑k{c\x91{\xa5zJ\xeeSO͛P\xb3\xfa\xb3\x1bObʴV:\x17\xe7\xcfߡeӿ\xbc8\u05fd\xa28f9\x1d\x85^\xfc+P\x10\x99\xaf\xc0\xba\xc36\xc3\x1fml\x9b\x92\xeb\xdd1?o\xb9^3T\x10\xdd\xf1\x8f\xed\xdbT\xbbvߦ\a\xfa\xff\xf6\xe4\xb1\xde\xfbI\xf1\xdf\x00\x00 \x00IDAT/\xed\xfcc\x183\xfcQ\xd3\x18\xa5\xe0\xfazo\xe5c\x87\x0fWV\xf4s\\Z\x14Q\xe7\x15)\xd0\"1\xcc]\xc0\x8cDr\xf8Y\xba.Lw\xf4\b@\"\x83\x05ʎ\xa5\x8a\xfb`a\v\x0e\xf7\x93\x83\xdd+s\x86\x11\n\x0f5\xe7\f\xa1\x0e\xa5\x13?Rإ\x94uu\x95卣\xe0\x85\xe2m\x93h\xb2\xb9\xc0\x1f\f^\xf0ϯ\xf2\xfb\xfd\x9aT\xb81g\xbb\xaf\xb5\xb0,\x8c#\xbc\xfe\x8d\x01\xaf[\x89\t\xe4\x13\xcar\xfc+\xd4Ѫ\xd3a\xada\x84\xdfh\xec\xc6\xf1\xb9JasK\x81~\x801\xaa\xe8O<G\x1f\xff\xd9K箜][\xfd;\xfd\xbf\x17\x98G\f\xb6\xfe1D\x84\xdf0\x8d\x91B\xaaКe\xa7\xda\xca+N?u\x82\xe3\xd2\"1\xdd_\xa4\u05cc\xc00w\x013\x12\xc9\xe1g\xe9\xbaP\xf4b\x80l\x8a֫\xa1\xf7\xa1\xc6'\xd5=\u007f7~G*{B+o\\8U\xac_Kw\x95\xe0\xc7P\xcf_\xacN6\xe3=\xfdz\xfdH\xdb8\xec\xf7)\xf8Jܰ҅Pk!^\x95Vw̃\x99n\x1f\xbc\xad\xfd\x9e\xbc\xad\x13s\x88\x13\r?\xd1\x18r\xb9\xd5\x01Y_\x18)\xd7\x1b@g\x1ap\xecϬ\x8e\xec\xf9\x03\xca\x1b֦\xc4\xfe1#\xfc\xa4i\xcc\x14R\xf5cw\xc0)\x8f\x1eW\x96K\x8b\x80r\u007f\xb1\x0f\xfbMs\x170\x03\x91\x1d~\x84bt]*\x03i\xffH\x8dEQ\x17\x1aR\x82\xa8\t_\xbe\x9bj]>\xaf r(\x1f*+\\\xa9\xd7Я\xb4y\x95)\x1c\xb5q\xf5\x00\\?@1\xc2_?/\x84)V\xdf\x13\x02E\xf3\xb6y\xdfgH\xe3#\xdcV\xa2ܶ\xfc%\x1a~\xa21\xe4\xc2?\x9a]Zyot\x8e/\x1b6\x1d;\xfb\xe9\x83o#\xf3\x05\xb4\xb7\t\v\"\xff\x98\x11~\xd24f\n\xa9^^\x84p\x90\xb5'\b\xb3]Z&\x94\xfb\x8b\x1d~\xd3\xdc\x05\xcc@\xa4\x86\x9f\xad\xebR\xe9\x90/\xecP)\xeaC\xc3j\xbep\xf8\x87\v\x8b\x9bN\xfa\xab\xf4\xf0\xa37\x94\xc8G\x0f\xfa\x05?\xbf\x82?\xda[\xb1\x03\xf5\xb9\xf5l\x1b\xe1/\x8b\xe4\x19\x1f1\x04\xbdu%\n>\x85\xe0\xe0\xf7\xe9\xf8\xad\u007f\x88\x86\x9flL[p$\xfcC\xc6\xe1\xfd\xfd\xb3/l\xad^\xdb\xf3 :_\xec\a$B\xff\x98\x11~\xd24fj)Nx\xbe\xc6;\xf3\x98=?\xa1\xf20\xa0\xdc_6\x17\xfc4s\x170\x03\x91\x19~\x8e\xae\v_\t\xb0\xee\r\xa5@\x84\xbfd1>\xec\xaf\xd3\xc3\x1f(\xdaS\xac_\x88t\xed\xc0?\xdb\x15\xfcG\x9f;\xd4\x18\xb9\xbe\xae\x85\xbf\x1d\x1f\x98\xcf\x1b\xd5Pk_\xc6\a\t\xc1\xae<ާ\xef|\xa2\xe1'\x1a\xa3\xc2\x1f\x8c~\xe6p\xebU5\xf6\xf7\xcf՞\xd1\xff\xdb\xec\x8a\xfd\x10@\xe8\x1f3\xc2O\x9a\xc6\xccl\xdf\xf1<}\xe7\xa3U\x9b\xf57i\x96K\x8b\x80r\u007f\xb1\xc3o\x9a\xbb\x80\x19\x88\xcc\xf0st]\xf8\x94?#/\x0f\"\xfc\xc58\xce\xe12-\xfc\xa1\xc5{ГK\xb5\u05ff\xab\x18\x9f\xb4\x96Ti\xc5n\x9f;r\xe5\xadJ-\x98T\xd4S\x95>E;_\xd9sP\x8d\xa2\xa2\xad\\\xd56\xebR\xa2\xe7\xfc\\\xa2\xe1'\x1a\xa3¯\x9e\x0f\xe8a쩾\x82\u007f\xed>\xa2\xfd/\\\xb2\x02Y\x11\xfbnj\xf0\x93\xa613\xdb\x1fz\x96x<[\"\x17\xeeX.-\x02\xca\xfd\xc5\x0e\xbfi\xee\x02f R\xc3\xcf\xd1u\xa1\x1b\xdeL|\xc8\u007f\xc3\xdd\x12\xecʽ\x1a\xac\xaf\n\xa8ѭk=X\xa6\xb8[\x86B\x17\xb6\x15\x06\xd0\xed\x82\xed\x17\xf0G}\xca\xf2\xa1\xc1\xc5n=\xbdM\xf3\"G\xfdj*[z\x97\xe6\xe3k\x94MJ}wo\xa3҉ß\xdf\xec;\xd9\x18\xbd2o\xb2R\x89\r\xa9\x89v\x87_\x8b\xdfO5\x16\xf0\xe76\x0e\xa1\xd1\xc6\\\xad\x18\xdd\xcc\xd1O&z\xaak{\xde}\xf7\xa5\xea1\xed\u007f-J\xec}\x86\"\xff\x18i\x8b2Lc\xa4\x90\xea\xa3\xf2K\xe7G\xeeF.Z\xb2\\Z$\xa6\xf3\x8a\x10h\x91\x10\xe6.`\x06\"5\xfc\\]\x17\xe3\xb2u\xda\t\x17*\xca\xf1\x02%\xbf\x1b\x9fe\x87[\xe6\xbb\n\xeb;湪\xfaԳ\xee\x1dh\xbb\xfaS\x8dqIs]A\xd1\xfa\xc8'\x117\x95'#\xb3\x86\xb6\xbb\U000ea1b5ɾ*\xb7{1\xde\xe7wV5\x17\xe7\x16U\xc5d?\xfa9?\x87\xc6ȉ\xbev\xcf`\xb4\xb1mjA\xeex\xbe\xfaS?\x8e\xd8\xf3=\xed\xec\xfe\xec\xee\x9eM\xb5\r\xbb\xf5\xec\xfb\xf3v\xc44&\xf2\x8fѶ\xa8\xa8i\x8c\x14R}P\x8a\xff\\\xbaY;\xe9g\xb9\xb4H\f\xe7\x15)\xd0\"!\xcc]\xc0\fDn\xf8g5AWl\xb2%\xb1\xdde\xfd8\xa4\xcb\xd5\x18{\xb44m\xff\xd8W\x15\a\xbe\n\x87\xef]\xdf\xf5(\\\xa0w\x00\x10\xfe\xb8\xe9v\xc7\xc6M\x16-Ŗ\xaf\xf4\x16\xb1\xbe\xd47\xed\xef\xf2\xbe\x1d\xb1Ɔ+\xcf\vj\x02Y\x00\x84?>\x9a\a\xd1R\xf6\x8d\xfe\xd9ć\x91\x0f\xf9>\xc1\xf7\xfa\x00\xd9\x0e\x84?.\x82J\xd96\xe6\xd7k\xb2\x8b\xf0\xfe\x8a\x03\xfd\xef\xf5\x1f\xa8H\xea\xb8\x01\x98e@\xf8\xe3\xa39\xbfꆨN6\xf0\xceS\xcbJ\x97=\r\a\xfd\x8e\x00\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\u009f}L\xfb\x16\u007f\xc0\x19\xc8\r?K\xd7EMf\b\x19b.\x84.\x94\xe5/\x1f\x12U\x9a>6\xba.\x11\xd30l\xcd\b]םRϚ8K/V2\x9e>\x12%\x03]\xcf\x04R\xc3\xcf\xd4u\x91\x93\x99B\x86\x98\v\r\xb8ֿQ\xefJ\xff3\xcamt]\"\xa6a\xd8J@\xd7\x15Հ\xa5\x81k\xfb-\x8f\x1b▞\xaf\xb0\x89\xf74\xc6a6!5\xfcl]\x171\x999\xd2/\xe6\n\x15\xe2's<Y\x94\xee\xef\x05\vt]\x02\x92\x95\xec$\xa2\xeb25`\xa9\xc7\xfa\xac1~i\xcc3\xd6)\x92\x1d\x87Y\x85\xd4\xf0\xb3u]VsWFH\xbf\x98\xcb\xeb\xc2_\xc9\x0f\xe4\xda=\xd7'\x15\bt]\x02\x92}\xd1'\xa2\xeb\xda0#\xc2oO\xb2\xe30\xab\x90\x1b~\xc4\xd2uY\xcc]Ҡ\xa4X\xe9\x17s=\xa1=\x06\x14U\xa5\xee턉\x9d\xae\x8b\x10s=\xef\xf1\xfc\\?\x19\x0e/)}\xe5\xb1e\x97\x0e-ڂW\x8e4lE}^\x1f\x95z<G'\xf6\xd6,xڲ\xb7\x8c[\xd7u^\xfd\xe3+\xa8M\xfdIk\xc0\x8cE 4\xf2TMi\xe535\x96\x16\xd8N14\xb1\xab\xb2t\xc93\xda;[\xb4\x0f\xea\xb1\xfa\xdee\x8bvE\x0e\xf0\xcdv\xc9R\x83{\xf8\x99d\xdaa?ݮ\x89#Lc\x92\xc3\xcf\xd4u\xd1\xe6.iPR\xac\xf4\x8b\xb9J\xf4'\x006\x96XgK-v\xba.B̥\x9f\xd5j'\xc3\xef-\xf2\xfc\xe4G\x9e\xcaז\x9c@\x94a\xcb\xf0y\x85\xfa\xfbkV=\xf2\xd8O\xf6zh\vH\xfc\xba\xae\xd0\a5\a\ue8af\xda\x16\x8d\x84(\r\x98\xb1\btݳ\xb7\xff\xe2\xe9J\x8f\xe5\xed\x85\xe9\x14C\xefUlx\xfdb\x9b\xe7\x04Շ\x89E\xabN\xbf\U000d49dcn\x97,%\xb8>2\xa2\xef۩v\t\x1ca\x1a\x93\x1c~\x96\xae\x8b6wɄ\x90b\xa5_\xcc\xe5\xd6u\x9bMn\xebl)E\xa0\xeb2\xc5\\\xc4㸗\xedUw\xcd\xef\xa0\xfd\xb8\xbai\xd8\"}^h\x83\xe7G\xc1\xc8Y\x9bAB\xba\xae6\xbc\xa7߫?M\xdc8\xec'\x16q\xaa\x12\x0f\xe7\xa9E\xf4\xa0\xb2\x9db\xa1\x9a\xa7q\xbb\xfd\xf7\xa8>l^\xa5\x16\x86וӳ\x11\xa5\x16\x16D\x0e\xec\x89!!p\x84iLv\xf8Q\xac\xae\x8b6wɄ\x90b\xa5_\xccU\xb2^\xfbU\x9f\xde=\xbf@\xd7e\x8a\xb9\xc8\xf0\xf7\xabA\t\xa2\xc3\xcf!ҰE\xfa\xbcІ\xf2ض\x12\xd2u}\xeeQ\xf7\xff\x8f\\Ҋ\x8d\xf0\x13\x8b\xf8|Y\xcd\xf3\xa7?\xb2\x0e*\xdb)v\xde|Șه{\x9e\xd3x\xeah95\x1bYj\xc1\b\xbf9$\x04\x8e0\x8dI\r?S\xd7e1wɄPc\xa4_\xcc\xf5\x84~\xe9 \"\x03M\x13\"]\x17a\xdf \xc2\u007f\x11]+E\xe8\xe5碥\x9aa\x8b\xf4y\xa1\r\x1bb\xdbJL\xd7\xf5\xf4atq\x91>\xa8F\xf8\xc9E\xdc;\xbdk\x8dg\xc9\xebt\x03<\xa7\x98\xf1\x1ea\xf6\xe1\xbag\x04E+\x98\xb3\x91\xa5\x16\x8c\xf0\xb3\x84$\xce0\x8d\xc9\f?[\xd7E\x9b\xbb\xa4B\x86?\xedb.\xafv pSI\xeb\xd5~\x91\xae\xcb\x1a\xfe\xa3\xd1\xf0\x97G\xc3o\x18\xb6H\x9f\x17\xf3\x02}b\xba\xaew*C\xfb#\x0e!C\x03F,\xe2:\xbe\x1b\xe9^\xff\x82ST\x03l\xa7\xd8%b\xcfo\xf4\xe1k\x8f6\xabviϜ\x8d,\xb5 \b\xbf\x13Lc2\xc3\xcf\xd1uQ\xe6.\xa9\x90\xe1O\xbb\x98+T\x88\xdfH\xea\n\xd3yiC\xa8\xeb\"^\xe9\x15\x87շ\xe3\x8d1\xe17\f[\xa4ϋ\x19\xfe\xc4t]\xa1\xcaw\x1eՏ\xfaM\r\x18\xb1\x886\xed\xe4\x1dm\xa1\x8fV\xd8N\xb1в-x\x10\x0f\x1d\xa2\xfa\xb0\xb1F=D\x9fXPN\xcfF\x94Z\x10\x84\xdf\t\xa61\xa9\xe1g\xeb\xba(s\x97D()V\xfa\xc5\\\xa8\xcfU\u007f\xb2\xde\xd5gWe\xba\bt]\x94wks\xe5\xeb\xafm\xf4\x94\xbe\xf5O\xff\xf4\xe8\x89P\u007f\xe9'\xa1\xe7\xb6|\x8eHÖ\xe1\xf3\n_\xd3.\xd0ǜ\xf5'\xa6\xebz\xf9\xf1\xe8ռ\xa8\x06\x8cX\x84\x1a\xfe\x8a\xb6\xf3\xea\xe4{t\vL\xa7\x18\xba\xb4`ͩ\xf3\x87\xb4\xd3y\xb3\x0f\x9fT<\xd6v\xf4Q\xbcBd\xbbd\xa9I胑\x91\xf2\xfd##A\xae\x8a\xcc\x11\xa61\xa9\xe1\xe7\xe8\xbaHs\x97D()V\xfa\xc5\\\b]X\x9aW\x96\xd6\xdb\x18E\xba.ʻ5\xb1e\xc1#O\xbd\xa2N.\xf1x\xfa\x1f\xf1T\xf4k\xa7֤a+\xea\xf3\xfa\x888\xf9'IL\xd75aȾ\xa2\x1a0d.\x02\xfd|s[M\xe9\xb2-\x96쳝b\xf8s\xfe\xc7\x1e\xd9\xf86\xfe\xbb\xd1\a\xb5p\xe7\xa35\x87\xdf*\xd5*\x18\xedR\xa5\x06\xd7#\x17\x05NsUd\x8e0\x8d\xc9\r\xff,!\x83b\xaei1m]W:\t\x95\xc7$\x1b\xc8,\x10~\x06\x99\x14sM\x87\x19\xfd]\xde\xfeJ\xe9\x17t\x01{ \xfcV\x9c!\xe6\x92L\xdb{\xe8GN\xb8[~v\x01\xe1\xb7\xe0\x101\x97\\B\x9e\r\xcf/\xcb\xea\xfbef%\x10~+N\x11sI\xa5\xadb˄\xa8\x0e \x1b\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b\xff̾#\x1e\x00҆\xdc\xf0\xb3u]\u1afd\xed'3vW\x1d\xdfn\xf5vi䛟\xa5o\xcb\xf57\xf1\x97FH\xb1b\xfdXl\xf8\x8d\xd9\x1a\xab\xf8\x15\xe2.ݯ\x0e]ńM\x05\vlٖ\x90\xf4\xce\x16ז'\xb6\x85x5g\x0eR\xc3\xcf\xd6u\x85}\x1d\xa3\xb7/\xb7_\x16͝&\xf8v\xab\xd7=##\xa7<'FF<\xaf'\xefo\x12\xba\xa9\x18\x15\xf8K#\xa4X\xb1~,6\xfc\xc6l\x8dU\xfc\nf)\xd9uF\xdd\xcf\xf1\xf0}`S\xc1\n[\xb6%$-\xb3E\xd7-\xae-Ol\v\xd1j\n_\x0f\x12\x91\x1a~\xb6\xae\xeb\xfdv\xac\xeb\xb8ٞ\x99o\xd3\xd8حN\x94\xe2\xe7?\xab\xafފ\x13\xd1':&\x8e\xd0MŬ\xc0Y\x1a!\xc5b\xfa\xb1\xd8p\xbb.<n`W0J\xa9\xae3\xeb^3\xc3/^Z2f\x1d\x8dt\xccf\xae\x9bx\xcbS\xdbB\xb0\x9a\xc2׃D\xa4\x86\x9f\xad\xeb\xf2\xe9O\xb6\xea\xcc̮\xdf\xc6n\x15\x9a\x88\xbcz'B\xf1\xbc\x04\xd8\b\xddT\xcc\n\x9c\xa5\x11O\xcac>4\x8fM\xb2]\x17\"\\7*\xfcq\x90\x8e\x14\xf3\xb1\x9dmC\x02\xe1O`[\xc41f\xf2\x90\x1b~\x95X]\xd7I\xfd\xd1V\xbd>\xc1\x9ci\xc1\xcen\x851^\xbd\xe5\x87M\xab\x93)\x83\"\x89\x8a\xa3L\x13\x16\"\xdcT\xcf{JO\x1cxL3@\xb1+P\x18\xb6(\xa2.!Ţ\xfdX\"\xad\x16S=e\x1a\xab8\xaa,\xb6\xd2\xca,%\xbbN4\x16ܵ\xac\xb4fg\xf4\xf1\xba\xd1\xe1#*\xac\x89̷\x19\xffG\xa0\xd5\"\a\x95\xad\xd5b8\xba(\xff\x98\xd9\x1d\xaa\x05\xceҢP\x9bE\xb0\xe5\xc9ma\xae&\xb5-\x8c\xf1\xe5m\xee\f!9\xfc,]ׅN\xed\f\xa0\xe3\xa4\xfd\xac\xe9\xc1\xcen\x851\xc3\xefY\xd3\xff\xce\x12\xedm۔A\x91\x18\xe2(\u0084E\xb8\xa9\xb0\x17\xaa浶\x9a\x8aO8\x15(\f[\x14Q\x97\x94b\x91~,\xa1V\x8b\xad\x9e2\x8cU<U\x16[ie\x94R]7\x1b;\xef9\xf0^\xffN\x8f\xfe\x88>s\xf8\xcc\n\xf8\xc1\x99##\x1b=\xf8\x11\xfdB\xad\x961\xa8\x1c\xad\x16\xd3\xd1E\xfa\xc7\xcc\xee\x90-p\x96f@\xad\x9bh˓\xdb\xc2XMr[\x98\xe3\xcb\xdb\xdc\x19Br\xf8Y\xba\xae`\x87o2\x14\xe8\xf5v\x8b\xe6M\x03\x02\xbb\x15\x19\xfe%_\xab\x1b\x1f[\x9d(\x8f\x95\x01)\xaf\"\x9f\x06M\x1c>֨\xeb}\xaff#\xb7\x02\x01a\x8b\"\xeb\xb2\x0e\xfb\x85Z-\xbez*\xf2\xf4j\xb6*\x8b\xa8`QZEK\xe9\xaeGJC\xfd\xf8\xad|]\xe4i\x9f\xe4a\u007f\xa4B\x9b\xba\x1b\x0e\xef\xd7D{B\xad\x165\xa8,\xad\x16\xdb\xd1E\xf8\xc7\xc8\xee\x98-\xf0%^\x06\xc4v\x13ly\xcba\xbf9:\xd1mA\x8d\xaf\xa3\x0f\xfbQ\x8c\xae\vM\xf9ԃ\x80!_\xafh\xc64 \xb0[\x91\xe1\xc7o\rZ\x06)\x8f\x95\x01)\xaf\xe2\x84_\xfb\x1cQ3@\x89\xc3oڢD\xe1\x17j\xb5\xf8\xea\xa9\xc8딭\xca\"*X\x94V\xb6\xe1G_\x9fz\xfa\xf1E\x1e}4X\xe1W\t\xed\xd2R$\xd6jQ\x83\xca\xd0j\xb1\x1d]\x94\u007f\x8c\xe8\x8eт\x8d\xc4ˀ\xd8n\x82-\xcf\r\u007ft[P\xe3\xeb\xd8\xf03u]\xda\x1f\xa6¨S\xbe\xabOh\xb7\"\xc3od\x90\xf2X\x19\x90\xf2*N\xf8\xb5W\x85f\x80\x12\x87\x9f]\x97\x15~\xa1V\x8b\xaf\x9e\x8a\xbeN\x99\xaa,\xb2\x02-\xb6\xb0\r\xff\xb5%5\x87\xdf\x1e\xd9b\x17\xfe\xd03\xa5\xdac\xb7\xc5Z-ޠFa;\xbaH\xff\x18\xd9\x1d\xa3\x05\x1b\x89\x97\x81e\xbb\xd9lyn\xf8\x8dmA\x8e\xafS\xc3\xcf\xd6u\xa9/\x06<u\xd3K\xd9\xec\xe5 \xb2[1\xc3Oy\xac\fHy\x95V\xf7(\x91m\xec\xa6B\xe5\xda\xf5D\xcd\x00Ů@@آȺ\xac\xf0\v\xb5Z|\xf5T\xe4u\xcaVe\x11\x15l\xc3\x1f\xedz\xa4t\xcdF\xbc9wل?\xb4\xb9\xfc\xbc>%\xd4j\xc5\f\xaa%\xaflG\x17\xa9 \"\xbbc\xb4`#\xf12 \xb6\x9b`\xcbs\xc3\x1f\xdd\x16\xd4\xf827w\x86\x90\x19~\x8e\xae\xeb\x86wR=5:>(\x989\r\b\xedV\xcc\xf0S\x1e+\x03R^e\x9a\xb0\b7\x95z\xee\x88/p<\xbe\x85[\x81\x80\xb0E\x91uY\xe1\x17j\xb5\xf8\xea\xa9\xe8Y8S\x95ET\xe0\x85\x9f\xeaz\xa4\xb4\x06\xf7 \xbc\x8e\x1f\xfe{\x1b*\xf0~\xf7<m\x04ck\xb5\xc8Ae\x85\x9f\xe3\xe8\"\xc2Ov\xc7l\x81^ڝ6\xc3\xfdgBl7\xc1\x96\x17\x86\x9f\x1a_\xe6\xe6\xce\x10R\xc3\xcf\xd6u\xdd\xf4\x0e\a\xde\xef\xf4e\xe0\x1e\x1f\x81\xddJ\xe5\xc3S\x9e\x13בEteʠHLq\x94i\xc2B\xf8U\x13uS\xe1\x8b\xee\xa7W-\x9a\xe0V  lQf]B\x8aE\xfa\xb1\x84Z-\xa6z\xca4VqTYl\xa5\x151\x1b\xd1u\xaa\xb1]\xa7^\xdb\xe0\xa9|\xfd\x9a~\x87\xdf\t\xadCf\x85{\xeb<\xaf\xe1\xcb\xfd\ap\x9aDZ-sP9Z-\xa6\xa3\x8b\xf4\x8f\x99\xdd![\xa0\x97\xb6\xd3øS2\xban\xe2-Ol\vs5\xc9mA\x8d/ssg\b\xa9\xe1\xe7\xe8\xbaF\xbb;|\xa3q\xdc\xff\x95jDv+\xb5\x93\xf8sۊ\xa0\xd5\x16eʠ\bHqTԄ\x85\x9b0\xdcT\xe5?ٿ(b\x80bW  lQF]B\x8aE\xfb\xb1DZ-\xa6z\xca4VqTYl\xa5\x151\x1b\xd1u\xa24|bUy\xe5\xaeӫJ\xb7h\xf7\xf6cv\x91\x15>\x8a~aB\xbb\xad@\xa0\xd52\a\x95\xa7\xd5b8\xba¤\u007f\xcc\xec\x0e\xed*#\x97v\xba\xc2c\x1d\u007fs݄[\x9e\xdc\x16\xc4j\xea\x13ڶ\xa0Ɨ\xb9\xb93\x84\xdc\xf0\xcf,$ۭ\xca\xdb\x100#y;\xf6\x83\x10G\xe0\xe4\xf0K\xfe./\x84\u007ff\x12~k\x91\x84\xad?\x13qr\xf8%\x03៙ܭ\x8c\xbdU\xdb\x19@\xf8%\xa1_8\x02\x80\x99\x03\x84_\x12څ\xa3\x99\xf1\xf1.\x00h@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8e\xdf\xe2\x0f\x003\x04\xb9\xe1't]\xa4\xa3+\xd0\xdbї\x81\xe7\xf8\xe8\xf0u]\x16R&b\x8a\xcb\x00\x95\x02L!\x15\xd1\xf5$\x84_@\x96\"5\xfc\x84\xae\x8btt\x05\xda\xfd\xb7\xfd\xed\x99J?_ׅ\x84B\xaa\xe4\x88\xcb\x00\xc5$Aד!\xa4\"\xba\x9e\x84\xf0\v\xc8R\xa4\x86\x9f\xd0u\x11\x8e\xae\xf0q\xfc\xe8\xce\v\xc73\xb3\x0f\xb2\xd1u\xa1x\x84TI\x91\xec\x17\xfc\x12u=\x19O\xbd2\xba\x9e\x9c\xf0\v\xc8J\xa4\x86\x9f\xd0u\x11\x8e\xae\x1b\xed\xf8\x15\x18lό\xa7\xd7Fׅ\xd2\xf6\xac\xd5dßhwb\x9fO\x9b\x9c\xf0\v\xc8J\xe4\x86_%\xa2\xeb\"\x1c]\x03\xfa\xfb\x80/\x03O\xf0\xb4\xd7u1\x85T\x94\f\x8am\ue88dU&\x13\xbb*K\x97<\x83\xdf`L\x03\x94Y\x97\x14<Q-Dg\xa3]O\"G\x97)\xa42\x1dR\x89\t\xbf\x98\x12/ \x8b\x90\x1c~C\xd7E8\xbaN\xea\x0f쿐\ti\x87\xad\xae\x8b-\xa4\"ePl\u007f\x13m\xac2x\xafb\xc3\xeb\x17\xdb4U\x8di\x802뒂'\xb2\x05c6\xaa;\"G\x17)\xa42UY\x89\b\xbf8\x12/ {\x90\x1c~C\xd7E8\xba:\x87\xb5\xbf\fw\nfM\a\"]\x17KKAȠ\xd8\xfe&\xdaXe\x94\xd6<\x8d\x9f\xa0ݏ\xaf\xb0\x99\x06(\xaa\xae!x\"J\xc9\xd9\xcc\xee\b\x1d]\x16!\x95\xf1<\xe9\xf8\x85_|\x89\x17\x90%\xc8\x0e?\x8a<\xb7\x9fptE\xce\x00\x063!\xea\x14麘\xe17eP\x1c\u007f\x13e\xac\x8ar\xdec\x9e\b\x98\x06(\xaa\xae)\xdb2K\xc9\xd9\xcc\xee\x88\x1c]V!\x95m\xf8ٍ\xf1%^@\x96 5\xfc\xa6\xaeK\xfb_\xc4\xd15\xa0\xbb\xb9{3p\xce/\xd4u1\xc3oʠ\xd8\xfe&\xdaX\x15\xe5\x84\xc7̑遠\xea\x1a\x82'\xa2\x94\x9c\xcd\xec\x8e\xc8\xd1e\x15Rن\x9f\xd3\x18W\xe2\x05d\t2\xc3O\xe8\xba\x10\xe1\xe8\xba\xe1\xc5G\xac\xda\a\x80\xb2\x11\xea\xbaXB*\xc2\a\xc3\xf67\xd1ƪ(\x97\xc8=\xbf\x11~\xaa\xae\x91m\xa2\xf4R̞\x1fwG\xe4\xe8\xb2\n\xa9l\xc3\xcfn\x8c/\xf1\x02\xb2\x04\x99\xe1'u]\x84\xa3+\xac\xfd\x1c\xcc\xc0\xe7\xfcb]\x17KHE\x84\x9f\xedo\xa2\x8dUQB˶\xe0D\x1f\xc2\x1f)\x98\xe1\xa7\xea\x1a\xc1#J\xc9\xd9\xcc\xee\b\x1d]\x16\xfd\x95m\xf8ٍ\xd1\x12\xaf;\xafM  ː\x1a~B\xd7E:\xba\x02탷\a3q\x87\x9fX\xd7\xc5\x10R\x912(\xb6\xbf\x890V\x91\\Z\xb0\xe6\xd4\xf9C\xea\xc98i\x802\xeb҂'\xb3\x05c6\xb2;BG\x17!\xa4\"\\Z\x89\b\xbfh\x89\xd7N\xcf3\b\xc82\xa4\x86\x9f\xd4u\x91\x8e\xae@_{o\x06\xb2/\xd6u1\x84T\x94\f\x8am\xee\"\x8cU\x14\x13\xbb\x1e{d\xe3۴\x01ʬK\n\x9e\xa8\x16\xa2\xb3\x91\xdd\x11;\xbaL!\x95\xe9\x90JH\xf8EK\xbcNW\x9e\xb6.\x01\x98\xed\xc8\r\xff\xccB\xb2\xae\v\x00f\x16N\x0e?|\x97\x17p4N\x0e?\x008\x1a\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b\xfft\ta\x8c_\x000k\x80\xf0O\x93\v9\x8a\xa2\xe4\x05\x83y\xea\xaf\x1c\xbf\xa86\x00\xcc\x1c \xfcӤ[\xf1\r\x0f\x8f#4><\xecS\xbaE\xb5\x01`\xe6 7\xfc\x1c]\x17B\x83\x19x\x8cO\"lSr8\xc1\xeeV\x8c/#\a\xf4\xf0\xf3\xeb\x02\xc0LBj\xf89\xba.\xfc\x87a\xfb93M\xc0\x9f\xdb\xcc\xfeKl\xf8\xb9u\aG\x99\xc5\x00\x90\x19\xa4\x86\x9f\xad\xebR\xe3\xd2=\xd3Ï\x90+\xee\xf0s\xeb.\xacg\x16\x03@f\x90\x1a~\xb6\xae\v\rz\a\u06dd\x10\xfe\xb2:f1\x00d\x06\xb9\xe1G,]\x17\n\x05\xa3\xe2\x0e\xa9t+\x8aҌ\x9a՟\xdd(XW\xe4*^yU-\xbd:WQ\xf6\xdc\\?/o9\xfd\xc1\x9dk{c\x91{\xe5MF+\x8c\xf0G\xeb\xfa\xd4ƛ\xf4E\xe0IL\x99V\xa3sq\xfe\xfc\x1d\xb4f\x03\x00$#9\xfc,]\x17&\x13\xe1\x0f\xfa\v\xf6L\xa2\xc9=n\u007fPM铃\xdd+s\x86\U0007314f\x17\xcf/(ޱ\xde\f\xb5\x86K)\xeb\xea*\xcb\x1b\xb7\xb6\xc2\f\u007f\xb4n\xf0B\xf16u\x11\xcd\x05\xfe`\xf0\x82\u007f~\x95\xdf\xef\u05eel6\xe6l\xf7\xb5\x16\x96\xc9\u007f^1\x00\x98H\x0e?Kׅ\xc9D\xf8\xd5\f\xe2\x93\xf0\xfaF\xf5G\xb0\x1b\xbf#\x95=\xa1\x15\x97)Kc\xf4W\xc8U\x82\xef䙿\xd8\xda\x063\xfcf\xddf\xbc\xa7_ߨ\x15\x1b\x87\xfd>\xa5C\xfd9\xact!\x00\xc8\x1c\xb2Ïbu]\x98̄\u007f0/\x88\x82y\x9aId\xaau\xf9\xbc\x82\xc81y\x99\x8b\xf1(aW\x13\xfe\xe9U\xa6,\xe5\xcc\xf0\x9bu\x03\xca8\n\x15\fh\xc5F\xf8\xeb\xe7i\xf7\x03\x167\"\x00\xc8\x1cR\xc3\xcf\xd6ua2\x13\xfe\x90\xfb$\xeau\xe3\xce\f\x17\x167\x9d\xf4WE\xc2_ƨ\xab_\xc4\xf3+֏\xeb\xf8\x17\xfc\xf4\xba+v\xa0>\xb7~\xf9\xc0\b\u007fY\xe4\xfc\xff\t\x04\x00\x99Cf\xf89\xba.Lf\u008f\xb6?\x81\x9e؎'J\x16\xe3\xa3\xfc\xbaH\xf8YW\xe5];\xf0\xcfv\xc5z\x95\x8e\x19~\xa2\xae\xcf\x1dj\x8c\xec\xe1\xb5v\xb1\x9cd\xfd\xbcQ\r\xebQ\x04\x00\xc8Df\xf89\xba.L\x86\xc2?\xe4\n\xb8\x86\xf0D1\xcee\xb8\xcc.\xfc\xc5\xf8<\xbe\xa4\xcaZ\xce\f?Q7\xe4\xf6\xb9#kY\xa5\x16L\xe2:}z\xc5=\a\xad\x8d\x01\x80D\xa4\x86\x9f\xa3\xeb\n\x05\x02\x1d\x83\x81I\xd1\xdci \\\xb4\xbcH;\x05iV\xeaZ\x0f\x96)\ue5a1АvU\xfe\xb6\xb5\xaaKY>4\xb8\xd8\x1dSξ\xdaO\xd4m\x9a\x179\xeaGͮ\x96ޥ\xf9\xb8z\x93R\xdf\xddۨtZ\x1b\x03\x00\x89H\r?G\xd7u٫\x91\x89\x8f\xbd[\\-\xda\xefp\xcb|Wa}\xc7<W\xd5\xd5\x1c\xedt|\x85\xb5fIs]A\xd1\xfa\xd8+\x81\xdd\xca\xcd\xe8WzoF\xc3Oս\xa9<\x19\xa9\x1a\xda\xeeΫ\xd2\x0fq\xfa\xaa\xdc\xee\xc5}1\x8d\x01\x80D\xe4\x86?\v\xd1nމ|\xa5W\xf11*\x04]\x83\b\x00f \x10\xfei\x12\xba:\x1c\xfdJ\xef\xf0U\xd6\xd3<\xbaݬR\x00\xc88\x10\xfe\xb4\xd2<\x88\x96r\xbe\x14\x00\x00\x19\x06\u009fN\x82Jٶ\xa2L\\\xcb\x00\x001\x10\xfe\xb4Ҝ_5\xc3\x1fS\x028\x17\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\xb9\xe1g뺂\xfe\xee\xf6^\xe6\x97b\x00\x00H\x1bR\xc3\xcf\xd6u\x05;z\xc7o_\xee\xe8\x85\xf4\x03\x80L\xa4\x86\x9f\xad\xeb\x1a\xec\xc6\xcf\xf4\x98\x8az\xfb\x00\x00\x90\x82\xd4\xf0\xb3u]'\xf5\xe7\xdf\f\xb2\x9e\x84\x01\x00@\xba\x90\x1b~\xc4\xd2u\x05\xf4\xe7]]x\xc3n6\x00\x00R\x8c\xe4\xf0\xf3t]\b\x85\x8f\xfb\xf9\xb3\x01\x00\x90r$\x87\x9f\xa7\xebR\xdf\r:\xe0)\xf6\x00 \x13\xd9\xe1Gl]\x17\x1a\xf2\xc6<\x14\x1b\x00\x80t\"5\xfc\\]Wh\xd0\v\x0f\xbc\x01\x00\xb9\xc8\f?W\xd7\x15\xf4u2Ԙ\x00\x00\xa4\x13\x99\xe1\xe7麦\xbaN\xe2\xdb~\xe0&\x1f\x00\x90\x89\xd4\xf0\xb3u]\x81\xf6\xaeہ@\xe0\x82q\xed\x0f\x00\x00\tH\r?[\xd7էۺ\xbcp\x93\x0f\x00\xc8Dn\xf8\x01\x00\x981@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\xb3\x9a\xb0\xa8\x02\xe0` \xfc\xd9K\xa0\xb1PyBT\tp.\x10\xfe\xac%\\R\xe2\x1d\x80\x87\xa4\x00\\䆟\xad\xeb\"Je3\xb5\xad0oE\x9c\xc7\xc6\x03\x85\xb3\xebK\xc7W\x95>Q\x15\xc0\xd1H\r?[\xd7E\x94Jgi\xa1\xb71/\xce\x05\xfb\xf2g\x97Y`X\x81\x87\xa1\x03vH\r?[\xd7E\x94\xcafJiE\xe18\xb3?뮞\r+C\xa2*\x80\xa3\x91\x1a~\xb6\xae\x8b(\x95\xcdMev\x1d\xc9'\x04\x84\x1f\xb0Gn\xf8\x11K\xd7E\x94J%\xe4V4vh\xffk-\xcb+kU\u007f_\x9d\xab({n\xae\x9f\x97\xb7\x9cz\xa0h0OQr\x8e3Z1\xb9]\xe7\xce-\\\x11\xf3\x16\xd6Q\xe8ſ\x02\x05\xfaҔ\x02\xb2\x06\xb9\xb4`]\x91\xabx\xe5U\xb5t\x9b\x92\xeb\xdd1?o\xb9Vsj\xbd\xbbx\xc7\x0ew>~\xc4a\xe7\xe2\xfc\xf9;\xacG*c\xfb6ծݷ遥\x18\rB\xf8\x01[$\x87\x9f\xad\xeb2J\xe5\xf2\xbe\xbfKi\xf6\xfb\xb5\x885\xba\xf6\xf8\xf6\xb8\xd6\xe3g\v\x1f/\x9e_P\xbcc\xbdB\xc7\xf8\xb2\xdf\xefjf6\x13a0\xbf\xace\xa0Yi\xb1\x96?\xa1,ǿB\x1d\xad:\x1d\xe4\x9b\n\xb94\x9f\xf2\xe4`\xf7ʜa\x84n\x1c\x9f\xab\x146\xb7\x14\xd4\xe1\x1a%E\xadͮ\xbc\xf6\xe5jÍ9\xdb}\xad\x85e\xf4\xbb\xe4\xc7\u007f\xf6ҹ+g\xd7V\xff\x8e*\rM\x0e.t\xcb\x1fR`6!9\xfc\x1c]W\xb4T6\xc6a\u007f\x9fve\\\xff\x89ʔ\xa5\xc1\xc8\xc9\bE\x9e]\xf8C\xc5\xf8P!\xd4\x1d#\x1d\xbb}Pw\x11M\xde֙\xb4\xfc\xddXZ\xb0\x1b/\xb2L\xfbd\xde\xe5V\xdfz\xd6\x17\xaaS]\x8az,Ъ\x8c\xab\x93>\xa5\x03\xe1\xa3\xf9.j\xfe3\r8\xf6gV\xd3{\xfe'\xd4c\x8c,>\xa5\x01R\x81\xec\xf0#\x8e\xae+R*\x19#\xfc\x8d%گ\x92F\xfc\xb3\xccž\xfc`\x1b~\x9f\xf2\xbe\xcd_\xd5\xf7\x00%\x8a\xc5Kf.m\xaau\xf9\xbc\x02\xa5\fO\xbapG\x9a]\xea\x8f&7\xc2\xfd\xc4\xe3T?/\x84)n\xa4\xe6\xff\xb2aӱ\xb3\x9f>\xf8\x96*D\x81>o\t\xec\xf9\x01[\xa4\x86\x9f\xad\xeb\xa2K\xa5b\x84\u007f\xf1J\xed\u05ca\x85\xf8gY\x19\xbb\xb6m\xf8[\x14\x81t\xc4\xefӱ~\xfef,m\xb8\xb0\xb8餿J\x0f?^\x94\x16\xfe\x16e\n\x1f\x92\xe0=\u007fY\xe4\xdd\xc3r\xd7\xde\xfd\xb3/l\xad^\xdb\x13s\xce\xefW\x86\xadE\x00@ 3\xfcl]\x17U*\x19s\xcf?O\xfb5O\xdf\xf3ױkۆ\u007f@\x19\xb5\xf9\xab\r\xc6\xd2J\x16\xe3=u\x9d%\xfc\x81\x9c\x15\x81\xab\xf3\x17\xe3\xb1Y?oT\x83>\xb3\xb8\xf5\xaa\x1a\xfb\xfb\xe7j\xcf \vp\xb5\x1f\xb0Gf\xf89\xba.\xa2T6F\xf8}ډt\x97\xfe_q\xf8o7\xc7$=XT\x85\xdf϶o\xb7\xfe!z\xce\xcf\xc3XZ1\x9e\b\x97Y\xc2?\xaa\x14*J\x95vfЧhWH\xf6\x1c\xa4\xe6奄\x82\u007f\xed>\x82,@\xf8\x01{\xa4\x86\x9f\xad\xeb\"J\xe5\xa2_\xed\x1f\xd2\x0e8\xd6\xe74\xf9\x9ar\xf0\xd5\xfe!\xff\xfc*\xbf\xdf\x1aX\xb5\xd8\xefj\xf4\xfb\xf5N\xaeT\xf2cz;\xf8\xbd\x12\xafo\xbb\xd2n-_\xa9\xac\xb0\x16\x99\x90KkV\xeaZ\x0f\x96)\ue5a1\x80?\xb7q\b\x8d6\xe6\xfa\x03h\xd45\xe0\xf3\a\xf4\x83\xa2&\xa5\xbe\xbb\xb7Q餚詮\xedy\xf7ݗ\xaaǬm_V.X\x8b\x00\x80@j\xf8ٺ.\xb2T&\x91\xcf\xf9\xe7jw\x16\x86\xb5\xcf\xf9\xd5\xfe\\\xcd\xd1J\xad\x81\x1d\u058b\x15\xed3{Ԟ\xcf8\x9f\xbeYW\\\xb0\xf0dLq\xe4s~6\xe4\xd2\xc2-\xf3]\x85\xf5\x1d\xf3\\U\xdbԢ\xdc\xf1|\xf5\xe76t\xc1\x85+\xe4V\xe1\x93~\xd4W\xe5v/\xb6ܱ\u007fvwϦچ\xdd1\xd9G\x93s\xeb\xaeN\xca?\x95\x02f\rrß5\xf4*\x92\x8eS&\xf3\xb7M\x86B\xc1\xe1\xba$.\xdd\xf7\x96\xc4\\\x1c\x04\x00\x13\b\u007f\x12\x84;\xdcO\x8a꤈^\xb7\xbe\xef\x0e\xbb\x93\xf9\xd4~\xf2j\x06\xee\x99\x06f\v\x10\xfe$\b\xb8w\xc8:I\x19\xcdю\xf7\xd1x\x8e\xfdm\x04\x00\x900\x10\xfe\x99M\xb81\xefɮ\xc1\xae'\xf3d\x1dj\x00\xce\x01\xc2?\xd3\xf1-/r\x15-O\xe6\xa0\x1f\x00l\x81\xf0\x03\x80C\x81\xf0g%\xffh\"\xaa\n8\x16\b\u007fV\x02\xe1\a\xc4@\xf8\xb3\x12\b? \x06\u009f\x95@\xf8\x011\x10\xfe\xac\x04\xc2\x0f\x88\x81\xf0g%\x10~@\f\x84?+\x81\xf0\x03b \xfcYI$\xf8\xff\xf5?\xfd\x03\x15\xfe\xa9Ž\b\x00\"\xc8\r?[ץ2\xee\x85[\xd8\x12\xe4Jû\xfc?\xea\xd9\xff\x9b꿲\xec\xf9[r\xe8'\x81\x00NFj\xf8ٺ.\x95`\xfb\x05\xfa\t\x15\x80\x90wk\xcf\xf1\xff\xa8g\xbf\xf6\xbf\xc6\x1c\xf6\xfb液\xe7\x00\x9c\x87\xd4\xf0\xb3u]*\xbe\x81\x00\x84?Qb\x9e\xd8i\x12\xfeǟ\xfd\xe3?\xfe\u007f\xb5\u007f\xc58\xe7\xdf\xc3y41\xe0<\xa4\x86\x9f\xa3\xebB\xe3\x1dA\b\u007f\n\xb9Y\xf6\xc7\u007f\xfc\xef\xff8\xe7\xff\xf8?\u007f\x16\x1b\xfe`\x11\xfd\xe4o\xc0\xb9\xc8\r?b꺂\xed7Q\x16\x85\x9f#\xfcB\xf6\xe6\xae߭\xad}\xb5\xa1a\xec\xd8\xea\xdd\xf7\x11\xba\xffBC\xed\xa6}\xb7\xd4\xe2#յg^jX\xbd\xef3j\x12ݯ\xad\xae\xae\xd6\x0e\xfb\xd5ҳǶ\xd6\xee\xfb-\xfe\xcf\xfd\x17\xd76\xbc\xfa\xea\xda\u007f\xa3TU\xcdɫZ8\xe7\xcf\u007f\xa6\x85\xff\xb3\x17\xd6\xd66\xe85\xd4]\u007f\x9e\xacg\x11\x003\x1c\xc9\xe1g\xea\xba|\x03(\x9b\xc2\xcf\x13~\t\xcc]c\xab\xab\x8f\xed\xae^۳\xf6\x8cz>_\xfd\xd2ع}\xd5\x1f#t\xeb\\m\xf5\xa6\x9e\x9eM\xb5\xb7\xc8I\xb5|l\xac\xb6\aφK\x1bzzV\xbf\xa0N\u007f\xbb\xb5\xe1LOm\xed\x99\xff\xf5\xe0\xef\u007f\u007f\xe3\u007f\xfe\xfe\xf7\x0f\xfd\xfb\u007f\xc0\xe1\x1f\xab}\xb6\xe7JOu\xe4\xd9\xde\x17\u087e\x80\x8e\xe4\xf0\xb3t]7\xf0\xbbA\x16\x85\x1fq\x85_\xf6殆\x17ѕ\xeaw\xd1K/\xe1\xc7\xf0\xab\xbb\xff\a?ƁF\xb5\x9b\xf0\xa1\xc0\xa6g\xe9I\xfc\xbf\x9e\xc8\xef\xd5\xea>\xfd\xc5\x06u\xea\\\xb5\xfa\xbep\xa6\xfa\xe3\x929s\xe6\x84\xeb\xe7\xcc\xf9Ο\xe3\xf0\u007f\xbbi߷\xea\x1b\x03n\x12\x13P\xde@\x00\x80\xe4\x87\x1f\xc5躂\xed7\xc2\xe1\xf5殛\x00\x00\r\xefIDATp\xa03\x9cE\x0f\x9a\xe5\t\xbft8殆s\xe8\xe3\xea\xfb\xe8\xd5\x17\xd5\xe9\xfbg\xf6mZ]\xfdc\\\\\xfb*\xfeyF\xfd\v9\x89\x88\xf0\xab\xef\x16\xa8\xa7V\xfd\xf1\xeaj\xf5\xc7o\xaa\xdf\rl\xffc5\xfc\xff˿\xfb\xf3\xff\x86\x0f\xfb\xafT\u007fJ.&`q\xfd\x01\x8eEj\xf8\x99\xba\xae\xdb\xde(\xd9s\x19\x9a'\xfc\x8a\xc06w5\\A\x1f\xab\x11\xc6\xe1\xff\xb8aӫ\xef\x8e\xed\xd6ïe|\f\xefԉID\x84\x1f\xff\xd6\xc2\u007f\xe6\xcfԷ\x85+շ\xc2\xc1?W\xc3\xffo\xfe\xdf\u007f\xd0.\xf8\x9d\xa9\xa6<~\xc3\xf08\u007f@Gf\xf89\xba\xae\xa9I\x95\xf1\x8e\xc9,z\xc6<\xcf\xf9c\v\x11\xfe\xad\xcf\xe2\x9d\xfb\vz\xf8\x8f\xe1\x9fg\xb5=\xbf9\x89X\xe1\xff\xb2zߗ\xb7\xb6\xee~\x80\xd0\u007f\xc1\xe1\xff\xcf?\xd3>\xea\xbb\x12y\xb3\x88\xd0\xecJ\xfc!\xe0@V\"3\xfc\x1c]\x97F\x96\x9d\xf3\xb3\xc3oo\xee\"¿\t\x9f\xed?\xf8\xb1\x1e\xfe\xb5ډ\xfenz\x12\xb1\xc2\u007f\xabzmu\xf5n|U\x1f\x87\xff\x0f\xff\x93\x1e\xfe\xfb\r\xbb\xf1\xae\xff\x98\xf6\u0381\xc2%6\x02!\xc0QH\r?[ץ\x12\x0e\x8cw\x04b\xcc\xf6\xb3\x14\x8e\xf0\v\t\xcc]\xb7V\x9f\xb9\u007f\xae\xf6\xd6\xfd\x17\xd5\xf4\xf6T\xbfp\xa6\xe7\xc7\xd5k{\xc6\xd4lW?{\xee\xec\xd6տA\xe4\xe4\xb7ccc\xb5G\xc6\xc6\xee\xa3/\xf1\xef\a\x9f\x1e\xa9\x1d\xfb\x12ݪ\xbdre\xec\xb7\xf8\xe6\x1f\x1c\xfe\xff\xed?\xfc\x8d~\x93\xcfX\xedֳW\x8eU\x9f\xd5\x16Ӓ\xacP\x14\xc8:\xa4\x86\x9f\xa3\xebR\xcb\xf1)\xffq\xfe|\xb3\n\x8e\xf0\vٛ\xbb\x1e\xa8;\xeds\xab\xabk\xcfUW\xbf\x80\x1e\x9c\xd9Z\xdb\xf0\xe2٭\xb5\xbb\xf1\xb1\xfeK\xab\x1b^\xfc\x12\xd71'?\xae\xd69\x8b\x8e\xa8?k?\xc5\x1f\xfb\x1fQS\x8e\xcbjw\xdf\xd2\xc2\xff\xbf\xff\xe7\xff\xeb\xbf\xeb7\xf9\xfc慆\xd5\xcf\xea\xdf\x04\xf0\xe7\xed\xe0v\x01p\x18r\xc3\x0f$N\xf4螞d\xf1\xaf\xb5G\xfe\xf5w\xbf\xbb\xff\xf1\v\xab\xefk\xe1\xffo\u007f\x85o\ue9eat\xb9\x1a\xe1\x16\x1f \x02\x84\u007f\xa6\x13\u007f\xf8\xdf]\xad\xdf\xee\xff`\xed\x15=\xfc?\xfb\x9b\xff\xdb\xf2\x95\xde\"\xf8R\x1f`\x00\xe1\x9f\xe9\xc4\x1f\xfe[\x91\xcb\xfa\xb7\xaa?\xfd\xb7\xf8j\xff\u007f\xd0\xce\x02lg\x01\x9c\f\x84\u007ff\xf3[\xedz\x9eu\x92̓\x97j\x8f\x9c\x1b;w\xa4\xf6\xa5\a\x10~@\f\x84\u007ff\xa3]\xcf\xfb\xcc:\xc9\xe1\xc1\xbb\xfb\x1aj\x1b\xf6\xbd\xfb\x00E\x0e\xfb\xe11^\x80\r\x10\xfe\xac\x04\xc2\x0f\x88\x81\xf0g%\x10~@\f\x84?\v\t\xb5\xd6\xe1;\xfc\x9a.\xc0\xc7z\x80\r\x10\xfe\xec#\xbc8\xfa\x95ޓ\x90~\x80\x0f\x84?\xfb\b=t\xf0\xf7\xbf\xff\x9f\xea\x06z\xe8\t\xf8\x0e\x0f\xc0\a\u009f}\x04\x15\xa5\xaa\xea\xa1ª\x85s\x1a\xb3\xe5\xfb\x12@:\x80\xf0g\x1f!\u007f\xb1\xdb=\xdf\xedv/\x1d\x86=?\xc0\a\u009f\x85\x84\x02\xdaS\u0086\xea\n\x95'Du\x01\xe7\x02\xe1\xcfF\xc2\xe1\x90\xfao\xfe|\xef@\xf6<\x1d\tH9r\xc3\xcf\xd4u\x85:\xb4\x87xudӕ\xe9\x81BC?6\xb5\xad0o\x05\xf5\x90\xa2#\x91\xa7nO\x8f\xe8\"\x1a\x15EɻɨpU\xe9c\x94\x02@\x14\xa9\xe1g뺂\xde\xf7\x03*\xf4\xa3lg9\xbe|\xe3\x11\xb9K\v\xbd\x8dyԹ\xf7o\xc7\x04\xdfЉ\x8b\xe8\"\x02~\u007f+\xf3i\xdc\xc3\n\xfd\x8c@\x00\xa0\x91\x1a~\xb6\xae+\x98EO\xee40v\xf5SJ+\n[\xaf\xbb\xa5\"\xfc\xe6\"Ԙ\x0f1\xfe\xce,\x9d\x932b\xdb\x06f\x19R\xc3\xcf\xd6uee\xf8\rn*\f\xffpJ\xc2o\x92H\xf8\xbfI\x11\x10\xfeُ\xdc\xf0#\x96\xae+\xeb\xc2\x1f\xccS\x94\x9c\xe3x*\xe4֟\xcfo}tV\xed\xb1\xa8w˄\x90x1}^h\x9b\x92\xeb\xdd1?o\xb9v\xf4d,\x02\xc3\x0e\xff \x84\x1f\xb0Er\xf8Y\xba\xae\xa0w\xe0\r\xefq\u007f\x16]\xef\xbb\xec\xf7\xbb\x9a\xb5\xa9\xf7\xfd]J\xb3\xdfo}w\xc3O\xe2<\xf7\xe3Z\xea\x91ڄċ\xed\xf3\xbaq|\xaeR\xd8\xdcR\xa0=\x19\xd8\\\x04b\x86?49\xb8\xd0\xcd\xf8\x94\x1f\xc2\x0f\x18H\x0e?K\xd7\x15\xf4v^\r\xdc\xe8\xeeʢ\xf4#\x94\x17M&\xfb\xb0\u007f+\x16hm}\x96*$$^l\x9f\x17r\xb9\xd5w\x91\xf5\x85\x91\xff\xe5م\xff\t\xf5\xb8\x81\xb1`\b?`\";\xfc(Fׅ\xc2\xe3\xfaA\xc0\x90`\xbeY\x85 \xfc\x9aw+j\xdf\xd0!$^\x1c\x9f\x17ra\xbbv\xb3+\xf2?\xdb\xf0\a\xfa\xbc%\xd3\xda\xf3\xcf\xd1\xfe\xd9\xfc=\xb6m`\x96!5\xfcL]W\x14\xffI\xf6L\xb3\x13A\xf8)\xefV\x04B\xe2\xc5\xf6y!\xed@?\xbe\xf0\xab\xf8\x95\xe1\xd8B\x1c\xe87\xffH\x8f\xf5\xbf\xfc\xe5\xc3s\xbe\xffS^\xb8!\xfcY\x8f\xcc\xf0\xb3u]h@O\xc7 \xeb(u\xd6\"\b?\xe5݊\x9b\xc4\xc2Ͻ\xda\xff\x837\xf5X\xff\xc5\x0f~\xf9\xc5/\xff\xe4\x17\x9cpC\xf8\xb3\x1e\x99\xe1\xe7\xe8\xba|\xda.\u007f\xaa\xe3}\xdbyg\x19\x82\xf07h\xe7\xfc\xbbc\xffbK\x8a\xc2\x1f\x8d\xf5\x1f\xfeJ\xfd\xf1\xab\xff\x18I\xf3O\xbf?\xe7\xe1\xbf\xfb\xe6\x9b_\xfe\xf0\xa1\xef\xfc\xf0\xd7F\xf8\u007f\xfa\xdd9\x0f\xff\xe57Ą\xfa\xf79\xdf\xff{\b\u007f6 5\xfcl]W\xc0\xdbw3p\xb9ݗ5\x9e\xceА\xdf\xefj\xf4\xfb\x83ѫ\xfdC\xd6U\xab\xad\xde76\xf6\xac\xa6\xe0\x8a\x9f\x80?\xb7q\b\x8d6\xe6\xfa\x03\xe4\"\xb4;\xfcZb?Q@\x97Y:\xde\xd8\xf0?\x1c\xc9\xfe\x1f\xfe\xf4\x8b_\xaao\x04\xdf\u007f\xf3\x8b_\xff\xe9\x9fF\xc3\xff?\xbe\xff?ԃ\x83\xbf$&\xbe\xff\u05ff\xfe\x97_\xfc\x10\u009f\rH\r?G\xd759p\xbc\xc37\x9e5\xd9Gú\xafK\xf1F?\xe7\x9f{\xc3Rck\xcf\vQ\x05W\xfclS[\xca\x1d\xcfW\u007fn#\x16\xa1\xddۏ\xa9\xb7֟\x9c[w5\xc6|L\x86_?\xec\x8f\x1c\xdc\xff\xd1\xdf\u007fc\xf0뇣\xe1\xff\xc1/\"\xef\x0f\xc6\xc4w~\xa5ׁ\xf0\xcf~\xe4\x86\x1f\x90Io\x89\x12\xf3\x95^2\xfc\xf8\x82\xdf\xc3\u007f\x17\t\xff\x9c_\xeb\xbf\u007f\xa5\x1e\xd6ϙ\x13\r\xffC\xfa\xad\xbc\xc4\xc4_<\xf4\xa7\u007f\xf7+\b\u007fV\x00\xe1\xcff&\xafZO\x06\xc8\xf0k\xbc\xf9]\xfd\xf7C\x91\xf0\xff\xe0/~\xf5\xcd\x17F\xf8\xe7D\xf6\xf3\xe6\xc47\xbf\xf8\xeb\x1f>\xf4\xd7\x10\xfel\x00\xc2\xef,b\xc2\xffÿ\x8c\x84>r\xd8\xff\x9d/\xd4\x13|#\xfc\u007f\xf4\xb7\x91j\xc6\x04\xe6\x97߁\xf0g\x03\x10~gA\x86\xffO~\xf1/\xbf\xfc\xd3?\xfa\x17=\xd0o>\x1c\xb9\xe0\xf7\xd7_\xfc\xe2\xbbF\xf8\xdf|\xe8\xef~\xfdś\u007fBL\xfc\xc9O\xbf\xf8\xe2o\xbf\x0f\xe1\xcf\x06 \xfc\xce\x02\xc7>r\xf6\xfe\xcd\xdf\u007f\xf7\x0f\x1e\xfe\x8b/\xa2\xbb\xf3\xbf\xff\xae\xf6Q\xdf/\xbe?\xe7\xe1\xbf5\xc2\xff͛?\xf8Μ\x1f\xbcIL\xfc\xf4\as\x1e\xfa\xe1/!\xfc\xd9\x00\x84\xdfY\x10\a\xfc\xd3\x03\xc2?\xfb\x81\xf0;\v\b?`\x00\xe1w\x16\x10~\xc0\x00\xc2\xef, \xfc\x80\x01\x84\xdfY@\xf8\x01\x03\b\xbf\xb3`?\x8c3\x19DK\x02f<\x10~\xc0\x96\xec\xf9\xca\x05`\x05\xc2\x0f\xf0\t4\x82\xf0+\x8b\x81\xf0\x03\\\xc2%% \xfc\xcab䆟\xa9\xebR\xb9\xd1\xd7\xd1}\xd9f> \x82\xad\x06,\xe5\x80\xf0+\xbb\x91\x1a~\xb6\xae\v\x85\x06\xbcC\xb7G\xbd\xf4\xc3*\x01\x16\xb6\x1a\xb0\x94\x03¯\xecFj\xf8ٺ.4\xd0\x1e\xc0o\f\xd6'^\x00\f\xec5`)\x86\xfdx0 [\x90\x1a~\xb6\xae+\xe0}\xdf\xf8\x1b\x10/\xccg\x03\xa6\x18\b\u007fv#7\xfc\x88\xa5\xeb\x1aj\x0f\xc1\aJ\xf1 Ҁݪ\xad\xae~\xf5\xb3\x177\xd5\xee\xfb\x1dQ*Ԁ\xa9|\xf6\xc2\xdaچ}\xbfE\x16\x98\xc2/ k\x90\x1c~\x96\xae\xab\xd7w\xe3\xa4\xf7\xf8\x85\xac\x12\xf6\xa4\a\x81\x06\xec\xdbs\xe76m]\xddp\xec\xc5?#\x9f\x0e(Ԁ!4V\xfblϕ\x9e\xea3T!O\xf8\x05d\r\x92\xc3\xcf\xd2uuk\xba\xae\xe3ݐ\xfe8\xb0\u007f$8\xfaq\xf5\xee\xfb\xe8\x01\xad\x03\x10j\xc0\xbeݴ\x0f?I\xfc\x1c=\x1bO\xf8\x05d\r\xb2Ïbu]>\xed\xaa_\xb0\x83\xe1\x97\x01\xac\x88\xc2_\x1b\xf3H`\xb1\x06\xecJ\xf5\xa7֙\x10_\xf8\x05d\rR\xc3\xcf\xd6u\r\ua7ae\xc1^\xfe\x8c@\x14Q\xf8i\xf7\xa7\x86P\x03v\xa6\xfa\xdbع\xb49Y\xc2/ k\x90\x19~\x8e\xaek\xb4C{/\x18\x80c\xcc8\x10\x85\xff\x05F\xa1\x88+\xb43\xd0\x04\xae\xf6g72\xc3\xcf\xd1uMi\x1f\xf5\x05\xdb\xe1\x16\xbf8HG\xf8\xef7\xecƻ\xfecǬ\u007f\x80\xf0g7R\xc3\xcf\xd6u\xa1\xcb\xed\x97\x03\xe3\x9d'႟\x00\x91\x06\xecwcc[w\x8f\x8d}ƙ\x9d\xcfX\xedֳW\x8eU\x9f\xb5\x963\x85_@\xd6 5\xfc\x1c]\x17\xba\xdd\xdbq\xf22d_\x84H\x03v\xabZc\x1fgv\x1b~\xf3B\xc3\xeagߍ)f\n\xbf\x80\xacAn\xf8\x81\xd9\x05K\xf8\x05d\r\x10~\xc0\x8eX\xe1\x17\x905@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1\xc8\r?K\xd7\x15\xea\xf4\xea\x1c\xb7\x9f\x17\x98!\x10\xca0`V#5\xfcL]W\xc8;\x1aP\xb9\xec\xbd*\x9a\x1d\xc8\x18\x83\xa3\xe64\xa1\f\x03f5R\xc3\xcf\xd6u\x8dk\x0f\xef턇\xc6\xcc`\x16\xd6\x13\xff\x81\xc7{d\tR\xc3\xcf\xd6ui\xf8ހ'\xf9\xcc`\xca\xeaD5\x80ه\xdc\xf0#\x96\xae\v\xa3=\xcf\x13\xc8\x14\xb7\xebܹ\x85+\xb4\xc7v\xb4\x96啵\xaa\xbf\xb7)\xb9\xde\x1d\xf3\xf3\x96\xe37\xea\xc8\xc3\xfe\xcb\x10\xa9\f#*lSr:\xd1m\x97R\xa25ֹ8\u007f\xfe\x0ex\xe0\xff,@r\xf8Y\xba.\x8c\xe6\xf1\x002\xc4`~Y\xcb@\xb3ҢN6\xba\xf6\xf8\xf6\xb8֫o\xc7\xc7\xe7*\x85\xcd-\x05\xea.?x\xc1?\xbf\xca\xef\xf7kO\f4\x94aD\x85\x80?W-\x1ajt\xe1\xf2Ɯ\xed\xbe\xd6\xc2287\x98\xf9H\x0e?Kׅ\xa2\x17\x03\x80\xcc\x10*^\x1e\xc2OT\x9fB\xa8O\xc1\xa7c\xfaO\x97[\xdd(\xeb\v\xb5*\xd4a\u007f\xf4\xf1\xe1D\x05\xed\xfd\xa0\x19\x87ߧt \xfc\xd0\xef.\x04\xcctd\x87\x1f\xc5\xea\xbaT\x06\xba\xedg\x01҉Oy?:٨\x1f\xb9\x974\xaa?\\\xf8\x87\x16h^\xf8\xcd\nf\xf8\xeb\xe7\x850ō\b\x98\xe9H\r?[ץ\xd2\x01\u008e\fҢ\x18\x17[\x17\xaf\xd4~\xadX\x88\xc8@\xf3\xc2oV0'\xcb\"\x17\b\u087f3\x1f\x99\xe1\xe7\xe8\xba\xf0\x95\x00J\x1c\t\xc8e@1>\xc5o\x9c\xa7\xfd\x9a\xa7\xed\xf9\xad\xe1o\x8f\x9c\x9b\xf1¿\aO\xae\x9f7\xaa1\x85\x80\x99\x8e\xcc\xf0st]\xf8\x94\x1f.\x0eg\x90`Q\x15~+\u07be\x1d\x9f\x01\xe0s\xf5.M\x05F\x86\xbf\xaa\n\xa1I%rr\xc6\b\u007f^\x93\xfa\u07be\x10O\xf6\xe9\xb5\xf6\x1cD\xc0LGj\xf89\xba.\xf5\x9d\x00>\xe4\xcf$\x83\xdf+\xf1\xfa\xb6+\xed\xea\xe4\xfa\x9c&_S\xcez\xed\n~\xe3\x10\x1am\xcc\xf5\xe3\xfd}\xb3\xab\xa5wi~\x80T\x86Q\x15\x16\x17\x1e<\xb8X\x99\xdbq\x03\xa1&\xa5\xbe\xbb\xb7Q\xe9\x14-\x14\xc88R\xc3\xcf\xd5u\xc1\xfd\xa2\x99\xe5f]q\xc1B\xedSװ\xf69\u007f\x18\u007fv\xaf(\xb9\xe3\xf9\xea\xcfmjqh\xbb;\xaf\n\xfb\xbaMe\x18U\xe1fU^\xc1\xf2&\xbdn_\x95۽\xb8\xcfvy\xc0\x8c@n\xf8\x01\x00\x981@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8g\x0f\xf5\x8a{\xfd\rQ%\x00\x88\x17\b\xff\xec!0\xd8Q\xe2\x86'\x1f\x00\xa9Bn\xf8Y\xba.\xfct\xd87\xda߸\x00\xaf\xea8\x18T\xc0k\x04\xa4\n\xa9\xe1g\xea\xbaP\xb0\xf3$.\xed\x84\xf4\x8b\x19V\x86DU\x00 N\xa4\x86\x9f\xad\xeb\xf2wk\x8f\xf0\xef\xf6\v\xe6\x06 \xfc@*\x91\x1a~\xb6\xaek@\u007f|w/x;\xc4@\xf8\x81\xd4!7\xfc\x88\xa5\xeb\x9a\xea\x1c\x9c\nM\xf9;\xe1y\xafb\xae*\x83\xa2*\x00\x10'\x92\xc3\xcf\xd4u\x85\x06\xd4\xd2>x\x86g\x1c\x84\xdc\v/\x04\xc0\x84\x05\xa4\x04\xc9\xe1g\xe9\xbaB\x03\xdd\xf8\x99\xbe\x03\x90\xfe8\xe8S\x14e\xa5\xa8\x12\x00ă\xec\xf0\xa3X]W\xf4\x82\xdf\x05ь\x00\n\x16\xcek\x19\x04\xc3\t\x90\x12\xa4\x86\x9f\xa9\xeb\n\xb7\xeb\xa68\xcd\xe3\x03\xd83\xac\xc0eQ U\xc8\f?[\xd7\x15\r\xff(\x84_\f\\\xed\aR\x87\xcc\xf0st]\x83\x91\xc3~\xb8\x8e-\x06\xc2\x0f\xa4\x0e\xa9\xe1g\xeb\xbaB]\xdd\xe3\x81\xf1\xee.\xb8\xe0'f\b\xc2\x0f\xa4\f\xa9\xe1\xe7\xe8\xbaB\xc3';N\x0eC\xf6E\x84\x02\xa3\xf5\xae\x80\xa8\x16\x00ĉ\xdc\xf0\x03\xd3\xe1\tE)\xee\x15U\x02\x80x\x81\xf0\xcf\x1e\x02\xa3\xb0\xdb\aR\b\x84\x1f\x00\x1c\n\x84\x1f\x00\x1c\n\x84\x1f\x00\x1c\n\x84\x1f\x00\x1c\n\x84\x1f\x00\x1c\xca\xff\x0fL\f\x1em+\xfdz{\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/chan1.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x04\xc0\x00\x00\x02n\b\x03\x00\x00\x00aR\x8e\x00\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\a\n\a\x0f\x11\x0e\x1a\x1a\x14\x1f\x1f\x18!# #$\"\x15%D$%#%'%'(&+)\x1e()'*+)/,!+-*,-+-/,02/63(241564796<9.9;8#?r@=2<>;>@=C@4DA5AB@DFCFHELH:IKHKLJNOMUP?PRORTQTVSVWU]XGWYV_ZI,`\xaeZ[Y7]\xad[]Z\\^[9a\xab;b\xac<c\xad_a^faO>e\xafac`hcQcdbAg\xb2efdCi\xb4fheDl\xb0Mj\xafqjRikhGn\xb2Ip\xb4lmkKr\xb7npmUt\xb4{s\\rtqWv\xb6tvsuwt[y\xb9\\{\xbbxzw]~\xb8e|\xb8\x84|dX\x80\xbf{}za\u007f\xbf|~{~\x80}b\x82\xbc\u007f\x81~d\x84\xbf\x81\x83\x80|\x83\x97\x83\x85\x82l\x86\xbch\x88Ð\x86hn\x88\xbej\x8ać\x88\x86q\x8b\xc1\x89\x8a\x87t\x8e×\x8doz\x8e\xbf\x8c\x8e\x8b|\x90\xc1\x8e\x90\x8dx\x92Ȑ\x92\x8f~\x93ĝ\x93ux\x96Œ\x94\x90\x81\x95Ɠ\x95\x92{\x98Ȕ\x96\x94\xa2\x97y\x96\x98\x95\x81\x9aė\x99\x96\x84\x9cƇ\x9b̙\x9b\x98\x80\x9eͦ\x9c}\x87\x9fɜ\x9e\x9b\x89\xa1˞\xa0\x9d\xa0\xa2\x9f\xa1\xa3\xa0\xa2\xa4\xa1\x91\xa5ʏ\xa7Ѥ\xa6\xa3\x94\xa7̥\xa7\xa4\xb3\xa7\x83\x92\xaaԧ\xa9\xa6\x97\xaaϩ\xab\xa8\x9d\xac̫\xad\xaa\x9b\xaeӟ\xafλ\xae\x89\xad\xaf\xac\x9e\xb1ע\xb1ѯ\xb1\xae\xb1\xb3\xaf\xa5\xb4Ԣ\xb5۳\xb5\xb2ö\x91\xab\xb7ѵ\xb7\xb4\xa8\xb8ح\xb9ӷ\xb9\xb6\xb9\xbb\xb8\xb0\xbc\u05ed\xbdݻ\xbd\xba\xb3\xbeٽ\xbf\xbc\xb7\xbf\xd4\xcd\xc0\x9a\xbf\xc1\xbe\xb6\xc1ܹ\xc1\xd6\xc1ÿ\xbb\xc3\xd8\xc2\xc4\xc1\xbd\xc4ں\xc5\xe0\xc4\xc6\xc3\xc6\xc8\xc5\xc0\xc8\xdd\xd7ȝ\xbb\xca\u07bd\xc9\xe4\xc5\xc9\xd9\xc0\xcb\xe6\xca\xcc\xc8\xc7\xcb\xdb\xc2\xceܿ\xcf\xe2\xc9\xcd\xdd\xcd\xcf\xcc\xc9\xd0\xe6\xcc\xd0\xe0\xc6\xd2\xe0\xdfѤ\xcf\xd2\xce\xd1\xd3\xd0\xd2\xd3\xdd\xd3\xd5\xd2\xcd\xd5\xea\xce\xd7\xdf\xd5\xd7\xd4\xe6ת\xd6\xd8\xd5\xd1\xda\xe2\xd8\xda\xd6\xd9\xd9\xe4\xd3\xdc\xe4\xd5\xdb\xea\xda\xdc\xd9\xd8\xdd\xe0\xdc\xdd\xe7\xdc\xdf\xdb\xda\xdf\xe2\xe0\xde\xe2\xde\xe0\xdd\xf0\xe0\xb3\xd6\xe2\xf0\xdc\xe2\xe4\xe0\xe2\xdf\xde\xe3\xe6\xde\xe2\xf2\xe2\xe4\xe1\xe1\xe6\xe9\xe4\xe6\xe3\xde\xe7\xef\xe8\xe5\xea\xe5\xe7\xe4\xe6\xe8\xe5\xe4\xe9\xeb\xe7\xe9\xe6\xe8\xe8\xf3\xe8\xea\xe7\xe2\xeb\xf3\xe9\xeb\xe8\xec\xee\xeb\xe6\xef\xf7\xe8\xf1\xf9\xef\xf1\xee\xf0\xf0\xfb\xf1\xf3\xf0\xf1\xf6\xf9\xf4\xf6\xf3\xf7\xfa\xf6\xf5\xfa\xfd\xf9\xfb\xf8\xfa\xfc\xf9\xfd\xfb\xff\xf9\xfe\xff\xfc\xfe\xfb\xfe\xff\xfc\xc5\xe5[\xa2\x00\x00 \x00IDATx^\xec\xbdqLS[\xda\xef\xef93\x8b\xab}\x87Ax+\xc3}\xf5^8#\xbe\x1c\xbc^gk\xa9\x17\u007f\xe2A.U\xe1u^\x05މ9\xf6\xe8}\xc9\x18\xc5\x174z\x8fg<W\xb7i\x86\x1e\xa0D\x99`1\xbcD0\f\rp\x022\x04\xa5i\x99\x89\xa9F\xc2;\x8d\x8d\x9c\xd83\x89\xf6L\x8c\x90BL\xbb\xfe\xfc\xe5\x97\xdc\xff&\xbf\xb5\xd6\xdem\xf7nw[@\xd9Px>\t\xddk\xaf\xfd\xac\xb5\xf7j\xd9߮\xf5\xec\xd5\xf5l\xf8\xdb{\x80\x01\x00\x00V\x8e\xbfmH&R\x89HV;\x00\x00\xc02\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\xac\v\x02\xc9\f\x80\x94\x04\x04\fX\xfbx*\xb6\xa0\xfdɌ\x80T\x04\x04\fxO\xda\v\xbc\xc9L\xd4\xc1[Ю| \x90\x97\xc7\xf7\xb8\x95\x8f\x01\xa9\x8d\xda\x02\xe6\xe9j6Y\x06|\xb2\xe4|\x13/М\xa0\xe0_\xaf\x95\xe9k\x83\t\fbiۈ\x046\xb6%3]\x94\xed\x12\xa9C\x9b\xe8\rf\xcd@u\xca\x06w\xd9\x05d\xeds)\x1f\xc6\xd8L\x0eבz\x102\xc53\x890\x9aƪK{ \xecNnByds\x84de(\x9c\xc0\xb1'#\xbb\xb47{:\xf6H2\x1aйd&K`\xec\xd0p2\x13F\xbf\x8e\x13\xd0\xf5\x93KIkP4\x1aG]\x8a\xf9@ꣲ\x80M\xf3V\xa7\xdb\xd9\xd6\xec\x93&g\xf8Q\x0f\xe1\x01?\x9e\xa0\xe4\xe9C\x9d\x17\xf5o\x13\x18\xc4Ҁl\xb6\xaf\xd1e\x9b\r)\xff_SzG\x17n\xbbDB\xa7\xf0\x96f\xec\"\x9b]\xe9\xa5qz,\xbe\x81MGl\xbd\xbfٖ\xeeT>\x8e}f\xd4\xe0\xc5\xde\x06d\xf6ű\x88\x9c\r\xcf\x0f\xb2\x06\r\xfa\xc5\xfd\xc1#\x1a\xf2\xea\xa6\xcd\x1c\x8c)Օ\xb1\x83oَP\xbc3\xc7\xe77if!\x11>q<\x1e=Y\x84\xc1pq\u007f|C\tw8\xbb\xbd\x93\xeb\xb0\xdbw\xdf!{֍W\x95\x8c\x86\x90M)\x1bX\x03\xa8,`.\x9e\xf6\xe4}\xbcS\x96t\xd0\xfb\xd1\xd74\x90\xa0\xe0\x0f\\'\x0e\xce&0Pಆ\xfe\uf4bb5\xfdr\\\x9b\x1d\xa5\v\xb7]\"\xa1S\xe0S{3|؛\xbe\xf7T\\S\r\xed\x9b\xf9r\xf6\xc4;\xee`]\x89^\xe4\x88g 9\x1b\x16\x1b\x14\xa6N\xa3\x94\xcb\xf0f\xee':\xe7۶x\x01\x9bԄZ#=\xb1\x04oaH\xaek.(\x1aD\x90\x19,\xb0\xb3ݡ\xc3\xf817\x81\xb1\xbe\x83\xee\x9e\xd1(\x8d\x14\x15Z\f\xac\x11T\x160̺\x0e^\xde#OR\xeeޚW.\xc2x\xc1-lH!\xc5\xef\x12\xffw]~\x1c\x8f\xfc\x83\v\xb7]\"\xa1S\xe0S\xa5\xbbZp\xd3/J\x93\b\x18>\x97\x1e\xef\x91\xd9\x02\x04,|6\xbc\b\x01;\x95\xceƎ\x97P\xdc\xd1k<*\xb2C\x9dA\xe9\x89%8\xc2\x17[\x95L\xc0\x92\x1a(0\xf7B\x14\xb0\x17stח]\xa1`\x04\x02\xb6vQ[\xc0\b3n\x8b5\x10\x93t\xf2\xf1\xfd/se\x82\x9f\xe3&\xc6\xd78\xae\x0f\xbf\xd0q\xbf\xa4Iݽ\x9b\x95\xfa\xda\xef\x99͋\ve\xbaCbZB\xe4\u007f\xb7\xa9 #\xb7\x9a\xddm\xb6=9\x9b\xb4{\xb7\x92\x11\x87\xe8\xf7ʗَoD茫|k\xfa\x9ey\xec;\x98\xad\xc9\xd9G\x87\xb6\xc7\xd0&\xbe:7c\x8f[V\xc31\xb4\xf1jEN\xc8mu=?c\xfbuy\r\xd2S\x9c*\xbd~\x00\xef\xbdN\x05,R\xaf\x93\xd8\xee\xc39\be\xf9C\x02ְ\xd1/\xb9^\xe9\xe5\xc8\x04,t\xb6\xa4\r\xc2\xd8S\x9e\x9du\x80\r!\xb1\xe2[\xb2M\xb8\xed\xbd\x97\xfc\x92z%-Vn<\xc1\x9f\xf99\xdbF\x9d8\xc4\xd5\\\xab\x139\xad\xb9\xd7\xf1\xb0說\xa1\xd9\xc1\xfb5ŕ7Y\u007f\xda^{XWV{8(3x\xab\xe7\xe8nj\xa3>\xe3W\x17\xcb\f7o\x96\x15\xf7\xc9O\"\b\x98ș\xf4\x19\x1cC/\bؚEu\x01\xf3\xf2</\xbap$I\x8c-=\xf1\xcb\xe0\xa7\xf6>\xae\xd5n\xff\v\xc6\xdf\xdbu\xad88\xf1e\x11\xc6S}:\xeeP띒\xf3\xd4\xe2Qq͝\xb1V\xae#\xbad\xf8n\xadH;n\xbd\xaa\xcd\x0fЬ#\xb7\xbay-\"\xf24`\xcb-\xb4\xd9lN\x99팥yknfNu9r\x93\x1b\xb3\xa2ײ/m\x88\bM\xf3F\xa4\xad\xbb\x94y\x00Kk\xa0\xb9[\xeb\xea\xb6fPI9\xa29c=\xa3)\x97\xd5 =ũRw\x86\xf7'\x1e*`\x91z\x03\x83ui\x83،\x9a\x1ebQ\xc0\x02\xf9ۥ\xd7+\xbd\x1c\a\xb2\xce\xcc\xcc\xdcE\xb2\xb3%m\x10ve\xe6\x9a\xdb\u007f\x814\xf1\xde\x12\u007f\x9ad\xdc\x1c\xaeW\xd2b\xe5\xc6\x13FQ/+\x14u\xe2\x10\x9er\x94\x87>A\xa5n<;a\xaf4\xda\xed\xf6\xe74\xfb\nwc\xa4\xf3P\x15\x19%>\xdd}\xb1\u007f\xec^\x19\xf7Nn\xf0\xd8n\u05f7҄\xf43\x9e;a\xe8l\xd5\xeb\xef\xd5F\u007f\xc8R\x01\x1b\x88Ѫ\xf9\xe9\xde\x1dY\xf1}\x86@j\xa3\xba\x80a\xaf\xc7ai\xf6E'\xdd|\xe2\xc7ܑ!d\x11\xfd\xcfn-b\xc9\x12\xf2\xcd|\xf1\x10I\xcd\x1d\xae%C\x88\xb9\xbe\x1f\xa2˅\xeeV+2\xb3\xbd\x16\xd2\xc3\xd0\xd2{\xef\xeb,\xd6\xf5S\x1eq\xe5\xa3]>6\xc6\xf5Y\xe8\xe5}\xc2\xe6\x10i\xb2\xc8%\x96k\xb1\xbc\x06\xcdVj\x96S\x80q\x17\xeb\x1eu\xa1\xbb\xb2\x1adCH\xfcɱ\x1d\x98\xf5\xc0$\xf5\xe2#\x05\xde\x1c\xe1с\xe6_g|\xe3\aP\x8f\xecz%\x959Ď\x8eCv\xb6\xa4\r\xfat\x1b)\x1bخ\x91\xe7FN\xe1F\x91\xf9\a\xd2VDZ\x1c\xa7\xf1\xa4\x8e\xc9PA\xe5!d\xd7&\xb4鮐\f\x8f\x10\x87\xb9\xfb\x98\xca\x0e\xe9Iu\x1ezG\x92\x9d%A\x99\x01E\x100\xe9g\xdc\xc7=#\xa6\xdc\x14\x8eF*`nt+\xea\xe8~\xf2~Y1\xb0FQ_\xc0\b~Kwt\xb2\xdb\x12ך\xa1,`\x17C\xc9\x11\xee\xa9r\xb9\xd0\xddZ\xba\xcd?O\xc8!c%w\xf6\xd6\u007f\xe6\x1f\x06\x04_W\x1c\x01\v\xfb\x82\xbd\xd7\xf7l\xcbD\xb4K\x845G\xc8\xcb9\r\x96נ\xf9\x82\xbe~\x8d\xbc\xb8\xe2\x13V\"\uf23c\x06\x99\x805\xa0\x06&`\xd2z\xf1\xcc\xf6-\xfb\x04\v\rU'-U\x13\xc9\xf5J*s\xa0KCCC\x97\xa9\x80IΖ\xacA>\xc4\xd3\xcd\x19\x8d,Wr\n\xff\xc6H\x0fLڊH\x8b\xe34\x1e\xb7'\x160o\xb5&\aekN2?~X\x9f\xea\x8fν#\x18\xae`\xfc\xd2p\xf4ƽ\xa7A濊#`\xe1ϸ\xb1\x84\xbc<\xe7\xbe\xc5\xd1\xc8\x05\xac%\uaa3b\x8bσ\x1eؚEe\x01\xf3\v\x1e\xafq> M\x12\xcc\x0f\xe2\x96a(\vX8\xd9\xc1\xcd)\x97\vݭ\xdbž\v\xed\xf3\xf8\xf8\x83yh\x8b\xd0\xe7\x89#`;BY[r>o\xb3\xed\x14\x04\xec\x1c\x0ey\xc2%5\bn\xab^4\x8a?\x15Tho\x81\xac\x06\xb9\x80yɽL\x05LZ/Ʒ\x90\xf8\x00VS14$\xb8Ӥ\xd7\x1b\xa9L\xe2\x03\x93\x9e-I\x83\x1e\b\xb3\b\x04%R|KD\x1f\x98\xbfK^\xaf\xa4\xc5ʍǃ\x91\x11\x9b\x92\x805hy'r\xfeF\xcbޣ\xb0>\x9d\x10\xdd]gI\xfa\xed\xbd\v\x95\\ٝ\x04=\xb0\xc8g\xbc\xfb\x15\xfd\xa6J\xdc\x03\x1b\n\xbd\x95Rlh(6\x13X\x13\xa8+`\x81&\xc1e\xf2\xd0\x14\x90$1u\x87%\x99(\x1d%`\xdfD\t\xd8\x18\x1d^(\x11\xba[˷\x8d2H_\xe0\x01\xed\x01\xf9Zҙ\x03\x9c\xddv&\xb7̖\xe4\x1e\x10\x13y\x05\xf4\xbb\xfb\x80 `\xf46d\xf7\xb0\xb4\x06M5=\xc6#\x1f\xae\xd8Ɗl=\"\xabAr\x8aS\xc2D\x03*`\xd2z\xb1'\xfb\x8b\xad\xc2\\\x03Mx\x8a\xab\xe4z%\x95I\x04Lr\xb6d\r\xf2\"v$ډ/9\x85\xf8\x14\xd2B\xfb\x91\x92VDZ\x1c\xa7\xf1\xd8DŽ\x8d!=q\x18?{\n)\xf4֘>\xdd{I{`O\x18D\x8f\x1e7\x12\xe9zۧ\xef\x94\x19Pb\x05\xec%W\xfb\xf2Y\xa51v~\x85T\xc0\xea4\n\x9d-x\n\xb9vQW\xc0p3\x9b\x12\xed\xa7\x1e{I\x12\xe3I>I'?\"`\xfaF\x8c\x83\xff\x12%`\xb3\x06#\xed\x82ݸ\x11].\xf4\xbfۅ\xd8\x18\xf5\x8b::#\x9e\x9d\xb9\xf0\x18{-\xc4xZ8&\x15\xb0Po\"\x87JG`{\x94\x80Ik\xd0l\xa1\xee\xa9m\x85\xd4\x1fDG/-\x82\xc3E\xd2\x1f\t\x9fB\"`\xd2z\xfd\x05g\xf0\xb1]\x81\xf0)\x18\x92\xeb\x95T&\x110\xc9ْ6\xa8 \x87\x88\x94\xeb'\x1a,˕\x9c\u009by\x80\x88L\xa0p\xab\xbc\x15\x8a\x02&;\x1b\x19\x87\n\x1di\xf9\x89%\xb8\xb3B\x9af4b\xfc\x9a:\xbeƄ'\x8c\x8d\xb7ɇǍ\xb0C\xd7d\x06\x94X\x01{\u0095q\xdc\xe9\xd0sfwCx\xf0*\x11\xb0@\xde^\x1c\v\b\xd8\xdaEe\x01s\xf1\xddN\xb7\x93y\xee%I:\x89\"\xe1\xf4+\xe1)\xe4\x04\xfb\xf25\x1e\xbas\xbb\x86\xd3ݟ\xfa\x8b]\xf7\xe5D\xf0\xe9\x97:\xfat\xf2\x91\xfeD\xe7\xc8\r\xee^T\xc1ѯ\xd1\xe5\a,u\n\x95Z\xda+P\x13\xbd\x037\x9f\xb3\xb6U\b\xcf\xcf\xcei.\xb5\xef\xcapKm\xe7\a\xd9\x135v\u007fԡ\x83\xd7\xeb\xf2\x91\xb6a\xd0c\xdbtd\x10\x8f\x1e\xd9d\xf3\xc8jР|\x8b)7\x8bZ\x97\xa7\x9d\xb2\x9eJ+\x97\xd7\x109\x85\xb7t\xa7\x87\xeczv\x96z%\xf5\xce\f\x1cӺ\xf1df\xf5\x80\x9f\xce\xc4\x0f?\xc6\v_\xaf\xa42\xd9L\xfc\xf0\xd9\xe24H2\x13ߑ\x91Sw&+m\xa3\xd9)\xccĿl\xb3\xb9eo\t\xee\xca(0\xb7\xffb〴\x15\x92\x16\xc7k<\xf9\x14\xd3.ay3\xe3\xd2Z\xd4\xd1\u007f\xba\x98v\xb0\x1aw\xd7\xf7\u007f{\x85JU+W\xdc:\xdc\u007f\x85{$3\x98\x9b\xb0\xdb\xf5_\xda\xedo\xb1\xf43~\xa6\x1f\x1b\xb1\u007f\x1f\xea\x80\xedC!\xa9z\xda\xc9u<\x16ӗ\x91\xd2\xef\x01\x1e(\x8d+\x815\x81\xca\x02\x86==\x16S\x9b\xf0\xf3\x16I\x12\xbbo%*4W\"\xfc܍=b\u007fa\xd4\x17\xd7~\xc3q\u05eeѬ\xff(&\xaf\xf4\xfb\xfb\xf9\x05CqM\xf4\xcfO|\x9b\x11B\xe9B\xe7\xaek\xa76\xebS\xfa@\xac\xa9\xb0.gSv\xa1p\x03\xfa\x8fg\xa5\x17\x0e\xc9lDž\x1f\x11\xb2\xfb#p9W\xa3-5o\xd3\x14\x1e#Y\x9b\x1c\x19\xe4\xf5\x98\xac\x06MuEfv\xb9\x87\x19\xfff{\xc6\xf6\xaf\x03\xf2\x1a\"\xa7\xa8C\x88\xba\x9a\x8e\xd1\xdf3F\xea\xed\"\x86\xd5\xf88y\xed\xa5\xbf\x85\xcc\v_{\xe8z%\x95E~\v\xc9K\xce\x16\xa7A\x0f%\xbf\x85t\xed\xcb\xdazҼ\x91\\\xfa\x11\xd1\xf1U*=\x05\xc1\xf1\x8b\x8c-\xfb\x1c\xb2VHZ\x1c\xaf\xf1\x843?\x19\x9073.s7>\xd3\x1b\x05\xa5\x19;]Vb\xa4}\xaf\xfb\xc6ۇu\x06\xe3#\xb9\xc1S\xd1Iv\x0fK?\xe3\t\xf6\xb3G\x9dQp\x82\x99\xb5\xbcP\xed,=*\xfe\xc8̖~2\xfa\xac\x94\xe9\x8d\aǧ\x03\x18X\x83\xa8-`k\x8eȨo\x9dR\xad\x89\x196.\v\xaf\x8b\xaf\xbd~\xf7\xee\xed\xd3\xf3\x9f\xc5\xfdEl\x8b\xa6B\xf9\xd7\x1c\xedy\b\x96\xd3Y\x9b\x80\x80\xbd'\xeb^\xc0\xf0\xe5\x9c%\xaca\xb1x\xfa\x85\xc9b8X6\x12\xc7\u009b\x1d\xff\x87\xf8\xd3㞸ǀ\x14\x06\x04\xec=\x01\x01S\x89'\xe2\x04\x8a\xa9xS\xfe\x80\xf5\b\b\xd8{!x\xb7\x01\x15\b^\xd1_\xeb{\xd4wM\xff\xd5\x02\x17\xaa\x00\xd6\x03 `\xef\x05\xf3nOb@\x05\x82õ\x06\x9d\xa1v\x18\xf4\v\x88\x00\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x96\"\f\u05fc\x96\xed{\v\"\xeb\xd8\x03\xc0zEm\x01\xf3t5\x9b,\x03\xbe\xa8\xa4o\xe0\x96\xe9\xd6\xc0\xca,\\>\xb9I\xb2\x86M\b\xef\xb1-\xe9{\x17\xbf\x00\xcb_\xaf\x95\xe9k\x170S\xbc_'.\x18\xa3[X\xfci\x1a\x81\xba5\xaaކ\xb4\x0f\x1eC\x1c\x00R\r\x95\x05l\x9a\xb7:\xdd\xce6\xba\x8a\xa1$\xe9kj\xa3ɦ\x95Q\xb0\xc1\xd0Z\xcb\x12vm\xb9~$}\xf1\x97s\xfaP\xe7Eai\xaaGO\x12\xd9\xdd\xe1\xec\xf6N\xae\xc3n\xdf}'\xae\x8d\xac\x86N\x16\xc8G\x9ek\xddx\x15\x03\xc0\xfaFe\x01s\xb1\xb5\xef}\xbcS\x96\xb4Y\xe82N\xf3\x16[\x92\xd2\xcbD(du\x04/\xba\x8a\x03\x8b\u05ef\x1f\xb8N\x1cd\xf1Zq\x8d4@E\f\x1d:q!d}L \xcb0\xd2\x1a^\xe8\x1a\x15r\xcfh\x12\xac\u007f\n\x00\xeb\x01\x95\x05L\x88\x94\xe8\xe5=\xb2d\x8f\xe0\xceiO\x14\xdbv\x19\x89\x150\xd7\xd2\"\tF\x16\xee\x97G؉a\xee\x85(`/\xe2\x04S\xc2\xf2\x1a\xae\x18f\x15r}\xd9\x15\x18\x00\xd65j\v\x18a\xc6m\xb1\x06dIoS\xaf\xd7\xef\xb55y\x13\x17\\\x06<\xe5\xd9Y\a\xc4!dSAFn5QU\xbfVXu\xb9Z\x96;\xbe\x11\xa13\xae\xf2\xad\xe9{d\x8b~\xbe\xbd`\xd0\x1d>KC\"͕\tn\xad\x9b4r\xab@\r\xb5\bޯ)\xae\xbcI\x04虎\xe3\xbeyq\U00068f96\x06s\x8d\x84\xa2\b\x1b`l\xaf=\xac+\xab=\x1c\x94׀犅\x0e\x98<\x97t\xc1\xd2g0\x00\xacgT\x170/\xcf\xf3f_Tr\xa6\x9b$\xbbԿ\x1b]\x99\xb9\xe6\xf6_ \rMW\xa4\x1d\xb7^\xd5\xe6\x13=}hkAu6\x9bG\x96;ciޚ\x9b\x99S]\x8ed\xe3\xb6a\xee\xabG}g9\xb6\x92;\x8b<B#\x8c\xccN\xd8+\x8dv\xbb\x9d\xad\xe1\u007f\x85\xbb1\xd2y\xa8*\x88\xe7\xfa\xfa\x0eW\x16\x1bn\xd6\xeff\x91\xc3\xc2\x02\x166\xc0Ow_\xec\x1f\xbbWƽ\x93׀\x9frv\xb6\x95\xe7b<\x00\xd1v\x80u\x8e\xea\x02\x86\xbd\x1e\x87\x18\x8a(\x9c\xf4w[\x9c\x1e\xa7\xa5[yA\xf3e\xe4\xd3m>\x1a\xddL\x83i813\xa6\x01\xb8X`\xe7\xf0\x10R\x96\x9b\x8fv\xf9đo\x98\xd9>\xd2u\n\x9e8\xcfv\x94\x86\x90\xc3\xcc\xfd\xfeX\x88\x16Vŝ~\x8b\x83\u009a\xee!\x01\x93\x18t\x1e\xa2}\xb3Β\xe80\xaf#\\H\xb2\xe4CS7\xba\x85\x01`=\xa3\xbe\x80a\x1a\f\xb2[\x96\xb4Y\xfc,\xa9v\xf0+\x1fb\x91m\xceh0\rp\xe8\x9f'\xe40\xb7RX\xc0d\xb9\xf9JN\xf3W\x9d\xb5GK\xb8\x13,\xad$`\xf5G\xe7\xde\x11\fWXn\xd1\xcbp\xc1\x90\x80I\f^\x1a\x8e\u07b8\xf748'\xaf\x01\xe3~\xeeE(\x19%`-\x18\x00\xd63*\v\x98_p~\x8d\xf3\x01I2`zȒB\x90n\x15y\x80\xd8s\xcfs\x1a\xf2\xb2]\x8c7Ƃׄ\x05L\x96\x9b\xbf#\xb6\x8aLJ\x0e7\xf6\xdbO\xc7\x17\xb0\x13\xa2\xdf\xea,\xcb\ry\xafpD\xc0\xa4\x06o\xef]\xa8\xe4\xca\xeeD\xf7\xc0&\"\x91[e\x026\x04\xf1\x0e\x81u\x8e\xba\x02\x16h\x12\xc2\t\x12\xa9\x92&E\x01\x1bU[\xc0\xbc\xe8:\xdd0'~\xf9\xb6Q\x06{\x90\x10\x160Yn\xfe\x81\xd8**k\xa8\xf7\xfd\x82\xb2\x80\xdd{I;XO\x18\xaf¹\"\x91\x1eX\xd8\xe0q#\x91\xae\xb7}\xfaNY\rd\x9c\xca\xc2S\xcb\xeb\xa5\xd4i\x16?\xd5\x03\x00\xd6\x12\xea\n\x18nfa\xe9\xfd\x96\x1eY\xb2G\x1cB\xaa>\x8d\xa2 \x87(\x93\xeb'\x1a\x92\xecB,\xbc\xe1\x17,\xc8PX\xc0d\xb9\xf9\ack8L\x05%X\x15#`F#Ư\xa9_kL\xf0~5ަ\xafJ\x02&1h\xe5X\xc40\xe35Y\r\x84\v\x95\xa1i\xf8\xd2\xdc@^(85\x00\xacST\x160\x17\xdf\xedt;\x99\xe7^\x92\x9ci\xb18\xdc\x0eK\x8b\xea\x8f!\x1d\x199ug\xb2\xd26\x9a\x9d\x18\x9fB\xa5\x96\xf6\n\xd4\x14z\n9Ⱥ\x83\xe1\xdc\xf9A[n\xa1\xcd\x16\x1d\xc0\xa3\x95\xbb\xd0y\xbb\x8a\f\xfb&ħ\x90\x13\x82Դ\x16u\xf4\x9f.\xa6=\xa5\xc6\xdd\xf5\xfd\xdf^!\x9a\xf3\xeeO\xec\x19\xa2\xe8\xcez\xda\xc9u\ba\xaa\xc3\x06\xa4\xb2\xe2\xd6\xe1\xfe+\xdc#y\r\x18?\xe7B3\xf6\xa5\xb9\x97\xd1(\x06\x80u\x8d\xca\x02\x86==\x16S۠?*\xe9\x1fj3\xb7\r\xf9\x13\x17]\x0e\\\xfb\xb2\xb6\x9e4oD\xc7H\xbak\xa76\xebӻ\xe4b\xb2\x98\xdbk\xa3\x93Y\x84r\xc7\xd3Xnt\x9f'\xd8QYt\xa8\xfe~\xa5\xce8W\"\xfc\xbaQx`8w\xe33\xbdQ\x10\xa8\xb1\xd3e%Fҵz&\xf8\xbajY\xe6l1I\n\xbf:\n\x1b\xe0\xfb\xc6ۇu\x06\xe3\xa3\xe8\x1a\x88n\xe9E/\x98$ז~\x12\x03\xc0\xfaFm\x01\x03\x96D\xf0\x86\xae/*\xabES\xa1\xfa\xb4\x13\x00Xe\x80\x80\xa5\x06\xc1\x0e\xc3+Y\x867\x1b\x16\xa3\x00\x00\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x10\xb0UG{\x81\xfaљ\"x\vړ\x99\x00\xc0\xaaAm\x01\xf3t5\x9b,\x03\xbe\xa8d`\xbc\xdd\xd4\xe6L\\r\x859\x86\xd2,\xc9l\x16L'\xc7E/.\x11\xa6\x01\x9d\x93\xed\u007f\xd0\x13S\xba\xb5\t\x83^6\xa4\xc1\xafā\x94Ae\x01\x9b\xe6\xadN\xb7\xb3\x8d\xaeb(I\x06\xac\xe6Q\xf7\x03Ӄd\xa5W\x12\x8fmS]2\x9b\x05\xf3\xd6^ӊ\x95\xf9M\x9aY\x9e\xb1\xf4\x13\xf7*\xafwh\u0378\xa5\x98\x1f>\xbe\xf1j\xc2\xe3\x00\xb0zPY\xc0\\<\r\xec\xe3㝲\xe4C\x13\x1d4\xb9L\xab{\x85w\xcd\x12uD\x91\xb3q\x04lRs*&o\xa9'\xdeQ\xaa\x9c\x9f,\xf2\xc0\x19\xa5\xe8K\x00\xb0\x1aQY\xc0\x84\xa8\x8a^\xde#KZ\xd9\xf2\xf8\xb8\xe9A\x9cB\xab\x83\xa5\xea\x88\"\xf1\x04\xac\";Vŗzb\xa55\xfc\x17\x82/\xbb\"\x99\t\x00\xac\x0e\xd4\x160\u008c\xdbb\rȒm,\xba\x19n\xbf\x9b\xa0\xd4r0\xbe\x11\xa13\xae\xf2\xad\xe9{\xe8ڦM\x05\x19\xb9\xd5L>l{r6i\xf7ne6\xae\x03\xdaM[\xf6zHJs\xb2:7cOl\xe7ļ\x85E\x97tg\x8a!\xd82%&\xef\xcat\x8d\x06ã\x1b%\xc6Y2p\xbc`\xd0\x1d>\xfb\x8c\x1d \x02v\x83.*\xfd\n\xe3\xe0\xfd\x9a\xe2ʛ\xb3,۟\xf9y\xa8\xa8҉}\a\xb359\xfb\xc61\xf5\x8cm\xe2\x95.'|\xe9V\xf1j\xf2\xe5\xcd\xf4\xa5#\x94\u058c\xa3k\xf0\x96ksN\x9e\xd4n\x16\xbcmg\xd2U\x8fN\x00\x00KBu\x01\xf3\xf2<o\xf6ɓ\x03M,*\x91\xb9-a\xc9\x0fό\xa5yknfNu9\"wqE\xdaq\xebUm~\x80\x86[<r\xab\x9b\xd7\"\xaaj\xbd\x9b\xf3\x1b\xbaϡ\xcb$\xa9Ay\xcd\xed[bC\xab\xedG{\xe8\xc6o\xbe*`\x96\xae\xed\xff\xa8\x84\xbby\x9a+\xbb]\xd6Acp\u007f\xf5\xa8\xef,\xc7V\xb4'\x02\xf6}\xbd\x10\xd6\xe3\nwc\xa4\xf3P\x15\v\x062\x8azł\x8a'\xb6\xa2\x8a^˾\xb4!\x8c\x9d\xcd\x1b\x91\xb6\xeeRf\xd4\xe5D.\xdd7\xc0\x82\x90\u061cQ\xcd|`\xb3\t=:i\r\xfe\xbc\xec\xaf\xcfi\xd2M\xbf\xb8\xccj\x19@\x83\x18\x00R\x01\xd5\x05\f{=\x0e\x16\x8aH\x92\xf4\x99\xad\xde\x19O;\xffa\x9f\xb6-\x88|\xb4\xcb\xc7F\xb3VD\x9d\xe7C4\xd6\xf5u-\x95\xae\xaf\xb3\x88\x96\xcd\xe4\xec\xf1Ӏo\xd4G\xa7\xd9B^+\xb41UL\xd6\t\xa1\x8a\xa6'\x05\xa6eG\r\x17\xf1\b7\x8c/~\x85\xf1l\x1f\xe9f\x05O\x9c\xa7\xd9D\xc0:\x8aX\x10\xb6a\xee>\xa6A\xd6\xd8cI+\x12\xc3\x1e)\x9f\xd8g\xa1o\xdc',̮&\x8b\xc8Qy\xd4\xe5H.]6\x84\f7\x93\x92.\x0eI#5\xb4 ҫ\xfb\x1a9Dk7\xba\x85\x01 \x15P_\xc00\xbd/\xbb\xe5I\xaf\x95t\xc6\x06\xad+0\x03)?\xe4\xb0.\xdd\xe6\x9f'\xe4T\x90\xfb7{\xeb?\xf3\x0f\x03\xb4#u\x17=\f\x9bj\xa8g\x88E\xf1Vd\x12\x85\x90\r\xeb\f}D\x9cfqc=I\xbf\xea\xac=Z±\x18\x92g[[\xc5 \x92\xf5G\xe7\xde\x11\fW\xe8N{H\xc0\xe2\x9c\xd8{}϶L\xb4\x9d\xe5\x1e\xc1\xb1\x97#\xb9t\xb9\x80I\xfd\xf2a\x01\v\xd7p*\v\xd3`\x98\xa1\xf7\xdfMe\x1c\x00R\x00\x95\x05\xcc/8\xbf\xc6\xf9\x804I\x98\xf1\x06p\xd3@\xfc\x82\xcbE\xfe\x0e1\xb1]T\x1fڻ\xf1\xf1\a\xf3\xd0\x16:\x1d\xea2\x8ax\x834t~V\x9d&\xb6\x0e\x11\x9bU\xc0&\xcb5\x8c\xe0\xc7:\xcc\x04\xec\xf1\xa1Í\xfd\xf6ӂ\x80\x1d*\xa9<\xcfF\x8d'\x84hk\xdcY\xba3\x18\x1a\xbc)\x9fxhK\xce\xe7m\xb6\x9d\xdb\xe5\xb9R\"\x97.\x17\xb0\x1d8BX\xc0\xc25\\F^\x1a\xc47\xd4\x03\x1bB+\xf0I\x00\xc0\x12PW\xc0\x02M\x82\x8b\xe7\xa1) Ib\xcc\u20f9سI\x95\xc9\x0f9\x91ʷ\x8d2ȝ\xfc\x80\xced\xf0\xb5\xa4_ǸG\x12;\x96\xb9\x8e\x12\b\x982\x861\xfc\xb8H\x10\xb0\xca\x1aꩿ \n\xd8ԋ\x92\x0e\x9a\xaa?\xfa\x84\xc1\x82\x0e\xf94\xe2,V\xe5\x13\xe7\x15\xd0Q\xe0\x81\xed\xf2\\\t\x92K\x17\x05\xccĺ^\xf9R_YX\xc0\xc25\xb8\xd3\xf6\xba\xc7s\vB\xf3+\xea4\xab{B\v\x00\x84PW\xc0p3\x9b0\xe1\xb7\xf4ȒN\x9eȆ\xaf9\xe4\xbfV\x93p/\xa5\v1\x0f\xdc\x17䦮C\xec\xd2\n\x8f\xd1\x19\x05\x85t8v\xbc\x1a\xc7\x170wCt\xb8n)\x12\x01;|\x81\xec\a\xab\xc4!$\xc6#:\xea\xc3\x1f\x13\xbc_\x8d\xb7\x99y\xe96AE\x94O\x9cCu(\xb0=\xbe\x80I.\x9d\xbc\x16b<-4K6\xa3\"V\xc0F\xd1\x16\x84vz\xc4ぼ\xe8\xf0\xbd\x00\xb0JQY\xc0\\|\xb7\xd3\xedd\x9e{Yr\xc8\xfd\xb0ɪ\xfa\xd7\xfe\xfc {R'\xe8\xcf)Tji\xaf@MT\x056\x9f\xb3\xb6U\xb0\a\x82\xbd?ɻ~\xf782\xd1\t\xf1G\x06\xf1\xe8\x91M6OT-\xfbb\xc2uK\x98\xfa\xacc\xb6O75[\u007f\xfa{\xdc\xca]\xe8\xbc]ŕݙxk\xaf\xf9rbn\xb6\xd6\xf0\xe85\x91\xae\xdd\xf5\xfd\xdf^\x11\u007f[\xe4J\xbb$\x14T<q\x1d:x\xbd.\x1fi\x1b\x06\xe3\\\x8e\xf4\xd2\xf19ͥ\xf6]\x19nY3\xfd\x836\x9b\xe6\x88\xcd\xe6\x93\xd5;\xaa\xe9\xb1\xda<\xa1\x0e\xd8e\xa4<\x85\x1f\x00V\x1d*\v\x18\xf6\xf4XLm\x83\xfe\xa8\xe4\xa8\xc5l\x1dM6A\xfc\xc33\x9e\xc6\xdc^\xa2\xfet\xed\xd4f}J\xa7\xa25\x15\xd6\xe5l\xca.\x14:\x84\xae\x839\x99\x05mt\xda\x14B\x9b\x1c\x19\xe4\xf5XT-f-\x8f\xe3\x11,㸾b\xae\xb8\x8f\xe3\xce\xe3`Geѡ\xfa\xfb\x95:c'uz=%\x99\x1c\x9d\xcf:v\xba\xac\xc48\"\x968\xf3\x13\xd1\xff\xa4t\xe2\xc0\xe5\\\x8d\xb6ԼMS\x18\xe7rd\x97\xee?\x9e\x95^8$o搐F\xbc\xac\xde\x01\r\xcd\xdbTȜ`\xb6\xf4\x93\x18\x00R\x03\xb5\x05\fHF\xb5F\xf5\xd9$\xde\xcdǼ\xf3\xf3\xbe\xa1\x03Y\xa4\x13ܢ\xa9\x98OV\x00\x00V\t `\xab\x8e\xcb9\xf2\x99d\xcbO\xbb0o\f\a\xb4w\xb17\x1b\x16\xa3\x00R\a\x100\x00\x8f\xa6\t\x13(\x1ci\x91\xc9g\x00\x90\n\x80\x80\x018P\x91~\xac\xa5\xb7\xe5X:\xfc\x88\x1bH1@\xc0\x00\x82uO\xb6&{O\u0085\x0e\x01`\x15\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\xb6\x9ai/\xf0&3\xf9 x\vV`5o\x00x\u007f\xd4\x160OW\xb3\xc92\x10Z\xf9\xcb\xc1\x8b\x93\xbf=\xed\xe6.O\xbc2+\x87\x99\xae2\xa3ݳ\x9c\xcbcur\xe2J`\n4\xa0s\xb2\xfdc(m\xc1+U$\xb7=Bږ\xe1\x12\xd2\ri\xf0\x13n \x15QY\xc0\xa6y\xab\xd3\xedl\x13\xa3\x12\xf9L\x03M,\xe16\xd9\\6\x93,\x18Ɗ\xd2+J\x96ό\x1az\xcd\x05\xe1Xg\xcb\xc0[{M\x9c\x18\xb7\xf87ify\x86Ƕ\xa9N\xd94\x96\xe4\xb6n\x9b\xed\xebp\xfc4\xebƫ\t\x8d\x01`U\xa2\xb2\x80\xb9x\xaaR>\xde\xc9\xf6\xac=n&`\x81f\xba\x88\xdf@\xb3\xfaK\x1a\xc6aG\xa9\x98p\xd0%\x9a\x03\x9f\xe6&\xb4~O\xe2\x05\xe9\x9eԜ\x8a\xc9[L\x90\xee\x05\xd8\x0eE\x02@\x9eѬ\x9e\xef\x0f\x00X(*\v\x98\x10\x9a\xd0+\x84\xefp\x98}\x1e&`N\x13\r\xc1\xe339\xe3\x97S\x97\xf0\x12\xf2L\xc0\xf0o\xd0r\xaev\x1dO\xc0*\xb2cϺ\x00Q\n\xb3\x00[\x89\x80\xf9\xb2a)\n \xf5P[\xc0\b3n\x8b\x95\xf6\xb5|&\x17\x16\x04\xac\xe7.;pw\x19Gjq\xf0\x96ksN\x9e\xd4n\xa6\xee\xa2\xeb\xf9\x19\xdbi4\x1f\xab\x18`-\x1f\x87\x04\xac<\x87\x197\x15d\xe4V3Q\xf1}\x9e\xb7\xb9p0\xe7ntu\xe6-luiw\xa6XE\xa6\xa4W\xf3\xaeL\xd7h0<\xbaQb\x9c%\x03\xc7\v\x06\xdd\xe1\xb3\xcf\xd8\x01\"`78\x8eӿ\xc28x\xbf\xa6\xb8\xf2\xe6,\xcb\xf6g~\x1e*\xea:\xa0ݴe\xaf\x87\xa44'\xabs3\xf6\xb0^\xec\xc1lMξqL\xbd]\x9b\xf8P\xae\x14\xcd\xf1\x8a\xec\xac}\x82\x93+\xd46yR*`\xf8Lz$\x90\x1b\x00\xa4\b\xaa\v\x98\x97\xe7y3S\x01k7\x16\x05\xacMX\x06~@\xf5Ga\xfe\xbc\xec\xaf\xcfi\xd2M\xbf\xb8\x8c\xf1\x11\xcd\x19\xeb\x19M9\x91\x86\x01\x16\x03\xc3F\xfb\x83\x0ed\xf59?G\xac/S\x91v\xdczU\x9bO\xb4\u05f7M{\xe9\xee1\x84B:\x10f?\xdaê5_\x150\xfb%\a\x1f\x95p7Ose\xb7\xcb:h8\xee\xaf\x1e\xf5\x9d\xe5hT\"*`\xdf\xd7s\x1d4}\x85\xbb1\xd2y\xa8\x8aŋ\x1c\r{\xdez7\xe77t\x9fC\xe4\x1a\xb1\x06\xe55\xb7o\xa1\xb1\x89\xac\xa8\xa2ײ/m\x88\xf4_\x9b7\"mݥLi\xe44\xccl\xf3[Z\xb6gе\n\xc3m\x93%\xe5\x026 I\x03@\x8a\xa0\xba\x80a\xaf\xc7\xc1B\x119\xa9\x8c\t\x02\xd64Ď\f5%,\xb8\f\xb4 ҅\xf9\x9a\x05t\xedb}\xad.\xc4zU\x92!$\x85\xdd\xeeVD]\xeaC4huy\x96\x87$\xabc\x05l\xb2N\x88p4=) _\x1b\xdap\x11\x8fp\xc3\xf8\xe2W\x18\xcf\xf6\x91nV\xf0\xc4y\x9aM\x04\xac\xa3\x88E\xe9\x1e\xe6\xee\x93\xd7\xc7\xc2cIk(H\xf7L\xce\x1e?\x8d?GgTh\xb6\x90\xd7\n-I\xf9,\xf4[\xe0\x13\x1a\x87\x17k\xb2H\xef\xab\\\x8b\xe5h\xf2H\x97j&\xb7@\xd66Y3e\x02\xe6F\xb70\x00\xa4\x18\xea\v\x18\xa67c7\xf5x\x05\x02\x01wS\x80\xf4hڄ`ֽmI\xca}pNe\x91\x17\x17\xa2=\xbf\x8aOXN\xde\x11\xfa*\x11\xb0K\x83ւt*%\xa5\xdb\xfc\xf3\x84\x9c\n\x1c\xc8`\xb3\x1b\x9c\xb1\x02&2\x89BȆu\x86>\"N\xb3,D$~\xd5Y{\xb4\x84\x13CD\xb6rL\xbfp\xfdѹw\x04\xc3\x15\xba\xd3\x1e\x12\xb0\xbb(\xb2г\x86:\xaa\xceih\xd2{}϶L$\x84\x88<\x12Ε\xa0\xf9\x82\xbe^G^i\xdbd͌\x12\xb0\x16\f\x00)\x86\xca\x02\xe6\x17\x1e4\x8e\xf3\x81I>\x84\a\xf7\b\xb3\xc1\xda{\x12\x15]\x0e.\x93\xbb\x9btGh\x0f\xec\xd3},go\x01}\x95;\xf1}iԳ\xb5]Ԥ\xfd\xe4VgJ\xeb\x8b+`\xd8f\x15\xb0\xc9r\r#\xf8\xb1N\x88q\xfb\xf8\xd0\xe1\xc6~\xfbi1HwI\xe5y6j<\xc1\t\x9c\xa5;\x83!q\xb9\x8c\"\xce)\x16\xb8\x9bŢ\x1dڒ\xf3y\x9bm\xe7vy\xae\x14\xc1\x89oC\xa3Ҷɚ)\x13\xb0!4\x80\x01 \xc5PW\xc0\x02M\x82_\xe7\xa1)\x10\xf0R\x1cf\xaf7\x80\x9d<\x1d\x0e\x85&W\xa8\x88;m\xaf{<\xb7\x80\xaaj\xc56\x96\xb35\xd2\x03\xa3\xf3\xd2\x04'~&\x15\x88\xf2m\xa3\f/\x0e\b\xa1\xad\x1d\xf1\x05L\x19I\x90\xee\xca\x1aꩿ \n\xd8ԋ\x92\x0e\x9a\xaa?\xfa\x84\xf1\x8a\xee\xf84\xe2,\xd6\x1eI\x9c\xd9H0\xed\xbc\x02\xfa\x9e\x1d\x88\x1f\xa4\x1bkhTolB>i\xdbd͔\tX\x9df9\x1f\xb5\x02\xc0\xb2\xa0\xae\x80\xe1f\xaa\ad\b\x19\xeaky\xc4y`T\xd7z՟\a6\x8a\xb6 \xb4\xd3C\x93V6\x82jA\xac3XX\x88\xf14\xb2\x84\x04lK\xf5x\x1d騱\x99\xed_\x10\xb1(\xd5R\u007fTy\xac\x80\xb9\x1b&\xa3\xb3$H\x04\xec\xf0\x05\xb2\x1f\xac\x12\x87\x90\x18\x8f\xe8\xa8\x0f\u007fL\xf0~5\xdef\xe6\xa5ۄ\xf7×]H\x9f\x05\x1c\xa7z\x14\x91\xaa\x1c\xea\xb3\x0flO$`9\xd4u\x96W(k\x9b\xac\x99R\x01\v\xe4%\x88/\x0e\x00\xab\x14\x95\x05\xcc\xc5w;\xddN\x8b8\x13?\xe0q\x98=T\vܦ\xde\xc9\xde\x15\x98\x89?\xaa\xe9\xb1\xda<\x82N\x94\xa7\x9d\xb2\x9eJ\x13\x1eϝ\xd3\\jߕA\xaeg\x9cy\xbbw\xee=\xf2\tƧP\xa9\xa5\xbd\x02\x11\xc9\xf5d\xe7\\oۯ\x89\x15\xb0}(\x81\nL}\xd61ۧ\x9b\x9a\xad?\xfd=n\xe5.tޮ\xe2\xca\xeeL\xbc\xb5\xd7|917[kx\xf4\x9aH\xd7\xee\xfa\xfeo\xaf\x88\xbf-r\xa5]\x12\n\xf6\xfe$\xef\xfa\xdd\xe3\xc8Dg\xd7\x1f\x19ģG6\xd9<\xb8\x0e\x1d\xbc^\x97\x8f\xb4\r\x83\xd2\\)\x1a\xb4g\xb0\xa7 \x8bJ\xaa\xa4m\x91$\x9b\x89\u007f\xd9f\x13\xde\xf6\xcbh9\u007f0\x05\x00˃\xca\x02\x86==\x16S۠8\xbb\xc0C]`\xcd,\xd5ej\xf7$(\xb6L\fh\xa8WkS!u\x82\x05~\xb3=c\xfbׂ\x98\xf9\x8fg\xa5\x17\x0eal!G\x1b\x88\x8c\xe5ji\x8f\xa5k\xa76\xebS\xf6\xf8\xce[\x91\x93\xbe\xebA\xac\x80\x99\xb5|tV\x98`\x19\xc7\xf5\x15s\xc5}\x1cw\x1e\a;*\x8b\x0e\xd5߯\xd4\x19;\xa9\xd3\xeb)\xc9\xe4\xe8|ֱ\xd3e%\xc6\x11\xb1ę\x9f\x88^)\xd7\xc1\x9ĉ6:\xe3\x8b\\\xac#\x83\xbc\x1eÁ˹\x1am\xa9y\x9b\xa6P\x9a+%\xaf\xee`fv\xb9\x87&%m\x8b$\x8f\x88N=\xf6\xab\x03[\xfaI\f\x00)\x87\xda\x02\xb6\xaa\xf0n>束\xf7\r\x1d\xc8Z\x8a\xfb'\x81\x13\xff\x03Q\xad\xb1$3\xf9@\xb4h*\xe6\x93\xd9\x00\xc0\xeac]\vX{\x96\xd0\xe1\nhc\xe6\xd4/\x80\xe5\x170|9G>\x93l\xb9\xf0f\xc3b\x14@J\xb2\xae\x05l4\xcd\xc1\xb6\x8e\xb4\xc8L\xab\x85\xa3\x82\x80\x01\x00\x90q~\xef\xa6\x00\x00 \x00IDAT\x90u-`\x81\x8a\xf4c-\xbd-\xc7җ\xf2;fW\x17\xaa\x1eT\xfd\xb9)\x00\x00\x12ֵ\x80alݓ\xad\xc9\xdecMf\xa6ħ\b\xa1\x8d\xaedV\x00\x00,#\xeb\\\xc0\x00\x00He@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00P$\x15f9\x82\x80\x01\x00\x10\x8b\xa7b\vڟ\xcch\xe5\x01\x01\x03B\f\u05fcNf\xb2\xec\xb4\x17x\x93\x99(\xb1\xc4b\x80\xb7 N$\x9d@^\x1eߣ\xfe\x02W\x8bFm\x01\xf3t5\x9b,\x03\xa1\xc5\x1f\x1c|x\x12|\xaf\xea˱~\b\xaeq\xe2\xe2]\xcbǣݜ1\x88\xfb9n\xf7\xa3x&S\xb5\x9f\x95\x18\x1f\x9d\x98\x88w|a\xdc\xe1Z\x83\xf8>\xc7q\xb7\xf1m\xf2z/\x81\xe9\v\x1d\xf7K\xb2\xf9\x92F\x83{\x11\xdf̾[\\#[\xff,\xbe\x91\x8c\x06$.C\xfb\xd7ke\xfa\xda`b\xe3\b\xe1b\xb1\xd0\x06q\x9f\xd5>\x8dw|\xa9|\xc5qt\x15\xdd\x0e\x8e\xfb*\xea\xc8ءa\xa5\x02\x1f\x8a\x0fܠ\x864\xe5\xdf\U0004fce5<W?*\v\xd84ou\xba\x9dm₆>\xd3@S\xf8\xc0P\xfcR\xcbH\xef\xfb-\xe3\xf7\xbd]'\tK\xfb\xe8\x89RR\x82rnb\x83\xb91Nodz\xfd\xdc\u061cB\x01\xca\x13\xdd\xd9\xfe\xbe\xf3\xef+\xa5\x9d,$\xd2\xdb\xfb\xdc\xed\xd7\xf8\xf5\x1d\xee\xfe\xdb\x04\xb6\xc1\x89/\x8b0m\xbd\xbd\x93K \x9bs\x13\x87j\xed\x84\xfb\xdc\b^\x10\xbfI3\x8b\xa9Ӈ:/\xea\x13]\x82\x94H\xb1Xh\x83\x1eݯ\x89\xaf\xfeK\xe4e\xf1\x9d\x1f\xc8\xe6\x87;\xc5/\xa3\x8e\f\x17\xf7\x8b\xa9\xa4\x1f\xf7R\xf8 \r\x92\\\x99u\xe3U%\x8b!$\x0f\xe8\xb0ZQY\xc0\\<\v\xca*\xae~o\xedq\x8b\x02汬\x90\x80\xed(Mf\x91\x84\"\x89\x80\xd5\\PJJP\xceMb0\xcb]\xfc\x92tz\xb8\xd9\xd8C\x02\xb5\xa7IW%\xf8\xe5\xfb\t\xd8\v]#\xdbNqc\xe4\xf5\x117\x95ؼ\xb5H\xd8>N$`\x18\x1f\xbdF_\x9f/P\xc0&5\xa7\xc4\xd4\x0f\\'\x0e\xc6mp\x14\x91bJ\xb0\x06\x05\x8d\x95\tL\x96\xc4\t\xa1\x8bz\xefD̑p\xc71\xe9ǽ(\xbc\x85\xc20\xf9C4Hzeg4J#š\x14\t\x13\xaa\xb2\x80a\xd6\xf5\xf2\xf2\x1e\xbaq\x98}\u009a\xf8\xb8\x97\xef5\xad\x8c\x80\x85\xe3\x0f-\x15\xa9\x80U]PJJP\xceMb0\xcb=*\x9eM$`G\x99\xf4Lq\xa1/\xfe%q\xc5 Կ\x1c\x026\u05f9\xb0\xbeTEvȷ\xf0\x82[\xc40,RL\t\xa1A\x9d\xf1\u07fe%r\xfe\x1b\xb6i<\x1f\xdf$\xe9ǽ(\x1cHX\xfc\xe9C4Hze\xbel\xa5\xc5X@\xc0\xe22\xe3\xb6X\xe9\x03Z\x9f\xc9%\x06\xf5\xc03\xbePp[U\xb1\x8a\x8b*\xe7\xd3\x1d۞\x9cMڽ[c\x8c\xcc[\xd82\xd1\xeeL\xd18S\xfe}U\xd4x\xb3R_\xfb=\x8dJ+P#K^\xe3t\x9d_\x19>;\xfbB\x96K\xbeA\xef\xd7\x14W\xded\xff\x83\xf6\xdaú\xb2\xda\xc3A\xb9A\x84Y\xeeEU\xbf(`\xe1b\xad\x1c\x1d2\n+Q\xd7\x1b\xa8\xda\x04Gd\x06\xcft\x1c\xf7͋\x8bG\xf5\xb5凞\xe0\xd7\xeaS6 \xe5抅\x0e\x98T\xc0\xde^0\xe8\x0e\x9f\xa5\xee+Ҋ{b3\xc9\xc0\xb1\xdePr\xe1\xcbh\x01S\xaeW\x100,:\v\x05י\xac2\xfc\xe2B\x99\ue410\xf6g~β\xe6ʄ\xf7\xe1\xe6⊝#\x1fN3n&\xafg\xb0\x04\xa1A\xf5\x06\x9aVz\xd7%\x9f\x101\xe8\xac\xd1Wu\x06\xa3\xce\x16\xb6\x95\xd6\xc0\xc2{b|\xa1Q\xd6\xe2\xb7zN\x1c\xcb+\u007f\xdc\xf2w]\x81\xf1\x8d\xe4\xfa]\xe5[\xd3\xf7ȖȽ\x9aku\"\xa75\xf7z\xdc\x06\xcd6\xfe\xb2\xd88a\x18\x91\xbeg\v\xfb?;\x93\x1e\x89\xdb\x17\xa6\x17\x04L\x19/\xcf\xf3f\xf6\x8di\xed\x0eE%\xa2\xac\x84\x80\xf9\x06l\xb9\x856\x9b\x8d\x0eh\x87Б[ݼ\x16Ŭ\xac\xbc\x1f\xed\xa1\x1b\xbf\xf9\xaa\x80\xd9/;\\\xc4U\xf6\r\x97\x91\xaf\xe1\xd9\t{\xa5\xd1n\xb7?\x97%\xa7\xfat\xdc\xe1۷\x0f매\xb9\xa4\xc3\xc3\xdd\x18\xe9<TE\ue267\xbb/\xf6\x8f\xdd+\xe3\xde\xc9\r\"\x10\x01\xeb\xac\x15\x05,\\\xecu}\x8d}\x96\x940ֿ\xc2/\x0fs\xb5\xb7\xff$x\xc8\xc2\x06s}}\x87+\x8b\r7\xebw\xbf\x9c\xb5\x97\xb4\xbeƯ[KH\tE\x03R\xee)g\x17\xce6ō\xcc\xcd͍P\x01\x1b\xe6\xbez\xd4w\x96{,\xb4\xe2P\xeb\x9d\x12\xda\xdbxQRy\u007f\xb8\x96\x8b\x160\xe5z\x8f^\x99\x9b\xeb0b\xd1Y(\xb8Τ\x95\xe1G\xc55w\xc6Z\x99?\x1c\x8f\xa2^\xa1\xae\xa7\xf6>\xae\xd5n\xff\xcb\xe2\x8ayK\vl>\xf2\x99~Z*[Ɩ4h\xf6y#w[v\x91\x92w]\xf2\ta|\xb1蛑o\x8a.\xca\xcf\x16\xb1\x95\xd6p\xaf\x06O\x18&p\xd5=y\x8b\x1f\xdb\xedz\xd6)W\xfe\xb8\xe5\xef\xba\x023\x96歹\x999\xd5\xe5\xf2\xa0Ȟr\x94\x87>A\xa5\xeex\rz{\xf4\xb3\x8e\x11\xa2]\x9d\xd2\xf7la\xffg\x031Z5?ݻcIˬ\xab\x8f\xea\x02\x86\xbd\x1e\a\x8bJ\xe4\xa42\xb6\xb2\x02\x86%C\xc8\xebZ*]_g\xc5Lޛ\xac\x13B\xa5MO\nD-\xf2\\t\xe8\xaf\xe4\xdf\xe4\x10K+\x0e!\x8b\x8e\x92\xf1\xd3\xdb\xc35\xb2\xdca\xe61\u007fL\xbf\xab;\x0f\xd1\x1b\xa3\xb3$\x18UC\x18\"`\xaf\xf4\xaf\x98\x80I\x8a\xddg_\xb0\xf8\x04\xcd\xf8\xe1\xf6\xbf踒>y\xbd\xa42\xee\xf4[\x1c\xa4\xa3\xb7+\xf5\xe4\xa5\xfeJ|\x03<\u0089\xff\xceS\xe2\xd73\xb9\x9dg\xfb\xc8)\x83'\x98b\x14\x95\x90\xbe\xc8E\xdaLc%ˍ\x12\xb08\xf5\x1e\xa5U\xb1\xbe\x820\xd6\x16F\x9e\x91\xca\xe6\x0e\xd7\x12\xe1\x9d\xeb\xa3\xfep\xd2!\x0e\a\xa5\x8b\f!\x17Q̜\xc76\x9f\x84\xff\xa7\x18B\x83.ҷ7λ\x1e\xf9\x84FX\xe7f\x8c\xb9\xec\"g\x93\xd8Jj\xb0\x97\xe1F]#\xfe\x8c\t\xbf\xe4\x9d\xc4X\x1f\xf2*(}\xdcQ\xb6J\xe4\xa3]>\xd1\xd9\"\xa1k\x13\xda\xc4V>Wn\xd0Ez\xb9\xf8\x06\x110\xe9{\xb6\xa0\xff37\xba\x85\xe5\xec'\xdd\xd8%-\x92\xa7>\xea\v\x18\xa6q!\xbb\xc9\x00\xd2\x19\b\x04\xdcM\x01Q1VZ\xc0\xdc\xd9[\xff\x99\u007f\x18\x90w\xaf$L\xa2\x10QCH\xfa\x14]\xf4\b)\v\x18\x1b\x9bur?Hs\xeb\x8fν#\x18\x88\xa6\xbc4\x1c\xbdq\xefip.\xba\x860D\xc0pm\a\x130I\xb1g\xdc\xdc\xec\xfd\xb7\xef\x8a\xc4\t\nsc\xb5\xf4\xb6\x93\x18\x90ʊB\xdf\xf2\x8f\xf4\xa4\xb7\xa6\u007f\x84\xe3\x1a\xe0~N\x9c\x0e1\xc5\xddy\xfc\xf8q\a\xf3\x81\xbd\xea\xac=Z\xc21/5핰f\xbe\x15\xe6W|\x13%`q\xea=z\xf6\xf1㋱\x02\x16\xaa\x8c(\x86d:@{2\x01KRl<\xcd\xef3\xfb\xe65\xe3X\nm\xd0p\r\x9b\xed\x11\xe7]\x8f|BW\x04\x8f\xfc\x89/\xb1\xf4l\x12[i\rܬ\xf1\xa2q\x96cM\x95\xbc\x93J\x02\x16\xef]W&_\xc1\xab\xee\xad\xd6\xe4\xa0l\xcdIo\x9c\x06\x05\x85\x93NE\t\u0602\xfe\xcf\xdc,V\xa8\x14w\x17\x9f\a=0%\xfc\x82\\\x8d\xf3\x81I>\x84\x87e\xad\xb4\x80a\x1f\u007f0\x0fm\x89\x1f\xdc\xc2f\x15\x88z\xba,\xb9\xc1\xe2\b\x18\xfbϲsO\xa4\xb9'\xc4~\xceY\x92~{\xefB%Wv'Q\x0f\f\xf7W1\x01\x93\x14\x9b\xd3Mup\xad\xcf9\xf2\x0f\xf9\x989j\x82Ƴ\xf2zqUؙ\xf6\xee\xb3~\xdc_\x16\xc4q\r\xf0Dh((\xf1\x81=>t\xb8\xb1\xdf~Z\x10\xb0P3\x1f\vc\xcdh'~\x9cz\xa9\x0flJx\\'U\xa2p\xb2\x83\x93\xcc\r\x19\x8c\fe\x94\x05,I1\xff\xc6\xf1\xcb\xe8_\x9di\xf2/!\xd6 Av\xe3\xbc\xeb\x91O\xc8\xc8.\x1f\xd7\xd6`ى#\xb6\x92\x1a\x82ES\xc5ϊ\xa7t\xc2\xe7&\xf5[\xc6\nX\xbcw]\x99\xfc\x1d\xb1y\rZމ\x9c\xbf\xd1\xd6\xc5i\xd0\xf7\xc2#\x9c\xd9(\x01[\xd0\xff\xd9\x10\x1a\x88>\x1d\xf9wG+sC.\x16u\x05,\xd0$\xb8+\x1e\x9a\x02\x01/\xc5a\xf6z\x05M[I\x01\xa3!u\x1f\xd0G\xf1\xbe\x96\xf4\xc5\x06\xea\x88\x11\xb0{/\xe5ɢ\x1bt\xff\x1e\xf7V\x9a[\u007f\xf4\t\xe3\x15\x91\x80F\xea\xc1\xe8\xd3wF\xd5\x10\x86\n\xd8l\xf1\x98\xd0\x03\v\x17Õ}\xa7\x8d\x95\xfdt i`g\xc0\x8d\x95r\x03\xe9\u007f\xe9\x8d\xf3\xf8<\xb3\x8ag0\x1bz\x9a*\x11\xb0\xca\x1a\xeav\xbb \x17\xb0\xbf\xb2[\x04_\x8c\xe9\x81)\xd6\x1bv\xe2\x8b5|\x13\xa5Dc\x9cd\x8a\xabO\x13\x9e\x8e\x1a%`\v,\x96\u05fc\xf3Ӽ\xf6<,ChP\t-\x1b\xe7]\x8f|BW\x8e2G\xfdQ\xda\xf9\x8a\x9cMb+\xfb\x00\xee\x18\xb0\xa1\xa3\x92\x9dD&\br\x01\x8b\xfa\xb8\x95\xbf\xa4d\xe4\x1fP\xc8\xf4\xb3\xa7\x90T\x9b\x15\x1b\x14\xd43\x9f\xd8\u007fD\x04\xec\x9b\"\x1c\xb7\xc5\xf2\xff\xb3:\x8dBg\v\x9eB*\xd2̦\xf7\xfa-=\xe2\xfe\x8a\xfb\xc0\n\v1\x9eF\x16\xf2)\n3\x8f\v\xe5\xc1a\t\xee\x86I\x9c\x00\xa9\x80\x19\x8d\x18\xbf\x16\x1c\x1d\x91dQ\x19\x91\x81٣FY\xee\x98`\xd5x\x9b>Od\x93\xa4\x8cעj\b\x9f\x98\n\x18\xbeXO\x05LR\f\xd7\xdfЍp\xd7\xe8?b\x99\x81\x0eO\x83\xf4\x9fRj \xbdS\xfe\xa4\xff\x8b\xfeO4\x11\xcf\x00_\xa8d_\xcdR\x01;|\x81U+\x170\\s\x98\x9c\xed\xb9>J\xc0\xe2\xd4+\x110=\x19\xa8\x05\xff%J\x89f\rFڗ\xba!Hp鶀h\x1c\x11\xb0\xc5\x14+\xfdgM\x17:\x165\xb3OhС\x1bS\xb7\xe3\xbd\xeb\x91Oh\x84\x19\xf4\t>\xb0\xf0\xd9$\xb6\xd2f\xd6\u0590o\x05c-;\x89\xb2\x80)}\xdcr\xdb\xc9:\x85\x89\xd4q\xa6\xf6\xb8\xb3\x84\x91\xa5r\x83.\x94\x11\x91\n^d\x02\x16y\xcf\x16\xf2\u007f\x16\xc8\xdb\x1bs.\x10\xb08\xb8\xf8n\xa7\xdbi\x11g\xe2\a<\x0e\xb3\x87\xceΛ\xf1x̽\x1eub \xca9\xa7\xb9Ծ+\xc3M\x05l\xf39k[E\xe8AX\x84}H\xe9\xf3\x15\xf9\x8b]\xf7\xe5D\xf0\xe9\x97:\xfaȌ\xfc\xbbw\xf4\x9f\x16ffG\x92E\\M\u07fdʒ\xe7\xf2\xdc\xc6\xdd\xf5\xfd\xdf^\xa1\xffB\xad\\q\xebp\xff\x15\xee\x91\xdc |\xe2\xb91\xae\u007f\x16?ҳ\xa7\x90\x91b\xf8\xb6\xbe$Xɾw\xcb8C\xebH\xffi\xfds\xa9\xc1\xbb?\xb1GM\xa2g+h\xa85\b\x02\x15\xc7\x00?\xe7\xeeЍt&~+w\xa1\xf3v\x15\x19uLH\x9b9\xa57\xdc\xfe\xe63Nw\u007f\n\xbf\xa43\xf1;\xec\xf6\x97q\xea\xa53\xf1'f\xc5\x13\x18\x0fݹ]C\x8b\xc9\u07b3G\xfa\x13\x9d#7\xc4\xdf-\xb9\xd2.\xb1\xad\xf0\x14r\"\xb8\xc8b\xb8!#3\x90\x9b^\x87eL\xb1\x1b\xf7t\xed\x97'\xe2\xbd\xeb\x92O\xa8\x9ek\x1cn\xe4\xea\xe5\x1f\xac\xd4V\xf2\x01\xdc\xd8}\a\xdf\xd9M4T\xfaN\xceM\xd8\xed\xfa/\xedv\xe6\xa3W\xf8\xb8\xa3\xde\xf5}hsT\xefg~\x90=\x19O\xf0\xa5\xa9ܠ\xbf\x18\x0ew\xf6\x9f\xd73\x01\v\xbfg\v\xfa?\xbb\x8c\x94~\x8d\xf2@i\\\xb9\nQY\xc0\xb0\xa7\xc7bj\x1b\x14\xbd\x14\x1e\xea\x02k&\x89\a\x827l\x05܆\xfe\xe3Y酴\xf3\xd7TX\x97\xb3)\xbb0F\xbf\xb0Y\xcb\xc7\x16\vq\x8d\xe38\xdd\u007f\x14\x93W\xfa\xc56w\xe33\xbd\xf11;\x10I\x16ݼRb\xb8\xf8\x97\xa8\\<v\xba\xac\xc4H\xff\x13\xef\x1bo\x1f\xd6\x19\x8c\x8f\xa2\rB'~\xb4\x9b\xce\xeb\t\xd6\b\x02\x14.\x86\x1f\x93Aĝbj\xfb/\xf7\x1a\u007fY|\xe8\xecsY\xbd\xcf\x04\xe7\x87\xd0A\xc0\xb8\xa3\xa8CL\xc51\xc0\xadzڗ\x12~\vIg\x99\xdd\xc3\xc1\x8eʢC\xf5\xf7+uFY3_\x9c\xfd\xech\xe3}\x1dI^\x14=,\x17\xe2\xd4\xcb~\v\xd9'\xd6\xff¨/\xae\xfd\x86\xd4 \u007fϞ_0\x14ׄ\xa6\xe0\x9e\xf9\t\xbdk\xe6JX\r\xba\xe7\x8b+F\xfe\x8d\xb2\xfe\x157l\x96w\xe5\xe9$8\"\xcdS\x95e\xb4O\xa7\xf8\xaeK>\xa1`\xe7\t\"\x8dA\xf9\a+\xfb\x84\"\x1f\xc0\x88\xfe\x19\x9e*\x1e\x96\xbf\x93Oŷ\x84I\xab\xc2\xc7\x1d\xf5\xae\x9b6G\xbb\x9a\xc6\xd3ؓ\xa2\xf8_\x9aq\x1a\x84_]9\xac?\xfd\x98\tX\xf8=\xc3qZ,\xbd2[\xfaI\xa5\xd3Lo<8>\x1d\xc0\xab\x1e\xb5\x05l\xfd!\x9d\xaa\xbf\x9a\t\xde\xd0\xf5ᕦZcIf\xa2\xc4\x12\x8b\x89\xac\xe4'Ԏ>跶\xe0\xc4_\f-\x9a\x8a\x98\xa9\x8f\x8c\xf6<\x04\xcb\xe9\x00+{{,\x8a`\x87\xe1U2\x9be\xe7rΒ\x1c\tK,&\xb0r\x9fP\xc0\x9c\x15\xe3s}/\x16-`\xde\xec\xf8\xcfݧ\xc7=q\x8f\xad\x1a@\xc0\x96\x9b\x95\xbb=\x80\x85\xb1r\x9f\x90G[\x1dw\xe2\xe1\x92X\xb4\x80\xa5< `\xcb\xcb\xf7\xcc\x19\x9c\xcc\nX9\xd6\xd2'\xf4b\x84\xbb\xf9\xa75Җ\x05\x02\x02\xb6\xbc0gp\x825\xff\x80\x95f-}B\xc65Ԗ\x05\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x96j\x04\x02\xf3\x01\xfa\x97\xcc\x0e\x00\xd6\x01 `)\x86kG^\xde\xdeO\xf2\xf2\xaa?\xe8o\xe8\x00 5\x01\x01K-\xe65hg\xe1G\x19;wl\xf8W\x85P2\x00\xb0\xceP[\xc0<]\xcd&\xcb@\xa8\xf7\xe0\xe0\x85\xd0\x01>\x9b\xc5\xd4>\xae\xfc\xab\xf8\xb5\xc8\xd2\xc3\xc3\xfb>\xae\xfb\xdbߜ\xff\xdf\xdf\xfe\xef\xc7\xfb\xbc\xc9l\x01`ͣ\xb2\x80M\xf3V\xa7\xdb\xd9&.h\xe83\r\xb0\x15Y}\xe6v\x87\xfb\x81\xb9}\xcd+X(\xa2\xfbR\xc2ÿe\vV\xcd|\xb2aÆ@\xe9\x86\r\x1f\xd5IƐ\xbdJK\xd2\x01\xc0\xdaGe\x01s\xf1tY\\\x1f\xefd{\xd6\x1e7\x13\xb0\x1e\vuI{M\x0f\xe2\x17\\\x1b\x84#\xba/:<|\xf0^\xc9i\xba\rx\xaa\xf3\x89\x80\xfdh\u007f\x83K\xb2\x8e\xc1\x8e\xa8e\x94\x01`\x9d\xa0\xb2\x80\t\xd1\xee\xbcB$\"\x87\xd9'\xac\x89\xdf&,Gכ\"\xa1\xe8\x96N\x95L\xc0\x16\x11\x1e~\xaa\x86;+\x84\xa4\x0e\xf8x\"`\x1bG\xbd\xd2uX⬢\x0e\x00k\x1d\xb5\x05\x8c0\xe3\xb6Xi\x8f\xcbgr\x89A=<B\xb4\x82\x81[\tJ\xa5\x16\xaf.\x96\x19n\xde,+\xee\x93D\xab\x97FtO\x16\x1e^\xce\xecM\xce0\x1c\u07b3P\x01sE\x86\xdbV1^e\xbe,.\xfd1\x94ք'5(\x8f\xd94\x15d\xe4\xc2sK`\xed\xa1\xba\x80yy\x9e7\xb3[\xc9\xda-\x8dJD\xfa\x16\xcdQ!\x17S\x97\xb9\x13\x86\xceV\xbd\xfe^m\x87$Z\xbd4\xa2{\xb2\xf0\xf0R\x82\xfd\x06]\xa3\xd0U\x9b{A\xf8:J\xc0|\x03,\f\x84\xcd)\x8bK\xef\xb1m\xaa\xc3x\xf0\x88\x86\x9aT\xa4\x1d\xb7^\xd5\xe6\xc3\xdc1`\xad\xa1\xba\x80a\xaf\xc7\xc1\xa2\x129\xa9\x8cI\x05l\xc0\xbcf\x9e\xab\xf5Ѹ\x85\x9d,\xba\xb54Z\xbdt\bII\x14\x1e>\xc25\xaejJL\xd2\xf5\x9e\xb8\xff\x1c%`X6\x84\x8cĥ\xd7\xd0\xf0<u\x1aL\xfbhfL\x03eE\a`\x06\x80TG}\x01\xc34.d7\x19@:\x03\x81\x80\xbb)\x10\xea\x16\f\xf2\xb1\x01\xd5S\x95\xc6\x12L\x03\x95}K^\xa5\xd1\xea\xa5\x02\x96,<|\x84\xfbE\x9f\xdd\x17W\xd9|>L\xf8_\x89\x05,\x1c\x97>\"`\xa5\xdb\xfc\xf3\x84\x9c\n\f\x00k\v\x95\x05\xcc/\xc8\xd58\x1f\x98\xe4Cxh\xce|\xaf\xf8drMб\xfb\x15\xed{ю\x934Z}\x94\x13?axx\t/j\xb9\x9a\xa9\xc8n\xb4\x0f\f\xcb\x05,\x1c\x97>\"`\xdbE/Y\n\x04\x99\x01\x80E\xa1\xae\x80\x05\x9a\x84\xb8\x8b\x0fM\x81\x80\x97\xe20{\xbd̡om\xf2$,\x99Z\xbc\xe4j_>\xab4\xd2~\x934Z}$\xa2{\xf2\xf0\xf0R$^0\x1c_\xc0L\xac\xeb\x15\x89K\xcf\x04쌆\xbc\x94o\x1be\xac\x99!:\x00\x88\xa8+`\xb8\xb9\x8b\xbe\xfa-=\xe2\xbe\xe8\x03\xf3\xb6\xb4\xf9\x88\xbc\xad\x99\x1f\xc7<\xe1\xca8\xee4\x9b\xf7 \x8dV\x1f\x89\xe8\x9e<<\xbc\x1c\xfa\x1crLL+\bXa!\xc6ӈMF\x89t\xc62>'o\xe9\x0e\rIu\t\x87\xbe\x88\x8aY\r\x00)\x8f\xca\x02\xe6⻝n\xa7E\x9c\x89\x1f\xf08\xcc\x1e\xd2-p\x9bZ\xdc\x1e\x8fg\xe0}\xa2\x93\xae*\x9e\xe9\xc7F\xec\xdf\v\x8e\xabp\xb4z,\x89\xe8\x9e<<|4S\xc6\xd0\xf0SA\xc0\xcei.\xb5\xef\xcap\xcb\xe3\xd2\u007f\xaam\xa8+@\x1b\xcddh~\n\x95Z\xda+\x90\xe4\x89\t\x00\xac\tT\x160\xec鱘\xda\x06\xc5I\x98\x1e\xea\x02k\xc6\xf8\xae\xe8\r[3\x13Y'tԫ\xa53R\xcfU8Z=\x8eDt_@x\xf8\xf8(\b\x98\xffxVz\xe1PT\\zWaz\xe6\x9e/\x10\xa2\xa1S\xbbvj\xb3>\xbd\xabT\x1b\x00\xa42j\vغ\xe0u\xf1\xb5\xd7\xef\u07bd}z\xfe\xb3\xb7\xc9L\x15H\x16\x9cTA\xc0\x00`\x9d\x02\x02\xb6\f\xf4\x97\b\x1d\xae`Y\xf4\x9c\xfa\x85\x00\x02\x06\x00\v\x05\x04l\x19x\xc2\t\xb3\x1e\xa6\xb8%,\x98\x13-`\\\x14\xff\xf9?\xd1\xd5(>\x1f\xf8\xb01\xe9\x01 %\x01\x01[\x06\x82W\xf4\xd7\xfa\x1e\xf5]\xd3\u007f\xb5\x840\xef\xd1\xe1\xe1\xa3\xf4\xeb?\x85\x96\xd3i\x03\x05\x03\x00\x10\xb0\xe5 8\\k\xd0\x19j\x87\x97\xa0_I\xc2\xc3\xcf\xd0\x05\r\xff\u07ff\xfd\xed\xff~\xbc\x1f~\x9b\r\x00 `\xa9\x85\x0f\xa1\x9d;?\u07b2sdž\n\x98\x96\n\x00 `\xa9ż-'++7++k\xd7К\x99\xf6\v\x00K\x06\x04,\xc5\xf0{&]\x93\x93.\x97\x1bF\x90\x00\x00\x02\x96r@\\H\x00\b\x03\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x96\xfalXq\x92]!\x00,\x13 `\xa9φ7+\f\b\x18\xb0R\x80\x80\xa5> `\xc0\xbaEm\x01\xf3t5\x9b,\x03\xa1)\x00\x0eq\x05\x1dy.\xb08@\xc0\x80u\x8b\xca\x026\xcd[\x9dng\x9b\xb8\xa0\xa1\xcf4\xd0\x14\x9b\v(\xf2\xf6/\U0004e000\x01\xeb\x16\x95\x05\xcc\xc5B\x0f\xf9\xc4\x00\x1e\xd6\x1ewSl.\xa0@\xf0^\xc9\xe9x\xc7$\x02\xb6`-[\xb0\xe1\x9b\x05\u0602\x80\x01+\x85\xca\x02\xc6\x02\x16b\xaf\x10\x89\xc8a\xf6\x89k\xe2Ks\x01\x05\xa6j\xb8\xb3\xdf\xc7;\b\x02\x06\xac[\xd4\x160\u008c\xdbbe\x91\x88L.I`\xdbP\xee\x1a`~˦/r\xb2{\x8fg\x15Ra\xb6\xed\xc9٤ݻ\x95\x1e\xf0\x96ksN\x9e\xd4n\x8e^\xfb\u07fc\x85\xa7\x1bw\xa6\x18\xfe,3*B&\r\xe91,\xcfz\xa6\xe3\xb8o^\\<\xaa\xaf}\a\x02\x06\xac_T\x170/\xcf\xf3f\xd6\xe3\xb2vG\"sGr\xd7\x02\xbd\x99\xa8z\x17\xd26l\xb9L\xe3a\x1f\xb9\xd5\xcdk\xd1<\xc6\xfe\xbc\xec\xaf\xcfi\xd2M\xbf\xb8\x1ce\xbf\x1f\xed\xa1\x1b\xbf\xf9\xaa\x80Y\xb6ԗ$\xa8\xda\xdc\v\x819<\xd7\xd7w\xb8\xb2\xd8p\xb3~\xf7K*`\u007f\xf8\xf9\xc7\x1f\xfd\xf4\u007f\x13)\xf9\xdf?\xfd\xe8\xe3\u007f\xfc3\x11\x95_\xffxÏ\u007fM\x0e|L\xd2\xffH\xfe>\xfe\xa3 6\xbf\xfd\xe9G?\xfa7\x89!)\xf9\xf1\xcf\xff,ɈT\xf1ۿ\xfb\xe8\xc7\xff\xf4&\"`b\x95o6\xd0\x04\xa9#rV\f\x00+\x83\xea\x02\x86\xbd\x1e\a\x8bJ䤂\x15\ue045r\xd7\x06\xd9\xe5؊\xac\xf8H\x05\xc6\u05f5t\xf1篳H\xef\xb2\x05\x8d\x93\x14rĘO\xd6\tq\x84\xa6'\x05\xa6eG\xafqU\xa1\xb0\xb6FqUC#ݩ\xe2N\xbf\xc5\xc1\xb7l\b\xf9\xd3_\xfd\xf9\xbb\u007f\xff9\x91\x92\xbf\xfb\xddw\u007f\xfcG\"X\xff\xe7G\xbf\xfb\xf3\xef~\xf4\xdb7o~\xfc\xfb7\u007f\xd8\xf0\xc77\xff\xfecQ\xbf>\xfe\xedw\u007f\xf8G\x89!\xd9\xfe\xf9\u007f\xfc7IF8\xf1\xef\u007f\xf7\xef\xdf\xfd\xe1\xbf\xfcSX\xc0\xc2Un\xf8\xd1\xef\xbec\x89\xf0Y1\x00\xac\f\xea\v\x18\xa6q!\xbb\xc9\x00\xd2\x19\b\x04\xdcM\x81\x804w\x8d\x90݂\a\x91\x0f\u007f^Jƅ\xd9[\xff\x99\u007f\x18\xa0}\xaaSY\xe4Ņ\xda㕚D!dC\xc8\xfbE\x9f\xdd\x17WF|>,\xf0\x9c\xeeT\x15\xbd\x14r\x89\xc0|$\xf6\xaf6\xfc\x9e\xbc\xfc\x99\xf4\xba\xfe\xfe\xffP\xc9\xf9\xfb7o\xfeǯ\xde\xfcjÿ\xbd\xf9\xa7\xffG0`\xf9RCʟ\u007f$\xc9\b'\xfe\x81&\xfe\xf8㰀\x85\xab\xdc\xf0[\x9a\xf8\x99\xe4\xac\x18\x00V\x06\x95\x05\xcc/\xc8\xd58\x1f\x98\xe4Cx$\xb9\x89ʦ\x10\xd9]xHC\x14\x8b\b\x18\xf6\xf1\a\xf3Ж\x06\x92\xba\x8c\xbc4\xc8ll\x0f,\x84\xcd*`\x93g\xbf\xa8\xe5j\xa6p\fU5b\x82\b\xcc\xff\xfc\xf8\xbf\xff\x1bU\x13Ak\xc8\xeb\xc7\u007f\x16e\xe8\xb7\xff\xf5\xcd\xcf\xfe\xdb\xcf\xdf\xfc\xfdo\x05\xad\xf9\xe8\xcfoB&\xc2\xeb\x1f\u007f\xfe\xf1\x86\r\x1fI2\"U|\xf4\x11\xfd\x99PX\xc0\xc2Un\b%\xc2g\x8d\xbd8\x00P\x05u\x05,\xd0\xd4˶\x0fM\x81\x80\x97\xe20{\xbd\x01In\xa2\xc2)\x84D\xc0\x1e\x9c\"\xfb\xbe\x96\xf4\xeb\xa43\x96\xb6\xd7=\x9e[\xb0\xf8FJ\xbc`\x12\xaaB\x91n\xa9\xc0\xfc\xfeW?\xff\xf8WJ\x02\xf6\xdd\xc7\u007f\xfc\xe8\x8f\xe4\xef;\x89\nI\x05\xecg\xff\xf3\x8fo\xbe\x93\xeaV8\x11\xea_\xc5\x17\xb0\xf0Y\xa3/\r\x00TB]\x01\xc3\xcd]\xf4\xd5o\xe9\x11\xf7\x05\x1fXtn\xca#\x11\xb0:\xc4\x1aWx\f\xe3Q\xb4\x05\xa1\x9d\x9eXsw\xc3dl\xa6\f\xfa\x1cr,*O&`o\x04\u007f}X}X\x8f\x8b\x8e\xf7\xde\xfc\xc3\u007f\xff\a\xf6'\xf0\xb3\xd0\x102\xf4J\x95\xed\xdf\x15\x05\xec\xef\u007f\xfdFj\x1b\xa92<\x84\xa4\xb0\xb3F_.\x00\xa8\x84\xca\x02\xe6⻝ng\xc8]\x1f\xf08\xcc\x1eotn\xea\xe3̺\xeck\xd94\xee+\xdd\xe9&\x02\xb6\xf9\x9c\xb5\xad\x02\x91N樦\xc7j\xf3(t\xc0\xf6\x89\xb1\xb4\x131e\xbc\x80%\xbc\xfb\x93\xbd\xd2h\xb7\xb3\xe0\x1fD`\xfe\xcb\xef\xbe\xfb\xee\xd7?\x95\xa8\xcf\xff\t9\xda\xdf\xfcjï؟\x00\xc9\x13\x9c\xf8!ß\xfe\xea\xbb\xdf\xffXQ\xc0~\xf7\xf1\xbf\xfd\xf9\xbb\xdf\xfdװ\x80\x85\xab\f;\xf1\xc3gU\xbed\x00XvT\x160\xec鱘\xda\x06\xc5i\x02\x1e\xea\x02k\x8e\xceMy\x02\xa4\xa3՜\x892,\b\xed\xc7M\x85u9\x9b\xb2\v\xe9 y@C\x1d\xf4\x9b\nc\x9c`f-\xafPMB\x9e\t\x8f#ki\x9a\b\xcco\u007f\xf6\xd1\xc7?\xff\x83D}\xde\xfc\xfa\xc7\x1f\xb19\x0fo~\xbf\xe1\x0fo\xfe\xc0<\xf3\x82\f\xfd\xddGt\nD\xd8\xf0\xf7?\xfd\xe8G\xbfV\x14\xb07\xbf\xfb\xd9G\x1f\xfd\xecwa\x01\vW\xb9\x81&\xe84\x8a\xf0Y\x93]-\x00,\x13j\v\xd8:ƻ\xf9\x98w~\xde7t \xeb\x03\xf74C\x02\xa3\x161\xe7\x03\x01\x03V\n\x100\xd5h\xcf\x12F\x8f\x01\xed\xdd$\x96\x8b\x04\x04\fX\xb7\x80\x80\xa9\xc6h\x9a0vt\xa4=Lb\xb9H@\xc0\x80u\v\b\x98j\x04*ҏ\xb5\xf4\xb6\x1cK\xafHf\xb9H\xd4\x16\xb0\x18@\xc0\x80\x95\x02\x04LE\xac{\xb25\xd9{\xac\xc9\xcc\x16\v\b\x18\xb0n\x01\x01K}\x92\x85\xdcX~\x92]!\x00,\x13 `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `@\"\xfc333\xf3\x18ϓ\xcdZ\xf9\xa9*\xb0\x96\x00\x01\x03\x120\x90\x86\x10J\xf7\xf9\xd2\xc9&-j\x9dE\x00Xy@\xc0\x00\x05\x86k^\xb3\xad\x05Y\x87\x86\x1c\x18;\x86\x86\xac(:\x98\xd2Bi/\xf0&3!x\v\xda\x15\x92\x00\x90\x10\xb5\x05\xcc\xd3\xd5l\xb2\f\x84\x96cp\xf0\xe1i\xe9\x92$\xf0\x01\xf8\x8a\xe3:Ȧ\x83㾊:2v(*D[,w\xb8Va\x15~Kdy~\xb7 `\xc7P\xda\"\x85\xac\x01\x9dKf\xc2hHkPH\x02@\"T\x16\xb0i\xde\xeat;\xdbĥ\v}\xa6\x81PT\"I\x12\xf8\x10\xbc,\xbe\xf3\x03\xd9\xfcp\xa7\xf8eԑ\xe1\xe2~1\xf5\xe8\tV\xa4\x93\xbb/\xa6b\x05\xccc\xdbT\xa7X\xa8wT1\x1b\xff&ͬ| \x06\xebƫ\nI\x00H\x80\xca\x02\xe6\xe2\xe9\r\xe1\xe3\x9dl\xcf\xda\xe3\x0e\xa9\x96$\t|\x10N\xdcc\x9b{'b\x8e\x04C\x89\x1a\xd9\"\xafa^\xe8\x1aC\xc9X\x01\xc3X\xa3,`;J\x15\xb3'5\xa7\x14\xf3\x958\xa3q+$\x01 >*\v\x18f]//\xef\xa1\x1b\x87\xd9\x17\x8a\v)I\x02\x1f\x86\xf3߰M\xe3\xf9\xf8&U\xca\x02v\xc5\x10\x0e \xb2\b\x01\xcb?\xa8\x98]\x91\xbd\xf0\xe5\x1b}\xd9\x15\nI\x00\x88\x8f\xda\x02F\x98q[\xacti?\x9f\xc9\x15\nl+I\xae\x17\x9a\n2r\xabɽ=\xbe\x11\xa13\xae\xf2\xad\xe9{\xe6%\xc9(c\xf3\x16\xb6\xe6\xb4;S\x8c\x1b\x99)ힴr\x1cׇ\xfb\xc8k\xab\xb4Lc=\xdb\\h\xc4\xcft\x1c\xf7͋\x8bG\xf5\xb5\xef\xf0[=\xb3&\f\x8bArYp\xb6\xe0\xfd\x9a\xe2ʛb\xf8\xef\xe2p\aLY\xc0\x8eWdg\xeds\x91^3\xb9\x92/p\x1dy\xb5X\xc5\v\xcbg\x16\xa1\xb6\x11\xfc\x99\x9f\xd3ͻ2]\xa3\xc1\xf0\xe8F\x89\x91\x9e\xc3^{XWV{\x98\xf6\x04_],3ܼYV\xcc.\t\x9fI\x9f\t\x9dN\x92\x04\x80\xb8\xa8.`^\x9e\xe7\xcd\xec\x9f\xdb\xda\x1d\x8e\xcc-I\xae\x13*Ҏ[\xafj\xf3\x03x\xc6Ҽ573\xa7\xba\x1c\xb9%\xc9(\xeb\xfdh\x0f\xdd\xf8\xcdW\x05\xcc\xd29Y\xaf\xebk\xec\xb3xv\xc2X\xffJZ\xe6^\r\x9e0L\xe0\xaa{x\xae\xaf\xefpe\xb1\xe1f\xfd\xee\x97\x18?\xb6\xdb\xf5L\xe8f'XX\x10;\v\x92{\x85\xbb1\xd2y\xa8\x8a\r.\x9fr\xf6p%\x8a\x02\x86\xf2[Z\xb6g8\xb0o \xe7\xd84\xf6\x9e˴\xf9|\x03\xb6\xdcB\x9b\xcd\xc6\\\x03\xe1\xb6a\x1a\x89I\b\x99\xf7\xa8\x84\xbby\x9a+\xbb]\xd6AN\xb0\xfbb\xffؽ2\xee\x1d\x11\xcb\x13\x86\xceV\xbd\xfe^m\a\xb3\x1a@\x83\xa1\xd3I\x92\x00\x10\x17\xd5\x05\f{=\x0e\x16\u007f\xc8IeLP-Ir\x9d`EԳ=\x84Z\xe8N>\xda\xe5\x13\aג\xa4\x94\xc9:!\xee\xda\xf4\xa4\xc0\xb4\xec\xe8\xfd_\xb2͉\x90\xe7]\xc0^\x86\x1bu\x8d\xf83\xa6FU\xdc\xe9\xb78\xf8V8\xa2\x0f\xf5\xd4\xc2C\xc8a\xe6\xb5\u007f,t\xcdF\xb8\xe7\xe1J\x14\x05,\x8f\xf4\x8dfr\vH\xb2\x8e\xf6\xb8\x8e\b\x83\xbd\xf0\x10R\xd66+\x12#\xc6\x19.\x92\x8a\x87\xf1ů0\xee<D\xa4\vw\x96\x10\xb9\xec\xe3\x9e\xd1g\x06\xa1\xb0\xbdnt\v\xc7&\x01 .\xea\v\x18\xa6\x11 \xbbɨ\xd1\x19\b\x04\xdcM\x81\x804\xb9^(\xdd\xe6\x9f'\xe4\xb0{??\xe2\xb0\xceO軞D!dVϸ\xb9\xd9\xfbo\xdf\x15=\x93\x19\xbf\xe4f\x8d\x17\x8d\xb3\x1c{\bYU$y\x16\x19+`\xf5G\xe7\xde\x11\fW\xe8N?\xf7\"l\xaa(`_\xd0\xd7\xeb4̸\x1b9\xc8 Q\b\xe7\x19\x160Y\xdb\xda\xc3\x02\xd6G\x04r\x96\rl_\x1a\x8e\u07b8\xf748Gr\x1bK\xc8\xcbs\xee\xdb\xf09Zpl\x12\x00⢲\x80\xf9\x05\x8d\x1a\xe7\x03\x93|\b\x8f$\x99\xb8\xf4\xdaa\xbb(D\xfb\xe9N\xfe\x8ep\xbe$\xa9\x84\xcd* \x9f\x13?\xa7\x9b\xea\xe0Z\x9fss\xb2\xdc`\xd1T\xf1\xb3\xe2)\x1d\x1b\x16V\xd5H\x8e\xc4\n\xd8\t\xd1\x1fv\x96\xeeLp\x13a\xd3\xf8N|\x1b\xa2\xd3&\xf6\x9e\xc4]Y\xc2x6,`\xb2\xb6\r\x86F\x82\x86\x11\xfcX'z\xe6\xde\u07bbPɕ\xdd!Wֱ\xfb\x15\xed\xf2\x85z`Ch\x00\xc7&\x01 .\xea\nX\xa0I\xf0\x88<4\x05\x02^\x8a\xc3\xec\xf5J\x93Iʯ\x19ʷ\x8d2\xd8\x14\xf5\xfc\x03\xe1|Ir\x11T\xf6\x9d6V\xf6\xff2:\xf7\x8e\x01\x1b:*YZ\xf6\xbcQ.`\xf7^\xd2\x1e\xd8\x13\x06s\xa2\xcd\x16E\x1e\x06(\nX5}5!:еj\xfd\xe2\bR\x100\x93;\xaam>\x8d8\x8b\xd50\x86\x1f\x17\t\x02\xf6\xb8\x91H\xd7\xdb>}'\xed&־|Vi\fM\xec\xa8ӄGϒ$\x00\xc4E]\x01\xc3\xcd]\xf4\xd5o\xe9\x11\xf7%\x8e\xaf\xb5\xeb\x03\x9b\xac\x8b\x99\xe3\xd9%\xa8\xc1\x17\xac3#\x99\x80\x10g.\x82\xbbaR1_\xa4\xfe\x86n\x84\xbbv!ʶ\xb6\xe6<>od\xa1o\xe3\b\x98ш\xf1k\xea\xf8\x1a\x13\xbc_\x8d\xb7Y\xf6\x85\xca\xf0L1E\x01\xcb!].\u007f^!M\xfb\xb5\xd6,\xf1\xb3,$\x19\xd3\xd4F\xd662\xa0\x14\xbe\x95$\x02\xd6ʍ\xd0\x1c\xe35\x8c\x9fpe\x1cw\xfa{\xf1\x14\x81\xbcp\x84rI\x12\x00⣲\x80\xb9\xf8n\xa7\xdbi\x11g\xe2\a<\x0e\xb3\xc7\x1b\x9d\\s\xecC\x9bcz\x13\xa7P\xa9\xa5\xbd\x025\xe1\xf9A\xf6\xfc\x8e\x8a\x8e$\x19SC\xc2\xdb\xf9\xb6\xbe$X\xa9\xbf\x1de{c\xf7\x1d|g\xf7\r\x8c\xdf\xfd\x89=od\x9e\xad\xb9\t\xbb]\xff\xa5\xdd\xce\xfc\xf9\xadE\x1d\xfd\xa7\xd9L\xfd\xc6\xdd\xf5\xfd\xdf^\x11d\f?\xe7\xee\x84jV~\n\xb9g\xb0\xa7 K\xb8\xccS۲\xc49\x1f\xe74\x97\xdaweP\xf3p\xdb(\xae\xb4Kt3\xf5Y\xc7l\x9fnj\xb6\x9e\xa8U+W\xdc:\xdc\u007f\x85{\x84\xf13\xfd؈\xfd\xfb\x90^^Fa\xa5\x97$\x01 >*\v\x18\xf6\xf4XLm\x83\xe2,\x00\x0f\xf5{5G'\xd7\x1c\xa6\xcdh(&\xb3k\xa76\xebӻ\x18\x8f\xa71\x87\x11\x15\x1dI2\n\xb3\x96\x8f͌\xf0\xb8\xa4\x15\xdf)~\x1ce;\xa2\u007f\x86\xa7\x8a\x87\xa9\x93\x9f\xc1\xfabOEo\x17\x9b\xa6?w\xe33\xbdQ(6v\xba\xac\xc48\"\xd6ת\x0fy\xc1,\xc8\x15ZN\xc7\x15\x12\xb0\xbc\xba\x83\x99\xd9\xe5\x1eaDžB\x13N\xfddz\xd2\v\x85v\x86\xda\xc68\xf3\x93\x01\x8c\x83\xa4\xa3\xd5W\xcc\x15\xf7q\xdcy|\xdfx\xfb\xb0\xce`$\xfa\x85't\xf4btF\xe6\x04\xb3\xa5\x9f\x14\xcbH\x93\x00\x90\x00\xb5\x05l]ҎR˟\x13\xbc\xa1\x13\xfabl\xaejh9\x1d\xa4\x14Pܧ\xe9UȕQ\xad\xb1\xc4;\xf4\xba\xf8\xda\xebw\xef\xde>=\xff\x19\xe9\x11\xb6h*B\x13x%I\x00H\x04\b\xd8r0#\xce\xd7b\x93\xc9\x03\xe6\xacc\xc9\n\xac2\x82\x1d\x06aR\xec\xfc\xf8Ph9\x9d\xa1q%M\xb1h\x93+\xcd\xe5\x1c\xf9\xbc\xb5\b\xfd%\xc2\xe81X6\x82\xbd\xd9\xe1\x15($I\x00H\b\b\xd8rP(\xce$`\x8en\x8f\xb6z\x8d.fZ\u05cbw-l\xa9\x9c\x89'\xb4\x8b\x00\x00 \x00IDAT8<\x11'PLqO\x93X\x02\x80\" `ˁK\x9c\xaf\xe5Jf\x98\xd2\xf8P\xfe\xb1E\xfcT[\x81\xe0\x15\xfd\xb5\xbeG}\xd7\xf4_\x051\x00,\x01\x100`ɜۼә\xcc&1\xc1\xe1Z\x83\xceP;\f\xfa\x05,\r\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x10\xb0uɺY\xb7\bX\u3000\xad?<\x15[\x84\xd5\x06\x01 \xd5\x01\x01[w\x04\xf2\xf2\xf8\x9eD+W\x03@ʠ\xb6\x80y\xba\x9aM\x96\x81\xd0\xefO\x1c\xbc\x95nf\xcclAi\xf3Z\xfa\xc9`\xb7\xd6\x1aJz\x8fmI\xdf\xfb^\x836k\x96\x15/\x94Љ\x8f \x842\x94~\xcb4\x8e\xba\x14r\x01 \x15QY\xc0\xa6y\xab\xd3\xedl\x13\x174\xf4\x99\x06تw>\xfe\xa1\x87\xb0\xa6\xd63\xb4f\xdc\n%wm\xb9~$\xfd\xbd~3\xf89\xfa<\x99I\x98Љ\xdd6\xdb\u05ca\xa1Ɇ\x90|I}\x00H]T\x160\x17O\xc7.>^\xf8\t\x9d\xb5\xc7-\n\xd8\x1a\x1cф\xbb\\^t\x15\a\xdeK\xbf\xf0\x19t&\x99I\x84H_o(\x8e\x80A\xc4E`\xad\xa0\xb2\x80\t!\x0f\xbdB\xf8!\x87\xd9\xe7Y\xbb\x02\x16ƅ\x16>\xfe\x8bC\x1d\xaaKf\xa2\x04\b\x18\xb0\xd6Q[\xc0\b3n\x8b\x95\xf6\x12|&\x17^\xa3\x02FW0Mc\vd\xfb\xb5\xc2\xca`\xd5Q\x16\xc1\xfb5ŕ7g1~\xa6\xe3\xb8o^\\<\xaa\xaf}'IFY7 \xb6\u009f;S\\g,S\xfa~\x1dC\x9b\xf8\xea܌=\xaco\x1b>1EY\xaazA\xc0\x805\x83\xea\x02\xe6\xa5\xdez\xd6\x0f\xb3v㰀u\xdf\xe2\x9bm3\x89K\xa6\x12\x0fl6!|\"~hkAu6\x9b'\xca\xe0\nwc\xa4\xf3PU\x10\xcf\xf5\xf5\x1d\xae,6ܬ\xdf\xfdR\x92\x8c\xb2\xbe\x8a.Ӎ\xdf|U@\xf6\xb8\xc3ټ\x11i\xeb.e\xb2\x88l\x91\x13cE\x01\x9b\x9f\xeeݑ\xf5~\xe3Y\x00X=\xa8.`\xd8\xebq\xb0\xa8DN*c!\x01k\x1aw;--k\xe9)$N\x0f\xe9\x88\xd2\x10r\x98\xbbO^\x1f\va\x80\xaa\xb8\xd3oq\xf0mTR\n\x8f\x84@\x1d\xd3\xe2R\xd5QK4k\xb2h8F\xad\xb8\x97\x9eH\xc0\xf6\x93\xfe\xdb{\x8fh\x01`\xb5\xa0\xbe\x80a\x1a\x17\xb2\x9b\f \x9d\x81@\xc0\xdd\x14 \xa3ɀ\x83v\xbef\xcckjh\x93P\xc0\xea\x8fν#\x18\xaeН\xaa\xa2p\x8fK\x92\x94bFf\xba\x99D!\xe4Cn\xcd\x11LÚ\x89{\t\x05\xcc\xdd\xc5\xe7A\x0f\fX3\xa8,`~\xe1\x11\xd98\x1f\x98\xe4CxB\amm\xf1\x8a\xa5\"\t\x05\xec\x84\x18\xdd\xec,ݩ\xaa\t\xe7K\x92R\x06\xb2\x04%\xb2\x89KUG̓`ѯ\xeb4\xe2^B\x01#\xd8\x14\x82\xbc\x01@j\xa2\xae\x80\x05\x9a\x84 \\\x0fM\x81\x80\x97\xe20{\xbd\x01\xdc#\xdc\xe1\xbdkjl\x93\xa4\a\xf6\x84\xc1b\xffH\xc2f\xcb\"h/\x18\xe6\xf5Z\xb0\x80\xc1SH`\xed\xa0\xae\x80\xe1f6\t\xdco\x11\xc3ы>0+\xebzy\xcd\x0f\xe3\x94JI\x12\nؘ\xe0\xfdjdѴ\x17 `\x89\xe7\xf1\x83\x80\x01\xeb\x15\x95\x05\xcc\xc5w;\xddN\x8b8\x13?\xe0q\x98\xe9\xfc{7\xdf\xe5r?0Y\xdf\xeb\xe76\xab\t\xff\xa0ͦ9b\xb3\xf9BO!\a\xa3\x9bָ\xbb\xbe\xff\xdb+D\xc6\xde\xfd\xc9^i\xb4\xdb_\x90<I2\n\xeb\xe6\x04\x9dS\x8fmӑA<zd\x93\xcd#=1\x9b\x89\u007f\xd9f\x8b\x99\xa1\xf2\x00\r(U\x03\x00)\x88\xca\x02\x86==\x16S۠\xf8\xb8\xd1C]`t\xd6\xd2tw\xb3\xd9\xeaX3\xfa\x85\x87\xd2\x04_;\x8f\xfdY,\xb11&z\xcf\xd8\xe9\xb2\x12\xe3\b\xc6\xcf\x04gX-\x96%\xa3\xb8\xabU\x8a\x8a-r\x8cԿɑA^\x8fIN\xcc~\vI)\x8d\xb6\x9f\xdexp|z\xed\xbc\xd7\xc0\xbaFm\x01\x03V\x9e\xf6<\x04\xcb\xe9\x00k\x03\x10\xb0\xf5\xc8\xf4\xb8'\x99\t\x00\xa4\x02 `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x80*\\Ϡ\x91\xe1\x06\xb3\xd6T\xf0O`\xc5\x01\x01\x03B\f\u05fcNf\xb2d|\x19\xd5t\x1d\xec\x03\xda\xf9d\x96\x8b\xc4[О\xcc\x04Xè-`\x9e\xaef\x93e \xb4(\xbb\x83\x0f\xads\xe5\xbck\xb6<\x88S\x06H\x88}\xb7\xb8>\xb5\xfeY2S\x8c\xbf\xa4v\xe1\x15\xc7\xfez\xadL_\x1b\x14w\xeep\xad4\xe9Ԛ\xb1I\xeb¸\x02\xa1Kd\xff\x12B\x15Q\x95tk\x17\xbdv\xee\xe8F\u007fv;\x9e\xde\xf4ET~\xf8lK\xa6!\xad!\x99\t\xb0vQY\xc0\xa6y\xab\xd3\xedl\x13\x174\xf4\x99\x06؊\xac\xd8\xdf\xcd\x0fN\x8e\xf2\xef\xf3\u007f\xbcNx\xf4$&kn\xe2P\xad\x9dp\x9f\x1bIj\x8b\xbf\xb7\xdb;\xb9\x89\xd0\xde\xe9C\x9d\x17\xf5b\f\xa4N\x16(\t\xe3\x1eT\x8d\xabQ\x0f\xc6\xee\xcd\rt\xbc\xe7mȌ^\x13њqKL\xf5\x8e\xe2\x851\xa4\tl\xb5\xe0\x064\x19\x95\x1f>\xdbұn\xbc\x9a\xcc\x04X\xb3\xa8,`.\x16\xc2\xd6\xc7\v\xeb\xfbY{܂\x80\xf5\x98<4bd̪\u007f@45JkN\x1f\xbdF_\x9fG\v\x98\xa2-\r\xe6\x16\x12\xb0\x1f\xb8N\x1c\x9c\x15\xd2/t\x8dB\xe2\x01:\x87\xcf!*L\x9f\x98X\x86i{L\x15\xe1\xe5\x10w\xc4,\x97\x18\a\xefF\x13r\x04\xb6\xee\x8aΏ\x9cm\xe9\x9cѬ\xb1\xb8\xc8\xc0\xc2QY\xc00\xebzy\x85HD\x0e\xb3OX\x13\xdf\xc3?\f\x1f\x03\x12\xa2\xb8h\xbe `s\x9dQ\xf1$\xe3,\xb0\x1f\x11\xb0\x17\xdcp8\xf7\x8aAT2\x17\xba\x8c\xaf\"\xda\x19>p\x86e|q\x00\xc7%\xff`\xfccr\x8e\xa3\xbd\xb8\x17\xc5\xf8\xab\"g[:\xbe\xec\xe81.\xb0nP[\xc0\b3n\v[\xfd\xdegr\x89A=\x06M\xf3I\xc2V\x00\x94a\xd1\xd9\x15\x1d{M\x100\xca\xdb\v\x06\xdd\xe1\xb3Ϣl#\xb9\x14Q\xc0\xe6\xca\x04\x83\x9b,s\xaeX\xec\x80a/j\xc2\x16D\a\x8f_\bݫ\xd2/\xf0\xf8F\x84θʷ\xa6\xef\x99Ǿt\x84\xd2\xe8:\xe0\xd8*.Z\x9d\xcf̚\n2r\xab\xc5\xef \xf3\x16\x1eG\x11p\xce\xe3\x83Z\xba\x96\xb8\x85\x14\xa9\xc3u\xe4\xd5\"=[\x1c\x82\xf7k\x8a+o\x12q}\xa6\xe3\xb8o^\\<\xaa\xaf}'I2\x9b3\xe9k(\xa8;\xb0(T\x170/\xcf\xf3f\xf6\u007fn\xed\x0eE%j\xb7:\xdb\xf8\xe6\x01\xf8/L\xc2\xec\x04\x8b\xfaa\u007f\x1e\x95\u007f\xf4\xca\xdc\\\x87\x91\xa6\x86\xb9\xaf\x1e\xf5\x9d\xe5\x1e\xcbm#\xb9\x94P\x0f쩽\x8fk\xb5\xdb\xff\"\xecpv\xb1\xb2@\xce \x1eʡ\xdf'\xa6\x1dx\x90\xec\xe4\xf3x\xc6Ҽ573\xa7\xba\x9c>I|`\xb3\xb10H\xd87`\xcb-\xb4\xd9ll\xe4_\x91v\xdczU\x9b/|\x0f\xedG{p,\xa2\v\xdfg\xcb<\xe3\xc5\xde\u007f͢\xa1G\"g\x8b\xc3\x15\xee\xc6H硪 \x9e\xeb\xeb;\\Yl\xb8Y\xbf\xfb\xa5$\xc9l\x06 \xceҺEu\x01\xc3^\x8f\x83E%rR\x19\x13\x04\xcc\xc27\x8d\xbb\x9d\xcd\x16\u007f\xb2\xb2\x80\xf2\x10\x92\xf6\xa4\f45\xdbG\xfa*\xc1\x13\xe7嶲\\\xe5!\xe4\b\x17\xad\x8a\x18۴\xf8s\xcdI\xace\xb1<\xf3\xd1._x\x94\x1f\x8e\xdc\x16\x1eBZY\xec\xf0!\xd4\xc2\xf6&뢝\xf5\x94\xb0\v\xbf\x82v\xedJ\x174\xee\x1bf\x8f\x16\x1e\vQ誸\xd3oq\xf0mT\x12c7\xba\x15\xaf<\xb0\xc6Q_\xc00\x8d\v\xd9M\x06\x90\xce@ \xe0n\n\x90o_\xab\x89\xde\x18>3D\x8cN\x8a\xb2\x80\x9d}\xfc\xf8\"\x130\xfc\xaa\xb3\xf6h\tw\"\xcaV\x9a\xab,`\xfd\\l477\xf2\x15\x1e\xf9ԇ\x98\x8b<_\xea)\x8f\x15\xb0\xd2m\xfeyBN\"UڶSL\xf4\xa6\xfb\xb0/\xa37\x81i\x98\xfa\xa3s\xef\b\x86+t\xa7\xaa\xe8e(_\x92\xa4\x17\xda\x12[\x12X\x17\xa8,`~a\xb00\xce\a&\xf9\x10\x1e\xdc\xcb\x02\xdb\xe2^\x98\x92\x98\x94\xb8N\xfc\xa9{4\xf5\xf8\xd0\xe1\xc6~\xfb\xe9(\x01\x93\xe5*\v\xd8DdnE\x98\x80Ʊyt\xb3c\x13\xfb\xcc\xf2wH\x8e\xc4\n\xd8v\xd1\x1f\x96 ڑ\r\xb5\x89\xcf/\xe7\xb5m\xb8]\xbb \xaf\xe7\tѕw\x96\xeeTE\x9c\u007fUR?\xe0\x10D\xba\\\xb7\xa8+`\x81&\xe1k\xf7\xa1)\x10\xf0R\x1cf\xaf7\x80G\xcd쟹g\xd1\xd3#\xd7\x1fL\x94\xeeIz\x1f\x94\x88\x13\xbf\xb2\x86>K\xbc \x110j+\xcbU\x16\xb0٢V\x1cCnC6ι\xb4\x8d\xa5\xf3\xa5\xcf\"\xe5\x02f\"}\xb3\xf2m\xa3\x8c\x04\xee\xf8R\xad\x1fW\b\u07b3\xe3\xfb\xf1\xfe\xe3\xf1-%\xd4\x1f}\xc2xEw\xe2\x850\xaf\xd3\xc0\x03\xec\xf5\x8a\xba\x02\x86\x9b\xbb\xe8\xab\xdf\x12\x9a\xb9(\xf8\xc0\xbcl\x1a\x85\xcf\xf4 N) \x8cш\xf1k\xc1#\x84\xdd\r\xa2O)\"`\x87\xe9}\x1d\xac:!\xb7\x95\xe5ƙFq\xa12\x88\xa3\xd9[\xb0\x1f\x1f(\x10\xfc\xf1\xb2\t\x13a\x01+,\xc4x\x9a>M\xec\xa2/\x18\u007f!\x1c\b_\x99\x04\xaf\xe6s<\x8aΥM\x93\xf4\xa0ƣQ\xf0\xbbO\xd6\xc5L\b\x1b\x13\xda\xdax\x9b\xbe\xc6\x11\xb0@\xde^\f\xacST\x160\x17\xdf\xedt;-\xe2L\xfc\x80\xc7a\xf6\xd0\xef\xec\a\xa6\anGSۇ\xfe\x9d\xdc\x1a\xa4\xb5\xa8\xa3\xfft\xb1\xd0\x03ۇ؍Kg\xe2O\x88\x93\xb8Z\xb9\v\x9d\xb7\xab\xb8\xb2;\x13R[I\xeeK:\x13\xbf\xc3n\u007f\x19z\n9!\xea\xd6s\xeeN\xccɪQ\x03n@\xa4\xab4?Ȟ72U\xf2\x0f\xdal\x9a#6\x1b\xfb\b\xcfi.\xb5\xefʠޱS\xa8\xd4\xd2^\x81\x84\x89\xc9\xe2\x95ɸ\x84\\\xb8yk\x80\tW {O\xb6\xc2\br\x1f\xda\x1cӕj\xdc]\xdf\xff\xed\x15\"c\xef\xfe\xc4\x1e\xabRW\x9d$I\xb9\xfc\x9e\x13a\x81\x14Fe\x01Þ\x1e\x8b\xa9mP|\xdc\xe8\xa1.06\xa5\xc8\xd5nn{\x00\xfa\x95\x9c\xb9\x1b\x9f\xe9\x8d\xe2|\b\xb3\x96Ͷb\xbf\x85\x14\xfad8\xd8QYt\xa8\xfe~\xa5\xce(\xb5\x95\xe4^\x14}J\x17\xf0\\\tK\xe8BO\x1f[\xf51^0k\xc68vd\xb4c<\x9e\xc6\x1c\\L\x95\x86\x844b\xe7\xf6\x1f\xcfJ/\x14\x9e\xbdt\xed\xd4f}zW((^\x99\x8cm\xa4\xb3f\xd3X\x85G\x02\x975\x97c\f\xc8Xt3\x8a}\x8e3v\xba\xac\xc48\x82\xf13\xe1\xc2k\xb1,I\xb0\xa5\x9f\x8c)\x04\xac\x17\xd4\x160`\xb5\x12\xbc\xa1\xebKf\xf3\x1eL3\x17~\x01J\xf8ۣv\xb4xgV\x8b\xa6\x02\xbe\xf9\xd6/ `\x80H\xb0\xc3\xf0*\x99\xcd{\xc0z^~W\x82g\x8f\x01sֱ\xf8G\xe3\xe0͆\xc5(\xd63 `\xc0j\xc1\xa3\xad\x86\xa9\xcc\xc0\xe2\x00\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01[\x0eJ\x91\xb6\x1cb\xc4\x01\xc0\xb2\x03\x02\xb6\x1cxz\xcdy\xda\xc5\xff.\x19\x00\x80š\xb6\x80y\xba\x9aM\x96\x81н\xed\xe0\xe9\"\xac\xf3M\xe2\xe2\xd2͉J\xa6\x18\xbdh<\x99\t\x00\x00\xef\x89\xca\x026\xcd[\x9dng\x9b\xb8\xa0\xa1\xcf4@\x17\xc0\x9b\xe1G=\x84\a\xfcZ\xba\xe5\x87 \xd4\x17\x00,;*\v\x98\x8b\xa7\xab\xaa\xf8x\xc1Ad\xedq\xb3\x15<\x1d,(QӚ\x8a\xcc\x00\x02\x06\x00ˏ\xca\x02&\x04\x16\xf4\xf2\x1e\xbaq\x98}\u009a\xf8\x8c\xbb\xb7\xd6Ժt `\x00\xb0\xfc\xa8-`\x84\x19\xb7\xc5J\x97\xb5\xf3\x99\\8\"`N~:A\x99\xd4c\x1c-(\xee!\x00\x00\xef\x81\xea\x02\xe6\xe5y\xde\xcc\xfaa\xd6n,\x11\xb0p\xa0\xa25\x82_[0\xe0^P\xe8C\x00\x00\x96\x8a\xea\x02\x86\xbd\x1e\a\x8bJ\xe4\xa42\x16\x1607/\t\xfc\xbc&\xb8\x8b\x10ڗ\xcc\b\x00\x80\xf7A}\x01\xc34.d7\x19@:\x03\x81\x80\xbb) \xf4R\xba-Iʤ\x1a>\xed\xd6\xcb=kM\x94\x01`\x95\xa1\xb2\x80\xf9\x05\xb9\x1a\xe7\x03\x93|\b\x0f\xcd1?HP*\x15\x19B\xdd\xc9L\x00\x00xO\xd4\x15\xb0@\x93\xe0\xd9~h\n\x04\xbc\x14\x87\xd9륚\xe6]s#Hx\n\t\x00ˏ\xba\x02\x86\x9b\xbb\xe8\xab?\xec\xb1\x0f\xf9\xc0&\xf9\xb5\xf6\xc3\x1b\x100\x00X~T\x160\x17\xdf\xedt;-\xe2L\xfc\x80\xc7a\xf6xi\xcaɯ\xb5\x80Z\x83 `\x00\xb0\xec\xa8,`\xd8\xd3c1\xb5\r\x8aj\xe5\t\xff\x00\xd2}+A\x99\xd4\xc3\xef\x19-\xd5x\x92Y\x01\x00\xf0\x9e\xa8-`\xeb\x83\xfd\bmmOf\x04\x00\xc0\xfb\x02\x02\xb6\x1cxF\xd7\xda3\t\x00X\x95\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\xaco\x01+E\xdarg2#\x00\x00V+\xeb[\xc0<\xbd\xe6<\xad\xb0\xb4\x8f\xb7 \xfc\xebkI\x12\x00\x80Ռ\xda\x02\xe6\xe9j6Y\x06B\xab\x17:x+\xdb\xfa\x06n\x99n\r\xacȚ\x86\xbdH\x8c\aސ\xd6\x10ʓ$\x01\x00XŨ,`Ӽ\xd5\xe9v\xb6\x89\v\x1a\xfaL\x03lEV_S\x1b\xcdmZ\t\x05\x8b\xac\x9cj\xddx\x15\xc7&\x01\x00X\xbd\xa8,`.\xb6\xf6\xbd\x8f\x17\x1cO\xd6\x1e7\x130\x9b\x85\x06垷\xd8\x12\x94\\.$K?\x9fѸ\x15\x92\x00\x00\xacZT\x160\xcc:Y^!\x12\x91\xc3\xec\x13\xd6\xc4\xef\x11|N\xed+\x11\xdbV\"`\xbe\xec\n\x85$\x00\x00\xab\x16\xb5\x05\x8c0\xe3\xb6Xi$\"\x9f\xc9%\x06\xf5\xf06\xf5z\xfd^[\x937I\xc9\xe5`\x1c\xf5\x86\xd3g\xd2g\x14\x92\x00\x00\xacVT\x170/\xcf\xf3f\xd6\x0f\xb3v\x87\xa3\x12\xcdt\x93ܮ\x15\x91\f\xbf\xb6`\xc0-D\xab\xc4\x03\x91\xde\xd8\x00\xc4\xe4\x00\x80Տ\xea\x02\x86\xbd\x1e\a\x8bJ\xe4\xa42&\b\x98\xbf\xdb\xe2\xf48-\xdd\xf3\xc9\xca.\aw\x11B\xfb\x84\xa4\x1b\xdd\n\xe5J\x92\x00\x00\xacV\xd4\x170L\xe3Bv\x93\x01\xa43\x10\b\xb8\x9b\x02\x01\xea\xc4\xf7\xb3܁d\x05\x97\x01\x9fv\xeb\xe5\x1e\xd1c\xefF-\xa1lI\x12\x00\x80Պ\xca\x02\xe6\x17\x06k\xe3|`\x92\x0f\xe1\t\x98\x1e\xb2܇\xa6@\xa2\xb2\xcb\xc3\x10ꖤ\a\x14\x92\x00\x00\xacV\xd4\x15\xb0@\x93\xe01'R\x15\xf0R\x1cf\xaf7\x10\x12\xb0ѕ\x11\xb0\x88\xb3\xabN\xe3SH\x02\x00\xb0ZQW\xc0ps\x17}\xf5[B\x13&\xc4i\x14\xe2\x10r\x85\xa7Q\x04\xf2\xf6*$\x01\x00X\xb5\xa8,`.\xbe\xdb\xe9vZę\xf8\x01\x8f\xc3\xec\xf1b<\xd3bq\xb8\x1d\x96\x96\x95x\f9\x18\x11\xb0\xcbhT!\t\x00\xc0\xaaEe\x01Þ\x1e\x8b\xa9m\xd0/\xeeP\x17X3I\xf8\x87\xda\xccmC\xfe\x84%\x97\x03\xbfg\xb4T\xe3\x11wl\xe9'ql\x12\x00\x80Ջ\xda\x02\xb6\xba؏\xd0\xd6\xd0\xca\x13-\x9a\x8a\xf9\xd8$\x00\x00\xab\x98\xf5-`\x9e\xd1\xf0O\x1e\xbd\xd9\r\nI\x00\x00V3\xeb[\xc0\x00\x00Hi@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0V3\xc35\xaf1\xf6\x16\xb4c\x00\x00\x94P[\xc0<]\xcd&\xcb@h\xb5S\aoe\xdb\xc0x\xbb\xa9\xcd\x19\xbf\xd4r2\xb9\t\xe5\xc5dz\x8fmI\xdf\xfb\x81և\x9d\xaa-6\xd4?2\xbc\xc6_r\x1c\xa7\u007f\x91\xcc\\\xc2\x1d\xae5H6\ri\xf0\xe3r\x00PDe\x01\x9b\xe6\xadN\xb7\xb3M\\\xd0\xd0g\x1a`+\xb2\x06\xac\xe6Q\xf7\x03ӃD%\x97\x8f\xc1#\x9a\x98\xbc][\xae\x1fI_آҏ\x9e$>>V\xfc/\xf7\xfaNp\xdc\u007f\xe0\xef\xed\xf6Nn\"\xb1\xb5\x94N\uef90\xb0n\xbc\x9a\xd8\x12\x00\xd6)*\v\x98\x8b\xa7\xeb\xd7\xf8x\xa1\xb7e\xedq3\x01{h\xa2!m]\xa6\x85)\xc6\a\xa7N\x13\x9d\xe3EWq`\x81WSs!\xe1\xe1\x1fJ\xce\xcea<[I\x04\x8c\xf0x\x11\x02\xf6B\xd7\x18J\x9eф\x97\xfd\x01\x00 \x82\xca\x02\x86\x99*xy\x0f\xdd8\xcc>aM|+[)\x1f7=\x88Sh\x99\x89\x150\x17\xb2*\xd8)S\x95X\xc0\x1a\xf5\u007f\xa1\x9b\x0e\xee9\xdd,F\xc0\xae\x18fCI_vE\"K\x00X\xaf\xa8-`\x84\x19\xb7\xc5J\xddK>\x93K\f\xea\xd1fc\a\xda\xef&*\xb6,xʳ\xb3\x0e\x88CȦ\x82\x8c\xdcj\x1f\x8dՍ\x18ղ\xdc\xf1\x8d\b\x9dq\x95oM\xdf#]\xacu\x98\x13\xa8\xa1;\xf6\xdaú\xb2\xda\xc3A\xd9\x19*\xaf\xb0ͫ\x8e9\xba\t\vX\xb0\xb3F_\xd5\x19\x8c*\x16\xbc_S\\ySЭ\xb9\xe2p\a\x8ct\xc1\xd2W\"^\x00\x00\xacvT\x170/\xcf\xf3f\xd6\x0f\xb3v\x87\xa2\x12\r4\xb1\xa8D涄%\x97\x01Wf\xae\xb9\xfd\x17HC\xd3\x15iǭW\xb5\xf9DZ\x1f\xdaZP\x9d\xcd\xe6\x91\xe5\xceX\x9a\xb7\xe6f\xe6T\x97#\xe9hnv\xc2^i\xb4\xdb\xed\xb4{\xf5t\xf7\xc5\xfe\xb1{e\xdc;\xe9\x19\xe6\xb8\x0e\xe9nX\xc0.\x16}3\xf2M\xd1ŨbW\xb8\x1b#\x9d\x87\xaa\x98\xae=\xe5\xec\x91r\x03\x92\xe0o\x00\x00\x84P]\xc0\xb0\xd7\xe3`Q\x89\x9cT\xc6\x04\x01\xf3\x99\xad\xde\x19O;oIV\xf6C\xf3\xe96r\r\x81\xed\x1a\x92\xb4\"3\xa6A\xd6X@\xee\xf0\x10R\x96\x9b\x8fv\xf9\xc4A\xb0\x84\xf0\x10\xb2\xf3\x10\u0560\xce\x12Y\x0f\xec\x05\xf7\xadt7$`#\xdc\x18y\x1d\xe3Fdņ\x99\xd7\xfe1\xd7'\x98<\x8f\x94s\xa3[\x18\x00\x80h\xd4\x170L#@v\x93\x01\xa43\x10\b\xb8\x9b\x02t4鵒~٠U\xed\xf9N>\xc4\xd3\xcd\x19\ry)\xdd\xe6\x9f'\xe40gSX\xc0d\xb9\xf9\x8a\xae\xf4\xb0\x80\xbd4\x1c\xbdq\xefipNvtN\xa7\xd8\x03\xbbr\x82mN|)+V\u007ft\xee\x1d\xc1\xc0F\x9d\xfd\x9cdƅ[\x90P\x00\x00d\xa8,`~an\xd58\x1f\x98\xe4CxhΌ7\x80\x9b\x06\x12\x15]\x06\x1e \xe6|;\xa7!/\xdb\x05\xc7\x17\xdaOs\xc2\x02&\xcb\xcdߡTIĉ\xff\xf6ޅJ\xae쎢\x0fln\x8cmB\x02f<\xcb6\xb55\xb2b'D\x8f\x1a;8!\xf5\xf7\x0f!\xb5\xdf\x1b\x00H\x05\xd4\x15\xb0@S/\xdb>4\x05\x02^\x8a\xc3\xec%ʅ\x99_\xdc%H\x99\x8ax\xd1u\xbaaN\xfc\xf2m\xa3\f:\xa1#\"`\xb2\xdc\xfc\x03J\x950\x01\xbb\xf7\x92\x88S#Ѡ\xb7}\xfaN\xd9\xe1F\xfd+\xba\xe9\xe3^\xd3M\xb8\av\x94\xf9\xec\x8f^\x94\x15\xab?\xfa\x84\xc1J\xcc\x16\xb5Fj\xa9\xd3,pR\a\x00\xac+\xd4\x150\xdc\xcc&L\xf8-=\xe2\xbe\xe0\x03s\xf2D |ͽq\x8b-\x17\x059\xe4Į\x9fhH\xb2\v1\x0f\xdc\x17u\xf45,`\xb2\xdc\xfc\x83Ju\x18\x8d\x18\xbf\xa6n\xabV\xea\xd1\"\xfb\xd7X\xb6\xbba\x92m\u007f(9OF\x87A\xe3Q\xb6\x17\xf1\x81Q?W\x1f-!)6&x\xbf\x1ao3\x9b\v\x95\xe1\xbe\\ o/\x06\x00 \x06\x95\x05\xcc\xc5w;\xddN\x8b8\x13?\xe0q\x98=TB\xf8!\xf7\xc3&\xab\xfa\x9d\fGFNݙ\xac\xb4\x8df'ƧP\xa9\xa5\xbd\x025\x85\x9eB\x0e\xb2\xd1n8w~Ж[h\xb3M\xc6\xd4\xd1Z\xd4\xd1\u007f\xba\xf8%U\xa2\xe2\xd6\xe1\xfe+\xdc#\x96\xbd\x0f\x89\x9a3\xa27\xde\x1f\xae\xd5\x11\xe1zIg\xe2w\xd8\xed\xc4\x16\xd7s\x8dÍ\\=\x96\x17k\xdc]\xdf\xff\xed\x15A\xc6\xf0s\xeeN\xe8\x1c\x97\xd1(\x06\x00 \x06\x95\x05\f{z,\xa6\xb6A\xbf\xb8C]`\xcd$1j1[G?\xd0O\x0f\x17\x85k_\xd6֓\xe6\x8d\xe8\x18Iw\xed\xd4f}z\x97\xf4\x0f\xb3\x98\xdbk\xa3\xf0k\x81P\xeex\x1aˍ\xed\t\xcd\xdd\xf8Lo|L\x12\xf7\x8d\xb7\x0f\xeb\fFA\xbf\xb0Yˋ\x06S\xb5\xfa\xb2\xb3t\x1e\xfeE\xd1\xc5Eǜ\xc1\xce\x13\xfa\x13l\x1e\x98\xac\xd8\xd8\xe9\xb2\x12\xe3\x88X\xb0U/z\xc1l\xe9'1\x00\x00\xb1\xa8-`\xc0\xc2\t\xdeб\xbeX\x8b\xa6B:y\x16\x00\x80\x10 `\xab\x98`\x87\xe1\x15\xc6\xdelX\x8c\x02\x00\x94\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 eQ[\xc0<]\xcd&\xcb\x00]\xf9k\xc6\xcc\x16\x946\xb3\xa5u<\xed\xe6.O\xe2\x92+¨\xb0\x88N\xda\x03awr\x13\xca#\x9b#$+\xc3\x15k\xedؓ\x91]ڛ=\x1d{\xe4C\xe1.\xcf\xc9\xf8\xa4N\xfd\x85\xd3\x00`u\xa2\xb2\x80M\xf3V\xa7\xdb\xd9F\x174\xf4\xf1\x0f=\x04\xb6X\xb3\xdbds\xd9L\xab0\xfa\xf4\xfc\xa0\xedkt\xd9\x16Z\xc0\f\x0f\xb2\xe5\xa7\xdd6\x92\x1b\x1b\xe7\xac+c\a߲\x1d!g̑\x0f\x85k\xf3'\x97\xac_d~\x02\n\x06\x00\f\x95\x05\xcc\xc5S\x95\xf2\xf1N\xfa\x12\x16\xac@3\rY1м\x12K\x1a&eH&U\xa1(\xdeC\xb1\x02\xe6\xcd\xdcOtηm\x19\x05l\xffV\x1a\xdf֙\xf1E2C\x00X\x1f\xa8,`BTE/\r\xdf!\x110\xa7\x89ޗ>\xd3\xf2\xdd\xf9\xef\xc1\x82\x05\xecT:\x1b;^B\n\x83\xcb\x0fD\xdeV\xb69\xa0\x18\x1e\t\x00\xd6\x1fj\v\x18a\xc6m\xb1\x06d\x02\xd6s\x97m\xee\xaa\x1c\xd5c~˦/r\xb2{\x8fg\x15\xd2\x11\xed\xc1lMξq\x92\xed܈\xd0>\x9c\x83P\x16\x1b8\x86\xa5\xcaS\x9e\x9du\x80\r!\xa5\xb9\xb8\xa9 #\xf7\xffo\xef\xfcc\xe28\xee\xfe\xff\xfdg\x10\xac\x8c\x0eN\x1cB:\xa4\x039\b\x13Y\xc9`|',\x1cS\x041\x17\xd1`\x93\xafj\xe3\x1f(\xa9\x12\xfb,\x13\x9b\xa8NS94D\xc6`\xf2\x03\xc5%ND\x83c\x14\x1axL\x1d\x91\x1fv\xb8\xa8\x8ay\xda\xe2|\x85\x1e\x92HϵV{\xcf#5\x8e\xb1]\xe1m\x1cR\x82}\x86Z\xa3\xef\xce쯙\xe5\x8e=(\x06\xce\xf9\xbc\x12\xf9\xf6n?\xf3\x99\x99ݝ73\xb3\xb3\xfb\xa9\xa1\xba\x9c͂Gʡ\x034\xd9\xe1\xfb\x1c\xabiȣ*\x94\xd2X\xe3q\x14\x8e\b\x9b\xb2\xdcS\x98\x95\x92\xb1\xce-[iv\xb17Q\x8f\xa4k\xf1\xdc҅qu\xaf\x1a\fes\xf6\xact\x00\xf0\x83d\xc9\x05,D'\xeei{\x0f7v\xbd\xd2\xd8\xdaC\xfb^\xedj\xd0\xc3ޥ\x0el\u06dd\x8ej֢\x8czW\x03\x8d\xc1\xed\xefn\xf3%\xf5+\x03ھ@R\x9f܌Z>dF\xbaT\r\xa5{\x9a\x8f?\x88$Y\xf8U\xf6'Uw\x1cʸo\\\x1eKj0=o\x96\xea:\xea\xa4rE\r[\x93QF\xe0@z\x89\xb0\xa9$\xdf\xfcJWc\x06\x9a\xf5\xaa\xe8\r\xa8\x90~\x8c5\x1fRi\xd6g\xdf8.\xb9\xcag\xff\b\x00?D\x96\\\xc0\xe4\xd0\xe8`\x9b:\x89\xdfrv$\xd8vLi\xa1-\xfdlO\u007f\x8bM\xd2E'\xb3\\\x11\xae\x0ey\xb3\xd2w\n\xb7QU\xcde\x11l\xe5\xcd\xf9\xa1,\xfd=κT\xad\xc9V\f\xc6WK\xe2\xaf\x1d\xa8\x99};&\x8f S\u007f;Q'\xfb\x97\xf6,%\xa7҉*ϐ\x85\xcd\xc3\x19T\xba~\xe1\x9c5\xeb7\x1cP\xe3\x1e}9\xac\x12\xe5\x8e\xe6\xf8\xe6\xd4\x159\xd6\x06\x80\xa5g\xe9\x05L\xa6q!\xbb\x94v8H;_\x97\x9a\x15!hg\x01\xb2\xe5\xee\xf6\xb9\x93->\x99\xc7\xe4>\x14\x96kK\x95\xed\xd0\xe1\xc2\xect\xb4\x9a\xfd~i\xb5˧\xdbhR\x15FllW'\t\xbfʥ\xd9cW\x15\xb2\xfc\xf2X\xb2\xd9\x03\xf3粏\x9c\xcd\xca?\x12\xfd\x87\x05\xff\xe66G2ݏ6~8\x1e\xa5{\xa52\x8ctfߚ}T\x0fZ\t\x00?x\x96X\xc0\xc6\xd4.\xc7\xd9F\xa3\xebѣ\xa8\xd6I\xb5E\x1e\xd7\xc3\xdd.\x19\x99\x9dr\xbf$\xcb;\x14\x01\xebweն\xf7ܯ\n\x98\xfc\n\xea\xd5m4\xa9:\x83\x98ʪJd\n\xd8jMg6\x18s`cJ\xe7k\x8d*\u007f\xeb\xf2\x95\u007f\xa4=\xb2>\xf7\xcfm\x86\x1b\x1f\xcaA\xae\xd8\xd1:z:Tz\xac;¥\xc9\xcd\xd1\x12\x00\xc0\x0f\x91\xa5\x15\xb0\xf1\x16u\x9e\xfeæq]\xb5\xba;hdnuRl\xc9GF\x9c\x80\xe5\xe4\xd32\x94\xa8\x026\x9a\xb9\xcb\x1d\xd2l4\xa9\n!:'/['\xf1˳\a\x18!\xe3.d\x1b\n\xc9~u\x96\xdd\xcdz`4\xaa\xb7&`\xc6\xe6\x99\x1d\xca?\xe1c\xa9\x87\xe5y2z\x9fs\x96\xa6\x01\xc0\x0f\x96\xa5\x150\xb9\x95\xce\r)CH\xa5\xaf\xd5\xc1\x06\x8c\xa1\xe6\x0f\xe9:0\xaak\xddK\xbf\x0e\x8c\x13\xb0,:\xb7>\xbe\x9a\t\xd8X~\x9d\\\xb5V+\x8d.U\xf9Y4\x86\xf8*I\xfc\xb5\x13\xb5я]\x01\xba\x0e\xacD\x19\x12\x8e\x17\xb8\xe9\xcc\xd81\xe5\xc7cl\xac\x17U\xc0\x02l\x92L.\xa8\x92-\x8c\xd4ώ\xfd\xcdq6\xd33\xa4\x94\xef.\xae\xf5\a\x80Db\x89\x05l\xa8\xb1+8\x12d\x93\xf8#\x8d\x9dC#g\x9a\xe8\x8a\ny\xa4\xa9{\xb8{\xe9W\xe2\a\x9d\r\xe1c)gå\xf7\x8f(\x92\xf2\xd0\xe1\xc0}(\xa3\xbe\xefRoUƈ<\x9c^\xd3;Ư\xc4\x1ftd\x05\xea\x9cI\xc9\xcdAu%~CO\x0f-\xf0\x0eT\xdav\u070f\xe8\xfd\x87NG~\xf3\xf1\a\x93\xe9\xe0\xb3<iGǎ\xa4r\xa5\xc7ԓ\xb2\xb9O\x1e\u061c\xd23\xcam*\xb9\xa5\xed\xe9h\xf7\xa3Y\vG|Qb\u007f\x9b\x9cH\xcd\xec\xe8\xe9\xe9\xf1g\xcda\x03\x00? \x96X\xc0\xe4ѓmM\xed\xea\x939_v\xb56w\f\xaa\xfd\x9c\xd1Φ\xe3\xa3s\xa5\xbb\x1b\x8c\xbb\x10jMG\x8e6:\x855\xde\xe0\x912J\x9b\xb3\xa5\x82N\x84P\x8d\\\xad\xfc\xdb-\u007f\xc8=\v9\xe4s\xba\xb75'\xa3*\xf6,$\x85\xce\xfd˝\xf7g8ר\v\xd9\x06\x1ft\xb8|\x83\xcc\xf5\xcfW;V\xffb\x9c.\xfeB(eС\xfc[\xc5m\xca-\x05\x81\xac\x94̂\xd9\vߚ3\x1ag\xfdfR\xa0e\f\vY\x01\x80\xb1\xd4\x02\x06\x00\x00\xb0h\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80% K\xfe\xd6\x0e\x00X\xa1\x80\x80%\x1a\xa3~\x17\xda`g\x04\x00KD)\xca(_\xf2\x17\xf9\x99\x80\x80%\x18\xe399\x8d'\x97\xfc\xc5C\x00\x10\x83\xd1\xee朌勴\xbc\xd4\x026\xda\xd9\xda\xd4\xd6K\xeb{\xa9\xb9\x91\xa2\x87\xdd\xe9^F\x15\xffw\b\xadu\xaa/\x86~\xb7\b\xab\x14\xbdk\x93\xe4\xdf\xe2\xac\xfa*\xc4\xd7iN\x0f<\xf2\xd6u\xf5\xd7\x0f~\xf4\xdb\xd8I\x9e\xc3\xf8\x1d}\xfbgJ2\xef\x17\x16\x83\xf7\x1e\xc0\xf8S\xf9\x13e\xcfWr<\xbc\xee\xfd\x15\xfb\x14\x9d\xcdY\x86\xb8\bU\xb9R\u05c9\xe3c\xfa\xe6\"Ǽ\x03m\xbe\x8a\x8bhY\xde\xf3\xe2WcX\xfcQ;Y\x9f\xaa_\xbf(\xc2?\x96c\x1c\x1d\x85Ϟ(\xae\xd8\xffQ\xc5_g\xef\x89\r=\xa8\x18oz\xf2\xbfb\x19\xbc\xad\xec~U)*\xc6o\xc52\xf9\xb7\xb9\xfbդt\xa3\xb3v&w\x8d%\x16\xb0/\x1b;\x82#\xc1v5*ч\xa3\n!}G\xff\xdc)\xef\x12\xdd\x03v\x166lˮObu\xf8\x15>w\xeeM\xfc\xfa\xb9s\x0f\xfc\xca.\xcd|\xf9\xe8?\xcd\xed~\xf5\xdd\xfc\xff\xf3+\xfc\xf6\xb9\xf7\xf6\xe3\x97\xd4_\u007f[<\x87j\xfe\xe9\\\xd1K\xe6\xb6R\xc8O,\x06_\xbf\x8b?\xba\"_y\xe4\xb1?\xcaq\xb1\xa5h\v\xfb\x14\x9d\xcdY\x86\xb8X\xeb:\xbc9U\xfcc\xce\xde\x1d9+\x86\xb0\x1d\u007f\xd9\xefݭ|\xec\xf6\xee\xffK\f\x8b\xbf\u007f\xc2N\xd6'Wԯ\xd7?\xf9\xd9z9\xc6\xd1Q\xa4\xb9\xf8\xff\xbe\xf5\xce\x16\x8c\xff߬=s\xf0\xf5'E?;\xf7ћ\x8fx?\x8ba\xf0\xd5\xdb\xf8տ\xca\u007fUNd\xec?\x1b\xfc\x99_\bw\xbf\x9a\x94(Q\x9e\x97\x8c%\x16\xb0!\x16͖\xbd\xfd\x9e\vl\xabt\xccږI\xc0\xf2J\xed,l\xc8\v\xc8\x0e&)\xaf\x17\xc9\xf2\xa7\xf4\xb2\xf0\xben\x97f\xbe<\xb6\xcf\xdc\xd6/\x96\x0f\xb0\xd20\xae?\x87\xb5?\xf0ף$3Y\xff\x92\xb9\xad\x16R\xe4\v\xfc\xb5,\xbfT\xf6\xdf\xd6ߣ\xf35\xdeO\xed\x19\xbc\xb3\xb9\xcb`O\b\x1d\x92\xc7g\x0fF\x16\xd2<\x8e<\xa1t&\xff\xc7\xfbđ9l\xc4\xe3\xf0\xd2\xfah\xbf2\xfeg㓊\x00|\xfd\xc8|[6;\xea_W<\x11k\xffg\xf8\x03\xe5ߏp,\x85\x93\xc53\xbf@\xeez5\x17v\x86\x16\x8b%\x160\x99]\x9f\xa1\xc6QQ\xc0\xba\x1b\xbb\x9b\x96G\xc0\xee{\xc8\xce\u0086\xdc\xe6\x11Ć8W\xbe\xd0.\x8b/\xaeإ\x99/[c\t\x98|e\xe3sѓ\x88\xc4#`\x1f\x14}d\xfd9\x06\x1f\xe1?b\xdd6\x8a\xb3\x053\x14=^\xdcB\x9aǑ\xfd\xbbߑ\xdf~b\xff\xa2\b\xd8\x11\xef\x9f\xe9\xc7\xeb8\xe6h0:\xeaQ\u007f\xc9\x1bK\xd8\xe3\x10\xb0\xadK(`\v\xad\xe6\xc2\xce\xd0b\xb1\xd4\x02\xa6pi\xa4\x8d\xbe\b\x9f\x17\xb0Ka=\xb8\xed\x92ҡ\xbd\xa1\xf9>Y>\x9b\x8cP\xddP\xb9;\xb5\xd0\x1a,\xbb\xd9\xc5^\xf2<\x92\xae\x19\xa7\x8b3\xe8\xeb\xea6\xe4*\x89\x93\xd9\x14\x9evY\xfc\xb1\b\xe3\xa3_<]\xe9}\xe2\xef\xf2W\xfb*\x8a\x1e~\x92\x8e͞\xc3Eo\xfd\xf2\x11\xef\x13\u007f\xa2&\xe7\x9ex\xb8\xa8쉇\xaf\xd3_\xdf|\xb6bӓlJ\xe2\xfa\x9b\x8fy\xb7\xbey]\xf0\xf0[m\x1a\xe315\xbfnA\xc0\xe4\xe7ʔ\xb1\x88\x17\x1b\xb3\\\x86_.c\xa5)=\xff\x8c\x9e\x05w\xed^\u007f\xfb\xb1\xe2G~I\xfbR\x8a\x80}\xb1\xf1U\xeb\xaf\xe6\xa6PH\xf9\xa5\n\xb9BWDݙY\x86w\x8c\xa9\x9dw\x04gf\xc9d\xe3\xa0r\x8ce\xa8\x87\xb7F\xd9\x0e?\x94)e\xf9\xf4y\x15\xa3y\xf4\x14f\xa5d\xacs\xb3\xed\x96|\x87\xa7&\xf6\xd4\xf1\x91\xfdo\ue55fx\x93\n\x98y\x1c>S\x0e\xea\x93\xd7+0\xde\xc8\xfe\xc4\x18\xc7\xe1O\xfb+6\xee\xfb\x99\xb5e\x9bE\u007f\xe4\x19\xf6\xc3_^\xbf\u009d!\xeelF?\xb1\xba\x80\xfd\xaa\xe8\n猿4x\x013\xfcr\x1e\xaa6\xf9\v\x00\x00 \x00IDAT,g~\xd61\xfb{Yё\x8a\x8a\x8f\x9e߸\xf3\xeb\xe5\xac&\x9d\x97\x9d\xfdn\xf4\xa5b\xc9\x05,D'\xee\xd5(j]\xaf4\xb6\xf6\\\xd2~_\x0e\x01\v\xf7\xf6x\nzzz\x14\xf1\xb9\xd4\xd6\xea\xf6\xa4gՔϊ$\xbb\x01\x15ҏ\xb1\xe6C*\xcdb4\xda@\xbat\xe6꺂>6\xf7\xac]\x16W\xdey\xe7\xe1G\x8a+~\xb9\xff\x81\xffV\xae\xc2g?z\xe7I:\x8b\xfa\xd9;E\xf8G/\xfdj\xe3^\xc5\xe2\xf7\x0f<\xfd\xee\ao\x95ῳ_\x1f~\xf5Շ\xd9T\xc9\xd3돾wt\xfdӂ\x87\xaf?9\xf7\xc8\xces\xe7\xceѿ\x8bW\xbf\xec\xces\xaa\xcdV\x13\xb0\xb7\xe8`\xee\xd3s缪\xa2\x98~\xb9\x8c\x95\xa6\x84\x1f{\xe7\x9d-\xdal\x8cq\xed>\x83\x9f\u007f\xef\xcd\x1fm\xbdN\x05\xec\xaf[\x8a\xafX\u007f57\x85Bʻ\xf7\xc9\xfbv\xabƦ3\xa3\f_\x9f\xdb\xf8\xd2_忾\xb4\xf1\xdc\u05fc3\xaed\xb2qPy>\xec9\x86\x02==\xa32\xfd\xc3\xe2\xefn\xf3%iW\x84.`\xfdh\xf3+]\x8d\x19\x88\xfe\x85\xf1'Uw\x1cʸ/悸#\xfb\xffT\xfc\xbf\xde?S\x013\x8f\xc3\xf5\u07fd\x84\u007f'\xbf\xfd\xc0ۿg6zѿ\xd8\xf8\xc8ۿ}\x02[[\xb6Q\xf4+\x98\x9b\x130\xce\x10w6\xa3\x9fXM\xc0\xae?\xb6Ep\xc6]\x1a\x9f\xe1\xf7\xae\\\xb9\xf2\x1e\x16\xce<\xe7\x81?\xf3r\xb4c\xf6\xd1F\xfc\xcbݸ\xecղח\xb3\x9a\xf4\x8fO~\xef\xc82-N\\r\x01\x93C\xa3\x83m\xea$~\xcbّ`\xdb1M\x0f\x96C\xc0da\by\x1fZ\x1b\xd6Ƹ<\xc3\x015\xd0ٗ\xc3*\x96\x90f\xf5\xa8Q\x0e;Ԡ\x1e\\\xc7|+\xde\xfd\x95|\xfd+\xa5=\xbf\xa3\xb4\xe3\xeb[\xe8Y\x97\xd7oT\xfez=\xfd#e\xeb\xcd\x1f\xd1S\xff\xe6F\xf6\x87\xbaR1\xfb\xeaa\xe5\xef\xec{\xecO\xf2\a\xf8=\xc1\x037\x90ؠtQ\xb4a\x96&`\xefi\x1d~M\xc08\xbfB\xc6?V\xd4\xe9\xca#\xea\x9fr\xbd\x90\xbf\xc5o\xb3o\xefP\x01\xdb\xffȏ\u07b4\xfe\xcamr\x85\x94\xaf\x17\xbf.\xbf^\xac\x8d\x8b\xf8\xa1\x88V\x06\xf9\x99\xfd\xca?\xfb\x9f\x11\x9d\xf156\x0f\xaa\x801\x84\f\xb7ѳ\x90\xab\xadv\xd3\x05\xecp\x06\x95\xae_8ǩ\xc25\xb3\x1d\xc7f;Q9\xb2_\xde\xf2\xdcc2\x150\xfe8\\\u007f\xfa\xb1\xbfT\xe87&\xf5\xa2\xef|\x84\x19XZ\xb6Y\xf4/\xf0\u007f\x18~\xf93d\x9e\xcdX'\xf6\xa5+_\xffq/M\xc1\x1fI\xf3\xc4~\xa6\xf5\xb0>\x13\xfc\n\a\x8a\x1fBF9f\x15O+)\u007f+?\xfd\xecrVS\xe1\x84r]\x1a\xa1엖\xa5\x170\x99ƅ\xec\x92\xe5\xf1A\xda\xf9\xbaԬ\x8d\x0fV\x80\x80Is-\xaf\x1aF:\x82U\x1br\xd6\xc8\r\x99ڸ\x93\x13\xb0\xf5\xfa\x8c\xf8_\xde|\xa2r#f\xb7\xed\xd8_X6\v\xf1\xdf\x15\x95Ͽ\xf5\xfb\xeb\xacӳ\x9eMԼ\x89\xffG~F\xbd\xb9\xb7\xe5g\xa2\a\xf32\x1e\xe9l\xcc\x11{`o+\xc9(\x9ax\xf0~\xf9\x8c\x8f\xd2\u007f\xdfTm\xf5B\uebfc\xf2w\x85\x8ag\xa8\x80y?{\xab\xec+˯\xdc&WH\xf9\x8f\xf8\x93+\x9f`\xed\x86e4\x01\xfb\xc8\xfb\xb5\xfc\xb5\xf7#\xd1\x19_\xb2\x18\x98s`\xa1Å\xd9\xe9H\x8b\x92\xae\v\xd8H\xa6\xfb\xd1\xc6\x0f\xc7\xe9\x1f\xbc\xd2챫\nY\xfe\xa8~d&`\xbf¿b\x02\xc6\x1f\a\xf9\xcaֲ'\xf5))\xad\xe8_\xa9\xab\x18\x8eZZ\xb6Y\xf4+Efׄ?C\xe6ٌub\xd9:\x8a\xff\x90\xc5#i\x9e\xd8\xcf\xf0\xaf>\xfd\xf4\xd3\xd7\xe9\x89\xe4\xfc\n\a\xcaf\x0e\xac\xe2\x1d\xa5\xbc_\xd3\xda.c5\x95?8\x19\xee\x86\xe5Z\x9b\xb8\xc4\x026\xa6v4\xcf6\x1a\x1dΞv\xf5s\x05\b\xd8\xdc\xc1\xcaz:T\x84\xc0\xd8_:j\xbaW\rg\a\xb4\xaf\x9c\x80=\xa6\xff\xf4\xa3\x87\x8f\xbc{n\xb7\xaa#\xb4\x85\xab\xd7\xc2Wo\xed{\x04\x97\xfdʜ*9\x87\xffS\xde\xf9$K\xf2\xc4c\x82\a\xf12\xeeA\xea\x81\xd2\x04\xec\xc8F\xf5g]<L\xbf\xb32fY\xc8f!\xb7h\x1d\x80'\xa9\x80\xbd#\xff\xfd\x91#\x96_\xb9M\xdeÛ\xecG\xb5\xbf\x16U\xc0\xfe\xbe\xe9]\xf9ݲ\xeb\xa23\xbe\xc610\x04\xacߕU\xdb\xdes\xbfE\xc0\x94>\xfbC9\xc8EWݭ\xd6\xfe\x96\xc4|\"Ai\xd2\u007f9\xf2W&`\xfcq\x90\xe5w\xcd\xf2jE\xff\x14\x9f\xa3\x1f\xd6\xd9m\xae\xe8\xda\xe4\xd0\x15\xa5W\u009f!\xeel\xc68\xb1\xcf~\xfa\xe9\x17\xd7-θ\x13\xcb́\xf1~\xf9\x03e'`\xefɟ\x16\xb1\xda.c5\xe9\x19꒗\x8b\xa5\x15\xb0\xf1\x16u\xb6\xefæq\xf9\xa4z\xb5vk\x17\xedr\n\x98\x1aR\xf7\xbe\x12\x1b\xdb(\x1cG\xc3r\x89;]\x1fwr\x02\xa6_y\x8f<F'H\xf7Y\x04\xec\xd3#t\x9a\xfd\x1d/\x95\x81\xf5\xcf\xd3}o\xe1\xaf\xe4g*\xe9\x05q\xbd\xf2i\xc1\x83\xb6\xf9\x96\xfaw\xdbr\x17\xf2G\x9a\x95&\x1e\x9c_!c#\v\x99\xff\xe3\xfb\x9f\x8c\xbfh\xcb(\xde\xf3\xfe\xb7\xf8+\xb7\xc9{\xd8\xf7\x98\xd2o\xd0\xef\xefG\x130\xf9\xf9\xbd\xf2\xde\xe7-Y\xf05\x8e\x81!`9\xf9\xf4\x80\x96X\x04\xec\xcc\x0e\xe5\x9f\xf0\xb1\xd4ò\\\x9e=\xc0\bE\xf5#\xabMZ\x81\n\x18\u007f\x1c\xe4?U\x1cy\xf8\u007f5\x1b\xad\xe8\xff\xabj\xf1ӳ\xba&Fяx\xd9j\xb2w\xf0_\x853\x14\xb5e\v'V?\x1e\u00914O,'`\x9c_\xe1@\xf1g>\n\x15\x1fȟ\xaeWk\xbb|\xd5\xfcA݅l\xed\xa4\xff\x8e\xb5\x9d\x94\xe5\x0e\xd6\xf5\n5\u007f\xa8\xeeY&\x01+(P\xbaQ\xa8\x8dn\xc6XQ1R\x1fe\xbaF\xa7\x1d\r\xc9\x1f\xa2Ry\xdc͌\xa2\b\xd8\xc3t\xe3\xfaV\x8b\x80\xbd\xa4\xces\xed\xa4\x8b ֗)\x97\xdeו;\xe9\xd4\x03\x9d$yG\x9b\x033\x05l\xa7\xb2\xef\xaf\xda}FQ\xc0\x8e\xe8C9M<8\xbfB\xc6\x15t\x0el\xcbNf\xa3\x17\xf2\x03\xd5\xe3\x91W5\x01\xbb\xbe\xf3g\xe2\xaf\xdc&WH\xb9\xe2\x97\xca?\xbf\xac\x90\x05g\x14C\xc0~\xe7\xfd\xb3\xf7w\x96,\xf8\x1a\xc78\xa8\x86\x80e\xd1?%\xe3\xab-\x02\x16P\x9fA(\xa8\x92\xe5N\xf5\x8c\xedR{\xbeÁY\xab\x919\x01\xe3\x8fÕ\xc7^\x92\x9f\xdbm\x99\xbe{\xecae\\\xfc_^K\xcb\xe6\x8a\xfe?\x1b\xf7\xd2\x1bs;+\xc53\x14\xb5e\v'\xd6\x100\xfeHF\x150ίp\xa0\xf83\x1f\xe5\x98q\x02\xb6|\xd5\xfcA\t\xd8PcWp$\xc8&\xf1G\x1a;\x87F\xce4\xd1\x15\x15\xf2\xa5\xd1\xd1\xe6\xeeQ\xcb\xf4\xf8\x92\xb0G:p|\xadcD\xbe\xda\xc7nHFiV>\xb4n\xf6\x8f:_:J\xdb\xdd\x1e\xa9:\x90B;\x03\xbf\u007f\x13\xbfN\xef\xfa\xfd\xfdw\xec\xf6\x11[t\xf0\x12\xde\xf7\xe6\xab[\x95\xde\xf6'\u007f>W\xf4\xb3O\xae\xff\xfegE\xe7\xfe\xac\xfcZ\xfc\xd2o\xdf}\x86-\xa7\xa2\xb7\b\xdfzd#\x9d\x8cߏ\x8f\xfc\xf6\b\xde/z\xa0\xd7\xcc\xeb\xef\xee.V\xff\x0e\x9fA\xbd\xf4C]\x89\xff4[\x89\u007f\xe5\x93s\xe7\xbc?;w\xee+\x99\xf7kfL\xb3x\xe2w\x1f=F\xb3\xf8o\xedq\x01\xea\xec\xc8\x03\xfb\xdf\xfd\x8fg\x94kU]\x89/\xbf\xfb\xc0{W\xb8_\x85M\xa3\x90W\xde\xc3G\xbe\x96\xbf>\x82\x15[\xce\x19W\x06\xa5\x11T<Q\xa16\x1f\xd3\x03_\xe3\xa8\aU\xbd\v\xc9\xee\xe6\x06\xd0C\x87\x03\xf7\xa1\x8c\xfa>u%~CO\xcf\b\xfd5mOG\xbb\x9fݲ߁Jێ\xfbQ\x8b\xe6,\xcdr\xeb\xe5\u007f\xf7\xef\xa6k\x9a\xfe\xbc{\xff\xffr\xc7\xe1\xca'\xcf\xfd\xe8O\xf2\x17\x1b\x9f\xff䊾D\xfdwJ\x85?\xf3V\xbczt\x13.z\xfb\xb3\xe8G\x87\xf6Mw\xbe\xfd\xdb'\x8ah\x937\xce\x10w6\xa3\x9fX\xba\x12\xff\xbf\xf4\x02\x19θ\x13+\xac\xc47\xfc\x8a\a\x8a?\xf3\xb3\x8f\xd9g\x9b^\xff\xfa\x9d\xa2Ͼ\u07bf\xfbO\xcbVMJ\xdf\x0fG\xc0\xe4ѓmM\xed}\xec\xce\xe3\x97]\xad\xcd\x1d\x83\xf4\x82\x95ϰ\xc7\"\x1b\x97\xe1\x91бjgj\x81\xd2\xf9;\x9b\xc4&U\xa2hUs\x86u\xc9\x12\xcf\xc9쌪p\x97ǩ\x8ck䯋\xb1\xfa8\xa1\xf6\x04\xda\x13\xd4\xe0\xfa돬\xff\xd1\xfe\xb7\x1f)\xda\xf9\x9c\xf2S\xd1\xff\xa36\xcf\xc9o\xef|\xf5ᢊ\x9d\xec\xfc\xaf\xff\xe53\x1b+\x9ef\x8b\b\xaf\xbf\xb9Ż\x85\xad\x03\xe3<(\xea\xf0\xfc&\xefN\xedq\xb6/\x93\x1f:\xfb\xe5\xb8\xfa,$\xaed\x13\xb3\xbf\xd7\xe61\x94/\x9c_3cY\xde\xf2\xea\xbeb5\x8b\xa75[\xd6\v\xf8`w\xd9Ɲ\xef\xd1?\xb8\xeci\xb9\x9d\xf8\x81O\xb8_\x85M\xa3\x90\x1f<@\x17x\xbd\x8b\xf1\x03\x1f\xf0θ2(\xbc\xbe^\x9f\x106<\xf05\x8evPǜ\xec\x04\xb0\xf5t\xe3\r\x1e)\xa3\xb49[*`\xcfBRJ\x95>zA +%\xb3@\x9d\x84\xe8\xbc?ùF\xbb\xf7۔\x86,\xdd\xf7\x970\xa6\x13:\xcf\xd1\x15i\xe6q\xf8@)\xdf\xf3\xf2\xf3J\xd1?2\xcaK\x8f\xea\x17On\xaa<\xf2v\x91rZ\xa2\x1e\x1d\x99>$\xe8-{\x92-P7\xce\x10w6\xa3\x9fXzP\xb7\x18%ҝq'V}\x16\xf2%\xf5\xa0\x19~\xc5\x03ş\xf9Y\xc7\xecz\x99r*\x8aq\xf1;\x18\xef]\xb6j\xcac\xa3\x03\xa5Ҩ\xbc\\,\xb5\x80\x01\xb3\x10\x96\xc9\xdbs<g\x8e\xc9\xeb\xbb\xc6<\v\xb9\xb4\x1cG\xcb\xf0\xa7\x0fPـ\x90\xfb\xb8\x9d\xd1\xdd\x03\x04lٙ\xb76|yv\xd4\xcedљw!\x97\x8e\xf1fg\x95\x9d\rp\xd7\x18\x1dX\xa6\x05\x14* `\xcb\xce\n\xd6\x06\x93\x15\\\xc8ь\x1a\xf1\xe1\b\xe0\a\x04\b\xd82\xf3'65jg\xb5\xcc$D!\x81\x1f\" `\xcb\f\x9b\x1a\x8d\xf2r\xb9\x15EB\x14\x12\xf8!\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\xb6B\x18\xb73\x00\x00`\x16\xe4\xff\xec\x02\x00\x00HP\xfe\xad\x1e\x18\x00\x00\xc0r\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x12\x8f\x80\xc9\xf5\xf9\x19)\xaeu\xafD\xec\fc0F\x13\xb6\xa1\rvv\xf3\x87ynE\x0f\x99\xbfē\x8d\x90`!\x1cF~;\x13\x00\x00\x96\x808\x04\xac9\x15\xa9\xb8G\xecL\xa3r8u\x92ħ,\xf3E\xf5\f\x02\x06\x00?T\xec\x05l\x0fB\x05\xbd\xdfF\xc2\xcdYH\xea\xb73\x8eB\x04!*3\xa3\x87{\xec,\xe7\x8b\xe6YУx\xb2\x01\x01\x03\x80{\x04[\x01\xebA\xe8\x17\xea\xd6\xe4\xfd\xc8\xf9\xed\xdc\xc6\xd1\xd0d\xe6.\x10M\xc0\xe2a\xde\t\xac\x80\x80\x01\xc0\xca\xc0V\xc0\xb2Q\x8d\xbe9\xe9B\xd5s\x99F\a\x04\f\x00\x80\xbb\x84\x9d\x80\x9dAIW\x8d/-(-B\xdb\xff\x81P\x893=\xff\x84\xfa\xe3\xd86\xb7\xe4\xdc0@7\x9bQ\xe3@vj^\x98\x90\xbe\xd2LɑS\xf7\r!\xb5l\xfalT\x9f\x9c\nUe\xa587\xb0\xa1h+j\xf8v[\x96䮛\xa0\xdf\u008f\xbaS\xd2\xd74\v7\nb\x1a3tϊ\x1e}\xb3-Sr?>E\xf49\xb0h\xceµ\xd9J9\x83\xcc\x17\x97\x80/\xab\x98\x8b%K\xae\x9e\xaa\x80\xe5\xa2Z\x02\x00\xc0rb'`{\xd0}\xe6\x97q\x84\xfai\xc3.M\x93\n\v\x92P\x15\xfdm\xc0\x81\xa4\xd5n\x84\x02\x84\nضU\b9\"\xa4\x1a\xa1\xcc\xd5.\xe5\x9f\tr\xbc\x14\xa1\x92\xd21MY:RP\xda}\xca\x0e\xda\xf4[QM&Jw\"\x94\xa3\b͗\xe9ș\xe7A\xe8A.\xef\x98\xc6*\xba\xe7V\x94\xebB.eWnD\x13\xb0h\xcezSQZ\x9e⬇\x88\t\xf8\xb2\x8a\xb9\x88Y\xf2\xf5\x04\x01\x03\x80\x95\x81\x9d\x80\xad\x13F\x8dY\xa8\x996l\xe4Q:Y#Nt\\闤\xa3\xda[\x84\f:Q\x17\x15\xb0$Ow\xff+\xa4\x1f\xa5~\xa8X\x0f\xa6\xa1\xc3\xc6@\x8f)\xcbH\x12\n(j\xd0)\xa1\x16Տ\xd2!\xea\x91P;!\x1bPݴ\xb2?\x1d\xf5\x1a\x99\xc56\xd60\x86\x90({H\xe9H\xa5\xd0\xf2\xb0l\xa28\xbb\x9a\x86\xea\"d\xe6\x00Z5!&\x10\xca*\xe4\"|\x11\xea\xa9\nXG\xe3 \x01\x00`9\xb1\x13\xb0<\xb4\xc7\xfa\xad\x95\x8e\xdb\x14N 7\x1d\xc7\xf9\x88\xfa\xc5C\x05\f\x85\xe8\x97\x1dZ\xa2\x1dT\xfdx\x01+\xd1&\x8f\xdaPF\x84\xfaa\xd6U\xb4+\xe7V}6\x95\xf7\x19\x99\xc56\xd60\x05L\xdbU\xade\x13\xc5\xd9\x1e\xb4\x8e}\x16\xa061\x81PV!\x17\xe1\x8bPO\x98\x03\x03\x80\x95\x81\x9d\x80\xadF\xf5ܷ|\xb4\x8b6\xec5\xecKDR\x1ax\x16\xeaV\xbf$\xa1\xb0\"`n\xd5.\xa2\x8e\xf3\xeaiC\xe7\x04,\x92\x8a\x86\xd4\xfdi(\xa8\xf8\xc9a_\x9aP)!\x85(?8Mx\xe60\xd6-t\x01\xcb\xd5v=\xa4\t\xd8lg$\a\x9dd\x9fcW-\t\x84\xb2\n\xb9\b_\x84z\x82\x80\x01\xc0\xca\xc0N\xc06\b\x13=٨\x816\xec]\xea\xb7\\\xd47\x85Pn>#\x05\xf5+\x02\xb6N3\x8c\x04\xdb\x03\xa5n\x846\v\x02\x16FH\x9b\xc1Z\xa3\x8c\xdeZ\xb5N\rӜ\xa0\x84Pz\xe9qn\x99\xc6\x1c\xc6z&\xba\x80\xa9\xbb\x8e\xd3\xcf\x18Έ\xa4\xf6\xa6\x18B\x02\xa1\xacB.\xfc\x17\xb1\x9e `\x00\xb02\xb0\x13\xb0:\x94o~\x99DtV\xa9U\xef\x94\xe5\xa3\x13\xe3ȤK\x110\xad{\xd4\xe4\xa2?\xac^c\x11\xb0Q\x94\xacy\xf2\xa1f\xa2\xaffP5)\xb4١$I\xae\xbe\xa5g6\x97\xb1\x8ae\x19\x85)`\xb3\x9d\xddBh\xccH'$\x10\xca*\xe4\xc2\u007f\x11\xeb\t\x02\x06\x00+\x03;\x01\x1bBIf\xcb?\x8eR&iîS\xbf\xe6\xa03\x8a\xa4\x85Mc]\xc0\x0e \xf4h\xc7\xf0\x14i\x88\xd9\x03\xcbg\x9d*Q\x93\"\x83\x81\\dJ\xc3\xdc\xc6,AL\x01\x9b\xe5\x8c \xa1\a\xc6%\x10\xca\x1aS\xc0\xc4z\x82\x80\x01\xc0\xca\xc0N\xc0\x88\xc7l\xacS\xd9l\xbbU\x1b(\xdeJQz5\x19\xf4\xae\x1ce0<\xad\v\xd8t\x1ajc\xbfm\xb3\b\xd8\xf4*qZ\x8bS\x8bp\x90m\xb7\xa0d}\xf2j\x0ec\x8d\x98\x026ۙR\r\xf5\x11\xa3\x93\x85MB\x02\xb1\xac1\x05L\xac'\b\x18\x00\xac\fl\x05l\x10\xa1\x03\xea\xd6-\x1fJ\xbdDh\xc3Na\x9d\xb2ct\x89X\x15ʛ\xa1_\xfa\x904\xa1\v\x98\xacuw\xa62\xe9\xf7hw!\xdbQzD\x10\b%\x89L\xb7C(\xc9X\xe7\x15\xd3X'\x96\x80EsV\x8bJاO\xa9\r\x9f@,kl\x01\x13\xea\t\x02\x06\x00+\x03[\x01\xa3c\xac\a\xfb'\xc9\xf8\xf1l\x94\xd4M\u007fhE\xe8>E\xc1\xfaR\xe9\xaa\u0590\x84\xaa\xa7\x94\x91\xa6\x13m3\x86\x90\xd3\xe9l\xe6\u007f\xbc\x10\xb1I\xa6\x14\xd4ukZ\x95\x81\x91dT\xafhJw*j\xb2\bă\xa8P\x11\x9d\xa9R\xe36\xc0\\\xc6:\xaa\xe7\xd9=\xb0(\xce©\xa8~\x9a\xcc\x1cB\x8eq\xb1\a&\x945\xb6\x80\t\xf5\x84u`\x00\xb02\xb0\x170ҡ\xbfN'\x93=G\xa34\xec\xecU\xc9\xf7ek=\xb3n\t\xad\xcaS\xbe\xdc\x1f1\xe7\xc0\x9a\x10r\xfb\xf2\x92\x9c\x01\xb6^!OI:\xa0)OG2J\xcf\xcbDT\x05D\x81\xb8\xe4DR\xce\xeaT\xe4⦚b\x1a먞g\vX4g=\x12r\xe69QJ\x8f\xa5\xcb&\x945\xb6\x80\t\xf5\x84\x95\xf8\x00\xb02\x88C\xc0\x88| ?=)c]\x9bvOOiأ\xbe4\xa7\xef\xac\xfa5\\\xe3\x96R\xf3\x9a\xe8`\u0378\v\xd9\u007f\u007f\x86\x94\xb3\xe7\xdb)\x89\xde\xfb\v\x15\xacJ?\xa1+Ϩ?S\xca,\x19\xd0\xfc0cu\xcf\xd86\x8f\xb4JI\xc3g\x1c\xd3XC\xf5\x1ce\x12?\x9a\xb3PUfrF\xf9(\xb1\b\x98P\xd69\x04\x8c\xaf'\b\x18\x00\xac\f\xe2\x110\vz\xc3\x06\x00\x00X^@\xc0\x00\x00HX@\xc0\x00\x00HX@\xc0\x00\x00HX@\xc0\x00\x00HX\x16 `\x00\x00\x00+\x03\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x96E\x13\xb07\xf0\x8b\xd1w\xc0MK\x00\x00\xee\x12 `\x00\x00$, `\x00\x00$, `\x00\x00$, `\x00\x00$,v\x02v\x1a\xff\xfa\xbb\xe7ʼ[?&wNoY_\xf1\xe2M\xf6\xeb\x1f\x0eV\x14y\xb7\xbc\xfcO\xf6\xe5\U000fd6ca\x9f\xba\xa8\t؍\x17+\x8b6\xed\xbd\xc0yP\x04,\\\xeet\xe4w\x10\xfa\x96z5\"#9`\x04\xfc\xeeI\xd6^\x97\x98\xdcM옏\xed\x029\x84Rh8\xef>\a:\x14ݠ\x9f\x15 \xe3!\xee]\x89\"\x1d\xca\xeeC\x8a\x1fD\xe3~\xdb1\x92\xc4\xdc%\x8d\xa8_\xc7R\xd8\x01\xaaV~rD\xc9 \xe4K\xcb\xf4\x0ff\n\xaf9\x03\x80\x1f2\xf6\x02\xf6\xe2&\\\xb6\x1e㏟\xc5\xde2\x8cw\xd3\x1f_ĸbk\x85\xf2\x0f\x95\xb3S\xf4KQ\xd1n&`\x17\x8a\xb1wk%Ư\x99\x1eZQ\xae\x13\xe5z\x10*'d\"E\v\x0e\xe4AAmw#\n\x06\xdbPK0\x88\x1aI,Ύ\xc4o\xbb@\xf4,&\xfc\x0e\xfa\x96C\x9f\xc3?\x11\xdd0\x12L\xa9\x0e\x0e\x1e\xf38\xcc(G\"S\x1d\xe8\xf0\x04\x99hB\x1dS1,\xcc\xdc\xc8\xf4\x10\xabА\x1e|d\xa8ZR\xfe\x1d\xa7\xd5\x1c\x9a\x95j m\xcd\xf1\xce<!>\x12\x00\xfc\xb0\xb1\x170\xbc\xe52\xb9}\x10{\xbd\xa7\uf40f1\xbe\xa8\xa8\x14\xf6~\xae\xec\xfa\xbc\x18\x9f\"\xe4\"~@\xd9\xf1\xfdS\x98\n؍b|\xf4\xb6\xb2g\x13\xfe\xd8\xf0ЊP\xb6\xd2\xd8\a\x1c4\xfcO\t\n\xd0\xdfF\xf4\x10\xdeJ\xa7Li\xb1ô\xb5\xa6\xb6\xcc\xce]c\x8d?~\xdb\x05\xa2gA\x02%\x8e)2\xe9(\t\xc44\x95\x1a\x94\u007f\xa6\xdcܛaEB\x88\xbeC\xf6,\x8a\xa5p\x84ˍh\x152h\x90\xa2\xfdʘL/\x8d\x10r\xcb\x03\x02\x06\x00:q\b\xd8e\xe5\xe32\xc6oЯ;\xf1iB\x8e>\xf02\xdbw\x14\xbf@\xc8A|\x94n\xdf,\xa3\x02v\x14\xefe{\xde\xc7?6<\xb4jq\u007f\x8e\xa1le\x10\xa8*\xd7.d\xe8C$\xac\xb5ְ\x11Ah\x16\xf9\x9b\xe3\xb7] z\x16$\xe0\xf7u\x91\x13>\xbf\x8d\x80\x91\x86ԙ\x18\xfb\xe3\x100#72\x0f\x01\v\xa4\xb2\xb1c3\b\x18\x00\xe8\xd8\vX%\xfd\xb8\x8d\xf1\xdf\xe8\xe7A\xda\xe9\"\xb7o\xb3}o\xe0gɝ\x8d\xb4OF\xa8v)\x02\xf6\xb0\xd6\xf3R̯\xe9\x1eZ\xd1Z\xf69\x95\xa4\xb4\xbc\x88\x936\xcc\x19\x97\xd8\b\xcd\xd6z\xa2 -\xe7q\xf6\xee\xfd\xa0ϝ\xe2*Q4\xafW\x9b\xf7\xca\x17lG\x93\x11\xaa\x0fWe;6L\x93\xa9\xcdY\x92\xbb\x94\xbe\xed\xbe\x16\xa5\xb4\xd7\xe58|ょZ\x94\xdcZ\xe3\xce(U\xf3l\xcbw䵉\x1e\xf8,\x02\xfe\xb6rR\xf2\n\x150\xd3oH\xb1-%n\x84\x9c\x11]\xc0\x1a\x93#\\y\xf9\xe2\b\x02\xa6\xe7f[!B\xe4\xaa,gy\xf5,\x013\x0e\x89\xa7\x86}\x9fh\x8ep~\xb9\x1aG\xaf<\x00\xdc\xcb\xd8\v\xd8S\xf4\xe3_\x18\u007fO?\x9fe\x02Fn\u007f~\xfa\xb5\x83\x95X\x11\xb0\xef1\xbe\xad\x19\xbeHn*\xe3\xcd\xed\x8c\"l\xcc\xe3\x1b\x81\xbc\xb3i\x18\xb6mh\x872\x9cDyB&Fk\xadI\xda\xd1\xd7\xeaʟ\xa1\x83\xccG\xbb\a\xda]h\x9a\xdc\n\x06s\x1e\f\x06\x83a\xc16r\xb23;'\xdd]W\x85\xae\x92>T3x\xb24iX\x11\x9a\xced\xe4jhN/'\xbc\a\xfak\xf6\xe1\x9fg\xb3i\xabj\xa9\xbe\xaf^\xaa\x12<\xf0Y\x04\xfc\xe3i\x93\xabd*`\xa6ߙ\xa1\x86\xa4!ҁNP5S\x05,?\x8f//_\x9c\x10\xea\x8bD\"\xfdH\xc8ͶB$\xec\xcc\xe9\xe8\xf5!\xab\x80\x99Y$q\xe3f\xc3/W\xe3\xe8\x95\a\x80{\x19{\x01\xdbG?\x14\x01c\xb7\x1c\x99\x80\xdd9U\x861~`\xebNE\xc0\xaea\xac\x1a\x9eW\x04\xec;lbL\x82\xb5\xa2zuc5\xea&d\b\xb9f\x88\x1f\x89sXzk\xedC\x1d\xec[\xa7\xd2\xc3pѶ\xd7\xe6d\xbfG\x1fq\xe5#ߔ\xd2MR\xa4\xa8\x8bN\x97籈H\x92S\xe9\x80T\xb9\x88\xe8A\xcaV,&\xdd\x05\x84\x9caݣ\x01\xaa\xa5\x9c\aa\bI\xf2\xb6\xad!T\xc0x\xbf\xa4\xba`\xc2}\x98mI\xf5\x91[\xa3\xe5\xe8C\xa1\xbc\x9c\xb3\x90\xd6\xc3\n\t\xb9\xd9Vh\xadG\xe9f\xcd\xe4Y\x04\xcc\xccb\f\xf5\x1ai\xf8Z\x985\x8eQy\x00\xb8wY\x88\x80\xbd\x81\x1fx\xe1\xf4śl\b\xa9t\xbaԕ\x15\xef\xab=0c\xe4hЊ\x1eW7ܴ\xcd\x13\x0f:\x1bq$\x8b+\x01\xf4\xd6\xea\xf7LS\xdcՄ\x8cgyj\x8f\x8f\x12\xb5\a\x11C\xc0\xa4\xab\xda\xd6D\xdb\x06\x8fS\xed\xd5Ity\x06\x9bH\xe2=HlF\xab\rM\x92\x9a\xd5,\xc5\xeajу `M\xa8\x91\t\x18\xef\x97D\xf22\x1fR-$\xaaN.\xaa&\\y9g!\xd4<<<\xdcB\x05\x8c\xcbͮB\x93ꪋz\x8b\x80\x99YL'\x9b\xaa\xcf\xd7¬q\x8c\xca\x03\xc0\xbd\xcb\x02\x04\xecv1\x9d\xc9't5ų\xe4\xce&\xfc9\xfb\xf2\x1a\x9d\x03+\xd3;^\x9f\xff\xe3_\xba\x87V-\x92\xe3$Btv\xa6\x01\xd5\xf6\xf3\xb1\x1d)zk\xcd\xd3\xfa.\xb4\xcf3پ9\x17e\xaa\xcb%b\bX\xbe\xfeS\xa6{OOp\x9d*`t|\xa76g\u0383:\xea\x1bD#d\xad\xaaB%\x05\x82\aQ\xc0&\xf6L0\x01\xe3\xfd\x12ҭ\xaf\xfc\x90j\x86\x87\xd5\xe1\x1f_^\xd3\x197\a\xc6\xe7fS\xa1\x11սu\x12\x9f\xcbB\x9b\x03\x9b\x1e\x10\xfdr5\x8e^y\x00\xb8wY\x80\x80\xfdS\xbd1InV\xe0\x83\x84\xbc\xa0\xa8\x98\xc2\xedJ*`\xcf\xe1\xedw\xe8\xb7?`\xef\xf7\xba\x87V\xb4\x8aM+\xff\x02\xb1n\xc3\x18rע\x93b&zk\xad\xf2\x8c0&\x94\xf6L{@S\x9d\x0e6\x01\xce\xda{\xc7U\xc1V\xf9\xb5\\\xdb\xc8-\xa0\xd3\xda\xe5\x16\x01\xe3=Hl\x1a\xae\x1dM\x91j\x0fK\xe2\xa9\x16<pY\x04\xd4\x15\x0eT\xc0x\xbfDάϞ$F\x16\f\xae\xbc\x9c3N\xc0\xb8\xdc\xec*4\x89\xd8\x1e\xeb$>\x97E\xc0\xc1\xfa\xad]hB\xa8ET\x01\x13r\x03\x80{\x96\x05\bؿ6⣊Lѥ_{\t\xb9\xb6\x1e\xff\xfa\x0e\xb9y\x90\xad\x03\xbb\xec\xc5/(#ʋ\x9b\xb8\xe7\x8aZ\x11\xcaS\x14줤\xcd\xe1\u070f\x1c\xe9\x96U\x10zk\x1d@]\xf4\xa3\xfe0\xed\xa8\x9d\xa1\x9b\x85\xdbؿ\x85\x84|\xab\xee\xe3\x05L\xefƸ\xa9t\xcc\xe4Y\x04\x8c\xf7 eN\xd1\x15T\x85tN\x89NXu\xa2>\xc1\x03\x97\x05'`\xbc\xdf\xe9\x82z\xb2\xcd7cd\xc1\xe0\xca\xcb9\xe3\x04\x8c\xcbͶB\x05nE\x1fë,\x02\xc6e1\x99^\xae\f\tg\n=b-\xa2\n\x98\x90\x1b\x00ܳ,@\xc0\xc8\xdb\x18W>\xf5\x13\xbc\xf1e\xbcU\xf9\xe9\xe3\"\\\xf6\x13/\xde\xc74\xeb\xfcz\xec\xdd^\x89\xf1\xeeۆ\x87V\xe4KM\xb9ύ\xf4\xb9\xfc\xe3\xc8x\x8cHc\xa4\r\xb5\x8c\xb0\xad\x00\xf2\x9f\xec\xadF'h\vL?\xd0\xd7S\x8d\x06\xe9\xcf\rRs\x8f/m\x9c\xb7\x9d\x1eb\xb7\xf2\xc6\xd8n\xb4\xb9\xedp>r5\r\xc9\xc1\x94\xea!2R\x9d\x12\x94\x05\x0f\x12\xca\xef:\x9e\xe3\xa4\x03\xbf\xaa\xa4@_ \xa9J\xf4`f1\xe9_\xf7\x8d\xf2\xf5\x9bu\xfeI\xceo$X\xeb\x1a'\x97\x9c\xbb\x82\x11\xba\x12\xdfX\x03b\x94\x97s&\xac\xc47r\x8bQ!n%~\xc8\xe1>T\x9f\x91\x94\xdc\x11RW\xe2\xb7\x04\x83W\x85CB\xce8\xee\xef\xe8\xf5%\a\xf9Zp5\x8eUy\x00\xb8wY\x88\x80\x91\v\xbb˼[^\xfe\xfef\xd1\x037\x94o\u007f;X\xe6\xdd~\xe1c\xb5\xd3u\xed\x85\xca\"\xef\xf6S\xa6~)\x02\x16\x18\xf5\xa59\xd6\xf6kߧ$\xe31\"\x95[\xe9\b\xa1T\xf5\xb9\x9b\x81u\x19Nfy\xa2\xf0\x90;%\xb3Pm\x80\x91\x1d\x19\x8e\a\x87\x05\xdbQ\xf5!\xc2\x12\xfa\xe3LK\x8e\xe4\xf2wx\xa4\xc2Z委P\x9a\xf2o\xad\xe0Az\xbcڙU%3g\xc7\xf2\xb4u`\x9c\a3\x8b\x06\x84\xe8T\xd36\xfa<\xa3\xe9w@1\xac#;\x94\u007f\xcf\xd2g!W\x1be\xd7\xcb\xcb9S\x9f\x85T\xfc\xb0Yy=\xb7\x18\x15\x1a垅\f\x97fd\xef\xe9HV\x8a^\xadM|\xf9\xf9,\b}\x16ґY\x1a\x12j\xc1\xd58V\xe5\x01\xe0\xde\xc5N\xc0\x16\x9fK\xe6cDK\x869\xea\x03\x00\xe0\x1eb\xe9\x05\xac\x1e\x1d\xb03Yt@\xc0\x00\xe0\x9ed\x89\x05,4ֵJ\x92\xed\xac\x16\x1d\x100\x00\xb8'Yb\x01+G\b-\xb9\x98\xa8\xb3\xdb\x00\x00\xdcs,\xb1\x805\xa5\xba\x96~\x00\xc9f\xb7\xc7\xec\xac\x00\x00H8\x96X\xc0\x00\x00\x00\x16\x0f\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x96\xc5\x12\xb0\x1b\xc2\xc3C\x0f\xc56\x04\x00\x00X,\x16G\xc0\xee\x9c\xf2\xde4\xbf\x81\x80\x01\x00\xb0$,\x8e\x80\xdd\xd6\xdf\xcb\xca\x00\x01\x03\x00`I\x00\x01\x03\x00 aI\f\x01\xeb-\x88\x11';~\xb6\xd5\xd8Y\x00VV\xca1\x9b\xbcߌgr\x17X)\xd5\x04\x16\x80\xad\x80]{\xe1ᢍ;\u007f\xa3\xce\xd1\xdfx\xb1\xb2h\xd3^\x161\xed4~\xe3\xfb\x17+\x8a*_\xfe\x9eƄ\xa4\\֓(\x02\x16.w:\xf2i<\x9d\x16\x94\xab\xfex@x\x8d\xe1\xe4\xb6LGI\xacȰ\xb3h\xfc\xf7\x9f\x9f\f\xa3\x00\xa9EI]vvQ\xa0/\xf8B\xae\r#vv\xf3\xa5\x06\xa1fB\x03\xd5\"k\x03\x1ap\xdd\xd5\x06\x1b/+\xe7\x985%\x1d\x8e\xfa\xfb\xa2\x1c\xa8\u007f\xa3\x9a\v\xa4'Y{\xe1[r\xb7\x9d\xe9\xbcl\x17\xc8!\x94B\x0fc\x9f\x03\x1d\x8an\xd0\xcf\n\x90\xf1P̈\xca\xea;\xf0\x0e!\xf5\x1dx6\x8cp\xef\xc0S\x18Ka\x12A߁爒Aȗ\x96\xe9\x1f\xcc\x14\xa3\x00q\xd8\t\xd8\xe5b\xbci\xfb\x8f1\xfe)}\xd7\xfd\x85b\xec\xddZ\x89\xf1k\x84Ł\xac\xc0ś0\xder\x9b\x9c>\x88\xf1\xbe\x837\xf44\xad(\u05c9r=\b\x95\x132\x91\xa2E\xa8\xf6\b\xaf1\xf4e\xbeR\x9d:I\xe2\xe3XR\x87\x9d\xc9lΊ\x8d\xa7jշ\xf4\xa1nN\b9\x83\xb3s64\xfa\x8a\xd5\xc1\x8e\x82E\u007f\xbb\xe9xz\x13=\x02\x93M\xe9\xe3\x96=}i\xdd\xda\xd6\xdc%[lV\xd81\xe3\xb2\xe8Kn\x8dfa\x1e\xa8\xf9\xb0x\xd5\\\xa0A#\xd2^\xb9\x8bbG]ѓ\xc5c\xbb@\xf4,&\xfc\x0e\x9f\xf2\xe1s\xf8c\x8cs\xe8[\x88\x83\x83\xc7<\x8eP\xf4\xfd\xe2[\x88c`\x1c\a\xee-Č!\x16\a\x82\xbd\x85x\xf6+\x17\x06\xd2\xd6\x1c\xef\xccC\xb1\xa3\xd1\xdb\t\xd8>\xfc\xb2\xd2\xf9\xba\xb8\x11\x9fW\xfa_\xc5\xf8\xa8\xf2\xe5\xf3M4\xf6\xd0i\x8c\u007f\xfc9!\xe7\x8bh\x88\"\xeb\x10\x12e+U\x1dp\xd08\x15%\x88Ɨ #\xc2k\f'Q\xab\x16\x8f1\x0e.\xa9A\xd1\xe6\xc9\x1a?\xff-\xacF\xd7\xe5_\xab\xc3\x19\x88\xb6\xb3P_r\xbf6gN\xa3\x05\x90\xa7\xea\xf2q1ʯ\x80M\xc9\xe6\xc9D\xe1\xdc#\xf1\x15v\xcc\xf8,\xea%\xab\xca/\x9cE\xac\xe6\xc2\fZ$-\xe8A\xaa\x18\x1f\x95GO\x16\x8f\xed\x021J\x16(qL\x91IGI\xecvƎΔ\xdb\x12M\xccD\x88F\x1f\x1d\xfe8\f\vRe\x8d\xc4\xc51\x99^\x1a\xa1\xd1,\x16.`\x95\xea\xc8\xf0\xed\x83\u007f\xa0#Ž\xec\xb7\xf7\U0004f640\xb1=\xcf\xe1\xe7\xa2\b\x18\xab\xc81\x94\xadt\x81U\xe5څ\xf8\xa3\x13F\xf3\xe8\xfaWgݲ3\x89\x02\x1f\xb9\x8c\x06\xfba/!\xe3\xafR\xce@\xb4\x9d\x85zv\x8e\xa1\x85\x14c.\xca\xd5(\x01\xf5fl\xa4Yؔl\x9e|9\xd7\x05FV\xdc1㳸\x95e\t\xa4\xf0o\xb0\x88\xd5\\\x98A$\xac\xb5ְ%\xba\r\x87\x9e,\x1e\xdb\x05\u0085\x12\xf4u\x91\x13>\xbf\x8d\x80\x91\x86\xd4X\xb3>q\bX\xf4؈\x949\x04,\x90\xcaƎ\xcd\v\x17\xb0\x9f❟\xeb!\x1e\x1f֢>ަ\xf1kO\xe3-\xec\xcb)\xfa\xd2|\xab\x80\xade\x9fSIJ\xbe\x11'-\u058c\xcb,\xc2t\x86:\xa8\xaf\xa3/\xbaI:A\xc6$:\b\xaeE)\xedu9\x0e\x9f\xfa\x876\\\xeeJ\xc9\xdc\xc0\xae\xac\xe9\xf4=\xec\xa7\x03J\x92N҉\x8c\xe8 \f1ى\x82\xb4\x9cǕ6ӫ\xcd\x1b\xe4kVcɻا\xb4G\xb3\xe5\f\xb8\xcdZ\x94\xdcZ\xe3\xce(\xb5\x1c-\xf5\xecT\xb9\x85,\b\t\xfa\xdc)\xae\x92lk\xb2\xb6|\xfdm\xf5\\\xc9\f[ރ\x19\x00i4Y\xa9U\xb8*۱a\x9aL\xa6\"\x94\xc4b}\x8b\xb5Г\xf1\xb6Q\x89aК\xd3\x17Fᾜ\xb6\xe5<fS{r\xd3\x1f\x1cr\xf7\xf3g\x9eD=\xa8\xd6\xe2ԧZ\x1b\xb0y\xa0\xc4\n\xe9,A5\xa3\x9f\xa19jab\xb6V\xfbd\x9a-\u007fb\xa76gI\xee\xd2Q\x12\xeb:\x8b~Mr\x1e\xf8,\x02\xfe\xb6rR\xf2\n\x150\xd3o(\x99F#u#\xe4\x8c\xe8\x02֘\x1c!\xd1/DA\xc0\xf4\xdcl+D\x88\\\x95\xe5,\xb7\x86\x12\xe4\x0e\x89\x16\vu\xa29B\xa2\xb6\xacZd'`\x9f\x17a\xbc\xf1\xe0i*O71\u07b2\x9dQ\x84/(\x02\xa6v\xc7NG\x13\xb0:u#\x1b\xf5\xd3\xf8\x18;ht0n\x9c4\x1a\xecD\r\xc1\xe07D\x9bz`\x83\xe0Pg2r54\xa7\xb3\xee\xc8`z~\xd3@\x03b\x9d\xe6\x11m\"e\xc2_\x10\x9c\"S\xc1\xb5~~BOHV\x93\xb4\xa3\xafՕ?Cn\x05Y\x90\xa0\xa0~\xb9\xd5h\x03\x10\xa5\xc1t\xf6f*\xb6\x9c\x01\xb7I\x9de\x1f\xfey\xb6e\xac\x1fB}\x91\xf0\x1etX\xc8B)ף\xdd\x03\xed.4-&\xab\x96\xea\xfb\xea\xa5*\xb1d\xa6-\xef\xe1\xf8\x1a2\xe4\x1e\"\xf9\xc7I\xe4dgvN\xba\xbb\xae\n]U\x8c\x83A\xf5z\x11ja$\x13l\xa3\x11\xc3@\xaeB\xab\x95\xff6\x8f/\xe31\x9b\xf4\xb8\x9a\xfak\x11j\xe3\xcf|\xf4\x97\xdcG\xa5\x00\x00 \x00IDAT\x83j-Np\xf6\x9fg\xe3@\t\x152X\x82jF?Cs\xd4\xc2\xc4h\xadq$\xd3l\xf9\x13ۇj\x06O\x96&\rǺ\u03a2_\x93\x9c\a>\x8b\x80\u007f<mr\x95L\x05\xcc\xf4;3Ԑ4D:\xd0\t\xaaf\xeaq\xce\xcf\xe3\xcb\xcb\x17\x87\x9e\xeeH\xa4\x1f\t\xb9\xd9V\x88\x84\x9d9\x1d\xbd>d\x1503\x8b$n\xdc\x1c\xade\x85:\xed\x04\x8c\\>\xe8\xc5\x18\x17\xbdx\x9b|\x87M>\xd6\xc3\x15E\x170\xad\x8f\xb4\x1au+\x17)r\xcd\x10?\x12F\xf0\xe6\x10\x92\x8fj\xe8T.\xa5*\x97\xb2\x15qoP\x14w\xfa$\x9b\xe5\xef\xd3\xfbn\x1d\xea_\xeb\xd5'\x88\x80\x99\xac\x0f\xd1I\xa5a\x163Q\xe8\xb1^M\xa9\xd5l3\x15\x975.b107\xa5\xec)\xa5\x99\xb9\v\bO\x88\xfd\xf1\xa0g\x84Ϣ\xcdE\xe5\xa8\xcd)&;\xc3\xfe\x14\rP\xe5\xe6J\xc6\xd9r\x1e\x82.\xb2G\xdaC\\L\xa0\xf3\x91oʘ\x17t\xe8\xe3\x19\xa3db\xddx\xdbhD78\x93\x82R\xfa\xd9\xd6r\x1d\xb3*'\xedTױ\x18\xbe晏qP\xc5\xc1\xd78\xbd\x96f\xa1\x1f(\xb3B<w\xbf\x9a\xd1\xcfP\xecZ\x98\xe8\xad5\x9ed\\,T\xfd\xc4F\xba\xe8\xd9\xcdc1\xe1\xa3^g1\xaeI\xfe\xd2\xe0\x86\x90$o\xdb\x1a\x16\v\x95\xf7K\xaa\v&\xdc\xea\xed_\xa9>rk\xb4\x1c}\x18\xebB\fi=\xac\x90\x90\x9bm\x85\xd6zn\xd1ȫ\x16\x013\xb3\x18㦚\xa2\xb7,\xdb!\xa4\xc2\xed\xcf_ۊ\xf1\xb3\xb4\av\xcd\xfcuN\x01{\\\xddp\xd3\x1a\x13\x0f:\x1bq$\v\xf7A\xa3\vX\xb5\xbeُFM\xdb\x1e\xa4\xbdLu4)r\xabcrZ\xe2\xf6\x89\xc9\xfc\x9ei\x8a[\x8d\xba\xcd\x1d\xafZ\xfd}\xacR\r1\x86\xdcѯR6\rІ\x84\x1b\xa4!\xd4<\xd4W\xe0\xa0>\xb8,Ƴ<\xb5\xc7Gɴ\x98\xacF\r\xb9\xb6\x9a\xc5\xcc6J\xc6\xd9r\x1e\xae\xa2[\x0f>\xbavJ\xed(\xe5K\\\u007fi\xb6\x80\x89u\x93\x84\xbe\xd5l\xa2\x19L\xd6In\x94%\xed\xa1U[\xaec\xe68\xa0\xee\x13\x05,\xc6A\xb5\nX\xb4u\x0e\x86\x80\x19\x15\xe2\xb9\xfbՌ~\x86b\xd7\xc2Do\xad\xf1$\xe3\x04\xcc8\xb1\x13m\x1b<Nu\\\x13\xf5:\x8bqM\xf2\x97\x06/`M\xa8\x91\t\x18\xef\x97D\xf22\xb5\x15\x9d\x12U'\xb6f%\xfa\x85\xa8\x9c\xee\xe1\xe1\xe1\x16*`\\nv\x15\x9aTW]\xd4[\x04\xcc\xccb:\xd9\xec\xf7DoYv\x02v\xe7\x1f\x9f\xb3\xcf\xdf\xe0\xa2\u007f\x912m\x0e\x8c|\xfe\x8f\u007f\xcd-`\xea݊I\x84h\xf7\xbc\x01\xd5\xf6#\xf1\xfeEt\x0136[\x107\xdf1\xa4\x9f\xbdH\xf2h\xb32\xe8N\xb2̅\x98\xc9\xf2\xb4?\x03\xec\xcf\aw\xbcd\xa9f\x96m\xac\xab\x945\x88A4B8\xd8\x00\u007f2\xa9\x9d\x88YL\xb6o\xceE\x99\x8db\xb2\xb5\xea\x19/) Bn\xa6-\xefA\n\xa5\x8f\xa4\x87R\xd8\xcch>?M2[\xc0ĺ͞R\x11\x89f\xd0\xe8j\x0f\xa1\xd01\x17\xfd\x93\xbaL\xc7l\x1c\xf5\xd0}S\x16\x01\x8bqPŦ?l\x89&\xaab\b\x18WH\x93\xbb_\xcd\x18g(f-L\xf4\xd6\x1aO2N\xc0\xf4\x13;\x9c\xe9\xde\xd3\x13\\g\x89Fo\u007fM\xf2\x97\x06/`\x13{&\x98\x80\xf1~\t\xe9\xd6\x0f\xbaT3<\xac\x0e\x84\xc4#\xa9;\xe3\xe6\xc0\xf8\xdcl*4\xa2\xba\xb7N\xe2sYhs`\xd3\x03$V˲\x11\xb0\xef\xf1\x03\xff\xa4\x9f\x971\xbeM\x9e\xc3\xdb\xe9j0\xf2\a\xec\xfd~n\x01[\xc5\xe6\x15~\xa1F\x80\x1dC\xeeZtRpk\x11\xb0z\x8b\x80}\xc8_%\xb7\x8c\xfbC\xb9\x9d\xeb\xd6\xe6\xf6\xe4\x12\x113Y\x95g\x841A\u007ffǫ\x83\xfd\x81\xa8K\xba4\xcbV007%6{\u05ce\x84їzv\x9c\xb4\xf7\xc0e1B\xff^Mu:ڄd\xd5\x1e\x96\xc4S-\xe4\xc6\xd9\xf2\x85\xcci\xca\"\xeef5E>?\x81#\n\x18-\x99X\xb79\xee[\x92\x98\x06t\xaa5\xa4\xfdu^\x9ec6\x93\xfasu\x9f!`\xf5\x962\xf0\a\x95ύ\x90CR\xb4!s\xbc\x02v\xb7\xaa\x19\xfd\fŮ\x85\x89\xdeZ\xe3I\xc6\t\x98~bs\v\xe8\xdf\xf1r\x8b\x80\xd9_\x93\xfc\xa5ada\xdeM\x12\xfc\x129\xb3>[\xedp\x1am0ƅ\xc8\t\x18\x97\x9b]\x85&م@\xac\x93\xf8\\\x16\x01\a\x1b\xb9u\xa1\x89\x18-\xcbN\xc0\xc8O\xf1O\x15\x05\xbby\x10?\xa5\xa8\x98\x17\xbf\xa0\xe8\xd4\xc5M4\b\xb7 `\xa4\b\u007f|[\xbfYI\x97Q\xe4)\nvR\xd2d\xea~\xe4H\x17\xbbM\xa6\x809\xf6(\x83\xe05\x16\x01\x9b\xca,\xa4\xedl\x17;\x05d\xb3G\xbby믕ΠZ?\x111\x93\r\xa8\xa3\x8cz6l/,$\xe4[\xf6\xc37\x92q\a\x9e\xbfJM\x03nSʜ\xa2\xcbN\n\x99\xc5\xd8a\xf5\xeaV\xcfNf\xdd\xe8/\xf8,\x1a\xd0\x19\x96v\x9b\x90\xac\x8fM\x0et\xa2>!7Ζ/䆂rR~\xbf\x8fe\"\xfc\xa16\x04\xcc(\x99P7\xdev\xac\xc1\xd2%\xb0\x1ap\x8c;\xd5\t\xebe;f\x9b]\xf4\xba\xafb\u05edy\xe6c\x1cT>72\x93\xab\x85P\x17\x89W\xc0\x16\xbb\x9a&\xd1\xceP\xccZ\xe8G\x87\x98\xad5\x9ed\x9c\x80\xe9'\xd6M\xa5c&\xcf\"`\xf6\xd7$\u007fi\x18Yp\x02\xc6\xfb\x9d.\xa8'\xdb|3F\x16\x8c\xe8\x17\"'`\\n\xb6\x15*p+\xfa\x18^e\x110.\x8b\xc9\xf4rE\tf\n=\xb1Z\x96\xad\x80\xdd\u0604\x8b\xb6l\xf5\xe22:\xfdu~=\xf6n\xaf\xc4x\xf7m\xab\x80m\xc7\x18_\xd0Ӵ\"_j\xca}nc\xbd\xc3q$<F\xa4݅Ԧ\xf1\\\x8d\x87\vPrGH\x8d}6R\x9d\x12\x94\x95#\xb1j\xf5+\xfd;\xb4\xe7\x12\xc2I\xcdj\xba\xc3\x0e\xe7L\x8e\xe30\xef\x8a\b\xc9\x02\xc8\u007f\xb2\xb7\x1a\xb1Y\xfe\x06\xa9\xb9ǗF\x1b\xec\xe3\xfa]\x00\xc1\x963\xe06%\x94\xdfu<ǩ&(\xd5\x06\xbe\xa3l\xe2p݆\xea\xfb\xf8,\x1aP\xfa\x81\xbe\x9ejv\x8f\x94KV\x95\x14\xe8\v$U\x89\xb9\xf1\xb6\\!\xebP#i\xa27i\xa7\x87\xd8M\x1a6\x1d\xa3l\a\xa5\xea`pJ,\x99\x91\x8c\xb7e\x85L\xb7\xcc\xcaX\ff\xb3|\xc7\xec\x9bLw[w\xa9\xc4\x04\xcc8\xf3\xb1\x0e*\x9f\x1bi\xb1\x0e\xdd\xf8\x03%\x16R\xe7nV\xd3$\xca\x19\x8a]\x8bRc*e\xa4\r\xb5\xa85\xb2O\xa6\xdb\xf2'\xb6\x01mn;\x9c\x8f\\MC\xb1\xae\xb3hפxi\xe8YL\xfa\xd7}\xa3|\xfdf\x9d\u007f\x92\xf3\x1b\tֺ\xc6\xc9%\xe7\xae`\x84\xae\xc47\xea\x1d\xedB\x14V\xe2\x1b\xb9Ũ\x10\xb7\x12?\xe4p\x1f\xaa\xcfH\xa2\x17\xc1\xb8\xf6\xc0\xc1Uᐐ3\x8e\xfb;z}\xc9A\x12\xbde\xc9A;\x01c\x8f?z\xb7\xbc\xac\x8e\x10\xaf\xbd\xa0|\xd9~J\xd1/\x8b\x80]\xde\xed\xdd\xf8\xbe\x9e\xa4\x15\x05F}i\x8e\xb5\xfd\xda\xf7)I\x98\xbf\x888\xd9\b7\x99\x1d\x92p\xa1#\xdd\x17@\xa8\x96\xc5>\v\xa5)\xff\xd2\xdbB\xe1\xcd\xee\xf4\x82\x1e-A\xfd*5\xf9\x882\"iL\x1f&<b\xb2\x81u\x19N-\xdbȎ\fǃ\xd4\xf6\xdbԪ\xa8\xb6\x86\x01\xbf)=^\xed̪ҚA\x87\x8bN\xe1(\xfdW\x84\x9a\x94&\x99\xe3\xea\xe3\xb38Qxȝ\x92Y8hMv,O_\xadb\xe6\xc6\xdbr\x85\xecs\x8c\x92PZ/\xbd?\xc1\x0e\t\xebdh\x8f\x8a\xa1v\xb1dF2ޖ\x162\x1d\x89G\xc4j0\x9b\xe5;fd\xa2\xda\xed\xf0\x8d0\x013\xce<\x89qP\xf9܂\x8e=Ċy\xa0\xc4B\xea\xdc\xcdj\x9aD9C1k\xa1\x1f\x1d\xa5g\x94\xaed\x95:\x15W2Ö?\xb13-9\x92\xcb\xdf\xe1\x91\nc]gѮI\xf1\xd2гhP\x9f\xc6\xddF\x9fg4\xfd\x0e \xbaTs\x87\xf2\xefY\xfa,\xa4:\x85Η\x97s\xa6>\v\xa9\xf8a}\x0e=\xb7\x18\x15\x1a垅\f\x97fd\xef\xe9HV\x8a^\xad\x9eL\xe4\xe7\xb3P\b\xf9\x1c\x99\xa5!\xa1\x16\\\x8d\xedׁ-\x06\x97\x84Lj\x16\xc0.)\xda\x1d\xa88\t\xc4^\xc5;\x1b\xb3\xab</\x16\x98lQ\xe8\xb1\xce\xca,\x02w\xf7\x98\xa9\x93\xf8\xf3\xa1K\xaa\x9e\xb6\xb3Y\x00w\xb7\x9a\xcbL\xa2\x95w\x81,\x85\x80գ\u007f7\x98m\x8b\xfb[;\x93\x98\xd4Ԑ\xf8Y\xe0Y_`\xb2Šù\xcd\xced\xfe\xdc\xddc6o\x01\x9b\xcc\x12\xe7\r\x16\x8b\x05V32\xa6\xb2\xe8\xcf\xf6,*\xf3>-\x89\xc9]\x17\xb0\xd0X\xd7*iV\xc7{\xa5\xb2\xc0\xb3\xbe\xc0d\x8b\x80\xec\xaa[\xeev4\xef\xca\xcf[\xc0V\x04f5\x1f\xd4F;\xd6\xf9\xfc\x95żOKbr\xd7\x05\xac\\9Ӊr(\xd5\xd9\xc1y\xb3\xc0d\xf7\x06\xf3\xaf|\xf8\f\xaa\x9b_\x8a\x15\x00_\xcdp\xaf\xca<ƟK\xce\xfcOK\x82r\xd7\x05\xac)\xd5\xf5\xef\x0e \x97\f6;\x18\xfb\xee],\x16\x98\xec\xde`\xfe\x95_\x8b\xf4;8\t\xc4\xfc\xab\xb9\xbc$Zy\x17\xcc]\x170\x00\x00\x80\xbb\x05\b\x18\x00\x00\t\v\b\x18\x00\x00\t\v\b\x18\x00\x00\t\v\b\x18\x00\x00\t\xcb\xe2\n\x98\xfe|\xd1ܼA\x1f\x06\xd7X\xfc\x18\x92\x00\x00\xfc`\x00\x01\x03\x00 aY\\\x01\xbb\xfc\xeb\xf3v&\x04\x04\f\x00\x80Ebq\x05,>@\xc0\x00\x00X\x14\xee\x15\x01\xdb6\x9f\xe7r\x01\x00\xb87\xb0\x13\xb0\xdf\xe0S\x17*\xbd?\xb9\xa6\xbe\x18l\xd3^\xed\xad\x85\u05ceT\xaeߴO}_>\xb7\x83\u0381\xbd\xa1σ=\x8b_&\x96d\x9f\xef\xddT\xfc\xd4E\x8b\x80\x85˝\x8e\xfc\x0eB_Z\xa7\xbd.\xfa\x80\xf8\x02\xc48\b\xa3\x00\r5\xf8o\xbcug\xbe\xf4$k\x8f\xf4&wۙ\xce\xcbv\x81\x1cB)\xf4%\xb7}\x0et(\xbaA?+@\xc6C1\x9f\xe1Q\xdf\xe9t\b!\xed=\x92s2½\xd3Ia,\x85\x9d:\xfaN'G\x94\fB\xbe\xb4L\xff`\xe6\xc2\xdf(\x02\x001\xb0\x17\xb0\x17\xbd\x18\x17\xdf&\x17\x8a\xb1wk%Ư\xd1_\xcf{q\xf1\xf62\x8c\xe9\x8c\x17\xbf\x83\n\xd8?p\x11{\xfb\xe1\xedb\x1a\xba[Hv\n㊭EE\xbb\x05\x01\xcbu\xa2\\\x0fB\xe5\x84L\xa4h\x91}=Q\x038\b\x9c\x15_\xd0Y\xb5\xea[-\xd4`\x14\x03\x8b\xedl\x16bЈ\xb4WH\xa2\xc6(\tT\xf4d\xf1\xd8.\x10=\x8b\t\xbf\x83\xbe\x9a\xda\xe7\xf0OD7\xa4o\xd5\f\x0e\x1e\xf3X\xe27\x9a\boՌ\x81q\x1c\xb8\xb7j2\xd4\x00\x8f쭚\xb3\x1f!\x1eH[s\xbc3\x0f\xcd\xe7\xe5[\x00\x10\x1f\xf6\x02\x86+\xcf_8Mn\x14㣷\x95.\xd4&\x1a\x99\xe8\xbbb\xfc\xf2mr\xe7\r\x1a\xdcC\xd8\xc1\xeeB\xeeħi\xca\xf3x+\x11\xf7^\xc4\x0f\x9c\xbeC\xbe\u007f\n\v\x02\x86\xb2\x95&5\u082fX)A4\n\x00\x19\x89\xe3\x05\x88k\xfc\xfc\xb7\xb0\x1aJ\x97\u007f\x83\bg \xdaFa!\x06-\x92\xf6\x12\xefT3\xf2\x93\x15=Y<\xb6\v\xc4(Y\xa0\xc41E&\x1d%\x81\x98\xa6\xec\xe8L\xb9\xc5\xf8P\x1cq\x84\x87\xe7\x8fC\xdc\xe1\xe1'\xd3K#\xf4\xed\xec `\xc0\xe2\x13\x87\x80]\xa6\x9fG\xb5@\xdc\xef\xe3\x1f\x13\xf22\r\xf1\xa1\xb0[\x91*a\a\x13\xb0\xd3\xeaރ\xf8\x94%\xd9A|\x94n\xdf,\x13\x05\x8c5\x98c(\x9b\xbe\\\x94)\xd7.\x14\xbb\x15\xea\x88a+\xaa\xd57\x8e\xf1\x02\x1654V\f\x16b\x10\tk\xad5\x1c\xfb}\\z\xb2xl\x17\b\x17\x1a\xcb\xd7EN\xf8\xfc6\x02F\x1aRgb\xec\x8fC\xc0\xa2\xc7\xfa\xa2\xcc!`\x81T6vl\x06\x01\x03\x16\x1f{\x01\xabd\x9f\x0fk1!o\xd3\xe8\xb6[\xb4/7n\xdc\x11w0\x01\xbbY\x84\xff\xa9\xfc\xeb\xa5\xff\xf2{\xefl\xc4\x17ٗ\xa3\x82\x80\xade\x9fSI\xca\xf5\x1dq\xd2\xcb\u007f\xc6e^\xea\xb5(\xa5\xbd.\xc7\xe1c\xc1\rȉ\x82\xb4\x9c\xc7o\x11ҫM)\xe5kVcɻا\xb4G\xb3\xe5\f\xb8\xcdZ\x94\xdcZ\xe3\xce(\x15\x1b\x92\xe8Lς\x90\xa0ϝ\xe2*ɞ\x9d\x9b\x89\xd9Z\xed\x93i\xb6\xa3\xc9\bՇ\xab\xb2\x1d\x1b\xa6\xc9\xd4\xe6,\xc9]:J,\xd54<\x88\xe5m\xcb\xd7\xdeknz\xe0\xb3\b\xf8\xdb\xcaI\xc9+T\xc0L\xbf\xa1d\x1a]ύ\x903\xa2\vXcr\x84+/_\x1cA\xc0\xf4\xdcl+D\x88\\\x95\xe5,\xb7\x86\xc6\xe2\x0e\x89\x16\xdbo\xa29\xc2\xf9\xe5j\x1c\xbd\xf2\x00\x10\x0f\xf6\x02ƺS71\u07b2\x9dQ\x84/\x90\xf5\xf8o\xfa~q\x87\xba\x90u\x1f\x1dC\xbeO\x13\n{\xbf\xa7\xb1%)\xa7\x05\x01\xabS7\xb2i\x18\x9bm4Dπ\x16\x17\x98\x12\xeaLF\xae\x86\xe6t\x16\u007f\xae&iG_\xab+\u007f\x86\xdc\n\xb2x(A]\x89j$U\xe0$\x94\xdbٛ\xa9\xd8r\x06\xdc&u\x96}\xf8\xe7\xd9\xe24\x90\xe0\xcc\xc8B\x19\xc7>\xda=\xd0\xeeBӳr31Zk\x1c\xc94\xdb\xc8\xc9\xce\xec\x9ctw]\x15\xbaJ\xfaP\xcd\xe0\xc9Ҥa\xb1\x9a\xa6\a\xa1\xbc\xd5R}_\xbdT%x\xe0\xb3\b\xf8\xc7\xd3&W\xc9T\xc0L\xbf3C\rIC\xa4\x03\x9d\xa0j\xa6\nX~\x1e_^\xbe8!\xd4\x17\x89D\xfa\x91\x90\x9bm\x85Hؙ\xd3\xd1\xebCV\x013\xb3H\xe2\xc6͆_\xae\xc6\xd1+\x0f\x00\xf1`/`\a\xe9\xc7w\xd8\xe4c\xa5;uC\xdf/\xec\xd0\x04\xec<\xdeM\xc8S\xf8}\xcb\xdek\x18\xabi\xce\v\x02\xa6\xc5^[\x8d\xbai\x14n\xd7\f\xf1#~\xa6H\xa2\xb1\f\xab\\\x84\xb6Kz\xabr\x98\x85\x87\x13\x063WS\xb4`4R\xe6\xa4\xd2r\\\xc4b`nJ\xd9S\x84L\xba\v\x88\x88a\xc0e\xd1梍\xa8\xcdi\xf1 \xa0\xb7\xd6x\x92q\xb1\xfd\x90O)\x85\xf2\u007f\xa4\x8bN\x97\xe7\xb1\x18\xc7f5y\x0ffyϰ\xee\xd1\x00\vVfz\x10\x86\x90$o\xdb\x1a\x16ۏ\xf7K\xaa\v&\xdc\xea\x1b\xe5\xa5\xfaȭ\xd1r\xf4\xa1\xf5H\xea\xceBZ\x0f+$\xe4f[\xa1\xb5\x9e[4\x92\xa0E\xc0\xcc,ƌ\x18\xa0b-\xcc\x1aǨ<\x00\xd8\x13\xa7\x80ݤ\x03D\x9d;ڼج\x1d\x9a\x80\xddވ\xbf\xff'\xf6\u07b4콩\x87\xef~_\x10\xb0\xc7\xd5\r7mYă\xceF\x1c\xc9\xfc\xfdv\x16z\x94Ͱ\xf8=\xd3\x14\xb7\x1a`\x98kJ\xb5\xfa\xab'Y\x9c\xf89\xc3ó\x19\xa26d\x89\xa4h\x18pY\x8cgyj\x8f\x8f\xaa\x81\xac\xed\x04,\x9ed\x9c\x80Iz\x98扶\r\x1e\xa7\xda\xdf4\xab\xc9{0\xcb[\xa3\x86\xb5Z]-z\x10\x04\xac\t52\x01\xe3\xfd\x92H^\xa6\xb6\xd2N\xa2\xea\xe4\xa2j\"\x1eI\xddY\b5\x0f\x0f\x0f\xb7P\x01\xe3r\xb3\xabФ\xba\xea\xa2\xde\"`f\x16\xd3\xc9\xe6\xdf#\xbe\x16f\x8dcT\x1e\x00\xec\x89S\xc0H\x996\x99E>\xffǿH%V\x9f\x18\xfa\xf8\xa7\xa7\xc4\x1dڳ\x90/\xe2ӧ\xf1\xb3\xd6dw6au\xe1\xd8k\x82\x80\xa9w\xc5&\x11\xa2\xc3\xc0\x06T\xdbo\x04\xffd\x98Ax\xf3\xb4\x1e\x02\xebYpMI\x96\xf4E\xac|t\xe5\xe8\x02\xc6FQ\x83\xd6 \xa9\x86\x01\x9f\xc5d\xfb\xe6\\\x94\xd9h\xf1 \xa0\xb7\xd6x\x92q\x02\xa6O\xa6\rg\xba\xf7\xf4\x04\xd7Y\xa2+\xf3\x1e\xcc\xf2\xaeUU\xa8\xa4@\xf0 \n\xd8Ğ\t&`\xbc_B\xba\xf55)R\xcd\xf0\xb0:\xfc\x13\x8f\xa4\ue31b\x03\xe3s\xb3\xa9Ј\xea\xde:\x89\xcfe\xa1́M\x0f\x88~\xb9\x1aG\xaf<\x00\xd8\x13\xaf\x80=\x87\xb7ߡ\x9f\u007f\xa0K'\x8ejkU\xf7\xe27\xc4\x1d\x9a\x80]\xc4O=\xa5\x06\xea\x16\xf6\xbe\xa0\x8a\xda\xedJA\xc0V\xb1\xf9\xab_\xa8\x913ǐ\xbb\x16\x9d$\x1c\xe6\xc5]\xe5\x19a\xb0\x85N\xac)u\xb0\xbeC]\x92\x1e\xaf}\x96\x80\xa9\x06\xe6\xa6\xc4&\xdcڭ\x91\x14\r\x03.\x8b\x11ڕ\x99\xeat\xb4Y\x9c\xf1\xe8\xad5\x9ed\x9c\x80\x95k\x1b\xb9\x05tZ\xbb\xdc\"`\xbc\a\xb3\xbc\xd5\x1e\x96\xc4S-x\xe0\xb2\xe0\xc2\xc3\xf3~\x89\x9cY\x9f\xadv8\xcd{\xb4\xe2\x91ԝq\x02\xc6\xe5fW\xa1I5Đu\x12\x9f\xcb\"\xe0`=\xea.4!\xd4\"\xaa\x80\t\xb9\x01\x80-\xf1\n\xd8e/~A\x19\x00^\xdcD\xc5\xe7\x86\x17\xbf\xc1ց\x15\u007f'\xee\xd0\xdfFQYTTqgV\xb2k\xeb\xf1\xaf\uf41b\a-\xeb\xc0\xf2\x14\x05;)i3%\xf7#G\xba\xb0\xd6\xc0\xbc\xb8\a\x10[h_\xcfft\n\v\t\xf9\x96\xfd\xf0\x8dd,\xdb\xe7\x05\xcc4\xe06\xa5\xcc)\xba\"\xc9\x1a\x0f\xcb0\xe0\xb2h@gخm\x16gd찮\x97Fk\x8d'\x19'`z7\xc6M\xa5c&\xcf\"`\xbc\a\xb3\xbc}lª\x13\xf5\t\x1e\xb8,8\x01\xe3\xfdN\x17ԓm\xbe\x19#\v\x86p$\rg\x9c\x80q\xb9\xd9V\xa8\xc0\xad\xe8cx\x95E\xc0\xb8,&\xd3˕!\xe1L\xa1G\xacET\x01\x13r\x03\x00[\xe2\x150r~=\xf6n\xaf\xc4x7\xbd\x93x\xbe\boܾ\t\x17\x9d\xb7\xec\xd0\x05\xec\r\xcc\x1e#\xb2&\xfb\xb8\b\x97\xfdċ\xf7\t\x02\xe6KM\xb9ύ\xf4\xb9\xfc\xe3Hx\x8cH\x8d\x0e5R\x9d\x12\x94i e\xff\xc9\xdejt\x82\xeeh\x90\x9a{|i\xb4\xf3\xf6\xb8\xbe\xe8B\xb0\xe5\f\xb8M\t\xe5w\x1d\xcfqZ\xef'\x9a\x06f\x16\r(\xfd@_O5\x1a\x14\r\b)5\x86\xb8#m\xa8E\x1d\x8c\xda'\xd3m\xa7\x87ح<6i׀6\xb7\x1d\xceG\xae\xa6!\xbe\xe8\xbc\a\xae\xbcUI\x81\xbe@R\x95\xe8\xc1\xccbҿ\xee\x1b\xe5\xeb7\xeb\xfc\x93\x9c\xdfH\xb0\xd65N.9w\x05#t%\xbeQo\xa3\xbc\x9c3a%\xbe\x91[\x8c\nq+\xf1C\x0e\xf7\xa1\xfa\x8c\xa4䎐\xba\x12\xbf%\x18\xbc*\x1c\x12r\xc6q\u007fG\xaf/9\xc8ׂ\xabq\xac\xca\x03\x80=q\v\x18\xb9\xf6Be\x91w\xfb)u%\xc4\xe5g+\x8a\xca\x0e^\xb6\xee\xd0\x05\xec\x869\xcd/$\xfb\xdb\xc12\xef\xf6\v\x1f\v\x02\x16\x18\xf5\xa59\xd6\xf6kߧ$\xe11\"\x16\x1d*\x94\xa6\xfcKo4\x0e\xac\xcbpj\x96\x91\x1d\x19\x8e\a\x87\x95\x8doS\xab\xa2\xda\x1a\x06\xfc\xa6\xf4x\xb53\xabJ&\x168[#\x8b\x13\x85\x87\xdc)\x99\x85\x83V\x03\xd2\xe1jW7n\xa5+Y\xa5Nŕ̰\x1dU\x1f\",\xa1?δ\xe4H.\u007f\x87G*\xe4\x8b\xce{\xe0\xcb{,O[\a\xc6y0\xb3h@\x88N5m\xa3\xcf3\x9a~\a\x14\xc3:\xb2C\xf9\xf7,}\x16R\x9dB\xe7\xcb\xcb9S\x9f\x85T\xfc\xb0Yy=\xb7\x18\x15\x1a垅\f\x97fd\xef\xe9HV\x8a^\xadM|\xf9\xf9,\b}\x16ґY\x1a\x12j\xc1\xd58V\xe5\x01\xc0\x1e;\x01[j.\xc5\xf1\x18\x91@`>\v\xbc\x13-Zq\xa2\x95\x17\x00\x96\x98\x95&`\xf5h\x9eapkjH\xfc\x98\x82\x10\x19SY\xf4g{\x16\x15\x100\x00\x98\x93\x15%`\xa1\xb1\xaeUҬ\x01\xde\"b\n\u0083\xdah\xc7:\x9f\xbf\xb2\x00\x01\x03\x809YQ\x02V\xae(\xca]l\xb2\xeal\xb1J\xb8We\x1e\xe3\xcf%\x87//\x00\x00QXQ\x02֔\xea\x9a\xe7\x00r^\xb0\xd9\xe21;\xab\x95C\xa2\x95\x17\x00\x96\x9c\x15%`\x00\x00\x00\xf3\x01\x04\f\x00\x80\x84\x05\x04\f\x00\x80\x84\x05\x04\f\x00\x80\x84\x05\x04\f\x00\x80\x84eq\x05L\u007f\x94hn\xeeF\\H\x00\x00~\x80\x80\x80\x01\x00\x90\xb0,\xae\x80]\xfe\xf5y;\x13\x02\x02\x06\x00\xc0\"\xb1\xb8\x02\x16\x1f `\x00\x00,\n\xf7\x8a\x80m\x9b\xcf3\xdd\x00\x00\xdc\x1b\xd8\t\xd8o\xf0\xa9\v\x95ޟ\\#\xe4Ƌ\x95E\x9b\xf6^P\u007f\xbev\xa4r\xfd\xa6}\xea+\xee\xb9\x1dt\x0e\xec\r}\x1e\xecY\xf6RC!\xd9\xe7{7\x15?u\xd1\"`\xe1r\xa7#\x9fưiA\xb9\xea\x8f\a\x84\x97\x1a\xc6C\x18\x05H-J겳[<z\x92\xb5\xc7\xc1\x93\xbb\xedL\xe7e\xbb@\x0e\xa1\x14\xfaJ\xdb>\a:\x14ݠ\x9f\x15 㡘\x0f\u007f\xaa\xef\x03;\x84\xd4\xf7\x81\xd90½\x0fLa,\x85\x9d:\xfa>0G\x94\fB\xbe\xb4L\xff`&\x1f\xab\x05\x00\x16\x05{\x01{ыq\xf1mr\xa1\x18{\xb7Vb\xfc\x1a\xfd\xf5\xbc\x17\x17o/\xc3,\xb6\a\xbf\x83\n\xd8?p\x11\v>t\xbb\x98\xbe\xd4PHv\n㊭EE\xbb\x05\x01\xcbu\xa2\\\x0fB\xe5\x84L\xa4hQ\xa1=\xc2K\r\xa3rV\x8c\xcbQ\xb5\xea[\xfa\xec3\xf7$8g`\xb1\x9d\xcdB\f\x1a\x91\xf6\xfaQ\x14;\x02\x85\x9e,\x1e\xdb\x05\xa2g1\xe1w\xf8\x94\x0f\x9f\xc3?\x11ݐ\xbe\x9158x\xcc#\x06\xc5\xe4\x10\xde\xc8\x1a\x03\xe38pode\f\xb1w\xe2\xb37\xb2\xce~\xfc| m\xcd\xf1\xce<4\x9f\x17\xb7\x01@|\xd8\v\x18\xae<\u007f\xe14\xb9Q\x8c\x8f\xdeV\xbaP\x9bh\x98\xa1\xef\x8a\xf1\xcb\xec\x9d\xf8\xde\xef\xc5\x1d\xec.\xe4N\x1aזF\u007f\xdcJĽ\x17\xf1\x03\xa7\xef\x90\uf7f2\xbc\x13?[iR\x03\x0e\x1a\x1b\xa2\x04ј\x0ed$\x8e\x97\x1a\xae\xf1\xf3\xdf\xc2jx\\\xfe\xed3\x9c\x81h\x1b\x85\x85\x18\xb4H\xda\v\xe0S\xf9(\x96\"z\xb2xl\x17\x88Q\xb2@\x89c\x8aL:J\x021M\xd9љr\v1\x9fx\x84\xc8\xdc\xd1\xe1\x8fð U֨D\x1c\x93\xe9\xa5\x11\xfaf\u007f\x100`\xf1\x89C\xc0\xd8ˡ\x8f\xe2\xbd\xec\xfb\xfb\xf8DŽ\xbc\xac\x86\xeb&\xbb\x15\xa9\x12v0\x01;\xad\xee=\x88OY\x92\x1d\xc4G\xe9\xf6\xcd2Q\xc0X\x839\x86\xb2\x95\xa1\x96\xaa\\\xbbP\xecV\xa8#\x06:\xabV\xdf\"\xc6\vX\u0530j1X\x88A$\xac\xb5\xd6p\xecw\"\xea\xc9\xe2\xb1] \\X5_\x179\xe1\xf3\xdb\b\x18iH\x9d\x89\xb1?\x0e\x01\x8b\x1e'\x8e2\x87\x80\x05R\xd9ر\x19\x04\fX|\xec\x05\xac\x92}>\xac\x05x\xbcMC\xd5nѾܸqG\xdc\xc1\x04\xecf\x11\xfe\xa7\xf2\xaf\x97\xfe\xcbウ\x11_d_\x8e\n\x02\xb6\x96}N%)\xd7w\xc4I/\xff\x19\x97y\xa9ע\x94\xf6\xba\x1c\x87O\x8d\xa7q\xa2 -\xe7\xf1[\x84\xf4jSJ\xf9\x9a\xd5X\xf2.\xf6)\xed\xd1l9\x03n\xb3\x16%\xb7ָ3Jņ$:ӳ $\xe8s\xa7\xb8J\xb2g\xe7fb\xb6V\xfbd\x9a\xedh2B\xf5\xe1\xaaldži2\xb59Kr\x97\x8e\x12K5\r\x0fby\xdb\xf2\xb5w\xe2\x9b\x1e\xf8,\x02\xfe\xb6rR\xf2\n\x150\xd3o(\x99Fft#\xe4\x8c\xe8\x02֘\x1c\xe1\xca\xcb\x17G\x100=7\xdb\n\x11\"We9˭aոC\xa2Ņ\x9ch\x8ep~\xb9\x1aG\xaf<\x00ă\xbd\x80\xb1\xee\xd4M\x8c\xb7lg\x14\xe1\vd=\xfe\x9b\xbe_ܡ.d\xddGǐ\xefӄ\xc2\xde\xef1VC{\x9c\x16\x04\xacN\xddȦ\xf1淡\x1d4\"W\x9e\xb1;ԙ\x8c\\\r\xcd\xe9,vaMҎ\xbeVW\xfe\f\xb9\x15d\xb1t\x82\xba\x12\xd5H\xaa\xc0I(\xb7\xb37S\xb1\xe5\f\xb8M\xea,\xfb\xf0ϳ\xc5i \xc1\x99\x91\x852\x8e}\xb4{\xa0݅\xa6g\xe5fb\xb4\xd68\x92i\xb6\x91\x93\x9d\xd99\xe9\xee\xba*t\x95\xf4\xa1\x9a\xc1\x93\xa5I\xc3b5M\x0fBy\xab\xa5\xfa\xbez\xa9J\xf0\xc0g\x11\xf0\x8f\xa7M\xae\x92\xa9\x80\x99~g\x86\x1a\x92\x86H\a:A\xd5L\x15\xb0\xfc<\xbe\xbc|qB\xa8/\x12\x89\xf4#!7\xdb\n\x91\xb03\xa7\xa3ׇ\xac\x02ff\x91č\x9b\r\xbf\\\x8d\xa3W\x1e\x00\xe2\xc1^\xc0XT\xa2\xef\xb0\xc9\xc7Jwꆾ_ء\t\xd8y\xbc\x9b\x90\xa7\xf0\xfb\x96\xbd\xd70VӜ\x17\x04L\x8b\xa7\xb6\x1au\x132\x84\\3ď\xf8\x99\"ɩ\x88S\x95\x8b\xd0vIoU\x0e\xb3Ђ\xc2`\xe6jJ\xadf\x9b9\xa9\xb4\x1c\x17\xb1\x18p\x91\xb9\xb3\xa7\b\x99t\x17\x10\x11Àˢ\xcdE\x1bQ\x9b\xd3\xe2A@o\xad\xf1$\xe3\xe2B\"\x9fR\n\xe5\xffH\x17\x9d.\xcfc\xf1\xb1\xcdj\xf2\x1e\xcc\xf2\x9eaݣ\x01\xd4/x\x10\x86\x90$o\xdb\x1a\x16\x17\x92\xf7K\xaa\v&\xdc,\xfe#\x91\xea#\xb7F\xcbч\xd6#\xa9;\vi=\xac\x90\x90\x9bm\x85\xd6zn\xd1(\x94\x16\x013\xb3\x18\xd3\"~R\xf8Z\x985\x8eQy\x00\xb0'N\x01\xbbI\a\x88:w̠i\xe2\x0eM\xc0no\xc4\xdf\xff\x13{oZ\xf6*_\xd8\xedI\xa5s\xc6\v\xd8\xe3ꆛ\xb6,\xe2Ag#\x8ed\xfe~;\v[\xcbfX\xfc\x9ei\x8a[\rN\xcd5\xa5Z\xfd\xb5\xa5R\r1fc\xa2\v\x18\x9b!jC\x93D\xc00\xe0\xb2\x18\xcf\xf2\xd4\x1e\x1f%\xd3\x16\x0f\x02zk\x8d'\x19'`\x92\x1e\xe2{\xa2m\x83ǩ\xf67\xcdj\xf2\x1e\xcc\xf2֨!\xd1VW\x8b\x1e\x04\x01kB\x8dL\xc0x\xbf$\x92\x97\xa9\xad\xb4\x93\xa8:\xb9\xa8\x9a\x88GRw\x16B\xcd\xc3\xc3\xc3-T\xc0\xb8\xdc\xec*4\xa9\xae\xba\xa8\xb7\b\x98\x99\xc5t\xb2\xf9\xf7\x88\xaf\x85Y\xe3\x18\x95\a\x00{\xe2\x140R\xa6Mf\x91\xcf\xff\xf1/R\x89\xd5'\x86>\xfe\xe9)q\x87\xf6,\xe4\x8b\xf8\xf4i\xfc\xac5ٝMX]8\xf6\x9a `\xea]\xb1I\x84\xe80\xb0\x01\xd5\xf6\x1b\x81c\x19f\xd4\xe6<\xad\x87\xc0z\x16\\S\x92%}\x11+\x1f\x99;\xba\x80\xb1Q\xd4 \xb2\xac\x8a0\f\xf8,&\xdb7\xe7\xa2\xccF\x8b\a\x01\xbd\xb5Ɠ\x8c\x130}2m8ӽ\xa7'\xb8\xce\x12\x99\x9b\xf7`\x96w\xad\xaaB%\x05\x82\aQ\xc0&\xf6L0\x01\xe3\xfd\x12ҭ\xafI\x91j\x86\x87\xd5\xe1\x9fx$ug\xdc\x1c\x18\x9f\x9bM\x85FT\xf7\xd6I|.\vm\x0elz@\xf4\x1b52\xb7\x90\x1b\x00\xd8\x12\xaf\x80=\x87\xb7ߡ\x9f\u007f\xa0K'\x8ejkU\xf7\xe27\xc4\x1d\x9a\x80]\xc4O=\x85/\xccJ\xf6\x82*j\xb7+\x05\x01[\xc5\xe6\xaf~\xa1F]\x1dC\xeeZt\x92p\x98\x17w\x95g\x84\xc1\x16:\xb1\xa6\xd4\xc1\xfa\x0euI\x97f\xd9\n\x06\xe6\xa6\xc4&\xdcڑe\xa5\x93a\xc0e1B\xbb2S\x9d\x8e6\x8b3\x1e\xbd\xb5Ɠ\x8c\x13\xb0rm#\xb7\x80Nk\x97[\x04\x8c\xf7`\x96\xb7\xdaÒx\xaa\x05\x0f\\\x16\x01u\x85\x03\x150\xde/\x913\xeb\xb3\xd5\x0e\xa7y\x8fV<\x92\xba3N\xc0\xb8\xdc\xec*4\x89\xd8\x1e\xeb$>\x97E\xc0\xc1z\xd4]hB\xa8ET\x01\x13r\x03\x00[\xe2\x15\xb0\xcb^\xfc\x822\x00\xbc\xb8\x89\x8a\xcf\r/~\x83\xad\x03+\xfeNܡ\xbf\x8d\xa2\xb2\xa8\xa8\xe2άd\xd7\xd6\xe3_\xdf!7\x0fZց\xe5)\nvR\xd2fJ\xeeG\x8eta\xad\x81yq\x0f \xb6о\x9e\xcd\xe8\x14\x16\x12\xf2-\xfb\xe1\x1b\xc9X\xb6\xcf\v\x98i\xc0mJ\x99StE\x925\x96\x9aa\xc0eрΰ]\xdb,\xce\xc8\xd8a]/\x8d\xd6\x1aO2N\xc0\xf4n\x8c\x9bJ\xc7L\x9eE\xc0x\x0ffy\xfb\u0604U'\xea\x13<pYp\x02\xc6\xfb\x9d.\xa8'\xdb|3F\x16\f\xe1H\x1a\xce8\x01\xe3r\xb3\xadP\x81[\xd1\xc7\xf0*\x8b\x80qYL\xa6\x97+C\u0099B\x8fX\x8b\xa8\x02&\xe4\x06\x00\xb6\xc4+`\xe4\xfcz\xec\xdd^\x89\xf1nz'\xf1|\x11\u07b8}\x13.:o١\v\xd8\x1b\x98=FdM\xf6q\x11.\xfb\x89\x17\xef\x13\x04̗\x9ar\x9f\x1b\xe9s\xf9Ǒ\xf0\x18\x91\x1aYl\xa4:%(\xd3 \xdc\xfe\x93\xbd\xd5\xe8\x04\xdd\xd1 5\xf7\xf8\xd2h\xe7\xedq}х`\xcb\x19p\x9b\x12\xca\xef:\x9e\xe3\xb4\xdeO4\r\xcc,\x1aP\xfa\x81\xbe\x9ej4(\x1a\x10Rj\fqG\xdaP\x8b:\x18\xb5O\xa6\xdbN\x0f\xb1[ylҮ\x01mn;\x9c\x8f\\MC|\xd1y\x0f\\y\xab\x92\x02}\x81\xa4*у\x99Ť\u007f\xdd7\xca\xd7o\xd6\xf9'9\xbf\x91`\xadk\x9c\\r\xee\nF\xe8J|\xa3\xdeFy9g\xc2J|#\xb7\x18\x15\xe2V\xe2\x87\x1c\xeeC\xf5\x19I\xc9\x1d!u%~K0xU8$\xe4\x8c\xe3\xfe\x8e^_r\x90\xaf\x05W\xe3X\x95\a\x00{\xe2\x160r\xed\x85\xca\"\xef\xf6S\xeaJ\x88\xcb\xcfV\x14\x95\x1d\xbclݡ\v\xd8\rs\x9a_H\xf6\xb7\x83e\xde\xed\x17>\x16\x04,0\xeaKs\xac\xed\u05feOI\xc2cD,\xb2X(M\xf9\x97\xdeh\x1cX\x97\xe1\xd4,#;2\x1c\x0f\x0e+\x1bߦVE\xb55\f\xf8M\xe9\xf1jgV\x95L,p\xb6F\x16'\n\x0f\xb9S2\v\a\xad\x06\xa4\xc3ծn\xdcJW\xb2J\x9d\x8a+\x99a;\xaa>DXB\u007f\x9ciɑ\\\xfe\x0e\x8fT\xc8\x17\x9d\xf7\xc0\x97\xf7X\x9e\xb6\x0e\x8c\xf3`fр\x10\x9dj\xdaF\x9fg4\xfd\x0e(\x86ud\x87\xf2\xefY\xfa,\xa4:\x85Η\x97s\xa6>\v\xa9\xf8a\xb3\xf2zn1*4\xca=\v\x19.\xcd\xc8\xdeӑ\xac\x14\xbdZ\x9b\xf8\xf2\xf3Y\x10\xfa,\xa4#\xb34$Ԃ\xabq\xac\xca\x03\x80=v\x02\xb6\xd4\\\x8a\xe31\"\x81\xc0|\x16x'Z\xa4\xebD+/\x00,1+M\xc0\xea\xd1<C\xdb\xd6Ԑ\xf81\x05!2\xa6\xb2\xe8\xcf\xf6,* `\x000'+J\xc0Bc]\xab\xa4Y\x03\xbcE\xc4\x14\x84\a\xb5юu>\u007fe\x01\x02\x06\x00s\xb2\xa2\x04\xac\\Q\x94\xbb\xd8d\xd5\xd9b\x95p\xaf\xca<ƟK\x0e_^\x00\x00\xa2\xb0\xa2\x04\xac)\xd55\xcf\x01\xe4\xbc`\xb3\xc5cvV+\x87D+/\x00,9+J\xc0\x00\x00\x00\xe6\x03\b\x18\x00\x00\t\v\b\x18\x00\x00\t\v\b\x18\x00\x00\t\v\b\x18\x00\x00\t\xcb\xe2\n\x98\xfe(\xd1\xdc܍\xb8\x90\x00\x00\xfc\x00\x01\x01\x03\x00 aY\\\x01\xbb\xfc\xeb\xf3v&\x04\x04\f\x00\x80Ebq\x05,>@\xc0\x00\x00X\x14\xee\x15\x01\xdb6\x9fg\xba\x01\x00\xb87\xb0\x13\xb0\xdf\xe0S\x17*\xbd?\xb9Fȍ\x17+\x8b6\xed\xbd\xa0\xfe|\xedH\xe5\xfaM\xfb\xd4W\xdcs;\xe8\x1c\xd8\x1b\xfa<س쥆B\xb2\xcf\xf7n*~\xea\xa2E\xc0\xc2\xe5NG>\x8daӂr\xd5\x1f\x0f\b/5\x8c\x870\n\x90Z\x94\xd4eg\xb7x\xf4$k\x8f\x83'wۙ\xce\xcbv\x81\x1cB)\xf4\x95\xb6}\x0et(\xbaA?+@\xc6C1\x1f\xfeT\xdf\av\b\xa9\xef\x03\xb3a\x84{\x1f\x98\xc2X\n;u\xf4}`\x8e(\x19\x84|i\x99\xfe\xc1L>V\v\x00,\n\xf6\x02\xf6\xa2\x17\xe3\xe2\xdb\xe4B1\xf6n\xad\xc4\xf85\xfa\xeby/.\xde^\x86Yl\x0f~\a\x15\xb0\u007f\xe0\"\x16|\xe8v1}\xa9\xa1\x90\xec\x14\xc6\x15[\x8b\x8av\v\x02\x96\xebD\xb9\x1e\x84\xca\t\x99HѢB{\x84\x97\x1aF\xe5\xac\x18\x97\xa3jշ\xf4\xd9g\xeeIp\xce\xc0b;\x9b\x85\x184\"\xed\xf5\xa3(v\x04\n=Y<\xb6\vD\xcfb\xc2\xef\xf0)\x1f>\x88\x9f\x8f(\x00\x00\ttIDAT\x87\u007f\"\xba!}#kp\xf0\x98G\f\x8a\xc9!\xbc\x915\x06\xc6q\xe0\xde\xc8\xca\x18b\xef\xc4god\x9d\xfd\xf8\xf9@ښ\xe3\x9dyh>/n\x03\x80\xf8\xb0\x170\\y\xfe\xc2ir\xa3\x18\x1f\xbd\xadt\xa16\xd10C\xdf\x15\xe3\x97\xd9;\xf1\xbdߋ;\xd8]ȝ4\xae-\x8d\xfe\xb8\x95\x88{/\xe2\aN\xdf!\xdf?ey'~\xb6Ҥ\x06\x1c46D\t\xa21\x1d\xc8H\x1c/5\\\xe3翅\xd5\xf0\xb8\xfc\xdbg8\x03\xd16\n\v1h\x91\xb4\x17\xc0\xa7\xf2Q,E\xf4d\xf1\xd8.\x10\xa3d\x81\x12\xc7\x14\x99t\x94\x04b\x9a\xb2\xa33\xe5\x16b>\xf1\b\x91\xb9\xa3\xc3\x1f\x87aA\xaa\xacQ\x898&\xd3K#\xf4\xcd\xfe `\xc0\xe2\x13\x87\x80\xb1\x97C\x1f\xc5{\xd9\xf7\xf7\xf1\x8f\tyY\r\xd7Mv+R%\xec`\x02vZ\xdd{\x10\x9f\xb2$;\x88\x8f\xd2\xed\x9be\xa2\x80\xb1\x06s\fe+C-U\xb9v\xa1حPG\ftV\xad\xbeE\x8c\x17\xb0\xa8a\xd5b\xb0\x10\x83HXk\xad\xe1\xd8\xefDԓ\xc5c\xbb@\xb8\xb0j\xbe.r\xc2\xe7\xb7\x110Ґ:\x13c\u007f\x1c\x02\x16=N\x1ce\x0e\x01\v\xa4\xb2\xb1c3\b\x18\xb0\xf8\xd8\vX%\xfb|X\v\xf0x\x9b\x86\xaaݢ}\xb9q㎸\x83\t\xd8\xcd\"\xfcO\xe5_/\xfd\x97\xdf{g#\xbeȾ\x1c\x15\x04l-\xfb\x9cJR\xae\uf213^\xfe3.\xf3R\xafE)\xedu9\x0e\x9f\x1aO\xe3DAZ\xce\xe3\xb7\b\xe9զ\x94\xf25\xab\xb1\xe4]\xecSڣ\xd9r\x06\xdcf-Jn\xadqg\x94\x8a\rIt\xa6gAH\xd0\xe7Nq\x95d\xcf\xce\xcd\xc4l\xad\xf6\xc94\xdb\xd1d\x84\xea\xc3Uَ\r\xd3djs\x96\xe4.\x1d%\x96j\x1a\x1e\xc4\xf2\xb6\xe5k\xef\xc47=\xf0Y\x04\xfcm\xe5\xa4\xe4\x15*`\xa6\xdfP2\x8d\xcc\xe8F\xc8\x19\xd1\x05\xac19\u0095\x97/\x8e `zn\xb6\x15\"D\xae\xcar\x96[êq\x87D\x8b\v9\xd1\x1c\xe1\xfcr5\x8e^y\x00\x88\a{\x01cݩ\x9b\x18o\xd9\xce(\xc2\x17\xc8z\xfc7}\xbf\xb8C]Ⱥ\x8f\x8e!ߧ\t\x85\xbd\xdfc\xac\x86\xf68-\bX\x9d\xba\x91M\xe3\xcdoC;hD\xae<cw\xa83\x19\xb9\x1a\x9a\xd3Y\xec\u009a\xa4\x1d}\xad\xae\xfc\x19r+\xc8b\xe9\x04u%\xaa\x91T\x81\x93Pngo\xa6b\xcb\x19p\x9b\xd4Y\xf6\xe1\x9fg\x8b\xd3@\x823#\ve\x1c\xfbh\xf7@\xbb\vM\xcf\xca\xcd\xc4h\xadq$\xd3l#';\xb3s\xd2\xdduU\xe8*\xe9C5\x83'K\x93\x86\xc5j\x9a\x1e\x84\xf2VK\xf5}\xf5R\x95\xe0\x81\xcf\"\xe0\x1fO\x9b\\%S\x013\xfd\xce\f5$\r\x91\x0et\x82\xaa\x99*`\xf9y|y\xf9\xe2\x84P_$\x12\xe9GBn\xb6\x15\"agNG\xaf\x0fY\x05\xcc\xcc\"\x89\x1b7\x1b~\xb9\x1aG\xaf<\x00ă\xbd\x80\xb1\xa8D\xdfa\x93\x8f\x95\xee\xd4\r}\xbf\xb0C\x13\xb0\xf3x7!O\xe1\xf7-{\xafa\xac\xa69/\b\x98\x16Om5\xea&d\b\xb9f\x88\x1f\xf13E\x92S\x11\xa7*\x17\xa1\xed\x92ު\x1cf\xa1\x05\x85\xc1\xccՔZ\xcd6sRi9.b1\xe0\"sgO\x112\xe9. \"\x86\x01\x97E\x9b\x8b6\xa26\xa7Ń\x80\xdeZ\xe3I\xc6ŅD>\xa5\x14\xca\xff\x91.:]\x9e\xc7\xe2c\x9b\xd5\xe4=\x98\xe5=úG\x03\xa8_\xf0 \f!I\u07b65,.$\xef\x97T\x17L\xb8Y\xfcG\"\xd5Gn\x8d\x96\xa3\x0f\xadGRw\x16\xd2zX!!7\xdb\n\xad\xf5ܢQ(-\x02ff1\xa6E\xfc\xa4\xf0\xb50k\x1c\xa3\xf2\x00`O\x9c\x02v\x93\x0e\x10u\xee\x98A\xd3\xc4\x1d\x9a\x80\xddވ\xbf\xff'\xf6\u07b4\xecU\xbe\xb0ۓJ\xe7\x8c\x17\xb0\xc7\xd5\r7mYă\xceF\x1c\xc9\xfc\xfdv\x16\xb6\x96Ͱ\xf8=\xd3\x14\xb7\x1a\x9c\x9akJ\xb5\xfakK\xa5\x1ab\xcc\xc6D\x1706CԆ&\x89\x80a\xc0e1\x9e\xe5\xa9=>J\xa6-\x1e\x04\xf4\xd6\x1aO2N\xc0$=\xc4\xf7D\xdb\x06\x8fS\xedo\x9a\xd5\xe4=\x98\xe5\xadQC\xa2\xad\xae\x16=\b\x02ք\x1a\x99\x80\xf1~I$/S[i'QurQ5\x11\x8f\xa4\xee,\x84\x9a\x87\x87\x87[\xa8\x80q\xb9\xd9UhR]uQo\x1103\x8b\xe9d\xf3\xef\x11_\v\xb3\xc61*\x0f\x00\xf6\xc4)`\xa4L\x9b\xcc\"\x9f\xff\xe3_\xa4\x12\xabO\f}\xfc\xd3S\xe2\x0e\xedY\xc8\x17\xf1\xe9\xd3\xf8Yk\xb2;\x9b\xb0\xbap\xec5A\xc0Իb\x93\b\xd1a`\x03\xaa\xed7\x02\xc72̨\xcdyZ\x0f\x81\xf5,\xb8\xa6$K\xfa\"V>2wt\x01c\xa3\xa8AdY\x15a\x18\xf0YL\xb6o\xceE\x99\x8d\x16\x0f\x02zk\x8d'\x19'`\xfad\xdap\xa6{OOp\x9d%27\xef\xc1,\xefZU\x85J\n\x04\x0f\xa2\x80M\xec\x99`\x02\xc6\xfb%\xa4[_\x93\"\xd5\f\x0f\xab\xc3?\xf1H\xeaθ90>7\x9b\n\x8d\xa8\ueb53\xf8\\\x16\xda\x1c\xd8\xf4\x80\xe87jdn!7\x00\xb0%^\x01{\x0eo\xbfC?\xff@\x97N\x1c\xd5֪\xee\xc5o\x88;4\x01\xbb\x88\x9fz\n_\x98\x95\xec\x05U\xd4nW\n\x02\xb6\x8a\xcd_\xfdB\x8d\xba:\x86ܵ\xe8$\xe10/\xee*\xcf\b\x83-tbM\xa9\x83\xf5\x1d\xea\x92.Ͳ\x15\f\xccM\x89M\xb8\xb5#\xcbJ'À\xcbb\x84ve\xa6:\x1dm\x16g<zk\x8d'\x19'`\xe5\xdaFn\x01\x9d\xd6.\xb7\b\x18\xef\xc1,o\xb5\x87%\xf1T\v\x1e\xb8,\x02\xea\n\a*`\xbc_\"g\xd6g\xab\x1dN\xf3\x1e\xadx$ug\x9c\x80q\xb9\xd9Uh\x12\xb1=\xd6I|.\x8b\x80\x83\xf5\xa8\xbbЄP\x8b\xa8\x02&\xe4\x06\x00\xb6\xc4+`\x97\xbd\xf8\x05e\x00xq\x13\x15\x9f\x1b^\xfc\x06[\aV\xfc\x9d\xb8C\u007f\x1bEeQQŝYɮ\xadǿ\xbeCn\x1e\xb4\xac\x03\xcbS\x14줤͔\u070f\x1c\xe9\xc2Z\x03\xf3\xe2\x1e@l\xa1}=\x9b\xd1),$\xe4[\xf6\xc37\x92\xb1l\x9f\x170Ӏ۔2\xa7\xe8\x8a$k,5Àˢ\x01\x9da\xbb\xb6Y\x9c\x91\xb1ú^\x1a\xad5\x9ed\x9c\x80\xe9\xdd\x187\x95\x8e\x99<\x8b\x80\xf1\x1e\xcc\xf2\xf6\xb1\t\xabN\xd4'x\xe0\xb2\xe0\x04\x8c\xf7;]PO\xb6\xf9f\x8c,\x18\u00914\x9cq\x02\xc6\xe5f[\xa1\x02\xb7\xa2\x8f\xe1U\x16\x01㲘L/W\x86\x843\x85\x1e\xb1\x16Q\x05L\xc8\r\x00l\x89W\xc0\xc8\xf9\xf5ػ\xbd\x12\xe3\xdd\xf4N\xe2\xf9\"\xbcq\xfb&\\t\u07b2C\x17\xb070{\x8cȚ\xec\xe3\"\\\xf6\x13/\xde'\b\x98/5\xe5>7\xd2\xe7\xf2\x8f#\xe11\"5\xb2\xd8HuJP\xa6A\xb8\xfd'{\xab\xd1\t\xba\xa3Aj\xee\xf1\xa5\xd1\xce\xdb\xe3\xfa\xa2\v\xc1\x963\xe06%\x94\xdfu<\xc7i\xbd\x9fh\x1a\x98Y4\xa0\xf4\x03}=\xd5hP4 \xa4\xd4\x18⎴\xa1\x16u0j\x9fL\xb7\x9d\x1eb\xb7\xf2ؤ]\x03\xda\xdcv8\x1f\xb9\x9a\x86\xf8\xa2\xf3\x1e\xb8\xf2V%\x05\xfa\x02IU\xa2\a3\x8bI\xff\xbao\x94\xaf߬\xf3Or~#\xc1Z\xd78\xb9\xe4\xdc\x15\x8cЕ\xf8F\xbd\x8d\xf2r΄\x95\xf8Fn1*ĭ\xc4\x0f9܇\xea3\x92\x92;B\xeaJ\xfc\x96`\xf0\xaapH\xc8\x19\xc7\xfd\x1d\xbd\xbe\xe4 _\v\xaeƱ*\x0f\x00\xf6\xc4-`\xe4\xda\v\x95E\xde\xed\xa7ԕ\x10\x97\x9f\xad(*;xٺC\x17\xb0\x1b\xe64\xbf\x90\xeco\a˼\xdb/|,\bX`ԗ\xe6Xۯ}\x9f\x92\x84LjXd\xb1P\x9a\xf2/\xbd\xd18\xb0.éYFvd8\x1e\x1cV6\xbeM\xad\x8ajk\x18\xf0\x9b\xd2\xe3\xd5ά*\x99X\xe0l\x8d,N\x14\x1er\xa7d\x16\x0eZ\rH\x87\xab]ݸ\x95\xaed\x95:\x15W2\xc3vT}\x88\xb0\x84\xfe8Ӓ#\xb9\xfc\x1d\x1e\xa9\x90/:\xef\x81/\xef\xb1<m\x1d\x18\xe7\xc1̢\x01!:մ\x8d>\xcfh\xfa\x1dP\f\xeb\xc8\x0e\xe5߳\xf4YHu\n\x9d//\xe7L}\x16R\xf1\xc3f\xe5\xf5\xdcbTh\x94{\x162\\\x9a\x91\xbd\xa7#Y)z\xb56\xf1\xe5\xe7\xb3 \xf4YHGfiH\xa8\x05W\xe3X\x95\a\x00{\xec\x04l\xa9\xb9\x14\xc7cD\x02\x81\xf9,\xf0N\xb4H\u05c9V^\x00XbV\x9a\x80գy\x86\xb6\xad\xa9!\xf1c\nBdLeџ\xedYT@\xc0\x00`NV\x94\x80\x85ƺVI\xb3\x06x\x8b\x88)\b\x0fj\xa3\x1d\xeb|\xfe\xca\x02\x04\f\x00\xe6dE\tX\xb9\xa2(w\xb1ɪ\xb3\xc5*\xe1^\x95y\x8c?\x97\x1c\xbe\xbc\x00\x00DaE\tXS\xaak\x9e\x03\xc8y\xc1f\x8b\xc7\xec\xacV\x0e\x89V^\x00XrV\x94\x80\x01\x00\x00\xcc\a\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x96\xff\x0f}\xc6-\xc8\xe3>\xf6\xcf\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/chan2a.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x04\x89\x00\x00\x01\x95\b\x03\x00\x00\x00M@Q-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\n\x03\x01\x04\x06\x02\a\n\x06\x0e\x10\r\r\x12\x14\x0e\x12\x1d\x11\x13\x10\x16\x18\x15\x1b\x1a\x13\x13\x1e7\x1f\x1f\x18!# #$\"%$\x1d%%\x1e$%#%'%'(&+)\x1e()'*+)/,!+-*,-+-/,02/63(241564796<9.9;8<=;=>FA?3>@=#CxDA5AB@DFCFHEKH<MH7IKHKLJNOMUP?PROSTRUVTWXV]XG<Z\xa5_ZIY[Y,`\xae7]\xad[]Z\\^[9a\xab;b\xac<c\xad_a^faO]ao>e\xafac`hcQbdaAg\xb2efdCi\xb3ghfMj\xafEm\xb1qjRikhIp\xb4lmkLr\xb7npm{s\\rtqWv\xb6tvsuwt\\z\xbaxzw]~\xb8e|\xb8\x84|dX\x80\xbf{}za\u007f\xbf|~{~\x80}b\x82\xbc\u007f\x81~d\x85\xbf\x82\x83\x80\x83\x85\x82m\x87\xbdh\x88Ð\x86hj\x8ać\x88\x86r\x8c\xc1\x89\x8b\x88t\x8eė\x8do\x8c\x8e\x8bz\x8f\xc0\x8e\x90\x8dx\x92Ȑ\x92\x8f~\x93\xc3x\x95Ē\x93\x90\x81\x95\xc6{\x98Ȕ\x96\x93\xa0\x96w\x96\x98\x95\x82\x9aė\x99\x96\x83\x9cņ\x9b̀\x9d̚\x9b\x98\xa5\x9b|\x87\x9fɃ\xa0Ϝ\x9e\x9b\x89\xa1̞\xa0\x9d\xaa\xa0\x81\xa0\xa2\x9f\xa1\xa3\xa0\xa2\xa4\xa1\x91\xa5ʮ\xa4\x85\x8f\xa7Ѥ\xa6\xa3\x94\xa7̥\xa7\xa4\xb4\xa7\x83\x92\xaaԧ\xa9\xa6\x97\xabЩ\xab\xa8\x9d\xad̫\xad\xaa\xa5\xad\xc1\x9f\xaeλ\xae\x89\xad\xaf\xac\x9e\xb1ע\xb1ѯ\xb1\xae\xa5\xb4Ԣ\xb5۳\xb5\xb2ö\x91\xb5\xb7\xb4\xac\xb7ҩ\xb8ط\xb9\xb6\xb9\xbb\xb8\xad\xbcܱ\xbc\u05fb\xbd\xba\xb3\xbeٽ\xbf\xbc\xb7\xbfԱ\xc0\xe1\xbf\xc1\xbe\xb6\xc1ܹ\xc1\xd6\xce\xc1\x9b\xc1ÿ\xbb\xc3\xd8\xc2\xc4\xc1\xbd\xc4ں\xc5\xe0\xc4\xc6\xc3\xc6\xc8\xc5\xc0\xc8ݽ\xc9\xe4\xd8ɞ\xc6\xca\xda\xc0\xcb\xe6\xca\xcc\xc9\xc3\xceܿ\xcf\xe2\xc8\xcd\xdc\xcd\xcf\xcc\xc8\xd0\xe6\xcc\xd0\xe0\xcf\xd1\xce\xc6\xd2\xe0\xdbҥ\xe1ѥ\xd1\xd3\xd0\xd2\xd3\xdd\xd3\xd5\xd2\xcd\xd5\xeb\xce\xd7\xdf\xe6\u05eb\xd6\xd8\xd4\xd1\xda\xe2\xd8\xda\xd6\xd8\xd9\xe3\xd6\xda\xea\xd3\xdc\xe4\xda\xdc\xd9\xd8\xdd\xe0\xd2\xde\xec\xdc\xde\xdb\xdc\xdd\xe7\xe0\xde\xe2\xdb\xe0\xe2\xde\xe0\xdd\xf0\xe0\xb3\xd5\xe2\xf0\xe0\xe2\xdf\xde\xe3\xe5\xde\xe2\xf2\xe2\xe4\xe1\xe1\xe6\xe9\xe4\xe6\xe3\xde\xe7\xef\xe8\xe5\xea\xe5\xe7\xe4\xe4\xe9\xec\xe7\xe9\xe6\xe8\xe9\xf3\xe2\xeb\xf3\xe9\xeb\xe8\xec\xee\xea\xe6\xef\xf7\xe8\xf1\xf9\xef\xf1\xee\xf0\xf0\xfb\xf2\xf4\xf1\xf1\xf6\xf9\xf4\xf6\xf3\xf7\xf9\xf6\xf5\xfa\xfd\xf9\xfb\xf8\xfa\xfc\xf9\xfd\xfb\xff\xf9\xfe\xff\xfc\xfe\xfb\xfe\xff\xfc\xfa<^\xc5\x00\x00 \x00IDATx^\xed\xbd\x0fX\x15\u05fd\xef}^\xdb\xf7\xcd\xed\xdb\xc5y`\x1f\xe9\x16\nD\xde\xcb{\xc0s\x94\x83xߛ\x8cA\xbc\xafy\xfd\xcbE\xe5`Qo\x8f1\xb4\xc46\x86T\xebc8\xf14\x98\xee\xa6H\x11o\x12RJ\xbc\x1e\"\t\xdd\x16\"\xd1Rk$\xec<MHKbO\tI(m\xec\xb17x5h\xaa\xd3\xd4\x1eBD=>\xf3\xbc\xb3\xe6\xefZ\xb3g\xefa#\xcc\xf0\xe7\xfbɓ\xbdמ\xf9\xad5k\x96{\xbe\xac\xb5f\xf6\xfa\xfe\x854vD\x00\x00\x18\x17\xfe\xc2In\xa2\xe0T6\x00\x00\x8c\x0e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11и\xec\x14\x00\xc0\xc4\x01%\x02\x94\xbe\xa2T\xb2\xdc)\b\x80\tc\xda+Q}N\x9fSH\x8c\xf4\xe7\xd4;\x85LB\x94v\x88\\\xf5\xac\xac@\xd3\xe9\b\xfb\x00\x98x\\W\xa2\xe6\x10}\xbdT]\xa9R\xa3n\xed\f4D\xcb$\xfe\xcfG\xd7\xe4o\xbb\x125Ğ\x1dd\xbbSH\xcc\xec\x88\xdb\xe1\x14\xe2D\xe7b\u007f\xda\xea\xe6\xb4>q\x1d!\xc4ߥonJ\x89\xde\f\f\xf5Y\xb3\xe7\xd5.\x18u\xb8\xd6\x0e\x91\xaa~\x8a4\xdan\a\xc0%\xdcV\xa2\xbe\xca6\xfav\xbe\xb2\xbdW\xe6X\xe5)e\xeb\x99@Ku\xb4\\\xe2W\v\x0e\xef\xce\xff j\x88-\x15qUN!c\xa0!\xbe\xc2)Ġ\xb9\xddfc\xa3?;\xb0\u007f>!!\xb1'\x18\xdcCZ\xf5\xed\r\xfe\xa7l\xa2M\xcc\xc2*Ha\xfd\x16BF[\x0f\xa3\x1d\"T\xbd\x8d\x04\xed6\x03\xe0\x16.+Qo\xad\xaaDb\xe7\x80\xfc2PݢnnhꉪD\x1f\b\x87\xc4+\x17\xa2E\xd8\xd3\xed\xbb?z@\u007fn\u007f\xf4\x00{\xca|=N!:\xd9+÷\xf5'\xdd;(\x9f}\x06Q\xfa\x87m\xa6\x129a\x14\xd6E\xca\xe4\xd7M\xa3U\"\xa6\x1d\xec\xab\x1eC\x1d\x00\x98\b\xdcU\xa2\xe6\xca\xe6@\x9b\xf9\xf1\xe0S\x97\x94\xf7Ϊ\x81ިJ\xf4\xaep4\xda\xee\x88\x14\xa5\rD\x0f\xe8$\x9d\xd1\x03\xec\x19H+r\n\xd1Y`\xa3D\xf7'*sW\x15D\x19\x96Š\x02Fa\x85)\xb2\x94\x89!\xb2'Z\xb4\t\xd3\x0e\xf6U\x8f\xa1\x0e\x00L\x04\xee*\xd1\xf9\x01\xb1\xba\xcd\xf8\x14\xaaT'\x93\xcf\x06\xba\xc4(Jtq\x8d\xa0\xb0W\x14\x1f\x15\x84#\xe2\xbby\xc2\x06\x9a\xcc;\xbcwC\xfe\xb6\xdf(1\xef>\xb4&\xaf@K\x9b\f&mՓ]+S\x12R\xef\xe9\xe5vWd6\x84H\xa8!s\x0f_\u0095Û\xf37\x1e\xba\xc2\x1d\x82?\x9aܳH<\xcf\x15%\x16\x93\x84\xc0\xa6L\xff\xe2\x1e\xe5Ӟ\x05\xfe\xf9\xb4\xd4\x06\xa2\xb2@\xd9Z\x9d\xe3\xcf\xdcD%!C\x15\x83\xfe\n*'\x86\n\x9cI$$N\x9b73b\x99r\xd9\u0092\xd5\x13\xab8\xcd\x1e\x8d\xaf\x83q4\xae\x1dl\xaaNi\x86\x12\x01oqW\x89d\x18%\xaamR\xdf\x1b\xe4\xf7h}\xa27:\x8e\b\a::\xde\x17\xc5\xdft\xe4\x1d\x10\xaf\xbc\xfa\xc8\x12Q|\xebH\x9ePp\xe0\a+\x1e\xa2\x11//\xdb\xfc\x83\x13\a\x84g-\x19\xdbI\xb3\x96j\x9e\xb3`G\xd3v\xcb`\xa6\xb7\x90d\x91yde\x0f_\xc2\xee%\xfb\x8e\xef[\xb2\x9b;\x04w4\x99\x16\xeb\x95\x1b\xaa\x89')\xdb+\x92\x94;\xe1\xeb|e\re\xbeB\xb9\x03\xd2\x12\xcc\\\x18\f\x06\x95QXQ\\ICEʂ\xcb\xe2`\x1cW\x0f\xa3?r,\x18\xf4i\xf3\xebF,S.S\xd8\x19\xc2L\u007f\x19G\xe3\xea`\x94 \xb2\xed \xdaT]\xbc\xd4ל\x9d\xec\xd0y\x04`b\xf1P\x89\xba+{\x94\xf7P\xd5@t%bGgK\x0e\xc8/\a\x96(\xc9\x15r\x0feg\x81\x9c\xba\xb8v\xdbE\xf9\xf5\x88uJ\xbb\x81t\xab\x89\xf3s\x17\xcbݏ\xc1Z\xeb\xa4Pc\x02I8(\xf2%\x1c\x17N\xc8\x1bN\b\xc7E\xf6\x10lR\xa6\x87\x84M-\xfb\x92{訉\x96\xaa܈j$J\xc9ƀ\xaaAQ\x8f6\xb2_\xec&ܽtvd\x94\xb8\xdd\x12˖k\x16֩\xde\xea:\u007f~\x90?\x9a\x19˖`\xb6\x03%\xbc\xea\xf7\xca\x1d\xadQ߄\x03`B\xf0P\x89\x9aj\x95\xb7\x81@\xe8\xf2\xe5˧\xab\xa3=\xe2k\xafD\xbb\xf5\xe4q\xe1\r\xdbl\xf5\xfa\x15x\x90\x9c\xb4\xd9ݿ\xc97\x97\xa4\xf9\xb6\xf4s%\xecޠ\xbcmxDd\x0f\xc1&Ez9\xef\xb7\x14&\xfa\xd6\xc9/\xdb}\xf2K\xd1<eC\x16\xdd`*\xd1\xea\x8c\xc1K2s\x8b\xc4\xc1x\xfb>\x91h(\x91\x19˖k\x16vVљղ\x824qG3c\xd9\x12\xccv\xa0\x84W\xfdtce\x16\xfaD\xc0[<T\xa2\xaac\xca[w\xa5\x0e?\x8b\xc3b\xafDF\xf2Y\xe1\xa2m\xb6V\xfd\x1a\xaf 6s#⎔\xca\x10\tU\xa4\x94s%\x94nS\u07b6m\x16#\x1c\x8d\xd2FZ,\x85\x89\xca\xc0JQ\x81\x85K\x95\r\xf7\xe4\xd0WC\x89\xe6k\xd3<\xf7\x1a\xf3D\x83\x8dZYaJ\xc4\xc42\xe52\x85\xa5Љ\x9f\xbe:r\xff w43\x96-\xc1l\a\x8aM\xd5E1H\xda\xc27\x02\xe0\x1e\xde)Q\u007f\xa5\xf6\x87\xba\xbfO\xa6\xb3\xaa/ʳ\xd0\x16%\xdagц\x13\xc2/l\xb3\r\xe8\xd3.M\xc4\xee\xa9\x1eqP\xb9wF\xa7\x8d\x99\x12v\xaf\xa7OP^YO\xfb@\x11\x95\xa8\xdcw\xd6Z\x98\xa9\x02E\x19ʆ\f\xb3O\x148-\x0f\x9a2\xda\x15\xfa\x8d{g\xb5Dy\xb3Q\"&6\\\x89\x94\xc2Ri\xad\xeb\xe8\xc4\x17{43\x96-\xc1l\a\x8aM\xd5q\xef\fx\x8ewJ\xd4]y\x86\xd9<\xday\xa2\xfc\xbd\xb2J\xfc7\x8b6\\((\xa5]\x9a\xc7\xf6Z\xf3\xad\xccP\xc7|\x03i\xb9\xf4\xca-\xd9d\r\xe8\xa1\x13+\"W\xc2qሜ:\xa2\xce\x13EP\xa2\xcbY\xf7XKbT\xa0A\x19\xff\xecW\xe7^rs\xe5\xce\v\xa9\xa539\xb5\xf4sY9}\x9eh\xb9\\\x9d˹\xaa\x86\xd8(\x11\x13\xcb)\x91QX\x97\xf2\xc8t.U\"\xf6hf,[\x82\xd9\x0e\xa2}աD\xc0s\xdcU\xa2\xf3\xbd\xbdUͽj\xe7'T9hl\xbf,\xf7\x89z#>c\xa8\xde;{\x95vU\xc4҂\xa7\x9f\xde,\xe4=\xff\xd6\xfb\x1dy\x8f\xbcz\xe5\x8dG\xf2\xe8=\xb5\x97\xf37\x1c>\xfe\x98pؚ\xb3K\xbfK\xd5<;\xeb[\aKH\xc0\x1a`\xc0\x94\xb0Sx\xe2\xa5'\x84\x9d\xa2\xc8\x1c\x82;\x1a\x1d\xedY\xfbX\xbd\xc1\x84u\xadb\xfb\xba\x84\xa0<\xc6,\x8c\xbb\xbf\xe1\xfe\xb8Be\xc7v_E\xfd\"\u007f\x8f\x9c\xba\x9f\xac\xae\xad/\"Tr\x1b\xfd9U\xf5w\xc5\xcb\xc3$\xe5\x19\xeb\x8a`P\xee\xe7\f\xb6\x06\x83\xbeu\xc1\xe0Y6\x96+\x97)\xac\x82\x145\x14\xa9\xcfX\x1bG\xe3b\x99\xa31\xed`Wu\xca1\xbb!\x1b\x00\xee\xe1\xae\x12\x1dS\xe6\x83\x02\xca𠛹\x85\xd3\xcb\xfc\x04-\x8c\x8b+\x94lj\xf2ަ\x1f\xde-\xcd_\xb6m\x9f <\xfa(\xdd\xf4\xcbe\xf2\xeb\xa3\xf2\xe6\xb7\x1f^\xbbl\xb3\xdeob(\x9b\xad]a]+\xe7&\xe5ԅ\a\x18\x98%\\9\xb4Q\u007f\x9e\xc88\x04\u007f\xb4`\xe2\x16k\xf6bBHB\xa7_~-\x96?U\xccW\x9f\xf0\x91\x19,IN\\ئ$\x1bsS\x92\x17*7\xd4\xc4λ\xfc\xa9K\xe9C\x95\xeb\xb4\xf9\x1cy\xd8\xd5\x16\xa7&+\xd9X\xbe\\\xa6\xb0\xfa\xacĜ\x83s\x95\xd2\xf4\xa3\xf1\xb1\xccјv\xb0\xa9:\xa5/~\xe5\xa9>,\v\x02\xbc\xc3]%r\x9fM\xbeZ\xa7\x90\x98\xd9\xef+\xba\xe4\x143\xd9\xd0\xda!b\xd5보\xd9m\x00<a\xba+\x91X1w\xdcW\x05I\xbb\xed\x9f\xe2{\x80\xd2\x0eѪ\xdewj\xbc\x1b\n\x80\xd13\xed\x95\b\x000\x05\x80\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x91\v\x1c\xdd\xfc\xfb\xa9jb\r\x80;\xb8\xaeD\xe1n\xd4竔T\x95\xb9\\Ѥ\xe6\x17t\x89\x92\xddQ\x02\x0e\v\xcaZk&O\v\a\xe8\xdaJ\xe3`b\r\xc0t\xc5m%\xb2q\xa3>Sy\x92\xa6\xa7\xca/\xc1\xff\xf0\xeaƍ\x1d\xbf\x8e\x12\xf0A\xc7\xe6\x03\xec\xe7C\xc2\xf3j\"\x16\x13k\x00f\x16.+\x91\x9d\x1b\xf5\x99\xca\xd3ѲL>\xbeZ\xea\x10\xb0\x8dU\xa2w\xf3\x9eГ1\x98X\x030\xb3pW\x89lݨ\xa7\xb9\x12\xed.\xb8\xa0'c0\xb1\x06`f\xe1\xae\x12ٺQ{\xa8D\xe1&\xd6\u007fX\x93\xb7om\xc1ˏ\xad(\xbd\xc0z_s0Jd8Ws\x85\xc9J\xf4\x98 \b\xf9\xbf\x93\xd3\x17\x971\xeb\xfc\xdb:A\x03\x00\\V\"\xd1\u038d\xfaLe\xd3S\x955A\x0f\xaeQ;\x13\xeb\x97W\b{K\x855O\xafy\x96\xf5\xbe\xe6`\x94\xc8p\xae\xe6\n\x93\x95\xe87;\x85g_\xa3\x9b\xdf\x10:̜\xe1N\xd0\x00\x00\x8a\x87J\xa4\xbbQ\x9f\xad\xac>\xd5\x13\xaa\xdd\xef\xfa\xbd3{\x13낝\xe2qᨸ\xdb\xe2w\xc6`*\x11\xe3\\\xcd\x16&+ѳK^\xd2C\xde6sژX\x03\x00DO\x95Hs\xa3\x16\xc5N\xda\x1d:_\xe5zw\xc1\xdeĺ\xe0\x88\xf8\x9apA|b\xa7\xe8\xacD\x8cs5[ض\x03\a\f\x83\xb6\xa3»fN\x1b\x13k\x00\x80\xe8\xa9\x12in\xd4:\xc1h\x1e@\x13\x82\xbd\x89u\xc1q\xf1\xb5<qtJ\xc48W\xb3\x85m+X\xb1\xe1!u\xf2H|Ux\xd5\xcci\xeb\x04\r\x00\xf0P\x89\f7\xea&\xc5+Uln\xb0\x8d\x9f@\xecM\xac\vN\x88\xaf-a\x95h\x9f\xbd\x12]8\xf0\x01\xeb\\\xcd\x16\xb6\xad\xe0\xadwWh\xb3O\x17\x9607\xd2l\x9d\xa0\x01\x00\x1e*\x91\xe1Fݠt\x86\xfa\xabN\xdag\x988x\x13\xeb\xee\x1d\xaa2\xb2J\xc4x_\x9b\x01\x9a\x12ѩhƹ\x9a-\x8c\xde\xc5?\x9e\xf7\x9a\x1a\xfd\xf0\x86+\xfa\x01흠\x01\x00.+\x91\xad\x1buO\xa0\xb1\xeb\xf4\xb1\x80\xeb]\"\x8b\x89\xf5R\xa2\xc8\xc4[\xab\x9e\xbdp$\xef\xad\v;K\u007f\xc3x_3\x01\u007f\xf8\xf9ƍ\x1d2\x87\xe9M1ù\x9a)샎͏\xbcz\xf1¶\x82\x97\u007fO\xb7\xbf-\xfc@?\x9e\xbd\x134\x00\xc0e%\xb2w\xa3\xeek\xaa\xa9j茜k\xe2`M\xac\xabR\xa8\r\xf4\x955\x82pd\x99\xb0\xec\x88 <\xc4x_\x9b\x01\xe2[\x82F\xfeیs5S\xd8a\xba\xf3\r\xb9\x00A\x1d\x97\x1d\xc8\xd7f\x8a\"8A\x03\x00\\V\xa2\x19ɕ\xbdy\xca/b\xa7\xa2\x895\x00.\x01%\x9ax\xae<\xbb\xf6wS\xd5\xc4\x1a\x00w\x80\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0DS\x18\xb8\\\x83i\x83\xebJ\x14\xeeF-\x13:XU˯%\xeb\x16\xdd\t$+lc\u007fqj\xe2=\x97m\xa2LJR\x81\xda\x17\xd1eC8\xe3\xb4G\xe8J#̢\xd7V\xe0r\r\xa61n+\x91\x8d\x1b\xb58\xd8\x14h\xedn\xaf슞s\x82h]\xe7\v۶(\xf5[\xeb\x12\xcf\xd8\x04\x8f\x0f\xef\xee\x15^\xbe ^\xe8\x10\xf6r\xba\U000db38eC\xec\xa2\xd7V\xe0r\r\xa61.+\x91\x9d\x1b\xb5\xd8\x14\xe8\xa5\x12\x15\x8a\x92o\x02\xd9\x1e\xa6D\xfdD\xbe\xb2\a\xecbljC\xca\xea\xfb\u007f\x10\x0eYw\xbc\x16M\x89\xe0r\r\xa61\xee*\x91\xad\x1bu_\xa5\xb2\x82\xb5Wk͇+Q\x17\x99\xe0\x95l\xc7E\x89\xe0r\r\xa6\x13\xee*\x91\xad\x1buk\xc0\xab\xa5\f{\vӒWj\xa3\xb3\xea\x1c\u007f\xe6&\xb9#4\x98B\x146q[O\xc5\x13R\xd6U\x98\x9e\xb8\xd8R\xd71\xf9Y\x9bJ\xf4\xa8\x90wx\xef\x86|\xbd\x00C\x89\xe0r\rf\x18\xee*\x91h\xe7F]\xdf\x10\xaa\vԴ\xb8\u007f-u%eV\xd5\xdfE\x14%*\x8a+i\xa8HYpY\x14O\x06\xf7\x93\xed\xc1`\x1f\xb7\xf5|mMzf\xd2\xdcM\x85\xe44W\xc4\xd8\xfc\xacM%z\xebH\x9ePp\xe0\a+\x1eRw\x18J\x04\x97k0\xc3\xf0P\x89t7\xea\xda\x00u\xa3\xae\xa9uݍza\x86\xdc۹<\x9f*Q\x03\xa9\x12\xa91\xa2b\xd1j\x8cθ\xad\vȢ\xb3\xd61\xe4\x18\xfd\xac\xd9\xd1ْ\x15rogg\x81\xbaCW\"\xb8\\\x83\x99\x86\x87J\xa4\xbbQ7(^\x1f\x03U\xc6\x0e\x978C\x02\xf4\xad\x8c*\xd1\xea\x8c\xc1K2s\x95\xf9\x16C\x89\xb8\xad\v||w\x882F?kN\x89v3\x01\xba\x12\xc1\xe5\x1a\xcc4<T\"ݍ\xbaY\xb5\xa1nv\xfb\x01\xbdc$Hߔ\x19\xeb\xf9\xea\xe4\x10\xb9\x97n1\x94\x88ۺ ;\xbc\x881\xfaY\x1f\x16h\x0f\xe7\x82b\xb4\xc6\x05\xe8J\x04\x97k0\xd3\xf0N\x89\f7\xea\xf6*\xe5!¦\t\xbea\x15F?\xd9Cߔ\x19\xeb\u008cv\x85~\xba\xc5P\"n낕\xe1E\x8c\xd1ϺCɦ\xce\xf4\xd8*\x11\\\xae\xc1L\xc3;%2ܨ\xfb\x95\xbb\xf8g\x03\xae?d\x9d3W\x96\x98\xae\xd9T\x89\x1aI-\xddRVN_\r%\xe2\xb6\xda)\xd1\x18\xfd\xac/\xac\xa2C\xb2ݫ\xe8mx[%\x82\xcb5\x98i\xb8\xabD\xb6n\xd4\xe2\xb1\xc0\xb1\x9e\xce\xea:\xd7\xef\xe5w\xfa疗%\xc7\xc5W\x85D\xf1~\xb2\xba\xb6\xbe\x88T\xeb\xf7\xce\xd4{Q\xc6\xd6K\xad\xc1̅\xc1`\xb7\xb5\x881\xf9YS\x8dy\xf4\xf8\xa3Tm\xde\xef\xc8{\xe4\xd5+o<\x92\xd7\xf1\xbe\xf8k\xfa\x8c\xf5\xb3\x1d\x1d\xbf\x16\xe1r\rf\x1c\xee*\x91\xbd\x1b\xb5\xd8U_Uw\xccu!\x92\x8f\xbb49}KU<)\x96Ӎ\xb9)\xc9\v\x0f\x8a\xe2`\xb225\x14\xaf>\xf1\xado=\x15\xa7l\r\xefz\x8c\xc5\xcfZ\xe6\xf8\xe6e\x9b\xe5\x0e\x0f}\xe0H\xc8\xfb\xe52\x81\x06\xec\xd6\\\xae\x1f\x16\xe1r\rf\x1c\xee*\x11\x18G\xe0r\r\xa6\x11P\xa2\xa9\v\\\xae\xc1\xf4\x01J\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x98VL\x9cM\x1d\x98P\xa0D`\xfa\xd0W\x94J\x96;\x05\x81I\t\x94\bL\x1f\xb2\xb2\x02M\xe1k\xfc\x82\xa9\x80\xebJ\x14\xe6Fm1\xa6v\x97\xa6\x14c\xa5ȱXP;\x19H3\xbc|\xb7Pz\x85ZP\xdf\xfdr\xe4\xa0\x13\x05\xfa2\xd5\xe2\xff|tM\xfe6c-\xb4\xe84$\x8f~\xbdK\xfd\x8c\xd7\x11B\xfcᶻ\xfd\x8b\x92w\x84'9F}4\xbeu\x98ss\xe2\xe8\x86\xfc\x8dG6\xbe\xe4\x14\x16\xc6)\xd2\xe8\x14\x02&+n+Q\xb8\x1b5gL\xed6\r~c\x95\xa4\xb1XP;\x19H3\\<!\xe4w\x88\x17\x8e\b',K_\xbf\xcc,@\xfbҲ#z\xf2\xab\x05\x87w\xe7\xf3\x9e!\x11\xd9J\xb6:\x85\x18\xe8g\xdc\x13\f\xee\xb1\xf1&ڒ\xb1#\xae/,\xc91\xea\xa3\xf1\xadÜ\x9b-f;\x1c\x12v\x1e\xdd+\x84\xfbR:Ҧ\xaeL\x0e\xa6\".+\x91\x9d\x1b5kL\xed\x1dc\xb5\xa0v\xb0m5\xb9 \xec|D\x14\xdf\x15.\x88<\x9b\x1ff>\x18\x9d\xa0\x0f\xe4\v\xf1\x8a54\x12e\xa4\xcc)Ď6\x1b%\xca.\x17\xfd\xc1\xb0$G,Gc[ǡ\x83g\xb4\xc3\xdbw\xef\x93_\xf7\x8eI\x89`\xfb6eqW\x89lݨ\xadIo\x18\xab\x05u\fJ\xf4\xf2\xb2\v6J\xb4\x91U\"\x83w\x85Q\x8feD\xb1\x9c\x94;\x85\xd8aw\xe1Ϋ\xea!]aI\x8eX\x8e6\xea\xd6a\xdaaw\x01\xed5\xfe\x12J4\xb3pW\x89lݨ-I\xf78\x93HH\x9c2;\xc5[P3\x84\x9bM[\xb7\xda\x19Hwl[\x9b\xb7f\xdbZş\xe3\xf9\xcd\xcb6\xec\xa5\xeasAxw\xe3\x11M\x89\x8cأڊ\xb1\x9b\xe5\x8d\x1f\xe4\v\x82\xb2\x92\xbexq\x8d\xbau\xaf<\xa6\x91\xdf\xf6\x89Ok{\xec\xab#\xee ʄNO\x92抔\xd4\xc3\xec,&\t\x81M\x99\xfe\xc5t\x9by\xc6\x14\xbb\v\xf7\x9e\xb2{睊W\x16\xcfe\x92\x1c\xda\xd1\xc4XZ\xc7<7\xa6I\x18+n\xb6\x1dV=\xa1\x84\x1d\xa2\xeby\x1b\r\xc5\xd9v\x9b\x8d\xca\xd3\f%\x9a\xba\xb8\xabD\xa2\x9d\x1b\xb5%\xe9\"ǂA\xdfv%\xc5ZP3ؙM[\xb6\xda\x18H\xbfq\xf7\xee#'\x0e\xaf\x11\xfe@\xb7\n\x8f\x1d?T\xb0\xf1\x8a\xa2D\x87\xb6iJd\xc4^x\xb5cCiGG\x87\xe2\xe7\xfaZGG\xbe\xbaD\xf5\x1b\x1dG\x84\x03\x1d\x1d\xefӀ\xb5\x8f\xfe^\xfc\xfd\x81\x15\x1d\x17\"U\x87\xae\xa8_A\xdf\x06\xab*T\xaaX;\xddPM<I\xd9^\x91\xa4\xdc\xdd6\xcfX\xb4W\xa2\xf2$߱K\xf7,l\xe5\x93\x1c\xda\xd1bk\x1d\xf3\xdc\xcc&a\xac\xb8\x99v\xf8@x\xde,\xcch(ζ\xdblT\x86K}\xcd\xd9\xc9c\x18^\x83Ɂ\x87J\xa4\xbbQ\xf3I\x97IԯK\xbbљ\xbd\xd94\xbf\xd5\xc6@\xfaP\x01\u0560C+\xae\xd0.\xcd\xf3J\xcc\x11E\x89~\x97\xff;E\x89\x98X\xcb\xe8L\xbfZ\x99\xd1\xd9\x01\xdaOP\x9c\xad\xed\xab#\x13 \xeaJ\xfd}\xdd*\x16A\xf5%\xf7\x88ba\x8a\xf6)1\xaa\x12\xed \x01\xf1\xac\xff\xa0%ɡ\x1f-\x96֡h\xe7\xc64\tgŭ\xb7\xc3/\x95ƹr\xf1\xe2E\xbe\xa1\xccX\xb6\x04\x93{\xe5\xce\xe0\xd8\x06\xd8`2\xe0\xa1\x12\xe9n\xd4|\xd2e\xa2*\x91\xbd\xd94\xbf\xd5\xc6@\xfa\xd7\x05\xeb\x1f;\xfc\xc6\x15:۱s\xfd\xc5?Ȭݭ(\x91\xb8\xedYE\x89\x98Xg%\xfa\xcdݿ\x14/\xae\xa0W\xa4}ud\xaaH\x15}\xeb&:\xbc\x1b\x92o\x9d\xa8Y\xddR\xa2*Q-I\xde$V\xa4]\xe2\x93<\xda\xd1bj\x1d\x8avnL\x93pV\xdcz;\xa8}\xa2\x9d\xf2P\xed\x04\xd7Pf,[\x82\xc9\xe9\xc6\xca,\xf4\x89\xa6.\x1e*\x91\xeeF\xcd']&\xaa\x12ٛM\xf3[m\f\xa4\xc5\x0f\x0e?\xbcAX\xf3\xb4\xdc'ڨ\xcd\u007f<\xa4*ё\x8d\x8a\x12\xb1\xb1\x8eJ$n\xdb+\x1e_A\x0fi_\x1d\x99\x96dUR\x82\r*\x96;^\xcaxlTJ\xd4\xe7\xdf\xd4<\xbb;c;\x9f\xb4\xa0\x1f-\x96֡h\xe7\xc64\tg;i\xb4\xc3\x1a:O\xf4\xfe\x11ቋ\\C\x99\xb1l\t\x1cA\xd2f\xdd\x04\xa6\n\xde)\x91\xe1F\xcd%\xdd&\xaa\x12ٛM\xf3[m\f\xa4_{BN~p$\xff\x10\xfd\xf3\xfd\v\x85ߩJta\xd9\t\xa5Od\xc6jW\xe0\xe1_\xab\xa5\xd9)\xd1\xd1U\x17\x95\xc1Y\x84\xea83z%\xaa\x97{S\xcbӓ\xce\xf0\xc9\b\xc4\xd2:\x14\xa3Od4I\xb8\x12\xd1vؽ\x86j\xd9Qz\xef\x8cm(3\x96-\x81\x03\xf7Φ0\xde)\x91\xe1F\xcd%\xdd&\xaa\x12ٛM\xf3[m\f\xa4\x0f\xa8\x13@\xa5\x8f\xd2\xebR\x99\xcc\xd8\xf7\xb4\xaaD\xe2\xee\x9d\xea<\x91\x11+\x87\x95\x8a\xe2\xef\xf59\x0f;%\xba\xb8\xe6誗\xc3\x0f<zF\xafDu\xa4K<IV\x8b\x97ӻ\x99\xa4hO,\xadC\xd1\u038di\x12N\x89\x8cvx\xfbny\xeb\x95R\xaaDlC\x99\xb1l\t\x1cP\xa2)\x8c\xbbJd\xefF\xcd&\xddd\xb05\x18\xf4\xad\v\x06\xcf\xf2\x16\xd4\fvf\xd3\xecV{\x03\xe9\x03²\x03/\x1d\xdd-P\xf9x\xe2\xee\x9dG\xe4\xe4\x11\xfa\x8c\xf5\x91\vrV\xe5\xde\x19c6-_\\\xcf\x1e\xfd\xea2\xb9\x84\x8b\xafvt\xe4?\xd2\xd1\xf1\x81~\xef\xecU\xed\xe6\xd0\x13\xebW\xfc!\xbc:\f\rs\xa2L\xd5\xf6\x06\x13ֵ\x8a\xed\xeb\x12\x82\xbd\xec\x19+\xcfXW\x04\x83\xdcϴ\xfa\xfc+\xeb\xd23}%\xe5\t}L\xd2R\xa0q\xb4\x18Z\x8797\xb3IX+n\xa6\x1d\xe4\x01\xde\xee\x97v\xab\xcfX\x1b\r\xc5\xc5\x1a%X8F<~<\x16\x8c\x1dw\x95(\x82\x1b5\x93t\x936\xd5b\x9aTZ,\xa8\x19\xc2ͦ\xb9\xad\xf6\x06\xd2ϗ>\xbd6\xaf\xa0T\xfd}ى\xd25+J\x8f+\xbf;\x93/\x9d+\x9b\v\xaep\xb1\xf2E\xfaت\xfc\xd2\xd7\xe4\xc4\x1bZa\x87ŋ+\x94D\xde\xdb\xda\xe1\x04}n\x96\xad\x0e\xc3\xc1\x94\xf0;\\\x06\xc5\xf2\x89%t\xfa\xe5\xd7b挕ߝQVr\xc1M\x19)\xc5\x03M\x99\xc9{\xb8$\x8fy\xb4ѷ\x8eyn\xa2\xd9$\xac\x157\xd3\x0e\xca\xef\xce6\x1f_K;BFC\xf1\xb1z\t\x16\xfa\xe2W\x9e\xea\x8b\xf1\xa7\x83`\x92\xe0\xae\x12\x81\xb1paI\x94\x1f\xcd\x02\x86\xfa,B\xeeu\n\x02\x93\x12(\xd1\xe4\xe7Ț?8\x85\x00\x8d\xbeS\x1e<\xac\x0f\xc6\x01(\xd1$\xe7闯|\xf5\x80\b\xc04\aJ4\xb9\xb9 l~\xb4`\x94\x8b\x83\x000u\x81\x12Mr\x0e,+}\xdb)\x06\x80)\x0f\x94\b\x00\xe0=P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=\xae+Q\x98\x1b\xb5(\x0e\xb4<\x15x\xaae\xc0!\xe34b\x92\x98X\x030yp[\x89\xc2ݨ\xc53\xd5u\xa1\x9eP]\xb5g\xeb6\xba\xce$1\xb1\xa6|\xf0~\xe4}\xcd\xed\x91\xf7\x010\xbe\xb8\xacDvn\xd4\xc1Z\xea\x1fq\xa9vFy\x9a\x8f\xda\x1cu\x02M\xac\xa9\xb1\xe1\x8aR-y\xf9\xd2\xe5\xcb\xf2\xff\xec\xdel~\x155\x00&\x10w\x95\xc8֍\xba\xa9^\xf9P\xef\x89\xf9\xa2WĠD\x13fb-\xbe\xb5YмZ\xbb\xb2\xb3\xb2\ue657\x95\xb5\x89\x1d#/\x80\x12\x01\xd7pW\x89lݨ\xfb\xab\x9b\xfb\a\xfb\x83\xd5\xfd\x91rM=Fo\xd3졉\xf5\x85\xbd\xc2ڗ\xd4\xe4%\x1f\xc9͝\xe5\xcf͞\xf5\xc0ymo\x83\xb6\xba\xec\x02Q<\x15OHYWaz\xe2\xe2K\xc5$\xaeZ\xec\xf6\x91,%\xa6:ǟ\xb9i\x06\xcd\xef\x81\t\xc4]%\x12mݨ\xcf7UVV6\xea\x97\xc04 \x16\x9bf\xafL\xac\xaf\x1c-\xc8{B\xedh]|\xf7\xed\xff\xbd\\\x92B\xc3\xd2\xc8g\x97\xea\u007f\x0f\x06Z\x82\x99\v\x83\xc1`H\xfe\xf7\xa9\xadI\xcfL\x9a\xbb\xa9\x90\x9c\xee\r&l\x17\xc5\xd6u\x8aQHQ\\ICE\xca\x02,\x1c\r\xc6\x01\x0f\x95H\xb7\xa0\x1el\xaa\r\xf5\x86j\x9b\xc2\xddF\xa7(\xb1\xd84{fb\xfd\xa8\xb0\xf1--Y*\xfc?\xff\xe7\xacY\xb3ĕ\xb3f}\xa6\x9c\xb9o\xc0\x8c\xce\x16\x90EgE\x91:!\x98\x96E\r\x8a\x17l\x1b\xd9/\x02p\xdbx\xa8D\xba\x05u\xb0\x96z\f\r\xd6N\x1b\x87\x98Xl\x9a=3\xb1~~ɪ絉\uedcf\x1e\xfd\x1f\xff\xef\xff%+\xd1\u007f\xb8wG\x17\xe3\xf7\xc4*\x91Ow#2\x95hu\xc6\xe0%\x99\xb9E\"\x00\xb7\x8d\x87J\xa4[P\aN*o'\x03v\xe1S\x91Xl\x9a\xbd3\xb1~w\x9b\xb0Y\xef\x15\x89\x97\xcf\x06d%\x8ao\xefg\x8d\xe7X%\xca\xd6S\xa6\x12\xcd\xd7f\x92`\xa6\x01\xc6\x01\xef\x94Ȱ\xa0֔\xa8}\xda(Q,6\xcd\x1e\x9aXә\xa2\xbd\xc6-\xb9Z\xaaD]\xdc\bYQ\xa2\xc0i#\xa9\xa0(Q\x19U\xa2\u008cv\x85it\xa7\x01x\x87wJdXP7k\xa3\xb3\xe6\b9\xa6\x1c\xb1\xd84{jb}a\xafPpBK\xdb(Qn\xae(\xf6\x91Z\x9a4\x95ȿU\xeeAeS%jTw\x95\x95\x8b\x00\xdc6\xee*\x91\xad\x1b\xf5\xf9\xfd\xb5\x9d=\x9d\xb5\xfb\xa7\xcfͳ\x18l\x9a\xbd4\xb1\x96y\xabT\x1f\xe4\xd9(\xd1v_E\xfd\"\u007f\x8fx\xa9U\xb9\x8d\xa6\n\xea\u0094\x1d\xe59$\xbe*$\x8a\xf7\x93յ\xf5E\xa4\xdaZ(\x00\xb1\xe3\xae\x12ٻQ\x0f\xb6\xd5Uյ\xb13\x14S\x9d\xd1\xdb4{ib\xcda\xa3D\x83%ɉ\v\xdbD\xf1\x94\xeaa\xad\njWnb\xd2\xe2\xafPkk\xb9W\x94\x9b\x92\xbc0\x8a\x116\x00\xa3\xc6]%\x02.\x12\x9b\x89\xb5\x8d\x12\x01\xe0\x1eP\xa2iKl&\xd6P\"\xe0)P\xa2鉓\x89\xb5`\xe5\xff\x96\x95\xe8\xff\x80\x12\x01\xaf\x80\x12MK\x1cM\xac\xa1D`r\x01%\x9a\x9e\xc4lb\x8d\xd1\x19\xf0\x14(\x11P\x80\x12\x01O\x81\x12\x01\x05(\x11\xf0\x14(\x11\x90\x19ܳ\x92\xfe\x02vk\xcbtz\xaa\vL%\xa0D@&G_\x15\xa4\x0eR\x04<\x01J\x04D\xf1\xfc\x1d\xe5\x924$I#w,\x9f9\xbe\x06`R\x01%\x02\xa28@Hn\xee\x1d\xa9\xb9ٳ\x8a\xf0\xcbz\xe0\tP\" \x8a\x97\x82s\x93\x933\x93\x93\x93\x17\xb5M\x9f\xdf!\x83)\xc5LV\xa2\x95$\xa50\xe4\x1443\x18\xec\xeb\xee\xea\xee\xee\xea:\x8d\xf5\xf1\x817\xccd%\xeam\xae\xcaJ\xc1\xa5\xa7B\xbd\xce,~g\x00\xb8\x87\xebJd\xe3F}\xf9T}\xa0Λ\xceI39\xe5\x14\x02\x00\x98x\xdcV\"\x1b7j\xb1\xa1\xaa\xbd\xfbX\xe0X\xf4\x8c\x13C\x1biu\n\x01\x00L<.+\x91\x9d\x1b\xf5\xc9\x00\xbd_\xd3\x15\xf0b\x9c\x04%\x8a\xc8,\xcfq\xaa!\x98N\xb8\xabD\xb6n\xd4\r\x8dʇj/:EP\xa2\x88\xcc:\xe71P\xa2\x19\x85\xbbJd\xebF]\x17T>\xd5{\xb1\f\xe9)2m\xd6\xf1\x1fo\xa0D\xc0M\xdcU\"\xd1\u038d\xba\xa5Z\xf1\xf6\xa8\xaa\xb3\xcf0\xa1\f\xa6\xe4\xb4\xf4\xe0\x86\x91\x1dP\"\xe0&\x1e*\x91\xeeF=P\xd5\xd0w\xbe\xb7\xbe\xb2\xd6>\xc3\xc4r\x90\x10\xb2\xd4)hF\x02%\x02n\xe2\xa1\x12\xe9n\xd4b\u007fCee\xa0\xb5\xa1\xde6~b\x19Hɨh\xeev\x8a\x9a\x910J4jQ\x1au\xe0\xb9Q\xc4B\x89f\x14\x1e*Q\x959E}\xbe\xff\xb2\xa8\xdcGs\x9b6\xd2\xe4\x142S\x81\x12\x017\xf1N\x89\f7jQY\x9e\xabK\x9d\xbev\x19\xdc;\x8b\b\x94\b\xb8\x89wJd\xb8Q+\xb7\xd0\xce\xd6xr\x13\vJ\x14\x11Y)~\xfa\xb7w\xcc\xfa\xc2?ɚ\xf0\x8d/̺\xe3\xef~%\xab\xc3\xd7?\xff\xbf}\xfe\xeb\xf2\x8e;\xe4\xf4\xdf\xc9\xff\xdf\xf13U5\xbe\xf3\x85Y\x9f\xfb\x06\x13(\xe7\xfc\xec\xdf\xfe\x8a\xd9`\x16\U0005dfda\xf5\xf9\xbf?g*\x91V\xe4\xb9Y4!\x97a\x1eթ\x86`:\xe1\xae\x12ٺQwU\xb6\xf5\x9c\xacn\xf0\xe2\xc1F\xb1\x15J\x14\tY)\xbe\xf0\xe5_\xbd\xf7\xcf\u007f#k\xc2_>\xf3\xde\xcf\xfeNV\x9e\xef|\xee\x99\u007fy\xe6s\xdf9w\xee/\u007fx\ue9f3~v\xee\x9f\xffRU\x93\xef\xfd\x87\xef\xbd\xf7ӿc\x02\xff\xea\x99\xf7\xfe\xe5\xbf\xfc'f\x83\x91\xf8\xe7\xbf\xfa\xe7\xf7~\xfa\x1f\xff\xdeP\"\xa3\xc8Y\x9f{\xe6\xbdg>\xf7ߙ\xa3:\xd5\x10L'\xdcU\"{7\xea\xf6ڪ\x86\xf6ș&\x8c\xc1\xde\xf6\x95\xbe^\xa7\xa8\x99\x8a\xac\x14\x9f\xd1z<\xb3~(\xbf\xfc\x8b\xdc\x0f\xfa\xe2w\xa8v|\xf1ܹ\xff\xf2\xe5s_\x9e\xf5\x8ds\u007f\xff\xff\xa9\x01_\xfc'K \xe5_>\xc7l0\x12w\xd2\xc4\xcf>o(\x91Q\xe4,%q'sT\xa7\x1a\x82鄻J4\xb9\xb8\x97\x90t/n\xd8M\rd\xa5\xf8\xafw\xfc\xe7oPYPEC~\xfd,\x1d^\xfd\xea\xb3r'\xe8\xaf\xcf\xdd\xf9\x9f\xfe\xe6\xdc\x17\xbf\xa7\x89Ư\xce\xe9!\xea\xeb\xcf\xfe\xe6\x8eY\xb3f1\x1b\x8c\xc4\x1d\xea/9\f%2\x8aT\xca\xf8\xd5\x1d\xccQ\x9dj\b\xa6\x133Y\x89\xfa\xda{\x9cBf0T)~\xf8\xe5\xbf\xfd\xec\x97\xed\x94\xe8\xbd;~\xf6\x99\x9f\xdd\xf1\xb3Y\xef\xa9rr\x87U\x89\xee\xfc\xaf?;\xf7\x9e\xad\x12\xcd\xd2z<\x91\x95\xc88\xaaS\r\xc1tb&+\x11\x88\x86\xa6\x14?\xfd,##\xc6P\xeaܝ\xff\xf9?\xca\xffߩ\xa9ʝ\xfa\xe8L\u007f\xfd\x8c,Q\xcf\xd8*\xd1\x17\xbf~\x8e\x8d\xb5\x19\x9dQ\x94\xa3:\xd5\x10L'\xa0D\xc0\x1eY)\xfe\xfa\xbf\xbf\xf7\xde\u05ff\xc0\xc8\xc8w\x94Ye*\x19_\x9e\xf5e\xe5\u007f\x95g>\xa7\xcdX\xeb\x81_\xf8\xf2{?\xfcK[%z\xe6\x8eo\xfc\xea\xbdg\xfe\xdaP\"\xa3Hu\xc6\xfa{\xccQ\x9dj\b\xa6\x13P\"`\x8f\xac\x14\u07fbs\xd6\x1d\u007f\xf3SFF\xce}\xfd\xf3\xb3\x94[\xee\xe7~8\xeb\xa7\xe7~\xaaLC+\xfc\xd3_\xa9w\xf1\xf5\xc0\x1f~a\xd6\xe7\xben\xabD瞹\xf33\xb3\xee|\xc6P\"\xa3\xc8Y4A\xef\xe2\x1bGu\xaa!\x98N@\x89\x80=\xbaR\xb8E\xd8\xf1\xa0D3\n(\x11\xb0\aJ\x04\xdc\x04J\x04\xec\x81\x12\x017\x81\x12\x01{\xdcV\xa20\xa0D3\n(\x11\xb0\aJ\x04\xdc\x04J\x04쉺ؽ+8\xd5\x10L'\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1eו\xa8Y\xb3\x9d\x1ehy*\xf0T\x8b\xba(Q_}U\xa3\x17+6:\xf1\x88 \b\xf9\xef\xea\x9fN\x14\x1c\x8d\x16\xccrtC\xfe\xc6#\x1b_r\n\x03\x00h\xb8\xadD\x9a\x1b\xb5x\xa6\xba.\xd4\x13\xaa\xab\xa6\xeb6\xf6\x04\x82]\xc1@O\xb4l\xde\U0001b38eC«\xfa\xa7\x97\x96\x1d\x89\x16,\xbe\xfc\v=uH\xd8yt\xaf \x1c\x8a\x16=z\x9a\xbdX\xbb\t\x00wqY\x89\f7\xea`-]\xbd\xfaRmP\x14/\xd7е\xf4[j&\xa5\xed\xd8k\xa6\x12\x89W\xa2\xc4\xc9l~XK\xbc}\xf7>\xf9u\xefx)Q\xf6J\xa7\b\x00\xa6<\xee*\x91\xe9Fݤ.QV\xdf$\x8a\xa1\xc0y95\x10\bE\xce\xe7\x1d\xac\x129\xb0QW\xa2\xdd\x05\x17\xe5\xd7_\x8e\x97\x12-\x80\x12\x81鏻Jd\xbaQ\xf7W7\xf7\x0f\xf6\a\xab\xfbeQRm\xa8\x0fz\xb0\xa4\xfe\xbb\x0f\xad\xc9+\xd8\xf6\x9b([u%\xfa _\x10\x04mtv\xe5\xf9\xcd\xcb6\xec\xbd \x8a\x8f\ny\x87\xf7nȧ\xa1G\x05\x95\xcd\xf2\xfeUO(a\x87~Mc\x0fo\xce\xdfx\xe8\n\x17˔\xc0ГDT\x92z\x98\xad\r\xda\xc6\x05\xa2x*\x9e\x90\xb2\xae\xc2\xf4\xc4ŗ\x8aI\\\xb5\xd8\xed#YJLu\x8e?s\x93'ˀ\x030^\xb8\xabD\xa2\xe9\xedq\xbe\xa9\xb2\xb2\xb2\x91\xf6\x86\xeaT\xa3\xb3\x16\xf7\x17r}y\xd9\xe6\x1f\x9c8 <\x1be\xab\xd1'z\xad\xa3#\xff\x80\x9a\xdc-<v\xfcP\xc1\xc6+\xe2[G\xf2\x84\x82\x03?X\xf1\x90(^x\xb5cCiGG\xc7۲h\tϛ\x85\xed^\xb2\xef\xf8\xbe%\xbbE6\x96)\x81a\xb0\xaaB\xa5j\x90\xd9:\xd0\x12\xcc\\\x18\f\x06\xe5\x0e\xe3\xf9ښ\xf4̤\xb9\x9b\n\xc9\xe9\xde`\xc2vQl]\xe7\xa3!Eq%\r\x15)\v&\xe5\xe0\x16\x80Q\xe2\x95\x12\r6ՆzC\xb5M\x97\x8c-mՑ3M\f\x17\xd7n\x93\x87Q\x17\x8f|\x10e+;:Ӕ\xe8%Ei^SzHKV\xc8}\x9c\x9d\x05\xcav}t\xf6K\xe1\x84\xfcz\xe5\xe2E\xb9\x98\xe3J\xfa\x84p\x9c\x8beK0\xe9\xebV\xb1\xdeEdFg\vȢ\xb3\xa2H\r\t|\xb2\x12\x89۩\x125\x90*\x91\xda%\xed\x17\x01\x98\xbax\xa5D\xc1Z\xfa\x97\xa8\x1c\x16}\x00\x00 \x00IDAT\u007f\xb0V\xee\x0f\xd5\x05\x95-\xcdu\x913M\fDž7\x1c\xb7\xda(\xd1\xce\xf5\x17\xff \xb3V\xee舴\xb7#\x1eX\xa2lוH\xed\x13픇j'\xc4\xdd\x1b\x94M\x1b\x1e\xe1b\xd9\x12\f\xba\x89\x8e\xc5\x1d\x9bU\"\xdfi-e*\xd1\xea\x8c\xc1K2s\x8bD\x00\xa6.^)Q\xe0\xa4\xf2v2 \x8aM\rJ\xb2\xde\xf5y\xa2g\x85\x8b\x8e[m\x94h\xa36%\xf4\x90\x9c^B7Y\x94H\\C\xe7\x89\xde?\"<qQ,ݦlٶ\x99\x8beK0\t6\xa8\x04E\x1eV\x89\xb2\xf5\x94\xa9D\xf35\xfd\xbaW\x04`\xea\xe2\xb1\x12\xb5\a\xa8\x05#\x1dn\x9c\xadt\xfd\xde\xd9\t\xe1\x17b8\xfcV\xdb>\xd1/\x14~'\xda(\xd1\xe1_\x8b\xe2\xee5Tˎ\xd2{g\xbb\xd7ӹ\xa0+\xebws\xb1l\t\xce(J\x148m$\x15\x14%*\xa3JT\x98Ѯ\xd0\x1f!;\x00S\x01\xaf\x94\xa8Y\x1b\x9d5\xd3\xe7\x89ho\xa8\xd9\xfd\xe7\x89.\x14\x94R\xc9xl\xaf\xf2\xa9{G\xb7\xcdV\x1b%:\xa1\xce\xef\xec{Z䕨\xb4T\x14\u007fO\xf7\xbd}\xb7\xbc\xf5J)U\xa2\xe3J\xec\x11u\x9eȈeKp&7W\x14\xfbH-M\x9aJ\xe4\xdf*7\\6U\xa2FuWY\xb9mf\x00\xa6\x06\xee*\x91\xe9F}~\u007fmgOg\xed~z\xf3\xac'\xd0\xdc\xdd\xec\xc53\xd6/\xe7o8|\xfc1\xe1\xb0\xf2a)\xb9Ǻ\xf5\xd7\xf4\x19\xebg;:\xe4~\xce\xc5W;:\xf2\x1f\xe9\xe8\xa0\xf3\xd8Oܽ\xf3\xc8\xd1ݲ\x9a\xbcߑ\xf7ȫW\xdex$\xaf\xe3}\x91\x8a̳G\xbf\xba\x8c\u07ba\u007fV\xd8\xfd\xd2n\xf5\x19\xeb\x9d\xc2\x13/=!\xec\x14\xf9X\xa3\x84Ѱ\xddWQ\xbf\xc8\xdf#^jUn\xa3\xa9z\xb90eGy\x0e\x89\xaf\x92;\x92\xf7\x93յ\xf5E\xc4\xf5\t\u007f\x00\xc6\x11w\x95\x88q\xa3\x1el\xab\xab\xaakSoX\xf76\x06\xea=q\x85~\xfb\xe1\xb5\xcb6k\xbf&\xabJ\xa9\xb4nݭ\xcd\xe7\xc8î7\xb4\xa4\xa2Z'J\u05ec(=N\x9f\x11\x12\x84\xbc_.\x93_\x1f\x95\xb7^|lU~\xe9kJ\tG7\xe4o>\xbe\x96v\x84\xae\x1cڨ?O\xc4\xc6\xea%\x8c\x86\xc1\x92\xe4ąm\xa2x*N\x99\x0fR\xf5\xb2+71i\xf1W\b)\x96Ӎ\xb9)\xc9\v\x0fF-\x03\x80I\x8e\xbbJ\x04\x00\x00v@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=SA\x89V\x92\x94B\xd7\x17/\x02\x00\xb8\xc8TP\xa2\xde檬\x14xW\x000\x8dq]\x89\xecܨͭ\x91h&\xa7\xa2\a\x00\x00\xa62n+\x91\x9d\x1b\xb5\xb95\"m\xa45z\x00\x00`*\xe3\xb2\x12ٹQ3[#\x02%\x02`Z\xe3\xae\x12ٺQ3[#\x02%\x02`Z\xe3\xae\x12ٺQ3[#r\x8a\xb8\xeeA\x04\x00p\x0fw\x95H\xb4s\xa3f\xb7Fb0%\xa7\xa5\xc7u\xf3\x0f\x00\x80Kx\xa5D\x8c\x1b5\xb352\a\t!K\x1db\x00\x00S\x15\xaf\x94\x88q\xa3f\xb6Fd %\xa3\xa2\xd9\xe2\xd2\f\x00\x986x\xa5D\x8c\x1b5\xb35\"m\xa4)z\x00\x00`*\xe3\xb1\x12\xb5\x8fZ\x89p\xef\f\x80i\x8cWJĸQ3[#\x02%\x02`Z\xe3\xae\x12ٻQ\x9b[#\xd2\n%\x02`:\xe3\xae\x12ٻQ3[m\x19\xecm_\xe9\xf3ĭ\x1a\x00\xe0\x0e\xee*\xd1ظ\x97\x90\xf4z\xa7 \x00\xc0\x14f*(Q_{\x8fS\b\x00`J3\x15\x94\b\x000݁\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\\W\"\x1b7\xea\x81`m\xa0\xfeԥh\xb9\x00\x00\xd3\x1a\xb7\x95\xc8ƍ\xfalU}g\xf7\xb1\xaazH\x11\x003\x16\x97\x95\xc8\u038d\xba\xb9\x96\x1a\x99\xf5\a\x8eE\xcb\b\x00\x98θ\xabD\xb6n\xd4u\xb5꾆\b\x99\x00\x00\xd3\x1ew\x95\xc8֍\xba\xb7G\xd9\xd2\xf2T\xe4|\x00\x80鍻J$Fr\xa3\x16\xc5\xcb5A\xfb\f\x00\x80\xe9\x8fWJdq\xa3\x96\xbbDU\xfd\x91\xb2\x00\x00\xa6;^)\x91ōZl\xad\x84\xd74\x003\x17\xaf\x94\x88w\xa3\xbe\xd4\x1c\bE\xca\x00\x00\x98\xfex\xacD\xaa\x1b\xf5@C5\xec\xcc\x00\x98\xc9x\xa5D\xac\x1bu\xff\xfe:\xea\xbah\xce^\x03\x00f\x18\xee*\x91\xad\x1b\xf5\xe9\xc0\xfe\xee\xde\xdeޖZ\xa7\xdc\x00\x80銻Jd\xebF}\xb0R\x05O6\x020cqW\x89\x00\x00\xc0\x0e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xfe\xe2+\x00\x00\xe05\xb7\xd3'\x02\x00\x80\xf1\x01J\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbcg\x14J$\xee\xc8IIH\xbd\xe7\xa9\x11\xa7\xc0\b\fҌ\xb5d\xb9S\\\xec(%א\x95\xe6\x96\xd1\x1c\x86\xcb0\x16\xf6\x90\"\xa7\x10\x00@L8+QU\"QI\xefq\n\xb5eO\xe2\x904:\x89\x88\x15\xb5d(\x11\x00S\x1fG%\xdaNHn\xcbՑ\xb3Us\x89\xaf\xcd)؆\x11B\xa8^\xf4\xee\t:EƊV2',\xa39\f\x94\b\x80I\x87\x93\x12\x05\t٣\xa6\x86rI\xf2\x9f\xa2\aۡ\xe9\xc5\x04`\xa7D\xa3!\xe6\fV\xa0D\x00\x8c7NJ\x94A6\xe9ɡTR\x12-\xd4\x1e(\x11\x00\xc0\x11\a%:F\xe2.\x19\x1f\xaaɜ\x11z!\u007f\xb3\u007ferR\xceAu\xe3\xe0\x96t_\xf2\xbd\xed4YE\x02\xed\x19\x89\xd9\x03\x92Ժ:\xcd\xe7\xcf*\x13%i\xab2\xc5ԫO\xe0\xf4\x15\xcfMH\xbeW\x19\xe5Ր\x8a?m\x99\xebK/\xbbJ?\x9d\xfdRzB\xd2\xc2*nV<b\xb0\x82^\xb2,,\xe2\x964_\xc6\x03Ò>OdW\xd8٭\x19\xbe\xe4\xe5!\xa5,&\x03[W\xfe(\x96C2\xe7\xa9*\xd1<\xb2U\x02\x00\x8c\x0f\x0eJ\xb4\x9d,0?\x88\x84\xb4)\x17\xf2\x1c\xdf\xe2\xdc8RL\xb7\xb5\xfb\x89o~\x06!\xe5\x12U\xa2-\xb3\t\xf1\x8fH%\x84\xa4\xcdO\x95_\xaeJ\xf5\xab\tY\xb9zP\x93\x88\x86\x042g\x81\xbc\x83^\xc35dS\x1aIJ&$KV\x8c\xbe$\x92\x9c\x9dI\xc8]̱#\x06\xab\xe8%אy\xa9$U\xde5oDS\"\xbb\xc2Z\x12ɜl\xb9\xb0\xa0\xc4g`\xeb\xca\x1f\x85?${\x9eP\"\x00\xc6\x1b\a%\xba\x87\x1b\x90\xcd%U\xf4\n%\x99\x03\x92ԝL\xea\xe5\x9eB\x12\xd9zM\x92:\x93I\x13U\xa2\xb8\xcc涧\xa46\x92xR\x8e\xee\x9cC\xbee\x8c\xa1\x14\x898\x1dG\xca\xe5˺\xd1G\xaa\xd5r\xe4.J\xd0G\xea$i9)\xbb!\xefO\"-\xc6\xc1\"\ak\x18\xa33\x92\xd1%wm\x12h}\x94\xc3\xd8\x14vi\x0e)\x1b\x91n~\x93̾\xcag\xe0\xea\xca\x1d\x85\xfb\xc0\x9d\xa7\xaaD\r\x81N\t\x000>8(Q6\xd9n\xfd$_\xa1}\xf4\xc3A\x92A\x87HK%\xf5C&U\"u\xcf\xfdZ\xa6\xfb\xa9\x8c\xb1J\xb4R\x9b`\xa9%)#\xb4\x9c~\xfa\xa1\x98v\xae\xd2\xe5a\x96L\xa0\xb0\xd58X\xe4`\rS\x89\xb4]%\xdaal\n\xdbN\xeeQ\xde\x17\x92Z>\x03WW\xee(\xdc\a\xee<1O\x04\xc0x\xe3\xa0D\xf3\xc9\x0e\xe6S\x0e)\xa3W\xe8B\xe5ÈO\xbeR\xe7\x92f\xf5C\x1c\x19\x90\x95(C\x8d\x1bQ\x87P;\xe8\x15\xcb(\xd1H\"\xe9R\xf7\xcf!!\xb9\x9c,\xe5C\x80N /&9\xa1\x1b\x12K\x94`=BW\xa2y\xe6.E\x89\xc2\v\x93\xb2\xb4z\x0e^\xb2d\xe0\xea\xca\x1d\x85\xfb\xc0\x9d'\x94\b\x80\xf1\xc6A\x89\x96s\x93!\x19\xa4\x82^\xa1_Q?\xcd#\xadÄ\xcc\xcbQH m\xb2\x12ݣ\x05\x8e\x84\xea\xcaW\xa7\x13\xb2\x8eS\xa2\x01B\xb4Y\x9e\x85\xf2\xc0\xa8F\xebf(\xe2\x11\xf2\x11\x92\xb4\xbaޜ\x8f\x8e\x16\xac\x1fDW\"uW=}\x8fP\x98\xe4S\xfb7\n\\\x06\xae\xae\xdcQ\xd8\x0f\xfcyB\x89\x00\x18o\x1c\x94\xa8\x8c\xe4\x98\x1f\x86\b\x9dy\xa9ѻI9\xe4\xa0HL\x9ad%Z\xad\xee\t\xa4\xd2\r\xf3\x17Z\x94\xa8\x8f\xc4k%-%U\x92~3]\x15\x97\xbeu~9K|\xc95\xfd`тU,w\xf1M%\n/\xec\x1a!\x83F>.\x03WW\xee(\xec\a\xfe<\xa1D\x00\x8c7\x0eJ\xd4E\xe2\xccK\xb8\x9e$\f\xd1+\xb4L\xfd\x98E\x8e\xc9\xdat\xc6\f֕蛄|\xa9\xa1{X\xaa\x88\xd8'\xcaQ\xba9\xbc\xb8\x8ct\x96\xcf#\xe65\x1e=X\xc9\x10Q\x89\xc2\n\x93\b\xd7'b2pu\x8d\xa8D\xfcyB\x89\x00\x18o\x9c\x9el\xcc4\xaf\xba\xe1\f%]\xa3\x8d\xc1\xae%\xc8\xfd\x8c\x14z/\x89\xd29pCW\xa2\x1bsH\xad\xb2m\x8bE\x89n\xcc\xe6\xa7~\x98\xcb~ \xa4\xa4\xabI\xbc>\xc1\x13%X#\xa2\x12\x85\x17&\x9f\x86\xfa+\x90\xe6\xc5\x01.\x03_\u05c8Jğ'\x94\b\x80\xf1\xc6I\x89:\t\x9d\x1b\xa2\\[J\x12\xcfK\xf4\nMP\xbaI\xfb\xe9\xa3F\xc5$\xfb&\xfd\xd0J|Wu%\x12\xb5[h\xc3i\xf4\xb3ݽ\xb3:\x924b\x1d\xfd\xd0'\v\xa5~\x12g</\x141X'\x92\x12\xd9\x15\xb6U˷\x94|\x93\xcb\xc0\xd75\xb2\x12q\xe7\t%\x02`\xbcqR\"y\xd8B\xeej\x1b\x92\xc4\xfa\f\x12\xa7\xdc?\xaa!d\x81,E\xad\x89\xf41\xc7~\x1f)\x19\x96\aq\xc9d\x8b1:\xbb\x91\xa4Ls_^L\x94\x89\x98\x04\xd2t\xed\x86z=wǓ\x1d\xb284'\x92\x80\xe5J\xbf\x8b,\x96\xd5cx\xb51\xe7\x1d-XG-9\xbcOdS\xd8@\"\xd9qC\xbaYA\xfc\"\xdf'\xe2\xea\x1aY\x89\xb8\xf3\xc4\xf3D\x00\x8c7\x8eJ$5諂\xa4)?u\x90\xafЌ\xd9\xf1\v2\xb4\xbeR\xb3\x8f\xccΖ?䎘\xf3D\x01Bҗf\xc7%oWn\x97g\xcbY\xdb5\ti\x88'I\xd9i\x84^\xce\xfc\x95~>\x99\xf8\xb2\xe6'\x92\xd4\x01\xe6\xc0\x91\x82uԒÕȮ\xb0\xa0\x8f$g'\x93\x84\xa0\xa5\x13\xc5\xd55\xb2\x12q\xe7\x89g\xac\x01\x18o\x9c\x95H\x12+r\x92\xe2R\xee\xa9\xd5\xeeD\xc9Wh\xef\xd29\xc9KO\xa9\x1f\xcfnJ\xf7%f\a\xe88ȸw֖\x9b\xe2\xcb\xda\xfe\xa7a\x1f\xbdc՟;;\xe9\xa0.!}Ei\xbe\xb4\x95\xedZ9J\xb0\xbagpK\xa6ov\xd6v\xf6\xce{\xe4`\r\xb5d\x9b\x19k\xbb\xc2\xfa\x8b\xd3\xe2S\n{%\x8b\x12qu\x8d\xa2D\xecyB\x89\x00\x18oF\xa1D\x16\xf4+\x14\x00\x00\xc6\v(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x9eؕ\b\x00\x00\xc6\x1b(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x9e\xf1R\xa2\xe7\x84o\xdb\xef\xc0\xad6\x00\x80#P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\xcf$Q\xa2\x96\\n\t\x8f\x98\x18\xcamq\n\x01\x00Ln\x1c\x94\xe8E\xe1\xb9?\u007f{M\xfe\xc6W\xa4[/n\\R\xf0\xddO\x95\xad?ߵ6/\u007fÓ\xff\xa6|x\xe7\xa1U\xcb\x1e\xfc\xad\xa6D\x1f\u007fw}ު\x87\xdedJ\x90\x95h\xa00ٟ\xd3 ѕ\xa5U\xa71\xa9\x82\xb3\x96\xa5\xeb\x95UHc'\x10\xf7\xad\xa8\xfbK\b!\xfe\x81\xa8!:\x9d\x84\xe4JR\xb3\x9c\xe1T\xe4\xa0\xf6TC\xfa\x86\xb6\xa4\xf9\x97ߌ\x1c\n\x00\x18\x15\x8eJ\xf4\xedU\u009a%\x82\xf0\xca\xe3B\xfe\x1aA(\xa5\x1b\xbf-\b\x05\x1b\v\x04a-ե\x17臼\xbc\xaf*J\xf4\xe62!\u007f\xe3zA\xf8\xbeYB\r\x99\x97L\xe6e\x12R(IW\x13\xd4U\xa3\xa5L\x12b\x8f\xb2?\xaeA\xba\x1dZ\xe3k\xa2\xed\xbe\x1c\n\xd5j\xcb\xf3;1r\x92\xf8C\xd2p399\"q\x9c\xea1ӭs\x9a\xf5\xe4Ҵ\xa7J\x12\x87$\x00\xc0\xed\xe1\xa8D\u0086\x0f\xa5뻄\xfc\xfc\x1fߒ^\x11\x84\u007f\x95\xe5Fȧ\x9d\x9ew\x96\t/H\xd2o\x85\xbb_\xbc%}\xf2\xa0@\x95\xe8\xe3e¾\xeb\xf2\x9eU\xc2+F\tԅ\xbe_\xeeG\xf8\xa9\x89\xc6JRN\xb7\x9d&\xe9\xecA\xce\xfb\xca\xf5\xe4\xd5\xc5c\x1a\xa5\xed\xf0]\x8e\x1e\xd0=J%\x92\x86I\xb1\xdc]\x1b$Ö\xed\vm\x17\xd1\x1f\"\xb2\x04ZC\x01\x001\xe3\xacD\x1f\xcao\x1f\n\xc2s\xf4c\xa9\xf0\xa2$\xed\xbb\xfbIe\xdf>\xe1qI\xda%\xec\xa3\xe9O\xd7P%\xda'<\xa4\xec\xf9\x89\xb0\xc1(\xa1Fs\xcf\xd8O\xad\xaa\x83\xaa\x04\x95\x11Cz(%s\x19\xbf\xc5>i\f\\\x9bˏ\xf6\u0088A\x89N%\x8d\xd8(Q\xce:\xbb\xe8\x01\x82)*\x00\xc6\x03G%ZO߮\v\xc2\xff\xa2\xef\xbbh7H\xba~]\xd9\xf7\x03\xe1\x1f\xa5[+h/I\xa2\"$+\xd1Z\xad/$\x87\u007f\xa4\x97PC\x16)\xef\xc3\xd4Q~$\x99*\xc2\xcdT\xd6\xc7P\xba\x91\xb4]\v\xcdj=Cζf)\x0ed\x03\x85\xa9\ti\xcb\x15\xbb\xa0\xda\x1c\u007f6ݶ\x95$ԕe\xf9\x97^\xe6\x92\n;\x12-\xa3)\xbe\x04F\x89\xf4\xc2$)\xb44=!uy\x86\x92>\x98;'\xeb\x01\xaa\x87\xc3d0\xa7YW\"=\xb6E\xf3\x14\xa0~\xb8C\x89\x84\xc45ҽ7Rԭe\xd4|\x88\xc8\xe2Z\xa18\xc4\x02\x00b\xc7Q\x89\x1e\xa4o\xff.\b\x9f\xd0\xf7݊\x12I\xd7\xdfy\xf1\xfb\xbb\xd6\v\xc2n\xe9\x13APe\xe9Dz\x12}*\b\x1b\xefS\xc8\x13\x8cIk\xc326\x83\xba\x12m!\xf7\xcb#5\x92\xcd\x1e\xa3\x87hv=b1\x99/\xff\xb7\x8e\x8aGgRN\xa0\xbd\x82T\xcb\xc9\x12ߎ\xd6\x1d\xbebI\xeao\x8c'\xa9\x15UI\x85\\R!\x14\xde\xe7aJ`\x94\xc8(L\xde\xf4\xa5\xe6\xf6\xbaTB\xdd\x197\xc5\xdd\xdfZ\x93\x9asSQ\xa2\x9a\xe5\x9a\x12\x19\xb1\xd7B\xa1\xac\xbbB\xa1\xd0YZ\xc2\xe9Pȧί\xf7\x86\x1aIE($Ҁ\xf4-\u007f\x92\xaeV$\x870T\x03`,8*\xd1\xc3\xf4MV\"\xe5F\x99\xa2D\xb7^X#\b\xc2\xdd\x1bKe%\xfaH\x10\xd4\xc0\xd7e%\xfa\xb3`bL\x14Ր\x1djb>i\xa6\xee֩7\xa5\"M\x1e4Z\xe5ΒƱ\x04\x92\xd0F\x13#\xe9\xf7ʝ\x9c\x1bMC\xf26B\xdd=ک\x8eI\xbed\xb9\x13T\x9c*\xf1I\x99\xcbĘD\xd6`J\x90L%b\n\xabM\xa5\x1aT\x9b,\xd1\x1a4(1\x8d\x8a\x12]\x9d}UQ\"\xf6\xc0\xfc\xe8̯\xdf\xe93Gg\x15\xb4\xbf\xf4%\x871\"\x00 \x02cP\xa2焻\x1f\xff\xf1o?\x95\xdfw\xd3n\x90zc\xff'j\x9f\xc8\x18\x94\x19Ԑ\a\xd4D\x069)ѻf\xa7F\xfc\xf1ܴt\x90\f\xaa\x89\xa12_:\x99\xeb\xdb.\x8bG\x1b\xe9\xd5wo\x9a\xaf\xbcͧW\xb9\x8f\xbeT\xf8$>)Q%\xb2\x0e\x8b\x98\x12$S\x89\x98\xc2Ĺ\x99[\xeb{%*GE\x997(\xe9%\x8a\x12I˫\x15%b\x0f\xec\xa8D\x97I\xbf4\x92tR\x02\x00\x8c\x85ؕ\xe8\xfa2:m-\xf3]Y\x89n\xad\x12\xdeQ>|\x9f\xce\x13\xadѻB\xef\xfc\xf1\xdf\xf5\x12j4\x87\xb2!\xd5#\xba\x82lmc=\xcb$\xdaO\xd2FN\x81Ժ~ҿ?u\x0f}\xf2Ș\xf7Y\xa4>\x19\xb9r\xa1\xfc\xa2\f\x8b4%2\x93\x12U\x1a\xee\xb1\x00\x89+A2\x95\x88-l\xa8n\xdd<\x92\x16\x90T\vG\xcajU\x89\x9a\xb3\x15%bc\x1d\x95HZ\xfe\x80t,\xf9\x86\x04\x00\x18\v\xb1+ѿ\xa9\xb7ӤO\xd7\n\xbb$\xe9q\xe1\x1f\xe9\x87\xeb\xeb\xa9\x12}[\xb8\xef\x16\xfd\xf4s!\xff\x13\xbd\x84\x1a2[\x994\xdeC\x94.\xc6 I\xdfj\x19I]\xf3\xe9\x17\xf6\r\xe5\xde\x19\xbd\x9cO\x12\xe3\xf9\x9d\x92L\xe5-S\xe9\x13ER\xa2\n\x9fu\x82\x86)A2\x95\x88)\xec4\xbd\u007f7\xdc试\ay\x99=\nWU%\xba6\xa7\x9d*\x11{`U\x89\x1a.\xa9\xa5\xd9)QKꍒM\x12\x00`LĮD\xff\xbeB\xd8'\xeb\xcd\x1f\x1f\x14\xe8=\xfb\x8f\x96\b\xcfݒ>ݥ<O\xf4a\xbe\xf0\xb8<X\xfb\xed*\xe1\xbbF\t5\x84d_\x96\xa4&\x9fv\xd1\xe6\x12\u007f\x92\xe5>\u05faL\xe3)e1Y\xbd\xd75\x9c\xb6\x98\n\xd2W\x94\xfbR\xf4NU#i\x95\"+\xd1\xcdy\xc6OJ\x06\xbfu\xdeZ\x82d*\x11SX\x059F\xb7,\xdeB炔\xb1ݎ=\xaa\x12I%ET\x89\xd8\x03K\x8b\x17Kҟ\xf4!\xa0\x9d\x12\xddHmI\x89\xf2\\6\x00 \x1a\xb1+\x91\xf4#AX\xff\xe0?\b+\x9e\x146ʛ^\xc9\x13\xd6\xfcC\xbe\xf0\xb0\xf2\x8c\xf5\xebK\x84\xfc\xfb\xd6\v\xc2\u05ee\x1b%Ԑ\xa5\x89\t\v҉>q]O,\xbf\xf4\x90\xa4\xb3qU\x92\x95S\xb3\xe7?\xd5v?\xa9\x97\x93\xc5q\xe5\xad\xe5qŲL\x85\x12J\xba\xa4\x9e\x92\x84\x90\xc8$it\xb5\xd9\x01Z\xad\x8f\xfd\xcc\x12D\xfa\x8cuu(t\x89-LV\xa2\xa4\x8a\xd6`\x89r㮜\x145\xb7\x94\x90\x83\xf4\x19\xeb\xe6a\xa93Q\xb9wf\xc6Rͫ\n.\x9d#\x1f\xecFW(\xe4+\tћd\xea\xbd3\xfd\xa6]y&\x06g\x00\x8c\x951(\x91\xf4\xe6\xd7\xd6\xe4ox\xf2\x93O\xf3\xee\xfeX\xfe\xf4\xaf\xbb\xd6\xe4\xdf\xf7\xe6+\xea\xef\xce>z|}^\xfe}/\x98B$+Qy\xdf\xd29\xfeEm\xda\xe7a_ؔ\x8e\xb4cv\xd8&i`]z\xd2\u00a0\x92ܟ\xad?ODHB\xff\x1c\xf9u+\x93\x94w\x84\xfcۍ|\r\xa9u\xd6\x12J\xb4i\xa0\"\xb60\xe9\xe0\xe2\x8a\xf4\x84\xb4\xc5\xea\x13\x04\xed\xf7\xa4$\xd3*v*\x8f\x04\xdd\xccM\xbb\xc9\xc5J\xd2\xc8\xfd)\xfe\xbb\xba\xe5Dw\x9cZX\x1d}8\x8a\x12\u007fV;\x1c\xc1\xe0\f\x80\xb1\xe2\xa0D\xe3\xcfy\xfe\x97\x1e*e\xbe\xdby\"\xb0\xc9W2\tz#þN\xa7\x10\x00@\x04\\W\xa2\x1d\xe4\x9b6[\xab\xd3\xc7\xf4{3\x85\xa1\xb9\xd1\u007f\x8a\xef\x12M)\x93@\x0e\x01\x98\xa2\xb8\xabD\xfd\x83M\xb3}\xa2S\xd4\x14\xa4\xa2SZZ!\x01\x00ƈ\xbbJTH\xc8m\xadD4Y\x19!9[Ӱ8\b\x00c\xc6]%\n$\xa6NG!\x92\xfbDI\xf7\x9cu\x8a\x01\x00D\xc4]%\x02\x00\x00;\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xc6I\x89>\xe6~\xdf1\x1a\x873\x00\x000\x18\x17%\xba\xf5B\xfe\xa7\xe6'(\x11\x00 F\xc6E\x89\xae\xeb+7*@\x89\x00\x001\x02%\x02\x00x\x8fgJԒ;\xb6\u07fcnqg퍡\\8\x99\x01\xe0\x1eNJ\xf4\xd1\xe3k\xf3V\x94\xfeH\x9d\x90f\\\xef_\x14\x9e\xfb\xe4\xbbk\xf3\xd6?\xf9\t\xf5:\xa3|\xa8g\x91\x95h\xa00ٟC\xfd2\xaa\xc9<uc\x85e}\xb4\xc0\x18\u007f\u007fv\x86\x94K[I\xdc\xed,\"2:\x02q\xb7\xfd\v\xff\xbe\xa5sҊ:\xd3\xfe\xa4,\x90\xe4\x1f\xd07\xb7\xa7\x8eZ\xe4Z\xe6\xcd^М\xd3\xea\x14\x06\xc0\x94\xc7A\x89>\\&\xac\xbao\x83 |\x8d\xaeOͺ\u07bf(|\xb7@X\xb6J\x106\\\x97~\xbcK\x10\x1e\xde\xf5\xb1\x9e\xa7\x86\xccK&\xf32\t)\x94\xa4\xab\t\x9a\xa9k&\xbf>\xda\xfe\xb8\x06it\xb0\x86\xf42ų\xffD\xd7ndd\x8c\t\xb0\xc4\xde\x1e\xad\xf15N!\x06\xb6\an\x9f\xb3\xb0\xbe1\x9b\x903\xd2e\xbah\xa4\xbe\xb6\xa3\xd4:\xc7\xea\x88\xc4c\x16\xb6\x9f\x14\xb7l'd\xf4\xf5\x00`\xaa\xe2\xa0D\x0f\vO\xcaݡ߮\x10^\xb7\xb8\u07bf(k\xd0;\x92\xf4z\x1e5\xfa\xb0\x8e\xceHF\xbf|!\xfaI\xad$\xadT\x8d\xa7O\xf3룝\xf7\x19v\xd4W\x17G\x1f\xa5\xf1\x86\xf4\x03\xaa\x8f\xa3\x8fQ\"&\xc0\u07bc~\xac\xec\xf0]\x96F\x89݁\x87\x92V\x8fHҵL\xd5\xefv\xd4v\xd8La\x03ʊ\xbbeP\"0\x03pP\xa2\xf5\xea\xa0\xebG\xbb~nq\xbd\u007fQ\x1b\x8e}\x9b\xae\x1a\x1b\xa6DJ?h?ɠff\x8a\x04\x95\x11Cz(%s\xaf\xe9\xc9>\xad\xd3\x14\tސ\xbeD]݈U\"&\xc0\u07bc~\xac\\\x9bk]p;\"v\a.OT$\xb6\x8a(?ҏA\x89\x8c\u008aS\xa9\xf5\xc0\x19R\x1b-\x1a\x80i\x81\x83\x12}M(}G\xb7.\xe3\\\xef_\xa4r$\xf3\x02]\xe8ڪD\x8b\x94\xf7\xe182@\x17{\x96/\xc1\x9b\xa9j\xcf@\xe3F\x92\xb6\xeetMV\xeb\x19r\xb65\xab\xd6bt\xaf\xdbԳ\x86\xf4\x94\xc1\xf8\xaf(\xef\xbe\xedZ,\x13\xc0$\xb7\x92\xf8\x9aM\xe9)+\a$\v\x03\x85\xa9\ti\xcb\x151\xd3=\xef\x99\x03\xf3u\x90;E\x89\x16\x13\x12>@/\x81\xaf\xa4^u)S\x9dZ\xbfZ\xa5\x14\xa2+\xd1P\"!q\x8dZyz,S.[X\x8a\xdaJ\xfb/\xb1G\xb3o(\x00\xa68\x0eJ\xf4N\x9e \xac\xd8\xf5c\xaa3\xbc\xeb\xfd\x8bZ\a\xe9E;%R\x9d}\xa4\fj伅\xdcOm|\xb2\xd9R{\x88\xb6\xe4\xb3XL\xe6\xcb\xff\xad\x13y\xa3{æ\x9e3\xa4\xa7;\xb4\x01\x93\x8f\xccklI+\xe4\x1c\xeb\x99$-,cOE\x86\xdf\xd2\xdd\xeaL\xca\t\xb4W(^؆\xe7=s`\xae\x0e2!k?\x86\v0J\xe0*iT}$\x8e\xb3\xdc6\xfaD\xa7C!\xbdGg\xc42\xe52\x85\r\x11f.ͮ\xbeL\t\x00Lq\x9c\xee\x9d}\xb8+_\x10\x84\xbco_\xb7\xb8\xdek\xa6\x1f\xaa\"Y\x95H3\x14\x9aO-\x16\xbbH\xeaM\xa9\x88p\x97e\xab\xdcY\xd28\x96@\x12T\xdb\x0f\xd3螱\xa9\xe7\a>\x97\x12\xb6\xaa\t\x1f] qS\xaad\t0\x93\xbe\x8ca\xf9RNϕXF\xd2\xef\x95\xfb'7\x9a\x86x\xcf{\xf3\xc0lR\xa2\x0e\xd3aS\xcbf\x00[\x82y`\xb3ꃄ\xbbCƎ\xce4\xbb4\xf64\xd9\x03\xeb\x85\xf5+G\x90FFF\"\u0557k(\x00\xa62NJ$\xcb\xcc;\xdf\xdf(\b\xffhq\xbd\x8f\xaaD\x0f\xa8\x89\fB}\xe23ɩ\x11\u007f<7-\x1d\xa4\xf6\x86\x94\xa12_:\x99\xeb\xdbN\x17^5\x8d\xee\x19\x9bz^\x89\xb6&h\xf9|\x9b$\xc3v\xd1^\x89\x94i\xa9Z\u00ad\xe8\xdaFz\xf5$\xebyo\x1e\x98MJT\x89\xc2\x1e\x160\x03\xd8\x12\xcc\x03\x9bU\xbf\x11o\xdf'\x92\f%bO\x93=\xb0^ذ\xa23E\xf2P\xedd\x84\xfar\r\x05\xc0T&\xba\x12\xdd\xfa\xa3\xeaz\xff#!\xef\xdfy\xd7\xfb\xa8J\xa4z\x1f\x0e\x11Bgd*\xc8\xd66\xdd\rQ\xa3K\xbf,\x03\xa9u\xfd\xa4\u007f\u007f\xea\x1e\x895uel\xea9\xa1\x11}\xfaS\x8d\xac\x01\xac\xbd\x12)\x17{'\xe7H-U\x13cއ\xf5\xbc\x8fhq\xdd\x1d\xee\xccf\x06\xb0%\x98\af\xaa\xae\xcd\x13\xddh\xd7\xca\nS\"\xf64mOH\x99'\x12\x9bI\xf9H\x84\xfar\r\x05\xc0T&\xba\x12}\"ܭ8.~(\b\xd7y\xd7\xfb\xa8J4[\x99\x13\xdeC\x94?\xe4\x83$}\xabe\x98s\u0378\xf7uC\xb9w\xa6\xd8\xf3\x98\x17\x18cS\xcf\x19җŝײ\x85]\xb8j\x80\x99\xf4)SUu\x8a\x95\xab\xc1IS\x98X\xcf\xfb\x88JT\xe1\xe3\xb2\xf3\x01l\t恙\xaa\x97\xfb\x95\xfa7\x11\xe5\xcdF\x89\xd8Ӵ=\xa1\xe24\xaa\x9cAz\x17\u07fe\xbe\\C\x010\x95q\xbcw\xf65Y\x8a>\xdd%<hq\xbd\xe7\x94H\xca\x13^\xb9\xae\xdfb\xa3w\xf1\xb3/S?Dm\xa6$\x97\xf8\x93,7\xa1\xd6e\x1a\x93\xacb\xb2\xe6:d^`\x8cM=kH/\xfa\x8cQ\b{\xe12\x8e\xf5fҗ6L\x9f\xe5Y\xacD\f~KU\xb0\xe1\xb4\xc5T\xf3\xbeR\xc6{\xdeGR\xa2\x9b\xf3\x8c_\xad\xe8%0\x01l\t恙\xaa\x0f%\x15\xcaG\xbb\xb9X\xd5\x10\x1b%bO\xd3\xf6\x84\x06\x94\xe7\xd0\xef\xa1Jd__\xae\xa1\x00\x98\xca8(\xd1ǫ\x84\xbc\r\x1b\xf3\x855t\x8a\x88u\xbd\xe7\x95\xe8>A\x10\xde\xd4\xf3Ԑ\xa5\x89\t\v҉>q]O,\xbf\xf4\x90\xa4\xb3qU\x96-\x9cѽaS/I\xa6!\xbd\xf4\x80>\xcf\xcd\xc52\x01L\xd2Gr\x9a곒\xd5\f\xab\xf5\xc1\xe1\xa9\xd9\xf3\x9fj\xbb\x9f\xd4K\x8c\xe7=S\x18_\xae<\x983\xbaPZ\t\\\x80Q\x02w`\xa6\xea\xc7\xfc\xb9\r-K\xe3C4_\xa8\x96T\x87Br?\xe7FW(\xe4+\t\x85\x86\xd9\xd8H'TM6\xb5\x96\xa8\xcfX\xdb\u0557o(\x00\xa62N3\xd6\xf4\xa7f\xf9\x1b\x9eT\a_\x8c\xeb=\xafD\x1f\x96\xe6\xaf\xf8\x89\x9e\xa5\x86\x94\xf7-\x9d\xe3_Ԧ}\x1e\xf6\x85Ϸ\xec\x98m\xd9\xc4\x1b\xdd\xeb6\xf5\x12cH\u007f5\xb1\xd86\xd6\b`\x93\xbe\aJ\x92\xe7\x16k\xbd\xad\x86\xd4:-\xe7\xc0\xba\xf4\xa4\x85A%\xa9{\xde3\x85\xf1\xe5\x86\xfc\xdaCOf\t|\x80^\x02w`\xb6\xea}K\xfdi\xab\xfb\xe5D\x896\x9fS$\xf7\x8d\xe2\xd4d\x1d\x1b\x1b\xf1\x84\x82\xf3\x12s\xdb\xd2\xdb\"ԗ?\x1a\x00S\x19'%\x1a\a\xce\xf3\xbf\xf4P)\xf3\xc5\xfa#\xd6r\xee\xe1H\a؇\xb0\xc7F\x93\xaf\x04\xee\xd2\x00\xb8\x85\vJ\xb4\x83|\xd3fkuz\x8c\xf3\xac\x9bbY\x0e䶕hh\xeem\xff\x14\x1f\x000j&Z\x89\xfa\a\x9bf\xfbD\xa7\xa8q綕\b\x00\xe0&\x13\xadD\x85\x84\x8cq%\xa2\xdb@\x9d\xd5\x05\x00L\x19&Z\x89\x02\x89\xa9\xae\v\x91:\xab;\xe8\x14\x05\x00\x984L\xb4\x12\x01\x00\x803P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=\xe3\xaaD\xfaB\x8e\xd1y\x8e.}\xad1:o4\x00\xc04\aJ\x04\x00\xf0\x9eqU\xa2\x0f\x9f{\xdd)D\x82\x12\x01\x00\xc2\x18W%\x1a\x1dP\"\x00\x80\x85i\xa7D-\xb91\xfe\xb26*[b\xf9\xd9-\x88\xc2diɡ\xdcQ{\x81\x8f\x85\xc9r\x9aS\x0f\a%\xfa\x91\xf0\u009b\xeb\xf3\xff\xe1#u\xa1\xa2U\x0fiˡ}\xb4o\xfd\x92U\x0f\xabk\\3;\xe8<\xd1\x0f\xb4\x85\x8b\xa4Dž'%K\xb6w\x1eZ\xb5\xec\xc1\xdfZ\x94h\xa00ٟ\xd3 \xd1u\xc1\xe6\xa9\x1b+\xb8\x95Ն\xb6\xa4\xf9\x97\x8f\xdaG'0\xae\xbfr;Cʥ\xad$.\xd6\x05L(\rt\x15\xa2\xd4{{\xa4qf\x13!t\x95\xb9*B\xac\xdf\xf9\xf6\xd4\t\xbd\xc6n\x8f\xc9Ӓ\x818\xfbU\x16ƥ\xf9n\xe34\xc7H0^[\xfc*>\xbaǹF\xdf\xd29iE\x9di\u007fR\xd6\xcc\xf2\x0f8\x85+t\x12\x92+I\xcdr\x86S\x91\x83\x98\xe6c\xae\xd8\x18\x1a\xd5Q\x89\xbe\x9b/\bˮKo.\x13\xf27\xae\x17\x84\xefӭ\xaf\xe7\v\xcb\xee[#P\x8bjn\aU\xa2?\nyʲjחQ\x93X.\xdb\v\x82P\xb01/\ufadc\x12\xcdK&\xf32\t)\x94\xa4\xab\t\x9a\x1dl&\xb7\xb2\xdaҴ\xa7J\x129\x8f\x8e(\xec\x8fkp\n\x89\x8a\xc5\xe0\xbex\xf6\x9f\xe8\xcfi\x19qc\x02NE\xbd6\x86\x1bȷ:\x1brug\xb7qCL\n\xd0\xc6\x18\n$YW8h\x9d\xa3\u007f\x17\xa3\xd7\xcc\x1d&YK2\x87h\x8d\xb7\xb5\xf76\x9b/\x16\xc6\xef4\xc7\x18\x10 ڂ\xa0$`\x93A\xc5\xcc\xd6>ga}c6!g\xa4\xcb4\xdb\xe8~&>r\x92\xf8C\xd2p39iY\x04\x9a\xad\x0e\xd3|\xcc\x15\x1bC\xa3:*\x91\xb0\xfe\xf57_\x94>^&\xec\xbb.wjVQ\u007f\x8f?/\x13\x9e\xbc.\xddz\x8e\xae\xac\xcf\xedP\ue755\n?\xa69_\x176J\xfc\xde\xdf\nw\xbfxK\xfa\xe4A\x81S\"\x92\xd1/7\x90\x9fZ.\xafT-\xabOs+\xab\r\xd1\xc5S\xc3V\xb6\x8f\xc0y\x1fgz\x1d;\xbc\xc1\xfd\x80\xea!\xc9.1\xc2\x04\xf0\xb1a\xf4)\x16e\x8b\xb2\xa2\x06\x8d\x81lUk\xeb9/K\x1e\x87\x9a\x8d\vW\x17G\x1f\x05O\xb2\x96d\x0f\xb1\xc3wY\x1a/\xc6\xf14\xc7\x16P\xed\xd3\x16IO\xe4\\\xad8\x8clCI\xabG\xe8\xfa\xeeꢃ\xa3vH\x1f&\xc5%\xd4\x1a\xc3z\x19\xda\xd77\xa6+\xd6\xc4Y\x89>\xa4\xef\xfb\xb4\xfb\xf3?\xa1&\xd4O\xd2\xf5\xf5%\xaa9/\xf2;\x14%zQݻKx\xc1\x92m\x97\xb0\x8f\xa6?]\xc3+\x91\xd2\x0f\xdaO2\xa8\x8b\x85\"Ae\x84\x95\x93\x012\xea\xfe\x9d$\x95̽\xe6\x14\x12\x1d\xde\xe0\xbeD]Y\x89\xfdb\xd9z\x1a٢^?\xfb\xc9m\xd6(\x8cBuy\xf0\x1d\xbaS\xad\r\x0e5\x1b\x17\xfa\x88\xc5`\xd7\xc2$kI\xf6\x10\xd7\xe6Z\xd7U\x1f;\xe3x\x9ac\v\x18\x19\xd0$e\xc0\xd2aa0\xb2\x95'*\u007f>\xaa\x88\xe2W\x1c\x83\x12\x9dJ\x1a\xb1Q\"\xfb\xfa\xc6tŚ8*\xd1z\xe5}\xad\xe6uv\x9d\xda/n\xd0>|\xfc\xf1-~\x87\xa2D\x9f\xe6\t\xd4\x0e$\x9f\xbe\xb2{o\xad\x10\xfeU\xf9\xb0\x8fS\xa2E\xca\xfbp\x1c\x19\x90F\x92i\xd3\xdcL5\x97\x89\xbd\x91\xa2\x8e\x81\xcb\xe8J\x1fq\a\xa5A\x1f\x9dK\xe2\xad\xe1\x19\xaf\xfb\x1bI\xea\xd2ӽ\xf2\xd8y\xc7@q\x86\xff\xde\x1b\x15r\xeeF\xa9\x91\x18\xeb\xfb+؛\xcb\xf3\x06\xf7\xf2\x1f\x81\xf8\xaf(\xef\xbe\xed\xe1\xa6\xf5Lr+\x89\xafٔ\x9e\xb2r@\xe2P\xaf\x9f\xe2t\xee\x10\x92\x14Z\x9a\x9e\x90\xba<Ú\xcd\xd6\xf6ވeK(W\xff\x10\x15\x95\xb3\xa7)\r%\x12\x12\xa7x\xc1\xf2g\xa1gccm\xe1\x03\xcc\xfa\x0eo\x9f\x97tW\x97\xba\x96\xb6AMV\xeb\x19r\xb65\xab\xd6˖4j\xc6|5$ۦ\xb6VgG\xa2\xf5\xaa5\x9b\x8f?!\x1d\x17N\xd3\xfe\xdf-\xcaY\x98\x98\x92\xe2\x90M\xf3\xe0\xbbZ5\xc2gӿ}\x11\xber\xc3d0\xa7YW\"=\x96-\xd7l>\xe6\x8ae\xb62\x85E\xfc\":*\x91\xd2\xc1\xf9T\x106ާ\x90'\xbc)-\x11\xfe\x97\xbe\x9fߡ>\xd9\xf8\xb0\xdcU\x92{A\x0fZ\xf6~B=\xd3(?攨LMdP\xa3\xe5-\xe4~j\x9dÌ;zC\x8d\xa4\"Dm,\xd4\xd1wW\x89\xcfb\r\xcfxՄ8\xd0\x00\x00\t)IDAT\xddK=\xda\\\xc2HScFVRFY1\xb9t\xb5(74,\r\x87\x16\x15\xb1\x83\t{sy\xce\xe0\x9e\xee\xd0z\xf1\xf2w\xbc\xb1%\x8d7\xadg\x92\xb4\xb0\x8c=\x15\x19~\xbe\x93\xd0GZG\xcen'{\xb8C\xc8\xff\xfa_jn\xafK%7\xf8l\xb6\xb6\xf7f,[B\xfdB\xa9+\xa3KʩgOS\x1eӆB\xea\x9fb\xee,\x8cl\\\xac\x1d\\\x80y\xb4\xa1\xcc\xd4@\xdbVBj\xb9`\xb1\x98̗\xff['zؒf͘\xaf\x86}S[\xab\x13\n\xef\f\x18\xcdǝ\x90\x81\v\xa7i\xff\xef\x16\xe5,L\fIq\xc86\x12g\xefKl|\xfb\"|\xe5d%\xaaY\xae)\x91\x11\xcbU\xc7h>\xe6\x8ae\xb7\x8e\xe2\x8b\xe8\xa8D\xbb\xe8۟\x05\x93W\xe4\x0e\xce\xc7\xfa~n\x87\xa6D\xaf\v\xa5\x92\xf4\xa0\xf0\x13\xcbޏ\x04A\xcd\xf3:\xa7DZWe>5g\xec\"\xa97\xa5\"\xc25\x97\xd9\xd7c}\xc9\fkx\xc6랺\x82\r\xe8\xd9r\xc8\xd2ae\xb4ڠ\xfe\xa5\x9coq\xe2\x89`.\xcf\xf67/%l\xd5b\xd3\xe4\xd27\xf1\xa6\xf5\\җ!\x1fh(=Wb\xe9S\xfe6(~$\xcc!jS\xe9?rm2\x9f\xcd\xde\xf6\x9e\x89eJ\b\xa5J\xdb}ۥTEt\x8dӤ\xf8\xf5A\x81Q3\xfe\xdc\xd8X;\x8c\x00&[\xb1bGWfQ\"\xb9\xc6\t$A\xed'yՒl\xcdX\x1b:ۦ\xe6\a\x12\x97\x89\xdd<\xaa\xde|\xe6\t\xb1L\xfci\xda\xff\xbbE>\v\x13]R\x9c\xb2\r\xf2\xe3&=\x1b\xf3\xed\xb3\xff\xca\xc9Jtu\xf6UE\x89\xd8o*_\x1d\xe3\xdbǍδ\xad\xa3\xf8\"\x8eN\x89>\xa5c/\x9d[\xda\xdcQ\xd8\x0eM\x89\xae\xaf\x10\xfe\xf8oB\xfe\xa7\x96\xbd\x9f\xeaF\xb1?\xe1\x94\xe8\x015\x91ANJ\xf4\xae٩\x11\u007f<\xdb{\x89\xa0D%z\x92\xf1\xba\xa7\x13M\xc6B\x8d9>Mr{\xe3F\xae5\f\xdd\xf01a|\t\x9c\xb9<۶[\xf5e\x1f\x15\x13\xec\xa8\xde\xd7\xca\xc4V-\xe1\xee\xf0\xf5\x91\xaa\xae\xd6\\?-\x839\x8487sk}\xaf\xe6zkd\xb3\xb7\xbdgb\x99\x12.\x91kw}iѰ\xfa'\xc58MJ\xb8\x12\xf1\xe7\xe6\x8b\xd0\x1d\xd21\x02\x98lj\x99\xfd\x16%\x1a*\U000e54f9\xbe\xed\xf4\x84\xbdjI\xb6f\xe6W#BS[\x95\xc8\xee6\xbb\xa1D\xc6\t\xb1L\xfci\xda\xff\xbbE>\v\x13]R\x9c\xb2݈\xb7\xed\x131\xdf>\xfb\xaf\x9c\xacD\xd2\xf2jE\x89\xd8oj\fJ4\x8a/\xe2\xe8\x94HZ\xa3M\xf8H\xef\xfc\xf1ߥ\xf5\x82\xfa\xa3\x8eW\xbe\xf6\x02\xbfC\xfb\xdd\xd9w\x85\x17_\x14\xfeњ\xed\xd6*A}\x00\xe9\xfb\x9c\x12\xa9\xa6\x88C\x84пp\x15dk\x9bn\x93\xa8a\xafDF\x92\xf1\xba\xa7}*\xa3ם\xa3\x8f\xa6G\xe2\xfb\xaaȎ\xb3q\x96\x99\x01\xb3\x04\xce\\\x9ei[ѧ?\xb0\x13f\x15-Y\x92j\x17\xb4\xd3tj\xa4(\xb3\x1bCq\xd4،=\xc4Pݺy$-\xc0g\xb3\xb7\xbdgb\xd9\x12|}I=I}\t\xca\x03\x1b9\xec\xa4A\xb8\x12\xf1\xe7\x16>\xc1\xc0c\x04\x98\xd9.\x13\xc5\x1dnآD\x81Ժ~ҿ?\x95\xb7\xafu\xb5%\xb9\x9a\xd9ׁij\xfe\xa2\xe9\x0e7\xe0\x93\x18%b*i2\xf1\xa7\x19\xe1\xdf-\xe2Y\x98\xe8\x92\xe2\x98M\x9b'\xba\xd1\xceec\xbf}\xb6_9\xaaD\xcdي\x12\xb1\xb11(\xd1(\xbe\x88\xa3T\xa2o\v\xf7ݢ\xef?\xa7w\xee\xf7i\x0f/>$<\xc7\xefД\xe8\xb7\u0083\x0f\xaa\x96\xb0\xdc\xde\xc7Uu\xba\xbe\x9eS\xa2\xd9ʈr\x0fQ\xb4v\x90\xa4o\xb5\xf4\x9c-J\xb4âD'\xd9\u007f\xcdk\xe6M\x8b\x1cc\x9c?\xaf\xf1\x9eE\xf3\x82\xf3$\x1e\xb3\x04\xce\\^i\xdb\x06E\xb2\xcb\xe2·\xc5r\x01fҧLv\xd5\xf1\xf7\x16\xd4y\xd6d\x9a\x979\xc4i\xfa\xd7p\xb8\xd1_\xcbe\xb3\xb7\xbdgb\xd9Jf\x05\xe6J\xe9Uj\x0e\xf34%\xab\x12њ\xf1\xe7\x16\xe5n\x9b\xc4\x05\x98\xd9n&*eZ\xfbD\xf2\x1fMz\xefL\xed\xd9yӒ\\\xcd̯F\x84\xa6f\x8fFk`7F\x1d\xad\x12M\xd4i\xda\xff\xbbE>\v\x13]R\x1c\xb3\x95\xfb\x95J7\x91\xabl6\xe6\xdbg\xff\x95\xa3JtmN;\xad.\xfbM\xe5\xab\x13U\x89F\xf1E\x1c\xa5\x12}\x98/<.\x8f\xad~\xbbJ\xf8\xae$}\x9c/\xfc@y\x9ehٟ\xf9\x1d\xfao\xf1\xd7\xe7\xe5\x15\xdc\n\xcb\xf6\xd1\x12\xe1\xb9[ҧ\xbb,\xcf\x13e_\xa66\x87Z\xeds\x89?\x89x\xe7E=Yo.\xb4(\x11\xe3u/\xb3.\xf3\xa6\x16l\xcau\xd1V\xdf1\xb2\xd5\xfa\xe4\x83Y\x02g.ox\xd2\xcb\u007f\xe1J\xc2c\xd9\x00&\xe9K\x1b\xa6Oi,V\"\x06\xbf\xa5~!\xd5\xeb'\xad\xaco\x0f{\x88\nrLɻ\x85\xcbfo{\xcfIJ\x95\\\x9e[(\x15\xe6.U\x0eb\xffWɨ\x19wnl\xec`\x85\xe5\xcf1\x17\xc0d[\x97J\xbf<\xc5a\xf3D\x92\xa8L\xd3H\u07b5$[3\xf3\xab\x11\xa1\xa9٣I7\xe7\xa9\u007f\xd8-\x8cV\x89\xc6\xfb4M\xec\xfe\xdd\"\x9e\x85\xde:\x92))\x8eن\x92\n\xe5\xab\xe5\xe6\xe2L.\x1b\xf3\xed\xb3\xff\xcaQ%\x92J\x8a\xc80\xffM\xe5\xaa\x13]\x89\"~\x11MF\xa9D\xd2\xebK\x84\xfc\xfb\xd6\v\xc2\xd7\xe8\xfd\xaf\xd7\xf3\x84\x15\xf7\xad\x12\xf2^\xb7\xecЕ\xe89A\xf9\xa5\x875\xdb+y\u009a\u007f\xc8\x17\x1e\xe6\x94hib\u0082t\xe3\x1e{=\xe1~\xe9\xa1\xcd\xc4k\x9d\xc8\xd4\xca=\xb9$\xbe\xa1\x9f\xb3\x86g\xbc\xee%\xe9l\x1c\xfd%\x045\x9f\xa7\xd3\xfa\xea\xa8\xfd[\xfe\xe4\x9bY\xfe=l\xa9\x91\xcd\xe5MO\xfa\a\xf4\xd9\xefH\xa6\xf5L\xd2Gr\x9a곒\xd5\f\xab\xb5\xe1e\x9f2\xabw\xcf\xf2\x92\x05\xec!*HREk\xb0D\xb9\xc9\xc7d\xb3\xb5\xbdgc\x99J\x96\x91\x80\x14\xa0w\x19\xd9Ӕ\xd3!_I(4\xcc\xd7\xcc\xc8\xc65\t}\x884iH\xe2\xe0\x02̣\x89i\xe9\xb5ͫ}\xe1J\xa4\xe1]K\xb253\xbe\x1a\x91\x9a\x9a=\x9a<\xa2\x0f\x93a\xb3\xf9\xf8J\xeaL\xe4i\x9a\xd8\xfc\xbbE>\x8b\xd5\xc64FO-\xa9>\xad\xa4\x1c\xb3\x1d\xf3\xe76\xb4,\x8d\x0f\xd1Z\xaa\x8ff\xd3\x1e\x8d\xf1\xed\xb3\xffʍ\x9c$\xcd\xc3Rg\xa2҅3c\x99r\x99o\x1fsŲ\xdf\xc9H_D\x93\xd1*\x91\xf4\xd1\xe3\xeb\xf3\xf2\xef{A\xbd\x11\xff\xe1\xe3\x05ykv}hݡ+\xd1\xc7\xe6\x9c6\x97\xed_w\xadɿ\xef\xcdW8%*\xef[:\xc7oX\xbb\x0f\xfb\xb8!\xfcH\xb22\xba\x8cW\xee\x14\x0e,\xf6'--\x0f\xf3\xafg\xbc\xeeeѝM\xb3\xf7\xaa\xe6\xf3\xea_\xbe\xd3\xc9ߔ\x02I\xdd\x12KDsyÓ\xfejb\xb1m,cZo&}\x0f\x94$\xcf-־\xb9\r\xa9tBC\xee\x01\x13\xfa\xfc}_Vj+{\x88\x83\x8b+\xd2\x13\xd2\x16wZ\xb3\xd9\xd9\u07b3\xb1L%[\xfd\xbdRߜ\x16\xfe4\xbb\xd54\xa9\xe3kfd\xe3\x9aD\xaed\x12\xe1[\xc4\x12`\x1e\xedjI\xba\u007f\xe9\xe9\x88J\xe4]K\xb253\xbe\x1aR\x84\xa6f\x8f\x16\xf2o\x97\xac\x98\xcd\xc7WRg\"O\xd3\xc4\xe6\xdf-\xe2Y\xe8\xad#\xf7\xad\x92\xe4C%\x0e\x8f.[\xdfR\u007f\xdajY\xb0\x95ߝQ\x94\xc1\x82\xfe\xed\xb3\xff\xcau\xcaaM\xd2\xcdܴ\x9b\\,S\xae\xd9|\xec\x15\xcb}'#|\x11M\x1c\x94\xc8m\xces\xbf\xf4\x18\x03e\xbe&\xa7\x90QQn>^\xe9\x8c9=\x15\x13c\xcc6.\x04\xc3\x1e\x98\x8d\x86u\xc6:\x16&\xb6%c\xafY\x93\xaf\xe4\x86S\xcc\x18\x98\xd8Ӝ\x01L2%\xdaA\xbe\xe9\x14\xe2@u\xfaU\xa7\x90Ѱi\x934z\xc6\xf8\xc5\x1ac\xb6\xf1\xa0!y\x8bS\bK\xec\u05fb\xc9Ķd\xcc5\x1b\x9ak\xffS\xfc\xdbe\x8c\xa792\xa8\x12\xf9\xa7\x1a3\x85ɤD\xfd\x83M\xb3}a]\xd6)@\xcc\u05cf\xca\x18\xb3\x8d\x03bjYL_\xfd\x98\xaf\xf7\xb1\x12s\x93\xb8V\xb3q\xc5<ͻ\xb4A\x92u\xf2z\xe61\x99\x94\xa8P\xfe\x17\x89\xf5\x9b8\tPg(cf\x8cټ`\xe0\x18)s\xa3\xaa\xb17\x89[5\x1bW\xd8\xd3\x1chQ\x19\x88\x96aF0\x99\x94(\x90\x98:\x05\x85H\x9d\xa1\f\xbf\x17\xe0\xc4\x18\xb3y\xc1\":\a9\xe0\x14u\xfb\xc4\xde$n\xd5l\\\x89\xfd4g\x02\x93I\x89\x00\x003\x15(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\xe7\xff\a\xfd\xa4@\x82&\x8eJ\xdf\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/chan2b.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x04Q\x00\x00\x011\b\x03\x00\x00\x00\x83\v\xcdh\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x03\x06\x02\b\n\x06\x0e\x10\r\x19\x1a\x18!# #$\"$%#%'$&(%'(&()'*+)+-*,-+-.,01/2313425747968:7:;9<>;>@=AB@CEBEGDFHEIKHKLJMOMPROSURUVTVXV,`\xae7]\xad[\\Z8^\xae8`\xaa]^\\:b\xab;b\xac<c\xad_a^Fb\xa1=d\xae?e\xb0ac`Kd\x9dAg\xb2cebefdCi\xb3fheLi\xafDl\xafMk\xb0Fm\xb1ikhei\x8fjliGo\xb3Ip\xb5lnkJq\xb6ll\x8dnolKr\xb7pl\x88Us\xb3Vu\xb4xp\x84Xv\xb6surZx\xb8uwt[z\xba\\{\xbbxzw\\}\xb7\x8evve|\xb8^\u007f\xb9{}z\x95wq_\x80\xba|~{a\x82\xbc~\x80}b\x83\xbd\u007f\x81~c\x84\xbed\x85\xbf\x81\x83\x80k\x86\xbb\x84\x85\x83m\x87\xbdn\x88\xbe\x86\x88\x85p\x8a\xbf\x87\x89\x86\xb3\x81_\x88\x8a\x87q\x8c\xc1\x8a\x8c\x89s\x8dË\x8d\x8ay\x8e\xbe\u0083Wz\x8f\xc0\x8d\x8f\x8c|\x91\xc1\x8f\x91\x8eƇT\x90\x92\x8f~\x93\xc4x\x95Ā\x94Œ\x94\x91z\x97\xc6{\x98Ȕ\x96\x93\x96\x97\x94\u074bE\x81\x9aė\x99\x96\x98\x9a\x97\x84\x9c\xc6\xe1\x8eA\x9a\x9b\x98\xe9\x8e<\x86\x9eț\x9d\x99\x87\x9fʜ\x9e\x9b\x9d\x9f\x9c\x89\xa1˞\xa0\x9d\xf6\x935\xa0\xa2\x9f\x90\xa3ȡ\xa3\xa0\xa2\xa4\xa1\x92\xa5\xca\xff\x952\xa4\xa6\xa3\x94\xa8ͦ\xa8\xa5\x96\xa9Η\xaaϨ\xaa\xa7\x98\xabѩ\xab\xa8\x9d\xac̪\xac\xa9\x9f\xaeά\xae\xab\xa0\xb0Ю\xb0\xad\xa2\xb2Ұ\xb2\xaf\xa4\xb3Բ\xb4\xb1\xa5\xb5ճ\xb5\xb2\xb4\xb6\xb3\xab\xb6ѵ\xb7\xb4\xac\xb7Ҷ\xb8\xb5\xad\xb9ӷ\xb9\xb6\xb9\xbb\xb8\xb0\xbbֻ\xbd\xba\xb2\xbdؼ\xbe\xbb\xb3\xbeٶ\xbeӽ\xbf\xbc\xb8\xc0տ\xc1\xbd\xb9\xc1\xd6\xc1ÿ\xbb\xc3\xd8\xc2\xc4\xc1\xbc\xc4پ\xc5\xdb\xc4\xc6ÿ\xc6\xdc\xc0\xc8ݻ\xca\xde\xc7\xc9\xc6\xc5\xc9\xd9\xc9\xcb\xc7\xc0\xcc\xda\xc7\xcb\xdb\xca\xcc\xc9\xcc\xce\xcb\xc3\xcf\xdd\xca\xce\xde\xce\xd0\xcc\xcc\xd0\xe0\xcf\xd1\xce\xc6\xd2\xe0\xd0\xd2\xcf\xd1\xd3\xd0\xc8\xd4\xe2\xd2\xd2\xdc\xd2\xd4\xd1\xd3\xd5\xd2\xcd\xd6\xde\xd4\xd5\xdf\xd5\xd7\xd4\xcf\xd8\xe0\xd6\xd8\xd5\xd8\xd8\xe3\xd2\xda\xe2\xd8\xda\xd6\xd3\xdc\xe4\xda\xda\xe5\xd9\xdc\xd8\xd8\xdd\xe0\xdb\xdd\xda\xdc\xde\xdb\xdc\xdd\xe7\xd9\xdf\xe1\xdd\xdf\xdc\xe0\xde\xe2\xdb\xe0\xe3\xde\xe0\xdd\xdf\xe1\xde\xdc\xe2\xe4\xe0\xe2\xdf\xdd\xe3\xe5\xe1\xe4\xe0\xdf\xe4\xe6\xe0\xe5\xe8\xe3\xe5\xe1\xe4\xe6\xe3\xe8\xe5\xea\xe2\xe7\xea\xe5\xe7\xe4\xe3\xe8\xeb\xe6\xe8\xe5\xe4\xe9\xec\xe7\xe9\xe6\xe8\xea\xe7\xeb\xed\xea\xf0\xf2\xef\xf4\xf7\xf3\xfa\xfc\xf9\xfe\xff\xfcS\x19\x91\xf7\x00\x00 \x00IDATx^\xed\x9d}P\x14\xd7\xde\xe7\xcdݧQ\t\xa8\xf8\xae\xb9r\x91\xd82\x16\xb8S\xd9I\x14\x1c\xf7֔\x0fٰ\x9aD\xddK\xb6\xa2\\\xa3\x0fX>IH=\x88k\x89Z<P\xeel\x15(W\x85X\x18//F \xa5\x80o1\xbe\x11\x1c\xd1@\xe2\vP\xb7\\ū\xa5\xa4H\x95rE\v\x84\x92\x02\xce>\xcfsS\xdb\xe7\xf4L\xf7\xe9\x99\xd3Ӄ6\r\xcc\xfc>\u007f̜9\xfd;\xa7\xcf\xe9\x9e\xfe\xce\xe9\xd3=\xfd\x1d\xf3\xeb+\x80\x00\x00\x00h\xc6h\xa9\x867\xb4*\a\x00 \xc0\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05xE\xfa\xb5\x02\x80@\x02\x14\x05x\x15Z\xe2\xa7poi\x05\x01\x01\x04(\xca\b\xe6PD\xabV\x881\xb4E\x1cb/\xe8\x9f=\xdb^\xde\xc4^\x06\x04$\x06)ʱzW\xaa\xfe\xf0\xee\xfc\xf38\xd1Q\x95o?t\xa9\xc7-\xa9\xc6\xdfv,\x89I\xee\xf3\x16\xe1A\xe1XNd\xec\x01\xadPL\xdd\xfc\xd0)\x8b\x8fM\xb9\x87\xe2\x85\"\xa1\u05f5\xc2\tG9.\xa2\x1f\x1d\x10\n|\xa3\x1eT>\xb9ȕl]1%dA\xbf{\xae\x1a\x9b\xb9\x8dZ!/AM\xdc\x19\xad\x10\xc2i\x13/b:!4%\xe8\vf\xd0%\xee03\x1f\bX\x8cQ\x94{\xd9߉\x89\x9er\xfb\xa9\xa6\x8b\xd97\x10j\xcf=T\xd7t~wa\x8f\"\xa9\xca'q_\xa7\x9b\x9fx\t\xf0d3WU\x95\xc9m\xad\xaa\xe26\xab\xc6\x1c\xbd\xe8J\x1d\t\x8d\xb0\xef\x9f\xc3q\xf5\xe8\x16.vJ\xb5\bMW9\x17R\x85:\x0ep\xe5]\xca\x05r\xbd\b\x95\x84J\x8a\xf6\xe6\x94\xcc\xf8\x906\xf7\\\x152\x83v\x8b\t\xba2&\xb5\xd7\x06\x11p\xd6|B=\x90\xe2 \xefp\x94\xf2\xc5\x0eǼ\x83§\x92\xb1\xdbYA\xdfq\xc7Y\xd9@\xe0b\x88\xa2\xb4\xe4\xbb\x14\xa5\xdc\xde\"\xfcRg\v#\x96o\xf2\xf1ou\x9b\xfd\xbc\"\xa9\xc6c\xbe\x14\xf5u\xaa/g\xb1u<B\xdfbi\b٪\x1a\xf3\xbb\xc5\xceD\xdbķ\x04Q\xe8\x98ɑ\xc1Է>*\n\xea\xe0\x96\xc6#\xd4\xc4u\xb8\xe5K\xf5b\xa4\xa9\xcb6n;\xeaw\x85jMh\xde\x18\xbf֙RT&\xd3\x1a\xe9:'Z\x9d\xca\f\x90Q\x04\xf88\xd2+6!\xd4\xc0_E\xc8\\\x8c?\xae\x0f\xbe\xc5\b\xf2yC\x01\x81\x82\x11\x8ar,\xfb\x98]T\x94\x96\xec\xef\xf1\x1b\xfe\x95.\xcc'9G\x8b\x14I5\xee\xf2\xbe\r\xd5i\xban8\xbf\xf17\xdc\x06\x10\x14\xe1\xef8\x13kC\xee\xe1\xb7-\u070f\xf8\xcd\xe7\x03\xa5\x83\xfbf\xc2S\x86\xa2H\xf5*\xb8\xcei\x9e\xe9\xc8\xc4OuUʮ\f\xd5qu\xce\xd4J-E\xd1\f`\xd0}ש(w\xbb\xf1ǎ\xa9\xf1\x8c \x9f7\x14\x10(\x18\xa1(]OQ\x9e\xa8(\xa7\xec=\xae\xdf\xe6\x96;\xe4\xed\xe4\x01E\x92Io\xacxB\xbf\v\xa1\x9d|T%\xbao\xe2\x97㤩lW\x82y\xc3\x03\x12s75\xd6\x14\x97\xfc\xc0\xbd\xa8\xfc\x8dϋ\b\x9d\xb5\x8a\x1c\xa3\xc7\xe7O\x1f\x17\xb6`\x06BE\xcey\x96p!s\xa6x\xbc\xb4n\xe9R\x16\xcb\f\x0f\x9d\x93\x89\x14\xc5\xe8\xca:\xb8\xa6\xf0|\x97\xa2\xb8b\xe9z\xdbB8.h/^\xda\x13&\xe6\xaeR\xe4R\x95]\x1a\xcbq\xeb\xaf/\x9d\x112\x1f\x9f\xfe\xf5L\xfc\x98,\xa5+\xa3\xd8>\xab\xa8\x9e\xab/\x99\x95\x89\xce8\xa7;V\xe3쁊Ds®\xe78yy\x83\xcd\x14\x9bl\x1bP\x04<1\xf3x\v\"\xb7\xcd\xf78=֖\x93\x13k\xaeV\xaeDT\x14'\xebC\x18\xc2|\f\x14\x05Pb\x84\xa2\b8\x15\xe5PQ}\xa1}\xefI\xf9\xabٿ\xb7\x8a\x91t禣\x92/p8~F\xe8\x81\xc3T\x80\x06\xaen\x8bF\xa8\xb9\xd2\xc4\xc7\x15\xfc\xd9\xf2\x19\x8e\xa85\xaf\xfe\xaa\xa6\x80/v/)IC|\xd0\a%\xdb'\x87\xf7\xe3S\xff\xf8\x03\xe5\xf60\xae\au\x9c\xac\x9a5\xb7\xaa\xaaJ8\xd1\xe9\nR\x9c\x19\xc9łח\xac\x0f\xfe=\xa2\x8bѕ\t\x8a\xb2}\x81SQ\xa4X\xaa^\x84\xceWU\x05o\"u}_\xb5\x9f\xdbTUբ̕+\xeb\xca\xdf;c\xd6\xc4髖r\xf8\xe2\xc9E\xee\x18Y\xac\xa8L\xa6e)\xf7\x06\xf7[n\xf1\x1d\xd4yő\x90\xe4p8n\xe3쌨\xacs\xa5q+\x85\x13\x9b\x9f楟\xa8)\x8b\xe5_(\x03\x1a\x1c\x8e\x98\x02\x9c\xa07_\xefrk\xe9\xbe\x18s\xd9\x06\xf7\xedG+\xcaI\x0f\xf1\xe8\xb9w\xecw\x93\xdcGg@\x80c\xac\xa2\xe4\xdb\xf3.ݪߛ/\xcd\xc1\x9e\xccmc$=\x91\xcfz\xa2\xf1\xf1P\x10M\x92\x16\xe1\a6=NHuے\x85\xa1yo\xf5c\xf7r.i(\xe2rɧ\xfd\xc2Hb2^{\xe6$2Vr\x9dP4q\x87X\xc5\x0esG\x84\xd7#\xf8\x82\x06U\x8c\xaaLP\x94{\xaf\xdf#\x8aBź\x9d\xa8\x848\xb5Cy\xd6\xe3̥*\x13\x8aqo\xb6\x89'\x85\xa8\x84\xbb\xe1\x8ad\x9f\xf5\x1c\x1eǍs^h\x91Nj\xce\xf2\x15\b\xeb\x800\n)\x8d{!$K-}\x8a\x00\x8c\xa8(\xf4\xe6\xab\xe6\x1b\x85P\xbe\x19\xb9C+\xca-\xce}\f\xf9\x960t\x1a\xc4i\x1c\x10\x10\x18\xab(E\xf6v\xe1\xb5#\xf7[g\xf6\xa9l\xe9^\x06*ɀ\xad(\xe9\xae\xe4\x05\xfe&\xbb\x9cK\x1a\x16\xcf\xec\xc1L\x13\xcem\xeeL\x9d\xb1\xc2\xfe}\xbf(j\xae\x83\xb5g,s\x8c\x12\xff[\xf2\xf6\x86\xb2\x18U\x99\xa0(h\xc1V\xa2(T\xec`\x14\x85\xaaL(\x16,m\x84BNJ\xb2\x14\xa5m\xd5\xf8i\xdc\xd4\xe0\x8f\xc8\xe4\xac$\x18i\xef\xf6\xbe\x10\xb0e \xf4к,\xab\xecf_/R\x04`$E\x916_\x8eEx\xb9͟F\xee(\x15e\xbf\xdbҦ\xc3ٳ\xc3`\x8c\x02(0VQ\x8e\x15\x8ao\x87\xc8[\xcfQ\xbbk,O%\x99\xb0\x15EJ\x16\xf3\xdd\xecr.i\x98㜍\xc0\xb7w\xb6e\xbf3\x9b\x9b\"^Q\x96\x0eV\xe7<J\xcf\x11E\xb1\xb9\v\xc9ۂ\bE1\xaa2\xac(\xf9s\x88\xa2б\x83P\x14\xbae(\\\x9e-9%\x9fd\xb0\x14esXv=W\x9f\x19\xf69\xfe \tƇ\xce)\x93\x14!\xfd\xa4,5\x81_rp@\x11\x80\x91\x14E\xde|\xf3\x1ecU\xf6>F\xf9\x96;\xe9\xb1\x1cUq\xdf\"\x00\xa00VQ.\xee&\xe7\x1a\xe5\xe4\xc0zZ\x94\xd7\xe2\\L%ٸ)\xca\x1e7E\xa9\xe1U\xee\xc8pI\xc3ҙ\x17\t\xc2O\xfay|Q\xb6m\u007f\b\x99o%\a\xab\xbdI\xba֓ϵ\xd2\xc5\xe2g\x92\xb7\x19\xf1\x8abTeXQ:B\xcb\xc9\x18E\x8e\xa5\xea\xc5xU\x14\xaa2\xa1\xd8\xdb\xd2\xe2\x8e`\xe9\xf66Ee.zȵ\x1eq\xa4E\x04\xa3\xe2!\x1e\xa3\\#\b\x02ѐ#hɓʘRE\x00\xc6SQ\x1eF%?lLH\xf4\xbc\xacL+ʧ\xe3\xdb=\x96õ\x1e\xc0\x1dc\x15\xa5\x8d\\=n'w\x9e\xb4\xee? |E\xfb\xbb\x94I\x15dE1\xe7 \xd4\xf7\a7E\xe9\xb4&\xe1\xe1}V\x96{9\xd77\xfe\bG\xaeP\xffQ\xf8I\xdf$\xcetD\xae \xaf\x91\b\xdd\xc3\xcb\xda&\xbe-\x1c\x9d\xfd\x913\x14\xc5J\xc8H\u007f?W\xa2(FU\x86\x15\x05\xc5/ƊB\xc5R\xf5b\xbc*\nU\x99r4\xb2x\xa6\xeb\x8e\x15Ee2w&\xddq\xa6\x92\x92\x10z\xc4Wce%Wkr\x0e\nۅ\xbf@\x16\xedP\x04`<\x15\xe5\x1a\xbf\x84\xe7\u05f9.\x945}!\xcd\xe0P\x8a\xd2?{\x01\xf2\x04\x14\x05p\xc3\bE\xe9ji\xc9=\xdaB\xc6\x00\xe7\xed\xe7o\xd5\xe5\xe1\xbbc\x9b\xec\xfb\x9bZZZN\xe6+\x92l\xc4k=W\xc9ohb\xdc\xc1\x82D\xdeT\xd1\xfc\xb3ô\xed\xea\xc0\xcdm&|\r\xa86f\xf9\xd7\x17\xb2\xf82\xb7\x82\x173\xb9\xad\xe2}sk\xb9\xc5\xf9\x87\xe2\xb9<,\r\x136\x96\x14Ƌ\x97R6\x06o)|3\x14\x1f\x99\x87C#r\x0f\xcd\x1f+\x8c\xec\xef8o\xb5Ń\x82\xa5Ak\x8b\xd6\x06-E\xcabRe]\xe5܁\x0et4\x84\\\xeb\x91c\xa9z{NUU\x05\xc7W\x1dos]\xeb9\x85u\x82ʕ+\x132\xf1U\x1d\xd7X\xe4Ǡ-Δ\xdcH\x15\n\xa2\x8bO\u007fb\xc6C\x90\x9cyi'Ng\xe0\x99\xd9\x02\u07bc\ufb10\xacU\x04\xf4^u8b\xb69.?C\xf4\xe6\xbb\x16Ss\xce\xf1\xc05DYȹ\xb4\xe3f)_\xdc\xe0Lo\xe5Xw\xee\x9eg\x9d\n\x01\x81\x8c\x11\x8ar>\x1bC&eэC\xb9\a\xce\xe3\xb1\xfa\xe1l\x91\"E\x92I\xb7E\xfc\u007f\t\xb9\xfcy7)Ʋa\x0f\xcf\xef܉\xb3\xfeb\x16^w\nٷSm\x96D\xf7\xa9Ŏ\t\x1c\xc79\xefz?\x12\x196i.\x1ef\xe4\xcd\xfdt\xfa\xb8)\x91\xe2\xb5ٮ\x0f\xc2B\xe6\x8aS\x01\xf8\u007f=\v\xf1=c\xf1Ι\r|\xa7j\u007f\xe6\x9c\xd09\x99\xfd\xee\xc5\\\x95\x1d\x13\xc2\xf2Q\u007fĔ~E,U\xefwAbe٨k\x12I\x8c\xadW\xe4R\x95]\x123\xa5\xa1\xc0\xfaםG+\xd5H6\xddY\x8bb\x92\xc4C\xbff]\xace\r\x1e\x9dT\xac)\xb0\x99\xacI\xb5ʀ\x9f\xa2ĉ\x962Do\xbe+\xe4/<\xa65\xe2DJ\xee\xe4l\xb1\xda\xe7x\xa9\xf9\x19I\x1f\x0f\xf9\xc8}\xad\x98{c߹tO\xeb\xee_ \x900BQ\x80\x97c\xd5x\xd5Q\x9b\xae<2\xefx\xf4\xe2œ\x9f>[\xa4\xfaǩ\xfd\xe3\xe3{\x10\x8b\xc2\xd9\x1c<\xcd\x00\xa0\x00E\x19\xc1l\x9dvO+D\x0fN\x8b7\xad\xa0\xbe\xd8\v*\x11mS\xd9\u007f=\xc6ܻ\xe4}R\x1d\b,@Q\x80kQ\xe2\xe9Ns\x94\xca]=\x00\xe03\xa0(@_\x86yGum\xf5\x0esƀV(\x00h\x00\x8a\x02\xa0\x813\x1b\xac&k\xf2Y\x10\x14\xe0\x95\x01E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x19\x1d\x9cI|\xa4\xf8\xac\xea\x1b\n\x00ÊA\x8a\xe2ݥ\xb4\xe5\xc8^{\xfeI\xc6#\xc2\f\xa0i\x1c7\xdb#\x93r\x13\x1d\f\xbeZ\xa9*\f@}\xe2 _\xe0vC\xab\x9ao(\x00\f+\xc6(\x8aw\x97\xd2{\xd9%\xf5w\xea\x0f\xec}꽒!\xe2T|\xb0G\x1e\xe5&:\x18d+UᄀJ\x03P6\x8a\x1aJ\xa3*<rU|C\x01`X1DQ4\\Jod\xe3\xe7\x93=\xcd\xf6\xfa\xec\xea\xa1c\x93\x87\xa2(\xdcD}\x87\xb2R\xf5\xee\x1b\xeaf\x00ʄ\xae\xe1\xae)\x87\x91\xcb\xf6\r\x05\x80a\xc5\bE\xd1r)EdpҚ=L\xcf\xd9\xf0T\x94A\xb9\x89\xcaPV\xaa\xdemA\xdd\f@\x99\xd05dX\x9f3rپ\xa1\x000\xac\x18\xa1(Z.\xa5$\xe6V~\xd1\xe0'.^\x95\x96\xa5S'\xbd\xed<\xebq\x99\x85\xd2n\xa2j\x16\xa2\x12\xcfR\xad&[J#RX\xa9\xb2}C\x1bM<\xbf\xe7n\xfa\xb2\x98dl\xcd%?\x14Z\xcbXT\xa8\xda\"\x0eQ\x94\xb9*\xbe\xa1\x000\xac\x18\xa1(Hӥ\xb45;;;\xd7\xf8\x99\xd9\xeb\x13g\xe5\x1e\x9a\xcf\x11E\x91\x9dGi7Q\x15\vQ\x89\xb3|FmuJ\x14~\x84\xabl\xa5\xca\xf6\r\xed\xae\xae\xb4%Xl\xbb\xd2\xe6\x11\x97\vIQ4\x8dE\xd1M\xdeAޕ\xb9,\xdfP\x00\x18n\x8cU\x14U\x97\xd2֖\xba\xfc\xbd\x86K\xcaܙ\xc2\xe8\xa3\u007f\x0eV\x14\x85Y\xa8t֣f!*\xf1\xbc\xbaS\x18e\xbc\x9fB>\xb0\xcez(\xdfP!\x97\xff\xe4\x19\x1a\x10\x1f\x05\xedR\x14\x1f\x8cE\xcf\xf1\u007f\xf5\xa8\x17\xe3\xe9\x1b\n\x00Í\xb1\x8a\xe2ť\x14\xf5\xe4\x97{\x96\x1bR\xda8;~[\x8f\x15Ea\x16*)\x8a\x9a\x85\xa8\xcc\xe3\xd2\xe4w-\xfc\x87$\xcdR\x14\xca7Tȍ~(\x15t)\x8a\x0fƢ\xa7\xf9\xfb\xae\xa4\x9b\xa2\xb8\xfb\x86\x02\xc0pc\xac\xa2\xb0]J\xbb\xc4\t\x94Kv\x83'R\xces\xe4\x94k#V\x14\x85Y\xa8\xa4(j\x16\xa2\x12\rq\xb6\x9cӎu\xea\x8aB\xfb\x86\xa2\x95\xae\x19\x10$+\x8a\x0fƢWe\x1f.\x85\xa20}C\x01`X1VQ\x98.\xa5\xfdyG\xc9\xc2\xef\x8dV\x94V\x8e8\x95\x92\x99Y\x85Y\xa8\xa4(j\x16\xa2\x12\t\x89xJ5\x95\xad(n\xbe\xa1J=\x90\xc7(\x9aƢϣ\v<\xea\xc50}C\x01`X1VQ\xd8.\xa5{\x89}\xb9\xf1g=(bz\x9b \x1f\xafcEQ\x98\x85J\x8a\xa2j!\xea\u0086\x8f\xf0\xbe\x95\x1e\x8a\xc2\xf2\re+\x8a/Ƣ\xa9\xef\xb9nĥsپ\xa1\x000\xac\x18\xa1(Z.\xa5?f\x97\xd7ߩ\xcf7\xfe\x9eٺ\xd0韮\x0f\v\x1a\x9b[OۘRn\xa2\xaa\x16\xa2.\n\xf8\xd4҂\x95|\xecWW\x15V\xaa,\xdf\xd0\x17?\x90+5\xf7ł\xb2\x01\xa8\x96\xb1\xa8\xc0\xed\xa8?\xbb\xd6G\xe5\xb2}C\x01`X1BQ\xb4\\JQ\xcb7\xf9\xf6\xc2S\xc3ps\xc5\xf5\x85a3>\xca\x1d˭@\xb2Y(\xed&\xaan!꤯8!:.\xad\xe2=S\x92\xc2J\x95\xe5\x1b\xda(\x1a\x84&\x93L\xda\x00T\xc3X\x14\xb3/\xe6\nr\xcfU\xf1\r\x05\x80a\xc5\bE\x01^\x95\x81,S\xb5[\x96\xaao(\x00\f'\xa0(\xa3\x82\x81b\xdb/\x8a\fo\xbe\xa1\x000|\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a2\x829\x14Ѫ\x15b\f\xe0\x89\n\xf8\x8aA\x8a\xe2ݥT\xa0\xce\xfeR\x169CK.~\x80A\xd8\xfc\xa1|\f\xc9\xd7|T\xa5ڲ\xcd\xdcF\xc5\xe7\x15\\P\xbeJ\xa8\aڱ\xf1B\xdfB\xaf{\x8fA\xefd\x8a\xef\xe0\x89\n\xf8\x881\x8a\xe2ݥ\x14ao\xc1\x93y^\xca\x1b\xccQ\xa7\x86\xb4\xe5r_\x1c͍\xe0\x8ey\x0f\u007f\x15\x9e\\N,@l2\x83v+3Z\xaa\xc6mb\x87z\xa2\x1d{\xab\xaa*S˞\xe3;n\xad3\x05\x9e\xa8\x80o\x18\xa2(\x1a.\xa5\x02E\xe5wF\x90\xa2\xfcn\xb13Q\xc7\x1dA\xa8\u007f\xee,\xafѯH\x8a\x8a\xa2\xdc\x18\xbf\x16\xb9\x13쳢\xf8\x14\xfb\xad\x86\xa2\x1c\x9f&)\nx\xa2\x02\xbea\x84\xa2h\xba\x94\xa2\xba\xddO[F\x90\xa2HO\x94%\x8a\x822\xb9\xc1{ \xfb\x8e\x9a\xa2\xc4O\xf5\\\xab\x0f*!\xe1C\xac\x86\xa2\xbc\xc3-\x0e\x95\x14\x05<Q\x01\x9f0BQ4]J\xdb\xed\xd7Ѱ(J\xebҰi\x1f}\x146\x01\xab[fx\xe8\x1c<kP\xe4t\xd4\xc0^\x1a\xa2\xa2,\x9dF\x82]\x86\xa5\xc2\xd1\xf5\xf1\xec\tsOM;\xec^]\xee\x14b\x00tk\xa2\xb3\x8a\x89w\xe4e/\x96\x98rl\xd6\xda,KR'mnJ\x14%\x8b\xe7\xf9\x98\xc7\n\xc3R\xd43\xf1cW\xd1\x1bo\x87\x8d\x9b\xb2\x00\xfb\x06\x04\u007f\xb4jV\xe8|<Xh{g\xea\xf8\xe9\v/!<c2\xce\xeeʥ\t\xfe ~j\xd8Bq\xa2\xc4\xd57eRKQ\ued60I\xf28\t<Q\x01_0BQ\x90\x96KiI9\x1a\x16E\xe9ycJ\xe6\xc6\xe0\x10\xfb\xfc\xad\xd8cc}\xc9\xfa\xe0\xdf\vrq\x92<\xa3\xba\n\xcf%\xd7q%O\xeb?\xe6ȣ\xf0e\x1bӶ\x99a\x9bKVp\x9c\xeb\xc0\x94x\x8b\x9bO\xaaݽ]$\x97~nc\xad\x85ߵ\x8e\x8f=\xb8\xa4Xan\x8a\x15\xe5AZ\x14y\x8c\xb5lX\x8a\xd0Ei\xf6\xe6\u0604\xf0\xcd\xe5\x1b9\xa1\x8d(\x98\x9b\xbd\xf7\xd0\x14\xec\xf2Q\xc4\xc5\x1f\xcb_\x18\xf4-B\xf5{\xc7r\x937m\x99\xe8\xee\xfd\x11̅\xef\xdf?'\xb4\x0eQ}S$5\x15E\x80R\x14\xf0D\x05|\xc1XEa\xbb\x94\xd6\xe7v\f\x8f\xa2\xec\xe7.\xe1s\x1a|\xd0\x1d&\xa3\x91#\x1c\x19wPg=\x98\xa58I\x19\x96\xfe~\x12\x1e/\xac\xf2T\x94\xa6\xcfo\x90\xf7{M\"\xf7\x14K\xad\xe9\xe8\x1c\u007f\x06\xa5g(\xcdM\x05E)\x8e>\x8bS\nG\xd3\x12N\xac\vuM\x9f߅\xbdG\xf0\xa9b\xf0\x94VA\x14&\v\xa9\xa7\xf9x\xb4\xf4[bM\x16<I\x18\x9f,\x9d\x8c\x94\x04\xcf\x16\x8au͊P\xf4M\xd1\xcd\xc1)\nx\xa2\x02\xbe`\xac\xa20]J;\xec\xf5\xfd\xfd\xfdMy\xfd\x06\x1b\x80!\xb4v\x12\xc2\xe6<\x87\x84\xd7\xf8ߒ\x9c7D?RYQ\xb6\x9c*\x89\b\xc1\x9e\x1a\xb2ai\u007f(\xb9\xa8[\xef\xa9(N\x9a8\x17\n3\x0ek\xa5\xa0\x16\x9d('\r)\xccMS\n\xf69}~\x14\x8e\xa6\x85\xae\xc2%\xdc\xf7R\x15\xc1\xb8y\xc4\x03\x11\xb5fΟ9\x91\x9b\xe3\x96K\x11\xfcG\xfc\x9aɵ\xd1}Sts\xb0\x8a\x02\x9e\xa8\x806\xc6*\nӥ\xb4)\xdbE\x8bJ\xe9\xa1b+\u05ca\u007f\xb6\xf1\x18e\xeeB\x92\xb3 \x02\xbf*gfۂ\xb2\x11mXz\x8b#\xbdhWU\x14TU$R\xa5ȵ^@\r&D\x14\x8567M\x89\xb3$|F\x8cI\x15\x8e\xa6\xa7\\G\xfbVN>I\f\xc6Z\xb6\tkǷS\xa6\u007f\\X\x159G\x99K#\xce\xccVq\x17\xe9\xbe)\xba98E\x01OT\xc0\x17\x8cU\x14\xb6Ki+\xa6.\xb7\xb5\xd5\xe8AJSЂ\xa6K\xb3\"\xf0j\xe3g\x92\x9c\x19\xf2\x18\xc5\xde䚙\x9d\x88\x8fXٰ\xb4?\xe4S\x1cT\xa7\xae(l\xac5\xa8!ZT\x14\xda\xdc4%\xae\xf9\xbe\xa5\x18\xa7\x14\x8e\xa6\x1d\xc1\xce\xdb\xdb\xca)\xa3/\xa2\x12D;fG`\xbf\xb4\xb7\xe7(si\x82W\xe1W;\x1e\xa3\xcc$\x19\xb8o\x8an\x0eNQ\xc0\x13\x15\xf0\x05c\x15\x85\xedRJ\x18\x8ey\x94\x8b\xdc\x14\x8e\x8b$\xb2VB\xc6\xf4\xfb\xb9\x12\xfc!2\x12\xa1{ؠTT\x94)\xab.}J\x1b\x96.\x0e\xc37\xc7/ẹ|q\xc3=\x8b\x82R\x14\xda\xdc\x14_=\xbe`\xc2\x13\xb3\nGS\xe14K\x14؎)\x91x\xda\xe9\x03,\x10\xb2vL\xc7\x13\xb1\xfds\xbc)\xca4<\xfd2;R\xd17E7iEi\xdaļ3XV\x14\xf0D\x05|\xc2\bE\xd1r)\x15\xe8o\xa9\xcbmi\xf3Z\xcb\x10p1\xb8\xbc\xa4\xaaE<p\x97\x06\xad-Z\x1bD&a\xd1\xc6\xe0-\x85o\x86\xdeA\xe8\x12\x99\u008c\\\x80\xa7\x1fd\x1bӖ)\xd33\x0f\xbc\x15\xec\xa9(\v=<\a)\x9a\x17\x15?\xaf45>O[\xf7\x8027}r9q\xdb\xd5\xde\xcedk\xed#ڰT\xe0Ǡ-b\xc1\xa3\xaf\xbf\x91Y\xf2\x01g\xc7\xf7\xc1ƟB\x17\xe3\xc7U\xb5\xa0M\xdc;\x99\x9f\x87sa\x9bOѹ4\xc1\xdc\xfcS\xdfDL\xc2\x1aG\xf5MN\xde\xc1\xf7\xccnu\x19\xaf.\xe4&xl\xfe{UU\x13\x16;\xedZ\xc1\x13\x15\xf0\r#\x14Eӥ\x14\xdf\xfa&\xb0\xd7[%C\xc1\xc9\xf1xfd\xdc\\<\x91ҟ9'tN\xa6x\xf4t}\x10\x162\xf7[\x84\U0008595b\x05]\x99\x15\x86\u007f\xd3]\x86\xa5\xc2\xf0*~zț\xe7=\x15%wr\xb6{\x96D\xdf\x12\x9e\xaf\xb4\xf0\xe6j<O\"\x9b\x9b~\xcd\xf3|\xd4O\x95\xc2\xeb>D\x19\x96bֿ\ue738\xb8\xfeδ\x89\x11\x85\xf8\xce\x13\xa1\xb1u\xa1\xc2\xeb\nԿuV\xf0\xe4Ź3\xc7Gҹ4\xb3?}g\xe2ԥ\xe2y\xa5\xdc79\x19\xef\x9c\x18\x12\xef\x0f\xb6O\xe0\\\xd3\xe5\x12\xeb\xc9\xf2\xb1\xe4\x96\x16\xf0D\x05|\xc3\bE\x19\xa9\xb4NX\xd1\xda\xd3\xd3\xf6\xdd\xdba/3:\xea\x18\xec<ʠY5\xde\xe7?\x06\xbe:\x85\x9c\xb7\x8d\x00\x9e\xa8\x80\x8f\x04\xb2\xa2\x14N\x12\x87$\xfda%\x1a\x91,\x86^Q\xd0\xd6i\xca;Z\x86\x8e\xfe\xdcI\xca\x11\x8e\x12\xf0D\x05|%\x90\x15\xe5bP\x1dy\xaf\v\x92\xef\xf8\xf0\x1d\x03\x14\xc58Z\xc2V\xc1=\xf6\x80\x1e\x04\xb2\xa2\xf4LJ\xac\xd8\u007fl\xff\x8a\x90\x97\xf9\x0f\xdc\xf5\xc3ܪSF_\xee\x06\x80\x91N +\nBE\U000e739f:\xff\xa5\x9e\xf54W\x9a\xb4\x04\x00@\"\xb0\x15\x05\x00\x00}\x01E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14e\xd4\x01ޥ\xc0\b\xc6 E\xf1\xeaRڵ\x9b<\xd7 w$\xfe\xbb\xb5n~\xe8\x94\xc5Ǧ\xdc\xf3\xcd\xd4S/\xc0\xbb\x14\x18\xad\x18\xa3(\xde]J۲\xbfo\x11\x18!\xbf\xbc\n\x8e\x84F\xd8\xf7\xcf\xe1\xb8z\x9fL=u\x03\xbcK\x81ъ!\x8a\xa2\xe1Rږ\xadxf\xfc\b\xa2m\xe2[]\xc2hj&G\x86Xڏe\xd5\x0f\xf0.\x05F'F(\x8a\x96K\xe9\xc8U\x94\xb5!\xe4\x01%[\xb8\x1f\xf1\x9b֡\xa6'\xe0]\n\x8cN\x8cP\x14-\x97\xd2\xe1S\x94\xe3\xf3\xa7\x8f\v[0\x03Ѯ\x9f\x1b9\x8eۋ\xf6\n\xaf\xeb\xd1L\xf1xi\xddB\x1e\x1e\"\x1fj\xb2է\\\x03mc\xaa\x00\xbcK\x81\x00\xc2\bEA\x1a.\xa5m\xd9\xe5\a\xb2\xf7\x1e7\xfe\xab\xf9\x1d\x17\u007f\xa0\xdc\x1e\xc6\xf5Ю\x9f\xad\x8b#\x8e\xb7\xa3\xf6\x93s\x17\xdf\xeb\n\xdaJ\x87K\x87\x9al\xf5I\xd5@٘*\x01\xefR \x800VQ\xd8.\xa5m\xd987\u007f\xbfᒒ9\x197$\x13?\x1c\x92r\xfd\xdc=\x9b,\xfcm\x1ej\"v\x83\x12\xaeC\x8d\xb2\xfa\xa4j\xa0lL\x95\x80w)\x10@\x18\xab(L\x97R\xd4_\x87\xb5\xa4k\xb7\xd6\x17Yw\xeeL\x9d\xb1\xc2\xfe}?\xd17\xd9\xf5\xf3RPW\xc7\ued9e\xe0K\xa8g,s\x8cBY}R5\xc86\xa6l\xc0\xbb\x14\b\x04\x8cU\x14\xa6K\xa9\x8b\xe3\x85\xc8hڲߙ\xcdMٌ\x14\xae\x9f]c/m\xe5\xfe\xa9>H\x909\xe7<J\xcf\x11\xf2\xe6:\xd4h\xabO\xb9\x06\xd9\xc6T\x05\xf0.\x05\x02\x00c\x15\x85\xe9R\x8a\xca\xc5G\xd1\x1f}\xa9\xa73\xbe\n\xe7\xf1\x91Ѷ?$S\xe9\xfa9{o\xe4\xdcم\xf8\xdc\xc7y\xad'\x9f#\xf7\xcaHc\x94\x99\xe4\r[}R5\xc86\xa6\x83\x02\xbcK\x01\xbf\xc2XEa\xbb\x94\x96\x90S\xf1\xb6ܗy\"\xfd+\xb1I\x9c9\x88\\\xa1t\xfd\\\xbcb\xfcan\x05v\xc6j\x9b\xf8\xb6pB\xd3\x1f)^\xcbq\x1dj\x94\xd5'U\x03ec\xaa\x04\xbcK\x81\x00\xc2\bE\xd1r)\xbde?|\xbd鼽\xc4\xf0'\xcbo\xe2&l,)\x8c\xc7\xd7Od\xd7O\x84\xbe\b\x9d\xd8?+\x84(\xc3\xe1Ј\xdcC\xf3ǞT\x9az\xcaV\x9fT\r\x94\x8d\xa9\x12\xf0.\x05\x02\b#\x14Eӥ\xf4^\xf9\xdeܢ:\xc3\x05\x05\xe5\xcd\xfdt\xfa\xb8)\x91X\x0ed\xd7O\xa1\xbd\x93\xfe\tm\x9e \xce\x1e\xe3\xff\xf5,$\xd7Z)SO\xd9ꓪ\x81\xb61U\x00ޥ@\x00a\x84\xa2\x00z\x02ޥ\xc0H\x06\x14e\xd4\x01ޥ\xc0\b\x06\x14\x05P\x05\xbcK\x81A\x03\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\xc0K\xc1\xfc'\x1e(\n\x00\x00\x83\xa7%~\n\xf3\xe9b\xa0(\x80\x933\x89\x8f\xb4B\x86\x9c\x97t`}\xc9b\x80&\xaaN\xb4\xfd\xb3g\xdb\xcbY\x1e\x16\x06)\x8aW\x97R:wt\xb1\x93\x8f\xaa֊yEj\xe7\xf1\x89}\xe8\x04\xcfϫU\viL^dYS\xfb\xfe\x15\xb5\xe5\xbeq\x90/\x18@\x15<\xcf\x17\xa0\x02\xe1\xb5\xccK\xe8}\x13\xbf\\x\xdb&\x84\x99慎9\xe69\x1fh\x19Ө\x1e\xa4@r`\xfdێ%1\xc9}ރe܍[\xd9\xe0\xbe\xf1\x8b\x92oj\xc5\r\x96\f\x9e\xc7\x0f\xdb+\xe6\xf9\f\xb7%5qgX\x05\x86\x16\x9d\xbb\xa9\xe6D{\x89\xf3|n\a\xc1\x18E\xf1\xeeRJ\xe5\x1a\xcd\xd1W{`\xd0\x03\x87\x89rꪽ\xc6JR\xb0s\xbd\at\xd7\xf01\x0e\xd4y\x82\xaf\xe9f\x14\xc0\\3\xa5\x9c\xa8\xfc\x8c\xe7_M\xdbJ\xa3\xf0#\xf7\x9fU\xf0\a\x1f\xa1G_\xf1\x15ϼ\xc4\x0e\\\xdd\x16\x8dp\xef\x1d\xa5\xfcU\xf5\xb0\xee+q\xc9\x0e\x81\n\xfe\x02\xf2\tف\xf5\x93\xb8\xaf\xd3\xcdO\xbc\x06\xcbx\x18\xb7\xb2\xc1}\xab\xadHTW\xe6\x97\xe4\xa1\xf9+\xfc\xc4\xce\xc7_Y\x1e\xba-9k>\xe1Li\xeey\xfdХ\x9bT{U\x9ch\xbf㎳\xb2\rR\x14\r\x97R*\xd7h~\xb7X+B\x83hJQV\xa7\xb2\x92\x14\xec\\\x8d\x80N>}\x9b0,\xe0;=\x17\x89lX7 \x1c\xe4\xdb^MQ\xee\x9ar\xc8{3_#\xbc\xd6\xf2\xcd^\xa3QA\xb4\xf8\xde\xe0MQ\x10Z\xb6\x03\xbf\xde\xf6QQd\a\xd6\xc7|)\xeaS\xed\xb0\x1b,\xe3V&\xa4o}k\x12\xb4\xe2\x06\xcb\xfb\x15\xe4\xad\xecC\x8f%\xd2(Ks\xcf\xeb@k\xa4x\xea\xa7G7\xe9\xf6\xb2\x9dhU\x9fFl\x84\xa2h\xb9\x94R\xb9F\x13\xfe\x8eV\x84\x06\xb4\xa2\xacLe%)ع\x1a\x01\x9d|\xad\xf9\xb97EYF\xb4\xa0\x91?\xad\x16\xe0\v\x19VѴp(\x14\xa5\xb7\xd4ۀGFv`\xbd\xcb\x0f\xe2t\x81e\xdc\xcaD\xec[)\xff\\+p\x90|\xb6\x87\xbc\xe5|\xa6\x1e\xa2\xb9\xe7u\xa0\x8e\xab#\xefzt\x93n/ۉvX\x15E˥\x94\xca5\x94\"\xe7\x13\x10\xc3\xf1\a\xdan\x94ƛǨ@tή\x04\xf3\x86\a\b\x9dq\xce\x19\xacV$w\xf2\xa6\xd2\f뢔\xbb\x8a\\\x85\xf3\xe8\xe5\r6Sl\xb2m@\x19 \xd3\xc9\xdf_y©(R\xb1}B\\%\x12\x1f\x1b\x99fŇ\xff\xc09E@\xa3\x89\xe7\xf7\xdcM_\x16\x93\xfc\xa2\x9aw͍T\xb3\x03\x84r\xbd\x16q\x88B+\x8al\x9a*\xf4\xa2\xcc\xd9M\xe1\\'\xcdjI\xdd\xe6\xae(\xeczEE!5DU:\xa7_\x14\x95\xa1\xbb\xa9\xb1\xa6\xb8d\x92v9\xb0\xf6Ɗ\xdba\xd7\xe0\x8a]\x1a\xcbq\xeb\xaf/\x9d\x112\xbf\x876\x9a\xa5\x10\xfb\x96f\xc5i\xd6\x0e\xa0v\x96\x10\xf0\xf5j\xf3\xca\xd2\x01\xb7\x15K\xb1t\r\xc4k\t\xa1\xd4\x1cE矘y\xdcz\xa4\xb6\xe7\x95;\x80\x01\xd5!D[\xe0v|<{\xc2\xdcSӔ\xd3\x18\xdbg\x15\xd5s\xf5%\xb32U\xbbٙ\xb3ܜt\xd5v\x81ި\xbe}\x11\x99N\xb4džSQ\x90\x86K\xa9G\xaeAt\x9c\xac\x9a5\xb7\xaa\xaa\n\x9fm\xd1v\xa3\n\xbcz\x8c\n\x8a\xc2'T\x9eY\"\xfc:u^q$$9\x1c\x8eۊds\xa5\x89\xb7\x15\x14\xd8\xcc\xcdt.\xed<\xfaӼ\xf4\x135e\xb1\xfc\ve\x80\x8c\xa0(\xa5\xc9NE\x91\x8a=JK\xbc\xdc)\x94X\x93\xf6\vzh\x8bJ.\xf8\xa1\x17)\xea\xed\xae\xae\xb4%Xl\xbb\xd2\xe6=\xec\xbcl\xd9\xf7\b=\xdag\x11J0\x03\x84r7y\x87\xb8\xb6f\xfe\\ww\xf7\x05\xac(\xb2i*\xeeE\\\xc1\x9f-\xf8G\xf8\xae%\xa1\xe2\xcc\x06\xde]Q\xd8\xf5.\xcb\xe8\xee.ND\xce\t'q\xfa\x85\xae\f՚W\u007fUS@f6e\a֛\x8eJ\xbe\xc0\xe1\xf8ypź\xf2\xf7Θ5q\xfa\xaa\xa5\\\x13e4\x8b(\x84\xbe=\xbf\x9d\xc3\x17(\xdaK\xed\x00jg!\x94\x1e\xbd\xe7ܞ\xe8t\xe5\x8a\xe5X\xba\x86\xb2\xd5\xe8\xaa\xed*ZY\xa6\xec|\x83\xc3\x11C\xd6\xc5\xde\xf3\xca\x1d\xc0\x80\xea\x10m\x81\xdb63ls\xc9\n\x8e\xcbD4-K\xb97\xb8\xdfr\x8b\xef\xa8u\xf3ɻ\x8b\x8a/\xec\xe4\xf9\xaf\xe9\x8d\xea\xdb\x17\xd1Ӊ\xb6\xe7ޱ\xdfMR\x19\x19\x1a\xab(l\x97R\x8f\\\xe3\x90\xcez(\xbbQ%\xde=FQt\xdc߄\xdd\x12G\xd2̳\x9e\xe8e\u0090\xff\x89-Q\x91K9\x8f\x96\xc6\xe1\xafg\xa9\xa5ϭ\x06\tAQ~\x89\xf9\x85(\nU\xac\x82\xfc\u0088\xa7\xf0\x8f\v\xfe`\xe2-\xd5\xc8\xcd\xd1t%\xff\xc934\x80O82\xf0\x8fhZ\x86z\x00:\xc7\xffU\\[\xb3\xf3\xf7\xa9Yi\x9a\x1am\x11~\xa2\xd3q7\u05fc'\xfc\xa0\xf5}\xe8\xa6(*\xf5.\xc3U\x91\x1fK\xf1\xf4P<Y\x92+\xeb\xb6%w\v\x83\x92j\xe2E$9\xb0\xd2g=\x83*\x16ν\xd9FΞe\xa3Y\x1a\xb1o\xe9x\x80\xa1\xb2\x03\xe4\x9du\x81\xfc\xd0א\x19 y\xc5T,U\x83#\x16\xe5\x98r\xd0\"\"\xca\xd4FE(\xc6uN\xcc\xda\xf3n\xb1,\xa4\x0eQ\x16\xb8\xbf\x9f\x84\x9f;\xbe\xcaMQ\x10:<\x8e\x1bG\xc6-\xecn\xa6\xe3N\xa0,AQ\xe8\x8d\xea\xd3\x17\xd1Ӊ\xf6-a\xf8\xa7\xe6\xaee\xac\xa2\xb0]J\xdds\rDR\x14ڰ\x94\x85\x8a\xc7(\x8a\xc6ǩsV\x81\xad(\xe4t\xa2\x94\u007fL\xe7RΣ\x0f\xad˲\xcan\xf6\xf5\xba\xd7 !(\nJ.&\x8aB\x15k\x8c\xea~^\xf1\xe4E\xb4\xf3\xbalwM2\u007f\xce\xcd\xd1te\xb4\xebǯ6\xe69zn\xaeE\xaa\x01贰\x12B3\xff熆\x86b2\x8fB\x99\xa6\xe2\x1fk\xd2\xcd'\xe2e\xe5=n\x8a\xa2Rﲔ\x86\x86tOEqU&\x1c\xb7\xd4E\xceByӲ\x15E\xb3Xx\xb03)\x1b\xcd\xd2ྜྷM\x8c\xb9\x8fTw\x80\xbc\xb32\xde'E\x96oC\xf4\x8a\xa9X\xba\x06\xfeyR\xfa\x9aN\x9e\xf4\x9aڨ,EQ\xdb\x01l\xa4\x0e\xc9\x16\xb8\xfd\xa1\xe4Jy\xbd\x9b\xa2\xb4\xad\x1a?\x8d\x9b\x1a\xfcQ\xabJ7\xfb\xcc\xd8UAX\xa6T\x14\x9f\xbe\x88\x9eN\xb4M\x87\xb3g\x87\x8d\x881\nۥT\x99k(\xf2̬l7ʆ\xed1J\u007f\xe3U\x14\x85|\xa9\x1c\xfc5:\x97v\x1e}R\x96\x9a\xc0/98\xe0V\x83\x04V\x94\x13+\x89\xa2PźM\x8d\xc5\xfc\xbe\xdbQ\xc2ou\x039\xc3\xefKLqs4])MȼXt\x1a\x9d\x8e\xedC\xaa\x01\xe8\xaa\xeb셚G\xa1MS\xa5n6\x88\xa7G\xee3\xb3*\xf5\xe2y\x94f\xf1J\b-\rR\xb2\x98\xa7.\x89\x9f\x92\a\xd7lE\xd1,\x16\x1e\xeeLPF\xb3\x14\xa4oO\xa2\xb0$\xaa\xec\x00yg%\x92\x9e\xa0\xe4D\xa4h\x83\x1cK\xd5\xd0\x17\xddl\xbefn6\x89\xbf\xee\xf2Fe)\x8a\xda\x0e`#uH\xb6\xc0\xbdő\xa3\xa5\xddMQ6\x87e\xd7s\xf5\x99a\x9f\xabt\xf3\x818q\xdf\xe9\xa6(>}\x11\x99N\xb4U\x9e\xbe+\"\xc6*\nۥT\x91k,DQ\xecM\n\xbb\xd1A\xe1\xa1(\x15\x0f\x95\xc9\xe8,\xfc\xb9\x8c\u007fF\xe7RΣ\r9\xc2.|R\x19S\xeaV\x83\x04V\x94\xe7\xe6\x1aq\x8c\"\x1b\x96&T\xae[\x93p\x1a\x9f\xfbX\xc9\x1aP\xce{n\x8e\xa6Է\"+\x05}F\xa2\xd4\x02\x9e\xbb\xaeYQ\x8aB\x9b\xa6J\xdd\xfc\x1bO\x1a\x9a\xee\xa6(*\xf5J3\xb3\xce\x1a\xf6\xb8IC\rOݧ!9\xb0z(\x8a\xaf\xc5\xc2\xdfv\xa5d\xa3Y\n\xb1o\x16\xfcc\xad\xb2\x03䝕\xf1.\x99}]\xee\x03\xcf]\x00\x00 \x00IDAT\x86\x87'\xf2\x8a\xa9Xž\xf8ʊ\xac\xc5\uf455(\x8eE\xa5\xa2\xb8\xedy\xf6\x0f\x88\x02\xa9C\xb2\x05n\u007fȧ8\xa3\xce\xfd\xac\xa7\x87\\\xeb\xc1clf7\xfb̤)\u007f\x91\x15\x85lT\x9f\xbe\x88L'\xdaa\xbdփ4\\J\xe9\\\x83\x89\x8cD\xe8\x1e\xb6\x17\xa5\xecF\x95x\xf7\x18U(JR\x12B\x8f\xc4\xdbB\xe4d\xf4\x12A\n:\xdfMR\xe4RΣ\x05\xe2\xcd\x1aI;\xdcj\x90V\x8c\x15\x05\xa5\xa7aE\xa1\rKӲL\x17\xf8\x9dx\xc7\xc7Z\xf1׳\x0f\u007f\t\x14\x8e\xa6\xd4\xf7\xf5\x87\x98\x9fc~\xc0\t\xb5\x00\x94\xfa\x9ex\xef\x04\xa5(\xb4i\xaa\xdc\xcdD\x9b\xb0\xb6\xdb1n\x8a\xa2R/\xa5(fᄢ\xef\x0fn\xd2\xd0iM£\xec,Q\x13]\x0e\xac\xb4\xa2\f\xaa\x98<┍f)ľ\xc5e5\x16\xa8\xed\x00yg\x9d#3\x1d\x95\xf8T\x92Z1\x15K\xf789\xf13\xf4Y\xe2\x06\xb2\x12\xb6\xa2\xb0\xf6\xbc2\x96i\b+u\x88\xb2\xc0]\x1c\x86o;Y\xea1\x8f\x82\xeeL\x12/C\xb2\xbb\x99\x1a+췁t\xa2(\xf2F\xf5\xe5\x8b\xc8v\xa2\x1dVE\xd1r)\xa5r\x8dfc\xf0\x96\xc27C\xef(\xedF\x15x\xf5\x18\xfd\xd9a\xdavu\xe0\xe66\x13\xbe0!|\xe9\x8aO\u007fb&\xc2.'\xa3\xf9\xd5\xd5e\t\x96\xbf*se\xe7\xd1\x02\u07bc\ufb10\xacU\x06H+\xee\xae\xe1Ot\xa2Z3\xb9\xd6C\x19\x96\x1e4[\xfa\x12\xc876\x96\xb7\xee\xbb \x14\xbbM\a\xbc\xf8\x81\xcc\xd7\xdf\x17\xdb\xd9g\xdd`\x15\x15C%\x00ݎ\xfa3~\xa3\uf655MS\xe9n6\x9bm\x05{\x16E\x99*\x9a\xd1C|\xcfl\xb1á\xe8\x10Uo\xf7ո\xe4+\xae\xdbh\x12\xe3\x0e\x16$\xf2B1\xc56\xab\x8dY\xfe\xf5\x85,\xe7-\xff.\aV\xf1Z\xcfվ\xc1\x15\xeb9E\xae\xdc5\x91<\xcahV\xa6\x91\x1c3뒷\xbd\xaf\xb6\x03\xa8\x9d\x95\x16\x95s6'*M\xb9\x8f\xe9Xj_d\xcd;\x88\xbe\x9a'\xe8\x1b\xbdQ{\xaf:\x1c1\xdb\x1c\x97\xc9\xc4+cϻ\xed\x00OCXE\x87d\vܖ)\xd33\x0f\xbc\x15\xec\xa9(.\xd8\xdd\xfc\xd9j+=\x91\x12C\x14Eڨ>}\x11\xd9N\xb4\xe7Y\xa7B\x18#\x14EӥT\xce5\x9a\xae\x0f\xc2B\xe6\xe2\x13B\x85\xdd(\x8d7\x8fQ\xb4S8\x055\xfd\xc5,\xbc\xee\x14>ug-\x8aIj \v\xe4d\xf4\xae\f\x8b5\xfdg\xb7\\\xd9y\xb4bM\x81\xcddM\xaau\x0fp\xad\xb8v\x1e\xbe\x8f\xa4/QT\x04ٰ\xb4A\x18\xd6\x1e4\xe3\xd8?\x94\xe5,7ǥ\xdcV\xd4\xdb\x18EΏ\x93źPqt\xb13\xa5\x12\x80\xf6\xc5\xe0\xff\x05\xd1\xff\xeb\x91MS\x15ݼ\x9b\xb2hYN\x85IH\xa6;O\xc2SU\xea%\xff\xeb\xa9t\xd6\u007f7)Ʋa\x8fP\x83r\x9b\xddN\xb5Y\x12]\xf7\xe6\x89\x0e\xac\xdd\x16R\x83\xe9\xf6\xe0\x8a]\n\"3\r\xa2\xfe\xd3F\xb3.\xf0}9_\t\rL\x88=\x8bTv\x00\xb5\xb3\xfaJ?4\u007fXڧ\xdcNJ\x9d%\xef\x8bs\xe6FAi\xcf(7\xeaObZ\x94=ƞw\xdb\x01\x9e\x86\xb0\x8a\x0eQ\x16\xb8\xad\xf1\xd3C\xde<\xaf\xaa(*\xddD\x8f3l1\x9f4\x10E\x916*R\xd9\x0et{U\x9ch\xef\x8d}\xe7ҽ~\xe4\x89\x11\x8a\x12\xd0\xd07Վd\x06\xb2L\xd5Z1C\xceK:\xb0\xbed1O\x86sgy7\x84u\xa7C}\x8c\xe2\rqfv0\xa8:\xd1\x16\xce\xe6\xe0i\x06\xc3\xc1p~I\a\xc5@\xb1\xed\x17\xad\x98!\xe7%\x1dX_\xb2\x98\a÷\xb34\fa=0JQ\xbc9\xd1\u07bb\xd4\xc2\xc8\x05E\x19b\x86\xefK\n\f\x9a\xe1\xdbY\x835\x845JQ\x06\x0f(ʐ\xf2\x80L\xebiE\x01#\x82Q\xb4\xb3\xae\x1f\xe6V\x9db\xcdbx\xe7\xee\x05~\xd7\x0f}hH\x01E\x19Rȴ\xde}\xad(`D0\x8av\xd6\\\x8e\xe3\xc6^\u05ca\xf2`\r\xee\xe1]\xad\xa8W\x03\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd0HQ\xbc\xb9\x94\xf6\xe49\x1fl\xb0W\xbd\xbc\u007f\xa1\xb3\x91$\x00\x8c\x1c\x8cQ\x14\xaf.\xa5]\xd9\x17[\x04\xceg+\x9f3쇸\xbc\x1f_\xc6H\xf2\xd9\xcf\xea\xcb^\xd1k\x15\x00\xf4\xc3\x10E\xd1p)\xad{*\xa4\x9e\xe6\xa9<\x13ʏ\x90\xbc\x1f\am$\xd9WfY\xa7\xbe\xf4\x95\xbdV\x01@/\x8cP\x14-\x97RBɁ\xe1x\x86\x9b\xb1\xacT(\xca \x8c$\x1bW\xf3)\x0f\xd4\x17\xbf\xb2\xd7*\x00\xe8\x85\x11\x8a\xa2\xe5R\x8a\xa9\xcf\xd6\xe7\x999#\x83\xc7鱶\x9c\x9cXs5\xe5vI{?j\x19I*\xe9\xdc\x15e;\x8bԠ\xbcV)_\xcb\x15\\P\x1ej\x1aω\x8f\x83\x97-.\x01`h1BQ\x90\x86K)&\xbf\x9cUl\x94һ\xdcZ\xba/\xc6\\\xb6\xa1\x98r\xbb\xa4\xbd\x1f\xb5\x8c$i\x06N[M9\xe2\xf3\x9f\xbb\xef\x8bPn5\n\xafU\xcaײ\xa5j\xdc&A\xc1\xe3\x83q\x88lq\t\x00C\x8c\xb1\x8a\xc2v)\x15h\xcaV\x1a\x94\x8fn\xaa\xf9F|N\x83}\xf9h\xb7K\xfa\xac\a\xe3\xcdHRf'\xbf\xb2ٙLr\x0es\xd6 %\xd4Y\x8f\xe4k\x89\x82\x05EA\x9b\xb0\xa2P\x16\x97\x000\xc4\x18\xab(l\x97R\x81r\x9d\x1e=<2ȱ\b/\xb7\x89\x8b\x1b\xedvI+\x8a\x96\x91\xa4LE\xf4\xa2\n\xe7\x83\xc5n\x9f\x11q\xf3ZW(\x8a\xcbגR\x14\xd9\xe2\x12\x00\x86\x1ac\x15\x85\xedR*\xb0{\x18ܿ\x86\x8e\xe2y\x8f\xf1\xe8\x04\x0f-h\xb7K\xb7\x99Y\xafF\x92\x14w7\xf0\x89\xcd\xc8\x1b\xb4\xa2\x84\xbbR\xb2\xa2\xc8\x16\x97\x000\xd4\x18\xab(l\x97R|=\xd9\xf5\xcb\xea\x17<\x8cJ~ؘ\x90\x88\x1f\xe8I\xbb]\xcaޏ\xdaF\x924\xd4L\n\x1b\xc9k\x956\xea$\x8a\xb2\x1e+\x8alq\t\x00C\x8d\xb1\x8a\xc2v)\xc5\xd3(\x83\xf1*\x19\xf1\\\xe3\x97\xf0\xfc:r\xb9\x97v\xbb\x94\xbd\x1f\xb5\x8d$\x95t\ue2b2\xd6x\xe4JH^\xab\xf4p%\xf4ca\xebF`E\xa1,.\x01`\x881BQ4]JQ}\xf6\xa0\xac\x05F:\xd7bj\xce9\x1e\x88\xcf\x1c\x97\xdc.\x11\xe5\xfd\xa8m$\xe9N\xf3\x1a\xdaO\xd7\r\x97ת\xc2\xd7r\xee\xe4/>\x8f\xe0\xc6\xe6\xd6\xd3\x16\x97\x000\xc4\x18\xa1(\xda.\xa5M\a\xbcV0ڸb\xc23#\xa65x\xf6Cr\xbbD\xb2\xf7\xa3\x0fF\x92\x83\xc2嵪\xf0\xb5\xbc\x1e\x192q\xfe\x1f9\x0e\x1bK\xc9\x16\x97\x000\xb4\x18\xa1(\x81\xc6#\xf3\x8eG/^<\xf9\xe9\xb3EO\xb4B\x19\x18`\xd2\x04\x00C\x06(\x8a\xfe\x9c\xb6\x88C\x92\xbeX\xf7\xbb_}\x01\x14\x05\x18̀\xa2\xe8ϵ(\xf1bos\xd4\xcb<\xaf\x00\x14\x05\x18̀\xa2\xe8O_\x86yGum\xf5\x0es\xc6KX^\x1aa$\t\x00C\x06(\xca\x100pf\x83\xd5dM>\xfb\x12\x82b\x88\x91$\x00\f\x19\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\xa3\x99C\x11#\xef)Jm\x11\x87\xb4B\x8c\xe7L\xe2\xa3\x11\xda2\xbf\xc3 E\xf1\xe6R\x8a\x1f\xe7~\xc0~\xe0$\xb8?\f\x96\xcd\xdcF\xf2\u07bc\xc1lM\xab\xb5>B\xdbx\x9e7\xfbv\xc3m\xed<>\xb1\x0f\x9d\xe0yoΆ5qg\\ɿ\xedX\x12\x93\xdc\xe7\x9e\xcbbs\xd0\x17\xacl\x83\x1b\xa9\xe0 _\x80\xef_Vi\x19\xa0'\xc6(\x8aW\x97RԖWX\u007f\xab\xfe@\x9e_=\xc7\xcd\x002\x83v\x93\xf7\x1a\xf3\x1f\xca*?\xe4\xf9\xff\x8b\x1e8\x1c\xa5\xfcU\x8db\"\xdd5|\x8c\x03u\x9e\xe0k\x14^\x1d\xb2\x95*\xe6\xac\xf9\x84+\xf9I\xdc\xd7\xe9\xe6'\xee\xb9LJ\xc6n\xf7\xcc4\xba\x914\xa5Q\x15b\x82\xd92@W\fQ\x14\r\x97\xd2*\xe2\xb6ѓ\u007f\xdc[\x1d\x80;7Ư%\xef\x8f-)\xc2\xf1\xd6\xf9\x9ep\xb0\"\xec\xd3\xe1\xdb\xc1\x8a:\xf9\xf4m\b\xdd\xe7\xdd\x1f`\xbb\x9a~X\x9c\xf4{\xff\x98/E}\xaeP\xad?2\xae\x0f\xbe\xe5\x9ee|#e\xee\x9ar\\IF\xcb\x00}1BQ\xb4\\J\xcb\xc5'\xe4\x1f\xf2'\x130\x03\x88\x9f*\x9e'昉\xc9z1OL7\x06q\xb0֚\x9f3\x0e֕\xcc\xc7O\xde彞\xe9(\xe9\x98\xeaa\xe41\x9c\x8d̰Jn\xb0\x8c\x96\x01\xfab\x84\xa2h\xb9\x94\xb6\xe5\x1dk\xedi\xad\xca\x1by\xb3\x8c/͍\xb7\xc3\xc6MY\xd0▤ɝb\xc7o\xb7&:\xad/&\xd2\x16h\x8d&\x9e\xdfs7}YL\xf2\x8b}<\xcfW\xa2J\xe1u\x9f\xb2\x82\x9e\x89\x1f\x8b\x89\xf72\xc8\xdb\xe3brf \x1d\xac\x92=*B\x977\xd8L\xb1\xc96\xf2T~\xc9\x13\xb5\x93\xbf\xbf\xf2\x84\xf3`eZ\xa9>1\xf3|\x14~\xee6\xea\x8d\x15sw)r\xa9ʨ\xf6\x92\x05\xebCܟ\x1blh#\xcf\no{P\x81\xf0\x8a\x9f\n\xdek\x91\x86(\xac\x96\x01\xfab\x84\xa2 -\x97Ү\xf2\xec\xec\xec#~\xb4\xab\x8fM\b\xdf\\\xbe\x91۪L*x\x8b\x9b\x8f\xdfzvo\x17ɥ\x8d仫+m\t\x16ۮ\xb4y\x0f\x1f\xa5%^\xeeD\x9dW֤\xfd\xa2\xac\xe0\"wL\x8c\x8d*\xa6\xb3\xa5\x83U\xb2GE?\xcdK?QS\x16\xcb\xe3\xa3]\xf6D\x15\x0e\xd6\xd2d\xe7\xc1ʴRE\r\x0eG\f1\xfc@7\x1d\x95|\x81\xc3\xf1\xb32W\xae\x8cj/Yp\x92;\x85\x14\x18\xdb\xc8\xe7Wl;\x1e\xa1G\xfb,\x97q\xb9\x9b\xbcC^\xb3G\xcb\x00\x9d1VQ\xd8.\xa5=\xe5\xf9\xf5-\xf5\xf9\xe5\xf415\xaa\xe9\x9a>\xbf\vO\f\xb5)\x92J\x9a>\xbfA\xde\xef5\x89\xb8\x1bɯ\xe4?y\x86\x06\x9e!T\xb1\x9c|~\xbf\xc2-\xa0\x84\x13+\xb8/\x1a\x87\xb9p\x1d\xac\x94=ji\x1c>LK\xf1\xb3*)OT\xe1`\xfd%\xe6\x17r\xb0\xb2\xadT1.\xedP\x9eP8s\xa9ʨ\xf6bnqn\x8f\"7\xba\x91\x05x\xfc\x92.\x8e\x8b\xce\xf1\u007f\x95c=Z\x06茱\x8a\xc2v)=\x9e\x8f\x87'=\xf9'U\n\x8f:J\xb8\xef\x19I&M\x9c\v7\x0f\xb4\x95\xd1\xe2\xcf=j\x8c\xea~^\xf1\xe4Et\xa3[\xc9Bg\x89^\x13\xf3矲G}h]\x96Uv\xb3\xaf\x17ў\xa8\xf8`E\xc9\xc5\xe4`e[\xa9b\xbc*\nU\x19\xd5^\xcc-w\x8fe\xa3\x1b\xf9`\xde_P\xb7\xa5\x86\xa4O\vuHx\xb4\f\xd0\x19c\x15\x85\xe9R\xdao\x17\x0f\xba\xef\xed\xfd\xac\xa2\xa3\x90\xad\\\x17#ɦ\xaaH\xa4\xca-\u007f\xe5jg\xa2\xdb\xd4X\xcc\xef\xbb\x1d\xe5v\xfd\x14\x9dr\x8dߝS\x14\xbd5\xe4\xcdu\xb0\xd2\xf6\xa8O\xcaR\x13\xf8%\a\ahOTr\xb0\x9eXI\x0eV\xb6\x95*ƫ\xa2P\x95Q\xed\xc5|˹\xff:\x18\xdd\xc8\xe4\x1ct\xc1\xd2K\x92W\xe9i`ϖ\x01\xfab\xac\xa20]J]\x8ar\xd1o\x14\xa5\x9c\xbb\xc8H\x0e\x0e\xf9\x98I\xa8\\\xb7&\xe1\xf4r\xf7\x80\x8e`\xf1\xf66\x94\x13CfX\xaa\xf9G\xf8M\xfa\xf9\x97\xedQ\x1br\x84\xe4\x93ʘR\xda\x13\x95\x1c\xac\xcf\xcd5\xe4\xe7\x9fi\xa5\x8a\xd1\x18\xa3H\x95\xb9\x1d㟎oGJ\x8cn\xe4\x99E\xbdΓ\x1e\xf4<ڵ\x1c\xb1Z\x06英\x8a\xc2v)\xfd\x86\x9c\xf5t\xe5\u007f㭆\xd1DǔH<'\xf4\xc1*ERI\xd3\x177<\vR\xc8GhZ\x96\xe9\x02\xbf\xd3\xf9\x91*\xb6x\xa6\xa8\xc0\x8f-\x9f\t?\xc6}I\xcb\xc8'\xd7\xc1J٣\x16\x88s\x0fI;\x10퉊\x0fV\x94\x9e\x86\x0fV\xb6\x95*ƫ\xa2P\x95)\x15\xa5\u007f\xf6\x02W\xd2\xd5^\xa3\x1b\xd9\x1b{f\x91\xeb>\xdb\xd4\xf7\xa4;V\xa8\x96\x01C\x83\x11\x8a\xa2\xe5Rڵ?\xbf\xeeN]\xfe~\xff\xb9\xd8s\xf4\xf572K>\xe0\xecʤ\x82\x85\x9c\x97\xef\xf6\x8b\x1f\xc8Ռ\xfb\xe4\xc3A\xb3\xa5/\xc1u\xd4P\xc5~\f\xda\"&.\x98\x13+\xcel0]A\xe8!\xbe\x1d\xb5\xd8\xe1\xc0?\u07b2=j\x01o\xdew\xf6t\x06\x8f\x8f0\xc9\x13\xb5\xbb\x86?щj\xcd\xe42\n\xd3J\xb5\xf7\xaa\xc3\x11\xb3\xcdq\xf9\x99\xeb2\xcaU|`R\xb9re\x8a\xf6\xe2S=i`&\xb5\xd7\xd0F\xe2:\u07b5\xbcp\xb6\xe1vԟ]\xcd\xd9\xfa\xb2CF\xc0W\x8cP\x14M\x97Ҟo\x0f\xe4\x16~\xeb7\x97z\x04\xae\xbf3mbD\xa1{\x92&wr\xb6G\x9eDc\x14\x99HH&\x1f\x1a,\xfb\x04Ui\xf0,\xb6\xfeu\xe7\x9c@\xf3\x06\U000d253f\b\x89t\xe7\f\x04\x1e/\xc8\xf6\xa8\x15k\nl&k\x92\xf8\x93\xed\xf2D\xad\x9d\x87\xef\xd6\xe8K\xb4\xf6)be+U\xf4\x93\xd8\b\xbe\fu[H\xc2t[\x91KU\xa6h/:\x1e\xf2\x91\xd4F\xb9\xbdF6R\xe06\x9f!5b_\xcc\x151A\xb7\f\x18\x1a\x8cP\x14`\x88X5>_+d\x18\xd8?>~\x04\xfc8tF\xcb\u007f.\x1c\xc82\x91\x13\xa4\x91\xd12?\a\x14e4\xb3u\x9a\xfbm,\xc3O\xdb\xd4\x11\xf1\a\xdf\xea\xd8\x17\xf2\x87\x81b\xdb/#\xa6e~\x0e(\n\xe0\u007f\x14\xd4\x0e|\xe2\xf6\xa7\x05\xc0 @Q\x00\xbf\xe39\xbfz\xa7\xd5\xf3\xa1\x06\x80\x11\x80\xa2\x00\xfe\xc7>\xf3\xba\xdbZ1\xc0\xd0\x00\x8a\x02\x00\x80~\x80\xa2\xe8ϗL\xb4J\x01\x80?\x00\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0b\x90\xa2xw)\xed\xbfTh/\x94\"F=\xa0(@\xe0b\x8c\xa2xw)\xed/ʽ\xd8t\x9e<\xd8\xcd/piȟ\xfe\x0f(\n\x10h\x18\xa2(\x1a.\xa5\xdf۱\xf7\u05cfv\u007f\xb1RwJ\xc8?\xff\xe7\xff\x06\x8a\x02\x04\x1aF(\x8a\x96Ki\xc9\x11\x92\xcc\xf3\x97A\n\x11\x90\u007f\xfd\xaf\xfc\u007f\x871\n\x10p\x18\xa1(Z.\xa5\x85\xa2\xb3ġ\x12f\xe9ч \x1f\u007f\xfa\x1f\xa6\xff\xf2/_*\x10\x16\xdcM\x8d5\xc5%?@\xca$\x00\xf8\x11F(\n\xd2p)=\x99\x87\xe7g\xbbr\xfd\xc5\xed\xed\xcb/\xff忘\xfe矈\x8e\xfc\xe9\xff\x88\xfcIP\x94Z\xf3\xea\xafj\nx\xec\x85E%\x01\xc0\x9f0VQ\xd8.\xa5\x1d\xbb\x8bZ\xbbZ\x0ee\x8fć\xa6\xbe\f_\xfe\x0f\xfe\xbf\xfe\xabsd\xf2\x8f\xce\xc74\xff㗨ۖ܍Po\xf5cD'\x01\xc0\xaf0VQ\xd8.\xa5\xa8\xad(;\xdb~\xaa\xe8\x10\xbb\xec\xa8\xe3\xcb\u007f6\xfd\xe7\u007fv*\xca\xff\xfe\x17\x91\xff\xfd%\xba\xc0\xdftEPI\x00\xf0+\x8cU\x14\xa6K)\xa6\xab\xad\x1f\xe5\xf9\x8b\u007f\xa4\xa0#\xffM\x1e\xa5H\xf3(żd4J%\x01\xc0\xaf0VQ\x98.\xa5\x82\xb4\xe0\x97\xeb\xd9-̢\xa3\x0f\xac\x1f\xf2L\x8a\xa4(5\xfc5W\x04\x95\x04\x00\xbf\xc2XEa\xbb\x94\xd6g\xb7\n\x8b\xf6\x1e\xf3Z\xc3(\x82\b\b\xbe\xda\xf3\xbf\x14\x8a\xd2iM\xc2\xd6\xdeYY\x88N\x02\x80_a\x84\xa2h\xb9\x94\xfe\x98\xfdݝ\xef\xf3\x8a\x9ej\xd53ZpJȿ\xfe\xe3\u007fW(\n\xaa\x8dY\xfe\xf5\x85,\xe2\xc6G%\x01\xc0\x9f0BQ4]J/\xe6\xe7\x16]\xec\xf7^\xc9(\xe2K&\u0082۩6K\xe2i\x12C%\x01\xc0\x8f0BQ\x02\rUE\x01\x00\xbf\a\x14E\u007f@Q\x80\xc0\x05\x14E\u007f@Q\x80\xc0\x05\x14E\u007f@Q\x80\xc0\x05\x14E\u007f@Q\x80\xc0\x05\x14E\u007f@Q\x80\xc0\x05\x14E\u007f@Q\x80\xc0\x05\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x01\x00#h\xf5\x9f\xbf\xc2z\x05\x14\x05\x00\f\xa0gҍ\xa7\x01\xa1)\x06)\nå\xb4\xe5\xc8^{\xfeI\xf2\x88\x03\xd4r(\xf7\x88\xbf<\xc1\xcd7\x9a7\x98\xadi\xb5\xd6Gh\x1b\xcf\xf3\xe6\xbbZ\xe1\xc0h\xe7\xe9\x98\t\xdfw\x04\x82\xa4\x18\xa3(\f\x97\xd2{\xd9%\xf5w\xea\x0f\xec\xc5\xcfY\xbac\xaf\xbaQe\xbf\xe3\xb5\n\xff\xa2\xc6\xfc\x87\xb2\xca\x0fy\xfe\xff\xa2\a\x0eG)\u007fU+^\x8dg?\xab/;zQ}\x19`4\xedc\xc6L\xbc\xe47\x0f\x15\xf3\x82!\x8a\xc2r)\xbd\x91\x8d\x15\xe4)N\xf6\xef\xc5Ϭ>\xb97\x10\x14\\\xe4\xb1%\xa5\x1b\xa1\xce\xf7\x04E\x11hxYE\xe9+\xb3\xacS_\xfa\xbb\xc5\xea\xcb\x00\xa3i\x1f\x13\xff\x9b\xb0\xfa\x00\x90\x14#\x14\x85\xe9R\x8a\xc8\xc6mŏ\xab\xae\xb7cK\xb0\xa7҃\xf1\xfd\x9f\x1c3\x19[\x14\xf3\xb7\xf1\xdb\xcb*J\xe3j>ŋ+a\xf8;\xea\xcb\x00\xa3i\x1fSx\xfe7S\xebe\xf3;\u007f\xc5\bEa\xba\x94\x92\x05\xb7\U0008b10f\xe5\x87ɧ\x92\xa3\xac£\x92\xcb\x1bl\xa6\xd8dۀpZ\x92j5\xd9R\x1a\x85\xbc}<\xcfW\xa2J\xe1u\x1fz/\x83\x84=.&&\x1b\x92\xa2\f|\xbdڼ\xb2t@Y\x03\x1a\xa8H4'\xecz\uef8e\xce]Q\xb6\xb3\xee\x99\x12E\x9cH8B\x97\xc6r\xdc\xfa\xebKg\x84\xcc\xefY\xc1\x05塦\xf1\xdcl\x12\x93\x17\x11:k\x95\xbf\xd8\u05cft\xda\xc7\x1c\xf8\xf5\xe4k3\u007f\xf4{I1BQ\x10ۥ\xb45;;;\x17\xcf\xcc\x16\x8aF='\v\xd5J\x8f6~\x9a\x97~\xa2\xa6,\x96\u007f\x81\xd0Y>\xa3\xb6:%\xaa\x01\xa1Gi\x89\x97;Q\xe7\x955i\xbftG)\xecI%EI\x8f\xdesnOt\xba\xb2\x06\x94\x11\x95u\xae4ne\x9fb\x15\x03\xa7\xad\xa6\x9cN\x92\xec\xbe/\xa2\xb0\x00\xea8Y5knUU\x950\xee\xeb\xca\xdf;c\xd6\xc4髖rM-U\xe36\t\xba\x1e\x1f\x8cC\xe2\x83>(\xd9>9<p\xce5\x87\x95\xf61\xf9\xbf\xfez\xe4\xb5\xd97\xfc]R\x8cU\x14\xa5KikK]\xfe\xdevi\xe1wy\xaa\xc5G\x19\xa5qX\tJ-\x82\b<\xaf\x16\x0e\xfb\x81\xf7S\x84\xcf\x15\xcb\xc9\xc2\xf7+\xd0}^\xf1\xccj\x97\xa2\\\xe0k\x10\xf6\U000b9828\xe1,_Ab*\xe9\"h'\xbf\xb2ٙLr\x1a\xa1\xaeAJ\xa8\xb3\x9ep\xee\xcd6\xf1d3XP\x14\xb4\t+J\x11\x97+\xbc~\xcb\xedG\x80\x01\xb4\x8f\xd9\xff\xf7_\u007f-|-\xbc\xc9\xcf%\xc5XEqw)E=\xf9\xe5\xc2\x18\xa5\x8a\xa4\x8f\xf9\xcd\x18\xe5\xa1uYV\xd9\xcd>lɃ\x1e\x97&\xbfk\xe1?\x14R\x8dQ\xdd\xcf+\x9e\xbc\x88nD\xbd&\xe6\x18%\xe3}\xf2\xb6|\x9b\xa2\x86\xb4w{_\b\xd82\x14\xab\xa8\x88^T1 &o\x9f\x11\xb9\x8d\x94Њ\x12\xdc\xe4LɊ\xb2xf\x0ffZ<\x02\f\xa0}L\x9e\xa0(\xbf\xe6\xbd6\xb7\xa9\a\xf93\xc6*\n\xe5R\xda%\x8e\xb6/\xd9\xfb\x9d\x16\x83\xe8\xd07̢\xa3\x91'e\xa9\t\xfc\x92\x83\xc2!\xdf\x10g\xcb9\xedX\x87\x15\xa5\xdb\xd4X\xcc\xef\xbb\x1d%\x9c\x9d8\xe7QzkțKQ\x12S\xc8[r\xa2\xa2\x86\x0f\x9dC\x90\x14\xe5*\xeen\xe0\x13\x9b\x917hE\tw\xa5dE\x99\xe3\x9ciy\x8bQ\x14Н\xf61\xbb\xff\x03KJ\xe6\x98\xf9\xfe-)\xc6*\x8a\xecRڟ'\xce\xc3~/(J}6\x1e\xb9\xb4e\xfb͵\x9e\x86\x1cA\t\x9eTƔ\"\x94\x90\x88\xa7TS\xb1\xa2\xa0\x84\xcauk\x12N\xe3s\x9f\x9c\x98_pF5\xff\x88\x84\xbb\xc6(\uf489\xd8e\xe9\x8a\x1a\xd2\u07bdFx\xec\xb6\x12j&\x85\rQ\x14;\x19\x9c\x84\xbf\xed\xca$\x8a\xb2\x1e+\xcaҙ\x17\t\xad*\xc5\x01]i\x1f\x93K\x14\xe5\xd7/Ƽu˟%\xc5XE\xa1\\J\xf7\x1e\xc1\x19䬧\x9f\x18\x94\x1e\xf5\x9f\xfbQ\n\xf0T\bBI;\x10\xb2\xa5\n\x89\xbe\x95DQҲL\x17\xf8\x9d8\xe3\xb1\xe53ᄦ/i\x19\tw)\xca92WRɟS\xd4P\xc3W\xe3d\xceA\x8f\xd5t\ue2b2\xd6x\xe4JDF\"t\x8f\xcb\xc7Iy\xb8\x12\xfa\xb1\xb0\xbd#\xb0\xa2\x1c\x11\x17\xfd\xf1svi@_\xda\xc7\xd8\xff]\x94\x94\xf5c\x96\xde\xf1cI1BQ\x98.\xa5?f\x97\xd7ߩ\xcf'\xf7\xcc\u07b2\x1f\xbdq\xcc~K\xa3\x9a\xd1C\x01o\xdew\xf6t\x06_\x8b\x93\xa9\xa5\x05+\xf9د\x04\xd18h\xb6\xf4%\xc4\x14\xe0\x88\v\xe6Ċ3\x1bLW\x10z\x88\xef\x99-v8\x1e\n\xb9iQ9gs\xa2Ҕ5\xa0\x9cyi'\x84\xa4rfV\xa4yM*#\xd7\xc9\xc6\xe0-\x85o\x86\xdeA=\xa7\xc8e\x1fq&e\xee\xe4/>\x8f\xe0\xc6\xe6\n\xe3\xc1\xb5\xdc\xe2\xfcC\xf1\x9c\xdḟ\x8fl\xda\xc7d;\x15\xe5\xd7U\xaf\xadh\xf1_I1BQ\x98.\xa5\xa8\xe5\x9b|{\xe1)q\xe2\xbb\xe5\xb0\xfd\x90\x1f\xfd\xaf\xa7bM\x81\xcddM\xc2r\xd0W\x9c\x10\x1d\x97V\xf1\x9e)I\x18\x8bX\xf6\t\xaa\xd2@B\x9a7\x98\x97\xa4\xfcEH\xa4;\xa7I\xc8X\xa6\xf4C\xf3\x87\xa5}\xca\x1a\x84QʺX˚\vj+S\xa5냰\x90\xb9\xdf\"t)\x88̗, \x99\xd7#C&\xce\xff#ǭ\x10\xd2G\"\xc3&\xcd=\xec\xbd\x12@'\xda\xc7d\xfeۿ\xff\x87x\xdcĿ\xb6\xca\u007f%\xc5\bE\x01\x80\x80GP\x94\xff\xe7\x1a\xa4\xfc\xfa\xf6kk\xef\xf9\xab\xa4\x80\xa2\x00\x80\x01\xb4\x8f\xd9ޏ\a)\u007f?y\xfc\xf8\xf1c\xaf\xbf\xb6\xb1\xd5O%\x05\x14\x05\x00\f\xa0}\xcc\xd6\x1e2H\x996\x86\xf0\x9b\xedm~s%B\x01(\n\x00\x18@\xfb\x98-]\xe8\xdf\xec\xff\xfek\xf9\x98\x05\xff\xb4y\xf3\x16\xfb7~\xfaP7P\x14\x000\x80\xf61\x9b;z6\xbe\xb6\xf9ᅫ\x9ft\xb8\xbe\xa9\xa9\xa9\xd5O\xef\xc6\aE\x01\x00\x03\x10\x14\xa5m\u0558\xff\xf4\x0f\xff\xfe\xeb\xde\xd72[z\xfa\xfb\xfds\x84\x02\x8a\x02\x00\x86 (J\xfc\x987>~-\xf3\xef\u007f\xff\x87Yu~:>\xc1\x80\xa2\x00\x80\x01\xb4\x8f\t\x1d3g\xf7\xa9\xd9\xdc\u007f\xfc\xba\xf97\xf9~:\x87\x82\x01E\x01\x00\x03h\x1f\xf3ZD^]k\xf9k\xb9\u007f\xff\x8f\u07fc\xe5\xc7\u007f\x16\x04E\x01\x00\x03h\u007fma~}G\u007f\xdbl\xee\xdf\xda~\x13Y\x0f\x8a\xc2D\xabr\x00\x00D\x9e\xfe\xd3qAPP\xcf\xe1\xdf\xfc\xa7\xdf\xfcç?\x82\xa20Ѫ\x1c\x00\x00\x91\x9e\xb6V\xf2H\xa0\xf6\xa2\x88\xf9[N\xc2<\n\x1b\xad\xcaG:\x8b\xb9\xb0\xdf\xfb\xcdCY\x80\x91\x8d\xf3rq\u007fۍ\xba\xeb\xfez\a>&\xa0\x15\xa5\xe5h\xee\xec0\xf1a\xf0m\x11\x87\\\xb9T\x12\x00\xf4\xa6\xbf\xa7\xa7\xc7\u007fG(\x86)\x8a\x86K)\x1d`,ǸKbbs\xd0\x17\xae<*\t\x00\xc0\xa00FQ4\\J\xa9\x00\xa3\xf9\x96;\xe5L\x95\x8cݎ<\x93\x00\x00\f\x06C\x14Eå\x94\x0e0\x1aYQ\xd0\xfa\xe0[\x8c$\x00\x00\x83\xc0\bE\xd1r)\xa5\x02\f\x87R\x94\x8e\xa9\xf1\x8c$\x00\x00\x83\xc0\bE\xd1r)\xa5\x02\f\xe7\x12wLJ\xaf\x0f\xe9b$\x01\x00\xf0\x1d#\x14\x05i\xb8\x94R\x01\x86\xd3\x13\x16q\xf2\x8eS\xe4N\xca\xe3\x15*\t\x00\x80\xef\x18\xab(l\x97R*\xc0x\x0es\x1c\xb7PL\xde\xe2\x0e\xb8r\xa9$\x00\x00\xbec\xac\xa2\xb0]J\xa9\x00\xc3\xe9\x98<c\xeb7N\v\xcf[\xb2\a\xf0-\xb0\x03\x06\x80\x97\xc1XEa\xbb\x94R\x01\x86\xf3-WN\xa5O2\x92\x00\x00\xf8\x8e\xb1\x8a\xc2v)\xa5\x02\f\x87\xbaփ>\x1d\xdf\xceH\x02\x00\xe0;\xc6*\nۥ\x94\n0\x1cJQ\xfag/`$\x01\x00\x18\x04F(\x8a\xa6K)\x15`4\xa7dE\xd9\xca]d$\x01\x00\x18\x04F(\x8a\xa6K)\x1d`$=-\x17\x17\a\xbb\xdcQ\x8f\x87|\x84<\x93\x00\x00\f\x06#\x14e\xc4\xf2\x16\xc7\xcd8\xe4L\xef\x1f\x1f\xdf\xe3\x99\x04\x00`P\x04\xb4\xa2\xb4\\\xbc\xe3J\xb6M\xfd\x82\x91\x04\x00`p\x04\xb4\xa2\x00\x00\xa03\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x12(\x9cI|\xa4\x15\x12\x10\x90\xed0\xb4N\xb4\xee\xab\x18ڵ\x8d0\fR\x14\xef.\xa5\x1dU\xf9\xf6C\x97\xe0\xff\xbe\xbeS\xcc\v\xccK(\x1b\x10?\xd6ĝq\x8f\xd8&\x04\x98\xefʟ\x0f\xf2\x058\xb8>,\x17\xd9î\xbbG3\x19L,\x8b\xc6(\xa1\r\x19\xd2GF#u\xa18\xe6\xcfR\xfa\xbe\x89_\ue664qn\a\xb6\x13mc\xf2\"˚\xda\xf7\xaf0\x16\xb9\xf0\xa1\x17\x9e\xab\b$\xdf[c\x14ŻKi{\ue87a\xa6\xf3\xbb\vAR\xd8\xd4^\xf3\xc8z|\x90\xafp\x9cK\xe3\xf7\x89\x1fϚO\xb8G<p8J\xf9\xab\xd2\xc7Ҩ\n\xf2^έB\xab\xb8oH\xfa\xa8\xc6c\xa5\xe8X6\x8c\x96Q\xbc\xb8\xba\xf2}\xc7C\xe9#\xa3\x91Z5\xf8ć\xa6\xf7\xa5\xf4\xc0\xd5mўI\n\xd7v`:\xd1^3\xa5\x9c\xa8\xfc\x8c\xe7\xab\xf1\a\x95\x961{\xa1\x80\xb5\x8a\x00\xf2\xbd5DQ4\\J\xbf\xc9\xc7Ϛm\xb3\x9f\xf7VG\x00\xb3:\xd53\xaf\x86o\x16\x0e\x9a\x9d\xfcm\xf1c\x9fg\x04B\r\xb2\xa2\xdc5刉\xf3\xdcF\xb4\xd1\xf9\x84\xba\xdf-f\x95\x92\xa1cٰZF\xf3I\x12\xfd\x89\xd5H\xad\x1a\xb4\xe9\x8cJ\x8b\xea\x94?\x16D\xb3\x92.\xa4\xed\xc0t\xa2ݰN\x18[\fl\x13\x15E\xade\xccMM\xc1^E\xe0\xf8\xde\x1a\xa1(Z.\xa5\x85\xf9d\xe1\xd1\"v\xf1\x80g\xa5\x9a\xa2\xa0n\xcbN\xcfE\x12\x94\xa2dX\x9f\x8b\x89\xeb\xdcV\xb4\x9d\xbbA\xd2\xe1\xef0\x8bIбlX-\xa3Q*\n\v\xad\x1a\xb4\xa9\xe5\xaf\xf1\xb5\xf2G\xef\x8a\"m\a\xa6\x13\xed2\xa2\x05\x8d\xfci\xfc\xf6\xb2-c\xaf\"p|o\x8dP\x14-\x97\xd2\x16\xf1\xb9G'\x87\xc1t\xeb\xc6\xdba\xe3\xa6, \x0f\x86\xcc\f\x0f\x9d\x93)\xbc\xaf\xe0\xc6\xd9W\xcd\n\x9d\u007fK\x91T%/\"t֪\x0e\x84.\x8d\xe5\xb8\xf5ח\xce\b\x99\xdfC%݂s\xa7\xd8\xf1ۭ\x89\x9c\xc8D\xe9\x89O\x02;ySٮ\x04\xf3\x86\a\xf8\xc3@E\xa29a\x97\xf0\xdd<Ë\xacV\xd6$*\n\xda\x19\x8b\xd0\x133\xcfGU\x92\xdcg\xa9V\x93-\xa5\xd1\x19#+J\xaf\xc5\xf5\xbb\xd9\xca\xe5\xa1|\xae\x15\xa1\"g\x13\xc2I\xb6k;\xac\xe0\xc6n\x8f\x9f\x16\xb6\xf0\xba\"\x96\x8d\xa2e\x977\xd8L\xb1ɶ\x01e\x88\xac(T#\xe5XE\rR\x8f\xd9ۡ\xd1\xc4\xf3{\xee\xa6/\x8bI~\xa1\\G\x81\rYœ\xbf\aiVK\xaax\xaa#%\x95\xc5\xe4\xed\x80XN\xb4iV\xbcQ\a\xceu\xd2-\xa3k\x90{\xa1h\xe4\xe3\xf4X[NN\xac\xb9\xda\xcb*\x02\xc6\xf7\xd6\bEA>\xb8\x94\"Կ\xb7\x8aYt(96!|s\xf9F\xe1\xa7\x18\xa1\xf8\xe0\xf5%\xeb\x83\u007f\x8fP\xfdޱ\xdc\xe4M[&\xbe\xadH\xaa\x11\x1f\xf4A\xc9\xf6\xc9\xe1\xfd\xa8+\u007f\xef\x8cY\x13\xa7\xafZ\xca5QI\xb7跸\xf9\xf8\xadg\xf7v\x91\\Zr\x9a+M|\\\xc1\x9f-\x9f\xe1\x0f\x19QY\xe7J\xe3V\xf6\xa1\xce+\x8e\x84$\x87\xc3q[Y\x93SQ\xcaxa\xc0\xdf\xe0p\xc4\x14\x90ܳ|FmuJT\x83\x18#+\xcaM\xde\xe1L\xf5O;\x85\xbe\x9b&\xc8x\xc7ɪYs\xab\xaa\xaaȔ\xb9\xb4\x1dp\x8fg|\xfe\xe9\x8c\xd0::\x96\rݲ\x9f楟\xa8)\x8b\xe5ݎvj\x8c\"7R\x8eU\xf4M\xea1{;tWW\xda\x12,\xb6]i\xf3\xe4\x99\x19ºT\x94\xba\x0e'\xeeZ\x12*\xcel\xe0\xa3\x15Ie1y; \x96\x13\xedC[Tr\xc1\x0f\xbdH\xd17E\rR/\xe8F\xf6.\xb7\x96\xee\x8b1\x97m(\xf6\xb2\x8a\x80\xf1\xbd5VQ\xd4]J\x85M\x9e\xdb\xc6.;ttM\x9f߅\x1d>ڰY)v\xfb8\xc2\x1d\x16^\x83'\t\x83\x92\xa5\x93\x912ɤ\x88\xcbEآ\x838\x10\x86so\xb69O\xe9\xa8$M\xd3\xe7\xe29Ľ&\x11\xb7\xc7\xffG[\x84\x9f\xbc\xf48\x84\xa5\x01\xcf\xee5\xf0\xe4\xf7P\xfd\xac\a]pN\xa48\x0f\xd6\xe7Ղ\xc0\f\xbc\x9f\"\xc6Ȋr\x8e\xff\xabG\r\xd4Y\x0f\xb5\x1dP\xf0\f\xdc\xf0\xe9\x11\x8cxO\xa4\x96\x95\xc6a-)\xb5\xb8M2(\xcfz\x9c\x8dT\xc4J5\xd0=V\xdb\x0e\xfc'\xcf\xd0\xc03\xa4\xa0\xcf\\\x8c\x8a\u0378\xae5\xef\tC\x99\xbe\x0f\xa3\x95IE1\xc5v`8\xd1>.\xf8\x83\x89\xb7T\x8b\xc5䭮X\xb1\xb3\x17T#\xabyaTX*\xee\x10\xd5U\x04\x8cﭱ\x8a\xa2\xeeR\x8aNe\xbb\xff\xa0\x0f=%\xdc\xf7\xaed\xfco\xc9\xdb\x1b\xf8l7\x18\xbfl\fF\xca$\x93\xc53{0\xd3\xc8Irx\xb0\xd4\x05*ɠ\x89s\xa1\x8c\x8aNGγ\xff\xb4w{_\b\xd8ȵW/\x8aR\xc1?&\x1f]_\xf3ǥ\xc9\xefZ\xf8\x0f\xc5\x0f\xb2\xa2\x9c\xe6\xef#O$E\xa1\xb6\x03\n\xfe#~\xcd\xe4|\x92w\xa9e\x0f\xad˲\xcan\xf6\xf5\xba-g*\x8a\"V\xaa\x81\xee\xb1\xdav\x88v\x1b\x9e`\x1a\xf9+\xddW\xf0!\xfd\x84/ß\xf7D+\x92\xcab\x8a\xed\xc0v\xa2\xed\xaeI\xe6\xcf\xe1\x04\xad(\xf4\x8a%E\x91\x1a\x99c\x11^n\x8b\xb3/\xaa\xab\b\x18\xdf[c\x15Eե\xb4\xe7\xa8]\xbac\xc58\xb6rҹ\xed\\\xd1M}\x01\xfem\x0e\xde(\xbcl\x12\x15EN2\x99\xe3T\x86\xb7\xf0\x87\xf0p)\x9fJ\xb2\xa8*\x12q;ϋ\xc6_V\xf2%\xfd\xd0y\x1eOF\x1b^\x14\x85|\x99\x91\xf45o\x88\xb3\xe5\x9cv\xac\xf3P\x94\xab\xd4ud\x19IQ\xa8퀂7\xe1\xd7c\xbe\x19\x16\xc9-{R\x96\x9a\xc0/9\xa8:\x8f\x82q\x1d\x8bt\xacT\x03\xddc\xb5\xed\xe06\x97D(%\xcbKqo\xc9\xe9\x06.F%\x95\xc5\x14\xdb\xc1Ӊ\xb6\x81̊\xf4%\xbaouŊ%E\x91\x1aY<\xef1\x1e-\x8ac\x14\xb5U\x04\x8cﭱ\x8a\xa2\xe6R\xfa\xb4(\xcfe\x9bc$\xe5\xf2q\x13?\x93\xbc\xcd c\x14|P9\x15EN2Y:\xf3\"\x81L_\x86\xcb\xf3-\xe1^\xa6^ԑ\xbf\xa4i\xef^#\x90\x11\b\xf9nW(\u007f\x9fEE\xe9\x8ds~\xed\x9d_\xf3\x84D|\x9d!\xd5CQ\x9eG\x17 O\x88\xa2؛\x14\xdb\x01\x05\xaf¯\xf6A\x8cQp\xcb\x1ar\x04}xR\x19S\xaa\\.*J\xe7>\xc5@J\x11+\xd5@\xf7\xd8\xdbvp'uuCC\x03\xbe\xd2\xfb7\x9eT\x98\x1e\xadH*\x8b)\xb6\x83\xa7\x13\xad5\x8b\xbc弇_\xa9\xad\xaeX\xb1\xa7\xa2<\x8cJ~ؘ\x90(\x9e\xf1\xa9\xad\"`|o\x8dU\x14\x15\x97\xd2\xd6\xfd\a\x84\xcd\xddo\xf8dxǔHf\b$f\x00\x00\x03\xb5IDAT<\xa3\xf3\xc1*<\xf0ǃ\xd2\xfd\\\tRW\x94\xa6M\x1e?\xdcG8r\xe5\xfb\x8f\x9f\xe3W\xeaj\xacʅ٦/\xbc]\x8b\xa5\xbe\xa45\xe2=\x119\a\xf1k\x92p\\>\x123\xa4\x1aDE\xc9\u1777a9\xbf\xe66\xfc\xd5\xef[\xe9\xa1((\xf5=\xc6m\x14\x91\x91\b\xdd\xc3\x1d\xa0\xb6\x03\n\x9e\xd2!ďt\x0fft\x9ejY\x01\u007f\x81|\xde!ƺ\xba)*\xcaM\xfe2\xf9\xe4l\xa4\"V\xaa\x81\xee\xb1\xcav\xa0\x0fli\x15\xd6]\xc2\xcb.\xab\xf0\x92h\x13t\xe7vL\xb42\xa9,Fm\aʉ\xd6UY\xac\x15+W\x9fX\x80\xda\xea\x1a\x8ar\x8d_\xc2\xf3\xeb\x1e8\x97\xb3W\x118\xbe\xb7F(\x8a\x96Ki\x93}\u007fSKK\xcb\xc9|\xad\x8at\xe7\xe8\xebod\x96|\xc0\xe1K\xbaK\x83\xd6\x16\xad\rZ\x8aPKո\xf8S\xe8b\xfc\xb8\xaa\x16*\x89\xa3\x17r\x13<~\xb9\xd7r\x8b\xf3\x0f\xc5sy\xa8\xe7\x14\xb9v\"\xfc\xe2\xd3I7\x16r^\xbeW?;Lۮ\x0e\xdc\xdcfr\xfc,\x1cC\xf3\xd2N\x9c\xce\x10g$\v\xa2\x8bO\u007fb~H\xd7@\ue67d\x90N\xee\x99\xed\xbd\xeap\xc4ls\\~\x86\x0f\xd6\xd4҂\x95|\xecWW\xd1C|\xcfl\xb1\xc3y\xcf\xea\xed(\xf9Nu\x89\x8d\xc1[\n\xdf\f\xc5\x17\xb0\xa9\xed\x10̅\xe7\xdbgM\xf2P>V\xe7\xe5\x96\x15\xf0\xe6}g\x85\xf6\xd6:cI#_\xfc\xb0\xf2}\x87\xc0\xd7\xc2I\x88\xa2\x91T\xac\xdc7\xa9\xc7\xec\xed\xf0\xe2\ar\xf5\xe5\xbe\xd4\x1c\xb2\x8a\xee\v|N'\xea\xcc\xe1/t\xa3f\xb3\xad`Ϣ(SE3\x95t+Fm\aʉֵ[by\xeb\xbe\vBsn\xd3-\xa3k\x90{A7\xf2ZL\xcd9\xc7\x03\x97\x8e\xb0W\x118\xbe\xb7F(\x8a\x96K\xe9\xe1l\x91a\xb8\xc3\xed\xfa;\xd3&F\x90ɝ\xfe\xcc9\xa1s2\xfb\xf1M(\x1c7\xae.Tx]A%q\x88}\x02'M)K\x1c\x89\f\x9b4\xf70B\x97\x82Ȅ\n\xfejRI7r'g{f\xba\xd8\xc9\xf3\xbc\xe9/f\xe1\x15߶V\xb3.ֲ\x86\xfc\x98\xa3\xee\xacE1I\r\x8a\x1a\xc8\xffz\xf8ed\x02\xf2\xa7(q\xaeA\xf8\xd0W\x9c\x10\x1d\x97V\xf1\x9e)\t\xa5;g \x9c?\xaf\xfbb<\xff\xac\xd2\xf5AX\xc8\\\xb1G\xf2v\b^\x15?q\xeaR\xcfsPf祖U\xac)\xb0\x99\xacI\xce;͜\x8dlt6\x8c\x17\x0eQ\xaa\x91\x8aX\xaao\xae\x1e\xb3\xb7\x83\xb3\xb2d\xa4XE\xcd<|\xcf\xfc\t\x9e\x9fW\x83\xd0ݔE\xcbr*L\xb8\x98\x94t+&o\aډֵ[\xfeP\x96\xb3\xdc\x1c\x97\"^>s\xb5\x8c\xaeA\xee\x05\xdd\xc8+&\x9cgZӬ\xbe\x8a\x00\xf2\xbd5BQ\xfc\x86B\xdff\x17F\"\x03Y\xa6j\xad\x18\x8283\xcb`\x14w\x9eµ\x1dtt\xa2}d\xde\xf1\xe8ŋ'?}\xb6\xe8\t\xf9\xccX\x85\x8ek\x1b\xf1\x80\xa2\xf8L\u007f\xee\xa4\x15Z1#\x97\x81b\xdb/Z1\x18\x15E\x19ݝ\xa7\x10\xb7\x83\x9eN\xb4\xa7\x9dw\xe1\xf4ŊCJ\xcfU蹶\x11\x0f(\x8aϴ\x84\xad2|\xee\xd8xT\x14%0:\xffR\\\x8b\x12Ow\x9a\xa3njD\x06\x04\xa0(\x00\x858\x17\r\f\x86\xbe\f\xf3\x8e\xea\xda\xea\x1d\xe6\f\xb7\xbbq\x02\x13P\x14\x80\x82\xccE3.R\x01^\x188\xb3\xc1j\xb2&\x9f\x05A\xc1\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xff\x1f\xec\x88D\xdc\xfa\xfa\x88\xfa\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/error1.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x04\xc1\x00\x00\x00\xbd\b\x03\x00\x00\x00\x8d\xa5\x9a\x96\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x02\x05\x01\n\x03\x01\x05\a\x03\x1e\x01\x00\v\r\n\x10\x12\x0f\x16\x17\x13y\x00\x01\x19\x1b\x18\x1b\x1b\x14\x83\x01\x00\x8c\x00\x00\x8c\x00\x04 \x1f\x19!# #$\"%%\x1e$%#&'%'(&+)\x1e()'++$*,)/,!-/,02/63(241\x98\x1b\x1b786;8,\x82%#:;9><0>?=C@4@B@\xa0*,CEB\x9c.-KH<MH7\x00f\x00\x00g\x00\x00h\x00JKI\x00i\x01\x00j\x02MOL\x04l\x05TO>\tn\aPRP\xa9:<WRA\fo\t\x0fp\vTVT\fr\x17\x11t\x19^YG\xaaDCY[X,`\xae7]\xad\x15v\x1c\\^[\x19y\x1e;b\xac_a^faO>e\xaf*{!bda)}*Bh\xb2egdLj\xafpiR.\x81.Em\xb1ikh\xb3XX0\x8301\x841/\x858Jq\xb5mol;\x86:Vu\xb4>\x89={t\\tvs@\x8b?B\x8c@@\x8dG\\z\xbay{xJ\x8eI^~\xb8\x84|d\xbbkkL\x90K~\u007f}O\x93Mb\x83\xbdN\x95UW\x95V\x82\x84\x81\x8f\x85hm\x87\xbdZ\x98Y[\x9aZ\x87\x89\x86\xc0{|]\x9c\\\\\x9dcr\x8d\u0096\x8cnd\x9dd\x8c\x8e\x8b{\x8f\xc0f\x9fg\x90\x92\x8f~\x93\xc4j\xa3jy\x96Ŕ\x96\x93s\xa4l\xa1\x96xq\xa5s\x81\x99×\x99\x96\x83\x9bť\x9b}u\xaaw\x9a\x9c\x98Ǒ\x92\x9c\x9e\x9b~\xaby\x88\xa0ʞ\xa0\x9d\x81\xad|\xab\xa0\x82\x8e\xa2ǡ\xa3\xa0\xa2\xa4\xa1\x81\xb1\x85\x92\xa5ʋ\xb2\x88\xb4\xa7\x83\xa6\xa8\xa5\x8d\xb5\x8a\x97\xabЩ\xab\xa8\x8e\xb6\x8c\x8d\xb8\x93\xab\xad\xaa\xb9\xad\x88\x9f\xaeή\xb0\xad\x96\xba\x96\x98\xbb\x98\xa3\xb2Ұ\xb2\xaf٨\xa6\x9b\xbe\x9aµ\x90\xb4\xb6\xb3\xa3\xbf\x9d\xac\xb7Ҷ\xb8\xb5\xa2\xc0\xa4\xb7\xb9\xb6۰\xb3\xa5ħ\xba\xbc\xb9\xb1\xbdקƩ\xbd\xbf\xbc\xa8ǫ̿\x99\xafƫ\xb8\xc0տ\xc1\xbe\xb2ɮ\xd0Þ\xc2\xc4\xc1\xbc\xc4\xd9⽾\xc4\xc6òͷ\xbb\u0379\xc0\xc8ݻ\xca\xde\xc7\xc9\xc5\xd8ɝ\xbdϻ\xc6\xca\xda\xc0\xcc\xda\xca\xccɿҾ\xd7ϡ\xcd\xcf\xcc\xc4\xd0\xde\xcb\xcf\xdf\xc8\xd3\xc1\xe0ѥ\xd0\xd2\xce\xc8\xd6\xc9\xea\xcc\xcb\xd1\xd3\xd0\xd2\xd3\xdd\xca\xd8\xcb\xd3\xd5\xd2\xdf֨\xcd\xd6\xde\xcc\xda\xce\xe6֪\xd6\xd8\xd5\xd4\xdb\xd0\xeb\xd4\xd2\xd2\xda\xe3\xd8\xd9\xe3\xeaۯ\xda\xdc\xd9\xd7\xde\xd3\xe1\xdb\xda\xd5\xdf\xda\xdc\xdd\xe7\xdc\xdf\xdb\xd7\xe1\xdc\xde\xe0\xdd\xdc\xe1\xe3\xf0\xe0\xb3\xe0\xe2\xdf\xe2\xe4\xe1\xee\xe1\xe2\xdf\xe5\xe7\xe4\xe6\xe3\xe8\xe5\xea\xe5\xe7\xe4\xf2\xe4\xe5\xe6\xe8\xe5\xe3\xe9\xeb\xe7\xe9\xe6\xe8\xea\xe7\xeb\xed\xea\xf6\xf0\xef\xf2\xf4\xf1\xfe\xf8\xf7\xf9\xfb\xf8\xfe\xff\xfc!l\x99S\x00\x00 \x00IDATx^\xed\x9d\x0fXTם\xf7\xf7\xd9\xd9\xd8w\xd3$C\x03\x9b\x12-K^\xd6fm\xfb\xdc\xe1\x19\xa9\xbe+\f\x8d\x1d\x14\xd7?1+\xbeVQ\x8aV1\x1b1\x18\xe7a\x13\xa3\x82ƄL\n\x19%) B\xe6\x89E\x1eY3*\xbe\">\x19Me\xc1\x96hqm\x12\xe8S\xa6ѱ\xb6\xda\xe4\xf2(\xac\xe4y\xaf\xe7\xed\xa6\xe5y\xcf9\xf7߹ý3(\x03\x97\xd1\xdf\xe7\xd1;\x87;\xbf\xf3\xbb眹\xf7;\xe7\xfc\xee\x99{\xfejh\x14 \x00\x00\x00\xf3\x18\x1a\xfa\xabH*\x15\x8eH\xee\x01\x00\x00\xc6\x10P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x173\x15,p\xa0\xaa\xa2\xfa\x18O\x92\u0099\xba\x8a\xba\xceH\x19\x00\x00\x004\x98\xa8`A\xb7\xb7\xb3\xbb\xb3\xae\nK\x98\xe0\xf5\x9c\xee>Yq2R\x16\x00\x00\x00\x16\x13\x15\xac\xcbݍ\xb7\xbc\x1bw\xbd\xceT\\#;*\xf8Hy\x00\x00\x00\x18LT0D\xf5*\xe8\x0e \xe4=@wTB'\f\x00\x80;\xc1L\x05\xc3\xf4wW{\x05\x84\xea|\xf4/\xef\xfe\b\xe6\x00\x00\x00,\xa6*X\xd0\xedv{HO\xecX\xe5\x00\xde\x0ex\xea\"\xe5\x00\x00\x00`0U\xc1P0\xd0^M\"\xf9\xbc\xc7\x1b\xec\x0fx\xddՑ2\x00\x00\x000\x98\xab`\x98\x81\xea&\xbc\xbd\xe6\xc5ݱ\x16\xaf7\x925\x00\x00\x00\x83\x89\n6 З3n\xfa\xda\u007fM@\x95\xc7\xc2f\x00\x00\x00\xd0b\x9e\x82\t\x95b\xf8\xfeL\x05V\xb0A\x92\xea\"\xb7%\x01\x00\x00F\x8cy\n\x86\xaa\xe8\x14\n:\x8a\xect\a\x11\xe2\xab|\x91\xb2\x00\x00\x00\xb0\x98\xa8`]\xee\xa6\xce\xeeN\x1a\xc9\xefr\x9f\xec>S\xe9\x85\t\xad\x00\x00\xdc\x11&*\x18\n4UWԵ\x90y\x14\xe8t\xb5\xc7{Z\x88\x94\x01\x00\x00@\x83\x99\n\x06\x00\x000:@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]bK\xc1\\.\xbd$\x00\x00\xf7+&+X\xbb[z4~\xc0\xeb9\x10\xf1\t\xad\x1fs;u\x92\x84z\x8e\xe3\xcaQ9\xde\xd6\x0fϦ\xd0k\xe3\x16\xe1\x17\x176K\xeb\tc\xa7\xe5\xb8\xe3p\x98w\xef\xd0\xd9\xe8\xc0\a\xab\xc1/5\x1c\xc7\xea\xf7\x8b\x1cר\xfcq\xeeG\x8eY+[\x97|0,\xafH-k\x1b\x81\x17Gd{w\x8d\xfaً\x0e\xfb\x8f\xa2\xf28%\xed\x81\xc3\u007fX\xe3\xc3D(\xc3\xfd\x83\xb9\n\xc6W\x1c\xab\xa4\x89\xee\n_\x97\xaf\xa2;\x82y\x91\xfd\x8aN\x92\xc0\xbf\xcb\xed\xbe\x8e\xae\xbfŽ\x1b\xf6)\x89\x1d.;\xde^\xf2\xfbk9\xa3K|8\xcdi\xe1\xae\xe3;t\xa6\xd2z6\x92\xc5p.\xa5\xbdՇ_\xfaޚq\x89\xd9{\xc5o+\x97\xd3gm\x05\x87\x1a\x9f3\x96\x9e>\xff\xf2r\xa4\x87NqX\xbfa\xb8\xabF\xcdsԺ\xd2\xfa\"Y\x8d\x04\xed\x81\xc3\u007fXw\xd7\xea#\x81\xf5\x1b\xa9\f@41W\xc1\xbcM\xddT\xc1\x84*\xb2\xc6DZ\xaa\xf0_\xca=\\\x89NR\xe4\x02w\x1co[\xb9\v(,\xe5v\xf1\xb5\xe3\x0e.6\x14\xa9\xabpG\xce\x14~P\x18\xc9B\x87%b\x17\xb3~\x89v\xb7]Q\x9a\xd5yd\xeb\n\xd3y*\xd0W%\xdd\xe2\xd8G\xa2`wӨ}\xb8/)\xf4G\xb2\x1a)\xec\x81#|Xw\xd5\xea#@\xe37\xd2\t\x03D\x11S\x15\xac\xdd\xc3\a\xa8\x82uV\x90\xb3\x99\xaf\xe8\fk\xeeR\xfb].m\x17ll\x15,\x12w\xe7l\xd9\xdd\\K\x85e\xf4\xa5,$\xaf\xaa4s\xa9\xc19\xee\x102\xc2@\xc1t\x8b3f\n\xd6\xc3Es\xa0u\a\a\xbe\xabV\x1f\x01c\xe5\x17\x88\x84\x99\n\xc6Wt!Q\xc1\x9a\xf6\xd3\x1d\xfb\xc3.\xf5\xd1k۪\x93\x94`\x14\x8c/̴e\x15\x9c\xc3\u007f\xbe\xc4\xd9\xeaK\x16\xa4\xad\xa6C\xae+E\x99酮a\x17[\xe3ʴ\x05%X?\xcf\xd98\xae\xac\xa7h\xae}\x8d\xe6\x1b\xb4/\x8d\x13\x87d\x82\xc3\xf6jVf\xeb\xd6Yy<\xf1[\xe3\xcaJ/\xe81p\xc6\xda2\x87`\x8as\x98\x13YF\xde\xf7\xafβ9~\x94\x854\xa8\xb5`\xd9)^(\x85;Y\xbfXi\xb6\xba2\xc5\xe2\x14fR\ro\xa6\xbbk\x97\xa5-\xa9\x153\xf6\x14:\xf01\x88\xecc\x05ۊ\x8fl\xff\x8c\xf1\xa0)\x0e\x83\xbdDn\xbeh6\xea\xa0C<\x9a؍\x96\vi\xf0\x01\xe8\xb7\x03[!\xf5\xc0ʇE\x88\xd4\xea\x06\xce\xe4\xe20\xd945fZ]\xc9\xc6\xfaՔA\xc7\x19\x10e\xccT0o\x13\x92\x14\xacN\\(\xf2X]8s\x97\xed\x92NR\xe2\x02\xd7<00\xd0L\x14\xac\x99s\xb56\x16p\x1d\b}\xdch\xe3\x1c\xe553\xc8e\xdf3kA\xfd\xe1\xd5\\\xe8\xc5\xe6\xe2\xb66\xd78\x96\th\xa0\xb11k\xc1\x8c\xac\x92\"\xaeW\xe3\xf8\xac\xdf/\xf6DZgq%y\x9cc\xb7\xa3\x86\xfa\xcd\xda]\x9e\x95v\xc1\xc0\x19c\xcb\xece\x8a\xc3\u007f\xe0_\x90\xe7\xf7\xfb\x89\xe8\x9c\xe5\x8a\x1a\x8f\xd7;8\xed\xd8C\xad\x05K\xfd\x0fPG\xd6\ahY=\xeb\x17+\r\xb7\xac\xb1q\t)No\x16\xb7\xa6\xbccP,\x8e\xbd\xac\xb9\xcc^D\x92\xadi\xcb\xde:^No\x03`\x05\xbbR\xc4\xd5t\xb0\x1e\xd8\xe2\xb0عE\x8d\x87\x1d\xa4\xf9\xa2ڨ\xe7\xfc\x8d\\\xb9\xdfO\x15C)\xa4\x81\xad~;\xb0\x15b\x0e\xac|X\x91[\xdd\xc0\x99R\x1c&\x1b[c\xb6Օl\x1a\xbfl\x19t\x9c\x01Q\xc6D\x05\xeb\xf4\xf0\xb2\x82U\x9e\xa4{NV\x861ﵽ\xa8\x93\x94\xb9 }\r⋸\xbf\x91|C.y\x8e춧c\xa9+r\xe0\xd4\xca\x05x\xaf\xb0$\xe4bk\xe6ޥ\u007f\xd1/\xcde\x1c\xe93\r\xbf\x15 \x9d\x90\x99E\xd8\xfc\xb08\x8d\xc3>\x17\x9b\xf5e-7r\xc6ز\x87P\x8bÌ;j\x1d\xe4r\xa8\x9d\xa5U0\xb6\x16*~\a\xdai+A\x0e\u007f\x88\xdfE\x03X\x02\x16,\xc7ɾ\xdd\xcbm\\:\xd9y\x9cvK\x8fs\xcd\xf8\xad\xac5\xd8`\xb0\x91\x84α\x82\xd5؛\x893m\xe5uG\x91\x0e\xdcSs\x91\xf2F\xb9Q\x95Q$SH}[\xfdv`+\xa4\x1dEJ\x1fV\xc4Vg`\x9c\xb1\xc5a\xb2\xa9IƯ\xa6\f\x1a\xbfR\x19\f\x9c\x01Q\xc5<\x05\xe3+:\x05A\xe8\xae\x14\xf0\x95['\x0e\x1f}\xe1\xfa`/\xd9zu\x922\x17p\xaf\xa2\xa3\xa3\x86\xc6\xc1>\xab]3w\x16G\x83\xddv\"7$N\xd3'N\xb3(\v\xb9\xd8\n\xe7\x0e\xe2B\bYtr\xc22\xfb0\xb7\x14Y\xc1\x1aq6\x1e\xed|\x9e\xec\xa2øZ\x8e\x9e\xbd:\xce\x18[\xf6\x10Jq\x10s\xce_ʜ\xfbR\xfd9a\x10iaj\xa1\xd2\xcb\xf5\xe7\x15\xad\xec'\xdd\x14\x8d\xdfWɛRq\xd0@\xeb\x1arո\x16ѿ\x16Q\x15U\x87a\x05\xe5e\x92|h+\xaf\xab`jy\xa3ۨ\x8a\x821\x854\xb0\xd5m\a\xb6B\xba\n\x16\xb1\xd5\x19\x18glq\x98lj\x92\xf1\xab)\x83\x9e\x82\x198\x03\xa2\x8ay\nv\xd1-\x13@M\xe2\xac02\xac4\xe2\n=\aB\x93\nL\x1c\xacÑ\xb5\xf3\x90?O\xbc\xd8ȹDN\x9c\xb3\x9c\x1f\xa1\xe1A\xe7%R\u05cd~\xc5/\x1b\x16\x1f\x11\x91\x15\xec8\xea\xb0!I\xc1\xe8.?G\xef\xa1\xeb8cl\xd9C(\xc5A\xec9\xdfW_\xb8\b\x0f9\x91\x06\xb6\x16*\x82\xfdBڹ\xb4\v6A\xc7/-N\a\x1d\x9a\t+\vp\a\xa9\x80f)XN&\x90\r(.\n\x1c3\x16\x89\x87\xd6V\xde0\x92O\xcb\x1b\xe5FU\x14\x8c)\xa4\xbe\xad~;\xb0\x15\xd2U\xb0ȭ\xae\xc28c\x8b\xc3dS\x93\x8c_M\x19\xf4\x14\xcc\xc0\x19\x10U\xccS0!Hh\xf7\x04\x83\x02\xeat\x93\xa1\x03\xef\x0es/r+ף\x93T`\x14l\xd1r2\xee(\xd4^l\x9fq\xb5\xe4\xefРs\xd1ܳ\x14\x12\xd66\xbc\x9f\xc4(\x98]V0z'\xa1\x9e\xa3#\x1e\x1dg\x8c-{\x88a\xd7R}/\xd6\x01ҟ\xebk\xb4\xd7j\x0e\xcaւa\xc1[\x99(\xabf\x01\n\xf1K\x83\xe2\xa48\x99/Q\xb32l\xe1\x9aK\x93s]\xa4]\x98>\x98\xe3B\xef,\x1a?\x1a^yR\x1c\x16\xb5\xbcQnT\xb5\x0f\xa6\x16R\xdfV\xbf\x1dZ#\xf5\xc1\"\xb6:\x03\xe3\x8c-\x8e\xae\x821~[\x87\xf5\xc1d\xbfr\x1fL\xdf\x19\x10U\xccS0\x91\x804\x1f\x8c\f#}a\xe6\x83E肱\n\x96EN&a\x89\xf6bC˳\xf0\x10\xab\xc7\x1er\xb1\x1d\x17\x835e\xb4\x03t'\n\xe6\xc0\xd7\x15?\x97N\xbe\xd2s\xc6ز\x87`\xcf\xe3<\x9c\xf9\ny\xaf\x9c\x16\x1d\xe5ic{l-\x18֬|\x0e\x15\xae\\\x8dB\xfcf\x91\x88\xcc\"\xec\xd1A\xaa\x89\x04R\x95fj\xd0H\x06\x94\xfd\x99y\x838\xbd\x95\xe8.\x99M\xd1l\xeb\b\xf1\xa0\x16\x87E-o\x94\x1bUQ0\xa6\x90\xfa\xb6\xfa\xed\xc0VHW\xc1\"\xb6\xba\xbe3\xb68\xba\n\xc6\xf8ՔA\xe3W*\x83\x813\x84zw\x8f\xfc\xc7\v@\x04\xccU0!\xd0\xee\t\\CtN\xfeŰs\xf2K\xd4~W\x89N\x17\x8c\x9d\x93_\xce\x15\xd6\xee^\xc69\xde\xea\xb8ⷹ:\xd0Y\x97\xcd\u007f\x05]H\xcb*/K\xe7l\xef^\x10gq\xd7\xf8\xfd\xbd8\xe3N\xee\xf9\xc6Cd\x02\xa8\xd0A\xef'\xf5\x868\x1e\xfc\xc0ﷻ\xfc~\x1e]H\xaf\xe9o\xb4\x9d\xeb\u007f>\xef\x12\xa27\xff\xea\x17\xa4\xf7 }g\x1a[e/[\x1cr:\xd7\x1c\xcaK\xbbD\x14,\xad\xac\x19\x1b\xb4j\x0e\xac\xd6B\xb3{+\xb7\x1b\xbd\xc5ыF\xf1K\x8a\xb3\xa6\xa3u%)\x8e\x83\xcb,;\x8e\xfd\x92&*\xe2v6\xef\xe4\xc4{\x91\xf6E\xb5\xcd[\xb9z2'\xdf\xf5\xc1`\u007fAf\xebu\x8d\a\xb58*ly\xa3ڨ\xe2\xbd\xc8\x0e\xfa}\xa5\x14\xd2\xc0֠\x1d\x94\n\xb1\aV?\xacȭ\xae\xefL-\x0e\x93M\xe3\x81i3&\x9b\xea\x97-\x83\x9e3b\\\xc0\xfd\b\x01Q\xc2\\\x05\v\x900X\x15M\x1d\xa8\xf0\x86\xf9]\xe4\xf5\xb4\"\x9d\xa4\n\xfb\xbbH\xa1f\x81\xddQX\xbf\xc0\x96\xf7\"\xfe\xdbv\x81L\xd0\xc1\xfd\x9b\x9e\x82\xf4\xb9%\xef\xdap\xd2%\xc52\xe87\xfe\xf1<G\xfa\xcaf2\t\x94R\x10\xe2\xf8\xacd[/88\xaeq\x06\x97\xd6Hc \xf6\x12\u05ec\xcc\"r:\xea9\xd3\xda*\x87\xd0\x14\a\rlM\xb7\xe7\x91˲qey\x96-3O+`L-4\xbb\x9b\xd3\xcea\xdd\x10;0\xb2_<\xd4*/\x9c!\x16gy}٢4\x878SM\xa8Y\x92\xb6\xa4V\xec\xd7\xf6\x14f\xcdX~\x88\xfe.\x92\xe3\xce\xe2\x82qe\x1a\x0fjqT\xd8\xf2F\xb3Q\afѽ6m!\r>\x00\x83vP*\xc4\x1eX\xf9\xb0\x88A\x84V\xd7w\xa6\x16\x87ɦ\xf5\xc0\xb4\x99\x9aM\xf5˖A\xcf\x191\xaew\x84\xfb\xf5.pG\x98\xab`#\xe6U\xeec\x9d\xa4yH\xe3\x04\x00\x00\xcc%F\x14l\xa2=V\a\x14\f\x00&\x041\xa2`\x13\rP0\x00\x98\x10\x80\x82\xdd\x05b`V\xe6\xcdo=\xc4\xf2\xad7\xc3\xe4\x04\x00 \xaa\x80\x82\xdd\x0540\xdb+\xa6\xff\xa8\xd5/\xaaa\u007f\f\x9b\x1b\x00\x80\xa8\x01\n6J\x86\v\x18\x96\xb0H\x99\x00\x00\x88\x0e\xa0`\xa3\xe3M\x1d\x01{\xe8!\x18H\x02\xc0\xf8\x00\n6:\xf4\xba`\xd0\t\x03\x80\xf1\x02\x14lt\xe8\n\xd8C\x0fE\xca\x06\x00@T\x00\x05\x1b\x1d\xa0`\x00`&\xa0`\xa3\x03\x14\f\x00\xcc\x04\x14lt\x80\x82\x01\x80\x99\x80\x82\x8d\x0eP0\x000\x13P\xb0\xd1qo)\x98wf0\x92ɸsm\xa67\x92\tp\x1fc\xb2\x82\xb5\xbb\x95\xd3\xd3\x17~\xb1\xc8\x11\xe3\xb1Z\xadŨ\x18o+\xc2X]\x8c\xb7N\xc3/\xb9\xd8,\xb1+\x8c]$\"+X\xbe5\xae\xda0{\b\xbb\xacqU\x91ldƠ\x9e۰\xc3\xc848\x9dG\xc2\x1a\x1ct:\x9d{\xd1^\xbc=\x18\xc6\xea\xd3l\xe7*\xfc\xf2\n6\x9b\xffi\x18;\xb4-n[\xb8\xb7\x81\xfb\x1bs\x15\x8c\xaf8&/O\x14t\x9f\fk:bx\x8fu[\x10\x05\xb7Y=\xc3W\x1dbh\xc9M\xc0\xdbn\x9fo\x97\xb5%\x9c]\x04\"+X\xc0\x17?\x12]\xa0\xf0G\xa7\xeb\xdb\xfaN\x0f\xdb\x15\xfdz\xee\x8a\xf3D\xb0\xa0\xdch[\xbfW\xf7\x8d\xb6\xf3\x92\xc1A\xe7\xde\xcf\xd1\xe7\xef8\x0f\xdeе\x13\xb9\xfd\xf3W\xb2\xf1\xcb\xef\xdb\xda\x1a\x9c?\x0fc\x87{\x86\x8f\x96\x86}\x1f\xb8\x9f1W\xc1\xbcMݒ\x82\x05\xaa\xa3\xa5`\xa8\xddz\x00o}\xd6\xf6\xf0f\xc5\t\xe2kK\xc4+;\x1c\x91\x15\f\xa1\x84\x11+\x18B\xf3\xf4m\xa7/\x1e\xbe/\xda\xf5\xbc\x18\xbf!\xbc\x81\xc2f}\x05[\xbfEJ|\xe4<\x85\xb7mΏt\xcd\x14\xf6f\x8b\xaf\xe7#(\x18ڔ\x10\xe6\xe9\xbd\xc0\xfd\x8d\xa9\n\xd6\xee\xe1\xc5\xe7\xe4#\x9f\xdbW\x11\xc3\n\xf6\xbf\u007f\xf7_\xff\xf5\xeb\u007f\xfc_x\xfb\xbb\xa7\xc6D\xc1R\xc7A\xc1r\x93\xc3v\xe6\x18\f\x14l\xed\x16)\x11m\x05\xe3\x93s\xc3\x1b\x00\xf7/f*\x18_\xd1%\xad\xf4\x81\xfayy\xd5[]\xaa\x95\x98O5\xe2\x17'ǧ\xcc;\x83\xf7\x9ey\xd4j\xddԵtj\xe2\x9cA֘\xb9\xb2U\xdb|k\xbc{ݴ\xc4\xd9\xf4\xcb<\xb04y\xca\xc2\xdcaWv\xe5\xcc\xc4i\xebx#\xbfݓ\xad\"\x93\xd9\x0e\x81\xa8`o\x92\xb6x\xea_\xc9\xf6_e\x05\x93\xbda\x05\xcb\xcfM\x9e2\x8fF\xa1\x8e\xceN\x89O\x9a\x93B\xb3\xeeJML\xdd%z\xe9Z\x98\x14\x9f<\x87<e\x1b+X>>\xc6cAƃW:p*\xd2\x10\xe5z\x0eL\x96\xbb`m\x9bWd?\xb3y\xc5m\x9c\xbcݰ~\xfeچ\xdbt\xf7\xa7[\x9e\xc9\xce\xd9\xfc{D\x15\xecu\xa7ә\x8d\a\x89\xb7\x0f\xae\x9f\xbf\xea\x8d[\b\x9dp\x8a\xacG\x1a\x05\xbb\xb1%'{\xc5f\"e\xaf8\xb3\x0f\xbe\xb1j>u\x80~\xbf=\xe7\xe9-\xaf\x84*\x98\xe2\xec\xa3l\xa7sϧ\xdbWdo\xfe\x82\xbe\xb1)\xb1\x1f\x01\x80\x1ef*\x18Y\x1e2\xa0,\xd3\x1dN\xc1\xf8\xa3\x937\x05QpӔ\xa3<\xbe\x9es}\xd5\xf3\xe2\xf0\xe5\xd8_]\x95\xf2\xe4\xe4\x94uK\xad\x9aAF\xbb\xd5\xdb\xdf\u07ff\x9f\\٪mgգ֤\xe2\xd2\xc9\v\xb1A\xd7\xe4i\x1e\xeflk蕝\x1b\x97\xef-MJ\x15\f\xfc\x0exJE<\xecR\x85\xa2\x82=\xfc\xe6\xd0\u007f\xfc\xe3C\x0f\u007f\xeb\xd7C\xff\xf6\xb0\xa4`\x8a7\xac`\xd6Ԫ\xaa\xd4D\\\x9e\x93֥\xd5M\xee$+Q\x8c܄M\xdeM\tK\x89\x13_b궦b+\x89\xf6`\x05\v,\x8d+ma\xcb\xc3\x1f\xf3=\x99\xe1\xf3\x85\xde\xea\x88r=O[}\xe2\xfb\xbf\xfc\xfe\xf6#\xa7\x0e>\xe3$\xe2\xb1#{ϩ=\xd9\xdb\xc9\xee\xb6\xf9\xeb\xdf9\xb5\xd7ـ\xa8\x82\xfd~\xbb\xb3\x81\x84\xbdv8_?Ր\xb3\xf66\xba\xd1ֶjc[[\xdbo\x10U\xb0[\xb7n\x9d\"\nv¹\xa3\xed\xc8f'6\xfd\xe8H\xb63g\xef;\xf3\xb7`\x83O\xe7\xaf:xb\xb33T\xc1\x14g\xb7\x8e\x1cY\xb1j~\xce\x1bۿ\u007f\x95\xbeq,R\xff\x11\xb8o1Q\xc1:I\bzd\n\x86/;2\x8cZL\x06\x13|5\xe9ؤ.\xa4\xbbS\xad\xb3\xf9\xd0u\xeaۥ.K\xbb\xd66a\n\xbeN\x97&\xe1T\xc6T\xbcWH\r\xb9\xb2\xbdV\x0f\xfd\xab\xca\xc8o\xf0\xa2\x88f\u0081\x14\xf7zj\xe8\xd7\x0f}\xeb[\x0f\xfdߡ\u007f\x94\xe2`\xac\xb7\x84i\xb8\a\xd1?u&\xeev%\x11\xed\xda5\x05\xeb\xda\x01ڃ:`ݏ\xdfJ\x99\x83Eq\xa0\x9a,ڄ\x15l[\x82wxytG\x91Q\xad\xa7\xd7zQ4l\xc8!\xda\xd5\xf04\xeey\x9d\xa2\x9d)\xba\xbd\xb5b3\xee\x1c\xdd>B\x82\xf3X\xc1\x1a\xb2O\x10\xdb\x13\xf4v\xe3y\xf1\xe6$3\x8a\x14\xc1\nv\x8bd\xb8-\xbe\x93\xfd4\xee\u007fm\xcf\xc1\xa9\x8d\xab\x88\xaf\xb5!\n\xa6u\xe6\xdcx\x03ݖn\x05t[G|;\x17\xb8\xcf0O\xc1\xf8\x8aNA\x10\xba+\x05i\x91\xc8\xf0\n\xe6K\xe4\x11\x9fH{\t\xc1]s\xa6N\x96\x86T\xa9:1\xdevkiKKK)\x8d\x0f1\xb6\tD\xfeHP\x88\xb7\xba\xc9ߛB\xae\xec\xc5S\a\x061)\xb9\x06~/Ze\x86\x8f\"\x1f\xfa\xfb\xa1??\xf5硧\x86\xfe\xfc\xb0\xa4`\xac\xb7\x04:<s[\xaf\xa1\xee\xe4\xa9\xf9\xee3\x02\xe9\xc4\xe5N\xa3\xf9\xa7a\x83\xfd\xd63\x8a\xbfyś\xac\xe2\x04\x13myt\x15,\xaa\xf5\xac\x93\x15\xecjΊ\xd7\x0f\xfe\xea6\x19:\xeeXK\xf7\xacz\x85\xc8دdK\xac`?qR\x01C\xdbW\xdc\xfe\x02\x93\xb3\x83\xfc\xc1(\xd8;\xe7ϟo\xa0q\xb0\x1b\r\x9bW\xccwR?\xd9Ċ\x04\xbfn\x88\xd3,\xf6\x84(\x98\xd6Y\xf6U\xa4\xd0m\x1d\xf1$\x13\xe0>\xc3<\x05\xbb\xe8\x96\x11WY\v\xaf`\x83Iu\xa8.\x89\x88]Krʆ:_\x86\xa4`Ӈ\x9b2\xf1!֖\xc6\xd3ɕ}R\x1c.\x85F\xb8S%}Zh\xe4\xd7\xe7\x15\xf1\xb1;%\x05{过\xfech\xe8\xd7C\xbf\x93\xfe\xd4x\x13#\xf9>\xebi\xb2,\xf9\xe2i\xd6$2\xbfi\xe6<\x9a\u007f\x0e>P\xa9U\x8d\xf2\xccK\x9e<M\xee^\xb2\xe5\t\x1fɏF=\xd58ٍ\x83[V9\x9fy\aK\xd8\xc6\xcdt\xc7\xe6\xf5d\x16\xd8-\xc5ts\xce\xfcU[hpl\xad\xd4ۢvz\x91\xfc\xf39+\xf6\x9ch\xdb(*\x18\xb9\x01@\x14켳\r\xa1\xe1\x91|\xad\xb3\xf5H\xa5\xc5z\f\x01\x80\x1e\xe6)\x98\x10$\xb4{\x82A\xb1\x13\x16^\xc1P\xfeB\xb40\x9f$\xa6\xcd$\x83\x9e\x85\x92\x82-\x1cn\xc9\\٬\xadre_\xb3\xd2\xf8yh\x84{\xe9\xd4Ӕ\xa0\x91_]d\x05\xfb\x0f\xb1=\xfe]V0\xd6[\xc2:bYa\xe5\xd1I\xd2\x1b\xe3\xab\x12q\x01r\xa7\xd2\xfcSqW\xa8ɪ\xce\xf6\x9a\x97\xd4~q2\x9d\xfe\xa4-\x0fQ\xb0\x90\x15\x81\xa3\\O^\xbeez~\x0f\x16\xa7\x1bG\xb2\x1bp\x1fL\f\xe7\xaf\xd8A\xfa`\xe7\x15\xd3\xcd9\x1f}:\x9f\x04\xc4p\xb7\xe9<\x85\x8e\xf6\xa8\x82\x1d\xbc\xaaQ\xb0U\xeb\x89\xf0m\xd1*\xd8\x1fi4\r\xed\x18\xd6\a\vu&S\x1c?\xd2ۤ\xc0\xfd\x86y\n&2\xd28\x18jI\b$\xd0K0\x85\\tB\xaa\xa4`\xe1\xfb&\xac\xadre\xa3\xe9)\xd7\x10\xeaz,\xe4\xca> \xc6Z6\xd1\t\xe0z~u\x91\x15\xec͡\xa1?\xffyh\xe8\xdfd\x05c\xbd%\xa4\x900״\f|xZ4\x94\x91O\xc2Nd`TE\x86\x8c|r\x06\x19W\xe6\x13\xa1#\xb3)\xf6Ǔ\x12iʓ\x813\a\xa5`P\xf76q\xb8\x17\xedz.\x9e*~\x95\xec\xa5\xfa\x836ҡ#\x89I\x1d!;n\xe4l$j\xf6\xfa\x1bH\x9cMq*\x9b(\x9ah\x80\xf6\xd0\xe9\x15\x1b7\"\xf49\xd9\xc1(؊-\x88D\xbc\xb4\n\x86֯\xc0*\xf5\x9b\xec\x10\x05\xd38c\x15L\x986\a\x01\x80.\xe6*\x98\x10h\xf7\x04H\x00\xbb?\x10\xf0\xf8\x02\xe1~\x94'$\xcfN\xa6WX\xb1u\xf1\xaem\xa9x(\xd62\xd8B\xef\xd1]\xd4\x1a\xb2s\xd5Uۀ/>\xb7\x05\x9d\u038d\xf7\x05P{bJ\xf1\xa6)q\x8fz:Ź\xea\xa5>\x1f\xe9\xddl\xb0.\xae\xf6\xe6Z+\x91\xbe_}d\x05\xfbס\xa1\xff\xf3\xefCCO\xc9\n\xa6z#\xf7\"\xe7\xb44͜r\x91\x94=\xb1\xd8[\x97K\x87wK\xe36x7ĉ\xf7\"\x1f\x9b\xe6ޟo\xad s\xf2s[\x06\xf89ɾ\xa0\xc6\x03V\xa4Һىb\x1fl\x9e\x95^\xcfQ\xafgW\x9c8\xf5}\xafs\xfe\xde\x13'vБ\xdev\xe7\x9e\x13{\x9c\xe2\xbd\xc8\xecU\r\xa7^w\x1e$s\xf2_\xf9\xf9\xed\x1b\x9bs\xda>\xc7r\xf3\xfd\xedG\xb0-\x95\x9e\xbd\xd9\r'6ο\xaa\x99\x93\xbf\u05f9\xa5a\xefZ<&\xfd\xf9նl\x9c헯d\xb7]E\x1f\xcd\xcfٻ\xe7ig\xf6\xc1\x8f\xd0U2'\xbf\xa1\xad\x8dD\xbd\x14g_\xfc\x82\xdeؔ\u007flT\xcatR\x01@\x83\xb9\n\x16 a0\xd2\x179)F\xc4\u008d\x15J\x13\xc4\vL(}2!i\xb1gj|ƙ8\x1a\xd0\t\xf9~V\u007f/\xe8fl\xc9$\xab\xf8\xf6D\xbc\xc5\xfd\x9f\xaeyS\xa6\xae\xf3<\x8a\x93\xb9RP\x88vE\x0ed$M\xc9؏\x90\xbe_}d\x05\xfb\xfb\xff\xfa吏\xfa\xef\xdf=\xac(\x98\xe2\r\x8f\xf1\x8a\x17ON^J\xa2}\x95\x19\xc5)\xf1\xc9\x194>%\xd0\xf9`b\xb7\xa7kq\xca\xe4\xe9u\xe4w\x91Vk\xdc\xc9*\xbcݤ\xf1\x80\x06\xf2\xa7$fHq*O\x12\x8d\xd0G\xbf\x9e\x9b\x1e\xa3Ѧ\x83\x1b\xf7\xae\xc8\xce\xd9HCU\xb7\x1b\xd6*\xf3\xc1~\xb3%g\xfe\xfa\x13\xf4w\x91N\xe7/\x8f\xe0\xcdO\xf0\xdeS\x1b\x9fyz#\xed\xb4\xa1[\xaf?\x9d\xbd\xf1\xbc\xf6w\x91\xb7\x1bVe\xe7l?\xb8*{#\xf9\x01d\xf6\xaf\xe6\xe3-\xee\xdc}\xba\xf9\xe9\x15{\x0ef\xe3\xe4\x0e)\xf8\xb5\x051\xce>b\x02b\b\x1dM\\\x87\x00@\x1fs\x15,\xf6yH\x9fH\xd9&&\xeb\xe2'⤅\xaa\xf8\\͌e\x00`\x00\x05\x1b\x1d\xf7\x94\x82\xa1Ҕ\t\xf8t\x9ddx4\x05`\f(\xd8\xe8\x10\x05\x8bi\x91\x98V0\x00\x885@\xc1F\a(\x18\x00\x98\t(\xd8\xe8\x18>\x80\xfc\xeaà`\x000^\x80\x82\x8d\x8ea+\xde>\xfc7\xff\xe3aX\xf1\x16\x00\xc6\tP\xb0\xd1\xf1o\x0f\x85\xf0\xb0\x05K؛\x91\xb2\x01\x00\x10\x15@\xc1FIh'\xec\xab\x16\xcb\xdf\xfcO\xf8\r\f\x00\x8c\x0f\xa0`\xa3\xe4\x8f!\x12\xf6UK\xee_O\xe9\x04\t\x03\x80q\x01\x14lԼ\xa9Ѱ\xafZ\xeaNZ\x92;ᙢ\x000\x1e\x80\x82E\x19\xdeR=t\xcc2\xb5\v$\f\x00\xc6\x01P\xb0(C\x14l\xe8\x80e\xdaE\xf6Y\xd4\x00\x00\x8c\r\xa0`Q\x86\xb7T\xfdeh\xa8\xce2\x1d$\f\x00\xc6\x1eP\xb0(\xc3[*\xb1\x82\rUZ2\xbaA\xc2\x00`\xac1Y\xc1\xda\xdd\xe2C\xe1y_u\x85\xf7̽\xf0\b\x02\xde\xe2\xf9\x92H\xd8.\xcbl\x900\x00\x18k\xccU0\xbe\xe2\x18}\x80\x1f\xef\xf1\xb6w\x9f\xf4\xd4\xdd\x03\x12&+\xd8\xd06\xcbB\x900\x00\x18c\xccU0oS7U\xb0\xa6j\xf2\xa4\xbfkQ[\xb6\xdbDxKŗ\xa2\x84m\xb2,\x05\t\x03\x80\xb1\xc5T\x05k\xf7\xf0\xe2s\xf2\xeb\xc4'\xeb\xf9\xbca\xcdc\x02\xde\xe2\xfe\x93\xa8`C\xeb,\xf9\x01\x900\x00\x18K\xccT0\xbe\xa2KZ\xe9# >\x01\xfe\xd8D|D\xe8\x1d\xc2[v\xfd\xe9\xcb/\xc5\xd6ɵ\xac\x03\t\x03\x80\xb1\xc4L\x05\xf36\xb1k\x15!$Ti\x96b\x8cM\xb0\x82\xfd?\xb9\x136\xb4в!x\x0f\xc4\xf6\x00`\xc2b\xa2\x82uzx\xad\x82\x1d\xf3\\3\xb6\x8e\x15xK\xa9@:a\u007f9v\xf4\xe8Q\xdfc\x96b\x900\x00\x18;\xccS0\xbe\xa2S\x10\x84\xeeJA\x90v\xb4\xb8\xb5+\xba\xc6&X\xc1\x06i',\xc5\"R\xca\v\b\x00\x80\xb1\xc1<\x05\xbb\xe8\x96!됡A\x9f\xbb3R\x96X\x00+X?\xfaSŗCM\x969\x9b\xb6m+u7\x05A\xc1\x00`\xac0O\xc1\x84 \xa1\xdd\x13\xa4W8\xef\xad\fD\xca\x11\x13\xf0\x96m\xfc`\xb1e\xdb_\x86\xe2\xa7\xec\xef\xbcx\xb1;8`\xb9\xe7\x88\xd4\b\x000^\x98\xa7`\"R\x1c\xecZU\x1d\x8fE\xed\x1ex\xa0\x03Q\xb0u\x96I\u007f\xfb\xe5P\x95eW`\x00\x0f\x94\x91\xe5\xe6=\x06(\x180a0W\xc1\x84@\xbb'p\r\xa1\ue2aa\xee@ po̦ؖk\x99\xb6\xc1\xb2\xeb/\u007f\xf9\xdb'\xdb\xe9\\\nP0\x00\x18+\xccU\xb0\x00\t\x83U!\xb4_\x8a\x88\xdd\x133Z\x13-\xa9\x9e\x96i\xd6/\x87\xb6Y\xaa\xe9\b\x19\x14\f\x00\xc6\ns\x15\xec\x1e\x84\xb7X\xa6W\xb6_k\xb2x\xfe\xf2\xa5e\xe1E2\x95\x02\x14\f\x00\xc6\nP\xb0(\xc3[\xe6Uw\xf2\x02?\xcd\xfa'ޒ\xd1I\x86\x91a\x14L\xef\xad\b\x82\x17E=\x8c\xecJ\xdf\x02\x14\f\x980\x80\x82E\x19~\xd3Q,`h\xe0\xc0\x03\x93,_)\xee\xba\xd7\x14\x8c\xee\x00\x05\x03&\f\xa0`Qf\xe0Z\xb0_\x9c\x1e2}v\xe9\xb1k\x11\xe2`\xa0`\x000*@\xc1\xa2\x8d\xf4\x1b\x03\x81\xbf\xd8\xdeu\x8d\xfe\xa2\xc8\"+\x01I\xbc\xf6\xb8e\xd2w?\xc1\u007f\xbc\xfc\xc8_?\xf2\x02\xd9\xff\xe3\xaf[\x1e\xf9\xe1\x1fH\xe2q˃/S\xab\xf7\xbf3\xe9\x81\xef`#˳\x0fZ\x18\x03%\xcbMƑb\xfb\xc2#\x96\xaf\xff\xf4\xe5G,O\xfc\x8cu*\xf1\xb3Ix\xf3]\xfc\u007f҇\xea\x9b8\xcb_?\x82\x8fH|X\x1e\u007f\r'Ȏ\x17nj\xcar\xf3\xa7_yA\xc9Bg\x83\x81\x82\x01\x13\aP\xb0\xb1B\x18\x18\x18\x10\xc5L\xa3`_\xdbw\xf9\xc3\xefb)y\xfb\xc1}\x97\xf7\x11}\xfa\xe9\xdf\xfd\xf4\xf2\xfb\xdf\xfc!\xde\xf3\x95\xb7/\xbf\xffO\xd4\xea\xef\xf6]\xfe\xed?\u007f\x0f'\x9f\xf8\x905\x90\xb3P_\xb2#\xd5\xf6\xfd\xcb\xff\xf2\x00\xd9|\x93ɣ\xf4\xa2\xbe\xf6\xde͟Y>\xbc\xf9\xdeט7-\xd4\xe1\xdb7o>\xfe\xec'\u007f\xf8鷱N=\xb8\xef\xb7\xfb\x1e\xfc\xb1\xa6,x\x1f\x9b\x85\x1e;B\xd5\x01`\xdc\x00\x05\x1b{4\n\xf6\x1e~\xfdO\xdc!z\xe2Ǥ\xa7\x83\xf7\xfc\x03\xd9\xf3\xe1#7o~㵛\xb2\x15\xe1\xb7\x0fJ֊\x81\x92\x85ZɎ\x14\xdb\xf7o\xde\xfc\x84n\x1e`\xf2(\n\xf6\xcf\xcf\xde|\xd6\xf2\xf2\xcd\x1f\xfe3\xf3\xa6\x85:|\xe2\xe6\xcd\a>\x14\x8d\xbeAw|\x83-\xcb\v_\u007f\x9f-\x03(\x180\xb1\x00\x05\x1b{4\n&'&\x91\x91\xe4'$!\xfeP\a\xef\xfcDV\x8d\x9b\x1f~{\x92\xb8\x8b\x8c\x03\x15\x03%\x8bd\x15b\xab\xece\x9d*\xbc\xfd͛O|\xef\xdb7\xbf\xf1v\xe8\x11?\xc1*\xf8/\x93\xbe\xf72\x11\xb1I\xf2\x0e\xa5,?\xfc\xc6oo\xb2e\x00\x05\x03&\x16\xa0`cOx\x05\xb3H\xfd\x1fq\x8f\xf8\xe6\x13\xff\xf2\xe1\x1f\xfe\xa0\xe8\x85\xc6`\x98\x82im\xe5\xc3\xc8y\x14.O\xfa\xf0\x81\x0f'}h\xb9̼\xa9(\xd8\xcd\xf7\x9e\xfdΤg\x19\x05Sʲo\xd2\xdb\xf4U\xc9B7\x91j\f\x00\xe3\x05(\xd8\xd8C\xf4\xea?\x89L\xb0\n\xa6\f\t\xbf\xf1\x82$\x0eO\xbc\xa6\x88\xc4\x03Xg\xf6\xc9֪\x81f\x14\xa9k+o\x94<*\xff\xf0\xbd\u007f\xa0\xff\x997\x95Q$\xe1g\x0f0\xa3H\xb5,\xef}\xe55M\x16\xba\x89Tc\x00\x18/@\xc1\xc6\x1e|\xd5\u007f\xf7\xbb\x1f^\xde\xf75V\xc1\x94\xb0\xfc\xbeI/\u007fry\xdf7q\xe2A%z\xfe\xf8\xb3\x97\xdfS\xac\x15\x03m$_\xdejl卒G\xb2\xc3<ky\x96\xfeg\xdeT\"\xf9\xdf|\xfb\xf2\xe5\x17\x1e\xa7Q\xfb\xcb4\x92ϔ\xe5\xfd\a_`\xb2<\xf26(\x180\x91\x00\x05\x1b{\xb0\f|\xf2O\x93,_\u007f\x8dU\xb0\x9b/?(M\x8d\xd8\xf7\xc4\x03\x96'\xf6\xe1\xc4k_\x97g0\xbc\xf7\xb8\xe5\xc1\x17\x14k\xc5@\xc9\xc2*\x98\xc6V\xd9(y\x14\x05{\xcf\xf2\xfe\xcd\xf7i\xfc_y\x93L\xc0\xa0\xb3)\xde~\xc22\xe9\xdbd\x12\x06\xd9A\xbb[jYn\xfe\xec\x91g\xd5,\xaf=\x02\xb3)\x80\x89\x04(\xd8أ\x88Ƚ\x02(\x180a\x88-\x05s\xb9\xf4\x92\x13\x1dP0\x00\x18+LV\xb0v\xe9\x81:\x81\x03U\x15\xd5\xc7\xf8\b\xd6\x1fs;u\x92\x84fN\xc2\x11f]\x8d\xe3\x8e\xc3\xc6oF\a\xf6\x10\xbd6n\x11M\x80\x82iy\x91\xe3\x1a\x99?\xc7\xe1c\x91\b9\xf0]0z\x0f\x91q\xe1\xd38\xad'\xbc\xcd\xf8\xb5ل\xc7\\\x05\xe3+\x8e\xd1g\xb4\x06\xdd\xde\xce\xeeκ\xaa\b\x12Vd\xbf\xa2\x93$\xf4\u007f`s\xf91;\xb9\xebó\xc94\xa7\x8d\xf9٧9D\x87\xcbN_A\xc1\xb4\\\xf1\xdbʙ?\xc7\xe1c\x91\b9\xf0\x1d\xd0zV|\xbd{\x0f\f\xb23\x03.\xf9\xfd\xb5\xdc\aaMƱ\xcd&<\xe6*\x98\xb7\xa9\x9b*X\x17]\xa6\x88\x8f\xb0\xd6G\x0fW\xa2\x93\x94\xb0\xd33\xab\x91\xfb\f\x193\x0eKnh\x0eQ\x0e\n\xa6\x8f]#\x03\xe3\xf0\xb1\xc8\xd8\xefR\u007f~P(\xa7\xee\xd6\x03\x83\xeä\x8eH\n6\x9em6\xc11U\xc1\xda=\xbc\xf4\x9c|\xda\xf9\n\xba\xc3/\xf6\xe1R\xfb].m\x17\f\xc9gVO\xa8\xb0\x99\x8a\xac`\xf7\x1c\x11\xea\x1d\x91(\xc8\xc0\xddq\xb7\a^\x16M\x05[\x16\x05\x05\x03d\xccT0\xbe\xa2\x8bY\U00076ffb\xda\x1b\xf6\x9b\xa5\u05f6U')\xa3\x9cY/q\xb6\xfa\x92\x05i\xab/\x91\x1e\x19Ǖ\xa3r\x8e\x04/\xfa\xd28)\x86q\xce\xc6qe=Es\xedk\xc8\xe1j\x97\xa5-\xa9\xd5fc\xc0{k\\Y\xe9\x05=F\xd9\xf4\x0f\x81\x87\x1bE\x99\xe9\x85\xd2(\xb2qeڂ\x12\xba\x88\x89\u007fu\x96\xcd\xf1\xa3,\xcd!\x10_\x98i\xcb*8\x87\x8c\xca\xc0x\x18u\xdd\x04\x87\xedլ\xcc֭\xb3\xf2x\x03\xbf\x87\xa5\x80\xe22M\x01\xca\xe8\x01\xc81\xcbpS\x97\xa8\x85\xd4\xf1\xc0\xa2\xd6M\x83}\xab+\x936*Stփ\x9a\x8d\xa9\x10\x89u\xbe*\xd5\xd8\x00\xa5}_\"FJ \xb2\xa7Ёw\x93\xef<\xb6\xe8\nl!\xf5>!M\x93\xe8U^\xc3gE\x8e\xac\x92\x12\a\x1d\xe6\xc9\x1f\x80\x913ր\xb5\r\xaf`\xecy\xa6{F\xddW\x98\xa9`\xde&u\xcd\xee\xa0\xdb\xed\xf6\x84\x0f\x83\xb9l\x97t\x922\xf6\xb2\x81\x81B\xd2\x03\xfb\xb8\xd1\xc69\xcakf\xe0/\xba~\xff\xac\xb2\xeb\xe8z\xd9,?>\xcd\xce\xfa\xfd\xa2\xca\r46f-\x98\x91UR\xc4\xf5\x92\xce\\Ys\x99\xbdH\x93\x8d\x81\xec\xcd\xda]\x9e\x95v\xc1 \x9b\xfe!PϬ\x05\xf5\x87WsT\xc1\\\xdc\xd6\xe6\x1a\xc72,)g\xb9\xa2\xc6\xe3\xf5\x0eN+\xd4͜\xab\xb5\xb1\x80\xeb0*\x03\xe3a\xf4uk\x9dŕ\xe4q\x8eݎ\x1a\x03\xbf\xfc\a\xfe\x05y~\xbf_\x1bJ\xbe\xfe\xfcJ?\x8f\xdf[\xf9\xfcu\xdc\xd4ܢ\xc6ÎB\xa3\x92\xb1\xa8u\xd3`\xe7\x9656.\xc1\x8d\xca\x14\x9d\xf5\xa0fc*\xd4\xffA\u058bW\xe4\x1a뢶\xaf\x18\xaf\x92\x02\x91\xadi\xcb\xde:^\xce\xd5 M\xd1U\x98B\xea~B\x9a&ѫ<\xcb\xe0\xa2\xcc\xda2{Z\xfd\xea\x1a\xe6\x030r\xc6\x18hl#\xf4\xc1\xd4\xf3L\xff\x8c\xba\xaf0Q\xc1:\x89b)}\xb0`\xa0\xbd:l$\xbf\xd7\xf6\xa2NR\xc1N\xbe\xd8\n\xc4d:ַ\"\aI\xbaȩ\xf6\xbc<\xf1B\xe9\xa7-\xe3H\x1f\x04\xff;\xce\x1dGd۬\xcd\xc6\xfa\x9d\x8b\xcd\xfa\xb2\x96\x1bf\xd3=\xc4\xca\x05\xf8*\x13\x96\x90\v\xa8\x99{\x17\x91s\x12\u007fi\xd6:h\xcfh\x96\xf6|\xebo$W\xe4\x92]M\xa7\x00\x00\x00\x11\xe6IDAT\xe7hv\xbd20\x1eF_\xb7\xcc\"\xec\xef0\x9d\x8cb\xe0Ww\x94\xf3\xae؛YDm\x1d\x9f\xe1\xa3\x13[#\x0f\nl\xdd\x18\xec\x8b\x06\xb08-X.\xfd%\x15]\xf5\xa0ɦT\b\x95\x93\x8eK\x91\xf14\x1a\xb6}\xa9S:\x8c\x1f\xc8Z\x83\x8f6\xd8؇آ30G\xd3\xff\x844\xa3H\xddʫ4r\xb83W\xcb\x11qf?\x00\x16\xc5\x19c\xa0\xb5\x8d<\x8a\x94\xdą\xbc\xf7\x11\xe6)\x18_\xd1)\bBw\xa5\xa0\xb4\xfe@uS\x18\xfb\x97l\xbd:I\x05\xbb\xab\xa3c\x89\xa4`\xe4\x1c\x17cP\xad\xf6~ԟ\xe6\x97m\x94\xab\xdc.9pI\x17\xa6K\x9b\x8d\xc1Ngm\xd4r}F\xd9\xf4\x0e\xd1\xc7Փ\x972\xe2\xacp\xee \xae\xa7\x90\x85m/e\xce}\xa9\xfe\x9c\x10:\xe1\xe3\xb3\xda5sgqKhv\xbd20\x1eF_\xb7\xccF|}\xf0h\xe7\xf3\x86~u\x15\xec\x1c7\xd0\xffn\x9f`?\xa7\xb15\xf2\xa0\xc2ԍ\xc1\xfe*ي\x8d\xca(\x98\xea\x81ͦT\b]\xc2\xc200\xa3\x15\x19\xc1\xb6\xaf\xaa`͜:\x8a\x8dTH\x83O\x88U0\xddʫ\xecLG\xe4F\xd3!\xa4\xfd\x00X\x14g\x8c\x81\xd6v\xc4\nfT\xde\xfb\b\xf3\x14\xec\xa2[&\x80\xa4G\x01\x9eq\x1b\u007f\x97\\\xb1\xbbt\x92*\xe4#mnU\x92\xd2i*8\x0e\xa1C\x0e٫z\x95\xcbQ\x9e\x95\xa2\xe6\x15,\xd7fc\x10\xf3\xf8\xb9\xb3F\xd9\xf4\x0eq\x96\xa3\xc2B\x9d-\x91\x02\x1f\xe4+\xbe\xaf\xbep\x11\x1e\xc2!\r\x1d\x8e\xac\x9d\x87\xfcyK\x94\xec\xa1e`=\x8c\xban\x99\xc7Q\x87\rQ\x053\xf0\xab\xab`\x03\xb6s5\\Y\x0f7\xa0\xb15\xf2\xa0\xc0֍\x81mTF\xc1\x14\x0f\x9alJ\x85\x10ZS\x82\x8e\xa7\x87\xb9\\\x99\xf6U\x9d\xd5\xd0B\x8bD,\xa4\xee'4,\x92?\xac\xf2*5\xe4n\xf8q\xda\ac?\x00\x16\xc5\x19c\xa0\xb5\x1d\xb1\x82\x19\x95\xf7>\xc2<\x05\x13\x82\x84vO0(\b\x95>\xba\xebL\x85\xb1\x82m\xe5zt\x92*\xd2Gz\xee3\xedi\xba\xf59\xf4\x9c\x12\xf5W\xafr\xe5[p.}\x99\xebB\x06g7\xb2\xd3\xdc\xf5\x1co\x94M\xef\x10\x9fq\xb5Ԍ8+\x9a{\x96\x82\vv\x96\xf4\xe7\xfa\x1a\xed\xb5\x88e\xd1r2\x88)4V0\xc6\xc3\xe8\xebF\x14\xcc.*\x98\x91_\ua87e\x17iXԘ\xb7r\xd1!\xdaSPm\x8d<\xa8\xb9\x98\xba1\xd8\xe9-c\xb1Q\xf5\x14L\x93\x8d\x11\xd4Î\xc1p\xbf\xc5`ۗ:\xa3\x9d\xe0V\xb6\x0f\x16\xa1\x90\xfa\x9f\x10\xdb$\xfa\x95W\xe9\xe5\xd6\xf4\x9e[\xb0\x92\x9cȚ\xb3\x84Aq\xc6\x18hmG\xac`F彏0O\xc1D\xc48X\xd5\x01\xb2\r7\x8a\x8c\xd4\x05\x93?\xd2̝\xdaӴ\xc3~Ůđ\x87_\xe5\xcd4\x8a\xd1(Ɗ\xf4\x15́Oo~n\x9ea6\xddC,\xcf\xea\xc3c\t;qv\\\f\x94\x94\xe1\xef\xc9r\xee8I\xe6i\xa3xYī\xb0\xc4X\xc1\x18\x0f\xa3\xaf\x1b\xa3`F~\xf3pe\xaf\x84\xde\xf0{\xfe%\xdbq\xeeE\xea[\xb55\xf2\xa0\xc0֍\xc1\x9eE\"S\x8b\U000a4fc6)\x98&\x1b\xa3`\x83\x8e\xc3\xe9\xf2 \xb2\xb7|\xd8-N\xb6}\xd3\xf0\x89 ,'\xce\xfa3\xf3\x06\xf1\xcbV\"\xf6\x91\n\xa9\xff\t\xb1M\xa2_y\x95\xb3\x9c\x83\xe3\xf2\xe8\\\x1f\xcdY\xa2\xe7\x8c1\xd0\xda2\n\xa6SM\x82\xd4fF彏0W\xc1\x84@\xbb'p\x8d\xcchm\xea\xec\xee\f\x17\xc9/Q\xfb]%:]0yN\xbe\u007fV\xc9\x15\xbf\xcdՁκl~r\x1a\t\x99\xab3i\xc7n\xf0\x03\xbfߎmx$tлA\xbd4c\x11\xb7\xb3y'WDg[3\xd9T\xc8m\xb3\xfa\x05\xe9=\x06\xd9\xf4\x0f\x81.\xa4e\x95\x97\xa5s\xb6w\xf1hb'\xf7|\xe3!\x179C˹\xb4\xb2f\x9c\xd4Frʹ\xc2\xda\xdd\xcb8\xc7[\x1dFeP<\x8c\xben\x17\xd2k\xfa\x1bm\xe7\xfa\x9fϻd\xe8\xb7\xdc^s(/-\xe4n\xef\xee\xb4Y\xc2\x02\xfb\ue4062\xf0\xa0\xa0\xd6M\xe3\xccέ\xe9h]\x89\x1b\x95):\xebAͦ\xa9\x10>\xde\xdct\xb9\x9b^\xc0\xa5\xf5!-l\xfb\xaet\xec\u07bd\\\xfc\x00Z\xed\x8bj\x9b\xb7r\xf5#(\xa4\xfe'\xa46\x89~\xe5Y\xce\xd9[\x9b\xfdW\xc4B\xb2g\x89\x8e3\x8d\x81\x9a\xa4s\xf2k\xe4:\xebT\x939ό\xca{\x1fa\xae\x82\x05H\x18\xac\x8a$\x9a\xaa+\xeaZ\xd4xE(\xd7ӊt\x92*\xca\xef\"\xb9\x9a\x17\xf1\xc6v\x81L\x99\xa1_L5\xf6\x1ajqVz\xbf\x1e\x9d\x13\x13b\xe0A\xa8Y\x92\xb6\xa4V\xa0\xbfxc\xb3)\xd8K\\\xb32\x8b\xae \x83l\xfa\x87\xc0\xfd\xaf\x82\xf4\xb9%\xefڨ\xb3\xe3y\x8e\xf4\x95\xe4˵qey\x96-3/\xe4t\x13j\x16\xd8\x1d\x85\xf5\vlyFeP<\x8c\xben\xb8\x83\xd08\x83Kk\x14\xc37\xfa~\a\xb6\xa6\xdb\xf3B'@\x9c\x9dU\x86U\xac#\xd4֠d2j\xdd4\xce\x16\x95\x17Π\x8d\xca\x14\x9d\xf5\xa0f\xd3T\x88\x84ȕ\xfew}ڰI\x1al\xfb\xf6\xe4\xd9g\xac~U,NOa\u058c\xe5\x87FRH\xfdOHm\x12\xfdʳ|`#嵭<\x87BΒ\xe1\xce4\x06j\xd2%5\x89\xd8\xf5ԩ&s\x9e\x19\x95\xf7>\xc2\\\x05\x1b1\xafr\x1f\xeb$\xc7\x03et\x06L\x00\xfa\xed\xea\xc5z\x88\v\xed\x9cL\x00\xae\xa7\xbdx]\x10\xfa\xce\x16\xa6G\xabp\x13\xb2\x9a\x13\x88\x18Q0\xf3\x1e\xab\x03\n6\x91hT\xee\xbd\n\xef\xce\x1a\xdf\x13ad\x1c\x92F\xb9\x82#4\xfauwL\xd0jN bD\xc1\xcc\x03\x14l\xc2Pފ\xf2\xca\xe4?\xae8J\x8c\x83\x0e\xe6qV\xba\xf1y\x8e\xd3\r\xc0\xdf1\x13\xb4\x9a\x13\bP\xb0\xb0\x88\x91[`\"\xd0\xcf-{)s\xa2\x8f\xa8\x04W\x9a\xab\xb1\xb5\x11o#Y\x02\xd1\x01\x14,,4r\xdb\x1b\xc9\n\x18\x17\xca\xd2\xf2\"<\xf8o\"pxu\xa6-sMtƐ@d@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]bK\xc1\xcc\xfby$\x00\x00\x13\x11\x93\x15\xac\xdd\xed\xd5I\x1a\xf11\xb7S')3ҕ\xd8k\x8d\x97\xebR\xd6\xe7\x02\x00 &0W\xc1\xf8\x8ac\x95Ó\x86\x14\xa9\xeb\xdc\x16\r[\xf2v\xc4+\xb1\xf7\xf9\x97\x1b\xfeZ[Z\x9f\v\x00\x80\xd8\xc0\\\x05\xf36uW\x0eO\x1a\xd1Õ\xe8$U\x86=JΈ\x02\xe3\xe7M\f{\xca4\x00\x00\x13\x18S\x15\xac\xdd\xc3\xcb\xebE2IC\\j\xbf\xcb5\xbc\vv\a\x80\x82\x01\xc0=\x82\x99\n\xc6Wt\xc9+\xde2ICzm[u\x92\x12\xba\xab\xd77\xe2}\xe5\xca:\xf5\xea\xb2\xeeX\xc1\xb6\xe2\x9dv\xb2ʌ\xbar\xfc\x95\xa2\xcc\xf4B\x18E\x02@,a\xa6\x82y\x9b\x945\xbb\x99\xa4!.\xdb%\x9d\xa4\x8c\xde\xea\xf5\xfd\xfeYe\xd7\xe5u\xea\x99eݱ\x82])\xe2jȃ\xbfԕ\xe3{f-\xa8?\xbc\x9a\x03\x05\x03\x80\x18\xc2D\x05\xeb\xf4\xf0\xb2l1ICzm/\xea$Y\x94U\xbb\x94\xd5둋,\x97\xf0<\x99x\xc1.\xeb\x8e\x15\xac\xc6N\x9f\xe0Ĭ\x1c\xbfrA?Ys\v\x14\f\x00b\b\xf3\x14\x8c\xaf\xe8\x14\x04\xa1\xbbR\x10ؤ1/\xa9O\x1ad\x92,\x8a\x82\x11\xc5\x12\x03Z\xad\xf6~ԟF\x16\xd0f\x97u/(/\xe3ę\x17\xea\xca\xf1}t\x89!q\x8dT\x00\x00b\x04\xf3\x14\xec\xa2[&\xc0$\r\xcd#.y\xab\xb7r*\x12\x1c\x87\xd0!\xba:\x04\xbb\xac{\x81c\xc6\"q-+u\xe5\xf8\xb3\x1c\xd19\x88\xe4\x03@La\x9e\x82\tAB\xbb'\x18\x14\x98\xa4\xa1\xf9Vu\x9dۭ:K\xde\x12t\x14\fm}\x0e=G\xa3\xfe\xec\xb2\xee\x05\x8e\v\xbd\xb3\xe8R\x8b\xea\xca\xf1\x9fq\xb5\xd4\f\x14\f\x00b\b\xf3\x14L\x84\t~\x85\x8d\x83\x8d\xa0\v\xa6\xab`\x1d\xf6+v\xbaT\a\xbb\xac;\x99M\xd1l#\xbb\x99\x95\xe3\x97g\xf5!\xd4c\x97\x14\xacww\f<\x92\x1d\x00\xee{\xccU0!\xd0\xee\t\\\vM\xeaQ\xa2\xf6\xbbJ\xf4\xba`\xfa\xab\xd7c\xb7\x99\xab3C\x96\x80\xef\xf3/w}0\xd8_\x90\xd9z\x9d]9\xfeBZVyY\xba\xb8N=Y\xec\xfdG\xc3\x0f\x02\x00\xc0\x04\xc3\\\x05\v\x90\xd8WUhR\x87\xebiE:I\x06\xfd\xd5\xeb15\xf6\x1a\xd1BYֽ\x96\u061d%s\xc5\xc8\xe2\x83\xea\xca\xf1=\x05\xe9sK\u07b5\x89\xd9\xea\x1d\xf5:G\x01\x00`ba\xae\x82\x8d\x98W\xb9\x8fu\x92\x00\x00\xdc\xe7Ĉ\x82\xc1cu\x00\x00\xd0!F\x14\f\x00\x00@\aP0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\xf3\x18\xe8\xef\xef\x1fDh\x10\xbf\fD\xb2\x05\x00@\x0fP0\xd38\x16g\xb5Z\x13y>\x11\xbf\xc4\x1d\x8dd\r\x00\x80\x0e\xa0`c\x88wf\x10\xa1k3\r\xd6\"\xaf\xb6z[Z\xda\x11joi\xf1Z\xab\xf5m\x00\x00\b\x8b\xc9\n\xd6\ue997w\xbf\x87>c\xda\x13\x8d\xc1\xd4~\xabDR\x18oMI\x06\xb2\x12\x9ek\xf9I\x89sF\xbc\xb0\xee6k1}\x89ۦ\xfbv\xb5\xb5[Nv߁\x82\xdde\xd1Gʩ\xef;Ern\x871\xca9a\xfc&\x00\x8c#\xe6*\x18_q\x8c>\x98\x95w\x9f\t`\x82\x91\xecG\x02\u007f,>ׇ\xd9`\r\xe3Λ8r\xc9`\x98\x9d\xec\xceM\xe4#YI\xec\x8a\xf3\x88\t\uf8e5z\xefGR0\xdf\xe9\xe1\xfb\xd0]\x17}\xa4\xdcj\xcb~\xa5\r\xb3\xc7\xf9\xb9\xb1щ\xf9G\x8c\xdf\x04\x80q\xc4\\\x05\xf36uK\n\xa6\\\xccQ \x81v}*\xc3)\x18\x1aqG\x8a嚵\x14\t#\x15\xb0\x8b\xf1\x1b\xe4\xe4\xa6\x04\xbd\xeaER\xb0鋇\xef#\xdcU\xd1\xef\x80\xec\xbdd{\xd0y#\x8cM\x98\xfe\x19\x00\x8c'\xa6*X\xbb\x87\x0f\x8c\x99\x82u\xad\x8bdw\xc7tY\xef`\x00\x97\x9b\xach\x1d\x9f\x9c\xabc\x10I\xc1R\r\x14l\xac\x11\x15\xec7o\x80J\x011\x80\x99\n\xc6Wt\xa1\x91)X\xb5\xd5j-F\xc5x[\x8d\xf8\xc5\xc9\xf1)\xf3\xce\xe0\xbdg\x1e\xb5Z7u-\x9d\x9a8gPc-*\x18&\xdf\x1a\xef^7-qvw\x88\x87D\xab5\x8e>\xd0Z\xebaWjb\xea.m6\x86\x81$1\xbc\xb6\x8e\x18\xc4U\xe2>\x96uZ\xa8m\xd7¤\xf8\xe49tɸ\x81\xc9J\x17\fw\xc2\x12\xfb\xd10\xf4\x14\xec\xe8\xec\x94\xf8\xa49)\xb8w*\x05\xf3R\xb5\x85T\x8b\xae9ppiRʺuI\x9a\xf1e\xf7d\xc9\xc5dm=n7\xac\x9f\xbf\xb6\x81\xcaS\xdb\xe6\x15\xd9\xcfl^\x11\"U\xa2\x82a^qf\x1f|c\xd5\xfcͿG\xe8\x88\xd3\xe9܋\xf6\xe2\xed\x11tc>}\xc1|\x94\xedt\xee\xf9t\xfb\x8a\xec\xcd_0~\x99l\x000֘\xa9`\xde&\xa4(XS\xb5\xbb\xea\xa8\xcee.\xc2\x1f\x9d\xbc)\x88\x82\x9b\xa6\x1c\xe5\xf1\xb5\x9d뫞\x17ׂP\u007fuUʓ\x93S\xd6-\xb5j\xafфM\xfd\xfd\x8bI\x0f\xac\xb3\xeaQkRq\xe9\xe4\x85Z\x0f\xe8\xa4\xcf'\xaa\x9c\xc6Cn\xc2&濾\xa5\x9al,g|U\xd6b\x9f\x0f\xebS\xc0\x17\x8f\xb3\xb7\xe4&\x84\xd8\xfa\x12S\xb75\x15[i\xd4\xeb\xb4էf=fmA\xc3\xd0Q\xb0\x93֥\xd5M\xee$+\x96\xaac\xbe'3|>_gH!\x95\xa2\xb3\a\x1e\x98\x96\xbc\xab8!\xb1b6\x1bo\x1b\U00014284\xdc\x1fّ\xbd\xe7Ԟ\xec\xed8\xf5\xcb\xefo?r\xea\xe03\xce/4\xef\xa3\xec\x9fܺ\xb5\xe5\r\x9c\xf8\xe8H\xb63g\xef;\xf3\xb7 t\xa3m\xfeO>G\x9f\xef}\xba\r\x8f-Ϸ\xb5\x89*w\xebȑ\x15\xab\xe6缱\xfd\xfbW\x19\xbfL6\x00\x18kLT\xb0N\x0f\xaf*X\xe5\x99\xee\xce\xea*㻇\xb9dH\xb5\x98\f\xc6\xf8j2:K\x15\xe5%\xd5:\x1b\xff\x15\x12\x9aJ =\x8fybr\n\xbe\xea\x97&i=\x10\x12\xe5~\x9a\xe2\xe1\x80\xf5\x00\"\xdb\xfd\xdal,\xea(\x92\xaaHq\x02\xd2\xd8\xf6\xa7\xcc\xc1\x15\x18\xa8\xa6+.y\xad\x17Ռ\xba\xa3D\x1d\x05ەD\xfb\x82Sh\xa8\x8b\x19Ej\xaa)\x17]=p\x95\x15wIwYۑ\x86\xe0E\x11m8\xf0\x94\xf3\x94\xbcm\xc8!\xda\xd5\xf0th\x1f\x8c܉\xdc,&\x9f\xc6\x1d\xa9\xed9$\xb9\x83h\xde\xf6\x1d\xb2\x8d\xdcO[\xeb\xdcx\x03ݾ\xa1\xf1\xcbf\x03\x80\xb1\xc5<\x05\xe3+:\x05A\xe8\xae\x14\xf0\xe5*\xb4\x93\xeeW\xbfG\xa7\xa7\"\xe1K\xe4\xf1\x10\x8avk\x82\xbb\xe6L\x9dL\x86W\x98T\xbd\x18yBnKK\xaa\xa4`D\xb1D\xa5a< V\xc1d\x0f\xb9\xd3\xe8˴\\m6\x16}\x05Sl\xf7\x13!\x91\xa9\xd3*\x98\xce*L:\n֝<5\xdf}F\x10\x85\x9cU0\xb6\x9a\x8a\x82)\a\xde0\x05\r\x0f\xd2]\x94g\x95h{\xa8;\xd6җU\xaf t5g\xc5\xeb\a\u007fu;4ޕ\xbd\xe3\xfc\xf9\xb5\x92\x82\x11\xc5ڛM\x92mٷЭ\xf9m\xb2\x8d\xa2`\xd9W\xc5\x04\xe3\x97\xcd\x06\x00c\x8by\nv\xd1-\x13\x90w\x1d\xad3\xb4\x1eL\xaaCuI\xa4oҒ\x9c\xb2\xa1Η!)\xd8t\x1d[\"/\xfb\x9b\x94\xa4\xa44\xaa\a\x82\xaa`\xb2\x87\x99\xa2\xe6͙\xae\xcdƢ\xaf`J\xb2\xd4\xca\f\x83[\u0601c\x8b\xf5\x18\x1a\x86^\x1c\x8cw/\x9efM\x12珱\n\xc6VSQ0\xe6\xc0A\xd2{\f\xe9\x83\xf9\xbc\"\xcch\x16\xb3QԦ\xcd\xeb\xf1\xe6\xc6\xc1-\xab\x9cϼ\xa3\x13\a;զ$%)\xfa\xe2\xe9\x13\xe8\xc43\xb2\xa9\xaa`\xeb\xa5\x04\xeb\x97\xc9\x06\x00c\x8by\n&\x04\t\xed\x9e`P@M\xa22\xf8\xc2\xdc\xea\xcb_\x88\x16\xe6\x93Ĵ\x99d4\xb5PR\xb0\x90X\x15E\x8a\xe4\x9f\tj\xa5H\xf1@P\x15L\xf6\x90;\x95\xbeL\xcdE#U\xb0M!\n\xd6defp\xf1\xca\xfd\x04\xf2v\xbc\xce\x1c\f\xbd8\x18\x89\xfe\xf3U\x89\xe4~\x82\xa8`\x15\xd4FS\xcd\xe1\n\xd6\x1d7\xa7\xfb\xccԙ#\x9af\xb1\x83\x06\xeeo\xaf\xc0ݤ\xf3{p\xf2Ƒ\xec\x06\xad\x85\xa4N\x1f\xdd\xd0J\xd1\xeb[Ж\xd7Cl\xb0\x82m\x91\x12\x8c_P0`\xfc0O\xc1D\xc48\x98\x97v\xbe\xaey\x98QX(-\t\x81\x04ګI!W\xb3\x90*)\x98ތ\x03I;\x927h\xa5H\xf1@P\x15L\xf6\xe0\xa5#\xbd**R\x11\x15,\x11\xfb\x16\xa6\x87(\x18\x9f\x9cA\xc6\u007f\xf9\xe24\x8e\xc5S\x15E\x11\xa6\xcdA\xc3\xd1Q\xb0b\x1a\x8bC\x19Th32\xf0\x88Y|CS\xcd\xe1\nvښd\xb5f(]ٰ\x9c\xa2\xb7\x11\x8f\x90x\xd5^\x1a\xb4B\x1b_\xa1oto\x93\x86\xbd\x92:\xe5\xec\xd1J\xd1/\xb2\xaff\xffB\xf62\\\xc1\x18\xbf\xa0`\xc0\xf8a\xae\x82\t\x81vO\xe0\x1a\xbez\xdc\a\xba\xbaOVx\xc3\xf4\"\x84\xe4\xd9\xc9\xf4\xedb\xeb\xe2]\xdbR\xf1P\xabe\xb0\x85ޯc\xe2M\x04yN\xbeo\xf2\xba\x80/>\xb7\x05\x9d\u038d'7\x10U\x0f\x03->_B\xae\xef(\x8f4\x1e\x96\xc6m\xf0n\x88[Jo52\xd9\x14\xc4{\x91-\xd4\xc5̤m\xdbfZ\x1f\xf5tjl}\x8fMs\xefϷVP\xf3\xae8\xe5\xce`\xa9Uoz\xbd\xae\x82%\x16{\xebr\xc5ۘ\xc5\t\xa5u\xb3\x13\xbb5\x85T\x8b\xce\x1e\xf8tB\x93\xd7\x17\x18Q\x17\f\xa1\xed\xce='\xf68I\\~\xafs\xfe\xde\x13'v8\xc5\x11\xe3<+\x95YyN~\xdb\xfc7\xae\xe2\xe4\xcfo\xff\xf2\x95\xec6\x12뺝\xb3Y\xfc\xa1\xd1ퟷQ\x9b\x1b\xe8\x8b_\xb4\xad\xda\xd8\xd6\xf6\xa9֯6\x1b\x00\x8c)\xe6*X\x80\x84\xc1H\xd7'\xd8T\xe5\U000761fd\x06K\x13DE\x10J\x9fLHZ\xec\x99\x1a\x9fq&\x8e\x06\xaaC\xfa7\xca\xef\"\xad\xa5\xf9x\x13\xdfN\x9e\xfd\x90\xcfz8)泺\x91ƃ@\xe7\x83\td\xaa\x95&\x9b\xc4\xc0\x14j\xfbh'\xf9\xa3+#q\xf2\xec\r\xd8@k۵8e\xf2t9\x98\xb7\xe91)\xf8u4Qwrm\xb5\xb5K~\xbaN\x97\xa4`\x95\x19\xc5)\xf1\xc9\x19b\xe4j \u007fJb\x06\xee4\xb2\x85T\x8b\xce\x1e\xf8X<\xd9\x17\x9f\x11\x12\b\xd3\xe7v\xc3Zi>\xd8\xc1\x8d{Wd\xe7l\x94\xa2\xf3\x9e$7y9\xe5\x94ix\x05o\xb2\u007fEf\u007f\xd1^Z\x834\xdc\xfc\xa5\xf4\xfeA\xf4\x91\x98ج\xf5\x1b\x92\r\x00\xc6\x12s\x15\xec\xdef]<ե\xaa\xf8\\\xed\x8c[\t:iUz\xba\x0e\x9d\xc3q\xb7\x04\x13\U000c30c3\xfcɅSF\xfa\x8b'\x00\xb8W\x00\x05\x1bCJS\xc8\xd3u\x92\xf5\x1fM\x81\x06ϴ\xc8O\xd7i9\xa3\xabq#\xa4N\x9c?\x86\x84\xa4\xd1\xe8 \x00\xc4\"\xa0`\xb1\xcf\xe98q\xf8\xd8\x1e\x17\xe6N\b\x00ܓ\x80\x82\xc5>Bnb~\x95\xaf*?Q\xef\xf7\xe3\x00pO\x03\nv/\xe0\x9d\x9d\x1c\x9f<\xe7\x0e\x1e\x9c\x01\x00\xf7\b\xa0`\x00\x00\xc4.\xa0`\x00\x00\xc4.CC\xff\x1f\xf8\xaa\xf0z\xf7Oɏ\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/help.html": `<!--{
+        "Title": "Static analysis features of godoc"
+}-->
+
+<style>
+  span.err { 'font-size:120%; color:darkred; background-color: yellow; }
+  img.ss { margin-left: 1in; } /* screenshot */
+  img.dotted { border: thin dotted; }
+</style>
+
+<!-- Images were grabbed from Chrome/Linux at 150% zoom, and are
+     displayed at 66% of natural size.  This allows users to zoom a
+     little before seeing pixels. -->
+
+<p>
+  When invoked with the <code>-analysis</code> flag, godoc performs
+  static analysis on the Go packages it indexes and displays the
+  results in the source and package views.  This document provides a
+  brief tour of these features.
+</p>
+<p>
+  The current status of the analysis features is that of a technology
+  preview; there are many problems and user-interface difficulties
+  which will be addressed in due course.  Some known problems are
+  mentioned in passing, accompanied by a warning triangle, <span
+  style='font-size:120%; color:darkred; background-color:
+  yellow'>⚠</span>.
+
+  Nonetheless, godoc's static analysis may be immediately useful today
+  for small-to-medium sized Go corpora, and it contains several
+  advances over the state of the art in code browsing.
+</p>
+
+<h2>Type analysis features</h2>
+<p>
+  <code>godoc -analysis=type</code> performs static checking similar
+  to that done by a compiler: it detects ill-formed programs, resolves
+  each identifier to the entity it denotes, computes the type of each
+  expression and the method set of each type, and determines which
+  types are assignable to each interface type.
+
+  <b>Type analysis</b> is relatively quick, requiring about 10 seconds for
+  the &gt;200 packages of the standard library, for example.
+</p>
+
+<h3>Compiler errors</h3>
+<p>
+  If any source file contains a compilation error, the source view
+  will highlight the errant location in red.  Hovering over it
+  displays the error message.
+</p>
+<img class="ss" width='811' src='error1.png'><br/>
+<p>
+  <span class='err'>⚠</span> The mark-up for compilation errors may
+  cause duplication of portions of the input.
+</p>
+
+<h3>Identifier resolution</h3>
+<p>
+  In the source view, every referring identifier is annotated with
+  information about the language entity it refers to: a package,
+  constant, variable, type, function or statement label.
+
+  Hovering over the identifier reveals the entity's kind and type
+  (e.g. <code>var x int</code> or <code>func f
+  func(int) string</code>).
+</p>
+<img class="ss" width='652' src='ident-field.png'><br/>
+<br/>
+<img class="ss" width='652' src='ident-func.png'>
+<p>
+  Clicking the link takes you to the entity's definition.
+</p>
+<img class="ss" width='652' src='ident-def.png'><br/>
+
+<h3>Type information: size/alignment, method set, interfaces</h3>
+<p>
+  Clicking on the identifier that defines a named type causes a panel
+  to appear, displaying information about the named type, including
+  its size and alignment in bytes, its <a href='http://golang.org/ref/spec#Method_sets'>method set</a>, and its
+  <i>implements</i> relation: the set of types T that are assignable to
+  or from this type U where at least one of T or U is an interface.
+
+  This example shows information about <code>net/rpc.methodType</code>.
+</p>
+<img class="ss" width='470' src='typeinfo-src.png'>
+<p>
+  The method set includes not only the declared methods of the type,
+  but also any methods "promoted" from anonymous fields of structs,
+  such as <code>sync.Mutex</code> in this example.
+
+  In addition, the receiver type is displayed as <code>*T</code> or
+  <code>T</code> depending on whether it requires the address or just
+  a copy of the receiver value.
+</p>
+<p>
+  The method set and <i>implements</i> relation are also available
+  via the package view.
+</p>
+<img class="ss dotted" width='716' src='typeinfo-pkg.png'>
+
+<h2>Pointer analysis features</h2>
+<p>
+  <code>godoc -analysis=pointer</code> additionally performs a precise
+  whole-program <b>pointer analysis</b>.  In other words, it
+  approximates the set of memory locations to which each
+  reference&mdash;not just vars of kind <code>*T</code>, but also
+  <code>[]T</code>, <code>func</code>, <code>map</code>,
+  <code>chan</code>, and <code>interface</code>&mdash;may refer.  This
+  information reveals the possible destinations of each dynamic call
+  (via a <code>func</code> variable or interface method), and the
+  relationship between send and receive operations on the same
+  channel.
+</p>
+<p>
+  Pointer analysis is slower than type analysis, taking an additional
+  15 seconds or so for the standard libraries and their tests.
+</p>
+
+<h3>Call graph navigation</h3>
+<p>
+  When pointer analysis is complete, the source view annotates the
+  code with <b>callers</b> and <b>callees</b> information: callers
+  information is associated with the <code>func</code> keyword that
+  declares a function, and callees information is associated with the
+  open paren '<span style="color: dark-blue"><code>(</code></span>' of
+  a function call.
+</p>
+<p>
+  In this example, hovering over the declaration of the
+  <code>rot13</code> function (defined in strings/strings_test.go)
+  reveals that it is called in exactly one place.
+</p>
+<img class="ss" width='612' src='callers1.png'>
+<p>
+  Clicking the link navigates to the sole caller.  (If there were
+  multiple callers, a list of choices would be displayed first.)
+</p>
+<img class="ss" width='680' src='callers2.png'>
+<p>
+  Notice that hovering over this call reveals that there are 19
+  possible callees at this site, of which our <code>rot13</code>
+  function was just one: this is a dynamic call through a variable of
+  type <code>func(rune) rune</code>.
+
+  Clicking on the call brings up the list of all 19 potential callees,
+  shown truncated.  Many of them are anonymous functions.
+</p>
+<img class="ss" width='564' src='call3.png'>
+<p>
+  Pointer analysis gives a very precise approximation of the call
+  graph compared to type-based techniques.
+
+  As a case in point, the next example shows the dynamic call inside
+  the <code>testing</code> package responsible for calling all
+  user-defined functions named <code>Example<i>XYZ</i></code>.
+</p>
+<img class="ss" width='361' src='call-eg.png'>
+<p>
+  Recall that all such functions have type <code>func()</code>,
+  i.e. no arguments and no results.  A type-based approximation could
+  only conclude that this call might dispatch to any function matching
+  that type&mdash;and these are very numerous in most
+  programs&mdash;but pointer analysis can track the flow of specific
+  <code>func</code> values through the testing package.
+
+  As an indication of its precision, the result contains only
+  functions whose name starts with <code>Example</code>.
+</p>
+
+<h3>Intra-package call graph</h3>
+<p>
+  The same call graph information is presented in a very different way
+  in the package view.  For each package, an interactive tree view
+  allows exploration of the call graph as it relates to just that
+  package; all functions from other packages are elided.
+
+  The roots of the tree are the external entry points of the package:
+  not only its exported functions, but also any unexported or
+  anonymous functions that are called (dynamically) from outside the
+  package.
+</p>
+<p>
+  This example shows the entry points of the
+  <code>path/filepath</code> package, with the call graph for
+  <code>Glob</code> expanded several levels
+</p>
+<img class="ss dotted" width='501' src='ipcg-pkg.png'>
+<p>
+  Notice that the nodes for Glob and Join appear multiple times: the
+  tree is a partial unrolling of a cyclic graph; the full unrolling
+  is in general infinite.
+</p>
+<p>
+  For each function documented in the package view, another
+  interactive tree view allows exploration of the same graph starting
+  at that function.
+
+  This is a portion of the internal graph of
+  <code>net/http.ListenAndServe</code>.
+</p>
+<img class="ss dotted" width='455' src='ipcg-func.png'>
+
+<h3>Channel peers (send ↔ receive)</h3>
+<p>
+  Because concurrent Go programs use channels to pass not just values
+  but also control between different goroutines, it is natural when
+  reading Go code to want to navigate from a channel send to the
+  corresponding receive so as to understand the sequence of events.
+</p>
+<p>
+  Godoc annotates every channel operation&mdash;make, send, range,
+  receive, close&mdash;with a link to a panel displaying information
+  about other operations that might alias the same channel.
+</p>
+<p>
+  This example, from the tests of <code>net/http</code>, shows a send
+  operation on a <code>chan bool</code>.
+</p>
+<img class="ss" width='811' src='chan1.png'>
+<p>
+  Clicking on the <code>&lt;-</code> send operator reveals that this
+  channel is made at a unique location (line 332) and that there are
+  three receive operations that might read this value.
+
+  It hardly needs pointing out that some channel element types are
+  very widely used (e.g. struct{}, bool, int, interface{}) and that a
+  typical Go program might contain dozens of receive operations on a
+  value of type <code>chan bool</code>; yet the pointer analysis is
+  able to distinguish operations on channels at a much finer precision
+  than based on their type alone.
+</p>
+<p>
+  Notice also that the send occurs in a different (anonymous) function
+  from the outer one containing the <code>make</code> and the receive
+  operations.
+</p>
+<p>
+  Here's another example of send on a different <code>chan
+  bool</code>, also in package <code>net/http</code>:
+</p>
+<img class="ss" width='774' src='chan2a.png'>
+<p>
+  The analysis finds just one receive operation that might receive
+  from this channel, in the test for this feature.
+</p>
+<img class="ss" width='737' src='chan2b.png'>
+
+<h2>Known issues</h2>
+<p>
+  <span class='err'>⚠</span> All analysis results pertain to exactly
+  one configuration (e.g. amd64 linux).  Files that are conditionally
+  compiled based on different platforms or build tags are not visible
+  to the analysis.</br>
+
+  <span class='err'>⚠</span> Files that <code>import "C"</code> require
+  preprocessing by the cgo tool.  The file offsets after preprocessing
+  do not align with the unpreprocessed file, so markup is misaligned.<br/>
+
+  <span class='err'>⚠</span> Files are not periodically re-analyzed.
+  If the files change underneath the running server, the displayed
+  markup is misaligned.</br>
+
+  <span class='err'>⚠</span> Additional issues are listed at <a href='https://code.google.com/p/go/source/browse/godoc/analysis/README?repo=tools'>go.tools/godoc/analysis/README</a>.</br>
+</p>
+`,
+
+	"analysis/ident-def.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xd2\x00\x00\x00\xf5\b\x03\x00\x00\x00\x8b\f=\xff\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE!# #$\"$%#($#&'%'(&-'\")+(4,\",.+01/>/\"241A2%685G6$8:7;<:Q9$>@=W>#AB@CEB\\B'cC$GIF\x00f\x00\x00g\x00\x00h\x00gF'\x00i\x01KLJ\x00j\x02\x02k\x03\x04l\x05mJ&\x06m\x06sJ(OQN\vo\b\x0ep\nwN&\nq\x16TUS\x10q\f\fr\x17\x0fs\x18~R%WYV\x12u\x1a,`\xae7]\xad\x15v\x1c\x86T)\x16w\x1d[]Z9a\xab\x19y\x1e^_];b\xac<c\xad\x8dZ(>e\xaf)z ac`+{\"(|*\x92]%cebAh\xb2egd+\u007f,\x9a_)Li\xafDl\xb0.\x81.ikh0\x830Ho\xb31\x841/\x858Jq\xb6mol\xa3f);\x86:Us\xb3\xabg->\x88<Wu\xb5\xaej(sur@\x8b>B\x8c@\xb3m,vxu@\x8dGC\x8dA\\z\xbbxzwI\x8dH]}\xb7K\x8fJ\xb9r*_\x80\xbaM\x91L}\u007f|\xc1s-O\x93MP\x94Oc\x84\xbeN\x95U\x81\x83\x80\xc7x+W\x95VX\x97Xm\x87\xbcY\x98Y\xd1z(Z\x99Z[\x9aZ\x87\x89\x86\\\x9b[r\x8c\xc2\xd6~-^\x9d]\\\x9dc\x8a\x8c\x89d\x9ddz\x8f\xbff\x9ff\x8f\x91\x8eh\xa1hޅ+~\x93\xc4j\xa3j\x92\x94\x91k\xa4ky\x97\xc6s\xa4lq\xa5s\x95\x97\x94\xec\x8a,\x83\x9bŘ\x9a\x96\x9a\x9b\x98u\xaaw\x86\x9e\xc8\xf1\x8e/\x9b\x9d\x9a~\xaay\x88\xa0˞\xa0\x9d\x80\xad|\xf7\x93-\xa0\xa2\x9f\xfd\x92/\x81\xb0\x85\xa2\xa4\xa1\x92\xa5\xca\xff\x952\x82\xb2\x86\xa4\xa6\xa3\x83\xb3\x87\x8b\xb2\x88\xa6\xa8\xa5\x96\xa9\u038d\xb5\x8a\xa9\xab\xa8\x8e\xb6\x8c\x9e\xad͍\xb8\x93\xac\xae\xab\x95\xb8\x95\xa1\xb1ї\xba\x96\xaf\xb1\xae\x98\xbb\x98\xa4\xb3Բ\xb4\xb0\xa5\xb5՛\xbe\x9a\xb5\xb7\xb4\xac\xb7ѣ\xbf\x9d\xa2\xc0\xa4\xb7\xb9\xb6\xa4¦\xb9\xbb\xb8\xa5Ĩ\xb1\xbd\u05fb\xbd\xba\xa8Ǫ\xb7\xbfԯƫ\xbe\xc0\xbd\xb9\xc1\xd6\xc0¾\xb2ɮ\xc1\xc3\xc0\xbb\xc3ؼ\xc4ٱ̶\xc4\xc6ó\u0378\xb9̸\xc1\xc8\u07bb\xca\xde\xc7\xc9ƻκ\xbdϻ\xca\xcc\xc8\xc7\xcbۿҾ\xc4\xcf\xdd\xcd\xcf\xcc\xcb\xcf\xdf\xc8\xd3\xc1\xc6\xd4\xc7\xcd\xd1\xe1\xd0\xd2\xcf\xc8\xd6\xca\xd2\xd2\xdd\xd2\xd4\xd1\xca\xd8\xcc\xd3\xd5\xd2\xce\xd6\xdf\xcc\xda\xcd\xd5\xd7\xd4\xd6\xd8\xd5\xcd\xdc\xcf\xd4\xdb\xd0\xd8\xd9\xe3\xd2\xdb\xe3\xd5\xdc\xd1\xd9\xdb\xd8\xd7\xde\xd3\xd5\xdf\xda\xdc\xde\xdb\xda\xdf\xe2\xd7\xe1\xdc\xe0\xde\xe2\xde\xe0\xdd\xd8\xe2\xdd\xdd\xe2\xe5\xe0\xe2\xdf\xe2\xe4\xe1\xdf\xe5\xe7\xe4\xe6\xe3\xe8\xe5\xea\xe2\xe7\xea\xe5\xe7\xe4\xe6\xe8\xe5\xe4\xe9\xec\xe7\xe9\xe6\xfe\xff\xfc\x93\x8dkM\x00\x00 \x00IDATx^\xed\x9d\u007ft\x14\xd5\xdd\xff\a%\x064*\x15\xe1y<\xb3=lbJ0@\x94\x86F\xac(\x98o崆\xf4\x89i\xfa\x8d\xf6\xa4R\u007f`A\x10\x1a͓ñ\"\x02\x15\x1e\x8c\xf5l\xea\x81ش\x91`h\xf6(\xb89r\xb2\x12\xe4Ⱥ(<\x12\xda''\x94\xd2\xf6!\xc5\b\xc8S(ȓv\xd7Գ\xde\xef\xf9\xde{\xe7\u05fd\xb3wfv\x03a\xc8\xec\xe7\xf5\xc7\xee\xec\xe43\xf7\xde\xf9̼\xf7\xde;;\x99\xb7\xf4\xff.\x00\x04\x00\xc0e\x86\xe4$[;\x9c\n\a\x00\xe0R\x03\x92\x06\x00O\x01\x92\x06\x00O\x01\x92\x06\x00O\x01\x92\x06\x00O1\x92$]_/Z\x04\x00\x80\xc1=I\xf7w4\aZv\x9dS?u\a\x82\xb6ј?\xc9\xeb\x04\x8b\x84_˄9\xed\xc9\xdbX\xf0\xb1O.u\x8a\xb1'\xc5\x12\x9e\x95\xe5\x90S\xccP\xe9$;]\x82\x17z\x17\x14\x16TE\xca\xf6!\x94h\x983\xcd7\xed\x9eF\x84\xa2\xb2\\\x95@!\x1c\x11q*\xc7\x0e\xf1n\xa6\xb8\xf3\xa8\x0eW\x9f\xd7\xe7\x14\xa5s\xb6\xbe(wA\xc2)*\x89\xc8\xf4\x9dN!\x19\x85k\x92>\x11\b\xf6\x1c\xeb\xd9\xd2<@?\x9d\v\xecjr\xd8\x00\xd5\xe6\x9e\x16,\x12ο*\xb7G\xbb\x96\xca\r\xc9\x1bYp\xa0\xce\xef\x14\xe2\x80}\t\x91^\xe5\xfdT\xd4\xd7h\x13\x96\x1aZa&\x06\xf6E\v\x16\x1dƊ\xf6=ڹ}\x11\xfd\xee\x88\xc8\vں\xda\x17\xcaQ\x14\x8fȹQ\x14\vɑ\xb8p\xe3T\x11\xeff\x8a\xe9;\x1e\x8d\xb6\xc9\xfb\x9c\xa2t\xaa\x8b\xda\xea\xf2\xce;E%ѕ\xa7}kZ$*\xc3pM҇\x02\xc7\xf0\xeb@\xa0\x87~\nv\x1cs\x92t\x9f\xbcZ\xb0\xa8\x10\x91\U0006937b\xc4?\xa3TiL霴ö\x84\u007f[\xa2-\xf9/\\\xd2Faf\n\xd7◚j\xb2XG$\xbd\xba\x80\b8>\x05\xa7'&\xd7\xd6\xe1\xfeT\x8eYm\x9b\"\xe2\xddL9}\aS\x97\xf4y\xb9\x15%\x86\xd2\\\xbdc\xb7NT&ᚤ\x11\xed\x9eO\x06\xfa\xc9[w\xd3@\xbf\x93\xa4\xeb\xfc\xa7\x04\x8b\n\x8a\xa4\xe3\x05+Q\xaa\xa4|NZb[B\xf9Ŕt\xb9\xbd\xa4K\xe8\xe0\xa4W\xee\xc4\xfd\\\x05]]QC$\x1dɏ\x8d(I\xf7\xc9\x17:\x80\xb6NT&ឤ1\xb1\xa3-A\xf2\x15{.p\b9I\xfac\xdf*\xc1\xa2\x8a\"i\xb4\xb2\x90\xbcn\xafʻg\xb5r&\xf7-*\xf4\x15-\xa0\xfao+\xcf+k\xa3+O\xd5Θ\xb2H\x1d92\xb1\x1a\xbd>Yn\xe8\xab-ɭI\xb0\x01\x03Kf\xf8J\x16\xf6\x9aK\x88֔\xf8\n\x17\x94p%\xec\x94\x15\xca\xc9\a\xff\xda\xd5\xf7\xe4\xd5\x1c\xa7\u007f\x10ԶR\xf6\xb5'\a\x1c\xc6mX\x88f\xcarA\x9c+\xcc\f\x95\xf4\xd2\"\xba\xf3]x\xbb\xaaEt\xf5\xa2*\"\xe9\x8f\xcbC\x02IkU\xf0\x15\xa7\x91(v\xad\x06\x99\xb37\xa2F\x99\x8c\xfe\xd9D\xe9\x92^)\xcbۍ)\xb8 \x0f\x83\x85\xcan\xae6\x1f\x00\xb59\x89\"ߋ3gDV\x15T\x0fp\u06ddϓ\xd5\xcb\x15\\\xa2D\x87%SpQ\xd2'\x03\x18zy,\u0601\x1c%]\xef;.XTQ%\xdd.\xe3\xe3]/\xaf\xeaj\x9d^NN\x87H~\xf9\xab\x91F<\x9e#\x1d{CW\x83\xff)\xbc\xd4WpO\xfb\xce\x1a\x99\x9e\x93L\xacN<\x14*\x99\x93?su\xad|\x9c\r\xe8\x92\xeb#\xa1\x85\xf2A\xbe\x84\xdf\xcaO\x85\"\xed\x852W\x02\x9e\xe4Ω\x8eF\xa3t\x1a\xe0\x97KC;\x8b\x16Y\xd5\xf6\xa7\x90O\x9e\xde\xf8\xeb|> q\xa0Q>\x80ޔ\xb7\xf7\U00085661\x92>^\"\xd74\x1e\x18$\x9f˖\xd1\xd5\xcbʨ\xa4[\x17(\x92\x8e\u007f\xac\x10g\xab\xe0*N#Q\xecZ\x9dX\xb4\xa0\xe1o\xe8o\r\x05\xd1\x18\x9b(\xa4KZ\xb9\xa6\xa0N\xc1Ey@\xbdѐ\xdc\x18\x8d\x9e6\x1d\x00\xbd9\x91\x02yu\xb5\\\xb8\xb1\xa8\x95\xdb\fo\x17U\x06Bl\xa2\x84\x87%SpQ\xd2\xe8d\u007fwK3\xd6tO`\xc0Q\xd2\xc7}\xcf\n\x165TIw\xe1\xc9t\x97\xfc&\"g\x12\xfe掗\xd4\xe0\xb3x0t\x1e\xa1w\xe9\x85߈܅{\xb29\xf8,O\x94\xf9i\xbc\x1e\xcbQ.\x93\xbe`\x80\v\x88\x85H\xb7R\xb6\x10q%\xb4M\xa7=I\x81\xf9\xdca\x06\xdeEg\xf1I<\x1dY\xd6柂\xcf\xdcڤ\x80\xba\x8a\xb337\x9a\v3C%\x8d\xceo\xac\xf0\xc9S\xc8V\xa5\xb5tum)\x95\xf4\xe9\xdc\xd3T\xd2\xd5j\xffU\xc5WaT\x9cN\xa2\x98\xb5,\xf5K\xf1\xcb2\xf2\xd3\"\x93(\xc4\f\xbc\xa9\xee\x1a\xed\xb2\xce\f\xbc\xf5\x03\xc04\xa7\xa8\x16o\xb9\x13\xd5%\xff|\x99\xab\xcdm\xf4DY\x1d\x96\x8c\xc0MIc\xe2-\x1d\xe4\x12Y\"\x918ڔ\xb0;\x00+}\x1f\v\x165\xf4^\xfa<Zz\xc7 .-1\xb3\x9e\x9c;\xfa\x15\xd0\xfa2\xfaVZ\x87\xce\xcb\xf4\xb7\xae\x06rr1\xb1\x1c\xe5~u\x18\xc0\x06\x9cm\xab\xb9\xa3@.C\\\t\x9f\xce(Y\xd9ޛ\x184\x15\xc0J\x9al\xdbhS\x9b\xbfN\x18\x10/+z4\xa903\x8a\xa4It\xe4G\xe4\xb4W{\xe9\xa5J/\x8d\x16\xb4RI\xf7\xedT\xe8\xe3\xab0*N#Q\xecZ\x96Hn\f\xc5\xf2\xa2dQO\x14A i\xab\xac\xb3\x92\xd6\x0e\x80\xd1\x1cT\x14\u0085\r\xa0\xb5ː\x99dI[\x1d\x96\x8c\xc05I\xc7\x15\x01\xef\x0f$\x8e\x044\xfa-\xa3O\xf9\xeb\x05\x8b:\xaa\xa4\xd7\x16\xe0\xb3Z\xed\x92p/\xd1*\xeb?\xe0T)\xf2x\xb4\x02\xf5\xca\xf4\xbc\xa3'\x17\x13\xcbQ\xaeM\\\x99\x80\x83E%k;\xa3\xd5e\x88+\x01\x9do_R*\x17\xbdj*\xc0|y̮6\xab\x80\x90~a\xc9A\xd2\a\xe9\x148Q\x857\xabR6]\xa8̥Q\xa8\xcc<\x97f\xab0*N#Q\xdc\xce3$\n;Qg!9\xa6F\xa2\b\x02I[e\x9d\x95\xb4v\x00\x8c栢w\xd1A\x1fB\xebR\x91\xb4\xd5a\xc9\bܒt\xa2i\a}ǒN\x9c$t\aN\x9e\xb4\xee\xa6W\xc9}\x82E\x1dE҃\xd3\xf1!\xad\xbd\xa3\x97r\x96\xac5:\x9f;\xe8[I\x1d:+\xd3k?tV\xc7\xc4r\x94/R\x17\x98\x80\xd2\n\"\x8eE\xf8LeK\xe8%\xb7\xbc\xfc=\x94\xdbf.\x81\x9c\\\xed\xa4\xab1Ne\x8b\xda,\x02N\x155\x94\x9c5\x17f\x90\xa0sk*颕tM\xc3\x1c<\xc4V\xa4P^\xa3H:\x96\x171I\x9a\xad¨8\x8dD\xb1k9V-D\x8b\xe8UK#Q\x04^\xd2\rvYg%\xad\x1d\x00\xa39\xa8(\x82\x0e\xfaS\x904I\x94\xd5a\xc9\bܒ4j\xee \xafd\xe0\xad`;\x97>M\a\x89\xe6E\x03E\xd2\xebș\x19Q\xe6h\rx\x1e\x1a+\xaa&C\xafU\xab\xc8В\xac\r\x91\xc1iE\t\x9e2\xf6\xe5*\xa7\xb2\x1eˡ\u007f\xdb3\x01%\xe4,K\x94\x913\x95)\xa1Q~\x97\x04T\x9b\a\x0e\xd5ո\xa5ʌ\x95\x11\x8e\xb06q\xc0`E\x03\xaa\xafN\x98\n3h#\xbd\xe5Y\xf9u\xbcX8\x93ܞ\x91 2X\x9dO\u007f\x97ΫW$\x8dꖙ$\xcdVaT\x9cN\xa2\x98\xb5\x1c\a\xfc\xa7\xfc\a\xc8\x02\x93(\xc4H:\x0f\u007f\xfb$*\xec\xb2\xceJZ;\x00LsR\x90\xb4\x9e(\xabÒ\x11\xb8&\xe9C\x81\x8e\x9ec=-\xea\xddc\x89\xfe\xee@\xff\x19\xcb\xe0\xb5FϼV\xd0I+w\x8f=\xa5\xdc=\xb6N^\x16\uab17\xb7#2\xc1+m\xebZEg\u007f\xb5\xf2\xba\xaeu2\xb9zt8ofc\xc34\xd9\xf7\xe6a.V'q\x80^9U\xe6\xebF@\xa3\xbc\xa4mc\xb9\\\xf8\xea\x01\xb6\x84F9\xbf\xa1\v\a\x98\xef\xbal\xf4\xff\xba\xb3:\xefSr\xa5\xb7\xee\x00\xea\xad\xf3EO\x89k\x13\a\xc4\xf7=;\xfd8\xea+X\xbd/\xce\x14\xc6\x12\x91\x17\x84ެ($+\v墆wq@\x1fY[\xd3\x19\xed\xac\x91;\xc9\xddc\xa1\x18\x8a\xe6\x99\u007f\xc4ҫ\xe0*N#Q\xecZ\x96Č\x9a\x19\xf4\x1b\x88Iԧ\xe4\xee\xb1\xd6h\x94\f0\xaa\xa6\xbf\xba\xb1\xc2:\xeb\xea\x15\xef\x03\t\xd3\x01ЛsxZk,\xe4\xeb\x8d-\xab\xe6\x86+\x83\xfb\xa2Q\u007f]4JO#=QV\x87%#pMҨ\u007fGK`\xebnu\x12\xd7O\xa6\xd2\xcdV\xa1\xa7\xf3j\x05\x8b\x06\xca=\xde%\xea=ޑ\xea\xc2)U]t\xb1o\xc9\xcc\xfc\x8aN\xb2\x94x\xbd,\xaf\xac\x8d\x9es}\v\xa7\x95\xac}\xd3'?\xcb\xc7j\xf4*3\xbdGM\x85%Z\xe7\xf8\xa7/m\x9f\xe3\xabfK\xd8^\xd5X\xe2+\xaaN:u⫦\xe5V\x1f\xa4\xf7x˾\xc3\xe4\xb7S\x8b\xda\xc4\x01\x11\x99\xfcB\xbbJV\xee\xd0\xd6\n\xe3\xe8,\xcf+x\x94ʪ\xa2\xbd\xa14o\xfaB\xf2M\x97h\x98S \x17\xcciL\xd0\x12B\xb8[,2Of\xb4*\xf8\x8a\xd3H\x14\xbb\x96\xa5\xd5\xdfJߙDթ\xb3f\xd2\xe7\xf6U\xe7\xe6\u05fch\x99\x87x\x01\x8d\xf4\xfd\xd9t\x00\xb4\xe6$\x8a\xf0\xfe\xe4\xcby!\xd3\x1c\xfc\xb7j\x15\xf4\xd8뉲:,\x19\x81{\x92N\x83\x17\xe5?\t\x16\x01\x00HfDH\x1a\xfe\xab\x12\x00ReDH\x1a\x00\x80T\x01I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x18I\x92\x86[\xbd\x01\xc0\x11\xf7$m\x18\xe8Ě\x94\xe7\x149\xf8BX\x1b\xe8\x10\x86\xcdF%U\xb7\x98\xa1\xe3\xd8t\xc7\x00\x95\xa1\xda\xf5\xa4it#&\xd5FR\xd2O\xeaP\xf7-\xf3pMҌ\x81ι\xc0\xfe~\xccI\x87-\xac\rt\b\x86\x8d\x8a#i\xfa\xac\xa4f\x95s\x018:\xc08\xedۅ\xda\xf5\xa4it#F\xd8H\xcb\xec\b\x92j\x9fɡ\xee[\xe6ᚤ\x19\x03\x9ds\x81\xa3N\xd1\xc8\xde@\x87\x90\xfa\x03^\xd3\xf5YI\xd1*g\xe88:\xc08\xec\xdbE\xb0\xebI\xc3\x15\xc3\nQ#\xad\xb3\x93\x9cT\xa7L\x0ey\xdf2\f\xd7$\xcd\x18\xe8\xa4&i;\x03\x9d\xf4H\xd7g%E\xab\x9c\x8b\xc0\x10\v\xbb\bv=\x17A\xd2\"\xacw(9\xa9N;?\xe4}\xcb0ܓ4\xd2\rtR\x92\xb4\xad\x81\x8ea\xa3\xc2\xf8\xc2\xe0\xc5\xd6\xfa\x99\xd3\xc8\x13|\x18\xff\x16\vC\x1a\xc3\xf6\x85s\x96\x11\xb9\xc50\xf6,|a\x9a\xf5\x8c\x85\x05\x8f\xd8\xd5\xc5\xc2\x01F\x14\xc0{\xdeh\xa4c\xd7s\xe1F7LR\x11c\xb6#l$\xbfC\xf6\x16<\xe2Lr\xf8W\xd5Ϡ\x15w\xe1\xb8\x17ս0`\xf7-\xa3qQҺ\x81ι@ǖ@s\xd8\xf4\xe0;\x13\xb6\x06:\x86\x8d\n\xe3\vC\x16K66\x96\xe4\x1df\xfd[,\fi\f\xdb\x17\xd6YF\xe8\x16\xc3سp\x85\xe9^/\x16\x16<\x16\xae.B\a\x18a\x00\xe7y\xa3\x93\x8e]υ\x1b\xdd0Ie\xcdv\x84\x8d\xe4Z\xe6`\xc1#\xce$\x87_.\x0f\x85\xcapű}%\xf5\xa7ս0`\xf7-\xa3qQҺ\x81ι@S\xf7ў\x96f\xbb+\xde\xf6\x06:\x04\xedѯ\x86/\f\xf2\x97\xe0\xd1\xfd\xf9\x12b\xe7h<\xe1V<\xc2cm_\x8c\x12\xc4n1\x9c=\x8b^\x18\xe3\xf5\"\xb6\xe0\xb1vu\x11<[^\x1c\xc0\xec\x1bK\x1av=\x17ntc$\x95\xdbcq#\x99\xa7\xf7:Y\xf0Xd\xd2\xc0_\x8aO\x90\xf8\x1cr4\x1bIg\xfe\x94\xf9\x87Lc\xdf2\x1a7%\x8d\xd4\xe7x'\xba\xc9\xc9\x15k\xdam\x13ho\xa0C\xd0\xcf(\xf2\x9coE\xbc\xfe\xff \xafm\xf2ygI\xb3\xb6/z\t\x16n1\x9c=\x8b^\x18\xe3\xf5\x82\x84\x16<֮.\xa9K\xda\xd87\x964\xecz.\xdc\xe8\xc6H*\xb7\xc7\xe2F\xea-s\xb6\xe0\xb1Ȥ\x81\xffE\xf2J\x8f\xe6q\xf90\x8a\xe7\x9b\x1f\x00\xca\xec[&㚤\r\x03\x1dmMx\xabe\xb0\x93\x81\x0eA?\xa3\f\xf1*C\xc1(yb\xbf\x93\xa4Y\xdb\x17=\xd6\xca-\x86\xb5g\xd1\vc\xbc^\x90Ђ\xc7\xda\xd5%uI3{\xc1\x90\x86]υ\x1b\xdd\x18I\xe5\xf6X\xdcH\xbde\xce\x16<\x16\x994`\x8e&\xfa\xd1Z\xf4\xee\x14\U000d78f1o\x19\x8d[\x92f\ftPG\x90.\xee\bZ\x87;\x18\xe8\x10D\x92\xa6\x97ѨE\xad\xe1\xdf\xc2\xf8\xac0\xb0\xb6/z\t\x16n1\x9c=\x8b^\x18\xe3\xf5\x82\x84\x16<֮.\xc9\x0e0\x16\x01v\x92Nͮ\xe7\u008dn\x8c\xa4r{l#iҲ\x14,xę4\xf0\xd3_.\xe9\xd1D;\v\a\x05\x16\x96\xfa\xbee4nI\x9a5\xd0\tn!\x8bg\x02\xfb-\x83\x9d\ft\b\"I\x17\xe1\xb3v\xe0\x8ej\xc4\xfa\xb7\x88\riX\xdb\x17\xa3\x04\xb1[\fgϢ\x17\xc6x\xbd0=\x0e\xe3\x16c\xed\xea\x92\xec\x00c\x11`!\xe94\xecz.\xdc\xe8\xc6H*\xb7\xc7\xe2F\xea-K\xc1\x82G\x9cI\x03\xffL\xe2\x98[J\x8e&\x1a,\xdc9-\xf9\xc1\xfb\xfa\xbea>\xdex\xa1\xb7ÍT\\\x934c\xa0s4\xb0\xed\xd0ѽ\x81\xa0\xf5\x90\xc9\xc1@\x87\xb1Q\xe1|a\xc85\xd2\xf69S\xc8\x06\x8c\u007f\v\x12\x19\xd2\x18\xb6/l\tb\xb7\x18Ξ\xc5(L\xf7z\xb1\xb4\xe0\x11\xb9\xba\x88\x1d`\x84\x01ܾ\xb1\xa4l׃.\xdc\xe8\x86M\xaaa\xb6c\xd5Hc\x87\x9c-x\x04\x994U\\s R5E9\xfc\xeb\ue612|\xba\xe8\xfb\x86Y(/H\xfa{f\xe0\x9a\xa4Y\x03\x9d\x13\x1d́`\xb7\xb5\xa2\x9d\ft\x18\x1b\x15\xce\x17ƿ\xba\xbe`F-=\xffY\xff\x16\x91!\x8da\xfb\u0095 t\x8b\xe1\xecY\x8c\xc2t\xeb\x19\v\v\x1e\xb1\xab\x8b\xd8\x01F\x18\xc0{\xde0\xa4l\xd7C\xb80\xa3\x1b.\xa9\x86َU#\x99\x1dr\xb4\xe0\x11d\x92\xa3\xb4qI\xbeZ1\xb9\x81PtEE\xdb7L\xfb\xf4vA@&\xe0\x9e\xa4\xd3`\xa8\x06:p\xbf\xd10py$5\xe6\xcfLë\x14\x18\x11\x92\x1e\xea\u007fU^\x1eg\x9fǸ<\x92\x1a\x82+\xdbV\x8c\bI\x0f\x95\xcb\xe3\xec\xf3\x18\x97AR\x1b#\xa8\xba\xc1)(c\U00070915\v5\xc0E\xe5rHjL._Yt\xde)*c\xf1\xb0\xa4\xe9\x85\x1a\xe1\x8df\xc0\x90\xb9,\x92ڐ_m\xbe\x11\x1e\xd0\xf1\xb0\xa4\x01 \x13\x01I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x18I\x92\x1e\xea\xad\xde\x00\x90A\xb8'i\xc3@\aӳ\xad\xa9e\xaf}\xbc\x83\x81\x0e\x00\x00\x04\xd7$\xcd\x18\xe8\xa0xG`\xf7\x91\xbd\x81C\xf6[\xd8\x1b\xe8\x00\x00@pMҌ\x81\x0e\xea \x9e\x1b'\xe9\xa25N\x06:\x00\x00 \x17%\xcd\x18\xe8\xf4+O\x1d;g\x1f\u007f\xf1\ft\x00\xc0ø'i\xa4\x1b\xe8\xec\x0e\f:\x19\xb99\x18\xe8\x00\x00\xa0⢤u\x03\x9d`\xb0gk\xa0yׅ\x18\xe8\x00\x00\xa0ࢤu\x03\x9d\x16j\xa0\xd3\xdcra\x06:\x00\x00 w%\x8d\xb4\xe7xӾz \xb0\xc7&\xd0\xd9@\a\x00\x00䢤\x19\x03\x1d\xd59'l㶑\x82\x81\x0e\x00\x00\xc8=I\xb3\x06:{\x9b\xa8\xbc;.\xcc@\a\x00\x00䞤Y\x03\x1d\xc5:\xe7\\\xc0\xfa\xf6\xb1T\ft\x00\x00@.J\x9a1\xd0A{\x03{\x8fv7m\x15ش\xaa8\x19\xe8\x00\x00\xa0⚤Y\x03\x1dt(\x18ز\xd7Zю\x06:\x00\x00\xa8\xb8'\xe94\x18\xaa\x81\x0e\x00d\x1e#B\xd2\xf0_\x95\x00\x90*#B\xd2\x00\x00\xa4\nH\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\xc5H\x924\xdc\xea\r\x00\x8e\xb8'i\xdd@g\xb0)\xa0\xd0l\xbf\x81\x9d\x81N\xef\x82\u0082\xaaH\xd9>\xf36\xb6<+\xcb!\xa7\x18\xf2\x88a\xb9\xd4)\xe6\xa2\x11\x99\xbe\xd3)D\xe7l}Q\xee\x02LJ%#T%\x93\xfd\f\xe1\xd7*\xa7P\v,\x12U\x87\x8b\xcc\x13\xfd\xf7z\xaa-\xa3\xa4\x91_-;\x96\x15'\x93\xda1\xf6\x14\xaeI\xda0Љ\x05\xf6\xf6c\xf6*\x0f\xe8\xb7\xc6\xc6@\xa7\xd7\xf7h\xe7\xf6E\xa9\x1e\xbdH\xaf\xf2~*\xeak\xb4\x8f\xa4\x1c\xa8\xf3;\x85\xa4\x88V\xb1\xf5ڮ\xbc\xd4v\x81P]\xd4V\x97w\xde)\n\xa1\xbe\xd5r$\x86bQyuj*H\xc6\"Qǣ\xd16Y\xf4-\x9aj\xcb\x14\x04\xf9\x15'Jώe\xc5ɤr\x8c-j\x1b\xa9\xb8&i\xc6@\xa7\x9b<\xd9d\xa0i\x97\xfd\x06v\x06:5\xd5\xe4\xb5.EI\xff\xdb\x12m\xc9\xefx\xb8\t\x8d\x17K\xd2FŖkS\xed\xdb\x10:/\xb7\xa2\x84\xfd\xb3\xcfUZe\xf2\xa0\x89\x04\x8e\x1f2V\x89:(RV\xea-SHί8Qlv\x84\x15\vq>\xc6V\xb5\x8dP\\\x934c\xa0Cٶ\xc5\xfa\xa9&\x14;\x03\x9d\x92\x06\xf2\xda+w\xa2T(wK\xd2\xe5\xc2sG\xbc֑>9\xd51\xfa\xa5\x96t\xea-SHίsJ.\xa6\xa4\x9dk\x1bQ\xb8'i\xa4\x1b\xe8\x10z\x02'\xeccm\rt\x96\x16\x1d&o]\xb4k\xd8^\x95w\xcfj\xa5\x93`\x165v\xca\n\xe5\xe4\x83\u007f\xed\xea{\xf2j\x8e[\xc5\xe2q[\xed\x8c)\x8bԁa[y^Y\x9b\xb2\xbaoQ\xa1\xafh\xc1)\xb4R\x96\xb7+\x93\xc1D\x91\xefř3\"\xab\n\xaa\a\xd8\xc2Vʾv\xb5\n\xb6\xe2\x81%3|%\v{M\xcd9\x9f'\x1bs\a\xad6\xa6\x04\x86\xc1Be\xb3\xd5\\l\xafO\x96\x1b\xfajKrk\xb8\xceސ\xb4Q\x18\xd7^\xa39\\\tњ\x12_\xe1\x82\x12R\x84\x91(#\x96\x90\xac\xac\xb4Z\xc6\xe5W˙8Q|v\x8c\x8a\x99F\x1a\xb0\x8d\xf4\xaf\xaa\x9f1m\xa12\xe70\x92\xaa\x1d7\xfe|\xf0\x04.JZ7\xd0!\xb4t\xd8\xc6:\x18\xe8\x1c/\x91k\x1a\x0f(\xdd|\xbd\xbc\xaa\xabuzy\x82_\xd4\x19\xd8\x17\x9dS\x1d\x8dF\xffL>\xf8\xe5\xd2\xd0\u03a2E\xa6\xcd\f\xfa\n\xeei\xdfY#\xd3S\xae\xce\xdf\xd0\xd5\xe0\u007f\x8a,F\xf2\xcb_\x8d4b\x89(35:\x19\x8c\x14ȫ\xab\xe5\u008dE\xadla\u007f\n\xf9\xe4鍿\xce_\xc4W\xdc%\xd7GB\v僦\xe6\xf4F\xa3Z\x9f\xa2\xd7Ɣ\xc0\xd2\x1b\rɍ\xd1\xe8i.6\x1e\n\x95\xccɟ\xb9\xbaV\xe6\x12dH\x9a)\x8cm\xaf\xd1\x1c\xb6\x84\xdf\xcaO\x85\"\xed\x852I\x89\x91(#\x96 \xe8,\xd3i\x19\x9b_=g\xe2Dq\xd91*f\x1bi\xc0n\xe6\x97\xcbC\xa1\xb2<\xf2\x9d\xaf7\x879n\xdc\x01\xf0\x04.JZ7\xd0\xc1\x1c\xa13k\x1b\x1c\ft\xceo\xac\xf0\xc9S\xc8wx\x97\xfc&\"G<\xc4-r0\x03\uf8b3\xf8\\\x9a\x8e\xacb\xab\xe6\xe0^#QFN\xb9w\xe5\b~\x8d\xc8]\xf8\xfc,\xa9\xc1\x1a\x19\f\x91\v@\xf4$\xa3#ǢZ\\\xc8NTW\xcf\x17柂O\xe2\xda\xe9|ű\x10\x19\x0e\x94-\xe4\xd7\x12r\x95\x93\x96\xa9\x8d+\x81A\x1f\u07b2\xb1\xa8\\\xa6\xdd.\x17\xc9\x0e\xbc\x8d\u0098\xf6\xf2\xcd\xd1Jh\x9bNt\xd2V@%\xad'\x8a\x8bu\x18x;\xb6\x8c\xc9/w\x00ĉҳ\x83\x8c\x8a\xd9F\x1a\xb0\x9b\xf9K\xf1\xde\xc7\xe7T\x98\x92\xaa\x1f7\x18x\xb38\x15\xeeL\\\xed\x9d;Z\xec\xe3R0ЉG~D\x0e\xd6\xd2;\x06\x13\x98\x99\xf5\xdc\"\a#i\xf2'z`\x85\xb1\xe7\xe5v\xf2\xd6@\x02\xea\xcb\xe8\xaa\xd2:r\xf6\x19\x97H\x19I\x87\xf0y6\x80\xd6.\xe3\v\xa3\x8f\x1dO:wζ\xd5\xdcQ \x97\x99\xd6\"\xfd\xa4ej\xe3J`Ѕ\xc3Ƣr\u007f\xb2\x05 'i\xbd0\xa6\xbd|s\xb4\x12>\x9dQ\xb2\xb2\xbd7A\xc7>F\xa2\xb8X\aI;\xb5\x8c\xcd/w\x00ĉ\x12I\x9am$\x03\xb3\x99\xffE\xf2\xda&\x9f\xe7\x93\n\x92\x16\xe2T\xb8\x1d\x8c\x81\x0e\xa6\xc9\xfa\xb1\xfc\x14\a\x03\x9d\x83\xf4rY\xa2\n\u007f-\x97\xa9s#~\x91\xc3ty\x8c\x1eXal\xaf\x1cEZ@գtգ\x15\x9aD\xcc%\x14\xbd\x8b\x0e\xfa\x10Z\xb7\x8c/Lx\xee\x1c,*Y\xdb\x19\xad\xb6\x964S\x1bW\x02\x83.\x1c6\x16\x95\v\xe6\x84m\xf2\xdf\xf1kL&\xb3Ha{\xf9\xe6\xe8%\x9co_R*\x17\xbd\x8a\xb8\u0378X\aI;\xb5\x8c\xcd/w\x00ĉ\x12I\x9am\xa4\x01\xbb\x992X\x8f\xe2\xafa\xab\xa4\x82\xa4\r\x9c\n\xb7\x815\xd0!~\x1bG\xec\xc3\x1d\ft\x8aVҷ\x869xPyG/\xe5,\xb7\xc8A\x0fa;\xe93\x8c\x03+\x8c=KU\x80\xe8\xe5\x9b\xfa;誒:2t3\xf5Ҵ\x9b)\x8a\xa0\x83~E\"laI\xe7\x0e\xa9\xb8\xb4\x82\f\f\x17\x95\xf1k\tZ/m\xd4\xe6(i6\x16\x95\x9b\xe6܄(m\xaf\xa2\x1fF\xd2F{\xf9\xe6h%\xf4\x92\xdby\xfe\x1e\xca\xe5\xbf\t\xb8X\xa7^ڡel~\xb9\x03 N\x94H\xd2l#\r\xd8\xcd\xfc\xf4B];\x1e\x90$%\xb5\xc1tX\xbc\x81[\x92f\rt\xc8TZ\xbbL&\xc6\xc9@\xa7p&\x99\xd7&\xc8Y\x13Qfc\r\x1b\xb9E\x8e\xeaj\\\x8c2\xd1\xd5\xcfTqlE\t.\xb7/\x97\x04tр\x10\x19\xdbNJ\xaa\xc9@o\x15\xb9\ue7b7\x16\xd7[a\x92\b[\x18+H\xbd\xe2\x12rz'\xca\xcaL\xcdA\xfaI\xcb\xd4\xe6(i6V\xd8\xe3\fL#\xe3\x9a\xfai\x03\xc8B\xd2\\s\xf4\x12\x1a\xe5w\xc9[u=\xb7\x19\x17\xeb iǖ1\xf9\xe5\x0e\x808Q\"I\xb3\x8d4`7\xf3\xcf$\x17>J\xab\xf9\xe6\x18\xc7\xcdt\x00F>\xaeI\x9a5\xd0A=\x01;oig\x03\x9dB\xb9\xa8\xe1\xdd\xcejz\x93\xe0:yY\xa8\xb3^\xde\xce/\xb24\xfa\u007f\x8dc?%\xd7=\xeb\x0e\xa0\xde:_\xf4\x94E\xecἙ\x8d\r\xd3dߛ\x87q7\"\xaf\xebZ'גՑ\xdcҶ\xaeUt\"X5\xfdՍ\x15$\xe0\xf0\xb4\xd6X\xc8\xd7\x1b[V}\x9c)\x8c\xabB\xaf\x18\x9f\x88K\xda6\x96˅\xaf\x1e`\xd7\x0e\xee\x8bF\xfdu\xd1(I\x89^\x1b_\x82\x8er]\xf9\x00\x9d\xb5豉\x03\xf4\xeamҥ\x86\x90\xfclW=9g\x99\xc2\xd8\xf6\x1a\xcdaKh\x94\xf3\x1b\xba\xf0^D\xb860M\xff\x94\xdc\xc4\xd5\x1a\x8d\xf2\xfd[:-c\xf3\xcb\x1e\x00Q\xa2\x98\xec0\x15\x1b\x8dda\xf3\xeb\x97k\x0eD\xaa\xa6\xf4!\xee\x10\xeaǍ\xad\xcd\x1b\xb8&i\xce@\xe7\xc8\x16\xdbPG\x03\x9d\x8a\xf6\x86Ҽ\xe9ꏏ\x91\xea\xc2)U]\xe6E\x86\xf8\xaai\xb9\xd5\a\xe9\xfd\xbf\xb2\xef0\xf9\xb9\xf3Y\xabؾ\x85\xd3J־\xe9#\x01\x89\xd7\xcb\xf2\xcaڔ+\x00}Kf\xe6Wtҥ\xea\xdc\xfc\x9a\x17e\xb9\xbeH\x96C\xf9r^H\x99\rj\x85\xf1Uh\x15\xa3D\xeb\x1c\xff\xf4\xa5\xeds|\xd5\xec\xdaߪ\xd3I\xf2U\xa1\xd7Ɨ\xa0\x11/\xa0\x91>\xfaӋ\x1e۫l\xff(2\xd3U\x9eWNv\xcd(\x8ck\xaf\xd1\x1c\xb6\x84\xedU\x8d%\xbe\xa2\xea\b\xdf\x06\xa6\xe9uj{\xb9\xee7\xbd\x961\xf9e\x0f\x80(QLv\x98\x8a\x8dF\xb2\xb0\xf9-m\\\x92?\xa3V\xb9\xd8b\x1cB\xed\xb8q\x87\xc5\x1b\xb8'\xe94\x00\x03\x1d\x00H\x95\x11!i\xf8\xafJ\x00H\x95\x11!i\x00\x00R\x05$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9eb$I\x1an\xf5\x06\x00Gܓ\xb4n\xa0\x83\xd0\xc0\xae-\x81-\xbb\x06\x1c6\xb03\xd0ѹ\xf4\x86)\xe9x\xde0\x88Mf:\xc9\xff\f\x92'\xd8\x1a\x8e@\x89\x869\xd3|\xd3\xeei$O'\x91\xab\x12\xd4\t\xc7\xf4\xbf\x84Cm\x83\x90\xce\xd2ܲPy\xd2\u007f\xa4ړ\x86\xa5\r0̸&i\xc3@\a\x9dk\xda\xdas\xb4gK\x93\xfd\x93M\xec\ft\xd26Ź\x88\xa4\xe3y\xc3 6\x99\x19\xd8\x17-Xt\x98s\x04\x8a\xc8\vں\xda\x17\xcaQ\x14\x8fȹQ\x14\v\xc9\x11\xf3\x03#\x84m\x18\x9a/\xcc\xebrm\xe7Z9\xdd\xc7\xf8\xa7ai\x03\f3\xaeI\x9a1\xd0\t\xb7\x90\xe7\xfe\f\xb6\x84m7\xb03\xd0I\xdf\x14\xe7\"\x92\xba\xe7\r\x83\xb5\xc9L\xe1Z\xc49\x02\xad. \x02\x8eOYM\x9e\bX[\x87\xd0\xc7r\xf2v\xa26\f\xc9\x17\xa6On\xc0\xaf\xabӕ4J\xc7\xff\x02\x18V\\\x934c\xa0ӱ\x95\xae\b\xda?\x9d\xdf\xce@'驟\x97=\xd6&3TҌ#P5}\xbe&\xaa\xa8!\x92\x8e\xe4DŽ\x92\x161\xa4\a_>5\x9d|\x81\xfcI\xe6\x1fϗ\n \xe9\xcb\x04\xf7$\x8dt\x03\x9d3M\xe13\xf13\xe1\xa63v\xb1v\x06:\xe9\x99\xe2\xe8\xf67HhSC檍\xa8QV&\xe5Z\t\x16\xce2ix\xde0\x01\xbcɌ\t*i\xc6\x11\xa8Jy\xb2\xe6\xa2*\"\xe9\x8f\xcbCI\x926\xda`a\xd7\xc3y\xff\xe8\xf0N8\x1a\xd3\xd6ҷ\u05cf[l\xc6fG\xe8\xa5\xc3x\xd3 \xab\x03\x00\f'.J\xda0Љu\xe0\xa5\x0e\xfb#og\xa0\x93\x96)\x8ea\u007f#\xb6\xa9\x89E\v\x1a\xfe\x86\xfe\xd6P\x10\x8d1%X9ˤ\xe1y\xc3X\xf0\xb0&3f\xa8\xa4\x19G\xa0\xb2et\xf5\xb22*\xe9\xd6\x05ɽ\xb4\xde\x06\v\xbb\x1e\xd6\xfbǀw\xc2QQ\x1f\x96\xaf ڌ͎\xd0K\x87\xf1\xa6\xb1:\x00\xc0\xb0⢤u\x03\x9dxGKO\u007fOK\x87\x9du\xa5\x83\x81N\x1a\xa68\x8c\xfd\x8d\x85MM\xfdR\xfc\xb2\xac\xde\\\x82\xd0Y\x06\xa5\xeey\xc3\xd9\xc98\f\xbc\x19G\xa0R\xe5\xf9\x89\xb5\xa5TҧsO\x8b\x06\xde\xda\xd3p\x85v=\\\xc5:&o\x1a\x85\xc3\xca\xc5\xf4x<n\xb5\x19\x93\x1d\v/\x1d\xe3\x01\xc1V\x0eF\xc0p⦤\x91\xfa\x1c\xefp\v\xbd\x00\xd4bg0\xedd\xa0\x93\xb2)\x0ek\u007fcaS\x13ɍ\xa1X^\xd4\\\x82\xd0Y\x06\xa5\xeey\xc3\xd9\xc98I\x1a\xe9\x8e@j/\xbdT\xe9\xa5тV[I3\x15\xeb)\xe1*6\xe0\xbdi\x14\xfeN{\xe9e\xf4w2\x8b͌\xecXx\xe9\x18\x92\xb6r0\x02\x86\x13\xd7$m\x18\xe8$\x02\xfb\xb5E\xcbh\a\x03\x9d4LqX\xfb\x1b\vG\x95Da'\xea,L\x98K\x10:ˠ\xd4=o8;\x19\aI3\x8e@UJ\xf3\x17*si\x14*\xb3\x954S\xb1\x9e\x12\xaeb\x1d\x937\x8d\n\xad\xfdt\xa7\xbc.n\xb1\x19\x93\x1d\v/\x1d\xa7\x03\x00\f/nI\x9a1\xd0\xd1$\xfd\xa1\x8d\xa4\x1d\ft\xd20\xc5a\xedo\xacljV-D\x8b\xe8\x158\xde\xd5E\xe4,\x83R\xf7\xbc\xe1\xecdD\x92NЉ/\x15\x15\xe3\bT\xad|\x93\x94\xd7(\x92\x8e\xe5Eґ4I\tW\xb1\x8eɛF\xe5\xa9\"\xf2\x85\xd7I\xae4\x887c\xb2c\xe1\xa5cx\xd3X9\x18\x01É[\x92f\rtv\xa8\x03\xef\x1d\x96\xc1N\x06:\xe9\x98\xe20\xf67V65\a\xfc\xa7\xfc\xc4\a\x83/A\xe8,\x83R\xf7\xbc\xe1\xecdD\x92n#\xaeUg\xe5\xd7\x11\xe7\b\xb4:\x9ff'\xaf^\x914\xaa[\x96\xa2\xa4\xf5\x94p\x15똼iT\x94ߥ\xab\x89\xa4ś1ٱ\xf0\xd21\xbci\xf8\x03\xf0\xf1F\xb8\xbd\xecR\xe0\x9a\xa4\x19\x03\x9dXsK\xf7\xb1\xee\x96f\xebK\xdeN\x06:\xe9\x98\xe2\xb0\xf67\x1665\x89\x1953\x94\x11\x83^\x82\xd8Y&-\xcf\x1bƿ\x855\x99a\x1a&/\b\xbdYQH\x9c\\\x18G\xa0\x88\\\xd3\x19\xed\xac\x91;\xc9\xddc\xa1\x18\x8a\xe6\x99$m\xb4\xc1®\x875\x8e1\xe0L|\fZ\xe5\xfa\xaez\xe5\xee1\xe1fLv,\xbct\x18o\x1a\xee\x00,\x94\x17\x98\x8b\x02\x86\x01\xd7$\xcd\x1a\xe8\xc4\xf7l\tl\xddcm\x8b\xe5h\xa0\x93\x96)\x0ec\u007fceS\xd3\xea\xd7\xee\x9e\xd2J\x10;ˤ\xe3y\xc3\x04p&3\f\x9d\xe5y\x05\x8f\x1e&K\x8c#P\xa2aN\x81\\0\xa71\x81\xc5M~\rNT\x14\xf1_\x05F\x1b,\xecz8\xef\x1f\x1d\xceć\xa1\xb34\xaf\xa2\xab\xa4\xcbj3dd\xc7\xc2K\x87\xf5\xa6a\x0f@\xfbt\xe6\a2`\xd8pO\xd2i\x00\x06:\x00\x90*#B\xd2\xf0_\x95\x00\x90*#B\xd2\x00\x00\xa4\nH\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\xda]6_0N5\x00\x19\x06H\xda]\x9c\x04\xeb\x8cS\r@\x86\x01\x92v\x17'\xc1:\xe3T\x03\x90a\x80\xa4\xdd\xc5I\xb0\xce8\xd5\x00d\x18 iwq\x12\xac3N5\x00\x19\x06H\xda]\x9c\x04\xeb\x8cS\r\x97\x92K\xfbD\xa2K[ۈ\x01$\xed.N\x82uƩ\x86KF\u007f\xe5u\xd2\\\x84\xe6I9\xf3{\x9cb/\x1c\xb56 \t\xefK:8\xf9\xa4Sȥ\xe1\xcc\xe4`\xf2J'\xc1:\xa3\x16\xe4\xfan&&N\ft\x1c%\xffa\x17\x98\x983@W\t\xf7\xf8\xe2\xa0\xd5\x06$ឤ\x19\x03\x9d\xc4\xfe\xad\x81\xad\xf6\xdf\xec\xff\xbb\xe1;\xb3\x9f\xfe\xc26D\xcc\x1ai\x85\xbatd\xb44\xd164\x897\x8a1_\xff\xfe[_:\x05j|2\xab\xf8\x01뿮\x19\xf5\\ҺoK\x84\xeb\xff\xaf\x93pu~v\xa5t=\xb7B-[\xdfM!\x1d9C\x12י\x1f\xe4dߞ\xe2\xf8\xb6[ڦ-\x86%\xe595\xc2=\xbe80\xb5\x01<\xaeI\x9a1\xd0I\x04\x03\x1f\x1e\xd9\x1b\xd8k\x17\xfe\xe4}o\xbd0\xfb3\xbb\b1\xebG5\xe9˻+\xb3l\"\x05|\xf6\x9b\xe2\xb7?z\xff\xf9\xe2ל\x025\xbe\xfc݆;m\xfe\x1c\xbcb\xbdy\xd5+ߖ\x1e\xfc\xc9\xe37KwY(8\x99\x9f\xdcr%\xf7\x99\x16\xc3\ue988`\xf6\x96\xe4\x95;l3N\xb8\xed\xba\x97*\xb3\x1d|\x8d4\xf6Hacq\xb7\xba$\xd8\xe3\x8b\x03S\x1b\xc0㚤\x19\x03\x9d\xfd\x813tŀu\xf4g\xc5o\xa0/\xfea\xfdw+\x8e\x8c^\xcc|Z\x91\xaa\xa4ONUF\xb1\x1f\x14\xff\x11\xebtC\xf1_\xec\xc3\x19^\xb3\x934Z\x9ee\x1e+n~B\xfa)\xd6\xe5\xad\xd2\xcf\xc4\x02\x16\xf0\u007f\x92%\xcd\xef\xa6\bQW;y\x9e`%\xcb\x19i=J\xd8\x1c\x15\x0eC\xc7\xecb\xf2\x1e_\x1c\x98*\x00\x1e\xd7$\xcd\x18\xe8\xa8\xce9M6\x9d\xc6'\xc5\xefY\xffц\xca\xeb\xd832eIwK\xdd\xf4\x9dJ\x1a}~\xf7\x06\xfbp\x06{I\x0f\\WiZ\xa3J\xfa\x97W\xdd*֯\x00\x81\xa4\xf9\xddL\x95IN\x92>$\xa51\\\x17K:y\x8f/\x0e iKܓ4\xd2\rt\xb6*c\xa8\xa0\xd5\xec\xe8\x8b\xef\x14S^FhCq\xf1;\xea\x8cuC\xf1\xac\xb7^~`\xf6\xd3\xffCc>y\xe6;\xb3\xeeS\x97\r\xe2c\xb5ޫ\u007f\xfe\xb8\xab\xbf\xa5\x0e\xbc\x9b&gOxD\xd1\xc0\xa1o匾\xee\xf6~n\xa3\xf5\x13\x82=ROp\xc2K\x9a\xa4ц\xef\xe0\x97/\xdf\xfe\xf1\xdd\x0f\xbc\xfc\x99\xd61\x82\x00\x00\x0f\xfaIDAT9\r1j\xfb\xf2\xad\xc7f?\xfc\x06\x9dl\xff\xcf\xf3\u07fd\xf7\x19e\xe0\xad\xc7\xfeqVq\xf1\xa6O\x9e\xbf\u007f\xf6\xd3\xff\xa4\x1b.\xcf6=`M\x95\xf4\xe6[ǐ\xd7\ao\xbc\xea\xfao\xfc\x92*\xf5g7\x8f\xb9r\xccW\u007fN\x16\xbfw\xc3U7|\x8f\xae\xfc\xf9\u05ee\x19s\xb3:\xf0\xd6b\x91\xb1\x9b-xZ\xbe\x02\xad\xc0\xaf-l\x1d\xe7\xb2%iT3Y\xfa\x814:\xf0Ȅ\xec\xdbq\xcf\x19\x94\x14&\xd1\x10-%\xfb\xaf\x90\xa4\xe5\x87\xe6\x8fϾ}0\x9e\xa3\x04<BJ\x987n\xf4\xb8\xb9\xea\x04\x99\xc9\x19\x93I<\x81\xd6E\xd6͌\x8a\x93\xf6\x18\tkc\x16q\xc0K\x93\xb2'\xe1\xf4#~-K\x18$m\x85\x8b\x92\xd6\rtv5\xd1g`\x06\x04\xd3=\x85?|\xf4N\xf1k\x1f}\xf4W,\x9b\x8ff\xbd\xa6\xceX\xff\xfb\x9dY\xc5\xf7\xbd\xf6\x9b\xbb\x9f!\x11\xffy\xf7c\xbf\xf9\xe05<:\xe7٫\x9d[\x87\xc6N\b\x04o\x93\xa8\xa4+G=\x14\\\x9f3\x89\fE\xc3c'\xad\xe9X!\xad\xe16\xea\x9f/M\x94n\x92\xe6\x1d\xd3%\xfdV1\x1e\xf3\xbfP\xfc\xf2\xfbo\xdc\xf70\xb9D\xc7\xd4\xf6\u009d\x9b\xde\xdft\xe7\xf3x铻\x1fx\xfb\xbd\xa7\x8b\xa9\xa4\xf5\xd8\xcf\xdfy\xe7\xfe\xef\xdf\xfdݗ\x9f\xff\xfa_iٻ\xccg\xa2&\xe9\xefIX\x9d\xb7H\xb7>\xfe\xbd17\xfc\n\u007f\xfe\xc9U7|\xfb\x89\xbb$\xa2\xe4[\xae\xbc\xeb\U0007bbbc\x85\xc8\xfc\xaa\xeb\x1f|\xfc_%*i=\x16\x19\xbb9\x10\x1e\xbb\xfc$:\xb9\xfc\xea0\xdfi\xef\r\x87\xb3\xe8ճ\x9e\xe6+\xa4\x9c\x15k\xc6~\x8bxz\x87'L\r\x87\xc3\xf4\xaa\xa4\x9e\x92XK\xf3W&\x8c\x1d\xf7\xc8|\xe9(\xda\x1fn\x96V\x84\xc3D\xbbA\xa92\xdc2w\xd4\x1e\x12\xcb\xe4\xcc\xc8\xe4\xe0\x89\xf0\xe4\xab\xf5J\xe39\x93w\x1dS\x87\xfaI{,\xae\x8d\xad\x18Uf-\x0f.Ϛ\x8f\xb8\xe60\xf0\xb5\x01<.JZ7\xd0\x19h\n\x9e\x8c\xf5\a\x03-֡\xc6\xc0\xfbNr\xadJ\x19\xde\xdey/\xee'\x9f\xbf\x0f/}~\xffӸK\xfc\xe2\x1d\xf3\xf5\xb3\xa0tDY\x98:\x9e\\\x86\x9b\x94E\xd7\x05\x10\x19\xb8\xe1n+6\xee\xf68yڰ\xd9_o\xdbhi4\x1d2\xa8\x92~\x1fO\xa6\xdf+~\x1b/\xfd\x1e\x0f\x12\xd8\xda\xde/\xfe\x80\x86\xbd\x8fЏ\xbfOV>LZ\xc6\xc4\"\xf4p\xf1\x93\xff@_\xaa\xd7\x01\x8eJ\xa6\xef-M\xd2O\xe0\xc9\xf4\xe3҃x\xe9ߥ\x1f\xe2\x81\xf85\xff\x8a\x85\xfd\xcb\x1f\xbeB\xfe\xf2\xc4f\xf5\xf5\xc6k\xb1\xee\u007fu\x03\x91\xb4\x11\x8b\x98\xddD\x95d,=O0\xd6\xcdV/\x88g]\x8d\xc51?\x87.\xeb\x03o&%x\xadt\x1b>&\xf4\x9a\x98>\xf0\x1eh!\x02\xba\x89\xfc\x0e\xcc\xe4\x8c\xd9l.\xeeΙA\xfa6\xfc\xf1\x9b\xcab\xd2\x1e[֦/n\x93\xc8L\xacC\xb9\xa6\xcd\x04\xe8\x98j\x038ܔ4R\x9f\xe3\x8d\xce\x04q\u007f\xbd;hs\x94Ē~A[|\xbf\xf8\x0f\xc2Ͷ\xaa\xe7\xfa9z\x16\xa1\xe5D\xd2\xf3\xc6\xc7\a1\xe3*ɹ\xb3_\xb0љGF\x8f\x93\xc6e->\xa3K\xfa\xed\xe2\xcf\xd0\xf3\xf7\u007f\xf1O\xccw_\xe0j{A\xf9\xcd\xea\x81\r\xe8\xb3\xe2\xb7\xc8\xd2&\xd2\x1c&\x16K\xfaο\x1ae\x1fUNd\x03M\xd2\x0fJ\xafl\xbe\xf9\xda_\xfe\ns\xcd-\x9b\xb5\xb5\xb4;V~\xb3\xba\xfe\x96ͯ\xd0N{\xf3]D\xd2F,2v\x13w\xa1\xd9\x03h [\xf0@t]\xd2D\xee\xea5\x05]\xd2LJ\xf0Zゖ1\x97>\xf9\xd2\xed\xe3\xc7J7!.g\xccfG\xb7\xe9?Fc\x06rƯߡ6)i\x8f-k\xd3\x17+o\xa2o\x13\xcd\x01:|m\x00\x8fk\x926\ft\xc8[\xecL\x025\xd9xb\x89%\xad/\xbeQ\xfc\xb9p\xb3\xdd\xea\xa8O\x1d\x99\xd2Sy\x92:\x89\xc4]\xcezI\xf4\xe8\xf059\x01<\x97^\x9f\xf3\x9c.\xe9_\xdcM:[\x85\xa7\xb9\xda~\xfc4}{\xfa1\xdc'\u007fD\x96hs\x98X\xfc\xe11\xa6\xec=\x92i'5\xf1~\xe3\xaa͛oP[\xf6Uu\x1c\xaep\xe3W\xe9\xdbWo\xdc\xfcS\xe9'\xba\xa4\x8dXd\xec&\x1e\x92\xe6lE[s\x12(\t]\xd2\xe4\xdd,i&%\xf8\xc3$}#]\xd2{\xae\x1b\xb7xk\xf86\"5&g\xdcfxv\xbbG\xfb\xc3\x1eɰ\nO\xdac\xcb\xda\xf4ũJ\a\xff\xcdɦ\x00\x16\xa66\x80\xc7-I3\x06:\xf8D$K\x87\x02\xfcU*\x0e\x93\xa47\x99$\xfdA\xf1\uf15b\r(SHtF\"\x17[\x10\xbd<6\u007f\xfc^\xcaI2\xb6\xfbP\xb4U\x9c^\xf1&\xf3{E\xd2_\xdc\xf7\f\xe9y\u007fO\xf9\x8c\xab\xed\x85\xfbɕ\xb1/\xef\u007f\x01\xfd\xaf2\x91\u007fA\xe9\xa5\xf5X,\xe9g\x98\xa2W\x8c6\xfdʫ]\xf1\x1es\xf3\xe6\xcd_\xbb\xf6\xa7\x94\x9f\xf3\xbd\xf4\xb5\xf4\xedZ\xbd\x97\xa6\x97njXd\xec&桹h\xeeC(\x19KI\a\x8er)\xc1k\xbf\xa5o\xa4Kz\xe2d\xd2'~\x8bH\x9a\xc9\x19\xb7\x99\xc5\x15\xef\xe4=\xb6\xacM_\xac\x1cO\xdf\xc6W\x9a\x02X\xe0\x8a\xb7%nI\x9a5\xd0\xe9\t\xe0\xa3{\xae\xd9\xee\xde\x01Cҳ\u007f\x815\xf6\x98I\xd2\xff\xb8\xefIr\xd9\xea\xe5\x97\xcd\xdb\xcd\x1b\xaf\xf4X\x93\xc7\xe1a\xf4\xa1,r*w(\x97\x83\x97?G~a\x99J\x84\xfbP\x92\x06\x8e]}\x8c\xbe+\x92\xdeD$\xfc\x8123\xde\xf4\x1b\xae\xb6\xf7\xe9\xdaw\xc8\\\xfa\xb1\xfb\xb1\x82\xff2[\xf9\x86\xd1cyI'&~\x13\xf1\xa8⽋\xbc>Af\xd1x\xf9ۛ7\xbf2\xe6_H7}\xeb7Ȭ\x99\xac\xfd\xa1\xf48\uec2fy\x85\\##\x926bI)\xdan\xe2\x0e;\xab?Kt\xb2\x8b$=u*B'H6\x98\x94p?m\xe9\x92\x1eGt\x95\x98D$\xcd\xe4\x8c\xdb\xccB\xd2\xc9{lY\x1b3\xb5'c\xf5f\xa5r\x8b_\xda@Җ\xb8&i\xc6@\xe7P`ϱ\xfdMA\xebɑr\xc5\xfbw\xf4~\xd0\x1f\xdf\xf7\x9b\xd7\x1e+\x9e\xf5\xf6\u007f\xff\xf5\xa3Y\x1b~\xf7\xe5\x1f6\xcc\"W\xc2\xffs\xf6\x03o\xbd\xff\xb22\x9de94J\xb9\x9aݝ=n\xc5\xf2\x9cQW\x90;[\x16K\xf3Z\x82\x95\x12\xb9\xddjG\xd6ė\xb6=\xa4L\xb4\x05pw\x8fm\xfa\xfa\xf3\xef\xbc\xf7\x02\x15+S\xdb\xf3ś\xde\xdbTL\xaex\xffq\xf6w_\xdbt/i\x19\x13\xfb\xcf\xff\xfa\xe8\xfbO~\xf4\xd1'j\x81k$\xf3o\xef\xf4\xee\xb1'nQ\xee\x1e\xbbK\xfa\xda\x0f\x1f\xbf\x85^\xf8\xfa\xc9U\xd7\u007f\xef\x89[%r\xa3\xe8פ\xbb\x1e\xc7\u007f\xc1K?\xbd\xea\x9ao\xdf5F\xba\xf2\xc1\x9f1\xb1\xa4\x14m7\xb1\x84\xc6\xdd>\xce<\xee\x8e\xef\x0e\x87\xb3*\xc3\xe1s\xa8?<\xbar7\xda[9\x9a^\xc7^\x91\xb5f\xebm\xd9\xe4\xcbKO\xc9\xe0nz\x1d\x9c\u0383\x95+\u07bbIi+\xa4y/=7I\xcaY\xb3\x9b\xcb\x19\x93I2\xb9\xd1G\xd8\xc6D@\xb0\xc7\xe2\xda؊\xd1\xfcQ\x8b\x83\x8bG\xcd7\xad\xe5؛4\x9e\aT\\\x934k\xa0\xf3aK \xf8\xa1`\x02\xa8\xf2\xf9\xbdtf:\xeb/\xe4\xc3'Oξ\xfb\xe9M\xc5\xc5\x1b6\x90U\u007f\xb8\x1b\xbf\x92\x1bA\xfe\xf2\xccw\xef~\xec\xbd\xe4m\x97g)\x87\xfe\xd0ܜ\xf1\x8b\x03WH?\xc0\xcb\x1d\xb7\xe5\\=U\xf9\x11\xfcмqc'oM\xdeL\x81\xde\xe3]|\xbf\xfaE\xf1\xc1\x93߹\xf7\xc7\xef\xd3E\xa3\xb6/\xdexx\xf6\xc3o\xd0/\x9bO\x9e\xbe\xf7\xfe_\xbc=\x8b6G\x8b\xfd#3\xa9&\x17\xaf\x92n\xf2R\xee\xf1\xbeV\xf9\xd9y\xf3\x13\xff2f̍O\xd0ş\xdd|\xcdU7>N\x96~E\u007f\x97\xfe\x15]\xf9\xd51\xd7~\xe3\xc1+\xa5[\x99XZ\x8c\xb6\x9bx\xae\x9b\xc5\xff$\x87\xd93J\x99\xbc\x06\xd0\x0f\xf0\xeb\xe8\xeel\xfcJ\xf2\x10\u007f('{\xaa2%\xd5R\xb2_\t%=k\xfcj\xbax\x05\xf9\x95+\xb1fBVμ\xc0\xf8Ѹ_gs\xc6d\x12\x9d\xb8b\xde\xfe\x13\xf8 \xc6\xfb\xf7\xce\xcb\xd2\xe6P\x82=\x16\xd7\xc6,\xe2\xea\xd6ߔ}\xd3K\t\xd3Z\x0e\xad6 \t\xf7$}\x89xht\x8bSȥ\xa2yt\xa5\xf9\x8e\x89\x8b\xf6\x9fX\x97\xc1nn\x9dH/y͕\xa4\xafh\x17\xcaE{|\x91Pk\x03\x92\xf0\xbc\xa4њq'\x9cB.\rg\xae{.y\xa5\x93`\x9dQ\v\xba\x1cv\xf3\xc4~\xdc;\xf7\u007fxL\xfb,\xdc\xe3\x8b\x06\xad\rH\xc2\xfb\x92\xbe\xbcq\x12\xac3N5\x00\x19\x06H\xda]\x9c\x04\xeb\x8cS\r@\x86\x01\x92v\x17'\xc1:\xe3T\x03\x90a\x80\xa4\xdd\xc5I\xb0\xce8\xd5\x00d\x18 iwq\x12\xac3N5\x00\x19\x06H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\xda+\xc0\r\xcf\x00\x05$\xed\t\xc0N\x06\xd0\x00I{\x01\xb0\x93\x01t\\\x95tw@\xfd\x97\x9d\xfe`\xa0Ý{\xf0\x19g\x19\v\xb7\x18{S\x9c!\x13\xbc:\xf5\a\xe2i\x8d\xac\x94$)\xfb\x90 \x00\xecd\x00\x1d7%}.\xb0K\xf9\xef\xf9c\x81\xf0\xa1p@\xff\a\x9eK\t\xe3,c\xe1\x16\xe3`\x8a3T\x16KN\x06\x19\x06Z#\x8f\x86\xc3/\t\x9f\xe6\x01v2\x80\x8e\x9b\x92\x0ev\x1c\xa3\x92N4\x93\xff\xdf\xdf\xd5\xec\xca\x05\x1e\xbdRk\xb7\x18{\a\x8d!\xb2\\Z\xee\x14b`dF\xfc\x80\x1exl\x0f\xa0㢤\xbb\x9b\x06\xfa\xa9\xa4{\x02䡓\xd4\x1e\xcbE\xac\xddb\x86E\xd2+\xec\xad&\xad\x00I\x03\x0e\xb8'\xe9s\x81CH\x91t\x872\x11\xdc&x\xfc\xf4\xf0b8˰n1,\"S\x1cda\xd7#r\xcd1\x1b\xe8\x18\xacQ<>\x8e\x8eU*\x96Ʋ\xf3\x0e\xc6\xe8\x86i$A,^\xb0\x93\x01tܓ41\xb7S$\xbdUyn\xd6.\xcbg\x80\r\x1b\xba\xb3\f\xeb\x16\xc3 4ű\xb2\xeb\x11\xb9\xe6\x98\rt\f\xd6KԦ5\u07b4^!\x10g\xfe\xc8\x18ݰ\x8dDBI\x83\x9d\f\xc0⚤{\x88\xf7\xac\"\xe9&\xe5\x91v{\xec-\x92\x87\t\xedi\xb8\u0081\xb7\xd8\x14Gl\xd7c\xe5\x9a\xc3\x19\xe8\x18\x04\xd4璞8\xa2`z\xcc\x10kt\xc34R$\xe9\xb9\x12\xd8\xc9\x00\x06nI\x1aϜ\x13\x89\xc4ѦDBw\xae\f_\xfa^\x1a\xd9K\xda\xc2\x14Gl\xd7c\xe5\x9a\xc3\x19\xe8\x184)\xcf\xca=\"i\xf0O\xb6e\x8dn\x1c$\rv2\x00\x8b[\x92>\x12\xd0\xe8G\x1d\x8a\x96\x82\x97|.M\xb0\x93\xb4\x85)\x8eخ\xc7\xca5\x873\xd01\xd8u\xb5\xa2\xcdpP\xc1\xf4+\x14\xfb\b}\aI#\xb0\x93\x01\x18ܒt\xe2$\xa1;p\xf2d\x02\x8f\xc1ɯ\xc1\xe7ܹ\xe2m'i\vS\x1c\xb1]\x8f\x95k\x0eg\xa0\x932\xe9I\x1a\xaex\x03:nIZ\xa1_\xfd]\x9atQ;\xdc\xf9]\xdav.-6\xc5\xe1\xedz\x8e<\xa7\f\x99\xad\\s\xac$m\xbf\xb7 i`\x88\xb8)\xe9D\u007fw\xa0\x9fx;\x1f\r\xec8\x12&~k\x97\x18\xc3Y\x86u\x8ba\x10\x9a\xe2\x98\xecz\xe6J\xb7+\xc1\"\xd7\x1c\x93\x81\x0eCp\xac\xcd%-\xd6\xe8\x86i\xe41r\xf7\xd8\xfap8)S`'\x03\xe8\xb8)\xe9~2\x95\xa6\xbf\xb8\xf6o\v\x04]\xb8\xc7\xdbp\x96a\xddbXD\xa68\x88\xb7\xeb\t\xe4h\x96Z\x02\xd7\x1c\xde@\x87e[\x8e\xcdm٬э\xd1Hz\x8f7!\xc9\xf9\r\xecd\x00\x1d7%\r\\4\xc0N\x06\xd0\x00I{\x04\xb0\x93\x01\x14@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)\\\x95\xb4n\xa0\x83PؕG\x9a\x8c\x14\x86\xc9\xc4\a\xf0\"nJZ7\xd0A\xe8D \x13\x1e\x9e\xb5c\xafS\x84\x05\xc3d\xe2\x03x\x117%\xad\x19\xe8 \xd4ߒ\x11\x92\x9e\x9c\xf4삔\x19\x16\xc7\x0f\xc0\x8b\xb8(i\xdd@\a\x85\x03ጐ\xf4$\x9040\xec\xb8'i\xc3@\a\xc5\x06\xb4\xc7\xf3{\x82\xfdWH\xd2\xf2C\xf3\xc7g\xdf>\x88?5MΞ\xf0\xc8\x00\x1e\x93\xa8O\x19\x9aD\x9eC4\xaa\t\x1d\x19-M\xe4bY\xd7\x1c\x96\xe13\xf1\x01\xbc\x88{\x926\ft\b^\x92t\xac\xa5\xf9+\x13Ǝ{d\xbe\x84\xd5Y9\xea\xa1\xe0\xfa\x9cI\t4\xb0+<aj8L\xae\x03\xf6\x87G\xaf@hwe\x16\x17˹\xe6\x18\f\xa3\x89\x0f\xe0E\\\x934c\xa0C\xf0\x92\xa41\x93\xa4\xdb\xce\xe1\x81\b\xe9\x9b\xc9\xc3\x06\xf7H\xf4\xa9\x89\xc6\xc0\x9b}\xa6\xaf\x1ekr\xcdQ\x19F\x13\x1f\xc0\x8b\xb8%i\xd6@\x87\xe05Ig\xa9\xc3\xe7y\xe3ヘq\x95t\xadX\xd2Z\xac\xc95Ga8M|\x00/▤Y\x03\x1d\x82\xd7$=I[Pg\xd0\xf4\xf1\x9d\x16\x92\xd6bM\xcf\xe3W\x18N\x13\x1f\xc0\x8b\xb8%i\xd6@\x87\xe05Ik\x13\xe2\xf9\xe3\xf7RNҵD\xd2Ԃ\x80\x8awy\x16\x1f+\x94\xb4\x8b&>\xc0\x88\xc4-I+xw.\xad\xf5\xc7\x1dR\vy[\xfe\x1cy\x9d:\x15\xa1\x13tE\xf6b\xfc\xad69\x8b\x8f\x15JzXM|\x00\x0f⦤u\x03\x9dX\u007f\u007f`G\xbf\xc9ay\xe42\xb8\x9b^\xdbVT\xb6X\x9a\xd7\x12\xacT\x9cgWd\xad\xd9z[\xf61\xbc45\xe7\xb9\xe7&KW\x04z\x98X\xd65\x87a\x18M|\x00/⦤u\x03\x9d\xbdʬ\xfa\x9c\xd3\x06#\x84\xfd\x8a\xe5\xcd7\x95O\x1d\xb7\xe5\\=U1ˉ?\x94\x93=\x95\x0eG\x0eM\xcd\x1e{\xfbbI\xfa\x01\x13˺\xe6\xb0\f\x9f\x89\x0f\xe0Eܔ4\x00\x00\x17\x1d\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\x8a\x8c\x96\xf4<)g>X\x02\x00\xde\"\xa3%ݿ#01g\xc0)\n\x00F\x12\xaeJZ3\xd0\x19\b\xb7\x04\x82\xfb\a\x1d\xa2\x87\x85\xb0\xb4\xdf)\x04\x00F\x12nJZ3\xd09\x17\bv\x1f\xd9۴\xd5\rM\xef\x91v;\x85\x00\xc0H\xc2MIk\x06:;Z\xc8\xf3\xc7\xce\x04\x86\xea\x18u!\x80\xa4\x01\x8fᢤu\x03\x9d\xad-\xf4\xf3\x0e\xdd\xc6\xf2\x12\x02\x92\x06<\x86{\x926\ft\xfa\x8f\xd1\x15\xbb\xb6\xd8\xc6\x0f\x0f\xddR\xd8)\x04\x00F\x12\xeeI\x9a7\xd0A(\xd1솸\xe29\x93w\x1dK8E\x01\xc0\x88\xc15I\x9b\ftp'\x1d8c\x1d=|l3\x1e\xfc\a\x00\x1e\xc0-I\x9b\rt\xd0\xee\xc0\x11\xdb\r\x86\x89\x81\x9c\xf1\xebw\xb8R3\x00\f\vnI\xdad\xa03\xb8#\xe0\xcem\\{\xa4\x0e\xa7\x10\x00\x18I\xb8%i\xde@g \xd8\xc4=\x8e\xfe\xd2\x01W\xbc\x01\x8fᖤ\x15Թ\xf4\x99\xe6-\xe7\xb0\xcac\x0e\xd1\xc3\x01H\x1a\xf0\x18nJZ3\xd09\x1ah>\xd2\xdf\u07ff\xab\xc5i\x83a`7H\x1a\xf0\x16nJZ3\xd0٦Ϊ/\xf9\xad&\xf1\xfe\xbd\xf3\xb2\\\x1a\xf1\x03\xc0\xf0ত]g\xae$}\xe5\x92\u007f\x8f\x00\xc0\xb0\x92ђ\xee\xff\xf0\x98S\b\x00\x8c02Z\xd2\x00\xe0=@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)\xfe??\xe8B\x81\x97E\xcd\x14\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/ident-field.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xd2\x00\x00\x00\xde\b\x03\x00\x00\x00\xe6g\xc8\n\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x02\x05\x01\n\x03\x01\x05\b\x03\f\x0e\v\f\x10\x1c\x0e\x11\x14\x10\x12\x0f\r\x15$\x16\x17\x14\x1c\x1b\x15\x1b\x1d\x1a\x1f\x1f\x19\x13#A!# $$\x1d#$\"$%#&'%\x19(G((!'(&+)\x1e\x14+N()'++$*,)/-\"*.0-.,02/63(241685<9-5:=:;9=?=CA5AB@CEBKH<MH7HIG\x00f\x00\x00i\x01JLI\x00j\x02SN=MOL\x05m\x05PRO\fo\t4U\x98XSBTUS\x0fq\v\fr\x177Y\xa3WYV,`\xae7]\xad\x15w\x1c\\^[c^L9a\xab\x19y\x1e_`^;c\xad=d\xae)z!ac`De\xa3?f\xb0)|*Bh\xb3egdghfLi\xafDl\xb0qjSikh/\x82/Ho\xb3/\x859Jq\xb6mol;\x86:Ut\xb4Xv\xb6?\x8a>|u]tvsB\x8c@@\x8dG\\z\xbby{x]~\xb7e|\xb8K\x90J\x85}e_\x80\xba}\u007f|O\x93Nb\x83\xbdN\x95Ud\x85\xbf\x81\x83\x80W\x95Vl\x87\xbc\x90\x86hZ\x98Yo\x89\xbf\x87\x89\x86]\x9c\\\\\x9dds\x8dÕ\x8cn\x8b\x8d\x8az\x8e\xbfe\x9ef\x8d\x8f\x8c|\x90\xc1\x9b\x91s\x90\x92\x8fi\xa2i~\x93\xc4x\x95Ā\x94œ\x94\x91\x9f\x95w{\x98\xc7s\xa4lq\xa5s\x95\x97\x94\x82\x9aė\x99\x96\x83\x9cƙ\x9b\x98u\xaaw\xa6\x9b}\x87\x9f\xc9~\xaay\x9c\x9e\x9b\x89\xa1ˀ\xad|\x9f\xa1\x9e\x8f\xa2ǫ\xa1\x82\xa1\xa3\xa0\xa2\xa4\xa1\x92\xa5ʂ\xb1\x85\xa5\xa7\xa4\x8a\xb2\x87\xb4\xa7\x83\x8b\xb3\x89\x96\xa9Χ\xa9\xa6\x98\xabю\xb6\x8c\xaa\xac\xa9\x9e\xad͍\xb8\x93\xba\xad\x88\xad\xaf\xac\x95\xb9\x95\xa1\xb0Я\xb1\xae\xa3\xb2Ә\xbc\x98\xa5\xb5ճ\xb5\xb2\x9b\xbf\x9bµ\x90\xab\xb7ѵ\xb7\xb4\xa3\xbf\x9d\xa2\xc0\xa4\xad\xb9ӷ\xb9\xb6\xb9\xbb\xb8\xb0\xbc֦Ũ\xbb\xbd\xba\xb3\xbeٽ\xbf\xbc\xa8ǫ\xb7\xbfԯƫ\xbf\xc1\xbd\xce\xc0\x9b\xb9\xc1ֲɮ\xc1ÿ\xbb\xc3\xd8\xc2\xc4\xc1\xbd\xc4ڲ̷\xc4\xc6\xc3\xc0\xc8ݻ\xca\xde\xc7\xc9ƻκ\xd9ɝ\xc6\xca\xd9\xc0\xcc\xda\xc7\xcb\xdb\xca\xccɿҾ\xc9\xcd\xdd\xd7ϡ\xcd\xcf\xcc\xc4\xd0\xde\xc8\xd3\xc1\xcc\xd0\xe0\xcf\xd1\xce\xe1ѥ\xd2\xd2\xdd\xc9\xd7\xcb\xd2\xd4\xd1\xcd\xd6\xde\xcc\xda\xce\xe6֪\xcf\xd8\xe0\xd5\xd8\xd4\xd2\xda\xe2\xd8\xda\xd6\xd8\xd9\xe3\xd5\xdc\xd1\xd3\xdc\xe4\xda\xdc\xd9\xe6ݯ\xd8\xdd\xe0\xd5\xdf\xda\xdc\xde\xdb\xdc\xdd\xe7\xda\xdf\xe2\xd7\xe1\xdc\xe0\xde\xe2\xde\xe0\xdd\xf0\xe0\xb3\xdf\xe1\xde\xdc\xe2\xe4\xde\xe3\xe6\xe1\xe3\xdf\xe3\xe5\xe2\xe1\xe6\xe9\xe8\xe5\xea\xe5\xe7\xe4\xe4\xe9\xeb\xe7\xe9\xe6\xf1\xf3\xf0\xfa\xfc\xf9\xfe\xff\xfcŃ\x89%\x00\x00 \x00IDATx^\xed\x9d\x0fX\x14\u05fd\xf7/\u05fc\xf5m\xea\x9d(o\xb9o/)\x04S\xac\xb6Y\xd9摖p\xcd<f\t\xe8\x8d\x18\xb9\x8a \x1aR\xa4&J\xa3VL\x8c\x18b\x1e5ָ\xc1\x10,i@\xafJ\xb34\x06\xb4\xa4P\xe3\x1fb\xc0\x98\bj0&$/)i\xc0\x98\r\x1a\x93\x9a?\xf8\xc8B\xe0\xb4<\xef9gfg\xce\xcc\xce\xec,\b;\xec\xf2\xfb<\x0f\xbbgg\u007fs\xe6\xec\xd9\xf3\xdd\xf3g\x86\xf9\xfeK\xff\xa0A\x00\x00\x8c8\xfe\xc5H\xb8\xfa\x18e\r\x00\x80\xff\x01I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\x00\x18Zz\x8d\x02\x86\x17\x904\x00\f!\xce\xf4\x89\xdc,\xa3\xa0a%\xd8%]6\xcdi\x14b&\x1d\xd3ʌB\x02\x91Q\\\xebS\xa6\xd8+?4\n\x1aV̓tӾ\xa2\x92cb\xfa\xb4\xdd\xe15\xf6\x9b\x8ds\x13s\xfb\xbc\x86h\xf3\x18\xb7\xc6(d\xa8h]\x95\x94\x92w2\xe5K\xf5\xf6Ol\xfc\"\xadx\x81\xc7Ư\xf3\xd8V\xc4a\xa2f\x1c\xd7\bgh\t\xe5\xa6\xf8\x1a\xeb#$\xb35h\r~,\xf0\x12%\x1c\xd8\x1bC_\xeb\xfbyL\xf2\xaaw\x8c\xe2|D\xabև\x86\x06n\x9fQ\xc8pc\x96\xa4]\x95\xf6\xc3-\xc7\xed\xcd\xf4\xc5\xe5\x82C\xc5^\xa3\x1fJ\xa9\xc8O\xba\xe65D\x93\xcd㋌B\x86\x8a\x13I\xbf\xaa\xa8\xce\xe2\xf9\x0f\xd4o\xf4\x9d\xd9h\xd3\xdaA\xc41a\xb3zӕ\"n]U\xd14\xaeJ+^\xe6pz\x98ϱީ\x12\u007f\x11HfN\xe4|\x8c+\xba\xe2-\x9c\x1e\xd8\v\xc3P\xeb\xd7\xf6\xf3{O\xeeϾ\xf3\xa4Q\xa07N\xbe+%5j}h\xa8\xe5j\x8cB\x86\x1b\xb3$]Y\x80\x87fN{\x13}\xe1\xa8l\xf7*\xe9\xaf\xf8r\xd4\xd7\xe5-B\x9b\x96\xd0e\xde\x03:\xe2:\xbc\a\xf8\xccWɹ=\buexJ\x1a\xa1Ro\x92F+\xc2\xda՛Nӟ\xfa\xb8\xc9\x1a\xd1,k\xc2|\x8f\xf5\xca\xedsĄ\x90Y\x15w\xda[\xb4x`]\x86\xa5\xd6[\xf9\x13\xf8\xd71'\xc3(\xce\x1b\xd9k\xe5\xb4F\xad\x0f\t\xb5\xdca\xa3\x90\xe1\xc6$I;\xedo\x92'\xa138]\xe4rz\x95\xf4y\xfe\x88\xb7\xb7uI\x9f\xd8\xe9=\xe0\xb4Q\xe3\xf5\x99¤\xcf\xc8S9\xff\x91\xe7{\xde%\xdd91]\xbdIP\xd6fΠ\xf4\x8c\xa4\rc\xbd\x123\xa4\x92\x1e\x96Z\xa7\x92\xc6\xd5;\x88\x1fv\x89,F\xd2\x1a\xb5>$\x8c^I\x1f.\xe8\x96\xd2W\n\x9a\x91\x17I\xf7\xcc\xe5)O#\xb4\x85\xe7\xabŹ\xe9\x16\xdeV\xf1tFҪ\x8b4\xe6\xfcڹ\xb6\x94܋\xaa=]\x11Rw\xd1<'*t\xe2\f\xe5\x9a\xcd\xe6Ɏ&\xae\xc91\xf9)\x9cn\\\x95f\x9b\x9b\x9bF\xa6\xeb}\u007f\xcaN\xcax\x1a7\x9d\xf7m<\xbf\xe3|~Z\xe2\xaao\xab\xf1\xf1KQ)O\x8e\xaf\x19\x8026\xd1<\xbf(\xc7}u_EvRV\x05\x9d\xfa_\xccKM^+\f\xbc\xa5ݐ\xaa\xbc+\xc2]H\x89\xa0\xacy\xd1\xf4E\xf1\xb4\xf0\xc9K\x88H\xae̙\x18\x1a}w\x03\xdd\xe8\x9c71rN\xba,iu,\xea\\6%\"\xeep\xf4>\x94ɍ/\x96\xa7\xbfr@͌\xe8Ш\x19x7\a'\x10\x83T\x9268\xb0\x1c\xd00\x81\xe3V4ϛ\x14>\x83|\xa9\xeeZWn\x95\x90k\x9d\xa9>\xfcm\x96oJM\xce=OC\xb4\xbeMA\xd2y\xa9$\xcd\xd4dWᢤ\x9c3\xa9ul\xd3P\x04H_\xec\x11\xa1\x15\xf1\xd9b\x86\x9e\xb5\xae\xf9\x81\x94\x9f⩘\xf0\x18\xd2\\t>\x1b\"u7Z%]\xe6h\xdae/>Dk\xd5Q\x89\xbcI\x1a}\xd0X͗66\xe2^\xf0b\xa3\xadT\x9c\x9b\xb6V\xdb\xf8\x94\xd2?$璈\x93I\xd9{O\x94\xe2ѹ\x92\xe3\xd2\f\xb3*\"\xe6\xb1\xca5\xdc\x06\xc5\xdb\xcey\xdc\x14\xee6n\x0e\x1e\x81\xbdsg\xfe+'*\xe6\xf2\xdf\xe2͛\xf8mu\xe5)Y}\xa8\xa7\xba:-\xe3\x9eԧ\xf3\xee\xfc\xb4\xab1\xf9\xb9/ї\xcf%7vi\a\xf4\xb0\aϷ\xed\xa8\xdba\xcbǩ\xf3\xc9\x19\xfb\x8f\xac⩤\xa5\xdd\xd4\xe5=\xe4\xd1\nNs\x0eW\xd32\x8e.ᤏ\xcftl\x8e\x8a\xe9%\xdaK\xaf*\xb9{|-\xde\xd8\x1c1\xb9\xa8l:\x17\xa6\x1b{yR\xd4c\x8eL\x8e{\n9kB\xd7H\xd3_9\xa0\x96\x9b\xb7\xab\xd2\x1e\xc5u\xa3\xceC5\x93\xe3jjj\x9a\xc4\xcc\\\xae}T\xd2F\a\x96\x03\\%\xc5ѓ#\xa2\x97\xcc\xe3\xc8R\xaf\xbb֕[%\xe4Zg\xaa\x8f|\x9bi\xa5\xa5iI\xadH\xe7\xdbl\xe5\xeb\xba>*Ŀ\xab\x88\xad\xc9ki\xc9\xe5uX\xcd\x15l\xd3`\x03\xe4/\xb6\xebLcFNcc\xa3{\x14\xe5Y\xeb\x9a\x1fH\xf1)\xd2\xc3V8V\x84\xcd\xd3\xfdl\xddΪ\xdb#\xafg\xb84$\x98$\xe9\x12{qC{Sq\t\xd6tSQ\xa7wI\xb3\x03o\x1b\xf9N\x85\x81\xac-\x19\xff\x8e\xe7\xa7\xe0TO\xda*\xdc7\xf6T\u007f\xa5\xda\xcd\xc1\xb5\b\tW\xf4\f\x17\xf9\x1e\xd4S\xb8}\xa1\\(]\xa0\xacH!b.Oƍ\xe0U~?N\x9e#\xdd1\x1e\xaa\xf1\x0f]C}d]nS\x1e~\xc8#]\xb1f\xc0'\xccԠ\x8ev('\xf8:\x84r2\xf0O@_\x96M\xb9\x9b\xaa\xbc\xed\xdc.\xa4\xe44\xed6瑤\x83#KM\xb5\xdc\xf3\xa4\xfc\xa4\xb5\xdcFNz\xc6M\xc2\xc9ޘ0\xdd\xd8y\x91dD\xb2\x84#]J\x18Y~\xa6ce&\xe0\xa9(ҿl\x8e\xa4\xc7c\x06\xde\x02\xa7}80\x13\x80s\xe0\xa6_\x11\xe7QR\xad+\xb62H\xb5\xce֯-\xed\x1aQh\xb6\u07b7\xd9J\xbb\xd8|\xf2\x83\xc8\xd4d>i\x03h\x1b\x964\xdb4\x98\x00\xe6\x8bU\x0e\xbc5j]\xef\x03I\xc9}t\f#<j~\xb6Y\xb8꼟\xba\xf1\a&I\xdaQ@*\xa3\xb3\xa8\x16u\x164\xf5\xf6\xf6~X\xec\xed\x92\x1bmI结uZkR\x982w\xe3rpoj\xbcݱ$4\x9a\x9b\x18\xb6\x04\v\xfd\xd3Դm\x15\x1f\xf4ᦄ\xf2\xd2z\xbeŤҁt\x96\xedS1\xf8db\x17\xeaJ:\xa9\x17\xd0c\x93;\x95M\xc29\xabE\x1b\xd15\xda\xd6\xd0\x0e\x9br7UyۅF\xc4p\x9a\xdbp\xd81-\x9c\x94\xfe\xdeI\xaenL4\x99\xf9u<5cR\x04w\x1b\xee\x839;\t[\x11\xa6\x1b\x1bN\xcf\"5\xa9$\xcd\x04\xb4O\x9c\x94i\u007f\x13\t\x83OF\xd2\x1bjkk7\x10I\x1b\x1e\x98\r@1aRwU\xc6H:LщQ\x98Zg\xeb\xd7VH\x1e\xcb\xf9\xaft\xbe\xcdV\xfe\x0f\xe7^\xcdN\xfc\x04\xb15ٗT*\xbc\xa7\x944S\xd5\xcc\x17\xeb!iu\xad\xeb} )\x99~\x1b}\x9a\xa2\x0e\x90\xf8p\x9f}ʨ\xed\xa5\xab\x84\x9fȪ2\xd4bw\xa3\u007fu\x82\xb6\xa4\xa5d9ߣ\xb9\xdba\xf7\xd8j3\xe79oB\xe8\xb1(;\x9e\xd5m\x8e\"c\xd6k\x15k3\xf8\xb9{\xfbH\xc7!@G\xf4Y\xee\x99\x17\xfa6\xf9\b:2\x97\xfc\xd8k\a\x88s\xe9\x1e\xdcA?H\xdfA\xb9ٸ\xa3h$)ZHf7Uyk\xb9CH\t\x9d\xd2^\x1eO\xe4\x13#\xf6\x9b\xb8\x8b\xac\x9d\x18\xbdlW\xcdtܮ\x8e\tgJ\xe4\xe51u\xac\xd8\x05]QI\x9a\xc9\f]\xb6ϙ\xc2E=F\x8f\xa7\xb5<fx`63\x14s\xbbT\xf8\xc3\xf2\x88\x96\xd9*\xc1\xd6:S\xbf\xf4\xdbD\x8d\xfc\xbb:\xdf&\x9dK\v?\x91rM^\x14\xdaE\x97J\xd2\xec7$\u007f\xb1*I{ֺ\xde\a\x92\x92\xd3\xee\xa6O3\xa6\xa9\x02Xj\xb8Z\xcd\xed~\xc4$I\x1f/\xa2\xbdr%\x1e\xa6t81\xa7\x8b\x9c\xfa\x8aVKz\x87J\xd2'\xf8\xf75w\xeb\f\x13\xafx\xa8\xe44/\xc5pѵW\xa2\xf6s\x85dbV\x9dXA~\xe2ߥ|A\"\x98F\xb0-\x17\xe5n#\t\xed\x80\xc2D\xfa\xba\x9a\xff\x12m\x12V\xd9\xd2\xf2\xd17B/\x9doS\xee\xa6*\xef\x9aP\xf5\xd0TPV\x04)\xfd\xbcI\xc7)\xb8S\x9b2\x8d\x14u\x0eVV\a\x95*b\x96\xc7T\xb1\xbdB/}Z\x964\xedX\x99̎\x915\xac+χӌ\xa8\xa4\v>TH\xda\xf0\xc0L\x00\xf3\xa3\xc0Ժb\xab\x8c\\\xebl\xfd\xdah\xddV\xf0\xd7t\xbeMay,\x99|\xe7rM\x8a\xbd\xf4\a\xb2\xa4w\xa8\xaa\x9a\xf9bţ\xed\x17\xc7\x05\x9e\xb5\xae\xf7\x81\xa4d\xfa$\xfa4)]\x15\xc02zW\xbc;\xe8I\xac+\x05\xee\xcb\xc7|\x9dK'\xe1\xf1Y߯T\x92\xeeJ\xc9!?\xec۶\xa9\xf7\x9b3Y\x18\xcewN\x8c#M(s\x89:\xa0=R8;YJ&\xbex껑\xe8\x8dN\x92\v\xf7\x92GF\xd2o%~\x96\xf8\x16Ih\a\b\xe7\xa5\xfbr\xd2ȸ\x9a\x04T\x93,\xb3\xd3\xf0\x8c\xf0\xa3D\x9br7ey{\xa7\xcc@*\x04eM\\Ұ\x06\xcf\xdcJȖ\x15\xb8S\x8b&\x8d\xa87\x86\x8c\xfe\xa6E\xe3v\xd7\xfc\x830\xdd\xd89Q\xa4aΣ\n\f\xc7\xea\xed\xbd\x9d\xc42\x01k\x84\x19a\\&}\x8c\xc3\xdf\x00y\x8f\x91\xb4ၙ\x00e\x03w\u05fan\xb3w\u05faB\xd2s\xbbpŤ\xe5\xa8k\xa7e\x9d0\x8c\x17$\x9d\xb2\xad\xb5\x94\xadɵs\xb1l\xfb\xf2\xa9\xa4\xe5\xa6\xc1\x040_,~Ĺ\u007f)\xbc\xa7U\xebz\x1fHJ:\xe8X\xfdya\xba\f\x92Vs\xac\xe0X\xfb\xe9\xe2]\xdd\xf4E/\xe9\xa5u/?\x10V\xbc\xcfбӃ){K\xb3y\xdb\xfe\xd6\xcf\x1am\x1b\xcf\xf4\xbd\xb3\xd1FV\xc2O&.\xaa\xa8\x13\x16I\x144\x8f\x17\u05f8\xab~0\xe5)G\xa6\xfee\x8e\xa5|R\xe9\xabG6\xf1d\xae\\xg\xde+8Y\x8d\xbe}\x8b\xae\x91~\"\x84\xf4\xa5\xaeJ\x15.I\xd5\x0e\xa8Kzp\xff\x91U\xb638\x99\xc7\x17\xbeZȓ\xf5\xb4֤\xd4\xd2\x1dɤ\xbc\xccn\xaa\xf2n\xf0\x1cB\bW\x15N\x9fA&o˸{K\xcaҹb\xa2\xc29O\xad\x8b\xc1\x83\xe5\xc3\xe8tx\xf4\x9a\x15\x91\xe3'\x145\xe9\xc4:'F?\xb5kV\x18\x95\xf4\xb4\xa8u\xeb\xa6q$V\x91Y\xc4\x1aǮtauzM؆\xb2\xe9\xe1\xedʫnj\x0e,\at\x1f\xa6k\xe6\xee)\xb4X몭\x9e(\xaa\xcf\xc6gWWd$\x93\xf5hE\xed\xcc\xe2\x04\xe9\xb5Rm\xe6\xe4n\xccbk\U000b3534\x8aWr\x13i\xac\xd44\xd8\x00\xf6\x8bſ\xff\xe5G\x1eJ\x12zi\x8dZ\xd7\xfc@\x8aO1o\xfc2Dz\xf1\xf3\xbc}\xb6c\x1e\xe3y\xbfc\x96\xa4QsYѮc\x82\xa2\x91\x93L\xa5\xf5\xfa\xe9\x9ed:1\xb2ѳ\x0f\xe7s\x12\xefY\xb5\x83\xe7\xb7l!\x9b>H\u008f[\xf0\xe6\x8f֦ޓ-\xaf9K\xac\xf8\x81X\xc1\xcds\xa2#\xa6\xa9\x978e\xfe\x94S\x9afK\xc9\x11.7<\x91379\a7\xa0\xf7\x9993\xa6\\Z\x01\xd3\x0eh]\x9547\x97\xae\xec\xf4\x95g%e\x95S\xfd\x9f\xcfMN+\xdco\xa3\x85t\xef\x86\x14\xe5\xad\t\xf7\x18;\x94\xe0\t\x1d\x9e\xe46L\x8e\"\xfd\xc1\xbe\xe9Q\x91qD\xb6\xbd\x1b&\x87E\xdd[49\x14\xf7\xa9\xcdwGNZR4\x81\xcbԉE\x1d\xe9\xd1\xe1ӏQI7DžG\xccX\xc6q\x99l@qܚ\xe8Љq\xe2\xf9\xa6\xcc\xc8\xf0\xb8Z\xf6\x1ao\xbbၙ\x80\x86\xf1t\x0e*u{B\xad\xab\xb7z\xa0\xa8>\xdbӛ\x92S\xf3\xe9\xe5:\x8ao\xb3(\x8a.ȑ\v\x03p\xa7ۚ1\xf7U\xc4\xd6\xe4\x17\x9b\xd2\x12\x1f:G%-5\r6@\xf1\xc5\xf6lKN\xcc9G\x93\x1a\xb5\x8e4?\x90\xf2Sl\xbe-\xfc\xb6\xcd\x1e[Y\x9c\x13\xe648\xcd\xfd\xefJ\xd3$\xed\x1f\x96\x84\x96\x18\x85\x98\xcb\xf3\xa1\xe9\xddF1\x83\xa6S\x98\xfa\xfa\x9dAԺ\xb0<68\xba<\xc7g\x06\fc\xad\x97M\xe1\xe0\x9f+\x87\x95\r\xd1^\x96\xdḑc\xe2:\xa3\x90\xeb\xc0,I\x0f\xa2\xd6\xfd*\xe9\xe1\xadug\xc3@?\xfc\xd0\x12\xec\x92\x1e\u0558&\xe9\x81\xe3WI\a7 \xe9\xe0\xa5y\x1f\xb7\xc4\xf4\xf5W\x9f\xb8H\x17;\x8d\xa2t8_\xc7?\xfd\xd6`w\x0eB@\xd2\xc1K\x1c\xc7q\x13\x9a\x8d\xa2F\x02t\xb1\xf3\x13\xa3(\x1dr\xc8\xce獢F\x0f i\x00\b*@\xd2\x00\x10T\x80\xa4\x01 \xa8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\xb38\x92\xfd\xe5\xf0Z\xb9\x00\xa3\x13\xf3$\xed6\xd0q\x15\xd1\xdb\x14\x15i\xddK(\x88\xd9˗\x92\x8b\x18\x87\xcf\xca\x05\x18\xa5\x98%i\xd9@\xe7\xb2\xfdMr\xab\"s\xff{\xc5\x1f0\xfe-\xe4\xfec\u007f\x12\x12\xc3f\xe5\x02\x8cR̒\xb4l\xa0s\xd9n\xaeџ\xdf`\xfd[\xce\vw\xc4$\f\x97\x95\v0J1IҌ\x81Ψ\x914{\x83\xcaM)]\xee\xe4pY\xb9\x00\xa3\x14\x93$\xcd\x18\xe8\x98(i\r\xa7\x16\xd6\x14GөŇX-7\x1e\xa5\u007fK\xcf=R'\xadm\xe5\x02\x00\x83\xc5$I3\x06:\x97\xed\x958YcB\xb3\xd6rja\\]\xb4\x9dZ\x8cc5\xddx\x94\xfe-\xef\b7\xf8\x16аr\x01\x80Ac\x92\xa4\x19\x03\x9d+4Y\xf2\xbc\xdf5\xad\xe7\xbb#\xb9\xba\xe88\xb5\x18\xc5\xea\xba\xf1\xc8\x03\xef:\xd6\xe0\xd2\xd3\xca\x05\x00\x06\x8fI\x92\x96\rt\x10:M\xc4\xec*\xf2{W\xa5\xe7\xbb#\xb9\xba\xe88\xb5\x18\xc4\xea\xbb\xf1Ȓ>\xc23\xff\xef\xefi\xe5\x02\x00\x83\xc7$I\xcb\x06:nj\xfc\xdeU\xe9\xf9\xeeH\xae.:N-\x06\xb1\xfan<\xb2\xa4\xcf\xf0g\xe4<<\xad\\\x00`\xf0\x98$i\xc6@\xa7\x92\x9a\x17\xa0*\x87\xd7\x1d\x86\x01=\xdf\x1dIz:N-\x06\xb1\xde\xddx\x04\xff\x96.\xf6\xeey\x9eV.\x000xL\x924c\xa0\xe3\xa0\xddsG\x91\x96\xb9䰢\xed\xd4\xc2\xc8Tǩ\xc5(Vύ\x87\xf5oY\x9b!\xdd\xffN\xc3\xca\x05\x00\x06\x8fI\x92f\ft\xda\xed\xfb\x9a?<V\xe0\xf7NZ۩E\xe1\xea\xa2\xed\xd4b\x14\xab\xe9ƃ\x94\xfe-\x1f\xf1\u007fp\x97B\xcb\xca\x05\x00\x06\x8dY\x92f\ft\x9c\x95\xc5E\x8e\xd3F\xf1Á\x86S\x8b\xd2\x14Gө\xc5(VӍ\a)\xfc[\x10z.Q\x9cMk[\xb9\x00\xc0`1Mҁ\xc8\x10\xde\x03\xbeo\x9b\x8dv\xdd\xc3h\xe5\x02\x8cN@\xd2\x03`\b%\x8d\xfa\xcaS\xbf\x18n+\x17`4\x02\x92\x1e\x00C)i\x00\x18\x1e@Ҿ\x03N-@\x00\x00\x92\xf6\x1dpj\x01\x02\x00\x904\x00\x04\x15 i\x00\b*@\xd2\x00\x10T\x80\xa4\x01 \xa8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x04)\xbdF\x01A\nH\x1a\bF\x9c\xe9\x13\xb9YFA\xc1\tHz\xd4A\x9d{\xae\x9f\x91\xed\xfd3e\x8a\xbdҴ;Ϛ\x8by\x92v\x1b\xe8(\x93\xfe\xa52J\xfa7\xed\x8ę\xf0\x19\xa6\x8c\xd5>\xb1\xf1\x8b\x8cb\x10\xb9\xaf\x12\xe6Ό\n\x9f\xafH\xd5\xc9Wt\xee\xe9\x98\x1e\xf9\x98ƻ\x03`\x88\xbd\u007f\x1c\x91\xbe\xff˼\xfb{K\xe78.\xbcY#\xa0\x81ۧ\xb1ut`\x96\xa4e\x03\x1d6\xe9o\x1c\xe1\xd2\x1dϦO|*=\xfc\xb2\xb7\xe0\xe1\xa2\xef\xccF\x9bQ\f櫽\xfc\xfeƺ<\xfe9\xa3@7\xda\xf9\xba\x9d{\x96Lzl\xfcu\x9a\x16\r\xad\xf7\xcf2n\x99Q\x88\x84\xfb{k\xaf\xa9٬y\xcb\xe4Z\xaeFc\xeb\xe8\xc0,I\xcb\x06:l\xd2<:8\xdc<;\x8d\xa2\x86\x89R_$\x8dN\xf0\xadX\xa7[\xd8\xfb\x05\x1b\xa0\x91\xaf\xe4\xdcs\xfb:\x14~\xbd\xcd~H\xbd\u007fVp+\x8cB\xb4\xa8Ց\xb4\xdfo8;b0IҌ\x81\x0e\x934\x91f\xce\xf7aߐ3\x00I\xa3\x9e\xe4-F\x81\x12\x1a\xf9J\xce=\xb7\x15\xb5s\xd7;0\x1aR\xef\x9f5\xdc\x1a\xa3\x10-@\xd2jL\x924c\xa0\xc3$\xfd\xcb\xe5p\x8e\x1b_LR\xae(\x8e\xe2qˠ\xe2iᓗྻa\x02ǭh\x9e7)|F7\x93T\x05\x8b\xb7/j\x8f\x102\xe3\"T]\x98\x86]\x0fB\x17\xf3R\x93\xd7\n\x03dƂG3V\x904\xda2W7\xb6\xaf\";)K\x98l\xeb\xe4+;\xf7\xccX1\xeb6\xfcY&4i\x1f\xcd7#!\xd9\xfbG\xfc\xf0\n\xa4ݘ\xcc\x14\xf9*x\x8c\xa3s{\xed\xea\xcb\xe4B\xedK&\x87\xcf \xdb\xe4\uf360-\xde*\x90\xf4`0\xca\xda\x1b\x8c\x81\x0e\x93\xf43\xc7jj\u0084\x9e\xe1͚\xe7\xb9555\xea\xb9e\xfa\xf8L\xc7樘^\xe4*)\x8e\x9e\x1c\x11\xbdd\x1e\xf7!\x93TE\x8b7\x19t\x15m\x16P9fk\xd9\xf5\xa0\xf3\xc9\x19\xfb\x8f\xac\xe2\xa9\xf4d\v\x1e\xedXQ\xd2\x15|\x97^l\xbemG\xdd\x0e[\xbe~\xbe\x8csϚ\x88\xb0c\xdd3\xe2\x0e\xeb\x1c\xcd7#!\xd9\xfbG\xfc\xf0\n\xa4ݘ\xcc\x14\xf9*\xd8\xccљ\xb9v\xf55\x15O\xe0\xa2\xd6l\x88\xa0\xe7\xa5\xe4\xef\riJ\xba\xdbYu{\xa4Y\x93(\xf31IҌ\x81\x0e\x93\xf4?\xe1\ue9a15\xf0vpE\x88\xb4\x19j\x86\x11\xc3M\xbf\"N\x0f\x98$\x8b\xfbV\xc0\xce\x16\x01\xe5\x0f\x84\xb6]ON\x06\xd6g_\x16\x91\x1ec\xb6\xa3\x1d+J\x9a\x98\xefh\xc7\xd6\xf1'hX\x9d^\xbe\xacs\xcf:Ύ\xae\x84\x93\x0f}\x1dFB\xb2\xf7\x8f|\x1fd\t\xa5{\x90;3E\x92\xc5\xce\t\xfd\xbcv\xf5\xa1\xb0H\xdcCϋ\x12_\x85{\x93\xf4,\xdcǛ8\x8d2\x1b\x93$\xcd\x18\xe8\xb0^:~ǫ\xa4\xef\x9d\xe4\xea\xc6D\xd3\tcL\x98\xd4+3I\rZ87\x8aF\xaei\xd7sM\xd0\xc6\x0e\"=\xc6lG\xdb\xdaG\x94\xf4~\xfe+\x9d\xd8M\xc29\xabE\x1b\xf5\xf2e\x9c{J\xb8\xc8%h\xc3D2y\xb8\x0e#!\xaf\xde?J\xf7 \x9b\xd4+3I\x96\"\xfa\x03\xaaW}(\x8c|\vk\xc2\xc4W^%\xfd\xe1>\xfb\x14\xe8\xa5\a\x83Q\xd6\xde`\ft<\xbdt\xfc\x88WILjm\x8b\x8e\xf6bn\x97\xb7\xcbI-j\x1c\x02\xca\xf5dM\xbb\x9es\xc28\x98.c1f;\xda\xd6>\xa2\xa4\v\x93\xf5b\x1f\x14n?\x9c\x9b\xad\x97\xaf\xec\xdc\xe3\f_R\xf5\x83\x96I\xf4\xd3_\x87\x91\x90W\xef\x1f\xa5{\x90;3E\x92\xe5P\xa4\xa0M\xed\xeaCt\xa8훤15\x9c)=Ĉ\xc0$I3\x06:L\xd2\xffx\x95\xf4\xbcI\xc7)\x1d\xe4E\xcc\x1ci;\x93\xf4\x1dM\xbb\x9eo\x04m\xe4\v\xbd\xa9d\xb6\xa3m\xed#\xaex\xa7\xacՋ\xdd$XZ\xa7\xe5\xeb\xe5+;\xf7\x94\xe1>p֤\x88\xcbB\xbe\x836\x12\xf2\xea\xfd\xe3\xe9\x1e$\xc0$\a\xc0\xc0$\r+ރ\xc2(ko0\x06:L\xd2\xffx\x95\xf4>\xae\x84<\xad\xa0\x17I\x19KZc:ɠmד\x9d\x86g\xb0\x1f%\x12\xe91f;ڱ\x82\xa4\v\x89\x00\xb5c\xeb\xe8\xd6j2\x97\xd6\xce\x17I\xce=\xbb\xb8f\xf4&w/\xea\x8dn\xb9\x0e#!\xc6\xfb\xa7e\x8d\xc7\x191ŁA\xd2~\xc3$I3\x06:lү\xb8\x0e\xd7Ԅ\xa5\xd7\xd4\\q\xafx{\xb4\x82eܽ%e\xe9\\1\xea>\\39\xae\xa6\x864v&\xa9BkїAˮ\a\xb5&\xa5\x96\xeeH\xe6m\xfb[\x15f;Z\xb1\xc2\xd5c\xf9<\xed'\xb5c\xf3\xf8\xc2W\v\xf9<\xfd|%\xe7\x1eg\xf8\x9c]ѓC3ׅ:\xaf\xc3H\x88\xf1\xfe\x99\xc5\xc5!5\xd2nLf\x8a|\x158\"\xbc\x8cӜ5\xa1\xe9\x87\xd1\xf1\xf4\xd0\x1a'\xfb\xbdѫ\xc76\xd7\xd4x\xacm\x1c\x1b\xc5n\xa0fI\x9a1\xd0a\x93\xfe\xa4v\xbc0U\xb6#W$ML\xf0\xb8\x80m\xdf\xf4\xa8ȸ}\b5\b\xa1\xa4\xb13I\x15Z\xa7fY4\xecz\x10:\x9f\x9b\x9cV\xb8\xdfƓ\xebG\x18\xb3\x1d\x8dXz\x8d7\x9f&\x0ey5c\xfbʳ\x92\xb2\xca\xfb\xbc\xe4+9\xf7TN\x8e\xca쬜\x1c\xf9\x94\xce\xd1|1\x12b\xbd\u007f6\x87E!\x0fܻ1\x99)\xf3e\xd9\x17\xe5\xe5\xb2\xecL\\塧\xc3\xf1c&\xf3\xbd\xd1k\xbc\t\x1e\xc3&\xe7\x849\rNS\xae\xd87\x1f\xd3$\r\x98\x83۹\xe7z\x10\x96ǔ\xde?\xb3\xa6\xebE\x9bB\xd9\x14\x0e\xfe\xb9r\xc0\x18e\r\x8cH\x04\xe7\x9e\xeb\x82JZ\xe9\xfd\xb3nĝ\tv6\xa8\xaf\x1c\x1a%\x80\xa4\x81\x01\xe3i$\xd4\x1e\xb5Y3\x12\xf0? i`\xa0\x80\x91Ј\x06$\r\f\x140\x12\x1aр\xa4\x01 \xa8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\x00\b*@\xd2\x00\x10T\x80\xa4\x01 \xa80OҢkNw\xb1]\xa0\x18\x01\x00pݘ%i\xc95\xc7e?\xee\xc4\x1c\xb37\x18\xed\x12\xe8T\x1dG\x000\xec\x98%i\xd95\xe74\xb9ۯ\xab8\xf8\xefBq\xfb`nY\x06\x00\x03\xc4$I\xab]s\x1c\xfe\xbfO\x91\xdf\x19\xd4]\b\x01`\x80\x98$i\x95kN\x93=x\xfe]]\xe9\xb0\xe3\xb6\xe0q\x88\xb7ԉ!7\xdd\x19_\x8cZB\xb9)\x8aX\xd6\"\x86e`.4\x00`\x92\xa4U\xae9%\x95^\xa3\x03\n\x85Îd\xc1\xd3y\x88ޅ\xb0\xa6\x89\xde\x1ao\r\xfeQK\x0fS\xc4*,b\x18\x06\xe6B\x03\x00&IZ\xe9\x9a\xd3b\x1fBS\xd3\x11\x80䰣\xb4\xe0\x91\x06\xde\xec\rle7\x1e\xa5E\x8c\xc8\x00]h\x00\xc0$I+]s*K\xbcG\a\x1a\x92Î҂G[Ғ\x1b\x8f\xd2\"Fd\x80.4\x00`\x92\xa4\x95\xae9E\xa6ܖ\u007f\xf8\x90\x1cvb\xc4\x19\xb4`\xc1\xa3-iɍGy\xf3y\x91\x01\xba\xd0\x00\x80I\x92V\xb8\xe6tؽ\xd9T\x04 \x92x=-x\nH\x9fLŻ\"L\x19\xab-\xe9\xa1u\xa1\x01F\x01&IZ\xe1\x9a\xd3b\xbfl\x10\x1e`H2UX\xf0\xc4\xc5!\xe4\xa4\x1b\u0097!\xd4{\xbbO\x92\x1eZ\x17\x1a`\x14`\x92\xa4\x15\xae9Mv\xf7\xcaw0\xa0pؑ,x\x10Q놲\xe9\xe1d!pZԺuӸ\tEML,k\x11\xc320\x17\x1a\x000KҬkN\x8b\xdbw<(P:\xec\xb8-x0\xae\xcc\xc8\xf08\xba\x1e\xd8\x1c\x17\x1e1c\x19\xc7e2\xb1\xacE\x8c\x82\x01\xb9\xd0\x00\x80i\x92\x06\x00`8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\x00\b*@\xd2\x00\x10T\x80\xa4\x01 \xa8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\xc5(\x96\xf4\x1c.j^\x93Q\x10\x00\x04\x18\xa3X\xd2Ϊ\xa2)Q\x9dFQ\x00\x10X\x98'i\xd1@\a\xa1\xceC\xbb\nv\x1d2E[U\\\xd0{|\x00\xa3\r\xb3$-\x19\xe8\xa0\xcbŻ\x9aڛv\x15\x9bqg\x93Z\xee\xb0Q\b\x00\x04\x16fIZ6Щ)!7B\xe8.\xa91\xdae\x18\x00I\x03A\x87I\x92f\ft*\x85\xbb\x84\x96\x99qw~\x904\x10t\x98$i\xc6@\xa7\xa3\xb8\xaa\xc3\xd5QS\xdc\xe1-~\x98hઌB\x00 \xb00IҬ\x81\x0e\x9eV\xdb\xed\xfbL\xb9\xa3\xa0+jڡ\xf6^\xa3(\x00\b L\x924c\xa0\xe3\xaa,ir6\x95T\x9ab]\xb9\x8f㸻\x8d\x82\x00 \x800IҌ\x81N\r5\xc6r\x95\x98a0\xdd\x195isU\x90\xf9\x02\x00\xa3\x1c\x93$\xcd\x18\xe8\x14Ѕ2\xf4f\x81\xb7\xf8a\xa2\x963cQ\x0e\x00\x86\x11\x93$\xcd\x18舒>n\x8e\xa4a\xc5\x1b\b2L\x924c\xa0S%\x0e\xbc\xcdX{\x06I\x03A\x87I\x92f\ft\\ϗ\x9cn?]\xf2\xbc\x19KއA\xd2@\xb0a\x96\xa4\x19\x03\x1dW\xed\xae\xa2]\xb5\xfeW\xb4\xcby|N\x98Ҁ\n\x00\x02\x1e\xd3$m>\xb38.\xba\xcc(\b\x00\x02\x8cQ,i\xe7\xf1v\xa3\x10\x00\b8F\xb1\xa4\x01 \x18\x01I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\x00\b*@\xd2\x00\x10T\x80\xa4\x01 \xa8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x85y\x92\x96\ftz\x1b\xca\nv\x8d\x1c\xbf\xb9\xd6\xdc\xe4䜓Yg\x8c\xe2\x04N\xa4\x1c\xd1\u007f\xb3\x94\xb7\x91w\xeb\x92\xf8R\xed\x80-<_\xad\xfd\x0e\xfa\xc4\xc6/\xd2ykh\t\x88B\x02\xbec\x96\xa4e\x03\x1d\xe4(:\xder\xac\xe0\x98\xd1\x1e~\xe2][\xee+չ\xfa\xadXūI\xaf\xe8\xbf\xf9E^\xd2C\xf8\xe9\xa1ļ/\x94o\x9c|Wx\xbe\xd8h\xd3\xd1\x11\xea;\xb3Ѧ\xf3\xd6\xd0\x12\x10\x85\x04|\xc7,I\xcb\x06:o\x16\x90\x9b\xf27\x17\x98\xe2s\xe7ɪ\x9c>\xdcT7\xfa*i\xd4\xe7\xed\xcd\xc2ܤk\xe8\xab\xc4\xdcB\xd5\xf6\xec\xb5\ue52eZp\xf7\xe9'\xb5\x04D!\x01\x9f1IҌ\x81\x8ec\x1f\xddR<B\xba\xe94ڲ[y/\xe3i\xdf)\xcc{\xa8\x1a\xfdiU\x9eZ-Y#I-\x01QH\xc0gL\x924c\xa0\xb3K\xf0\xb7+s\xe8\x06\x0f\x0f\xef\xdbx~\xc7\xf9\xfc\xb4\xc4U߲\x9b\xf3RZ\xf1c_]\x17y\xfcSvR\xc6\xd3]\x8a\xd8j\x9eǓ\xceR\x9e\fͯ%\xf1\xf2\b\xfd\xfcڹ\xb6\x94܋\xecnX-\x15\xb9(\xb7\x82\xaaE\xdaz\x84\x17\xc8&{\xd9\n\x9f\xceHZE\xf6B}\x15\xd9IY\x15\xb4\u05ff\x98\x97\x9a\xbcV5\xa6m\x8f\xe0\x04\"Twn\x90\x0f,\xa1\xf8lrqPWᢤ\x9c3\xa9u\x8a\xfd\x87\xb2\x90\x80\xf9\x98$i\xc6@\xe7P1\xbdCh\xd1.\xa3}\x86\x98\x9e\xea괌{R\x9fλ\xf3Sv\xf3\xa7i\xfc\xaaҷzhz\x13\xbf\xad\xae<%\xab\x8f\x8d\xedjL~\xeeK\xf4\xe5sɍ\xb8\xe1\x9fklL\x14{\xb0\x93I\xd9{O\x94\xf2\xe5\xecnX-\x17\x93\xbeI\xfc\x8c\xaaE\xda\xdau\xa61#\xa7\xb1\xb1\xf1#\xb2\x9b\x8dϨ>27\x97$\xf3m;\xeav\xd8\xf2q\xea|r\xc6\xfe#\xabx\xa5Z\\E\x9b\x05\x8a\x94\xb7ic\x0e,\xa1\xf8lrq\xae\xa5%\x97\xd7m\xe1\xf9\nE\x06CYH\xc0|L\x924c\xa0\xd3Y\xe4p\xba\x9ce\xf6\x12\xa3}\x86\x9e,\xfe\xa1k\xa8\xef\x9ar\xe3W\xa5\xbf\xb2\xf1ɤ\xef}\x95ߏ\x1f\xcf\t\xfd\xb0\x1c\xbb)\x0f?\xe4m\x12\xc3EI\xf7\xa4\xad\xea!R\xfaJ\xb1[a\x1e\xcaژ\x8d\x88Z\x94\x99\xc9cڔop\x8e)8Uǟ\xc0\x8f'x܅\xe6d\xe0\x9f\x8b\xbe,\x95Z\x9c-\x02\xca; 2\aV \x95\x979p~2\xe9i\xb7yHz\b\v\t\x98\x8eI\x92f\ftP\x87\xc3n\xb7\x1fv\x98pg\xbf,\x9b\xa2\x83\x96\xe89\xb1\x8a4ڼ\xb4\x9eo1\xa9\x9b\x94\xb1'\x13\xbbPW\xd2I\xf1\x95(\xe9:\xfe\x03\xf7\xde\xccnX-{\xf9\xbdT-\xca\xccd\xb5\x90\xd7tB\xbaI8\x1d\xb4h#\xba&hn\x87R--\x9c\x1b\x85\xe3\x0fs`\x05Ry\xe5\x03\xf7%Ѳ\xb6zJz\xc8\n\t\x98\x8fI\x92f\ft0\xae\x8e^Tl\x82'VV\xb6\xe7\xb6s\u0094\xf1\xc1\\\xd2\xd1\t\xe4*c\xbfM>\x82\x8e\xccu\xaft\x8b\x92.\xe7{\xdc\xef3\xbba\xb5|Q\xf8%U\x8b23\xe5\xca\x13U˃\xf4\x1d\x94\x9b\x8d{\xc9F\x84<W\x9ej\x1c\x025\x8a\xad́\x15H\xe5\x95\x0f|QX\xf3\xeb\xf2\x94\xf4\xd0\x15\x120\x1d\x93$\xcd\x18\xe8 \xbaP\xd6l7\xe1\x8e\xdar\xa3\x95I\xd9F\x9f\n3H\x9f\xf5.\xe5\vU\xec\xb6\\\x94\xbb\xcd\xfdB\x94\xf4\t\xfe}\xf7\x16f\xb7\xc2<aK\xa1Vf\xfbI7*\xabeS\x1a\xf9\x95\xe8K\xcbG\xdf\xf0\xe5\xbd\x1dW\\\xf9>\xa9\x859\xb0\x02\xa9\xbc\xf2\x81\xc5^\xfa\x03OIӸ\x81\x16\x92\xe6\xe2[!\x01?b\x92\xa4\x19\x03\x9d&\"\xe6+\xc5f\xf8簒nY'\x8cg禒Yi\x1fy\xeb\x840\xa7,ܫ\x8a}+\xf1\xb3ķ\xdc/DIw\xa5\xe4\x90\xder\xdb6\xc5n\x8cZ\x14\x99\xe5\xe4 \xf4%\xdd \xab\xa5\x8e\xbe\xae&#\xfe\xec\xff\xfaј1?\xfa\xb9Oja\x0e\x8c\xe4O\xc1\x94\x979\xf0ڹX\xab}\xf9\xa2\xa4ݱ\x83-d\x1a\xae\xa8\x8f\x12}*$\xe0GL\x924c\xa0\xd3l\xafm\u007f\xb3\xd8\xe1w\xb7\x8doߢk\xba\x9f\x88/gq3\xe8\xf3\\>\xa5\xb4\xee\xc8CId\xa9\xb7\xf0μW\x8el\u00adX\x19ۗ\xba*\x95\x8e\xbb{\xce46&nll$\x8bf'\x13\x17U\xd4\t+O\xd2n\xdf\xe4\xe5|\x86_\u007f\x96\x93\xf7\r\xb3\x15\x11y\x94\xe3C|\x8a>k\xb4m<\xd3\xf7\xceF[#\x8e\xcb\xe3\v_-䉾\xde\xff?\xdf).\x18\xf3\u007f\xff\xb3\xa2\x15\x19\xc3\x1cX\xfa\x14\x8a\xf2\xca\a\xfe,%\xad\xe2\x95\xdcDe\xec`\vٚ\x94Z\xba#\x99\xb7\xed\xf7\xa5\x90\x80\xff0KҌ\x81\xce\xf1\x92\"\xc7q\xa3\xf0\xa1\xe7}fڈ)\x8a\xb2\xd3\xe7_U\x14.JJɥ'oЉ\x9c\xb9\xc99u\x1e\xb1\xe56\xe1\x94\xd1;\xe2ԓJ䣵\xa9\xf7d\x1fQ\xecV\xca\xf3dai#O/\x9fvo\xc5\xf4lKN\xcc9G/\x9f\xe6m\x1f\x90\xb3\xdb[\xf0/EyVRV9\xf9\xadp\xfdpV\u007f\u007f\xe4\x8f~N\xb6\x1a\xc3\x1c\xd8\xfd)\x94\xe5\x95\x0f\xfcŦ\xb4ćΉ\x92\x16c\a[Ht>79\xadp\xbfͷB\x02~\xc34I\x03\xfatF\xce\xc1\x92\xbe\xadyxF.\xea\xe51 \xb8\x00I\x8f@\xa8\xa4#nk\x02I\x03\x03\a$\xad\x84\x1f\t\xfc\xe7\xffƒ\xfe\xe1\xff\xfa\xb7\u007f\xfb\xf9p\x88\x1a$\x1d܀\xa4\x95\x18\xa9\xcd/PIG|\xe7\x87\xdf\xfdN\xc3.\xc7\xe5n4\xa4\x9c\xaf\xe3\x9f~\xcb\xeb\xff\x8f\x01\x01\rHz\x04B\a\xde\x13;\xfa\xbbC0\xa1\x87\xdb;\x87R\xd59\xf87\xc3v\xde(\n\bX@\xd2#\x8f\xde+D\xd2w\xe3*\xfe\xde,W\xf3ؐ\x90\xef\xd9;{\x8dv\x02\x00\x01\x90\xf4\x88\xa3%.f,\x96\xf4f\\\xc5ӛ\xfa\xfbӗ\x1c\x8a\v\x99\xde\x01\x9a\x06|\x03$=\xd2pE|\xef\xf6\x1b\xb0\xa4kq\x15/\xfb\a\x96\xb6\xb3\xbf\u007fF\xf80\x9d\xd0\x02\x82\x0f\x90\xf4H\xa3!\xe4p\u007f8\x964\xc2U|\f\xff\x1d\xc6\u007fs\xc2\x1aF\xc8}\x9c\x80\x11\x0fHz\x84ѻ!\xe4\x1f\xfdd.M\xf8\xa7\xf8\a\x92\x06|\x06$=\xc2\xe8\xce\xfc^\u007f\xff\xc49\xfd\xbd\xae\u007f\xf6w\xe3?\x17\xfe\x03I\x03\xbe\x03\x92\x1ea\xb8\xe6\x85\xf5\xf7\xc7d\xfe\xf3\x1f\xfd\xc7\xff\xf1\xcf\xfe\x86\xde\xfe\xfe&\x9040\x00@\xd2#\f\u05ecHZ\xbb\x9b\x1fs\xf6oXw\xa5\u007f\xdd:\x04\x92\x06\x06\x00Hz\x84\xe1\x9a\x1e\xfdO\x0f@ҀϘ#\xe9\xeeb\xbb@1y\xe5,+\xdag\xc2=MF&\xaei\x93\xff\xe1\xc1,\x904\xe0+\xe6H\x94>:\xac\x00\x00\f\bIDAT\xdae?\xee\xc4\x1c\xb37\xe0\x17\xed\x055\xcd5\x05\xaa\x9bS\x8fZ\\\xd3&zn\x8c\x8e\x02I\x03>b\x8e\xa4\xd1iz\xefnz\v\xc1^\xfax\xa8\x18.\x8f\xa2\xb8\x96\x8d\xa9\xb9\xa2bWȽ\xa7AҀo\x98$i\x8a\x83ܧ\b5\x15Py\x17\x8c\x1c\xefJS\xe9m\n\r\xb9Ổ\xb1\x84\x1b0!?(iq\xa1\x90\x00\xc5\xe8\x13\x03C\x8b\x89\x92n\x12n\nZ)xb9̸\x9f\xe0H\xc4uzŬ\xe9230\x99\x8e\x86˽(\xe4j@\x02\x92\xf63&J\xba\xa4\x92>\xed\x12n\xe0}Ȅ[\xf3\x8fL\\Ζ&\x05\xcd-N\xf2\x9fX i\xc0\x17̓t\x8b]X\x11+\xae\xa5O\xb5\xc5ނG\x17\xdd.%\xddt\x9d\x01$\r\xf8\x82y\x92\xae\x14M\xb0D\xe7\xca*\u007f\xdb\xdc\x05\x1c i\xc0\x17̓t\x91h(M\x1d7\x10*\x83\xb9\xb4\x01D\xd2O\x8eŏ\xac\xb6C<\x12\xde\xf0)HB/Z7\x17\xcd7@\xd2~\xc64Iw\xd8E_\x88&;q\xbc\xbbb\x87\x15o\x03\x88`\xc6\xfd\xf9\xaawI\u007f~\xdfMcn\xf8\xe9\xee\xab\xdahi.\xe4\x16\xe1\xf9\x16\x8fl}\x94t\x88F\x8a}\xdb\xe8s\x01C\x8bi\x92n\xb1_\x16\x12\xbd\xd4;\xa7\n\xceK\x1b\x11\xa2%\x1a\xb5\xa4\u007f\xf1\xb3\xd7?\u007f\xfb\xc9[\xd5a^\b\xb9\x89\xfe\x00\xec\xbe\xe9\xfa%\xad\tH\xdaϘ&\xe9&\xbb\xfb>\x1d\xed\x05U-Up\xf5\x98!d\xc8-\x80\x85\xf2\xcc\u007f\x8c\x19w\x9f\xa8\xa7G\xc7\xfd\xeb\xb8߈\xc2\x1a\xf37\xb7\x94\xa4\x88\an\f\x19{\x01'.\x8c}\x9b\xeey\xf3\x98\x1b\x1fe\xdf\u007f\xfc\xc7$\xfcǏ3\xd9\nG\ty\xfc\xe61c\u007fA2\xfc\r9\xc2Uա^\xff\xe9\xd817?\xee\x8e\xc5G!\x85a\xf6\xb9Q\b\x05I\xfb\x19\xd3$\xdd\"/\x879\xf7\x15\x94\xc15ކH\xbd4~x\xf1\xdf_\xbc\xf0\xfa\x8f\xef\xa3\xe9\xdf߸\xfb\xc2\xee\x1bE\x9d\x8d{QT\xb4\x1cq\xeb\xdbW\u007f\xf28\xde\xf2\xf8Oh\xf4w\x9f\xb9\xf0\xfa/\x149܄G\xf3\u007f\xfe\xbe:[\xda\u007f_x\xfbg?\xc3B\xbfq\xf7\xe7\xbbo|Fu\xa8\x9b\x1f\xf8\xdb\xe7/\xfe\xc4\x1d\x8b\x8fB%\xcd\xec#\x84\x82\xa4\xfd\x8ci\x92\x06\x06\n+\xe9[ɜ\xfa\xedqB\x1ak\xed\xea3\xa2Ξ\x19\xfb\xd3\a\xa8\xaa\xe5\b\x9c\xa0#\xf1[\x9f$ѷ<)\x0429<\x8e\x15\xf8\xb3'\xd5\xd9\n{^\xfd\u007fc\xf1>\xf4\b\xb7\xa8\x0eu\xc3\xdb³\x1c\x1b\xc2\xec#\x85\x82\xa4\xfd\fH:``%=\xd6=\x02'i2\xcc\xfd\x9b\xa8\xb3\xab\u007f{\xf4\xae\x9bIW-G|~\xf5\xea\xe7c\u07fe\xfa\xf6\xd8\xcfI\xb4{d\xce\xe6\xf0\xfd\xd7_\xff\xbeG\xb6\xe2\x03y\xbc\x81\x1e\xe1\x06ա\xfe{\xec]\x8f\xbe-\x95\xe9sQ\xd2\xca}@\xd2\xfe\a$\x1d0\xb0\x92\x1e#\xf6\x90\n\xf1H<\xfe}e\xc4իw\xddw\xf5\xbe\xbb\xe4\x1f\x80\xab\xca\xf7\x9f\xbc\xeb\xae'=\xb2Ւ\xb4\xf2P\u007f~\xe0\xa77<\xc0Ƃ\xa4G\x02 送\x95\xf4-\xbf\x91\xb5\xa7\x18\rS\x88\xfa\xd8\b<I\xbe\xe9\xeaM/\n\xd1\xe2\xc0[\xf1\xfe\xcd7_\xf5Ȗ\x91\xa7\xf6\xc0\x9b\xf0\xfa\rz\x92\x86\x81\xb7Y\x80\xa4\x03\x06Vһ\xc7>\xfa\xb7\v\xbb\u007fLӊ5\xab[\x9f|\xfb\xf3\xd7\u007f\xf6\ve\x04\xe6\xa6\an\x12\xf7\xbc\xf1\xf7tyL\xf5\xbe*\xdbq\xbfw\x1f\x8c<\nK]\xea\xe5\xb1\x1f\xff\xfe\u0085\xdf\xdc\xccƲ\x92~f\x1c\x0e\x1d\a\x92\xf6? 送\x95\xf4\xd5ݷ\x8e\x19s\xebn!\xfd\xe8\x8d\xf2\x99\xa5\xdd?\xbda̸\xff\xbe\xa0\x8a\xb8z\xf5\xbe\u007fu\x9f\xf2z\xe6?\x84\x93X\xca\xf7U\xd9>3.$D\x96\xe7\xd5ߌ\v\x11Ob1\x87\xfa\xfd\xadc\xc6\xfe\xe4u6\x96\x954=\x89\xf5\xc0\x18\x90\xb4\xdf\x01I\a\f\x92\xf6\x02\a<\xde\aI\xfb\x1b\x90t\xc0\x10`\x92\xfeş/\xbc\xf8\xef\x0f\x80\xa4\xfd\x0eH:`\b0I?\xfa\xfd17aE\x83\xa4\xfd\rH:`\b0I\xbb\x01I\xfb\x19\x90t\xc0\x00\x92\x06|\x01$\x1d0\x84\x04(F\x9f\v\x18Z@\xd2\x00\x10T\x80\xa4W\xaf\xd6J\x02@\x80b\x8e\xa4\x95\x06:\bU\x99wK\x93\xbfZ\x9e\xd0H\xbayقI\xc0\x89\xf7~\x19\x1f\xbb\xf0\xe8\xfc7pr\xeb\xcc;\xa6\xde1s;B\xf5\x16\xcbB\x84\x0e\xe0\x88\xa3\xea\xfd\x86\x89\xa3\xf1\u007f\x91\xd2mS-\xb3\xbd\x84z\xe7a\x8b\xe5\x80Q̀\x18\xba\x8aZ\x8dìmFQ\x80.\xe6HZa\xa0\x83\x90\xd3^k\xb0\xc3\xf0\xb1\xd2zI#\xe9\xc6\xf5F}\xec\xf2\xf7\x10:;u遗\x96S\x1d\x1c\xb5\xfcr\xcf\xc1\x17\x96Z\xea\x91\xeb\xa8Ŋ\x1f\x0fX\x8e\xba\xd0\x10s\xf4\xac\xe6\xe6\x83VF\x88\xa7V[5\x83|\xe1R\xfd\xd4\xedF1\x03b\xe8*\xea\xe3\xfa\xfa\xff\xb1\xbca\x14\x05\xe8b\x8e\xa4Y\x03\x1d\xac\xe8\x12\xf3$\xddfY\xaf\x91d\x89']\xf7\xe2\xc5$\xb9\x9a\xb4\xd4\xf5\xb1\xb4\xec\xb18\xd8eY\xb9\x9a\xec\xe7CC\x1d \xf3\x97\x1bE`\xb6\x0f^\xd2\bY\x87V\xd2h(+\xea\x14H\xfa:0I\xd2\x14\xc1@\aU٫\nL\x93\xf4j\xb9g^\xed\xd9I\x13hKM\xd8J\x92\uf456\xbax\x01ݼ`1i\xa9Gq\xb3\xf5\xb9\xa5\x0e\x80\x80\x95\xf4\x90T\x14H\xfaz0QҢ\x81\x0er\xb9ܷ\xe7\xf7?mS\xd7k$\x15Ж\xba<\xfe=\x92>\x88\xdb\xe4BAm\xcb\x17\x92\x96\xda6\xff\x80\xba\xa5\x9e\x9dj\xb1lm[\x99`\xbd\x9f\xdc \xf1\xa5\x85֙\xeb\xe9\xfb\xae'f\xc7.|#\xe1 z\xc4byI\x9e\t\xcb\x01\xf5\x8b\x13\xa6\xc6\xff\x12\xcfG\xffb\x11\x98\x8f\x14|m\xb5\x90=)\x97V\xc6\xc7.\xf7\x1cx\xb7-\x8f\xc7Y\xe0_\xa6N\x9cHXJF\xef\x8fX\xa6\xeeY?Ӻ\xf8cU\xa8u\xfd\xea\xf8;\x96\xb6Ѵ\\\x06\x19\xcd\x1c\x0e\xe2\x12\xfc\x16m\xb7h\xce\xc4\aZQdn\xbd]\xccL>\x1aA\x94\xb4^E!\xf4B\xfc\x1e\x04\xe8`\xa2\xa4E\x03\x1d\x82i\x92^=\xf5c\x8d\xa4\x02\xdaR?N\xb0ܿ\xfd\x14\x1dT\xcc\xff5\xdd\xfc\xeb\xf9\xb4\xa5\xee\xfc\xa5\xba\xa5\xba\x0e\xbc\x94036a\xfdJ\xcb\xc7d\x04\xba\xfe\xe0\xce\xf8\xf9X\xdc_'\xc4\xef<\xf8\xb0ŲG\x9cNJ3a9\xe0\xace偣{\xe2-\xbdd^:sa}}}\x9b\xaa$g\xeb\xebž\xb5-v\xe6\v\u007fYlQK\xfa\xb5\xd8\xf9\xbf;\xbaݲ\x93ho\xf5k\a\x96ZN!\xf4ח\xa6Z\xe2\xb7\xef\x8cUw\xfbV\xcb\xfc\x97^\x9ao%\x02\x94\xcb\xc0\xa0\x99\x83덄\x87/\xa1K[c\xeb5\xfa\xdb\x01WT}\xecVwf\xf2\xd1\b\xa2\xa4u*\n\xb3\xdcr?\x02t0O\xd2n\x03\x1d\x82Y\x92\xfex\xea\xc3\x1aI%\xb4\xa5\xa2\xaf\x9f]0\xd5\x12K\xfa\xa6\xd9+\xe9敳iK\xbdd\xbd\xe49\x9e\x9coY܉\xfb9\xa2\x8b?\"\xd2Bqߺ2\x96\f\xeb\xd7[H\xf7B\x85I\x87\xcdL\xc0\x9ex\xd2\\\xff'V\xc8Ag\xe0-Jz\xe1L|\xc8\xde\xf9*I\xbb\x12\xeeǛ\xbb\x0f|M~WH\x99\x84\\\xac\xb1\xf8\xb7ee\xbc:\xa7\xd98\xc25s\x81\xa2\flf\xda9l'C\x87\x95\x9a'\xfb\x06^Q\xabI\xee\xbf&\x99\xb1Gc\x06ޚ\x15\x85i{\xb6\r\x01:\x98'i\xb7\x81\x0e\xc1,I?2\xb5M#\xa9$\xde}f\xcbu\xf4~\xcbA\xa9\xf3Y.t>\xe8\x97;5$m\x15;\xfc\xe5\tݽ\x98\x04\xdcj\xadt\x92\xf9W\x95\xa4\x99\x80\x8f\xe3\x13\x1e\xd9s\x16u\v9x\x95\xf4\xd74\x17\xb4U%\xe9\x83\x16y\x9d\xfc\xef{\xeeO\x88\x15\x86\xeeV\xa2\x19\x8fy\xb7\xf5\xb7\xe4q\x8f\xe5k\xb6\f,\xda9|ly\x0f\xb9b5\xcfE\r\xbc\xa2^\xb3\xba\x90\xcbZO\x92\xcc\xd14%\xadSH\xc0\x13\xf3$\xed6\xd0!\x98$\xe9K\xd6\xd5\x1aI\x15\xb4\xa5\x9e\x12V\xce\x16.\x15\xfe0K\x85)\":0_C\xd2\xeeY\xf0|qV\xbc\x1cK\x81\xce>]*I\xcb\x01X\xa8{\x96϶\xc4\xffN\xd8ѫ\xa4\xcfZ\xa8\f\xd42\xdd)\x17\xe4T|\xc2\x13\a\xea\x17ϗ\xf6\xf1\x944ͩ\x1e\xff\n\xb0e\x90\xd1\xcb\xe1\xfe'\xd0\xd1\xd8n\xa4\xc1\xc0+\xaa7\xfe\x00z\x99\x0eNأiJZ\xbb\x90\x80\x06\xa6IZ2\xd0!\x98$\xe9\xf5\xb8\xa5y&%z\xe9&\xdaR\xe3\x1f\xa1[\xb6\xceDHlw\xf3\x17\v-\xd5e=\xea)iw\xc3[\x99p\x96\xf2w\xd4+H\xe8=YҴ\x8f\x95\x03\xd0Yr\x9c\xaf_\xb2\xee\x91rx\xc1sr/\xe4\xf2w\xa1\x97V/\x8f\x1d\x95{\xe9\xd9\vH\x99\x96{\x934]\f|\xc1\xd2ɖ\x81A/\x87\xbf\xc4w{\\d7\xe8\x8aZ\xbf\x1c-\xa7\xe5`\x8f\xa6\x96\xb4\xba\xa2\x00\xef\x98&i\xc9@\x87`\x8e\xa4\x8d:\xe9=\xa43\xfc;YmB\xf1\t_\x93-Di\xe2\xe9V\xb2\x03i\xa9h\xf5\xaf\xf5%}T蛷>K\x96\x82Ik\\)H\x1a7\xfe\xde\x05Ve\xc0v\xe1Ҫ\x85tJ\xbf\x10wm\x974\x96\x95Ź\xf4\x02R\x9c6\xabJ\xa6\xae\xf8\x85\xa4\xfb\\\x8fE\x92@J\xd0;ߛ\xa4\x13ȼ{\xf6BE\x19\x18\xf4r\xe8\x8e\xff\xcb\x1d\xeaq\xf7\xa0+\xea\x94\xf5\x92\x95.\x89\xb1Gc%\xadUQ\x98\xb6\xedm\b\xd0\xc14I\xcb\x06:.\xa7\xb3\xa8\xcai\x82\xdd\xc6\x13r\xcf\xfc\x84F'M.\u007f:\xf0\xc7\x05\U00064bcc\xb7\xc4o=z`1\xb9P\xf1\xa8\xe5\xfe\x97\xeb_^ly\x99\\\x14u\xc0\x85\xea\xadʖ\xda{\x8a\xaeW\v\xf9=a\xf9\xf5\x81\x97W\x93E\x9dK\xf1\t{\x0e,\xb7RI/\x8c\xffݳ\v,S\xff\xf8\x1e\x1b\xb0\xdd\x12\xbb\xf5\xe0\x81Ֆ\xd7\xc8~ۭ;_^lU\xf6\xd2\xddo\xd4\xd7[W\xd7\xd7w\xe2\xceޚ\xb0}\xeb\x1dB\x0e\fG\xad\xb3\xf7\x1c\\oy\x81d\xb6|ϳ\xf3\xf10\xfeԥ\xfa\xa9\xabO\xa1\xb3\xab\xa7\xd6+Ϻ[-\xf7\x9f:\xba0\xb6\r\xb1e`\xd0\xcdቄX\xb5}\xd9\xe0*\x8a\x10\xbfXX\xb6\x93\x8f&\\=\xb6\xb3\xbe\x9e\xe4\xa6YQ\x98\xa5\xe4\x02S@\x1b\xd3$-\x1b\xe8\x1c\x13.\xf7\xbe\xe2-z8\xb8d]\xa9\x91d90\xdf\x1a\xbb\x94\xaaf\xc1\v[g[\xe3\x85Ӹ[g\xc6Zbɥ˯\xd1S\xaa\xbd\v\xe2\x15M\xfc\xac0\xe9\x13&\x92\xe8\xe8\xe2\xf8\u0605\aI\xea\xef\xab\x13\xac\x8b\xcfRI\xb7-\xb4\xc6.\xfe\xad\xc5\xf20\x1b\xf0\xd2\xc2\xed\tS\xe3\x17\xbeFws\xad\xbfú\xf0\x14R f,\xe4\xb0\xf4\x8e\x84'\xfe8բZ\xa5o[\x9e\x10\xbb\x80tg\xbd;gZ㗿0s\xea\u0087\xf1\x1eS\xdf#\xa7\xb4\x95\xb1\xb3\xb7/\x8f\x8d_)\xc8\\.\xa4\x8cn\x0em\x16\xcf\x01͠*\x8a\xb0Ӻ\x93>\xcbG\xa3\xd7x\xbbg͚\x15EwS/\xe0\x03\x12\xa6I\xda|~k\xf9\xabFrx\x11\x96\xc7\x02\x1a\x97\xf55\xa3\x90\xe1g\xe9b\xa3\x88\xd1\xcb(\x96\xb4\x19\xffU\x19\x04\x92>\xe0\xd9\xd7\xfa\x9dg-\xaa1\x05 3\x8a%m\x06\x81.\xe9\xed\xaf\xa1\xc5[\x8d\x82\x86\x9d\x8f\xe3w\x1a\x85\x8cb@\xd2\xfe\xa4\xed\xa8e\xbdj\x86\x1cP\xb8,\xf3\x1f\x89\xff\xda(\n0\x15\x90\xb4?YHV\x9aڌ\xa2F0[c\x17\xb7\x19\xc5\x00\xe6\x02\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\x00\b*\xfe?\xb6^u\v\xa5[\x1f\x81\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/ident-func.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xd2\x00\x00\x00\xda\b\x03\x00\x00\x00}\xf6\x8a\x1c\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x01\x04\x00\x02\x05\x01\n\x03\x01\x05\b\x03\t\f\b\t\x0f\x11\x0e\x10\f\x10\x12\x0f\x13\x15\x12\x15\x16\x14\x0f\x17&\x19\x18\x11\x1a\x1a\x13\x1a\x1c\x19\x1c\x1c\x16\x13\x1e7 \x1f\x19!# $$\x1d#$\"$%#'(&)(\"+)\x1e\x14+N++$*,)/-\"-.,.2402/63(241:7+685;9-:;9?<0=?=C@4AB@CEBGE8KH<MI8HIG\x00f\x00\x00i\x01JLI\x00j\x02SN=MOL\x05m\x051S\x96WRAQSP\fo\t\x0fq\vUVT\fr\x175[\xa4XZW,`\xae7]\xad\x15w\x1cb]K\\^[9a\xab\x19y\x1e;c\xad=d\xae`b_)z!?f\xb0)|*Bh\xb3egdLi\xafDl\xb0qjRikh/\x82/Ho\xb3/\x859Jq\xb6mol;\x86:Ut\xb4Xv\xb6?\x8a>|u]tvsB\x8c@@\x8dG\\z\xbby{x]~\xb7e|\xb8\x84|dK\x90J_\x80\xba}\u007f|O\x93Nb\x83\xbd\x8b\x81cN\x95Ud\x85\xbf\x81\x83\x80W\x95Vl\x87\xbc\x8f\x86hZ\x98Yo\x89\xbe\\\x9a[\x87\x89\x86\x93\x89k^\x9d]\\\x9dds\x8dË\x8d\x8a\x96\x8doz\x8e\xbfe\x9ef\x8d\x8f\x8c|\x90\xc1\x9b\x91s\x90\x92\x8fi\xa2i~\x93\xc4x\x95Ā\x94œ\x94\x91{\x98\xc7s\xa4l\xa0\x96xq\xa5s\x97\x99\x96\x83\x9bţ\x99{\x99\x9b\x98u\xaaw\xa7\x9d~\x87\x9fɜ\x9e\x9b\u007f\xabz\x89\xa1˫\xa0\x82\x9f\xa1\x9e\x8f\xa2ǡ\xa3\xa0\xa2\xa4\xa1\x92\xa5ʂ\xb1\x85\xa5\xa7\xa4\x94\xa8ͳ\xa7\x82\x8b\xb3\x89\xa7\xa9\xa6\x96\xaa϶\xa9\x84\x8e\xb6\x8c\x9d\xac̪\xac\xa9\x8d\xb8\x93\xba\xad\x88\x9f\xafέ\xaf\xac\xa1\xb1ѯ\xb1\xae\x97\xbb\x97\xc0\xb3\x8e\xa5\xb4Ԛ\xbe\x9a\xb3\xb5\xb2\xab\xb7ѵ\xb7\xb4\xa3\xbf\x9d\xa2\xc0\xa4Ÿ\x93\xb7\xb9\xb6\xae\xbaԹ\xbb\xb8\xb0\xbc֦Ũ\xbb\xbd\xba\xb2\xbdض\xbeӽ\xbf\xbc\xa8ǫ\xafƫ\xcd\xc0\x9a\xb9\xc0տ\xc1\xbe\xba\xc2ײɮ\xc2\xc4\xc1\xbc\xc4ٲ̷\xd2Š\xc4\xc6\xc3\xd5ƚ\xc0\xc8ݻ\xca\xde\xc7\xc9ƻκ\xd8ɝ\xc0\xcc\xda\xc7\xcb\xdb\xca\xccɿҾ\xc9\xcd\xdd\xd7ϡ\xcd\xcf\xcc\xc4\xd0\xde\xdfϣ\xc8\xd3\xc1\xcc\xd0\xe0\xcf\xd1\xce\xe1Ҧ\xc9\xd7\xcb\xd2\xd4\xd1\xd2\xd3\xdd\xdf֨\xcd\xd6\xde\xcc\xda\xce\xe6֪\xd6\xd8\xd5\xd0\xd9\xe1\xd8\xd9\xe3\xd5\xdc\xd1\xd3\xdc\xe4\xda\xdc\xd9\xe6ݯ\xecܰ\xd5\xdf\xda\xdc\xdc\xe7\xdc\xde\xdb\xda\xdf\xe2\xd7\xe1\xdc\xe0\xde\xe2\xde\xe0\xdd\xf0\xe0\xb3\xdf\xe1\xde\xdd\xe3\xe5\xe1\xe3\xdf\xe3\xe5\xe2\xe1\xe6\xe9\xe8\xe5\xea\xe5\xe7\xe4\xe4\xe9\xeb\xe7\xe9\xe6\xf1\xf3\xf0\xfa\xfc\xf9\xfe\xff\xfcd\x82\x05\xe8\x00\x00 \x00IDATx^\xed\x9d\x0fT\x14\xd7\xdd\xf7\x1fZ\xf3\xc6\xe6M\xda\xd7Q\xf6\xe9S\xe2K\xa9%F\xdbd\x95x\xdeJ\xa0fN\\@\x13\x90*\x82Ę*M\xa2\xb4Q⟜h0\xc4\x1c\xff\xb4.\xc1@\f\th\"I\xa4\xc1\x83A\xa4V\xadx\fA\x03\x96'\xc1D\x92\x87\xa4\xa6nj$QL#\t\x1c\x16\x02\xb7\xf5\xbc\xf7ޙ\x9d\xb93;\xb3\xb3\xc0\xee\x0e\f\xbf\xcf\xd1ݻw\u007f\xf7\xcfܹ\u07fd\u007ff\x98\xdf\u007f\\\x1b<\b\x00\x80\xe1\xc6\u007f\x18\xe9\xd6\aFy\x03\x00\x10r@\xd2\x00`)@\xd2\x00`)@\xd2\x00`)@\xd2\x00\x10`\xfa\x8c\f\x82\nH\x1a\x00\x02\x89+c\x127\xc7\xc8(\x98X^\xd2e3یL̤}f\x99\x91\xc9Hd\x14\xb7\xfaԩ\xce\xcaO\x8c\x8c\x82\x89\x89\x92n\xdeWTrB\f79\xcb}\xda~\xb3y^bN\xbfO\x13m\x9e\xe4\xd6\x19\x99\x04\x8as9I\xa9\xb9\xa7R\xbfR\xc7\u007f\xee\xe0\xefӲ\x17xr\xc2\x06\xaf\xb8\"\x0e\x135\xfb\xa4\x869Ck87\xd5_[?!\x99\xadC\xeb\xf0k\x81\x0f+\xa1`_\x04\xbeիxLr\xce\xfbFv~\xa2\xd5ꁡ\x81\xdbgd\x12dL\x93\xb4\xbb\xd2y\xb4\xf5\xa4\xb3\x85~h/8\\\xec\xd3\xfa\x91Ԋ\xbc\xa4\x0e\x9f&\x9al\x9dPdd\x12(\xea\x93~Sqp)\xcf\u007f\xa4\xfe\xa2\xff\x9d\xcd\x0e\xad\x04\"\xe5\xe1[\xd5QW\x8b\xb8\r\xd5E3\xb9j-{\x99\xa3\x196\xbfm}S-\xfe\"\x90\xcc\xdaPۓ\\\xd1U_\xe6\xb4`\x1f\x04\xa1ջ\xab\xf8\x97NUe\xddu\xca\xc8\xd0\x17\xa7\xceJA\x8dV\x0f\f\xb5\\\x8d\x91I\x901Mҕ\x05.\x84ڜ\xcd\xf4Cy\xa5˧\xa4;\xf8\n\xd4\xdf\xed\xcbB\x9bV\xdbr\xdf\x06mq\x81\x9a v$\xaf\xe9\xc5=/\xd3[\xd2\b\x95\xfa\x924Zis\xa9\xa3\x9a\xe8O\xfd\xcc)\x1a\xd6,\xebl\xfe\xdb\xfadF\x8a\x18\x102\xab\xe6\x9a|Y\x8b\x05\xeb\x12\x94V?\xc7\xd7\xe3_\xc7\xecL#;_d\xad\x97\xc3\x1a\xad\x1e\x10j\xb9\xa3F&A\xc6,I\xbb\x9c\r\xe4M\x18\f\x9a\x8aܾ%}\x81?\xee\xebk]2&u\xfa6h2\xea\xbc~S\x98t\x99\xbc\xed\xe5?\xf5\xfeη\xa4;'e\xa8\xa3\x04em\xe5\fj\xcfH\xda\xd0\xd6'\xd3\x03*頴:\x954\xaa\xe0\a\xf1\xc3.\xb1\x94\x91\xb4F\xab\a\x84\xd1+\xe9\xa3\x05=R\xf8jA\v\xf2!\xe9\xdey<%\x1f\xa1m<\u007fP\\\x9bn\xe3\x1d\x15\xf9\x99I9_P\x9b\v\xeb\xe79RŰ\x8c{\xa24\\\xb4\xa4D\x85O\x9a\xad\xfca\xde:\xa5\xbc\x99k.\x9f\xe2\xc4\xe1ƜtǼ\x9ct\xb2\\\xef\xaf\xcaJ\xca\xcc\xc7]\xe7C\a\xcf0\x97\x9e\x98\xf3\xedA\\~)*\xe5I\xf9\x9a\x06(s\vͳc/\x1e\xab\xfb+\xb2\x92\x96VХ\xff\x17\xb9i\xc9녉\xb7\x94\f\xa9\xea\xbb2\u008d\x94\bʚ\x1fM?\x14ό\x98\xb2\x8c\x88\xe4j\xca$[\xf4\x1c\xfaS\x88\\\xf3'E\xa6dȒVۢ\xce\xe5S'\xc6\x1d\x8dއ\x96p\x13\x8a\xf1\xc0).\u007fe\x83\x9aY\xd1\xe1Q\xb3q\xb2rN`:RIڠ`٠!\x9c\xe3V\xb6̟\x1c1\x9b\x9cTO\xab+c%\xe4Vg\x9a\x8f\x9c\xcd-i\xc9k.P\x13\xad\xb3)H:7\x8d\x84\x99\x96\xec.\xbc/)\xfb\x9d\xb4z\xb6k(\f\xa4\x13{\\\xe8E|\x96\x98\xa1w\xabk\x1e\x90\xf2(\x9c\xd3#\xa6\x93\xee\xa2sl\x88\xb4\xddh\x95tYy\xf3ng\xf1aڪ\xe5\x95ȗ\xa4\xd1G\x8d\a\xf9\xd2\xc6F<\n~\xd1\xe8(\x15צ\xe7\x0e:\xf8\xd4\xd2W\x92\xe9\x0f賓\xacW\xeaK\xf9\xbd\xaa\x84'\xa5\x15f\xf5\xc4\xe9OV\xae\xe36)\xbev\xcd\xe7\xa6r\xb7s)X\xe8\xefߕw\xa4\xbeb\x1e\xff-\x8e\xde\xc2\xe7\xd7W\xa4.\xedG\xbd\a\x0f\xa6gޓ\x96\x9f{\xd7\xe7ݍ\xc9/|\x85\xbez!\xb9\xb1[۠\x97-<ϱ\xb3~\xa7#\x0f\x87.$gV\x1d\xcfᩤ\xa5d\xea\xfa\x1e\xf6\xea\x05M\\\xb9\xbby9G\xb7p2&,)\xdf\x1a5\xbd\x8fh/\xa3\xbad΄Z\x1c\xd92qJQ\xd9,Φk\xdb>9\xea\xc9\xf2%\x1c\xe7D\xae\x9a\xf0u\xd2\xf2W6\xa8\xe5\xe6\xef\xaetFq=\xa8\xf3p͔\xb8\x9a\x9a\x9af13\xb7{\x1f\x95\xb4Q\xc1\xb2\x81\xbb\xa48z\xca\xc4\xe8e\xf39\xb2\xd5\xebiue\xac\x84\xdc\xeaL\U000d1cd9^Z\x9a\x9et\x0e\xe9\x9cM,\xe9\xeeO\v\xf1\xef*b[\xb2#=yo=Vs\x05\xdb5X\x03\xf9\xc4v76ff766zfQޭ\xaey@\x8a\xa3Ȱ\xad,_i\x9b\xaf{l=m\xd53\"\x872]\n\x04fI\xba\xc4Y\xdc\xe0j..\xc1\x9an.\xea\xf4-iv\xe2\xed \xe7T\x98\xc8:\x92\xf1\xefx^*\x0e\xf5\xa6\xe7\u0c71\xf7\xa0z\xff\xac\x9ck\x15\x02\xee\xe8\xd9nr\x1e\xdaU\x06\xfb¹p\xbaAY\x91J\xc4\\\x91\x8c;\xc1q\xbe\n\aϒ\xe1\x18O\xd5\xf8G\xba\x85U\xfc\x96\\\xfc\x92K\x86bM\x83\xcf\xf9\xbfH\xb9\xd6\xd3\x01\x85\xbefg\xe2\xb4\xfdK\x1d\xcad\xaa\xfa\xba\xb8\xddHI\x13\x1d6\xe7\x93`9G\xb6\x9aj\xb9\x17I\xfdIo\xb9\x9d\\\xf4\x9c9\x19\a\xfb\xa6\xdbtm\xe7G\x92\x19\xc92\x8e\f)6\xb2\xfdL\xe7ʌ\x813\x8a\x8c/[#iy\xcc\xc4[\xa0ɏ\x82\x19\x03\x9c\x037몸\x8e\x92Z]\x11\xcb \xb5:۾\x8e\xf4n\xa2\xd0,\xbd\xb3y\x8e\x0e\xb1y\xe4\a\x91i\xc9<\xd2\aP>\x964\xdb5\x18\x03\xe6\xc4*'\xde\x1a\xad\xaew@Rp\x1f\x9d\xc3\b\xaf\x9a\xc76\a7\x9d\xefK7!\xc0,I\x97\x17\x90\xc6\xe8,\xaaE\x9d\x05\xcd}}}\x9f\x14\xfb\xba\xe5F[\xd2y\x9e`\xbd֞\x14\xa6\xccӹʹ\x06\x8d\xafۗ٢\xb9I\xb6eX\xe8\x97\xd3\xd2\xf3+>\xea\xc7]\t\xe5\xa6\xf7~\x8bI\xa3\x13饎\xcfE\xe3S\x89ݨ;锞A\xafC\x1eT\xb6\b\u05ec\xee\xdbL\xb7\xf50;\x1d\xcad\xaa\xfa\xba\x84N\xc4\xd0\xc4m:Z>3\x82\xd4>e\xb2\xbb\a\x13MV~m\xceٓ'r\xb7\xe3\x9aS\xa9\xa2\x956]\xdb\bz\x15\xa9Y%i\xc6\xc05i\xf2\x12g\x03\x12&\x9f\x8c\xa47\xd5\xd6\xd6n\"\x926,\x985@\xd3m\xd2pU\xc6HZ\x8e\x95`Z\x9dm_G!y\xad\xe0;t\xce\xe69\xfe\x95\xb3dz\x12\x89\xb9ܒ\xfdI\xa5\xc2wJI3M͜X/I\xab[]\uf024`\xc6\xed\xf4m\xaa\xda@\xe2\x93}Ω\xa3v\x94\xae\x16~\"\xab\xcbP\xabӃ\xfe\x16\xa4\xb6\xa4\xa5\xe0^\xbeW3\xd9Q\xcf\xdcj+\xe7\xbdnB\xe8\xc9('^\xd5m\x8d\"s֎\x8a\xf5\x99\xfc\xbc\x97\xfa\xc9\xc0!\xb0\x86\x98,\xf5\xac\xbcз\xc9GБy\xe4\xc7^\xdb@\\K\xf7\xe2\xa1\xf9a\xfa\r\xca\xc9\xc2\x03E#\t\xd1J2\xc9T\xf5\xad\xe5\x0e#%tI\xdb>\x81\xc8g\xba8n\xe2!\xb2vR\xf4\xf2\xdd5q\xb8_\x9d\x10\xae\x94\xc8\xdbcj[q\b\xba\xaa\x924\x93\x19jw\xa6L增\xa4\xe5im\x8f\x19\x16\xccf\x86\xa6ϐ*\u007fT\x9e\xd12\xb1\x12l\xab3\xedK\xcf&j\xe4\xcf\xea\x9cM\xba\x96\x16~\"\xe5\x96\xfc\x82?B\xbe\xebVI\x9a=C\xf2\x89UIڻ\xd5\xf5\x0eH\nΜM\xdff\xcfP\x19\xb0\xd4p\xb5\x9a\xf1\xa1\xc3,I\x9f,\xa2\xa3r%\x9e\xa6\xb4\x11\x9a\x8a\xda|\\\xd8PIz\xa7Jҧ\xf8\x0f5\x93u\xda\xc4;\x1e*9\xcd[1\xdct\uf568\xfdl!Y\x98\x1dL\xac ?\xf1g)t\xde\xc7t\x82\xfc5h}>\th\x1b\x14&\xd2\xcf\a\xf9\xaf\xd0\x16a\x97-=\x0f}#\x8c\xd2y\x0ee2U}\xd7\xd9\xd4SSAY\x13I\xed\xe7O>I\xc1\xad3u&\xa9j\x8a<X2\xdbc*\xdb>a\x94n\x92%M\aV&\xb3\x13d\x0f\xeb\xea\x8b\x114#*\xe9\x82O\x14\x926,\x981`~\x14\x98VW\xc4\xcaȭζ\xaf\x83\xb6-\xd9\xd1\xd6>\x9b\xc2\xf6X29\xe7rK\x8a\xa3\xf4G\xb2\xa4w\xaa\x9a\x9a9\xb1biU\xe2\xbc\xc0\xbb\xd5\xf5\x0eH\nfL\xa6o\x933T\x06,\xa3wǻ\x9d^ĺZ\xe0\xb9}\xccߵt\x12\x9e\x9f\xf5\xffF%\xe9\xee\xd4l\xf2Þ\x9f\xafN\x972E\x98\xcewN\x8a#]h\xc92\xb5\x81+R\x98\x1a\x94\xd2\x0e\x83\xb27\x93Y1]$\x17\xbeD^\x19I\xbf\x9bx9\xf1]\x12\xd06\xe8H^O\xf6\xba\xb3\xd3=\x06\aI\x96Y\xe9\xb8[}\x9a\xe8P&Sַo\xeal\xa4BP֤e\r\xeb\xf0ʭ\x84ĬăZ4\xe9D}\xd3\xc9\xecoF4\x9e\xb7\xb6\xd8l\xba\xb6)Q\xa4cΧ\n\x8c\xc0\xea\xed\x9bAl\x19\x83u\u008a0n\t}\x8dÿ\xac\xe4;F҆\x053\x06\xca\x0e\xeeiu\xddn\xefiu\x85\xa4\xe7\xe1\xb5twz\xb6\xbauZ7\b\xd3xAҩ\xf9\xe7Jٖ\\?\x0f\xb7o\u007f\x1e\x95\xb4\xdc5\x18\x03\xe6\xc4\xe2W\x9c\xfbW\xc2wZ\xad\xaew@R\xb0\x9c\xce\xd5_\x14\x96\xcb i5'\nN\xb8\x9a\x8aw\xf7\xd0\x0f}\xae\xa6\"\x97z\xefJB\xd8\xf1~\x87Ν\x1eN}\xa94\x8bwT\x9d\xbb\xdc\xe8\xd8\xfcN\xff\xfb\x9b\x1dd'\xfcT\xe2}\x15\xf5\xc2&\x89\x82\x96\t\xe2\x1ew\xb5m\xaa\xb3|\x89\xfem\x8e\xa5|R\xe9\xf1#[x\xb2V.\xbc+\xf7\xc8_\xb6\xe03\xff\xed\xbbt\x8fT\xfcU\xefO\xcbI\xa3U\xd01\xa8Oz\xb8\xeax\x8e\x83̴s\xf9\xc2\xe3\x85<\xd9O;\x97\x94V\xba3\x99ԗI\xa6\xaa\xef&\xef)\x84pWa\xdcl\xb2x[Υ\x94\x94ep\xc5D\x85)\xce\r\xd3\xf1d\xf9(j\x8a\x88^\xb72rBxQ\xb3\x8e\xadkR\xb4s\xf7\x1c\x1b\x95\xf4̨\r\x1bfr\xc4V\x91\xd9\xc4u\xe5\xbb3\x84\xdd\xe9u\xb6Me\xb3\"\\ʻnj\n\x96\rz\x8e\xd2=s\xcf\x12ZluU\xac7\x8a\xe6s\xf0Y\a+2\x93\xc9~\xb4\xa2u\xe6p\x82\xf4\x04Ig\xe7l^ʶ\xe4\xe5\xd4\xf4\x8a#k\x12\xa9\xad\xd45X\x03\xf6\xc4\xe2\xdf\xff\xbdG\x1e\x11\xee\x1f\xd0ju\xcd\x03R\x1c\xc5\xfc\t\xcb˗O\x98\xef\xeb\xd8Nx\xcd\xe7C\x8di\x92F-eE\xbbO\b\x8aF.\xb2\x94\xd6\x1b\xa7{\x93\xe9\xc2\xc8A\xaf>\\\xc8N\xbc'g'\xcfo\xdbF\xa2>J¯\xdbp\xf4\xa7\xeb\xd3\xee\xc9:\xe2\x9dv\xa5Ml\xe0\x96\x94\xe8\x893\xd4[\x9c2U٥\xe9\x8e\xd4l\xe1v\xc3\xfa\xecy\xc9ٸ\x03}(\xac\xc8rD\x9b\xbd\xd2\x0e\x98\xb6\xc1\xb9\x9c\xa4yk\xe8\xceN\u007f\xc5R\xcfu\xe9\vk\x92\xd3\v\xab\x1c\xb4\x92\x9edHQߚ\b\xaf\xb9C\t^\xd0\xe1EnÔ(2\x1e싋\x8a\x9cId۷i\x8a-*\xa5h\x8a-\x0e\x1fϜ\xc8\xc9ˊ¹%:\xb6\xa8-#:b\xd6\t*閸\x88\x89\xb3\x96s\xdc\x12֠8n]t\xf8\xa48\xf1zӒȈ\xb8Z\xf6\x1eo\xa7a\xc1\x8cA\xc3\x04\xba\x06\x95\x86=\xa1\xd5ձ^(\x9aϑ\xbf%9-O\x90\x1b{6\x8b\xa2\xe8T\x9f\xdc\x18\xf0\nn\xe3\xccyd\xbe&\xb7dǖ\xf4\xc4G\xceRIK]\x835P\x9c\xd8\xde\xfc\xe4\xc4l\xe1\xa6P\x8dVG\x9a\a\xa4<\x8a\xad\xb7Gܾ\xd5+\x96\xa5-<\xa5\xa1\xcdԿ\xae4Oҡa\x99\xad\xc4\xc8\xc4\\^\xb4e\xf4\x18\xd9\f\x9aNa\xe9\x1br\x06\xd1\xea\xc2\xf6\xd8\xe0\xe8\xf6\x9e\x9f\x19\x10\xc4V/\x9b\xca\xc1\x1fW\x06\x95M\xd1\x03\xbf\x9f8\x84\xb4O\n֟\x04\x11̒\xf4 Z=\xa4\x92\x0en\xab\xb75\x04\xe7\xf6q?\xb1\xbc\xa4G5\xa6Iz\xe0\x84TҖ\x06$maZ\xf6q\xcb\xcc\xde\u007f\xf5\x8f/\xe8f\xa7\x91\x95\x0e\x17\xea\xf9\xfcw\a\x9b\xd8z\x80\xa4-\xccL\x8e\xe3\xc2[\x8c\xac\x86\x03t\xb3\xf3s48\xb2I\xe2\vFV\xa3\x06\x904\x00X\n\x904\x00X\n\x904\x00X\n\x904\x00X\n\x904\x00X\n\x904\x00X\n\x904\x00X\n\x904\x00X\n\x90\xb4i\x1c\xcf\xfa*\xb8\xae\\\x80Q\x89\x89\x92\xf68\xd0q\x17\xd1\xc7\x14\x15i=K\xc8¼ė\x92\x9b\x18\x83\xe7\xca\x05\x18\x9d\x98&iفN\xbb\xb3\xc1\x85\x19\xe8\x9f\xee\x8c<\x18\xff-\xe4\x91<UB h\xae\\\x80щi\x92\x96\x1d\xe8\xb4;\xbd\x1f\xb5hIX\xff-\x17\x84'b\x12\x82\xe5\xca\x05\x18\x9d\x98%iƁΨ\x914\xfb\x80\xca-\xa9\x92'\x98`\xb9r\x01F'fI\x9aq\xa0c\xa2\xa45<\xb5\xb0Nq4=\xb5\xf8a\xab\xe5\x8dG\u9fe5\xf7\x1ei\x90\xd6v\xe5\x02\x00\x83\xc4,I3\x0etڝ\x958XcB\xb7\xd6\xf2\xd4\xc2xu\xd1\xf6\xd4bl\xab\xe9\x8dG\xe9\xbf\xe5}\xe1\x01\xdf\x02\x1a\xae\\\x00`\xb0\x98%iƁ\xceU\x1a,y1\xe4\x9a\xd6\xf3\xbb#yu\xd1\xf1\xd4bd\xab\xeb\x8dG\x9ex׳\x0e.\xbd]\xb9\x00\xc0\xa01KҲ\x03\x1d\x84\x9a\x88\x98\xddE!\x1f\xaa\xf4\xfc\xeeH^]t<\xb5\x18\xd8\xea{\xe3\x91%}\x84g\xfe\xde\xdfە\v\x00\f\x1a\xb3$-;\xd0\xf1P\x13\xf2\xa1J\xcf\xef\x8e\xe4\xd5E\xc7S\x8b\x81\xad\xbe7\x1eY\xd2\xef\xf0\xef\xc8yx\xbbr\x01\x80Ac\x96\xa4\x19\a:\x95\x82\xaf\xbf\xear\x9f\t\x82\x80\x9e\xdf\x1dIz:\x9eZ\fl}{\xe3\x11\xfc\xb7t\xb3O\xcf\xf3v\xe5\x02\x00\x83\xc6,I3\x0et\xca\xe9\xf0\xdc^\xd4`\x90$\xe0h{jad\xaa\xe3\xa9\xc5\xc8V\xcf\x1b\x0f\xeb\xbfe}\xa6\xf4\xfc;\rW.\x000h̒4\xe3@\xc7\xe5\xdc\xd7\xf2ɉ\x82\x90\x0f\xd2ڞZ\x14^]\xb4=\xb5\x18\xd9jz\xe3AJ\xff-\x9f\x12\xdf\x11\x02Z\xae\\\x00`\xb0\x98&iƁN[eqQy\x93\x91}0\xd0\xf0Ԣt\x8a\xa3\xe9\xa9\xc5\xc8V\xd3\x1b\x0fR\xf8oA\xe8\x85D\xf12\x96\xb6+\x17\x00\x18$\xe6Iz$\x12\xc0g\xc0\xf7\xe7;\xe8\xd0\x1dDW.\xc0\xa8\x04$=\x10\x02(iԿ7\xad#خ\\\x80Q\bHz \x04R\xd2\x00\x10\x14@\xd2\x03\x00<\xb5\x00\xc3\x1f\x90\xf4\x00\x00O-\xc0\xf0\a$\r\x00\x96\x02$\r\x00\x96\x02$\r\x00\x96\x02$\r\x00\x96\x02$\r\x00\x96\x02$\r\x00\x96\x02$\rX\x95>#\x03k\x02\x92\x06,\x89+c\x127\xc7\xc8Ȓ\x80\xa4G\x1f\xd4s\xcf\xd0\x19\u07be\u007f\xa6NuV\x9a\xf6\xe4YS1Q\xd2\x1e\a:\xca`h\xa9\x8c\x92\xfeL\xbb}IT\xc4lS\xe6j\x9f;\xf8\xfb\x8cl\x10y\xae\x12\xe6\xae\xcc\n\xbf\xefH\xd5\xc9W\xf4\xdc\xd3>+\xf2I\x8do\a@\x80}\xff\x94G\xfa\xff'\xf3\x9e\xf3\x96\xc1q\\D\x8b\x86A\x03\xb7O#vT`\x9a\xa4e\a:l0ԔGHO<\x9b5ə\x11\xd1\xee\xcb8X\xf4\xbf\xb3\xd9ad\x83\xe9x\x89\xafj\xac\xcf\xe5_02\xf4\xa0\x9d\xaf\xc7sϲ\xc9ON\x18\xa2Ӣ\xc0\xfa\xfeY\xce-72\x91\xf0\x9c7WM\xcdV\xcdG&\xd7r5\x1a\xb1\xa3\x02\xd3$-;\xd0a\x83\xe6\xd1\xce\xe1\xee\xd9id\x15$J\xfd\x914\xaa\xe7\xcfa\x9dnc\x9f\x17l\x80F\xbe\x92\xe7\x9e\x19\x1bP\xc4P\xbb}@}\xff\xac\xe4V\x1a\x99hQ\xab#\xe9\x90?pv\xb8`\x96\xa4\x19\a:L\xd0DZ8\xff\xa7}\x01g\x00\x92F\xbd\xc9ی\f%4\xf2\x95<\xf7\xdc^\xe4\xe2\x86:1\n\xa8\xef\x9fu\xdc:#\x13-@\xd2*̒4\xe3@\x87\t\x86\x96\xf6\b\x8e\x9bPLB\xee(\x8e\xe2\xf5Ƞ\xe2\x99\x11S\x96ᱻ!\x9c\xe3V\xb6̟\x1c1\xbb\x87\t\xaa\x8c\xc5\xc7\x17\xb9&\n\x99q\x13UC\x98\x86\xbb\x1e\x84\xbe\xc8MK^/L\x90\x19\x17<\x9a\xb6\x82\xa4Ѷy\xba\xb6\xfd\x15YIK\x85ŶN\xbe\xb2\xe7\x9e\xd9+\xe7\u070e\x8f%\xbcY\xbb4\xff\x1c\tɾ\u007făW %c2S\xe4\xab\xe0I\x8e\xae\xed\xb5\x9bo\t\x17\xee\\6%b\x16\x89\x93\xcf\x1bA[\xbc\xd5 \xe9\xc1`\x94\xb7/\x18\a:L0Ĝ\xa8\xa9\xb1\t#CC͋ܺ\x9a\x1a\xf542c\u0092\xf2\xadQ\xd3\xfb\x90\xbb\xa48z\xca\xc4\xe8e\xf3\xb9O\x98\xa0\xcaZ|Ƞ\xbbh\xab\x80\xcac\xb6\x96\xbb\x1et!9\xb3\xeax\x0eO\xa5'\xbb\xe0Ѷ\x15%]\xc1w\xeb\xd9\xe69v\xd6\xeft\xe4\xe9\xe7\xcbx\xeeY7\xd1v\xa2gv\xdcQ\x9d\xd2\xfcs$$\xfb\xfe\x11\x0f^\x81\x94\x8c\xc9L\x91\xaf\x82\xad\x1c]\x99k7_sq8\x17\xb5n\xd3Dz]J>oHS\xd2=m\xd53\"\xcdZD\x99\x8eY\x92f\x1c\xe80\xc1\xd0\x13\xe1\xe9\x1aZ\x13\xefr\xae\b\x91>C\x9daL\xe7f]\x15\x97\aL\x90\xc5\xf3(\xe0\xb6V\x01\xe5擶\xbb\x9e\xecL\xac\xcf\xfe\xa5Dz\x8c\xb3\x1dm[Q\xd2\xc4\xf9\x8e\xb6m=}\xda0}\xd5Η\xf5ܳ\x81s\xa2\xab\x11䠇\xe0HH\xf6\xfd#?\aYB\xe9=ȓ\x99\"\xc8\xe2\xe4\x84q^\xbb\xf9\x90-\x12\xff\xe0Ώ\x12?E\xf8\x92\xf4\x1c<ƛ\xb8\x8c2\x19\xb3$\xcd8\xd0a}\xe9\x84\x1c\x9f\x92N\x99\xec\xee\xc1D\xd3\x05\xe3t\x9b4*3A\rZ9\x0f\x8aN\xae鮧C\xd0\xc6N\"=\xc6َ\xb6k\x1fQ\xd2U|\x87\x8e\xed\x16\xe1\x9a\xd5}\x9b\xf5\xf2e<\xf7\x94p\x91\xcbЦI=hH\x8e\x84|\xfa\xfeQz\x0frH\xa32\x13d)\xa2?\xa0z͇l\xe4,\xac\xb3\x89\x9f|J\xfa\x93}Ω0J\x0f\x06\xa3\xbc}\xc18\xd0\xf1\xf6\xa5\x13B|Jz\xbaط\xe8lo\xfa\f9^\x0ejQS.\xa0\xdcO\xd6t\xd7sV\x98\a\xd3m,\xc6َ\xb6k\x1fQ҅\xc9z\xb6\x0fS?=('K/_\xd9sO[IJj[\xebdz\xf4Cp$\xe4\xd3\xf7\x8f\xd2{\x90'3E\x90\xe5p\xa4\xa0M\xed\xe6Ct\xaaퟤ15\x9c)#\xc4p\xc0,I3\x0et\x98`\xe8\xf1)\xe9\xf9\x93OR\xe8\x14pz\x8a\x14\xcf\x04\xfdG\xd3]\xcf7\x826\xf2\x84\xd1Tr\xb6\xa3\xed\xdaG\xdc\xf1N]\xafg\xbbEpi\x9d\x9e\xa7\x97\xaf칧\f\x8f\x81s&O\xa4\xd7\xe1\x87\xe0Hȧ\xef\x1fo\xefA\x02Lp\x00\fLҰ\xe3=(\x8c\xf2\xf6\x05\xe3@\x87\t\x86\x1e\x9f\x92\xdeǕ\x90\xb7\x95\xf4&)cIk,'\x19\xb4\xdd\xf5d\xa5\xe3\x0e\xffi\"\x91\x1e\xe3lG\xdbV\x90t!\x11\xa0\xb6\xad\x10{\x90\xac\xa5\xb5\xf3E\x92\xe7\x9e\xdd\\\vj\xe0RP_t\xeb\x10\x1c\t1\xbe\u007fZ\xd7y]\x11S\x14\f\x92\x0e\x15fI\x9aq\xa0\xc3\x06C\x8a\xfbhM\x8d-\xa3\xa6\xe6\xaag\xc7۫\x17,\xe7RJ\xca2\xb8b\xd4s\xb4fJ\\M\r\xe9\xecLP\x85֦/\x83\x96\xbb\x1et.)\xadtg2\xef\xa8:\xa7p\xb6\xa3e+\xdc=\x96\xc7\xd3qR\xdb6\x97/<^\xc8\xe7\xea\xe7+y\xeei\x8bH\xd9\x1d=ŶdCx\xdb\x10\x1c\t1\xbe\u007f\xe6p3\x91\x1a)\x19\x93\x99\"_\x05\xe5\x13}\xcc\xd3\\5\xe1\x19G\xd1Ɍ\xf0\x1a\x17{\xde\xe8\xddc[kj\xbc\xf66N\x8c^o\xa0\xa6I\x9aq\xa0\xc3\x06CI\xed\x04a\xa9\xecD\xeeH\x1a\b\xf7\xba\x81m_\\T\xe4\xcc}X\xf2\x82)\xe9\xecLP\x85֥Y\x16\rw=\b]X\x93\x9c^X\xe5\xe0\xc9\xfd#\x8c\xb3\x1d\r[z\x8f7\x9f.Ny5m\xfb+\x96z\xaeK\xeb\xe4+y\uea5c\x12\xb5\xa4\xb3rJ\xa4S\xa74\u007f\x1c\t\xb1\xbe\u007f\xb6ڢ\x90\x17\x9edLf\xca|Y\xf6E\xf9\xb8-{\t9=M\x11\xf8u\ts\xde\xe8=\xde\x04\xafiS[xJC\x9b)w웎y\x92\x06\x82B_\xfbU\xdfW\x03=\x9e{\x86\x82\xb0=\xa6\xf4\xfd3'N\xcf\xda\x14ʦr\xf0Ǖ\x03\xc6(o \xf4\xb8&\x8d\x193\xc5\xe5SԂ\xe7\x9e!A%\xad\xf4\xfd\xb3a\xd8]\tnk\b\xe0\r\xe8#\b\x90\xf4\x88\x81\xf7\x83_\xfe\xd7\xff*.\x18\xf3_\xbf\xd4\xfe֨\x04\xbf\xf1v$\xe4\x8aڪi\t\x84\x1c\x90\xf4\x88A[\xa6J~\xf9\xbf\xe7\\\xbb\xf6\u007f\xff\xcf\xff\xd3\xfe֨\x04\u007f\x01GB\xc3\x19\x90\xb4\xa5\xe8\x8cL\xb9v-\xf2\xf6\x96\xe0\xde\\\v\x8e\x84\x863 iKA%=\xf1\xf6\xe6\xe0J\x1a\x18\u0380\xa4-\x85 i[ܬ&\x10\xf5h\x05$m)\x04I\x8f\x8d\xfc\xfe\r\r\xbb\xcb\xdbC\u007f\xa9\x1f0\x1f\x90\xb4\xa5\xa0\x92\x9e\xd4~\xad\xe7;aaa\xb6\xa3\xaeNP\xf5\xa8\x03$m%\xfa\xae\x12I\xcf\xc6\xe7\xe6\xfbs\xdc-c\xc3¾\xef\xec\x1c\x9d\xb7P\x8db@\xd2\x16\xa2u\xe6\xf4뱤\xb7\xe2s3\xab\xf9ڵ\x8ce\x87g\x86ŵ\x83\xa6G\x17 i\xeb\xe0\x9e\xf8\xfd\x19\xd7aI\xd7\xe2s\xb3\xfc_X\xdamxĎ\b\xf2\x05-`\xb8\x01\x92\xb6\x0e\raG\xafE`I#|nN\xe0\xffG\xf1\xff\x14[è}\xbc\xc7(\x05$m\x19\xfa6\x85\xfd\xeb\x1aYK\x13\xfe-\xfe\aI\x8f:L\x94\xb4\xe85\xa7\xa7\xd8)P\x8c\x80\xa1г\xe4\xfb\u05eeMJ\xb9\xd6\xe7\xfe\xf7\xb5\x1e\xfcߍ\xff\x13I\x87\x01\xc3\x17\xa3\x93:\bL\x93\xb4\xe45\xc7\xed<\xe9\u009c\x10\x1e\xd0oe\xaaO\xa2`\xe2\x9eo\xbbvm\xfa\x92\u007f\xff\xeb\xda\xc9\u007f\xfd\xfbZCߵk͂\xa4\xbb\x80እ$-{͡7:\xb9\x8b\xad\xff\x14\x8a\x19\x83yd\x99\xff\xb8\xe7D\xd2Ӳ\xf5I\u05f5M\x1b\xae^۰\x01\x81\xa4\x879V\x92\xb4\xdakNy\xe8\x9fS\x14r\x06\xf5\x14B\xffqϊ\xfe\xb7\x17 \xe9a\x8d\x95$\xad\xf2\x9a\xd3\xec\x1c\xa2\x13\xc5a\x84\xd2Î\xc7\x05O\xb9\xf8H\x9d\xe9\xe4\xa1;\x13\x8aQ\xab\x8d\x9b\xaa\xb0e]İ\xf8\xed\x85\xc6=sʿ\xbc\x98\x03\x92\x1e\xceXI\xd2*\xaf9%\x95>\xadG\x14\n\x0f;\x92\v\x9e\xce\xc3\xf4)\x845\xcd\xf4\xd1x\xeb\xf0\x8fZ\x86Ma\xabp\x11\xc3\xe0\xb7\x17\x1a\xf7\xccIȋ\xe8(\"\xe9gn4\xd4\xf5\xfd\xb7\x1aYx\x13F\xff\xe9\u007f\x190\xbc\xf2\xba\xf5~-3\xdf(2Q\x1d\xaeAe\x8d\xda\xef\x89\x1f|\x87\xbe\x87\xdd\xf8\x18y\xf3\xbfvV\x92\xb4\xd2kN\xab\xd3Zϔ\x91<\xec(]\xf0H\x13o\xf6\x01\xb6\xb27\x1e\xa5\x8b\x18\x11\xff\xbdи\x97\x8f\xa9\xb9\xaabwXJ\x13\xee\x8d\xe3^7\xea[\x17ǾE\xbb\x98\x91\x9d\x02}I\xbf>\xde8\xab\xb0\xb0\xb017\xdd\xf6\x94\x91\x19\xc1+\xaf\xb7\xc6^\x14\xbf\x19\\&\xe2\xe1j~\xa7Qq\xa3\xf6\xbb\xe1\xf9/\xe9\xfb\x97\xcf\xdfHޤ\xda\x19b%I+\xbd\xe6T\x96\xf8\xb6\x1eiH\x1ev\x94.x\xb4%-y\xe3Q\xba\x88\x11\xf1\xdf\vM_\xb3-\xec\xfa\x1bn\xb8\xe1{\xdf\xfb\xdeرc\xaf\xc7\\w]\x98\xad\xa4\xd5\xe7X\xea\u125fuu\xdd\xf1\xdb+aW~{\x87\x91\xa9\x8c~\xb6\xbf\xfa\x95\xeeW\x128\xf5\x95\xbf\xfe\xe1Ƿ^12\xd4*\xe8֧\xa4o\x06\x93\t9\\=4\x8eʨ\xfd¾\x14\x03_\n\x96\xb7\xfa\xf5\x1b\xd3e-I+\xbd\xe6\x14\x99\xf2X\xfe\xe0!y\xd8Q\xba\xe0і\xb4\xe4\x8dG\xf9\xf0y\x91\x01x\xa1q7\xad\x9c3+n\x96\xcc\xec\xd9K\xca\x1b\xda\xc3\xc8P\x16&vK\xa2\xef\xa7n\x1e3\xf6\x17\x1f\xe3\x0f\xcf\xde<\xe6\xa6DŽ\xbeu\xdb\x13X\x1b\x8f\xde\x12vˣX\x1c\xcf\xfeh̸\xfb\xbfԲ|t\xdcw\xc7\xd1\x14\x8f\xe1\xc0\xa3a\xaa\xfc\x1e\xfd\x81\x10\x89\x87\xb5?\x93o\u07bam옛\x9fb\x92ɦ]\x1e\x9d|y\v\x99\xa5zJ\xd4/H\xaeԃd\x16\xfc\xc4\x1dC\xca\x04\x1f\xee\xc7t(\xbd8\xf6c1\x1bO\xdd\xe8\xe5beq4\xe6\xadۮ\xbf\xee6\xb6-\xa4\xe2X\xc9\v!O픕\x16j.\xb5\x05\x8d\xf2:\x89C\xc7,I+\xbc\xe6\xb4;}\xb9\xa9\x18\x81H\xe2\xf5v\xc1S@\xc6d*ޕ6\xa5\xad\xb6\xa4\a\xe2\x85\xc6\xdd\xd6ڬ\xa0\xa5\xd5\xd5\xd9'\x8eҲ\xa4ǿ|\xf1\xbd;p\xa7{\xfe\x86g/\xbe\xf5\v\xa1\xef\x8d{K\x96\xf4\xeb?|\xfd\xe2[d=\xe8e\xf9̍/\xff\xe3\xe5\x1b\x9f\xc5\x11?x\xf5\xe2\xab7\x85)\xf3{\xd6\x13\xd9\xf5\xc6x\xfa\xcd\xcd\x0f\xfe\xfd\xca\xeb?g\x92I\xa6\x8c\x0e^\xff\xcf.\xb9D\xfd\x82\xe4J\xfd\xf4\xbfq\xaa\xb7\xc6\r)\x13r\xb8?#?6O\xfd̫Yh\x96\xca\xe2H\xd4\x0f_\xbe\xf8\x8f\xbb\xef\x96s\x97,\xf0\uf0b0\x92&|\x87N\xb9=\xb5S\xe5B^䶠Q\xde'qȘ%i\x85לVg\xbb\x81\xf9\bC\x92\xa9\xc2\x05O\\\x1cBm4\"b9\x9e'\xcf\xf0K\xd2\x03\xf3B\xd3\xe3V҃\u007f8\xbd$\xfd\x06~\xff\x9f\xb1]]?\xfe\x83\xd4\x13\xbb\xc6\\\x94'\u07b7\x10\x83\xf7\xc6iX\xfe\xf8\x19\xfc\xf2̏\xbb\xba~\xf2,\t\x84)\xf3\xa3\x91ϒrȼ\x1b\xbf_\xf7\x9e*\x99d*V\x85pqL\x97\\\xa2~Ar\xa5\xfe\xecI5\x84L\xc8\xe1\xfe\xe1\x16\xfc\xe1\x96?x\xb2\x91\xeaF\xb3T\x16\xe7\x19\x85\xffq\xa3\x9c\xbbd\xd1u\xe5\xb1\xf1]\x1e\xc6?F\x96\x00\x9eکr!/r[\xd0(\xad\x938D̒\xb4\xc2kN\xb3\xd3J\u007f-\xa4\xf0\xb0#\xb9\xe0AD\xad\x9b\xcafE\x90\x8d\xc0\x99Q\x1b6\xcc\xe4\u008b\x9a\x19[\xd6E\f\xcb\xc0\xbc\xd0h\xe0%iO`\xcc\xc7RO\xa4}\xdcc46L\x9c|zY^\xffw\xfc\xf2\xf7\xeb=\x810e~R$\x99w\x93\x88_\x8d\xbd\xfb\x89\xf7\xd8d\x92)\xf3F\xba\xbfT\xa2~Ar\xa5\xaexR\r!\x13r\xb8Wƾ\xd7\xf5\xde\xd8+\x9el\x94\xed\xa3,\x8eD\xfd\xf7\xcf\xc7*r\x97,\xf0T]\xfem\xfc\x03\x8d\xf1\xd4N\x95\xcb\x15\xb6RB\x94\xd1\xc9\x1b\x04\xa6I\x9a\xf5\x9a\xd3\xea\xf1;n\t\x94\x1ev<.x0\xee%\x91\x11qt?\xb0%.b\xe2\xac\xe5\x1c\xb7\x84\xb1e]\xc4(\x18\x90\x17\x1a\r\xc2\xf4$}=#\xe9q\xcc\x0e\xf0\x18qp\xf5\xb6\xf4S\xd2\u007f\x1e'&\xfe\xf3\x83\xb7]\xff\xa0\x81\xa4ɜY*Q\xbf U\xa54&\xde\x03Ʉ\x1e\xee\xdd\xf7w\xdd\u007f\xb7\x94\x8d\xb2}\x94ő\x97\x9f\xfc\xea\xbd//2m!Yt]\xf9-3J\xff\x96(\xd5S;\xef\\Tma-I\x03!B\xec\xa5c\xff\a\xbf\xbc\xc1\xf6ݟ0\x13o\xb2=\xe6\xe1Ǐ\x8a\x01/K퉷d\xe5\x99x\xd3\xfdnQl\u007f\xbd\x8e\x9dl2يo_\x92\xa5\xa6T\xa2~A\xaaJ\xa9\xb6\xc7\x06\x9a\t=\xdc\xd7\xc7w\x8d\u007f]\xcaF\xaa\xdbwȖ\x97\xb28\xf2r\x1d\x1e\xd8_e\xdb\xc2c\xa1\xb1\x96\xf6\xd4\xce;\x17U[\x80\xa4\x81A v\xd7;\xeex\xef\xe2\xcb\xe3پ\xfb\xea\x8d\xcfK\xdbc\xecU\x9d\x97\xaf\u007f\xe2\xe3\x8b/ߪa\xf9\xccMd\x9fI\xbd=\xe6\xb1zv\x1c\x8e\x1c\x87\x03\xe3\xdf\x10\"n}\xfe\xe2\xc5Gof\x92ɒ\x16\xd2]yO\xb8\xfe$\x95\xa8_\x90\xaaR\xf42\xd1\xe03\x11\x0ew\xfc\x83\x9e\xe1\x95=\x8cq\xcf{\xb5\x01y\xb9\xf9\xc1\x8bo\x8cg\xdaB\xb2\xe8\xf2\xa4\x95C\x9e\x8bX\u07b9\xa8\xda\x02$\r\f\x02\xb1\xbb~\xfc\x8b\xb1c~\xf4\x14\xdbw\xbb\x9e\xf9ј\x1f\x88\x17\xb1\x14\xf7^\xbc\xfa\xd3\xeb\xc6\xfc\xf4e-\xcbG\xc7}G\xbc,\xf4\x03\xf9\"\x96d\xf5\xe8M\xdf\x1d\xf7\xe0\x18a\xdeM\"\x9e\xffɘ\xb1?\xff+\x93L)ir\x97\xc8ϞR\x94\xa8_\x90\xb2R\xc2\xcd\x1c\x83\xcfD8\xdc\xfb\xbf\xeb\xb9͋=\x8cgƑկ\xa28\xf2\xf2\xc6\xcdcn\xfa-\xdb\x16Rq]\xea\xeb\xd2\xf2\xad&^\xb9\xa8\xda\x02$\r\f\x82\xb0.\u007f\x18\xcc\r\xa1Z\xe0\xd9,\x9dw\u007f9\xc6\xc8r(\xf8\u007f˥\x0e\x81:\\\x81\x9b\xa4\xbb\xc7n\"o\xfe\xd7\x0e$\r\f\x02\xff$\x1d\b~\xf1狯\xff\xf0Aa\x81\xfa\xfa\xcdF\xd6\x16≛\xc4{\xbcox\xcc\xc0R\x05H\x1a\x18\x04\xa1\x93\xf4\x13\xff9f\xfc\x83B0l\xfc\xab\xbem\x01\x02H\x1a\x18\x04\xa1\x9340P@\xd2\xc0 \x00I\x0f_@\xd2\xc0 \b\x03\x86/F'o\x10\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x8cfI\xa7pQ\U000db34c\x00`d1\x9a%\xed\xaa.\x9a\x1a\x05\xeee\x00ka\xa2\xa4E\a:\bu\x1e\xde]\xb0\xfb\xb0)ڪ\xe6,\xef\xe3\x03\x18e\x98&iɁ\x0ej/\xde\xdd\xecj\xde]lƓMj\xb9\xa3F&\x000\xa20MҲ\x03\x9d\x9a\x12\xf2 \x84\x9e\x92\x1a\xa3$A\x00$\rX\r\xb3$\xcd8Щ\x14\x9e\x12Zf\xc6\xd3\xf9AҀ\xd50KҌ\x03\x9d\xf6\xe2\xeavw{\x8d)\x13\xef\x06\xae\xda\xc8\x04\x00F\x14fI\x9au\xa0\x83\x97\xd5N\xe7>S\x9e(莚q\xd8\xd5gd\x05\x00#\a\xb3$\xcd8\xd0qW\x964\xbb\x9aK*Mq]\xb9O~\xf0\x1f\x00X\x01\xb3$\xcd8Щ\xa1\x8e\xb1\xdc%f8\x98\ue31a\xbc\xb5\xdab~\x01\x80эY\x92f\x1c\xe8\x14\b\x97\x86\x1b\n|\xd9\a\x89ZΌM9\x00\b\x1efI\x9aq\xa0#J\xfa\xa49\x92\x86\x1do\xc0Z\x98%iƁN\xb58\xf16c\xef\x19$\rX\r\xb3$\xcd8\xd0q\xbfX\xd2\xe4j*yь-\xef\xa3 i\xc0b\x98&iƁ\x8e\xbbvw\xd1\xee\xda\xd0+\xda\xed:\x99b\xb3\x96\xafz\x000O\xd2\xe63\x87\xe3\xa2ˌ\x8c\x00`d1\x9a%\xed:\tC4`9F\xb3\xa4\x01\xc0\x82\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x98(iɁN_CY\xc1\xee\xe1\xe3o\xee\\Nrr\xf6\xa9\xa5\x8dFv\x02\xf5\xa9\xc7\xf5\xbf,\xe5\x1d\xe4\xdb\xfa$\xbeT\xdb`\x1b\xcf\x1f\xd4\xfe\x06}\xee\xe0\xef\xd3\xf9*\xb0\x8c\x88J\x02~c\x9a\xa4e\a:\xa8\xbc\xe8d뉂\x13F)B\xc4Yǚ#\a\xd7\xeb\xf7b\x15Ǔ\x8e\xe8\u007fّ\x9b\xf4\b~{$1\xb7C\xf9ũ\xb3\xc2\xfb\x17\x8d\x0e\x1d\x1d\xa1\xfew6;t\xbe\n,#\xa2\x92\x80ߘ&iفNC\x01y(\u007fK\x81)~\xee\xbc\xc9\xc9\xee\xc7]u\xb3\xbf\x92F\xfd\xbe\xbe,\xccI\xea@\x1d\x899\x85\xaa\xf8\xac\xf5\x9e\x90\xaeZ\xf0\xf0\x19\"\xb5\x8c\x88J\x02\xfeb\x96\xa4\x19\a:\xe5\xfbhL\xf10\x19\xa6\xd3i\xcf>\xc7\xfb\x18|\"\x05\xd7\xcf\x00\x00\r\xafIDAT\xfd\xa70\xf7\x91\x83\xa8*'W\xad\x96\xa5\xc3I-#\xa2\x92\x80\xbf\x98%iƁ\xcen\xc1\xbf]Y\xb9\xaeqp\xf8\xd0\xc1\xf3;/\xe4\xa5'\xe6|\xcbF禞ï\xfd\xf5\xdd\xe4\xb5*+)3\xbf[a{\x90\xe7\U00062cd4'S\xf3\x8e$^\x9e\xa1_X?ϑ\x9a\xf3\x05\x9b\f\xab\xa5b=ʩ\xa0j\x91b\x8f\xf3\x02Y$\x95\xa30?3\x89\xa6B\xfd\x15YIK+\xe8\xa8\xffEnZ\xf2z՜\xd65\x91\x13\x98\xa8zr\x83\\\xb0\x84\xe2\xd8\xe4\xea\xa0\xee\xc2\xfb\x92\xb2\xdfI\xabW\xa4\x0fd%\x01\xd31KҌ\x03\x9d\xc3\xc5\xf4\t\xa1E\xbb\x8d\xd2\x04\x98ރ\a\xd33\xefI\xcbϽ\xebs6\xfa\xf3t>\xa7\xf4\xdd^\x1a\xde\xc2\xe7\xd7W\xa4.\xedgm\xbb\x1b\x93_\xf8\n}\xf5Br#\xee\xf8g\x1b\x1b\x13\xc5\x11\xecTR\xd6+\xf5\xa5\xfc^6\x19V\xcb\x17I\xdf$^\xa6j\x91b\xbb\x1b\x1b3\xb3\x1b\x1b\x1b?%\xc9\x1c|\xe6\xc1\xe3\xf3\xe8x\x98\xe7\xd8Y\xbfӑ\x87C\x17\x923\xab\x8e\xe7\xf0J\xb5\xb8\x8b\xb6\n\x14)\x1f\xd3\xc6\x14,\xa186\xb9:\x1d\xe9\xc9{\xeb\xb7\xf1|\x85\"\x83@V\x120\x1d\xb3$\xcd8\xd0\xe9,*os\xbbʜ%Fi\x02\xcfR\xfe\x91n\xd4߭\x8c\xec(\xfd\x8d\x83O&c\xefq\xbe\n\xbf\x9e\x15\xc6a\xd9vK.~\xc9\xdd\"\x9a\x8b\x92\xeeM\xcf\xe9%R\xeaP$+\xccEK7g!\xa2\x16ef\xf2\x9c6\xf5\x1b\x9cc*\x0e\xd5\xf3\xf5\x9e\xd7\xecL\\N\xffR\x95Z\xdaZ\x05\xda\x14\xb1L\xc1\n\xa4\xfa2\x05\xe7%\x93\x916\xdfK\xd2\x01\xac$`6fI\x9aq\xa0\x83\xda˝N\xe7\xd1r\x13\x9e\xec\xb7ԡ\x18\xa0%zO\xe5\x90N\x9b\x9b\xde\xfb-&m\x8b\xd2\xf6Tb7\xeaN:%~\x12%]\xcf\u007f\xe4I\xcd$\xc3jy\x85\u007f\x89\xaaE\x99\x99\xac\x16\xf2\x99.H\xb7\b\x97\x83\xeeی:\x04\xcd\xedT\xaa\xa5\x95\xf3\xa0\xf0\xf8\xc3\x14\xac@\xaa\xaf\\p\u007f\x12\xad\xeb9oI\a\xac\x92\x80\xe9\x98%iƁ\x0e\xc6\xddއ\x8aM\xf0\x89\xb54\xcb;\ueb30d|x\r\x19\xe8\x04\xd6(m\xbfM>\x82\x8e\xcc\xf3\xect\x8b\x92\xde\xcb\xf7z\xbeg\x92a\xb5t\x14~Eբ\xccL\xb9\xf3D\xd5\xf20\xfd\x06\xe5d\xe1Q\x92^\x14W\xef<Ք\v\xd4(b\x99\x82\x15H\xf5\x95\v\xfeB\xd8\xf3\xeb\xf6\x96t\xe0*\t\x98\x8dY\x92f\x1c\xe8 \xbaQ\xd6\xe24\xe1q\x9dr\xa7\x95Iͧo\x85\x99d\xcc:K\xe9P\xd9\xe6\xafA\xeb\xf3=\x1fDI\x9f\xe2?\xf4\xc40\xc9\ns\x85\x98B\xad̪\xc80*\xabeK:\xf9\x95\xe8O\xcfC\xdf\b\x9a\xcb\xf3K-L\xc1\n\xa4\xfa\xca\x05\x8b\xa3\xf4Gޒ\xa6vA\xac$\x10:̒4\xe3@\xa7ى\x17\x87W\x8b\xcd\xf0\x9f\xc3J\xbau\x830\x9f\x9d\x97F\xfas?\xf9\xaa^XS\x16\xbe\xa4\xb2}7\xf1r⻞\x0f\xa2\xa4\xbbS\xb3\xc9h\x99\x9f\xafHƨE\x91Yv6B_\xd1\bY-\x82\xc1A2\xe3\xcfJ\xc7u\xf84\xd1/\xb50\x05#\xf9(\x98\xfa2\x05\xaf\x9f\x87\xf3\xed\xcf\x13%\xed\xb1\rA%\x81\xd0a\x96\xa4\x19\a:-\xceZWCqyȽm|\xfb.\xdd\xd3\xf5\xac\x90\xe7\x88~\xa6\xe7\xf1\xa9\xa5\xf5G\x1eI\"[\xbd\x85w\xe5\x1e\xf9\xcb\x16܋\x95\xb6\xfdi9it\xde\xdd\xfbNcc\xe2\xe6F\xb2\xf7\x8dW\xd8\xf7U\xd4\v;OR\xb2or\xb3/\xe3ϗ\xb3s\xbfab\x11\x91\xc7^\\\xc4et\xb9ѱ\xf9\x9d\xfe\xf77;\x1a\xb1]._x\xbc\x90'\xfa:\x97\x94V\xba3\x99wT\x9dC\xc60\x05KG\xa1\xa8\xaf\\\xf0\xe5\xd4\xf4\x8a#k\x12\x95\xb6!\xa9$\x102L\x934\xe3@\xe7dIQ\xf9I#\xf3\xc0\xf3\xa1\xb0l\xcc\x11?\x16E9\xe9\xfbo*\n\xefKJ]C/ޠ\xfa\xecy\xc9\xd9\xf5^\xb6{\x1d\xc2%\xa3\xf7ť'\x95ȧ\xeb\xd3\xee\xc9:\xa2HV\xca\xf3dci3Oo\x9f\xf6\xc4bz\xf3\x93\x13\xb3\xcf\xd2ۧy\xc7G\xe4\xea\xf66r\xc9w\xa9\xe7\x92\xef\x855\xc9\xe9\x85U\x0e\x12k\fS\xb0\xe7(\x94\xf5\x95\v\xeeؒ\x9e\xf8\xc8YQҢmh*\t\x84\n\xf3$\r\x98\x85z{\f\xb0\x14 \xe9\xd1\aH\xdaҀ\xa4G\x1f iK\x03\x92\x1eu\\\xa8\xe7\xf3\xdf\xf5\xf9\xf7c\xc0H\x06$=\xea\xc8&\xbb]\x17\x8c\xac\x80\x91\nH\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x85I\x92\xee)v\n\x14\x93O\xae\xb2\xa2}&<\xd3\x04\x00,\x88I\x92v;O\xba0'\xe8\xb3M\\\x055-5\x05\xa0i\x00\b\x00&I\x1a5\xd1gw\xd3G\b\xf6\xd1\xd7\xc3\xc5}\x06I\x00\x000\xc6,IS\xca\xc9s\x8aPs\x01\x95w\xc1\xf0\xf1]\t\x00#\x173%M\x9f#\x88P\xa5\xe0\x13\xab܌\xe7\t\x02\x80\xd50S\xd2%\x95\xf4m\xb7\xf0\x00\xef\xc3&<\x9a\x1f\x00,\x87\x89\x92n\x15\x9f\xdc]\\K\xdfj\x8b}\x19\x03\x00\xe0\x17&J\xbaRt\x82%z\xae\xac\x0e\xb5\x9b;\x00\xb0\"&J\xbaHt(])x\xa1-\x83\xb54\x00\f\x1d\xf3$\xdd\xee\x14\xfdB4;\x89ǻ\xabN\xd8\xf1\x06\x80\xa1c\x9e\xa4[\x9d\xedB\xa0\x8f\xfaΩ\x86\xeb\xd2\x00\x10\x00̓t\xb3\xd3\xe32\xc7UP\xddZ\rw\x8f\x01@ 0Oҭ\xf2v\x98k_A\x19(\x1a\x00\x02\x81y\x92\x06\x00 \b\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\xd1ڵZA\x00\x18\x99\x98$i\xa5\x03\x1d\x84\xaa\xcd{\xa4\xc9\xdf\xecOk\x04=\x1c\xb0c\x12p\xe0\x83_\xc7\xc7.:\xb6\xe0m\x1c\xdc>\xf7\xceiw\xce݁P\x9dݾ\b\xa1\xfd\xd8\xe2\x98:]\x908\x16\xff')|~\x9a\xfd^\x1f\xa6\xbeYk\xb7\xef7\xb2\x19\x10\x81k\xa8\xd5\xd8,漑\x15\xa0\x87I\x92V8\xd0A\xa8\xcdYk\x90 x\xac\x8a\xb9\xa4\x11\xf4\xe0~\xbb.v\xc5\a\b\x9d\x99\xf6Ё\xfd+\xa8\x0e\x8e\xd9\u007f\xbd\xe7\xd0k\x0f\xd9\xeb\x90\xfb\x98=\x06\xbf\xee\xb7\x1fs\xa3\x00s\xec\x8cf\xf4\xa1\x18F\x88\xa7W\xc7h\x1a\xf9å\xbai;\x8cl\x06D\xe0\x1a곺\xba=\xf6\xb7\x8d\xac\x00=L\x924\xeb@\a!W\x89y\x92>oߨ\x11d\x89'C\xf7\xe2\xc5$\xb8\x9a\xf4ԍ\xb1\xb4\xee\xb1\xd8\xd8m_\xb5\x9a\xa4\xf3\xa3\xa3\x0e\x90\x05+\x8c,0;\x06/i\x84b\x02+i\x14Ȇ:\r\x92\x1e<fI\x9a\"8\xd0A\xd5\xce\xea\x02\xd3$\xbdZ\x1e\x99W{\x0f\xd2\x04\xdaS\x13\xb6\x93\xe0\a\xf6\x03\xb8\xd3.\xa4\xd1\v\x17\x93\x9ez\fw[\xbf{\xea\x00\x18\xb1\x92\x0eHC\x81\xa4\x87\x80\x99\x92\x16\x1d\xe8 \xb7\xdb\xf3x\xfe\xd0s~\xdaF\x8d\xa0\x02\xdaSW\xc4\u007f@\u0087p\x9f\\$\xa8m\xc5\"\xd2S\xcf/د\xee\xa9g\xa6\xd9\xed\xdbϯJ\x88y\x80< q\xff\xa2\x98\xb9\x1b\xe9\xf7\xee\xa7\xef\x8d]\xf4v\xc2!\xf48\x99\x96J+a٠nq´\xf8_\xe3\xf5\xe8\x9f\xec\x02\v\x90\x82\xafc\xec\xd2\n\xf8Ҫ\xf8\xd8\x15\xde\x13\xef\xf3+\xe2q\x16\xf8\x97\xa9\x13\a\x12\x1e\"\xb3\xf7\xc7\xed\xd3\xf6l\x9c\x1b\xb3\xf83\x95i\xccƵ\xf1w>$\xacY\xe5:\xc8h\xe6p\b\xd7\xe0\xf7h\x87]s%>І\"k\xeb\x1dbfri\x04Q\xd2z\r\x85\xd0k\xf1{\x10\xa0\x8d\x99\x92\x16\x1d\xe8\x10L\x93\xf4\xdai\x9fi\x04\x15О\xfaY\x82\xfd\x81\x1d\xa7\xe9\xa4b\xc1\xefh\xf4\xef\x16О\xba\xeb\xd7\xea\x9e\xea\u07bf?anl\xc2\xc6U\xf6\xcf\xc8\ft\xe3\xa1]\xf1\v\xb0\xb8\xbfN\x88\xdfuh\xadݾG\\NJ+a\xd9\xe0\x8c}\xd5\xfec{\xe2\xed}d]:wQ]]\x9dz\x8f\xe8L]\x9d8\xb6\x9e\x8f\x9d\xfbڟ\x16\xdbՒ~3v\xc1s\xc7v\xd8w\x11\xed\xad}s\xffC\xf6\xd3\b\xfdm\xff4{\xfc\x8e]\xb1\xeaa?ƾ`\xff\xfe\x051D\x80r\x1d\x184sp\xbf\x9d\xb0\xf6\x12\xba\xb4=\xb6Nc\xbc\x1dpC\xd5\xc5n\xf7d&\x97F\x10%\xad\xd3P\x98\x15\xf6\a\x10\xa0\x8d\x89\x92\xf68\xd0!\x98%\xe9Ϧ\xad\xd5\b*\xa1=\x15}\xfd\xdc\xc2i\xf6X26ݻ\x8aF\xaf\xba\x97\xf6\xd4K1\x97\xbc\xe7\x93\v\xec\x8b;\xf18Gt\xf1GDz(N\xb7*\x96L\xeb7\xda\xc9\xf0B\x85I\xa7͌\xc1\x9ex\xd2]\xf7\xc4\n9\xe8L\xbcEI/\x9a\x8b\x8b\xec[\xa0\x92\xb4;\xe1\x01\x1cݳ\xffk\xf2\xbbB\xea$\xe4\x12\x13\x8b\u007f[Vūs\xba\x17[\xb8\xe7.Tԁ\xcdL;\x87\x1dd\xea@\x16\xc6\xde\f\xbc\xa1V\x93\xdc\u007fGڝ-\x8d\x99xk6\x14\xe6\xfcs\xb0%\xae\x87\x89\x92\xf68\xd0!\x98%\xe9ǧ\x9d\xd7\b*\x89\xf7\\\xd9r\x1f{\xc0~H\x1a|V\b\x83\x0f\xfa\xf5.\rILj\x03\xfe\x8a\x84\x9e>L\x02\x96@\f]d\xfeM%i\xc6\xe0\xb3\xf8\x84\xc7\xf7\x9cA=B\x0e>%\xfd5\xcd\x05mWI\xfa\x90]\xde'\xff\xe7\x9e\a\x12b\x85\xa9{\f\x11\xa0\u05fa;\xe6\xf7\xe4u\x8f\xfdk\xb6\x0e,\xda9|f\xff\x00\xb9c5\xafE\r\xbc\xa1ތq#wL\x1d\t2\xa5iJZ\xa7\x92\x80\x17&J\xda\xe3@\x87`\x92\xa4/Ŭ\xd5\b\xaa\xa0=\xf5\xb4\xb0s\xb6\xe8!\xe1?\xe6!a\x89\x88\xf6/А\xb4g\x15\xbc@\\\x15\xaf\xc0R8@\"\xdc*I\xcb\x06X\xa8{V\xdck\x8f\u007fNH\xe8S\xd2g\xecT\x06j\x99\xee\x92+r:>\xe1\xe9\x03u\x8b\x17Hi\xbc%Ms\xaaÿ\x02l\x1dd\xf4rx\xe0it,\xb6\ai0\xf0\x86\xea\x8b?\x80\x0e\xd0\xc9\t[\x9a\xa6\xa4\xb5+\txc\x9e\xa4%\a:\x04\x93$\xbd\xd1~^#(\xd1G\xa3hO\x8d\u007f\x9c\xc6l\x9f\x8b\x90\xd8\xef\x16,\x16z\xaa;昷\xa4=\x1doU\xc2\x19\xca?Q\x9f \xa1\x0fdI\xd31V6@gH9_\xef\x8f\xd9#\xe5\xf0\x9a\xf7\xe2^\xc8\xe5\x9f\xc2(\xad\xde\x1e;&\x8f\xd2\xf7.$uZ\xe1K\xd2\x1b\xc9\xebk\xf6N\xb6\x0e\fz9\xfc)\xbeg\xb5z\xa8\x1ctCm\\\x81Vl$\x01\xb64\xb5\xa4\xd5\r\x05\xf8\xc4<IK\x0et\b\xe6H\xfaR\xccj\x8d\xa0\xcc\x1e2\x18\xfe\x93\xec6\xa1\xf8\x84\xafI\fQ\x9ax\xb9\x95\x8cꤧ\xa2տӗ\xf41a\xed\xb7\xfd9\xb2\x15Lz\xe3*AҸ\xf3\xf7-\x8cQ\x1a\xec\x10n\xadZDg\v\x8b\xf0\xd0vIc[Y\\K/$\xd59\x1f\xa3\x92\xa9;~\x11\x19>7nD(\x81Ԡo\x81/I'\x90u\xf7\xbd\x8b\x14u`\xd0ˡ'\xfeOw\xaa\xe7݃n\xa8\xd31\x97b\xe8\x96\x18[\x1a+i\xad\x86\u009c\xdf\x01ki=̓\xb4\xec@\xc7\xedr\x15U\xbb\xda|Z\a\x85\xa7\xe5\x91\xf9i\x8dA\x9a\xdc\xfe\xb4\xff\x8f\v\xe3\xc9X\x19o\x8f\xdf~\xec\xc0br\xa3\xe21\xfb\x03\a\xea\x0e,\xc6\x13i7\xeegnT\x17\xa3\xec\xa9}\xa7\xe9~\xf5y1\xdf\xdf\xed?@o\xbc\xb8\x14\x9f\xb0\xe7\xc0\x8a\x18*\xe9E\xf1\xcf=\xb7\xd0>\xed\x8f\x1f\xb0\x06;\xec\xb1\xdb\x0f\xe1\xe0\x9b$ݎ\x98]\xb84\xe5(\xdd\xf3v]]\xcc꺺N<\xd8\xc7$\xec\xd8~\xa7\x90\x03ñ\x98{\xf7\x1c\xdah\u007f\x8dd\xb6b\xcfs\v\xf04\xfe\xf4\xa5\xbai\xabO\xa33\xab\xa7\xd5)\xaf\xba\xc7\xd8\x1f8}lQ,\xa9\xa6\\\a\x06\xdd\x1c\x9eN\x88U\xbb/\x1b\\C\x11\xe2\x17\v\xdbvri\xc2\xddc\xbb\xea\xeaHn\x9a\r\x85y\x88\xdc`\nhb\x9e\xa4e\a:'\x84۽\xaf\xfa\xb2\x0e\x06\x97bVi\x04Y\x0e,\x88\x89}\x88\xaaf\xe1k\xdb\uf349\x17.\xe3n\x9f\x1bk\x8f%\xb7.\xbfI/\xa9\xf6-\x8cWt\xf13¢OXH\xa2c\x8b\xe3c\x17\x1d\"\xa1\u007f\xaeN\x88Y|\x86J\xfa\xfc\xa2\x98\xd8ſ\xb7\xdbײ\x06\xfb\x17\xedH\x98\x16\xbf\x88*\x1a\xb97\xde\x19\xb3\xe84R f,\xe4\xf0Н\tO\xffq\x1á\xe1\xfc\x8a\x84\u0605d\xd1\u07b7knL\xfc\x8a\xd7\xe6N[\xb4\x16\xa7\x98\xf6\x01\xb9\xa4\xad\xb4\xbdwNJ\xd8\xf8U\x82\xcc\xe5J\xca\xe8\xe6p^](\x1adC\x11v\xc5\xec\xa2\xefri\xf4\x1eoϪY\xb3\xa1h2\xf5\x06>\xe0\xc1<I\x9b\xcf\xef\xed\u007f\xd3\b\x06\x17a{lD\xe3\x8ey\xd3\xc8$\xf8<\xb4\xd8\xc8b\xd42\x9a%m\xc6_UZ@\xd2\xfb\xbd\xc7ڐ\xf3\x9c]5\xa7\x00$F\xb3\xa4\xcd`\xa4KzǛh\xf1v#\xa3\xa0\xf3Y\xfc.#\x93\xd1\vH:\xa4\x9c?fߨZ!\x8f(\xdc\xf6\x05\x8f\xc7\u007fmd\x05\x98\tH:\xa4,\";M#\xf9\xfa\xcb\xf6\xd8\xc5#\xb9\xfa\xa3\x01\x904\x00X\n\x904\x00X\n\x904\x00X\x8a\xff\x0f\xb8\x98\xba\xeaw\xacpV\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/ipcg-func.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\xaa\x00\x00\x01\xb1\b\x03\x00\x00\x00\x9d\xa2d\x9d\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x02\x04\x00\a\t\x05\n\f\b\x0e\x10\r\x13\x15\x12!# '(&+-*2319:8?@>QSPVXU,`\xae7]\xadZ\\Z8^\xae8a\xaa:b\xab;b\xac^`]<c\xad=d\xae?e\xaf@f\xb0Ag\xb2Bh\xb3Ci\xb4fgeCk\xafEj\xb5Lj\xafMk\xb0Fm\xb2Ol\xb2Ho\xb4Ip\xb5Jq\xb6molKr\xb7Ms\xb8Nt\xb9Ou\xbaPv\xbbrtqWv\xb6Xw\xb7Yx\xb8[y\xb9wyv\\{\xbbV~\xbd^|\xbdX\x80\xbf`~\xbeZ\x81\xc0`\x81\xbbb\x80\xc0}\u007f|b\x83\xbd\x80\x81\u007fc\x84\xbed\x85\xbfe\x86\xc0\x82\x84\x81f\x87\xc1\x84\x86\x83h\x88\u0085\x87\x84i\x89Æ\x88\x85j\x8a\xc4k\x8bƈ\x89\x86q\x8b\xc1r\x8d\u008a\x8c\x89s\x8e\xc3t\x8f\xc4v\x90ō\x8f\x8cw\x91Ə\x91\x8ex\x92\xc8q\x94\xc9y\x93\xc9z\x94\xcas\x96ˀ\x94Ł\x95\xc6z\x97Ǔ\x95\x92\x82\x96ǃ\x97Ȗ\x98\x95\x84\x99\xca~\x9b\xca\u007f\x9c̆\x9b̀\x9d́\x9eΈ\x9d\u0382\x9fϛ\x9d\x9a\x88\xa0˄\xa1ѝ\x9f\x9c\x8a\xa2̌\xa4\u038d\xa5Ў\xa6ѣ\xa5\xa1\x8f\xa7Ґ\xa8Ӧ\xa8\xa5\x91\xaaԘ\xabє\xac֙\xacҪ\xac\xa9\x9a\xadӛ\xaeԭ\xaf\xac\x9d\xb0֘\xb4ذ\xb2\xae\x9f\xb3ر\xb3\xb0\xa0\xb4٢\xb5۳\xb5\xb2\xb4\xb6\xb3\xa3\xb7ݝ\xb9ݨ\xb8ض\xb8\xb5\xaa\xb9ٷ\xb9\xb6\xa4\xbcڬ\xbb۹\xbb\xb8\xad\xbcܮ\xbdݯ\xbeߩ\xc0߰\xbfཿ\xbc\xab\xc2\xe1\xb1\xc1\xe1\xb6\xc1\xdc\xc0¾\xad\xc4\xe3\xb7\xc2\xdd\xc1\xc3\xc0\xb8\xc3\u07b2\xc5\u07b9\xc4\xdf\xc3\xc5º\xc5\xe0\xb4\xc7\xe1\xbb\xc7\xe2\xb6\xc9\xe3\xc6\xc8ż\xc8\xe3\xb8\xcb\xe5\xbe\xca\xe5\xc9\xcb\xc8\xc0\xcb\xe6\xba\xce\xe7\xc2\xcd\xe8\xbf\xcf\xe2\xcc\xceʼ\xd0\xe9\xc3\xce\xe9\xc7\xcf\xe4\xc8\xd0\xe6\xc3\xd3\xe6\xca\xd2\xe7\xd1\xd3\xd0\xcc\xd4\xe9\xc6\xd6\xea\xd4\xd6\xd2\xce\xd6\xeb\xcf\xd7\xec\xca\xd9\xed\xd0\xd8\xed\xcb\xdb\xee\xd7\xda\xd6\xd4\xd9\xe9\xcc\xdc\xf0\xd6\xda\xea\xd7\xdb\xeb\xda\xdc\xd9\xd2\xde\xec\xdb\xde\xda\xd9\xdd\xed\xd4\xe0\xee\xdb\xdf\xef\xde\xe0\xdd\xdc\xe0\xf0\xd6\xe2\xf0\xdd\xe1\xf2\xd7\xe3\xf2\xe1\xe3\xe0\xdf\xe3\xf3\xe3\xe5\xe2\xda\xe6\xf4\xe1\xe5\xf5\xde\xe7\xef\xe5\xe7\xe4\xdc\xe8\xf6\xe6\xe8\xe5\xdd\xe9\xf7\xe6\xe7\xf1\xe0\xe9\xf1\xe1\xea\xf2\xe8\xea\xe6\xe2\xeb\xf3\xe9\xeb\xe8\xe3\xec\xf4\xea\xec\xe9\xe5\xee\xf6\xec\xec\xf7\xec\xee\xeb\xed\xed\xf8\xe7\xef\xf8\xe8\xf0\xf9\xee\xf0\xed\xe9\xf1\xfa\xef\xf1\xee\xf0\xf0\xfb\xee\xf3\xf6\xf1\xf3\xf0\xf4\xf2\xf6\xef\xf5\xf7\xf2\xf5\xf1\xf0\xf6\xf8\xf4\xf7\xf3\xf2\xf7\xf9\xf3\xf8\xfb\xf6\xf8\xf4\xf4\xf9\xfc\xf7\xf9\xf6\xf5\xfa\xfd\xf8\xfa\xf7\xf6\xfb\xfe\xf9\xfb\xf8\xfa\xfc\xf9\xfd\xfb\xff\xf7\xfd\xff\xfb\xfd\xfa\xf8\xfe\xff\xf9\xff\xff\xfc\xff\xfb\xfe\xff\xfc\x1d\xe0k\xdb\x00\x00 \x00IDATx^\xed\x9d\tp\x14\u05f9\xef}\x93\xdc\xfb\xde]t2\xaa\xbe3\x12\xd2\x13TI\"b\xb9PzFU\xc0Ř\xb5j\"\x95)!\x97\x8b\x87\x1d+U\x02\xa2\xd8O@L \x18\xa1g\f\x97\xa4,,\x16\x13H\xbc@t\xcbv\n\xd9\xd8V\x99'{\xd8\\Pl\x97\xe0`\x85\xb2͢\xc8\x06\x83\x1fKر@\bMթw\x96\x99\x9e\xd33=\xea\x99Ѩ՟\xfa\xfbE\x91z\xce|}\xba\xc7\xfa\xe9\xcc鞦\xff\x0fQ\x04\x01\xc1CV\x05\b\xe2\fPU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80`\xa1j\x1b\x828\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x84$Tm\x988X\xcb\x1d\xf3\\\xbc\x9e\x12c\n!\xa4\xdc\xd02\x8c\xb5l\x89S\xfd\xe9\xfbq\x9e\x88\xc3H\xd6\x17\xf9ȪJ\xe2g\xa5\xb5r\xf1ͪ\xe2<\xcdW0m\xe9\xe1\x1e\xd7@\xfa\x95\xc4U}\x96\b\xfcq\xbbJ\x88dT=\xbdj\xc8\"\xd3'\xe2\xf1\x8e\xd8\xc3j\xab2\x89\xae\xea\x81i$L\xd6*\x8b\x95\x90\xfe#aU\x0fg\xc8\xdf\xe6\xc2\xf8}%B\x12\xaa\xbe_BHr\xaa>%\xf6p\xc8\xe7Vu\x82\xb0\xaa\x9f\x16\x13\x85eV\xab!\xfdEªna\xbfnj\x15\u007f\\\xbf+~_\x89\x10\xab광#G\xfeѬt\x06IR\xd5\xd6AR\xb7\x97\xad\n\x05aU\xe7\xf3U|\x13ʧ\xe4\xf1\x05-\xc1\xe9\x03b;\t\xab\xfa2\xfb=\x16\xc7\xef'QbU\x8dKҪ\xbe\x1c\x1a\x19'Y\x15\nª\x0ef?\xffן\xd8\xc2\xe7\v\xf9\xcas-VC\xfa\x8b\x84U\xfd\r\xfb5\x8e\x8d\xdfO\xa2\xf4\xa5\xaa\x13\xf9.\xf2\xc1\u007f\x8fU%'\xa4\xea\x01\xee\xe7\x9fdSIz\xfe\x1c\x91>!AU\xcbC\x03\x16\x19\xd9֖\xcd~\xc8#\xf3!l\x89\xbfw\x17\xb0wж\xd6ec\x06\xf9\x8a\x17|\x1aZ\xe3\xf3U~vT]\xf4ě\xc6\xed\xf50W\xdd3\u007fL\x8e\xa6\r\x9e\xb0H\x8837\xbc\xc5M\xfcсg\x8b\xb3\xbc\x85\xe5\xe19\xad\xd9\x06\xdbv\xf1\xd9\xf4G|\x90\\\x10n2\xab\xdbU5ԛ3\xe5U\x83\xaa\xafȧ^\xad\xaa\xaa\x9a/\x17\x8d\x1b\xfc\\8\xbcl\xa8\x967\x83\xff\x97(\x93\xad{\xf8\x06w\xc5V#}B\xdaT\xdd5R\x16\x14\xca\xc9\xecG#\xc3k<\xf5\xa5\xba\xbd\xf8\xaan\xca\n\xaf\x91\xc7\xe7\x8b\x06Uׇ\x9f\xf3K\xe1L6\xd8ֶ\x80=\x18#\xd6+<\x1dj2\xa9{\xd9+\x1fV\x86T=ͧ\xa8ު\xa8\xb3bQ\x1b\x14\xaa\xf2\xfeɣ|\xce\xee\x95{\xb1\x88-N4\xa9F\xfa\x84t\xa9\xaa\r\rW\x88\xb3Y{\x06\x13\x9dy\xea\xf6⪺K($O3\xe4\xb7\x1aUݔ\xa1w6AX\x18\xbbA\xe6\\!\xe1\xee\xbdϛ^\r\xf5\x1d[\xb7E\xef*\x93ȹ\xeas\xf2a^\xc5\xca\xc8\x11c\xf4\x06\xb9\xaa\x83DۊӼ?yN\x8b\xff\rԛT#}B\x82\xaa~\xb8\x85\x9fV-\u07b2\xe5\x9d8\xaa\x12R\xb0\xe2\x9dz\xbe\x90\xc9G\x16n\xa4\xb7zS\xfd\x04\xf6\xd3\U000e1cbd\xb8\xaaV\xb3\x1fU\xbbN\xb7n\xe2\x9d.c[\xdc4\x9e-<\xb1iӁ\xb6Os\xd9Ҙ\x86?\xfe\x8a\x1f\xe1\u05f6\x99nP\x9e\xa2\xc8< \x05\xfaq\xa8\xef\x98:!\x9a6\xff\x9d-O\b\xb3xg\xadcI\x98⥲\xab\x98\r~.\x9e\xce\x1c3\xccs@\x8c\xa5\x13x\x15\xff\xa3\x18\xd4jR\x8d\xf4\t\t\xaa\xaa\x1eV\x99\xab\x9aÏe\xc49xf\xf3\x87\xfc'\u007fW\xffr\f1\x9e\x93\x8f\xab*\u007f?\x16\xf3\xdaM?\x9e\xbf^\x1c\x17\xe9\x87U˸E\xfcd\xe9\x1f\xd9\xf05\xbc\xcdl\x83\x8c\n\"\x8f\xfd\xb9J\xda\x01\xd9wL\x1d\xf7\x99\xac\xe7OU\x91\xb0X\x9f\xf25C\x14l1ݠP\xd5\xc7\xd6\xdf\xce楙\xa1\x037>\xeeW\x99\xee\x1e\xd2\x17\xa4M\xd5gE\v\x1fX\xd8o{1\xe1\xd3FΖ\xe7^1\x9c\x89\x8d\xab*\xf7\xc5W\xf1\xf2\x81\xc8\x13\xba\xaa\xfc\xc8~\x85h\xe2\xe2\xf3\x89l\xcc\x06\x99p>\xb6\xf4\x1b\xb6\xb0\x87k\xb5Dv\x11S\xf7\xac\xbec\x875\xa2\x8f\x81\xef?\x95\x13vU{\xd3l\x83Bէd\xb1\xf8\xa3Z\xcc\xfe\n\a\x87\xfe;\xc4\xee\x1e\xd2\x17\xa4MUy\u07bd\x88\x88\xc9%\x9f\xdaVEoJ\x10W\xd5M!W\x86=\xb5\xa9U>\xa1\xab\xca=*\x9b\xcb\x19\x1e\xdaP\xcc\x06\xdb\xda\xfe\x0f[\xf0\x89\xf7o\xfe\x86>Bv\x11S\xf7c\xa2\x0f\xf2\xfcC\xaa\xda\xf0N\x9c~gѣ>\xb1\xfd\xa1\xa7M6(T\r\u007f\xb2\xc0\xf7\xb4\xb8\xad\xedU\x12:\xb3\x15\xbb{H_\xd0+U\xf9$-\xac\xaa<Q3R\x1a1\x89\xfd\x98\x1f\xbd)A\xfc3\x00\xe2\x1dY\x90/Ǩ\xb0\xaa_\x12\x03\xb5m&\x1b\x94#Zn9g4\xaf\x92\xe7\xc8b\xea\xf8\xdcy\xb1\xdc\xee$\x125\xb3lm\xe0\xbb\xc2\xeac7(T}'T\xf7%?g\xf0\xa1x\x1b\xe0\xeb\x9b\xec\x1e\xd2\x17\xf4JU~\x8e&\xac\xaat\x83\x0fU!U\x9f\x8dޔ\xa0\x87\xf3\xaa\x9b&z¿oq\xf9VX\xd5V\xa3\v\xbc)f\x83rv\xacP!\x9e\x8d\xa9\x9bH\xf4\x8f\x15B\xaa\xbe\xbc\xa8jF\xf8\x84\xc1\x01>\xb0.3٠PU\u007fk\xe7\x1f\xc5\xceoe\xb5\xde?\x99\xef\x1e\xd2\x17\xa4\xa0*\x9f\xf6\x89\xdf\xff\x97\xfc$\x8d\xa9\xaa|\xc4yB4\xb4~d8\xad\xda\xf3\xe5*\a^~B\fl\xc4\xcb\xe7\x00\xfa\x04\xc0\x17\xa9\b\x11\xabj\xb5Q\x98\xd0\\ \xa6\x8e\xf7\x19\x9as\x8e&B\xd5\x12u\x87\xf8\xd8\xfb\xac\xc9\x06\x85\xaa\xfag`\xfc\xb3\x86\x91\xaf\xe8\xeb\xc5\xee\x1e\xd2\x17\xa4\xa0\xea\xe0\x90\x1dr$3U\x95\x1fV\x15\x88S\x8c\xbf&\xdeb\xf5c\xf5\xf8\xaa\xb6n\x97\x9fK\xf1uŨ͵\x12\xc3+\u007fo\x97\xc7I[B\xba\xc4l\xf0\xcb|\x12\xc5\n\xd3:~\x12u\xa4h\xd8Ç\xf0Z\xe9\xb8\x16:\x9d\xb6\x8b\x1fj-3٠QնG\x89\xfc\x04W\n\x1a\xbb{H_\x90\x82\xaa|\xe8\x11\xf6\x89\x93<\xa6\xaa\n\x89\u007f\xc5\x1e\u007f\xce\x1b\u0087Μx\xaa\xee\xe2}D\xa6\x15\x1f\x86\xba\x17\xb3\x88\x85la0\x1f%\xdf!${\xec\x01\xb3\r\x8a\x832\xfd\x13'~\xf2\xf4\xe16\xb3:qҊ[|\xba\x8c/Նv\xb5@|\xb2\xfa\xfe\b\"7\x1d\xb3A\xa1j\xe4\xe4D躘Їb\xb1\xbb\x87\xf4\x05)\xa8\xca\x15\xf2,|\u007f\x8b_\xfc\xbeLUm\x9bƟ\xf2\xd7.*\x0e\xfd\xf2u\xb8\xaa\x85\xe5:[\xf4Q\xb5X\x18s\xb8\xf5C~r>\x8fK\xc0\xaf>͙\xff\xd4\u007f\xca)d\xf1\xab\xbb^\xe1\xdb\x11g\xdfc6\xc8ŋ\x9c\xd2\xe4\xf2\x90\xed\xa6;Ƈ@\xf2D\xc3o\xe4y\xffڶ\xf0\aq\xf9c'ɹ\a?5\x1b\xb3\xc1(U?\xcf\x15\xa5\xa1Kwcw\x0f\xe9\vRP\xf5U\x12\"\x93\x8fB檪\x1f\xac\x1a\xaeʟB\f\xd4ꪾ\xefS\x9a\xf9Ǖm\xb5z\xc9\xca\xc83Y\xc2\xfb\xe8\r\x8a\x93\xa4\x91\x8b\xbeŅ+\x95\xa6;\xf6\xa1\xbe\x99a\xb2\xef\xb6\xc3\xfa\xd5\n\x9c\"!d\xf4\x06\xa3Tm\x9b\xc7\x1f\xeb\x17p\xc5\xec\x1e\xd2\x17\xa4\xa0j\xf8\xe3\xf9\xac\xfaY$\x9e\xaam\x1f\x8d\b\xff\xf6\xaa\f\x1f\x8b\xc7U\xb5\xedͼp\xa3W\x9e\xac:,\xcf\xcbs\xd3\xeb\u0082\xe5ɋ\xb0\xa37\xc8?0\"\xcaG\r\xfc\x9cTN\xab鎽\x19\xba\xfezn\x1d\t\xff\x83\x952\xa23)\xd4I\xd4\x06\xa3U\x15\xb3\x86\xc8e\xb1ѻ\x87\xf4\x05\xa9\xa8\xda\xf6ʣ\xb9\xdea\xf3\xf6\xb4\xf5\xa0j\xdb\xe7+\xa7\f\xd6|ß\n\x9f\x8d\f\x11_ն\xd6\x15S\xf2\xbcZ\xee\x98g\xc3\xce}T>X\x1b<It\xb7g~qn\xe6\xa01\x8bBW.Eo\x90\u007f\x1f\xa3l\x85\xef,?\x19o\xb6c\a\xe6\x16y\x87\x94\xbd٦\xab\xcaF\xf4\xb9c\x06k\u07bc1\xf3\xfeS\xef\xc1\xb8\xc1hU\xdb\xf8\xf5\t\xf5\x91\x87Q\xbb\x87\xf4\x05\t\xab\x8a \xfd\v\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80`\xa1*\x828\x05T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa4]ՉdIlc\xfb\xbd\xd86+V\x90\xa7\xadJBE\tU\x9a\xd3@ʭJ\x10\x87`\x87\xaa\xc1\x95\xbe\xebf\xa5=\x93\x90\x80\xa8\xaa{\xb0C\xd5\x0eBPU\xa4\xb7\xa0\xaaV%\x88C@U\xadJ\x10\x87\xd0\x1bU?~O\xe7\xff\xea\x8dR\xd5\x06Rw\xa9\xba@+\x9a\u007f\x89\xd2\x1a\x11\xfbs\x84\xb5\xb6W\x17i\xb9e;xY=Y\xb5c\xb8o\xec)\xb5\x90\xb1\xbd\xa2@\xf3\x8d^p\x81F\vx\xe2\x99aZ\xee\x8cݦE\xc6ʝe\xf9\xbe\xf1M\x87Ȥ\xc8F\f\xab4\x90\xda\xe3\xe59\xd9\xe3_\v\x8a\a\xe5\x17\xf8\xe6\x17\xa6\xf0\xb7\x84\xd8KoT}\xe4\xefu\xfeMo\f\xabZ]@\xb2s\t\x19\xddA7W\x10R^\xd1N\xe9\x8e,\xe2}\xb8\x88\x90Ŕ[T\xed%$\xabC-\xa4\xb4\x8a\x90\x82\x92<\xf6\xedr\x94\x80M>\x92]\x92OH\x93Y\x91\xa1\xb2\x81\x90\xfc\x12\x8dTHU\xe5F\f\xab0;\xb35\xff\xa3\x1eR\x19\xe4\x0f\x1e\xce#\xf9l\xf3\xc5\x1d\x14q6\xbdQ\xf5\xcc?\xe8\xaa\x1e\xd4\x1bê\x92Ql\bl\xd2\xc8\x06}\x02ОMj\xeePڒK\x1a\xb9E\x9e\xe1M\xcd\x1b\x8c\x85\xcd\xc4LJ\xdc@6Yi\x14\xf0\xebl\xb2\xa0\x83\x06k\x89\xf7\x92I\x91Zy\xd4C\xea\x83\xf4\xf2\f\"U\x95\x1b1\xac¶8\xfc$\xa5\ar\xc9F\xf1`\xd8>J?\xd0\xc8f\x8a8\x9bި\x1a\x19V#\x83jDտ\xf0GU\xa4JW\xb5\x86\x94\x89\x8a7\xc8(n\x119F\xa3\vk2\x16\x89\x8a\x1a2\xc7(\xe0\"\xe2\x0fu\xbeޤH\xad\x9cEj\xf8\x8f\x8eaRU\xb9\x11\xc3*l\x8bG\xf9\x837H\x91x\xd0\xca\x1f\x88\xcd#\x8e\xa6W\xaa\xea\xc3jdP\xd5U-\x16\x8fV\xf1Ö\x90\xaa\x85\xe4m\xd1\xd6\xe1!\xa7\x98EE\u2061\x90ޓo\xc3\xcbȓF\x01\x8bC\xab\xb6\xb7\aM\x8a\x94ʮl)'k\x13\xaaʍ\x18Vi \x13d\x9b\x97\x1c\xd77_\x8f\x87W\x8e\xa7W\xaa\xd2\u007f\x8f\x19TuU\xe5\b\xba\x9e\xcc\b\xabz\x8bM\b\xc7\v4\xd2\xccܐ㤡\x90\x95\xeeް\xb8b(!\xb3\x8d\xaajr\xec\v\x11]\xa4T\xb6\x93̠Xh\x96\xaa\xfacWi\x90\xe3.\xf7\u007f;{ +6ꕈS靪_\xfcC\xf4\xa0\xaa\xab*G\xa9\xf5\xdcD\xa9\xeay%\x05\xb8\x91YT!\n\f\x85\xc1U\xecȉd\x94L\x88R\xf5\x0e!\xed\xfa\x06b\x8b\x94\xcaC$K.|\"U\xad\x88]\xa5\x81,\x95%\xe3\xc8\x1b\xfa\xe6QU\xe7\xd3;U\xe5\xb0\xfa#\xb5%\xae\xaa\xd7\t9\x11)3U\xb5\x96dTn\xde\u007f\x8b\xd6E\xa9\x1a$\xec\xbd:Ll\x91Ry\x82d\x18FՊ\xd8U\x1a\xc8\x02Y;\x9a\r\xee\xa8*\x1cz\xa9\xaa\x18V\xd5A5\xbe\xaat\b?\xf2紜\xec2U\xf5A6;j\xe2TGO\x00\x86\x8b\xb3T\x94\xbe=m\x95I\x91R\xf9\xc0\x1b\x9a\xab\xaeTT5\xae\x12~Ͽ\xa3\xb1\xa1\x1aU\x85C/U\xe5êaP5S\xf5\x1e!\u007f\xa3\xfc(\xbbD\x8cx\xdb\xf9)'3U/\x84\x06\xcf[\x05\xfcIU\xd5\x1a9\x93\xa5e\xa4֤H\xad\xac\x90cfW\xb1\xa2\xaaq\x95\x06\xa2\xb5\xcb-\x97PT\x15\x10\xbdU\x95\r\xab\x86A\xd5LUvT\xd4x\xa7\x8b\x1e\xf7\x9297\xd9,2\x97T\x9bO\x00\xba\x06\x91\x1a&\xf3Y?\xe1k\xa9\x02\x9e\xf6\x91e\x0fh\xb0\x8ed\x9d7)R+\x0fgx\xd6\a\xe9\xcd'\x89\xa2\xaaq\x95\x06BJ\x98\xab\xdb}\xec\xfd\x1fU\x05DoU\xa5\xffn\x1cTMU-a\a5\xcd\xe2<\xbf\xb7d8\x93\xa8#\xce\\\xb5\x9e\x90\xa1\xfe\xb1\x9e\x9cE\xe4\xe1\xe8O\xab4\x92S\x92K\xb4&\xb3\"Ce=\xff\xb4\xcaG\xc6q\xf7\xc2\x1b1\xac\xd2@\x86y3K\x86\x11RKQUH\xf4Z\xd5/\x8c\x83\xaa\xa9\xaa\xc7'zs\xde`?O\xfc\xacH\xf3\x95\xac\xe2\xd7Y\x9b\xaaJ\x9b'\r\xf1\x8e^t首\xd1n\x14\x90\x1e\xaf,\xc8\x1cR\xc1/$\x88-2V6\xfb\ay'47\xf0)Cx#\x86U\xd8\x16\x8f\x94e疵\xa8\x9bGU\x9dO\xafUu(+ȼ8\xcf\xe0\xc5T@\x19h\xaa\x96\x95\x04\xc4ωd]\x9c\nT\x15(\x03M\xd5\xf9☩c1ɽ\x1c\xa7\x02U\x05\xca@S\xf5B\x11\xc9\x1cU\xec#Y\xcd\xf1*PU\xa0\f4U\xe9͕%\xb9\xbe\x115'\xe3\x16\xa0\xaa@\x19p\xaa\"\x03\x15T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 ؤ\xea\xc5o/^\xb9ml\xba}\xe5\xe2\xb5k\xdd\xe6\xe5\b\x12\x83M\xaaF\xf8x\xed\x15\x8a\x82\"\xc9c\xaf\xaa\xf7)]\xfd\xd8_\xf9\x0f\x04I\x12{U\xa5\xfc}\x1f\xc7T$\x15\xecT\xf5\xfe\xfd\xce\xfb\xf7\x0fn\xbb\xc6~t\xa3\xafH\x92ة\xaa`u\xe99\xab\x12\x041\xc1vU\xbb\xafXU \x88\x19v\xa9\xca\xde\xf0\xbf\xd8\xf6۵kּ\xbe\x8d}[\xfb\xd6{\xdfY\xad\x81 \x06\xecR\x95\x1d\xf4\xaf}\xbct\xfa\xe4ɓ\x1fa\xff\x9f\xfe8\x9b\x06\xe0y\x00$\x19lT\xf5\x85\xc9\x1f\u007f\xf6\xe7\xcf\xfe\xcc\xf8\xec\xb3_N>\x83\xaa\"Ia\xa3\xaa/\x96\xde\xd5\x1f\xae)=C;)ڊ$\x8e\x9d\xaaN\xffB\u007f\xf4\xc2\xf43=U#H\fv\xaa:UW\x95.GU\x91$\xb1Q\xd5\xe5\x8f\xdd\xd8\xf6\xa3\x1f\xfd\x1b\xfb_\xe9\xfd\xdfN\xbf\xb8wm\xe7\xc15\xca\xf5\x00G<\x84\x90\xb9\xfa\n;\xf2\x9aL;\xb2\xa0\xde\xfbk\xb3\xe6v\x8d\x14\xf3\x9fGg\xe4\xe7Lk)\xd9mV\x838\x1b\x1bU}~&\xfd\xe5\xf7\xfe\xee\xfb\u007f\xf7\xfd\xef\xfd\xf7\xcemSo\xbf\xfe\xd8\xed?\x94*\aW]\x9f\x8c-\t\x9c\xd7W\xf8 \xfb\xed\xd8^Z\x0eŶ\x19)\xd1J̚\x83\xfb\xaa4\xf6\xe3\x90V\xde\xf4F\x05\tGh#\x90\xb0Q\xd5\x17J\xbf=\xb7m\xdb{\xec\u007f\x1fӗ\xa6\x9e\xbb\xf2Y\xf7\x95/:\xd5\x1a\xbf!<2Hc\x99\xf0\xa4I\xa3\xca\x1dO\xa5\xe7\x96\xe93u\\\xd52?\xeb5X\x85\xaaB\xc4FU\x95\xb9j\xb7\xe9\\\xd5o\x99s:~\xb6EA\v9DZL\x9f\x11\xaa\x0e\xe7\xf9\xaf\xf4(Iin\x81\xf4/v\xaaZzN\xceLٷ\xff\x98z\x86ލ>Y\x15Q\xf5\xba\x8f\x10\xcfV\xb9\xbc\xb3\xacH˟1,H\x9b\x88d\x1co\r\xbe\xf6hv\xf1\xc2\x0eJ\x9f!\xda\xc6\x05\xc5YegEq\xddPZ\xc8\x13\xa9\r\xad\xdfT\x16\xe6\xce\x12\x13\x80'\v\x8e\xf1u\xb7\xdfR{8\x92I\xc8\xd2S\x95\xc3}e]\x8d\xac\xfb:ZG\xc4\x14A/@\x1c\x81\xad\xaa\xde\xd0\x1f\xae)5\xf9\b@\x19U\x0f\x05\x02\xde:\xb1t \xa3\xf2\xed\x1d\x1b\xf3I\x17\xbd\xb3;0zZ \x108\xc1\x9b\xe7yj\xb67\xe4\x8d\x0fҿl\xcd$yu\xbfΑ\x19\xd5\xfeYt6\xefEm=\x95S\xbc\xb9\xa9\x8cpUۋ<eu{\x1ePC\x0f\x1d\x8d[\x87\x8d\x1eT\xb4\xa02\xe3\xeb[;s\x96]\xa2\x97jsw\xdeR\n\x10G`\xa7\xaa3\x9f\u007f\xe9\xc5Ռ\x17W\xbf\xf4\x93GL.\xb06N\x00|R\xd5uy]\xfc{\xae0F\x9f\x00\xbcK~Ǿ\xef'|\xe4\xd5r\xcfRZ\x99Ǜ\x83\xd9\xf5\xb4>[\x94FZ\xa7\x8cb#c\xb0\x84\xabJ\xaf\xae\x98\xa0\x91\xdcƨ\x1e\xe8x\xe2\xbfI\x837\xd9\xd2<>\x1b\xae\xfcYt\x01\xd2\xffب\xea[?}\xact\xaa\xa4\xf4\xa7?\xbf\x98\xa0\xaa\xe7\v\x87\xd7l<\x1c\x94#\xa1\xae\xea\x93#\x1et1\x86\xf2\x93[\xda\x1c\x1a\x9a\x8a\xd2#dw\xc7nr\x84\xaa\xad\xd7\xc9F\xfex\xa9\x16Z\xf5ގ2\xb2\xdd\xd8\x03\x1d\xaf}\x1dz\xb6\xc5\xd7A;\xb2Z\xa26\x818\x00\xbbTe\xdc8w\xe6\x8b0\xe7\xbe5\xb9\xb6\xdaTUz}\xc3\xecb\x92\xbf\xca8\xaa\x96\x84\xe6\xad\xfc\r^\xe3\x85R\xd5\x06\xd1\xd8@\xd5\xd6CDĮ\x8b\x82\xfd\xdf\xf0\xc5\xe0\xa4rc\x0ft\xfc\xb8\xf0V\xbb\xf2\x9bhS~0j\x13\x88\x03\xb0QUK\xa4\xaa\xb7\x96]\x15\x8fB\xaa\x1eZ̼\xb9\xbeշ\x8e?\x10\xaanf#`\xe5\x88C\x02\x9e\xa4\xae\xa8:k\xdc\xfe\xfd\xfb\xc7͢j\xeb߈Xu\x0e/(\xa8\x11}.\x19e쁎\x9f\x15\xde\aZSA+D\x95\xa1\x00\xe9\u007f\xecT\xb5\xbb\xfb~\x98n\xb3\vU\xa4\xaa\x87\xc9N\xf1(\xa4j\x1d\x11q\xe9\xfe\xeap\xc5%~t\xde,O\x8d.YI\r\xaa\x16.d\xdf\x16\x14RC\xeb\xc4\"\xe6\xfeI/_\xcc/\xe4\u007f\x06An\xa6ڃz\x12l\x8f\xf7\x82w\x0f_0\x14 \xfd\x8f\x9d\xaa\xf6Lמ\xb1%\xec\xf8>\xb0\x81\xbda?\xf8$\x10\xf0V\x05v\xde\xe4\xaaf\xd7~\xd04W\x9e-\xad\xd3\xea\x9b\xfc\xd9\xfc#\xad\xc5\x19O\xbf\xcdZߠ\x17\x02Zվ\xe0\xe1*-p\xa1\xa3\x99,\xb9C\xef\xfc\x8a4\xdfSZ鱬\xa2\xba\xa5\x83=\x99\xbf;N\xf3IAms\x93\xdfwR\xed\xa1k\x8f8\xb3\xd0.w#XXV(\x0f\xfa\xf5\x02\xc4\x118Gգ\x9e\xd0\xe4\xd0w\x82\x1e\b-o\xa0\xf4\xb5iuEZ\x81_\x9e\u05ffW3\xd87m\xbfXl\xf6\x0fɝ\xd2\xccϠ\x12\xa2\xb5f\xb3\xef\xcf\xec\xc8\xe0\xe7C\x9b\b\xc9ء\xb4Rz\xaa|\xf0\xf0\xe7~\x97\xc9\x16'l^R\x9c\x9dWq\xd2\xd0\xc3\x11\xb9\xb1\xf2\xd0~\xd4k\xf5\xa1\xa5p\x01\xe2\b\x9c\xa3*\x82\xf4\b\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xf4\xb3\xaa\x18\x12\x84$J?\xab\x1a\x01C\x82\x90\x9eq\x86\xaa\x18\x12\x84X\xe2\fU)\x86\x04!V8AU\f\tB\x12\xc0\t\xaa\n0$\b\xe9\x19Ǩ\x8a!AH\xcf\xf4\xb7\xaa\x18\x12\x84$H\u007f\xab\x8a!AH\x828@U\f\tB\x12\xc1\x01\xaabH\x10\x92\bNP5\xa1\x90\xa0\xa6G/\xc5y&U\xaeN\u009bWC\xc2\t\xaa&\x12\x12\xb4\x8a\xd4Eݓ\xb7\xd7a)\xc1U\x9e\xd8\xfbQa\u038bcq\x80\xaa\x16!A\x82\x06\xcfkQ+\xa6#,e{fCt\x13\xe6\xbc8\x16\a\xa8j\x11\x12\xc4i\xd3\x16\x87\x17/\xfb\xe5]$\xd3\x12\x96\xb2L;\x1bӆ9/\x0e\xc5\x01\xaaZ\x86\x04Q:\xb7@O\x8f8F\x8e\x89\x9fi\tK\xb9S\x10{Oj\xccyq(\x0eP\xd52$\x88>\x18\xb4H.4\x8c~\xf7\x049\xb1}\xf4\xfaT\xc3R\x94\x02\xd1\xe12_L\x82\n\xe6\xbc8\x14'\xa8j\x15\x12D\x0f\xcb{\xa4\xf3_7y\x98\x94\x90Y\xe7S\rKQ\nĚ\xbb\xc9\x1e\x1a\x05\xe6\xbc8\x14G\xa8j\x11\x12D\xb7\x93\x93\xe1\xc5f\x8dh\U000969e9\x86\xa5D\n\x18gI\xcca\x13\xe6\xbc8\x14'\xa8j\x15\x12\xc4\xdetC\xb7\x94\xbe\xba@+$\x85\xde\xe7\xfe&\x1f\xa6\x14\x96\x12)\xa0\\\xd5F\x1a\x05\xe6\xbc8\x14\a\xa8j\x19\x12D\xf7\x91O\xe4ª\xfc\r\xc7\xc9_\x1a\xf2W\xf6\",%R@\xf9p\x15sr\x13s^\x1cJ\u007f\xabJ\x13\b\t\xa2\x1dZH\x18\xfa\x80\x1e#\xc7\xe9\x83`/\xc2R\x94\x02\xaeN\xccI%\xccyq(\x0eP5\x01f\x8d\xd2\x0f+\xce\xe7\xca\x13\xf4)\x87\xa5\xa8\xa7\x9a\x82\xc5\xe1\x04\x00ھ\xb2M.`\u038bCq\x82\xaaV!A\x94\x9e\xf0\xc4|P\x99ZX\x8a\xb1\x80\xd6\x13\xfd\x83\xa7\n2\x83\xff\xc0\x9c\x17\xc7\xe2\x04U\x13`\x997zN\x99ZX\x8a\xb1`\xa7\xef9\xbd\xbf\xcdy\x1b\xf8\x0f\xccyq,@T\r\xce\xd7\x1a\xadj\x92\xa6Q\x9b\xdbeU\x838\x06 \xaa\xd2`\xfd\xd0t\x1fY\\-X\x89'\xd6\x01\x01EU\xc4\xf5\xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\x0eU\x15\x93W\x90h\x1c\xaaj\x04L^A$\xceV\x15\x93W\x10\x1dg\xabJ1y\x05\t\xe3dU1y\x05Qp\xb2\xaa\x02L^A$\x8eW\x15\x93W\x10\x89SU\xc5\xe4\x15$\n\xa7\xaa\x8a\xc9+H\x14\x0eV\x15\x93W\x10\x15\a\xab\x8a\xc9+\x88\x8a\x93UM(y\x05q\vNV5\x91\xe4\x15\f\tr\r\x0eV5\x91\xe4\x15\xdbB\x82\xd2\xd0/\xd2;\x1c\xacj\x02\xc9+\xf6\x85\x04\xa5\xa5_\xa478X\xd5\x04\x92Wl\f\tJK\xbfH/p\xb0\xaa\xd6\xc9+v\x86\x04\xa5\xa5_\xa4\x178YU\xcb\xe4\x15;C\x82R\xeb\x17I\x1f\x8eV\xd5*y\xc5ΐ\xa0\xd4\xfaE҇\x93U\xb5L^\xb15$(\xd5~\x914\xe1`U\xad\x93Wl\r\t\xa2)\xf6\x8b\xa4\t\xa7\xaaJ\x13I^\xb13$(\xe5~\x914\xe1`U\xad\xb13$(\xe5~\x914\xe1dU\xad\x93Wl\f\tJ\xb9_$M8YUk\xec\v\tJ\xb1_$}\xc0Vվ\x90\xa0\x14\xfbE\xd2\apU1$\xc8=\x00W\x15C\x82\xdc\x03tU\x11׀\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10`\xaaڍ!A\xee\x03\xa6\xaa\xf7)}i&\x86\x04\xb9\v\x98\xaa2:\xa3\xc2\x02\x91\x81\x0eLU\xd9;\xff\xde\u05ef\xe1\x04\xc0U\xc0T\x15'\x00.\x04\xa6\xaa\x14'\x00\xee\x03\xa6\xaa8\x01p!0U\xc5\t\x80\v\x81\xa9*\xc5\t\x80\xfb\x80\xa9\xaa\x9c\x00tw\xd2\xee\xfb\xfc\v\x87W7\x00S\xd5\xd0\x04\x00q\x130Uet\xde\xe8y(Ő\xa0\x81\x06LU\xf95\x00o\xdd\xdf\xfbR\xe7\xde\xd5\xec\xeb\xee\xc1\xb51\x15\xb6\x85\x04U\x11B\xb2NŶ\xab\xfc\xad:\xdf7\x03o\x83\xd1K`\xaa\xca\xefi\xfd\x93\xef^\x9fy[|\xdd\xd8\xf6\x93\xe8\x02\xfbB\x82\xce\x06\x02\xeb·y\x8d\x87\xbf`\xc3\x1c\xdf\xf5\x9ek\x10+`\xaaʸ\xfb\x1d\xbd\xf6\xd7\xd0\u05cdsQO\xda\x18\x12D\xf9}\x83{V\xf5*i\xa0\xc1\xe8\xfb\xb5\"\xc9\x02SUq\x06\xe0J\xfc\xe7m\f\t\xa2֪\x9e\xea\xddF\x11\tLU\xc5\x19\x80\xaf\xba\xef\xc69YegH\x10UT\r\xae\x1f\x975v\x9d\x98\x94^\xae\x1c2t\xe1\xc2!ٍ\x0f\x86ț\xad/\x88]\x0fI\n\x98\xaaҞ?\x02\xb03$\x88*\xaa\xceіn_\xaaU\xb1\xa5\a\x0f\x17\xac\xab\xf5\xfa6\x97\xd5\xd3Á\xad\xa4.\x10\xb8\x10\xbb\x1e\x92\x140U\xb5\xb8\x06\xc0\u0590\xa0\x88\xaaͤ9\xfc\xbd\x91\x1c\xa1t\x1d9.\xdaq\x02\x90\x16`\xaajq\r\x80\xcd!AaU畈\x1f\x0f\xb3auq.[8\x19R\x14UM\v0U\xa5=O\x00\xec\f\t\xa2\x11U'\xc9\x1b\xad\x97O\xa4\xb4>\xe32\x1f_\xe5\x11\x1d\xaa\x9a\x16`\xaaj1\x01\xb03$\x88FT\x9d;\x82{\x1e\x1c>\x87ү=e_\x1f\x19=I\x9e\xf6GU\xd3\x02LU\xad.\x02\xb41$\x88FT\xdd.&\xb7[\xf9\x1c\xe3\x10\xc9'\xc4\xff\x8d|\x1eUM\v0U\xa5\x16\x17\x01\xda\x18\x12t\x9e\u007fZU\x1f\b\xf0\tm\xa5g\xf1\xbb\x8b=\x95l\xe9\x90w\xc7\xf6\xc07\xa23y\x06`\x1f~\xae\xda[`\xaaj\xf9\xaf\x00\xec\v\t\x9a\x13\x9a\xd7\xf2\xd3\a\xc1\x86\x92\xac\x12q^u\xb7\xc6۴i\xc7\xe8\xbd\\\xf1t\xe6\t\x8a\xf4\x0e\x98\xaaZM\x00\xfa;$\xe8Rv\xf5\xa5\xae\xae\xeb\a*\x06\xe3'\xffi\x03\xa6\xaa\xd4\xf2_\x01\xf4oHPS\xae\xac\f\xe6c\xccZڀ\xa9\xaa\xe5\x04\xa0\x9f9䑧\xa9\x8ey\x0e[T\"\t\x03SU\xcb\t@?\x13\x9c\xeb\xabnli\xac\xf6U':\x0e#\x96\xc0T\x95ZN\x00\xfa\x99`SY\xa1VX\xf6.\x9a\x9a>`\xaa\xea\xf4\t\x00\xd2\a\xc0T\xd5\xe9\x13\x00\xa4\x0f\x80\xa9*u\xfa\x04\x00I?0U\xc5\t\x80\v\x81\xa9*N\x00\\\bLU)N\x00\xdc\a\xaa\x8a\x00\x01\xa6\xaa8Wu!0UŹ\xaa\v\x81\xa9*\xc5\t\x80\xfb\x00\xa6\xea\xb6\xce+w;\xef\xdfg_{_\xbf\xc2\u007fܧ\xf7\xef\xde\xed\xbck\xb5\x1e\x02\x1f`\xaa\ue95d\xfc\a{\xe7\xff\x8f\xd238\x01p\x15\xc0T\xedԗ\xae\x9c\x89,#n\x00\x98\xaa\xfc\xa0\xff\xe0\x1fV\xbf\xb0|\xf9\xf3\xbf\\\xbe|\xf9\v\xbf\u007f\xeb6\x9e\ap\t\xd0Te\xef\xf9k\x1e/e̔ߧ\x9e\xc3i\x80K\x00\xa8\xea\v\x93\xf7~u\xe6\xab\xef\xe8\xc53_}\xf5\xfcd\x9c\xb1\xba\x05\x80\xaa\xbeX\xfa\x1d[x\xef\x17\xfc\xe1\x9a\xd23\xddw1\xb6\xc2\x15@Tu\xfa\x17l\xe1_\x1e\xda\xcb\x1e-\x9f~\xc6j\rd\x80\x00RU\xae\xe7\xffx\x88\v\x1b_U\x8c\xad\x18h\x00Tu\xf9\xcc\xdb\u007f\xf8\xd7\x1f\xfe\xb7\xef\xfd\xf3\xbf\xfe\xcf\xfb\xafO\xbd\xf2\xf1\x8b\x9d\a_\x8a\xa9\xb3-\xb6\"\x01\x8e\x97e\x17T\xb6\x14\xa4\xfbO\xc7m\x00T\xf5\xf9\x99ݿ\xfc\xc1\xf7\xbf\xf7\xd0\x0f~\xf0\x8f\x9doM\xbd\U00047677\xfb3\xb6\u009a\xe6\xec\t\x1b\xb7\x96\x10\x82\xf7W\xe9\x1d\x00U}\xb1\xf4ܕ\x83\a\u007f\xf8\xfd\xb5\a\xffLWO\xff\xea\xc6W\xf4\xf6\xb7QU\xf6\xc6V\xf4\xcc՜\x8a{\x94\xde\x19\x85\xaa\xf6\x12\x88\xaaN\xfd\x8c-\xfc\xf0!6K\xed^^j:W\xb57\xb6\xa2g\x16\xfb\xfe\x1f\xffQ\x8f\xaa\xf6\x12\x88\xaa\x96^d\v\xa5\xffą]=\xdd\xecd\x95\x8d\xb1\x15\xcf\x10m\xe3\x82⬲\xb3T\xed\xb7\x96u\xb3\x95neߗ\xd1Q?\x13\x85\x97\xeb\xef)\xb9\x16\xcaj\x86\x1e\x90\xf8\x80T\xf5\x9a\xfe\xf0%ӋVl\x8c\xad\xf8\xcb\xd6L\x92W\xf7\xeb\x9c\nC\xbf\x97\x9e~\x94usk\xf7\x94\xca\xcb\xf7<\xe1\xbb\vR%\xd7BY\xcd\xd0\x03\x12\x1f\x88\xaa>\xfe\x8b\xe5\xcf?\xbf\xe6\xf7\xec\xdb\xf2\xc7\x1f1\xbb\xc0\xda\xd6\xd8\n-\xf7,[-ϸ\xdak\xc5\u2e52\xd7h\xbb2\xe5Pr-\x94\xd5\xd4E$>\x00U\xdd\xf6\U000d93d5J\x1e\xfb\xf9/\xae\x98\xa8jkl\x856\x87\xf2\x1b\xaf\x1bW;\xe2\xb9\xd7\xf1\xda\xf5.\xed\b}\x90\x19\x19U\x95\\\ve5u\x11\x89\x0f4U\x19w\xaf\\\xbc\xf8\xed\xb7\xd7\xee\xb2o\xdf^\x89\xcc\x05\x14l\x8d\xad\x10\xb9\x03B4e\xb5{\x99G\xebɲ\x13\x1e6?\r\xcdU\x1f4\x1br-\x94\xd5\xd4E$>\x00U\xa5\xe2R\xc05?\xbd\xe2\x8c؊\x88h\xeaj\xc5[\xfdS\x8a\x9b\xf84`\xb1Ot\xd3H.\xa9\xb9\x16\xa8j\xd2\x00T\xb5\xbb\xb3\xf3Fg\xe7O'\xef\xed\xbcq\xbf\xd3\xfcB\x15;c+\"\xa2\xa9\xab=]\xa35\x93g\xf8\xec\xf7jN\x05;\x98\v\xfa\x87\x1br-Pդ\x01\xa8\xaa\xe4\xf6\x95\x1e.\xa9\xb6/\xb6\xe2B@\xab\xda\x17<\\\xa5\xf1dJ}5JWf\xe5\x04G\xfbV\xf0\x92\xe6\xacI\xbfk*\xcb\xe43\a=\xd7BY\xcd\xd0\x03\x12\x1f\x98\xaavR\xba\xf6\u007f\x9f\xa1\xf1\xffɊm\xb1\x15\xcf\xf0t\x8a\xd6l\xf6\xfd\x19e5J\x0f\xe5\xd6\xd2U\xd9\xfbE\xe9\xf1\xb2\xac\xfc\x8aV\xbe\xa4\xe7Z(\xab\x19{@\xe2\x02Sջ\x94\xb2\t\x00\x8d\xff\x0fU\xfb9\xb6\x02\xe9\x03`\xaaJ-&\x00\xfd\x1d[\x81\xf4\x010U\xc5\x1b\x01\xb9\x10\x98\xaa⍀\\\bLU)\xde\b\xc8}\xc0T\x15'\x00.\x04\xa6\xaa8\x01p!0U\xa58\x01p\x1f0U\xc5\t\x80\v\x81\xa9*N\x00\\\bLU)N\x00\xdc\a\xaa\x8a\x00\x01\xa6\xaa8Wu!0UŹ\xaa\v\x81\xa9*\xc5\t\x80\xfb\x00\xa6*\xc6V\xb8\x17`\xaabl\x85{\x01\xa6*\xc6V\xb8\x17`\xaabl\x85{\x81\xa6*\xc6V\xb8\x16\x80\xaabl\x85;\x01\xa8*\xc6V\xb8\x13\x88\xaabl\x85+\x01\xa9j_\xc7V`@\x85\x13\x01\xa8j\x8a\xb1\x15I\x90r@\x05҇\x00T5\xb5؊\xe4H-\xa0\x02\xe9K\x00\xaa\x9aZlE\x92\xa4\x12P\x81\xf4)\x10UM)\xb6\"IR\t\xa8@\xfa\x14\x88\xaa\xa6\x14[A\xe9\xe9Y\xf9Z\xc1\x8cohb\xe9\x111\x01\x15\x94\xee,+\xd2\xf2g\f\x13\xf7HM8\xf8\x02I\x17 UM%\xb6\x82\xb6d\x8f[\xb5\xa3\x8e\xf0{\xfd%\x92\x1e\x11\x13PA\x0fdT\xbe\xbdcc>\xe1\xb7XK<\xf8\x02I\x17\x10UM)\xb6\xa2\xa3\xa8\xec\x1e\x1bo\x1b\xaf&\x98\x1e\x11\x1bP\xb1.\x8fK\xba.7\x98l\xf0\x05\x92\x16\x00\xaa\x9aZlE39\x1c~:\xa1\xf4\x88\u0600\x8a\xf3\x85\xc3k6\x1e\x0e\xf2<\xa1\xe4\x82/\x90\xb4\x00MU\x9ajlE=\xd1'\x8e\t\xa5G\x98\x04T\\\xdf0\xbb\x98\xe4\xaf\n&\x1b|\x81\xa4\x05\x80\xaaҔb+vD\ue35ePzDl@š\xc5l\xb5\xeb[}\xeb\x92\r\xbe@\xd2\x02@US\x8b\xad\xb8U\xe0\xe7o\xdd5\xf3\x13K\x8f0\t\xa8\xa8\x13\x93[\xea\xafN6\xf8\x02I\v\x00U\x95$\x1b[A[\xbc\x0foh\xae!\x9biB\xe9\x11\xb1\x01\x15L\xd5\xec\xda\x0f\x9a\xe6\x12>\x17M<\xf8\x02I\x170UM!\xb6\x82ғ\xb3\x87\x0e\x9a(\xaeC\xb1N\x8f0\t\xa8\xa0\xafM\xab+\xd2\n\xfc-\xe2A\xc2\xc1\x17H\xba\x80\xa9j_\xc7V`@\x85\x03\x81\xa9*\xed\xdb\xd8\n\f\xa8p\"0U\xc5\x1b\x01\xb9\x10\x98\xaa⍀\\\bLU)\xde\b\xc8}\xc0T\x15'\x00.\x04\xa6\xaa8\x01p!0U\xa58\x01p\x1f0U\xc5\t\x80\v\x81\xa9*N\x00\\\bLU)N\x00\xdc\aXU\x11\xb7\x01SU6I\xfdxm\xfc\xebU\x91\x81\bLUq\xae\xeaB`\xaaJq\xae\xea>`\xaa\x8a'\xab\\\bLUq\x02\xe0B`\xaaJq\x02\xe0>`\xaa\x8a\x13\x00\x17\x02SU\x9c\x00\xb8\x10\x98\xaaR\x9c\x00\xb8\x0f\x98\xaa\xca\t@w'\xed\xbeϿpxu\x030U\rM\x00\x107\x01SUF獞\x87R\x8c\xad\x18h\xc0T\x95_\x03\xf0\xd6\xfd\xbd/u\xee];\xee\x1e\\\x1bS\xd1/\xb1\x15Gg\xe4\xe7Lk)\x89\xbd[\x06\x92\x06`\xaa\xca\xef\xb2\xfa\x93\xef^\x9fy[|\xdd\xe8\xdf؊\x96\xf0-\x83\x0ei\xe5MoT\x10y\xbb*\xbdռ\x16I\x1a\x98\xaa2\xee~G\xaf\xfd5\xf4u\xe3\\ԓ\xb6\xc6VLx2\xb4P\xe6g\x03\xe6\xac֍\x00\x00\aLIDATy\xb0J\xaa\xaa\xb7\x9a\xd7\"I\x03SUq\x06\xe0J\xfc\xe7m\x8d\xad\xd0\xef\x048|\t\xff~\x944\x19Z\xcdk\x91\xa4\x81\xa9\xaa8\x03\xf0U\xf7\xdd8'\xabl\x8c\xadh\n\xdd\xf3\x97\xdf\x0e\xf8\xc9\x02\xfeW\x11\xdc~\xcb\xd0zsv\xa1VT~\x84\x1ak1\xd7\"i`\xaaJ{\xfe\b\xc0\xc6؊;\xbb\xc5M+\x03'Xc{\x91\xa7\xacn\x0f\xbf\x8b\xab\xda\xfa.\xa9ni,\xf7\xec7\xb6b\xaeE\xd2\xc0T\xd5\xe2\x1a\x00\x9bc+\xf47\xf5\xab+&h$\xb7\x91\x1aZ;\x1ao\xb11\xb4\xa4\xc2؊\xb9\x16I\x03SU\x8bk\x00l\x8e\xadP\xe7\x9f\xf7v\x94\x89\xbba+\xad\x97ו\x8d\xc8!r\x9bz+\xe6Z$\rLUi\xcf\x13\x00\x9bc+\xc2\xfa\xed\xe7\xf3`\x1a\x94\xddGZ\v\x8a\x165\x05\xfcQ\xaab\xaeE\xd2\xc0T\xd5b\x02`sl\x05\xd7o\xf3ה\x16\x88\xc4\n\xbad\x94\xa1\xb5x\"\xff\x1b\x99\xa5\xa8\xca[1\xd7\"i`\xaaju\x11\xa0\xad\xb1\x15~?\xa5\x97xC~\xe1U\xbe\xa6L\\\xd1[\x8b\xf8\xc3\xe0X\xa9\xaaފ\xb9\x16I\x03SUjq\x11\xa0}\xb1\x15\xbc]\xabo\xf2g\xb3?\x88|RP\xdb\xdc\xe4\xf7\x9d4\xb4֑\xd9\xebV\x8cg\x13\x87}j+\xe6Z$\rLU-\xff\x15\x80m\xb1\x15\x8c{5\x83}\xd3\xf6\xb3\x85\t\x9b\x97\x14g\xe7U\x9c4\xb6\x06\xebGkyOn\x1e\xa5\xf9\xd5V̵H\x1a\x98\xaaZM\x000\xb6b\x00\x02SUj\xf9\xaf\x000\xb6b\xc0\x01SU\xcb\t\x002\xf0\x80\xa9\xaa\xe5\x04\x00\x19x\xc0T\x95ZN\x00\x90\x01\aLUq\x02\xe0B`\xaa\x8a\x13\x00\x17\x02SU\x8a\x13\x00\xf7\x01SU\x9c\x00\xb8\x10\x98\xaa\xe2\x04\xc0\x85\xc0T\x95\xe2\x04\xc0}\xa0\xaa\b\x10`\xaa\x8asU\x17\x02SU\x9c\xab\xba\x10\x98\xaaR\x9c\x00\xb8\x0f\x98\xaa\xe2\x04\xc0\x85\xc0T\x15'\x00.\x04\xa6\xaa\x14'\x00\xee\x03\xa6\xaa8\x01p!0U\xc5\t\x80\v\x81\xa9*\xc5\t\x80\xfb\x80\xa9*\xc6V\xb8\x10\x98\xaabl\x85\v\x81\xa9*\xed\xdb\xd8\n\x10\xb8.[\x03\xac\xaa\a\xdf\xeb>\xf8\xdbN\xf9\xf5_\xbf\x8fy:\xb1؊\xe6\f\xe2\xd9G?\xf1\x10\xdfu\xabRA\xbdW\u07b5\xa5\x8a\x10\x92u*ܺ#\xaf\ai\x8exXm\xe4~\u007f=\xd6&E\xdcl\x8d\xf0N\x0e4`\xaa\xca\x06\xd4_L\xbe\xb1\x96}=¾\xae\xbd\xfe\xf3\xe8\x02=\xb6\xa2眈\x8e\xb7Ɏ\a\xb4cԄ\x04\xd3$J4y멳\x81\xc0\xba\xf0\xdd\x06)\xfd ;\xfaV\xac\n]\x9f\x8c-\t\x9c\xd7\x1f\x9a֦\x18f\x11'[#\xbc\x93ɑ\xe2>\xd8\bLU\xad\x88\xc4VX\xe4D\xb4\x93[\x94\xd6\x0e\x89\xa8\xd4#w<\x95\x9e\xf0\xfd\x01\xf7GT\xa5=\x8f\xdf\xfc\x96j\x11\xccjS\r\xb30\xcd\xd6Pw2\tR\xdd\a\xfb\x18\x98\xaaFb+,r\"\xb8\xaa͙-=\xd6Dh!\x87H\xb8VU\xb5g\x8c\xaa\x9a\x91j\x98\x85i\xb6\x86\xba\x93I\x90\xea>\xd8ǀT5\x1c[aȉ\xd0c+\x9e!\x99\rՅ\x83\xcb\xf9\\\x93\xa9ڞ\xbbB\xae\xa5\x04I\xe8\x8bj-\xa5uCiamh\x1baU\xaf\xfb\b\xf1\x88ۤ7\xb2-\xd5\xd1:\"\x82\xab\x94\xce\"\xaaFj\x95\f\f\xf30\vC\x8a\x86\xdez$\x93\x90\xa5\xa7*\x87\xfb\xca\xe4-\xb5L\xb25ԝ\x8c\x04u\xa8\x99\x1d&\xaf\xcd\xf8\x1fʡ\fHUñ\x15\x86\x9c\b=\xb6\x82\aT\f[\xb1bX\xd61\xaeꥒA\xf7\xe4ZJ\x90\x84\xbe\xa8\xd62\xe9f\xd1\xd9a\xef\xf4Q\xf5P \xe0\x15w\x1e\xbe\xb53g\xd9%z\xa96w\xe7-Cgʨ\xaa\xd7*\x19\x18\xe6a\x16\x86\x14\r\xbd\xb5\xa3q\xeb\xb0у\x8a\x16Tf|-z\x89\xcd\xd6PwR\t\xeaP\x16\xcd^\x9ba\x1f\x9cʀTU\x89\xad\x88\xa4GDb+\xa86\xfc&\x1b\xe2\x8a&rU\x9f\x1eU\xb0N\x14(A\x12j\xa6D\xa4\x96\x06\xb3\xebi}vh\xb2\xa9N\x00|\xa1\x9bd\xcf\xe3\xf3\xbdʟ\x19;\x8b\x9a\x00\x84j\x95\f\x8c8a\x16\x91\x14\rcH\x06\xf1ߤ\xc1\x9b\xb2>6[C\xd9I\xe5\x15+\x8bq^\x1bN\x00\xfa\a=\xb6B\xf9\r(\xb1\x15T\x1et\xad#W\x99\xaa\xbe㛇\x88_\xbc\x12$\xa1fJDj\xe9\x11\xb2\xbbc79\"\xfb0S\xb5\x85\xbd\x1fwd\xb5\x18;3WU\xc9\xc0\x88\x13f\x11I\xd10\x86dh_G:\x8b\xcd\xd6PvRy\xc5\xcab\x9c׆\xaa\xf6\x0f\xfb\"\x1a\xe9\xbf\x01%\xb6B\xdeJ\x9d\x06\xc8!\xa6\xeaV\xdaU,R\xfc\x94 \t5S\"RK\x1bDc\xe8\x04\x91\x99\xaa]\xf9M\xb4)?h\xec\xcc\\U%\x03#N\x98E\xe4~\xefƐ\fu>i\x92\xad\x11\xd9I\xe5\x15+\x8bq^\x1b\xaa\xda?Db+\"9\x11Jl\x05\xd5\xe6\xf3\xef\x1b\xc9My\xb2\xaa\xd9\xcbOV)A\x12j\xa6D\xa4\x96\xce\x1a\xb7\u007f\xff\xfeq\xb3d\x1ff\xaaҚ\nZ!\xb2+\xd4\x1e\xa4\xaa\xb7\x96]Uk\x95\f\x8c8a\x16\x11U\x8d!\x19\xb3h\x84\xd8l\re'\x95W\xac,\xc6ym\x91}p,\x03RU%\xb6BωPb+\xa8\x96\xcf~\xc3wF\xf8C\xe7U\x83\x93x\x82\x95\x12$\xa1fJDji\xe1B\xf6mA\xa1\xec\xd8T\xd5=\xde\v^q\xa0\xa3\xf6 U=Lv\xaa\xb5J\x06F\x9c0\x8b\x88\xaa\x86\x88\vu\xf43\xc9\xd6PvRy\xc5\xcab\x9c\xd7\x16\xd9\a\xc720U\x8d\xc4VDr\"\x94\xd8\n\x8d\x8ck\xdc<:\xf7$\xedh\xe2\x9fVѷ3\xb6\xdf3\x04I(\x8b\x91\xdaf\xb2\xe4\x0e\xbd\xf3+\xd2|\x8f\x9e\xe7\x9fV\xd5\a\x02l\x10z\xf0\t;\xaa\xaf\n\xec\x14\xf3\xdd`aY\xa1\xfc#\xd1{\xe8\xda3\xb6\x84\x1d[\a6\x90\x80Z\xabf`\x98\x85Y\x18R4\x94\xceđzx&\x1e\x9b\xad\xa1\xee\xa4\xfa\x8a\x95E\xb3\xd7f\xd8\a\xa720U\x8d\xc4V(9\x11\x91\xd8\nm\xe1ܜ\xc2\xca\v|\x88\xe1\xd7\x00\xd0i$\x83\x0f\x91J\x90DdQ\xafݑ\xc1O\x986\x11\x92\xb1\x83\xce\tM\xf8\xd8\x11\xff\x01\x8f\\\x94\xd1\x16\xf5Z}h\x0f\xc2=\x1c\r=O|'\xd4ZC\x06\x86I\x98\x851E#\xdczDv\x10\x1aKM\xb25ԝT_\xb1\xbah\xf2ڌ\xfb\xe0P\x06\xa8\xaa=\xc7VD\xa6\xb2\xd6$Sk/\xbd\xcf\xd6p\xeek3c\x80\xaa\xdaslE2\xbf\xa2djm%\r\xd9\x1a\x8e}m\xa6\fTU{$\x99_Q2\xb5Ѐ\xf5\xda\\\xa8\xea7\xe2\x88ŪJ\x92L-4\xa0\xbd6\x17\xaa*\x8eX\xdaiB$S\v\rh\xafͅ\xaa\"0AU\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\xc2\xff\amu\xa3\x1c\xa2\xebff\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/ipcg-pkg.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\xf0\x00\x00\x03\xc6\b\x03\x00\x00\x00\xb2,^L\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x02\x04\x00\t\v\a\r\x0f\f\x10\x12\x0f\x13\x15\x12\x1b\x1d\x1a !\x1f!#!$%#&(&+-*/1.2416859:8<=;>@=AB@DFCFHEJKIOQNQSPTVSWYV,`\xae7]\xad8^\xae[]Z8a\xaa:b\xab;b\xac_`^<c\xad=d\xae?e\xaf@g\xb1Bh\xb3egdDi\xb4Ck\xafFk\xb6Lj\xafhjgNk\xb1Fn\xb2Ho\xb4Pm\xb2kmjIp\xb5Kr\xb6nomMs\xb8Nt\xb9Ou\xbaPv\xbbrtqXv\xb6Yx\xb8vwuZy\xb9[z\xbaxyw]{\xbbV~\xbd_}\xbeY\x80\xbf`\x81\xbbb\x80\xc0[\x82\xc1~\x80}b\x83\xbdc\x84\xbe\x81\x83\x80e\x85\xc0g\x87\u0084\x86\x83\x85\x87\x84i\x89Æ\x88\x85j\x8aŇ\x89\x86\x88\x8a\x87q\x8c\xc1\x89\x8b\x88s\x8eË\x8d\x8at\x8f\xc4v\x90ō\x8f\x8cw\x91Ǐ\x91\x8eq\x94\xc9y\x93ɑ\x93\x90z\x94ʀ\x94Ł\x95Ɠ\x95\x92{\x98ǂ\x96ǃ\x98ɖ\x98\x95\u007f\x9cˆ\x9a˘\x9a\x97\x80\x9d͈\x9d\u0382\x9fϜ\x9e\x9a\x88\xa0˄\xa1ў\xa0\x9d\x8a\xa2̋\xa3Ρ\xa3\xa0\x8d\xa5ώ\xa6я\xa7Ҥ\xa6\xa3\x90\xa8ӑ\xa9ԧ\xa9\xa5\x92\xabՔ\xac֩\xab\xa8\x98\xacѪ\xac\xa9\x9a\xadӛ\xafԭ\xaf\xab\xae\xb0\xad\x9d\xb1֘\xb4ذ\xb2\xaf\x9f\xb3ء\xb4ڲ\xb4\xb1\xb3\xb5\xb2\xa2\xb6ܣ\xb7ݝ\xb9ݵ\xb7\xb4\xa9\xb8ٶ\xb8\xb5\xa3\xbb٫\xbaڸ\xba\xb7\xac\xbbۦ\xbdܹ\xbb\xb8\xad\xbcܮ\xbdݯ\xbeߩ\xc1\u07fd\xbf\xbb\xb0\xc0\xe0\xab\xc2\xe1\xb2\xc1\xe2\xbf\xc1\xbe\xad\xc4\xe3\xb7\xc2\xdd\xc1ÿ\xb2\xc5\xde\xc2\xc4\xc1\xb9\xc4\xdf\xc3\xc5º\xc5\xe0\xb4\xc7\xe0\xbb\xc7\xe2\xb6\xc9\xe3\xbc\xc8\xe3\xc6\xc9ſ\xca\xe5\xb9\xcd\xe6\xc9\xcc\xc8\xc1\xcc\xe7\xc2\xcd\xe9\xbc\xcf\xe9\xbf\xcf\xe2\xcd\xcf\xcc\xc7\xcf\xe4\xc8\xd0\xe6\xc2\xd2\xe6\xca\xd1\xe7\xcb\xd3\xe9\xc6\xd5\xe9\xd2\xd4\xd1\xce\xd6\xeb\xc9\xd9\xed\xd5\xd8\xd4\xd0\xd8\xed\xcb\xdb\xee\xd4\xd9\xe9\xd8\xda\xd6\xcc\xdc\xf0\xd6\xda\xea\xd7\xdb\xeb\xda\xdc\xd9\xd1\xdd\xeb\xd8\xdc\xec\xd9\xdd\xed\xdc\xdf\xdb\xd4\xe0\xee\xdb\xdf\xef\xde\xe0\xdd\xdd\xe1\xf1\xe0\xe2\xdf\xd7\xe3\xf1\xd9\xe5\xf4\xdf\xe4\xf4\xe3\xe5\xe2\xde\xe6\xef\xe5\xe7\xe4\xdc\xe8\xf6\xdd\xe9\xf7\xe6\xe7\xf1\xe0\xe9\xf1\xe7\xe9\xe6\xe8\xea\xe7\xe2\xeb\xf3\xe9\xeb\xe8\xe3\xec\xf4\xeb\xed\xea\xe5\xee\xf6\xec\xed\xf7\xe7\xef\xf8\xed\xef\xeb\xe8\xf0\xf9\xee\xf0\xed\xf0\xf0\xfb\xf0\xf2\xef\xee\xf3\xf6\xf1\xf3\xf0\xf4\xf2\xf6\xf2\xf4\xf1\xef\xf5\xf7\xf0\xf6\xf8\xf4\xf6\xf3\xf2\xf7\xf9\xf3\xf8\xfb\xf6\xf8\xf4\xf7\xf9\xf6\xf5\xfa\xfd\xf8\xfa\xf7\xf6\xfb\xfe\xf9\xfb\xf8\xfa\xfc\xf9\xfd\xfb\xff\xf7\xfd\xff\xfb\xfd\xfa\xf8\xfe\xff\xf9\xff\xff\xfc\xff\xfb\xfe\xff\xfc\x9fIc\x17\x00\x00 \x00IDATx^\xed\xbd\vlT\xe7\x9d\xff\x9dn\xbb\u007f\x92\xf4\xbe\xffM[\x1e\a\x9d\xe0\x91c\xaf\x16\xd9kհuJ\x9b8\xf0&\u0080\x18\xe3\x80l(\xb7֊X\x87\xb0\x15\x97\x10\x93FXd^BH߄\x05\x8aCK\x92%\x1b\xe3\xd5\xca.V\xc1ZHF@P$\xccE\xa4)I\x1b\xc0\t!\\\x82\x13\b66c\xec\x91~z\xcfs\xce\\\xce̜\xb9ٞ\xe7\xfc\xec\xf9~\x82f\x9e9\xf3\x9ccW\xfd\xcc\xf1\xf7\x9c\x999\xdf;\b\x80,\xe2\x8ed\x13\x00\x18M@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U$\x12\xbe\x03\x80\xd1\x06\x84\aY\x05\x84\aY\x05\x84\aY\x05\x84\aY\x05\x84\aY\x05\x84\aY\x05\x84\aY\x05\x84\aYEj\xc2\xe7\n!\xfe\xdfx\x9b\xf8\xf3\x9f\xe2=\x93\x16%\xfa\xcf\xf8\xafd\x93\"\b\xae\x91\xfe\x9aI\x90\x1b\xfc\xefd\x93\xc0\x88d\xc8\u009f\xd98\xe1i\xfbg\xd2$}m!<H\x9b\xa1\n\xff\xa72! <\x181\fU\xf89\x02\u0083\x11\x04\x84\xb7\x01\u008f^ \xbc\rq\x84?\xfa\xefQ\xe0E1\xf2HO\xf8B!r;\xfeZ\xffP^\xee\x03\xab\xfe\xac?\xae\x15\x01^\x95\xb3\x8e\xfe\xfb\x03\xae\xf1\xc5U\x01\xf7\xfe\xaa/\xfeYG}\xb1V0\xe7L̊:g\xfe\xc3]8>\xc75\xf1\x17\u007f4\x1f\xc7j\xfb\xd7\x17\xdd\x05Zn\xc9/\xfe\xa7#\xf1\x1a\xb1k\x1e\xae-\x19\x9f_\xfej\xc73\xfa3\x9e\xa8_%f3\x9a\x10\x85\x1dG\x97M\xd4\xd7\xf8}x\xc3\xff\xfd7\xcfC\xae\xdc\xc9O\xbfo\xd9\xec\x83\"\x02\xedp\a\x18i\xa4/\xfc\xe1\u007f5\xff\xef.>\x1c%\xfc+\xae\xc0\x03\xb7\xa1\xb4a\xd9*\xf9\xb8<vŎ\x8e??\x1c\x12g\x85\xf13b\xb4}\xeb_\x83\x13~\xf5\xb7\x84kĬ\xf9jn`\xbd:\x11\x16>\xf8\xab\xc4lF\n\xff?\xf9撪\xbf\x067\xbc\xad\xcc\\2\xe9\x84e\xbb\"\x82E\x1d`đ\xb6\xf0Zq\xf0\xffow\xa4\xf0\xaf\x8e\r\x99\xf0\xa8\xbe\x1f5,\xcb3\x96=\x1f\xbbbGG\x95\b\xf3\x9frA\xb4\xb6\x87\xf3\xc3\x13j\x13\xae\x11\xbd\xe6\x1f\xb5\xe0\xb4\t\"$|\xe8W\x89ٌ>;//\xb8dAp\xc3\xc1W\xaf\x98g\xd9\xf2\xcf,\xebb\a?\"I[x}w\xe8\xf9\xe3\x169\x18\xf7玷^\x9d\xaa\x0f~\xf1\xea\xab':\xfe,\xfd|h\xdb\x1f\u007f#\xdd\xd1%3,\xd3'=T\x92s\"vŎ\xff\x95\xf7\xab\xff\xf8\xa7\x8dr\xb5_ɟ\x11\xad\xedt\xfd\xf1\xf8e\xafnyT\xbf\xcfy+\xd1\x1a\xd1k> \xd7\\\xf5\xc7\xff2\xd5\xf6D\xfe*\xb1\x9b1^\x1e\xf9O\xbf\xea1^\x91\xc1\r\x8a\xe2\x8d\u007f\xfa\xddD\xb9%K\xa8\x89\xd8\xc5\xff\xa2\x03\x8c<\xd2\x17>O\xee\xd8\xfe(\xff\x1f\x97ﰆ\x0eZ\xeb\xf5\xc1\x032\x10\xfcQߕN\xec\bX\x96\xab\xcf\xd9k\xb7\xe2\x9f~55\xcfH\x14\x1ea\x04\x8d\x18m\xdf\n\xda\xf7\xb7\x87\xf4\xc1\xb2DkD\xad\xf9?rM#\x8d\xd7ȑ'\xf2W\x89\u074c\x16\xfc\xddNH\xe3݁\r\xe6\x1d\r\xfe\x12\xd67\x92-\xbbx\xec\xe0G$\xe9\v\xff\xefƒ\xbc\x80d!\xe1˅\x11\x18t\xa4\xa0o\x05,\xfbU`\x03\xb1+\xea\xc8\xe0\xd3\xf1\xbc\xfe\xb8L\x0e\xa2\xb4\x95Ǜ\x0f\x19\xa3\xffz\xea\xf7A\xb7\xec\u05c8Zs\xb5\xfep\xb21\xfa\xf3x\x11\x16>\xf8\xab\xc4lF\n\xff\x94\xb1|\xa3>r\x9d17h\xa4\xa8\x8e\t\x91\x9b\xee\xf8\xbd\b\x81\x04?\"I_\xf8\xff0\x96H'\xe4\x91jHx)re\xadD\xe6\x80\xdf\x05,\xfb]`\x03\xb1+\xea\xbc\xff\xdf\xf5s\xfeI\xcez(\xf8\x84ŭ\xaa\x90t\x16\xec\u05c8Z\xb32\xbc\xa6<>\xf5D\xfd*1\x9b\x91\u009b'l\x0e\xcbe\x87\xcd\r\x9a\xbf\xed\xc4\xf0ok2Y\x04\x18\x87\x1d\xfc\x88$}\xe1M\xb5\xfeUD\n\xff7\x11A}\xc0\xb2\xc0\x99?\x9b\x15;~W\x1e:\xb6|X>\x8e\xd2V\xfe\xc5X\xd5\x11A\xbc5l\xd6\f\xbc5\xe0\x16aჿJ\xccf\xe4#\xd3^\xe3\u007fğ\xac/\xca\aD\x94\xf0\xbf\x0f\xae\xfa\x8b\x0e0\x12I_x\xf3ݖ\xa0\tA\xe1\xff*\"x:\xb0\xe4\xad\xc0\x06bV<Si\xcc+\xf9\x85<\xd1\x13O\xf8\u007f\xef\xb0\x10\u007f\x8d\xa85\xe5Q\xeejsh\x15\xfe\xadx\x9b\xd1BO\x1a\xf3\xf6\x9a\x1b\x8c\xfc\x9f\x19&\xb0\x8b\x1f\xf7V\a\x18\x89\f\x97\xf0Ɣ\x88w\x1e\r{\x82\u007f\xf7cV\x94Ǹ\xf9\x1bOtt\xfc\xa7>\xf8\u007f\xe4\x13Q\xda\xce\x13\xc1\xbd\xe8\xfbo\x19\xa7\xe1\xe3\xafa\x13i\x02\x81]\x1ecz\"\u007f\x95\xd8\xcdH\xe1\x8d\xf3\x93\x11\x91&\x9e\xf0\xbf\x17\x06\v:\xc0\x88d8\x847\x8e\xf8\xe4\xa1j\xbd\xf1\xd4\u007f\x9bj%\x16^\xaah\xc4\xe4\xff\xd0\a\x8fʁ\xcdAk\xa1qt\xf9[1\xfe\x81\xdaDkD\xad\xb9J\u007fXl\xacyX\x9e{\x8f\x12>v3Rx\xf3\x05\xf2\xa2>\xca\xefH,\xbc\xb9\x8b\xc7\x0e~\xa42T\xe1\xe7\x89@\xf2\x90\xe7F\xfeI\xbe\xc5\xfaG!\\\x0f\x1f\rXv4\xb0\x81\x98\x15\xf3\x83&UF\xeb\x1b\xe0-\xb9\xfao\xf4\xc1_'\x9bB\xc6_#jM\xe3\xcc\xe73\xfa\xe0}\x19\x8bB\xc2\a~\x95\xd8\xcdH\xe15\x99\xf0\xff,7TՑD\xf8W\xe4\xc6~\xd1\x01F&C\x15\xfeW\xfa}ު_\xfdw\xc7Q9g\xf2\u007f\x1e\xfe}a@\xa4\xc4\xc2˻\u007f}\xab\xe3\xf0/\xe4,\xbb\xb34\xc6\x1bO\xc2\xedyZ\xce\x14\xff\x9bh\x8d\xe85\x8d\x8f\xbc\xcc\xd9Xo~4!J\xf8\xd8\xcd\x18\x87\xb0\xe3\x97m\xab\x97\xdb1\x8em\x13\n\u007f\xe6\x01\xf3\x8d00\"\x19\xaa\xf0\x1e\x11\xb4j\xa3\b\xe1\x92>$\x16\xfe\x19c\xe2xs~\xb1|\"Z[\xebG\v\x96u$Z#z\xcd?\x05&\x89q\x05\"F\xf8\xd8\xcdH\xe1s\x83?\xe9W\xc1\r\xc7\x15^\xa6\xf8_t\x80\x11\xcaP\x85?a~\nE\x1a\xe9\tZS`\x9c\x01L,\xfc_\xa7\x9bssV\xffk`Z\xb4\xb6\x1doM\nlO\xd4\x1a\x9f͉\xbbF̚\xaf\x98\xbf\x89\xf6[\xb9\xca\xf3\x91\xbfJ\xecf\xa4\U0002f598K\x17\x19\xc7lj\x85?\xf3\x00v\xf0#\x97\xa1\n\xdf\xf1VU\xbe\xf6O\xe5\xc6\xf0\xf0\x8a\x9f\xe5\x8f\xcb{\xe8i\xf3\U000ff245\xef8\xe3yȥ\x15\xff\xea-\xe3\x03hu\x1d6\xdav\xfcu\xe3\xf4\u007f\xd2r'\xfe*\xf0\xde~\xdc5b\xd7|\xebW\xc5\xda?\xcd\xfb_#\x16\xfd\u007fQ\xbfJ\xccf\x8cӒ\u007f\xfe\xf7\x12-\u007fz\xc0\xed\xc4\xc2w\xfc\xce\xfay20\xb2HM\xf8\x11\xc5\xdf\xfe\x16\x1a\xcawZ\xff3\xc1T\x83\xf0y\xf8\x149s\xb4\x03\x8cTF\xa1\xf0\u007f\xcc)x\xa8r\x9b\x1c\xfdY此\x1f\x01H[x0\x82\x19\x85\u009f\xc8\x11\xf2\xbd\xa5?\xfd\xe9?\xe4{\x03\x0f$\x9b\x0e\u1ccaQ(\xbc\xf1\xde@\x88\xdf'\x9b\r\u1cca\xd1(\xfc\x9f\xcbC\xba\x8f\xfbM\xb2\xc9\x10>\xbb\x18\x8d\xc2wt\xbc\xfa\x8b\a\xf24-\xff\xa1e\xa9\x88\f\u1cc9\xd1)<\x00q\x80\xf0 \xab\x80\xf0 \xab\x80\xf0 \xab\x80\xf0 \xabH$<\x00\xa3\x0e\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n5\xc2_\xbe\xfcygw\xe4\xa2\xee\xce\xcb_}9`?\x1d\x80L\xa1F\xf80\a\xb7w\x124\a\x8e\xa1T\xf8>\xa2Ms?\x96w\x008\x83R\xe1I&\x19\xec߁\x83(\x14\xbe\xaf\xcf\xd7\xd7w|ϗ\xfa\xdd\x00\xac\aΠPx\x83\x97\x1e\xbb\x98l\n\x00\x99C\xb5\xf0\x03\x9d\xc9f\x00\x90A\x14\t\xafG\x98\xd3{\xfe\xb0}\xeb\xe67\x9b\xb7oݺ\xbdy\xdf\xcddk\x00\x90\t\x14\t\xdfG\xb4}\xfe\xac\x99\xd3fL\x93̜_q\x11\xe7j\x80\x13\xa8\x13~ô\x83\xa7\xdf;\xfd\x9e\xce\xe9\xd3k\xa6\x9d\x83\xf0\xc0\t\x14\n?\xbb7\xf4pk\xc59\xf2\x11\x9c\a\xcaQ(\xfc̳\xa1G\x1bf\x9eK4\x1b\x80L\xa1P\xf8\x19!\xe1i}X~\x00T\xa2N\xf8\xf5s\xbb\xf7\xfc\xf8\xc7?\xd1\xff\xab\xe8{}\xe6\xe7G\xb6\xfb\x8eoU\U0007969f\x8e\x193\xe6\xee\xe3\xc9f\x81,A\x9d\xf0\xeb\xaai\xcd\u05fe\xf6w\xfa\u007f\xdf\xf25\xcf\xe8~cn\xf7\xeeY6\x87\xae\x9d\t\xc2\xce\xee\xb7\xe3?\x17\x97\x0f\x9b\x9bW\x8e\xd9c\f\xcf\xe1M\x80\xacG\x9d\xf0\x1bf_\xbeؼgߞ}\xcd\ai\U000cc2dd\xa7\a:?\xf4E\xcf\x1bX\xfb\xcd\xfb\xec\xd67\xf9\xc1\x8f\xe3?\x97\x88}\x01\xe1\xef\xfb\xe6\xda\xcc\xffE\x01\xacQ'\xfc\v3N\a\x1f\r\xc4\xcb\xf0\a\u007f0\xe6\xfe\x0fm\x9f1\xb8\xe7_\xe2?\x97\x88\xa0\xf0g\xef\x1f\U000c30c9\xa7\x82Q\x8e:\xe17̺h&v\xfdfӌs\xd4\x1bsZ\xb2sƝ\xdf\xddn\x0e\xd7\xfd\xf0\xee\u007f\x98\xd1Mt\xe4\xce1c\xee\xa7\xef\x8d\x19\xf3\xcdޭcL\ue258pP\x9f0\xf7\xf8O\xbew\xf7}\xbeG\xc6ܹv\xda?\xdc}\x9f|\xc5t\xfe\xcbw\xee\xfa\xee\xfd\a\x03\x1b\x0e\nO\xb4\xfd\xbbwNC\xae\xc9f\x14\n?;\xfc\x9d\xa7\xcd\x156\xe9}\xf3w\xee\x9c\xfd\x959\xfc\xf9\x9d\x8fl_\xf9\xed{\xfa\xa8o\xcf\xc2;\xf7к;\xd7\x1d\xa4\xaf\x9a\x9b\xff\xe1G\xcd\xcd\xcd\xc7#&\xdcܰ\xfe{\xff\xf0\xcd\xefM\xfbɝ\xa7\x8f\xac\xbfs̷\x17>\xf9\xcd\u007f֟\xdf>\xe6\xe7\xbb7\xdc\u007f\xe7>ssa\xe1\xe9\xab\xd9w~{S\xf4O\x06كB\xe1\xab\xd7m~a\x93\xce\v\x9b6\xff\xf2\x91د\x81<2枃\x81\xe1\xf61ϒ\xd4\xf49\xf9\xe0\xa7?\xbc\xf8\xbd\xc7\xcd\xe5\xa1H\x131\xe1\x9e1\xf7\xe9;m\xb9\u07fe\xeb\x9b\xfa\xde\xfd'\xdf\xd6G\xdd\x1b\xbe\x94\xcf\xfc\xb39\xdd\"\xbc\xfe7\xe1\x9e1\xd3\bd+\xea\x84o~\xfc\xb1\x8a\x19&\x15\x8f?\xf9y\x8c\xf0\xcf\xde\xf5\xadu\x81\u13ff\xef\x93|\xf7\xa7\xf2\xc1\xcd{\xbe}\u007f`yH\xf8\x88\t\xf7\xdc\x15<8\xb8K>\x9e\u007f\x97\x1c^\\s\xdf\xf7\xbf\x19\x88?\x91¯\xfb\xd6\xddk\td+\x8a\x84\xd7\xe9\xbex6\xc4\xc5\xcb6gK\x8e\xdf7\xe6\x87\a\x8d\xd1=\x81\xb8n\xee\xa07\x8di\x0e\xcc\b\t\x1f1\xe1\x9e\x1f\x04\xb7p\xd7|\xfdf\xa1\x14~߷\xbf;\xeb\xa5\xe6{c\x85?\xf2\xc31\xf7\x87\x0e\x9eA\xf6\xa1N\xf8\x14x\xe9;wΒQ\xe4'\xdf\u007f\xdb\xc0\xf8\xae\xc8\xd9\xef\xcc\xfd\xdee\xf3yC\xf8gOGM\b\x9f\xbb\xb9k!\x05\x84\xff\xbf?\x94\a\f\xff\x12-\xbc\x9e\xe0\x83\x87\xc5 ;Q(\xfc\xc0@_\x90\x818\x1f\x1b\xeb\x9cq\xe7w^'z}\xcc\x06\xf9h\xae\x8c\xee\xbe\x1fV\xd3\xcf\xef3\xe7\xdf{/\xd1\xc7\xf29\xeb\x04[\xe1\xbf+\x97\xf5\xdd\x13%\xfc\x9b\u07fds\xd6W\x04\xb2\x19\x85§\xc4\xc1\x1fIUg\xdf\xf9\xe3\x176\xfft\xccz\xba\xd9\xfcȷ?\xa4\xf7\xbe9\xadY~\xd4r\xfe]On\xbe\xef\xee\xb3\xd6\t\xbe=ƹ\x9b\xf7\xf4eg\x9b\xef\xfc\xe9\x1ez\xfb\xa7w6\x9f\xa5\x85c\xfee\xcd\xe3\xf7\x8c\xf9ֿ\xed\xd1\x177\xaf\x1c\xf3\xeb\xe6f\xfd\x0fÿ\xfc\xe8`\xc2\x1f\x0eF?܄\x0f\xf0\xfa\xbd\xdf\xfa\xe6\x8f\xfe w\xe5c\xc6L\xa3Gƌ\xb9s\xb7\xbe\xb4\xf7\x91o\xdd\xfd\xa3}\x11\x13\xe4y\xf81\xf2\\\xbd<ͣO;r\xb7~\xfb\b\xf5\xfd\xfa\x1f\xee\xfa\xf6\x8f\x9f\xfd\xfe]\xf7\x1a\x9f\xa5\x91\f\xf2]Z0\xba`*<\x00\x99\x01\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x82\x8b\xf0\xbe\xa8VK\x002\x02\v\xe1\a\x88\x8e\xbc\xf1\xa5\x82\xcb\ue06c\x87\x85\xf0}D\x9b\xabQg\t\x14\xc0BxB\xa4\x01\x8apV\xf8=\xbe\xce^\x9fQgy\xf0\xcdNy\xd7G}\xbd\xbd\xbeps\x02\x00Ë\xb3\xc2\x1f!\xe3r\xaa\xb2\xa1{6Jp\x80\x02\x9c\x15>|\xf5\xe0\xces1W\x12\x06`\xf8qVxyb\xe6\xf8\xeeM\x1b\x9e[\xff\xec\xda\xf5ϭ\xdf\xf0zs7\xceՀL\xe2\xb0\xf0z\x8aٺp\xf6c\xb3fUϟ=k\xd6c\xd53Pg\t2\x8a\xf3\xc2o\x98v\xe4\xfc\xd9\xf37\xe9\xf2\xd9\xf3\xe7\x9fE\x9d%\xc8,\f\x84\xaf\x90\xad\xdc\xfbVʇ[+\xce\r\xc4^7\x1e\x80a\xc3y\xe1_\x98)\x1b\f~t\xc7A\xfd\xd1s\xa8\xb3\x04\x99\xc5y\xe1\xcd\xfe\xd6\xfb\uf437\xa8\xb3\x04\x19\xc6y\xe1\xd7\xcf\xed\xde}\u07fdw\u007f\xed\a\xf7\xfd\xbc\xef\x8d\x19\x9d\a7\xf8\x8eo\x8e\x9a\xb5e\xfco\xe5\xddr\x91\xd3d\xb3\r\x00R\xc7y\xe1\xd7U\x0f\xac\xfd\xc6\xd7\xff\xee\x8eo|\xe3;\xb2\xcerwu\xf7\x9e_F\xcd*\xd3\xca\xe4\xdd\x05\xaf\xe6\xb1\xd9\x06\x00\xa9\xe3\xbc\xf0\x1b*.v\x1e?~\xef\u05f7\x1f\u007f\x8f^\x9ay\xbe\xfb<u_\x8e\x9cԕS\x93\xd3e\x8c <\x18\"\xce\vo\xd6Y\xde+3\xfc\xc0\xfaYv\x19\xde+\x8e\x89\x03\xc6\b\u0083!\xe2\xbc\xf0\x1bf\xc9\x1d\xfa\xac\xefI\xed7ʹ;-\xe9)\xa6b\xd3tm\xc5\x13\xc5\xf9Ug\xe4\xd0[Y\xa2\x15\xcd)\xf1\x13\x00i\xc0@\xf8\x8a/C\x0fm\xeb,ɽ\x88\x16\xbb\x8d\x91&\xa645\x96\xb9N\x11\x1d\x1d\xbb\xb4e\xff\xce\"q;f6\x00\t` \xfc\xfc5\xeb\x9f]\xb7\xf5\xf5\xe7\x9e]\xb7~\xbeM\x9d%\xf9][\xe8e\x97\xb1+\xd7&\xf7\x10\xf5\x94\x96\x135\x14H\xd5\x1b\xf2\xb1\x87\ai\xe1\xbc\xf0{\x9e\xac\x9e;{vEE\xc5\xec\xd9s\x9f\\\xd9\x19+\xfcIq\xa8\xe7\x908)\x87\xda3\xf2v\x87\xb8F\x9f\x15O\\\xb1\xf3\x84\xbf?z2\x00\tqXx\x9d\xde\xce\xcb:_\xf5~\xae\xdfv\xdaU\x8em\x13\x92mrh\x1e\xb4\xea\a\xb1D\xd7w,\x9e,\x8a6b\x0f\x0f\xd2\xc2y\xe1\xc9\xf8\x90\xf0\xe6\xc7;\xe3}0xє\xf6\xf6\xf6)\x8b\xe4P[%ow\x8a\x1b\xd4^\xa7\xab~\xbd1\xb7\xc1~\x1d\x00\xecq^\xf8\x01\x9f\xaf\xdb\xe7{|\xda\x11_w\x9f\xcf\xeeccū\xf5\x9bU\xc5r\xa8\x15\xdf\"\xea\u007fP?\x82\xf5\x886\xb9\xc0\xbd\xccf\x05\x00\xe2\xe2\xbc\xf0&ݝq\xf6\xef=m\xa2\xbe\x8b\xba~#\xdanɳ4\x95\x87\xf7\x97\xe7\u007f$\x85wշ\xb6\xd4\x06\xce\xcf\x03\x90\",\x84\xf7\x11m\u007f\xf2,\xd9~\xc9o\xffX!\x9a\xa8E\x88\xb1\xfb\x89\x1e\xf4,\xce+\xae\xb9\xa4/\xde5\xddS\xa2\x15\xba\xe1;H\x0f\x16\xc2\xf7\x12鑆p\xb1\x02\x90qX\bO\t\"\r\x00\xc3\t\v\xe1q\xa9=\xa0\n\x16\xc2\xe3R{@\x15,\x84'\\j\x0f(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\b\x0f\xb2\n\x16\xc2#\xc3\x03U\xb0\x10\x1e\x19\x1e\xa8\x82\x85\xf0\x84H\x03\x14\xe1\xac\xf0(5\x03\x8aqVx\x94\x9a\x01\xc58+<J̀b\x9c\x15\x1e\xa5f@1\x0e\v\x8fR3\xa0\x16\xe7\x85G\xa9\x19P\b\x03\xe1Qj\x06\xd4\xe1\xbc\xf0(5\x03\nq^x\x94\x9a\x01\x858/|\x92R\xb3F\xe3R\xaa\x13\xe6}\x12o\x13\x00\xa4\x81\xf3\xc2')5\xebj\x15\xbf\xf1zw\x95M\xf8\"\xeeF\x00H\x19\xe7\x85OVjvI4\xea\xb7WsQ\xef\x04\x86\x01\xe7\x85OVjf\nOeKb\x9e\x01 m\x9c\x17>Y\xa9\x99)\xfc\x95\xf1\xcf\x13\xddX\\\xac\x95T\x19] \xd6R3\xff\xaer\xd7\x03\xab{b6\x0e@\f\f\x84ORjvI\xec\xec\xb9\xf1N\xd9\xcfn\x10\xb5\x8ae\a\x9a\xaar\xda)\xb2Ԭ6g\xc5\xdem\x05SQ\x06\x02\x92\xc3@\xf8$\xa5f\x97\x8c\xd34\xa5\x17\xf4aOS\x97\xbe?/\x9bG\x11\xa5f\xadb\x97>l7\x93\x0f\x00\tq^\xf8d\xa5f\x97D}{{\xdb\x13\x13\x8e\xea\xe3\xab\r\x95\x93\xf2\x84졷\x94\x9a-\x99\xd4\u007f[\xa7\xb86v\xf3\x00D\xe1\xb0\xf0\x94\xbc\xd4,pк\xa4\xd4O\xed\x85%O\xb7x\xddRxK\xa9Y\x990\x99\x17\xbb.\x00Q8/<%)5\v\b\xff\x9a\xb8J\x93\xcb\xe5\x91\xe9\")\xbc\xa5Ԭf\xd21\x83\xab\xb6\xab\x03`\xc5yᓕ\x9a\x05\x84_\x9a\xe7\xa7\x12Y\xe5\xe7\u007fX\no)5k\x13MrX\xbf1v]\x00\xa2p^x\x93\xb8\r \xe6;\xad-5\xe2Ei\xf9\xe2\x86秊\xa2\x17ߍ(5\xab\x1b[Ӣ\x0fw\xd9o\x00\x00\v,\x84OTjf~\x96F+۩G\x18\xff\x96R\xad`\xc9k\xa5\x9a;\xb2Ԭ\xcd=!\u007fz\x9b\xdd\xda\x00D\xc2Bx\x94\x9a\x01U\xb0\x10\x9ePj\x06\x14\xc1Bx\\j\x0f\xa8\x82\x85\xf0\xb8\xd4\x1eP\x05\v\xe1\t\x97\xda\x03\x8a`!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x02\u0083\xac\x82\x85\xf0\xc8\xf0@\x15,\x84G\x86\a\xaa`!<!\xd2\x00E8+<J̀b\x9c\x15\x1e\xa5f@1\xce\n\x8fR3\xa0\x18g\x85G\xa9\x19P\x8c\xc3£\xd4\f\xa8\xc5y\xe1Qj\x06\x14\xc2@x\x94\x9a\x01u8/<J̀B\x9c\x17\x1e\xa5f@!\xce\v\x9f\xa4\xd4L\xe7T\xa5\xab\xb0\xe6@\xe1\x15\xaa\x15B\xb8\xce\xd8o\t\x80Tp^\xf8$\xa5fDm\xaeGw6\x96\t\xf1\x01]\xf0z\x1b\xc4;q6\x05@\n8/|\xb2R\xb3ky\xf3n\x11u\x95\xea\u0093\xec=\x80\xf0`\b8/|\xb2R\xb3\xba\xdcK\xf2n\x8b0\xb2\f\x84\aC\xc2yᓕ\x9a\x95>a\xdc]\xddrKޅ\x84\x0f7\x99\x85\xabΖ\vm\xe7\xaa\a\\\x95\x17\b\x00{\x18\b\x9f\xb8\xd4\xecV\xce\x16\xebÐ\xf0\xe1&\xb3p\xd5\xd9_\x1alj\x02\xcfo\xf3\x16\x10\x00\xf60\x10>q\xa9\xd9'\xa2\xc5\xfa0(\xbc\xa5\xc9\xccRuFZ\xbe\xbew\xaf) \x00\xecq^\xf8$\xa5f\xfd\xe3l\xf7\xf0\xd6&\xb3p\xd5\x19iK\xf5\x1b\x8fF\x00\xd8\xe3\xb0\xf0\x94\xbc\xd4,\x90\xe1\xfb\xcd\u0083\xa0\xf0\x96&3kՙ&\v\xea!<\x88\x8b\xf3\xc2S\x92R\xb3\xba\\\xa3\xad\xacI\\\x91wA\xe1-Mf\x96\xaa3\b\x0f\x92\xe0\xbc\xf0\xc9Jͮ\xe5-\xe8\xd73\xba{\xa2\xf1((\xbc\xa5\xc9\xccRu\x06\xe1A\x12\x9c\x17\xde$A\x03H\x9b\xab|WK\xe5\xb8CD\x9f\xc9wZ\xb7x\xbd\x9f\x92\xb5\xc9,\\uvɫվ\xeb?Q\xaby/\xc5\xdb\x18\xc8rX\b\x9f\xa8Ԍ\x8c\xcf\xd2\x14\xcd{_\x1f,\r\x04\xf7%ri\xa8\xc9,\\u\xb6\\֟\xbd\xef\xd2o\x97\xc7\xd9\x14\xc8vX\b\x8fR3\xa0\n\x16\xc2\x13J̀\"X\b\x8fK\xed\x01U\xb0\x10\x1e\x97\xda\x03\xaa`!<\xe1R{@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E@x\x90U\xb0\x10\x1e\x19\x1e\xa8\x82\x85\xf0\xc8\xf0@\x15,\x84'D\x1a\xa0\bg\x85G\xa9\x19P\x8c\xb3£\xd4\f(\xc6Y\xe1Qj\x06\x14\xe3\xac\xf0(5\x03\x8aqXx\x94\x9a\x01\xb58/<J̀B\x18\b\x8fR3\xa0\x0e\xe7\x85G\xa9\x19P\x88\xf3£\xd4\f(\xc4yᓔ\x9am\x91W^\x1a[\xba\xd3o>\xdc_\xd0j\xbb!\x00R\xc2yᓔ\x9a]\xdb(^\xf3\xee]\"\xea͇\xad\xae\x88\xcb\xc5\x03\x90\x1e\xce\v\x9f\xacԬM\x9c\"\xf2/7;\xcd\xf4\x91\xddf\x00H\x11\xe7\x85OVjf\bO=y\xb8\\$\x18\x06\x9c\x17>Y\xa9\x99)<-/\"\xba\x9e+DN\xa3|tr\x9c\x10\xf5gj&\xe6Vގ\xdd(\x00qa |\xe2R\xb3\xa0\xf0;D\x17Q\xbb\xd7;^^\x01\x9ez\x9a\x1aKJ\xf3JVՌ\xfd\x94\x00H\x1d\x06\xc2'.5\v\n\xdf\x16\b\xf1\xb9\x9e\xc0\xf2\xa9\xc2}\x83\xfc7\b\x804p^\xf8$\xa5fA\xe1_\x13\u05cc\x87a\xe15\xec\xdcA\xda8,<%/5\v\b\xffT\x9e\xf90,\xfc\x94ع\x00$\xc1y\xe1)I\xa9\x99)|\u007f\xc1\x12\xf3aX\xf8E\xb6\xd3\x01H\x84\xf3\xc2'+53\x85\xaf\x13\xc7̇a\xe1\x17\xc7\xce\x05 \t\xce\vo\x12\xb7\x01\xc4x\xa7\xb5m\xa9\x90\x9e\xf7\xbf\xe3\xf5\x8e\xaf\xf5zo\xd0\xed\xc3\xde\xd2\xe9^\xef'\xf6\xeb\x00\x10\x0f\x16\xc2'*53>K#&\xee\x90\xe3\xa39f\xa9\xd9\x0e:i\x8e\xaa\xec\xd6\x00 >,\x84G\xa9\x19P\x05\v\xe1\t\xa5f@\x11,\x84ǥ\xf6\x80*X\b\x8fK\xed\x01U\xb0\x10\x9ep\xa9=\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\" <\xc8*X\b\x8f\f\x0fT\xc1Bxdx\xa0\n\x16\xc2\x13\"\rP\x84\xb3£\xd4\f(\xc6Y\xe1Qj\x06\x14\xe3\xac\xf0(5\x03\x8aqVx\x94\x9a\x01\xc58,<J̀Z\x9c\x17\x1e\xa5f@!\f\x84G\xa9\x19P\x87\xf3£\xd4\f(\xc4y\xe1Qj\x06\x14\xe2\xbc\xf0IJ\xcd\xdaƚ\x17_\x12\x05\xfdq\xb6Q\xab?\xe9:c\x8eOΙ\x907\xfd@١8S#\xe6\xda5\xa4\xbd\x12(\\\x00\xa3\x15\xe7\x85ORj\xd6sH\xab\xf5\xeaԉ+q\xb6q\xc1\xebm\x10\xef\x18\xc3cZUˮ\x05B4řj\x9dKv\ri\u05fd\xe5\x1e\x02\xa3\x18\xe7\x85OVjF\x9a\xa1\xe0.q\xd5v\v\x06\xed\x01\x89+\xdd~\"\u007fm|\xe1-s%6\riU\x10~T\xe3\xbc\xf0\xc9J\xcd\x02\u009fY\x95\xa0\xbf/(\xf1\xc4zy{R$\xaa\xb6\xb4\no\x03\x84\x1f\xdd8/|\xb2R\xb3\x80\xf0:Mz\x00\xf7\x90G\xc8\xc8rcq\xb1VRu2\xf0LP\xe2%\x85\xf2\xd2\xda\xfe\xbd]Ԫ\xcfzƘ\xdbX\xa4\xfd\xa6\xb8\xf8\xc0\x8a|wW\xc4\xdcpC\xdar\xa1\xed\\\xf5\x80\xab\xf2\x82|\xa0\v\xbfB_k\xbc\xfe\xf7\xc4[Y\xa2\x15\xcd)AQ\xe6h\x82\x81\xf0IJ\xcdH\xab\xef\xe9Y\xb2Z\x1fty\xf3\xea\xafЕ\xfa|\xaf\x14zف\xa6\xaa\x9cvsJP\xe2OJr*=\x87\xe5\xd1mϡ\x92ern\x9e\xb7\xeb@\x9eX\xe5\x16\x136\x16\xbd\x1c17ܐ\xf6\x97\xc6q\xa2\xc0\xf3ۼ\x05\xf2\x81.\xfc\x85\x9a\x9c-\xfa\x86\x8f\x8e]ڲ\u007fg\x91@O\xe0h\x82\x81\xf0IJ\xcdH\v_\x18\xbbVր\xd4<A\xb2\xc6O\xdf_\xfb\xcb\xe6\x99SB\x12_{\xfeQM\xe4\x1b\x11\xde#+q\x96\xd6\xea7\x855\xb4W\xb4\xd2\xd2e\x91s)ܮ\xa0\xe5\xeb{\xf7\x9a\x029ԅ\u007fY3N\xde4\x14H\xd5\x1b\xf2\xb1\x87\x1fM8/|\xb2R3Җ\xb5\xb7\x97\x99\xc2\x1f\xc8\xed\xa1\x1e\x97W\x0e\xaf6TN\xca\x13e\xe6\x14\xabķ\xf6W\x8a\xbd\xfa\xfd\x85\xb1\xefӭ\xbc\xfd\xfa\xa8\xb0\x91\xde\x15]\xf4tM\xccܐ\xf0K\xf5\x1b\x8f&\x87U\x9eza\x9e\xac\xfc\xacx⊝'\xfc\xf1Ά\x82\x11\x89\xc3\xc2S\xf2R3#÷\xed7\x86\xb7'\xb4PK\x91\xdc\xe5\xb6\x17\x96<\xdd\xe2uG\t\xdfn\xc4p\u007f\xb9\xf1\xf2\xa8\\Mm\xf9R\xd7\xc26j\xd7e\xaeK \xbc\xbc\x0f\b_\x987y\x81\xb9S\xbf\xbec\xf1dQ\xb4\x11{\xf8ф\xf3\xc2S\x92R\xb3\xe0A\xebIyZr\xc5<Z\xb0B>\x9a\\ޣ\xdf.\x8a\x12\xbe\xd0x\x8e\xeaK\xe5m\xeb\x84~#Ѥ)|\xc1\xa9O\xf2\xb6\x18\x13\xebtկ7\xe66\x10\x18=8/|\xb2R\xb3\xa0\xf0\x85u\xfa\xcd\xe1\xf1\x97\xc6\x1f\x96\x8fJd\x87\x9f\xff\xe1(ዊe\x99\xab\xdf,\xf8\xeb/j\xcd7\xfe0\xa4'\xbc\xfc{\xa2Ƀa\x8fh\x93\v\xdc\xcb\b\x8c\x1e\x9c\x17\xde$n\x03H\xf0\x9dVo\x9e<Q\xe3/\xae,6\"\x86G,nx~\xaa(z\xf1]\xfaL\xbe{\xba\xc5\xeb\xfdT\x17^\x14z\xdaZܹ\x1f\x19\xab\xd6Mʗ\x87\x9d\xa7\xf2_\xeei\xd4N\xf6Ը/X\xe7\x86\x1b\xd2.y\xb5\xdaw\xfd'j5\xef\xa5\xeb\xde\xf2\xdaw\xfa\xbb\xaa\n\x0f\\\xd1\u007f\x84\xab\xbe\xb5\xa5V\x1c\xb0\xff\xc5\xc0\x88\x84\x85\xf0\x89J\xcd\xdaD\x10#glь;\xf2o)\xd5\n\x96\xbcV\xaa\xb9ii\xe0\xf9%D\x8f\xee\xac\xff\x99\xab`\x9e\xe9;}$\xe4\xce\xd9_$Dc\x9ep5\t1\xcf:7ܐ\xb6\\\xbf\xd5\xdew\xe9\xb7\xcb_\xd1or\x8e6\xea\xb7\xf5\xb4k\xba\xa7D+t\xc3\xf7Q\x05\v\xe13Tj֥AV\x10\x05\v\xe1)3\xa5fM\x13\xf0\x9e\x11\x88\x82\x85\xf0\x99\xb8Ԟ\xe7\x80\xdf]\x9fl\x12\xc8:X\b\x9f\x81K\xed\xf5\x88)\xcb\v\xaf'\x9b\x05\xb2\x0e\x16\xc2S\x06.\xb5\xe7q\xb9?H6\ad\x1f,\x84\xcfD\xa4\x01\xc0\x0e\x16\xc2g \xd2\x00`\v\v\xe1)\x03\x91\x06\x00;X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\x17\xe1\x01P\x02\v\xe1\xf5\xf0\xfe\xf6\xf6\xb8\x9f\x87\a`\xf8`!<2<P\x05\v\xe1\t\x19\x1e(\x82\x85\xf08-\tT\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1\x11i\x80*X\b\x8fH\x03T\xc1BxB\xa4\x01\x8a`!\xbc\x8c4o~5\u08c1>\xf9\x0f\xbbz\x901X\b\x1f\x884\x00d\x1c\x16\u0093\x8c4ح\x03\x05\xb0\x10^\x8f4\aw\xf7\x1d\xd9\xec;\xf2\x92\xfe\xaf\xf7\xf8v\xcbs\xc9K\xcd\x00H\x1d\x16\xc2\xcb⛅7߬\xee6\xff\xa5Vjv\xe0\x18\x01\x90.,\x84\xd7\xe9\xbdI_~\x1c\xf8\xd7}1\xe2\xa98\xa5f\x8f.!\x00҅\x85\xf0\xc6\x1bO\x9d\xf1\x9e\x8dSj6u\xb1\xddd\x00\x12\xc2Bx\xe3,\xcd\xf9\x81^\xfbӒ\xa1R\xb3Sㄨ\xf2\x97\b\x91\u007f\xab5\x10\xec\xa7\xc4n\f\x80\x04\xb0\x10\x9e\x12\xbe\xf1\x14*5\xf3\x1f\xf6\xe4\x1c\xa6]cw\x9d\xa0\xaeC\xde\xd2\xe9z\xb2ǵ\x96@z\xb0\x10>\xf1gi,\xa5f\xfe\xa5\xe5WK6\x9a\x8b\x11i\xc0 `!|\xe2\xcf\xd2XJͨ\xe7ᢪ@\x96\x87\xf0`\x10\xb0\x10\x9e\x12G\x9ap\xa9\x19Q\x8b8\x14\x18Ax0\bX\b\x9f$\xd2XJ\xcd.\x14֗|a.6\x84\xdf\xf9\xa9\xfd:\x00\xd8\xc3B\xf8$\x91&\\j\xd6_^O\xcb\xdcf\xa6q\xbb\x89\xae\x88&\xfbu\x00\xb0\x87\x85\xf0\x94 \xd2XJ\xcdz\x0e-/\xb8@\x1dy+\x0e\xdd\"Y\xba\xb7\xa5\xc5\xed\xfa,\xcej\x00\xd8\xc2B\xf8D\x91\xc6Rj&\x87\xabh\x85\x10cewӭ\x15\xf9\xb9\xd3\xdb\xedV\x01 .,\x84\xc77\x9e\x80*X\bO\xf8\xc6\x13P\x04\v\xe1\xf1%n\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1\x11i\x80*X\b\x8fH\x03T\xc1BxB\xa4\x01\x8a\xe0\"<\x00J`!<J̀*X\b\x8f\f\x0fT\xc1BxB\x86\a\x8a`!<NK\x02U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fR3\xa0\n\x16£\xd4\f\xa8\x82\x85\xf0\x84R3\xa0\b\x16\xc2'*5\xf3\x06K\xcdƟ\x8c\xbb~\x98\x93s&\xe4M?Pv\x88\xa8V_\xc5u&\xfe\xcc\xe5\"\a\x97\xe9\xcbBX\b\x9f\xa8\xd4\xec֡\xc29\xf2J{\xbbD[\xdc\xf5C\x1cӪZv-\x10\xf2\x8a\x93\x17\xbc\xde\x06\xf1N\xfc\xa9\x17\xbc\xa1f\x11\x90E\xb0\x10\x9e\x12\x96\x9aM\\&o?JE\xf8Jy\xa1U\u007fm\xe0\x12\xab퉄\xb7T\xe9\x80,\x82\x85\xf0\x89K\xcdL\xe1\xfb\xb7݈7!\xcc\xc4zy{R\xb4\x18\x8f <\x88\x81\x85\xf0\x89K\xcdL\xe1uN\x8e\x13\xa2\xfeL\xcd\xc4\xdc\xca\xdb\xfa~\xfc\x95)\xae\x87\x1b\xfct\xbbH\xfbMq\xf1\x81\x15\xf9\xee.\xa2%\x85\xa7\xf4y\xfe\xbd]\xc6\xfc\xa0\xf07\x16\x17k%U\xe6!\x80\xb7\xb2D+\x9aS\"\xaf\xb8\xad=\xb5\xea\x01W\xe5\x05\x02\xd9\x04\v\xe1)\xe1\x1bO\x13k{z^.\xd7\a=M\x8d%\xa5y%\xabj\xc6~J\xb4T\xab\xdf[\xaf\xd5\x12\x1d\xc8\x13\xab\xdcb\xc2Ƣ\x97\x89>)ɩ\xf4\x1c\x0eVv\a\x85o\x15\xcb\x0e4U\xe5\xc8+\r\x1f\x1d\xbb\xb4e\xff\xce\"\xa1\xbfbH\x13\x93\x1b[\x8a\x16\xc4\xf9\xa9`t\xc2B\xf8ğ\xa5\x99(\xcf\xd1\x14\x9a\xe3\xa9\xc2}\x83\xfc7\xe4U\xb4e\xa47n\vkh\xafh\xa5\xa5\xf2\x0f\xc1\xb5\xe7\x1f\xd5D~\xe0\xf4KP\xf8\x9e&}\x8f\xef/\x9b\xa7\x0f\x1b\n\xa4\xea\r\xf9\xc6\x1e\xbe\xf0\v\xa2ڂ\xd8\x1f\bF1,\x84O\xfcY\x9a\x89U\xed\xedK\x83\xc2k\x9f\x9a\x83\xda2\xe3\xeeA}\x17_\xd8H\xef\x8a.z\xba\xc6|\xe6\xd6\xfeJ\xb1\xd7\x18\x852\xfcՆ\xcaIyB\xae\xf1Y\xf1\xc4\x15;O\xf8\x8d\xbf\x01\x9a|\x85x4\x02\xd9\x04\v\xe1)q\xa4\xd1\xc5<\xb5\xd3\x1cO\r6\x11\x97\x9b\xb5~Uz\xd4)l\xa3v]\xdb:]\xf8v#\x91\xfb\x03O\x06\x85o/,y\xba\xc5\xeb6^\"\xd7w,\x9e,\x8a6\x1a{xy\xd0\n\xe1\xb3\f\x16\xc2'\x894\xcb\xc2㩋\x02\x83\xdaI\xd2Y\xffĥ\x11\xc2\x17\xae0\x9e\xac/5\xee\x82\xc2O.\xef\xd1o\x17I\xe1\xdb\xeb\xf4ծ7\xe66\x10\x84\xcfNX\b\x9f$\xd2X\x85_\x1c\x18\xec\x15\x8d\xfam\xa3\f/\x16ዊ\xaf\xe9K\xfd\x81\x97EP\xf8\x12\xf9\xd0\xff\xb0\x14\xdec\x9e\xcdw\xcbMB\xf8l\x84\x85\xf0\x94 \xd2\xdcz\xa7p\xce!\xf34\xe3\xed\xc3F\xdf\xfc'ƃ\x9a\x9c\xbaֺ\x1c]\xf2S\xf9/\xf74j'{j\xdc\x17\xa8H\x14z\xdaZܹ\x1f\xe9i]\xbeӺ\xc5\xeb\xfdTZ\xbe\xb8\xe1\xf9\xa9\xa2\xe8\xc5w\xf5\xa1\xab\xbe\xb5\xa5V\x1c\xa0K^\xad\xf6]\xff\x89Z\xcd{)\xceO\x06\xa3\x11\x16\xc2'\x8a4\xc6giv\x19Ó9\xc2\xd2B\xbf\xad\xccU\xd6\xe0'\u007f\x91\x10\x8dy\xc2\xd5$\xc4<ztg\xfd\xcf\\\x05\xf3t\xdfii\xe0#8K\xf4\xa9[J\xb5\x82%\xaf\x95jn\xda5\xddS\xa2\x15\xba\x0f\xc8\xcf\xd2\b\xa1\xbd\xef\xd2o\x97\xdb\xfdX0Ja!<\xbe\xf1\x04T\xc1Bx\xc27\x9e\x80\"X\b\x8f/q\x03U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x04\x82U\v\x00\x00 \x00IDAT\x16\xc2\x13\"\rP\x04\x84\aY\x05\v\xe1\x91\xe1\x81*X\b\x8f\f\x0fT\xc1BxB\xa4\x01\x8apV\xf8^=\xc6\f\xf8$\a\xdf\xf8\xdc\xe7\xeb\xeb\x93;y$\x1b\x909\x9c\x15>\x80\xae\xf9\xa6\xd9\xe7\x10i@\xe6a!\xbcN\xe79_\xb2)\x00\f\x1d\x87\x85\xd7\xe3\xcb\xf1\xed\xeb֮]\xa3\xb3v\xcdڭ\xafw#рL\xe2\xb0\xf0\xf2\xfc\xcc¹\xd5sM\xaa\xab\xa7\x9dG\xb0\x01\x99\xc4y\xe17\xcc8\xfe\xe5\xe7_\xea\xe87\xebf Ƀ\x8c\xc2@\xf8\x8a\xf0\x19\xc9ͳ\xce\xc9k\b#\u0383L\xe1\xbc\xf0/\xcc\xf80\xf4h\xfd\xac\xb3\x89f\x030T\x9c\x17~\xc3̰\xe4\xcfʹ\x13\xbe\xe5\xc1\xf1e-S[\xe3\xf46\xa1\xac\t\xa4\x81\xf3¯\xaf\xee\xfd\xc3?\xfe\xe3=\xfa\u007f\xff\xec\xdb=\xa3\xf3\xed\xb5\xbdo\xaf\x8d\x98\xb3MԴ<%Ķ8\xbdM(k\x02i\xe0\xbc\xf0\xeb\xaa\xfb\xd6\xfd\xfd\xdf\xff\x1f\xfd\xbf\xef\xfb\x9agt7/\xbc\xd9\\m\x9d\xf2\xd1\xd8z\xfdv\x95\x14\x9e\xeckl <H\x19\xe7\x85\xdf0\xeb\xfcͳ\x1f\x9f\xff\xf8\xfc\xd9˴i\xe6ǾN\xf2}e\x9dR[pK\xbf\xfd@4\x18\x8f <\x18\x12\xce\v\xff\u008cӡGv\a\xad\xf9O\x1bw\xdb>1\xeeB\xc2\a;\x9et\xb4\x15O\x14\xe7W%\xe8d\x05 \x88\xf3\xc2o\x98\x19\xee\xef{if\xcci\xc9\xeb\xe25\xeb\n!\xe1C\x1dO\xb2\xaciJSc\x99\xeb\x14\x01\x90\f\x06\xc2W|\x1ez\xf8Ҭ\x987\x9e\xde7\xae\xe8\xee\xef\xe9\xb9e<\f\no\xe9x\"mr\x0fQOi9\x01\x90\f\xe7\x85ߴ\xf0\xc95+W\xfe\xfa\xd7+W\xae\\S\xfdH\xcc\xd7@\xcc=|\x8d\x10b\xbf|\x18\x14\xde\xd2\xf1D\xda3r\xb8C\\#\x00\x92\xe0\xb0\xf0\x03D\xfbV\xfer~u\xf5\xc2ǫ\xab\xab\xe7\xaf\\\xdb\x19\xf3\xe1\xb1\t2\xc3_j\x11u\xc6.>(\xbc\xa5\xe3)p\xd0\xea\x15\xc7\b\x80$8,\xbcN_o\xb7\x8eo@\xde\xf6\xf6\xc6>_[$Mo\x89:-i\xe9x\"m\x95\\\xb2S\xa4P\xd5\r\xb2\x1d\xe7\x85'c?\xff\xc2\xc2\xcf\xe3|0\xd88\x0f\xefwG\to\xe9x\"\xadX\u007fI\xf4?\xe8\xb6]\x1d\x00+\xce\v?\xd0\xd7\xd7\xed\xf3\xfd۴#\xben_\x9f\xddG%\xb7\x88'Zk\x8dwZ-\xbdM\xe1\x8e'y\x96\xa6\xf2\xf0\xfe\xf2\xfc\x8fl\xd6\x05 \x12\xe7\x857\xe9M\xf0%\xee\x96ɹ\xe5m%m\x11\xbdM\xa1\x8e'\x9d\a=\x8b\xf3\x8ak\xd0M\x06R\x80\x85\xf0>\xa2M\x8f\x9f%|*\x18d\x1c\x16\xc2뇪z\xa4!\x9b#V\x00\x86\x17\x16\xc2S\xe2H\x03\xc0\xb0\xc1Bx\\j\x0f\xa8\x82\x85\xf0\xb8\xd4\x1eP\x05\v\xe1\t\x97\xda\x03\x8a`!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84O\x10i\xb0\xe7\a\xc3\n\v\xe1)\x8e\xd8\xd8\xf3\x83ᆅ\xf0\xf1\xc4\xc6\xc1,\x18nX\b\x8fH\x03T\xc1Bx\x8a/\xf6\x91\xdd\x11\xd7\xdd\x03`h\xb0\x10>&\xd2\xec\xf1u\xf6\xfa\xfa\xfaz\xfb\xfa6T\x9c\x95w}\xd4\xd7\xdb\xeb\xc37D\xc0Pa!|L\xa49\x12\xfa\xba\x1f\xda\xfd\xc0\xb0\xc2Bx\x8a\x8e4\x90\x1cd\b\x16\xc2Ǟ\xa5\x91u\x96\xbb7mxn\xfd\xb3k\xd7?\xb7~\xc3\xebͨ\xb3\x04\xc3\x02\v\xe1c\xcf\xd2\xe8í\vg?6kV\xf5\xfcٳf=V=\xe3\"NN\x82စ\xf0\x14s\x96F^Uxڑ\xf3g\xcfߤ\xcbgϟ\u007fv\x1a\xea,\xc1\xb0\xc0B\xf8\xd8Hc\\F\xfb&\xc9K\xadʇ[+\xe4u\xe3\xe1<\x182,\x84\xb7\x8d4/̔u\x96?\xba\xe3\xa0\xfe蹙\xe7\xe2\xad\v@:\xb0\x10\x9el#\x8dQay\xff\x1d\xf2v=\xea,\xc1\xf0\xc0Bx\xdbH\xb3~n\xf7\xee\xfb\xee\xbd\xfbk?\xb8\xef\xe7}o\xcc\xe8<\xb8\xc1w|s\xc4Z\xa8\xb3\x04\xe9\xc3Bx\xdbH\xb3\xaez`\xed7\xbe\xfeww|\xe3\x1bߑu\x96\xbb\xab\xbb\xf7\xfcҺ\x12\xea,\xc1 `!<\xd9F\x9a\x8a\x8b\x9dǏ\xdf\xfb\xf5\xed\xc7ߣ\x97f\x9e\xef>Oݗ\xadSPg\t\x06\x01\v\xe1m#\x8dYgy\xaf\xcc\xf0\x03\xa8\xb3\x04\xc3\x04\v\xe1m#͆Yr\x87>\xeb{R\xfbM3cNK\xa2\xce\x12\f\x06\x16\u0093}\xa4\xf9R\x1f\x98\x9d\xad\x9b+Pg\t\x86\x05\x16\xc2ۿ\xf14\u007f\xcd\xfag\xd7m\u007f\xe3\xb9g\u05ed\x9f\x8f:K0<\xb0\x10\xde6\xd2\xecy\xb2z\xee\xec\xd9\x15\x15\x15\xb3g\xcf}reg\xcc۬\xa8\xb3\x04\x83\x80\x85\xf0d\xf7\x8d\xa7\xde\xce\xcb\x17/_n^\u007fZ\xbf\xeb\xb4\xf9\xda\x13\xea,\xc1 `!|\x82/q\xaf\x9du>\xceGhPg\t\x06\x01\v\xe1c#\r\xc9\xc3U_\xaf\xcf\xf7\xd2\xfc\xb3\xbe\xde>\x9f\x9d\xf3\xa8\xb3\x04\xe9\xc3Bx\x8a\u007f]\x9a\x83\u007f\x88-\xa3\x0f\x82:K\x906,\x84\x8f\x17i|Dkf\x1e\xc7\x17\xfe\xc0\xf0\xc1Bx\xdbH\x13X>\x1f\x17b\x02\xc3\b\v\xe1ip\x91\x06\x80\xb4a!<.\xb5\aT\xc1B\xf8\x04b\xe3R{`Xa!<\xe1\xea\xc1@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<\xc5\x17\x1b\u0083a\x85\x85\xf0\xf1\"\r2<\x18nX\b\x9f\xe8\xb34\xc8\xf0`8a!<!\xd2\x00E\xb0\x10>AtA\xa9\x19\x18VX\b\x1f\x13]Pj\x062\x04\v\xe1):\xba\xa0\xd4\fd\b\x16\xc2\xc7D\x1aH\x0e2\x04\v\xe1c\xcf\xc6\f\xa0\xd4\fd\x04\x16\u0093ݥ\xf6Pj\x062\x00\v\xe1\xed/\xb5\x87R30\xfc\xb0\x10>6\xd2\xf4\xa1\xd4\fd\x04\x16\u0093]\xa4A\xa9\x19\xc8\x00,\x84\xb7\x8f4\xc9J\xcdNΙ\x907\xfd@١\x88\x85\x91\xfdf\xfb\vZcV\x03Y\r\v\xe1m#M\xb2R\xb3cZUˮ\x05BDV\xf5E\xf6\x9b\xb5\xbaZ\x02\xa3\x03\xb8\x840\x90\xb0\x10\x9e\xec\"M\xb2R\xb3J\xb7\x9f\xc8_+b\xba)\xaduO\xfe\xe0\xe0\xd1%\xd1\xd3@V\xc2Bx\xfbH\x93\xa4\xd4lb\xbd\xbc=)\x82\xfb\xf0\x10v\xfdf4uq\xec2\x90\x85\xb0\x10\xde6\xd2$+5[R(˛\xfc{\xbbh\xb9\x18\xb7mY\xb8\xbe,(\xfc\xf5\\!r\xe4ų\xa95p\xb1\xd5)1\x1b\x01\xd9\x06\v\xe1ɶ\xe3)q\xa9\x19}R\x92S\xe99ܯ\x8f\xfe\xd28N\x94<\xef)\tԗ\x85\xf6\xf0\xed^\xefx\xa3\x04\xa4됷t\xba\xd7\xeb\xfd\x80@\xb6\xc3B\xf88\x91&a\xa9\x19ѵ\xe7\x1f\xd5D\xbe\x11ᵉ7\xf4=z\x89Y_f\x8d4\xb9\xc1\xaaVD\x1a`\xc0Bx\xfb7\x9e\x12\x97\x9a\x19\xdc\xda_iv}\xd4\xc9G\rf}\x19\x84\a\xf1a!<\xd9E\x9ad\xa5f\xed\x17\xe4\xad\xdfh1\x8b\xa8/\x83\xf0 >,\x84\xb7\xfd\xc6S\xb2R\xb3\xc2\x15\xc6]})E\u0557\xc5\x17~\xe7\xa7\x04\xb2\x1c\x16\xc2\xc7F\x9a\xd0\xf2\xf8\xa5fE\xc52\xc0\xf8\xa7.\xd2o\xb5\xa2.\xfd\xd0t\x92Y_f+\xbc[\u007f\xeeJ\xec9{\x90m\xb0\x10\x9e쾬\x9d\xacԬH\x14z\xdaZܹ\xb2\xb3L\x96\xcc\xef,\x95\xf5e\x96~\xb3\xfew\xbc\xde\xf1\xb5^\xaf\xb1\xdb\xf7h[Zܮ\xcfb7\x03\xb2\v\x16\xc2'\xb8.M\xfc\x06\x90Gw\xd6\xff\xccU0\xcf\xe8\xe8\xd3V\xd7\x06\xea\xcb,\xfdfGs\xcc\xe1\x0e9\xe3֊\xfc\xdc\xe9\xed\xb6\x1b\x02\xd9\x04\v\xe1\xe3E\x9a\x94K\xcd4\x0f\x01\x90\n,\x84\xa78ן\xe9K\xb5\xd4\f\u0083\x14a!\xfc\xa0\"\x8d\x15\b\x0fR\x84\x85\xf0\t\xceҤr\xa9\xbd\v^\xad\xf6]?\x01\x90\x1c\x16\xc2\xd3\xd0.\xb5\xb7\\?2\xd5>I6\v\x00b\"|\x82H\x83\xab\a\x83a\x85\x85\xf0C\x8c4\x00\xa4\f\v\xe1ih\x91\x06\x80\x94a!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84O\x10] <\x18VX\b\x1f/\xba Ãᆅ\xf0\x94\xe0\xb34\xc8\xf0`8a!<\"\rP\x05\v\xe1\x13\xec\xc9Qj\x06\x86\x15\x16\xc2S\xf4\x9e\xbcW\xdfۛ\xdfx\xdaP\xf1\xa1\xef\xa6,5#Dy0\f\xb0\x10>A\xa4A\xa9\x19\x18VX\b\x8f\x83S\xa0\n\x16\xc2S\xcc\xc1\xa9\xbe\xb3?\xbe}\xddڵkt֮Y\xbb\xf5u\x94\x9a\x81a\x81\x85\xf0\xb6\x97\xdaۼpn\xf5\\\x93\xea\xeai\xf1.\xd6\x01@Z\xb0\x10>6\xd2\xe8\xc3\r3\x8e\u007f\xf9\xf9\x97:\xfaͺ\x19(5\x03\xc3\x02\v\xe1\xc9\xf6\xea\xc1\x15\xe1E\x9bgɫ\a\x0f\xe0\xf8\x15\f\x15\x16\xc2\xdbF\x9a\x17f|\x18zdw}x\x00\x06\x01\v\xe1\xed#\x8d\xa5\xc8\xec9\xbbR\xb30\x91Mf\x01\x96\x8b\x1c\\Y\x0fD\xc3Bx\xb2\x8b4\xeb\xab{\xff\xf0\x8f\xffx\x8f\xfe\xdf?\xfbv\xcf\xe8|{m\xef\xdbk\xe3\xac\x1c\xd9d\x16Z\x88\x8bw\x80\x18X\bo\x1bi\xd6U\xf7\xad\xfb\xfb\xbf\xff?\xfa\u007fߗ\xa5f\xcd\vo6W\xc7߄]\xb1\x13\x84\a1\xb0\x10\xde>\xd2\xcc:\u007f\xf3\xec\xc7\xe7?>\u007f\xf62m\x9a\xf9\xb1\xaf\x93|\t>V\x03\xe1AJ\xb0\x10\x9el\x9b\xb8\x8dR3\xf3\x91\xedA\xeb՚\tūWOp\x19I=$\xbc\xff\x95)\xae\x87\x1b\x8c\xcb2i+\x9e\bW\x9d\x01 a!\xbcm\xa4\xd90\xb33\xf4𥙱\xa7%\xfb\x1f,l\xf0\x8c\xcf\xddY\xf9\xb2|\x14\x12~\xa9V\xbf\xb7^\xab\x95Cy\x11\xedƲ@\xd5\x19\x00\x12\x16\xc2\xdbG\x9a\x8a\xcf\xf5\xc1\x80\xb1\xf0\xa5Y\xb1o<5\x89\x93\xb2\xd6)\xa0sP\xf86\xd1\x16\xba\xd5&\xf7\x10\xf5\x94\x96\x13\x00AX\bOv\x91f\xd3\xc2'\u05ec\\\xf9\xeb_\xaf\\\xb9rM\xb5M\xa9Y]\xbe~\xf3Q\xb0\x978(|m\x99q\xf7\xa0\xdc\xc5k\xcf\xc8\xe1\x0e\xb3\xea\f\x00\t\v\xe1c#\x8d>ܷ\xf2\x97\xf3\xab\xab\x17>^]]=\u007f\xe5\xda\xd8k\b\xbf<\xf6\xaaܕG\xedፎ3\xa2*\xb9[\x8f\xa8:\x03@\xc2Bxۏ\a\xf7\xf5v\u007f\xd5ݽgù\xee/\xbb{{cW\xfa4\xa7\xf2ӓ\xa5偫\x06\x87\xf6\xf0\x93\xe4\x02\xffĥ\x14Uu\x06\x80\x84\x85\xf0\x14\xffK\xdckf\xc6\xfb\x9c\xfc1Q$\x84\xfbB\xe0QP\xf8\xbdB\x96\xcd7\x9a\xed\xadŷ䱭\xdbvu\x90\x9d\xb0\x10\xde\xf6\x1bO\x03}}\xbd>\xdf\xf6\xc7\xcf\xfaz}}6\xce\x1f\x1b\xbf\u007f\xaf\xf7\x82\xb1\x83\xb74\x99QMN]k]N\x8d\\\xac\x89\xca\xc3\xfb\xcb\xf3?\x8a]\x17d-,\x84\x8f\xf7\x8d'\xfd\x15p\xf0\xf5xץ9\xa4\xc9\xc62m\xfa\xa9\x88&3\xf2o+s\x95\x99\xe7\xe1\x1f\xf4,\x0eT\x9d\x01\x10\x80\x85\xf0\x14'\xd2\xf8\x88~=#N\xa9\xd9\x15ײ+\xb7o_?\xba \xff\xba\xdd\xd3\x00\xd8\xc2B\xf8x_\xe2\xd6w\xf9\xdb\x1f\x8f\xf3]\xa7\x96|\xf3p\xd5_\xd4f\xf74\x00\xb6\xb0\x10~0\x91\xe6X\x8eyB\xf2T\xce\t\xbb\xa7\x01\xb0\x85\x85\xf04\x88K\xed\xf9ks\x975\x1dhZ\x96\xbb\fuf uX\b?\xa8K\xed\xf9[+\x8b\xb5\xe2\xcaV\xf8\x0eҀ\x85\xf0\t\"\r\xae\x1e\f\x86\x15\x16\xc2\xd3 \"\r\x00\x83\x81\x85\xf0\x83\x8a4\x00\f\x02\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1\a\x11i\x10u\xc0\xa0`!|\xba\x91\x06Q\a\f\x16\x16\xc2S\x9a\x91\x06Q\a\f\x16\x16\xc2#\xd2\x00U\xb0\x10>\xe5H\x13h\xf7\xd39\xf8\xc6\xe7>\x1f\xda\xfd@\xba\xb0\x10\x9eҏ4\x9bf\xa3\x13\x04\f\x02\x16\xc2\x0f\"Ҡ\xce\x12\f\n\x16§\x1ci\xe4\x10\xed~`\b\xb0\x10\x9eR\x8e4}h\xf7\x03C\x82\x85\xf0\xa9G\x9a>\xb4\xfb\x81!\xc1B\xf8\xd4#M\x1f\xda\xfd\xc0\x90`!<\xa5\x13i\xd0\xee\a\x86\x00\v\xe1Ӌ4\xc9\xdb\xfdZ\xe4e\xc8&F\u007f\xbb{\u007fA\xab\xddd\x90U\xb0\x10>\xadH\x93B\xbb_\xd7!oޢ\x98\xe2\x8fVWK\xf4\"\x90u\xb0\x10\x9e҉4\xa9\xb5\xfb\x15\xad\x8e]\x86\vz\x00\x1e§\x17iRj\xf7\xb3\x13\x1e\x00\x1e§\x15i\x92\xb6\xfb\x19\x98\u0087+\xfd\xae\xe7\n\x91#/\x1dO˅\xb6s\xd5\x03\xae\xca\xe0\x95\xe5AV\xc1BxJ'\xd2$k\xf731\x85\xb7T\xfa\xb5{\xbd\xe3\x8d\n\x9c\xbf4\x8e\x13\x05\x9e\xdf\xe6-\x88]\t\x8c~X\b\x9f^\xa41\xda\xfdL\xec\xda\xfdL\f᭕~:\xb9\x81\xa2b-_\u07fb\xd7\x14خ\aF9,\x84O+\xd2$k\xf731\x84\xb7V\xfa\x91ExY\x00\xe5\xd1l\xd7\x03\xa3\x1c\x16\xc2Sʑf y\xbb\x9f\x89!\xbc\xb5ҏ,\xc2\xcb{\b\x9f\x9d\xb0\x10>\xf5H\xa3\xd3\xd7ۭ\xe3\x1b\x90\xb7v\xed~\xb7?\x90\a\xa9\x13\x8c=\xbc\xa5ҏ < &§\x1eiB\xcb_X\xf8y\x9c}\xfb+\xc2KtUl\xa3\xc8J?\x82\xf0\x80\x98\bO)G\x1a2\xda\xfd\xba}\xbe\u007f\x9bv\xc4\xd7m\xdb\xeew@\xcci\xd9U>\xe139\x0eW\xfa\xf5\xbf\xe3\xf5\x8e\xaf\xf5zo\xd0%\xafV\xfb\xae\xffD\xad\xe6E\xddY\x16\xc2B\xf8\xb4\"\x8dIo\xfc/q\xb7Lu\xe5W\xbdo\fÕ~Gs̢\xbf\x1d\xb4\\v\xff\xbd\xef\xd2o\x97\xc7\xdd\x04\x18\xb5\xb0\x10>\xddH\xe3#\xda\xf4\xf8Y\xfbv?\x00\x12\xc1BxJ'Ґ\xbcx\x01鑆l\x8eX\x01H\f\v\xe1\x877\xd2\x00\x10\x1f\x16§\x1bi\x12\xbc@\x00H\b\v\xe1)\xcdH\x13o9\x00\xc9`!\xfc \"\r.\xb5\a\x06\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<\r5\xd2\\\xbe\xfcyg\xd4\x06\xba;/\u007f\xf5%^\x12 \n\x16\xc2\x0fc\xa49\xb8=ޗ\xfe\x00 &\xc2\x0fW\xa4\xd17\xb0i.\x0efA\x02X\bOC\x8d4a\xba;\xb1\u007f\a\t`!\xfc\xf0D\x9a\xbe>__\xdf\xf1=_\xeaw\x03\xb0\x1e\xd8\xc3B\xf8\xe1\x8a4:/=v\xd1f)\x00\x01X\bO\xc3\x17i\x06\xc2\xd7\xe1\x03 \x16\x16\xc2\x0f=\xd2諞\xde\xf3\x87\xed[7\xbfټ}\xeb\xd6\xed\xcd\xfbnگ\x06\xb2\x1d\x16\xc2\x0f=\xd2\xe8\xabn\x9f?k\xe6\xb4\x19\xd3$3\xe7W\\Ĺ\x1a`\a\v\xe1iȑF\x1fn\x98v\xf0\xf4{\xa7\xdf\xd39}z\xcd4\xb4\xfb\x01[X\b?\xf4H#\x85\x9f\x1d\xbe\x8a\xc1֊s\xf2\"\x1ep\x1eD\xc3B\xf8a\x894\x96\xb2\xb3\xbe\r3\xcfE\xaf\x03\x80\x84\x85\xf04,\x91fFHxZo\xdf\xee\a\x00\v\xe1\x87%Ҭ\x9f۽\xe7\xc7?\xfe\x89\xfe_E\xdf\xeb3??\xb2\xddw|k\xe4\xe7jNU\xba\nk\x0e\x14^\xa1Z!\x84\xeb\f\x81,\x84\x85\xf0\xc3\x12i\xd6UӚ\xaf}\xed\xef\xf4\xff\xbe%\xdb\xfdޘ۽;\xb2\x1f\xa4\xcd\xf5\xe8\xce\xc62!>\xa0\v^o\x83x'z\xab \x1b`!<\rK\xa4\x99}\xf9b\xf3\x9e}{\xf65\x1f\xa4\xcd3.v\x9e\x1e\xe8\xfc\xd0z\xf5\xc9ky\xf3n\x11u\x95\xea\xc2\xeb\xb4C\xf8섅\xf0\xc3\x12i,\xed~\x03v\x19\xbe.\u05f8<\xf6\x16ad\x19\b\x9f\xa5\xb0\x10~X\"͆Y\x17\xcd%\xfaͦ\x19\xe7\xe4\xa5V#6X\xfa\x84qwu\xcb-y\x17\x12\u07bf\xab\xdc\xf5\xc0\xea\x1e}tcq\xb1VRu\x92\xd0l9\x9aa!<\rO\xa4\tobsE\xcc\x1bO\xb7r\xb6X\x1f\x86\x84\xaf\xcdY\xb1w[\xc1T?Q\xabXv\xa0\xa9*\xa7\x1d͖\xa3\x19\x16\xc2\x0fK\xa4\xd9P\xbdn\xf3\v\x9bt^ش\xf9\x97\xb1\xed~\x9f\x88\x16\xebà\xf0\xadb\x97\U00068468\xa7\xa9K\xdf\xe1\x97͓\x8b\xd1l9Za!\xfc\xb0D\x9a\xe6\xc7\x1f\xab\x98aR\xf1\xf8\x93\x9fGo\xad\u007f\x9c\xed\x1e~ɤ\xfe\xdb:Ų\xd9\xf2jC\xe5\xa4<aT]\xa2\xd9r\xb4\xc2Bx\x1ar\xa4\xd1\xe9\xbex6\xc4\xc5˱\u007f-\x02\x19\xbe\xdfl)\x0e\n_f6\xe1\b}\xbf\xde^X\xf2t\x8b\xd7m\n\x8f\u07b3Q\n\v\xe1\x87\x1eiR\xa0.\xf7\xaa\xbck\x12W\xe4]P\xf8\x9aI\xc7\f\xf4\xe7&\x97\xcbC\xd7E\x10~T\xc3B\xf8\xa1G\x1ac\xe9@_\x90\x81\x98M\xc9\xf3\xf0\v\xfa\xf5\x8c\xee\x9eh<\n\n\xdf&\x9a\xe4]\xfdF\xa2\x92E\xfa\xc0\xff0\x84\x1fհ\x10\x9e\x86#\xd2$\xa5\xcdU\xbe\xab\xa5r\xdc!\xa2\xcf\xe4;\xad[\xbc\xdeO\xf5\xa5uckZZj填G,nx~\xaa(z\xf1]4[\x8e^X\b\xaf$\xd2\x18\x9f\xa5)\x9a\xf7\xbe>X\x1a\b\xeeK\xe4\xd26\xf7\x84\xfc\xe92\xd8\xfb\xb7\x94j\x05K^+\xd5\xdch\xb6\x1c\xbd\xb0\x10~x\"\r\x00\xc9a!<)\x894\x000\x11^Q\xa4\x01\x80\x87\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe13\x1di\xf4\r\xbf\x8d:K a!|\xa6#\r\xfe\"\x80 ,\x84\xa7\xccG\x9a\xb4\xfe\"\x80\xd1\v\v\xe1\x15D\x9a\xb4\xfe\"\x80\xd1\v\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0*\"͛_\r\xf8h\xa0O\xfeK\xeb\x95\x02F\x17,\x84W\x14i\x00\xe0!<\xa9\x884\x89g\xb7\x94_I\xf8\xfc\x90\xb8V\x1eqmz\xe0 ,\x84W\x10i\x0e\xee\xee;\xb2\xd9w\xe4%\xfd_\xef\xf1\xed136\n\x8f?bA\x1a͖\xcbEN\x93\xfd3_,+ʝ\xa3o\xd7\xffb\xceF\xfb\x19\x83\xe4\x13MLN6\a\xd8\xc2Bx\x05\x91慅7߬\xee6\xff\xed\xf9e\xf4\x84m9\xbb\xa2\x96\xa4\xd1ly\xc1k\\k\xd8\x06wᎥ\xb9\xd7\xe5h\xef\xb8m\xf6S\x06\x87\xff\xddZ\\\xd9xp\xb0\x10\x9e2\x1fizoҗ\x1f\a\xfeu_\x8cz\xb2C\xab\v\x0e\xaf\xba\xaf\x06\x87\xa9\x17\xfd\xc5\x11\xfe\x9a\xd8F\xfe.s\\\xaf\roC\x1a.\xe5=HX\b\xaf \xd2\x1cy\xa33\xfe\xf3\xb5\x85=\xc1\xe1)q*8\x1c\xb2\xf0gDkh\xdcUXk;g\xb0@\xf8A\xc2Bx\x05\x91fs\xf5\xf9\x81\xde8\xa7%\xfb\xf3\x9e6\a\xdbJ[?\x10\x1f\xec-}\xc5x\x14\x14>\\gI\x93\x03\xd7ٞN\xad\xfa\xed3\xe4\xd1o\xf5\xfc\xae\xadx\xa28\xbf\xea\x8c\x11\xe7w\x05\x02v\xff\x04s\xea\xaa\xc0\x0f\xa9\xcf\r\xbd\xa8\x02Xk2\xc7m[\x16\xdcBhh\xa9Ԍ\xe8ѼPS\x9c\xbf\b\x91f\x90\xb0\x10\x9e2\x1fi\x12\xfdE8!\xbc\xe6\xe0B\x8dxP\x94\x89E\x9f\x19\x8f\xc2E\u007f\xc1:K\xd2j\xbd:\xe5b#\xf5\x1c*Yv\x85\xae\xd4\xe7y\xf5̢\x89)M\x8de\xaeSf\x9c\x0f\x04\xec\x13\xdeF\xe1\xf1\x86*\x15\x0e\x89\xc3Q?6\xb2&\xb3\xe4yO\x89\xbe\x05\xcb\xd0R\xa9i\xed\xd1<\x93\xf7\xc0k-\x95\x02\xc2\x0f\x0e\x16\xc2+\x894\xf1\xff\"\xec\x15\x1f\x05\x87m\x9a\xd0\xda\x02\xe3\xa0\xf0\x96:K\xcf1}T+\x8c\x03P\xcf\x14\xfdf\xa9\x11T\xb4\xc9\xfa^\xb8\xa7\xb4\x9c\"\xbbr\xac\x91\x86.\x88\xe8S\x93\x115\x99\x13o\x10]/)\x8f\x18Z*5-=\x9a\xd3K{\xe4j\x10~p\xb0\x10^I\xa4\x89\xff\x17\xa1E|b\x0e\xae\xadҊE\xf1\xf8\xa7\xbe0\x1e\x852\xbc\xa5\xceR\x8f*\x8bǚgt.\x8c}\x9fn\xe5\xed\x97C\xed\x19y\xbbC\\K(|̹KkM\xa6q\xd4\xdc`l!4\xb4Vj\x86z4\xaf\x8b\x9d\xf2\xf9z\b?8X\bO\xceF\x9aw\x83fo\x9c\xb0\xe3\x94\xf8˶\"\xf3\xa4yPxk\x9d%\xf5\xccт{\xea\xca\xd5Ԗ\xdf/G\xe6A\xabW\x1cK |\xbb8D\x91\xc4\xd4dZ\xb6`\f-\x95\x9a\xe1\xed\xb6\x9b\xf9\v\a\xad\x83\x84\x85\xf0\x0eG\x9a\x9e\xd0Y\x96~\xe3,M\xbf\xf9\x1eTPxk\x9de\xd7\xf4\xf1\xc1\xc4C\xad\x13\xfa\xcdDC\x9aqd\xbaS\xdc\b\x88Yo#\xbcG\xeb\xa2H\"j2-[\b\r-\x95\x9aa\xe1\xbf\x10\r\xf2\xf9\xa5\x10~p\xb0\x10\xde\xe1HC\x8bJCo\xb3~\x96\xffYp\x18\x14\xdeRgym\x8aK\xee_[\xddry\u007fQk\xbe\x91hH+\xbe\xa5?|P.u=\xad\xcf}4Vx\xff\xe4\xaa\xe0\xf0\x93\x8d\x1d\xd1\xdb%\xadH\u007f9tMrG\f-\x95\x9a\x96\xbf\x1c\xe5%z\xee\xf9h<\x84\x1f\x1c,\x84'g#\r\x9d\xc9\xf9m\xf4\"K\xb3e\xb8\xce\xf2z\x99\xd8(O\xd3<a\xdaV7)\xff\xb61\xd0D\xe5\xe1\xfd\xe5\xf9\xf2з\xbc`\xe3\xf3\xe5bܮS\x81\xb34\xef\x06^J[dZ1\x99'\xe6\x18\xf7\xe1\xed\x9a\xe7yv\x96\x1a[\xb0\fC\x95\x9a\xd6\x1e\xcdS\xae\x12O}~\x8e\xfc\x11 }X\b\xefp\xa4\xd1w\xa2\xe3\xa3\x03\xb6\xa5\xd92\\gyb\\`i\x891\xe7#\xb1̜\xfc\xa0gq^q\x8dq\x02\xf2\x8c;7\xaf\xf2\x19!\x96\xdf\xca7f\x8e\xfb\xc0\x98\xe1\xcd}*\xb4\xe9\xd7\nv\x18\xf7\xe1\xedꖯ\xae\rn\xc12\fUjF\xf4h\x9e\xa9ʟ\xf8Ԯq\xa8\xd4\x1c\x14,\x84w:Ґ\u007f\x85\x16\xe7\xf3_\x89\xe8\xd2\x0e$\x9b\x12\xa0I\xab\xbd\x9dp\x82\xe5\xbd\xdax\x1f\xcc\x01\xc3\x02\v\xe1\xc9\xe1H#\xf7\xb6\xc5W)]\x9a&$\xb68ĵ\u008d\x91\x9fŌ\x01«\x82\x85\xf0\x8eG\x9aA\xe09\xe0w\xd7'\x9b\x942\x10^\x15,\x84w<ҤO\x8f\x98\xb2\xbc\xf0z\xb2Y)r\xc18&\x8d\x1e\x82L\xc0Bxr<Ҥ\x8f\xc7\xe5\xfe ٜT1\x8eI?\x89\x1e\x82L\xc0B\xf8\x91\x18i\xc0Ȅ\x85\xf0#0Ҁ\x11\n\v\xe1i\x04F\x1a02a!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84\xcft\xa4\x01 \b\v\xe13\x1di\x06Pj\x06\x02\xb0\x10\x9e2\x1ciҝ\x0fF/,\x84W\x10iҝ\x0fF),\x84W\x10iҚ\x0fF/,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16«\x884(5\x03\x12\x16\u0093\x9aH\x03\x00\x0f\xe1\x95D\x9a\xc4/\x0f\x94\x9ae\t,\x84W\x10ix\x96\x9a\xed/\xb0\\}2\f:\xcb2\a\v\xe1)\xf3\x91\x86g\xa9Y\xab\xcbv\u05cfβ\xcc\xc1Bx\x05\x91\x86i\xa9Y\xbc\vr\xe0jؙ\x82\x85\xf0\n\"\xcd\b+5\x83\U00019085\xf0\x94\xf9Hð\xd4\xecz\xae\x109\xb2\xce&ngY\xa8\xd4\xec\xd48!\xaa\xfc%B\xe4\xdf\"0$X\b\xaf \xd2$\x9a\xefP\xa9\x19\xb5{\xbd㍿\r\xf1:\xcbB\xa5f\xfeÞ\x9côk\xec\xae\x13\xd1\xdb\x00i\xc2Bx%\x91&\xfe|\x87J\xcd$\xb9\x810d\xdbYf-5\xf3/-\xbfZ2\xbc\xfd\xf5\xd9\t\v\xe1IE\xa4\x89?ߩR3\xb2\bo\xd7Yf-5\xa3\x9e\x87\x8b\xaap\xcdɡ\xc3Bx\x87#\x8dC\xa5f\x92\x90\xf0v\x9de\xd6R3\xf9\xb2\xb4\xdb\x00H\x13\x16\xc2;\x1ci\x1c*5\x93\xc4\bo\xed,\xb3\x96\x9aх\xc2\xfa\x92/l\xb6\x00҃\x85\xf0\xe4l\xa4q\xa8\xd4L\x12#\xbc\xb5\xb3\xccZj\xd6_^O\xcb\xdc\xc84C\x86\x85\xf0\x0eG\x1a\x87J\xcd\xfa\xdf\xf1z\xc7\xd7z\xbd7\xe2v\x96\x85J\xcdz\x0e-/\xb8@\x1dy+\x0e\xe1\xb4\xe4\x10a!\xbcÑơR\xb3\xa39\xe6\xc6v\xc4\xef,\v\x96\x9a\xb5\x19'\xf4W\b16\xd5V)\x10\a\x16\u0093Ñ\xc6\xf9R3\xa0\n\x16\xc2;\x1di\x9c/5\x03\xaa`!\xbc\xe3\x91f\x10\fo\xa9\x19P\x05\v\xe1\xc9\xe9H\x93>\xc3Zj\x06\xd4\xc1Bx\xe7#M\xfa\fg\xa9\x19P\a\v\xe1Gb\xa4\x01#\x13\x16\xc2\xd3ȋ4`\x84\xc2B\xf8\x91\x18i\xc0Ȅ\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10>ӑ\x06\x80 ,\x84\xa7\fG\x9a\x01\x94\x9a\x81\x00,\x84\xcft\xa4I\xf7\x05\x02F/,\x84W\x10i\xd2z\x81\x80\xd1\v\v\xe1)\xf3\x91&\xdd\x17\b\x18\xa5\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\xa4 Ҡ\xd4\fHX\b\xaf(\xd2\x00\xc0Cx%\x91&\xf1n\x1d\xa5fY\x02\v\xe1)\xf3\x91\x86g\xa9YRⴞ\x81A\xc3Bx\x05\x91\x86g\xa9Y\x98\x03\xc7Ȏ8\xadg`а\x10^A\xa4aZj\x16\xe2\xd1%\xf6\xcbq\x01\xa7a\x86\x85\xf0\x94\xf9Hý\xd4l\xea\xe2\x84O\x83ႅ\xf0\n\"\r\xc3R3\xf2V\x96hEsJ\xfc\xc6\xc6$S\x88N\x8e\x13\xa2\xfeL\xcd\xc4\xdc\xca\xdb\xf1ZϮ\xd6L(^\xbdz\x82k\x10W\xc3\x04<\x84W\x10i\x12\xbd@\x1c*5;:vi\xcb\xfe\x9dE\xe26u\x1d\xf2\x96N\xd77\xfc\x81,\x94j,)\xcd+YU3\xf6\xd38\xadg\xfd\x0f\x166x\xc6\xe7\xee\xac|\x99@\xfa\xb0\x10\x9eTD\x9a\xf8/\x10\x87J\xcd\x1a\n\xe4\xb5X\x1b\xf2\x8d\x98n\x894S\x85\xfb\x06\xf9o\x98\x0fb[Ϛ\x84\xfeǦ!\x9c\xbc@Z\xb0\x10^I\xa4\x89\xff\x02q\xa8\xd4\xec\xb3\xe2\x89+v\x9e\xf0\x1b-Q\x11\xc2k\x9f\x86'Ŵ\x9eQ]>\xc9K\xd3\xe3\xec\xcd\xe0`!\xbcÑƩR\xb3\xeb;\x16O\x16E\x1bc\xf6\xf0S,sb;q^\x1e{U6$`\x0f?8X\bO\xceF\x1a\x87J\xcd\xda\xeb\xf4\x9fs\xbd1\xb7A>0\x84\xdfi\xecڧ.\xb2L\x8a\x15\xfeӜ\xcaOO\x96\x96\xe3|\xe5\xe0`!\xbcÑơR3\x8f0^;n\xa37ǭ\xaf|\xc5L=\x11g(c\x85?&\x8a\x84p'>\xab\x0f\xe2\xc2Bx\x87#\x8dC\xa5f\x1e\xe1\xaaom\xa9\x15Fo\x8eG\xdb\xd2\xe2v}F\xb7\x0f\x1b'l>\x91\xcb\xec[ώ\x8d\u07ff\xd7{\x01;\xf8A\xc2Bxr6\xd28Tj\xb6k\xba\xa7D+t\x9b=Q\xb7V\xe4\xe7No':i6\x9d\x19\u007f\x0e\xec[\xcf\x0eir\x996\x1d!~P\xb0\x10\xde\xe9H3\x92Jͮ\xb8\x96]\xb9}\xfb\xfa\xd1\x05\xf9\xe8\x1f\x19\f,\x84w:Ҍ\xa4R\xb3\x16\xf3\xbc=\xf9\x8bBG\xcf \rX\bONG\x9aA\xe0T\xa9ٱ\x1c3˜\xca9\x91d&\xb0\x83\x85\xf0\x8eG\x9a\xf4q\xac\xd4\xcc_\x9b\xbb\xac\xe9@Ӳ\xdce\xc3\xf6G#\xab`!\xbc\xf3\x91&}\x1c+5\xf3\xb7V\x16kŕ\xad\xf0}P\xb0\x10\x9eF`\xa4\x01#\x13\x16\u008f\xc0H\x03F(,\x84\x1f\x89\x91\x06\x8cLX\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1)Ñ\x06\x80 ,\x84\xcft\xa4\x19@\xa9\x19\b\xc0B\xf8LG\x1a\xfcE\x00AX\bO\x99\x8f4i\xfdE\x00\xa3\x17\x16\xc2+\x884i\xfdE\x00\xa3\x17\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1UD\x1a\x94\x9a\x01\t\v\xe1\x15E\x1a\x00x\bO*\"M:\xb3\xc1\xa8\x85\x85\xf0\n\"M\xdcR3\xef\xd8\xc0ŕƟ\x8c\xbb~\x98\x93s&\xe4M?Pv(y\xebY\xfc\xaa3\xe0$,\x84W\x10i▚\xdd:T8G^>o\x97H\xe1:/Ǵ\xaa\x96]\v\x8c֏d\xadg\xf1\xab\u0380\x93\xb0\x10\x9e2\x1fi\x12\x94\x9aM4.\x98\xf7Q*\xc2W\xba\xfdF#\x82\xb9\xefNR\x02\x05\xe19\xc2Bx\x05\x91&A\xa9\x99)|\xff\xb6\x1b\xf1&\x84\x99h\\z\xe9d\xa0\x8d\x00\u008f@X\b\xaf \xd2$(5\x9b\x18\xb8$jD\xa1\x18\xf9_\x99\xe2z\xb8\xc1O\xb7\x8b\xb4\xdf\x14\x17\x1fX\x91\xef\xee\"ZR(/\xfb\xe5\xdfk^\xeaݦ\xf5,\\T\xa6\v\xffT\xa8\x87\f\xb0\x81\x85\xf0\x94\xf9H\x93\xe0/\xc2\xc4ڞ\x9e\x97e?SD\xa1\xd8R\xad~o\xbdVKt O\xacr\x8b\t\x1b\x8b^&\xfa\xa4$\xa7\xd2s\xb8?\xb0\xa2M\xebY\xb8\xa8L^D{rcKт8?\x158\x03\v\xe1\x95D\x9a\xb8\u007f\x11&\xcas4\x85\xe68T(\xd6fDz㶰\x86\xf6\x8aVZ*\xff\x10\\{\xfeQM\xe4\aN\xbfش\x9eY\x8bʴ\xc2/\x88j\vb\u007f p\x10\x16\xc2+\x894q\xff\"L\xacjo_\x1a\x14>X(VkV:=\xa8\xef\xe2\v\x1b\xe9]\xd1EOט\xcf\xdc\xda_)\xf6\x1a#\x9b\xd63kQ\x99&_!\x81\xba'\xc0\x05\x16\u0093\xb3\x91F\x17\xf3\xd4Ns\x1c*\x14+7\x1bj\xaa\xf4\xa8S\xd8F\xed\xba\xb6u\xba\xf0\xedF\"\xf7\a\x9e\xb4k=\xb3\x14\x95Y\xfb\xcd\x00\x17X\b\xefp\xa4Y\x16\x1e\x87\n\xc5j'Ig\xfd\x13\x97F\b_\xb8\xc2x\xb2\xbeԸ\xb3i=\xb3\x16\x95Ax\x8e\xb0\x10\xde\xe1Hc\x15~q`\xb0W\xc8\xce\xf7F\x19^,\xc2\x17\x15_ӗ\xfa\x03/\v\x9b\xd63kQ\x19\x84\xe7\b\v\xe1\xc9\xc1Hs\xeb\x9d\xc29\x87\xccӌ\xd6B1\xaaɩk\xad\xcb\xd1%?\x95\xffrO\xa3v\xb2\xa7\xc6}\x81\x8aD\xa1\xa7\xadŝ\xfbQ\x9c\xd63KQ\x99\xb5\x87\f\xf0\x81\x85\xf0NF\x1a\xe3\xb34f\xb7\xb6\xb5P\x8c\xfc\xdb\xca\\e\r~\xf2\x17\tј'\\MḄGw\xd6\xff\xccU0O\xd6\xf5ٶ\x9eY\x8aʬ=d\x80\x0f,\x84w6Ҁl\x82\x85\xf0\xe4`\xa4\x01\xd9\x05\vᝌ4 \xbb`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2g:\xd2P\xfa\xf3\xc1(\x85\x85\xf0\x99\x8e4\xe9\xce\a\xa3\x17\x16\xc2S\x86#M\xba\xf3\xc1腅\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10^E\xa4A\xa9\x19\x90\xb0\x10\x9e\x14D\x9a\xb9(5\x03\xc4Dx%\x91&\xe5\x97\a\x18Ͱ\x10>ӑF\xe7\xf8\xbe\x81\xe3\u007f\xf0\x05\xfe\xbd\x9elv\xf2\xce2\vޱ\xa2\xdcO-B\x8cݟl\xaay\xad\xa7\xdad\xb3@\xe6`!<e>Ҭ\x99ֽ=\xf0\xef\xab7\x9eL\xb6B\xf2\xce2\v=\xfbE\xae\x97\xbaZ\xc4\xfe\x9edS\xe9\xf6;\x0f\x97y?K6\vd\x0e\x16\xc2+\x88\xc7O\xf3\xe3\x00\x00\x0e\xfdIDAT4\x83 I\x85S\x98.Q\xa3\xef\xb4?\x11]\xc9&J\xdc\xeed3@&a!\xbc\x82H3\b\xd2\x10~\xbf\xab\a\u008f\fX\bO\x19\x8e4\x89h\xd2C\xb5\x87<\xc2(_\r6\x99\x19\x04\x84_.rv\xd1'\x9a\x98\x1c\xd9oF\xfe]\xe5\xae\aV\xcb\x14\xd3%>\x99\xdab\n\x1f\xea7\x8b7\xd7*|h\xe9r\xa1\xedD\x01\x9a\x1aX\b\xefd\xa4\xe9\xf2\xe6\xd5_\xa1+\xf5\xf9\xde.K\x93\x99$ \xbc\xd10\xec\u007f\xb7V\x8b\xec7\xa3ڜ\x15{\xb7\x15L\xf5\x1b\xc2o\x9bc\n\x1f\xee7\x8b3\xd7*|h\xe9_\x1alj\x02\xcfo\xf3P\x80\x96yX\b\xefl\xa4\xa9]\xa2\xdf\xd4<A\x11Mfd\x894\xe1f\x03K\xbfY\xabq\x8d\xedvٛ\xa0\v\u007fu\xfcUCxK\xbf\x99\xfd\\\x8b\xf0֥Z\xbe\xbew\xafA\x01Z\xe6a!<9\x18i\xf4}qn\x0f\xf5\xb8\xbc\x14\xd1dF\xf6\u0087\xfb͖L꿭S\\k\bOs\xb6\x98\x19>\xdcof?\xd7\"\xbcu\xa9\xb6\x94\xd0\x16\xa2\x04\x16\xc2;\x19i\xf4\xb8=\xa1\x85Z\x8adܰ4\x99\x91\xbd\xf0\xe1\xf6\x9b\xb2@!\xc2<S\xf8\x96\x87\r\xe1-\xfdf\xf6s-\xc2[\x97\xa2\x1eG\x15,\x84w6\xd2Њy\xb4\xc0h+\xb34\x99Q\xb4\xf0\xf5Q\xc2\xd7L:fp\xd5\x14\xbeǵ_\no\xe97\xb3\x9f\x1b\x10\xbe\xab\xfeZ\xc4R\b\xaf\n\x16\u0093\xa3\x91\x86\x0e\x8f\xbf4\xfe\xb0\x1cX\x9a\xcc\xc8\"\xbc\xebi\xfdU\xf0h\x94\xf0m¨'\xae\xdfh\nOKk\xa4\xf0\x96~3\xfb\xb9\x01\xe1O\bo\xc4R\b\xaf\n\x16\xc2;\x1bi\xc8_\\Yl\x9e\x8a\f5\x99Y;˨\xbc`\xe3\xf3\xe5bܮS\xd6~3\xaa\x1b[\xd3\xd2R\xab\x1fx\xf6\xec\x17-]\xe4͕\u0087\xfb\xcd\xec\xe7\xde>\xfcp\x99Wg\x87.|x)\n\xd0\xd4\xc1Bx\x87#\rmѶ\x98\x83`\x93YDg\x19\x9dq\xe7\xe6U>#\xc42k\xbf\x99\xbe\xdfvOȟަ\x1f\xf4\x8e\x95\xe7\xf0\xfd\xe5\x85~K\xbf\xd9t\xfb\xb9\x81\xde4!r?\xb0,E\x01\x9a:X\bO\xceF\x1a\x90E\xb0\x10\xde\xe1H\x03\xb2\b\x16\xc2;\x1di@\xf6\xc0BxB\xa4\x01\x8a`!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16§\x1ci\x8e\x9f\xfd\xf0|g\xe4\x9cΏϞ?\x8b}=H\x11\x16\xc2S\xaa\x91\xc6\x17\x1a\x1d߇]<\x18\x04,\x84O9\xd2\x04\xe6\xe87\x1bf\x9eC\x86\a\xe9\xc3B\xf8\x94#Mx|\xf1\xbd\xf0\xde\x1e\x80\x94a!<\xa5\x1ai:\xa5\xf0\x03\x92s\xc7o\xca;\x9b\x95\x00H\x00\v\xe1Ӎ4}\x884`\x90\xb0\x10>\xe5H\x13\x8e1_\x9e\x8e\x9e\f@\n\xb0\x10\x9eR\x8d4\x92\x8bG\xf6\xed۷砼\xddw\xf08\x92<H\v\x16§\x1ci\xa4\xfb\u007fxlƴG\x1e\x996M\xdeTW_F\xb0\x01\xe9\xc0B\xf8\x94#\x8d\x91\xde+v\xbf\xbd\xef\xed\xf7\xce\x1f\xdc\xf7\xf6ۿ~\x04I\x1e\xa4\x05\v\xe1)\xe5H#\x85\x9f-cL\xe7A\xf9p{\xc59\x99\xebq\xb2\x06\xa4\n\v\xe1ӊ4\xf2\xfc\f\xd1}_;H8W\x03҆\x85\xf0iE\x9a\x17f|\xa8\x0f\xee\xbf\xe3\xa2~\xbb~\xe6\xd9\xe8u\x00H\x04\v\xe1)\x9dH\xf3\xdcc\x9dG\x1e\xff\xe5\xf7\xbf>\xed\xf1\xb5\x03\xdbg\\>\xbd\xa7\xef\xf4\x1e\xcb\xca\x1e\xa1\xb5\xe8w{]\xc2\x13\xb3\xbdh\x96\x8b\x9c\xa6ds\xc0肅\xf0iE\x9auմ\xe6\x8e;\xbe\xa6\xffw\xb7\xafyF\xf7\xeb\x15\xddoL;\x1b~Q\\\xadq\xc9\xda0wn\xcd\xd5\xc8-\x1d8F\xd1\x18%\xdb \xab`!|Z\x91\xe6\xb9\xc7>?\xfe\xec\xda\xff\xfb\xf5\xeag7\x0fl\x9fy\xf1\xdc\xc1\xbes\aoZV\xaa\x9b\xe3\xbaN\xd7r\xe7\xd4Em\xec\xd1%\x14\v\x84\xcf6X\bO\xe9D\x9a\x17f\xc87Y\uf2db\xe1\xebj\xdcM\xb4\xab\xb2&Z\xf8\xa9\x8bc\xa6B\xf8샅\xf0iE\x9a\r3?\xd6\a\xff\xfc\x8d\x83d\x9e\xa5\x89~\xaf\xb5\xae\xa6a\x01\xcd\xd9!\x85\xbf\xb1\xb8X+\xa9:\xa9/l\r\x94\xe7M1\xa6\x9cYT\xa4\x15ι\xa0\x8f\xb4\xa7V=઼@ [`!|Z\x91f\xc3\xec^}\xe03>K\x138\x0f\x1fA]\xcd\x05\xd7\x17\xe3/I\xe1[Ų\x03MU9\xedD]\x87\xbc\xa5ӽ^\xaf,\x8b\xa4\x03\xae)/\xee\xf7\bYU\xa9\x89ɍ-E\v\bd\v,\x84\xa7t\"͆Ƕ7\xefn>rz\xdf\xee\xe6\xe6'm\xdei\xad\xab\xa1\xb2e\x8f\x92\x14\xbe\xa7\xa9\x8b\xc8_6\xcfX\x1e\x8a4=%\x95\xb7\x88\xfa\x9b\xae\xe9c\xad\xf0\v\xa2\xda\x02\x02\xd9\x02\v\xe1ӊ4o̝9\xed\x11\x93i\xd5\vc?K\xa3\v\xff\xa2\xd8h\bOW\x1b*'\xe5\x892cyH\xf86q\"4Y[F\xa8|\xcf*X\b\x9fz\xa4ѹ|\xfc\xa0\xce\xdbo\xcb\xdb\xe36\xdf{҅\xbf\xfa\xd4\x15C\xf8\xf6\u0092\xa7[\xbc\xee(᷈\x9e\xd0d\xe3\xa0\x15\xc2g\x11,\x84\xa7\x94#M\n\xe8\xc2K\xa4\xf0\x93˥ڋ,\xc2\xef\xfc\x94h\xbf\b\x9f\x91\x87\xf0\xd9\x06\v\xe1S\x8f4)`\x11\xbed\x91>\xf0?l\n\xefv\x13]\x11M\xfa\x01l\xa1\xbb_\u007f\xbcb\x15A\xf8샅\xf0iE\x9a$|Q㾤\xdf]r\xd7|A\x1e\xb1\xb8\xe1\xf9\xa9\xa2\xe8\xc5wIj\xbd\xa5\xc5\xed\xfaL\x1f\x1d\x18\xff\xe0\x8e\xb6\x15b']\xf2j\xb5\xef\xfaO\xd4j\xdeKI\xb6\nF\v,\x84\xa7a\x8c4\x1e!\x9e\xd0\xef\x96\t\xe1!\xff\x96R\xad`\xc9k\xa5\x9a\xfc\xb0\xc1\xad\x15\xf9\xb9\xd3ۍ9\x1f-.\xce+o\x91\x9f\xa5\x11B{ߥ\xdf.O\xb8M0z`!\xfc\xb0F\x1a\x00\x12\xc0B\xf8\x94#\r\xec\aC\x84\x85\xf0\x94j\xa4\xe9L/\xcf\x03\x10\r\v\xe1S\x8e4i\x1e\xc0\x02\x10\r\v\xe1S\x8e4\x10\x1e\f\x11\x16\xc2S\xaa\x91\x06\u0083!\xc2B\xf8\x94#M7\x84\aC\x83\x85\xf0)G\x1a\x00\x86\b\v\xe1)\xd5H\x03\xc0\x10a!|ʑ\x06\x80!\xc2BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1\x11i\x80*X\b\x8fH\x03T\xc1BxB\xa4\x01\x8a`!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x89\"͛_\r\xf8h\xa0O\xfeî\x1e\f\x19\x16\xc2S\x82H3\xf7c\x9b'\x00\x18$,\x84O\x18i\xb0[\a\xc3\b\v\xe1\x13\x1c\x9c\x1e\xdf7p\xfc\x0f\xbe\xc0\xbf\xd7-O$-\x15N\xa7\xa1\x18d\r,\x84\xa7\xf8\x91fʹ\xee\xed\x81\u007f_\xbd\xf1\xa4幤\xa5\xc2\xe94\x14\x83\xac\x81\x85\xf0\x83;ߞ\xacc5\xad\x86b\x90%\xb0\x10~p\xe7ۓ\n\x9fNC1\xc8\x12X\bO\x83:\xdf\x1e.\x15\x0e\x17\x10\x13y+K\xb4\xa29%\xfe\x88\x86b\xf2\xef*w=\xb0\xba'\xb2\xa1غ\x1a\xc8\x12X\b?\xc8H\x13*\x15\x0e\x17\x10\xd3ѱK[\xf6\xef,\x12\xb7#\x1a\x8a\xa96g\xc5\xdem\x05S\xfd\x11\rŖ\xd5@\xb6\xc0B\xf8AF\x9aP\xa9\xb0\xa5\x80\xb8\xa1\u0dbc\xcd\xf7G4\x14\xb7\x8a]\xfa\xd2v\xd1(\xd7\v7\x14[{\x8bAv\xc0Bx\x1a\\\xa4\t\x97\n\x87\v\x88?+\x9e\xb8b\xe7\t\xbf\xac\xe9\xb34\x14/\x99\xd4\u007f[\xa7\xb8VN\x0egxko1\xc8\x0eX\b?\xc8H\x13\xaa\x9c\xb4\x16\x10_߱x\xb2(\xda\xe8\x8fh(.\v$wcg\x1e\x12>\xa2\xb7\x18d\a,\x84\x1fd\xa4\t\to) n\xaf\xd3U\xbfޘ\xdb\x10Q\xd8Z3阁qF>\xd4P\x1c\xd1[\f\xb2\x03\x16\xc2\xd3\xe0\"MHxK\x01\xb1G\xb4\xc9\xe7\xdc\xcb\"\x84o\x13ƻ\xb2\xf5\x1b\x8d\xe7\x82\r\xc5\x11\xbd\xc5 ;`!\xfc`\"\x8d\xb5T\xd8R@\xec\x11\xae\xfa֖Zq \xa2\xa1\x98\xea\xc6ִ\xe8K\xe5\xa1k\xb8\xa18\xa2\xb7\x18d\a,\x84\x1fL\xa4\xb1\x96\n[\n\x88wM\xf7\x94h\x85\xee\x03\x91\r\xc5\xfa>\xde=!\u007f\xba\xb1\xf3\x0f7\x14G\xf4\x16\x83쀅\xf04\xa8H\x03@\xfa\xb0\x10~0\x91\x06\x80\xc1\xc0B\xf8\xc1D\x1a\x00\x06\x03\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"\xb8\b\x0f\x80\x12X\b\xaf\x87\xf7\xb7\xb7w\"Ã\xcc\xc3Bxdx\xa0\n\x16\xc2\x132<P\x04\v\xe1qZ\x12\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1Bx4n\x03U\xb0\x10>\x10i\x00\xc88,\x84'4n\x03E\xb0\x10^\x8f4\aw\xf7\x1d\xd9\xec;\xf2\x92\xfe\xaf\xf7\xf8v\xeb\x93\xc7r\x8c\xf2\x8e\xd8\xee\xb1-\xe3\u007f+\xef\x92Vr\x03\x10\x86\x85\xf0\xfa\xce\xfd\x85\x857߬\xee6\xff\xed\xf9\xa5\xf5\xc9\xdb\xefx\x1b\xc4\x16\xef;\xfd\xd1k\x95iF\x95A\xd2Jn\x00°\x10^\xa7\xf7&}\xf9q\xe0_\xf7Ũ'\xdb\xc5;\xb1kt\xe5\xd4\xe4t\x19#\b\x0fR\x86\x85\xf0\xc6\x1bO\x9d\xf1\x9f\xb7\x15\xde+\x8e\x89\x03\xc6\b\u0083\x94a!\xbcq\x96\xe6\xfc@o\xbcӒ!\xe1\xc35\xdbD\x9eb*6M\xd7V<Q\x9c_u&z\x02\x00\xb1\xb0\x10\x9e\x92\xbc\xf1\x14\x14\xdeR\xb3M\xe4^D\x8bͮ\x1aMLij,s\x9d\x8a\x9a\x00@,,\x84O\xf6Y\x9a\xa0\xf0\x96\x9am\xf2\xbb\xb6\xd0\xcb.cW\xaeM\xee!\xea)-\x8f\x9c\x00\x80\r,\x84O\xf6Y\x9a\xa0\xf0\x96\x9am:)\x0e\xf5\x1c\x12'\xe5P{F\xde\xee\x10\xd7\"&\x00`\x03\v\xe1)\xc5Hc\xa9٦m\xc6\xd9\xf9mr\xa9yЪ\x1f\xc4FL\x00\xc0\x06\x16§\x1ai,5۴hJ{{\xfb\x14Y-L\xda*y\xbbS܈\x98\x00\x80\r,\x84O5\xd2Xj\xb6\xa9x\xb5~\xb3\xaaX>֊o\x11\xf5?莜\x00\x80\r,\x84\xa7D\x91&\xf0N\xeb\xe1~\xb2\xd4l\xf7\xb4\x89\xfa.\xea\xfa\x8dh\xbb%\xcf\xd2T\x1e\xde_\x9e\xff\x91u\x02\x00\xb6\xb0\x10>a\xa49\x11\xfe,M\xb8f{\xffX!\x9a\xa8E\x88\xb1\xfb\x89\x1e\xf4,\xce+\xae\x91=\xf3\xe1\t\x00\xd8\xc2B\xf8d\x91\x06\x80ႅ\xf0\x84o<\x01E\xb0\x10>\xd9Y\x1a\x00\x86\v\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1\x11i\x80*X\b\x8fH\x03T\xc1BxB\xa4\x01\x8a\x80\xf0 \xab`!<2<P\x05\v\xe1\x91\xe1\x81*X\bO\x884@\x11\xce\n\xbf\xc7\xd7\xd9\xeb\xeb\xeb\xd3\xff\x1d|\xb3S\xde\xf5Q_o\xaf\xaf7\xd9z\x00\f\x12g\x85?B>y\xa7g\x99M\xb3\xcf!Ҁ\xcc\xe3\xac\xf0\xbeШ\xf3\\x\f@\xc6pVxyb\xe6\xf8\xeeM\x1b\x9e[\xff\xec\xda\xf5ϭ\xdf\xf0zs7\xceՀL\xe2\xb0\xf0z\x8aٺp\xf6c\xb3fUϟ=k\xd6c\xd53.\"\u0600L\xe2\xbc\xf0\x1b\xa6\x1d9\u007f\xf6\xfcM\xba|\xf6\xfc\xf9g\xa7!Ƀ\x8c\xc2@\xf8\x8a\x9b\xfa`\xdfJ\xf9pkŹ\x81^\x94\x9a\x81\xcc\xe1\xbc\xf0/\xcc\xfcP\x1f\xfc莃\xfa\xa3\xe7f\x9eK\xb6\x06\x00C\xc1y\xe17\xcc<\xab\x0f\xee\xbfCޮ7\xc6\x00d\f\xe7\x85_?\xb7{\xf7}\xf7\xde\xfd\xb5\x1f\xdc\xf7\xf3\xbe7ft\x1e\xdc\xe0;\xbe9jV\x8b\xbc\x12\xd3\xc4\xe8+\xa4\xee/h%\x00\xd2\xc3y\xe1\xd7U\x0f\xac\xfd\xc6\xd7\xff\xee\x8eo|\xe3;\xbe\xe6\x19ݻ\xa3K\xcdt\xba\x0ey\xf3\x16\x9d\x8a^\xb7\xd5\xd5\x12\xbd\b\x80$8/\xfc\x86\x8a\x8b\x9dǏ\xdf\xfb\xf5\xed\xc7ߣ\x97f\x9e\xef>Oݗc'\x16\xad\x8e]\x86\x8bb\x83\xb4q^\xf8\x17f\x9c\xd6\a\xf7\xca\f?\xb0~V\xbc\fo'<\x00i\xe3\xbc\xf0\x1bf\xc9\x1d\xfa\xac\xefI\xed7͌wZ\xd2\x14\xde\xff\xca\x14\xd7\xc3\rr\xcf~=W\x88\x9cF\xb9l\xb9\xd0v\xaez\xc0Uy!v%\x00\xa2a |ŗ\xa1\x87\x9b+\xe2\xbd\xf1d\n\xbfT\xab\xdf[\xaf\xd5\xcaa\xbb\xd7;\xdeh\xfe\xf8K\xe38Q\xe0\xf9m\xde\x02\xdb\xf5\x00\x88\x80\x81\xf0\xf3\u05ec\u007fv\xdd\xd6ן{v\xdd\xfa\xf9\x8f\xc4\xfb\x1a\x88!|\x9b\xd1w`\xde\xea\xe4\x06\xfaY\xb5|}\xef^S`\xbb\x1e\x00\x118/\xfc\x9e'\xab\xe7Ξ]QQ1{\xf6\xdc'Wv&\x12\xbe\xd6蚧\ak\xcde!\xe1\x97\xea7\x1e\xcdv=\x00\"pXx\x9d\xde\xce\xcb:_\xf5~\xae\xdfv~\x15o\x96!|y\x951\xae*7\x97\x85\x84\x97\xf7\x10\x1e\xa4\x82\xf3\u0093\xf1!\xe1͏w\xc6\xf9`\xf0\xed\x0f\xe4A\xea\x04c\x0f?\xc9hh\x9d\xb8\xd4|\x06\u0083\xb4q^\xf8\x01\x9f\xaf\xdb\xe7{|\xda\x11_w\x9f\xcf&ϼ\"\xbcDW\x8d\x82ʽB\x9e\x97i\x14{\xcdg <H\x1b\xe7\x857\xe9\xee\x8c\xf7ŏ\x03bNˮ\xf2\t\x9f\xc9qMN]k]N\x8d>\xea\u007f\xc7\xeb\x1d_\xeb\xf5ޠK^\xad\xf6]\xff\x89Z\xcd{)\xce\x16\x00\b\xc1Bx\x1f\xd1\xf6'\xcfR\x9c/\xf9\xb5Lu\xe5W\xbdo\f\xfd\xdb\xca\\e\xc6y\xf8\xa3fՙ\xd8A\xcb\xf5[\xed}\x97~\xbb\xdc~}\x00°\x10\xbe\x97H\x8f4\x84\x8b\x15\x80\x8c\xc3BxJ\x14i\x00\x18FX\b\x8fK\xed\x01U\xb0\x10\x1e\x97\xda\x03\xaa`!<\xe1R{@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E@x\x90U\xb0\x10\x1e\x19\x1e\xa8\x82\x85\xf0\xc8\xf0@\x15,\x84'D\x1a\xa0\bg\x85G\xa9\x19P\xcc\xff\x0f\x19\x026\x1d6\x9ff\xc5\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/typeinfo-pkg.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x042\x00\x00\x03\xa2\b\x03\x00\x00\x00\xb5\xb6\a\xdf\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x03\x00PLTE!# #$\"$%#&(%()'*,),.,/0.231463685;<:>@=BDAGHF\x00f\x00JLI\x00j\x02\x03l\x04OQN\rp\nSUR\fr\x17VXU,`\xae7]\xad8^\xae\x16w\x1d[]Z8a\xaa:b\xab;b\xac<c\xad`a_=d\xae?e\xaf@f\xb0*{!bdaAg\xb2)}*Bh\xb3Ci\xb4egdEj\xb5higMj\xb0Fm\xb2/\x82/Ol\xb1Ho\xb4Pm\xb2Ip\xb5/\x858Jq\xb6molKr\xb7Ms\xb8Nt\xb9pro=\x87<Ou\xbaXv\xb6tvs@\x8b?Yx\xb8Zy\xb9@\x8dG]{\xbbxzwI\x8dH_}\xbdX\x80\xbf`~\xbeZ\x81\xc1|~{`\x81\xbbb\x80\xc0N\x92Mb\x83\xbdM\x95U\x80\x82\u007fd\x84\xbfW\x95Vf\x86\xc1h\x88\xc2Z\x98Y\x85\x87\x84i\x89\xc3j\x8a\xc4q\x8b\xc1^\x9d]\\\x9dc\x8a\x8c\x89s\x8e\xc3d\x9deu\x8fŎ\x90\x8dw\x91\xc7h\xa1hy\x93\xc9z\x94ʀ\x94Œ\x94\x91z\x97Ɓ\x95Ƃ\x96\xc7q\xa5r\x83\x97Ȗ\x98\x95\x84\x99\xca\u007f\x9cˆ\x9b̀\x9d͙\x9b\x98u\xaaw\x81\x9eΈ\x9d\u0383\xa0ψ\xa0\xcb\u007f\xabz\x9d\x9f\x9c\x8a\xa2̠\xa2\x9f\x8c\xa4\u0380\xb0\x84\x8d\xa5Ў\xa6ѣ\xa5\xa2\x82\xb2\x86\x8f\xa7Ҥ\xa6\xa3\x91\xa9Ԍ\xb4\x89\x98\xabє\xac֩\xab\xa8\x99\xacҚ\xadӍ\xb8\x93\x9b\xafԮ\xb0\xad\x9d\xb1֗\xba\x97\x9f\xb3ؠ\xb4٢\xb5ۛ\xbe\x9b\xb3\xb5\xb2\xa3\xb7ݣ\xbf\x9d\xa9\xb8٢\xc1\xa4\xaa\xbaڸ\xba\xb7\xa5\xbd۬\xbbۭ\xbcܦĨ\xae\xbdݯ\xbfߨǪ\xbd\xbf\xbc\xb1\xc0\xe1\xab\xc3\xe1\xb0Ǭ\xb2\xc1\xe2\xb6\xc1\xdc\xc0¿\xb7\xc2ݸ\xc3\u07b2\xc5\u07b9\xc4߳\xc7\xe0\xba\xc5\xe0\xb2ͷ\xc5\xc7Ļ\xc7\xe2\xbc\xc8\xe3\xb7\xca\xe3\xbbκ\xbe\xca\xe5\xb9\xcc\xe6\xc9\xcb\xc8\xc0\xcb\xe6\xc1\xcc\xe7\xc2\xcd\xe9\xbf\xcf\xe2\xc0ӿ\xbc\xd0\xe9\xcd\xcf\xcc\xc7\xcf\xe4\xc8\xd3\xc1\xc8\xd0\xe6\xca\xd1\xe7\xd1\xd3\xd0\xc8\xd7\xca\xcb\xd3\xe9\xc5\xd5\xe8\xce\xd5\xeb\xcc\xda\xce\xd5\xd7\xd4\xcf\xd7\xec\xd0\xd8\xed\xcb\xda\xee\xd5\xdb\xd0\xd4\xd9\xe9\xd6\xda\xea\xd9\xdb\xd8\xd7\xdb\xeb\xd2\xde\xec\xdc\xde\xda\xd9\xdd\xed\xd6\xe0\xdb\xd4\xe0\xee\xdb\xdf\xef\xde\xe0\xdd\xd5\xe1\xf0\xe0\xe2\xdf\xdd\xe1\xf2\xdf\xe3\xf3\xe3\xe5\xe1\xda\xe6\xf5\xe1\xe5\xf5\xde\xe7\xef\xe5\xe7\xe4\xe6\xe7\xf1\xe0\xe9\xf1\xe7\xe9\xe6\xe1\xea\xf2\xe2\xeb\xf3\xe3\xec\xf4\xe5\xee\xf6\xec\xec\xf7\xeb\xee\xea\xed\xed\xf8\xe7\xef\xf8\xe8\xf0\xf9\xf0\xf0\xfb\xed\xf2\xf5\xf0\xf2\xef\xee\xf3\xf6\xf4\xf2\xf6\xf2\xf4\xf1\xef\xf5\xf7\xf0\xf6\xf8\xf2\xf7\xf9\xf3\xf8\xfb\xf7\xf9\xf6\xf5\xfa\xfd\xfa\xfc\xf8\xfd\xfb\xff\xf7\xfd\xff\xf8\xfe\xff\xf9\xff\xff\xfe\xff\xfc\x8c\xab\xeb\xca\x00\x00 \x00IDATx^\xec\xbd\x0fpT\xd5\xdd\xff\u007fu\x8d\x80\x80\x80\x88r\x02\x99\x8d!\x85\x87\x80~ML%\xa0\x86\xca\x17j\x11\xed\xfc\x8c\xa8\x93<\x0fc\xa4\xa2\x8fm\x9c\xaf\xd16T\xa0\xea\x83X\x91g\x88\x98\x87>t(\x14\n\xa2և\xa1\x8c\xed<\x86\xe1\xa9y\x06\xa4)jU\bJ\xad\x04\x19\x89ЂR\xadB\x88$s~\xf7ܿ\xe7\xde=w\xef\x9eݻٽ\xbb\xef\x97#\xb9{\xf7s\xce\xf9\x9c\xb3{\xde{\xef\xb9w\xf7\xadP\x00\x00H\x18\xc5/\x00\x00\x00l \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t|$\xe3\x18\x00\x00p@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12\xc8H\xc6\a\xbf\xf7\xa8D\x8a\xdf6\xce\xf8?ђ\x8a;\x9ey\xdf/\x12\x00\x90u$.\x19\x9f\xb4\\\xb5Գ\x9a\x84\xd9\u007f\a1\x19\xd7\xe2\x17\f\x00\xc86\x12\x96\x8c\xdf\xcf$$u\xc9\xf8`\x06\xe1X\xe1\x17\x0e\x00\xc82\x12\x96\x8cz\x12\x84d,aJQRS?\xb7\x82mD\xff\xe0\x17\x0f\x00\xc8.\xfaY2&\xab\xb5,\xf8@\xdd8\xfc8ӌF\xbfx\x00@vѿ\x92\xb1\x9f\xe9\xc4\a\xfa\xf6lusF\xfcp\x00@\xb6\x91\xa0d4\x9a\xcb\x0f\xcf/P\xff\xb9Y\xdf\xf9[u\xb3X\x15\x80(!\x15\xc7\xf67M+.\x9b\xfb\xbcY`\u007fӍ\xe3\x8a+\xeb\xff\xcbٚ&\x19F\xcc\U000cd34dKD\xc1\x875-Yqm\xb4\xa2\x9e\xe9T\x9d\xbe\xf7\xad\xd1\xea\xf6[q\xa3?9\x06\x00H3Ғ\xc1tb\xf4~kg\xfd1]2~;Y\u007f\xbe\xfe\xb0\xf6ԆqF|\xeda\xbe\xb5O\xd8\x12Fq\xa3\xebb\xad+X\x13\x81\xc7\xd8\xe3\x9a\xff\"\xba(\xa9,e\x8f\xe3G\x1f\x03\x00\xa4\x1bi\xc98VE\xccK\x1d\x15D?dP%c\xc2D3\xe0^\xf6\xcc\xf3\xa3͇\xa4\xc6\xf1ٿT\xdfY1\xff\xb9\xb7\xac}\xee`&\x02\x13\xb4}\xab>\xb9V\xfdW\xbf\x16{\x83\xba\xb5&~\xf41\x00@\xbaIP2\xfe\xf0\xfc\xadꤼ\xf7\xf9\xe7\xf7k\xb3^;3\xf9ou\xe3*\xf6I\x1fe\x13\xb6l\xe9\xf3͕lC=a\xf8\xa0L\xfd\xfb\x9du\xbf}z\x82\xfa\xb7\x99o\xee\xf0\xcdք\xbf\xf1\x19\xfd\xf0!&\xf8\xb0\xf6t\xd1w\xa6\x16\uedcf-~ϔ\xe1\xb0O4\x00 \xdd$(\x19\xdc\xf2'[T\x18͎\x11\x9a\x88qɃI\xc6D\xb6g?ӌ\xdac\xc7V0E`b\xf2[5v\x9a\xa3\xbd\x0f\xe6[\x9aA*\xb4刘`M\x04Jԓ\x97\x9dj\x8dEFc\xec0\xe7\xff\xf9E\x03\x00ҍ\xbcd\x1c\xab!\xfa\x99\t;i\xd0V%\xa2\xd6S-\xeaV\xe9'Z\x84~\x9a\xf0\x1du\xeb\x0f\x8e\x06\x8f\xfd\xfe_\xad\x93\x98\xe8o\x8d\xea\x1c\xc1\x9a\b\xfc\xab\x11]\xabn?\xad\xee\x9bl4\x16?\x1a\x00\x90f\x92\x90\x8c_\xa8[\xb3\xf5S\x85\x1b\xb4\x1dL2\xfe[\xdbz\x8b\xcd߷\x8e1M\xa8kdLS\xb7~\xe1n\xf3\x93\xff^ZS\xa2iƵ\x9f\x1c\x8b\r\xd6D\xc0,\xf4<\xd1.\xc5\x1a\u007f\xfc\xa2\x01\x00i&\t\xc98<AӅ&kG\x94\x18\x97?\xf5\xf9\xfb{}y\xc1Bx[\xf8\xe1uS\xd9s\xffu,6X\xdb\xf3\xdff\x1c[c\xfdñ\xf9F=>\xd1\x00\x804\x93\x84d\x1c\xfbWm\xb2N3V\x19t\xc9\xf8\x83\xb6\xa5\xcdߝ\xaey\xcd\xdd\x00\xf6\x8b\xa5\x8d\xf5\xe6\xad\x1b\xfbK\xb4jb\x83\xb5=\u007f0\x8b\xb0[̗\x1c.1.\xb6\xfaE\x03\x00\xd2K2\x92\xc1.\x95\xdc\xfc\ab\xdd\t\xc1$C\x17\x02\xe3Ą\x89\x81\xeb&.\x1dv\xc7g\xbd\xf9\x80]6m:\x16\x1b|X\xafĀ\xad\xb6\xde\xf0\xbcU\xce'\x1a\x00\x90^\x92\x91\fv\x80Aء\x86\xf1\xedu&\x19\xffO\xdbb˟e\xfa\xca\xe4O\xb5\x1d\xff\xe5\x9c\xcc\xecd\xc6\xfc.\xda[\xac\xd8\nA\xb0K\x04\u0602\xe7͖P\xf8E\x03\x00\xd2J\u00921_?&\xd00n\xc8*1\xee\xecds?ʖ\x13>\x98\xaa\x1f\r\xb0\xaf\x9cMf\xe7\x11\xea\xf1H\xe9\xcd\xdc\xfd\x12\xecЄThG$\xbfg\a\x19d\xa7 X\x13\x01\xbb\xd0/\xf4\xc6*\xf5[\xc2\xfc\xa2\x01\x00i%a\xc9`G\x15\x13\x97\xfc+\xbb,z\xec\xadBm\x16\xcf7\x9e\xd2n\xe5*nZ\xb7\x82\xdd\x18J~k,S\xccx\xfe\xad\xe7\xd9ڥ\xe3>\xeez\xad`\xf9\xcds\xa7j\x1bs\x8f\t\x82]\"p\xb8L\v}\\\u007f\xe4\x17\r\x00H+\tKF\xb36q\x8d{9\xe7j\xdb\xe6\x9a\x02\x93\f\xfd\xa2)1\xceP\x9e#\x16\xe3\xfe\xc07\xf7\xfe\r\x84\xa3j\xbf(\xd8-\x02?d\x8fG\x9b\xe7\x1e~\xd1\x00\x80t\x92\xb0d\xbc\xaf߀\xa5\x9f\x9bh'\v\xe5\xe6\xb7G\xb4\xe5\xcf*}\x1a/\xd0OV\x9aM\t\xf9?\xbfu\xb6\xb7\xbfΞ\xf2s\r\x19p\x05\xbbE@;\x9b\x99k=\xf4\x89\x06\x00\xa4\x93\x84%\xe3\xd8\x1f\xea'G'\x1b\xdfng\x17=\xc9\x0f\xcdg\xb4\x8b\xac\x1f4M\x8dr_~\u007fkɌ\xb2\xa2\t7/\xfd\xe0\x98\x9b\xdf7~gr\xb4\xb8\xe2;?\xb4\xc5\xc4\x19\x1c#\x02\xec\xeb-\xeb\xec\x87>\xd1\x00\x804\x92\xb8d\xf0\xecd\xf3\xd4\xfa\n\xbb}_\x06\x00 \xc7IJ2>ak\x19\xf6\xd7\xcd \x19\x00\xe4\r\xf2\x92\xf1\x8b_<\xc7n\x95\xe0\xee\x03\x87d\x00\x907\xc8KF\xad\xbe\xf8Xa\xff\xdc\x16$\x03\x80\xbcA^2\xfeUS\x8cq\xdc7\xc1 \x19\x00\xe4\r\xf2\x92\xd129Z<\xad\x81\xbfE\x1b\x92\x01@\xde /\x19\x00\x80<\x06\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\xc0G2\x00\x00\x80\a\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90 e\xc9\xf8\xfcD\x17\x00 oHQ2\xbe\xf4\xab\x1f\x00\x90S\xa4&\x19P\f\x00\xf2\x8c\xd4$ïv\x00@\x8e\x91\x92d|\xeeW;\x00 \xc7HI2\xb0\xf2\t@\xbe\x91\x92d\xf8U\x0e\x00\xc85 \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\t\xd0\xe9\x17\x00@\xde\x00\xc9\xf0c\xef\x94A\xcax\xbf \x00\xf2\x05H\x86\x1fC\x87>\xbcr\xb7_\x10\x00\xf9BVH\xc6\xf6\xb1\x03\a\x8cZ}\xf1Z\xbf\xb8L\xb0]Y\xe9\x17\x02@\x1e\x11\xb0d\xac\xde\x14\xbbϗM\x91+\x9e\\<^Q\x9e\xf0\v\x94F&\x1d\x8f\xd8MJV*\x19\x00\x19\"`\xc9\x189)v\x9f/c/g\xffNI\x83dȤ\xe3\x11\v\xc9\x00\x80'`\xc9\x18.1G-\x86\xdc\xc6\xfeݮ<\xe9\x17(\x8dL:\x1e\xb1\x90\f\x00x\x82\x94\x8c\xe5\x8a\xcep}\xf3\xb6\xaey\xea\xbfOLWο\xff\xba\xc1\x03\xafxU\x8bytd\xc1\xd0Y\x1d\xcer\x93.ڮ\x15\xef\xe0\x03^:_\xad\xe1\xd5+\x87\x14\x8c\xed|B\xadf\x9e^\x998\xc0Q\xdbڱ\x83#\x03\xc7\x0ev\xa4\xc3\xc5NW\xce[\xdc\xf5ZD\x19\xaa\x05\xbf6~`d\xd0\xd8\xdd|\xac\x8bՐ\f\x008\x82\x94\x8c\x8e\xb5\xab\x87\x8eZ\xbdz\xf5\xabls\xf0u{\xbb\xf6\xde5`m\xc7\xf6\xc5\xe7+\x83\xe7\xcd\x1b\\\xc0ta\xcayӗ\xdf?p\xb8s\x92\xef\x1e|\xde\xd8yk\xf5}V\xc0_\x9eX<x腃g]\xa9\xec\xeeX;\xe06\xa32q\x00_\xd9&eʓ+\x1f\x1e\xa8t\xf2\xe9p\xb1\xbbWG\xeeRueJ\x84\x05\xaf.\x18~\xcfʻ\x94{\xf8X\x9eν\xabG\x0ep\t\x1c\x00yM\x90\x92\xd1\xc5\x1f\xdd\xdf\xc5>\xb0\xa7La\x9b\x91!\xea\xac\xeb\x18<\x92}\xf0?\xda\xc5f\xf5bg\xa9\x8ey##\xca\x00v\b\xe1\b\x18\xae\\\xce\n\xb2zX\xb5WN\xf1\x0e\xb0yp Ӟ\xfb\ah\x0f\xb8\x93\r;\x96IF\xd7]L2\xfe2\x98\x1d\xa1t>\xd1ኵ\x18\xaf\x1ex,\x8f\xdd\r@\xfe\x926\xc9حl\xef\xea\xbcP\xbb@\x19\xd1\xd6*\xeeW:\xba&\r\xe9d\f\x9e\x12S\xb0s\xe5X69\x1d\x01\xc3#\xe6\xf1\xc3ꂎ\xae?\x17\xac\xee\xf2\f\xb0\xd9}ѐ\xe9\x0f\xbfdܰ\xc9K\x86\x15kK\xc6r\xe5%\xbb\xa0H2v\xaf|p\xe8@\x1ce\x00`\x936\xc9\xe8\x1a;\xabk\xe5\x00m\xe6js\xb4k\xb5\xb2I\xfd\xa8\xd7q\xdeM\xb9I\x9f\xcc#\xaf\xe8r\x06\f\xb7V\x16:\a>ٵ\\;|\xf0\b\xe0\xe8xp\xd2Pe\xd0=\xda6/\x19V\xac-\x19\xf7+\u007f\xb1\xcby,\u007f\xb2\xb4\x01\x00&鐌\x875\tP\xa7\xb8~^\xd2\x15\x99\xc5\xfe}X=ʸr\xc8&\x8dw\x1d\x85.\x9a\xae\xfd\xb9mH\x973`\xb8\xad,\xd3\xc7w\x8dע\xbc\x02,6\xcdQ\xff\xe9X\\\xf0\xa0\x16`\xa7c\xc7j\x92q\x1b\x93\x8c\x951G\x19\x0f\xc7\x1c\xb6\xe0\x8a\t\x00<\x01KƨQ]]{\xf5\x1b,:\a.\x1f\xb8Z\xdb\x19\x19\xc4V\x11\x86\x8cbsT{\xea\xb6y\x8eB\x03\a\xeb\x8b\t\xe3]\x01\xdc\xe7\xfe\xda\xc8\xee\x886u\xbd\x02,\xee\xd2\xef\xd6\x1cu\x9d\xf6\xaf\x9d\x8e\x1d[\xa0\x8aJ\xe7H&\x19\x1d\x17\x8dbG.\xd3g\xb9by \x19\x00\xf0\x04,\x19wE\xeeY~y\x81\xfeQ=g\x88~^\xd2\x15Q\x86?\xf1\xf0\x90\x01\xaf\xb1}ʤ'\x96Oq-\u007f\x0eT.\xbak哗\x17\xbc\xca\at\xea\xd70^3b.\x1a{\x91\xbe\xe1\x15`r\x97Rp\xd7\xf2'\xa7(\x9aZ\x99\xe98bG\r\x9c7o\xa4r\xfe\xa3\xdbճ\x8e\v.~p\xf9t\xe5a>\xd6\x05$\x03\x00\x9e\x80%\xa3s\xfa\xc0\x82Q\xc6\xc9\xff\xab\xcau\xfaFd֔\x01\x17]\xa9Oƕ\x97\x0f\x1c0\xca\xf5\xad\x8d\x91\x0f\xdf6\xb4\xc0\xbcq\xc3\fx\xe9<m\xcdb\xac\x11s\u007f\xe4\x1ec\xcb#\xc0\xe4\xd1Q\xf3\x06G.\x1a\xa5\x1fߘ\xe98b_\x1dUp\xe1\xd8\xdb\x14\x85\x9d\xe8\xbc:i\xf0\x85#\x9ftĺ\xd8{\xfe\xa4\x97\xf6\xe2\xdb\xef\x00\x18\x04,\x19<\x1d\x11}\xde\x1a˟ae\xf9P\xf7r-\x00yL\x1a%㉁Ƈs\xb8%C=\xd0xi\xaf_\b\x00\xf9B\xba$c\xde\xea\xae\xcbM\xa5\b\xbbd\x00\x00,\xd2$\x19\u007fV\x86O\xbfH\xbf\aj\xf7\xea\xc8\x14\xac \x02\x90#\xa4I2\xba\xee*\xb8\xdc\xf8\xbe\xc6tEQ\"\xee\xeb\x1a\x00\x80p\x92.\xc9\x00\x00\xe4$\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x99\x96\x8c;\xef\x14m\x02\x00\xb2\x94\fK\xc6\xff\x0e\xfb\x9e`3E~y\xd9\u007f\xfa\x85X\xbc\xf7ϗ\x8d\xf8\xbf\xfa\xd7\xe7\xccbw\x0e\x1b6\xec\x92\xd7\xe3\x94\xf1\xe6\xf5\x11\xc3\xfe\xc9/&3\b3\x13t\x9e\xc35\x0e\xd9\xdb7ЯdX2n\x1f\xf1'\xc1f\xa2\xfc\xeaw\xc2\xdd?\xbf\xe4Y\xe1~\x11ߺ\xec\xa9;/yO\xdb4\x8b\xfdq˖\xa7\x86m1\x9e\xf7h\u008b\xdf\xdc9\xc2/$\xbdx\xe6+\xcaL\xd0y\x0e\xc78teA\xdf@V\x90Y\xc9x}\xd8݂̈́\xb9\xfa\xbb~\x11~\xbc7\xecߺ\xba\xb8\xdf\f6\xf8\x8d5Ud\x9bx$\xc3\xd3\xca;\xdf\xd8\xcc<:\xcf\xf1\x1b^22\xde7\x90\x15dV2\ued0f,\xee\x94?Ȑ\x9eϱ\xbc>Lx\x0e\x93\x1f\x92\xe1\xd1y\x0eH\x06\x88!\xa3\x92\xf1\xfa\x88\xbb\x05\x9b\xf6\xd3\u07fdl\xc4e\xffWS\x92\xa7\xae\xbe\xe4\xea\xa7Կ\xff2l\xc4Sw\u007f\xe3\x92o\xfd\xb1\xab\xeb?\x87\xe9\\\xad\xee\xee\xf8\xee\x98\x11c\xbe\xad\x1d\x93\xbfw\x89\xbaO;\xc8\xe6b\xbb\xba\xb6|k\x8cZ\xd7\x18G\xfd\x9d\x97\xe95\xdc\xed(\xc60\xa6\n\xdfDW׳\xd7_\xf2\x8d\xef\xa9\x1fʿ\x1b1l\xd8\x0f^\xbf}̈our{\xbb\xba\xfet\xfb\x98K\xbf\x1b{\xf0n\xa6\xee,f\xf2/\xacU}\x99\xc0\x91\xafU\xef\xff\xa8ž\xdd5fذK;Հ\u007f\xbbs̥\xdf~ݫ^q\xbe\xe2\xcc<;o\x17\xe3$\x83\xabA4\x92 \x8fȨd\xdc9⏂M\x93_]r\xf5\x8f\u007f\xf9Ȱ\x9fh\xcf\xfe\xe0\xe7?\x18q{W\xd7\xff>;b\xd8e\x8f\xfc\xe4\x12\xf5\xb3\xf4\xcf[\xb6|\xe3\xfa-[\xb6\xbc\xae>\xff\xf3aw\xfe\xea\xd9o\x0f\xfb\r+\xf6\xbb-[F<\xc26\xb8خ\xdf\r\xbb\xfd\xd9_>u\xd90\xe7\x8fx\xfen˳\xc3\x1eٲ\xe5O\x8eb\fc\xaa\xf0Mt\xdd9\xec\xee\x9f\xff\xdbeWwvu>\xfb\xec\x98o\\2\xe6\xeeۇ\xfd\x91\xdb\xdb\xf5\xfa\xa5\xdfx\xea?\xbf5\xcc-\x19V\xea\x8eb\x16\u007f\xd2ZՖ\t\xf8|\xb9\xd6~\xf3\x88گ\u007f\x1f\xf6\xecﴀ1?~d\xcc%\xff\xe3Q\xaf8_\x8f\xcc<:o\x17\xeb\xb2%\x83\xabA<\x92 \u007fȤd\xfcq\xc4?\v6M:ǰ\x8f\xe3\xceg\xdf\xeb\xea\xfa\xe5\xb0_v\xb1\u007f\u007f\xae\xfe;\xe2Ru\xc6\xdd~\x99\x16b\x1d\x85\xff\xe5ٿ\xf0\x0fͷ\xbf\x1d\xfb\xd4e\xec-\xfeԥ].\x1c\xc7\xe61\x92\xd1\xc5\xd5\xf9\xf3a\xff\xae=\xa1}\x18_=\xec[\xba[#\xb7\xf7\xfao\xa89t^횘|\xeav1\x1e\xadU\xfd\x98\xdf\xce\xd7\xd1ڝ\xdf|ȍ\xf5\xd81j\xe1\xf7\xc6|ӻ^Q\xbe\xe2\xccĝw4l\x8d\x03W\x83\xd7H\x82|!\x93\x92\xf1/#^\x17l\x9a\xfc|\x98\xb5\xf8\u007f\xa7~u\xef\x9f؍\x1b#\xd8?\xc6Y\xb5}\xe2\xfe\xdeS\xdf\x1as\xa9q@\xceI\x86\x15\xfb\xc71c\xfe\xe5\xa9\xdfu\xc5|4&.\x19\xdf\x1d\xa39;\x8e\xd1n\x1e\xb9\xda<&\xb2\xf7\xbe7\x8c\x9d%t\xfd\xc051\xf9\xd4\xedb<\xbcdX\xf9:Z\xeb\xbc\xfa\xb2o\x1b\xb1\xdau视\xbd\xe7Y\xaf _\x8f\xccĝw4l\x8e\x03_\x83\xd7H\x82|!\x83\x92\xf1\xa7\x11w\n6-~b\x1f\xfb^\xafϘo\xab\x9f\xae\xfc\f\xb3\xe7\xc7o.\x1b\xf3\xbd\xff\xd8r}\x8cdر\xef=\xf5\xdd\u007f\x1avُ\xbb\\$.\x19W\x1b\xeb\x04\xda㫯\x8e\xd9\xfb;\xbd\x88{\x89\x90O\xdd.\xc6\xc3K\x86\xb5\xe9h\xad\xebY3\x1d=\xc3-\xaa\x98z\xd5+\xc8\xd7#3q\xe7\x9d\r\x1b\xe3\xe0\xa8\xc1c$A\xbe\x90Aɸ{\xd8\xeb\x82M\x8b_qG\x19\xfab\x9b\xf6\xd1\x17#\x19O\xa9\x9f\xb0\xff\xf4Mvb\xf2]o\xc9\xf8\x1d\xfbx~\xef\xd9\x11Ou9IL2X\x13\xb7\x8f\xf9\x9d\xc6{\xd6^\x86\xbd\xd7\xf8$v/\u007f\xf2\xa9\x8b/gh\xad\xfe\xc0%\x19\x8e\xd6\xfet\xd9\x0f\xc6\xe8wO\xe8k\xc4O\r\xeb\xf0\xacW\x90\xafGf\xe2\xce;\x1av\x1de\xdc\x19o$A\xbe\x909\xc9\xf09\xc8\xe8\xfa\xcbe׳Ì\xbb\xeff\xe7(\xec\xd4\xfaY}-\x83\x93\x8c\xeb\xafW˲\xe7ư\x89\xd2y\xb5\xb7d<\xa2\x9d\xfaw]\xef^1\xf1\x95\f\xab\x89_\xea\xa7\xf7?\xd0>^\xad9\xca\xed\xfd&\x9b֯\x8fpML>u\xb1d\\\xa2\xce\xc1\xceo\xba$\x83o\xad\xf3\x9b?\xe8\xbaS\xbf\xcc2\xe22U\x1a\xff<\xe6z\xefzE\xf9\x8a3\x13w\xde\xd1Mk\x1c\xb8\x1a\xbcF\x12\xe4\v\x99\x93\x8c\xef\xd9G\x16\xdc&ǯF\xfc\xd3S?\xbf[\xfb\x80\xbb}\xd8\xf7~\xfe\xbda\xb7k\x17\x18\xee\xfcM\xd7\xef\xee\x1c\xa1\xad\xf4?2\xe2'\xff\xf1\xadK\xfe\xc8\xde\xc7\xdf}\xea\xc7W\xab\x87˿\xe9\xeaܲE\x8dٲ\xa5\xc3\x11\xfbȰK\x1e\xf9\xf9\u007f\xdc9\xecW\x8e\x16\xf4\x8b\x06\xdau\x16\xbb\x98~\xd7\xe3O\xb6l\xd1\xd6\a\xac&\xd4$\xff\xbfg\xd5\x1a\x9e\xed\xea\xfc\x8dv]\xe2u\xad\nko\xd7\xff\\2\xe6\x91\x1f\\:lĿ\xff\x8f\xa3\r+uG1\x8e\xeb/\xfb\xf1\x8f\xbfɊ9\xfaf\xb7\xb6\xe5\x9f/\xfbc\xd7\xeb\x97\u07bdE\x15\x8d\x11î~\xf6\xa9o\\\xfa\xbaw\xbd\x82|=2\x13w\x9e+ƍ\x03W\x83x$A\xfe\x901\xc9\xf8\xd3%\xb7\v6\x1d\xbc\xfe\xdd1\x97|\xf3?\xb4\xcd\u007f3nB\xf8g\xf54{\xc4\xff\xb0\xdb\bا\\\xe7ݗ\x8e\xb8\x9e\xbd\xe9;\u007f\xf2\x8d\x11\x97}\xf7\xa9o\x8c\xb8^=\xef\xd6y\xca\x11\xfb\xec\xf5\x8f\x8c\x19q\xd9\xf5\xce\xf7y\xe7\xa5Z\xa4\xb6\xf2j\x17Ӿ[a\x9d\xce[M\xa8\x1f\xc0\xd7_v\xe9\xf5?\xb7B\x8d\x15Is\xaf\x9a\xee\xb7/\x1d\xf3\xbd\u007f\x1f1\xcc\xf5\xf9k\xa6\xee,f\xf3\xfa\xf5#.\xf9\xd6\x0f\xd4$\x9d}3\xeb\xfd\xe50v\xef\xc4\xdd꿿b˟w^:\xe6\xf6?ũW\x90\xaf83\x8f\xces\xc5\xf8q\xb0k\x10\x8e$\xc8#2&\x19?\x18\xf6\xbf\x82M\x10\x17\xfb\xd4\t\x80\f\x911\xc9\xc0\xb7ޓ\x00\x92\x012N\xc6$\x03$\x01$\x03d\x1cHFx\xd0\xd7G\x01\xc8(\x90\x8c\xf0\xf0\xcf\xe6r%\x00\x99\x03\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90 Pɘ\xa4\f\x9c\xb2]\xd4\n\x00 G\bT2v\xaf~t\xe8\xc0\x0eQ3\x00\x80\xdc P\xc9PY\xad\xbc$\xd8\v\x00\xc8\x11\x82\x96\x8cM\xcaZ\xc1^\x00@\x8e\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x10\xb4dlWV\v\xf6\x02\x00r\x84\xa0%\xa3s\xe0ȵ\xbb\xe1\x8b\x03@\xae\x12\xb4dt\xadT\x14\xe5\n\xd1\x13\x00\x80\x1c h\xc9\xe8\x188\xe4\xfeկ\t\x9e\x00\x00\xe4\x02AK\xc6&e\xa5`/\x00 G\b^2p\xc5\x04\x80\x1c\x06\x92\x01\x00\x90 h\xc9X\v\xc9\x00 \x97\tT2:wo\x9a\x14\xd9-j\x06\x00\x90\x1b\x04*\x19\xe3\x15e\xf0rQ+\x00\x80\x1c!P\xc9\xd8\xfb\x12\x0e1\x00\xc8m\x02\x95\f\x00@\xae\x03\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x90\x92d\x9c\xf0\xab\x1d\x00\x90c\xa4$\x19\x9f\xfb\xd5\x0e\x00\xc81R\x92\f\x9c\x99\x00\x90o\xa4&\x19_\xfaU\x0f\x00\xc8-R\x93\fh\x06\x00yF\x8a\x92A\xe9\xe7X\x03\x05 \x8fHY2\x00\x00\xf9\x04$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 Aʒ\xb1\xf6\xca\xc1\x91\x01\x17߶\xd7/.\xe3t\x9e\xf5\x8b\xf0\xa0S1\xb8`Ȕ\xddlG\x87\xf182\xf8\xcaMVм\xe1\x05\x91\x8bƯu\x95\r\xcd\xe8\x00\x90 )J\xc6\xd9\xf1\xc6\xf49\xff~\xbf\xd0\f\xf3`\xc1\xe7~!\x1e\xa8\x92Q0@\xe5B\xd6\xcf\xd5Ԗ\f\xc6<=\xe6ш\xf1x,\xdfJxF\a\x80DIQ2\xe6(\x05\x0f\xbe\xfby\xe7K\xea\xdcX\xe9\x17\x9bQ\xce*J\n\x92ѡm|\xbd}\xa8\u0084G\x95\x8c\xbd\x9f\xabt\xbd:VQ^e\xcf\xccR\x94\xf1/u}\xb9\xf7\xae\x882\xeak\xbbdhF\a\x80\x84IM2>\x8f(ơ\xf8\x14eH\xfc\xd0\f\x13\x84d\xa8b\x11Q\x9e\xd0$\xa3S\u007f|v\x882E\xfd\xb3ZQ\x16\xeb;^R\x94G\xad\x82\xe1\x19\x1d\x00\x12&5\xc9xM\x89\x18\x1f\xaa{\xadi\x94\x9d\x04#\x19t\xa4r\x1b/\x19\xf4\x1ee\xb0Z\xf7 e\xba\x190\x9d\x13\x87\xf0\x8c\x0e\x00\t\x93\x9ad\xec\xb5g\xd3\xea\xed_\xb2?\x9d\xb3\x86D\x06\x8e\u007f\x89m>\xaa<\xfcҐ\x82\x91s\x94\xf1z\xc4u\xca]\xc2\x00\xb3\x06\xfb!\x17\xb3X\xb9\xe7\xdd\xf1\x03.\x1c\xb9\xdc3\x82vL\x1f\x1c\x190\xeaQ}u\xd3Q\xf4\xfe\x13\xb3\x06G\x86\xdcv\x82\x9d\"0v\xbb\x82\r\xd6N\xba(R0\xf4\xb6.W\x19\x13^2\x86+s\x1c\x92\xf1\x84r\xa1Z^Q\xfeb\x06t\xdc\xff\xaaU0\xd0\xd1\x01 ;HM2\xe8\x10e\xe8Z\xee䝾T\xa0D\x86\x0f\xd1W\x05\x1fU\xe6\\\xa0(\x05\xef*\x11\xed\xf3\xfd\xec\x85\xca^a\x809}\xad\x87|\xccbeRAd\xec\xa8\xf3\x94\xeb\xbc\"\xf6^\xa8\f\x18>TQƺ\xdb_\xac̺H\xb9p\xa0\xa2\f=K\x97OR\x94\xf1Wv:\x83\r\xa6+\xcaE\xc3\a\xa9\xff\x9cp\x961\xe1$c\xb7\xa2,wH\xc6]\xcaPJoc\xff\x88\brt\x00\xc8\x0eR\x94\x8c\xed\x11E\x190\xfe\xd1\xdd\xc6\xc3\xce\v\x959\xea\xc7\xe9\xf6\x01l\xb9\xefQ\xe5\xbc!\xab7=\xa9\x1e\xcck\x87\b\xab\x95\xe1\x1e\x01\x06\xe6CG\xccbE\x19\xf2g\xf5\x18\u007f\x00\xabD\x181^\xb9M\x9d\x96\xbb\a\xb0u\x03wѡ\xdb\xd5c\x80\x88\xf2\xa4ub\xc2\a\x1blR\nا\xfa\xf6\x02\xe5AW\x19\xb3S\x86d\x9c\xed\\>H\x19r\x96\x97\x8c\x13\x83\x94Y\x94^\xa1-h\b\brt\x00\xc8\x0eR\x94\f\xda1V;\xe4\x1f4\x87\x1d֫\xc7\xffWh{W\xb2\xcf\xddG\x15E\xbb\x1f\xe1\t\xfd3\xfdJ\xe5a\x8f\x00\x03\xf3\xa1#f\xb1\xb1s%[#\x10F\fV\xb4)\xf9\xf0\x95kc\x8bjS}:[i0$\x83\x0f6\x98\xa3\x9d\x11\xb0\xbf\xd3]e\f\xac\xfb2T\x86\xb0gU\xc9\xd8}B\xa5c\xe5\xc5J\xe4]\xb6\xc01\x87\x8a\tpt\x00\xc8\x0eR\x95\fuF=q\xa5z \xaf\\\xc8\xeej\x1a\xacݷ\xa0N\xd0\xf3ԙ\xf7\xa8\xb1\x12x\"r\xde\tv\xf9\xe0\xbc.\x8f\x00\x03\xf3\xa1#f\xb12J\u007f\x10Q\xde\x15G\x8cUFn7\x8f\xfe]E/\xd6\x1e<\xacL\xb2$\x83\x0f69\xab\x1f\xfb\xdfÎ\x15\x1ce\f,\xc98\u007f\xd2r-\x94\xbb/\xe3\xbc\xe5Z\xa5^\x92\x11\xe0\xe8\x00\x90\x1d\xa4.\x19\x8c\xbd\xf3\x06(\x05\x9d\xf4sE\xb9x\xa4FD٤\xbe\xe7\x8d\x15\x83I\xec\x12\xe4r\xf6\xc8#@\xc7x\xe8\x8cY\xcc.Q0.V\xcf%\x84\x11\xaf\xb2\xa3\xff+\x97\x9f\x10\x14\xd5?\xb3\x9f`+\x8c\x86dp\xc16g\xb7?9o\xd2`E\x97\f\xae\x8c\x81*\x19\xef~\xfd\xf5\x97\x9b\x86*c\xf5r\xa6d\\x\xf1,\xed8`\x8ar%\x8dG \xa3\x03@v\x90\xa2d|m~dw^\xa4̣]\xf6ǯz6\xfe\xa89\x93ֲ#\x85\xb1\xec\xfc\xdc#@\xc7x\xe8\x8cYl\xde_9\xd2.\xe0\x8c\xa0{\xa7\x14\xa8\x1b\xe7O\xff2\xa6\xa8~\xa4\xc0K\x06\x17l\xf1\xf0 \x16?|\x94.\x19\\\x19\x03s-\xe3\xc4`e\xb8V\xac\xc3u\xc9\xf4\x1e~\xf9\xf3%\xeeZn\x90\xa3\x03@v\x90\x9ad\x8c4\x8e\xa4U橓\xecs\xeer$\xb5\xdf\xf3g\a(\x9d'\xce+\xf8\x92z\x058\x1e:c\xac\xa3\x8c\xa1\xda\a\xaf \x82\xb2Äy\x17+\xcau1E\x05\x92a\a\x9bܣ(ӗ\xbf\xf6\xa5yb\xe2-\x19t\xbb\xa2\xafp\xb8%c7\xf7\xb8C9Ϻ\xca\x1a\xe8\xe8\x00\x90\x1d\xa4&\x19\xe3\xedk\x05\xf3\xd8\xe6@\xf3\xc6\xe8\xed\x1d_s\xef\xf9Y\xca\xe2'\xf4H\x8f\x00\r\xf3\xa1#f\xb1qx\xfeeD\x9d\x96\u0088?o7J\x9f\xff\xb5\xbbh\xacd\xf0\xc1:_\x17\xb0\x1b:)[{\xf4\x93\fvw\a\xbb\xb8\xe2\x96\f:\x98]71C\x06Z\x97E\x03\x1d\x1d\x00\xb2\x83\xd4$c\xb5\xf5\xe5\x89\xceA\xecb\xe1te\xb86\x15\xd7*\x91\x13\xdc{\xfeUe\xecXm\xb2y\x05h\x98\x0f\x1d1\x8b\x95\x886=\x17\xb3\x8b\x90\xa2\b\xf5h^\xbb\x1c\xf1\xaer\xdeYwQ\xa7d\x9c\xd0\x0e\xfd\xed`\x9d.\xe3\xc2\xc4\xe7\x17\xb1\xca\xe3K\xc6\xe7\ue2ec\x06O*\xfa\x95R\xed\xae\xae\a\xad݁\x8e\x0e\x00\xd9Aj\x92\xa1\x9e\x83+\xe3Wwt\xed~p\x90r\xb1:\x99ލ(\xd3\xd5\x0f\xf3W\a\xb2k\b\xdc{~H$2H\x9b\f^\x01\f\xf3\xa1#f\xb1\xa2\fW\xe7\xe7\xda\x02\xf5\xbcD\x1c1V\x19\xab\xca\xc0\xe7\x93\xd8ራ(?\xfd#\xca\xca/\xbfv\x04\xeb|=@\xbb\xdeѩ\xf6\xe4\n?ɠ+\x15\xe5\x1e\x81d\xa8\xc7\x13ʔ\xed\x9f\u007f\xbd\xf76\xc5\xf1\xb5\xb4`Fg\xf9\xc3\xdb)\x00\xd9B\x8a\x92\xf1\xb9\xf9\xf5nmb\xab\x1f\xac\x11傑C\x14\xe5\xf2\xb3\x8eIq\x8fb.Ix\x040\xac\x87|\xccbe\xc8\x05\xe7\xb3\x1b\"\xef\xf1\x8a\xf8\xcb@%r\xf1\xf0\x02ePGLQ~\xfa\x8fTs\xdc\xe4\f\xd6yXQ\x06_1\xf2\xbc\x01w\xb1\xeb\xab>\x92\xa1\x8a@\xa4C \x19g\xa7\x98\xc3p\x05\xffM\x96`Fgx\x9ck\xb8\x00\xf47)J\x06\xa5/\xcd\x1a: r\xd1\x15ˍ\x0f\u05ceYC\"\x05#\x1ff\x87\xfdܤ\xe8P\x14\xf3\x16Hq\x00u<\xe4b\xd49\xbc\xfb\x8a\x82\x81Wl\xf7\x8c\xa0\x9ds\x86D.\x18z\xd7\tAQm\x97>\xfd\xdf\x1du\xc1\x80\x95\xae`\x9dM\x97\x0f\x8c\xa8{>g\xab%~\x92\xd1\x11Q\x8fOb%\x83\xd2\xedӇ^\x10\xb9h\x92\xfb'v\x82\x18\x1dH\x06\xc8&R\x96\x8c4c\xcea\x00@V\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x90\xed\x92\x01\x00\xc8* \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t\x82\x97\x8c\x1a\xf2S\xbf\x10\xc6*\xf2}\xbf\x10\x1f\x8e\xf7\xfaE\x00\x00\x82&\xb4\x92\xd1\xf7\\\xc9i\xbf\x18\x00@ЄV2z\b\x81d\x00\xd0\xef@2\x00\x00\x12@2\x00\x00\x12\xa4$\x19\xbb_\xb3\xd8m\xed\xd4%c\x1dY\xf5\xd7\xc6\xf2\xe2\x99\xdbhߺ\x19ъ\xa6\xd3ھ\x15\x87\xea'\x96\xde\xfa\xeb>jI\xc6\xf1\xa6\xaahY\xdd.\xeaQ\xc4\x15\xd0|\xaa\xa9\"Z\xb5\xe4\x14\xa5\x8b\b\xe3 \xa5G\x1a*\xa3\x13k\xd6`)\x14\x80~!%ɸM\xb1\x98n\xed4%\xa3q2)\x8f\x12\xb2\xad\x81\x14\x97\x13R\xa3\xed\xab/\x8d\xd6\xd6\x14\x92\x86>S2v\x8d#\xc53\xab\bY\xe6Q\xc4\x15\xd0TAJ\xcb\b\xa9\ue85b\xe7\x13R?\xff8\xfd\xb0\x94\x94\xddTM\xc8\x1d}\x82\xfc\x00\x00A\x93\x92dtEL\xc58\xaf\xc3\xdaiJ\x06\xa9\xfe\x90\xf6\xce'\xc5\xc5/\xf4\xd1W\bٯ\xed\x9b\xf61\xa5\xfb\xcb\xc8FC2\x8e\x97\x92Eݔ\xee)#\xdb\xc4Eb\x02ޤ\xb45J6X'&\xf5d\x89z\x80q`\x02i\xf5J\x12\x00\x10 )I\x86}\x98q\x9d\xbdϒ\x8cC\xea\x9f\x0f\tif;oa\xb3|\x9dv&A\xe9ˤʐ\x8cE\xa4\x8e\xea{\xaa\xc5E\xdc\x01\x1f\xb1\a\x8d\xa4ђ\x8ck\xf5*\xd7ܻ\x93\x02\x00\xd2Oj\x92a\x1efp\a\x19\x96dLc\x0f\xba\t\xf9\x80\xfd\x9dOZ\xd8>\xed\\\x83\xf6\x16\xabڠIF%yE\xdb\xd3SH\x8e\n\x8b\xb8\x02n\xd4\x1e\xb4\x90zK2\xee 5o\x9e\xa3\x00\x80~\"5ɠsb\x0e2,ɨe\x0f\xce\x11r\x92\xfd\xbdO\x97\x8cEz\xc8\f\xb2S\x93\fU\x1dfܪ\x11%m\xa2\"\xee\x00\xfd\x90c\x03'\x19oF\t\x990\u007f\xf3\xdf)\x00\xa0?HQ2\xf4\xc3\f\xfe Ò\x8cz\xf6@\x9d\xff\x9f\xb1\xbf\x86d<c\x86\xbc\xacIƧ\xc4f\x9b\xa8\x880@\x95\x8c:\xfb\"\xeb\x87\vJ\xd4'\x8b\x1a\xbb)\x00 \xfd\xa4(\x19\xfaa\x06\u007f\x90\x11W2\x1e\xd3C\xaa\xd5C\x06&\x19\xa7\t9b\x17\x14\x14\x11\x068%C=\xcfi\u007fz&!\r\x14\x00\x90~R\x95\fv\x98\xe18Ȉ+\x19ڙ\a펒\xe3\xfaZ\xc6U\xecB\bc\xcf\xc7\xe7\x84ED\x01\xbcd\xf4}\xfc\x86\xb6k\r)\u008a\x06\x00\xfd@\xaa\x92\xc1\x0e3\xa68vē\x8c\xe8q\xaa=w\x93qŤ\x91ܤ\xddO\xb1\x93\x14\x9f\x12\x16\x11\x05\xe8\x92\xd1K\xc8?(=IFk\xc1\x87H!n\xe6\x02\xa0\x1fHY2:#\x8a\xe3 #\xaed\x90\x9bT\xcd\xd8Y\xa2\x9e\x97\xe8\x92q\xa8\x98<t\x86ҷ\xcbH\x93\xb8\x88(@\x97\f\x1a%ۺ\xcf\xd1;\xc8\x1dj\xf4\xe9\xf9\xc6\x01\f\x00 \xbd\xa4,\x19t\x8e\xf3 #\xaedL-.\xbai*!+\xa8y\xf7gk\x94\x14ϞF\xc8\xdc\x1eq\x11Q\x80!\x19\xb3\tQ\xa5\xe7X\x19\x89\xde8\xb3\x84\x94\x1f\xa5\x00\x80\xf4\x93\xbadt:\x0f2\xe2JF\xfd\xc1\xbaҲ\xba=l\x8f\xf1\x1d\x93#?\xaa\x8a\x96\xccn\xe9\xf5(\"\n0$\xe3PM\xf1ė\xd9wP\xa6E\x8b\xab\x97\xe2*+\x00\xfdB꒑8\xe6\x94\a\x00\x84\x16H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x82\xfe\x94\f\x00@\xe8\x81d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80dP\xfa\x842\xde/D\xe5Ae\x8a_\x88\x0f\x9dg\xfd\"L\xd0Y\xe9\x00\x00 \x00IDAT\x00\xc8z \x19\xfd&\x19\x0f\x16|\xee\x17\x02@\xd6\x03ɠt\xf7\x83\xab\xfdBh\xea\x92qVQ \x19 \xfc@2\x12\x05\x92\x01\x00\x85d$N\xe6%\xa3\xa9\xc9/\x02\x80\xb4\x13f\xc9\xd8;~Ѐ\xb1ۇo\xf7\x8b\xf3C[\xcbX\xac<\xd89}\xd0\x05\xc3W\xaa\x9b\x17G\x06\xcdb\xd3{\xb1rϻ\xe3\a\\8r9\x8b2$\xa3s\u0590\xc8\xc0\xf1/Q*.\xe2\n\xb8\xffĬ\xc1\x91!\xb7\x9d\xa0t\x8e\xc2\xd8Mi\xc7\xf4\xc1\x91\x01\xa3\x1e\x95_\n=B\x96х\xa4p\x9b_\x9c\x80\x17\b!ʹY\xfdws\x9c\xa8\xe3Q2C\xfdӨ\x86\x8d;\x1a'\x0e\xe45!\x96\x8cݑI\xabW^\xa9(+\xfd\x02\xfd0$c\xfa@ePD\xad\xee:\xe5\x82A\x8a2\x8a\xb2}\x93\n\"cG\x9d\xa7\\GM\xc9x\xa9@\x89\f\x1f\xa2(\U000e8e08+`\xd6Eʅ\x03\x15e\xe8Y\xba|\x92\xa2\x8c\xbf\xb2\x93\xee\xbdP\x190|\xa8\xa2\x8c\x8d\x93\x90\xc1\x9e\x03\x8e\x87\rŧ\xe8\xc9\xf6h\xb30\xc0\x15\xeb\xe2̋\xe4\xb9S\xf4T\vy\xf1L\x9c\xa8\xbew\x1a\xa3ꟿ\xb5\xb7\xaf'olj\x03yM\b%\xe3\xc4\xd8\x13\xda\xdf+\xb4Y7=0\xc9P\x86\xee\xa5g\xafT\"\x17,\xff\x9a\xaeV\x94״}C\xfeL\xe9k\x03\x94\xe5\x86dt^\xa8\xcc\xf9\x92\xd2\xed\x03X\xab\xa2\"1\x01\xea1\xd0ڈ\xf2\xa4ub2^\xb9\xedkU\xee\x06(k\xfdҢ5\x0f\xf0\x8f\x8e\x8e~\x8c\xfd\xe1%\x83\vp\xc6\xc6p\x88\xb4\xa9\xff\xee!\x87\xe2F\xd1\xe6\xa8\xfew\x1f$\x03x\x11B\xc9ث\xec\xd5\xfe\x0e\x99\xa7?J\xe4rG\\L\xc9`\xd5\xeeU\x94{ؾ\x91l\x96\x1b\xfb\xe8Je\x88!\x19s\x94+\xa8\xbeg\xa8\xb8\x88;\xa0\x83=\x98\xaeL\xb7$c0;9\xa1\xf4\xe1+\xfd%\xe3\xd6\xfb\xf8G\x0fE?c\u007fx\xc9\xe0\x02\x9c\xb11@2@P\x84M2\x16\x0f]ۡt\xac\x1d\xfa\x04\xa5S\x06k\xf3y\xed\x97\xec\xdf\xe5\xa3\n.\xbeK\xdd\xda}\xbezN\xd0qݐ\x82\xf1_\xafT\x14\xe5~z\xbf\xa2\x9f\xba\b\x02\xcc:\r\xc9\x18¶\xbfT\xf4)}\xa5\xf20ۧ\x9dkг\x11\xe5]]2\x06\x1b\x02u\xf6<U\fDE\\\x01\x17k\x0f\x1eV&Y\x921V\x19\xb9\xddjYc!\x89n|\xec\xc6qu\u007fc\x0f\xfa~]Sz\xe3\xe3=\x94\xee :\xb7\x18QNj\x16i\u007f\xa3K\x8dX.\x80\xdb\\H\x8a\xd65UN\xaew\xadEp\x92q\xe6\xbe\xcahU\xfdAw\xc3'\x1b*\xcb\x16h'&\x94\x93\f+\x9d\x83E\x84<s\xb4aZI\xdd9\n\xf2\x9a\xb0IF\xd7u\xcap\xf5\xbf)]\xea9\xc0\x90\xf3\xc6\xdf\xff\xaa>\xfdf\x9d7g\xed\xe2A#\xbf\xa6gW\xae\x1c2t\xc0\x90ۮS:\xbf\xdc>\xe0\x9e\x13\xf4\xc4=\x03\xb6\u007f)\x0e0\xeb4$C;\xcf\xf9ZQ\xba\xd8\xdf)\xbadܦG\\\xac\x9eF0\xc9\xf8\\Q.\x1e\xa9\x11Q6\x89\x8a\xb8\x03\xae\xb0\x1b0$\xe3Ո\xa2\f\xb8r\xf9\t\xabG\xf4\xa3\xadE\xa4\xa2\xf9g\x13\xefe\x0f~X\xb8h纊[\xfbh\xf7\x9b\xed\xd5w\xb4\xb7\xb7\x1f1\xa2\x9a\xa2\xda̦Q2ck\xeb5j,\x17\xc0m\xb2ʦ\xaej\x9e:\xeeC\xcas\x88\xec\xec\xe9\xe9ic\x92\xb1\x834\xed\xd9V_\xb8\xcf\xd9\xf0щ7\xbe\xd0ZG\xa2z\xb8%\x19V:=۶N\xad\x9eP\xf5X\xc3\xe8\xbfR\x90ׄM2(\xdd\x14Q\"\x9b\xb4\xad\xcf\xef\x1f\x15Q\x06\xb2C\x88\xb5l\xb1\x81\xbe\xa6/k\x8cT\xaeP\xe7&\x9b\x9e\xb3\u0602\xe5u\xb3\xbc\x03t\fɘĶ]\x921O\x8f\x18\xa9\x16d\x92ѥج\x14\x15\x11\x068$\x83\xee\x9dR\xa0>y\xfe\xf4/\xad\xf6i\xb4L\x95\x83\x86\n\xca\xe6\xf3\x8b\x94\xcdحl7\u007f\xb2q<\xbaЈ\xad\xf8\x87:\x93+\xa8+\xc0ތN;C\xe9\xe9\xaa\x1a\xcas\xc88\x0eQ%\xa3g[\xb7z\xf4p\xd3|-\xd6jxn\xb5z(\xd17;\xaa\x87\x9b\x92\xe1L\x87Ԟ\xa1}\xf1\xd6OA>\x106\xc9\xf8\xfc\xb6\xc8`ep\xe4.\xe3S\xfa\xecK\xe3\xd9:┡_3\x06Og\xfbFF\xcc\xe3\x87\xed\x05_ҳ\x05\xec\"\xacG\x80N\x1c\xc90\x8e2\x86\xaa\x87\f\xc6QF\x87]NPD\x18\xe0\x94\fuk\xfb\xbc\x8b\x15\xed*\x8cA\xf4!j\xac#<pC\xef9\x95k\x1b\xd9n^2\x16F\x8f\x1b\xb1M\xd4Zs\x10K\xc62\xf6\xefz\xf2\x15\xe58D~\xb6o\u07fe5\xdaZ\xc6\x17\xeb\xebn\x98Hfk\xb1fç\xc9F\xf6\xf8\x99\xa8\x1enJ\x863\x9d(\x0e0@\xf8$\xe3\xe1AO\xbe\xabt,\x1e\xf4\xa0z̠MTz\xf9$v\x14\xa0s%\xdb1r\xa4\x19\xfc\xf5\xa0\xd5t\xed v\xea\xe2\x11\xa0\x13G2\xf4K\xa1_FԳ\x18m-c\xa0y}f{\xc7\xd7\xc2\"\xa2\x00\x87d\xfcY\xbf\x8d\xe4Q\xe5|{EC[\xd2\xd4d`\xb6q4\xa0\x1d\x03p\x8ap2\xfa\xa3\x98X/\xc9\xd0\xd6Gۉ\xe3\xaa+\xb7\x96\xb1\xaf\xa2jik{\xedl+\x96Uv\x80\xb4S\x1a\xbb\xfc\xe9L\xc7y\xe0\x02\xf2\x94\xb0I\x06\xfdZ\xbbb¦\xdbEs\xb4\x1d\xf3\x86\xaa'\x1fCwkh\xc7\x1e#\xed\xbb4\xe7\\I\xafԢ\xbc\x024\xe2H\x86~<\xb2X\x19n\\1\x99\xae\f\xd7f\xfaZ%rBXD\x14`I\x86\xdaz\x97\x11\xfc\xaer\x9e}3\x97-\x03\r7\x1c\xd0\xf8\x82\xed\xd6d`\xb3\xf6Ѿ\xa4\xf0XL\xac#\xc0ތ.a\x8f7\x12\xc7\x19\x04'\x193j\xd4S\x10\xba\xc0)\x19\xff \xeb\xd9\xe3\x87\xf4z-\xc9p\xa6\xb3\x80\x02\x10>\xc9Pg\xdd@\xfd\xf0b\xd0`\xed@\x9f\t\xc0&\xfd\xb3}ރ\xe6\x0e\x83W#]\x91WنW\x80F\x1c\xc9P\x86\xab\x9a\xb1\xb6@=/\xd1%\xe3݈2]m\xf5Ձ\xca\x1cq\x11Q\x80\xf1Uو\xb2\xf2˯\xe9Xe\xac\x1a\xfd\xf9$\xfe^.[\x06ڈvs\xe7O\x9fc\xff\xd6\xd6RzJ\xdb\xf1Y\xf1C\xb1\xb1|\x00\xb7\x19\xbd\xa6\x9b\xd2\xee\x1bj\xb5\x88\xe3\xcf\xe9R\xc3IF\x15\x9b\xf9}7;%\x83\xd6T\xa9'2\x1f\x17\xeb\xf5Z\x92\xe1H\xc7\xe7:.\xc8\x13B(\x19&\x83\x94\x8b\xeeٴ\xfa\x8a\x02\xb6x0O\x99\xb2z-\xbb\xab\xeb\xebW\xb7\x0f\x1d\xbb}\xbb\xb9X1\xf8\x8a\xc1\xfa\x86W\x00#\x8ed\f\xb9\xe0|v+'\xbb\xefB\xbf\xfbsuD\xb9`\xa4\xba\xe7\xf2\xb3\xe2\"\xa2\x00C2\xd8\xc9\xd1&\xfa\x97\x81J\xe4\xe2\xe1\x05\xca k\xcd\xe3\xb3\xf6h\xe3;}\xef7F\xdb?\xa3t\xd9\xe8\xef\xbf\xd2\xdaH^fO4G״֖~\xaan=>\xfa\xa8 \x96\v\xe06\xa3\xe4\x96m\x9b\xab\xcb>\xd6\xe2\xe7\x93z\xf6\x87\xbf\xfb\xb3\x99ܷ~խ\xa4\xbc\xe5\x1d\xbe\xb2\x0f\xc7U5?3\xb9\xb0\xe8\xc5C\xf4Sv\xf7\xe7\xba\xf6vv\xc8b\xa5s\xee-\xed\xa2\xccq\n\xf2\x9d\x10Kƨ\xe5\xf3..\x184I\x9fz\x9b\xc6\x0e\x1cx\xb9z,\xb0\xfb<m\xcdb\xbc\x11\xb38\xf2\xa8\xb1\xe5\x11\xc0\x88#\x19\x93v_Q0\xf0\nm\xf9\xc1\xf8\x8eIǬ!\x91\x82\x91\x0f\xb3\xb3\n\xa1d\b\x02\f\xc9xw\xd4\x05\x03\xd4c\x9d\xce9C\"\x17\f\xbd˾ʺ\x90\x10\x12=\\\xaa\xfe\xcb.\x8a\xb4\xd5^U6\xb7M{\xa2w\xd1\xe4\x92;\xf6\xa9\x1b\u007f/i\x10\xc6Z\x01\xfcf\xf4\xf1Ɖ\x95\r\x9f\xe9\xf1/Tl\xd0\xfe\x10\xf3;&\x1biߚ\xeah\xc5\x03/TGk\x1d\x95\x1d\xad\x9f<m\xe9\x8bE\xea\xe6C\xc6\x02\x86v?\xa9\x99\xce\xc1Bm_=\x05\xf9N\x88%#\xfd\x98S>\xd3<M\x8eЄ\xe1o\x0f\x05 p \x19q\xc8\x16\xc9\xf8\x91̷\xde!\x19 \xad@2\xe2\x90-\x92!\x05$\x03\xa4\x15HF\x1cB(\x19'\xb5%M\xbf(\x00\x92\x06\x92\x11\x87\x10J\x86\xb6\xa4\x89\xeb\x1a }@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12\x04.\x19\xfb\b![\xcd\a\xa7\xa3\x84\x1c\x8a\t9ޫ\xfe\xb3\x8e\xd4\xc7<ᤙ4\xfaDhh\xb5\x01\x00\xfa\x87\xb4H\xc6|\xf3\xc1\xafI\xacd\xf4=Wr\x9a\x06&\x19Fm\x00\x80\xfe!\r\x921ztI\x8f\xf1\xa0^ \x19=\x84\x04(\x19Fm\x00\x80\xfe!\r\x92\x11\xad!\xad\xfa\xf6\x99\xe8LH\x06\x009E:$c\riз\xb7\x92fH\x06\x009EJ\x92\xb1\xfb5\x8b\xdd\xe6>U2\x8e\x93\x89\xfa\x92d=9bH\xc6\xf1\xa6\xaahY\xdd.uk\x11a\x1cd\x92\xf1YSE\xb4\xeaq}\xc6\u007f\xd8X\xa9\x06\xb4\xe9u쩛\\Z\xbb\xcf!\x19G\x1a*\xa3\x13k\xd6\xe8\xf5\xc6\xd6\x06\x00\xe8\x1fR\x92\x8c\xdb\x14\x8b\xe9\xe6>U2\xe8̈́Mg\xda]|\xd39]2v\x8d#\xc53\xab\bYF\xe9\xe6\xf9\x84\xd4\xcf?\xaeJ\xc6\xcc\nR^F\xc8\f\xb6\xf0\xf1b\x94\x94\xdeTN\xc8BV\xae\x85\x90\x8a\x99Ѣ\x1aN2>,%e7U\x13rG\x9f\xb86\x00@\xff\x90\x92dtEL\xc58\xaf\xc3\xdc\xc7$\xe39\xd2\xc46\xb7\x91U\xbad\x1c/%\x8b\xbaՃ\x872\xb2\x8d;1!SߡtG\x94l\xa6\xf4@!y\xba\x87\xf6m-&k\xd4\ad\xf4\xfa>z\xaa\x96p\x92QO\x96\xa8\a\x18\a&\xb0U\x12Qm\x00\x80\xfe!%ɰ\x0f3\xae\xb3v1\xc98J*\xd8\xd1\xc0|rT\x97\x8cE\xa4N{\xeeeR\xcdK\xc6a\xb6\xaf\x91\tC=y@\vXO&\xf7\xd2{\xc9\"\xb6}\xfa*N2\xae\xd5O>\xd6ܻS\\\x1b\x00\xa0\u007fHM2\xcc\xc3\f\xfb C\x93\f:\x93\xa8\a\x10\xdd%3\xa9.\x19\x95\xe4\x15\xed\xb9\x9eBrԖ\x8c\x19ھ5\xa4\x9e\xf6\x96\xb0x\x95\xdeR\xf2f\xdf\x04\xb2_{\xb0\x88\x93\x8c;H͛\xe7\x8cmQm\x00\x80\xfe!5ɠs\xdc\a\x19\xbad4\x93\xc7)m%ͺdt\x132\xe3V\x8d(i\xb3%\xa3V\x8bߨ\xfe\xfd\x98\x10\xe3N\x8e\x1a\xb2\xf1\x14!\xdd\xc63\xb6d\xbc\x19%d\xc2\xfc\xcd\u007fW7\x85\xb5\x01\x00\xfa\x87\x14%C?\xcc\xe0\x0e2t\xc98L\xa6R\xba\x80\x1c\xd1%\xe3Sb\xb3\xcd}\x91\x95I\xc6ARd\x94\xae%k\x8e\x10\xa2o\xb7\xf2WL>\\P\xa2\x96.j\xec\x16\xd7\x06\x00\xe8\x1fR\x94\f\xfd0\x83;\xc8\xd0%\x83V\x93\x83=\xeay\x89.\x19\xa7\x89*\x1e\x16\x02\xc9\xf8\x84?\xca\xf8\xbby\x94\xf1\xb2\xf3\xbe\x8c\xde\xf6\xa7g\x12\xd2 \xae\r\x00\xd0?\xa4*\x19\xec0\x83?\xc80$\xe3i\xb2b\x87z^b\xace\\Ům0\xf6||N$\x19\xbd\xc5\xf6ZF{_\x19yK{\xb0̖\x8c\xbe\x8f\xdf\xd0\xfe\xae!E焵\x01\x00\xfa\x87T%\x83\x1dfL\xe1\x1f\xeb\x92q\x80\xccld\a\x03\xbad4\x92\x9b\xd8\x15\x14\xba\x93\x14\x9f\xa2\xbd\x84\xfc\x83:%\x83\xd6\x1b\xf7\x8bn$\x13zh\x83\xfe\xa0\xa7ʖ\x8c\x93d\xf4g\xec\xef!R\xd8+\xac\r\x00\xd0?\xa4,\x19\x9d\x11\x85?\xc80$\x83V\x91q슈.\x19\x87\x8a\xc9Cg(}\xbbL\xbb_#J\xb6u\x9fsJ\xc6\xfe\"\xb2\xa2\x97\xd2\xd6\x12\xd2B\xe9\x91(Y\xd5G\xcf\xcc'\x8e+&w\xa8\x9aqz>\v\x16\xd5\x06\x00\xe8\x1fR\x96\f:\xc7q\x90aJ\xc6ㄝ\x97\x18\x92A[\xa3\xa4x\xf64B\xe6\xb2%\x8bل\x906\xa7d\xd0\xcdEd\xe2\xcd\x15\x844\xb1\xe3\x87mQR~s\t\xa9\xe7$\xe3X\x19\x89\xde8\xb3\x84\x94\x1f\x15\xd7\x06\x00\xe8\x1fR\x97\x8cN\xc7A\x86)\x19\xef\xe8ZaH\x06=\xf2\xa3\xaah\xc9\xec\x16\xed+\"\x87j\x8a'\xbe\xec\x92\fz\xb0\xa1\"zM}\x9b^\xc7\xfb\xf3\xcbKnm\xdb\xc6/\u007f\x1eo\x9a\x16-\xae^\xfaw*\xae\r\x00\xd0?\xa4.\x19\x00\x80<\x02\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92A[kN\xf9\x85H\xf2\xd5\xdcV\xbf\x90\x14\b>\xdf~ \xbdC\x02\xfa\x91\\\x93\x8c\x85\xa4p\x9b\xc7Sǣd\x86`w\vi\xees\xee9X_>\xf1\x8e=7\xbd)\bN\x8c\xbe\x96\xc2\xe7\x84O\xac)\xfe\x99p\xbf\fz\xbe\x8d\x84\x90qG\xcd}\xbb*v\xc4+\x928\a\v\xd5z\x1b\xad\x87\x81\xd5\xeb=$ l\xe4\x8ad\xec9\xa0\xff=\xd9\x1em\xf6\b\xe9{\xa71\x1a\xbbw]\xe1\xaf]{\x0eD\xeb[_\xbe\x97\x10/\xe9I\x84\x9dE\xebD\xbbgGo\x12\xed\xf6\xc1웆\x91\xef\xdf\xda\xdbד\xb7͝;J_\x89)口^\x9dso\xdf|S\xfb\xa7\xd6Ca\xbd\x82b\x89\xe01$ l\xe4\x8ad\xd4<`nyJ\x06\xa5\xcdј]Ǣ\xcb\xcc\xcd/j\xbf\xd0\xfe\xd6ժ\x9f\xe2}\x8d)I\x06]\x11\xfd[\xec\xce\xee\u0086\xc2\xee\xd8\xdd~\xd8}s\xe4\xbbϖ\f\xea:NJ\f\xbe^\x8b\xdaZ\xfe\x91\xa8^a\xb1\x04\x10\x0e\t\b\x1d\xb9\"\x19\xb7\xdegn\xc9IFcE\x8f\xb9\xf9!\xf9P\xfb;\xed\xa7\xec߃$\xa5\x93\xef\xee\n\xfb\xf0ޢ\x9d\x1c {bw\xfba\xf7͑//\x19I\xc1\xd7k\xe1\x94\f\x11\xc2b\t \x1c\x12\x10:\xc2%\x19箉>}m\xe5\x9eEe\xb5\xecú\xef\xd75\xa57>\xaeN\xa1\x1dD\xe7\x16\x16\x13]\xfa؍\xe3\xea\xb4\x0f\xb4\xbe\r\xb7\x8c\xbby\xbd\xf6Iy\xb2\xa1\xb2lA\xec\x89I\uf125\xfaƺ\xea\x1dGȑ\x9d\xd5\x1b(}\xa0\x82IG\xdfNG\x13\a\x8b\by\xe6hô\x92\xbas\xdbԖ\x9ai3\xd1N]D\x01Z\x85+J\xac\xb9m\xd1|-\xad4\x04\xed\x93\x05\xe5ъ\xfa\x93\xceM\xab\xb2\x85\xa4h]S\xe5\xe4\xfa\xa3\xae\xbe\xd9\xf9R[2N\x97\x10R\xb8U\xdf\xf7F]U\xb4\xbc~\xaa\xe3\xe0`!\x89n\xb4\x87D8f\x1c\xb6d\b\xebu\x14\xe3\xf2\x155\x91Ȑ\x80\xd0\x11.ɠ{&\x92\xc7j\xc9U\xcf]\xb3F}\xf0\xc3\xc2E;\xd7U\xdc\xdaG\xbb\xdfl\xaf\xbe\xa3\xbd\xbd\xfd\b\v\x89\x92\x19[[\xaf\xb9\x97m>\x14}f\xe73Q\xf6\xd9vt\xe2\x8d/\xb4֑\xa8\xbb\xbe\xf7I\xbb\xbeq\xb2\x81\xccT\xff[\xa0\x9e\xc7\x1f\xaf*\xack~\xabW\xdbm5ѳm\xeb\xd4\xea\tU\x8f5\x8c\xfek\xf7\x1b\x13W\x9c\xa2\xa7V\x94\xbd\xd1-\x0e\xd0J\xbeI\xder7Fk\x17\xd0\xfb\xf4\x19\xb9\xa7\xf4\x96\x96]\xcdd\x8dsӪ죭Ed\xea\xaa\xe6\xa9\xe3>t\xf6\xcdΗrG\x19\a\xdaۋu%\xda?\xba\xe1\x95]\x1b\xcb\xc99\xbeUVYE\xf3\xcf&jC\"\x1e3\x0e\xee(CT\xaf\xa3\x98#\xdf\xd8&\x12\x19\x12\x10:B&\x19\xb4\xa2\x81\xee$;\xe8CM\xecs\xf2E\xca&\x8e\xf6Aȝ\x98T\xfcC}\xdbV\xa8[m\xa4\xcd\xfcwn\xb5\xfa\x01\xd77;\xea\xaen'\xf9\xd8\xdcl\x8b\x92h\x9b\xb6\xf5ժ\x9a()cK\x19\xce&H\xed\x19\xdawF\xdd\xfa!;\x9bo\xf8\x91w\x80\xca\xdfH\xcc\xcaa_\xe9\x1a\xba\xa6\x94\x1d\x01\xf4Tթ\x92Ի\xed+\xc7&_Yt\x9aZ\xcf\xe9\xaa\x1a\xad^\xfbL\x80\xcb\xd7qbR\xa2O\xed\xf5\x15L,֗\xb9\x96 \xa2e\xea\xc7\u007f\x03\x1b\x12\x8f1\xe3p\x9e\x98\x88굊9\xf2\xf5h\xc2gH@\xf8\b\x9ddl\xa5\xef\x90n\xba\xf4\xfb\xea\t\xc4\r\xbd\xe7T\xae\xd5ΐ9\xc9P\xd5D_\xb5\xf8\xe1Lm\xc7\xccFz\x9ald[\xcfD\xddյ\x92\xe3\xfa\xc6W\x8fE+Ie\xf1\xd2\u007f\xe8\x0f{wՑ\x9d\xee&\xa2\u007f5J\xedQ\x8f\xb0{Ʊ\xcf{\x8f\x00\xca\xe6G\xcc\xf2\xe9A\xf2fϛ\xe4 e2\xf6\x81\xb9\x93\xdb\xe4+\xd3W9\xd7\x13UI\xf8\xa9m\xe5K\x85\x92\xf1i\xe5\xb4E\x1b?\xe8\xeb\xa5N\xa2\x0fQcH<ƌC(\x19\x8ez\xadb\x8e|=\x9a\xf0\x19\x12\x10>B'\x19mt_\x94\xd2e\xaad\xcc6N\xab\xe7\xb3\xfd\xae\xe5O\xed\xcd;\xb7^\xdbQ_C\x0f\xe8\xc7\xf3\xb1˟\xef\x98Ӯ\xa5|\xc3!\xf2Ѻ\xf2\xe7ԩ\xa8\xad0\xf4\xb1\xd2\xce&j\xccR\xe7\xca[ik9\xfb\xc8\xf5\b\xa0lB\xc7\xdcױN\v]\xa7m\xf5\xd8;\xadM\xbe2}\x11\xb7\x9d\xb0\v\x9a\xdc\xd4~\x87\x93\t\x81d\xd0\xd3\x1b\xee\x9bA\xaeiq\x1feXC\xe21f\x1cB\xc9p\xd4k\x15\x8b\xc9WЄϐ\x80\xf0\x11b\xc9h\xb8ဆviT{\x1fof\x1fi\xf6\x9b\xb7\xf1\x06\xf6\x16\xef\x9b\xf6\x10\xfd\aYς\x1e\x8a\xba\xab뱮\xaf\xf4\xd2\x0f\xc9!ګ\x96\xa8X\xa4\xed\xf8i\xb5\xbb\x89\x05V\xb1E\xf3\xe9\xbdZ\x94W\x00\xcb \xe6r\xea\x82[\xf6\xed\xdbw\v\v\xdaE\xac{\x1b\xb8M\xbe\xb2\xe8\x12\xb6g#a\xc7\xf4v߸|\x85\x92q`\x99\x9a\xff\xe9\xad%\xeb\xa9\x03{H<ƌC\x97\x8c\xee\x15_i\x8fD\xf5Z\xc5\x1c\xf9z4\xe13$ |\x84X2\xda\xf4\xe3ܟjw\x15\xb2w\xfa)m\x87\xfd\xe6ݩ\x9dOoeg\x185U\xea\x14\xf8\xb88\x1aS߂j\xeb\x13\xf9\xd32\xfd\x1e\xa6\xf2J6]\xfaػ\xdd\xd1\x04\xf7\xa1\xfcV\xf1g\xc5\xdaR\x9eW\x00\xed\x9bQO\xddT>\xae\xfe\xf3X%e\xd7\x1bk\xd9A\xfe\xa2%\x8eM\xbe\xb2\xe85\xea\xf4\xea\xbeA\x9b\xbfv\xdf\x1c\xf9\n$\xa3Y[\xbd\xa1\xb5Mԁ=$\x1ecF\xe9\xf1\xe7\x8e鱺d\xbcO\xde\xd0\x1e\x89굊9\xf2\x157\xe17$ |\x84L2\x0eM^ӳ5z\xb0\xa7\xa1\xf6o\xaan\x8c\xfe\xfe+\xad\x8d\xe4e\xf6DstMkm\xe9\xa7\xf4\xb3\xf6h\xe3;}\xef7F\xdb?S?\xf0\n\x97\xedXVؠ>\xfdḪ\xe6g&\x17\x16\xbdx\xc8U\xe1\x91\u0098[\xb8\xcbIEs[km\t[h\xb4\x9a8\xf7\x96v\xa5\xc0XI諬\xabԧ\xaeG\x00]c\x1f<\x18\xf4\xb4\x91\x9fv\xd3\xee\xa7I\x9b*\x11{\x8agnh[D6S\xc7&ס(\xb9e\xdb\xe6\xea2m\xb1\xd3\xec\x1b\xc3\xcc\xf7Sv\xf7\xe7\xba\xf6v\xf5þ\xf7\xed\xf6\xf6\xe2\xc6\xf67ΰ\xa9]\xbab\x87Z\x83\xe3\xe6\x0fǐ\x88ƌ1\x9fh\xf3\xf9\xdc[7\xdfԮ\xb2A=\x93\xf3\xaa\xd7.fU&n\xc2wH@\x18\t\x97d\xf4]C\xc8\xd6\t\xa4t\x9b~\xaa\xdcV{U\xd9\xdc6\xed\x99\xdeE\x93K\xee\xd8\xc7\xee\x10 $z\xb8T\xfdw\xa1\x1a\xben\xf6\xb8\xd9\xfa}\x19G\xeb'O[\xfab\x11\xdb\xebdE\xb1\xfb\x04\xbbf\xf3Og\x94V\xcc\xd7/M\x98Mh_\xbe \xc4\xfc\x9c\\\x17]cl\x89\x03\xde(\xb1\xef\x9f0\xd85\x9a\xdd\xc8\xd1J\xc8\xe8]꣏\xef\xbbvB\x8d~\xb3\x18\xb7iw(\xfax\xe3\xc4ʆϴ\xbdf\xdf4\x8c|\x1f2V\f\x1e\xa0t\xbf\xde2\xd9@\xe9\xaf\xefh\xae\x8aV\xd4:o\x17s\f\x89h\xcc\x18/Tl`\u007f\x8c^\x10Rrij^\xae\x98Y\x99\xb8\t\xdf!\x01a$\\\x92\x91\x06\xfa\x96D\xb7\xf9\xc5H\xb3-\xda\xe8\xb85B\x1e\xefoʤ#\xdf~ \xf5!\x01\xd9A\xdeK\x06\xed[s\xed\xdf\xfdb$\xf9\xaa\u2e64\xbe\xf4\xc1\xe1}\xdb{\x1a\xf2\xed\a\x02\x18\x12\x90\x1d@2\xb2\x938ߔ\x01 \x93@2\xb2\x91\x93\xdar\xa2_\x14\x00\x19\x00\x92\x91\x8dhˉ\xf6}\x9e\x00d\x0f\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\x8c4x\x9cf\x8f\x01i\xf0}\x031d\xcf\xcb\xdd/\xe4\x9add\xaf'\xeb\vĴ?\xd9,(bb$\xe9\xb4\\5\xe0jh-2~ע\xa8\x95\xdbl\x1b\xcd\xfeN\xae?b\x96\x88훈\x98bn\xe2\f\xaa\x1fɺ\xbaƼX\xbe9d\xae\x17y\xe67\x9b+\x92\x91\xfd\x9e\xacg^$ϝ\xa2\xa7ZȋgD%\f\x8c$\x9d\x96\xab\x06\\\r-\xc4\xf8U\xae\xd1-\xdcfϛ\xd1\xc6\xf6=\xeb\xaaK>\xd2\v\xc4\xf6M\x88\xbb\x98E\x02\x83j\xe1\xe1Ԛ\x9c[\xac\xe0\xc5\xf2\xcd!\x93\xbd\xc8+\xbf\xd9\\\x91\x8c\x10x\xb2\x1e\xd2~@s\x0fq\xff\x96\xa0\v3I\x81\u007f\xa2]ú\xa8\x11P\xb2\x8e\xdb4:\xdf]Y\xa7\x85s}\xf3\xc1Q\xcc&\xa1A5\xf0rjM\xe0(GL̋\xe5\x9bC\x06{\x91O~\xb3\xb9\"\x19!\xf0d\rR2z?1\x02>\xe9\xe56\xcd\xce7\x97hoq\xaeo>8\x8a\xd9$4\xa8\x06\xc9:\xb5z\x92\xa4dd\xa6\x17\xf9\xe47\x1b.\xc9\b\xb5'+'\x19g\ueaccV\xd53\x13$\x87\x9b\xa9#IK2\xac&\\\xa2\xc3i\x8a\xb5\xa9O\x8a\x96\"\xf6\xa3\xe5f߸\xcc8\xafWʛ\xc1\xda\xc5\xec̼\x06\x95C\xe4\xd4ʏ\x83\xed\xea\xea\xe8\xe6\x17\rW]\xfb\xf8\xe3W\x95z\x1e\xc6q\xe3`w\x9eF\x17\xfdHO}!)|\xd9Z\xec\xe0*\xcbd/\xf2\xc8o6\\\x92\x11jO\xd6CdgOOO\x1b\x9b\xf0;HӞm\xf5\x85\xfb\x9c\x86\xa9\xce$-\x19\xb0\x9a\xe0k\xa0q$\xa3\xef\x96\xd9l\xdb\xec\x1b\x97\x19\xe7\xf5\xea0\x83\xb5\x8bٙy\r\xaa\x8dЩ\xd51\x0e\x96\xab+\xdf\xcdޙ\x15뛋K6י\xbf\xb8\xec\x86\x1f\a\xbb\xf3ڏ\xaeo\x9d\xad\xa6\xae-J\x18\x8b\x1d|e\x99\xecE\x1e\xf9͆L2\xc2\xec\xc9z\xc8\xf8\x10;\xc4ޑ\xaa\xda\xf4ݤ\x19\x8a\xd9n\xa6\xce$M\x19\xe0\x9a\xe0j\xa0\x1e\x92\xb1\xa2\xa7\xe7ང\xfd\x869\xdf7;3\xdb\xeb\x953\x83\xe5\x8a\xf1\x99\t\a\x95C\xec\xd4\xea\x1a\a\xd3o\xcd\xee\xe66\xe61\xb9>\xce\xf9\x197\x0e\x0e\xdb\xd7\x19\xea\xee\x9ej\xe6\xbff\xbb\xa6\xf0\x95e\xb2\x17y\xe47\x1b:\xc9\b\xaf'\xeb!\xf2\xb3}\xfb\xf6\xad\xd1\xdee_\xac\xaf\xbba\"\xd1\x0e\x06,7SW\x92\xa6\fpM\xf05xH\x06S\x94r}\x15\x86\xf3o\xb53\xb3\xbd^93X\xbe\x18\x97\x99pP9\xc4N\xad\xaeq\xb0&\x9beں\xacL\xfd\xe7c\xef\xa5\"~\x1c\x1c\xb6\xafO\xb3\xdd\x1b\x98M\xad-\x19|e\x99\xecE\x1e\xf9͆N2\xc2\xeb\xc9ʭD쫨Z\xda\xda^\xabK\x86\x99\xaf+IS\x06\xb8&\x12X\xcbhڷ\xef\x13c\xf9\x8f\xf3o\xb53\xd3\xcf\xf7\x99\xd7+g\x06\xcb\x15\xe33\x13\x0e*\x8fЩ\xd55\x0e\xd6d\xb3jX3\xfa\vv\xec\xf7!\xf5\x80\x1f\a\x0f\x9bZqe\x99\xecE\x1e\xf9͆X2\xc2\xe6\xc9\xcaM\xf8\x195l\xba.pJ\x86+IS\x06\xb8&\x12\x90\f\xb3;\xd4\xe1\xdfjgf{\xbdrf\xb0\\1>3\xe1\xa0r\x88\x9dZ]\xe3\x10;\xd9\xfeZX\xf7׃\xd5s=\xaf[\xf2\xe3\x10kS\xbb\x99\xd9\xd4j\x95=\xe3\xae,\x93\xbd\xc8#\xbf\xd9\x10KF\xd8<Y\xb9\t_\xc5ގ}7;%Õ\xa4)\x03\\\x13r\x92\xc1\xf5\x8d\xfb\xa0\xb5\xbc^93X\xae\x18\x9f\x99pP9\xc4N\xad\xceq\x10L\xb6\x03\xe4\x1aBjO\x1a\xcf\x1fo\x8e\xb9{\x8a\x1b\a\x87\xed\xeb\xb5l\xede&\xf3\x8c\x1d\xb7TM\xb2\xc6]Y\x06{\x91O~\xb3!\x93\x8c\x10{\xb2\xf2w\u007f6\x93\xfb֯\xba\x95\x94\xb7\xbc\xc3\xe7\xcb%\xc9Y\xae\xdaM8\xef\x1f}_\r0\xda07\xd9\r\x90\xdc\xfd\xd2F\xdf\x1c\x99q^\xaf\x96\x19,_\xccΌz\f\xaa\x8dЩ\x95o\xcdvu\xe5k8P\xbckg\xfbIS\xcd\xeaI\xe9i\xea\x84\u007f\xb1\x1c6\xb5uo\xed\xaa\xd1R\x9f[Ѳ\xaa\x86\xb0\x00\xbb\xb2\x8c\xf6\"\x9f\xfcf\xc3%\x19a\xf6d\xb5\xbf!\xb2\x91\xf6\xad\xa9\x8eV<\xf0Bu\xb4֑\xaf\x9d$g\xb9j7\xc1\xd7@{X\x99\x12mA\xdf\xdalS\xff\xce\xe4\x9a\xd4\xfb\xe6Ȍ\xf7z5\xcd`\xf9bvf\xd4cPm\x84N\xad|k\xb6\xab+_Û\xda2e\xf4\x0e}\x19`s)\xd9G]\xf0/\x96\xfd\x1a\xcfl\xbeo\x82\x91\xfa\xd1ڒ\tuO;+\xcbd/\xf2\xcao6\\\x92\x91\x06\xd2\xe2q\x9a%\x06\xa4\x82\xbe9\xce\\2©ҦS\xe7Ν\xde\u007f\xefd\xfd袕\xb8\x8f2$pW\xd6o8\x1aΒ\x97\xbb\x9f\xc8{\xc9H\x87\xc7i\xd6\x18\x90\xc6\xf6-\xf3\x92Ѫ\xdf\x01A\xfb\xca\xdbؿ/\x965\xc5\r\x8f\x8f\xb3\xb2~\x84o8k^\xee\xfe\x01\x92\x91_d^2\x0e\x14\xeag$\x1f\x16\xb2\xfbBN\x96/\xe9\x8d\x1f\x1f\x17ge\xfdH\xc6\x1a\xce<\x90\x8c|\"\x1b\xbc^\xfb\x1aK\x9a\xb6\xed\xd9\xd6T\xd2\x14@\"\x81V&C\xc6\x1a\xce<\x90\x8c|\"+\xbc^\xfbv\xd4UF+\xebv\x042\xd7\x02\xadL\x86\x8c5\x9cq \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\xa0\x1f\xe9\xeb\xd3\xff\a\xe1\x05\x92\x01\xfa\x8b\xcf\x1a+Ƚ\x94>@\xca\x1b\xbd\u007f\xf8\x13d;\x90\x8c4\xf8\x96f¤3\xf8^\x04Mߌ\x19\x1bw\x1dW\x95\xa3\xfd\x85\x19W\xe9?\"\x98\x89\x81\x02)\x92k\x92\x91ݞ\xac\xa4\xbc\xee}A\xbcM\xb2\x16\xa6\t\xba\xafz\x93d\xc3\xffh\xba\xa6\xa4>\xc1\x86\x0f\xea?\u007f\xc5\xd8\xc3~\x9e\x9bz\f\x14\xc8nrE2\x120\xde\xcc\x02O\xd6\xf6\x17jF\xef\x11ś\b\xcd?=\x8cBy\x12t_\xf5&Ɇk+6<T\x92\xe0OU\xec'o\x98\x9b\xf6o\x10敛in\x90+\x92\x91\x90\xf1f̏K\xf7\xbf'k\xdf\xdcjA\xb4\x8d\xe8\x13\xdb\xcb(\xd4&q\xf7UO\x92j\xf8+\xb2\x8e\xf6%\xfa;\xb9\xa2\xdf*\xcd/7\xd3\xdc W$#!\xe3M\x81d\xf4\xbb'+\xef\x05\x90 \xfeF\xa1\x89\xbb\xafJ\xe1\xdb\xf0Q\"q:#\x96\x8c|r3\xcd\r\xc2%\x199\xe0\xc9\xdaPI\xf9zyoO\xdb\xfcSl\x14\xeaٚ\xc0}\x95ږ\xab\\\xbe\xee$\r\x84\xae\xa3\xbe\r\xf7^\xa5\a<Fy\x93Y\xca{\xbdr\xddd\v\x18\xef\x98\r\x1e$\xf6\xe9\x99\xc0\xcdTԚ#u\xeb\x85\xf5\xe8\x10H#ᒌ\xd0{\xb2\x1eYJV9\xeaux{Z\xe6\x9fb\xa3P\xcf\xd6\x04\ueadc\xe5*\x97\xaf;I\x13\x91\xeb\xa8\u007f\xc3\x1f\xb4o%\xcd\xed\xda\xefu\xdb&\xa8\x0e\xafW\xbb\x9b\xe7\xfe\xbe\xa7\xa6\xcc҆ޫj\xde\xfc\xd48\x15\x12\xb8\x99\x8aZs\xa4n\xbd\xb0^\x1d\x02\xe9#d\x92\x11~Oֆ>g1\x97\xb7\xa7a\x98!6\n\xf5jM\xe4\xbe\xca[\xae\xda\xf9\xba\x92\xe4\x88u\x1dM\xa0a\xebĄ3A\xe5\x1a\xe6\x8a\xcdW\xbbΝİ\x9f\x037~\x8c=v\xa0\xbcZ\xb36\xb9\x17ֻC M\x84N2B\xed\xc9\xfaΎ\x9a\x92\xe3\xceb.oOc抍B\xbdZ\x13\xb9\xaf\xf2\x96\xabv\xbe\xae$9b]G\x13h\xd8^˰MP\xb9\x86\xb9b\u007fm\xdb0c\xb2\xb5P\xda]1m\xdd.#\xe7\u0601\xf2j\xcdڴ_X\xea\xdd!\x90&B'\x19!\xf7d=]\xb8\xc1Y\xcc\xe5\xedi\xce\\\xa1Q\xa8Wk\"\xf7U~\x99\xd5\xceו$G\xac\x1fX\x02\r[\x92\xc1\x99\xa0r\r;\x8a\xd1v۰d\x9f\xeeMol\xbb\aʫ5k\xd3~a\xa9w\x87@\x9a\b\xb1d\x84ӓu\xe2\ng1\x97\xb7\xa71s\xc5F\xa1^\xad\x89\xdcWy\xcbU;_W\x92\x1c\x9e\x92\x11\xafaK28\x13T\xaeaG1\x8f+&\x82\x81\xf2j\xcdڴ_X\xea\xdd!\x90&B,\x19\xe1\xf4d\xadXrp\x15_\xcc\xe9\xedi\xce\\\xb1Q\xa8gk\x02\xf7U\xder\xd5\xce\xd7Y\x8cG$\x19\xbe\r[\x92\xc1\x99\xa0r\r;\x8ayH\x86`\xa0\xbcZ\xb36\xb9\x17ֻC M\x84L2B\xec\xc9j\xdc0][\xdfx\x13\x9f:\xe7\xedi\x9b\u007f\x8a\x8dB\xbd[\x13\xb9\xafZ\x96\xab\xd4\xce\xd7U\xccD\xec:\xea۰~\xc5D39\xe0MP\xb9\x86\xf9WH\x15G\xeb\f\xe4\x1d\xfbz\xab\xc8\xcdTԚ#u\xeb\x85\xf5\xe8\x10H#ᒌ0{\xb2\xb2\xdb#ZԸ\xea\xf2\x1d\\1\xde\xdb\xd36\xff\x14\x1b\x85z\xb6&t_\xb5,W\x19F\xbe\xeeb\x06b\xd7Q\xbf\x86{˴\xcd\"v\x15\xd6a\x82\xca5̽B\xf4\xefE\xf7\x1d\xfc\x8c]V\xfe\xec\xfd\x05Q\xd3IY\xecf*h͑\xba\xf5\xc2zt\b\xa4\x91pIF\x1aȰ'k@\xa6\xa2i\xe9Eд\xceԔ~>!S\xcd\vD\x89\x0f\x14\xc8\x16\xf2^22\xec\xc9\x1a\x94\xa9h\x1az\x91\x06N\x1dT\x8f.>;\xf0\xa9\xf9Xb\xa0@\xb6\x00\xc9\xc8,y\xec\xed\t\xc2\t$#\xb3䱷'\b'\x90\x8c\f\x93\xbfޞ \x9c@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00H\x04\xd8\xc9\x1a@2\x00\xf0\x05v\xb26\x90\x8c4\xb8\x99f\xbb\xd5h\xf0=\xceq`'ˑk\x92\x91\u007f\x9e\xac\xed\xa3\xc9\xdc>\xfa\n!\xa3\xed\xdfӌO\xaa\xfe\xad\xbe$ы\x14H\xb25\xd8\xc9&I\xaeHF\xfez\xb2\xf6\xec\"%\xed\xb4\xfb\x15\xb2+\xc6BHL\xca\xfe\xad6\x1e\x99\t{\x916\x92\x183\x06\xecd\x93$W$#\x8f=Y\xbbIC\xa3z\fE\x12\xf4F\r\xc0\xbf\xd5\xc2+\xb3\x04?\xbc\x03\"\x891\x83\x9dl\xf2\xe4\x8ad\xe4\xb1'k7\xd9\xf7\xbad\xee\x00\x00 \x00IDATUړ\xb8d\x04\xe9ߚ\xbd?\xd5\xeb\x9b\x19\xecd\x93%\\\x92\x01OVAk\xdd\xe4\xf8\xad\xaf\xe8\x92aY\xa3z\f\x14\xb5{̹\xaf&R\xccF\x94\x19\x9f\x8e\xd0\xe0\x95\xef\xa6\x10\xd8Ɇ\x86pI\x06<Y\x05\xad\xa9\x92\xb1\xae^\x97\f\xdb\x1aU<P\xd4\xee1羚H1\vaf\x8e\u038b\f^\x1d\xdd\x14\x01;\xd9\xd0\x102ɀ'klk\xaad\xfc\xbd\xf8\xef\x9adp֨^\x03e\xf7\xd8v_M\xa0\x98\x8583W\xe7c\r^]\xdd\x14\x01;\xd9p\x10:ɀ'\xab\xbb5U2h\xfd:}-öF\xf5\x1a(ۿ\x95s_\xf5/f!\xce\xcc\xd5\xf9X\x83WW7E\xc0N6\x1c\x84N2\xe0\xc9\xean\x8dI\xc6+7k\x92\xc1Y\xa3z\r\x94\xed\xdfj\x0fT\x02\xc5l\x84\x99\xb9:\x1fk\xbd\xe6\xea\xa6\b\xd8Ɇ\x83\x10K\x06<Yu\x98d\xf4\x94\xeeb\x92\xc1Y\xa3z\r\x94\xddc{\xa0\x12(f!\xce\xcc\xd5\xf9\xd8I\xec\xea\xa6\b\xd8Ɇ\x83\x10K\x06<Yu\x98dЇ\x1a\x98dp֨^\x03e\xf7\xd8\x1e\xa8D\x8a\x99\x883sv^0\x89\x9d\xdd<\xde,\xb8\xd3\nv\xb2\xe1 d\x92\x01O֘\xd6zv\x91W\xbai{\t\x93\f\xdb\x1a\xd5s\xa0\xcc\x1e\xf3\x03\x95H1\x13af|\xe7\xc5\x06\xaf\\7U\xeaI\xa9\xeb\xbeK\xd8Ɇ\x86pI\x06<Yc[\xdb3\x9a\xdd \xd2WS\xa1\xf6ӲF\x9d\xeb9Pf\x8f\xf9\x81J\xa8\x98\x8103\xbe\xf3b\x83W\xae\x9b*\x9bK\xed\xc5\x01\x1d\xd8Ɇ\x86pIF\x1aH\x8b\x9bi\xe2V\xa3\x01y\xb2ʐ\x96\x1e\xfb\xe0\xeef+\xe9\xb7\xee\x06\x02\xecdm\xf2^2\xd2\xe1f*a5\x1a\x94'\xab\fi\xe8\xb1\x1f\xcen\xf6\xbdX\xd6\x147<\v\x81\x9d\xac\t$#\xb3\xe4\x89'\xab\xb3\x9b'˗\xf4Ə\a\xd9\v$#\xb3\xe4\x89'k\x9et3/\x80dd\x98<\xf1d͓n\xe6\x03\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\x8c48\x94f\x8f_g\xf0}\xeb_\xb2g$\x81I\xaeIF\xf6z\xb2&_\uf87aҊ\x86=\x151\x93ߣC\x1c~\xee\xab\xfe5\x18$\x9b:GR\xbd\xc8_\xe7\xd3\xec%W$#\xfb=Y\x93\xae\xb7\xad\xb4f\xe3\xd6ل\x1cq?!\xee\x10\x87\xaf\xfb\xaao\r\x06ɦΑl/\xf2\xd5\xf94{\xc9\x15\xc9\b\x81'k\x92\xf5~5q~/\xa5\xddձ\x93M\xd8!\x8eD\xdcW\xe3\xd7`\x92d\xea\x1c\xc9\xf7\"O\x9dO\xb3\x97\\\x91\x8c\x10x\xb2&Y\xef\xb2\x12\xed\x97\xe3\xd6\xc8O\xb6D\xdcW\x13\x93\x8c$S\xe7H\xbe\x17y\xea|\x9a\xbd\x84K2B\xedɚ\\\xbd\xb4Z\xb7\n\xfbbM\xafW\x87x\xfbP\xdbT\xd4\xee\x9b\xc3jT\xa6\x06\x8b\xe4R\xe7\x87$\xe9^\b\x9dOA\x06\t\x97d\x84ړ5\xb9z{\v\xb9syq\x878\xefT\xceT\xd4\xee\x1b\xbfW\xaa\x06\x8b\xe4R\xe7\x02\x92\xef\x85\xd0\xf9\x14d\x90\x90IF\x98=Y\x93\xab\xf78w6 \xee\x10W\x19\xeffj\xf7\x8d\xdb+W\x83MR\xa9s\x01\xc9\xf7B8\x92 \x83\x84N2\xc2\xeb\xc9ʐ\xaf\xb7\xb7\xc8\xfe\xc0\x17w\x88\xab\x8cw3\xb5\xfb\xc6핫\xc1\x81|\xea\\@\xf2\xbd\xf0\x1aI\x90)B'\x19\xe1\xf5dM\xb2^c\x15\xa0\xb7ͫC\\,\xeffj\xf7\x8d\xdb+W\x83E\x92\xa9s\x01I\xf7B4\x92 \x93\x84X2\xc2\xe6ɚd\xbd\xcbJ4\a\x81m\xe4\x94G\x87\xb8X\x87\x9b\xa9\xd57n\xaf\\\r\x16I\xa6\xce\x05$\xdd\v\xd1H\x82L\x12b\xc9\b\x9b'k\x92\xf5~5\xf1^v\x95\xa1v\x9aW\x87\xb8X\x87\x9b\xa9\xd57n\xafd\r&I\xa6\xce\x05$\xdf\v\xc1H\x82L\x122\xc9\b\xb3'kr\xf5\xaa\x93i\xdc\xdc\x17[\xeb\x8a\xd8ѹ\xb8C\\,\xeffj\xf7\x8d\xdb+W\x83Ir\xa9;\x02\x92\xee\x85\xc8\xf9\x14d\x90pIF\x98=Y\x93\xac\x97\xb2og\x8c\xbbf\xfea\xb6\xe5\xd1!.\x96w3\xb5\xfbf\uf56c\xc1 \xb9ԝ\x01I\xf6B\xec|\n2G\xb8$#\r\xa4š4K\xfc:\xd3ҷ\xfe%KF\x12\xd8\xe4\xbdd\xa4á4k\xfc:\xd3з\xfe%kF\x12X@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\xd2\xe0[\x9aa'\xd1\xe0;\x1462\xfc\x02\xe46\xb9&\x19\xf9\xe4\xc9ꁟ\x11\xab\x1f\xbb*vx?\xf9\x02\xfb\x05\x8c\xf2\xba\xf7\xbd#\x18\xfaP7\x11\xcdW`\r!M\xae\xe7\xe36A\xb9\x1e7\xaa\xad\x8d;\x1a7V\x04\xac\\\xd3H\xaeHF>z\xb2\x8a\xf15b\xf5cGi\x1c\x13\x803/\x92\xe7\xda_\xa8\x19\xbd\xc7;\x84\x9aC\xfdii\v\xfb\xfd\xbf\xafZ&|\xeaz\xdenb\x8f\xe8'\xb7\xec\x1e\xff\xad\xbd}\xbd\xf9\xab\xc7R\xc0\xca5m\xe4\x8ad\xe4\xa7'\xab\x80D\x8cX}\x88{\x8cr\x88\xf9\x8f\xf4ͭ\x8e\x17C\x8d\xa1\xbeI\xff)\xbeͳc\x9e\xb6\x9a\xb0_7\x1bg\x8f\xf7%%\x19\xb0rM\x1b\xb9\"\x19\xf9\xe9\xc9* \x11#\xd6T\xd0$\xc3û\x80C\x1b\xea{\x9fѶ\u007fz\xafw\x1c\xff\x13\xcb&\xce\x1e')\x19\xb0rM\x17\xe1\x92\fx\xb2\x1a\x1dZH\xa2\x1b\x8dnr\x9b|\x87\x84F\xac\x9e\xc5,N\x97\x10R\xb8U\xdf\xe6\x86\xcfF\x97\x8c\x86J-\xc0J\xf2\xcc}\x95Ѫ\xfa\x83Z\x84=\xd4\xcb\xf4C\x88\a\x969F\xc7n\xc2\xf1\xba\x89{\xccI\x06\x97\xce\x1buU\xd1\xf2\xfa\xa9}T<\x92Z8\xac\\\xd3D\xb8$\x03\x9e\xacF\x87>\xdaZD*\x9a\u007f6\xf1^\xc7&\xf53b\xf5,fs\xa0\xbd\xbd\xb8\xd9\xd5\x1a\xcf!\xb2\xb3\xe7\xc8R\xb2\x8am\xdb6\xaa;HӞm\xf5\x85\xfb\xa8c\xa87\xd7\xd0w\xaaަ\xb7nt\x8e\x8eՄ\xe3u\x13\xf7\x98\x93\f;\x9d\xfd\xa3\x1b^ٵ\xb1\x9c\x9c\xa3R/\x00\b\x84\x90I\x06<Y\xcd\u007f\xa3e\xea\xf1A\x03\xeb&\xbf\xe9g\xc4\xeaU\xccA\x89.\x19|1\x9bC\xdaqA\x03\xfb\x80\xe7mT\xb7\xa92\xd7w\x13\xfb\xd9wn\xa8\xdb\xcb\xe9\xd2\xe8RZ\xae\xa9\x98ctJ̳G\xebu\x13\xf7\x98ڒ\xc1\xa5\xb3\xbe\x82\x89\xc5\xfa\xb2>\xc9\x17\x00\x04A\xe8$\x03\x9e\xac\xacCj7\x1f\xa2\xe6\xe2\f\xb7\xe9c\xc4\xeaÝ1\x9f\xf9b6\x87\xc8\xcf\xde\xd9QS\xc2Z\xe1{\xf1\xc5\xfa\xba\x1b&\x92\xd9\xd41\xd4\u007f%=w4\xcc\xed\xd6Sr\x8cN\xacd\x88{Lm\xc9\xe0\xd2\xf9\xb4rڢ\x8d\x1f\xf4\xf5R\xf9\x17\x00\xa4L\xe8$\x03\x9e\xac\xacC|7\xf9M\x1f#V\xcfb\x0e\x8c\xf9\xcc\x17\xb3\xd1\xd62N\x17n\xa0\x8e$\xf7UT-mm\xafU%\x83\x1f\xea\xbe臥\aJ?\x8cj\xeb\x0f\x8eщ\x95\fq\x8f\xa9-\x19|:\xa77\xdc7\x83\\\xd3\xd2'\xf7\x02\x80@\b\xb1d\xe4\xb3'\xab\xe7\u070fo\xc4*%\x19|1\x1b}\xf9s\xe2\n\xeaHrF\r\x13\xa8\x05\xaad8\x86\xba\xba\xa5\x92V\xae\xd1/\xc8:F\xc7)\x19\xecu\x13\xf7\x98ڒ\xc1\xa5s`\x99\xbayzk\xc9z\xb9\x17\x00\x04B\x88%#\xaf=Y=\xe7~|#V\x19\xc9\xe0\x8bQz\xfc\xb9c\xda_]2*\x96\x1c\\\xc5'Y\xc5&k\xdfͪd8\x86\xba\xae\xe6^z\xef\xdc:\xad\xa0\xe3r\xaa%\x19\xd6\xeb&\xee1\xb5%\x83K\xa7Y__\xa9m\x92{\x01@ \x84L2\xe0ɪw\x88릣\xc7>F\xac\xde\xc5Lz\xdfno/nl\u007f\xe3\f_\x8c1\xdf0J<\xa8M\xd7\xda\xfaƛ\xf8$\x9b\xc9}\xebW\xddJ\xca[\xdeq\f\xf5\x92\xd1-\xb4e\xb4z\xdc\xc4w\x93o\xc2z\xdd<z\xfc)\xbb\xfbs]{\xfb_\x1d\xe94\x93\xd2\x15;\xd4\xd8=T\xea\x05\x00\x81\x10.ɀ'\xab\xd1!\xae\x9b\x8e\x1e\xd3\xf8F\xacq\x8a\x19\xec\xd7\xf3!\x1b\xa8c\xf8(}\xa1\x82\xed\xa2\xec\xe6\x91\x165\xed\xear\xf6-\x11+ɾ5\xd5ъ\a^\xa8\x8e\xd6:\x86z縃\xf4Pi\xab\xb3\x9b|\x13\xd6\xebF\xc5=~H\x0f%\x0f8\xd2\xf9\xf5\x1d\xcdUъ\xda=\x8eb\xfe/\x00\b\x84pIF\x1aH\x8boi&\x9dD\xd3ҡ\xb0\x91\xc9\x17 \xd7\xc9{\xc9H\x87oif\x9dD\xd3С\xb0\x91\xd9\x17 ǁd\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\xa4\xc1\xc24Ö\xa0\x01t\xa8\xc9m\x89\b\x92$[F2\xb8\xf7d\xaeIF\xcey\xb22\x13T\xdd\xdddsk\x91\xf1\xeb\x11E\xad\xdcf\xdbh\xf6wr\xfd\x11\xb3D\xaa\x9e\xac*GȲx#\x19\x8f\xc4L[\xe5I\xde\xe05\xa3d\xcdH\x06gS\x9b+\x92\x91\xb3\x9e\xac\xcc\x04\xf5\x14=\xd5B^<\xd3B\x8cߨ\x1a\xdd\xc2m\xf6\xbc\x19ml߳\xae\xba\xe4#\xbd@R\x9e\xac.kԆ\xe2S\xae\x91\xe4\x02\x846\xaa\x16\x89\x99\xb6ʓ\xb4\xc1k?\x93e#\xc95\x11\x94Mm\xaeHF\xeez\xb2\xea?\xb6\xb9\x87\x1c\xa2\xeb\xa2\xc6/a\x96\xac\xe36\x8d\x1ewW\xea?\xb1\x99\x9c'\xab\xd3\x1a\xf5\xe8\xe8\xc7\xd8\x1f~$\xb9\x00\x91\x8d*G\x82\xa6\xad\xd2$i\xf0\x1a4\xe6\xbbċ,\x1bI\xbe\x89\x80ljsE2rדՖ\x8c\xdeO\f\x9d\xf8\xa4\x97\xdb4{\xdc\\\xa2M\x9d\xe4<Y\x9d֨\x0fE\xb5\xdf\x03\xe5G\x92\v\x10٨r$h\xda*M\x92\x06\xafAc\xbeK\xbcȲ\x91\xe4\x9b\bȦ6\\\x92\x91\x8f\x9e\xac\xb6d08SckS\u007fC\xb6\x14\xb1_\x147;\xb4B\xadf+ݪ\xfe\xbb\xc2\xce\xc0i\xc4*\x1e>\x95\xe3E\xba}\x825\x92\\\x00\xb7\xb9\x90\x14\xadk\xaa\x9c\\\u007f\x94:\x10\x9b\xb6\xda6\xaa\x8eb\"\xb7X\xb1\xe5j\x92\x06\xaf\xee\x97%\x06G\x00\x97o\xf7\xd2\x19\xa5w\xbc}m\x9b#\xd8~\x97dp$\xad\xcc\x16\x92\u0097\xad\x15:\xd1P\xbb\xd3\tƦ6\\\x92\x91\x87\x9e\xac\x9a\tjOO\x9b\x9fd\xf4ݢ\x1d\xb1\x9b\x1d:\xf5\xfd\x1a\xb5\x9a\xee7\xe76\xf0?\xea\xe70b\x15\x0f\x9fJ\x93q\x00k\x8d$\x17\xc0m\xb2ʦ\xaej\x9e:\xce\xf9\xb1+6m\xb5mT\x1d\xc5Dn\xb1b\xcb\xd5$\r^\xdd/K\f\x8e\x00\xbb\xb5\xd37\x94\xafi[h\xfc\xa6\xb1\x85\xfd.\xc9\xdcHڙik$\xe6\n\x9dh\xa8\xdd\xe9\x04cS\x1b2\xc9\xc8?OV\xc3\x04\x95ē\x8c\x15==\a\xef%\xbbضա_\xebW\x87f\xba\xd6Bm#V\x8f\xe1cW\x96\x8c\xdf\x1c\xb7G\xd2\xe3p::M\xcd\xfat\x95\xdbN\x8d\xe16m\xe5lT\xb9bb\xb7X\xb1\xe5jr\x06\xaf\xeeX\x11V\x00W\xac\xb1\x8cy\xdb-qI\x06\xff.\xc9\xd4H\xf2\x99\xd9V4\x1eC\xed<\xf7\tƦ6t\x92\x91o\x9e\xac\xcc\x04u\u07fe}k\xe2I\x06{g\x95\xebK$V\x87\x0e\x16\xf6\xf6\xfc\xfa\xf4\xb9\xe8A\xea\xc06b\xf5\x18>\xf509jTa\x8f\xa4\xd7\x1b][i]O\xbe\xa2\x1cb\xd3V\xceF\x95+&v\x8b\x15[\xae&g\xf0\xea\x8e\x15a\x05\xd8\xc5\xfa\xc6iu~\xe4\x92\f\xfe]\x92\xa1\x91tdfK\x86\xc7P\xbb%C\xf4\x9e\x94%t\x92іo\x9e\xac\t\xace4\xed\xdb\xf7\x89q\xd9\xc0\xeaPo\xd1\xc15dő\xc2^\xea\xc0\x1e\x1d\x8f\xe1\xa3'\xa3?\x8a\x89\xf5z\xa3k\xef\xdev\xa7ɐش\x95\xb3Q\xe5\x8ay\xb8\xc5\n-W\x934xuŊ\xb0\x02\xecb\u007f\xd3\x17\xa9\xbb]\x92\xc1\xbdK25\x92\x8e\xcc\xc49pC플`ljC,\x19y\xe2ɚ\x80d\x98}\xa0|\x87fl\xad\x9d;\xa3\xd5}\xf3\x9a=:\x1e\xc3G\x97\x14\x1e\x8b\x89u\x04pC\xbd\x84=\xdeH\x1c\a\xfdb\xd3V\xceF\x95+&v\x8b\xf5\xb0\\M\xce\xe0\xd5\x15+\xc2\n\xb0\x8b\xf5\xe9u\x1ev\x9f\x98\xd8\xef\x92L\x8d\xa4#3\xad\xdeg\xa2\xd4s\xa8\xf9\xd6D\xef\xc9d\b\xb1d\xe4\x89'\xab\x9cd\xd8\x1d\xfa\xfe\xa2h\x1bY\xf8\x00ub\x8f\x8e\xc7\xf0}Vl\xd96\xf3ot;\x80\x1f\xeakԷ`\xf7\r\xb5ZD|\xd3V\xceF\x95+&v\x8b\xf5\xb0\\M\xce\xe0\xd5\x19{\xbcYp\xf7\x94\x15\xc0\x15[P\xaeN\xbe\xbe\x86\x98\xb5\f\xeb]\x92\xb1\x91\xe43\x1b\xb7Tݬa\xf5z\f5\xdfZP6\xb5!\x93\x8c\xfc\xf3d\xe5\xee\xfeTw\xbf\xbf\x9e\xac3*67\xd9ݟ\xd6\xcd\xe2\\\x87\x9e\x1b7\xb1\xaf\xbad\x15\xe5q\x8c\x8eh\xf8(}|\xf4QA,\x17\xc0mF\xc9-\xdb6W\x97\xe9\v\xae~\xa6\xad\xb6\x8d*WL\xe4\x16+\xb6\\M\xd2\xe0\xd5\xf5\xb2ԓ\xd2\xd3ԁ#\xc0n\xed\xb3\x8a\xaa\xf5\xad\xf3\x8bc%\xc3 s#\xc9g6\xb7\xa2eU\r\xd1\xde\xd5\xe2\xa1\xe6[\vʦ6\\\x92\x91\x87\x9e\xac\xf6wL6\xaa\xf2\xc0:V\xa2M\x0fk\xb3M\xfd;\x93k\xc6\xecЁ\xb2\x15\xb4\xa5t\x1f\xe5q\x1a\xb1\n\x86\x8f\xfe\xbd\xa4A\x18\xcby\xa7ڛ\xd1\xc7\x1b'V6\x186\xd0\xf1M[y\x1bU\xae\x98\xc8-Vl\xb9\x9a\xa4\xc1\xabk|7\x97\x12爸\x02\xec־h\xac*\xa9=\xe0)\x19\x99\x1bI>\xb3\xa3\xb5%\x13\xea\x9ev\xe5\xe0\x18>\xae\xb5\xa0lj\xc3%\x19i -\x16\xa6\x99\xb4\x04M\xadCO\x13\xee\x88\xc5\x0f\xc7\x19Q\xe2$Y,\x10Z\x89\xeb(#.\xee\xe5O\x19\xd2;\x92\xf2\x99\x05\xf6\x9e\xcc{\xc9H\x87\x85if-AS\xeaЏ\x9a\xfc\"8\xa4\xdf\xe8:I\x16\v\x80\xbe\x17\xcbd\xfa\x97\xc4ĴI\xefHJg\x16\xdc{\x12\x92\x01\x92F\xfa\x8d\xae\x93d\xb1\x008Y\xbe\xc4u\xd19>\xd2\x133Y\xa4\x87\xa4\xdf2\x8b\x05\x92\x01\x92䤶\xaa\xe7\x17\x15C\x92\xc52\xc1\xd16\xf2\xd8[\xfd\x90\xaa\xfc\x90\xf4Wf\" \x19 I\xb4U\xbd\xe3T\x96$\x8be\x82\xb9j\xaaE\xae\uf2a5\x03\xf9!\xe9\xaf\xccD@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x82\xb00u\x11\x9c\xffez\b\xbe\xc7\xfdK\xb6\x8fon\x93k\x92\x91\x93\x9e\xac\xc19sj\xf8\x99\xb6z\fT,Iu\xc8ɡ\xbaҊ\x86=\x151\x12\x167\x87\xe0\xfcE\x81<\xb9\"\x199\xed\xc9\x1a\xa43g\x02\xa6\xad⁊%\xb9\x0e9h+\xadٸu6\x89\xfdi\t\x9f\x1c\x82\xf2\x17\x05\xf2\xe4\x8ad\xe4\xb8'k\x80Μ\x89\x98\xb6\n\x06J@\x92\x1d\xe2\xf8j\xe2\xfc^J\xbb\xabE\xbfF\x13?\x87\x80\xfcE\x81<\xb9\"\x19\xee\xdfw\x17\"x\x17\x86œ58g\xceDL[\x13\x93\x8c$;ı\xacD\xfb\xed\xba5\xf2\x92\x11\x90\xbf(\x90'\\\x92\x91\xbf\x9e\xac\x819sZ=\xa6\xf4\x93\x05\xe5ъz\xe6\xae\"\x1e(\xae2.\xd6&\xb9\x0e\xf1\x03U\xad\x1b}|\xb1\xa6W:\a\x81\xbf\xa8\xa8\t\xa7\xe5\xaaل\xafS+\xf0&\\\x92\x91\xaf\x9e\xac\x01:sZ=\xa6{Joi\xd9\xd5L\xd8H\x8a\aʮ\x8c\x8f\xb5I\xaeC\\@o!\xb7\"!\x99\x83\xc0_TԄ\xe3e\xb1\x9a\xf0uj\x05ބL2\xf2֓50gN\xab\xc7=Uu\xeal\xef\xdd\xf6\x95\xd7@q\x95q\xb1<\xc9u\xc8\x0e8Ν\xd3\xc8\xe6\x10;\xbe^\xaf\x85\xb5\xc9;\xc0\xfa;\xb5\x02\x0fB'\x19\xf9\xe8\xc9\x1a\xa43\xa7\xd5\xe36\xf2\x81\xb9O<P\\e\\\xac\x8b$:d\a\xf4\x16ه-\xb29Ď\xaf\xd7kam\xf2\x0e\xb0\xfeN\xad\xc0\x83\xd0IF~z\xb2\x06\xe7\xcci\xf5\x98[P\x15\x0f\x14W\x99x\xf15\xc9\x0eq\x01\xc6ZFo\x9b|\x0e\xb1\xe3\xeb\xf5ZX\x9b\xbc\x03\xac\xbfS+\xf0 Ē\x91W\x9e\xac\x819sZ=\xdee{g\x89\a\x8a\xabl\x97\xd0g+\xc9\x0eq\x01\xcbJ4\xfb\x84m\xe4\x94t\x0e\xb1\xe3땃\xb5\xc9;\xc0\xfa;\xb5\x02\x0fB,\x19y\xe5\xc9\x1a\x9c3\xa7\xd9\xe3\xee\x8aZvֲh\x89\xd7@q\x95q\xb1\x1cIv\x88\v\xf8j\xe2\xbd\xecZI\xed4\xe9\x1c\x04\xe3땃\xb5\xc9;\xc0:]]\x81\x04!\x93\x8c\xfc\xf3d\rܙ\xd3\xea\xf1\x9e\xe2\x99\x1b\xda\x16\x91\xcd\xd4k\xa0\xb8\xf1\xe5bm\x92\xeb\x90#\xa0m\xdc\xdc\x17[\xeb\x8aޔ\xceA\xe4/*j\xc2њՄ\xeb\xc5\x022\x84K2\xf2Г5hgN\xae\xc7\x1f\xdfw\xed\x84\x1amM\xc4c\xa0\xb8\xf1\xb5cm\x92\xeb\x903\xe0Pݸk\xe6\x1ff[R9\x88\xfdE\x05M8Z\xb3\x9ap%\td\b\x97d\xa4\x81\xd4,L=\b\xcc\xff҇\xa4<\xb3\xd2\xd2\xe3\xfe\xa5\xbf\xc6\x17\b\xc8{\xc9H\xcd\xc2TLp\xfe\x97>$%\x19\xe9\xe8q\xff\xd2o\xe3\v\x04@2\xc2Lr\x92\x01@\n@2BL&\x9d9A\xbe\x02\xc9\b1\x99t\xe6\x04\xf9\n$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$#\r\x0e\xa5Y\xe9\x19\x1a|7\x93$+G\a$L\xaeIF6{\xb2R\xfa\x8f\xa6kJ\xea\x13\xf8RH\x06\x8cX\xe3\x11l:pT\r7\xb9\"\x19!\xf0dU\xa9\xad\xd8\xf0P\xc9i\xd13N2`\xc4\x1a\x8f\xa0Ӂ\xa3j\x98\xc9\x15\xc9\b\x81'\xabzHN\xd6\xd1>\xf7\xaf\xdc\nɄ\x11\xab\x00sH\x82N\a\x8e\xaa!&W$#\x04\x9e\xac\x94\x1e%;bw\nɄ\x11\xab\x00sH\x82N\a\x8e\xaa!&\\\x92\x11fO\xd6ޫ\xf4$\x1fs\xc5r\xae\xa3i7b\xf5jت\x97\x87\x1b\x92\x80\xd3\x11:\xaa\x82\x90\x10.\xc9\b\xb5'\xeb\a\xed[Is;\xfb\xe5sG,\xe7:\x9av#V\x8f\x86\xedzy\xb8!\t8\x1d\xa1\xa3*\b\t!\x93\x8cP{\xb2\xf2'&V,WC?\x18\xb1\x8a\x1b\xe6\xeb屆$\xe0tģ\x03\xc2A\xe8$#̞\xac\xbcd\x98\xb1\\\r\xfd`\xc4*l\xd8Q\xaf\r7$\x01\xa7\xe3\xe5X\v\xc2@\xe8$#\xbc\x9e\xacN\xc90c\xb9\x1a\xfa\xc1\x88Uذ\xa3^\x1bnH\x02NG<: \x1c\x84X2\xc2\xe6\xc9\xea\x94\f3\x96\xab\xa1\x1f\x8cX\x85\r;\xea將$\xe0tģ\x03\xc2A\x88%#l\x9e\xacN\xc90c\xb9\x1a\xfa\xc1\x88U\xdc0_\xaf\x03sH\x82NG8: \x1c\x84L2\xc2\xecɪ_1y\xa7\xcfe\t\xca\xf5\"\xedF\xac\x1e\r\xf3\xf5\n\t:\x1d\x91\xa3*\b\tᒌ0{\xb2\xf6\x96i\x01EGܱ\\/\xd2m\xc4\xea\xd50W\xaf\x88\xa0\xd3\x11;\xaa\x82p\x10.\xc9H\x03iq(M\xabghR\x16i\tt3\xa9z\x93)\x96\xd6\xd1\x01\xe9&\xef%#\x1d\x0e\xa5\xe9\xf5\f\x95\x9f\xa3\f\xffn&W\xaf|\xb1\xf4\x8e\x0eH7\x90\x8c\xd0!=G\x13$\xc9z\x93,\x06\xc2\n$#l\xa4ˈ5\xc9z\x93,\x06B\v$#l\xa4ˈ5\xc9z\x93,\x06B\v$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$#\rf\xa5\xd9\xee:\x1a|\x8f\x03%ۇ/\xcf\xc95ɀ'\xab?\xa9سr\xa4-I\x98\xb6f5\xb9\"\x19\xf0dM\x98\x94\xecY9Ҙ$L[\xb3\x98\\\x91\fx\xb2&J\x92\xf6\xac\x1cA:\xb5z\x00\xd3\xd6\xec%W$\x03\x9e\xac\x89\x92\xa4=+G\x90N\xad\x1e\xc0\xb45{\t\x97d\xe4\xbb'\xab\xe5q\xba\x90\x14\xadk\xaa\x9c\\\xaf}\xeb\xdc\xea\xe6B\x12\xddhuފu\xd4\xe0k\xcf*n\xc2\xc6ߩ5\x80$aښńK2\xf2ܓ\xd5\xf68\xfdhk\x11\x99\xba\xaay\xea8\xa6nV7\xd9ފ\xe6\x9fMd\x9d\xb7c\x1dM\xf8ٳz4a\xe3\xeb\xd4\x1aD\x920m\xcdbB&\x19\xf9\xed\xc9\xca{\x9cF\xa7\xa9\x85OW\xd58\xbaI\xa3e\xea\x87w\x03\xeb<\x17\xebH\xd2ǞU܄\x03\x1f\xa7\xd6 \x92\x84ik\x16\x13:\xc9\xc8cOV\x87ǩ\xbe\x88\xb9\x9e|\xc5uS\xdd\xfb\x105:\xcf\xc5:\x92\x8co\xcf\xea\xd1\x04\x87\x9fSk I´5\x8b\t\x9dd\xe4\xb1'\xab\xc3\xe3T_\xe5m'\a\xb8n\xf2\x9d\xe7b\x1dIƷg\xf5h\x82\xc3ϩ5\x90$aښńX2\xf2Γ\xd5\xe1q\x1a]\xc2Jo$g\xb8n\xf2\x9d\xe7b\x1dIƷg\xf5h\x82\xc7ǩ5\x90$aښńX2\xf2ϓ\x95\xf78\x8d^\xa3Ω\xee\x1bj\x1d\xdd\xe4:\xcf\xc5:\x92\xf4\xb1g\x157\xe1$\xbeSk I´5{\t\x99d\xe4\xb7'+\xefq\x1a%\xb7l\xdb\\]ƒ\xb4\xba\xc9w\x9e\x8f\xe5\a\xcaǞգ\t!iL\x12\xa6\xad\xd9K\xb8$#\xcf=Yy\x8f\xd3\xe8\xe3\x8d\x13+\x1b>c\x9bV7\xf9\xce;\xfcP\xb9&|\xecY=\x9a\x10\x91\xc6$aښńK2\xd2@\x02f\xa5\xf2\xf4\x83\xebh\x9c\x9b\\}H\xb8\xc7\xc97a\x92d\r\xfd0| i\xf2^2\x120+\x95\xa6?\\G\x93\x9c\x8d\x8cD{\x9cB\x13\x06\xc9\xd5\xd0\x1f\xc3\a\x92\x06\x92\x11R\x92\x9b\x8dR\xa4\xdeD\xea5\x80\xac\x03\x92\x11JNjk\x88~Q)\x91z\x13\xa9\xd7\x00\xb2\x10HF(\xd1\xd6\x10\x8f\xd3t\x92z\x13\xa9\xd7\x00\xb2\x10H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02HF\x1a\x1cJ\xb3\xc7TT\xeb[\xf6\xa4\x03r\x80\\\x93\x8c\xec\xf6d\x8dK\x1a<N\xf5\xbe\xf9\xa5\x93\x86\x86A\xee\x92+\x92\x11\x0eOV!f\xea\x81x\x9c\xee\xe1\u007f\xcd\xca\xea[\xfct\x82o\x18\xe40\xb9\"\x19\xa1\xf0d\x15c\xa5\x1e\x84ǩ=\x0e\x8e\xbe\x89\xd3\t\xd2\\\x95o\x18\xe42\xb9\"\x19\xa1\xf0d\x15c\xa5\x1e\x84\xc7)\xff\x93\xc5\\\xdf\xc4\xe9\x04i\xae\xca7\fr\x99pIF\x98=Y\xd5\x0f\xf5\x86\xab\xae}\xfc\xf1\xabJ\xb7y\xa4\xee\xe1qڽtF\xe9\x1do_\xdb\xc6\xd6i^\xb6VdD&\xa8\x8eq\xb0\xfbƈM\xc7\xdf\\5نAN\x13.\xc9\b\xb5'k\xef̊\xf5\xcd\xc5%\x9b\xeb\xd6x\xa4.\xf68=}C\xf9\x9a\xb6\x85\x84l\xd0\xd7i\xcc\x15\x19\x91\t\xaac\x1c쾉\xd3\xf15WM\xbaa\x90ӄL2\xc2\xecɺ\x8d\x1cdf\x83\x87b\x8a\xd9'&\f\xb7\xc7ic\x19so[\xa2\xce\\\xde\x01\xc4\xc3\x04\x95??\xe0\xfa&\xf68\xf51WM\xbaa\x90ӄN2\xc2\xebɺ\xacL\xfd\xe7cm\x89D\x9c\xba\xd0\xe3\xb4o\x9c\xb66\xf3\x91k\xe6z\x98\xa0\xf23\x97s_\x15\xa5\xe3g\xae\x9a|\xc3 \xa7\t\x9dd\x84דu\xcd\xe8/\xd81χ1\xc5\x1c˟n\x8fӿ\xe9˰ݮ\x99\xeba\x82\xca\xcf\\\xce}U\x94\x8e\x9f\xb9j\xf2\r\x83\x9c&Ē\x116Oֿ\x16\xd6\xfd\xf5`\xf5ܾ\x98bf\xeaB\x8fӾ\x12-\xc3\xc3\xf6\xccՎ\x95<LP\xb9q\xe0\xddW\x85\x1e\xa7>\xe6\xaa\xc97\fr\x9a\x10KF\xd8<Y\x0f\x90k\b\xa9=\x19S\xccJ]\xecq\xba\xa0\\\x9d\x9d}\r\xda\xcc\x1d\xb7Tݬ\x89:k\xe0MP\xb9qp\xf4M\xecq\x1a\xdf\\5\xf9\x86A.\x132\xc9\b\xb3'\xeb\x81\xe2];\xdbO\xba\x8aQ;u\x0f\x8f\xd3\xcf*\xaaַ\xce/\xd6f\xee܊\x96U5D\xeb\x85\xd8\x04ծ\x8c:\xfa\x16\xdf\xe34\xe8\x86A.\x13.\xc9\b\xb3'+}3\xca\x02\xa2w|\xc8\x17\xa3v\xea\x1e\x1e\xa7\xf4\x8bƪ\x92\xda\x03\xda\xcc=Z[2\xa1\xeei\xadob\x13T\xab2\r\xabo\xf1=N\x83o\x18\xe40ᒌ4\x90\xb0C\xa9\f\"S\xd1S\xa5M\xa7Ν;\xbd\xff\xdeɧEE|\xd0W!%1\xfb\x96\x8a\xc7iR\r\x83\x1c&\xef%#a\x87R\t\x84\xa6\xa2\xad\xfa\xfd\v\xb4\xaf\xbc-\xe69\u007f\x92\x9b\xb9z\xdfR\xf28M\xaea\x90\xbb@2\xfa\x8b\x03\x85\xfa\x17:>,\xfc\xc0'RD\xc6fn\xc6\x1a\x06Y\n$\xa3\xbf\xe8k,iڶg[SIS\x12\x1f\xf9G\xdb\xc8co%Q.e2\xd60\xc8V \x19\xfdFߎ\xba\xcaheݎd&\xe0\\BH\xd1Q\xbf\xa84\x90\xb1\x86A\xb6\x02\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\xc8iOV\x0eس\x82@\xc85ɀ'\xab\a\xb0g\x05\xc1\x90+\x92\x01O\xd6\xf8\xf4\xa7=+\xc8irE2\xe0\xc9\x1a\x97~\xb5g\x059M\xaeH\x06<Y\xe3ү\xf6\xac \xa7\t\x97d\xe4\xa5'\xab\xe5|\xba\x90\x14\xadk\xaa\x9c\\\xaf}\x17\xdd\xea\xdbB\x12\xddh\xf5؊uԐ\xba=k\x009\x80\x1c!\\\x92\x91\x8f\x9e\xac\xb6\xf3\xe9G[\x8b\xc8\xd4U\xcdS\xc71I\xb3\xfa\xc6\xf6V4\xffl\"\xeb\xb1\x1d\xcbא\xba=k\x109\x80\x1c!d\x92\x91\x87\x9e\xac\xbc\xf3it\x9aZ\xfb\xe9\xaa\x1aG\xdfh\xb4L\xfdto`=\xe6b\x1dM\xa4j\xcf\x1aD\x0e G\b\x9dd\xe4\x9b'\xab\xc3\xf9T_\xc4\\O\xbe\xe2\xfa\xa6\xee}\x88\x1a=\xe6b\x1dM\xa4h\xcf\x1aH\x0e G\b\x9dd\xe4\x9b'\xab\xc3\xf9T_\xdam'\a\xb8\xbe\xf1=\xe6b\x1dM\xa4h\xcf\x1aH\x0e G\b\xb1d\xe4\x87'\xab\xc3\xf94\xba\x84\x15\xd8H\xcep}\xe3{\xcc\xc5:\x9aHў5\x90\x1c@\x8e\x10b\xc9\xc8\x13OV\xde\xf94z\x8d:ۻo\xa8u\xf4\x8d\xeb1\x17\xebh\"U{\xd6@r\x00\xb9A\xc8$#\x0f=Yy\xe7\xd3(\xb9e\xdb\xe6\xea2\x96\x99\xd57\xbe\xc7|,\xdfD\xaa\xf6\xac\x81\xe4\x00r\x83pIF>z\xb2\xf2Χ\xd1\xc7\x1b'V6|\xc66\xad\xbe\xf1=v\xb8\xa4rM\xa4j\xcf\x1aL\x0e '\b\x97d\xa4\x81\x90x\xb2\xeaĹ\xb3Շ \xecYu\x92\xcf\x01\xe4\x04y/\x19!\xf1d\xd5Ia\xba\x06`Ϫ\x93B\x0e \x17\x80d\xf4\x17\xa9y\xb2\xead\xc3t͆\x1c@\x06\x81d\xf4\x17)y\xb2j\x9c\xd4\x16\x19\xfd\xa2\xd2K6\xe4\x002\n$\xa3\xdfHœUC[d\xe4n\xe3\xcc\x04ِ\x03\xc8(\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\x8c\xbc\xf2d\r1\xf1\x065\xec}\v\x15\xb9&\x19!\xf6d\xd5ГL\x835jl7\x9dx\x8cN,)\x8f\x0e\xa5\x87\xeaJ+\x1a\xf6T\xc4L\xf3\xb89\xc4\x19T\xbf\xbe\t\xd9U\xb1\xc3/$U\xfa\xa1\x89\xd4\xf0\x9d-\xadE\xc6Ϸ\x16\xd9z\x9d+\x92\x11bOV\az\x92\x81X\xa3\xee\xe1\u007f}+\xb6\x9b.ģ\x13K\x00\xa3\xd3VZ\xb3q\xeblB\x8e\xb8\x9f\xf0\xc9\xc1kP}\xfb&dGi\xac7C\xc0\xa4\xdcĞx?\xa0\x96\x02\tϖ\x16\xd2\u07be\x9e\xacko\x1f\xddb=\x93+\x92\x11bOV\x17Z\x92AX\xa3\xdaC\xe2\xe8\xa6'\x82\xd1\x11\x90\xfa\xe8|5q~/\xa5\xddձ\x92ᗃxP\x13\xe9\x9b\b\x89\x03\x13\xf3\xad!\x8bD\x13B\xf8\x97P\x06\xbf|\x13\x9e-\xeb\xa2\xec\x17\xe9ߦ\xb4\xc4V\xeb\\\x91\x8c\x10{\xb2\xba\xb0%#EkT\xfe\u05cb\xb9nz\x92\x98d\xa4>:\xcbJ\xb4_\x01\\#/\x19\xe2AM\xa4o)b\xbe5\xfa\x1b\xfe%\x94\xc1/߄gK\xef'\x86d|\xd2k\xed\x0f\x97d\x84ٓ\xd5\x11`\x9b\x95\x9e\xb9\xaf2ZU\u007fP\v\xb1\x93\xf4\xb0F\xed^:\xa3\U0010edefmc'\xa1/[\xa7\xfe\"\xefTǐ\U0001eb1f,(\x8fVԳ\xdf9\x17\x8f\x0eo\xa3j\xc7ڤ>:\xd5?\xd2*\xfabM\xaft\x0e\x02\xa3[\xaeo\"3X\x8f\xccN\x97\x10Rh\x9a\xb8qC\"\xf2\x90\xe5\xde\x1a\xe9j\u0082\u007f\x83s/!\xdb|Z\xaf\xd7i\x8a\x1b7߀f\xcb>\xdd\x04\xc7\xca!\\\x92\x11fOVG\x80mV\xba\x834\xed\xd9V_\xb8\x8f:\x92\x14[\xa3\x9e\xbe\xa1|M\xdbBB6\xe8'\xa1橿\xc8;\xd51$\x9c'\xeb\x9e\xd2[Zv5\x136|\xe2\xd1\xe1lT\xb9X\x9b\x94G\xa7\xb7\x90[\x91\x90\xcc!\xd6N\x96\xeb\x9b\xd0\f\xd6+\xb3\x03\xed\xed\xc5\xc6\a,ׄ\xd0C\x96{k\xa4\xab\t\x1b\xee\rν\x84=oV5\xb1z'\xbe\xd1\xed0\xc5\xf5\xc97\x98\xd9bH\x86\x95C\xc8$#̞\xac\\\x00W\xacg\x9b\xfa\xee껉\xfd`:\x97\xa4\xd8\x1a\xb5\xb1\x8c}N-Q%\x837\x0e\xf1\xf0N\xe5\x8fj\xadn\xf6Tթ\xb3\xbdw\xdbW^\xa3\xc3gf\xc7\xf2\xa4::ǹs\x1a\xd9\x1cD\x83j\xf5\xcd\xcb\fV\x94\x19\xa3D\x9f\xcf\\\x13^\x1e\xb2\xd6[#}MXpop\xfe%lf\xc7\x04\r\xday\x99m\x8a\xeb\x9bo \xb3e\x9fi\xb5g\xe4\x10:\xc9\b\xaf'+\x17\xc0\x17\xfbb}\xdd\r\x13\xc9l\xeaHRh\x8d\xda7N{\a~\xe4\x92\f\x0f\xefT^2\xacn\xb6\x11\xeb\x87Gţ\xc3U\xc6źHitz\x8b\xec\xc3\x16\xd9\x1cD\x83j\xf5\xcd\xcb\fV\x94\x19Ø\xcf\\\x13b\x0fY\ueb51\xae&8\xb878\xff\x12\xfem\xf4a\xda;q\x17۴Mq}\xf3\rd\xb6X\x92a\xe4\x10:\xc9\b\xaf'+\x17\xc0\x15\xdbWQ\xb5\xb4\xb5\xbdv6u$)\xb4F\xfd\x9b\xfe\xf9\xdc\xed\x92\f\x0f\xefT^2\xacnr\v\xaa\xe2\xd1\xe1*\x13/\xbe\xa6>:\xc6ZFo\x9b|\x0e\xa2A\xb5\xfdf=\xcc`E\x991\x8c\xf9\xcc5!\xf6\x90\xe5\xde\x1a\xe9j\x82\x83{\x83;^º\xc7i[\x99\ue8edU\xcaLq}\xf3\rd\xb6X\x92a\xe4\x10b\xc9\b\x9b'+\x17\xc0\x15\x9bQ\xc3\xdeN\vT\xc9\xe0\x93\x14Z\xa3\xf6\xe9\xef\xc0ödh\x1f\x04\x1eީܐ\xd8\xdd\xdce[\xa5\x89G\x87\xabl\x97\xd0V-\xf5\xd1YV\xa2\x99@l#\xa7\xa4s\x10\r\xaa\xd57/3XQf\fc>sMxx\xc8\xdao\x8d\xb45a\x13+\x19\xfaK\xb8\xa3\xbc\xf7\xa1\x1fj\x11\xb6)\xaeo\xbe\x81\xcc\x16[2\xf4\x1cB,\x19a\xf3d\xe5\x02\xb8bU\xec\xdd\xd6w\xb3*\x19|\x92bk\xd4\x05\xe5\xea\v\xdeנIƸ\x85CSm\x00\x00\x11\xbeIDAT\xa5\xeafM\xd4Y\x19\xef\x9d\xca\r\x89\xdd\xcd\xee\x8aZ\xf6I\xb5h\x89\xd7\xe8p\x95q\xb1\x1c\xa9\x8f\xceW\x13\xefe\xd7Jj\xa7I\xe7 \xb6\x935\xfb\xe6e\x06+ʌa\xccg\xae\tO\x0fY\xf3\xad\x11t\x13ǛcT\xd9!\x19\xdcK\xd8[\xbec\xb2v^\u0099\xe2\xfa\xe6\x1b\xc8l\xb1%C\xcf!d\x92\x11bOVG\x00owz\xdf\xfaU\xb7\x92\xf2\x96w\xf8$\xc5֨\x9fUT\xado\x9d_\xacI\xc6܊\x96U5D\xeb\x90\xd8;\xd5\xf6z\xa5\\7\xf7\x14\xcf\xdcж\x88l\xa6^\xa3\xc3\r*\x17k\x13\xc0贍\x9b\xfbbk]ћ\xd29\x88\xedd;\t\xcd`=2\xeb}\xbb\xbd\xbd\xb8\xb1\xfd\x8d3\xce&\xfc<d\x83n\xa2\x9e\x94\xba\xac\xf3\x1cop\xc7K\xb8\xec\x862\xfd\xf2=g\x8a\xeb\x93o \xb3\xe5\xfd\xf5d\x9d9\xecZ\x0eᒌ0{\xb2:\x03\xac\xd4\xfb\xd6TG+\x1ex\xa1:Z\xcb%\xe9a\x8dJ\xbfh\xac*\xa9=\xa0I\xc6\xd1ڒ\tuOk\xdd\x14{\xa7ZC\xa2au\xf3\xe3\xfb\xae\x9dP\xa3\xad\x89x\x8c\x0e7\xa8v\xacM\x10\xa3s\xa8n\xdc5\xf3\x0f\xb3-\xa9\x1c\xbc\xecd\x8d\xbe\t\xcd`=2ۯ\xef\xd6F\x92o\xc2\xc7C6\xe8&6\x97\x12\xf3\x05\xd2q\xbd\xc1\xf9\x97\xf0cҤop\xa6\xb8\xf1\xf3\rd\xb6\xf4\xb0gK\xce\xfc\xff\xed\x9d\xcdk\x1cG\x1a\x87\xff\r\x95\xc1\x8c\x91\x05\x8bE\x10h\x1c\x82\x1d\x88\x0f\xc6\x106d/\xc29\x8cN\xc2$\x81\b\x1d,ؕ!\x98\x18\x82ذ>\fYC\xf0\xc5Ɔ\x80C \xe8\xe0\x93M\x0e\x02\x81\x18\x88\xcd\x06\a\x13\xb3X\x84\xb0\x868Ƒ\x8dM\x1c!\xa2\xa1v\xfac\xba\xde\xeayk\xaa\xab\xa7{F\xd5\xf3{ \xc90\xe9\xa9z\xab\xde\xd6o4\x1f\xea'\x1a1\xac\xc1\xaf\xc8(\x81\xa19Y\v#z\xfbӑR\x969\\\x8c\x9b\xea\xf1\xdan\x89̂ޝZ\xfc\x17G#\xd4Յ5\x8c}d\f\xcd\xc9Z\x18\xb9\"\xa3\x8ce\x0e\x97>\x9b\xea\xeb\xda\xda_M\xaf؎IX\x9b\x89\x03s\x84\x91\x11ր\xc8\xf0\x8e|\x91\x01\xf6\x1fOg\xcf\xefَ\x89hn\xb6\x1b\x17\xe3ۣ\x8a\x8cn\r\x88\f\xdfx\xb4.>\xb9[\xe2/1`\xff\xb1+\xde=W\x8f^\u008cL\x8a\x9bԀ\xc8\xf0\x8d\xd3B\x88\x83\x8flG\x81Jќj\xfc\x1c\xdd\x1a\x9d\x14\xb7[\x03\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\xa3\x04\xa1\xe7\xbet\xb2\x0eN\xf1\x1b5\\`u-\x84\xaaE\x86\xd52\xd9C坬\xc1`\x91\\C\xbfX\x8e\x8e\xdd\xc9j3\x9f\xdaG\x88\x19x\u007fau\x1d%U\x89\x8c̖\xc94\xd5w\xb2\x06\x83=\x93\xcf.\x89\xaf\xfe\xe8s\xb4\xd5\xc9j5\x9fZG\x88)`\u007fau\xcdJ\tVתDFf\xcbd\x8aqp\xb2F\x17\x12\xdd\x14\xe9\x8b\x18\xa6`v\x87\x90\xc5|\xda\u007f\x84.\x83\xef/\xac\xae\x99)\xc1\xeaZ\x95\xc8\xc8l\x99L1\x0eN\xd6B\"#\x8b\xf94[d\f\xbe\xbf\xb0\xbaf\xa6\x04\xab\xab_\x91Q\x90eR1\x16NV\x1a\x19\xb6\x89M\v\x82\xd5u\x00\xe5j\xb5\xac\xae~EFA\x96I\xc5X8Y\x83\xc1vw\xd7\xc3ȰMlZ\x10\xac\xae\x03(W\xabeu\xf5,2\x8a\xb1L*\xc6\xc2ɺ\x15?\xd9le\x98ش X]\aR\xaeV\xc9\xea\xea]d\x14a\x99T\x8c\x85\x93\xb53ؽ{\xf7.\a\x91a\x9dش X]C\xf2)W\xabeu\xf5.2\x8a\xb0L*\xc6\xc2\xc9J\xde˰NlZ\x10\xac\xae!\xf9\x94\xabղ\xbaz\x1c\x19\xf9-\x93\x8a\xb1p\xb2\x92ȰNlZ\x10\xac\xae\x11\xf9\x94\xab\x95\xb2\xbaz\x1c\x19\xf9-\x93\x84qp\xb2\x92ȰNl\\\x10\xac\xae!N\xcaUB\x85\xac\xae\x9eEF!\x96I\xca\x188Y\xb5o\u007f\xda&6.\bV\xd7\x10'\xe5*C\xd1S\x8c\xc0\xea\xeaWd\x14b\x99ԩ\xbe\x93U\xfd\x8d\xc9u\xeb\xc4ҸbX]#\\\x94\xab\fEO1\x02\xab\xab_\x91Q\x02\xa5\b=\xf7\x9f\x93upJ٨\xe1\x02\xabktc0\xdf\xda\xd8GF\x19B\xcf\xfd\xe8d\x1d\x9c\x126j\xb8\xc0\xea\x1a\a&\"c\xcc\x18Ud\x80\xfd\xc7(\xac\xae\x88\f߀\x93\x15\xb8S\xa0\xd5\x15\x91\xe1\x1bp\xb2\x82\x1c\x14guEd\x00\x00\x1c@d\x00\x00\x1c@d\x00\x00\x1c@d\x00\x00\x1c@d\x00\x00\x1c@d\x00\x00\x1c@d\x00\x00\x1c@d\x80!\xd2nG\xff\x00\u007fAd\x80a\xb1\xbd\\\x17\xefK\xf9\x91\x98]N_\x83\x00\xf8\x03\"\xa3\x04\x1d\xe7(\x9c\xaců\xa2h\xda'O^\xdfx\xdcI\x8e֍\x933\xa6k\xea\x03\x96Q\x9cQ&\xaa\x16\x19\x9e;Ys;8sIE\t9'~\xb9rtr!\xe3\xc4\xd1e\x83B6Ń>\a\x96H\xcee\xf6\xa55!N\xb7\xe5M!&6l\x87R\xfa\x9c\xa91\xcbB\x88\xc3џ\x06\xe4?\xa3\x8a\xa7*\x91Q\x11'+\xeb\xe0\xcc\xe0\xd5\xcc'\x15%䜸Q\xbfvv2\xe3\x05\x1b~\x10\xdfuo\xdeK.\xd0[\x16\x86\xd2\av\x9c2\xecn\x88ɖܹ)6\x9c~u\xeas\xa6\xc6<i\xb5\xae&\x1b\x95\xf7\x8c*\x9e\xaaDFU\x9c\xac\xdc3\xb6ݫ\x99W*J\xc85\xf1\xef\xe2\x8al\xf7^\u007f\x97\x87\xe4D\xf9\x91a*=\xe3oDN\xec\x88@\x0f\xf2Xd݈.\xb6Ȑ\xdaF\xe5=\xa3\n\xa7*\x91Q\x1d'k/v\xaffIRQ\xebď\x84\xc3\xef\xf9C\x8d\fk\xe9\x05\xb2#6\xa6vK\x8f\x8c\"Ϩ\x81\xf0+2*\xe8d\x95/\x96f\u07b8pafJwp\xb2rU\x9b0U\xbf\xb7k\xf1$\xf5\xa6\x8b\x8cQ\x13\x9f\x13\xb5\xeb\xf1\xf6Y'ޛ\x89\x0e\xf8D\xea\x82W\x93>tS|ߝ\xf0\x81ؔFH\rj\\C\xe75\xb8=\xa3+f\x97I\x1b\xc0\xa2\xe9o9\xa3j'2\x1e\xff\xedf\x14\x19N\xf5\xd6>\xfeG\xa2FUg*\xb9\xa9g+\xa3\x93\xe5ڢ\x9fg\xdd\xc1\f\x9dσ_\x91QA'\xebީ\xfa\xd5\xe6\xa1\xc9/\xe7/S\a'/W\xb5\tS\xb5{\x13\x8b'\xa97]d\x97d\xe2\xc0\xd7Yo~q\xa4\xb3}\xf6\x89\xff\xdb\xfaF4[\xc1\xa5\xdc%\x11\xbc\xf2\xfa\xd0?\x9fo\xceM'\xa7\xfc\xde\xccܝ\xdfL\xaf\x11H\rd\\\xbe\xf3\x14vϴ\x15s\xcb\xd4\x1a\xc0A\xf5\xb7\xacQ5\x88\x8c+\vQd\xb8\xd4\x1b^\xe8\xfb\x9b\xbf\x86jTu\xa6қzd0:Y\xae-ڊ\x93\xc1L\x9dρg\x91Q='\xebZ\xf0\xe1\xc1U\xd1\xfd\xa2B\xec\xad\xe0\xe5\xaaVa*\xb9\x97\xbaH\xa9\xe6S+\x92\x10O,kӝ\xa7ޥzt\xacm\xe2\xe4\x85\t\x11\xbc\xf2\xfa\xd03\x9d'}\xf2\"f]\x90k\x97\xf7\xa0j \xe3\x9a:\x9f\xc0\xefYjŽ\xcbL5\x80A\x99qx\xa3j'2\x9e\x1fz\x1eF\x86K\xbd\xb2v\xb2sR\ue798\xd3\xceTrS\xea\x91\xd1{F\x99ڒ\xdc\xd4\x063u\xde\x15\xef\"\xa3jN\xd6\xd5i\x19\\.\xbe\xfb\xc6I|J\xf3rU\xab0\x95\xdcK]\xa4T\xf3\xa9\x15IH~\x96\xce\xca\xe4M\x1f\xeb\xc4꽌D\xf0jЇ\xfe\xba~\xed\xe4kɋ\xfd\x9d\xfa\x9bW6\xcc\x17\x86\"5\xa8qM\x9dO\xe0\xf7,\xb5\xe2\xdee\xa6\x1a\xc0\xa0\"\x837\xaav\"C.\\\x89\xde\xcbp\xa8W\xd6>\v\xfe}M\xfcN\xceTzS\xa6##}F\x99ڒ\xdc\xd4\x063u\xde\x15\xef\"\xa3\xd7\x11\x199-}u\xb2^\x9ex\x11\xfc\x98=\x8c\xffO\xf7\x94f\xe5\xaaVa*\xb9\x97\xbaH\xa9\xe6S+\x92\x90\xfc,%ۗa\xe2$2\x94\xe0լ\x0fm)\xe3\xc6=\xd1\xf7+\f\xaa\x062\xae\xa9\xf3\nv\xcfR+\xee]f\xaa\x01\fdKX\xa3j\x10\x197\xdf\t#é^\xa5FUg*\xbd)\xf5\xc8\xe8=\xa3LmInj\x83\x99:\xef\x8aǑQ\r'\xeb\xaf\a\xe6\u007f}p\xe2t\xf7en|J\xf3rU\xab0\x95ܫ\xb9H\x89\xe6S+\x92`\x8c\x8c~\x13'\x91\xa1\x04\xaff}h\xf6OLT\rd\\S\xe7\x13\xf8=K\xad\xb8w\x99\xa9\x060(\xfd-oT\r\"cwj#\x88\f\x97zc5\xea\x97\xe2\x0fr\xa6қRߨ\xde3\xcaԖ\xe4\xa66\x98\xa9\xf3\xaex\x1c\x19\xd5p\xb2\xde\x17G\x85h<\xed\x1e\x12\x9fҼ\\\xd5*L%\xf7j.R\xa2\xf94}\xfa\xc8E\x86u\xe2$2\x88\xe0ը\x0f\xe5#\x83\x91\x8a\x92\x1aȸ\xa6\xce'\xf0{\x96Zq\xef2\xf5\x06p\xe5(\xfd-oT\r\"C\x9e]\n\"å^Y{#x\xd3\xe7TC;S\xc9M\xa9m\x14sF\x99ڒ\xdc\xd4\x06+\xeasg\xcf\"\xa3zN\xd6\xfb\x876\xbem=\r\a#\x0eNV\xaej\x15\xa6j\xf7R\x17i\xb7\xde\xd4ú\xa8\x89\xb5\xed\xb3M\x1c}b\x12^ߞ\b^\x8d\xfa\xd0\xfb\xea\x17\xeb\xef\xd5筽RQZ\x83\x1a\xd7\xd8\xf9\x04v\xcfh\xbd\xfc2I\x03\xd8r\xa8\xfe\x965\xaa\xeen\x88\x9b;\xb25\x19D\x86K\xbd\xb2&\xe6\xefn̅jTu\xa6\x92\x9b\xbf\x05\xdf\xfe\xbc\xd2jEoAp:Y\xae-Z\x8f\x93\xc1\f\x9dσ_\x91QA'\xeb\x9dZpo\xed\xbd\x87\x9a\x83\x93\x95\xab\x1ag\xeb\xaeB\xbf\x97\xfaP\xe3z\xd3\x0f\x8bQ\x13k\xdbg\x99xo:\xbcy0\xf8\x14\x96\n^M\xfa\xd0\xe7\a?|\xb0\xddi\xc6\xde\xf6\x8f\x1fԶ\xbbs\xf7HE\xb5\x1a\x92qO\x1b;\x9f\xc0\xee\x19]1\xbfL\xd2\x00ɕC\xf5\xb7\xacQus\"\xf8\x86N{\xaeޖN\xf5\xcaS\xcd\x0f\xff\x12\xabQə\xaan\x9e\x8d\xca\x15\x1f\x05w\xf3:Y\xa6-Z\x8f\x93\xc1\f\x9dσ_\x91Q\x02\xa5\xe88\xb3;Y\x9fM\xad<\xfb\xf3\xcfW?\xbc\xffZƿ\xd4\xe0)e\x15Es\xebT\xf8\xf3sF\x88\xe3\xe4\xf3\t\a\xa9h\x19\xa4\x1b0\xe2rLd?\xa3Jg\xec#\xa3\f\x1d\xa7\x83\x93\xf5V\xf45\x02ٞ]\xef\u007f\xa0\x85\x12VQ\x02\xcf\x1et\x9eS\xb7\xef\xff\xa6\xeeq\x92\x8a\x96\x81ހ\x91\x97c\xc0\xe1\x8c*\x1dD\xc6h\xb9\u007f \xfa\x85\xf8\xe1\x01\xf55\x8aq\"\xbbT\xb4$\xf4\x06\x8c\xbc\x1c\x0f@d\x8c\x96\xf6\xf2\xe4\xca\xda\xe6\xda\xca\xe4ʾy\x16\x19/\xd0\x00W\x10\x19#\xa6}{\xfe\xf5\xda\xeb\xf3\xb7q\u008e\b4\xc0\x11D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x02u\xe9\"2\x00\x00\xfdH\xb9t\x11\x19%\xd8L\xf7\x93A\x93\xa3\xf8\x15\x83\xea\x92v\xe9V-2<w\xb2\xc6E\xde\b\xaem0;\xff\xa3\xed\xe8|8\xf8[՞\x95a3\xe5i\x8aZ\x90\xb8\xdf\x1e\x16Mۡ\xa5Qn\x032B\x9c\xacFr\xb6e\x10\x97nU\"\xa3\"Nָ\xc8?\xbe\x12\xffnݘ\x9b\xe8#\bʏ\x8b\xbfU\xedY\x196S\x9e\x17\x8b\x87\x83\v\xf54&\x17S\xd7ʴ+b\v\xa3\x90\x06\fZ\xaf\xe6d50\x02\x97nU\"\xa3*Nָȭ \xd9ۧOX\x8e̓\xa3\xbf5ٳ\x8c\xcfI\x01ݝ\xcc\xc9\xea\xc2\xe1W\xf2\xf7Ʌt\x9dVEl\x01tK/\xa2\x01\x05\xd4k7Qrm\xb1N<\x90K\xb7*\x91Q\x1d'\xab\x8a\fM,P\x18\x8e\xfeVfϬ<\xecw\x89\u007f;\xab\x8b\x8d5\xf9\xf5\xfcb:2\x8a\xba\xdem?\xba\xa5\x17р\x02\xea\xb5G\x06\x87u\xe2\x81\\\xba~E\x86\xcfNV^\xe8\xa9\xd9AU\x91\xd1\x19\xbb\xf4\xba\xa4ǒ\x11Ή\x83WVz\x84\x9e\xda`\xac>\x94\xacإ\x1c\x17\x9b)\xd9Iݒ\xfaY\xb4g\xda\b\xc4ߪX]\xbc\xfa\xbe\\\xb8։\f\xe2C\xd5z\x9cԻ\xd5\xd9\xf5\x85\xf61!\xa6\rW\xc61\x99pw>=9\xf5\xde\u007f\xdeX\xd7\x0e&\xa5\x1b\x1a\x90<L3\xb5r\x1d\xd2\xea\xe5\xe0+\xd3\x1a\x9b\xfc\xb8\x92\xed\xa3C\x8cƥ\xebWd\xf8\xecd兞\xd4\x0eJ\x8a\xdc\x12\xdf\xee\xfe\xfc\xa9\xf8\\\xab\x81\x8c\x10<\xec\xf8\xe7\xcd\xe3\xbaГ\x0e\xc6\xebCɊ]\xcaq\xb1\x99\x92\x9dTS\xec\xde9\xb6\x12\xecّ\xefv\xe8\b\xd4ߪX]|2\xf5\xf2\xd0v'2\x88\x0f\x95WĶ\xef6\x0fܕ_O|m\xba\xa6\x99\xc1\x84\xfb\xea\xad\xd9\xcb\xeb\xe7\xc2+3\x13H\xe9|\x03\xd4è\xa9\x95\xed\x90V/\a_\x99\xd6\xd8$2\xc8\xf6ic\x8cĥ\xebYd\xf8\xecd兞\xc4\x0eJ\x8a\xdc\n\x9f\a\x96\xda\xfa\x14\xd4:Z{\xb33ѫc\xbaГ\ff\x98M\xadإ\x9c\x80\xec6\xd3d'i\xbd\xcd\xe0YoiY\x1f\x81\x8ac\x15\xab\x8b\xf2\xed\x959\x19\xbe0a\xe5m\xb4\xde\xf6ٹ\x17\xc7\xfa~>řp\x97\xa7\x83'\xd3\xf3\xa9\xc8 \xa5\xf3\r\xa0\x0fS\x95\x19:d\u007f}\xc0UF\x1a+ɋ\x02\xb2}:\xc3w\xe9z\x17\x19\xfe:Yy\xa1\xa7\xb2\x83\xd2\"\xb7\xc4\x17\xdfߞ\x9b|\xac\x1fK\xad\xa3ћ\x98Wu\xa1'Q\x8d\x1afS+v)' \xab͔\xec$\xad\xf7\xc9\xc4Or\xefȆ>\x02\x15\xc7*:\x91qI\\\xea\x13\x19ڂv\xdf9\xda\xff\xe3BƄ\xdb>\x1c=7\xa7\"\x83\x94\xce6@{\x98\xaa\xccС\f\x91\xc18zIc%\x89\f\xb2}:\xc3w\xe9z\x17\x19\xeb\xbc\xe9\xd2\a'++\xf4T\xf5\xd2\"×ү\x0e\\\x93\xfa\xb1\xc4:\xca\n=\xad\xfaP\xeaou(' \xab͔\xec\xa4fI\x9d\xbf ףw\x1c\xd4\b\xfcۋ\x9d\xe6\xbe\xf8\xf4Y\x9f\xc8\xd0\x1d\xa77\x19\xfb-\x851\xe1>\x89rn'\x15\x19\xa4t\xb6\x01\xda\xc3Te\x86\x0ee\x88\f\xc6\xd1K\x1a+\xe9[\x8fj\xfbt\x86\xef\xd2\xf582|s\xb2\xf2BOU/-2z\xf7\xed\xc8E\xa9\x1dK\xad\xa3\x91\xd0\xf3\xba.\xf4\xa4\xde@~6\xb5b\x97r\x022\xdbL\xd5Nj\x96\xd4۳{g\xff\x9e\x1aa\x831\x80E\xcd\xed\xa0\"\xe3_\xb5\xf0\x0e^\x11\xfb\xb4\xfe\xcf\xe3/\x99Q\x12\x18\x13n;Z\xccO\xe9\x17&\xaat\xb6\x01\xda\xc3Te\x86\x0eQ/,\x0f\xe7\xe8%\x8d\x9542\xd4\xf6\xe9\fߥ\xebqd\xf8\xe6d兞\xa4^Rdt\xc6\xd6\xcf?\xf8\x9c\x1eK\xad\xa3\xb5\xa3\x9dH\xday\xab\xa1\x8b7\xd5`\x86\xd9Ԋ]\xca\t\xb0\xd9L\tݝ\xd4,\xa9{\xb3\xb7_\xdbH\x8d\xa0\x89c\xe5\xe3\u007f\xff\x12\xfe\x97F\x86\xf2\xa1\x1a\x14\xb1{s\x17\xe5J#n\"gTeM\xb8\x1f\xccv~\x1c\xdaK=\xefe$\xa5\xf3\r\xa0\x0fS\x95\x19:D\xbd\xb0\xd9+#\x8d\x95\xf4\xc7Um\x9f\xce\xf0]\xba\x9eE\x86\xc7NV^\xe8I\xeb%EF_\xd2m,,\xbfM\x97IG\xa8\x89w\u05fe<\xa1\v=u\x9b)3[@w\xc5.\xe5d\xb1\x992h\x96T\xb9\xfa\xd6t\xf0ޠ\xd6!*\x8e\x95g\"\xff\xdf˥F\xf0f\xfevc\xe9%\xf5\xa1\xaa\x1eS\x1f\xea\x9ds\xf5'\xf2\x97#\xe7\uf13f\xb3\xf7\x1aU\r&\xdc\xed\xfa\xb1\xab\xb7\xce\x1cꍌ.|\x03\xe8\xc3He|\x87H\xbd\x0e\x95\x91\xc6\xeaN\xd6x\xfb(\xa3q\xe9\xfa\x15\x19>;Yy\xa1\xa7VoRd\xf0ՏK\x9d1O\xcc\xde&\xc7j#\xd4.,\x1fI\v=\xe9`\xecl!\xf1\x8a\x1d\xca\xc9d3eЦ\x90\xff\x13\xe1s\xaf\xae}\xa5\xe2\xd8\x1b\xf5k\xc1\u007f\x9aB\x04\x1fF\xad\x04\xdf~!>TV\x11\x1b\xbc\x83\u007f^~,D\xf4\xd5\xee^\xa3\xaa\xc1\x84+_,\x1f\x9bl\xdc7F\x86\xa1\x01\xf4a\xb42\xb6C\xb4^\x87\xcaTc5'kw\xfb(\xa3q\xe9\xfa\x15\x19%P\x8a\xcdt\b\x06\xcd\xe4M\x18g\x8aZ\xb1\xabNv\xa76\xd0_ld\xc2ͨ\x9a~\xfb3#\xb9\x1e\x96\xb92Sc\x87\xb1}<)\x97\xee\xd8GF\x196\xd3a\x184\xf3GFQ+v\xd5ɮ͔\x1d\xa3\xaeF\xd5\\?\xfb\xb9\x1e\xe6P\x99\xa9\xb1\xe5o\x9f\x19ͥ\x8b\xc8\xf0\x94\x01\"\xa3 \x9ct\xb2\xcd\xcdv\xe3\xa2\xed\xa0Aq5\xaa\xe6\xf8\xd9\x0f\xc8\xf10\x87\xca\xd8\xc6\x0ee\xfb2\x82\xc8\xf0\x92\xa7\xe1\xdb]\xb6\xa3\xca\xc5\xc5f\xba+\xde=W\xcf\xf8\x9b\xf9\xd0x\xb4.>\xb9k\xaf=M·e\x83o\xec\xbe\xda>D\x86\x97\x84ow=\x96\xa3\xc5\xc5fڜj\x18\xff\xdabT\x9c\x0e\xde\x04\xb4\\\u0086!\xe7òah\xec~\xda>D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x81\xff\x03&\xf2B\xcdI\x1b+\x96\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/typeinfo-src.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\xc1\x00\x00\x01\xb3\b\x03\x00\x00\x00\xf9m:\x11\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\n\x03\x01\x05\a\x03\x02\r\x14\n\f\b\x10\x12\x0e\x0f\x13\x1e\x1b\x1a\x14 \x1f\x19\x1c \"\x17!;!# #$\"$%#&'%'(&+)\x1e()'\x18-T*,)/,!-/,12053'35386*6758:7<:.<>;>@=CA5&CxAB@EFDIJH\x00g\x00KLJ\x00j\x026NzNOM0R\x95\x06m\x06UP?PRO>V\x82\x0fq\vTVS\rr\x17\\WEVXU,`\xae7]\xad\x15w\x1c[]Z8`\xaa\x19y\x1e;b\xac_a^=d\xae?f\xb0*{!bdaSe\x84)}+Bh\xb3efdDi\xb4ghfLj\xafpiQEm\xb1ikh0\x820Ol\xb2Ip\xb4lnkTp\xa3Kr\xb7npm6\x869Nt\xb9zs[Wu\xb5>\x89=strZx\xb9vwt]{\xbbG\x8eHy{xX\x80\xbf^\u007f\xb9\x85}ea\u007f\xbf}\u007f|O\x93N\u007f\x81~c\x84\xbeW\x95V\x82\x84\x81m\x87\xbch\x88Ð\x86h[\x99Zj\x8ać\x88\x85q\x8b\xc1\x8a\x8c\x89`\x9dd\x96\x8cnt\x8e\xc4z\x8f\xbf\x8f\x91\x8eg\xa1hy\x93\xc9~\x93\xc4x\x95Ē\x94\x91\x81\x95Ɵ\x95w{\x98ǃ\x98ɂ\x9aė\x99\x96u\xa8v\x86\x9b̀\x9d̙\x9b\x98\xa5\x9b|\x85\x9eȂ\xa0ϙ\x9e\xa0\x9c\x9e\x9b\x89\xa1˞\xa0\x9d\xab\xa1\x82\xa0\xa2\x9f\xa1\xa3\xa0\x81\xb0\x83\x91\xa5ʕ\xa5Ď\xa6ѣ\xa5\xa2\x91\xa9Դ\xa7\x83\x95\xa9Χ\xa9\xa6\x8c\xb4\x8a\x94\xac֪\xac\xa9\x99\xadҟ\xaeλ\xae\x89\xad\xaf\xac\x9d\xb1֯\xb1\xae\x98\xbb\x97\xa3\xb3ӡ\xb5ڧ\xb6ֱ\xb5Ĵ\xb6\xb3\xa3\xbf\x9d\xac\xb7\xd2ķ\x92\xaa\xb9ڢ\xc1\xa4\xb7\xb9\xb6\xb3\xbcĭ\xbcܺ\xbc\xb9\xa6Ũ\xb1\xbd\u05fd\xbf\xbb\xb1\xc0\xe1\xb8\xc0կǫ\xcd\xc0\x9a\xc0¾\xb7\xc2ݻ\xc3ؽ\xc4ڲ̷\xc4\xc6ú\xc6\xe1\xc0\xc8\xdd\xc7\xc9żκ\xd8ɝ\xc6\xca\xda\xc0\xcb\xe6\xc9\xcc\xc8\xc2\xcd\xe8\xbf\xcf\xe2\xcd\xcf\xcc\xc4\xd0\xde\xcb\xcf\xdf\xc8\xd3\xc1\xc8\xd0\xe5\xe1ѥ\xd0\xd2\xce\xc8\xd7\xca\xcb\xd3\xe9\xd2\xd4\xd1\xd2\xd3\xdd\xce\xd6\xdf\xdfש\xce\xd6\xec\xcc\xda\xce\xe6֪\xd6\xd8\xd5\xcb\xdb\xee\xd5\xdc\xd1\xd3\xdb\xe4\xd6\xda\xea\xd9\xda\xe4\xda\xdc\xd9\xd2\xde\xec\xd9\xdd\xed\xdc\xdd\xe7\xd7\xe1\xdc\xe0\xde\xe2\xdd\xe0\xdc\xdb\xe0\xe2\xf0\xe0\xb3\xd6\xe2\xf0\xdd\xe1\xf1\xe0\xe2\xdf\xde\xe3\xe6\xe0\xe4\xf4\xe3\xe5\xe2\xe1\xe6\xe9\xde\xe7\xef\xe8\xe5\xea\xe5\xe7\xe4\xe6\xe7\xf2\xe4\xe9\xeb\xe7\xe9\xe6\xe2\xea\xf3\xeb\xee\xea\xec\xed\xf7\xe6\xef\xf7\xe8\xf0\xf9\xf0\xf0\xfb\xf0\xf2\xef\xf4\xf2\xf6\xef\xf4\xf7\xf4\xf6\xf3\xf2\xf8\xfa\xf8\xfb\xf7\xf6\xfb\xfe\xfd\xfb\xff\xf9\xff\xff\xfe\xff\xfc\x11\n֍\x00\x00 \x00IDATx^\xed\x9d\r\\T\xe7\xbd\xe7\xef\xb2\xcd&\xbb\x0f\xcc4w.s?e\x8a\xbd\xbc\xe8z-[\xb2z>\x8c#\xd6-h\x16#,6\xd7\x17\xbc\x94+\x95h\xae\xa2\xb7Jbȍ\x8e\x91\xd8\x05\nac\x12r'\x161vg\xbd)+\x91\x98b,\ti41\xb9\x96H,-\x9b\x17\x92\xb6c\x1a-&\xd4\x13\x93[\xaf\n\xfd\x9c\xcf>/g\xe6<g\xe6\x9cy\x81\xe1\f\a\xfeߴ\xe3\x993\xcfy\xce\x19\xf8\xce3\xff\xf3\xf6\xe3Ϥq#\x02@\xe2\xf9\xb3H\x9e\xea\x13\xa9k\x000\x000\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01sc\xb4\xc1\xde\xde\xc0d\x8f\xdbC\xff\xf5u\xec\xaf\xdb\xdf\xe1\xd3[\x02\x00\xc2a\xb0\xc1\x83\xee.\xff\xe4P]G#\xfd\xb7\xb1\xb5\xb7\xafw\u007f\xe3\x90\xeeB\x00\xa0\x8f\xb1\x06\xf77+\x06{\xda\xfb\xa8\xc1\xde\xe6a\xfc8\xdcܡ\xb7\x10\x00\x84\xc1P\x83\xbdno]\x97<\xddS\xef\xeb\xa7\x06\xb7\xb7\xd2\xe7\xad\xed:\v\x01@8\f5\xd8\xe7\x13\x1b\xbb\xe4ɺ\xd3b\xbf\\Ex\x87\x86\x87\xbcPE\x00\xe3\xc2P\x831~\x83=x\xc8e\x06\x8b\xbev\xb7\xdb\xdd\x06{r\xc0\xb8H\x90\xc1\xbd\xf5>\xbf\xc1\xc3\xedͽ\xfd\xbd\xcd\xed\xc3\xe1\x16\x03\x00\x1d\x12c\xb0\xaf\xaewdd\xa4\xafq\x04Ow4_\x14aO\x0e\x18/\x891\xf8\x8c\xdbO\xbfX\xd7M_\xe8\xae\v\xb7\x18\x00\xe8\x90\x18\x83\xc5ABO\xfd\xe0\xa0\b\x06\x03\x13\"A\x06S\xe4\xa3i\xb4\x8a\xb8\xd8\fGӀ\xf1`\xa8\xc1\xbe\xfe\xfezo\xff {2\xd2\xdfS\xdf?\x84g67\xf7\xf4\xf547\xc3\xc1\b`<\x18jp\x17\xab}\x99\xab\xfdd\xb2\tO\fw\xee\xafo\xed\x84C\x11\xc0\xb80\xd4`\x00\x88;`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\xa6`$R\x83\x99\v\x18<\x0eF\x86GF\xf0\xff#5\x8b\x17\xfd%ihI\xa4F3\x1608fzggf\xe6eef\x96\x1bu=hf\xa6\xbb\xbd/R\xa3\x19\x8b\xd1\x06k\xa4N\x8dt\xb7ֵ*\xb3\x8d\xe2!A8\xa2\xf3\xd2y\xa7\xb0J\x14\x8f9\x05\x86S\xd5n\u0602rs\x93l\xb9s\x936\x1a\xa3p\x0fj\x8b\xd4d&c\xb0\xc1\x1a\xa9S\xa2\xa7\xbe\xbb\xaf+\x90\x84\xa2\x857܋\xb1\xf2\xe2\xab\xec\xdf\xf7O:[t\x9a\\y\xf9\x01\x97(>)\x9c<y@8p\xf2\xe4\x82'\xf9\x17}\xb7l\x93\xa4\xdek\xd2\xe8\x97\x16E\x11q\x11˦\xeb\xb4\xedBp\x13l\x18\x8c5X+u\xaa\xbb\x8e\x88p\xba.̀6\xb7P\xff\xb5\x98\xa9\xd8\xee\x9fr\xe9\x19,\x8a-\xd8\xe0\x03NQ|UxY\x14\xf3\x0f\xf0/\xf92\x93\x92\x92\xc4¤\xa4/UGap,\x9b\xaeӶ\x13uj\xce\a(\x86\x1a\xac\x99:\xe5aߑ\xfc\rt\xc1̎A\x83\x88\xac\x8b\xd6\xe0\xcb\xe7e\x83\xcf_V\xbd\xd6_\x96\x85\r\xbeeѶ\xde(\xee+\x89e\xd3uڂ\xc1a1\xd4`\xcdԩV/\x9d\xd1\xea\xd1Yȃ\x18\xb3\xd9\xe4\x06\xb1\x1a?6\x97\xa1\x94ڕ\x0e\xfb\xa2ӴMc\x8e-C\xbdc\xf5\xe9\ngCqы\xbb\v\xaa.\xe1gW~T\x91\xbfj7\x9e:&\x97\xb6\x15\xa4\x8dk\xdf\xeeU\xf9\x9b\xde'\x93W\x0eT\xe4\xaf;p\x85L\xbe\xbf\xa3\xa8`+\xa9\"\b\xd4`\xb6X\x83\u0602\x1f\x8f<$8\xff\xd7\u007f\xc3\x06\xffǮ\xc1a\xa5_\x15\x1dy\x0e\x8b=/]\xb5\xe9\xdd)\bm<\xbd<ݖ7\\\x86\x92\x1b\xc53\x16\x94I\x1b\x9f)\xb4[\xd2\xf2\xfa\xf9\xb6Ax\xc1\xe0p\x18j\xb0\xa8\x95:\xd5\xd1H\x86\xb2\x8b\xf5\xfbu\x96\xf0ux3r\xbd^\xb2\v\xe8\xebp\xac\x19\x14\a\xabS;|\xbdM)(}[u\xba\xad\a7)I.\xf3\xd4\xdag\xab\x0eo\xbdX \xec\xae\x12\xee|r\x05)\x01v\n\xbb\x8f\x1f(ZwE\xbc\xf4\xf2\xc9UU'O\x9e|\x9b4q\t\xab\x8e\x1c[\xb1\x95L\xeet5\x1cop\xed\xc0S\xe7\vV=sl\x93\xa06\xf8\xd2\xcb\xc5\x0f\xfcZ\xfcuK\xc1\xc9Ko\x1eq\n\xff\x19\x1b\xfc\x1f\xfe\xf70\xd7/O\x17*\xd9\xdf\ueda3aզ77\xa5g\xa4:ʗ\xa3\xbe~\xaf\xa5\x1a\x8f\xac%V\xd2\xd8k\x9b]\xd3^\x8dj\xf8\xb6<Ã\u07b9vc\xf6\x18MJ\x82\f\xe6R\xa7|\xf5\x9eA_\u007f\xab\xbbY\u007f!\xe5뵚\fQ%%dҚ\x8e\xbb\x18r䐡\xae^$_\xb6\xea\x1e\x8av\x88Džc\xe2\xce\a\xc9\x10\xfa\x8cHl\xa4\xc7\x14\xb8*\xa2\xe8\xb7X\xc2\"<u\\8\xee\u007f\xacZ\x85\x87\xd4+k\xd5\x06㲂\x8c\xda;v\xd2\xc5J\xff'1\xf8\u007f\f\xab\xfb\rඓ\x8fdm*}\xc2U\x06\xb3\xd1|\xbc\xc5\xc4F+6X\xac&\x06\xfb\x1cy\x17I`\xd1PP\xdb\x00K\xf0\xb0\xac\xf7\xed\x04\x10\x12c0\x9f:%\x0ey\xdcnw\xa7\xa7U\u007f!\xe5Wۇzċ\xa94Zº\x81<֢!q٬a\x82\xa3D\xb5P\xd1\x11\xec\xd6%q\x1f\x1eXw\x94^\xfe\x14SL\x05\xe4\f\xc6rӊWܹ\x96\xceX\xf5\x80x\x81J)6\x04\x1b\xfc\xfe\x827\xc4\xcb\x05/\xd2\xc5\x1a\x9aI\x15\xf1\xd7\x17\xd4\xfd\x06\xe8s\xa4\x97\xb9\xbbEV$\xf3\x06[\xfd\au\x15\x83=\xa8[YP\xcb\xe0\xbe6w&\x8c\xc1\xe1H\x8c\xc1|\xea\x14\xc674\"6\x869d\xc4\xfdj\xf3\xca\xc56:\xc61\rp\x91\xd8%f\xc9%\xa4\xfa\xbcU\xd1q\xf1U\xa7H\r^+W\xbf\x9b\xc8\xfc\xa0=9jp\x05}E\xdcT\x81\x95=)\xfa犜\xc1\xe2\xa6}\xe2\xf1\x82\xcbl1f\xf0\xab\xea~\x15\x86܅\x99(\xad\x86N\xf3\x06\xcf\xf5O)\x06\xd7\"\xceN\x9d=9\xa8\x83Ò\x18\x83\xf9\xd4)6X\x9df.kC\u007f\xb5ut\x04\xf3؇Y\x11!Z\xcbȣ\x1b+\xb0|V\x17eP\xb5\x101\xd8%\xcac\xf0\xab\x94\vd>5\xf8\x99wE\xde\xe0\x9d\xa5\xa4\x94\xbdR\xbaS\xfc\xad@\x0f\x9d\xed\f1\xf8\xd8\xd2\xcb;\xd9X\xebڭ\x8c\xc1\\\xbf\x01\xba*ER\xf7\xda\xdc\xe4\t\xb7銠\xd4\xe0\x8d\xc4\xe0\xf6\x901\xb8.\xe4\xec\x1b\x1c\x8b\bK\x82\f\xa6\xb0:\xb8\u05cd\xcd\xf35yu\x16 \xe4\xe6b\xe7Y\x99;l\xf7\xd8Y>\x955\x8dT\x95\xb3\xf0Km\xec\xa5\r\xdbT\vq\x06\x1fg\x95j\x03=3QU%\x8a\xbf\xa63\x14\x83Y\x83#\xa4\x0e\xae(\xc6>\xbe\xed\n1\xf8\xf2\x9dǖ\xd2\"Bt\xad\xf0\xd7\xc1\xaa~\x03T\xb3sh\xb9k裲\xe9\x8a\xc16\xec\xf8\xc8\\Z\a\xa7\xe5\x92\x0fpYYP[\x1e08,\x86\x1a\xac\x99:u\xda\xdd\xd5\xd7\xdd\xe8\tW\xebU[kZ\xe7\xdb\xd8\xe0T9\x8b\x15\x11\xa2\x15\xcdn\xae˰\x9f!\xf3в\xfd\xad%\xa8\x91_\xe6ͥ\a.\x1dq\xbeyiG\xd5\xfbX\xe3\x05;\x8e\x1c\xdb\xc9|kq\x1d8V\x95\xff\xae\xf8\xeeI\xe7\x03/_y\xe3\x01\xe7I<\x1e\xef\x10\xf6\x1d\xdb'\x90c\x11o\xe6\x17\xb74,\x15\x9cϼ\x89\x9f\xbcq@8 \x9f\xc2\x13\xf7\x95\x16|J'\\\xc2\u007f!\x06\xff\xdfau\xbf\x01\xaa\x91\xadڃ7\x87~&\xfd\x9b>\xdcI\x0f5\x9c\xa1-r\xec۶堔\xfa^\\\"ܞ\xe9\xf6\x94\xa1:\xbem\x10pN.,\x86\x1a\xac\x9d:ս\xbf\xde\xc3}\x97jp\xb1\xccn˕\a\xa2\xd3h%\x9b\xb0\x96\x97\xa4:\x96\xb3ڣ-\xd7n\xcfU]=pe\x85 \x1cY,\xe4\x1f\x11\x04r\xb8\xecx՝\x05U\xc7\xe9+\x97w/uU\xbdJ\xaf\x8b\x10\x9co\xe4\xe3LJ\xc8\xf1\xe0\xb5\xf9k\xd9\xf1\xe0\U000db596\xee{\xc6I\xe6^\"\xaf\xe6\xcb5\xc2\xdb\u0083lµ\x9b\x1e\x0f>=\xac\xee7@cn\xb5Ò\x96˾T\xfc\x9bޝLK\xf5<:\xf3t\xae-5o\x03Bd\xe4=]\xe8H\xcdiU\xb5\rb0\xa5\xb0{а\v\xe1L\x87\xa1\x06\xc7\x03\x9fU\xae7؞\x9cq\\r\xb1\"BޓK9\x1d\xc5\x19\xb9\xf8К\x19\xbc\x97\n(\x98\xce\xe0f\xb9\x880\xdc\xe0#w\xb2\"\xc2x\x83\xf10\xdc\x1df?w\x86c.\x83\xab\xbd\xe2|\xbf\xb8\x11\f\x16&\x91\xbf\"u\xf0_\xf3s\xc2n\n0\x99\x98\xca`\x1f\x9a]\x96\xc6.\b\xeb\xf7ZJ\xc2\xee\xa2\xeb\xd97q\x9c\u007f\xf5\xe7\xd8\xe0\u007f\xff\xe7\u007f\xedT\xe6\x85\xdb\x12`R1\x95\xc1b\xb5-W\xben\xa0\f\xef\x16Y΄o\x1dGZ\xf2\xab\xdefS\x0f\t\xff\xc9\u007fu\xe5~\x03\xeb\b@\x0fs\x19<\x15\xa0W\xb8_\x95\xa4\xd1[\x96Dq}00ـ\xc1\xb1\xe2C(7\xf7\x96\xb4ܹI+\xc1\xe0)\x00\x18\x1c+\xc3^\x87\xdd>\xcbn\xb7\xcf\xef\x82+n\xa6\x00`p\xcc\\\xec?s\xfa̙ӧ\xfb@\xe0\xa9\x00\x18<\x0eHV\x84\x81y\x11@8\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06'\x8c͛\xb5&\x81\x181\xda`\xf9^\\_=\xbdβ\x9e\x9e\xd5\xeao\xado3͕+-\x82\xf3\x18\xfe\xe7x\xbe\xa0\x9f6\x11\x15\xff\x92}\x9f\xc6$\x10+\x06\x1b\xecO\x9d\x1arw\xf7c\xe8\xc5\xee}u\xde3\xdeЛk\xa6(\x17v\xe4W\xe1\u007f\xaa\\;\xd4\xf7\x16\x05Ҭ\xa2\xe5\x9e9\xefhLF\xcbs\xafL\xb4A,ĵ\xb38c\xac\xc1\x81ԩ!w\xc0ؑ&r\vBG\x93Y\x0eN\xed۔\u007fA\xbc\xe0ڴ/h\xbe\x92f\x15\x15o)\xe3\xee[\xe3\x18\x82\xef\xfa\xeeD\x1b\xc4B\\;\x8b3\x86\x1a\xac\xa4Nq\x06\xf7\xd2\xc44_\x9d\xf1\xe9\x95\xe3cߎ\xaa#\xe2\x8f6\xed\b6x]l\x06oV\xc6\xddͱ\x0f\xc1\x91\x9d\x8a\xd8 \x16\xe2\xdaY\x9c1\xd4`%u\x8a3\xb8\x9d\xdd\x1d\xe4\tw\xab\xe7\xe4prS\xb1\xf3\xceM\xc5W\x82B\xa5\x9e\tdQ\x89\xe7\xb7\xde\xe9,\x92\xa7\xfd\xec\xdbq`\xab\xb8\xe9\x006\x98\xe6\xb7\xcaI\xad\xf2U\x964\xcd*\x90E\xf5\xa6S\x106])\x16\x84\x02u\xf2\x9a\x18~\b\xfe\x87\xec\xecG7/\xfc\xc6w\xdf\x12\xc5W\xb2\xb3\xb3\xf7\xbcu\xcf\xc29\xab\xc9W\xd4Swͻ\xeb)\xfc\xef\xff\xc9f\xdcE\x9b\x1fZ=\xef\x9b\xf7\xb1\xf3\x83o}\xf7\x8e\xec;\xfe\xf6\x1du\x83\x17V/\xc43\x17\x8aA\xf8\xdbr\xfd\xe2\x15\x1f\u009b\x93\xfd-:\xf9\xd4}ߜ\xb7\xfa\x97zkSm\x99\xce*\f\xc1P\x83EQ1\xb8}\xbf\xbb\xa9\x83\xfc\xdc[\xd9}\x8c\x1da\x12O&\x877\x16\xec8r\xfc\x99;\x85O\x83C\xa5\x8aZ\x9e,\xa0YT/\xe6W<y\xbcEPEWb\x83\xdf\xcf\xff\xad\xeb]l0\xcdoeI\xad\xaa4\xab@\x16Օ\xd7[\x84\xd7\xc5\x1f-\xf8\xd1\x1b!+ߜ\xfdK\x8dIƿ\x1c\xca\xce^\xb8g\xcf\xc2y\xaf\x88\x17\x0f\x1dZ\xf8\xcdy\vﻇ\xb4\xd9<gϏ\xf7̹\a\x8f\x04/\xbc\xf0\xcd\xd5/\xbc\xf0\xc2[l\xf1\xfb~\xfc\xe8\x1dw\x11ß\x9bwף\xcf\xed\xc9~T\xd5\xe0\x95\xec{\x0e=\xf7\xd4\x1d\xd9AUZ\xa0-\xd7\xef;/d\xef\x11şn\x9eö\xe1\x8e=\x8f\xce\xfb\xae\xde\xda\xf8-\xd3Y\x851$\xc8`\x9f\xbb\xb1\xa7\xafw\u007f\xf3\xc5\xc0\x9c.՝\xc6Fp\xa0\x88\xdc6t\xa0\x80\xdc\xdfɇJ\x15\xe01w\aɢ\xba\\\xbc\t\x8f\x9d\x97\x8f\xa8w\xd9\xf6\xed\x10\xd7>P!\xd2*B\xb9_\x9f\xab\"\xf8,\xaa+;+.\x14\xaboƧ\xfc2{\xb3\xc6d\x809\v\xf1g\xfb7\v\xbfM\xa6\xef\xca^\xcdª\x9e\xcb~N$\x8f?\xa6s\xfd\xdf\xeb?\xc6\xc3&\xb6\x8e<^\\\xb8zX\x14\x87\x0f\xfdF\xd5\xe0\xa9;\xe8\xf0=O\xbd\x06\xae-\xdf\xef\x1cl\xb0\xb8g\x0ei1\xe7\x1b\xf8Cs\xcf\x1d\xa2\xaa3nmܖi\xaf\xc2 \x12d\xb0\xd8C\x8b\xdf\xfa\xce@v\xa5\xd7\xf01\xf8ݢ\xd2\xddϼq\x85~\xc1\xf3\xa1R\xc4c9E\"t\xec\xa4\x06?)<\x19\xc6`U\x16\xd5\xe5u+6\xa9\x83\x01)\xff\x90\xfd\x96\xc6d\x809\xb4\xaex*\x9b\xb8x\xd7\x1cy\x88\xde\xfc-\xfaϷ\xa8\xf0\x01\xa7\xbe\xbb\x90\xfcQ\x8f\x91\x85\x9b\x89^\xdc!\x83@\x83_ޱ\xf0\x1f\x9ezE\f\xba\x1a\x9fk\xcb\xf7\xcb\x1b\xbc90\xa9\xb96n˴Wa\x10\x892\x98AJ\x87v\x16l\xd7ڮ\xd5|R\xb9\xf0\xcc\xf6U\u008a'\xa9`|\xa8\x94([y@\b)_Ej\xf0\x85}\xbf\x0ec\xb0:\x8b\xeaH 3\x85\xe3\x9d9\x9b5&\x15\xa8H\xe2\vԲ\xbb\xee\x92g\xaef\x1a\xfd-\x1b\x99\xfdN\xdd%W\xa9\xf8\xf9\xa3\xd9\x17\x95.\x94\x9d\xaf\xdf<\xf5\xddoe\xdf\U00068a02k\xcb\xf7\xcb\x1b\xacLj\xae\x8d\xdb2\xedU\x18D\x82\f\x96\xb5\xf5zHf\x0f\x1d\x8e݆\x1f\x8bxu\x1fv\xf7\xc2\x11\x17-s\xb9P\xa9\x80\x95/\nZ\x87xI\b\x10F1\xb8\x813\x98\xa4Y\xa9\xb2\xa8\xde/j(\xfemH\x1f\xf7)\xe3\xee}\x1aCp`\f&?\x99\x80=\x9bٞ\xd2Be\f~\x8a|\xcf/|\x85Bˁ\xe01\x984x\x85\xf4\xf5\x9bCs\x9e\x12y\xb8\xb6|\xbf\xe1\f\x0eZ\x1b\xb7eګ0\x88\x04\x19\xec\xa1i\xc1C\xf5\xdd\xe4x0)#\xbc\xc6\x1f\x0fn\xa1\x91\xabb\xd5\x03\xe4\x91\v\x95\n\x18|\xa9\xa8\x8a\f»w\xd3\xf9}\xdb\xd8my\xbc\xc1\xf9\xf8\xe1J\x0538\x90f\xc5gQ]\xaeh\x11\x1f\xa8\n.#\"\r\xc1\xe2\x9c;H\x81\xb9p5\x99\x0e\xaaA\x0f\xb1:x5~\xed\x1d2\xe39V\x93\xee\xc1\xbe\xf9\xee \xb5\xadx\xdf}\xaa\x06{h\x99+\xaeV\xaf\x87k\xcb\xf7;\x0f?\x1f\xf9v\x88\xc1Zk\xe3\xb6L{\x15\x06a\xa8\xc1J\xeaT\x9f\xbb\xedt_W\x1d\x1d\x89\x13uN\xaeE\xc8o9vl\xa7\xc0ĕC\xa5TYT/\xbaV\x1d8\xbe\x9b届\x8bX\xe0\xceowT\x91\xd4\xc0w\xabv\u0875\xa2\xe8ɖ\n9\xa1ʟf\xc5eQ]~\xf9\xa1\xa2\xf7\xc5\xf3\x05\xbb_V\x97#\x91\x86`qN\xf6]\x87\x9e\xfa\xe67\xde\x12G~J\x8f\x03\xb06\xf7d\xdf\xf7\xe3\xfb\xb2\xef\xa1\xd3{\xe6<zh\xf5\xbc_\xd2\x1e\xee9th35\xeb\xb99\xdfz\n\xb7xJ\xd5`O\xf6\xbc=?\xc6\r\x9eS\xaf\x82k\xcb\xf5\xbb\xfa\x8eG\xf7|;;\xfb\xd0+0\xbd\xf9\xa7\xe2+\x9b\xb3_xG{m\xfc\x96\xe9\xac\xc2\x18\f5\x98K\x9d\x1alo\xaa\xf7\xf4\xb0\xd9\xfdmu\xad\t\xb8.\xe2GU-\xc5\u03a2*9\x89G\x0e\x95ReQ\x89oo/^\\q\x8c5\xa8\xb7\xd30\xca\x16A \xd5\xc6\x03\x02\xb9.\xe2|\x95k\xf1\xa6\x06\xd6֟f%*YT\xc7q7\xbb\xc5݂\xb0\xe0E~\xc5\xef̻Gc\x92g\xce}\x9b\xe7\xddq\xcf;\xec\xa8+\xe6o\xd9\xecG\xe5㶘\xe1\xfb\xbe1g\xf5O\xe9\xe4s\xab\xef\xf8\xc6j:0\x8bo}w\xe1\xbco\x1fR78\xb4z\xcf\xc2\xec;V\x87\xd8ŵU\xfa}k\xf5\x9cy\xab\xf7dgo\xdeLV\xfb\xca<\xfc\xb0Y{m\xfc\x96\xe9\xad\xc2\x10\f5x*\x13\b\x95\x9a|\xf6d\xff\x8b\xc6$\x0fۓ\x03\xa2\x01\f\x96\t\x84JM>\x91/\xab\x04\x83\xa3\a\f&\xb4\xbcx\xa5j\x82\x17K\xc6\x1508z\xc0`\xcc%\xa1\xe2\xa1\"\xf5\x99\xb7D\xc2\xf6\xa2\x80\xe8\x00\x83\tJ\xa8\xd4T\x80\xeeEi\x1d\xa2\x004\x00\x83\x01s\x03\x06\x03\xe6\x06\f\x8e+I\xe6\"\xd2\xdb1\x03`p\\I\xfa\xc8L\x80\xc1@0`\xb0\xe1\x80\xc1q\x05\f6\x1c08\xae\x80\xc1\x86\x03\x06Ǖ\xa8\f\xe6\x1b=rk\xd0\"!3\"\xa1\xd7<\x8an\xc0` \x98\xa4h\xcc\xe1[\xdc\xf6à\x17Cf\x84!)\xf0\xa0\xf9b\xe0\x90\x83N\v0x<h\xa5N\x05\xe6N-\xcaPr\xc8\xdf8\x969cA\x99\x9a/De0OH\xebX\x16\x8f`p\xb8Wً\x81\xedf\x99\x01\xa6\xc4`\x83\xb5R\xa7\x94\xb9S\x03o\x17\xfb\xb7\xdfk\xd1\xfd\x93u\x9d%V\xcd\xf9\xf2\xc0w\xeb/\xb0\x1f\xbf\xba\xe5\xe7I\u007f\u007fۿ\xbb\xed{D\x96G\xbe\x9ct\xdb\xdf\xf8\xc5\xc1\xff\xfbǿH\xba\xe5\xeb?\xff\x88\x8d\x90\xa4\xd5\xdf˯\xa9f$\xfd\x9d\\S\xe0\x8e\x92\xbe\xfc\xc3\xefݖ\xf4\x95\x9f(\x9d\xb1\xf1\xd5\xdf\x15\xd7\xcd\xf7Ȅ\xdf\xe0\x9f\xe8o\x8cb0\xcb\f0%\xc6\x1a\xac\x95:\xc5͝\x1a\xcc\r\xfc\r\xfa0\u007ft\xb1Z\xcf`:\xea}\x8d\x88\xf2\xbd\xff\xfaQҭO\xfc\xea\x89[\u007f\xf0\xd1G?\xfc\xf2\x0f\u007f\xf5\x93\xaf\xfd\x8db\xf0mO\xfc\xeag_\xff:k\xfdȭO\xfc\xe2\x89[\x1f\t\xbc\xa8\xccH\xfa\xea\xcf\xe4\xb9_\xf9ɯ\xfe\xfb\x97\xc8\xc3\u05f8\xce\xd8\x18\xec\xef*\xb0\xd4\x0f\xe8Z\x03c\xb0\xfe\xc6\xf0UD\v\x18\x1c\x05\x9a\xa9S\xdcܩ\xc1\xec\x89\x1b\xfc\xc4m\xf8\xe1\xab\xff\xfcQ\x12\xd1\xf2\x91\xaf\xe2iR\xdd\xfe\xec6\xc5\xe0\u007f&\xcfoa\xad\xff\x92\xb6\xfaK\xc5\xe0\xc0\fڌ\xce\xc5C\xef\xcf\xe9×\xb8Θ\xc1\xfe\xae\x02K}\x85N\x04\f\xd6\xdf\x1808V4S\xa7\xb8\xb9F2\x9cf\xd9\xe0px\xcbRsi`Sc\x8e-\xa3\x1cOy\x10c6\x99i-/ϰ\xe5\xb1-u϶e\xd1ی\xc4\xfe\xe5\x0e{\xa1n\x15\xc1\xb4\xfa\x8bG>\xfa\xc9W\xf04\xf9r\xff9\xb6\xeb\x16~\x97*P,\xcb\x13\xb7\xf8[\xc9\xf3\x94\x19I\xbf\xf8H\x99\x1bx\bt\xa6̥\xb3\x03+\xa3\x13\x81\xf9\xfa\x1b\x93t\x80ރ\xfa\xfe\x8e\xa2\x82\xadPEDIh\xea\x147\xd7P\xbc\xa9\xa8|>\xb2oK\xab\xc1OJ\x92\xcb<\xb5\xf6\xd9#\xa2\xafÛ\x91\xeb\xf5\xb2]K+\xcaljM[B&K\xac\x1b=\x1b\xad\xcb\xf1\xd4\xe9Ԍ\xfa\xd6<\x14\xde\xe0\u007f\xfc\xcaG\u007f\xf3\x8f\x9c4Ir5\xe0\xb7*Z\x83\xb9E\x94\x87@gQ\x1a\xac\xbb1I.r\xdf\xf5\xf9\x82U\xcf\x1c\xdb$\x80\xc1\xd1\x11\x9a:\xc5\xcd5\x96\xb4\xe5x\xc4\xf5\x88%+\xc9\xc8[\x8fgt\"z쁫\"\xc8\x1fq.\xb1\xe3\xa96\xd4\xe6\u007f̝\x85?w#Y\xe1\r\xfe\xe8\xd6\x1f\x92\xaa \xe9\x11\xfc\xf0\b\x1e\xff\xfeR\xdeQ\xf3[\xa528L\x15\xc1-\xa2<\x04:S\x1b\xacWE\xe8oL\xd2q\x128P\xb5\xea\x12ޕ[\v\x06GGh\xea\x14?\xd7PҚ\xb1\xb3>\xb1r\x99(.\x9b5Lp\x94\x90\xf9\x9c\xc1XnV\U00056c03g\x99%\xe2\x10\xa2\xb5\xc4F]\x83o\xfb\x01\x91\xe3\xef\xd8ξ\u007f\xe7\xe9\x89[\xbe\xf7\xf3_=\xf1\xb5\x80x*\x83\x1f\xa1\xad\x1e\t\xbc\xa8\xcc\xd068\xd0\x19]U\xa0\xab\xc0RA{r\xfa\x1b\x93$\xaez@\xbc\xc0\xd2\x04\x1a\xc0\xe0\xe8\bM\x9d\n\x9dk\x10imb\xa7E\xa4\x06g\xc9\xd5/-\x18\x82\xf6\xe4\xa8\xc19\x8b茼\x1c\xb1\vќ7\xfd=\xb9Gn#%\xe6/\xbeD\xbe\xaa\xc9A0v\x00뉯~)\xe9\xabO\x04tT\x19\xfc\x11i\xa5\x1aW\xfd3\xb4\r\x0etFW\xa5\x98\x1a\xe8\xe6{\xb7rG\xd3>\xd2ߘ$qS\x85\xf8\xaap\x92l9\xec\xc9EIh\xea\x147\xd7X\x88\xc1Vf\xf0\xf2Y]\x14z|\x9a\x1aL\x13X\x14\x83Kf\xd1E\xd2\x03c\xb0\xfe\x9e\x1c㑯\a\xfcI<z\x1b\x93t\xa5t\xa7\xf8[\x96.\xbb\x13\f\x8e\x8e\xd0\xd4)n\xae\xb1p\x06\xb7\xb1\nx\xc36\xf2\x98\x9b+\x8a\x83t\x86b\xb0\x87>o\xc6e\xb3\x98\xe3\xc0\xc5\xf1\xe9\xdb\xc3\x1b\xfc\xb3/\xffL[\x9aD\xa0\xbb1IGH\x1d\\Q|A\x14\xdfv\x81\xc1Q\xa0\x9d:\xa5\xcc5\x94^{\x8d\xaf\xd9\xd2\xe3[\x96\x8b\x87\xdbJ\xb4l\u007fk\t\xa2\x19\xc6\xd5֚\xd6\xf9\xb6>rN\xae\xa4S\xec*\xb1x\xfb\xf1(\x9d\\\xe9\xa9L&\xc7\"zl\x8e\xea\x8d\xf6\xe4\x94z\xad3\xe1\xb2%I_\xfa\xc1G\xda\xd2$\x00\xfd\x8dI\x12ȱ\x887\xf3\x8b[\x1a\x96\xca\xd9Y\xe6\xc3P\x83\xb5S\xa7\xb8\xb9\x062\x92\x86PS*\xb25\xb3\xea\xb7-\xd7n\xcfe\u007f\x0f\xe1b\x99ݖ\xdbI\xae\x8b@\xc8\xd2cÏexnm\x96-\xab\x96\xbe~z\x91=\xbd\xbc>\x85\xce\rfJ(\x1b5\xf2\xf1\xe0\U000db596\xee{\xc6I\xb3\xb3̇\xa1\x06O\u007fLfp\xa4\xb7c\x06\xc0ฒd.\"\xbd\x1d3\x00\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807F\x1b\xac\x91:\xe5\xf36\u05f5v\x0f\x87_nr\xa8\xb1\xd6\xe8\xbfؚ\"\xdf{\x94\xb2_\xbfQ\\\xf9\xed\x03+\\\x9b\xae\xd0?\x18*䟏\xd4:\x98cN\x81\xe1<\x12\xa9\xe9t\xc2`\x835R\xa7|\xf5\xad=}]\xf5\xad\x89P8˒\xa5\xffb\r\xf2zkQ\xad\u05cb\xc2h\x1eW\xaa\x8a\x0e\xec̿ \x8a\xef\x9f<y@x9l\xd3\x17_\r\x99\xf5\xa4@\x16;p\xf2\xe4\x82'5\x16\x98\xb6\x18k\xb0V\xeaT{3\xf9\xab\xf6C\x89\x88\xed\xf1%/Oֿ\xb0\xbe\xd6Bn\xc0\xef\x14E[\xadn\x9b\xb8rA8 ^\xb9Ħ_\x8d`p\xc5\xf6\x90Y\a\x9c\xf2b\xf9\a4\x16\x98\xb6\x18j\xb0f\xeaT+\xfb\x8e\xf6\xdf\xf4i$^\xd4\xcd\xee<\xd6\xe4\xe2\x19\xd9\xe03\x17u\xdbĕ\xf3±\xc0t$\x83ׅ\x1a|\xf9\xbc\xbc\xd8\xf9ˡ\xed\xa7/\x86\x1a\xac\x99:\xd5Ϧ:\x8c*69\xaa\x1d\xa2\x83\xdc\xccٍ+ލ\xa7\x97\xa7\xdb\xf2p)3\xb8\xdc\xee(/\xb7\xdb轟\xd4`\x96E\xb5A\xacƏ\xcde(\xa5v\xa5þ\xe84\xed\xc1\x1fV\x15\vo\xe2z\xb5\xe1\xfc\x8eRצOE\xf1ʏ*\xf2W\xed\xc6\x03\xef\xe5;Y\x11\xbb\x9b5\n\x18\x1ch\x809\xbf\xf5NgѦ\xf7\xc5cr\xc1[\x11ҷ\xbc\x18i\xd0 \xb6\xe0\xc7#\x0f\t\xce\x03\x0f\x16-\xddt>\xb8\xb3邡\x06\x8bz\xa9S\xa28Ҥ?\x18N\x1a\xf3\v\xc5\xc2\\\xfc\xaf\xaf\xb9)=#\xd5Q\xbe\x1c\xf5\x89Ùi\xb5\xd5V[]\x1e-~e\x83}\x1d\x8e5\x83\xe2`uj\x87\xaf\xb7)\x05\xa5o\xabN\xb7\x91\x9b\xfc\x02aU\xb1p\xf9ȑ\xe2U\x8b\x8bw\xefX\xf0\xae(\xee\x14v\x1f?P\xb4\x0eᄑq\xf2\x88\xd0r\xf2们Q\xc0`\xa5\x81\xf8b~œ\xc7[p\xa9q\xe9哫\xaaN\x9e<\x19\xfawH\xe5\xc5.\xbd\\\xfc\xc0\xaf\xc5_\xb7\x14\x9c\xbc\xf4\xe6\x11\xa7P\xdc\xd2R\x9c\xff\xa6\xba\xb3iC\x82\f\x0eJ\x9d\xc2Cp\xfd\x90\xde\"\x93ƈ\xadF\xac\xb11\xfdf\xa3\xf9\xf8\xe3\xe4#w\xd4w\xe3\x12\x18\xb1\x9bP\xfd\x06\xe3\xe1\x9aD\x01\x96\xd0L\x1fk:n6\xe4\xc8\t\n\xab\x8a\x85uB\xd5\x05\xf1\xca\x052X>#\x12\xef\xe8\xd1\x03\xad*\x82kp\xb9x\xd3e\xe2?\xfd\x03\xd0\x1aU\x04\xbf\x98\xd8B\xc6\xe7\x1d;ɤ\xab\x14/q\xa1\xb8\"hmӅ\x04\x19\x1c\x94:%v\xf2y\xc2Fэ:|\x1d\x88EV̶\xca\x1bPIb\xd2N#9L(`p\x1fv\xfabj;\x99\xb4n \x8f\xb5hH\x1dV\x15\v\xeb\\\xf2P\xbb\xa3\xf4\xf2\xa7\x98b\xaa\x9a\x96\xc1\\\x83\xe3\xc2\x1b\\\x0f\x11\f~\u007f\xc1\x1b\xe2\xe5\x82\x17ɤ\xab\x81<\x1e\x10.\xa8\xd76]H\x94\xc1\f9uj\xd8\xebNğ!\xa8\xa5G{ف\x86\xd9s\xe5\x995h\x90$\xa0\x04\x8f\xc1b^\xb9\xd8f\xa7G\xfcX\xaa\xb0\x17u\xa9êba\x9d\xbf\x82]+W\xb4\x9b\xc8\x13-\x83\xb9\x06\a\x04n\x0f-\x92\xc1\xe2\xa6}\xe2\xf1\x02\xba\x80\xab\x85<\x9e\x14^U\xafm\xba\x90 \x83U\xa9S>Oc\xbf\xee\x02\x93H\xe1\xec\xce\xceN9%-\x10\x96֗\x9c\xd7ם\x91#?S\f\xf6؇Y\x11!ZiP\x84\x1b\xf9\xd4aU\xb1\xb0n\xab<\xb1\xa3\xf4U\n\xad\f\xb4\xc7\xe0@\x83\x17\x05\xee\x1805\xf8\x99w\xc5 \x14\x83\x8f-\xbd\xbc\x93\x8d\xb5.\xbas\xf8\f\x1d\x83\xb9\xb5M\x17\x12d0\x9f:5Լ\x9f\x96\x14\xfa\vM\x12\x8er\xfcP\xee\xa0\xd3\x01\x83\xbbP\x1aB\xb9\xfeO\x94b\xf0\xb0\xddc\xa7E\x84hM#\x15\xf3\xacܠ\xb0\xaaX\b\x8c\xa0\xc7YM\xda@\xcfAh\x19\xcc5\xb8TTE\xc6\xd4\xddTȪ*Q\xfc\xb5\\\xd0\xf6m;\x13\xbc\x189\xb6ql)-\"D\u05caKx\xe1Ҫ\xa0\xb5M\x17\f5X3u\xaa\xaf\xae\xb9\xaf\xbf\xbf\xbf#\xe6ݡ\t\xe2\xf3\xa0\r>ѷ\x01\xb5]\x1c\ue931\xd7ԃnk\xbb\xc7\xeb\x17\xb8\xab\x16\xd5v\xc9ӕ\xb3X\x11!Z\xd1\xec\xe6\xba\f;i͇UEͧ\xaf\xd3#\t\xe7\xe9\x93}\vv\x1c9\xb6\x93\x98ŎE\xbcL\x8e\x13\xbc+\x9f\\{W\xd5@|ѵ\xea\xc0\xf1\xdd,,\xb5\xc5u\xe0XU>\x1b\x83\x17\xa1<\xb9\xeb7\xf0b\xfe\x81z_i\xc1\xa7t\xc2%T\x1cyfU\xc1\xdb\xeaΦ\r\x86\x1a\xac\x99:\xd5\xc6f\xba\x8d>\xa3\xd1N\x8e\xee\x8a\xfb\xf1c{w2-g\xa9\a\x1d\x162i\xc9%\xdb\xe6#\x91S6\xf9\xcb\xe14Z\xc9&\xac\xe5%\xa9\x8e\xe5Lr.\xac*j\xdeT\x15\xa3ǫ\xee,\xa8:\x8e\xc7\xcc\x02:\xd7ID\xdb)\u05eb\xdb\xf9\x06\x98\xb7\xb7\x17/\xae`\xe3\xf4\xe5\xddK]U\xb2\xac\xf5v\xf6\xe7\x11\xc4K\xf9x\xa1|\xb9Fx[x\x90M\xb8v\xef,(\xda\xf1\xaejm\xd3\bC\r6\x01\x83\xb65\x83\xc3\xc3C]K\xec\xc1U\x8d\xcf*\x1f\xb1\x0e\xf3\xf7a\xa6\x12\x97\\\xac\x88\x90\xf7\xe4\xa6-`\xb0\x9aV\xbb<a\x0f\xfeNh\x96\x8b\b\xb3\x18|\xe4NVD\x80\xc1\xbaD\xeaڔt%\xb3\xe3h=\xc9\xdd\xfc\xecj\xaf8\xdf/\xae\x19\fny\xf1J\x95_\\0X\x8fH]\x9b\x93\x12ۚfo\xf3\x1a\xdbJ~\xa6\x0f\xcd.Kc'\rY\xaa\xf0\x14\xe7\x92P\xf1P\x11\xab\x87\xdf?\xe9|\xe0\xe5iu\x1a9\b08\x18O\x9e\xc3\xe2\xc8\v\xaa!\xaam\xb9\xf29\x17\x9a*\x1c8z5Uiɯ\x92/\x9ax\x88\xec\x1e\x9e\x0f\xdb\xd8܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb91\xda`\x8dԩ\xfe\xb6\xa6\xba\xe6\x0e\xc3/p\xaf'WQ\xda\xf3\xba\xf4[\x94\x90k+O\a͜\xcc,*H\x9d\x1a\a\x06\x1b\xac\x91:5\xe8\xf6\xf4\xf6\xf5\xeeo2Za_=\xda\xe6\xad\xcf\t\x13y\xd2GR\xa7\x82\xaf\x81\x98\xcc,*H\x9d\x1a\a\xc6\x1a\xac\x95:u\x86N\xfa\x8c\xbf׳\a\x91K\xd3s3µ\xe9\f1x\x12\xb3\xa8 uj<\x18j\xb0f\xea\x14\xbbAn\xd0m\xf8͞\xcc\xe0Z\x14n\xf0\x0f5x\x12\xb3\xa8 uj<\x18j\xb0f\xea\x14}\xa1\xaf\xd9蛌\xfc\x06/gwz\xfa\xe3\xa3ԡR~\x83\xb9\xd4)\xed\xb9\xb1dQA\xeaT\\1\xd4`Q;uj\x90\xec\xd3\x19]\x06\x13\x83=\xbe\xdeJDo4\x0e\xc4G\xa9B\xa5\xb4R\xa7\xb4\xe7ƒE\x05\xa9Sq%A\x06\xabS\xa7\x06\xfb{\x9a\rߓ\xc3\x06\x13\x96\x93I>>J\t\x95\x12\xb5S\xa7\xe2\x90E\x05\xa9S\xf1#A\x06\a\xa7N\x89\xc3\xcd\xed\xda\vL\x1e=\xa8\xa6ӓc#W\xab\xf3\xf1QJ\xa8\x94\xa8\x9d:\x15\x87,*H\x9d\x8a\x1f\x892\x98AR\xa7\xe4\x1d\xa2n\xb7F\xebI\x85\xd6\xc1C\xc9d\xbd||\x94\x12*%j\xa7N\xc5!\x8b\nR\xa7\xe2G\x82\f\xe6R\xa7\x1a\xd9\x01\xd9\xee:\xbdE&\v\xb6'\x97J\xcc\xe3㣔P)Q;u*\x0eYT\x90:\x15?\x12d0\x97:\xd5D\x03C\x12RE\x905\xa7\x95\xf7lS\xc5G)\xa1R\xa2v\xeaT\x1c\xb2\xa8 u*~\x18j\xb0f\xea\xd4iw{o_oB\xf6\xe4\xe8\x19\x8d\xbc\x92,U|\x94\x12*\xd5'\x9f}c\a\xfe\x02\xa9S\x13͢\x82ԩ\xb8b\xa8\xc1\x9a\xa9Sb\u007f{s]kg\xdc\xcf\x0fD\xa2\x19\x97\xaa5\xd8\xe3\f\x9am\xa2\xc4G)\xa1R%rA\xcbB\x01\x03\xa9S\x13͢\x82ԩ\xb8b\xa8\xc1\xa6@/\xd0$\x90:\xa5=w\xca\xe5\xa0@\xeaTD\"umR\xf4T\f\xa4Niϝr\x06C\xeaTD\"umR4U\xe4S\xa7\xb4\xe7N-\x83!u*\x1a\"umJ\xb4C\xa5\xb8\xd4)\xed\xb9S,\x8b\nR\xa7\xa2\"RצD'TJI\x9dҞ;ղ\xa8 u*\x1a\"u\r\x00\x06\x00\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01sc\xb4\xc1\x1a\xa9S\x98\x1e\xc3\xff\xa2gt\xf4\xe4\xd9Җy\xd3Tw[pYT\x9a\xb1T\xb1\xd2\x1e\xf2\x97\xeb\x80X0\xd8`\x8d\xd4)\xf2\xac\xae#\xb6?Ml\x10m\xb6\xb9\xee\xe6,\x84T'\x94\xb9,*\xcdX\xaaX\xf1\xd84\x02ؼ]\xa1\xf3\x00M\x8c5X+u\n\xe3i\uf6ca\x06\x0f\xa5.\xb9H\xee\x1cB\xc1\x97DpI>\xa1\xa1>qana\xa4\x16\x80\x8c\xa1\x06k\xa7N\x89=\xf5\xbe\xfe\xa9hp\xa5\x8d~GԠ\xe0Ba\xf2\r\x9e\r\x06G\x8b\xa1\x06k\xa7N\xf9\xeaN\x8b\t0\xb8\fY\xdc\xe5\x19\xb6\xbc>2\x99\xdc(\x9e\xb1\xa0Lq8Ͳ\xc1\xe1\xf0\x96\xa5\xe6\xfaDq\x16\xbb\x81h\xb0\xe6\xa2\xe8+tX\x1c\x8b\xfc\u007f\xa8V\xcb\xe0\x8e<\x87Ş\x97\x1e\xbc\x16\r\x94\xb5ៃ\r\xa1\xe4&67\xb09\x1e\xf9\xee\xa6\xd9\x11:\x02\b\x86\x1a,j\xa6Ny\xda\xc5D\x18L\x82\xa2\xec\xd55\xa9K\xe8ս\xd5X\xc6\x12+\xfe\x9aHE\xe5\xf3\x91}[Z\x8dx1YI\xa7\xf4\xa0\x95\xde\xe6Eɲ\xad\x1a\x06w\xa1\x92\xfd\xedn;Һ\x8f#\bnmx9\xaf\x97]\x1b\xcfm\x8e\xafÛ\x91\xeb\xf5z\rO\xf34%\t2\x98K\x9d\xea%\x91i\t0X\x14\xadv<\xe0-\xa7\u007f̞ZTM\x9cJ[\x8eu\xf5\x88%+\xc5>\xd4\x1ah\xeak&\x1f\xb6\xac%왆\xc1nz\xb7Qm\xaa\x18\r\xca\xda\b6\xf9\xee\x0ens\xa0\x8a\x88\x9e\x04\x19\xac\xa4N\xf9\xeazGFF\xfa\x1a\xf5r\xf2&\x11+\xc9*a\"q\x067c+}b\xe52q8\x85˸\x1et\xe7\xcdJEY쉆\xc1}\x8e\xf42w\xb7\x18\xc5\x10,\xea\x1a\xacl\x0e\x18\x1c=\x892\x98\xd1\xd1*\x9eq\xfb1<@\x98\x13\x893\xb8M초\xc4`\u007f\x1d<܆EMsT\xb6zs\xf5\r\xc6uQa&J\x8b.\xd7]\xc7`n.\x18\x1c5\t2\x98K\x9d\x1a$\xf4\xd4\x0f\x86\ti\x9a$\x82\r\xde\xe87\xd8\xca\f\x96\x8fE4\xa3A13\x87|g\x14\xea\x1b\xdcU2\x10U\xbe\x00\x00\x1e\xa0IDAT)\x92Z\xc3\x16U\xfa\x9b\xb26\x82\xae\xc1u\xaa\x8ce@\x9b\x04\x19̥NQ\x12S\a+\xcaذ\x80#s\x83\f\x1eJ]\x82\xab\x82\x91\xdctQt\x10\xa3F\xb2\xf4\r\xae\xa6\x01@b\xee\x1a1\n\x94\xb5\xd1g\x1a\x06\xe7\xe6\xe2\x8fv\xb8\xfcV\xc0\x8f\xa1\x06k\xa6NaF\xfa{\xea\xfbCn\x05\x9ed\xd8\xed\xc5]%\x16/._r\xec۶堔\xfa\xde^{\x8d\xaf\xd9\xd2\xe3[\x96\xdbG\xce\xc9\xe5Է\xe6\xa5t\x10A\v\xdd\xdbf#{M'\x9fE\xc5MV#[\xb5\xa7\xb5$\xccߕ\xe1\b\xacM\x1c\xee\xf4z\xad%\xde\x0e\x9fzs\xb0\xc85\xad\xf3m0\x06G\x81\xa1\x06k\xa7Na\x99\xc8ܦpKN\x02\xf4\xf6\xe2\x1e\x92 U&\x8a\xa7sm\xa9y\x1b\x10Z\x93\x86PS*\xb25\xb3\xf0Tr]\xc4\"\xb2\x95#5\x19V\xfb\xb2\xfaY\x96\\>\x8b\x8a\x9bḽvX\xd2r\xa3\x128\xb0\xb62\xb1+\x99\xf5\xe0Vo\x8ex\xb1\xccn˝\x94s%\xd3\x0eC\r\x06\x80\xb8\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b\x13\x18\\\x88\xec\xcb\xe1\x961@\a\x13\x18\xdc\xef\xadϴ\x1b\xfe\x17?\x01\x93`\xb4\xc1\xa1\xa9SA\x01T\xdaK\xa1n\x11\x00\xb40\xd8`\x8d\xd4)u\x00\x956\x93\x94+\x02L\x03\x8c5X+uJ\x1d@\xa5\r\x18\f\xe8a\xa8\xc1\x9a\xa9S`00\x11\f5X3u*\x1a\x83{\xa2\xbb\xff\f\x98\x81\x18j\xb0\xa8\x95:\xc5\aP\xe91l\xcf\xe9\xe8K@&\n0\xf5I\x90\xc1\\\xea\x147\xa9O\x1bBhQ\xb8\x06\xc0L%A\x06+\xa9S\xaaI=|\xf6\xf4\xda\xf6\xc8\xc5\x060\x03I\x94\xc1\x8c\x8eV\xad\xc9P:Q{\x98W\x81\x99L\x82\f\xe6R\xa7\xb8I]\xe0X\x04\xa0G\x82\f\xe6R\xa7\x82\x03\xa8\xb4\x00\x83\x01=\f5X3uJ\x1d@\xa5\r\x18\f\xe8a\xa8\xc1کS\xaa\x00*\r\x86\xfb\xbb\n\xad\x86G\xb3\x02&\xc1P\x83\xc7\xc7\x12\x84\xd2\xc3\xed\xe6\x013\x1a\x13\x18\xdc\xdf\r\xc7\xd1\x00]L`0\x00\x84\x01\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807F\x1b\x1c\x9a:\x85\xe9m\xabo\xee\n\xb3\x10\x00\xe8b\xb0\xc1\x1a\xa9S\xe2p\xbb\xbb\xf3L\x97\xfbL\xb8\xe5\x00@\ac\r\xd6J\x9d\x12\xdb\xeb\xfa\x89\xda\x10\xb0\n\x8c\aC\r\xd6L\x9d\xeaw\xd3;\xe4 ^\x15\x18\x17\x86\x1a\xac\x99:\xd5Y\x17.w\x15\x00\xc2c\xa8\xc1\xa2V\xeaT\xab\xa7\xb75R\xea\x14\x00\xe8\x91 \x83\xb9\xa8\xa9f:\xd9\xd4\f#10\x1e\x12d0\x175婋\x9c:\x05\x00z$\xca`\x06\x89\x9a\xf2\xb2\xfb\x90\xbdp;20\x1e\x12d0\x175\xd5U?\xc2\xcd\x01\x80\xd8H\x90\xc1\\\xd4\xd4\x10=\x9a\xe6\x93\x0f\xb3\x01@l\x18j\xb0f\xea\x94\xd8U\xd7\xd5\xd7\xd3\xd8\n{r\xc0x0\xd4`\xed\xd4)\xf1Lk\xfd\xfe.\x10\x18\x18\x17\x86\x1a\f\x00q\a\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0x*0\x12\xa9\x01\xa0\v\x18\x9cp\xfaK\xd2ВH\x8d\x00=\xc0\xe0\x84\x93\x99\xe9n\x87\xbf76n\x8c68$uj\xb8\x91]r\xe9n\x8a\xb0\xe4$s\xbc\xe8X\xa4&\x93C\x0fj\x8b\xd4\x04\b\x83\xc1\x06\x87\xa6N\xf9\xdc]d\xaa\xcb\x1d\xe6/\x83{\xbb\xf4_\x8b\x17\xc7\xf2\x8fDj\xa2A,[\xa6Ӷ\vuh\xce\a\xa2\xc3X\x83\xb5R\xa7\xd8]ˍ\xe1~\x8ds\vü\x18/\xaeDj\xa0E,[\xa6\xd3\x16\xfe\xea\xf9\xc40\xd4`\xcd\xd4)\x8ag\u007f\xb8{4f\xc7\xe0\x89\xb1IJe:m\xc1\xe0\x89\xf1g\x1b\x00\xc0\xccL`\f\x06\x80)\x00\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xccMX\x83\xeb\x11O\u007f\xb8\xa6\x00\x90\x18\xc0`\xc0܄5x\xf4\x1aa.\xaa\xa6\xff\x8e\x86k\n\x00\x89!\x8a:8\a\xd5DjbjJJ\xf8gː\xa8\xd7P\xcdU\xbb\x9b\xfd[\x9e~{\xa6\x9b}\xbc\xdbsli\x85C\xfa\xcb,B\xa3Ѯ\xe0Z\xa5\xc3⨼\x86\xa7jr\"\xb5\x9dр\xc1]\xd6a\xfei\x94\x82I\xa3\xf3\x115\xf8j:*\xac\x9e\x8b\n\xc9\xf46\x94Q]\x92\x92\xea\xd3](z\x83G\xb3Pn\xf5|\x94uC\x92n\xa4\xd5Gj=\x93\x89\xc5\xe0F\x94\xc9&jP\x99Ԅj\x86\nSSs<l\xd6\xc5\xf2t\x8b}I\xb7v\x0f\x9aT\xa2\xe4v\x9d\x97.ZȚ\xbc)r\x01\x9e\xe2\xd5iǓ\x89*#5\xd1d4]\xbdܵh\xfc\x92$1\a1\x83+Q\xabD\xbc\xc7o\xbd\x0f\xe5b\xe1:\x91jLWA\f\x8en\x05\xfbQ9~܀\x1a\xf1c\xbd-\xaaEf(\xb1\x18|Ղ\x06\xe9D\x06\xea\xc5\x06\x17ڬy\xb9\xc9h\r\x99\xd3mC֬t\x84\xb6\xe9\xf6\x12\xa0\xa7\x8f\xfd+\xf6Zj\xf5ڜ.\xb3J\x92\x1b\xf5\xf66\xa3\xc6\xde^\xa6J\x04\xc6k\xb0\a\x85\xf9\xd6\xd7e\u007f*\xcac\x9bU\x92E\x1e\xdb\x11~/k\x10\x1d}+\xf5\xbf\xb2\x88\xc1\xd1Q\x89\u007f\xc4\xe43Q\x86\x1f\xaf٢\xf8\xb1\xceXb1X*d\x86\xf6\xa1t\t\x1b\x8c2\xf0/\xac\xcfNƠ\x8b\xa9\xa8\x12\x0f?=v\xa47\xac*\xe4\x04\x86(\xab\xae\xc1R-6\xb8\xd1\"Ig\xd0iI\xb25\xea\xb6S\xf0\xb8{\"5\xd1$k.\xfd\xa76˖\x9a\xd7%\xd1*\xe2\x8c\xff\xe8\v\xee\xf1Zu:.G\xaf\xe2\x17\x1c\xfe\xb9\x1b\xf1\x93̌\x9e\x0e\xfe\x83UM\u07b8}\xae\xd6\n$\xa9\xbf\xc4aI\xcd픸*·2Ͷh0\x13W\xb8\x85i\xbe\xe5vkNW\xd0\x1a\xdch\xbfD>\x18\xf4\a^\x92zC\xbbg F\x83;\x88\xba\xe4\xbbm\x1b5\x98\x1e^k#\xf3*\xd1\"\x89=\xc9\xd0\xee\x83#j\x83G}\xb2\xc1\xbeh\a\xaeq0\xc8\x1cو\xe6W\x97\xa7\xa2.j\xb0XO\u0600\xec\xa2t-\x13\x97\xa3˓ӱ\xc2e\x852\xa4j\xe8\x1e\x95\x14\x83\xaf\xf5W\xa3\x9cQ\xe9**'uղ\xe02\xf8\xcc\xed\xb65\xd5\xcbRH\x9d\xe17ؗ\x86\x96T\xceJ\xb5\x13\x83mi\x8bZ\xdd\xf6\xe4~\xf5\x1a\xae\xa6\xa7\xb6\x0ez\xec\x0eZ?xP\x87\x04\xe8\x10\x93\xc1\xa3\xa9D\xa8\xd14\xf2\xc5ۄr\xd9<+~\xe6@\xacT\xbd\x91\x8c\xe4\xdf\xdfh\x9ae[\xba\xa3g\x83=\x8f\xecNK\x9e\\[\xe6\xc6\x1b\xe43\xc0\xa0\xbb\xd7\xd6ꍙ\xb6E#\xb4\xfd\xfe\x1c\xdb\xdc\xfdtJ\\\xe3\xb0/'U\x04\x81\x1aLjKR\xa0\xd4\xe2\xc7\xf6J\x94\xd2T\x9en/d\xeb\xf1\xf7;n\x9a\xa9\x1c7R\xf2$b\xf3\"eO\xeeFV\n\xfe\x1e/\xa7\xef]\xb3\xb4U\f\xaeDȁ\u007f\"\xfdhIj\xfa\xf2,d\x0fR8\x0f\x91\xba\xc9K\n\x02\xbf\xc1\x85\xa8\r\xaf!\x97\xfc\x18\ni\xa1\xd0\x15R\x03\r\xcf\xc2\xef\xd6\xc1\xba\x1aD\x1b$@\x87\x98\fƿ\xd0J\xf2\xd3&ߖM\xfe\x9fj\x16꼆PV\x0e\xc5B\x861JO*ژ\x87\xecn\xba#]\x96\\\xd9ٔ\x86ǩ\x1b\xbd\xbd\x99y\xbd\xbd\xbd\xf47cEYm\x1di\xcb\xc9d\x99u[\xe76+\xf9]\xfaR3=\x1d\x8b\x90\xda\xe0\x1b\xbd\xe9\xe5W\xa5\xab5\xa9\xbd7\x86\xdaR\xd0,w\xed,\xdb \xdf\xef\xb8)\xa3\x1f\xb9\x1bɳ\x88\xb7d\xb0\xf7\x1b\xbc\x8c\xecD\x8d\xdeN\xbft\xa4\x9c\x94\xd0O\x89bpWG\x8d\xcd\xd6+\x9dFh\xd9(\xd9\xcd]\xa2n\xd8Iwv\xaf\x92ٲ\xc1ג\xe9'\xb8\x8f\x19L\xde\xe15\x94\xa7^h(ͺѳ\xd1\xca\x14\x1eMΕ\x00\x1db3\xf8\fJ\x1b\x95V\xd2\x1d\xe4&\xff^[\x0ej\x13\x91B\xa0\x10v\xac\xc1cW\x87TVN\xc60\x0f]\xb8\x8d\xb6W\xaa\b\a\xf9rN\x93ȇ\xa2\xcb\xff8?\x03\xcb2:Wm0.+\xc8L\x8c.6\v\x0f\xeb\xd7\xd2s\x83\xfa\x1d\x1fK\x10\xa9q\xb1Ȗ\xf9n\xba\x9b*\x1b\\C\xf7P\xfbQF\ra6:#\x95-\x91ieK\xaa\xea\xe0^\\>\x9dA\x16\xd2\xd7\xe8\xac\xe4k\xeauHW{=\xd59d\x80\x97\r\ue875\xb4$Y\xa8\xc1d}\xa3h\xbe\xa4ZC.):p\xb7\xecXpj\xe4\xe2l\xc6\x12\x9b\xc1R\x06\xea\x19\xb5\xa5\x90_T\x93\xfc[\x902Q\x17\x1e\x83Cw\xe8\x1dm\xf8wzC\xaa^)I+3F\t\xe9T@\xce`r\xc0\xa8\x86\xb8ZFw襬2<\x18QA\xb6\x05\x1b<\x82\x06q\x11C\x8f\xd6Y\xe9G\xa7\x19]S\xf7;>r\xd9с\xd1\xc6,\xfc\xe9\xcb\xea\xf3\x1b܁\xe6\x92\xf9\xbd\x81\x0ff\x97zON\n2X\x9a\x8b\x86\x87䃍\xcb\xe5#6~\x86\x97\x93z\xa0\x843\xb8]^4\x9d\x1aL\xb5'\x06sk\xb8*\xab\xbb\bу\xd5\x0e\xbb\x04\xe8\x10\xa3\xc15\xa8\xb2\x8b}K6\xc9\xdf{7,\xf8\x87\x1c8\x06ѣ\xecu9\xba\xa43\x16\x89\x1a<W\xfe\xcd,\xa3\xdd)\x06\x93~\xc9>\x9b4\x9f\x9e\x10\x90\ns\xf17k/]O\xb0\xc1Ғj\xa9\xcbN;g;\x80=\xb8\xbaT\xf5;>\x98@\x04ѳ\x04\xd9o0\x83\amvjN\x1fZ\xa9\xbb$3\xf8\x86\x87\xed\x01,A\xfd\xa3\xc9l\xa4\\\x8eT\x85\xf0h&\xaa\xec\xc5%\x10gp\x97\xfc\xfd\x95\xaa6\x98cH\xae\xbc\xcb\xf1\xe0\x8f\xb19$@\x87\x18\r\xbe\x88\xd2+\x99\xadM\xc8r\x91\xfcیf\x93/a:d\xe1\xafu\xab_\bj\xb0\x95\x19\xbc&\xa3\x8fB_\xa3\x06{\x88 TEjp\x19\xfb\xddg\x94\xe1_4ݟ+\v1\xb8#m\x94\x15\x11\x92\x95\x0e\x82\xadx\fV\xf5;>\xca\xe9\x80髦\xe5{!\xfeT\x10\x83\xaf\xa6\xa7\xb0Cs7,\xe9\xf4}5\xd6\x06\x17\x06\x01\x83-T\xaeQ\x87\xe5\x1a\xfeA\xd1\x02$#UU\x97\x9fa\xe7\xebz\xc9'^6Xd\xbe\xfa\x90\xae\xc1\xd7\x10\xfbV\x9a\x8fF\xe8\xabP\a\xeb\x12\xa3\xc1\xf8[\xd7\xc6\x0eN6!4\x1bk\xd8i#\xc5\xeb\x90\x15\x95\xe1\xdf\xf1i;=\x93\xc4\xe0\f\xeeb\xd2o\xa3ߝyyd\xb7\x86\xccP\f\ue925l\x1b\xea\xc4+H\xc7\x1d\xf9n\x0f1x4\xad\xc3\xceN\xf9Y\xd3ȩ\u058c<u\xbf\xe3<\x1e\xdcL\x8f\xa2\x88h6\xb6ntv\xf2U\"\xd8\xe8|\xe4?\x02\xbd\x92\x8e\x96\xbd\xc9\x1au\xa8\\E,\xa7\xffT\x93\xc1\xdaC\xf7\xe4\x1a\xc9\xde\xee\xe8Հ\xf2\xfdT\xbf\x1b\xb9\x9c\xc1x\xc4\xc6k\x1d]\xa2o0nA\xaa)/S\xb7o\x9cgkf\x04\xb1\x1a܊\x10\x1b\t\x9bЬ\xdbSf\xcfB\xecE\xaf\x15\xdd>\x17?\xc9\r\f?C\xf6\xfa\x1bm\x96\xfe\x1b+\xf3F\xe8/\xb8\xbd\xa3\x8c\xedq\xd5X\xeb;\x16\xd9DrN\xae\xec\xb4\xd4Wf\xe9\xc5#ך\xe4\xea\xce\xead\xb2\xf34hK\xaf\xddfON\xf1\x90ʺ\xaf\x195ʧ\xf0\xa4\xea\fVDHV\x94\xd3ޚI\x8fYq\xfd\x8e\xf3\x9c\xdcEvHe#\x9a\xb5ac\x16)q\xb1`5\xc8QS\xbd\x11\xd3A\xaez\xc8ٸ\xd2z\xbb\xffs\xc4!\x1b<\xec@y\x1bsP&\xf1p\x19ʪ^\x82f]%\x9f\xbc\x1c\u007f\xbb\xd1\xd9h\x91\xbbڑ\x99\x96\xc5\x1d\x0fNEK*3\xec\xc4O\x1d\x83\x87\xd3\xd0\"\xdc\x17;2\xd7\bǃ\xf5\x89\xd5\xe0kVV\xa8\x92\xb3\xca\xfd\x8bl\xf6E\xf2\xc8\xe7+O\xb7\xd8\xe6\xd6\x05\x04\x1eMC\xa8-\x15\xd9\xdaY\x95ڕg\xb7\xcfg\a\xdaF+\xed\xb6\xbc3\xf4(*\xb2\f\xda\xf0#Q\xafy\xaemn3\xeb\xa9\xd0>\xabړB\xe6\xdeHů\xda\xe4\xd1\xcc\xe7\x1f߭\x1b\xcbR\x1dk\xd81/\xa5\xdfq\x1a,e\xd1\xe1ut\xff\xdcT\xdb\\v\x85\x83X\xe6ߣ\xc2=^ݘnq,W\xef\x9a1\xfc{rbY\x9a%\xbd\x9an\xe4h}\xa6\xd5QN\x8c\xe4\f&\a\xb8\xad\x99\xb57\x96\xe1\x82 pNn\xa80նd\x88\f\xcb:\x06Kb\xb9ÒV\xc6.:Z\xa2\xaeK\x00\x9e(\fV\xe1c\xa7\xe5\xa8\xc1\xe1[ƛ\x1bV\xf9\xc3\x12\xe6T\xde8\xf0\xb0}\xa5x\xd3\x1dt|W\r\xdb\xdf\x15Qt\aQĔm\x91\x9a\xcc`b5\xb8\xc6? \x1bnp\xbb\\D\xc4\xd9\xe0\t\x1d\x8bӧ,\xec\x15\xa9v\xba\x83\xb81\xca\x03ٵ\xb6\t\xec\xaaN{b2xh\xb8\xfdv\xab|\xa5\x9f\xb1\x06\xd7\xf6H\x8b\xfcN\xc4\xd7`ɛ\xa2\u007f=︹X\x18\xf6Tw5\xca\xd8X\x9d\x1b|\x1eN\x87k\xf6h\xae͛\xb1\xc4d094\xef\xf7\xc8P\x83o\xa0\x9cJ\a\xab\x87\xd9\x0e`<Y\xbe<R\x8b\xf8\xe3\xc9I\xb5e\xd5FW\xddn\x9b\xc8Y\xf3\xe9OL\x06\xd7\xd9\xd2\x02_\x8e\x86\x1a,դ\xe6\xc9#%\xdd\x01\xbc\x18\xbe50\x83\x88\xc9`\x00\x98r\x80\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\xcd\xd46x\u007f\xf0\xfd\x0e\x9a\xb8\xc3\\\x03\x19\x1d\x17\xe1x\x95i\x01\x831n[\xe8œ\x80I\x98\xda\x06\xf7\xbb\xa3\t;\x99\xa8\xc1\xa3\b\x81\xc1\xa6ej\x1b\x1c\x1d`\xf0L\x06\f\x06\x83\xcdM\xdc\f\x8es\f\x1a\x83\xd6\xc1M\xc8=\\\x96v{\x16\xee\xbe)ӚVNlS\xa5\xb6\xc9\x06s\xd1mZ\x8b\x045\xa8\xbdZ\uec24o\xbc\xca\xceS\xd3\xf8\x16_Y\xba%5\xa7~\xc2{u\x1f\n\x98\xbda\x1a\x1c\x15\x84\x13a^\x06ba\xc2\x06OR\f\x1aC6\xb8̎Ҭ\b\xb5\xafA\xb7\xa7!z\xe3\x8d*\xb5\x8d\x19\xccG\xb7i-\x12Ԡ܁R\xed\beސZ\x97!T\xb8\xec\xa24\x98\x8a\xecs3P\x94W\x8c\x85\xe1O\xef}g\xfd\xc0\x17a\x1a\\\x1f\xa8:\x18\xe6e \x16\"\x1a|5/\xfcũQ\x87H\xc5\x16\x83Ɛ\rF\x99\x83\xd2\xe82d\xbd\xdd3*\xb5#\x12\x81\xa3Jm\xa3\x06\xab\xa2۴\x16\tn\x90\xd1+I\x1d\x16rc\xa9\\E,A\x1b\xf1\xf0ۗ\x1a\x87[z\xb6l\x89\xd0`;\x18\x1c/\"\x1a<\x88\xb4n\xb1Q\x88\xda\xe0\xf1Ġ\xf9\r&\x9b0(_ٙC\xa4S\xa5\xb6Q\x83U\xd1mZ\x8b\x047\xa0\t\x17e\xe46\t\xd9\xe0t\xd6e\xdd\xf2Ni\xa2\x80\xc1\xc6\x11\xde\xe0\xa6\xcc\xce!\xe4\xeb\xccܟ\xa0\x184\xd9`z+\xdb\rY\xdae\xa8NR\xa7\xb6Q\x83U\xd1mZ\x8b\x045`\xe9$u\xe4\x1aQ\xd9\xe0<\x94\xd3\x1b\xfc\xe1\x1a\xd8Z\xea\\\xb1\xbdtLz\r\x97\xb6\xff$\x1dď/5\b\xce\xe7\x1f[\x9b\xbf\xf5s\xda\xe2\xb3\xfbW8\x8b\xb6\u007f\xae^\x8c3x\xechE\xfew\x8e\x8e\x05\xb5\xc5\x067\xe0\xbe\\\xd7q\x83\x13U\x8b\xd7>\x86\x1b|\xe8\x14\x84\xa7?\xd9uw\xfe\xd6?I@Ԅ7X\\\x83\xb2\xf0\u007f%b\x82b\xd0d\x83ie\x8a=\xa3\xb7\x87\x94\x90:\x9aOm\xa3\x06\xab\xa3\xdb4\x16\tn\xb0HY\x81lp\xaf\x05\xa1\xd4e\xad|\xd1\xf4\xc1\x82\x87O\x9d}~\x85\xf0'il\xa0\xf4\xfb\u007f\x94\xfex\xb0`\xe0\xe6\xefO8\x85\xa2\x83\x87\v\xee'-\xce-\xae8|\xf6\xa0\U0002c9023\xf8a\xd7ӯ?\xed\xda\x1b\xd4\x16\x1b\xfc\xf9.\xe1\xd9\x0f\xf1\xe4^\xa1\xe1\xf5\xa3E\xebǤ\xb1\x97N\x94\xae*(}lׂp54\x10D\xa4*\xa2˂,\xf4^\xe0\x84Ġ\xc9\x06\xd3k\xe9\x83\fVRۨ\xc1\xea\xe86\x8dE4\x1b\xa8\f\x96\x06Kȝ\xd3)eʗ\xc0\xd1\"2\x1c\x1e]J\x86Ѓ\x15\xf8\xe1a\xaa\xa2k)\x1eGw\x15ᩱҭ\xf8\xb5\xb1\x97\xaeK*\x14\x83\xcf\ng\xfd\x8f|[l\xf0\xb3\xae\xd7H\x83\xd7\xe8a\x89\x0f\xd9\xc1\x89\xf5\u0096\x9b\xd2\xd8M\t\x88\x9e\xf0\x06_\xdbhIG\x0ek\xf5\xd5\x04Š\x851XIm\xf3\x8f\xc1\\t\x9b\xc6\"\x9a\r\xd4\x06㩞mY\x88;\xba\xfcE\xf1\xdd\r\xcf\xffn\x8c\xd6\x00\x9f/\xf8\x9d4V@|\x94\\\x0f㇃.\x89\xa8\xf9;I\x03\xc5\xe0\xbd\xeb\xe8?\xeb\xf6\xaa\xdbn?\xf8\xb4p\x8aN=x\xf7؟0\xa5\xf4\xa3\xb1\xde\x05\xc3o\xac\x847\u061d\xb6\u007f\b\r5\xa7\xb9\x13\x14\x83\x16\xc6`.\xb5\x8d\xd6\xc1\xaa\xe86\xadE\xb4\x1a\xa8\f\xf6\xb1 \x8cF\x94\xa2\x941\u05cf>\xb8VXq\x98*\xbc\xf51\xe9,\x1d\x8d%\x17\xd9\x0f\xa3\x06?+\x8cI\x1a(\x06\u07fb\x9d\xfe\xb3\xbdJ\xddv{Q\xc1\xda\xfb\xe9\xd3\xf5\x02\x83\xd6$\xeb\xab$ F\"T\x11\xa3\xf4X\x04\xf9\x8d&$\x06-\x8c\xc1\\j\x1b5X\x15ݦ\xb5\x88V\x83\x80\xc1WIz\x03k<\x84\x92\x03\x06\u007f\xf88\xb6\xec\xfa\x89\xfc\xa3\xe4ɩ\x15c\xac\x88\xe0\f>+|(i\xc0\f\xbe\xf9\xf4ui\xef\xdd\xc4ӱ\xbb\x1fV\xb7\xdd^\xf4\xf1g\x05\xb4x\xdeu\xf7\x87\x14Z\x87\xac\xbf_\xa33 ,\x91\xea`I\xb4\xb3\xdb\xeb\r\x8eAc\x841\x98Km\xa3\x06\xab\xa2۴\x16\xd1j _\xfcfA\xed7F\xa5<\x94\x87[_[Ɲ\xd28H\xabXi\xcb\xf7\xc9\xe3؊SK\xe9S\xce\xe0\x9b\xc5[\x88\xa1\r\x8f\xd1\xf9\x9f\x1d\xfe\x8c-\xc7\f\xfe@\x18\x90^\xa7\x05\xee\t\xe1uu[r4\xed\xac\x93\x18}Vx\x89\xb4}\xf20y\\\xff\xa0\x04\xc4HD\x83e\x8c\x8eAc\x841\x98Kmc\xe7\xe4\xf8\xe86\xadE\xb4\x1a\xc8\x06\x93\xf2\xa5K\xf2ّ%3ˆҔ\xfc\x88\x83\xc2⃯\x9d\xda+\x9c\xa3\xcf\x1e\xbf{)ٱ\xfb\xd7\x01\xe7\xde\xf7\xc6>\xd8\xeb\x1c\xf8WI:\xe7Zw\xf4l\x83\xf0<mp\xbf@k\x86?\xfd\xbf\xef\xac\x1f\xc0\x1c\xc5\x06K\xbb\x84\xc7_{\\\xd8E\xe6\a\xda^\x1f\xa8\xc2=\xdc\xdc^|\ue3f8\xd7\x05\x0f\x9e«8\x81\x17\x1bXu\xef\xc0\xc0g\x12\x10\vQ\x1alx\f\x1a#\x8c\xc1\\j\x9b|]\x04\x17ݦi\xb0F\x03\xd9\xe0\xa1\xdc\xdbS\xdb\xc8u\x13\x19\x96\xdb3\xab\xb9\xc3i'\xee=X\xea,\xde\xc2\x04\x96\xfe\xc0.v \ar\x9d\xbf[\x8c\x1f\x1b\xc8\xcc\aK\v\xaa\xd8N\x99\xf4|\x11-7>\x96K[!\xff\x13r<x}\xfez\xf9x\xb0\xbf\xedQ\xf2\xe2\a'\xf0\xc3\xd3x\xee\xd9-w.\xbd\xf7\xac|9\x85\xc0>\x04@\xd4Dip\xfc\x99X\f\x9a\xb1i\x1527]\xe7\"5\x01\f'a\x06O,\x06-!\x06\xbft'\x9c,\x9bz$\xc6\xe0\tǠ\x19o\xf0\xc1sc[\xe0b\x86)HB\f\x9ex\f\x9a\xe1\x06\x8f\t\x15\r\xc5Agހ\xa9@B\f\x9ex\f\x9a\xe1\x06K\a\x17o\xf9$R\x1b \x01$\xc6`\x00\x88\x17`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807\x86\x1b|\xaaꏑ\x9aL\"\xd7\xef=\x15\xa9IT\xd0w\x11\xaf\u0380\x8901\x83\x1b\x04v\x87\x81\x06\x9f9\x85\xb5\x1a\xb3\x0f\v\a5\xef,\xd3%\xe2*N9\xe5\xabq\x9dQ\xf84vX8\x1c23\xf6\x9c3\xf6.4;\x03\ff|\x06\x9f\x93\xef\xf8\xfa|\xc0\xa9w\xbd\xd6\xd8{{]\xa1s\x8fF\x1dy\x17\xf5*\x0e\v\xe4n\x88g\a\x06\x16D\xa5\xd3\xebΣ\xc1\xb3b\xce9\v\xbc\v\x8d\xce\x00\x83\x19\x9f\xc1U\x81\xfb\xb9\\\xfaW\x1c\x1e\f5\xf83\xe7\xe3\xfe\xc9\xeb[\xc2_\xe9\x15\xf5*\x9eu\x92Q\xf4=I\xca\x0f\x8a\x1d\xd1\xe1iWP\xc0\x8e\x14kJ\x14\xf7.\xb4:\x03\fe|\x06\xaf\x8fV\xaf \xf6\x16\aJ\x88\x8f\x85\x8fC^\xe6\x89z\x15c\x9f\xc9\x06\u007f\x16]yr\xb38\xb4`\x88\xcd`\xee]hu\x06\x18J8\x83\xff\xb4\xc2\xf9O\xa5\xc5\xe7\x1a\x96n!)2\x81|\xafSr\xddI2l$\xd7c\x81\b1.!\xec\xf3]\xc5K\xef\x0f\xad\"\xc6\n\xe4\xc1\xeb\xe8\xaa\xd7>\x11>y}\xd5\xd18\xad\x82\x1a,\x05\x85\x9b\x1d\xdd[\xbct;\xbd\"2\xd0/\xe5\xe9\xfc\x10\xd5c\xc99S\xde\x05A\xa33\xc0P\u008e\xc1\xe7\n\x84Ƕ\bw\x1e^A\xbe\x9f\x03\xf9^7\a\xe8=\xb5\x03T\x0e\x97\xb0\xf6ĩ\x154\xe6@I\b\xfb\xa4`\xed\xf3\xa7\xb6\n!\x06\x93\xdb\xcf)\x9f\xef\x12\xd6\xe1\xff\xee\xff\"N\xab\x90\r\x0e\n7+=x\xb04\xffc\xbe_ʀ\xf0\xff\xa4 b\xc99S\xde\x05A\xa33\xc0P\xc2W\x11Ż\xa4ׅS4-L\x9d\xef\xa5|\xc5\x17\xfd\x1b6\x84D\x88q\ta\xf7\xae\"{\xea\xebC\f~]\xf8\x83\u007f\xf2\xacSp\xd2\xf0\x85\xb8\xacB6X\x1dnv7\x1e֯\x97V\x05\xf5\x8b?>B\xc8A\x8b\x18r\xceT\xefB\xb33\xc0P\"\x18|BzO\xb8)=\xfe`p\xbe\x97\xa2\x17yN+^%!\xec:\x8bOx:\xc4\xe0S\x82\x1c\x86p\xfd1g\xb1P\xecz\xec\xdfⴊ\x80\xc1|\xb8\x19\xfd\xae?*\\W\xf7K\xa4\v9<\x17C\xce\x19\xf7.\b\x1a\x9d\x01\x86\x12\xc1\xe0\xb3҇xW\x9f\xe8\xa5\xce\xf7R\xeffQ\xbd\x94\x84\xb0\x0f\xd9\xd7l\xe8\x9e\xdc{~\xd1\x0e\xaf8\xfa{\xe1\xf7GW\x1c\x8e\xd3*\x02\x06\a\x87\x9b\xe1o\xf9\x0f\xd5\xfdJ\xfeeyb\xc89\xe3\xde\x05A\xa33\xc0P\"\x1b\xecbz\xa9\xf3\xbd\x88^ϓC\xa8\x8a^JBؿ\t\xf4(\xe9á{r\x81\xc3\nc\xf4X\x04\t\x85\x8c\xcb*\x14\x83\xb9p3\x9a\x04\xf5<\x1e\xdfU\xfd⮜7\xa5 b\xc89\xe3߅\xa4\xd9\x19`(Q\x1b\xac\xca\xf7\"\xbf\xf1?\xd2\x19\x8a^\\BXU)\x96\xe5\x0f\xae\x10\x83\xa5\xfbW\x05\x86\xb5/\x96~\x11\xbfU(\x06s\xe1f+\xb0[7\xef\xde\x12ԯ4\xb664\x15'\x86\x9c3I\xf5.\xb4:\x03\f%\xac\xc1\xbf_\xfa\xec\xd8\t\xe7\xc7c\xbb\xb6|\xce\xe5{IħgOmY\xfc\x85:BLI\b\xfb8\xbf\xf4\xe0\xd3K\x05\xe7\x89\xdf\au\xf8I\xc8iظ\xac⃣\xf2a\x02)\x10nF\x0eaT\xbc\xf4\xfc\xaa\xa5d\xaf\x8b\xef\x17\x17\a\xca\xd0ʈ-\xe7L\xf5.B;\x03\f&\x9c\xc1c+\x04\xe1D\x81\xb0\xf8%VB\xfa\xf3\xbd\xc8+\rK\xf3\xef\xfd0(B\x8cK\b\xfbd\xfbһ\x1f;\xe1\xa4\xc1b*\x9ev\xa9\xcbƸ\xacb\x8c\xbc\x9a/\u007f\x9b\xff\xc1\u007f\x85\x83뱽\x05Ż\xfe\x95Ns\xfd\x0e\xe4?&\x05\x11c\xce\x19\xf7.4:\x03\ff|\xe7\xe4\xc6\xcdX\x83s\x92\xf7\xdd\x03\xe1fڧ\xf2^r\xee\x9dxt\x94\xff]ĥ3`b\x18l\xb04\xf6l\xe9\xf5Hm&D \xdcL\xd3\xe0\xebŇ\x95\x03\fㇽ\x8b8u\x06L\b\xa3\r\x9e\\\xf8p\xb30\x97S\x00ӈie0\x17n\xf69\xdd\x01\x8c\xd0\x1e\x98\x06L+\x83\xb9p3\xba\x03\bq\xe83\x80\xe9e00\xf3\x00\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb91\xdc\xe0鑛\x16\v\x113\xd6\xe2\xf4#I\xc4{\x9b\x02L\xcc\xe0\x88\xa1f!L\xc5ܴs\v\x84{\xc7HFł\xb3\x1a\x8b0>\u07ba\xb8x\u05f9b\x95j{\xe5K\x8aՓ\xc1D\xccX\x8b\xfeGr\xb6(\xdc[\x9c\xa11n\xe338\xeaP\xb3`\xa6dn\xda\xd8Y!\u007f@\xbayJ8\xabk\xd2\xd9\xc5UϟX/\b*I?'+~/x2\x88\x88\x19k\xd1\xffH\xa4\xd7\x16k\x18\xec\xffAI34\xc6m|\x06G\x1dj\x16\xc4\x14\xcdM\xbb)\xecڋ7Nнi\xf3z\x01\xb9Q\xf9\xe6*!x\x98Un\xd0\xe3'9\"f\xacq\r\"\xa3\xf5\tS~P33\xc6m|\x06G\x1dj\x16\xc4\x14\xcdM\xbb)\x9c]<\x16\xce\xe0\xc7\xf3\xe9\xddJ\xcf\xc6npČ5\xae\xc1\xf8X\xcf\x19<\x13c\xdc 7M\"\x06\u007f\xb6\xfe\x145\xb8\x81$\x05\xd3\xfaZ\xb5e\xab\x1e\xa6\xed\xae?;&\xdd|\xb0\xd8Y\xba\xdd\xffͭe\xf0\xc0\xd6R\xe7\x8a\xed\xa5t%\x113\xd6\xfc\r\xf0\xf6>\x1fx\x9b\x01\x94\xcd\xc1+\xcf\x17\xe4\x18c\xae\xad\xea\a%\xcd\xc8\x187\xc8M\x93\xa8\xc1G\xb7S\x83i\xd5\xcd\xeakn\xcb\xc6\x04\xa5@yM\xd8{\xee\xa5\xed\xfe[\x945\f\xfe`\xc1ç\xce>\xbfB\xa07;E\xccX\xf37 \xdb[t\xf0p\xc1\xfd\xaaW\xb9\xcd\xc1+\x18\x18`_G\\[\xd5\x0fJ\x9a\x911n\x90\x9b&Q\x83\xaf\xbb\xae\xb3*BI\xa7P\xb6\xec3n\x89\xb1\x97n\x92\x15\a\xf2\u007fB\f>ZD\xdc=ʂ\x83\"f\xac)\r\\K\U00058eab(\xe8ues\b\xf9\aC\xdb\xf2U\xc4L\x8cq\x83\xdc4\x89\x1a,m\u007f6\xc4\xe0\xc0\x96\x8d9\xb9\x9d\xc4\xebG\xb7\xde] \xacgO4\f\xfe\xa2\xf8\xee\x86\xe7\u007f7\xc6\x06\xfc\x88\x19kJ\x03\xd7Òƾ\x83\x8e\xc1\\\xdb \x83CW1͉\x9c\xd9\xe3\x9ch\xa8\x99\xc2T\xcdM#\x06\x9f\xfaN\x88\xc1ʖ\xc9u\xf0\x18\xfeh|XT\xfa\xf8\xa9\x81-\xeb\xfd}\x85\xd6\xc1\u05cf>\xb8VX\xc1nc\x8e\x98\xb1\xa64P\xbb\xeaG\xc7`n\xae\xca\xe0\x19\x18\xe3\x16\xd9`\xd7DC\xcd\x14\xa6jn\x1a1xl\xf1Y\xc5\xe0\xa7\xfd\x06\xcb[\xf6x>]\xf6%\xe1\x8f\xd2\xda*\xb2\r\xf7\xafgKj\x18\xfc\xe1\xe3\xb8\xc1\xf5\x13\xf9t\x03#f\xac)\r\xc2\x18\x1c\xf86\xd35\xf8y\xf9π\xcc\xc0\x18\xb7\xa8\r\x1e\u007f\xa8\x19\xc7\x14\xcdM#\x06K\x0f\xef\xa2\x06\xe7\xe3\xe2c\xac*\xc8`v<xl\xcbݒTJF\xf2\xb1\xef\xacgKj\x18|\x90\x16\xebҖ\xef\xd3g\x113\xd6\x02\r\xb4\rV6\x87>\xd30X\xf9A\xe9\xadbz\x03\xb9i\xf4\x9cܩ\x9bҹ|j\xf0\xbdE\x87\x0fV\x91~U[v6\xff\xde\x13\xa7\xb6:\a\x88\xa0\x0f\x1e=\xb8\x1eW\t\xefI_\xc8'\x03\xf1G\x91\x9b<(,>\xf8\x1a^\x1b\x8b\x0e\x8a\x98\xb1&7P\xbdM\x8e\xc0\xe6Hc\xef\r\f\xb8\xf6\x0e\f\xdc\fj\xeb\xffA\x11fb\x8c\x1b\xe4\xa6\xd1\xeb\"\xf0\x186VE\xcf-|\xb2%\xbf`\xeb?\t\xc2^\xf5\x96}\xbc5\u007f\xc5\xfd$\x11{\xec\xd9U\xae\xa2\a\x9f_\xe5\xdc\"=,\xd7\xd7x\x90\xe6&O\xdc{\xb0\xd4Y\xbcEξ\x8a\x9c\xb1\xc6\x1a\xa8\xde&\x87\u007fs\x1a\xa4\x0f\xe4U\x1c\rj\xeb\xffAI34\xc6m|\xe7\xe4\xc6\xcd\xf4\xc8M\x8b\x85\x88\x19k\xf1\xfb\x91\x18\xfeަ\x04\x06\x1b<Mr\xd3b!b\xc6Z\xbc~$\txoS\x01\xa3\r\x9e\\ 7m\xe61\xad\f\x86ܴ\x19ȴ2\x18r\xd3f \xd3\xcb``\xe6\x01\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01sc\xb8\xc1q\n\t\x1b'\x93\x9b-\x161!\r\x88?\x1338b\xa8Y\bч\x84\xc9D\\\xc5\xc4s\xd3\xee\x15H\x10\xc3\t\xfcx/?;L\x16\x1a\xe5\xa8\x10\x94\x17\x151!\r\x98\x04\xc6gpԡf\xc1D\x1f\x12\x16\xf5*&\x9e\x9b\xf6I\x83p\xee\xa6ts@hЋE\xd3\xe4\xfa@\x95j\xcb\"&\xa4\x01\x93\xc1\xf8\f\x8e:\xd4,\x88)\x9a\x9bvT \xdf\v\u007f\x12B\xc4\xd3N\x92\n\xb0\x9d߲\x88\ti\xc0\xa40>\x83\xa3\x0e5\vb\x8a\xe6\xa6\xc5\xc5\xe0\x88\ti\xc0\xa4\x00\xb9i\x12opP|Y\xc0`n\xc5\xd2g\xf7\xafp\x16m'-\xb0\xc1\xe4*N\x17\xf96\x89\x98\x90\x06L\x0e\x90\x9b&\xf1\x06\aŗ\x05\fVV,\x9d[\\q\xf8\xecA\x9a\xa4\x86\r\xc6\xef\x84\xdd&\x1d1!\r\x98\x1c 7MRW\x11\xaa\xf82\u007f\xbf܊\xc7J\xb7\x925\xbfD\xc6]l\xf0\xb3\xae\xd7Xӈ\ti\xc0\xe4\x00\xb9iR\x90\xc1\x0fK\xa1iVʊ\xb1ƿ\v,\xb7\xfd\xe0\xd3\x01U#&\xa4\x01\x93C\xe4\xcc\x1e\xe7DC\xcd\x14\xa6jn\x1aќ$\xf7\x1c\x95\xf8\xb5IJ\xbfʊ\xa5g\x05\xa5\xc4\xdd^T\xb0\xf6~\xf9iĄ4`r\x88l\xb0k\xa2\xa1f\nS57m\x80FݰJV\xd3`e\xc5x\f\xfe0\xb0\xdc\xf6\xa2\x8f?+\x90\x8f\xe1ELH\x03&\x87\xa8\r\x1e\u007f\xa8\x19\xc7T\xcdM[J\xa4\u07fb\x94h\xa7i0\xb7\xe2\x9b\xc5[\xc8{h \x9f\x0fr4\xed\xacS6:bB\x1a0)@n\x1a\xe1\x84\xd0p\xf6\xfb\xe4u~m\\\x16\x1a\xb7b\xe9\x9ck\xddѳ\r\xb8\x0e\xbf>P\x85\xdb\xde\xdc^|\x8e^\xe9\x111!\r\x98\x14 7\x8d5\xa8Z\\E^\xe7\xd7\xc6e\xa1\xf1+\x96\xfe\xf0`iA\xd5)z]\x84 |p\x02?<M\xe7GLH\x03&\x83\xf1\x9d\x93\x1b7\xf1\v\t\xd3#q\xb9i\x11\x13Ҁ\xc9\xc0`\x83\xe3\x16\x12\xa6K\x02s\xd3\"&\xa4\x01\x93\x80\xd1\x06O.\x90\x9b6\xf3\x98V\x06Cn\xda\fdZ\x19\f\xb9i3\x90\xe9e00\xf3\x00\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\xcd\xff\aڧC\xea]\xae?U\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"callgraph.html": `<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Internal call graph</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Internal call graph</span></p>
+		<p>
+		  This viewer shows the portion of the internal call
+		  graph of this package that is reachable from this function.
+		  See the <a href='#pkg-callgraph'>package's call
+		  graph</a> for more information.
+		</p>
+		<ul style="margin-left: 0.5in" id="callgraph-{{.Index}}" class="treeview"></ul>
+	</div>
+</div>
+`,
+
+	"codewalk.html": `<!--
+	Copyright 2010 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.
+-->
+
+<style type='text/css'>@import "/doc/codewalk/codewalk.css";</style>
+<script type="text/javascript" src="/doc/codewalk/codewalk.js"></script>
+
+<div id="codewalk-main">
+  <div class="left" id="code-column">
+    <div id='sizer'></div>
+    <div id="code-area">
+      <div id="code-header" align="center">
+        <a id="code-popout-link" href="" target="_blank">
+          <img title="View code in new window" alt="Pop Out Code" src="/doc/codewalk/popout.png" style="display: block; float: right;"/>
+        </a>
+        <select id="code-selector">
+          {{range .File}}
+          <option value="/doc/codewalk/?fileprint=/{{urlquery .}}">{{html .}}</option>
+          {{end}}
+        </select>
+      </div>
+      <div id="code">
+        <iframe class="code-display" name="code-display" id="code-display"></iframe>
+      </div>
+    </div>
+    <div id="code-options" class="setting">
+      <span>code on <a id="set-code-left" class="selected" href="#">left</a> &bull; <a id="set-code-right" href="#">right</a></span>
+      <span>code width <span id="code-column-width">70%</span></span>
+      <span>filepaths <a id="show-filepaths" class="selected" href="#">shown</a> &bull; <a id="hide-filepaths" href="#">hidden</a></span>
+    </div>
+  </div>
+  <div class="right" id="comment-column">
+    <div id="comment-area">
+      {{range .Step}}
+      <div class="comment first last">
+        <a class="comment-link" href="/doc/codewalk/?fileprint=/{{urlquery .File}}&amp;lo={{urlquery .Lo}}&amp;hi={{urlquery .Hi}}#mark" target="code-display"></a>
+        <div class="comment-title">{{html .Title}}</div>
+        <div class="comment-text">
+	{{with .Err}}
+	ERROR LOADING FILE: {{html .}}<br/><br/>
+	{{end}}
+        {{.XML}}
+        </div>
+        <div class="comment-text file-name"><span class="path-file">{{html .}}</span></div>
+      </div>
+      {{end}}
+    </div>
+    <div id="comment-options" class="setting">
+      <a id="prev-comment" href="#"><span class="hotkey">p</span>revious step</a>
+      &bull;
+      <a id="next-comment" href="#"><span class="hotkey">n</span>ext step</a>
+    </div>
+  </div>
+</div>
+`,
+
+	"codewalkdir.html": `<!--
+	Copyright 2010 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.
+-->
+
+<table class="layout">
+{{range .}}
+<tr>
+	{{$name_html := html .Name}}
+	<td><a href="{{$name_html}}">{{$name_html}}</a></td>
+	<td width="25">&nbsp;</td>
+	<td>{{html .Title}}</td>
+</tr>
+{{end}}
+</table>
+`,
+
+	"dirlist.html": `<!--
+	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.
+-->
+
+<p>
+<table class="layout">
+<tr>
+	<th align="left">File</th>
+	<td width="25">&nbsp;</td>
+	<th align="right">Bytes</th>
+	<td width="25">&nbsp;</td>
+	<th align="left">Modified</th>
+</tr>
+<tr>
+	<td><a href="..">..</a></td>
+</tr>
+{{range .}}
+<tr>
+	{{$name_html := fileInfoName . | html}}
+	<td align="left"><a href="{{$name_html}}">{{$name_html}}</a></td>
+	<td></td>
+	<td align="right">{{html .Size}}</td>
+	<td></td>
+	<td align="left">{{fileInfoTime . | html}}</td>
+</tr>
+{{end}}
+
+</table>
+</p>
+`,
+
+	"error.html": `<!--
+	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.
+-->
+
+<p>
+<span class="alert" style="font-size:120%">{{html .}}</span>
+</p>
+`,
+
+	"example.html": `<div id="example_{{.Name}}" class="toggle">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Example{{example_suffix .Name}}</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Example{{example_suffix .Name}}</span></p>
+		{{with .Doc}}<p>{{html .}}</p>{{end}}
+		{{$output := .Output}}
+		{{with .Play}}
+			<div class="play">
+				<div class="input"><textarea class="code">{{html .}}</textarea></div>
+				<div class="output"><pre>{{html $output}}</pre></div>
+				<div class="buttons">
+					<a class="run" title="Run this code [shift-enter]">Run</a>
+					<a class="fmt" title="Format this code">Format</a>
+					<a class="share" title="Share this code">Share</a>
+				</div>
+			</div>
+		{{else}}
+			<p>Code:</p>
+			<pre class="code">{{.Code}}</pre>
+			{{with .Output}}
+			<p>Output:</p>
+			<pre class="output">{{html .}}</pre>
+			{{end}}
+		{{end}}
+	</div>
+</div>
+`,
+
+	"godoc.html": `<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+{{with .Tabtitle}}
+  <title>{{html .}} - The Go Programming Language</title>
+{{else}}
+  <title>The Go Programming Language</title>
+{{end}}
+<link type="text/css" rel="stylesheet" href="/lib/godoc/style.css">
+{{if .SearchBox}}
+<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
+{{end}}
+<link rel="stylesheet" href="/lib/godoc/jquery.treeview.css">
+<script type="text/javascript">window.initFuncs = [];</script>
+</head>
+<body>
+
+<div id='lowframe' style="position: fixed; bottom: 0; left: 0; height: 0; width: 100%; border-top: thin solid grey; background-color: white; overflow: auto;">
+...
+</div><!-- #lowframe -->
+
+<div id="topbar"{{if .Title}} class="wide"{{end}}><div class="container">
+
+<form method="GET" action="/search">
+<div id="menu">
+<a href="/doc/">Documents</a>
+<a href="/pkg/">Packages</a>
+<a href="/project/">The Project</a>
+<a href="/help/">Help</a>
+<a href="/blog/">Blog</a>
+{{if .Playground}}
+<a id="playgroundButton" href="http://play.golang.org/" title="Show Go Playground">Play</a>
+{{end}}
+<input type="text" id="search" name="q" class="inactive" value="Search" placeholder="Search">
+</div>
+<div id="heading"><a href="/">The Go Programming Language</a></div>
+</form>
+
+</div></div>
+
+{{if .Playground}}
+<div id="playground" class="play">
+	<div class="input"><textarea class="code">package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, 世界")
+}</textarea></div>
+	<div class="output"></div>
+	<div class="buttons">
+		<a class="run" title="Run this code [shift-enter]">Run</a>
+		<a class="fmt" title="Format this code">Format</a>
+		<a class="share" title="Share this code">Share</a>
+	</div>
+</div>
+{{end}}
+
+<div id="page"{{if .Title}} class="wide"{{end}}>
+<div class="container">
+
+{{with .Title}}
+  <h1>{{html .}}</h1>
+{{end}}
+{{with .Subtitle}}
+  <h2>{{html .}}</h2>
+{{end}}
+
+{{/* The Table of Contents is automatically inserted in this <div>.
+     Do not delete this <div>. */}}
+<div id="nav"></div>
+
+{{/* Body is HTML-escaped elsewhere */}}
+{{printf "%s" .Body}}
+
+<div id="footer">
+Build version {{html .Version}}.<br>
+Except as <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
+the content of this page is licensed under the
+Creative Commons Attribution 3.0 License,
+and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
+<a href="/doc/tos.html">Terms of Service</a> | 
+<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
+</div>
+
+</div><!-- .container -->
+</div><!-- #page -->
+
+<!-- TODO(adonovan): load these from <head> using "defer" attribute? -->
+<script type="text/javascript" src="/lib/godoc/jquery.js"></script>
+<script type="text/javascript" src="/lib/godoc/jquery.treeview.js"></script>
+<script type="text/javascript" src="/lib/godoc/jquery.treeview.edit.js"></script>
+
+{{if .Playground}}
+<script type="text/javascript" src="/lib/godoc/playground.js"></script>
+{{end}}
+<script type="text/javascript" src="/lib/godoc/godocs.js"></script>
+
+</body>
+</html>
+
+`,
+
+	"godocs.js": `// 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.
+
+/* A little code to ease navigation of these documents.
+ *
+ * On window load we:
+ *  + Bind search box hint placeholder show/hide events (bindSearchEvents)
+ *  + Generate a table of contents (generateTOC)
+ *  + Bind foldable sections (bindToggles)
+ *  + Bind links to foldable sections (bindToggleLinks)
+ */
+
+(function() {
+'use strict';
+
+function bindSearchEvents() {
+
+  var search = $('#search');
+  if (search.length === 0) {
+    return; // no search box
+  }
+
+  function clearInactive() {
+    if (search.is('.inactive')) {
+      search.val('');
+      search.removeClass('inactive');
+    }
+  }
+
+  function restoreInactive() {
+    if (search.val() !== '') {
+      return;
+    }
+    search.val(search.attr('placeholder'));
+    search.addClass('inactive');
+  }
+
+  search.on('focus', clearInactive);
+  search.on('blur', restoreInactive);
+
+  restoreInactive();
+}
+
+/* Generates a table of contents: looks for h2 and h3 elements and generates
+ * links. "Decorates" the element with id=="nav" with this table of contents.
+ */
+function generateTOC() {
+  if ($('#manual-nav').length > 0) {
+    return;
+  }
+
+  var nav = $('#nav');
+  if (nav.length === 0) {
+    return;
+  }
+
+  var toc_items = [];
+  $(nav).nextAll('h2, h3').each(function() {
+    var node = this;
+    if (node.id == '')
+      node.id = 'tmp_' + toc_items.length;
+    var link = $('<a/>').attr('href', '#' + node.id).text($(node).text());
+    var item;
+    if ($(node).is('h2')) {
+      item = $('<dt/>');
+    } else { // h3
+      item = $('<dd/>');
+    }
+    item.append(link);
+    toc_items.push(item);
+  });
+  if (toc_items.length <= 1) {
+    return;
+  }
+
+  var dl1 = $('<dl/>');
+  var dl2 = $('<dl/>');
+
+  var split_index = (toc_items.length / 2) + 1;
+  if (split_index < 8) {
+    split_index = toc_items.length;
+  }
+  for (var i = 0; i < split_index; i++) {
+    dl1.append(toc_items[i]);
+  }
+  for (/* keep using i */; i < toc_items.length; i++) {
+    dl2.append(toc_items[i]);
+  }
+
+  var tocTable = $('<table class="unruled"/>').appendTo(nav);
+  var tocBody = $('<tbody/>').appendTo(tocTable);
+  var tocRow = $('<tr/>').appendTo(tocBody);
+
+  // 1st column
+  $('<td class="first"/>').appendTo(tocRow).append(dl1);
+  // 2nd column
+  $('<td/>').appendTo(tocRow).append(dl2);
+}
+
+function bindToggle(el) {
+  $('.toggleButton', el).click(function() {
+    if ($(el).is('.toggle')) {
+      $(el).addClass('toggleVisible').removeClass('toggle');
+    } else {
+      $(el).addClass('toggle').removeClass('toggleVisible');
+    }
+  });
+}
+function bindToggles(selector) {
+  $(selector).each(function(i, el) {
+    bindToggle(el);
+  });
+}
+
+function bindToggleLink(el, prefix) {
+  $(el).click(function() {
+    var href = $(el).attr('href');
+    var i = href.indexOf('#'+prefix);
+    if (i < 0) {
+      return;
+    }
+    var id = '#' + prefix + href.slice(i+1+prefix.length);
+    if ($(id).is('.toggle')) {
+      $(id).find('.toggleButton').first().click();
+    }
+  });
+}
+function bindToggleLinks(selector, prefix) {
+  $(selector).each(function(i, el) {
+    bindToggleLink(el, prefix);
+  });
+}
+
+function setupDropdownPlayground() {
+  if (!$('#page').is('.wide')) {
+    return; // don't show on front page
+  }
+  var button = $('#playgroundButton');
+  var div = $('#playground');
+  var setup = false;
+  button.toggle(function() {
+    button.addClass('active');
+    div.show();
+    if (setup) {
+      return;
+    }
+    setup = true;
+    playground({
+      'codeEl': $('.code', div),
+      'outputEl': $('.output', div),
+      'runEl': $('.run', div),
+      'fmtEl': $('.fmt', div),
+      'shareEl': $('.share', div),
+      'shareRedirect': '//play.golang.org/p/'
+    });
+  },
+  function() {
+    button.removeClass('active');
+    div.hide();
+  });
+  button.show();
+  $('#menu').css('min-width', '+=60');
+}
+
+function setupInlinePlayground() {
+	'use strict';
+	// Set up playground when each element is toggled.
+	$('div.play').each(function (i, el) {
+		// Set up playground for this example.
+		var setup = function() {
+			var code = $('.code', el);
+			playground({
+				'codeEl':   code,
+				'outputEl': $('.output', el),
+				'runEl':    $('.run', el),
+				'fmtEl':    $('.fmt', el),
+				'shareEl':  $('.share', el),
+				'shareRedirect': '//play.golang.org/p/'
+			});
+
+			// Make the code textarea resize to fit content.
+			var resize = function() {
+				code.height(0);
+				var h = code[0].scrollHeight;
+				code.height(h+20); // minimize bouncing.
+				code.closest('.input').height(h);
+			};
+			code.on('keydown', resize);
+			code.on('keyup', resize);
+			code.keyup(); // resize now.
+		};
+		
+		// If example already visible, set up playground now.
+		if ($(el).is(':visible')) {
+			setup();
+			return;
+		}
+
+		// Otherwise, set up playground when example is expanded.
+		var built = false;
+		$(el).closest('.toggle').click(function() {
+			// Only set up once.
+			if (!built) {
+				setup();
+				built = true;
+			}
+		});
+	});
+}
+
+// fixFocus tries to put focus to div#page so that keyboard navigation works.
+function fixFocus() {
+  var page = $('div#page');
+  var topbar = $('div#topbar');
+  page.css('outline', 0); // disable outline when focused
+  page.attr('tabindex', -1); // and set tabindex so that it is focusable
+  $(window).resize(function (evt) {
+    // only focus page when the topbar is at fixed position (that is, it's in
+    // front of page, and keyboard event will go to the former by default.)
+    // by focusing page, keyboard event will go to page so that up/down arrow,
+    // space, etc. will work as expected.
+    if (topbar.css('position') == "fixed")
+      page.focus();
+  }).resize();
+}
+
+function toggleHash() {
+    var hash = $(window.location.hash);
+    if (hash.is('.toggle')) {
+      hash.find('.toggleButton').first().click();
+    }
+}
+
+$(document).ready(function() {
+  bindSearchEvents();
+  generateTOC();
+  bindToggles(".toggle");
+  bindToggles(".toggleVisible");
+  bindToggleLinks(".exampleLink", "example_");
+  bindToggleLinks(".overviewLink", "");
+  bindToggleLinks(".examplesLink", "");
+  bindToggleLinks(".indexLink", "");
+  setupDropdownPlayground();
+  setupInlinePlayground();
+  fixFocus();
+  setupTypeInfo();
+  setupCallgraphs();
+  toggleHash();
+
+  // godoc.html defines window.initFuncs in the <head> tag, and root.html and
+  // codewalk.js push their on-page-ready functions to the list.
+  // We execute those functions here, to avoid loading jQuery until the page
+  // content is loaded.
+  for (var i = 0; i < window.initFuncs.length; i++) window.initFuncs[i]();
+});
+
+// -- analysis ---------------------------------------------------------
+
+// escapeHTML returns HTML for s, with metacharacters quoted.
+// It is safe for use in both elements and attributes
+// (unlike the "set innerText, read innerHTML" trick).
+function escapeHTML(s) {
+    return s.replace(/&/g, '&amp;').
+             replace(/\"/g, '&quot;').
+             replace(/\'/g, '&#39;').
+             replace(/</g, '&lt;').
+             replace(/>/g, '&gt;');
+}
+
+// makeAnchor returns HTML for an <a> element, given an anchorJSON object.
+function makeAnchor(json) {
+  var html = escapeHTML(json.Text);
+  if (json.Href != "") {
+      html = "<a href='" + escapeHTML(json.Href) + "'>" + html + "</a>";
+  }
+  return html;
+}
+
+function showLowFrame(html) {
+  var lowframe = document.getElementById('lowframe');
+  lowframe.style.height = "200px";
+  lowframe.innerHTML = "<p style='text-align: left;'>" + html + "</p>\n" +
+      "<div onclick='hideLowFrame()' style='position: absolute; top: 0; right: 0; cursor: pointer;'>✘</div>"
+};
+
+document.hideLowFrame = function() {
+  var lowframe = document.getElementById('lowframe');
+  lowframe.style.height = "0px";
+}
+
+// onClickCallers is the onclick action for the 'func' tokens of a
+// function declaration.
+document.onClickCallers = function(index) {
+  var data = document.ANALYSIS_DATA[index]
+  if (data.Callers.length == 1 && data.Callers[0].Sites.length == 1) {
+    document.location = data.Callers[0].Sites[0].Href; // jump to sole caller
+    return;
+  }
+
+  var html = "Callers of <code>" + escapeHTML(data.Callee) + "</code>:<br/>\n";
+  for (var i = 0; i < data.Callers.length; i++) {
+    var caller = data.Callers[i];
+    html += "<code>" + escapeHTML(caller.Func) + "</code>";
+    var sites = caller.Sites;
+    if (sites != null && sites.length > 0) {
+      html += " at line ";
+      for (var j = 0; j < sites.length; j++) {
+        if (j > 0) {
+          html += ", ";
+        }
+        html += "<code>" + makeAnchor(sites[j]) + "</code>";
+      }
+    }
+    html += "<br/>\n";
+  }
+  showLowFrame(html);
+};
+
+// onClickCallees is the onclick action for the '(' token of a function call.
+document.onClickCallees = function(index) {
+  var data = document.ANALYSIS_DATA[index]
+  if (data.Callees.length == 1) {
+    document.location = data.Callees[0].Href; // jump to sole callee
+    return;
+  }
+
+  var html = "Callees of this " + escapeHTML(data.Descr) + ":<br/>\n";
+  for (var i = 0; i < data.Callees.length; i++) {
+    html += "<code>" + makeAnchor(data.Callees[i]) + "</code><br/>\n";
+  }
+  showLowFrame(html);
+};
+
+// onClickTypeInfo is the onclick action for identifiers declaring a named type.
+document.onClickTypeInfo = function(index) {
+  var data = document.ANALYSIS_DATA[index];
+  var html = "Type <code>" + data.Name + "</code>: " +
+  "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<small>(size=" + data.Size + ", align=" + data.Align + ")</small><br/>\n";
+  html += implementsHTML(data);
+  html += methodsetHTML(data);
+  showLowFrame(html);
+};
+
+// implementsHTML returns HTML for the implements relation of the
+// specified TypeInfoJSON value.
+function implementsHTML(info) {
+  var html = "";
+  if (info.ImplGroups != null) {
+    for (var i = 0; i < info.ImplGroups.length; i++) {
+      var group = info.ImplGroups[i];
+      var x = "<code>" + escapeHTML(group.Descr) + "</code> ";
+      for (var j = 0; j < group.Facts.length; j++) {
+        var fact = group.Facts[j];
+        var y = "<code>" + makeAnchor(fact.Other) + "</code>";
+        if (fact.ByKind != null) {
+          html += escapeHTML(fact.ByKind) + " type " + y + " implements " + x;
+        } else {
+          html += x + " implements " + y;
+        }
+        html += "<br/>\n";
+      }
+    }
+  }
+  return html;
+}
+
+
+// methodsetHTML returns HTML for the methodset of the specified
+// TypeInfoJSON value.
+function methodsetHTML(info) {
+  var html = "";
+  if (info.Methods != null) {
+    for (var i = 0; i < info.Methods.length; i++) {
+      html += "<code>" + makeAnchor(info.Methods[i]) + "</code><br/>\n";
+    }
+  }
+  return html;
+}
+
+// onClickComm is the onclick action for channel "make" and "<-"
+// send/receive tokens.
+document.onClickComm = function(index) {
+  var ops = document.ANALYSIS_DATA[index].Ops
+  if (ops.length == 1) {
+    document.location = ops[0].Op.Href; // jump to sole element
+    return;
+  }
+
+  var html = "Operations on this channel:<br/>\n";
+  for (var i = 0; i < ops.length; i++) {
+    html += makeAnchor(ops[i].Op) + " by <code>" + escapeHTML(ops[i].Fn) + "</code><br/>\n";
+  }
+  if (ops.length == 0) {
+    html += "(none)<br/>\n";
+  }
+  showLowFrame(html);
+};
+
+$(window).load(function() {
+    // Scroll window so that first selection is visible.
+    // (This means we don't need to emit id='L%d' spans for each line.)
+    // TODO(adonovan): ideally, scroll it so that it's under the pointer,
+    // but I don't know how to get the pointer y coordinate.
+    var elts = document.getElementsByClassName("selection");
+    if (elts.length > 0) {
+	elts[0].scrollIntoView()
+    }
+});
+
+// setupTypeInfo populates the "Implements" and "Method set" toggle for
+// each type in the package doc.
+function setupTypeInfo() {
+  for (var i in document.ANALYSIS_DATA) {
+    var data = document.ANALYSIS_DATA[i];
+
+    var el = document.getElementById("implements-" + i);
+    if (el != null) {
+      // el != null => data is TypeInfoJSON.
+      if (data.ImplGroups != null) {
+        el.innerHTML = implementsHTML(data);
+        el.parentNode.parentNode.style.display = "block";
+      }
+    }
+
+    var el = document.getElementById("methodset-" + i);
+    if (el != null) {
+      // el != null => data is TypeInfoJSON.
+      if (data.Methods != null) {
+        el.innerHTML = methodsetHTML(data);
+        el.parentNode.parentNode.style.display = "block";
+      }
+    }
+  }
+}
+
+function setupCallgraphs() {
+  if (document.CALLGRAPH == null) {
+    return
+  }
+  document.getElementById("pkg-callgraph").style.display = "block";
+
+  var treeviews = document.getElementsByClassName("treeview");
+  for (var i = 0; i < treeviews.length; i++) {
+    var tree = treeviews[i];
+    if (tree.id == null || tree.id.indexOf("callgraph-") != 0) {
+      continue;
+    }
+    var id = tree.id.substring("callgraph-".length);
+    $(tree).treeview({collapsed: true, animated: "fast"});
+    document.cgAddChildren(tree, tree, [id]);
+    tree.parentNode.parentNode.style.display = "block";
+  }
+}
+
+document.cgAddChildren = function(tree, ul, indices) {
+  if (indices != null) {
+    for (var i = 0; i < indices.length; i++) {
+      var li = cgAddChild(tree, ul, document.CALLGRAPH[indices[i]]);
+      if (i == indices.length - 1) {
+        $(li).addClass("last");
+      }
+    }
+  }
+  $(tree).treeview({animated: "fast", add: ul});
+}
+
+// cgAddChild adds an <li> element for document.CALLGRAPH node cgn to
+// the parent <ul> element ul. tree is the tree's root <ul> element.
+function cgAddChild(tree, ul, cgn) {
+   var li = document.createElement("li");
+   ul.appendChild(li);
+   li.className = "closed";
+
+   var code = document.createElement("code");
+
+   if (cgn.Callees != null) {
+     $(li).addClass("expandable");
+
+     // Event handlers and innerHTML updates don't play nicely together,
+     // hence all this explicit DOM manipulation.
+     var hitarea = document.createElement("div");
+     hitarea.className = "hitarea expandable-hitarea";
+     li.appendChild(hitarea);
+
+     li.appendChild(code);
+
+     var childUL = document.createElement("ul");
+     li.appendChild(childUL);
+     childUL.setAttribute('style', "display: none;");
+
+     var onClick = function() {
+       document.cgAddChildren(tree, childUL, cgn.Callees);
+       hitarea.removeEventListener('click', onClick)
+     };
+     hitarea.addEventListener('click', onClick);
+
+   } else {
+     li.appendChild(code);
+   }
+   code.innerHTML += "&nbsp;" + makeAnchor(cgn.Func);
+   return li
+}
+
+})();
+`,
+
+	"images/minus.gif": "GIF89a\t\x00\t\x00\xf7\x00\x00\x00\x00\x00\x80\x80\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xff\x00,\x00\x00\x00\x00\t\x00\t\x00\x00\b\"\x00\x03\b\x1cH\xf0\x9f\xc1\x83\xff\x04\"<\xa8pa\xc2\x00\xff\x00H\x94\xf8\xd0aE\x87\r\x17\x12\xdc\x18  \x00;",
+
+	"images/plus.gif": "GIF89a\t\x00\t\x00\xf7\x00\x00\x00\x00\x00\x80\x80\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xff\x00,\x00\x00\x00\x00\t\x00\t\x00\x00\b&\x00\x03\b\x1cH\xf0\x9f\xc1\x83\xff\x04\x1e\x04pP\xa1A\x86\x06\x15\x02\x9881a\x80\x85\r/>̈0#A\x82\x01\x01\x00;",
+
+	"images/treeview-black-line.gif": "GIF89a\x10\x00\xf0\x06\xf7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xff\x00,\x00\x00\x00\x00\x10\x00\xf0\x06\x00\b\xff\x00\xff\t\x1c\xf8\x0f\x00\xc1\x83\b\r\"\\X\x90\xe1B\x85\x0e\tB\x8c(p\"E\x8b\x111:\xd4\xc8\x10\x80Ǐ\x1f\x1fR\x948r G\x91%\x1b\xa6<\x990\xa5ʒ,\x0f\xc6$\xb9\xd2\xe5L\x936s\xd6\xdc\tSgO\x9e#oV\xf4\x19\x94\xe8E\xa3\x19\x91nTڑ)ʟP\x8b\x02=:5iեW\x9bf}*5*U\xafV\xc1b\x15\xab\x95,\u05ef]Ӣ]\x1bVm[\xb6c\xddƅ[Vn]\xbag\xdfꝻ\xf7n\u07fc|\x03\xfb\x15\fx\xb0\xe1\u0088[nUl\x96\xb1\xdd\xc42\x9d:\xc6;\xf9oe\u0097\x0fg\x86L\xb3q\xe4ş=w~\xbc\xb9thҧ)\xa7\xb6\xbc\x1askͯ9\xe3\x04=Zumַ]熽[\xf6PڳE\aG\xdd\xdbt\xf1\xd8Ƈ\xdbV\x8e\x9b\xb9n缡\xfb~Iܥ\xf5\xebسk\xdfν{\xf4\xdf\xc2\xc1W\xff\x17\xbf\x9c|s\xf3\xcf\xd1\u007f\xa7^\x9e\xfdy\xf7\xe9\xe1\xaf\x17*\u007f:\xfd\xfb\x92\x91\xeb?\xce_zr\xf5\xf6\xe5\xd7\x1f\x80\xff\xd5W ~\xc0\x11\xb8\x9f\u007f\v*8\xa0\x81\rB\xf8 \x82\xe1I\xc8\xe0\x84\x02^\xa8\xa1\x83\x1bZ\xc8\xe1\x87\x1e\x86H\xe1x\"f\b\xe2\x88\xed\xa1\xf8\x9e\x8a\xf1\xb18\x9f\x89%&\x18c\x85.\x06(c\x8d\a\u0088c\x84;bx\xa3\x8e@\xfe($\x8dA\x129$\x89=v\x98\xe4\x89E\"\xd9d\x8aO\xae\x18e\x8bS\xbex$\x94WJ\x99%\x95[Zi\xe4\x97Nvi#\x98X\x92\xa9\xa5\x99\\\xa2\xe9e\x98j\x8e\xc9\xe6\x9be\xc2y\xa6\x9ciҹf\x9cxΙg\x9d{ީ\xe7\x9f|\x02\xeag\xa0\x84\x0ej\xa8\x9b}\"*\xa8\xa2\x852zh\x8ebBڦ\xa4v:j)\xa5\x89b\xba\xa8\xa6\x8dr\xfa(\x8fU^\nj\xa4\xa3NZj\xa5\x9e\x8a꣩\xab\xa2zj\xa6\xafn\xff\x1ak\xa7\xb3~\xda*\xac\xb7ʚ+\xad\xbbڪd\xa8\xa9\x06[\xab\xaa\xbf\x92\xda+\xb1L\x1a[,\xab˺z\xac\xb0\xcf\x0e\vm\xb3\xb8R\xab\xab\xb5\xbcb\xebk\xb2\xccr묶\xc8\xce\xf8\xad\xb7Ւ{\xad\xb9٢\xbb\xad\xb8\xe5\xb2{\xae\xbb\xe9»\xee\x92\xf2\x86K\xef\xbd\xc0J\xabo\xb4\xfc\x82;\xad\xba\xf6\xe6\xdb/\xc0\xff\xd6[0\xbe\xca\x12\xbc\xaf\xbf\v+<\xb0\xc1\rC\xfc0\xc2\xddJ\xcc\xf0\xc4\x02_\xac\xb1\xc3\x1b[\xcc\xf1\xc7\x1e\x87L\xf1\xb8\"g\f\xf2\xc8\xed\xa2\xfc\xae\xca\xf1\xb2<\xaf\xc9%'\x1cs\xc5.\a,s\xcd\aÌs\xc4;c|\xb3\xce@\xff,4\xcdA\x13=4\xc9=w\x9c\xf4\xc9E#\xddt\xcaO\xaf\x1cu\xcbS\xbf|4\xd4WK\x9d5\xd5[[m\xf4\xd7Nwm3\xd8X\x93\xad\xb5\xd9\\\xa3\xedu\xd8j\x8f\xcd\xf6\xdbe\xc3}\xb6\xdciӽv\xdcxϝw\xdd{\xdf\xff\xad\xf7\xdf|\x03\xeew\xe0\x84\x0fn\xb8\xdb}#.\xb8\xe2\x853~x\xcebC\u07b6\xe4v;n9\xe5\x89c\xbe\xb8\xe6\x8ds\xfe8\xcfU_\x0ez\xe4\xa3O^z型\xee\xb3髣~z\xe6\xafo\x1e{\xe7\xb3\u007f\xde:\xec\xb7˞;\xed\xbbۮt\xe8\xa9\a_\xbb꿓\xde;\xf1L\x1b_<\xeb˻~\xbc\xf0\xcf\x0f\x0f}\xf3\xb8S\xaf\xbb\xf5\xbcc\xef{\xf2\xccs\xef\xbc\xf6\xc8\xcf\xfc\xbd\xf7Փ\u007f\xbd\xf9٣\xbf\xbd\xf8\xe5\xb3\u007f\xbe\xfb\xe9ÿ\xfe\xd2\xf2\x87O\xff\xfd\xc0K\xaf\u007f\xf4\xfc\x83?\xbd\xfa\xf6\xcb_\xff\x00\xf8\xbf\xfa\x15\x10\u007f\xca#\xe0\xfe\xfc\xb7@\x05\x0eЀ\r\x84\xe0\x03\x11\xd8=\t2p\x82\x02\xbc\xa0\x06\x1d\xb8A\vr\xf0\x83\x1e\f!\x05\xc7'\xc2\f\x82p\x84\xedC\xe1\xfbT\x18?\x16\xceτ%L`\f+\xe8\xc2\x00ʰ\x86\a\x84!\x0e#\xb8C\f\xdeP\x87@\xfc\xa1\x102i\x18D\"\x0e\x91\x84=\xec`\x12OXD$61\x85O\\a\x14[8\xc5\x17\x1e\x11\x8aW\x94b\x16\xa9\xb8E+\x1a\xf1\x8bN\xec\xa2\ri\b\x12\x90\x04\x04\x00;",
+
+	"images/treeview-black.gif": "GIF89a`\x00\x85\x00\xa1\x01\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff!\xf9\x04\x01\x00\x00\x02\x00,\x00\x00\x00\x00`\x00\x85\x00\x00\x02\xfe\x94\x8f\xa9\xcb\xed\x0fE\x98\xc1ш\xb3ި\xf2\x0f\x86\x9a'\x96\xa6I\x9e\xeaʶ\xee\nIJ\xfc\xd6&\xb0\xe0\xf6\xfe\xe9\x82\xef\xe3\t#\xc0Cp\x88d\xe0f\xcbY\xf2\x89(\x1a\x8eP\xa8\xf4W\xcdNs\xda,\xd3\xd9\xedR\xc3^\xb2yl~\xa2\xd3\xc85[\xe8~\xabRF9\x8f\xbe\xb5o.\x96\tW?R\x12\a\x98\x80Gx\x88\x98\b\xf8E\xa3\xa826\xe8\x88\x01)yBY)\xf8\xe3Ą\xd9\xf3\xd7\tr\t\xea\xa9\x109\x9a\xc3hzڠ\xba\xfa\xd0\xea\xca\x1a{3\x9bY\x1b\x02\xebj\x98\xbb\xba\x1b\xcb\xd7\x00\x1c\xf5k\xdb{{\x8c\x9c\xac\x8cʸ\xac\xf4\xe9<\x9c\x87\x15\x9dp\xc5{\xdaD\xc3Y}]m]7\xfdM\r>>\x95j\x9e\xae\xbe\xceގd\xb8\x0e\xff+\xac@\u007f뛎o\xae?\xce\xef\x8e\x1d+\x15@P\xa2\xc6yKwМ\xb6\x18\x9a\x1aEKh0\x1c\xb9\x88\xa5\xd4\tt\x871\xa3\xc6d\x8d\x06\xe4\xe5\xdb豗\x9f>!O\x95\xfcv\xb2ZJ\x8e,\r\xa2C\b\xed[A\x991\xbb5d\xc8\xedaM\x9d\x15a\xf6T\xf8\xb2\xa5СDG\xadtvtY\xd2J\xf6:\x8cT\xb8q`-\xa9\xb3\xa8\x06\xfc\x17\x94b9\xa8?\xb5J\x83\xca)\xa7\xb3\x996\xbb\xd24\xdb-kѵlۺ}\v7.\x82\x02\x00;",
+
+	"images/treeview-default-line.gif": "GIF89a\x10\x00\xf0\x06\xf7\x00\x00\x00\x00\x00\x80\x80\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xff\x00,\x00\x00\x00\x00\x10\x00\xf0\x06\x00\b\xff\x00\xff\t\x1cH\xb0\xa0A\x81\x01\x0e*\\x0!Ç\v\x1dB\x9cHP\"E\x8a\t3\xfe\xd3x\xb1aNj\x16?2\f)R!ɒ\x06O\xa2\xac\xb8rdˈ/M\xc6\xf48\xb3\xa0ʗ7[\xe6\\\xb9\x13eϒ?E\x06\xfd8\xb4cQ\x905m&e\xb9\x14aS\xa7O\x8fb|\xba\x91\xaaԉW!f}\xb8\xd5eT\xab`\xbf\x8am\xda\x15\xe6إee\x9eM\x9a\x96&ٰo\xd7\xd6l\x9b\x12.Z\xbbl\xf1\xce\xd5;\x93\xaeR\xb9}\xf9\xc6\xf4\xcb4\xaeỀ\a\vƹXgc\x9e\x8f}F\x06:Yhe\xa2\x97\xa9j\xde̹3\xd7\xccH\x133\x16\xed\x984dӒQSVm\x995f\xd7FAO\x85\x1d\xfap^ڳm\xefōUvo\xdeZ}\a\a\xfe\x99\xb8W݁\x8d\x9bE\xaeX\xb9Z棡\x97\x96~\x9azj뫱\xb7\xd6\xfe\x9a{l\xe7n\x11{\xff\xaf-\xbe\xfc\xed\xf1\xb9\xcd\xefF\xff\x9b\xfdp\xf7\xc5\xe1\x1fW\x9f\\\xfer\xfa\xcd\xed?\xc7\x1f\x9d\xfft\xff\xd5\x01x\x9d\x80\xd9\x11\xb8\x9d\x81\xdd!\xf8\x9d~ᝧ y\x0eF\xb8ރ\xe9IX\x1f\x85\xeda\xf8\x9e\x86\xf1q8\x9f\x85\xf9yx\x1f\x88\xfd\x91\xf8\x9f\x89\x01\xa28\xa0\x8a\x05\xb2x\xa0\x8b\t¸\xa0\x88\xfb\xc9\b\xe1\x846V\x88\xe3\x8e\x17昡\x8f\x1b\x02١\x90\x1f\xf2\x18\"\x91#\x1aY\xa2\x92'2\x99\xa2\x93+B٢\x94/R\x19\xa3\x953\"Y#\x967\xf6ȥ\x8e^\x86y\xe4\x97?\x92\x19\xa4\x99C\xa2Y\xa4\x98K\xb2٤\x9bO\xc2\x19\xa5\x9cS\xd2Y\xa5\x9dW♥\x9aI\xea\xd9\xe5\x98~\x82\t\xe8\xa0m\x12\xfa\xa6\xa1q\":\xa7\xa2u2z\xa7\xa3yB\xbag\xa0eRz\xa6\xa5ib\xba\xa6\xa4\u007f\x16\xea顟&\x1aꢣ6Z꣧F\x9aꤜ\n\xbaj\xa7\xa0\xc6\xff*\xaa\xac\xa4\xd2j\xaa\xad\xa8⪪\xae\xac\xbe\xea*\xaf\xb0\xce*l\xad\xc3\xdeZl\xae\xc7\xee\x9al\xaf\xc0\xfe\xbal\xb0\xc4Fk\xac\xb4\xc8R\xab\xac\xb5\xcc>\xeb,\xb6\xd0N\xebm\xb5\xdf^\x1bn\xb6\xdcn;n\xb7\xe0\xa6+\xae\xba\xe4\x9ek.\xbb\xe8\xae+o\xbb\xf0\xbe;o\xbc\xf4\xdeko\xbe\xfc\xe2\xeb\xef\xbe\xffVڪ\xc0\xbe\x12ܬ\xc1\xda\"\\\xae\xc2\xee2\\\xaf\xc3\xfaB\xdc/\xc0\x14K\x1c\xf0\xa5\x03c\\\xb0\xc6\as\x9c\xb0\xc7\v\x83ܰ\xc8\x0f\x93\x1c\xb1\xc9\x13[\\1\xca\x17g\x9a\xb1\xcb\x1b\xc3ܱ\xcc\x1f\xd3\x1c\xb2\xcd#\xe3\\\xb2\xce'\xf3\x9c2\xcb+\xfb\xdc\xf2\xa61\x13=\xb3\xd15#}\xb3\xd293\xbd\xb3\xd3=C\xfd\xb3\xd0AK=t\x9f/[]5\xd6Es}\xb4\xd7I\x83\xbd\xb4\xd8M\x93\xfd\xb4\xd9Q\xa3=\xb5\xd6*\xb7\r\xb4\xdbT\xc3\xcd\xf6\xdbt\xc7]\xf7\xdcv\xe7\x8d\xf7\xdej_\xff\xbd\xa5\xa6}o\xfdwց\xcb]\xf8݇\xeb\x9d8߃w\xdd\xf8\u05cf\x87\x1d\xf9ؓ\x97]\xf9ٗ\xa7\x9d\xf9ڋw\xbe\xb9\xdf\r\xf2\xf9\xb9\xe0\xa1\x03>\xba\xe1\xa7#\x9e\xba\xe2\xab3^:\xe1\xad{\xfe\xba\xe3\xb3C^\xbb\xe4\xb7S\x9e\xbb\xe5\xbbc\u07bb\xe6\xbfs\x1e\xfb\xf0\xc1\x83^\x17x\xc73\x98<\x8dœ\xbe\xbc\x96ͣ\x1e\xbd\xeaӳ^\xbd\xebϋ~\xbd\xecٛ\xbe=\xf1\xdd\xc3\xfe\xfd\xf8\xe1\xd3^\xbe\xed\xe7㞾\xee\xeb\xf3\u07be\xef\xef\x03\x1f\xbf\xf0\xe4\xff\xa5\xbc\xfd\xcc\xcfo<\xfe\xd0\xeb\xef<\xff\xda\xf3\x9f\xf4\x04H=\x02Zπ\xd8\x03\xa0\xf7\x10\xc8=\x05\x8a\x8f\x81\xe0s\xa0\xf9$\x88>\n\xaaς\xecà\xfb4\b?\x0e\xcaσ\xf4\x83`\xfd\n\x93?\x10\ue3c4\xfd3\xe1\xffP\x18@\x15\x0eЅ\x05\x84\xe1\x01e\x98@\x16.\x90\x86\r\xb4\xe1\x03q\x18A\x1dNЇ\x15\x04\xe2\x05\xa6\x85\x98A\"nЈ\x1dD\xe2\a\x95\x18B\x1e\x8ep \x84\x81\xa2pf\xc8\xc4\x13J\x11yN\x14\xa1\x16\xb3\xc8\xc5*\xae\xf0\x8a\xf7\xf3\xe2\v\xc5\x18C2R\x11\x8c%4c\rјB5損-tc\x0f\xe1xC9>\x11*a\xa4\xe3\x0e\xed\xb8E>vQ\x8f?\x04d\x10\x059DB\x16ѐGDd\x12\x15\xb9DF6я\x90t\xa4\x15\xf1\x98FI~\x91\x92m\xb4\xe4\x185YFN\x9e\x11\x93q\xf4\xe4\x1aAYGQ\xbe\x91\x94{4\xe5\x1cQ\x19HV\x0eҕ\x85\x84\xe5!e\x99HZ.\xd2)\x1a\xc9H@\x00\x00;",
+
+	"images/treeview-default.gif": "GIF89a`\x00\x85\x00\xa1\x03\x00\x00\x00\x00\x80\x80\x80\xbc\xbc\xbc\xff\xff\xff!\xf9\x04\x01\x00\x00\x03\x00,\x00\x00\x00\x00`\x00\x85\x00\x00\x02\xfe\x9c\x8f\xa9\xcb\xed\x0f\a\x98\xc0ш\xb3ި\xf2\x0f\x86\x9a'\x96\xa6I\x9e\xeaʶ\xee\x1aIJ\xfc\xd6f\xb0\xe0\xf6\xfe\xe9\xd2\xe1\xe3\t#>Rp\x88d\xe0(\x93\x01\ue64c\"\x8a@\xa9uz0^\xb7GCw;\x9c\x89\xc1\xe4\xb2\xd9yN\xab\xa5ߵ\xfb}j\xc3M\x82y\xb2\xae\x90\xdb\x13\x82\xfe\xa3\x8f\xb7\xf7\x11\b\xa2'h@x\xa8\xb8\xc8\xc8&F\xd3(\xf2e\x18\xf90Y\x19r\x89\xd9#\xc1\x84\x06\xb5\x89\xa1\x19\xaa1J*\x9asZ\xfa\x18\xa3\xeajE\xf9*\xeb\x12;k\x1bwې\x98\xfb\x97J\n\xf8\xe7w\xbb\xbbQkG̛\xac\xbc\xfc\xc6\xda\xca\xec\xe5\vM\x15\r\x8df\xa0e\xbd\xe4\te\xbcI}=\x9dU\xa5-\xcd\xec\xecm\xad\xbe\xce\xde\ueb81\xac\x1e\xff\v\xac+l;\x0fM\x9c\xfe\xfb~\xb0\xef/ :u\xa6\x96\x81\xe3\x17\xea \xc1N\x17\xba\x19\x1cWM\x1c6r\x12\x13 \xfc\xe6,\xa0\xc6b\x8d\x1c\xf5i\xcc\xc7\f$\xa6z\xf6DV2\x99\f%/\x95\x1d[\xde\x1aX.\xcfB\x991-.dR\xc1\xa1\xb2\x82;\xcd=\xa49-\xa3ˡD\x8b\x1eb9\xec\xe3\xca{\vH\x1a\x9du\xf1i\xa5\xa8R\x0f\xc1\xac\x88\xa5fV\xac\x14\xcf1l\xa23\x19O\xb1>{\x02='\xb4\xaaڵlۺ}˫\x00\x00;",
+
+	"images/treeview-gray-line.gif": "GIF89a\x10\x00\xf0\x06\xf7\x00\x00\x00\x00\x00\x80\x80\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xff\x00,\x00\x00\x00\x00\x10\x00\xf0\x06\x00\b\xff\x00\xff\t\x1c\xf8/\x00\xc1\x83\b\r\"\\X\x90\xe1B\x85\x0e\tB\x8c(p\"E\x8b\x111:\xd4\xc80\x80Ǐ\x1f\x1fR\x948r G\x91%\x1b\xa6<\x990\xa5ʒ,\x0f\xc6$\xb9\xd2\xe5L\x936s\xd6\xdc\tSgO\x9e#oV\xf4\x19\x94\xe8E\xa3\x19\x91nTڑ)ʟP\x8b\x02=:5iեW\x9bf}*5*U\xafV\xc1b\x15\xab\x95,\u05ef]Ӣ]\x1bVm[\xb6c\xddƅ[Vn]\xbag\xdfꝻ\xf7n\u07fc|\x03\xfb\x15\fx\xb0\xe1\u0088[nUl\x96\xb1\xdd\xc42\x9d:\xc6;\xf9oe\u0097\x0fg\x86L\xb3q\xe4ş=w~\xbc\xb9thҧ)\xa7\xb6\xbc\x1askͯ9\xe3\x04=Zumַ]熽[\xf6PڳE\aG\xdd\xdbt\xf1\xd8Ƈ\xdbV\x8e\x9b\xb9n缡\xfb~Iܥ\xf5\xebسk\xdfν{\xf4\xdf\xc2\xc1W\xff\x17\xbf\x9c|s\xf3\xcf\xd1\u007f\xa7^\x9e\xfdy\xf7\xe9\xe1\xaf\x17*\u007f:\xfd\xfb\x92\x91\xeb?\xce_zr\xf5\xf6\xe5\xd7\x1f\x80\xff\xd5W ~\xc0\x11\xb8\x9f\u007f\v*8\xa0\x81\rB\xf8 \x82\xe1I\xc8\xe0\x84\x02^\xa8\xa1\x83\x1bZ\xc8\xe1\x87\x1e\x86H\xe1x\"f\b\xe2\x88\xed\xa1\xf8\x9e\x8a\xf1\xb18\x9f\x89%&\x18c\x85.\x06(c\x8d\a\u0088c\x84;bx\xa3\x8e@\xfe($\x8dA\x129$\x89=v\x98\xe4\x89E\"\xd9d\x8aO\xae\x18e\x8bS\xbex$\x94WJ\x99%\x95[Zi\xe4\x97Nvi#\x98X\x92\xa9\xa5\x99\\\xa2\xe9e\x98j\x8e\xc9\xe6\x9be\xc2y\xa6\x9ciҹf\x9cxΙg\x9d{ީ\xe7\x9f|\x02\xeag\xa0\x84\x0ej\xa8\x9b}\"*\xa8\xa2\x852zh\x8ebBڦ\xa4v:j)\xa5\x89b\xba\xa8\xa6\x8dr\xfa(\x8fU^\nj\xa4\xa3NZj\xa5\x9e\x8a꣩\xab\xa2zj\xa6\xafn\xff\x1ak\xa7\xb3~\xda*\xac\xb7ʚ+\xad\xbbڪd\xa8\xa9\x06[\xab\xaa\xbf\x92\xda+\xb1L\x1a[,\xab˺z\xac\xb0\xcf\x0e\vm\xb3\xb8R\xab\xab\xb5\xbcb\xebk\xb2\xccr묶\xc8\xce\xf8\xad\xb7Ւ{\xad\xb9٢\xbb\xad\xb8\xe5\xb2{\xae\xbb\xe9»\xee\x92\xf2\x86K\xef\xbd\xc0J\xabo\xb4\xfc\x82;\xad\xba\xf6\xe6\xdb/\xc0\xff\xd6[0\xbe\xca\x12\xbc\xaf\xbf\v+<\xb0\xc1\rC\xfc0\xc2\xddJ\xcc\xf0\xc4\x02_\xac\xb1\xc3\x1b[\xcc\xf1\xc7\x1e\x87L\xf1\xb8\"g\f\xf2\xc8\xed\xa2\xfc\xae\xca\xf1\xb2<\xaf\xc9%'\x1cs\xc5.\a,s\xcd\aÌs\xc4;c|\xb3\xce@\xff,4\xcdA\x13=4\xc9=w\x9c\xf4\xc9E#\xddt\xcaO\xaf\x1cu\xcbS\xbf|4\xd4WK\x9d5\xd5[[m\xf4\xd7Nwm3\xd8X\x93\xad\xb5\xd9\\\xa3\xedu\xd8j\x8f\xcd\xf6\xdbe\xc3}\xb6\xdciӽv\xdcxϝw\xdd{\xdf\xff\xad\xf7\xdf|\x03\xeew\xe0\x84\x0fn\xb8\xdb}#.\xb8\xe2\x853~x\xcebC\u07b6\xe4v;n9\xe5\x89c\xbe\xb8\xe6\x8ds\xfe8\xcfU_\x0ez\xe4\xa3O^z型\xee\xb3髣~z\xe6\xafo\x1e{\xe7\xb3\u007f\xde:\xec\xb7˞;\xed\xbbۮt\xe8\xa9\a_\xbb꿓\xde;\xf1L\x1b_<\xeb˻~\xbc\xf0\xcf\x0f\x0f}\xf3\xb8S\xaf\xbb\xf5\xbcc\xef{\xf2\xccs\xef\xbc\xf6\xc8\xcf\xfc\xbd\xf7Փ\u007f\xbd\xf9٣\xbf\xbd\xf8\xe5\xb3\u007f\xbe\xfb\xe9ÿ\xfe\xd2\xf2\x87O\xff\xfd\xc0K\xaf\u007f\xf4\xfc\x83?\xbd\xfa\xf6\xcb_\xff\x00\xf8\xbf\xfa\x15\x10\u007f\xca#\xe0\xfe\xfc\xb7@\x05\x0eЀ\r\x84\xe0\x03\x11\xd8=\t2p\x82\x02\xbc\xa0\x06\x1d\xb8A\vr\xf0\x83\x1e\f!\x05\xc7'\xc2\f\x82p\x84\xedC\xe1\xfbT\x18?\x16\xceτ%L`\f+\xe8\xc2\x00ʰ\x86\a\x84!\x0e#\xb8C\f\xdeP\x87@\xfc\xa1\x102i\x18D\"\x0e\x91\x84=\xec`\x12OXD$61\x85O\\a\x14[8\xc5\x17\x1e\x11\x8aW\x94b\x16\xa9\xb8E+\x1a\xf1\x8bN\xec\xa2\ri\b\x12\x90\x04\x04\x00;",
+
+	"images/treeview-gray.gif": "GIF89a`\x00\x85\x00\xa1\x03\x00\x00\x00\x00\x80\x80\x80\xbc\xbc\xbc\xff\xff\xff!\xf9\x04\x01\x00\x00\x03\x00,\x00\x00\x00\x00`\x00\x85\x00\x00\x02\xfe\x9c\x8f\xa9\xcb\xed\x0f\x87\x98\xc2ш\xb3ި\xf2\x0f\x86\x9a'\x96\xa6I\x9e\xeaʶ\xee\x1aIJ\xfc\xd6f\xb0\xe0\xf6\xfe\xe9\x03p\xf0\xf1\x86\x11\x1f\xd0 $*\x198\x80\xd39\x98%\x97Kc\x90\x8aUX\x91\xd9.W\xeb\xedJg\xe1\xf2\xb4,F\xab\xcfj*\xbb\xad|Ç\xf2\xb9*u\xb5\xef\xf0_\xfdh\xf2p\x01\xe67RRG\x98\xc0\x87\xb8\xc8\xd8H8F\xe3\xa8rv(\x89Aiy\x82\x99i\xf8\xf3\x04$\xc5ٓ#*\xb2Y::\x88\xca\x01\x19\xb3\xda\xf9\xaa\x19+;\v[\x1bRyې{\xab\xc8[\xeb;+\xd80\x8c\xf0K\xa8\xa8q여\xeb\xfc\f\rݺ\xfcz\x1a\xadz\x14u\xcdt\x90M\xbd\xda\xf4\x19E\xb6\xdd\xe7]\x8e\x9d\x87\xaen\xbcn\xdc\xea\x1e/?O_\xef\xd5,\x8f\xffJ\x81_\xec\x1c\x9c\x8fT@U\xee\x00\xdac7oZB\x81\xf1\xb6h\x93\xe7\xf0\x1b\xaapO\xc6E*\x17q\xa1\x81ms\x10\x19\xbaSx0\xa4ȑ$%\x90\xd4W\xf0\x9a?\x05+{\x9d|Y2fL\x90\r=\xae\xb3v\xd3&:\x8aPB\xedԉ\x11\xe86\x9c;\xe1\xc9<\x8a4\xe9*\x94똢sZ\xaa\xe5\x01\xa9\xd7$\xea\xb2z\vk-\xad\xb3\xb8\x96\xa2\xf9QhU\xb1ш\x06\xfd\x04\x8a\\P\x829\xd9\xfet\x8bѨҹt\xebڽ\x8b7\xaf\x82\x02\x00;",
+
+	"implements.html": `<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Implements</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Implements</span></p>
+		<div style="margin-left: 1in" id='implements-{{.Index}}'>...</div>
+	</div>
+</div>
+`,
+
+	"jquery.js": `/*! jQuery v1.8.2 jquery.com | jquery.org/license */
+(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call("` + "\xEF\xBB\xBF" + ` ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);`,
+
+	"jquery.treeview.css": `/* https://github.com/jzaefferer/jquery-treeview/blob/master/jquery.treeview.css */
+/* License: MIT. */
+.treeview, .treeview ul {
+	padding: 0;
+	margin: 0;
+	list-style: none;
+}
+
+.treeview ul {
+	background-color: white;
+	margin-top: 4px;
+}
+
+.treeview .hitarea {
+	background: url(images/treeview-default.gif) -64px -25px no-repeat;
+	height: 16px;
+	width: 16px;
+	margin-left: -16px;
+	float: left;
+	cursor: pointer;
+}
+/* fix for IE6 */
+* html .hitarea {
+	display: inline;
+	float:none;
+}
+
+.treeview li {
+	margin: 0;
+	padding: 3px 0pt 3px 16px;
+}
+
+.treeview a.selected {
+	background-color: #eee;
+}
+
+#treecontrol { margin: 1em 0; display: none; }
+
+.treeview .hover { color: red; cursor: pointer; }
+
+.treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; }
+.treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }
+
+.treeview .expandable-hitarea { background-position: -80px -3px; }
+
+.treeview li.last { background-position: 0 -1766px }
+.treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(images/treeview-default.gif); }
+.treeview li.lastCollapsable { background-position: 0 -111px }
+.treeview li.lastExpandable { background-position: -32px -67px }
+
+.treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; }
+
+.treeview-red li { background-image: url(images/treeview-red-line.gif); }
+.treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); }
+
+.treeview-black li { background-image: url(images/treeview-black-line.gif); }
+.treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); }
+
+.treeview-gray li { background-image: url(images/treeview-gray-line.gif); }
+.treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); }
+
+.treeview-famfamfam li { background-image: url(images/treeview-famfamfam-line.gif); }
+.treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); }
+
+.treeview .placeholder {
+	background: url(images/ajax-loader.gif) 0 0 no-repeat;
+	height: 16px;
+	width: 16px;
+	display: block;
+}
+
+.filetree li { padding: 3px 0 2px 16px; }
+.filetree span.folder, .filetree span.file { padding: 1px 0 1px 16px; display: block; }
+.filetree span.folder { background: url(images/folder.gif) 0 0 no-repeat; }
+.filetree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }
+.filetree span.file { background: url(images/file.gif) 0 0 no-repeat; }
+`,
+
+	"jquery.treeview.edit.js": `/* https://github.com/jzaefferer/jquery-treeview/blob/master/jquery.treeview.edit.js */
+/* License: MIT. */
+(function($) {
+	var CLASSES = $.treeview.classes;
+	var proxied = $.fn.treeview;
+	$.fn.treeview = function(settings) {
+		settings = $.extend({}, settings);
+		if (settings.add) {
+			return this.trigger("add", [settings.add]);
+		}
+		if (settings.remove) {
+			return this.trigger("remove", [settings.remove]);
+		}
+		return proxied.apply(this, arguments).bind("add", function(event, branches) {
+			$(branches).prev()
+				.removeClass(CLASSES.last)
+				.removeClass(CLASSES.lastCollapsable)
+				.removeClass(CLASSES.lastExpandable)
+			.find(">.hitarea")
+				.removeClass(CLASSES.lastCollapsableHitarea)
+				.removeClass(CLASSES.lastExpandableHitarea);
+			$(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, $(this).data("toggler"));
+		}).bind("remove", function(event, branches) {
+			var prev = $(branches).prev();
+			var parent = $(branches).parent();
+			$(branches).remove();
+			prev.filter(":last-child").addClass(CLASSES.last)
+				.filter("." + CLASSES.expandable).replaceClass(CLASSES.last, CLASSES.lastExpandable).end()
+				.find(">.hitarea").replaceClass(CLASSES.expandableHitarea, CLASSES.lastExpandableHitarea).end()
+				.filter("." + CLASSES.collapsable).replaceClass(CLASSES.last, CLASSES.lastCollapsable).end()
+				.find(">.hitarea").replaceClass(CLASSES.collapsableHitarea, CLASSES.lastCollapsableHitarea);
+			if (parent.is(":not(:has(>))") && parent[0] != this) {
+				parent.parent().removeClass(CLASSES.collapsable).removeClass(CLASSES.expandable)
+				parent.siblings(".hitarea").andSelf().remove();
+			}
+		});
+	};
+	
+})(jQuery);
+`,
+
+	"jquery.treeview.js": `/*
+ * Treeview 1.4.1 - jQuery plugin to hide and show branches of a tree
+ * 
+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
+ * http://docs.jquery.com/Plugins/Treeview
+ *
+ * Copyright (c) 2007 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.treeview.js 5759 2008-07-01 07:50:28Z joern.zaefferer $
+ *
+ */
+
+;(function($) {
+
+	// TODO rewrite as a widget, removing all the extra plugins
+	$.extend($.fn, {
+		swapClass: function(c1, c2) {
+			var c1Elements = this.filter('.' + c1);
+			this.filter('.' + c2).removeClass(c2).addClass(c1);
+			c1Elements.removeClass(c1).addClass(c2);
+			return this;
+		},
+		replaceClass: function(c1, c2) {
+			return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
+		},
+		hoverClass: function(className) {
+			className = className || "hover";
+			return this.hover(function() {
+				$(this).addClass(className);
+			}, function() {
+				$(this).removeClass(className);
+			});
+		},
+		heightToggle: function(animated, callback) {
+			animated ?
+				this.animate({ height: "toggle" }, animated, callback) :
+				this.each(function(){
+					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+					if(callback)
+						callback.apply(this, arguments);
+				});
+		},
+		heightHide: function(animated, callback) {
+			if (animated) {
+				this.animate({ height: "hide" }, animated, callback);
+			} else {
+				this.hide();
+				if (callback)
+					this.each(callback);				
+			}
+		},
+		prepareBranches: function(settings) {
+			if (!settings.prerendered) {
+				// mark last tree items
+				this.filter(":last-child:not(ul)").addClass(CLASSES.last);
+				// collapse whole tree, or only those marked as closed, anyway except those marked as open
+				this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
+			}
+			// return all items with sublists
+			return this.filter(":has(>ul)");
+		},
+		applyClasses: function(settings, toggler) {
+			// TODO use event delegation
+			this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) {
+				// don't handle click events on children, eg. checkboxes
+				if ( this == event.target )
+					toggler.apply($(this).next());
+			}).add( $("a", this) ).hoverClass();
+			
+			if (!settings.prerendered) {
+				// handle closed ones first
+				this.filter(":has(>ul:hidden)")
+						.addClass(CLASSES.expandable)
+						.replaceClass(CLASSES.last, CLASSES.lastExpandable);
+						
+				// handle open ones
+				this.not(":has(>ul:hidden)")
+						.addClass(CLASSES.collapsable)
+						.replaceClass(CLASSES.last, CLASSES.lastCollapsable);
+						
+	            // create hitarea if not present
+				var hitarea = this.find("div." + CLASSES.hitarea);
+				if (!hitarea.length)
+					hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea);
+				hitarea.removeClass().addClass(CLASSES.hitarea).each(function() {
+					var classes = "";
+					$.each($(this).parent().attr("class").split(" "), function() {
+						classes += this + "-hitarea ";
+					});
+					$(this).addClass( classes );
+				})
+			}
+			
+			// apply event to hitarea
+			this.find("div." + CLASSES.hitarea).click( toggler );
+		},
+		treeview: function(settings) {
+			
+			settings = $.extend({
+				cookieId: "treeview"
+			}, settings);
+			
+			if ( settings.toggle ) {
+				var callback = settings.toggle;
+				settings.toggle = function() {
+					return callback.apply($(this).parent()[0], arguments);
+				};
+			}
+		
+			// factory for treecontroller
+			function treeController(tree, control) {
+				// factory for click handlers
+				function handler(filter) {
+					return function() {
+						// reuse toggle event handler, applying the elements to toggle
+						// start searching for all hitareas
+						toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
+							// for plain toggle, no filter is provided, otherwise we need to check the parent element
+							return filter ? $(this).parent("." + filter).length : true;
+						}) );
+						return false;
+					};
+				}
+				// click on first element to collapse tree
+				$("a:eq(0)", control).click( handler(CLASSES.collapsable) );
+				// click on second to expand tree
+				$("a:eq(1)", control).click( handler(CLASSES.expandable) );
+				// click on third to toggle tree
+				$("a:eq(2)", control).click( handler() ); 
+			}
+		
+			// handle toggle event
+			function toggler() {
+				$(this)
+					.parent()
+					// swap classes for hitarea
+					.find(">.hitarea")
+						.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+						.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+					.end()
+					// swap classes for parent li
+					.swapClass( CLASSES.collapsable, CLASSES.expandable )
+					.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+					// find child lists
+					.find( ">ul" )
+					// toggle them
+					.heightToggle( settings.animated, settings.toggle );
+				if ( settings.unique ) {
+					$(this).parent()
+						.siblings()
+						// swap classes for hitarea
+						.find(">.hitarea")
+							.replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+							.replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+						.end()
+						.replaceClass( CLASSES.collapsable, CLASSES.expandable )
+						.replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+						.find( ">ul" )
+						.heightHide( settings.animated, settings.toggle );
+				}
+			}
+			this.data("toggler", toggler);
+			
+			function serialize() {
+				function binary(arg) {
+					return arg ? 1 : 0;
+				}
+				var data = [];
+				branches.each(function(i, e) {
+					data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
+				});
+				$.cookie(settings.cookieId, data.join(""), settings.cookieOptions );
+			}
+			
+			function deserialize() {
+				var stored = $.cookie(settings.cookieId);
+				if ( stored ) {
+					var data = stored.split("");
+					branches.each(function(i, e) {
+						$(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
+					});
+				}
+			}
+			
+			// add treeview class to activate styles
+			this.addClass("treeview");
+			
+			// prepare branches and find all tree items with child lists
+			var branches = this.find("li").prepareBranches(settings);
+			
+			switch(settings.persist) {
+			case "cookie":
+				var toggleCallback = settings.toggle;
+				settings.toggle = function() {
+					serialize();
+					if (toggleCallback) {
+						toggleCallback.apply(this, arguments);
+					}
+				};
+				deserialize();
+				break;
+			case "location":
+				var current = this.find("a").filter(function() {
+					return this.href.toLowerCase() == location.href.toLowerCase();
+				});
+				if ( current.length ) {
+					// TODO update the open/closed classes
+					var items = current.addClass("selected").parents("ul, li").add( current.next() ).show();
+					if (settings.prerendered) {
+						// if prerendered is on, replicate the basic class swapping
+						items.filter("li")
+							.swapClass( CLASSES.collapsable, CLASSES.expandable )
+							.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+							.find(">.hitarea")
+								.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+								.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea );
+					}
+				}
+				break;
+			}
+			
+			branches.applyClasses(settings, toggler);
+				
+			// if control option is set, create the treecontroller and show it
+			if ( settings.control ) {
+				treeController(this, settings.control);
+				$(settings.control).show();
+			}
+			
+			return this;
+		}
+	});
+	
+	// classes used by the plugin
+	// need to be styled via external stylesheet, see first example
+	$.treeview = {};
+	var CLASSES = ($.treeview.classes = {
+		open: "open",
+		closed: "closed",
+		expandable: "expandable",
+		expandableHitarea: "expandable-hitarea",
+		lastExpandableHitarea: "lastExpandable-hitarea",
+		collapsable: "collapsable",
+		collapsableHitarea: "collapsable-hitarea",
+		lastCollapsableHitarea: "lastCollapsable-hitarea",
+		lastCollapsable: "lastCollapsable",
+		lastExpandable: "lastExpandable",
+		last: "last",
+		hitarea: "hitarea"
+	});
+	
+})(jQuery);
+`,
+
+	"methodset.html": `<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Method set</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Method set</span></p>
+		<div style="margin-left: 1in" id='methodset-{{.Index}}'>...</div>
+	</div>
+</div>
+`,
+
+	"opensearch.xml": `<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <ShortName>godoc</ShortName>
+  <Description>The Go Programming Language</Description>
+  <Tags>go golang</Tags>
+  <Contact />
+  <Url type="text/html" template="{{.BaseURL}}/search?q={searchTerms}" />
+  <Image height="15" width="16" type="image/x-icon">/favicon.ico</Image>
+  <OutputEncoding>UTF-8</OutputEncoding>
+  <InputEncoding>UTF-8</InputEncoding>
+</OpenSearchDescription>
+`,
+
+	"package.html": `<!--
+	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.
+-->
+<!--
+	Note: Static (i.e., not template-generated) href and id
+	attributes start with "pkg-" to make it impossible for
+	them to conflict with generated attributes (some of which
+	correspond to Go identifiers).
+-->
+{{with .PDoc}}
+	<script type='text/javascript'>
+	document.ANALYSIS_DATA = {{$.AnalysisData}};
+	document.CALLGRAPH = {{$.CallGraph}};
+	</script>
+
+	{{if $.IsMain}}
+		{{/* command documentation */}}
+		{{comment_html .Doc}}
+	{{else}}
+		{{/* package documentation */}}
+		<div id="short-nav">
+			<dl>
+			<dd><code>import "{{html .ImportPath}}"</code></dd>
+			</dl>
+			<dl>
+			<dd><a href="#pkg-overview" class="overviewLink">Overview</a></dd>
+			<dd><a href="#pkg-index" class="indexLink">Index</a></dd>
+			{{if $.Examples}}
+				<dd><a href="#pkg-examples" class="examplesLink">Examples</a></dd>
+			{{end}}
+			{{if $.Dirs}}
+				<dd><a href="#pkg-subdirectories">Subdirectories</a></dd>
+			{{end}}
+			</dl>
+		</div>
+		<!-- The package's Name is printed as title by the top-level template -->
+		<div id="pkg-overview" class="toggleVisible">
+			<div class="collapsed">
+				<h2 class="toggleButton" title="Click to show Overview section">Overview ▹</h2>
+			</div>
+			<div class="expanded">
+				<h2 class="toggleButton" title="Click to hide Overview section">Overview ▾</h2>
+				{{comment_html .Doc}}
+			</div>
+		</div>
+		{{example_html $ ""}}
+
+		<div id="pkg-index" class="toggleVisible">
+		<div class="collapsed">
+			<h2 class="toggleButton" title="Click to show Index section">Index ▹</h2>
+		</div>
+		<div class="expanded">
+			<h2 class="toggleButton" title="Click to hide Index section">Index ▾</h2>
+
+		<!-- Table of contents for API; must be named manual-nav to turn off auto nav. -->
+			<div id="manual-nav">
+			<dl>
+			{{if .Consts}}
+				<dd><a href="#pkg-constants">Constants</a></dd>
+			{{end}}
+			{{if .Vars}}
+				<dd><a href="#pkg-variables">Variables</a></dd>
+			{{end}}
+			{{range .Funcs}}
+				{{$name_html := html .Name}}
+				<dd><a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+			{{end}}
+			{{range .Types}}
+				{{$tname_html := html .Name}}
+				<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
+				{{range .Funcs}}
+					{{$name_html := html .Name}}
+					<dd>&nbsp; &nbsp; <a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+				{{end}}
+				{{range .Methods}}
+					{{$name_html := html .Name}}
+					<dd>&nbsp; &nbsp; <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+				{{end}}
+			{{end}}
+			{{if $.Notes}}
+				{{range $marker, $item := $.Notes}}
+				<dd><a href="#pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</a></dd>
+				{{end}}
+			{{end}}
+			</dl>
+			</div><!-- #manual-nav -->
+
+		{{if $.Examples}}
+		<div id="pkg-examples">
+			<h4>Examples</h4>
+			<dl>
+			{{range $.Examples}}
+			<dd><a class="exampleLink" href="#example_{{.Name}}">{{example_name .Name}}</a></dd>
+			{{end}}
+			</dl>
+		</div>
+		{{end}}
+
+		{{with .Filenames}}
+			<h4>Package files</h4>
+			<p>
+			<span style="font-size:90%">
+			{{range .}}
+				<a href="{{.|srcLink|html}}">{{.|filename|html}}</a>
+			{{end}}
+			</span>
+			</p>
+		{{end}}
+		</div><!-- .expanded -->
+		</div><!-- #pkg-index -->
+
+		<div id="pkg-callgraph" class="toggle" style="display: none">
+		<div class="collapsed">
+			<h2 class="toggleButton" title="Click to show Internal Call Graph section">Internal call graph ▹</h2>
+		</div> <!-- .expanded -->
+		<div class="expanded">
+			<h2 class="toggleButton" title="Click to hide Internal Call Graph section">Internal call graph ▾</h2>
+			<p>
+			  In the call graph viewer below, each node
+			  is a function belonging to this package
+			  and its children are the functions it
+			  calls&mdash;perhaps dynamically.
+			</p>
+			<p>
+			  The root nodes are the entry points of the
+			  package: functions that may be called from
+			  outside the package.
+			  There may be non-exported or anonymous
+			  functions among them if they are called
+			  dynamically from another package.
+			</p>
+			<p>
+			  Click a node to visit that function's source code.
+			  From there you can visit its callers by
+			  clicking its declaring <code>func</code>
+			  token.
+			</p>
+			<p>
+			  Functions may be omitted if they were
+			  determined to be unreachable in the
+			  particular programs or tests that were
+			  analyzed.
+			</p>
+			<!-- Zero means show all package entry points. -->
+			<ul style="margin-left: 0.5in" id="callgraph-0" class="treeview"></ul>
+		</div>
+		</div> <!-- #pkg-callgraph -->
+
+		{{with .Consts}}
+			<h2 id="pkg-constants">Constants</h2>
+			{{range .}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+		{{end}}
+		{{with .Vars}}
+			<h2 id="pkg-variables">Variables</h2>
+			{{range .}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+		{{end}}
+		{{range .Funcs}}
+			{{/* Name is a string - no need for FSet */}}
+			{{$name_html := html .Name}}
+			<h2 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h2>
+			<pre>{{node_html $ .Decl true}}</pre>
+			{{comment_html .Doc}}
+			{{example_html $ .Name}}
+			{{callgraph_html $ "" .Name}}
+
+		{{end}}
+		{{range .Types}}
+			{{$tname := .Name}}
+			{{$tname_html := html .Name}}
+			<h2 id="{{$tname_html}}">type <a href="{{posLink_url $ .Decl}}">{{$tname_html}}</a></h2>
+			<pre>{{node_html $ .Decl true}}</pre>
+			{{comment_html .Doc}}
+
+			{{range .Consts}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+
+			{{range .Vars}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+
+			{{example_html $ $tname}}
+			{{implements_html $ $tname}}
+			{{methodset_html $ $tname}}
+
+			{{range .Funcs}}
+				{{$name_html := html .Name}}
+				<h3 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+				{{example_html $ .Name}}
+				{{callgraph_html $ "" .Name}}
+			{{end}}
+
+			{{range .Methods}}
+				{{$name_html := html .Name}}
+				<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+				{{$name := printf "%s_%s" $tname .Name}}
+				{{example_html $ $name}}
+				{{callgraph_html $ .Recv .Name}}
+			{{end}}
+		{{end}}
+	{{end}}
+
+	{{with $.Notes}}
+		{{range $marker, $content := .}}
+			<h2 id="pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</h2>
+			<ul style="list-style: none; padding: 0;">
+			{{range .}}
+			<li><a href="{{posLink_url $ .}}">&#x261e;</a> {{html .Body}}</li>
+			{{end}}
+			</ul>
+		{{end}}
+	{{end}}
+{{end}}
+
+{{with .PAst}}
+	{{range $filename, $ast := .}}
+		<a href="{{$filename|srcLink|html}}">{{$filename|filename|html}}</a>:<pre>{{node_html $ $ast false}}</pre>
+	{{end}}
+{{end}}
+
+{{with .Dirs}}
+	{{/* DirList entries are numbers and strings - no need for FSet */}}
+	{{if $.PDoc}}
+		<h2 id="pkg-subdirectories">Subdirectories</h2>
+	{{end}}
+	{{if eq $.Dirname "/src"}}
+		<div id="manual-nav">
+			<dl>
+				<dt><a href="#stdlib">Standard library</a></dt>
+				<dt><a href="#other">Other packages</a></dt>
+				<dd><a href="#subrepo">Sub-repositories</a></dd>
+				<dd><a href="#community">Community</a></dd>
+			</dl>
+		</div>
+		<h2 id="stdlib">Standard library</h2>
+		<img class="gopher" src="/doc/gopher/pkg.png"/>
+	{{end}}
+	<table class="dir">
+	<tr>
+	<th>Name</th>
+	<th>&nbsp;&nbsp;&nbsp;&nbsp;</th>
+	<th style="text-align: left; width: auto">Synopsis</th>
+	</tr>
+	{{if not (or (eq $.Dirname "/src") (eq $.Dirname "/src/cmd") $.DirFlat)}}
+		<tr>
+		<td><a href="..">..</a></td>
+		</tr>
+	{{end}}
+	{{range .List}}
+		{{if $.DirFlat}}
+			{{if .HasPkg}}
+				<tr>
+				<td class="name"><a href="{{html .Path}}/">{{html .Path}}</a></td>
+				<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+				<td style="width: auto">{{html .Synopsis}}</td>
+				</tr>
+			{{end}}
+		{{else}}
+			<tr>
+			<td class="name">{{repeat ` + "`" + `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;` + "`" + ` .Depth}}<a href="{{html .Path}}/">{{html .Name}}</a></td>
+			<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+			<td style="width: auto">{{html .Synopsis}}</td>
+			</tr>
+		{{end}}
+	{{end}}
+	</table>
+
+	{{if eq $.Dirname "/src"}}
+	<h2 id="other">Other packages</h2>
+
+	<h3 id="subrepo">Sub-repositories</h3>
+	<p>
+	These packages are part of the Go Project but outside the main Go tree.
+	They are developed under looser <a href="/doc/go1compat">compatibility requirements</a> than the Go core.
+	Install them with "<a href="/cmd/go/#hdr-Download_and_install_packages_and_dependencies">go get</a>".
+	</p>
+	<ul>
+		<li><a href="//godoc.org/golang.org/x/crypto">crypto</a> — additional cryptography packages.</li>
+		<li><a href="//godoc.org/golang.org/x/image">image</a> — additional imaging packages.</li>
+		<li><a href="//godoc.org/golang.org/x/net">net</a> — additional networking packages.</li>
+		<li><a href="//godoc.org/golang.org/x/sys">sys</a> — packages for making system calls.</li>
+		<li><a href="//godoc.org/golang.org/x/text">text</a> — packages for working with text.</li>
+		<li><a href="//godoc.org/golang.org/x/tools">tools</a> — godoc, vet, cover, and other tools.</li>
+		<li><a href="//godoc.org/golang.org/x/exp">exp</a> — experimental code (handle with care; may change without warning).</li>
+	</ul>
+
+	<h3 id="community">Community</h3>
+	<p>
+	These services can help you find Open Source packages provided by the community.
+	</p>
+	<ul>
+		<li><a href="//godoc.org">GoDoc</a> - a package index and search engine.</li>
+		<li><a href="http://go-search.org">Go Search</a> - a code search engine.</li>
+		<li><a href="/wiki/Projects">Projects at the Go Wiki</a> - a curated list of Go projects.</li>
+	</ul>
+	{{end}}
+{{end}}
+`,
+
+	"package.txt": `{{$info := .}}{{$filtered := .IsFiltered}}{{/*
+
+---------------------------------------
+
+*/}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
+{{node $ $ast}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if and $filtered (not (or .PDoc .PAst))}}No match found.
+{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND DOCUMENTATION
+
+{{comment_text .Doc "    " "\t"}}
+{{else}}{{if not $filtered}}PACKAGE DOCUMENTATION
+
+package {{.Name}}
+    import "{{.ImportPath}}"
+
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ "" "    "}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Consts}}{{if not $filtered}}CONSTANTS
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Vars}}{{if not $filtered}}VARIABLES
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Funcs}}{{if not $filtered}}FUNCTIONS
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ .Name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Types}}{{if not $filtered}}TYPES
+
+{{end}}{{range .}}{{$tname := .Name}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{/*
+
+---------------------------------------
+
+*/}}{{if .Consts}}{{range .Consts}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Vars}}{{range .Vars}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{range $name := .Names}}{{example_text $ $name "    "}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Funcs}}{{range .Funcs}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ .Name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Methods}}{{range .Methods}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{$name := printf "%s_%s" $tname .Name}}{{example_text $ $name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if and $filtered (not (or .Consts (or .Vars (or .Funcs .Types))))}}No match found.
+{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with $.Notes}}
+{{range $marker, $content := .}}
+{{$marker}}S
+
+{{range $content}}{{comment_text .Body "   " "\t"}}
+{{end}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if not $filtered}}{{with .Dirs}}SUBDIRECTORIES
+{{if $.DirFlat}}{{range .List}}{{if .HasPkg}}
+	{{.Path}}{{end}}{{end}}
+{{else}}{{range .List}}
+	{{repeat ` + "`" + `. ` + "`" + ` .Depth}}{{.Name}}{{end}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{/*
+Make sure there is no newline at the end of this file.
+perl -i -pe 'chomp if eof' package.txt
+*/}}
+`,
+
+	"play.js": `// 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.
+
+function initPlayground(transport) {
+	"use strict";
+
+	function text(node) {
+		var s = "";
+		for (var i = 0; i < node.childNodes.length; i++) {
+			var n = node.childNodes[i];
+			if (n.nodeType === 1) {
+				if (n.tagName === "BUTTON") continue
+				if (n.tagName === "SPAN" && n.className === "number") continue;
+				if (n.tagName === "DIV" || n.tagName == "BR") {
+					s += "\n";
+				}
+				s += text(n);
+				continue;
+			}
+			if (n.nodeType === 3) {
+				s += n.nodeValue;
+			}
+		}
+		return s.replace("\xA0", " "); // replace non-breaking spaces
+	}
+
+	function init(code) {
+		var output = document.createElement('div');
+		var outpre = document.createElement('pre');
+		var running;
+
+		if ($ && $(output).resizable) {
+			$(output).resizable({
+				handles: "n,w,nw",
+				minHeight:	27,
+				minWidth:	135,
+				maxHeight: 608,
+				maxWidth:	990
+			});
+		}
+
+		function onKill() {
+			if (running) running.Kill();
+		}
+
+		function onRun(e) {
+			onKill();
+			output.style.display = "block";
+			outpre.innerHTML = "";
+			run1.style.display = "none";
+			var options = {Race: e.shiftKey};
+			running = transport.Run(text(code), PlaygroundOutput(outpre), options);
+		}
+
+		function onClose() {
+			onKill();
+			output.style.display = "none";
+			run1.style.display = "inline-block";
+		}
+
+		var run1 = document.createElement('button');
+		run1.innerHTML = 'Run';
+		run1.className = 'run';
+		run1.addEventListener("click", onRun, false);
+		var run2 = document.createElement('button');
+		run2.className = 'run';
+		run2.innerHTML = 'Run';
+		run2.addEventListener("click", onRun, false);
+		var kill = document.createElement('button');
+		kill.className = 'kill';
+		kill.innerHTML = 'Kill';
+		kill.addEventListener("click", onKill, false);
+		var close = document.createElement('button');
+		close.className = 'close';
+		close.innerHTML = 'Close';
+		close.addEventListener("click", onClose, false);
+
+		var button = document.createElement('div');
+		button.classList.add('buttons');
+		button.appendChild(run1);
+		// Hack to simulate insertAfter
+		code.parentNode.insertBefore(button, code.nextSibling);
+
+		var buttons = document.createElement('div');
+		buttons.classList.add('buttons');
+		buttons.appendChild(run2);
+		buttons.appendChild(kill);
+		buttons.appendChild(close);
+
+		output.classList.add('output');
+		output.appendChild(buttons);
+		output.appendChild(outpre);
+		output.style.display = "none";
+		code.parentNode.insertBefore(output, button.nextSibling);
+	}
+
+	var play = document.querySelectorAll('div.playground');
+	for (var i = 0; i < play.length; i++) {
+		init(play[i]);
+	}
+}
+
+`,
+
+	"playground.js": `// 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.
+
+/*
+In the absence of any formal way to specify interfaces in JavaScript,
+here's a skeleton implementation of a playground transport.
+
+        function Transport() {
+                // Set up any transport state (eg, make a websocket connnection).
+                return {
+                        Run: function(body, output, options) {
+                                // Compile and run the program 'body' with 'options'.
+				// Call the 'output' callback to display program output.
+                                return {
+                                        Kill: function() {
+                                                // Kill the running program.
+                                        }
+                                };
+                        }
+                };
+        }
+
+	// The output callback is called multiple times, and each time it is
+	// passed an object of this form.
+        var write = {
+                Kind: 'string', // 'start', 'stdout', 'stderr', 'end'
+                Body: 'string'  // content of write or end status message
+        }
+
+	// The first call must be of Kind 'start' with no body.
+	// Subsequent calls may be of Kind 'stdout' or 'stderr'
+	// and must have a non-null Body string.
+	// The final call should be of Kind 'end' with an optional
+	// Body string, signifying a failure ("killed", for example).
+
+	// The output callback must be of this form.
+	// See PlaygroundOutput (below) for an implementation.
+        function outputCallback(write) {
+        }
+*/
+
+function HTTPTransport() {
+	'use strict';
+
+	// TODO(adg): support stderr
+
+	function playback(output, events) {
+		var timeout;
+		output({Kind: 'start'});
+		function next() {
+			if (events.length === 0) {
+				output({Kind: 'end'});
+				return;
+			}
+			var e = events.shift();
+			if (e.Delay === 0) {
+				output({Kind: 'stdout', Body: e.Message});
+				next();
+				return;
+			}
+			timeout = setTimeout(function() {
+				output({Kind: 'stdout', Body: e.Message});
+				next();
+			}, e.Delay / 1000000);
+		}
+		next();
+		return {
+			Stop: function() {
+				clearTimeout(timeout);
+			}
+		}
+	}
+
+	function error(output, msg) {
+		output({Kind: 'start'});
+		output({Kind: 'stderr', Body: msg});
+		output({Kind: 'end'});
+	}
+
+	var seq = 0;
+	return {
+		Run: function(body, output, options) {
+			seq++;
+			var cur = seq;
+			var playing;
+			$.ajax('/compile', {
+				type: 'POST',
+				data: {'version': 2, 'body': body},
+				dataType: 'json',
+				success: function(data) {
+					if (seq != cur) return;
+					if (!data) return;
+					if (playing != null) playing.Stop();
+					if (data.Errors) {
+						error(output, data.Errors);
+						return;
+					}
+					playing = playback(output, data.Events);
+				},
+				error: function() {
+					error(output, 'Error communicating with remote server.');
+				}
+			});
+			return {
+				Kill: function() {
+					if (playing != null) playing.Stop();
+					output({Kind: 'end', Body: 'killed'});
+				}
+			};
+		}
+	};
+}
+
+function SocketTransport() {
+	'use strict';
+
+	var id = 0;
+	var outputs = {};
+	var started = {};
+	var websocket = new WebSocket('ws://' + window.location.host + '/socket');
+
+	websocket.onclose = function() {
+		console.log('websocket connection closed');
+	}
+
+	websocket.onmessage = function(e) {
+		var m = JSON.parse(e.data);
+		var output = outputs[m.Id];
+		if (output === null)
+			return;
+		if (!started[m.Id]) {
+			output({Kind: 'start'});
+			started[m.Id] = true;
+		}
+		output({Kind: m.Kind, Body: m.Body});
+	}
+
+	function send(m) {
+		websocket.send(JSON.stringify(m));
+	}
+
+	return {
+		Run: function(body, output, options) {
+			var thisID = id+'';
+			id++;
+			outputs[thisID] = output;
+			send({Id: thisID, Kind: 'run', Body: body, Options: options});
+			return {
+				Kill: function() {
+					send({Id: thisID, Kind: 'kill'});
+				}
+			};
+		}
+	};
+}
+
+function PlaygroundOutput(el) {
+	'use strict';
+
+	return function(write) {
+		if (write.Kind == 'start') {
+			el.innerHTML = '';
+			return;
+		}
+
+		var cl = 'system';
+		if (write.Kind == 'stdout' || write.Kind == 'stderr')
+			cl = write.Kind;
+
+		var m = write.Body;
+		if (write.Kind == 'end') 
+			m = '\nProgram exited' + (m?(': '+m):'.');
+
+		if (m.indexOf('IMAGE:') === 0) {
+			// TODO(adg): buffer all writes before creating image
+			var url = 'data:image/png;base64,' + m.substr(6);
+			var img = document.createElement('img');
+			img.src = url;
+			el.appendChild(img);
+			return;
+		}
+
+		// ^L clears the screen.
+		var s = m.split('\x0c');
+		if (s.length > 1) {
+			el.innerHTML = '';
+			m = s.pop();
+		}
+
+		m = m.replace(/&/g, '&amp;');
+		m = m.replace(/</g, '&lt;');
+		m = m.replace(/>/g, '&gt;');
+
+		var needScroll = (el.scrollTop + el.offsetHeight) == el.scrollHeight;
+
+		var span = document.createElement('span');
+		span.className = cl;
+		span.innerHTML = m;
+		el.appendChild(span);
+
+		if (needScroll)
+			el.scrollTop = el.scrollHeight - el.offsetHeight;
+	}
+}
+
+(function() {
+  function lineHighlight(error) {
+    var regex = /prog.go:([0-9]+)/g;
+    var r = regex.exec(error);
+    while (r) {
+      $(".lines div").eq(r[1]-1).addClass("lineerror");
+      r = regex.exec(error);
+    }
+  }
+  function highlightOutput(wrappedOutput) {
+    return function(write) {
+      if (write.Body) lineHighlight(write.Body);
+      wrappedOutput(write);
+    }
+  }
+  function lineClear() {
+    $(".lineerror").removeClass("lineerror");
+  }
+
+  // opts is an object with these keys
+  //  codeEl - code editor element
+  //  outputEl - program output element
+  //  runEl - run button element
+  //  fmtEl - fmt button element (optional)
+  //  fmtImportEl - fmt "imports" checkbox element (optional)
+  //  shareEl - share button element (optional)
+  //  shareURLEl - share URL text input element (optional)
+  //  shareRedirect - base URL to redirect to on share (optional)
+  //  toysEl - toys select element (optional)
+  //  enableHistory - enable using HTML5 history API (optional)
+  //  transport - playground transport to use (default is HTTPTransport)
+  function playground(opts) {
+    var code = $(opts.codeEl);
+    var transport = opts['transport'] || new HTTPTransport();
+    var running;
+  
+    // autoindent helpers.
+    function insertTabs(n) {
+      // find the selection start and end
+      var start = code[0].selectionStart;
+      var end   = code[0].selectionEnd;
+      // split the textarea content into two, and insert n tabs
+      var v = code[0].value;
+      var u = v.substr(0, start);
+      for (var i=0; i<n; i++) {
+        u += "\t";
+      }
+      u += v.substr(end);
+      // set revised content
+      code[0].value = u;
+      // reset caret position after inserted tabs
+      code[0].selectionStart = start+n;
+      code[0].selectionEnd = start+n;
+    }
+    function autoindent(el) {
+      var curpos = el.selectionStart;
+      var tabs = 0;
+      while (curpos > 0) {
+        curpos--;
+        if (el.value[curpos] == "\t") {
+          tabs++;
+        } else if (tabs > 0 || el.value[curpos] == "\n") {
+          break;
+        }
+      }
+      setTimeout(function() {
+        insertTabs(tabs);
+      }, 1);
+    }
+  
+    function keyHandler(e) {
+      if (e.keyCode == 9 && !e.ctrlKey) { // tab (but not ctrl-tab)
+        insertTabs(1);
+        e.preventDefault();
+        return false;
+      }
+      if (e.keyCode == 13) { // enter
+        if (e.shiftKey) { // +shift
+          run();
+          e.preventDefault();
+          return false;
+        } if (e.ctrlKey) { // +control
+          fmt();
+          e.preventDefault();
+        } else {
+          autoindent(e.target);
+        }
+      }
+      return true;
+    }
+    code.unbind('keydown').bind('keydown', keyHandler);
+    var outdiv = $(opts.outputEl).empty();
+    var output = $('<pre/>').appendTo(outdiv);
+  
+    function body() {
+      return $(opts.codeEl).val();
+    }
+    function setBody(text) {
+      $(opts.codeEl).val(text);
+    }
+    function origin(href) {
+      return (""+href).split("/").slice(0, 3).join("/");
+    }
+  
+    var pushedEmpty = (window.location.pathname == "/");
+    function inputChanged() {
+      if (pushedEmpty) {
+        return;
+      }
+      pushedEmpty = true;
+      $(opts.shareURLEl).hide();
+      window.history.pushState(null, "", "/");
+    }
+    function popState(e) {
+      if (e === null) {
+        return;
+      }
+      if (e && e.state && e.state.code) {
+        setBody(e.state.code);
+      }
+    }
+    var rewriteHistory = false;
+    if (window.history && window.history.pushState && window.addEventListener && opts.enableHistory) {
+      rewriteHistory = true;
+      code[0].addEventListener('input', inputChanged);
+      window.addEventListener('popstate', popState);
+    }
+
+    function setError(error) {
+      if (running) running.Kill();
+      lineClear();
+      lineHighlight(error);
+      output.empty().addClass("error").text(error);
+    }
+    function loading() {
+      lineClear();
+      if (running) running.Kill();
+      output.removeClass("error").text('Waiting for remote server...');
+    }
+    function run() {
+      loading();
+      running = transport.Run(body(), highlightOutput(PlaygroundOutput(output[0])));
+    }
+
+    function fmt() {
+      loading();
+      var data = {"body": body()}; 
+      if ($(opts.fmtImportEl).is(":checked")) {
+        data["imports"] = "true";
+      }
+      $.ajax("/fmt", {
+        data: data,
+        type: "POST",
+        dataType: "json",
+        success: function(data) {
+          if (data.Error) {
+            setError(data.Error);
+          } else {
+            setBody(data.Body);
+            setError("");
+          }
+        }
+      });
+    }
+
+    $(opts.runEl).click(run);
+    $(opts.fmtEl).click(fmt);
+
+    if (opts.shareEl !== null && (opts.shareURLEl !== null || opts.shareRedirect !== null)) {
+      var shareURL;
+      if (opts.shareURLEl) {
+        shareURL = $(opts.shareURLEl).hide();
+      }
+      var sharing = false;
+      $(opts.shareEl).click(function() {
+        if (sharing) return;
+        sharing = true;
+        var sharingData = body();
+        $.ajax("/share", {
+          processData: false,
+          data: sharingData,
+          type: "POST",
+          complete: function(xhr) {
+            sharing = false;
+            if (xhr.status != 200) {
+              alert("Server error; try again.");
+              return;
+            }
+            if (opts.shareRedirect) {
+              window.location = opts.shareRedirect + xhr.responseText;
+            }
+            if (shareURL) {
+              var path = "/p/" + xhr.responseText;
+              var url = origin(window.location) + path;
+              shareURL.show().val(url).focus().select();
+  
+              if (rewriteHistory) {
+                var historyData = {"code": sharingData};
+                window.history.pushState(historyData, "", path);
+                pushedEmpty = false;
+              }
+            }
+          }
+        });
+      });
+    }
+  
+    if (opts.toysEl !== null) {
+      $(opts.toysEl).bind('change', function() {
+        var toy = $(this).val();
+        $.ajax("/doc/play/"+toy, {
+          processData: false,
+          type: "GET",
+          complete: function(xhr) {
+            if (xhr.status != 200) {
+              alert("Server error; try again.");
+              return;
+            }
+            setBody(xhr.responseText);
+          }
+        });
+      });
+    }
+  }
+
+  window.playground = playground;
+})();
+`,
+
+	"search.html": `<!--
+	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.
+-->
+{{with .Alert}}
+	<p>
+	<span class="alert" style="font-size:120%">{{html .}}</span>
+	</p>
+{{end}}
+{{with .Alt}}
+	<p>
+	<span class="alert" style="font-size:120%">Did you mean: </span>
+	{{range .Alts}}
+		<a href="search?q={{urlquery .}}" style="font-size:120%">{{html .}}</a>
+	{{end}}
+	</p>
+{{end}}
+`,
+
+	"search.txt": `QUERY
+	{{.Query}}
+
+{{with .Alert}}{{.}}
+{{end}}{{/* .Alert */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Alt}}DID YOU MEAN
+
+{{range .Alts}}	{{.}}
+{{end}}
+{{end}}{{/* .Alt */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Pak}}PACKAGE {{$.Query}}
+
+{{range .}}	{{pkgLink .Pak.Path}}
+{{end}}
+{{end}}{{/* .Pak */}}{{/*
+
+---------------------------------------
+
+*/}}{{range $key, $val := .Idents}}{{if $val}}{{$key.Name}}
+{{range $val.Idents}}    {{.Path}}.{{.Name}}
+{{end}}
+{{end}}{{end}}{{/* .Idents */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Hit}}{{with .Decls}}PACKAGE-LEVEL DECLARATIONS
+
+{{range .}}package {{.Pak.Name}}
+{{range $file := .Files}}{{range .Groups}}{{range .}}	{{srcLink $file.File.Path}}:{{infoLine .}}{{end}}
+{{end}}{{end}}{{/* .Files */}}
+{{end}}{{end}}{{/* .Decls */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Others}}LOCAL DECLARATIONS AND USES
+
+{{range .}}package {{.Pak.Name}}
+{{range $file := .Files}}{{range .Groups}}{{range .}}	{{srcLink $file.File.Path}}:{{infoLine .}}
+{{end}}{{end}}{{end}}{{/* .Files */}}
+{{end}}{{end}}{{/* .Others */}}{{end}}{{/* .Hit */}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Textual}}{{if .Complete}}{{.Found}} TEXTUAL OCCURRENCES{{else}}MORE THAN {{.Found}} TEXTUAL OCCURRENCES{{end}}
+
+{{range .Textual}}{{len .Lines}}	{{srcLink .Filename}}
+{{end}}{{if not .Complete}}...	...
+{{end}}{{end}}
+`,
+
+	"searchcode.html": `<!--
+	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.
+-->
+{{$query_url := urlquery .Query}}
+{{if not .Idents}}
+	{{with .Pak}}
+		<h2 id="Packages">Package {{html $.Query}}</h2>
+		<p>
+		<table class="layout">
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<tr><td><a href="/{{$pkg_html}}">{{$pkg_html}}</a></td></tr>
+		{{end}}
+		</table>
+		</p>
+	{{end}}
+{{end}}
+{{with .Hit}}
+	{{with .Decls}}
+		<h2 id="Global">Package-level declarations</h2>
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<h3 id="Global_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
+			{{range .Files}}
+				{{$file := .File.Path}}
+				{{range .Groups}}
+					{{range .}}
+						{{$line := infoLine .}}
+						<a href="{{queryLink $file $query_url $line | html}}">{{$file}}:{{$line}}</a>
+						{{infoSnippet_html .}}
+					{{end}}
+				{{end}}
+			{{end}}
+		{{end}}
+	{{end}}
+	{{with .Others}}
+		<h2 id="Local">Local declarations and uses</h2>
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<h3 id="Local_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
+			{{range .Files}}
+				{{$file := .File.Path}}
+				<a href="{{queryLink $file $query_url 0 | html}}">{{$file}}</a>
+				<table class="layout">
+				{{range .Groups}}
+					<tr>
+					<td width="25"></td>
+					<th align="left" valign="top">{{index . 0 | infoKind_html}}</th>
+					<td align="left" width="4"></td>
+					<td>
+					{{range .}}
+						{{$line := infoLine .}}
+						<a href="{{queryLink $file $query_url $line | html}}">{{$line}}</a>
+					{{end}}
+					</td>
+					</tr>
+				{{end}}
+				</table>
+			{{end}}
+		{{end}}
+	{{end}}
+{{end}}
+`,
+
+	"searchdoc.html": `<!--
+	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.
+-->
+{{range $key, $val := .Idents}}
+	{{if $val}}
+		<h2 id="{{$key.Name}}">{{$key.Name}}</h2>
+		{{range $val}}
+			{{$pkg_html := pkgLink .Path | html}}
+			{{if eq "Packages" $key.Name}}
+				<a href="/{{$pkg_html}}">{{html .Path}}</a>
+			{{else}}
+				{{$doc_html := docLink .Path .Name| html}}
+				<a href="/{{$pkg_html}}">{{html .Package}}</a>.<a href="{{$doc_html}}">{{.Name}}</a>
+			{{end}}
+			{{if .Doc}}
+				<p>{{comment_html .Doc}}</p>
+			{{else}}
+				<p><em>No documentation available</em></p>
+			{{end}}
+		{{end}}
+	{{end}}
+{{end}}
+`,
+
+	"searchtxt.html": `<!--
+	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.
+-->
+{{$query_url := urlquery .Query}}
+{{with .Textual}}
+	{{if $.Complete}}
+		<h2 id="Textual">{{html $.Found}} textual occurrences</h2>
+	{{else}}
+		<h2 id="Textual">More than {{html $.Found}} textual occurrences</h2>
+		<p>
+		<span class="alert" style="font-size:120%">Not all files or lines containing "{{html $.Query}}" are shown.</span>
+		</p>
+	{{end}}
+	<p>
+	<table class="layout">
+	{{range .}}
+		{{$file := .Filename}}
+		<tr>
+		<td align="left" valign="top">
+		<a href="{{queryLink $file $query_url 0}}">{{$file}}</a>:
+		</td>
+		<td align="left" width="4"></td>
+		<th align="left" valign="top">{{len .Lines}}</th>
+		<td align="left" width="4"></td>
+		<td align="left">
+		{{range .Lines}}
+			<a href="{{queryLink $file $query_url .}}">{{html .}}</a>
+		{{end}}
+		{{if not $.Complete}}
+			...
+		{{end}}
+		</td>
+		</tr>
+	{{end}}
+	{{if not $.Complete}}
+		<tr><td align="left">...</td></tr>
+	{{end}}
+	</table>
+	</p>
+{{end}}
+`,
+
+	"style.css": `body {
+	margin: 0;
+	font-family: Helvetica, Arial, sans-serif;
+	font-size: 16px;
+}
+pre,
+code {
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+pre {
+	line-height: 18px;
+}
+pre .comment {
+	color: #006600;
+}
+pre .highlight,
+pre .highlight-comment,
+pre .selection-highlight,
+pre .selection-highlight-comment {
+	background: #FFFF00;
+}
+pre .selection,
+pre .selection-comment {
+	background: #FF9632;
+}
+pre .ln {
+	color: #999;
+}
+body {
+	color: #222;
+}
+a,
+.exampleHeading .text {
+	color: #375EAB;
+	text-decoration: none;
+}
+a:hover,
+.exampleHeading .text:hover {
+	text-decoration: underline;
+}
+p,
+pre,
+ul,
+ol {
+	margin: 20px;
+}
+pre {
+	background: #e9e9e9;
+	padding: 10px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+h1,
+h2,
+h3,
+h4,
+.rootHeading {
+	margin: 20px 0;
+	padding: 0;
+	color: #375EAB;
+	font-weight: bold;
+}
+h1 {
+	font-size: 24px;
+}
+h2 {
+	font-size: 20px;
+	background: #E0EBF5;
+	padding: 2px 5px;
+}
+h3 {
+	font-size: 20px;
+}
+h3,
+h4 {
+	margin: 20px 5px;
+}
+h4 {
+	font-size: 16px;
+}
+.rootHeading {
+	font-size: 20px;
+	margin: 0;
+}
+
+dl {
+	margin: 20px;
+}
+dd {
+	margin: 2px 20px;
+}
+dl,
+dd {
+	font-size: 14px;
+}
+div#nav table td {
+	vertical-align: top;
+}
+
+table.dir th {
+	text-align: left;
+}
+table.dir td {
+	word-wrap: break-word;
+	vertical-align: top;
+}
+div#page.wide table.dir td.name {
+	white-space: nowrap;
+}
+.alert {
+	color: #AA0000;
+}
+
+div#heading {
+	float: left;
+	margin: 0 0 10px 0;
+	padding: 21px 0;
+	font-size: 20px;
+	font-weight: normal;
+}
+div#heading a {
+	color: #222;
+	text-decoration: none;
+}
+
+div#topbar {
+	background: #E0EBF5;
+	height: 64px;
+	overflow: hidden;
+}
+
+body {
+	text-align: center;
+}
+div#page {
+	width: 100%;
+}
+div#page > .container,
+div#topbar > .container {
+	text-align: left;
+	margin-left: auto;
+	margin-right: auto;
+	padding: 0 20px;
+	width: 900px;
+}
+div#page.wide > .container,
+div#topbar.wide > .container {
+	width: auto;
+}
+div#plusone {
+	float: right;
+	clear: right;
+	margin-top: 5px;
+}
+
+div#footer {
+	text-align: center;
+	color: #666;
+	font-size: 14px;
+	margin: 40px 0;
+}
+
+div#menu > a,
+div#menu > input,
+div#learn .buttons a,
+div.play .buttons a,
+div#blog .read a {
+	padding: 10px;
+
+	text-decoration: none;
+	font-size: 16px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+div#playground .buttons a,
+div#menu > a,
+div#menu > input {
+	border: 1px solid #375EAB;
+}
+div#playground .buttons a,
+div#menu > a {
+	color: white;
+	background: #375EAB;
+}
+#playgroundButton.active {
+	background: white;
+	color: #375EAB;
+}
+a#start,
+div#learn .buttons a,
+div.play .buttons a,
+div#blog .read a {
+	color: #222;
+	border: 1px solid #375EAB;
+	background: #E0EBF5;
+}
+.download {
+	width: 150px;
+}
+
+div#menu {
+	float: right;
+	min-width: 590px;
+	padding: 10px 0;
+	text-align: right;
+}
+div#menu > a {
+	margin-right: 5px;
+	margin-bottom: 10px;
+
+	padding: 10px;
+}
+div#menu > input {
+	position: relative;
+	top: 1px;
+	width: 60px;
+	background: white;
+	color: #222;
+}
+div#menu > input.inactive {
+	color: #999;
+}
+
+div.left {
+	float: left;
+	clear: left;
+}
+div.right {
+	float: right;
+	clear: right;
+}
+div.left,
+div.right {
+	width: 415px;
+}
+
+div#learn,
+div#about {
+	padding-top: 20px;
+}
+div#learn h2,
+div#about {
+	margin: 0;
+}
+div#about {
+	font-size: 20px;
+}
+
+div#about {
+	height: 96px;
+}
+div#gopher {
+	background: url(/doc/gopher/frontpage.png) no-repeat;
+	background-position: center top;
+	height: 155px;
+}
+a#start {
+	display: block;
+	padding: 10px;
+
+	text-align: center;
+	text-decoration: none;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+a#start .big {
+	display: block;
+	font-weight: bold;
+	font-size: 20px;
+}
+a#start .desc {
+	display: block;
+	font-size: 14px;
+	font-weight: normal;
+	margin-top: 5px;
+}
+
+div#learn .popout {
+	float: right;
+	display: block;
+	cursor: pointer;
+	font-size: 12px;
+	background: url(/doc/share.png) no-repeat;
+	background-position: right top;
+	padding: 5px 27px;
+}
+div#learn pre,
+div#learn textarea {
+	padding: 0;
+	margin: 0;
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+div#learn .input {
+	padding: 10px;
+	margin-top: 10px;
+	height: 150px;
+
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-top-right-radius: 5px;
+	-moz-border-radius-topleft: 5px;
+	-moz-border-radius-topright: 5px;
+	border-top-left-radius: 5px;
+	border-top-right-radius: 5px;
+}
+div#learn .input textarea {
+	width: 100%;
+	height: 100%;
+	border: none;
+	outline: none;
+	resize: none;
+}
+div#learn .output {
+	border-top: none !important;
+
+	padding: 10px;
+	height: 59px;
+	overflow: auto;
+
+	-webkit-border-bottom-right-radius: 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-moz-border-radius-bottomright: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	border-bottom-right-radius: 5px;
+	border-bottom-left-radius: 5px;
+}
+div#learn .output pre {
+	padding: 0;
+
+	-webkit-border-radius: 0;
+	-moz-border-radius: 0;
+	border-radius: 0;
+}
+div#learn .input,
+div#learn .input textarea,
+div#learn .output,
+div#learn .output pre {
+	background: #FFFFD8;
+}
+div#learn .input,
+div#learn .output {
+	border: 1px solid #375EAB;
+}
+div#learn .buttons {
+	float: right;
+	padding: 20px 0 10px 0;
+	text-align: right;
+}
+div#learn .buttons a {
+	height: 16px;
+	margin-left: 5px;
+	padding: 10px;
+}
+div#learn .toys {
+	margin-top: 8px;
+}
+div#learn .toys select {
+	border: 1px solid #375EAB;
+	margin: 0;
+}
+div#learn .output .exit {
+	display: none;
+}
+
+div#blog,
+div#video {
+	margin-top: 40px;
+}
+div#blog > a,
+div#blog > div,
+div#blog > h2,
+div#video > a,
+div#video > div,
+div#video > h2 {
+	margin-bottom: 10px;
+}
+div#blog .title,
+div#video .title {
+	display: block;
+	font-size: 20px;
+}
+div#blog .when {
+	color: #666;
+	font-size: 14px;
+}
+div#blog .read {
+	text-align: right;
+}
+
+.toggleButton { cursor: pointer; }
+.toggle .collapsed { display: block; }
+.toggle .expanded { display: none; }
+.toggleVisible .collapsed { display: none; }
+.toggleVisible .expanded { display: block; }
+
+table.codetable { margin-left: auto; margin-right: auto; border-style: none; }
+table.codetable td { padding-right: 10px; }
+hr { border-style: none; border-top: 1px solid black; }
+
+img.gopher {
+	float: right;
+	margin-left: 10px;
+	margin-bottom: 10px;
+	z-index: -1;
+}
+h2 { clear: right; }
+
+/* example and drop-down playground */
+div.play {
+	padding: 0 20px 40px 20px;
+}
+div.play pre,
+div.play textarea,
+div.play .lines {
+	padding: 0;
+	margin: 0;
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+div.play .input {
+	padding: 10px;
+	margin-top: 10px;
+
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-top-right-radius: 5px;
+	-moz-border-radius-topleft: 5px;
+	-moz-border-radius-topright: 5px;
+	border-top-left-radius: 5px;
+	border-top-right-radius: 5px;
+
+	overflow: hidden;
+}
+div.play .input textarea {
+	width: 100%;
+	height: 100%;
+	border: none;
+	outline: none;
+	resize: none;
+
+	overflow: hidden;
+}
+div#playground .input textarea {
+	overflow: auto;
+	resize: auto;
+}
+div.play .output {
+	border-top: none !important;
+
+	padding: 10px;
+	max-height: 200px;
+	overflow: auto;
+
+	-webkit-border-bottom-right-radius: 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-moz-border-radius-bottomright: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	border-bottom-right-radius: 5px;
+	border-bottom-left-radius: 5px;
+}
+div.play .output pre {
+	padding: 0;
+
+	-webkit-border-radius: 0;
+	-moz-border-radius: 0;
+	border-radius: 0;
+}
+div.play .input,
+div.play .input textarea,
+div.play .output,
+div.play .output pre {
+	background: #FFFFD8;
+}
+div.play .input,
+div.play .output {
+	border: 1px solid #375EAB;
+}
+div.play .buttons {
+	float: right;
+	padding: 20px 0 10px 0;
+	text-align: right;
+}
+div.play .buttons a {
+	height: 16px;
+	margin-left: 5px;
+	padding: 10px;
+	cursor: pointer;
+}
+.output .stderr {
+	color: #933;
+}
+.output .system {
+	color: #999;
+}
+
+/* drop-down playground */
+#playgroundButton,
+div#playground {
+	/* start hidden; revealed by javascript */
+	display: none;
+}
+div#playground {
+	position: absolute;
+	top: 63px;
+	right: 20px;
+	padding: 0 10px 10px 10px;
+	z-index: 1;
+	text-align: left;
+	background: #E0EBF5;
+
+	border: 1px solid #B0BBC5;
+	border-top: none;
+
+	-webkit-border-bottom-left-radius: 5px;
+	-webkit-border-bottom-right-radius: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	-moz-border-radius-bottomright: 5px;
+	border-bottom-left-radius: 5px;
+	border-bottom-right-radius: 5px;
+}
+div#playground .code {
+	width: 520px;
+	height: 200px;
+}
+div#playground .output {
+	height: 100px;
+}
+
+/* Inline runnable snippets (play.js/initPlayground) */
+#content .code pre, #content .playground pre, #content .output pre {
+        margin: 0;
+        padding: 0;
+        background: none;
+        border: none;
+	outline: 0px solid transparent;
+        overflow: auto;
+}
+#content .playground .number, #content .code .number {
+        color: #999;
+}
+#content .code, #content .playground, #content .output {
+	width: auto;
+        margin: 20px;
+        padding: 10px;
+        -webkit-border-radius: 5px;
+        -moz-border-radius: 5px;
+        border-radius: 5px;
+}
+#content .code, #content .playground {
+        background: #e9e9e9;
+}
+#content .output {
+        background: #202020;
+}
+#content .output .stdout, #content .output pre {
+        color: #e6e6e6;
+}
+#content .output .stderr, #content .output .error {
+        color: rgb(244, 74, 63);
+}
+#content .output .system, #content .output .exit {
+        color: rgb(255, 209, 77)
+}
+#content .buttons {
+        position: relative;
+        float: right;
+        top: -50px;
+        right: 30px;
+}
+#content .output .buttons {
+        top: -60px;
+        right: 0;
+        height: 0;
+}
+#content .buttons .kill {
+        display: none;
+        visibility: hidden;
+}
+a.error {
+	font-weight: bold;
+        color: white;
+	background-color: darkred;
+        border-bottom-left-radius: 4px;
+        border-bottom-right-radius: 4px;
+        border-top-left-radius: 4px;
+        border-top-right-radius: 4px;
+        padding: 2px 4px 2px 4px; /* TRBL */
+}
+`,
+}
diff --git a/third_party/go.tools/godoc/static/style.css b/third_party/go.tools/godoc/static/style.css
new file mode 100644
index 0000000..dd417a2
--- /dev/null
+++ b/third_party/go.tools/godoc/static/style.css
@@ -0,0 +1,595 @@
+body {
+	margin: 0;
+	font-family: Helvetica, Arial, sans-serif;
+	font-size: 16px;
+}
+pre,
+code {
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+pre {
+	line-height: 18px;
+}
+pre .comment {
+	color: #006600;
+}
+pre .highlight,
+pre .highlight-comment,
+pre .selection-highlight,
+pre .selection-highlight-comment {
+	background: #FFFF00;
+}
+pre .selection,
+pre .selection-comment {
+	background: #FF9632;
+}
+pre .ln {
+	color: #999;
+}
+body {
+	color: #222;
+}
+a,
+.exampleHeading .text {
+	color: #375EAB;
+	text-decoration: none;
+}
+a:hover,
+.exampleHeading .text:hover {
+	text-decoration: underline;
+}
+p,
+pre,
+ul,
+ol {
+	margin: 20px;
+}
+pre {
+	background: #e9e9e9;
+	padding: 10px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+h1,
+h2,
+h3,
+h4,
+.rootHeading {
+	margin: 20px 0;
+	padding: 0;
+	color: #375EAB;
+	font-weight: bold;
+}
+h1 {
+	font-size: 24px;
+}
+h2 {
+	font-size: 20px;
+	background: #E0EBF5;
+	padding: 2px 5px;
+}
+h3 {
+	font-size: 20px;
+}
+h3,
+h4 {
+	margin: 20px 5px;
+}
+h4 {
+	font-size: 16px;
+}
+.rootHeading {
+	font-size: 20px;
+	margin: 0;
+}
+
+dl {
+	margin: 20px;
+}
+dd {
+	margin: 2px 20px;
+}
+dl,
+dd {
+	font-size: 14px;
+}
+div#nav table td {
+	vertical-align: top;
+}
+
+table.dir th {
+	text-align: left;
+}
+table.dir td {
+	word-wrap: break-word;
+	vertical-align: top;
+}
+div#page.wide table.dir td.name {
+	white-space: nowrap;
+}
+.alert {
+	color: #AA0000;
+}
+
+div#heading {
+	float: left;
+	margin: 0 0 10px 0;
+	padding: 21px 0;
+	font-size: 20px;
+	font-weight: normal;
+}
+div#heading a {
+	color: #222;
+	text-decoration: none;
+}
+
+div#topbar {
+	background: #E0EBF5;
+	height: 64px;
+	overflow: hidden;
+}
+
+body {
+	text-align: center;
+}
+div#page {
+	width: 100%;
+}
+div#page > .container,
+div#topbar > .container {
+	text-align: left;
+	margin-left: auto;
+	margin-right: auto;
+	padding: 0 20px;
+	width: 900px;
+}
+div#page.wide > .container,
+div#topbar.wide > .container {
+	width: auto;
+}
+div#plusone {
+	float: right;
+	clear: right;
+	margin-top: 5px;
+}
+
+div#footer {
+	text-align: center;
+	color: #666;
+	font-size: 14px;
+	margin: 40px 0;
+}
+
+div#menu > a,
+div#menu > input,
+div#learn .buttons a,
+div.play .buttons a,
+div#blog .read a {
+	padding: 10px;
+
+	text-decoration: none;
+	font-size: 16px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+div#playground .buttons a,
+div#menu > a,
+div#menu > input {
+	border: 1px solid #375EAB;
+}
+div#playground .buttons a,
+div#menu > a {
+	color: white;
+	background: #375EAB;
+}
+#playgroundButton.active {
+	background: white;
+	color: #375EAB;
+}
+a#start,
+div#learn .buttons a,
+div.play .buttons a,
+div#blog .read a {
+	color: #222;
+	border: 1px solid #375EAB;
+	background: #E0EBF5;
+}
+.download {
+	width: 150px;
+}
+
+div#menu {
+	float: right;
+	min-width: 590px;
+	padding: 10px 0;
+	text-align: right;
+}
+div#menu > a {
+	margin-right: 5px;
+	margin-bottom: 10px;
+
+	padding: 10px;
+}
+div#menu > input {
+	position: relative;
+	top: 1px;
+	width: 60px;
+	background: white;
+	color: #222;
+}
+div#menu > input.inactive {
+	color: #999;
+}
+
+div.left {
+	float: left;
+	clear: left;
+}
+div.right {
+	float: right;
+	clear: right;
+}
+div.left,
+div.right {
+	width: 415px;
+}
+
+div#learn,
+div#about {
+	padding-top: 20px;
+}
+div#learn h2,
+div#about {
+	margin: 0;
+}
+div#about {
+	font-size: 20px;
+}
+
+div#about {
+	height: 96px;
+}
+div#gopher {
+	background: url(/doc/gopher/frontpage.png) no-repeat;
+	background-position: center top;
+	height: 155px;
+}
+a#start {
+	display: block;
+	padding: 10px;
+
+	text-align: center;
+	text-decoration: none;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+a#start .big {
+	display: block;
+	font-weight: bold;
+	font-size: 20px;
+}
+a#start .desc {
+	display: block;
+	font-size: 14px;
+	font-weight: normal;
+	margin-top: 5px;
+}
+
+div#learn .popout {
+	float: right;
+	display: block;
+	cursor: pointer;
+	font-size: 12px;
+	background: url(/doc/share.png) no-repeat;
+	background-position: right top;
+	padding: 5px 27px;
+}
+div#learn pre,
+div#learn textarea {
+	padding: 0;
+	margin: 0;
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+div#learn .input {
+	padding: 10px;
+	margin-top: 10px;
+	height: 150px;
+
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-top-right-radius: 5px;
+	-moz-border-radius-topleft: 5px;
+	-moz-border-radius-topright: 5px;
+	border-top-left-radius: 5px;
+	border-top-right-radius: 5px;
+}
+div#learn .input textarea {
+	width: 100%;
+	height: 100%;
+	border: none;
+	outline: none;
+	resize: none;
+}
+div#learn .output {
+	border-top: none !important;
+
+	padding: 10px;
+	height: 59px;
+	overflow: auto;
+
+	-webkit-border-bottom-right-radius: 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-moz-border-radius-bottomright: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	border-bottom-right-radius: 5px;
+	border-bottom-left-radius: 5px;
+}
+div#learn .output pre {
+	padding: 0;
+
+	-webkit-border-radius: 0;
+	-moz-border-radius: 0;
+	border-radius: 0;
+}
+div#learn .input,
+div#learn .input textarea,
+div#learn .output,
+div#learn .output pre {
+	background: #FFFFD8;
+}
+div#learn .input,
+div#learn .output {
+	border: 1px solid #375EAB;
+}
+div#learn .buttons {
+	float: right;
+	padding: 20px 0 10px 0;
+	text-align: right;
+}
+div#learn .buttons a {
+	height: 16px;
+	margin-left: 5px;
+	padding: 10px;
+}
+div#learn .toys {
+	margin-top: 8px;
+}
+div#learn .toys select {
+	border: 1px solid #375EAB;
+	margin: 0;
+}
+div#learn .output .exit {
+	display: none;
+}
+
+div#blog,
+div#video {
+	margin-top: 40px;
+}
+div#blog > a,
+div#blog > div,
+div#blog > h2,
+div#video > a,
+div#video > div,
+div#video > h2 {
+	margin-bottom: 10px;
+}
+div#blog .title,
+div#video .title {
+	display: block;
+	font-size: 20px;
+}
+div#blog .when {
+	color: #666;
+	font-size: 14px;
+}
+div#blog .read {
+	text-align: right;
+}
+
+.toggleButton { cursor: pointer; }
+.toggle .collapsed { display: block; }
+.toggle .expanded { display: none; }
+.toggleVisible .collapsed { display: none; }
+.toggleVisible .expanded { display: block; }
+
+table.codetable { margin-left: auto; margin-right: auto; border-style: none; }
+table.codetable td { padding-right: 10px; }
+hr { border-style: none; border-top: 1px solid black; }
+
+img.gopher {
+	float: right;
+	margin-left: 10px;
+	margin-bottom: 10px;
+	z-index: -1;
+}
+h2 { clear: right; }
+
+/* example and drop-down playground */
+div.play {
+	padding: 0 20px 40px 20px;
+}
+div.play pre,
+div.play textarea,
+div.play .lines {
+	padding: 0;
+	margin: 0;
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+div.play .input {
+	padding: 10px;
+	margin-top: 10px;
+
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-top-right-radius: 5px;
+	-moz-border-radius-topleft: 5px;
+	-moz-border-radius-topright: 5px;
+	border-top-left-radius: 5px;
+	border-top-right-radius: 5px;
+
+	overflow: hidden;
+}
+div.play .input textarea {
+	width: 100%;
+	height: 100%;
+	border: none;
+	outline: none;
+	resize: none;
+
+	overflow: hidden;
+}
+div#playground .input textarea {
+	overflow: auto;
+	resize: auto;
+}
+div.play .output {
+	border-top: none !important;
+
+	padding: 10px;
+	max-height: 200px;
+	overflow: auto;
+
+	-webkit-border-bottom-right-radius: 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-moz-border-radius-bottomright: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	border-bottom-right-radius: 5px;
+	border-bottom-left-radius: 5px;
+}
+div.play .output pre {
+	padding: 0;
+
+	-webkit-border-radius: 0;
+	-moz-border-radius: 0;
+	border-radius: 0;
+}
+div.play .input,
+div.play .input textarea,
+div.play .output,
+div.play .output pre {
+	background: #FFFFD8;
+}
+div.play .input,
+div.play .output {
+	border: 1px solid #375EAB;
+}
+div.play .buttons {
+	float: right;
+	padding: 20px 0 10px 0;
+	text-align: right;
+}
+div.play .buttons a {
+	height: 16px;
+	margin-left: 5px;
+	padding: 10px;
+	cursor: pointer;
+}
+.output .stderr {
+	color: #933;
+}
+.output .system {
+	color: #999;
+}
+
+/* drop-down playground */
+#playgroundButton,
+div#playground {
+	/* start hidden; revealed by javascript */
+	display: none;
+}
+div#playground {
+	position: absolute;
+	top: 63px;
+	right: 20px;
+	padding: 0 10px 10px 10px;
+	z-index: 1;
+	text-align: left;
+	background: #E0EBF5;
+
+	border: 1px solid #B0BBC5;
+	border-top: none;
+
+	-webkit-border-bottom-left-radius: 5px;
+	-webkit-border-bottom-right-radius: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	-moz-border-radius-bottomright: 5px;
+	border-bottom-left-radius: 5px;
+	border-bottom-right-radius: 5px;
+}
+div#playground .code {
+	width: 520px;
+	height: 200px;
+}
+div#playground .output {
+	height: 100px;
+}
+
+/* Inline runnable snippets (play.js/initPlayground) */
+#content .code pre, #content .playground pre, #content .output pre {
+        margin: 0;
+        padding: 0;
+        background: none;
+        border: none;
+	outline: 0px solid transparent;
+        overflow: auto;
+}
+#content .playground .number, #content .code .number {
+        color: #999;
+}
+#content .code, #content .playground, #content .output {
+	width: auto;
+        margin: 20px;
+        padding: 10px;
+        -webkit-border-radius: 5px;
+        -moz-border-radius: 5px;
+        border-radius: 5px;
+}
+#content .code, #content .playground {
+        background: #e9e9e9;
+}
+#content .output {
+        background: #202020;
+}
+#content .output .stdout, #content .output pre {
+        color: #e6e6e6;
+}
+#content .output .stderr, #content .output .error {
+        color: rgb(244, 74, 63);
+}
+#content .output .system, #content .output .exit {
+        color: rgb(255, 209, 77)
+}
+#content .buttons {
+        position: relative;
+        float: right;
+        top: -50px;
+        right: 30px;
+}
+#content .output .buttons {
+        top: -60px;
+        right: 0;
+        height: 0;
+}
+#content .buttons .kill {
+        display: none;
+        visibility: hidden;
+}
+a.error {
+	font-weight: bold;
+        color: white;
+	background-color: darkred;
+        border-bottom-left-radius: 4px;
+        border-bottom-right-radius: 4px;
+        border-top-left-radius: 4px;
+        border-top-right-radius: 4px;
+        padding: 2px 4px 2px 4px; /* TRBL */
+}
diff --git a/third_party/go.tools/godoc/tab.go b/third_party/go.tools/godoc/tab.go
new file mode 100644
index 0000000..7973b74
--- /dev/null
+++ b/third_party/go.tools/godoc/tab.go
@@ -0,0 +1,78 @@
+// TODO(bradfitz,adg): move to util
+
+package godoc
+
+import "io"
+
+var spaces = []byte("                                ") // 32 spaces seems like a good number
+
+const (
+	indenting = iota
+	collecting
+)
+
+// A tconv is an io.Writer filter for converting leading tabs into spaces.
+type tconv struct {
+	output io.Writer
+	state  int // indenting or collecting
+	indent int // valid if state == indenting
+	p      *Presentation
+}
+
+func (p *tconv) writeIndent() (err error) {
+	i := p.indent
+	for i >= len(spaces) {
+		i -= len(spaces)
+		if _, err = p.output.Write(spaces); err != nil {
+			return
+		}
+	}
+	// i < len(spaces)
+	if i > 0 {
+		_, err = p.output.Write(spaces[0:i])
+	}
+	return
+}
+
+func (p *tconv) Write(data []byte) (n int, err error) {
+	if len(data) == 0 {
+		return
+	}
+	pos := 0 // valid if p.state == collecting
+	var b byte
+	for n, b = range data {
+		switch p.state {
+		case indenting:
+			switch b {
+			case '\t':
+				p.indent += p.p.TabWidth
+			case '\n':
+				p.indent = 0
+				if _, err = p.output.Write(data[n : n+1]); err != nil {
+					return
+				}
+			case ' ':
+				p.indent++
+			default:
+				p.state = collecting
+				pos = n
+				if err = p.writeIndent(); err != nil {
+					return
+				}
+			}
+		case collecting:
+			if b == '\n' {
+				p.state = indenting
+				p.indent = 0
+				if _, err = p.output.Write(data[pos : n+1]); err != nil {
+					return
+				}
+			}
+		}
+	}
+	n = len(data)
+	if pos < n && p.state == collecting {
+		_, err = p.output.Write(data[pos:])
+	}
+	return
+}
diff --git a/third_party/go.tools/godoc/template.go b/third_party/go.tools/godoc/template.go
new file mode 100644
index 0000000..78550de
--- /dev/null
+++ b/third_party/go.tools/godoc/template.go
@@ -0,0 +1,179 @@
+// 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.
+
+// Template support for writing HTML documents.
+// Documents that include Template: true in their
+// metadata are executed as input to text/template.
+//
+// This file defines functions for those templates to invoke.
+
+// The template uses the function "code" to inject program
+// source into the output by extracting code from files and
+// injecting them as HTML-escaped <pre> blocks.
+//
+// The syntax is simple: 1, 2, or 3 space-separated arguments:
+//
+// Whole file:
+//	{{code "foo.go"}}
+// One line (here the signature of main):
+//	{{code "foo.go" `/^func.main/`}}
+// Block of text, determined by start and end (here the body of main):
+//	{{code "foo.go" `/^func.main/` `/^}/`
+//
+// Patterns can be `/regular expression/`, a decimal number, or "$"
+// to signify the end of the file. In multi-line matches,
+// lines that end with the four characters
+//	OMIT
+// are omitted from the output, making it easy to provide marker
+// lines in the input that will not appear in the output but are easy
+// to identify by pattern.
+
+package godoc
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"regexp"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+// Functions in this file panic on error, but the panic is recovered
+// to an error by 'code'.
+
+// contents reads and returns the content of the named file
+// (from the virtual file system, so for example /doc refers to $GOROOT/doc).
+func (c *Corpus) contents(name string) string {
+	file, err := vfs.ReadFile(c.fs, name)
+	if err != nil {
+		log.Panic(err)
+	}
+	return string(file)
+}
+
+// stringFor returns a textual representation of the arg, formatted according to its nature.
+func stringFor(arg interface{}) string {
+	switch arg := arg.(type) {
+	case int:
+		return fmt.Sprintf("%d", arg)
+	case string:
+		if len(arg) > 2 && arg[0] == '/' && arg[len(arg)-1] == '/' {
+			return fmt.Sprintf("%#q", arg)
+		}
+		return fmt.Sprintf("%q", arg)
+	default:
+		log.Panicf("unrecognized argument: %v type %T", arg, arg)
+	}
+	return ""
+}
+
+func (p *Presentation) code(file string, arg ...interface{}) (s string, err error) {
+	defer func() {
+		if r := recover(); r != nil {
+			err = fmt.Errorf("%v", r)
+		}
+	}()
+
+	text := p.Corpus.contents(file)
+	var command string
+	switch len(arg) {
+	case 0:
+		// text is already whole file.
+		command = fmt.Sprintf("code %q", file)
+	case 1:
+		command = fmt.Sprintf("code %q %s", file, stringFor(arg[0]))
+		text = p.Corpus.oneLine(file, text, arg[0])
+	case 2:
+		command = fmt.Sprintf("code %q %s %s", file, stringFor(arg[0]), stringFor(arg[1]))
+		text = p.Corpus.multipleLines(file, text, arg[0], arg[1])
+	default:
+		return "", fmt.Errorf("incorrect code invocation: code %q %q", file, arg)
+	}
+	// Trim spaces from output.
+	text = strings.Trim(text, "\n")
+	// Replace tabs by spaces, which work better in HTML.
+	text = strings.Replace(text, "\t", "    ", -1)
+	var buf bytes.Buffer
+	// HTML-escape text and syntax-color comments like elsewhere.
+	FormatText(&buf, []byte(text), -1, true, "", nil)
+	// Include the command as a comment.
+	text = fmt.Sprintf("<pre><!--{{%s}}\n-->%s</pre>", command, buf.Bytes())
+	return text, nil
+}
+
+// parseArg returns the integer or string value of the argument and tells which it is.
+func parseArg(arg interface{}, file string, max int) (ival int, sval string, isInt bool) {
+	switch n := arg.(type) {
+	case int:
+		if n <= 0 || n > max {
+			log.Panicf("%q:%d is out of range", file, n)
+		}
+		return n, "", true
+	case string:
+		return 0, n, false
+	}
+	log.Panicf("unrecognized argument %v type %T", arg, arg)
+	return
+}
+
+// oneLine returns the single line generated by a two-argument code invocation.
+func (c *Corpus) oneLine(file, text string, arg interface{}) string {
+	lines := strings.SplitAfter(c.contents(file), "\n")
+	line, pattern, isInt := parseArg(arg, file, len(lines))
+	if isInt {
+		return lines[line-1]
+	}
+	return lines[match(file, 0, lines, pattern)-1]
+}
+
+// multipleLines returns the text generated by a three-argument code invocation.
+func (c *Corpus) multipleLines(file, text string, arg1, arg2 interface{}) string {
+	lines := strings.SplitAfter(c.contents(file), "\n")
+	line1, pattern1, isInt1 := parseArg(arg1, file, len(lines))
+	line2, pattern2, isInt2 := parseArg(arg2, file, len(lines))
+	if !isInt1 {
+		line1 = match(file, 0, lines, pattern1)
+	}
+	if !isInt2 {
+		line2 = match(file, line1, lines, pattern2)
+	} else if line2 < line1 {
+		log.Panicf("lines out of order for %q: %d %d", text, line1, line2)
+	}
+	for k := line1 - 1; k < line2; k++ {
+		if strings.HasSuffix(lines[k], "OMIT\n") {
+			lines[k] = ""
+		}
+	}
+	return strings.Join(lines[line1-1:line2], "")
+}
+
+// match identifies the input line that matches the pattern in a code invocation.
+// If start>0, match lines starting there rather than at the beginning.
+// The return value is 1-indexed.
+func match(file string, start int, lines []string, pattern string) int {
+	// $ matches the end of the file.
+	if pattern == "$" {
+		if len(lines) == 0 {
+			log.Panicf("%q: empty file", file)
+		}
+		return len(lines)
+	}
+	// /regexp/ matches the line that matches the regexp.
+	if len(pattern) > 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' {
+		re, err := regexp.Compile(pattern[1 : len(pattern)-1])
+		if err != nil {
+			log.Panic(err)
+		}
+		for i := start; i < len(lines); i++ {
+			if re.MatchString(lines[i]) {
+				return i + 1
+			}
+		}
+		log.Panicf("%s: no match for %#q", file, pattern)
+	}
+	log.Panicf("unrecognized pattern: %q", pattern)
+	return 0
+}
diff --git a/third_party/go.tools/godoc/util/throttle.go b/third_party/go.tools/godoc/util/throttle.go
new file mode 100644
index 0000000..53d9ba6
--- /dev/null
+++ b/third_party/go.tools/godoc/util/throttle.go
@@ -0,0 +1,88 @@
+// 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.
+
+package util
+
+import "time"
+
+// A Throttle permits throttling of a goroutine by
+// calling the Throttle method repeatedly.
+//
+type Throttle struct {
+	f  float64       // f = (1-r)/r for 0 < r < 1
+	dt time.Duration // minimum run time slice; >= 0
+	tr time.Duration // accumulated time running
+	ts time.Duration // accumulated time stopped
+	tt time.Time     // earliest throttle time (= time Throttle returned + tm)
+}
+
+// NewThrottle creates a new Throttle with a throttle value r and
+// a minimum allocated run time slice of dt:
+//
+//	r == 0: "empty" throttle; the goroutine is always sleeping
+//	r == 1: full throttle; the goroutine is never sleeping
+//
+// A value of r == 0.6 throttles a goroutine such that it runs
+// approx. 60% of the time, and sleeps approx. 40% of the time.
+// Values of r < 0 or r > 1 are clamped down to values between 0 and 1.
+// Values of dt < 0 are set to 0.
+//
+func NewThrottle(r float64, dt time.Duration) *Throttle {
+	var f float64
+	switch {
+	case r <= 0:
+		f = -1 // indicates always sleep
+	case r >= 1:
+		f = 0 // assume r == 1 (never sleep)
+	default:
+		// 0 < r < 1
+		f = (1 - r) / r
+	}
+	if dt < 0 {
+		dt = 0
+	}
+	return &Throttle{f: f, dt: dt, tt: time.Now().Add(dt)}
+}
+
+// Throttle calls time.Sleep such that over time the ratio tr/ts between
+// accumulated run (tr) and sleep times (ts) approximates the value 1/(1-r)
+// where r is the throttle value. Throttle returns immediately (w/o sleeping)
+// if less than tm ns have passed since the last call to Throttle.
+//
+func (p *Throttle) Throttle() {
+	if p.f < 0 {
+		select {} // always sleep
+	}
+
+	t0 := time.Now()
+	if t0.Before(p.tt) {
+		return // keep running (minimum time slice not exhausted yet)
+	}
+
+	// accumulate running time
+	p.tr += t0.Sub(p.tt) + p.dt
+
+	// compute sleep time
+	// Over time we want:
+	//
+	//	tr/ts = r/(1-r)
+	//
+	// Thus:
+	//
+	//	ts = tr*f with f = (1-r)/r
+	//
+	// After some incremental run time δr added to the total run time
+	// tr, the incremental sleep-time δs to get to the same ratio again
+	// after waking up from time.Sleep is:
+	if δs := time.Duration(float64(p.tr)*p.f) - p.ts; δs > 0 {
+		time.Sleep(δs)
+	}
+
+	// accumulate (actual) sleep time
+	t1 := time.Now()
+	p.ts += t1.Sub(t0)
+
+	// set earliest next throttle time
+	p.tt = t1.Add(p.dt)
+}
diff --git a/third_party/go.tools/godoc/util/util.go b/third_party/go.tools/godoc/util/util.go
new file mode 100644
index 0000000..9562671
--- /dev/null
+++ b/third_party/go.tools/godoc/util/util.go
@@ -0,0 +1,89 @@
+// Copyright 2013 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 util contains utility types and functions for godoc.
+package util
+
+import (
+	pathpkg "path"
+	"sync"
+	"time"
+	"unicode/utf8"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+// An RWValue wraps a value and permits mutually exclusive
+// access to it and records the time the value was last set.
+type RWValue struct {
+	mutex     sync.RWMutex
+	value     interface{}
+	timestamp time.Time // time of last set()
+}
+
+func (v *RWValue) Set(value interface{}) {
+	v.mutex.Lock()
+	v.value = value
+	v.timestamp = time.Now()
+	v.mutex.Unlock()
+}
+
+func (v *RWValue) Get() (interface{}, time.Time) {
+	v.mutex.RLock()
+	defer v.mutex.RUnlock()
+	return v.value, v.timestamp
+}
+
+// IsText reports whether a significant prefix of s looks like correct UTF-8;
+// that is, if it is likely that s is human-readable text.
+func IsText(s []byte) bool {
+	const max = 1024 // at least utf8.UTFMax
+	if len(s) > max {
+		s = s[0:max]
+	}
+	for i, c := range string(s) {
+		if i+utf8.UTFMax > len(s) {
+			// last char may be incomplete - ignore
+			break
+		}
+		if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' && c != '\f' {
+			// decoding error or control character - not a text file
+			return false
+		}
+	}
+	return true
+}
+
+// textExt[x] is true if the extension x indicates a text file, and false otherwise.
+var textExt = map[string]bool{
+	".css": false, // must be served raw
+	".js":  false, // must be served raw
+}
+
+// IsTextFile reports whether the file has a known extension indicating
+// a text file, or if a significant chunk of the specified file looks like
+// correct UTF-8; that is, if it is likely that the file contains human-
+// readable text.
+func IsTextFile(fs vfs.Opener, filename string) bool {
+	// if the extension is known, use it for decision making
+	if isText, found := textExt[pathpkg.Ext(filename)]; found {
+		return isText
+	}
+
+	// the extension is not known; read an initial chunk
+	// of the file and check if it looks like text
+	f, err := fs.Open(filename)
+	if err != nil {
+		return false
+	}
+	defer f.Close()
+
+	var buf [1024]byte
+	n, err := f.Read(buf[0:])
+	if err != nil {
+		return false
+	}
+
+	return IsText(buf[0:n])
+}
diff --git a/third_party/go.tools/godoc/vfs/gatefs/gatefs.go b/third_party/go.tools/godoc/vfs/gatefs/gatefs.go
new file mode 100644
index 0000000..7d3dad3
--- /dev/null
+++ b/third_party/go.tools/godoc/vfs/gatefs/gatefs.go
@@ -0,0 +1,89 @@
+// Copyright 2013 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 gatefs provides an implementation of the FileSystem
+// interface that wraps another FileSystem and limits its concurrency.
+package gatefs
+
+import (
+	"fmt"
+	"os"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+// New returns a new FileSystem that delegates to fs.
+// If gateCh is non-nil and buffered, it's used as a gate
+// to limit concurrency on calls to fs.
+func New(fs vfs.FileSystem, gateCh chan bool) vfs.FileSystem {
+	if cap(gateCh) == 0 {
+		return fs
+	}
+	return gatefs{fs, gate(gateCh)}
+}
+
+type gate chan bool
+
+func (g gate) enter() { g <- true }
+func (g gate) leave() { <-g }
+
+type gatefs struct {
+	fs vfs.FileSystem
+	gate
+}
+
+func (fs gatefs) String() string {
+	return fmt.Sprintf("gated(%s, %d)", fs.fs.String(), cap(fs.gate))
+}
+
+func (fs gatefs) Open(p string) (vfs.ReadSeekCloser, error) {
+	fs.enter()
+	defer fs.leave()
+	rsc, err := fs.fs.Open(p)
+	if err != nil {
+		return nil, err
+	}
+	return gatef{rsc, fs.gate}, nil
+}
+
+func (fs gatefs) Lstat(p string) (os.FileInfo, error) {
+	fs.enter()
+	defer fs.leave()
+	return fs.fs.Lstat(p)
+}
+
+func (fs gatefs) Stat(p string) (os.FileInfo, error) {
+	fs.enter()
+	defer fs.leave()
+	return fs.fs.Stat(p)
+}
+
+func (fs gatefs) ReadDir(p string) ([]os.FileInfo, error) {
+	fs.enter()
+	defer fs.leave()
+	return fs.fs.ReadDir(p)
+}
+
+type gatef struct {
+	rsc vfs.ReadSeekCloser
+	gate
+}
+
+func (f gatef) Read(p []byte) (n int, err error) {
+	f.enter()
+	defer f.leave()
+	return f.rsc.Read(p)
+}
+
+func (f gatef) Seek(offset int64, whence int) (ret int64, err error) {
+	f.enter()
+	defer f.leave()
+	return f.rsc.Seek(offset, whence)
+}
+
+func (f gatef) Close() error {
+	f.enter()
+	defer f.leave()
+	return f.rsc.Close()
+}
diff --git a/third_party/go.tools/godoc/vfs/httpfs/httpfs.go b/third_party/go.tools/godoc/vfs/httpfs/httpfs.go
new file mode 100644
index 0000000..5e79b43
--- /dev/null
+++ b/third_party/go.tools/godoc/vfs/httpfs/httpfs.go
@@ -0,0 +1,94 @@
+// Copyright 2013 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 httpfs implements http.FileSystem using a godoc vfs.FileSystem.
+package httpfs
+
+import (
+	"fmt"
+	"io"
+	"net/http"
+	"os"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+func New(fs vfs.FileSystem) http.FileSystem {
+	return &httpFS{fs}
+}
+
+type httpFS struct {
+	fs vfs.FileSystem
+}
+
+func (h *httpFS) Open(name string) (http.File, error) {
+	fi, err := h.fs.Stat(name)
+	if err != nil {
+		return nil, err
+	}
+	if fi.IsDir() {
+		return &httpDir{h.fs, name, nil}, nil
+	}
+	f, err := h.fs.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	return &httpFile{h.fs, f, name}, nil
+}
+
+// httpDir implements http.File for a directory in a FileSystem.
+type httpDir struct {
+	fs      vfs.FileSystem
+	name    string
+	pending []os.FileInfo
+}
+
+func (h *httpDir) Close() error               { return nil }
+func (h *httpDir) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) }
+func (h *httpDir) Read([]byte) (int, error) {
+	return 0, fmt.Errorf("cannot Read from directory %s", h.name)
+}
+
+func (h *httpDir) Seek(offset int64, whence int) (int64, error) {
+	if offset == 0 && whence == 0 {
+		h.pending = nil
+		return 0, nil
+	}
+	return 0, fmt.Errorf("unsupported Seek in directory %s", h.name)
+}
+
+func (h *httpDir) Readdir(count int) ([]os.FileInfo, error) {
+	if h.pending == nil {
+		d, err := h.fs.ReadDir(h.name)
+		if err != nil {
+			return nil, err
+		}
+		if d == nil {
+			d = []os.FileInfo{} // not nil
+		}
+		h.pending = d
+	}
+
+	if len(h.pending) == 0 && count > 0 {
+		return nil, io.EOF
+	}
+	if count <= 0 || count > len(h.pending) {
+		count = len(h.pending)
+	}
+	d := h.pending[:count]
+	h.pending = h.pending[count:]
+	return d, nil
+}
+
+// httpFile implements http.File for a file (not directory) in a FileSystem.
+type httpFile struct {
+	fs vfs.FileSystem
+	vfs.ReadSeekCloser
+	name string
+}
+
+func (h *httpFile) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) }
+func (h *httpFile) Readdir(int) ([]os.FileInfo, error) {
+	return nil, fmt.Errorf("cannot Readdir from file %s", h.name)
+}
diff --git a/third_party/go.tools/godoc/vfs/mapfs/mapfs.go b/third_party/go.tools/godoc/vfs/mapfs/mapfs.go
new file mode 100644
index 0000000..fe11ea2
--- /dev/null
+++ b/third_party/go.tools/godoc/vfs/mapfs/mapfs.go
@@ -0,0 +1,152 @@
+// Copyright 2013 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 mapfs file provides an implementation of the FileSystem
+// interface based on the contents of a map[string]string.
+package mapfs
+
+import (
+	"io"
+	"os"
+	pathpkg "path"
+	"sort"
+	"strings"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+// New returns a new FileSystem from the provided map.
+// Map keys should be forward slash-separated pathnames
+// and not contain a leading slash.
+func New(m map[string]string) vfs.FileSystem {
+	return mapFS(m)
+}
+
+// mapFS is the map based implementation of FileSystem
+type mapFS map[string]string
+
+func (fs mapFS) String() string { return "mapfs" }
+
+func (fs mapFS) Close() error { return nil }
+
+func filename(p string) string {
+	return strings.TrimPrefix(p, "/")
+}
+
+func (fs mapFS) Open(p string) (vfs.ReadSeekCloser, error) {
+	b, ok := fs[filename(p)]
+	if !ok {
+		return nil, os.ErrNotExist
+	}
+	return nopCloser{strings.NewReader(b)}, nil
+}
+
+func fileInfo(name, contents string) os.FileInfo {
+	return mapFI{name: pathpkg.Base(name), size: len(contents)}
+}
+
+func dirInfo(name string) os.FileInfo {
+	return mapFI{name: pathpkg.Base(name), dir: true}
+}
+
+func (fs mapFS) Lstat(p string) (os.FileInfo, error) {
+	b, ok := fs[filename(p)]
+	if ok {
+		return fileInfo(p, b), nil
+	}
+	ents, _ := fs.ReadDir(p)
+	if len(ents) > 0 {
+		return dirInfo(p), nil
+	}
+	return nil, os.ErrNotExist
+}
+
+func (fs mapFS) Stat(p string) (os.FileInfo, error) {
+	return fs.Lstat(p)
+}
+
+// slashdir returns path.Dir(p), but special-cases paths not beginning
+// with a slash to be in the root.
+func slashdir(p string) string {
+	d := pathpkg.Dir(p)
+	if d == "." {
+		return "/"
+	}
+	if strings.HasPrefix(p, "/") {
+		return d
+	}
+	return "/" + d
+}
+
+func (fs mapFS) ReadDir(p string) ([]os.FileInfo, error) {
+	p = pathpkg.Clean(p)
+	var ents []string
+	fim := make(map[string]os.FileInfo) // base -> fi
+	for fn, b := range fs {
+		dir := slashdir(fn)
+		isFile := true
+		var lastBase string
+		for {
+			if dir == p {
+				base := lastBase
+				if isFile {
+					base = pathpkg.Base(fn)
+				}
+				if fim[base] == nil {
+					var fi os.FileInfo
+					if isFile {
+						fi = fileInfo(fn, b)
+					} else {
+						fi = dirInfo(base)
+					}
+					ents = append(ents, base)
+					fim[base] = fi
+				}
+			}
+			if dir == "/" {
+				break
+			} else {
+				isFile = false
+				lastBase = pathpkg.Base(dir)
+				dir = pathpkg.Dir(dir)
+			}
+		}
+	}
+	if len(ents) == 0 {
+		return nil, os.ErrNotExist
+	}
+
+	sort.Strings(ents)
+	var list []os.FileInfo
+	for _, dir := range ents {
+		list = append(list, fim[dir])
+	}
+	return list, nil
+}
+
+// mapFI is the map-based implementation of FileInfo.
+type mapFI struct {
+	name string
+	size int
+	dir  bool
+}
+
+func (fi mapFI) IsDir() bool        { return fi.dir }
+func (fi mapFI) ModTime() time.Time { return time.Time{} }
+func (fi mapFI) Mode() os.FileMode {
+	if fi.IsDir() {
+		return 0755 | os.ModeDir
+	}
+	return 0444
+}
+func (fi mapFI) Name() string     { return pathpkg.Base(fi.name) }
+func (fi mapFI) Size() int64      { return int64(fi.size) }
+func (fi mapFI) Sys() interface{} { return nil }
+
+type nopCloser struct {
+	io.ReadSeeker
+}
+
+func (nc nopCloser) Close() error { return nil }
diff --git a/third_party/go.tools/godoc/vfs/mapfs/mapfs_test.go b/third_party/go.tools/godoc/vfs/mapfs/mapfs_test.go
new file mode 100644
index 0000000..6b7db29
--- /dev/null
+++ b/third_party/go.tools/godoc/vfs/mapfs/mapfs_test.go
@@ -0,0 +1,111 @@
+// Copyright 2013 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 mapfs
+
+import (
+	"io/ioutil"
+	"os"
+	"reflect"
+	"testing"
+)
+
+func TestOpenRoot(t *testing.T) {
+	fs := New(map[string]string{
+		"foo/bar/three.txt": "a",
+		"foo/bar.txt":       "b",
+		"top.txt":           "c",
+		"other-top.txt":     "d",
+	})
+	tests := []struct {
+		path string
+		want string
+	}{
+		{"/foo/bar/three.txt", "a"},
+		{"foo/bar/three.txt", "a"},
+		{"foo/bar.txt", "b"},
+		{"top.txt", "c"},
+		{"/top.txt", "c"},
+		{"other-top.txt", "d"},
+		{"/other-top.txt", "d"},
+	}
+	for _, tt := range tests {
+		rsc, err := fs.Open(tt.path)
+		if err != nil {
+			t.Errorf("Open(%q) = %v", tt.path, err)
+			continue
+		}
+		slurp, err := ioutil.ReadAll(rsc)
+		if err != nil {
+			t.Error(err)
+		}
+		if string(slurp) != tt.want {
+			t.Errorf("Read(%q) = %q; want %q", tt.path, tt.want, slurp)
+		}
+		rsc.Close()
+	}
+
+	_, err := fs.Open("/xxxx")
+	if !os.IsNotExist(err) {
+		t.Errorf("ReadDir /xxxx = %v; want os.IsNotExist error", err)
+	}
+}
+
+func TestReaddir(t *testing.T) {
+	fs := New(map[string]string{
+		"foo/bar/three.txt": "333",
+		"foo/bar.txt":       "22",
+		"top.txt":           "top.txt file",
+		"other-top.txt":     "other-top.txt file",
+	})
+	tests := []struct {
+		dir  string
+		want []os.FileInfo
+	}{
+		{
+			dir: "/",
+			want: []os.FileInfo{
+				mapFI{name: "foo", dir: true},
+				mapFI{name: "other-top.txt", size: len("other-top.txt file")},
+				mapFI{name: "top.txt", size: len("top.txt file")},
+			},
+		},
+		{
+			dir: "/foo",
+			want: []os.FileInfo{
+				mapFI{name: "bar", dir: true},
+				mapFI{name: "bar.txt", size: 2},
+			},
+		},
+		{
+			dir: "/foo/",
+			want: []os.FileInfo{
+				mapFI{name: "bar", dir: true},
+				mapFI{name: "bar.txt", size: 2},
+			},
+		},
+		{
+			dir: "/foo/bar",
+			want: []os.FileInfo{
+				mapFI{name: "three.txt", size: 3},
+			},
+		},
+	}
+	for _, tt := range tests {
+		fis, err := fs.ReadDir(tt.dir)
+		if err != nil {
+			t.Errorf("ReadDir(%q) = %v", tt.dir, err)
+			continue
+		}
+		if !reflect.DeepEqual(fis, tt.want) {
+			t.Errorf("ReadDir(%q) = %#v; want %#v", tt.dir, fis, tt.want)
+			continue
+		}
+	}
+
+	_, err := fs.ReadDir("/xxxx")
+	if !os.IsNotExist(err) {
+		t.Errorf("ReadDir /xxxx = %v; want os.IsNotExist error", err)
+	}
+}
diff --git a/third_party/go.tools/godoc/vfs/namespace.go b/third_party/go.tools/godoc/vfs/namespace.go
new file mode 100644
index 0000000..dbba20c
--- /dev/null
+++ b/third_party/go.tools/godoc/vfs/namespace.go
@@ -0,0 +1,381 @@
+// 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.
+
+package vfs
+
+import (
+	"fmt"
+	"io"
+	"os"
+	pathpkg "path"
+	"sort"
+	"strings"
+	"time"
+)
+
+// Setting debugNS = true will enable debugging prints about
+// name space translations.
+const debugNS = false
+
+// A NameSpace is a file system made up of other file systems
+// mounted at specific locations in the name space.
+//
+// The representation is a map from mount point locations
+// to the list of file systems mounted at that location.  A traditional
+// Unix mount table would use a single file system per mount point,
+// but we want to be able to mount multiple file systems on a single
+// mount point and have the system behave as if the union of those
+// file systems were present at the mount point.
+// For example, if the OS file system has a Go installation in
+// c:\Go and additional Go path trees in  d:\Work1 and d:\Work2, then
+// this name space creates the view we want for the godoc server:
+//
+//	NameSpace{
+//		"/": {
+//			{old: "/", fs: OS(`c:\Go`), new: "/"},
+//		},
+//		"/src/pkg": {
+//			{old: "/src/pkg", fs: OS(`c:\Go`), new: "/src/pkg"},
+//			{old: "/src/pkg", fs: OS(`d:\Work1`), new: "/src"},
+//			{old: "/src/pkg", fs: OS(`d:\Work2`), new: "/src"},
+//		},
+//	}
+//
+// This is created by executing:
+//
+//	ns := NameSpace{}
+//	ns.Bind("/", OS(`c:\Go`), "/", BindReplace)
+//	ns.Bind("/src/pkg", OS(`d:\Work1`), "/src", BindAfter)
+//	ns.Bind("/src/pkg", OS(`d:\Work2`), "/src", BindAfter)
+//
+// A particular mount point entry is a triple (old, fs, new), meaning that to
+// operate on a path beginning with old, replace that prefix (old) with new
+// and then pass that path to the FileSystem implementation fs.
+//
+// Given this name space, a ReadDir of /src/pkg/code will check each prefix
+// of the path for a mount point (first /src/pkg/code, then /src/pkg, then /src,
+// then /), stopping when it finds one.  For the above example, /src/pkg/code
+// will find the mount point at /src/pkg:
+//
+//	{old: "/src/pkg", fs: OS(`c:\Go`), new: "/src/pkg"},
+//	{old: "/src/pkg", fs: OS(`d:\Work1`), new: "/src"},
+//	{old: "/src/pkg", fs: OS(`d:\Work2`), new: "/src"},
+//
+// ReadDir will when execute these three calls and merge the results:
+//
+//	OS(`c:\Go`).ReadDir("/src/pkg/code")
+//	OS(`d:\Work1').ReadDir("/src/code")
+//	OS(`d:\Work2').ReadDir("/src/code")
+//
+// Note that the "/src/pkg" in "/src/pkg/code" has been replaced by
+// just "/src" in the final two calls.
+//
+// OS is itself an implementation of a file system: it implements
+// OS(`c:\Go`).ReadDir("/src/pkg/code") as ioutil.ReadDir(`c:\Go\src\pkg\code`).
+//
+// Because the new path is evaluated by fs (here OS(root)), another way
+// to read the mount table is to mentally combine fs+new, so that this table:
+//
+//	{old: "/src/pkg", fs: OS(`c:\Go`), new: "/src/pkg"},
+//	{old: "/src/pkg", fs: OS(`d:\Work1`), new: "/src"},
+//	{old: "/src/pkg", fs: OS(`d:\Work2`), new: "/src"},
+//
+// reads as:
+//
+//	"/src/pkg" -> c:\Go\src\pkg
+//	"/src/pkg" -> d:\Work1\src
+//	"/src/pkg" -> d:\Work2\src
+//
+// An invariant (a redundancy) of the name space representation is that
+// ns[mtpt][i].old is always equal to mtpt (in the example, ns["/src/pkg"]'s
+// mount table entries always have old == "/src/pkg").  The 'old' field is
+// useful to callers, because they receive just a []mountedFS and not any
+// other indication of which mount point was found.
+//
+type NameSpace map[string][]mountedFS
+
+// A mountedFS handles requests for path by replacing
+// a prefix 'old' with 'new' and then calling the fs methods.
+type mountedFS struct {
+	old string
+	fs  FileSystem
+	new string
+}
+
+// hasPathPrefix returns true if x == y or x == y + "/" + more
+func hasPathPrefix(x, y string) bool {
+	return x == y || strings.HasPrefix(x, y) && (strings.HasSuffix(y, "/") || strings.HasPrefix(x[len(y):], "/"))
+}
+
+// translate translates path for use in m, replacing old with new.
+//
+// mountedFS{"/src/pkg", fs, "/src"}.translate("/src/pkg/code") == "/src/code".
+func (m mountedFS) translate(path string) string {
+	path = pathpkg.Clean("/" + path)
+	if !hasPathPrefix(path, m.old) {
+		panic("translate " + path + " but old=" + m.old)
+	}
+	return pathpkg.Join(m.new, path[len(m.old):])
+}
+
+func (NameSpace) String() string {
+	return "ns"
+}
+
+// Fprint writes a text representation of the name space to w.
+func (ns NameSpace) Fprint(w io.Writer) {
+	fmt.Fprint(w, "name space {\n")
+	var all []string
+	for mtpt := range ns {
+		all = append(all, mtpt)
+	}
+	sort.Strings(all)
+	for _, mtpt := range all {
+		fmt.Fprintf(w, "\t%s:\n", mtpt)
+		for _, m := range ns[mtpt] {
+			fmt.Fprintf(w, "\t\t%s %s\n", m.fs, m.new)
+		}
+	}
+	fmt.Fprint(w, "}\n")
+}
+
+// clean returns a cleaned, rooted path for evaluation.
+// It canonicalizes the path so that we can use string operations
+// to analyze it.
+func (NameSpace) clean(path string) string {
+	return pathpkg.Clean("/" + path)
+}
+
+type BindMode int
+
+const (
+	BindReplace BindMode = iota
+	BindBefore
+	BindAfter
+)
+
+// Bind causes references to old to redirect to the path new in newfs.
+// If mode is BindReplace, old redirections are discarded.
+// If mode is BindBefore, this redirection takes priority over existing ones,
+// but earlier ones are still consulted for paths that do not exist in newfs.
+// If mode is BindAfter, this redirection happens only after existing ones
+// have been tried and failed.
+func (ns NameSpace) Bind(old string, newfs FileSystem, new string, mode BindMode) {
+	old = ns.clean(old)
+	new = ns.clean(new)
+	m := mountedFS{old, newfs, new}
+	var mtpt []mountedFS
+	switch mode {
+	case BindReplace:
+		mtpt = append(mtpt, m)
+	case BindAfter:
+		mtpt = append(mtpt, ns.resolve(old)...)
+		mtpt = append(mtpt, m)
+	case BindBefore:
+		mtpt = append(mtpt, m)
+		mtpt = append(mtpt, ns.resolve(old)...)
+	}
+
+	// Extend m.old, m.new in inherited mount point entries.
+	for i := range mtpt {
+		m := &mtpt[i]
+		if m.old != old {
+			if !hasPathPrefix(old, m.old) {
+				// This should not happen.  If it does, panic so
+				// that we can see the call trace that led to it.
+				panic(fmt.Sprintf("invalid Bind: old=%q m={%q, %s, %q}", old, m.old, m.fs.String(), m.new))
+			}
+			suffix := old[len(m.old):]
+			m.old = pathpkg.Join(m.old, suffix)
+			m.new = pathpkg.Join(m.new, suffix)
+		}
+	}
+
+	ns[old] = mtpt
+}
+
+// resolve resolves a path to the list of mountedFS to use for path.
+func (ns NameSpace) resolve(path string) []mountedFS {
+	path = ns.clean(path)
+	for {
+		if m := ns[path]; m != nil {
+			if debugNS {
+				fmt.Printf("resolve %s: %v\n", path, m)
+			}
+			return m
+		}
+		if path == "/" {
+			break
+		}
+		path = pathpkg.Dir(path)
+	}
+	return nil
+}
+
+// Open implements the FileSystem Open method.
+func (ns NameSpace) Open(path string) (ReadSeekCloser, error) {
+	var err error
+	for _, m := range ns.resolve(path) {
+		if debugNS {
+			fmt.Printf("tx %s: %v\n", path, m.translate(path))
+		}
+		r, err1 := m.fs.Open(m.translate(path))
+		if err1 == nil {
+			return r, nil
+		}
+		if err == nil {
+			err = err1
+		}
+	}
+	if err == nil {
+		err = &os.PathError{Op: "open", Path: path, Err: os.ErrNotExist}
+	}
+	return nil, err
+}
+
+// stat implements the FileSystem Stat and Lstat methods.
+func (ns NameSpace) stat(path string, f func(FileSystem, string) (os.FileInfo, error)) (os.FileInfo, error) {
+	var err error
+	for _, m := range ns.resolve(path) {
+		fi, err1 := f(m.fs, m.translate(path))
+		if err1 == nil {
+			return fi, nil
+		}
+		if err == nil {
+			err = err1
+		}
+	}
+	if err == nil {
+		err = &os.PathError{Op: "stat", Path: path, Err: os.ErrNotExist}
+	}
+	return nil, err
+}
+
+func (ns NameSpace) Stat(path string) (os.FileInfo, error) {
+	return ns.stat(path, FileSystem.Stat)
+}
+
+func (ns NameSpace) Lstat(path string) (os.FileInfo, error) {
+	return ns.stat(path, FileSystem.Lstat)
+}
+
+// dirInfo is a trivial implementation of os.FileInfo for a directory.
+type dirInfo string
+
+func (d dirInfo) Name() string       { return string(d) }
+func (d dirInfo) Size() int64        { return 0 }
+func (d dirInfo) Mode() os.FileMode  { return os.ModeDir | 0555 }
+func (d dirInfo) ModTime() time.Time { return startTime }
+func (d dirInfo) IsDir() bool        { return true }
+func (d dirInfo) Sys() interface{}   { return nil }
+
+var startTime = time.Now()
+
+// ReadDir implements the FileSystem ReadDir method.  It's where most of the magic is.
+// (The rest is in resolve.)
+//
+// Logically, ReadDir must return the union of all the directories that are named
+// by path.  In order to avoid misinterpreting Go packages, of all the directories
+// that contain Go source code, we only include the files from the first,
+// but we include subdirectories from all.
+//
+// ReadDir must also return directory entries needed to reach mount points.
+// If the name space looks like the example in the type NameSpace comment,
+// but c:\Go does not have a src/pkg subdirectory, we still want to be able
+// to find that subdirectory, because we've mounted d:\Work1 and d:\Work2
+// there.  So if we don't see "src" in the directory listing for c:\Go, we add an
+// entry for it before returning.
+//
+func (ns NameSpace) ReadDir(path string) ([]os.FileInfo, error) {
+	path = ns.clean(path)
+
+	var (
+		haveGo   = false
+		haveName = map[string]bool{}
+		all      []os.FileInfo
+		err      error
+		first    []os.FileInfo
+	)
+
+	for _, m := range ns.resolve(path) {
+		dir, err1 := m.fs.ReadDir(m.translate(path))
+		if err1 != nil {
+			if err == nil {
+				err = err1
+			}
+			continue
+		}
+
+		if dir == nil {
+			dir = []os.FileInfo{}
+		}
+
+		if first == nil {
+			first = dir
+		}
+
+		// If we don't yet have Go files in 'all' and this directory
+		// has some, add all the files from this directory.
+		// Otherwise, only add subdirectories.
+		useFiles := false
+		if !haveGo {
+			for _, d := range dir {
+				if strings.HasSuffix(d.Name(), ".go") {
+					useFiles = true
+					haveGo = true
+					break
+				}
+			}
+		}
+
+		for _, d := range dir {
+			name := d.Name()
+			if (d.IsDir() || useFiles) && !haveName[name] {
+				haveName[name] = true
+				all = append(all, d)
+			}
+		}
+	}
+
+	// We didn't find any directories containing Go files.
+	// If some directory returned successfully, use that.
+	if !haveGo {
+		for _, d := range first {
+			if !haveName[d.Name()] {
+				haveName[d.Name()] = true
+				all = append(all, d)
+			}
+		}
+	}
+
+	// Built union.  Add any missing directories needed to reach mount points.
+	for old := range ns {
+		if hasPathPrefix(old, path) && old != path {
+			// Find next element after path in old.
+			elem := old[len(path):]
+			elem = strings.TrimPrefix(elem, "/")
+			if i := strings.Index(elem, "/"); i >= 0 {
+				elem = elem[:i]
+			}
+			if !haveName[elem] {
+				haveName[elem] = true
+				all = append(all, dirInfo(elem))
+			}
+		}
+	}
+
+	if len(all) == 0 {
+		return nil, err
+	}
+
+	sort.Sort(byName(all))
+	return all, nil
+}
+
+// byName implements sort.Interface.
+type byName []os.FileInfo
+
+func (f byName) Len() int           { return len(f) }
+func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
+func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
diff --git a/third_party/go.tools/godoc/vfs/os.go b/third_party/go.tools/godoc/vfs/os.go
new file mode 100644
index 0000000..4063690
--- /dev/null
+++ b/third_party/go.tools/godoc/vfs/os.go
@@ -0,0 +1,63 @@
+// Copyright 2013 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 vfs
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	pathpkg "path"
+	"path/filepath"
+)
+
+// OS returns an implementation of FileSystem reading from the
+// tree rooted at root.  Recording a root is convenient everywhere
+// but necessary on Windows, because the slash-separated path
+// passed to Open has no way to specify a drive letter.  Using a root
+// lets code refer to OS(`c:\`), OS(`d:\`) and so on.
+func OS(root string) FileSystem {
+	return osFS(root)
+}
+
+type osFS string
+
+func (root osFS) String() string { return "os(" + string(root) + ")" }
+
+func (root osFS) resolve(path string) string {
+	// Clean the path so that it cannot possibly begin with ../.
+	// If it did, the result of filepath.Join would be outside the
+	// tree rooted at root.  We probably won't ever see a path
+	// with .. in it, but be safe anyway.
+	path = pathpkg.Clean("/" + path)
+
+	return filepath.Join(string(root), path)
+}
+
+func (root osFS) Open(path string) (ReadSeekCloser, error) {
+	f, err := os.Open(root.resolve(path))
+	if err != nil {
+		return nil, err
+	}
+	fi, err := f.Stat()
+	if err != nil {
+		return nil, err
+	}
+	if fi.IsDir() {
+		return nil, fmt.Errorf("Open: %s is a directory", path)
+	}
+	return f, nil
+}
+
+func (root osFS) Lstat(path string) (os.FileInfo, error) {
+	return os.Lstat(root.resolve(path))
+}
+
+func (root osFS) Stat(path string) (os.FileInfo, error) {
+	return os.Stat(root.resolve(path))
+}
+
+func (root osFS) ReadDir(path string) ([]os.FileInfo, error) {
+	return ioutil.ReadDir(root.resolve(path)) // is sorted
+}
diff --git a/third_party/go.tools/godoc/vfs/vfs.go b/third_party/go.tools/godoc/vfs/vfs.go
new file mode 100644
index 0000000..937c2b2
--- /dev/null
+++ b/third_party/go.tools/godoc/vfs/vfs.go
@@ -0,0 +1,45 @@
+// Copyright 2013 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 vfs defines types for abstract file system access and provides an
+// implementation accessing the file system of the underlying OS.
+package vfs
+
+import (
+	"io"
+	"io/ioutil"
+	"os"
+)
+
+// The FileSystem interface specifies the methods godoc is using
+// to access the file system for which it serves documentation.
+type FileSystem interface {
+	Opener
+	Lstat(path string) (os.FileInfo, error)
+	Stat(path string) (os.FileInfo, error)
+	ReadDir(path string) ([]os.FileInfo, error)
+	String() string
+}
+
+// Opener is a minimal virtual filesystem that can only open regular files.
+type Opener interface {
+	Open(name string) (ReadSeekCloser, error)
+}
+
+// A ReadSeekCloser can Read, Seek, and Close.
+type ReadSeekCloser interface {
+	io.Reader
+	io.Seeker
+	io.Closer
+}
+
+// ReadFile reads the file named by path from fs and returns the contents.
+func ReadFile(fs Opener, path string) ([]byte, error) {
+	rc, err := fs.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer rc.Close()
+	return ioutil.ReadAll(rc)
+}
diff --git a/third_party/go.tools/godoc/vfs/zipfs/zipfs.go b/third_party/go.tools/godoc/vfs/zipfs/zipfs.go
new file mode 100644
index 0000000..fc99afa
--- /dev/null
+++ b/third_party/go.tools/godoc/vfs/zipfs/zipfs.go
@@ -0,0 +1,237 @@
+// 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.
+
+// Package zipfs file provides an implementation of the FileSystem
+// interface based on the contents of a .zip file.
+//
+// Assumptions:
+//
+// - The file paths stored in the zip file must use a slash ('/') as path
+//   separator; and they must be relative (i.e., they must not start with
+//   a '/' - this is usually the case if the file was created w/o special
+//   options).
+// - The zip file system treats the file paths found in the zip internally
+//   like absolute paths w/o a leading '/'; i.e., the paths are considered
+//   relative to the root of the file system.
+// - All path arguments to file system methods must be absolute paths.
+package zipfs
+
+import (
+	"archive/zip"
+	"fmt"
+	"io"
+	"os"
+	"path"
+	"sort"
+	"strings"
+	"time"
+
+	"llvm.org/llgo/third_party/go.tools/godoc/vfs"
+)
+
+// zipFI is the zip-file based implementation of FileInfo
+type zipFI struct {
+	name string    // directory-local name
+	file *zip.File // nil for a directory
+}
+
+func (fi zipFI) Name() string {
+	return fi.name
+}
+
+func (fi zipFI) Size() int64 {
+	if f := fi.file; f != nil {
+		return int64(f.UncompressedSize)
+	}
+	return 0 // directory
+}
+
+func (fi zipFI) ModTime() time.Time {
+	if f := fi.file; f != nil {
+		return f.ModTime()
+	}
+	return time.Time{} // directory has no modified time entry
+}
+
+func (fi zipFI) Mode() os.FileMode {
+	if fi.file == nil {
+		// Unix directories typically are executable, hence 555.
+		return os.ModeDir | 0555
+	}
+	return 0444
+}
+
+func (fi zipFI) IsDir() bool {
+	return fi.file == nil
+}
+
+func (fi zipFI) Sys() interface{} {
+	return nil
+}
+
+// zipFS is the zip-file based implementation of FileSystem
+type zipFS struct {
+	*zip.ReadCloser
+	list zipList
+	name string
+}
+
+func (fs *zipFS) String() string {
+	return "zip(" + fs.name + ")"
+}
+
+func (fs *zipFS) Close() error {
+	fs.list = nil
+	return fs.ReadCloser.Close()
+}
+
+func zipPath(name string) string {
+	name = path.Clean(name)
+	if !path.IsAbs(name) {
+		panic(fmt.Sprintf("stat: not an absolute path: %s", name))
+	}
+	return name[1:] // strip leading '/'
+}
+
+func (fs *zipFS) stat(abspath string) (int, zipFI, error) {
+	i, exact := fs.list.lookup(abspath)
+	if i < 0 {
+		// abspath has leading '/' stripped - print it explicitly
+		return -1, zipFI{}, fmt.Errorf("file not found: /%s", abspath)
+	}
+	_, name := path.Split(abspath)
+	var file *zip.File
+	if exact {
+		file = fs.list[i] // exact match found - must be a file
+	}
+	return i, zipFI{name, file}, nil
+}
+
+func (fs *zipFS) Open(abspath string) (vfs.ReadSeekCloser, error) {
+	_, fi, err := fs.stat(zipPath(abspath))
+	if err != nil {
+		return nil, err
+	}
+	if fi.IsDir() {
+		return nil, fmt.Errorf("Open: %s is a directory", abspath)
+	}
+	r, err := fi.file.Open()
+	if err != nil {
+		return nil, err
+	}
+	return &zipSeek{fi.file, r}, nil
+}
+
+type zipSeek struct {
+	file *zip.File
+	io.ReadCloser
+}
+
+func (f *zipSeek) Seek(offset int64, whence int) (int64, error) {
+	if whence == 0 && offset == 0 {
+		r, err := f.file.Open()
+		if err != nil {
+			return 0, err
+		}
+		f.Close()
+		f.ReadCloser = r
+		return 0, nil
+	}
+	return 0, fmt.Errorf("unsupported Seek in %s", f.file.Name)
+}
+
+func (fs *zipFS) Lstat(abspath string) (os.FileInfo, error) {
+	_, fi, err := fs.stat(zipPath(abspath))
+	return fi, err
+}
+
+func (fs *zipFS) Stat(abspath string) (os.FileInfo, error) {
+	_, fi, err := fs.stat(zipPath(abspath))
+	return fi, err
+}
+
+func (fs *zipFS) ReadDir(abspath string) ([]os.FileInfo, error) {
+	path := zipPath(abspath)
+	i, fi, err := fs.stat(path)
+	if err != nil {
+		return nil, err
+	}
+	if !fi.IsDir() {
+		return nil, fmt.Errorf("ReadDir: %s is not a directory", abspath)
+	}
+
+	var list []os.FileInfo
+	dirname := path + "/"
+	prevname := ""
+	for _, e := range fs.list[i:] {
+		if !strings.HasPrefix(e.Name, dirname) {
+			break // not in the same directory anymore
+		}
+		name := e.Name[len(dirname):] // local name
+		file := e
+		if i := strings.IndexRune(name, '/'); i >= 0 {
+			// We infer directories from files in subdirectories.
+			// If we have x/y, return a directory entry for x.
+			name = name[0:i] // keep local directory name only
+			file = nil
+		}
+		// If we have x/y and x/z, don't return two directory entries for x.
+		// TODO(gri): It should be possible to do this more efficiently
+		// by determining the (fs.list) range of local directory entries
+		// (via two binary searches).
+		if name != prevname {
+			list = append(list, zipFI{name, file})
+			prevname = name
+		}
+	}
+
+	return list, nil
+}
+
+func New(rc *zip.ReadCloser, name string) vfs.FileSystem {
+	list := make(zipList, len(rc.File))
+	copy(list, rc.File) // sort a copy of rc.File
+	sort.Sort(list)
+	return &zipFS{rc, list, name}
+}
+
+type zipList []*zip.File
+
+// zipList implements sort.Interface
+func (z zipList) Len() int           { return len(z) }
+func (z zipList) Less(i, j int) bool { return z[i].Name < z[j].Name }
+func (z zipList) Swap(i, j int)      { z[i], z[j] = z[j], z[i] }
+
+// lookup returns the smallest index of an entry with an exact match
+// for name, or an inexact match starting with name/. If there is no
+// such entry, the result is -1, false.
+func (z zipList) lookup(name string) (index int, exact bool) {
+	// look for exact match first (name comes before name/ in z)
+	i := sort.Search(len(z), func(i int) bool {
+		return name <= z[i].Name
+	})
+	if i >= len(z) {
+		return -1, false
+	}
+	// 0 <= i < len(z)
+	if z[i].Name == name {
+		return i, true
+	}
+
+	// look for inexact match (must be in z[i:], if present)
+	z = z[i:]
+	name += "/"
+	j := sort.Search(len(z), func(i int) bool {
+		return name <= z[i].Name
+	})
+	if j >= len(z) {
+		return -1, false
+	}
+	// 0 <= j < len(z)
+	if strings.HasPrefix(z[j].Name, name) {
+		return i + j, false
+	}
+
+	return -1, false
+}
diff --git a/third_party/go.tools/imports/fix.go b/third_party/go.tools/imports/fix.go
new file mode 100644
index 0000000..46352e3
--- /dev/null
+++ b/third_party/go.tools/imports/fix.go
@@ -0,0 +1,387 @@
+// Copyright 2013 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 imports
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+	"sync"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+)
+
+// importToGroup is a list of functions which map from an import path to
+// a group number.
+var importToGroup = []func(importPath string) (num int, ok bool){
+	func(importPath string) (num int, ok bool) {
+		if strings.HasPrefix(importPath, "appengine") {
+			return 2, true
+		}
+		return
+	},
+	func(importPath string) (num int, ok bool) {
+		if strings.Contains(importPath, ".") {
+			return 1, true
+		}
+		return
+	},
+}
+
+func importGroup(importPath string) int {
+	for _, fn := range importToGroup {
+		if n, ok := fn(importPath); ok {
+			return n
+		}
+	}
+	return 0
+}
+
+func fixImports(fset *token.FileSet, f *ast.File) (added []string, err error) {
+	// refs are a set of possible package references currently unsatisfied by imports.
+	// first key: either base package (e.g. "fmt") or renamed package
+	// second key: referenced package symbol (e.g. "Println")
+	refs := make(map[string]map[string]bool)
+
+	// decls are the current package imports. key is base package or renamed package.
+	decls := make(map[string]*ast.ImportSpec)
+
+	// collect potential uses of packages.
+	var visitor visitFn
+	visitor = visitFn(func(node ast.Node) ast.Visitor {
+		if node == nil {
+			return visitor
+		}
+		switch v := node.(type) {
+		case *ast.ImportSpec:
+			if v.Name != nil {
+				decls[v.Name.Name] = v
+			} else {
+				local := importPathToName(strings.Trim(v.Path.Value, `\"`))
+				decls[local] = v
+			}
+		case *ast.SelectorExpr:
+			xident, ok := v.X.(*ast.Ident)
+			if !ok {
+				break
+			}
+			if xident.Obj != nil {
+				// if the parser can resolve it, it's not a package ref
+				break
+			}
+			pkgName := xident.Name
+			if refs[pkgName] == nil {
+				refs[pkgName] = make(map[string]bool)
+			}
+			if decls[pkgName] == nil {
+				refs[pkgName][v.Sel.Name] = true
+			}
+		}
+		return visitor
+	})
+	ast.Walk(visitor, f)
+
+	// Search for imports matching potential package references.
+	searches := 0
+	type result struct {
+		ipath string
+		name  string
+		err   error
+	}
+	results := make(chan result)
+	for pkgName, symbols := range refs {
+		if len(symbols) == 0 {
+			continue // skip over packages already imported
+		}
+		go func(pkgName string, symbols map[string]bool) {
+			ipath, rename, err := findImport(pkgName, symbols)
+			r := result{ipath: ipath, err: err}
+			if rename {
+				r.name = pkgName
+			}
+			results <- r
+		}(pkgName, symbols)
+		searches++
+	}
+	for i := 0; i < searches; i++ {
+		result := <-results
+		if result.err != nil {
+			return nil, result.err
+		}
+		if result.ipath != "" {
+			if result.name != "" {
+				astutil.AddNamedImport(fset, f, result.name, result.ipath)
+			} else {
+				astutil.AddImport(fset, f, result.ipath)
+			}
+			added = append(added, result.ipath)
+		}
+	}
+
+	// Nil out any unused ImportSpecs, to be removed in following passes
+	unusedImport := map[string]bool{}
+	for pkg, is := range decls {
+		if refs[pkg] == nil && pkg != "_" && pkg != "." {
+			unusedImport[strings.Trim(is.Path.Value, `"`)] = true
+		}
+	}
+	for ipath := range unusedImport {
+		if ipath == "C" {
+			// Don't remove cgo stuff.
+			continue
+		}
+		astutil.DeleteImport(fset, f, ipath)
+	}
+
+	return added, nil
+}
+
+// importPathToName returns the package name for the given import path.
+var importPathToName = importPathToNameGoPath
+
+// importPathToNameBasic assumes the package name is the base of import path.
+func importPathToNameBasic(importPath string) (packageName string) {
+	return path.Base(importPath)
+}
+
+// importPathToNameGoPath finds out the actual package name, as declared in its .go files.
+// If there's a problem, it falls back to using importPathToNameBasic.
+func importPathToNameGoPath(importPath string) (packageName string) {
+	if buildPkg, err := build.Import(importPath, "", 0); err == nil {
+		return buildPkg.Name
+	} else {
+		return importPathToNameBasic(importPath)
+	}
+}
+
+type pkg struct {
+	importpath string // full pkg import path, e.g. "net/http"
+	dir        string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
+}
+
+var pkgIndexOnce sync.Once
+
+var pkgIndex struct {
+	sync.Mutex
+	m map[string][]pkg // shortname => []pkg, e.g "http" => "net/http"
+}
+
+// gate is a semaphore for limiting concurrency.
+type gate chan struct{}
+
+func (g gate) enter() { g <- struct{}{} }
+func (g gate) leave() { <-g }
+
+// fsgate protects the OS & filesystem from too much concurrency.
+// Too much disk I/O -> too many threads -> swapping and bad scheduling.
+var fsgate = make(gate, 8)
+
+func loadPkgIndex() {
+	pkgIndex.Lock()
+	pkgIndex.m = make(map[string][]pkg)
+	pkgIndex.Unlock()
+
+	var wg sync.WaitGroup
+	for _, path := range build.Default.SrcDirs() {
+		fsgate.enter()
+		f, err := os.Open(path)
+		if err != nil {
+			fsgate.leave()
+			fmt.Fprint(os.Stderr, err)
+			continue
+		}
+		children, err := f.Readdir(-1)
+		f.Close()
+		fsgate.leave()
+		if err != nil {
+			fmt.Fprint(os.Stderr, err)
+			continue
+		}
+		for _, child := range children {
+			if child.IsDir() {
+				wg.Add(1)
+				go func(path, name string) {
+					defer wg.Done()
+					loadPkg(&wg, path, name)
+				}(path, child.Name())
+			}
+		}
+	}
+	wg.Wait()
+}
+
+func loadPkg(wg *sync.WaitGroup, root, pkgrelpath string) {
+	importpath := filepath.ToSlash(pkgrelpath)
+	dir := filepath.Join(root, importpath)
+
+	fsgate.enter()
+	defer fsgate.leave()
+	pkgDir, err := os.Open(dir)
+	if err != nil {
+		return
+	}
+	children, err := pkgDir.Readdir(-1)
+	pkgDir.Close()
+	if err != nil {
+		return
+	}
+	// hasGo tracks whether a directory actually appears to be a
+	// Go source code directory. If $GOPATH == $HOME, and
+	// $HOME/src has lots of other large non-Go projects in it,
+	// then the calls to importPathToName below can be expensive.
+	hasGo := false
+	for _, child := range children {
+		// Avoid .foo, _foo, and testdata directory trees.
+		name := child.Name()
+		if name == "" || name[0] == '.' || name[0] == '_' || name == "testdata" {
+			continue
+		}
+		if strings.HasSuffix(name, ".go") {
+			hasGo = true
+		}
+		if child.IsDir() {
+			wg.Add(1)
+			go func(root, name string) {
+				defer wg.Done()
+				loadPkg(wg, root, name)
+			}(root, filepath.Join(importpath, name))
+		}
+	}
+	if hasGo {
+		shortName := importPathToName(importpath)
+		pkgIndex.Lock()
+		pkgIndex.m[shortName] = append(pkgIndex.m[shortName], pkg{
+			importpath: importpath,
+			dir:        dir,
+		})
+		pkgIndex.Unlock()
+	}
+
+}
+
+// loadExports returns a list exports for a package.
+var loadExports = loadExportsGoPath
+
+func loadExportsGoPath(dir string) map[string]bool {
+	exports := make(map[string]bool)
+	buildPkg, err := build.ImportDir(dir, 0)
+	if err != nil {
+		if strings.Contains(err.Error(), "no buildable Go source files in") {
+			return nil
+		}
+		fmt.Fprintf(os.Stderr, "could not import %q: %v\n", dir, err)
+		return nil
+	}
+	fset := token.NewFileSet()
+	for _, files := range [...][]string{buildPkg.GoFiles, buildPkg.CgoFiles} {
+		for _, file := range files {
+			f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "could not parse %q: %v\n", file, err)
+				continue
+			}
+			for name := range f.Scope.Objects {
+				if ast.IsExported(name) {
+					exports[name] = true
+				}
+			}
+		}
+	}
+	return exports
+}
+
+// findImport searches for a package with the given symbols.
+// If no package is found, findImport returns "".
+// Declared as a variable rather than a function so goimports can be easily
+// extended by adding a file with an init function.
+var findImport = findImportGoPath
+
+func findImportGoPath(pkgName string, symbols map[string]bool) (string, bool, error) {
+	// Fast path for the standard library.
+	// In the common case we hopefully never have to scan the GOPATH, which can
+	// be slow with moving disks.
+	if pkg, rename, ok := findImportStdlib(pkgName, symbols); ok {
+		return pkg, rename, nil
+	}
+
+	// TODO(sameer): look at the import lines for other Go files in the
+	// local directory, since the user is likely to import the same packages
+	// in the current Go file.  Return rename=true when the other Go files
+	// use a renamed package that's also used in the current file.
+
+	pkgIndexOnce.Do(loadPkgIndex)
+
+	// Collect exports for packages with matching names.
+	var wg sync.WaitGroup
+	var pkgsMu sync.Mutex // guards pkgs
+	// full importpath => exported symbol => True
+	// e.g. "net/http" => "Client" => True
+	pkgs := make(map[string]map[string]bool)
+	pkgIndex.Lock()
+	for _, pkg := range pkgIndex.m[pkgName] {
+		wg.Add(1)
+		go func(importpath, dir string) {
+			defer wg.Done()
+			exports := loadExports(dir)
+			if exports != nil {
+				pkgsMu.Lock()
+				pkgs[importpath] = exports
+				pkgsMu.Unlock()
+			}
+		}(pkg.importpath, pkg.dir)
+	}
+	pkgIndex.Unlock()
+	wg.Wait()
+
+	// Filter out packages missing required exported symbols.
+	for symbol := range symbols {
+		for importpath, exports := range pkgs {
+			if !exports[symbol] {
+				delete(pkgs, importpath)
+			}
+		}
+	}
+	if len(pkgs) == 0 {
+		return "", false, nil
+	}
+
+	// If there are multiple candidate packages, the shortest one wins.
+	// This is a heuristic to prefer the standard library (e.g. "bytes")
+	// over e.g. "github.com/foo/bar/bytes".
+	shortest := ""
+	for importPath := range pkgs {
+		if shortest == "" || len(importPath) < len(shortest) {
+			shortest = importPath
+		}
+	}
+	return shortest, false, nil
+}
+
+type visitFn func(node ast.Node) ast.Visitor
+
+func (fn visitFn) Visit(node ast.Node) ast.Visitor {
+	return fn(node)
+}
+
+func findImportStdlib(shortPkg string, symbols map[string]bool) (importPath string, rename, ok bool) {
+	for symbol := range symbols {
+		path := stdlib[shortPkg+"."+symbol]
+		if path == "" {
+			return "", false, false
+		}
+		if importPath != "" && importPath != path {
+			// Ambiguous. Symbols pointed to different things.
+			return "", false, false
+		}
+		importPath = path
+	}
+	return importPath, false, importPath != ""
+}
diff --git a/third_party/go.tools/imports/fix_test.go b/third_party/go.tools/imports/fix_test.go
new file mode 100644
index 0000000..9382a19
--- /dev/null
+++ b/third_party/go.tools/imports/fix_test.go
@@ -0,0 +1,804 @@
+// Copyright 2013 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 imports
+
+import (
+	"flag"
+	"go/build"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sync"
+	"testing"
+)
+
+var only = flag.String("only", "", "If non-empty, the fix test to run")
+
+var tests = []struct {
+	name    string
+	in, out string
+}{
+	// Adding an import to an existing parenthesized import
+	{
+		name: "factored_imports_add",
+		in: `package foo
+import (
+  "fmt"
+)
+func bar() {
+var b bytes.Buffer
+fmt.Println(b.String())
+}
+`,
+		out: `package foo
+
+import (
+	"bytes"
+	"fmt"
+)
+
+func bar() {
+	var b bytes.Buffer
+	fmt.Println(b.String())
+}
+`,
+	},
+
+	// Adding an import to an existing parenthesized import,
+	// verifying it goes into the first section.
+	{
+		name: "factored_imports_add_first_sec",
+		in: `package foo
+import (
+  "fmt"
+
+  "appengine"
+)
+func bar() {
+var b bytes.Buffer
+_ = appengine.IsDevServer
+fmt.Println(b.String())
+}
+`,
+		out: `package foo
+
+import (
+	"bytes"
+	"fmt"
+
+	"appengine"
+)
+
+func bar() {
+	var b bytes.Buffer
+	_ = appengine.IsDevServer
+	fmt.Println(b.String())
+}
+`,
+	},
+
+	// Adding an import to an existing parenthesized import,
+	// verifying it goes into the first section. (test 2)
+	{
+		name: "factored_imports_add_first_sec_2",
+		in: `package foo
+import (
+  "fmt"
+
+  "appengine"
+)
+func bar() {
+_ = math.NaN
+_ = fmt.Sprintf
+_ = appengine.IsDevServer
+}
+`,
+		out: `package foo
+
+import (
+	"fmt"
+	"math"
+
+	"appengine"
+)
+
+func bar() {
+	_ = math.NaN
+	_ = fmt.Sprintf
+	_ = appengine.IsDevServer
+}
+`,
+	},
+
+	// Adding a new import line, without parens
+	{
+		name: "add_import_section",
+		in: `package foo
+func bar() {
+var b bytes.Buffer
+}
+`,
+		out: `package foo
+
+import "bytes"
+
+func bar() {
+	var b bytes.Buffer
+}
+`,
+	},
+
+	// Adding two new imports, which should make a parenthesized import decl.
+	{
+		name: "add_import_paren_section",
+		in: `package foo
+func bar() {
+_, _ := bytes.Buffer, zip.NewReader
+}
+`,
+		out: `package foo
+
+import (
+	"archive/zip"
+	"bytes"
+)
+
+func bar() {
+	_, _ := bytes.Buffer, zip.NewReader
+}
+`,
+	},
+
+	// Make sure we don't add things twice
+	{
+		name: "no_double_add",
+		in: `package foo
+func bar() {
+_, _ := bytes.Buffer, bytes.NewReader
+}
+`,
+		out: `package foo
+
+import "bytes"
+
+func bar() {
+	_, _ := bytes.Buffer, bytes.NewReader
+}
+`,
+	},
+
+	// Remove unused imports, 1 of a factored block
+	{
+		name: "remove_unused_1_of_2",
+		in: `package foo
+import (
+"bytes"
+"fmt"
+)
+
+func bar() {
+_, _ := bytes.Buffer, bytes.NewReader
+}
+`,
+		out: `package foo
+
+import "bytes"
+
+func bar() {
+	_, _ := bytes.Buffer, bytes.NewReader
+}
+`,
+	},
+
+	// Remove unused imports, 2 of 2
+	{
+		name: "remove_unused_2_of_2",
+		in: `package foo
+import (
+"bytes"
+"fmt"
+)
+
+func bar() {
+}
+`,
+		out: `package foo
+
+func bar() {
+}
+`,
+	},
+
+	// Remove unused imports, 1 of 1
+	{
+		name: "remove_unused_1_of_1",
+		in: `package foo
+
+import "fmt"
+
+func bar() {
+}
+`,
+		out: `package foo
+
+func bar() {
+}
+`,
+	},
+
+	// Don't remove empty imports.
+	{
+		name: "dont_remove_empty_imports",
+		in: `package foo
+import (
+_ "image/png"
+_ "image/jpeg"
+)
+`,
+		out: `package foo
+
+import (
+	_ "image/jpeg"
+	_ "image/png"
+)
+`,
+	},
+
+	// Don't remove dot imports.
+	{
+		name: "dont_remove_dot_imports",
+		in: `package foo
+import (
+. "foo"
+. "bar"
+)
+`,
+		out: `package foo
+
+import (
+	. "bar"
+	. "foo"
+)
+`,
+	},
+
+	// Skip refs the parser can resolve.
+	{
+		name: "skip_resolved_refs",
+		in: `package foo
+
+func f() {
+	type t struct{ Println func(string) }
+	fmt := t{Println: func(string) {}}
+	fmt.Println("foo")
+}
+`,
+		out: `package foo
+
+func f() {
+	type t struct{ Println func(string) }
+	fmt := t{Println: func(string) {}}
+	fmt.Println("foo")
+}
+`,
+	},
+
+	// Do not add a package we already have a resolution for.
+	{
+		name: "skip_template",
+		in: `package foo
+
+import "html/template"
+
+func f() { t = template.New("sometemplate") }
+`,
+		out: `package foo
+
+import "html/template"
+
+func f() { t = template.New("sometemplate") }
+`,
+	},
+
+	// Don't touch cgo
+	{
+		name: "cgo",
+		in: `package foo
+
+/*
+#include <foo.h>
+*/
+import "C"
+`,
+		out: `package foo
+
+/*
+#include <foo.h>
+*/
+import "C"
+`,
+	},
+
+	// Put some things in their own section
+	{
+		name: "make_sections",
+		in: `package foo
+
+import (
+"os"
+)
+
+func foo () {
+_, _ = os.Args, fmt.Println
+_, _ = appengine.FooSomething, user.Current
+}
+`,
+		out: `package foo
+
+import (
+	"fmt"
+	"os"
+
+	"appengine"
+	"appengine/user"
+)
+
+func foo() {
+	_, _ = os.Args, fmt.Println
+	_, _ = appengine.FooSomething, user.Current
+}
+`,
+	},
+
+	// Delete existing empty import block
+	{
+		name: "delete_empty_import_block",
+		in: `package foo
+
+import ()
+`,
+		out: `package foo
+`,
+	},
+
+	// Use existing empty import block
+	{
+		name: "use_empty_import_block",
+		in: `package foo
+
+import ()
+
+func f() {
+	_ = fmt.Println
+}
+`,
+		out: `package foo
+
+import "fmt"
+
+func f() {
+	_ = fmt.Println
+}
+`,
+	},
+
+	// Blank line before adding new section.
+	{
+		name: "blank_line_before_new_group",
+		in: `package foo
+
+import (
+	"fmt"
+	"net"
+)
+
+func f() {
+	_ = net.Dial
+	_ = fmt.Printf
+	_ = snappy.Foo
+}
+`,
+		out: `package foo
+
+import (
+	"fmt"
+	"net"
+
+	"code.google.com/p/snappy-go/snappy"
+)
+
+func f() {
+	_ = net.Dial
+	_ = fmt.Printf
+	_ = snappy.Foo
+}
+`,
+	},
+
+	// Blank line between standard library and third-party stuff.
+	{
+		name: "blank_line_separating_std_and_third_party",
+		in: `package foo
+
+import (
+	"code.google.com/p/snappy-go/snappy"
+	"fmt"
+	"net"
+)
+
+func f() {
+	_ = net.Dial
+	_ = fmt.Printf
+	_ = snappy.Foo
+}
+`,
+		out: `package foo
+
+import (
+	"fmt"
+	"net"
+
+	"code.google.com/p/snappy-go/snappy"
+)
+
+func f() {
+	_ = net.Dial
+	_ = fmt.Printf
+	_ = snappy.Foo
+}
+`,
+	},
+
+	// golang.org/issue/6884
+	{
+		name: "issue 6884",
+		in: `package main
+
+// A comment
+func main() {
+	fmt.Println("Hello, world")
+}
+`,
+		out: `package main
+
+import "fmt"
+
+// A comment
+func main() {
+	fmt.Println("Hello, world")
+}
+`,
+	},
+
+	// golang.org/issue/7132
+	{
+		name: "issue 7132",
+		in: `package main
+
+import (
+"fmt"
+
+"gu"
+"github.com/foo/bar"
+)
+
+var (
+a = bar.a
+b = gu.a
+c = fmt.Printf
+)
+`,
+		out: `package main
+
+import (
+	"fmt"
+
+	"gu"
+
+	"github.com/foo/bar"
+)
+
+var (
+	a = bar.a
+	b = gu.a
+	c = fmt.Printf
+)
+`,
+	},
+
+	{
+		name: "renamed package",
+		in: `package main
+
+var _ = str.HasPrefix
+`,
+		out: `package main
+
+import str "strings"
+
+var _ = str.HasPrefix
+`,
+	},
+
+	{
+		name: "fragment with main",
+		in:   `func main(){fmt.Println("Hello, world")}`,
+		out: `package main
+
+import "fmt"
+
+func main() { fmt.Println("Hello, world") }
+`,
+	},
+
+	{
+		name: "fragment without main",
+		in:   `func notmain(){fmt.Println("Hello, world")}`,
+		out: `import "fmt"
+
+func notmain() { fmt.Println("Hello, world") }`,
+	},
+
+	// Remove first import within in a 2nd/3rd/4th/etc. section.
+	// golang.org/issue/7679
+	{
+		name: "issue 7679",
+		in: `package main
+
+import (
+	"fmt"
+
+	"github.com/foo/bar"
+	"github.com/foo/qux"
+)
+
+func main() {
+	var _ = fmt.Println
+	//var _ = bar.A
+	var _ = qux.B
+}
+`,
+		out: `package main
+
+import (
+	"fmt"
+
+	"github.com/foo/qux"
+)
+
+func main() {
+	var _ = fmt.Println
+	//var _ = bar.A
+	var _ = qux.B
+}
+`,
+	},
+
+	// Blank line can be added before all types of import declarations.
+	// golang.org/issue/7866
+	{
+		name: "issue 7866",
+		in: `package main
+
+import (
+	"fmt"
+	renamed_bar "github.com/foo/bar"
+
+	. "github.com/foo/baz"
+	"io"
+
+	_ "github.com/foo/qux"
+	"strings"
+)
+
+func main() {
+	_, _, _, _, _ = fmt.Errorf, io.Copy, strings.Contains, renamed_bar.A, B
+}
+`,
+		out: `package main
+
+import (
+	"fmt"
+
+	renamed_bar "github.com/foo/bar"
+
+	"io"
+
+	. "github.com/foo/baz"
+
+	"strings"
+
+	_ "github.com/foo/qux"
+)
+
+func main() {
+	_, _, _, _, _ = fmt.Errorf, io.Copy, strings.Contains, renamed_bar.A, B
+}
+`,
+	},
+
+	// Non-idempotent comment formatting
+	// golang.org/issue/8035
+	{
+		name: "issue 8035",
+		in: `package main
+
+import (
+	"fmt"                     // A
+	"go/ast"                  // B
+	_ "launchpad.net/gocheck" // C
+)
+
+func main() { _, _ = fmt.Print, ast.Walk }
+`,
+		out: `package main
+
+import (
+	"fmt"    // A
+	"go/ast" // B
+
+	_ "launchpad.net/gocheck" // C
+)
+
+func main() { _, _ = fmt.Print, ast.Walk }
+`,
+	},
+
+	// Failure to delete all duplicate imports
+	// golang.org/issue/8459
+	{
+		name: "issue 8459",
+		in: `package main
+
+import (
+	"fmt"
+	"log"
+	"log"
+	"math"
+)
+
+func main() { fmt.Println("pi:", math.Pi) }
+`,
+		out: `package main
+
+import (
+	"fmt"
+	"math"
+)
+
+func main() { fmt.Println("pi:", math.Pi) }
+`,
+	},
+}
+
+func TestFixImports(t *testing.T) {
+	simplePkgs := map[string]string{
+		"fmt":       "fmt",
+		"os":        "os",
+		"math":      "math",
+		"appengine": "appengine",
+		"user":      "appengine/user",
+		"zip":       "archive/zip",
+		"bytes":     "bytes",
+		"snappy":    "code.google.com/p/snappy-go/snappy",
+		"str":       "strings",
+	}
+	findImport = func(pkgName string, symbols map[string]bool) (string, bool, error) {
+		return simplePkgs[pkgName], pkgName == "str", nil
+	}
+
+	options := &Options{
+		TabWidth:  8,
+		TabIndent: true,
+		Comments:  true,
+		Fragment:  true,
+	}
+
+	for _, tt := range tests {
+		if *only != "" && tt.name != *only {
+			continue
+		}
+		buf, err := Process(tt.name+".go", []byte(tt.in), options)
+		if err != nil {
+			t.Errorf("error on %q: %v", tt.name, err)
+			continue
+		}
+		if got := string(buf); got != tt.out {
+			t.Errorf("results diff on %q\nGOT:\n%s\nWANT:\n%s\n", tt.name, got, tt.out)
+		}
+	}
+}
+
+func TestFindImportGoPath(t *testing.T) {
+	goroot, err := ioutil.TempDir("", "goimports-")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(goroot)
+
+	pkgIndexOnce = sync.Once{}
+
+	origStdlib := stdlib
+	defer func() {
+		stdlib = origStdlib
+	}()
+	stdlib = nil
+
+	// Test against imaginary bits/bytes package in std lib
+	bytesDir := filepath.Join(goroot, "src", "pkg", "bits", "bytes")
+	for _, tag := range build.Default.ReleaseTags {
+		// Go 1.4 rearranged the GOROOT tree to remove the "pkg" path component.
+		if tag == "go1.4" {
+			bytesDir = filepath.Join(goroot, "src", "bits", "bytes")
+		}
+	}
+	if err := os.MkdirAll(bytesDir, 0755); err != nil {
+		t.Fatal(err)
+	}
+	bytesSrcPath := filepath.Join(bytesDir, "bytes.go")
+	bytesPkgPath := "bits/bytes"
+	bytesSrc := []byte(`package bytes
+
+type Buffer2 struct {}
+`)
+	if err := ioutil.WriteFile(bytesSrcPath, bytesSrc, 0775); err != nil {
+		t.Fatal(err)
+	}
+	oldGOROOT := build.Default.GOROOT
+	oldGOPATH := build.Default.GOPATH
+	build.Default.GOROOT = goroot
+	build.Default.GOPATH = ""
+	defer func() {
+		build.Default.GOROOT = oldGOROOT
+		build.Default.GOPATH = oldGOPATH
+	}()
+
+	got, rename, err := findImportGoPath("bytes", map[string]bool{"Buffer2": true})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got != bytesPkgPath || rename {
+		t.Errorf(`findImportGoPath("bytes", Buffer2 ...)=%q, %t, want "%s", false`, got, rename, bytesPkgPath)
+	}
+
+	got, rename, err = findImportGoPath("bytes", map[string]bool{"Missing": true})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got != "" || rename {
+		t.Errorf(`findImportGoPath("bytes", Missing ...)=%q, %t, want "", false`, got, rename)
+	}
+}
+
+func TestFindImportStdlib(t *testing.T) {
+	tests := []struct {
+		pkg     string
+		symbols []string
+		want    string
+	}{
+		{"http", []string{"Get"}, "net/http"},
+		{"http", []string{"Get", "Post"}, "net/http"},
+		{"http", []string{"Get", "Foo"}, ""},
+		{"bytes", []string{"Buffer"}, "bytes"},
+		{"ioutil", []string{"Discard"}, "io/ioutil"},
+	}
+	for _, tt := range tests {
+		got, rename, ok := findImportStdlib(tt.pkg, strSet(tt.symbols))
+		if (got != "") != ok {
+			t.Error("findImportStdlib return value inconsistent")
+		}
+		if got != tt.want || rename {
+			t.Errorf("findImportStdlib(%q, %q) = %q, %t; want %q, false", tt.pkg, tt.symbols, got, rename, tt.want)
+		}
+	}
+}
+
+func strSet(ss []string) map[string]bool {
+	m := make(map[string]bool)
+	for _, s := range ss {
+		m[s] = true
+	}
+	return m
+}
diff --git a/third_party/go.tools/imports/imports.go b/third_party/go.tools/imports/imports.go
new file mode 100644
index 0000000..8af4080
--- /dev/null
+++ b/third_party/go.tools/imports/imports.go
@@ -0,0 +1,279 @@
+// Copyright 2013 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 imports implements a Go pretty-printer (like package "go/format")
+// that also adds or removes import statements as necessary.
+package imports
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/format"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"io"
+	"regexp"
+	"strconv"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+)
+
+// Options specifies options for processing files.
+type Options struct {
+	Fragment  bool // Accept fragment of a source file (no package statement)
+	AllErrors bool // Report all errors (not just the first 10 on different lines)
+
+	Comments  bool // Print comments (true if nil *Options provided)
+	TabIndent bool // Use tabs for indent (true if nil *Options provided)
+	TabWidth  int  // Tab width (8 if nil *Options provided)
+}
+
+// Process formats and adjusts imports for the provided file.
+// If opt is nil the defaults are used.
+func Process(filename string, src []byte, opt *Options) ([]byte, error) {
+	if opt == nil {
+		opt = &Options{Comments: true, TabIndent: true, TabWidth: 8}
+	}
+
+	fileSet := token.NewFileSet()
+	file, adjust, err := parse(fileSet, filename, src, opt)
+	if err != nil {
+		return nil, err
+	}
+
+	_, err = fixImports(fileSet, file)
+	if err != nil {
+		return nil, err
+	}
+
+	sortImports(fileSet, file)
+	imps := astutil.Imports(fileSet, file)
+
+	var spacesBefore []string // import paths we need spaces before
+	for _, impSection := range imps {
+		// Within each block of contiguous imports, see if any
+		// import lines are in different group numbers. If so,
+		// we'll need to put a space between them so it's
+		// compatible with gofmt.
+		lastGroup := -1
+		for _, importSpec := range impSection {
+			importPath, _ := strconv.Unquote(importSpec.Path.Value)
+			groupNum := importGroup(importPath)
+			if groupNum != lastGroup && lastGroup != -1 {
+				spacesBefore = append(spacesBefore, importPath)
+			}
+			lastGroup = groupNum
+		}
+
+	}
+
+	printerMode := printer.UseSpaces
+	if opt.TabIndent {
+		printerMode |= printer.TabIndent
+	}
+	printConfig := &printer.Config{Mode: printerMode, Tabwidth: opt.TabWidth}
+
+	var buf bytes.Buffer
+	err = printConfig.Fprint(&buf, fileSet, file)
+	if err != nil {
+		return nil, err
+	}
+	out := buf.Bytes()
+	if adjust != nil {
+		out = adjust(src, out)
+	}
+	if len(spacesBefore) > 0 {
+		out = addImportSpaces(bytes.NewReader(out), spacesBefore)
+	}
+
+	out, err = format.Source(out)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// parse parses src, which was read from filename,
+// as a Go source file or statement list.
+func parse(fset *token.FileSet, filename string, src []byte, opt *Options) (*ast.File, func(orig, src []byte) []byte, error) {
+	parserMode := parser.Mode(0)
+	if opt.Comments {
+		parserMode |= parser.ParseComments
+	}
+	if opt.AllErrors {
+		parserMode |= parser.AllErrors
+	}
+
+	// Try as whole source file.
+	file, err := parser.ParseFile(fset, filename, src, parserMode)
+	if err == nil {
+		return file, nil, nil
+	}
+	// If the error is that the source file didn't begin with a
+	// package line and we accept fragmented input, fall through to
+	// try as a source fragment.  Stop and return on any other error.
+	if !opt.Fragment || !strings.Contains(err.Error(), "expected 'package'") {
+		return nil, nil, err
+	}
+
+	// If this is a declaration list, make it a source file
+	// by inserting a package clause.
+	// Insert using a ;, not a newline, so that the line numbers
+	// in psrc match the ones in src.
+	psrc := append([]byte("package main;"), src...)
+	file, err = parser.ParseFile(fset, filename, psrc, parserMode)
+	if err == nil {
+		// If a main function exists, we will assume this is a main
+		// package and leave the file.
+		if containsMainFunc(file) {
+			return file, nil, nil
+		}
+
+		adjust := func(orig, src []byte) []byte {
+			// Remove the package clause.
+			// Gofmt has turned the ; into a \n.
+			src = src[len("package main\n"):]
+			return matchSpace(orig, src)
+		}
+		return file, adjust, nil
+	}
+	// If the error is that the source file didn't begin with a
+	// declaration, fall through to try as a statement list.
+	// Stop and return on any other error.
+	if !strings.Contains(err.Error(), "expected declaration") {
+		return nil, nil, err
+	}
+
+	// If this is a statement list, make it a source file
+	// by inserting a package clause and turning the list
+	// into a function body.  This handles expressions too.
+	// Insert using a ;, not a newline, so that the line numbers
+	// in fsrc match the ones in src.
+	fsrc := append(append([]byte("package p; func _() {"), src...), '}')
+	file, err = parser.ParseFile(fset, filename, fsrc, parserMode)
+	if err == nil {
+		adjust := func(orig, src []byte) []byte {
+			// Remove the wrapping.
+			// Gofmt has turned the ; into a \n\n.
+			src = src[len("package p\n\nfunc _() {"):]
+			src = src[:len(src)-len("}\n")]
+			// Gofmt has also indented the function body one level.
+			// Remove that indent.
+			src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1)
+			return matchSpace(orig, src)
+		}
+		return file, adjust, nil
+	}
+
+	// Failed, and out of options.
+	return nil, nil, err
+}
+
+// containsMainFunc checks if a file contains a function declaration with the
+// function signature 'func main()'
+func containsMainFunc(file *ast.File) bool {
+	for _, decl := range file.Decls {
+		if f, ok := decl.(*ast.FuncDecl); ok {
+			if f.Name.Name != "main" {
+				continue
+			}
+
+			if len(f.Type.Params.List) != 0 {
+				continue
+			}
+
+			if f.Type.Results != nil && len(f.Type.Results.List) != 0 {
+				continue
+			}
+
+			return true
+		}
+	}
+
+	return false
+}
+
+func cutSpace(b []byte) (before, middle, after []byte) {
+	i := 0
+	for i < len(b) && (b[i] == ' ' || b[i] == '\t' || b[i] == '\n') {
+		i++
+	}
+	j := len(b)
+	for j > 0 && (b[j-1] == ' ' || b[j-1] == '\t' || b[j-1] == '\n') {
+		j--
+	}
+	if i <= j {
+		return b[:i], b[i:j], b[j:]
+	}
+	return nil, nil, b[j:]
+}
+
+// matchSpace reformats src to use the same space context as orig.
+// 1) If orig begins with blank lines, matchSpace inserts them at the beginning of src.
+// 2) matchSpace copies the indentation of the first non-blank line in orig
+//    to every non-blank line in src.
+// 3) matchSpace copies the trailing space from orig and uses it in place
+//   of src's trailing space.
+func matchSpace(orig []byte, src []byte) []byte {
+	before, _, after := cutSpace(orig)
+	i := bytes.LastIndex(before, []byte{'\n'})
+	before, indent := before[:i+1], before[i+1:]
+
+	_, src, _ = cutSpace(src)
+
+	var b bytes.Buffer
+	b.Write(before)
+	for len(src) > 0 {
+		line := src
+		if i := bytes.IndexByte(line, '\n'); i >= 0 {
+			line, src = line[:i+1], line[i+1:]
+		} else {
+			src = nil
+		}
+		if len(line) > 0 && line[0] != '\n' { // not blank
+			b.Write(indent)
+		}
+		b.Write(line)
+	}
+	b.Write(after)
+	return b.Bytes()
+}
+
+var impLine = regexp.MustCompile(`^\s+(?:[\w\.]+\s+)?"(.+)"`)
+
+func addImportSpaces(r io.Reader, breaks []string) []byte {
+	var out bytes.Buffer
+	sc := bufio.NewScanner(r)
+	inImports := false
+	done := false
+	for sc.Scan() {
+		s := sc.Text()
+
+		if !inImports && !done && strings.HasPrefix(s, "import") {
+			inImports = true
+		}
+		if inImports && (strings.HasPrefix(s, "var") ||
+			strings.HasPrefix(s, "func") ||
+			strings.HasPrefix(s, "const") ||
+			strings.HasPrefix(s, "type")) {
+			done = true
+			inImports = false
+		}
+		if inImports && len(breaks) > 0 {
+			if m := impLine.FindStringSubmatch(s); m != nil {
+				if m[1] == string(breaks[0]) {
+					out.WriteByte('\n')
+					breaks = breaks[1:]
+				}
+			}
+		}
+
+		fmt.Fprintln(&out, s)
+	}
+	return out.Bytes()
+}
diff --git a/third_party/go.tools/imports/mkindex.go b/third_party/go.tools/imports/mkindex.go
new file mode 100644
index 0000000..755e239
--- /dev/null
+++ b/third_party/go.tools/imports/mkindex.go
@@ -0,0 +1,173 @@
+// +build ignore
+
+// Copyright 2013 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.
+
+// Command mkindex creates the file "pkgindex.go" containing an index of the Go
+// standard library. The file is intended to be built as part of the imports
+// package, so that the package may be used in environments where a GOROOT is
+// not available (such as App Engine).
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"log"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+)
+
+var (
+	pkgIndex = make(map[string][]pkg)
+	exports  = make(map[string]map[string]bool)
+)
+
+func main() {
+	// Don't use GOPATH.
+	ctx := build.Default
+	ctx.GOPATH = ""
+
+	// Populate pkgIndex global from GOROOT.
+	for _, path := range ctx.SrcDirs() {
+		f, err := os.Open(path)
+		if err != nil {
+			log.Print(err)
+			continue
+		}
+		children, err := f.Readdir(-1)
+		f.Close()
+		if err != nil {
+			log.Print(err)
+			continue
+		}
+		for _, child := range children {
+			if child.IsDir() {
+				loadPkg(path, child.Name())
+			}
+		}
+	}
+	// Populate exports global.
+	for _, ps := range pkgIndex {
+		for _, p := range ps {
+			e := loadExports(p.dir)
+			if e != nil {
+				exports[p.dir] = e
+			}
+		}
+	}
+
+	// Construct source file.
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, pkgIndexHead)
+	fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex)
+	fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports)
+	src := buf.Bytes()
+
+	// Replace main.pkg type name with pkg.
+	src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1)
+	// Replace actual GOROOT with "/go".
+	src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1)
+	// Add some line wrapping.
+	src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1)
+	src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1)
+
+	var err error
+	src, err = format.Source(src)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	// Write out source file.
+	err = ioutil.WriteFile("pkgindex.go", src, 0644)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+const pkgIndexHead = `package imports
+
+func init() {
+	pkgIndexOnce.Do(func() {
+		pkgIndex.m = pkgIndexMaster
+	})
+	loadExports = func(dir string) map[string]bool {
+		return exportsMaster[dir]
+	}
+}
+`
+
+type pkg struct {
+	importpath string // full pkg import path, e.g. "net/http"
+	dir        string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
+}
+
+var fset = token.NewFileSet()
+
+func loadPkg(root, importpath string) {
+	shortName := path.Base(importpath)
+	if shortName == "testdata" {
+		return
+	}
+
+	dir := filepath.Join(root, importpath)
+	pkgIndex[shortName] = append(pkgIndex[shortName], pkg{
+		importpath: importpath,
+		dir:        dir,
+	})
+
+	pkgDir, err := os.Open(dir)
+	if err != nil {
+		return
+	}
+	children, err := pkgDir.Readdir(-1)
+	pkgDir.Close()
+	if err != nil {
+		return
+	}
+	for _, child := range children {
+		name := child.Name()
+		if name == "" {
+			continue
+		}
+		if c := name[0]; c == '.' || ('0' <= c && c <= '9') {
+			continue
+		}
+		if child.IsDir() {
+			loadPkg(root, filepath.Join(importpath, name))
+		}
+	}
+}
+
+func loadExports(dir string) map[string]bool {
+	exports := make(map[string]bool)
+	buildPkg, err := build.ImportDir(dir, 0)
+	if err != nil {
+		if strings.Contains(err.Error(), "no buildable Go source files in") {
+			return nil
+		}
+		log.Printf("could not import %q: %v", dir, err)
+		return nil
+	}
+	for _, file := range buildPkg.GoFiles {
+		f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
+		if err != nil {
+			log.Printf("could not parse %q: %v", file, err)
+			continue
+		}
+		for name := range f.Scope.Objects {
+			if ast.IsExported(name) {
+				exports[name] = true
+			}
+		}
+	}
+	return exports
+}
diff --git a/third_party/go.tools/imports/mkstdlib.go b/third_party/go.tools/imports/mkstdlib.go
new file mode 100644
index 0000000..c43d325
--- /dev/null
+++ b/third_party/go.tools/imports/mkstdlib.go
@@ -0,0 +1,90 @@
+// +build ignore
+
+// mkstdlib generates the zstdlib.go file, containing the Go standard
+// library API symbols. It's baked into the binary to avoid scanning
+// GOPATH in the common case.
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"go/format"
+	"io"
+	"log"
+	"os"
+	"path"
+	"path/filepath"
+	"regexp"
+	"sort"
+	"strings"
+)
+
+func mustOpen(name string) io.Reader {
+	f, err := os.Open(name)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return f
+}
+
+func api(base string) string {
+	return filepath.Join(os.Getenv("GOROOT"), "api", base)
+}
+
+var sym = regexp.MustCompile(`^pkg (\S+).*?, (?:var|func|type|const) ([A-Z]\w*)`)
+
+func main() {
+	var buf bytes.Buffer
+	outf := func(format string, args ...interface{}) {
+		fmt.Fprintf(&buf, format, args...)
+	}
+	outf("// AUTO-GENERATED BY mkstdlib.go\n\n")
+	outf("package imports\n")
+	outf("var stdlib = map[string]string{\n")
+	f := io.MultiReader(
+		mustOpen(api("go1.txt")),
+		mustOpen(api("go1.1.txt")),
+		mustOpen(api("go1.2.txt")),
+	)
+	sc := bufio.NewScanner(f)
+	fullImport := map[string]string{} // "zip.NewReader" => "archive/zip"
+	ambiguous := map[string]bool{}
+	var keys []string
+	for sc.Scan() {
+		l := sc.Text()
+		has := func(v string) bool { return strings.Contains(l, v) }
+		if has("struct, ") || has("interface, ") || has(", method (") {
+			continue
+		}
+		if m := sym.FindStringSubmatch(l); m != nil {
+			full := m[1]
+			key := path.Base(full) + "." + m[2]
+			if exist, ok := fullImport[key]; ok {
+				if exist != full {
+					ambiguous[key] = true
+				}
+			} else {
+				fullImport[key] = full
+				keys = append(keys, key)
+			}
+		}
+	}
+	if err := sc.Err(); err != nil {
+		log.Fatal(err)
+	}
+	sort.Strings(keys)
+	for _, key := range keys {
+		if ambiguous[key] {
+			outf("\t// %q is ambiguous\n", key)
+		} else {
+			outf("\t%q: %q,\n", key, fullImport[key])
+		}
+	}
+	outf("}\n")
+	fmtbuf, err := format.Source(buf.Bytes())
+	if err != nil {
+		log.Fatal(err)
+	}
+	os.Stdout.Write(fmtbuf)
+}
diff --git a/third_party/go.tools/imports/sortimports.go b/third_party/go.tools/imports/sortimports.go
new file mode 100644
index 0000000..68b3dc4
--- /dev/null
+++ b/third_party/go.tools/imports/sortimports.go
@@ -0,0 +1,214 @@
+// +build go1.2
+
+// Copyright 2013 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.
+
+// Hacked up copy of go/ast/import.go
+
+package imports
+
+import (
+	"go/ast"
+	"go/token"
+	"sort"
+	"strconv"
+)
+
+// sortImports sorts runs of consecutive import lines in import blocks in f.
+// It also removes duplicate imports when it is possible to do so without data loss.
+func sortImports(fset *token.FileSet, f *ast.File) {
+	for i, d := range f.Decls {
+		d, ok := d.(*ast.GenDecl)
+		if !ok || d.Tok != token.IMPORT {
+			// Not an import declaration, so we're done.
+			// Imports are always first.
+			break
+		}
+
+		if len(d.Specs) == 0 {
+			// Empty import block, remove it.
+			f.Decls = append(f.Decls[:i], f.Decls[i+1:]...)
+		}
+
+		if !d.Lparen.IsValid() {
+			// Not a block: sorted by default.
+			continue
+		}
+
+		// Identify and sort runs of specs on successive lines.
+		i := 0
+		specs := d.Specs[:0]
+		for j, s := range d.Specs {
+			if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line {
+				// j begins a new run.  End this one.
+				specs = append(specs, sortSpecs(fset, f, d.Specs[i:j])...)
+				i = j
+			}
+		}
+		specs = append(specs, sortSpecs(fset, f, d.Specs[i:])...)
+		d.Specs = specs
+
+		// Deduping can leave a blank line before the rparen; clean that up.
+		if len(d.Specs) > 0 {
+			lastSpec := d.Specs[len(d.Specs)-1]
+			lastLine := fset.Position(lastSpec.Pos()).Line
+			if rParenLine := fset.Position(d.Rparen).Line; rParenLine > lastLine+1 {
+				fset.File(d.Rparen).MergeLine(rParenLine - 1)
+			}
+		}
+	}
+}
+
+func importPath(s ast.Spec) string {
+	t, err := strconv.Unquote(s.(*ast.ImportSpec).Path.Value)
+	if err == nil {
+		return t
+	}
+	return ""
+}
+
+func importName(s ast.Spec) string {
+	n := s.(*ast.ImportSpec).Name
+	if n == nil {
+		return ""
+	}
+	return n.Name
+}
+
+func importComment(s ast.Spec) string {
+	c := s.(*ast.ImportSpec).Comment
+	if c == nil {
+		return ""
+	}
+	return c.Text()
+}
+
+// collapse indicates whether prev may be removed, leaving only next.
+func collapse(prev, next ast.Spec) bool {
+	if importPath(next) != importPath(prev) || importName(next) != importName(prev) {
+		return false
+	}
+	return prev.(*ast.ImportSpec).Comment == nil
+}
+
+type posSpan struct {
+	Start token.Pos
+	End   token.Pos
+}
+
+func sortSpecs(fset *token.FileSet, f *ast.File, specs []ast.Spec) []ast.Spec {
+	// Can't short-circuit here even if specs are already sorted,
+	// since they might yet need deduplication.
+	// A lone import, however, may be safely ignored.
+	if len(specs) <= 1 {
+		return specs
+	}
+
+	// Record positions for specs.
+	pos := make([]posSpan, len(specs))
+	for i, s := range specs {
+		pos[i] = posSpan{s.Pos(), s.End()}
+	}
+
+	// Identify comments in this range.
+	// Any comment from pos[0].Start to the final line counts.
+	lastLine := fset.Position(pos[len(pos)-1].End).Line
+	cstart := len(f.Comments)
+	cend := len(f.Comments)
+	for i, g := range f.Comments {
+		if g.Pos() < pos[0].Start {
+			continue
+		}
+		if i < cstart {
+			cstart = i
+		}
+		if fset.Position(g.End()).Line > lastLine {
+			cend = i
+			break
+		}
+	}
+	comments := f.Comments[cstart:cend]
+
+	// Assign each comment to the import spec preceding it.
+	importComment := map[*ast.ImportSpec][]*ast.CommentGroup{}
+	specIndex := 0
+	for _, g := range comments {
+		for specIndex+1 < len(specs) && pos[specIndex+1].Start <= g.Pos() {
+			specIndex++
+		}
+		s := specs[specIndex].(*ast.ImportSpec)
+		importComment[s] = append(importComment[s], g)
+	}
+
+	// Sort the import specs by import path.
+	// Remove duplicates, when possible without data loss.
+	// Reassign the import paths to have the same position sequence.
+	// Reassign each comment to abut the end of its spec.
+	// Sort the comments by new position.
+	sort.Sort(byImportSpec(specs))
+
+	// Dedup. Thanks to our sorting, we can just consider
+	// adjacent pairs of imports.
+	deduped := specs[:0]
+	for i, s := range specs {
+		if i == len(specs)-1 || !collapse(s, specs[i+1]) {
+			deduped = append(deduped, s)
+		} else {
+			p := s.Pos()
+			fset.File(p).MergeLine(fset.Position(p).Line)
+		}
+	}
+	specs = deduped
+
+	// Fix up comment positions
+	for i, s := range specs {
+		s := s.(*ast.ImportSpec)
+		if s.Name != nil {
+			s.Name.NamePos = pos[i].Start
+		}
+		s.Path.ValuePos = pos[i].Start
+		s.EndPos = pos[i].End
+		for _, g := range importComment[s] {
+			for _, c := range g.List {
+				c.Slash = pos[i].End
+			}
+		}
+	}
+
+	sort.Sort(byCommentPos(comments))
+
+	return specs
+}
+
+type byImportSpec []ast.Spec // slice of *ast.ImportSpec
+
+func (x byImportSpec) Len() int      { return len(x) }
+func (x byImportSpec) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x byImportSpec) Less(i, j int) bool {
+	ipath := importPath(x[i])
+	jpath := importPath(x[j])
+
+	igroup := importGroup(ipath)
+	jgroup := importGroup(jpath)
+	if igroup != jgroup {
+		return igroup < jgroup
+	}
+
+	if ipath != jpath {
+		return ipath < jpath
+	}
+	iname := importName(x[i])
+	jname := importName(x[j])
+
+	if iname != jname {
+		return iname < jname
+	}
+	return importComment(x[i]) < importComment(x[j])
+}
+
+type byCommentPos []*ast.CommentGroup
+
+func (x byCommentPos) Len() int           { return len(x) }
+func (x byCommentPos) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() }
diff --git a/third_party/go.tools/imports/sortimports_compat.go b/third_party/go.tools/imports/sortimports_compat.go
new file mode 100644
index 0000000..295f237
--- /dev/null
+++ b/third_party/go.tools/imports/sortimports_compat.go
@@ -0,0 +1,14 @@
+// +build !go1.2
+
+// Copyright 2013 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 imports
+
+import "go/ast"
+
+// Go 1.1 users don't get fancy package grouping.
+// But this is still gofmt-compliant:
+
+var sortImports = ast.SortImports
diff --git a/third_party/go.tools/imports/zstdlib.go b/third_party/go.tools/imports/zstdlib.go
new file mode 100644
index 0000000..6cdc033
--- /dev/null
+++ b/third_party/go.tools/imports/zstdlib.go
@@ -0,0 +1,8374 @@
+// AUTO-GENERATED BY mkstdlib.go
+
+package imports
+
+var stdlib = map[string]string{
+	"adler32.Checksum":                        "hash/adler32",
+	"adler32.New":                             "hash/adler32",
+	"adler32.Size":                            "hash/adler32",
+	"aes.BlockSize":                           "crypto/aes",
+	"aes.KeySizeError":                        "crypto/aes",
+	"aes.NewCipher":                           "crypto/aes",
+	"ascii85.CorruptInputError":               "encoding/ascii85",
+	"ascii85.Decode":                          "encoding/ascii85",
+	"ascii85.Encode":                          "encoding/ascii85",
+	"ascii85.MaxEncodedLen":                   "encoding/ascii85",
+	"ascii85.NewDecoder":                      "encoding/ascii85",
+	"ascii85.NewEncoder":                      "encoding/ascii85",
+	"asn1.BitString":                          "encoding/asn1",
+	"asn1.Enumerated":                         "encoding/asn1",
+	"asn1.Flag":                               "encoding/asn1",
+	"asn1.Marshal":                            "encoding/asn1",
+	"asn1.ObjectIdentifier":                   "encoding/asn1",
+	"asn1.RawContent":                         "encoding/asn1",
+	"asn1.RawValue":                           "encoding/asn1",
+	"asn1.StructuralError":                    "encoding/asn1",
+	"asn1.SyntaxError":                        "encoding/asn1",
+	"asn1.Unmarshal":                          "encoding/asn1",
+	"asn1.UnmarshalWithParams":                "encoding/asn1",
+	"ast.ArrayType":                           "go/ast",
+	"ast.AssignStmt":                          "go/ast",
+	"ast.Bad":                                 "go/ast",
+	"ast.BadDecl":                             "go/ast",
+	"ast.BadExpr":                             "go/ast",
+	"ast.BadStmt":                             "go/ast",
+	"ast.BasicLit":                            "go/ast",
+	"ast.BinaryExpr":                          "go/ast",
+	"ast.BlockStmt":                           "go/ast",
+	"ast.BranchStmt":                          "go/ast",
+	"ast.CallExpr":                            "go/ast",
+	"ast.CaseClause":                          "go/ast",
+	"ast.ChanDir":                             "go/ast",
+	"ast.ChanType":                            "go/ast",
+	"ast.CommClause":                          "go/ast",
+	"ast.Comment":                             "go/ast",
+	"ast.CommentGroup":                        "go/ast",
+	"ast.CommentMap":                          "go/ast",
+	"ast.CompositeLit":                        "go/ast",
+	"ast.Con":                                 "go/ast",
+	"ast.DeclStmt":                            "go/ast",
+	"ast.DeferStmt":                           "go/ast",
+	"ast.Ellipsis":                            "go/ast",
+	"ast.EmptyStmt":                           "go/ast",
+	"ast.ExprStmt":                            "go/ast",
+	"ast.Field":                               "go/ast",
+	"ast.FieldFilter":                         "go/ast",
+	"ast.FieldList":                           "go/ast",
+	"ast.File":                                "go/ast",
+	"ast.FileExports":                         "go/ast",
+	"ast.Filter":                              "go/ast",
+	"ast.FilterDecl":                          "go/ast",
+	"ast.FilterFile":                          "go/ast",
+	"ast.FilterFuncDuplicates":                "go/ast",
+	"ast.FilterImportDuplicates":              "go/ast",
+	"ast.FilterPackage":                       "go/ast",
+	"ast.FilterUnassociatedComments":          "go/ast",
+	"ast.ForStmt":                             "go/ast",
+	"ast.Fprint":                              "go/ast",
+	"ast.Fun":                                 "go/ast",
+	"ast.FuncDecl":                            "go/ast",
+	"ast.FuncLit":                             "go/ast",
+	"ast.FuncType":                            "go/ast",
+	"ast.GenDecl":                             "go/ast",
+	"ast.GoStmt":                              "go/ast",
+	"ast.Ident":                               "go/ast",
+	"ast.IfStmt":                              "go/ast",
+	"ast.ImportSpec":                          "go/ast",
+	"ast.Importer":                            "go/ast",
+	"ast.IncDecStmt":                          "go/ast",
+	"ast.IndexExpr":                           "go/ast",
+	"ast.Inspect":                             "go/ast",
+	"ast.InterfaceType":                       "go/ast",
+	"ast.IsExported":                          "go/ast",
+	"ast.KeyValueExpr":                        "go/ast",
+	"ast.LabeledStmt":                         "go/ast",
+	"ast.Lbl":                                 "go/ast",
+	"ast.MapType":                             "go/ast",
+	"ast.MergeMode":                           "go/ast",
+	"ast.MergePackageFiles":                   "go/ast",
+	"ast.NewCommentMap":                       "go/ast",
+	"ast.NewIdent":                            "go/ast",
+	"ast.NewObj":                              "go/ast",
+	"ast.NewPackage":                          "go/ast",
+	"ast.NewScope":                            "go/ast",
+	"ast.Node":                                "go/ast",
+	"ast.NotNilFilter":                        "go/ast",
+	"ast.ObjKind":                             "go/ast",
+	"ast.Object":                              "go/ast",
+	"ast.Package":                             "go/ast",
+	"ast.PackageExports":                      "go/ast",
+	"ast.ParenExpr":                           "go/ast",
+	"ast.Pkg":                                 "go/ast",
+	"ast.Print":                               "go/ast",
+	"ast.RECV":                                "go/ast",
+	"ast.RangeStmt":                           "go/ast",
+	"ast.ReturnStmt":                          "go/ast",
+	"ast.SEND":                                "go/ast",
+	"ast.Scope":                               "go/ast",
+	"ast.SelectStmt":                          "go/ast",
+	"ast.SelectorExpr":                        "go/ast",
+	"ast.SendStmt":                            "go/ast",
+	"ast.SliceExpr":                           "go/ast",
+	"ast.SortImports":                         "go/ast",
+	"ast.StarExpr":                            "go/ast",
+	"ast.StructType":                          "go/ast",
+	"ast.SwitchStmt":                          "go/ast",
+	"ast.Typ":                                 "go/ast",
+	"ast.TypeAssertExpr":                      "go/ast",
+	"ast.TypeSpec":                            "go/ast",
+	"ast.TypeSwitchStmt":                      "go/ast",
+	"ast.UnaryExpr":                           "go/ast",
+	"ast.ValueSpec":                           "go/ast",
+	"ast.Var":                                 "go/ast",
+	"ast.Visitor":                             "go/ast",
+	"ast.Walk":                                "go/ast",
+	"atomic.AddInt32":                         "sync/atomic",
+	"atomic.AddInt64":                         "sync/atomic",
+	"atomic.AddUint32":                        "sync/atomic",
+	"atomic.AddUint64":                        "sync/atomic",
+	"atomic.AddUintptr":                       "sync/atomic",
+	"atomic.CompareAndSwapInt32":              "sync/atomic",
+	"atomic.CompareAndSwapInt64":              "sync/atomic",
+	"atomic.CompareAndSwapPointer":            "sync/atomic",
+	"atomic.CompareAndSwapUint32":             "sync/atomic",
+	"atomic.CompareAndSwapUint64":             "sync/atomic",
+	"atomic.CompareAndSwapUintptr":            "sync/atomic",
+	"atomic.LoadInt32":                        "sync/atomic",
+	"atomic.LoadInt64":                        "sync/atomic",
+	"atomic.LoadPointer":                      "sync/atomic",
+	"atomic.LoadUint32":                       "sync/atomic",
+	"atomic.LoadUint64":                       "sync/atomic",
+	"atomic.LoadUintptr":                      "sync/atomic",
+	"atomic.StoreInt32":                       "sync/atomic",
+	"atomic.StoreInt64":                       "sync/atomic",
+	"atomic.StorePointer":                     "sync/atomic",
+	"atomic.StoreUint32":                      "sync/atomic",
+	"atomic.StoreUint64":                      "sync/atomic",
+	"atomic.StoreUintptr":                     "sync/atomic",
+	"atomic.SwapInt32":                        "sync/atomic",
+	"atomic.SwapInt64":                        "sync/atomic",
+	"atomic.SwapPointer":                      "sync/atomic",
+	"atomic.SwapUint32":                       "sync/atomic",
+	"atomic.SwapUint64":                       "sync/atomic",
+	"atomic.SwapUintptr":                      "sync/atomic",
+	"base32.CorruptInputError":                "encoding/base32",
+	"base32.Encoding":                         "encoding/base32",
+	"base32.HexEncoding":                      "encoding/base32",
+	"base32.NewDecoder":                       "encoding/base32",
+	"base32.NewEncoder":                       "encoding/base32",
+	"base32.NewEncoding":                      "encoding/base32",
+	"base32.StdEncoding":                      "encoding/base32",
+	"base64.CorruptInputError":                "encoding/base64",
+	"base64.Encoding":                         "encoding/base64",
+	"base64.NewDecoder":                       "encoding/base64",
+	"base64.NewEncoder":                       "encoding/base64",
+	"base64.NewEncoding":                      "encoding/base64",
+	"base64.StdEncoding":                      "encoding/base64",
+	"base64.URLEncoding":                      "encoding/base64",
+	"big.Int":                                 "math/big",
+	"big.MaxBase":                             "math/big",
+	"big.NewInt":                              "math/big",
+	"big.NewRat":                              "math/big",
+	"big.Rat":                                 "math/big",
+	"big.Word":                                "math/big",
+	"binary.BigEndian":                        "encoding/binary",
+	"binary.ByteOrder":                        "encoding/binary",
+	"binary.LittleEndian":                     "encoding/binary",
+	"binary.MaxVarintLen16":                   "encoding/binary",
+	"binary.MaxVarintLen32":                   "encoding/binary",
+	"binary.MaxVarintLen64":                   "encoding/binary",
+	"binary.PutUvarint":                       "encoding/binary",
+	"binary.PutVarint":                        "encoding/binary",
+	"binary.Read":                             "encoding/binary",
+	"binary.ReadUvarint":                      "encoding/binary",
+	"binary.ReadVarint":                       "encoding/binary",
+	"binary.Size":                             "encoding/binary",
+	"binary.Uvarint":                          "encoding/binary",
+	"binary.Varint":                           "encoding/binary",
+	"binary.Write":                            "encoding/binary",
+	"bufio.ErrAdvanceTooFar":                  "bufio",
+	"bufio.ErrBufferFull":                     "bufio",
+	"bufio.ErrInvalidUnreadByte":              "bufio",
+	"bufio.ErrInvalidUnreadRune":              "bufio",
+	"bufio.ErrNegativeAdvance":                "bufio",
+	"bufio.ErrNegativeCount":                  "bufio",
+	"bufio.ErrTooLong":                        "bufio",
+	"bufio.MaxScanTokenSize":                  "bufio",
+	"bufio.NewReadWriter":                     "bufio",
+	"bufio.NewReader":                         "bufio",
+	"bufio.NewReaderSize":                     "bufio",
+	"bufio.NewScanner":                        "bufio",
+	"bufio.NewWriter":                         "bufio",
+	"bufio.NewWriterSize":                     "bufio",
+	"bufio.ReadWriter":                        "bufio",
+	"bufio.Reader":                            "bufio",
+	"bufio.ScanBytes":                         "bufio",
+	"bufio.ScanLines":                         "bufio",
+	"bufio.ScanRunes":                         "bufio",
+	"bufio.ScanWords":                         "bufio",
+	"bufio.Scanner":                           "bufio",
+	"bufio.SplitFunc":                         "bufio",
+	"bufio.Writer":                            "bufio",
+	"build.AllowBinary":                       "go/build",
+	"build.ArchChar":                          "go/build",
+	"build.Context":                           "go/build",
+	"build.Default":                           "go/build",
+	"build.FindOnly":                          "go/build",
+	"build.Import":                            "go/build",
+	"build.ImportDir":                         "go/build",
+	"build.ImportMode":                        "go/build",
+	"build.IsLocalImport":                     "go/build",
+	"build.NoGoError":                         "go/build",
+	"build.Package":                           "go/build",
+	"build.ToolDir":                           "go/build",
+	"bytes.Buffer":                            "bytes",
+	"bytes.Compare":                           "bytes",
+	"bytes.Contains":                          "bytes",
+	"bytes.Count":                             "bytes",
+	"bytes.Equal":                             "bytes",
+	"bytes.EqualFold":                         "bytes",
+	"bytes.ErrTooLarge":                       "bytes",
+	"bytes.Fields":                            "bytes",
+	"bytes.FieldsFunc":                        "bytes",
+	"bytes.HasPrefix":                         "bytes",
+	"bytes.HasSuffix":                         "bytes",
+	"bytes.Index":                             "bytes",
+	"bytes.IndexAny":                          "bytes",
+	"bytes.IndexByte":                         "bytes",
+	"bytes.IndexFunc":                         "bytes",
+	"bytes.IndexRune":                         "bytes",
+	"bytes.Join":                              "bytes",
+	"bytes.LastIndex":                         "bytes",
+	"bytes.LastIndexAny":                      "bytes",
+	"bytes.LastIndexFunc":                     "bytes",
+	"bytes.Map":                               "bytes",
+	"bytes.MinRead":                           "bytes",
+	"bytes.NewBuffer":                         "bytes",
+	"bytes.NewBufferString":                   "bytes",
+	"bytes.NewReader":                         "bytes",
+	"bytes.Reader":                            "bytes",
+	"bytes.Repeat":                            "bytes",
+	"bytes.Replace":                           "bytes",
+	"bytes.Runes":                             "bytes",
+	"bytes.Split":                             "bytes",
+	"bytes.SplitAfter":                        "bytes",
+	"bytes.SplitAfterN":                       "bytes",
+	"bytes.SplitN":                            "bytes",
+	"bytes.Title":                             "bytes",
+	"bytes.ToLower":                           "bytes",
+	"bytes.ToLowerSpecial":                    "bytes",
+	"bytes.ToTitle":                           "bytes",
+	"bytes.ToTitleSpecial":                    "bytes",
+	"bytes.ToUpper":                           "bytes",
+	"bytes.ToUpperSpecial":                    "bytes",
+	"bytes.Trim":                              "bytes",
+	"bytes.TrimFunc":                          "bytes",
+	"bytes.TrimLeft":                          "bytes",
+	"bytes.TrimLeftFunc":                      "bytes",
+	"bytes.TrimPrefix":                        "bytes",
+	"bytes.TrimRight":                         "bytes",
+	"bytes.TrimRightFunc":                     "bytes",
+	"bytes.TrimSpace":                         "bytes",
+	"bytes.TrimSuffix":                        "bytes",
+	"bzip2.NewReader":                         "compress/bzip2",
+	"bzip2.StructuralError":                   "compress/bzip2",
+	"cgi.Handler":                             "net/http/cgi",
+	"cgi.Request":                             "net/http/cgi",
+	"cgi.RequestFromMap":                      "net/http/cgi",
+	"cgi.Serve":                               "net/http/cgi",
+	"cipher.AEAD":                             "crypto/cipher",
+	"cipher.Block":                            "crypto/cipher",
+	"cipher.BlockMode":                        "crypto/cipher",
+	"cipher.NewCBCDecrypter":                  "crypto/cipher",
+	"cipher.NewCBCEncrypter":                  "crypto/cipher",
+	"cipher.NewCFBDecrypter":                  "crypto/cipher",
+	"cipher.NewCFBEncrypter":                  "crypto/cipher",
+	"cipher.NewCTR":                           "crypto/cipher",
+	"cipher.NewGCM":                           "crypto/cipher",
+	"cipher.NewOFB":                           "crypto/cipher",
+	"cipher.Stream":                           "crypto/cipher",
+	"cipher.StreamReader":                     "crypto/cipher",
+	"cipher.StreamWriter":                     "crypto/cipher",
+	"cmplx.Abs":                               "math/cmplx",
+	"cmplx.Acos":                              "math/cmplx",
+	"cmplx.Acosh":                             "math/cmplx",
+	"cmplx.Asin":                              "math/cmplx",
+	"cmplx.Asinh":                             "math/cmplx",
+	"cmplx.Atan":                              "math/cmplx",
+	"cmplx.Atanh":                             "math/cmplx",
+	"cmplx.Conj":                              "math/cmplx",
+	"cmplx.Cos":                               "math/cmplx",
+	"cmplx.Cosh":                              "math/cmplx",
+	"cmplx.Cot":                               "math/cmplx",
+	"cmplx.Exp":                               "math/cmplx",
+	"cmplx.Inf":                               "math/cmplx",
+	"cmplx.IsInf":                             "math/cmplx",
+	"cmplx.IsNaN":                             "math/cmplx",
+	"cmplx.Log":                               "math/cmplx",
+	"cmplx.Log10":                             "math/cmplx",
+	"cmplx.NaN":                               "math/cmplx",
+	"cmplx.Phase":                             "math/cmplx",
+	"cmplx.Polar":                             "math/cmplx",
+	"cmplx.Pow":                               "math/cmplx",
+	"cmplx.Rect":                              "math/cmplx",
+	"cmplx.Sin":                               "math/cmplx",
+	"cmplx.Sinh":                              "math/cmplx",
+	"cmplx.Sqrt":                              "math/cmplx",
+	"cmplx.Tan":                               "math/cmplx",
+	"cmplx.Tanh":                              "math/cmplx",
+	"color.Alpha":                             "image/color",
+	"color.Alpha16":                           "image/color",
+	"color.Alpha16Model":                      "image/color",
+	"color.AlphaModel":                        "image/color",
+	"color.Black":                             "image/color",
+	"color.Color":                             "image/color",
+	"color.Gray":                              "image/color",
+	"color.Gray16":                            "image/color",
+	"color.Gray16Model":                       "image/color",
+	"color.GrayModel":                         "image/color",
+	"color.Model":                             "image/color",
+	"color.ModelFunc":                         "image/color",
+	"color.NRGBA":                             "image/color",
+	"color.NRGBA64":                           "image/color",
+	"color.NRGBA64Model":                      "image/color",
+	"color.NRGBAModel":                        "image/color",
+	"color.Opaque":                            "image/color",
+	"color.Palette":                           "image/color",
+	"color.RGBA":                              "image/color",
+	"color.RGBA64":                            "image/color",
+	"color.RGBA64Model":                       "image/color",
+	"color.RGBAModel":                         "image/color",
+	"color.RGBToYCbCr":                        "image/color",
+	"color.Transparent":                       "image/color",
+	"color.White":                             "image/color",
+	"color.YCbCr":                             "image/color",
+	"color.YCbCrModel":                        "image/color",
+	"color.YCbCrToRGB":                        "image/color",
+	"cookiejar.Jar":                           "net/http/cookiejar",
+	"cookiejar.New":                           "net/http/cookiejar",
+	"cookiejar.Options":                       "net/http/cookiejar",
+	"cookiejar.PublicSuffixList":              "net/http/cookiejar",
+	"crc32.Castagnoli":                        "hash/crc32",
+	"crc32.Checksum":                          "hash/crc32",
+	"crc32.ChecksumIEEE":                      "hash/crc32",
+	"crc32.IEEE":                              "hash/crc32",
+	"crc32.IEEETable":                         "hash/crc32",
+	"crc32.Koopman":                           "hash/crc32",
+	"crc32.MakeTable":                         "hash/crc32",
+	"crc32.New":                               "hash/crc32",
+	"crc32.NewIEEE":                           "hash/crc32",
+	"crc32.Size":                              "hash/crc32",
+	"crc32.Table":                             "hash/crc32",
+	"crc32.Update":                            "hash/crc32",
+	"crc64.Checksum":                          "hash/crc64",
+	"crc64.ECMA":                              "hash/crc64",
+	"crc64.ISO":                               "hash/crc64",
+	"crc64.MakeTable":                         "hash/crc64",
+	"crc64.New":                               "hash/crc64",
+	"crc64.Size":                              "hash/crc64",
+	"crc64.Table":                             "hash/crc64",
+	"crc64.Update":                            "hash/crc64",
+	"crypto.Hash":                             "crypto",
+	"crypto.MD4":                              "crypto",
+	"crypto.MD5":                              "crypto",
+	"crypto.MD5SHA1":                          "crypto",
+	"crypto.PrivateKey":                       "crypto",
+	"crypto.PublicKey":                        "crypto",
+	"crypto.RIPEMD160":                        "crypto",
+	"crypto.RegisterHash":                     "crypto",
+	"crypto.SHA1":                             "crypto",
+	"crypto.SHA224":                           "crypto",
+	"crypto.SHA256":                           "crypto",
+	"crypto.SHA384":                           "crypto",
+	"crypto.SHA512":                           "crypto",
+	"csv.ErrBareQuote":                        "encoding/csv",
+	"csv.ErrFieldCount":                       "encoding/csv",
+	"csv.ErrQuote":                            "encoding/csv",
+	"csv.ErrTrailingComma":                    "encoding/csv",
+	"csv.NewReader":                           "encoding/csv",
+	"csv.NewWriter":                           "encoding/csv",
+	"csv.ParseError":                          "encoding/csv",
+	"csv.Reader":                              "encoding/csv",
+	"csv.Writer":                              "encoding/csv",
+	"debug.FreeOSMemory":                      "runtime/debug",
+	"debug.GCStats":                           "runtime/debug",
+	"debug.PrintStack":                        "runtime/debug",
+	"debug.ReadGCStats":                       "runtime/debug",
+	"debug.SetGCPercent":                      "runtime/debug",
+	"debug.SetMaxStack":                       "runtime/debug",
+	"debug.SetMaxThreads":                     "runtime/debug",
+	"debug.Stack":                             "runtime/debug",
+	"des.BlockSize":                           "crypto/des",
+	"des.KeySizeError":                        "crypto/des",
+	"des.NewCipher":                           "crypto/des",
+	"des.NewTripleDESCipher":                  "crypto/des",
+	"doc.AllDecls":                            "go/doc",
+	"doc.AllMethods":                          "go/doc",
+	"doc.Example":                             "go/doc",
+	"doc.Examples":                            "go/doc",
+	"doc.Filter":                              "go/doc",
+	"doc.Func":                                "go/doc",
+	"doc.IllegalPrefixes":                     "go/doc",
+	"doc.Mode":                                "go/doc",
+	"doc.New":                                 "go/doc",
+	"doc.Note":                                "go/doc",
+	"doc.Package":                             "go/doc",
+	"doc.Synopsis":                            "go/doc",
+	"doc.ToHTML":                              "go/doc",
+	"doc.ToText":                              "go/doc",
+	"doc.Type":                                "go/doc",
+	"doc.Value":                               "go/doc",
+	"draw.Draw":                               "image/draw",
+	"draw.DrawMask":                           "image/draw",
+	"draw.Drawer":                             "image/draw",
+	"draw.FloydSteinberg":                     "image/draw",
+	"draw.Image":                              "image/draw",
+	"draw.Op":                                 "image/draw",
+	"draw.Over":                               "image/draw",
+	"draw.Quantizer":                          "image/draw",
+	"draw.Src":                                "image/draw",
+	"driver.Bool":                             "database/sql/driver",
+	"driver.ColumnConverter":                  "database/sql/driver",
+	"driver.Conn":                             "database/sql/driver",
+	"driver.DefaultParameterConverter":        "database/sql/driver",
+	"driver.Driver":                           "database/sql/driver",
+	"driver.ErrBadConn":                       "database/sql/driver",
+	"driver.ErrSkip":                          "database/sql/driver",
+	"driver.Execer":                           "database/sql/driver",
+	"driver.Int32":                            "database/sql/driver",
+	"driver.IsScanValue":                      "database/sql/driver",
+	"driver.IsValue":                          "database/sql/driver",
+	"driver.NotNull":                          "database/sql/driver",
+	"driver.Null":                             "database/sql/driver",
+	"driver.Queryer":                          "database/sql/driver",
+	"driver.Result":                           "database/sql/driver",
+	"driver.ResultNoRows":                     "database/sql/driver",
+	"driver.Rows":                             "database/sql/driver",
+	"driver.RowsAffected":                     "database/sql/driver",
+	"driver.Stmt":                             "database/sql/driver",
+	"driver.String":                           "database/sql/driver",
+	"driver.Tx":                               "database/sql/driver",
+	"driver.Value":                            "database/sql/driver",
+	"driver.ValueConverter":                   "database/sql/driver",
+	"driver.Valuer":                           "database/sql/driver",
+	"dsa.ErrInvalidPublicKey":                 "crypto/dsa",
+	"dsa.GenerateKey":                         "crypto/dsa",
+	"dsa.GenerateParameters":                  "crypto/dsa",
+	"dsa.L1024N160":                           "crypto/dsa",
+	"dsa.L2048N224":                           "crypto/dsa",
+	"dsa.L2048N256":                           "crypto/dsa",
+	"dsa.L3072N256":                           "crypto/dsa",
+	"dsa.ParameterSizes":                      "crypto/dsa",
+	"dsa.Parameters":                          "crypto/dsa",
+	"dsa.PrivateKey":                          "crypto/dsa",
+	"dsa.PublicKey":                           "crypto/dsa",
+	"dsa.Sign":                                "crypto/dsa",
+	"dsa.Verify":                              "crypto/dsa",
+	"dwarf.AddrType":                          "debug/dwarf",
+	"dwarf.ArrayType":                         "debug/dwarf",
+	"dwarf.Attr":                              "debug/dwarf",
+	"dwarf.AttrAbstractOrigin":                "debug/dwarf",
+	"dwarf.AttrAccessibility":                 "debug/dwarf",
+	"dwarf.AttrAddrClass":                     "debug/dwarf",
+	"dwarf.AttrAllocated":                     "debug/dwarf",
+	"dwarf.AttrArtificial":                    "debug/dwarf",
+	"dwarf.AttrAssociated":                    "debug/dwarf",
+	"dwarf.AttrBaseTypes":                     "debug/dwarf",
+	"dwarf.AttrBitOffset":                     "debug/dwarf",
+	"dwarf.AttrBitSize":                       "debug/dwarf",
+	"dwarf.AttrByteSize":                      "debug/dwarf",
+	"dwarf.AttrCallColumn":                    "debug/dwarf",
+	"dwarf.AttrCallFile":                      "debug/dwarf",
+	"dwarf.AttrCallLine":                      "debug/dwarf",
+	"dwarf.AttrCalling":                       "debug/dwarf",
+	"dwarf.AttrCommonRef":                     "debug/dwarf",
+	"dwarf.AttrCompDir":                       "debug/dwarf",
+	"dwarf.AttrConstValue":                    "debug/dwarf",
+	"dwarf.AttrContainingType":                "debug/dwarf",
+	"dwarf.AttrCount":                         "debug/dwarf",
+	"dwarf.AttrDataLocation":                  "debug/dwarf",
+	"dwarf.AttrDataMemberLoc":                 "debug/dwarf",
+	"dwarf.AttrDeclColumn":                    "debug/dwarf",
+	"dwarf.AttrDeclFile":                      "debug/dwarf",
+	"dwarf.AttrDeclLine":                      "debug/dwarf",
+	"dwarf.AttrDeclaration":                   "debug/dwarf",
+	"dwarf.AttrDefaultValue":                  "debug/dwarf",
+	"dwarf.AttrDescription":                   "debug/dwarf",
+	"dwarf.AttrDiscr":                         "debug/dwarf",
+	"dwarf.AttrDiscrList":                     "debug/dwarf",
+	"dwarf.AttrDiscrValue":                    "debug/dwarf",
+	"dwarf.AttrEncoding":                      "debug/dwarf",
+	"dwarf.AttrEntrypc":                       "debug/dwarf",
+	"dwarf.AttrExtension":                     "debug/dwarf",
+	"dwarf.AttrExternal":                      "debug/dwarf",
+	"dwarf.AttrFrameBase":                     "debug/dwarf",
+	"dwarf.AttrFriend":                        "debug/dwarf",
+	"dwarf.AttrHighpc":                        "debug/dwarf",
+	"dwarf.AttrIdentifierCase":                "debug/dwarf",
+	"dwarf.AttrImport":                        "debug/dwarf",
+	"dwarf.AttrInline":                        "debug/dwarf",
+	"dwarf.AttrIsOptional":                    "debug/dwarf",
+	"dwarf.AttrLanguage":                      "debug/dwarf",
+	"dwarf.AttrLocation":                      "debug/dwarf",
+	"dwarf.AttrLowerBound":                    "debug/dwarf",
+	"dwarf.AttrLowpc":                         "debug/dwarf",
+	"dwarf.AttrMacroInfo":                     "debug/dwarf",
+	"dwarf.AttrName":                          "debug/dwarf",
+	"dwarf.AttrNamelistItem":                  "debug/dwarf",
+	"dwarf.AttrOrdering":                      "debug/dwarf",
+	"dwarf.AttrPriority":                      "debug/dwarf",
+	"dwarf.AttrProducer":                      "debug/dwarf",
+	"dwarf.AttrPrototyped":                    "debug/dwarf",
+	"dwarf.AttrRanges":                        "debug/dwarf",
+	"dwarf.AttrReturnAddr":                    "debug/dwarf",
+	"dwarf.AttrSegment":                       "debug/dwarf",
+	"dwarf.AttrSibling":                       "debug/dwarf",
+	"dwarf.AttrSpecification":                 "debug/dwarf",
+	"dwarf.AttrStartScope":                    "debug/dwarf",
+	"dwarf.AttrStaticLink":                    "debug/dwarf",
+	"dwarf.AttrStmtList":                      "debug/dwarf",
+	"dwarf.AttrStride":                        "debug/dwarf",
+	"dwarf.AttrStrideSize":                    "debug/dwarf",
+	"dwarf.AttrStringLength":                  "debug/dwarf",
+	"dwarf.AttrTrampoline":                    "debug/dwarf",
+	"dwarf.AttrType":                          "debug/dwarf",
+	"dwarf.AttrUpperBound":                    "debug/dwarf",
+	"dwarf.AttrUseLocation":                   "debug/dwarf",
+	"dwarf.AttrUseUTF8":                       "debug/dwarf",
+	"dwarf.AttrVarParam":                      "debug/dwarf",
+	"dwarf.AttrVirtuality":                    "debug/dwarf",
+	"dwarf.AttrVisibility":                    "debug/dwarf",
+	"dwarf.AttrVtableElemLoc":                 "debug/dwarf",
+	"dwarf.BasicType":                         "debug/dwarf",
+	"dwarf.BoolType":                          "debug/dwarf",
+	"dwarf.CharType":                          "debug/dwarf",
+	"dwarf.CommonType":                        "debug/dwarf",
+	"dwarf.ComplexType":                       "debug/dwarf",
+	"dwarf.Data":                              "debug/dwarf",
+	"dwarf.DecodeError":                       "debug/dwarf",
+	"dwarf.DotDotDotType":                     "debug/dwarf",
+	"dwarf.Entry":                             "debug/dwarf",
+	"dwarf.EnumType":                          "debug/dwarf",
+	"dwarf.EnumValue":                         "debug/dwarf",
+	"dwarf.Field":                             "debug/dwarf",
+	"dwarf.FloatType":                         "debug/dwarf",
+	"dwarf.FuncType":                          "debug/dwarf",
+	"dwarf.IntType":                           "debug/dwarf",
+	"dwarf.New":                               "debug/dwarf",
+	"dwarf.Offset":                            "debug/dwarf",
+	"dwarf.PtrType":                           "debug/dwarf",
+	"dwarf.QualType":                          "debug/dwarf",
+	"dwarf.Reader":                            "debug/dwarf",
+	"dwarf.StructField":                       "debug/dwarf",
+	"dwarf.StructType":                        "debug/dwarf",
+	"dwarf.Tag":                               "debug/dwarf",
+	"dwarf.TagAccessDeclaration":              "debug/dwarf",
+	"dwarf.TagArrayType":                      "debug/dwarf",
+	"dwarf.TagBaseType":                       "debug/dwarf",
+	"dwarf.TagCatchDwarfBlock":                "debug/dwarf",
+	"dwarf.TagClassType":                      "debug/dwarf",
+	"dwarf.TagCommonDwarfBlock":               "debug/dwarf",
+	"dwarf.TagCommonInclusion":                "debug/dwarf",
+	"dwarf.TagCompileUnit":                    "debug/dwarf",
+	"dwarf.TagConstType":                      "debug/dwarf",
+	"dwarf.TagConstant":                       "debug/dwarf",
+	"dwarf.TagDwarfProcedure":                 "debug/dwarf",
+	"dwarf.TagEntryPoint":                     "debug/dwarf",
+	"dwarf.TagEnumerationType":                "debug/dwarf",
+	"dwarf.TagEnumerator":                     "debug/dwarf",
+	"dwarf.TagFileType":                       "debug/dwarf",
+	"dwarf.TagFormalParameter":                "debug/dwarf",
+	"dwarf.TagFriend":                         "debug/dwarf",
+	"dwarf.TagImportedDeclaration":            "debug/dwarf",
+	"dwarf.TagImportedModule":                 "debug/dwarf",
+	"dwarf.TagImportedUnit":                   "debug/dwarf",
+	"dwarf.TagInheritance":                    "debug/dwarf",
+	"dwarf.TagInlinedSubroutine":              "debug/dwarf",
+	"dwarf.TagInterfaceType":                  "debug/dwarf",
+	"dwarf.TagLabel":                          "debug/dwarf",
+	"dwarf.TagLexDwarfBlock":                  "debug/dwarf",
+	"dwarf.TagMember":                         "debug/dwarf",
+	"dwarf.TagModule":                         "debug/dwarf",
+	"dwarf.TagMutableType":                    "debug/dwarf",
+	"dwarf.TagNamelist":                       "debug/dwarf",
+	"dwarf.TagNamelistItem":                   "debug/dwarf",
+	"dwarf.TagNamespace":                      "debug/dwarf",
+	"dwarf.TagPackedType":                     "debug/dwarf",
+	"dwarf.TagPartialUnit":                    "debug/dwarf",
+	"dwarf.TagPointerType":                    "debug/dwarf",
+	"dwarf.TagPtrToMemberType":                "debug/dwarf",
+	"dwarf.TagReferenceType":                  "debug/dwarf",
+	"dwarf.TagRestrictType":                   "debug/dwarf",
+	"dwarf.TagSetType":                        "debug/dwarf",
+	"dwarf.TagStringType":                     "debug/dwarf",
+	"dwarf.TagStructType":                     "debug/dwarf",
+	"dwarf.TagSubprogram":                     "debug/dwarf",
+	"dwarf.TagSubrangeType":                   "debug/dwarf",
+	"dwarf.TagSubroutineType":                 "debug/dwarf",
+	"dwarf.TagTemplateTypeParameter":          "debug/dwarf",
+	"dwarf.TagTemplateValueParameter":         "debug/dwarf",
+	"dwarf.TagThrownType":                     "debug/dwarf",
+	"dwarf.TagTryDwarfBlock":                  "debug/dwarf",
+	"dwarf.TagTypedef":                        "debug/dwarf",
+	"dwarf.TagUnionType":                      "debug/dwarf",
+	"dwarf.TagUnspecifiedParameters":          "debug/dwarf",
+	"dwarf.TagUnspecifiedType":                "debug/dwarf",
+	"dwarf.TagVariable":                       "debug/dwarf",
+	"dwarf.TagVariant":                        "debug/dwarf",
+	"dwarf.TagVariantPart":                    "debug/dwarf",
+	"dwarf.TagVolatileType":                   "debug/dwarf",
+	"dwarf.TagWithStmt":                       "debug/dwarf",
+	"dwarf.Type":                              "debug/dwarf",
+	"dwarf.TypedefType":                       "debug/dwarf",
+	"dwarf.UcharType":                         "debug/dwarf",
+	"dwarf.UintType":                          "debug/dwarf",
+	"dwarf.VoidType":                          "debug/dwarf",
+	"ecdsa.GenerateKey":                       "crypto/ecdsa",
+	"ecdsa.PrivateKey":                        "crypto/ecdsa",
+	"ecdsa.PublicKey":                         "crypto/ecdsa",
+	"ecdsa.Sign":                              "crypto/ecdsa",
+	"ecdsa.Verify":                            "crypto/ecdsa",
+	"elf.ARM_MAGIC_TRAMP_NUMBER":              "debug/elf",
+	"elf.Class":                               "debug/elf",
+	"elf.DF_BIND_NOW":                         "debug/elf",
+	"elf.DF_ORIGIN":                           "debug/elf",
+	"elf.DF_STATIC_TLS":                       "debug/elf",
+	"elf.DF_SYMBOLIC":                         "debug/elf",
+	"elf.DF_TEXTREL":                          "debug/elf",
+	"elf.DT_BIND_NOW":                         "debug/elf",
+	"elf.DT_DEBUG":                            "debug/elf",
+	"elf.DT_ENCODING":                         "debug/elf",
+	"elf.DT_FINI":                             "debug/elf",
+	"elf.DT_FINI_ARRAY":                       "debug/elf",
+	"elf.DT_FINI_ARRAYSZ":                     "debug/elf",
+	"elf.DT_FLAGS":                            "debug/elf",
+	"elf.DT_HASH":                             "debug/elf",
+	"elf.DT_HIOS":                             "debug/elf",
+	"elf.DT_HIPROC":                           "debug/elf",
+	"elf.DT_INIT":                             "debug/elf",
+	"elf.DT_INIT_ARRAY":                       "debug/elf",
+	"elf.DT_INIT_ARRAYSZ":                     "debug/elf",
+	"elf.DT_JMPREL":                           "debug/elf",
+	"elf.DT_LOOS":                             "debug/elf",
+	"elf.DT_LOPROC":                           "debug/elf",
+	"elf.DT_NEEDED":                           "debug/elf",
+	"elf.DT_NULL":                             "debug/elf",
+	"elf.DT_PLTGOT":                           "debug/elf",
+	"elf.DT_PLTREL":                           "debug/elf",
+	"elf.DT_PLTRELSZ":                         "debug/elf",
+	"elf.DT_PREINIT_ARRAY":                    "debug/elf",
+	"elf.DT_PREINIT_ARRAYSZ":                  "debug/elf",
+	"elf.DT_REL":                              "debug/elf",
+	"elf.DT_RELA":                             "debug/elf",
+	"elf.DT_RELAENT":                          "debug/elf",
+	"elf.DT_RELASZ":                           "debug/elf",
+	"elf.DT_RELENT":                           "debug/elf",
+	"elf.DT_RELSZ":                            "debug/elf",
+	"elf.DT_RPATH":                            "debug/elf",
+	"elf.DT_RUNPATH":                          "debug/elf",
+	"elf.DT_SONAME":                           "debug/elf",
+	"elf.DT_STRSZ":                            "debug/elf",
+	"elf.DT_STRTAB":                           "debug/elf",
+	"elf.DT_SYMBOLIC":                         "debug/elf",
+	"elf.DT_SYMENT":                           "debug/elf",
+	"elf.DT_SYMTAB":                           "debug/elf",
+	"elf.DT_TEXTREL":                          "debug/elf",
+	"elf.DT_VERNEED":                          "debug/elf",
+	"elf.DT_VERNEEDNUM":                       "debug/elf",
+	"elf.DT_VERSYM":                           "debug/elf",
+	"elf.Data":                                "debug/elf",
+	"elf.Dyn32":                               "debug/elf",
+	"elf.Dyn64":                               "debug/elf",
+	"elf.DynFlag":                             "debug/elf",
+	"elf.DynTag":                              "debug/elf",
+	"elf.EI_ABIVERSION":                       "debug/elf",
+	"elf.EI_CLASS":                            "debug/elf",
+	"elf.EI_DATA":                             "debug/elf",
+	"elf.EI_NIDENT":                           "debug/elf",
+	"elf.EI_OSABI":                            "debug/elf",
+	"elf.EI_PAD":                              "debug/elf",
+	"elf.EI_VERSION":                          "debug/elf",
+	"elf.ELFCLASS32":                          "debug/elf",
+	"elf.ELFCLASS64":                          "debug/elf",
+	"elf.ELFCLASSNONE":                        "debug/elf",
+	"elf.ELFDATA2LSB":                         "debug/elf",
+	"elf.ELFDATA2MSB":                         "debug/elf",
+	"elf.ELFDATANONE":                         "debug/elf",
+	"elf.ELFMAG":                              "debug/elf",
+	"elf.ELFOSABI_86OPEN":                     "debug/elf",
+	"elf.ELFOSABI_AIX":                        "debug/elf",
+	"elf.ELFOSABI_ARM":                        "debug/elf",
+	"elf.ELFOSABI_FREEBSD":                    "debug/elf",
+	"elf.ELFOSABI_HPUX":                       "debug/elf",
+	"elf.ELFOSABI_HURD":                       "debug/elf",
+	"elf.ELFOSABI_IRIX":                       "debug/elf",
+	"elf.ELFOSABI_LINUX":                      "debug/elf",
+	"elf.ELFOSABI_MODESTO":                    "debug/elf",
+	"elf.ELFOSABI_NETBSD":                     "debug/elf",
+	"elf.ELFOSABI_NONE":                       "debug/elf",
+	"elf.ELFOSABI_NSK":                        "debug/elf",
+	"elf.ELFOSABI_OPENBSD":                    "debug/elf",
+	"elf.ELFOSABI_OPENVMS":                    "debug/elf",
+	"elf.ELFOSABI_SOLARIS":                    "debug/elf",
+	"elf.ELFOSABI_STANDALONE":                 "debug/elf",
+	"elf.ELFOSABI_TRU64":                      "debug/elf",
+	"elf.EM_386":                              "debug/elf",
+	"elf.EM_486":                              "debug/elf",
+	"elf.EM_68HC12":                           "debug/elf",
+	"elf.EM_68K":                              "debug/elf",
+	"elf.EM_860":                              "debug/elf",
+	"elf.EM_88K":                              "debug/elf",
+	"elf.EM_960":                              "debug/elf",
+	"elf.EM_ALPHA":                            "debug/elf",
+	"elf.EM_ALPHA_STD":                        "debug/elf",
+	"elf.EM_ARC":                              "debug/elf",
+	"elf.EM_ARM":                              "debug/elf",
+	"elf.EM_COLDFIRE":                         "debug/elf",
+	"elf.EM_FR20":                             "debug/elf",
+	"elf.EM_H8S":                              "debug/elf",
+	"elf.EM_H8_300":                           "debug/elf",
+	"elf.EM_H8_300H":                          "debug/elf",
+	"elf.EM_H8_500":                           "debug/elf",
+	"elf.EM_IA_64":                            "debug/elf",
+	"elf.EM_M32":                              "debug/elf",
+	"elf.EM_ME16":                             "debug/elf",
+	"elf.EM_MIPS":                             "debug/elf",
+	"elf.EM_MIPS_RS3_LE":                      "debug/elf",
+	"elf.EM_MIPS_RS4_BE":                      "debug/elf",
+	"elf.EM_MIPS_X":                           "debug/elf",
+	"elf.EM_MMA":                              "debug/elf",
+	"elf.EM_NCPU":                             "debug/elf",
+	"elf.EM_NDR1":                             "debug/elf",
+	"elf.EM_NONE":                             "debug/elf",
+	"elf.EM_PARISC":                           "debug/elf",
+	"elf.EM_PCP":                              "debug/elf",
+	"elf.EM_PPC":                              "debug/elf",
+	"elf.EM_PPC64":                            "debug/elf",
+	"elf.EM_RCE":                              "debug/elf",
+	"elf.EM_RH32":                             "debug/elf",
+	"elf.EM_S370":                             "debug/elf",
+	"elf.EM_S390":                             "debug/elf",
+	"elf.EM_SH":                               "debug/elf",
+	"elf.EM_SPARC":                            "debug/elf",
+	"elf.EM_SPARC32PLUS":                      "debug/elf",
+	"elf.EM_SPARCV9":                          "debug/elf",
+	"elf.EM_ST100":                            "debug/elf",
+	"elf.EM_STARCORE":                         "debug/elf",
+	"elf.EM_TINYJ":                            "debug/elf",
+	"elf.EM_TRICORE":                          "debug/elf",
+	"elf.EM_V800":                             "debug/elf",
+	"elf.EM_VPP500":                           "debug/elf",
+	"elf.EM_X86_64":                           "debug/elf",
+	"elf.ET_CORE":                             "debug/elf",
+	"elf.ET_DYN":                              "debug/elf",
+	"elf.ET_EXEC":                             "debug/elf",
+	"elf.ET_HIOS":                             "debug/elf",
+	"elf.ET_HIPROC":                           "debug/elf",
+	"elf.ET_LOOS":                             "debug/elf",
+	"elf.ET_LOPROC":                           "debug/elf",
+	"elf.ET_NONE":                             "debug/elf",
+	"elf.ET_REL":                              "debug/elf",
+	"elf.EV_CURRENT":                          "debug/elf",
+	"elf.EV_NONE":                             "debug/elf",
+	"elf.File":                                "debug/elf",
+	"elf.FileHeader":                          "debug/elf",
+	"elf.FormatError":                         "debug/elf",
+	"elf.Header32":                            "debug/elf",
+	"elf.Header64":                            "debug/elf",
+	"elf.ImportedSymbol":                      "debug/elf",
+	"elf.Machine":                             "debug/elf",
+	"elf.NT_FPREGSET":                         "debug/elf",
+	"elf.NT_PRPSINFO":                         "debug/elf",
+	"elf.NT_PRSTATUS":                         "debug/elf",
+	"elf.NType":                               "debug/elf",
+	"elf.NewFile":                             "debug/elf",
+	"elf.OSABI":                               "debug/elf",
+	"elf.Open":                                "debug/elf",
+	"elf.PF_MASKOS":                           "debug/elf",
+	"elf.PF_MASKPROC":                         "debug/elf",
+	"elf.PF_R":                                "debug/elf",
+	"elf.PF_W":                                "debug/elf",
+	"elf.PF_X":                                "debug/elf",
+	"elf.PT_DYNAMIC":                          "debug/elf",
+	"elf.PT_HIOS":                             "debug/elf",
+	"elf.PT_HIPROC":                           "debug/elf",
+	"elf.PT_INTERP":                           "debug/elf",
+	"elf.PT_LOAD":                             "debug/elf",
+	"elf.PT_LOOS":                             "debug/elf",
+	"elf.PT_LOPROC":                           "debug/elf",
+	"elf.PT_NOTE":                             "debug/elf",
+	"elf.PT_NULL":                             "debug/elf",
+	"elf.PT_PHDR":                             "debug/elf",
+	"elf.PT_SHLIB":                            "debug/elf",
+	"elf.PT_TLS":                              "debug/elf",
+	"elf.Prog":                                "debug/elf",
+	"elf.Prog32":                              "debug/elf",
+	"elf.Prog64":                              "debug/elf",
+	"elf.ProgFlag":                            "debug/elf",
+	"elf.ProgHeader":                          "debug/elf",
+	"elf.ProgType":                            "debug/elf",
+	"elf.R_386":                               "debug/elf",
+	"elf.R_386_32":                            "debug/elf",
+	"elf.R_386_COPY":                          "debug/elf",
+	"elf.R_386_GLOB_DAT":                      "debug/elf",
+	"elf.R_386_GOT32":                         "debug/elf",
+	"elf.R_386_GOTOFF":                        "debug/elf",
+	"elf.R_386_GOTPC":                         "debug/elf",
+	"elf.R_386_JMP_SLOT":                      "debug/elf",
+	"elf.R_386_NONE":                          "debug/elf",
+	"elf.R_386_PC32":                          "debug/elf",
+	"elf.R_386_PLT32":                         "debug/elf",
+	"elf.R_386_RELATIVE":                      "debug/elf",
+	"elf.R_386_TLS_DTPMOD32":                  "debug/elf",
+	"elf.R_386_TLS_DTPOFF32":                  "debug/elf",
+	"elf.R_386_TLS_GD":                        "debug/elf",
+	"elf.R_386_TLS_GD_32":                     "debug/elf",
+	"elf.R_386_TLS_GD_CALL":                   "debug/elf",
+	"elf.R_386_TLS_GD_POP":                    "debug/elf",
+	"elf.R_386_TLS_GD_PUSH":                   "debug/elf",
+	"elf.R_386_TLS_GOTIE":                     "debug/elf",
+	"elf.R_386_TLS_IE":                        "debug/elf",
+	"elf.R_386_TLS_IE_32":                     "debug/elf",
+	"elf.R_386_TLS_LDM":                       "debug/elf",
+	"elf.R_386_TLS_LDM_32":                    "debug/elf",
+	"elf.R_386_TLS_LDM_CALL":                  "debug/elf",
+	"elf.R_386_TLS_LDM_POP":                   "debug/elf",
+	"elf.R_386_TLS_LDM_PUSH":                  "debug/elf",
+	"elf.R_386_TLS_LDO_32":                    "debug/elf",
+	"elf.R_386_TLS_LE":                        "debug/elf",
+	"elf.R_386_TLS_LE_32":                     "debug/elf",
+	"elf.R_386_TLS_TPOFF":                     "debug/elf",
+	"elf.R_386_TLS_TPOFF32":                   "debug/elf",
+	"elf.R_ALPHA":                             "debug/elf",
+	"elf.R_ALPHA_BRADDR":                      "debug/elf",
+	"elf.R_ALPHA_COPY":                        "debug/elf",
+	"elf.R_ALPHA_GLOB_DAT":                    "debug/elf",
+	"elf.R_ALPHA_GPDISP":                      "debug/elf",
+	"elf.R_ALPHA_GPREL32":                     "debug/elf",
+	"elf.R_ALPHA_GPRELHIGH":                   "debug/elf",
+	"elf.R_ALPHA_GPRELLOW":                    "debug/elf",
+	"elf.R_ALPHA_GPVALUE":                     "debug/elf",
+	"elf.R_ALPHA_HINT":                        "debug/elf",
+	"elf.R_ALPHA_IMMED_BR_HI32":               "debug/elf",
+	"elf.R_ALPHA_IMMED_GP_16":                 "debug/elf",
+	"elf.R_ALPHA_IMMED_GP_HI32":               "debug/elf",
+	"elf.R_ALPHA_IMMED_LO32":                  "debug/elf",
+	"elf.R_ALPHA_IMMED_SCN_HI32":              "debug/elf",
+	"elf.R_ALPHA_JMP_SLOT":                    "debug/elf",
+	"elf.R_ALPHA_LITERAL":                     "debug/elf",
+	"elf.R_ALPHA_LITUSE":                      "debug/elf",
+	"elf.R_ALPHA_NONE":                        "debug/elf",
+	"elf.R_ALPHA_OP_PRSHIFT":                  "debug/elf",
+	"elf.R_ALPHA_OP_PSUB":                     "debug/elf",
+	"elf.R_ALPHA_OP_PUSH":                     "debug/elf",
+	"elf.R_ALPHA_OP_STORE":                    "debug/elf",
+	"elf.R_ALPHA_REFLONG":                     "debug/elf",
+	"elf.R_ALPHA_REFQUAD":                     "debug/elf",
+	"elf.R_ALPHA_RELATIVE":                    "debug/elf",
+	"elf.R_ALPHA_SREL16":                      "debug/elf",
+	"elf.R_ALPHA_SREL32":                      "debug/elf",
+	"elf.R_ALPHA_SREL64":                      "debug/elf",
+	"elf.R_ARM":                               "debug/elf",
+	"elf.R_ARM_ABS12":                         "debug/elf",
+	"elf.R_ARM_ABS16":                         "debug/elf",
+	"elf.R_ARM_ABS32":                         "debug/elf",
+	"elf.R_ARM_ABS8":                          "debug/elf",
+	"elf.R_ARM_AMP_VCALL9":                    "debug/elf",
+	"elf.R_ARM_COPY":                          "debug/elf",
+	"elf.R_ARM_GLOB_DAT":                      "debug/elf",
+	"elf.R_ARM_GNU_VTENTRY":                   "debug/elf",
+	"elf.R_ARM_GNU_VTINHERIT":                 "debug/elf",
+	"elf.R_ARM_GOT32":                         "debug/elf",
+	"elf.R_ARM_GOTOFF":                        "debug/elf",
+	"elf.R_ARM_GOTPC":                         "debug/elf",
+	"elf.R_ARM_JUMP_SLOT":                     "debug/elf",
+	"elf.R_ARM_NONE":                          "debug/elf",
+	"elf.R_ARM_PC13":                          "debug/elf",
+	"elf.R_ARM_PC24":                          "debug/elf",
+	"elf.R_ARM_PLT32":                         "debug/elf",
+	"elf.R_ARM_RABS32":                        "debug/elf",
+	"elf.R_ARM_RBASE":                         "debug/elf",
+	"elf.R_ARM_REL32":                         "debug/elf",
+	"elf.R_ARM_RELATIVE":                      "debug/elf",
+	"elf.R_ARM_RPC24":                         "debug/elf",
+	"elf.R_ARM_RREL32":                        "debug/elf",
+	"elf.R_ARM_RSBREL32":                      "debug/elf",
+	"elf.R_ARM_SBREL32":                       "debug/elf",
+	"elf.R_ARM_SWI24":                         "debug/elf",
+	"elf.R_ARM_THM_ABS5":                      "debug/elf",
+	"elf.R_ARM_THM_PC22":                      "debug/elf",
+	"elf.R_ARM_THM_PC8":                       "debug/elf",
+	"elf.R_ARM_THM_RPC22":                     "debug/elf",
+	"elf.R_ARM_THM_SWI8":                      "debug/elf",
+	"elf.R_ARM_THM_XPC22":                     "debug/elf",
+	"elf.R_ARM_XPC25":                         "debug/elf",
+	"elf.R_INFO":                              "debug/elf",
+	"elf.R_INFO32":                            "debug/elf",
+	"elf.R_PPC":                               "debug/elf",
+	"elf.R_PPC_ADDR14":                        "debug/elf",
+	"elf.R_PPC_ADDR14_BRNTAKEN":               "debug/elf",
+	"elf.R_PPC_ADDR14_BRTAKEN":                "debug/elf",
+	"elf.R_PPC_ADDR16":                        "debug/elf",
+	"elf.R_PPC_ADDR16_HA":                     "debug/elf",
+	"elf.R_PPC_ADDR16_HI":                     "debug/elf",
+	"elf.R_PPC_ADDR16_LO":                     "debug/elf",
+	"elf.R_PPC_ADDR24":                        "debug/elf",
+	"elf.R_PPC_ADDR32":                        "debug/elf",
+	"elf.R_PPC_COPY":                          "debug/elf",
+	"elf.R_PPC_DTPMOD32":                      "debug/elf",
+	"elf.R_PPC_DTPREL16":                      "debug/elf",
+	"elf.R_PPC_DTPREL16_HA":                   "debug/elf",
+	"elf.R_PPC_DTPREL16_HI":                   "debug/elf",
+	"elf.R_PPC_DTPREL16_LO":                   "debug/elf",
+	"elf.R_PPC_DTPREL32":                      "debug/elf",
+	"elf.R_PPC_EMB_BIT_FLD":                   "debug/elf",
+	"elf.R_PPC_EMB_MRKREF":                    "debug/elf",
+	"elf.R_PPC_EMB_NADDR16":                   "debug/elf",
+	"elf.R_PPC_EMB_NADDR16_HA":                "debug/elf",
+	"elf.R_PPC_EMB_NADDR16_HI":                "debug/elf",
+	"elf.R_PPC_EMB_NADDR16_LO":                "debug/elf",
+	"elf.R_PPC_EMB_NADDR32":                   "debug/elf",
+	"elf.R_PPC_EMB_RELSDA":                    "debug/elf",
+	"elf.R_PPC_EMB_RELSEC16":                  "debug/elf",
+	"elf.R_PPC_EMB_RELST_HA":                  "debug/elf",
+	"elf.R_PPC_EMB_RELST_HI":                  "debug/elf",
+	"elf.R_PPC_EMB_RELST_LO":                  "debug/elf",
+	"elf.R_PPC_EMB_SDA21":                     "debug/elf",
+	"elf.R_PPC_EMB_SDA2I16":                   "debug/elf",
+	"elf.R_PPC_EMB_SDA2REL":                   "debug/elf",
+	"elf.R_PPC_EMB_SDAI16":                    "debug/elf",
+	"elf.R_PPC_GLOB_DAT":                      "debug/elf",
+	"elf.R_PPC_GOT16":                         "debug/elf",
+	"elf.R_PPC_GOT16_HA":                      "debug/elf",
+	"elf.R_PPC_GOT16_HI":                      "debug/elf",
+	"elf.R_PPC_GOT16_LO":                      "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16":                   "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16_HA":                "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16_HI":                "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16_LO":                "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16":                   "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16_HA":                "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16_HI":                "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16_LO":                "debug/elf",
+	"elf.R_PPC_GOT_TPREL16":                   "debug/elf",
+	"elf.R_PPC_GOT_TPREL16_HA":                "debug/elf",
+	"elf.R_PPC_GOT_TPREL16_HI":                "debug/elf",
+	"elf.R_PPC_GOT_TPREL16_LO":                "debug/elf",
+	"elf.R_PPC_JMP_SLOT":                      "debug/elf",
+	"elf.R_PPC_LOCAL24PC":                     "debug/elf",
+	"elf.R_PPC_NONE":                          "debug/elf",
+	"elf.R_PPC_PLT16_HA":                      "debug/elf",
+	"elf.R_PPC_PLT16_HI":                      "debug/elf",
+	"elf.R_PPC_PLT16_LO":                      "debug/elf",
+	"elf.R_PPC_PLT32":                         "debug/elf",
+	"elf.R_PPC_PLTREL24":                      "debug/elf",
+	"elf.R_PPC_PLTREL32":                      "debug/elf",
+	"elf.R_PPC_REL14":                         "debug/elf",
+	"elf.R_PPC_REL14_BRNTAKEN":                "debug/elf",
+	"elf.R_PPC_REL14_BRTAKEN":                 "debug/elf",
+	"elf.R_PPC_REL24":                         "debug/elf",
+	"elf.R_PPC_REL32":                         "debug/elf",
+	"elf.R_PPC_RELATIVE":                      "debug/elf",
+	"elf.R_PPC_SDAREL16":                      "debug/elf",
+	"elf.R_PPC_SECTOFF":                       "debug/elf",
+	"elf.R_PPC_SECTOFF_HA":                    "debug/elf",
+	"elf.R_PPC_SECTOFF_HI":                    "debug/elf",
+	"elf.R_PPC_SECTOFF_LO":                    "debug/elf",
+	"elf.R_PPC_TLS":                           "debug/elf",
+	"elf.R_PPC_TPREL16":                       "debug/elf",
+	"elf.R_PPC_TPREL16_HA":                    "debug/elf",
+	"elf.R_PPC_TPREL16_HI":                    "debug/elf",
+	"elf.R_PPC_TPREL16_LO":                    "debug/elf",
+	"elf.R_PPC_TPREL32":                       "debug/elf",
+	"elf.R_PPC_UADDR16":                       "debug/elf",
+	"elf.R_PPC_UADDR32":                       "debug/elf",
+	"elf.R_SPARC":                             "debug/elf",
+	"elf.R_SPARC_10":                          "debug/elf",
+	"elf.R_SPARC_11":                          "debug/elf",
+	"elf.R_SPARC_13":                          "debug/elf",
+	"elf.R_SPARC_16":                          "debug/elf",
+	"elf.R_SPARC_22":                          "debug/elf",
+	"elf.R_SPARC_32":                          "debug/elf",
+	"elf.R_SPARC_5":                           "debug/elf",
+	"elf.R_SPARC_6":                           "debug/elf",
+	"elf.R_SPARC_64":                          "debug/elf",
+	"elf.R_SPARC_7":                           "debug/elf",
+	"elf.R_SPARC_8":                           "debug/elf",
+	"elf.R_SPARC_COPY":                        "debug/elf",
+	"elf.R_SPARC_DISP16":                      "debug/elf",
+	"elf.R_SPARC_DISP32":                      "debug/elf",
+	"elf.R_SPARC_DISP64":                      "debug/elf",
+	"elf.R_SPARC_DISP8":                       "debug/elf",
+	"elf.R_SPARC_GLOB_DAT":                    "debug/elf",
+	"elf.R_SPARC_GLOB_JMP":                    "debug/elf",
+	"elf.R_SPARC_GOT10":                       "debug/elf",
+	"elf.R_SPARC_GOT13":                       "debug/elf",
+	"elf.R_SPARC_GOT22":                       "debug/elf",
+	"elf.R_SPARC_H44":                         "debug/elf",
+	"elf.R_SPARC_HH22":                        "debug/elf",
+	"elf.R_SPARC_HI22":                        "debug/elf",
+	"elf.R_SPARC_HIPLT22":                     "debug/elf",
+	"elf.R_SPARC_HIX22":                       "debug/elf",
+	"elf.R_SPARC_HM10":                        "debug/elf",
+	"elf.R_SPARC_JMP_SLOT":                    "debug/elf",
+	"elf.R_SPARC_L44":                         "debug/elf",
+	"elf.R_SPARC_LM22":                        "debug/elf",
+	"elf.R_SPARC_LO10":                        "debug/elf",
+	"elf.R_SPARC_LOPLT10":                     "debug/elf",
+	"elf.R_SPARC_LOX10":                       "debug/elf",
+	"elf.R_SPARC_M44":                         "debug/elf",
+	"elf.R_SPARC_NONE":                        "debug/elf",
+	"elf.R_SPARC_OLO10":                       "debug/elf",
+	"elf.R_SPARC_PC10":                        "debug/elf",
+	"elf.R_SPARC_PC22":                        "debug/elf",
+	"elf.R_SPARC_PCPLT10":                     "debug/elf",
+	"elf.R_SPARC_PCPLT22":                     "debug/elf",
+	"elf.R_SPARC_PCPLT32":                     "debug/elf",
+	"elf.R_SPARC_PC_HH22":                     "debug/elf",
+	"elf.R_SPARC_PC_HM10":                     "debug/elf",
+	"elf.R_SPARC_PC_LM22":                     "debug/elf",
+	"elf.R_SPARC_PLT32":                       "debug/elf",
+	"elf.R_SPARC_PLT64":                       "debug/elf",
+	"elf.R_SPARC_REGISTER":                    "debug/elf",
+	"elf.R_SPARC_RELATIVE":                    "debug/elf",
+	"elf.R_SPARC_UA16":                        "debug/elf",
+	"elf.R_SPARC_UA32":                        "debug/elf",
+	"elf.R_SPARC_UA64":                        "debug/elf",
+	"elf.R_SPARC_WDISP16":                     "debug/elf",
+	"elf.R_SPARC_WDISP19":                     "debug/elf",
+	"elf.R_SPARC_WDISP22":                     "debug/elf",
+	"elf.R_SPARC_WDISP30":                     "debug/elf",
+	"elf.R_SPARC_WPLT30":                      "debug/elf",
+	"elf.R_SYM32":                             "debug/elf",
+	"elf.R_SYM64":                             "debug/elf",
+	"elf.R_TYPE32":                            "debug/elf",
+	"elf.R_TYPE64":                            "debug/elf",
+	"elf.R_X86_64":                            "debug/elf",
+	"elf.R_X86_64_16":                         "debug/elf",
+	"elf.R_X86_64_32":                         "debug/elf",
+	"elf.R_X86_64_32S":                        "debug/elf",
+	"elf.R_X86_64_64":                         "debug/elf",
+	"elf.R_X86_64_8":                          "debug/elf",
+	"elf.R_X86_64_COPY":                       "debug/elf",
+	"elf.R_X86_64_DTPMOD64":                   "debug/elf",
+	"elf.R_X86_64_DTPOFF32":                   "debug/elf",
+	"elf.R_X86_64_DTPOFF64":                   "debug/elf",
+	"elf.R_X86_64_GLOB_DAT":                   "debug/elf",
+	"elf.R_X86_64_GOT32":                      "debug/elf",
+	"elf.R_X86_64_GOTPCREL":                   "debug/elf",
+	"elf.R_X86_64_GOTTPOFF":                   "debug/elf",
+	"elf.R_X86_64_JMP_SLOT":                   "debug/elf",
+	"elf.R_X86_64_NONE":                       "debug/elf",
+	"elf.R_X86_64_PC16":                       "debug/elf",
+	"elf.R_X86_64_PC32":                       "debug/elf",
+	"elf.R_X86_64_PC8":                        "debug/elf",
+	"elf.R_X86_64_PLT32":                      "debug/elf",
+	"elf.R_X86_64_RELATIVE":                   "debug/elf",
+	"elf.R_X86_64_TLSGD":                      "debug/elf",
+	"elf.R_X86_64_TLSLD":                      "debug/elf",
+	"elf.R_X86_64_TPOFF32":                    "debug/elf",
+	"elf.R_X86_64_TPOFF64":                    "debug/elf",
+	"elf.Rel32":                               "debug/elf",
+	"elf.Rel64":                               "debug/elf",
+	"elf.Rela32":                              "debug/elf",
+	"elf.Rela64":                              "debug/elf",
+	"elf.SHF_ALLOC":                           "debug/elf",
+	"elf.SHF_EXECINSTR":                       "debug/elf",
+	"elf.SHF_GROUP":                           "debug/elf",
+	"elf.SHF_INFO_LINK":                       "debug/elf",
+	"elf.SHF_LINK_ORDER":                      "debug/elf",
+	"elf.SHF_MASKOS":                          "debug/elf",
+	"elf.SHF_MASKPROC":                        "debug/elf",
+	"elf.SHF_MERGE":                           "debug/elf",
+	"elf.SHF_OS_NONCONFORMING":                "debug/elf",
+	"elf.SHF_STRINGS":                         "debug/elf",
+	"elf.SHF_TLS":                             "debug/elf",
+	"elf.SHF_WRITE":                           "debug/elf",
+	"elf.SHN_ABS":                             "debug/elf",
+	"elf.SHN_COMMON":                          "debug/elf",
+	"elf.SHN_HIOS":                            "debug/elf",
+	"elf.SHN_HIPROC":                          "debug/elf",
+	"elf.SHN_HIRESERVE":                       "debug/elf",
+	"elf.SHN_LOOS":                            "debug/elf",
+	"elf.SHN_LOPROC":                          "debug/elf",
+	"elf.SHN_LORESERVE":                       "debug/elf",
+	"elf.SHN_UNDEF":                           "debug/elf",
+	"elf.SHN_XINDEX":                          "debug/elf",
+	"elf.SHT_DYNAMIC":                         "debug/elf",
+	"elf.SHT_DYNSYM":                          "debug/elf",
+	"elf.SHT_FINI_ARRAY":                      "debug/elf",
+	"elf.SHT_GNU_ATTRIBUTES":                  "debug/elf",
+	"elf.SHT_GNU_HASH":                        "debug/elf",
+	"elf.SHT_GNU_LIBLIST":                     "debug/elf",
+	"elf.SHT_GNU_VERDEF":                      "debug/elf",
+	"elf.SHT_GNU_VERNEED":                     "debug/elf",
+	"elf.SHT_GNU_VERSYM":                      "debug/elf",
+	"elf.SHT_GROUP":                           "debug/elf",
+	"elf.SHT_HASH":                            "debug/elf",
+	"elf.SHT_HIOS":                            "debug/elf",
+	"elf.SHT_HIPROC":                          "debug/elf",
+	"elf.SHT_HIUSER":                          "debug/elf",
+	"elf.SHT_INIT_ARRAY":                      "debug/elf",
+	"elf.SHT_LOOS":                            "debug/elf",
+	"elf.SHT_LOPROC":                          "debug/elf",
+	"elf.SHT_LOUSER":                          "debug/elf",
+	"elf.SHT_NOBITS":                          "debug/elf",
+	"elf.SHT_NOTE":                            "debug/elf",
+	"elf.SHT_NULL":                            "debug/elf",
+	"elf.SHT_PREINIT_ARRAY":                   "debug/elf",
+	"elf.SHT_PROGBITS":                        "debug/elf",
+	"elf.SHT_REL":                             "debug/elf",
+	"elf.SHT_RELA":                            "debug/elf",
+	"elf.SHT_SHLIB":                           "debug/elf",
+	"elf.SHT_STRTAB":                          "debug/elf",
+	"elf.SHT_SYMTAB":                          "debug/elf",
+	"elf.SHT_SYMTAB_SHNDX":                    "debug/elf",
+	"elf.STB_GLOBAL":                          "debug/elf",
+	"elf.STB_HIOS":                            "debug/elf",
+	"elf.STB_HIPROC":                          "debug/elf",
+	"elf.STB_LOCAL":                           "debug/elf",
+	"elf.STB_LOOS":                            "debug/elf",
+	"elf.STB_LOPROC":                          "debug/elf",
+	"elf.STB_WEAK":                            "debug/elf",
+	"elf.STT_COMMON":                          "debug/elf",
+	"elf.STT_FILE":                            "debug/elf",
+	"elf.STT_FUNC":                            "debug/elf",
+	"elf.STT_HIOS":                            "debug/elf",
+	"elf.STT_HIPROC":                          "debug/elf",
+	"elf.STT_LOOS":                            "debug/elf",
+	"elf.STT_LOPROC":                          "debug/elf",
+	"elf.STT_NOTYPE":                          "debug/elf",
+	"elf.STT_OBJECT":                          "debug/elf",
+	"elf.STT_SECTION":                         "debug/elf",
+	"elf.STT_TLS":                             "debug/elf",
+	"elf.STV_DEFAULT":                         "debug/elf",
+	"elf.STV_HIDDEN":                          "debug/elf",
+	"elf.STV_INTERNAL":                        "debug/elf",
+	"elf.STV_PROTECTED":                       "debug/elf",
+	"elf.ST_BIND":                             "debug/elf",
+	"elf.ST_INFO":                             "debug/elf",
+	"elf.ST_TYPE":                             "debug/elf",
+	"elf.ST_VISIBILITY":                       "debug/elf",
+	"elf.Section":                             "debug/elf",
+	"elf.Section32":                           "debug/elf",
+	"elf.Section64":                           "debug/elf",
+	"elf.SectionFlag":                         "debug/elf",
+	"elf.SectionHeader":                       "debug/elf",
+	"elf.SectionIndex":                        "debug/elf",
+	"elf.SectionType":                         "debug/elf",
+	"elf.Sym32":                               "debug/elf",
+	"elf.Sym32Size":                           "debug/elf",
+	"elf.Sym64":                               "debug/elf",
+	"elf.Sym64Size":                           "debug/elf",
+	"elf.SymBind":                             "debug/elf",
+	"elf.SymType":                             "debug/elf",
+	"elf.SymVis":                              "debug/elf",
+	"elf.Symbol":                              "debug/elf",
+	"elf.Type":                                "debug/elf",
+	"elf.Version":                             "debug/elf",
+	"elliptic.Curve":                          "crypto/elliptic",
+	"elliptic.CurveParams":                    "crypto/elliptic",
+	"elliptic.GenerateKey":                    "crypto/elliptic",
+	"elliptic.Marshal":                        "crypto/elliptic",
+	"elliptic.P224":                           "crypto/elliptic",
+	"elliptic.P256":                           "crypto/elliptic",
+	"elliptic.P384":                           "crypto/elliptic",
+	"elliptic.P521":                           "crypto/elliptic",
+	"elliptic.Unmarshal":                      "crypto/elliptic",
+	"encoding.BinaryMarshaler":                "encoding",
+	"encoding.BinaryUnmarshaler":              "encoding",
+	"encoding.TextMarshaler":                  "encoding",
+	"encoding.TextUnmarshaler":                "encoding",
+	"errors.New":                              "errors",
+	"exec.Cmd":                                "os/exec",
+	"exec.Command":                            "os/exec",
+	"exec.ErrNotFound":                        "os/exec",
+	"exec.Error":                              "os/exec",
+	"exec.ExitError":                          "os/exec",
+	"exec.LookPath":                           "os/exec",
+	"expvar.Do":                               "expvar",
+	"expvar.Float":                            "expvar",
+	"expvar.Func":                             "expvar",
+	"expvar.Get":                              "expvar",
+	"expvar.Int":                              "expvar",
+	"expvar.KeyValue":                         "expvar",
+	"expvar.Map":                              "expvar",
+	"expvar.NewFloat":                         "expvar",
+	"expvar.NewInt":                           "expvar",
+	"expvar.NewMap":                           "expvar",
+	"expvar.NewString":                        "expvar",
+	"expvar.Publish":                          "expvar",
+	"expvar.String":                           "expvar",
+	"expvar.Var":                              "expvar",
+	"fcgi.Serve":                              "net/http/fcgi",
+	"filepath.Abs":                            "path/filepath",
+	"filepath.Base":                           "path/filepath",
+	"filepath.Clean":                          "path/filepath",
+	"filepath.Dir":                            "path/filepath",
+	"filepath.ErrBadPattern":                  "path/filepath",
+	"filepath.EvalSymlinks":                   "path/filepath",
+	"filepath.Ext":                            "path/filepath",
+	"filepath.FromSlash":                      "path/filepath",
+	"filepath.Glob":                           "path/filepath",
+	"filepath.HasPrefix":                      "path/filepath",
+	"filepath.IsAbs":                          "path/filepath",
+	"filepath.Join":                           "path/filepath",
+	"filepath.ListSeparator":                  "path/filepath",
+	"filepath.Match":                          "path/filepath",
+	"filepath.Rel":                            "path/filepath",
+	"filepath.Separator":                      "path/filepath",
+	"filepath.SkipDir":                        "path/filepath",
+	"filepath.Split":                          "path/filepath",
+	"filepath.SplitList":                      "path/filepath",
+	"filepath.ToSlash":                        "path/filepath",
+	"filepath.VolumeName":                     "path/filepath",
+	"filepath.Walk":                           "path/filepath",
+	"filepath.WalkFunc":                       "path/filepath",
+	"flag.Arg":                                "flag",
+	"flag.Args":                               "flag",
+	"flag.Bool":                               "flag",
+	"flag.BoolVar":                            "flag",
+	"flag.CommandLine":                        "flag",
+	"flag.ContinueOnError":                    "flag",
+	"flag.Duration":                           "flag",
+	"flag.DurationVar":                        "flag",
+	"flag.ErrHelp":                            "flag",
+	"flag.ErrorHandling":                      "flag",
+	"flag.ExitOnError":                        "flag",
+	"flag.Flag":                               "flag",
+	"flag.FlagSet":                            "flag",
+	"flag.Float64":                            "flag",
+	"flag.Float64Var":                         "flag",
+	"flag.Getter":                             "flag",
+	"flag.Int":                                "flag",
+	"flag.Int64":                              "flag",
+	"flag.Int64Var":                           "flag",
+	"flag.IntVar":                             "flag",
+	"flag.Lookup":                             "flag",
+	"flag.NArg":                               "flag",
+	"flag.NFlag":                              "flag",
+	"flag.NewFlagSet":                         "flag",
+	"flag.PanicOnError":                       "flag",
+	"flag.Parse":                              "flag",
+	"flag.Parsed":                             "flag",
+	"flag.PrintDefaults":                      "flag",
+	"flag.Set":                                "flag",
+	"flag.String":                             "flag",
+	"flag.StringVar":                          "flag",
+	"flag.Uint":                               "flag",
+	"flag.Uint64":                             "flag",
+	"flag.Uint64Var":                          "flag",
+	"flag.UintVar":                            "flag",
+	"flag.Usage":                              "flag",
+	"flag.Value":                              "flag",
+	"flag.Var":                                "flag",
+	"flag.Visit":                              "flag",
+	"flag.VisitAll":                           "flag",
+	"flate.BestCompression":                   "compress/flate",
+	"flate.BestSpeed":                         "compress/flate",
+	"flate.CorruptInputError":                 "compress/flate",
+	"flate.DefaultCompression":                "compress/flate",
+	"flate.InternalError":                     "compress/flate",
+	"flate.NewReader":                         "compress/flate",
+	"flate.NewReaderDict":                     "compress/flate",
+	"flate.NewWriter":                         "compress/flate",
+	"flate.NewWriterDict":                     "compress/flate",
+	"flate.NoCompression":                     "compress/flate",
+	"flate.ReadError":                         "compress/flate",
+	"flate.Reader":                            "compress/flate",
+	"flate.WriteError":                        "compress/flate",
+	"flate.Writer":                            "compress/flate",
+	"fmt.Errorf":                              "fmt",
+	"fmt.Formatter":                           "fmt",
+	"fmt.Fprint":                              "fmt",
+	"fmt.Fprintf":                             "fmt",
+	"fmt.Fprintln":                            "fmt",
+	"fmt.Fscan":                               "fmt",
+	"fmt.Fscanf":                              "fmt",
+	"fmt.Fscanln":                             "fmt",
+	"fmt.GoStringer":                          "fmt",
+	"fmt.Print":                               "fmt",
+	"fmt.Printf":                              "fmt",
+	"fmt.Println":                             "fmt",
+	"fmt.Scan":                                "fmt",
+	"fmt.ScanState":                           "fmt",
+	"fmt.Scanf":                               "fmt",
+	"fmt.Scanln":                              "fmt",
+	"fmt.Scanner":                             "fmt",
+	"fmt.Sprint":                              "fmt",
+	"fmt.Sprintf":                             "fmt",
+	"fmt.Sprintln":                            "fmt",
+	"fmt.Sscan":                               "fmt",
+	"fmt.Sscanf":                              "fmt",
+	"fmt.Sscanln":                             "fmt",
+	"fmt.State":                               "fmt",
+	"fmt.Stringer":                            "fmt",
+	"fnv.New32":                               "hash/fnv",
+	"fnv.New32a":                              "hash/fnv",
+	"fnv.New64":                               "hash/fnv",
+	"fnv.New64a":                              "hash/fnv",
+	"format.Node":                             "go/format",
+	"format.Source":                           "go/format",
+	"gif.Decode":                              "image/gif",
+	"gif.DecodeAll":                           "image/gif",
+	"gif.DecodeConfig":                        "image/gif",
+	"gif.Encode":                              "image/gif",
+	"gif.EncodeAll":                           "image/gif",
+	"gif.GIF":                                 "image/gif",
+	"gif.Options":                             "image/gif",
+	"gob.CommonType":                          "encoding/gob",
+	"gob.Decoder":                             "encoding/gob",
+	"gob.Encoder":                             "encoding/gob",
+	"gob.GobDecoder":                          "encoding/gob",
+	"gob.GobEncoder":                          "encoding/gob",
+	"gob.NewDecoder":                          "encoding/gob",
+	"gob.NewEncoder":                          "encoding/gob",
+	"gob.Register":                            "encoding/gob",
+	"gob.RegisterName":                        "encoding/gob",
+	"gosym.DecodingError":                     "debug/gosym",
+	"gosym.Func":                              "debug/gosym",
+	"gosym.LineTable":                         "debug/gosym",
+	"gosym.NewLineTable":                      "debug/gosym",
+	"gosym.NewTable":                          "debug/gosym",
+	"gosym.Obj":                               "debug/gosym",
+	"gosym.Sym":                               "debug/gosym",
+	"gosym.Table":                             "debug/gosym",
+	"gosym.UnknownFileError":                  "debug/gosym",
+	"gosym.UnknownLineError":                  "debug/gosym",
+	"gzip.BestCompression":                    "compress/gzip",
+	"gzip.BestSpeed":                          "compress/gzip",
+	"gzip.DefaultCompression":                 "compress/gzip",
+	"gzip.ErrChecksum":                        "compress/gzip",
+	"gzip.ErrHeader":                          "compress/gzip",
+	"gzip.Header":                             "compress/gzip",
+	"gzip.NewReader":                          "compress/gzip",
+	"gzip.NewWriter":                          "compress/gzip",
+	"gzip.NewWriterLevel":                     "compress/gzip",
+	"gzip.NoCompression":                      "compress/gzip",
+	"gzip.Reader":                             "compress/gzip",
+	"gzip.Writer":                             "compress/gzip",
+	"hash.Hash":                               "hash",
+	"hash.Hash32":                             "hash",
+	"hash.Hash64":                             "hash",
+	"heap.Fix":                                "container/heap",
+	"heap.Init":                               "container/heap",
+	"heap.Interface":                          "container/heap",
+	"heap.Pop":                                "container/heap",
+	"heap.Push":                               "container/heap",
+	"heap.Remove":                             "container/heap",
+	"hex.Decode":                              "encoding/hex",
+	"hex.DecodeString":                        "encoding/hex",
+	"hex.DecodedLen":                          "encoding/hex",
+	"hex.Dump":                                "encoding/hex",
+	"hex.Dumper":                              "encoding/hex",
+	"hex.Encode":                              "encoding/hex",
+	"hex.EncodeToString":                      "encoding/hex",
+	"hex.EncodedLen":                          "encoding/hex",
+	"hex.ErrLength":                           "encoding/hex",
+	"hex.InvalidByteError":                    "encoding/hex",
+	"hmac.Equal":                              "crypto/hmac",
+	"hmac.New":                                "crypto/hmac",
+	"html.EscapeString":                       "html",
+	"html.UnescapeString":                     "html",
+	"http.CanonicalHeaderKey":                 "net/http",
+	"http.Client":                             "net/http",
+	"http.CloseNotifier":                      "net/http",
+	"http.Cookie":                             "net/http",
+	"http.CookieJar":                          "net/http",
+	"http.DefaultClient":                      "net/http",
+	"http.DefaultMaxHeaderBytes":              "net/http",
+	"http.DefaultMaxIdleConnsPerHost":         "net/http",
+	"http.DefaultServeMux":                    "net/http",
+	"http.DefaultTransport":                   "net/http",
+	"http.DetectContentType":                  "net/http",
+	"http.Dir":                                "net/http",
+	"http.ErrBodyNotAllowed":                  "net/http",
+	"http.ErrBodyReadAfterClose":              "net/http",
+	"http.ErrContentLength":                   "net/http",
+	"http.ErrHandlerTimeout":                  "net/http",
+	"http.ErrHeaderTooLong":                   "net/http",
+	"http.ErrHijacked":                        "net/http",
+	"http.ErrLineTooLong":                     "net/http",
+	"http.ErrMissingBoundary":                 "net/http",
+	"http.ErrMissingContentLength":            "net/http",
+	"http.ErrMissingFile":                     "net/http",
+	"http.ErrNoCookie":                        "net/http",
+	"http.ErrNoLocation":                      "net/http",
+	"http.ErrNotMultipart":                    "net/http",
+	"http.ErrNotSupported":                    "net/http",
+	"http.ErrShortBody":                       "net/http",
+	"http.ErrUnexpectedTrailer":               "net/http",
+	"http.ErrWriteAfterFlush":                 "net/http",
+	"http.Error":                              "net/http",
+	"http.File":                               "net/http",
+	"http.FileServer":                         "net/http",
+	"http.FileSystem":                         "net/http",
+	"http.Flusher":                            "net/http",
+	"http.Get":                                "net/http",
+	"http.Handle":                             "net/http",
+	"http.HandleFunc":                         "net/http",
+	"http.Handler":                            "net/http",
+	"http.HandlerFunc":                        "net/http",
+	"http.Head":                               "net/http",
+	"http.Header":                             "net/http",
+	"http.Hijacker":                           "net/http",
+	"http.ListenAndServe":                     "net/http",
+	"http.ListenAndServeTLS":                  "net/http",
+	"http.MaxBytesReader":                     "net/http",
+	"http.NewFileTransport":                   "net/http",
+	"http.NewRequest":                         "net/http",
+	"http.NewServeMux":                        "net/http",
+	"http.NotFound":                           "net/http",
+	"http.NotFoundHandler":                    "net/http",
+	"http.ParseHTTPVersion":                   "net/http",
+	"http.ParseTime":                          "net/http",
+	"http.Post":                               "net/http",
+	"http.PostForm":                           "net/http",
+	"http.ProtocolError":                      "net/http",
+	"http.ProxyFromEnvironment":               "net/http",
+	"http.ProxyURL":                           "net/http",
+	"http.ReadRequest":                        "net/http",
+	"http.ReadResponse":                       "net/http",
+	"http.Redirect":                           "net/http",
+	"http.RedirectHandler":                    "net/http",
+	"http.Request":                            "net/http",
+	"http.Response":                           "net/http",
+	"http.ResponseWriter":                     "net/http",
+	"http.RoundTripper":                       "net/http",
+	"http.Serve":                              "net/http",
+	"http.ServeContent":                       "net/http",
+	"http.ServeFile":                          "net/http",
+	"http.ServeMux":                           "net/http",
+	"http.Server":                             "net/http",
+	"http.SetCookie":                          "net/http",
+	"http.StatusAccepted":                     "net/http",
+	"http.StatusBadGateway":                   "net/http",
+	"http.StatusBadRequest":                   "net/http",
+	"http.StatusConflict":                     "net/http",
+	"http.StatusContinue":                     "net/http",
+	"http.StatusCreated":                      "net/http",
+	"http.StatusExpectationFailed":            "net/http",
+	"http.StatusForbidden":                    "net/http",
+	"http.StatusFound":                        "net/http",
+	"http.StatusGatewayTimeout":               "net/http",
+	"http.StatusGone":                         "net/http",
+	"http.StatusHTTPVersionNotSupported":      "net/http",
+	"http.StatusInternalServerError":          "net/http",
+	"http.StatusLengthRequired":               "net/http",
+	"http.StatusMethodNotAllowed":             "net/http",
+	"http.StatusMovedPermanently":             "net/http",
+	"http.StatusMultipleChoices":              "net/http",
+	"http.StatusNoContent":                    "net/http",
+	"http.StatusNonAuthoritativeInfo":         "net/http",
+	"http.StatusNotAcceptable":                "net/http",
+	"http.StatusNotFound":                     "net/http",
+	"http.StatusNotImplemented":               "net/http",
+	"http.StatusNotModified":                  "net/http",
+	"http.StatusOK":                           "net/http",
+	"http.StatusPartialContent":               "net/http",
+	"http.StatusPaymentRequired":              "net/http",
+	"http.StatusPreconditionFailed":           "net/http",
+	"http.StatusProxyAuthRequired":            "net/http",
+	"http.StatusRequestEntityTooLarge":        "net/http",
+	"http.StatusRequestTimeout":               "net/http",
+	"http.StatusRequestURITooLong":            "net/http",
+	"http.StatusRequestedRangeNotSatisfiable": "net/http",
+	"http.StatusResetContent":                 "net/http",
+	"http.StatusSeeOther":                     "net/http",
+	"http.StatusServiceUnavailable":           "net/http",
+	"http.StatusSwitchingProtocols":           "net/http",
+	"http.StatusTeapot":                       "net/http",
+	"http.StatusTemporaryRedirect":            "net/http",
+	"http.StatusText":                         "net/http",
+	"http.StatusUnauthorized":                 "net/http",
+	"http.StatusUnsupportedMediaType":         "net/http",
+	"http.StatusUseProxy":                     "net/http",
+	"http.StripPrefix":                        "net/http",
+	"http.TimeFormat":                         "net/http",
+	"http.TimeoutHandler":                     "net/http",
+	"http.Transport":                          "net/http",
+	"httptest.DefaultRemoteAddr":              "net/http/httptest",
+	"httptest.NewRecorder":                    "net/http/httptest",
+	"httptest.NewServer":                      "net/http/httptest",
+	"httptest.NewTLSServer":                   "net/http/httptest",
+	"httptest.NewUnstartedServer":             "net/http/httptest",
+	"httptest.ResponseRecorder":               "net/http/httptest",
+	"httptest.Server":                         "net/http/httptest",
+	"httputil.ClientConn":                     "net/http/httputil",
+	"httputil.DumpRequest":                    "net/http/httputil",
+	"httputil.DumpRequestOut":                 "net/http/httputil",
+	"httputil.DumpResponse":                   "net/http/httputil",
+	"httputil.ErrClosed":                      "net/http/httputil",
+	"httputil.ErrLineTooLong":                 "net/http/httputil",
+	"httputil.ErrPersistEOF":                  "net/http/httputil",
+	"httputil.ErrPipeline":                    "net/http/httputil",
+	"httputil.NewChunkedReader":               "net/http/httputil",
+	"httputil.NewChunkedWriter":               "net/http/httputil",
+	"httputil.NewClientConn":                  "net/http/httputil",
+	"httputil.NewProxyClientConn":             "net/http/httputil",
+	"httputil.NewServerConn":                  "net/http/httputil",
+	"httputil.NewSingleHostReverseProxy":      "net/http/httputil",
+	"httputil.ReverseProxy":                   "net/http/httputil",
+	"httputil.ServerConn":                     "net/http/httputil",
+	"image.Alpha":                             "image",
+	"image.Alpha16":                           "image",
+	"image.Black":                             "image",
+	"image.Config":                            "image",
+	"image.Decode":                            "image",
+	"image.DecodeConfig":                      "image",
+	"image.ErrFormat":                         "image",
+	"image.Gray":                              "image",
+	"image.Gray16":                            "image",
+	"image.Image":                             "image",
+	"image.NRGBA":                             "image",
+	"image.NRGBA64":                           "image",
+	"image.NewAlpha":                          "image",
+	"image.NewAlpha16":                        "image",
+	"image.NewGray":                           "image",
+	"image.NewGray16":                         "image",
+	"image.NewNRGBA":                          "image",
+	"image.NewNRGBA64":                        "image",
+	"image.NewPaletted":                       "image",
+	"image.NewRGBA":                           "image",
+	"image.NewRGBA64":                         "image",
+	"image.NewUniform":                        "image",
+	"image.NewYCbCr":                          "image",
+	"image.Opaque":                            "image",
+	"image.Paletted":                          "image",
+	"image.PalettedImage":                     "image",
+	"image.Point":                             "image",
+	"image.Pt":                                "image",
+	"image.RGBA":                              "image",
+	"image.RGBA64":                            "image",
+	"image.Rect":                              "image",
+	"image.Rectangle":                         "image",
+	"image.RegisterFormat":                    "image",
+	"image.Transparent":                       "image",
+	"image.Uniform":                           "image",
+	"image.White":                             "image",
+	"image.YCbCr":                             "image",
+	"image.YCbCrSubsampleRatio":               "image",
+	"image.YCbCrSubsampleRatio420":            "image",
+	"image.YCbCrSubsampleRatio422":            "image",
+	"image.YCbCrSubsampleRatio440":            "image",
+	"image.YCbCrSubsampleRatio444":            "image",
+	"image.ZP":                                "image",
+	"image.ZR":                                "image",
+	"io.ByteReader":                           "io",
+	"io.ByteScanner":                          "io",
+	"io.ByteWriter":                           "io",
+	"io.Closer":                               "io",
+	"io.Copy":                                 "io",
+	"io.CopyN":                                "io",
+	"io.EOF":                                  "io",
+	"io.ErrClosedPipe":                        "io",
+	"io.ErrNoProgress":                        "io",
+	"io.ErrShortBuffer":                       "io",
+	"io.ErrShortWrite":                        "io",
+	"io.ErrUnexpectedEOF":                     "io",
+	"io.LimitReader":                          "io",
+	"io.LimitedReader":                        "io",
+	"io.MultiReader":                          "io",
+	"io.MultiWriter":                          "io",
+	"io.NewSectionReader":                     "io",
+	"io.Pipe":                                 "io",
+	"io.PipeReader":                           "io",
+	"io.PipeWriter":                           "io",
+	"io.ReadAtLeast":                          "io",
+	"io.ReadCloser":                           "io",
+	"io.ReadFull":                             "io",
+	"io.ReadSeeker":                           "io",
+	"io.ReadWriteCloser":                      "io",
+	"io.ReadWriteSeeker":                      "io",
+	"io.ReadWriter":                           "io",
+	"io.Reader":                               "io",
+	"io.ReaderAt":                             "io",
+	"io.ReaderFrom":                           "io",
+	"io.RuneReader":                           "io",
+	"io.RuneScanner":                          "io",
+	"io.SectionReader":                        "io",
+	"io.Seeker":                               "io",
+	"io.TeeReader":                            "io",
+	"io.WriteCloser":                          "io",
+	"io.WriteSeeker":                          "io",
+	"io.WriteString":                          "io",
+	"io.Writer":                               "io",
+	"io.WriterAt":                             "io",
+	"io.WriterTo":                             "io",
+	"iotest.DataErrReader":                    "testing/iotest",
+	"iotest.ErrTimeout":                       "testing/iotest",
+	"iotest.HalfReader":                       "testing/iotest",
+	"iotest.NewReadLogger":                    "testing/iotest",
+	"iotest.NewWriteLogger":                   "testing/iotest",
+	"iotest.OneByteReader":                    "testing/iotest",
+	"iotest.TimeoutReader":                    "testing/iotest",
+	"iotest.TruncateWriter":                   "testing/iotest",
+	"ioutil.Discard":                          "io/ioutil",
+	"ioutil.NopCloser":                        "io/ioutil",
+	"ioutil.ReadAll":                          "io/ioutil",
+	"ioutil.ReadDir":                          "io/ioutil",
+	"ioutil.ReadFile":                         "io/ioutil",
+	"ioutil.TempDir":                          "io/ioutil",
+	"ioutil.TempFile":                         "io/ioutil",
+	"ioutil.WriteFile":                        "io/ioutil",
+	"jpeg.Decode":                             "image/jpeg",
+	"jpeg.DecodeConfig":                       "image/jpeg",
+	"jpeg.DefaultQuality":                     "image/jpeg",
+	"jpeg.Encode":                             "image/jpeg",
+	"jpeg.FormatError":                        "image/jpeg",
+	"jpeg.Options":                            "image/jpeg",
+	"jpeg.Reader":                             "image/jpeg",
+	"jpeg.UnsupportedError":                   "image/jpeg",
+	"json.Compact":                            "encoding/json",
+	"json.Decoder":                            "encoding/json",
+	"json.Encoder":                            "encoding/json",
+	"json.HTMLEscape":                         "encoding/json",
+	"json.Indent":                             "encoding/json",
+	"json.InvalidUTF8Error":                   "encoding/json",
+	"json.InvalidUnmarshalError":              "encoding/json",
+	"json.Marshal":                            "encoding/json",
+	"json.MarshalIndent":                      "encoding/json",
+	"json.Marshaler":                          "encoding/json",
+	"json.MarshalerError":                     "encoding/json",
+	"json.NewDecoder":                         "encoding/json",
+	"json.NewEncoder":                         "encoding/json",
+	"json.Number":                             "encoding/json",
+	"json.RawMessage":                         "encoding/json",
+	"json.SyntaxError":                        "encoding/json",
+	"json.Unmarshal":                          "encoding/json",
+	"json.UnmarshalFieldError":                "encoding/json",
+	"json.UnmarshalTypeError":                 "encoding/json",
+	"json.Unmarshaler":                        "encoding/json",
+	"json.UnsupportedTypeError":               "encoding/json",
+	"json.UnsupportedValueError":              "encoding/json",
+	"jsonrpc.Dial":                            "net/rpc/jsonrpc",
+	"jsonrpc.NewClient":                       "net/rpc/jsonrpc",
+	"jsonrpc.NewClientCodec":                  "net/rpc/jsonrpc",
+	"jsonrpc.NewServerCodec":                  "net/rpc/jsonrpc",
+	"jsonrpc.ServeConn":                       "net/rpc/jsonrpc",
+	"list.Element":                            "container/list",
+	"list.List":                               "container/list",
+	"list.New":                                "container/list",
+	"log.Fatal":                               "log",
+	"log.Fatalf":                              "log",
+	"log.Fatalln":                             "log",
+	"log.Flags":                               "log",
+	"log.Ldate":                               "log",
+	"log.Llongfile":                           "log",
+	"log.Lmicroseconds":                       "log",
+	"log.Logger":                              "log",
+	"log.Lshortfile":                          "log",
+	"log.LstdFlags":                           "log",
+	"log.Ltime":                               "log",
+	"log.New":                                 "log",
+	"log.Panic":                               "log",
+	"log.Panicf":                              "log",
+	"log.Panicln":                             "log",
+	"log.Prefix":                              "log",
+	"log.Print":                               "log",
+	"log.Printf":                              "log",
+	"log.Println":                             "log",
+	"log.SetFlags":                            "log",
+	"log.SetOutput":                           "log",
+	"log.SetPrefix":                           "log",
+	"lzw.LSB":                                 "compress/lzw",
+	"lzw.MSB":                                 "compress/lzw",
+	"lzw.NewReader":                           "compress/lzw",
+	"lzw.NewWriter":                           "compress/lzw",
+	"lzw.Order":                               "compress/lzw",
+	"macho.Cpu":                               "debug/macho",
+	"macho.Cpu386":                            "debug/macho",
+	"macho.CpuAmd64":                          "debug/macho",
+	"macho.Dylib":                             "debug/macho",
+	"macho.DylibCmd":                          "debug/macho",
+	"macho.Dysymtab":                          "debug/macho",
+	"macho.DysymtabCmd":                       "debug/macho",
+	"macho.File":                              "debug/macho",
+	"macho.FileHeader":                        "debug/macho",
+	"macho.FormatError":                       "debug/macho",
+	"macho.Load":                              "debug/macho",
+	"macho.LoadBytes":                         "debug/macho",
+	"macho.LoadCmd":                           "debug/macho",
+	"macho.LoadCmdDylib":                      "debug/macho",
+	"macho.LoadCmdDylinker":                   "debug/macho",
+	"macho.LoadCmdDysymtab":                   "debug/macho",
+	"macho.LoadCmdSegment":                    "debug/macho",
+	"macho.LoadCmdSegment64":                  "debug/macho",
+	"macho.LoadCmdSymtab":                     "debug/macho",
+	"macho.LoadCmdThread":                     "debug/macho",
+	"macho.LoadCmdUnixThread":                 "debug/macho",
+	"macho.Magic32":                           "debug/macho",
+	"macho.Magic64":                           "debug/macho",
+	"macho.NewFile":                           "debug/macho",
+	"macho.Nlist32":                           "debug/macho",
+	"macho.Nlist64":                           "debug/macho",
+	"macho.Open":                              "debug/macho",
+	"macho.Regs386":                           "debug/macho",
+	"macho.RegsAMD64":                         "debug/macho",
+	"macho.Section":                           "debug/macho",
+	"macho.Section32":                         "debug/macho",
+	"macho.Section64":                         "debug/macho",
+	"macho.SectionHeader":                     "debug/macho",
+	"macho.Segment":                           "debug/macho",
+	"macho.Segment32":                         "debug/macho",
+	"macho.Segment64":                         "debug/macho",
+	"macho.SegmentHeader":                     "debug/macho",
+	"macho.Symbol":                            "debug/macho",
+	"macho.Symtab":                            "debug/macho",
+	"macho.SymtabCmd":                         "debug/macho",
+	"macho.Thread":                            "debug/macho",
+	"macho.Type":                              "debug/macho",
+	"macho.TypeExec":                          "debug/macho",
+	"macho.TypeObj":                           "debug/macho",
+	"mail.Address":                            "net/mail",
+	"mail.ErrHeaderNotPresent":                "net/mail",
+	"mail.Header":                             "net/mail",
+	"mail.Message":                            "net/mail",
+	"mail.ParseAddress":                       "net/mail",
+	"mail.ParseAddressList":                   "net/mail",
+	"mail.ReadMessage":                        "net/mail",
+	"math.Abs":                                "math",
+	"math.Acos":                               "math",
+	"math.Acosh":                              "math",
+	"math.Asin":                               "math",
+	"math.Asinh":                              "math",
+	"math.Atan":                               "math",
+	"math.Atan2":                              "math",
+	"math.Atanh":                              "math",
+	"math.Cbrt":                               "math",
+	"math.Ceil":                               "math",
+	"math.Copysign":                           "math",
+	"math.Cos":                                "math",
+	"math.Cosh":                               "math",
+	"math.Dim":                                "math",
+	"math.E":                                  "math",
+	"math.Erf":                                "math",
+	"math.Erfc":                               "math",
+	"math.Exp":                                "math",
+	"math.Exp2":                               "math",
+	"math.Expm1":                              "math",
+	"math.Float32bits":                        "math",
+	"math.Float32frombits":                    "math",
+	"math.Float64bits":                        "math",
+	"math.Float64frombits":                    "math",
+	"math.Floor":                              "math",
+	"math.Frexp":                              "math",
+	"math.Gamma":                              "math",
+	"math.Hypot":                              "math",
+	"math.Ilogb":                              "math",
+	"math.Inf":                                "math",
+	"math.IsInf":                              "math",
+	"math.IsNaN":                              "math",
+	"math.J0":                                 "math",
+	"math.J1":                                 "math",
+	"math.Jn":                                 "math",
+	"math.Ldexp":                              "math",
+	"math.Lgamma":                             "math",
+	"math.Ln10":                               "math",
+	"math.Ln2":                                "math",
+	"math.Log":                                "math",
+	"math.Log10":                              "math",
+	"math.Log10E":                             "math",
+	"math.Log1p":                              "math",
+	"math.Log2":                               "math",
+	"math.Log2E":                              "math",
+	"math.Logb":                               "math",
+	"math.Max":                                "math",
+	"math.MaxFloat32":                         "math",
+	"math.MaxFloat64":                         "math",
+	"math.MaxInt16":                           "math",
+	"math.MaxInt32":                           "math",
+	"math.MaxInt64":                           "math",
+	"math.MaxInt8":                            "math",
+	"math.MaxUint16":                          "math",
+	"math.MaxUint32":                          "math",
+	"math.MaxUint64":                          "math",
+	"math.MaxUint8":                           "math",
+	"math.Min":                                "math",
+	"math.MinInt16":                           "math",
+	"math.MinInt32":                           "math",
+	"math.MinInt64":                           "math",
+	"math.MinInt8":                            "math",
+	"math.Mod":                                "math",
+	"math.Modf":                               "math",
+	"math.NaN":                                "math",
+	"math.Nextafter":                          "math",
+	"math.Phi":                                "math",
+	"math.Pi":                                 "math",
+	"math.Pow":                                "math",
+	"math.Pow10":                              "math",
+	"math.Remainder":                          "math",
+	"math.Signbit":                            "math",
+	"math.Sin":                                "math",
+	"math.Sincos":                             "math",
+	"math.Sinh":                               "math",
+	"math.SmallestNonzeroFloat32":             "math",
+	"math.SmallestNonzeroFloat64":             "math",
+	"math.Sqrt":                               "math",
+	"math.Sqrt2":                              "math",
+	"math.SqrtE":                              "math",
+	"math.SqrtPhi":                            "math",
+	"math.SqrtPi":                             "math",
+	"math.Tan":                                "math",
+	"math.Tanh":                               "math",
+	"math.Trunc":                              "math",
+	"math.Y0":                                 "math",
+	"math.Y1":                                 "math",
+	"math.Yn":                                 "math",
+	"md5.BlockSize":                           "crypto/md5",
+	"md5.New":                                 "crypto/md5",
+	"md5.Size":                                "crypto/md5",
+	"md5.Sum":                                 "crypto/md5",
+	"mime.AddExtensionType":                   "mime",
+	"mime.FormatMediaType":                    "mime",
+	"mime.ParseMediaType":                     "mime",
+	"mime.TypeByExtension":                    "mime",
+	"multipart.File":                          "mime/multipart",
+	"multipart.FileHeader":                    "mime/multipart",
+	"multipart.Form":                          "mime/multipart",
+	"multipart.NewReader":                     "mime/multipart",
+	"multipart.NewWriter":                     "mime/multipart",
+	"multipart.Part":                          "mime/multipart",
+	"multipart.Reader":                        "mime/multipart",
+	"multipart.Writer":                        "mime/multipart",
+	"net.Addr":                                "net",
+	"net.AddrError":                           "net",
+	"net.CIDRMask":                            "net",
+	"net.Conn":                                "net",
+	"net.DNSConfigError":                      "net",
+	"net.DNSError":                            "net",
+	"net.Dial":                                "net",
+	"net.DialIP":                              "net",
+	"net.DialTCP":                             "net",
+	"net.DialTimeout":                         "net",
+	"net.DialUDP":                             "net",
+	"net.DialUnix":                            "net",
+	"net.Dialer":                              "net",
+	"net.ErrWriteToConnected":                 "net",
+	"net.Error":                               "net",
+	"net.FileConn":                            "net",
+	"net.FileListener":                        "net",
+	"net.FilePacketConn":                      "net",
+	"net.FlagBroadcast":                       "net",
+	"net.FlagLoopback":                        "net",
+	"net.FlagMulticast":                       "net",
+	"net.FlagPointToPoint":                    "net",
+	"net.FlagUp":                              "net",
+	"net.Flags":                               "net",
+	"net.HardwareAddr":                        "net",
+	"net.IP":                                  "net",
+	"net.IPAddr":                              "net",
+	"net.IPConn":                              "net",
+	"net.IPMask":                              "net",
+	"net.IPNet":                               "net",
+	"net.IPv4":                                "net",
+	"net.IPv4Mask":                            "net",
+	"net.IPv4allrouter":                       "net",
+	"net.IPv4allsys":                          "net",
+	"net.IPv4bcast":                           "net",
+	"net.IPv4len":                             "net",
+	"net.IPv4zero":                            "net",
+	"net.IPv6interfacelocalallnodes":          "net",
+	"net.IPv6len":                             "net",
+	"net.IPv6linklocalallnodes":               "net",
+	"net.IPv6linklocalallrouters":             "net",
+	"net.IPv6loopback":                        "net",
+	"net.IPv6unspecified":                     "net",
+	"net.IPv6zero":                            "net",
+	"net.Interface":                           "net",
+	"net.InterfaceAddrs":                      "net",
+	"net.InterfaceByIndex":                    "net",
+	"net.InterfaceByName":                     "net",
+	"net.Interfaces":                          "net",
+	"net.InvalidAddrError":                    "net",
+	"net.JoinHostPort":                        "net",
+	"net.Listen":                              "net",
+	"net.ListenIP":                            "net",
+	"net.ListenMulticastUDP":                  "net",
+	"net.ListenPacket":                        "net",
+	"net.ListenTCP":                           "net",
+	"net.ListenUDP":                           "net",
+	"net.ListenUnix":                          "net",
+	"net.ListenUnixgram":                      "net",
+	"net.Listener":                            "net",
+	"net.LookupAddr":                          "net",
+	"net.LookupCNAME":                         "net",
+	"net.LookupHost":                          "net",
+	"net.LookupIP":                            "net",
+	"net.LookupMX":                            "net",
+	"net.LookupNS":                            "net",
+	"net.LookupPort":                          "net",
+	"net.LookupSRV":                           "net",
+	"net.LookupTXT":                           "net",
+	"net.MX":                                  "net",
+	"net.NS":                                  "net",
+	"net.OpError":                             "net",
+	"net.PacketConn":                          "net",
+	"net.ParseCIDR":                           "net",
+	"net.ParseError":                          "net",
+	"net.ParseIP":                             "net",
+	"net.ParseMAC":                            "net",
+	"net.Pipe":                                "net",
+	"net.ResolveIPAddr":                       "net",
+	"net.ResolveTCPAddr":                      "net",
+	"net.ResolveUDPAddr":                      "net",
+	"net.ResolveUnixAddr":                     "net",
+	"net.SRV":                                 "net",
+	"net.SplitHostPort":                       "net",
+	"net.TCPAddr":                             "net",
+	"net.TCPConn":                             "net",
+	"net.TCPListener":                         "net",
+	"net.UDPAddr":                             "net",
+	"net.UDPConn":                             "net",
+	"net.UnixAddr":                            "net",
+	"net.UnixConn":                            "net",
+	"net.UnixListener":                        "net",
+	"net.UnknownNetworkError":                 "net",
+	"os.Args":                                 "os",
+	"os.Chdir":                                "os",
+	"os.Chmod":                                "os",
+	"os.Chown":                                "os",
+	"os.Chtimes":                              "os",
+	"os.Clearenv":                             "os",
+	"os.Create":                               "os",
+	"os.DevNull":                              "os",
+	"os.Environ":                              "os",
+	"os.ErrExist":                             "os",
+	"os.ErrInvalid":                           "os",
+	"os.ErrNotExist":                          "os",
+	"os.ErrPermission":                        "os",
+	"os.Exit":                                 "os",
+	"os.Expand":                               "os",
+	"os.ExpandEnv":                            "os",
+	"os.File":                                 "os",
+	"os.FileInfo":                             "os",
+	"os.FileMode":                             "os",
+	"os.FindProcess":                          "os",
+	"os.Getegid":                              "os",
+	"os.Getenv":                               "os",
+	"os.Geteuid":                              "os",
+	"os.Getgid":                               "os",
+	"os.Getgroups":                            "os",
+	"os.Getpagesize":                          "os",
+	"os.Getpid":                               "os",
+	"os.Getppid":                              "os",
+	"os.Getuid":                               "os",
+	"os.Getwd":                                "os",
+	"os.Hostname":                             "os",
+	"os.Interrupt":                            "os",
+	"os.IsExist":                              "os",
+	"os.IsNotExist":                           "os",
+	"os.IsPathSeparator":                      "os",
+	"os.IsPermission":                         "os",
+	"os.Kill":                                 "os",
+	"os.Lchown":                               "os",
+	"os.Link":                                 "os",
+	"os.LinkError":                            "os",
+	"os.Lstat":                                "os",
+	"os.Mkdir":                                "os",
+	"os.MkdirAll":                             "os",
+	"os.ModeAppend":                           "os",
+	"os.ModeCharDevice":                       "os",
+	"os.ModeDevice":                           "os",
+	"os.ModeDir":                              "os",
+	"os.ModeExclusive":                        "os",
+	"os.ModeNamedPipe":                        "os",
+	"os.ModePerm":                             "os",
+	"os.ModeSetgid":                           "os",
+	"os.ModeSetuid":                           "os",
+	"os.ModeSocket":                           "os",
+	"os.ModeSticky":                           "os",
+	"os.ModeSymlink":                          "os",
+	"os.ModeTemporary":                        "os",
+	"os.ModeType":                             "os",
+	"os.NewFile":                              "os",
+	"os.NewSyscallError":                      "os",
+	"os.O_APPEND":                             "os",
+	"os.O_CREATE":                             "os",
+	"os.O_EXCL":                               "os",
+	"os.O_RDONLY":                             "os",
+	"os.O_RDWR":                               "os",
+	"os.O_SYNC":                               "os",
+	"os.O_TRUNC":                              "os",
+	"os.O_WRONLY":                             "os",
+	"os.Open":                                 "os",
+	"os.OpenFile":                             "os",
+	"os.PathError":                            "os",
+	"os.PathListSeparator":                    "os",
+	"os.PathSeparator":                        "os",
+	"os.Pipe":                                 "os",
+	"os.ProcAttr":                             "os",
+	"os.Process":                              "os",
+	"os.ProcessState":                         "os",
+	"os.Readlink":                             "os",
+	"os.Remove":                               "os",
+	"os.RemoveAll":                            "os",
+	"os.Rename":                               "os",
+	"os.SEEK_CUR":                             "os",
+	"os.SEEK_END":                             "os",
+	"os.SEEK_SET":                             "os",
+	"os.SameFile":                             "os",
+	"os.Setenv":                               "os",
+	"os.Signal":                               "os",
+	"os.StartProcess":                         "os",
+	"os.Stat":                                 "os",
+	"os.Stderr":                               "os",
+	"os.Stdin":                                "os",
+	"os.Stdout":                               "os",
+	"os.Symlink":                              "os",
+	"os.SyscallError":                         "os",
+	"os.TempDir":                              "os",
+	"os.Truncate":                             "os",
+	"palette.Plan9":                           "image/color/palette",
+	"palette.WebSafe":                         "image/color/palette",
+	"parse.ActionNode":                        "text/template/parse",
+	"parse.BoolNode":                          "text/template/parse",
+	"parse.BranchNode":                        "text/template/parse",
+	"parse.ChainNode":                         "text/template/parse",
+	"parse.CommandNode":                       "text/template/parse",
+	"parse.DotNode":                           "text/template/parse",
+	"parse.FieldNode":                         "text/template/parse",
+	"parse.IdentifierNode":                    "text/template/parse",
+	"parse.IfNode":                            "text/template/parse",
+	"parse.IsEmptyTree":                       "text/template/parse",
+	"parse.ListNode":                          "text/template/parse",
+	"parse.New":                               "text/template/parse",
+	"parse.NewIdentifier":                     "text/template/parse",
+	"parse.NilNode":                           "text/template/parse",
+	"parse.Node":                              "text/template/parse",
+	"parse.NodeAction":                        "text/template/parse",
+	"parse.NodeBool":                          "text/template/parse",
+	"parse.NodeChain":                         "text/template/parse",
+	"parse.NodeCommand":                       "text/template/parse",
+	"parse.NodeDot":                           "text/template/parse",
+	"parse.NodeField":                         "text/template/parse",
+	"parse.NodeIdentifier":                    "text/template/parse",
+	"parse.NodeIf":                            "text/template/parse",
+	"parse.NodeList":                          "text/template/parse",
+	"parse.NodeNil":                           "text/template/parse",
+	"parse.NodeNumber":                        "text/template/parse",
+	"parse.NodePipe":                          "text/template/parse",
+	"parse.NodeRange":                         "text/template/parse",
+	"parse.NodeString":                        "text/template/parse",
+	"parse.NodeTemplate":                      "text/template/parse",
+	"parse.NodeText":                          "text/template/parse",
+	"parse.NodeType":                          "text/template/parse",
+	"parse.NodeVariable":                      "text/template/parse",
+	"parse.NodeWith":                          "text/template/parse",
+	"parse.NumberNode":                        "text/template/parse",
+	"parse.Parse":                             "text/template/parse",
+	"parse.PipeNode":                          "text/template/parse",
+	"parse.Pos":                               "text/template/parse",
+	"parse.RangeNode":                         "text/template/parse",
+	"parse.StringNode":                        "text/template/parse",
+	"parse.TemplateNode":                      "text/template/parse",
+	"parse.TextNode":                          "text/template/parse",
+	"parse.Tree":                              "text/template/parse",
+	"parse.VariableNode":                      "text/template/parse",
+	"parse.WithNode":                          "text/template/parse",
+	"parser.AllErrors":                        "go/parser",
+	"parser.DeclarationErrors":                "go/parser",
+	"parser.ImportsOnly":                      "go/parser",
+	"parser.Mode":                             "go/parser",
+	"parser.PackageClauseOnly":                "go/parser",
+	"parser.ParseComments":                    "go/parser",
+	"parser.ParseDir":                         "go/parser",
+	"parser.ParseExpr":                        "go/parser",
+	"parser.ParseFile":                        "go/parser",
+	"parser.SpuriousErrors":                   "go/parser",
+	"parser.Trace":                            "go/parser",
+	"path.Base":                               "path",
+	"path.Clean":                              "path",
+	"path.Dir":                                "path",
+	"path.ErrBadPattern":                      "path",
+	"path.Ext":                                "path",
+	"path.IsAbs":                              "path",
+	"path.Join":                               "path",
+	"path.Match":                              "path",
+	"path.Split":                              "path",
+	"pe.COFFSymbol":                           "debug/pe",
+	"pe.COFFSymbolSize":                       "debug/pe",
+	"pe.File":                                 "debug/pe",
+	"pe.FileHeader":                           "debug/pe",
+	"pe.FormatError":                          "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_AM33":              "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_AMD64":             "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_ARM":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_EBC":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_I386":              "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_IA64":              "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_M32R":              "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_MIPS16":            "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_MIPSFPU":           "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_MIPSFPU16":         "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_POWERPC":           "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_POWERPCFP":         "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_R4000":             "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH3":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH3DSP":            "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH4":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH5":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_THUMB":             "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_UNKNOWN":           "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_WCEMIPSV2":         "debug/pe",
+	"pe.ImportDirectory":                      "debug/pe",
+	"pe.NewFile":                              "debug/pe",
+	"pe.Open":                                 "debug/pe",
+	"pe.Section":                              "debug/pe",
+	"pe.SectionHeader":                        "debug/pe",
+	"pe.SectionHeader32":                      "debug/pe",
+	"pe.Symbol":                               "debug/pe",
+	"pem.Block":                               "encoding/pem",
+	"pem.Decode":                              "encoding/pem",
+	"pem.Encode":                              "encoding/pem",
+	"pem.EncodeToMemory":                      "encoding/pem",
+	"pkix.AlgorithmIdentifier":                "crypto/x509/pkix",
+	"pkix.AttributeTypeAndValue":              "crypto/x509/pkix",
+	"pkix.CertificateList":                    "crypto/x509/pkix",
+	"pkix.Extension":                          "crypto/x509/pkix",
+	"pkix.Name":                               "crypto/x509/pkix",
+	"pkix.RDNSequence":                        "crypto/x509/pkix",
+	"pkix.RelativeDistinguishedNameSET":       "crypto/x509/pkix",
+	"pkix.RevokedCertificate":                 "crypto/x509/pkix",
+	"pkix.TBSCertificateList":                 "crypto/x509/pkix",
+	"png.Decode":                              "image/png",
+	"png.DecodeConfig":                        "image/png",
+	"png.Encode":                              "image/png",
+	"png.FormatError":                         "image/png",
+	"png.UnsupportedError":                    "image/png",
+	"pprof.Cmdline":                           "net/http/pprof",
+	"pprof.Handler":                           "net/http/pprof",
+	"pprof.Index":                             "net/http/pprof",
+	"pprof.Lookup":                            "runtime/pprof",
+	"pprof.NewProfile":                        "runtime/pprof",
+	// "pprof.Profile" is ambiguous
+	"pprof.Profiles":         "runtime/pprof",
+	"pprof.StartCPUProfile":  "runtime/pprof",
+	"pprof.StopCPUProfile":   "runtime/pprof",
+	"pprof.Symbol":           "net/http/pprof",
+	"pprof.WriteHeapProfile": "runtime/pprof",
+	"printer.CommentedNode":  "go/printer",
+	"printer.Config":         "go/printer",
+	"printer.Fprint":         "go/printer",
+	"printer.Mode":           "go/printer",
+	"printer.RawFormat":      "go/printer",
+	"printer.SourcePos":      "go/printer",
+	"printer.TabIndent":      "go/printer",
+	"printer.UseSpaces":      "go/printer",
+	"quick.Check":            "testing/quick",
+	"quick.CheckEqual":       "testing/quick",
+	"quick.CheckEqualError":  "testing/quick",
+	"quick.CheckError":       "testing/quick",
+	"quick.Config":           "testing/quick",
+	"quick.Generator":        "testing/quick",
+	"quick.SetupError":       "testing/quick",
+	"quick.Value":            "testing/quick",
+	"rand.ExpFloat64":        "math/rand",
+	"rand.Float32":           "math/rand",
+	"rand.Float64":           "math/rand",
+	// "rand.Int" is ambiguous
+	"rand.Int31":                    "math/rand",
+	"rand.Int31n":                   "math/rand",
+	"rand.Int63":                    "math/rand",
+	"rand.Int63n":                   "math/rand",
+	"rand.Intn":                     "math/rand",
+	"rand.New":                      "math/rand",
+	"rand.NewSource":                "math/rand",
+	"rand.NewZipf":                  "math/rand",
+	"rand.NormFloat64":              "math/rand",
+	"rand.Perm":                     "math/rand",
+	"rand.Prime":                    "crypto/rand",
+	"rand.Rand":                     "math/rand",
+	"rand.Read":                     "crypto/rand",
+	"rand.Reader":                   "crypto/rand",
+	"rand.Seed":                     "math/rand",
+	"rand.Source":                   "math/rand",
+	"rand.Uint32":                   "math/rand",
+	"rand.Zipf":                     "math/rand",
+	"rc4.Cipher":                    "crypto/rc4",
+	"rc4.KeySizeError":              "crypto/rc4",
+	"rc4.NewCipher":                 "crypto/rc4",
+	"reflect.Append":                "reflect",
+	"reflect.AppendSlice":           "reflect",
+	"reflect.Array":                 "reflect",
+	"reflect.Bool":                  "reflect",
+	"reflect.BothDir":               "reflect",
+	"reflect.Chan":                  "reflect",
+	"reflect.ChanDir":               "reflect",
+	"reflect.ChanOf":                "reflect",
+	"reflect.Complex128":            "reflect",
+	"reflect.Complex64":             "reflect",
+	"reflect.Copy":                  "reflect",
+	"reflect.DeepEqual":             "reflect",
+	"reflect.Float32":               "reflect",
+	"reflect.Float64":               "reflect",
+	"reflect.Func":                  "reflect",
+	"reflect.Indirect":              "reflect",
+	"reflect.Int":                   "reflect",
+	"reflect.Int16":                 "reflect",
+	"reflect.Int32":                 "reflect",
+	"reflect.Int64":                 "reflect",
+	"reflect.Int8":                  "reflect",
+	"reflect.Interface":             "reflect",
+	"reflect.Invalid":               "reflect",
+	"reflect.Kind":                  "reflect",
+	"reflect.MakeChan":              "reflect",
+	"reflect.MakeFunc":              "reflect",
+	"reflect.MakeMap":               "reflect",
+	"reflect.MakeSlice":             "reflect",
+	"reflect.Map":                   "reflect",
+	"reflect.MapOf":                 "reflect",
+	"reflect.Method":                "reflect",
+	"reflect.New":                   "reflect",
+	"reflect.NewAt":                 "reflect",
+	"reflect.Ptr":                   "reflect",
+	"reflect.PtrTo":                 "reflect",
+	"reflect.RecvDir":               "reflect",
+	"reflect.Select":                "reflect",
+	"reflect.SelectCase":            "reflect",
+	"reflect.SelectDefault":         "reflect",
+	"reflect.SelectDir":             "reflect",
+	"reflect.SelectRecv":            "reflect",
+	"reflect.SelectSend":            "reflect",
+	"reflect.SendDir":               "reflect",
+	"reflect.Slice":                 "reflect",
+	"reflect.SliceHeader":           "reflect",
+	"reflect.SliceOf":               "reflect",
+	"reflect.String":                "reflect",
+	"reflect.StringHeader":          "reflect",
+	"reflect.Struct":                "reflect",
+	"reflect.StructField":           "reflect",
+	"reflect.StructTag":             "reflect",
+	"reflect.TypeOf":                "reflect",
+	"reflect.Uint":                  "reflect",
+	"reflect.Uint16":                "reflect",
+	"reflect.Uint32":                "reflect",
+	"reflect.Uint64":                "reflect",
+	"reflect.Uint8":                 "reflect",
+	"reflect.Uintptr":               "reflect",
+	"reflect.UnsafePointer":         "reflect",
+	"reflect.Value":                 "reflect",
+	"reflect.ValueError":            "reflect",
+	"reflect.ValueOf":               "reflect",
+	"reflect.Zero":                  "reflect",
+	"regexp.Compile":                "regexp",
+	"regexp.CompilePOSIX":           "regexp",
+	"regexp.Match":                  "regexp",
+	"regexp.MatchReader":            "regexp",
+	"regexp.MatchString":            "regexp",
+	"regexp.MustCompile":            "regexp",
+	"regexp.MustCompilePOSIX":       "regexp",
+	"regexp.QuoteMeta":              "regexp",
+	"regexp.Regexp":                 "regexp",
+	"ring.New":                      "container/ring",
+	"ring.Ring":                     "container/ring",
+	"rpc.Accept":                    "net/rpc",
+	"rpc.Call":                      "net/rpc",
+	"rpc.Client":                    "net/rpc",
+	"rpc.ClientCodec":               "net/rpc",
+	"rpc.DefaultDebugPath":          "net/rpc",
+	"rpc.DefaultRPCPath":            "net/rpc",
+	"rpc.DefaultServer":             "net/rpc",
+	"rpc.Dial":                      "net/rpc",
+	"rpc.DialHTTP":                  "net/rpc",
+	"rpc.DialHTTPPath":              "net/rpc",
+	"rpc.ErrShutdown":               "net/rpc",
+	"rpc.HandleHTTP":                "net/rpc",
+	"rpc.NewClient":                 "net/rpc",
+	"rpc.NewClientWithCodec":        "net/rpc",
+	"rpc.NewServer":                 "net/rpc",
+	"rpc.Register":                  "net/rpc",
+	"rpc.RegisterName":              "net/rpc",
+	"rpc.Request":                   "net/rpc",
+	"rpc.Response":                  "net/rpc",
+	"rpc.ServeCodec":                "net/rpc",
+	"rpc.ServeConn":                 "net/rpc",
+	"rpc.ServeRequest":              "net/rpc",
+	"rpc.Server":                    "net/rpc",
+	"rpc.ServerCodec":               "net/rpc",
+	"rpc.ServerError":               "net/rpc",
+	"rsa.CRTValue":                  "crypto/rsa",
+	"rsa.DecryptOAEP":               "crypto/rsa",
+	"rsa.DecryptPKCS1v15":           "crypto/rsa",
+	"rsa.DecryptPKCS1v15SessionKey": "crypto/rsa",
+	"rsa.EncryptOAEP":               "crypto/rsa",
+	"rsa.EncryptPKCS1v15":           "crypto/rsa",
+	"rsa.ErrDecryption":             "crypto/rsa",
+	"rsa.ErrMessageTooLong":         "crypto/rsa",
+	"rsa.ErrVerification":           "crypto/rsa",
+	"rsa.GenerateKey":               "crypto/rsa",
+	"rsa.GenerateMultiPrimeKey":     "crypto/rsa",
+	"rsa.PSSOptions":                "crypto/rsa",
+	"rsa.PSSSaltLengthAuto":         "crypto/rsa",
+	"rsa.PSSSaltLengthEqualsHash":   "crypto/rsa",
+	"rsa.PrecomputedValues":         "crypto/rsa",
+	"rsa.PrivateKey":                "crypto/rsa",
+	"rsa.PublicKey":                 "crypto/rsa",
+	"rsa.SignPKCS1v15":              "crypto/rsa",
+	"rsa.SignPSS":                   "crypto/rsa",
+	"rsa.VerifyPKCS1v15":            "crypto/rsa",
+	"rsa.VerifyPSS":                 "crypto/rsa",
+	"runtime.BlockProfile":          "runtime",
+	"runtime.BlockProfileRecord":    "runtime",
+	"runtime.Breakpoint":            "runtime",
+	"runtime.CPUProfile":            "runtime",
+	"runtime.Caller":                "runtime",
+	"runtime.Callers":               "runtime",
+	"runtime.Compiler":              "runtime",
+	"runtime.Error":                 "runtime",
+	"runtime.Func":                  "runtime",
+	"runtime.FuncForPC":             "runtime",
+	"runtime.GC":                    "runtime",
+	"runtime.GOARCH":                "runtime",
+	"runtime.GOMAXPROCS":            "runtime",
+	"runtime.GOOS":                  "runtime",
+	"runtime.GOROOT":                "runtime",
+	"runtime.Goexit":                "runtime",
+	"runtime.GoroutineProfile":      "runtime",
+	"runtime.Gosched":               "runtime",
+	"runtime.LockOSThread":          "runtime",
+	"runtime.MemProfile":            "runtime",
+	"runtime.MemProfileRate":        "runtime",
+	"runtime.MemProfileRecord":      "runtime",
+	"runtime.MemStats":              "runtime",
+	"runtime.NumCPU":                "runtime",
+	"runtime.NumCgoCall":            "runtime",
+	"runtime.NumGoroutine":          "runtime",
+	"runtime.ReadMemStats":          "runtime",
+	"runtime.SetBlockProfileRate":   "runtime",
+	"runtime.SetCPUProfileRate":     "runtime",
+	"runtime.SetFinalizer":          "runtime",
+	"runtime.Stack":                 "runtime",
+	"runtime.StackRecord":           "runtime",
+	"runtime.ThreadCreateProfile":   "runtime",
+	"runtime.TypeAssertionError":    "runtime",
+	"runtime.UnlockOSThread":        "runtime",
+	"runtime.Version":               "runtime",
+	"scanner.Char":                  "text/scanner",
+	"scanner.Comment":               "text/scanner",
+	"scanner.EOF":                   "text/scanner",
+	"scanner.Error":                 "go/scanner",
+	"scanner.ErrorHandler":          "go/scanner",
+	"scanner.ErrorList":             "go/scanner",
+	"scanner.Float":                 "text/scanner",
+	"scanner.GoTokens":              "text/scanner",
+	"scanner.GoWhitespace":          "text/scanner",
+	"scanner.Ident":                 "text/scanner",
+	"scanner.Int":                   "text/scanner",
+	"scanner.Mode":                  "go/scanner",
+	"scanner.Position":              "text/scanner",
+	"scanner.PrintError":            "go/scanner",
+	"scanner.RawString":             "text/scanner",
+	"scanner.ScanChars":             "text/scanner",
+	// "scanner.ScanComments" is ambiguous
+	"scanner.ScanFloats":     "text/scanner",
+	"scanner.ScanIdents":     "text/scanner",
+	"scanner.ScanInts":       "text/scanner",
+	"scanner.ScanRawStrings": "text/scanner",
+	"scanner.ScanStrings":    "text/scanner",
+	// "scanner.Scanner" is ambiguous
+	"scanner.SkipComments":                                 "text/scanner",
+	"scanner.String":                                       "text/scanner",
+	"scanner.TokenString":                                  "text/scanner",
+	"sha1.BlockSize":                                       "crypto/sha1",
+	"sha1.New":                                             "crypto/sha1",
+	"sha1.Size":                                            "crypto/sha1",
+	"sha1.Sum":                                             "crypto/sha1",
+	"sha256.BlockSize":                                     "crypto/sha256",
+	"sha256.New":                                           "crypto/sha256",
+	"sha256.New224":                                        "crypto/sha256",
+	"sha256.Size":                                          "crypto/sha256",
+	"sha256.Size224":                                       "crypto/sha256",
+	"sha256.Sum224":                                        "crypto/sha256",
+	"sha256.Sum256":                                        "crypto/sha256",
+	"sha512.BlockSize":                                     "crypto/sha512",
+	"sha512.New":                                           "crypto/sha512",
+	"sha512.New384":                                        "crypto/sha512",
+	"sha512.Size":                                          "crypto/sha512",
+	"sha512.Size384":                                       "crypto/sha512",
+	"sha512.Sum384":                                        "crypto/sha512",
+	"sha512.Sum512":                                        "crypto/sha512",
+	"signal.Notify":                                        "os/signal",
+	"signal.Stop":                                          "os/signal",
+	"smtp.Auth":                                            "net/smtp",
+	"smtp.CRAMMD5Auth":                                     "net/smtp",
+	"smtp.Client":                                          "net/smtp",
+	"smtp.Dial":                                            "net/smtp",
+	"smtp.NewClient":                                       "net/smtp",
+	"smtp.PlainAuth":                                       "net/smtp",
+	"smtp.SendMail":                                        "net/smtp",
+	"smtp.ServerInfo":                                      "net/smtp",
+	"sort.Float64Slice":                                    "sort",
+	"sort.Float64s":                                        "sort",
+	"sort.Float64sAreSorted":                               "sort",
+	"sort.IntSlice":                                        "sort",
+	"sort.Interface":                                       "sort",
+	"sort.Ints":                                            "sort",
+	"sort.IntsAreSorted":                                   "sort",
+	"sort.IsSorted":                                        "sort",
+	"sort.Reverse":                                         "sort",
+	"sort.Search":                                          "sort",
+	"sort.SearchFloat64s":                                  "sort",
+	"sort.SearchInts":                                      "sort",
+	"sort.SearchStrings":                                   "sort",
+	"sort.Sort":                                            "sort",
+	"sort.Stable":                                          "sort",
+	"sort.StringSlice":                                     "sort",
+	"sort.Strings":                                         "sort",
+	"sort.StringsAreSorted":                                "sort",
+	"sql.DB":                                               "database/sql",
+	"sql.ErrNoRows":                                        "database/sql",
+	"sql.ErrTxDone":                                        "database/sql",
+	"sql.NullBool":                                         "database/sql",
+	"sql.NullFloat64":                                      "database/sql",
+	"sql.NullInt64":                                        "database/sql",
+	"sql.NullString":                                       "database/sql",
+	"sql.Open":                                             "database/sql",
+	"sql.RawBytes":                                         "database/sql",
+	"sql.Register":                                         "database/sql",
+	"sql.Result":                                           "database/sql",
+	"sql.Row":                                              "database/sql",
+	"sql.Rows":                                             "database/sql",
+	"sql.Scanner":                                          "database/sql",
+	"sql.Stmt":                                             "database/sql",
+	"sql.Tx":                                               "database/sql",
+	"strconv.AppendBool":                                   "strconv",
+	"strconv.AppendFloat":                                  "strconv",
+	"strconv.AppendInt":                                    "strconv",
+	"strconv.AppendQuote":                                  "strconv",
+	"strconv.AppendQuoteRune":                              "strconv",
+	"strconv.AppendQuoteRuneToASCII":                       "strconv",
+	"strconv.AppendQuoteToASCII":                           "strconv",
+	"strconv.AppendUint":                                   "strconv",
+	"strconv.Atoi":                                         "strconv",
+	"strconv.CanBackquote":                                 "strconv",
+	"strconv.ErrRange":                                     "strconv",
+	"strconv.ErrSyntax":                                    "strconv",
+	"strconv.FormatBool":                                   "strconv",
+	"strconv.FormatFloat":                                  "strconv",
+	"strconv.FormatInt":                                    "strconv",
+	"strconv.FormatUint":                                   "strconv",
+	"strconv.IntSize":                                      "strconv",
+	"strconv.IsPrint":                                      "strconv",
+	"strconv.Itoa":                                         "strconv",
+	"strconv.NumError":                                     "strconv",
+	"strconv.ParseBool":                                    "strconv",
+	"strconv.ParseFloat":                                   "strconv",
+	"strconv.ParseInt":                                     "strconv",
+	"strconv.ParseUint":                                    "strconv",
+	"strconv.Quote":                                        "strconv",
+	"strconv.QuoteRune":                                    "strconv",
+	"strconv.QuoteRuneToASCII":                             "strconv",
+	"strconv.QuoteToASCII":                                 "strconv",
+	"strconv.Unquote":                                      "strconv",
+	"strconv.UnquoteChar":                                  "strconv",
+	"strings.Contains":                                     "strings",
+	"strings.ContainsAny":                                  "strings",
+	"strings.ContainsRune":                                 "strings",
+	"strings.Count":                                        "strings",
+	"strings.EqualFold":                                    "strings",
+	"strings.Fields":                                       "strings",
+	"strings.FieldsFunc":                                   "strings",
+	"strings.HasPrefix":                                    "strings",
+	"strings.HasSuffix":                                    "strings",
+	"strings.Index":                                        "strings",
+	"strings.IndexAny":                                     "strings",
+	"strings.IndexByte":                                    "strings",
+	"strings.IndexFunc":                                    "strings",
+	"strings.IndexRune":                                    "strings",
+	"strings.Join":                                         "strings",
+	"strings.LastIndex":                                    "strings",
+	"strings.LastIndexAny":                                 "strings",
+	"strings.LastIndexFunc":                                "strings",
+	"strings.Map":                                          "strings",
+	"strings.NewReader":                                    "strings",
+	"strings.NewReplacer":                                  "strings",
+	"strings.Reader":                                       "strings",
+	"strings.Repeat":                                       "strings",
+	"strings.Replace":                                      "strings",
+	"strings.Replacer":                                     "strings",
+	"strings.Split":                                        "strings",
+	"strings.SplitAfter":                                   "strings",
+	"strings.SplitAfterN":                                  "strings",
+	"strings.SplitN":                                       "strings",
+	"strings.Title":                                        "strings",
+	"strings.ToLower":                                      "strings",
+	"strings.ToLowerSpecial":                               "strings",
+	"strings.ToTitle":                                      "strings",
+	"strings.ToTitleSpecial":                               "strings",
+	"strings.ToUpper":                                      "strings",
+	"strings.ToUpperSpecial":                               "strings",
+	"strings.Trim":                                         "strings",
+	"strings.TrimFunc":                                     "strings",
+	"strings.TrimLeft":                                     "strings",
+	"strings.TrimLeftFunc":                                 "strings",
+	"strings.TrimPrefix":                                   "strings",
+	"strings.TrimRight":                                    "strings",
+	"strings.TrimRightFunc":                                "strings",
+	"strings.TrimSpace":                                    "strings",
+	"strings.TrimSuffix":                                   "strings",
+	"subtle.ConstantTimeByteEq":                            "crypto/subtle",
+	"subtle.ConstantTimeCompare":                           "crypto/subtle",
+	"subtle.ConstantTimeCopy":                              "crypto/subtle",
+	"subtle.ConstantTimeEq":                                "crypto/subtle",
+	"subtle.ConstantTimeLessOrEq":                          "crypto/subtle",
+	"subtle.ConstantTimeSelect":                            "crypto/subtle",
+	"suffixarray.Index":                                    "index/suffixarray",
+	"suffixarray.New":                                      "index/suffixarray",
+	"sync.Cond":                                            "sync",
+	"sync.Locker":                                          "sync",
+	"sync.Mutex":                                           "sync",
+	"sync.NewCond":                                         "sync",
+	"sync.Once":                                            "sync",
+	"sync.RWMutex":                                         "sync",
+	"sync.WaitGroup":                                       "sync",
+	"syntax.ClassNL":                                       "regexp/syntax",
+	"syntax.Compile":                                       "regexp/syntax",
+	"syntax.DotNL":                                         "regexp/syntax",
+	"syntax.EmptyBeginLine":                                "regexp/syntax",
+	"syntax.EmptyBeginText":                                "regexp/syntax",
+	"syntax.EmptyEndLine":                                  "regexp/syntax",
+	"syntax.EmptyEndText":                                  "regexp/syntax",
+	"syntax.EmptyNoWordBoundary":                           "regexp/syntax",
+	"syntax.EmptyOp":                                       "regexp/syntax",
+	"syntax.EmptyOpContext":                                "regexp/syntax",
+	"syntax.EmptyWordBoundary":                             "regexp/syntax",
+	"syntax.ErrInternalError":                              "regexp/syntax",
+	"syntax.ErrInvalidCharClass":                           "regexp/syntax",
+	"syntax.ErrInvalidCharRange":                           "regexp/syntax",
+	"syntax.ErrInvalidEscape":                              "regexp/syntax",
+	"syntax.ErrInvalidNamedCapture":                        "regexp/syntax",
+	"syntax.ErrInvalidPerlOp":                              "regexp/syntax",
+	"syntax.ErrInvalidRepeatOp":                            "regexp/syntax",
+	"syntax.ErrInvalidRepeatSize":                          "regexp/syntax",
+	"syntax.ErrInvalidUTF8":                                "regexp/syntax",
+	"syntax.ErrMissingBracket":                             "regexp/syntax",
+	"syntax.ErrMissingParen":                               "regexp/syntax",
+	"syntax.ErrMissingRepeatArgument":                      "regexp/syntax",
+	"syntax.ErrTrailingBackslash":                          "regexp/syntax",
+	"syntax.ErrUnexpectedParen":                            "regexp/syntax",
+	"syntax.Error":                                         "regexp/syntax",
+	"syntax.ErrorCode":                                     "regexp/syntax",
+	"syntax.Flags":                                         "regexp/syntax",
+	"syntax.FoldCase":                                      "regexp/syntax",
+	"syntax.Inst":                                          "regexp/syntax",
+	"syntax.InstAlt":                                       "regexp/syntax",
+	"syntax.InstAltMatch":                                  "regexp/syntax",
+	"syntax.InstCapture":                                   "regexp/syntax",
+	"syntax.InstEmptyWidth":                                "regexp/syntax",
+	"syntax.InstFail":                                      "regexp/syntax",
+	"syntax.InstMatch":                                     "regexp/syntax",
+	"syntax.InstNop":                                       "regexp/syntax",
+	"syntax.InstOp":                                        "regexp/syntax",
+	"syntax.InstRune":                                      "regexp/syntax",
+	"syntax.InstRune1":                                     "regexp/syntax",
+	"syntax.InstRuneAny":                                   "regexp/syntax",
+	"syntax.InstRuneAnyNotNL":                              "regexp/syntax",
+	"syntax.IsWordChar":                                    "regexp/syntax",
+	"syntax.Literal":                                       "regexp/syntax",
+	"syntax.MatchNL":                                       "regexp/syntax",
+	"syntax.NonGreedy":                                     "regexp/syntax",
+	"syntax.OneLine":                                       "regexp/syntax",
+	"syntax.Op":                                            "regexp/syntax",
+	"syntax.OpAlternate":                                   "regexp/syntax",
+	"syntax.OpAnyChar":                                     "regexp/syntax",
+	"syntax.OpAnyCharNotNL":                                "regexp/syntax",
+	"syntax.OpBeginLine":                                   "regexp/syntax",
+	"syntax.OpBeginText":                                   "regexp/syntax",
+	"syntax.OpCapture":                                     "regexp/syntax",
+	"syntax.OpCharClass":                                   "regexp/syntax",
+	"syntax.OpConcat":                                      "regexp/syntax",
+	"syntax.OpEmptyMatch":                                  "regexp/syntax",
+	"syntax.OpEndLine":                                     "regexp/syntax",
+	"syntax.OpEndText":                                     "regexp/syntax",
+	"syntax.OpLiteral":                                     "regexp/syntax",
+	"syntax.OpNoMatch":                                     "regexp/syntax",
+	"syntax.OpNoWordBoundary":                              "regexp/syntax",
+	"syntax.OpPlus":                                        "regexp/syntax",
+	"syntax.OpQuest":                                       "regexp/syntax",
+	"syntax.OpRepeat":                                      "regexp/syntax",
+	"syntax.OpStar":                                        "regexp/syntax",
+	"syntax.OpWordBoundary":                                "regexp/syntax",
+	"syntax.POSIX":                                         "regexp/syntax",
+	"syntax.Parse":                                         "regexp/syntax",
+	"syntax.Perl":                                          "regexp/syntax",
+	"syntax.PerlX":                                         "regexp/syntax",
+	"syntax.Prog":                                          "regexp/syntax",
+	"syntax.Regexp":                                        "regexp/syntax",
+	"syntax.Simple":                                        "regexp/syntax",
+	"syntax.UnicodeGroups":                                 "regexp/syntax",
+	"syntax.WasDollar":                                     "regexp/syntax",
+	"syscall.AF_ALG":                                       "syscall",
+	"syscall.AF_APPLETALK":                                 "syscall",
+	"syscall.AF_ARP":                                       "syscall",
+	"syscall.AF_ASH":                                       "syscall",
+	"syscall.AF_ATM":                                       "syscall",
+	"syscall.AF_ATMPVC":                                    "syscall",
+	"syscall.AF_ATMSVC":                                    "syscall",
+	"syscall.AF_AX25":                                      "syscall",
+	"syscall.AF_BLUETOOTH":                                 "syscall",
+	"syscall.AF_BRIDGE":                                    "syscall",
+	"syscall.AF_CAIF":                                      "syscall",
+	"syscall.AF_CAN":                                       "syscall",
+	"syscall.AF_CCITT":                                     "syscall",
+	"syscall.AF_CHAOS":                                     "syscall",
+	"syscall.AF_CNT":                                       "syscall",
+	"syscall.AF_COIP":                                      "syscall",
+	"syscall.AF_DATAKIT":                                   "syscall",
+	"syscall.AF_DECnet":                                    "syscall",
+	"syscall.AF_DLI":                                       "syscall",
+	"syscall.AF_E164":                                      "syscall",
+	"syscall.AF_ECMA":                                      "syscall",
+	"syscall.AF_ECONET":                                    "syscall",
+	"syscall.AF_ENCAP":                                     "syscall",
+	"syscall.AF_FILE":                                      "syscall",
+	"syscall.AF_HYLINK":                                    "syscall",
+	"syscall.AF_IEEE80211":                                 "syscall",
+	"syscall.AF_IEEE802154":                                "syscall",
+	"syscall.AF_IMPLINK":                                   "syscall",
+	"syscall.AF_INET":                                      "syscall",
+	"syscall.AF_INET6":                                     "syscall",
+	"syscall.AF_IPX":                                       "syscall",
+	"syscall.AF_IRDA":                                      "syscall",
+	"syscall.AF_ISDN":                                      "syscall",
+	"syscall.AF_ISO":                                       "syscall",
+	"syscall.AF_IUCV":                                      "syscall",
+	"syscall.AF_KEY":                                       "syscall",
+	"syscall.AF_LAT":                                       "syscall",
+	"syscall.AF_LINK":                                      "syscall",
+	"syscall.AF_LLC":                                       "syscall",
+	"syscall.AF_LOCAL":                                     "syscall",
+	"syscall.AF_MAX":                                       "syscall",
+	"syscall.AF_MPLS":                                      "syscall",
+	"syscall.AF_NATM":                                      "syscall",
+	"syscall.AF_NDRV":                                      "syscall",
+	"syscall.AF_NETBEUI":                                   "syscall",
+	"syscall.AF_NETBIOS":                                   "syscall",
+	"syscall.AF_NETGRAPH":                                  "syscall",
+	"syscall.AF_NETLINK":                                   "syscall",
+	"syscall.AF_NETROM":                                    "syscall",
+	"syscall.AF_NS":                                        "syscall",
+	"syscall.AF_OROUTE":                                    "syscall",
+	"syscall.AF_OSI":                                       "syscall",
+	"syscall.AF_PACKET":                                    "syscall",
+	"syscall.AF_PHONET":                                    "syscall",
+	"syscall.AF_PPP":                                       "syscall",
+	"syscall.AF_PPPOX":                                     "syscall",
+	"syscall.AF_PUP":                                       "syscall",
+	"syscall.AF_RDS":                                       "syscall",
+	"syscall.AF_RESERVED_36":                               "syscall",
+	"syscall.AF_ROSE":                                      "syscall",
+	"syscall.AF_ROUTE":                                     "syscall",
+	"syscall.AF_RXRPC":                                     "syscall",
+	"syscall.AF_SCLUSTER":                                  "syscall",
+	"syscall.AF_SECURITY":                                  "syscall",
+	"syscall.AF_SIP":                                       "syscall",
+	"syscall.AF_SLOW":                                      "syscall",
+	"syscall.AF_SNA":                                       "syscall",
+	"syscall.AF_SYSTEM":                                    "syscall",
+	"syscall.AF_TIPC":                                      "syscall",
+	"syscall.AF_UNIX":                                      "syscall",
+	"syscall.AF_UNSPEC":                                    "syscall",
+	"syscall.AF_VENDOR00":                                  "syscall",
+	"syscall.AF_VENDOR01":                                  "syscall",
+	"syscall.AF_VENDOR02":                                  "syscall",
+	"syscall.AF_VENDOR03":                                  "syscall",
+	"syscall.AF_VENDOR04":                                  "syscall",
+	"syscall.AF_VENDOR05":                                  "syscall",
+	"syscall.AF_VENDOR06":                                  "syscall",
+	"syscall.AF_VENDOR07":                                  "syscall",
+	"syscall.AF_VENDOR08":                                  "syscall",
+	"syscall.AF_VENDOR09":                                  "syscall",
+	"syscall.AF_VENDOR10":                                  "syscall",
+	"syscall.AF_VENDOR11":                                  "syscall",
+	"syscall.AF_VENDOR12":                                  "syscall",
+	"syscall.AF_VENDOR13":                                  "syscall",
+	"syscall.AF_VENDOR14":                                  "syscall",
+	"syscall.AF_VENDOR15":                                  "syscall",
+	"syscall.AF_VENDOR16":                                  "syscall",
+	"syscall.AF_VENDOR17":                                  "syscall",
+	"syscall.AF_VENDOR18":                                  "syscall",
+	"syscall.AF_VENDOR19":                                  "syscall",
+	"syscall.AF_VENDOR20":                                  "syscall",
+	"syscall.AF_VENDOR21":                                  "syscall",
+	"syscall.AF_VENDOR22":                                  "syscall",
+	"syscall.AF_VENDOR23":                                  "syscall",
+	"syscall.AF_VENDOR24":                                  "syscall",
+	"syscall.AF_VENDOR25":                                  "syscall",
+	"syscall.AF_VENDOR26":                                  "syscall",
+	"syscall.AF_VENDOR27":                                  "syscall",
+	"syscall.AF_VENDOR28":                                  "syscall",
+	"syscall.AF_VENDOR29":                                  "syscall",
+	"syscall.AF_VENDOR30":                                  "syscall",
+	"syscall.AF_VENDOR31":                                  "syscall",
+	"syscall.AF_VENDOR32":                                  "syscall",
+	"syscall.AF_VENDOR33":                                  "syscall",
+	"syscall.AF_VENDOR34":                                  "syscall",
+	"syscall.AF_VENDOR35":                                  "syscall",
+	"syscall.AF_VENDOR36":                                  "syscall",
+	"syscall.AF_VENDOR37":                                  "syscall",
+	"syscall.AF_VENDOR38":                                  "syscall",
+	"syscall.AF_VENDOR39":                                  "syscall",
+	"syscall.AF_VENDOR40":                                  "syscall",
+	"syscall.AF_VENDOR41":                                  "syscall",
+	"syscall.AF_VENDOR42":                                  "syscall",
+	"syscall.AF_VENDOR43":                                  "syscall",
+	"syscall.AF_VENDOR44":                                  "syscall",
+	"syscall.AF_VENDOR45":                                  "syscall",
+	"syscall.AF_VENDOR46":                                  "syscall",
+	"syscall.AF_VENDOR47":                                  "syscall",
+	"syscall.AF_WANPIPE":                                   "syscall",
+	"syscall.AF_X25":                                       "syscall",
+	"syscall.AI_CANONNAME":                                 "syscall",
+	"syscall.AI_NUMERICHOST":                               "syscall",
+	"syscall.AI_PASSIVE":                                   "syscall",
+	"syscall.APPLICATION_ERROR":                            "syscall",
+	"syscall.ARPHRD_ADAPT":                                 "syscall",
+	"syscall.ARPHRD_APPLETLK":                              "syscall",
+	"syscall.ARPHRD_ARCNET":                                "syscall",
+	"syscall.ARPHRD_ASH":                                   "syscall",
+	"syscall.ARPHRD_ATM":                                   "syscall",
+	"syscall.ARPHRD_AX25":                                  "syscall",
+	"syscall.ARPHRD_BIF":                                   "syscall",
+	"syscall.ARPHRD_CHAOS":                                 "syscall",
+	"syscall.ARPHRD_CISCO":                                 "syscall",
+	"syscall.ARPHRD_CSLIP":                                 "syscall",
+	"syscall.ARPHRD_CSLIP6":                                "syscall",
+	"syscall.ARPHRD_DDCMP":                                 "syscall",
+	"syscall.ARPHRD_DLCI":                                  "syscall",
+	"syscall.ARPHRD_ECONET":                                "syscall",
+	"syscall.ARPHRD_EETHER":                                "syscall",
+	"syscall.ARPHRD_ETHER":                                 "syscall",
+	"syscall.ARPHRD_EUI64":                                 "syscall",
+	"syscall.ARPHRD_FCAL":                                  "syscall",
+	"syscall.ARPHRD_FCFABRIC":                              "syscall",
+	"syscall.ARPHRD_FCPL":                                  "syscall",
+	"syscall.ARPHRD_FCPP":                                  "syscall",
+	"syscall.ARPHRD_FDDI":                                  "syscall",
+	"syscall.ARPHRD_FRAD":                                  "syscall",
+	"syscall.ARPHRD_FRELAY":                                "syscall",
+	"syscall.ARPHRD_HDLC":                                  "syscall",
+	"syscall.ARPHRD_HIPPI":                                 "syscall",
+	"syscall.ARPHRD_HWX25":                                 "syscall",
+	"syscall.ARPHRD_IEEE1394":                              "syscall",
+	"syscall.ARPHRD_IEEE802":                               "syscall",
+	"syscall.ARPHRD_IEEE80211":                             "syscall",
+	"syscall.ARPHRD_IEEE80211_PRISM":                       "syscall",
+	"syscall.ARPHRD_IEEE80211_RADIOTAP":                    "syscall",
+	"syscall.ARPHRD_IEEE802154":                            "syscall",
+	"syscall.ARPHRD_IEEE802154_PHY":                        "syscall",
+	"syscall.ARPHRD_IEEE802_TR":                            "syscall",
+	"syscall.ARPHRD_INFINIBAND":                            "syscall",
+	"syscall.ARPHRD_IPDDP":                                 "syscall",
+	"syscall.ARPHRD_IPGRE":                                 "syscall",
+	"syscall.ARPHRD_IRDA":                                  "syscall",
+	"syscall.ARPHRD_LAPB":                                  "syscall",
+	"syscall.ARPHRD_LOCALTLK":                              "syscall",
+	"syscall.ARPHRD_LOOPBACK":                              "syscall",
+	"syscall.ARPHRD_METRICOM":                              "syscall",
+	"syscall.ARPHRD_NETROM":                                "syscall",
+	"syscall.ARPHRD_NONE":                                  "syscall",
+	"syscall.ARPHRD_PIMREG":                                "syscall",
+	"syscall.ARPHRD_PPP":                                   "syscall",
+	"syscall.ARPHRD_PRONET":                                "syscall",
+	"syscall.ARPHRD_RAWHDLC":                               "syscall",
+	"syscall.ARPHRD_ROSE":                                  "syscall",
+	"syscall.ARPHRD_RSRVD":                                 "syscall",
+	"syscall.ARPHRD_SIT":                                   "syscall",
+	"syscall.ARPHRD_SKIP":                                  "syscall",
+	"syscall.ARPHRD_SLIP":                                  "syscall",
+	"syscall.ARPHRD_SLIP6":                                 "syscall",
+	"syscall.ARPHRD_STRIP":                                 "syscall",
+	"syscall.ARPHRD_TUNNEL":                                "syscall",
+	"syscall.ARPHRD_TUNNEL6":                               "syscall",
+	"syscall.ARPHRD_VOID":                                  "syscall",
+	"syscall.ARPHRD_X25":                                   "syscall",
+	"syscall.AUTHTYPE_CLIENT":                              "syscall",
+	"syscall.AUTHTYPE_SERVER":                              "syscall",
+	"syscall.Accept":                                       "syscall",
+	"syscall.Accept4":                                      "syscall",
+	"syscall.AcceptEx":                                     "syscall",
+	"syscall.Access":                                       "syscall",
+	"syscall.Acct":                                         "syscall",
+	"syscall.AddrinfoW":                                    "syscall",
+	"syscall.Adjtime":                                      "syscall",
+	"syscall.Adjtimex":                                     "syscall",
+	"syscall.AttachLsf":                                    "syscall",
+	"syscall.B0":                                           "syscall",
+	"syscall.B1000000":                                     "syscall",
+	"syscall.B110":                                         "syscall",
+	"syscall.B115200":                                      "syscall",
+	"syscall.B1152000":                                     "syscall",
+	"syscall.B1200":                                        "syscall",
+	"syscall.B134":                                         "syscall",
+	"syscall.B14400":                                       "syscall",
+	"syscall.B150":                                         "syscall",
+	"syscall.B1500000":                                     "syscall",
+	"syscall.B1800":                                        "syscall",
+	"syscall.B19200":                                       "syscall",
+	"syscall.B200":                                         "syscall",
+	"syscall.B2000000":                                     "syscall",
+	"syscall.B230400":                                      "syscall",
+	"syscall.B2400":                                        "syscall",
+	"syscall.B2500000":                                     "syscall",
+	"syscall.B28800":                                       "syscall",
+	"syscall.B300":                                         "syscall",
+	"syscall.B3000000":                                     "syscall",
+	"syscall.B3500000":                                     "syscall",
+	"syscall.B38400":                                       "syscall",
+	"syscall.B4000000":                                     "syscall",
+	"syscall.B460800":                                      "syscall",
+	"syscall.B4800":                                        "syscall",
+	"syscall.B50":                                          "syscall",
+	"syscall.B500000":                                      "syscall",
+	"syscall.B57600":                                       "syscall",
+	"syscall.B576000":                                      "syscall",
+	"syscall.B600":                                         "syscall",
+	"syscall.B7200":                                        "syscall",
+	"syscall.B75":                                          "syscall",
+	"syscall.B76800":                                       "syscall",
+	"syscall.B921600":                                      "syscall",
+	"syscall.B9600":                                        "syscall",
+	"syscall.BASE_PROTOCOL":                                "syscall",
+	"syscall.BIOCFEEDBACK":                                 "syscall",
+	"syscall.BIOCFLUSH":                                    "syscall",
+	"syscall.BIOCGBLEN":                                    "syscall",
+	"syscall.BIOCGDIRECTION":                               "syscall",
+	"syscall.BIOCGDIRFILT":                                 "syscall",
+	"syscall.BIOCGDLT":                                     "syscall",
+	"syscall.BIOCGDLTLIST":                                 "syscall",
+	"syscall.BIOCGETBUFMODE":                               "syscall",
+	"syscall.BIOCGETIF":                                    "syscall",
+	"syscall.BIOCGETZMAX":                                  "syscall",
+	"syscall.BIOCGFEEDBACK":                                "syscall",
+	"syscall.BIOCGFILDROP":                                 "syscall",
+	"syscall.BIOCGHDRCMPLT":                                "syscall",
+	"syscall.BIOCGRSIG":                                    "syscall",
+	"syscall.BIOCGRTIMEOUT":                                "syscall",
+	"syscall.BIOCGSEESENT":                                 "syscall",
+	"syscall.BIOCGSTATS":                                   "syscall",
+	"syscall.BIOCGSTATSOLD":                                "syscall",
+	"syscall.BIOCGTSTAMP":                                  "syscall",
+	"syscall.BIOCIMMEDIATE":                                "syscall",
+	"syscall.BIOCLOCK":                                     "syscall",
+	"syscall.BIOCPROMISC":                                  "syscall",
+	"syscall.BIOCROTZBUF":                                  "syscall",
+	"syscall.BIOCSBLEN":                                    "syscall",
+	"syscall.BIOCSDIRECTION":                               "syscall",
+	"syscall.BIOCSDIRFILT":                                 "syscall",
+	"syscall.BIOCSDLT":                                     "syscall",
+	"syscall.BIOCSETBUFMODE":                               "syscall",
+	"syscall.BIOCSETF":                                     "syscall",
+	"syscall.BIOCSETFNR":                                   "syscall",
+	"syscall.BIOCSETIF":                                    "syscall",
+	"syscall.BIOCSETWF":                                    "syscall",
+	"syscall.BIOCSETZBUF":                                  "syscall",
+	"syscall.BIOCSFEEDBACK":                                "syscall",
+	"syscall.BIOCSFILDROP":                                 "syscall",
+	"syscall.BIOCSHDRCMPLT":                                "syscall",
+	"syscall.BIOCSRSIG":                                    "syscall",
+	"syscall.BIOCSRTIMEOUT":                                "syscall",
+	"syscall.BIOCSSEESENT":                                 "syscall",
+	"syscall.BIOCSTCPF":                                    "syscall",
+	"syscall.BIOCSTSTAMP":                                  "syscall",
+	"syscall.BIOCSUDPF":                                    "syscall",
+	"syscall.BIOCVERSION":                                  "syscall",
+	"syscall.BPF_A":                                        "syscall",
+	"syscall.BPF_ABS":                                      "syscall",
+	"syscall.BPF_ADD":                                      "syscall",
+	"syscall.BPF_ALIGNMENT":                                "syscall",
+	"syscall.BPF_ALIGNMENT32":                              "syscall",
+	"syscall.BPF_ALU":                                      "syscall",
+	"syscall.BPF_AND":                                      "syscall",
+	"syscall.BPF_B":                                        "syscall",
+	"syscall.BPF_BUFMODE_BUFFER":                           "syscall",
+	"syscall.BPF_BUFMODE_ZBUF":                             "syscall",
+	"syscall.BPF_DFLTBUFSIZE":                              "syscall",
+	"syscall.BPF_DIRECTION_IN":                             "syscall",
+	"syscall.BPF_DIRECTION_OUT":                            "syscall",
+	"syscall.BPF_DIV":                                      "syscall",
+	"syscall.BPF_H":                                        "syscall",
+	"syscall.BPF_IMM":                                      "syscall",
+	"syscall.BPF_IND":                                      "syscall",
+	"syscall.BPF_JA":                                       "syscall",
+	"syscall.BPF_JEQ":                                      "syscall",
+	"syscall.BPF_JGE":                                      "syscall",
+	"syscall.BPF_JGT":                                      "syscall",
+	"syscall.BPF_JMP":                                      "syscall",
+	"syscall.BPF_JSET":                                     "syscall",
+	"syscall.BPF_K":                                        "syscall",
+	"syscall.BPF_LD":                                       "syscall",
+	"syscall.BPF_LDX":                                      "syscall",
+	"syscall.BPF_LEN":                                      "syscall",
+	"syscall.BPF_LSH":                                      "syscall",
+	"syscall.BPF_MAJOR_VERSION":                            "syscall",
+	"syscall.BPF_MAXBUFSIZE":                               "syscall",
+	"syscall.BPF_MAXINSNS":                                 "syscall",
+	"syscall.BPF_MEM":                                      "syscall",
+	"syscall.BPF_MEMWORDS":                                 "syscall",
+	"syscall.BPF_MINBUFSIZE":                               "syscall",
+	"syscall.BPF_MINOR_VERSION":                            "syscall",
+	"syscall.BPF_MISC":                                     "syscall",
+	"syscall.BPF_MSH":                                      "syscall",
+	"syscall.BPF_MUL":                                      "syscall",
+	"syscall.BPF_NEG":                                      "syscall",
+	"syscall.BPF_OR":                                       "syscall",
+	"syscall.BPF_RELEASE":                                  "syscall",
+	"syscall.BPF_RET":                                      "syscall",
+	"syscall.BPF_RSH":                                      "syscall",
+	"syscall.BPF_ST":                                       "syscall",
+	"syscall.BPF_STX":                                      "syscall",
+	"syscall.BPF_SUB":                                      "syscall",
+	"syscall.BPF_TAX":                                      "syscall",
+	"syscall.BPF_TXA":                                      "syscall",
+	"syscall.BPF_T_BINTIME":                                "syscall",
+	"syscall.BPF_T_BINTIME_FAST":                           "syscall",
+	"syscall.BPF_T_BINTIME_MONOTONIC":                      "syscall",
+	"syscall.BPF_T_BINTIME_MONOTONIC_FAST":                 "syscall",
+	"syscall.BPF_T_FAST":                                   "syscall",
+	"syscall.BPF_T_FLAG_MASK":                              "syscall",
+	"syscall.BPF_T_FORMAT_MASK":                            "syscall",
+	"syscall.BPF_T_MICROTIME":                              "syscall",
+	"syscall.BPF_T_MICROTIME_FAST":                         "syscall",
+	"syscall.BPF_T_MICROTIME_MONOTONIC":                    "syscall",
+	"syscall.BPF_T_MICROTIME_MONOTONIC_FAST":               "syscall",
+	"syscall.BPF_T_MONOTONIC":                              "syscall",
+	"syscall.BPF_T_MONOTONIC_FAST":                         "syscall",
+	"syscall.BPF_T_NANOTIME":                               "syscall",
+	"syscall.BPF_T_NANOTIME_FAST":                          "syscall",
+	"syscall.BPF_T_NANOTIME_MONOTONIC":                     "syscall",
+	"syscall.BPF_T_NANOTIME_MONOTONIC_FAST":                "syscall",
+	"syscall.BPF_T_NONE":                                   "syscall",
+	"syscall.BPF_T_NORMAL":                                 "syscall",
+	"syscall.BPF_W":                                        "syscall",
+	"syscall.BPF_X":                                        "syscall",
+	"syscall.BRKINT":                                       "syscall",
+	"syscall.Bind":                                         "syscall",
+	"syscall.BindToDevice":                                 "syscall",
+	"syscall.BpfBuflen":                                    "syscall",
+	"syscall.BpfDatalink":                                  "syscall",
+	"syscall.BpfHdr":                                       "syscall",
+	"syscall.BpfHeadercmpl":                                "syscall",
+	"syscall.BpfInsn":                                      "syscall",
+	"syscall.BpfInterface":                                 "syscall",
+	"syscall.BpfJump":                                      "syscall",
+	"syscall.BpfProgram":                                   "syscall",
+	"syscall.BpfStat":                                      "syscall",
+	"syscall.BpfStats":                                     "syscall",
+	"syscall.BpfStmt":                                      "syscall",
+	"syscall.BpfTimeout":                                   "syscall",
+	"syscall.BpfTimeval":                                   "syscall",
+	"syscall.BpfVersion":                                   "syscall",
+	"syscall.BpfZbuf":                                      "syscall",
+	"syscall.BpfZbufHeader":                                "syscall",
+	"syscall.ByHandleFileInformation":                      "syscall",
+	"syscall.BytePtrFromString":                            "syscall",
+	"syscall.ByteSliceFromString":                          "syscall",
+	"syscall.CCR0_FLUSH":                                   "syscall",
+	"syscall.CERT_CHAIN_POLICY_AUTHENTICODE":               "syscall",
+	"syscall.CERT_CHAIN_POLICY_AUTHENTICODE_TS":            "syscall",
+	"syscall.CERT_CHAIN_POLICY_BASE":                       "syscall",
+	"syscall.CERT_CHAIN_POLICY_BASIC_CONSTRAINTS":          "syscall",
+	"syscall.CERT_CHAIN_POLICY_EV":                         "syscall",
+	"syscall.CERT_CHAIN_POLICY_MICROSOFT_ROOT":             "syscall",
+	"syscall.CERT_CHAIN_POLICY_NT_AUTH":                    "syscall",
+	"syscall.CERT_CHAIN_POLICY_SSL":                        "syscall",
+	"syscall.CERT_E_CN_NO_MATCH":                           "syscall",
+	"syscall.CERT_E_EXPIRED":                               "syscall",
+	"syscall.CERT_E_PURPOSE":                               "syscall",
+	"syscall.CERT_E_ROLE":                                  "syscall",
+	"syscall.CERT_E_UNTRUSTEDROOT":                         "syscall",
+	"syscall.CERT_STORE_ADD_ALWAYS":                        "syscall",
+	"syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG":  "syscall",
+	"syscall.CERT_STORE_PROV_MEMORY":                       "syscall",
+	"syscall.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT":      "syscall",
+	"syscall.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT":   "syscall",
+	"syscall.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT": "syscall",
+	"syscall.CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT":    "syscall",
+	"syscall.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT": "syscall",
+	"syscall.CERT_TRUST_INVALID_BASIC_CONSTRAINTS":         "syscall",
+	"syscall.CERT_TRUST_INVALID_EXTENSION":                 "syscall",
+	"syscall.CERT_TRUST_INVALID_NAME_CONSTRAINTS":          "syscall",
+	"syscall.CERT_TRUST_INVALID_POLICY_CONSTRAINTS":        "syscall",
+	"syscall.CERT_TRUST_IS_CYCLIC":                         "syscall",
+	"syscall.CERT_TRUST_IS_EXPLICIT_DISTRUST":              "syscall",
+	"syscall.CERT_TRUST_IS_NOT_SIGNATURE_VALID":            "syscall",
+	"syscall.CERT_TRUST_IS_NOT_TIME_VALID":                 "syscall",
+	"syscall.CERT_TRUST_IS_NOT_VALID_FOR_USAGE":            "syscall",
+	"syscall.CERT_TRUST_IS_OFFLINE_REVOCATION":             "syscall",
+	"syscall.CERT_TRUST_IS_REVOKED":                        "syscall",
+	"syscall.CERT_TRUST_IS_UNTRUSTED_ROOT":                 "syscall",
+	"syscall.CERT_TRUST_NO_ERROR":                          "syscall",
+	"syscall.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY":          "syscall",
+	"syscall.CERT_TRUST_REVOCATION_STATUS_UNKNOWN":         "syscall",
+	"syscall.CFLUSH":                                       "syscall",
+	"syscall.CLOCAL":                                       "syscall",
+	"syscall.CLONE_CHILD_CLEARTID":                         "syscall",
+	"syscall.CLONE_CHILD_SETTID":                           "syscall",
+	"syscall.CLONE_DETACHED":                               "syscall",
+	"syscall.CLONE_FILES":                                  "syscall",
+	"syscall.CLONE_FS":                                     "syscall",
+	"syscall.CLONE_IO":                                     "syscall",
+	"syscall.CLONE_NEWIPC":                                 "syscall",
+	"syscall.CLONE_NEWNET":                                 "syscall",
+	"syscall.CLONE_NEWNS":                                  "syscall",
+	"syscall.CLONE_NEWPID":                                 "syscall",
+	"syscall.CLONE_NEWUSER":                                "syscall",
+	"syscall.CLONE_NEWUTS":                                 "syscall",
+	"syscall.CLONE_PARENT":                                 "syscall",
+	"syscall.CLONE_PARENT_SETTID":                          "syscall",
+	"syscall.CLONE_PTRACE":                                 "syscall",
+	"syscall.CLONE_SETTLS":                                 "syscall",
+	"syscall.CLONE_SIGHAND":                                "syscall",
+	"syscall.CLONE_SYSVSEM":                                "syscall",
+	"syscall.CLONE_THREAD":                                 "syscall",
+	"syscall.CLONE_UNTRACED":                               "syscall",
+	"syscall.CLONE_VFORK":                                  "syscall",
+	"syscall.CLONE_VM":                                     "syscall",
+	"syscall.CPUID_CFLUSH":                                 "syscall",
+	"syscall.CREAD":                                        "syscall",
+	"syscall.CREATE_ALWAYS":                                "syscall",
+	"syscall.CREATE_NEW":                                   "syscall",
+	"syscall.CREATE_NEW_PROCESS_GROUP":                     "syscall",
+	"syscall.CREATE_UNICODE_ENVIRONMENT":                   "syscall",
+	"syscall.CRYPT_DEFAULT_CONTAINER_OPTIONAL":             "syscall",
+	"syscall.CRYPT_DELETEKEYSET":                           "syscall",
+	"syscall.CRYPT_MACHINE_KEYSET":                         "syscall",
+	"syscall.CRYPT_NEWKEYSET":                              "syscall",
+	"syscall.CRYPT_SILENT":                                 "syscall",
+	"syscall.CRYPT_VERIFYCONTEXT":                          "syscall",
+	"syscall.CS5":                                          "syscall",
+	"syscall.CS6":                                          "syscall",
+	"syscall.CS7":                                          "syscall",
+	"syscall.CS8":                                          "syscall",
+	"syscall.CSIZE":                                        "syscall",
+	"syscall.CSTART":                                       "syscall",
+	"syscall.CSTATUS":                                      "syscall",
+	"syscall.CSTOP":                                        "syscall",
+	"syscall.CSTOPB":                                       "syscall",
+	"syscall.CSUSP":                                        "syscall",
+	"syscall.CTL_MAXNAME":                                  "syscall",
+	"syscall.CTL_NET":                                      "syscall",
+	"syscall.CTL_QUERY":                                    "syscall",
+	"syscall.CTRL_BREAK_EVENT":                             "syscall",
+	"syscall.CTRL_C_EVENT":                                 "syscall",
+	"syscall.CancelIo":                                     "syscall",
+	"syscall.CancelIoEx":                                   "syscall",
+	"syscall.CertAddCertificateContextToStore":             "syscall",
+	"syscall.CertChainContext":                             "syscall",
+	"syscall.CertChainElement":                             "syscall",
+	"syscall.CertChainPara":                                "syscall",
+	"syscall.CertChainPolicyPara":                          "syscall",
+	"syscall.CertChainPolicyStatus":                        "syscall",
+	"syscall.CertCloseStore":                               "syscall",
+	"syscall.CertContext":                                  "syscall",
+	"syscall.CertCreateCertificateContext":                 "syscall",
+	"syscall.CertEnhKeyUsage":                              "syscall",
+	"syscall.CertEnumCertificatesInStore":                  "syscall",
+	"syscall.CertFreeCertificateChain":                     "syscall",
+	"syscall.CertFreeCertificateContext":                   "syscall",
+	"syscall.CertGetCertificateChain":                      "syscall",
+	"syscall.CertOpenStore":                                "syscall",
+	"syscall.CertOpenSystemStore":                          "syscall",
+	"syscall.CertRevocationInfo":                           "syscall",
+	"syscall.CertSimpleChain":                              "syscall",
+	"syscall.CertTrustStatus":                              "syscall",
+	"syscall.CertUsageMatch":                               "syscall",
+	"syscall.CertVerifyCertificateChainPolicy":             "syscall",
+	"syscall.Chdir":                                        "syscall",
+	"syscall.CheckBpfVersion":                              "syscall",
+	"syscall.Chflags":                                      "syscall",
+	"syscall.Chmod":                                        "syscall",
+	"syscall.Chown":                                        "syscall",
+	"syscall.Chroot":                                       "syscall",
+	"syscall.Clearenv":                                     "syscall",
+	"syscall.Close":                                        "syscall",
+	"syscall.CloseHandle":                                  "syscall",
+	"syscall.CloseOnExec":                                  "syscall",
+	"syscall.Closesocket":                                  "syscall",
+	"syscall.CmsgLen":                                      "syscall",
+	"syscall.CmsgSpace":                                    "syscall",
+	"syscall.Cmsghdr":                                      "syscall",
+	"syscall.CommandLineToArgv":                            "syscall",
+	"syscall.ComputerName":                                 "syscall",
+	"syscall.Connect":                                      "syscall",
+	"syscall.ConnectEx":                                    "syscall",
+	"syscall.ConvertSidToStringSid":                        "syscall",
+	"syscall.ConvertStringSidToSid":                        "syscall",
+	"syscall.CopySid":                                      "syscall",
+	"syscall.Creat":                                        "syscall",
+	"syscall.CreateDirectory":                              "syscall",
+	"syscall.CreateFile":                                   "syscall",
+	"syscall.CreateFileMapping":                            "syscall",
+	"syscall.CreateIoCompletionPort":                       "syscall",
+	"syscall.CreatePipe":                                   "syscall",
+	"syscall.CreateProcess":                                "syscall",
+	"syscall.Credential":                                   "syscall",
+	"syscall.CryptAcquireContext":                          "syscall",
+	"syscall.CryptGenRandom":                               "syscall",
+	"syscall.CryptReleaseContext":                          "syscall",
+	"syscall.DIOCBSFLUSH":                                  "syscall",
+	"syscall.DIOCOSFPFLUSH":                                "syscall",
+	"syscall.DLL":                                          "syscall",
+	"syscall.DLLError":                                     "syscall",
+	"syscall.DLT_A429":                                     "syscall",
+	"syscall.DLT_A653_ICM":                                 "syscall",
+	"syscall.DLT_AIRONET_HEADER":                           "syscall",
+	"syscall.DLT_AOS":                                      "syscall",
+	"syscall.DLT_APPLE_IP_OVER_IEEE1394":                   "syscall",
+	"syscall.DLT_ARCNET":                                   "syscall",
+	"syscall.DLT_ARCNET_LINUX":                             "syscall",
+	"syscall.DLT_ATM_CLIP":                                 "syscall",
+	"syscall.DLT_ATM_RFC1483":                              "syscall",
+	"syscall.DLT_AURORA":                                   "syscall",
+	"syscall.DLT_AX25":                                     "syscall",
+	"syscall.DLT_AX25_KISS":                                "syscall",
+	"syscall.DLT_BACNET_MS_TP":                             "syscall",
+	"syscall.DLT_BLUETOOTH_HCI_H4":                         "syscall",
+	"syscall.DLT_BLUETOOTH_HCI_H4_WITH_PHDR":               "syscall",
+	"syscall.DLT_CAN20B":                                   "syscall",
+	"syscall.DLT_CAN_SOCKETCAN":                            "syscall",
+	"syscall.DLT_CHAOS":                                    "syscall",
+	"syscall.DLT_CHDLC":                                    "syscall",
+	"syscall.DLT_CISCO_IOS":                                "syscall",
+	"syscall.DLT_C_HDLC":                                   "syscall",
+	"syscall.DLT_C_HDLC_WITH_DIR":                          "syscall",
+	"syscall.DLT_DBUS":                                     "syscall",
+	"syscall.DLT_DECT":                                     "syscall",
+	"syscall.DLT_DOCSIS":                                   "syscall",
+	"syscall.DLT_DVB_CI":                                   "syscall",
+	"syscall.DLT_ECONET":                                   "syscall",
+	"syscall.DLT_EN10MB":                                   "syscall",
+	"syscall.DLT_EN3MB":                                    "syscall",
+	"syscall.DLT_ENC":                                      "syscall",
+	"syscall.DLT_ERF":                                      "syscall",
+	"syscall.DLT_ERF_ETH":                                  "syscall",
+	"syscall.DLT_ERF_POS":                                  "syscall",
+	"syscall.DLT_FC_2":                                     "syscall",
+	"syscall.DLT_FC_2_WITH_FRAME_DELIMS":                   "syscall",
+	"syscall.DLT_FDDI":                                     "syscall",
+	"syscall.DLT_FLEXRAY":                                  "syscall",
+	"syscall.DLT_FRELAY":                                   "syscall",
+	"syscall.DLT_FRELAY_WITH_DIR":                          "syscall",
+	"syscall.DLT_GCOM_SERIAL":                              "syscall",
+	"syscall.DLT_GCOM_T1E1":                                "syscall",
+	"syscall.DLT_GPF_F":                                    "syscall",
+	"syscall.DLT_GPF_T":                                    "syscall",
+	"syscall.DLT_GPRS_LLC":                                 "syscall",
+	"syscall.DLT_GSMTAP_ABIS":                              "syscall",
+	"syscall.DLT_GSMTAP_UM":                                "syscall",
+	"syscall.DLT_HDLC":                                     "syscall",
+	"syscall.DLT_HHDLC":                                    "syscall",
+	"syscall.DLT_HIPPI":                                    "syscall",
+	"syscall.DLT_IBM_SN":                                   "syscall",
+	"syscall.DLT_IBM_SP":                                   "syscall",
+	"syscall.DLT_IEEE802":                                  "syscall",
+	"syscall.DLT_IEEE802_11":                               "syscall",
+	"syscall.DLT_IEEE802_11_RADIO":                         "syscall",
+	"syscall.DLT_IEEE802_11_RADIO_AVS":                     "syscall",
+	"syscall.DLT_IEEE802_15_4":                             "syscall",
+	"syscall.DLT_IEEE802_15_4_LINUX":                       "syscall",
+	"syscall.DLT_IEEE802_15_4_NOFCS":                       "syscall",
+	"syscall.DLT_IEEE802_15_4_NONASK_PHY":                  "syscall",
+	"syscall.DLT_IEEE802_16_MAC_CPS":                       "syscall",
+	"syscall.DLT_IEEE802_16_MAC_CPS_RADIO":                 "syscall",
+	"syscall.DLT_IPFILTER":                                 "syscall",
+	"syscall.DLT_IPMB":                                     "syscall",
+	"syscall.DLT_IPMB_LINUX":                               "syscall",
+	"syscall.DLT_IPNET":                                    "syscall",
+	"syscall.DLT_IPOIB":                                    "syscall",
+	"syscall.DLT_IPV4":                                     "syscall",
+	"syscall.DLT_IPV6":                                     "syscall",
+	"syscall.DLT_IP_OVER_FC":                               "syscall",
+	"syscall.DLT_JUNIPER_ATM1":                             "syscall",
+	"syscall.DLT_JUNIPER_ATM2":                             "syscall",
+	"syscall.DLT_JUNIPER_ATM_CEMIC":                        "syscall",
+	"syscall.DLT_JUNIPER_CHDLC":                            "syscall",
+	"syscall.DLT_JUNIPER_ES":                               "syscall",
+	"syscall.DLT_JUNIPER_ETHER":                            "syscall",
+	"syscall.DLT_JUNIPER_FIBRECHANNEL":                     "syscall",
+	"syscall.DLT_JUNIPER_FRELAY":                           "syscall",
+	"syscall.DLT_JUNIPER_GGSN":                             "syscall",
+	"syscall.DLT_JUNIPER_ISM":                              "syscall",
+	"syscall.DLT_JUNIPER_MFR":                              "syscall",
+	"syscall.DLT_JUNIPER_MLFR":                             "syscall",
+	"syscall.DLT_JUNIPER_MLPPP":                            "syscall",
+	"syscall.DLT_JUNIPER_MONITOR":                          "syscall",
+	"syscall.DLT_JUNIPER_PIC_PEER":                         "syscall",
+	"syscall.DLT_JUNIPER_PPP":                              "syscall",
+	"syscall.DLT_JUNIPER_PPPOE":                            "syscall",
+	"syscall.DLT_JUNIPER_PPPOE_ATM":                        "syscall",
+	"syscall.DLT_JUNIPER_SERVICES":                         "syscall",
+	"syscall.DLT_JUNIPER_SRX_E2E":                          "syscall",
+	"syscall.DLT_JUNIPER_ST":                               "syscall",
+	"syscall.DLT_JUNIPER_VP":                               "syscall",
+	"syscall.DLT_JUNIPER_VS":                               "syscall",
+	"syscall.DLT_LAPB_WITH_DIR":                            "syscall",
+	"syscall.DLT_LAPD":                                     "syscall",
+	"syscall.DLT_LIN":                                      "syscall",
+	"syscall.DLT_LINUX_EVDEV":                              "syscall",
+	"syscall.DLT_LINUX_IRDA":                               "syscall",
+	"syscall.DLT_LINUX_LAPD":                               "syscall",
+	"syscall.DLT_LINUX_PPP_WITHDIRECTION":                  "syscall",
+	"syscall.DLT_LINUX_SLL":                                "syscall",
+	"syscall.DLT_LOOP":                                     "syscall",
+	"syscall.DLT_LTALK":                                    "syscall",
+	"syscall.DLT_MATCHING_MAX":                             "syscall",
+	"syscall.DLT_MATCHING_MIN":                             "syscall",
+	"syscall.DLT_MFR":                                      "syscall",
+	"syscall.DLT_MOST":                                     "syscall",
+	"syscall.DLT_MPEG_2_TS":                                "syscall",
+	"syscall.DLT_MPLS":                                     "syscall",
+	"syscall.DLT_MTP2":                                     "syscall",
+	"syscall.DLT_MTP2_WITH_PHDR":                           "syscall",
+	"syscall.DLT_MTP3":                                     "syscall",
+	"syscall.DLT_MUX27010":                                 "syscall",
+	"syscall.DLT_NETANALYZER":                              "syscall",
+	"syscall.DLT_NETANALYZER_TRANSPARENT":                  "syscall",
+	"syscall.DLT_NFC_LLCP":                                 "syscall",
+	"syscall.DLT_NFLOG":                                    "syscall",
+	"syscall.DLT_NG40":                                     "syscall",
+	"syscall.DLT_NULL":                                     "syscall",
+	"syscall.DLT_PCI_EXP":                                  "syscall",
+	"syscall.DLT_PFLOG":                                    "syscall",
+	"syscall.DLT_PFSYNC":                                   "syscall",
+	"syscall.DLT_PPI":                                      "syscall",
+	"syscall.DLT_PPP":                                      "syscall",
+	"syscall.DLT_PPP_BSDOS":                                "syscall",
+	"syscall.DLT_PPP_ETHER":                                "syscall",
+	"syscall.DLT_PPP_PPPD":                                 "syscall",
+	"syscall.DLT_PPP_SERIAL":                               "syscall",
+	"syscall.DLT_PPP_WITH_DIR":                             "syscall",
+	"syscall.DLT_PPP_WITH_DIRECTION":                       "syscall",
+	"syscall.DLT_PRISM_HEADER":                             "syscall",
+	"syscall.DLT_PRONET":                                   "syscall",
+	"syscall.DLT_RAIF1":                                    "syscall",
+	"syscall.DLT_RAW":                                      "syscall",
+	"syscall.DLT_RAWAF_MASK":                               "syscall",
+	"syscall.DLT_RIO":                                      "syscall",
+	"syscall.DLT_SCCP":                                     "syscall",
+	"syscall.DLT_SITA":                                     "syscall",
+	"syscall.DLT_SLIP":                                     "syscall",
+	"syscall.DLT_SLIP_BSDOS":                               "syscall",
+	"syscall.DLT_STANAG_5066_D_PDU":                        "syscall",
+	"syscall.DLT_SUNATM":                                   "syscall",
+	"syscall.DLT_SYMANTEC_FIREWALL":                        "syscall",
+	"syscall.DLT_TZSP":                                     "syscall",
+	"syscall.DLT_USB":                                      "syscall",
+	"syscall.DLT_USB_LINUX":                                "syscall",
+	"syscall.DLT_USB_LINUX_MMAPPED":                        "syscall",
+	"syscall.DLT_USER0":                                    "syscall",
+	"syscall.DLT_USER1":                                    "syscall",
+	"syscall.DLT_USER10":                                   "syscall",
+	"syscall.DLT_USER11":                                   "syscall",
+	"syscall.DLT_USER12":                                   "syscall",
+	"syscall.DLT_USER13":                                   "syscall",
+	"syscall.DLT_USER14":                                   "syscall",
+	"syscall.DLT_USER15":                                   "syscall",
+	"syscall.DLT_USER2":                                    "syscall",
+	"syscall.DLT_USER3":                                    "syscall",
+	"syscall.DLT_USER4":                                    "syscall",
+	"syscall.DLT_USER5":                                    "syscall",
+	"syscall.DLT_USER6":                                    "syscall",
+	"syscall.DLT_USER7":                                    "syscall",
+	"syscall.DLT_USER8":                                    "syscall",
+	"syscall.DLT_USER9":                                    "syscall",
+	"syscall.DLT_WIHART":                                   "syscall",
+	"syscall.DLT_X2E_SERIAL":                               "syscall",
+	"syscall.DLT_X2E_XORAYA":                               "syscall",
+	"syscall.DNSMXData":                                    "syscall",
+	"syscall.DNSPTRData":                                   "syscall",
+	"syscall.DNSRecord":                                    "syscall",
+	"syscall.DNSSRVData":                                   "syscall",
+	"syscall.DNSTXTData":                                   "syscall",
+	"syscall.DNS_TYPE_A":                                   "syscall",
+	"syscall.DNS_TYPE_A6":                                  "syscall",
+	"syscall.DNS_TYPE_AAAA":                                "syscall",
+	"syscall.DNS_TYPE_ADDRS":                               "syscall",
+	"syscall.DNS_TYPE_AFSDB":                               "syscall",
+	"syscall.DNS_TYPE_ALL":                                 "syscall",
+	"syscall.DNS_TYPE_ANY":                                 "syscall",
+	"syscall.DNS_TYPE_ATMA":                                "syscall",
+	"syscall.DNS_TYPE_AXFR":                                "syscall",
+	"syscall.DNS_TYPE_CERT":                                "syscall",
+	"syscall.DNS_TYPE_CNAME":                               "syscall",
+	"syscall.DNS_TYPE_DHCID":                               "syscall",
+	"syscall.DNS_TYPE_DNAME":                               "syscall",
+	"syscall.DNS_TYPE_DNSKEY":                              "syscall",
+	"syscall.DNS_TYPE_DS":                                  "syscall",
+	"syscall.DNS_TYPE_EID":                                 "syscall",
+	"syscall.DNS_TYPE_GID":                                 "syscall",
+	"syscall.DNS_TYPE_GPOS":                                "syscall",
+	"syscall.DNS_TYPE_HINFO":                               "syscall",
+	"syscall.DNS_TYPE_ISDN":                                "syscall",
+	"syscall.DNS_TYPE_IXFR":                                "syscall",
+	"syscall.DNS_TYPE_KEY":                                 "syscall",
+	"syscall.DNS_TYPE_KX":                                  "syscall",
+	"syscall.DNS_TYPE_LOC":                                 "syscall",
+	"syscall.DNS_TYPE_MAILA":                               "syscall",
+	"syscall.DNS_TYPE_MAILB":                               "syscall",
+	"syscall.DNS_TYPE_MB":                                  "syscall",
+	"syscall.DNS_TYPE_MD":                                  "syscall",
+	"syscall.DNS_TYPE_MF":                                  "syscall",
+	"syscall.DNS_TYPE_MG":                                  "syscall",
+	"syscall.DNS_TYPE_MINFO":                               "syscall",
+	"syscall.DNS_TYPE_MR":                                  "syscall",
+	"syscall.DNS_TYPE_MX":                                  "syscall",
+	"syscall.DNS_TYPE_NAPTR":                               "syscall",
+	"syscall.DNS_TYPE_NBSTAT":                              "syscall",
+	"syscall.DNS_TYPE_NIMLOC":                              "syscall",
+	"syscall.DNS_TYPE_NS":                                  "syscall",
+	"syscall.DNS_TYPE_NSAP":                                "syscall",
+	"syscall.DNS_TYPE_NSAPPTR":                             "syscall",
+	"syscall.DNS_TYPE_NSEC":                                "syscall",
+	"syscall.DNS_TYPE_NULL":                                "syscall",
+	"syscall.DNS_TYPE_NXT":                                 "syscall",
+	"syscall.DNS_TYPE_OPT":                                 "syscall",
+	"syscall.DNS_TYPE_PTR":                                 "syscall",
+	"syscall.DNS_TYPE_PX":                                  "syscall",
+	"syscall.DNS_TYPE_RP":                                  "syscall",
+	"syscall.DNS_TYPE_RRSIG":                               "syscall",
+	"syscall.DNS_TYPE_RT":                                  "syscall",
+	"syscall.DNS_TYPE_SIG":                                 "syscall",
+	"syscall.DNS_TYPE_SINK":                                "syscall",
+	"syscall.DNS_TYPE_SOA":                                 "syscall",
+	"syscall.DNS_TYPE_SRV":                                 "syscall",
+	"syscall.DNS_TYPE_TEXT":                                "syscall",
+	"syscall.DNS_TYPE_TKEY":                                "syscall",
+	"syscall.DNS_TYPE_TSIG":                                "syscall",
+	"syscall.DNS_TYPE_UID":                                 "syscall",
+	"syscall.DNS_TYPE_UINFO":                               "syscall",
+	"syscall.DNS_TYPE_UNSPEC":                              "syscall",
+	"syscall.DNS_TYPE_WINS":                                "syscall",
+	"syscall.DNS_TYPE_WINSR":                               "syscall",
+	"syscall.DNS_TYPE_WKS":                                 "syscall",
+	"syscall.DNS_TYPE_X25":                                 "syscall",
+	"syscall.DT_BLK":                                       "syscall",
+	"syscall.DT_CHR":                                       "syscall",
+	"syscall.DT_DIR":                                       "syscall",
+	"syscall.DT_FIFO":                                      "syscall",
+	"syscall.DT_LNK":                                       "syscall",
+	"syscall.DT_REG":                                       "syscall",
+	"syscall.DT_SOCK":                                      "syscall",
+	"syscall.DT_UNKNOWN":                                   "syscall",
+	"syscall.DT_WHT":                                       "syscall",
+	"syscall.DUPLICATE_CLOSE_SOURCE":                       "syscall",
+	"syscall.DUPLICATE_SAME_ACCESS":                        "syscall",
+	"syscall.DeleteFile":                                   "syscall",
+	"syscall.DetachLsf":                                    "syscall",
+	"syscall.Dirent":                                       "syscall",
+	"syscall.DnsQuery":                                     "syscall",
+	"syscall.DnsRecordListFree":                            "syscall",
+	"syscall.Dup":                                          "syscall",
+	"syscall.Dup2":                                         "syscall",
+	"syscall.Dup3":                                         "syscall",
+	"syscall.DuplicateHandle":                              "syscall",
+	"syscall.E2BIG":                                        "syscall",
+	"syscall.EACCES":                                       "syscall",
+	"syscall.EADDRINUSE":                                   "syscall",
+	"syscall.EADDRNOTAVAIL":                                "syscall",
+	"syscall.EADV":                                         "syscall",
+	"syscall.EAFNOSUPPORT":                                 "syscall",
+	"syscall.EAGAIN":                                       "syscall",
+	"syscall.EALREADY":                                     "syscall",
+	"syscall.EAUTH":                                        "syscall",
+	"syscall.EBADARCH":                                     "syscall",
+	"syscall.EBADE":                                        "syscall",
+	"syscall.EBADEXEC":                                     "syscall",
+	"syscall.EBADF":                                        "syscall",
+	"syscall.EBADFD":                                       "syscall",
+	"syscall.EBADMACHO":                                    "syscall",
+	"syscall.EBADMSG":                                      "syscall",
+	"syscall.EBADR":                                        "syscall",
+	"syscall.EBADRPC":                                      "syscall",
+	"syscall.EBADRQC":                                      "syscall",
+	"syscall.EBADSLT":                                      "syscall",
+	"syscall.EBFONT":                                       "syscall",
+	"syscall.EBUSY":                                        "syscall",
+	"syscall.ECANCELED":                                    "syscall",
+	"syscall.ECAPMODE":                                     "syscall",
+	"syscall.ECHILD":                                       "syscall",
+	"syscall.ECHO":                                         "syscall",
+	"syscall.ECHOCTL":                                      "syscall",
+	"syscall.ECHOE":                                        "syscall",
+	"syscall.ECHOK":                                        "syscall",
+	"syscall.ECHOKE":                                       "syscall",
+	"syscall.ECHONL":                                       "syscall",
+	"syscall.ECHOPRT":                                      "syscall",
+	"syscall.ECHRNG":                                       "syscall",
+	"syscall.ECOMM":                                        "syscall",
+	"syscall.ECONNABORTED":                                 "syscall",
+	"syscall.ECONNREFUSED":                                 "syscall",
+	"syscall.ECONNRESET":                                   "syscall",
+	"syscall.EDEADLK":                                      "syscall",
+	"syscall.EDEADLOCK":                                    "syscall",
+	"syscall.EDESTADDRREQ":                                 "syscall",
+	"syscall.EDEVERR":                                      "syscall",
+	"syscall.EDOM":                                         "syscall",
+	"syscall.EDOOFUS":                                      "syscall",
+	"syscall.EDOTDOT":                                      "syscall",
+	"syscall.EDQUOT":                                       "syscall",
+	"syscall.EEXIST":                                       "syscall",
+	"syscall.EFAULT":                                       "syscall",
+	"syscall.EFBIG":                                        "syscall",
+	"syscall.EFER_LMA":                                     "syscall",
+	"syscall.EFER_LME":                                     "syscall",
+	"syscall.EFER_NXE":                                     "syscall",
+	"syscall.EFER_SCE":                                     "syscall",
+	"syscall.EFTYPE":                                       "syscall",
+	"syscall.EHOSTDOWN":                                    "syscall",
+	"syscall.EHOSTUNREACH":                                 "syscall",
+	"syscall.EHWPOISON":                                    "syscall",
+	"syscall.EIDRM":                                        "syscall",
+	"syscall.EILSEQ":                                       "syscall",
+	"syscall.EINPROGRESS":                                  "syscall",
+	"syscall.EINTR":                                        "syscall",
+	"syscall.EINVAL":                                       "syscall",
+	"syscall.EIO":                                          "syscall",
+	"syscall.EIPSEC":                                       "syscall",
+	"syscall.EISCONN":                                      "syscall",
+	"syscall.EISDIR":                                       "syscall",
+	"syscall.EISNAM":                                       "syscall",
+	"syscall.EKEYEXPIRED":                                  "syscall",
+	"syscall.EKEYREJECTED":                                 "syscall",
+	"syscall.EKEYREVOKED":                                  "syscall",
+	"syscall.EL2HLT":                                       "syscall",
+	"syscall.EL2NSYNC":                                     "syscall",
+	"syscall.EL3HLT":                                       "syscall",
+	"syscall.EL3RST":                                       "syscall",
+	"syscall.ELAST":                                        "syscall",
+	"syscall.ELF_NGREG":                                    "syscall",
+	"syscall.ELF_PRARGSZ":                                  "syscall",
+	"syscall.ELIBACC":                                      "syscall",
+	"syscall.ELIBBAD":                                      "syscall",
+	"syscall.ELIBEXEC":                                     "syscall",
+	"syscall.ELIBMAX":                                      "syscall",
+	"syscall.ELIBSCN":                                      "syscall",
+	"syscall.ELNRNG":                                       "syscall",
+	"syscall.ELOOP":                                        "syscall",
+	"syscall.EMEDIUMTYPE":                                  "syscall",
+	"syscall.EMFILE":                                       "syscall",
+	"syscall.EMLINK":                                       "syscall",
+	"syscall.EMSGSIZE":                                     "syscall",
+	"syscall.EMT_TAGOVF":                                   "syscall",
+	"syscall.EMULTIHOP":                                    "syscall",
+	"syscall.EMUL_ENABLED":                                 "syscall",
+	"syscall.EMUL_LINUX":                                   "syscall",
+	"syscall.EMUL_LINUX32":                                 "syscall",
+	"syscall.EMUL_MAXID":                                   "syscall",
+	"syscall.EMUL_NATIVE":                                  "syscall",
+	"syscall.ENAMETOOLONG":                                 "syscall",
+	"syscall.ENAVAIL":                                      "syscall",
+	"syscall.ENDRUNDISC":                                   "syscall",
+	"syscall.ENEEDAUTH":                                    "syscall",
+	"syscall.ENETDOWN":                                     "syscall",
+	"syscall.ENETRESET":                                    "syscall",
+	"syscall.ENETUNREACH":                                  "syscall",
+	"syscall.ENFILE":                                       "syscall",
+	"syscall.ENOANO":                                       "syscall",
+	"syscall.ENOATTR":                                      "syscall",
+	"syscall.ENOBUFS":                                      "syscall",
+	"syscall.ENOCSI":                                       "syscall",
+	"syscall.ENODATA":                                      "syscall",
+	"syscall.ENODEV":                                       "syscall",
+	"syscall.ENOENT":                                       "syscall",
+	"syscall.ENOEXEC":                                      "syscall",
+	"syscall.ENOKEY":                                       "syscall",
+	"syscall.ENOLCK":                                       "syscall",
+	"syscall.ENOLINK":                                      "syscall",
+	"syscall.ENOMEDIUM":                                    "syscall",
+	"syscall.ENOMEM":                                       "syscall",
+	"syscall.ENOMSG":                                       "syscall",
+	"syscall.ENONET":                                       "syscall",
+	"syscall.ENOPKG":                                       "syscall",
+	"syscall.ENOPOLICY":                                    "syscall",
+	"syscall.ENOPROTOOPT":                                  "syscall",
+	"syscall.ENOSPC":                                       "syscall",
+	"syscall.ENOSR":                                        "syscall",
+	"syscall.ENOSTR":                                       "syscall",
+	"syscall.ENOSYS":                                       "syscall",
+	"syscall.ENOTBLK":                                      "syscall",
+	"syscall.ENOTCAPABLE":                                  "syscall",
+	"syscall.ENOTCONN":                                     "syscall",
+	"syscall.ENOTDIR":                                      "syscall",
+	"syscall.ENOTEMPTY":                                    "syscall",
+	"syscall.ENOTNAM":                                      "syscall",
+	"syscall.ENOTRECOVERABLE":                              "syscall",
+	"syscall.ENOTSOCK":                                     "syscall",
+	"syscall.ENOTSUP":                                      "syscall",
+	"syscall.ENOTTY":                                       "syscall",
+	"syscall.ENOTUNIQ":                                     "syscall",
+	"syscall.ENXIO":                                        "syscall",
+	"syscall.EN_SW_CTL_INF":                                "syscall",
+	"syscall.EN_SW_CTL_PREC":                               "syscall",
+	"syscall.EN_SW_CTL_ROUND":                              "syscall",
+	"syscall.EN_SW_DATACHAIN":                              "syscall",
+	"syscall.EN_SW_DENORM":                                 "syscall",
+	"syscall.EN_SW_INVOP":                                  "syscall",
+	"syscall.EN_SW_OVERFLOW":                               "syscall",
+	"syscall.EN_SW_PRECLOSS":                               "syscall",
+	"syscall.EN_SW_UNDERFLOW":                              "syscall",
+	"syscall.EN_SW_ZERODIV":                                "syscall",
+	"syscall.EOPNOTSUPP":                                   "syscall",
+	"syscall.EOVERFLOW":                                    "syscall",
+	"syscall.EOWNERDEAD":                                   "syscall",
+	"syscall.EPERM":                                        "syscall",
+	"syscall.EPFNOSUPPORT":                                 "syscall",
+	"syscall.EPIPE":                                        "syscall",
+	"syscall.EPOLLERR":                                     "syscall",
+	"syscall.EPOLLET":                                      "syscall",
+	"syscall.EPOLLHUP":                                     "syscall",
+	"syscall.EPOLLIN":                                      "syscall",
+	"syscall.EPOLLMSG":                                     "syscall",
+	"syscall.EPOLLONESHOT":                                 "syscall",
+	"syscall.EPOLLOUT":                                     "syscall",
+	"syscall.EPOLLPRI":                                     "syscall",
+	"syscall.EPOLLRDBAND":                                  "syscall",
+	"syscall.EPOLLRDHUP":                                   "syscall",
+	"syscall.EPOLLRDNORM":                                  "syscall",
+	"syscall.EPOLLWRBAND":                                  "syscall",
+	"syscall.EPOLLWRNORM":                                  "syscall",
+	"syscall.EPOLL_CLOEXEC":                                "syscall",
+	"syscall.EPOLL_CTL_ADD":                                "syscall",
+	"syscall.EPOLL_CTL_DEL":                                "syscall",
+	"syscall.EPOLL_CTL_MOD":                                "syscall",
+	"syscall.EPOLL_NONBLOCK":                               "syscall",
+	"syscall.EPROCLIM":                                     "syscall",
+	"syscall.EPROCUNAVAIL":                                 "syscall",
+	"syscall.EPROGMISMATCH":                                "syscall",
+	"syscall.EPROGUNAVAIL":                                 "syscall",
+	"syscall.EPROTO":                                       "syscall",
+	"syscall.EPROTONOSUPPORT":                              "syscall",
+	"syscall.EPROTOTYPE":                                   "syscall",
+	"syscall.EPWROFF":                                      "syscall",
+	"syscall.ERANGE":                                       "syscall",
+	"syscall.EREMCHG":                                      "syscall",
+	"syscall.EREMOTE":                                      "syscall",
+	"syscall.EREMOTEIO":                                    "syscall",
+	"syscall.ERESTART":                                     "syscall",
+	"syscall.ERFKILL":                                      "syscall",
+	"syscall.EROFS":                                        "syscall",
+	"syscall.ERPCMISMATCH":                                 "syscall",
+	"syscall.ERROR_ACCESS_DENIED":                          "syscall",
+	"syscall.ERROR_ALREADY_EXISTS":                         "syscall",
+	"syscall.ERROR_BROKEN_PIPE":                            "syscall",
+	"syscall.ERROR_BUFFER_OVERFLOW":                        "syscall",
+	"syscall.ERROR_ENVVAR_NOT_FOUND":                       "syscall",
+	"syscall.ERROR_FILE_EXISTS":                            "syscall",
+	"syscall.ERROR_FILE_NOT_FOUND":                         "syscall",
+	"syscall.ERROR_HANDLE_EOF":                             "syscall",
+	"syscall.ERROR_INSUFFICIENT_BUFFER":                    "syscall",
+	"syscall.ERROR_IO_PENDING":                             "syscall",
+	"syscall.ERROR_MOD_NOT_FOUND":                          "syscall",
+	"syscall.ERROR_NOT_FOUND":                              "syscall",
+	"syscall.ERROR_NO_MORE_FILES":                          "syscall",
+	"syscall.ERROR_OPERATION_ABORTED":                      "syscall",
+	"syscall.ERROR_PATH_NOT_FOUND":                         "syscall",
+	"syscall.ERROR_PROC_NOT_FOUND":                         "syscall",
+	"syscall.ESHLIBVERS":                                   "syscall",
+	"syscall.ESHUTDOWN":                                    "syscall",
+	"syscall.ESOCKTNOSUPPORT":                              "syscall",
+	"syscall.ESPIPE":                                       "syscall",
+	"syscall.ESRCH":                                        "syscall",
+	"syscall.ESRMNT":                                       "syscall",
+	"syscall.ESTALE":                                       "syscall",
+	"syscall.ESTRPIPE":                                     "syscall",
+	"syscall.ETHERCAP_JUMBO_MTU":                           "syscall",
+	"syscall.ETHERCAP_VLAN_HWTAGGING":                      "syscall",
+	"syscall.ETHERCAP_VLAN_MTU":                            "syscall",
+	"syscall.ETHERMIN":                                     "syscall",
+	"syscall.ETHERMTU":                                     "syscall",
+	"syscall.ETHERMTU_JUMBO":                               "syscall",
+	"syscall.ETHERTYPE_8023":                               "syscall",
+	"syscall.ETHERTYPE_AARP":                               "syscall",
+	"syscall.ETHERTYPE_ACCTON":                             "syscall",
+	"syscall.ETHERTYPE_AEONIC":                             "syscall",
+	"syscall.ETHERTYPE_ALPHA":                              "syscall",
+	"syscall.ETHERTYPE_AMBER":                              "syscall",
+	"syscall.ETHERTYPE_AMOEBA":                             "syscall",
+	"syscall.ETHERTYPE_AOE":                                "syscall",
+	"syscall.ETHERTYPE_APOLLO":                             "syscall",
+	"syscall.ETHERTYPE_APOLLODOMAIN":                       "syscall",
+	"syscall.ETHERTYPE_APPLETALK":                          "syscall",
+	"syscall.ETHERTYPE_APPLITEK":                           "syscall",
+	"syscall.ETHERTYPE_ARGONAUT":                           "syscall",
+	"syscall.ETHERTYPE_ARP":                                "syscall",
+	"syscall.ETHERTYPE_AT":                                 "syscall",
+	"syscall.ETHERTYPE_ATALK":                              "syscall",
+	"syscall.ETHERTYPE_ATOMIC":                             "syscall",
+	"syscall.ETHERTYPE_ATT":                                "syscall",
+	"syscall.ETHERTYPE_ATTSTANFORD":                        "syscall",
+	"syscall.ETHERTYPE_AUTOPHON":                           "syscall",
+	"syscall.ETHERTYPE_AXIS":                               "syscall",
+	"syscall.ETHERTYPE_BCLOOP":                             "syscall",
+	"syscall.ETHERTYPE_BOFL":                               "syscall",
+	"syscall.ETHERTYPE_CABLETRON":                          "syscall",
+	"syscall.ETHERTYPE_CHAOS":                              "syscall",
+	"syscall.ETHERTYPE_COMDESIGN":                          "syscall",
+	"syscall.ETHERTYPE_COMPUGRAPHIC":                       "syscall",
+	"syscall.ETHERTYPE_COUNTERPOINT":                       "syscall",
+	"syscall.ETHERTYPE_CRONUS":                             "syscall",
+	"syscall.ETHERTYPE_CRONUSVLN":                          "syscall",
+	"syscall.ETHERTYPE_DCA":                                "syscall",
+	"syscall.ETHERTYPE_DDE":                                "syscall",
+	"syscall.ETHERTYPE_DEBNI":                              "syscall",
+	"syscall.ETHERTYPE_DECAM":                              "syscall",
+	"syscall.ETHERTYPE_DECCUST":                            "syscall",
+	"syscall.ETHERTYPE_DECDIAG":                            "syscall",
+	"syscall.ETHERTYPE_DECDNS":                             "syscall",
+	"syscall.ETHERTYPE_DECDTS":                             "syscall",
+	"syscall.ETHERTYPE_DECEXPER":                           "syscall",
+	"syscall.ETHERTYPE_DECLAST":                            "syscall",
+	"syscall.ETHERTYPE_DECLTM":                             "syscall",
+	"syscall.ETHERTYPE_DECMUMPS":                           "syscall",
+	"syscall.ETHERTYPE_DECNETBIOS":                         "syscall",
+	"syscall.ETHERTYPE_DELTACON":                           "syscall",
+	"syscall.ETHERTYPE_DIDDLE":                             "syscall",
+	"syscall.ETHERTYPE_DLOG1":                              "syscall",
+	"syscall.ETHERTYPE_DLOG2":                              "syscall",
+	"syscall.ETHERTYPE_DN":                                 "syscall",
+	"syscall.ETHERTYPE_DOGFIGHT":                           "syscall",
+	"syscall.ETHERTYPE_DSMD":                               "syscall",
+	"syscall.ETHERTYPE_ECMA":                               "syscall",
+	"syscall.ETHERTYPE_ENCRYPT":                            "syscall",
+	"syscall.ETHERTYPE_ES":                                 "syscall",
+	"syscall.ETHERTYPE_EXCELAN":                            "syscall",
+	"syscall.ETHERTYPE_EXPERDATA":                          "syscall",
+	"syscall.ETHERTYPE_FLIP":                               "syscall",
+	"syscall.ETHERTYPE_FLOWCONTROL":                        "syscall",
+	"syscall.ETHERTYPE_FRARP":                              "syscall",
+	"syscall.ETHERTYPE_GENDYN":                             "syscall",
+	"syscall.ETHERTYPE_HAYES":                              "syscall",
+	"syscall.ETHERTYPE_HIPPI_FP":                           "syscall",
+	"syscall.ETHERTYPE_HITACHI":                            "syscall",
+	"syscall.ETHERTYPE_HP":                                 "syscall",
+	"syscall.ETHERTYPE_IEEEPUP":                            "syscall",
+	"syscall.ETHERTYPE_IEEEPUPAT":                          "syscall",
+	"syscall.ETHERTYPE_IMLBL":                              "syscall",
+	"syscall.ETHERTYPE_IMLBLDIAG":                          "syscall",
+	"syscall.ETHERTYPE_IP":                                 "syscall",
+	"syscall.ETHERTYPE_IPAS":                               "syscall",
+	"syscall.ETHERTYPE_IPV6":                               "syscall",
+	"syscall.ETHERTYPE_IPX":                                "syscall",
+	"syscall.ETHERTYPE_IPXNEW":                             "syscall",
+	"syscall.ETHERTYPE_KALPANA":                            "syscall",
+	"syscall.ETHERTYPE_LANBRIDGE":                          "syscall",
+	"syscall.ETHERTYPE_LANPROBE":                           "syscall",
+	"syscall.ETHERTYPE_LAT":                                "syscall",
+	"syscall.ETHERTYPE_LBACK":                              "syscall",
+	"syscall.ETHERTYPE_LITTLE":                             "syscall",
+	"syscall.ETHERTYPE_LLDP":                               "syscall",
+	"syscall.ETHERTYPE_LOGICRAFT":                          "syscall",
+	"syscall.ETHERTYPE_LOOPBACK":                           "syscall",
+	"syscall.ETHERTYPE_MATRA":                              "syscall",
+	"syscall.ETHERTYPE_MAX":                                "syscall",
+	"syscall.ETHERTYPE_MERIT":                              "syscall",
+	"syscall.ETHERTYPE_MICP":                               "syscall",
+	"syscall.ETHERTYPE_MOPDL":                              "syscall",
+	"syscall.ETHERTYPE_MOPRC":                              "syscall",
+	"syscall.ETHERTYPE_MOTOROLA":                           "syscall",
+	"syscall.ETHERTYPE_MPLS":                               "syscall",
+	"syscall.ETHERTYPE_MPLS_MCAST":                         "syscall",
+	"syscall.ETHERTYPE_MUMPS":                              "syscall",
+	"syscall.ETHERTYPE_NBPCC":                              "syscall",
+	"syscall.ETHERTYPE_NBPCLAIM":                           "syscall",
+	"syscall.ETHERTYPE_NBPCLREQ":                           "syscall",
+	"syscall.ETHERTYPE_NBPCLRSP":                           "syscall",
+	"syscall.ETHERTYPE_NBPCREQ":                            "syscall",
+	"syscall.ETHERTYPE_NBPCRSP":                            "syscall",
+	"syscall.ETHERTYPE_NBPDG":                              "syscall",
+	"syscall.ETHERTYPE_NBPDGB":                             "syscall",
+	"syscall.ETHERTYPE_NBPDLTE":                            "syscall",
+	"syscall.ETHERTYPE_NBPRAR":                             "syscall",
+	"syscall.ETHERTYPE_NBPRAS":                             "syscall",
+	"syscall.ETHERTYPE_NBPRST":                             "syscall",
+	"syscall.ETHERTYPE_NBPSCD":                             "syscall",
+	"syscall.ETHERTYPE_NBPVCD":                             "syscall",
+	"syscall.ETHERTYPE_NBS":                                "syscall",
+	"syscall.ETHERTYPE_NCD":                                "syscall",
+	"syscall.ETHERTYPE_NESTAR":                             "syscall",
+	"syscall.ETHERTYPE_NETBEUI":                            "syscall",
+	"syscall.ETHERTYPE_NOVELL":                             "syscall",
+	"syscall.ETHERTYPE_NS":                                 "syscall",
+	"syscall.ETHERTYPE_NSAT":                               "syscall",
+	"syscall.ETHERTYPE_NSCOMPAT":                           "syscall",
+	"syscall.ETHERTYPE_NTRAILER":                           "syscall",
+	"syscall.ETHERTYPE_OS9":                                "syscall",
+	"syscall.ETHERTYPE_OS9NET":                             "syscall",
+	"syscall.ETHERTYPE_PACER":                              "syscall",
+	"syscall.ETHERTYPE_PAE":                                "syscall",
+	"syscall.ETHERTYPE_PCS":                                "syscall",
+	"syscall.ETHERTYPE_PLANNING":                           "syscall",
+	"syscall.ETHERTYPE_PPP":                                "syscall",
+	"syscall.ETHERTYPE_PPPOE":                              "syscall",
+	"syscall.ETHERTYPE_PPPOEDISC":                          "syscall",
+	"syscall.ETHERTYPE_PRIMENTS":                           "syscall",
+	"syscall.ETHERTYPE_PUP":                                "syscall",
+	"syscall.ETHERTYPE_PUPAT":                              "syscall",
+	"syscall.ETHERTYPE_QINQ":                               "syscall",
+	"syscall.ETHERTYPE_RACAL":                              "syscall",
+	"syscall.ETHERTYPE_RATIONAL":                           "syscall",
+	"syscall.ETHERTYPE_RAWFR":                              "syscall",
+	"syscall.ETHERTYPE_RCL":                                "syscall",
+	"syscall.ETHERTYPE_RDP":                                "syscall",
+	"syscall.ETHERTYPE_RETIX":                              "syscall",
+	"syscall.ETHERTYPE_REVARP":                             "syscall",
+	"syscall.ETHERTYPE_SCA":                                "syscall",
+	"syscall.ETHERTYPE_SECTRA":                             "syscall",
+	"syscall.ETHERTYPE_SECUREDATA":                         "syscall",
+	"syscall.ETHERTYPE_SGITW":                              "syscall",
+	"syscall.ETHERTYPE_SG_BOUNCE":                          "syscall",
+	"syscall.ETHERTYPE_SG_DIAG":                            "syscall",
+	"syscall.ETHERTYPE_SG_NETGAMES":                        "syscall",
+	"syscall.ETHERTYPE_SG_RESV":                            "syscall",
+	"syscall.ETHERTYPE_SIMNET":                             "syscall",
+	"syscall.ETHERTYPE_SLOW":                               "syscall",
+	"syscall.ETHERTYPE_SLOWPROTOCOLS":                      "syscall",
+	"syscall.ETHERTYPE_SNA":                                "syscall",
+	"syscall.ETHERTYPE_SNMP":                               "syscall",
+	"syscall.ETHERTYPE_SONIX":                              "syscall",
+	"syscall.ETHERTYPE_SPIDER":                             "syscall",
+	"syscall.ETHERTYPE_SPRITE":                             "syscall",
+	"syscall.ETHERTYPE_STP":                                "syscall",
+	"syscall.ETHERTYPE_TALARIS":                            "syscall",
+	"syscall.ETHERTYPE_TALARISMC":                          "syscall",
+	"syscall.ETHERTYPE_TCPCOMP":                            "syscall",
+	"syscall.ETHERTYPE_TCPSM":                              "syscall",
+	"syscall.ETHERTYPE_TEC":                                "syscall",
+	"syscall.ETHERTYPE_TIGAN":                              "syscall",
+	"syscall.ETHERTYPE_TRAIL":                              "syscall",
+	"syscall.ETHERTYPE_TRANSETHER":                         "syscall",
+	"syscall.ETHERTYPE_TYMSHARE":                           "syscall",
+	"syscall.ETHERTYPE_UBBST":                              "syscall",
+	"syscall.ETHERTYPE_UBDEBUG":                            "syscall",
+	"syscall.ETHERTYPE_UBDIAGLOOP":                         "syscall",
+	"syscall.ETHERTYPE_UBDL":                               "syscall",
+	"syscall.ETHERTYPE_UBNIU":                              "syscall",
+	"syscall.ETHERTYPE_UBNMC":                              "syscall",
+	"syscall.ETHERTYPE_VALID":                              "syscall",
+	"syscall.ETHERTYPE_VARIAN":                             "syscall",
+	"syscall.ETHERTYPE_VAXELN":                             "syscall",
+	"syscall.ETHERTYPE_VEECO":                              "syscall",
+	"syscall.ETHERTYPE_VEXP":                               "syscall",
+	"syscall.ETHERTYPE_VGLAB":                              "syscall",
+	"syscall.ETHERTYPE_VINES":                              "syscall",
+	"syscall.ETHERTYPE_VINESECHO":                          "syscall",
+	"syscall.ETHERTYPE_VINESLOOP":                          "syscall",
+	"syscall.ETHERTYPE_VITAL":                              "syscall",
+	"syscall.ETHERTYPE_VLAN":                               "syscall",
+	"syscall.ETHERTYPE_VLTLMAN":                            "syscall",
+	"syscall.ETHERTYPE_VPROD":                              "syscall",
+	"syscall.ETHERTYPE_VURESERVED":                         "syscall",
+	"syscall.ETHERTYPE_WATERLOO":                           "syscall",
+	"syscall.ETHERTYPE_WELLFLEET":                          "syscall",
+	"syscall.ETHERTYPE_X25":                                "syscall",
+	"syscall.ETHERTYPE_X75":                                "syscall",
+	"syscall.ETHERTYPE_XNSSM":                              "syscall",
+	"syscall.ETHERTYPE_XTP":                                "syscall",
+	"syscall.ETHER_ADDR_LEN":                               "syscall",
+	"syscall.ETHER_ALIGN":                                  "syscall",
+	"syscall.ETHER_CRC_LEN":                                "syscall",
+	"syscall.ETHER_CRC_POLY_BE":                            "syscall",
+	"syscall.ETHER_CRC_POLY_LE":                            "syscall",
+	"syscall.ETHER_HDR_LEN":                                "syscall",
+	"syscall.ETHER_MAX_DIX_LEN":                            "syscall",
+	"syscall.ETHER_MAX_LEN":                                "syscall",
+	"syscall.ETHER_MAX_LEN_JUMBO":                          "syscall",
+	"syscall.ETHER_MIN_LEN":                                "syscall",
+	"syscall.ETHER_PPPOE_ENCAP_LEN":                        "syscall",
+	"syscall.ETHER_TYPE_LEN":                               "syscall",
+	"syscall.ETHER_VLAN_ENCAP_LEN":                         "syscall",
+	"syscall.ETH_P_1588":                                   "syscall",
+	"syscall.ETH_P_8021Q":                                  "syscall",
+	"syscall.ETH_P_802_2":                                  "syscall",
+	"syscall.ETH_P_802_3":                                  "syscall",
+	"syscall.ETH_P_AARP":                                   "syscall",
+	"syscall.ETH_P_ALL":                                    "syscall",
+	"syscall.ETH_P_AOE":                                    "syscall",
+	"syscall.ETH_P_ARCNET":                                 "syscall",
+	"syscall.ETH_P_ARP":                                    "syscall",
+	"syscall.ETH_P_ATALK":                                  "syscall",
+	"syscall.ETH_P_ATMFATE":                                "syscall",
+	"syscall.ETH_P_ATMMPOA":                                "syscall",
+	"syscall.ETH_P_AX25":                                   "syscall",
+	"syscall.ETH_P_BPQ":                                    "syscall",
+	"syscall.ETH_P_CAIF":                                   "syscall",
+	"syscall.ETH_P_CAN":                                    "syscall",
+	"syscall.ETH_P_CONTROL":                                "syscall",
+	"syscall.ETH_P_CUST":                                   "syscall",
+	"syscall.ETH_P_DDCMP":                                  "syscall",
+	"syscall.ETH_P_DEC":                                    "syscall",
+	"syscall.ETH_P_DIAG":                                   "syscall",
+	"syscall.ETH_P_DNA_DL":                                 "syscall",
+	"syscall.ETH_P_DNA_RC":                                 "syscall",
+	"syscall.ETH_P_DNA_RT":                                 "syscall",
+	"syscall.ETH_P_DSA":                                    "syscall",
+	"syscall.ETH_P_ECONET":                                 "syscall",
+	"syscall.ETH_P_EDSA":                                   "syscall",
+	"syscall.ETH_P_FCOE":                                   "syscall",
+	"syscall.ETH_P_FIP":                                    "syscall",
+	"syscall.ETH_P_HDLC":                                   "syscall",
+	"syscall.ETH_P_IEEE802154":                             "syscall",
+	"syscall.ETH_P_IEEEPUP":                                "syscall",
+	"syscall.ETH_P_IEEEPUPAT":                              "syscall",
+	"syscall.ETH_P_IP":                                     "syscall",
+	"syscall.ETH_P_IPV6":                                   "syscall",
+	"syscall.ETH_P_IPX":                                    "syscall",
+	"syscall.ETH_P_IRDA":                                   "syscall",
+	"syscall.ETH_P_LAT":                                    "syscall",
+	"syscall.ETH_P_LINK_CTL":                               "syscall",
+	"syscall.ETH_P_LOCALTALK":                              "syscall",
+	"syscall.ETH_P_LOOP":                                   "syscall",
+	"syscall.ETH_P_MOBITEX":                                "syscall",
+	"syscall.ETH_P_MPLS_MC":                                "syscall",
+	"syscall.ETH_P_MPLS_UC":                                "syscall",
+	"syscall.ETH_P_PAE":                                    "syscall",
+	"syscall.ETH_P_PAUSE":                                  "syscall",
+	"syscall.ETH_P_PHONET":                                 "syscall",
+	"syscall.ETH_P_PPPTALK":                                "syscall",
+	"syscall.ETH_P_PPP_DISC":                               "syscall",
+	"syscall.ETH_P_PPP_MP":                                 "syscall",
+	"syscall.ETH_P_PPP_SES":                                "syscall",
+	"syscall.ETH_P_PUP":                                    "syscall",
+	"syscall.ETH_P_PUPAT":                                  "syscall",
+	"syscall.ETH_P_RARP":                                   "syscall",
+	"syscall.ETH_P_SCA":                                    "syscall",
+	"syscall.ETH_P_SLOW":                                   "syscall",
+	"syscall.ETH_P_SNAP":                                   "syscall",
+	"syscall.ETH_P_TEB":                                    "syscall",
+	"syscall.ETH_P_TIPC":                                   "syscall",
+	"syscall.ETH_P_TRAILER":                                "syscall",
+	"syscall.ETH_P_TR_802_2":                               "syscall",
+	"syscall.ETH_P_WAN_PPP":                                "syscall",
+	"syscall.ETH_P_WCCP":                                   "syscall",
+	"syscall.ETH_P_X25":                                    "syscall",
+	"syscall.ETIME":                                        "syscall",
+	"syscall.ETIMEDOUT":                                    "syscall",
+	"syscall.ETOOMANYREFS":                                 "syscall",
+	"syscall.ETXTBSY":                                      "syscall",
+	"syscall.EUCLEAN":                                      "syscall",
+	"syscall.EUNATCH":                                      "syscall",
+	"syscall.EUSERS":                                       "syscall",
+	"syscall.EVFILT_AIO":                                   "syscall",
+	"syscall.EVFILT_FS":                                    "syscall",
+	"syscall.EVFILT_LIO":                                   "syscall",
+	"syscall.EVFILT_MACHPORT":                              "syscall",
+	"syscall.EVFILT_PROC":                                  "syscall",
+	"syscall.EVFILT_READ":                                  "syscall",
+	"syscall.EVFILT_SIGNAL":                                "syscall",
+	"syscall.EVFILT_SYSCOUNT":                              "syscall",
+	"syscall.EVFILT_THREADMARKER":                          "syscall",
+	"syscall.EVFILT_TIMER":                                 "syscall",
+	"syscall.EVFILT_USER":                                  "syscall",
+	"syscall.EVFILT_VM":                                    "syscall",
+	"syscall.EVFILT_VNODE":                                 "syscall",
+	"syscall.EVFILT_WRITE":                                 "syscall",
+	"syscall.EV_ADD":                                       "syscall",
+	"syscall.EV_CLEAR":                                     "syscall",
+	"syscall.EV_DELETE":                                    "syscall",
+	"syscall.EV_DISABLE":                                   "syscall",
+	"syscall.EV_DISPATCH":                                  "syscall",
+	"syscall.EV_ENABLE":                                    "syscall",
+	"syscall.EV_EOF":                                       "syscall",
+	"syscall.EV_ERROR":                                     "syscall",
+	"syscall.EV_FLAG0":                                     "syscall",
+	"syscall.EV_FLAG1":                                     "syscall",
+	"syscall.EV_ONESHOT":                                   "syscall",
+	"syscall.EV_OOBAND":                                    "syscall",
+	"syscall.EV_POLL":                                      "syscall",
+	"syscall.EV_RECEIPT":                                   "syscall",
+	"syscall.EV_SYSFLAGS":                                  "syscall",
+	"syscall.EWINDOWS":                                     "syscall",
+	"syscall.EWOULDBLOCK":                                  "syscall",
+	"syscall.EXDEV":                                        "syscall",
+	"syscall.EXFULL":                                       "syscall",
+	"syscall.EXTA":                                         "syscall",
+	"syscall.EXTB":                                         "syscall",
+	"syscall.EXTPROC":                                      "syscall",
+	"syscall.Environ":                                      "syscall",
+	"syscall.EpollCreate":                                  "syscall",
+	"syscall.EpollCreate1":                                 "syscall",
+	"syscall.EpollCtl":                                     "syscall",
+	"syscall.EpollEvent":                                   "syscall",
+	"syscall.EpollWait":                                    "syscall",
+	"syscall.Errno":                                        "syscall",
+	"syscall.EscapeArg":                                    "syscall",
+	"syscall.Exchangedata":                                 "syscall",
+	"syscall.Exec":                                         "syscall",
+	"syscall.Exit":                                         "syscall",
+	"syscall.ExitProcess":                                  "syscall",
+	"syscall.FD_CLOEXEC":                                   "syscall",
+	"syscall.FD_SETSIZE":                                   "syscall",
+	"syscall.FILE_ACTION_ADDED":                            "syscall",
+	"syscall.FILE_ACTION_MODIFIED":                         "syscall",
+	"syscall.FILE_ACTION_REMOVED":                          "syscall",
+	"syscall.FILE_ACTION_RENAMED_NEW_NAME":                 "syscall",
+	"syscall.FILE_ACTION_RENAMED_OLD_NAME":                 "syscall",
+	"syscall.FILE_APPEND_DATA":                             "syscall",
+	"syscall.FILE_ATTRIBUTE_ARCHIVE":                       "syscall",
+	"syscall.FILE_ATTRIBUTE_DIRECTORY":                     "syscall",
+	"syscall.FILE_ATTRIBUTE_HIDDEN":                        "syscall",
+	"syscall.FILE_ATTRIBUTE_NORMAL":                        "syscall",
+	"syscall.FILE_ATTRIBUTE_READONLY":                      "syscall",
+	"syscall.FILE_ATTRIBUTE_SYSTEM":                        "syscall",
+	"syscall.FILE_BEGIN":                                   "syscall",
+	"syscall.FILE_CURRENT":                                 "syscall",
+	"syscall.FILE_END":                                     "syscall",
+	"syscall.FILE_FLAG_BACKUP_SEMANTICS":                   "syscall",
+	"syscall.FILE_FLAG_OVERLAPPED":                         "syscall",
+	"syscall.FILE_LIST_DIRECTORY":                          "syscall",
+	"syscall.FILE_MAP_COPY":                                "syscall",
+	"syscall.FILE_MAP_EXECUTE":                             "syscall",
+	"syscall.FILE_MAP_READ":                                "syscall",
+	"syscall.FILE_MAP_WRITE":                               "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES":                "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_CREATION":                  "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_DIR_NAME":                  "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_FILE_NAME":                 "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS":               "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_LAST_WRITE":                "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_SIZE":                      "syscall",
+	"syscall.FILE_SHARE_DELETE":                            "syscall",
+	"syscall.FILE_SHARE_READ":                              "syscall",
+	"syscall.FILE_SHARE_WRITE":                             "syscall",
+	"syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS":         "syscall",
+	"syscall.FILE_SKIP_SET_EVENT_ON_HANDLE":                "syscall",
+	"syscall.FILE_TYPE_CHAR":                               "syscall",
+	"syscall.FILE_TYPE_DISK":                               "syscall",
+	"syscall.FILE_TYPE_PIPE":                               "syscall",
+	"syscall.FILE_TYPE_REMOTE":                             "syscall",
+	"syscall.FILE_TYPE_UNKNOWN":                            "syscall",
+	"syscall.FILE_WRITE_ATTRIBUTES":                        "syscall",
+	"syscall.FLUSHO":                                       "syscall",
+	"syscall.FORMAT_MESSAGE_ALLOCATE_BUFFER":               "syscall",
+	"syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY":                "syscall",
+	"syscall.FORMAT_MESSAGE_FROM_HMODULE":                  "syscall",
+	"syscall.FORMAT_MESSAGE_FROM_STRING":                   "syscall",
+	"syscall.FORMAT_MESSAGE_FROM_SYSTEM":                   "syscall",
+	"syscall.FORMAT_MESSAGE_IGNORE_INSERTS":                "syscall",
+	"syscall.FORMAT_MESSAGE_MAX_WIDTH_MASK":                "syscall",
+	"syscall.F_ADDFILESIGS":                                "syscall",
+	"syscall.F_ADDSIGS":                                    "syscall",
+	"syscall.F_ALLOCATEALL":                                "syscall",
+	"syscall.F_ALLOCATECONTIG":                             "syscall",
+	"syscall.F_CANCEL":                                     "syscall",
+	"syscall.F_CHKCLEAN":                                   "syscall",
+	"syscall.F_CLOSEM":                                     "syscall",
+	"syscall.F_DUP2FD":                                     "syscall",
+	"syscall.F_DUP2FD_CLOEXEC":                             "syscall",
+	"syscall.F_DUPFD":                                      "syscall",
+	"syscall.F_DUPFD_CLOEXEC":                              "syscall",
+	"syscall.F_EXLCK":                                      "syscall",
+	"syscall.F_FLUSH_DATA":                                 "syscall",
+	"syscall.F_FREEZE_FS":                                  "syscall",
+	"syscall.F_FSCTL":                                      "syscall",
+	"syscall.F_FSDIRMASK":                                  "syscall",
+	"syscall.F_FSIN":                                       "syscall",
+	"syscall.F_FSINOUT":                                    "syscall",
+	"syscall.F_FSOUT":                                      "syscall",
+	"syscall.F_FSPRIV":                                     "syscall",
+	"syscall.F_FSVOID":                                     "syscall",
+	"syscall.F_FULLFSYNC":                                  "syscall",
+	"syscall.F_GETFD":                                      "syscall",
+	"syscall.F_GETFL":                                      "syscall",
+	"syscall.F_GETLEASE":                                   "syscall",
+	"syscall.F_GETLK":                                      "syscall",
+	"syscall.F_GETLK64":                                    "syscall",
+	"syscall.F_GETLKPID":                                   "syscall",
+	"syscall.F_GETNOSIGPIPE":                               "syscall",
+	"syscall.F_GETOWN":                                     "syscall",
+	"syscall.F_GETOWN_EX":                                  "syscall",
+	"syscall.F_GETPATH":                                    "syscall",
+	"syscall.F_GETPATH_MTMINFO":                            "syscall",
+	"syscall.F_GETPIPE_SZ":                                 "syscall",
+	"syscall.F_GETPROTECTIONCLASS":                         "syscall",
+	"syscall.F_GETSIG":                                     "syscall",
+	"syscall.F_GLOBAL_NOCACHE":                             "syscall",
+	"syscall.F_LOCK":                                       "syscall",
+	"syscall.F_LOG2PHYS":                                   "syscall",
+	"syscall.F_LOG2PHYS_EXT":                               "syscall",
+	"syscall.F_MARKDEPENDENCY":                             "syscall",
+	"syscall.F_MAXFD":                                      "syscall",
+	"syscall.F_NOCACHE":                                    "syscall",
+	"syscall.F_NODIRECT":                                   "syscall",
+	"syscall.F_NOTIFY":                                     "syscall",
+	"syscall.F_OGETLK":                                     "syscall",
+	"syscall.F_OK":                                         "syscall",
+	"syscall.F_OSETLK":                                     "syscall",
+	"syscall.F_OSETLKW":                                    "syscall",
+	"syscall.F_PARAM_MASK":                                 "syscall",
+	"syscall.F_PARAM_MAX":                                  "syscall",
+	"syscall.F_PATHPKG_CHECK":                              "syscall",
+	"syscall.F_PEOFPOSMODE":                                "syscall",
+	"syscall.F_PREALLOCATE":                                "syscall",
+	"syscall.F_RDADVISE":                                   "syscall",
+	"syscall.F_RDAHEAD":                                    "syscall",
+	"syscall.F_RDLCK":                                      "syscall",
+	"syscall.F_READAHEAD":                                  "syscall",
+	"syscall.F_READBOOTSTRAP":                              "syscall",
+	"syscall.F_SETBACKINGSTORE":                            "syscall",
+	"syscall.F_SETFD":                                      "syscall",
+	"syscall.F_SETFL":                                      "syscall",
+	"syscall.F_SETLEASE":                                   "syscall",
+	"syscall.F_SETLK":                                      "syscall",
+	"syscall.F_SETLK64":                                    "syscall",
+	"syscall.F_SETLKW":                                     "syscall",
+	"syscall.F_SETLKW64":                                   "syscall",
+	"syscall.F_SETLK_REMOTE":                               "syscall",
+	"syscall.F_SETNOSIGPIPE":                               "syscall",
+	"syscall.F_SETOWN":                                     "syscall",
+	"syscall.F_SETOWN_EX":                                  "syscall",
+	"syscall.F_SETPIPE_SZ":                                 "syscall",
+	"syscall.F_SETPROTECTIONCLASS":                         "syscall",
+	"syscall.F_SETSIG":                                     "syscall",
+	"syscall.F_SETSIZE":                                    "syscall",
+	"syscall.F_SHLCK":                                      "syscall",
+	"syscall.F_TEST":                                       "syscall",
+	"syscall.F_THAW_FS":                                    "syscall",
+	"syscall.F_TLOCK":                                      "syscall",
+	"syscall.F_ULOCK":                                      "syscall",
+	"syscall.F_UNLCK":                                      "syscall",
+	"syscall.F_UNLCKSYS":                                   "syscall",
+	"syscall.F_VOLPOSMODE":                                 "syscall",
+	"syscall.F_WRITEBOOTSTRAP":                             "syscall",
+	"syscall.F_WRLCK":                                      "syscall",
+	"syscall.Faccessat":                                    "syscall",
+	"syscall.Fallocate":                                    "syscall",
+	"syscall.Fbootstraptransfer_t":                         "syscall",
+	"syscall.Fchdir":                                       "syscall",
+	"syscall.Fchflags":                                     "syscall",
+	"syscall.Fchmod":                                       "syscall",
+	"syscall.Fchmodat":                                     "syscall",
+	"syscall.Fchown":                                       "syscall",
+	"syscall.Fchownat":                                     "syscall",
+	"syscall.FdSet":                                        "syscall",
+	"syscall.Fdatasync":                                    "syscall",
+	"syscall.FileNotifyInformation":                        "syscall",
+	"syscall.Filetime":                                     "syscall",
+	"syscall.FindClose":                                    "syscall",
+	"syscall.FindFirstFile":                                "syscall",
+	"syscall.FindNextFile":                                 "syscall",
+	"syscall.Flock":                                        "syscall",
+	"syscall.Flock_t":                                      "syscall",
+	"syscall.FlushBpf":                                     "syscall",
+	"syscall.FlushFileBuffers":                             "syscall",
+	"syscall.FlushViewOfFile":                              "syscall",
+	"syscall.ForkExec":                                     "syscall",
+	"syscall.ForkLock":                                     "syscall",
+	"syscall.FormatMessage":                                "syscall",
+	"syscall.Fpathconf":                                    "syscall",
+	"syscall.FreeAddrInfoW":                                "syscall",
+	"syscall.FreeEnvironmentStrings":                       "syscall",
+	"syscall.FreeLibrary":                                  "syscall",
+	"syscall.Fsid":                                         "syscall",
+	"syscall.Fstat":                                        "syscall",
+	"syscall.Fstatfs":                                      "syscall",
+	"syscall.Fstore_t":                                     "syscall",
+	"syscall.Fsync":                                        "syscall",
+	"syscall.Ftruncate":                                    "syscall",
+	"syscall.Futimes":                                      "syscall",
+	"syscall.Futimesat":                                    "syscall",
+	"syscall.GENERIC_ALL":                                  "syscall",
+	"syscall.GENERIC_EXECUTE":                              "syscall",
+	"syscall.GENERIC_READ":                                 "syscall",
+	"syscall.GENERIC_WRITE":                                "syscall",
+	"syscall.GUID":                                         "syscall",
+	"syscall.GetAcceptExSockaddrs":                         "syscall",
+	"syscall.GetAdaptersInfo":                              "syscall",
+	"syscall.GetAddrInfoW":                                 "syscall",
+	"syscall.GetCommandLine":                               "syscall",
+	"syscall.GetComputerName":                              "syscall",
+	"syscall.GetConsoleMode":                               "syscall",
+	"syscall.GetCurrentDirectory":                          "syscall",
+	"syscall.GetCurrentProcess":                            "syscall",
+	"syscall.GetEnvironmentStrings":                        "syscall",
+	"syscall.GetEnvironmentVariable":                       "syscall",
+	"syscall.GetExitCodeProcess":                           "syscall",
+	"syscall.GetFileAttributes":                            "syscall",
+	"syscall.GetFileAttributesEx":                          "syscall",
+	"syscall.GetFileExInfoStandard":                        "syscall",
+	"syscall.GetFileExMaxInfoLevel":                        "syscall",
+	"syscall.GetFileInformationByHandle":                   "syscall",
+	"syscall.GetFileType":                                  "syscall",
+	"syscall.GetFullPathName":                              "syscall",
+	"syscall.GetHostByName":                                "syscall",
+	"syscall.GetIfEntry":                                   "syscall",
+	"syscall.GetLastError":                                 "syscall",
+	"syscall.GetLengthSid":                                 "syscall",
+	"syscall.GetLongPathName":                              "syscall",
+	"syscall.GetProcAddress":                               "syscall",
+	"syscall.GetProcessTimes":                              "syscall",
+	"syscall.GetProtoByName":                               "syscall",
+	"syscall.GetQueuedCompletionStatus":                    "syscall",
+	"syscall.GetServByName":                                "syscall",
+	"syscall.GetShortPathName":                             "syscall",
+	"syscall.GetStartupInfo":                               "syscall",
+	"syscall.GetStdHandle":                                 "syscall",
+	"syscall.GetSystemTimeAsFileTime":                      "syscall",
+	"syscall.GetTempPath":                                  "syscall",
+	"syscall.GetTimeZoneInformation":                       "syscall",
+	"syscall.GetTokenInformation":                          "syscall",
+	"syscall.GetUserNameEx":                                "syscall",
+	"syscall.GetUserProfileDirectory":                      "syscall",
+	"syscall.GetVersion":                                   "syscall",
+	"syscall.Getcwd":                                       "syscall",
+	"syscall.Getdents":                                     "syscall",
+	"syscall.Getdirentries":                                "syscall",
+	"syscall.Getdtablesize":                                "syscall",
+	"syscall.Getegid":                                      "syscall",
+	"syscall.Getenv":                                       "syscall",
+	"syscall.Geteuid":                                      "syscall",
+	"syscall.Getfsstat":                                    "syscall",
+	"syscall.Getgid":                                       "syscall",
+	"syscall.Getgroups":                                    "syscall",
+	"syscall.Getpagesize":                                  "syscall",
+	"syscall.Getpeername":                                  "syscall",
+	"syscall.Getpgid":                                      "syscall",
+	"syscall.Getpgrp":                                      "syscall",
+	"syscall.Getpid":                                       "syscall",
+	"syscall.Getppid":                                      "syscall",
+	"syscall.Getpriority":                                  "syscall",
+	"syscall.Getrlimit":                                    "syscall",
+	"syscall.Getrusage":                                    "syscall",
+	"syscall.Getsid":                                       "syscall",
+	"syscall.Getsockname":                                  "syscall",
+	"syscall.Getsockopt":                                   "syscall",
+	"syscall.GetsockoptByte":                               "syscall",
+	"syscall.GetsockoptICMPv6Filter":                       "syscall",
+	"syscall.GetsockoptIPMreq":                             "syscall",
+	"syscall.GetsockoptIPMreqn":                            "syscall",
+	"syscall.GetsockoptIPv6MTUInfo":                        "syscall",
+	"syscall.GetsockoptIPv6Mreq":                           "syscall",
+	"syscall.GetsockoptInet4Addr":                          "syscall",
+	"syscall.GetsockoptInt":                                "syscall",
+	"syscall.GetsockoptUcred":                              "syscall",
+	"syscall.Gettid":                                       "syscall",
+	"syscall.Gettimeofday":                                 "syscall",
+	"syscall.Getuid":                                       "syscall",
+	"syscall.Getwd":                                        "syscall",
+	"syscall.Getxattr":                                     "syscall",
+	"syscall.HANDLE_FLAG_INHERIT":                          "syscall",
+	"syscall.HKEY_CLASSES_ROOT":                            "syscall",
+	"syscall.HKEY_CURRENT_CONFIG":                          "syscall",
+	"syscall.HKEY_CURRENT_USER":                            "syscall",
+	"syscall.HKEY_DYN_DATA":                                "syscall",
+	"syscall.HKEY_LOCAL_MACHINE":                           "syscall",
+	"syscall.HKEY_PERFORMANCE_DATA":                        "syscall",
+	"syscall.HKEY_USERS":                                   "syscall",
+	"syscall.HUPCL":                                        "syscall",
+	"syscall.Handle":                                       "syscall",
+	"syscall.Hostent":                                      "syscall",
+	"syscall.ICANON":                                       "syscall",
+	"syscall.ICMP6_FILTER":                                 "syscall",
+	"syscall.ICMPV6_FILTER":                                "syscall",
+	"syscall.ICMPv6Filter":                                 "syscall",
+	"syscall.ICRNL":                                        "syscall",
+	"syscall.IEXTEN":                                       "syscall",
+	"syscall.IFAN_ARRIVAL":                                 "syscall",
+	"syscall.IFAN_DEPARTURE":                               "syscall",
+	"syscall.IFA_ADDRESS":                                  "syscall",
+	"syscall.IFA_ANYCAST":                                  "syscall",
+	"syscall.IFA_BROADCAST":                                "syscall",
+	"syscall.IFA_CACHEINFO":                                "syscall",
+	"syscall.IFA_F_DADFAILED":                              "syscall",
+	"syscall.IFA_F_DEPRECATED":                             "syscall",
+	"syscall.IFA_F_HOMEADDRESS":                            "syscall",
+	"syscall.IFA_F_NODAD":                                  "syscall",
+	"syscall.IFA_F_OPTIMISTIC":                             "syscall",
+	"syscall.IFA_F_PERMANENT":                              "syscall",
+	"syscall.IFA_F_SECONDARY":                              "syscall",
+	"syscall.IFA_F_TEMPORARY":                              "syscall",
+	"syscall.IFA_F_TENTATIVE":                              "syscall",
+	"syscall.IFA_LABEL":                                    "syscall",
+	"syscall.IFA_LOCAL":                                    "syscall",
+	"syscall.IFA_MAX":                                      "syscall",
+	"syscall.IFA_MULTICAST":                                "syscall",
+	"syscall.IFA_ROUTE":                                    "syscall",
+	"syscall.IFA_UNSPEC":                                   "syscall",
+	"syscall.IFF_ALLMULTI":                                 "syscall",
+	"syscall.IFF_ALTPHYS":                                  "syscall",
+	"syscall.IFF_AUTOMEDIA":                                "syscall",
+	"syscall.IFF_BROADCAST":                                "syscall",
+	"syscall.IFF_CANTCHANGE":                               "syscall",
+	"syscall.IFF_CANTCONFIG":                               "syscall",
+	"syscall.IFF_DEBUG":                                    "syscall",
+	"syscall.IFF_DRV_OACTIVE":                              "syscall",
+	"syscall.IFF_DRV_RUNNING":                              "syscall",
+	"syscall.IFF_DYING":                                    "syscall",
+	"syscall.IFF_DYNAMIC":                                  "syscall",
+	"syscall.IFF_LINK0":                                    "syscall",
+	"syscall.IFF_LINK1":                                    "syscall",
+	"syscall.IFF_LINK2":                                    "syscall",
+	"syscall.IFF_LOOPBACK":                                 "syscall",
+	"syscall.IFF_MASTER":                                   "syscall",
+	"syscall.IFF_MONITOR":                                  "syscall",
+	"syscall.IFF_MULTICAST":                                "syscall",
+	"syscall.IFF_NOARP":                                    "syscall",
+	"syscall.IFF_NOTRAILERS":                               "syscall",
+	"syscall.IFF_NO_PI":                                    "syscall",
+	"syscall.IFF_OACTIVE":                                  "syscall",
+	"syscall.IFF_ONE_QUEUE":                                "syscall",
+	"syscall.IFF_POINTOPOINT":                              "syscall",
+	"syscall.IFF_POINTTOPOINT":                             "syscall",
+	"syscall.IFF_PORTSEL":                                  "syscall",
+	"syscall.IFF_PPROMISC":                                 "syscall",
+	"syscall.IFF_PROMISC":                                  "syscall",
+	"syscall.IFF_RENAMING":                                 "syscall",
+	"syscall.IFF_RUNNING":                                  "syscall",
+	"syscall.IFF_SIMPLEX":                                  "syscall",
+	"syscall.IFF_SLAVE":                                    "syscall",
+	"syscall.IFF_SMART":                                    "syscall",
+	"syscall.IFF_STATICARP":                                "syscall",
+	"syscall.IFF_TAP":                                      "syscall",
+	"syscall.IFF_TUN":                                      "syscall",
+	"syscall.IFF_TUN_EXCL":                                 "syscall",
+	"syscall.IFF_UP":                                       "syscall",
+	"syscall.IFF_VNET_HDR":                                 "syscall",
+	"syscall.IFLA_ADDRESS":                                 "syscall",
+	"syscall.IFLA_BROADCAST":                               "syscall",
+	"syscall.IFLA_COST":                                    "syscall",
+	"syscall.IFLA_IFALIAS":                                 "syscall",
+	"syscall.IFLA_IFNAME":                                  "syscall",
+	"syscall.IFLA_LINK":                                    "syscall",
+	"syscall.IFLA_LINKINFO":                                "syscall",
+	"syscall.IFLA_LINKMODE":                                "syscall",
+	"syscall.IFLA_MAP":                                     "syscall",
+	"syscall.IFLA_MASTER":                                  "syscall",
+	"syscall.IFLA_MAX":                                     "syscall",
+	"syscall.IFLA_MTU":                                     "syscall",
+	"syscall.IFLA_NET_NS_PID":                              "syscall",
+	"syscall.IFLA_OPERSTATE":                               "syscall",
+	"syscall.IFLA_PRIORITY":                                "syscall",
+	"syscall.IFLA_PROTINFO":                                "syscall",
+	"syscall.IFLA_QDISC":                                   "syscall",
+	"syscall.IFLA_STATS":                                   "syscall",
+	"syscall.IFLA_TXQLEN":                                  "syscall",
+	"syscall.IFLA_UNSPEC":                                  "syscall",
+	"syscall.IFLA_WEIGHT":                                  "syscall",
+	"syscall.IFLA_WIRELESS":                                "syscall",
+	"syscall.IFNAMSIZ":                                     "syscall",
+	"syscall.IFT_1822":                                     "syscall",
+	"syscall.IFT_A12MPPSWITCH":                             "syscall",
+	"syscall.IFT_AAL2":                                     "syscall",
+	"syscall.IFT_AAL5":                                     "syscall",
+	"syscall.IFT_ADSL":                                     "syscall",
+	"syscall.IFT_AFLANE8023":                               "syscall",
+	"syscall.IFT_AFLANE8025":                               "syscall",
+	"syscall.IFT_ARAP":                                     "syscall",
+	"syscall.IFT_ARCNET":                                   "syscall",
+	"syscall.IFT_ARCNETPLUS":                               "syscall",
+	"syscall.IFT_ASYNC":                                    "syscall",
+	"syscall.IFT_ATM":                                      "syscall",
+	"syscall.IFT_ATMDXI":                                   "syscall",
+	"syscall.IFT_ATMFUNI":                                  "syscall",
+	"syscall.IFT_ATMIMA":                                   "syscall",
+	"syscall.IFT_ATMLOGICAL":                               "syscall",
+	"syscall.IFT_ATMRADIO":                                 "syscall",
+	"syscall.IFT_ATMSUBINTERFACE":                          "syscall",
+	"syscall.IFT_ATMVCIENDPT":                              "syscall",
+	"syscall.IFT_ATMVIRTUAL":                               "syscall",
+	"syscall.IFT_BGPPOLICYACCOUNTING":                      "syscall",
+	"syscall.IFT_BLUETOOTH":                                "syscall",
+	"syscall.IFT_BRIDGE":                                   "syscall",
+	"syscall.IFT_BSC":                                      "syscall",
+	"syscall.IFT_CARP":                                     "syscall",
+	"syscall.IFT_CCTEMUL":                                  "syscall",
+	"syscall.IFT_CELLULAR":                                 "syscall",
+	"syscall.IFT_CEPT":                                     "syscall",
+	"syscall.IFT_CES":                                      "syscall",
+	"syscall.IFT_CHANNEL":                                  "syscall",
+	"syscall.IFT_CNR":                                      "syscall",
+	"syscall.IFT_COFFEE":                                   "syscall",
+	"syscall.IFT_COMPOSITELINK":                            "syscall",
+	"syscall.IFT_DCN":                                      "syscall",
+	"syscall.IFT_DIGITALPOWERLINE":                         "syscall",
+	"syscall.IFT_DIGITALWRAPPEROVERHEADCHANNEL":            "syscall",
+	"syscall.IFT_DLSW":                                     "syscall",
+	"syscall.IFT_DOCSCABLEDOWNSTREAM":                      "syscall",
+	"syscall.IFT_DOCSCABLEMACLAYER":                        "syscall",
+	"syscall.IFT_DOCSCABLEUPSTREAM":                        "syscall",
+	"syscall.IFT_DOCSCABLEUPSTREAMCHANNEL":                 "syscall",
+	"syscall.IFT_DS0":                                      "syscall",
+	"syscall.IFT_DS0BUNDLE":                                "syscall",
+	"syscall.IFT_DS1FDL":                                   "syscall",
+	"syscall.IFT_DS3":                                      "syscall",
+	"syscall.IFT_DTM":                                      "syscall",
+	"syscall.IFT_DUMMY":                                    "syscall",
+	"syscall.IFT_DVBASILN":                                 "syscall",
+	"syscall.IFT_DVBASIOUT":                                "syscall",
+	"syscall.IFT_DVBRCCDOWNSTREAM":                         "syscall",
+	"syscall.IFT_DVBRCCMACLAYER":                           "syscall",
+	"syscall.IFT_DVBRCCUPSTREAM":                           "syscall",
+	"syscall.IFT_ECONET":                                   "syscall",
+	"syscall.IFT_ENC":                                      "syscall",
+	"syscall.IFT_EON":                                      "syscall",
+	"syscall.IFT_EPLRS":                                    "syscall",
+	"syscall.IFT_ESCON":                                    "syscall",
+	"syscall.IFT_ETHER":                                    "syscall",
+	"syscall.IFT_FAITH":                                    "syscall",
+	"syscall.IFT_FAST":                                     "syscall",
+	"syscall.IFT_FASTETHER":                                "syscall",
+	"syscall.IFT_FASTETHERFX":                              "syscall",
+	"syscall.IFT_FDDI":                                     "syscall",
+	"syscall.IFT_FIBRECHANNEL":                             "syscall",
+	"syscall.IFT_FRAMERELAYINTERCONNECT":                   "syscall",
+	"syscall.IFT_FRAMERELAYMPI":                            "syscall",
+	"syscall.IFT_FRDLCIENDPT":                              "syscall",
+	"syscall.IFT_FRELAY":                                   "syscall",
+	"syscall.IFT_FRELAYDCE":                                "syscall",
+	"syscall.IFT_FRF16MFRBUNDLE":                           "syscall",
+	"syscall.IFT_FRFORWARD":                                "syscall",
+	"syscall.IFT_G703AT2MB":                                "syscall",
+	"syscall.IFT_G703AT64K":                                "syscall",
+	"syscall.IFT_GIF":                                      "syscall",
+	"syscall.IFT_GIGABITETHERNET":                          "syscall",
+	"syscall.IFT_GR303IDT":                                 "syscall",
+	"syscall.IFT_GR303RDT":                                 "syscall",
+	"syscall.IFT_H323GATEKEEPER":                           "syscall",
+	"syscall.IFT_H323PROXY":                                "syscall",
+	"syscall.IFT_HDH1822":                                  "syscall",
+	"syscall.IFT_HDLC":                                     "syscall",
+	"syscall.IFT_HDSL2":                                    "syscall",
+	"syscall.IFT_HIPERLAN2":                                "syscall",
+	"syscall.IFT_HIPPI":                                    "syscall",
+	"syscall.IFT_HIPPIINTERFACE":                           "syscall",
+	"syscall.IFT_HOSTPAD":                                  "syscall",
+	"syscall.IFT_HSSI":                                     "syscall",
+	"syscall.IFT_HY":                                       "syscall",
+	"syscall.IFT_IBM370PARCHAN":                            "syscall",
+	"syscall.IFT_IDSL":                                     "syscall",
+	"syscall.IFT_IEEE1394":                                 "syscall",
+	"syscall.IFT_IEEE80211":                                "syscall",
+	"syscall.IFT_IEEE80212":                                "syscall",
+	"syscall.IFT_IEEE8023ADLAG":                            "syscall",
+	"syscall.IFT_IFGSN":                                    "syscall",
+	"syscall.IFT_IMT":                                      "syscall",
+	"syscall.IFT_INFINIBAND":                               "syscall",
+	"syscall.IFT_INTERLEAVE":                               "syscall",
+	"syscall.IFT_IP":                                       "syscall",
+	"syscall.IFT_IPFORWARD":                                "syscall",
+	"syscall.IFT_IPOVERATM":                                "syscall",
+	"syscall.IFT_IPOVERCDLC":                               "syscall",
+	"syscall.IFT_IPOVERCLAW":                               "syscall",
+	"syscall.IFT_IPSWITCH":                                 "syscall",
+	"syscall.IFT_IPXIP":                                    "syscall",
+	"syscall.IFT_ISDN":                                     "syscall",
+	"syscall.IFT_ISDNBASIC":                                "syscall",
+	"syscall.IFT_ISDNPRIMARY":                              "syscall",
+	"syscall.IFT_ISDNS":                                    "syscall",
+	"syscall.IFT_ISDNU":                                    "syscall",
+	"syscall.IFT_ISO88022LLC":                              "syscall",
+	"syscall.IFT_ISO88023":                                 "syscall",
+	"syscall.IFT_ISO88024":                                 "syscall",
+	"syscall.IFT_ISO88025":                                 "syscall",
+	"syscall.IFT_ISO88025CRFPINT":                          "syscall",
+	"syscall.IFT_ISO88025DTR":                              "syscall",
+	"syscall.IFT_ISO88025FIBER":                            "syscall",
+	"syscall.IFT_ISO88026":                                 "syscall",
+	"syscall.IFT_ISUP":                                     "syscall",
+	"syscall.IFT_L2VLAN":                                   "syscall",
+	"syscall.IFT_L3IPVLAN":                                 "syscall",
+	"syscall.IFT_L3IPXVLAN":                                "syscall",
+	"syscall.IFT_LAPB":                                     "syscall",
+	"syscall.IFT_LAPD":                                     "syscall",
+	"syscall.IFT_LAPF":                                     "syscall",
+	"syscall.IFT_LINEGROUP":                                "syscall",
+	"syscall.IFT_LOCALTALK":                                "syscall",
+	"syscall.IFT_LOOP":                                     "syscall",
+	"syscall.IFT_MEDIAMAILOVERIP":                          "syscall",
+	"syscall.IFT_MFSIGLINK":                                "syscall",
+	"syscall.IFT_MIOX25":                                   "syscall",
+	"syscall.IFT_MODEM":                                    "syscall",
+	"syscall.IFT_MPC":                                      "syscall",
+	"syscall.IFT_MPLS":                                     "syscall",
+	"syscall.IFT_MPLSTUNNEL":                               "syscall",
+	"syscall.IFT_MSDSL":                                    "syscall",
+	"syscall.IFT_MVL":                                      "syscall",
+	"syscall.IFT_MYRINET":                                  "syscall",
+	"syscall.IFT_NFAS":                                     "syscall",
+	"syscall.IFT_NSIP":                                     "syscall",
+	"syscall.IFT_OPTICALCHANNEL":                           "syscall",
+	"syscall.IFT_OPTICALTRANSPORT":                         "syscall",
+	"syscall.IFT_OTHER":                                    "syscall",
+	"syscall.IFT_P10":                                      "syscall",
+	"syscall.IFT_P80":                                      "syscall",
+	"syscall.IFT_PARA":                                     "syscall",
+	"syscall.IFT_PDP":                                      "syscall",
+	"syscall.IFT_PFLOG":                                    "syscall",
+	"syscall.IFT_PFLOW":                                    "syscall",
+	"syscall.IFT_PFSYNC":                                   "syscall",
+	"syscall.IFT_PLC":                                      "syscall",
+	"syscall.IFT_PON155":                                   "syscall",
+	"syscall.IFT_PON622":                                   "syscall",
+	"syscall.IFT_POS":                                      "syscall",
+	"syscall.IFT_PPP":                                      "syscall",
+	"syscall.IFT_PPPMULTILINKBUNDLE":                       "syscall",
+	"syscall.IFT_PROPATM":                                  "syscall",
+	"syscall.IFT_PROPBWAP2MP":                              "syscall",
+	"syscall.IFT_PROPCNLS":                                 "syscall",
+	"syscall.IFT_PROPDOCSWIRELESSDOWNSTREAM":               "syscall",
+	"syscall.IFT_PROPDOCSWIRELESSMACLAYER":                 "syscall",
+	"syscall.IFT_PROPDOCSWIRELESSUPSTREAM":                 "syscall",
+	"syscall.IFT_PROPMUX":                                  "syscall",
+	"syscall.IFT_PROPVIRTUAL":                              "syscall",
+	"syscall.IFT_PROPWIRELESSP2P":                          "syscall",
+	"syscall.IFT_PTPSERIAL":                                "syscall",
+	"syscall.IFT_PVC":                                      "syscall",
+	"syscall.IFT_Q2931":                                    "syscall",
+	"syscall.IFT_QLLC":                                     "syscall",
+	"syscall.IFT_RADIOMAC":                                 "syscall",
+	"syscall.IFT_RADSL":                                    "syscall",
+	"syscall.IFT_REACHDSL":                                 "syscall",
+	"syscall.IFT_RFC1483":                                  "syscall",
+	"syscall.IFT_RS232":                                    "syscall",
+	"syscall.IFT_RSRB":                                     "syscall",
+	"syscall.IFT_SDLC":                                     "syscall",
+	"syscall.IFT_SDSL":                                     "syscall",
+	"syscall.IFT_SHDSL":                                    "syscall",
+	"syscall.IFT_SIP":                                      "syscall",
+	"syscall.IFT_SIPSIG":                                   "syscall",
+	"syscall.IFT_SIPTG":                                    "syscall",
+	"syscall.IFT_SLIP":                                     "syscall",
+	"syscall.IFT_SMDSDXI":                                  "syscall",
+	"syscall.IFT_SMDSICIP":                                 "syscall",
+	"syscall.IFT_SONET":                                    "syscall",
+	"syscall.IFT_SONETOVERHEADCHANNEL":                     "syscall",
+	"syscall.IFT_SONETPATH":                                "syscall",
+	"syscall.IFT_SONETVT":                                  "syscall",
+	"syscall.IFT_SRP":                                      "syscall",
+	"syscall.IFT_SS7SIGLINK":                               "syscall",
+	"syscall.IFT_STACKTOSTACK":                             "syscall",
+	"syscall.IFT_STARLAN":                                  "syscall",
+	"syscall.IFT_STF":                                      "syscall",
+	"syscall.IFT_T1":                                       "syscall",
+	"syscall.IFT_TDLC":                                     "syscall",
+	"syscall.IFT_TELINK":                                   "syscall",
+	"syscall.IFT_TERMPAD":                                  "syscall",
+	"syscall.IFT_TR008":                                    "syscall",
+	"syscall.IFT_TRANSPHDLC":                               "syscall",
+	"syscall.IFT_TUNNEL":                                   "syscall",
+	"syscall.IFT_ULTRA":                                    "syscall",
+	"syscall.IFT_USB":                                      "syscall",
+	"syscall.IFT_V11":                                      "syscall",
+	"syscall.IFT_V35":                                      "syscall",
+	"syscall.IFT_V36":                                      "syscall",
+	"syscall.IFT_V37":                                      "syscall",
+	"syscall.IFT_VDSL":                                     "syscall",
+	"syscall.IFT_VIRTUALIPADDRESS":                         "syscall",
+	"syscall.IFT_VIRTUALTG":                                "syscall",
+	"syscall.IFT_VOICEDID":                                 "syscall",
+	"syscall.IFT_VOICEEM":                                  "syscall",
+	"syscall.IFT_VOICEEMFGD":                               "syscall",
+	"syscall.IFT_VOICEENCAP":                               "syscall",
+	"syscall.IFT_VOICEFGDEANA":                             "syscall",
+	"syscall.IFT_VOICEFXO":                                 "syscall",
+	"syscall.IFT_VOICEFXS":                                 "syscall",
+	"syscall.IFT_VOICEOVERATM":                             "syscall",
+	"syscall.IFT_VOICEOVERCABLE":                           "syscall",
+	"syscall.IFT_VOICEOVERFRAMERELAY":                      "syscall",
+	"syscall.IFT_VOICEOVERIP":                              "syscall",
+	"syscall.IFT_X213":                                     "syscall",
+	"syscall.IFT_X25":                                      "syscall",
+	"syscall.IFT_X25DDN":                                   "syscall",
+	"syscall.IFT_X25HUNTGROUP":                             "syscall",
+	"syscall.IFT_X25MLP":                                   "syscall",
+	"syscall.IFT_X25PLE":                                   "syscall",
+	"syscall.IFT_XETHER":                                   "syscall",
+	"syscall.IGNBRK":                                       "syscall",
+	"syscall.IGNCR":                                        "syscall",
+	"syscall.IGNORE":                                       "syscall",
+	"syscall.IGNPAR":                                       "syscall",
+	"syscall.IMAXBEL":                                      "syscall",
+	"syscall.INFINITE":                                     "syscall",
+	"syscall.INLCR":                                        "syscall",
+	"syscall.INPCK":                                        "syscall",
+	"syscall.INVALID_FILE_ATTRIBUTES":                      "syscall",
+	"syscall.IN_ACCESS":                                    "syscall",
+	"syscall.IN_ALL_EVENTS":                                "syscall",
+	"syscall.IN_ATTRIB":                                    "syscall",
+	"syscall.IN_CLASSA_HOST":                               "syscall",
+	"syscall.IN_CLASSA_MAX":                                "syscall",
+	"syscall.IN_CLASSA_NET":                                "syscall",
+	"syscall.IN_CLASSA_NSHIFT":                             "syscall",
+	"syscall.IN_CLASSB_HOST":                               "syscall",
+	"syscall.IN_CLASSB_MAX":                                "syscall",
+	"syscall.IN_CLASSB_NET":                                "syscall",
+	"syscall.IN_CLASSB_NSHIFT":                             "syscall",
+	"syscall.IN_CLASSC_HOST":                               "syscall",
+	"syscall.IN_CLASSC_NET":                                "syscall",
+	"syscall.IN_CLASSC_NSHIFT":                             "syscall",
+	"syscall.IN_CLASSD_HOST":                               "syscall",
+	"syscall.IN_CLASSD_NET":                                "syscall",
+	"syscall.IN_CLASSD_NSHIFT":                             "syscall",
+	"syscall.IN_CLOEXEC":                                   "syscall",
+	"syscall.IN_CLOSE":                                     "syscall",
+	"syscall.IN_CLOSE_NOWRITE":                             "syscall",
+	"syscall.IN_CLOSE_WRITE":                               "syscall",
+	"syscall.IN_CREATE":                                    "syscall",
+	"syscall.IN_DELETE":                                    "syscall",
+	"syscall.IN_DELETE_SELF":                               "syscall",
+	"syscall.IN_DONT_FOLLOW":                               "syscall",
+	"syscall.IN_EXCL_UNLINK":                               "syscall",
+	"syscall.IN_IGNORED":                                   "syscall",
+	"syscall.IN_ISDIR":                                     "syscall",
+	"syscall.IN_LINKLOCALNETNUM":                           "syscall",
+	"syscall.IN_LOOPBACKNET":                               "syscall",
+	"syscall.IN_MASK_ADD":                                  "syscall",
+	"syscall.IN_MODIFY":                                    "syscall",
+	"syscall.IN_MOVE":                                      "syscall",
+	"syscall.IN_MOVED_FROM":                                "syscall",
+	"syscall.IN_MOVED_TO":                                  "syscall",
+	"syscall.IN_MOVE_SELF":                                 "syscall",
+	"syscall.IN_NONBLOCK":                                  "syscall",
+	"syscall.IN_ONESHOT":                                   "syscall",
+	"syscall.IN_ONLYDIR":                                   "syscall",
+	"syscall.IN_OPEN":                                      "syscall",
+	"syscall.IN_Q_OVERFLOW":                                "syscall",
+	"syscall.IN_RFC3021_HOST":                              "syscall",
+	"syscall.IN_RFC3021_MASK":                              "syscall",
+	"syscall.IN_RFC3021_NET":                               "syscall",
+	"syscall.IN_RFC3021_NSHIFT":                            "syscall",
+	"syscall.IN_UNMOUNT":                                   "syscall",
+	"syscall.IOC_IN":                                       "syscall",
+	"syscall.IOC_INOUT":                                    "syscall",
+	"syscall.IOC_OUT":                                      "syscall",
+	"syscall.IOC_WS2":                                      "syscall",
+	"syscall.IPMreq":                                       "syscall",
+	"syscall.IPMreqn":                                      "syscall",
+	"syscall.IPPROTO_3PC":                                  "syscall",
+	"syscall.IPPROTO_ADFS":                                 "syscall",
+	"syscall.IPPROTO_AH":                                   "syscall",
+	"syscall.IPPROTO_AHIP":                                 "syscall",
+	"syscall.IPPROTO_APES":                                 "syscall",
+	"syscall.IPPROTO_ARGUS":                                "syscall",
+	"syscall.IPPROTO_AX25":                                 "syscall",
+	"syscall.IPPROTO_BHA":                                  "syscall",
+	"syscall.IPPROTO_BLT":                                  "syscall",
+	"syscall.IPPROTO_BRSATMON":                             "syscall",
+	"syscall.IPPROTO_CARP":                                 "syscall",
+	"syscall.IPPROTO_CFTP":                                 "syscall",
+	"syscall.IPPROTO_CHAOS":                                "syscall",
+	"syscall.IPPROTO_CMTP":                                 "syscall",
+	"syscall.IPPROTO_COMP":                                 "syscall",
+	"syscall.IPPROTO_CPHB":                                 "syscall",
+	"syscall.IPPROTO_CPNX":                                 "syscall",
+	"syscall.IPPROTO_DCCP":                                 "syscall",
+	"syscall.IPPROTO_DDP":                                  "syscall",
+	"syscall.IPPROTO_DGP":                                  "syscall",
+	"syscall.IPPROTO_DIVERT":                               "syscall",
+	"syscall.IPPROTO_DONE":                                 "syscall",
+	"syscall.IPPROTO_DSTOPTS":                              "syscall",
+	"syscall.IPPROTO_EGP":                                  "syscall",
+	"syscall.IPPROTO_EMCON":                                "syscall",
+	"syscall.IPPROTO_ENCAP":                                "syscall",
+	"syscall.IPPROTO_EON":                                  "syscall",
+	"syscall.IPPROTO_ESP":                                  "syscall",
+	"syscall.IPPROTO_ETHERIP":                              "syscall",
+	"syscall.IPPROTO_FRAGMENT":                             "syscall",
+	"syscall.IPPROTO_GGP":                                  "syscall",
+	"syscall.IPPROTO_GMTP":                                 "syscall",
+	"syscall.IPPROTO_GRE":                                  "syscall",
+	"syscall.IPPROTO_HELLO":                                "syscall",
+	"syscall.IPPROTO_HMP":                                  "syscall",
+	"syscall.IPPROTO_HOPOPTS":                              "syscall",
+	"syscall.IPPROTO_ICMP":                                 "syscall",
+	"syscall.IPPROTO_ICMPV6":                               "syscall",
+	"syscall.IPPROTO_IDP":                                  "syscall",
+	"syscall.IPPROTO_IDPR":                                 "syscall",
+	"syscall.IPPROTO_IDRP":                                 "syscall",
+	"syscall.IPPROTO_IGMP":                                 "syscall",
+	"syscall.IPPROTO_IGP":                                  "syscall",
+	"syscall.IPPROTO_IGRP":                                 "syscall",
+	"syscall.IPPROTO_IL":                                   "syscall",
+	"syscall.IPPROTO_INLSP":                                "syscall",
+	"syscall.IPPROTO_INP":                                  "syscall",
+	"syscall.IPPROTO_IP":                                   "syscall",
+	"syscall.IPPROTO_IPCOMP":                               "syscall",
+	"syscall.IPPROTO_IPCV":                                 "syscall",
+	"syscall.IPPROTO_IPEIP":                                "syscall",
+	"syscall.IPPROTO_IPIP":                                 "syscall",
+	"syscall.IPPROTO_IPPC":                                 "syscall",
+	"syscall.IPPROTO_IPV4":                                 "syscall",
+	"syscall.IPPROTO_IPV6":                                 "syscall",
+	"syscall.IPPROTO_IPV6_ICMP":                            "syscall",
+	"syscall.IPPROTO_IRTP":                                 "syscall",
+	"syscall.IPPROTO_KRYPTOLAN":                            "syscall",
+	"syscall.IPPROTO_LARP":                                 "syscall",
+	"syscall.IPPROTO_LEAF1":                                "syscall",
+	"syscall.IPPROTO_LEAF2":                                "syscall",
+	"syscall.IPPROTO_MAX":                                  "syscall",
+	"syscall.IPPROTO_MAXID":                                "syscall",
+	"syscall.IPPROTO_MEAS":                                 "syscall",
+	"syscall.IPPROTO_MH":                                   "syscall",
+	"syscall.IPPROTO_MHRP":                                 "syscall",
+	"syscall.IPPROTO_MICP":                                 "syscall",
+	"syscall.IPPROTO_MOBILE":                               "syscall",
+	"syscall.IPPROTO_MPLS":                                 "syscall",
+	"syscall.IPPROTO_MTP":                                  "syscall",
+	"syscall.IPPROTO_MUX":                                  "syscall",
+	"syscall.IPPROTO_ND":                                   "syscall",
+	"syscall.IPPROTO_NHRP":                                 "syscall",
+	"syscall.IPPROTO_NONE":                                 "syscall",
+	"syscall.IPPROTO_NSP":                                  "syscall",
+	"syscall.IPPROTO_NVPII":                                "syscall",
+	"syscall.IPPROTO_OLD_DIVERT":                           "syscall",
+	"syscall.IPPROTO_OSPFIGP":                              "syscall",
+	"syscall.IPPROTO_PFSYNC":                               "syscall",
+	"syscall.IPPROTO_PGM":                                  "syscall",
+	"syscall.IPPROTO_PIGP":                                 "syscall",
+	"syscall.IPPROTO_PIM":                                  "syscall",
+	"syscall.IPPROTO_PRM":                                  "syscall",
+	"syscall.IPPROTO_PUP":                                  "syscall",
+	"syscall.IPPROTO_PVP":                                  "syscall",
+	"syscall.IPPROTO_RAW":                                  "syscall",
+	"syscall.IPPROTO_RCCMON":                               "syscall",
+	"syscall.IPPROTO_RDP":                                  "syscall",
+	"syscall.IPPROTO_ROUTING":                              "syscall",
+	"syscall.IPPROTO_RSVP":                                 "syscall",
+	"syscall.IPPROTO_RVD":                                  "syscall",
+	"syscall.IPPROTO_SATEXPAK":                             "syscall",
+	"syscall.IPPROTO_SATMON":                               "syscall",
+	"syscall.IPPROTO_SCCSP":                                "syscall",
+	"syscall.IPPROTO_SCTP":                                 "syscall",
+	"syscall.IPPROTO_SDRP":                                 "syscall",
+	"syscall.IPPROTO_SEND":                                 "syscall",
+	"syscall.IPPROTO_SEP":                                  "syscall",
+	"syscall.IPPROTO_SKIP":                                 "syscall",
+	"syscall.IPPROTO_SPACER":                               "syscall",
+	"syscall.IPPROTO_SRPC":                                 "syscall",
+	"syscall.IPPROTO_ST":                                   "syscall",
+	"syscall.IPPROTO_SVMTP":                                "syscall",
+	"syscall.IPPROTO_SWIPE":                                "syscall",
+	"syscall.IPPROTO_TCF":                                  "syscall",
+	"syscall.IPPROTO_TCP":                                  "syscall",
+	"syscall.IPPROTO_TLSP":                                 "syscall",
+	"syscall.IPPROTO_TP":                                   "syscall",
+	"syscall.IPPROTO_TPXX":                                 "syscall",
+	"syscall.IPPROTO_TRUNK1":                               "syscall",
+	"syscall.IPPROTO_TRUNK2":                               "syscall",
+	"syscall.IPPROTO_TTP":                                  "syscall",
+	"syscall.IPPROTO_UDP":                                  "syscall",
+	"syscall.IPPROTO_UDPLITE":                              "syscall",
+	"syscall.IPPROTO_VINES":                                "syscall",
+	"syscall.IPPROTO_VISA":                                 "syscall",
+	"syscall.IPPROTO_VMTP":                                 "syscall",
+	"syscall.IPPROTO_VRRP":                                 "syscall",
+	"syscall.IPPROTO_WBEXPAK":                              "syscall",
+	"syscall.IPPROTO_WBMON":                                "syscall",
+	"syscall.IPPROTO_WSN":                                  "syscall",
+	"syscall.IPPROTO_XNET":                                 "syscall",
+	"syscall.IPPROTO_XTP":                                  "syscall",
+	"syscall.IPV6_2292DSTOPTS":                             "syscall",
+	"syscall.IPV6_2292HOPLIMIT":                            "syscall",
+	"syscall.IPV6_2292HOPOPTS":                             "syscall",
+	"syscall.IPV6_2292NEXTHOP":                             "syscall",
+	"syscall.IPV6_2292PKTINFO":                             "syscall",
+	"syscall.IPV6_2292PKTOPTIONS":                          "syscall",
+	"syscall.IPV6_2292RTHDR":                               "syscall",
+	"syscall.IPV6_ADDRFORM":                                "syscall",
+	"syscall.IPV6_ADD_MEMBERSHIP":                          "syscall",
+	"syscall.IPV6_AUTHHDR":                                 "syscall",
+	"syscall.IPV6_AUTH_LEVEL":                              "syscall",
+	"syscall.IPV6_AUTOFLOWLABEL":                           "syscall",
+	"syscall.IPV6_BINDANY":                                 "syscall",
+	"syscall.IPV6_BINDV6ONLY":                              "syscall",
+	"syscall.IPV6_BOUND_IF":                                "syscall",
+	"syscall.IPV6_CHECKSUM":                                "syscall",
+	"syscall.IPV6_DEFAULT_MULTICAST_HOPS":                  "syscall",
+	"syscall.IPV6_DEFAULT_MULTICAST_LOOP":                  "syscall",
+	"syscall.IPV6_DEFHLIM":                                 "syscall",
+	"syscall.IPV6_DONTFRAG":                                "syscall",
+	"syscall.IPV6_DROP_MEMBERSHIP":                         "syscall",
+	"syscall.IPV6_DSTOPTS":                                 "syscall",
+	"syscall.IPV6_ESP_NETWORK_LEVEL":                       "syscall",
+	"syscall.IPV6_ESP_TRANS_LEVEL":                         "syscall",
+	"syscall.IPV6_FAITH":                                   "syscall",
+	"syscall.IPV6_FLOWINFO_MASK":                           "syscall",
+	"syscall.IPV6_FLOWLABEL_MASK":                          "syscall",
+	"syscall.IPV6_FRAGTTL":                                 "syscall",
+	"syscall.IPV6_FW_ADD":                                  "syscall",
+	"syscall.IPV6_FW_DEL":                                  "syscall",
+	"syscall.IPV6_FW_FLUSH":                                "syscall",
+	"syscall.IPV6_FW_GET":                                  "syscall",
+	"syscall.IPV6_FW_ZERO":                                 "syscall",
+	"syscall.IPV6_HLIMDEC":                                 "syscall",
+	"syscall.IPV6_HOPLIMIT":                                "syscall",
+	"syscall.IPV6_HOPOPTS":                                 "syscall",
+	"syscall.IPV6_IPCOMP_LEVEL":                            "syscall",
+	"syscall.IPV6_IPSEC_POLICY":                            "syscall",
+	"syscall.IPV6_JOIN_ANYCAST":                            "syscall",
+	"syscall.IPV6_JOIN_GROUP":                              "syscall",
+	"syscall.IPV6_LEAVE_ANYCAST":                           "syscall",
+	"syscall.IPV6_LEAVE_GROUP":                             "syscall",
+	"syscall.IPV6_MAXHLIM":                                 "syscall",
+	"syscall.IPV6_MAXOPTHDR":                               "syscall",
+	"syscall.IPV6_MAXPACKET":                               "syscall",
+	"syscall.IPV6_MAX_GROUP_SRC_FILTER":                    "syscall",
+	"syscall.IPV6_MAX_MEMBERSHIPS":                         "syscall",
+	"syscall.IPV6_MAX_SOCK_SRC_FILTER":                     "syscall",
+	"syscall.IPV6_MIN_MEMBERSHIPS":                         "syscall",
+	"syscall.IPV6_MMTU":                                    "syscall",
+	"syscall.IPV6_MSFILTER":                                "syscall",
+	"syscall.IPV6_MTU":                                     "syscall",
+	"syscall.IPV6_MTU_DISCOVER":                            "syscall",
+	"syscall.IPV6_MULTICAST_HOPS":                          "syscall",
+	"syscall.IPV6_MULTICAST_IF":                            "syscall",
+	"syscall.IPV6_MULTICAST_LOOP":                          "syscall",
+	"syscall.IPV6_NEXTHOP":                                 "syscall",
+	"syscall.IPV6_OPTIONS":                                 "syscall",
+	"syscall.IPV6_PATHMTU":                                 "syscall",
+	"syscall.IPV6_PIPEX":                                   "syscall",
+	"syscall.IPV6_PKTINFO":                                 "syscall",
+	"syscall.IPV6_PMTUDISC_DO":                             "syscall",
+	"syscall.IPV6_PMTUDISC_DONT":                           "syscall",
+	"syscall.IPV6_PMTUDISC_PROBE":                          "syscall",
+	"syscall.IPV6_PMTUDISC_WANT":                           "syscall",
+	"syscall.IPV6_PORTRANGE":                               "syscall",
+	"syscall.IPV6_PORTRANGE_DEFAULT":                       "syscall",
+	"syscall.IPV6_PORTRANGE_HIGH":                          "syscall",
+	"syscall.IPV6_PORTRANGE_LOW":                           "syscall",
+	"syscall.IPV6_PREFER_TEMPADDR":                         "syscall",
+	"syscall.IPV6_RECVDSTOPTS":                             "syscall",
+	"syscall.IPV6_RECVERR":                                 "syscall",
+	"syscall.IPV6_RECVHOPLIMIT":                            "syscall",
+	"syscall.IPV6_RECVHOPOPTS":                             "syscall",
+	"syscall.IPV6_RECVPATHMTU":                             "syscall",
+	"syscall.IPV6_RECVPKTINFO":                             "syscall",
+	"syscall.IPV6_RECVRTHDR":                               "syscall",
+	"syscall.IPV6_RECVTCLASS":                              "syscall",
+	"syscall.IPV6_ROUTER_ALERT":                            "syscall",
+	"syscall.IPV6_RTABLE":                                  "syscall",
+	"syscall.IPV6_RTHDR":                                   "syscall",
+	"syscall.IPV6_RTHDRDSTOPTS":                            "syscall",
+	"syscall.IPV6_RTHDR_LOOSE":                             "syscall",
+	"syscall.IPV6_RTHDR_STRICT":                            "syscall",
+	"syscall.IPV6_RTHDR_TYPE_0":                            "syscall",
+	"syscall.IPV6_RXDSTOPTS":                               "syscall",
+	"syscall.IPV6_RXHOPOPTS":                               "syscall",
+	"syscall.IPV6_SOCKOPT_RESERVED1":                       "syscall",
+	"syscall.IPV6_TCLASS":                                  "syscall",
+	"syscall.IPV6_UNICAST_HOPS":                            "syscall",
+	"syscall.IPV6_USE_MIN_MTU":                             "syscall",
+	"syscall.IPV6_V6ONLY":                                  "syscall",
+	"syscall.IPV6_VERSION":                                 "syscall",
+	"syscall.IPV6_VERSION_MASK":                            "syscall",
+	"syscall.IPV6_XFRM_POLICY":                             "syscall",
+	"syscall.IP_ADD_MEMBERSHIP":                            "syscall",
+	"syscall.IP_ADD_SOURCE_MEMBERSHIP":                     "syscall",
+	"syscall.IP_AUTH_LEVEL":                                "syscall",
+	"syscall.IP_BINDANY":                                   "syscall",
+	"syscall.IP_BLOCK_SOURCE":                              "syscall",
+	"syscall.IP_BOUND_IF":                                  "syscall",
+	"syscall.IP_DEFAULT_MULTICAST_LOOP":                    "syscall",
+	"syscall.IP_DEFAULT_MULTICAST_TTL":                     "syscall",
+	"syscall.IP_DF":                                        "syscall",
+	"syscall.IP_DONTFRAG":                                  "syscall",
+	"syscall.IP_DROP_MEMBERSHIP":                           "syscall",
+	"syscall.IP_DROP_SOURCE_MEMBERSHIP":                    "syscall",
+	"syscall.IP_DUMMYNET3":                                 "syscall",
+	"syscall.IP_DUMMYNET_CONFIGURE":                        "syscall",
+	"syscall.IP_DUMMYNET_DEL":                              "syscall",
+	"syscall.IP_DUMMYNET_FLUSH":                            "syscall",
+	"syscall.IP_DUMMYNET_GET":                              "syscall",
+	"syscall.IP_EF":                                        "syscall",
+	"syscall.IP_ERRORMTU":                                  "syscall",
+	"syscall.IP_ESP_NETWORK_LEVEL":                         "syscall",
+	"syscall.IP_ESP_TRANS_LEVEL":                           "syscall",
+	"syscall.IP_FAITH":                                     "syscall",
+	"syscall.IP_FREEBIND":                                  "syscall",
+	"syscall.IP_FW3":                                       "syscall",
+	"syscall.IP_FW_ADD":                                    "syscall",
+	"syscall.IP_FW_DEL":                                    "syscall",
+	"syscall.IP_FW_FLUSH":                                  "syscall",
+	"syscall.IP_FW_GET":                                    "syscall",
+	"syscall.IP_FW_NAT_CFG":                                "syscall",
+	"syscall.IP_FW_NAT_DEL":                                "syscall",
+	"syscall.IP_FW_NAT_GET_CONFIG":                         "syscall",
+	"syscall.IP_FW_NAT_GET_LOG":                            "syscall",
+	"syscall.IP_FW_RESETLOG":                               "syscall",
+	"syscall.IP_FW_TABLE_ADD":                              "syscall",
+	"syscall.IP_FW_TABLE_DEL":                              "syscall",
+	"syscall.IP_FW_TABLE_FLUSH":                            "syscall",
+	"syscall.IP_FW_TABLE_GETSIZE":                          "syscall",
+	"syscall.IP_FW_TABLE_LIST":                             "syscall",
+	"syscall.IP_FW_ZERO":                                   "syscall",
+	"syscall.IP_HDRINCL":                                   "syscall",
+	"syscall.IP_IPCOMP_LEVEL":                              "syscall",
+	"syscall.IP_IPSECFLOWINFO":                             "syscall",
+	"syscall.IP_IPSEC_LOCAL_AUTH":                          "syscall",
+	"syscall.IP_IPSEC_LOCAL_CRED":                          "syscall",
+	"syscall.IP_IPSEC_LOCAL_ID":                            "syscall",
+	"syscall.IP_IPSEC_POLICY":                              "syscall",
+	"syscall.IP_IPSEC_REMOTE_AUTH":                         "syscall",
+	"syscall.IP_IPSEC_REMOTE_CRED":                         "syscall",
+	"syscall.IP_IPSEC_REMOTE_ID":                           "syscall",
+	"syscall.IP_MAXPACKET":                                 "syscall",
+	"syscall.IP_MAX_GROUP_SRC_FILTER":                      "syscall",
+	"syscall.IP_MAX_MEMBERSHIPS":                           "syscall",
+	"syscall.IP_MAX_SOCK_MUTE_FILTER":                      "syscall",
+	"syscall.IP_MAX_SOCK_SRC_FILTER":                       "syscall",
+	"syscall.IP_MAX_SOURCE_FILTER":                         "syscall",
+	"syscall.IP_MF":                                        "syscall",
+	"syscall.IP_MINFRAGSIZE":                               "syscall",
+	"syscall.IP_MINTTL":                                    "syscall",
+	"syscall.IP_MIN_MEMBERSHIPS":                           "syscall",
+	"syscall.IP_MSFILTER":                                  "syscall",
+	"syscall.IP_MSS":                                       "syscall",
+	"syscall.IP_MTU":                                       "syscall",
+	"syscall.IP_MTU_DISCOVER":                              "syscall",
+	"syscall.IP_MULTICAST_IF":                              "syscall",
+	"syscall.IP_MULTICAST_IFINDEX":                         "syscall",
+	"syscall.IP_MULTICAST_LOOP":                            "syscall",
+	"syscall.IP_MULTICAST_TTL":                             "syscall",
+	"syscall.IP_MULTICAST_VIF":                             "syscall",
+	"syscall.IP_NAT__XXX":                                  "syscall",
+	"syscall.IP_OFFMASK":                                   "syscall",
+	"syscall.IP_OLD_FW_ADD":                                "syscall",
+	"syscall.IP_OLD_FW_DEL":                                "syscall",
+	"syscall.IP_OLD_FW_FLUSH":                              "syscall",
+	"syscall.IP_OLD_FW_GET":                                "syscall",
+	"syscall.IP_OLD_FW_RESETLOG":                           "syscall",
+	"syscall.IP_OLD_FW_ZERO":                               "syscall",
+	"syscall.IP_ONESBCAST":                                 "syscall",
+	"syscall.IP_OPTIONS":                                   "syscall",
+	"syscall.IP_ORIGDSTADDR":                               "syscall",
+	"syscall.IP_PASSSEC":                                   "syscall",
+	"syscall.IP_PIPEX":                                     "syscall",
+	"syscall.IP_PKTINFO":                                   "syscall",
+	"syscall.IP_PKTOPTIONS":                                "syscall",
+	"syscall.IP_PMTUDISC":                                  "syscall",
+	"syscall.IP_PMTUDISC_DO":                               "syscall",
+	"syscall.IP_PMTUDISC_DONT":                             "syscall",
+	"syscall.IP_PMTUDISC_PROBE":                            "syscall",
+	"syscall.IP_PMTUDISC_WANT":                             "syscall",
+	"syscall.IP_PORTRANGE":                                 "syscall",
+	"syscall.IP_PORTRANGE_DEFAULT":                         "syscall",
+	"syscall.IP_PORTRANGE_HIGH":                            "syscall",
+	"syscall.IP_PORTRANGE_LOW":                             "syscall",
+	"syscall.IP_RECVDSTADDR":                               "syscall",
+	"syscall.IP_RECVDSTPORT":                               "syscall",
+	"syscall.IP_RECVERR":                                   "syscall",
+	"syscall.IP_RECVIF":                                    "syscall",
+	"syscall.IP_RECVOPTS":                                  "syscall",
+	"syscall.IP_RECVORIGDSTADDR":                           "syscall",
+	"syscall.IP_RECVPKTINFO":                               "syscall",
+	"syscall.IP_RECVRETOPTS":                               "syscall",
+	"syscall.IP_RECVRTABLE":                                "syscall",
+	"syscall.IP_RECVTOS":                                   "syscall",
+	"syscall.IP_RECVTTL":                                   "syscall",
+	"syscall.IP_RETOPTS":                                   "syscall",
+	"syscall.IP_RF":                                        "syscall",
+	"syscall.IP_ROUTER_ALERT":                              "syscall",
+	"syscall.IP_RSVP_OFF":                                  "syscall",
+	"syscall.IP_RSVP_ON":                                   "syscall",
+	"syscall.IP_RSVP_VIF_OFF":                              "syscall",
+	"syscall.IP_RSVP_VIF_ON":                               "syscall",
+	"syscall.IP_RTABLE":                                    "syscall",
+	"syscall.IP_SENDSRCADDR":                               "syscall",
+	"syscall.IP_STRIPHDR":                                  "syscall",
+	"syscall.IP_TOS":                                       "syscall",
+	"syscall.IP_TRAFFIC_MGT_BACKGROUND":                    "syscall",
+	"syscall.IP_TRANSPARENT":                               "syscall",
+	"syscall.IP_TTL":                                       "syscall",
+	"syscall.IP_UNBLOCK_SOURCE":                            "syscall",
+	"syscall.IP_XFRM_POLICY":                               "syscall",
+	"syscall.IPv6MTUInfo":                                  "syscall",
+	"syscall.IPv6Mreq":                                     "syscall",
+	"syscall.ISIG":                                         "syscall",
+	"syscall.ISTRIP":                                       "syscall",
+	"syscall.IUCLC":                                        "syscall",
+	"syscall.IUTF8":                                        "syscall",
+	"syscall.IXANY":                                        "syscall",
+	"syscall.IXOFF":                                        "syscall",
+	"syscall.IXON":                                         "syscall",
+	"syscall.IfAddrmsg":                                    "syscall",
+	"syscall.IfAnnounceMsghdr":                             "syscall",
+	"syscall.IfData":                                       "syscall",
+	"syscall.IfInfomsg":                                    "syscall",
+	"syscall.IfMsghdr":                                     "syscall",
+	"syscall.IfaMsghdr":                                    "syscall",
+	"syscall.IfmaMsghdr":                                   "syscall",
+	"syscall.IfmaMsghdr2":                                  "syscall",
+	"syscall.ImplementsGetwd":                              "syscall",
+	"syscall.Inet4Pktinfo":                                 "syscall",
+	"syscall.Inet6Pktinfo":                                 "syscall",
+	"syscall.InotifyAddWatch":                              "syscall",
+	"syscall.InotifyEvent":                                 "syscall",
+	"syscall.InotifyInit":                                  "syscall",
+	"syscall.InotifyInit1":                                 "syscall",
+	"syscall.InotifyRmWatch":                               "syscall",
+	"syscall.InterfaceAddrMessage":                         "syscall",
+	"syscall.InterfaceAnnounceMessage":                     "syscall",
+	"syscall.InterfaceInfo":                                "syscall",
+	"syscall.InterfaceMessage":                             "syscall",
+	"syscall.InterfaceMulticastAddrMessage":                "syscall",
+	"syscall.InvalidHandle":                                "syscall",
+	"syscall.Ioperm":                                       "syscall",
+	"syscall.Iopl":                                         "syscall",
+	"syscall.Iovec":                                        "syscall",
+	"syscall.IpAdapterInfo":                                "syscall",
+	"syscall.IpAddrString":                                 "syscall",
+	"syscall.IpAddressString":                              "syscall",
+	"syscall.IpMaskString":                                 "syscall",
+	"syscall.Issetugid":                                    "syscall",
+	"syscall.KEY_ALL_ACCESS":                               "syscall",
+	"syscall.KEY_CREATE_LINK":                              "syscall",
+	"syscall.KEY_CREATE_SUB_KEY":                           "syscall",
+	"syscall.KEY_ENUMERATE_SUB_KEYS":                       "syscall",
+	"syscall.KEY_EXECUTE":                                  "syscall",
+	"syscall.KEY_NOTIFY":                                   "syscall",
+	"syscall.KEY_QUERY_VALUE":                              "syscall",
+	"syscall.KEY_READ":                                     "syscall",
+	"syscall.KEY_SET_VALUE":                                "syscall",
+	"syscall.KEY_WOW64_32KEY":                              "syscall",
+	"syscall.KEY_WOW64_64KEY":                              "syscall",
+	"syscall.KEY_WRITE":                                    "syscall",
+	"syscall.Kevent":                                       "syscall",
+	"syscall.Kevent_t":                                     "syscall",
+	"syscall.Kill":                                         "syscall",
+	"syscall.Klogctl":                                      "syscall",
+	"syscall.Kqueue":                                       "syscall",
+	"syscall.LANG_ENGLISH":                                 "syscall",
+	"syscall.LAYERED_PROTOCOL":                             "syscall",
+	"syscall.LCNT_OVERLOAD_FLUSH":                          "syscall",
+	"syscall.LINUX_REBOOT_CMD_CAD_OFF":                     "syscall",
+	"syscall.LINUX_REBOOT_CMD_CAD_ON":                      "syscall",
+	"syscall.LINUX_REBOOT_CMD_HALT":                        "syscall",
+	"syscall.LINUX_REBOOT_CMD_KEXEC":                       "syscall",
+	"syscall.LINUX_REBOOT_CMD_POWER_OFF":                   "syscall",
+	"syscall.LINUX_REBOOT_CMD_RESTART":                     "syscall",
+	"syscall.LINUX_REBOOT_CMD_RESTART2":                    "syscall",
+	"syscall.LINUX_REBOOT_CMD_SW_SUSPEND":                  "syscall",
+	"syscall.LINUX_REBOOT_MAGIC1":                          "syscall",
+	"syscall.LINUX_REBOOT_MAGIC2":                          "syscall",
+	"syscall.LOCK_EX":                                      "syscall",
+	"syscall.LOCK_NB":                                      "syscall",
+	"syscall.LOCK_SH":                                      "syscall",
+	"syscall.LOCK_UN":                                      "syscall",
+	"syscall.LazyDLL":                                      "syscall",
+	"syscall.LazyProc":                                     "syscall",
+	"syscall.Lchown":                                       "syscall",
+	"syscall.Linger":                                       "syscall",
+	"syscall.Link":                                         "syscall",
+	"syscall.Listen":                                       "syscall",
+	"syscall.Listxattr":                                    "syscall",
+	"syscall.LoadCancelIoEx":                               "syscall",
+	"syscall.LoadConnectEx":                                "syscall",
+	"syscall.LoadDLL":                                      "syscall",
+	"syscall.LoadGetAddrInfo":                              "syscall",
+	"syscall.LoadLibrary":                                  "syscall",
+	"syscall.LoadSetFileCompletionNotificationModes":       "syscall",
+	"syscall.LocalFree":                                    "syscall",
+	"syscall.Log2phys_t":                                   "syscall",
+	"syscall.LookupAccountName":                            "syscall",
+	"syscall.LookupAccountSid":                             "syscall",
+	"syscall.LookupSID":                                    "syscall",
+	"syscall.LsfJump":                                      "syscall",
+	"syscall.LsfSocket":                                    "syscall",
+	"syscall.LsfStmt":                                      "syscall",
+	"syscall.Lstat":                                        "syscall",
+	"syscall.MADV_AUTOSYNC":                                "syscall",
+	"syscall.MADV_CAN_REUSE":                               "syscall",
+	"syscall.MADV_CORE":                                    "syscall",
+	"syscall.MADV_DOFORK":                                  "syscall",
+	"syscall.MADV_DONTFORK":                                "syscall",
+	"syscall.MADV_DONTNEED":                                "syscall",
+	"syscall.MADV_FREE":                                    "syscall",
+	"syscall.MADV_FREE_REUSABLE":                           "syscall",
+	"syscall.MADV_FREE_REUSE":                              "syscall",
+	"syscall.MADV_HUGEPAGE":                                "syscall",
+	"syscall.MADV_HWPOISON":                                "syscall",
+	"syscall.MADV_MERGEABLE":                               "syscall",
+	"syscall.MADV_NOCORE":                                  "syscall",
+	"syscall.MADV_NOHUGEPAGE":                              "syscall",
+	"syscall.MADV_NORMAL":                                  "syscall",
+	"syscall.MADV_NOSYNC":                                  "syscall",
+	"syscall.MADV_PROTECT":                                 "syscall",
+	"syscall.MADV_RANDOM":                                  "syscall",
+	"syscall.MADV_REMOVE":                                  "syscall",
+	"syscall.MADV_SEQUENTIAL":                              "syscall",
+	"syscall.MADV_UNMERGEABLE":                             "syscall",
+	"syscall.MADV_WILLNEED":                                "syscall",
+	"syscall.MADV_ZERO_WIRED_PAGES":                        "syscall",
+	"syscall.MAP_32BIT":                                    "syscall",
+	"syscall.MAP_ANON":                                     "syscall",
+	"syscall.MAP_ANONYMOUS":                                "syscall",
+	"syscall.MAP_COPY":                                     "syscall",
+	"syscall.MAP_DENYWRITE":                                "syscall",
+	"syscall.MAP_EXECUTABLE":                               "syscall",
+	"syscall.MAP_FILE":                                     "syscall",
+	"syscall.MAP_FIXED":                                    "syscall",
+	"syscall.MAP_GROWSDOWN":                                "syscall",
+	"syscall.MAP_HASSEMAPHORE":                             "syscall",
+	"syscall.MAP_HUGETLB":                                  "syscall",
+	"syscall.MAP_JIT":                                      "syscall",
+	"syscall.MAP_LOCKED":                                   "syscall",
+	"syscall.MAP_NOCACHE":                                  "syscall",
+	"syscall.MAP_NOCORE":                                   "syscall",
+	"syscall.MAP_NOEXTEND":                                 "syscall",
+	"syscall.MAP_NONBLOCK":                                 "syscall",
+	"syscall.MAP_NORESERVE":                                "syscall",
+	"syscall.MAP_NOSYNC":                                   "syscall",
+	"syscall.MAP_POPULATE":                                 "syscall",
+	"syscall.MAP_PREFAULT_READ":                            "syscall",
+	"syscall.MAP_PRIVATE":                                  "syscall",
+	"syscall.MAP_RENAME":                                   "syscall",
+	"syscall.MAP_RESERVED0080":                             "syscall",
+	"syscall.MAP_RESERVED0100":                             "syscall",
+	"syscall.MAP_SHARED":                                   "syscall",
+	"syscall.MAP_STACK":                                    "syscall",
+	"syscall.MAP_TYPE":                                     "syscall",
+	"syscall.MAXLEN_IFDESCR":                               "syscall",
+	"syscall.MAXLEN_PHYSADDR":                              "syscall",
+	"syscall.MAX_ADAPTER_ADDRESS_LENGTH":                   "syscall",
+	"syscall.MAX_ADAPTER_DESCRIPTION_LENGTH":               "syscall",
+	"syscall.MAX_ADAPTER_NAME_LENGTH":                      "syscall",
+	"syscall.MAX_COMPUTERNAME_LENGTH":                      "syscall",
+	"syscall.MAX_INTERFACE_NAME_LEN":                       "syscall",
+	"syscall.MAX_LONG_PATH":                                "syscall",
+	"syscall.MAX_PATH":                                     "syscall",
+	"syscall.MAX_PROTOCOL_CHAIN":                           "syscall",
+	"syscall.MCL_CURRENT":                                  "syscall",
+	"syscall.MCL_FUTURE":                                   "syscall",
+	"syscall.MNT_DETACH":                                   "syscall",
+	"syscall.MNT_EXPIRE":                                   "syscall",
+	"syscall.MNT_FORCE":                                    "syscall",
+	"syscall.MSG_BCAST":                                    "syscall",
+	"syscall.MSG_CMSG_CLOEXEC":                             "syscall",
+	"syscall.MSG_COMPAT":                                   "syscall",
+	"syscall.MSG_CONFIRM":                                  "syscall",
+	"syscall.MSG_CONTROLMBUF":                              "syscall",
+	"syscall.MSG_CTRUNC":                                   "syscall",
+	"syscall.MSG_DONTROUTE":                                "syscall",
+	"syscall.MSG_DONTWAIT":                                 "syscall",
+	"syscall.MSG_EOF":                                      "syscall",
+	"syscall.MSG_EOR":                                      "syscall",
+	"syscall.MSG_ERRQUEUE":                                 "syscall",
+	"syscall.MSG_FASTOPEN":                                 "syscall",
+	"syscall.MSG_FIN":                                      "syscall",
+	"syscall.MSG_FLUSH":                                    "syscall",
+	"syscall.MSG_HAVEMORE":                                 "syscall",
+	"syscall.MSG_HOLD":                                     "syscall",
+	"syscall.MSG_IOVUSRSPACE":                              "syscall",
+	"syscall.MSG_LENUSRSPACE":                              "syscall",
+	"syscall.MSG_MCAST":                                    "syscall",
+	"syscall.MSG_MORE":                                     "syscall",
+	"syscall.MSG_NAMEMBUF":                                 "syscall",
+	"syscall.MSG_NBIO":                                     "syscall",
+	"syscall.MSG_NEEDSA":                                   "syscall",
+	"syscall.MSG_NOSIGNAL":                                 "syscall",
+	"syscall.MSG_NOTIFICATION":                             "syscall",
+	"syscall.MSG_OOB":                                      "syscall",
+	"syscall.MSG_PEEK":                                     "syscall",
+	"syscall.MSG_PROXY":                                    "syscall",
+	"syscall.MSG_RCVMORE":                                  "syscall",
+	"syscall.MSG_RST":                                      "syscall",
+	"syscall.MSG_SEND":                                     "syscall",
+	"syscall.MSG_SYN":                                      "syscall",
+	"syscall.MSG_TRUNC":                                    "syscall",
+	"syscall.MSG_TRYHARD":                                  "syscall",
+	"syscall.MSG_USERFLAGS":                                "syscall",
+	"syscall.MSG_WAITALL":                                  "syscall",
+	"syscall.MSG_WAITFORONE":                               "syscall",
+	"syscall.MSG_WAITSTREAM":                               "syscall",
+	"syscall.MS_ACTIVE":                                    "syscall",
+	"syscall.MS_ASYNC":                                     "syscall",
+	"syscall.MS_BIND":                                      "syscall",
+	"syscall.MS_DEACTIVATE":                                "syscall",
+	"syscall.MS_DIRSYNC":                                   "syscall",
+	"syscall.MS_INVALIDATE":                                "syscall",
+	"syscall.MS_I_VERSION":                                 "syscall",
+	"syscall.MS_KERNMOUNT":                                 "syscall",
+	"syscall.MS_KILLPAGES":                                 "syscall",
+	"syscall.MS_MANDLOCK":                                  "syscall",
+	"syscall.MS_MGC_MSK":                                   "syscall",
+	"syscall.MS_MGC_VAL":                                   "syscall",
+	"syscall.MS_MOVE":                                      "syscall",
+	"syscall.MS_NOATIME":                                   "syscall",
+	"syscall.MS_NODEV":                                     "syscall",
+	"syscall.MS_NODIRATIME":                                "syscall",
+	"syscall.MS_NOEXEC":                                    "syscall",
+	"syscall.MS_NOSUID":                                    "syscall",
+	"syscall.MS_NOUSER":                                    "syscall",
+	"syscall.MS_POSIXACL":                                  "syscall",
+	"syscall.MS_PRIVATE":                                   "syscall",
+	"syscall.MS_RDONLY":                                    "syscall",
+	"syscall.MS_REC":                                       "syscall",
+	"syscall.MS_RELATIME":                                  "syscall",
+	"syscall.MS_REMOUNT":                                   "syscall",
+	"syscall.MS_RMT_MASK":                                  "syscall",
+	"syscall.MS_SHARED":                                    "syscall",
+	"syscall.MS_SILENT":                                    "syscall",
+	"syscall.MS_SLAVE":                                     "syscall",
+	"syscall.MS_STRICTATIME":                               "syscall",
+	"syscall.MS_SYNC":                                      "syscall",
+	"syscall.MS_SYNCHRONOUS":                               "syscall",
+	"syscall.MS_UNBINDABLE":                                "syscall",
+	"syscall.Madvise":                                      "syscall",
+	"syscall.MapViewOfFile":                                "syscall",
+	"syscall.MaxTokenInfoClass":                            "syscall",
+	"syscall.Mclpool":                                      "syscall",
+	"syscall.MibIfRow":                                     "syscall",
+	"syscall.Mkdir":                                        "syscall",
+	"syscall.Mkdirat":                                      "syscall",
+	"syscall.Mkfifo":                                       "syscall",
+	"syscall.Mknod":                                        "syscall",
+	"syscall.Mknodat":                                      "syscall",
+	"syscall.Mlock":                                        "syscall",
+	"syscall.Mlockall":                                     "syscall",
+	"syscall.Mmap":                                         "syscall",
+	"syscall.Mount":                                        "syscall",
+	"syscall.MoveFile":                                     "syscall",
+	"syscall.Mprotect":                                     "syscall",
+	"syscall.Msghdr":                                       "syscall",
+	"syscall.Munlock":                                      "syscall",
+	"syscall.Munlockall":                                   "syscall",
+	"syscall.Munmap":                                       "syscall",
+	"syscall.MustLoadDLL":                                  "syscall",
+	"syscall.NAME_MAX":                                     "syscall",
+	"syscall.NETLINK_ADD_MEMBERSHIP":                       "syscall",
+	"syscall.NETLINK_AUDIT":                                "syscall",
+	"syscall.NETLINK_BROADCAST_ERROR":                      "syscall",
+	"syscall.NETLINK_CONNECTOR":                            "syscall",
+	"syscall.NETLINK_DNRTMSG":                              "syscall",
+	"syscall.NETLINK_DROP_MEMBERSHIP":                      "syscall",
+	"syscall.NETLINK_ECRYPTFS":                             "syscall",
+	"syscall.NETLINK_FIB_LOOKUP":                           "syscall",
+	"syscall.NETLINK_FIREWALL":                             "syscall",
+	"syscall.NETLINK_GENERIC":                              "syscall",
+	"syscall.NETLINK_INET_DIAG":                            "syscall",
+	"syscall.NETLINK_IP6_FW":                               "syscall",
+	"syscall.NETLINK_ISCSI":                                "syscall",
+	"syscall.NETLINK_KOBJECT_UEVENT":                       "syscall",
+	"syscall.NETLINK_NETFILTER":                            "syscall",
+	"syscall.NETLINK_NFLOG":                                "syscall",
+	"syscall.NETLINK_NO_ENOBUFS":                           "syscall",
+	"syscall.NETLINK_PKTINFO":                              "syscall",
+	"syscall.NETLINK_RDMA":                                 "syscall",
+	"syscall.NETLINK_ROUTE":                                "syscall",
+	"syscall.NETLINK_SCSITRANSPORT":                        "syscall",
+	"syscall.NETLINK_SELINUX":                              "syscall",
+	"syscall.NETLINK_UNUSED":                               "syscall",
+	"syscall.NETLINK_USERSOCK":                             "syscall",
+	"syscall.NETLINK_XFRM":                                 "syscall",
+	"syscall.NET_RT_DUMP":                                  "syscall",
+	"syscall.NET_RT_DUMP2":                                 "syscall",
+	"syscall.NET_RT_FLAGS":                                 "syscall",
+	"syscall.NET_RT_IFLIST":                                "syscall",
+	"syscall.NET_RT_IFLIST2":                               "syscall",
+	"syscall.NET_RT_IFLISTL":                               "syscall",
+	"syscall.NET_RT_IFMALIST":                              "syscall",
+	"syscall.NET_RT_MAXID":                                 "syscall",
+	"syscall.NET_RT_OIFLIST":                               "syscall",
+	"syscall.NET_RT_OOIFLIST":                              "syscall",
+	"syscall.NET_RT_STAT":                                  "syscall",
+	"syscall.NET_RT_STATS":                                 "syscall",
+	"syscall.NET_RT_TABLE":                                 "syscall",
+	"syscall.NET_RT_TRASH":                                 "syscall",
+	"syscall.NLA_ALIGNTO":                                  "syscall",
+	"syscall.NLA_F_NESTED":                                 "syscall",
+	"syscall.NLA_F_NET_BYTEORDER":                          "syscall",
+	"syscall.NLA_HDRLEN":                                   "syscall",
+	"syscall.NLMSG_ALIGNTO":                                "syscall",
+	"syscall.NLMSG_DONE":                                   "syscall",
+	"syscall.NLMSG_ERROR":                                  "syscall",
+	"syscall.NLMSG_HDRLEN":                                 "syscall",
+	"syscall.NLMSG_MIN_TYPE":                               "syscall",
+	"syscall.NLMSG_NOOP":                                   "syscall",
+	"syscall.NLMSG_OVERRUN":                                "syscall",
+	"syscall.NLM_F_ACK":                                    "syscall",
+	"syscall.NLM_F_APPEND":                                 "syscall",
+	"syscall.NLM_F_ATOMIC":                                 "syscall",
+	"syscall.NLM_F_CREATE":                                 "syscall",
+	"syscall.NLM_F_DUMP":                                   "syscall",
+	"syscall.NLM_F_ECHO":                                   "syscall",
+	"syscall.NLM_F_EXCL":                                   "syscall",
+	"syscall.NLM_F_MATCH":                                  "syscall",
+	"syscall.NLM_F_MULTI":                                  "syscall",
+	"syscall.NLM_F_REPLACE":                                "syscall",
+	"syscall.NLM_F_REQUEST":                                "syscall",
+	"syscall.NLM_F_ROOT":                                   "syscall",
+	"syscall.NOFLSH":                                       "syscall",
+	"syscall.NOTE_ABSOLUTE":                                "syscall",
+	"syscall.NOTE_ATTRIB":                                  "syscall",
+	"syscall.NOTE_CHILD":                                   "syscall",
+	"syscall.NOTE_DELETE":                                  "syscall",
+	"syscall.NOTE_EOF":                                     "syscall",
+	"syscall.NOTE_EXEC":                                    "syscall",
+	"syscall.NOTE_EXIT":                                    "syscall",
+	"syscall.NOTE_EXITSTATUS":                              "syscall",
+	"syscall.NOTE_EXTEND":                                  "syscall",
+	"syscall.NOTE_FFAND":                                   "syscall",
+	"syscall.NOTE_FFCOPY":                                  "syscall",
+	"syscall.NOTE_FFCTRLMASK":                              "syscall",
+	"syscall.NOTE_FFLAGSMASK":                              "syscall",
+	"syscall.NOTE_FFNOP":                                   "syscall",
+	"syscall.NOTE_FFOR":                                    "syscall",
+	"syscall.NOTE_FORK":                                    "syscall",
+	"syscall.NOTE_LINK":                                    "syscall",
+	"syscall.NOTE_LOWAT":                                   "syscall",
+	"syscall.NOTE_NONE":                                    "syscall",
+	"syscall.NOTE_NSECONDS":                                "syscall",
+	"syscall.NOTE_PCTRLMASK":                               "syscall",
+	"syscall.NOTE_PDATAMASK":                               "syscall",
+	"syscall.NOTE_REAP":                                    "syscall",
+	"syscall.NOTE_RENAME":                                  "syscall",
+	"syscall.NOTE_RESOURCEEND":                             "syscall",
+	"syscall.NOTE_REVOKE":                                  "syscall",
+	"syscall.NOTE_SECONDS":                                 "syscall",
+	"syscall.NOTE_SIGNAL":                                  "syscall",
+	"syscall.NOTE_TRACK":                                   "syscall",
+	"syscall.NOTE_TRACKERR":                                "syscall",
+	"syscall.NOTE_TRIGGER":                                 "syscall",
+	"syscall.NOTE_TRUNCATE":                                "syscall",
+	"syscall.NOTE_USECONDS":                                "syscall",
+	"syscall.NOTE_VM_ERROR":                                "syscall",
+	"syscall.NOTE_VM_PRESSURE":                             "syscall",
+	"syscall.NOTE_VM_PRESSURE_SUDDEN_TERMINATE":            "syscall",
+	"syscall.NOTE_VM_PRESSURE_TERMINATE":                   "syscall",
+	"syscall.NOTE_WRITE":                                   "syscall",
+	"syscall.NameCanonical":                                "syscall",
+	"syscall.NameCanonicalEx":                              "syscall",
+	"syscall.NameDisplay":                                  "syscall",
+	"syscall.NameDnsDomain":                                "syscall",
+	"syscall.NameFullyQualifiedDN":                         "syscall",
+	"syscall.NameSamCompatible":                            "syscall",
+	"syscall.NameServicePrincipal":                         "syscall",
+	"syscall.NameUniqueId":                                 "syscall",
+	"syscall.NameUnknown":                                  "syscall",
+	"syscall.NameUserPrincipal":                            "syscall",
+	"syscall.Nanosleep":                                    "syscall",
+	"syscall.NetApiBufferFree":                             "syscall",
+	"syscall.NetGetJoinInformation":                        "syscall",
+	"syscall.NetSetupDomainName":                           "syscall",
+	"syscall.NetSetupUnjoined":                             "syscall",
+	"syscall.NetSetupUnknownStatus":                        "syscall",
+	"syscall.NetSetupWorkgroupName":                        "syscall",
+	"syscall.NetUserGetInfo":                               "syscall",
+	"syscall.NetlinkMessage":                               "syscall",
+	"syscall.NetlinkRIB":                                   "syscall",
+	"syscall.NetlinkRouteAttr":                             "syscall",
+	"syscall.NetlinkRouteRequest":                          "syscall",
+	"syscall.NewCallback":                                  "syscall",
+	"syscall.NewLazyDLL":                                   "syscall",
+	"syscall.NlAttr":                                       "syscall",
+	"syscall.NlMsgerr":                                     "syscall",
+	"syscall.NlMsghdr":                                     "syscall",
+	"syscall.NsecToFiletime":                               "syscall",
+	"syscall.NsecToTimespec":                               "syscall",
+	"syscall.NsecToTimeval":                                "syscall",
+	"syscall.Ntohs":                                        "syscall",
+	"syscall.OCRNL":                                        "syscall",
+	"syscall.OFDEL":                                        "syscall",
+	"syscall.OFILL":                                        "syscall",
+	"syscall.OFIOGETBMAP":                                  "syscall",
+	"syscall.OID_PKIX_KP_SERVER_AUTH":                      "syscall",
+	"syscall.OID_SERVER_GATED_CRYPTO":                      "syscall",
+	"syscall.OID_SGC_NETSCAPE":                             "syscall",
+	"syscall.OLCUC":                                        "syscall",
+	"syscall.ONLCR":                                        "syscall",
+	"syscall.ONLRET":                                       "syscall",
+	"syscall.ONOCR":                                        "syscall",
+	"syscall.ONOEOT":                                       "syscall",
+	"syscall.OPEN_ALWAYS":                                  "syscall",
+	"syscall.OPEN_EXISTING":                                "syscall",
+	"syscall.OPOST":                                        "syscall",
+	"syscall.O_ACCMODE":                                    "syscall",
+	"syscall.O_ALERT":                                      "syscall",
+	"syscall.O_ALT_IO":                                     "syscall",
+	"syscall.O_APPEND":                                     "syscall",
+	"syscall.O_ASYNC":                                      "syscall",
+	"syscall.O_CLOEXEC":                                    "syscall",
+	"syscall.O_CREAT":                                      "syscall",
+	"syscall.O_DIRECT":                                     "syscall",
+	"syscall.O_DIRECTORY":                                  "syscall",
+	"syscall.O_DSYNC":                                      "syscall",
+	"syscall.O_EVTONLY":                                    "syscall",
+	"syscall.O_EXCL":                                       "syscall",
+	"syscall.O_EXEC":                                       "syscall",
+	"syscall.O_EXLOCK":                                     "syscall",
+	"syscall.O_FSYNC":                                      "syscall",
+	"syscall.O_LARGEFILE":                                  "syscall",
+	"syscall.O_NDELAY":                                     "syscall",
+	"syscall.O_NOATIME":                                    "syscall",
+	"syscall.O_NOCTTY":                                     "syscall",
+	"syscall.O_NOFOLLOW":                                   "syscall",
+	"syscall.O_NONBLOCK":                                   "syscall",
+	"syscall.O_NOSIGPIPE":                                  "syscall",
+	"syscall.O_POPUP":                                      "syscall",
+	"syscall.O_RDONLY":                                     "syscall",
+	"syscall.O_RDWR":                                       "syscall",
+	"syscall.O_RSYNC":                                      "syscall",
+	"syscall.O_SHLOCK":                                     "syscall",
+	"syscall.O_SYMLINK":                                    "syscall",
+	"syscall.O_SYNC":                                       "syscall",
+	"syscall.O_TRUNC":                                      "syscall",
+	"syscall.O_TTY_INIT":                                   "syscall",
+	"syscall.O_WRONLY":                                     "syscall",
+	"syscall.Open":                                         "syscall",
+	"syscall.OpenCurrentProcessToken":                      "syscall",
+	"syscall.OpenProcess":                                  "syscall",
+	"syscall.OpenProcessToken":                             "syscall",
+	"syscall.Openat":                                       "syscall",
+	"syscall.Overlapped":                                   "syscall",
+	"syscall.PACKET_ADD_MEMBERSHIP":                        "syscall",
+	"syscall.PACKET_BROADCAST":                             "syscall",
+	"syscall.PACKET_DROP_MEMBERSHIP":                       "syscall",
+	"syscall.PACKET_FASTROUTE":                             "syscall",
+	"syscall.PACKET_HOST":                                  "syscall",
+	"syscall.PACKET_LOOPBACK":                              "syscall",
+	"syscall.PACKET_MR_ALLMULTI":                           "syscall",
+	"syscall.PACKET_MR_MULTICAST":                          "syscall",
+	"syscall.PACKET_MR_PROMISC":                            "syscall",
+	"syscall.PACKET_MULTICAST":                             "syscall",
+	"syscall.PACKET_OTHERHOST":                             "syscall",
+	"syscall.PACKET_OUTGOING":                              "syscall",
+	"syscall.PACKET_RECV_OUTPUT":                           "syscall",
+	"syscall.PACKET_RX_RING":                               "syscall",
+	"syscall.PACKET_STATISTICS":                            "syscall",
+	"syscall.PAGE_EXECUTE_READ":                            "syscall",
+	"syscall.PAGE_EXECUTE_READWRITE":                       "syscall",
+	"syscall.PAGE_EXECUTE_WRITECOPY":                       "syscall",
+	"syscall.PAGE_READONLY":                                "syscall",
+	"syscall.PAGE_READWRITE":                               "syscall",
+	"syscall.PAGE_WRITECOPY":                               "syscall",
+	"syscall.PARENB":                                       "syscall",
+	"syscall.PARMRK":                                       "syscall",
+	"syscall.PARODD":                                       "syscall",
+	"syscall.PENDIN":                                       "syscall",
+	"syscall.PFL_HIDDEN":                                   "syscall",
+	"syscall.PFL_MATCHES_PROTOCOL_ZERO":                    "syscall",
+	"syscall.PFL_MULTIPLE_PROTO_ENTRIES":                   "syscall",
+	"syscall.PFL_NETWORKDIRECT_PROVIDER":                   "syscall",
+	"syscall.PFL_RECOMMENDED_PROTO_ENTRY":                  "syscall",
+	"syscall.PF_FLUSH":                                     "syscall",
+	"syscall.PKCS_7_ASN_ENCODING":                          "syscall",
+	"syscall.PMC5_PIPELINE_FLUSH":                          "syscall",
+	"syscall.PRIO_PGRP":                                    "syscall",
+	"syscall.PRIO_PROCESS":                                 "syscall",
+	"syscall.PRIO_USER":                                    "syscall",
+	"syscall.PRI_IOFLUSH":                                  "syscall",
+	"syscall.PROCESS_QUERY_INFORMATION":                    "syscall",
+	"syscall.PROCESS_TERMINATE":                            "syscall",
+	"syscall.PROT_EXEC":                                    "syscall",
+	"syscall.PROT_GROWSDOWN":                               "syscall",
+	"syscall.PROT_GROWSUP":                                 "syscall",
+	"syscall.PROT_NONE":                                    "syscall",
+	"syscall.PROT_READ":                                    "syscall",
+	"syscall.PROT_WRITE":                                   "syscall",
+	"syscall.PROV_DH_SCHANNEL":                             "syscall",
+	"syscall.PROV_DSS":                                     "syscall",
+	"syscall.PROV_DSS_DH":                                  "syscall",
+	"syscall.PROV_EC_ECDSA_FULL":                           "syscall",
+	"syscall.PROV_EC_ECDSA_SIG":                            "syscall",
+	"syscall.PROV_EC_ECNRA_FULL":                           "syscall",
+	"syscall.PROV_EC_ECNRA_SIG":                            "syscall",
+	"syscall.PROV_FORTEZZA":                                "syscall",
+	"syscall.PROV_INTEL_SEC":                               "syscall",
+	"syscall.PROV_MS_EXCHANGE":                             "syscall",
+	"syscall.PROV_REPLACE_OWF":                             "syscall",
+	"syscall.PROV_RNG":                                     "syscall",
+	"syscall.PROV_RSA_AES":                                 "syscall",
+	"syscall.PROV_RSA_FULL":                                "syscall",
+	"syscall.PROV_RSA_SCHANNEL":                            "syscall",
+	"syscall.PROV_RSA_SIG":                                 "syscall",
+	"syscall.PROV_SPYRUS_LYNKS":                            "syscall",
+	"syscall.PROV_SSL":                                     "syscall",
+	"syscall.PR_CAPBSET_DROP":                              "syscall",
+	"syscall.PR_CAPBSET_READ":                              "syscall",
+	"syscall.PR_CLEAR_SECCOMP_FILTER":                      "syscall",
+	"syscall.PR_ENDIAN_BIG":                                "syscall",
+	"syscall.PR_ENDIAN_LITTLE":                             "syscall",
+	"syscall.PR_ENDIAN_PPC_LITTLE":                         "syscall",
+	"syscall.PR_FPEMU_NOPRINT":                             "syscall",
+	"syscall.PR_FPEMU_SIGFPE":                              "syscall",
+	"syscall.PR_FP_EXC_ASYNC":                              "syscall",
+	"syscall.PR_FP_EXC_DISABLED":                           "syscall",
+	"syscall.PR_FP_EXC_DIV":                                "syscall",
+	"syscall.PR_FP_EXC_INV":                                "syscall",
+	"syscall.PR_FP_EXC_NONRECOV":                           "syscall",
+	"syscall.PR_FP_EXC_OVF":                                "syscall",
+	"syscall.PR_FP_EXC_PRECISE":                            "syscall",
+	"syscall.PR_FP_EXC_RES":                                "syscall",
+	"syscall.PR_FP_EXC_SW_ENABLE":                          "syscall",
+	"syscall.PR_FP_EXC_UND":                                "syscall",
+	"syscall.PR_GET_DUMPABLE":                              "syscall",
+	"syscall.PR_GET_ENDIAN":                                "syscall",
+	"syscall.PR_GET_FPEMU":                                 "syscall",
+	"syscall.PR_GET_FPEXC":                                 "syscall",
+	"syscall.PR_GET_KEEPCAPS":                              "syscall",
+	"syscall.PR_GET_NAME":                                  "syscall",
+	"syscall.PR_GET_PDEATHSIG":                             "syscall",
+	"syscall.PR_GET_SECCOMP":                               "syscall",
+	"syscall.PR_GET_SECCOMP_FILTER":                        "syscall",
+	"syscall.PR_GET_SECUREBITS":                            "syscall",
+	"syscall.PR_GET_TIMERSLACK":                            "syscall",
+	"syscall.PR_GET_TIMING":                                "syscall",
+	"syscall.PR_GET_TSC":                                   "syscall",
+	"syscall.PR_GET_UNALIGN":                               "syscall",
+	"syscall.PR_MCE_KILL":                                  "syscall",
+	"syscall.PR_MCE_KILL_CLEAR":                            "syscall",
+	"syscall.PR_MCE_KILL_DEFAULT":                          "syscall",
+	"syscall.PR_MCE_KILL_EARLY":                            "syscall",
+	"syscall.PR_MCE_KILL_GET":                              "syscall",
+	"syscall.PR_MCE_KILL_LATE":                             "syscall",
+	"syscall.PR_MCE_KILL_SET":                              "syscall",
+	"syscall.PR_SECCOMP_FILTER_EVENT":                      "syscall",
+	"syscall.PR_SECCOMP_FILTER_SYSCALL":                    "syscall",
+	"syscall.PR_SET_DUMPABLE":                              "syscall",
+	"syscall.PR_SET_ENDIAN":                                "syscall",
+	"syscall.PR_SET_FPEMU":                                 "syscall",
+	"syscall.PR_SET_FPEXC":                                 "syscall",
+	"syscall.PR_SET_KEEPCAPS":                              "syscall",
+	"syscall.PR_SET_NAME":                                  "syscall",
+	"syscall.PR_SET_PDEATHSIG":                             "syscall",
+	"syscall.PR_SET_PTRACER":                               "syscall",
+	"syscall.PR_SET_SECCOMP":                               "syscall",
+	"syscall.PR_SET_SECCOMP_FILTER":                        "syscall",
+	"syscall.PR_SET_SECUREBITS":                            "syscall",
+	"syscall.PR_SET_TIMERSLACK":                            "syscall",
+	"syscall.PR_SET_TIMING":                                "syscall",
+	"syscall.PR_SET_TSC":                                   "syscall",
+	"syscall.PR_SET_UNALIGN":                               "syscall",
+	"syscall.PR_TASK_PERF_EVENTS_DISABLE":                  "syscall",
+	"syscall.PR_TASK_PERF_EVENTS_ENABLE":                   "syscall",
+	"syscall.PR_TIMING_STATISTICAL":                        "syscall",
+	"syscall.PR_TIMING_TIMESTAMP":                          "syscall",
+	"syscall.PR_TSC_ENABLE":                                "syscall",
+	"syscall.PR_TSC_SIGSEGV":                               "syscall",
+	"syscall.PR_UNALIGN_NOPRINT":                           "syscall",
+	"syscall.PR_UNALIGN_SIGBUS":                            "syscall",
+	"syscall.PTRACE_ARCH_PRCTL":                            "syscall",
+	"syscall.PTRACE_ATTACH":                                "syscall",
+	"syscall.PTRACE_CONT":                                  "syscall",
+	"syscall.PTRACE_DETACH":                                "syscall",
+	"syscall.PTRACE_EVENT_CLONE":                           "syscall",
+	"syscall.PTRACE_EVENT_EXEC":                            "syscall",
+	"syscall.PTRACE_EVENT_EXIT":                            "syscall",
+	"syscall.PTRACE_EVENT_FORK":                            "syscall",
+	"syscall.PTRACE_EVENT_VFORK":                           "syscall",
+	"syscall.PTRACE_EVENT_VFORK_DONE":                      "syscall",
+	"syscall.PTRACE_GETCRUNCHREGS":                         "syscall",
+	"syscall.PTRACE_GETEVENTMSG":                           "syscall",
+	"syscall.PTRACE_GETFPREGS":                             "syscall",
+	"syscall.PTRACE_GETFPXREGS":                            "syscall",
+	"syscall.PTRACE_GETHBPREGS":                            "syscall",
+	"syscall.PTRACE_GETREGS":                               "syscall",
+	"syscall.PTRACE_GETREGSET":                             "syscall",
+	"syscall.PTRACE_GETSIGINFO":                            "syscall",
+	"syscall.PTRACE_GETVFPREGS":                            "syscall",
+	"syscall.PTRACE_GETWMMXREGS":                           "syscall",
+	"syscall.PTRACE_GET_THREAD_AREA":                       "syscall",
+	"syscall.PTRACE_KILL":                                  "syscall",
+	"syscall.PTRACE_OLDSETOPTIONS":                         "syscall",
+	"syscall.PTRACE_O_MASK":                                "syscall",
+	"syscall.PTRACE_O_TRACECLONE":                          "syscall",
+	"syscall.PTRACE_O_TRACEEXEC":                           "syscall",
+	"syscall.PTRACE_O_TRACEEXIT":                           "syscall",
+	"syscall.PTRACE_O_TRACEFORK":                           "syscall",
+	"syscall.PTRACE_O_TRACESYSGOOD":                        "syscall",
+	"syscall.PTRACE_O_TRACEVFORK":                          "syscall",
+	"syscall.PTRACE_O_TRACEVFORKDONE":                      "syscall",
+	"syscall.PTRACE_PEEKDATA":                              "syscall",
+	"syscall.PTRACE_PEEKTEXT":                              "syscall",
+	"syscall.PTRACE_PEEKUSR":                               "syscall",
+	"syscall.PTRACE_POKEDATA":                              "syscall",
+	"syscall.PTRACE_POKETEXT":                              "syscall",
+	"syscall.PTRACE_POKEUSR":                               "syscall",
+	"syscall.PTRACE_SETCRUNCHREGS":                         "syscall",
+	"syscall.PTRACE_SETFPREGS":                             "syscall",
+	"syscall.PTRACE_SETFPXREGS":                            "syscall",
+	"syscall.PTRACE_SETHBPREGS":                            "syscall",
+	"syscall.PTRACE_SETOPTIONS":                            "syscall",
+	"syscall.PTRACE_SETREGS":                               "syscall",
+	"syscall.PTRACE_SETREGSET":                             "syscall",
+	"syscall.PTRACE_SETSIGINFO":                            "syscall",
+	"syscall.PTRACE_SETVFPREGS":                            "syscall",
+	"syscall.PTRACE_SETWMMXREGS":                           "syscall",
+	"syscall.PTRACE_SET_SYSCALL":                           "syscall",
+	"syscall.PTRACE_SET_THREAD_AREA":                       "syscall",
+	"syscall.PTRACE_SINGLEBLOCK":                           "syscall",
+	"syscall.PTRACE_SINGLESTEP":                            "syscall",
+	"syscall.PTRACE_SYSCALL":                               "syscall",
+	"syscall.PTRACE_SYSEMU":                                "syscall",
+	"syscall.PTRACE_SYSEMU_SINGLESTEP":                     "syscall",
+	"syscall.PTRACE_TRACEME":                               "syscall",
+	"syscall.PT_ATTACH":                                    "syscall",
+	"syscall.PT_ATTACHEXC":                                 "syscall",
+	"syscall.PT_CONTINUE":                                  "syscall",
+	"syscall.PT_DATA_ADDR":                                 "syscall",
+	"syscall.PT_DENY_ATTACH":                               "syscall",
+	"syscall.PT_DETACH":                                    "syscall",
+	"syscall.PT_FIRSTMACH":                                 "syscall",
+	"syscall.PT_FORCEQUOTA":                                "syscall",
+	"syscall.PT_KILL":                                      "syscall",
+	"syscall.PT_MASK":                                      "syscall",
+	"syscall.PT_READ_D":                                    "syscall",
+	"syscall.PT_READ_I":                                    "syscall",
+	"syscall.PT_READ_U":                                    "syscall",
+	"syscall.PT_SIGEXC":                                    "syscall",
+	"syscall.PT_STEP":                                      "syscall",
+	"syscall.PT_TEXT_ADDR":                                 "syscall",
+	"syscall.PT_TEXT_END_ADDR":                             "syscall",
+	"syscall.PT_THUPDATE":                                  "syscall",
+	"syscall.PT_TRACE_ME":                                  "syscall",
+	"syscall.PT_WRITE_D":                                   "syscall",
+	"syscall.PT_WRITE_I":                                   "syscall",
+	"syscall.PT_WRITE_U":                                   "syscall",
+	"syscall.ParseDirent":                                  "syscall",
+	"syscall.ParseNetlinkMessage":                          "syscall",
+	"syscall.ParseNetlinkRouteAttr":                        "syscall",
+	"syscall.ParseRoutingMessage":                          "syscall",
+	"syscall.ParseRoutingSockaddr":                         "syscall",
+	"syscall.ParseSocketControlMessage":                    "syscall",
+	"syscall.ParseUnixCredentials":                         "syscall",
+	"syscall.ParseUnixRights":                              "syscall",
+	"syscall.PathMax":                                      "syscall",
+	"syscall.Pathconf":                                     "syscall",
+	"syscall.Pause":                                        "syscall",
+	"syscall.Pipe":                                         "syscall",
+	"syscall.Pipe2":                                        "syscall",
+	"syscall.PivotRoot":                                    "syscall",
+	"syscall.PostQueuedCompletionStatus":                   "syscall",
+	"syscall.Pread":                                        "syscall",
+	"syscall.Proc":                                         "syscall",
+	"syscall.ProcAttr":                                     "syscall",
+	"syscall.ProcessInformation":                           "syscall",
+	"syscall.Protoent":                                     "syscall",
+	"syscall.PtraceAttach":                                 "syscall",
+	"syscall.PtraceCont":                                   "syscall",
+	"syscall.PtraceDetach":                                 "syscall",
+	"syscall.PtraceGetEventMsg":                            "syscall",
+	"syscall.PtraceGetRegs":                                "syscall",
+	"syscall.PtracePeekData":                               "syscall",
+	"syscall.PtracePeekText":                               "syscall",
+	"syscall.PtracePokeData":                               "syscall",
+	"syscall.PtracePokeText":                               "syscall",
+	"syscall.PtraceRegs":                                   "syscall",
+	"syscall.PtraceSetOptions":                             "syscall",
+	"syscall.PtraceSetRegs":                                "syscall",
+	"syscall.PtraceSingleStep":                             "syscall",
+	"syscall.PtraceSyscall":                                "syscall",
+	"syscall.Pwrite":                                       "syscall",
+	"syscall.REG_BINARY":                                   "syscall",
+	"syscall.REG_DWORD":                                    "syscall",
+	"syscall.REG_DWORD_BIG_ENDIAN":                         "syscall",
+	"syscall.REG_DWORD_LITTLE_ENDIAN":                      "syscall",
+	"syscall.REG_EXPAND_SZ":                                "syscall",
+	"syscall.REG_FULL_RESOURCE_DESCRIPTOR":                 "syscall",
+	"syscall.REG_LINK":                                     "syscall",
+	"syscall.REG_MULTI_SZ":                                 "syscall",
+	"syscall.REG_NONE":                                     "syscall",
+	"syscall.REG_QWORD":                                    "syscall",
+	"syscall.REG_QWORD_LITTLE_ENDIAN":                      "syscall",
+	"syscall.REG_RESOURCE_LIST":                            "syscall",
+	"syscall.REG_RESOURCE_REQUIREMENTS_LIST":               "syscall",
+	"syscall.REG_SZ":                                       "syscall",
+	"syscall.RLIMIT_AS":                                    "syscall",
+	"syscall.RLIMIT_CORE":                                  "syscall",
+	"syscall.RLIMIT_CPU":                                   "syscall",
+	"syscall.RLIMIT_DATA":                                  "syscall",
+	"syscall.RLIMIT_FSIZE":                                 "syscall",
+	"syscall.RLIMIT_NOFILE":                                "syscall",
+	"syscall.RLIMIT_STACK":                                 "syscall",
+	"syscall.RLIM_INFINITY":                                "syscall",
+	"syscall.RTAX_ADVMSS":                                  "syscall",
+	"syscall.RTAX_AUTHOR":                                  "syscall",
+	"syscall.RTAX_BRD":                                     "syscall",
+	"syscall.RTAX_CWND":                                    "syscall",
+	"syscall.RTAX_DST":                                     "syscall",
+	"syscall.RTAX_FEATURES":                                "syscall",
+	"syscall.RTAX_FEATURE_ALLFRAG":                         "syscall",
+	"syscall.RTAX_FEATURE_ECN":                             "syscall",
+	"syscall.RTAX_FEATURE_SACK":                            "syscall",
+	"syscall.RTAX_FEATURE_TIMESTAMP":                       "syscall",
+	"syscall.RTAX_GATEWAY":                                 "syscall",
+	"syscall.RTAX_GENMASK":                                 "syscall",
+	"syscall.RTAX_HOPLIMIT":                                "syscall",
+	"syscall.RTAX_IFA":                                     "syscall",
+	"syscall.RTAX_IFP":                                     "syscall",
+	"syscall.RTAX_INITCWND":                                "syscall",
+	"syscall.RTAX_INITRWND":                                "syscall",
+	"syscall.RTAX_LABEL":                                   "syscall",
+	"syscall.RTAX_LOCK":                                    "syscall",
+	"syscall.RTAX_MAX":                                     "syscall",
+	"syscall.RTAX_MTU":                                     "syscall",
+	"syscall.RTAX_NETMASK":                                 "syscall",
+	"syscall.RTAX_REORDERING":                              "syscall",
+	"syscall.RTAX_RTO_MIN":                                 "syscall",
+	"syscall.RTAX_RTT":                                     "syscall",
+	"syscall.RTAX_RTTVAR":                                  "syscall",
+	"syscall.RTAX_SRC":                                     "syscall",
+	"syscall.RTAX_SRCMASK":                                 "syscall",
+	"syscall.RTAX_SSTHRESH":                                "syscall",
+	"syscall.RTAX_TAG":                                     "syscall",
+	"syscall.RTAX_UNSPEC":                                  "syscall",
+	"syscall.RTAX_WINDOW":                                  "syscall",
+	"syscall.RTA_ALIGNTO":                                  "syscall",
+	"syscall.RTA_AUTHOR":                                   "syscall",
+	"syscall.RTA_BRD":                                      "syscall",
+	"syscall.RTA_CACHEINFO":                                "syscall",
+	"syscall.RTA_DST":                                      "syscall",
+	"syscall.RTA_FLOW":                                     "syscall",
+	"syscall.RTA_GATEWAY":                                  "syscall",
+	"syscall.RTA_GENMASK":                                  "syscall",
+	"syscall.RTA_IFA":                                      "syscall",
+	"syscall.RTA_IFP":                                      "syscall",
+	"syscall.RTA_IIF":                                      "syscall",
+	"syscall.RTA_LABEL":                                    "syscall",
+	"syscall.RTA_MAX":                                      "syscall",
+	"syscall.RTA_METRICS":                                  "syscall",
+	"syscall.RTA_MULTIPATH":                                "syscall",
+	"syscall.RTA_NETMASK":                                  "syscall",
+	"syscall.RTA_OIF":                                      "syscall",
+	"syscall.RTA_PREFSRC":                                  "syscall",
+	"syscall.RTA_PRIORITY":                                 "syscall",
+	"syscall.RTA_SRC":                                      "syscall",
+	"syscall.RTA_SRCMASK":                                  "syscall",
+	"syscall.RTA_TABLE":                                    "syscall",
+	"syscall.RTA_TAG":                                      "syscall",
+	"syscall.RTA_UNSPEC":                                   "syscall",
+	"syscall.RTCF_DIRECTSRC":                               "syscall",
+	"syscall.RTCF_DOREDIRECT":                              "syscall",
+	"syscall.RTCF_LOG":                                     "syscall",
+	"syscall.RTCF_MASQ":                                    "syscall",
+	"syscall.RTCF_NAT":                                     "syscall",
+	"syscall.RTCF_VALVE":                                   "syscall",
+	"syscall.RTF_ADDRCLASSMASK":                            "syscall",
+	"syscall.RTF_ADDRCONF":                                 "syscall",
+	"syscall.RTF_ALLONLINK":                                "syscall",
+	"syscall.RTF_ANNOUNCE":                                 "syscall",
+	"syscall.RTF_BLACKHOLE":                                "syscall",
+	"syscall.RTF_BROADCAST":                                "syscall",
+	"syscall.RTF_CACHE":                                    "syscall",
+	"syscall.RTF_CLONED":                                   "syscall",
+	"syscall.RTF_CLONING":                                  "syscall",
+	"syscall.RTF_CONDEMNED":                                "syscall",
+	"syscall.RTF_DEFAULT":                                  "syscall",
+	"syscall.RTF_DELCLONE":                                 "syscall",
+	"syscall.RTF_DONE":                                     "syscall",
+	"syscall.RTF_DYNAMIC":                                  "syscall",
+	"syscall.RTF_FLOW":                                     "syscall",
+	"syscall.RTF_FMASK":                                    "syscall",
+	"syscall.RTF_GATEWAY":                                  "syscall",
+	"syscall.RTF_HOST":                                     "syscall",
+	"syscall.RTF_IFREF":                                    "syscall",
+	"syscall.RTF_IFSCOPE":                                  "syscall",
+	"syscall.RTF_INTERFACE":                                "syscall",
+	"syscall.RTF_IRTT":                                     "syscall",
+	"syscall.RTF_LINKRT":                                   "syscall",
+	"syscall.RTF_LLDATA":                                   "syscall",
+	"syscall.RTF_LLINFO":                                   "syscall",
+	"syscall.RTF_LOCAL":                                    "syscall",
+	"syscall.RTF_MASK":                                     "syscall",
+	"syscall.RTF_MODIFIED":                                 "syscall",
+	"syscall.RTF_MPATH":                                    "syscall",
+	"syscall.RTF_MPLS":                                     "syscall",
+	"syscall.RTF_MSS":                                      "syscall",
+	"syscall.RTF_MTU":                                      "syscall",
+	"syscall.RTF_MULTICAST":                                "syscall",
+	"syscall.RTF_NAT":                                      "syscall",
+	"syscall.RTF_NOFORWARD":                                "syscall",
+	"syscall.RTF_NONEXTHOP":                                "syscall",
+	"syscall.RTF_NOPMTUDISC":                               "syscall",
+	"syscall.RTF_PERMANENT_ARP":                            "syscall",
+	"syscall.RTF_PINNED":                                   "syscall",
+	"syscall.RTF_POLICY":                                   "syscall",
+	"syscall.RTF_PRCLONING":                                "syscall",
+	"syscall.RTF_PROTO1":                                   "syscall",
+	"syscall.RTF_PROTO2":                                   "syscall",
+	"syscall.RTF_PROTO3":                                   "syscall",
+	"syscall.RTF_REINSTATE":                                "syscall",
+	"syscall.RTF_REJECT":                                   "syscall",
+	"syscall.RTF_RNH_LOCKED":                               "syscall",
+	"syscall.RTF_SOURCE":                                   "syscall",
+	"syscall.RTF_SRC":                                      "syscall",
+	"syscall.RTF_STATIC":                                   "syscall",
+	"syscall.RTF_STICKY":                                   "syscall",
+	"syscall.RTF_THROW":                                    "syscall",
+	"syscall.RTF_TUNNEL":                                   "syscall",
+	"syscall.RTF_UP":                                       "syscall",
+	"syscall.RTF_USETRAILERS":                              "syscall",
+	"syscall.RTF_WASCLONED":                                "syscall",
+	"syscall.RTF_WINDOW":                                   "syscall",
+	"syscall.RTF_XRESOLVE":                                 "syscall",
+	"syscall.RTM_ADD":                                      "syscall",
+	"syscall.RTM_BASE":                                     "syscall",
+	"syscall.RTM_CHANGE":                                   "syscall",
+	"syscall.RTM_CHGADDR":                                  "syscall",
+	"syscall.RTM_DELACTION":                                "syscall",
+	"syscall.RTM_DELADDR":                                  "syscall",
+	"syscall.RTM_DELADDRLABEL":                             "syscall",
+	"syscall.RTM_DELETE":                                   "syscall",
+	"syscall.RTM_DELLINK":                                  "syscall",
+	"syscall.RTM_DELMADDR":                                 "syscall",
+	"syscall.RTM_DELNEIGH":                                 "syscall",
+	"syscall.RTM_DELQDISC":                                 "syscall",
+	"syscall.RTM_DELROUTE":                                 "syscall",
+	"syscall.RTM_DELRULE":                                  "syscall",
+	"syscall.RTM_DELTCLASS":                                "syscall",
+	"syscall.RTM_DELTFILTER":                               "syscall",
+	"syscall.RTM_DESYNC":                                   "syscall",
+	"syscall.RTM_F_CLONED":                                 "syscall",
+	"syscall.RTM_F_EQUALIZE":                               "syscall",
+	"syscall.RTM_F_NOTIFY":                                 "syscall",
+	"syscall.RTM_F_PREFIX":                                 "syscall",
+	"syscall.RTM_GET":                                      "syscall",
+	"syscall.RTM_GET2":                                     "syscall",
+	"syscall.RTM_GETACTION":                                "syscall",
+	"syscall.RTM_GETADDR":                                  "syscall",
+	"syscall.RTM_GETADDRLABEL":                             "syscall",
+	"syscall.RTM_GETANYCAST":                               "syscall",
+	"syscall.RTM_GETDCB":                                   "syscall",
+	"syscall.RTM_GETLINK":                                  "syscall",
+	"syscall.RTM_GETMULTICAST":                             "syscall",
+	"syscall.RTM_GETNEIGH":                                 "syscall",
+	"syscall.RTM_GETNEIGHTBL":                              "syscall",
+	"syscall.RTM_GETQDISC":                                 "syscall",
+	"syscall.RTM_GETROUTE":                                 "syscall",
+	"syscall.RTM_GETRULE":                                  "syscall",
+	"syscall.RTM_GETTCLASS":                                "syscall",
+	"syscall.RTM_GETTFILTER":                               "syscall",
+	"syscall.RTM_IEEE80211":                                "syscall",
+	"syscall.RTM_IFANNOUNCE":                               "syscall",
+	"syscall.RTM_IFINFO":                                   "syscall",
+	"syscall.RTM_IFINFO2":                                  "syscall",
+	"syscall.RTM_LLINFO_UPD":                               "syscall",
+	"syscall.RTM_LOCK":                                     "syscall",
+	"syscall.RTM_LOSING":                                   "syscall",
+	"syscall.RTM_MAX":                                      "syscall",
+	"syscall.RTM_MAXSIZE":                                  "syscall",
+	"syscall.RTM_MISS":                                     "syscall",
+	"syscall.RTM_NEWACTION":                                "syscall",
+	"syscall.RTM_NEWADDR":                                  "syscall",
+	"syscall.RTM_NEWADDRLABEL":                             "syscall",
+	"syscall.RTM_NEWLINK":                                  "syscall",
+	"syscall.RTM_NEWMADDR":                                 "syscall",
+	"syscall.RTM_NEWMADDR2":                                "syscall",
+	"syscall.RTM_NEWNDUSEROPT":                             "syscall",
+	"syscall.RTM_NEWNEIGH":                                 "syscall",
+	"syscall.RTM_NEWNEIGHTBL":                              "syscall",
+	"syscall.RTM_NEWPREFIX":                                "syscall",
+	"syscall.RTM_NEWQDISC":                                 "syscall",
+	"syscall.RTM_NEWROUTE":                                 "syscall",
+	"syscall.RTM_NEWRULE":                                  "syscall",
+	"syscall.RTM_NEWTCLASS":                                "syscall",
+	"syscall.RTM_NEWTFILTER":                               "syscall",
+	"syscall.RTM_NR_FAMILIES":                              "syscall",
+	"syscall.RTM_NR_MSGTYPES":                              "syscall",
+	"syscall.RTM_OIFINFO":                                  "syscall",
+	"syscall.RTM_OLDADD":                                   "syscall",
+	"syscall.RTM_OLDDEL":                                   "syscall",
+	"syscall.RTM_OOIFINFO":                                 "syscall",
+	"syscall.RTM_REDIRECT":                                 "syscall",
+	"syscall.RTM_RESOLVE":                                  "syscall",
+	"syscall.RTM_RTTUNIT":                                  "syscall",
+	"syscall.RTM_SETDCB":                                   "syscall",
+	"syscall.RTM_SETGATE":                                  "syscall",
+	"syscall.RTM_SETLINK":                                  "syscall",
+	"syscall.RTM_SETNEIGHTBL":                              "syscall",
+	"syscall.RTM_VERSION":                                  "syscall",
+	"syscall.RTNH_ALIGNTO":                                 "syscall",
+	"syscall.RTNH_F_DEAD":                                  "syscall",
+	"syscall.RTNH_F_ONLINK":                                "syscall",
+	"syscall.RTNH_F_PERVASIVE":                             "syscall",
+	"syscall.RTNLGRP_IPV4_IFADDR":                          "syscall",
+	"syscall.RTNLGRP_IPV4_MROUTE":                          "syscall",
+	"syscall.RTNLGRP_IPV4_ROUTE":                           "syscall",
+	"syscall.RTNLGRP_IPV4_RULE":                            "syscall",
+	"syscall.RTNLGRP_IPV6_IFADDR":                          "syscall",
+	"syscall.RTNLGRP_IPV6_IFINFO":                          "syscall",
+	"syscall.RTNLGRP_IPV6_MROUTE":                          "syscall",
+	"syscall.RTNLGRP_IPV6_PREFIX":                          "syscall",
+	"syscall.RTNLGRP_IPV6_ROUTE":                           "syscall",
+	"syscall.RTNLGRP_IPV6_RULE":                            "syscall",
+	"syscall.RTNLGRP_LINK":                                 "syscall",
+	"syscall.RTNLGRP_ND_USEROPT":                           "syscall",
+	"syscall.RTNLGRP_NEIGH":                                "syscall",
+	"syscall.RTNLGRP_NONE":                                 "syscall",
+	"syscall.RTNLGRP_NOTIFY":                               "syscall",
+	"syscall.RTNLGRP_TC":                                   "syscall",
+	"syscall.RTN_ANYCAST":                                  "syscall",
+	"syscall.RTN_BLACKHOLE":                                "syscall",
+	"syscall.RTN_BROADCAST":                                "syscall",
+	"syscall.RTN_LOCAL":                                    "syscall",
+	"syscall.RTN_MAX":                                      "syscall",
+	"syscall.RTN_MULTICAST":                                "syscall",
+	"syscall.RTN_NAT":                                      "syscall",
+	"syscall.RTN_PROHIBIT":                                 "syscall",
+	"syscall.RTN_THROW":                                    "syscall",
+	"syscall.RTN_UNICAST":                                  "syscall",
+	"syscall.RTN_UNREACHABLE":                              "syscall",
+	"syscall.RTN_UNSPEC":                                   "syscall",
+	"syscall.RTN_XRESOLVE":                                 "syscall",
+	"syscall.RTPROT_BIRD":                                  "syscall",
+	"syscall.RTPROT_BOOT":                                  "syscall",
+	"syscall.RTPROT_DHCP":                                  "syscall",
+	"syscall.RTPROT_DNROUTED":                              "syscall",
+	"syscall.RTPROT_GATED":                                 "syscall",
+	"syscall.RTPROT_KERNEL":                                "syscall",
+	"syscall.RTPROT_MRT":                                   "syscall",
+	"syscall.RTPROT_NTK":                                   "syscall",
+	"syscall.RTPROT_RA":                                    "syscall",
+	"syscall.RTPROT_REDIRECT":                              "syscall",
+	"syscall.RTPROT_STATIC":                                "syscall",
+	"syscall.RTPROT_UNSPEC":                                "syscall",
+	"syscall.RTPROT_XORP":                                  "syscall",
+	"syscall.RTPROT_ZEBRA":                                 "syscall",
+	"syscall.RTV_EXPIRE":                                   "syscall",
+	"syscall.RTV_HOPCOUNT":                                 "syscall",
+	"syscall.RTV_MTU":                                      "syscall",
+	"syscall.RTV_RPIPE":                                    "syscall",
+	"syscall.RTV_RTT":                                      "syscall",
+	"syscall.RTV_RTTVAR":                                   "syscall",
+	"syscall.RTV_SPIPE":                                    "syscall",
+	"syscall.RTV_SSTHRESH":                                 "syscall",
+	"syscall.RTV_WEIGHT":                                   "syscall",
+	"syscall.RT_CACHING_CONTEXT":                           "syscall",
+	"syscall.RT_CLASS_DEFAULT":                             "syscall",
+	"syscall.RT_CLASS_LOCAL":                               "syscall",
+	"syscall.RT_CLASS_MAIN":                                "syscall",
+	"syscall.RT_CLASS_MAX":                                 "syscall",
+	"syscall.RT_CLASS_UNSPEC":                              "syscall",
+	"syscall.RT_DEFAULT_FIB":                               "syscall",
+	"syscall.RT_NORTREF":                                   "syscall",
+	"syscall.RT_SCOPE_HOST":                                "syscall",
+	"syscall.RT_SCOPE_LINK":                                "syscall",
+	"syscall.RT_SCOPE_NOWHERE":                             "syscall",
+	"syscall.RT_SCOPE_SITE":                                "syscall",
+	"syscall.RT_SCOPE_UNIVERSE":                            "syscall",
+	"syscall.RT_TABLEID_MAX":                               "syscall",
+	"syscall.RT_TABLE_COMPAT":                              "syscall",
+	"syscall.RT_TABLE_DEFAULT":                             "syscall",
+	"syscall.RT_TABLE_LOCAL":                               "syscall",
+	"syscall.RT_TABLE_MAIN":                                "syscall",
+	"syscall.RT_TABLE_MAX":                                 "syscall",
+	"syscall.RT_TABLE_UNSPEC":                              "syscall",
+	"syscall.RUSAGE_CHILDREN":                              "syscall",
+	"syscall.RUSAGE_SELF":                                  "syscall",
+	"syscall.RUSAGE_THREAD":                                "syscall",
+	"syscall.Radvisory_t":                                  "syscall",
+	"syscall.RawSockaddr":                                  "syscall",
+	"syscall.RawSockaddrAny":                               "syscall",
+	"syscall.RawSockaddrDatalink":                          "syscall",
+	"syscall.RawSockaddrInet4":                             "syscall",
+	"syscall.RawSockaddrInet6":                             "syscall",
+	"syscall.RawSockaddrLinklayer":                         "syscall",
+	"syscall.RawSockaddrNetlink":                           "syscall",
+	"syscall.RawSockaddrUnix":                              "syscall",
+	"syscall.RawSyscall":                                   "syscall",
+	"syscall.RawSyscall6":                                  "syscall",
+	"syscall.Read":                                         "syscall",
+	"syscall.ReadConsole":                                  "syscall",
+	"syscall.ReadDirectoryChanges":                         "syscall",
+	"syscall.ReadDirent":                                   "syscall",
+	"syscall.ReadFile":                                     "syscall",
+	"syscall.Readlink":                                     "syscall",
+	"syscall.Reboot":                                       "syscall",
+	"syscall.Recvfrom":                                     "syscall",
+	"syscall.Recvmsg":                                      "syscall",
+	"syscall.RegCloseKey":                                  "syscall",
+	"syscall.RegEnumKeyEx":                                 "syscall",
+	"syscall.RegOpenKeyEx":                                 "syscall",
+	"syscall.RegQueryInfoKey":                              "syscall",
+	"syscall.RegQueryValueEx":                              "syscall",
+	"syscall.RemoveDirectory":                              "syscall",
+	"syscall.Removexattr":                                  "syscall",
+	"syscall.Rename":                                       "syscall",
+	"syscall.Renameat":                                     "syscall",
+	"syscall.Revoke":                                       "syscall",
+	"syscall.Rlimit":                                       "syscall",
+	"syscall.Rmdir":                                        "syscall",
+	"syscall.RouteMessage":                                 "syscall",
+	"syscall.RouteRIB":                                     "syscall",
+	"syscall.RtAttr":                                       "syscall",
+	"syscall.RtGenmsg":                                     "syscall",
+	"syscall.RtMetrics":                                    "syscall",
+	"syscall.RtMsg":                                        "syscall",
+	"syscall.RtMsghdr":                                     "syscall",
+	"syscall.RtNexthop":                                    "syscall",
+	"syscall.Rusage":                                       "syscall",
+	"syscall.SCM_BINTIME":                                  "syscall",
+	"syscall.SCM_CREDENTIALS":                              "syscall",
+	"syscall.SCM_CREDS":                                    "syscall",
+	"syscall.SCM_RIGHTS":                                   "syscall",
+	"syscall.SCM_TIMESTAMP":                                "syscall",
+	"syscall.SCM_TIMESTAMPING":                             "syscall",
+	"syscall.SCM_TIMESTAMPNS":                              "syscall",
+	"syscall.SCM_TIMESTAMP_MONOTONIC":                      "syscall",
+	"syscall.SHUT_RD":                                      "syscall",
+	"syscall.SHUT_RDWR":                                    "syscall",
+	"syscall.SHUT_WR":                                      "syscall",
+	"syscall.SID":                                          "syscall",
+	"syscall.SIDAndAttributes":                             "syscall",
+	"syscall.SIGABRT":                                      "syscall",
+	"syscall.SIGALRM":                                      "syscall",
+	"syscall.SIGBUS":                                       "syscall",
+	"syscall.SIGCHLD":                                      "syscall",
+	"syscall.SIGCLD":                                       "syscall",
+	"syscall.SIGCONT":                                      "syscall",
+	"syscall.SIGEMT":                                       "syscall",
+	"syscall.SIGFPE":                                       "syscall",
+	"syscall.SIGHUP":                                       "syscall",
+	"syscall.SIGILL":                                       "syscall",
+	"syscall.SIGINFO":                                      "syscall",
+	"syscall.SIGINT":                                       "syscall",
+	"syscall.SIGIO":                                        "syscall",
+	"syscall.SIGIOT":                                       "syscall",
+	"syscall.SIGKILL":                                      "syscall",
+	"syscall.SIGLIBRT":                                     "syscall",
+	"syscall.SIGLWP":                                       "syscall",
+	"syscall.SIGPIPE":                                      "syscall",
+	"syscall.SIGPOLL":                                      "syscall",
+	"syscall.SIGPROF":                                      "syscall",
+	"syscall.SIGPWR":                                       "syscall",
+	"syscall.SIGQUIT":                                      "syscall",
+	"syscall.SIGSEGV":                                      "syscall",
+	"syscall.SIGSTKFLT":                                    "syscall",
+	"syscall.SIGSTOP":                                      "syscall",
+	"syscall.SIGSYS":                                       "syscall",
+	"syscall.SIGTERM":                                      "syscall",
+	"syscall.SIGTHR":                                       "syscall",
+	"syscall.SIGTRAP":                                      "syscall",
+	"syscall.SIGTSTP":                                      "syscall",
+	"syscall.SIGTTIN":                                      "syscall",
+	"syscall.SIGTTOU":                                      "syscall",
+	"syscall.SIGUNUSED":                                    "syscall",
+	"syscall.SIGURG":                                       "syscall",
+	"syscall.SIGUSR1":                                      "syscall",
+	"syscall.SIGUSR2":                                      "syscall",
+	"syscall.SIGVTALRM":                                    "syscall",
+	"syscall.SIGWINCH":                                     "syscall",
+	"syscall.SIGXCPU":                                      "syscall",
+	"syscall.SIGXFSZ":                                      "syscall",
+	"syscall.SIOCADDDLCI":                                  "syscall",
+	"syscall.SIOCADDMULTI":                                 "syscall",
+	"syscall.SIOCADDRT":                                    "syscall",
+	"syscall.SIOCAIFADDR":                                  "syscall",
+	"syscall.SIOCAIFGROUP":                                 "syscall",
+	"syscall.SIOCALIFADDR":                                 "syscall",
+	"syscall.SIOCARPIPLL":                                  "syscall",
+	"syscall.SIOCATMARK":                                   "syscall",
+	"syscall.SIOCAUTOADDR":                                 "syscall",
+	"syscall.SIOCAUTONETMASK":                              "syscall",
+	"syscall.SIOCBRDGADD":                                  "syscall",
+	"syscall.SIOCBRDGADDS":                                 "syscall",
+	"syscall.SIOCBRDGARL":                                  "syscall",
+	"syscall.SIOCBRDGDADDR":                                "syscall",
+	"syscall.SIOCBRDGDEL":                                  "syscall",
+	"syscall.SIOCBRDGDELS":                                 "syscall",
+	"syscall.SIOCBRDGFLUSH":                                "syscall",
+	"syscall.SIOCBRDGFRL":                                  "syscall",
+	"syscall.SIOCBRDGGCACHE":                               "syscall",
+	"syscall.SIOCBRDGGFD":                                  "syscall",
+	"syscall.SIOCBRDGGHT":                                  "syscall",
+	"syscall.SIOCBRDGGIFFLGS":                              "syscall",
+	"syscall.SIOCBRDGGMA":                                  "syscall",
+	"syscall.SIOCBRDGGPARAM":                               "syscall",
+	"syscall.SIOCBRDGGPRI":                                 "syscall",
+	"syscall.SIOCBRDGGRL":                                  "syscall",
+	"syscall.SIOCBRDGGSIFS":                                "syscall",
+	"syscall.SIOCBRDGGTO":                                  "syscall",
+	"syscall.SIOCBRDGIFS":                                  "syscall",
+	"syscall.SIOCBRDGRTS":                                  "syscall",
+	"syscall.SIOCBRDGSADDR":                                "syscall",
+	"syscall.SIOCBRDGSCACHE":                               "syscall",
+	"syscall.SIOCBRDGSFD":                                  "syscall",
+	"syscall.SIOCBRDGSHT":                                  "syscall",
+	"syscall.SIOCBRDGSIFCOST":                              "syscall",
+	"syscall.SIOCBRDGSIFFLGS":                              "syscall",
+	"syscall.SIOCBRDGSIFPRIO":                              "syscall",
+	"syscall.SIOCBRDGSMA":                                  "syscall",
+	"syscall.SIOCBRDGSPRI":                                 "syscall",
+	"syscall.SIOCBRDGSPROTO":                               "syscall",
+	"syscall.SIOCBRDGSTO":                                  "syscall",
+	"syscall.SIOCBRDGSTXHC":                                "syscall",
+	"syscall.SIOCDARP":                                     "syscall",
+	"syscall.SIOCDELDLCI":                                  "syscall",
+	"syscall.SIOCDELMULTI":                                 "syscall",
+	"syscall.SIOCDELRT":                                    "syscall",
+	"syscall.SIOCDEVPRIVATE":                               "syscall",
+	"syscall.SIOCDIFADDR":                                  "syscall",
+	"syscall.SIOCDIFGROUP":                                 "syscall",
+	"syscall.SIOCDIFPHYADDR":                               "syscall",
+	"syscall.SIOCDLIFADDR":                                 "syscall",
+	"syscall.SIOCDRARP":                                    "syscall",
+	"syscall.SIOCGARP":                                     "syscall",
+	"syscall.SIOCGDRVSPEC":                                 "syscall",
+	"syscall.SIOCGETKALIVE":                                "syscall",
+	"syscall.SIOCGETLABEL":                                 "syscall",
+	"syscall.SIOCGETPFLOW":                                 "syscall",
+	"syscall.SIOCGETPFSYNC":                                "syscall",
+	"syscall.SIOCGETSGCNT":                                 "syscall",
+	"syscall.SIOCGETVIFCNT":                                "syscall",
+	"syscall.SIOCGETVLAN":                                  "syscall",
+	"syscall.SIOCGHIWAT":                                   "syscall",
+	"syscall.SIOCGIFADDR":                                  "syscall",
+	"syscall.SIOCGIFADDRPREF":                              "syscall",
+	"syscall.SIOCGIFALIAS":                                 "syscall",
+	"syscall.SIOCGIFALTMTU":                                "syscall",
+	"syscall.SIOCGIFASYNCMAP":                              "syscall",
+	"syscall.SIOCGIFBOND":                                  "syscall",
+	"syscall.SIOCGIFBR":                                    "syscall",
+	"syscall.SIOCGIFBRDADDR":                               "syscall",
+	"syscall.SIOCGIFCAP":                                   "syscall",
+	"syscall.SIOCGIFCONF":                                  "syscall",
+	"syscall.SIOCGIFCOUNT":                                 "syscall",
+	"syscall.SIOCGIFDATA":                                  "syscall",
+	"syscall.SIOCGIFDESCR":                                 "syscall",
+	"syscall.SIOCGIFDEVMTU":                                "syscall",
+	"syscall.SIOCGIFDLT":                                   "syscall",
+	"syscall.SIOCGIFDSTADDR":                               "syscall",
+	"syscall.SIOCGIFENCAP":                                 "syscall",
+	"syscall.SIOCGIFFIB":                                   "syscall",
+	"syscall.SIOCGIFFLAGS":                                 "syscall",
+	"syscall.SIOCGIFGATTR":                                 "syscall",
+	"syscall.SIOCGIFGENERIC":                               "syscall",
+	"syscall.SIOCGIFGMEMB":                                 "syscall",
+	"syscall.SIOCGIFGROUP":                                 "syscall",
+	"syscall.SIOCGIFHWADDR":                                "syscall",
+	"syscall.SIOCGIFINDEX":                                 "syscall",
+	"syscall.SIOCGIFKPI":                                   "syscall",
+	"syscall.SIOCGIFMAC":                                   "syscall",
+	"syscall.SIOCGIFMAP":                                   "syscall",
+	"syscall.SIOCGIFMEDIA":                                 "syscall",
+	"syscall.SIOCGIFMEM":                                   "syscall",
+	"syscall.SIOCGIFMETRIC":                                "syscall",
+	"syscall.SIOCGIFMTU":                                   "syscall",
+	"syscall.SIOCGIFNAME":                                  "syscall",
+	"syscall.SIOCGIFNETMASK":                               "syscall",
+	"syscall.SIOCGIFPDSTADDR":                              "syscall",
+	"syscall.SIOCGIFPFLAGS":                                "syscall",
+	"syscall.SIOCGIFPHYS":                                  "syscall",
+	"syscall.SIOCGIFPRIORITY":                              "syscall",
+	"syscall.SIOCGIFPSRCADDR":                              "syscall",
+	"syscall.SIOCGIFRDOMAIN":                               "syscall",
+	"syscall.SIOCGIFRTLABEL":                               "syscall",
+	"syscall.SIOCGIFSLAVE":                                 "syscall",
+	"syscall.SIOCGIFSTATUS":                                "syscall",
+	"syscall.SIOCGIFTIMESLOT":                              "syscall",
+	"syscall.SIOCGIFTXQLEN":                                "syscall",
+	"syscall.SIOCGIFVLAN":                                  "syscall",
+	"syscall.SIOCGIFWAKEFLAGS":                             "syscall",
+	"syscall.SIOCGIFXFLAGS":                                "syscall",
+	"syscall.SIOCGLIFADDR":                                 "syscall",
+	"syscall.SIOCGLIFPHYADDR":                              "syscall",
+	"syscall.SIOCGLIFPHYRTABLE":                            "syscall",
+	"syscall.SIOCGLINKSTR":                                 "syscall",
+	"syscall.SIOCGLOWAT":                                   "syscall",
+	"syscall.SIOCGPGRP":                                    "syscall",
+	"syscall.SIOCGPRIVATE_0":                               "syscall",
+	"syscall.SIOCGPRIVATE_1":                               "syscall",
+	"syscall.SIOCGRARP":                                    "syscall",
+	"syscall.SIOCGSTAMP":                                   "syscall",
+	"syscall.SIOCGSTAMPNS":                                 "syscall",
+	"syscall.SIOCGVH":                                      "syscall",
+	"syscall.SIOCIFCREATE":                                 "syscall",
+	"syscall.SIOCIFCREATE2":                                "syscall",
+	"syscall.SIOCIFDESTROY":                                "syscall",
+	"syscall.SIOCIFGCLONERS":                               "syscall",
+	"syscall.SIOCINITIFADDR":                               "syscall",
+	"syscall.SIOCPROTOPRIVATE":                             "syscall",
+	"syscall.SIOCRSLVMULTI":                                "syscall",
+	"syscall.SIOCRTMSG":                                    "syscall",
+	"syscall.SIOCSARP":                                     "syscall",
+	"syscall.SIOCSDRVSPEC":                                 "syscall",
+	"syscall.SIOCSETKALIVE":                                "syscall",
+	"syscall.SIOCSETLABEL":                                 "syscall",
+	"syscall.SIOCSETPFLOW":                                 "syscall",
+	"syscall.SIOCSETPFSYNC":                                "syscall",
+	"syscall.SIOCSETVLAN":                                  "syscall",
+	"syscall.SIOCSHIWAT":                                   "syscall",
+	"syscall.SIOCSIFADDR":                                  "syscall",
+	"syscall.SIOCSIFADDRPREF":                              "syscall",
+	"syscall.SIOCSIFALTMTU":                                "syscall",
+	"syscall.SIOCSIFASYNCMAP":                              "syscall",
+	"syscall.SIOCSIFBOND":                                  "syscall",
+	"syscall.SIOCSIFBR":                                    "syscall",
+	"syscall.SIOCSIFBRDADDR":                               "syscall",
+	"syscall.SIOCSIFCAP":                                   "syscall",
+	"syscall.SIOCSIFDESCR":                                 "syscall",
+	"syscall.SIOCSIFDSTADDR":                               "syscall",
+	"syscall.SIOCSIFENCAP":                                 "syscall",
+	"syscall.SIOCSIFFIB":                                   "syscall",
+	"syscall.SIOCSIFFLAGS":                                 "syscall",
+	"syscall.SIOCSIFGATTR":                                 "syscall",
+	"syscall.SIOCSIFGENERIC":                               "syscall",
+	"syscall.SIOCSIFHWADDR":                                "syscall",
+	"syscall.SIOCSIFHWBROADCAST":                           "syscall",
+	"syscall.SIOCSIFKPI":                                   "syscall",
+	"syscall.SIOCSIFLINK":                                  "syscall",
+	"syscall.SIOCSIFLLADDR":                                "syscall",
+	"syscall.SIOCSIFMAC":                                   "syscall",
+	"syscall.SIOCSIFMAP":                                   "syscall",
+	"syscall.SIOCSIFMEDIA":                                 "syscall",
+	"syscall.SIOCSIFMEM":                                   "syscall",
+	"syscall.SIOCSIFMETRIC":                                "syscall",
+	"syscall.SIOCSIFMTU":                                   "syscall",
+	"syscall.SIOCSIFNAME":                                  "syscall",
+	"syscall.SIOCSIFNETMASK":                               "syscall",
+	"syscall.SIOCSIFPFLAGS":                                "syscall",
+	"syscall.SIOCSIFPHYADDR":                               "syscall",
+	"syscall.SIOCSIFPHYS":                                  "syscall",
+	"syscall.SIOCSIFPRIORITY":                              "syscall",
+	"syscall.SIOCSIFRDOMAIN":                               "syscall",
+	"syscall.SIOCSIFRTLABEL":                               "syscall",
+	"syscall.SIOCSIFRVNET":                                 "syscall",
+	"syscall.SIOCSIFSLAVE":                                 "syscall",
+	"syscall.SIOCSIFTIMESLOT":                              "syscall",
+	"syscall.SIOCSIFTXQLEN":                                "syscall",
+	"syscall.SIOCSIFVLAN":                                  "syscall",
+	"syscall.SIOCSIFVNET":                                  "syscall",
+	"syscall.SIOCSIFXFLAGS":                                "syscall",
+	"syscall.SIOCSLIFPHYADDR":                              "syscall",
+	"syscall.SIOCSLIFPHYRTABLE":                            "syscall",
+	"syscall.SIOCSLINKSTR":                                 "syscall",
+	"syscall.SIOCSLOWAT":                                   "syscall",
+	"syscall.SIOCSPGRP":                                    "syscall",
+	"syscall.SIOCSRARP":                                    "syscall",
+	"syscall.SIOCSVH":                                      "syscall",
+	"syscall.SIOCZIFDATA":                                  "syscall",
+	"syscall.SIO_GET_EXTENSION_FUNCTION_POINTER":           "syscall",
+	"syscall.SIO_GET_INTERFACE_LIST":                       "syscall",
+	"syscall.SOCK_CLOEXEC":                                 "syscall",
+	"syscall.SOCK_DCCP":                                    "syscall",
+	"syscall.SOCK_DGRAM":                                   "syscall",
+	"syscall.SOCK_FLAGS_MASK":                              "syscall",
+	"syscall.SOCK_MAXADDRLEN":                              "syscall",
+	"syscall.SOCK_NONBLOCK":                                "syscall",
+	"syscall.SOCK_NOSIGPIPE":                               "syscall",
+	"syscall.SOCK_PACKET":                                  "syscall",
+	"syscall.SOCK_RAW":                                     "syscall",
+	"syscall.SOCK_RDM":                                     "syscall",
+	"syscall.SOCK_SEQPACKET":                               "syscall",
+	"syscall.SOCK_STREAM":                                  "syscall",
+	"syscall.SOL_AAL":                                      "syscall",
+	"syscall.SOL_ATM":                                      "syscall",
+	"syscall.SOL_DECNET":                                   "syscall",
+	"syscall.SOL_ICMPV6":                                   "syscall",
+	"syscall.SOL_IP":                                       "syscall",
+	"syscall.SOL_IPV6":                                     "syscall",
+	"syscall.SOL_IRDA":                                     "syscall",
+	"syscall.SOL_PACKET":                                   "syscall",
+	"syscall.SOL_RAW":                                      "syscall",
+	"syscall.SOL_SOCKET":                                   "syscall",
+	"syscall.SOL_TCP":                                      "syscall",
+	"syscall.SOL_X25":                                      "syscall",
+	"syscall.SOMAXCONN":                                    "syscall",
+	"syscall.SO_ACCEPTCONN":                                "syscall",
+	"syscall.SO_ACCEPTFILTER":                              "syscall",
+	"syscall.SO_ATTACH_FILTER":                             "syscall",
+	"syscall.SO_BINDANY":                                   "syscall",
+	"syscall.SO_BINDTODEVICE":                              "syscall",
+	"syscall.SO_BINTIME":                                   "syscall",
+	"syscall.SO_BROADCAST":                                 "syscall",
+	"syscall.SO_BSDCOMPAT":                                 "syscall",
+	"syscall.SO_DEBUG":                                     "syscall",
+	"syscall.SO_DETACH_FILTER":                             "syscall",
+	"syscall.SO_DOMAIN":                                    "syscall",
+	"syscall.SO_DONTROUTE":                                 "syscall",
+	"syscall.SO_DONTTRUNC":                                 "syscall",
+	"syscall.SO_ERROR":                                     "syscall",
+	"syscall.SO_KEEPALIVE":                                 "syscall",
+	"syscall.SO_LABEL":                                     "syscall",
+	"syscall.SO_LINGER":                                    "syscall",
+	"syscall.SO_LINGER_SEC":                                "syscall",
+	"syscall.SO_LISTENINCQLEN":                             "syscall",
+	"syscall.SO_LISTENQLEN":                                "syscall",
+	"syscall.SO_LISTENQLIMIT":                              "syscall",
+	"syscall.SO_MARK":                                      "syscall",
+	"syscall.SO_NETPROC":                                   "syscall",
+	"syscall.SO_NKE":                                       "syscall",
+	"syscall.SO_NOADDRERR":                                 "syscall",
+	"syscall.SO_NOHEADER":                                  "syscall",
+	"syscall.SO_NOSIGPIPE":                                 "syscall",
+	"syscall.SO_NOTIFYCONFLICT":                            "syscall",
+	"syscall.SO_NO_CHECK":                                  "syscall",
+	"syscall.SO_NO_DDP":                                    "syscall",
+	"syscall.SO_NO_OFFLOAD":                                "syscall",
+	"syscall.SO_NP_EXTENSIONS":                             "syscall",
+	"syscall.SO_NREAD":                                     "syscall",
+	"syscall.SO_NWRITE":                                    "syscall",
+	"syscall.SO_OOBINLINE":                                 "syscall",
+	"syscall.SO_OVERFLOWED":                                "syscall",
+	"syscall.SO_PASSCRED":                                  "syscall",
+	"syscall.SO_PASSSEC":                                   "syscall",
+	"syscall.SO_PEERCRED":                                  "syscall",
+	"syscall.SO_PEERLABEL":                                 "syscall",
+	"syscall.SO_PEERNAME":                                  "syscall",
+	"syscall.SO_PEERSEC":                                   "syscall",
+	"syscall.SO_PRIORITY":                                  "syscall",
+	"syscall.SO_PROTOCOL":                                  "syscall",
+	"syscall.SO_PROTOTYPE":                                 "syscall",
+	"syscall.SO_RANDOMPORT":                                "syscall",
+	"syscall.SO_RCVBUF":                                    "syscall",
+	"syscall.SO_RCVBUFFORCE":                               "syscall",
+	"syscall.SO_RCVLOWAT":                                  "syscall",
+	"syscall.SO_RCVTIMEO":                                  "syscall",
+	"syscall.SO_RESTRICTIONS":                              "syscall",
+	"syscall.SO_RESTRICT_DENYIN":                           "syscall",
+	"syscall.SO_RESTRICT_DENYOUT":                          "syscall",
+	"syscall.SO_RESTRICT_DENYSET":                          "syscall",
+	"syscall.SO_REUSEADDR":                                 "syscall",
+	"syscall.SO_REUSEPORT":                                 "syscall",
+	"syscall.SO_REUSESHAREUID":                             "syscall",
+	"syscall.SO_RTABLE":                                    "syscall",
+	"syscall.SO_RXQ_OVFL":                                  "syscall",
+	"syscall.SO_SECURITY_AUTHENTICATION":                   "syscall",
+	"syscall.SO_SECURITY_ENCRYPTION_NETWORK":               "syscall",
+	"syscall.SO_SECURITY_ENCRYPTION_TRANSPORT":             "syscall",
+	"syscall.SO_SETFIB":                                    "syscall",
+	"syscall.SO_SNDBUF":                                    "syscall",
+	"syscall.SO_SNDBUFFORCE":                               "syscall",
+	"syscall.SO_SNDLOWAT":                                  "syscall",
+	"syscall.SO_SNDTIMEO":                                  "syscall",
+	"syscall.SO_SPLICE":                                    "syscall",
+	"syscall.SO_TIMESTAMP":                                 "syscall",
+	"syscall.SO_TIMESTAMPING":                              "syscall",
+	"syscall.SO_TIMESTAMPNS":                               "syscall",
+	"syscall.SO_TIMESTAMP_MONOTONIC":                       "syscall",
+	"syscall.SO_TYPE":                                      "syscall",
+	"syscall.SO_UPCALLCLOSEWAIT":                           "syscall",
+	"syscall.SO_UPDATE_ACCEPT_CONTEXT":                     "syscall",
+	"syscall.SO_UPDATE_CONNECT_CONTEXT":                    "syscall",
+	"syscall.SO_USELOOPBACK":                               "syscall",
+	"syscall.SO_USER_COOKIE":                               "syscall",
+	"syscall.SO_WANTMORE":                                  "syscall",
+	"syscall.SO_WANTOOBFLAG":                               "syscall",
+	"syscall.SSLExtraCertChainPolicyPara":                  "syscall",
+	"syscall.STANDARD_RIGHTS_ALL":                          "syscall",
+	"syscall.STANDARD_RIGHTS_EXECUTE":                      "syscall",
+	"syscall.STANDARD_RIGHTS_READ":                         "syscall",
+	"syscall.STANDARD_RIGHTS_REQUIRED":                     "syscall",
+	"syscall.STANDARD_RIGHTS_WRITE":                        "syscall",
+	"syscall.STARTF_USESHOWWINDOW":                         "syscall",
+	"syscall.STARTF_USESTDHANDLES":                         "syscall",
+	"syscall.STD_ERROR_HANDLE":                             "syscall",
+	"syscall.STD_INPUT_HANDLE":                             "syscall",
+	"syscall.STD_OUTPUT_HANDLE":                            "syscall",
+	"syscall.SUBLANG_ENGLISH_US":                           "syscall",
+	"syscall.SW_FORCEMINIMIZE":                             "syscall",
+	"syscall.SW_HIDE":                                      "syscall",
+	"syscall.SW_MAXIMIZE":                                  "syscall",
+	"syscall.SW_MINIMIZE":                                  "syscall",
+	"syscall.SW_NORMAL":                                    "syscall",
+	"syscall.SW_RESTORE":                                   "syscall",
+	"syscall.SW_SHOW":                                      "syscall",
+	"syscall.SW_SHOWDEFAULT":                               "syscall",
+	"syscall.SW_SHOWMAXIMIZED":                             "syscall",
+	"syscall.SW_SHOWMINIMIZED":                             "syscall",
+	"syscall.SW_SHOWMINNOACTIVE":                           "syscall",
+	"syscall.SW_SHOWNA":                                    "syscall",
+	"syscall.SW_SHOWNOACTIVATE":                            "syscall",
+	"syscall.SW_SHOWNORMAL":                                "syscall",
+	"syscall.SYNCHRONIZE":                                  "syscall",
+	"syscall.SYSCTL_VERSION":                               "syscall",
+	"syscall.SYSCTL_VERS_0":                                "syscall",
+	"syscall.SYSCTL_VERS_1":                                "syscall",
+	"syscall.SYSCTL_VERS_MASK":                             "syscall",
+	"syscall.SYS_ABORT2":                                   "syscall",
+	"syscall.SYS_ACCEPT":                                   "syscall",
+	"syscall.SYS_ACCEPT4":                                  "syscall",
+	"syscall.SYS_ACCEPT_NOCANCEL":                          "syscall",
+	"syscall.SYS_ACCESS":                                   "syscall",
+	"syscall.SYS_ACCESS_EXTENDED":                          "syscall",
+	"syscall.SYS_ACCT":                                     "syscall",
+	"syscall.SYS_ADD_KEY":                                  "syscall",
+	"syscall.SYS_ADD_PROFIL":                               "syscall",
+	"syscall.SYS_ADJFREQ":                                  "syscall",
+	"syscall.SYS_ADJTIME":                                  "syscall",
+	"syscall.SYS_ADJTIMEX":                                 "syscall",
+	"syscall.SYS_AFS_SYSCALL":                              "syscall",
+	"syscall.SYS_AIO_CANCEL":                               "syscall",
+	"syscall.SYS_AIO_ERROR":                                "syscall",
+	"syscall.SYS_AIO_FSYNC":                                "syscall",
+	"syscall.SYS_AIO_READ":                                 "syscall",
+	"syscall.SYS_AIO_RETURN":                               "syscall",
+	"syscall.SYS_AIO_SUSPEND":                              "syscall",
+	"syscall.SYS_AIO_SUSPEND_NOCANCEL":                     "syscall",
+	"syscall.SYS_AIO_WRITE":                                "syscall",
+	"syscall.SYS_ALARM":                                    "syscall",
+	"syscall.SYS_ARCH_PRCTL":                               "syscall",
+	"syscall.SYS_ARM_FADVISE64_64":                         "syscall",
+	"syscall.SYS_ARM_SYNC_FILE_RANGE":                      "syscall",
+	"syscall.SYS_ATGETMSG":                                 "syscall",
+	"syscall.SYS_ATPGETREQ":                                "syscall",
+	"syscall.SYS_ATPGETRSP":                                "syscall",
+	"syscall.SYS_ATPSNDREQ":                                "syscall",
+	"syscall.SYS_ATPSNDRSP":                                "syscall",
+	"syscall.SYS_ATPUTMSG":                                 "syscall",
+	"syscall.SYS_ATSOCKET":                                 "syscall",
+	"syscall.SYS_AUDIT":                                    "syscall",
+	"syscall.SYS_AUDITCTL":                                 "syscall",
+	"syscall.SYS_AUDITON":                                  "syscall",
+	"syscall.SYS_AUDIT_SESSION_JOIN":                       "syscall",
+	"syscall.SYS_AUDIT_SESSION_PORT":                       "syscall",
+	"syscall.SYS_AUDIT_SESSION_SELF":                       "syscall",
+	"syscall.SYS_BDFLUSH":                                  "syscall",
+	"syscall.SYS_BIND":                                     "syscall",
+	"syscall.SYS_BREAK":                                    "syscall",
+	"syscall.SYS_BRK":                                      "syscall",
+	"syscall.SYS_BSDTHREAD_CREATE":                         "syscall",
+	"syscall.SYS_BSDTHREAD_REGISTER":                       "syscall",
+	"syscall.SYS_BSDTHREAD_TERMINATE":                      "syscall",
+	"syscall.SYS_CAPGET":                                   "syscall",
+	"syscall.SYS_CAPSET":                                   "syscall",
+	"syscall.SYS_CAP_ENTER":                                "syscall",
+	"syscall.SYS_CAP_FCNTLS_GET":                           "syscall",
+	"syscall.SYS_CAP_FCNTLS_LIMIT":                         "syscall",
+	"syscall.SYS_CAP_GETMODE":                              "syscall",
+	"syscall.SYS_CAP_GETRIGHTS":                            "syscall",
+	"syscall.SYS_CAP_IOCTLS_GET":                           "syscall",
+	"syscall.SYS_CAP_IOCTLS_LIMIT":                         "syscall",
+	"syscall.SYS_CAP_NEW":                                  "syscall",
+	"syscall.SYS_CAP_RIGHTS_GET":                           "syscall",
+	"syscall.SYS_CAP_RIGHTS_LIMIT":                         "syscall",
+	"syscall.SYS_CHDIR":                                    "syscall",
+	"syscall.SYS_CHFLAGS":                                  "syscall",
+	"syscall.SYS_CHMOD":                                    "syscall",
+	"syscall.SYS_CHMOD_EXTENDED":                           "syscall",
+	"syscall.SYS_CHOWN":                                    "syscall",
+	"syscall.SYS_CHOWN32":                                  "syscall",
+	"syscall.SYS_CHROOT":                                   "syscall",
+	"syscall.SYS_CHUD":                                     "syscall",
+	"syscall.SYS_CLOCK_ADJTIME":                            "syscall",
+	"syscall.SYS_CLOCK_GETCPUCLOCKID2":                     "syscall",
+	"syscall.SYS_CLOCK_GETRES":                             "syscall",
+	"syscall.SYS_CLOCK_GETTIME":                            "syscall",
+	"syscall.SYS_CLOCK_NANOSLEEP":                          "syscall",
+	"syscall.SYS_CLOCK_SETTIME":                            "syscall",
+	"syscall.SYS_CLONE":                                    "syscall",
+	"syscall.SYS_CLOSE":                                    "syscall",
+	"syscall.SYS_CLOSEFROM":                                "syscall",
+	"syscall.SYS_CLOSE_NOCANCEL":                           "syscall",
+	"syscall.SYS_CONNECT":                                  "syscall",
+	"syscall.SYS_CONNECT_NOCANCEL":                         "syscall",
+	"syscall.SYS_COPYFILE":                                 "syscall",
+	"syscall.SYS_CPUSET":                                   "syscall",
+	"syscall.SYS_CPUSET_GETAFFINITY":                       "syscall",
+	"syscall.SYS_CPUSET_GETID":                             "syscall",
+	"syscall.SYS_CPUSET_SETAFFINITY":                       "syscall",
+	"syscall.SYS_CPUSET_SETID":                             "syscall",
+	"syscall.SYS_CREAT":                                    "syscall",
+	"syscall.SYS_CREATE_MODULE":                            "syscall",
+	"syscall.SYS_CSOPS":                                    "syscall",
+	"syscall.SYS_DELETE":                                   "syscall",
+	"syscall.SYS_DELETE_MODULE":                            "syscall",
+	"syscall.SYS_DUP":                                      "syscall",
+	"syscall.SYS_DUP2":                                     "syscall",
+	"syscall.SYS_DUP3":                                     "syscall",
+	"syscall.SYS_EACCESS":                                  "syscall",
+	"syscall.SYS_EPOLL_CREATE":                             "syscall",
+	"syscall.SYS_EPOLL_CREATE1":                            "syscall",
+	"syscall.SYS_EPOLL_CTL":                                "syscall",
+	"syscall.SYS_EPOLL_CTL_OLD":                            "syscall",
+	"syscall.SYS_EPOLL_PWAIT":                              "syscall",
+	"syscall.SYS_EPOLL_WAIT":                               "syscall",
+	"syscall.SYS_EPOLL_WAIT_OLD":                           "syscall",
+	"syscall.SYS_EVENTFD":                                  "syscall",
+	"syscall.SYS_EVENTFD2":                                 "syscall",
+	"syscall.SYS_EXCHANGEDATA":                             "syscall",
+	"syscall.SYS_EXECVE":                                   "syscall",
+	"syscall.SYS_EXIT":                                     "syscall",
+	"syscall.SYS_EXIT_GROUP":                               "syscall",
+	"syscall.SYS_EXTATTRCTL":                               "syscall",
+	"syscall.SYS_EXTATTR_DELETE_FD":                        "syscall",
+	"syscall.SYS_EXTATTR_DELETE_FILE":                      "syscall",
+	"syscall.SYS_EXTATTR_DELETE_LINK":                      "syscall",
+	"syscall.SYS_EXTATTR_GET_FD":                           "syscall",
+	"syscall.SYS_EXTATTR_GET_FILE":                         "syscall",
+	"syscall.SYS_EXTATTR_GET_LINK":                         "syscall",
+	"syscall.SYS_EXTATTR_LIST_FD":                          "syscall",
+	"syscall.SYS_EXTATTR_LIST_FILE":                        "syscall",
+	"syscall.SYS_EXTATTR_LIST_LINK":                        "syscall",
+	"syscall.SYS_EXTATTR_SET_FD":                           "syscall",
+	"syscall.SYS_EXTATTR_SET_FILE":                         "syscall",
+	"syscall.SYS_EXTATTR_SET_LINK":                         "syscall",
+	"syscall.SYS_FACCESSAT":                                "syscall",
+	"syscall.SYS_FADVISE64":                                "syscall",
+	"syscall.SYS_FADVISE64_64":                             "syscall",
+	"syscall.SYS_FALLOCATE":                                "syscall",
+	"syscall.SYS_FANOTIFY_INIT":                            "syscall",
+	"syscall.SYS_FANOTIFY_MARK":                            "syscall",
+	"syscall.SYS_FCHDIR":                                   "syscall",
+	"syscall.SYS_FCHFLAGS":                                 "syscall",
+	"syscall.SYS_FCHMOD":                                   "syscall",
+	"syscall.SYS_FCHMODAT":                                 "syscall",
+	"syscall.SYS_FCHMOD_EXTENDED":                          "syscall",
+	"syscall.SYS_FCHOWN":                                   "syscall",
+	"syscall.SYS_FCHOWN32":                                 "syscall",
+	"syscall.SYS_FCHOWNAT":                                 "syscall",
+	"syscall.SYS_FCHROOT":                                  "syscall",
+	"syscall.SYS_FCNTL":                                    "syscall",
+	"syscall.SYS_FCNTL64":                                  "syscall",
+	"syscall.SYS_FCNTL_NOCANCEL":                           "syscall",
+	"syscall.SYS_FDATASYNC":                                "syscall",
+	"syscall.SYS_FEXECVE":                                  "syscall",
+	"syscall.SYS_FFCLOCK_GETCOUNTER":                       "syscall",
+	"syscall.SYS_FFCLOCK_GETESTIMATE":                      "syscall",
+	"syscall.SYS_FFCLOCK_SETESTIMATE":                      "syscall",
+	"syscall.SYS_FFSCTL":                                   "syscall",
+	"syscall.SYS_FGETATTRLIST":                             "syscall",
+	"syscall.SYS_FGETXATTR":                                "syscall",
+	"syscall.SYS_FHOPEN":                                   "syscall",
+	"syscall.SYS_FHSTAT":                                   "syscall",
+	"syscall.SYS_FHSTATFS":                                 "syscall",
+	"syscall.SYS_FILEPORT_MAKEFD":                          "syscall",
+	"syscall.SYS_FILEPORT_MAKEPORT":                        "syscall",
+	"syscall.SYS_FKTRACE":                                  "syscall",
+	"syscall.SYS_FLISTXATTR":                               "syscall",
+	"syscall.SYS_FLOCK":                                    "syscall",
+	"syscall.SYS_FORK":                                     "syscall",
+	"syscall.SYS_FPATHCONF":                                "syscall",
+	"syscall.SYS_FREEBSD6_FTRUNCATE":                       "syscall",
+	"syscall.SYS_FREEBSD6_LSEEK":                           "syscall",
+	"syscall.SYS_FREEBSD6_MMAP":                            "syscall",
+	"syscall.SYS_FREEBSD6_PREAD":                           "syscall",
+	"syscall.SYS_FREEBSD6_PWRITE":                          "syscall",
+	"syscall.SYS_FREEBSD6_TRUNCATE":                        "syscall",
+	"syscall.SYS_FREMOVEXATTR":                             "syscall",
+	"syscall.SYS_FSCTL":                                    "syscall",
+	"syscall.SYS_FSETATTRLIST":                             "syscall",
+	"syscall.SYS_FSETXATTR":                                "syscall",
+	"syscall.SYS_FSGETPATH":                                "syscall",
+	"syscall.SYS_FSTAT":                                    "syscall",
+	"syscall.SYS_FSTAT64":                                  "syscall",
+	"syscall.SYS_FSTAT64_EXTENDED":                         "syscall",
+	"syscall.SYS_FSTATAT":                                  "syscall",
+	"syscall.SYS_FSTATAT64":                                "syscall",
+	"syscall.SYS_FSTATFS":                                  "syscall",
+	"syscall.SYS_FSTATFS64":                                "syscall",
+	"syscall.SYS_FSTATV":                                   "syscall",
+	"syscall.SYS_FSTATVFS1":                                "syscall",
+	"syscall.SYS_FSTAT_EXTENDED":                           "syscall",
+	"syscall.SYS_FSYNC":                                    "syscall",
+	"syscall.SYS_FSYNC_NOCANCEL":                           "syscall",
+	"syscall.SYS_FSYNC_RANGE":                              "syscall",
+	"syscall.SYS_FTIME":                                    "syscall",
+	"syscall.SYS_FTRUNCATE":                                "syscall",
+	"syscall.SYS_FTRUNCATE64":                              "syscall",
+	"syscall.SYS_FUTEX":                                    "syscall",
+	"syscall.SYS_FUTIMENS":                                 "syscall",
+	"syscall.SYS_FUTIMES":                                  "syscall",
+	"syscall.SYS_FUTIMESAT":                                "syscall",
+	"syscall.SYS_GETATTRLIST":                              "syscall",
+	"syscall.SYS_GETAUDIT":                                 "syscall",
+	"syscall.SYS_GETAUDIT_ADDR":                            "syscall",
+	"syscall.SYS_GETAUID":                                  "syscall",
+	"syscall.SYS_GETCONTEXT":                               "syscall",
+	"syscall.SYS_GETCPU":                                   "syscall",
+	"syscall.SYS_GETCWD":                                   "syscall",
+	"syscall.SYS_GETDENTS":                                 "syscall",
+	"syscall.SYS_GETDENTS64":                               "syscall",
+	"syscall.SYS_GETDIRENTRIES":                            "syscall",
+	"syscall.SYS_GETDIRENTRIES64":                          "syscall",
+	"syscall.SYS_GETDIRENTRIESATTR":                        "syscall",
+	"syscall.SYS_GETDTABLECOUNT":                           "syscall",
+	"syscall.SYS_GETDTABLESIZE":                            "syscall",
+	"syscall.SYS_GETEGID":                                  "syscall",
+	"syscall.SYS_GETEGID32":                                "syscall",
+	"syscall.SYS_GETEUID":                                  "syscall",
+	"syscall.SYS_GETEUID32":                                "syscall",
+	"syscall.SYS_GETFH":                                    "syscall",
+	"syscall.SYS_GETFSSTAT":                                "syscall",
+	"syscall.SYS_GETFSSTAT64":                              "syscall",
+	"syscall.SYS_GETGID":                                   "syscall",
+	"syscall.SYS_GETGID32":                                 "syscall",
+	"syscall.SYS_GETGROUPS":                                "syscall",
+	"syscall.SYS_GETGROUPS32":                              "syscall",
+	"syscall.SYS_GETHOSTUUID":                              "syscall",
+	"syscall.SYS_GETITIMER":                                "syscall",
+	"syscall.SYS_GETLCID":                                  "syscall",
+	"syscall.SYS_GETLOGIN":                                 "syscall",
+	"syscall.SYS_GETLOGINCLASS":                            "syscall",
+	"syscall.SYS_GETPEERNAME":                              "syscall",
+	"syscall.SYS_GETPGID":                                  "syscall",
+	"syscall.SYS_GETPGRP":                                  "syscall",
+	"syscall.SYS_GETPID":                                   "syscall",
+	"syscall.SYS_GETPMSG":                                  "syscall",
+	"syscall.SYS_GETPPID":                                  "syscall",
+	"syscall.SYS_GETPRIORITY":                              "syscall",
+	"syscall.SYS_GETRESGID":                                "syscall",
+	"syscall.SYS_GETRESGID32":                              "syscall",
+	"syscall.SYS_GETRESUID":                                "syscall",
+	"syscall.SYS_GETRESUID32":                              "syscall",
+	"syscall.SYS_GETRLIMIT":                                "syscall",
+	"syscall.SYS_GETRTABLE":                                "syscall",
+	"syscall.SYS_GETRUSAGE":                                "syscall",
+	"syscall.SYS_GETSGROUPS":                               "syscall",
+	"syscall.SYS_GETSID":                                   "syscall",
+	"syscall.SYS_GETSOCKNAME":                              "syscall",
+	"syscall.SYS_GETSOCKOPT":                               "syscall",
+	"syscall.SYS_GETTHRID":                                 "syscall",
+	"syscall.SYS_GETTID":                                   "syscall",
+	"syscall.SYS_GETTIMEOFDAY":                             "syscall",
+	"syscall.SYS_GETUID":                                   "syscall",
+	"syscall.SYS_GETUID32":                                 "syscall",
+	"syscall.SYS_GETVFSSTAT":                               "syscall",
+	"syscall.SYS_GETWGROUPS":                               "syscall",
+	"syscall.SYS_GETXATTR":                                 "syscall",
+	"syscall.SYS_GET_KERNEL_SYMS":                          "syscall",
+	"syscall.SYS_GET_MEMPOLICY":                            "syscall",
+	"syscall.SYS_GET_ROBUST_LIST":                          "syscall",
+	"syscall.SYS_GET_THREAD_AREA":                          "syscall",
+	"syscall.SYS_GTTY":                                     "syscall",
+	"syscall.SYS_IDENTITYSVC":                              "syscall",
+	"syscall.SYS_IDLE":                                     "syscall",
+	"syscall.SYS_INITGROUPS":                               "syscall",
+	"syscall.SYS_INIT_MODULE":                              "syscall",
+	"syscall.SYS_INOTIFY_ADD_WATCH":                        "syscall",
+	"syscall.SYS_INOTIFY_INIT":                             "syscall",
+	"syscall.SYS_INOTIFY_INIT1":                            "syscall",
+	"syscall.SYS_INOTIFY_RM_WATCH":                         "syscall",
+	"syscall.SYS_IOCTL":                                    "syscall",
+	"syscall.SYS_IOPERM":                                   "syscall",
+	"syscall.SYS_IOPL":                                     "syscall",
+	"syscall.SYS_IOPOLICYSYS":                              "syscall",
+	"syscall.SYS_IOPRIO_GET":                               "syscall",
+	"syscall.SYS_IOPRIO_SET":                               "syscall",
+	"syscall.SYS_IO_CANCEL":                                "syscall",
+	"syscall.SYS_IO_DESTROY":                               "syscall",
+	"syscall.SYS_IO_GETEVENTS":                             "syscall",
+	"syscall.SYS_IO_SETUP":                                 "syscall",
+	"syscall.SYS_IO_SUBMIT":                                "syscall",
+	"syscall.SYS_IPC":                                      "syscall",
+	"syscall.SYS_ISSETUGID":                                "syscall",
+	"syscall.SYS_JAIL":                                     "syscall",
+	"syscall.SYS_JAIL_ATTACH":                              "syscall",
+	"syscall.SYS_JAIL_GET":                                 "syscall",
+	"syscall.SYS_JAIL_REMOVE":                              "syscall",
+	"syscall.SYS_JAIL_SET":                                 "syscall",
+	"syscall.SYS_KDEBUG_TRACE":                             "syscall",
+	"syscall.SYS_KENV":                                     "syscall",
+	"syscall.SYS_KEVENT":                                   "syscall",
+	"syscall.SYS_KEVENT64":                                 "syscall",
+	"syscall.SYS_KEXEC_LOAD":                               "syscall",
+	"syscall.SYS_KEYCTL":                                   "syscall",
+	"syscall.SYS_KILL":                                     "syscall",
+	"syscall.SYS_KLDFIND":                                  "syscall",
+	"syscall.SYS_KLDFIRSTMOD":                              "syscall",
+	"syscall.SYS_KLDLOAD":                                  "syscall",
+	"syscall.SYS_KLDNEXT":                                  "syscall",
+	"syscall.SYS_KLDSTAT":                                  "syscall",
+	"syscall.SYS_KLDSYM":                                   "syscall",
+	"syscall.SYS_KLDUNLOAD":                                "syscall",
+	"syscall.SYS_KLDUNLOADF":                               "syscall",
+	"syscall.SYS_KQUEUE":                                   "syscall",
+	"syscall.SYS_KQUEUE1":                                  "syscall",
+	"syscall.SYS_KTIMER_CREATE":                            "syscall",
+	"syscall.SYS_KTIMER_DELETE":                            "syscall",
+	"syscall.SYS_KTIMER_GETOVERRUN":                        "syscall",
+	"syscall.SYS_KTIMER_GETTIME":                           "syscall",
+	"syscall.SYS_KTIMER_SETTIME":                           "syscall",
+	"syscall.SYS_KTRACE":                                   "syscall",
+	"syscall.SYS_LCHFLAGS":                                 "syscall",
+	"syscall.SYS_LCHMOD":                                   "syscall",
+	"syscall.SYS_LCHOWN":                                   "syscall",
+	"syscall.SYS_LCHOWN32":                                 "syscall",
+	"syscall.SYS_LGETFH":                                   "syscall",
+	"syscall.SYS_LGETXATTR":                                "syscall",
+	"syscall.SYS_LINK":                                     "syscall",
+	"syscall.SYS_LINKAT":                                   "syscall",
+	"syscall.SYS_LIO_LISTIO":                               "syscall",
+	"syscall.SYS_LISTEN":                                   "syscall",
+	"syscall.SYS_LISTXATTR":                                "syscall",
+	"syscall.SYS_LLISTXATTR":                               "syscall",
+	"syscall.SYS_LOCK":                                     "syscall",
+	"syscall.SYS_LOOKUP_DCOOKIE":                           "syscall",
+	"syscall.SYS_LPATHCONF":                                "syscall",
+	"syscall.SYS_LREMOVEXATTR":                             "syscall",
+	"syscall.SYS_LSEEK":                                    "syscall",
+	"syscall.SYS_LSETXATTR":                                "syscall",
+	"syscall.SYS_LSTAT":                                    "syscall",
+	"syscall.SYS_LSTAT64":                                  "syscall",
+	"syscall.SYS_LSTAT64_EXTENDED":                         "syscall",
+	"syscall.SYS_LSTATV":                                   "syscall",
+	"syscall.SYS_LSTAT_EXTENDED":                           "syscall",
+	"syscall.SYS_LUTIMES":                                  "syscall",
+	"syscall.SYS_MAC_SYSCALL":                              "syscall",
+	"syscall.SYS_MADVISE":                                  "syscall",
+	"syscall.SYS_MADVISE1":                                 "syscall",
+	"syscall.SYS_MAXSYSCALL":                               "syscall",
+	"syscall.SYS_MBIND":                                    "syscall",
+	"syscall.SYS_MIGRATE_PAGES":                            "syscall",
+	"syscall.SYS_MINCORE":                                  "syscall",
+	"syscall.SYS_MINHERIT":                                 "syscall",
+	"syscall.SYS_MKCOMPLEX":                                "syscall",
+	"syscall.SYS_MKDIR":                                    "syscall",
+	"syscall.SYS_MKDIRAT":                                  "syscall",
+	"syscall.SYS_MKDIR_EXTENDED":                           "syscall",
+	"syscall.SYS_MKFIFO":                                   "syscall",
+	"syscall.SYS_MKFIFOAT":                                 "syscall",
+	"syscall.SYS_MKFIFO_EXTENDED":                          "syscall",
+	"syscall.SYS_MKNOD":                                    "syscall",
+	"syscall.SYS_MKNODAT":                                  "syscall",
+	"syscall.SYS_MLOCK":                                    "syscall",
+	"syscall.SYS_MLOCKALL":                                 "syscall",
+	"syscall.SYS_MMAP":                                     "syscall",
+	"syscall.SYS_MMAP2":                                    "syscall",
+	"syscall.SYS_MODCTL":                                   "syscall",
+	"syscall.SYS_MODFIND":                                  "syscall",
+	"syscall.SYS_MODFNEXT":                                 "syscall",
+	"syscall.SYS_MODIFY_LDT":                               "syscall",
+	"syscall.SYS_MODNEXT":                                  "syscall",
+	"syscall.SYS_MODSTAT":                                  "syscall",
+	"syscall.SYS_MODWATCH":                                 "syscall",
+	"syscall.SYS_MOUNT":                                    "syscall",
+	"syscall.SYS_MOVE_PAGES":                               "syscall",
+	"syscall.SYS_MPROTECT":                                 "syscall",
+	"syscall.SYS_MPX":                                      "syscall",
+	"syscall.SYS_MQUERY":                                   "syscall",
+	"syscall.SYS_MQ_GETSETATTR":                            "syscall",
+	"syscall.SYS_MQ_NOTIFY":                                "syscall",
+	"syscall.SYS_MQ_OPEN":                                  "syscall",
+	"syscall.SYS_MQ_TIMEDRECEIVE":                          "syscall",
+	"syscall.SYS_MQ_TIMEDSEND":                             "syscall",
+	"syscall.SYS_MQ_UNLINK":                                "syscall",
+	"syscall.SYS_MREMAP":                                   "syscall",
+	"syscall.SYS_MSGCTL":                                   "syscall",
+	"syscall.SYS_MSGGET":                                   "syscall",
+	"syscall.SYS_MSGRCV":                                   "syscall",
+	"syscall.SYS_MSGRCV_NOCANCEL":                          "syscall",
+	"syscall.SYS_MSGSND":                                   "syscall",
+	"syscall.SYS_MSGSND_NOCANCEL":                          "syscall",
+	"syscall.SYS_MSGSYS":                                   "syscall",
+	"syscall.SYS_MSYNC":                                    "syscall",
+	"syscall.SYS_MSYNC_NOCANCEL":                           "syscall",
+	"syscall.SYS_MUNLOCK":                                  "syscall",
+	"syscall.SYS_MUNLOCKALL":                               "syscall",
+	"syscall.SYS_MUNMAP":                                   "syscall",
+	"syscall.SYS_NAME_TO_HANDLE_AT":                        "syscall",
+	"syscall.SYS_NANOSLEEP":                                "syscall",
+	"syscall.SYS_NEWFSTATAT":                               "syscall",
+	"syscall.SYS_NFSCLNT":                                  "syscall",
+	"syscall.SYS_NFSSERVCTL":                               "syscall",
+	"syscall.SYS_NFSSVC":                                   "syscall",
+	"syscall.SYS_NFSTAT":                                   "syscall",
+	"syscall.SYS_NICE":                                     "syscall",
+	"syscall.SYS_NLSTAT":                                   "syscall",
+	"syscall.SYS_NMOUNT":                                   "syscall",
+	"syscall.SYS_NSTAT":                                    "syscall",
+	"syscall.SYS_NTP_ADJTIME":                              "syscall",
+	"syscall.SYS_NTP_GETTIME":                              "syscall",
+	"syscall.SYS_OABI_SYSCALL_BASE":                        "syscall",
+	"syscall.SYS_OBREAK":                                   "syscall",
+	"syscall.SYS_OLDFSTAT":                                 "syscall",
+	"syscall.SYS_OLDLSTAT":                                 "syscall",
+	"syscall.SYS_OLDOLDUNAME":                              "syscall",
+	"syscall.SYS_OLDSTAT":                                  "syscall",
+	"syscall.SYS_OLDUNAME":                                 "syscall",
+	"syscall.SYS_OPEN":                                     "syscall",
+	"syscall.SYS_OPENAT":                                   "syscall",
+	"syscall.SYS_OPENBSD_POLL":                             "syscall",
+	"syscall.SYS_OPEN_BY_HANDLE_AT":                        "syscall",
+	"syscall.SYS_OPEN_EXTENDED":                            "syscall",
+	"syscall.SYS_OPEN_NOCANCEL":                            "syscall",
+	"syscall.SYS_OVADVISE":                                 "syscall",
+	"syscall.SYS_PACCEPT":                                  "syscall",
+	"syscall.SYS_PATHCONF":                                 "syscall",
+	"syscall.SYS_PAUSE":                                    "syscall",
+	"syscall.SYS_PCICONFIG_IOBASE":                         "syscall",
+	"syscall.SYS_PCICONFIG_READ":                           "syscall",
+	"syscall.SYS_PCICONFIG_WRITE":                          "syscall",
+	"syscall.SYS_PDFORK":                                   "syscall",
+	"syscall.SYS_PDGETPID":                                 "syscall",
+	"syscall.SYS_PDKILL":                                   "syscall",
+	"syscall.SYS_PERF_EVENT_OPEN":                          "syscall",
+	"syscall.SYS_PERSONALITY":                              "syscall",
+	"syscall.SYS_PID_HIBERNATE":                            "syscall",
+	"syscall.SYS_PID_RESUME":                               "syscall",
+	"syscall.SYS_PID_SHUTDOWN_SOCKETS":                     "syscall",
+	"syscall.SYS_PID_SUSPEND":                              "syscall",
+	"syscall.SYS_PIPE":                                     "syscall",
+	"syscall.SYS_PIPE2":                                    "syscall",
+	"syscall.SYS_PIVOT_ROOT":                               "syscall",
+	"syscall.SYS_PMC_CONTROL":                              "syscall",
+	"syscall.SYS_PMC_GET_INFO":                             "syscall",
+	"syscall.SYS_POLL":                                     "syscall",
+	"syscall.SYS_POLLTS":                                   "syscall",
+	"syscall.SYS_POLL_NOCANCEL":                            "syscall",
+	"syscall.SYS_POSIX_FADVISE":                            "syscall",
+	"syscall.SYS_POSIX_FALLOCATE":                          "syscall",
+	"syscall.SYS_POSIX_OPENPT":                             "syscall",
+	"syscall.SYS_POSIX_SPAWN":                              "syscall",
+	"syscall.SYS_PPOLL":                                    "syscall",
+	"syscall.SYS_PRCTL":                                    "syscall",
+	"syscall.SYS_PREAD":                                    "syscall",
+	"syscall.SYS_PREAD64":                                  "syscall",
+	"syscall.SYS_PREADV":                                   "syscall",
+	"syscall.SYS_PREAD_NOCANCEL":                           "syscall",
+	"syscall.SYS_PRLIMIT64":                                "syscall",
+	"syscall.SYS_PROCESS_POLICY":                           "syscall",
+	"syscall.SYS_PROCESS_VM_READV":                         "syscall",
+	"syscall.SYS_PROCESS_VM_WRITEV":                        "syscall",
+	"syscall.SYS_PROC_INFO":                                "syscall",
+	"syscall.SYS_PROF":                                     "syscall",
+	"syscall.SYS_PROFIL":                                   "syscall",
+	"syscall.SYS_PSELECT":                                  "syscall",
+	"syscall.SYS_PSELECT6":                                 "syscall",
+	"syscall.SYS_PSET_ASSIGN":                              "syscall",
+	"syscall.SYS_PSET_CREATE":                              "syscall",
+	"syscall.SYS_PSET_DESTROY":                             "syscall",
+	"syscall.SYS_PSYNCH_CVBROAD":                           "syscall",
+	"syscall.SYS_PSYNCH_CVCLRPREPOST":                      "syscall",
+	"syscall.SYS_PSYNCH_CVSIGNAL":                          "syscall",
+	"syscall.SYS_PSYNCH_CVWAIT":                            "syscall",
+	"syscall.SYS_PSYNCH_MUTEXDROP":                         "syscall",
+	"syscall.SYS_PSYNCH_MUTEXWAIT":                         "syscall",
+	"syscall.SYS_PSYNCH_RW_DOWNGRADE":                      "syscall",
+	"syscall.SYS_PSYNCH_RW_LONGRDLOCK":                     "syscall",
+	"syscall.SYS_PSYNCH_RW_RDLOCK":                         "syscall",
+	"syscall.SYS_PSYNCH_RW_UNLOCK":                         "syscall",
+	"syscall.SYS_PSYNCH_RW_UNLOCK2":                        "syscall",
+	"syscall.SYS_PSYNCH_RW_UPGRADE":                        "syscall",
+	"syscall.SYS_PSYNCH_RW_WRLOCK":                         "syscall",
+	"syscall.SYS_PSYNCH_RW_YIELDWRLOCK":                    "syscall",
+	"syscall.SYS_PTRACE":                                   "syscall",
+	"syscall.SYS_PUTPMSG":                                  "syscall",
+	"syscall.SYS_PWRITE":                                   "syscall",
+	"syscall.SYS_PWRITE64":                                 "syscall",
+	"syscall.SYS_PWRITEV":                                  "syscall",
+	"syscall.SYS_PWRITE_NOCANCEL":                          "syscall",
+	"syscall.SYS_QUERY_MODULE":                             "syscall",
+	"syscall.SYS_QUOTACTL":                                 "syscall",
+	"syscall.SYS_RASCTL":                                   "syscall",
+	"syscall.SYS_RCTL_ADD_RULE":                            "syscall",
+	"syscall.SYS_RCTL_GET_LIMITS":                          "syscall",
+	"syscall.SYS_RCTL_GET_RACCT":                           "syscall",
+	"syscall.SYS_RCTL_GET_RULES":                           "syscall",
+	"syscall.SYS_RCTL_REMOVE_RULE":                         "syscall",
+	"syscall.SYS_READ":                                     "syscall",
+	"syscall.SYS_READAHEAD":                                "syscall",
+	"syscall.SYS_READDIR":                                  "syscall",
+	"syscall.SYS_READLINK":                                 "syscall",
+	"syscall.SYS_READLINKAT":                               "syscall",
+	"syscall.SYS_READV":                                    "syscall",
+	"syscall.SYS_READV_NOCANCEL":                           "syscall",
+	"syscall.SYS_READ_NOCANCEL":                            "syscall",
+	"syscall.SYS_REBOOT":                                   "syscall",
+	"syscall.SYS_RECV":                                     "syscall",
+	"syscall.SYS_RECVFROM":                                 "syscall",
+	"syscall.SYS_RECVFROM_NOCANCEL":                        "syscall",
+	"syscall.SYS_RECVMMSG":                                 "syscall",
+	"syscall.SYS_RECVMSG":                                  "syscall",
+	"syscall.SYS_RECVMSG_NOCANCEL":                         "syscall",
+	"syscall.SYS_REMAP_FILE_PAGES":                         "syscall",
+	"syscall.SYS_REMOVEXATTR":                              "syscall",
+	"syscall.SYS_RENAME":                                   "syscall",
+	"syscall.SYS_RENAMEAT":                                 "syscall",
+	"syscall.SYS_REQUEST_KEY":                              "syscall",
+	"syscall.SYS_RESTART_SYSCALL":                          "syscall",
+	"syscall.SYS_REVOKE":                                   "syscall",
+	"syscall.SYS_RFORK":                                    "syscall",
+	"syscall.SYS_RMDIR":                                    "syscall",
+	"syscall.SYS_RTPRIO":                                   "syscall",
+	"syscall.SYS_RTPRIO_THREAD":                            "syscall",
+	"syscall.SYS_RT_SIGACTION":                             "syscall",
+	"syscall.SYS_RT_SIGPENDING":                            "syscall",
+	"syscall.SYS_RT_SIGPROCMASK":                           "syscall",
+	"syscall.SYS_RT_SIGQUEUEINFO":                          "syscall",
+	"syscall.SYS_RT_SIGRETURN":                             "syscall",
+	"syscall.SYS_RT_SIGSUSPEND":                            "syscall",
+	"syscall.SYS_RT_SIGTIMEDWAIT":                          "syscall",
+	"syscall.SYS_RT_TGSIGQUEUEINFO":                        "syscall",
+	"syscall.SYS_SBRK":                                     "syscall",
+	"syscall.SYS_SCHED_GETAFFINITY":                        "syscall",
+	"syscall.SYS_SCHED_GETPARAM":                           "syscall",
+	"syscall.SYS_SCHED_GETSCHEDULER":                       "syscall",
+	"syscall.SYS_SCHED_GET_PRIORITY_MAX":                   "syscall",
+	"syscall.SYS_SCHED_GET_PRIORITY_MIN":                   "syscall",
+	"syscall.SYS_SCHED_RR_GET_INTERVAL":                    "syscall",
+	"syscall.SYS_SCHED_SETAFFINITY":                        "syscall",
+	"syscall.SYS_SCHED_SETPARAM":                           "syscall",
+	"syscall.SYS_SCHED_SETSCHEDULER":                       "syscall",
+	"syscall.SYS_SCHED_YIELD":                              "syscall",
+	"syscall.SYS_SCTP_GENERIC_RECVMSG":                     "syscall",
+	"syscall.SYS_SCTP_GENERIC_SENDMSG":                     "syscall",
+	"syscall.SYS_SCTP_GENERIC_SENDMSG_IOV":                 "syscall",
+	"syscall.SYS_SCTP_PEELOFF":                             "syscall",
+	"syscall.SYS_SEARCHFS":                                 "syscall",
+	"syscall.SYS_SECURITY":                                 "syscall",
+	"syscall.SYS_SELECT":                                   "syscall",
+	"syscall.SYS_SELECT_NOCANCEL":                          "syscall",
+	"syscall.SYS_SEMCONFIG":                                "syscall",
+	"syscall.SYS_SEMCTL":                                   "syscall",
+	"syscall.SYS_SEMGET":                                   "syscall",
+	"syscall.SYS_SEMOP":                                    "syscall",
+	"syscall.SYS_SEMSYS":                                   "syscall",
+	"syscall.SYS_SEMTIMEDOP":                               "syscall",
+	"syscall.SYS_SEM_CLOSE":                                "syscall",
+	"syscall.SYS_SEM_DESTROY":                              "syscall",
+	"syscall.SYS_SEM_GETVALUE":                             "syscall",
+	"syscall.SYS_SEM_INIT":                                 "syscall",
+	"syscall.SYS_SEM_OPEN":                                 "syscall",
+	"syscall.SYS_SEM_POST":                                 "syscall",
+	"syscall.SYS_SEM_TRYWAIT":                              "syscall",
+	"syscall.SYS_SEM_UNLINK":                               "syscall",
+	"syscall.SYS_SEM_WAIT":                                 "syscall",
+	"syscall.SYS_SEM_WAIT_NOCANCEL":                        "syscall",
+	"syscall.SYS_SEND":                                     "syscall",
+	"syscall.SYS_SENDFILE":                                 "syscall",
+	"syscall.SYS_SENDFILE64":                               "syscall",
+	"syscall.SYS_SENDMMSG":                                 "syscall",
+	"syscall.SYS_SENDMSG":                                  "syscall",
+	"syscall.SYS_SENDMSG_NOCANCEL":                         "syscall",
+	"syscall.SYS_SENDTO":                                   "syscall",
+	"syscall.SYS_SENDTO_NOCANCEL":                          "syscall",
+	"syscall.SYS_SETATTRLIST":                              "syscall",
+	"syscall.SYS_SETAUDIT":                                 "syscall",
+	"syscall.SYS_SETAUDIT_ADDR":                            "syscall",
+	"syscall.SYS_SETAUID":                                  "syscall",
+	"syscall.SYS_SETCONTEXT":                               "syscall",
+	"syscall.SYS_SETDOMAINNAME":                            "syscall",
+	"syscall.SYS_SETEGID":                                  "syscall",
+	"syscall.SYS_SETEUID":                                  "syscall",
+	"syscall.SYS_SETFIB":                                   "syscall",
+	"syscall.SYS_SETFSGID":                                 "syscall",
+	"syscall.SYS_SETFSGID32":                               "syscall",
+	"syscall.SYS_SETFSUID":                                 "syscall",
+	"syscall.SYS_SETFSUID32":                               "syscall",
+	"syscall.SYS_SETGID":                                   "syscall",
+	"syscall.SYS_SETGID32":                                 "syscall",
+	"syscall.SYS_SETGROUPS":                                "syscall",
+	"syscall.SYS_SETGROUPS32":                              "syscall",
+	"syscall.SYS_SETHOSTNAME":                              "syscall",
+	"syscall.SYS_SETITIMER":                                "syscall",
+	"syscall.SYS_SETLCID":                                  "syscall",
+	"syscall.SYS_SETLOGIN":                                 "syscall",
+	"syscall.SYS_SETLOGINCLASS":                            "syscall",
+	"syscall.SYS_SETNS":                                    "syscall",
+	"syscall.SYS_SETPGID":                                  "syscall",
+	"syscall.SYS_SETPRIORITY":                              "syscall",
+	"syscall.SYS_SETPRIVEXEC":                              "syscall",
+	"syscall.SYS_SETREGID":                                 "syscall",
+	"syscall.SYS_SETREGID32":                               "syscall",
+	"syscall.SYS_SETRESGID":                                "syscall",
+	"syscall.SYS_SETRESGID32":                              "syscall",
+	"syscall.SYS_SETRESUID":                                "syscall",
+	"syscall.SYS_SETRESUID32":                              "syscall",
+	"syscall.SYS_SETREUID":                                 "syscall",
+	"syscall.SYS_SETREUID32":                               "syscall",
+	"syscall.SYS_SETRLIMIT":                                "syscall",
+	"syscall.SYS_SETRTABLE":                                "syscall",
+	"syscall.SYS_SETSGROUPS":                               "syscall",
+	"syscall.SYS_SETSID":                                   "syscall",
+	"syscall.SYS_SETSOCKOPT":                               "syscall",
+	"syscall.SYS_SETTID":                                   "syscall",
+	"syscall.SYS_SETTID_WITH_PID":                          "syscall",
+	"syscall.SYS_SETTIMEOFDAY":                             "syscall",
+	"syscall.SYS_SETUID":                                   "syscall",
+	"syscall.SYS_SETUID32":                                 "syscall",
+	"syscall.SYS_SETWGROUPS":                               "syscall",
+	"syscall.SYS_SETXATTR":                                 "syscall",
+	"syscall.SYS_SET_MEMPOLICY":                            "syscall",
+	"syscall.SYS_SET_ROBUST_LIST":                          "syscall",
+	"syscall.SYS_SET_THREAD_AREA":                          "syscall",
+	"syscall.SYS_SET_TID_ADDRESS":                          "syscall",
+	"syscall.SYS_SGETMASK":                                 "syscall",
+	"syscall.SYS_SHARED_REGION_CHECK_NP":                   "syscall",
+	"syscall.SYS_SHARED_REGION_MAP_AND_SLIDE_NP":           "syscall",
+	"syscall.SYS_SHMAT":                                    "syscall",
+	"syscall.SYS_SHMCTL":                                   "syscall",
+	"syscall.SYS_SHMDT":                                    "syscall",
+	"syscall.SYS_SHMGET":                                   "syscall",
+	"syscall.SYS_SHMSYS":                                   "syscall",
+	"syscall.SYS_SHM_OPEN":                                 "syscall",
+	"syscall.SYS_SHM_UNLINK":                               "syscall",
+	"syscall.SYS_SHUTDOWN":                                 "syscall",
+	"syscall.SYS_SIGACTION":                                "syscall",
+	"syscall.SYS_SIGALTSTACK":                              "syscall",
+	"syscall.SYS_SIGNAL":                                   "syscall",
+	"syscall.SYS_SIGNALFD":                                 "syscall",
+	"syscall.SYS_SIGNALFD4":                                "syscall",
+	"syscall.SYS_SIGPENDING":                               "syscall",
+	"syscall.SYS_SIGPROCMASK":                              "syscall",
+	"syscall.SYS_SIGQUEUE":                                 "syscall",
+	"syscall.SYS_SIGQUEUEINFO":                             "syscall",
+	"syscall.SYS_SIGRETURN":                                "syscall",
+	"syscall.SYS_SIGSUSPEND":                               "syscall",
+	"syscall.SYS_SIGSUSPEND_NOCANCEL":                      "syscall",
+	"syscall.SYS_SIGTIMEDWAIT":                             "syscall",
+	"syscall.SYS_SIGWAIT":                                  "syscall",
+	"syscall.SYS_SIGWAITINFO":                              "syscall",
+	"syscall.SYS_SOCKET":                                   "syscall",
+	"syscall.SYS_SOCKETCALL":                               "syscall",
+	"syscall.SYS_SOCKETPAIR":                               "syscall",
+	"syscall.SYS_SPLICE":                                   "syscall",
+	"syscall.SYS_SSETMASK":                                 "syscall",
+	"syscall.SYS_SSTK":                                     "syscall",
+	"syscall.SYS_STACK_SNAPSHOT":                           "syscall",
+	"syscall.SYS_STAT":                                     "syscall",
+	"syscall.SYS_STAT64":                                   "syscall",
+	"syscall.SYS_STAT64_EXTENDED":                          "syscall",
+	"syscall.SYS_STATFS":                                   "syscall",
+	"syscall.SYS_STATFS64":                                 "syscall",
+	"syscall.SYS_STATV":                                    "syscall",
+	"syscall.SYS_STATVFS1":                                 "syscall",
+	"syscall.SYS_STAT_EXTENDED":                            "syscall",
+	"syscall.SYS_STIME":                                    "syscall",
+	"syscall.SYS_STTY":                                     "syscall",
+	"syscall.SYS_SWAPCONTEXT":                              "syscall",
+	"syscall.SYS_SWAPCTL":                                  "syscall",
+	"syscall.SYS_SWAPOFF":                                  "syscall",
+	"syscall.SYS_SWAPON":                                   "syscall",
+	"syscall.SYS_SYMLINK":                                  "syscall",
+	"syscall.SYS_SYMLINKAT":                                "syscall",
+	"syscall.SYS_SYNC":                                     "syscall",
+	"syscall.SYS_SYNCFS":                                   "syscall",
+	"syscall.SYS_SYNC_FILE_RANGE":                          "syscall",
+	"syscall.SYS_SYSARCH":                                  "syscall",
+	"syscall.SYS_SYSCALL":                                  "syscall",
+	"syscall.SYS_SYSCALL_BASE":                             "syscall",
+	"syscall.SYS_SYSFS":                                    "syscall",
+	"syscall.SYS_SYSINFO":                                  "syscall",
+	"syscall.SYS_SYSLOG":                                   "syscall",
+	"syscall.SYS_TEE":                                      "syscall",
+	"syscall.SYS_TGKILL":                                   "syscall",
+	"syscall.SYS_THREAD_SELFID":                            "syscall",
+	"syscall.SYS_THR_CREATE":                               "syscall",
+	"syscall.SYS_THR_EXIT":                                 "syscall",
+	"syscall.SYS_THR_KILL":                                 "syscall",
+	"syscall.SYS_THR_KILL2":                                "syscall",
+	"syscall.SYS_THR_NEW":                                  "syscall",
+	"syscall.SYS_THR_SELF":                                 "syscall",
+	"syscall.SYS_THR_SET_NAME":                             "syscall",
+	"syscall.SYS_THR_SUSPEND":                              "syscall",
+	"syscall.SYS_THR_WAKE":                                 "syscall",
+	"syscall.SYS_TIME":                                     "syscall",
+	"syscall.SYS_TIMERFD_CREATE":                           "syscall",
+	"syscall.SYS_TIMERFD_GETTIME":                          "syscall",
+	"syscall.SYS_TIMERFD_SETTIME":                          "syscall",
+	"syscall.SYS_TIMER_CREATE":                             "syscall",
+	"syscall.SYS_TIMER_DELETE":                             "syscall",
+	"syscall.SYS_TIMER_GETOVERRUN":                         "syscall",
+	"syscall.SYS_TIMER_GETTIME":                            "syscall",
+	"syscall.SYS_TIMER_SETTIME":                            "syscall",
+	"syscall.SYS_TIMES":                                    "syscall",
+	"syscall.SYS_TKILL":                                    "syscall",
+	"syscall.SYS_TRUNCATE":                                 "syscall",
+	"syscall.SYS_TRUNCATE64":                               "syscall",
+	"syscall.SYS_TUXCALL":                                  "syscall",
+	"syscall.SYS_UGETRLIMIT":                               "syscall",
+	"syscall.SYS_ULIMIT":                                   "syscall",
+	"syscall.SYS_UMASK":                                    "syscall",
+	"syscall.SYS_UMASK_EXTENDED":                           "syscall",
+	"syscall.SYS_UMOUNT":                                   "syscall",
+	"syscall.SYS_UMOUNT2":                                  "syscall",
+	"syscall.SYS_UNAME":                                    "syscall",
+	"syscall.SYS_UNDELETE":                                 "syscall",
+	"syscall.SYS_UNLINK":                                   "syscall",
+	"syscall.SYS_UNLINKAT":                                 "syscall",
+	"syscall.SYS_UNMOUNT":                                  "syscall",
+	"syscall.SYS_UNSHARE":                                  "syscall",
+	"syscall.SYS_USELIB":                                   "syscall",
+	"syscall.SYS_USTAT":                                    "syscall",
+	"syscall.SYS_UTIME":                                    "syscall",
+	"syscall.SYS_UTIMENSAT":                                "syscall",
+	"syscall.SYS_UTIMES":                                   "syscall",
+	"syscall.SYS_UTRACE":                                   "syscall",
+	"syscall.SYS_UUIDGEN":                                  "syscall",
+	"syscall.SYS_VADVISE":                                  "syscall",
+	"syscall.SYS_VFORK":                                    "syscall",
+	"syscall.SYS_VHANGUP":                                  "syscall",
+	"syscall.SYS_VM86":                                     "syscall",
+	"syscall.SYS_VM86OLD":                                  "syscall",
+	"syscall.SYS_VMSPLICE":                                 "syscall",
+	"syscall.SYS_VM_PRESSURE_MONITOR":                      "syscall",
+	"syscall.SYS_VSERVER":                                  "syscall",
+	"syscall.SYS_WAIT4":                                    "syscall",
+	"syscall.SYS_WAIT4_NOCANCEL":                           "syscall",
+	"syscall.SYS_WAIT6":                                    "syscall",
+	"syscall.SYS_WAITEVENT":                                "syscall",
+	"syscall.SYS_WAITID":                                   "syscall",
+	"syscall.SYS_WAITID_NOCANCEL":                          "syscall",
+	"syscall.SYS_WAITPID":                                  "syscall",
+	"syscall.SYS_WATCHEVENT":                               "syscall",
+	"syscall.SYS_WORKQ_KERNRETURN":                         "syscall",
+	"syscall.SYS_WORKQ_OPEN":                               "syscall",
+	"syscall.SYS_WRITE":                                    "syscall",
+	"syscall.SYS_WRITEV":                                   "syscall",
+	"syscall.SYS_WRITEV_NOCANCEL":                          "syscall",
+	"syscall.SYS_WRITE_NOCANCEL":                           "syscall",
+	"syscall.SYS_YIELD":                                    "syscall",
+	"syscall.SYS__LLSEEK":                                  "syscall",
+	"syscall.SYS__LWP_CONTINUE":                            "syscall",
+	"syscall.SYS__LWP_CREATE":                              "syscall",
+	"syscall.SYS__LWP_CTL":                                 "syscall",
+	"syscall.SYS__LWP_DETACH":                              "syscall",
+	"syscall.SYS__LWP_EXIT":                                "syscall",
+	"syscall.SYS__LWP_GETNAME":                             "syscall",
+	"syscall.SYS__LWP_GETPRIVATE":                          "syscall",
+	"syscall.SYS__LWP_KILL":                                "syscall",
+	"syscall.SYS__LWP_PARK":                                "syscall",
+	"syscall.SYS__LWP_SELF":                                "syscall",
+	"syscall.SYS__LWP_SETNAME":                             "syscall",
+	"syscall.SYS__LWP_SETPRIVATE":                          "syscall",
+	"syscall.SYS__LWP_SUSPEND":                             "syscall",
+	"syscall.SYS__LWP_UNPARK":                              "syscall",
+	"syscall.SYS__LWP_UNPARK_ALL":                          "syscall",
+	"syscall.SYS__LWP_WAIT":                                "syscall",
+	"syscall.SYS__LWP_WAKEUP":                              "syscall",
+	"syscall.SYS__NEWSELECT":                               "syscall",
+	"syscall.SYS__PSET_BIND":                               "syscall",
+	"syscall.SYS__SCHED_GETAFFINITY":                       "syscall",
+	"syscall.SYS__SCHED_GETPARAM":                          "syscall",
+	"syscall.SYS__SCHED_SETAFFINITY":                       "syscall",
+	"syscall.SYS__SCHED_SETPARAM":                          "syscall",
+	"syscall.SYS__SYSCTL":                                  "syscall",
+	"syscall.SYS__UMTX_LOCK":                               "syscall",
+	"syscall.SYS__UMTX_OP":                                 "syscall",
+	"syscall.SYS__UMTX_UNLOCK":                             "syscall",
+	"syscall.SYS___ACL_ACLCHECK_FD":                        "syscall",
+	"syscall.SYS___ACL_ACLCHECK_FILE":                      "syscall",
+	"syscall.SYS___ACL_ACLCHECK_LINK":                      "syscall",
+	"syscall.SYS___ACL_DELETE_FD":                          "syscall",
+	"syscall.SYS___ACL_DELETE_FILE":                        "syscall",
+	"syscall.SYS___ACL_DELETE_LINK":                        "syscall",
+	"syscall.SYS___ACL_GET_FD":                             "syscall",
+	"syscall.SYS___ACL_GET_FILE":                           "syscall",
+	"syscall.SYS___ACL_GET_LINK":                           "syscall",
+	"syscall.SYS___ACL_SET_FD":                             "syscall",
+	"syscall.SYS___ACL_SET_FILE":                           "syscall",
+	"syscall.SYS___ACL_SET_LINK":                           "syscall",
+	"syscall.SYS___CLONE":                                  "syscall",
+	"syscall.SYS___DISABLE_THREADSIGNAL":                   "syscall",
+	"syscall.SYS___GETCWD":                                 "syscall",
+	"syscall.SYS___GETLOGIN":                               "syscall",
+	"syscall.SYS___GET_TCB":                                "syscall",
+	"syscall.SYS___MAC_EXECVE":                             "syscall",
+	"syscall.SYS___MAC_GETFSSTAT":                          "syscall",
+	"syscall.SYS___MAC_GET_FD":                             "syscall",
+	"syscall.SYS___MAC_GET_FILE":                           "syscall",
+	"syscall.SYS___MAC_GET_LCID":                           "syscall",
+	"syscall.SYS___MAC_GET_LCTX":                           "syscall",
+	"syscall.SYS___MAC_GET_LINK":                           "syscall",
+	"syscall.SYS___MAC_GET_MOUNT":                          "syscall",
+	"syscall.SYS___MAC_GET_PID":                            "syscall",
+	"syscall.SYS___MAC_GET_PROC":                           "syscall",
+	"syscall.SYS___MAC_MOUNT":                              "syscall",
+	"syscall.SYS___MAC_SET_FD":                             "syscall",
+	"syscall.SYS___MAC_SET_FILE":                           "syscall",
+	"syscall.SYS___MAC_SET_LCTX":                           "syscall",
+	"syscall.SYS___MAC_SET_LINK":                           "syscall",
+	"syscall.SYS___MAC_SET_PROC":                           "syscall",
+	"syscall.SYS___MAC_SYSCALL":                            "syscall",
+	"syscall.SYS___OLD_SEMWAIT_SIGNAL":                     "syscall",
+	"syscall.SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL":            "syscall",
+	"syscall.SYS___POSIX_CHOWN":                            "syscall",
+	"syscall.SYS___POSIX_FCHOWN":                           "syscall",
+	"syscall.SYS___POSIX_LCHOWN":                           "syscall",
+	"syscall.SYS___POSIX_RENAME":                           "syscall",
+	"syscall.SYS___PTHREAD_CANCELED":                       "syscall",
+	"syscall.SYS___PTHREAD_CHDIR":                          "syscall",
+	"syscall.SYS___PTHREAD_FCHDIR":                         "syscall",
+	"syscall.SYS___PTHREAD_KILL":                           "syscall",
+	"syscall.SYS___PTHREAD_MARKCANCEL":                     "syscall",
+	"syscall.SYS___PTHREAD_SIGMASK":                        "syscall",
+	"syscall.SYS___QUOTACTL":                               "syscall",
+	"syscall.SYS___SEMCTL":                                 "syscall",
+	"syscall.SYS___SEMWAIT_SIGNAL":                         "syscall",
+	"syscall.SYS___SEMWAIT_SIGNAL_NOCANCEL":                "syscall",
+	"syscall.SYS___SETLOGIN":                               "syscall",
+	"syscall.SYS___SETUGID":                                "syscall",
+	"syscall.SYS___SET_TCB":                                "syscall",
+	"syscall.SYS___SIGACTION_SIGTRAMP":                     "syscall",
+	"syscall.SYS___SIGTIMEDWAIT":                           "syscall",
+	"syscall.SYS___SIGWAIT":                                "syscall",
+	"syscall.SYS___SIGWAIT_NOCANCEL":                       "syscall",
+	"syscall.SYS___SYSCTL":                                 "syscall",
+	"syscall.SYS___TFORK":                                  "syscall",
+	"syscall.SYS___THREXIT":                                "syscall",
+	"syscall.SYS___THRSIGDIVERT":                           "syscall",
+	"syscall.SYS___THRSLEEP":                               "syscall",
+	"syscall.SYS___THRWAKEUP":                              "syscall",
+	"syscall.S_ARCH1":                                      "syscall",
+	"syscall.S_ARCH2":                                      "syscall",
+	"syscall.S_BLKSIZE":                                    "syscall",
+	"syscall.S_IEXEC":                                      "syscall",
+	"syscall.S_IFBLK":                                      "syscall",
+	"syscall.S_IFCHR":                                      "syscall",
+	"syscall.S_IFDIR":                                      "syscall",
+	"syscall.S_IFIFO":                                      "syscall",
+	"syscall.S_IFLNK":                                      "syscall",
+	"syscall.S_IFMT":                                       "syscall",
+	"syscall.S_IFREG":                                      "syscall",
+	"syscall.S_IFSOCK":                                     "syscall",
+	"syscall.S_IFWHT":                                      "syscall",
+	"syscall.S_IREAD":                                      "syscall",
+	"syscall.S_IRGRP":                                      "syscall",
+	"syscall.S_IROTH":                                      "syscall",
+	"syscall.S_IRUSR":                                      "syscall",
+	"syscall.S_IRWXG":                                      "syscall",
+	"syscall.S_IRWXO":                                      "syscall",
+	"syscall.S_IRWXU":                                      "syscall",
+	"syscall.S_ISGID":                                      "syscall",
+	"syscall.S_ISTXT":                                      "syscall",
+	"syscall.S_ISUID":                                      "syscall",
+	"syscall.S_ISVTX":                                      "syscall",
+	"syscall.S_IWGRP":                                      "syscall",
+	"syscall.S_IWOTH":                                      "syscall",
+	"syscall.S_IWRITE":                                     "syscall",
+	"syscall.S_IWUSR":                                      "syscall",
+	"syscall.S_IXGRP":                                      "syscall",
+	"syscall.S_IXOTH":                                      "syscall",
+	"syscall.S_IXUSR":                                      "syscall",
+	"syscall.S_LOGIN_SET":                                  "syscall",
+	"syscall.SecurityAttributes":                           "syscall",
+	"syscall.Seek":                                         "syscall",
+	"syscall.Select":                                       "syscall",
+	"syscall.Sendfile":                                     "syscall",
+	"syscall.Sendmsg":                                      "syscall",
+	"syscall.Sendto":                                       "syscall",
+	"syscall.Servent":                                      "syscall",
+	"syscall.SetBpf":                                       "syscall",
+	"syscall.SetBpfBuflen":                                 "syscall",
+	"syscall.SetBpfDatalink":                               "syscall",
+	"syscall.SetBpfHeadercmpl":                             "syscall",
+	"syscall.SetBpfImmediate":                              "syscall",
+	"syscall.SetBpfInterface":                              "syscall",
+	"syscall.SetBpfPromisc":                                "syscall",
+	"syscall.SetBpfTimeout":                                "syscall",
+	"syscall.SetCurrentDirectory":                          "syscall",
+	"syscall.SetEndOfFile":                                 "syscall",
+	"syscall.SetEnvironmentVariable":                       "syscall",
+	"syscall.SetFileAttributes":                            "syscall",
+	"syscall.SetFileCompletionNotificationModes":           "syscall",
+	"syscall.SetFilePointer":                               "syscall",
+	"syscall.SetFileTime":                                  "syscall",
+	"syscall.SetHandleInformation":                         "syscall",
+	"syscall.SetKevent":                                    "syscall",
+	"syscall.SetLsfPromisc":                                "syscall",
+	"syscall.SetNonblock":                                  "syscall",
+	"syscall.Setdomainname":                                "syscall",
+	"syscall.Setegid":                                      "syscall",
+	"syscall.Setenv":                                       "syscall",
+	"syscall.Seteuid":                                      "syscall",
+	"syscall.Setfsgid":                                     "syscall",
+	"syscall.Setfsuid":                                     "syscall",
+	"syscall.Setgid":                                       "syscall",
+	"syscall.Setgroups":                                    "syscall",
+	"syscall.Sethostname":                                  "syscall",
+	"syscall.Setlogin":                                     "syscall",
+	"syscall.Setpgid":                                      "syscall",
+	"syscall.Setpriority":                                  "syscall",
+	"syscall.Setprivexec":                                  "syscall",
+	"syscall.Setregid":                                     "syscall",
+	"syscall.Setresgid":                                    "syscall",
+	"syscall.Setresuid":                                    "syscall",
+	"syscall.Setreuid":                                     "syscall",
+	"syscall.Setrlimit":                                    "syscall",
+	"syscall.Setsid":                                       "syscall",
+	"syscall.Setsockopt":                                   "syscall",
+	"syscall.SetsockoptByte":                               "syscall",
+	"syscall.SetsockoptICMPv6Filter":                       "syscall",
+	"syscall.SetsockoptIPMreq":                             "syscall",
+	"syscall.SetsockoptIPMreqn":                            "syscall",
+	"syscall.SetsockoptIPv6Mreq":                           "syscall",
+	"syscall.SetsockoptInet4Addr":                          "syscall",
+	"syscall.SetsockoptInt":                                "syscall",
+	"syscall.SetsockoptLinger":                             "syscall",
+	"syscall.SetsockoptString":                             "syscall",
+	"syscall.SetsockoptTimeval":                            "syscall",
+	"syscall.Settimeofday":                                 "syscall",
+	"syscall.Setuid":                                       "syscall",
+	"syscall.Setxattr":                                     "syscall",
+	"syscall.Shutdown":                                     "syscall",
+	"syscall.SidTypeAlias":                                 "syscall",
+	"syscall.SidTypeComputer":                              "syscall",
+	"syscall.SidTypeDeletedAccount":                        "syscall",
+	"syscall.SidTypeDomain":                                "syscall",
+	"syscall.SidTypeGroup":                                 "syscall",
+	"syscall.SidTypeInvalid":                               "syscall",
+	"syscall.SidTypeLabel":                                 "syscall",
+	"syscall.SidTypeUnknown":                               "syscall",
+	"syscall.SidTypeUser":                                  "syscall",
+	"syscall.SidTypeWellKnownGroup":                        "syscall",
+	"syscall.Signal":                                       "syscall",
+	"syscall.SizeofBpfHdr":                                 "syscall",
+	"syscall.SizeofBpfInsn":                                "syscall",
+	"syscall.SizeofBpfProgram":                             "syscall",
+	"syscall.SizeofBpfStat":                                "syscall",
+	"syscall.SizeofBpfVersion":                             "syscall",
+	"syscall.SizeofBpfZbuf":                                "syscall",
+	"syscall.SizeofBpfZbufHeader":                          "syscall",
+	"syscall.SizeofCmsghdr":                                "syscall",
+	"syscall.SizeofICMPv6Filter":                           "syscall",
+	"syscall.SizeofIPMreq":                                 "syscall",
+	"syscall.SizeofIPMreqn":                                "syscall",
+	"syscall.SizeofIPv6MTUInfo":                            "syscall",
+	"syscall.SizeofIPv6Mreq":                               "syscall",
+	"syscall.SizeofIfAddrmsg":                              "syscall",
+	"syscall.SizeofIfAnnounceMsghdr":                       "syscall",
+	"syscall.SizeofIfData":                                 "syscall",
+	"syscall.SizeofIfInfomsg":                              "syscall",
+	"syscall.SizeofIfMsghdr":                               "syscall",
+	"syscall.SizeofIfaMsghdr":                              "syscall",
+	"syscall.SizeofIfmaMsghdr":                             "syscall",
+	"syscall.SizeofIfmaMsghdr2":                            "syscall",
+	"syscall.SizeofInet4Pktinfo":                           "syscall",
+	"syscall.SizeofInet6Pktinfo":                           "syscall",
+	"syscall.SizeofInotifyEvent":                           "syscall",
+	"syscall.SizeofLinger":                                 "syscall",
+	"syscall.SizeofMsghdr":                                 "syscall",
+	"syscall.SizeofNlAttr":                                 "syscall",
+	"syscall.SizeofNlMsgerr":                               "syscall",
+	"syscall.SizeofNlMsghdr":                               "syscall",
+	"syscall.SizeofRtAttr":                                 "syscall",
+	"syscall.SizeofRtGenmsg":                               "syscall",
+	"syscall.SizeofRtMetrics":                              "syscall",
+	"syscall.SizeofRtMsg":                                  "syscall",
+	"syscall.SizeofRtMsghdr":                               "syscall",
+	"syscall.SizeofRtNexthop":                              "syscall",
+	"syscall.SizeofSockFilter":                             "syscall",
+	"syscall.SizeofSockFprog":                              "syscall",
+	"syscall.SizeofSockaddrAny":                            "syscall",
+	"syscall.SizeofSockaddrDatalink":                       "syscall",
+	"syscall.SizeofSockaddrInet4":                          "syscall",
+	"syscall.SizeofSockaddrInet6":                          "syscall",
+	"syscall.SizeofSockaddrLinklayer":                      "syscall",
+	"syscall.SizeofSockaddrNetlink":                        "syscall",
+	"syscall.SizeofSockaddrUnix":                           "syscall",
+	"syscall.SizeofTCPInfo":                                "syscall",
+	"syscall.SizeofUcred":                                  "syscall",
+	"syscall.SlicePtrFromStrings":                          "syscall",
+	"syscall.SockFilter":                                   "syscall",
+	"syscall.SockFprog":                                    "syscall",
+	"syscall.SockaddrDatalink":                             "syscall",
+	"syscall.SockaddrGen":                                  "syscall",
+	"syscall.SockaddrInet4":                                "syscall",
+	"syscall.SockaddrInet6":                                "syscall",
+	"syscall.SockaddrLinklayer":                            "syscall",
+	"syscall.SockaddrNetlink":                              "syscall",
+	"syscall.SockaddrUnix":                                 "syscall",
+	"syscall.Socket":                                       "syscall",
+	"syscall.SocketControlMessage":                         "syscall",
+	"syscall.SocketDisableIPv6":                            "syscall",
+	"syscall.Socketpair":                                   "syscall",
+	"syscall.Splice":                                       "syscall",
+	"syscall.StartProcess":                                 "syscall",
+	"syscall.StartupInfo":                                  "syscall",
+	"syscall.Stat":                                         "syscall",
+	"syscall.Stat_t":                                       "syscall",
+	"syscall.Statfs":                                       "syscall",
+	"syscall.Statfs_t":                                     "syscall",
+	"syscall.Stderr":                                       "syscall",
+	"syscall.Stdin":                                        "syscall",
+	"syscall.Stdout":                                       "syscall",
+	"syscall.StringBytePtr":                                "syscall",
+	"syscall.StringByteSlice":                              "syscall",
+	"syscall.StringSlicePtr":                               "syscall",
+	"syscall.StringToSid":                                  "syscall",
+	"syscall.StringToUTF16":                                "syscall",
+	"syscall.StringToUTF16Ptr":                             "syscall",
+	"syscall.Symlink":                                      "syscall",
+	"syscall.Sync":                                         "syscall",
+	"syscall.SyncFileRange":                                "syscall",
+	"syscall.SysProcAttr":                                  "syscall",
+	"syscall.Syscall":                                      "syscall",
+	"syscall.Syscall12":                                    "syscall",
+	"syscall.Syscall15":                                    "syscall",
+	"syscall.Syscall6":                                     "syscall",
+	"syscall.Syscall9":                                     "syscall",
+	"syscall.Sysctl":                                       "syscall",
+	"syscall.SysctlUint32":                                 "syscall",
+	"syscall.Sysctlnode":                                   "syscall",
+	"syscall.Sysinfo":                                      "syscall",
+	"syscall.Sysinfo_t":                                    "syscall",
+	"syscall.Systemtime":                                   "syscall",
+	"syscall.TCGETS":                                       "syscall",
+	"syscall.TCIFLUSH":                                     "syscall",
+	"syscall.TCIOFLUSH":                                    "syscall",
+	"syscall.TCOFLUSH":                                     "syscall",
+	"syscall.TCPInfo":                                      "syscall",
+	"syscall.TCP_CA_NAME_MAX":                              "syscall",
+	"syscall.TCP_CONGCTL":                                  "syscall",
+	"syscall.TCP_CONGESTION":                               "syscall",
+	"syscall.TCP_CONNECTIONTIMEOUT":                        "syscall",
+	"syscall.TCP_CORK":                                     "syscall",
+	"syscall.TCP_DEFER_ACCEPT":                             "syscall",
+	"syscall.TCP_INFO":                                     "syscall",
+	"syscall.TCP_KEEPALIVE":                                "syscall",
+	"syscall.TCP_KEEPCNT":                                  "syscall",
+	"syscall.TCP_KEEPIDLE":                                 "syscall",
+	"syscall.TCP_KEEPINIT":                                 "syscall",
+	"syscall.TCP_KEEPINTVL":                                "syscall",
+	"syscall.TCP_LINGER2":                                  "syscall",
+	"syscall.TCP_MAXBURST":                                 "syscall",
+	"syscall.TCP_MAXHLEN":                                  "syscall",
+	"syscall.TCP_MAXOLEN":                                  "syscall",
+	"syscall.TCP_MAXSEG":                                   "syscall",
+	"syscall.TCP_MAXWIN":                                   "syscall",
+	"syscall.TCP_MAX_SACK":                                 "syscall",
+	"syscall.TCP_MAX_WINSHIFT":                             "syscall",
+	"syscall.TCP_MD5SIG":                                   "syscall",
+	"syscall.TCP_MD5SIG_MAXKEYLEN":                         "syscall",
+	"syscall.TCP_MINMSS":                                   "syscall",
+	"syscall.TCP_MINMSSOVERLOAD":                           "syscall",
+	"syscall.TCP_MSS":                                      "syscall",
+	"syscall.TCP_NODELAY":                                  "syscall",
+	"syscall.TCP_NOOPT":                                    "syscall",
+	"syscall.TCP_NOPUSH":                                   "syscall",
+	"syscall.TCP_NSTATES":                                  "syscall",
+	"syscall.TCP_QUICKACK":                                 "syscall",
+	"syscall.TCP_RXT_CONNDROPTIME":                         "syscall",
+	"syscall.TCP_RXT_FINDROP":                              "syscall",
+	"syscall.TCP_SACK_ENABLE":                              "syscall",
+	"syscall.TCP_SYNCNT":                                   "syscall",
+	"syscall.TCP_WINDOW_CLAMP":                             "syscall",
+	"syscall.TCSAFLUSH":                                    "syscall",
+	"syscall.TCSETS":                                       "syscall",
+	"syscall.TF_DISCONNECT":                                "syscall",
+	"syscall.TF_REUSE_SOCKET":                              "syscall",
+	"syscall.TF_USE_DEFAULT_WORKER":                        "syscall",
+	"syscall.TF_USE_KERNEL_APC":                            "syscall",
+	"syscall.TF_USE_SYSTEM_THREAD":                         "syscall",
+	"syscall.TF_WRITE_BEHIND":                              "syscall",
+	"syscall.TIME_ZONE_ID_DAYLIGHT":                        "syscall",
+	"syscall.TIME_ZONE_ID_STANDARD":                        "syscall",
+	"syscall.TIME_ZONE_ID_UNKNOWN":                         "syscall",
+	"syscall.TIOCCBRK":                                     "syscall",
+	"syscall.TIOCCDTR":                                     "syscall",
+	"syscall.TIOCCONS":                                     "syscall",
+	"syscall.TIOCDCDTIMESTAMP":                             "syscall",
+	"syscall.TIOCDRAIN":                                    "syscall",
+	"syscall.TIOCDSIMICROCODE":                             "syscall",
+	"syscall.TIOCEXCL":                                     "syscall",
+	"syscall.TIOCEXT":                                      "syscall",
+	"syscall.TIOCFLAG_CDTRCTS":                             "syscall",
+	"syscall.TIOCFLAG_CLOCAL":                              "syscall",
+	"syscall.TIOCFLAG_CRTSCTS":                             "syscall",
+	"syscall.TIOCFLAG_MDMBUF":                              "syscall",
+	"syscall.TIOCFLAG_PPS":                                 "syscall",
+	"syscall.TIOCFLAG_SOFTCAR":                             "syscall",
+	"syscall.TIOCFLUSH":                                    "syscall",
+	"syscall.TIOCGDEV":                                     "syscall",
+	"syscall.TIOCGDRAINWAIT":                               "syscall",
+	"syscall.TIOCGETA":                                     "syscall",
+	"syscall.TIOCGETD":                                     "syscall",
+	"syscall.TIOCGFLAGS":                                   "syscall",
+	"syscall.TIOCGICOUNT":                                  "syscall",
+	"syscall.TIOCGLCKTRMIOS":                               "syscall",
+	"syscall.TIOCGLINED":                                   "syscall",
+	"syscall.TIOCGPGRP":                                    "syscall",
+	"syscall.TIOCGPTN":                                     "syscall",
+	"syscall.TIOCGQSIZE":                                   "syscall",
+	"syscall.TIOCGRANTPT":                                  "syscall",
+	"syscall.TIOCGRS485":                                   "syscall",
+	"syscall.TIOCGSERIAL":                                  "syscall",
+	"syscall.TIOCGSID":                                     "syscall",
+	"syscall.TIOCGSIZE":                                    "syscall",
+	"syscall.TIOCGSOFTCAR":                                 "syscall",
+	"syscall.TIOCGTSTAMP":                                  "syscall",
+	"syscall.TIOCGWINSZ":                                   "syscall",
+	"syscall.TIOCINQ":                                      "syscall",
+	"syscall.TIOCIXOFF":                                    "syscall",
+	"syscall.TIOCIXON":                                     "syscall",
+	"syscall.TIOCLINUX":                                    "syscall",
+	"syscall.TIOCMBIC":                                     "syscall",
+	"syscall.TIOCMBIS":                                     "syscall",
+	"syscall.TIOCMGDTRWAIT":                                "syscall",
+	"syscall.TIOCMGET":                                     "syscall",
+	"syscall.TIOCMIWAIT":                                   "syscall",
+	"syscall.TIOCMODG":                                     "syscall",
+	"syscall.TIOCMODS":                                     "syscall",
+	"syscall.TIOCMSDTRWAIT":                                "syscall",
+	"syscall.TIOCMSET":                                     "syscall",
+	"syscall.TIOCM_CAR":                                    "syscall",
+	"syscall.TIOCM_CD":                                     "syscall",
+	"syscall.TIOCM_CTS":                                    "syscall",
+	"syscall.TIOCM_DCD":                                    "syscall",
+	"syscall.TIOCM_DSR":                                    "syscall",
+	"syscall.TIOCM_DTR":                                    "syscall",
+	"syscall.TIOCM_LE":                                     "syscall",
+	"syscall.TIOCM_RI":                                     "syscall",
+	"syscall.TIOCM_RNG":                                    "syscall",
+	"syscall.TIOCM_RTS":                                    "syscall",
+	"syscall.TIOCM_SR":                                     "syscall",
+	"syscall.TIOCM_ST":                                     "syscall",
+	"syscall.TIOCNOTTY":                                    "syscall",
+	"syscall.TIOCNXCL":                                     "syscall",
+	"syscall.TIOCOUTQ":                                     "syscall",
+	"syscall.TIOCPKT":                                      "syscall",
+	"syscall.TIOCPKT_DATA":                                 "syscall",
+	"syscall.TIOCPKT_DOSTOP":                               "syscall",
+	"syscall.TIOCPKT_FLUSHREAD":                            "syscall",
+	"syscall.TIOCPKT_FLUSHWRITE":                           "syscall",
+	"syscall.TIOCPKT_IOCTL":                                "syscall",
+	"syscall.TIOCPKT_NOSTOP":                               "syscall",
+	"syscall.TIOCPKT_START":                                "syscall",
+	"syscall.TIOCPKT_STOP":                                 "syscall",
+	"syscall.TIOCPTMASTER":                                 "syscall",
+	"syscall.TIOCPTMGET":                                   "syscall",
+	"syscall.TIOCPTSNAME":                                  "syscall",
+	"syscall.TIOCPTYGNAME":                                 "syscall",
+	"syscall.TIOCPTYGRANT":                                 "syscall",
+	"syscall.TIOCPTYUNLK":                                  "syscall",
+	"syscall.TIOCRCVFRAME":                                 "syscall",
+	"syscall.TIOCREMOTE":                                   "syscall",
+	"syscall.TIOCSBRK":                                     "syscall",
+	"syscall.TIOCSCONS":                                    "syscall",
+	"syscall.TIOCSCTTY":                                    "syscall",
+	"syscall.TIOCSDRAINWAIT":                               "syscall",
+	"syscall.TIOCSDTR":                                     "syscall",
+	"syscall.TIOCSERCONFIG":                                "syscall",
+	"syscall.TIOCSERGETLSR":                                "syscall",
+	"syscall.TIOCSERGETMULTI":                              "syscall",
+	"syscall.TIOCSERGSTRUCT":                               "syscall",
+	"syscall.TIOCSERGWILD":                                 "syscall",
+	"syscall.TIOCSERSETMULTI":                              "syscall",
+	"syscall.TIOCSERSWILD":                                 "syscall",
+	"syscall.TIOCSER_TEMT":                                 "syscall",
+	"syscall.TIOCSETA":                                     "syscall",
+	"syscall.TIOCSETAF":                                    "syscall",
+	"syscall.TIOCSETAW":                                    "syscall",
+	"syscall.TIOCSETD":                                     "syscall",
+	"syscall.TIOCSFLAGS":                                   "syscall",
+	"syscall.TIOCSIG":                                      "syscall",
+	"syscall.TIOCSLCKTRMIOS":                               "syscall",
+	"syscall.TIOCSLINED":                                   "syscall",
+	"syscall.TIOCSPGRP":                                    "syscall",
+	"syscall.TIOCSPTLCK":                                   "syscall",
+	"syscall.TIOCSQSIZE":                                   "syscall",
+	"syscall.TIOCSRS485":                                   "syscall",
+	"syscall.TIOCSSERIAL":                                  "syscall",
+	"syscall.TIOCSSIZE":                                    "syscall",
+	"syscall.TIOCSSOFTCAR":                                 "syscall",
+	"syscall.TIOCSTART":                                    "syscall",
+	"syscall.TIOCSTAT":                                     "syscall",
+	"syscall.TIOCSTI":                                      "syscall",
+	"syscall.TIOCSTOP":                                     "syscall",
+	"syscall.TIOCSTSTAMP":                                  "syscall",
+	"syscall.TIOCSWINSZ":                                   "syscall",
+	"syscall.TIOCTIMESTAMP":                                "syscall",
+	"syscall.TIOCUCNTL":                                    "syscall",
+	"syscall.TIOCVHANGUP":                                  "syscall",
+	"syscall.TIOCXMTFRAME":                                 "syscall",
+	"syscall.TOKEN_ADJUST_DEFAULT":                         "syscall",
+	"syscall.TOKEN_ADJUST_GROUPS":                          "syscall",
+	"syscall.TOKEN_ADJUST_PRIVILEGES":                      "syscall",
+	"syscall.TOKEN_ALL_ACCESS":                             "syscall",
+	"syscall.TOKEN_ASSIGN_PRIMARY":                         "syscall",
+	"syscall.TOKEN_DUPLICATE":                              "syscall",
+	"syscall.TOKEN_EXECUTE":                                "syscall",
+	"syscall.TOKEN_IMPERSONATE":                            "syscall",
+	"syscall.TOKEN_QUERY":                                  "syscall",
+	"syscall.TOKEN_QUERY_SOURCE":                           "syscall",
+	"syscall.TOKEN_READ":                                   "syscall",
+	"syscall.TOKEN_WRITE":                                  "syscall",
+	"syscall.TOSTOP":                                       "syscall",
+	"syscall.TRUNCATE_EXISTING":                            "syscall",
+	"syscall.TUNATTACHFILTER":                              "syscall",
+	"syscall.TUNDETACHFILTER":                              "syscall",
+	"syscall.TUNGETFEATURES":                               "syscall",
+	"syscall.TUNGETIFF":                                    "syscall",
+	"syscall.TUNGETSNDBUF":                                 "syscall",
+	"syscall.TUNGETVNETHDRSZ":                              "syscall",
+	"syscall.TUNSETDEBUG":                                  "syscall",
+	"syscall.TUNSETGROUP":                                  "syscall",
+	"syscall.TUNSETIFF":                                    "syscall",
+	"syscall.TUNSETLINK":                                   "syscall",
+	"syscall.TUNSETNOCSUM":                                 "syscall",
+	"syscall.TUNSETOFFLOAD":                                "syscall",
+	"syscall.TUNSETOWNER":                                  "syscall",
+	"syscall.TUNSETPERSIST":                                "syscall",
+	"syscall.TUNSETSNDBUF":                                 "syscall",
+	"syscall.TUNSETTXFILTER":                               "syscall",
+	"syscall.TUNSETVNETHDRSZ":                              "syscall",
+	"syscall.Tee":                                          "syscall",
+	"syscall.TerminateProcess":                             "syscall",
+	"syscall.Termios":                                      "syscall",
+	"syscall.Tgkill":                                       "syscall",
+	"syscall.Time":                                         "syscall",
+	"syscall.Time_t":                                       "syscall",
+	"syscall.Times":                                        "syscall",
+	"syscall.Timespec":                                     "syscall",
+	"syscall.TimespecToNsec":                               "syscall",
+	"syscall.Timeval":                                      "syscall",
+	"syscall.Timeval32":                                    "syscall",
+	"syscall.TimevalToNsec":                                "syscall",
+	"syscall.Timex":                                        "syscall",
+	"syscall.Timezoneinformation":                          "syscall",
+	"syscall.Tms":                                          "syscall",
+	"syscall.Token":                                        "syscall",
+	"syscall.TokenAccessInformation":                       "syscall",
+	"syscall.TokenAuditPolicy":                             "syscall",
+	"syscall.TokenDefaultDacl":                             "syscall",
+	"syscall.TokenElevation":                               "syscall",
+	"syscall.TokenElevationType":                           "syscall",
+	"syscall.TokenGroups":                                  "syscall",
+	"syscall.TokenGroupsAndPrivileges":                     "syscall",
+	"syscall.TokenHasRestrictions":                         "syscall",
+	"syscall.TokenImpersonationLevel":                      "syscall",
+	"syscall.TokenIntegrityLevel":                          "syscall",
+	"syscall.TokenLinkedToken":                             "syscall",
+	"syscall.TokenLogonSid":                                "syscall",
+	"syscall.TokenMandatoryPolicy":                         "syscall",
+	"syscall.TokenOrigin":                                  "syscall",
+	"syscall.TokenOwner":                                   "syscall",
+	"syscall.TokenPrimaryGroup":                            "syscall",
+	"syscall.TokenPrivileges":                              "syscall",
+	"syscall.TokenRestrictedSids":                          "syscall",
+	"syscall.TokenSandBoxInert":                            "syscall",
+	"syscall.TokenSessionId":                               "syscall",
+	"syscall.TokenSessionReference":                        "syscall",
+	"syscall.TokenSource":                                  "syscall",
+	"syscall.TokenStatistics":                              "syscall",
+	"syscall.TokenType":                                    "syscall",
+	"syscall.TokenUIAccess":                                "syscall",
+	"syscall.TokenUser":                                    "syscall",
+	"syscall.TokenVirtualizationAllowed":                   "syscall",
+	"syscall.TokenVirtualizationEnabled":                   "syscall",
+	"syscall.Tokenprimarygroup":                            "syscall",
+	"syscall.Tokenuser":                                    "syscall",
+	"syscall.TranslateAccountName":                         "syscall",
+	"syscall.TranslateName":                                "syscall",
+	"syscall.TransmitFile":                                 "syscall",
+	"syscall.TransmitFileBuffers":                          "syscall",
+	"syscall.Truncate":                                     "syscall",
+	"syscall.USAGE_MATCH_TYPE_AND":                         "syscall",
+	"syscall.USAGE_MATCH_TYPE_OR":                          "syscall",
+	"syscall.UTF16FromString":                              "syscall",
+	"syscall.UTF16PtrFromString":                           "syscall",
+	"syscall.UTF16ToString":                                "syscall",
+	"syscall.Ucred":                                        "syscall",
+	"syscall.Umask":                                        "syscall",
+	"syscall.Uname":                                        "syscall",
+	"syscall.Undelete":                                     "syscall",
+	"syscall.UnixCredentials":                              "syscall",
+	"syscall.UnixRights":                                   "syscall",
+	"syscall.Unlink":                                       "syscall",
+	"syscall.Unlinkat":                                     "syscall",
+	"syscall.UnmapViewOfFile":                              "syscall",
+	"syscall.Unmount":                                      "syscall",
+	"syscall.Unshare":                                      "syscall",
+	"syscall.UserInfo10":                                   "syscall",
+	"syscall.Ustat":                                        "syscall",
+	"syscall.Ustat_t":                                      "syscall",
+	"syscall.Utimbuf":                                      "syscall",
+	"syscall.Utime":                                        "syscall",
+	"syscall.Utimes":                                       "syscall",
+	"syscall.UtimesNano":                                   "syscall",
+	"syscall.Utsname":                                      "syscall",
+	"syscall.VDISCARD":                                     "syscall",
+	"syscall.VDSUSP":                                       "syscall",
+	"syscall.VEOF":                                         "syscall",
+	"syscall.VEOL":                                         "syscall",
+	"syscall.VEOL2":                                        "syscall",
+	"syscall.VERASE":                                       "syscall",
+	"syscall.VERASE2":                                      "syscall",
+	"syscall.VINTR":                                        "syscall",
+	"syscall.VKILL":                                        "syscall",
+	"syscall.VLNEXT":                                       "syscall",
+	"syscall.VMIN":                                         "syscall",
+	"syscall.VQUIT":                                        "syscall",
+	"syscall.VREPRINT":                                     "syscall",
+	"syscall.VSTART":                                       "syscall",
+	"syscall.VSTATUS":                                      "syscall",
+	"syscall.VSTOP":                                        "syscall",
+	"syscall.VSUSP":                                        "syscall",
+	"syscall.VSWTC":                                        "syscall",
+	"syscall.VT0":                                          "syscall",
+	"syscall.VT1":                                          "syscall",
+	"syscall.VTDLY":                                        "syscall",
+	"syscall.VTIME":                                        "syscall",
+	"syscall.VWERASE":                                      "syscall",
+	"syscall.VirtualLock":                                  "syscall",
+	"syscall.VirtualUnlock":                                "syscall",
+	"syscall.WAIT_ABANDONED":                               "syscall",
+	"syscall.WAIT_FAILED":                                  "syscall",
+	"syscall.WAIT_OBJECT_0":                                "syscall",
+	"syscall.WAIT_TIMEOUT":                                 "syscall",
+	"syscall.WALL":                                         "syscall",
+	"syscall.WALLSIG":                                      "syscall",
+	"syscall.WALTSIG":                                      "syscall",
+	"syscall.WCLONE":                                       "syscall",
+	"syscall.WCONTINUED":                                   "syscall",
+	"syscall.WCOREFLAG":                                    "syscall",
+	"syscall.WEXITED":                                      "syscall",
+	"syscall.WLINUXCLONE":                                  "syscall",
+	"syscall.WNOHANG":                                      "syscall",
+	"syscall.WNOTHREAD":                                    "syscall",
+	"syscall.WNOWAIT":                                      "syscall",
+	"syscall.WNOZOMBIE":                                    "syscall",
+	"syscall.WOPTSCHECKED":                                 "syscall",
+	"syscall.WORDSIZE":                                     "syscall",
+	"syscall.WSABuf":                                       "syscall",
+	"syscall.WSACleanup":                                   "syscall",
+	"syscall.WSADESCRIPTION_LEN":                           "syscall",
+	"syscall.WSAData":                                      "syscall",
+	"syscall.WSAEACCES":                                    "syscall",
+	"syscall.WSAEnumProtocols":                             "syscall",
+	"syscall.WSAID_CONNECTEX":                              "syscall",
+	"syscall.WSAIoctl":                                     "syscall",
+	"syscall.WSAPROTOCOL_LEN":                              "syscall",
+	"syscall.WSAProtocolChain":                             "syscall",
+	"syscall.WSAProtocolInfo":                              "syscall",
+	"syscall.WSARecv":                                      "syscall",
+	"syscall.WSARecvFrom":                                  "syscall",
+	"syscall.WSASYS_STATUS_LEN":                            "syscall",
+	"syscall.WSASend":                                      "syscall",
+	"syscall.WSASendTo":                                    "syscall",
+	"syscall.WSASendto":                                    "syscall",
+	"syscall.WSAStartup":                                   "syscall",
+	"syscall.WSTOPPED":                                     "syscall",
+	"syscall.WTRAPPED":                                     "syscall",
+	"syscall.WUNTRACED":                                    "syscall",
+	"syscall.Wait4":                                        "syscall",
+	"syscall.WaitForSingleObject":                          "syscall",
+	"syscall.WaitStatus":                                   "syscall",
+	"syscall.Win32FileAttributeData":                       "syscall",
+	"syscall.Win32finddata":                                "syscall",
+	"syscall.Write":                                        "syscall",
+	"syscall.WriteConsole":                                 "syscall",
+	"syscall.WriteFile":                                    "syscall",
+	"syscall.X509_ASN_ENCODING":                            "syscall",
+	"syscall.XCASE":                                        "syscall",
+	"syscall.XP1_CONNECTIONLESS":                           "syscall",
+	"syscall.XP1_CONNECT_DATA":                             "syscall",
+	"syscall.XP1_DISCONNECT_DATA":                          "syscall",
+	"syscall.XP1_EXPEDITED_DATA":                           "syscall",
+	"syscall.XP1_GRACEFUL_CLOSE":                           "syscall",
+	"syscall.XP1_GUARANTEED_DELIVERY":                      "syscall",
+	"syscall.XP1_GUARANTEED_ORDER":                         "syscall",
+	"syscall.XP1_IFS_HANDLES":                              "syscall",
+	"syscall.XP1_MESSAGE_ORIENTED":                         "syscall",
+	"syscall.XP1_MULTIPOINT_CONTROL_PLANE":                 "syscall",
+	"syscall.XP1_MULTIPOINT_DATA_PLANE":                    "syscall",
+	"syscall.XP1_PARTIAL_MESSAGE":                          "syscall",
+	"syscall.XP1_PSEUDO_STREAM":                            "syscall",
+	"syscall.XP1_QOS_SUPPORTED":                            "syscall",
+	"syscall.XP1_SAN_SUPPORT_SDP":                          "syscall",
+	"syscall.XP1_SUPPORT_BROADCAST":                        "syscall",
+	"syscall.XP1_SUPPORT_MULTIPOINT":                       "syscall",
+	"syscall.XP1_UNI_RECV":                                 "syscall",
+	"syscall.XP1_UNI_SEND":                                 "syscall",
+	"syslog.Dial":                                          "log/syslog",
+	"syslog.LOG_ALERT":                                     "log/syslog",
+	"syslog.LOG_AUTH":                                      "log/syslog",
+	"syslog.LOG_AUTHPRIV":                                  "log/syslog",
+	"syslog.LOG_CRIT":                                      "log/syslog",
+	"syslog.LOG_CRON":                                      "log/syslog",
+	"syslog.LOG_DAEMON":                                    "log/syslog",
+	"syslog.LOG_DEBUG":                                     "log/syslog",
+	"syslog.LOG_EMERG":                                     "log/syslog",
+	"syslog.LOG_ERR":                                       "log/syslog",
+	"syslog.LOG_FTP":                                       "log/syslog",
+	"syslog.LOG_INFO":                                      "log/syslog",
+	"syslog.LOG_KERN":                                      "log/syslog",
+	"syslog.LOG_LOCAL0":                                    "log/syslog",
+	"syslog.LOG_LOCAL1":                                    "log/syslog",
+	"syslog.LOG_LOCAL2":                                    "log/syslog",
+	"syslog.LOG_LOCAL3":                                    "log/syslog",
+	"syslog.LOG_LOCAL4":                                    "log/syslog",
+	"syslog.LOG_LOCAL5":                                    "log/syslog",
+	"syslog.LOG_LOCAL6":                                    "log/syslog",
+	"syslog.LOG_LOCAL7":                                    "log/syslog",
+	"syslog.LOG_LPR":                                       "log/syslog",
+	"syslog.LOG_MAIL":                                      "log/syslog",
+	"syslog.LOG_NEWS":                                      "log/syslog",
+	"syslog.LOG_NOTICE":                                    "log/syslog",
+	"syslog.LOG_SYSLOG":                                    "log/syslog",
+	"syslog.LOG_USER":                                      "log/syslog",
+	"syslog.LOG_UUCP":                                      "log/syslog",
+	"syslog.LOG_WARNING":                                   "log/syslog",
+	"syslog.New":                                           "log/syslog",
+	"syslog.NewLogger":                                     "log/syslog",
+	"syslog.Priority":                                      "log/syslog",
+	"syslog.Writer":                                        "log/syslog",
+	"tabwriter.AlignRight":                                 "text/tabwriter",
+	"tabwriter.Debug":                                      "text/tabwriter",
+	"tabwriter.DiscardEmptyColumns":                        "text/tabwriter",
+	"tabwriter.Escape":                                     "text/tabwriter",
+	"tabwriter.FilterHTML":                                 "text/tabwriter",
+	"tabwriter.NewWriter":                                  "text/tabwriter",
+	"tabwriter.StripEscape":                                "text/tabwriter",
+	"tabwriter.TabIndent":                                  "text/tabwriter",
+	"tabwriter.Writer":                                     "text/tabwriter",
+	"tar.ErrFieldTooLong":                                  "archive/tar",
+	"tar.ErrHeader":                                        "archive/tar",
+	"tar.ErrWriteAfterClose":                               "archive/tar",
+	"tar.ErrWriteTooLong":                                  "archive/tar",
+	"tar.FileInfoHeader":                                   "archive/tar",
+	"tar.Header":                                           "archive/tar",
+	"tar.NewReader":                                        "archive/tar",
+	"tar.NewWriter":                                        "archive/tar",
+	"tar.Reader":                                           "archive/tar",
+	"tar.TypeBlock":                                        "archive/tar",
+	"tar.TypeChar":                                         "archive/tar",
+	"tar.TypeCont":                                         "archive/tar",
+	"tar.TypeDir":                                          "archive/tar",
+	"tar.TypeFifo":                                         "archive/tar",
+	"tar.TypeGNULongLink":                                  "archive/tar",
+	"tar.TypeGNULongName":                                  "archive/tar",
+	"tar.TypeLink":                                         "archive/tar",
+	"tar.TypeReg":                                          "archive/tar",
+	"tar.TypeRegA":                                         "archive/tar",
+	"tar.TypeSymlink":                                      "archive/tar",
+	"tar.TypeXGlobalHeader":                                "archive/tar",
+	"tar.TypeXHeader":                                      "archive/tar",
+	"tar.Writer":                                           "archive/tar",
+	"template.CSS":                                         "html/template",
+	"template.ErrAmbigContext":                             "html/template",
+	"template.ErrBadHTML":                                  "html/template",
+	"template.ErrBranchEnd":                                "html/template",
+	"template.ErrEndContext":                               "html/template",
+	"template.ErrNoSuchTemplate":                           "html/template",
+	"template.ErrOutputContext":                            "html/template",
+	"template.ErrPartialCharset":                           "html/template",
+	"template.ErrPartialEscape":                            "html/template",
+	"template.ErrRangeLoopReentry":                         "html/template",
+	"template.ErrSlashAmbig":                               "html/template",
+	"template.Error":                                       "html/template",
+	"template.ErrorCode":                                   "html/template",
+	// "template.FuncMap" is ambiguous
+	"template.HTML":     "html/template",
+	"template.HTMLAttr": "html/template",
+	// "template.HTMLEscape" is ambiguous
+	// "template.HTMLEscapeString" is ambiguous
+	// "template.HTMLEscaper" is ambiguous
+	"template.JS": "html/template",
+	// "template.JSEscape" is ambiguous
+	// "template.JSEscapeString" is ambiguous
+	// "template.JSEscaper" is ambiguous
+	"template.JSStr": "html/template",
+	// "template.Must" is ambiguous
+	// "template.New" is ambiguous
+	"template.OK": "html/template",
+	// "template.ParseFiles" is ambiguous
+	// "template.ParseGlob" is ambiguous
+	// "template.Template" is ambiguous
+	"template.URL": "html/template",
+	// "template.URLQueryEscaper" is ambiguous
+	"testing.AllocsPerRun":                        "testing",
+	"testing.B":                                   "testing",
+	"testing.Benchmark":                           "testing",
+	"testing.BenchmarkResult":                     "testing",
+	"testing.Cover":                               "testing",
+	"testing.CoverBlock":                          "testing",
+	"testing.InternalBenchmark":                   "testing",
+	"testing.InternalExample":                     "testing",
+	"testing.InternalTest":                        "testing",
+	"testing.Main":                                "testing",
+	"testing.RegisterCover":                       "testing",
+	"testing.RunBenchmarks":                       "testing",
+	"testing.RunExamples":                         "testing",
+	"testing.RunTests":                            "testing",
+	"testing.Short":                               "testing",
+	"testing.T":                                   "testing",
+	"testing.Verbose":                             "testing",
+	"textproto.CanonicalMIMEHeaderKey":            "net/textproto",
+	"textproto.Conn":                              "net/textproto",
+	"textproto.Dial":                              "net/textproto",
+	"textproto.Error":                             "net/textproto",
+	"textproto.MIMEHeader":                        "net/textproto",
+	"textproto.NewConn":                           "net/textproto",
+	"textproto.NewReader":                         "net/textproto",
+	"textproto.NewWriter":                         "net/textproto",
+	"textproto.Pipeline":                          "net/textproto",
+	"textproto.ProtocolError":                     "net/textproto",
+	"textproto.Reader":                            "net/textproto",
+	"textproto.TrimBytes":                         "net/textproto",
+	"textproto.TrimString":                        "net/textproto",
+	"textproto.Writer":                            "net/textproto",
+	"time.ANSIC":                                  "time",
+	"time.After":                                  "time",
+	"time.AfterFunc":                              "time",
+	"time.April":                                  "time",
+	"time.August":                                 "time",
+	"time.Date":                                   "time",
+	"time.December":                               "time",
+	"time.Duration":                               "time",
+	"time.February":                               "time",
+	"time.FixedZone":                              "time",
+	"time.Friday":                                 "time",
+	"time.Hour":                                   "time",
+	"time.January":                                "time",
+	"time.July":                                   "time",
+	"time.June":                                   "time",
+	"time.Kitchen":                                "time",
+	"time.LoadLocation":                           "time",
+	"time.Local":                                  "time",
+	"time.Location":                               "time",
+	"time.March":                                  "time",
+	"time.May":                                    "time",
+	"time.Microsecond":                            "time",
+	"time.Millisecond":                            "time",
+	"time.Minute":                                 "time",
+	"time.Monday":                                 "time",
+	"time.Month":                                  "time",
+	"time.Nanosecond":                             "time",
+	"time.NewTicker":                              "time",
+	"time.NewTimer":                               "time",
+	"time.November":                               "time",
+	"time.Now":                                    "time",
+	"time.October":                                "time",
+	"time.Parse":                                  "time",
+	"time.ParseDuration":                          "time",
+	"time.ParseError":                             "time",
+	"time.ParseInLocation":                        "time",
+	"time.RFC1123":                                "time",
+	"time.RFC1123Z":                               "time",
+	"time.RFC3339":                                "time",
+	"time.RFC3339Nano":                            "time",
+	"time.RFC822":                                 "time",
+	"time.RFC822Z":                                "time",
+	"time.RFC850":                                 "time",
+	"time.RubyDate":                               "time",
+	"time.Saturday":                               "time",
+	"time.Second":                                 "time",
+	"time.September":                              "time",
+	"time.Since":                                  "time",
+	"time.Sleep":                                  "time",
+	"time.Stamp":                                  "time",
+	"time.StampMicro":                             "time",
+	"time.StampMilli":                             "time",
+	"time.StampNano":                              "time",
+	"time.Sunday":                                 "time",
+	"time.Thursday":                               "time",
+	"time.Tick":                                   "time",
+	"time.Ticker":                                 "time",
+	"time.Time":                                   "time",
+	"time.Timer":                                  "time",
+	"time.Tuesday":                                "time",
+	"time.UTC":                                    "time",
+	"time.Unix":                                   "time",
+	"time.UnixDate":                               "time",
+	"time.Wednesday":                              "time",
+	"time.Weekday":                                "time",
+	"tls.Certificate":                             "crypto/tls",
+	"tls.Client":                                  "crypto/tls",
+	"tls.ClientAuthType":                          "crypto/tls",
+	"tls.Config":                                  "crypto/tls",
+	"tls.Conn":                                    "crypto/tls",
+	"tls.ConnectionState":                         "crypto/tls",
+	"tls.Dial":                                    "crypto/tls",
+	"tls.Listen":                                  "crypto/tls",
+	"tls.LoadX509KeyPair":                         "crypto/tls",
+	"tls.NewListener":                             "crypto/tls",
+	"tls.NoClientCert":                            "crypto/tls",
+	"tls.RequestClientCert":                       "crypto/tls",
+	"tls.RequireAndVerifyClientCert":              "crypto/tls",
+	"tls.RequireAnyClientCert":                    "crypto/tls",
+	"tls.Server":                                  "crypto/tls",
+	"tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA":    "crypto/tls",
+	"tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": "crypto/tls",
+	"tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA":    "crypto/tls",
+	"tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA":        "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA":     "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA":      "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256":   "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA":      "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA":          "crypto/tls",
+	"tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA":           "crypto/tls",
+	"tls.TLS_RSA_WITH_AES_128_CBC_SHA":            "crypto/tls",
+	"tls.TLS_RSA_WITH_AES_256_CBC_SHA":            "crypto/tls",
+	"tls.TLS_RSA_WITH_RC4_128_SHA":                "crypto/tls",
+	"tls.VerifyClientCertIfGiven":                 "crypto/tls",
+	"tls.VersionSSL30":                            "crypto/tls",
+	"tls.VersionTLS10":                            "crypto/tls",
+	"tls.VersionTLS11":                            "crypto/tls",
+	"tls.VersionTLS12":                            "crypto/tls",
+	"tls.X509KeyPair":                             "crypto/tls",
+	"token.ADD":                                   "go/token",
+	"token.ADD_ASSIGN":                            "go/token",
+	"token.AND":                                   "go/token",
+	"token.AND_ASSIGN":                            "go/token",
+	"token.AND_NOT":                               "go/token",
+	"token.AND_NOT_ASSIGN":                        "go/token",
+	"token.ARROW":                                 "go/token",
+	"token.ASSIGN":                                "go/token",
+	"token.BREAK":                                 "go/token",
+	"token.CASE":                                  "go/token",
+	"token.CHAN":                                  "go/token",
+	"token.CHAR":                                  "go/token",
+	"token.COLON":                                 "go/token",
+	"token.COMMA":                                 "go/token",
+	"token.COMMENT":                               "go/token",
+	"token.CONST":                                 "go/token",
+	"token.CONTINUE":                              "go/token",
+	"token.DEC":                                   "go/token",
+	"token.DEFAULT":                               "go/token",
+	"token.DEFER":                                 "go/token",
+	"token.DEFINE":                                "go/token",
+	"token.ELLIPSIS":                              "go/token",
+	"token.ELSE":                                  "go/token",
+	"token.EOF":                                   "go/token",
+	"token.EQL":                                   "go/token",
+	"token.FALLTHROUGH":                           "go/token",
+	"token.FLOAT":                                 "go/token",
+	"token.FOR":                                   "go/token",
+	"token.FUNC":                                  "go/token",
+	"token.File":                                  "go/token",
+	"token.FileSet":                               "go/token",
+	"token.GEQ":                                   "go/token",
+	"token.GO":                                    "go/token",
+	"token.GOTO":                                  "go/token",
+	"token.GTR":                                   "go/token",
+	"token.HighestPrec":                           "go/token",
+	"token.IDENT":                                 "go/token",
+	"token.IF":                                    "go/token",
+	"token.ILLEGAL":                               "go/token",
+	"token.IMAG":                                  "go/token",
+	"token.IMPORT":                                "go/token",
+	"token.INC":                                   "go/token",
+	"token.INT":                                   "go/token",
+	"token.INTERFACE":                             "go/token",
+	"token.LAND":                                  "go/token",
+	"token.LBRACE":                                "go/token",
+	"token.LBRACK":                                "go/token",
+	"token.LEQ":                                   "go/token",
+	"token.LOR":                                   "go/token",
+	"token.LPAREN":                                "go/token",
+	"token.LSS":                                   "go/token",
+	"token.Lookup":                                "go/token",
+	"token.LowestPrec":                            "go/token",
+	"token.MAP":                                   "go/token",
+	"token.MUL":                                   "go/token",
+	"token.MUL_ASSIGN":                            "go/token",
+	"token.NEQ":                                   "go/token",
+	"token.NOT":                                   "go/token",
+	"token.NewFileSet":                            "go/token",
+	"token.NoPos":                                 "go/token",
+	"token.OR":                                    "go/token",
+	"token.OR_ASSIGN":                             "go/token",
+	"token.PACKAGE":                               "go/token",
+	"token.PERIOD":                                "go/token",
+	"token.Pos":                                   "go/token",
+	"token.Position":                              "go/token",
+	"token.QUO":                                   "go/token",
+	"token.QUO_ASSIGN":                            "go/token",
+	"token.RANGE":                                 "go/token",
+	"token.RBRACE":                                "go/token",
+	"token.RBRACK":                                "go/token",
+	"token.REM":                                   "go/token",
+	"token.REM_ASSIGN":                            "go/token",
+	"token.RETURN":                                "go/token",
+	"token.RPAREN":                                "go/token",
+	"token.SELECT":                                "go/token",
+	"token.SEMICOLON":                             "go/token",
+	"token.SHL":                                   "go/token",
+	"token.SHL_ASSIGN":                            "go/token",
+	"token.SHR":                                   "go/token",
+	"token.SHR_ASSIGN":                            "go/token",
+	"token.STRING":                                "go/token",
+	"token.STRUCT":                                "go/token",
+	"token.SUB":                                   "go/token",
+	"token.SUB_ASSIGN":                            "go/token",
+	"token.SWITCH":                                "go/token",
+	"token.TYPE":                                  "go/token",
+	"token.Token":                                 "go/token",
+	"token.UnaryPrec":                             "go/token",
+	"token.VAR":                                   "go/token",
+	"token.XOR":                                   "go/token",
+	"token.XOR_ASSIGN":                            "go/token",
+	"unicode.ASCII_Hex_Digit":                     "unicode",
+	"unicode.Arabic":                              "unicode",
+	"unicode.Armenian":                            "unicode",
+	"unicode.Avestan":                             "unicode",
+	"unicode.AzeriCase":                           "unicode",
+	"unicode.Balinese":                            "unicode",
+	"unicode.Bamum":                               "unicode",
+	"unicode.Batak":                               "unicode",
+	"unicode.Bengali":                             "unicode",
+	"unicode.Bidi_Control":                        "unicode",
+	"unicode.Bopomofo":                            "unicode",
+	"unicode.Brahmi":                              "unicode",
+	"unicode.Braille":                             "unicode",
+	"unicode.Buginese":                            "unicode",
+	"unicode.Buhid":                               "unicode",
+	"unicode.C":                                   "unicode",
+	"unicode.Canadian_Aboriginal":                 "unicode",
+	"unicode.Carian":                              "unicode",
+	"unicode.CaseRange":                           "unicode",
+	"unicode.CaseRanges":                          "unicode",
+	"unicode.Categories":                          "unicode",
+	"unicode.Cc":                                  "unicode",
+	"unicode.Cf":                                  "unicode",
+	"unicode.Chakma":                              "unicode",
+	"unicode.Cham":                                "unicode",
+	"unicode.Cherokee":                            "unicode",
+	"unicode.Co":                                  "unicode",
+	"unicode.Common":                              "unicode",
+	"unicode.Coptic":                              "unicode",
+	"unicode.Cs":                                  "unicode",
+	"unicode.Cuneiform":                           "unicode",
+	"unicode.Cypriot":                             "unicode",
+	"unicode.Cyrillic":                            "unicode",
+	"unicode.Dash":                                "unicode",
+	"unicode.Deprecated":                          "unicode",
+	"unicode.Deseret":                             "unicode",
+	"unicode.Devanagari":                          "unicode",
+	"unicode.Diacritic":                           "unicode",
+	"unicode.Digit":                               "unicode",
+	"unicode.Egyptian_Hieroglyphs":                "unicode",
+	"unicode.Ethiopic":                            "unicode",
+	"unicode.Extender":                            "unicode",
+	"unicode.FoldCategory":                        "unicode",
+	"unicode.FoldScript":                          "unicode",
+	"unicode.Georgian":                            "unicode",
+	"unicode.Glagolitic":                          "unicode",
+	"unicode.Gothic":                              "unicode",
+	"unicode.GraphicRanges":                       "unicode",
+	"unicode.Greek":                               "unicode",
+	"unicode.Gujarati":                            "unicode",
+	"unicode.Gurmukhi":                            "unicode",
+	"unicode.Han":                                 "unicode",
+	"unicode.Hangul":                              "unicode",
+	"unicode.Hanunoo":                             "unicode",
+	"unicode.Hebrew":                              "unicode",
+	"unicode.Hex_Digit":                           "unicode",
+	"unicode.Hiragana":                            "unicode",
+	"unicode.Hyphen":                              "unicode",
+	"unicode.IDS_Binary_Operator":                 "unicode",
+	"unicode.IDS_Trinary_Operator":                "unicode",
+	"unicode.Ideographic":                         "unicode",
+	"unicode.Imperial_Aramaic":                    "unicode",
+	"unicode.In":                                  "unicode",
+	"unicode.Inherited":                           "unicode",
+	"unicode.Inscriptional_Pahlavi":               "unicode",
+	"unicode.Inscriptional_Parthian":              "unicode",
+	"unicode.Is":                                  "unicode",
+	"unicode.IsControl":                           "unicode",
+	"unicode.IsDigit":                             "unicode",
+	"unicode.IsGraphic":                           "unicode",
+	"unicode.IsLetter":                            "unicode",
+	"unicode.IsLower":                             "unicode",
+	"unicode.IsMark":                              "unicode",
+	"unicode.IsNumber":                            "unicode",
+	"unicode.IsOneOf":                             "unicode",
+	"unicode.IsPrint":                             "unicode",
+	"unicode.IsPunct":                             "unicode",
+	"unicode.IsSpace":                             "unicode",
+	"unicode.IsSymbol":                            "unicode",
+	"unicode.IsTitle":                             "unicode",
+	"unicode.IsUpper":                             "unicode",
+	"unicode.Javanese":                            "unicode",
+	"unicode.Join_Control":                        "unicode",
+	"unicode.Kaithi":                              "unicode",
+	"unicode.Kannada":                             "unicode",
+	"unicode.Katakana":                            "unicode",
+	"unicode.Kayah_Li":                            "unicode",
+	"unicode.Kharoshthi":                          "unicode",
+	"unicode.Khmer":                               "unicode",
+	"unicode.L":                                   "unicode",
+	"unicode.Lao":                                 "unicode",
+	"unicode.Latin":                               "unicode",
+	"unicode.Lepcha":                              "unicode",
+	"unicode.Letter":                              "unicode",
+	"unicode.Limbu":                               "unicode",
+	"unicode.Linear_B":                            "unicode",
+	"unicode.Lisu":                                "unicode",
+	"unicode.Ll":                                  "unicode",
+	"unicode.Lm":                                  "unicode",
+	"unicode.Lo":                                  "unicode",
+	"unicode.Logical_Order_Exception":             "unicode",
+	"unicode.Lower":                               "unicode",
+	"unicode.LowerCase":                           "unicode",
+	"unicode.Lt":                                  "unicode",
+	"unicode.Lu":                                  "unicode",
+	"unicode.Lycian":                              "unicode",
+	"unicode.Lydian":                              "unicode",
+	"unicode.M":                                   "unicode",
+	"unicode.Malayalam":                           "unicode",
+	"unicode.Mandaic":                             "unicode",
+	"unicode.Mark":                                "unicode",
+	"unicode.MaxASCII":                            "unicode",
+	"unicode.MaxCase":                             "unicode",
+	"unicode.MaxLatin1":                           "unicode",
+	"unicode.MaxRune":                             "unicode",
+	"unicode.Mc":                                  "unicode",
+	"unicode.Me":                                  "unicode",
+	"unicode.Meetei_Mayek":                        "unicode",
+	"unicode.Meroitic_Cursive":                    "unicode",
+	"unicode.Meroitic_Hieroglyphs":                "unicode",
+	"unicode.Miao":                                "unicode",
+	"unicode.Mn":                                  "unicode",
+	"unicode.Mongolian":                           "unicode",
+	"unicode.Myanmar":                             "unicode",
+	"unicode.N":                                   "unicode",
+	"unicode.Nd":                                  "unicode",
+	"unicode.New_Tai_Lue":                         "unicode",
+	"unicode.Nko":                                 "unicode",
+	"unicode.Nl":                                  "unicode",
+	"unicode.No":                                  "unicode",
+	"unicode.Noncharacter_Code_Point":             "unicode",
+	"unicode.Number":                              "unicode",
+	"unicode.Ogham":                               "unicode",
+	"unicode.Ol_Chiki":                            "unicode",
+	"unicode.Old_Italic":                          "unicode",
+	"unicode.Old_Persian":                         "unicode",
+	"unicode.Old_South_Arabian":                   "unicode",
+	"unicode.Old_Turkic":                          "unicode",
+	"unicode.Oriya":                               "unicode",
+	"unicode.Osmanya":                             "unicode",
+	"unicode.Other":                               "unicode",
+	"unicode.Other_Alphabetic":                    "unicode",
+	"unicode.Other_Default_Ignorable_Code_Point":  "unicode",
+	"unicode.Other_Grapheme_Extend":               "unicode",
+	"unicode.Other_ID_Continue":                   "unicode",
+	"unicode.Other_ID_Start":                      "unicode",
+	"unicode.Other_Lowercase":                     "unicode",
+	"unicode.Other_Math":                          "unicode",
+	"unicode.Other_Uppercase":                     "unicode",
+	"unicode.P":                                   "unicode",
+	"unicode.Pattern_Syntax":                      "unicode",
+	"unicode.Pattern_White_Space":                 "unicode",
+	"unicode.Pc":                                  "unicode",
+	"unicode.Pd":                                  "unicode",
+	"unicode.Pe":                                  "unicode",
+	"unicode.Pf":                                  "unicode",
+	"unicode.Phags_Pa":                            "unicode",
+	"unicode.Phoenician":                          "unicode",
+	"unicode.Pi":                                  "unicode",
+	"unicode.Po":                                  "unicode",
+	"unicode.PrintRanges":                         "unicode",
+	"unicode.Properties":                          "unicode",
+	"unicode.Ps":                                  "unicode",
+	"unicode.Punct":                               "unicode",
+	"unicode.Quotation_Mark":                      "unicode",
+	"unicode.Radical":                             "unicode",
+	"unicode.Range16":                             "unicode",
+	"unicode.Range32":                             "unicode",
+	"unicode.RangeTable":                          "unicode",
+	"unicode.Rejang":                              "unicode",
+	"unicode.ReplacementChar":                     "unicode",
+	"unicode.Runic":                               "unicode",
+	"unicode.S":                                   "unicode",
+	"unicode.STerm":                               "unicode",
+	"unicode.Samaritan":                           "unicode",
+	"unicode.Saurashtra":                          "unicode",
+	"unicode.Sc":                                  "unicode",
+	"unicode.Scripts":                             "unicode",
+	"unicode.Sharada":                             "unicode",
+	"unicode.Shavian":                             "unicode",
+	"unicode.SimpleFold":                          "unicode",
+	"unicode.Sinhala":                             "unicode",
+	"unicode.Sk":                                  "unicode",
+	"unicode.Sm":                                  "unicode",
+	"unicode.So":                                  "unicode",
+	"unicode.Soft_Dotted":                         "unicode",
+	"unicode.Sora_Sompeng":                        "unicode",
+	"unicode.Space":                               "unicode",
+	"unicode.SpecialCase":                         "unicode",
+	"unicode.Sundanese":                           "unicode",
+	"unicode.Syloti_Nagri":                        "unicode",
+	"unicode.Symbol":                              "unicode",
+	"unicode.Syriac":                              "unicode",
+	"unicode.Tagalog":                             "unicode",
+	"unicode.Tagbanwa":                            "unicode",
+	"unicode.Tai_Le":                              "unicode",
+	"unicode.Tai_Tham":                            "unicode",
+	"unicode.Tai_Viet":                            "unicode",
+	"unicode.Takri":                               "unicode",
+	"unicode.Tamil":                               "unicode",
+	"unicode.Telugu":                              "unicode",
+	"unicode.Terminal_Punctuation":                "unicode",
+	"unicode.Thaana":                              "unicode",
+	"unicode.Thai":                                "unicode",
+	"unicode.Tibetan":                             "unicode",
+	"unicode.Tifinagh":                            "unicode",
+	"unicode.Title":                               "unicode",
+	"unicode.TitleCase":                           "unicode",
+	"unicode.To":                                  "unicode",
+	"unicode.ToLower":                             "unicode",
+	"unicode.ToTitle":                             "unicode",
+	"unicode.ToUpper":                             "unicode",
+	"unicode.TurkishCase":                         "unicode",
+	"unicode.Ugaritic":                            "unicode",
+	"unicode.Unified_Ideograph":                   "unicode",
+	"unicode.Upper":                               "unicode",
+	"unicode.UpperCase":                           "unicode",
+	"unicode.UpperLower":                          "unicode",
+	"unicode.Vai":                                 "unicode",
+	"unicode.Variation_Selector":                  "unicode",
+	"unicode.Version":                             "unicode",
+	"unicode.White_Space":                         "unicode",
+	"unicode.Yi":                                  "unicode",
+	"unicode.Z":                                   "unicode",
+	"unicode.Zl":                                  "unicode",
+	"unicode.Zp":                                  "unicode",
+	"unicode.Zs":                                  "unicode",
+	"url.Error":                                   "net/url",
+	"url.EscapeError":                             "net/url",
+	"url.Parse":                                   "net/url",
+	"url.ParseQuery":                              "net/url",
+	"url.ParseRequestURI":                         "net/url",
+	"url.QueryEscape":                             "net/url",
+	"url.QueryUnescape":                           "net/url",
+	"url.URL":                                     "net/url",
+	"url.User":                                    "net/url",
+	"url.UserPassword":                            "net/url",
+	"url.Userinfo":                                "net/url",
+	"url.Values":                                  "net/url",
+	"user.Current":                                "os/user",
+	"user.Lookup":                                 "os/user",
+	"user.LookupId":                               "os/user",
+	"user.UnknownUserError":                       "os/user",
+	"user.UnknownUserIdError":                     "os/user",
+	"user.User":                                   "os/user",
+	"utf16.Decode":                                "unicode/utf16",
+	"utf16.DecodeRune":                            "unicode/utf16",
+	"utf16.Encode":                                "unicode/utf16",
+	"utf16.EncodeRune":                            "unicode/utf16",
+	"utf16.IsSurrogate":                           "unicode/utf16",
+	"utf8.DecodeLastRune":                         "unicode/utf8",
+	"utf8.DecodeLastRuneInString":                 "unicode/utf8",
+	"utf8.DecodeRune":                             "unicode/utf8",
+	"utf8.DecodeRuneInString":                     "unicode/utf8",
+	"utf8.EncodeRune":                             "unicode/utf8",
+	"utf8.FullRune":                               "unicode/utf8",
+	"utf8.FullRuneInString":                       "unicode/utf8",
+	"utf8.MaxRune":                                "unicode/utf8",
+	"utf8.RuneCount":                              "unicode/utf8",
+	"utf8.RuneCountInString":                      "unicode/utf8",
+	"utf8.RuneError":                              "unicode/utf8",
+	"utf8.RuneLen":                                "unicode/utf8",
+	"utf8.RuneSelf":                               "unicode/utf8",
+	"utf8.RuneStart":                              "unicode/utf8",
+	"utf8.UTFMax":                                 "unicode/utf8",
+	"utf8.Valid":                                  "unicode/utf8",
+	"utf8.ValidRune":                              "unicode/utf8",
+	"utf8.ValidString":                            "unicode/utf8",
+	"x509.CANotAuthorizedForThisName":             "crypto/x509",
+	"x509.CertPool":                               "crypto/x509",
+	"x509.Certificate":                            "crypto/x509",
+	"x509.CertificateInvalidError":                "crypto/x509",
+	"x509.ConstraintViolationError":               "crypto/x509",
+	"x509.CreateCertificate":                      "crypto/x509",
+	"x509.DSA":                                    "crypto/x509",
+	"x509.DSAWithSHA1":                            "crypto/x509",
+	"x509.DSAWithSHA256":                          "crypto/x509",
+	"x509.DecryptPEMBlock":                        "crypto/x509",
+	"x509.ECDSA":                                  "crypto/x509",
+	"x509.ECDSAWithSHA1":                          "crypto/x509",
+	"x509.ECDSAWithSHA256":                        "crypto/x509",
+	"x509.ECDSAWithSHA384":                        "crypto/x509",
+	"x509.ECDSAWithSHA512":                        "crypto/x509",
+	"x509.EncryptPEMBlock":                        "crypto/x509",
+	"x509.ErrUnsupportedAlgorithm":                "crypto/x509",
+	"x509.Expired":                                "crypto/x509",
+	"x509.ExtKeyUsage":                            "crypto/x509",
+	"x509.ExtKeyUsageAny":                         "crypto/x509",
+	"x509.ExtKeyUsageClientAuth":                  "crypto/x509",
+	"x509.ExtKeyUsageCodeSigning":                 "crypto/x509",
+	"x509.ExtKeyUsageEmailProtection":             "crypto/x509",
+	"x509.ExtKeyUsageIPSECEndSystem":              "crypto/x509",
+	"x509.ExtKeyUsageIPSECTunnel":                 "crypto/x509",
+	"x509.ExtKeyUsageIPSECUser":                   "crypto/x509",
+	"x509.ExtKeyUsageMicrosoftServerGatedCrypto":  "crypto/x509",
+	"x509.ExtKeyUsageNetscapeServerGatedCrypto":   "crypto/x509",
+	"x509.ExtKeyUsageOCSPSigning":                 "crypto/x509",
+	"x509.ExtKeyUsageServerAuth":                  "crypto/x509",
+	"x509.ExtKeyUsageTimeStamping":                "crypto/x509",
+	"x509.HostnameError":                          "crypto/x509",
+	"x509.IncompatibleUsage":                      "crypto/x509",
+	"x509.IncorrectPasswordError":                 "crypto/x509",
+	"x509.InvalidReason":                          "crypto/x509",
+	"x509.IsEncryptedPEMBlock":                    "crypto/x509",
+	"x509.KeyUsage":                               "crypto/x509",
+	"x509.KeyUsageCRLSign":                        "crypto/x509",
+	"x509.KeyUsageCertSign":                       "crypto/x509",
+	"x509.KeyUsageContentCommitment":              "crypto/x509",
+	"x509.KeyUsageDataEncipherment":               "crypto/x509",
+	"x509.KeyUsageDecipherOnly":                   "crypto/x509",
+	"x509.KeyUsageDigitalSignature":               "crypto/x509",
+	"x509.KeyUsageEncipherOnly":                   "crypto/x509",
+	"x509.KeyUsageKeyAgreement":                   "crypto/x509",
+	"x509.KeyUsageKeyEncipherment":                "crypto/x509",
+	"x509.MD2WithRSA":                             "crypto/x509",
+	"x509.MD5WithRSA":                             "crypto/x509",
+	"x509.MarshalECPrivateKey":                    "crypto/x509",
+	"x509.MarshalPKCS1PrivateKey":                 "crypto/x509",
+	"x509.MarshalPKIXPublicKey":                   "crypto/x509",
+	"x509.NewCertPool":                            "crypto/x509",
+	"x509.NotAuthorizedToSign":                    "crypto/x509",
+	"x509.PEMCipher":                              "crypto/x509",
+	"x509.PEMCipher3DES":                          "crypto/x509",
+	"x509.PEMCipherAES128":                        "crypto/x509",
+	"x509.PEMCipherAES192":                        "crypto/x509",
+	"x509.PEMCipherAES256":                        "crypto/x509",
+	"x509.PEMCipherDES":                           "crypto/x509",
+	"x509.ParseCRL":                               "crypto/x509",
+	"x509.ParseCertificate":                       "crypto/x509",
+	"x509.ParseCertificates":                      "crypto/x509",
+	"x509.ParseDERCRL":                            "crypto/x509",
+	"x509.ParseECPrivateKey":                      "crypto/x509",
+	"x509.ParsePKCS1PrivateKey":                   "crypto/x509",
+	"x509.ParsePKCS8PrivateKey":                   "crypto/x509",
+	"x509.ParsePKIXPublicKey":                     "crypto/x509",
+	"x509.PublicKeyAlgorithm":                     "crypto/x509",
+	"x509.RSA":                                    "crypto/x509",
+	"x509.SHA1WithRSA":                            "crypto/x509",
+	"x509.SHA256WithRSA":                          "crypto/x509",
+	"x509.SHA384WithRSA":                          "crypto/x509",
+	"x509.SHA512WithRSA":                          "crypto/x509",
+	"x509.SignatureAlgorithm":                     "crypto/x509",
+	"x509.SystemRootsError":                       "crypto/x509",
+	"x509.TooManyIntermediates":                   "crypto/x509",
+	"x509.UnhandledCriticalExtension":             "crypto/x509",
+	"x509.UnknownAuthorityError":                  "crypto/x509",
+	"x509.UnknownPublicKeyAlgorithm":              "crypto/x509",
+	"x509.UnknownSignatureAlgorithm":              "crypto/x509",
+	"x509.VerifyOptions":                          "crypto/x509",
+	"xml.Attr":                                    "encoding/xml",
+	"xml.CharData":                                "encoding/xml",
+	"xml.Comment":                                 "encoding/xml",
+	"xml.CopyToken":                               "encoding/xml",
+	"xml.Decoder":                                 "encoding/xml",
+	"xml.Directive":                               "encoding/xml",
+	"xml.Encoder":                                 "encoding/xml",
+	"xml.EndElement":                              "encoding/xml",
+	"xml.Escape":                                  "encoding/xml",
+	"xml.EscapeText":                              "encoding/xml",
+	"xml.HTMLAutoClose":                           "encoding/xml",
+	"xml.HTMLEntity":                              "encoding/xml",
+	"xml.Header":                                  "encoding/xml",
+	"xml.Marshal":                                 "encoding/xml",
+	"xml.MarshalIndent":                           "encoding/xml",
+	"xml.Marshaler":                               "encoding/xml",
+	"xml.MarshalerAttr":                           "encoding/xml",
+	"xml.Name":                                    "encoding/xml",
+	"xml.NewDecoder":                              "encoding/xml",
+	"xml.NewEncoder":                              "encoding/xml",
+	"xml.ProcInst":                                "encoding/xml",
+	"xml.StartElement":                            "encoding/xml",
+	"xml.SyntaxError":                             "encoding/xml",
+	"xml.TagPathError":                            "encoding/xml",
+	"xml.Token":                                   "encoding/xml",
+	"xml.Unmarshal":                               "encoding/xml",
+	"xml.UnmarshalError":                          "encoding/xml",
+	"xml.Unmarshaler":                             "encoding/xml",
+	"xml.UnmarshalerAttr":                         "encoding/xml",
+	"xml.UnsupportedTypeError":                    "encoding/xml",
+	"zip.Compressor":                              "archive/zip",
+	"zip.Decompressor":                            "archive/zip",
+	"zip.Deflate":                                 "archive/zip",
+	"zip.ErrAlgorithm":                            "archive/zip",
+	"zip.ErrChecksum":                             "archive/zip",
+	"zip.ErrFormat":                               "archive/zip",
+	"zip.File":                                    "archive/zip",
+	"zip.FileHeader":                              "archive/zip",
+	"zip.FileInfoHeader":                          "archive/zip",
+	"zip.NewReader":                               "archive/zip",
+	"zip.NewWriter":                               "archive/zip",
+	"zip.OpenReader":                              "archive/zip",
+	"zip.ReadCloser":                              "archive/zip",
+	"zip.Reader":                                  "archive/zip",
+	"zip.RegisterCompressor":                      "archive/zip",
+	"zip.RegisterDecompressor":                    "archive/zip",
+	"zip.Store":                                   "archive/zip",
+	"zip.Writer":                                  "archive/zip",
+	"zlib.BestCompression":                        "compress/zlib",
+	"zlib.BestSpeed":                              "compress/zlib",
+	"zlib.DefaultCompression":                     "compress/zlib",
+	"zlib.ErrChecksum":                            "compress/zlib",
+	"zlib.ErrDictionary":                          "compress/zlib",
+	"zlib.ErrHeader":                              "compress/zlib",
+	"zlib.NewReader":                              "compress/zlib",
+	"zlib.NewReaderDict":                          "compress/zlib",
+	"zlib.NewWriter":                              "compress/zlib",
+	"zlib.NewWriterLevel":                         "compress/zlib",
+	"zlib.NewWriterLevelDict":                     "compress/zlib",
+	"zlib.NoCompression":                          "compress/zlib",
+	"zlib.Writer":                                 "compress/zlib",
+}
diff --git a/third_party/go.tools/oracle/TODO b/third_party/go.tools/oracle/TODO
new file mode 100644
index 0000000..b9d4271
--- /dev/null
+++ b/third_party/go.tools/oracle/TODO
@@ -0,0 +1,99 @@
+
+
+ORACLE TODO
+===========
+
+General
+=======
+
+Refactor control flow so that each mode has a "one-shot setup" function.
+
+Use a fault-tolerant parser that can recover from bad parses.
+
+Save unsaved editor buffers into an archive and provide that to the
+tools, which should act as if they were saved.
+
+Fix: make the guessImportPath hack work with external _test.go files too.
+
+Include complete pos/end information Serial output.
+  But beware that sometimes a single token (e.g. +) is more helpful
+  than the pos/end of the containing expression (e.g. x \n + \n y).
+
+Specific queries
+================
+
+callers, callees
+
+  Use a type-based (e.g. RTA) callgraph when a callers/callees query is
+  outside the analysis scope.
+
+implements
+
+   Make it require that the selection is a type, and show only the
+   implements relation as it applies to that type.
+
+definition, referrers
+
+  Use the parser's resolver information to answer the query
+  for local names.  Only run the type checker if that fails.
+  (NB: gri's new parser won't do any resolution.)
+
+  referrers: Show the text of the matching line of code, like grep.
+
+  definition: Make it work with qualified identifiers (SelectorExpr) too.
+
+  references: Make it work on things that are implicit idents, like
+  import specs, perhaps?
+
+what
+
+  Report def/ref info if available.
+  Editors could use it to highlight all idents of the same local var.
+
+  Fix: support it in (*Oracle).Query (long-running tools).
+
+  More tests.
+
+pointsto
+
+  When invoked on a function Ident, we get an error.
+
+  When invoked on a named return parameter, we get an error.
+
+describe
+
+  When invoked on a var, we want to see the type and its methods.
+
+  Split "show type" and "describe syntax" into separate commands?
+
+peers
+
+  Permit querying from a makechan, for...range, or reflective op.
+
+  Report aliasing reflect.{Send,Recv,Close} and close() operations.
+
+New queries
+
+"updaters": show all statements that may update the selected lvalue
+  (local, global, field, etc).
+
+"creators": show all places where an object of type T is created
+  (&T{}, var t T, new(T), new(struct{array [3]T}), etc.
+  (Useful for datatypes whose zero value is not safe)
+
+
+Editor-specific
+===============
+
+Add support for "what" to .el; clean up.
+
+Emacs: use JSON to get the raw information from the oracle.  Don't
+ open an editor buffer for simpler queries, just jump to the result
+ and/or display it in the modeline.
+
+Emacs: go-root-and-paths depends on the current buffer, so be sure to
+   call it from within the source file, not the *go-oracle* buffer:
+   the user may have switched workspaces and the oracle should run in
+   the new one.
+
+Support other editors: vim, Eclipse, Sublime, etc.
diff --git a/third_party/go.tools/oracle/callees.go b/third_party/go.tools/oracle/callees.go
new file mode 100644
index 0000000..5922a04
--- /dev/null
+++ b/third_party/go.tools/oracle/callees.go
@@ -0,0 +1,162 @@
+// Copyright 2013 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 oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// Callees reports the possible callees of the function call site
+// identified by the specified source location.
+func callees(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	pkg := o.prog.Package(qpos.info.Pkg)
+	if pkg == nil {
+		return nil, fmt.Errorf("no SSA package")
+	}
+
+	// Determine the enclosing call for the specified position.
+	var e *ast.CallExpr
+	for _, n := range qpos.path {
+		if e, _ = n.(*ast.CallExpr); e != nil {
+			break
+		}
+	}
+	if e == nil {
+		return nil, fmt.Errorf("there is no function call here")
+	}
+	// TODO(adonovan): issue an error if the call is "too far
+	// away" from the current selection, as this most likely is
+	// not what the user intended.
+
+	// Reject type conversions.
+	if qpos.info.Types[e.Fun].IsType() {
+		return nil, fmt.Errorf("this is a type conversion, not a function call")
+	}
+
+	// Reject calls to built-ins.
+	if id, ok := unparen(e.Fun).(*ast.Ident); ok {
+		if b, ok := qpos.info.Uses[id].(*types.Builtin); ok {
+			return nil, fmt.Errorf("this is a call to the built-in '%s' operator", b.Name())
+		}
+	}
+
+	buildSSA(o)
+
+	// Ascertain calling function and call site.
+	callerFn := ssa.EnclosingFunction(pkg, qpos.path)
+	if callerFn == nil {
+		return nil, fmt.Errorf("no SSA function built for this location (dead code?)")
+	}
+
+	// Find the call site.
+	site, err := findCallSite(callerFn, e.Lparen)
+	if err != nil {
+		return nil, err
+	}
+
+	funcs, err := findCallees(o, site)
+	if err != nil {
+		return nil, err
+	}
+
+	return &calleesResult{
+		site:  site,
+		funcs: funcs,
+	}, nil
+}
+
+func findCallSite(fn *ssa.Function, lparen token.Pos) (ssa.CallInstruction, error) {
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			if site, ok := instr.(ssa.CallInstruction); ok && instr.Pos() == lparen {
+				return site, nil
+			}
+		}
+	}
+	return nil, fmt.Errorf("this call site is unreachable in this analysis")
+}
+
+func findCallees(o *Oracle, site ssa.CallInstruction) ([]*ssa.Function, error) {
+	// Avoid running the pointer analysis for static calls.
+	if callee := site.Common().StaticCallee(); callee != nil {
+		switch callee.String() {
+		case "runtime.SetFinalizer", "(reflect.Value).Call":
+			// The PTA treats calls to these intrinsics as dynamic.
+			// TODO(adonovan): avoid reliance on PTA internals.
+
+		default:
+			return []*ssa.Function{callee}, nil // singleton
+		}
+	}
+
+	// Dynamic call: use pointer analysis.
+	o.ptaConfig.BuildCallGraph = true
+	cg := ptrAnalysis(o).CallGraph
+	cg.DeleteSyntheticNodes()
+
+	// Find all call edges from the site.
+	n := cg.Nodes[site.Parent()]
+	if n == nil {
+		return nil, fmt.Errorf("this call site is unreachable in this analysis")
+	}
+	calleesMap := make(map[*ssa.Function]bool)
+	for _, edge := range n.Out {
+		if edge.Site == site {
+			calleesMap[edge.Callee.Func] = true
+		}
+	}
+
+	// De-duplicate and sort.
+	funcs := make([]*ssa.Function, 0, len(calleesMap))
+	for f := range calleesMap {
+		funcs = append(funcs, f)
+	}
+	sort.Sort(byFuncPos(funcs))
+	return funcs, nil
+}
+
+type calleesResult struct {
+	site  ssa.CallInstruction
+	funcs []*ssa.Function
+}
+
+func (r *calleesResult) display(printf printfFunc) {
+	if len(r.funcs) == 0 {
+		// dynamic call on a provably nil func/interface
+		printf(r.site, "%s on nil value", r.site.Common().Description())
+	} else {
+		printf(r.site, "this %s dispatches to:", r.site.Common().Description())
+		for _, callee := range r.funcs {
+			printf(callee, "\t%s", callee)
+		}
+	}
+}
+
+func (r *calleesResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	j := &serial.Callees{
+		Pos:  fset.Position(r.site.Pos()).String(),
+		Desc: r.site.Common().Description(),
+	}
+	for _, callee := range r.funcs {
+		j.Callees = append(j.Callees, &serial.CalleesItem{
+			Name: callee.String(),
+			Pos:  fset.Position(callee.Pos()).String(),
+		})
+	}
+	res.Callees = j
+}
+
+type byFuncPos []*ssa.Function
+
+func (a byFuncPos) Len() int           { return len(a) }
+func (a byFuncPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
+func (a byFuncPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
diff --git a/third_party/go.tools/oracle/callers.go b/third_party/go.tools/oracle/callers.go
new file mode 100644
index 0000000..88cca9f
--- /dev/null
+++ b/third_party/go.tools/oracle/callers.go
@@ -0,0 +1,82 @@
+// Copyright 2013 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 oracle
+
+import (
+	"fmt"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// Callers reports the possible callers of the function
+// immediately enclosing the specified source location.
+//
+func callers(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	pkg := o.prog.Package(qpos.info.Pkg)
+	if pkg == nil {
+		return nil, fmt.Errorf("no SSA package")
+	}
+	if !ssa.HasEnclosingFunction(pkg, qpos.path) {
+		return nil, fmt.Errorf("this position is not inside a function")
+	}
+
+	buildSSA(o)
+
+	target := ssa.EnclosingFunction(pkg, qpos.path)
+	if target == nil {
+		return nil, fmt.Errorf("no SSA function built for this location (dead code?)")
+	}
+
+	// Run the pointer analysis, recording each
+	// call found to originate from target.
+	o.ptaConfig.BuildCallGraph = true
+	cg := ptrAnalysis(o).CallGraph
+	cg.DeleteSyntheticNodes()
+	edges := cg.CreateNode(target).In
+	// TODO(adonovan): sort + dedup calls to ensure test determinism.
+
+	return &callersResult{
+		target:    target,
+		callgraph: cg,
+		edges:     edges,
+	}, nil
+}
+
+type callersResult struct {
+	target    *ssa.Function
+	callgraph *callgraph.Graph
+	edges     []*callgraph.Edge
+}
+
+func (r *callersResult) display(printf printfFunc) {
+	root := r.callgraph.Root
+	if r.edges == nil {
+		printf(r.target, "%s is not reachable in this program.", r.target)
+	} else {
+		printf(r.target, "%s is called from these %d sites:", r.target, len(r.edges))
+		for _, edge := range r.edges {
+			if edge.Caller == root {
+				printf(r.target, "the root of the call graph")
+			} else {
+				printf(edge, "\t%s from %s", edge.Description(), edge.Caller.Func)
+			}
+		}
+	}
+}
+
+func (r *callersResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var callers []serial.Caller
+	for _, edge := range r.edges {
+		callers = append(callers, serial.Caller{
+			Caller: edge.Caller.Func.String(),
+			Pos:    fset.Position(edge.Pos()).String(),
+			Desc:   edge.Description(),
+		})
+	}
+	res.Callers = callers
+}
diff --git a/third_party/go.tools/oracle/callgraph.go b/third_party/go.tools/oracle/callgraph.go
new file mode 100644
index 0000000..fd72d58
--- /dev/null
+++ b/third_party/go.tools/oracle/callgraph.go
@@ -0,0 +1,152 @@
+// Copyright 2013 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 oracle
+
+import (
+	"fmt"
+	"go/token"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// doCallgraph displays the entire callgraph of the current program,
+// or if a query -pos was provided, the query package.
+func doCallgraph(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	buildSSA(o)
+
+	// Run the pointer analysis and build the callgraph.
+	o.ptaConfig.BuildCallGraph = true
+	cg := ptrAnalysis(o).CallGraph
+	cg.DeleteSyntheticNodes()
+
+	var qpkg *types.Package
+	var isQueryPkg func(fn *ssa.Function) bool
+	var keep, remove, roots []*callgraph.Node
+	if qpos == nil {
+		// No -pos provided: show complete callgraph.
+		roots = append(roots, cg.Root)
+		isQueryPkg = func(fn *ssa.Function) bool { return true }
+	} else {
+		// A query -pos was provided: restrict result to
+		// functions belonging to the query package.
+		qpkg = qpos.info.Pkg
+		isQueryPkg = func(fn *ssa.Function) bool {
+			return fn.Pkg != nil && fn.Pkg.Object == qpkg
+		}
+	}
+
+	// First compute the nodes to keep and remove.
+	for fn, cgn := range cg.Nodes {
+		if isQueryPkg(fn) {
+			keep = append(keep, cgn)
+		} else {
+			remove = append(remove, cgn)
+		}
+	}
+
+	// Compact the Node.ID sequence of the kept nodes,
+	// preserving the original order.
+	sort.Sort(nodesByID(keep))
+	for i, cgn := range keep {
+		cgn.ID = i
+	}
+
+	// Compute the set of roots:
+	// in-package nodes with out-of-package callers.
+	// For determinism, roots are ordered by original Node.ID.
+	for _, cgn := range keep {
+		for _, e := range cgn.In {
+			if !isQueryPkg(e.Caller.Func) {
+				roots = append(roots, cgn)
+				break
+			}
+		}
+	}
+
+	// Finally, discard all out-of-package nodes.
+	for _, cgn := range remove {
+		cg.DeleteNode(cgn)
+	}
+
+	return &callgraphResult{qpkg, cg.Nodes, roots}, nil
+}
+
+type callgraphResult struct {
+	qpkg  *types.Package
+	nodes map[*ssa.Function]*callgraph.Node
+	roots []*callgraph.Node
+}
+
+func (r *callgraphResult) display(printf printfFunc) {
+	descr := "the entire program"
+	if r.qpkg != nil {
+		descr = fmt.Sprintf("package %s", r.qpkg.Path())
+	}
+
+	printf(nil, `
+Below is a call graph of %s.
+The numbered nodes form a spanning tree.
+Non-numbered nodes indicate back- or cross-edges to the node whose
+ number follows in parentheses.
+`, descr)
+
+	printed := make(map[*callgraph.Node]int)
+	var print func(caller *callgraph.Node, indent int)
+	print = func(caller *callgraph.Node, indent int) {
+		if num, ok := printed[caller]; !ok {
+			num = len(printed)
+			printed[caller] = num
+
+			// Sort the children into name order for deterministic* output.
+			// (*mostly: anon funcs' names are not globally unique.)
+			var funcs funcsByName
+			for callee := range callgraph.CalleesOf(caller) {
+				funcs = append(funcs, callee.Func)
+			}
+			sort.Sort(funcs)
+
+			printf(caller.Func, "%d\t%*s%s", num, 4*indent, "", caller.Func.RelString(r.qpkg))
+			for _, callee := range funcs {
+				print(r.nodes[callee], indent+1)
+			}
+		} else {
+			printf(caller.Func, "\t%*s%s (%d)", 4*indent, "", caller.Func.RelString(r.qpkg), num)
+		}
+	}
+	for _, root := range r.roots {
+		print(root, 0)
+	}
+}
+
+type nodesByID []*callgraph.Node
+
+func (s nodesByID) Len() int           { return len(s) }
+func (s nodesByID) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s nodesByID) Less(i, j int) bool { return s[i].ID < s[j].ID }
+
+type funcsByName []*ssa.Function
+
+func (s funcsByName) Len() int           { return len(s) }
+func (s funcsByName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s funcsByName) Less(i, j int) bool { return s[i].String() < s[j].String() }
+
+func (r *callgraphResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	cg := make([]serial.CallGraph, len(r.nodes))
+	for _, n := range r.nodes {
+		j := &cg[n.ID]
+		fn := n.Func
+		j.Name = fn.String()
+		j.Pos = fset.Position(fn.Pos()).String()
+		for callee := range callgraph.CalleesOf(n) {
+			j.Children = append(j.Children, callee.ID)
+		}
+		sort.Ints(j.Children)
+	}
+	res.Callgraph = cg
+}
diff --git a/third_party/go.tools/oracle/callstack.go b/third_party/go.tools/oracle/callstack.go
new file mode 100644
index 0000000..0f0f4af
--- /dev/null
+++ b/third_party/go.tools/oracle/callstack.go
@@ -0,0 +1,96 @@
+// Copyright 2013 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 oracle
+
+import (
+	"fmt"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/callgraph"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// Callstack displays an arbitrary path from a root of the callgraph
+// to the function at the current position.
+//
+// The information may be misleading in a context-insensitive
+// analysis. e.g. the call path X->Y->Z might be infeasible if Y never
+// calls Z when it is called from X.  TODO(adonovan): think about UI.
+//
+// TODO(adonovan): permit user to specify a starting point other than
+// the analysis root.
+//
+func callstack(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	pkg := o.prog.Package(qpos.info.Pkg)
+	if pkg == nil {
+		return nil, fmt.Errorf("no SSA package")
+	}
+
+	if !ssa.HasEnclosingFunction(pkg, qpos.path) {
+		return nil, fmt.Errorf("this position is not inside a function")
+	}
+
+	buildSSA(o)
+
+	target := ssa.EnclosingFunction(pkg, qpos.path)
+	if target == nil {
+		return nil, fmt.Errorf("no SSA function built for this location (dead code?)")
+	}
+
+	// Run the pointer analysis and build the complete call graph.
+	o.ptaConfig.BuildCallGraph = true
+	cg := ptrAnalysis(o).CallGraph
+	cg.DeleteSyntheticNodes()
+
+	// Search for an arbitrary path from a root to the target function.
+	isEnd := func(n *callgraph.Node) bool { return n.Func == target }
+	callpath := callgraph.PathSearch(cg.Root, isEnd)
+	if callpath != nil {
+		callpath = callpath[1:] // remove synthetic edge from <root>
+	}
+
+	return &callstackResult{
+		qpos:     qpos,
+		target:   target,
+		callpath: callpath,
+	}, nil
+}
+
+type callstackResult struct {
+	qpos     *QueryPos
+	target   *ssa.Function
+	callpath []*callgraph.Edge
+}
+
+func (r *callstackResult) display(printf printfFunc) {
+	if r.callpath != nil {
+		printf(r.qpos, "Found a call path from root to %s", r.target)
+		printf(r.target, "%s", r.target)
+		for i := len(r.callpath) - 1; i >= 0; i-- {
+			edge := r.callpath[i]
+			printf(edge, "%s from %s", edge.Description(), edge.Caller.Func)
+		}
+	} else {
+		printf(r.target, "%s is unreachable in this analysis scope", r.target)
+	}
+}
+
+func (r *callstackResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var callers []serial.Caller
+	for i := len(r.callpath) - 1; i >= 0; i-- { // (innermost first)
+		edge := r.callpath[i]
+		callers = append(callers, serial.Caller{
+			Pos:    fset.Position(edge.Pos()).String(),
+			Caller: edge.Caller.Func.String(),
+			Desc:   edge.Description(),
+		})
+	}
+	res.Callstack = &serial.CallStack{
+		Pos:     fset.Position(r.target.Pos()).String(),
+		Target:  r.target.String(),
+		Callers: callers,
+	}
+}
diff --git a/third_party/go.tools/oracle/definition.go b/third_party/go.tools/oracle/definition.go
new file mode 100644
index 0000000..3586494
--- /dev/null
+++ b/third_party/go.tools/oracle/definition.go
@@ -0,0 +1,53 @@
+// Copyright 2013 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 oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// definition reports the location of the definition of an identifier.
+//
+// TODO(adonovan): opt: for intra-file references, the parser's
+// resolution might be enough; we should start with that.
+//
+func definition(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	id, _ := qpos.path[0].(*ast.Ident)
+	if id == nil {
+		return nil, fmt.Errorf("no identifier here")
+	}
+
+	obj := qpos.info.ObjectOf(id)
+	if obj == nil {
+		// Happens for y in "switch y := x.(type)", but I think that's all.
+		return nil, fmt.Errorf("no object for identifier")
+	}
+
+	return &definitionResult{qpos, obj}, nil
+}
+
+type definitionResult struct {
+	qpos *QueryPos
+	obj  types.Object // object it denotes
+}
+
+func (r *definitionResult) display(printf printfFunc) {
+	printf(r.obj, "defined here as %s", r.qpos.ObjectString(r.obj))
+}
+
+func (r *definitionResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	definition := &serial.Definition{
+		Desc: r.obj.String(),
+	}
+	if pos := r.obj.Pos(); pos != token.NoPos { // Package objects have no Pos()
+		definition.ObjPos = fset.Position(pos).String()
+	}
+	res.Definition = definition
+}
diff --git a/third_party/go.tools/oracle/describe.go b/third_party/go.tools/oracle/describe.go
new file mode 100644
index 0000000..fc89b20
--- /dev/null
+++ b/third_party/go.tools/oracle/describe.go
@@ -0,0 +1,746 @@
+// Copyright 2013 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 oracle
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"log"
+	"os"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// describe describes the syntax node denoted by the query position,
+// including:
+// - its syntactic category
+// - the definition of its referent (for identifiers) [now redundant]
+// - its type and method set (for an expression or type expression)
+//
+func describe(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	if false { // debugging
+		fprintf(os.Stderr, o.fset, qpos.path[0], "you selected: %s %s",
+			astutil.NodeDescription(qpos.path[0]), pathToString(qpos.path))
+	}
+
+	path, action := findInterestingNode(qpos.info, qpos.path)
+	switch action {
+	case actionExpr:
+		return describeValue(o, qpos, path)
+
+	case actionType:
+		return describeType(o, qpos, path)
+
+	case actionPackage:
+		return describePackage(o, qpos, path)
+
+	case actionStmt:
+		return describeStmt(o, qpos, path)
+
+	case actionUnknown:
+		return &describeUnknownResult{path[0]}, nil
+
+	default:
+		panic(action) // unreachable
+	}
+}
+
+type describeUnknownResult struct {
+	node ast.Node
+}
+
+func (r *describeUnknownResult) display(printf printfFunc) {
+	// Nothing much to say about misc syntax.
+	printf(r.node, "%s", astutil.NodeDescription(r.node))
+}
+
+func (r *describeUnknownResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Describe = &serial.Describe{
+		Desc: astutil.NodeDescription(r.node),
+		Pos:  fset.Position(r.node.Pos()).String(),
+	}
+}
+
+type action int
+
+const (
+	actionUnknown action = iota // None of the below
+	actionExpr                  // FuncDecl, true Expr or Ident(types.{Const,Var})
+	actionType                  // type Expr or Ident(types.TypeName).
+	actionStmt                  // Stmt or Ident(types.Label)
+	actionPackage               // Ident(types.Package) or ImportSpec
+)
+
+// findInterestingNode classifies the syntax node denoted by path as one of:
+//    - an expression, part of an expression or a reference to a constant
+//      or variable;
+//    - a type, part of a type, or a reference to a named type;
+//    - a statement, part of a statement, or a label referring to a statement;
+//    - part of a package declaration or import spec.
+//    - none of the above.
+// and returns the most "interesting" associated node, which may be
+// the same node, an ancestor or a descendent.
+//
+func findInterestingNode(pkginfo *loader.PackageInfo, path []ast.Node) ([]ast.Node, action) {
+	// TODO(adonovan): integrate with go/types/stdlib_test.go and
+	// apply this to every AST node we can find to make sure it
+	// doesn't crash.
+
+	// TODO(adonovan): audit for ParenExpr safety, esp. since we
+	// traverse up and down.
+
+	// TODO(adonovan): if the users selects the "." in
+	// "fmt.Fprintf()", they'll get an ambiguous selection error;
+	// we won't even reach here.  Can we do better?
+
+	// TODO(adonovan): describing a field within 'type T struct {...}'
+	// describes the (anonymous) struct type and concludes "no methods".
+	// We should ascend to the enclosing type decl, if any.
+
+	for len(path) > 0 {
+		switch n := path[0].(type) {
+		case *ast.GenDecl:
+			if len(n.Specs) == 1 {
+				// Descend to sole {Import,Type,Value}Spec child.
+				path = append([]ast.Node{n.Specs[0]}, path...)
+				continue
+			}
+			return path, actionUnknown // uninteresting
+
+		case *ast.FuncDecl:
+			// Descend to function name.
+			path = append([]ast.Node{n.Name}, path...)
+			continue
+
+		case *ast.ImportSpec:
+			return path, actionPackage
+
+		case *ast.ValueSpec:
+			if len(n.Names) == 1 {
+				// Descend to sole Ident child.
+				path = append([]ast.Node{n.Names[0]}, path...)
+				continue
+			}
+			return path, actionUnknown // uninteresting
+
+		case *ast.TypeSpec:
+			// Descend to type name.
+			path = append([]ast.Node{n.Name}, path...)
+			continue
+
+		case ast.Stmt:
+			return path, actionStmt
+
+		case *ast.ArrayType,
+			*ast.StructType,
+			*ast.FuncType,
+			*ast.InterfaceType,
+			*ast.MapType,
+			*ast.ChanType:
+			return path, actionType
+
+		case *ast.Comment, *ast.CommentGroup, *ast.File, *ast.KeyValueExpr, *ast.CommClause:
+			return path, actionUnknown // uninteresting
+
+		case *ast.Ellipsis:
+			// Continue to enclosing node.
+			// e.g. [...]T in ArrayType
+			//      f(x...) in CallExpr
+			//      f(x...T) in FuncType
+
+		case *ast.Field:
+			// TODO(adonovan): this needs more thought,
+			// since fields can be so many things.
+			if len(n.Names) == 1 {
+				// Descend to sole Ident child.
+				path = append([]ast.Node{n.Names[0]}, path...)
+				continue
+			}
+			// Zero names (e.g. anon field in struct)
+			// or multiple field or param names:
+			// continue to enclosing field list.
+
+		case *ast.FieldList:
+			// Continue to enclosing node:
+			// {Struct,Func,Interface}Type or FuncDecl.
+
+		case *ast.BasicLit:
+			if _, ok := path[1].(*ast.ImportSpec); ok {
+				return path[1:], actionPackage
+			}
+			return path, actionExpr
+
+		case *ast.SelectorExpr:
+			// TODO(adonovan): use Selections info directly.
+			if pkginfo.Uses[n.Sel] == nil {
+				// TODO(adonovan): is this reachable?
+				return path, actionUnknown
+			}
+			// Descend to .Sel child.
+			path = append([]ast.Node{n.Sel}, path...)
+			continue
+
+		case *ast.Ident:
+			switch pkginfo.ObjectOf(n).(type) {
+			case *types.PkgName:
+				return path, actionPackage
+
+			case *types.Const:
+				return path, actionExpr
+
+			case *types.Label:
+				return path, actionStmt
+
+			case *types.TypeName:
+				return path, actionType
+
+			case *types.Var:
+				// For x in 'struct {x T}', return struct type, for now.
+				if _, ok := path[1].(*ast.Field); ok {
+					_ = path[2].(*ast.FieldList) // assertion
+					if _, ok := path[3].(*ast.StructType); ok {
+						return path[3:], actionType
+					}
+				}
+				return path, actionExpr
+
+			case *types.Func:
+				// For f in 'interface {f()}', return the interface type, for now.
+				if _, ok := path[1].(*ast.Field); ok {
+					_ = path[2].(*ast.FieldList) // assertion
+					if _, ok := path[3].(*ast.InterfaceType); ok {
+						return path[3:], actionType
+					}
+				}
+				return path, actionExpr
+
+			case *types.Builtin:
+				// For reference to built-in function, return enclosing call.
+				path = path[1:] // ascend to enclosing function call
+				continue
+
+			case *types.Nil:
+				return path, actionExpr
+			}
+
+			// No object.
+			switch path[1].(type) {
+			case *ast.SelectorExpr:
+				// Return enclosing selector expression.
+				return path[1:], actionExpr
+
+			case *ast.Field:
+				// TODO(adonovan): test this.
+				// e.g. all f in:
+				//  struct { f, g int }
+				//  interface { f() }
+				//  func (f T) method(f, g int) (f, g bool)
+				//
+				// switch path[3].(type) {
+				// case *ast.FuncDecl:
+				// case *ast.StructType:
+				// case *ast.InterfaceType:
+				// }
+				//
+				// return path[1:], actionExpr
+				//
+				// Unclear what to do with these.
+				// Struct.Fields             -- field
+				// Interface.Methods         -- field
+				// FuncType.{Params.Results} -- actionExpr
+				// FuncDecl.Recv             -- actionExpr
+
+			case *ast.File:
+				// 'package foo'
+				return path, actionPackage
+
+			case *ast.ImportSpec:
+				// TODO(adonovan): fix: why no package object? go/types bug?
+				return path[1:], actionPackage
+
+			default:
+				// e.g. blank identifier
+				// or y in "switch y := x.(type)"
+				// or code in a _test.go file that's not part of the package.
+				log.Printf("unknown reference %s in %T\n", n, path[1])
+				return path, actionUnknown
+			}
+
+		case *ast.StarExpr:
+			if pkginfo.Types[n].IsType() {
+				return path, actionType
+			}
+			return path, actionExpr
+
+		case ast.Expr:
+			// All Expr but {BasicLit,Ident,StarExpr} are
+			// "true" expressions that evaluate to a value.
+			return path, actionExpr
+		}
+
+		// Ascend to parent.
+		path = path[1:]
+	}
+
+	return nil, actionUnknown // unreachable
+}
+
+func describeValue(o *Oracle, qpos *QueryPos, path []ast.Node) (*describeValueResult, error) {
+	var expr ast.Expr
+	var obj types.Object
+	switch n := path[0].(type) {
+	case *ast.ValueSpec:
+		// ambiguous ValueSpec containing multiple names
+		return nil, fmt.Errorf("multiple value specification")
+	case *ast.Ident:
+		obj = qpos.info.ObjectOf(n)
+		expr = n
+	case ast.Expr:
+		expr = n
+	default:
+		// TODO(adonovan): is this reachable?
+		return nil, fmt.Errorf("unexpected AST for expr: %T", n)
+	}
+
+	typ := qpos.info.TypeOf(expr)
+	constVal := qpos.info.Types[expr].Value
+
+	return &describeValueResult{
+		qpos:     qpos,
+		expr:     expr,
+		typ:      typ,
+		constVal: constVal,
+		obj:      obj,
+	}, nil
+}
+
+type describeValueResult struct {
+	qpos     *QueryPos
+	expr     ast.Expr     // query node
+	typ      types.Type   // type of expression
+	constVal exact.Value  // value of expression, if constant
+	obj      types.Object // var/func/const object, if expr was Ident
+}
+
+func (r *describeValueResult) display(printf printfFunc) {
+	var prefix, suffix string
+	if r.constVal != nil {
+		suffix = fmt.Sprintf(" of constant value %s", r.constVal)
+	}
+	switch obj := r.obj.(type) {
+	case *types.Func:
+		if recv := obj.Type().(*types.Signature).Recv(); recv != nil {
+			if _, ok := recv.Type().Underlying().(*types.Interface); ok {
+				prefix = "interface method "
+			} else {
+				prefix = "method "
+			}
+		}
+	}
+
+	// Describe the expression.
+	if r.obj != nil {
+		if r.obj.Pos() == r.expr.Pos() {
+			// defining ident
+			printf(r.expr, "definition of %s%s%s", prefix, r.qpos.ObjectString(r.obj), suffix)
+		} else {
+			// referring ident
+			printf(r.expr, "reference to %s%s%s", prefix, r.qpos.ObjectString(r.obj), suffix)
+			if def := r.obj.Pos(); def != token.NoPos {
+				printf(def, "defined here")
+			}
+		}
+	} else {
+		desc := astutil.NodeDescription(r.expr)
+		if suffix != "" {
+			// constant expression
+			printf(r.expr, "%s%s", desc, suffix)
+		} else {
+			// non-constant expression
+			printf(r.expr, "%s of type %s", desc, r.qpos.TypeString(r.typ))
+		}
+	}
+}
+
+func (r *describeValueResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var value, objpos string
+	if r.constVal != nil {
+		value = r.constVal.String()
+	}
+	if r.obj != nil {
+		objpos = fset.Position(r.obj.Pos()).String()
+	}
+
+	res.Describe = &serial.Describe{
+		Desc:   astutil.NodeDescription(r.expr),
+		Pos:    fset.Position(r.expr.Pos()).String(),
+		Detail: "value",
+		Value: &serial.DescribeValue{
+			Type:   r.qpos.TypeString(r.typ),
+			Value:  value,
+			ObjPos: objpos,
+		},
+	}
+}
+
+// ---- TYPE ------------------------------------------------------------
+
+func describeType(o *Oracle, qpos *QueryPos, path []ast.Node) (*describeTypeResult, error) {
+	var description string
+	var t types.Type
+	switch n := path[0].(type) {
+	case *ast.Ident:
+		t = qpos.info.TypeOf(n)
+		switch t := t.(type) {
+		case *types.Basic:
+			description = "reference to built-in "
+
+		case *types.Named:
+			isDef := t.Obj().Pos() == n.Pos() // see caveats at isDef above
+			if isDef {
+				description = "definition of "
+			} else {
+				description = "reference to "
+			}
+		}
+
+	case ast.Expr:
+		t = qpos.info.TypeOf(n)
+
+	default:
+		// Unreachable?
+		return nil, fmt.Errorf("unexpected AST for type: %T", n)
+	}
+
+	description = description + "type " + qpos.TypeString(t)
+
+	// Show sizes for structs and named types (it's fairly obvious for others).
+	switch t.(type) {
+	case *types.Named, *types.Struct:
+		// TODO(adonovan): use o.imp.Config().TypeChecker.Sizes when
+		// we add the Config() method (needs some thought).
+		szs := types.StdSizes{8, 8}
+		description = fmt.Sprintf("%s (size %d, align %d)", description,
+			szs.Sizeof(t), szs.Alignof(t))
+	}
+
+	return &describeTypeResult{
+		qpos:        qpos,
+		node:        path[0],
+		description: description,
+		typ:         t,
+		methods:     accessibleMethods(t, qpos.info.Pkg),
+	}, nil
+}
+
+type describeTypeResult struct {
+	qpos        *QueryPos
+	node        ast.Node
+	description string
+	typ         types.Type
+	methods     []*types.Selection
+}
+
+func (r *describeTypeResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+
+	// Show the underlying type for a reference to a named type.
+	if nt, ok := r.typ.(*types.Named); ok && r.node.Pos() != nt.Obj().Pos() {
+		printf(nt.Obj(), "defined as %s", r.qpos.TypeString(nt.Underlying()))
+	}
+
+	// Print the method set, if the type kind is capable of bearing methods.
+	switch r.typ.(type) {
+	case *types.Interface, *types.Struct, *types.Named:
+		if len(r.methods) > 0 {
+			printf(r.node, "Method set:")
+			for _, meth := range r.methods {
+				// TODO(adonovan): print these relative
+				// to the owning package, not the
+				// query package.
+				printf(meth.Obj(), "\t%s", r.qpos.SelectionString(meth))
+			}
+		} else {
+			printf(r.node, "No methods.")
+		}
+	}
+}
+
+func (r *describeTypeResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var namePos, nameDef string
+	if nt, ok := r.typ.(*types.Named); ok {
+		namePos = fset.Position(nt.Obj().Pos()).String()
+		nameDef = nt.Underlying().String()
+	}
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "type",
+		Type: &serial.DescribeType{
+			Type:    r.qpos.TypeString(r.typ),
+			NamePos: namePos,
+			NameDef: nameDef,
+			Methods: methodsToSerial(r.qpos.info.Pkg, r.methods, fset),
+		},
+	}
+}
+
+// ---- PACKAGE ------------------------------------------------------------
+
+func describePackage(o *Oracle, qpos *QueryPos, path []ast.Node) (*describePackageResult, error) {
+	var description string
+	var pkg *types.Package
+	switch n := path[0].(type) {
+	case *ast.ImportSpec:
+		var pkgname *types.PkgName
+		if n.Name != nil {
+			pkgname = qpos.info.Defs[n.Name].(*types.PkgName)
+		} else if p := qpos.info.Implicits[n]; p != nil {
+			pkgname = p.(*types.PkgName)
+		}
+		pkg = pkgname.Imported()
+		description = fmt.Sprintf("import of package %q", pkg.Path())
+
+	case *ast.Ident:
+		if _, isDef := path[1].(*ast.File); isDef {
+			// e.g. package id
+			pkg = qpos.info.Pkg
+			description = fmt.Sprintf("definition of package %q", pkg.Path())
+		} else {
+			// e.g. import id "..."
+			//  or  id.F()
+			pkg = qpos.info.ObjectOf(n).(*types.PkgName).Imported()
+			description = fmt.Sprintf("reference to package %q", pkg.Path())
+		}
+
+	default:
+		// Unreachable?
+		return nil, fmt.Errorf("unexpected AST for package: %T", n)
+	}
+
+	var members []*describeMember
+	// NB: "unsafe" has no types.Package
+	if pkg != nil {
+		// Enumerate the accessible package members
+		// in lexicographic order.
+		for _, name := range pkg.Scope().Names() {
+			if pkg == qpos.info.Pkg || ast.IsExported(name) {
+				mem := pkg.Scope().Lookup(name)
+				var methods []*types.Selection
+				if mem, ok := mem.(*types.TypeName); ok {
+					methods = accessibleMethods(mem.Type(), qpos.info.Pkg)
+				}
+				members = append(members, &describeMember{
+					mem,
+					methods,
+				})
+
+			}
+		}
+	}
+
+	return &describePackageResult{o.fset, path[0], description, pkg, members}, nil
+}
+
+type describePackageResult struct {
+	fset        *token.FileSet
+	node        ast.Node
+	description string
+	pkg         *types.Package
+	members     []*describeMember // in lexicographic name order
+}
+
+type describeMember struct {
+	obj     types.Object
+	methods []*types.Selection // in types.MethodSet order
+}
+
+func (r *describePackageResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+
+	// Compute max width of name "column".
+	maxname := 0
+	for _, mem := range r.members {
+		if l := len(mem.obj.Name()); l > maxname {
+			maxname = l
+		}
+	}
+
+	for _, mem := range r.members {
+		printf(mem.obj, "\t%s", formatMember(mem.obj, maxname))
+		for _, meth := range mem.methods {
+			printf(meth.Obj(), "\t\t%s", types.SelectionString(r.pkg, meth))
+		}
+	}
+}
+
+func formatMember(obj types.Object, maxname int) string {
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "%-5s %-*s", tokenOf(obj), maxname, obj.Name())
+	switch obj := obj.(type) {
+	case *types.Const:
+		fmt.Fprintf(&buf, " %s = %s", types.TypeString(obj.Pkg(), obj.Type()), obj.Val().String())
+
+	case *types.Func:
+		fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type()))
+
+	case *types.TypeName:
+		// Abbreviate long aggregate type names.
+		var abbrev string
+		switch t := obj.Type().Underlying().(type) {
+		case *types.Interface:
+			if t.NumMethods() > 1 {
+				abbrev = "interface{...}"
+			}
+		case *types.Struct:
+			if t.NumFields() > 1 {
+				abbrev = "struct{...}"
+			}
+		}
+		if abbrev == "" {
+			fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type().Underlying()))
+		} else {
+			fmt.Fprintf(&buf, " %s", abbrev)
+		}
+
+	case *types.Var:
+		fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type()))
+	}
+	return buf.String()
+}
+
+func (r *describePackageResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var members []*serial.DescribeMember
+	for _, mem := range r.members {
+		typ := mem.obj.Type()
+		var val string
+		switch mem := mem.obj.(type) {
+		case *types.Const:
+			val = mem.Val().String()
+		case *types.TypeName:
+			typ = typ.Underlying()
+		}
+		members = append(members, &serial.DescribeMember{
+			Name:    mem.obj.Name(),
+			Type:    typ.String(),
+			Value:   val,
+			Pos:     fset.Position(mem.obj.Pos()).String(),
+			Kind:    tokenOf(mem.obj),
+			Methods: methodsToSerial(r.pkg, mem.methods, fset),
+		})
+	}
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "package",
+		Package: &serial.DescribePackage{
+			Path:    r.pkg.Path(),
+			Members: members,
+		},
+	}
+}
+
+func tokenOf(o types.Object) string {
+	switch o.(type) {
+	case *types.Func:
+		return "func"
+	case *types.Var:
+		return "var"
+	case *types.TypeName:
+		return "type"
+	case *types.Const:
+		return "const"
+	case *types.PkgName:
+		return "package"
+	}
+	panic(o)
+}
+
+// ---- STATEMENT ------------------------------------------------------------
+
+func describeStmt(o *Oracle, qpos *QueryPos, path []ast.Node) (*describeStmtResult, error) {
+	var description string
+	switch n := path[0].(type) {
+	case *ast.Ident:
+		if qpos.info.Defs[n] != nil {
+			description = "labelled statement"
+		} else {
+			description = "reference to labelled statement"
+		}
+
+	default:
+		// Nothing much to say about statements.
+		description = astutil.NodeDescription(n)
+	}
+	return &describeStmtResult{o.fset, path[0], description}, nil
+}
+
+type describeStmtResult struct {
+	fset        *token.FileSet
+	node        ast.Node
+	description string
+}
+
+func (r *describeStmtResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+}
+
+func (r *describeStmtResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "unknown",
+	}
+}
+
+// ------------------- Utilities -------------------
+
+// pathToString returns a string containing the concrete types of the
+// nodes in path.
+func pathToString(path []ast.Node) string {
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "[")
+	for i, n := range path {
+		if i > 0 {
+			fmt.Fprint(&buf, " ")
+		}
+		fmt.Fprint(&buf, strings.TrimPrefix(fmt.Sprintf("%T", n), "*ast."))
+	}
+	fmt.Fprint(&buf, "]")
+	return buf.String()
+}
+
+func accessibleMethods(t types.Type, from *types.Package) []*types.Selection {
+	var methods []*types.Selection
+	for _, meth := range typeutil.IntuitiveMethodSet(t, nil) {
+		if isAccessibleFrom(meth.Obj(), from) {
+			methods = append(methods, meth)
+		}
+	}
+	return methods
+}
+
+func isAccessibleFrom(obj types.Object, pkg *types.Package) bool {
+	return ast.IsExported(obj.Name()) || obj.Pkg() == pkg
+}
+
+func methodsToSerial(this *types.Package, methods []*types.Selection, fset *token.FileSet) []serial.DescribeMethod {
+	var jmethods []serial.DescribeMethod
+	for _, meth := range methods {
+		jmethods = append(jmethods, serial.DescribeMethod{
+			Name: types.SelectionString(this, meth),
+			Pos:  fset.Position(meth.Obj().Pos()).String(),
+		})
+	}
+	return jmethods
+}
diff --git a/third_party/go.tools/oracle/freevars.go b/third_party/go.tools/oracle/freevars.go
new file mode 100644
index 0000000..c037811
--- /dev/null
+++ b/third_party/go.tools/oracle/freevars.go
@@ -0,0 +1,200 @@
+// Copyright 2013 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 oracle
+
+import (
+	"bytes"
+	"go/ast"
+	"go/printer"
+	"go/token"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// freevars displays the lexical (not package-level) free variables of
+// the selection.
+//
+// It treats A.B.C as a separate variable from A to reveal the parts
+// of an aggregate type that are actually needed.
+// This aids refactoring.
+//
+// TODO(adonovan): optionally display the free references to
+// file/package scope objects, and to objects from other packages.
+// Depending on where the resulting function abstraction will go,
+// these might be interesting.  Perhaps group the results into three
+// bands.
+//
+func freevars(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	file := qpos.path[len(qpos.path)-1] // the enclosing file
+	fileScope := qpos.info.Scopes[file]
+	pkgScope := fileScope.Parent()
+
+	// The id and sel functions return non-nil if they denote an
+	// object o or selection o.x.y that is referenced by the
+	// selection but defined neither within the selection nor at
+	// file scope, i.e. it is in the lexical environment.
+	var id func(n *ast.Ident) types.Object
+	var sel func(n *ast.SelectorExpr) types.Object
+
+	sel = func(n *ast.SelectorExpr) types.Object {
+		switch x := unparen(n.X).(type) {
+		case *ast.SelectorExpr:
+			return sel(x)
+		case *ast.Ident:
+			return id(x)
+		}
+		return nil
+	}
+
+	id = func(n *ast.Ident) types.Object {
+		obj := qpos.info.Uses[n]
+		if obj == nil {
+			return nil // not a reference
+		}
+		if _, ok := obj.(*types.PkgName); ok {
+			return nil // imported package
+		}
+		if !(file.Pos() <= obj.Pos() && obj.Pos() <= file.End()) {
+			return nil // not defined in this file
+		}
+		scope := obj.Parent()
+		if scope == nil {
+			return nil // e.g. interface method, struct field
+		}
+		if scope == fileScope || scope == pkgScope {
+			return nil // defined at file or package scope
+		}
+		if qpos.start <= obj.Pos() && obj.Pos() <= qpos.end {
+			return nil // defined within selection => not free
+		}
+		return obj
+	}
+
+	// Maps each reference that is free in the selection
+	// to the object it refers to.
+	// The map de-duplicates repeated references.
+	refsMap := make(map[string]freevarsRef)
+
+	// Visit all the identifiers in the selected ASTs.
+	ast.Inspect(qpos.path[0], func(n ast.Node) bool {
+		if n == nil {
+			return true // popping DFS stack
+		}
+
+		// Is this node contained within the selection?
+		// (freevars permits inexact selections,
+		// like two stmts in a block.)
+		if qpos.start <= n.Pos() && n.End() <= qpos.end {
+			var obj types.Object
+			var prune bool
+			switch n := n.(type) {
+			case *ast.Ident:
+				obj = id(n)
+
+			case *ast.SelectorExpr:
+				obj = sel(n)
+				prune = true
+			}
+
+			if obj != nil {
+				var kind string
+				switch obj.(type) {
+				case *types.Var:
+					kind = "var"
+				case *types.Func:
+					kind = "func"
+				case *types.TypeName:
+					kind = "type"
+				case *types.Const:
+					kind = "const"
+				case *types.Label:
+					kind = "label"
+				default:
+					panic(obj)
+				}
+
+				typ := qpos.info.TypeOf(n.(ast.Expr))
+				ref := freevarsRef{kind, printNode(o.fset, n), typ, obj}
+				refsMap[ref.ref] = ref
+
+				if prune {
+					return false // don't descend
+				}
+			}
+		}
+
+		return true // descend
+	})
+
+	refs := make([]freevarsRef, 0, len(refsMap))
+	for _, ref := range refsMap {
+		refs = append(refs, ref)
+	}
+	sort.Sort(byRef(refs))
+
+	return &freevarsResult{
+		qpos: qpos,
+		refs: refs,
+	}, nil
+}
+
+type freevarsResult struct {
+	qpos *QueryPos
+	refs []freevarsRef
+}
+
+type freevarsRef struct {
+	kind string
+	ref  string
+	typ  types.Type
+	obj  types.Object
+}
+
+func (r *freevarsResult) display(printf printfFunc) {
+	if len(r.refs) == 0 {
+		printf(r.qpos, "No free identifiers.")
+	} else {
+		printf(r.qpos, "Free identifiers:")
+		for _, ref := range r.refs {
+			// Avoid printing "type T T".
+			var typstr string
+			if ref.kind != "type" {
+				typstr = " " + types.TypeString(r.qpos.info.Pkg, ref.typ)
+			}
+			printf(ref.obj, "%s %s%s", ref.kind, ref.ref, typstr)
+		}
+	}
+}
+
+func (r *freevarsResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var refs []*serial.FreeVar
+	for _, ref := range r.refs {
+		refs = append(refs,
+			&serial.FreeVar{
+				Pos:  fset.Position(ref.obj.Pos()).String(),
+				Kind: ref.kind,
+				Ref:  ref.ref,
+				Type: ref.typ.String(),
+			})
+	}
+	res.Freevars = refs
+}
+
+// -------- utils --------
+
+type byRef []freevarsRef
+
+func (p byRef) Len() int           { return len(p) }
+func (p byRef) Less(i, j int) bool { return p[i].ref < p[j].ref }
+func (p byRef) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// printNode returns the pretty-printed syntax of n.
+func printNode(fset *token.FileSet, n ast.Node) string {
+	var buf bytes.Buffer
+	printer.Fprint(&buf, fset, n)
+	return buf.String()
+}
diff --git a/third_party/go.tools/oracle/implements.go b/third_party/go.tools/oracle/implements.go
new file mode 100644
index 0000000..be7cc49
--- /dev/null
+++ b/third_party/go.tools/oracle/implements.go
@@ -0,0 +1,203 @@
+// Copyright 2013 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 oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"reflect"
+	"sort"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// Implements displays the "implements" relation as it pertains to the
+// selected type.
+//
+func implements(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	// Find the selected type.
+	// TODO(adonovan): fix: make it work on qualified Idents too.
+	path, action := findInterestingNode(qpos.info, qpos.path)
+	if action != actionType {
+		return nil, fmt.Errorf("no type here")
+	}
+	T := qpos.info.TypeOf(path[0].(ast.Expr))
+	if T == nil {
+		return nil, fmt.Errorf("no type here")
+	}
+
+	// Find all named types, even local types (which can have
+	// methods via promotion) and the built-in "error".
+	//
+	// TODO(adonovan): include all packages in PTA scope too?
+	// i.e. don't reduceScope?
+	//
+	var allNamed []types.Type
+	for _, info := range o.typeInfo {
+		for _, obj := range info.Defs {
+			if obj, ok := obj.(*types.TypeName); ok {
+				allNamed = append(allNamed, obj.Type())
+			}
+		}
+	}
+	allNamed = append(allNamed, types.Universe.Lookup("error").Type())
+
+	var msets types.MethodSetCache
+
+	// Test each named type.
+	var to, from, fromPtr []types.Type
+	for _, U := range allNamed {
+		if isInterface(T) {
+			if msets.MethodSet(T).Len() == 0 {
+				continue // empty interface
+			}
+			if isInterface(U) {
+				if msets.MethodSet(U).Len() == 0 {
+					continue // empty interface
+				}
+
+				// T interface, U interface
+				if !types.Identical(T, U) {
+					if types.AssignableTo(U, T) {
+						to = append(to, U)
+					}
+					if types.AssignableTo(T, U) {
+						from = append(from, U)
+					}
+				}
+			} else {
+				// T interface, U concrete
+				if types.AssignableTo(U, T) {
+					to = append(to, U)
+				} else if pU := types.NewPointer(U); types.AssignableTo(pU, T) {
+					to = append(to, pU)
+				}
+			}
+		} else if isInterface(U) {
+			if msets.MethodSet(U).Len() == 0 {
+				continue // empty interface
+			}
+
+			// T concrete, U interface
+			if types.AssignableTo(T, U) {
+				from = append(from, U)
+			} else if pT := types.NewPointer(T); types.AssignableTo(pT, U) {
+				fromPtr = append(fromPtr, U)
+			}
+		}
+	}
+
+	var pos interface{} = qpos
+	if nt, ok := deref(T).(*types.Named); ok {
+		pos = nt.Obj()
+	}
+
+	// Sort types (arbitrarily) to ensure test determinism.
+	sort.Sort(typesByString(to))
+	sort.Sort(typesByString(from))
+	sort.Sort(typesByString(fromPtr))
+
+	return &implementsResult{T, pos, to, from, fromPtr}, nil
+}
+
+type implementsResult struct {
+	t       types.Type   // queried type (not necessarily named)
+	pos     interface{}  // pos of t (*types.Name or *QueryPos)
+	to      []types.Type // named or ptr-to-named types assignable to interface T
+	from    []types.Type // named interfaces assignable from T
+	fromPtr []types.Type // named interfaces assignable only from *T
+}
+
+func (r *implementsResult) display(printf printfFunc) {
+	if isInterface(r.t) {
+		if types.NewMethodSet(r.t).Len() == 0 { // TODO(adonovan): cache mset
+			printf(r.pos, "empty interface type %s", r.t)
+			return
+		}
+
+		printf(r.pos, "interface type %s", r.t)
+		// Show concrete types first; use two passes.
+		for _, sub := range r.to {
+			if !isInterface(sub) {
+				printf(deref(sub).(*types.Named).Obj(), "\tis implemented by %s type %s",
+					typeKind(sub), sub)
+			}
+		}
+		for _, sub := range r.to {
+			if isInterface(sub) {
+				printf(deref(sub).(*types.Named).Obj(), "\tis implemented by %s type %s", typeKind(sub), sub)
+			}
+		}
+
+		for _, super := range r.from {
+			printf(super.(*types.Named).Obj(), "\timplements %s", super)
+		}
+	} else {
+		if r.from != nil {
+			printf(r.pos, "%s type %s", typeKind(r.t), r.t)
+			for _, super := range r.from {
+				printf(super.(*types.Named).Obj(), "\timplements %s", super)
+			}
+		}
+		if r.fromPtr != nil {
+			printf(r.pos, "pointer type *%s", r.t)
+			for _, psuper := range r.fromPtr {
+				printf(psuper.(*types.Named).Obj(), "\timplements %s", psuper)
+			}
+		} else if r.from == nil {
+			printf(r.pos, "%s type %s implements only interface{}", typeKind(r.t), r.t)
+		}
+	}
+}
+
+func (r *implementsResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Implements = &serial.Implements{
+		T:                 makeImplementsType(r.t, fset),
+		AssignableTo:      makeImplementsTypes(r.to, fset),
+		AssignableFrom:    makeImplementsTypes(r.from, fset),
+		AssignableFromPtr: makeImplementsTypes(r.fromPtr, fset),
+	}
+}
+
+func makeImplementsTypes(tt []types.Type, fset *token.FileSet) []serial.ImplementsType {
+	var r []serial.ImplementsType
+	for _, t := range tt {
+		r = append(r, makeImplementsType(t, fset))
+	}
+	return r
+}
+
+func makeImplementsType(T types.Type, fset *token.FileSet) serial.ImplementsType {
+	var pos token.Pos
+	if nt, ok := deref(T).(*types.Named); ok { // implementsResult.t may be non-named
+		pos = nt.Obj().Pos()
+	}
+	return serial.ImplementsType{
+		Name: T.String(),
+		Pos:  fset.Position(pos).String(),
+		Kind: typeKind(T),
+	}
+}
+
+// typeKind returns a string describing the underlying kind of type,
+// e.g. "slice", "array", "struct".
+func typeKind(T types.Type) string {
+	s := reflect.TypeOf(T.Underlying()).String()
+	return strings.ToLower(strings.TrimPrefix(s, "*types."))
+}
+
+func isInterface(T types.Type) bool {
+	_, isI := T.Underlying().(*types.Interface)
+	return isI
+}
+
+type typesByString []types.Type
+
+func (p typesByString) Len() int           { return len(p) }
+func (p typesByString) Less(i, j int) bool { return p[i].String() < p[j].String() }
+func (p typesByString) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
diff --git a/third_party/go.tools/oracle/oracle.go b/third_party/go.tools/oracle/oracle.go
new file mode 100644
index 0000000..1fb41ac
--- /dev/null
+++ b/third_party/go.tools/oracle/oracle.go
@@ -0,0 +1,557 @@
+// Copyright 2014 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 oracle contains the implementation of the oracle tool whose
+// command-line is provided by golang.org/x/tools/cmd/oracle.
+//
+// http://golang.org/s/oracle-design
+// http://golang.org/s/oracle-user-manual
+//
+package oracle
+
+// This file defines oracle.Query, the entry point for the oracle tool.
+// The actual executable is defined in cmd/oracle.
+
+// TODO(adonovan): new queries
+// - show all statements that may update the selected lvalue
+//   (local, global, field, etc).
+// - show all places where an object of type T is created
+//   (&T{}, var t T, new(T), new(struct{array [3]T}), etc.
+
+// ORACLE CONTROL FLOW
+//
+// The Oracle is somewhat convoluted due to the need to support two
+// very different use-cases, "one-shot" and "long running", and to do
+// so quickly.
+//
+// The cmd/oracle tool issues "one-shot" queries via the exported
+// Query function, which creates an Oracle to answer a single query.
+// newOracle consults the 'needs' flags of the query mode and the
+// package containing the query to avoid doing more work than it needs
+// (loading, parsing, type checking, SSA construction).
+//
+// The Pythia tool (github.com/fzipp/pythia) is an example of a "long
+// running" tool.  It calls New() and then loops, calling
+// ParseQueryPos and (*Oracle).Query to handle each incoming HTTP
+// query.  Since New cannot see which queries will follow, it must
+// load, parse, type-check and SSA-build the entire transitive closure
+// of the analysis scope, retaining full debug information and all
+// typed ASTs.
+//
+// TODO(adonovan): experiment with inverting the control flow by
+// making each mode consist of two functions: a "one-shot setup"
+// function and the existing "impl" function.  The one-shot setup
+// function would do all of the work of Query and newOracle,
+// specialized to each mode, calling library utilities for the common
+// things.  This would give it more control over "scope reduction".
+// Long running tools would not call the one-shot setup function but
+// would have their own setup function equivalent to the existing
+// 'needsAll' flow path.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/token"
+	"io"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/pointer"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// An Oracle holds the program state required for one or more queries.
+type Oracle struct {
+	fset      *token.FileSet                         // file set [all queries]
+	prog      *ssa.Program                           // the SSA program [needSSA]
+	ptaConfig pointer.Config                         // pointer analysis configuration [needPTA]
+	typeInfo  map[*types.Package]*loader.PackageInfo // type info for all ASTs in the program [needRetainTypeInfo]
+}
+
+// A set of bits indicating the analytical requirements of each mode.
+//
+// Typed ASTs for the whole program are always constructed
+// transiently; they are retained only for the queried package unless
+// needRetainTypeInfo is set.
+const (
+	needPos            = 1 << iota // needs a position
+	needExactPos                   // needs an exact AST selection; implies needPos
+	needRetainTypeInfo             // needs to retain type info for all ASTs in the program
+	needSSA                        // needs ssa.Packages for whole program
+	needSSADebug                   // needs debug info for ssa.Packages
+	needPTA            = needSSA   // needs pointer analysis
+	needAll            = -1        // needs everything (e.g. a sequence of queries)
+)
+
+type modeInfo struct {
+	name  string
+	needs int
+	impl  func(*Oracle, *QueryPos) (queryResult, error)
+}
+
+var modes = []*modeInfo{
+	// Pointer analyses, whole program:
+	{"callees", needPTA | needExactPos, callees},
+	{"callers", needPTA | needPos, callers},
+	{"callgraph", needPTA, doCallgraph},
+	{"callstack", needPTA | needPos, callstack},
+	{"peers", needPTA | needSSADebug | needPos, peers},
+	{"pointsto", needPTA | needSSADebug | needExactPos, pointsto},
+
+	// Type-based, modular analyses:
+	{"definition", needPos, definition},
+	{"describe", needExactPos, describe},
+	{"freevars", needPos, freevars},
+
+	// Type-based, whole-program analyses:
+	{"implements", needRetainTypeInfo | needPos, implements},
+	{"referrers", needRetainTypeInfo | needPos, referrers},
+}
+
+func findMode(mode string) *modeInfo {
+	for _, m := range modes {
+		if m.name == mode {
+			return m
+		}
+	}
+	return nil
+}
+
+type printfFunc func(pos interface{}, format string, args ...interface{})
+
+// queryResult is the interface of each query-specific result type.
+type queryResult interface {
+	toSerial(res *serial.Result, fset *token.FileSet)
+	display(printf printfFunc)
+}
+
+// A QueryPos represents the position provided as input to a query:
+// a textual extent in the program's source code, the AST node it
+// corresponds to, and the package to which it belongs.
+// Instances are created by ParseQueryPos.
+//
+type QueryPos struct {
+	fset       *token.FileSet
+	start, end token.Pos           // source extent of query
+	path       []ast.Node          // AST path from query node to root of ast.File
+	exact      bool                // 2nd result of PathEnclosingInterval
+	info       *loader.PackageInfo // type info for the queried package (nil for fastQueryPos)
+}
+
+// TypeString prints type T relative to the query position.
+func (qpos *QueryPos) TypeString(T types.Type) string {
+	return types.TypeString(qpos.info.Pkg, T)
+}
+
+// ObjectString prints object obj relative to the query position.
+func (qpos *QueryPos) ObjectString(obj types.Object) string {
+	return types.ObjectString(qpos.info.Pkg, obj)
+}
+
+// SelectionString prints selection sel relative to the query position.
+func (qpos *QueryPos) SelectionString(sel *types.Selection) string {
+	return types.SelectionString(qpos.info.Pkg, sel)
+}
+
+// A Result encapsulates the result of an oracle.Query.
+type Result struct {
+	fset     *token.FileSet
+	q        queryResult       // the query-specific result
+	mode     string            // query mode
+	warnings []pointer.Warning // pointer analysis warnings (TODO(adonovan): fix: never populated!)
+}
+
+// Serial returns an instance of serial.Result, which implements the
+// {xml,json}.Marshaler interfaces so that query results can be
+// serialized as JSON or XML.
+//
+func (res *Result) Serial() *serial.Result {
+	resj := &serial.Result{Mode: res.mode}
+	res.q.toSerial(resj, res.fset)
+	for _, w := range res.warnings {
+		resj.Warnings = append(resj.Warnings, serial.PTAWarning{
+			Pos:     res.fset.Position(w.Pos).String(),
+			Message: w.Message,
+		})
+	}
+	return resj
+}
+
+// Query runs a single oracle query.
+//
+// args specify the main package in (*loader.Config).FromArgs syntax.
+// mode is the query mode ("callers", etc).
+// ptalog is the (optional) pointer-analysis log file.
+// buildContext is the go/build configuration for locating packages.
+// reflection determines whether to model reflection soundly (currently slow).
+//
+// Clients that intend to perform multiple queries against the same
+// analysis scope should use this pattern instead:
+//
+//	conf := loader.Config{Build: buildContext, SourceImports: true}
+//	... populate config, e.g. conf.FromArgs(args) ...
+//	iprog, err := conf.Load()
+//	if err != nil { ... }
+// 	o, err := oracle.New(iprog, nil, false)
+//	if err != nil { ... }
+//	for ... {
+//		qpos, err := oracle.ParseQueryPos(imp, pos, needExact)
+//		if err != nil { ... }
+//
+//		res, err := o.Query(mode, qpos)
+//		if err != nil { ... }
+//
+//		// use res
+//	}
+//
+// TODO(adonovan): the ideal 'needsExact' parameter for ParseQueryPos
+// depends on the query mode; how should we expose this?
+//
+func Query(args []string, mode, pos string, ptalog io.Writer, buildContext *build.Context, reflection bool) (*Result, error) {
+	if mode == "what" {
+		// Bypass package loading, type checking, SSA construction.
+		return what(pos, buildContext)
+	}
+
+	minfo := findMode(mode)
+	if minfo == nil {
+		return nil, fmt.Errorf("invalid mode type: %q", mode)
+	}
+
+	conf := loader.Config{Build: buildContext, SourceImports: true}
+
+	// Determine initial packages.
+	args, err := conf.FromArgs(args, true)
+	if err != nil {
+		return nil, err
+	}
+	if len(args) > 0 {
+		return nil, fmt.Errorf("surplus arguments: %q", args)
+	}
+
+	// For queries needing only a single typed package,
+	// reduce the analysis scope to that package.
+	if minfo.needs&(needSSA|needRetainTypeInfo) == 0 {
+		reduceScope(pos, &conf)
+	}
+
+	// TODO(adonovan): report type errors to the user via Serial
+	// types, not stderr?
+	// conf.TypeChecker.Error = func(err error) {
+	// 	E := err.(types.Error)
+	// 	fmt.Fprintf(os.Stderr, "%s: %s\n", E.Fset.Position(E.Pos), E.Msg)
+	// }
+
+	// Load/parse/type-check the program.
+	iprog, err := conf.Load()
+	if err != nil {
+		return nil, err
+	}
+
+	o, err := newOracle(iprog, ptalog, minfo.needs, reflection)
+	if err != nil {
+		return nil, err
+	}
+
+	qpos, err := ParseQueryPos(iprog, pos, minfo.needs&needExactPos != 0)
+	if err != nil && minfo.needs&(needPos|needExactPos) != 0 {
+		return nil, err
+	}
+
+	// SSA is built and we have the QueryPos.
+	// Release the other ASTs and type info to the GC.
+	iprog = nil
+
+	return o.query(minfo, qpos)
+}
+
+// reduceScope is called for one-shot queries that need only a single
+// typed package.  It attempts to guess the query package from pos and
+// reduce the analysis scope (set of loaded packages) to just that one
+// plus (the exported parts of) its dependencies.  It leaves its
+// arguments unchanged on failure.
+//
+// TODO(adonovan): this is a real mess... but it's fast.
+//
+func reduceScope(pos string, conf *loader.Config) {
+	fqpos, err := fastQueryPos(pos)
+	if err != nil {
+		return // bad query
+	}
+
+	// TODO(adonovan): fix: this gives the wrong results for files
+	// in non-importable packages such as tests and ad-hoc packages
+	// specified as a list of files (incl. the oracle's tests).
+	_, importPath, err := guessImportPath(fqpos.fset.File(fqpos.start).Name(), conf.Build)
+	if err != nil {
+		return // can't find GOPATH dir
+	}
+	if importPath == "" {
+		return
+	}
+
+	// Check that it's possible to load the queried package.
+	// (e.g. oracle tests contain different 'package' decls in same dir.)
+	// Keep consistent with logic in loader/util.go!
+	cfg2 := *conf.Build
+	cfg2.CgoEnabled = false
+	bp, err := cfg2.Import(importPath, "", 0)
+	if err != nil {
+		return // no files for package
+	}
+
+	// Check that the queried file appears in the package:
+	// it might be a '// +build ignore' from an ad-hoc main
+	// package, e.g. $GOROOT/src/net/http/triv.go.
+	if !pkgContainsFile(bp, fqpos.fset.File(fqpos.start).Name()) {
+		return // not found
+	}
+
+	conf.TypeCheckFuncBodies = func(p string) bool { return p == importPath }
+
+	// Ignore packages specified on command line.
+	conf.CreatePkgs = nil
+	conf.ImportPkgs = nil
+
+	// Instead load just the one containing the query position
+	// (and possibly its corresponding tests/production code).
+	// TODO(adonovan): set 'augment' based on which file list
+	// contains
+	_ = conf.ImportWithTests(importPath) // ignore error
+}
+
+func pkgContainsFile(bp *build.Package, filename string) bool {
+	for _, files := range [][]string{bp.GoFiles, bp.TestGoFiles, bp.XTestGoFiles} {
+		for _, file := range files {
+			if sameFile(file, filename) {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// New constructs a new Oracle that can be used for a sequence of queries.
+//
+// iprog specifies the program to analyze.
+// ptalog is the (optional) pointer-analysis log file.
+// reflection determines whether to model reflection soundly (currently slow).
+//
+func New(iprog *loader.Program, ptalog io.Writer, reflection bool) (*Oracle, error) {
+	return newOracle(iprog, ptalog, needAll, reflection)
+}
+
+func newOracle(iprog *loader.Program, ptalog io.Writer, needs int, reflection bool) (*Oracle, error) {
+	o := &Oracle{fset: iprog.Fset}
+
+	// Retain type info for all ASTs in the program.
+	if needs&needRetainTypeInfo != 0 {
+		o.typeInfo = iprog.AllPackages
+	}
+
+	// Create SSA package for the initial packages and their dependencies.
+	if needs&needSSA != 0 {
+		var mode ssa.BuilderMode
+		if needs&needSSADebug != 0 {
+			mode |= ssa.GlobalDebug
+		}
+		prog := ssa.Create(iprog, mode)
+
+		// For each initial package (specified on the command line),
+		// if it has a main function, analyze that,
+		// otherwise analyze its tests, if any.
+		var testPkgs, mains []*ssa.Package
+		for _, info := range iprog.InitialPackages() {
+			initialPkg := prog.Package(info.Pkg)
+
+			// Add package to the pointer analysis scope.
+			if initialPkg.Func("main") != nil {
+				mains = append(mains, initialPkg)
+			} else {
+				testPkgs = append(testPkgs, initialPkg)
+			}
+		}
+		if testPkgs != nil {
+			if p := prog.CreateTestMainPackage(testPkgs...); p != nil {
+				mains = append(mains, p)
+			}
+		}
+		if mains == nil {
+			return nil, fmt.Errorf("analysis scope has no main and no tests")
+		}
+		o.ptaConfig.Log = ptalog
+		o.ptaConfig.Reflection = reflection
+		o.ptaConfig.Mains = mains
+
+		o.prog = prog
+	}
+
+	return o, nil
+}
+
+// Query runs the query of the specified mode and selection.
+//
+// TODO(adonovan): fix: this function does not currently support the
+// "what" query, which needs to access the go/build.Context.
+//
+func (o *Oracle) Query(mode string, qpos *QueryPos) (*Result, error) {
+	minfo := findMode(mode)
+	if minfo == nil {
+		return nil, fmt.Errorf("invalid mode type: %q", mode)
+	}
+	return o.query(minfo, qpos)
+}
+
+func (o *Oracle) query(minfo *modeInfo, qpos *QueryPos) (*Result, error) {
+	// Clear out residue of previous query (for long-running clients).
+	o.ptaConfig.Queries = nil
+	o.ptaConfig.IndirectQueries = nil
+
+	res := &Result{
+		mode: minfo.name,
+		fset: o.fset,
+	}
+	var err error
+	res.q, err = minfo.impl(o, qpos)
+	if err != nil {
+		return nil, err
+	}
+	return res, nil
+}
+
+// ParseQueryPos parses the source query position pos.
+// If needExact, it must identify a single AST subtree;
+// this is appropriate for queries that allow fairly arbitrary syntax,
+// e.g. "describe".
+//
+func ParseQueryPos(iprog *loader.Program, posFlag string, needExact bool) (*QueryPos, error) {
+	filename, startOffset, endOffset, err := parsePosFlag(posFlag)
+	if err != nil {
+		return nil, err
+	}
+	start, end, err := findQueryPos(iprog.Fset, filename, startOffset, endOffset)
+	if err != nil {
+		return nil, err
+	}
+	info, path, exact := iprog.PathEnclosingInterval(start, end)
+	if path == nil {
+		return nil, fmt.Errorf("no syntax here")
+	}
+	if needExact && !exact {
+		return nil, fmt.Errorf("ambiguous selection within %s", astutil.NodeDescription(path[0]))
+	}
+	return &QueryPos{iprog.Fset, start, end, path, exact, info}, nil
+}
+
+// WriteTo writes the oracle query result res to out in a compiler diagnostic format.
+func (res *Result) WriteTo(out io.Writer) {
+	printf := func(pos interface{}, format string, args ...interface{}) {
+		fprintf(out, res.fset, pos, format, args...)
+	}
+	res.q.display(printf)
+
+	// Print warnings after the main output.
+	if res.warnings != nil {
+		fmt.Fprintln(out, "\nPointer analysis warnings:")
+		for _, w := range res.warnings {
+			printf(w.Pos, "warning: "+w.Message)
+		}
+	}
+}
+
+// ---------- Utilities ----------
+
+// buildSSA constructs the SSA representation of Go-source function bodies.
+// Not needed in simpler modes, e.g. freevars.
+//
+func buildSSA(o *Oracle) {
+	o.prog.BuildAll()
+}
+
+// ptrAnalysis runs the pointer analysis and returns its result.
+func ptrAnalysis(o *Oracle) *pointer.Result {
+	result, err := pointer.Analyze(&o.ptaConfig)
+	if err != nil {
+		panic(err) // pointer analysis internal error
+	}
+	return result
+}
+
+// unparen returns e with any enclosing parentheses stripped.
+func unparen(e ast.Expr) ast.Expr {
+	for {
+		p, ok := e.(*ast.ParenExpr)
+		if !ok {
+			break
+		}
+		e = p.X
+	}
+	return e
+}
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// fprintf prints to w a message of the form "location: message\n"
+// where location is derived from pos.
+//
+// pos must be one of:
+//    - a token.Pos, denoting a position
+//    - an ast.Node, denoting an interval
+//    - anything with a Pos() method:
+//         ssa.Member, ssa.Value, ssa.Instruction, types.Object, pointer.Label, etc.
+//    - a QueryPos, denoting the extent of the user's query.
+//    - nil, meaning no position at all.
+//
+// The output format is is compatible with the 'gnu'
+// compilation-error-regexp in Emacs' compilation mode.
+// TODO(adonovan): support other editors.
+//
+func fprintf(w io.Writer, fset *token.FileSet, pos interface{}, format string, args ...interface{}) {
+	var start, end token.Pos
+	switch pos := pos.(type) {
+	case ast.Node:
+		start = pos.Pos()
+		end = pos.End()
+	case token.Pos:
+		start = pos
+		end = start
+	case interface {
+		Pos() token.Pos
+	}:
+		start = pos.Pos()
+		end = start
+	case *QueryPos:
+		start = pos.start
+		end = pos.end
+	case nil:
+		// no-op
+	default:
+		panic(fmt.Sprintf("invalid pos: %T", pos))
+	}
+
+	if sp := fset.Position(start); start == end {
+		// (prints "-: " for token.NoPos)
+		fmt.Fprintf(w, "%s: ", sp)
+	} else {
+		ep := fset.Position(end)
+		// The -1 below is a concession to Emacs's broken use of
+		// inclusive (not half-open) intervals.
+		// Other editors may not want it.
+		// TODO(adonovan): add an -editor=vim|emacs|acme|auto
+		// flag; auto uses EMACS=t / VIM=... / etc env vars.
+		fmt.Fprintf(w, "%s:%d.%d-%d.%d: ",
+			sp.Filename, sp.Line, sp.Column, ep.Line, ep.Column-1)
+	}
+	fmt.Fprintf(w, format, args...)
+	io.WriteString(w, "\n")
+}
diff --git a/third_party/go.tools/oracle/oracle_test.go b/third_party/go.tools/oracle/oracle_test.go
new file mode 100644
index 0000000..d2665d6
--- /dev/null
+++ b/third_party/go.tools/oracle/oracle_test.go
@@ -0,0 +1,319 @@
+// Copyright 2013 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 oracle_test
+
+// This file defines a test framework for oracle queries.
+//
+// The files beneath testdata/src/main contain Go programs containing
+// query annotations of the form:
+//
+//   @verb id "select"
+//
+// where verb is the query mode (e.g. "callers"), id is a unique name
+// for this query, and "select" is a regular expression matching the
+// substring of the current line that is the query's input selection.
+//
+// The expected output for each query is provided in the accompanying
+// .golden file.
+//
+// (Location information is not included because it's too fragile to
+// display as text.  TODO(adonovan): think about how we can test its
+// correctness, since it is critical information.)
+//
+// Run this test with:
+// 	% go test golang.org/x/tools/oracle -update
+// to update the golden files.
+
+import (
+	"bytes"
+	"encoding/json"
+	"flag"
+	"fmt"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/oracle"
+)
+
+var updateFlag = flag.Bool("update", false, "Update the golden files.")
+
+type query struct {
+	id       string         // unique id
+	verb     string         // query mode, e.g. "callees"
+	posn     token.Position // position of of query
+	filename string
+	queryPos string // value of -pos flag
+}
+
+func parseRegexp(text string) (*regexp.Regexp, error) {
+	pattern, err := strconv.Unquote(text)
+	if err != nil {
+		return nil, fmt.Errorf("can't unquote %s", text)
+	}
+	return regexp.Compile(pattern)
+}
+
+// parseQueries parses and returns the queries in the named file.
+func parseQueries(t *testing.T, filename string) []*query {
+	filedata, err := ioutil.ReadFile(filename)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Parse the file once to discover the test queries.
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, filename, filedata, parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	lines := bytes.Split(filedata, []byte("\n"))
+
+	var queries []*query
+	queriesById := make(map[string]*query)
+
+	// Find all annotations of these forms:
+	expectRe := regexp.MustCompile(`@([a-z]+)\s+(\S+)\s+(\".*)$`) // @verb id "regexp"
+	for _, c := range f.Comments {
+		text := strings.TrimSpace(c.Text())
+		if text == "" || text[0] != '@' {
+			continue
+		}
+		posn := fset.Position(c.Pos())
+
+		// @verb id "regexp"
+		match := expectRe.FindStringSubmatch(text)
+		if match == nil {
+			t.Errorf("%s: ill-formed query: %s", posn, text)
+			continue
+		}
+
+		id := match[2]
+		if prev, ok := queriesById[id]; ok {
+			t.Errorf("%s: duplicate id %s", posn, id)
+			t.Errorf("%s: previously used here", prev.posn)
+			continue
+		}
+
+		q := &query{
+			id:       id,
+			verb:     match[1],
+			filename: filename,
+			posn:     posn,
+		}
+
+		if match[3] != `"nopos"` {
+			selectRe, err := parseRegexp(match[3])
+			if err != nil {
+				t.Errorf("%s: %s", posn, err)
+				continue
+			}
+
+			// Find text of the current line, sans query.
+			// (Queries must be // not /**/ comments.)
+			line := lines[posn.Line-1][:posn.Column-1]
+
+			// Apply regexp to current line to find input selection.
+			loc := selectRe.FindIndex(line)
+			if loc == nil {
+				t.Errorf("%s: selection pattern %s doesn't match line %q",
+					posn, match[3], string(line))
+				continue
+			}
+
+			// Assumes ASCII. TODO(adonovan): test on UTF-8.
+			linestart := posn.Offset - (posn.Column - 1)
+
+			// Compute the file offsets.
+			q.queryPos = fmt.Sprintf("%s:#%d,#%d",
+				filename, linestart+loc[0], linestart+loc[1])
+		}
+
+		queries = append(queries, q)
+		queriesById[id] = q
+	}
+
+	// Return the slice, not map, for deterministic iteration.
+	return queries
+}
+
+// WriteResult writes res (-format=plain) to w, stripping file locations.
+func WriteResult(w io.Writer, res *oracle.Result) {
+	capture := new(bytes.Buffer) // capture standard output
+	res.WriteTo(capture)
+	for _, line := range strings.Split(capture.String(), "\n") {
+		// Remove a "file:line: " prefix.
+		if i := strings.Index(line, ": "); i >= 0 {
+			line = line[i+2:]
+		}
+		fmt.Fprintf(w, "%s\n", line)
+	}
+}
+
+// doQuery poses query q to the oracle and writes its response and
+// error (if any) to out.
+func doQuery(out io.Writer, q *query, useJson bool) {
+	fmt.Fprintf(out, "-------- @%s %s --------\n", q.verb, q.id)
+
+	var buildContext = build.Default
+	buildContext.GOPATH = "testdata"
+	res, err := oracle.Query([]string{q.filename},
+		q.verb,
+		q.queryPos,
+		nil, // ptalog,
+		&buildContext,
+		true) // reflection
+	if err != nil {
+		fmt.Fprintf(out, "\nError: %s\n", err)
+		return
+	}
+
+	if useJson {
+		// JSON output
+		b, err := json.MarshalIndent(res.Serial(), "", "\t")
+		if err != nil {
+			fmt.Fprintf(out, "JSON error: %s\n", err.Error())
+			return
+		}
+		out.Write(b)
+	} else {
+		// "plain" (compiler diagnostic format) output
+		WriteResult(out, res)
+	}
+}
+
+func TestOracle(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows":
+		t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS)
+	}
+
+	for _, filename := range []string{
+		"testdata/src/main/calls.go",
+		"testdata/src/main/callgraph.go",
+		"testdata/src/main/callgraph2.go",
+		"testdata/src/main/describe.go",
+		"testdata/src/main/freevars.go",
+		"testdata/src/main/implements.go",
+		"testdata/src/main/imports.go",
+		"testdata/src/main/peers.go",
+		"testdata/src/main/pointsto.go",
+		"testdata/src/main/reflection.go",
+		"testdata/src/main/what.go",
+		// JSON:
+		// TODO(adonovan): most of these are very similar; combine them.
+		"testdata/src/main/callgraph-json.go",
+		"testdata/src/main/calls-json.go",
+		"testdata/src/main/peers-json.go",
+		"testdata/src/main/describe-json.go",
+		"testdata/src/main/implements-json.go",
+		"testdata/src/main/pointsto-json.go",
+		"testdata/src/main/referrers-json.go",
+		"testdata/src/main/what-json.go",
+	} {
+		useJson := strings.HasSuffix(filename, "-json.go")
+		queries := parseQueries(t, filename)
+		golden := filename + "lden"
+		got := filename + "t"
+		gotfh, err := os.Create(got)
+		if err != nil {
+			t.Errorf("Create(%s) failed: %s", got, err)
+			continue
+		}
+		defer gotfh.Close()
+		defer os.Remove(got)
+
+		// Run the oracle on each query, redirecting its output
+		// and error (if any) to the foo.got file.
+		for _, q := range queries {
+			doQuery(gotfh, q, useJson)
+		}
+
+		// Compare foo.got with foo.golden.
+		var cmd *exec.Cmd
+		switch runtime.GOOS {
+		case "plan9":
+			cmd = exec.Command("/bin/diff", "-c", golden, got)
+		default:
+			cmd = exec.Command("/usr/bin/diff", "-u", golden, got)
+		}
+		buf := new(bytes.Buffer)
+		cmd.Stdout = buf
+		cmd.Stderr = os.Stderr
+		if err := cmd.Run(); err != nil {
+			t.Errorf("Oracle tests for %s failed: %s.\n%s\n",
+				filename, err, buf)
+
+			if *updateFlag {
+				t.Logf("Updating %s...", golden)
+				if err := exec.Command("/bin/cp", got, golden).Run(); err != nil {
+					t.Errorf("Update failed: %s", err)
+				}
+			}
+		}
+	}
+}
+
+func TestMultipleQueries(t *testing.T) {
+	// Loader
+	var buildContext = build.Default
+	buildContext.GOPATH = "testdata"
+	conf := loader.Config{Build: &buildContext, SourceImports: true}
+	filename := "testdata/src/main/multi.go"
+	conf.CreateFromFilenames("", filename)
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %s", err)
+	}
+
+	// Oracle
+	o, err := oracle.New(iprog, nil, true)
+	if err != nil {
+		t.Fatalf("oracle.New failed: %s", err)
+	}
+
+	// QueryPos
+	pos := filename + ":#54,#58"
+	qpos, err := oracle.ParseQueryPos(iprog, pos, true)
+	if err != nil {
+		t.Fatalf("oracle.ParseQueryPos(%q) failed: %s", pos, err)
+	}
+	// SSA is built and we have the QueryPos.
+	// Release the other ASTs and type info to the GC.
+	iprog = nil
+
+	// Run different query modes on same scope and selection.
+	out := new(bytes.Buffer)
+	for _, mode := range [...]string{"callers", "describe", "freevars"} {
+		res, err := o.Query(mode, qpos)
+		if err != nil {
+			t.Errorf("(*oracle.Oracle).Query(%q) failed: %s", pos, err)
+		}
+		WriteResult(out, res)
+	}
+	want := `multi.f is called from these 1 sites:
+	static function call from multi.main
+
+function call (or conversion) of type ()
+
+Free identifiers:
+var x int
+
+`
+	if got := out.String(); got != want {
+		t.Errorf("Query output differs; want <<%s>>, got <<%s>>\n", want, got)
+	}
+}
diff --git a/third_party/go.tools/oracle/peers.go b/third_party/go.tools/oracle/peers.go
new file mode 100644
index 0000000..2a5f68b
--- /dev/null
+++ b/third_party/go.tools/oracle/peers.go
@@ -0,0 +1,222 @@
+// Copyright 2013 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 oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/ssa/ssautil"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// peers enumerates, for a given channel send (or receive) operation,
+// the set of possible receives (or sends) that correspond to it.
+//
+// TODO(adonovan): support reflect.{Select,Recv,Send,Close}.
+// TODO(adonovan): permit the user to query based on a MakeChan (not send/recv),
+// or the implicit receive in "for v := range ch".
+func peers(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	opPos := findOp(qpos)
+	if opPos == token.NoPos {
+		return nil, fmt.Errorf("there is no channel operation here")
+	}
+
+	buildSSA(o)
+
+	var queryOp chanOp // the originating send or receive operation
+	var ops []chanOp   // all sends/receives of opposite direction
+
+	// Look at all channel operations in the whole ssa.Program.
+	// Build a list of those of same type as the query.
+	allFuncs := ssautil.AllFunctions(o.prog)
+	for fn := range allFuncs {
+		for _, b := range fn.Blocks {
+			for _, instr := range b.Instrs {
+				for _, op := range chanOps(instr) {
+					ops = append(ops, op)
+					if op.pos == opPos {
+						queryOp = op // we found the query op
+					}
+				}
+			}
+		}
+	}
+	if queryOp.ch == nil {
+		return nil, fmt.Errorf("ssa.Instruction for send/receive not found")
+	}
+
+	// Discard operations of wrong channel element type.
+	// Build set of channel ssa.Values as query to pointer analysis.
+	// We compare channels by element types, not channel types, to
+	// ignore both directionality and type names.
+	queryType := queryOp.ch.Type()
+	queryElemType := queryType.Underlying().(*types.Chan).Elem()
+	o.ptaConfig.AddQuery(queryOp.ch)
+	i := 0
+	for _, op := range ops {
+		if types.Identical(op.ch.Type().Underlying().(*types.Chan).Elem(), queryElemType) {
+			o.ptaConfig.AddQuery(op.ch)
+			ops[i] = op
+			i++
+		}
+	}
+	ops = ops[:i]
+
+	// Run the pointer analysis.
+	ptares := ptrAnalysis(o)
+
+	// Find the points-to set.
+	queryChanPtr := ptares.Queries[queryOp.ch]
+
+	// Ascertain which make(chan) labels the query's channel can alias.
+	var makes []token.Pos
+	for _, label := range queryChanPtr.PointsTo().Labels() {
+		makes = append(makes, label.Pos())
+	}
+	sort.Sort(byPos(makes))
+
+	// Ascertain which channel operations can alias the same make(chan) labels.
+	var sends, receives, closes []token.Pos
+	for _, op := range ops {
+		if ptr, ok := ptares.Queries[op.ch]; ok && ptr.MayAlias(queryChanPtr) {
+			switch op.dir {
+			case types.SendOnly:
+				sends = append(sends, op.pos)
+			case types.RecvOnly:
+				receives = append(receives, op.pos)
+			case types.SendRecv:
+				closes = append(closes, op.pos)
+			}
+		}
+	}
+	sort.Sort(byPos(sends))
+	sort.Sort(byPos(receives))
+	sort.Sort(byPos(closes))
+
+	return &peersResult{
+		queryPos:  opPos,
+		queryType: queryType,
+		makes:     makes,
+		sends:     sends,
+		receives:  receives,
+		closes:    closes,
+	}, nil
+}
+
+// findOp returns the position of the enclosing send/receive/close op.
+// For send and receive operations, this is the position of the <- token;
+// for close operations, it's the Lparen of the function call.
+//
+// TODO(adonovan): handle implicit receive operations from 'for...range chan' statements.
+func findOp(qpos *QueryPos) token.Pos {
+	for _, n := range qpos.path {
+		switch n := n.(type) {
+		case *ast.UnaryExpr:
+			if n.Op == token.ARROW {
+				return n.OpPos
+			}
+		case *ast.SendStmt:
+			return n.Arrow
+		case *ast.CallExpr:
+			// close function call can only exist as a direct identifier
+			if close, ok := unparen(n.Fun).(*ast.Ident); ok {
+				if b, ok := qpos.info.Info.Uses[close].(*types.Builtin); ok && b.Name() == "close" {
+					return n.Lparen
+				}
+			}
+		}
+	}
+	return token.NoPos
+}
+
+// chanOp abstracts an ssa.Send, ssa.Unop(ARROW), or a SelectState.
+type chanOp struct {
+	ch  ssa.Value
+	dir types.ChanDir // SendOnly=send, RecvOnly=recv, SendRecv=close
+	pos token.Pos
+}
+
+// chanOps returns a slice of all the channel operations in the instruction.
+func chanOps(instr ssa.Instruction) []chanOp {
+	// TODO(adonovan): handle calls to reflect.{Select,Recv,Send,Close} too.
+	var ops []chanOp
+	switch instr := instr.(type) {
+	case *ssa.UnOp:
+		if instr.Op == token.ARROW {
+			ops = append(ops, chanOp{instr.X, types.RecvOnly, instr.Pos()})
+		}
+	case *ssa.Send:
+		ops = append(ops, chanOp{instr.Chan, types.SendOnly, instr.Pos()})
+	case *ssa.Select:
+		for _, st := range instr.States {
+			ops = append(ops, chanOp{st.Chan, st.Dir, st.Pos})
+		}
+	case ssa.CallInstruction:
+		cc := instr.Common()
+		if b, ok := cc.Value.(*ssa.Builtin); ok && b.Name() == "close" {
+			ops = append(ops, chanOp{cc.Args[0], types.SendRecv, cc.Pos()})
+		}
+	}
+	return ops
+}
+
+type peersResult struct {
+	queryPos                       token.Pos   // of queried channel op
+	queryType                      types.Type  // type of queried channel
+	makes, sends, receives, closes []token.Pos // positions of aliased makechan/send/receive/close instrs
+}
+
+func (r *peersResult) display(printf printfFunc) {
+	if len(r.makes) == 0 {
+		printf(r.queryPos, "This channel can't point to anything.")
+		return
+	}
+	printf(r.queryPos, "This channel of type %s may be:", r.queryType)
+	for _, alloc := range r.makes {
+		printf(alloc, "\tallocated here")
+	}
+	for _, send := range r.sends {
+		printf(send, "\tsent to, here")
+	}
+	for _, receive := range r.receives {
+		printf(receive, "\treceived from, here")
+	}
+	for _, clos := range r.closes {
+		printf(clos, "\tclosed, here")
+	}
+}
+
+func (r *peersResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	peers := &serial.Peers{
+		Pos:  fset.Position(r.queryPos).String(),
+		Type: r.queryType.String(),
+	}
+	for _, alloc := range r.makes {
+		peers.Allocs = append(peers.Allocs, fset.Position(alloc).String())
+	}
+	for _, send := range r.sends {
+		peers.Sends = append(peers.Sends, fset.Position(send).String())
+	}
+	for _, receive := range r.receives {
+		peers.Receives = append(peers.Receives, fset.Position(receive).String())
+	}
+	for _, clos := range r.closes {
+		peers.Closes = append(peers.Closes, fset.Position(clos).String())
+	}
+	res.Peers = peers
+}
+
+// -------- utils --------
+
+type byPos []token.Pos
+
+func (p byPos) Len() int           { return len(p) }
+func (p byPos) Less(i, j int) bool { return p[i] < p[j] }
+func (p byPos) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
diff --git a/third_party/go.tools/oracle/pointsto.go b/third_party/go.tools/oracle/pointsto.go
new file mode 100644
index 0000000..bcb2da6
--- /dev/null
+++ b/third_party/go.tools/oracle/pointsto.go
@@ -0,0 +1,264 @@
+// Copyright 2013 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 oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/pointer"
+	"llvm.org/llgo/third_party/go.tools/go/ssa"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// pointsto runs the pointer analysis on the selected expression,
+// and reports its points-to set (for a pointer-like expression)
+// or its dynamic types (for an interface, reflect.Value, or
+// reflect.Type expression) and their points-to sets.
+//
+// All printed sets are sorted to ensure determinism.
+//
+func pointsto(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	path, action := findInterestingNode(qpos.info, qpos.path)
+	if action != actionExpr {
+		return nil, fmt.Errorf("pointer analysis wants an expression; got %s",
+			astutil.NodeDescription(qpos.path[0]))
+	}
+
+	var expr ast.Expr
+	var obj types.Object
+	switch n := path[0].(type) {
+	case *ast.ValueSpec:
+		// ambiguous ValueSpec containing multiple names
+		return nil, fmt.Errorf("multiple value specification")
+	case *ast.Ident:
+		obj = qpos.info.ObjectOf(n)
+		expr = n
+	case ast.Expr:
+		expr = n
+	default:
+		// TODO(adonovan): is this reachable?
+		return nil, fmt.Errorf("unexpected AST for expr: %T", n)
+	}
+
+	// Reject non-pointerlike types (includes all constants---except nil).
+	// TODO(adonovan): reject nil too.
+	typ := qpos.info.TypeOf(expr)
+	if !pointer.CanPoint(typ) {
+		return nil, fmt.Errorf("pointer analysis wants an expression of reference type; got %s", typ)
+	}
+
+	// Determine the ssa.Value for the expression.
+	var value ssa.Value
+	var isAddr bool
+	var err error
+	if obj != nil {
+		// def/ref of func/var object
+		value, isAddr, err = ssaValueForIdent(o.prog, qpos.info, obj, path)
+	} else {
+		value, isAddr, err = ssaValueForExpr(o.prog, qpos.info, path)
+	}
+	if err != nil {
+		return nil, err // e.g. trivially dead code
+	}
+
+	// Run the pointer analysis.
+	ptrs, err := runPTA(o, value, isAddr)
+	if err != nil {
+		return nil, err // e.g. analytically unreachable
+	}
+
+	return &pointstoResult{
+		qpos: qpos,
+		typ:  typ,
+		ptrs: ptrs,
+	}, nil
+}
+
+// ssaValueForIdent returns the ssa.Value for the ast.Ident whose path
+// to the root of the AST is path.  isAddr reports whether the
+// ssa.Value is the address denoted by the ast.Ident, not its value.
+//
+func ssaValueForIdent(prog *ssa.Program, qinfo *loader.PackageInfo, obj types.Object, path []ast.Node) (value ssa.Value, isAddr bool, err error) {
+	switch obj := obj.(type) {
+	case *types.Var:
+		pkg := prog.Package(qinfo.Pkg)
+		pkg.Build()
+		if v, addr := prog.VarValue(obj, pkg, path); v != nil {
+			return v, addr, nil
+		}
+		return nil, false, fmt.Errorf("can't locate SSA Value for var %s", obj.Name())
+
+	case *types.Func:
+		fn := prog.FuncValue(obj)
+		if fn == nil {
+			return nil, false, fmt.Errorf("%s is an interface method", obj)
+		}
+		// TODO(adonovan): there's no point running PTA on a *Func ident.
+		// Eliminate this feature.
+		return fn, false, nil
+	}
+	panic(obj)
+}
+
+// ssaValueForExpr returns the ssa.Value of the non-ast.Ident
+// expression whose path to the root of the AST is path.
+//
+func ssaValueForExpr(prog *ssa.Program, qinfo *loader.PackageInfo, path []ast.Node) (value ssa.Value, isAddr bool, err error) {
+	pkg := prog.Package(qinfo.Pkg)
+	pkg.SetDebugMode(true)
+	pkg.Build()
+
+	fn := ssa.EnclosingFunction(pkg, path)
+	if fn == nil {
+		return nil, false, fmt.Errorf("no SSA function built for this location (dead code?)")
+	}
+
+	if v, addr := fn.ValueForExpr(path[0].(ast.Expr)); v != nil {
+		return v, addr, nil
+	}
+
+	return nil, false, fmt.Errorf("can't locate SSA Value for expression in %s", fn)
+}
+
+// runPTA runs the pointer analysis of the selected SSA value or address.
+func runPTA(o *Oracle, v ssa.Value, isAddr bool) (ptrs []pointerResult, err error) {
+	buildSSA(o)
+
+	T := v.Type()
+	if isAddr {
+		o.ptaConfig.AddIndirectQuery(v)
+		T = deref(T)
+	} else {
+		o.ptaConfig.AddQuery(v)
+	}
+	ptares := ptrAnalysis(o)
+
+	var ptr pointer.Pointer
+	if isAddr {
+		ptr = ptares.IndirectQueries[v]
+	} else {
+		ptr = ptares.Queries[v]
+	}
+	if ptr == (pointer.Pointer{}) {
+		return nil, fmt.Errorf("pointer analysis did not find expression (dead code?)")
+	}
+	pts := ptr.PointsTo()
+
+	if pointer.CanHaveDynamicTypes(T) {
+		// Show concrete types for interface/reflect.Value expression.
+		if concs := pts.DynamicTypes(); concs.Len() > 0 {
+			concs.Iterate(func(conc types.Type, pta interface{}) {
+				labels := pta.(pointer.PointsToSet).Labels()
+				sort.Sort(byPosAndString(labels)) // to ensure determinism
+				ptrs = append(ptrs, pointerResult{conc, labels})
+			})
+		}
+	} else {
+		// Show labels for other expressions.
+		labels := pts.Labels()
+		sort.Sort(byPosAndString(labels)) // to ensure determinism
+		ptrs = append(ptrs, pointerResult{T, labels})
+	}
+	sort.Sort(byTypeString(ptrs)) // to ensure determinism
+	return ptrs, nil
+}
+
+type pointerResult struct {
+	typ    types.Type       // type of the pointer (always concrete)
+	labels []*pointer.Label // set of labels
+}
+
+type pointstoResult struct {
+	qpos *QueryPos
+	typ  types.Type      // type of expression
+	ptrs []pointerResult // pointer info (typ is concrete => len==1)
+}
+
+func (r *pointstoResult) display(printf printfFunc) {
+	if pointer.CanHaveDynamicTypes(r.typ) {
+		// Show concrete types for interface, reflect.Type or
+		// reflect.Value expression.
+
+		if len(r.ptrs) > 0 {
+			printf(r.qpos, "this %s may contain these dynamic types:", r.qpos.TypeString(r.typ))
+			for _, ptr := range r.ptrs {
+				var obj types.Object
+				if nt, ok := deref(ptr.typ).(*types.Named); ok {
+					obj = nt.Obj()
+				}
+				if len(ptr.labels) > 0 {
+					printf(obj, "\t%s, may point to:", r.qpos.TypeString(ptr.typ))
+					printLabels(printf, ptr.labels, "\t\t")
+				} else {
+					printf(obj, "\t%s", r.qpos.TypeString(ptr.typ))
+				}
+			}
+		} else {
+			printf(r.qpos, "this %s cannot contain any dynamic types.", r.typ)
+		}
+	} else {
+		// Show labels for other expressions.
+		if ptr := r.ptrs[0]; len(ptr.labels) > 0 {
+			printf(r.qpos, "this %s may point to these objects:",
+				r.qpos.TypeString(r.typ))
+			printLabels(printf, ptr.labels, "\t")
+		} else {
+			printf(r.qpos, "this %s may not point to anything.",
+				r.qpos.TypeString(r.typ))
+		}
+	}
+}
+
+func (r *pointstoResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var pts []serial.PointsTo
+	for _, ptr := range r.ptrs {
+		var namePos string
+		if nt, ok := deref(ptr.typ).(*types.Named); ok {
+			namePos = fset.Position(nt.Obj().Pos()).String()
+		}
+		var labels []serial.PointsToLabel
+		for _, l := range ptr.labels {
+			labels = append(labels, serial.PointsToLabel{
+				Pos:  fset.Position(l.Pos()).String(),
+				Desc: l.String(),
+			})
+		}
+		pts = append(pts, serial.PointsTo{
+			Type:    r.qpos.TypeString(ptr.typ),
+			NamePos: namePos,
+			Labels:  labels,
+		})
+	}
+	res.PointsTo = pts
+}
+
+type byTypeString []pointerResult
+
+func (a byTypeString) Len() int           { return len(a) }
+func (a byTypeString) Less(i, j int) bool { return a[i].typ.String() < a[j].typ.String() }
+func (a byTypeString) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+type byPosAndString []*pointer.Label
+
+func (a byPosAndString) Len() int { return len(a) }
+func (a byPosAndString) Less(i, j int) bool {
+	cmp := a[i].Pos() - a[j].Pos()
+	return cmp < 0 || (cmp == 0 && a[i].String() < a[j].String())
+}
+func (a byPosAndString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+func printLabels(printf printfFunc, labels []*pointer.Label, prefix string) {
+	// TODO(adonovan): due to context-sensitivity, many of these
+	// labels may differ only by context, which isn't apparent.
+	for _, label := range labels {
+		printf(label, "%s%s", prefix, label)
+	}
+}
diff --git a/third_party/go.tools/oracle/pos.go b/third_party/go.tools/oracle/pos.go
new file mode 100644
index 0000000..d9b0d43
--- /dev/null
+++ b/third_party/go.tools/oracle/pos.go
@@ -0,0 +1,149 @@
+package oracle
+
+// This file defines utilities for working with file positions.
+
+import (
+	"fmt"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+)
+
+// parseOctothorpDecimal returns the numeric value if s matches "#%d",
+// otherwise -1.
+func parseOctothorpDecimal(s string) int {
+	if s != "" && s[0] == '#' {
+		if s, err := strconv.ParseInt(s[1:], 10, 32); err == nil {
+			return int(s)
+		}
+	}
+	return -1
+}
+
+// parsePosFlag parses a string of the form "file:pos" or
+// file:start,end" where pos, start, end match #%d and represent byte
+// offsets, and returns its components.
+//
+// (Numbers without a '#' prefix are reserved for future use,
+// e.g. to indicate line/column positions.)
+//
+func parsePosFlag(posFlag string) (filename string, startOffset, endOffset int, err error) {
+	if posFlag == "" {
+		err = fmt.Errorf("no source position specified (-pos flag)")
+		return
+	}
+
+	colon := strings.LastIndex(posFlag, ":")
+	if colon < 0 {
+		err = fmt.Errorf("invalid source position -pos=%q", posFlag)
+		return
+	}
+	filename, offset := posFlag[:colon], posFlag[colon+1:]
+	startOffset = -1
+	endOffset = -1
+	if hyphen := strings.Index(offset, ","); hyphen < 0 {
+		// e.g. "foo.go:#123"
+		startOffset = parseOctothorpDecimal(offset)
+		endOffset = startOffset
+	} else {
+		// e.g. "foo.go:#123,#456"
+		startOffset = parseOctothorpDecimal(offset[:hyphen])
+		endOffset = parseOctothorpDecimal(offset[hyphen+1:])
+	}
+	if startOffset < 0 || endOffset < 0 {
+		err = fmt.Errorf("invalid -pos offset %q", offset)
+		return
+	}
+	return
+}
+
+// findQueryPos searches fset for filename and translates the
+// specified file-relative byte offsets into token.Pos form.  It
+// returns an error if the file was not found or the offsets were out
+// of bounds.
+//
+func findQueryPos(fset *token.FileSet, filename string, startOffset, endOffset int) (start, end token.Pos, err error) {
+	var file *token.File
+	fset.Iterate(func(f *token.File) bool {
+		if sameFile(filename, f.Name()) {
+			// (f.Name() is absolute)
+			file = f
+			return false // done
+		}
+		return true // continue
+	})
+	if file == nil {
+		err = fmt.Errorf("couldn't find file containing position")
+		return
+	}
+
+	// Range check [start..end], inclusive of both end-points.
+
+	if 0 <= startOffset && startOffset <= file.Size() {
+		start = file.Pos(int(startOffset))
+	} else {
+		err = fmt.Errorf("start position is beyond end of file")
+		return
+	}
+
+	if 0 <= endOffset && endOffset <= file.Size() {
+		end = file.Pos(int(endOffset))
+	} else {
+		err = fmt.Errorf("end position is beyond end of file")
+		return
+	}
+
+	return
+}
+
+// sameFile returns true if x and y have the same basename and denote
+// the same file.
+//
+func sameFile(x, y string) bool {
+	if filepath.Base(x) == filepath.Base(y) { // (optimisation)
+		if xi, err := os.Stat(x); err == nil {
+			if yi, err := os.Stat(y); err == nil {
+				return os.SameFile(xi, yi)
+			}
+		}
+	}
+	return false
+}
+
+// fastQueryPos parses the -pos flag and returns a QueryPos.
+// It parses only a single file, and does not run the type checker.
+//
+// Caveat: the token.{FileSet,Pos} info it contains is not comparable
+// with that from the oracle's FileSet!  (We don't accept oracle.fset
+// as a parameter because we don't want the same filename to appear
+// multiple times in one FileSet.)
+//
+func fastQueryPos(posFlag string) (*QueryPos, error) {
+	filename, startOffset, endOffset, err := parsePosFlag(posFlag)
+	if err != nil {
+		return nil, err
+	}
+
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, filename, nil, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	start, end, err := findQueryPos(fset, filename, startOffset, endOffset)
+	if err != nil {
+		return nil, err
+	}
+
+	path, exact := astutil.PathEnclosingInterval(f, start, end)
+	if path == nil {
+		return nil, fmt.Errorf("no syntax here")
+	}
+
+	return &QueryPos{fset, start, end, path, exact, nil}, nil
+}
diff --git a/third_party/go.tools/oracle/referrers.go b/third_party/go.tools/oracle/referrers.go
new file mode 100644
index 0000000..cc180cc
--- /dev/null
+++ b/third_party/go.tools/oracle/referrers.go
@@ -0,0 +1,107 @@
+// Copyright 2013 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 oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// Referrers reports all identifiers that resolve to the same object
+// as the queried identifier, within any package in the analysis scope.
+//
+func referrers(o *Oracle, qpos *QueryPos) (queryResult, error) {
+	id, _ := qpos.path[0].(*ast.Ident)
+	if id == nil {
+		return nil, fmt.Errorf("no identifier here")
+	}
+
+	obj := qpos.info.ObjectOf(id)
+	if obj == nil {
+		// Happens for y in "switch y := x.(type)", but I think that's all.
+		return nil, fmt.Errorf("no object for identifier")
+	}
+
+	// Iterate over all go/types' Uses facts for the entire program.
+	var refs []*ast.Ident
+	for _, info := range o.typeInfo {
+		for id2, obj2 := range info.Uses {
+			if sameObj(obj, obj2) {
+				refs = append(refs, id2)
+			}
+		}
+	}
+	sort.Sort(byNamePos(refs))
+
+	return &referrersResult{
+		query: id,
+		obj:   obj,
+		refs:  refs,
+	}, nil
+}
+
+// same reports whether x and y are identical, or both are PkgNames
+// that import the same Package.
+//
+func sameObj(x, y types.Object) bool {
+	if x == y {
+		return true
+	}
+	if x, ok := x.(*types.PkgName); ok {
+		if y, ok := y.(*types.PkgName); ok {
+			return x.Imported() == y.Imported()
+		}
+	}
+	return false
+}
+
+// -------- utils --------
+
+type byNamePos []*ast.Ident
+
+func (p byNamePos) Len() int           { return len(p) }
+func (p byNamePos) Less(i, j int) bool { return p[i].NamePos < p[j].NamePos }
+func (p byNamePos) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+type referrersResult struct {
+	query *ast.Ident   // identifier of query
+	obj   types.Object // object it denotes
+	refs  []*ast.Ident // set of all other references to it
+}
+
+func (r *referrersResult) display(printf printfFunc) {
+	if r.query.Pos() != r.obj.Pos() {
+		printf(r.query, "reference to %s", r.obj.Name())
+	}
+	// TODO(adonovan): pretty-print object using same logic as
+	// (*describeValueResult).display.
+	printf(r.obj, "defined here as %s", r.obj)
+	for _, ref := range r.refs {
+		if r.query != ref {
+			printf(ref, "referenced here")
+		}
+	}
+}
+
+// TODO(adonovan): encode extent, not just Pos info, in Serial form.
+
+func (r *referrersResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	referrers := &serial.Referrers{
+		Pos:  fset.Position(r.query.Pos()).String(),
+		Desc: r.obj.String(),
+	}
+	if pos := r.obj.Pos(); pos != token.NoPos { // Package objects have no Pos()
+		referrers.ObjPos = fset.Position(pos).String()
+	}
+	for _, ref := range r.refs {
+		referrers.Refs = append(referrers.Refs, fset.Position(ref.NamePos).String())
+	}
+	res.Referrers = referrers
+}
diff --git a/third_party/go.tools/oracle/serial/serial.go b/third_party/go.tools/oracle/serial/serial.go
new file mode 100644
index 0000000..6776872
--- /dev/null
+++ b/third_party/go.tools/oracle/serial/serial.go
@@ -0,0 +1,256 @@
+// Copyright 2013 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 serial defines the oracle's schema for structured data
+// serialization using JSON, XML, etc.
+package serial
+
+// All 'pos' strings are of the form "file:line:col".
+// TODO(adonovan): improve performance by sharing filename strings.
+// TODO(adonovan): improve precision by providing the start/end
+// interval when available.
+//
+// TODO(adonovan): consider richer encodings of types, functions,
+// methods, etc.
+
+// A Peers is the result of a 'peers' query.
+// If Allocs is empty, the selected channel can't point to anything.
+type Peers struct {
+	Pos      string   `json:"pos"`                // location of the selected channel op (<-)
+	Type     string   `json:"type"`               // type of the selected channel
+	Allocs   []string `json:"allocs,omitempty"`   // locations of aliased make(chan) ops
+	Sends    []string `json:"sends,omitempty"`    // locations of aliased ch<-x ops
+	Receives []string `json:"receives,omitempty"` // locations of aliased <-ch ops
+	Closes   []string `json:"closes,omitempty"`   // locations of aliased close(ch) ops
+}
+
+// A Referrers is the result of a 'referrers' query.
+type Referrers struct {
+	Pos    string   `json:"pos"`              // location of the query reference
+	ObjPos string   `json:"objpos,omitempty"` // location of the definition
+	Desc   string   `json:"desc"`             // description of the denoted object
+	Refs   []string `json:"refs,omitempty"`   // locations of all references
+}
+
+// A Definition is the result of a 'definition' query.
+type Definition struct {
+	ObjPos string `json:"objpos,omitempty"` // location of the definition
+	Desc   string `json:"desc"`             // description of the denoted object
+}
+
+type CalleesItem struct {
+	Name string `json:"name"` // full name of called function
+	Pos  string `json:"pos"`  // location of called function
+}
+
+// A Callees is the result of a 'callees' query.
+//
+// Callees is nonempty unless the call was a dynamic call on a
+// provably nil func or interface value.
+type Callees struct {
+	Pos     string         `json:"pos"`               // location of selected call site
+	Desc    string         `json:"desc"`              // description of call site
+	Callees []*CalleesItem `json:"callees,omitempty"` // set of possible call targets
+}
+
+// A Caller is one element of the slice returned by a 'callers' query.
+// (Callstack also contains a similar slice.)
+//
+// The root of the callgraph has an unspecified "Caller" string.
+type Caller struct {
+	Pos    string `json:"pos,omitempty"` // location of the calling function
+	Desc   string `json:"desc"`          // description of call site
+	Caller string `json:"caller"`        // full name of calling function
+}
+
+// A CallGraph is one element of the slice returned by a 'callgraph' query.
+// The index of each item in the slice is used to identify it in the
+// Callers adjacency list.
+//
+// Multiple nodes may have the same Name due to context-sensitive
+// treatment of some functions.
+//
+// TODO(adonovan): perhaps include edge labels (i.e. callsites).
+type CallGraph struct {
+	Name     string `json:"name"`               // full name of function
+	Pos      string `json:"pos"`                // location of function
+	Children []int  `json:"children,omitempty"` // indices of child nodes in callgraph list
+}
+
+// A CallStack is the result of a 'callstack' query.
+// It indicates an arbitrary path from the root of the callgraph to
+// the query function.
+//
+// If the Callers slice is empty, the function was unreachable in this
+// analysis scope.
+type CallStack struct {
+	Pos     string   `json:"pos"`     // location of the selected function
+	Target  string   `json:"target"`  // the selected function
+	Callers []Caller `json:"callers"` // enclosing calls, innermost first.
+}
+
+// A FreeVar is one element of the slice returned by a 'freevars'
+// query.  Each one identifies an expression referencing a local
+// identifier defined outside the selected region.
+type FreeVar struct {
+	Pos  string `json:"pos"`  // location of the identifier's definition
+	Kind string `json:"kind"` // one of {var,func,type,const,label}
+	Ref  string `json:"ref"`  // referring expression (e.g. "x" or "x.y.z")
+	Type string `json:"type"` // type of the expression
+}
+
+// An Implements contains the result of an 'implements' query.
+
+// It describes the queried type, the set of named non-empty interface
+// types to which it is assignable, and the set of named/*named types
+// (concrete or non-empty interface) which may be assigned to it.
+//
+type Implements struct {
+	T                 ImplementsType   `json:"type,omitempty"`    // the queried type
+	AssignableTo      []ImplementsType `json:"to,omitempty"`      // types assignable to T
+	AssignableFrom    []ImplementsType `json:"from,omitempty"`    // interface types assignable from T
+	AssignableFromPtr []ImplementsType `json:"fromptr,omitempty"` // interface types assignable only from *T
+}
+
+// An ImplementsType describes a single type as part of an 'implements' query.
+type ImplementsType struct {
+	Name string `json:"name"` // full name of the type
+	Pos  string `json:"pos"`  // location of its definition
+	Kind string `json:"kind"` // "basic", "array", etc
+}
+
+// A SyntaxNode is one element of a stack of enclosing syntax nodes in
+// a "what" query.
+type SyntaxNode struct {
+	Description string `json:"desc"`  // description of syntax tree
+	Start       int    `json:"start"` // start byte offset, 0-based
+	End         int    `json:"end"`   // end byte offset
+}
+
+// A What is the result of the "what" query, which quickly identifies
+// the selection, parsing only a single file.  It is intended for use
+// in low-latency GUIs.
+type What struct {
+	Enclosing  []SyntaxNode `json:"enclosing"`            // enclosing nodes of syntax tree
+	Modes      []string     `json:"modes"`                // query modes enabled for this selection.
+	SrcDir     string       `json:"srcdir,omitempty"`     // $GOROOT src directory containing queried package
+	ImportPath string       `json:"importpath,omitempty"` // import path of queried package
+}
+
+// A PointsToLabel describes a pointer analysis label.
+//
+// A "label" is an object that may be pointed to by a pointer, map,
+// channel, 'func', slice or interface.  Labels include:
+//    - functions
+//    - globals
+//    - arrays created by literals (e.g. []byte("foo")) and conversions ([]byte(s))
+//    - stack- and heap-allocated variables (including composite literals)
+//    - arrays allocated by append()
+//    - channels, maps and arrays created by make()
+//    - and their subelements, e.g. "alloc.y[*].z"
+//
+type PointsToLabel struct {
+	Pos  string `json:"pos"`  // location of syntax that allocated the object
+	Desc string `json:"desc"` // description of the label
+}
+
+// A PointsTo is one element of the result of a 'pointsto' query on an
+// expression.  It describes a single pointer: its type and the set of
+// "labels" it points to.
+//
+// If the pointer is of interface type, it will have one PTS entry
+// describing each concrete type that it may contain.  For each
+// concrete type that is a pointer, the PTS entry describes the labels
+// it may point to.  The same is true for reflect.Values, except the
+// dynamic types needn't be concrete.
+//
+type PointsTo struct {
+	Type    string          `json:"type"`              // (concrete) type of the pointer
+	NamePos string          `json:"namepos,omitempty"` // location of type defn, if Named
+	Labels  []PointsToLabel `json:"labels,omitempty"`  // pointed-to objects
+}
+
+// A DescribeValue is the additional result of a 'describe' query
+// if the selection indicates a value or expression.
+type DescribeValue struct {
+	Type   string `json:"type"`             // type of the expression
+	Value  string `json:"value,omitempty"`  // value of the expression, if constant
+	ObjPos string `json:"objpos,omitempty"` // location of the definition, if an Ident
+}
+
+type DescribeMethod struct {
+	Name string `json:"name"` // method name, as defined by types.Selection.String()
+	Pos  string `json:"pos"`  // location of the method's definition
+}
+
+// A DescribeType is the additional result of a 'describe' query
+// if the selection indicates a type.
+type DescribeType struct {
+	Type    string           `json:"type"`              // the string form of the type
+	NamePos string           `json:"namepos,omitempty"` // location of definition of type, if named
+	NameDef string           `json:"namedef,omitempty"` // underlying definition of type, if named
+	Methods []DescribeMethod `json:"methods,omitempty"` // methods of the type
+}
+
+type DescribeMember struct {
+	Name    string           `json:"name"`              // name of member
+	Type    string           `json:"type,omitempty"`    // type of member (underlying, if 'type')
+	Value   string           `json:"value,omitempty"`   // value of member (if 'const')
+	Pos     string           `json:"pos"`               // location of definition of member
+	Kind    string           `json:"kind"`              // one of {var,const,func,type}
+	Methods []DescribeMethod `json:"methods,omitempty"` // methods (if member is a type)
+}
+
+// A DescribePackage is the additional result of a 'describe' if
+// the selection indicates a package.
+type DescribePackage struct {
+	Path    string            `json:"path"`              // import path of the package
+	Members []*DescribeMember `json:"members,omitempty"` // accessible members of the package
+}
+
+// A Describe is the result of a 'describe' query.
+// It may contain an element describing the selected semantic entity
+// in detail.
+type Describe struct {
+	Desc   string `json:"desc"`             // description of the selected syntax node
+	Pos    string `json:"pos"`              // location of the selected syntax node
+	Detail string `json:"detail,omitempty"` // one of {package, type, value}, or "".
+
+	// At most one of the following fields is populated:
+	// the one specified by 'detail'.
+	Package *DescribePackage `json:"package,omitempty"`
+	Type    *DescribeType    `json:"type,omitempty"`
+	Value   *DescribeValue   `json:"value,omitempty"`
+}
+
+type PTAWarning struct {
+	Pos     string `json:"pos"`     // location associated with warning
+	Message string `json:"message"` // warning message
+}
+
+// A Result is the common result of any oracle query.
+// It contains a query-specific result element.
+//
+// TODO(adonovan): perhaps include other info such as: analysis scope,
+// raw query position, stack of ast nodes, query package, etc.
+type Result struct {
+	Mode string `json:"mode"` // mode of the query
+
+	// Exactly one of the following fields is populated:
+	// the one specified by 'mode'.
+	Callees    *Callees    `json:"callees,omitempty"`
+	Callers    []Caller    `json:"callers,omitempty"`
+	Callgraph  []CallGraph `json:"callgraph,omitempty"`
+	Callstack  *CallStack  `json:"callstack,omitempty"`
+	Definition *Definition `json:"definition,omitempty"`
+	Describe   *Describe   `json:"describe,omitempty"`
+	Freevars   []*FreeVar  `json:"freevars,omitempty"`
+	Implements *Implements `json:"implements,omitempty"`
+	Peers      *Peers      `json:"peers,omitempty"`
+	PointsTo   []PointsTo  `json:"pointsto,omitempty"`
+	Referrers  *Referrers  `json:"referrers,omitempty"`
+	What       *What       `json:"what,omitempty"`
+
+	Warnings []PTAWarning `json:"warnings,omitempty"` // warnings from pointer analysis
+}
diff --git a/third_party/go.tools/oracle/testdata/src/lib/lib.go b/third_party/go.tools/oracle/testdata/src/lib/lib.go
new file mode 100644
index 0000000..0603d4b
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/lib/lib.go
@@ -0,0 +1,14 @@
+package lib
+
+type Type int
+
+func (Type) Method(x *int) *int {
+	return x
+}
+
+func Func() {
+}
+
+const Const = 3
+
+var Var = 0
diff --git a/third_party/go.tools/oracle/testdata/src/main/callgraph-json.go b/third_party/go.tools/oracle/testdata/src/main/callgraph-json.go
new file mode 100644
index 0000000..33708fd
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/callgraph-json.go
@@ -0,0 +1,54 @@
+package main
+
+// Tests of call-graph queries, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See callgraph-json.golden for expected query results.
+
+func A() {}
+
+func B() {}
+
+// call is not (yet) treated context-sensitively.
+func call(f func()) {
+	f()
+}
+
+// nop *is* treated context-sensitively.
+func nop() {}
+
+func call2(f func()) {
+	f()
+	f()
+}
+
+func main() {
+	call(A)
+	call(B)
+
+	nop()
+	nop()
+
+	call2(func() {
+		// called twice from main.call2,
+		// but call2 is not context sensitive (yet).
+	})
+
+	print("builtin")
+	_ = string("type conversion")
+	call(nil)
+	if false {
+		main()
+	}
+	var nilFunc func()
+	nilFunc()
+	var i interface {
+		f()
+	}
+	i.f()
+}
+
+func deadcode() {
+	main()
+}
+
+// @callgraph callgraph "^"
diff --git a/third_party/go.tools/oracle/testdata/src/main/callgraph-json.golden b/third_party/go.tools/oracle/testdata/src/main/callgraph-json.golden
new file mode 100644
index 0000000..7d99870
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/callgraph-json.golden
@@ -0,0 +1,51 @@
+-------- @callgraph callgraph --------
+{
+	"mode": "callgraph",
+	"callgraph": [
+		{
+			"name": "main.main",
+			"pos": "testdata/src/main/callgraph-json.go:24:6",
+			"children": [
+				0,
+				1,
+				2,
+				3
+			]
+		},
+		{
+			"name": "main.call",
+			"pos": "testdata/src/main/callgraph-json.go:12:6",
+			"children": [
+				5,
+				6
+			]
+		},
+		{
+			"name": "main.nop",
+			"pos": "testdata/src/main/callgraph-json.go:17:6"
+		},
+		{
+			"name": "main.call2",
+			"pos": "testdata/src/main/callgraph-json.go:19:6",
+			"children": [
+				7
+			]
+		},
+		{
+			"name": "main.init",
+			"pos": "-"
+		},
+		{
+			"name": "main.A",
+			"pos": "testdata/src/main/callgraph-json.go:7:6"
+		},
+		{
+			"name": "main.B",
+			"pos": "testdata/src/main/callgraph-json.go:9:6"
+		},
+		{
+			"name": "main.main$1",
+			"pos": "testdata/src/main/callgraph-json.go:31:8"
+		}
+	]
+}
\ No newline at end of file
diff --git a/third_party/go.tools/oracle/testdata/src/main/callgraph.go b/third_party/go.tools/oracle/testdata/src/main/callgraph.go
new file mode 100644
index 0000000..ee190df
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/callgraph.go
@@ -0,0 +1,60 @@
+package main
+
+// Tests of call-graph queries.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See callgraph.golden for expected query results.
+
+import "lib"
+
+func A() {}
+
+func B() {}
+
+// call is not (yet) treated context-sensitively.
+func call(f func()) {
+	f()
+}
+
+// nop *is* treated context-sensitively.
+func nop() {}
+
+func call2(f func()) {
+	f()
+	f()
+}
+
+func main() {
+	call(A)
+	call(B)
+
+	nop()
+	nop()
+
+	call2(func() {
+		// called twice from main.call2,
+		// but call2 is not context sensitive (yet).
+	})
+
+	print("builtin")
+	_ = string("type conversion")
+	call(nil)
+	if false {
+		main()
+	}
+	var nilFunc func()
+	nilFunc()
+	var i interface {
+		f()
+	}
+	i.f()
+
+	lib.Func()
+}
+
+func deadcode() {
+	main()
+}
+
+// @callgraph callgraph-main "^"
+
+// @callgraph callgraph-complete "nopos"
diff --git a/third_party/go.tools/oracle/testdata/src/main/callgraph.golden b/third_party/go.tools/oracle/testdata/src/main/callgraph.golden
new file mode 100644
index 0000000..697c857
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/callgraph.golden
@@ -0,0 +1,37 @@
+-------- @callgraph callgraph-main --------
+
+Below is a call graph of package main.
+The numbered nodes form a spanning tree.
+Non-numbered nodes indicate back- or cross-edges to the node whose
+ number follows in parentheses.
+
+0	init
+1	main
+2	    call
+3	        A
+4	        B
+5	    call2
+6	        main$1
+	    main (1)
+7	    nop
+
+-------- @callgraph callgraph-complete --------
+
+Below is a call graph of the entire program.
+The numbered nodes form a spanning tree.
+Non-numbered nodes indicate back- or cross-edges to the node whose
+ number follows in parentheses.
+
+0	<root>
+1	    main.init
+2	        lib.init
+3	    main.main
+4	        lib.Func
+5	        main.call
+6	            main.A
+7	            main.B
+8	        main.call2
+9	            main.main$1
+	        main.main (3)
+10	        main.nop
+
diff --git a/third_party/go.tools/oracle/testdata/src/main/callgraph2.go b/third_party/go.tools/oracle/testdata/src/main/callgraph2.go
new file mode 100644
index 0000000..5da4c88
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/callgraph2.go
@@ -0,0 +1,16 @@
+package main
+
+// Tests of call-graph queries.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See callgraph2.golden for expected query results.
+
+// (Regression test for pointer analysis: programs that use reflection
+// create some cgnodes before the root of the callgraph.)
+import _ "reflect"
+
+func f() {}
+func main() {
+	f()
+}
+
+// @callgraph callgraph "^"
diff --git a/third_party/go.tools/oracle/testdata/src/main/callgraph2.golden b/third_party/go.tools/oracle/testdata/src/main/callgraph2.golden
new file mode 100644
index 0000000..1208b56
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/callgraph2.golden
@@ -0,0 +1,11 @@
+-------- @callgraph callgraph --------
+
+Below is a call graph of package main.
+The numbered nodes form a spanning tree.
+Non-numbered nodes indicate back- or cross-edges to the node whose
+ number follows in parentheses.
+
+0	init
+1	main
+2	    f
+
diff --git a/third_party/go.tools/oracle/testdata/src/main/calls-json.go b/third_party/go.tools/oracle/testdata/src/main/calls-json.go
new file mode 100644
index 0000000..1c7a6c9
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/calls-json.go
@@ -0,0 +1,16 @@
+package main
+
+// Tests of call-graph queries, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See calls-json.golden for expected query results.
+
+func call(f func()) {
+	f() // @callees @callees-f "f"
+}
+
+func main() {
+	call(func() {
+		// @callers callers-main.anon "^"
+		// @callstack callstack-main.anon "^"
+	})
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/calls-json.golden b/third_party/go.tools/oracle/testdata/src/main/calls-json.golden
new file mode 100644
index 0000000..435db7e
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/calls-json.golden
@@ -0,0 +1,33 @@
+-------- @callees @callees-f --------
+{
+	"mode": "callees",
+	"callees": {
+		"pos": "testdata/src/main/calls-json.go:8:3",
+		"desc": "dynamic function call",
+		"callees": [
+			{
+				"name": "main.main$1",
+				"pos": "testdata/src/main/calls-json.go:12:7"
+			}
+		]
+	}
+}-------- @callstack callstack-main.anon --------
+{
+	"mode": "callstack",
+	"callstack": {
+		"pos": "testdata/src/main/calls-json.go:12:7",
+		"target": "main.main$1",
+		"callers": [
+			{
+				"pos": "testdata/src/main/calls-json.go:8:3",
+				"desc": "dynamic function call",
+				"caller": "main.call"
+			},
+			{
+				"pos": "testdata/src/main/calls-json.go:12:6",
+				"desc": "static function call",
+				"caller": "main.main"
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/third_party/go.tools/oracle/testdata/src/main/calls.go b/third_party/go.tools/oracle/testdata/src/main/calls.go
new file mode 100644
index 0000000..7c54e0e
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/calls.go
@@ -0,0 +1,100 @@
+package main
+
+// Tests of call-graph queries.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See calls.golden for expected query results.
+
+func A(x *int) { // @pointsto pointsto-A-x "x"
+	// @callers callers-A "^"
+	// @callstack callstack-A "^"
+}
+
+func B(x *int) { // @pointsto pointsto-B-x "x"
+	// @callers callers-B "^"
+}
+
+// apply is not (yet) treated context-sensitively.
+func apply(f func(x *int), x *int) {
+	f(x) // @callees callees-apply "f"
+	// @callers callers-apply "^"
+}
+
+// store *is* treated context-sensitively,
+// so the points-to sets for pc, pd are precise.
+func store(ptr **int, value *int) {
+	*ptr = value
+	// @callers callers-store "^"
+}
+
+func call(f func() *int) {
+	// Result points to anon function.
+	f() // @pointsto pointsto-result-f "f"
+
+	// Target of call is anon function.
+	f() // @callees callees-main.call-f "f"
+
+	// @callers callers-main.call "^"
+}
+
+func main() {
+	var a, b int
+	apply(A, &a) // @callees callees-main-apply1 "app"
+	apply(B, &b)
+
+	var c, d int
+	var pc, pd *int // @pointsto pointsto-pc "pc"
+	store(&pc, &c)
+	store(&pd, &d)
+	_ = pd // @pointsto pointsto-pd "pd"
+
+	call(func() *int {
+		// We are called twice from main.call
+		// @callers callers-main.anon "^"
+		return &a
+	})
+
+	// Errors
+	_ = "no function call here"   // @callees callees-err-no-call "no"
+	print("builtin")              // @callees callees-err-builtin "builtin"
+	_ = string("type conversion") // @callees callees-err-conversion "str"
+	call(nil)                     // @callees callees-err-bad-selection "call\\(nil"
+	if false {
+		main() // @callees callees-err-deadcode1 "main"
+	}
+	var nilFunc func()
+	nilFunc() // @callees callees-err-nil-func "nilFunc"
+	var i interface {
+		f()
+	}
+	i.f() // @callees callees-err-nil-interface "i.f"
+
+	i = new(myint)
+	i.f() // @callees callees-not-a-wrapper "f"
+}
+
+type myint int
+
+func (myint) f() {
+	// @callers callers-not-a-wrapper "^"
+}
+
+var dynamic = func() {}
+
+func deadcode() {
+	main() // @callees callees-err-deadcode2 "main"
+	// @callers callers-err-deadcode "^"
+	// @callstack callstack-err-deadcode "^"
+
+	// Within dead code, dynamic calls have no callees.
+	dynamic() // @callees callees-err-deadcode3 "dynamic"
+}
+
+// This code belongs to init.
+var global = 123 // @callers callers-global "global"
+
+// The package initializer may be called by other packages' inits, or
+// in this case, the root of the callgraph.  The source-level init functions
+// are in turn called by it.
+func init() {
+	// @callstack callstack-init "^"
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/calls.golden b/third_party/go.tools/oracle/testdata/src/main/calls.golden
new file mode 100644
index 0000000..c06f0e8
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/calls.golden
@@ -0,0 +1,109 @@
+-------- @pointsto pointsto-A-x --------
+this *int may point to these objects:
+	a
+	b
+
+-------- @callstack callstack-A --------
+Found a call path from root to main.A
+main.A
+dynamic function call from main.apply
+static function call from main.main
+
+-------- @pointsto pointsto-B-x --------
+this *int may point to these objects:
+	a
+	b
+
+-------- @callers callers-B --------
+main.B is called from these 1 sites:
+	dynamic function call from main.apply
+
+-------- @callees callees-apply --------
+this dynamic function call dispatches to:
+	main.A
+	main.B
+
+-------- @callers callers-apply --------
+main.apply is called from these 2 sites:
+	static function call from main.main
+	static function call from main.main
+
+-------- @callers callers-store --------
+main.store is called from these 2 sites:
+	static function call from main.main
+	static function call from main.main
+
+-------- @pointsto pointsto-result-f --------
+this func() *int may point to these objects:
+	main.main$1
+
+-------- @callees callees-main.call-f --------
+this dynamic function call dispatches to:
+	main.main$1
+
+-------- @callers callers-main.call --------
+main.call is called from these 2 sites:
+	static function call from main.main
+	static function call from main.main
+
+-------- @callees callees-main-apply1 --------
+this static function call dispatches to:
+	main.apply
+
+-------- @pointsto pointsto-pc --------
+this *int may point to these objects:
+	c
+
+-------- @pointsto pointsto-pd --------
+this *int may point to these objects:
+	d
+
+-------- @callees callees-err-no-call --------
+
+Error: there is no function call here
+-------- @callees callees-err-builtin --------
+
+Error: this is a call to the built-in 'print' operator
+-------- @callees callees-err-conversion --------
+
+Error: this is a type conversion, not a function call
+-------- @callees callees-err-bad-selection --------
+
+Error: ambiguous selection within function call (or conversion)
+-------- @callees callees-err-deadcode1 --------
+this static function call dispatches to:
+	main.main
+
+-------- @callees callees-err-nil-func --------
+dynamic function call on nil value
+
+-------- @callees callees-err-nil-interface --------
+dynamic method call on nil value
+
+-------- @callees callees-not-a-wrapper --------
+this dynamic method call dispatches to:
+	(main.myint).f
+
+-------- @callers callers-not-a-wrapper --------
+(main.myint).f is called from these 1 sites:
+	dynamic method call from main.main
+
+-------- @callees callees-err-deadcode2 --------
+this static function call dispatches to:
+	main.main
+
+-------- @callstack callstack-err-deadcode --------
+main.deadcode is unreachable in this analysis scope
+
+-------- @callees callees-err-deadcode3 --------
+
+Error: this call site is unreachable in this analysis
+-------- @callers callers-global --------
+main.init is called from these 1 sites:
+the root of the call graph
+
+-------- @callstack callstack-init --------
+Found a call path from root to main.init#1
+main.init#1
+static function call from main.init
+
diff --git a/third_party/go.tools/oracle/testdata/src/main/describe-json.go b/third_party/go.tools/oracle/testdata/src/main/describe-json.go
new file mode 100644
index 0000000..1f22d01
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/describe-json.go
@@ -0,0 +1,29 @@
+package describe // @describe pkgdecl "describe"
+
+// Tests of 'describe' query, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See describe-json.golden for expected query results.
+
+func main() { //
+	var s struct{ x [3]int }
+	p := &s.x[0] // @describe desc-val-p "p"
+	_ = p
+
+	var i I = C(0)
+	if i == nil {
+		i = new(D)
+	}
+	print(i) // @describe desc-val-i "\\bi\\b"
+
+	go main() // @describe desc-stmt "go"
+}
+
+type I interface {
+	f()
+}
+
+type C int // @describe desc-type-C "C"
+type D struct{}
+
+func (c C) f()  {}
+func (d *D) f() {}
diff --git a/third_party/go.tools/oracle/testdata/src/main/describe-json.golden b/third_party/go.tools/oracle/testdata/src/main/describe-json.golden
new file mode 100644
index 0000000..8baf837
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/describe-json.golden
@@ -0,0 +1,107 @@
+-------- @describe pkgdecl --------
+{
+	"mode": "describe",
+	"describe": {
+		"desc": "definition of package \"describe\"",
+		"pos": "testdata/src/main/describe-json.go:1:9",
+		"detail": "package",
+		"package": {
+			"path": "describe",
+			"members": [
+				{
+					"name": "C",
+					"type": "int",
+					"pos": "testdata/src/main/describe-json.go:25:6",
+					"kind": "type",
+					"methods": [
+						{
+							"name": "method (C) f()",
+							"pos": "testdata/src/main/describe-json.go:28:12"
+						}
+					]
+				},
+				{
+					"name": "D",
+					"type": "struct{}",
+					"pos": "testdata/src/main/describe-json.go:26:6",
+					"kind": "type",
+					"methods": [
+						{
+							"name": "method (*D) f()",
+							"pos": "testdata/src/main/describe-json.go:29:13"
+						}
+					]
+				},
+				{
+					"name": "I",
+					"type": "interface{f()}",
+					"pos": "testdata/src/main/describe-json.go:21:6",
+					"kind": "type",
+					"methods": [
+						{
+							"name": "method (I) f()",
+							"pos": "testdata/src/main/describe-json.go:22:2"
+						}
+					]
+				},
+				{
+					"name": "main",
+					"type": "func()",
+					"pos": "testdata/src/main/describe-json.go:7:6",
+					"kind": "func"
+				}
+			]
+		}
+	}
+}-------- @describe desc-val-p --------
+{
+	"mode": "describe",
+	"describe": {
+		"desc": "identifier",
+		"pos": "testdata/src/main/describe-json.go:9:2",
+		"detail": "value",
+		"value": {
+			"type": "*int",
+			"objpos": "testdata/src/main/describe-json.go:9:2"
+		}
+	}
+}-------- @describe desc-val-i --------
+{
+	"mode": "describe",
+	"describe": {
+		"desc": "identifier",
+		"pos": "testdata/src/main/describe-json.go:16:8",
+		"detail": "value",
+		"value": {
+			"type": "I",
+			"objpos": "testdata/src/main/describe-json.go:12:6"
+		}
+	}
+}-------- @describe desc-stmt --------
+{
+	"mode": "describe",
+	"describe": {
+		"desc": "go statement",
+		"pos": "testdata/src/main/describe-json.go:18:2",
+		"detail": "unknown"
+	}
+}-------- @describe desc-type-C --------
+{
+	"mode": "describe",
+	"describe": {
+		"desc": "definition of type C (size 8, align 8)",
+		"pos": "testdata/src/main/describe-json.go:25:6",
+		"detail": "type",
+		"type": {
+			"type": "C",
+			"namepos": "testdata/src/main/describe-json.go:25:6",
+			"namedef": "int",
+			"methods": [
+				{
+					"name": "method (C) f()",
+					"pos": "testdata/src/main/describe-json.go:28:12"
+				}
+			]
+		}
+	}
+}
\ No newline at end of file
diff --git a/third_party/go.tools/oracle/testdata/src/main/describe.go b/third_party/go.tools/oracle/testdata/src/main/describe.go
new file mode 100644
index 0000000..69e0a75
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/describe.go
@@ -0,0 +1,87 @@
+package describe // @describe pkgdecl "describe"
+
+// Tests of 'describe' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See describe.golden for expected query results.
+
+// TODO(adonovan): more coverage of the (extensive) logic.
+
+type cake float64 // @describe type-ref-builtin "float64"
+
+const c = iota // @describe const-ref-iota "iota"
+
+const pi = 3.141     // @describe const-def-pi "pi"
+const pie = cake(pi) // @describe const-def-pie "pie"
+const _ = pi         // @describe const-ref-pi "pi"
+
+var global = new(string) // NB: ssa.Global is indirect, i.e. **string
+
+func main() { // @describe func-def-main "main"
+	// func objects
+	_ = main   // @describe func-ref-main "main"
+	_ = (*C).f // @describe func-ref-*C.f "..C..f"
+	_ = D.f    // @describe func-ref-D.f "D.f"
+	_ = I.f    // @describe func-ref-I.f "I.f"
+	var d D    // @describe type-D "D"
+	var i I    // @describe type-I "I"
+	_ = d.f    // @describe func-ref-d.f "d.f"
+	_ = i.f    // @describe func-ref-i.f "i.f"
+
+	// var objects
+	anon := func() {
+		_ = d // @describe ref-lexical-d "d"
+	}
+	_ = anon   // @describe ref-anon "anon"
+	_ = global // @describe ref-global "global"
+
+	// SSA affords some local flow sensitivity.
+	var a, b int
+	var x = &a // @describe var-def-x-1 "x"
+	_ = x      // @describe var-ref-x-1 "x"
+	x = &b     // @describe var-def-x-2 "x"
+	_ = x      // @describe var-ref-x-2 "x"
+
+	i = new(C) // @describe var-ref-i-C "i"
+	if i != nil {
+		i = D{} // @describe var-ref-i-D "i"
+	}
+	print(i) // @describe var-ref-i "\\bi\\b"
+
+	// const objects
+	const localpi = 3.141     // @describe const-local-pi "localpi"
+	const localpie = cake(pi) // @describe const-local-pie "localpie"
+	const _ = localpi         // @describe const-ref-localpi "localpi"
+
+	// type objects
+	type T int      // @describe type-def-T "T"
+	var three T = 3 // @describe type-ref-T "T"
+	_ = three
+
+	print(1 + 2*3)        // @describe const-expr " 2.3"
+	print(real(1+2i) - 3) // @describe const-expr2 "real.*3"
+
+	m := map[string]*int{"a": &a}
+	mapval, _ := m["a"] // @describe map-lookup,ok "m..a.."
+	_ = mapval          // @describe mapval "mapval"
+	_ = m               // @describe m "m"
+
+	defer main() // @describe defer-stmt "defer"
+	go main()    // @describe go-stmt "go"
+
+	panic(3) // @describe builtin-ref-panic "panic"
+
+	var a2 int // @describe var-decl-stmt "var a2 int"
+	_ = a2
+	var _ int // @describe var-decl-stmt2 "var _ int"
+	var _ int // @describe var-def-blank "_"
+}
+
+type I interface { // @describe def-iface-I "I"
+	f() // @describe def-imethod-I.f "f"
+}
+
+type C int
+type D struct{}
+
+func (c *C) f() {}
+func (d D) f()  {}
diff --git a/third_party/go.tools/oracle/testdata/src/main/describe.golden b/third_party/go.tools/oracle/testdata/src/main/describe.golden
new file mode 100644
index 0000000..3f305d4
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/describe.golden
@@ -0,0 +1,173 @@
+-------- @describe pkgdecl --------
+definition of package "describe"
+	type  C      int
+		method (*C) f()
+	type  D      struct{}
+		method (D) f()
+	type  I      interface{f()}
+		method (I) f()
+	const c      untyped int = 0
+	type  cake   float64
+	var   global *string
+	func  main   func()
+	const pi     untyped float = 3141/1000
+	const pie    cake = 1768225803696341/562949953421312
+
+-------- @describe type-ref-builtin --------
+reference to built-in type float64
+
+-------- @describe const-ref-iota --------
+reference to const iota untyped int of constant value 0
+
+-------- @describe const-def-pi --------
+definition of const pi untyped float
+
+-------- @describe const-def-pie --------
+definition of const pie cake
+
+-------- @describe const-ref-pi --------
+reference to const pi untyped float of constant value 3141/1000
+defined here
+
+-------- @describe func-def-main --------
+definition of func main()
+
+-------- @describe func-ref-main --------
+reference to func main()
+defined here
+
+-------- @describe func-ref-*C.f --------
+reference to method func (*C).f()
+defined here
+
+-------- @describe func-ref-D.f --------
+reference to method func (D).f()
+defined here
+
+-------- @describe func-ref-I.f --------
+reference to interface method func (I).f()
+defined here
+
+-------- @describe type-D --------
+reference to type D (size 0, align 1)
+defined as struct{}
+Method set:
+	method (D) f()
+
+-------- @describe type-I --------
+reference to type I (size 16, align 8)
+defined as interface{f()}
+Method set:
+	method (I) f()
+
+-------- @describe func-ref-d.f --------
+reference to method func (D).f()
+defined here
+
+-------- @describe func-ref-i.f --------
+reference to interface method func (I).f()
+defined here
+
+-------- @describe ref-lexical-d --------
+reference to var d D
+defined here
+
+-------- @describe ref-anon --------
+reference to var anon func()
+defined here
+
+-------- @describe ref-global --------
+reference to var global *string
+defined here
+
+-------- @describe var-def-x-1 --------
+definition of var x *int
+
+-------- @describe var-ref-x-1 --------
+reference to var x *int
+defined here
+
+-------- @describe var-def-x-2 --------
+reference to var x *int
+defined here
+
+-------- @describe var-ref-x-2 --------
+reference to var x *int
+defined here
+
+-------- @describe var-ref-i-C --------
+reference to var i I
+defined here
+
+-------- @describe var-ref-i-D --------
+reference to var i I
+defined here
+
+-------- @describe var-ref-i --------
+reference to var i I
+defined here
+
+-------- @describe const-local-pi --------
+definition of const localpi untyped float
+
+-------- @describe const-local-pie --------
+definition of const localpie cake
+
+-------- @describe const-ref-localpi --------
+reference to const localpi untyped float of constant value 3141/1000
+defined here
+
+-------- @describe type-def-T --------
+definition of type T (size 8, align 8)
+No methods.
+
+-------- @describe type-ref-T --------
+reference to type T (size 8, align 8)
+defined as int
+No methods.
+
+-------- @describe const-expr --------
+binary * operation of constant value 6
+
+-------- @describe const-expr2 --------
+binary - operation of constant value -2
+
+-------- @describe map-lookup,ok --------
+index expression of type (*int, bool)
+
+-------- @describe mapval --------
+reference to var mapval *int
+defined here
+
+-------- @describe m --------
+reference to var m map[string]*int
+defined here
+
+-------- @describe defer-stmt --------
+defer statement
+
+-------- @describe go-stmt --------
+go statement
+
+-------- @describe builtin-ref-panic --------
+function call (or conversion) of type ()
+
+-------- @describe var-decl-stmt --------
+definition of var a2 int
+
+-------- @describe var-decl-stmt2 --------
+definition of var _ int
+
+-------- @describe var-def-blank --------
+definition of var _ int
+
+-------- @describe def-iface-I --------
+definition of type I (size 16, align 8)
+Method set:
+	method (I) f()
+
+-------- @describe def-imethod-I.f --------
+type interface{f()}
+Method set:
+	method (interface{f()}) f()
+
diff --git a/third_party/go.tools/oracle/testdata/src/main/freevars.go b/third_party/go.tools/oracle/testdata/src/main/freevars.go
new file mode 100644
index 0000000..1ce0ae6
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/freevars.go
@@ -0,0 +1,41 @@
+package main
+
+// Tests of 'freevars' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See freevars.golden for expected query results.
+
+// TODO(adonovan): it's hard to test this query in a single line of gofmt'd code.
+
+type T struct {
+	a, b int
+}
+
+type S struct {
+	x int
+	t T
+}
+
+func f(int) {}
+
+func main() {
+	type C int
+	x := 1
+	const exp = 6
+	if y := 2; x+y+int(C(3)) != exp { // @freevars fv1 "if.*{"
+		panic("expected 6")
+	}
+
+	var s S
+
+	for x, y := range "foo" {
+		println(s.x + s.t.a + s.t.b + x + int(y)) // @freevars fv2 "print.*y."
+	}
+
+	f(x) // @freevars fv3 "f.x."
+
+	// TODO(adonovan): enable when go/types supports labels.
+loop: // #@freevars fv-def-label "loop:"
+	for {
+		break loop // #@freevars fv-ref-label "break loop"
+	}
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/freevars.golden b/third_party/go.tools/oracle/testdata/src/main/freevars.golden
new file mode 100644
index 0000000..b9eeab2
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/freevars.golden
@@ -0,0 +1,18 @@
+-------- @freevars fv1 --------
+Free identifiers:
+type C
+const exp int
+var x int
+
+-------- @freevars fv2 --------
+Free identifiers:
+var s.t.a int
+var s.t.b int
+var s.x int
+var x int
+var y rune
+
+-------- @freevars fv3 --------
+Free identifiers:
+var x int
+
diff --git a/third_party/go.tools/oracle/testdata/src/main/implements-json.go b/third_party/go.tools/oracle/testdata/src/main/implements-json.go
new file mode 100644
index 0000000..d5f8102
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/implements-json.go
@@ -0,0 +1,27 @@
+package main
+
+// Tests of 'implements' query, -output=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See implements.golden for expected query results.
+
+func main() {
+}
+
+type E interface{} // @implements E "E"
+
+type F interface { // @implements F "F"
+	f()
+}
+
+type FG interface { // @implements FG "FG"
+	f()
+	g() []int // @implements slice "..int"
+}
+
+type C int // @implements C "C"
+type D struct{}
+
+func (c *C) f() {} // @implements starC ".C"
+func (d D) f()  {} // @implements D "D"
+
+func (d *D) g() []int { return nil } // @implements starD ".D"
diff --git a/third_party/go.tools/oracle/testdata/src/main/implements-json.golden b/third_party/go.tools/oracle/testdata/src/main/implements-json.golden
new file mode 100644
index 0000000..d43969b
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/implements-json.golden
@@ -0,0 +1,152 @@
+-------- @implements E --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "main.E",
+			"pos": "testdata/src/main/implements-json.go:10:6",
+			"kind": "interface"
+		}
+	}
+}-------- @implements F --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "main.F",
+			"pos": "testdata/src/main/implements-json.go:12:6",
+			"kind": "interface"
+		},
+		"to": [
+			{
+				"name": "*main.C",
+				"pos": "testdata/src/main/implements-json.go:21:6",
+				"kind": "pointer"
+			},
+			{
+				"name": "main.D",
+				"pos": "testdata/src/main/implements-json.go:22:6",
+				"kind": "struct"
+			},
+			{
+				"name": "main.FG",
+				"pos": "testdata/src/main/implements-json.go:16:6",
+				"kind": "interface"
+			}
+		]
+	}
+}-------- @implements FG --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "main.FG",
+			"pos": "testdata/src/main/implements-json.go:16:6",
+			"kind": "interface"
+		},
+		"to": [
+			{
+				"name": "*main.D",
+				"pos": "testdata/src/main/implements-json.go:22:6",
+				"kind": "pointer"
+			}
+		],
+		"from": [
+			{
+				"name": "main.F",
+				"pos": "testdata/src/main/implements-json.go:12:6",
+				"kind": "interface"
+			}
+		]
+	}
+}-------- @implements slice --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "[]int",
+			"pos": "-",
+			"kind": "slice"
+		}
+	}
+}-------- @implements C --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "main.C",
+			"pos": "testdata/src/main/implements-json.go:21:6",
+			"kind": "basic"
+		},
+		"fromptr": [
+			{
+				"name": "main.F",
+				"pos": "testdata/src/main/implements-json.go:12:6",
+				"kind": "interface"
+			}
+		]
+	}
+}-------- @implements starC --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "*main.C",
+			"pos": "testdata/src/main/implements-json.go:21:6",
+			"kind": "pointer"
+		},
+		"from": [
+			{
+				"name": "main.F",
+				"pos": "testdata/src/main/implements-json.go:12:6",
+				"kind": "interface"
+			}
+		]
+	}
+}-------- @implements D --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "main.D",
+			"pos": "testdata/src/main/implements-json.go:22:6",
+			"kind": "struct"
+		},
+		"from": [
+			{
+				"name": "main.F",
+				"pos": "testdata/src/main/implements-json.go:12:6",
+				"kind": "interface"
+			}
+		],
+		"fromptr": [
+			{
+				"name": "main.FG",
+				"pos": "testdata/src/main/implements-json.go:16:6",
+				"kind": "interface"
+			}
+		]
+	}
+}-------- @implements starD --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "*main.D",
+			"pos": "testdata/src/main/implements-json.go:22:6",
+			"kind": "pointer"
+		},
+		"from": [
+			{
+				"name": "main.F",
+				"pos": "testdata/src/main/implements-json.go:12:6",
+				"kind": "interface"
+			},
+			{
+				"name": "main.FG",
+				"pos": "testdata/src/main/implements-json.go:16:6",
+				"kind": "interface"
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/third_party/go.tools/oracle/testdata/src/main/implements.go b/third_party/go.tools/oracle/testdata/src/main/implements.go
new file mode 100644
index 0000000..0b5ee12
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/implements.go
@@ -0,0 +1,40 @@
+package main
+
+// Tests of 'implements' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See implements.golden for expected query results.
+
+import _ "lib"
+import _ "sort"
+
+func main() {
+}
+
+type E interface{} // @implements E "E"
+
+type F interface { // @implements F "F"
+	f()
+}
+
+type FG interface { // @implements FG "FG"
+	f()
+	g() []int // @implements slice "..int"
+}
+
+type C int // @implements C "C"
+type D struct{}
+
+func (c *C) f() {} // @implements starC ".C"
+func (d D) f()  {} // @implements D "D"
+
+func (d *D) g() []int { return nil } // @implements starD ".D"
+
+type sorter []int // @implements sorter "sorter"
+
+func (sorter) Len() int           { return 0 }
+func (sorter) Less(i, j int) bool { return false }
+func (sorter) Swap(i, j int)      {}
+
+type I interface { // @implements I "I"
+	Method(*int) *int
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/implements.golden b/third_party/go.tools/oracle/testdata/src/main/implements.golden
new file mode 100644
index 0000000..01d41f6
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/implements.golden
@@ -0,0 +1,44 @@
+-------- @implements E --------
+empty interface type main.E
+
+-------- @implements F --------
+interface type main.F
+	is implemented by pointer type *main.C
+	is implemented by struct type main.D
+	is implemented by interface type main.FG
+
+-------- @implements FG --------
+interface type main.FG
+	is implemented by pointer type *main.D
+	implements main.F
+
+-------- @implements slice --------
+slice type []int implements only interface{}
+
+-------- @implements C --------
+pointer type *main.C
+	implements main.F
+
+-------- @implements starC --------
+pointer type *main.C
+	implements main.F
+
+-------- @implements D --------
+struct type main.D
+	implements main.F
+pointer type *main.D
+	implements main.FG
+
+-------- @implements starD --------
+pointer type *main.D
+	implements main.F
+	implements main.FG
+
+-------- @implements sorter --------
+slice type main.sorter
+	implements sort.Interface
+
+-------- @implements I --------
+interface type main.I
+	is implemented by basic type lib.Type
+
diff --git a/third_party/go.tools/oracle/testdata/src/main/imports.go b/third_party/go.tools/oracle/testdata/src/main/imports.go
new file mode 100644
index 0000000..2f5ffa4
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/imports.go
@@ -0,0 +1,29 @@
+package imports
+
+import (
+	"hash/fnv" // @describe ref-pkg-import2 "fnv"
+	"lib"      // @describe ref-pkg-import "lib"
+)
+
+// Tests that import another package.  (To make the tests run quickly,
+// we avoid using imports in all the other tests.  Remember, each
+// query causes parsing and typechecking of the whole program.)
+//
+// See go.tools/oracle/oracle_test.go for explanation.
+// See imports.golden for expected query results.
+
+var a int
+
+func main() {
+	const c = lib.Const // @describe ref-const "Const"
+	lib.Func()          // @describe ref-func "Func"
+	lib.Var++           // @describe ref-var "Var"
+	var t lib.Type      // @describe ref-type "Type"
+	p := t.Method(&a)   // @describe ref-method "Method"
+
+	print(*p + 1) // @pointsto p "p "
+
+	var _ lib.Type // @describe ref-pkg "lib"
+
+	fnv.New32()
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/imports.golden b/third_party/go.tools/oracle/testdata/src/main/imports.golden
new file mode 100644
index 0000000..788a3ad
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/imports.golden
@@ -0,0 +1,49 @@
+-------- @describe ref-pkg-import2 --------
+import of package "hash/fnv"
+	func  New32  func() hash.Hash32
+	func  New32a func() hash.Hash32
+	func  New64  func() hash.Hash64
+	func  New64a func() hash.Hash64
+
+-------- @describe ref-pkg-import --------
+import of package "lib"
+	const Const untyped int = 3
+	func  Func  func()
+	type  Type  int
+		method (Type) Method(x *int) *int
+	var   Var   int
+
+-------- @describe ref-const --------
+reference to const lib.Const untyped int
+defined here
+
+-------- @describe ref-func --------
+reference to func lib.Func()
+defined here
+
+-------- @describe ref-var --------
+reference to var lib.Var int
+defined here
+
+-------- @describe ref-type --------
+reference to type lib.Type (size 8, align 8)
+defined as int
+Method set:
+	method (lib.Type) Method(x *int) *int
+
+-------- @describe ref-method --------
+reference to method func (lib.Type).Method(x *int) *int
+defined here
+
+-------- @pointsto p --------
+this *int may point to these objects:
+	imports.a
+
+-------- @describe ref-pkg --------
+reference to package "lib"
+	const Const untyped int = 3
+	func  Func  func()
+	type  Type  int
+		method (Type) Method(x *int) *int
+	var   Var   int
+
diff --git a/third_party/go.tools/oracle/testdata/src/main/multi.go b/third_party/go.tools/oracle/testdata/src/main/multi.go
new file mode 100644
index 0000000..54caf15
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/multi.go
@@ -0,0 +1,13 @@
+package multi
+
+func g(x int) {
+}
+
+func f() {
+	x := 1
+	g(x) // "g(x)" is the selection for multiple queries
+}
+
+func main() {
+	f()
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/peers-json.go b/third_party/go.tools/oracle/testdata/src/main/peers-json.go
new file mode 100644
index 0000000..1f5beb2
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/peers-json.go
@@ -0,0 +1,13 @@
+package peers
+
+// Tests of channel 'peers' query, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See peers-json.golden for expected query results.
+
+func main() {
+	chA := make(chan *int)
+	<-chA
+	select {
+	case <-chA: // @peers peer-recv-chA "<-"
+	}
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/peers-json.golden b/third_party/go.tools/oracle/testdata/src/main/peers-json.golden
new file mode 100644
index 0000000..80eb3c4
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/peers-json.golden
@@ -0,0 +1,15 @@
+-------- @peers peer-recv-chA --------
+{
+	"mode": "peers",
+	"peers": {
+		"pos": "testdata/src/main/peers-json.go:11:7",
+		"type": "chan *int",
+		"allocs": [
+			"testdata/src/main/peers-json.go:8:13"
+		],
+		"receives": [
+			"testdata/src/main/peers-json.go:9:2",
+			"testdata/src/main/peers-json.go:11:7"
+		]
+	}
+}
\ No newline at end of file
diff --git a/third_party/go.tools/oracle/testdata/src/main/peers.go b/third_party/go.tools/oracle/testdata/src/main/peers.go
new file mode 100644
index 0000000..8370f64
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/peers.go
@@ -0,0 +1,52 @@
+package peers
+
+// Tests of channel 'peers' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See peers.golden for expected query results.
+
+var a2 int
+
+func main() {
+	chA := make(chan *int)
+	a1 := 1
+	chA <- &a1
+
+	chA2 := make(chan *int, 2)
+	if a2 == 0 {
+		chA = chA2
+	}
+
+	chB := make(chan *int)
+	b := 3
+	chB <- &b
+
+	<-chA  // @pointsto pointsto-chA "chA"
+	<-chA2 // @pointsto pointsto-chA2 "chA2"
+	<-chB  // @pointsto pointsto-chB "chB"
+
+	select {
+	case rA := <-chA: // @peers peer-recv-chA "<-"
+		_ = rA // @pointsto pointsto-rA "rA"
+	case rB := <-chB: // @peers peer-recv-chB "<-"
+		_ = rB // @pointsto pointsto-rB "rB"
+
+	case <-chA: // @peers peer-recv-chA' "<-"
+
+	case chA2 <- &a2: // @peers peer-send-chA' "<-"
+	}
+
+	for _ = range chA {
+	}
+
+	close(chA) // @peers peer-close-chA "chA"
+
+	chC := make(chan *int)
+	(close)(chC) // @peers peer-close-chC "chC"
+
+	close := func(ch chan *int) chan *int {
+		return ch
+	}
+
+	close(chC) <- &b // @peers peer-send-chC "chC"
+	<-close(chC)     // @peers peer-recv-chC "chC"
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/peers.golden b/third_party/go.tools/oracle/testdata/src/main/peers.golden
new file mode 100644
index 0000000..f97e672
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/peers.golden
@@ -0,0 +1,100 @@
+-------- @pointsto pointsto-chA --------
+this chan *int may point to these objects:
+	makechan
+	makechan
+
+-------- @pointsto pointsto-chA2 --------
+this chan *int may point to these objects:
+	makechan
+
+-------- @pointsto pointsto-chB --------
+this chan *int may point to these objects:
+	makechan
+
+-------- @peers peer-recv-chA --------
+This channel of type chan *int may be:
+	allocated here
+	allocated here
+	sent to, here
+	sent to, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	closed, here
+
+-------- @pointsto pointsto-rA --------
+this *int may point to these objects:
+	peers.a2
+	a1
+
+-------- @peers peer-recv-chB --------
+This channel of type chan *int may be:
+	allocated here
+	sent to, here
+	received from, here
+	received from, here
+
+-------- @pointsto pointsto-rB --------
+this *int may point to these objects:
+	b
+
+-------- @peers peer-recv-chA' --------
+This channel of type chan *int may be:
+	allocated here
+	allocated here
+	sent to, here
+	sent to, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	closed, here
+
+-------- @peers peer-send-chA' --------
+This channel of type chan *int may be:
+	allocated here
+	sent to, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	closed, here
+
+-------- @peers peer-close-chA --------
+This channel of type chan *int may be:
+	allocated here
+	allocated here
+	sent to, here
+	sent to, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	closed, here
+
+-------- @peers peer-close-chC --------
+This channel of type chan *int may be:
+	allocated here
+	sent to, here
+	received from, here
+	closed, here
+
+-------- @peers peer-send-chC --------
+This channel of type chan *int may be:
+	allocated here
+	sent to, here
+	received from, here
+	closed, here
+
+-------- @peers peer-recv-chC --------
+This channel of type chan *int may be:
+	allocated here
+	sent to, here
+	received from, here
+	closed, here
+
diff --git a/third_party/go.tools/oracle/testdata/src/main/pointsto-json.go b/third_party/go.tools/oracle/testdata/src/main/pointsto-json.go
new file mode 100644
index 0000000..79d7d3d
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/pointsto-json.go
@@ -0,0 +1,27 @@
+package pointsto
+
+// Tests of 'pointsto' queries, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See pointsto-json.golden for expected query results.
+
+func main() { //
+	var s struct{ x [3]int }
+	p := &s.x[0] // @pointsto val-p "p"
+	_ = p
+
+	var i I = C(0)
+	if i == nil {
+		i = new(D)
+	}
+	print(i) // @pointsto val-i "\\bi\\b"
+}
+
+type I interface {
+	f()
+}
+
+type C int
+type D struct{}
+
+func (c C) f()  {}
+func (d *D) f() {}
diff --git a/third_party/go.tools/oracle/testdata/src/main/pointsto-json.golden b/third_party/go.tools/oracle/testdata/src/main/pointsto-json.golden
new file mode 100644
index 0000000..b3f8511
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/pointsto-json.golden
@@ -0,0 +1,34 @@
+-------- @pointsto val-p --------
+{
+	"mode": "pointsto",
+	"pointsto": [
+		{
+			"type": "*int",
+			"labels": [
+				{
+					"pos": "testdata/src/main/pointsto-json.go:8:6",
+					"desc": "s.x[*]"
+				}
+			]
+		}
+	]
+}-------- @pointsto val-i --------
+{
+	"mode": "pointsto",
+	"pointsto": [
+		{
+			"type": "*D",
+			"namepos": "testdata/src/main/pointsto-json.go:24:6",
+			"labels": [
+				{
+					"pos": "testdata/src/main/pointsto-json.go:14:10",
+					"desc": "new"
+				}
+			]
+		},
+		{
+			"type": "C",
+			"namepos": "testdata/src/main/pointsto-json.go:23:6"
+		}
+	]
+}
\ No newline at end of file
diff --git a/third_party/go.tools/oracle/testdata/src/main/pointsto.go b/third_party/go.tools/oracle/testdata/src/main/pointsto.go
new file mode 100644
index 0000000..0657fac
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/pointsto.go
@@ -0,0 +1,75 @@
+package pointsto
+
+// Tests of 'pointsto' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See pointsto.golden for expected query results.
+
+const pi = 3.141 // @pointsto const "pi"
+
+var global = new(string) // NB: ssa.Global is indirect, i.e. **string
+
+func main() {
+	livecode()
+
+	// func objects
+	_ = main   // @pointsto func-ref-main "main"
+	_ = (*C).f // @pointsto func-ref-*C.f "..C..f"
+	_ = D.f    // @pointsto func-ref-D.f "D.f"
+	_ = I.f    // @pointsto func-ref-I.f "I.f"
+	var d D
+	var i I
+	_ = d.f // @pointsto func-ref-d.f "d.f"
+	_ = i.f // @pointsto func-ref-i.f "i.f"
+
+	// var objects
+	anon := func() {
+		_ = d.f // @pointsto ref-lexical-d.f "d.f"
+	}
+	_ = anon   // @pointsto ref-anon "anon"
+	_ = global // @pointsto ref-global "global"
+
+	// SSA affords some local flow sensitivity.
+	var a, b int
+	var x = &a // @pointsto var-def-x-1 "x"
+	_ = x      // @pointsto var-ref-x-1 "x"
+	x = &b     // @pointsto var-def-x-2 "x"
+	_ = x      // @pointsto var-ref-x-2 "x"
+
+	i = new(C) // @pointsto var-ref-i-C "i"
+	if i != nil {
+		i = D{} // @pointsto var-ref-i-D "i"
+	}
+	print(i) // @pointsto var-ref-i "\\bi\\b"
+
+	m := map[string]*int{"a": &a}
+	mapval, _ := m["a"] // @pointsto map-lookup,ok "m..a.."
+	_ = mapval          // @pointsto mapval "mapval"
+	_ = m               // @pointsto m "m"
+
+	if false {
+		panic(3) // @pointsto builtin-panic "panic"
+	}
+
+	// NB: s.f is addressable per (*ssa.Program).VarValue,
+	// but our query concerns the object, not its address.
+	s := struct{ f interface{} }{f: make(chan bool)}
+	print(s.f) // @pointsto var-ref-s-f "s.f"
+}
+
+func livecode() {} // @pointsto func-live "livecode"
+
+func deadcode() { // @pointsto func-dead "deadcode"
+	// Pointer analysis can't run on dead code.
+	var b = new(int) // @pointsto b "b"
+	_ = b
+}
+
+type I interface {
+	f()
+}
+
+type C int
+type D struct{}
+
+func (c *C) f() {}
+func (d D) f()  {}
diff --git a/third_party/go.tools/oracle/testdata/src/main/pointsto.golden b/third_party/go.tools/oracle/testdata/src/main/pointsto.golden
new file mode 100644
index 0000000..7b12b2a
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/pointsto.golden
@@ -0,0 +1,96 @@
+-------- @pointsto const --------
+
+Error: pointer analysis wants an expression of reference type; got untyped float
+-------- @pointsto func-ref-main --------
+this func() may point to these objects:
+	pointsto.main
+
+-------- @pointsto func-ref-*C.f --------
+this func() may point to these objects:
+	(*pointsto.C).f
+
+-------- @pointsto func-ref-D.f --------
+this func() may point to these objects:
+	(pointsto.D).f
+
+-------- @pointsto func-ref-I.f --------
+
+Error: func (pointsto.I).f() is an interface method
+-------- @pointsto func-ref-d.f --------
+this func() may point to these objects:
+	(pointsto.D).f
+
+-------- @pointsto func-ref-i.f --------
+
+Error: func (pointsto.I).f() is an interface method
+-------- @pointsto ref-lexical-d.f --------
+this func() may point to these objects:
+	(pointsto.D).f
+
+-------- @pointsto ref-anon --------
+this func() may point to these objects:
+	pointsto.main$1
+
+-------- @pointsto ref-global --------
+this *string may point to these objects:
+	new
+
+-------- @pointsto var-def-x-1 --------
+this *int may point to these objects:
+	a
+
+-------- @pointsto var-ref-x-1 --------
+this *int may point to these objects:
+	a
+
+-------- @pointsto var-def-x-2 --------
+this *int may point to these objects:
+	b
+
+-------- @pointsto var-ref-x-2 --------
+this *int may point to these objects:
+	b
+
+-------- @pointsto var-ref-i-C --------
+this I may contain these dynamic types:
+	*C, may point to:
+		new
+
+-------- @pointsto var-ref-i-D --------
+this I may contain these dynamic types:
+	D
+
+-------- @pointsto var-ref-i --------
+this I may contain these dynamic types:
+	*C, may point to:
+		new
+	D
+
+-------- @pointsto map-lookup,ok --------
+
+Error: pointer analysis wants an expression of reference type; got (*int, bool)
+-------- @pointsto mapval --------
+this *int may point to these objects:
+	a
+
+-------- @pointsto m --------
+this map[string]*int may point to these objects:
+	makemap
+
+-------- @pointsto builtin-panic --------
+
+Error: pointer analysis wants an expression of reference type; got ()
+-------- @pointsto var-ref-s-f --------
+this interface{} may contain these dynamic types:
+	chan bool, may point to:
+		makechan
+
+-------- @pointsto func-live --------
+
+Error: pointer analysis did not find expression (dead code?)
+-------- @pointsto func-dead --------
+
+Error: pointer analysis did not find expression (dead code?)
+-------- @pointsto b --------
+
+Error: pointer analysis did not find expression (dead code?)
diff --git a/third_party/go.tools/oracle/testdata/src/main/referrers-json.go b/third_party/go.tools/oracle/testdata/src/main/referrers-json.go
new file mode 100644
index 0000000..4799e53
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/referrers-json.go
@@ -0,0 +1,24 @@
+package referrers
+
+// Tests of 'referrers' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See referrers.golden for expected query results.
+
+import "lib"
+
+type s struct {
+	f int
+}
+
+func main() {
+	var v lib.Type = lib.Const // @referrers ref-package "lib"
+	_ = v.Method               // @referrers ref-method "Method"
+	_ = v.Method
+	v++ //@referrers ref-local "v"
+	v++
+
+	_ = s{}.f // @referrers ref-field "f"
+
+	var s2 s
+	s2.f = 1
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/referrers-json.golden b/third_party/go.tools/oracle/testdata/src/main/referrers-json.golden
new file mode 100644
index 0000000..ad7ec1d
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/referrers-json.golden
@@ -0,0 +1,51 @@
+-------- @referrers ref-package --------
+{
+	"mode": "referrers",
+	"referrers": {
+		"pos": "testdata/src/main/referrers-json.go:14:8",
+		"objpos": "testdata/src/main/referrers-json.go:7:8",
+		"desc": "package lib",
+		"refs": [
+			"testdata/src/main/referrers-json.go:14:8",
+			"testdata/src/main/referrers-json.go:14:19"
+		]
+	}
+}-------- @referrers ref-method --------
+{
+	"mode": "referrers",
+	"referrers": {
+		"pos": "testdata/src/main/referrers-json.go:15:8",
+		"objpos": "testdata/src/lib/lib.go:5:13",
+		"desc": "func (lib.Type).Method(x *int) *int",
+		"refs": [
+			"testdata/src/main/referrers-json.go:15:8",
+			"testdata/src/main/referrers-json.go:16:8"
+		]
+	}
+}-------- @referrers ref-local --------
+{
+	"mode": "referrers",
+	"referrers": {
+		"pos": "testdata/src/main/referrers-json.go:17:2",
+		"objpos": "testdata/src/main/referrers-json.go:14:6",
+		"desc": "var v lib.Type",
+		"refs": [
+			"testdata/src/main/referrers-json.go:15:6",
+			"testdata/src/main/referrers-json.go:16:6",
+			"testdata/src/main/referrers-json.go:17:2",
+			"testdata/src/main/referrers-json.go:18:2"
+		]
+	}
+}-------- @referrers ref-field --------
+{
+	"mode": "referrers",
+	"referrers": {
+		"pos": "testdata/src/main/referrers-json.go:20:10",
+		"objpos": "testdata/src/main/referrers-json.go:10:2",
+		"desc": "field f int",
+		"refs": [
+			"testdata/src/main/referrers-json.go:20:10",
+			"testdata/src/main/referrers-json.go:23:5"
+		]
+	}
+}
\ No newline at end of file
diff --git a/third_party/go.tools/oracle/testdata/src/main/reflection.go b/third_party/go.tools/oracle/testdata/src/main/reflection.go
new file mode 100644
index 0000000..b10df0b
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/reflection.go
@@ -0,0 +1,30 @@
+package reflection
+
+// This is a test of 'pointsto', but we split it into a separate file
+// so that pointsto.go doesn't have to import "reflect" each time.
+
+import "reflect"
+
+var a int
+var b bool
+
+func main() {
+	m := make(map[*int]*bool)
+	m[&a] = &b
+
+	mrv := reflect.ValueOf(m)
+	if a > 0 {
+		mrv = reflect.ValueOf(&b)
+	}
+	if a > 0 {
+		mrv = reflect.ValueOf(&a)
+	}
+
+	_ = mrv                  // @pointsto mrv "mrv"
+	p1 := mrv.Interface()    // @pointsto p1 "p1"
+	p2 := mrv.MapKeys()      // @pointsto p2 "p2"
+	p3 := p2[0]              // @pointsto p3 "p3"
+	p4 := reflect.TypeOf(p1) // @pointsto p4 "p4"
+
+	_, _, _, _ = p1, p2, p3, p4
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/reflection.golden b/third_party/go.tools/oracle/testdata/src/main/reflection.golden
new file mode 100644
index 0000000..4782132
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/reflection.golden
@@ -0,0 +1,34 @@
+-------- @pointsto mrv --------
+this reflect.Value may contain these dynamic types:
+	*bool, may point to:
+		reflection.b
+	*int, may point to:
+		reflection.a
+	map[*int]*bool, may point to:
+		makemap
+
+-------- @pointsto p1 --------
+this interface{} may contain these dynamic types:
+	*bool, may point to:
+		reflection.b
+	*int, may point to:
+		reflection.a
+	map[*int]*bool, may point to:
+		makemap
+
+-------- @pointsto p2 --------
+this []reflect.Value may point to these objects:
+	<alloc in (reflect.Value).MapKeys>
+
+-------- @pointsto p3 --------
+this reflect.Value may contain these dynamic types:
+	*int, may point to:
+		reflection.a
+
+-------- @pointsto p4 --------
+this reflect.Type may contain these dynamic types:
+	*reflect.rtype, may point to:
+		*bool
+		*int
+		map[*int]*bool
+
diff --git a/third_party/go.tools/oracle/testdata/src/main/what-json.go b/third_party/go.tools/oracle/testdata/src/main/what-json.go
new file mode 100644
index 0000000..d07a6c9
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/what-json.go
@@ -0,0 +1,9 @@
+package what
+
+// Tests of 'what' queries, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See what-json.golden for expected query results.
+
+func main() {
+	f() // @what call "f"
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/what-json.golden b/third_party/go.tools/oracle/testdata/src/main/what-json.golden
new file mode 100644
index 0000000..13860dd
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/what-json.golden
@@ -0,0 +1,52 @@
+-------- @what call --------
+{
+	"mode": "what",
+	"what": {
+		"enclosing": [
+			{
+				"desc": "identifier",
+				"start": 179,
+				"end": 180
+			},
+			{
+				"desc": "function call (or conversion)",
+				"start": 179,
+				"end": 182
+			},
+			{
+				"desc": "expression statement",
+				"start": 179,
+				"end": 182
+			},
+			{
+				"desc": "block",
+				"start": 176,
+				"end": 202
+			},
+			{
+				"desc": "function declaration",
+				"start": 164,
+				"end": 202
+			},
+			{
+				"desc": "source file",
+				"start": 0,
+				"end": 202
+			}
+		],
+		"modes": [
+			"callees",
+			"callers",
+			"callgraph",
+			"callstack",
+			"definition",
+			"describe",
+			"freevars",
+			"implements",
+			"pointsto",
+			"referrers"
+		],
+		"srcdir": "testdata/src",
+		"importpath": "main"
+	}
+}
\ No newline at end of file
diff --git a/third_party/go.tools/oracle/testdata/src/main/what.go b/third_party/go.tools/oracle/testdata/src/main/what.go
new file mode 100644
index 0000000..041e921
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/what.go
@@ -0,0 +1,11 @@
+package what // @what pkgdecl "what"
+
+// Tests of 'what' queries.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See what.golden for expected query results.
+
+func main() {
+	f()             // @what call "f"
+	var ch chan int // @what var "var"
+	<-ch            // @what recv "ch"
+}
diff --git a/third_party/go.tools/oracle/testdata/src/main/what.golden b/third_party/go.tools/oracle/testdata/src/main/what.golden
new file mode 100644
index 0000000..3f83291
--- /dev/null
+++ b/third_party/go.tools/oracle/testdata/src/main/what.golden
@@ -0,0 +1,39 @@
+-------- @what pkgdecl --------
+identifier
+source file
+modes: [callgraph definition describe freevars implements pointsto referrers]
+srcdir: testdata/src
+import path: main
+
+-------- @what call --------
+identifier
+function call (or conversion)
+expression statement
+block
+function declaration
+source file
+modes: [callees callers callgraph callstack definition describe freevars implements pointsto referrers]
+srcdir: testdata/src
+import path: main
+
+-------- @what var --------
+variable declaration
+variable declaration statement
+block
+function declaration
+source file
+modes: [callers callgraph callstack describe freevars pointsto]
+srcdir: testdata/src
+import path: main
+
+-------- @what recv --------
+identifier
+unary <- operation
+expression statement
+block
+function declaration
+source file
+modes: [callers callgraph callstack definition describe freevars implements peers pointsto referrers]
+srcdir: testdata/src
+import path: main
+
diff --git a/third_party/go.tools/oracle/what.go b/third_party/go.tools/oracle/what.go
new file mode 100644
index 0000000..2aaf6bc
--- /dev/null
+++ b/third_party/go.tools/oracle/what.go
@@ -0,0 +1,216 @@
+// Copyright 2013 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 oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/token"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+	"llvm.org/llgo/third_party/go.tools/oracle/serial"
+)
+
+// what reports all the information about the query selection that can be
+// obtained from parsing only its containing source file.
+// It is intended to be a very low-latency query callable from GUI
+// tools, e.g. to populate a menu of options of slower queries about
+// the selected location.
+//
+func what(posFlag string, buildContext *build.Context) (*Result, error) {
+	qpos, err := fastQueryPos(posFlag)
+	if err != nil {
+		return nil, err
+	}
+
+	// (ignore errors)
+	srcdir, importPath, _ := guessImportPath(qpos.fset.File(qpos.start).Name(), buildContext)
+
+	// Determine which query modes are applicable to the selection.
+	// TODO(adonovan): refactor: make each minfo have an 'enable'
+	// predicate over qpos.
+	enable := map[string]bool{
+		"callgraph": true, // whole program; always enabled
+		"describe":  true, // any syntax; always enabled
+	}
+
+	if qpos.end > qpos.start {
+		enable["freevars"] = true // nonempty selection?
+	}
+
+	for _, n := range qpos.path {
+		switch n := n.(type) {
+		case *ast.Ident:
+			enable["definition"] = true
+			enable["referrers"] = true
+			enable["implements"] = true
+		case *ast.CallExpr:
+			enable["callees"] = true
+		case *ast.FuncDecl:
+			enable["callers"] = true
+			enable["callstack"] = true
+		case *ast.SendStmt:
+			enable["peers"] = true
+		case *ast.UnaryExpr:
+			if n.Op == token.ARROW {
+				enable["peers"] = true
+			}
+		}
+
+		// For implements, we approximate findInterestingNode.
+		if _, ok := enable["implements"]; !ok {
+			switch n.(type) {
+			case *ast.ArrayType,
+				*ast.StructType,
+				*ast.FuncType,
+				*ast.InterfaceType,
+				*ast.MapType,
+				*ast.ChanType:
+				enable["implements"] = true
+			}
+		}
+
+		// For pointsto, we approximate findInterestingNode.
+		if _, ok := enable["pointsto"]; !ok {
+			switch n.(type) {
+			case ast.Stmt,
+				*ast.ArrayType,
+				*ast.StructType,
+				*ast.FuncType,
+				*ast.InterfaceType,
+				*ast.MapType,
+				*ast.ChanType:
+				enable["pointsto"] = false // not an expr
+
+			case ast.Expr, ast.Decl, *ast.ValueSpec:
+				enable["pointsto"] = true // an expr, maybe
+
+			default:
+				// Comment, Field, KeyValueExpr, etc: ascend.
+			}
+		}
+	}
+
+	// If we don't have an exact selection, disable modes that need one.
+	if !qpos.exact {
+		for _, minfo := range modes {
+			if minfo.needs&needExactPos != 0 {
+				enable[minfo.name] = false
+			}
+		}
+	}
+
+	var modes []string
+	for mode := range enable {
+		modes = append(modes, mode)
+	}
+	sort.Strings(modes)
+
+	return &Result{
+		mode: "what",
+		fset: qpos.fset,
+		q: &whatResult{
+			path:       qpos.path,
+			srcdir:     srcdir,
+			importPath: importPath,
+			modes:      modes,
+		},
+	}, nil
+
+}
+
+// guessImportPath finds the package containing filename, and returns
+// its source directory (an element of $GOPATH) and its import path
+// relative to it.
+//
+// TODO(adonovan): what about _test.go files that are not part of the
+// package?
+//
+func guessImportPath(filename string, buildContext *build.Context) (srcdir, importPath string, err error) {
+	absFile, err := filepath.Abs(filename)
+	if err != nil {
+		err = fmt.Errorf("can't form absolute path of %s", filename)
+		return
+	}
+	absFileDir := segments(filepath.Dir(absFile))
+
+	// Find the innermost directory in $GOPATH that encloses filename.
+	minD := 1024
+	for _, gopathDir := range buildContext.SrcDirs() {
+		absDir, err := filepath.Abs(gopathDir)
+		if err != nil {
+			continue // e.g. non-existent dir on $GOPATH
+		}
+		d := prefixLen(segments(absDir), absFileDir)
+		// If there are multiple matches,
+		// prefer the innermost enclosing directory
+		// (smallest d).
+		if d >= 0 && d < minD {
+			minD = d
+			srcdir = gopathDir
+			importPath = strings.Join(absFileDir[len(absFileDir)-minD:], string(os.PathSeparator))
+		}
+	}
+	if srcdir == "" {
+		err = fmt.Errorf("can't find package for file %s", filename)
+	}
+	return
+}
+
+func segments(path string) []string {
+	return strings.Split(path, string(os.PathSeparator))
+}
+
+// prefixLen returns the length of the remainder of y if x is a prefix
+// of y, a negative number otherwise.
+func prefixLen(x, y []string) int {
+	d := len(y) - len(x)
+	if d >= 0 {
+		for i := range x {
+			if y[i] != x[i] {
+				return -1 // not a prefix
+			}
+		}
+	}
+	return d
+}
+
+type whatResult struct {
+	path       []ast.Node
+	modes      []string
+	srcdir     string
+	importPath string
+}
+
+func (r *whatResult) display(printf printfFunc) {
+	for _, n := range r.path {
+		printf(n, "%s", astutil.NodeDescription(n))
+	}
+	printf(nil, "modes: %s", r.modes)
+	printf(nil, "srcdir: %s", r.srcdir)
+	printf(nil, "import path: %s", r.importPath)
+}
+
+func (r *whatResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var enclosing []serial.SyntaxNode
+	for _, n := range r.path {
+		enclosing = append(enclosing, serial.SyntaxNode{
+			Description: astutil.NodeDescription(n),
+			Start:       fset.Position(n.Pos()).Offset,
+			End:         fset.Position(n.End()).Offset,
+		})
+	}
+	res.What = &serial.What{
+		Modes:      r.modes,
+		SrcDir:     r.srcdir,
+		ImportPath: r.importPath,
+		Enclosing:  enclosing,
+	}
+}
diff --git a/third_party/go.tools/playground/appengine.go b/third_party/go.tools/playground/appengine.go
new file mode 100644
index 0000000..073b419
--- /dev/null
+++ b/third_party/go.tools/playground/appengine.go
@@ -0,0 +1,22 @@
+// 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.
+
+// +build appengine
+
+package playground
+
+import (
+	"net/http"
+
+	"appengine"
+	"appengine/urlfetch"
+)
+
+func client(r *http.Request) *http.Client {
+	return urlfetch.Client(appengine.NewContext(r))
+}
+
+func report(r *http.Request, err error) {
+	appengine.NewContext(r).Errorf("%v", err)
+}
diff --git a/third_party/go.tools/playground/common.go b/third_party/go.tools/playground/common.go
new file mode 100644
index 0000000..0551362
--- /dev/null
+++ b/third_party/go.tools/playground/common.go
@@ -0,0 +1,46 @@
+// Copyright 2013 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 playground registers HTTP handlers at "/compile" and "/share" that
+// proxy requests to the golang.org playground service.
+// This package may be used unaltered on App Engine.
+package playground
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"net/http"
+)
+
+const baseURL = "http://play.golang.org"
+
+func init() {
+	http.HandleFunc("/compile", bounce)
+	http.HandleFunc("/share", bounce)
+}
+
+func bounce(w http.ResponseWriter, r *http.Request) {
+	b := new(bytes.Buffer)
+	if err := passThru(b, r); err != nil {
+		http.Error(w, "Server error.", http.StatusInternalServerError)
+		report(r, err)
+		return
+	}
+	io.Copy(w, b)
+}
+
+func passThru(w io.Writer, req *http.Request) error {
+	defer req.Body.Close()
+	url := baseURL + req.URL.Path
+	r, err := client(req).Post(url, req.Header.Get("Content-type"), req.Body)
+	if err != nil {
+		return fmt.Errorf("making POST request: %v", err)
+	}
+	defer r.Body.Close()
+	if _, err := io.Copy(w, r.Body); err != nil {
+		return fmt.Errorf("copying response Body: %v", err)
+	}
+	return nil
+}
diff --git a/third_party/go.tools/playground/local.go b/third_party/go.tools/playground/local.go
new file mode 100644
index 0000000..b114b87
--- /dev/null
+++ b/third_party/go.tools/playground/local.go
@@ -0,0 +1,20 @@
+// 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.
+
+// +build !appengine
+
+package playground
+
+import (
+	"log"
+	"net/http"
+)
+
+func client(r *http.Request) *http.Client {
+	return http.DefaultClient
+}
+
+func report(r *http.Request, err error) {
+	log.Println(err)
+}
diff --git a/third_party/go.tools/playground/socket/socket.go b/third_party/go.tools/playground/socket/socket.go
new file mode 100644
index 0000000..fe1ac9e
--- /dev/null
+++ b/third_party/go.tools/playground/socket/socket.go
@@ -0,0 +1,474 @@
+// 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.
+
+// +build !appengine
+
+// Package socket implements an WebSocket-based playground backend.
+// Clients connect to a websocket handler and send run/kill commands, and
+// the server sends the output and exit status of the running processes.
+// Multiple clients running multiple processes may be served concurrently.
+// The wire format is JSON and is described by the Message type.
+//
+// This will not run on App Engine as WebSockets are not supported there.
+package socket
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/http"
+	"net/url"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+	"unicode/utf8"
+
+	"golang.org/x/net/websocket"
+)
+
+// RunScripts specifies whether the socket handler should execute shell scripts
+// (snippets that start with a shebang).
+var RunScripts = true
+
+// Environ provides an environment when a binary, such as the go tool, is
+// invoked.
+var Environ func() []string = os.Environ
+
+const (
+	// The maximum number of messages to send per session (avoid flooding).
+	msgLimit = 1000
+
+	// Batch messages sent in this interval and send as a single message.
+	msgDelay = 10 * time.Millisecond
+)
+
+// Message is the wire format for the websocket connection to the browser.
+// It is used for both sending output messages and receiving commands, as
+// distinguished by the Kind field.
+type Message struct {
+	Id      string // client-provided unique id for the process
+	Kind    string // in: "run", "kill" out: "stdout", "stderr", "end"
+	Body    string
+	Options *Options `json:",omitempty"`
+}
+
+// Options specify additional message options.
+type Options struct {
+	Race bool // use -race flag when building code (for "run" only)
+}
+
+// NewHandler returns a websocket server which checks the origin of requests.
+func NewHandler(origin *url.URL) websocket.Server {
+	return websocket.Server{
+		Config:    websocket.Config{Origin: origin},
+		Handshake: handshake,
+		Handler:   websocket.Handler(socketHandler),
+	}
+}
+
+// handshake checks the origin of a request during the websocket handshake.
+func handshake(c *websocket.Config, req *http.Request) error {
+	o, err := websocket.Origin(c, req)
+	if err != nil {
+		log.Println("bad websocket origin:", err)
+		return websocket.ErrBadWebSocketOrigin
+	}
+	_, port, err := net.SplitHostPort(c.Origin.Host)
+	if err != nil {
+		log.Println("bad websocket origin:", err)
+		return websocket.ErrBadWebSocketOrigin
+	}
+	ok := c.Origin.Scheme == o.Scheme && (c.Origin.Host == o.Host || c.Origin.Host == net.JoinHostPort(o.Host, port))
+	if !ok {
+		log.Println("bad websocket origin:", o)
+		return websocket.ErrBadWebSocketOrigin
+	}
+	log.Println("accepting connection from:", req.RemoteAddr)
+	return nil
+}
+
+// socketHandler handles the websocket connection for a given present session.
+// It handles transcoding Messages to and from JSON format, and starting
+// and killing processes.
+func socketHandler(c *websocket.Conn) {
+	in, out := make(chan *Message), make(chan *Message)
+	errc := make(chan error, 1)
+
+	// Decode messages from client and send to the in channel.
+	go func() {
+		dec := json.NewDecoder(c)
+		for {
+			var m Message
+			if err := dec.Decode(&m); err != nil {
+				errc <- err
+				return
+			}
+			in <- &m
+		}
+	}()
+
+	// Receive messages from the out channel and encode to the client.
+	go func() {
+		enc := json.NewEncoder(c)
+		for m := range out {
+			if err := enc.Encode(m); err != nil {
+				errc <- err
+				return
+			}
+		}
+	}()
+
+	// Start and kill processes and handle errors.
+	proc := make(map[string]*process)
+	for {
+		select {
+		case m := <-in:
+			switch m.Kind {
+			case "run":
+				log.Println("running snippet from:", c.Request().RemoteAddr)
+				proc[m.Id].Kill()
+				lOut := limiter(in, out)
+				proc[m.Id] = startProcess(m.Id, m.Body, lOut, m.Options)
+			case "kill":
+				proc[m.Id].Kill()
+			}
+		case err := <-errc:
+			if err != io.EOF {
+				// A encode or decode has failed; bail.
+				log.Println(err)
+			}
+			// Shut down any running processes.
+			for _, p := range proc {
+				p.Kill()
+			}
+			return
+		}
+	}
+}
+
+// process represents a running process.
+type process struct {
+	id   string
+	out  chan<- *Message
+	done chan struct{} // closed when wait completes
+	run  *exec.Cmd
+	bin  string
+}
+
+// startProcess builds and runs the given program, sending its output
+// and end event as Messages on the provided channel.
+func startProcess(id, body string, out chan<- *Message, opt *Options) *process {
+	p := &process{
+		id:   id,
+		out:  out,
+		done: make(chan struct{}),
+	}
+	var err error
+	if path, args := shebang(body); path != "" {
+		if RunScripts {
+			err = p.startProcess(path, args, body)
+		} else {
+			err = errors.New("script execution is not allowed")
+		}
+	} else {
+		err = p.start(body, opt)
+	}
+	if err != nil {
+		p.end(err)
+		return nil
+	}
+	go p.wait()
+	return p
+}
+
+// Kill stops the process if it is running and waits for it to exit.
+func (p *process) Kill() {
+	if p == nil {
+		return
+	}
+	p.run.Process.Kill()
+	<-p.done // block until process exits
+}
+
+// shebang looks for a shebang ('#!') at the beginning of the passed string.
+// If found, it returns the path and args after the shebang.
+// args includes the command as args[0].
+func shebang(body string) (path string, args []string) {
+	body = strings.TrimSpace(body)
+	if !strings.HasPrefix(body, "#!") {
+		return "", nil
+	}
+	if i := strings.Index(body, "\n"); i >= 0 {
+		body = body[:i]
+	}
+	fs := strings.Fields(body[2:])
+	return fs[0], fs
+}
+
+// startProcess starts a given program given its path and passing the given body
+// to the command standard input.
+func (p *process) startProcess(path string, args []string, body string) error {
+	cmd := &exec.Cmd{
+		Path:   path,
+		Args:   args,
+		Stdin:  strings.NewReader(body),
+		Stdout: &messageWriter{id: p.id, kind: "stdout", out: p.out},
+		Stderr: &messageWriter{id: p.id, kind: "stderr", out: p.out},
+	}
+	if err := cmd.Start(); err != nil {
+		return err
+	}
+	p.run = cmd
+	return nil
+}
+
+// start builds and starts the given program, sending its output to p.out,
+// and stores the running *exec.Cmd in the run field.
+func (p *process) start(body string, opt *Options) error {
+	// We "go build" and then exec the binary so that the
+	// resultant *exec.Cmd is a handle to the user's program
+	// (rather than the go tool process).
+	// This makes Kill work.
+
+	bin := filepath.Join(tmpdir, "compile"+strconv.Itoa(<-uniq))
+	src := bin + ".go"
+	if runtime.GOOS == "windows" {
+		bin += ".exe"
+	}
+
+	// write body to x.go
+	defer os.Remove(src)
+	err := ioutil.WriteFile(src, []byte(body), 0666)
+	if err != nil {
+		return err
+	}
+
+	// build x.go, creating x
+	p.bin = bin // to be removed by p.end
+	dir, file := filepath.Split(src)
+	args := []string{"go", "build", "-tags", "OMIT"}
+	if opt != nil && opt.Race {
+		p.out <- &Message{
+			Id: p.id, Kind: "stderr",
+			Body: "Running with race detector.\n",
+		}
+		args = append(args, "-race")
+	}
+	args = append(args, "-o", bin, file)
+	cmd := p.cmd(dir, args...)
+	cmd.Stdout = cmd.Stderr // send compiler output to stderr
+	if err := cmd.Run(); err != nil {
+		return err
+	}
+
+	// run x
+	if isNacl() {
+		cmd, err = p.naclCmd(bin)
+		if err != nil {
+			return err
+		}
+	} else {
+		cmd = p.cmd("", bin)
+	}
+	if opt != nil && opt.Race {
+		cmd.Env = append(cmd.Env, "GOMAXPROCS=2")
+	}
+	if err := cmd.Start(); err != nil {
+		// If we failed to exec, that might be because they built
+		// a non-main package instead of an executable.
+		// Check and report that.
+		if name, err := packageName(body); err == nil && name != "main" {
+			return errors.New(`executable programs must use "package main"`)
+		}
+		return err
+	}
+	p.run = cmd
+	return nil
+}
+
+// wait waits for the running process to complete
+// and sends its error state to the client.
+func (p *process) wait() {
+	p.end(p.run.Wait())
+	close(p.done) // unblock waiting Kill calls
+}
+
+// end sends an "end" message to the client, containing the process id and the
+// given error value. It also removes the binary.
+func (p *process) end(err error) {
+	if p.bin != "" {
+		defer os.Remove(p.bin)
+	}
+	m := &Message{Id: p.id, Kind: "end"}
+	if err != nil {
+		m.Body = err.Error()
+	}
+	// Wait for any outstanding reads to finish (potential race here).
+	time.AfterFunc(msgDelay, func() { p.out <- m })
+}
+
+// cmd builds an *exec.Cmd that writes its standard output and error to the
+// process' output channel.
+func (p *process) cmd(dir string, args ...string) *exec.Cmd {
+	cmd := exec.Command(args[0], args[1:]...)
+	cmd.Dir = dir
+	cmd.Env = Environ()
+	cmd.Stdout = &messageWriter{id: p.id, kind: "stdout", out: p.out}
+	cmd.Stderr = &messageWriter{id: p.id, kind: "stderr", out: p.out}
+	return cmd
+}
+
+func isNacl() bool {
+	for _, v := range append(Environ(), os.Environ()...) {
+		if v == "GOOS=nacl" {
+			return true
+		}
+	}
+	return false
+}
+
+// naclCmd returns an *exec.Cmd that executes bin under native client.
+func (p *process) naclCmd(bin string) (*exec.Cmd, error) {
+	pwd, err := os.Getwd()
+	if err != nil {
+		return nil, err
+	}
+	var args []string
+	env := []string{
+		"NACLENV_GOOS=" + runtime.GOOS,
+		"NACLENV_GOROOT=/go",
+		"NACLENV_NACLPWD=" + strings.Replace(pwd, runtime.GOROOT(), "/go", 1),
+	}
+	switch runtime.GOARCH {
+	case "amd64":
+		env = append(env, "NACLENV_GOARCH=amd64p32")
+		args = []string{"sel_ldr_x86_64"}
+	case "386":
+		env = append(env, "NACLENV_GOARCH=386")
+		args = []string{"sel_ldr_x86_32"}
+	case "arm":
+		env = append(env, "NACLENV_GOARCH=arm")
+		selLdr, err := exec.LookPath("sel_ldr_arm")
+		if err != nil {
+			return nil, err
+		}
+		args = []string{"nacl_helper_bootstrap_arm", selLdr, "--reserved_at_zero=0xXXXXXXXXXXXXXXXX"}
+	default:
+		return nil, errors.New("native client does not support GOARCH=" + runtime.GOARCH)
+	}
+
+	cmd := p.cmd("", append(args, "-l", "/dev/null", "-S", "-e", bin)...)
+	cmd.Env = append(cmd.Env, env...)
+
+	return cmd, nil
+}
+
+func packageName(body string) (string, error) {
+	f, err := parser.ParseFile(token.NewFileSet(), "prog.go",
+		strings.NewReader(body), parser.PackageClauseOnly)
+	if err != nil {
+		return "", err
+	}
+	return f.Name.String(), nil
+}
+
+// messageWriter is an io.Writer that converts all writes to Message sends on
+// the out channel with the specified id and kind.
+type messageWriter struct {
+	id, kind string
+	out      chan<- *Message
+
+	mu   sync.Mutex
+	buf  []byte
+	send *time.Timer
+}
+
+func (w *messageWriter) Write(b []byte) (n int, err error) {
+	// Buffer writes that occur in a short period to send as one Message.
+	w.mu.Lock()
+	w.buf = append(w.buf, b...)
+	if w.send == nil {
+		w.send = time.AfterFunc(msgDelay, w.sendNow)
+	}
+	w.mu.Unlock()
+	return len(b), nil
+}
+
+func (w *messageWriter) sendNow() {
+	w.mu.Lock()
+	body := safeString(w.buf)
+	w.buf, w.send = nil, nil
+	w.mu.Unlock()
+	w.out <- &Message{Id: w.id, Kind: w.kind, Body: body}
+}
+
+// safeString returns b as a valid UTF-8 string.
+func safeString(b []byte) string {
+	if utf8.Valid(b) {
+		return string(b)
+	}
+	var buf bytes.Buffer
+	for len(b) > 0 {
+		r, size := utf8.DecodeRune(b)
+		b = b[size:]
+		buf.WriteRune(r)
+	}
+	return buf.String()
+}
+
+// limiter returns a channel that wraps dest. Messages sent to the channel are
+// sent to dest. After msgLimit Messages have been passed on, a "kill" Message
+// is sent to the kill channel, and only "end" messages are passed.
+func limiter(kill chan<- *Message, dest chan<- *Message) chan<- *Message {
+	ch := make(chan *Message)
+	go func() {
+		n := 0
+		for m := range ch {
+			switch {
+			case n < msgLimit || m.Kind == "end":
+				dest <- m
+				if m.Kind == "end" {
+					return
+				}
+			case n == msgLimit:
+				// process produced too much output. Kill it.
+				kill <- &Message{Id: m.Id, Kind: "kill"}
+			}
+			n++
+		}
+	}()
+	return ch
+}
+
+var tmpdir string
+
+func init() {
+	// find real path to temporary directory
+	var err error
+	tmpdir, err = filepath.EvalSymlinks(os.TempDir())
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+var uniq = make(chan int) // a source of numbers for naming temporary files
+
+func init() {
+	go func() {
+		for i := 0; ; i++ {
+			uniq <- i
+		}
+	}()
+}
diff --git a/third_party/go.tools/present/args.go b/third_party/go.tools/present/args.go
new file mode 100644
index 0000000..49ee1a9
--- /dev/null
+++ b/third_party/go.tools/present/args.go
@@ -0,0 +1,229 @@
+// 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 present
+
+import (
+	"errors"
+	"regexp"
+	"strconv"
+	"unicode/utf8"
+)
+
+// This file is stolen from go/src/cmd/godoc/codewalk.go.
+// It's an evaluator for the file address syntax implemented by acme and sam,
+// but using Go-native regular expressions.
+// To keep things reasonably close, this version uses (?m:re) for all user-provided
+// regular expressions. That is the only change to the code from codewalk.go.
+// See http://plan9.bell-labs.com/sys/doc/sam/sam.html Table II
+// for details on the syntax.
+
+// addrToByte evaluates the given address starting at offset start in data.
+// It returns the lo and hi byte offset of the matched region within data.
+func addrToByteRange(addr string, start int, data []byte) (lo, hi int, err error) {
+	if addr == "" {
+		lo, hi = start, len(data)
+		return
+	}
+	var (
+		dir        byte
+		prevc      byte
+		charOffset bool
+	)
+	lo = start
+	hi = start
+	for addr != "" && err == nil {
+		c := addr[0]
+		switch c {
+		default:
+			err = errors.New("invalid address syntax near " + string(c))
+		case ',':
+			if len(addr) == 1 {
+				hi = len(data)
+			} else {
+				_, hi, err = addrToByteRange(addr[1:], hi, data)
+			}
+			return
+
+		case '+', '-':
+			if prevc == '+' || prevc == '-' {
+				lo, hi, err = addrNumber(data, lo, hi, prevc, 1, charOffset)
+			}
+			dir = c
+
+		case '$':
+			lo = len(data)
+			hi = len(data)
+			if len(addr) > 1 {
+				dir = '+'
+			}
+
+		case '#':
+			charOffset = true
+
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			var i int
+			for i = 1; i < len(addr); i++ {
+				if addr[i] < '0' || addr[i] > '9' {
+					break
+				}
+			}
+			var n int
+			n, err = strconv.Atoi(addr[0:i])
+			if err != nil {
+				break
+			}
+			lo, hi, err = addrNumber(data, lo, hi, dir, n, charOffset)
+			dir = 0
+			charOffset = false
+			prevc = c
+			addr = addr[i:]
+			continue
+
+		case '/':
+			var i, j int
+		Regexp:
+			for i = 1; i < len(addr); i++ {
+				switch addr[i] {
+				case '\\':
+					i++
+				case '/':
+					j = i + 1
+					break Regexp
+				}
+			}
+			if j == 0 {
+				j = i
+			}
+			pattern := addr[1:i]
+			lo, hi, err = addrRegexp(data, lo, hi, dir, pattern)
+			prevc = c
+			addr = addr[j:]
+			continue
+		}
+		prevc = c
+		addr = addr[1:]
+	}
+
+	if err == nil && dir != 0 {
+		lo, hi, err = addrNumber(data, lo, hi, dir, 1, charOffset)
+	}
+	if err != nil {
+		return 0, 0, err
+	}
+	return lo, hi, nil
+}
+
+// addrNumber applies the given dir, n, and charOffset to the address lo, hi.
+// dir is '+' or '-', n is the count, and charOffset is true if the syntax
+// used was #n.  Applying +n (or +#n) means to advance n lines
+// (or characters) after hi.  Applying -n (or -#n) means to back up n lines
+// (or characters) before lo.
+// The return value is the new lo, hi.
+func addrNumber(data []byte, lo, hi int, dir byte, n int, charOffset bool) (int, int, error) {
+	switch dir {
+	case 0:
+		lo = 0
+		hi = 0
+		fallthrough
+
+	case '+':
+		if charOffset {
+			pos := hi
+			for ; n > 0 && pos < len(data); n-- {
+				_, size := utf8.DecodeRune(data[pos:])
+				pos += size
+			}
+			if n == 0 {
+				return pos, pos, nil
+			}
+			break
+		}
+		// find next beginning of line
+		if hi > 0 {
+			for hi < len(data) && data[hi-1] != '\n' {
+				hi++
+			}
+		}
+		lo = hi
+		if n == 0 {
+			return lo, hi, nil
+		}
+		for ; hi < len(data); hi++ {
+			if data[hi] != '\n' {
+				continue
+			}
+			switch n--; n {
+			case 1:
+				lo = hi + 1
+			case 0:
+				return lo, hi + 1, nil
+			}
+		}
+
+	case '-':
+		if charOffset {
+			// Scan backward for bytes that are not UTF-8 continuation bytes.
+			pos := lo
+			for ; pos > 0 && n > 0; pos-- {
+				if data[pos]&0xc0 != 0x80 {
+					n--
+				}
+			}
+			if n == 0 {
+				return pos, pos, nil
+			}
+			break
+		}
+		// find earlier beginning of line
+		for lo > 0 && data[lo-1] != '\n' {
+			lo--
+		}
+		hi = lo
+		if n == 0 {
+			return lo, hi, nil
+		}
+		for ; lo >= 0; lo-- {
+			if lo > 0 && data[lo-1] != '\n' {
+				continue
+			}
+			switch n--; n {
+			case 1:
+				hi = lo
+			case 0:
+				return lo, hi, nil
+			}
+		}
+	}
+
+	return 0, 0, errors.New("address out of range")
+}
+
+// addrRegexp searches for pattern in the given direction starting at lo, hi.
+// The direction dir is '+' (search forward from hi) or '-' (search backward from lo).
+// Backward searches are unimplemented.
+func addrRegexp(data []byte, lo, hi int, dir byte, pattern string) (int, int, error) {
+	// We want ^ and $ to work as in sam/acme, so use ?m.
+	re, err := regexp.Compile("(?m:" + pattern + ")")
+	if err != nil {
+		return 0, 0, err
+	}
+	if dir == '-' {
+		// Could implement reverse search using binary search
+		// through file, but that seems like overkill.
+		return 0, 0, errors.New("reverse search not implemented")
+	}
+	m := re.FindIndex(data[hi:])
+	if len(m) > 0 {
+		m[0] += hi
+		m[1] += hi
+	} else if hi > 0 {
+		// No match.  Wrap to beginning of data.
+		m = re.FindIndex(data)
+	}
+	if len(m) == 0 {
+		return 0, 0, errors.New("no match for " + pattern)
+	}
+	return m[0], m[1], nil
+}
diff --git a/third_party/go.tools/present/caption.go b/third_party/go.tools/present/caption.go
new file mode 100644
index 0000000..00e0b5d
--- /dev/null
+++ b/third_party/go.tools/present/caption.go
@@ -0,0 +1,22 @@
+// 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 present
+
+import "strings"
+
+func init() {
+	Register("caption", parseCaption)
+}
+
+type Caption struct {
+	Text string
+}
+
+func (c Caption) TemplateName() string { return "caption" }
+
+func parseCaption(_ *Context, _ string, _ int, text string) (Elem, error) {
+	text = strings.TrimSpace(strings.TrimPrefix(text, ".caption"))
+	return Caption{text}, nil
+}
diff --git a/third_party/go.tools/present/code.go b/third_party/go.tools/present/code.go
new file mode 100644
index 0000000..5a29951
--- /dev/null
+++ b/third_party/go.tools/present/code.go
@@ -0,0 +1,293 @@
+// 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 present
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"html/template"
+	"path/filepath"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+// Is the playground available?
+var PlayEnabled = false
+
+// TOOD(adg): replace the PlayEnabled flag with something less spaghetti-like.
+// Instead this will probably be determined by a template execution Context
+// value that contains various global metadata required when rendering
+// templates.
+
+func init() {
+	Register("code", parseCode)
+	Register("play", parseCode)
+}
+
+type Code struct {
+	Text     template.HTML
+	Play     bool   // runnable code
+	FileName string // file name
+	Ext      string // file extension
+	Raw      []byte // content of the file
+}
+
+func (c Code) TemplateName() string { return "code" }
+
+// The input line is a .code or .play entry with a file name and an optional HLfoo marker on the end.
+// Anything between the file and HL (if any) is an address expression, which we treat as a string here.
+// We pick off the HL first, for easy parsing.
+var (
+	highlightRE = regexp.MustCompile(`\s+HL([a-zA-Z0-9_]+)?$`)
+	hlCommentRE = regexp.MustCompile(`(.+) // HL(.*)$`)
+	codeRE      = regexp.MustCompile(`\.(code|play)\s+((?:(?:-edit|-numbers)\s+)*)([^\s]+)(?:\s+(.*))?$`)
+)
+
+// parseCode parses a code present directive. Its syntax:
+//   .code [-numbers] [-edit] <filename> [address] [highlight]
+// The directive may also be ".play" if the snippet is executable.
+func parseCode(ctx *Context, sourceFile string, sourceLine int, cmd string) (Elem, error) {
+	cmd = strings.TrimSpace(cmd)
+
+	// Pull off the HL, if any, from the end of the input line.
+	highlight := ""
+	if hl := highlightRE.FindStringSubmatchIndex(cmd); len(hl) == 4 {
+		highlight = cmd[hl[2]:hl[3]]
+		cmd = cmd[:hl[2]-2]
+	}
+
+	// Parse the remaining command line.
+	// Arguments:
+	// args[0]: whole match
+	// args[1]:  .code/.play
+	// args[2]: flags ("-edit -numbers")
+	// args[3]: file name
+	// args[4]: optional address
+	args := codeRE.FindStringSubmatch(cmd)
+	if len(args) != 5 {
+		return nil, fmt.Errorf("%s:%d: syntax error for .code/.play invocation", sourceFile, sourceLine)
+	}
+	command, flags, file, addr := args[1], args[2], args[3], strings.TrimSpace(args[4])
+	play := command == "play" && PlayEnabled
+
+	// Read in code file and (optionally) match address.
+	filename := filepath.Join(filepath.Dir(sourceFile), file)
+	textBytes, err := ctx.ReadFile(filename)
+	if err != nil {
+		return nil, fmt.Errorf("%s:%d: %v", sourceFile, sourceLine, err)
+	}
+	lo, hi, err := addrToByteRange(addr, 0, textBytes)
+	if err != nil {
+		return nil, fmt.Errorf("%s:%d: %v", sourceFile, sourceLine, err)
+	}
+
+	// Acme pattern matches can stop mid-line,
+	// so run to end of line in both directions if not at line start/end.
+	for lo > 0 && textBytes[lo-1] != '\n' {
+		lo--
+	}
+	if hi > 0 {
+		for hi < len(textBytes) && textBytes[hi-1] != '\n' {
+			hi++
+		}
+	}
+
+	lines := codeLines(textBytes, lo, hi)
+
+	data := &codeTemplateData{
+		Lines:   formatLines(lines, highlight),
+		Edit:    strings.Contains(flags, "-edit"),
+		Numbers: strings.Contains(flags, "-numbers"),
+	}
+
+	// Include before and after in a hidden span for playground code.
+	if play {
+		data.Prefix = textBytes[:lo]
+		data.Suffix = textBytes[hi:]
+	}
+
+	var buf bytes.Buffer
+	if err := codeTemplate.Execute(&buf, data); err != nil {
+		return nil, err
+	}
+	return Code{
+		Text:     template.HTML(buf.String()),
+		Play:     play,
+		FileName: filepath.Base(filename),
+		Ext:      filepath.Ext(filename),
+		Raw:      rawCode(lines),
+	}, nil
+}
+
+// formatLines returns a new slice of codeLine with the given lines
+// replacing tabs with spaces and adding highlighting where needed.
+func formatLines(lines []codeLine, highlight string) []codeLine {
+	formatted := make([]codeLine, len(lines))
+	for i, line := range lines {
+		// Replace tabs with spaces, which work better in HTML.
+		line.L = strings.Replace(line.L, "\t", "    ", -1)
+
+		// Highlight lines that end with "// HL[highlight]"
+		// and strip the magic comment.
+		if m := hlCommentRE.FindStringSubmatch(line.L); m != nil {
+			line.L = m[1]
+			line.HL = m[2] == highlight
+		}
+
+		formatted[i] = line
+	}
+	return formatted
+}
+
+// rawCode returns the code represented by the given codeLines without any kind
+// of formatting.
+func rawCode(lines []codeLine) []byte {
+	b := new(bytes.Buffer)
+	for _, line := range lines {
+		b.WriteString(line.L)
+		b.WriteByte('\n')
+	}
+	return b.Bytes()
+}
+
+type codeTemplateData struct {
+	Lines          []codeLine
+	Prefix, Suffix []byte
+	Edit, Numbers  bool
+}
+
+var leadingSpaceRE = regexp.MustCompile(`^[ \t]*`)
+
+var codeTemplate = template.Must(template.New("code").Funcs(template.FuncMap{
+	"trimSpace":    strings.TrimSpace,
+	"leadingSpace": leadingSpaceRE.FindString,
+}).Parse(codeTemplateHTML))
+
+const codeTemplateHTML = `
+{{with .Prefix}}<pre style="display: none"><span>{{printf "%s" .}}</span></pre>{{end}}
+
+<pre{{if .Edit}} contenteditable="true" spellcheck="false"{{end}}{{if .Numbers}} class="numbers"{{end}}>{{/*
+	*/}}{{range .Lines}}<span num="{{.N}}">{{/*
+	*/}}{{if .HL}}{{leadingSpace .L}}<b>{{trimSpace .L}}</b>{{/*
+	*/}}{{else}}{{.L}}{{end}}{{/*
+*/}}</span>
+{{end}}</pre>
+
+{{with .Suffix}}<pre style="display: none"><span>{{printf "%s" .}}</span></pre>{{end}}
+`
+
+// codeLine represents a line of code extracted from a source file.
+type codeLine struct {
+	L  string // The line of code.
+	N  int    // The line number from the source file.
+	HL bool   // Whether the line should be highlighted.
+}
+
+// codeLines takes a source file and returns the lines that
+// span the byte range specified by start and end.
+// It discards lines that end in "OMIT".
+func codeLines(src []byte, start, end int) (lines []codeLine) {
+	startLine := 1
+	for i, b := range src {
+		if i == start {
+			break
+		}
+		if b == '\n' {
+			startLine++
+		}
+	}
+	s := bufio.NewScanner(bytes.NewReader(src[start:end]))
+	for n := startLine; s.Scan(); n++ {
+		l := s.Text()
+		if strings.HasSuffix(l, "OMIT") {
+			continue
+		}
+		lines = append(lines, codeLine{L: l, N: n})
+	}
+	// Trim leading and trailing blank lines.
+	for len(lines) > 0 && len(lines[0].L) == 0 {
+		lines = lines[1:]
+	}
+	for len(lines) > 0 && len(lines[len(lines)-1].L) == 0 {
+		lines = lines[:len(lines)-1]
+	}
+	return
+}
+
+func parseArgs(name string, line int, args []string) (res []interface{}, err error) {
+	res = make([]interface{}, len(args))
+	for i, v := range args {
+		if len(v) == 0 {
+			return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
+		}
+		switch v[0] {
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			n, err := strconv.Atoi(v)
+			if err != nil {
+				return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
+			}
+			res[i] = n
+		case '/':
+			if len(v) < 2 || v[len(v)-1] != '/' {
+				return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
+			}
+			res[i] = v
+		case '$':
+			res[i] = "$"
+		case '_':
+			if len(v) == 1 {
+				// Do nothing; "_" indicates an intentionally empty parameter.
+				break
+			}
+			fallthrough
+		default:
+			return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
+		}
+	}
+	return
+}
+
+// parseArg returns the integer or string value of the argument and tells which it is.
+func parseArg(arg interface{}, max int) (ival int, sval string, isInt bool, err error) {
+	switch n := arg.(type) {
+	case int:
+		if n <= 0 || n > max {
+			return 0, "", false, fmt.Errorf("%d is out of range", n)
+		}
+		return n, "", true, nil
+	case string:
+		return 0, n, false, nil
+	}
+	return 0, "", false, fmt.Errorf("unrecognized argument %v type %T", arg, arg)
+}
+
+// match identifies the input line that matches the pattern in a code invocation.
+// If start>0, match lines starting there rather than at the beginning.
+// The return value is 1-indexed.
+func match(file string, start int, lines []string, pattern string) (int, error) {
+	// $ matches the end of the file.
+	if pattern == "$" {
+		if len(lines) == 0 {
+			return 0, fmt.Errorf("%q: empty file", file)
+		}
+		return len(lines), nil
+	}
+	// /regexp/ matches the line that matches the regexp.
+	if len(pattern) > 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' {
+		re, err := regexp.Compile(pattern[1 : len(pattern)-1])
+		if err != nil {
+			return 0, err
+		}
+		for i := start; i < len(lines); i++ {
+			if re.MatchString(lines[i]) {
+				return i + 1, nil
+			}
+		}
+		return 0, fmt.Errorf("%s: no match for %#q", file, pattern)
+	}
+	return 0, fmt.Errorf("unrecognized pattern: %q", pattern)
+}
diff --git a/third_party/go.tools/present/doc.go b/third_party/go.tools/present/doc.go
new file mode 100644
index 0000000..cc2f008
--- /dev/null
+++ b/third_party/go.tools/present/doc.go
@@ -0,0 +1,205 @@
+// 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.
+
+/*
+The present file format
+
+Present files have the following format.  The first non-blank non-comment
+line is the title, so the header looks like
+
+	Title of document
+	Subtitle of document
+	15:04 2 Jan 2006
+	Tags: foo, bar, baz
+	<blank line>
+	Author Name
+	Job title, Company
+	joe@example.com
+	http://url/
+	@twitter_name
+
+The subtitle, date, and tags lines are optional.
+
+The date line may be written without a time:
+	2 Jan 2006
+In this case, the time will be interpreted as 10am UTC on that date.
+
+The tags line is a comma-separated list of tags that may be used to categorize
+the document.
+
+The author section may contain a mixture of text, twitter names, and links.
+For slide presentations, only the plain text lines will be displayed on the
+first slide.
+
+Multiple presenters may be specified, separated by a blank line.
+
+After that come slides/sections, each after a blank line:
+
+	* Title of slide or section (must have asterisk)
+
+	Some Text
+
+	** Subsection
+
+	- bullets
+	- more bullets
+	- a bullet with
+
+	*** Sub-subsection
+
+	Some More text
+
+	  Preformatted text
+	  is indented (however you like)
+
+	Further Text, including invocations like:
+
+	.code x.go /^func main/,/^}/
+	.play y.go
+	.image image.jpg
+	.iframe http://foo
+	.link http://foo label
+	.html file.html
+	.caption _Gopher_ by [[http://www.reneefrench.com][Renée French]]
+
+	Again, more text
+
+Blank lines are OK (not mandatory) after the title and after the
+text.  Text, bullets, and .code etc. are all optional; title is
+not.
+
+Lines starting with # in column 1 are commentary.
+
+Fonts:
+
+Within the input for plain text or lists, text bracketed by font
+markers will be presented in italic, bold, or program font.
+Marker characters are _ (italic), * (bold) and ` (program font).
+Unmatched markers appear as plain text.
+Within marked text, a single marker character becomes a space
+and a doubled single marker quotes the marker character.
+
+	_italic_
+	*bold*
+	`program`
+	_this_is_all_italic_
+	_Why_use_scoped__ptr_? Use plain ***ptr* instead.
+
+Inline links:
+
+Links can be included in any text with the form [[url][label]], or
+[[url]] to use the URL itself as the label.
+
+Functions:
+
+A number of template functions are available through invocations
+in the input text. Each such invocation contains a period as the
+first character on the line, followed immediately by the name of
+the function, followed by any arguments. A typical invocation might
+be
+	.play demo.go /^func show/,/^}/
+(except that the ".play" must be at the beginning of the line and
+not be indented like this.)
+
+Here follows a description of the functions:
+
+code:
+
+Injects program source into the output by extracting code from files
+and injecting them as HTML-escaped <pre> blocks.  The argument is
+a file name followed by an optional address that specifies what
+section of the file to display. The address syntax is similar in
+its simplest form to that of ed, but comes from sam and is more
+general. See
+	http://plan9.bell-labs.com/sys/doc/sam/sam.html Table II
+for full details. The displayed block is always rounded out to a
+full line at both ends.
+
+If no pattern is present, the entire file is displayed.
+
+Any line in the program that ends with the four characters
+	OMIT
+is deleted from the source before inclusion, making it easy
+to write things like
+	.code test.go /START OMIT/,/END OMIT/
+to find snippets like this
+	tedious_code = boring_function()
+	// START OMIT
+	interesting_code = fascinating_function()
+	// END OMIT
+and see only this:
+	interesting_code = fascinating_function()
+
+Also, inside the displayed text a line that ends
+	// HL
+will be highlighted in the display; the 'h' key in the browser will
+toggle extra emphasis of any highlighted lines. A highlighting mark
+may have a suffix word, such as
+	// HLxxx
+Such highlights are enabled only if the code invocation ends with
+"HL" followed by the word:
+	.code test.go /^type Foo/,/^}/ HLxxx
+
+The .code function may take one or more flags immediately preceding
+the filename. This command shows test.go in an editable text area:
+	.code -edit test.go
+This command shows test.go with line numbers:
+	.code -numbers test.go
+
+play:
+
+The function "play" is the same as "code" but puts a button
+on the displayed source so the program can be run from the browser.
+Although only the selected text is shown, all the source is included
+in the HTML output so it can be presented to the compiler.
+
+link:
+
+Create a hyperlink. The syntax is 1 or 2 space-separated arguments.
+The first argument is always the HTTP URL.  If there is a second
+argument, it is the text label to display for this link.
+
+	.link http://golang.org golang.org
+
+image:
+
+The template uses the function "image" to inject picture files.
+
+The syntax is simple: 1 or 3 space-separated arguments.
+The first argument is always the file name.
+If there are more arguments, they are the height and width;
+both must be present, or substituted with an underscore.
+Replacing a dimension argument with the underscore parameter
+preserves the aspect ratio of the image when scaling.
+
+	.image images/betsy.jpg 100 200
+
+	.image images/janet.jpg _ 300
+
+
+caption:
+
+The template uses the function "caption" to inject figure captions.
+
+The text after ".caption" is embedded in a figcaption element after
+processing styling and links as in standard text lines.
+
+	.caption _Gopher_ by [[http://www.reneefrench.com][Renée French]]
+
+iframe:
+
+The function "iframe" injects iframes (pages inside pages).
+Its syntax is the same as that of image.
+
+html:
+
+The function html includes the contents of the specified file as
+unescaped HTML. This is useful for including custom HTML elements
+that cannot be created using only the slide format.
+It is your responsibilty to make sure the included HTML is valid and safe.
+
+	.html file.html
+
+*/
+package present
diff --git a/third_party/go.tools/present/html.go b/third_party/go.tools/present/html.go
new file mode 100644
index 0000000..cca90ef
--- /dev/null
+++ b/third_party/go.tools/present/html.go
@@ -0,0 +1,31 @@
+package present
+
+import (
+	"errors"
+	"html/template"
+	"path/filepath"
+	"strings"
+)
+
+func init() {
+	Register("html", parseHTML)
+}
+
+func parseHTML(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
+	p := strings.Fields(text)
+	if len(p) != 2 {
+		return nil, errors.New("invalid .html args")
+	}
+	name := filepath.Join(filepath.Dir(fileName), p[1])
+	b, err := ctx.ReadFile(name)
+	if err != nil {
+		return nil, err
+	}
+	return HTML{template.HTML(b)}, nil
+}
+
+type HTML struct {
+	template.HTML
+}
+
+func (s HTML) TemplateName() string { return "html" }
diff --git a/third_party/go.tools/present/iframe.go b/third_party/go.tools/present/iframe.go
new file mode 100644
index 0000000..2f3c5e5
--- /dev/null
+++ b/third_party/go.tools/present/iframe.go
@@ -0,0 +1,45 @@
+// Copyright 2013 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 present
+
+import (
+	"fmt"
+	"strings"
+)
+
+func init() {
+	Register("iframe", parseIframe)
+}
+
+type Iframe struct {
+	URL    string
+	Width  int
+	Height int
+}
+
+func (i Iframe) TemplateName() string { return "iframe" }
+
+func parseIframe(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
+	args := strings.Fields(text)
+	i := Iframe{URL: args[1]}
+	a, err := parseArgs(fileName, lineno, args[2:])
+	if err != nil {
+		return nil, err
+	}
+	switch len(a) {
+	case 0:
+		// no size parameters
+	case 2:
+		if v, ok := a[0].(int); ok {
+			i.Height = v
+		}
+		if v, ok := a[1].(int); ok {
+			i.Width = v
+		}
+	default:
+		return nil, fmt.Errorf("incorrect image invocation: %q", text)
+	}
+	return i, nil
+}
diff --git a/third_party/go.tools/present/image.go b/third_party/go.tools/present/image.go
new file mode 100644
index 0000000..cfa2af9
--- /dev/null
+++ b/third_party/go.tools/present/image.go
@@ -0,0 +1,50 @@
+// 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 present
+
+import (
+	"fmt"
+	"strings"
+)
+
+func init() {
+	Register("image", parseImage)
+}
+
+type Image struct {
+	URL    string
+	Width  int
+	Height int
+}
+
+func (i Image) TemplateName() string { return "image" }
+
+func parseImage(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
+	args := strings.Fields(text)
+	img := Image{URL: args[1]}
+	a, err := parseArgs(fileName, lineno, args[2:])
+	if err != nil {
+		return nil, err
+	}
+	switch len(a) {
+	case 0:
+		// no size parameters
+	case 2:
+		// If a parameter is empty (underscore) or invalid
+		// leave the field set to zero. The "image" action
+		// template will then omit that img tag attribute and
+		// the browser will calculate the value to preserve
+		// the aspect ratio.
+		if v, ok := a[0].(int); ok {
+			img.Height = v
+		}
+		if v, ok := a[1].(int); ok {
+			img.Width = v
+		}
+	default:
+		return nil, fmt.Errorf("incorrect image invocation: %q", text)
+	}
+	return img, nil
+}
diff --git a/third_party/go.tools/present/link.go b/third_party/go.tools/present/link.go
new file mode 100644
index 0000000..6b0968f
--- /dev/null
+++ b/third_party/go.tools/present/link.go
@@ -0,0 +1,97 @@
+// 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 present
+
+import (
+	"fmt"
+	"log"
+	"net/url"
+	"strings"
+)
+
+func init() {
+	Register("link", parseLink)
+}
+
+type Link struct {
+	URL   *url.URL
+	Label string
+}
+
+func (l Link) TemplateName() string { return "link" }
+
+func parseLink(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
+	args := strings.Fields(text)
+	url, err := url.Parse(args[1])
+	if err != nil {
+		return nil, err
+	}
+	label := ""
+	if len(args) > 2 {
+		label = strings.Join(args[2:], " ")
+	} else {
+		scheme := url.Scheme + "://"
+		if url.Scheme == "mailto" {
+			scheme = "mailto:"
+		}
+		label = strings.Replace(url.String(), scheme, "", 1)
+	}
+	return Link{url, label}, nil
+}
+
+func renderLink(href, text string) string {
+	text = font(text)
+	if text == "" {
+		text = href
+	}
+	// Open links in new window only when their url is absolute.
+	target := "_blank"
+	if u, err := url.Parse(href); err != nil {
+		log.Println("rendernLink parsing url:", err)
+	} else if !u.IsAbs() || u.Scheme == "javascript" {
+		target = "_self"
+	}
+
+	return fmt.Sprintf(`<a href="%s" target="%s">%s</a>`, href, target, text)
+}
+
+// parseInlineLink parses an inline link at the start of s, and returns
+// a rendered HTML link and the total length of the raw inline link.
+// If no inline link is present, it returns all zeroes.
+func parseInlineLink(s string) (link string, length int) {
+	if !strings.HasPrefix(s, "[[") {
+		return
+	}
+	end := strings.Index(s, "]]")
+	if end == -1 {
+		return
+	}
+	urlEnd := strings.Index(s, "]")
+	rawURL := s[2:urlEnd]
+	const badURLChars = `<>"{}|\^[] ` + "`" // per RFC2396 section 2.4.3
+	if strings.ContainsAny(rawURL, badURLChars) {
+		return
+	}
+	if urlEnd == end {
+		simpleUrl := ""
+		url, err := url.Parse(rawURL)
+		if err == nil {
+			// If the URL is http://foo.com, drop the http://
+			// In other words, render [[http://golang.org]] as:
+			//   <a href="http://golang.org">golang.org</a>
+			if strings.HasPrefix(rawURL, url.Scheme+"://") {
+				simpleUrl = strings.TrimPrefix(rawURL, url.Scheme+"://")
+			} else if strings.HasPrefix(rawURL, url.Scheme+":") {
+				simpleUrl = strings.TrimPrefix(rawURL, url.Scheme+":")
+			}
+		}
+		return renderLink(rawURL, simpleUrl), end + 2
+	}
+	if s[urlEnd:urlEnd+2] != "][" {
+		return
+	}
+	text := s[urlEnd+2 : end]
+	return renderLink(rawURL, text), end + 2
+}
diff --git a/third_party/go.tools/present/link_test.go b/third_party/go.tools/present/link_test.go
new file mode 100644
index 0000000..334e72b
--- /dev/null
+++ b/third_party/go.tools/present/link_test.go
@@ -0,0 +1,40 @@
+// 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 present
+
+import "testing"
+
+func TestInlineParsing(t *testing.T) {
+	var tests = []struct {
+		in     string
+		link   string
+		text   string
+		length int
+	}{
+		{"[[http://golang.org]]", "http://golang.org", "golang.org", 21},
+		{"[[http://golang.org][]]", "http://golang.org", "http://golang.org", 23},
+		{"[[http://golang.org]] this is ignored", "http://golang.org", "golang.org", 21},
+		{"[[http://golang.org][link]]", "http://golang.org", "link", 27},
+		{"[[http://golang.org][two words]]", "http://golang.org", "two words", 32},
+		{"[[http://golang.org][*link*]]", "http://golang.org", "<b>link</b>", 29},
+		{"[[http://bad[url]]", "", "", 0},
+		{"[[http://golang.org][a [[link]] ]]", "http://golang.org", "a [[link", 31},
+		{"[[http:// *spaces* .com]]", "", "", 0},
+		{"[[http://bad`char.com]]", "", "", 0},
+		{" [[http://google.com]]", "", "", 0},
+		{"[[mailto:gopher@golang.org][Gopher]]", "mailto:gopher@golang.org", "Gopher", 36},
+		{"[[mailto:gopher@golang.org]]", "mailto:gopher@golang.org", "gopher@golang.org", 28},
+	}
+
+	for i, test := range tests {
+		link, length := parseInlineLink(test.in)
+		if length == 0 && test.length == 0 {
+			continue
+		}
+		if a := renderLink(test.link, test.text); length != test.length || link != a {
+			t.Errorf("#%d: parseInlineLink(%q):\ngot\t%q, %d\nwant\t%q, %d", i, test.in, link, length, a, test.length)
+		}
+	}
+}
diff --git a/third_party/go.tools/present/parse.go b/third_party/go.tools/present/parse.go
new file mode 100644
index 0000000..449d5ed
--- /dev/null
+++ b/third_party/go.tools/present/parse.go
@@ -0,0 +1,505 @@
+// 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.
+
+package present
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"html/template"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/url"
+	"regexp"
+	"strings"
+	"time"
+	"unicode"
+	"unicode/utf8"
+)
+
+var (
+	parsers = make(map[string]ParseFunc)
+	funcs   = template.FuncMap{}
+)
+
+// Template returns an empty template with the action functions in its FuncMap.
+func Template() *template.Template {
+	return template.New("").Funcs(funcs)
+}
+
+// Render renders the doc to the given writer using the provided template.
+func (d *Doc) Render(w io.Writer, t *template.Template) error {
+	data := struct {
+		*Doc
+		Template    *template.Template
+		PlayEnabled bool
+	}{d, t, PlayEnabled}
+	return t.ExecuteTemplate(w, "root", data)
+}
+
+// Render renders the section to the given writer using the provided template.
+func (s *Section) Render(w io.Writer, t *template.Template) error {
+	data := struct {
+		*Section
+		Template    *template.Template
+		PlayEnabled bool
+	}{s, t, PlayEnabled}
+	return t.ExecuteTemplate(w, "section", data)
+}
+
+type ParseFunc func(ctx *Context, fileName string, lineNumber int, inputLine string) (Elem, error)
+
+// Register binds the named action, which does not begin with a period, to the
+// specified parser to be invoked when the name, with a period, appears in the
+// present input text.
+func Register(name string, parser ParseFunc) {
+	if len(name) == 0 || name[0] == ';' {
+		panic("bad name in Register: " + name)
+	}
+	parsers["."+name] = parser
+}
+
+// Doc represents an entire document.
+type Doc struct {
+	Title    string
+	Subtitle string
+	Time     time.Time
+	Authors  []Author
+	Sections []Section
+	Tags     []string
+}
+
+// Author represents the person who wrote and/or is presenting the document.
+type Author struct {
+	Elem []Elem
+}
+
+// TextElem returns the first text elements of the author details.
+// This is used to display the author' name, job title, and company
+// without the contact details.
+func (p *Author) TextElem() (elems []Elem) {
+	for _, el := range p.Elem {
+		if _, ok := el.(Text); !ok {
+			break
+		}
+		elems = append(elems, el)
+	}
+	return
+}
+
+// Section represents a section of a document (such as a presentation slide)
+// comprising a title and a list of elements.
+type Section struct {
+	Number []int
+	Title  string
+	Elem   []Elem
+}
+
+func (s Section) Sections() (sections []Section) {
+	for _, e := range s.Elem {
+		if section, ok := e.(Section); ok {
+			sections = append(sections, section)
+		}
+	}
+	return
+}
+
+// Level returns the level of the given section.
+// The document title is level 1, main section 2, etc.
+func (s Section) Level() int {
+	return len(s.Number) + 1
+}
+
+// FormattedNumber returns a string containing the concatenation of the
+// numbers identifying a Section.
+func (s Section) FormattedNumber() string {
+	b := &bytes.Buffer{}
+	for _, n := range s.Number {
+		fmt.Fprintf(b, "%v.", n)
+	}
+	return b.String()
+}
+
+func (s Section) TemplateName() string { return "section" }
+
+// Elem defines the interface for a present element. That is, something that
+// can provide the name of the template used to render the element.
+type Elem interface {
+	TemplateName() string
+}
+
+// renderElem implements the elem template function, used to render
+// sub-templates.
+func renderElem(t *template.Template, e Elem) (template.HTML, error) {
+	var data interface{} = e
+	if s, ok := e.(Section); ok {
+		data = struct {
+			Section
+			Template *template.Template
+		}{s, t}
+	}
+	return execTemplate(t, e.TemplateName(), data)
+}
+
+func init() {
+	funcs["elem"] = renderElem
+}
+
+// execTemplate is a helper to execute a template and return the output as a
+// template.HTML value.
+func execTemplate(t *template.Template, name string, data interface{}) (template.HTML, error) {
+	b := new(bytes.Buffer)
+	err := t.ExecuteTemplate(b, name, data)
+	if err != nil {
+		return "", err
+	}
+	return template.HTML(b.String()), nil
+}
+
+// Text represents an optionally preformatted paragraph.
+type Text struct {
+	Lines []string
+	Pre   bool
+}
+
+func (t Text) TemplateName() string { return "text" }
+
+// List represents a bulleted list.
+type List struct {
+	Bullet []string
+}
+
+func (l List) TemplateName() string { return "list" }
+
+// Lines is a helper for parsing line-based input.
+type Lines struct {
+	line int // 0 indexed, so has 1-indexed number of last line returned
+	text []string
+}
+
+func readLines(r io.Reader) (*Lines, error) {
+	var lines []string
+	s := bufio.NewScanner(r)
+	for s.Scan() {
+		lines = append(lines, s.Text())
+	}
+	if err := s.Err(); err != nil {
+		return nil, err
+	}
+	return &Lines{0, lines}, nil
+}
+
+func (l *Lines) next() (text string, ok bool) {
+	for {
+		current := l.line
+		l.line++
+		if current >= len(l.text) {
+			return "", false
+		}
+		text = l.text[current]
+		// Lines starting with # are comments.
+		if len(text) == 0 || text[0] != '#' {
+			ok = true
+			break
+		}
+	}
+	return
+}
+
+func (l *Lines) back() {
+	l.line--
+}
+
+func (l *Lines) nextNonEmpty() (text string, ok bool) {
+	for {
+		text, ok = l.next()
+		if !ok {
+			return
+		}
+		if len(text) > 0 {
+			break
+		}
+	}
+	return
+}
+
+// A Context specifies the supporting context for parsing a presentation.
+type Context struct {
+	// ReadFile reads the file named by filename and returns the contents.
+	ReadFile func(filename string) ([]byte, error)
+}
+
+// ParseMode represents flags for the Parse function.
+type ParseMode int
+
+const (
+	// If set, parse only the title and subtitle.
+	TitlesOnly ParseMode = 1
+)
+
+// Parse parses a document from r.
+func (ctx *Context) Parse(r io.Reader, name string, mode ParseMode) (*Doc, error) {
+	doc := new(Doc)
+	lines, err := readLines(r)
+	if err != nil {
+		return nil, err
+	}
+	err = parseHeader(doc, lines)
+	if err != nil {
+		return nil, err
+	}
+	if mode&TitlesOnly != 0 {
+		return doc, nil
+	}
+	// Authors
+	if doc.Authors, err = parseAuthors(lines); err != nil {
+		return nil, err
+	}
+	// Sections
+	if doc.Sections, err = parseSections(ctx, name, lines, []int{}, doc); err != nil {
+		return nil, err
+	}
+	return doc, nil
+}
+
+// Parse parses a document from r. Parse reads assets used by the presentation
+// from the file system using ioutil.ReadFile.
+func Parse(r io.Reader, name string, mode ParseMode) (*Doc, error) {
+	ctx := Context{ReadFile: ioutil.ReadFile}
+	return ctx.Parse(r, name, mode)
+}
+
+// isHeading matches any section heading.
+var isHeading = regexp.MustCompile(`^\*+ `)
+
+// lesserHeading returns true if text is a heading of a lesser or equal level
+// than that denoted by prefix.
+func lesserHeading(text, prefix string) bool {
+	return isHeading.MatchString(text) && !strings.HasPrefix(text, prefix+"*")
+}
+
+// parseSections parses Sections from lines for the section level indicated by
+// number (a nil number indicates the top level).
+func parseSections(ctx *Context, name string, lines *Lines, number []int, doc *Doc) ([]Section, error) {
+	var sections []Section
+	for i := 1; ; i++ {
+		// Next non-empty line is title.
+		text, ok := lines.nextNonEmpty()
+		for ok && text == "" {
+			text, ok = lines.next()
+		}
+		if !ok {
+			break
+		}
+		prefix := strings.Repeat("*", len(number)+1)
+		if !strings.HasPrefix(text, prefix+" ") {
+			lines.back()
+			break
+		}
+		section := Section{
+			Number: append(append([]int{}, number...), i),
+			Title:  text[len(prefix)+1:],
+		}
+		text, ok = lines.nextNonEmpty()
+		for ok && !lesserHeading(text, prefix) {
+			var e Elem
+			r, _ := utf8.DecodeRuneInString(text)
+			switch {
+			case unicode.IsSpace(r):
+				i := strings.IndexFunc(text, func(r rune) bool {
+					return !unicode.IsSpace(r)
+				})
+				if i < 0 {
+					break
+				}
+				indent := text[:i]
+				var s []string
+				for ok && (strings.HasPrefix(text, indent) || text == "") {
+					if text != "" {
+						text = text[i:]
+					}
+					s = append(s, text)
+					text, ok = lines.next()
+				}
+				lines.back()
+				pre := strings.Join(s, "\n")
+				pre = strings.Replace(pre, "\t", "    ", -1) // browsers treat tabs badly
+				pre = strings.TrimRightFunc(pre, unicode.IsSpace)
+				e = Text{Lines: []string{pre}, Pre: true}
+			case strings.HasPrefix(text, "- "):
+				var b []string
+				for ok && strings.HasPrefix(text, "- ") {
+					b = append(b, text[2:])
+					text, ok = lines.next()
+				}
+				lines.back()
+				e = List{Bullet: b}
+			case strings.HasPrefix(text, prefix+"* "):
+				lines.back()
+				subsecs, err := parseSections(ctx, name, lines, section.Number, doc)
+				if err != nil {
+					return nil, err
+				}
+				for _, ss := range subsecs {
+					section.Elem = append(section.Elem, ss)
+				}
+			case strings.HasPrefix(text, "."):
+				args := strings.Fields(text)
+				parser := parsers[args[0]]
+				if parser == nil {
+					return nil, fmt.Errorf("%s:%d: unknown command %q\n", name, lines.line, text)
+				}
+				t, err := parser(ctx, name, lines.line, text)
+				if err != nil {
+					return nil, err
+				}
+				e = t
+			default:
+				var l []string
+				for ok && strings.TrimSpace(text) != "" {
+					if text[0] == '.' { // Command breaks text block.
+						break
+					}
+					if strings.HasPrefix(text, `\.`) { // Backslash escapes initial period.
+						text = text[1:]
+					}
+					l = append(l, text)
+					text, ok = lines.next()
+				}
+				if len(l) > 0 {
+					e = Text{Lines: l}
+				}
+			}
+			if e != nil {
+				section.Elem = append(section.Elem, e)
+			}
+			text, ok = lines.nextNonEmpty()
+		}
+		if isHeading.MatchString(text) {
+			lines.back()
+		}
+		sections = append(sections, section)
+	}
+	return sections, nil
+}
+
+func parseHeader(doc *Doc, lines *Lines) error {
+	var ok bool
+	// First non-empty line starts header.
+	doc.Title, ok = lines.nextNonEmpty()
+	if !ok {
+		return errors.New("unexpected EOF; expected title")
+	}
+	for {
+		text, ok := lines.next()
+		if !ok {
+			return errors.New("unexpected EOF")
+		}
+		if text == "" {
+			break
+		}
+		const tagPrefix = "Tags:"
+		if strings.HasPrefix(text, tagPrefix) {
+			tags := strings.Split(text[len(tagPrefix):], ",")
+			for i := range tags {
+				tags[i] = strings.TrimSpace(tags[i])
+			}
+			doc.Tags = append(doc.Tags, tags...)
+		} else if t, ok := parseTime(text); ok {
+			doc.Time = t
+		} else if doc.Subtitle == "" {
+			doc.Subtitle = text
+		} else {
+			return fmt.Errorf("unexpected header line: %q", text)
+		}
+	}
+	return nil
+}
+
+func parseAuthors(lines *Lines) (authors []Author, err error) {
+	// This grammar demarcates authors with blanks.
+
+	// Skip blank lines.
+	if _, ok := lines.nextNonEmpty(); !ok {
+		return nil, errors.New("unexpected EOF")
+	}
+	lines.back()
+
+	var a *Author
+	for {
+		text, ok := lines.next()
+		if !ok {
+			return nil, errors.New("unexpected EOF")
+		}
+
+		// If we find a section heading, we're done.
+		if strings.HasPrefix(text, "* ") {
+			lines.back()
+			break
+		}
+
+		// If we encounter a blank we're done with this author.
+		if a != nil && len(text) == 0 {
+			authors = append(authors, *a)
+			a = nil
+			continue
+		}
+		if a == nil {
+			a = new(Author)
+		}
+
+		// Parse the line. Those that
+		// - begin with @ are twitter names,
+		// - contain slashes are links, or
+		// - contain an @ symbol are an email address.
+		// The rest is just text.
+		var el Elem
+		switch {
+		case strings.HasPrefix(text, "@"):
+			el = parseURL("http://twitter.com/" + text[1:])
+		case strings.Contains(text, ":"):
+			el = parseURL(text)
+		case strings.Contains(text, "@"):
+			el = parseURL("mailto:" + text)
+		}
+		if l, ok := el.(Link); ok {
+			l.Label = text
+			el = l
+		}
+		if el == nil {
+			el = Text{Lines: []string{text}}
+		}
+		a.Elem = append(a.Elem, el)
+	}
+	if a != nil {
+		authors = append(authors, *a)
+	}
+	return authors, nil
+}
+
+func parseURL(text string) Elem {
+	u, err := url.Parse(text)
+	if err != nil {
+		log.Printf("Parse(%q): %v", text, err)
+		return nil
+	}
+	return Link{URL: u}
+}
+
+func parseTime(text string) (t time.Time, ok bool) {
+	t, err := time.Parse("15:04 2 Jan 2006", text)
+	if err == nil {
+		return t, true
+	}
+	t, err = time.Parse("2 Jan 2006", text)
+	if err == nil {
+		// at 11am UTC it is the same date everywhere
+		t = t.Add(time.Hour * 11)
+		return t, true
+	}
+	return time.Time{}, false
+}
diff --git a/third_party/go.tools/present/style.go b/third_party/go.tools/present/style.go
new file mode 100644
index 0000000..1cd240d
--- /dev/null
+++ b/third_party/go.tools/present/style.go
@@ -0,0 +1,166 @@
+// 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 present
+
+import (
+	"bytes"
+	"html"
+	"html/template"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+/*
+	Fonts are demarcated by an initial and final char bracketing a
+	space-delimited word, plus possibly some terminal punctuation.
+	The chars are
+		_ for italic
+		* for bold
+		` (back quote) for fixed width.
+	Inner appearances of the char become spaces. For instance,
+		_this_is_italic_!
+	becomes
+		<i>this is italic</i>!
+*/
+
+func init() {
+	funcs["style"] = Style
+}
+
+// Style returns s with HTML entities escaped and font indicators turned into
+// HTML font tags.
+func Style(s string) template.HTML {
+	return template.HTML(font(html.EscapeString(s)))
+}
+
+// font returns s with font indicators turned into HTML font tags.
+func font(s string) string {
+	if strings.IndexAny(s, "[`_*") == -1 {
+		return s
+	}
+	words := split(s)
+	var b bytes.Buffer
+Word:
+	for w, word := range words {
+		if len(word) < 2 {
+			continue Word
+		}
+		if link, _ := parseInlineLink(word); link != "" {
+			words[w] = link
+			continue Word
+		}
+		const punctuation = `.,;:()!?—–'"`
+		const marker = "_*`"
+		// Initial punctuation is OK but must be peeled off.
+		first := strings.IndexAny(word, marker)
+		if first == -1 {
+			continue Word
+		}
+		// Is the marker prefixed only by punctuation?
+		for _, r := range word[:first] {
+			if !strings.ContainsRune(punctuation, r) {
+				continue Word
+			}
+		}
+		open, word := word[:first], word[first:]
+		char := word[0] // ASCII is OK.
+		close := ""
+		switch char {
+		default:
+			continue Word
+		case '_':
+			open += "<i>"
+			close = "</i>"
+		case '*':
+			open += "<b>"
+			close = "</b>"
+		case '`':
+			open += "<code>"
+			close = "</code>"
+		}
+		// Terminal punctuation is OK but must be peeled off.
+		last := strings.LastIndex(word, word[:1])
+		if last == 0 {
+			continue Word
+		}
+		head, tail := word[:last+1], word[last+1:]
+		for _, r := range tail {
+			if !strings.ContainsRune(punctuation, r) {
+				continue Word
+			}
+		}
+		b.Reset()
+		b.WriteString(open)
+		var wid int
+		for i := 1; i < len(head)-1; i += wid {
+			var r rune
+			r, wid = utf8.DecodeRuneInString(head[i:])
+			if r != rune(char) {
+				// Ordinary character.
+				b.WriteRune(r)
+				continue
+			}
+			if head[i+1] != char {
+				// Inner char becomes space.
+				b.WriteRune(' ')
+				continue
+			}
+			// Doubled char becomes real char.
+			// Not worth worrying about "_x__".
+			b.WriteByte(char)
+			wid++ // Consumed two chars, both ASCII.
+		}
+		b.WriteString(close) // Write closing tag.
+		b.WriteString(tail)  // Restore trailing punctuation.
+		words[w] = b.String()
+	}
+	return strings.Join(words, "")
+}
+
+// split is like strings.Fields but also returns the runs of spaces
+// and treats inline links as distinct words.
+func split(s string) []string {
+	var (
+		words = make([]string, 0, 10)
+		start = 0
+	)
+
+	// appendWord appends the string s[start:end] to the words slice.
+	// If the word contains the beginning of a link, the non-link portion
+	// of the word and the entire link are appended as separate words,
+	// and the start index is advanced to the end of the link.
+	appendWord := func(end int) {
+		if j := strings.Index(s[start:end], "[["); j > -1 {
+			if _, l := parseInlineLink(s[start+j:]); l > 0 {
+				// Append portion before link, if any.
+				if j > 0 {
+					words = append(words, s[start:start+j])
+				}
+				// Append link itself.
+				words = append(words, s[start+j:start+j+l])
+				// Advance start index to end of link.
+				start = start + j + l
+				return
+			}
+		}
+		// No link; just add the word.
+		words = append(words, s[start:end])
+		start = end
+	}
+
+	wasSpace := false
+	for i, r := range s {
+		isSpace := unicode.IsSpace(r)
+		if i > start && isSpace != wasSpace {
+			appendWord(i)
+		}
+		wasSpace = isSpace
+	}
+	for start < len(s) {
+		appendWord(len(s))
+	}
+	return words
+}
diff --git a/third_party/go.tools/present/style_test.go b/third_party/go.tools/present/style_test.go
new file mode 100644
index 0000000..d04db72
--- /dev/null
+++ b/third_party/go.tools/present/style_test.go
@@ -0,0 +1,116 @@
+// 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 present
+
+import (
+	"fmt"
+	"reflect"
+	"testing"
+)
+
+func TestSplit(t *testing.T) {
+	var tests = []struct {
+		in  string
+		out []string
+	}{
+		{"", []string{}},
+		{" ", []string{" "}},
+		{"abc", []string{"abc"}},
+		{"abc def", []string{"abc", " ", "def"}},
+		{"abc def ", []string{"abc", " ", "def", " "}},
+		{"hey [[http://golang.org][Gophers]] around",
+			[]string{"hey", " ", "[[http://golang.org][Gophers]]", " ", "around"}},
+		{"A [[http://golang.org/doc][two words]] link",
+			[]string{"A", " ", "[[http://golang.org/doc][two words]]", " ", "link"}},
+		{"Visit [[http://golang.org/doc]] now",
+			[]string{"Visit", " ", "[[http://golang.org/doc]]", " ", "now"}},
+		{"not [[http://golang.org/doc][a [[link]] ]] around",
+			[]string{"not", " ", "[[http://golang.org/doc][a [[link]]", " ", "]]", " ", "around"}},
+		{"[[http://golang.org][foo bar]]",
+			[]string{"[[http://golang.org][foo bar]]"}},
+		{"ends with [[http://golang.org][link]]",
+			[]string{"ends", " ", "with", " ", "[[http://golang.org][link]]"}},
+		{"my talk ([[http://talks.golang.org/][slides here]])",
+			[]string{"my", " ", "talk", " ", "(", "[[http://talks.golang.org/][slides here]]", ")"}},
+	}
+	for _, test := range tests {
+		out := split(test.in)
+		if !reflect.DeepEqual(out, test.out) {
+			t.Errorf("split(%q):\ngot\t%q\nwant\t%q", test.in, out, test.out)
+		}
+	}
+}
+
+func TestFont(t *testing.T) {
+	var tests = []struct {
+		in  string
+		out string
+	}{
+		{"", ""},
+		{" ", " "},
+		{"\tx", "\tx"},
+		{"_a_", "<i>a</i>"},
+		{"*a*", "<b>a</b>"},
+		{"`a`", "<code>a</code>"},
+		{"_a_b_", "<i>a b</i>"},
+		{"_a__b_", "<i>a_b</i>"},
+		{"_a___b_", "<i>a_ b</i>"},
+		{"*a**b*?", "<b>a*b</b>?"},
+		{"_a_<>_b_.", "<i>a <> b</i>."},
+		{"(_a_)", "(<i>a</i>)"},
+		{"((_a_), _b_, _c_).", "((<i>a</i>), <i>b</i>, <i>c</i>)."},
+		{"(_a)", "(_a)"},
+		{"(_a)", "(_a)"},
+		{"_Why_use_scoped__ptr_? Use plain ***ptr* instead.", "<i>Why use scoped_ptr</i>? Use plain <b>*ptr</b> instead."},
+		{"_hey_ [[http://golang.org][*Gophers*]] *around*",
+			`<i>hey</i> <a href="http://golang.org" target="_blank"><b>Gophers</b></a> <b>around</b>`},
+		{"_hey_ [[http://golang.org][so _many_ *Gophers*]] *around*",
+			`<i>hey</i> <a href="http://golang.org" target="_blank">so <i>many</i> <b>Gophers</b></a> <b>around</b>`},
+		{"Visit [[http://golang.org]] now",
+			`Visit <a href="http://golang.org" target="_blank">golang.org</a> now`},
+		{"my talk ([[http://talks.golang.org/][slides here]])",
+			`my talk (<a href="http://talks.golang.org/" target="_blank">slides here</a>)`},
+	}
+	for _, test := range tests {
+		out := font(test.in)
+		if out != test.out {
+			t.Errorf("font(%q):\ngot\t%q\nwant\t%q", test.in, out, test.out)
+		}
+	}
+}
+
+func TestStyle(t *testing.T) {
+	var tests = []struct {
+		in  string
+		out string
+	}{
+		{"", ""},
+		{" ", " "},
+		{"\tx", "\tx"},
+		{"_a_", "<i>a</i>"},
+		{"*a*", "<b>a</b>"},
+		{"`a`", "<code>a</code>"},
+		{"_a_b_", "<i>a b</i>"},
+		{"_a__b_", "<i>a_b</i>"},
+		{"_a___b_", "<i>a_ b</i>"},
+		{"*a**b*?", "<b>a*b</b>?"},
+		{"_a_<>_b_.", "<i>a &lt;&gt; b</i>."},
+		{"(_a_<>_b_)", "(<i>a &lt;&gt; b</i>)"},
+		{"((_a_), _b_, _c_).", "((<i>a</i>), <i>b</i>, <i>c</i>)."},
+		{"(_a)", "(_a)"},
+	}
+	for _, test := range tests {
+		out := string(Style(test.in))
+		if out != test.out {
+			t.Errorf("style(%q):\ngot\t%q\nwant\t%q", test.in, out, test.out)
+		}
+	}
+}
+
+func ExampleStyle() {
+	const s = "*Gophers* are _clearly_ > *cats*!"
+	fmt.Println(Style(s))
+	// Output: <b>Gophers</b> are <i>clearly</i> &gt; <b>cats</b>!
+}
diff --git a/third_party/go.tools/refactor/README b/third_party/go.tools/refactor/README
new file mode 100644
index 0000000..a315784
--- /dev/null
+++ b/third_party/go.tools/refactor/README
@@ -0,0 +1 @@
+golang.org/x/tools/refactor: libraries for refactoring tools.
diff --git a/third_party/go.tools/refactor/eg/eg.go b/third_party/go.tools/refactor/eg/eg.go
new file mode 100644
index 0000000..b2087f0
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/eg.go
@@ -0,0 +1,347 @@
+// Package eg implements the example-based refactoring tool whose
+// command-line is defined in golang.org/x/tools/cmd/eg.
+package eg
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/printer"
+	"go/token"
+	"os"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+const Help = `
+This tool implements example-based refactoring of expressions.
+
+The transformation is specified as a Go file defining two functions,
+'before' and 'after', of identical types.  Each function body consists
+of a single statement: either a return statement with a single
+(possibly multi-valued) expression, or an expression statement.  The
+'before' expression specifies a pattern and the 'after' expression its
+replacement.
+
+	package P
+ 	import ( "errors"; "fmt" )
+ 	func before(s string) error { return fmt.Errorf("%s", s) }
+ 	func after(s string)  error { return errors.New(s) }
+
+The expression statement form is useful when the expression has no
+result, for example:
+
+ 	func before(msg string) { log.Fatalf("%s", msg) }
+ 	func after(msg string)  { log.Fatal(msg) }
+
+The parameters of both functions are wildcards that may match any
+expression assignable to that type.  If the pattern contains multiple
+occurrences of the same parameter, each must match the same expression
+in the input for the pattern to match.  If the replacement contains
+multiple occurrences of the same parameter, the expression will be
+duplicated, possibly changing the side-effects.
+
+The tool analyses all Go code in the packages specified by the
+arguments, replacing all occurrences of the pattern with the
+substitution.
+
+So, the transform above would change this input:
+	err := fmt.Errorf("%s", "error: " + msg)
+to this output:
+	err := errors.New("error: " + msg)
+
+Identifiers, including qualified identifiers (p.X) are considered to
+match only if they denote the same object.  This allows correct
+matching even in the presence of dot imports, named imports and
+locally shadowed package names in the input program.
+
+Matching of type syntax is semantic, not syntactic: type syntax in the
+pattern matches type syntax in the input if the types are identical.
+Thus, func(x int) matches func(y int).
+
+This tool was inspired by other example-based refactoring tools,
+'gofmt -r' for Go and Refaster for Java.
+
+
+LIMITATIONS
+===========
+
+EXPRESSIVENESS
+
+Only refactorings that replace one expression with another, regardless
+of the expression's context, may be expressed.  Refactoring arbitrary
+statements (or sequences of statements) is a less well-defined problem
+and is less amenable to this approach.
+
+A pattern that contains a function literal (and hence statements)
+never matches.
+
+There is no way to generalize over related types, e.g. to express that
+a wildcard may have any integer type, for example.
+
+It is not possible to replace an expression by one of a different
+type, even in contexts where this is legal, such as x in fmt.Print(x).
+
+
+SAFETY
+
+Verifying that a transformation does not introduce type errors is very
+complex in the general case.  An innocuous-looking replacement of one
+constant by another (e.g. 1 to 2) may cause type errors relating to
+array types and indices, for example.  The tool performs only very
+superficial checks of type preservation.
+
+
+IMPORTS
+
+Although the matching algorithm is fully aware of scoping rules, the
+replacement algorithm is not, so the replacement code may contain
+incorrect identifier syntax for imported objects if there are dot
+imports, named imports or locally shadowed package names in the input
+program.
+
+Imports are added as needed, but they are not removed as needed.
+Run 'goimports' on the modified file for now.
+
+Dot imports are forbidden in the template.
+
+
+TIPS
+====
+
+Sometimes a little creativity is required to implement the desired
+migration.  This section lists a few tips and tricks.
+
+To remove the final parameter from a function, temporarily change the
+function signature so that the final parameter is variadic, as this
+allows legal calls both with and without the argument.  Then use eg to
+remove the final argument from all callers, and remove the variadic
+parameter by hand.  The reverse process can be used to add a final
+parameter.
+
+To add or remove parameters other than the final one, you must do it in
+stages: (1) declare a variant function f' with a different name and the
+desired parameters; (2) use eg to transform calls to f into calls to f',
+changing the arguments as needed; (3) change the declaration of f to
+match f'; (4) use eg to rename f' to f in all calls; (5) delete f'.
+`
+
+// TODO(adonovan): allow the tool to be invoked using relative package
+// directory names (./foo).  Requires changes to go/loader.
+
+// TODO(adonovan): expand upon the above documentation as an HTML page.
+
+// TODO(adonovan): eliminate dependency on loader.PackageInfo.
+// Move its TypeOf method into go/types.
+
+// A Transformer represents a single example-based transformation.
+type Transformer struct {
+	fset           *token.FileSet
+	verbose        bool
+	info           loader.PackageInfo // combined type info for template/input/output ASTs
+	seenInfos      map[*types.Info]bool
+	wildcards      map[*types.Var]bool                // set of parameters in func before()
+	env            map[string]ast.Expr                // maps parameter name to wildcard binding
+	importedObjs   map[types.Object]*ast.SelectorExpr // objects imported by after().
+	before, after  ast.Expr
+	allowWildcards bool
+
+	// Working state of Transform():
+	nsubsts    int            // number of substitutions made
+	currentPkg *types.Package // package of current call
+}
+
+// NewTransformer returns a transformer based on the specified template,
+// a package containing "before" and "after" functions as described
+// in the package documentation.
+//
+func NewTransformer(fset *token.FileSet, template *loader.PackageInfo, verbose bool) (*Transformer, error) {
+	// Check the template.
+	beforeSig := funcSig(template.Pkg, "before")
+	if beforeSig == nil {
+		return nil, fmt.Errorf("no 'before' func found in template")
+	}
+	afterSig := funcSig(template.Pkg, "after")
+	if afterSig == nil {
+		return nil, fmt.Errorf("no 'after' func found in template")
+	}
+
+	// TODO(adonovan): should we also check the names of the params match?
+	if !types.Identical(afterSig, beforeSig) {
+		return nil, fmt.Errorf("before %s and after %s functions have different signatures",
+			beforeSig, afterSig)
+	}
+
+	templateFile := template.Files[0]
+	for _, imp := range templateFile.Imports {
+		if imp.Name != nil && imp.Name.Name == "." {
+			// Dot imports are currently forbidden.  We
+			// make the simplifying assumption that all
+			// imports are regular, without local renames.
+			//TODO document
+			return nil, fmt.Errorf("dot-import (of %s) in template", imp.Path.Value)
+		}
+	}
+	var beforeDecl, afterDecl *ast.FuncDecl
+	for _, decl := range templateFile.Decls {
+		if decl, ok := decl.(*ast.FuncDecl); ok {
+			switch decl.Name.Name {
+			case "before":
+				beforeDecl = decl
+			case "after":
+				afterDecl = decl
+			}
+		}
+	}
+
+	before, err := soleExpr(beforeDecl)
+	if err != nil {
+		return nil, fmt.Errorf("before: %s", err)
+	}
+	after, err := soleExpr(afterDecl)
+	if err != nil {
+		return nil, fmt.Errorf("after: %s", err)
+	}
+
+	wildcards := make(map[*types.Var]bool)
+	for i := 0; i < beforeSig.Params().Len(); i++ {
+		wildcards[beforeSig.Params().At(i)] = true
+	}
+
+	// checkExprTypes returns an error if Tb (type of before()) is not
+	// safe to replace with Ta (type of after()).
+	//
+	// Only superficial checks are performed, and they may result in both
+	// false positives and negatives.
+	//
+	// Ideally, we would only require that the replacement be assignable
+	// to the context of a specific pattern occurrence, but the type
+	// checker doesn't record that information and it's complex to deduce.
+	// A Go type cannot capture all the constraints of a given expression
+	// context, which may include the size, constness, signedness,
+	// namedness or constructor of its type, and even the specific value
+	// of the replacement.  (Consider the rule that array literal keys
+	// must be unique.)  So we cannot hope to prove the safety of a
+	// transformation in general.
+	Tb := template.TypeOf(before)
+	Ta := template.TypeOf(after)
+	if types.AssignableTo(Tb, Ta) {
+		// safe: replacement is assignable to pattern.
+	} else if tuple, ok := Tb.(*types.Tuple); ok && tuple.Len() == 0 {
+		// safe: pattern has void type (must appear in an ExprStmt).
+	} else {
+		return nil, fmt.Errorf("%s is not a safe replacement for %s", Ta, Tb)
+	}
+
+	tr := &Transformer{
+		fset:           fset,
+		verbose:        verbose,
+		wildcards:      wildcards,
+		allowWildcards: true,
+		seenInfos:      make(map[*types.Info]bool),
+		importedObjs:   make(map[types.Object]*ast.SelectorExpr),
+		before:         before,
+		after:          after,
+	}
+
+	// Combine type info from the template and input packages, and
+	// type info for the synthesized ASTs too.  This saves us
+	// having to book-keep where each ast.Node originated as we
+	// construct the resulting hybrid AST.
+	//
+	// TODO(adonovan): move type utility methods of PackageInfo to
+	// types.Info, or at least into go/types.typeutil.
+	tr.info.Info = types.Info{
+		Types:      make(map[ast.Expr]types.TypeAndValue),
+		Defs:       make(map[*ast.Ident]types.Object),
+		Uses:       make(map[*ast.Ident]types.Object),
+		Selections: make(map[*ast.SelectorExpr]*types.Selection),
+	}
+	mergeTypeInfo(&tr.info.Info, &template.Info)
+
+	// Compute set of imported objects required by after().
+	// TODO reject dot-imports in pattern
+	ast.Inspect(after, func(n ast.Node) bool {
+		if n, ok := n.(*ast.SelectorExpr); ok {
+			if _, ok := tr.info.Selections[n]; !ok {
+				// qualified ident
+				obj := tr.info.Uses[n.Sel]
+				tr.importedObjs[obj] = n
+				return false // prune
+			}
+		}
+		return true // recur
+	})
+
+	return tr, nil
+}
+
+// WriteAST is a convenience function that writes AST f to the specified file.
+func WriteAST(fset *token.FileSet, filename string, f *ast.File) (err error) {
+	fh, err := os.Create(filename)
+	if err != nil {
+		return err
+	}
+	defer func() {
+		if err2 := fh.Close(); err != nil {
+			err = err2 // prefer earlier error
+		}
+	}()
+	return printer.Fprint(fh, fset, f)
+}
+
+// -- utilities --------------------------------------------------------
+
+// funcSig returns the signature of the specified package-level function.
+func funcSig(pkg *types.Package, name string) *types.Signature {
+	if f, ok := pkg.Scope().Lookup(name).(*types.Func); ok {
+		return f.Type().(*types.Signature)
+	}
+	return nil
+}
+
+// soleExpr returns the sole expression in the before/after template function.
+func soleExpr(fn *ast.FuncDecl) (ast.Expr, error) {
+	if fn.Body == nil {
+		return nil, fmt.Errorf("no body")
+	}
+	if len(fn.Body.List) != 1 {
+		return nil, fmt.Errorf("must contain a single statement")
+	}
+	switch stmt := fn.Body.List[0].(type) {
+	case *ast.ReturnStmt:
+		if len(stmt.Results) != 1 {
+			return nil, fmt.Errorf("return statement must have a single operand")
+		}
+		return stmt.Results[0], nil
+
+	case *ast.ExprStmt:
+		return stmt.X, nil
+	}
+
+	return nil, fmt.Errorf("must contain a single return or expression statement")
+}
+
+// mergeTypeInfo adds type info from src to dst.
+func mergeTypeInfo(dst, src *types.Info) {
+	for k, v := range src.Types {
+		dst.Types[k] = v
+	}
+	for k, v := range src.Defs {
+		dst.Defs[k] = v
+	}
+	for k, v := range src.Uses {
+		dst.Uses[k] = v
+	}
+	for k, v := range src.Selections {
+		dst.Selections[k] = v
+	}
+}
+
+// (debugging only)
+func astString(fset *token.FileSet, n ast.Node) string {
+	var buf bytes.Buffer
+	printer.Fprint(&buf, fset, n)
+	return buf.String()
+}
diff --git a/third_party/go.tools/refactor/eg/eg_test.go b/third_party/go.tools/refactor/eg/eg_test.go
new file mode 100644
index 0000000..66a5343
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/eg_test.go
@@ -0,0 +1,149 @@
+package eg_test
+
+import (
+	"bytes"
+	"flag"
+	"go/parser"
+	"go/token"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/refactor/eg"
+)
+
+// TODO(adonovan): more tests:
+// - of command-line tool
+// - of all parts of syntax
+// - of applying a template to a package it imports:
+//   the replacement syntax should use unqualified names for its objects.
+
+var (
+	updateFlag  = flag.Bool("update", false, "update the golden files")
+	verboseFlag = flag.Bool("verbose", false, "show matcher information")
+)
+
+func Test(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows":
+		t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS)
+	}
+
+	conf := loader.Config{
+		Fset:          token.NewFileSet(),
+		ParserMode:    parser.ParseComments,
+		SourceImports: true,
+	}
+
+	// Each entry is a single-file package.
+	// (Multi-file packages aren't interesting for this test.)
+	// Order matters: each non-template package is processed using
+	// the preceding template package.
+	for _, filename := range []string{
+		"testdata/A.template",
+		"testdata/A1.go",
+		"testdata/A2.go",
+
+		"testdata/B.template",
+		"testdata/B1.go",
+
+		"testdata/C.template",
+		"testdata/C1.go",
+
+		"testdata/D.template",
+		"testdata/D1.go",
+
+		"testdata/E.template",
+		"testdata/E1.go",
+
+		"testdata/F.template",
+		"testdata/F1.go",
+
+		"testdata/bad_type.template",
+		"testdata/no_before.template",
+		"testdata/no_after_return.template",
+		"testdata/type_mismatch.template",
+		"testdata/expr_type_mismatch.template",
+	} {
+		pkgname := strings.TrimSuffix(filepath.Base(filename), ".go")
+		if err := conf.CreateFromFilenames(pkgname, filename); err != nil {
+			t.Fatal(err)
+		}
+	}
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var xform *eg.Transformer
+	for _, info := range iprog.Created {
+		file := info.Files[0]
+		filename := iprog.Fset.File(file.Pos()).Name() // foo.go
+
+		if strings.HasSuffix(filename, "template") {
+			// a new template
+			shouldFail, _ := info.Pkg.Scope().Lookup("shouldFail").(*types.Const)
+			xform, err = eg.NewTransformer(iprog.Fset, info, *verboseFlag)
+			if err != nil {
+				if shouldFail == nil {
+					t.Errorf("NewTransformer(%s): %s", filename, err)
+				} else if want := exact.StringVal(shouldFail.Val()); !strings.Contains(err.Error(), want) {
+					t.Errorf("NewTransformer(%s): got error %q, want error %q", filename, err, want)
+				}
+			} else if shouldFail != nil {
+				t.Errorf("NewTransformer(%s) succeeded unexpectedly; want error %q",
+					filename, shouldFail.Val())
+			}
+			continue
+		}
+
+		if xform == nil {
+			t.Errorf("%s: no previous template", filename)
+			continue
+		}
+
+		// apply previous template to this package
+		n := xform.Transform(&info.Info, info.Pkg, file)
+		if n == 0 {
+			t.Errorf("%s: no matches", filename)
+			continue
+		}
+
+		got := filename + "t"       // foo.got
+		golden := filename + "lden" // foo.golden
+
+		// Write actual output to foo.got.
+		if err := eg.WriteAST(iprog.Fset, got, file); err != nil {
+			t.Error(err)
+		}
+		defer os.Remove(got)
+
+		// Compare foo.got with foo.golden.
+		var cmd *exec.Cmd
+		switch runtime.GOOS {
+		case "plan9":
+			cmd = exec.Command("/bin/diff", "-c", golden, got)
+		default:
+			cmd = exec.Command("/usr/bin/diff", "-u", golden, got)
+		}
+		buf := new(bytes.Buffer)
+		cmd.Stdout = buf
+		cmd.Stderr = os.Stderr
+		if err := cmd.Run(); err != nil {
+			t.Errorf("eg tests for %s failed: %s.\n%s\n", filename, err, buf)
+
+			if *updateFlag {
+				t.Logf("Updating %s...", golden)
+				if err := exec.Command("/bin/cp", got, golden).Run(); err != nil {
+					t.Errorf("Update failed: %s", err)
+				}
+			}
+		}
+	}
+}
diff --git a/third_party/go.tools/refactor/eg/match.go b/third_party/go.tools/refactor/eg/match.go
new file mode 100644
index 0000000..7064b09
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/match.go
@@ -0,0 +1,246 @@
+package eg
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"log"
+	"os"
+	"reflect"
+
+	"llvm.org/llgo/third_party/go.tools/go/exact"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// matchExpr reports whether pattern x matches y.
+//
+// If tr.allowWildcards, Idents in x that refer to parameters are
+// treated as wildcards, and match any y that is assignable to the
+// parameter type; matchExpr records this correspondence in tr.env.
+// Otherwise, matchExpr simply reports whether the two trees are
+// equivalent.
+//
+// A wildcard appearing more than once in the pattern must
+// consistently match the same tree.
+//
+func (tr *Transformer) matchExpr(x, y ast.Expr) bool {
+	if x == nil && y == nil {
+		return true
+	}
+	if x == nil || y == nil {
+		return false
+	}
+	x = unparen(x)
+	y = unparen(y)
+
+	// Is x a wildcard?  (a reference to a 'before' parameter)
+	if xobj, ok := tr.wildcardObj(x); ok {
+		return tr.matchWildcard(xobj, y)
+	}
+
+	// Object identifiers (including pkg-qualified ones)
+	// are handled semantically, not syntactically.
+	xobj := isRef(x, &tr.info)
+	yobj := isRef(y, &tr.info)
+	if xobj != nil {
+		return xobj == yobj
+	}
+	if yobj != nil {
+		return false
+	}
+
+	// TODO(adonovan): audit: we cannot assume these ast.Exprs
+	// contain non-nil pointers.  e.g. ImportSpec.Name may be a
+	// nil *ast.Ident.
+
+	if reflect.TypeOf(x) != reflect.TypeOf(y) {
+		return false
+	}
+	switch x := x.(type) {
+	case *ast.Ident:
+		log.Fatalf("unexpected Ident: %s", astString(tr.fset, x))
+
+	case *ast.BasicLit:
+		y := y.(*ast.BasicLit)
+		xval := exact.MakeFromLiteral(x.Value, x.Kind)
+		yval := exact.MakeFromLiteral(y.Value, y.Kind)
+		return exact.Compare(xval, token.EQL, yval)
+
+	case *ast.FuncLit:
+		// func literals (and thus statement syntax) never match.
+		return false
+
+	case *ast.CompositeLit:
+		y := y.(*ast.CompositeLit)
+		return (x.Type == nil) == (y.Type == nil) &&
+			(x.Type == nil || tr.matchType(x.Type, y.Type)) &&
+			tr.matchExprs(x.Elts, y.Elts)
+
+	case *ast.SelectorExpr:
+		y := y.(*ast.SelectorExpr)
+		return tr.matchSelectorExpr(x, y) &&
+			tr.info.Selections[x].Obj() == tr.info.Selections[y].Obj()
+
+	case *ast.IndexExpr:
+		y := y.(*ast.IndexExpr)
+		return tr.matchExpr(x.X, y.X) &&
+			tr.matchExpr(x.Index, y.Index)
+
+	case *ast.SliceExpr:
+		y := y.(*ast.SliceExpr)
+		return tr.matchExpr(x.X, y.X) &&
+			tr.matchExpr(x.Low, y.Low) &&
+			tr.matchExpr(x.High, y.High) &&
+			tr.matchExpr(x.Max, y.Max) &&
+			x.Slice3 == y.Slice3
+
+	case *ast.TypeAssertExpr:
+		y := y.(*ast.TypeAssertExpr)
+		return tr.matchExpr(x.X, y.X) &&
+			tr.matchType(x.Type, y.Type)
+
+	case *ast.CallExpr:
+		y := y.(*ast.CallExpr)
+		match := tr.matchExpr // function call
+		if tr.info.Types[x.Fun].IsType() {
+			match = tr.matchType // type conversion
+		}
+		return x.Ellipsis.IsValid() == y.Ellipsis.IsValid() &&
+			match(x.Fun, y.Fun) &&
+			tr.matchExprs(x.Args, y.Args)
+
+	case *ast.StarExpr:
+		y := y.(*ast.StarExpr)
+		return tr.matchExpr(x.X, y.X)
+
+	case *ast.UnaryExpr:
+		y := y.(*ast.UnaryExpr)
+		return x.Op == y.Op &&
+			tr.matchExpr(x.X, y.X)
+
+	case *ast.BinaryExpr:
+		y := y.(*ast.BinaryExpr)
+		return x.Op == y.Op &&
+			tr.matchExpr(x.X, y.X) &&
+			tr.matchExpr(x.Y, y.Y)
+
+	case *ast.KeyValueExpr:
+		y := y.(*ast.KeyValueExpr)
+		return tr.matchExpr(x.Key, y.Key) &&
+			tr.matchExpr(x.Value, y.Value)
+	}
+
+	panic(fmt.Sprintf("unhandled AST node type: %T", x))
+}
+
+func (tr *Transformer) matchExprs(xx, yy []ast.Expr) bool {
+	if len(xx) != len(yy) {
+		return false
+	}
+	for i := range xx {
+		if !tr.matchExpr(xx[i], yy[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+// matchType reports whether the two type ASTs denote identical types.
+func (tr *Transformer) matchType(x, y ast.Expr) bool {
+	tx := tr.info.Types[x].Type
+	ty := tr.info.Types[y].Type
+	return types.Identical(tx, ty)
+}
+
+func (tr *Transformer) wildcardObj(x ast.Expr) (*types.Var, bool) {
+	if x, ok := x.(*ast.Ident); ok && x != nil && tr.allowWildcards {
+		if xobj, ok := tr.info.Uses[x].(*types.Var); ok && tr.wildcards[xobj] {
+			return xobj, true
+		}
+	}
+	return nil, false
+}
+
+func (tr *Transformer) matchSelectorExpr(x, y *ast.SelectorExpr) bool {
+	if xobj, ok := tr.wildcardObj(x.X); ok {
+		field := x.Sel.Name
+		yt := tr.info.TypeOf(y.X)
+		o, _, _ := types.LookupFieldOrMethod(yt, true, tr.currentPkg, field)
+		if o != nil {
+			tr.env[xobj.Name()] = y.X // record binding
+			return true
+		}
+	}
+	return tr.matchExpr(x.X, y.X)
+}
+
+func (tr *Transformer) matchWildcard(xobj *types.Var, y ast.Expr) bool {
+	name := xobj.Name()
+
+	if tr.verbose {
+		fmt.Fprintf(os.Stderr, "%s: wildcard %s -> %s?: ",
+			tr.fset.Position(y.Pos()), name, astString(tr.fset, y))
+	}
+
+	// Check that y is assignable to the declared type of the param.
+	if yt := tr.info.TypeOf(y); !types.AssignableTo(yt, xobj.Type()) {
+		if tr.verbose {
+			fmt.Fprintf(os.Stderr, "%s not assignable to %s\n", yt, xobj.Type())
+		}
+		return false
+	}
+
+	// A wildcard matches any expression.
+	// If it appears multiple times in the pattern, it must match
+	// the same expression each time.
+	if old, ok := tr.env[name]; ok {
+		// found existing binding
+		tr.allowWildcards = false
+		r := tr.matchExpr(old, y)
+		if tr.verbose {
+			fmt.Fprintf(os.Stderr, "%t secondary match, primary was %s\n",
+				r, astString(tr.fset, old))
+		}
+		tr.allowWildcards = true
+		return r
+	}
+
+	if tr.verbose {
+		fmt.Fprintf(os.Stderr, "primary match\n")
+	}
+
+	tr.env[name] = y // record binding
+	return true
+}
+
+// -- utilities --------------------------------------------------------
+
+// unparen returns e with any enclosing parentheses stripped.
+// TODO(adonovan): move to astutil package.
+func unparen(e ast.Expr) ast.Expr {
+	for {
+		p, ok := e.(*ast.ParenExpr)
+		if !ok {
+			break
+		}
+		e = p.X
+	}
+	return e
+}
+
+// isRef returns the object referred to by this (possibly qualified)
+// identifier, or nil if the node is not a referring identifier.
+func isRef(n ast.Node, info *loader.PackageInfo) types.Object {
+	switch n := n.(type) {
+	case *ast.Ident:
+		return info.Uses[n]
+
+	case *ast.SelectorExpr:
+		if _, ok := info.Selections[n]; !ok {
+			// qualified ident
+			return info.Uses[n.Sel]
+		}
+	}
+	return nil
+}
diff --git a/third_party/go.tools/refactor/eg/rewrite.go b/third_party/go.tools/refactor/eg/rewrite.go
new file mode 100644
index 0000000..4b7a52a
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/rewrite.go
@@ -0,0 +1,340 @@
+package eg
+
+// This file defines the AST rewriting pass.
+// Most of it was plundered directly from
+// $GOROOT/src/cmd/gofmt/rewrite.go (after convergent evolution).
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"reflect"
+	"sort"
+	"strconv"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/astutil"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// Transform applies the transformation to the specified parsed file,
+// whose type information is supplied in info, and returns the number
+// of replacements that were made.
+//
+// It mutates the AST in place (the identity of the root node is
+// unchanged), and may add nodes for which no type information is
+// available in info.
+//
+// Derived from rewriteFile in $GOROOT/src/cmd/gofmt/rewrite.go.
+//
+func (tr *Transformer) Transform(info *types.Info, pkg *types.Package, file *ast.File) int {
+	if !tr.seenInfos[info] {
+		tr.seenInfos[info] = true
+		mergeTypeInfo(&tr.info.Info, info)
+	}
+	tr.currentPkg = pkg
+	tr.nsubsts = 0
+
+	if tr.verbose {
+		fmt.Fprintf(os.Stderr, "before: %s\n", astString(tr.fset, tr.before))
+		fmt.Fprintf(os.Stderr, "after: %s\n", astString(tr.fset, tr.after))
+	}
+
+	var f func(rv reflect.Value) reflect.Value
+	f = func(rv reflect.Value) reflect.Value {
+		// don't bother if val is invalid to start with
+		if !rv.IsValid() {
+			return reflect.Value{}
+		}
+
+		rv = apply(f, rv)
+
+		e := rvToExpr(rv)
+		if e != nil {
+			savedEnv := tr.env
+			tr.env = make(map[string]ast.Expr) // inefficient!  Use a slice of k/v pairs
+
+			if tr.matchExpr(tr.before, e) {
+				if tr.verbose {
+					fmt.Fprintf(os.Stderr, "%s matches %s",
+						astString(tr.fset, tr.before), astString(tr.fset, e))
+					if len(tr.env) > 0 {
+						fmt.Fprintf(os.Stderr, " with:")
+						for name, ast := range tr.env {
+							fmt.Fprintf(os.Stderr, " %s->%s",
+								name, astString(tr.fset, ast))
+						}
+					}
+					fmt.Fprintf(os.Stderr, "\n")
+				}
+				tr.nsubsts++
+
+				// Clone the replacement tree, performing parameter substitution.
+				// We update all positions to n.Pos() to aid comment placement.
+				rv = tr.subst(tr.env, reflect.ValueOf(tr.after),
+					reflect.ValueOf(e.Pos()))
+			}
+			tr.env = savedEnv
+		}
+
+		return rv
+	}
+	file2 := apply(f, reflect.ValueOf(file)).Interface().(*ast.File)
+
+	// By construction, the root node is unchanged.
+	if file != file2 {
+		panic("BUG")
+	}
+
+	// Add any necessary imports.
+	// TODO(adonovan): remove no-longer needed imports too.
+	if tr.nsubsts > 0 {
+		pkgs := make(map[string]*types.Package)
+		for obj := range tr.importedObjs {
+			pkgs[obj.Pkg().Path()] = obj.Pkg()
+		}
+
+		for _, imp := range file.Imports {
+			path, _ := strconv.Unquote(imp.Path.Value)
+			delete(pkgs, path)
+		}
+		delete(pkgs, pkg.Path()) // don't import self
+
+		// NB: AddImport may completely replace the AST!
+		// It thus renders info and tr.info no longer relevant to file.
+		var paths []string
+		for path := range pkgs {
+			paths = append(paths, path)
+		}
+		sort.Strings(paths)
+		for _, path := range paths {
+			astutil.AddImport(tr.fset, file, path)
+		}
+	}
+
+	tr.currentPkg = nil
+
+	return tr.nsubsts
+}
+
+// setValue is a wrapper for x.SetValue(y); it protects
+// the caller from panics if x cannot be changed to y.
+func setValue(x, y reflect.Value) {
+	// don't bother if y is invalid to start with
+	if !y.IsValid() {
+		return
+	}
+	defer func() {
+		if x := recover(); x != nil {
+			if s, ok := x.(string); ok &&
+				(strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
+				// x cannot be set to y - ignore this rewrite
+				return
+			}
+			panic(x)
+		}
+	}()
+	x.Set(y)
+}
+
+// Values/types for special cases.
+var (
+	objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
+	scopePtrNil  = reflect.ValueOf((*ast.Scope)(nil))
+
+	identType        = reflect.TypeOf((*ast.Ident)(nil))
+	selectorExprType = reflect.TypeOf((*ast.SelectorExpr)(nil))
+	objectPtrType    = reflect.TypeOf((*ast.Object)(nil))
+	positionType     = reflect.TypeOf(token.NoPos)
+	callExprType     = reflect.TypeOf((*ast.CallExpr)(nil))
+	scopePtrType     = reflect.TypeOf((*ast.Scope)(nil))
+)
+
+// apply replaces each AST field x in val with f(x), returning val.
+// To avoid extra conversions, f operates on the reflect.Value form.
+func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value {
+	if !val.IsValid() {
+		return reflect.Value{}
+	}
+
+	// *ast.Objects introduce cycles and are likely incorrect after
+	// rewrite; don't follow them but replace with nil instead
+	if val.Type() == objectPtrType {
+		return objectPtrNil
+	}
+
+	// similarly for scopes: they are likely incorrect after a rewrite;
+	// replace them with nil
+	if val.Type() == scopePtrType {
+		return scopePtrNil
+	}
+
+	switch v := reflect.Indirect(val); v.Kind() {
+	case reflect.Slice:
+		for i := 0; i < v.Len(); i++ {
+			e := v.Index(i)
+			setValue(e, f(e))
+		}
+	case reflect.Struct:
+		for i := 0; i < v.NumField(); i++ {
+			e := v.Field(i)
+			setValue(e, f(e))
+		}
+	case reflect.Interface:
+		e := v.Elem()
+		setValue(v, f(e))
+	}
+	return val
+}
+
+// subst returns a copy of (replacement) pattern with values from env
+// substituted in place of wildcards and pos used as the position of
+// tokens from the pattern.  if env == nil, subst returns a copy of
+// pattern and doesn't change the line number information.
+func (tr *Transformer) subst(env map[string]ast.Expr, pattern, pos reflect.Value) reflect.Value {
+	if !pattern.IsValid() {
+		return reflect.Value{}
+	}
+
+	// *ast.Objects introduce cycles and are likely incorrect after
+	// rewrite; don't follow them but replace with nil instead
+	if pattern.Type() == objectPtrType {
+		return objectPtrNil
+	}
+
+	// similarly for scopes: they are likely incorrect after a rewrite;
+	// replace them with nil
+	if pattern.Type() == scopePtrType {
+		return scopePtrNil
+	}
+
+	// Wildcard gets replaced with map value.
+	if env != nil && pattern.Type() == identType {
+		id := pattern.Interface().(*ast.Ident)
+		if old, ok := env[id.Name]; ok {
+			return tr.subst(nil, reflect.ValueOf(old), reflect.Value{})
+		}
+	}
+
+	// Emit qualified identifiers in the pattern by appropriate
+	// (possibly qualified) identifier in the input.
+	//
+	// The template cannot contain dot imports, so all identifiers
+	// for imported objects are explicitly qualified.
+	//
+	// We assume (unsoundly) that there are no dot or named
+	// imports in the input code, nor are any imported package
+	// names shadowed, so the usual normal qualified identifier
+	// syntax may be used.
+	// TODO(adonovan): fix: avoid this assumption.
+	//
+	// A refactoring may be applied to a package referenced by the
+	// template.  Objects belonging to the current package are
+	// denoted by unqualified identifiers.
+	//
+	if tr.importedObjs != nil && pattern.Type() == selectorExprType {
+		obj := isRef(pattern.Interface().(*ast.SelectorExpr), &tr.info)
+		if obj != nil {
+			if sel, ok := tr.importedObjs[obj]; ok {
+				var id ast.Expr
+				if obj.Pkg() == tr.currentPkg {
+					id = sel.Sel // unqualified
+				} else {
+					id = sel // pkg-qualified
+				}
+
+				// Return a clone of id.
+				saved := tr.importedObjs
+				tr.importedObjs = nil // break cycle
+				r := tr.subst(nil, reflect.ValueOf(id), pos)
+				tr.importedObjs = saved
+				return r
+			}
+		}
+	}
+
+	if pos.IsValid() && pattern.Type() == positionType {
+		// use new position only if old position was valid in the first place
+		if old := pattern.Interface().(token.Pos); !old.IsValid() {
+			return pattern
+		}
+		return pos
+	}
+
+	// Otherwise copy.
+	switch p := pattern; p.Kind() {
+	case reflect.Slice:
+		v := reflect.MakeSlice(p.Type(), p.Len(), p.Len())
+		for i := 0; i < p.Len(); i++ {
+			v.Index(i).Set(tr.subst(env, p.Index(i), pos))
+		}
+		return v
+
+	case reflect.Struct:
+		v := reflect.New(p.Type()).Elem()
+		for i := 0; i < p.NumField(); i++ {
+			v.Field(i).Set(tr.subst(env, p.Field(i), pos))
+		}
+		return v
+
+	case reflect.Ptr:
+		v := reflect.New(p.Type()).Elem()
+		if elem := p.Elem(); elem.IsValid() {
+			v.Set(tr.subst(env, elem, pos).Addr())
+		}
+
+		// Duplicate type information for duplicated ast.Expr.
+		// All ast.Node implementations are *structs,
+		// so this case catches them all.
+		if e := rvToExpr(v); e != nil {
+			updateTypeInfo(&tr.info.Info, e, p.Interface().(ast.Expr))
+		}
+		return v
+
+	case reflect.Interface:
+		v := reflect.New(p.Type()).Elem()
+		if elem := p.Elem(); elem.IsValid() {
+			v.Set(tr.subst(env, elem, pos))
+		}
+		return v
+	}
+
+	return pattern
+}
+
+// -- utilities -------------------------------------------------------
+
+func rvToExpr(rv reflect.Value) ast.Expr {
+	if rv.CanInterface() {
+		if e, ok := rv.Interface().(ast.Expr); ok {
+			return e
+		}
+	}
+	return nil
+}
+
+// updateTypeInfo duplicates type information for the existing AST old
+// so that it also applies to duplicated AST new.
+func updateTypeInfo(info *types.Info, new, old ast.Expr) {
+	switch new := new.(type) {
+	case *ast.Ident:
+		orig := old.(*ast.Ident)
+		if obj, ok := info.Defs[orig]; ok {
+			info.Defs[new] = obj
+		}
+		if obj, ok := info.Uses[orig]; ok {
+			info.Uses[new] = obj
+		}
+
+	case *ast.SelectorExpr:
+		orig := old.(*ast.SelectorExpr)
+		if sel, ok := info.Selections[orig]; ok {
+			info.Selections[new] = sel
+		}
+	}
+
+	if tv, ok := info.Types[old]; ok {
+		info.Types[new] = tv
+	}
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/A.template b/third_party/go.tools/refactor/eg/testdata/A.template
new file mode 100644
index 0000000..f611961
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/A.template
@@ -0,0 +1,13 @@
+// +build ignore
+
+package template
+
+// Basic test of type-aware expression refactoring.
+
+import (
+	"errors"
+	"fmt"
+)
+
+func before(s string) error { return fmt.Errorf("%s", s) }
+func after(s string) error  { return errors.New(s) }
diff --git a/third_party/go.tools/refactor/eg/testdata/A1.go b/third_party/go.tools/refactor/eg/testdata/A1.go
new file mode 100644
index 0000000..9e65eb3
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/A1.go
@@ -0,0 +1,51 @@
+// +build ignore
+
+package A1
+
+import (
+	. "fmt"
+	myfmt "fmt"
+	"os"
+	"strings"
+)
+
+func example(n int) {
+	x := "foo" + strings.Repeat("\t", n)
+	// Match, despite named import.
+	myfmt.Errorf("%s", x)
+
+	// Match, despite dot import.
+	Errorf("%s", x)
+
+	// Match: multiple matches in same function are possible.
+	myfmt.Errorf("%s", x)
+
+	// No match: wildcarded operand has the wrong type.
+	myfmt.Errorf("%s", 3)
+
+	// No match: function operand doesn't match.
+	myfmt.Printf("%s", x)
+
+	// No match again, dot import.
+	Printf("%s", x)
+
+	// Match.
+	myfmt.Fprint(os.Stderr, myfmt.Errorf("%s", x+"foo"))
+
+	// No match: though this literally matches the template,
+	// fmt doesn't resolve to a package here.
+	var fmt struct{ Errorf func(string, string) }
+	fmt.Errorf("%s", x)
+
+	// Recursive matching:
+
+	// Match: both matches are well-typed, so both succeed.
+	myfmt.Errorf("%s", myfmt.Errorf("%s", x+"foo").Error())
+
+	// Outer match succeeds, inner doesn't: 3 has wrong type.
+	myfmt.Errorf("%s", myfmt.Errorf("%s", 3).Error())
+
+	// Inner match succeeds, outer doesn't: the inner replacement
+	// has the wrong type (error not string).
+	myfmt.Errorf("%s", myfmt.Errorf("%s", x+"foo"))
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/A1.golden b/third_party/go.tools/refactor/eg/testdata/A1.golden
new file mode 100644
index 0000000..4f7ba82
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/A1.golden
@@ -0,0 +1,52 @@
+// +build ignore
+
+package A1
+
+import (
+	. "fmt"
+	"errors"
+	myfmt "fmt"
+	"os"
+	"strings"
+)
+
+func example(n int) {
+	x := "foo" + strings.Repeat("\t", n)
+	// Match, despite named import.
+	errors.New(x)
+
+	// Match, despite dot import.
+	errors.New(x)
+
+	// Match: multiple matches in same function are possible.
+	errors.New(x)
+
+	// No match: wildcarded operand has the wrong type.
+	myfmt.Errorf("%s", 3)
+
+	// No match: function operand doesn't match.
+	myfmt.Printf("%s", x)
+
+	// No match again, dot import.
+	Printf("%s", x)
+
+	// Match.
+	myfmt.Fprint(os.Stderr, errors.New(x+"foo"))
+
+	// No match: though this literally matches the template,
+	// fmt doesn't resolve to a package here.
+	var fmt struct{ Errorf func(string, string) }
+	fmt.Errorf("%s", x)
+
+	// Recursive matching:
+
+	// Match: both matches are well-typed, so both succeed.
+	errors.New(errors.New(x + "foo").Error())
+
+	// Outer match succeeds, inner doesn't: 3 has wrong type.
+	errors.New(myfmt.Errorf("%s", 3).Error())
+
+	// Inner match succeeds, outer doesn't: the inner replacement
+	// has the wrong type (error not string).
+	myfmt.Errorf("%s", errors.New(x+"foo"))
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/A2.go b/third_party/go.tools/refactor/eg/testdata/A2.go
new file mode 100644
index 0000000..3ae29ad
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/A2.go
@@ -0,0 +1,12 @@
+// +build ignore
+
+package A2
+
+// This refactoring causes addition of "errors" import.
+// TODO(adonovan): fix: it should also remove "fmt".
+
+import myfmt "fmt"
+
+func example(n int) {
+	myfmt.Errorf("%s", "")
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/A2.golden b/third_party/go.tools/refactor/eg/testdata/A2.golden
new file mode 100644
index 0000000..5c2384b
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/A2.golden
@@ -0,0 +1,15 @@
+// +build ignore
+
+package A2
+
+// This refactoring causes addition of "errors" import.
+// TODO(adonovan): fix: it should also remove "fmt".
+
+import (
+	myfmt "fmt"
+	"errors"
+)
+
+func example(n int) {
+	errors.New("")
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/B.template b/third_party/go.tools/refactor/eg/testdata/B.template
new file mode 100644
index 0000000..c16627b
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/B.template
@@ -0,0 +1,9 @@
+package template
+
+// Basic test of expression refactoring.
+// (Types are not important in this case; it could be done with gofmt -r.)
+
+import "time"
+
+func before(t time.Time) time.Duration { return time.Now().Sub(t) }
+func after(t time.Time) time.Duration  { return time.Since(t) }
diff --git a/third_party/go.tools/refactor/eg/testdata/B1.go b/third_party/go.tools/refactor/eg/testdata/B1.go
new file mode 100644
index 0000000..8b52546
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/B1.go
@@ -0,0 +1,17 @@
+// +build ignore
+
+package B1
+
+import "time"
+
+var startup = time.Now()
+
+func example() time.Duration {
+	before := time.Now()
+	time.Sleep(1)
+	return time.Now().Sub(before)
+}
+
+func msSinceStartup() int64 {
+	return int64(time.Now().Sub(startup) / time.Millisecond)
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/B1.golden b/third_party/go.tools/refactor/eg/testdata/B1.golden
new file mode 100644
index 0000000..4d4da21
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/B1.golden
@@ -0,0 +1,17 @@
+// +build ignore
+
+package B1
+
+import "time"
+
+var startup = time.Now()
+
+func example() time.Duration {
+	before := time.Now()
+	time.Sleep(1)
+	return time.Since(before)
+}
+
+func msSinceStartup() int64 {
+	return int64(time.Since(startup) / time.Millisecond)
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/C.template b/third_party/go.tools/refactor/eg/testdata/C.template
new file mode 100644
index 0000000..f6f94d4
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/C.template
@@ -0,0 +1,10 @@
+package template
+
+// Test of repeated use of wildcard in pattern.
+
+// NB: multiple patterns would be required to handle variants such as
+// s[:len(s)], s[x:len(s)], etc, since a wildcard can't match nothing at all.
+// TODO(adonovan): support multiple templates in a single pass.
+
+func before(s string) string { return s[:len(s)] }
+func after(s string) string  { return s }
diff --git a/third_party/go.tools/refactor/eg/testdata/C1.go b/third_party/go.tools/refactor/eg/testdata/C1.go
new file mode 100644
index 0000000..523b388
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/C1.go
@@ -0,0 +1,22 @@
+// +build ignore
+
+package C1
+
+import "strings"
+
+func example() {
+	x := "foo"
+	println(x[:len(x)])
+
+	// Match, but the transformation is not sound w.r.t. possible side effects.
+	println(strings.Repeat("*", 3)[:len(strings.Repeat("*", 3))])
+
+	// No match, since second use of wildcard doesn't match first.
+	println(strings.Repeat("*", 3)[:len(strings.Repeat("*", 2))])
+
+	// Recursive match demonstrating bottom-up rewrite:
+	// only after the inner replacement occurs does the outer syntax match.
+	println((x[:len(x)])[:len(x[:len(x)])])
+	// -> (x[:len(x)])
+	// -> x
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/C1.golden b/third_party/go.tools/refactor/eg/testdata/C1.golden
new file mode 100644
index 0000000..ae7759d
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/C1.golden
@@ -0,0 +1,22 @@
+// +build ignore
+
+package C1
+
+import "strings"
+
+func example() {
+	x := "foo"
+	println(x)
+
+	// Match, but the transformation is not sound w.r.t. possible side effects.
+	println(strings.Repeat("*", 3))
+
+	// No match, since second use of wildcard doesn't match first.
+	println(strings.Repeat("*", 3)[:len(strings.Repeat("*", 2))])
+
+	// Recursive match demonstrating bottom-up rewrite:
+	// only after the inner replacement occurs does the outer syntax match.
+	println(x)
+	// -> (x[:len(x)])
+	// -> x
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/D.template b/third_party/go.tools/refactor/eg/testdata/D.template
new file mode 100644
index 0000000..6d3b6fe
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/D.template
@@ -0,0 +1,8 @@
+package template
+
+import "fmt"
+
+// Test of semantic (not syntactic) matching of basic literals.
+
+func before() (int, error) { return fmt.Println(123, "a") }
+func after() (int, error)  { return fmt.Println(456, "!") }
diff --git a/third_party/go.tools/refactor/eg/testdata/D1.go b/third_party/go.tools/refactor/eg/testdata/D1.go
new file mode 100644
index 0000000..ae0a806
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/D1.go
@@ -0,0 +1,12 @@
+// +build ignore
+
+package D1
+
+import "fmt"
+
+func example() {
+	fmt.Println(123, "a")         // match
+	fmt.Println(0x7b, `a`)        // match
+	fmt.Println(0173, "\x61")     // match
+	fmt.Println(100+20+3, "a"+"") // no match: constant expressions, but not basic literals
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/D1.golden b/third_party/go.tools/refactor/eg/testdata/D1.golden
new file mode 100644
index 0000000..3f2dc59
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/D1.golden
@@ -0,0 +1,12 @@
+// +build ignore
+
+package D1
+
+import "fmt"
+
+func example() {
+	fmt.Println(456, "!")		// match
+	fmt.Println(456, "!")		// match
+	fmt.Println(456, "!")		// match
+	fmt.Println(100+20+3, "a"+"")	// no match: constant expressions, but not basic literals
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/E.template b/third_party/go.tools/refactor/eg/testdata/E.template
new file mode 100644
index 0000000..4bbbd11
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/E.template
@@ -0,0 +1,12 @@
+package template
+
+import (
+	"fmt"
+	"log"
+	"os"
+)
+
+// Replace call to void function by call to non-void function.
+
+func before(x interface{}) { log.Fatal(x) }
+func after(x interface{})  { fmt.Fprintf(os.Stderr, "warning: %v", x) }
diff --git a/third_party/go.tools/refactor/eg/testdata/E1.go b/third_party/go.tools/refactor/eg/testdata/E1.go
new file mode 100644
index 0000000..3ea1793
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/E1.go
@@ -0,0 +1,9 @@
+// +build ignore
+
+package E1
+
+import "log"
+
+func example() {
+	log.Fatal("oops") // match
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/E1.golden b/third_party/go.tools/refactor/eg/testdata/E1.golden
new file mode 100644
index 0000000..a0adfc8
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/E1.golden
@@ -0,0 +1,13 @@
+// +build ignore
+
+package E1
+
+import (
+	"log"
+	"os"
+	"fmt"
+)
+
+func example() {
+	fmt.Fprintf(os.Stderr, "warning: %v", "oops")	// match
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/F.template b/third_party/go.tools/refactor/eg/testdata/F.template
new file mode 100644
index 0000000..21e1bd2
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/F.template
@@ -0,0 +1,8 @@
+package templates
+
+// Test 
+
+import "sync"
+
+func before(s sync.RWMutex) { s.Lock() }
+func after(s sync.RWMutex) { s.RLock() }
\ No newline at end of file
diff --git a/third_party/go.tools/refactor/eg/testdata/F1.go b/third_party/go.tools/refactor/eg/testdata/F1.go
new file mode 100644
index 0000000..0b9c678
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/F1.go
@@ -0,0 +1,48 @@
+// +build ignore
+
+package F1
+
+import "sync"
+
+func example(n int) {
+	var x struct {
+		mutex sync.RWMutex
+	}
+
+	var y struct {
+		sync.RWMutex
+	}
+
+	type l struct {
+		sync.RWMutex
+	}
+
+	var z struct {
+		l
+	}
+
+	var a struct {
+		*l
+	}
+
+	var b struct{ Lock func() }
+
+	// Match
+	x.mutex.Lock()
+
+	// Match
+	y.Lock()
+
+	// Match indirect
+	z.Lock()
+
+	// Should be no match however currently matches due to:
+	// https://code.google.com/p/go/issues/detail?id=8584
+	// Will start failing when this is fixed then just change golden to
+	// No match pointer indirect
+	// a.Lock()
+	a.Lock()
+
+	// No match
+	b.Lock()
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/F1.golden b/third_party/go.tools/refactor/eg/testdata/F1.golden
new file mode 100644
index 0000000..c691b37
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/F1.golden
@@ -0,0 +1,48 @@
+// +build ignore
+
+package F1
+
+import "sync"
+
+func example(n int) {
+	var x struct {
+		mutex sync.RWMutex
+	}
+
+	var y struct {
+		sync.RWMutex
+	}
+
+	type l struct {
+		sync.RWMutex
+	}
+
+	var z struct {
+		l
+	}
+
+	var a struct {
+		*l
+	}
+
+	var b struct{ Lock func() }
+
+	// Match
+	x.mutex.RLock()
+
+	// Match
+	y.RLock()
+
+	// Match indirect
+	z.RLock()
+
+	// Should be no match however currently matches due to:
+	// https://code.google.com/p/go/issues/detail?id=8584
+	// Will start failing when this is fixed then just change golden to
+	// No match pointer indirect
+	// a.Lock()
+	a.RLock()
+
+	// No match
+	b.Lock()
+}
diff --git a/third_party/go.tools/refactor/eg/testdata/bad_type.template b/third_party/go.tools/refactor/eg/testdata/bad_type.template
new file mode 100644
index 0000000..6d53d7e
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/bad_type.template
@@ -0,0 +1,8 @@
+package template
+
+// Test in which replacement has a different type.
+
+const shouldFail = "int is not a safe replacement for string"
+
+func before() interface{} { return "three" }
+func after() interface{}  { return 3 }
diff --git a/third_party/go.tools/refactor/eg/testdata/expr_type_mismatch.template b/third_party/go.tools/refactor/eg/testdata/expr_type_mismatch.template
new file mode 100644
index 0000000..2c5c3f0
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/expr_type_mismatch.template
@@ -0,0 +1,15 @@
+package template
+
+import (
+	"crypto/x509"
+	"fmt"
+)
+
+// This test demonstrates a false negative: according to the language
+// rules this replacement should be ok, but types.Assignable doesn't work
+// in the expected way (elementwise assignability) for tuples.
+// Perhaps that's even a type-checker bug?
+const shouldFail = "(n int, err error) is not a safe replacement for (key interface{}, err error)"
+
+func before() (interface{}, error) { return x509.ParsePKCS8PrivateKey(nil) }
+func after() (interface{}, error)  { return fmt.Print() }
diff --git a/third_party/go.tools/refactor/eg/testdata/no_after_return.template b/third_party/go.tools/refactor/eg/testdata/no_after_return.template
new file mode 100644
index 0000000..536b01e
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/no_after_return.template
@@ -0,0 +1,6 @@
+package template
+
+const shouldFail = "after: must contain a single statement"
+
+func before() int { return 0 }
+func after() int  { println(); return 0 }
diff --git a/third_party/go.tools/refactor/eg/testdata/no_before.template b/third_party/go.tools/refactor/eg/testdata/no_before.template
new file mode 100644
index 0000000..9205e66
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/no_before.template
@@ -0,0 +1,5 @@
+package template
+
+const shouldFail = "no 'before' func found in template"
+
+func Before() {}
diff --git a/third_party/go.tools/refactor/eg/testdata/type_mismatch.template b/third_party/go.tools/refactor/eg/testdata/type_mismatch.template
new file mode 100644
index 0000000..787c9a7
--- /dev/null
+++ b/third_party/go.tools/refactor/eg/testdata/type_mismatch.template
@@ -0,0 +1,6 @@
+package template
+
+const shouldFail = "different signatures"
+
+func before() int   { return 0 }
+func after() string { return "" }
diff --git a/third_party/go.tools/refactor/importgraph/graph.go b/third_party/go.tools/refactor/importgraph/graph.go
new file mode 100644
index 0000000..71d0610
--- /dev/null
+++ b/third_party/go.tools/refactor/importgraph/graph.go
@@ -0,0 +1,125 @@
+// Copyright 2014 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 importgraph computes the forward and reverse import
+// dependency graphs for all packages in a Go workspace.
+package importgraph
+
+import (
+	"go/build"
+	"sync"
+
+	"llvm.org/llgo/third_party/go.tools/go/buildutil"
+)
+
+// A Graph is an import dependency graph, either forward or reverse.
+//
+// The graph maps each node (a package import path) to the set of its
+// successors in the graph.  For a forward graph, this is the set of
+// imported packages (prerequisites); for a reverse graph, it is the set
+// of importing packages (clients).
+//
+type Graph map[string]map[string]bool
+
+func (g Graph) addEdge(from, to string) {
+	edges := g[from]
+	if edges == nil {
+		edges = make(map[string]bool)
+		g[from] = edges
+	}
+	edges[to] = true
+}
+
+// Search returns all the nodes of the graph reachable from
+// any of the specified roots, by following edges forwards.
+// Relationally, this is the reflexive transitive closure.
+func (g Graph) Search(roots ...string) map[string]bool {
+	seen := make(map[string]bool)
+	var visit func(x string)
+	visit = func(x string) {
+		if !seen[x] {
+			seen[x] = true
+			for y := range g[x] {
+				visit(y)
+			}
+		}
+	}
+	for _, root := range roots {
+		visit(root)
+	}
+	return seen
+}
+
+// Builds scans the specified Go workspace and builds the forward and
+// reverse import dependency graphs for all its packages.
+// It also returns a mapping from import paths to errors for packages
+// that could not be loaded.
+func Build(ctxt *build.Context) (forward, reverse Graph, errors map[string]error) {
+	// The (sole) graph builder goroutine receives a stream of import
+	// edges from the package loading goroutine.
+	forward = make(Graph)
+	reverse = make(Graph)
+	edgec := make(chan [2]string)
+	go func() {
+		for edge := range edgec {
+			if edge[1] == "C" {
+				continue // "C" is fake
+			}
+			forward.addEdge(edge[0], edge[1])
+			reverse.addEdge(edge[1], edge[0])
+		}
+	}()
+
+	// The (sole) error goroutine receives a stream of ReadDir and
+	// Import errors.
+	type pathError struct {
+		path string
+		err  error
+	}
+	errorc := make(chan pathError)
+	go func() {
+		for e := range errorc {
+			if errors == nil {
+				errors = make(map[string]error)
+			}
+			errors[e.path] = e.err
+		}
+	}()
+
+	var wg sync.WaitGroup
+	buildutil.ForEachPackage(ctxt, func(path string, err error) {
+		if err != nil {
+			errorc <- pathError{path, err}
+			return
+		}
+		wg.Add(1)
+		// The import goroutines load the metadata for each package.
+		go func(path string) {
+			defer wg.Done()
+			bp, err := ctxt.Import(path, "", 0)
+			if _, ok := err.(*build.NoGoError); ok {
+				return // empty directory is not an error
+			}
+			if err != nil {
+				errorc <- pathError{path, err}
+				return
+			}
+			for _, imp := range bp.Imports {
+				edgec <- [2]string{path, imp}
+			}
+			for _, imp := range bp.TestImports {
+				edgec <- [2]string{path, imp}
+			}
+			for _, imp := range bp.XTestImports {
+				edgec <- [2]string{path, imp}
+			}
+		}(path)
+	})
+	wg.Wait()
+
+	close(edgec)
+	close(errorc)
+
+	return forward, reverse, errors
+}
diff --git a/third_party/go.tools/refactor/importgraph/graph_test.go b/third_party/go.tools/refactor/importgraph/graph_test.go
new file mode 100644
index 0000000..1c0e178
--- /dev/null
+++ b/third_party/go.tools/refactor/importgraph/graph_test.go
@@ -0,0 +1,95 @@
+package importgraph_test
+
+import (
+	"go/build"
+	"runtime"
+	"sort"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/refactor/importgraph"
+
+	_ "crypto/hmac" // just for test, below
+)
+
+const this = "llvm.org/llgo/third_party/go.tools/refactor/importgraph"
+
+func TestBuild(t *testing.T) {
+	saved := runtime.GOMAXPROCS(8) // Build is highly parallel
+	defer runtime.GOMAXPROCS(saved)
+
+	forward, reverse, errors := importgraph.Build(&build.Default)
+
+	// Test direct edges.
+	// We throw in crypto/hmac to prove that external test files
+	// (such as this one) are inspected.
+	for _, p := range []string{"go/build", "runtime", "testing", "crypto/hmac"} {
+		if !forward[this][p] {
+			t.Errorf("forward[importgraph][%s] not found", p)
+		}
+		if !reverse[p][this] {
+			t.Errorf("reverse[%s][importgraph] not found", p)
+		}
+	}
+
+	// Test non-existent direct edges
+	for _, p := range []string{"fmt", "errors", "reflect"} {
+		if forward[this][p] {
+			t.Errorf("unexpected: forward[importgraph][%s] found", p)
+		}
+		if reverse[p][this] {
+			t.Errorf("unexpected: reverse[%s][importgraph] found", p)
+		}
+	}
+
+	// Test Search is reflexive.
+	if !forward.Search(this)[this] {
+		t.Errorf("irreflexive: forward.Search(importgraph)[importgraph] not found")
+	}
+	if !reverse.Search(this)[this] {
+		t.Errorf("irrefexive: reverse.Search(importgraph)[importgraph] not found")
+	}
+
+	// Test Search is transitive.  (There is no direct edge to these packages.)
+	for _, p := range []string{"errors", "reflect", "unsafe"} {
+		if !forward.Search(this)[p] {
+			t.Errorf("intransitive: forward.Search(importgraph)[%s] not found", p)
+		}
+		if !reverse.Search(p)[this] {
+			t.Errorf("intransitive: reverse.Search(%s)[importgraph] not found", p)
+		}
+	}
+
+	// Test strongly-connected components.  Because A's external
+	// test package can depend on B, and vice versa, most of the
+	// standard libraries are mutually dependent when their external
+	// tests are considered.
+	//
+	// For any nodes x, y in the same SCC, y appears in the results
+	// of both forward and reverse searches starting from x
+	if !forward.Search("fmt")["io"] ||
+		!forward.Search("io")["fmt"] ||
+		!reverse.Search("fmt")["io"] ||
+		!reverse.Search("io")["fmt"] {
+		t.Errorf("fmt and io are not mutually reachable despite being in the same SCC")
+	}
+
+	// debugging
+	if false {
+		for path, err := range errors {
+			t.Logf("%s: %s", path, err)
+		}
+		printSorted := func(direction string, g importgraph.Graph, start string) {
+			t.Log(direction)
+			var pkgs []string
+			for pkg := range g.Search(start) {
+				pkgs = append(pkgs, pkg)
+			}
+			sort.Strings(pkgs)
+			for _, pkg := range pkgs {
+				t.Logf("\t%s", pkg)
+			}
+		}
+		printSorted("forward", forward, this)
+		printSorted("reverse", reverse, this)
+	}
+}
diff --git a/third_party/go.tools/refactor/lexical/lexical.go b/third_party/go.tools/refactor/lexical/lexical.go
new file mode 100644
index 0000000..0094b3b
--- /dev/null
+++ b/third_party/go.tools/refactor/lexical/lexical.go
@@ -0,0 +1,756 @@
+// Package lexical computes the structure of the lexical environment,
+// including the definition of and references to all universal,
+// package-level, file-level and function-local entities.  It does not
+// record qualified identifiers, labels, struct fields, or methods.
+//
+// It is intended for renaming and refactoring tools, which need a more
+// precise understanding of identifier resolution than is available from
+// the output of the type-checker alone.
+//
+// THIS INTERFACE IS EXPERIMENTAL AND MAY CHANGE OR BE REMOVED IN FUTURE.
+//
+package lexical
+
+// OVERVIEW
+//
+// As we traverse the AST, we build a "spaghetti stack" of Blocks,
+// i.e. a tree with parent edges pointing to the root.  Each time we
+// visit an identifier that's a reference into the lexical environment,
+// we create and save an Environment, which captures the current mapping
+// state of the Block; these are saved for the client.
+//
+// We don't bother recording non-lexical references.
+
+// TODO(adonovan):
+// - make it robust against syntax errors.  Audit all type assertions, etc.
+// - better still, after the Go 1.4 thaw, move this into go/types.
+//   I don't think it need be a big change since the visitor is already there;
+//   we just need to records Environments.  lexical.Block is analogous
+//   to types.Scope.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"strconv"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+const trace = false
+
+var logf = func(format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, format, args...)
+}
+
+// A Block is a level of the lexical environment, a tree of blocks.
+// It maps names to objects.
+//
+type Block struct {
+	kind   string   // one of universe package file func block if switch typeswitch case for range
+	syntax ast.Node // syntax declaring the block (nil for universe and package) [needed?]
+
+	parent   Environment
+	bindings []types.Object // bindings in lexical order
+	index    map[string]int // maps a name to the index of its binding, for fast lookup
+}
+
+// An Environment is a snapshot of a Block taken at a certain lexical
+// position. It may contain bindings for fewer names than the
+// (completed) block, or different bindings for names that are
+// re-defined later in the block.
+//
+// For example, the lexical Block for the function f below contains a
+// binding for the local var x, but the Environments captured by at the
+// two print(x) calls differ: the first contains this binding, the
+// second does not.  The first Environment contains a different binding
+// for x: the string var defined in the package block, an ancestor.
+//
+//	var x string
+// 	func f() {
+//		print(x)
+//		x := 1
+//		print(x)
+//	}
+//
+type Environment struct {
+	block     *Block
+	nbindings int // length of prefix of block.bindings that's visible
+}
+
+// Depth returns the depth of this block in the block tree.
+// The universal block has depth 1, a package block 2, a file block 3, etc.
+func (b *Block) Depth() int {
+	if b == nil {
+		return 0
+	}
+	return 1 + b.parent.block.Depth()
+}
+
+// env returns an Environment that is a snapshot of b's current state.
+func (b *Block) env() Environment {
+	return Environment{b, len(b.bindings)}
+}
+
+// Lookup returns the definition of name in the environment specified by
+// env, and the Block that defines it, which may be an ancestor.
+func (env Environment) Lookup(name string) (types.Object, *Block) {
+	if env.block == nil {
+		return nil, nil
+	}
+	return lookup(env.block, name, env.nbindings)
+}
+
+// nbindings specifies what prefix of b.bindings should be considered visible.
+func lookup(b *Block, name string, nbindings int) (types.Object, *Block) {
+	if b == nil {
+		return nil, nil
+	}
+	if i, ok := b.index[name]; ok && i < nbindings {
+		return b.bindings[i], b
+	}
+
+	parent := b.parent
+	if parent.block == nil {
+		return nil, nil
+	}
+	return lookup(parent.block, name, parent.nbindings)
+}
+
+// Lookup returns the definition of name in the environment specified by
+// b, and the Block that defines it, which may be an ancestor.
+func (b *Block) Lookup(name string) (types.Object, *Block) {
+	return b.env().Lookup(name)
+}
+
+// Block returns the block of which this environment is a partial view.
+func (env Environment) Block() *Block {
+	return env.block
+}
+
+func (env Environment) String() string {
+	return fmt.Sprintf("%s:%d", env.block, env.nbindings)
+}
+
+func (b *Block) String() string {
+	var s string
+	if b.parent.block != nil {
+		s = b.parent.block.String()
+		s += "."
+	}
+	return s + b.kind
+}
+
+var universe = &Block{kind: "universe", index: make(map[string]int)}
+
+func init() {
+	for i, name := range types.Universe.Names() {
+		obj := types.Universe.Lookup(name)
+		universe.bindings = append(universe.bindings, obj)
+		universe.index[name] = i
+	}
+}
+
+// -- resolver ---------------------------------------------------------
+
+// A Reference provides the lexical environment for a given reference to
+// an object in lexical scope.
+type Reference struct {
+	Id  *ast.Ident
+	Env Environment
+}
+
+// resolver holds the state of the identifier resolution visitation:
+// the package information, the result, and the current block.
+type resolver struct {
+	fset    *token.FileSet
+	imports map[string]*types.Package
+	pkg     *types.Package
+	info    *types.Info
+
+	// visitor state
+	block *Block
+
+	result *Info
+}
+
+func (r *resolver) setBlock(kind string, syntax ast.Node) *Block {
+	b := &Block{
+		kind:   kind,
+		syntax: syntax,
+		parent: r.block.env(),
+		index:  make(map[string]int),
+	}
+	if syntax != nil {
+		r.result.Blocks[syntax] = b
+	}
+	r.block = b
+	return b
+}
+
+func (r *resolver) use(id *ast.Ident, env Environment) {
+	if id.Name == "_" {
+		return // an error
+	}
+	obj, _ := env.Lookup(id.Name)
+	if obj == nil {
+		logf("%s: lookup of %s failed\n", r.fset.Position(id.Pos()), id.Name)
+	} else if want := r.info.Uses[id]; obj != want {
+		// sanity check against go/types resolver
+		logf("%s: internal error: lookup of %s yielded wrong object: got %v (%s), want %v\n",
+			r.fset.Position(id.Pos()), id.Name, types.ObjectString(r.pkg, obj),
+			r.fset.Position(obj.Pos()),
+			want)
+	}
+	if trace {
+		logf("use %s = %v in %s\n", id.Name, types.ObjectString(r.pkg, obj), env)
+	}
+
+	r.result.Refs[obj] = append(r.result.Refs[obj], Reference{id, env})
+}
+
+func (r *resolver) define(b *Block, id *ast.Ident) {
+	obj := r.info.Defs[id]
+	if obj == nil {
+		logf("%s: internal error: not a defining ident: %s\n",
+			r.fset.Position(id.Pos()), id.Name)
+		panic(id)
+	}
+	r.defineObject(b, id.Name, obj)
+
+	// Objects (other than PkgName) defined at file scope
+	// are also defined in the enclosing package scope.
+	if _, ok := b.syntax.(*ast.File); ok {
+		switch obj.(type) {
+		default:
+			r.defineObject(b.parent.block, id.Name, obj)
+		case nil, *types.PkgName:
+		}
+	}
+}
+
+// Used for implicit objects created by some ImportSpecs and CaseClauses.
+func (r *resolver) defineImplicit(b *Block, n ast.Node, name string) {
+	obj := r.info.Implicits[n]
+	if obj == nil {
+		logf("%s: internal error: not an implicit definition: %T\n",
+			r.fset.Position(n.Pos()), n)
+	}
+	r.defineObject(b, name, obj)
+}
+
+func (r *resolver) defineObject(b *Block, name string, obj types.Object) {
+	if obj.Name() == "_" {
+		return
+	}
+	i := len(b.bindings)
+	b.bindings = append(b.bindings, obj)
+	b.index[name] = i
+	if trace {
+		logf("def %s = %s in %s\n", name, types.ObjectString(r.pkg, obj), b)
+	}
+	r.result.Defs[obj] = b
+}
+
+func (r *resolver) function(recv *ast.FieldList, typ *ast.FuncType, body *ast.BlockStmt, syntax ast.Node) {
+	// Use all signature types in enclosing block.
+	r.expr(typ)
+	r.fieldList(recv, false)
+
+	savedBlock := r.block // save
+	r.setBlock("func", syntax)
+
+	// Define all parameters/results, and visit the body, within the func block.
+	r.fieldList(typ.Params, true)
+	r.fieldList(typ.Results, true)
+	r.fieldList(recv, true)
+	if body != nil {
+		r.stmtList(body.List)
+	}
+
+	r.block = savedBlock // restore
+}
+
+func (r *resolver) fieldList(list *ast.FieldList, def bool) {
+	if list != nil {
+		for _, f := range list.List {
+			if def {
+				for _, id := range f.Names {
+					r.define(r.block, id)
+				}
+			} else {
+				r.expr(f.Type)
+			}
+		}
+	}
+}
+
+func (r *resolver) exprList(list []ast.Expr) {
+	for _, x := range list {
+		r.expr(x)
+	}
+}
+
+func (r *resolver) expr(n ast.Expr) {
+	switch n := n.(type) {
+	case *ast.BadExpr:
+	case *ast.BasicLit:
+		// no-op
+
+	case *ast.Ident:
+		r.use(n, r.block.env())
+
+	case *ast.Ellipsis:
+		if n.Elt != nil {
+			r.expr(n.Elt)
+		}
+
+	case *ast.FuncLit:
+		r.function(nil, n.Type, n.Body, n)
+
+	case *ast.CompositeLit:
+		if n.Type != nil {
+			r.expr(n.Type)
+		}
+		tv := r.info.Types[n]
+		if _, ok := deref(tv.Type).Underlying().(*types.Struct); ok {
+			for _, elt := range n.Elts {
+				if kv, ok := elt.(*ast.KeyValueExpr); ok {
+					r.expr(kv.Value)
+
+					// Also uses field kv.Key (non-lexical)
+					//  id := kv.Key.(*ast.Ident)
+					//  obj := r.info.Uses[id]
+					//  logf("use %s = %v (field)\n",
+					// 	id.Name, types.ObjectString(r.pkg, obj))
+					// TODO make a fake FieldVal selection?
+				} else {
+					r.expr(elt)
+				}
+			}
+		} else {
+			r.exprList(n.Elts)
+		}
+
+	case *ast.ParenExpr:
+		r.expr(n.X)
+
+	case *ast.SelectorExpr:
+		r.expr(n.X)
+
+		// Non-lexical reference to field/method, or qualified identifier.
+		// if sel, ok := r.info.Selections[n]; ok { // selection
+		// 	switch sel.Kind() {
+		// 	case types.FieldVal:
+		// 		logf("use %s = %v (field)\n",
+		// 			n.Sel.Name, types.ObjectString(r.pkg, sel.Obj()))
+		// 	case types.MethodExpr, types.MethodVal:
+		// 		logf("use %s = %v (method)\n",
+		// 			n.Sel.Name, types.ObjectString(r.pkg, sel.Obj()))
+		// 	}
+		// } else { // qualified identifier
+		// 	obj := r.info.Uses[n.Sel]
+		// 	logf("use %s = %v (qualified)\n", n.Sel.Name, obj)
+		// }
+
+	case *ast.IndexExpr:
+		r.expr(n.X)
+		r.expr(n.Index)
+
+	case *ast.SliceExpr:
+		r.expr(n.X)
+		if n.Low != nil {
+			r.expr(n.Low)
+		}
+		if n.High != nil {
+			r.expr(n.High)
+		}
+		if n.Max != nil {
+			r.expr(n.Max)
+		}
+
+	case *ast.TypeAssertExpr:
+		r.expr(n.X)
+		if n.Type != nil {
+			r.expr(n.Type)
+		}
+
+	case *ast.CallExpr:
+		r.expr(n.Fun)
+		r.exprList(n.Args)
+
+	case *ast.StarExpr:
+		r.expr(n.X)
+
+	case *ast.UnaryExpr:
+		r.expr(n.X)
+
+	case *ast.BinaryExpr:
+		r.expr(n.X)
+		r.expr(n.Y)
+
+	case *ast.KeyValueExpr:
+		r.expr(n.Key)
+		r.expr(n.Value)
+
+	case *ast.ArrayType:
+		if n.Len != nil {
+			r.expr(n.Len)
+		}
+		r.expr(n.Elt)
+
+	case *ast.StructType:
+		// Use all the type names, but don't define any fields.
+		r.fieldList(n.Fields, false)
+
+	case *ast.FuncType:
+		// Use all the type names, but don't define any vars.
+		r.fieldList(n.Params, false)
+		r.fieldList(n.Results, false)
+
+	case *ast.InterfaceType:
+		// Use all the type names, but don't define any methods.
+		r.fieldList(n.Methods, false)
+
+	case *ast.MapType:
+		r.expr(n.Key)
+		r.expr(n.Value)
+
+	case *ast.ChanType:
+		r.expr(n.Value)
+
+	default:
+		panic(n)
+	}
+}
+
+func (r *resolver) stmtList(list []ast.Stmt) {
+	for _, s := range list {
+		r.stmt(s)
+	}
+}
+
+func (r *resolver) stmt(n ast.Stmt) {
+	switch n := n.(type) {
+	case *ast.BadStmt:
+	case *ast.EmptyStmt:
+		// nothing to do
+
+	case *ast.DeclStmt:
+		decl := n.Decl.(*ast.GenDecl)
+		for _, spec := range decl.Specs {
+			switch spec := spec.(type) {
+			case *ast.ValueSpec: // const or var
+				if spec.Type != nil {
+					r.expr(spec.Type)
+				}
+				r.exprList(spec.Values)
+				for _, name := range spec.Names {
+					r.define(r.block, name)
+				}
+
+			case *ast.TypeSpec:
+				r.define(r.block, spec.Name)
+				r.expr(spec.Type)
+			}
+		}
+
+	case *ast.LabeledStmt:
+		// Also defines label n.Label (non-lexical)
+		r.stmt(n.Stmt)
+
+	case *ast.ExprStmt:
+		r.expr(n.X)
+
+	case *ast.SendStmt:
+		r.expr(n.Chan)
+		r.expr(n.Value)
+
+	case *ast.IncDecStmt:
+		r.expr(n.X)
+
+	case *ast.AssignStmt:
+		if n.Tok == token.DEFINE {
+			r.exprList(n.Rhs)
+			for _, lhs := range n.Lhs {
+				id := lhs.(*ast.Ident)
+				if _, ok := r.info.Defs[id]; ok {
+					r.define(r.block, id)
+				} else {
+					r.use(id, r.block.env())
+				}
+			}
+		} else { // ASSIGN
+			r.exprList(n.Lhs)
+			r.exprList(n.Rhs)
+		}
+
+	case *ast.GoStmt:
+		r.expr(n.Call)
+
+	case *ast.DeferStmt:
+		r.expr(n.Call)
+
+	case *ast.ReturnStmt:
+		r.exprList(n.Results)
+
+	case *ast.BranchStmt:
+		if n.Label != nil {
+			// Also uses label n.Label (non-lexical)
+		}
+
+	case *ast.SelectStmt:
+		r.stmtList(n.Body.List)
+
+	case *ast.BlockStmt: // (explicit blocks only)
+		savedBlock := r.block // save
+		r.setBlock("block", n)
+		r.stmtList(n.List)
+		r.block = savedBlock // restore
+
+	case *ast.IfStmt:
+		savedBlock := r.block // save
+		r.setBlock("if", n)
+		if n.Init != nil {
+			r.stmt(n.Init)
+		}
+		r.expr(n.Cond)
+		r.stmt(n.Body) // new block
+		if n.Else != nil {
+			r.stmt(n.Else)
+		}
+		r.block = savedBlock // restore
+
+	case *ast.CaseClause:
+		savedBlock := r.block // save
+		r.setBlock("case", n)
+		if obj, ok := r.info.Implicits[n]; ok {
+			// e.g.
+			//   switch y := x.(type) {
+			//   case T: // we declare an implicit 'var y T' in this block
+			//   }
+			r.defineImplicit(r.block, n, obj.Name())
+		}
+		r.exprList(n.List)
+		r.stmtList(n.Body)
+		r.block = savedBlock // restore
+
+	case *ast.SwitchStmt:
+		savedBlock := r.block // save
+		r.setBlock("switch", n)
+		if n.Init != nil {
+			r.stmt(n.Init)
+		}
+		if n.Tag != nil {
+			r.expr(n.Tag)
+		}
+		r.stmtList(n.Body.List)
+		r.block = savedBlock // restore
+
+	case *ast.TypeSwitchStmt:
+		savedBlock := r.block // save
+		r.setBlock("typeswitch", n)
+		if n.Init != nil {
+			r.stmt(n.Init)
+		}
+		if assign, ok := n.Assign.(*ast.AssignStmt); ok { // y := x.(type)
+			r.expr(assign.Rhs[0]) // skip y: not a defining ident
+		} else {
+			r.stmt(n.Assign)
+		}
+		r.stmtList(n.Body.List)
+		r.block = savedBlock // restore
+
+	case *ast.CommClause:
+		savedBlock := r.block // save
+		r.setBlock("case", n)
+		if n.Comm != nil {
+			r.stmt(n.Comm)
+		}
+		r.stmtList(n.Body)
+		r.block = savedBlock // restore
+
+	case *ast.ForStmt:
+		savedBlock := r.block // save
+		r.setBlock("for", n)
+		if n.Init != nil {
+			r.stmt(n.Init)
+		}
+		if n.Cond != nil {
+			r.expr(n.Cond)
+		}
+		if n.Post != nil {
+			r.stmt(n.Post)
+		}
+		r.stmt(n.Body)
+		r.block = savedBlock // restore
+
+	case *ast.RangeStmt:
+		r.expr(n.X)
+		savedBlock := r.block // save
+		r.setBlock("range", n)
+		if n.Tok == token.DEFINE {
+			if n.Key != nil {
+				r.define(r.block, n.Key.(*ast.Ident))
+			}
+			if n.Value != nil {
+				r.define(r.block, n.Value.(*ast.Ident))
+			}
+		} else {
+			if n.Key != nil {
+				r.expr(n.Key)
+			}
+			if n.Value != nil {
+				r.expr(n.Value)
+			}
+		}
+		r.stmt(n.Body)
+		r.block = savedBlock // restore
+
+	default:
+		panic(n)
+	}
+}
+
+func (r *resolver) doImport(s *ast.ImportSpec, fileBlock *Block) {
+	path, _ := strconv.Unquote(s.Path.Value)
+	pkg := r.imports[path]
+	if s.Name == nil { // normal
+		r.defineImplicit(fileBlock, s, pkg.Name())
+	} else if s.Name.Name == "." { // dot import
+		for _, name := range pkg.Scope().Names() {
+			if ast.IsExported(name) {
+				obj := pkg.Scope().Lookup(name)
+				r.defineObject(fileBlock, name, obj)
+			}
+		}
+	} else { // renaming import
+		r.define(fileBlock, s.Name)
+	}
+}
+
+func (r *resolver) doPackage(pkg *types.Package, files []*ast.File) {
+	r.block = universe
+	r.result.Blocks[nil] = universe
+
+	r.result.PackageBlock = r.setBlock("package", nil)
+
+	var fileBlocks []*Block
+
+	// 1. Insert all package-level objects into file and package blocks.
+	//    (PkgName objects are only inserted into file blocks.)
+	for _, f := range files {
+		r.block = r.result.PackageBlock
+		fileBlock := r.setBlock("file", f) // package is not yet visible to file
+		fileBlocks = append(fileBlocks, fileBlock)
+
+		for _, d := range f.Decls {
+			switch d := d.(type) {
+			case *ast.GenDecl:
+				for _, s := range d.Specs {
+					switch s := s.(type) {
+					case *ast.ImportSpec:
+						r.doImport(s, fileBlock)
+
+					case *ast.ValueSpec: // const or var
+						for _, name := range s.Names {
+							r.define(r.result.PackageBlock, name)
+						}
+
+					case *ast.TypeSpec:
+						r.define(r.result.PackageBlock, s.Name)
+					}
+				}
+
+			case *ast.FuncDecl:
+				if d.Recv == nil { // function
+					if d.Name.Name != "init" {
+						r.define(r.result.PackageBlock, d.Name)
+					}
+				}
+			}
+		}
+	}
+
+	// 2. Now resolve bodies of GenDecls and FuncDecls.
+	for i, f := range files {
+		fileBlock := fileBlocks[i]
+		fileBlock.parent = r.result.PackageBlock.env() // make entire package visible to this file
+
+		for _, d := range f.Decls {
+			r.block = fileBlock
+
+			switch d := d.(type) {
+			case *ast.GenDecl:
+				for _, s := range d.Specs {
+					switch s := s.(type) {
+					case *ast.ValueSpec: // const or var
+						if s.Type != nil {
+							r.expr(s.Type)
+						}
+						r.exprList(s.Values)
+
+					case *ast.TypeSpec:
+						r.expr(s.Type)
+					}
+				}
+
+			case *ast.FuncDecl:
+				r.function(d.Recv, d.Type, d.Body, d)
+			}
+		}
+	}
+
+	r.block = nil
+}
+
+// An Info contains the lexical reference structure of a package.
+type Info struct {
+	Defs         map[types.Object]*Block      // maps each object to its defining lexical block
+	Refs         map[types.Object][]Reference // maps each object to the set of references to it
+	Blocks       map[ast.Node]*Block          // maps declaring syntax to block; nil => universe
+	PackageBlock *Block                       // the package-level lexical block
+}
+
+// Structure computes the structure of the lexical environment of the
+// package specified by (pkg, info, files).
+//
+// The info.{Types,Defs,Uses,Implicits} maps must have been populated
+// by the type-checker
+//
+// fset is used for logging.
+//
+func Structure(fset *token.FileSet, pkg *types.Package, info *types.Info, files []*ast.File) *Info {
+	r := resolver{
+		fset:    fset,
+		imports: make(map[string]*types.Package),
+		result: &Info{
+			Defs:   make(map[types.Object]*Block),
+			Refs:   make(map[types.Object][]Reference),
+			Blocks: make(map[ast.Node]*Block),
+		},
+		pkg:  pkg,
+		info: info,
+	}
+
+	// Build import map for just this package.
+	r.imports["unsafe"] = types.Unsafe
+	for _, imp := range pkg.Imports() {
+		r.imports[imp.Path()] = imp
+	}
+
+	r.doPackage(pkg, files)
+
+	return r.result
+}
+
+// -- Plundered from golang.org/x/tools/go/ssa -----------------
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
diff --git a/third_party/go.tools/refactor/lexical/lexical_test.go b/third_party/go.tools/refactor/lexical/lexical_test.go
new file mode 100644
index 0000000..2df1205
--- /dev/null
+++ b/third_party/go.tools/refactor/lexical/lexical_test.go
@@ -0,0 +1,55 @@
+// Copyright 2014 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 lexical
+
+import (
+	"go/build"
+	"testing"
+
+	"llvm.org/llgo/third_party/go.tools/go/buildutil"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+)
+
+func TestStdlib(t *testing.T) {
+	defer func(saved func(format string, args ...interface{})) {
+		logf = saved
+	}(logf)
+	logf = t.Errorf
+
+	ctxt := build.Default // copy
+
+	// Enumerate $GOROOT packages.
+	saved := ctxt.GOPATH
+	ctxt.GOPATH = "" // disable GOPATH during AllPackages
+	pkgs := buildutil.AllPackages(&ctxt)
+	ctxt.GOPATH = saved
+
+	// Throw in a number of go.tools packages too.
+	pkgs = append(pkgs,
+		"llvm.org/llgo/third_party/go.tools/cmd/godoc",
+		"llvm.org/llgo/third_party/go.tools/refactor/lexical")
+
+	// Load, parse and type-check the program.
+	conf := loader.Config{
+		Build:         &ctxt,
+		SourceImports: true,
+	}
+	for _, path := range pkgs {
+		if err := conf.ImportWithTests(path); err != nil {
+			t.Error(err)
+		}
+	}
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+
+	// This test ensures that Structure doesn't panic and that
+	// its internal sanity-checks against go/types don't fail.
+	for pkg, info := range iprog.AllPackages {
+		_ = Structure(iprog.Fset, pkg, &info.Info, info.Files)
+	}
+}
diff --git a/third_party/go.tools/refactor/rename/check.go b/third_party/go.tools/refactor/rename/check.go
new file mode 100644
index 0000000..e5a7d86
--- /dev/null
+++ b/third_party/go.tools/refactor/rename/check.go
@@ -0,0 +1,671 @@
+// Copyright 2014 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 rename
+
+// This file defines the safety checks for each kind of renaming.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/refactor/lexical"
+	"llvm.org/llgo/third_party/go.tools/refactor/satisfy"
+)
+
+// errorf reports an error (e.g. conflict) and prevents file modification.
+func (r *renamer) errorf(pos token.Pos, format string, args ...interface{}) {
+	r.hadConflicts = true
+	reportError(r.iprog.Fset.Position(pos), fmt.Sprintf(format, args...))
+}
+
+// check performs safety checks of the renaming of the 'from' object to r.to.
+func (r *renamer) check(from types.Object) {
+	if r.objsToUpdate[from] {
+		return
+	}
+	r.objsToUpdate[from] = true
+
+	// NB: order of conditions is important.
+	if from_, ok := from.(*types.PkgName); ok {
+		r.checkInFileBlock(from_)
+	} else if from_, ok := from.(*types.Label); ok {
+		r.checkLabel(from_)
+	} else if isPackageLevel(from) {
+		r.checkInPackageBlock(from)
+	} else if v, ok := from.(*types.Var); ok && v.IsField() {
+		r.checkStructField(v)
+	} else if f, ok := from.(*types.Func); ok && f.Type().(*types.Signature).Recv() != nil {
+		r.checkMethod(f)
+	} else if isLocal(from) {
+		r.checkInLocalScope(from)
+	} else {
+		r.errorf(from.Pos(), "unexpected %s object %q (please report a bug)\n",
+			objectKind(from), from)
+	}
+}
+
+// checkInFileBlock performs safety checks for renames of objects in the file block,
+// i.e. imported package names.
+func (r *renamer) checkInFileBlock(from *types.PkgName) {
+	// Check import name is not "init".
+	if r.to == "init" {
+		r.errorf(from.Pos(), "%q is not a valid imported package name", r.to)
+	}
+
+	// Check for conflicts between file and package block.
+	if prev := from.Pkg().Scope().Lookup(r.to); prev != nil {
+		r.errorf(from.Pos(), "renaming this %s %q to %q would conflict",
+			objectKind(from), from.Name(), r.to)
+		r.errorf(prev.Pos(), "\twith this package member %s",
+			objectKind(prev))
+		return // since checkInPackageBlock would report redundant errors
+	}
+
+	// Check for conflicts in lexical scope.
+	r.checkInLexicalScope(from, r.packages[from.Pkg()])
+
+	// Finally, modify ImportSpec syntax to add or remove the Name as needed.
+	info, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())
+	if from.Imported().Name() == r.to {
+		// ImportSpec.Name not needed
+		path[1].(*ast.ImportSpec).Name = nil
+	} else {
+		// ImportSpec.Name needed
+		if spec := path[1].(*ast.ImportSpec); spec.Name == nil {
+			spec.Name = &ast.Ident{NamePos: spec.Path.Pos(), Name: r.to}
+			info.Defs[spec.Name] = from
+		}
+	}
+}
+
+// checkInPackageBlock performs safety checks for renames of
+// func/var/const/type objects in the package block.
+func (r *renamer) checkInPackageBlock(from types.Object) {
+	// Check that there are no references to the name from another
+	// package if the renaming would make it unexported.
+	if ast.IsExported(from.Name()) && !ast.IsExported(r.to) {
+		for pkg, info := range r.packages {
+			if pkg == from.Pkg() {
+				continue
+			}
+			if id := someUse(info, from); id != nil &&
+				!r.checkExport(id, pkg, from) {
+				break
+			}
+		}
+	}
+
+	info := r.packages[from.Pkg()]
+	lexinfo := lexical.Structure(r.iprog.Fset, from.Pkg(), &info.Info, info.Files)
+
+	// Check that in the package block, "init" is a function, and never referenced.
+	if r.to == "init" {
+		kind := objectKind(from)
+		if kind == "func" {
+			// Reject if intra-package references to it exist.
+			if refs := lexinfo.Refs[from]; len(refs) > 0 {
+				r.errorf(from.Pos(),
+					"renaming this func %q to %q would make it a package initializer",
+					from.Name(), r.to)
+				r.errorf(refs[0].Id.Pos(), "\tbut references to it exist")
+			}
+		} else {
+			r.errorf(from.Pos(), "you cannot have a %s at package level named %q",
+				kind, r.to)
+		}
+	}
+
+	// Check for conflicts between package block and all file blocks.
+	for _, f := range info.Files {
+		if prev, b := lexinfo.Blocks[f].Lookup(r.to); b == lexinfo.Blocks[f] {
+			r.errorf(from.Pos(), "renaming this %s %q to %q would conflict",
+				objectKind(from), from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twith this %s",
+				objectKind(prev))
+			return // since checkInPackageBlock would report redundant errors
+		}
+	}
+
+	// Check for conflicts in lexical scope.
+	if from.Exported() {
+		for _, info := range r.packages {
+			r.checkInLexicalScope(from, info)
+		}
+	} else {
+		r.checkInLexicalScope(from, info)
+	}
+}
+
+func (r *renamer) checkInLocalScope(from types.Object) {
+	info := r.packages[from.Pkg()]
+
+	// Is this object an implicit local var for a type switch?
+	// Each case has its own var, whose position is the decl of y,
+	// but Ident in that decl does not appear in the Uses map.
+	//
+	//   switch y := x.(type) {	 // Defs[Ident(y)] is undefined
+	//   case int:    print(y)       // Implicits[CaseClause(int)]    = Var(y_int)
+	//   case string: print(y)       // Implicits[CaseClause(string)] = Var(y_string)
+	//   }
+	//
+	var isCaseVar bool
+	for syntax, obj := range info.Implicits {
+		if _, ok := syntax.(*ast.CaseClause); ok && obj.Pos() == from.Pos() {
+			isCaseVar = true
+			r.check(obj)
+		}
+	}
+
+	r.checkInLexicalScope(from, info)
+
+	// Finally, if this was a type switch, change the variable y.
+	if isCaseVar {
+		_, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())
+		path[0].(*ast.Ident).Name = r.to // path is [Ident AssignStmt TypeSwitchStmt...]
+	}
+}
+
+// checkInLexicalScope performs safety checks that a renaming does not
+// change the lexical reference structure of the specified package.
+//
+// For objects in lexical scope, there are three kinds of conflicts:
+// same-, sub-, and super-block conflicts.  We will illustrate all three
+// using this example:
+//
+//      var x int
+//	var z int
+//
+//	func f(y int) {
+//		print(x)
+//		print(y)
+//	}
+//
+// Renaming x to z encounters a SAME-BLOCK CONFLICT, because an object
+// with the new name already exists, defined in the same lexical block
+// as the old object.
+//
+// Renaming x to y encounters a SUB-BLOCK CONFLICT, because there exists
+// a reference to x from within (what would become) a hole in its scope.
+// The definition of y in an (inner) sub-block would cast a shadow in
+// the scope of the renamed variable.
+//
+// Renaming y to x encounters a SUPER-BLOCK CONFLICT.  This is the
+// converse situation: there is an existing definition of the new name
+// (x) in an (enclosing) super-block, and the renaming would create a
+// hole in its scope, within which there exist references to it.  The
+// new name casts a shadow in scope of the existing definition of x in
+// the super-block.
+//
+// Removing the old name (and all references to it) is always safe, and
+// requires no checks.
+//
+func (r *renamer) checkInLexicalScope(from types.Object, info *loader.PackageInfo) {
+	lexinfo := lexical.Structure(r.iprog.Fset, info.Pkg, &info.Info, info.Files)
+
+	b := lexinfo.Defs[from] // the block defining the 'from' object
+	if b != nil {
+		to, toBlock := b.Lookup(r.to)
+		if toBlock == b {
+			// same-block conflict
+			r.errorf(from.Pos(), "renaming this %s %q to %q",
+				objectKind(from), from.Name(), r.to)
+			r.errorf(to.Pos(), "\tconflicts with %s in same block",
+				objectKind(to))
+			return
+		} else if toBlock != nil {
+			// Check for super-block conflict.
+			// The name r.to is defined in a superblock.
+			// Is that name referenced from within this block?
+			for _, ref := range lexinfo.Refs[to] {
+				if obj, _ := ref.Env.Lookup(from.Name()); obj == from {
+					// super-block conflict
+					r.errorf(from.Pos(), "renaming this %s %q to %q",
+						objectKind(from), from.Name(), r.to)
+					r.errorf(ref.Id.Pos(), "\twould shadow this reference")
+					r.errorf(to.Pos(), "\tto the %s declared here",
+						objectKind(to))
+					return
+				}
+			}
+		}
+	}
+
+	// Check for sub-block conflict.
+	// Is there an intervening definition of r.to between
+	// the block defining 'from' and some reference to it?
+	for _, ref := range lexinfo.Refs[from] {
+		// TODO(adonovan): think about dot imports.
+		// (Is b == fromBlock an invariant?)
+		_, fromBlock := ref.Env.Lookup(from.Name())
+		fromDepth := fromBlock.Depth()
+
+		to, toBlock := ref.Env.Lookup(r.to)
+		if to != nil {
+			// sub-block conflict
+			if toBlock.Depth() > fromDepth {
+				r.errorf(from.Pos(), "renaming this %s %q to %q",
+					objectKind(from), from.Name(), r.to)
+				r.errorf(ref.Id.Pos(), "\twould cause this reference to become shadowed")
+				r.errorf(to.Pos(), "\tby this intervening %s definition",
+					objectKind(to))
+				return
+			}
+		}
+	}
+
+	// Renaming a type that is used as an embedded field
+	// requires renaming the field too. e.g.
+	// 	type T int // if we rename this to U..
+	// 	var s struct {T}
+	// 	print(s.T) // ...this must change too
+	if _, ok := from.(*types.TypeName); ok {
+		for id, obj := range info.Uses {
+			if obj == from {
+				if field := info.Defs[id]; field != nil {
+					r.check(field)
+				}
+			}
+		}
+	}
+}
+
+func (r *renamer) checkLabel(label *types.Label) {
+	// Check there are no identical labels in the function's label block.
+	// (Label blocks don't nest, so this is easy.)
+	if prev := label.Parent().Lookup(r.to); prev != nil {
+		r.errorf(label.Pos(), "renaming this label %q to %q", label.Name(), prev.Name())
+		r.errorf(prev.Pos(), "\twould conflict with this one")
+	}
+}
+
+// checkStructField checks that the field renaming will not cause
+// conflicts at its declaration, or ambiguity or changes to any selection.
+func (r *renamer) checkStructField(from *types.Var) {
+	// Check that the struct declaration is free of field conflicts,
+	// and field/method conflicts.
+
+	// go/types offers no easy way to get from a field (or interface
+	// method) to its declaring struct (or interface), so we must
+	// ascend the AST.
+	info, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())
+	// path matches this pattern:
+	// [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File]
+
+	// Ascend to FieldList.
+	var i int
+	for {
+		if _, ok := path[i].(*ast.FieldList); ok {
+			break
+		}
+		i++
+	}
+	i++
+	tStruct := path[i].(*ast.StructType)
+	i++
+	// Ascend past parens (unlikely).
+	for {
+		_, ok := path[i].(*ast.ParenExpr)
+		if !ok {
+			break
+		}
+		i++
+	}
+	if spec, ok := path[i].(*ast.TypeSpec); ok {
+		// This struct is also a named type.
+		// We must check for direct (non-promoted) field/field
+		// and method/field conflicts.
+		named := info.Defs[spec.Name].Type()
+		prev, indices, _ := types.LookupFieldOrMethod(named, true, info.Pkg, r.to)
+		if len(indices) == 1 {
+			r.errorf(from.Pos(), "renaming this field %q to %q",
+				from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twould conflict with this %s",
+				objectKind(prev))
+			return // skip checkSelections to avoid redundant errors
+		}
+	} else {
+		// This struct is not a named type.
+		// We need only check for direct (non-promoted) field/field conflicts.
+		T := info.Types[tStruct].Type.Underlying().(*types.Struct)
+		for i := 0; i < T.NumFields(); i++ {
+			if prev := T.Field(i); prev.Name() == r.to {
+				r.errorf(from.Pos(), "renaming this field %q to %q",
+					from.Name(), r.to)
+				r.errorf(prev.Pos(), "\twould conflict with this field")
+				return // skip checkSelections to avoid redundant errors
+			}
+		}
+	}
+
+	// Renaming an anonymous field requires renaming the type too. e.g.
+	// 	print(s.T)       // if we rename T to U,
+	// 	type T int       // this and
+	// 	var s struct {T} // this must change too.
+	if from.Anonymous() {
+		if named, ok := from.Type().(*types.Named); ok {
+			r.check(named.Obj())
+		} else if named, ok := deref(from.Type()).(*types.Named); ok {
+			r.check(named.Obj())
+		}
+	}
+
+	// Check integrity of existing (field and method) selections.
+	r.checkSelections(from)
+}
+
+// checkSelection checks that all uses and selections that resolve to
+// the specified object would continue to do so after the renaming.
+func (r *renamer) checkSelections(from types.Object) {
+	for pkg, info := range r.packages {
+		if id := someUse(info, from); id != nil {
+			if !r.checkExport(id, pkg, from) {
+				return
+			}
+		}
+
+		for syntax, sel := range info.Selections {
+			// There may be extant selections of only the old
+			// name or only the new name, so we must check both.
+			// (If neither, the renaming is sound.)
+			//
+			// In both cases, we wish to compare the lengths
+			// of the implicit field path (Selection.Index)
+			// to see if the renaming would change it.
+			//
+			// If a selection that resolves to 'from', when renamed,
+			// would yield a path of the same or shorter length,
+			// this indicates ambiguity or a changed referent,
+			// analogous to same- or sub-block lexical conflict.
+			//
+			// If a selection using the name 'to' would
+			// yield a path of the same or shorter length,
+			// this indicates ambiguity or shadowing,
+			// analogous to same- or super-block lexical conflict.
+
+			// TODO(adonovan): fix: derive from Types[syntax.X].Mode
+			// TODO(adonovan): test with pointer, value, addressable value.
+			isAddressable := true
+
+			if sel.Obj() == from {
+				if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), r.to); obj != nil {
+					// Renaming this existing selection of
+					// 'from' may block access to an existing
+					// type member named 'to'.
+					delta := len(indices) - len(sel.Index())
+					if delta > 0 {
+						continue // no ambiguity
+					}
+					r.selectionConflict(from, delta, syntax, obj)
+					return
+				}
+
+			} else if sel.Obj().Name() == r.to {
+				if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), from.Name()); obj == from {
+					// Renaming 'from' may cause this existing
+					// selection of the name 'to' to change
+					// its meaning.
+					delta := len(indices) - len(sel.Index())
+					if delta > 0 {
+						continue //  no ambiguity
+					}
+					r.selectionConflict(from, -delta, syntax, sel.Obj())
+					return
+				}
+			}
+		}
+	}
+}
+
+func (r *renamer) selectionConflict(from types.Object, delta int, syntax *ast.SelectorExpr, obj types.Object) {
+	r.errorf(from.Pos(), "renaming this %s %q to %q",
+		objectKind(from), from.Name(), r.to)
+
+	switch {
+	case delta < 0:
+		// analogous to sub-block conflict
+		r.errorf(syntax.Sel.Pos(),
+			"\twould change the referent of this selection")
+		r.errorf(obj.Pos(), "\tto this %s", objectKind(obj))
+	case delta == 0:
+		// analogous to same-block conflict
+		r.errorf(syntax.Sel.Pos(),
+			"\twould make this reference ambiguous")
+		r.errorf(obj.Pos(), "\twith this %s", objectKind(obj))
+	case delta > 0:
+		// analogous to super-block conflict
+		r.errorf(syntax.Sel.Pos(),
+			"\twould shadow this selection")
+		r.errorf(obj.Pos(), "\tto the %s declared here",
+			objectKind(obj))
+	}
+}
+
+// checkMethod performs safety checks for renaming a method.
+// There are three hazards:
+// - declaration conflicts
+// - selection ambiguity/changes
+// - entailed renamings of assignable concrete/interface types (for now, just reject)
+func (r *renamer) checkMethod(from *types.Func) {
+	// e.g. error.Error
+	if from.Pkg() == nil {
+		r.errorf(from.Pos(), "you cannot rename built-in method %s", from)
+		return
+	}
+
+	// As always, having to support concrete methods with pointer
+	// and non-pointer receivers, and named vs unnamed types with
+	// methods, makes tooling fun.
+
+	// ASSIGNABILITY
+	//
+	// For now, if any method renaming breaks a required
+	// assignability to another type, we reject it.
+	//
+	// TODO(adonovan): probably we should compute the entailed
+	// renamings so that an interface method renaming causes
+	// concrete methods to change too.  But which ones?
+	//
+	// There is no correct answer, only heuristics, because Go's
+	// "duck typing" doesn't distinguish intentional from contingent
+	// assignability.  There are two obvious approaches:
+	//
+	// (1) Update the minimum set of types to preserve the
+	//     assignability of types all syntactic assignments
+	//     (incl. implicit ones in calls, returns, sends, etc).
+	//     The satisfy.Finder enumerates these.
+	//     This is likely to be an underapproximation.
+	//
+	// (2) Update all types that are assignable to/from the changed
+	//     type.  This requires computing the "implements" relation
+	//     for all pairs of types (as godoc and oracle do).
+	//     This is likely to be an overapproximation.
+	//
+	// If a concrete type is renamed, we probably do not want to
+	// rename corresponding interfaces; interface renamings should
+	// probably be initiated at the interface.  (But what if a
+	// concrete type implements multiple interfaces with the same
+	// method?  Then the user is stuck.)
+	//
+	// We need some experience before we decide how to implement this.
+
+	// Check for conflict at point of declaration.
+	// Check to ensure preservation of assignability requirements.
+	recv := from.Type().(*types.Signature).Recv().Type()
+	if isInterface(recv) {
+		// Abstract method
+
+		// declaration
+		prev, _, _ := types.LookupFieldOrMethod(recv, false, from.Pkg(), r.to)
+		if prev != nil {
+			r.errorf(from.Pos(), "renaming this interface method %q to %q",
+				from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twould conflict with this method")
+			return
+		}
+
+		// Check all interfaces that embed this one for
+		// declaration conflicts too.
+		for _, info := range r.packages {
+			// Start with named interface types (better errors)
+			for _, obj := range info.Defs {
+				if obj, ok := obj.(*types.TypeName); ok && isInterface(obj.Type()) {
+					f, _, _ := types.LookupFieldOrMethod(
+						obj.Type(), false, from.Pkg(), from.Name())
+					if f == nil {
+						continue
+					}
+					t, _, _ := types.LookupFieldOrMethod(
+						obj.Type(), false, from.Pkg(), r.to)
+					if t == nil {
+						continue
+					}
+					r.errorf(from.Pos(), "renaming this interface method %q to %q",
+						from.Name(), r.to)
+					r.errorf(t.Pos(), "\twould conflict with this method")
+					r.errorf(obj.Pos(), "\tin named interface type %q", obj.Name())
+				}
+			}
+
+			// Now look at all literal interface types (includes named ones again).
+			for e, tv := range info.Types {
+				if e, ok := e.(*ast.InterfaceType); ok {
+					_ = e
+					_ = tv.Type.(*types.Interface)
+					// TODO(adonovan): implement same check as above.
+				}
+			}
+		}
+
+		// assignability
+		for T := range r.findAssignments(recv) {
+			if obj, _, _ := types.LookupFieldOrMethod(T, false, from.Pkg(), from.Name()); obj == nil {
+				continue
+			}
+
+			r.errorf(from.Pos(), "renaming this method %q to %q",
+				from.Name(), r.to)
+			var pos token.Pos
+			var other string
+			if named, ok := T.(*types.Named); ok {
+				pos = named.Obj().Pos()
+				other = named.Obj().Name()
+			} else {
+				pos = from.Pos()
+				other = T.String()
+			}
+			r.errorf(pos, "\twould make %s no longer assignable to it", other)
+			return
+		}
+	} else {
+		// Concrete method
+
+		// declaration
+		prev, indices, _ := types.LookupFieldOrMethod(recv, true, from.Pkg(), r.to)
+		if prev != nil && len(indices) == 1 {
+			r.errorf(from.Pos(), "renaming this method %q to %q",
+				from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twould conflict with this %s",
+				objectKind(prev))
+			return
+		}
+
+		// assignability (of both T and *T)
+		recvBase := deref(recv)
+		for _, R := range []types.Type{recvBase, types.NewPointer(recvBase)} {
+			for I := range r.findAssignments(R) {
+				if obj, _, _ := types.LookupFieldOrMethod(I, true, from.Pkg(), from.Name()); obj == nil {
+					continue
+				}
+				r.errorf(from.Pos(), "renaming this method %q to %q",
+					from.Name(), r.to)
+				var pos token.Pos
+				var iface string
+				if named, ok := I.(*types.Named); ok {
+					pos = named.Obj().Pos()
+					iface = "interface " + named.Obj().Name()
+				} else {
+					pos = from.Pos()
+					iface = I.String()
+				}
+				r.errorf(pos, "\twould make it no longer assignable to %s", iface)
+				return // one is enough
+			}
+		}
+	}
+
+	// Check integrity of existing (field and method) selections.
+	// We skip this if there were errors above, to avoid redundant errors.
+	r.checkSelections(from)
+}
+
+func (r *renamer) checkExport(id *ast.Ident, pkg *types.Package, from types.Object) bool {
+	// Reject cross-package references if r.to is unexported.
+	// (Such references may be qualified identifiers or field/method
+	// selections.)
+	if !ast.IsExported(r.to) && pkg != from.Pkg() {
+		r.errorf(from.Pos(),
+			"renaming this %s %q to %q would make it unexported",
+			objectKind(from), from.Name(), r.to)
+		r.errorf(id.Pos(), "\tbreaking references from packages such as %q",
+			pkg.Path())
+		return false
+	}
+	return true
+}
+
+// findAssignments returns the set of types to or from which type T is
+// assigned in the program syntax.
+func (r *renamer) findAssignments(T types.Type) map[types.Type]bool {
+	if r.satisfyConstraints == nil {
+		// Compute on demand: it's expensive.
+		var f satisfy.Finder
+		for _, info := range r.packages {
+			f.Find(&info.Info, info.Files)
+		}
+		r.satisfyConstraints = f.Result
+	}
+
+	result := make(map[types.Type]bool)
+	for key := range r.satisfyConstraints {
+		// key = (lhs, rhs) where lhs is always an interface.
+		if types.Identical(key.RHS, T) {
+			result[key.LHS] = true
+		}
+		if isInterface(T) && types.Identical(key.LHS, T) {
+			// must check both sides
+			result[key.RHS] = true
+		}
+	}
+	return result
+}
+
+// -- helpers ----------------------------------------------------------
+
+// someUse returns an arbitrary use of obj within info.
+func someUse(info *loader.PackageInfo, obj types.Object) *ast.Ident {
+	for id, o := range info.Uses {
+		if o == obj {
+			return id
+		}
+	}
+	return nil
+}
+
+// -- Plundered from golang.org/x/tools/go/ssa -----------------
+
+func isInterface(T types.Type) bool {
+	_, ok := T.Underlying().(*types.Interface)
+	return ok
+}
+
+func deref(typ types.Type) types.Type {
+	if p, _ := typ.(*types.Pointer); p != nil {
+		return p.Elem()
+	}
+	return typ
+}
diff --git a/third_party/go.tools/refactor/rename/rename.el b/third_party/go.tools/refactor/rename/rename.el
new file mode 100644
index 0000000..9268358
--- /dev/null
+++ b/third_party/go.tools/refactor/rename/rename.el
@@ -0,0 +1,92 @@
+;;; Copyright 2014 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.
+;;;
+;;; Integration of the 'gorename' tool into Emacs.
+;;;
+;;; To install:
+;;; % go get golang.org/x/tools/cmd/gorename
+;;; % go build golang.org/x/tools/cmd/gorename
+;;; % mv gorename $HOME/bin/         # or elsewhere on $PATH
+;;;
+;;; The go-rename-command variable can be customized to specify an
+;;; alternative location for the installed command.
+
+(require 'compile)
+(require 'go-mode)
+(require 'thingatpt)
+
+(defgroup go-rename nil
+  "Options specific to the Go rename."
+  :group 'go)
+
+(defcustom go-rename-command "gorename"
+  "The `gorename' command; by the default, $PATH is searched."
+  :type 'string
+  :group 'go-rename)
+
+(defun go-rename (new-name)
+  "Rename the entity denoted by the identifier at point, using
+the `gorename' tool."
+  (interactive (list (read-string "New name: " (thing-at-point 'symbol))))
+  (if (not buffer-file-name)
+      (error "Cannot use go-rename on a buffer without a file name"))
+  ;; It's not sufficient to save the current buffer if modified,
+  ;; since if gofmt-before-save is on the before-save-hook,
+  ;; saving will disturb the selected region.
+  (if (buffer-modified-p)
+      (error "Please save the current buffer before invoking go-rename"))
+  ;; Prompt-save all other modified Go buffers, since they might get written.
+  (save-some-buffers nil #'(lambda ()
+              (and (buffer-file-name)
+                   (string= (file-name-extension (buffer-file-name)) ".go"))))
+  (let* ((posflag (format "-offset=%s:#%d"
+                          buffer-file-name
+                          (1- (go--position-bytes (point)))))
+         (env-vars (go-root-and-paths))
+         (goroot-env (concat "GOROOT=" (car env-vars)))
+         (gopath-env (concat "GOPATH=" (mapconcat #'identity (cdr env-vars) ":")))
+         success)
+    (with-current-buffer (get-buffer-create "*go-rename*")
+      (setq buffer-read-only nil)
+      (erase-buffer)
+      (let ((args (list go-rename-command nil t nil posflag "-to" new-name)))
+        ;; Log the command to *Messages*, for debugging.
+        (message "Command: %s:" args)
+        (message "Running gorename...")
+        ;; Use dynamic binding to modify/restore the environment
+        (setq success (zerop (let ((process-environment (list* goroot-env gopath-env process-environment)))
+          (apply #'call-process args))))
+      (insert "\n")
+      (compilation-mode)
+      (setq compilation-error-screen-columns nil)
+
+      ;; On success, print the one-line result in the message bar,
+      ;; and hide the *go-rename* buffer.
+      (let ((w (display-buffer (current-buffer))))
+        (if success
+            (progn
+              (message "%s" (go--buffer-string-no-trailing-space))
+              (delete-window w))
+          ;; failure
+          (message "gorename exited")
+          (shrink-window-if-larger-than-buffer w)
+          (set-window-point w (point-min)))))))
+
+  ;; Reload the modified files, saving line/col.
+  ;; (Don't restore the point since the text has changed.)
+  ;;
+  ;; TODO(adonovan): should we also do this for all other files
+  ;; that were updated (the tool can print them)?
+  (let ((line (line-number-at-pos))
+        (col (current-column)))
+    (revert-buffer t t t) ; safe, because we just saved it
+    (goto-char (point-min))
+    (forward-line (1- line))
+    (forward-char col)))
+
+
+(defun go--buffer-string-no-trailing-space ()
+  (replace-regexp-in-string "[\t\n ]*\\'"
+                            ""
+                            (buffer-substring (point-min) (point-max))))
diff --git a/third_party/go.tools/refactor/rename/rename.go b/third_party/go.tools/refactor/rename/rename.go
new file mode 100644
index 0000000..431a14f
--- /dev/null
+++ b/third_party/go.tools/refactor/rename/rename.go
@@ -0,0 +1,339 @@
+// Copyright 2014 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 rename contains the implementation of the 'gorename' command
+// whose main function is in golang.org/x/tools/refactor/rename.
+// See that package for the command documentation.
+package rename
+
+import (
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/refactor/importgraph"
+	"llvm.org/llgo/third_party/go.tools/refactor/satisfy"
+)
+
+var (
+	// Force enables patching of the source files even if conflicts were reported.
+	// The resulting program may be ill-formed.
+	// It may even cause gorename to crash.  TODO(adonovan): fix that.
+	Force bool
+
+	// DryRun causes the tool to report conflicts but not update any files.
+	DryRun bool
+
+	// ConflictError is returned by Main when it aborts the renaming due to conflicts.
+	// (It is distinguished because the interesting errors are the conflicts themselves.)
+	ConflictError = errors.New("renaming aborted due to conflicts")
+
+	// Verbose enables extra logging.
+	Verbose bool
+)
+
+type renamer struct {
+	iprog              *loader.Program
+	objsToUpdate       map[types.Object]bool
+	hadConflicts       bool
+	to                 string
+	satisfyConstraints map[satisfy.Constraint]bool
+	packages           map[*types.Package]*loader.PackageInfo // subset of iprog.AllPackages to inspect
+}
+
+var reportError = func(posn token.Position, message string) {
+	fmt.Fprintf(os.Stderr, "%s: %s\n", posn, message)
+}
+
+func Main(ctxt *build.Context, offsetFlag, fromFlag, to string) error {
+	// -- Parse the -from or -offset specifier ----------------------------
+
+	if (offsetFlag == "") == (fromFlag == "") {
+		return fmt.Errorf("exactly one of the -from and -offset flags must be specified")
+	}
+
+	if !isValidIdentifier(to) {
+		return fmt.Errorf("-to %q: not a valid identifier", to)
+	}
+
+	var spec *spec
+	var err error
+	if fromFlag != "" {
+		spec, err = parseFromFlag(ctxt, fromFlag)
+	} else {
+		spec, err = parseOffsetFlag(ctxt, offsetFlag)
+	}
+	if err != nil {
+		return err
+	}
+
+	if spec.fromName == to {
+		return fmt.Errorf("the old and new names are the same: %s", to)
+	}
+
+	// -- Load the program consisting of the initial package  -------------
+
+	iprog, err := loadProgram(ctxt, map[string]bool{spec.pkg: true})
+	if err != nil {
+		return err
+	}
+
+	fromObjects, err := findFromObjects(iprog, spec)
+	if err != nil {
+		return err
+	}
+
+	// -- Load a larger program, for global renamings ---------------------
+
+	if requiresGlobalRename(fromObjects, to) {
+		// For a local refactoring, we needn't load more
+		// packages, but if the renaming affects the package's
+		// API, we we must load all packages that depend on the
+		// package defining the object, plus their tests.
+
+		if Verbose {
+			fmt.Fprintln(os.Stderr, "Potentially global renaming; scanning workspace...")
+		}
+
+		// Scan the workspace and build the import graph.
+		_, rev, errors := importgraph.Build(ctxt)
+		if len(errors) > 0 {
+			fmt.Fprintf(os.Stderr, "While scanning Go workspace:\n")
+			for path, err := range errors {
+				fmt.Fprintf(os.Stderr, "Package %q: %s.\n", path, err)
+			}
+		}
+
+		// Enumerate the set of potentially affected packages.
+		affectedPackages := make(map[string]bool)
+		for _, obj := range fromObjects {
+			// External test packages are never imported,
+			// so they will never appear in the graph.
+			for path := range rev.Search(obj.Pkg().Path()) {
+				affectedPackages[path] = true
+			}
+		}
+
+		// TODO(adonovan): allow the user to specify the scope,
+		// or -ignore patterns?  Computing the scope when we
+		// don't (yet) support inputs containing errors can make
+		// the tool rather brittle.
+
+		// Re-load the larger program.
+		iprog, err = loadProgram(ctxt, affectedPackages)
+		if err != nil {
+			return err
+		}
+
+		fromObjects, err = findFromObjects(iprog, spec)
+		if err != nil {
+			return err
+		}
+	}
+
+	// -- Do the renaming -------------------------------------------------
+
+	r := renamer{
+		iprog:        iprog,
+		objsToUpdate: make(map[types.Object]bool),
+		to:           to,
+		packages:     make(map[*types.Package]*loader.PackageInfo),
+	}
+
+	// Only the initially imported packages (iprog.Imported) and
+	// their external tests (iprog.Created) should be inspected or
+	// modified, as only they have type-checked functions bodies.
+	// The rest are just dependencies, needed only for package-level
+	// type information.
+	for _, info := range iprog.Imported {
+		r.packages[info.Pkg] = info
+	}
+	for _, info := range iprog.Created { // (tests)
+		r.packages[info.Pkg] = info
+	}
+
+	for _, from := range fromObjects {
+		r.check(from)
+	}
+	if r.hadConflicts && !Force {
+		return ConflictError
+	}
+	if DryRun {
+		// TODO(adonovan): print the delta?
+		return nil
+	}
+	return r.update()
+}
+
+// loadProgram loads the specified set of packages (plus their tests)
+// and all their dependencies, from source, through the specified build
+// context.  Only packages in pkgs will have their functions bodies typechecked.
+func loadProgram(ctxt *build.Context, pkgs map[string]bool) (*loader.Program, error) {
+	conf := loader.Config{
+		Build:         ctxt,
+		SourceImports: true,
+		ParserMode:    parser.ParseComments,
+
+		// TODO(adonovan): enable this.  Requires making a lot of code more robust!
+		AllowErrors: false,
+	}
+
+	// Optimization: don't type-check the bodies of functions in our
+	// dependencies, since we only need exported package members.
+	conf.TypeCheckFuncBodies = func(p string) bool {
+		return pkgs[p] || pkgs[strings.TrimSuffix(p, "_test")]
+	}
+
+	if Verbose {
+		var list []string
+		for pkg := range pkgs {
+			list = append(list, pkg)
+		}
+		sort.Strings(list)
+		for _, pkg := range list {
+			fmt.Fprintf(os.Stderr, "Loading package: %s\n", pkg)
+		}
+	}
+
+	for pkg := range pkgs {
+		if err := conf.ImportWithTests(pkg); err != nil {
+			return nil, err
+		}
+	}
+	return conf.Load()
+}
+
+// requiresGlobalRename reports whether this renaming could potentially
+// affect other packages in the Go workspace.
+func requiresGlobalRename(fromObjects []types.Object, to string) bool {
+	var tfm bool
+	for _, from := range fromObjects {
+		if from.Exported() {
+			return true
+		}
+		switch objectKind(from) {
+		case "type", "field", "method":
+			tfm = true
+		}
+	}
+	if ast.IsExported(to) && tfm {
+		// A global renaming may be necessary even if we're
+		// exporting a previous unexported name, since if it's
+		// the name of a type, field or method, this could
+		// change selections in other packages.
+		// (We include "type" in this list because a type
+		// used as an embedded struct field entails a field
+		// renaming.)
+		return true
+	}
+	return false
+}
+
+// update updates the input files.
+func (r *renamer) update() error {
+	// We use token.File, not filename, since a file may appear to
+	// belong to multiple packages and be parsed more than once.
+	// token.File captures this distinction; filename does not.
+	var nidents int
+	var filesToUpdate = make(map[*token.File]bool)
+	for _, info := range r.packages {
+		// Mutate the ASTs and note the filenames.
+		for id, obj := range info.Defs {
+			if r.objsToUpdate[obj] {
+				nidents++
+				id.Name = r.to
+				filesToUpdate[r.iprog.Fset.File(id.Pos())] = true
+			}
+		}
+		for id, obj := range info.Uses {
+			if r.objsToUpdate[obj] {
+				nidents++
+				id.Name = r.to
+				filesToUpdate[r.iprog.Fset.File(id.Pos())] = true
+			}
+		}
+	}
+
+	// TODO(adonovan): don't rewrite cgo + generated files.
+	var nerrs, npkgs int
+	for _, info := range r.packages {
+		first := true
+		for _, f := range info.Files {
+			tokenFile := r.iprog.Fset.File(f.Pos())
+			if filesToUpdate[tokenFile] {
+				if first {
+					npkgs++
+					first = false
+					if Verbose {
+						fmt.Fprintf(os.Stderr, "Updating package %s\n",
+							info.Pkg.Path())
+					}
+				}
+				if err := rewriteFile(r.iprog.Fset, f, tokenFile.Name()); err != nil {
+					fmt.Fprintf(os.Stderr, "gorename: %s\n", err)
+					nerrs++
+				}
+			}
+		}
+	}
+	fmt.Fprintf(os.Stderr, "Renamed %d occurrence%s in %d file%s in %d package%s.\n",
+		nidents, plural(nidents),
+		len(filesToUpdate), plural(len(filesToUpdate)),
+		npkgs, plural(npkgs))
+	if nerrs > 0 {
+		return fmt.Errorf("failed to rewrite %d file%s", nerrs, plural(nerrs))
+	}
+	return nil
+}
+
+func plural(n int) string {
+	if n != 1 {
+		return "s"
+	}
+	return ""
+}
+
+func writeFile(name string, fset *token.FileSet, f *ast.File) error {
+	out, err := os.Create(name)
+	if err != nil {
+		// assume error includes the filename
+		return fmt.Errorf("failed to open file: %s", err)
+	}
+	if err := format.Node(out, fset, f); err != nil {
+		out.Close() // ignore error
+		return fmt.Errorf("failed to write file: %s", err)
+	}
+	return out.Close()
+}
+
+var rewriteFile = func(fset *token.FileSet, f *ast.File, orig string) (err error) {
+	backup := orig + ".gorename.backup"
+	// TODO(adonovan): print packages and filenames in a form useful
+	// to editors (so they can reload files).
+	if Verbose {
+		fmt.Fprintf(os.Stderr, "\t%s\n", orig)
+	}
+	if err := os.Rename(orig, backup); err != nil {
+		return fmt.Errorf("failed to make backup %s -> %s: %s",
+			orig, filepath.Base(backup), err)
+	}
+	if err := writeFile(orig, fset, f); err != nil {
+		// Restore the file from the backup.
+		os.Remove(orig)         // ignore error
+		os.Rename(backup, orig) // ignore error
+		return err
+	}
+	os.Remove(backup) // ignore error
+	return nil
+}
diff --git a/third_party/go.tools/refactor/rename/rename_test.go b/third_party/go.tools/refactor/rename/rename_test.go
new file mode 100644
index 0000000..a4169b3
--- /dev/null
+++ b/third_party/go.tools/refactor/rename/rename_test.go
@@ -0,0 +1,803 @@
+// Copyright 2014 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 rename
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"regexp"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+)
+
+// TODO(adonovan): test reported source positions, somehow.
+
+func TestConflicts(t *testing.T) {
+	defer func(savedDryRun bool, savedReportError func(token.Position, string)) {
+		DryRun = savedDryRun
+		reportError = savedReportError
+	}(DryRun, reportError)
+	DryRun = true
+
+	var ctxt *build.Context
+	for _, test := range []struct {
+		ctxt             *build.Context // nil => use previous
+		offset, from, to string         // values of the -offset/-from and -to flags
+		want             string         // regexp to match conflict errors, or "OK"
+	}{
+		// init() checks
+		{
+			ctxt: fakeContext(map[string][]string{
+				"fmt": {`package fmt; type Stringer interface { String() }`},
+				"main": {`
+package main
+
+import foo "fmt"
+
+var v foo.Stringer
+
+func f() { v.String(); f() }
+`,
+					`package main; var w int`},
+			}),
+			from: "main.v", to: "init",
+			want: `you cannot have a var at package level named "init"`,
+		},
+		{
+			from: "main.f", to: "init",
+			want: `renaming this func "f" to "init" would make it a package initializer.*` +
+				`but references to it exist`,
+		},
+		{
+			from: "/go/src/main/0.go::foo", to: "init",
+			want: `"init" is not a valid imported package name`,
+		},
+
+		// Export checks
+		{
+			from: "fmt.Stringer", to: "stringer",
+			want: `renaming this type "Stringer" to "stringer" would make it unexported.*` +
+				`breaking references from packages such as "main"`,
+		},
+		{
+			from: "(fmt.Stringer).String", to: "string",
+			want: `renaming this method "String" to "string" would make it unexported.*` +
+				`breaking references from packages such as "main"`,
+		},
+
+		// Lexical scope checks
+		{
+			// file/package conflict, same file
+			from: "main.v", to: "foo",
+			want: `renaming this var "v" to "foo" would conflict.*` +
+				`with this imported package name`,
+		},
+		{
+			// file/package conflict, same file
+			from: "main::foo", to: "v",
+			want: `renaming this imported package name "foo" to "v" would conflict.*` +
+				`with this package member var`,
+		},
+		{
+			// file/package conflict, different files
+			from: "main.w", to: "foo",
+			want: `renaming this var "w" to "foo" would conflict.*` +
+				`with this imported package name`,
+		},
+		{
+			// file/package conflict, different files
+			from: "main::foo", to: "w",
+			want: `renaming this imported package name "foo" to "w" would conflict.*` +
+				`with this package member var`,
+		},
+		{
+			ctxt: main(`
+package main
+
+var x, z int
+
+func f(y int) {
+	print(x)
+	print(y)
+}
+
+func g(w int) {
+	print(x)
+	x := 1
+	print(x)
+}`),
+			from: "main.x", to: "y",
+			want: `renaming this var "x" to "y".*` +
+				`would cause this reference to become shadowed.*` +
+				`by this intervening var definition`,
+		},
+		{
+			from: "main.g::x", to: "w",
+			want: `renaming this var "x" to "w".*` +
+				`conflicts with var in same block`,
+		},
+		{
+			from: "main.f::y", to: "x",
+			want: `renaming this var "y" to "x".*` +
+				`would shadow this reference.*` +
+				`to the var declared here`,
+		},
+		{
+			from: "main.g::w", to: "x",
+			want: `renaming this var "w" to "x".*` +
+				`conflicts with var in same block`,
+		},
+		{
+			from: "main.z", to: "y", want: "OK",
+		},
+
+		// Label checks
+		{
+			ctxt: main(`
+package main
+
+func f() {
+foo:
+	goto foo
+bar:
+	goto bar
+	func(x int) {
+	wiz:
+		goto wiz
+	}(0)
+}
+`),
+			from: "main.f::foo", to: "bar",
+			want: `renaming this label "foo" to "bar".*` +
+				`would conflict with this one`,
+		},
+		{
+			from: "main.f::foo", to: "wiz", want: "OK",
+		},
+		{
+			from: "main.f::wiz", to: "x", want: "OK",
+		},
+		{
+			from: "main.f::x", to: "wiz", want: "OK",
+		},
+		{
+			from: "main.f::wiz", to: "foo", want: "OK",
+		},
+
+		// Struct fields
+		{
+			ctxt: main(`
+package main
+
+type U struct { u int }
+type V struct { v int }
+
+func (V) x() {}
+
+type W (struct {
+	U
+	V
+	w int
+})
+
+func f() {
+	var w W
+	print(w.u) // NB: there is no selection of w.v
+	var _ struct { yy, zz int }
+}
+`),
+			// field/field conflict in named struct declaration
+			from: "(main.W).U", to: "w",
+			want: `renaming this field "U" to "w".*` +
+				`would conflict with this field`,
+		},
+		{
+			// rename type used as embedded field
+			// => rename field
+			// => field/field conflict
+			// This is an entailed renaming;
+			// it would be nice if we checked source positions.
+			from: "main.U", to: "w",
+			want: `renaming this field "U" to "w".*` +
+				`would conflict with this field`,
+		},
+		{
+			// field/field conflict in unnamed struct declaration
+			from: "main.f::zz", to: "yy",
+			want: `renaming this field "zz" to "yy".*` +
+				`would conflict with this field`,
+		},
+
+		// Now we test both directions of (u,v) (u,w) (v,w) (u,x) (v,x).
+		// Too bad we don't test position info...
+		{
+			// field/field ambiguity at same promotion level ('from' selection)
+			from: "(main.U).u", to: "v",
+			want: `renaming this field "u" to "v".*` +
+				`would make this reference ambiguous.*` +
+				`with this field`,
+		},
+		{
+			// field/field ambiguity at same promotion level ('to' selection)
+			from: "(main.V).v", to: "u",
+			want: `renaming this field "v" to "u".*` +
+				`would make this reference ambiguous.*` +
+				`with this field`,
+		},
+		{
+			// field/method conflict at different promotion level ('from' selection)
+			from: "(main.U).u", to: "w",
+			want: `renaming this field "u" to "w".*` +
+				`would change the referent of this selection.*` +
+				`to this field`,
+		},
+		{
+			// field/field shadowing at different promotion levels ('to' selection)
+			from: "(main.W).w", to: "u",
+			want: `renaming this field "w" to "u".*` +
+				`would shadow this selection.*` +
+				`to the field declared here`,
+		},
+		{
+			from: "(main.V).v", to: "w",
+			want: "OK", // since no selections are made ambiguous
+		},
+		{
+			from: "(main.W).w", to: "v",
+			want: "OK", // since no selections are made ambiguous
+		},
+		{
+			// field/method ambiguity at same promotion level ('from' selection)
+			from: "(main.U).u", to: "x",
+			want: `renaming this field "u" to "x".*` +
+				`would make this reference ambiguous.*` +
+				`with this method`,
+		},
+		{
+			// field/field ambiguity at same promotion level ('to' selection)
+			from: "(main.V).x", to: "u",
+			want: `renaming this method "x" to "u".*` +
+				`would make this reference ambiguous.*` +
+				`with this field`,
+		},
+		{
+			// field/method conflict at named struct declaration
+			from: "(main.V).v", to: "x",
+			want: `renaming this field "v" to "x".*` +
+				`would conflict with this method`,
+		},
+		{
+			// field/method conflict at named struct declaration
+			from: "(main.V).x", to: "v",
+			want: `renaming this method "x" to "v".*` +
+				`would conflict with this field`,
+		},
+
+		// Methods
+		{
+			ctxt: main(`
+package main
+type C int
+func (C) f()
+func (C) g()
+type D int
+func (*D) f()
+func (*D) g()
+type I interface { f(); g() }
+type J interface { I; h() }
+var _ I = new(D)
+var _ interface {f()} = C(0)
+`),
+			from: "(main.I).f", to: "g",
+			want: `renaming this interface method "f" to "g".*` +
+				`would conflict with this method`,
+		},
+		{
+			from: `("main".I).f`, to: "h", // NB: exercises quoted import paths too
+			want: `renaming this interface method "f" to "h".*` +
+				`would conflict with this method.*` +
+				`in named interface type "J"`,
+		},
+		{
+			// type J interface { h; h() } is not a conflict, amusingly.
+			from: "main.I", to: "h",
+			want: `OK`,
+		},
+		{
+			from: "(main.J).h", to: "f",
+			want: `renaming this interface method "h" to "f".*` +
+				`would conflict with this method`,
+		},
+		{
+			from: "(main.C).f", to: "e",
+			want: `renaming this method "f" to "e".*` +
+				`would make it no longer assignable to interface{f..}`,
+		},
+		{
+			from: "(main.D).g", to: "e",
+			want: `renaming this method "g" to "e".*` +
+				`would make it no longer assignable to interface I`,
+		},
+		{
+			from: "(main.I).f", to: "e",
+			want: `renaming this method "f" to "e".*` +
+				`would make \*main.D no longer assignable to it`,
+		},
+	} {
+		var conflicts []string
+		reportError = func(posn token.Position, message string) {
+			conflicts = append(conflicts, message)
+		}
+		if test.ctxt != nil {
+			ctxt = test.ctxt
+		}
+		err := Main(ctxt, test.offset, test.from, test.to)
+		var prefix string
+		if test.offset == "" {
+			prefix = fmt.Sprintf("-from %q -to %q", test.from, test.to)
+		} else {
+			prefix = fmt.Sprintf("-offset %q -to %q", test.offset, test.to)
+		}
+		if err == ConflictError {
+			got := strings.Join(conflicts, "\n")
+			if false {
+				t.Logf("%s: %s", prefix, got)
+			}
+			pattern := "(?s:" + test.want + ")" // enable multi-line matching
+			if !regexp.MustCompile(pattern).MatchString(got) {
+				t.Errorf("%s: conflict does not match pattern:\n"+
+					"Conflict:\t%s\n"+
+					"Pattern: %s",
+					prefix, got, test.want)
+			}
+		} else if err != nil {
+			t.Errorf("%s: unexpected error: %s", prefix, err)
+		} else if test.want != "OK" {
+			t.Errorf("%s: unexpected success, want conflicts matching:\n%s",
+				prefix, test.want)
+		}
+	}
+}
+
+func TestRewrites(t *testing.T) {
+	defer func(savedRewriteFile func(*token.FileSet, *ast.File, string) error) {
+		rewriteFile = savedRewriteFile
+	}(rewriteFile)
+
+	var ctxt *build.Context
+	for _, test := range []struct {
+		ctxt             *build.Context    // nil => use previous
+		offset, from, to string            // values of the -from/-offset and -to flags
+		want             map[string]string // contents of updated files
+	}{
+		// Elimination of renaming import.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"main": {`package main
+
+import foo2 "foo"
+
+var _ foo2.T
+`},
+			}),
+			from: "main::foo2", to: "foo",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+import "foo"
+
+var _ foo.T
+`,
+			},
+		},
+		// Introduction of renaming import.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"main": {`package main
+
+import "foo"
+
+var _ foo.T
+`},
+			}),
+			offset: "/go/src/main/0.go:#36", to: "foo2", // the "foo" in foo.T
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+import foo2 "foo"
+
+var _ foo2.T
+`,
+			},
+		},
+		// Renaming of package-level member.
+		{
+			from: "foo.T", to: "U",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+import "foo"
+
+var _ foo.U
+`,
+				"/go/src/foo/0.go": `package foo
+
+type U int
+`,
+			},
+		},
+		// Label renamings.
+		{
+			ctxt: main(`package main
+func f() {
+loop:
+	loop := 0
+	go func() {
+	loop:
+		goto loop
+	}()
+	loop++
+	goto loop
+}
+`),
+			offset: "/go/src/main/0.go:#25", to: "loop2", // def of outer label "loop"
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+func f() {
+loop2:
+	loop := 0
+	go func() {
+	loop:
+		goto loop
+	}()
+	loop++
+	goto loop2
+}
+`,
+			},
+		},
+		{
+			offset: "/go/src/main/0.go:#70", to: "loop2", // ref to inner label "loop"
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+func f() {
+loop:
+	loop := 0
+	go func() {
+	loop2:
+		goto loop2
+	}()
+	loop++
+	goto loop
+}
+`,
+			},
+		},
+		// Renaming of type used as embedded field.
+		{
+			ctxt: main(`package main
+
+type T int
+type U struct { T }
+
+var _ = U{}.T
+`),
+			from: "main.T", to: "T2",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type T2 int
+type U struct{ T2 }
+
+var _ = U{}.T2
+`,
+			},
+		},
+		// Renaming of embedded field.
+		{
+			ctxt: main(`package main
+
+type T int
+type U struct { T }
+
+var _ = U{}.T
+`),
+			offset: "/go/src/main/0.go:#58", to: "T2", // T in "U{}.T"
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type T2 int
+type U struct{ T2 }
+
+var _ = U{}.T2
+`,
+			},
+		},
+		// Renaming of pointer embedded field.
+		{
+			ctxt: main(`package main
+
+type T int
+type U struct { *T }
+
+var _ = U{}.T
+`),
+			offset: "/go/src/main/0.go:#59", to: "T2", // T in "U{}.T"
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type T2 int
+type U struct{ *T2 }
+
+var _ = U{}.T2
+`,
+			},
+		},
+
+		// Lexical scope tests.
+		{
+			ctxt: main(`package main
+
+var y int
+
+func f() {
+	print(y)
+	y := ""
+	print(y)
+}
+`),
+			from: "main.y", to: "x",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+var x int
+
+func f() {
+	print(x)
+	y := ""
+	print(y)
+}
+`,
+			},
+		},
+		{
+			from: "main.f::y", to: "x",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+var y int
+
+func f() {
+	print(y)
+	x := ""
+	print(x)
+}
+`,
+			},
+		},
+		// Renaming of typeswitch vars (a corner case).
+		{
+			ctxt: main(`package main
+
+func f(z interface{}) {
+	switch y := z.(type) {
+	case int:
+		print(y)
+	default:
+		print(y)
+	}
+}
+`),
+			offset: "/go/src/main/0.go:#46", to: "x", // def of y
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+func f(z interface{}) {
+	switch x := z.(type) {
+	case int:
+		print(x)
+	default:
+		print(x)
+	}
+}
+`},
+		},
+		{
+			offset: "/go/src/main/0.go:#81", to: "x", // ref of y in case int
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+func f(z interface{}) {
+	switch x := z.(type) {
+	case int:
+		print(x)
+	default:
+		print(x)
+	}
+}
+`},
+		},
+		{
+			offset: "/go/src/main/0.go:#102", to: "x", // ref of y in default case
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+func f(z interface{}) {
+	switch x := z.(type) {
+	case int:
+		print(x)
+	default:
+		print(x)
+	}
+}
+`},
+		},
+
+		// Renaming of embedded field that is a qualified reference.
+		// (Regression test for bug 8924.)
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"main": {`package main
+
+import "foo"
+
+type _ struct{ *foo.T }
+`},
+			}),
+			offset: "/go/src/main/0.go:#48", to: "U", // the "T" in *foo.T
+			want: map[string]string{
+				"/go/src/foo/0.go": `package foo
+
+type U int
+`,
+				"/go/src/main/0.go": `package main
+
+import "foo"
+
+type _ struct{ *foo.U }
+`,
+			},
+		},
+	} {
+		if test.ctxt != nil {
+			ctxt = test.ctxt
+		}
+
+		got := make(map[string]string)
+		rewriteFile = func(fset *token.FileSet, f *ast.File, orig string) error {
+			var out bytes.Buffer
+			if err := format.Node(&out, fset, f); err != nil {
+				return err
+			}
+			got[filepath.ToSlash(orig)] = out.String()
+			return nil
+		}
+
+		err := Main(ctxt, test.offset, test.from, test.to)
+		var prefix string
+		if test.offset == "" {
+			prefix = fmt.Sprintf("-from %q -to %q", test.from, test.to)
+		} else {
+			prefix = fmt.Sprintf("-offset %q -to %q", test.offset, test.to)
+		}
+		if err != nil {
+			t.Errorf("%s: unexpected error: %s", prefix, err)
+			continue
+		}
+
+		for file, wantContent := range test.want {
+			gotContent, ok := got[file]
+			delete(got, file)
+			if !ok {
+				t.Errorf("%s: file %s not rewritten", prefix, file)
+				continue
+			}
+			if gotContent != wantContent {
+				t.Errorf("%s: rewritten file %s does not match expectation; got <<<%s>>>\n"+
+					"want <<<%s>>>", prefix, file, gotContent, wantContent)
+			}
+		}
+		// got should now be empty
+		for file := range got {
+			t.Errorf("%s: unexpected rewrite of file %s", prefix, file)
+		}
+	}
+}
+
+// ---------------------------------------------------------------------
+
+// Plundered/adapted from go/loader/loader_test.go
+
+// TODO(adonovan): make this into a nice testing utility within go/buildutil.
+
+// pkgs maps the import path of a fake package to a list of its file contents;
+// file names are synthesized, e.g. %d.go.
+func fakeContext(pkgs map[string][]string) *build.Context {
+	ctxt := build.Default // copy
+	ctxt.GOROOT = "/go"
+	ctxt.GOPATH = ""
+	ctxt.IsDir = func(path string) bool {
+		path = filepath.ToSlash(path)
+		if path == "/go/src" {
+			return true // needed by (*build.Context).SrcDirs
+		}
+		if p := strings.TrimPrefix(path, "/go/src/"); p == path {
+			return false
+		} else {
+			path = p
+		}
+		_, ok := pkgs[path]
+		return ok
+	}
+	ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) {
+		dir = filepath.ToSlash(dir)
+		dir = dir[len("/go/src/"):]
+		var fis []os.FileInfo
+		if dir == "" {
+			// Assumes keys of pkgs are single-segment.
+			for p := range pkgs {
+				fis = append(fis, fakeDirInfo(p))
+			}
+		} else {
+			for i := range pkgs[dir] {
+				fis = append(fis, fakeFileInfo(i))
+			}
+		}
+		return fis, nil
+	}
+	ctxt.OpenFile = func(path string) (io.ReadCloser, error) {
+		path = filepath.ToSlash(path)
+		path = path[len("/go/src/"):]
+		dir, base := filepath.Split(path)
+		dir = filepath.Clean(dir)
+		index, _ := strconv.Atoi(strings.TrimSuffix(base, ".go"))
+		return ioutil.NopCloser(bytes.NewBufferString(pkgs[dir][index])), nil
+	}
+	ctxt.IsAbsPath = func(path string) bool {
+		path = filepath.ToSlash(path)
+		// Don't rely on the default (filepath.Path) since on
+		// Windows, it reports our virtual paths as non-absolute.
+		return strings.HasPrefix(path, "/")
+	}
+	return &ctxt
+}
+
+// helper for single-file main packages with no imports.
+func main(content string) *build.Context {
+	return fakeContext(map[string][]string{"main": {content}})
+}
+
+type fakeFileInfo int
+
+func (fi fakeFileInfo) Name() string    { return fmt.Sprintf("%d.go", fi) }
+func (fakeFileInfo) Sys() interface{}   { return nil }
+func (fakeFileInfo) ModTime() time.Time { return time.Time{} }
+func (fakeFileInfo) IsDir() bool        { return false }
+func (fakeFileInfo) Size() int64        { return 0 }
+func (fakeFileInfo) Mode() os.FileMode  { return 0644 }
+
+type fakeDirInfo string
+
+func (fd fakeDirInfo) Name() string    { return string(fd) }
+func (fakeDirInfo) Sys() interface{}   { return nil }
+func (fakeDirInfo) ModTime() time.Time { return time.Time{} }
+func (fakeDirInfo) IsDir() bool        { return true }
+func (fakeDirInfo) Size() int64        { return 0 }
+func (fakeDirInfo) Mode() os.FileMode  { return 0755 }
diff --git a/third_party/go.tools/refactor/rename/spec.go b/third_party/go.tools/refactor/rename/spec.go
new file mode 100644
index 0000000..388d568
--- /dev/null
+++ b/third_party/go.tools/refactor/rename/spec.go
@@ -0,0 +1,569 @@
+// Copyright 2014 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 rename
+
+// This file contains logic related to specifying a renaming: parsing of
+// the flags as a form of query, and finding the object(s) it denotes.
+// See FromFlagUsage for details.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+
+	"llvm.org/llgo/third_party/go.tools/go/buildutil"
+	"llvm.org/llgo/third_party/go.tools/go/loader"
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+// A spec specifies an entity to rename.
+//
+// It is populated from an -offset flag or -from query; see
+// FromFlagUsage for the allowed -from query forms.
+//
+type spec struct {
+	// pkg is the package containing the position
+	// specified by the -from or -offset flag.
+	// If filename == "", our search for the 'from' entity
+	// is restricted to this package.
+	pkg string
+
+	// The original name of the entity being renamed.
+	// If the query had a ::from component, this is that;
+	// otherwise it's the last segment, e.g.
+	//   (encoding/json.Decoder).from
+	//   encoding/json.from
+	fromName string
+
+	// -- The remaining fields are private to this file.  All are optional. --
+
+	// The query's ::x suffix, if any.
+	searchFor string
+
+	// e.g. "Decoder" in "(encoding/json.Decoder).fieldOrMethod"
+	//                or "encoding/json.Decoder
+	pkgMember string
+
+	// e.g. fieldOrMethod in "(encoding/json.Decoder).fieldOrMethod"
+	typeMember string
+
+	// Restricts the query to this file.
+	// Implied by -from="file.go::x" and -offset flags.
+	filename string
+
+	// Byte offset of the 'from' identifier within the file named 'filename'.
+	// -offset mode only.
+	offset int
+}
+
+const FromFlagUsage = `
+A legal -from query has one of the following forms:
+
+  "encoding/json".Decoder.Decode	method of package-level named type
+  (*"encoding/json".Decoder).Decode	ditto, alternative syntax
+  "encoding/json".Decoder.buf           field of package-level named struct type
+  "encoding/json".HTMLEscape            package member (const, func, var, type)
+  "encoding/json".Decoder.Decode::x     local object x within a method
+  "encoding/json".HTMLEscape::x         local object x within a function
+  "encoding/json"::x                    object x anywhere within a package
+  json.go::x                            object x within file json.go
+
+  For methods, the parens and '*' on the receiver type are both optional.
+
+  Double-quotes may be omitted for single-segment import paths such as
+  fmt.  They may need to be escaped when writing a shell command.
+
+  It is an error if one of the ::x queries matches multiple objects.
+`
+
+// parseFromFlag interprets the "-from" flag value as a renaming specification.
+// See FromFlagUsage for valid formats.
+func parseFromFlag(ctxt *build.Context, fromFlag string) (*spec, error) {
+	var spec spec
+	var main string // sans "::x" suffix
+	switch parts := strings.Split(fromFlag, "::"); len(parts) {
+	case 1:
+		main = parts[0]
+	case 2:
+		main = parts[0]
+		spec.searchFor = parts[1]
+		if parts[1] == "" {
+			// error
+		}
+	default:
+		return nil, fmt.Errorf("-from %q: invalid identifier specification (see -help for formats)", fromFlag)
+	}
+
+	if strings.HasSuffix(main, ".go") {
+		// main is "filename.go"
+		if spec.searchFor == "" {
+			return nil, fmt.Errorf("-from: filename %q must have a ::name suffix", main)
+		}
+		spec.filename = main
+		if !buildutil.FileExists(ctxt, spec.filename) {
+			return nil, fmt.Errorf("no such file: %s", spec.filename)
+		}
+
+		bp, err := buildutil.ContainingPackage(ctxt, wd, spec.filename)
+		if err != nil {
+			return nil, err
+		}
+		spec.pkg = bp.ImportPath
+
+	} else {
+		// main is one of:
+		//  "importpath"
+		//  "importpath".member
+		//  (*"importpath".type).fieldormethod           (parens and star optional)
+		if err := parseObjectSpec(&spec, main); err != nil {
+			return nil, err
+		}
+	}
+
+	if spec.searchFor != "" {
+		spec.fromName = spec.searchFor
+	}
+
+	// Sanitize the package.
+	// TODO(adonovan): test with relative packages.  May need loader changes.
+	bp, err := ctxt.Import(spec.pkg, ".", build.FindOnly)
+	if err != nil {
+		return nil, fmt.Errorf("can't find package %q", spec.pkg)
+	}
+	spec.pkg = bp.ImportPath
+
+	if !isValidIdentifier(spec.fromName) {
+		return nil, fmt.Errorf("-from: invalid identifier %q", spec.fromName)
+	}
+
+	if Verbose {
+		fmt.Fprintf(os.Stderr, "-from spec: %+v\n", spec)
+	}
+
+	return &spec, nil
+}
+
+// parseObjectSpec parses main as one of the non-filename forms of
+// object specification.
+func parseObjectSpec(spec *spec, main string) error {
+	// Parse main as a Go expression, albeit a strange one.
+	e, _ := parser.ParseExpr(main)
+
+	if pkg := parseImportPath(e); pkg != "" {
+		// e.g. bytes or "encoding/json": a package
+		spec.pkg = pkg
+		if spec.searchFor == "" {
+			return fmt.Errorf("-from %q: package import path %q must have a ::name suffix",
+				main, main)
+		}
+		return nil
+	}
+
+	if e, ok := e.(*ast.SelectorExpr); ok {
+		x := unparen(e.X)
+
+		// Strip off star constructor, if any.
+		if star, ok := x.(*ast.StarExpr); ok {
+			x = star.X
+		}
+
+		if pkg := parseImportPath(x); pkg != "" {
+			// package member e.g. "encoding/json".HTMLEscape
+			spec.pkg = pkg              // e.g. "encoding/json"
+			spec.pkgMember = e.Sel.Name // e.g. "HTMLEscape"
+			spec.fromName = e.Sel.Name
+			return nil
+		}
+
+		if x, ok := x.(*ast.SelectorExpr); ok {
+			// field/method of type e.g. ("encoding/json".Decoder).Decode
+			y := unparen(x.X)
+			if pkg := parseImportPath(y); pkg != "" {
+				spec.pkg = pkg               // e.g. "encoding/json"
+				spec.pkgMember = x.Sel.Name  // e.g. "Decoder"
+				spec.typeMember = e.Sel.Name // e.g. "Decode"
+				spec.fromName = e.Sel.Name
+				return nil
+			}
+		}
+	}
+
+	return fmt.Errorf("-from %q: invalid expression", main)
+}
+
+// parseImportPath returns the import path of the package denoted by e.
+// Any import path may be represented as a string literal;
+// single-segment import paths (e.g. "bytes") may also be represented as
+// ast.Ident.  parseImportPath returns "" for all other expressions.
+func parseImportPath(e ast.Expr) string {
+	switch e := e.(type) {
+	case *ast.Ident:
+		return e.Name // e.g. bytes
+
+	case *ast.BasicLit:
+		if e.Kind == token.STRING {
+			pkgname, _ := strconv.Unquote(e.Value)
+			return pkgname // e.g. "encoding/json"
+		}
+	}
+	return ""
+}
+
+// parseOffsetFlag interprets the "-offset" flag value as a renaming specification.
+func parseOffsetFlag(ctxt *build.Context, offsetFlag string) (*spec, error) {
+	var spec spec
+	// Validate -offset, e.g. file.go:#123
+	parts := strings.Split(offsetFlag, ":#")
+	if len(parts) != 2 {
+		return nil, fmt.Errorf("-offset %q: invalid offset specification", offsetFlag)
+	}
+
+	spec.filename = parts[0]
+	if !buildutil.FileExists(ctxt, spec.filename) {
+		return nil, fmt.Errorf("no such file: %s", spec.filename)
+	}
+
+	bp, err := buildutil.ContainingPackage(ctxt, wd, spec.filename)
+	if err != nil {
+		return nil, err
+	}
+	spec.pkg = bp.ImportPath
+
+	for _, r := range parts[1] {
+		if !isDigit(r) {
+			return nil, fmt.Errorf("-offset %q: non-numeric offset", offsetFlag)
+		}
+	}
+	spec.offset, err = strconv.Atoi(parts[1])
+	if err != nil {
+		return nil, fmt.Errorf("-offset %q: non-numeric offset", offsetFlag)
+	}
+
+	// Parse the file and check there's an identifier at that offset.
+	fset := token.NewFileSet()
+	f, err := buildutil.ParseFile(fset, ctxt, nil, wd, spec.filename, parser.ParseComments)
+	if err != nil {
+		return nil, fmt.Errorf("-offset %q: cannot parse file: %s", offsetFlag, err)
+	}
+
+	id := identAtOffset(fset, f, spec.offset)
+	if id == nil {
+		return nil, fmt.Errorf("-offset %q: no identifier at this position", offsetFlag)
+	}
+
+	spec.fromName = id.Name
+
+	return &spec, nil
+}
+
+var wd = func() string {
+	wd, err := os.Getwd()
+	if err != nil {
+		panic("cannot get working directory: " + err.Error())
+	}
+	return wd
+}()
+
+// For source trees built with 'go build', the -from or -offset
+// spec identifies exactly one initial 'from' object to rename ,
+// but certain proprietary build systems allow a single file to
+// appear in multiple packages (e.g. the test package contains a
+// copy of its library), so there may be multiple objects for
+// the same source entity.
+
+func findFromObjects(iprog *loader.Program, spec *spec) ([]types.Object, error) {
+	if spec.filename != "" {
+		return findFromObjectsInFile(iprog, spec)
+	}
+
+	// Search for objects defined in specified package.
+
+	// TODO(adonovan): the iprog.ImportMap has an entry {"main": ...}
+	// for main packages, even though that's not an import path.
+	// Seems like a bug.
+	//
+	// pkgObj := iprog.ImportMap[spec.pkg]
+	// if pkgObj == nil {
+	// 	return fmt.Errorf("cannot find package %s", spec.pkg) // can't happen?
+	// }
+
+	// Workaround: lookup by value.
+	var pkgObj *types.Package
+	for pkg := range iprog.AllPackages {
+		if pkg.Path() == spec.pkg {
+			pkgObj = pkg
+			break
+		}
+	}
+	info := iprog.AllPackages[pkgObj]
+
+	objects, err := findObjects(info, spec)
+	if err != nil {
+		return nil, err
+	}
+	if len(objects) > 1 {
+		// ambiguous "*" scope query
+		return nil, ambiguityError(iprog.Fset, objects)
+	}
+	return objects, nil
+}
+
+func findFromObjectsInFile(iprog *loader.Program, spec *spec) ([]types.Object, error) {
+	var fromObjects []types.Object
+	for _, info := range iprog.AllPackages {
+		// restrict to specified filename
+		// NB: under certain proprietary build systems, a given
+		// filename may appear in multiple packages.
+		for _, f := range info.Files {
+			thisFile := iprog.Fset.File(f.Pos())
+			if !sameFile(thisFile.Name(), spec.filename) {
+				continue
+			}
+			// This package contains the query file.
+
+			if spec.offset != 0 {
+				// Search for a specific ident by file/offset.
+				id := identAtOffset(iprog.Fset, f, spec.offset)
+				if id == nil {
+					// can't happen?
+					return nil, fmt.Errorf("identifier not found")
+				}
+				obj := info.Uses[id]
+				if obj == nil {
+					obj = info.Defs[id]
+					if obj == nil {
+						// Ident without Object.
+
+						// Package clause?
+						pos := thisFile.Pos(spec.offset)
+						_, path, _ := iprog.PathEnclosingInterval(pos, pos)
+						if len(path) == 2 { // [Ident File]
+							// TODO(adonovan): support this case.
+							return nil, fmt.Errorf("cannot rename %q: renaming package clauses is not yet supported",
+								path[1].(*ast.File).Name.Name)
+						}
+
+						// Implicit y in "switch y := x.(type) {"?
+						if obj := typeSwitchVar(&info.Info, path); obj != nil {
+							return []types.Object{obj}, nil
+						}
+
+						// Probably a type error.
+						return nil, fmt.Errorf("cannot find object for %q", id.Name)
+					}
+				}
+				if obj.Pkg() == nil {
+					return nil, fmt.Errorf("cannot rename predeclared identifiers (%s)", obj)
+
+				}
+
+				fromObjects = append(fromObjects, obj)
+			} else {
+				// do a package-wide query
+				objects, err := findObjects(info, spec)
+				if err != nil {
+					return nil, err
+				}
+
+				// filter results: only objects defined in thisFile
+				var filtered []types.Object
+				for _, obj := range objects {
+					if iprog.Fset.File(obj.Pos()) == thisFile {
+						filtered = append(filtered, obj)
+					}
+				}
+				if len(filtered) == 0 {
+					return nil, fmt.Errorf("no object %q declared in file %s",
+						spec.fromName, spec.filename)
+				} else if len(filtered) > 1 {
+					return nil, ambiguityError(iprog.Fset, filtered)
+				}
+				fromObjects = append(fromObjects, filtered[0])
+			}
+			break
+		}
+	}
+	if len(fromObjects) == 0 {
+		// can't happen?
+		return nil, fmt.Errorf("file %s was not part of the loaded program", spec.filename)
+	}
+	return fromObjects, nil
+}
+
+func typeSwitchVar(info *types.Info, path []ast.Node) types.Object {
+	if len(path) > 3 {
+		// [Ident AssignStmt TypeSwitchStmt...]
+		if sw, ok := path[2].(*ast.TypeSwitchStmt); ok {
+			// choose the first case.
+			if len(sw.Body.List) > 0 {
+				obj := info.Implicits[sw.Body.List[0].(*ast.CaseClause)]
+				if obj != nil {
+					return obj
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// On success, findObjects returns the list of objects named
+// spec.fromName matching the spec.  On success, the result has exactly
+// one element unless spec.searchFor!="", in which case it has at least one
+// element.
+//
+func findObjects(info *loader.PackageInfo, spec *spec) ([]types.Object, error) {
+	if spec.pkgMember == "" {
+		if spec.searchFor == "" {
+			panic(spec)
+		}
+		objects := searchDefs(&info.Info, spec.searchFor)
+		if objects == nil {
+			return nil, fmt.Errorf("no object %q declared in package %q",
+				spec.searchFor, info.Pkg.Path())
+		}
+		return objects, nil
+	}
+
+	pkgMember := info.Pkg.Scope().Lookup(spec.pkgMember)
+	if pkgMember == nil {
+		return nil, fmt.Errorf("package %q has no member %q",
+			info.Pkg.Path(), spec.pkgMember)
+	}
+
+	var searchFunc *types.Func
+	if spec.typeMember == "" {
+		// package member
+		if spec.searchFor == "" {
+			return []types.Object{pkgMember}, nil
+		}
+
+		// Search within pkgMember, which must be a function.
+		searchFunc, _ = pkgMember.(*types.Func)
+		if searchFunc == nil {
+			return nil, fmt.Errorf("cannot search for %q within %s %q",
+				spec.searchFor, objectKind(pkgMember), pkgMember)
+		}
+	} else {
+		// field/method of type
+		// e.g. (encoding/json.Decoder).Decode
+		// or ::x within it.
+
+		tName, _ := pkgMember.(*types.TypeName)
+		if tName == nil {
+			return nil, fmt.Errorf("%s.%s is a %s, not a type",
+				info.Pkg.Path(), pkgMember.Name(), objectKind(pkgMember))
+		}
+
+		// search within named type.
+		obj, _, _ := types.LookupFieldOrMethod(tName.Type(), true, info.Pkg, spec.typeMember)
+		if obj == nil {
+			return nil, fmt.Errorf("cannot find field or method %q of %s %s.%s",
+				spec.typeMember, typeKind(tName.Type()), info.Pkg.Path(), tName.Name())
+		}
+
+		if spec.searchFor == "" {
+			return []types.Object{obj}, nil
+		}
+
+		searchFunc, _ = obj.(*types.Func)
+		if searchFunc == nil {
+			return nil, fmt.Errorf("cannot search for local name %q within %s (%s.%s).%s; need a function",
+				spec.searchFor, objectKind(obj), info.Pkg.Path(), tName.Name(),
+				obj.Name())
+		}
+		if isInterface(tName.Type()) {
+			return nil, fmt.Errorf("cannot search for local name %q within abstract method (%s.%s).%s",
+				spec.searchFor, info.Pkg.Path(), tName.Name(), searchFunc.Name())
+		}
+	}
+
+	// -- search within function or method --
+
+	decl := funcDecl(info, searchFunc)
+	if decl == nil {
+		return nil, fmt.Errorf("cannot find syntax for %s", searchFunc) // can't happen?
+	}
+
+	var objects []types.Object
+	for _, obj := range searchDefs(&info.Info, spec.searchFor) {
+		// We use positions, not scopes, to determine whether
+		// the obj is within searchFunc.  This is clumsy, but the
+		// alternative, using the types.Scope tree, doesn't
+		// account for non-lexical objects like fields and
+		// interface methods.
+		if decl.Pos() <= obj.Pos() && obj.Pos() < decl.End() && obj != searchFunc {
+			objects = append(objects, obj)
+		}
+	}
+	if objects == nil {
+		return nil, fmt.Errorf("no local definition of %q within %s",
+			spec.searchFor, searchFunc)
+	}
+	return objects, nil
+}
+
+func funcDecl(info *loader.PackageInfo, fn *types.Func) *ast.FuncDecl {
+	for _, f := range info.Files {
+		for _, d := range f.Decls {
+			if d, ok := d.(*ast.FuncDecl); ok && info.Defs[d.Name] == fn {
+				return d
+			}
+		}
+	}
+	return nil
+}
+
+func searchDefs(info *types.Info, name string) []types.Object {
+	var objects []types.Object
+	for id, obj := range info.Defs {
+		if obj == nil {
+			// e.g. blank ident.
+			// TODO(adonovan): but also implicit y in
+			//    switch y := x.(type)
+			// Needs some thought.
+			continue
+		}
+		if id.Name == name {
+			objects = append(objects, obj)
+		}
+	}
+	return objects
+}
+
+func identAtOffset(fset *token.FileSet, f *ast.File, offset int) *ast.Ident {
+	var found *ast.Ident
+	ast.Inspect(f, func(n ast.Node) bool {
+		if id, ok := n.(*ast.Ident); ok {
+			idpos := fset.Position(id.Pos()).Offset
+			if idpos <= offset && offset < idpos+len(id.Name) {
+				found = id
+			}
+		}
+		return found == nil // keep traversing only until found
+	})
+	return found
+}
+
+// ambiguityError returns an error describing an ambiguous "*" scope query.
+func ambiguityError(fset *token.FileSet, objects []types.Object) error {
+	var buf bytes.Buffer
+	for i, obj := range objects {
+		if i > 0 {
+			buf.WriteString(", ")
+		}
+		posn := fset.Position(obj.Pos())
+		fmt.Fprintf(&buf, "%s at %s:%d",
+			objectKind(obj), filepath.Base(posn.Filename), posn.Column)
+	}
+	return fmt.Errorf("ambiguous specifier %s matches %s",
+		objects[0].Name(), buf.String())
+}
diff --git a/third_party/go.tools/refactor/rename/util.go b/third_party/go.tools/refactor/rename/util.go
new file mode 100644
index 0000000..195d85c
--- /dev/null
+++ b/third_party/go.tools/refactor/rename/util.go
@@ -0,0 +1,113 @@
+// Copyright 2014 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 rename
+
+import (
+	"go/ast"
+	"os"
+	"path/filepath"
+	"reflect"
+	"runtime"
+	"strings"
+	"unicode"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+)
+
+func objectKind(obj types.Object) string {
+	switch obj := obj.(type) {
+	case *types.PkgName:
+		return "imported package name"
+	case *types.TypeName:
+		return "type"
+	case *types.Var:
+		if obj.IsField() {
+			return "field"
+		}
+	case *types.Func:
+		if obj.Type().(*types.Signature).Recv() != nil {
+			return "method"
+		}
+	}
+	// label, func, var, const
+	return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
+}
+
+func typeKind(T types.Type) string {
+	return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(T.Underlying()).String(), "*types."))
+}
+
+// NB: for renamings, blank is not considered valid.
+func isValidIdentifier(id string) bool {
+	if id == "" || id == "_" {
+		return false
+	}
+	for i, r := range id {
+		if !isLetter(r) && (i == 0 || !isDigit(r)) {
+			return false
+		}
+	}
+	return true
+}
+
+// isLocal reports whether obj is local to some function.
+// Precondition: not a struct field or interface method.
+func isLocal(obj types.Object) bool {
+	// [... 5=stmt 4=func 3=file 2=pkg 1=universe]
+	var depth int
+	for scope := obj.Parent(); scope != nil; scope = scope.Parent() {
+		depth++
+	}
+	return depth >= 4
+}
+
+func isPackageLevel(obj types.Object) bool {
+	return obj.Pkg().Scope().Lookup(obj.Name()) == obj
+}
+
+// -- Plundered from go/scanner: ---------------------------------------
+
+func isLetter(ch rune) bool {
+	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
+}
+
+func isDigit(ch rune) bool {
+	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
+}
+
+// -- Plundered from golang.org/x/tools/oracle -----------------
+
+// sameFile returns true if x and y have the same basename and denote
+// the same file.
+//
+func sameFile(x, y string) bool {
+	if runtime.GOOS == "windows" {
+		x = filepath.ToSlash(x)
+		y = filepath.ToSlash(y)
+	}
+	if x == y {
+		return true
+	}
+	if filepath.Base(x) == filepath.Base(y) { // (optimisation)
+		if xi, err := os.Stat(x); err == nil {
+			if yi, err := os.Stat(y); err == nil {
+				return os.SameFile(xi, yi)
+			}
+		}
+	}
+	return false
+}
+
+// unparen returns e with any enclosing parentheses stripped.
+func unparen(e ast.Expr) ast.Expr {
+	for {
+		p, ok := e.(*ast.ParenExpr)
+		if !ok {
+			break
+		}
+		e = p.X
+	}
+	return e
+}
diff --git a/third_party/go.tools/refactor/satisfy/find.go b/third_party/go.tools/refactor/satisfy/find.go
new file mode 100644
index 0000000..cc50b9d
--- /dev/null
+++ b/third_party/go.tools/refactor/satisfy/find.go
@@ -0,0 +1,725 @@
+// Copyright 2014 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 satisfy inspects the type-checked ASTs of Go packages and
+// reports the set of discovered type constraints of the form (lhs, rhs
+// Type) where lhs is a non-trivial interface, rhs satisfies this
+// interface, and this fact is necessary for the package to be
+// well-typed.
+//
+// THIS PACKAGE IS EXPERIMENTAL AND MAY CHANGE AT ANY TIME.
+//
+// It is provided only for the gorename tool.  Ideally this
+// functionality will become part of the type-checker in due course,
+// since it is computing it anyway, and it is robust for ill-typed
+// inputs, which this package is not.
+//
+package satisfy
+
+// NOTES:
+//
+// We don't care about numeric conversions, so we don't descend into
+// types or constant expressions.  This is unsound because
+// constant expressions can contain arbitrary statements, e.g.
+//   const x = len([1]func(){func() {
+//     ...
+//   }})
+//
+// TODO(adonovan): make this robust against ill-typed input.
+// Or move it into the type-checker.
+//
+// Assignability conversions are possible in the following places:
+// - in assignments y = x, y := x, var y = x.
+// - from call argument types to formal parameter types
+// - in append and delete calls
+// - from return operands to result parameter types
+// - in composite literal T{k:v}, from k and v to T's field/element/key type
+// - in map[key] from key to the map's key type
+// - in comparisons x==y and switch x { case y: }.
+// - in explicit conversions T(x)
+// - in sends ch <- x, from x to the channel element type
+// - in type assertions x.(T) and switch x.(type) { case T: }
+//
+// The results of this pass provide information equivalent to the
+// ssa.MakeInterface and ssa.ChangeInterface instructions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"llvm.org/llgo/third_party/go.tools/go/types"
+	"llvm.org/llgo/third_party/go.tools/go/types/typeutil"
+)
+
+// A Constraint records the fact that the RHS type does and must
+// satisify the LHS type, which is an interface.
+// The names are suggestive of an assignment statement LHS = RHS.
+type Constraint struct {
+	LHS, RHS types.Type
+}
+
+// A Finder inspects the type-checked ASTs of Go packages and
+// accumulates the set of type constraints (x, y) such that x is
+// assignable to y, y is an interface, and both x and y have methods.
+//
+// In other words, it returns the subset of the "implements" relation
+// that is checked during compilation of a package.  Refactoring tools
+// will need to preserve at least this part of the relation to ensure
+// continued compilation.
+//
+type Finder struct {
+	Result    map[Constraint]bool
+	msetcache types.MethodSetCache
+	canon     typeutil.Map // maps types to canonical type
+
+	// per-Find state
+	info *types.Info
+	sig  *types.Signature
+}
+
+// Find inspects a single package, populating Result with its pairs of
+// constrained types.
+//
+// The package must be free of type errors, and
+// info.{Defs,Uses,Selections,Types} must have been populated by the
+// type-checker.
+//
+func (f *Finder) Find(info *types.Info, files []*ast.File) {
+	if f.Result == nil {
+		f.Result = make(map[Constraint]bool)
+	}
+
+	f.info = info
+	for _, file := range files {
+		for _, d := range file.Decls {
+			switch d := d.(type) {
+			case *ast.GenDecl:
+				if d.Tok == token.VAR { // ignore consts
+					for _, spec := range d.Specs {
+						f.valueSpec(spec.(*ast.ValueSpec))
+					}
+				}
+
+			case *ast.FuncDecl:
+				if d.Body != nil {
+					f.sig = f.info.Defs[d.Name].Type().(*types.Signature)
+					f.stmt(d.Body)
+					f.sig = nil
+				}
+			}
+		}
+	}
+	f.info = nil
+}
+
+var (
+	tInvalid     = types.Typ[types.Invalid]
+	tUntypedBool = types.Typ[types.UntypedBool]
+	tUntypedNil  = types.Typ[types.UntypedNil]
+)
+
+// exprN visits an expression in a multi-value context.
+func (f *Finder) exprN(e ast.Expr) types.Type {
+	typ := f.info.Types[e].Type.(*types.Tuple)
+	switch e := e.(type) {
+	case *ast.ParenExpr:
+		return f.exprN(e.X)
+
+	case *ast.CallExpr:
+		// x, err := f(args)
+		sig := f.expr(e.Fun).Underlying().(*types.Signature)
+		f.call(sig, e.Args)
+
+	case *ast.IndexExpr:
+		// y, ok := x[i]
+		x := f.expr(e.X)
+		f.assign(f.expr(e.Index), x.Underlying().(*types.Map).Key())
+
+	case *ast.TypeAssertExpr:
+		// y, ok := x.(T)
+		f.typeAssert(f.expr(e.X), typ.At(0).Type())
+
+	case *ast.UnaryExpr: // must be receive <-
+		// y, ok := <-x
+		f.expr(e.X)
+
+	default:
+		panic(e)
+	}
+	return typ
+}
+
+func (f *Finder) call(sig *types.Signature, args []ast.Expr) {
+	if len(args) == 0 {
+		return
+	}
+
+	// Ellipsis call?  e.g. f(x, y, z...)
+	if _, ok := args[len(args)-1].(*ast.Ellipsis); ok {
+		for i, arg := range args {
+			// The final arg is a slice, and so is the final param.
+			f.assign(sig.Params().At(i).Type(), f.expr(arg))
+		}
+		return
+	}
+
+	var argtypes []types.Type
+
+	// Gather the effective actual parameter types.
+	if tuple, ok := f.info.Types[args[0]].Type.(*types.Tuple); ok {
+		// f(g()) call where g has multiple results?
+		f.expr(args[0])
+		// unpack the tuple
+		for i := 0; i < tuple.Len(); i++ {
+			argtypes = append(argtypes, tuple.At(i).Type())
+		}
+	} else {
+		for _, arg := range args {
+			argtypes = append(argtypes, f.expr(arg))
+		}
+	}
+
+	// Assign the actuals to the formals.
+	if !sig.Variadic() {
+		for i, argtype := range argtypes {
+			f.assign(sig.Params().At(i).Type(), argtype)
+		}
+	} else {
+		// The first n-1 parameters are assigned normally.
+		nnormals := sig.Params().Len() - 1
+		for i, argtype := range argtypes[:nnormals] {
+			f.assign(sig.Params().At(i).Type(), argtype)
+		}
+		// Remaining args are assigned to elements of varargs slice.
+		tElem := sig.Params().At(nnormals).Type().(*types.Slice).Elem()
+		for i := nnormals; i < len(argtypes); i++ {
+			f.assign(tElem, argtypes[i])
+		}
+	}
+}
+
+func (f *Finder) builtin(obj *types.Builtin, sig *types.Signature, args []ast.Expr, T types.Type) types.Type {
+	switch obj.Name() {
+	case "make", "new":
+		// skip the type operand
+		for _, arg := range args[1:] {
+			f.expr(arg)
+		}
+
+	case "append":
+		s := f.expr(args[0])
+		if _, ok := args[len(args)-1].(*ast.Ellipsis); ok && len(args) == 2 {
+			// append(x, y...)   including append([]byte, "foo"...)
+			f.expr(args[1])
+		} else {
+			// append(x, y, z)
+			tElem := s.Underlying().(*types.Slice).Elem()
+			for _, arg := range args[1:] {
+				f.assign(tElem, f.expr(arg))
+			}
+		}
+
+	case "delete":
+		m := f.expr(args[0])
+		k := f.expr(args[1])
+		f.assign(m.Underlying().(*types.Map).Key(), k)
+
+	default:
+		// ordinary call
+		f.call(sig, args)
+	}
+
+	return T
+}
+
+func (f *Finder) extract(tuple types.Type, i int) types.Type {
+	if tuple, ok := tuple.(*types.Tuple); ok && i < tuple.Len() {
+		return tuple.At(i).Type()
+	}
+	return tInvalid
+}
+
+func (f *Finder) valueSpec(spec *ast.ValueSpec) {
+	var T types.Type
+	if spec.Type != nil {
+		T = f.info.Types[spec.Type].Type
+	}
+	switch len(spec.Values) {
+	case len(spec.Names): // e.g. var x, y = f(), g()
+		for _, value := range spec.Values {
+			v := f.expr(value)
+			if T != nil {
+				f.assign(T, v)
+			}
+		}
+
+	case 1: // e.g. var x, y = f()
+		tuple := f.exprN(spec.Values[0])
+		for i := range spec.Names {
+			if T != nil {
+				f.assign(T, f.extract(tuple, i))
+			}
+		}
+	}
+}
+
+// assign records pairs of distinct types that are related by
+// assignability, where the left-hand side is an interface and both
+// sides have methods.
+//
+// It should be called for all assignability checks, type assertions,
+// explicit conversions and comparisons between two types, unless the
+// types are uninteresting (e.g. lhs is a concrete type, or the empty
+// interface; rhs has no methods).
+//
+func (f *Finder) assign(lhs, rhs types.Type) {
+	if types.Identical(lhs, rhs) {
+		return
+	}
+	if !isInterface(lhs) {
+		return
+	}
+	if f.msetcache.MethodSet(lhs).Len() == 0 {
+		return
+	}
+	if f.msetcache.MethodSet(rhs).Len() == 0 {
+		return
+	}
+	// canonicalize types
+	lhsc, ok := f.canon.At(lhs).(types.Type)
+	if !ok {
+		lhsc = lhs
+		f.canon.Set(lhs, lhsc)
+	}
+	rhsc, ok := f.canon.At(rhs).(types.Type)
+	if !ok {
+		rhsc = rhs
+		f.canon.Set(rhs, rhsc)
+	}
+	// record the pair
+	f.Result[Constraint{lhsc, rhsc}] = true
+}
+
+// typeAssert must be called for each type assertion x.(T) where x has
+// interface type I.
+func (f *Finder) typeAssert(I, T types.Type) {
+	// Type assertions are slightly subtle, because they are allowed
+	// to be "impossible", e.g.
+	//
+	// 	var x interface{f()}
+	//	_ = x.(interface{f()int}) // legal
+	//
+	// (In hindsight, the language spec should probably not have
+	// allowed this, but it's too late to fix now.)
+	//
+	// This means that a type assert from I to T isn't exactly a
+	// constraint that T is assignable to I, but for a refactoring
+	// tool it is a conditional constraint that, if T is assignable
+	// to I before a refactoring, it should remain so after.
+
+	if types.AssignableTo(T, I) {
+		f.assign(I, T)
+	}
+}
+
+// compare must be called for each comparison x==y.
+func (f *Finder) compare(x, y types.Type) {
+	if types.AssignableTo(x, y) {
+		f.assign(y, x)
+	} else if types.AssignableTo(y, x) {
+		f.assign(x, y)
+	}
+}
+
+// expr visits a true expression (not a type or defining ident)
+// and returns its type.
+func (f *Finder) expr(e ast.Expr) types.Type {
+	tv := f.info.Types[e]
+	if tv.Value != nil {
+		return tv.Type // prune the descent for constants
+	}
+
+	// tv.Type may be nil for an ast.Ident.
+
+	switch e := e.(type) {
+	case *ast.BadExpr, *ast.BasicLit:
+		// no-op
+
+	case *ast.Ident:
+		// (referring idents only)
+		if obj, ok := f.info.Uses[e]; ok {
+			return obj.Type()
+		}
+		if e.Name == "_" { // e.g. "for _ = range x"
+			return tInvalid
+		}
+		panic("undefined ident: " + e.Name)
+
+	case *ast.Ellipsis:
+		if e.Elt != nil {
+			f.expr(e.Elt)
+		}
+
+	case *ast.FuncLit:
+		saved := f.sig
+		f.sig = tv.Type.(*types.Signature)
+		f.stmt(e.Body)
+		f.sig = saved
+
+	case *ast.CompositeLit:
+		switch T := deref(tv.Type).Underlying().(type) {
+		case *types.Struct:
+			for i, elem := range e.Elts {
+				if kv, ok := elem.(*ast.KeyValueExpr); ok {
+					f.assign(f.info.Uses[kv.Key.(*ast.Ident)].Type(), f.expr(kv.Value))
+				} else {
+					f.assign(T.Field(i).Type(), f.expr(elem))
+				}
+			}
+
+		case *types.Map:
+			for _, elem := range e.Elts {
+				elem := elem.(*ast.KeyValueExpr)
+				f.assign(T.Key(), f.expr(elem.Key))
+				f.assign(T.Elem(), f.expr(elem.Value))
+			}
+
+		case *types.Array, *types.Slice:
+			tElem := T.(interface {
+				Elem() types.Type
+			}).Elem()
+			for _, elem := range e.Elts {
+				if kv, ok := elem.(*ast.KeyValueExpr); ok {
+					// ignore the key
+					f.assign(tElem, f.expr(kv.Value))
+				} else {
+					f.assign(tElem, f.expr(elem))
+				}
+			}
+
+		default:
+			panic("unexpected composite literal type: " + tv.Type.String())
+		}
+
+	case *ast.ParenExpr:
+		f.expr(e.X)
+
+	case *ast.SelectorExpr:
+		if _, ok := f.info.Selections[e]; ok {
+			f.expr(e.X) // selection
+		} else {
+			return f.info.Uses[e.Sel].Type() // qualified identifier
+		}
+
+	case *ast.IndexExpr:
+		x := f.expr(e.X)
+		i := f.expr(e.Index)
+		if ux, ok := x.Underlying().(*types.Map); ok {
+			f.assign(ux.Elem(), i)
+		}
+
+	case *ast.SliceExpr:
+		f.expr(e.X)
+		if e.Low != nil {
+			f.expr(e.Low)
+		}
+		if e.High != nil {
+			f.expr(e.High)
+		}
+		if e.Max != nil {
+			f.expr(e.Max)
+		}
+
+	case *ast.TypeAssertExpr:
+		x := f.expr(e.X)
+		f.typeAssert(x, f.info.Types[e.Type].Type)
+
+	case *ast.CallExpr:
+		if tvFun := f.info.Types[e.Fun]; tvFun.IsType() {
+			// conversion
+			arg0 := f.expr(e.Args[0])
+			f.assign(tvFun.Type, arg0)
+		} else {
+			// function call
+			if id, ok := unparen(e.Fun).(*ast.Ident); ok {
+				if obj, ok := f.info.Uses[id].(*types.Builtin); ok {
+					sig := f.info.Types[id].Type.(*types.Signature)
+					return f.builtin(obj, sig, e.Args, tv.Type)
+				}
+			}
+			// ordinary call
+			f.call(f.expr(e.Fun).Underlying().(*types.Signature), e.Args)
+		}
+
+	case *ast.StarExpr:
+		f.expr(e.X)
+
+	case *ast.UnaryExpr:
+		f.expr(e.X)
+
+	case *ast.BinaryExpr:
+		x := f.expr(e.X)
+		y := f.expr(e.Y)
+		if e.Op == token.EQL || e.Op == token.NEQ {
+			f.compare(x, y)
+		}
+
+	case *ast.KeyValueExpr:
+		f.expr(e.Key)
+		f.expr(e.Value)
+
+	case *ast.ArrayType,
+		*ast.StructType,
+		*ast.FuncType,
+		*ast.InterfaceType,
+		*ast.MapType,
+		*ast.ChanType:
+		panic(e)
+	}
+
+	if tv.Type == nil {
+		panic(fmt.Sprintf("no type for %T", e))
+	}
+
+	return tv.Type
+}
+
+func (f *Finder) stmt(s ast.Stmt) {
+	switch s := s.(type) {
+	case *ast.BadStmt,
+		*ast.EmptyStmt,
+		*ast.BranchStmt:
+		// no-op
+
+	case *ast.DeclStmt:
+		d := s.Decl.(*ast.GenDecl)
+		if d.Tok == token.VAR { // ignore consts
+			for _, spec := range d.Specs {
+				f.valueSpec(spec.(*ast.ValueSpec))
+			}
+		}
+
+	case *ast.LabeledStmt:
+		f.stmt(s.Stmt)
+
+	case *ast.ExprStmt:
+		f.expr(s.X)
+
+	case *ast.SendStmt:
+		ch := f.expr(s.Chan)
+		val := f.expr(s.Value)
+		f.assign(ch.Underlying().(*types.Chan).Elem(), val)
+
+	case *ast.IncDecStmt:
+		f.expr(s.X)
+
+	case *ast.AssignStmt:
+		switch s.Tok {
+		case token.ASSIGN, token.DEFINE:
+			// y := x   or   y = x
+			var rhsTuple types.Type
+			if len(s.Lhs) != len(s.Rhs) {
+				rhsTuple = f.exprN(s.Rhs[0])
+			}
+			for i := range s.Lhs {
+				var lhs, rhs types.Type
+				if rhsTuple == nil {
+					rhs = f.expr(s.Rhs[i]) // 1:1 assignment
+				} else {
+					rhs = f.extract(rhsTuple, i) // n:1 assignment
+				}
+
+				if id, ok := s.Lhs[i].(*ast.Ident); ok {
+					if id.Name != "_" {
+						if obj, ok := f.info.Defs[id]; ok {
+							lhs = obj.Type() // definition
+						}
+					}
+				}
+				if lhs == nil {
+					lhs = f.expr(s.Lhs[i]) // assignment
+				}
+				f.assign(lhs, rhs)
+			}
+
+		default:
+			// y op= x
+			f.expr(s.Lhs[0])
+			f.expr(s.Rhs[0])
+		}
+
+	case *ast.GoStmt:
+		f.expr(s.Call)
+
+	case *ast.DeferStmt:
+		f.expr(s.Call)
+
+	case *ast.ReturnStmt:
+		formals := f.sig.Results()
+		switch len(s.Results) {
+		case formals.Len(): // 1:1
+			for i, result := range s.Results {
+				f.assign(formals.At(i).Type(), f.expr(result))
+			}
+
+		case 1: // n:1
+			tuple := f.exprN(s.Results[0])
+			for i := 0; i < formals.Len(); i++ {
+				f.assign(formals.At(i).Type(), f.extract(tuple, i))
+			}
+		}
+
+	case *ast.SelectStmt:
+		f.stmt(s.Body)
+
+	case *ast.BlockStmt:
+		for _, s := range s.List {
+			f.stmt(s)
+		}
+
+	case *ast.IfStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		f.expr(s.Cond)
+		f.stmt(s.Body)
+		if s.Else != nil {
+			f.stmt(s.Else)
+		}
+
+	case *ast.SwitchStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		var tag types.Type = tUntypedBool
+		if s.Tag != nil {
+			tag = f.expr(s.Tag)
+		}
+		for _, cc := range s.Body.List {
+			cc := cc.(*ast.CaseClause)
+			for _, cond := range cc.List {
+				f.compare(tag, f.info.Types[cond].Type)
+			}
+			for _, s := range cc.Body {
+				f.stmt(s)
+			}
+		}
+
+	case *ast.TypeSwitchStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		var I types.Type
+		switch ass := s.Assign.(type) {
+		case *ast.ExprStmt: // x.(type)
+			I = f.expr(unparen(ass.X).(*ast.TypeAssertExpr).X)
+		case *ast.AssignStmt: // y := x.(type)
+			I = f.expr(unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)
+		}
+		for _, cc := range s.Body.List {
+			cc := cc.(*ast.CaseClause)
+			for _, cond := range cc.List {
+				tCase := f.info.Types[cond].Type
+				if tCase != tUntypedNil {
+					f.typeAssert(I, tCase)
+				}
+			}
+			for _, s := range cc.Body {
+				f.stmt(s)
+			}
+		}
+
+	case *ast.CommClause:
+		if s.Comm != nil {
+			f.stmt(s.Comm)
+		}
+		for _, s := range s.Body {
+			f.stmt(s)
+		}
+
+	case *ast.ForStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		if s.Cond != nil {
+			f.expr(s.Cond)
+		}
+		if s.Post != nil {
+			f.stmt(s.Post)
+		}
+		f.stmt(s.Body)
+
+	case *ast.RangeStmt:
+		x := f.expr(s.X)
+		// No conversions are involved when Tok==DEFINE.
+		if s.Tok == token.ASSIGN {
+			if s.Key != nil {
+				k := f.expr(s.Key)
+				var xelem types.Type
+				// keys of array, *array, slice, string aren't interesting
+				switch ux := x.Underlying().(type) {
+				case *types.Chan:
+					xelem = ux.Elem()
+				case *types.Map:
+					xelem = ux.Key()
+				}
+				if xelem != nil {
+					f.assign(xelem, k)
+				}
+			}
+			if s.Value != nil {
+				val := f.expr(s.Value)
+				var xelem types.Type
+				// values of strings aren't interesting
+				switch ux := x.Underlying().(type) {
+				case *types.Array:
+					xelem = ux.Elem()
+				case *types.Chan:
+					xelem = ux.Elem()
+				case *types.Map:
+					xelem = ux.Elem()
+				case *types.Pointer: // *array
+					xelem = deref(ux).(*types.Array).Elem()
+				case *types.Slice:
+					xelem = ux.Elem()
+				}
+				if xelem != nil {
+					f.assign(xelem, val)
+				}
+			}
+		}
+		f.stmt(s.Body)
+
+	default:
+		panic(s)
+	}
+}
+
+// -- Plundered from golang.org/x/tools/go/ssa -----------------
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// unparen returns e with any enclosing parentheses stripped.
+func unparen(e ast.Expr) ast.Expr {
+	for {
+		p, ok := e.(*ast.ParenExpr)
+		if !ok {
+			break
+		}
+		e = p.X
+	}
+	return e
+}
+
+func isInterface(T types.Type) bool {
+	_, ok := T.Underlying().(*types.Interface)
+	return ok
+}
diff --git a/third_party/gofrontend/LICENSE b/third_party/gofrontend/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/third_party/gofrontend/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/gofrontend/config-ml.in b/third_party/gofrontend/config-ml.in
new file mode 100644
index 0000000..927bad6
--- /dev/null
+++ b/third_party/gofrontend/config-ml.in
@@ -0,0 +1,885 @@
+# Configure fragment invoked in the post-target section for subdirs
+# wanting multilib support.
+#
+# Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2010, 2011, 2014 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+#
+# Please report bugs to <gcc-bugs@gnu.org>
+# and send patches to <gcc-patches@gnu.org>.
+
+# It is advisable to support a few --enable/--disable options to let the
+# user select which libraries s/he really wants.
+#
+# Subdirectories wishing to use multilib should put the following lines
+# in the "post-target" section of configure.in.
+#
+# if [ "${srcdir}" = "." ] ; then
+#   if [ "${with_target_subdir}" != "." ] ; then
+#     . ${with_multisrctop}../../config-ml.in
+#   else
+#     . ${with_multisrctop}../config-ml.in
+#   fi
+# else
+#   . ${srcdir}/../config-ml.in
+# fi
+#
+#
+# Things are complicated because 6 separate cases must be handled:
+# 2 (native, cross) x 3 (absolute-path, relative-not-dot, dot) = 6.
+#
+# srcdir=. is special.  It must handle make programs that don't handle VPATH.
+# To implement this, a symlink tree is built for each library and for each
+# multilib subdir.
+#
+# The build tree is layed out as
+#
+# ./
+#   newlib
+#   m68020/
+#          newlib
+#          m68881/
+#                 newlib
+#
+# The nice feature about this arrangement is that inter-library references
+# in the build tree work without having to care where you are.  Note that
+# inter-library references also work in the source tree because symlink trees
+# are built when srcdir=.
+#
+# Unfortunately, trying to access the libraries in the build tree requires
+# the user to manually choose which library to use as GCC won't be able to
+# find the right one.  This is viewed as the lesser of two evils.
+#
+# Configure variables:
+# ${with_target_subdir} = "." for native, or ${target_alias} for cross.
+# Set by top level Makefile.
+# ${with_multisrctop} = how many levels of multilibs there are in the source
+# tree.  It exists to handle the case of configuring in the source tree:
+# ${srcdir} is not constant.
+# ${with_multisubdir} = name of multilib subdirectory (eg: m68020/m68881).
+#
+# Makefile variables:
+# MULTISRCTOP = number of multilib levels in source tree (+1 if cross)
+# (FIXME: note that this is different than ${with_multisrctop}.  Check out.).
+# MULTIBUILDTOP = number of multilib levels in build tree
+# MULTIDIRS = list of multilib subdirs (eg: m68000 m68020 ...)
+# (only defined in each library's main Makefile).
+# MULTISUBDIR = installed subdirectory name with leading '/' (eg: /m68000)
+# (only defined in each multilib subdir).
+
+# FIXME: Multilib is currently disabled by default for everything other than
+# newlib.  It is up to each target to turn on multilib support for the other
+# libraries as desired.
+
+# Autoconf incoming variables:
+# srcdir, host, ac_configure_args
+#
+# We *could* figure srcdir and host out, but we'd have to do work that
+# our caller has already done to figure them out and requiring these two
+# seems reasonable.
+# Note that `host' in this case is GCC's `target'.  Target libraries are
+# configured for a particular host.
+
+Makefile=${ac_file-Makefile}
+ml_config_shell=${CONFIG_SHELL-/bin/sh}
+ml_realsrcdir=${srcdir}
+
+# Scan all the arguments and set all the ones we need.
+
+scan_arguments ()
+{
+  ml_verbose=--verbose
+  for option
+  do
+    # Strip single quotes surrounding individual options, that is, remove one
+    # level of shell quoting for these.
+    case $option in
+      \'*\') eval option=$option ;;
+    esac
+
+    case $option in
+      --*) ;;
+      -*) option=-$option ;;
+    esac
+
+    case $option in
+      --*=*)
+	optarg=`echo $option | sed -e 's/^[^=]*=//'`
+	;;
+    esac
+
+    case $option in
+      --disable-*)
+	enableopt=`echo ${option} | sed 's:^--disable-:enable_:;s:-:_:g'`
+	eval $enableopt=no
+	;;
+      --enable-*)
+	case "$option" in
+	*=*)	;;
+	*)	optarg=yes ;;
+	esac
+	enableopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'`
+	# enable_shared and enable_static are handled by configure.
+	# Don't undo its work.
+	case $enableopt in
+	enable_shared | enable_static) ;;
+	*) eval $enableopt='$optarg' ;;
+	esac
+	;;
+      --norecursion | --no-recursion)
+	ml_norecursion=yes
+	;;
+      --silent | --sil* | --quiet | --q*)
+	ml_verbose=--silent
+	;;
+      --verbose | --v | --verb*)
+	ml_verbose=--verbose
+	;;
+      --with-*)
+	case "$option" in
+	*=*)	;;
+	*)	optarg=yes ;;
+	esac
+	withopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'`
+	eval $withopt='$optarg'
+	;;
+      --without-*)
+	withopt=`echo ${option} | sed 's:^--::;s:out::;s:-:_:g'`
+	eval $withopt=no
+	;;
+    esac
+  done
+}
+# Use eval to properly handle configure arguments such as
+# --enable-foo='--enable-a=1 --enable-b=2 --enable-c=3'.
+eval scan_arguments "${ac_configure_args}"
+unset scan_arguments
+
+# Only do this if --enable-multilib.
+if [ "${enable_multilib}" = yes ]; then
+
+# Compute whether this is the library's top level directory
+# (ie: not a multilib subdirectory, and not a subdirectory like newlib/src).
+# ${with_multisubdir} tells us we're in the right branch, but we could be
+# in a subdir of that.
+# ??? The previous version could void this test by separating the process into
+# two files: one that only the library's toplevel configure.in ran (to
+# configure the multilib subdirs), and another that all configure.in's ran to
+# update the Makefile.  It seemed reasonable to collapse all multilib support
+# into one file, but it does leave us with having to perform this test.
+ml_toplevel_p=no
+if [ -z "${with_multisubdir}" ]; then
+  if [ "${srcdir}" = "." ]; then
+    # Use ${ml_realsrcdir} instead of ${srcdir} here to account for ${subdir}.
+    # ${with_target_subdir} = "." for native, otherwise target alias.
+    if [ "${with_target_subdir}" = "." ]; then
+      if [ -f ${ml_realsrcdir}/../config-ml.in ]; then
+	ml_toplevel_p=yes
+      fi
+    else
+      if [ -f ${ml_realsrcdir}/../../config-ml.in ]; then
+	ml_toplevel_p=yes
+      fi
+    fi
+  else
+    # Use ${ml_realsrcdir} instead of ${srcdir} here to account for ${subdir}.
+    if [ -f ${ml_realsrcdir}/../config-ml.in ]; then
+      ml_toplevel_p=yes
+    fi
+  fi
+fi
+
+# If this is the library's top level directory, set multidirs to the
+# multilib subdirs to support.  This lives at the top because we need
+# `multidirs' set right away.
+
+if [ "${ml_toplevel_p}" = yes ]; then
+
+multidirs=
+for i in `${CC-gcc} --print-multi-lib 2>/dev/null`; do
+  dir=`echo $i | sed -e 's/;.*$//'`
+  if [ "${dir}" = "." ]; then
+    true
+  else
+    if [ -z "${multidirs}" ]; then
+      multidirs="${dir}"
+    else
+      multidirs="${multidirs} ${dir}"
+    fi
+  fi
+done
+
+# Target libraries are configured for the host they run on, so we check
+# $host here, not $target.
+
+case "${host}" in
+arm-*-*)
+	if [ x"$enable_fpu" = xno ]
+	then
+	  old_multidirs=${multidirs}
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "${x}" in
+	      *fpu*) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x"$enable_26bit" = xno ]
+	then
+	  old_multidirs=${multidirs}
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "${x}" in
+	      *26bit*) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x"$enable_underscore" = xno ]
+	then
+	  old_multidirs=${multidirs}
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "${x}" in
+	      *under*) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x"$enable_interwork" = xno ]
+	then
+	  old_multidirs=${multidirs}
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "${x}" in
+	      *interwork*) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_biendian = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *le* ) : ;;
+	      *be* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x"$enable_nofmult" = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *nofmult* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	;;
+m68*-*-*)
+	if [ x$enable_softfloat = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *soft-float* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_m68881 = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *m68881* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_m68000 = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *m68000* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_m68020 = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *m68020* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	;;
+mips*-*-*)
+	if [ x$enable_single_float = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *single* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_biendian = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *el* ) : ;;
+	      *eb* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_softfloat = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *soft-float* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	;;
+powerpc*-*-* | rs6000*-*-*)
+	if [ x$enable_aix64 = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *ppc64* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_pthread = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *pthread* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_softfloat = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *soft-float* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_powercpu = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      power | */power | */power/* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_powerpccpu = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *powerpc* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_powerpcos = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *mcall-linux* | *mcall-solaris* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_biendian = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *mlittle* | *mbig* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_sysv = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *mcall-sysv* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	;;
+esac
+
+# Remove extraneous blanks from multidirs.
+# Tests like `if [ -n "$multidirs" ]' require it.
+multidirs=`echo "$multidirs" | sed -e 's/^[ ][ ]*//' -e 's/[ ][ ]*$//' -e 's/[ ][ ]*/ /g'`
+
+# Add code to library's top level makefile to handle building the multilib
+# subdirs.
+
+cat > Multi.tem <<\EOF
+
+PWD_COMMAND=$${PWDCMD-pwd}
+
+# FIXME: There should be an @-sign in front of the `if'.
+# Leave out until this is tested a bit more.
+multi-do:
+	if [ -z "$(MULTIDIRS)" ]; then \
+	  true; \
+	else \
+	  rootpre=`${PWD_COMMAND}`/; export rootpre; \
+	  srcrootpre=`cd $(srcdir); ${PWD_COMMAND}`/; export srcrootpre; \
+	  lib=`echo "$${rootpre}" | sed -e 's,^.*/\([^/][^/]*\)/$$,\1,'`; \
+	  compiler="$(CC)"; \
+	  for i in `$${compiler} --print-multi-lib 2>/dev/null`; do \
+	    dir=`echo $$i | sed -e 's/;.*$$//'`; \
+	    if [ "$${dir}" = "." ]; then \
+	      true; \
+	    else \
+	      if [ -d ../$${dir}/$${lib} ]; then \
+		flags=`echo $$i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; \
+		if (cd ../$${dir}/$${lib}; $(MAKE) $(FLAGS_TO_PASS) \
+				CFLAGS="$(CFLAGS) $${flags}" \
+				CCASFLAGS="$(CCASFLAGS) $${flags}" \
+				FCFLAGS="$(FCFLAGS) $${flags}" \
+				FFLAGS="$(FFLAGS) $${flags}" \
+				ADAFLAGS="$(ADAFLAGS) $${flags}" \
+				prefix="$(prefix)" \
+				exec_prefix="$(exec_prefix)" \
+				GCJFLAGS="$(GCJFLAGS) $${flags}" \
+				GOCFLAGS="$(GOCFLAGS) $${flags}" \
+				CXXFLAGS="$(CXXFLAGS) $${flags}" \
+				LIBCFLAGS="$(LIBCFLAGS) $${flags}" \
+				LIBCXXFLAGS="$(LIBCXXFLAGS) $${flags}" \
+				LDFLAGS="$(LDFLAGS) $${flags}" \
+				MULTIFLAGS="$${flags}" \
+				DESTDIR="$(DESTDIR)" \
+				INSTALL="$(INSTALL)" \
+				INSTALL_DATA="$(INSTALL_DATA)" \
+				INSTALL_PROGRAM="$(INSTALL_PROGRAM)" \
+				INSTALL_SCRIPT="$(INSTALL_SCRIPT)" \
+				$(DO)); then \
+		  true; \
+		else \
+		  exit 1; \
+		fi; \
+	      else true; \
+	      fi; \
+	    fi; \
+	  done; \
+	fi
+
+# FIXME: There should be an @-sign in front of the `if'.
+# Leave out until this is tested a bit more.
+multi-clean:
+	if [ -z "$(MULTIDIRS)" ]; then \
+	  true; \
+	else \
+	  lib=`${PWD_COMMAND} | sed -e 's,^.*/\([^/][^/]*\)$$,\1,'`; \
+	  for dir in : $(MULTIDIRS); do \
+	    test $$dir != : || continue; \
+EOF
+cat >>Multi.tem <<EOF
+	    if [ -f ../\$\${dir}/\$\${lib}/${Makefile} ]; then \\
+EOF
+cat >>Multi.tem <<\EOF
+	      if (cd ../$${dir}/$${lib}; $(MAKE) $(FLAGS_TO_PASS) $(DO)); \
+	      then true; \
+	      else exit 1; \
+	      fi; \
+	    else true; \
+	    fi; \
+	  done; \
+	fi
+EOF
+
+cat ${Makefile} Multi.tem > Makefile.tem
+rm -f ${Makefile} Multi.tem
+mv Makefile.tem ${Makefile}
+
+fi # ${ml_toplevel_p} = yes
+
+if [ "${ml_verbose}" = --verbose ]; then
+  echo "Adding multilib support to ${Makefile} in ${ml_realsrcdir}"
+  if [ "${ml_toplevel_p}" = yes ]; then
+    echo "multidirs=${multidirs}"
+  fi
+  echo "with_multisubdir=${with_multisubdir}"
+fi
+
+if [ "${srcdir}" = "." ]; then
+  if [ "${with_target_subdir}" != "." ]; then
+    ml_srcdotdot="../"
+  else
+    ml_srcdotdot=""
+  fi
+else
+  ml_srcdotdot=""
+fi
+
+if [ -z "${with_multisubdir}" ]; then
+  ml_subdir=
+  ml_builddotdot=
+  : # ml_srcdotdot= # already set
+else
+  ml_subdir="/${with_multisubdir}"
+  # The '[^/][^/]*' appears that way to work around a SunOS sed bug.
+  ml_builddotdot=`echo ${with_multisubdir} | sed -e 's:[^/][^/]*:..:g'`/
+  if [ "$srcdir" = "." ]; then
+    ml_srcdotdot=${ml_srcdotdot}${ml_builddotdot}
+  else
+    : # ml_srcdotdot= # already set
+  fi
+fi
+
+if [ "${ml_toplevel_p}" = yes ]; then
+  ml_do='$(MAKE)'
+  ml_clean='$(MAKE)'
+else
+  ml_do=true
+  ml_clean=true
+fi
+
+# TOP is used by newlib and should not be used elsewhere for this purpose.
+# MULTI{SRC,BUILD}TOP are the proper ones to use.  MULTISRCTOP is empty
+# when srcdir != builddir.  MULTIBUILDTOP is always some number of ../'s.
+# FIXME: newlib needs to be updated to use MULTI{SRC,BUILD}TOP so we can
+# delete TOP.  Newlib may wish to continue to use TOP for its own purposes
+# of course.
+# MULTIDIRS is non-empty for the cpu top level Makefile (eg: newlib/Makefile)
+# and lists the subdirectories to recurse into.
+# MULTISUBDIR is non-empty in each cpu subdirectory's Makefile
+# (eg: newlib/h8300h/Makefile) and is the installed subdirectory name with
+# a leading '/'.
+# MULTIDO is used for targets like all, install, and check where
+# $(FLAGS_TO_PASS) augmented with the subdir's compiler option is needed.
+# MULTICLEAN is used for the *clean targets.
+#
+# ??? It is possible to merge MULTIDO and MULTICLEAN into one.  They are
+# currently kept separate because we don't want the *clean targets to require
+# the existence of the compiler (which MULTIDO currently requires) and
+# therefore we'd have to record the directory options as well as names
+# (currently we just record the names and use --print-multi-lib to get the
+# options).
+
+sed -e "s:^TOP[ 	]*=[ 	]*\([./]*\)[ 	]*$:TOP = ${ml_builddotdot}\1:" \
+    -e "s:^MULTISRCTOP[ 	]*=.*$:MULTISRCTOP = ${ml_srcdotdot}:" \
+    -e "s:^MULTIBUILDTOP[ 	]*=.*$:MULTIBUILDTOP = ${ml_builddotdot}:" \
+    -e "s:^MULTIDIRS[ 	]*=.*$:MULTIDIRS = ${multidirs}:" \
+    -e "s:^MULTISUBDIR[ 	]*=.*$:MULTISUBDIR = ${ml_subdir}:" \
+    -e "s:^MULTIDO[ 	]*=.*$:MULTIDO = $ml_do:" \
+    -e "s:^MULTICLEAN[ 	]*=.*$:MULTICLEAN = $ml_clean:" \
+	${Makefile} > Makefile.tem
+rm -f ${Makefile}
+mv Makefile.tem ${Makefile}
+
+# If this is the library's top level, configure each multilib subdir.
+# This is done at the end because this is the loop that runs configure
+# in each multilib subdir and it seemed reasonable to finish updating the
+# Makefile before going on to configure the subdirs.
+
+if [ "${ml_toplevel_p}" = yes ]; then
+
+# We must freshly configure each subdirectory.  This bit of code is
+# actually partially stolen from the main configure script.  FIXME.
+
+if [ -n "${multidirs}" ] && [ -z "${ml_norecursion}" ]; then
+
+  if [ "${ml_verbose}" = --verbose ]; then
+    echo "Running configure in multilib subdirs ${multidirs}"
+    echo "pwd: `${PWDCMD-pwd}`"
+  fi
+
+  ml_origdir=`${PWDCMD-pwd}`
+  ml_libdir=`echo "$ml_origdir" | sed -e 's,^.*/,,'`
+  # cd to top-level-build-dir/${with_target_subdir}
+  cd ..
+
+  for ml_dir in ${multidirs}; do
+
+    if [ "${ml_verbose}" = --verbose ]; then
+      echo "Running configure in multilib subdir ${ml_dir}"
+      echo "pwd: `${PWDCMD-pwd}`"
+    fi
+
+    if [ -d ${ml_dir} ]; then true; else
+      # ``mkdir -p ${ml_dir}'' See also mkinstalldirs.
+      pathcomp=""
+      for d in `echo ":${ml_dir}" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`; do
+        pathcomp="$pathcomp$d"
+        case "$pathcomp" in
+          -* ) pathcomp=./$pathcomp ;;
+        esac
+        if test ! -d "$pathcomp"; then
+           echo "mkdir $pathcomp" 1>&2
+           mkdir "$pathcomp" > /dev/null 2>&1 || lasterr=$?
+        fi
+        if test ! -d "$pathcomp"; then
+	   exit $lasterr
+        fi
+        pathcomp="$pathcomp/"
+      done
+    fi
+    if [ -d ${ml_dir}/${ml_libdir} ]; then true; else mkdir ${ml_dir}/${ml_libdir}; fi
+
+    # Eg: if ${ml_dir} = m68000/m68881, dotdot = ../../
+    dotdot=../`echo ${ml_dir} | sed -e 's|[^/]||g' -e 's|/|../|g'`
+
+    case ${srcdir} in
+    ".")
+      echo "Building symlink tree in `${PWDCMD-pwd}`/${ml_dir}/${ml_libdir}"
+      if [ "${with_target_subdir}" != "." ]; then
+	ml_unsubdir="../"
+      else
+	ml_unsubdir=""
+      fi
+      (cd ${ml_dir}/${ml_libdir};
+       ../${dotdot}${ml_unsubdir}symlink-tree ../${dotdot}${ml_unsubdir}${ml_libdir} "")
+      if [ -f ${ml_dir}/${ml_libdir}/${Makefile} ]; then
+	if [ x"${MAKE}" = x ]; then
+	  (cd ${ml_dir}/${ml_libdir}; make distclean)
+	else
+	  (cd ${ml_dir}/${ml_libdir}; ${MAKE} distclean)
+	fi
+      fi
+      ml_newsrcdir="."
+      ml_srcdiroption=
+      multisrctop=${dotdot}
+      ;;
+    *)
+      case "${srcdir}" in
+      /* | [A-Za-z]:[\\/]* ) # absolute path
+        ml_newsrcdir=${srcdir}
+        ;;
+      *) # otherwise relative
+        ml_newsrcdir=${dotdot}${srcdir}
+        ;;
+      esac
+      ml_srcdiroption="-srcdir=${ml_newsrcdir}"
+      multisrctop=
+      ;;
+    esac
+
+    case "${progname}" in
+    /* | [A-Za-z]:[\\/]* )     ml_recprog=${progname} ;;
+    *)      ml_recprog=${dotdot}${progname} ;;
+    esac
+
+    # FIXME: POPDIR=${PWD=`pwd`} doesn't work here.
+    ML_POPDIR=`${PWDCMD-pwd}`
+    cd ${ml_dir}/${ml_libdir}
+
+    if [ -f ${ml_newsrcdir}/configure ]; then
+      ml_recprog="${ml_newsrcdir}/configure"
+    fi
+
+    # find compiler flag corresponding to ${ml_dir}
+    for i in `${CC-gcc} --print-multi-lib 2>/dev/null`; do
+      dir=`echo $i | sed -e 's/;.*$//'`
+      if [ "${dir}" = "${ml_dir}" ]; then
+        flags=`echo $i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`
+        break
+      fi
+    done
+    ml_config_env='CC="${CC_}$flags" CXX="${CXX_}$flags" F77="${F77_}$flags" GCJ="${GCJ_}$flags" GFORTRAN="${GFORTRAN_}$flags" GOC="${GOC_}$flags"'
+
+    if [ "${with_target_subdir}" = "." ]; then
+	CC_=$CC' '
+	CXX_=$CXX' '
+	F77_=$F77' '
+	GCJ_=$GCJ' '
+	GFORTRAN_=$GFORTRAN' '
+	GOC_=$GOC' '
+    else
+	# Create a regular expression that matches any string as long
+	# as ML_POPDIR.
+	popdir_rx=`echo "${ML_POPDIR}" | sed 's,.,.,g'`
+	CC_=
+	for arg in ${CC}; do
+	  case $arg in
+	  -[BIL]"${ML_POPDIR}"/*)
+	    CC_="${CC_}"`echo "X${arg}" | sed -n "s/X\\(-[BIL]${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X-[BIL]${popdir_rx}\\(.*\\)/\1/p"`' ' ;;
+	  "${ML_POPDIR}"/*)
+	    CC_="${CC_}"`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  *)
+	    CC_="${CC_}${arg} " ;;
+	  esac
+	done
+
+	CXX_=
+	for arg in ${CXX}; do
+	  case $arg in
+	  -[BIL]"${ML_POPDIR}"/*)
+	    CXX_="${CXX_}"`echo "X${arg}" | sed -n "s/X\\(-[BIL]${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X-[BIL]${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  "${ML_POPDIR}"/*)
+	    CXX_="${CXX_}"`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  *)
+	    CXX_="${CXX_}${arg} " ;;
+	  esac
+	done
+
+	F77_=
+	for arg in ${F77}; do
+	  case $arg in
+	  -[BIL]"${ML_POPDIR}"/*)
+	    F77_="${F77_}"`echo "X${arg}" | sed -n "s/X\\(-[BIL]${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X-[BIL]${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  "${ML_POPDIR}"/*)
+	    F77_="${F77_}"`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  *)
+	    F77_="${F77_}${arg} " ;;
+	  esac
+	done
+
+	GCJ_=
+	for arg in ${GCJ}; do
+	  case $arg in
+	  -[BIL]"${ML_POPDIR}"/*)
+	    GCJ_="${GCJ_}"`echo "X${arg}" | sed -n "s/X\\(-[BIL]${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X-[BIL]${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  "${ML_POPDIR}"/*)
+	    GCJ_="${GCJ_}"`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  *)
+	    GCJ_="${GCJ_}${arg} " ;;
+	  esac
+	done
+
+	GFORTRAN_=
+	for arg in ${GFORTRAN}; do
+	  case $arg in
+	  -[BIL]"${ML_POPDIR}"/*)
+	    GFORTRAN_="${GFORTRAN_}"`echo "X${arg}" | sed -n "s/X\\(-[BIL]${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X-[BIL]${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  "${ML_POPDIR}"/*)
+	    GFORTRAN_="${GFORTRAN_}"`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  *)
+	    GFORTRAN_="${GFORTRAN_}${arg} " ;;
+	  esac
+	done
+
+	GOC_=
+	for arg in ${GOC}; do
+	  case $arg in
+	  -[BIL]"${ML_POPDIR}"/*)
+	    GOC_="${GOC_}"`echo "X${arg}" | sed -n "s/X\\(-[BIL]${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X-[BIL]${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  "${ML_POPDIR}"/*)
+	    GOC_="${GOC_}"`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  *)
+	    GOC_="${GOC_}${arg} " ;;
+	  esac
+	done
+
+	if test "x${LD_LIBRARY_PATH+set}" = xset; then
+	  LD_LIBRARY_PATH_=
+	  for arg in `echo "$LD_LIBRARY_PATH" | tr ':' ' '`; do
+	    case "$arg" in
+	    "${ML_POPDIR}"/*)
+	      arg=`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`
+	      ;;
+	    esac
+	    if test "x$LD_LIBRARY_PATH_" != x; then
+	      LD_LIBRARY_PATH_=$LD_LIBRARY_PATH_:$arg
+	    else
+	      LD_LIBRARY_PATH_=$arg
+	    fi
+          done
+	  ml_config_env="$ml_config_env LD_LIBRARY_PATH=$LD_LIBRARY_PATH_"
+	fi
+
+	if test "x${SHLIB_PATH+set}" = xset; then
+	  SHLIB_PATH_=
+	  for arg in `echo "$SHLIB_PATH" | tr ':' ' '`; do
+	    case "$arg" in
+	    "${ML_POPDIR}"/*)
+	      arg=`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`
+	      ;;
+	    esac
+	    if test "x$SHLIB_PATH_" != x; then
+	      SHLIB_PATH_=$SHLIB_PATH_:$arg
+	    else
+	      SHLIB_PATH_=$arg
+	    fi
+          done
+	  ml_config_env="$ml_config_env SHLIB_PATH=$SHLIB_PATH_"
+	fi
+    fi
+
+    if eval ${ml_config_env} ${ml_config_shell} ${ml_recprog} \
+	--with-multisubdir=${ml_dir} --with-multisrctop=${multisrctop} \
+	"${ac_configure_args}" ${ml_config_env} ${ml_srcdiroption} ; then
+      true
+    else
+      exit 1
+    fi
+
+    cd "${ML_POPDIR}"
+
+  done
+
+  cd "${ml_origdir}"
+fi
+
+fi # ${ml_toplevel_p} = yes
+fi # ${enable_multilib} = yes
diff --git a/third_party/gofrontend/config.guess b/third_party/gofrontend/config.guess
new file mode 100755
index 0000000..73d671b
--- /dev/null
+++ b/third_party/gofrontend/config.guess
@@ -0,0 +1,1526 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011 Free Software Foundation, Inc.
+
+timestamp='2011-08-20'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner.  Please send patches (context
+# diff format) to <config-patches@gnu.org> and include a ChangeLog
+# entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
+Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+		os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+	echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval $set_cc_for_build
+	SUN_ARCH="i386"
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH="x86_64"
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[4567])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+			esac ;;
+		    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^		//' << EOF >$dummy.c
+
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
+
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
+
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+	exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+	exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+	exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+	exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    5000:UNIX_System_V:4.*:*)
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:windows32*:*)
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    8664:Windows_NT:*)
+	echo x86_64-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    aarch64*:Linux:*)
+	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+	    fi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-gnu
+	exit ;;
+    frv:Linux:*:*)
+	echo frv-unknown-linux-gnu
+	exit ;;
+    i*86:Linux:*:*)
+	LIBC=gnu
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+	echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo or32-unknown-linux-gnu
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-gnu
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-gnu
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-gnu
+	exit ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit ;;
+    xtensa*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+	# Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configury will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel@ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+		echo mips-nec-sysv${UNAME_RELEASE}
+	else
+		echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+	exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    i386)
+		eval $set_cc_for_build
+		if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		  if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		      (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		      grep IS_64BIT_ARCH >/dev/null
+		  then
+		      UNAME_PROCESSOR="x86_64"
+		  fi
+		fi ;;
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+	echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+	"4"
+#else
+	""
+#endif
+	); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/third_party/gofrontend/config.sub b/third_party/gofrontend/config.sub
new file mode 100755
index 0000000..673d62b
--- /dev/null
+++ b/third_party/gofrontend/config.sub
@@ -0,0 +1,1768 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011 Free Software Foundation, Inc.
+
+timestamp='2011-11-02'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted GNU ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
+Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray | -microblaze)
+		os=
+		basic_machine=$1
+		;;
+	-bluegene*)
+		os=-cnk
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+	-chorusrdb)
+		os=-chorusrdb
+		basic_machine=$1
+		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+   | aarch64 | aarch64_be \
+   | be32 | be64 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fido | fr30 | frv \
+	| hexagon \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| le32 | le64 \
+	| lm32 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| moxie \
+	| mt \
+	| msp430 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| open8 \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pyramid \
+	| rx \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| we32k \
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | picochip)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+   | aarch64-* | aarch64_be-* \
+	| avr-* | avr32-* \
+	| be32-* | be64-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hexagon-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| le32-* | le64-* \
+	| lm32-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pyramid-* \
+	| romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| tahoe-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
+	| tron-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16 | cr16-*)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	microblaze)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc | ppcbe)	basic_machine=powerpc-unknown
+		;;
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+	# First match some system type aliases
+	# that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* | -aros* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-nacl*)
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	score-*)
+		os=-elf
+		;;
+	spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-cnk*|-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/third_party/gofrontend/depcomp b/third_party/gofrontend/depcomp
new file mode 100644
index 0000000..df8eea7
--- /dev/null
+++ b/third_party/gofrontend/depcomp
@@ -0,0 +1,630 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
+# Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by `PROGRAMS ARGS'.
+  object      Object file output by `PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputing dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+   # This is just like msvisualcpp but w/o cygpath translation.
+   # Just convert the backslash-escaped backslashes to single forward
+   # slashes to satisfy depend.m4
+   cygpath_u="sed s,\\\\\\\\,/,g"
+   depmode=msvisualcpp
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> "$depfile"
+    echo >> "$depfile"
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$base.u
+    tmpdepfile3=$dir.libs/$base.u
+    "$@" -Wc,-M
+  else
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$dir$base.u
+    tmpdepfile3=$dir$base.u
+    "$@" -M
+  fi
+  stat=$?
+
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+    # That's a tab and a space in the [].
+    sed -e 's,^.*\.[a-z]*:[	 ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+icc)
+  # Intel's C compiler understands `-MD -MF file'.  However on
+  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # ICC 7.0 will fill foo.d with something like
+  #    foo.o: sub/foo.c
+  #    foo.o: sub/foo.h
+  # which is wrong.  We want:
+  #    sub/foo.o: sub/foo.c
+  #    sub/foo.o: sub/foo.h
+  #    sub/foo.c:
+  #    sub/foo.h:
+  # ICC 7.1 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using \ :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+    sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add `dependent.h:' lines.
+    sed -ne '2,${
+	       s/^ *//
+	       s/ \\*$//
+	       s/$/:/
+	       p
+	     }' "$tmpdepfile" >> "$depfile"
+  else
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+   # The Tru64 compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+   test "x$dir" = "x$object" && dir=
+   base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+   if test "$libtool" = yes; then
+      # With Tru64 cc, shared objects can also be used to make a
+      # static library.  This mechanism is used in libtool 1.4 series to
+      # handle both shared and static libraries in a single compilation.
+      # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+      #
+      # With libtool 1.5 this exception was removed, and libtool now
+      # generates 2 separate objects for the 2 libraries.  These two
+      # compilations output dependencies in $dir.libs/$base.o.d and
+      # in $dir$base.o.d.  We have to check for both files, because
+      # one of the two compilations can be disabled.  We should prefer
+      # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+      # automatically cleaned when .libs/ is deleted, while ignoring
+      # the former would cause a distcleancheck panic.
+      tmpdepfile1=$dir.libs/$base.lo.d   # libtool 1.4
+      tmpdepfile2=$dir$base.o.d          # libtool 1.5
+      tmpdepfile3=$dir.libs/$base.o.d    # libtool 1.5
+      tmpdepfile4=$dir.libs/$base.d      # Compaq CCC V6.2-504
+      "$@" -Wc,-MD
+   else
+      tmpdepfile1=$dir$base.o.d
+      tmpdepfile2=$dir$base.d
+      tmpdepfile3=$dir$base.d
+      tmpdepfile4=$dir$base.d
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+      exit $stat
+   fi
+
+   for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+   do
+     test -f "$tmpdepfile" && break
+   done
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a tab and a space in the [].
+      sed -e 's,^.*\.[a-z]*:[	 ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for `:'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  "$@" $dashmflag |
+    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no eat=no
+  for arg
+  do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    if test $eat = yes; then
+      eat=no
+      continue
+    fi
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -arch)
+      eat=yes ;;
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix=`echo "$object" | sed 's/^.*\././'`
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E |
+    sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+       -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+	set fnord "$@"
+	shift
+	shift
+	;;
+    *)
+	set fnord "$@" "$arg"
+	shift
+	shift
+	;;
+    esac
+  done
+  "$@" -E 2>/dev/null |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::	\1 \\:p' >> "$depfile"
+  echo "	" >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvcmsys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/third_party/gofrontend/include/dwarf2.def b/third_party/gofrontend/include/dwarf2.def
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/gofrontend/include/dwarf2.def
diff --git a/third_party/gofrontend/include/dwarf2.h b/third_party/gofrontend/include/dwarf2.h
new file mode 100644
index 0000000..9288226
--- /dev/null
+++ b/third_party/gofrontend/include/dwarf2.h
@@ -0,0 +1,94 @@
+//===----------------------------- dwarf2.h -------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+// DWARF constants. Derived from:
+//   - libcxxabi/src/Unwind/dwarf2.h
+//   - DWARF 4 specification
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DWARF2_H
+#define DWARF2_H
+
+enum dwarf_attribute {
+  DW_AT_name = 0x03,
+  DW_AT_stmt_list = 0x10,
+  DW_AT_low_pc = 0x11,
+  DW_AT_high_pc = 0x12,
+  DW_AT_comp_dir = 0x1b,
+  DW_AT_abstract_origin = 0x31,
+  DW_AT_specification = 0x47,
+  DW_AT_ranges = 0x55,
+  DW_AT_call_file = 0x58,
+  DW_AT_call_line = 0x59,
+  DW_AT_linkage_name = 0x6e,
+  DW_AT_MIPS_linkage_name = 0x2007
+};
+
+enum dwarf_form {
+  DW_FORM_addr = 0x01,
+  DW_FORM_block2 = 0x03,
+  DW_FORM_block4 = 0x04,
+  DW_FORM_data2 = 0x05,
+  DW_FORM_data4 = 0x06,
+  DW_FORM_data8 = 0x07,
+  DW_FORM_string = 0x08,
+  DW_FORM_block = 0x09,
+  DW_FORM_block1 = 0x0a,
+  DW_FORM_data1 = 0x0b,
+  DW_FORM_flag = 0x0c,
+  DW_FORM_sdata = 0x0d,
+  DW_FORM_strp = 0x0e,
+  DW_FORM_udata = 0x0f,
+  DW_FORM_ref_addr = 0x10,
+  DW_FORM_ref1 = 0x11,
+  DW_FORM_ref2 = 0x12,
+  DW_FORM_ref4 = 0x13,
+  DW_FORM_ref8 = 0x14,
+  DW_FORM_ref_udata = 0x15,
+  DW_FORM_indirect = 0x16,
+  DW_FORM_sec_offset = 0x17,
+  DW_FORM_exprloc = 0x18,
+  DW_FORM_flag_present = 0x19,
+  DW_FORM_ref_sig8 = 0x20,
+  DW_FORM_GNU_addr_index = 0x1f01,
+  DW_FORM_GNU_str_index = 0x1f02,
+  DW_FORM_GNU_ref_alt = 0x1f20,
+  DW_FORM_GNU_strp_alt = 0x1f21
+};
+
+enum dwarf_tag {
+  DW_TAG_entry_point = 0x03,
+  DW_TAG_compile_unit = 0x11,
+  DW_TAG_inlined_subroutine = 0x1d,
+  DW_TAG_subprogram = 0x2e
+};
+
+enum dwarf_lns {
+  DW_LNS_extended_op = 0x00,
+  DW_LNS_copy = 0x01,
+  DW_LNS_advance_pc = 0x02,
+  DW_LNS_advance_line = 0x03,
+  DW_LNS_set_file = 0x04,
+  DW_LNS_set_column = 0x05,
+  DW_LNS_negate_stmt = 0x06,
+  DW_LNS_set_basic_block = 0x07,
+  DW_LNS_const_add_pc = 0x08,
+  DW_LNS_fixed_advance_pc = 0x09,
+  DW_LNS_set_prologue_end = 0x0a,
+  DW_LNS_set_epilogue_begin = 0x0b,
+  DW_LNS_set_isa = 0x0c
+};
+
+enum dwarf_lne {
+  DW_LNE_end_sequence = 0x01,
+  DW_LNE_set_address = 0x02,
+  DW_LNE_define_file = 0x03,
+  DW_LNE_set_discriminator = 0x04
+};
+
+#endif  // DWARF2_H
diff --git a/third_party/gofrontend/include/filenames.h b/third_party/gofrontend/include/filenames.h
new file mode 100644
index 0000000..726b6ad
--- /dev/null
+++ b/third_party/gofrontend/include/filenames.h
@@ -0,0 +1,15 @@
+//===----------------------------- filenames.h ----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FILENAMES_H
+#define FILENAMES_H
+
+#define IS_ABSOLUTE_PATH(path) ((path)[0] == '/')
+
+#endif
diff --git a/third_party/gofrontend/install-sh b/third_party/gofrontend/install-sh
new file mode 100644
index 0000000..6781b98
--- /dev/null
+++ b/third_party/gofrontend/install-sh
@@ -0,0 +1,520 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2009-04-28.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""	$nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+	shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+	case $mode in
+	  *' '* | *'	'* | *'
+'*	  | *'*'* | *'?'* | *'['*)
+	    echo "$0: invalid mode: $mode" >&2
+	    exit 1;;
+	esac
+	shift;;
+
+    -o) chowncmd="$chownprog $2"
+	shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+	shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)	shift
+	break;;
+
+    -*)	echo "$0: invalid option: $1" >&2
+	exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dst_arg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dst_arg: Is a directory" >&2
+	exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+	(dirname "$dst") 2>/dev/null ||
+	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	     X"$dst" : 'X\(//\)[^/]' \| \
+	     X"$dst" : 'X\(//\)$' \| \
+	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+	echo X"$dst" |
+	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)[^/].*/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\).*/{
+		   s//\1/
+		   q
+		 }
+		 s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+	# Create intermediate dirs using mode 755 as modified by the umask.
+	# This is like FreeBSD 'install' as of 1997-10-28.
+	umask=`umask`
+	case $stripcmd.$umask in
+	  # Optimize common cases.
+	  *[2367][2367]) mkdir_umask=$umask;;
+	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+	  *[0-7])
+	    mkdir_umask=`expr $umask + 22 \
+	      - $umask % 100 % 40 + $umask % 20 \
+	      - $umask % 10 % 4 + $umask % 2
+	    `;;
+	  *) mkdir_umask=$umask,go-w;;
+	esac
+
+	# With -d, create the new directory with the user-specified mode.
+	# Otherwise, rely on $mkdir_umask.
+	if test -n "$dir_arg"; then
+	  mkdir_mode=-m$mode
+	else
+	  mkdir_mode=
+	fi
+
+	posix_mkdir=false
+	case $umask in
+	  *[123567][0-7][0-7])
+	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
+	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+	    ;;
+	  *)
+	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+	    if (umask $mkdir_umask &&
+		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+	    then
+	      if test -z "$dir_arg" || {
+		   # Check for POSIX incompatibilities with -m.
+		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+		   # other-writeable bit of parent directory when it shouldn't.
+		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
+		   case $ls_ld_tmpdir in
+		     d????-?r-*) different_mode=700;;
+		     d????-?--*) different_mode=755;;
+		     *) false;;
+		   esac &&
+		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+		   }
+		 }
+	      then posix_mkdir=:
+	      fi
+	      rmdir "$tmpdir/d" "$tmpdir"
+	    else
+	      # Remove any dirs left behind by ancient mkdir implementations.
+	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+	    fi
+	    trap '' 0;;
+	esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+	umask $mkdir_umask &&
+	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+	/*) prefix='/';;
+	-*) prefix='./';;
+	*)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+	test -z "$d" && continue
+
+	prefix=$prefix$d
+	if test -d "$prefix"; then
+	  prefixes=
+	else
+	  if $posix_mkdir; then
+	    (umask=$mkdir_umask &&
+	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+	    # Don't fail if two instances are running concurrently.
+	    test -d "$prefix" || exit 1
+	  else
+	    case $prefix in
+	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+	      *) qprefix=$prefix;;
+	    esac
+	    prefixes="$prefixes '$qprefix'"
+	  fi
+	fi
+	prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+	# Don't fail if two instances are running concurrently.
+	(umask $mkdir_umask &&
+	 eval "\$doit_exec \$mkdirprog $prefixes") ||
+	  test -d "$dstdir" || exit 1
+	obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+	# Now remove or move aside any old file at destination location.
+	# We try this two ways since rm can't unlink itself on some
+	# systems and the destination file might be busy for other
+	# reasons.  In this case, the final cleanup might fail but the new
+	# file should still install successfully.
+	{
+	  test ! -f "$dst" ||
+	  $doit $rmcmd -f "$dst" 2>/dev/null ||
+	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+	  } ||
+	  { echo "$0: cannot unlink or rename $dst" >&2
+	    (exit 1); exit 1
+	  }
+	} &&
+
+	# Now rename the file to the real destination.
+	$doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/third_party/gofrontend/libbacktrace/ChangeLog b/third_party/gofrontend/libbacktrace/ChangeLog
new file mode 100644
index 0000000..adb54d8
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/ChangeLog
@@ -0,0 +1,433 @@
+2014-05-08  Ian Lance Taylor  <iant@google.com>
+
+	* mmap.c (backtrace_free): If freeing a large aligned block of
+	memory, call munmap rather than holding onto it.
+	(backtrace_vector_grow): When growing a vector, double the number
+	of pages requested.  When releasing the old version of a grown
+	vector, pass the correct size to backtrace_free.
+
+2014-03-07  Ian Lance Taylor  <iant@google.com>
+
+	* sort.c (backtrace_qsort): Use middle element as pivot.
+
+2014-03-06  Ian Lance Taylor  <iant@google.com>
+
+	* sort.c: New file.
+	* stest.c: New file.
+	* internal.h (backtrace_qsort): Declare.
+	* dwarf.c (read_abbrevs): Call backtrace_qsort instead of qsort.
+	(read_line_info, read_function_entry): Likewise.
+	(read_function_info, build_dwarf_data): Likewise.
+	* elf.c (elf_initialize_syminfo): Likewise.
+	* Makefile.am (libbacktrace_la_SOURCES): Add sort.c.
+	(stest_SOURCES, stest_LDADD): Define.
+	(check_PROGRAMS): Add stest.
+
+2014-02-07  Misty De Meo  <misty@brew.sh>
+
+	PR target/58710
+	* configure.ac: Use AC_LINK_IFELSE in check for
+	_Unwind_GetIPInfo.
+	* configure: Regenerate.
+
+2014-01-02  Richard Sandiford  <rdsandiford@googlemail.com>
+
+	Update copyright years
+
+2013-12-06  Jakub Jelinek  <jakub@redhat.com>
+
+	* elf.c (ET_DYN): Undefine and define again.
+	(elf_add): Add exe argument, if true and ehdr.e_type is ET_DYN,
+	return early -1 without closing the descriptor.
+	(struct phdr_data): Add exe_descriptor.
+	(phdr_callback): If pd->exe_descriptor is not -1, for very first
+	call if dlpi_name is NULL just call elf_add with the exe_descriptor,
+	otherwise backtrace_close the exe_descriptor if not -1.  Adjust
+	call to elf_add.
+	(backtrace_initialize): Adjust call to elf_add.  If it returns
+	-1, set pd.exe_descriptor to descriptor, otherwise set it to -1.
+
+2013-12-05  Ian Lance Taylor  <iant@google.com>
+
+	* alloc.c (backtrace_vector_finish): Add error_callback and data
+	parameters.  Call backtrace_vector_release.  Return address base.
+	* mmap.c (backtrace_vector_finish): Add error_callback and data
+	parameters.  Return address base.
+	* dwarf.c (read_function_info): Get new address base from
+	backtrace_vector_finish.
+	* internal.h (backtrace_vector_finish): Update declaration.
+
+2013-11-27  Ian Lance Taylor  <iant@google.com>
+
+	* dwarf.c (find_address_ranges): New static function, broken out
+	of build_address_map.
+	(build_address_map): Call it.
+	* btest.c (check): Check for missing filename or function, rather
+	than crashing.
+	(f3): Check that enough frames were returned.
+
+2013-11-19  Jakub Jelinek  <jakub@redhat.com>
+
+	* backtrace.h (backtrace_syminfo_callback): Add symsize argument.
+	* elf.c (elf_syminfo): Pass 0 or sym->size to the callback as
+	last argument.
+	* btest.c (struct symdata): Add size field.
+	(callback_three): Add symsize argument.  Copy it to the data->size
+	field.
+	(f23): Set symdata.size to 0.
+	(test5): Likewise.  If sizeof (int) > 1, lookup address of
+	((uintptr_t) &global) + 1.  Verify symdata.val and symdata.size
+	values.
+
+	* atomic.c: Include sys/types.h.
+
+2013-11-18  Ian Lance Taylor  <iant@google.com>
+
+	* configure.ac: Check for support of __atomic extensions.
+	* internal.h: Declare or #define atomic functions for use in
+	backtrace code.
+	* atomic.c: New file.
+	* dwarf.c (dwarf_lookup_pc): Use atomic functions.
+	(dwarf_fileline, backtrace_dwarf_add): Likewise.
+	* elf.c (elf_add_syminfo_data, elf_syminfo): Likewise.
+	(backtrace_initialize): Likewise.
+	* fileline.c (fileline_initialize): Likewise.
+	* Makefile.am (libbacktrace_la_SOURCES): Add atomic.c.
+	* configure, config.h.in, Makefile.in: Rebuild.
+
+2013-11-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* elf.c (SHN_UNDEF): Define.
+	(elf_initialize_syminfo): Add base_address argument.  Ignore symbols
+	with st_shndx == SHN_UNDEF.  Add base_address to address fields.
+	(elf_add): Adjust caller.
+
+	* elf.c (phdr_callback): Process info->dlpi_addr == 0 normally.
+
+2013-11-16  Ian Lance Taylor  <iant@google.com>
+
+	* backtrace.h (backtrace_create_state): Correct comment about
+	threading.
+
+2013-11-15  Ian Lance Taylor  <iant@google.com>
+
+	* backtrace.h (backtrace_syminfo): Update comment and parameter
+	name to take any address, not just a PC value.
+	* elf.c (STT_OBJECT): Define.
+	(elf_nosyms): Rename parameter pc to addr.
+	(elf_symbol_search): Rename local variable pc to addr.
+	(elf_initialize_syminfo): Add STT_OBJECT symbols to elf_symbols.
+	(elf_syminfo): Rename parameter pc to addr.
+	* btest.c (global): New global variable.
+	(test5): New test.
+	(main): Call test5.
+
+2013-10-17  Ian Lance Taylor  <iant@google.com>
+
+	* elf.c (elf_add): Don't get the wrong offsets if a debug section
+	is missing.
+
+2013-10-15  David Malcolm  <dmalcolm@redhat.com>
+
+	* configure.ac: Add --enable-host-shared, setting up
+	pre-existing PIC_FLAG variable within Makefile.am et al.
+	* configure: Regenerate.
+
+2013-09-20  Alan Modra  <amodra@gmail.com>
+
+	* configure: Regenerate.
+
+2013-07-23  Alexander Monakov  <amonakov@ispras.ru>
+
+	* elf.c (elf_syminfo): Loop over the elf_syminfo_data chain.
+
+2013-07-23  Alexander Monakov  <amonakov@ispras.ru>
+
+	* elf.c (backtrace_initialize): Pass elf_fileline_fn to
+	dl_iterate_phdr callbacks.
+
+2013-03-25  Ian Lance Taylor  <iant@google.com>
+
+	* alloc.c: #include <sys/types.h>.
+	* mmap.c: Likewise.
+
+2013-01-31  Ian Lance Taylor  <iant@google.com>
+
+	* dwarf.c (read_function_info): Permit fvec parameter to be NULL.
+	(dwarf_lookup_pc): Don't use ddata->fvec if threaded.
+
+2013-01-25  Jakub Jelinek  <jakub@redhat.com>
+
+	PR other/56076
+	* dwarf.c (read_line_header): Don't crash if DW_AT_comp_dir
+	attribute was not seen.
+
+2013-01-16  Ian Lance Taylor  <iant@google.com>
+
+	* dwarf.c (struct unit): Add filename and abs_filename fields.
+	(build_address_map): Set new fields when reading unit.
+	(dwarf_lookup_pc): If we don't find an entry in the line table,
+	just return the main file name.
+
+2013-01-14  Richard Sandiford  <rdsandiford@googlemail.com>
+
+	Update copyright years.
+
+2013-01-01  Ian Lance Taylor  <iant@google.com>
+
+	PR bootstrap/54834
+	* Makefile.am (AM_CPPFLAGS): Remove -I ../gcc/include and -I
+	$(MULTIBUILDTOP)/../../gcc/include.
+	* Makefile.in: Rebuild.
+
+2013-01-01  Ian Lance Taylor  <iant@google.com>
+
+	PR other/55536
+	* mmap.c (backtrace_alloc): Don't call sync functions if not
+	threaded.
+	(backtrace_free): Likewise.
+
+2012-12-12  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+	* mmapio.c: Define MAP_FAILED if not defined.
+
+2012-12-11  Jakub Jelinek  <jakub@redhat.com>
+
+	PR bootstrap/54926
+	* Makefile.am (AM_CFLAGS): Remove -frandom-seed=$@.
+	* configure.ac: If --with-target-subdir, add -frandom-seed=$@
+	to EXTRA_FLAGS unconditionally, otherwise check whether the compiler
+	accepts it.
+	* Makefile.in: Regenerated.
+	* configure: Regenerated.
+
+2012-12-07  Jakub Jelinek  <jakub@redhat.com>
+
+	PR bootstrap/54926
+	* Makefile.am (AM_CFLAGS): Add -frandom-seed=$@.
+	* Makefile.in: Regenerated.
+
+2012-11-20  Ian Lance Taylor  <iant@google.com>
+
+	* dwarf.c (read_attribute): Always clear val.
+
+2012-11-13  Ian Lance Taylor  <iant@google.com>
+
+	PR other/55312
+	* configure.ac: Only add -Werror if building a target library.
+	* configure: Rebuild.
+
+2012-11-12  Ian Lance Taylor  <iant@google.com>
+	    Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+	    Gerald Pfeifer  <gerald@pfeifer.com>
+
+	* configure.ac: Check for getexecname.
+	* fileline.c: #include <errno.h>.  Define getexecname if not
+	available.
+	(fileline_initialize): Try to find the executable in a few
+	different ways.
+	* print.c (error_callback): Only print the filename if it came
+	from the backtrace state.
+	* configure, config.h.in: Rebuild.
+
+2012-10-29  Ian Lance Taylor  <iant@google.com>
+
+	* mmap.c (backtrace_vector_release): Correct last patch: add
+	aligned, not size.
+
+2012-10-29  Ian Lance Taylor  <iant@google.com>
+
+	* mmap.c (backtrace_vector_release): Make sure freed block is
+	aligned on 8-byte boundary.
+
+2012-10-26  Ian Lance Taylor  <iant@google.com>
+
+	PR other/55087
+	* posix.c (backtrace_open): Add does_not_exist parameter.
+	* elf.c (phdr_callback): Do not warn if shared library could not
+	be opened.
+	* fileline.c (fileline_initialize): Update calls to
+	backtrace_open.
+	* internal.h (backtrace_open): Update declaration.
+
+2012-10-26  Jack Howarth  <howarth@bromo.med.uc.edu>
+
+	PR target/55061
+	* configure.ac: Check for _Unwind_GetIPInfo function declaration.
+	* configure: Regenerate.
+
+2012-10-24  Ian Lance Taylor  <iant@google.com>
+
+	PR target/55061
+	* configure.ac: Check whether -funwind-tables option works.
+	* configure: Rebuild.
+
+2012-10-11  Ian Lance Taylor  <iant@google.com>
+
+	* configure.ac: Do not use dl_iterate_phdr on Solaris 10.
+	* configure: Rebuild.
+
+2012-10-10  Ian Lance Taylor  <iant@google.com>
+
+	* elf.c: Rename all Elf typedefs to start with b_elf, and be all
+	lower case.
+
+2012-10-10  Hans-Peter Nilsson  <hp@bitrange.com>
+
+	* elf.c (elf_add_syminfo_data): Add casts to avoid warning.
+
+2012-10-09  Ian Lance Taylor  <iant@google.com>
+
+	* dwarf.c (dwarf_fileline): Add cast to avoid warning.
+	(backtrace_dwarf_add): Likewise.
+
+2012-10-09  Ian Lance Taylor  <iant@google.com>
+
+	Add support for tracing through shared libraries.
+	* configure.ac: Check for link.h and dl_iterate_phdr.
+	* elf.c: #include <link.h> if system has dl_iterate_phdr.  #undef
+	ELF macros before #defining them.
+	(dl_phdr_info, dl_iterate_phdr): Define if system does not have
+	dl_iterate_phdr.
+	(struct elf_syminfo_data): Add next field.
+	(elf_initialize_syminfo): Initialize next field.
+	(elf_add_syminfo_data): New static function.
+	(elf_add): New static function, broken out of
+	backtrace_initialize.  Call backtrace_dwarf_add instead of
+	backtrace_dwarf_initialize.
+	(struct phdr_data): Define.
+	(phdr_callback): New static function.
+	(backtrace_initialize): Call elf_add.
+	* dwarf.c (struct dwarf_data): Add next and base_address fields.
+	(add_unit_addr): Add base_address parameter.  Change all callers.
+	(add_unit_ranges, build_address_map): Likewise.
+	(add_line): Add ddata parameter.  Change all callers.
+	(read_line_program, add_function_range): Likewise.
+	(dwarf_lookup_pc): New static function, broken out of
+	dwarf_fileline.
+	(dwarf_fileline): Call dwarf_lookup_pc.
+	(build_dwarf_data): New static function.
+	(backtrace_dwarf_add): New function.
+	(backtrace_dwarf_initialize): Remove.
+	* internal.h (backtrace_dwarf_initialize): Don't declare.
+	(backtrace_dwarf_add): Declare.
+	* configure, config.h.in: Rebuild.
+
+2012-10-04  Gerald Pfeifer  <gerald@pfeifer.com>
+
+	* btest.c (f23): Avoid uninitialized variable warning.
+
+2012-10-04  Ian Lance Taylor  <iant@google.com>
+
+	* dwarf.c: If the system header files do not declare strnlen,
+	provide our own version.
+
+2012-10-03  Ian Lance Taylor  <iant@google.com>
+
+	* dwarf.c (read_uleb128): Fix overflow test.
+	(read_sleb128): Likewise.
+	(build_address_map): Don't change unit_buf.start.
+
+2012-10-02  Uros Bizjak  <ubizjak@gmail.com>
+
+	PR other/54761
+	* configure.ac (EXTRA_FLAGS): New.
+	* Makefile.am (AM_FLAGS): Add $(EXTRA_FLAGS).
+	* configure, Makefile.in: Regenerate.
+
+2012-09-29  Ian Lance Taylor  <iant@google.com>
+
+	PR other/54749
+	* fileline.c (fileline_initialize): Pass errnum as -1 when
+	reporting that we could not read executable information after a
+	previous failure.
+
+2012-09-27  Ian Lance Taylor  <iant@google.com>
+
+	PR bootstrap/54732
+	* configure.ac: Add no-dependencies to AM_INIT_AUTOMAKE.
+	* Makefile.am: Add dependencies for all objects.
+	* configure, aclocal.m4, Makefile.in: Rebuild.
+
+2012-09-27  Ian Lance Taylor  <iant@google.com>
+
+	PR other/54726
+	* elf.c (backtrace_initialize): Set *fileln_fn, not
+	state->fileln_fn.
+
+2012-09-19  Ian Lance Taylor  <iant@google.com>
+
+	* configure.ac: Only use GCC_CHECK_UNWIND_GETIPINFO when compiled
+	as a target library.
+	* configure: Rebuild.
+
+2012-09-19  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+	    Ian Lance Taylor  <iant@google.com>
+
+        * configure.ac (GCC_HEADER_STDINT): Invoke.
+        * backtrace.h: If we can't find <stdint.h>, use "gstdint.h".
+        * btest.c: Don't include <stdint.h>.
+        * dwarf.c: Likewise.
+        * configure, aclocal.m4, Makefile.in, config.h.in: Rebuild.
+
+2012-09-18  Ian Lance Taylor  <iant@google.com>
+
+	PR bootstrap/54623
+	* Makefile.am (AM_CPPFLAGS): Define.
+	(AM_CFLAGS): Remove -I options.
+	* Makefile.in: Rebuild.
+
+2012-09-18  Ian Lance Taylor  <iant@google.com>
+
+	* posix.c (O_BINARY): Define if not defined.
+	(backtrace_open): Pass O_BINARY to open.  Only call fcntl if
+	HAVE_FCNTL is defined.
+	* configure.ac: Test for the fcntl function.
+	* configure, config.h.in: Rebuild.
+
+2012-09-18  Ian Lance Taylor  <iant@google.com>
+
+	* btest.c (test1, test2, test3, test4): Add the unused attribute.
+
+2012-09-18  Ian Lance Taylor  <iant@google.com>
+
+	* dwarf.c: Correct test of HAVE_DECL_STRNLEN.
+
+2012-09-18  Ian Lance Taylor  <iant@google.com>
+
+	* configure.ac: Add AC_USE_SYSTEM_EXTENSIONS.
+	* mmapio.c: Don't define _GNU_SOURCE.
+	* configure, config.h.in: Rebuild.
+
+2012-09-18  Ian Lance Taylor  <iant@google.com>
+
+	* configure.ac: Check whether strnlen is declared.
+	* dwarf.c: Declare strnlen if not declared.
+	* configure, config.h.in: Rebuild.
+
+2012-09-18  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+
+	* fileline.c: Include <stdlib.h>.
+	* mmap.c: Likewise.
+
+2012-09-17  Ian Lance Taylor  <iant@google.com>
+
+	PR bootstrap/54611
+	* nounwind.c (backtrace_full): Rename from backtrace.  Add state
+	parameter.
+
+2012-09-17  Gerald Pfeifer  <gerald@pfeifer.com>
+
+	PR bootstrap/54611
+	* nounwind.c (backtrace_simple): Add state parameter.
+
+2012-09-17  Ian Lance Taylor  <iant@google.com>
+
+	PR bootstrap/54609
+	* unknown.c (unknown_fileline): Add state parameter, remove
+	fileline_data parameter, name error_callback parameter.
+	(backtrace_initialize): Add state parameter.
+
+2012-09-17  Ian Lance Taylor  <iant@google.com>
+
+	* Initial implementation.
diff --git a/third_party/gofrontend/libbacktrace/Makefile.am b/third_party/gofrontend/libbacktrace/Makefile.am
new file mode 100644
index 0000000..ab1a6b3
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/Makefile.am
@@ -0,0 +1,132 @@
+# Makefile.am -- Backtrace Makefile.
+# Copyright (C) 2012-2014 Free Software Foundation, Inc.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+
+#     (1) Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer. 
+
+#     (2) Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.  
+
+#     (3) The name of the author may not be used to
+#     endorse or promote products derived from this software without
+#     specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+ACLOCAL_AMFLAGS = -I .. -I ../config
+
+AM_CPPFLAGS = -I $(top_srcdir)/../include -I $(top_srcdir)/../libgcc \
+	-I ../libgcc
+
+AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)
+
+noinst_LTLIBRARIES = libbacktrace.la
+
+libbacktrace_la_SOURCES = \
+	backtrace.h \
+	atomic.c \
+	dwarf.c \
+	fileline.c \
+	internal.h \
+	posix.c \
+	print.c \
+	sort.c \
+	state.c
+
+BACKTRACE_FILES = \
+	backtrace.c \
+	simple.c \
+	nounwind.c
+
+FORMAT_FILES = \
+	elf.c \
+	unknown.c
+
+VIEW_FILES = \
+	read.c \
+	mmapio.c
+
+ALLOC_FILES = \
+	alloc.c \
+	mmap.c
+
+EXTRA_libbacktrace_la_SOURCES = \
+	$(BACKTRACE_FILES) \
+	$(FORMAT_FILES) \
+	$(VIEW_FILES) \
+	$(ALLOC_FILES)
+
+libbacktrace_la_LIBADD = \
+	$(BACKTRACE_FILE) \
+	$(FORMAT_FILE) \
+	$(VIEW_FILE) \
+	$(ALLOC_FILE)
+
+libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
+
+# Testsuite.
+
+check_PROGRAMS =
+
+TESTS = $(check_PROGRAMS)
+
+if NATIVE
+
+btest_SOURCES = btest.c
+btest_CFLAGS = $(AM_CFLAGS) -g -O
+btest_LDADD = libbacktrace.la
+
+check_PROGRAMS += btest
+
+stest_SOURCES = stest.c
+stest_LDADD = libbacktrace.la
+
+check_PROGRAMS += stest
+
+endif NATIVE
+
+# We can't use automake's automatic dependency tracking, because it
+# breaks when using bootstrap-lean.  Automatic dependency tracking
+# with GCC bootstrap will cause some of the objects to depend on
+# header files in prev-gcc/include, e.g., stddef.h and stdarg.h.  When
+# using bootstrap-lean, prev-gcc is removed after each stage.  When
+# running "make install", those header files will be gone, causing the
+# library to be rebuilt at install time.  That may not succeed.
+
+# These manual dependencies do not include dependencies on unwind.h,
+# even though that is part of GCC, because where to find it depends on
+# whether we are being built as a host library or a target library.
+
+INCDIR = $(top_srcdir)/../include
+alloc.lo: config.h backtrace.h internal.h
+backtrace.lo: config.h backtrace.h
+btest.lo: (INCDIR)/filenames.h backtrace.h backtrace-supported.h
+dwarf.lo: config.h $(INCDIR)/dwarf2.h $(INCDIR)/dwarf2.def \
+	$(INCDIR)/filenames.h backtrace.h internal.h
+elf.lo: config.h backtrace.h internal.h
+fileline.lo: config.h backtrace.h internal.h
+mmap.lo: config.h backtrace.h internal.h
+mmapio.lo: config.h backtrace.h internal.h
+nounwind.lo: config.h internal.h
+posix.lo: config.h backtrace.h internal.h
+print.lo: config.h backtrace.h internal.h
+read.lo: config.h backtrace.h internal.h
+simple.lo: config.h backtrace.h internal.h
+state.lo: config.h backtrace.h backtrace-supported.h internal.h
+unknown.lo: config.h backtrace.h internal.h
diff --git a/third_party/gofrontend/libbacktrace/Makefile.in b/third_party/gofrontend/libbacktrace/Makefile.in
new file mode 100644
index 0000000..f2821fc
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/Makefile.in
@@ -0,0 +1,739 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am -- Backtrace Makefile.
+# Copyright (C) 2012-2014 Free Software Foundation, Inc.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+
+#     (1) Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer. 
+
+#     (2) Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.  
+
+#     (3) The name of the author may not be used to
+#     endorse or promote products derived from this software without
+#     specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+check_PROGRAMS = $(am__EXEEXT_1)
+@NATIVE_TRUE@am__append_1 = btest stest
+subdir = .
+DIST_COMMON = README ChangeLog $(srcdir)/Makefile.in \
+	$(srcdir)/Makefile.am $(top_srcdir)/configure \
+	$(am__configure_deps) $(srcdir)/config.h.in \
+	$(srcdir)/../mkinstalldirs $(srcdir)/backtrace-supported.h.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/lead-dot.m4 \
+	$(top_srcdir)/../config/multi.m4 \
+	$(top_srcdir)/../config/override.m4 \
+	$(top_srcdir)/../config/stdint.m4 \
+	$(top_srcdir)/../config/unwind_ipinfo.m4 \
+	$(top_srcdir)/../config/warnings.m4 \
+	$(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \
+	$(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
+	$(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = backtrace-supported.h
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am_libbacktrace_la_OBJECTS = atomic.lo dwarf.lo fileline.lo posix.lo \
+	print.lo sort.lo state.lo
+libbacktrace_la_OBJECTS = $(am_libbacktrace_la_OBJECTS)
+@NATIVE_TRUE@am__EXEEXT_1 = btest$(EXEEXT) stest$(EXEEXT)
+@NATIVE_TRUE@am_btest_OBJECTS = btest-btest.$(OBJEXT)
+btest_OBJECTS = $(am_btest_OBJECTS)
+@NATIVE_TRUE@btest_DEPENDENCIES = libbacktrace.la
+btest_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(btest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+@NATIVE_TRUE@am_stest_OBJECTS = stest.$(OBJEXT)
+stest_OBJECTS = $(am_stest_OBJECTS)
+@NATIVE_TRUE@stest_DEPENDENCIES = libbacktrace.la
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
+	$(btest_SOURCES) $(stest_SOURCES)
+MULTISRCTOP = 
+MULTIBUILDTOP = 
+MULTIDIRS = 
+MULTISUBDIR = 
+MULTIDO = true
+MULTICLEAN = true
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+ACLOCAL = @ACLOCAL@
+ALLOC_FILE = @ALLOC_FILE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BACKTRACE_FILE = @BACKTRACE_FILE@
+BACKTRACE_SUPPORTED = @BACKTRACE_SUPPORTED@
+BACKTRACE_SUPPORTS_THREADS = @BACKTRACE_SUPPORTS_THREADS@
+BACKTRACE_USES_MALLOC = @BACKTRACE_USES_MALLOC@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_FLAGS = @EXTRA_FLAGS@
+FGREP = @FGREP@
+FORMAT_FILE = @FORMAT_FILE@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PIC_FLAG = @PIC_FLAG@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+VIEW_FILE = @VIEW_FILE@
+WARN_FLAGS = @WARN_FLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__leading_dot = @am__leading_dot@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libtool_VERSION = @libtool_VERSION@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I .. -I ../config
+AM_CPPFLAGS = -I $(top_srcdir)/../include -I $(top_srcdir)/../libgcc \
+	-I ../libgcc
+
+AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)
+noinst_LTLIBRARIES = libbacktrace.la
+libbacktrace_la_SOURCES = \
+	backtrace.h \
+	atomic.c \
+	dwarf.c \
+	fileline.c \
+	internal.h \
+	posix.c \
+	print.c \
+	sort.c \
+	state.c
+
+BACKTRACE_FILES = \
+	backtrace.c \
+	simple.c \
+	nounwind.c
+
+FORMAT_FILES = \
+	elf.c \
+	unknown.c
+
+VIEW_FILES = \
+	read.c \
+	mmapio.c
+
+ALLOC_FILES = \
+	alloc.c \
+	mmap.c
+
+EXTRA_libbacktrace_la_SOURCES = \
+	$(BACKTRACE_FILES) \
+	$(FORMAT_FILES) \
+	$(VIEW_FILES) \
+	$(ALLOC_FILES)
+
+libbacktrace_la_LIBADD = \
+	$(BACKTRACE_FILE) \
+	$(FORMAT_FILE) \
+	$(VIEW_FILE) \
+	$(ALLOC_FILE)
+
+libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
+TESTS = $(check_PROGRAMS)
+@NATIVE_TRUE@btest_SOURCES = btest.c
+@NATIVE_TRUE@btest_CFLAGS = $(AM_CFLAGS) -g -O
+@NATIVE_TRUE@btest_LDADD = libbacktrace.la
+@NATIVE_TRUE@stest_SOURCES = stest.c
+@NATIVE_TRUE@stest_LDADD = libbacktrace.la
+
+# We can't use automake's automatic dependency tracking, because it
+# breaks when using bootstrap-lean.  Automatic dependency tracking
+# with GCC bootstrap will cause some of the objects to depend on
+# header files in prev-gcc/include, e.g., stddef.h and stdarg.h.  When
+# using bootstrap-lean, prev-gcc is removed after each stage.  When
+# running "make install", those header files will be gone, causing the
+# library to be rebuilt at install time.  That may not succeed.
+
+# These manual dependencies do not include dependencies on unwind.h,
+# even though that is part of GCC, because where to find it depends on
+# whether we are being built as a host library or a target library.
+INCDIR = $(top_srcdir)/../include
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+am--refresh:
+	@:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps'; \
+	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign --ignore-deps Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	$(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+	else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+backtrace-supported.h: $(top_builddir)/config.status $(srcdir)/backtrace-supported.h.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libbacktrace.la: $(libbacktrace_la_OBJECTS) $(libbacktrace_la_DEPENDENCIES) 
+	$(LINK)  $(libbacktrace_la_OBJECTS) $(libbacktrace_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+	@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+btest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES) 
+	@rm -f btest$(EXEEXT)
+	$(btest_LINK) $(btest_OBJECTS) $(btest_LDADD) $(LIBS)
+stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) 
+	@rm -f stest$(EXEEXT)
+	$(LINK) $(stest_OBJECTS) $(stest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+.c.o:
+	$(COMPILE) -c $<
+
+.c.obj:
+	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+	$(LTCOMPILE) -c -o $@ $<
+
+btest-btest.o: btest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c
+
+btest-btest.obj: btest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool config.lt
+
+# GNU Make needs to see an explicit $(MAKE) variable in the command it
+# runs to enable its job server during parallel builds.  Hence the
+# comments below.
+all-multi:
+	$(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE)
+install-multi:
+	$(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE)
+
+mostlyclean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE)
+clean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE)
+distclean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE)
+maintainer-clean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
+	srcdir=$(srcdir); export srcdir; \
+	list=' $(TESTS) '; \
+	$(am__tty_colors); \
+	if test -n "$$list"; then \
+	  for tst in $$list; do \
+	    if test -f ./$$tst; then dir=./; \
+	    elif test -f $$tst; then dir=; \
+	    else dir="$(srcdir)/"; fi; \
+	    if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xpass=`expr $$xpass + 1`; \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=XPASS; \
+	      ;; \
+	      *) \
+		col=$$grn; res=PASS; \
+	      ;; \
+	      esac; \
+	    elif test $$? -ne 77; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xfail=`expr $$xfail + 1`; \
+		col=$$lgn; res=XFAIL; \
+	      ;; \
+	      *) \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=FAIL; \
+	      ;; \
+	      esac; \
+	    else \
+	      skip=`expr $$skip + 1`; \
+	      col=$$blu; res=SKIP; \
+	    fi; \
+	    echo "$${col}$$res$${std}: $$tst"; \
+	  done; \
+	  if test "$$all" -eq 1; then \
+	    tests="test"; \
+	    All=""; \
+	  else \
+	    tests="tests"; \
+	    All="All "; \
+	  fi; \
+	  if test "$$failed" -eq 0; then \
+	    if test "$$xfail" -eq 0; then \
+	      banner="$$All$$all $$tests passed"; \
+	    else \
+	      if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+	      banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+	    fi; \
+	  else \
+	    if test "$$xpass" -eq 0; then \
+	      banner="$$failed of $$all $$tests failed"; \
+	    else \
+	      if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+	      banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+	    fi; \
+	  fi; \
+	  dashes="$$banner"; \
+	  skipped=""; \
+	  if test "$$skip" -ne 0; then \
+	    if test "$$skip" -eq 1; then \
+	      skipped="($$skip test was not run)"; \
+	    else \
+	      skipped="($$skip tests were not run)"; \
+	    fi; \
+	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$skipped"; \
+	  fi; \
+	  report=""; \
+	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+	    report="Please report to $(PACKAGE_BUGREPORT)"; \
+	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$report"; \
+	  fi; \
+	  dashes=`echo "$$dashes" | sed s/./=/g`; \
+	  if test "$$failed" -eq 0; then \
+	    echo "$$grn$$dashes"; \
+	  else \
+	    echo "$$red$$dashes"; \
+	  fi; \
+	  echo "$$banner"; \
+	  test -z "$$skipped" || echo "$$skipped"; \
+	  test -z "$$report" || echo "$$report"; \
+	  echo "$$dashes$$std"; \
+	  test "$$failed" -eq 0; \
+	else :; fi
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) all-multi config.h
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am clean-multi
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+	clean-noinstLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am distclean-multi
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-hdr distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-multi
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am maintainer-clean-multi
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am mostlyclean-multi
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: all all-multi check-am clean-multi distclean-multi install-am \
+	install-multi install-strip maintainer-clean-multi \
+	mostlyclean-multi
+
+.PHONY: CTAGS GTAGS all all-am all-multi am--refresh check check-TESTS \
+	check-am clean clean-checkPROGRAMS clean-generic clean-libtool \
+	clean-multi clean-noinstLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-hdr \
+	distclean-libtool distclean-multi distclean-tags dvi dvi-am \
+	html html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-multi install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic maintainer-clean-multi mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	mostlyclean-multi pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am
+
+alloc.lo: config.h backtrace.h internal.h
+backtrace.lo: config.h backtrace.h
+btest.lo: (INCDIR)/filenames.h backtrace.h backtrace-supported.h
+dwarf.lo: config.h $(INCDIR)/dwarf2.h $(INCDIR)/dwarf2.def \
+	$(INCDIR)/filenames.h backtrace.h internal.h
+elf.lo: config.h backtrace.h internal.h
+fileline.lo: config.h backtrace.h internal.h
+mmap.lo: config.h backtrace.h internal.h
+mmapio.lo: config.h backtrace.h internal.h
+nounwind.lo: config.h internal.h
+posix.lo: config.h backtrace.h internal.h
+print.lo: config.h backtrace.h internal.h
+read.lo: config.h backtrace.h internal.h
+simple.lo: config.h backtrace.h internal.h
+state.lo: config.h backtrace.h backtrace-supported.h internal.h
+unknown.lo: config.h backtrace.h internal.h
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/third_party/gofrontend/libbacktrace/README b/third_party/gofrontend/libbacktrace/README
new file mode 100644
index 0000000..e8b2257
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/README
@@ -0,0 +1,23 @@
+The libbacktrace library
+Initially written by Ian Lance Taylor <iant@google.com>
+
+The libbacktrace library may be linked into a program or library and
+used to produce symbolic backtraces.  Sample uses would be to print a
+detailed backtrace when an error occurs or to gather detailed
+profiling information.
+
+The libbacktrace library is provided under a BSD license.  See the
+source files for the exact license text.
+
+The public functions are declared and documented in the header file
+backtrace.h, which should be #include'd by a user of the library.
+
+Building libbacktrace will generate a file backtrace-supported.h,
+which a user of the library may use to determine whether backtraces
+will work.  See the source file backtrace-supported.h.in for the
+macros that it defines.
+
+As of September 2012, libbacktrace only supports ELF executables with
+DWARF debugging information.  The library is written to make it
+straightforward to add support for other object file and debugging
+formats.
diff --git a/third_party/gofrontend/libbacktrace/aclocal.m4 b/third_party/gofrontend/libbacktrace/aclocal.m4
new file mode 100644
index 0000000..42214c2
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/aclocal.m4
@@ -0,0 +1,667 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
+[m4_warning([this file was generated for autoconf 2.64.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.11.1], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+	[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+			     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+		  [_AM_DEPENDENCIES(CC)],
+		  [define([AC_PROG_CC],
+			  defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+		  [_AM_DEPENDENCIES(CXX)],
+		  [define([AC_PROG_CXX],
+			  defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+		  [_AM_DEPENDENCIES(OBJC)],
+		  [define([AC_PROG_OBJC],
+			  defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST(install_sh)])
+
+# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless `enable' is passed literally.
+# For symmetry, `disable' may be passed as well.  Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+       [enable], [m4_define([am_maintainer_other], [disable])],
+       [disable], [m4_define([am_maintainer_other], [enable])],
+       [m4_define([am_maintainer_other], [enable])
+        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
+  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+  AC_ARG_ENABLE([maintainer-mode],
+[  --][am_maintainer_other][-maintainer-mode  am_maintainer_other make rules and dependencies not useful
+			  (and sometimes confusing) to the casual installer],
+      [USE_MAINTAINER_MODE=$enableval],
+      [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST([MAINT])dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p.  We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+  [[\\/$]]* | ?:[[\\/]]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
+    AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([../config/lead-dot.m4])
+m4_include([../config/multi.m4])
+m4_include([../config/override.m4])
+m4_include([../config/stdint.m4])
+m4_include([../config/unwind_ipinfo.m4])
+m4_include([../config/warnings.m4])
+m4_include([../libtool.m4])
+m4_include([../ltoptions.m4])
+m4_include([../ltsugar.m4])
+m4_include([../ltversion.m4])
+m4_include([../lt~obsolete.m4])
diff --git a/third_party/gofrontend/libbacktrace/alloc.c b/third_party/gofrontend/libbacktrace/alloc.c
new file mode 100644
index 0000000..37eca65
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/alloc.c
@@ -0,0 +1,152 @@
+/* alloc.c -- Memory allocation without mmap.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Allocation routines to use on systems that do not support anonymous
+   mmap.  This implementation just uses malloc, which means that the
+   backtrace functions may not be safely invoked from a signal
+   handler.  */
+
+/* Allocate memory like malloc.  */
+
+void *
+backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		 size_t size, backtrace_error_callback error_callback,
+		 void *data)
+{
+  void *ret;
+
+  ret = malloc (size);
+  if (ret == NULL)
+    error_callback (data, "malloc", errno);
+  return ret;
+}
+
+/* Free memory.  */
+
+void
+backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		void *p, size_t size ATTRIBUTE_UNUSED,
+		backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+		void *data ATTRIBUTE_UNUSED)
+{
+  free (p);
+}
+
+/* Grow VEC by SIZE bytes.  */
+
+void *
+backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		       size_t size, backtrace_error_callback error_callback,
+		       void *data, struct backtrace_vector *vec)
+{
+  void *ret;
+
+  if (size > vec->alc)
+    {
+      size_t alc;
+      void *base;
+
+      if (vec->size == 0)
+	alc = 32 * size;
+      else if (vec->size >= 4096)
+	alc = vec->size + 4096;
+      else
+	alc = 2 * vec->size;
+
+      if (alc < vec->size + size)
+	alc = vec->size + size;
+
+      base = realloc (vec->base, alc);
+      if (base == NULL)
+	{
+	  error_callback (data, "realloc", errno);
+	  return NULL;
+	}
+
+      vec->base = base;
+      vec->alc = alc - vec->size;
+    }
+
+  ret = (char *) vec->base + vec->size;
+  vec->size += size;
+  vec->alc -= size;
+  return ret;
+}
+
+/* Finish the current allocation on VEC.  */
+
+void *
+backtrace_vector_finish (struct backtrace_state *state,
+			 struct backtrace_vector *vec,
+			 backtrace_error_callback error_callback,
+			 void *data)
+{
+  void *ret;
+
+  /* With this allocator we call realloc in backtrace_vector_grow,
+     which means we can't easily reuse the memory here.  So just
+     release it.  */
+  if (!backtrace_vector_release (state, vec, error_callback, data))
+    return NULL;
+  ret = vec->base;
+  vec->base = NULL;
+  vec->size = 0;
+  vec->alc = 0;
+  return ret;
+}
+
+/* Release any extra space allocated for VEC.  */
+
+int
+backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,
+			  struct backtrace_vector *vec,
+			  backtrace_error_callback error_callback,
+			  void *data)
+{
+  vec->base = realloc (vec->base, vec->size);
+  if (vec->base == NULL)
+    {
+      error_callback (data, "realloc", errno);
+      return 0;
+    }
+  vec->alc = 0;
+  return 1;
+}
diff --git a/third_party/gofrontend/libbacktrace/atomic.c b/third_party/gofrontend/libbacktrace/atomic.c
new file mode 100644
index 0000000..f139d74
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/atomic.c
@@ -0,0 +1,113 @@
+/* atomic.c -- Support for atomic functions if not present.
+   Copyright (C) 2013-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+#include "internal.h"
+
+/* This file holds implementations of the atomic functions that are
+   used if the host compiler has the sync functions but not the atomic
+   functions, as is true of versions of GCC before 4.7.  */
+
+#if !defined (HAVE_ATOMIC_FUNCTIONS) && defined (HAVE_SYNC_FUNCTIONS)
+
+/* Do an atomic load of a pointer.  */
+
+void *
+backtrace_atomic_load_pointer (void *arg)
+{
+  void **pp;
+  void *p;
+
+  pp = (void **) arg;
+  p = *pp;
+  while (!__sync_bool_compare_and_swap (pp, p, p))
+    p = *pp;
+  return p;
+}
+
+/* Do an atomic load of an int.  */
+
+int
+backtrace_atomic_load_int (int *p)
+{
+  int i;
+
+  i = *p;
+  while (!__sync_bool_compare_and_swap (p, i, i))
+    i = *p;
+  return i;
+}
+
+/* Do an atomic store of a pointer.  */
+
+void
+backtrace_atomic_store_pointer (void *arg, void *p)
+{
+  void **pp;
+  void *old;
+
+  pp = (void **) arg;
+  old = *pp;
+  while (!__sync_bool_compare_and_swap (pp, old, p))
+    old = *pp;
+}
+
+/* Do an atomic store of a size_t value.  */
+
+void
+backtrace_atomic_store_size_t (size_t *p, size_t v)
+{
+  size_t old;
+
+  old = *p;
+  while (!__sync_bool_compare_and_swap (p, old, v))
+    old = *p;
+}
+
+/* Do an atomic store of a int value.  */
+
+void
+backtrace_atomic_store_int (int *p, int v)
+{
+  size_t old;
+
+  old = *p;
+  while (!__sync_bool_compare_and_swap (p, old, v))
+    old = *p;
+}
+
+#endif
diff --git a/third_party/gofrontend/libbacktrace/backtrace-supported.h.in b/third_party/gofrontend/libbacktrace/backtrace-supported.h.in
new file mode 100644
index 0000000..901e3f7
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/backtrace-supported.h.in
@@ -0,0 +1,61 @@
+/* backtrace-supported.h.in -- Whether stack backtrace is supported.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+/* The file backtrace-supported.h.in is used by configure to generate
+   the file backtrace-supported.h.  The file backtrace-supported.h may
+   be #include'd to see whether the backtrace library will be able to
+   get a backtrace and produce symbolic information.  */
+
+
+/* BACKTRACE_SUPPORTED will be #define'd as 1 if the backtrace library
+   should work, 0 if it will not.  Libraries may #include this to make
+   other arrangements.  */
+
+#define BACKTRACE_SUPPORTED @BACKTRACE_SUPPORTED@
+
+/* BACKTRACE_USES_MALLOC will be #define'd as 1 if the backtrace
+   library will call malloc as it works, 0 if it will call mmap
+   instead.  This may be used to determine whether it is safe to call
+   the backtrace functions from a signal handler.  In general this
+   only applies to calls like backtrace and backtrace_pcinfo.  It does
+   not apply to backtrace_simple, which never calls malloc.  It does
+   not apply to backtrace_print, which always calls fprintf and
+   therefore malloc.  */
+
+#define BACKTRACE_USES_MALLOC @BACKTRACE_USES_MALLOC@
+
+/* BACKTRACE_SUPPORTS_THREADS will be #define'd as 1 if the backtrace
+   library is configured with threading support, 0 if not.  If this is
+   0, the threaded parameter to backtrace_create_state must be passed
+   as 0.  */
+
+#define BACKTRACE_SUPPORTS_THREADS @BACKTRACE_SUPPORTS_THREADS@
diff --git a/third_party/gofrontend/libbacktrace/backtrace.c b/third_party/gofrontend/libbacktrace/backtrace.c
new file mode 100644
index 0000000..cc3105c
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/backtrace.c
@@ -0,0 +1,108 @@
+/* backtrace.c -- Entry point for stack backtrace library.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include "unwind.h"
+#include "backtrace.h"
+
+/* The main backtrace_full routine.  */
+
+/* Data passed through _Unwind_Backtrace.  */
+
+struct backtrace_data
+{
+  /* Number of frames to skip.  */
+  int skip;
+  /* Library state.  */
+  struct backtrace_state *state;
+  /* Callback routine.  */
+  backtrace_full_callback callback;
+  /* Error callback routine.  */
+  backtrace_error_callback error_callback;
+  /* Data to pass to callback routines.  */
+  void *data;
+  /* Value to return from backtrace_full.  */
+  int ret;
+};
+
+/* Unwind library callback routine.  This is passed to
+   _Unwind_Backtrace.  */
+
+static _Unwind_Reason_Code
+unwind (struct _Unwind_Context *context, void *vdata)
+{
+  struct backtrace_data *bdata = (struct backtrace_data *) vdata;
+  uintptr_t pc;
+  int ip_before_insn = 0;
+
+#ifdef HAVE_GETIPINFO
+  pc = _Unwind_GetIPInfo (context, &ip_before_insn);
+#else
+  pc = _Unwind_GetIP (context);
+#endif
+
+  if (bdata->skip > 0)
+    {
+      --bdata->skip;
+      return _URC_NO_REASON;
+    }
+
+  if (!ip_before_insn)
+    --pc;
+
+  bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
+				 bdata->error_callback, bdata->data);
+  if (bdata->ret != 0)
+    return _URC_END_OF_STACK;
+
+  return _URC_NO_REASON;
+}
+
+/* Get a stack backtrace.  */
+
+int
+backtrace_full (struct backtrace_state *state, int skip,
+		backtrace_full_callback callback,
+		backtrace_error_callback error_callback, void *data)
+{
+  struct backtrace_data bdata;
+
+  bdata.skip = skip + 1;
+  bdata.state = state;
+  bdata.callback = callback;
+  bdata.error_callback = error_callback;
+  bdata.data = data;
+  bdata.ret = 0;
+  _Unwind_Backtrace (unwind, &bdata);
+  return bdata.ret;
+}
diff --git a/third_party/gofrontend/libbacktrace/backtrace.h b/third_party/gofrontend/libbacktrace/backtrace.h
new file mode 100644
index 0000000..03b5479
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/backtrace.h
@@ -0,0 +1,199 @@
+/* backtrace.h -- Public header file for stack backtrace library.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#ifndef BACKTRACE_H
+#define BACKTRACE_H
+
+#include <stddef.h>
+#include <stdio.h>
+
+/* We want to get a definition for uintptr_t, but we still care about
+   systems that don't have <stdint.h>.  */
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+
+#include <stdint.h>
+
+#elif defined(HAVE_STDINT_H)
+
+#include <stdint.h>
+
+#else
+
+/* Systems that don't have <stdint.h> must provide gstdint.h, e.g.,
+   from GCC_HEADER_STDINT in configure.ac.  */
+#include "gstdint.h"
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The backtrace state.  This struct is intentionally not defined in
+   the public interface.  */
+
+struct backtrace_state;
+
+/* The type of the error callback argument to backtrace functions.
+   This function, if not NULL, will be called for certain error cases.
+   The DATA argument is passed to the function that calls this one.
+   The MSG argument is an error message.  The ERRNUM argument, if
+   greater than 0, holds an errno value.  The MSG buffer may become
+   invalid after this function returns.
+
+   As a special case, the ERRNUM argument will be passed as -1 if no
+   debug info can be found for the executable, but the function
+   requires debug info (e.g., backtrace_full, backtrace_pcinfo).  The
+   MSG in this case will be something along the lines of "no debug
+   info".  Similarly, ERRNUM will be passed as -1 if there is no
+   symbol table, but the function requires a symbol table (e.g.,
+   backtrace_syminfo).  This may be used as a signal that some other
+   approach should be tried.  */
+
+typedef void (*backtrace_error_callback) (void *data, const char *msg,
+					  int errnum);
+
+/* Create state information for the backtrace routines.  This must be
+   called before any of the other routines, and its return value must
+   be passed to all of the other routines.  FILENAME is the path name
+   of the executable file; if it is NULL the library will try
+   system-specific path names.  If not NULL, FILENAME must point to a
+   permanent buffer.  If THREADED is non-zero the state may be
+   accessed by multiple threads simultaneously, and the library will
+   use appropriate atomic operations.  If THREADED is zero the state
+   may only be accessed by one thread at a time.  This returns a state
+   pointer on success, NULL on error.  If an error occurs, this will
+   call the ERROR_CALLBACK routine.  */
+
+extern struct backtrace_state *backtrace_create_state (
+    const char *filename, int threaded,
+    backtrace_error_callback error_callback, void *data);
+
+/* The type of the callback argument to the backtrace_full function.
+   DATA is the argument passed to backtrace_full.  PC is the program
+   counter.  FILENAME is the name of the file containing PC, or NULL
+   if not available.  LINENO is the line number in FILENAME containing
+   PC, or 0 if not available.  FUNCTION is the name of the function
+   containing PC, or NULL if not available.  This should return 0 to
+   continuing tracing.  The FILENAME and FUNCTION buffers may become
+   invalid after this function returns.  */
+
+typedef int (*backtrace_full_callback) (void *data, uintptr_t pc,
+					const char *filename, int lineno,
+					const char *function);
+
+/* Get a full stack backtrace.  SKIP is the number of frames to skip;
+   passing 0 will start the trace with the function calling
+   backtrace_full.  DATA is passed to the callback routine.  If any
+   call to CALLBACK returns a non-zero value, the stack backtrace
+   stops, and backtrace returns that value; this may be used to limit
+   the number of stack frames desired.  If all calls to CALLBACK
+   return 0, backtrace returns 0.  The backtrace_full function will
+   make at least one call to either CALLBACK or ERROR_CALLBACK.  This
+   function requires debug info for the executable.  */
+
+extern int backtrace_full (struct backtrace_state *state, int skip,
+			   backtrace_full_callback callback,
+			   backtrace_error_callback error_callback,
+			   void *data);
+
+/* The type of the callback argument to the backtrace_simple function.
+   DATA is the argument passed to simple_backtrace.  PC is the program
+   counter.  This should return 0 to continue tracing.  */
+
+typedef int (*backtrace_simple_callback) (void *data, uintptr_t pc);
+
+/* Get a simple backtrace.  SKIP is the number of frames to skip, as
+   in backtrace.  DATA is passed to the callback routine.  If any call
+   to CALLBACK returns a non-zero value, the stack backtrace stops,
+   and backtrace_simple returns that value.  Otherwise
+   backtrace_simple returns 0.  The backtrace_simple function will
+   make at least one call to either CALLBACK or ERROR_CALLBACK.  This
+   function does not require any debug info for the executable.  */
+
+extern int backtrace_simple (struct backtrace_state *state, int skip,
+			     backtrace_simple_callback callback,
+			     backtrace_error_callback error_callback,
+			     void *data);
+
+/* Print the current backtrace in a user readable format to a FILE.
+   SKIP is the number of frames to skip, as in backtrace_full.  Any
+   error messages are printed to stderr.  This function requires debug
+   info for the executable.  */
+
+extern void backtrace_print (struct backtrace_state *state, int skip, FILE *);
+
+/* Given PC, a program counter in the current program, call the
+   callback function with filename, line number, and function name
+   information.  This will normally call the callback function exactly
+   once.  However, if the PC happens to describe an inlined call, and
+   the debugging information contains the necessary information, then
+   this may call the callback function multiple times.  This will make
+   at least one call to either CALLBACK or ERROR_CALLBACK.  This
+   returns the first non-zero value returned by CALLBACK, or 0.  */
+
+extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
+			     backtrace_full_callback callback,
+			     backtrace_error_callback error_callback,
+			     void *data);
+
+/* The type of the callback argument to backtrace_syminfo.  DATA and
+   PC are the arguments passed to backtrace_syminfo.  SYMNAME is the
+   name of the symbol for the corresponding code.  SYMVAL is the
+   value and SYMSIZE is the size of the symbol.  SYMNAME will be NULL
+   if no error occurred but the symbol could not be found.  */
+
+typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc,
+					    const char *symname,
+					    uintptr_t symval,
+					    uintptr_t symsize);
+
+/* Given ADDR, an address or program counter in the current program,
+   call the callback information with the symbol name and value
+   describing the function or variable in which ADDR may be found.
+   This will call either CALLBACK or ERROR_CALLBACK exactly once.
+   This returns 1 on success, 0 on failure.  This function requires
+   the symbol table but does not require the debug info.  Note that if
+   the symbol table is present but ADDR could not be found in the
+   table, CALLBACK will be called with a NULL SYMNAME argument.
+   Returns 1 on success, 0 on error.  */
+
+extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr,
+			      backtrace_syminfo_callback callback,
+			      backtrace_error_callback error_callback,
+			      void *data);
+
+#ifdef __cplusplus
+} /* End extern "C".  */
+#endif
+
+#endif
diff --git a/third_party/gofrontend/libbacktrace/btest.c b/third_party/gofrontend/libbacktrace/btest.c
new file mode 100644
index 0000000..4b67c3d
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/btest.c
@@ -0,0 +1,715 @@
+/* btest.c -- Test for libbacktrace library
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+/* This program tests the externally visible interfaces of the
+   libbacktrace library.  */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "filenames.h"
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+
+/* Portable attribute syntax.  Actually some of these tests probably
+   won't work if the attributes are not recognized.  */
+
+#ifndef GCC_VERSION
+# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif
+
+#if (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+/* Used to collect backtrace info.  */
+
+struct info
+{
+  char *filename;
+  int lineno;
+  char *function;
+};
+
+/* Passed to backtrace callback function.  */
+
+struct bdata
+{
+  struct info *all;
+  size_t index;
+  size_t max;
+  int failed;
+};
+
+/* Passed to backtrace_simple callback function.  */
+
+struct sdata
+{
+  uintptr_t *addrs;
+  size_t index;
+  size_t max;
+  int failed;
+};
+
+/* Passed to backtrace_syminfo callback function.  */
+
+struct symdata
+{
+  const char *name;
+  uintptr_t val, size;
+  int failed;
+};
+
+/* The backtrace state.  */
+
+static void *state;
+
+/* The number of failures.  */
+
+static int failures;
+
+/* Return the base name in a path.  */
+
+static const char *
+base (const char *p)
+{
+  const char *last;
+  const char *s;
+
+  last = NULL;
+  for (s = p; *s != '\0'; ++s)
+    {
+      if (IS_DIR_SEPARATOR (*s))
+	last = s + 1;
+    }
+  return last != NULL ? last : p;
+}
+
+/* Check an entry in a struct info array.  */
+
+static void
+check (const char *name, int index, const struct info *all, int want_lineno,
+       const char *want_function, int *failed)
+{
+  if (*failed)
+    return;
+  if (all[index].filename == NULL || all[index].function == NULL)
+    {
+      fprintf (stderr, "%s: [%d]: missing file name or function name\n",
+	       name, index);
+      *failed = 1;
+      return;
+    }
+  if (strcmp (base (all[index].filename), "btest.c") != 0)
+    {
+      fprintf (stderr, "%s: [%d]: got %s expected test.c\n", name, index,
+	       all[index].filename);
+      *failed = 1;
+    }
+  if (all[index].lineno != want_lineno)
+    {
+      fprintf (stderr, "%s: [%d]: got %d expected %d\n", name, index,
+	       all[index].lineno, want_lineno);
+      *failed = 1;
+    }
+  if (strcmp (all[index].function, want_function) != 0)
+    {
+      fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
+	       all[index].function, want_function);
+      *failed = 1;
+    }
+}
+
+/* The backtrace callback function.  */
+
+static int
+callback_one (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
+	      const char *filename, int lineno, const char *function)
+{
+  struct bdata *data = (struct bdata *) vdata;
+  struct info *p;
+
+  if (data->index >= data->max)
+    {
+      fprintf (stderr, "callback_one: callback called too many times\n");
+      data->failed = 1;
+      return 1;
+    }
+
+  p = &data->all[data->index];
+  if (filename == NULL)
+    p->filename = NULL;
+  else
+    {
+      p->filename = strdup (filename);
+      assert (p->filename != NULL);
+    }
+  p->lineno = lineno;
+  if (function == NULL)
+    p->function = NULL;
+  else
+    {
+      p->function = strdup (function);
+      assert (p->function != NULL);
+    }
+  ++data->index;
+
+  return 0;
+}
+
+/* An error callback passed to backtrace.  */
+
+static void
+error_callback_one (void *vdata, const char *msg, int errnum)
+{
+  struct bdata *data = (struct bdata *) vdata;
+
+  fprintf (stderr, "%s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fprintf (stderr, "\n");
+  data->failed = 1;
+}
+
+/* The backtrace_simple callback function.  */
+
+static int
+callback_two (void *vdata, uintptr_t pc)
+{
+  struct sdata *data = (struct sdata *) vdata;
+
+  if (data->index >= data->max)
+    {
+      fprintf (stderr, "callback_two: callback called too many times\n");
+      data->failed = 1;
+      return 1;
+    }
+
+  data->addrs[data->index] = pc;
+  ++data->index;
+
+  return 0;
+}
+
+/* An error callback passed to backtrace_simple.  */
+
+static void
+error_callback_two (void *vdata, const char *msg, int errnum)
+{
+  struct sdata *data = (struct sdata *) vdata;
+
+  fprintf (stderr, "%s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fprintf (stderr, "\n");
+  data->failed = 1;
+}
+
+/* The backtrace_syminfo callback function.  */
+
+static void
+callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
+		const char *symname, uintptr_t symval,
+		uintptr_t symsize)
+{
+  struct symdata *data = (struct symdata *) vdata;
+
+  if (symname == NULL)
+    data->name = NULL;
+  else
+    {
+      data->name = strdup (symname);
+      assert (data->name != NULL);
+    }
+  data->val = symval;
+  data->size = symsize;
+}
+
+/* The backtrace_syminfo error callback function.  */
+
+static void
+error_callback_three (void *vdata, const char *msg, int errnum)
+{
+  struct symdata *data = (struct symdata *) vdata;
+
+  fprintf (stderr, "%s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fprintf (stderr, "\n");
+  data->failed = 1;
+}
+
+/* Test the backtrace function with non-inlined functions.  */
+
+static int test1 (void) __attribute__ ((noinline, unused));
+static int f2 (int) __attribute__ ((noinline));
+static int f3 (int, int) __attribute__ ((noinline));
+
+static int
+test1 (void)
+{
+  /* Returning a value here and elsewhere avoids a tailcall which
+     would mess up the backtrace.  */
+  return f2 (__LINE__) + 1;
+}
+
+static int
+f2 (int f1line)
+{
+  return f3 (f1line, __LINE__) + 2;
+}
+
+static int
+f3 (int f1line, int f2line)
+{
+  struct info all[20];
+  struct bdata data;
+  int f3line;
+  int i;
+
+  data.all = &all[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test1: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  if (data.index < 3)
+    {
+      fprintf (stderr,
+	       "test1: not enough frames; got %zu, expected at least 3\n",
+	       data.index);
+      data.failed = 1;
+    }
+
+  check ("test1", 0, all, f3line, "f3", &data.failed);
+  check ("test1", 1, all, f2line, "f2", &data.failed);
+  check ("test1", 2, all, f1line, "test1", &data.failed);
+
+  printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
+
+  if (data.failed)
+    ++failures;
+
+  return failures;
+}
+
+/* Test the backtrace function with inlined functions.  */
+
+static inline int test2 (void) __attribute__ ((always_inline, unused));
+static inline int f12 (int) __attribute__ ((always_inline));
+static inline int f13 (int, int) __attribute__ ((always_inline));
+
+static inline int
+test2 (void)
+{
+  return f12 (__LINE__) + 1;
+}
+
+static inline int
+f12 (int f1line)
+{
+  return f13 (f1line, __LINE__) + 2;
+}
+
+static inline int
+f13 (int f1line, int f2line)
+{
+  struct info all[20];
+  struct bdata data;
+  int f3line;
+  int i;
+
+  data.all = &all[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test2: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  check ("test2", 0, all, f3line, "f13", &data.failed);
+  check ("test2", 1, all, f2line, "f12", &data.failed);
+  check ("test2", 2, all, f1line, "test2", &data.failed);
+
+  printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
+
+  if (data.failed)
+    ++failures;
+
+  return failures;
+}
+
+/* Test the backtrace_simple function with non-inlined functions.  */
+
+static int test3 (void) __attribute__ ((noinline, unused));
+static int f22 (int) __attribute__ ((noinline));
+static int f23 (int, int) __attribute__ ((noinline));
+
+static int
+test3 (void)
+{
+  return f22 (__LINE__) + 1;
+}
+
+static int
+f22 (int f1line)
+{
+  return f23 (f1line, __LINE__) + 2;
+}
+
+static int
+f23 (int f1line, int f2line)
+{
+  uintptr_t addrs[20];
+  struct sdata data;
+  int f3line;
+  int i;
+
+  data.addrs = &addrs[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test3: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  if (!data.failed)
+    {
+      struct info all[20];
+      struct bdata bdata;
+      int j;
+
+      bdata.all = &all[0];
+      bdata.index = 0;
+      bdata.max = 20;
+      bdata.failed = 0;
+
+      for (j = 0; j < 3; ++j)
+	{
+	  i = backtrace_pcinfo (state, addrs[j], callback_one,
+				error_callback_one, &bdata);
+	  if (i != 0)
+	    {
+	      fprintf (stderr,
+		       ("test3: unexpected return value "
+			"from backtrace_pcinfo %d\n"),
+		       i);
+	      bdata.failed = 1;
+	    }
+	  if (!bdata.failed && bdata.index != (size_t) (j + 1))
+	    {
+	      fprintf (stderr,
+		       ("wrong number of calls from backtrace_pcinfo "
+			"got %u expected %d\n"),
+		       (unsigned int) bdata.index, j + 1);
+	      bdata.failed = 1;
+	    }
+	}      
+
+      check ("test3", 0, all, f3line, "f23", &bdata.failed);
+      check ("test3", 1, all, f2line, "f22", &bdata.failed);
+      check ("test3", 2, all, f1line, "test3", &bdata.failed);
+
+      if (bdata.failed)
+	data.failed = 1;
+
+      for (j = 0; j < 3; ++j)
+	{
+	  struct symdata symdata;
+
+	  symdata.name = NULL;
+	  symdata.val = 0;
+	  symdata.size = 0;
+	  symdata.failed = 0;
+
+	  i = backtrace_syminfo (state, addrs[j], callback_three,
+				 error_callback_three, &symdata);
+	  if (i == 0)
+	    {
+	      fprintf (stderr,
+		       ("test3: [%d]: unexpected return value "
+			"from backtrace_syminfo %d\n"),
+		       j, i);
+	      symdata.failed = 1;
+	    }
+
+	  if (!symdata.failed)
+	    {
+	      const char *expected;
+
+	      switch (j)
+		{
+		case 0:
+		  expected = "f23";
+		  break;
+		case 1:
+		  expected = "f22";
+		  break;
+		case 2:
+		  expected = "test3";
+		  break;
+		default:
+		  assert (0);
+		}
+
+	      if (symdata.name == NULL)
+		{
+		  fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
+		  symdata.failed = 1;
+		}
+	      /* Use strncmp, not strcmp, because GCC might create a
+		 clone.  */
+	      else if (strncmp (symdata.name, expected, strlen (expected))
+		       != 0)
+		{
+		  fprintf (stderr,
+			   ("test3: [%d]: unexpected syminfo name "
+			    "got %s expected %s\n"),
+			   j, symdata.name, expected);
+		  symdata.failed = 1;
+		}
+	    }
+
+	  if (symdata.failed)
+	    data.failed = 1;
+	}
+    }
+
+  printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
+
+  if (data.failed)
+    ++failures;
+
+  return failures;
+}
+
+/* Test the backtrace_simple function with inlined functions.  */
+
+static inline int test4 (void) __attribute__ ((always_inline, unused));
+static inline int f32 (int) __attribute__ ((always_inline));
+static inline int f33 (int, int) __attribute__ ((always_inline));
+
+static inline int
+test4 (void)
+{
+  return f32 (__LINE__) + 1;
+}
+
+static inline int
+f32 (int f1line)
+{
+  return f33 (f1line, __LINE__) + 2;
+}
+
+static inline int
+f33 (int f1line, int f2line)
+{
+  uintptr_t addrs[20];
+  struct sdata data;
+  int f3line;
+  int i;
+
+  data.addrs = &addrs[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test3: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  if (!data.failed)
+    {
+      struct info all[20];
+      struct bdata bdata;
+
+      bdata.all = &all[0];
+      bdata.index = 0;
+      bdata.max = 20;
+      bdata.failed = 0;
+
+      i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,
+			    &bdata);
+      if (i != 0)
+	{
+	  fprintf (stderr,
+		   ("test4: unexpected return value "
+		    "from backtrace_pcinfo %d\n"),
+		   i);
+	  bdata.failed = 1;
+	}
+
+      check ("test4", 0, all, f3line, "f33", &bdata.failed);
+      check ("test4", 1, all, f2line, "f32", &bdata.failed);
+      check ("test4", 2, all, f1line, "test4", &bdata.failed);
+
+      if (bdata.failed)
+	data.failed = 1;
+    }
+
+  printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS");
+
+  if (data.failed)
+    ++failures;
+
+  return failures;
+}
+
+int global = 1;
+
+static int
+test5 (void)
+{
+  struct symdata symdata;
+  int i;
+  uintptr_t addr = (uintptr_t) &global;
+
+  if (sizeof (global) > 1)
+    addr += 1;
+
+  symdata.name = NULL;
+  symdata.val = 0;
+  symdata.size = 0;
+  symdata.failed = 0;
+
+  i = backtrace_syminfo (state, addr, callback_three,
+			 error_callback_three, &symdata);
+  if (i == 0)
+    {
+      fprintf (stderr,
+	       "test5: unexpected return value from backtrace_syminfo %d\n",
+	       i);
+      symdata.failed = 1;
+    }
+
+  if (!symdata.failed)
+    {
+      if (symdata.name == NULL)
+	{
+	  fprintf (stderr, "test5: NULL syminfo name\n");
+	  symdata.failed = 1;
+	}
+      else if (strcmp (symdata.name, "global") != 0)
+	{
+	  fprintf (stderr,
+		   "test5: unexpected syminfo name got %s expected %s\n",
+		   symdata.name, "global");
+	  symdata.failed = 1;
+	}
+      else if (symdata.val != (uintptr_t) &global)
+	{
+	  fprintf (stderr,
+		   "test5: unexpected syminfo value got %lx expected %lx\n",
+		   (unsigned long) symdata.val,
+		   (unsigned long) (uintptr_t) &global);
+	  symdata.failed = 1;
+	}
+      else if (symdata.size != sizeof (global))
+	{
+	  fprintf (stderr,
+		   "test5: unexpected syminfo size got %lx expected %lx\n",
+		   (unsigned long) symdata.size,
+		   (unsigned long) sizeof (global));
+	  symdata.failed = 1;
+	}
+    }
+
+  printf ("%s: backtrace_syminfo variable\n",
+	  symdata.failed ? "FAIL" : "PASS");
+
+  if (symdata.failed)
+    ++failures;
+
+  return failures;
+}
+
+static void
+error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
+		       int errnum)
+{
+  fprintf (stderr, "%s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fprintf (stderr, "\n");
+  exit (EXIT_FAILURE);
+}
+
+/* Run all the tests.  */
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv)
+{
+  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
+				  error_callback_create, NULL);
+
+#if BACKTRACE_SUPPORTED
+  test1 ();
+  test2 ();
+  test3 ();
+  test4 ();
+  test5 ();
+#endif
+
+  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/third_party/gofrontend/libbacktrace/config.h.in b/third_party/gofrontend/libbacktrace/config.h.in
new file mode 100644
index 0000000..87cb805
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/config.h.in
@@ -0,0 +1,134 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* ELF size: 32 or 64 */
+#undef BACKTRACE_ELF_SIZE
+
+/* Define to 1 if you have the __atomic functions */
+#undef HAVE_ATOMIC_FUNCTIONS
+
+/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
+   don't. */
+#undef HAVE_DECL_STRNLEN
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define if dl_iterate_phdr is available. */
+#undef HAVE_DL_ITERATE_PHDR
+
+/* Define to 1 if you have the fcntl function */
+#undef HAVE_FCNTL
+
+/* Define if getexecname is available. */
+#undef HAVE_GETEXECNAME
+
+/* Define if _Unwind_GetIPInfo is available. */
+#undef HAVE_GETIPINFO
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <link.h> header file. */
+#undef HAVE_LINK_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the __sync functions */
+#undef HAVE_SYNC_FUNCTIONS
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of `char', as computed by sizeof. */
+#undef SIZEOF_CHAR
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* The size of `void *', as computed by sizeof. */
+#undef SIZEOF_VOID_P
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
diff --git a/third_party/gofrontend/libbacktrace/configure b/third_party/gofrontend/libbacktrace/configure
new file mode 100755
index 0000000..f4f9d05
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/configure
@@ -0,0 +1,15156 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.64 for package-unused version-unused.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
+# Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1
+
+  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  # We cannot yet assume a decent shell, so we have to provide a
+	# neutralization value for shells without unset; and this also
+	# works around shells that cannot unset nonexistent variables.
+	BASH_ENV=/dev/null
+	ENV=/dev/null
+	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+	export CONFIG_SHELL
+	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='package-unused'
+PACKAGE_TARNAME='libbacktrace'
+PACKAGE_VERSION='version-unused'
+PACKAGE_STRING='package-unused version-unused'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="backtrace.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+NATIVE_FALSE
+NATIVE_TRUE
+BACKTRACE_USES_MALLOC
+ALLOC_FILE
+VIEW_FILE
+BACKTRACE_SUPPORTED
+FORMAT_FILE
+BACKTRACE_SUPPORTS_THREADS
+PIC_FLAG
+WARN_FLAGS
+EXTRA_FLAGS
+BACKTRACE_FILE
+multi_basedir
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+AR
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+SED
+LIBTOOL
+RANLIB
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+libtool_VERSION
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_maintainer_mode
+with_target_subdir
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+with_gnu_ld
+enable_libtool_lock
+enable_multilib
+with_system_libunwind
+enable_host_shared
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)	ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information."
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures package-unused version-unused to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/libbacktrace]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of package-unused version-unused:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-maintainer-mode  enable make rules and dependencies not useful
+			  (and sometimes confusing) to the casual installer
+  --enable-shared[=PKGS]  build shared libraries [default=no]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-multilib       build many library versions (default)
+  --enable-host-shared    build host code as shared libraries
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-target-subdir=SUBDIR      Configuring in a subdirectory for target
+  --with-pic              try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-system-libunwind use installed libunwind
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+package-unused configure version-unused
+generated by GNU Autoconf 2.64
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+	 return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+	    return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
+# --------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_c_compute_int ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if test "$cross_compiling" = yes; then
+    # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid; break
+else
+  as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=$ac_mid; break
+else
+  as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  ac_lo= ac_hi=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid
+else
+  as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in #((
+?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
+'') ac_retval=1 ;;
+esac
+  else
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+static long int longval () { return $2; }
+static unsigned long int ulongval () { return $2; }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (($2) < 0)
+    {
+      long int i = longval ();
+      if (i != ($2))
+	return 1;
+      fprintf (f, "%ld", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ($2))
+	return 1;
+      fprintf (f, "%lu", i);
+    }
+  /* Do not output a trailing newline, as this causes \r\n confusion
+     on some platforms.  */
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  echo >>conftest.val; read $3 <conftest.val; ac_retval=0
+else
+  ac_retval=1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f conftest.val
+
+  fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_compute_int
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR
+# ------------------------------------
+# Tests whether SYMBOL is declared, setting cache variable VAR accordingly.
+ac_fn_c_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_decl
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by package-unused $as_me version-unused, which was
+generated by GNU Autoconf 2.64.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  for ac_t in install-sh install.sh shtool; do
+    if test -f "$ac_dir/$ac_t"; then
+      ac_aux_dir=$ac_dir
+      ac_install_sh="$ac_aux_dir/$ac_t -c"
+      break 2
+    fi
+  done
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if test "${ac_cv_target+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+target_alias=${target_alias-$host_alias}
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    rm -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then :
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "C compiler cannot create executables
+See \`config.log' for more details." "$LINENO" 5; }; }
+fi
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+  ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_minix_config_h" = x""yes; then :
+  MINIX=yes
+else
+  MINIX=
+fi
+
+
+  if test "$MINIX" = yes; then
+
+$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+
+$as_echo "#define _MINIX 1" >>confdefs.h
+
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if test "${ac_cv_safe_to_define___extensions__+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#	  define __EXTENSIONS__ 1
+	  $ac_includes_default
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_safe_to_define___extensions__=yes
+else
+  ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+  test $ac_cv_safe_to_define___extensions__ = yes &&
+    $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+  $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
+
+  $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
+
+  $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+  $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+
+
+libtool_VERSION=1:0:0
+
+
+# 1.11.1: Require that version of automake.
+# foreign: Don't require README, INSTALL, NEWS, etc.
+# no-define: Don't define PACKAGE and VERSION.
+# no-dependencies: Don't generate automatic dependencies.
+#    (because it breaks when using bootstrap-lean, since some of the
+#    headers are gone at "make install" time).
+# -Wall: Issue all automake warnings.
+# -Wno-portability: Don't warn about constructs supported by GNU make.
+#    (because GCC requires GNU make anyhow).
+am__api_version='1.11'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
+    as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      as_fn_error "ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+  [\\/$]* | ?:[\\/]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='libbacktrace'
+ VERSION='version-unused'
+
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+    # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+   if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+
+# Check whether --with-target-subdir was given.
+if test "${with_target_subdir+set}" = set; then :
+  withval=$with_target_subdir;
+fi
+
+
+# We must force CC to /not/ be precious variables; otherwise
+# the wrong, non-multilib-adjusted value will be used in multilibs.
+# As a side effect, we have to subst CFLAGS ourselves.
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    rm -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+case "$AWK" in
+"") as_fn_error "can't build without awk" "$LINENO" 5 ;;
+esac
+
+case `pwd` in
+  *\ * | *\	*)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.2.7a'
+macro_revision='1.3134'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`print -r -- -n 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO ""
+}
+
+case "$ECHO" in
+  printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+  print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+  *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if test "${ac_cv_path_SED+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if test "${ac_cv_path_FGREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+   then ac_cv_path_FGREP="$GREP -F"
+   else
+     if test -z "$FGREP"; then
+  ac_path_FGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in fgrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+  # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'FGREP' >> "conftest.nl"
+    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_FGREP="$ac_path_FGREP"
+      ac_path_FGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_FGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_FGREP"; then
+    as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_FGREP=$FGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if test "${lt_cv_path_NM+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+	*/dev/null* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in dumpbin "link -dump"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DUMPBIN+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DUMPBIN"; then
+  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$DUMPBIN" && break
+  done
+fi
+if test -z "$DUMPBIN"; then
+  ac_ct_DUMPBIN=$DUMPBIN
+  for ac_prog in dumpbin "link -dump"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DUMPBIN"; then
+  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_DUMPBIN" && break
+done
+
+  if test "x$ac_ct_DUMPBIN" = x; then
+    DUMPBIN=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DUMPBIN=$ac_ct_DUMPBIN
+  fi
+fi
+
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if test "${lt_cv_nm_interface+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+  cat conftest.out >&5
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[	 ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \
+	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OBJDUMP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if test "${lt_cv_deplibs_check_method+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_AR="ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDEGRST]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK '"\
+"     {last_section=section; section=\$ 3};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+const struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_save_LIBS="$LIBS"
+	  lt_save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$lt_save_LIBS"
+	  CFLAGS="$lt_save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&5
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE="32"
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE="64"
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    case `/usr/bin/file conftest.o` in
+	      *x86-64*)
+		LD="${LD-ld} -m elf32_x86_64"
+		;;
+	      *)
+		LD="${LD-ld} -m elf_i386"
+		;;
+	    esac
+	    ;;
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if test "${lt_cv_cc_needs_belf+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_cc_needs_belf=yes
+else
+  lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+  case $host_os in
+    rhapsody* | darwin*)
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DSYMUTIL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_NMEDIT+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+  ac_ct_NMEDIT=$NMEDIT
+  # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_NMEDIT"; then
+  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_NMEDIT="nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_NMEDIT" = x; then
+    NMEDIT=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    NMEDIT=$ac_ct_NMEDIT
+  fi
+else
+  NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_LIPO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LIPO"; then
+  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+  ac_ct_LIPO=$LIPO
+  # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_LIPO"; then
+  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_LIPO="lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_LIPO" = x; then
+    LIPO=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIPO=$ac_ct_LIPO
+  fi
+else
+  LIPO="$ac_cv_prog_LIPO"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL"; then
+  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+  ac_ct_OTOOL=$OTOOL
+  # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL"; then
+  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OTOOL="otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL" = x; then
+    OTOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL=$ac_ct_OTOOL
+  fi
+else
+  OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL64+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL64"; then
+  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+  ac_ct_OTOOL64=$OTOOL64
+  # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL64"; then
+  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OTOOL64="otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL64" = x; then
+    OTOOL64=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL64=$ac_ct_OTOOL64
+  fi
+else
+  OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if test "${lt_cv_apple_cc_single_mod+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&5
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if test "${lt_cv_ld_exported_symbols_list+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_ld_exported_symbols_list=yes
+else
+  lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+$as_echo_n "checking for -force_load linker flag... " >&6; }
+if test "${lt_cv_ld_force_load+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+      echo "$AR cru libconftest.a conftest.o" >&5
+      $AR cru libconftest.a conftest.o 2>&5
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then
+	lt_cv_ld_force_load=yes
+      else
+	cat conftest.err >&5
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+$as_echo "$lt_cv_ld_force_load" >&6; }
+    case $host_os in
+    rhapsody* | darwin1.[012])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+	10.[012]*)
+	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+	10.*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+
+for ac_header in dlfcn.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+# Set options
+# Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_shared=no
+fi
+
+
+
+
+
+
+
+
+
+
+        enable_dlopen=no
+
+
+  enable_win32_dll=no
+
+
+
+  # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+  withval=$with_pic; pic_mode="$withval"
+else
+  pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+  # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if test "${lt_cv_objdir+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+  case $cc_basename in
+  nvcc*)
+    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+  *)
+    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+  esac
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+
+
+
+  lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      lt_prog_compiler_wl='-Xlinker '
+      lt_prog_compiler_pic='-Xcompiler -fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      else
+	lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-KPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='--shared'
+	lt_prog_compiler_static='--static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fpic'
+	lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-qpic'
+	lt_prog_compiler_static='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ F* | *Sun*Fortran*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl=''
+	  ;;
+	*Sun\ C*)
+	  # Sun C 5.9
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Wl,'
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+	lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+	lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	lt_prog_compiler_pic='-Kconform_pic'
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5
+$as_echo "$lt_prog_compiler_pic" >&6; }
+
+
+
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if test "${lt_cv_prog_compiler_pic_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test "${lt_cv_prog_compiler_static_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  always_export_symbols=no
+  archive_cmds=
+  archive_expsym_cmds=
+  compiler_needs_object=no
+  enable_shared_with_static_runtimes=no
+  export_dynamic_flag_spec=
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic=no
+  hardcode_direct=no
+  hardcode_direct_absolute=no
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_flag_spec_ld=
+  hardcode_libdir_separator=
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  inherit_rpath=no
+  link_all_deplibs=unknown
+  module_cmds=
+  module_expsym_cmds=
+  old_archive_from_new_cmds=
+  old_archive_from_expsyms_cmds=
+  thread_safe_flag_spec=
+  whole_archive_flag_spec=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+	  *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	allow_undefined_flag=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      export_dynamic_flag_spec='${wl}--export-all-symbols'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    haiku*)
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      link_all_deplibs=yes
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  whole_archive_flag_spec=
+	  tmp_sharedflag='--shared' ;;
+	xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf* | bgf* | bgxlf* | mpixlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+	  hardcode_libdir_flag_spec=
+	  hardcode_libdir_flag_spec_ld='-rpath $libdir'
+	  archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        ld_shlibs=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    ld_shlibs=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	# Also, AIX nm treats weak defined symbols like other global
+	# defined symbols, whereas GNU nm marks them as "W".
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_direct_absolute=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      file_list_spec='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[012]|aix4.[012].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  hardcode_direct=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L=yes
+	  hardcode_libdir_flag_spec='-L$libdir'
+	  hardcode_libdir_separator=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      export_dynamic_flag_spec='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+	  allow_undefined_flag="-z nodefs"
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+	 hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  no_undefined_flag=' ${wl}-bernotok'
+	  allow_undefined_flag=' ${wl}-berok'
+	  if test "$with_gnu_ld" = yes; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    whole_archive_flag_spec='$convenience'
+	  fi
+	  archive_cmds_need_lc=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec=' '
+      allow_undefined_flag=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_from_new_cmds='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes=yes
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc=no
+  hardcode_direct=no
+  hardcode_automatic=yes
+  hardcode_shlibpath_var=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+  else
+    whole_archive_flag_spec=''
+  fi
+  link_all_deplibs=yes
+  allow_undefined_flag="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+  else
+  ld_shlibs=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_flag_spec_ld='+b $libdir'
+	hardcode_libdir_separator=:
+	hardcode_direct=yes
+	hardcode_direct_absolute=yes
+	export_dynamic_flag_spec='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+
+	  # Older versions of the 11.00 compiler do not understand -b yet
+	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+$as_echo_n "checking if $CC understands -b... " >&6; }
+if test "${lt_cv_prog_compiler__b+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler__b=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS -b"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler__b=yes
+       fi
+     else
+       lt_cv_prog_compiler__b=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+$as_echo "$lt_cv_prog_compiler__b" >&6; }
+
+if test x"$lt_cv_prog_compiler__b" = xyes; then
+    archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_separator=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  hardcode_direct=no
+	  hardcode_shlibpath_var=no
+	  ;;
+	*)
+	  hardcode_direct=yes
+	  hardcode_direct_absolute=yes
+	  export_dynamic_flag_spec='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  hardcode_minus_L=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+        save_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo(void) {}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+        LDFLAGS="$save_LDFLAGS"
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      inherit_rpath=yes
+      link_all_deplibs=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	hardcode_direct=yes
+	hardcode_shlibpath_var=no
+	hardcode_direct_absolute=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	  export_dynamic_flag_spec='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+	     archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     hardcode_libdir_flag_spec='-R$libdir'
+	     ;;
+	   *)
+	     archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  reload_cmds='$CC -r -o $output$reload_objs'
+	  hardcode_direct=no
+        ;;
+	motorola)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_shlibpath_var=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='${wl}-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='${wl}-z,text'
+      allow_undefined_flag='${wl}-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-R,$libdir'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	export_dynamic_flag_spec='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if test "${lt_cv_archive_cmds_need_lc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl
+	  pic_flag=$lt_prog_compiler_pic
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag
+	  allow_undefined_flag=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	  then
+	    lt_cv_archive_cmds_need_lc=no
+	  else
+	    lt_cv_archive_cmds_need_lc=yes
+	  fi
+	  allow_undefined_flag=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([A-Za-z]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[23].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+haiku*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  if test "${lt_cv_shlibpath_overrides_runpath+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+  lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+   test -n "$runpath_var" ||
+   test "X$hardcode_automatic" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink ||
+   test "$inherit_rpath" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+  if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+    ;;
+
+  *)
+    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = x""yes; then :
+  lt_cv_dlopen="shl_load"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_shl_load=yes
+else
+  ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = x""yes; then :
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_svld_dlopen=yes
+else
+  ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_dld_link=yes
+else
+  ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = x""yes; then :
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line 11092 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+void fnord () __attribute__((visibility("default")));
+#endif
+
+void fnord () { int i=42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line 11198 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+void fnord () __attribute__((visibility("default")));
+#endif
+
+void fnord () { int i=42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+    ;;
+  *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+  # Report which library types will actually be built
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[4-9]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+
+
+
+
+
+
+
+
+
+
+
+        ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+
+
+backtrace_supported=yes
+
+if test -n "${with_target_subdir}"; then
+  # We are compiling a GCC library.  We can assume that the unwind
+  # library exists.
+  # Default to --enable-multilib
+# Check whether --enable-multilib was given.
+if test "${enable_multilib+set}" = set; then :
+  enableval=$enable_multilib; case "$enableval" in
+  yes) multilib=yes ;;
+  no)  multilib=no ;;
+  *)   as_fn_error "bad value $enableval for multilib option" "$LINENO" 5 ;;
+ esac
+else
+  multilib=yes
+fi
+
+
+# We may get other options which we leave undocumented:
+# --with-target-subdir, --with-multisrctop, --with-multisubdir
+# See config-ml.in if you want the gory details.
+
+if test "$srcdir" = "."; then
+  if test "$with_target_subdir" != "."; then
+    multi_basedir="$srcdir/$with_multisrctop../.."
+  else
+    multi_basedir="$srcdir/$with_multisrctop.."
+  fi
+else
+  multi_basedir="$srcdir/.."
+fi
+
+
+# Even if the default multilib is not a cross compilation,
+# it may be that some of the other multilibs are.
+if test $cross_compiling = no && test $multilib = yes \
+   && test "x${with_multisubdir}" != x ; then
+   cross_compiling=maybe
+fi
+
+ac_config_commands="$ac_config_commands default-1"
+
+  BACKTRACE_FILE="backtrace.lo simple.lo"
+else
+  ac_fn_c_check_header_mongrel "$LINENO" "unwind.h" "ac_cv_header_unwind_h" "$ac_includes_default"
+if test "x$ac_cv_header_unwind_h" = x""yes; then :
+  ac_fn_c_check_func "$LINENO" "_Unwind_Backtrace" "ac_cv_func__Unwind_Backtrace"
+if test "x$ac_cv_func__Unwind_Backtrace" = x""yes; then :
+  BACKTRACE_FILE="backtrace.lo simple.lo"
+else
+  BACKTRACE_FILE="nounwind.lo"
+                    backtrace_supported=no
+fi
+
+else
+  BACKTRACE_FILE="nounwind.lo"
+     backtrace_supported=no
+fi
+
+
+fi
+
+
+EXTRA_FLAGS=
+if test -n "${with_target_subdir}"; then
+  EXTRA_FLAGS="-funwind-tables -frandom-seed=\$@"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -funwind-tables option" >&5
+$as_echo_n "checking for -funwind-tables option... " >&6; }
+if test "${libbacktrace_cv_c_unwind_tables+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold="$CFLAGS"
+     CFLAGS="$CFLAGS -funwind-tables"
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+static int f() { return 0; }
+int
+main ()
+{
+return f();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libbacktrace_cv_c_unwind_tables=yes
+else
+  libbacktrace_cv_c_unwind_tables=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+     CFLAGS="$CFLAGS_hold"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_c_unwind_tables" >&5
+$as_echo "$libbacktrace_cv_c_unwind_tables" >&6; }
+  if test "$libbacktrace_cv_c_unwind_tables" = "yes"; then
+    EXTRA_FLAGS=-funwind-tables
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -frandom-seed=string option" >&5
+$as_echo_n "checking for -frandom-seed=string option... " >&6; }
+if test "${libbacktrace_cv_c_random_seed_string+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold="$CFLAGS"
+     CFLAGS="$CFLAGS -frandom-seed=conftest.lo"
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libbacktrace_cv_c_random_seed_string=yes
+else
+  libbacktrace_cv_c_random_seed_string=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+     CFLAGS="$CFLAGS_hold"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_c_random_seed_string" >&5
+$as_echo "$libbacktrace_cv_c_random_seed_string" >&6; }
+  if test "$libbacktrace_cv_c_random_seed_string" = "yes"; then
+    EXTRA_FLAGS="$EXTRA_FLAGS -frandom-seed=\$@"
+  fi
+fi
+
+
+WARN_FLAGS=
+save_CFLAGS="$CFLAGS"
+for real_option in -W -Wall -Wwrite-strings -Wstrict-prototypes \
+			  -Wmissing-prototypes -Wold-style-definition \
+			  -Wmissing-format-attribute -Wcast-qual; do
+  # Do the check with the no- prefix removed since gcc silently
+  # accepts any -Wno-* option on purpose
+  case $real_option in
+    -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+    *) option=$real_option ;;
+  esac
+  as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $option" >&5
+$as_echo_n "checking whether $CC supports $option... " >&6; }
+if { as_var=$as_acx_Woption; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS="$option"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_acx_Woption=yes"
+else
+  eval "$as_acx_Woption=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+eval ac_res=\$$as_acx_Woption
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
+  WARN_FLAGS="$WARN_FLAGS${WARN_FLAGS:+ }$real_option"
+fi
+  done
+CFLAGS="$save_CFLAGS"
+
+
+if test -n "${with_target_subdir}"; then
+  WARN_FLAGS="$WARN_FLAGS -Werror"
+fi
+
+
+
+if test -n "${with_target_subdir}"; then
+
+
+# Check whether --with-system-libunwind was given.
+if test "${with_system_libunwind+set}" = set; then :
+  withval=$with_system_libunwind;
+fi
+
+  # If system-libunwind was not specifically set, pick a default setting.
+  if test x$with_system_libunwind = x; then
+    case ${target} in
+      ia64-*-hpux*) with_system_libunwind=yes ;;
+      *) with_system_libunwind=no ;;
+    esac
+  fi
+  # Based on system-libunwind and target, do we have ipinfo?
+  if  test x$with_system_libunwind = xyes; then
+    case ${target} in
+      ia64-*-*) have_unwind_getipinfo=no ;;
+      *) have_unwind_getipinfo=yes ;;
+    esac
+  else
+    # Darwin before version 9 does not have _Unwind_GetIPInfo.
+
+    case ${target} in
+      *-*-darwin[3-8]|*-*-darwin[3-8].*) have_unwind_getipinfo=no ;;
+      *) have_unwind_getipinfo=yes ;;
+    esac
+
+  fi
+
+  if test x$have_unwind_getipinfo = xyes; then
+
+$as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h
+
+  fi
+
+else
+  ac_save_CFFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -Werror-implicit-function-declaration"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _Unwind_GetIPInfo" >&5
+$as_echo_n "checking for _Unwind_GetIPInfo... " >&6; }
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "unwind.h"
+	struct _Unwind_Context *context;
+	int ip_before_insn = 0;
+int
+main ()
+{
+return _Unwind_GetIPInfo (context, &ip_before_insn);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  have_unwind_getipinfo=yes
+else
+  have_unwind_getipinfo=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  CFLAGS="$ac_save_CFLAGS"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_unwind_getipinfo" >&5
+$as_echo "$have_unwind_getipinfo" >&6; }
+  if test "$have_unwind_getipinfo" = "yes"; then
+
+$as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h
+
+  fi
+fi
+
+# When building as a target library, shared libraries may want to link
+# this in.  We don't want to provide another shared library to
+# complicate dependencies.  Instead, we just compile with -fPIC.
+PIC_FLAG=
+if test -n "${with_target_subdir}"; then
+  PIC_FLAG=-fPIC
+fi
+# Similarly, use -fPIC with --enable-host-shared:
+# Check whether --enable-host-shared was given.
+if test "${enable_host_shared+set}" = set; then :
+  enableval=$enable_host_shared; PIC_FLAG=-fPIC
+fi
+
+
+
+# Test for __sync support.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __sync extensions" >&5
+$as_echo_n "checking __sync extensions... " >&6; }
+if test "${libbacktrace_cv_sys_sync+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "${with_target_subdir}"; then
+   libbacktrace_cv_sys_sync=yes
+ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+int
+main ()
+{
+__sync_bool_compare_and_swap (&i, i, i);
+                       __sync_lock_test_and_set (&i, 1);
+                       __sync_lock_release (&i);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libbacktrace_cv_sys_sync=yes
+else
+  libbacktrace_cv_sys_sync=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_sync" >&5
+$as_echo "$libbacktrace_cv_sys_sync" >&6; }
+BACKTRACE_SUPPORTS_THREADS=0
+if test "$libbacktrace_cv_sys_sync" = "yes"; then
+  BACKTRACE_SUPPORTS_THREADS=1
+
+$as_echo "#define HAVE_SYNC_FUNCTIONS 1" >>confdefs.h
+
+fi
+
+
+# Test for __atomic support.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __atomic extensions" >&5
+$as_echo_n "checking __atomic extensions... " >&6; }
+if test "${libbacktrace_cv_sys_atomic+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "${with_target_subdir}"; then
+   libbacktrace_cv_sys_atomic=yes
+ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+int
+main ()
+{
+__atomic_load_n (&i, __ATOMIC_ACQUIRE);
+		       __atomic_store_n (&i, 1, __ATOMIC_RELEASE);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libbacktrace_cv_sys_atomic=yes
+else
+  libbacktrace_cv_sys_atomic=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_atomic" >&5
+$as_echo "$libbacktrace_cv_sys_atomic" >&6; }
+if test "$libbacktrace_cv_sys_atomic" = "yes"; then
+
+$as_echo "#define HAVE_ATOMIC_FUNCTIONS 1" >>confdefs.h
+
+fi
+
+# The library needs to be able to read the executable itself.  Compile
+# a file to determine the executable format.  The awk script
+# filetype.awk prints out the file type.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking output filetype" >&5
+$as_echo_n "checking output filetype... " >&6; }
+if test "${libbacktrace_cv_sys_filetype+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  filetype=
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+int
+main ()
+{
+int j;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  filetype=`${AWK} -f $srcdir/filetype.awk conftest.$ac_objext`
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "compiler failed
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+libbacktrace_cv_sys_filetype=$filetype
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_filetype" >&5
+$as_echo "$libbacktrace_cv_sys_filetype" >&6; }
+
+# Match the file type to decide what files to compile.
+FORMAT_FILE=
+case "$libbacktrace_cv_sys_filetype" in
+elf*) FORMAT_FILE="elf.lo" ;;
+*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not determine output file type" >&5
+$as_echo "$as_me: WARNING: could not determine output file type" >&2;}
+   FORMAT_FILE="unknown.lo"
+   backtrace_supported=no
+   ;;
+esac
+
+
+# ELF defines.
+elfsize=
+case "$libbacktrace_cv_sys_filetype" in
+elf32) elfsize=32 ;;
+elf64) elfsize=64 ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define BACKTRACE_ELF_SIZE $elfsize
+_ACEOF
+
+
+BACKTRACE_SUPPORTED=0
+if test "$backtrace_supported" = "yes"; then
+  BACKTRACE_SUPPORTED=1
+fi
+
+
+
+
+inttype_headers=`echo inttypes.h sys/inttypes.h  | sed -e 's/,/ /g'`
+
+acx_cv_header_stdint=stddef.h
+acx_cv_header_stdint_kind="(already complete)"
+for i in stdint.h $inttype_headers; do
+  unset ac_cv_type_uintptr_t
+  unset ac_cv_type_uintmax_t
+  unset ac_cv_type_int_least32_t
+  unset ac_cv_type_int_fast32_t
+  unset ac_cv_type_uint64_t
+  $as_echo_n "looking for a compliant stdint.h in $i, " >&6
+  ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "#include <sys/types.h>
+#include <$i>
+"
+if test "x$ac_cv_type_uintmax_t" = x""yes; then :
+  acx_cv_header_stdint=$i
+else
+  continue
+fi
+
+  ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#include <sys/types.h>
+#include <$i>
+"
+if test "x$ac_cv_type_uintptr_t" = x""yes; then :
+
+else
+  acx_cv_header_stdint_kind="(mostly complete)"
+fi
+
+  ac_fn_c_check_type "$LINENO" "int_least32_t" "ac_cv_type_int_least32_t" "#include <sys/types.h>
+#include <$i>
+"
+if test "x$ac_cv_type_int_least32_t" = x""yes; then :
+
+else
+  acx_cv_header_stdint_kind="(mostly complete)"
+fi
+
+  ac_fn_c_check_type "$LINENO" "int_fast32_t" "ac_cv_type_int_fast32_t" "#include <sys/types.h>
+#include <$i>
+"
+if test "x$ac_cv_type_int_fast32_t" = x""yes; then :
+
+else
+  acx_cv_header_stdint_kind="(mostly complete)"
+fi
+
+  ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include <sys/types.h>
+#include <$i>
+"
+if test "x$ac_cv_type_uint64_t" = x""yes; then :
+
+else
+  acx_cv_header_stdint_kind="(lacks uint64_t)"
+fi
+
+  break
+done
+if test "$acx_cv_header_stdint" = stddef.h; then
+  acx_cv_header_stdint_kind="(lacks uintmax_t)"
+  for i in stdint.h $inttype_headers; do
+    unset ac_cv_type_uintptr_t
+    unset ac_cv_type_uint32_t
+    unset ac_cv_type_uint64_t
+    $as_echo_n "looking for an incomplete stdint.h in $i, " >&6
+    ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "#include <sys/types.h>
+#include <$i>
+"
+if test "x$ac_cv_type_uint32_t" = x""yes; then :
+  acx_cv_header_stdint=$i
+else
+  continue
+fi
+
+    ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include <sys/types.h>
+#include <$i>
+"
+if test "x$ac_cv_type_uint64_t" = x""yes; then :
+
+fi
+
+    ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#include <sys/types.h>
+#include <$i>
+"
+if test "x$ac_cv_type_uintptr_t" = x""yes; then :
+
+fi
+
+    break
+  done
+fi
+if test "$acx_cv_header_stdint" = stddef.h; then
+  acx_cv_header_stdint_kind="(u_intXX_t style)"
+  for i in sys/types.h $inttype_headers; do
+    unset ac_cv_type_u_int32_t
+    unset ac_cv_type_u_int64_t
+    $as_echo_n "looking for u_intXX_t types in $i, " >&6
+    ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "#include <sys/types.h>
+#include <$i>
+"
+if test "x$ac_cv_type_u_int32_t" = x""yes; then :
+  acx_cv_header_stdint=$i
+else
+  continue
+fi
+
+    ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "#include <sys/types.h>
+#include <$i>
+"
+if test "x$ac_cv_type_u_int64_t" = x""yes; then :
+
+fi
+
+    break
+  done
+fi
+if test "$acx_cv_header_stdint" = stddef.h; then
+  acx_cv_header_stdint_kind="(using manual detection)"
+fi
+
+test -z "$ac_cv_type_uintptr_t" && ac_cv_type_uintptr_t=no
+test -z "$ac_cv_type_uint64_t" && ac_cv_type_uint64_t=no
+test -z "$ac_cv_type_u_int64_t" && ac_cv_type_u_int64_t=no
+test -z "$ac_cv_type_int_least32_t" && ac_cv_type_int_least32_t=no
+test -z "$ac_cv_type_int_fast32_t" && ac_cv_type_int_fast32_t=no
+
+# ----------------- Summarize what we found so far
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what to include in gstdint.h" >&5
+$as_echo_n "checking what to include in gstdint.h... " >&6; }
+
+case `$as_basename -- gstdint.h ||
+$as_expr X/gstdint.h : '.*/\([^/][^/]*\)/*$' \| \
+	 Xgstdint.h : 'X\(//\)$' \| \
+	 Xgstdint.h : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/gstdint.h |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'` in
+  stdint.h) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: are you sure you want it there?" >&5
+$as_echo "$as_me: WARNING: are you sure you want it there?" >&2;} ;;
+  inttypes.h) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: are you sure you want it there?" >&5
+$as_echo "$as_me: WARNING: are you sure you want it there?" >&2;} ;;
+  *) ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_header_stdint $acx_cv_header_stdint_kind" >&5
+$as_echo "$acx_cv_header_stdint $acx_cv_header_stdint_kind" >&6; }
+
+# ----------------- done included file, check C basic types --------
+
+# Lacking an uintptr_t?  Test size of void *
+case "$acx_cv_header_stdint:$ac_cv_type_uintptr_t" in
+  stddef.h:* | *:no) # The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+$as_echo_n "checking size of void *... " >&6; }
+if test "${ac_cv_sizeof_void_p+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_void_p" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (void *)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_void_p=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+$as_echo "$ac_cv_sizeof_void_p" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
+_ACEOF
+
+ ;;
+esac
+
+# Lacking an uint64_t?  Test size of long
+case "$acx_cv_header_stdint:$ac_cv_type_uint64_t:$ac_cv_type_u_int64_t" in
+  stddef.h:*:* | *:no:no) # The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
+$as_echo_n "checking size of long... " >&6; }
+if test "${ac_cv_sizeof_long+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_long" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (long)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_long=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
+$as_echo "$ac_cv_sizeof_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+ ;;
+esac
+
+if test $acx_cv_header_stdint = stddef.h; then
+  # Lacking a good header?  Test size of everything and deduce all types.
+  # The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
+$as_echo_n "checking size of int... " >&6; }
+if test "${ac_cv_sizeof_int+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_int" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (int)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_int=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
+$as_echo "$ac_cv_sizeof_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+  # The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
+$as_echo_n "checking size of short... " >&6; }
+if test "${ac_cv_sizeof_short+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_short" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (short)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_short=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
+$as_echo "$ac_cv_sizeof_short" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+_ACEOF
+
+
+  # The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char" >&5
+$as_echo_n "checking size of char... " >&6; }
+if test "${ac_cv_sizeof_char+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_char" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (char)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_char=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5
+$as_echo "$ac_cv_sizeof_char" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_CHAR $ac_cv_sizeof_char
+_ACEOF
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int8_t" >&5
+$as_echo_n "checking for type equivalent to int8_t... " >&6; }
+  case "$ac_cv_sizeof_char" in
+    1) acx_cv_type_int8_t=char ;;
+    *) as_fn_error "no 8-bit type, please report a bug" "$LINENO" 5
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int8_t" >&5
+$as_echo "$acx_cv_type_int8_t" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int16_t" >&5
+$as_echo_n "checking for type equivalent to int16_t... " >&6; }
+  case "$ac_cv_sizeof_int:$ac_cv_sizeof_short" in
+    2:*) acx_cv_type_int16_t=int ;;
+    *:2) acx_cv_type_int16_t=short ;;
+    *) as_fn_error "no 16-bit type, please report a bug" "$LINENO" 5
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int16_t" >&5
+$as_echo "$acx_cv_type_int16_t" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int32_t" >&5
+$as_echo_n "checking for type equivalent to int32_t... " >&6; }
+  case "$ac_cv_sizeof_int:$ac_cv_sizeof_long" in
+    4:*) acx_cv_type_int32_t=int ;;
+    *:4) acx_cv_type_int32_t=long ;;
+    *) as_fn_error "no 32-bit type, please report a bug" "$LINENO" 5
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int32_t" >&5
+$as_echo "$acx_cv_type_int32_t" >&6; }
+fi
+
+# These tests are here to make the output prettier
+
+if test "$ac_cv_type_uint64_t" != yes && test "$ac_cv_type_u_int64_t" != yes; then
+  case "$ac_cv_sizeof_long" in
+    8) acx_cv_type_int64_t=long ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int64_t" >&5
+$as_echo_n "checking for type equivalent to int64_t... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${acx_cv_type_int64_t-'using preprocessor symbols'}" >&5
+$as_echo "${acx_cv_type_int64_t-'using preprocessor symbols'}" >&6; }
+fi
+
+# Now we can use the above types
+
+if test "$ac_cv_type_uintptr_t" != yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to intptr_t" >&5
+$as_echo_n "checking for type equivalent to intptr_t... " >&6; }
+  case $ac_cv_sizeof_void_p in
+    2) acx_cv_type_intptr_t=int16_t ;;
+    4) acx_cv_type_intptr_t=int32_t ;;
+    8) acx_cv_type_intptr_t=int64_t ;;
+    *) as_fn_error "no equivalent for intptr_t, please report a bug" "$LINENO" 5
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_intptr_t" >&5
+$as_echo "$acx_cv_type_intptr_t" >&6; }
+fi
+
+# ----------------- done all checks, emit header -------------
+ac_config_commands="$ac_config_commands gstdint.h"
+
+
+
+
+for ac_header in sys/mman.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_mman_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_MMAN_H 1
+_ACEOF
+
+fi
+
+done
+
+if test "$ac_cv_header_sys_mman_h" = "no"; then
+  have_mmap=no
+else
+  if test -n "${with_target_subdir}"; then
+    # When built as a GCC target library, we can't do a link test.  We
+    # simply assume that if we have mman.h, we have mmap.
+    have_mmap=yes
+  else
+    ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap"
+if test "x$ac_cv_func_mmap" = x""yes; then :
+  have_mmap=yes
+else
+  have_mmap=no
+fi
+
+  fi
+fi
+if test "$have_mmap" = "no"; then
+  VIEW_FILE=read.lo
+  ALLOC_FILE=alloc.lo
+else
+  VIEW_FILE=mmapio.lo
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/mman.h>
+#if !defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
+  #error no MAP_ANONYMOUS
+#endif
+
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ALLOC_FILE=mmap.lo
+else
+  ALLOC_FILE=alloc.lo
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+
+
+
+BACKTRACE_USES_MALLOC=0
+if test "$ALLOC_FILE" = "alloc.lo"; then
+  BACKTRACE_USES_MALLOC=1
+fi
+
+
+# Check for dl_iterate_phdr.
+for ac_header in link.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "link.h" "ac_cv_header_link_h" "$ac_includes_default"
+if test "x$ac_cv_header_link_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINK_H 1
+_ACEOF
+
+fi
+
+done
+
+if test "$ac_cv_header_link_h" = "no"; then
+  have_dl_iterate_phdr=no
+else
+  if test -n "${with_target_subdir}"; then
+    # When built as a GCC target library, we can't do a link test.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <link.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "dl_iterate_phdr" >/dev/null 2>&1; then :
+  have_dl_iterate_phdr=yes
+else
+  have_dl_iterate_phdr=no
+fi
+rm -f conftest*
+
+    case "${host}" in
+    *-*-solaris2.10*)
+        # Avoid dl_iterate_phdr on Solaris 10, where it is in the
+    	# header file but is only in -ldl.
+	have_dl_iterate_phdr=no ;;
+    esac
+  else
+    ac_fn_c_check_func "$LINENO" "dl_iterate_phdr" "ac_cv_func_dl_iterate_phdr"
+if test "x$ac_cv_func_dl_iterate_phdr" = x""yes; then :
+  have_dl_iterate_phdr=yes
+else
+  have_dl_iterate_phdr=no
+fi
+
+  fi
+fi
+if test "$have_dl_iterate_phdr" = "yes"; then
+
+$as_echo "#define HAVE_DL_ITERATE_PHDR 1" >>confdefs.h
+
+fi
+
+# Check for the fcntl function.
+if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   *-*-mingw*) have_fcntl=no ;;
+   *) have_fcntl=yes ;;
+   esac
+else
+  ac_fn_c_check_func "$LINENO" "fcntl" "ac_cv_func_fcntl"
+if test "x$ac_cv_func_fcntl" = x""yes; then :
+  have_fcntl=yes
+else
+  have_fcntl=no
+fi
+
+fi
+if test "$have_fcntl" = "yes"; then
+
+$as_echo "#define HAVE_FCNTL 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_decl "$LINENO" "strnlen" "ac_cv_have_decl_strnlen" "$ac_includes_default"
+if test "x$ac_cv_have_decl_strnlen" = x""yes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STRNLEN $ac_have_decl
+_ACEOF
+
+
+# Check for getexecname function.
+if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   *-*-solaris2*) have_getexecname=yes ;;
+   *) have_getexecname=no ;;
+   esac
+else
+  ac_fn_c_check_func "$LINENO" "getexecname" "ac_cv_func_getexecname"
+if test "x$ac_cv_func_getexecname" = x""yes; then :
+  have_getexecname=yes
+else
+  have_getexecname=no
+fi
+
+fi
+if test "$have_getexecname" = "yes"; then
+
+$as_echo "#define HAVE_GETEXECNAME 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether tests can run" >&5
+$as_echo_n "checking whether tests can run... " >&6; }
+if test "${libbacktrace_cv_sys_native+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  libbacktrace_cv_sys_native=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  libbacktrace_cv_sys_native=yes
+else
+  libbacktrace_cv_sys_native=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_native" >&5
+$as_echo "$libbacktrace_cv_sys_native" >&6; }
+ if test "$libbacktrace_cv_sys_native" = "yes"; then
+  NATIVE_TRUE=
+  NATIVE_FALSE='#'
+else
+  NATIVE_TRUE='#'
+  NATIVE_FALSE=
+fi
+
+
+if test "${multilib}" = "yes"; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+ac_config_files="$ac_config_files Makefile backtrace-supported.h"
+
+
+# We need multilib support, but only if configuring for the target.
+ac_config_commands="$ac_config_commands default"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+  as_fn_error "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${NATIVE_TRUE}" && test -z "${NATIVE_FALSE}"; then
+  as_fn_error "conditional \"NATIVE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by package-unused $as_me version-unused, which was
+generated by GNU Autoconf 2.64.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+package-unused config.status version-unused
+configured by $0, generated by GNU Autoconf 2.64,
+  with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+fix_srcfile_path='`$ECHO "$fix_srcfile_path" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in SHELL \
+ECHO \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+AR \
+AR_FLAGS \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_wl \
+lt_prog_compiler_pic \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_flag_spec_ld \
+hardcode_libdir_separator \
+fix_srcfile_path \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'
+
+
+
+
+srcdir="$srcdir"
+host="$host"
+target="$target"
+with_multisubdir="$with_multisubdir"
+with_multisrctop="$with_multisrctop"
+with_target_subdir="$with_target_subdir"
+ac_configure_args="${multilib_arg} ${ac_configure_args}"
+multi_basedir="$multi_basedir"
+CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+CC="$CC"
+CXX="$CXX"
+GFORTRAN="$GFORTRAN"
+GCJ="$GCJ"
+
+GCC="$GCC"
+CC="$CC"
+acx_cv_header_stdint="$acx_cv_header_stdint"
+acx_cv_type_int8_t="$acx_cv_type_int8_t"
+acx_cv_type_int16_t="$acx_cv_type_int16_t"
+acx_cv_type_int32_t="$acx_cv_type_int32_t"
+acx_cv_type_int64_t="$acx_cv_type_int64_t"
+acx_cv_type_intptr_t="$acx_cv_type_intptr_t"
+ac_cv_type_uintmax_t="$ac_cv_type_uintmax_t"
+ac_cv_type_uintptr_t="$ac_cv_type_uintptr_t"
+ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
+ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
+ac_cv_type_u_int32_t="$ac_cv_type_u_int32_t"
+ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
+ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
+ac_cv_sizeof_void_p="$ac_cv_sizeof_void_p"
+
+
+# Variables needed in config.status (file generation) which aren't already
+# passed by autoconf.
+SUBDIRS="$SUBDIRS"
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+    "gstdint.h") CONFIG_COMMANDS="$CONFIG_COMMANDS gstdint.h" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "backtrace-supported.h") CONFIG_FILES="$CONFIG_FILES backtrace-supported.h" ;;
+    "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
+
+  *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\).*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\).*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || as_fn_error "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_t"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+    } >"$tmp/config.h" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$tmp/config.h" "$ac_file" \
+	|| as_fn_error "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=""
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking.  This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  case $xsi_shell in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+  func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+  # positional parameters, so assign one to ordinary parameter first.
+  func_stripname_result=${3}
+  func_stripname_result=${func_stripname_result#"${1}"}
+  func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=${1%%=*}
+  func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  case ${1} in
+    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+    *)    func_lo2o_result=${1} ;;
+  esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=$(( $* ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=${#1}
+}
+
+_LT_EOF
+    ;;
+  *) # Bourne compatible functions.
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result=`$ECHO "${1}" | $SED "$basename"`
+}
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+  case ${2} in
+    .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+    *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+  esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[^=]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=`$ECHO "${1}" | $SED "$my_sed_long_opt"`
+  func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=`expr "$@"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$1+=\$2"
+}
+_LT_EOF
+    ;;
+  *)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$1=\$$1\$2"
+}
+
+_LT_EOF
+    ;;
+  esac
+
+
+  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+ ;;
+    "default-1":C)
+# Only add multilib support code if we just rebuilt the top-level
+# Makefile.
+case " $CONFIG_FILES " in
+ *" Makefile "*)
+   ac_file=Makefile . ${multi_basedir}/config-ml.in
+   ;;
+esac ;;
+    "gstdint.h":C)
+if test "$GCC" = yes; then
+  echo "/* generated for " `$CC --version | sed 1q` "*/" > tmp-stdint.h
+else
+  echo "/* generated for $CC */" > tmp-stdint.h
+fi
+
+sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+  #ifndef GCC_GENERATED_STDINT_H
+  #define GCC_GENERATED_STDINT_H 1
+
+  #include <sys/types.h>
+EOF
+
+if test "$acx_cv_header_stdint" != stdint.h; then
+  echo "#include <stddef.h>" >> tmp-stdint.h
+fi
+if test "$acx_cv_header_stdint" != stddef.h; then
+  echo "#include <$acx_cv_header_stdint>" >> tmp-stdint.h
+fi
+
+sed 's/^ *//' >> tmp-stdint.h <<EOF
+  /* glibc uses these symbols as guards to prevent redefinitions.  */
+  #ifdef __int8_t_defined
+  #define _INT8_T
+  #define _INT16_T
+  #define _INT32_T
+  #endif
+  #ifdef __uint32_t_defined
+  #define _UINT32_T
+  #endif
+
+EOF
+
+# ----------------- done header, emit basic int types -------------
+if test "$acx_cv_header_stdint" = stddef.h; then
+  sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    #ifndef _UINT8_T
+    #define _UINT8_T
+    #ifndef __uint8_t_defined
+    #define __uint8_t_defined
+    #ifndef uint8_t
+    typedef unsigned $acx_cv_type_int8_t uint8_t;
+    #endif
+    #endif
+    #endif
+
+    #ifndef _UINT16_T
+    #define _UINT16_T
+    #ifndef __uint16_t_defined
+    #define __uint16_t_defined
+    #ifndef uint16_t
+    typedef unsigned $acx_cv_type_int16_t uint16_t;
+    #endif
+    #endif
+    #endif
+
+    #ifndef _UINT32_T
+    #define _UINT32_T
+    #ifndef __uint32_t_defined
+    #define __uint32_t_defined
+    #ifndef uint32_t
+    typedef unsigned $acx_cv_type_int32_t uint32_t;
+    #endif
+    #endif
+    #endif
+
+    #ifndef _INT8_T
+    #define _INT8_T
+    #ifndef __int8_t_defined
+    #define __int8_t_defined
+    #ifndef int8_t
+    typedef $acx_cv_type_int8_t int8_t;
+    #endif
+    #endif
+    #endif
+
+    #ifndef _INT16_T
+    #define _INT16_T
+    #ifndef __int16_t_defined
+    #define __int16_t_defined
+    #ifndef int16_t
+    typedef $acx_cv_type_int16_t int16_t;
+    #endif
+    #endif
+    #endif
+
+    #ifndef _INT32_T
+    #define _INT32_T
+    #ifndef __int32_t_defined
+    #define __int32_t_defined
+    #ifndef int32_t
+    typedef $acx_cv_type_int32_t int32_t;
+    #endif
+    #endif
+    #endif
+EOF
+elif test "$ac_cv_type_u_int32_t" = yes; then
+  sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    /* int8_t int16_t int32_t defined by inet code, we do the u_intXX types */
+    #ifndef _INT8_T
+    #define _INT8_T
+    #endif
+    #ifndef _INT16_T
+    #define _INT16_T
+    #endif
+    #ifndef _INT32_T
+    #define _INT32_T
+    #endif
+
+    #ifndef _UINT8_T
+    #define _UINT8_T
+    #ifndef __uint8_t_defined
+    #define __uint8_t_defined
+    #ifndef uint8_t
+    typedef u_int8_t uint8_t;
+    #endif
+    #endif
+    #endif
+
+    #ifndef _UINT16_T
+    #define _UINT16_T
+    #ifndef __uint16_t_defined
+    #define __uint16_t_defined
+    #ifndef uint16_t
+    typedef u_int16_t uint16_t;
+    #endif
+    #endif
+    #endif
+
+    #ifndef _UINT32_T
+    #define _UINT32_T
+    #ifndef __uint32_t_defined
+    #define __uint32_t_defined
+    #ifndef uint32_t
+    typedef u_int32_t uint32_t;
+    #endif
+    #endif
+    #endif
+EOF
+else
+  sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    /* Some systems have guard macros to prevent redefinitions, define them.  */
+    #ifndef _INT8_T
+    #define _INT8_T
+    #endif
+    #ifndef _INT16_T
+    #define _INT16_T
+    #endif
+    #ifndef _INT32_T
+    #define _INT32_T
+    #endif
+    #ifndef _UINT8_T
+    #define _UINT8_T
+    #endif
+    #ifndef _UINT16_T
+    #define _UINT16_T
+    #endif
+    #ifndef _UINT32_T
+    #define _UINT32_T
+    #endif
+EOF
+fi
+
+# ------------- done basic int types, emit int64_t types ------------
+if test "$ac_cv_type_uint64_t" = yes; then
+  sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    /* system headers have good uint64_t and int64_t */
+    #ifndef _INT64_T
+    #define _INT64_T
+    #endif
+    #ifndef _UINT64_T
+    #define _UINT64_T
+    #endif
+EOF
+elif test "$ac_cv_type_u_int64_t" = yes; then
+  sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    /* system headers have an u_int64_t (and int64_t) */
+    #ifndef _INT64_T
+    #define _INT64_T
+    #endif
+    #ifndef _UINT64_T
+    #define _UINT64_T
+    #ifndef __uint64_t_defined
+    #define __uint64_t_defined
+    #ifndef uint64_t
+    typedef u_int64_t uint64_t;
+    #endif
+    #endif
+    #endif
+EOF
+elif test -n "$acx_cv_type_int64_t"; then
+  sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    /* architecture has a 64-bit type, $acx_cv_type_int64_t */
+    #ifndef _INT64_T
+    #define _INT64_T
+    #ifndef int64_t
+    typedef $acx_cv_type_int64_t int64_t;
+    #endif
+    #endif
+    #ifndef _UINT64_T
+    #define _UINT64_T
+    #ifndef __uint64_t_defined
+    #define __uint64_t_defined
+    #ifndef uint64_t
+    typedef unsigned $acx_cv_type_int64_t uint64_t;
+    #endif
+    #endif
+    #endif
+EOF
+else
+  sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    /* some common heuristics for int64_t, using compiler-specific tests */
+    #if defined __STDC_VERSION__ && (__STDC_VERSION__-0) >= 199901L
+    #ifndef _INT64_T
+    #define _INT64_T
+    #ifndef __int64_t_defined
+    #ifndef int64_t
+    typedef long long int64_t;
+    #endif
+    #endif
+    #endif
+    #ifndef _UINT64_T
+    #define _UINT64_T
+    #ifndef uint64_t
+    typedef unsigned long long uint64_t;
+    #endif
+    #endif
+
+    #elif defined __GNUC__ && defined (__STDC__) && __STDC__-0
+    /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
+       does not implement __extension__.  But that compiler doesn't define
+       __GNUC_MINOR__.  */
+    # if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__)
+    # define __extension__
+    # endif
+
+    # ifndef _INT64_T
+    # define _INT64_T
+    # ifndef int64_t
+    __extension__ typedef long long int64_t;
+    # endif
+    # endif
+    # ifndef _UINT64_T
+    # define _UINT64_T
+    # ifndef uint64_t
+    __extension__ typedef unsigned long long uint64_t;
+    # endif
+    # endif
+
+    #elif !defined __STRICT_ANSI__
+    # if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__
+
+    #  ifndef _INT64_T
+    #  define _INT64_T
+    #  ifndef int64_t
+    typedef __int64 int64_t;
+    #  endif
+    #  endif
+    #  ifndef _UINT64_T
+    #  define _UINT64_T
+    #  ifndef uint64_t
+    typedef unsigned __int64 uint64_t;
+    #  endif
+    #  endif
+    # endif /* compiler */
+
+    #endif /* ANSI version */
+EOF
+fi
+
+# ------------- done int64_t types, emit intptr types ------------
+if test "$ac_cv_type_uintptr_t" != yes; then
+  sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    /* Define intptr_t based on sizeof(void*) = $ac_cv_sizeof_void_p */
+    #ifndef __uintptr_t_defined
+    #ifndef uintptr_t
+    typedef u$acx_cv_type_intptr_t uintptr_t;
+    #endif
+    #endif
+    #ifndef __intptr_t_defined
+    #ifndef intptr_t
+    typedef $acx_cv_type_intptr_t  intptr_t;
+    #endif
+    #endif
+EOF
+fi
+
+# ------------- done intptr types, emit int_least types ------------
+if test "$ac_cv_type_int_least32_t" != yes; then
+  sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    /* Define int_least types */
+    typedef int8_t     int_least8_t;
+    typedef int16_t    int_least16_t;
+    typedef int32_t    int_least32_t;
+    #ifdef _INT64_T
+    typedef int64_t    int_least64_t;
+    #endif
+
+    typedef uint8_t    uint_least8_t;
+    typedef uint16_t   uint_least16_t;
+    typedef uint32_t   uint_least32_t;
+    #ifdef _UINT64_T
+    typedef uint64_t   uint_least64_t;
+    #endif
+EOF
+fi
+
+# ------------- done intptr types, emit int_fast types ------------
+if test "$ac_cv_type_int_fast32_t" != yes; then
+      sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    /* Define int_fast types.  short is often slow */
+    typedef int8_t       int_fast8_t;
+    typedef int          int_fast16_t;
+    typedef int32_t      int_fast32_t;
+    #ifdef _INT64_T
+    typedef int64_t      int_fast64_t;
+    #endif
+
+    typedef uint8_t      uint_fast8_t;
+    typedef unsigned int uint_fast16_t;
+    typedef uint32_t     uint_fast32_t;
+    #ifdef _UINT64_T
+    typedef uint64_t     uint_fast64_t;
+    #endif
+EOF
+fi
+
+if test "$ac_cv_type_uintmax_t" != yes; then
+  sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+    /* Define intmax based on what we found */
+    #ifndef intmax_t
+    #ifdef _INT64_T
+    typedef int64_t       intmax_t;
+    #else
+    typedef long          intmax_t;
+    #endif
+    #endif
+    #ifndef uintmax_t
+    #ifdef _UINT64_T
+    typedef uint64_t      uintmax_t;
+    #else
+    typedef unsigned long uintmax_t;
+    #endif
+    #endif
+EOF
+fi
+
+sed 's/^ *//' >> tmp-stdint.h <<EOF
+
+  #endif /* GCC_GENERATED_STDINT_H */
+EOF
+
+if test -r gstdint.h && cmp -s tmp-stdint.h gstdint.h; then
+  rm -f tmp-stdint.h
+else
+  mv -f tmp-stdint.h gstdint.h
+fi
+
+ ;;
+    "default":C) if test -n "$CONFIG_FILES"; then
+   if test -n "${with_target_subdir}"; then
+     # Multilibs need MULTISUBDIR defined correctly in certain makefiles so
+     # that multilib installs will end up installed in the correct place.
+     # The testsuite needs it for multilib-aware ABI baseline files.
+     # To work around this not being passed down from config-ml.in ->
+     # srcdir/Makefile.am -> srcdir/{src,libsupc++,...}/Makefile.am, manually
+     # append it here.  Only modify Makefiles that have just been created.
+     #
+     # Also, get rid of this simulated-VPATH thing that automake does.
+     cat > vpsed << \_EOF
+  s!`test -f '$<' || echo '$(srcdir)/'`!!
+_EOF
+     for i in $SUBDIRS; do
+      case $CONFIG_FILES in
+       *${i}/Makefile*)
+	 #echo "Adding MULTISUBDIR to $i/Makefile"
+	 sed -f vpsed $i/Makefile > tmp
+	 grep '^MULTISUBDIR =' Makefile >> tmp
+	 mv tmp $i/Makefile
+	 ;;
+      esac
+     done
+     rm vpsed
+   fi
+ fi
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit $?
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/third_party/gofrontend/libbacktrace/configure.ac b/third_party/gofrontend/libbacktrace/configure.ac
new file mode 100644
index 0000000..878bd2c
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/configure.ac
@@ -0,0 +1,391 @@
+# configure.ac -- Backtrace configure script.
+# Copyright (C) 2012-2014 Free Software Foundation, Inc.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+
+#     (1) Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer. 
+
+#     (2) Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.  
+    
+#     (3) The name of the author may not be used to
+#     endorse or promote products derived from this software without
+#     specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+AC_PREREQ(2.64)
+AC_INIT(package-unused, version-unused,, libbacktrace)
+AC_CONFIG_SRCDIR(backtrace.h)
+AC_CONFIG_HEADER(config.h)
+
+AC_CANONICAL_SYSTEM
+target_alias=${target_alias-$host_alias}
+
+AC_USE_SYSTEM_EXTENSIONS
+
+libtool_VERSION=1:0:0
+AC_SUBST(libtool_VERSION)
+
+# 1.11.1: Require that version of automake.
+# foreign: Don't require README, INSTALL, NEWS, etc.
+# no-define: Don't define PACKAGE and VERSION.
+# no-dependencies: Don't generate automatic dependencies.
+#    (because it breaks when using bootstrap-lean, since some of the
+#    headers are gone at "make install" time).
+# -Wall: Issue all automake warnings.
+# -Wno-portability: Don't warn about constructs supported by GNU make.
+#    (because GCC requires GNU make anyhow).
+AM_INIT_AUTOMAKE([1.11.1 foreign no-dist no-define no-dependencies -Wall -Wno-portability])
+
+AM_MAINTAINER_MODE
+
+AC_ARG_WITH(target-subdir,
+[  --with-target-subdir=SUBDIR      Configuring in a subdirectory for target])
+
+# We must force CC to /not/ be precious variables; otherwise
+# the wrong, non-multilib-adjusted value will be used in multilibs.
+# As a side effect, we have to subst CFLAGS ourselves.
+m4_rename([_AC_ARG_VAR_PRECIOUS],[backtrace_PRECIOUS])
+m4_define([_AC_ARG_VAR_PRECIOUS],[])
+AC_PROG_CC
+m4_rename_force([backtrace_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
+
+AC_SUBST(CFLAGS)
+
+AC_PROG_RANLIB
+
+AC_PROG_AWK
+case "$AWK" in
+"") AC_MSG_ERROR([can't build without awk]) ;;
+esac
+
+LT_INIT([disable-shared])
+AM_PROG_LIBTOOL
+
+backtrace_supported=yes
+
+if test -n "${with_target_subdir}"; then
+  # We are compiling a GCC library.  We can assume that the unwind
+  # library exists.
+  AM_ENABLE_MULTILIB(, ..)
+  BACKTRACE_FILE="backtrace.lo simple.lo"
+else
+  AC_CHECK_HEADER([unwind.h],
+    [AC_CHECK_FUNC([_Unwind_Backtrace],
+	           [BACKTRACE_FILE="backtrace.lo simple.lo"],
+		   [BACKTRACE_FILE="nounwind.lo"
+                    backtrace_supported=no])],
+    [BACKTRACE_FILE="nounwind.lo"
+     backtrace_supported=no])
+fi
+AC_SUBST(BACKTRACE_FILE)
+
+EXTRA_FLAGS=
+if test -n "${with_target_subdir}"; then
+  EXTRA_FLAGS="-funwind-tables -frandom-seed=\$@"
+else
+  AC_CACHE_CHECK([for -funwind-tables option],
+    [libbacktrace_cv_c_unwind_tables],
+    [CFLAGS_hold="$CFLAGS"
+     CFLAGS="$CFLAGS -funwind-tables"
+     AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM([static int f() { return 0; }], [return f();])],
+       [libbacktrace_cv_c_unwind_tables=yes],
+       [libbacktrace_cv_c_unwind_tables=no])
+     CFLAGS="$CFLAGS_hold"])
+  if test "$libbacktrace_cv_c_unwind_tables" = "yes"; then
+    EXTRA_FLAGS=-funwind-tables
+  fi
+  AC_CACHE_CHECK([for -frandom-seed=string option],
+    [libbacktrace_cv_c_random_seed_string],
+    [CFLAGS_hold="$CFLAGS"
+     CFLAGS="$CFLAGS -frandom-seed=conftest.lo"
+     AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM([], [return 0;])],
+       [libbacktrace_cv_c_random_seed_string=yes],
+       [libbacktrace_cv_c_random_seed_string=no])
+     CFLAGS="$CFLAGS_hold"])
+  if test "$libbacktrace_cv_c_random_seed_string" = "yes"; then
+    EXTRA_FLAGS="$EXTRA_FLAGS -frandom-seed=\$@"
+  fi
+fi
+AC_SUBST(EXTRA_FLAGS)
+
+ACX_PROG_CC_WARNING_OPTS([-W -Wall -Wwrite-strings -Wstrict-prototypes \
+			  -Wmissing-prototypes -Wold-style-definition \
+			  -Wmissing-format-attribute -Wcast-qual],
+			  [WARN_FLAGS])
+
+if test -n "${with_target_subdir}"; then
+  WARN_FLAGS="$WARN_FLAGS -Werror"
+fi
+
+AC_SUBST(WARN_FLAGS)
+
+if test -n "${with_target_subdir}"; then
+  GCC_CHECK_UNWIND_GETIPINFO
+else
+  ac_save_CFFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -Werror-implicit-function-declaration"
+  AC_MSG_CHECKING([for _Unwind_GetIPInfo])
+  AC_LINK_IFELSE(
+    [AC_LANG_PROGRAM(
+       [#include "unwind.h"
+	struct _Unwind_Context *context;
+	int ip_before_insn = 0;],
+	[return _Unwind_GetIPInfo (context, &ip_before_insn);])],
+	[have_unwind_getipinfo=yes], [have_unwind_getipinfo=no])
+  CFLAGS="$ac_save_CFLAGS"
+  AC_MSG_RESULT([$have_unwind_getipinfo])
+  if test "$have_unwind_getipinfo" = "yes"; then
+    AC_DEFINE(HAVE_GETIPINFO, 1, [Define if _Unwind_GetIPInfo is available.])
+  fi
+fi
+
+# When building as a target library, shared libraries may want to link
+# this in.  We don't want to provide another shared library to
+# complicate dependencies.  Instead, we just compile with -fPIC.
+PIC_FLAG=
+if test -n "${with_target_subdir}"; then
+  PIC_FLAG=-fPIC
+fi
+# Similarly, use -fPIC with --enable-host-shared:
+AC_ARG_ENABLE(host-shared,
+[AS_HELP_STRING([--enable-host-shared],
+		[build host code as shared libraries])],
+[PIC_FLAG=-fPIC], [])
+AC_SUBST(PIC_FLAG)
+
+# Test for __sync support.
+AC_CACHE_CHECK([__sync extensions],
+[libbacktrace_cv_sys_sync],
+[if test -n "${with_target_subdir}"; then
+   libbacktrace_cv_sys_sync=yes
+ else
+   AC_LINK_IFELSE(
+     [AC_LANG_PROGRAM([int i;],
+                      [__sync_bool_compare_and_swap (&i, i, i);
+                       __sync_lock_test_and_set (&i, 1);
+                       __sync_lock_release (&i);])],
+     [libbacktrace_cv_sys_sync=yes],
+     [libbacktrace_cv_sys_sync=no])
+ fi])
+BACKTRACE_SUPPORTS_THREADS=0
+if test "$libbacktrace_cv_sys_sync" = "yes"; then
+  BACKTRACE_SUPPORTS_THREADS=1
+  AC_DEFINE([HAVE_SYNC_FUNCTIONS], 1,
+	    [Define to 1 if you have the __sync functions])
+fi
+AC_SUBST(BACKTRACE_SUPPORTS_THREADS)
+
+# Test for __atomic support.
+AC_CACHE_CHECK([__atomic extensions],
+[libbacktrace_cv_sys_atomic],
+[if test -n "${with_target_subdir}"; then
+   libbacktrace_cv_sys_atomic=yes
+ else
+   AC_LINK_IFELSE(
+     [AC_LANG_PROGRAM([int i;],
+     		      [__atomic_load_n (&i, __ATOMIC_ACQUIRE);
+		       __atomic_store_n (&i, 1, __ATOMIC_RELEASE);])],
+     [libbacktrace_cv_sys_atomic=yes],
+     [libbacktrace_cv_sys_atomic=no])
+ fi])
+if test "$libbacktrace_cv_sys_atomic" = "yes"; then
+  AC_DEFINE([HAVE_ATOMIC_FUNCTIONS], 1,
+	    [Define to 1 if you have the __atomic functions])
+fi
+
+# The library needs to be able to read the executable itself.  Compile
+# a file to determine the executable format.  The awk script
+# filetype.awk prints out the file type.
+AC_CACHE_CHECK([output filetype],
+[libbacktrace_cv_sys_filetype],
+[filetype=
+AC_COMPILE_IFELSE(
+  [AC_LANG_PROGRAM([int i;], [int j;])],
+  [filetype=`${AWK} -f $srcdir/filetype.awk conftest.$ac_objext`],
+  [AC_MSG_FAILURE([compiler failed])])
+libbacktrace_cv_sys_filetype=$filetype])
+
+# Match the file type to decide what files to compile.
+FORMAT_FILE=
+case "$libbacktrace_cv_sys_filetype" in
+elf*) FORMAT_FILE="elf.lo" ;;
+*) AC_MSG_WARN([could not determine output file type])
+   FORMAT_FILE="unknown.lo"
+   backtrace_supported=no
+   ;;
+esac
+AC_SUBST(FORMAT_FILE)
+
+# ELF defines.
+elfsize=
+case "$libbacktrace_cv_sys_filetype" in
+elf32) elfsize=32 ;;
+elf64) elfsize=64 ;;
+esac
+AC_DEFINE_UNQUOTED([BACKTRACE_ELF_SIZE], [$elfsize], [ELF size: 32 or 64])
+
+BACKTRACE_SUPPORTED=0
+if test "$backtrace_supported" = "yes"; then
+  BACKTRACE_SUPPORTED=1
+fi
+AC_SUBST(BACKTRACE_SUPPORTED)
+
+GCC_HEADER_STDINT(gstdint.h)
+
+AC_CHECK_HEADERS(sys/mman.h)
+if test "$ac_cv_header_sys_mman_h" = "no"; then
+  have_mmap=no
+else
+  if test -n "${with_target_subdir}"; then
+    # When built as a GCC target library, we can't do a link test.  We
+    # simply assume that if we have mman.h, we have mmap.
+    have_mmap=yes
+  else
+    AC_CHECK_FUNC(mmap, [have_mmap=yes], [have_mmap=no])
+  fi
+fi
+if test "$have_mmap" = "no"; then
+  VIEW_FILE=read.lo
+  ALLOC_FILE=alloc.lo
+else
+  VIEW_FILE=mmapio.lo
+  AC_PREPROC_IFELSE([
+#include <sys/mman.h>
+#if !defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
+  #error no MAP_ANONYMOUS
+#endif
+], [ALLOC_FILE=mmap.lo], [ALLOC_FILE=alloc.lo])
+fi
+AC_SUBST(VIEW_FILE)
+AC_SUBST(ALLOC_FILE)
+
+BACKTRACE_USES_MALLOC=0
+if test "$ALLOC_FILE" = "alloc.lo"; then
+  BACKTRACE_USES_MALLOC=1
+fi
+AC_SUBST(BACKTRACE_USES_MALLOC)
+
+# Check for dl_iterate_phdr.
+AC_CHECK_HEADERS(link.h)
+if test "$ac_cv_header_link_h" = "no"; then
+  have_dl_iterate_phdr=no
+else
+  if test -n "${with_target_subdir}"; then
+    # When built as a GCC target library, we can't do a link test.
+    AC_EGREP_HEADER([dl_iterate_phdr], [link.h], [have_dl_iterate_phdr=yes],
+		    [have_dl_iterate_phdr=no])
+    case "${host}" in
+    *-*-solaris2.10*)
+        # Avoid dl_iterate_phdr on Solaris 10, where it is in the
+    	# header file but is only in -ldl.
+	have_dl_iterate_phdr=no ;;
+    esac
+  else
+    AC_CHECK_FUNC([dl_iterate_phdr], [have_dl_iterate_phdr=yes],
+		  [have_dl_iterate_phdr=no])
+  fi
+fi
+if test "$have_dl_iterate_phdr" = "yes"; then
+  AC_DEFINE(HAVE_DL_ITERATE_PHDR, 1, [Define if dl_iterate_phdr is available.])
+fi
+
+# Check for the fcntl function.
+if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   *-*-mingw*) have_fcntl=no ;;
+   *) have_fcntl=yes ;;
+   esac
+else
+  AC_CHECK_FUNC(fcntl, [have_fcntl=yes], [have_fcntl=no])
+fi
+if test "$have_fcntl" = "yes"; then
+  AC_DEFINE([HAVE_FCNTL], 1,
+	    [Define to 1 if you have the fcntl function])
+fi
+
+AC_CHECK_DECLS(strnlen)
+
+# Check for getexecname function.
+if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   *-*-solaris2*) have_getexecname=yes ;;
+   *) have_getexecname=no ;;
+   esac
+else
+  AC_CHECK_FUNC(getexecname, [have_getexecname=yes], [have_getexecname=no])
+fi
+if test "$have_getexecname" = "yes"; then
+  AC_DEFINE(HAVE_GETEXECNAME, 1, [Define if getexecname is available.])
+fi
+
+AC_CACHE_CHECK([whether tests can run],
+  [libbacktrace_cv_sys_native],
+  [AC_RUN_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
+     [libbacktrace_cv_sys_native=yes],
+     [libbacktrace_cv_sys_native=no],
+     [libbacktrace_cv_sys_native=no])])
+AM_CONDITIONAL(NATIVE, test "$libbacktrace_cv_sys_native" = "yes")
+
+if test "${multilib}" = "yes"; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+AC_CONFIG_FILES(Makefile backtrace-supported.h)
+
+# We need multilib support, but only if configuring for the target.
+AC_CONFIG_COMMANDS([default],
+[if test -n "$CONFIG_FILES"; then
+   if test -n "${with_target_subdir}"; then
+     # Multilibs need MULTISUBDIR defined correctly in certain makefiles so
+     # that multilib installs will end up installed in the correct place.
+     # The testsuite needs it for multilib-aware ABI baseline files.
+     # To work around this not being passed down from config-ml.in ->
+     # srcdir/Makefile.am -> srcdir/{src,libsupc++,...}/Makefile.am, manually
+     # append it here.  Only modify Makefiles that have just been created.
+     #
+     # Also, get rid of this simulated-VPATH thing that automake does.
+     cat > vpsed << \_EOF
+  s!`test -f '$<' || echo '$(srcdir)/'`!!
+_EOF
+     for i in $SUBDIRS; do
+      case $CONFIG_FILES in
+       *${i}/Makefile*)
+	 #echo "Adding MULTISUBDIR to $i/Makefile"
+	 sed -f vpsed $i/Makefile > tmp
+	 grep '^MULTISUBDIR =' Makefile >> tmp
+	 mv tmp $i/Makefile
+	 ;;
+      esac
+     done
+     rm vpsed
+   fi
+ fi
+],
+[
+# Variables needed in config.status (file generation) which aren't already
+# passed by autoconf.
+SUBDIRS="$SUBDIRS"
+])
+
+AC_OUTPUT
diff --git a/third_party/gofrontend/libbacktrace/dwarf.c b/third_party/gofrontend/libbacktrace/dwarf.c
new file mode 100644
index 0000000..143bb28
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/dwarf.c
@@ -0,0 +1,3022 @@
+/* dwarf.c -- Get file/line information from DWARF for backtraces.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "dwarf2.h"
+#include "filenames.h"
+
+#include "backtrace.h"
+#include "internal.h"
+
+#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN
+
+/* If strnlen is not declared, provide our own version.  */
+
+static size_t
+xstrnlen (const char *s, size_t maxlen)
+{
+  size_t i;
+
+  for (i = 0; i < maxlen; ++i)
+    if (s[i] == '\0')
+      break;
+  return i;
+}
+
+#define strnlen xstrnlen
+
+#endif
+
+/* A buffer to read DWARF info.  */
+
+struct dwarf_buf
+{
+  /* Buffer name for error messages.  */
+  const char *name;
+  /* Start of the buffer.  */
+  const unsigned char *start;
+  /* Next byte to read.  */
+  const unsigned char *buf;
+  /* The number of bytes remaining.  */
+  size_t left;
+  /* Whether the data is big-endian.  */
+  int is_bigendian;
+  /* Error callback routine.  */
+  backtrace_error_callback error_callback;
+  /* Data for error_callback.  */
+  void *data;
+  /* Non-zero if we've reported an underflow error.  */
+  int reported_underflow;
+};
+
+/* A single attribute in a DWARF abbreviation.  */
+
+struct attr
+{
+  /* The attribute name.  */
+  enum dwarf_attribute name;
+  /* The attribute form.  */
+  enum dwarf_form form;
+};
+
+/* A single DWARF abbreviation.  */
+
+struct abbrev
+{
+  /* The abbrev code--the number used to refer to the abbrev.  */
+  uint64_t code;
+  /* The entry tag.  */
+  enum dwarf_tag tag;
+  /* Non-zero if this abbrev has child entries.  */
+  int has_children;
+  /* The number of attributes.  */
+  size_t num_attrs;
+  /* The attributes.  */
+  struct attr *attrs;
+};
+
+/* The DWARF abbreviations for a compilation unit.  This structure
+   only exists while reading the compilation unit.  Most DWARF readers
+   seem to a hash table to map abbrev ID's to abbrev entries.
+   However, we primarily care about GCC, and GCC simply issues ID's in
+   numerical order starting at 1.  So we simply keep a sorted vector,
+   and try to just look up the code.  */
+
+struct abbrevs
+{
+  /* The number of abbrevs in the vector.  */
+  size_t num_abbrevs;
+  /* The abbrevs, sorted by the code field.  */
+  struct abbrev *abbrevs;
+};
+
+/* The different kinds of attribute values.  */
+
+enum attr_val_encoding
+{
+  /* An address.  */
+  ATTR_VAL_ADDRESS,
+  /* A unsigned integer.  */
+  ATTR_VAL_UINT,
+  /* A sigd integer.  */
+  ATTR_VAL_SINT,
+  /* A string.  */
+  ATTR_VAL_STRING,
+  /* An offset to other data in the containing unit.  */
+  ATTR_VAL_REF_UNIT,
+  /* An offset to other data within the .dwarf_info section.  */
+  ATTR_VAL_REF_INFO,
+  /* An offset to data in some other section.  */
+  ATTR_VAL_REF_SECTION,
+  /* A type signature.  */
+  ATTR_VAL_REF_TYPE,
+  /* A block of data (not represented).  */
+  ATTR_VAL_BLOCK,
+  /* An expression (not represented).  */
+  ATTR_VAL_EXPR,
+};
+
+/* An attribute value.  */
+
+struct attr_val
+{
+  /* How the value is stored in the field u.  */
+  enum attr_val_encoding encoding;
+  union
+  {
+    /* ATTR_VAL_ADDRESS, ATTR_VAL_UINT, ATTR_VAL_REF*.  */
+    uint64_t uint;
+    /* ATTR_VAL_SINT.  */
+    int64_t sint;
+    /* ATTR_VAL_STRING.  */
+    const char *string;
+    /* ATTR_VAL_BLOCK not stored.  */
+  } u;
+};
+
+/* The line number program header.  */
+
+struct line_header
+{
+  /* The version of the line number information.  */
+  int version;
+  /* The minimum instruction length.  */
+  unsigned int min_insn_len;
+  /* The maximum number of ops per instruction.  */
+  unsigned int max_ops_per_insn;
+  /* The line base for special opcodes.  */
+  int line_base;
+  /* The line range for special opcodes.  */
+  unsigned int line_range;
+  /* The opcode base--the first special opcode.  */
+  unsigned int opcode_base;
+  /* Opcode lengths, indexed by opcode - 1.  */
+  const unsigned char *opcode_lengths;
+  /* The number of directory entries.  */
+  size_t dirs_count;
+  /* The directory entries.  */
+  const char **dirs;
+  /* The number of filenames.  */
+  size_t filenames_count;
+  /* The filenames.  */
+  const char **filenames;
+};
+
+/* Map a single PC value to a file/line.  We will keep a vector of
+   these sorted by PC value.  Each file/line will be correct from the
+   PC up to the PC of the next entry if there is one.  We allocate one
+   extra entry at the end so that we can use bsearch.  */
+
+struct line
+{
+  /* PC.  */
+  uintptr_t pc;
+  /* File name.  Many entries in the array are expected to point to
+     the same file name.  */
+  const char *filename;
+  /* Line number.  */
+  int lineno;
+};
+
+/* A growable vector of line number information.  This is used while
+   reading the line numbers.  */
+
+struct line_vector
+{
+  /* Memory.  This is an array of struct line.  */
+  struct backtrace_vector vec;
+  /* Number of valid mappings.  */
+  size_t count;
+};
+
+/* A function described in the debug info.  */
+
+struct function
+{
+  /* The name of the function.  */
+  const char *name;
+  /* If this is an inlined function, the filename of the call
+     site.  */
+  const char *caller_filename;
+  /* If this is an inlined function, the line number of the call
+     site.  */
+  int caller_lineno;
+  /* Map PC ranges to inlined functions.  */
+  struct function_addrs *function_addrs;
+  size_t function_addrs_count;
+};
+
+/* An address range for a function.  This maps a PC value to a
+   specific function.  */
+
+struct function_addrs
+{
+  /* Range is LOW <= PC < HIGH.  */
+  uint64_t low;
+  uint64_t high;
+  /* Function for this address range.  */
+  struct function *function;
+};
+
+/* A growable vector of function address ranges.  */
+
+struct function_vector
+{
+  /* Memory.  This is an array of struct function_addrs.  */
+  struct backtrace_vector vec;
+  /* Number of address ranges present.  */
+  size_t count;
+};
+
+/* A DWARF compilation unit.  This only holds the information we need
+   to map a PC to a file and line.  */
+
+struct unit
+{
+  /* The first entry for this compilation unit.  */
+  const unsigned char *unit_data;
+  /* The length of the data for this compilation unit.  */
+  size_t unit_data_len;
+  /* The offset of UNIT_DATA from the start of the information for
+     this compilation unit.  */
+  size_t unit_data_offset;
+  /* DWARF version.  */
+  int version;
+  /* Whether unit is DWARF64.  */
+  int is_dwarf64;
+  /* Address size.  */
+  int addrsize;
+  /* Offset into line number information.  */
+  off_t lineoff;
+  /* Primary source file.  */
+  const char *filename;
+  /* Compilation command working directory.  */
+  const char *comp_dir;
+  /* Absolute file name, only set if needed.  */
+  const char *abs_filename;
+  /* The abbreviations for this unit.  */
+  struct abbrevs abbrevs;
+
+  /* The fields above this point are read in during initialization and
+     may be accessed freely.  The fields below this point are read in
+     as needed, and therefore require care, as different threads may
+     try to initialize them simultaneously.  */
+
+  /* PC to line number mapping.  This is NULL if the values have not
+     been read.  This is (struct line *) -1 if there was an error
+     reading the values.  */
+  struct line *lines;
+  /* Number of entries in lines.  */
+  size_t lines_count;
+  /* PC ranges to function.  */
+  struct function_addrs *function_addrs;
+  size_t function_addrs_count;
+};
+
+/* An address range for a compilation unit.  This maps a PC value to a
+   specific compilation unit.  Note that we invert the representation
+   in DWARF: instead of listing the units and attaching a list of
+   ranges, we list the ranges and have each one point to the unit.
+   This lets us do a binary search to find the unit.  */
+
+struct unit_addrs
+{
+  /* Range is LOW <= PC < HIGH.  */
+  uint64_t low;
+  uint64_t high;
+  /* Compilation unit for this address range.  */
+  struct unit *u;
+};
+
+/* A growable vector of compilation unit address ranges.  */
+
+struct unit_addrs_vector
+{
+  /* Memory.  This is an array of struct unit_addrs.  */
+  struct backtrace_vector vec;
+  /* Number of address ranges present.  */
+  size_t count;
+};
+
+/* The information we need to map a PC to a file and line.  */
+
+struct dwarf_data
+{
+  /* The data for the next file we know about.  */
+  struct dwarf_data *next;
+  /* The base address for this file.  */
+  uintptr_t base_address;
+  /* A sorted list of address ranges.  */
+  struct unit_addrs *addrs;
+  /* Number of address ranges in list.  */
+  size_t addrs_count;
+  /* The unparsed .debug_info section.  */
+  const unsigned char *dwarf_info;
+  size_t dwarf_info_size;
+  /* The unparsed .debug_line section.  */
+  const unsigned char *dwarf_line;
+  size_t dwarf_line_size;
+  /* The unparsed .debug_ranges section.  */
+  const unsigned char *dwarf_ranges;
+  size_t dwarf_ranges_size;
+  /* The unparsed .debug_str section.  */
+  const unsigned char *dwarf_str;
+  size_t dwarf_str_size;
+  /* Whether the data is big-endian or not.  */
+  int is_bigendian;
+  /* A vector used for function addresses.  We keep this here so that
+     we can grow the vector as we read more functions.  */
+  struct function_vector fvec;
+};
+
+/* Report an error for a DWARF buffer.  */
+
+static void
+dwarf_buf_error (struct dwarf_buf *buf, const char *msg)
+{
+  char b[200];
+
+  snprintf (b, sizeof b, "%s in %s at %d",
+	    msg, buf->name, (int) (buf->buf - buf->start));
+  buf->error_callback (buf->data, b, 0);
+}
+
+/* Require at least COUNT bytes in BUF.  Return 1 if all is well, 0 on
+   error.  */
+
+static int
+require (struct dwarf_buf *buf, size_t count)
+{
+  if (buf->left >= count)
+    return 1;
+
+  if (!buf->reported_underflow)
+    {
+      dwarf_buf_error (buf, "DWARF underflow");
+      buf->reported_underflow = 1;
+    }
+
+  return 0;
+}
+
+/* Advance COUNT bytes in BUF.  Return 1 if all is well, 0 on
+   error.  */
+
+static int
+advance (struct dwarf_buf *buf, size_t count)
+{
+  if (!require (buf, count))
+    return 0;
+  buf->buf += count;
+  buf->left -= count;
+  return 1;
+}
+
+/* Read one byte from BUF and advance 1 byte.  */
+
+static unsigned char
+read_byte (struct dwarf_buf *buf)
+{
+  const unsigned char *p = buf->buf;
+
+  if (!advance (buf, 1))
+    return 0;
+  return p[0];
+}
+
+/* Read a signed char from BUF and advance 1 byte.  */
+
+static signed char
+read_sbyte (struct dwarf_buf *buf)
+{
+  const unsigned char *p = buf->buf;
+
+  if (!advance (buf, 1))
+    return 0;
+  return (*p ^ 0x80) - 0x80;
+}
+
+/* Read a uint16 from BUF and advance 2 bytes.  */
+
+static uint16_t
+read_uint16 (struct dwarf_buf *buf)
+{
+  const unsigned char *p = buf->buf;
+
+  if (!advance (buf, 2))
+    return 0;
+  if (buf->is_bigendian)
+    return ((uint16_t) p[0] << 8) | (uint16_t) p[1];
+  else
+    return ((uint16_t) p[1] << 8) | (uint16_t) p[0];
+}
+
+/* Read a uint32 from BUF and advance 4 bytes.  */
+
+static uint32_t
+read_uint32 (struct dwarf_buf *buf)
+{
+  const unsigned char *p = buf->buf;
+
+  if (!advance (buf, 4))
+    return 0;
+  if (buf->is_bigendian)
+    return (((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16)
+	    | ((uint32_t) p[2] << 8) | (uint32_t) p[3]);
+  else
+    return (((uint32_t) p[3] << 24) | ((uint32_t) p[2] << 16)
+	    | ((uint32_t) p[1] << 8) | (uint32_t) p[0]);
+}
+
+/* Read a uint64 from BUF and advance 8 bytes.  */
+
+static uint64_t
+read_uint64 (struct dwarf_buf *buf)
+{
+  const unsigned char *p = buf->buf;
+
+  if (!advance (buf, 8))
+    return 0;
+  if (buf->is_bigendian)
+    return (((uint64_t) p[0] << 56) | ((uint64_t) p[1] << 48)
+	    | ((uint64_t) p[2] << 40) | ((uint64_t) p[3] << 32)
+	    | ((uint64_t) p[4] << 24) | ((uint64_t) p[5] << 16)
+	    | ((uint64_t) p[6] << 8) | (uint64_t) p[7]);
+  else
+    return (((uint64_t) p[7] << 56) | ((uint64_t) p[6] << 48)
+	    | ((uint64_t) p[5] << 40) | ((uint64_t) p[4] << 32)
+	    | ((uint64_t) p[3] << 24) | ((uint64_t) p[2] << 16)
+	    | ((uint64_t) p[1] << 8) | (uint64_t) p[0]);
+}
+
+/* Read an offset from BUF and advance the appropriate number of
+   bytes.  */
+
+static uint64_t
+read_offset (struct dwarf_buf *buf, int is_dwarf64)
+{
+  if (is_dwarf64)
+    return read_uint64 (buf);
+  else
+    return read_uint32 (buf);
+}
+
+/* Read an address from BUF and advance the appropriate number of
+   bytes.  */
+
+static uint64_t
+read_address (struct dwarf_buf *buf, int addrsize)
+{
+  switch (addrsize)
+    {
+    case 1:
+      return read_byte (buf);
+    case 2:
+      return read_uint16 (buf);
+    case 4:
+      return read_uint32 (buf);
+    case 8:
+      return read_uint64 (buf);
+    default:
+      dwarf_buf_error (buf, "unrecognized address size");
+      return 0;
+    }
+}
+
+/* Return whether a value is the highest possible address, given the
+   address size.  */
+
+static int
+is_highest_address (uint64_t address, int addrsize)
+{
+  switch (addrsize)
+    {
+    case 1:
+      return address == (unsigned char) -1;
+    case 2:
+      return address == (uint16_t) -1;
+    case 4:
+      return address == (uint32_t) -1;
+    case 8:
+      return address == (uint64_t) -1;
+    default:
+      return 0;
+    }
+}
+
+/* Read an unsigned LEB128 number.  */
+
+static uint64_t
+read_uleb128 (struct dwarf_buf *buf)
+{
+  uint64_t ret;
+  unsigned int shift;
+  int overflow;
+  unsigned char b;
+
+  ret = 0;
+  shift = 0;
+  overflow = 0;
+  do
+    {
+      const unsigned char *p;
+
+      p = buf->buf;
+      if (!advance (buf, 1))
+	return 0;
+      b = *p;
+      if (shift < 64)
+	ret |= ((uint64_t) (b & 0x7f)) << shift;
+      else if (!overflow)
+	{
+	  dwarf_buf_error (buf, "LEB128 overflows uint64_t");
+	  overflow = 1;
+	}
+      shift += 7;
+    }
+  while ((b & 0x80) != 0);
+
+  return ret;
+}
+
+/* Read a signed LEB128 number.  */
+
+static int64_t
+read_sleb128 (struct dwarf_buf *buf)
+{
+  uint64_t val;
+  unsigned int shift;
+  int overflow;
+  unsigned char b;
+
+  val = 0;
+  shift = 0;
+  overflow = 0;
+  do
+    {
+      const unsigned char *p;
+
+      p = buf->buf;
+      if (!advance (buf, 1))
+	return 0;
+      b = *p;
+      if (shift < 64)
+	val |= ((uint64_t) (b & 0x7f)) << shift;
+      else if (!overflow)
+	{
+	  dwarf_buf_error (buf, "signed LEB128 overflows uint64_t");
+	  overflow = 1;
+	}
+      shift += 7;
+    }
+  while ((b & 0x80) != 0);
+
+  if ((b & 0x40) != 0 && shift < 64)
+    val |= ((uint64_t) -1) << shift;
+
+  return (int64_t) val;
+}
+
+/* Return the length of an LEB128 number.  */
+
+static size_t
+leb128_len (const unsigned char *p)
+{
+  size_t ret;
+
+  ret = 1;
+  while ((*p & 0x80) != 0)
+    {
+      ++p;
+      ++ret;
+    }
+  return ret;
+}
+
+/* Free an abbreviations structure.  */
+
+static void
+free_abbrevs (struct backtrace_state *state, struct abbrevs *abbrevs,
+	      backtrace_error_callback error_callback, void *data)
+{
+  size_t i;
+
+  for (i = 0; i < abbrevs->num_abbrevs; ++i)
+    backtrace_free (state, abbrevs->abbrevs[i].attrs,
+		    abbrevs->abbrevs[i].num_attrs * sizeof (struct attr),
+		    error_callback, data);
+  backtrace_free (state, abbrevs->abbrevs,
+		  abbrevs->num_abbrevs * sizeof (struct abbrev),
+		  error_callback, data);
+  abbrevs->num_abbrevs = 0;
+  abbrevs->abbrevs = NULL;
+}
+
+/* Read an attribute value.  Returns 1 on success, 0 on failure.  If
+   the value can be represented as a uint64_t, sets *VAL and sets
+   *IS_VALID to 1.  We don't try to store the value of other attribute
+   forms, because we don't care about them.  */
+
+static int
+read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
+		int is_dwarf64, int version, int addrsize,
+		const unsigned char *dwarf_str, size_t dwarf_str_size,
+		struct attr_val *val)
+{
+  /* Avoid warnings about val.u.FIELD may be used uninitialized if
+     this function is inlined.  The warnings aren't valid but can
+     occur because the different fields are set and used
+     conditionally.  */
+  memset (val, 0, sizeof *val);
+
+  switch (form)
+    {
+    case DW_FORM_addr:
+      val->encoding = ATTR_VAL_ADDRESS;
+      val->u.uint = read_address (buf, addrsize);
+      return 1;
+    case DW_FORM_block2:
+      val->encoding = ATTR_VAL_BLOCK;
+      return advance (buf, read_uint16 (buf));
+    case DW_FORM_block4:
+      val->encoding = ATTR_VAL_BLOCK;
+      return advance (buf, read_uint32 (buf));
+    case DW_FORM_data2:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_uint16 (buf);
+      return 1;
+    case DW_FORM_data4:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_uint32 (buf);
+      return 1;
+    case DW_FORM_data8:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_uint64 (buf);
+      return 1;
+    case DW_FORM_string:
+      val->encoding = ATTR_VAL_STRING;
+      val->u.string = (const char *) buf->buf;
+      return advance (buf, strnlen ((const char *) buf->buf, buf->left) + 1);
+    case DW_FORM_block:
+      val->encoding = ATTR_VAL_BLOCK;
+      return advance (buf, read_uleb128 (buf));
+    case DW_FORM_block1:
+      val->encoding = ATTR_VAL_BLOCK;
+      return advance (buf, read_byte (buf));
+    case DW_FORM_data1:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_byte (buf);
+      return 1;
+    case DW_FORM_flag:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_byte (buf);
+      return 1;
+    case DW_FORM_sdata:
+      val->encoding = ATTR_VAL_SINT;
+      val->u.sint = read_sleb128 (buf);
+      return 1;
+    case DW_FORM_strp:
+      {
+	uint64_t offset;
+
+	offset = read_offset (buf, is_dwarf64);
+	if (offset >= dwarf_str_size)
+	  {
+	    dwarf_buf_error (buf, "DW_FORM_strp out of range");
+	    return 0;
+	  }
+	val->encoding = ATTR_VAL_STRING;
+	val->u.string = (const char *) dwarf_str + offset;
+	return 1;
+      }
+    case DW_FORM_udata:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_uleb128 (buf);
+      return 1;
+    case DW_FORM_ref_addr:
+      val->encoding = ATTR_VAL_REF_INFO;
+      if (version == 2)
+	val->u.uint = read_address (buf, addrsize);
+      else
+	val->u.uint = read_offset (buf, is_dwarf64);
+      return 1;
+    case DW_FORM_ref1:
+      val->encoding = ATTR_VAL_REF_UNIT;
+      val->u.uint = read_byte (buf);
+      return 1;
+    case DW_FORM_ref2:
+      val->encoding = ATTR_VAL_REF_UNIT;
+      val->u.uint = read_uint16 (buf);
+      return 1;
+    case DW_FORM_ref4:
+      val->encoding = ATTR_VAL_REF_UNIT;
+      val->u.uint = read_uint32 (buf);
+      return 1;
+    case DW_FORM_ref8:
+      val->encoding = ATTR_VAL_REF_UNIT;
+      val->u.uint = read_uint64 (buf);
+      return 1;
+    case DW_FORM_ref_udata:
+      val->encoding = ATTR_VAL_REF_UNIT;
+      val->u.uint = read_uleb128 (buf);
+      return 1;
+    case DW_FORM_indirect:
+      {
+	uint64_t form;
+
+	form = read_uleb128 (buf);
+	return read_attribute ((enum dwarf_form) form, buf, is_dwarf64,
+			       version, addrsize, dwarf_str, dwarf_str_size,
+			       val);
+      }
+    case DW_FORM_sec_offset:
+      val->encoding = ATTR_VAL_REF_SECTION;
+      val->u.uint = read_offset (buf, is_dwarf64);
+      return 1;
+    case DW_FORM_exprloc:
+      val->encoding = ATTR_VAL_EXPR;
+      return advance (buf, read_uleb128 (buf));
+    case DW_FORM_flag_present:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = 1;
+      return 1;
+    case DW_FORM_ref_sig8:
+      val->encoding = ATTR_VAL_REF_TYPE;
+      val->u.uint = read_uint64 (buf);
+      return 1;
+    case DW_FORM_GNU_addr_index:
+      val->encoding = ATTR_VAL_REF_SECTION;
+      val->u.uint = read_uleb128 (buf);
+      return 1;
+    case DW_FORM_GNU_str_index:
+      val->encoding = ATTR_VAL_REF_SECTION;
+      val->u.uint = read_uleb128 (buf);
+      return 1;
+    case DW_FORM_GNU_ref_alt:
+      val->encoding = ATTR_VAL_REF_SECTION;
+      val->u.uint = read_offset (buf, is_dwarf64);
+      return 1;
+    case DW_FORM_GNU_strp_alt:
+      val->encoding = ATTR_VAL_REF_SECTION;
+      val->u.uint = read_offset (buf, is_dwarf64);
+      return 1;
+    default:
+      dwarf_buf_error (buf, "unrecognized DWARF form");
+      return 0;
+    }
+}
+
+/* Compare function_addrs for qsort.  When ranges are nested, make the
+   smallest one sort last.  */
+
+static int
+function_addrs_compare (const void *v1, const void *v2)
+{
+  const struct function_addrs *a1 = (const struct function_addrs *) v1;
+  const struct function_addrs *a2 = (const struct function_addrs *) v2;
+
+  if (a1->low < a2->low)
+    return -1;
+  if (a1->low > a2->low)
+    return 1;
+  if (a1->high < a2->high)
+    return 1;
+  if (a1->high > a2->high)
+    return -1;
+  return strcmp (a1->function->name, a2->function->name);
+}
+
+/* Compare a PC against a function_addrs for bsearch.  Note that if
+   there are multiple ranges containing PC, which one will be returned
+   is unpredictable.  We compensate for that in dwarf_fileline.  */
+
+static int
+function_addrs_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct function_addrs *entry = (const struct function_addrs *) ventry;
+  uintptr_t pc;
+
+  pc = *key;
+  if (pc < entry->low)
+    return -1;
+  else if (pc >= entry->high)
+    return 1;
+  else
+    return 0;
+}
+
+/* Add a new compilation unit address range to a vector.  Returns 1 on
+   success, 0 on failure.  */
+
+static int
+add_unit_addr (struct backtrace_state *state, uintptr_t base_address,
+	       struct unit_addrs addrs,
+	       backtrace_error_callback error_callback, void *data,
+	       struct unit_addrs_vector *vec)
+{
+  struct unit_addrs *p;
+
+  /* Add in the base address of the module here, so that we can look
+     up the PC directly.  */
+  addrs.low += base_address;
+  addrs.high += base_address;
+
+  /* Try to merge with the last entry.  */
+  if (vec->count > 0)
+    {
+      p = (struct unit_addrs *) vec->vec.base + (vec->count - 1);
+      if ((addrs.low == p->high || addrs.low == p->high + 1)
+	  && addrs.u == p->u)
+	{
+	  if (addrs.high > p->high)
+	    p->high = addrs.high;
+	  return 1;
+	}
+    }
+
+  p = ((struct unit_addrs *)
+       backtrace_vector_grow (state, sizeof (struct unit_addrs),
+			      error_callback, data, &vec->vec));
+  if (p == NULL)
+    return 0;
+
+  *p = addrs;
+  ++vec->count;
+  return 1;
+}
+
+/* Free a unit address vector.  */
+
+static void
+free_unit_addrs_vector (struct backtrace_state *state,
+			struct unit_addrs_vector *vec,
+			backtrace_error_callback error_callback, void *data)
+{
+  struct unit_addrs *addrs;
+  size_t i;
+
+  addrs = (struct unit_addrs *) vec->vec.base;
+  for (i = 0; i < vec->count; ++i)
+    free_abbrevs (state, &addrs[i].u->abbrevs, error_callback, data);
+}
+
+/* Compare unit_addrs for qsort.  When ranges are nested, make the
+   smallest one sort last.  */
+
+static int
+unit_addrs_compare (const void *v1, const void *v2)
+{
+  const struct unit_addrs *a1 = (const struct unit_addrs *) v1;
+  const struct unit_addrs *a2 = (const struct unit_addrs *) v2;
+
+  if (a1->low < a2->low)
+    return -1;
+  if (a1->low > a2->low)
+    return 1;
+  if (a1->high < a2->high)
+    return 1;
+  if (a1->high > a2->high)
+    return -1;
+  if (a1->u->lineoff < a2->u->lineoff)
+    return -1;
+  if (a1->u->lineoff > a2->u->lineoff)
+    return 1;
+  return 0;
+}
+
+/* Compare a PC against a unit_addrs for bsearch.  Note that if there
+   are multiple ranges containing PC, which one will be returned is
+   unpredictable.  We compensate for that in dwarf_fileline.  */
+
+static int
+unit_addrs_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct unit_addrs *entry = (const struct unit_addrs *) ventry;
+  uintptr_t pc;
+
+  pc = *key;
+  if (pc < entry->low)
+    return -1;
+  else if (pc >= entry->high)
+    return 1;
+  else
+    return 0;
+}
+
+/* Sort the line vector by PC.  We want a stable sort here.  We know
+   that the pointers are into the same array, so it is safe to compare
+   them directly.  */
+
+static int
+line_compare (const void *v1, const void *v2)
+{
+  const struct line *ln1 = (const struct line *) v1;
+  const struct line *ln2 = (const struct line *) v2;
+
+  if (ln1->pc < ln2->pc)
+    return -1;
+  else if (ln1->pc > ln2->pc)
+    return 1;
+  else if (ln1 < ln2)
+    return -1;
+  else if (ln1 > ln2)
+    return 1;
+  else
+    return 0;
+}
+
+/* Find a PC in a line vector.  We always allocate an extra entry at
+   the end of the lines vector, so that this routine can safely look
+   at the next entry.  Note that when there are multiple mappings for
+   the same PC value, this will return the last one.  */
+
+static int
+line_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct line *entry = (const struct line *) ventry;
+  uintptr_t pc;
+
+  pc = *key;
+  if (pc < entry->pc)
+    return -1;
+  else if (pc >= (entry + 1)->pc)
+    return 1;
+  else
+    return 0;
+}
+
+/* Sort the abbrevs by the abbrev code.  This function is passed to
+   both qsort and bsearch.  */
+
+static int
+abbrev_compare (const void *v1, const void *v2)
+{
+  const struct abbrev *a1 = (const struct abbrev *) v1;
+  const struct abbrev *a2 = (const struct abbrev *) v2;
+
+  if (a1->code < a2->code)
+    return -1;
+  else if (a1->code > a2->code)
+    return 1;
+  else
+    {
+      /* This really shouldn't happen.  It means there are two
+	 different abbrevs with the same code, and that means we don't
+	 know which one lookup_abbrev should return.  */
+      return 0;
+    }
+}
+
+/* Read the abbreviation table for a compilation unit.  Returns 1 on
+   success, 0 on failure.  */
+
+static int
+read_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset,
+	      const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
+	      int is_bigendian, backtrace_error_callback error_callback,
+	      void *data, struct abbrevs *abbrevs)
+{
+  struct dwarf_buf abbrev_buf;
+  struct dwarf_buf count_buf;
+  size_t num_abbrevs;
+
+  abbrevs->num_abbrevs = 0;
+  abbrevs->abbrevs = NULL;
+
+  if (abbrev_offset >= dwarf_abbrev_size)
+    {
+      error_callback (data, "abbrev offset out of range", 0);
+      return 0;
+    }
+
+  abbrev_buf.name = ".debug_abbrev";
+  abbrev_buf.start = dwarf_abbrev;
+  abbrev_buf.buf = dwarf_abbrev + abbrev_offset;
+  abbrev_buf.left = dwarf_abbrev_size - abbrev_offset;
+  abbrev_buf.is_bigendian = is_bigendian;
+  abbrev_buf.error_callback = error_callback;
+  abbrev_buf.data = data;
+  abbrev_buf.reported_underflow = 0;
+
+  /* Count the number of abbrevs in this list.  */
+
+  count_buf = abbrev_buf;
+  num_abbrevs = 0;
+  while (read_uleb128 (&count_buf) != 0)
+    {
+      if (count_buf.reported_underflow)
+	return 0;
+      ++num_abbrevs;
+      // Skip tag.
+      read_uleb128 (&count_buf);
+      // Skip has_children.
+      read_byte (&count_buf);
+      // Skip attributes.
+      while (read_uleb128 (&count_buf) != 0)
+	read_uleb128 (&count_buf);
+      // Skip form of last attribute.
+      read_uleb128 (&count_buf);
+    }
+
+  if (count_buf.reported_underflow)
+    return 0;
+
+  if (num_abbrevs == 0)
+    return 1;
+
+  abbrevs->num_abbrevs = num_abbrevs;
+  abbrevs->abbrevs = ((struct abbrev *)
+		      backtrace_alloc (state,
+				       num_abbrevs * sizeof (struct abbrev),
+				       error_callback, data));
+  if (abbrevs->abbrevs == NULL)
+    return 0;
+  memset (abbrevs->abbrevs, 0, num_abbrevs * sizeof (struct abbrev));
+
+  num_abbrevs = 0;
+  while (1)
+    {
+      uint64_t code;
+      struct abbrev a;
+      size_t num_attrs;
+      struct attr *attrs;
+
+      if (abbrev_buf.reported_underflow)
+	goto fail;
+
+      code = read_uleb128 (&abbrev_buf);
+      if (code == 0)
+	break;
+
+      a.code = code;
+      a.tag = (enum dwarf_tag) read_uleb128 (&abbrev_buf);
+      a.has_children = read_byte (&abbrev_buf);
+
+      count_buf = abbrev_buf;
+      num_attrs = 0;
+      while (read_uleb128 (&count_buf) != 0)
+	{
+	  ++num_attrs;
+	  read_uleb128 (&count_buf);
+	}
+
+      if (num_attrs == 0)
+	{
+	  attrs = NULL;
+	  read_uleb128 (&abbrev_buf);
+	  read_uleb128 (&abbrev_buf);
+	}
+      else
+	{
+	  attrs = ((struct attr *)
+		   backtrace_alloc (state, num_attrs * sizeof *attrs,
+				    error_callback, data));
+	  if (attrs == NULL)
+	    goto fail;
+	  num_attrs = 0;
+	  while (1)
+	    {
+	      uint64_t name;
+	      uint64_t form;
+
+	      name = read_uleb128 (&abbrev_buf);
+	      form = read_uleb128 (&abbrev_buf);
+	      if (name == 0)
+		break;
+	      attrs[num_attrs].name = (enum dwarf_attribute) name;
+	      attrs[num_attrs].form = (enum dwarf_form) form;
+	      ++num_attrs;
+	    }
+	}
+
+      a.num_attrs = num_attrs;
+      a.attrs = attrs;
+
+      abbrevs->abbrevs[num_abbrevs] = a;
+      ++num_abbrevs;
+    }
+
+  backtrace_qsort (abbrevs->abbrevs, abbrevs->num_abbrevs,
+		   sizeof (struct abbrev), abbrev_compare);
+
+  return 1;
+
+ fail:
+  free_abbrevs (state, abbrevs, error_callback, data);
+  return 0;
+}
+
+/* Return the abbrev information for an abbrev code.  */
+
+static const struct abbrev *
+lookup_abbrev (struct abbrevs *abbrevs, uint64_t code,
+	       backtrace_error_callback error_callback, void *data)
+{
+  struct abbrev key;
+  void *p;
+
+  /* With GCC, where abbrevs are simply numbered in order, we should
+     be able to just look up the entry.  */
+  if (code - 1 < abbrevs->num_abbrevs
+      && abbrevs->abbrevs[code - 1].code == code)
+    return &abbrevs->abbrevs[code - 1];
+
+  /* Otherwise we have to search.  */
+  memset (&key, 0, sizeof key);
+  key.code = code;
+  p = bsearch (&key, abbrevs->abbrevs, abbrevs->num_abbrevs,
+	       sizeof (struct abbrev), abbrev_compare);
+  if (p == NULL)
+    {
+      error_callback (data, "invalid abbreviation code", 0);
+      return NULL;
+    }
+  return (const struct abbrev *) p;
+}
+
+/* Add non-contiguous address ranges for a compilation unit.  Returns
+   1 on success, 0 on failure.  */
+
+static int
+add_unit_ranges (struct backtrace_state *state, uintptr_t base_address,
+		 struct unit *u, uint64_t ranges, uint64_t base,
+		 int is_bigendian, const unsigned char *dwarf_ranges,
+		 size_t dwarf_ranges_size,
+		 backtrace_error_callback error_callback, void *data,
+		 struct unit_addrs_vector *addrs)
+{
+  struct dwarf_buf ranges_buf;
+
+  if (ranges >= dwarf_ranges_size)
+    {
+      error_callback (data, "ranges offset out of range", 0);
+      return 0;
+    }
+
+  ranges_buf.name = ".debug_ranges";
+  ranges_buf.start = dwarf_ranges;
+  ranges_buf.buf = dwarf_ranges + ranges;
+  ranges_buf.left = dwarf_ranges_size - ranges;
+  ranges_buf.is_bigendian = is_bigendian;
+  ranges_buf.error_callback = error_callback;
+  ranges_buf.data = data;
+  ranges_buf.reported_underflow = 0;
+
+  while (1)
+    {
+      uint64_t low;
+      uint64_t high;
+
+      if (ranges_buf.reported_underflow)
+	return 0;
+
+      low = read_address (&ranges_buf, u->addrsize);
+      high = read_address (&ranges_buf, u->addrsize);
+
+      if (low == 0 && high == 0)
+	break;
+
+      if (is_highest_address (low, u->addrsize))
+	base = high;
+      else
+	{
+	  struct unit_addrs a;
+
+	  a.low = low + base;
+	  a.high = high + base;
+	  a.u = u;
+	  if (!add_unit_addr (state, base_address, a, error_callback, data,
+			      addrs))
+	    return 0;
+	}
+    }
+
+  if (ranges_buf.reported_underflow)
+    return 0;
+
+  return 1;
+}
+
+/* Find the address range covered by a compilation unit, reading from
+   UNIT_BUF and adding values to U.  Returns 1 if all data could be
+   read, 0 if there is some error.  */
+
+static int
+find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
+		     struct dwarf_buf *unit_buf, 
+		     const unsigned char *dwarf_str, size_t dwarf_str_size,
+		     const unsigned char *dwarf_ranges,
+		     size_t dwarf_ranges_size,
+		     int is_bigendian, backtrace_error_callback error_callback,
+		     void *data, struct unit *u,
+		     struct unit_addrs_vector *addrs)
+{
+  while (unit_buf->left > 0)
+    {
+      uint64_t code;
+      const struct abbrev *abbrev;
+      uint64_t lowpc;
+      int have_lowpc;
+      uint64_t highpc;
+      int have_highpc;
+      int highpc_is_relative;
+      uint64_t ranges;
+      int have_ranges;
+      size_t i;
+
+      code = read_uleb128 (unit_buf);
+      if (code == 0)
+	return 1;
+
+      abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
+      if (abbrev == NULL)
+	return 0;
+
+      lowpc = 0;
+      have_lowpc = 0;
+      highpc = 0;
+      have_highpc = 0;
+      highpc_is_relative = 0;
+      ranges = 0;
+      have_ranges = 0;
+      for (i = 0; i < abbrev->num_attrs; ++i)
+	{
+	  struct attr_val val;
+
+	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
+			       u->is_dwarf64, u->version, u->addrsize,
+			       dwarf_str, dwarf_str_size, &val))
+	    return 0;
+
+	  switch (abbrev->attrs[i].name)
+	    {
+	    case DW_AT_low_pc:
+	      if (val.encoding == ATTR_VAL_ADDRESS)
+		{
+		  lowpc = val.u.uint;
+		  have_lowpc = 1;
+		}
+	      break;
+
+	    case DW_AT_high_pc:
+	      if (val.encoding == ATTR_VAL_ADDRESS)
+		{
+		  highpc = val.u.uint;
+		  have_highpc = 1;
+		}
+	      else if (val.encoding == ATTR_VAL_UINT)
+		{
+		  highpc = val.u.uint;
+		  have_highpc = 1;
+		  highpc_is_relative = 1;
+		}
+	      break;
+
+	    case DW_AT_ranges:
+	      if (val.encoding == ATTR_VAL_UINT
+		  || val.encoding == ATTR_VAL_REF_SECTION)
+		{
+		  ranges = val.u.uint;
+		  have_ranges = 1;
+		}
+	      break;
+
+	    case DW_AT_stmt_list:
+	      if (abbrev->tag == DW_TAG_compile_unit
+		  && (val.encoding == ATTR_VAL_UINT
+		      || val.encoding == ATTR_VAL_REF_SECTION))
+		u->lineoff = val.u.uint;
+	      break;
+
+	    case DW_AT_name:
+	      if (abbrev->tag == DW_TAG_compile_unit
+		  && val.encoding == ATTR_VAL_STRING)
+		u->filename = val.u.string;
+	      break;
+
+	    case DW_AT_comp_dir:
+	      if (abbrev->tag == DW_TAG_compile_unit
+		  && val.encoding == ATTR_VAL_STRING)
+		u->comp_dir = val.u.string;
+	      break;
+
+	    default:
+	      break;
+	    }
+	}
+
+      if (abbrev->tag == DW_TAG_compile_unit
+	  || abbrev->tag == DW_TAG_subprogram)
+	{
+	  if (have_ranges)
+	    {
+	      if (!add_unit_ranges (state, base_address, u, ranges, lowpc,
+				    is_bigendian, dwarf_ranges,
+				    dwarf_ranges_size, error_callback,
+				    data, addrs))
+		return 0;
+	    }
+	  else if (have_lowpc && have_highpc)
+	    {
+	      struct unit_addrs a;
+
+	      if (highpc_is_relative)
+		highpc += lowpc;
+	      a.low = lowpc;
+	      a.high = highpc;
+	      a.u = u;
+
+	      if (!add_unit_addr (state, base_address, a, error_callback, data,
+				  addrs))
+		return 0;
+	    }
+
+	  /* If we found the PC range in the DW_TAG_compile_unit, we
+	     can stop now.  */
+	  if (abbrev->tag == DW_TAG_compile_unit
+	      && (have_ranges || (have_lowpc && have_highpc)))
+	    return 1;
+	}
+
+      if (abbrev->has_children)
+	{
+	  if (!find_address_ranges (state, base_address, unit_buf,
+				    dwarf_str, dwarf_str_size,
+				    dwarf_ranges, dwarf_ranges_size,
+				    is_bigendian, error_callback, data,
+				    u, addrs))
+	    return 0;
+	}
+    }
+
+  return 1;
+}
+
+/* Build a mapping from address ranges to the compilation units where
+   the line number information for that range can be found.  Returns 1
+   on success, 0 on failure.  */
+
+static int
+build_address_map (struct backtrace_state *state, uintptr_t base_address,
+		   const unsigned char *dwarf_info, size_t dwarf_info_size,
+		   const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
+		   const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
+		   const unsigned char *dwarf_str, size_t dwarf_str_size,
+		   int is_bigendian, backtrace_error_callback error_callback,
+		   void *data, struct unit_addrs_vector *addrs)
+{
+  struct dwarf_buf info;
+  struct abbrevs abbrevs;
+
+  memset (&addrs->vec, 0, sizeof addrs->vec);
+  addrs->count = 0;
+
+  /* Read through the .debug_info section.  FIXME: Should we use the
+     .debug_aranges section?  gdb and addr2line don't use it, but I'm
+     not sure why.  */
+
+  info.name = ".debug_info";
+  info.start = dwarf_info;
+  info.buf = dwarf_info;
+  info.left = dwarf_info_size;
+  info.is_bigendian = is_bigendian;
+  info.error_callback = error_callback;
+  info.data = data;
+  info.reported_underflow = 0;
+
+  memset (&abbrevs, 0, sizeof abbrevs);
+  while (info.left > 0)
+    {
+      const unsigned char *unit_data_start;
+      uint64_t len;
+      int is_dwarf64;
+      struct dwarf_buf unit_buf;
+      int version;
+      uint64_t abbrev_offset;
+      int addrsize;
+      struct unit *u;
+
+      if (info.reported_underflow)
+	goto fail;
+
+      unit_data_start = info.buf;
+
+      is_dwarf64 = 0;
+      len = read_uint32 (&info);
+      if (len == 0xffffffff)
+	{
+	  len = read_uint64 (&info);
+	  is_dwarf64 = 1;
+	}
+
+      unit_buf = info;
+      unit_buf.left = len;
+
+      if (!advance (&info, len))
+	goto fail;
+
+      version = read_uint16 (&unit_buf);
+      if (version < 2 || version > 4)
+	{
+	  dwarf_buf_error (&unit_buf, "unrecognized DWARF version");
+	  goto fail;
+	}
+
+      abbrev_offset = read_offset (&unit_buf, is_dwarf64);
+      if (!read_abbrevs (state, abbrev_offset, dwarf_abbrev, dwarf_abbrev_size,
+			 is_bigendian, error_callback, data, &abbrevs))
+	goto fail;
+
+      addrsize = read_byte (&unit_buf);
+
+      u = ((struct unit *)
+	   backtrace_alloc (state, sizeof *u, error_callback, data));
+      if (u == NULL)
+	goto fail;
+      u->unit_data = unit_buf.buf;
+      u->unit_data_len = unit_buf.left;
+      u->unit_data_offset = unit_buf.buf - unit_data_start;
+      u->version = version;
+      u->is_dwarf64 = is_dwarf64;
+      u->addrsize = addrsize;
+      u->filename = NULL;
+      u->comp_dir = NULL;
+      u->abs_filename = NULL;
+      u->lineoff = 0;
+      u->abbrevs = abbrevs;
+      memset (&abbrevs, 0, sizeof abbrevs);
+
+      /* The actual line number mappings will be read as needed.  */
+      u->lines = NULL;
+      u->lines_count = 0;
+      u->function_addrs = NULL;
+      u->function_addrs_count = 0;
+
+      if (!find_address_ranges (state, base_address, &unit_buf,
+				dwarf_str, dwarf_str_size,
+				dwarf_ranges, dwarf_ranges_size,
+				is_bigendian, error_callback, data,
+				u, addrs))
+	{
+	  free_abbrevs (state, &u->abbrevs, error_callback, data);
+	  backtrace_free (state, u, sizeof *u, error_callback, data);
+	  goto fail;
+	}
+
+      if (unit_buf.reported_underflow)
+	{
+	  free_abbrevs (state, &u->abbrevs, error_callback, data);
+	  backtrace_free (state, u, sizeof *u, error_callback, data);
+	  goto fail;
+	}
+    }
+  if (info.reported_underflow)
+    goto fail;
+
+  return 1;
+
+ fail:
+  free_abbrevs (state, &abbrevs, error_callback, data);
+  free_unit_addrs_vector (state, addrs, error_callback, data);
+  return 0;
+}
+
+/* Add a new mapping to the vector of line mappings that we are
+   building.  Returns 1 on success, 0 on failure.  */
+
+static int
+add_line (struct backtrace_state *state, struct dwarf_data *ddata,
+	  uintptr_t pc, const char *filename, int lineno,
+	  backtrace_error_callback error_callback, void *data,
+	  struct line_vector *vec)
+{
+  struct line *ln;
+
+  /* If we are adding the same mapping, ignore it.  This can happen
+     when using discriminators.  */
+  if (vec->count > 0)
+    {
+      ln = (struct line *) vec->vec.base + (vec->count - 1);
+      if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno)
+	return 1;
+    }
+
+  ln = ((struct line *)
+	backtrace_vector_grow (state, sizeof (struct line), error_callback,
+			       data, &vec->vec));
+  if (ln == NULL)
+    return 0;
+
+  /* Add in the base address here, so that we can look up the PC
+     directly.  */
+  ln->pc = pc + ddata->base_address;
+
+  ln->filename = filename;
+  ln->lineno = lineno;
+
+  ++vec->count;
+
+  return 1;
+}
+
+/* Free the line header information.  If FREE_FILENAMES is true we
+   free the file names themselves, otherwise we leave them, as there
+   may be line structures pointing to them.  */
+
+static void
+free_line_header (struct backtrace_state *state, struct line_header *hdr,
+		  backtrace_error_callback error_callback, void *data)
+{
+  backtrace_free (state, hdr->dirs, hdr->dirs_count * sizeof (const char *),
+		  error_callback, data);
+  backtrace_free (state, hdr->filenames,
+		  hdr->filenames_count * sizeof (char *),
+		  error_callback, data);
+}
+
+/* Read the line header.  Return 1 on success, 0 on failure.  */
+
+static int
+read_line_header (struct backtrace_state *state, struct unit *u,
+		  int is_dwarf64, struct dwarf_buf *line_buf,
+		  struct line_header *hdr)
+{
+  uint64_t hdrlen;
+  struct dwarf_buf hdr_buf;
+  const unsigned char *p;
+  const unsigned char *pend;
+  size_t i;
+
+  hdr->version = read_uint16 (line_buf);
+  if (hdr->version < 2 || hdr->version > 4)
+    {
+      dwarf_buf_error (line_buf, "unsupported line number version");
+      return 0;
+    }
+
+  hdrlen = read_offset (line_buf, is_dwarf64);
+
+  hdr_buf = *line_buf;
+  hdr_buf.left = hdrlen;
+
+  if (!advance (line_buf, hdrlen))
+    return 0;
+  
+  hdr->min_insn_len = read_byte (&hdr_buf);
+  if (hdr->version < 4)
+    hdr->max_ops_per_insn = 1;
+  else
+    hdr->max_ops_per_insn = read_byte (&hdr_buf);
+
+  /* We don't care about default_is_stmt.  */
+  read_byte (&hdr_buf);
+  
+  hdr->line_base = read_sbyte (&hdr_buf);
+  hdr->line_range = read_byte (&hdr_buf);
+
+  hdr->opcode_base = read_byte (&hdr_buf);
+  hdr->opcode_lengths = hdr_buf.buf;
+  if (!advance (&hdr_buf, hdr->opcode_base - 1))
+    return 0;
+
+  /* Count the number of directory entries.  */
+  hdr->dirs_count = 0;
+  p = hdr_buf.buf;
+  pend = p + hdr_buf.left;
+  while (p < pend && *p != '\0')
+    {
+      p += strnlen((const char *) p, pend - p) + 1;
+      ++hdr->dirs_count;
+    }
+
+  hdr->dirs = ((const char **)
+	       backtrace_alloc (state,
+				hdr->dirs_count * sizeof (const char *),
+				line_buf->error_callback, line_buf->data));
+  if (hdr->dirs == NULL)
+    return 0;
+
+  i = 0;
+  while (*hdr_buf.buf != '\0')
+    {
+      if (hdr_buf.reported_underflow)
+	return 0;
+
+      hdr->dirs[i] = (const char *) hdr_buf.buf;
+      ++i;
+      if (!advance (&hdr_buf,
+		    strnlen ((const char *) hdr_buf.buf, hdr_buf.left) + 1))
+	return 0;
+    }
+  if (!advance (&hdr_buf, 1))
+    return 0;
+
+  /* Count the number of file entries.  */
+  hdr->filenames_count = 0;
+  p = hdr_buf.buf;
+  pend = p + hdr_buf.left;
+  while (p < pend && *p != '\0')
+    {
+      p += strnlen ((const char *) p, pend - p) + 1;
+      p += leb128_len (p);
+      p += leb128_len (p);
+      p += leb128_len (p);
+      ++hdr->filenames_count;
+    }
+
+  hdr->filenames = ((const char **)
+		    backtrace_alloc (state,
+				     hdr->filenames_count * sizeof (char *),
+				     line_buf->error_callback,
+				     line_buf->data));
+  if (hdr->filenames == NULL)
+    return 0;
+  i = 0;
+  while (*hdr_buf.buf != '\0')
+    {
+      const char *filename;
+      uint64_t dir_index;
+
+      if (hdr_buf.reported_underflow)
+	return 0;
+
+      filename = (const char *) hdr_buf.buf;
+      if (!advance (&hdr_buf,
+		    strnlen ((const char *) hdr_buf.buf, hdr_buf.left) + 1))
+	return 0;
+      dir_index = read_uleb128 (&hdr_buf);
+      if (IS_ABSOLUTE_PATH (filename)
+	  || (dir_index == 0 && u->comp_dir == NULL))
+	hdr->filenames[i] = filename;
+      else
+	{
+	  const char *dir;
+	  size_t dir_len;
+	  size_t filename_len;
+	  char *s;
+
+	  if (dir_index == 0)
+	    dir = u->comp_dir;
+	  else if (dir_index - 1 < hdr->dirs_count)
+	    dir = hdr->dirs[dir_index - 1];
+	  else
+	    {
+	      dwarf_buf_error (line_buf,
+			       ("invalid directory index in "
+				"line number program header"));
+	      return 0;
+	    }
+	  dir_len = strlen (dir);
+	  filename_len = strlen (filename);
+	  s = ((char *)
+	       backtrace_alloc (state, dir_len + filename_len + 2,
+				line_buf->error_callback, line_buf->data));
+	  if (s == NULL)
+	    return 0;
+	  memcpy (s, dir, dir_len);
+	  /* FIXME: If we are on a DOS-based file system, and the
+	     directory or the file name use backslashes, then we
+	     should use a backslash here.  */
+	  s[dir_len] = '/';
+	  memcpy (s + dir_len + 1, filename, filename_len + 1);
+	  hdr->filenames[i] = s;
+	}
+
+      /* Ignore the modification time and size.  */
+      read_uleb128 (&hdr_buf);
+      read_uleb128 (&hdr_buf);
+
+      ++i;
+    }
+
+  if (hdr_buf.reported_underflow)
+    return 0;
+
+  return 1;
+}
+
+/* Read the line program, adding line mappings to VEC.  Return 1 on
+   success, 0 on failure.  */
+
+static int
+read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
+		   struct unit *u, const struct line_header *hdr,
+		   struct dwarf_buf *line_buf, struct line_vector *vec)
+{
+  uint64_t address;
+  unsigned int op_index;
+  const char *reset_filename;
+  const char *filename;
+  int lineno;
+
+  address = 0;
+  op_index = 0;
+  if (hdr->filenames_count > 0)
+    reset_filename = hdr->filenames[0];
+  else
+    reset_filename = "";
+  filename = reset_filename;
+  lineno = 1;
+  while (line_buf->left > 0)
+    {
+      unsigned int op;
+
+      op = read_byte (line_buf);
+      if (op >= hdr->opcode_base)
+	{
+	  unsigned int advance;
+
+	  /* Special opcode.  */
+	  op -= hdr->opcode_base;
+	  advance = op / hdr->line_range;
+	  address += (hdr->min_insn_len * (op_index + advance)
+		      / hdr->max_ops_per_insn);
+	  op_index = (op_index + advance) % hdr->max_ops_per_insn;
+	  lineno += hdr->line_base + (int) (op % hdr->line_range);
+	  add_line (state, ddata, address, filename, lineno,
+		    line_buf->error_callback, line_buf->data, vec);
+	}
+      else if (op == DW_LNS_extended_op)
+	{
+	  uint64_t len;
+
+	  len = read_uleb128 (line_buf);
+	  op = read_byte (line_buf);
+	  switch (op)
+	    {
+	    case DW_LNE_end_sequence:
+	      /* FIXME: Should we mark the high PC here?  It seems
+		 that we already have that information from the
+		 compilation unit.  */
+	      address = 0;
+	      op_index = 0;
+	      filename = reset_filename;
+	      lineno = 1;
+	      break;
+	    case DW_LNE_set_address:
+	      address = read_address (line_buf, u->addrsize);
+	      break;
+	    case DW_LNE_define_file:
+	      {
+		const char *f;
+		unsigned int dir_index;
+
+		f = (const char *) line_buf->buf;
+		if (!advance (line_buf, strnlen (f, line_buf->left) + 1))
+		  return 0;
+		dir_index = read_uleb128 (line_buf);
+		/* Ignore that time and length.  */
+		read_uleb128 (line_buf);
+		read_uleb128 (line_buf);
+		if (IS_ABSOLUTE_PATH (f))
+		  filename = f;
+		else
+		  {
+		    const char *dir;
+		    size_t dir_len;
+		    size_t f_len;
+		    char *p;
+
+		    if (dir_index == 0)
+		      dir = u->comp_dir;
+		    else if (dir_index - 1 < hdr->dirs_count)
+		      dir = hdr->dirs[dir_index - 1];
+		    else
+		      {
+			dwarf_buf_error (line_buf,
+					 ("invalid directory index "
+					  "in line number program"));
+			return 0;
+		      }
+		    dir_len = strlen (dir);
+		    f_len = strlen (f);
+		    p = ((char *)
+			 backtrace_alloc (state, dir_len + f_len + 2,
+					  line_buf->error_callback,
+					  line_buf->data));
+		    if (p == NULL)
+		      return 0;
+		    memcpy (p, dir, dir_len);
+		    /* FIXME: If we are on a DOS-based file system,
+		       and the directory or the file name use
+		       backslashes, then we should use a backslash
+		       here.  */
+		    p[dir_len] = '/';
+		    memcpy (p + dir_len + 1, f, f_len + 1);
+		    filename = p;
+		  }
+	      }
+	      break;
+	    case DW_LNE_set_discriminator:
+	      /* We don't care about discriminators.  */
+	      read_uleb128 (line_buf);
+	      break;
+	    default:
+	      if (!advance (line_buf, len - 1))
+		return 0;
+	      break;
+	    }
+	}
+      else
+	{
+	  switch (op)
+	    {
+	    case DW_LNS_copy:
+	      add_line (state, ddata, address, filename, lineno,
+			line_buf->error_callback, line_buf->data, vec);
+	      break;
+	    case DW_LNS_advance_pc:
+	      {
+		uint64_t advance;
+
+		advance = read_uleb128 (line_buf);
+		address += (hdr->min_insn_len * (op_index + advance)
+			    / hdr->max_ops_per_insn);
+		op_index = (op_index + advance) % hdr->max_ops_per_insn;
+	      }
+	      break;
+	    case DW_LNS_advance_line:
+	      lineno += (int) read_sleb128 (line_buf);
+	      break;
+	    case DW_LNS_set_file:
+	      {
+		uint64_t fileno;
+
+		fileno = read_uleb128 (line_buf);
+		if (fileno == 0)
+		  filename = "";
+		else
+		  {
+		    if (fileno - 1 >= hdr->filenames_count)
+		      {
+			dwarf_buf_error (line_buf,
+					 ("invalid file number in "
+					  "line number program"));
+			return 0;
+		      }
+		    filename = hdr->filenames[fileno - 1];
+		  }
+	      }
+	      break;
+	    case DW_LNS_set_column:
+	      read_uleb128 (line_buf);
+	      break;
+	    case DW_LNS_negate_stmt:
+	      break;
+	    case DW_LNS_set_basic_block:
+	      break;
+	    case DW_LNS_const_add_pc:
+	      {
+		unsigned int advance;
+
+		op = 255 - hdr->opcode_base;
+		advance = op / hdr->line_range;
+		address += (hdr->min_insn_len * (op_index + advance)
+			    / hdr->max_ops_per_insn);
+		op_index = (op_index + advance) % hdr->max_ops_per_insn;
+	      }
+	      break;
+	    case DW_LNS_fixed_advance_pc:
+	      address += read_uint16 (line_buf);
+	      op_index = 0;
+	      break;
+	    case DW_LNS_set_prologue_end:
+	      break;
+	    case DW_LNS_set_epilogue_begin:
+	      break;
+	    case DW_LNS_set_isa:
+	      read_uleb128 (line_buf);
+	      break;
+	    default:
+	      {
+		unsigned int i;
+
+		for (i = hdr->opcode_lengths[op - 1]; i > 0; --i)
+		  read_uleb128 (line_buf);
+	      }
+	      break;
+	    }
+	}
+    }
+
+  return 1;
+}
+
+/* Read the line number information for a compilation unit.  Returns 1
+   on success, 0 on failure.  */
+
+static int
+read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,
+		backtrace_error_callback error_callback, void *data,
+		struct unit *u, struct line_header *hdr, struct line **lines,
+		size_t *lines_count)
+{
+  struct line_vector vec;
+  struct dwarf_buf line_buf;
+  uint64_t len;
+  int is_dwarf64;
+  struct line *ln;
+
+  memset (&vec.vec, 0, sizeof vec.vec);
+  vec.count = 0;
+
+  memset (hdr, 0, sizeof *hdr);
+
+  if (u->lineoff != (off_t) (size_t) u->lineoff
+      || (size_t) u->lineoff >= ddata->dwarf_line_size)
+    {
+      error_callback (data, "unit line offset out of range", 0);
+      goto fail;
+    }
+
+  line_buf.name = ".debug_line";
+  line_buf.start = ddata->dwarf_line;
+  line_buf.buf = ddata->dwarf_line + u->lineoff;
+  line_buf.left = ddata->dwarf_line_size - u->lineoff;
+  line_buf.is_bigendian = ddata->is_bigendian;
+  line_buf.error_callback = error_callback;
+  line_buf.data = data;
+  line_buf.reported_underflow = 0;
+
+  is_dwarf64 = 0;
+  len = read_uint32 (&line_buf);
+  if (len == 0xffffffff)
+    {
+      len = read_uint64 (&line_buf);
+      is_dwarf64 = 1;
+    }
+  line_buf.left = len;
+
+  if (!read_line_header (state, u, is_dwarf64, &line_buf, hdr))
+    goto fail;
+
+  if (!read_line_program (state, ddata, u, hdr, &line_buf, &vec))
+    goto fail;
+
+  if (line_buf.reported_underflow)
+    goto fail;
+
+  if (vec.count == 0)
+    {
+      /* This is not a failure in the sense of a generating an error,
+	 but it is a failure in that sense that we have no useful
+	 information.  */
+      goto fail;
+    }
+
+  /* Allocate one extra entry at the end.  */
+  ln = ((struct line *)
+	backtrace_vector_grow (state, sizeof (struct line), error_callback,
+			       data, &vec.vec));
+  if (ln == NULL)
+    goto fail;
+  ln->pc = (uintptr_t) -1;
+  ln->filename = NULL;
+  ln->lineno = 0;
+
+  if (!backtrace_vector_release (state, &vec.vec, error_callback, data))
+    goto fail;
+
+  ln = (struct line *) vec.vec.base;
+  backtrace_qsort (ln, vec.count, sizeof (struct line), line_compare);
+
+  *lines = ln;
+  *lines_count = vec.count;
+
+  return 1;
+
+ fail:
+  vec.vec.alc += vec.vec.size;
+  vec.vec.size = 0;
+  backtrace_vector_release (state, &vec.vec, error_callback, data);
+  free_line_header (state, hdr, error_callback, data);
+  *lines = (struct line *) (uintptr_t) -1;
+  *lines_count = 0;
+  return 0;
+}
+
+/* Read the name of a function from a DIE referenced by a
+   DW_AT_abstract_origin or DW_AT_specification tag.  OFFSET is within
+   the same compilation unit.  */
+
+static const char *
+read_referenced_name (struct dwarf_data *ddata, struct unit *u,
+		      uint64_t offset, backtrace_error_callback error_callback,
+		      void *data)
+{
+  struct dwarf_buf unit_buf;
+  uint64_t code;
+  const struct abbrev *abbrev;
+  const char *ret;
+  size_t i;
+
+  /* OFFSET is from the start of the data for this compilation unit.
+     U->unit_data is the data, but it starts U->unit_data_offset bytes
+     from the beginning.  */
+
+  if (offset < u->unit_data_offset
+      || offset - u->unit_data_offset >= u->unit_data_len)
+    {
+      error_callback (data,
+		      "abstract origin or specification out of range",
+		      0);
+      return NULL;
+    }
+
+  offset -= u->unit_data_offset;
+
+  unit_buf.name = ".debug_info";
+  unit_buf.start = ddata->dwarf_info;
+  unit_buf.buf = u->unit_data + offset;
+  unit_buf.left = u->unit_data_len - offset;
+  unit_buf.is_bigendian = ddata->is_bigendian;
+  unit_buf.error_callback = error_callback;
+  unit_buf.data = data;
+  unit_buf.reported_underflow = 0;
+
+  code = read_uleb128 (&unit_buf);
+  if (code == 0)
+    {
+      dwarf_buf_error (&unit_buf, "invalid abstract origin or specification");
+      return NULL;
+    }
+
+  abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
+  if (abbrev == NULL)
+    return NULL;
+
+  ret = NULL;
+  for (i = 0; i < abbrev->num_attrs; ++i)
+    {
+      struct attr_val val;
+
+      if (!read_attribute (abbrev->attrs[i].form, &unit_buf,
+			   u->is_dwarf64, u->version, u->addrsize,
+			   ddata->dwarf_str, ddata->dwarf_str_size,
+			   &val))
+	return NULL;
+
+      switch (abbrev->attrs[i].name)
+	{
+	case DW_AT_name:
+	  /* We prefer the linkage name if get one.  */
+	  if (val.encoding == ATTR_VAL_STRING)
+	    ret = val.u.string;
+	  break;
+
+	case DW_AT_linkage_name:
+	case DW_AT_MIPS_linkage_name:
+	  if (val.encoding == ATTR_VAL_STRING)
+	    return val.u.string;
+	  break;
+
+	case DW_AT_specification:
+	  if (abbrev->attrs[i].form == DW_FORM_ref_addr
+	      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
+	    {
+	      /* This refers to a specification defined in some other
+		 compilation unit.  We can handle this case if we
+		 must, but it's harder.  */
+	      break;
+	    }
+	  if (val.encoding == ATTR_VAL_UINT
+	      || val.encoding == ATTR_VAL_REF_UNIT)
+	    {
+	      const char *name;
+
+	      name = read_referenced_name (ddata, u, val.u.uint,
+					   error_callback, data);
+	      if (name != NULL)
+		ret = name;
+	    }
+	  break;
+
+	default:
+	  break;
+	}
+    }
+
+  return ret;
+}
+
+/* Add a single range to U that maps to function.  Returns 1 on
+   success, 0 on error.  */
+
+static int
+add_function_range (struct backtrace_state *state, struct dwarf_data *ddata,
+		    struct function *function, uint64_t lowpc, uint64_t highpc,
+		    backtrace_error_callback error_callback,
+		    void *data, struct function_vector *vec)
+{
+  struct function_addrs *p;
+
+  /* Add in the base address here, so that we can look up the PC
+     directly.  */
+  lowpc += ddata->base_address;
+  highpc += ddata->base_address;
+
+  if (vec->count > 0)
+    {
+      p = (struct function_addrs *) vec->vec.base + vec->count - 1;
+      if ((lowpc == p->high || lowpc == p->high + 1)
+	  && function == p->function)
+	{
+	  if (highpc > p->high)
+	    p->high = highpc;
+	  return 1;
+	}
+    }
+
+  p = ((struct function_addrs *)
+       backtrace_vector_grow (state, sizeof (struct function_addrs),
+			      error_callback, data, &vec->vec));
+  if (p == NULL)
+    return 0;
+
+  p->low = lowpc;
+  p->high = highpc;
+  p->function = function;
+  ++vec->count;
+  return 1;
+}
+
+/* Add PC ranges to U that map to FUNCTION.  Returns 1 on success, 0
+   on error.  */
+
+static int
+add_function_ranges (struct backtrace_state *state, struct dwarf_data *ddata,
+		     struct unit *u, struct function *function,
+		     uint64_t ranges, uint64_t base,
+		     backtrace_error_callback error_callback, void *data,
+		     struct function_vector *vec)
+{
+  struct dwarf_buf ranges_buf;
+
+  if (ranges >= ddata->dwarf_ranges_size)
+    {
+      error_callback (data, "function ranges offset out of range", 0);
+      return 0;
+    }
+
+  ranges_buf.name = ".debug_ranges";
+  ranges_buf.start = ddata->dwarf_ranges;
+  ranges_buf.buf = ddata->dwarf_ranges + ranges;
+  ranges_buf.left = ddata->dwarf_ranges_size - ranges;
+  ranges_buf.is_bigendian = ddata->is_bigendian;
+  ranges_buf.error_callback = error_callback;
+  ranges_buf.data = data;
+  ranges_buf.reported_underflow = 0;
+
+  while (1)
+    {
+      uint64_t low;
+      uint64_t high;
+
+      if (ranges_buf.reported_underflow)
+	return 0;
+
+      low = read_address (&ranges_buf, u->addrsize);
+      high = read_address (&ranges_buf, u->addrsize);
+
+      if (low == 0 && high == 0)
+	break;
+
+      if (is_highest_address (low, u->addrsize))
+	base = high;
+      else
+	{
+	  if (!add_function_range (state, ddata, function, low + base,
+				   high + base, error_callback, data, vec))
+	    return 0;
+	}
+    }
+
+  if (ranges_buf.reported_underflow)
+    return 0;
+
+  return 1;
+}
+
+/* Read one entry plus all its children.  Add function addresses to
+   VEC.  Returns 1 on success, 0 on error.  */
+
+static int
+read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
+		     struct unit *u, uint64_t base, struct dwarf_buf *unit_buf,
+		     const struct line_header *lhdr,
+		     backtrace_error_callback error_callback, void *data,
+		     struct function_vector *vec)
+{
+  while (unit_buf->left > 0)
+    {
+      uint64_t code;
+      const struct abbrev *abbrev;
+      int is_function;
+      struct function *function;
+      size_t i;
+      uint64_t lowpc;
+      int have_lowpc;
+      uint64_t highpc;
+      int have_highpc;
+      int highpc_is_relative;
+      uint64_t ranges;
+      int have_ranges;
+
+      code = read_uleb128 (unit_buf);
+      if (code == 0)
+	return 1;
+
+      abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
+      if (abbrev == NULL)
+	return 0;
+
+      is_function = (abbrev->tag == DW_TAG_subprogram
+		     || abbrev->tag == DW_TAG_entry_point
+		     || abbrev->tag == DW_TAG_inlined_subroutine);
+
+      function = NULL;
+      if (is_function)
+	{
+	  function = ((struct function *)
+		      backtrace_alloc (state, sizeof *function,
+				       error_callback, data));
+	  if (function == NULL)
+	    return 0;
+	  memset (function, 0, sizeof *function);
+	}
+
+      lowpc = 0;
+      have_lowpc = 0;
+      highpc = 0;
+      have_highpc = 0;
+      highpc_is_relative = 0;
+      ranges = 0;
+      have_ranges = 0;
+      for (i = 0; i < abbrev->num_attrs; ++i)
+	{
+	  struct attr_val val;
+
+	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
+			       u->is_dwarf64, u->version, u->addrsize,
+			       ddata->dwarf_str, ddata->dwarf_str_size,
+			       &val))
+	    return 0;
+
+	  /* The compile unit sets the base address for any address
+	     ranges in the function entries.  */
+	  if (abbrev->tag == DW_TAG_compile_unit
+	      && abbrev->attrs[i].name == DW_AT_low_pc
+	      && val.encoding == ATTR_VAL_ADDRESS)
+	    base = val.u.uint;
+
+	  if (is_function)
+	    {
+	      switch (abbrev->attrs[i].name)
+		{
+		case DW_AT_call_file:
+		  if (val.encoding == ATTR_VAL_UINT)
+		    {
+		      if (val.u.uint == 0)
+			function->caller_filename = "";
+		      else
+			{
+			  if (val.u.uint - 1 >= lhdr->filenames_count)
+			    {
+			      dwarf_buf_error (unit_buf,
+					       ("invalid file number in "
+						"DW_AT_call_file attribute"));
+			      return 0;
+			    }
+			  function->caller_filename =
+			    lhdr->filenames[val.u.uint - 1];
+			}
+		    }
+		  break;
+
+		case DW_AT_call_line:
+		  if (val.encoding == ATTR_VAL_UINT)
+		    function->caller_lineno = val.u.uint;
+		  break;
+
+		case DW_AT_abstract_origin:
+		case DW_AT_specification:
+		  if (abbrev->attrs[i].form == DW_FORM_ref_addr
+		      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
+		    {
+		      /* This refers to an abstract origin defined in
+			 some other compilation unit.  We can handle
+			 this case if we must, but it's harder.  */
+		      break;
+		    }
+		  if (val.encoding == ATTR_VAL_UINT
+		      || val.encoding == ATTR_VAL_REF_UNIT)
+		    {
+		      const char *name;
+
+		      name = read_referenced_name (ddata, u, val.u.uint,
+						   error_callback, data);
+		      if (name != NULL)
+			function->name = name;
+		    }
+		  break;
+
+		case DW_AT_name:
+		  if (val.encoding == ATTR_VAL_STRING)
+		    {
+		      /* Don't override a name we found in some other
+			 way, as it will normally be more
+			 useful--e.g., this name is normally not
+			 mangled.  */
+		      if (function->name == NULL)
+			function->name = val.u.string;
+		    }
+		  break;
+
+		case DW_AT_linkage_name:
+		case DW_AT_MIPS_linkage_name:
+		  if (val.encoding == ATTR_VAL_STRING)
+		    function->name = val.u.string;
+		  break;
+
+		case DW_AT_low_pc:
+		  if (val.encoding == ATTR_VAL_ADDRESS)
+		    {
+		      lowpc = val.u.uint;
+		      have_lowpc = 1;
+		    }
+		  break;
+
+		case DW_AT_high_pc:
+		  if (val.encoding == ATTR_VAL_ADDRESS)
+		    {
+		      highpc = val.u.uint;
+		      have_highpc = 1;
+		    }
+		  else if (val.encoding == ATTR_VAL_UINT)
+		    {
+		      highpc = val.u.uint;
+		      have_highpc = 1;
+		      highpc_is_relative = 1;
+		    }
+		  break;
+
+		case DW_AT_ranges:
+		  if (val.encoding == ATTR_VAL_UINT
+		      || val.encoding == ATTR_VAL_REF_SECTION)
+		    {
+		      ranges = val.u.uint;
+		      have_ranges = 1;
+		    }
+		  break;
+
+		default:
+		  break;
+		}
+	    }
+	}
+
+      /* If we couldn't find a name for the function, we have no use
+	 for it.  */
+      if (is_function && function->name == NULL)
+	{
+	  backtrace_free (state, function, sizeof *function,
+			  error_callback, data);
+	  is_function = 0;
+	}
+
+      if (is_function)
+	{
+	  if (have_ranges)
+	    {
+	      if (!add_function_ranges (state, ddata, u, function, ranges,
+					base, error_callback, data, vec))
+		return 0;
+	    }
+	  else if (have_lowpc && have_highpc)
+	    {
+	      if (highpc_is_relative)
+		highpc += lowpc;
+	      if (!add_function_range (state, ddata, function, lowpc, highpc,
+				       error_callback, data, vec))
+		return 0;
+	    }
+	  else
+	    {
+	      backtrace_free (state, function, sizeof *function,
+			      error_callback, data);
+	      is_function = 0;
+	    }
+	}
+
+      if (abbrev->has_children)
+	{
+	  if (!is_function)
+	    {
+	      if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
+					error_callback, data, vec))
+		return 0;
+	    }
+	  else
+	    {
+	      struct function_vector fvec;
+
+	      /* Gather any information for inlined functions in
+		 FVEC.  */
+
+	      memset (&fvec, 0, sizeof fvec);
+
+	      if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
+					error_callback, data, &fvec))
+		return 0;
+
+	      if (fvec.count > 0)
+		{
+		  struct function_addrs *faddrs;
+
+		  if (!backtrace_vector_release (state, &fvec.vec,
+						 error_callback, data))
+		    return 0;
+
+		  faddrs = (struct function_addrs *) fvec.vec.base;
+		  backtrace_qsort (faddrs, fvec.count,
+				   sizeof (struct function_addrs),
+				   function_addrs_compare);
+
+		  function->function_addrs = faddrs;
+		  function->function_addrs_count = fvec.count;
+		}
+	    }
+	}
+    }
+
+  return 1;
+}
+
+/* Read function name information for a compilation unit.  We look
+   through the whole unit looking for function tags.  */
+
+static void
+read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
+		    const struct line_header *lhdr,
+		    backtrace_error_callback error_callback, void *data,
+		    struct unit *u, struct function_vector *fvec,
+		    struct function_addrs **ret_addrs,
+		    size_t *ret_addrs_count)
+{
+  struct function_vector lvec;
+  struct function_vector *pfvec;
+  struct dwarf_buf unit_buf;
+  struct function_addrs *addrs;
+  size_t addrs_count;
+
+  /* Use FVEC if it is not NULL.  Otherwise use our own vector.  */
+  if (fvec != NULL)
+    pfvec = fvec;
+  else
+    {
+      memset (&lvec, 0, sizeof lvec);
+      pfvec = &lvec;
+    }
+
+  unit_buf.name = ".debug_info";
+  unit_buf.start = ddata->dwarf_info;
+  unit_buf.buf = u->unit_data;
+  unit_buf.left = u->unit_data_len;
+  unit_buf.is_bigendian = ddata->is_bigendian;
+  unit_buf.error_callback = error_callback;
+  unit_buf.data = data;
+  unit_buf.reported_underflow = 0;
+
+  while (unit_buf.left > 0)
+    {
+      if (!read_function_entry (state, ddata, u, 0, &unit_buf, lhdr,
+				error_callback, data, pfvec))
+	return;
+    }
+
+  if (pfvec->count == 0)
+    return;
+
+  addrs_count = pfvec->count;
+
+  if (fvec == NULL)
+    {
+      if (!backtrace_vector_release (state, &lvec.vec, error_callback, data))
+	return;
+      addrs = (struct function_addrs *) pfvec->vec.base;
+    }
+  else
+    {
+      /* Finish this list of addresses, but leave the remaining space in
+	 the vector available for the next function unit.  */
+      addrs = ((struct function_addrs *)
+	       backtrace_vector_finish (state, &fvec->vec,
+					error_callback, data));
+      if (addrs == NULL)
+	return;
+      fvec->count = 0;
+    }
+
+  backtrace_qsort (addrs, addrs_count, sizeof (struct function_addrs),
+		   function_addrs_compare);
+
+  *ret_addrs = addrs;
+  *ret_addrs_count = addrs_count;
+}
+
+/* See if PC is inlined in FUNCTION.  If it is, print out the inlined
+   information, and update FILENAME and LINENO for the caller.
+   Returns whatever CALLBACK returns, or 0 to keep going.  */
+
+static int
+report_inlined_functions (uintptr_t pc, struct function *function,
+			  backtrace_full_callback callback, void *data,
+			  const char **filename, int *lineno)
+{
+  struct function_addrs *function_addrs;
+  struct function *inlined;
+  int ret;
+
+  if (function->function_addrs_count == 0)
+    return 0;
+
+  function_addrs = ((struct function_addrs *)
+		    bsearch (&pc, function->function_addrs,
+			     function->function_addrs_count,
+			     sizeof (struct function_addrs),
+			     function_addrs_search));
+  if (function_addrs == NULL)
+    return 0;
+
+  while (((size_t) (function_addrs - function->function_addrs) + 1
+	  < function->function_addrs_count)
+	 && pc >= (function_addrs + 1)->low
+	 && pc < (function_addrs + 1)->high)
+    ++function_addrs;
+
+  /* We found an inlined call.  */
+
+  inlined = function_addrs->function;
+
+  /* Report any calls inlined into this one.  */
+  ret = report_inlined_functions (pc, inlined, callback, data,
+				  filename, lineno);
+  if (ret != 0)
+    return ret;
+
+  /* Report this inlined call.  */
+  ret = callback (data, pc, *filename, *lineno, inlined->name);
+  if (ret != 0)
+    return ret;
+
+  /* Our caller will report the caller of the inlined function; tell
+     it the appropriate filename and line number.  */
+  *filename = inlined->caller_filename;
+  *lineno = inlined->caller_lineno;
+
+  return 0;
+}
+
+/* Look for a PC in the DWARF mapping for one module.  On success,
+   call CALLBACK and return whatever it returns.  On error, call
+   ERROR_CALLBACK and return 0.  Sets *FOUND to 1 if the PC is found,
+   0 if not.  */
+
+static int
+dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
+		 uintptr_t pc, backtrace_full_callback callback,
+		 backtrace_error_callback error_callback, void *data,
+		 int *found)
+{
+  struct unit_addrs *entry;
+  struct unit *u;
+  int new_data;
+  struct line *lines;
+  struct line *ln;
+  struct function_addrs *function_addrs;
+  struct function *function;
+  const char *filename;
+  int lineno;
+  int ret;
+
+  *found = 1;
+
+  /* Find an address range that includes PC.  */
+  entry = bsearch (&pc, ddata->addrs, ddata->addrs_count,
+		   sizeof (struct unit_addrs), unit_addrs_search);
+
+  if (entry == NULL)
+    {
+      *found = 0;
+      return 0;
+    }
+
+  /* If there are multiple ranges that contain PC, use the last one,
+     in order to produce predictable results.  If we assume that all
+     ranges are properly nested, then the last range will be the
+     smallest one.  */
+  while ((size_t) (entry - ddata->addrs) + 1 < ddata->addrs_count
+	 && pc >= (entry + 1)->low
+	 && pc < (entry + 1)->high)
+    ++entry;
+
+  /* We need the lines, lines_count, function_addrs,
+     function_addrs_count fields of u.  If they are not set, we need
+     to set them.  When running in threaded mode, we need to allow for
+     the possibility that some other thread is setting them
+     simultaneously.  */
+
+  u = entry->u;
+  lines = u->lines;
+
+  /* Skip units with no useful line number information by walking
+     backward.  Useless line number information is marked by setting
+     lines == -1.  */
+  while (entry > ddata->addrs
+	 && pc >= (entry - 1)->low
+	 && pc < (entry - 1)->high)
+    {
+      if (state->threaded)
+	lines = (struct line *) backtrace_atomic_load_pointer (&u->lines);
+
+      if (lines != (struct line *) (uintptr_t) -1)
+	break;
+
+      --entry;
+
+      u = entry->u;
+      lines = u->lines;
+    }
+
+  if (state->threaded)
+    lines = backtrace_atomic_load_pointer (&u->lines);
+
+  new_data = 0;
+  if (lines == NULL)
+    {
+      size_t function_addrs_count;
+      struct line_header lhdr;
+      size_t count;
+
+      /* We have never read the line information for this unit.  Read
+	 it now.  */
+
+      function_addrs = NULL;
+      function_addrs_count = 0;
+      if (read_line_info (state, ddata, error_callback, data, entry->u, &lhdr,
+			  &lines, &count))
+	{
+	  struct function_vector *pfvec;
+
+	  /* If not threaded, reuse DDATA->FVEC for better memory
+	     consumption.  */
+	  if (state->threaded)
+	    pfvec = NULL;
+	  else
+	    pfvec = &ddata->fvec;
+	  read_function_info (state, ddata, &lhdr, error_callback, data,
+			      entry->u, pfvec, &function_addrs,
+			      &function_addrs_count);
+	  free_line_header (state, &lhdr, error_callback, data);
+	  new_data = 1;
+	}
+
+      /* Atomically store the information we just read into the unit.
+	 If another thread is simultaneously writing, it presumably
+	 read the same information, and we don't care which one we
+	 wind up with; we just leak the other one.  We do have to
+	 write the lines field last, so that the acquire-loads above
+	 ensure that the other fields are set.  */
+
+      if (!state->threaded)
+	{
+	  u->lines_count = count;
+	  u->function_addrs = function_addrs;
+	  u->function_addrs_count = function_addrs_count;
+	  u->lines = lines;
+	}
+      else
+	{
+	  backtrace_atomic_store_size_t (&u->lines_count, count);
+	  backtrace_atomic_store_pointer (&u->function_addrs, function_addrs);
+	  backtrace_atomic_store_size_t (&u->function_addrs_count,
+					 function_addrs_count);
+	  backtrace_atomic_store_pointer (&u->lines, lines);
+	}
+    }
+
+  /* Now all fields of U have been initialized.  */
+
+  if (lines == (struct line *) (uintptr_t) -1)
+    {
+      /* If reading the line number information failed in some way,
+	 try again to see if there is a better compilation unit for
+	 this PC.  */
+      if (new_data)
+	return dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
+				data, found);
+      return callback (data, pc, NULL, 0, NULL);
+    }
+
+  /* Search for PC within this unit.  */
+
+  ln = (struct line *) bsearch (&pc, lines, entry->u->lines_count,
+				sizeof (struct line), line_search);
+  if (ln == NULL)
+    {
+      /* The PC is between the low_pc and high_pc attributes of the
+	 compilation unit, but no entry in the line table covers it.
+	 This implies that the start of the compilation unit has no
+	 line number information.  */
+
+      if (entry->u->abs_filename == NULL)
+	{
+	  const char *filename;
+
+	  filename = entry->u->filename;
+	  if (filename != NULL
+	      && !IS_ABSOLUTE_PATH (filename)
+	      && entry->u->comp_dir != NULL)
+	    {
+	      size_t filename_len;
+	      const char *dir;
+	      size_t dir_len;
+	      char *s;
+
+	      filename_len = strlen (filename);
+	      dir = entry->u->comp_dir;
+	      dir_len = strlen (dir);
+	      s = (char *) backtrace_alloc (state, dir_len + filename_len + 2,
+					    error_callback, data);
+	      if (s == NULL)
+		{
+		  *found = 0;
+		  return 0;
+		}
+	      memcpy (s, dir, dir_len);
+	      /* FIXME: Should use backslash if DOS file system.  */
+	      s[dir_len] = '/';
+	      memcpy (s + dir_len + 1, filename, filename_len + 1);
+	      filename = s;
+	    }
+	  entry->u->abs_filename = filename;
+	}
+
+      return callback (data, pc, entry->u->abs_filename, 0, NULL);
+    }
+
+  /* Search for function name within this unit.  */
+
+  if (entry->u->function_addrs_count == 0)
+    return callback (data, pc, ln->filename, ln->lineno, NULL);
+
+  function_addrs = ((struct function_addrs *)
+		    bsearch (&pc, entry->u->function_addrs,
+			     entry->u->function_addrs_count,
+			     sizeof (struct function_addrs),
+			     function_addrs_search));
+  if (function_addrs == NULL)
+    return callback (data, pc, ln->filename, ln->lineno, NULL);
+
+  /* If there are multiple function ranges that contain PC, use the
+     last one, in order to produce predictable results.  */
+
+  while (((size_t) (function_addrs - entry->u->function_addrs + 1)
+	  < entry->u->function_addrs_count)
+	 && pc >= (function_addrs + 1)->low
+	 && pc < (function_addrs + 1)->high)
+    ++function_addrs;
+
+  function = function_addrs->function;
+
+  filename = ln->filename;
+  lineno = ln->lineno;
+
+  ret = report_inlined_functions (pc, function, callback, data,
+				  &filename, &lineno);
+  if (ret != 0)
+    return ret;
+
+  return callback (data, pc, filename, lineno, function->name);
+}
+
+
+/* Return the file/line information for a PC using the DWARF mapping
+   we built earlier.  */
+
+static int
+dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
+		backtrace_full_callback callback,
+		backtrace_error_callback error_callback, void *data)
+{
+  struct dwarf_data *ddata;
+  int found;
+  int ret;
+
+  if (!state->threaded)
+    {
+      for (ddata = (struct dwarf_data *) state->fileline_data;
+	   ddata != NULL;
+	   ddata = ddata->next)
+	{
+	  ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
+				 data, &found);
+	  if (ret != 0 || found)
+	    return ret;
+	}
+    }
+  else
+    {
+      struct dwarf_data **pp;
+
+      pp = (struct dwarf_data **) (void *) &state->fileline_data;
+      while (1)
+	{
+	  ddata = backtrace_atomic_load_pointer (pp);
+	  if (ddata == NULL)
+	    break;
+
+	  ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
+				 data, &found);
+	  if (ret != 0 || found)
+	    return ret;
+
+	  pp = &ddata->next;
+	}
+    }
+
+  /* FIXME: See if any libraries have been dlopen'ed.  */
+
+  return callback (data, pc, NULL, 0, NULL);
+}
+
+/* Initialize our data structures from the DWARF debug info for a
+   file.  Return NULL on failure.  */
+
+static struct dwarf_data *
+build_dwarf_data (struct backtrace_state *state,
+		  uintptr_t base_address,
+		  const unsigned char *dwarf_info,
+		  size_t dwarf_info_size,
+		  const unsigned char *dwarf_line,
+		  size_t dwarf_line_size,
+		  const unsigned char *dwarf_abbrev,
+		  size_t dwarf_abbrev_size,
+		  const unsigned char *dwarf_ranges,
+		  size_t dwarf_ranges_size,
+		  const unsigned char *dwarf_str,
+		  size_t dwarf_str_size,
+		  int is_bigendian,
+		  backtrace_error_callback error_callback,
+		  void *data)
+{
+  struct unit_addrs_vector addrs_vec;
+  struct unit_addrs *addrs;
+  size_t addrs_count;
+  struct dwarf_data *fdata;
+
+  if (!build_address_map (state, base_address, dwarf_info, dwarf_info_size,
+			  dwarf_abbrev, dwarf_abbrev_size, dwarf_ranges,
+			  dwarf_ranges_size, dwarf_str, dwarf_str_size,
+			  is_bigendian, error_callback, data, &addrs_vec))
+    return NULL;
+
+  if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))
+    return NULL;
+  addrs = (struct unit_addrs *) addrs_vec.vec.base;
+  addrs_count = addrs_vec.count;
+  backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),
+		   unit_addrs_compare);
+
+  fdata = ((struct dwarf_data *)
+	   backtrace_alloc (state, sizeof (struct dwarf_data),
+			    error_callback, data));
+  if (fdata == NULL)
+    return NULL;
+
+  fdata->next = NULL;
+  fdata->base_address = base_address;
+  fdata->addrs = addrs;
+  fdata->addrs_count = addrs_count;
+  fdata->dwarf_info = dwarf_info;
+  fdata->dwarf_info_size = dwarf_info_size;
+  fdata->dwarf_line = dwarf_line;
+  fdata->dwarf_line_size = dwarf_line_size;
+  fdata->dwarf_ranges = dwarf_ranges;
+  fdata->dwarf_ranges_size = dwarf_ranges_size;
+  fdata->dwarf_str = dwarf_str;
+  fdata->dwarf_str_size = dwarf_str_size;
+  fdata->is_bigendian = is_bigendian;
+  memset (&fdata->fvec, 0, sizeof fdata->fvec);
+
+  return fdata;
+}
+
+/* Build our data structures from the DWARF sections for a module.
+   Set FILELINE_FN and STATE->FILELINE_DATA.  Return 1 on success, 0
+   on failure.  */
+
+int
+backtrace_dwarf_add (struct backtrace_state *state,
+		     uintptr_t base_address,
+		     const unsigned char *dwarf_info,
+		     size_t dwarf_info_size,
+		     const unsigned char *dwarf_line,
+		     size_t dwarf_line_size,
+		     const unsigned char *dwarf_abbrev,
+		     size_t dwarf_abbrev_size,
+		     const unsigned char *dwarf_ranges,
+		     size_t dwarf_ranges_size,
+		     const unsigned char *dwarf_str,
+		     size_t dwarf_str_size,
+		     int is_bigendian,
+		     backtrace_error_callback error_callback,
+		     void *data, fileline *fileline_fn)
+{
+  struct dwarf_data *fdata;
+
+  fdata = build_dwarf_data (state, base_address, dwarf_info, dwarf_info_size,
+			    dwarf_line, dwarf_line_size, dwarf_abbrev,
+			    dwarf_abbrev_size, dwarf_ranges, dwarf_ranges_size,
+			    dwarf_str, dwarf_str_size, is_bigendian,
+			    error_callback, data);
+  if (fdata == NULL)
+    return 0;
+
+  if (!state->threaded)
+    {
+      struct dwarf_data **pp;
+
+      for (pp = (struct dwarf_data **) (void *) &state->fileline_data;
+	   *pp != NULL;
+	   pp = &(*pp)->next)
+	;
+      *pp = fdata;
+    }
+  else
+    {
+      while (1)
+	{
+	  struct dwarf_data **pp;
+
+	  pp = (struct dwarf_data **) (void *) &state->fileline_data;
+
+	  while (1)
+	    {
+	      struct dwarf_data *p;
+
+	      p = backtrace_atomic_load_pointer (pp);
+
+	      if (p == NULL)
+		break;
+
+	      pp = &p->next;
+	    }
+
+	  if (__sync_bool_compare_and_swap (pp, NULL, fdata))
+	    break;
+	}
+    }
+
+  *fileline_fn = dwarf_fileline;
+
+  return 1;
+}
diff --git a/third_party/gofrontend/libbacktrace/elf.c b/third_party/gofrontend/libbacktrace/elf.c
new file mode 100644
index 0000000..e63aaf5
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/elf.c
@@ -0,0 +1,976 @@
+/* elf.c -- Get debug data from an ELF file for backtraces.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#ifdef HAVE_DL_ITERATE_PHDR
+#include <link.h>
+#endif
+
+#include "backtrace.h"
+#include "internal.h"
+
+#ifndef HAVE_DL_ITERATE_PHDR
+
+/* Dummy version of dl_iterate_phdr for systems that don't have it.  */
+
+#define dl_phdr_info x_dl_phdr_info
+#define dl_iterate_phdr x_dl_iterate_phdr
+
+struct dl_phdr_info
+{
+  uintptr_t dlpi_addr;
+  const char *dlpi_name;
+};
+
+static int
+dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
+				  size_t, void *) ATTRIBUTE_UNUSED,
+		 void *data ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+#endif /* ! defined (HAVE_DL_ITERATE_PHDR) */
+
+/* The configure script must tell us whether we are 32-bit or 64-bit
+   ELF.  We could make this code test and support either possibility,
+   but there is no point.  This code only works for the currently
+   running executable, which means that we know the ELF mode at
+   configure mode.  */
+
+#if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64
+#error "Unknown BACKTRACE_ELF_SIZE"
+#endif
+
+/* <link.h> might #include <elf.h> which might define our constants
+   with slightly different values.  Undefine them to be safe.  */
+
+#undef EI_NIDENT
+#undef EI_MAG0
+#undef EI_MAG1
+#undef EI_MAG2
+#undef EI_MAG3
+#undef EI_CLASS
+#undef EI_DATA
+#undef EI_VERSION
+#undef ELF_MAG0
+#undef ELF_MAG1
+#undef ELF_MAG2
+#undef ELF_MAG3
+#undef ELFCLASS32
+#undef ELFCLASS64
+#undef ELFDATA2LSB
+#undef ELFDATA2MSB
+#undef EV_CURRENT
+#undef ET_DYN
+#undef SHN_LORESERVE
+#undef SHN_XINDEX
+#undef SHN_UNDEF
+#undef SHT_SYMTAB
+#undef SHT_STRTAB
+#undef SHT_DYNSYM
+#undef STT_OBJECT
+#undef STT_FUNC
+
+/* Basic types.  */
+
+typedef uint16_t b_elf_half;    /* Elf_Half.  */
+typedef uint32_t b_elf_word;    /* Elf_Word.  */
+typedef int32_t  b_elf_sword;   /* Elf_Sword.  */
+
+#if BACKTRACE_ELF_SIZE == 32
+
+typedef uint32_t b_elf_addr;    /* Elf_Addr.  */
+typedef uint32_t b_elf_off;     /* Elf_Off.  */
+
+typedef uint32_t b_elf_wxword;  /* 32-bit Elf_Word, 64-bit ELF_Xword.  */
+
+#else
+
+typedef uint64_t b_elf_addr;    /* Elf_Addr.  */
+typedef uint64_t b_elf_off;     /* Elf_Off.  */
+typedef uint64_t b_elf_xword;   /* Elf_Xword.  */
+typedef int64_t  b_elf_sxword;  /* Elf_Sxword.  */
+
+typedef uint64_t b_elf_wxword;  /* 32-bit Elf_Word, 64-bit ELF_Xword.  */
+
+#endif
+
+/* Data structures and associated constants.  */
+
+#define EI_NIDENT 16
+
+typedef struct {
+  unsigned char	e_ident[EI_NIDENT];	/* ELF "magic number" */
+  b_elf_half	e_type;			/* Identifies object file type */
+  b_elf_half	e_machine;		/* Specifies required architecture */
+  b_elf_word	e_version;		/* Identifies object file version */
+  b_elf_addr	e_entry;		/* Entry point virtual address */
+  b_elf_off	e_phoff;		/* Program header table file offset */
+  b_elf_off	e_shoff;		/* Section header table file offset */
+  b_elf_word	e_flags;		/* Processor-specific flags */
+  b_elf_half	e_ehsize;		/* ELF header size in bytes */
+  b_elf_half	e_phentsize;		/* Program header table entry size */
+  b_elf_half	e_phnum;		/* Program header table entry count */
+  b_elf_half	e_shentsize;		/* Section header table entry size */
+  b_elf_half	e_shnum;		/* Section header table entry count */
+  b_elf_half	e_shstrndx;		/* Section header string table index */
+} b_elf_ehdr;  /* Elf_Ehdr.  */
+
+#define EI_MAG0 0
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4
+#define EI_DATA 5
+#define EI_VERSION 6
+
+#define ELFMAG0 0x7f
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+
+#define EV_CURRENT 1
+
+#define ET_DYN 3
+
+typedef struct {
+  b_elf_word	sh_name;		/* Section name, index in string tbl */
+  b_elf_word	sh_type;		/* Type of section */
+  b_elf_wxword	sh_flags;		/* Miscellaneous section attributes */
+  b_elf_addr	sh_addr;		/* Section virtual addr at execution */
+  b_elf_off	sh_offset;		/* Section file offset */
+  b_elf_wxword	sh_size;		/* Size of section in bytes */
+  b_elf_word	sh_link;		/* Index of another section */
+  b_elf_word	sh_info;		/* Additional section information */
+  b_elf_wxword	sh_addralign;		/* Section alignment */
+  b_elf_wxword	sh_entsize;		/* Entry size if section holds table */
+} b_elf_shdr;  /* Elf_Shdr.  */
+
+#define SHN_UNDEF	0x0000		/* Undefined section */
+#define SHN_LORESERVE	0xFF00		/* Begin range of reserved indices */
+#define SHN_XINDEX	0xFFFF		/* Section index is held elsewhere */
+
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+#define SHT_DYNSYM 11
+
+#if BACKTRACE_ELF_SIZE == 32
+
+typedef struct
+{
+  b_elf_word	st_name;		/* Symbol name, index in string tbl */
+  b_elf_addr	st_value;		/* Symbol value */
+  b_elf_word	st_size;		/* Symbol size */
+  unsigned char	st_info;		/* Symbol binding and type */
+  unsigned char	st_other;		/* Visibility and other data */
+  b_elf_half	st_shndx;		/* Symbol section index */
+} b_elf_sym;  /* Elf_Sym.  */
+
+#else /* BACKTRACE_ELF_SIZE != 32 */
+
+typedef struct
+{
+  b_elf_word	st_name;		/* Symbol name, index in string tbl */
+  unsigned char	st_info;		/* Symbol binding and type */
+  unsigned char	st_other;		/* Visibility and other data */
+  b_elf_half	st_shndx;		/* Symbol section index */
+  b_elf_addr	st_value;		/* Symbol value */
+  b_elf_xword	st_size;		/* Symbol size */
+} b_elf_sym;  /* Elf_Sym.  */
+
+#endif /* BACKTRACE_ELF_SIZE != 32 */
+
+#define STT_OBJECT 1
+#define STT_FUNC 2
+
+/* An index of ELF sections we care about.  */
+
+enum debug_section
+{
+  DEBUG_INFO,
+  DEBUG_LINE,
+  DEBUG_ABBREV,
+  DEBUG_RANGES,
+  DEBUG_STR,
+  DEBUG_MAX
+};
+
+/* Names of sections, indexed by enum elf_section.  */
+
+static const char * const debug_section_names[DEBUG_MAX] =
+{
+  ".debug_info",
+  ".debug_line",
+  ".debug_abbrev",
+  ".debug_ranges",
+  ".debug_str"
+};
+
+/* Information we gather for the sections we care about.  */
+
+struct debug_section_info
+{
+  /* Section file offset.  */
+  off_t offset;
+  /* Section size.  */
+  size_t size;
+  /* Section contents, after read from file.  */
+  const unsigned char *data;
+};
+
+/* Information we keep for an ELF symbol.  */
+
+struct elf_symbol
+{
+  /* The name of the symbol.  */
+  const char *name;
+  /* The address of the symbol.  */
+  uintptr_t address;
+  /* The size of the symbol.  */
+  size_t size;
+};
+
+/* Information to pass to elf_syminfo.  */
+
+struct elf_syminfo_data
+{
+  /* Symbols for the next module.  */
+  struct elf_syminfo_data *next;
+  /* The ELF symbols, sorted by address.  */
+  struct elf_symbol *symbols;
+  /* The number of symbols.  */
+  size_t count;
+};
+
+/* A dummy callback function used when we can't find any debug info.  */
+
+static int
+elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
+	     uintptr_t pc ATTRIBUTE_UNUSED,
+	     backtrace_full_callback callback ATTRIBUTE_UNUSED,
+	     backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data, "no debug info in ELF executable", -1);
+  return 0;
+}
+
+/* A dummy callback function used when we can't find a symbol
+   table.  */
+
+static void
+elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
+	    uintptr_t addr ATTRIBUTE_UNUSED,
+	    backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
+	    backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data, "no symbol table in ELF executable", -1);
+}
+
+/* Compare struct elf_symbol for qsort.  */
+
+static int
+elf_symbol_compare (const void *v1, const void *v2)
+{
+  const struct elf_symbol *e1 = (const struct elf_symbol *) v1;
+  const struct elf_symbol *e2 = (const struct elf_symbol *) v2;
+
+  if (e1->address < e2->address)
+    return -1;
+  else if (e1->address > e2->address)
+    return 1;
+  else
+    return 0;
+}
+
+/* Compare an ADDR against an elf_symbol for bsearch.  We allocate one
+   extra entry in the array so that this can look safely at the next
+   entry.  */
+
+static int
+elf_symbol_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct elf_symbol *entry = (const struct elf_symbol *) ventry;
+  uintptr_t addr;
+
+  addr = *key;
+  if (addr < entry->address)
+    return -1;
+  else if (addr >= entry->address + entry->size)
+    return 1;
+  else
+    return 0;
+}
+
+/* Initialize the symbol table info for elf_syminfo.  */
+
+static int
+elf_initialize_syminfo (struct backtrace_state *state,
+			uintptr_t base_address,
+			const unsigned char *symtab_data, size_t symtab_size,
+			const unsigned char *strtab, size_t strtab_size,
+			backtrace_error_callback error_callback,
+			void *data, struct elf_syminfo_data *sdata)
+{
+  size_t sym_count;
+  const b_elf_sym *sym;
+  size_t elf_symbol_count;
+  size_t elf_symbol_size;
+  struct elf_symbol *elf_symbols;
+  size_t i;
+  unsigned int j;
+
+  sym_count = symtab_size / sizeof (b_elf_sym);
+
+  /* We only care about function symbols.  Count them.  */
+  sym = (const b_elf_sym *) symtab_data;
+  elf_symbol_count = 0;
+  for (i = 0; i < sym_count; ++i, ++sym)
+    {
+      int info;
+
+      info = sym->st_info & 0xf;
+      if ((info == STT_FUNC || info == STT_OBJECT)
+	  && sym->st_shndx != SHN_UNDEF)
+	++elf_symbol_count;
+    }
+
+  elf_symbol_size = elf_symbol_count * sizeof (struct elf_symbol);
+  elf_symbols = ((struct elf_symbol *)
+		 backtrace_alloc (state, elf_symbol_size, error_callback,
+				  data));
+  if (elf_symbols == NULL)
+    return 0;
+
+  sym = (const b_elf_sym *) symtab_data;
+  j = 0;
+  for (i = 0; i < sym_count; ++i, ++sym)
+    {
+      int info;
+
+      info = sym->st_info & 0xf;
+      if (info != STT_FUNC && info != STT_OBJECT)
+	continue;
+      if (sym->st_shndx == SHN_UNDEF)
+	continue;
+      if (sym->st_name >= strtab_size)
+	{
+	  error_callback (data, "symbol string index out of range", 0);
+	  backtrace_free (state, elf_symbols, elf_symbol_size, error_callback,
+			  data);
+	  return 0;
+	}
+      elf_symbols[j].name = (const char *) strtab + sym->st_name;
+      elf_symbols[j].address = sym->st_value + base_address;
+      elf_symbols[j].size = sym->st_size;
+      ++j;
+    }
+
+  backtrace_qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol),
+		   elf_symbol_compare);
+
+  sdata->next = NULL;
+  sdata->symbols = elf_symbols;
+  sdata->count = elf_symbol_count;
+
+  return 1;
+}
+
+/* Add EDATA to the list in STATE.  */
+
+static void
+elf_add_syminfo_data (struct backtrace_state *state,
+		      struct elf_syminfo_data *edata)
+{
+  if (!state->threaded)
+    {
+      struct elf_syminfo_data **pp;
+
+      for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
+	   *pp != NULL;
+	   pp = &(*pp)->next)
+	;
+      *pp = edata;
+    }
+  else
+    {
+      while (1)
+	{
+	  struct elf_syminfo_data **pp;
+
+	  pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
+
+	  while (1)
+	    {
+	      struct elf_syminfo_data *p;
+
+	      p = backtrace_atomic_load_pointer (pp);
+
+	      if (p == NULL)
+		break;
+
+	      pp = &p->next;
+	    }
+
+	  if (__sync_bool_compare_and_swap (pp, NULL, edata))
+	    break;
+	}
+    }
+}
+
+/* Return the symbol name and value for an ADDR.  */
+
+static void
+elf_syminfo (struct backtrace_state *state, uintptr_t addr,
+	     backtrace_syminfo_callback callback,
+	     backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+	     void *data)
+{
+  struct elf_syminfo_data *edata;
+  struct elf_symbol *sym = NULL;
+
+  if (!state->threaded)
+    {
+      for (edata = (struct elf_syminfo_data *) state->syminfo_data;
+	   edata != NULL;
+	   edata = edata->next)
+	{
+	  sym = ((struct elf_symbol *)
+		 bsearch (&addr, edata->symbols, edata->count,
+			  sizeof (struct elf_symbol), elf_symbol_search));
+	  if (sym != NULL)
+	    break;
+	}
+    }
+  else
+    {
+      struct elf_syminfo_data **pp;
+
+      pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
+      while (1)
+	{
+	  edata = backtrace_atomic_load_pointer (pp);
+	  if (edata == NULL)
+	    break;
+
+	  sym = ((struct elf_symbol *)
+		 bsearch (&addr, edata->symbols, edata->count,
+			  sizeof (struct elf_symbol), elf_symbol_search));
+	  if (sym != NULL)
+	    break;
+
+	  pp = &edata->next;
+	}
+    }
+
+  if (sym == NULL)
+    callback (data, addr, NULL, 0, 0);
+  else
+    callback (data, addr, sym->name, sym->address, sym->size);
+}
+
+/* Add the backtrace data for one ELF file.  Returns 1 on success,
+   0 on failure (in both cases descriptor is closed) or -1 if exe
+   is non-zero and the ELF file is ET_DYN, which tells the caller that
+   elf_add will need to be called on the descriptor again after
+   base_address is determined.  */
+
+static int
+elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
+	 backtrace_error_callback error_callback, void *data,
+	 fileline *fileline_fn, int *found_sym, int *found_dwarf, int exe)
+{
+  struct backtrace_view ehdr_view;
+  b_elf_ehdr ehdr;
+  off_t shoff;
+  unsigned int shnum;
+  unsigned int shstrndx;
+  struct backtrace_view shdrs_view;
+  int shdrs_view_valid;
+  const b_elf_shdr *shdrs;
+  const b_elf_shdr *shstrhdr;
+  size_t shstr_size;
+  off_t shstr_off;
+  struct backtrace_view names_view;
+  int names_view_valid;
+  const char *names;
+  unsigned int symtab_shndx;
+  unsigned int dynsym_shndx;
+  unsigned int i;
+  struct debug_section_info sections[DEBUG_MAX];
+  struct backtrace_view symtab_view;
+  int symtab_view_valid;
+  struct backtrace_view strtab_view;
+  int strtab_view_valid;
+  off_t min_offset;
+  off_t max_offset;
+  struct backtrace_view debug_view;
+  int debug_view_valid;
+
+  *found_sym = 0;
+  *found_dwarf = 0;
+
+  shdrs_view_valid = 0;
+  names_view_valid = 0;
+  symtab_view_valid = 0;
+  strtab_view_valid = 0;
+  debug_view_valid = 0;
+
+  if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback,
+			   data, &ehdr_view))
+    goto fail;
+
+  memcpy (&ehdr, ehdr_view.data, sizeof ehdr);
+
+  backtrace_release_view (state, &ehdr_view, error_callback, data);
+
+  if (ehdr.e_ident[EI_MAG0] != ELFMAG0
+      || ehdr.e_ident[EI_MAG1] != ELFMAG1
+      || ehdr.e_ident[EI_MAG2] != ELFMAG2
+      || ehdr.e_ident[EI_MAG3] != ELFMAG3)
+    {
+      error_callback (data, "executable file is not ELF", 0);
+      goto fail;
+    }
+  if (ehdr.e_ident[EI_VERSION] != EV_CURRENT)
+    {
+      error_callback (data, "executable file is unrecognized ELF version", 0);
+      goto fail;
+    }
+
+#if BACKTRACE_ELF_SIZE == 32
+#define BACKTRACE_ELFCLASS ELFCLASS32
+#else
+#define BACKTRACE_ELFCLASS ELFCLASS64
+#endif
+
+  if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS)
+    {
+      error_callback (data, "executable file is unexpected ELF class", 0);
+      goto fail;
+    }
+
+  if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB
+      && ehdr.e_ident[EI_DATA] != ELFDATA2MSB)
+    {
+      error_callback (data, "executable file has unknown endianness", 0);
+      goto fail;
+    }
+
+  /* If the executable is ET_DYN, it is either a PIE, or we are running
+     directly a shared library with .interp.  We need to wait for
+     dl_iterate_phdr in that case to determine the actual base_address.  */
+  if (exe && ehdr.e_type == ET_DYN)
+    return -1;
+
+  shoff = ehdr.e_shoff;
+  shnum = ehdr.e_shnum;
+  shstrndx = ehdr.e_shstrndx;
+
+  if ((shnum == 0 || shstrndx == SHN_XINDEX)
+      && shoff != 0)
+    {
+      struct backtrace_view shdr_view;
+      const b_elf_shdr *shdr;
+
+      if (!backtrace_get_view (state, descriptor, shoff, sizeof shdr,
+			       error_callback, data, &shdr_view))
+	goto fail;
+
+      shdr = (const b_elf_shdr *) shdr_view.data;
+
+      if (shnum == 0)
+	shnum = shdr->sh_size;
+
+      if (shstrndx == SHN_XINDEX)
+	{
+	  shstrndx = shdr->sh_link;
+
+	  /* Versions of the GNU binutils between 2.12 and 2.18 did
+	     not handle objects with more than SHN_LORESERVE sections
+	     correctly.  All large section indexes were offset by
+	     0x100.  There is more information at
+	     http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
+	     Fortunately these object files are easy to detect, as the
+	     GNU binutils always put the section header string table
+	     near the end of the list of sections.  Thus if the
+	     section header string table index is larger than the
+	     number of sections, then we know we have to subtract
+	     0x100 to get the real section index.  */
+	  if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100)
+	    shstrndx -= 0x100;
+	}
+
+      backtrace_release_view (state, &shdr_view, error_callback, data);
+    }
+
+  /* To translate PC to file/line when using DWARF, we need to find
+     the .debug_info and .debug_line sections.  */
+
+  /* Read the section headers, skipping the first one.  */
+
+  if (!backtrace_get_view (state, descriptor, shoff + sizeof (b_elf_shdr),
+			   (shnum - 1) * sizeof (b_elf_shdr),
+			   error_callback, data, &shdrs_view))
+    goto fail;
+  shdrs_view_valid = 1;
+  shdrs = (const b_elf_shdr *) shdrs_view.data;
+
+  /* Read the section names.  */
+
+  shstrhdr = &shdrs[shstrndx - 1];
+  shstr_size = shstrhdr->sh_size;
+  shstr_off = shstrhdr->sh_offset;
+
+  if (!backtrace_get_view (state, descriptor, shstr_off, shstr_size,
+			   error_callback, data, &names_view))
+    goto fail;
+  names_view_valid = 1;
+  names = (const char *) names_view.data;
+
+  symtab_shndx = 0;
+  dynsym_shndx = 0;
+
+  memset (sections, 0, sizeof sections);
+
+  /* Look for the symbol table.  */
+  for (i = 1; i < shnum; ++i)
+    {
+      const b_elf_shdr *shdr;
+      unsigned int sh_name;
+      const char *name;
+      int j;
+
+      shdr = &shdrs[i - 1];
+
+      if (shdr->sh_type == SHT_SYMTAB)
+	symtab_shndx = i;
+      else if (shdr->sh_type == SHT_DYNSYM)
+	dynsym_shndx = i;
+
+      sh_name = shdr->sh_name;
+      if (sh_name >= shstr_size)
+	{
+	  error_callback (data, "ELF section name out of range", 0);
+	  goto fail;
+	}
+
+      name = names + sh_name;
+
+      for (j = 0; j < (int) DEBUG_MAX; ++j)
+	{
+	  if (strcmp (name, debug_section_names[j]) == 0)
+	    {
+	      sections[j].offset = shdr->sh_offset;
+	      sections[j].size = shdr->sh_size;
+	      break;
+	    }
+	}
+    }
+
+  if (symtab_shndx == 0)
+    symtab_shndx = dynsym_shndx;
+  if (symtab_shndx != 0)
+    {
+      const b_elf_shdr *symtab_shdr;
+      unsigned int strtab_shndx;
+      const b_elf_shdr *strtab_shdr;
+      struct elf_syminfo_data *sdata;
+
+      symtab_shdr = &shdrs[symtab_shndx - 1];
+      strtab_shndx = symtab_shdr->sh_link;
+      if (strtab_shndx >= shnum)
+	{
+	  error_callback (data,
+			  "ELF symbol table strtab link out of range", 0);
+	  goto fail;
+	}
+      strtab_shdr = &shdrs[strtab_shndx - 1];
+
+      if (!backtrace_get_view (state, descriptor, symtab_shdr->sh_offset,
+			       symtab_shdr->sh_size, error_callback, data,
+			       &symtab_view))
+	goto fail;
+      symtab_view_valid = 1;
+
+      if (!backtrace_get_view (state, descriptor, strtab_shdr->sh_offset,
+			       strtab_shdr->sh_size, error_callback, data,
+			       &strtab_view))
+	goto fail;
+      strtab_view_valid = 1;
+
+      sdata = ((struct elf_syminfo_data *)
+	       backtrace_alloc (state, sizeof *sdata, error_callback, data));
+      if (sdata == NULL)
+	goto fail;
+
+      if (!elf_initialize_syminfo (state, base_address,
+				   symtab_view.data, symtab_shdr->sh_size,
+				   strtab_view.data, strtab_shdr->sh_size,
+				   error_callback, data, sdata))
+	{
+	  backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
+	  goto fail;
+	}
+
+      /* We no longer need the symbol table, but we hold on to the
+	 string table permanently.  */
+      backtrace_release_view (state, &symtab_view, error_callback, data);
+
+      *found_sym = 1;
+
+      elf_add_syminfo_data (state, sdata);
+    }
+
+  /* FIXME: Need to handle compressed debug sections.  */
+
+  backtrace_release_view (state, &shdrs_view, error_callback, data);
+  shdrs_view_valid = 0;
+  backtrace_release_view (state, &names_view, error_callback, data);
+  names_view_valid = 0;
+
+  /* Read all the debug sections in a single view, since they are
+     probably adjacent in the file.  We never release this view.  */
+
+  min_offset = 0;
+  max_offset = 0;
+  for (i = 0; i < (int) DEBUG_MAX; ++i)
+    {
+      off_t end;
+
+      if (sections[i].size == 0)
+	continue;
+      if (min_offset == 0 || sections[i].offset < min_offset)
+	min_offset = sections[i].offset;
+      end = sections[i].offset + sections[i].size;
+      if (end > max_offset)
+	max_offset = end;
+    }
+  if (min_offset == 0 || max_offset == 0)
+    {
+      if (!backtrace_close (descriptor, error_callback, data))
+	goto fail;
+      *fileline_fn = elf_nodebug;
+      return 1;
+    }
+
+  if (!backtrace_get_view (state, descriptor, min_offset,
+			   max_offset - min_offset,
+			   error_callback, data, &debug_view))
+    goto fail;
+  debug_view_valid = 1;
+
+  /* We've read all we need from the executable.  */
+  if (!backtrace_close (descriptor, error_callback, data))
+    goto fail;
+  descriptor = -1;
+
+  for (i = 0; i < (int) DEBUG_MAX; ++i)
+    {
+      if (sections[i].size == 0)
+	sections[i].data = NULL;
+      else
+	sections[i].data = ((const unsigned char *) debug_view.data
+			    + (sections[i].offset - min_offset));
+    }
+
+  if (!backtrace_dwarf_add (state, base_address,
+			    sections[DEBUG_INFO].data,
+			    sections[DEBUG_INFO].size,
+			    sections[DEBUG_LINE].data,
+			    sections[DEBUG_LINE].size,
+			    sections[DEBUG_ABBREV].data,
+			    sections[DEBUG_ABBREV].size,
+			    sections[DEBUG_RANGES].data,
+			    sections[DEBUG_RANGES].size,
+			    sections[DEBUG_STR].data,
+			    sections[DEBUG_STR].size,
+			    ehdr.e_ident[EI_DATA] == ELFDATA2MSB,
+			    error_callback, data, fileline_fn))
+    goto fail;
+
+  *found_dwarf = 1;
+
+  return 1;
+
+ fail:
+  if (shdrs_view_valid)
+    backtrace_release_view (state, &shdrs_view, error_callback, data);
+  if (names_view_valid)
+    backtrace_release_view (state, &names_view, error_callback, data);
+  if (symtab_view_valid)
+    backtrace_release_view (state, &symtab_view, error_callback, data);
+  if (strtab_view_valid)
+    backtrace_release_view (state, &strtab_view, error_callback, data);
+  if (debug_view_valid)
+    backtrace_release_view (state, &debug_view, error_callback, data);
+  if (descriptor != -1)
+    backtrace_close (descriptor, error_callback, data);
+  return 0;
+}
+
+/* Data passed to phdr_callback.  */
+
+struct phdr_data
+{
+  struct backtrace_state *state;
+  backtrace_error_callback error_callback;
+  void *data;
+  fileline *fileline_fn;
+  int *found_sym;
+  int *found_dwarf;
+  int exe_descriptor;
+};
+
+/* Callback passed to dl_iterate_phdr.  Load debug info from shared
+   libraries.  */
+
+static int
+phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
+	       void *pdata)
+{
+  struct phdr_data *pd = (struct phdr_data *) pdata;
+  int descriptor;
+  int does_not_exist;
+  fileline elf_fileline_fn;
+  int found_dwarf;
+
+  /* There is not much we can do if we don't have the module name,
+     unless executable is ET_DYN, where we expect the very first
+     phdr_callback to be for the PIE.  */
+  if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0')
+    {
+      if (pd->exe_descriptor == -1)
+	return 0;
+      descriptor = pd->exe_descriptor;
+      pd->exe_descriptor = -1;
+    }
+  else
+    {
+      if (pd->exe_descriptor != -1)
+	{
+	  backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data);
+	  pd->exe_descriptor = -1;
+	}
+
+      descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
+				   pd->data, &does_not_exist);
+      if (descriptor < 0)
+	return 0;
+    }
+
+  if (elf_add (pd->state, descriptor, info->dlpi_addr, pd->error_callback,
+	       pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf, 0))
+    {
+      if (found_dwarf)
+	{
+	  *pd->found_dwarf = 1;
+	  *pd->fileline_fn = elf_fileline_fn;
+	}
+    }
+
+  return 0;
+}
+
+/* Initialize the backtrace data we need from an ELF executable.  At
+   the ELF level, all we need to do is find the debug info
+   sections.  */
+
+int
+backtrace_initialize (struct backtrace_state *state, int descriptor,
+		      backtrace_error_callback error_callback,
+		      void *data, fileline *fileline_fn)
+{
+  int ret;
+  int found_sym;
+  int found_dwarf;
+  fileline elf_fileline_fn;
+  struct phdr_data pd;
+
+  ret = elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn,
+		 &found_sym, &found_dwarf, 1);
+  if (!ret)
+    return 0;
+
+  pd.state = state;
+  pd.error_callback = error_callback;
+  pd.data = data;
+  pd.fileline_fn = &elf_fileline_fn;
+  pd.found_sym = &found_sym;
+  pd.found_dwarf = &found_dwarf;
+  pd.exe_descriptor = ret < 0 ? descriptor : -1;
+
+  dl_iterate_phdr (phdr_callback, (void *) &pd);
+
+  if (!state->threaded)
+    {
+      if (found_sym)
+	state->syminfo_fn = elf_syminfo;
+      else if (state->syminfo_fn == NULL)
+	state->syminfo_fn = elf_nosyms;
+    }
+  else
+    {
+      if (found_sym)
+	backtrace_atomic_store_pointer (&state->syminfo_fn, elf_syminfo);
+      else
+	__sync_bool_compare_and_swap (&state->syminfo_fn, NULL, elf_nosyms);
+    }
+
+  if (!state->threaded)
+    {
+      if (state->fileline_fn == NULL || state->fileline_fn == elf_nodebug)
+	*fileline_fn = elf_fileline_fn;
+    }
+  else
+    {
+      fileline current_fn;
+
+      current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
+      if (current_fn == NULL || current_fn == elf_nodebug)
+	*fileline_fn = elf_fileline_fn;
+    }
+
+  return 1;
+}
diff --git a/third_party/gofrontend/libbacktrace/fileline.c b/third_party/gofrontend/libbacktrace/fileline.c
new file mode 100644
index 0000000..bab5351
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/fileline.c
@@ -0,0 +1,194 @@
+/* fileline.c -- Get file and line number information in a backtrace.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+#ifndef HAVE_GETEXECNAME
+#define getexecname() NULL
+#endif
+
+/* Initialize the fileline information from the executable.  Returns 1
+   on success, 0 on failure.  */
+
+static int
+fileline_initialize (struct backtrace_state *state,
+		     backtrace_error_callback error_callback, void *data)
+{
+  int failed;
+  fileline fileline_fn;
+  int pass;
+  int called_error_callback;
+  int descriptor;
+
+  if (!state->threaded)
+    failed = state->fileline_initialization_failed;
+  else
+    failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
+
+  if (failed)
+    {
+      error_callback (data, "failed to read executable information", -1);
+      return 0;
+    }
+
+  if (!state->threaded)
+    fileline_fn = state->fileline_fn;
+  else
+    fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
+  if (fileline_fn != NULL)
+    return 1;
+
+  /* We have not initialized the information.  Do it now.  */
+
+  descriptor = -1;
+  called_error_callback = 0;
+  for (pass = 0; pass < 4; ++pass)
+    {
+      const char *filename;
+      int does_not_exist;
+
+      switch (pass)
+	{
+	case 0:
+	  filename = state->filename;
+	  break;
+	case 1:
+	  filename = getexecname ();
+	  break;
+	case 2:
+	  filename = "/proc/self/exe";
+	  break;
+	case 3:
+	  filename = "/proc/curproc/file";
+	  break;
+	default:
+	  abort ();
+	}
+
+      if (filename == NULL)
+	continue;
+
+      descriptor = backtrace_open (filename, error_callback, data,
+				   &does_not_exist);
+      if (descriptor < 0 && !does_not_exist)
+	{
+	  called_error_callback = 1;
+	  break;
+	}
+      if (descriptor >= 0)
+	break;
+    }
+
+  if (descriptor < 0)
+    {
+      if (!called_error_callback)
+	{
+	  if (state->filename != NULL)
+	    error_callback (data, state->filename, ENOENT);
+	  else
+	    error_callback (data,
+			    "libbacktrace could not find executable to open",
+			    0);
+	}
+      failed = 1;
+    }
+
+  if (!failed)
+    {
+      if (!backtrace_initialize (state, descriptor, error_callback, data,
+				 &fileline_fn))
+	failed = 1;
+    }
+
+  if (failed)
+    {
+      if (!state->threaded)
+	state->fileline_initialization_failed = 1;
+      else
+	backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
+      return 0;
+    }
+
+  if (!state->threaded)
+    state->fileline_fn = fileline_fn;
+  else
+    {
+      backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
+
+      /* Note that if two threads initialize at once, one of the data
+	 sets may be leaked.  */
+    }
+
+  return 1;
+}
+
+/* Given a PC, find the file name, line number, and function name.  */
+
+int
+backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
+		  backtrace_full_callback callback,
+		  backtrace_error_callback error_callback, void *data)
+{
+  if (!fileline_initialize (state, error_callback, data))
+    return 0;
+
+  if (state->fileline_initialization_failed)
+    return 0;
+
+  return state->fileline_fn (state, pc, callback, error_callback, data);
+}
+
+/* Given a PC, find the symbol for it, and its value.  */
+
+int
+backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
+		   backtrace_syminfo_callback callback,
+		   backtrace_error_callback error_callback, void *data)
+{
+  if (!fileline_initialize (state, error_callback, data))
+    return 0;
+
+  if (state->fileline_initialization_failed)
+    return 0;
+
+  state->syminfo_fn (state, pc, callback, error_callback, data);
+  return 1;
+}
diff --git a/third_party/gofrontend/libbacktrace/filetype.awk b/third_party/gofrontend/libbacktrace/filetype.awk
new file mode 100644
index 0000000..0a656f7
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/filetype.awk
@@ -0,0 +1,3 @@
+# An awk script to determine the type of a file.
+/\177ELF\001/ { if (NR == 1) { print "elf32"; exit } }
+/\177ELF\002/ { if (NR == 1) { print "elf64"; exit } }
diff --git a/third_party/gofrontend/libbacktrace/internal.h b/third_party/gofrontend/libbacktrace/internal.h
new file mode 100644
index 0000000..1ae4317
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/internal.h
@@ -0,0 +1,292 @@
+/* internal.h -- Internal header file for stack backtrace library.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#ifndef BACKTRACE_INTERNAL_H
+#define BACKTRACE_INTERNAL_H
+
+/* We assume that <sys/types.h> and "backtrace.h" have already been
+   included.  */
+
+#ifndef GCC_VERSION
+# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif
+
+#if (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+#ifndef ATTRIBUTE_MALLOC
+# if (GCC_VERSION >= 2096)
+#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+#  define ATTRIBUTE_MALLOC
+# endif
+#endif
+
+#ifndef HAVE_SYNC_FUNCTIONS
+
+/* Define out the sync functions.  These should never be called if
+   they are not available.  */
+
+#define __sync_bool_compare_and_swap(A, B, C) (abort(), 1)
+#define __sync_lock_test_and_set(A, B) (abort(), 0)
+#define __sync_lock_release(A) abort()
+
+#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
+
+#ifdef HAVE_ATOMIC_FUNCTIONS
+
+/* We have the atomic builtin functions.  */
+
+#define backtrace_atomic_load_pointer(p) \
+    __atomic_load_n ((p), __ATOMIC_ACQUIRE)
+#define backtrace_atomic_load_int(p) \
+    __atomic_load_n ((p), __ATOMIC_ACQUIRE)
+#define backtrace_atomic_store_pointer(p, v) \
+    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+#define backtrace_atomic_store_size_t(p, v) \
+    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+#define backtrace_atomic_store_int(p, v) \
+    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+
+#else /* !defined (HAVE_ATOMIC_FUNCTIONS) */
+#ifdef HAVE_SYNC_FUNCTIONS
+
+/* We have the sync functions but not the atomic functions.  Define
+   the atomic ones in terms of the sync ones.  */
+
+extern void *backtrace_atomic_load_pointer (void *);
+extern int backtrace_atomic_load_int (int *);
+extern void backtrace_atomic_store_pointer (void *, void *);
+extern void backtrace_atomic_store_size_t (size_t *, size_t);
+extern void backtrace_atomic_store_int (int *, int);
+
+#else /* !defined (HAVE_SYNC_FUNCTIONS) */
+
+/* We have neither the sync nor the atomic functions.  These will
+   never be called.  */
+
+#define backtrace_atomic_load_pointer(p) (abort(), 0)
+#define backtrace_atomic_load_int(p) (abort(), 0)
+#define backtrace_atomic_store_pointer(p, v) abort()
+#define backtrace_atomic_store_size_t(p, v) abort()
+#define backtrace_atomic_store_int(p, v) abort()
+
+#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
+#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */
+
+/* The type of the function that collects file/line information.  This
+   is like backtrace_pcinfo.  */
+
+typedef int (*fileline) (struct backtrace_state *state, uintptr_t pc,
+			 backtrace_full_callback callback,
+			 backtrace_error_callback error_callback, void *data);
+
+/* The type of the function that collects symbol information.  This is
+   like backtrace_syminfo.  */
+
+typedef void (*syminfo) (struct backtrace_state *state, uintptr_t pc,
+			 backtrace_syminfo_callback callback,
+			 backtrace_error_callback error_callback, void *data);
+
+/* What the backtrace state pointer points to.  */
+
+struct backtrace_state
+{
+  /* The name of the executable.  */
+  const char *filename;
+  /* Non-zero if threaded.  */
+  int threaded;
+  /* The master lock for fileline_fn, fileline_data, syminfo_fn,
+     syminfo_data, fileline_initialization_failed and everything the
+     data pointers point to.  */
+  void *lock;
+  /* The function that returns file/line information.  */
+  fileline fileline_fn;
+  /* The data to pass to FILELINE_FN.  */
+  void *fileline_data;
+  /* The function that returns symbol information.  */
+  syminfo syminfo_fn;
+  /* The data to pass to SYMINFO_FN.  */
+  void *syminfo_data;
+  /* Whether initializing the file/line information failed.  */
+  int fileline_initialization_failed;
+  /* The lock for the freelist.  */
+  int lock_alloc;
+  /* The freelist when using mmap.  */
+  struct backtrace_freelist_struct *freelist;
+};
+
+/* Open a file for reading.  Returns -1 on error.  If DOES_NOT_EXIST
+   is not NULL, *DOES_NOT_EXIST will be set to 0 normally and set to 1
+   if the file does not exist.  If the file does not exist and
+   DOES_NOT_EXIST is not NULL, the function will return -1 and will
+   not call ERROR_CALLBACK.  On other errors, or if DOES_NOT_EXIST is
+   NULL, the function will call ERROR_CALLBACK before returning.  */
+extern int backtrace_open (const char *filename,
+			   backtrace_error_callback error_callback,
+			   void *data,
+			   int *does_not_exist);
+
+/* A view of the contents of a file.  This supports mmap when
+   available.  A view will remain in memory even after backtrace_close
+   is called on the file descriptor from which the view was
+   obtained.  */
+
+struct backtrace_view
+{
+  /* The data that the caller requested.  */
+  const void *data;
+  /* The base of the view.  */
+  void *base;
+  /* The total length of the view.  */
+  size_t len;
+};
+
+/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET.  Store the
+   result in *VIEW.  Returns 1 on success, 0 on error.  */
+extern int backtrace_get_view (struct backtrace_state *state, int descriptor,
+			       off_t offset, size_t size,
+			       backtrace_error_callback error_callback,
+			       void *data, struct backtrace_view *view);
+
+/* Release a view created by backtrace_get_view.  */
+extern void backtrace_release_view (struct backtrace_state *state,
+				    struct backtrace_view *view,
+				    backtrace_error_callback error_callback,
+				    void *data);
+
+/* Close a file opened by backtrace_open.  Returns 1 on success, 0 on
+   error.  */
+
+extern int backtrace_close (int descriptor,
+			    backtrace_error_callback error_callback,
+			    void *data);
+
+/* Sort without using memory.  */
+
+extern void backtrace_qsort (void *base, size_t count, size_t size,
+			     int (*compar) (const void *, const void *));
+
+/* Allocate memory.  This is like malloc.  */
+
+extern void *backtrace_alloc (struct backtrace_state *state, size_t size,
+			      backtrace_error_callback error_callback,
+			      void *data) ATTRIBUTE_MALLOC;
+
+/* Free memory allocated by backtrace_alloc.  */
+
+extern void backtrace_free (struct backtrace_state *state, void *mem,
+			    size_t size,
+			    backtrace_error_callback error_callback,
+			    void *data);
+
+/* A growable vector of some struct.  This is used for more efficient
+   allocation when we don't know the final size of some group of data
+   that we want to represent as an array.  */
+
+struct backtrace_vector
+{
+  /* The base of the vector.  */
+  void *base;
+  /* The number of bytes in the vector.  */
+  size_t size;
+  /* The number of bytes available at the current allocation.  */
+  size_t alc;
+};
+
+/* Grow VEC by SIZE bytes.  Return a pointer to the newly allocated
+   bytes.  Note that this may move the entire vector to a new memory
+   location.  Returns NULL on failure.  */
+
+extern void *backtrace_vector_grow (struct backtrace_state *state, size_t size,
+				    backtrace_error_callback error_callback,
+				    void *data,
+				    struct backtrace_vector *vec);
+
+/* Finish the current allocation on VEC.  Prepare to start a new
+   allocation.  The finished allocation will never be freed.  Returns
+   a pointer to the base of the finished entries, or NULL on
+   failure.  */
+
+extern void* backtrace_vector_finish (struct backtrace_state *state,
+				      struct backtrace_vector *vec,
+				      backtrace_error_callback error_callback,
+				      void *data);
+
+/* Release any extra space allocated for VEC.  This may change
+   VEC->base.  Returns 1 on success, 0 on failure.  */
+
+extern int backtrace_vector_release (struct backtrace_state *state,
+				     struct backtrace_vector *vec,
+				     backtrace_error_callback error_callback,
+				     void *data);
+
+/* Read initial debug data from a descriptor, and set the
+   fileline_data, syminfo_fn, and syminfo_data fields of STATE.
+   Return the fileln_fn field in *FILELN_FN--this is done this way so
+   that the synchronization code is only implemented once.  This is
+   called after the descriptor has first been opened.  It will close
+   the descriptor if it is no longer needed.  Returns 1 on success, 0
+   on error.  There will be multiple implementations of this function,
+   for different file formats.  Each system will compile the
+   appropriate one.  */
+
+extern int backtrace_initialize (struct backtrace_state *state,
+				 int descriptor,
+				 backtrace_error_callback error_callback,
+				 void *data,
+				 fileline *fileline_fn);
+
+/* Add file/line information for a DWARF module.  */
+
+extern int backtrace_dwarf_add (struct backtrace_state *state,
+				uintptr_t base_address,
+				const unsigned char* dwarf_info,
+				size_t dwarf_info_size,
+				const unsigned char *dwarf_line,
+				size_t dwarf_line_size,
+				const unsigned char *dwarf_abbrev,
+				size_t dwarf_abbrev_size,
+				const unsigned char *dwarf_ranges,
+				size_t dwarf_range_size,
+				const unsigned char *dwarf_str,
+				size_t dwarf_str_size,
+				int is_bigendian,
+				backtrace_error_callback error_callback,
+				void *data, fileline *fileline_fn);
+
+#endif
diff --git a/third_party/gofrontend/libbacktrace/mmap.c b/third_party/gofrontend/libbacktrace/mmap.c
new file mode 100644
index 0000000..5a9f629
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/mmap.c
@@ -0,0 +1,295 @@
+/* mmap.c -- Memory allocation with mmap.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Memory allocation on systems that provide anonymous mmap.  This
+   permits the backtrace functions to be invoked from a signal
+   handler, assuming that mmap is async-signal safe.  */
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+/* A list of free memory blocks.  */
+
+struct backtrace_freelist_struct
+{
+  /* Next on list.  */
+  struct backtrace_freelist_struct *next;
+  /* Size of this block, including this structure.  */
+  size_t size;
+};
+
+/* Free memory allocated by backtrace_alloc.  */
+
+static void
+backtrace_free_locked (struct backtrace_state *state, void *addr, size_t size)
+{
+  /* Just leak small blocks.  We don't have to be perfect.  */
+  if (size >= sizeof (struct backtrace_freelist_struct))
+    {
+      struct backtrace_freelist_struct *p;
+
+      p = (struct backtrace_freelist_struct *) addr;
+      p->next = state->freelist;
+      p->size = size;
+      state->freelist = p;
+    }
+}
+
+/* Allocate memory like malloc.  */
+
+void *
+backtrace_alloc (struct backtrace_state *state,
+		 size_t size, backtrace_error_callback error_callback,
+		 void *data)
+{
+  void *ret;
+  int locked;
+  struct backtrace_freelist_struct **pp;
+  size_t pagesize;
+  size_t asksize;
+  void *page;
+
+  ret = NULL;
+
+  /* If we can acquire the lock, then see if there is space on the
+     free list.  If we can't acquire the lock, drop straight into
+     using mmap.  __sync_lock_test_and_set returns the old state of
+     the lock, so we have acquired it if it returns 0.  */
+
+  if (!state->threaded)
+    locked = 1;
+  else
+    locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0;
+
+  if (locked)
+    {
+      for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next)
+	{
+	  if ((*pp)->size >= size)
+	    {
+	      struct backtrace_freelist_struct *p;
+
+	      p = *pp;
+	      *pp = p->next;
+
+	      /* Round for alignment; we assume that no type we care about
+		 is more than 8 bytes.  */
+	      size = (size + 7) & ~ (size_t) 7;
+	      if (size < p->size)
+		backtrace_free_locked (state, (char *) p + size,
+				       p->size - size);
+
+	      ret = (void *) p;
+
+	      break;
+	    }
+	}
+
+      if (state->threaded)
+	__sync_lock_release (&state->lock_alloc);
+    }
+
+  if (ret == NULL)
+    {
+      /* Allocate a new page.  */
+
+      pagesize = getpagesize ();
+      asksize = (size + pagesize - 1) & ~ (pagesize - 1);
+      page = mmap (NULL, asksize, PROT_READ | PROT_WRITE,
+		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      if (page == NULL)
+	error_callback (data, "mmap", errno);
+      else
+	{
+	  size = (size + 7) & ~ (size_t) 7;
+	  if (size < asksize)
+	    backtrace_free (state, (char *) page + size, asksize - size,
+			    error_callback, data);
+
+	  ret = page;
+	}
+    }
+
+  return ret;
+}
+
+/* Free memory allocated by backtrace_alloc.  */
+
+void
+backtrace_free (struct backtrace_state *state, void *addr, size_t size,
+		backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+		void *data ATTRIBUTE_UNUSED)
+{
+  int locked;
+
+  /* If we are freeing a large aligned block, just release it back to
+     the system.  This case arises when growing a vector for a large
+     binary with lots of debug info.  Calling munmap here may cause us
+     to call mmap again if there is also a large shared library; we
+     just live with that.  */
+  if (size >= 16 * 4096)
+    {
+      size_t pagesize;
+
+      pagesize = getpagesize ();
+      if (((uintptr_t) addr & (pagesize - 1)) == 0
+	  && (size & (pagesize - 1)) == 0)
+	{
+	  /* If munmap fails for some reason, just add the block to
+	     the freelist.  */
+	  if (munmap (addr, size) == 0)
+	    return;
+	}
+    }
+
+  /* If we can acquire the lock, add the new space to the free list.
+     If we can't acquire the lock, just leak the memory.
+     __sync_lock_test_and_set returns the old state of the lock, so we
+     have acquired it if it returns 0.  */
+
+  if (!state->threaded)
+    locked = 1;
+  else
+    locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0;
+
+  if (locked)
+    {
+      backtrace_free_locked (state, addr, size);
+
+      if (state->threaded)
+	__sync_lock_release (&state->lock_alloc);
+    }
+}
+
+/* Grow VEC by SIZE bytes.  */
+
+void *
+backtrace_vector_grow (struct backtrace_state *state,size_t size,
+		       backtrace_error_callback error_callback,
+		       void *data, struct backtrace_vector *vec)
+{
+  void *ret;
+
+  if (size > vec->alc)
+    {
+      size_t pagesize;
+      size_t alc;
+      void *base;
+
+      pagesize = getpagesize ();
+      alc = vec->size + size;
+      if (vec->size == 0)
+	alc = 16 * size;
+      else if (alc < pagesize)
+	{
+	  alc *= 2;
+	  if (alc > pagesize)
+	    alc = pagesize;
+	}
+      else
+	{
+	  alc *= 2;
+	  alc = (alc + pagesize - 1) & ~ (pagesize - 1);
+	}
+      base = backtrace_alloc (state, alc, error_callback, data);
+      if (base == NULL)
+	return NULL;
+      if (vec->base != NULL)
+	{
+	  memcpy (base, vec->base, vec->size);
+	  backtrace_free (state, vec->base, vec->size + vec->alc,
+			  error_callback, data);
+	}
+      vec->base = base;
+      vec->alc = alc - vec->size;
+    }
+
+  ret = (char *) vec->base + vec->size;
+  vec->size += size;
+  vec->alc -= size;
+  return ret;
+}
+
+/* Finish the current allocation on VEC.  */
+
+void *
+backtrace_vector_finish (
+  struct backtrace_state *state ATTRIBUTE_UNUSED,
+  struct backtrace_vector *vec,
+  backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+  void *data ATTRIBUTE_UNUSED)
+{
+  void *ret;
+
+  ret = vec->base;
+  vec->base = (char *) vec->base + vec->size;
+  vec->size = 0;
+  return ret;
+}
+
+/* Release any extra space allocated for VEC.  */
+
+int
+backtrace_vector_release (struct backtrace_state *state,
+			  struct backtrace_vector *vec,
+			  backtrace_error_callback error_callback,
+			  void *data)
+{
+  size_t size;
+  size_t alc;
+  size_t aligned;
+
+  /* Make sure that the block that we free is aligned on an 8-byte
+     boundary.  */
+  size = vec->size;
+  alc = vec->alc;
+  aligned = (size + 7) & ~ (size_t) 7;
+  alc -= aligned - size;
+
+  backtrace_free (state, (char *) vec->base + aligned, alc,
+		  error_callback, data);
+  vec->alc = 0;
+  return 1;
+}
diff --git a/third_party/gofrontend/libbacktrace/mmapio.c b/third_party/gofrontend/libbacktrace/mmapio.c
new file mode 100644
index 0000000..72940b4
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/mmapio.c
@@ -0,0 +1,100 @@
+/* mmapio.c -- File views using mmap.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+/* This file implements file views and memory allocation when mmap is
+   available.  */
+
+/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET.  */
+
+int
+backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		    int descriptor, off_t offset, size_t size,
+		    backtrace_error_callback error_callback,
+		    void *data, struct backtrace_view *view)
+{
+  size_t pagesize;
+  unsigned int inpage;
+  off_t pageoff;
+  void *map;
+
+  pagesize = getpagesize ();
+  inpage = offset % pagesize;
+  pageoff = offset - inpage;
+
+  size += inpage;
+  size = (size + (pagesize - 1)) & ~ (pagesize - 1);
+
+  map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);
+  if (map == MAP_FAILED)
+    {
+      error_callback (data, "mmap", errno);
+      return 0;
+    }
+
+  view->data = (char *) map + inpage;
+  view->base = map;
+  view->len = size;
+
+  return 1;
+}
+
+/* Release a view read by backtrace_get_view.  */
+
+void
+backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
+			struct backtrace_view *view,
+			backtrace_error_callback error_callback,
+			void *data)
+{
+  union {
+    const void *cv;
+    void *v;
+  } const_cast;
+
+  const_cast.cv = view->base;
+  if (munmap (const_cast.v, view->len) < 0)
+    error_callback (data, "munmap", errno);
+}
diff --git a/third_party/gofrontend/libbacktrace/nounwind.c b/third_party/gofrontend/libbacktrace/nounwind.c
new file mode 100644
index 0000000..0097966
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/nounwind.c
@@ -0,0 +1,66 @@
+/* backtrace.c -- Entry point for stack backtrace library.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include "backtrace.h"
+
+#include "internal.h"
+
+/* This source file is compiled if the unwind library is not
+   available.  */
+
+int
+backtrace_full (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		int skip ATTRIBUTE_UNUSED,
+		backtrace_full_callback callback ATTRIBUTE_UNUSED,
+		backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data,
+		  "no stack trace because unwind library not available",
+		  0);
+  return 0;
+}
+
+int
+backtrace_simple (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		  int skip ATTRIBUTE_UNUSED,
+		  backtrace_simple_callback callback ATTRIBUTE_UNUSED,
+		  backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data,
+		  "no stack trace because unwind library not available",
+		  0);
+  return 0;
+}
diff --git a/third_party/gofrontend/libbacktrace/posix.c b/third_party/gofrontend/libbacktrace/posix.c
new file mode 100644
index 0000000..dba9e52
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/posix.c
@@ -0,0 +1,100 @@
+/* posix.c -- POSIX file I/O routines for the backtrace library.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+
+/* Open a file for reading.  */
+
+int
+backtrace_open (const char *filename, backtrace_error_callback error_callback,
+		void *data, int *does_not_exist)
+{
+  int descriptor;
+
+  if (does_not_exist != NULL)
+    *does_not_exist = 0;
+
+  descriptor = open (filename, O_RDONLY | O_BINARY | O_CLOEXEC);
+  if (descriptor < 0)
+    {
+      if (does_not_exist != NULL && errno == ENOENT)
+	*does_not_exist = 1;
+      else
+	error_callback (data, filename, errno);
+      return -1;
+    }
+
+#ifdef HAVE_FCNTL
+  /* Set FD_CLOEXEC just in case the kernel does not support
+     O_CLOEXEC. It doesn't matter if this fails for some reason.
+     FIXME: At some point it should be safe to only do this if
+     O_CLOEXEC == 0.  */
+  fcntl (descriptor, F_SETFD, FD_CLOEXEC);
+#endif
+
+  return descriptor;
+}
+
+/* Close DESCRIPTOR.  */
+
+int
+backtrace_close (int descriptor, backtrace_error_callback error_callback,
+		 void *data)
+{
+  if (close (descriptor) < 0)
+    {
+      error_callback (data, "close", errno);
+      return 0;
+    }
+  return 1;
+}
diff --git a/third_party/gofrontend/libbacktrace/print.c b/third_party/gofrontend/libbacktrace/print.c
new file mode 100644
index 0000000..bd224e6
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/print.c
@@ -0,0 +1,92 @@
+/* print.c -- Print the current backtrace.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Passed to callbacks.  */
+
+struct print_data
+{
+  struct backtrace_state *state;
+  FILE *f;
+};
+
+/* Print one level of a backtrace.  */
+
+static int
+print_callback (void *data, uintptr_t pc, const char *filename, int lineno,
+		const char *function)
+{
+  struct print_data *pdata = (struct print_data *) data;
+
+  fprintf (pdata->f, "0x%lx %s\n\t%s:%d\n",
+	   (unsigned long) pc,
+	   function == NULL ? "???" : function,
+	   filename == NULL ? "???" : filename,
+	   lineno);
+  return 0;
+}
+
+/* Print errors to stderr.  */
+
+static void
+error_callback (void *data, const char *msg, int errnum)
+{
+  struct print_data *pdata = (struct print_data *) data;
+
+  if (pdata->state->filename != NULL)
+    fprintf (stderr, "%s: ", pdata->state->filename);
+  fprintf (stderr, "libbacktrace: %s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fputc ('\n', stderr);
+}
+
+/* Print a backtrace.  */
+
+void
+backtrace_print (struct backtrace_state *state, int skip, FILE *f)
+{
+  struct print_data data;
+
+  data.state = state;
+  data.f = f;
+  backtrace_full (state, skip + 1, print_callback, error_callback,
+		  (void *) &data);
+}
diff --git a/third_party/gofrontend/libbacktrace/read.c b/third_party/gofrontend/libbacktrace/read.c
new file mode 100644
index 0000000..c618a50
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/read.c
@@ -0,0 +1,96 @@
+/* read.c -- File views without mmap.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* This file implements file views when mmap is not available.  */
+
+/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET.  */
+
+int
+backtrace_get_view (struct backtrace_state *state, int descriptor,
+		    off_t offset, size_t size,
+		    backtrace_error_callback error_callback,
+		    void *data, struct backtrace_view *view)
+{
+  ssize_t got;
+
+  if (lseek (descriptor, offset, SEEK_SET) < 0)
+    {
+      error_callback (data, "lseek", errno);
+      return 0;
+    }
+
+  view->base = backtrace_alloc (state, size, error_callback, data);
+  if (view->base == NULL)
+    return 0;
+  view->data = view->base;
+  view->len = size;
+
+  got = read (descriptor, view->base, size);
+  if (got < 0)
+    {
+      error_callback (data, "read", errno);
+      free (view->base);
+      return 0;
+    }
+
+  if ((size_t) got < size)
+    {
+      error_callback (data, "file too short", 0);
+      free (view->base);
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Release a view read by backtrace_get_view.  */
+
+void
+backtrace_release_view (struct backtrace_state *state,
+			struct backtrace_view *view,
+			backtrace_error_callback error_callback,
+			void *data)
+{
+  backtrace_free (state, view->base, view->len, error_callback, data);
+  view->data = NULL;
+  view->base = NULL;
+}
diff --git a/third_party/gofrontend/libbacktrace/simple.c b/third_party/gofrontend/libbacktrace/simple.c
new file mode 100644
index 0000000..efa8b6f
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/simple.c
@@ -0,0 +1,108 @@
+/* simple.c -- The backtrace_simple function.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include "unwind.h"
+#include "backtrace.h"
+
+/* The simple_backtrace routine.  */
+
+/* Data passed through _Unwind_Backtrace.  */
+
+struct backtrace_simple_data
+{
+  /* Number of frames to skip.  */
+  int skip;
+  /* Library state.  */
+  struct backtrace_state *state;
+  /* Callback routine.  */
+  backtrace_simple_callback callback;
+  /* Error callback routine.  */
+  backtrace_error_callback error_callback;
+  /* Data to pass to callback routine.  */
+  void *data;
+  /* Value to return from backtrace.  */
+  int ret;
+};
+
+/* Unwind library callback routine.  This is passd to
+   _Unwind_Backtrace.  */
+
+static _Unwind_Reason_Code
+simple_unwind (struct _Unwind_Context *context, void *vdata)
+{
+  struct backtrace_simple_data *bdata = (struct backtrace_simple_data *) vdata;
+  uintptr_t pc;
+  int ip_before_insn = 0;
+
+#ifdef HAVE_GETIPINFO
+  pc = _Unwind_GetIPInfo (context, &ip_before_insn);
+#else
+  pc = _Unwind_GetIP (context);
+#endif
+
+  if (bdata->skip > 0)
+    {
+      --bdata->skip;
+      return _URC_NO_REASON;
+    }
+
+  if (!ip_before_insn)
+    --pc;
+
+  bdata->ret = bdata->callback (bdata->data, pc);
+
+  if (bdata->ret != 0)
+    return _URC_END_OF_STACK;
+
+  return _URC_NO_REASON;
+}
+
+/* Get a simple stack backtrace.  */
+
+int
+backtrace_simple (struct backtrace_state *state, int skip,
+		  backtrace_simple_callback callback,
+		  backtrace_error_callback error_callback, void *data)
+{
+  struct backtrace_simple_data bdata;
+
+  bdata.skip = skip + 1;
+  bdata.state = state;
+  bdata.callback = callback;
+  bdata.error_callback = error_callback;
+  bdata.data = data;
+  bdata.ret = 0;
+  _Unwind_Backtrace (simple_unwind, &bdata);
+  return bdata.ret;
+}
diff --git a/third_party/gofrontend/libbacktrace/sort.c b/third_party/gofrontend/libbacktrace/sort.c
new file mode 100644
index 0000000..8c4760f
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/sort.c
@@ -0,0 +1,108 @@
+/* sort.c -- Sort without allocating memory
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* The GNU glibc version of qsort allocates memory, which we must not
+   do if we are invoked by a signal handler.  So provide our own
+   sort.  */
+
+static void
+swap (char *a, char *b, size_t size)
+{
+  size_t i;
+
+  for (i = 0; i < size; i++, a++, b++)
+    {
+      char t;
+
+      t = *a;
+      *a = *b;
+      *b = t;
+    }
+}
+
+void
+backtrace_qsort (void *basearg, size_t count, size_t size,
+		 int (*compar) (const void *, const void *))
+{
+  char *base = (char *) basearg;
+  size_t i;
+  size_t mid;
+
+ tail_recurse:
+  if (count < 2)
+    return;
+
+  /* The symbol table and DWARF tables, which is all we use this
+     routine for, tend to be roughly sorted.  Pick the middle element
+     in the array as our pivot point, so that we are more likely to
+     cut the array in half for each recursion step.  */
+  swap (base, base + (count / 2) * size, size);
+
+  mid = 0;
+  for (i = 1; i < count; i++)
+    {
+      if ((*compar) (base, base + i * size) > 0)
+	{
+	  ++mid;
+	  if (i != mid)
+	    swap (base + mid * size, base + i * size, size);
+	}
+    }
+
+  if (mid > 0)
+    swap (base, base + mid * size, size);
+
+  /* Recurse with the smaller array, loop with the larger one.  That
+     ensures that our maximum stack depth is log count.  */
+  if (2 * mid < count)
+    {
+      backtrace_qsort (base, mid, size, compar);
+      base += (mid + 1) * size;
+      count -= mid + 1;
+      goto tail_recurse;
+    }
+  else
+    {
+      backtrace_qsort (base + (mid + 1) * size, count - (mid + 1),
+		       size, compar);
+      count = mid;
+      goto tail_recurse;
+    }
+}
diff --git a/third_party/gofrontend/libbacktrace/state.c b/third_party/gofrontend/libbacktrace/state.c
new file mode 100644
index 0000000..a7d4e07
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/state.c
@@ -0,0 +1,72 @@
+/* state.c -- Create the backtrace state.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+#include "internal.h"
+
+/* Create the backtrace state.  This will then be passed to all the
+   other routines.  */
+
+struct backtrace_state *
+backtrace_create_state (const char *filename, int threaded,
+			backtrace_error_callback error_callback,
+			void *data)
+{
+  struct backtrace_state init_state;
+  struct backtrace_state *state;
+
+#ifndef HAVE_SYNC_FUNCTIONS
+  if (threaded)
+    {
+      error_callback (data, "backtrace library does not support threads", 0);
+      return NULL;
+    }
+#endif
+
+  memset (&init_state, 0, sizeof init_state);
+  init_state.filename = filename;
+  init_state.threaded = threaded;
+
+  state = ((struct backtrace_state *)
+	   backtrace_alloc (&init_state, sizeof *state, error_callback, data));
+  if (state == NULL)
+    return NULL;
+  *state = init_state;
+
+  return state;
+}
diff --git a/third_party/gofrontend/libbacktrace/stest.c b/third_party/gofrontend/libbacktrace/stest.c
new file mode 100644
index 0000000..5676745
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/stest.c
@@ -0,0 +1,137 @@
+/* stest.c -- Test for libbacktrace internal sort function
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Test the local qsort implementation.  */
+
+#define MAX 10
+
+struct test
+{
+  size_t count;
+  int input[MAX];
+  int output[MAX];
+};
+
+static struct test tests[] =
+  {
+    {
+      10,
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
+    },
+    {
+      9,
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
+    },
+    {
+      10,
+      { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 },
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+    },
+    {
+      9,
+      { 9, 8, 7, 6, 5, 4, 3, 2, 1 },
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+    },
+    {
+      10,
+      { 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 },
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+    },
+    {
+      5,
+      { 4, 5, 3, 1, 2 },
+      { 1, 2, 3, 4, 5 },
+    },
+    {
+      5,
+      { 1, 1, 1, 1, 1 },
+      { 1, 1, 1, 1, 1 },
+    },
+    {
+      5,
+      { 1, 1, 2, 1, 1 },
+      { 1, 1, 1, 1, 2 },
+    },
+    {
+      5,
+      { 2, 1, 1, 1, 1 },
+      { 1, 1, 1, 1, 2 },
+    },
+  };
+
+static int
+compare (const void *a, const void *b)
+{
+  const int *ai = (const int *) a;
+  const int *bi = (const int *) b;
+
+  return *ai - *bi;
+}
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+{
+  int failures;
+  size_t i;
+  int a[MAX];
+
+  failures = 0;
+  for (i = 0; i < sizeof tests / sizeof tests[0]; i++)
+    {
+      memcpy (a, tests[i].input, tests[i].count * sizeof (int));
+      backtrace_qsort (a, tests[i].count, sizeof (int), compare);
+      if (memcmp (a, tests[i].output, tests[i].count * sizeof (int)) != 0)
+	{
+	  size_t j;
+
+	  fprintf (stderr, "test %d failed:", (int) i);
+	  for (j = 0; j < tests[i].count; j++)
+	    fprintf (stderr, " %d", a[j]);
+	  fprintf (stderr, "\n");
+	  ++failures;
+	}
+    }
+
+  exit (failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/third_party/gofrontend/libbacktrace/unknown.c b/third_party/gofrontend/libbacktrace/unknown.c
new file mode 100644
index 0000000..c1fe881
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/unknown.c
@@ -0,0 +1,64 @@
+/* unknown.c -- used when backtrace configury does not know file format.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.  
+    
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* A trivial routine that always fails to find fileline data.  */
+
+static int
+unknown_fileline (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		  uintptr_t pc, backtrace_full_callback callback,
+		  backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+		  void *data)
+
+{
+  return callback (data, pc, NULL, 0, NULL);
+}
+
+/* Initialize the backtrace data when we don't know how to read the
+   debug info.  */
+
+int
+backtrace_initialize (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		      int descriptor ATTRIBUTE_UNUSED,
+		      backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+		      void *data ATTRIBUTE_UNUSED, fileline *fileline_fn)
+{
+  state->fileline_data = NULL;
+  *fileline_fn = unknown_fileline;
+  return 1;
+}
diff --git a/third_party/gofrontend/libffi/ChangeLog.libffi b/third_party/gofrontend/libffi/ChangeLog.libffi
new file mode 100644
index 0000000..f3ee8b0
--- /dev/null
+++ b/third_party/gofrontend/libffi/ChangeLog.libffi
@@ -0,0 +1,584 @@
+2011-02-08  Andreas Tobler  <andreast@fgznet.ch>
+
+	* testsuite/lib/libffi.exp: Tweak for stand-alone mode.
+
+2009-12-25  Samuli Suominen  <ssuominen@gentoo.org>
+
+	* configure.ac: Undefine _AC_ARG_VAR_PRECIOUS for autoconf 2.64.
+	* configure: Rebuilt.
+	* fficonfig.h.in: Rebuilt.
+
+2009-06-16  Andrew Haley  <aph@redhat.com>
+
+	* testsuite/libffi.call/cls_align_sint64.c,
+	testsuite/libffi.call/cls_align_uint64.c,
+	testsuite/libffi.call/cls_longdouble_va.c,
+	testsuite/libffi.call/cls_ulonglong.c,
+	testsuite/libffi.call/return_ll1.c,
+	testsuite/libffi.call/stret_medium2.c: Fix printf format
+	specifiers.
+	* testsuite/libffi.call/huge_struct.c: Ad x86 XFAILs.
+	* testsuite/libffi.call/float2.c: Fix dg-excess-errors.
+	* testsuite/libffi.call/ffitest.h,
+	testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRIuLL): Define.
+
+2009-06-12  Andrew Haley  <aph@redhat.com>
+
+	* testsuite/libffi.call/cls_align_sint64.c,
+	testsuite/libffi.call/cls_align_uint64.c,
+	testsuite/libffi.call/cls_ulonglong.c,
+	testsuite/libffi.call/return_ll1.c,
+	testsuite/libffi.call/stret_medium2.c: Fix printf format
+	specifiers.
+	testsuite/libffi.special/unwindtest.cc: include stdint.h.
+
+2009-06-11  Timothy Wall  <twall@users.sf.net>
+
+	* Makefile.am,
+        configure.ac,
+        include/ffi.h.in,
+        include/ffi_common.h,
+        src/closures.c,
+        src/dlmalloc.c,
+        src/x86/ffi.c,
+        src/x86/ffitarget.h,
+        src/x86/win64.S (new),
+	README: Added win64 support (mingw or MSVC)
+        * Makefile.in,
+        include/Makefile.in,
+        man/Makefile.in,
+        testsuite/Makefile.in,
+        configure,
+        aclocal.m4: Regenerated
+        * ltcf-c.sh: properly escape cygwin/w32 path
+        * man/ffi_call.3: Clarify size requirements for return value.
+        * src/x86/ffi64.c: Fix filename in comment.
+        * src/x86/win32.S: Remove unused extern.
+
+        * testsuite/libffi.call/closure_fn0.c,
+        testsuite/libffi.call/closure_fn1.c,
+        testsuite/libffi.call/closure_fn2.c,
+        testsuite/libffi.call/closure_fn3.c,
+        testsuite/libffi.call/closure_fn4.c,
+        testsuite/libffi.call/closure_fn5.c,
+        testsuite/libffi.call/closure_fn6.c,
+	testsuite/libffi.call/closure_stdcall.c,
+	testsuite/libffi.call/cls_12byte.c,
+	testsuite/libffi.call/cls_16byte.c,
+	testsuite/libffi.call/cls_18byte.c,
+	testsuite/libffi.call/cls_19byte.c,
+	testsuite/libffi.call/cls_1_1byte.c,
+	testsuite/libffi.call/cls_20byte.c,
+	testsuite/libffi.call/cls_20byte1.c,
+	testsuite/libffi.call/cls_24byte.c,
+	testsuite/libffi.call/cls_2byte.c,
+	testsuite/libffi.call/cls_3_1byte.c,
+	testsuite/libffi.call/cls_3byte1.c,
+ 	testsuite/libffi.call/cls_3byte2.c,
+ 	testsuite/libffi.call/cls_4_1byte.c,
+ 	testsuite/libffi.call/cls_4byte.c,
+ 	testsuite/libffi.call/cls_5_1_byte.c,
+ 	testsuite/libffi.call/cls_5byte.c,
+ 	testsuite/libffi.call/cls_64byte.c,
+ 	testsuite/libffi.call/cls_6_1_byte.c,
+ 	testsuite/libffi.call/cls_6byte.c,
+ 	testsuite/libffi.call/cls_7_1_byte.c,
+ 	testsuite/libffi.call/cls_7byte.c,
+ 	testsuite/libffi.call/cls_8byte.c,
+ 	testsuite/libffi.call/cls_9byte1.c,
+ 	testsuite/libffi.call/cls_9byte2.c,
+ 	testsuite/libffi.call/cls_align_double.c,
+ 	testsuite/libffi.call/cls_align_float.c,
+ 	testsuite/libffi.call/cls_align_longdouble.c,
+ 	testsuite/libffi.call/cls_align_longdouble_split.c,
+ 	testsuite/libffi.call/cls_align_longdouble_split2.c,
+ 	testsuite/libffi.call/cls_align_pointer.c,
+ 	testsuite/libffi.call/cls_align_sint16.c,
+ 	testsuite/libffi.call/cls_align_sint32.c,
+ 	testsuite/libffi.call/cls_align_sint64.c,
+ 	testsuite/libffi.call/cls_align_uint16.c,
+ 	testsuite/libffi.call/cls_align_uint32.c,
+ 	testsuite/libffi.call/cls_align_uint64.c,
+ 	testsuite/libffi.call/cls_dbls_struct.c,
+ 	testsuite/libffi.call/cls_double.c,
+ 	testsuite/libffi.call/cls_double_va.c,
+ 	testsuite/libffi.call/cls_float.c,
+ 	testsuite/libffi.call/cls_longdouble.c,
+ 	testsuite/libffi.call/cls_longdouble_va.c,
+ 	testsuite/libffi.call/cls_multi_schar.c,
+ 	testsuite/libffi.call/cls_multi_sshort.c,
+ 	testsuite/libffi.call/cls_multi_sshortchar.c,
+ 	testsuite/libffi.call/cls_multi_uchar.c,
+ 	testsuite/libffi.call/cls_multi_ushort.c,
+ 	testsuite/libffi.call/cls_multi_ushortchar.c,
+ 	testsuite/libffi.call/cls_pointer.c,
+ 	testsuite/libffi.call/cls_pointer_stack.c,
+ 	testsuite/libffi.call/cls_schar.c,
+ 	testsuite/libffi.call/cls_sint.c,
+ 	testsuite/libffi.call/cls_sshort.c,
+ 	testsuite/libffi.call/cls_uchar.c,
+ 	testsuite/libffi.call/cls_uint.c,
+ 	testsuite/libffi.call/cls_ulonglong.c,
+ 	testsuite/libffi.call/cls_ushort.c,
+ 	testsuite/libffi.call/err_bad_abi.c,
+ 	testsuite/libffi.call/err_bad_typedef.c,
+ 	testsuite/libffi.call/float2.c,
+ 	testsuite/libffi.call/huge_struct.c,
+ 	testsuite/libffi.call/nested_struct.c,
+ 	testsuite/libffi.call/nested_struct1.c,
+ 	testsuite/libffi.call/nested_struct10.c,
+ 	testsuite/libffi.call/nested_struct2.c,
+ 	testsuite/libffi.call/nested_struct3.c,
+ 	testsuite/libffi.call/nested_struct4.c,
+ 	testsuite/libffi.call/nested_struct5.c,
+ 	testsuite/libffi.call/nested_struct6.c,
+ 	testsuite/libffi.call/nested_struct7.c,
+ 	testsuite/libffi.call/nested_struct8.c,
+ 	testsuite/libffi.call/nested_struct9.c,
+ 	testsuite/libffi.call/problem1.c,
+ 	testsuite/libffi.call/return_ldl.c,
+ 	testsuite/libffi.call/return_ll1.c,
+ 	testsuite/libffi.call/stret_large.c,
+ 	testsuite/libffi.call/stret_large2.c,
+ 	testsuite/libffi.call/stret_medium.c,
+ 	testsuite/libffi.call/stret_medium2.c,
+        testsuite/libffi.special/unwindtest.cc: use ffi_closure_alloc instead
+        of checking for MMAP.  Use intptr_t instead of long casts.
+
+2009-06-04  Andrew Haley  <aph@redhat.com>
+
+	* src/powerpc/ffitarget.h: Fix misapplied merge from gcc.
+
+2009-06-04  Andrew Haley  <aph@redhat.com>
+
+	* src/mips/o32.S,
+	src/mips/n32.S: Fix licence formatting.
+
+2009-06-04  Andrew Haley  <aph@redhat.com>
+
+	* src/x86/darwin.S: Fix licence formatting.
+	src/x86/win32.S: Likewise.
+	src/sh64/sysv.S: Likewise.
+	src/sh/sysv.S: Likewise.
+
+2009-06-04  Andrew Haley  <aph@redhat.com>
+
+	* src/sh64/ffi.c: Remove lint directives.  Was missing from merge
+	of Andreas Tobler's patch from 2006-04-22.
+	
+2009-06-04  Andrew Haley  <aph@redhat.com>
+
+	* src/sh/ffi.c: Apply missing hunk from Alexandre Oliva's patch of
+	2007-03-07.
+
+2008-12-26  Timothy Wall  <twall@users.sf.net>
+
+	* testsuite/libffi.call/cls_longdouble.c,
+        testsuite/libffi.call/cls_longdouble_va.c,
+        testsuite/libffi.call/cls_align_longdouble.c,
+        testsuite/libffi.call/cls_align_longdouble_split.c,
+        testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected
+        failures on x86_64 cygwin/mingw.
+
+2008-12-22  Timothy Wall  <twall@users.sf.net>
+
+	* testsuite/libffi.call/closure_fn0.c,
+        testsuite/libffi.call/closure_fn1.c,    
+        testsuite/libffi.call/closure_fn2.c,    
+        testsuite/libffi.call/closure_fn3.c,    
+        testsuite/libffi.call/closure_fn4.c,    
+        testsuite/libffi.call/closure_fn5.c,    
+        testsuite/libffi.call/closure_fn6.c,    
+        testsuite/libffi.call/closure_loc_fn0.c,    
+        testsuite/libffi.call/closure_stdcall.c,    
+        testsuite/libffi.call/cls_align_pointer.c,    
+        testsuite/libffi.call/cls_pointer.c,    
+        testsuite/libffi.call/cls_pointer_stack.c: use portable cast from
+        pointer to integer (intptr_t).
+        * testsuite/libffi.call/cls_longdouble.c: disable for win64.
+	
+2008-12-19  Anthony Green  <green@redhat.com>
+
+	* configure.ac: Bump version to 3.0.8.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+	* libtool-version: Increment revision.
+	* README: Update for new release.
+
+2008-11-11  Anthony Green  <green@redhat.com>
+
+	* configure.ac: Bump version to 3.0.7.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+	* libtool-version: Increment revision.
+	* README: Update for new release.
+
+2008-08-25  Andreas Tobler  <a.tobler@schweiz.org>
+
+	* src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and
+	FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum.
+	Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT.
+	Adjust copyright notice.
+	* src/powerpc/ffi.c: Add two new flags to indicate if we have one
+	register or two register to use for FFI_SYSV structs.
+	(ffi_prep_cif_machdep): Pass the right register flag introduced above.
+	(ffi_closure_helper_SYSV): Fix the return type for
+	FFI_SYSV_TYPE_SMALL_STRUCT. Comment.
+	Adjust copyright notice.
+
+2008-07-24  Anthony Green  <green@redhat.com>
+
+	* testsuite/libffi.call/cls_dbls_struct.c,
+	testsuite/libffi.call/cls_double_va.c,
+	testsuite/libffi.call/cls_longdouble.c,
+	testsuite/libffi.call/cls_longdouble_va.c,
+	testsuite/libffi.call/cls_pointer.c,
+	testsuite/libffi.call/cls_pointer_stack.c,
+	testsuite/libffi.call/err_bad_abi.c: Clean up failures from
+	compiler warnings.
+
+2008-07-17  Anthony Green  <green@redhat.com>
+
+	* configure.ac: Bump version to 3.0.6.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+	* libtool-version: Increment revision.  Add documentation.
+	* README: Update for new release.
+
+2008-07-16  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+	* src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned
+	int.
+
+2008-07-16  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+	* src/sh/sysv.S: Add .note.GNU-stack on Linux.
+	* src/sh64/sysv.S: Likewise.
+
+2008-04-03  Anthony Green  <green@redhat.com>
+
+	* libffi.pc.in (Libs): Add -L${libdir}.
+	* configure.ac: Bump version to 3.0.5.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+	* libtool-version: Increment revision.
+	* README: Update for new release.
+
+2008-04-03  Anthony Green  <green@redhat.com>
+	    Xerces Ranby  <xerxes@zafena.se>
+
+	* include/ffi.h.in: Wrap definition of target architecture to
+	protect from double definitions.
+
+2008-03-22  Moriyoshi Koizumi  <moriyoshi@gmail.com>
+
+	* src/x86/ffi.c (ffi_prep_closure_loc): Fix for bug revealed in
+	closure_loc_fn0.c.
+	* testsuite/libffi.call/closure_loc_fn0.c (closure_loc_test_fn0):
+	New test.
+
+2008-03-04  Anthony Green  <green@redhat.com>
+	    Blake Chaffin
+	    hos@tamanegi.org
+
+	* testsuite/libffi.call/cls_align_longdouble_split2.c
+          testsuite/libffi.call/cls_align_longdouble_split.c
+          testsuite/libffi.call/cls_dbls_struct.c
+          testsuite/libffi.call/cls_double_va.c
+          testsuite/libffi.call/cls_longdouble.c
+          testsuite/libffi.call/cls_longdouble_va.c
+          testsuite/libffi.call/cls_pointer.c
+          testsuite/libffi.call/cls_pointer_stack.c
+          testsuite/libffi.call/err_bad_abi.c
+          testsuite/libffi.call/err_bad_typedef.c
+          testsuite/libffi.call/huge_struct.c
+          testsuite/libffi.call/stret_large2.c
+          testsuite/libffi.call/stret_large.c
+          testsuite/libffi.call/stret_medium2.c
+          testsuite/libffi.call/stret_medium.c: New tests from Apple.
+
+2008-02-26  Jakub Jelinek  <jakub@redhat.com>
+            Anthony Green  <green@redhat.com>
+
+	* src/alpha/osf.S: Add .note.GNU-stack on Linux.
+	* src/s390/sysv.S: Likewise.
+	* src/powerpc/linux64.S: Likewise.
+	* src/powerpc/linux64_closure.S: Likewise.
+	* src/powerpc/ppc_closure.S: Likewise.
+	* src/powerpc/sysv.S: Likewise.
+	* src/x86/unix64.S: Likewise.
+	* src/x86/sysv.S: Likewise.
+	* src/sparc/v8.S: Likewise.
+	* src/sparc/v9.S: Likewise.
+	* src/m68k/sysv.S: Likewise.
+	* src/ia64/unix.S: Likewise.
+	* src/arm/sysv.S: Likewise.
+
+2008-02-26  Anthony Green  <green@redhat.com>
+            Thomas Heller  <theller@ctypes.org>
+
+	* src/x86/ffi.c (ffi_closure_SYSV_inner): Change C++ comment to C
+	comment.
+
+2008-02-26  Anthony Green  <green@redhat.org>
+            Thomas Heller  <theller@ctypes.org>
+
+	* include/ffi.h.in: Change void (*)() to void (*)(void).
+
+2008-02-26  Anthony Green  <green@redhat.org>
+            Thomas Heller  <theller@ctypes.org>
+
+	* src/alpha/ffi.c: Change void (*)() to void (*)(void).
+	src/alpha/osf.S, src/arm/ffi.c, src/frv/ffi.c, src/ia64/ffi.c,
+	src/ia64/unix.S, src/java_raw_api.c, src/m32r/ffi.c,
+	src/mips/ffi.c, src/pa/ffi.c, src/pa/hpux32.S, src/pa/linux.S,
+	src/powerpc/ffi.c, src/powerpc/ffi_darwin.c, src/raw_api.c,
+	src/s390/ffi.c, src/sh/ffi.c, src/sh64/ffi.c, src/sparc/ffi.c,
+	src/x86/ffi.c, src/x86/unix64.S, src/x86/darwin64.S,
+	src/x86/ffi64.c: Ditto.
+
+2008-02-24  Anthony Green  <green@redhat.org>
+
+	* configure.ac: Accept openbsd*, not just openbsd.
+	Bump version to 3.0.4.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+	* libtool-version: Increment revision.
+	* README: Update for new release.
+
+2008-02-22  Anthony Green  <green@redhat.com>
+
+	* README: Clean up list of tested platforms.
+
+2008-02-22  Anthony Green  <green@redhat.com>
+
+	* configure.ac: Bump version to 3.0.3.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+	* libtool-version: Increment revision.
+	* README: Update for new release.  Clean up test docs.
+
+2008-02-22  Bjoern Koenig  <bkoenig@alpha-tierchen.de>
+	    Andreas Tobler  <a.tobler@schweiz.org>
+
+	* configure.ac: Add amd64-*-freebsd* target.
+	* configure: Regenerate.
+
+2008-02-22  Thomas Heller <theller@ctypes.org>
+
+	* configure.ac: Add x86 OpenBSD support.
+	* configure: Rebuilt.
+
+2008-02-21  Thomas Heller <theller@ctypes.org>
+
+	* README: Change "make test" to "make check".
+
+2008-02-21  Anthony Green  <green@redhat.com>
+
+	* configure.ac: Bump version to 3.0.2.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+	* libtool-version: Increment revision.
+	* README: Update for new release.
+
+2008-02-21  Björn König <bkoenig@alpha-tierchen.de>
+
+	* src/x86/freebsd.S: New file.
+	* configure.ac: Add x86 FreeBSD support.
+	* Makefile.am: Ditto.
+
+2008-02-15  Anthony Green  <green@redhat.com>
+
+	* configure.ac: Bump version to 3.0.1.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+	* libtool-version: Increment revision.
+	* README: Update for new release.
+
+2008-02-15  David Daney	 <ddaney@avtrex.com>
+
+	* src/mips/ffi.c: Remove extra '>' from include directive.
+	(ffi_prep_closure_loc): Use clear_location instead of tramp.
+
+2008-02-15  Anthony Green  <green@redhat.com>
+
+	* configure.ac: Bump version to 3.0.0.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+
+2008-02-15  David Daney	 <ddaney@avtrex.com>
+
+	* src/mips/ffi.c (USE__BUILTIN___CLEAR_CACHE):
+	Define (conditionally), and use it to include cachectl.h.
+	(ffi_prep_closure_loc): Fix cache flushing.
+	* src/mips/ffitarget.h (_ABIN32, _ABI64, _ABIO32): Define.
+
+2008-02-15  Anthony Green  <green@redhat.com>
+
+        * man/ffi_call.3, man/ffi_prep_cif.3, man/ffi.3:
+	Update dates and remove all references to ffi_prep_closure.
+	* configure.ac: Bump version to 2.99.9.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+
+2008-02-15  Anthony Green  <green@redhat.com>
+
+	* man/ffi_prep_closure.3: Delete.
+	* man/Makefile.am (EXTRA_DIST): Remove ffi_prep_closure.3.
+	(man_MANS): Ditto.
+	* man/Makefile.in: Rebuilt.
+	* configure.ac: Bump version to 2.99.8.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+	* configure.ac: Bump version to 2.99.7.
+	* configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+	* include/ffi.h.in LICENSE src/debug.c src/closures.c
+          src/ffitest.c src/s390/sysv.S src/s390/ffitarget.h
+          src/types.c src/m68k/ffitarget.h src/raw_api.c src/frv/ffi.c
+          src/frv/ffitarget.h src/sh/ffi.c src/sh/sysv.S
+          src/sh/ffitarget.h src/powerpc/ffitarget.h src/pa/ffi.c
+          src/pa/ffitarget.h src/pa/linux.S src/java_raw_api.c
+          src/cris/ffitarget.h src/x86/ffi.c src/x86/sysv.S
+          src/x86/unix64.S src/x86/win32.S src/x86/ffitarget.h
+          src/x86/ffi64.c src/x86/darwin.S src/ia64/ffi.c
+          src/ia64/ffitarget.h src/ia64/ia64_flags.h src/ia64/unix.S
+          src/sparc/ffi.c src/sparc/v9.S src/sparc/ffitarget.h
+          src/sparc/v8.S src/alpha/ffi.c src/alpha/ffitarget.h
+          src/alpha/osf.S src/sh64/ffi.c src/sh64/sysv.S
+          src/sh64/ffitarget.h src/mips/ffi.c src/mips/ffitarget.h
+          src/mips/n32.S src/mips/o32.S src/arm/ffi.c src/arm/sysv.S
+          src/arm/ffitarget.h src/prep_cif.c: Update license text.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+	* README: Update tested platforms.
+	* configure.ac: Bump version to 2.99.6.
+	* configure: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+	* configure.ac: Bump version to 2.99.5.
+	* configure: Rebuilt.
+	* Makefile.am (EXTRA_DIST): Add darwin64.S
+	* Makefile.in: Rebuilt.
+	* testsuite/lib/libffi-dg.exp: Remove libstdc++ bits from GCC tree.
+	* LICENSE: Update WARRANTY.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+	* libffi.pc.in (libdir): Fix libdir definition.
+	* configure.ac: Bump version to 2.99.4.
+	* configure: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+	* README: Update.
+	* libffi.info: New file.
+	* doc/stamp-vti: New file.
+	* configure.ac: Bump version to 2.99.3.
+	* configure: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+	* Makefile.am (SUBDIRS): Add man dir.
+	* Makefile.in: Rebuilt.
+	* configure.ac: Create Makefile.
+	* configure: Rebuilt.
+        * man/ffi_call.3 man/ffi_prep_cif.3 man/ffi_prep_closure.3
+          man/Makefile.am man/Makefile.in: New files.
+
+2008-02-14  Tom Tromey  <tromey@redhat.com>
+
+	* aclocal.m4, Makefile.in, configure, fficonfig.h.in: Rebuilt.
+	* mdate-sh, texinfo.tex: New files.
+	* Makefile.am (info_TEXINFOS): New variable.
+	* doc/libffi.texi: New file.
+	* doc/version.texi: Likewise.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+	* Makefile.am (AM_CFLAGS): Don't compile with -D$(TARGET).
+	(lib_LTLIBRARIES): Define.
+	(toolexeclib_LIBRARIES): Undefine.
+	* Makefile.in: Rebuilt.
+	* configure.ac: Reset version to 2.99.1.
+	* configure.in: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+	* libffi.pc.in: Use @PACKAGE_NAME@ and @PACKAGE_VERSION@.
+	* configure.ac: Reset version to 2.99.1.
+	* configure.in: Rebuilt.
+	* Makefile.am (EXTRA_DIST): Add ChangeLog.libffi.
+	* Makefile.in: Rebuilt.
+	* LICENSE: Update copyright notice.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+	* include/Makefile.am (nodist_includes_HEADERS): Define.  Don't
+	distribute ffitarget.h or ffi.h from the build include dir.
+	* Makefile.in: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+	* include/Makefile.am (includesdir): Install headers under libdir.
+	(pkgconfigdir): Define. Install libffi.pc.
+	* include/Makefile.in: Rebuilt.
+	* libffi.pc.in: Create.
+	* libtool-version: Increment CURRENT
+	* configure.ac: Add libffi.pc.in
+	* configure: Rebuilt.
+
+2008-02-03  Anthony Green  <green@redhat.com>
+
+	* include/Makefile.am (includesdir): Fix header install with
+	DESTDIR.
+	* include/Makefile.in: Rebuilt.
+
+2008-02-03  Timothy Wall  <twall@users.sf.net>
+
+	* src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL): Calculate jump return
+          offset based on code pointer, not data pointer.
+
+2008-02-01  Anthony Green  <green@redhat.com>
+
+	* include/Makefile.am: Fix header installs.
+	* Makefile.am: Ditto.
+	* include/Makefile.in: Rebuilt.
+	* Makefile.in: Ditto.
+
+2008-02-01  Anthony Green  <green@redhat.com>
+
+	* src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL,
+	FFI_INIT_TRAMPOLINE): Revert my broken changes to twall's last
+	patch.
+
+2008-01-31  Anthony Green  <green@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add missing files.
+	* testsuite/Makefile.am: Ditto.
+	* Makefile.in, testsuite/Makefile.in: Rebuilt.
+
+2008-01-31  Timothy Wall <twall@users.sf.net>
+
+	* testsuite/libffi.call/closure_stdcall.c: Add test for stdcall
+	closures.
+	* src/x86/ffitarget.h: Increase size of trampoline for stdcall
+	closures.
+	* src/x86/win32.S: Add assembly for stdcall closure.
+	* src/x86/ffi.c: Initialize stdcall closure trampoline.
+
+2008-01-30  H.J. Lu <hongjiu.lu@intel.com>
+
+	PR libffi/34612
+	* src/x86/sysv.S (ffi_closure_SYSV): Pop 4 byte from stack when
+	returning struct.
+
+	* testsuite/libffi.call/call.exp: Add "-O2 -fomit-frame-pointer"
+	tests.
+
+2008-01-30  Anthony Green  <green@redhat.com>
+
+	* Makefile.am, include/Makefile.am: Move headers to
+	libffi_la_SOURCES for new automake.
+	* Makefile.in, include/Makefile.in: Rebuilt.
+	
+	* testsuite/lib/wrapper.exp: Copied from gcc tree to allow for 
+	execution outside of gcc tree.
+	* testsuite/lib/target-libpath.exp: Ditto.
+
+	* testsuite/lib/libffi-dg.exp: Many changes to allow for execution
+	outside of gcc tree.
+
diff --git a/third_party/gofrontend/libffi/ChangeLog.libgcj b/third_party/gofrontend/libffi/ChangeLog.libgcj
new file mode 100644
index 0000000..ea5d02f
--- /dev/null
+++ b/third_party/gofrontend/libffi/ChangeLog.libgcj
@@ -0,0 +1,40 @@
+2004-01-14  Kelley Cook  <kcook@gcc.gnu.org>
+
+	* configure.in: Add in AC_PREREQ(2.13)
+
+2003-02-20  Alexandre Oliva  <aoliva@redhat.com>
+
+	* configure.in: Propagate ORIGINAL_LD_FOR_MULTILIBS to
+	config.status.
+	* configure: Rebuilt.
+
+2002-01-27  Alexandre Oliva  <aoliva@redhat.com>
+
+	* configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST.
+	Remove USE_LIBDIR conditional.
+	* Makefile.am (toolexecdir, toolexeclibdir): Don't override.
+	* Makefile.in, configure: Rebuilt.
+
+Mon Aug  9 18:33:38 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* include/Makefile.in: Rebuilt.
+	* Makefile.in: Rebuilt
+	* Makefile.am (toolexeclibdir): Add $(MULTISUBDIR) even for native
+	builds.
+	Use USE_LIBDIR.
+
+	* configure: Rebuilt.
+	* configure.in (USE_LIBDIR): Define for native builds.
+	Use lowercase in configure --help explanations.
+
+1999-08-08  Anthony Green  <green@cygnus.com>
+
+	* include/ffi.h.in (FFI_FN): Remove `...'.
+
+1999-08-08  Anthony Green  <green@cygnus.com>
+
+	* Makefile.in: Rebuilt.
+	* Makefile.am (AM_CFLAGS): Compile with -fexceptions.
+
+	* src/x86/sysv.S: Add exception handling metadata.
+
diff --git a/third_party/gofrontend/libffi/ChangeLog.v1 b/third_party/gofrontend/libffi/ChangeLog.v1
new file mode 100644
index 0000000..369820c
--- /dev/null
+++ b/third_party/gofrontend/libffi/ChangeLog.v1
@@ -0,0 +1,764 @@
+The libffi version 1 ChangeLog archive.
+
+Version 1 of libffi had per-directory ChangeLogs.  Current and future
+versions have a single ChangeLog file in the root directory.  The
+version 1 ChangeLogs have all been concatonated into this file for
+future reference only.
+
+--- libffi ----------------------------------------------------------------
+
+Mon Oct  5 02:17:50 1998  Anthony Green  <green@cygnus.com>
+
+	* configure.in: Boosted rev.
+	* configure, Makefile.in, aclocal.m4: Rebuilt.
+	* README: Boosted rev and updated release notes.
+
+Mon Oct  5 01:03:03 1998  Anthony Green  <green@cygnus.com>
+
+	* configure.in: Boosted rev.
+	* configure, Makefile.in, aclocal.m4: Rebuilt.
+	* README: Boosted rev and updated release notes.
+
+1998-07-25  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* m68k/ffi.c (ffi_prep_cif_machdep): Use bitmask for cif->flags.
+	Correctly handle small structures.
+	(ffi_prep_args): Also handle small structures.
+	(ffi_call): Pass size of return type to ffi_call_SYSV.
+	* m68k/sysv.S: Adjust for above changes.  Correctly align small
+	structures in the return value.
+
+	* types.c (uint64, sint64) [M68K]: Change alignment to 4.
+
+Fri Apr 17 17:26:58 1998  Anthony Green  <green@hoser.cygnus.com>
+
+	* configure.in: Boosted rev.
+	* configure,Makefile.in,aclocal.m4: Rebuilt.
+	* README: Boosted rev and added release notes.
+
+Sun Feb 22 00:50:41 1998  Geoff Keating  <geoffk@ozemail.com.au>
+
+	* configure.in: Add PowerPC config bits.
+
+1998-02-14  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* configure.in: Add m68k config bits.  Change AC_CANONICAL_SYSTEM
+	to AC_CANONICAL_HOST, this is not a compiler.  Use $host instead
+	of $target.  Remove AC_CHECK_SIZEOF(char), we already know the
+	result.  Fix argument of AC_ARG_ENABLE.
+	* configure, fficonfig.h.in: Rebuilt.
+
+Tue Feb 10 20:53:40 1998  Richard Henderson  <rth@cygnus.com>
+
+	* configure.in: Add Alpha config bits.
+
+Tue May 13 13:39:20 1997  Anthony Green  <green@hoser.cygnus.com>
+
+	* README: Updated dates and reworded Irix comments.
+
+	* configure.in: Removed AC_PROG_RANLIB.
+
+	* Makefile.in, aclocal.m4, config.guess, config.sub, configure,
+	ltmain.sh, */Makefile.in: libtoolized again and	rebuilt with 
+	automake and autoconf.
+	
+Sat May 10 18:44:50 1997  Tom Tromey  <tromey@cygnus.com>
+
+	* configure, aclocal.m4: Rebuilt.
+	* configure.in: Don't compute EXTRADIST; now handled in
+	src/Makefile.in.  Removed macros implied by AM_INIT_AUTOMAKE.
+	Don't run AM_MAINTAINER_MODE.
+
+Thu May  8 14:34:05 1997  Anthony Green  <green@hoser.cygnus.com>
+
+	* missing, ltmain.sh, ltconfig.sh: Created. These are new files
+	required by automake and libtool.
+
+	* README: Boosted rev to 1.14. Added notes.
+
+	* acconfig.h: Moved PACKAGE and VERSION for new automake.
+	
+	* configure.in: Changes for libtool.
+	
+	* Makefile.am (check): make test now make check. Uses libtool now.
+
+	* Makefile.in, configure.in, aclocal.h, fficonfig.h.in: Rebuilt.
+
+Thu May  1 16:27:07 1997  Anthony Green  <green@hoser.cygnus.com>
+
+	* missing: Added file required by new automake.
+
+Tue Nov 26 14:10:42 1996  Anthony Green  <green@csk3.cygnus.com>
+
+	* acconfig.h: Added USING_PURIFY flag. This is defined when
+	--enable-purify-safety was used at configure time.
+
+	* configure.in (allsources): Added --enable-purify-safety switch.
+	(VERSION): Boosted rev to 1.13.
+	* configure: Rebuilt.
+
+Fri Nov 22 06:46:12 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* configure.in (VERSION): Boosted rev to 1.12.
+	Removed special CFLAGS hack for gcc.
+	* configure: Rebuilt.
+
+	* README: Boosted rev to 1.12. Added notes.
+
+	* Many files: Cygnus Support changed to Cygnus Solutions.
+
+Wed Oct 30 11:15:25 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* configure.in (VERSION): Boosted rev to 1.11.
+	* configure: Rebuilt.
+
+	* README: Boosted rev to 1.11. Added notes about GNU make.
+
+Tue Oct 29 12:25:12 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* configure.in: Fixed -Wall trick.
+	(VERSION): Boosted rev.
+	* configure: Rebuilt
+
+	* acconfig.h: Needed for --enable-debug configure switch.
+
+	* README: Boosted rev to 1.09. Added more notes on building
+	libffi, and LCLint.
+
+	* configure.in: Added --enable-debug switch. Boosted rev to
+	1.09.
+	* configure: Rebuilt
+
+Tue Oct 15 13:11:28 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* configure.in (VERSION): Boosted rev to 1.08
+	* configure: Rebuilt.
+
+	* README: Added n32 bug fix notes.
+
+	* Makefile.am: Added "make lint" production. 
+	* Makefile.in: Rebuilt.
+
+Mon Oct 14 10:54:46 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* README: Added web page reference.
+
+	* configure.in, README: Boosted rev to 1.05
+	* configure: Rebuilt.
+
+	* README: Fixed n32 sample code.
+
+Fri Oct 11 17:09:28 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* README: Added sparc notes.
+
+	* configure.in, README: Boosted rev to 1.04.
+	* configure: Rebuilt.
+
+Thu Oct 10 10:31:03 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* configure.in, README: Boosted rev to 1.03.
+	* configure: Rebuilt.
+
+	* README: Added struct notes. 
+
+	* Makefile.am (EXTRA_DIST): Added LICENSE to distribution.
+	* Makefile.in: Rebuilt.
+
+	* README: Removed Linux section. No special notes now
+	because aggregates arg/return types work.
+
+Wed Oct  9 16:16:42 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* README, configure.in (VERSION): Boosted rev to 1.02
+	* configure: Rebuilt.
+
+Tue Oct  8 11:56:33 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* README (NOTE): Added n32 notes.
+
+	* Makefile.am: Added test production.
+	* Makefile: Rebuilt
+
+	* README: spell checked!
+
+	* configure.in (VERSION): Boosted rev to 1.01
+	* configure: Rebuilt.
+
+Mon Oct  7 15:50:22 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* configure.in: Added nasty bit to support SGI tools.
+	* configure: Rebuilt.
+	
+	* README: Added SGI notes. Added note about automake bug.
+
+Mon Oct  7 11:00:28 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* README: Rewrote intro, and fixed examples.
+
+Fri Oct  4 10:19:55 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* configure.in: -D$TARGET is no longer used as a compiler switch.
+	It is now inserted into ffi.h at configure time.
+	* configure: Rebuilt.
+
+	* FFI_ABI and FFI_STATUS are now ffi_abi and ffi_status.
+
+Thu Oct  3 13:47:34 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* README, LICENSE: Created. Wrote some docs.
+
+	* configure.in: Don't barf on i586-unknown-linuxaout.
+	Added EXTRADIST code for "make dist".
+	* configure: Rebuilt.
+
+	* */Makefile.in: Rebuilt with patched automake. 
+
+Tue Oct  1 17:12:25 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* Makefile.am, aclocal.m4, config.guess, config.sub,
+	configure.in, fficonfig.h.in, install-sh, mkinstalldirs, 
+	stamp-h.in: Created
+	* Makefile.in, configure: Generated
+
+--- libffi/include --------------------------------------------------------
+
+Tue Feb 24 13:09:36 1998  Anthony Green  <green@gerbil.cygnus.com>
+
+	* ffi_mips.h: Updated FFI_TYPE_STRUCT_* values based on
+	ffi.h.in changes.  This is a work-around for SGI's "simple"
+	assembler.
+
+Sun Feb 22 00:51:55 1998  Geoff Keating  <geoffk@ozemail.com.au>
+
+	* ffi.h.in: PowerPC support.
+
+1998-02-14  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* ffi.h.in: Add m68k support.
+	(FFI_TYPE_LONGDOUBLE): Make it a separate value.
+
+Tue Feb 10 20:55:16 1998  Richard Henderson  <rth@cygnus.com>
+
+	* ffi.h.in (SIZEOF_ARG): Use a pointer type by default.
+
+	* ffi.h.in: Alpha support.
+
+Fri Nov 22 06:48:45 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.h.in, ffi_common.h: Cygnus Support -> Cygnus Solutions.
+
+Wed Nov 20 22:31:01 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.h.in: Added ffi_type_void definition.
+
+Tue Oct 29 12:22:40 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* Makefile.am (hack_DATA): Always install ffi_mips.h.
+
+	* ffi.h.in: Removed FFI_DEBUG. It's now in the correct
+	place (acconfig.h).
+	Added #include <stddef.h> for size_t definition.
+
+Tue Oct 15 17:23:35 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.h.in, ffi_common.h, ffi_mips.h: More clean up.
+	Commented out #define of FFI_DEBUG.
+
+Tue Oct 15 13:01:06 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi_common.h: Added bool definition.
+
+	* ffi.h.in, ffi_common.h: Clean up based on LCLint output.
+	Added funny /*@...@*/ comments to annotate source.
+
+Mon Oct 14 12:29:23 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.h.in: Interface changes based on feedback from Jim
+	Blandy.
+
+Fri Oct 11 16:49:35 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.h.in: Small change for sparc support.
+
+Thu Oct 10 14:53:37 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi_mips.h: Added FFI_TYPE_STRUCT_* definitions for 
+	special structure return types.
+
+Wed Oct  9 13:55:57 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.h.in: Added SIZEOF_ARG definition for X86
+
+Tue Oct  8 11:40:36 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.h.in (FFI_FN): Added macro for eliminating compiler warnings.
+	Use it to case your function pointers to the proper type.
+
+	* ffi_mips.h (SIZEOF_ARG): Added magic to fix type promotion bug.
+
+	* Makefile.am (EXTRA_DIST): Added ffi_mips.h to EXTRA_DIST.
+	* Makefile: Rebuilt.
+
+	* ffi_mips.h: Created. Moved all common mips definitions here.
+
+Mon Oct  7 10:58:12 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.h.in: The SGI assember is very picky about parens. Redefined
+ 	some macros to avoid problems.
+
+	* ffi.h.in: Added FFI_DEFAULT_ABI definitions. Also added
+	externs for pointer, and 64bit integral ffi_types.
+
+Fri Oct  4 09:51:37 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.h.in: Added FFI_ABI member to ffi_cif and changed
+	function prototypes accordingly.
+	Added #define @TARGET@. Now programs including ffi.h don't 
+	have to specify this themselves.
+
+Thu Oct  3 15:36:44 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.h.in: Changed ffi_prep_cif's values from void* to void**
+
+	* Makefile.am (EXTRA_DIST): Added EXTRA_DIST for "make dist"
+	to work.
+	* Makefile.in: Regenerated.
+
+Wed Oct  2 10:16:59 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* Makefile.am: Created
+	* Makefile.in: Generated
+
+	* ffi_common.h: Added rcsid comment
+
+Tue Oct  1 17:13:51 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.h.in, ffi_common.h: Created
+
+--- libffi/src ------------------------------------------------------------
+
+Mon Oct  5 02:17:50 1998  Anthony Green  <green@cygnus.com>
+
+	* arm/ffi.c, arm/sysv.S: Created.
+
+	* Makefile.am: Added arm files.
+	* Makefile.in: Rebuilt.
+
+Mon Oct  5 01:41:38 1998  Anthony Green  <green@rtl.cygnus.com>
+
+	* Makefile.am (libffi_la_LDFLAGS): Incremented revision.
+
+Sun Oct  4 16:27:17 1998  Anthony Green  <green@cygnus.com>
+
+	* alpha/osf.S (ffi_call_osf): Patch for DU assembler.
+
+	* ffitest.c (main): long long and long double return values work
+	for x86.
+
+Fri Apr 17 11:50:58 1998  Anthony Green  <green@hoser.cygnus.com>
+
+	* Makefile.in: Rebuilt.
+
+	* ffitest.c (main): Floating point tests not executed for systems
+ 	with broken lond double (SunOS 4 w/ GCC).
+
+	* types.c: Fixed x86 alignment info for long long types.
+
+Thu Apr 16 07:15:28 1998  Anthony Green  <green@ada.cygnus.com>
+
+	* ffitest.c: Added more notes about GCC bugs under Irix 6.
+
+Wed Apr 15 08:42:22 1998  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffitest.c (struct5): New test function.
+	(main): New test with struct5.
+
+Thu Mar  5 10:48:11 1998  Anthony Green  <green@tootie.to.cygnus.com>
+
+	* prep_cif.c (initialize_aggregate): Fix assertion for
+	nested structures.
+
+Tue Feb 24 16:33:41 1998  Anthony Green  <green@hoser.cygnus.com>
+
+	* prep_cif.c (ffi_prep_cif): Added long double support for sparc.
+
+Sun Feb 22 00:52:18 1998  Geoff Keating  <geoffk@ozemail.com.au>
+
+	* powerpc/asm.h: New file.
+	* powerpc/ffi.c: New file.
+	* powerpc/sysv.S: New file.
+	* Makefile.am: PowerPC port.
+	* ffitest.c (main): Allow all tests to run even in presence of gcc
+ 	bug on PowerPC.
+
+1998-02-17  Anthony Green  <green@hoser.cygnus.com>
+
+	* mips/ffi.c: Fixed comment typo.
+
+	* x86/ffi.c (ffi_prep_cif_machdep), x86/sysv.S (retfloat): 
+	Fixed x86 long double return handling.
+
+	* types.c: Fixed x86 long double alignment info.
+
+1998-02-14  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* types.c: Add m68k support.
+
+	* ffitest.c (floating): Add long double parameter.
+	(return_ll, ldblit): New functions to test long long and long
+	double return value.
+	(main): Fix type error in assignment of ts[1-4]_type.elements.
+	Add tests for long long and long double arguments and return
+	values.
+
+	* prep_cif.c (ffi_prep_cif) [M68K]: Don't allocate argument for
+	struct value pointer.
+
+	* m68k/ffi.c, m68k/sysv.S: New files.
+	* Makefile.am: Add bits for m68k port.  Add kludge to work around
+	automake deficiency.
+	(test): Don't require "." in $PATH.
+	* Makefile.in: Rebuilt.
+
+Wed Feb 11 07:36:50 1998  Anthony Green  <green@hoser.cygnus.com>
+
+	* Makefile.in: Rebuilt.
+
+Tue Feb 10 20:56:00 1998  Richard Henderson  <rth@cygnus.com>
+
+	* alpha/ffi.c, alpha/osf.S: New files.
+	* Makefile.am: Alpha port.
+
+Tue Nov 18 14:12:07 1997  Anthony Green  <green@hoser.cygnus.com>
+
+	* mips/ffi.c (ffi_prep_cif_machdep): Initialize rstruct_flag
+	for n32.
+
+Tue Jun  3 17:18:20 1997  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffitest.c (main): Added hack to get structure tests working
+	correctly.
+
+Sat May 10 19:06:42 1997  Tom Tromey  <tromey@cygnus.com>
+
+	* Makefile.in: Rebuilt.
+	* Makefile.am (EXTRA_DIST): Explicitly list all distributable
+	files in subdirs.
+	(VERSION, CC): Removed.
+
+Thu May  8 17:19:01 1997  Anthony Green  <green@hoser.cygnus.com>
+
+	* Makefile.am: Many changes for new automake and libtool.
+	* Makefile.in: Rebuilt.
+
+Fri Nov 22 06:57:56 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffitest.c (main): Fixed test case for non mips machines.
+
+Wed Nov 20 22:31:59 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* types.c: Added ffi_type_void declaration.
+
+Tue Oct 29 13:07:19 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffitest.c (main): Fixed character constants.
+	(main): Emit warning for structure test 3 failure on Sun.
+
+	* Makefile.am (VPATH): Fixed VPATH def'n so automake won't
+	strip it out. 
+	Moved distdir hack from libffi to automake. 
+	(ffitest): Added missing -c for $(COMPILE) (change in automake).
+	* Makefile.in: Rebuilt.
+	
+Tue Oct 15 13:08:20 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* Makefile.am: Added "make lint" production. 
+	* Makefile.in: Rebuilt.
+
+	* prep_cif.c (STACK_ARG_SIZE): Improved STACK_ARG_SIZE macro.
+  	Clean up based on LCLint output. Added funny /*@...@*/ comments to
+ 	annotate source.
+
+	* ffitest.c, debug.c: Cleaned up code.
+
+Mon Oct 14 12:26:56 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffitest.c: Changes based on interface changes.
+
+	* prep_cif.c (ffi_prep_cif): Cleaned up interface based on
+	feedback from Jim Blandy.
+
+Fri Oct 11 15:53:18 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffitest.c: Reordered tests while porting to sparc.
+	Made changes to handle lame structure passing for sparc.
+	Removed calls to fflush().
+
+	* prep_cif.c (ffi_prep_cif): Added special case for sparc
+	aggregate type arguments.
+
+Thu Oct 10 09:56:51 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffitest.c (main): Added structure passing/returning tests.
+
+	* prep_cif.c (ffi_prep_cif): Perform proper initialization
+	of structure return types if needed.
+	(initialize_aggregate): Bug fix
+
+Wed Oct  9 16:04:20 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* types.c: Added special definitions for x86 (double doesn't
+	need double word alignment).
+
+	* ffitest.c: Added many tests
+
+Tue Oct  8 09:19:22 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* prep_cif.c (ffi_prep_cif): Fixed assertion.
+
+	* debug.c (ffi_assert): Must return a non void now.
+
+	* Makefile.am: Added test production.
+	* Makefile: Rebuilt.
+
+	* ffitest.c (main): Created. 
+
+	* types.c: Created. Stripped common code out of */ffi.c.
+
+	* prep_cif.c: Added missing stdlib.h include.
+
+	* debug.c (ffi_type_test): Used "a" to eliminate compiler
+	warnings in non-debug builds. Included ffi_common.h.
+
+Mon Oct  7 15:36:42 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* Makefile.am: Added a rule for .s -> .o
+	This is required by the SGI compiler.
+	* Makefile: Rebuilt.
+
+Fri Oct  4 09:51:08 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* prep_cif.c (initialize_aggregate): Moved abi specification
+	to ffi_prep_cif().
+
+Thu Oct  3 15:37:37 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* prep_cif.c (ffi_prep_cif): Changed values from void* to void**.
+	(initialize_aggregate): Fixed aggregate type initialization.
+
+	* Makefile.am (EXTRA_DIST): Added support code for "make dist".
+	* Makefile.in: Regenerated.
+
+Wed Oct  2 11:41:57 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* debug.c, prep_cif: Created.
+
+	* Makefile.am: Added debug.o and prep_cif.o to OBJ.
+	* Makefile.in: Regenerated.
+
+	* Makefile.am (INCLUDES): Added missing -I../include
+	* Makefile.in: Regenerated.
+
+Tue Oct  1 17:11:51 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* error.c, Makefile.am: Created.
+	* Makefile.in: Generated.
+
+--- libffi/src/x86 --------------------------------------------------------
+
+Sun Oct  4 16:27:17 1998  Anthony Green  <green@cygnus.com>
+
+	* sysv.S (retlongdouble): Fixed long long return value support.
+	* ffi.c (ffi_prep_cif_machdep): Ditto.
+
+Wed May 13 04:30:33 1998  Anthony Green  <green@raft.ppp.tsoft.net>
+
+	* ffi.c (ffi_prep_cif_machdep): Fixed long double return value
+	support.
+
+Wed Apr 15 08:43:20 1998  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.c (ffi_prep_args): small struct support was missing.
+
+Thu May  8 16:53:58 1997  Anthony Green  <green@hoser.cygnus.com>
+
+	* objects.mak: Removed.
+
+Mon Dec  2 15:12:58 1996  Tom Tromey  <tromey@cygnus.com>
+
+	* sysv.S: Use .balign, for a.out Linux boxes.
+
+Tue Oct 15 13:06:50 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.c: Clean up based on LCLint output.
+	Added funny /*@...@*/ comments to annotate source.
+
+Fri Oct 11 16:43:38 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.c (ffi_call): Added assertion for bad ABIs.
+
+Wed Oct  9 13:57:27 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* sysv.S (retdouble): Fixed double return problems.
+
+	* ffi.c	(ffi_call): Corrected fn arg definition.
+	(ffi_prep_cif_machdep): Fixed double return problems
+
+Tue Oct  8 12:12:49 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.c: Moved ffi_type definitions to types.c.
+	(ffi_prep_args): Fixed type promotion bug.
+
+Mon Oct  7 15:53:06 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.c (FFI_*_TYPEDEF): Removed redundant ';'
+
+Fri Oct  4 09:54:53 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.c (ffi_call): Removed FFI_ABI arg, and swapped
+	remaining args.
+
+Wed Oct  2 10:07:05 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.c, sysv.S, objects.mak: Created.
+	(ffi_prep_cif): cif->rvalue no longer initialized to NULL.
+	(ffi_prep_cif_machdep): Moved machine independent cif processing
+	to src/prep_cif.c. Introduced ffi_prep_cif_machdep().
+
+--- libffi/src/mips -------------------------------------------------------
+
+Tue Feb 17 17:18:07 1998  Anthony Green  <green@hoser.cygnus.com>
+
+	* o32.S: Fixed typo in comment.
+
+	* ffi.c (ffi_prep_cif_machdep): Fixed argument processing.
+
+Thu May  8 16:53:58 1997  Anthony Green  <green@hoser.cygnus.com>
+
+	* o32.s, n32.s: Wrappers for SGI tool support.
+
+	* objects.mak: Removed.
+
+Tue Oct 29 14:37:45 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.c (ffi_prep_args): Changed int z to size_t z.
+
+Tue Oct 15 13:17:25 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* n32.S: Fixed bad stack munging. 
+
+	* ffi.c: Moved prototypes for ffi_call_?32() to here from
+	ffi_mips.h because extended_cif is not defined in ffi_mips.h.
+
+Mon Oct 14 12:42:02 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.c: Interface changes based on feedback from Jim Blandy.
+
+Thu Oct 10 11:22:16 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* n32.S, ffi.c: Lots of changes to support passing and 
+	returning structures with the n32 calling convention.
+
+	* n32.S: Fixed fn pointer bug.
+
+	* ffi.c (ffi_prep_cif_machdep): Fix for o32 structure
+	return values.
+	(ffi_prep_args): Fixed n32 structure passing when structures
+	partially fit in registers.
+
+Wed Oct  9 13:49:25 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* objects.mak: Added n32.o.
+
+	* n32.S: Created.
+
+	* ffi.c (ffi_prep_args): Added magic to support proper
+	n32 processing.
+
+Tue Oct  8 10:37:35 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.c: Moved ffi_type definitions to types.c.
+	(ffi_prep_args): Fixed type promotion bug.
+
+	* o32.S: This code is only built for o32 compiles.
+	A lot of the #define cruft has moved to ffi_mips.h.
+
+	* ffi.c (ffi_prep_cif_machdep): Fixed arg flags. Second arg
+	is only processed if the first is either a float or double.
+
+Mon Oct  7 15:33:59 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* o32.S: Modified to compile under each of o32, n32 and n64.
+
+	* ffi.c (FFI_*_TYPEDEF): Removed redundant ';'
+
+Fri Oct  4 09:53:25 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.c (ffi_call): Removed FFI_ABI arg, and swapped
+	remaining args.
+
+Wed Oct  2 17:41:22 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* o32.S: Removed crufty definitions.
+
+Wed Oct  2 12:53:42 1996  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.c (ffi_prep_cif): cif->rvalue no longer initialized to NULL.
+	(ffi_prep_cif_machdep): Moved all machine independent cif processing
+	to src/prep_cif.c. Introduced ffi_prep_cif_machdep. Return types
+	of FFI_TYPE_STRUCT are no different than FFI_TYPE_INT.
+
+Tue Oct  1 17:11:02 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.c, o32.S, object.mak: Created
+	
+--- libffi/src/sparc ------------------------------------------------------
+
+Tue Feb 24 16:33:18 1998  Anthony Green  <green@hoser.cygnus.com>
+
+	* ffi.c (ffi_prep_args): Added long double support.
+
+Thu May  8 16:53:58 1997  Anthony Green  <green@hoser.cygnus.com>
+
+	* objects.mak: Removed.
+
+Thu May  1 16:07:56 1997  Anthony Green  <green@hoser.cygnus.com>
+
+	* v8.S: Fixed minor portability problem reported by 
+	Russ McManus <mcmanr@eq.gs.com>.
+
+Tue Nov 26 14:12:43 1996  Anthony Green  <green@csk3.cygnus.com>
+
+	* v8.S: Used STACKFRAME define elsewhere. 
+
+	* ffi.c (ffi_prep_args): Zero out space when USING_PURIFY
+	is set.
+	(ffi_prep_cif_machdep): Allocate the correct stack frame 
+	space for functions with < 6 args.
+
+Tue Oct 29 15:08:55 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.c (ffi_prep_args): int z is now size_t z.
+
+Mon Oct 14 13:31:24 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* v8.S (ffi_call_V8): Gordon rewrites this again. It looks
+	great now.
+
+	* ffi.c (ffi_call): The comment about hijacked registers
+	is no longer valid after gordoni hacked v8.S.
+
+        * v8.S (ffi_call_V8): Rewrote with gordoni. Much simpler.
+	
+	* v8.S, ffi.c: ffi_call() had changed to accept more than
+	two args, so v8.S had to change (because it hijacks incoming
+	arg registers).
+
+	* ffi.c: Interface changes based on feedback from Jim Blandy.
+
+Thu Oct 10 17:48:16 1996  Anthony Green  <green@rtl.cygnus.com>
+
+	* ffi.c, v8.S, objects.mak: Created.
+	
+
diff --git a/third_party/gofrontend/libffi/LICENSE b/third_party/gofrontend/libffi/LICENSE
new file mode 100644
index 0000000..aa60342
--- /dev/null
+++ b/third_party/gofrontend/libffi/LICENSE
@@ -0,0 +1,21 @@
+libffi - Copyright (c) 1996-2012  Anthony Green, Red Hat, Inc and others.
+See source files for details.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+``Software''), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/third_party/gofrontend/libffi/Makefile.am b/third_party/gofrontend/libffi/Makefile.am
new file mode 100644
index 0000000..645dc12
--- /dev/null
+++ b/third_party/gofrontend/libffi/Makefile.am
@@ -0,0 +1,253 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign subdir-objects
+ACLOCAL_AMFLAGS = -I .. -I ../config
+
+SUBDIRS = include testsuite man
+
+EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host	\
+	 src/aarch64/ffi.c src/aarch64/ffitarget.h			\
+	 src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h		\
+	 src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h		\
+	 src/avr32/ffi.c src/avr32/sysv.S src/avr32/ffitarget.h		\
+	 src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h		\
+	 src/ia64/ffi.c src/ia64/ffitarget.h src/ia64/ia64_flags.h	\
+	 src/ia64/unix.S src/mips/ffi.c src/mips/n32.S src/mips/o32.S	\
+	 src/mips/ffitarget.h src/m32r/ffi.c src/m32r/sysv.S		\
+	 src/m32r/ffitarget.h src/m68k/ffi.c src/m68k/sysv.S		\
+	 src/m68k/ffitarget.h						\
+	src/powerpc/ffi.c src/powerpc/ffi_powerpc.h			\
+	src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c		\
+	src/powerpc/sysv.S src/powerpc/linux64.S			\
+	src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S		\
+	src/powerpc/asm.h src/powerpc/aix.S src/powerpc/darwin.S	\
+	src/powerpc/aix_closure.S src/powerpc/darwin_closure.S		\
+	src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h		\
+	src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h		\
+	src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h src/sh64/ffi.c	\
+	src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S		\
+	src/sparc/v9.S src/sparc/ffitarget.h src/sparc/ffi.c		\
+	src/x86/darwin64.S src/x86/ffi.c src/x86/sysv.S			\
+	src/x86/win32.S src/x86/darwin.S src/x86/win64.S		\
+	src/x86/freebsd.S src/x86/ffi64.c src/x86/unix64.S		\
+	src/x86/ffitarget.h src/pa/ffitarget.h src/pa/ffi.c		\
+	src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c src/bfin/ffi.c	\
+	src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S		\
+	src/frv/ffitarget.h src/dlmalloc.c src/tile/ffi.c		\
+	src/tile/ffitarget.h src/tile/tile.S libtool-version		\
+	 ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4		\
+	 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4			\
+	 m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh	\
+	generate-ios-source-and-headers.py				\
+	 generate-osx-source-and-headers.py				\
+	 libffi.xcodeproj/project.pbxproj src/arm/trampoline.S
+
+# Automake Documentation:
+# If your package has Texinfo files in many directories, you can use the
+# variable TEXINFO_TEX to tell Automake where to find the canonical
+# `texinfo.tex' for your package. The value of this variable should be
+# the relative path from the current `Makefile.am' to `texinfo.tex'.
+TEXINFO_TEX   = ../gcc/doc/include/texinfo.tex
+
+# Defines info, dvi, pdf and html targets
+MAKEINFOFLAGS = -I $(srcdir)/../gcc/doc/include
+info_TEXINFOS = doc/libffi.texi
+
+# AM_CONDITIONAL on configure option --generated-files-in-srcdir
+if GENINSRC
+STAMP_GENINSRC = stamp-geninsrc
+else
+STAMP_GENINSRC =
+endif
+
+# AM_CONDITIONAL on configure check ACX_CHECK_PROG_VER([MAKEINFO])
+if BUILD_INFO
+STAMP_BUILD_INFO = stamp-build-info
+else
+STAMP_BUILD_INFO =
+endif
+
+all-local: $(STAMP_GENINSRC)
+
+stamp-geninsrc: doc/libffi.info
+	cp -p $(top_builddir)/doc/libffi.info $(srcdir)/doc/libffi.info
+	@touch $@
+
+doc/libffi.info: $(STAMP_BUILD_INFO)
+
+stamp-build-info: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp)
+	$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)/doc -o doc/libffi.info $(srcdir)/doc/libffi.texi
+	@touch $@
+
+
+CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO) doc/libffi.info
+MAINTAINERCLEANFILES = $(srcdir)/doc/libffi.info
+
+## ################################################################
+
+##
+## This section is for make and multilib madness.
+##
+
+# Work around what appears to be a GNU make bug handling MAKEFLAGS
+# values defined in terms of make variables, as is the case for CC and
+# friends when we are called from the top level Makefile.
+AM_MAKEFLAGS = \
+	"AR_FLAGS=$(AR_FLAGS)" \
+	"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+	"CFLAGS=$(CFLAGS)" \
+	"CXXFLAGS=$(CXXFLAGS)" \
+	"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+	"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+	"INSTALL=$(INSTALL)" \
+	"INSTALL_DATA=$(INSTALL_DATA)" \
+	"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+	"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+	"JC1FLAGS=$(JC1FLAGS)" \
+	"LDFLAGS=$(LDFLAGS)" \
+	"LIBCFLAGS=$(LIBCFLAGS)" \
+	"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+	"MAKE=$(MAKE)" \
+	"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+	"PICFLAG=$(PICFLAG)" \
+	"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+	"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+	"SHELL=$(SHELL)" \
+	"exec_prefix=$(exec_prefix)" \
+	"infodir=$(infodir)" \
+	"libdir=$(libdir)" \
+	"mandir=$(mandir)" \
+	"prefix=$(prefix)" \
+	"AR=$(AR)" \
+	"AS=$(AS)" \
+	"CC=$(CC)" \
+	"CXX=$(CXX)" \
+	"LD=$(LD)" \
+	"NM=$(NM)" \
+	"RANLIB=$(RANLIB)" \
+	"DESTDIR=$(DESTDIR)"
+
+# Subdir rules rely on $(FLAGS_TO_PASS)
+FLAGS_TO_PASS = $(AM_MAKEFLAGS)
+
+MAKEOVERRIDES=
+
+toolexeclib_LTLIBRARIES = libffi.la
+noinst_LTLIBRARIES = libffi_convenience.la
+
+libffi_la_SOURCES = src/prep_cif.c src/types.c \
+		src/raw_api.c src/java_raw_api.c src/closures.c
+
+nodist_libffi_la_SOURCES =
+
+if FFI_DEBUG
+nodist_libffi_la_SOURCES += src/debug.c
+endif
+
+if MIPS
+nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
+endif
+if BFIN
+nodist_libffi_la_SOURCES += src/bfin/ffi.c src/bfin/sysv.S
+endif
+if X86
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
+endif
+if X86_FREEBSD
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/freebsd.S
+endif
+if X86_WIN32
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.S
+endif
+if X86_WIN64
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win64.S
+endif
+if X86_DARWIN
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
+endif
+if SPARC
+nodist_libffi_la_SOURCES += src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
+endif
+if ALPHA
+nodist_libffi_la_SOURCES += src/alpha/ffi.c src/alpha/osf.S
+endif
+if IA64
+nodist_libffi_la_SOURCES += src/ia64/ffi.c src/ia64/unix.S
+endif
+if M32R
+nodist_libffi_la_SOURCES += src/m32r/sysv.S src/m32r/ffi.c
+endif
+if M68K
+nodist_libffi_la_SOURCES += src/m68k/ffi.c src/m68k/sysv.S
+endif
+if POWERPC
+nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
+endif
+if POWERPC_AIX
+nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
+endif
+if POWERPC_DARWIN
+nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
+endif
+if POWERPC_FREEBSD
+nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
+endif
+if AARCH64
+nodist_libffi_la_SOURCES += src/aarch64/sysv.S src/aarch64/ffi.c
+endif
+if ARM
+nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
+if FFI_EXEC_TRAMPOLINE_TABLE
+nodist_libffi_la_SOURCES += src/arm/trampoline.S
+endif
+endif
+if AVR32
+nodist_libffi_la_SOURCES += src/avr32/sysv.S src/avr32/ffi.c
+endif
+if LIBFFI_CRIS
+nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c
+endif
+if FRV
+nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c
+endif
+if S390
+nodist_libffi_la_SOURCES += src/s390/sysv.S src/s390/ffi.c
+endif
+if X86_64
+nodist_libffi_la_SOURCES += src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
+endif
+if SH
+nodist_libffi_la_SOURCES += src/sh/sysv.S src/sh/ffi.c
+endif
+if SH64
+nodist_libffi_la_SOURCES += src/sh64/sysv.S src/sh64/ffi.c
+endif
+if PA_LINUX
+nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c
+endif
+if PA_HPUX
+nodist_libffi_la_SOURCES += src/pa/hpux32.S src/pa/ffi.c
+endif
+if TILE
+nodist_libffi_la_SOURCES += src/tile/tile.S src/tile/ffi.c
+endif
+
+libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
+nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
+
+AM_CFLAGS = -Wall -g -fexceptions
+
+LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
+
+libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
+
+AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
+AM_CCASFLAGS = $(AM_CPPFLAGS)
+
+# Multilib support.  Automake should provide these on its own.
+all-recursive: all-multi
+install-recursive: install-multi
+mostlyclean-recursive: mostlyclean-multi
+clean-recursive: clean-multi
+distclean-recursive: distclean-multi
+maintainer-clean-recursive: maintainer-clean-multi
diff --git a/third_party/gofrontend/libffi/Makefile.in b/third_party/gofrontend/libffi/Makefile.in
new file mode 100644
index 0000000..2a04e0b
--- /dev/null
+++ b/third_party/gofrontend/libffi/Makefile.in
@@ -0,0 +1,1706 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@FFI_DEBUG_TRUE@am__append_1 = src/debug.c
+@MIPS_TRUE@am__append_2 = src/mips/ffi.c src/mips/o32.S src/mips/n32.S
+@BFIN_TRUE@am__append_3 = src/bfin/ffi.c src/bfin/sysv.S
+@X86_TRUE@am__append_4 = src/x86/ffi.c src/x86/sysv.S
+@X86_FREEBSD_TRUE@am__append_5 = src/x86/ffi.c src/x86/freebsd.S
+@X86_WIN32_TRUE@am__append_6 = src/x86/ffi.c src/x86/win32.S
+@X86_WIN64_TRUE@am__append_7 = src/x86/ffi.c src/x86/win64.S
+@X86_DARWIN_TRUE@am__append_8 = src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
+@SPARC_TRUE@am__append_9 = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
+@ALPHA_TRUE@am__append_10 = src/alpha/ffi.c src/alpha/osf.S
+@IA64_TRUE@am__append_11 = src/ia64/ffi.c src/ia64/unix.S
+@M32R_TRUE@am__append_12 = src/m32r/sysv.S src/m32r/ffi.c
+@M68K_TRUE@am__append_13 = src/m68k/ffi.c src/m68k/sysv.S
+@POWERPC_TRUE@am__append_14 = src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
+@POWERPC_AIX_TRUE@am__append_15 = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
+@POWERPC_DARWIN_TRUE@am__append_16 = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
+@POWERPC_FREEBSD_TRUE@am__append_17 = src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
+@AARCH64_TRUE@am__append_18 = src/aarch64/sysv.S src/aarch64/ffi.c
+@ARM_TRUE@am__append_19 = src/arm/sysv.S src/arm/ffi.c
+@ARM_TRUE@@FFI_EXEC_TRAMPOLINE_TABLE_TRUE@am__append_20 = src/arm/trampoline.S
+@AVR32_TRUE@am__append_21 = src/avr32/sysv.S src/avr32/ffi.c
+@LIBFFI_CRIS_TRUE@am__append_22 = src/cris/sysv.S src/cris/ffi.c
+@FRV_TRUE@am__append_23 = src/frv/eabi.S src/frv/ffi.c
+@S390_TRUE@am__append_24 = src/s390/sysv.S src/s390/ffi.c
+@X86_64_TRUE@am__append_25 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
+@SH_TRUE@am__append_26 = src/sh/sysv.S src/sh/ffi.c
+@SH64_TRUE@am__append_27 = src/sh64/sysv.S src/sh64/ffi.c
+@PA_LINUX_TRUE@am__append_28 = src/pa/linux.S src/pa/ffi.c
+@PA_HPUX_TRUE@am__append_29 = src/pa/hpux32.S src/pa/ffi.c
+@TILE_TRUE@am__append_30 = src/tile/tile.S src/tile/ffi.c
+subdir = .
+DIST_COMMON = README ChangeLog $(srcdir)/Makefile.in \
+	$(srcdir)/Makefile.am $(top_srcdir)/configure \
+	$(am__configure_deps) $(srcdir)/fficonfig.h.in \
+	$(srcdir)/../mkinstalldirs $(srcdir)/../depcomp mdate-sh \
+	$(srcdir)/doc/version.texi $(srcdir)/doc/stamp-vti
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+	$(top_srcdir)/../config/asmcfi.m4 \
+	$(top_srcdir)/../config/depstand.m4 \
+	$(top_srcdir)/../config/lead-dot.m4 \
+	$(top_srcdir)/../config/multi.m4 \
+	$(top_srcdir)/../config/override.m4 \
+	$(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \
+	$(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
+	$(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = fficonfig.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES)
+libffi_la_LIBADD =
+am__dirstamp = $(am__leading_dot)dirstamp
+am_libffi_la_OBJECTS = src/prep_cif.lo src/types.lo src/raw_api.lo \
+	src/java_raw_api.lo src/closures.lo
+@FFI_DEBUG_TRUE@am__objects_1 = src/debug.lo
+@MIPS_TRUE@am__objects_2 = src/mips/ffi.lo src/mips/o32.lo \
+@MIPS_TRUE@	src/mips/n32.lo
+@BFIN_TRUE@am__objects_3 = src/bfin/ffi.lo src/bfin/sysv.lo
+@X86_TRUE@am__objects_4 = src/x86/ffi.lo src/x86/sysv.lo
+@X86_FREEBSD_TRUE@am__objects_5 = src/x86/ffi.lo src/x86/freebsd.lo
+@X86_WIN32_TRUE@am__objects_6 = src/x86/ffi.lo src/x86/win32.lo
+@X86_WIN64_TRUE@am__objects_7 = src/x86/ffi.lo src/x86/win64.lo
+@X86_DARWIN_TRUE@am__objects_8 = src/x86/ffi.lo src/x86/darwin.lo \
+@X86_DARWIN_TRUE@	src/x86/ffi64.lo src/x86/darwin64.lo
+@SPARC_TRUE@am__objects_9 = src/sparc/ffi.lo src/sparc/v8.lo \
+@SPARC_TRUE@	src/sparc/v9.lo
+@ALPHA_TRUE@am__objects_10 = src/alpha/ffi.lo src/alpha/osf.lo
+@IA64_TRUE@am__objects_11 = src/ia64/ffi.lo src/ia64/unix.lo
+@M32R_TRUE@am__objects_12 = src/m32r/sysv.lo src/m32r/ffi.lo
+@M68K_TRUE@am__objects_13 = src/m68k/ffi.lo src/m68k/sysv.lo
+@POWERPC_TRUE@am__objects_14 = src/powerpc/ffi.lo \
+@POWERPC_TRUE@	src/powerpc/ffi_sysv.lo \
+@POWERPC_TRUE@	src/powerpc/ffi_linux64.lo src/powerpc/sysv.lo \
+@POWERPC_TRUE@	src/powerpc/ppc_closure.lo \
+@POWERPC_TRUE@	src/powerpc/linux64.lo \
+@POWERPC_TRUE@	src/powerpc/linux64_closure.lo
+@POWERPC_AIX_TRUE@am__objects_15 = src/powerpc/ffi_darwin.lo \
+@POWERPC_AIX_TRUE@	src/powerpc/aix.lo \
+@POWERPC_AIX_TRUE@	src/powerpc/aix_closure.lo
+@POWERPC_DARWIN_TRUE@am__objects_16 = src/powerpc/ffi_darwin.lo \
+@POWERPC_DARWIN_TRUE@	src/powerpc/darwin.lo \
+@POWERPC_DARWIN_TRUE@	src/powerpc/darwin_closure.lo
+@POWERPC_FREEBSD_TRUE@am__objects_17 = src/powerpc/ffi.lo \
+@POWERPC_FREEBSD_TRUE@	src/powerpc/ffi_sysv.lo \
+@POWERPC_FREEBSD_TRUE@	src/powerpc/sysv.lo \
+@POWERPC_FREEBSD_TRUE@	src/powerpc/ppc_closure.lo
+@AARCH64_TRUE@am__objects_18 = src/aarch64/sysv.lo src/aarch64/ffi.lo
+@ARM_TRUE@am__objects_19 = src/arm/sysv.lo src/arm/ffi.lo
+@ARM_TRUE@@FFI_EXEC_TRAMPOLINE_TABLE_TRUE@am__objects_20 = src/arm/trampoline.lo
+@AVR32_TRUE@am__objects_21 = src/avr32/sysv.lo src/avr32/ffi.lo
+@LIBFFI_CRIS_TRUE@am__objects_22 = src/cris/sysv.lo src/cris/ffi.lo
+@FRV_TRUE@am__objects_23 = src/frv/eabi.lo src/frv/ffi.lo
+@S390_TRUE@am__objects_24 = src/s390/sysv.lo src/s390/ffi.lo
+@X86_64_TRUE@am__objects_25 = src/x86/ffi64.lo src/x86/unix64.lo \
+@X86_64_TRUE@	src/x86/ffi.lo src/x86/sysv.lo
+@SH_TRUE@am__objects_26 = src/sh/sysv.lo src/sh/ffi.lo
+@SH64_TRUE@am__objects_27 = src/sh64/sysv.lo src/sh64/ffi.lo
+@PA_LINUX_TRUE@am__objects_28 = src/pa/linux.lo src/pa/ffi.lo
+@PA_HPUX_TRUE@am__objects_29 = src/pa/hpux32.lo src/pa/ffi.lo
+@TILE_TRUE@am__objects_30 = src/tile/tile.lo src/tile/ffi.lo
+nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
+	$(am__objects_3) $(am__objects_4) $(am__objects_5) \
+	$(am__objects_6) $(am__objects_7) $(am__objects_8) \
+	$(am__objects_9) $(am__objects_10) $(am__objects_11) \
+	$(am__objects_12) $(am__objects_13) $(am__objects_14) \
+	$(am__objects_15) $(am__objects_16) $(am__objects_17) \
+	$(am__objects_18) $(am__objects_19) $(am__objects_20) \
+	$(am__objects_21) $(am__objects_22) $(am__objects_23) \
+	$(am__objects_24) $(am__objects_25) $(am__objects_26) \
+	$(am__objects_27) $(am__objects_28) $(am__objects_29) \
+	$(am__objects_30)
+libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) \
+	$(nodist_libffi_la_OBJECTS)
+libffi_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(libffi_la_LDFLAGS) $(LDFLAGS) -o $@
+libffi_convenience_la_LIBADD =
+am__objects_31 = src/prep_cif.lo src/types.lo src/raw_api.lo \
+	src/java_raw_api.lo src/closures.lo
+am_libffi_convenience_la_OBJECTS = $(am__objects_31)
+am__objects_32 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
+	$(am__objects_4) $(am__objects_5) $(am__objects_6) \
+	$(am__objects_7) $(am__objects_8) $(am__objects_9) \
+	$(am__objects_10) $(am__objects_11) $(am__objects_12) \
+	$(am__objects_13) $(am__objects_14) $(am__objects_15) \
+	$(am__objects_16) $(am__objects_17) $(am__objects_18) \
+	$(am__objects_19) $(am__objects_20) $(am__objects_21) \
+	$(am__objects_22) $(am__objects_23) $(am__objects_24) \
+	$(am__objects_25) $(am__objects_26) $(am__objects_27) \
+	$(am__objects_28) $(am__objects_29) $(am__objects_30)
+nodist_libffi_convenience_la_OBJECTS = $(am__objects_32)
+libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \
+	$(nodist_libffi_convenience_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/../depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS)
+LTCPPASCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS)
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libffi_la_SOURCES) $(nodist_libffi_la_SOURCES) \
+	$(libffi_convenience_la_SOURCES) \
+	$(nodist_libffi_convenience_la_SOURCES)
+MULTISRCTOP = 
+MULTIBUILDTOP = 
+MULTIDIRS = 
+MULTISUBDIR = 
+MULTIDO = true
+MULTICLEAN = true
+INFO_DEPS = doc/libffi.info
+am__TEXINFO_TEX_DIR = $(srcdir)/../gcc/doc/include
+DVIS = doc/libffi.dvi
+PDFS = doc/libffi.pdf
+PSS = doc/libffi.ps
+HTMLS = doc/libffi.html
+TEXINFOS = doc/libffi.texi
+TEXI2DVI = texi2dvi
+TEXI2PDF = $(TEXI2DVI) --pdf --batch
+MAKEINFOHTML = $(MAKEINFO) --html
+AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS)
+DVIPS = dvips
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+	$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_LTLDFLAGS = @AM_LTLDFLAGS@
+AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
+HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARGET = @TARGET@
+TARGETDIR = @TARGETDIR@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign subdir-objects
+ACLOCAL_AMFLAGS = -I .. -I ../config
+SUBDIRS = include testsuite man
+EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host	\
+	 src/aarch64/ffi.c src/aarch64/ffitarget.h			\
+	 src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h		\
+	 src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h		\
+	 src/avr32/ffi.c src/avr32/sysv.S src/avr32/ffitarget.h		\
+	 src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h		\
+	 src/ia64/ffi.c src/ia64/ffitarget.h src/ia64/ia64_flags.h	\
+	 src/ia64/unix.S src/mips/ffi.c src/mips/n32.S src/mips/o32.S	\
+	 src/mips/ffitarget.h src/m32r/ffi.c src/m32r/sysv.S		\
+	 src/m32r/ffitarget.h src/m68k/ffi.c src/m68k/sysv.S		\
+	 src/m68k/ffitarget.h						\
+	src/powerpc/ffi.c src/powerpc/ffi_powerpc.h			\
+	src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c		\
+	src/powerpc/sysv.S src/powerpc/linux64.S			\
+	src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S		\
+	src/powerpc/asm.h src/powerpc/aix.S src/powerpc/darwin.S	\
+	src/powerpc/aix_closure.S src/powerpc/darwin_closure.S		\
+	src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h		\
+	src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h		\
+	src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h src/sh64/ffi.c	\
+	src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S		\
+	src/sparc/v9.S src/sparc/ffitarget.h src/sparc/ffi.c		\
+	src/x86/darwin64.S src/x86/ffi.c src/x86/sysv.S			\
+	src/x86/win32.S src/x86/darwin.S src/x86/win64.S		\
+	src/x86/freebsd.S src/x86/ffi64.c src/x86/unix64.S		\
+	src/x86/ffitarget.h src/pa/ffitarget.h src/pa/ffi.c		\
+	src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c src/bfin/ffi.c	\
+	src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S		\
+	src/frv/ffitarget.h src/dlmalloc.c src/tile/ffi.c		\
+	src/tile/ffitarget.h src/tile/tile.S libtool-version		\
+	 ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4		\
+	 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4			\
+	 m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh	\
+	generate-ios-source-and-headers.py				\
+	 generate-osx-source-and-headers.py				\
+	 libffi.xcodeproj/project.pbxproj src/arm/trampoline.S
+
+
+# Automake Documentation:
+# If your package has Texinfo files in many directories, you can use the
+# variable TEXINFO_TEX to tell Automake where to find the canonical
+# `texinfo.tex' for your package. The value of this variable should be
+# the relative path from the current `Makefile.am' to `texinfo.tex'.
+TEXINFO_TEX = ../gcc/doc/include/texinfo.tex
+
+# Defines info, dvi, pdf and html targets
+MAKEINFOFLAGS = -I $(srcdir)/../gcc/doc/include
+info_TEXINFOS = doc/libffi.texi
+@GENINSRC_FALSE@STAMP_GENINSRC = 
+
+# AM_CONDITIONAL on configure option --generated-files-in-srcdir
+@GENINSRC_TRUE@STAMP_GENINSRC = stamp-geninsrc
+@BUILD_INFO_FALSE@STAMP_BUILD_INFO = 
+
+# AM_CONDITIONAL on configure check ACX_CHECK_PROG_VER([MAKEINFO])
+@BUILD_INFO_TRUE@STAMP_BUILD_INFO = stamp-build-info
+CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO) doc/libffi.info
+MAINTAINERCLEANFILES = $(srcdir)/doc/libffi.info
+
+# Work around what appears to be a GNU make bug handling MAKEFLAGS
+# values defined in terms of make variables, as is the case for CC and
+# friends when we are called from the top level Makefile.
+AM_MAKEFLAGS = \
+	"AR_FLAGS=$(AR_FLAGS)" \
+	"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+	"CFLAGS=$(CFLAGS)" \
+	"CXXFLAGS=$(CXXFLAGS)" \
+	"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+	"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+	"INSTALL=$(INSTALL)" \
+	"INSTALL_DATA=$(INSTALL_DATA)" \
+	"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+	"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+	"JC1FLAGS=$(JC1FLAGS)" \
+	"LDFLAGS=$(LDFLAGS)" \
+	"LIBCFLAGS=$(LIBCFLAGS)" \
+	"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+	"MAKE=$(MAKE)" \
+	"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+	"PICFLAG=$(PICFLAG)" \
+	"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+	"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+	"SHELL=$(SHELL)" \
+	"exec_prefix=$(exec_prefix)" \
+	"infodir=$(infodir)" \
+	"libdir=$(libdir)" \
+	"mandir=$(mandir)" \
+	"prefix=$(prefix)" \
+	"AR=$(AR)" \
+	"AS=$(AS)" \
+	"CC=$(CC)" \
+	"CXX=$(CXX)" \
+	"LD=$(LD)" \
+	"NM=$(NM)" \
+	"RANLIB=$(RANLIB)" \
+	"DESTDIR=$(DESTDIR)"
+
+
+# Subdir rules rely on $(FLAGS_TO_PASS)
+FLAGS_TO_PASS = $(AM_MAKEFLAGS)
+MAKEOVERRIDES = 
+toolexeclib_LTLIBRARIES = libffi.la
+noinst_LTLIBRARIES = libffi_convenience.la
+libffi_la_SOURCES = src/prep_cif.c src/types.c \
+		src/raw_api.c src/java_raw_api.c src/closures.c
+
+nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \
+	$(am__append_3) $(am__append_4) $(am__append_5) \
+	$(am__append_6) $(am__append_7) $(am__append_8) \
+	$(am__append_9) $(am__append_10) $(am__append_11) \
+	$(am__append_12) $(am__append_13) $(am__append_14) \
+	$(am__append_15) $(am__append_16) $(am__append_17) \
+	$(am__append_18) $(am__append_19) $(am__append_20) \
+	$(am__append_21) $(am__append_22) $(am__append_23) \
+	$(am__append_24) $(am__append_25) $(am__append_26) \
+	$(am__append_27) $(am__append_28) $(am__append_29) \
+	$(am__append_30)
+libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
+nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
+AM_CFLAGS = -Wall -g -fexceptions
+LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
+libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
+AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
+AM_CCASFLAGS = $(AM_CPPFLAGS)
+all: fficonfig.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .S .c .dvi .lo .o .obj .ps
+am--refresh:
+	@:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	$(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+fficonfig.h: stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+	else :; fi
+
+stamp-h1: $(srcdir)/fficonfig.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status fficonfig.h
+$(srcdir)/fficonfig.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f fficonfig.h stamp-h1
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)"
+	@list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(toolexeclibdir)"; \
+	}
+
+uninstall-toolexeclibLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$f"; \
+	done
+
+clean-toolexeclibLTLIBRARIES:
+	-test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES)
+	@list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+src/$(am__dirstamp):
+	@$(MKDIR_P) src
+	@: > src/$(am__dirstamp)
+src/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/$(DEPDIR)
+	@: > src/$(DEPDIR)/$(am__dirstamp)
+src/prep_cif.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/types.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/java_raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/closures.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/debug.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/mips/$(am__dirstamp):
+	@$(MKDIR_P) src/mips
+	@: > src/mips/$(am__dirstamp)
+src/mips/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/mips/$(DEPDIR)
+	@: > src/mips/$(DEPDIR)/$(am__dirstamp)
+src/mips/ffi.lo: src/mips/$(am__dirstamp) \
+	src/mips/$(DEPDIR)/$(am__dirstamp)
+src/mips/o32.lo: src/mips/$(am__dirstamp) \
+	src/mips/$(DEPDIR)/$(am__dirstamp)
+src/mips/n32.lo: src/mips/$(am__dirstamp) \
+	src/mips/$(DEPDIR)/$(am__dirstamp)
+src/bfin/$(am__dirstamp):
+	@$(MKDIR_P) src/bfin
+	@: > src/bfin/$(am__dirstamp)
+src/bfin/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/bfin/$(DEPDIR)
+	@: > src/bfin/$(DEPDIR)/$(am__dirstamp)
+src/bfin/ffi.lo: src/bfin/$(am__dirstamp) \
+	src/bfin/$(DEPDIR)/$(am__dirstamp)
+src/bfin/sysv.lo: src/bfin/$(am__dirstamp) \
+	src/bfin/$(DEPDIR)/$(am__dirstamp)
+src/x86/$(am__dirstamp):
+	@$(MKDIR_P) src/x86
+	@: > src/x86/$(am__dirstamp)
+src/x86/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/x86/$(DEPDIR)
+	@: > src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/ffi.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/sysv.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/freebsd.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/win32.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/win64.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/darwin.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/ffi64.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/darwin64.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/sparc/$(am__dirstamp):
+	@$(MKDIR_P) src/sparc
+	@: > src/sparc/$(am__dirstamp)
+src/sparc/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/sparc/$(DEPDIR)
+	@: > src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/sparc/ffi.lo: src/sparc/$(am__dirstamp) \
+	src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/sparc/v8.lo: src/sparc/$(am__dirstamp) \
+	src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/sparc/v9.lo: src/sparc/$(am__dirstamp) \
+	src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/alpha/$(am__dirstamp):
+	@$(MKDIR_P) src/alpha
+	@: > src/alpha/$(am__dirstamp)
+src/alpha/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/alpha/$(DEPDIR)
+	@: > src/alpha/$(DEPDIR)/$(am__dirstamp)
+src/alpha/ffi.lo: src/alpha/$(am__dirstamp) \
+	src/alpha/$(DEPDIR)/$(am__dirstamp)
+src/alpha/osf.lo: src/alpha/$(am__dirstamp) \
+	src/alpha/$(DEPDIR)/$(am__dirstamp)
+src/ia64/$(am__dirstamp):
+	@$(MKDIR_P) src/ia64
+	@: > src/ia64/$(am__dirstamp)
+src/ia64/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/ia64/$(DEPDIR)
+	@: > src/ia64/$(DEPDIR)/$(am__dirstamp)
+src/ia64/ffi.lo: src/ia64/$(am__dirstamp) \
+	src/ia64/$(DEPDIR)/$(am__dirstamp)
+src/ia64/unix.lo: src/ia64/$(am__dirstamp) \
+	src/ia64/$(DEPDIR)/$(am__dirstamp)
+src/m32r/$(am__dirstamp):
+	@$(MKDIR_P) src/m32r
+	@: > src/m32r/$(am__dirstamp)
+src/m32r/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/m32r/$(DEPDIR)
+	@: > src/m32r/$(DEPDIR)/$(am__dirstamp)
+src/m32r/sysv.lo: src/m32r/$(am__dirstamp) \
+	src/m32r/$(DEPDIR)/$(am__dirstamp)
+src/m32r/ffi.lo: src/m32r/$(am__dirstamp) \
+	src/m32r/$(DEPDIR)/$(am__dirstamp)
+src/m68k/$(am__dirstamp):
+	@$(MKDIR_P) src/m68k
+	@: > src/m68k/$(am__dirstamp)
+src/m68k/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/m68k/$(DEPDIR)
+	@: > src/m68k/$(DEPDIR)/$(am__dirstamp)
+src/m68k/ffi.lo: src/m68k/$(am__dirstamp) \
+	src/m68k/$(DEPDIR)/$(am__dirstamp)
+src/m68k/sysv.lo: src/m68k/$(am__dirstamp) \
+	src/m68k/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/$(am__dirstamp):
+	@$(MKDIR_P) src/powerpc
+	@: > src/powerpc/$(am__dirstamp)
+src/powerpc/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/powerpc/$(DEPDIR)
+	@: > src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/ffi.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/ffi_sysv.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/ffi_linux64.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/sysv.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/ppc_closure.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/linux64.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/linux64_closure.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/ffi_darwin.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/aix.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/aix_closure.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/darwin.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/darwin_closure.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/aarch64/$(am__dirstamp):
+	@$(MKDIR_P) src/aarch64
+	@: > src/aarch64/$(am__dirstamp)
+src/aarch64/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/aarch64/$(DEPDIR)
+	@: > src/aarch64/$(DEPDIR)/$(am__dirstamp)
+src/aarch64/sysv.lo: src/aarch64/$(am__dirstamp) \
+	src/aarch64/$(DEPDIR)/$(am__dirstamp)
+src/aarch64/ffi.lo: src/aarch64/$(am__dirstamp) \
+	src/aarch64/$(DEPDIR)/$(am__dirstamp)
+src/arm/$(am__dirstamp):
+	@$(MKDIR_P) src/arm
+	@: > src/arm/$(am__dirstamp)
+src/arm/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/arm/$(DEPDIR)
+	@: > src/arm/$(DEPDIR)/$(am__dirstamp)
+src/arm/sysv.lo: src/arm/$(am__dirstamp) \
+	src/arm/$(DEPDIR)/$(am__dirstamp)
+src/arm/ffi.lo: src/arm/$(am__dirstamp) \
+	src/arm/$(DEPDIR)/$(am__dirstamp)
+src/arm/trampoline.lo: src/arm/$(am__dirstamp) \
+	src/arm/$(DEPDIR)/$(am__dirstamp)
+src/avr32/$(am__dirstamp):
+	@$(MKDIR_P) src/avr32
+	@: > src/avr32/$(am__dirstamp)
+src/avr32/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/avr32/$(DEPDIR)
+	@: > src/avr32/$(DEPDIR)/$(am__dirstamp)
+src/avr32/sysv.lo: src/avr32/$(am__dirstamp) \
+	src/avr32/$(DEPDIR)/$(am__dirstamp)
+src/avr32/ffi.lo: src/avr32/$(am__dirstamp) \
+	src/avr32/$(DEPDIR)/$(am__dirstamp)
+src/cris/$(am__dirstamp):
+	@$(MKDIR_P) src/cris
+	@: > src/cris/$(am__dirstamp)
+src/cris/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/cris/$(DEPDIR)
+	@: > src/cris/$(DEPDIR)/$(am__dirstamp)
+src/cris/sysv.lo: src/cris/$(am__dirstamp) \
+	src/cris/$(DEPDIR)/$(am__dirstamp)
+src/cris/ffi.lo: src/cris/$(am__dirstamp) \
+	src/cris/$(DEPDIR)/$(am__dirstamp)
+src/frv/$(am__dirstamp):
+	@$(MKDIR_P) src/frv
+	@: > src/frv/$(am__dirstamp)
+src/frv/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/frv/$(DEPDIR)
+	@: > src/frv/$(DEPDIR)/$(am__dirstamp)
+src/frv/eabi.lo: src/frv/$(am__dirstamp) \
+	src/frv/$(DEPDIR)/$(am__dirstamp)
+src/frv/ffi.lo: src/frv/$(am__dirstamp) \
+	src/frv/$(DEPDIR)/$(am__dirstamp)
+src/s390/$(am__dirstamp):
+	@$(MKDIR_P) src/s390
+	@: > src/s390/$(am__dirstamp)
+src/s390/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/s390/$(DEPDIR)
+	@: > src/s390/$(DEPDIR)/$(am__dirstamp)
+src/s390/sysv.lo: src/s390/$(am__dirstamp) \
+	src/s390/$(DEPDIR)/$(am__dirstamp)
+src/s390/ffi.lo: src/s390/$(am__dirstamp) \
+	src/s390/$(DEPDIR)/$(am__dirstamp)
+src/x86/unix64.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/sh/$(am__dirstamp):
+	@$(MKDIR_P) src/sh
+	@: > src/sh/$(am__dirstamp)
+src/sh/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/sh/$(DEPDIR)
+	@: > src/sh/$(DEPDIR)/$(am__dirstamp)
+src/sh/sysv.lo: src/sh/$(am__dirstamp) \
+	src/sh/$(DEPDIR)/$(am__dirstamp)
+src/sh/ffi.lo: src/sh/$(am__dirstamp) src/sh/$(DEPDIR)/$(am__dirstamp)
+src/sh64/$(am__dirstamp):
+	@$(MKDIR_P) src/sh64
+	@: > src/sh64/$(am__dirstamp)
+src/sh64/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/sh64/$(DEPDIR)
+	@: > src/sh64/$(DEPDIR)/$(am__dirstamp)
+src/sh64/sysv.lo: src/sh64/$(am__dirstamp) \
+	src/sh64/$(DEPDIR)/$(am__dirstamp)
+src/sh64/ffi.lo: src/sh64/$(am__dirstamp) \
+	src/sh64/$(DEPDIR)/$(am__dirstamp)
+src/pa/$(am__dirstamp):
+	@$(MKDIR_P) src/pa
+	@: > src/pa/$(am__dirstamp)
+src/pa/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/pa/$(DEPDIR)
+	@: > src/pa/$(DEPDIR)/$(am__dirstamp)
+src/pa/linux.lo: src/pa/$(am__dirstamp) \
+	src/pa/$(DEPDIR)/$(am__dirstamp)
+src/pa/ffi.lo: src/pa/$(am__dirstamp) src/pa/$(DEPDIR)/$(am__dirstamp)
+src/pa/hpux32.lo: src/pa/$(am__dirstamp) \
+	src/pa/$(DEPDIR)/$(am__dirstamp)
+src/tile/$(am__dirstamp):
+	@$(MKDIR_P) src/tile
+	@: > src/tile/$(am__dirstamp)
+src/tile/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/tile/$(DEPDIR)
+	@: > src/tile/$(DEPDIR)/$(am__dirstamp)
+src/tile/tile.lo: src/tile/$(am__dirstamp) \
+	src/tile/$(DEPDIR)/$(am__dirstamp)
+src/tile/ffi.lo: src/tile/$(am__dirstamp) \
+	src/tile/$(DEPDIR)/$(am__dirstamp)
+libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES) 
+	$(libffi_la_LINK) -rpath $(toolexeclibdir) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS)
+libffi_convenience.la: $(libffi_convenience_la_OBJECTS) $(libffi_convenience_la_DEPENDENCIES) 
+	$(LINK)  $(libffi_convenience_la_OBJECTS) $(libffi_convenience_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+	-rm -f src/aarch64/ffi.$(OBJEXT)
+	-rm -f src/aarch64/ffi.lo
+	-rm -f src/aarch64/sysv.$(OBJEXT)
+	-rm -f src/aarch64/sysv.lo
+	-rm -f src/alpha/ffi.$(OBJEXT)
+	-rm -f src/alpha/ffi.lo
+	-rm -f src/alpha/osf.$(OBJEXT)
+	-rm -f src/alpha/osf.lo
+	-rm -f src/arm/ffi.$(OBJEXT)
+	-rm -f src/arm/ffi.lo
+	-rm -f src/arm/sysv.$(OBJEXT)
+	-rm -f src/arm/sysv.lo
+	-rm -f src/arm/trampoline.$(OBJEXT)
+	-rm -f src/arm/trampoline.lo
+	-rm -f src/avr32/ffi.$(OBJEXT)
+	-rm -f src/avr32/ffi.lo
+	-rm -f src/avr32/sysv.$(OBJEXT)
+	-rm -f src/avr32/sysv.lo
+	-rm -f src/bfin/ffi.$(OBJEXT)
+	-rm -f src/bfin/ffi.lo
+	-rm -f src/bfin/sysv.$(OBJEXT)
+	-rm -f src/bfin/sysv.lo
+	-rm -f src/closures.$(OBJEXT)
+	-rm -f src/closures.lo
+	-rm -f src/cris/ffi.$(OBJEXT)
+	-rm -f src/cris/ffi.lo
+	-rm -f src/cris/sysv.$(OBJEXT)
+	-rm -f src/cris/sysv.lo
+	-rm -f src/debug.$(OBJEXT)
+	-rm -f src/debug.lo
+	-rm -f src/frv/eabi.$(OBJEXT)
+	-rm -f src/frv/eabi.lo
+	-rm -f src/frv/ffi.$(OBJEXT)
+	-rm -f src/frv/ffi.lo
+	-rm -f src/ia64/ffi.$(OBJEXT)
+	-rm -f src/ia64/ffi.lo
+	-rm -f src/ia64/unix.$(OBJEXT)
+	-rm -f src/ia64/unix.lo
+	-rm -f src/java_raw_api.$(OBJEXT)
+	-rm -f src/java_raw_api.lo
+	-rm -f src/m32r/ffi.$(OBJEXT)
+	-rm -f src/m32r/ffi.lo
+	-rm -f src/m32r/sysv.$(OBJEXT)
+	-rm -f src/m32r/sysv.lo
+	-rm -f src/m68k/ffi.$(OBJEXT)
+	-rm -f src/m68k/ffi.lo
+	-rm -f src/m68k/sysv.$(OBJEXT)
+	-rm -f src/m68k/sysv.lo
+	-rm -f src/mips/ffi.$(OBJEXT)
+	-rm -f src/mips/ffi.lo
+	-rm -f src/mips/n32.$(OBJEXT)
+	-rm -f src/mips/n32.lo
+	-rm -f src/mips/o32.$(OBJEXT)
+	-rm -f src/mips/o32.lo
+	-rm -f src/pa/ffi.$(OBJEXT)
+	-rm -f src/pa/ffi.lo
+	-rm -f src/pa/hpux32.$(OBJEXT)
+	-rm -f src/pa/hpux32.lo
+	-rm -f src/pa/linux.$(OBJEXT)
+	-rm -f src/pa/linux.lo
+	-rm -f src/powerpc/aix.$(OBJEXT)
+	-rm -f src/powerpc/aix.lo
+	-rm -f src/powerpc/aix_closure.$(OBJEXT)
+	-rm -f src/powerpc/aix_closure.lo
+	-rm -f src/powerpc/darwin.$(OBJEXT)
+	-rm -f src/powerpc/darwin.lo
+	-rm -f src/powerpc/darwin_closure.$(OBJEXT)
+	-rm -f src/powerpc/darwin_closure.lo
+	-rm -f src/powerpc/ffi.$(OBJEXT)
+	-rm -f src/powerpc/ffi.lo
+	-rm -f src/powerpc/ffi_darwin.$(OBJEXT)
+	-rm -f src/powerpc/ffi_darwin.lo
+	-rm -f src/powerpc/ffi_linux64.$(OBJEXT)
+	-rm -f src/powerpc/ffi_linux64.lo
+	-rm -f src/powerpc/ffi_sysv.$(OBJEXT)
+	-rm -f src/powerpc/ffi_sysv.lo
+	-rm -f src/powerpc/linux64.$(OBJEXT)
+	-rm -f src/powerpc/linux64.lo
+	-rm -f src/powerpc/linux64_closure.$(OBJEXT)
+	-rm -f src/powerpc/linux64_closure.lo
+	-rm -f src/powerpc/ppc_closure.$(OBJEXT)
+	-rm -f src/powerpc/ppc_closure.lo
+	-rm -f src/powerpc/sysv.$(OBJEXT)
+	-rm -f src/powerpc/sysv.lo
+	-rm -f src/prep_cif.$(OBJEXT)
+	-rm -f src/prep_cif.lo
+	-rm -f src/raw_api.$(OBJEXT)
+	-rm -f src/raw_api.lo
+	-rm -f src/s390/ffi.$(OBJEXT)
+	-rm -f src/s390/ffi.lo
+	-rm -f src/s390/sysv.$(OBJEXT)
+	-rm -f src/s390/sysv.lo
+	-rm -f src/sh/ffi.$(OBJEXT)
+	-rm -f src/sh/ffi.lo
+	-rm -f src/sh/sysv.$(OBJEXT)
+	-rm -f src/sh/sysv.lo
+	-rm -f src/sh64/ffi.$(OBJEXT)
+	-rm -f src/sh64/ffi.lo
+	-rm -f src/sh64/sysv.$(OBJEXT)
+	-rm -f src/sh64/sysv.lo
+	-rm -f src/sparc/ffi.$(OBJEXT)
+	-rm -f src/sparc/ffi.lo
+	-rm -f src/sparc/v8.$(OBJEXT)
+	-rm -f src/sparc/v8.lo
+	-rm -f src/sparc/v9.$(OBJEXT)
+	-rm -f src/sparc/v9.lo
+	-rm -f src/tile/ffi.$(OBJEXT)
+	-rm -f src/tile/ffi.lo
+	-rm -f src/tile/tile.$(OBJEXT)
+	-rm -f src/tile/tile.lo
+	-rm -f src/types.$(OBJEXT)
+	-rm -f src/types.lo
+	-rm -f src/x86/darwin.$(OBJEXT)
+	-rm -f src/x86/darwin.lo
+	-rm -f src/x86/darwin64.$(OBJEXT)
+	-rm -f src/x86/darwin64.lo
+	-rm -f src/x86/ffi.$(OBJEXT)
+	-rm -f src/x86/ffi.lo
+	-rm -f src/x86/ffi64.$(OBJEXT)
+	-rm -f src/x86/ffi64.lo
+	-rm -f src/x86/freebsd.$(OBJEXT)
+	-rm -f src/x86/freebsd.lo
+	-rm -f src/x86/sysv.$(OBJEXT)
+	-rm -f src/x86/sysv.lo
+	-rm -f src/x86/unix64.$(OBJEXT)
+	-rm -f src/x86/unix64.lo
+	-rm -f src/x86/win32.$(OBJEXT)
+	-rm -f src/x86/win32.lo
+	-rm -f src/x86/win64.$(OBJEXT)
+	-rm -f src/x86/win64.lo
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/closures.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/java_raw_api.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/prep_cif.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/raw_api.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/types.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/osf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/trampoline.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/avr32/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/avr32/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/bfin/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/bfin/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/frv/$(DEPDIR)/eabi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/frv/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/ia64/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/ia64/$(DEPDIR)/unix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/m32r/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/m32r/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/m68k/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/m68k/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/n32.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/o32.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/hpux32.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/linux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/aix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/aix_closure.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/darwin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/darwin_closure.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ffi_darwin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ffi_linux64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ffi_sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/linux64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/linux64_closure.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ppc_closure.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/s390/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/s390/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sh/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sh/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sh64/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sh64/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/v8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/v9.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/tile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/freebsd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/unix64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win32.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win64.Plo@am__quote@
+
+.S.o:
+@am__fastdepCCAS_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCCAS_TRUE@	$(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCCAS_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@	DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCCAS_FALSE@	$(CPPASCOMPILE) -c -o $@ $<
+
+.S.obj:
+@am__fastdepCCAS_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCCAS_TRUE@	$(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCCAS_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@	DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCCAS_FALSE@	$(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.S.lo:
+@am__fastdepCCAS_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCCAS_TRUE@	$(LTCPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCCAS_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@	DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCCAS_FALSE@	$(LTCPPASCOMPILE) -c -o $@ $<
+
+.c.o:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+	-rm -rf src/.libs src/_libs
+	-rm -rf src/aarch64/.libs src/aarch64/_libs
+	-rm -rf src/alpha/.libs src/alpha/_libs
+	-rm -rf src/arm/.libs src/arm/_libs
+	-rm -rf src/avr32/.libs src/avr32/_libs
+	-rm -rf src/bfin/.libs src/bfin/_libs
+	-rm -rf src/cris/.libs src/cris/_libs
+	-rm -rf src/frv/.libs src/frv/_libs
+	-rm -rf src/ia64/.libs src/ia64/_libs
+	-rm -rf src/m32r/.libs src/m32r/_libs
+	-rm -rf src/m68k/.libs src/m68k/_libs
+	-rm -rf src/mips/.libs src/mips/_libs
+	-rm -rf src/pa/.libs src/pa/_libs
+	-rm -rf src/powerpc/.libs src/powerpc/_libs
+	-rm -rf src/s390/.libs src/s390/_libs
+	-rm -rf src/sh/.libs src/sh/_libs
+	-rm -rf src/sh64/.libs src/sh64/_libs
+	-rm -rf src/sparc/.libs src/sparc/_libs
+	-rm -rf src/tile/.libs src/tile/_libs
+	-rm -rf src/x86/.libs src/x86/_libs
+
+distclean-libtool:
+	-rm -f libtool config.lt
+
+# GNU Make needs to see an explicit $(MAKE) variable in the command it
+# runs to enable its job server during parallel builds.  Hence the
+# comments below.
+all-multi:
+	$(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE)
+install-multi:
+	$(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE)
+
+mostlyclean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE)
+clean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE)
+distclean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE)
+maintainer-clean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE)
+doc/$(am__dirstamp):
+	@$(MKDIR_P) doc
+	@: > doc/$(am__dirstamp)
+
+doc/libffi.dvi: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp)
+	TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
+	MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I doc -I $(srcdir)/doc' \
+	$(TEXI2DVI) -o $@ `test -f 'doc/libffi.texi' || echo '$(srcdir)/'`doc/libffi.texi
+
+doc/libffi.pdf: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp)
+	TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
+	MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I doc -I $(srcdir)/doc' \
+	$(TEXI2PDF) -o $@ `test -f 'doc/libffi.texi' || echo '$(srcdir)/'`doc/libffi.texi
+
+doc/libffi.html: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp)
+	rm -rf $(@:.html=.htp)
+	if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I doc -I $(srcdir)/doc \
+	 -o $(@:.html=.htp) `test -f 'doc/libffi.texi' || echo '$(srcdir)/'`doc/libffi.texi; \
+	then \
+	  rm -rf $@; \
+	  if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \
+	    mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \
+	else \
+	  if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \
+	    rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \
+	  exit 1; \
+	fi
+$(srcdir)/doc/version.texi: @MAINTAINER_MODE_TRUE@ $(srcdir)/doc/stamp-vti
+$(srcdir)/doc/stamp-vti: doc/libffi.texi $(top_srcdir)/configure
+	test -f doc/$(am__dirstamp) || $(MAKE) $(AM_MAKEFLAGS) doc/$(am__dirstamp)
+	@(dir=.; test -f ./doc/libffi.texi || dir=$(srcdir); \
+	set `$(SHELL) $(srcdir)/mdate-sh $$dir/doc/libffi.texi`; \
+	echo "@set UPDATED $$1 $$2 $$3"; \
+	echo "@set UPDATED-MONTH $$2 $$3"; \
+	echo "@set EDITION $(VERSION)"; \
+	echo "@set VERSION $(VERSION)") > vti.tmp
+	@cmp -s vti.tmp $(srcdir)/doc/version.texi \
+	  || (echo "Updating $(srcdir)/doc/version.texi"; \
+	      cp vti.tmp $(srcdir)/doc/version.texi)
+	-@rm -f vti.tmp
+	@cp $(srcdir)/doc/version.texi $@
+
+mostlyclean-vti:
+	-rm -f vti.tmp
+
+maintainer-clean-vti:
+@MAINTAINER_MODE_TRUE@	-rm -f $(srcdir)/doc/stamp-vti $(srcdir)/doc/version.texi
+.dvi.ps:
+	TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
+	$(DVIPS) -o $@ $<
+
+uninstall-dvi-am:
+	@$(NORMAL_UNINSTALL)
+	@list='$(DVIS)'; test -n "$(dvidir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(dvidir)/$$f"; \
+	done
+
+uninstall-html-am:
+	@$(NORMAL_UNINSTALL)
+	@list='$(HTMLS)'; test -n "$(htmldir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \
+	  rm -rf "$(DESTDIR)$(htmldir)/$$f"; \
+	done
+
+uninstall-info-am:
+	@$(PRE_UNINSTALL)
+	@if test -d '$(DESTDIR)$(infodir)' && \
+	    (install-info --version && \
+	     install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \
+	  list='$(INFO_DEPS)'; \
+	  for file in $$list; do \
+	    relfile=`echo "$$file" | sed 's|^.*/||'`; \
+	    echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \
+	    if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \
+	    then :; else test ! -f "$(DESTDIR)$(infodir)/$$relfile" || exit 1; fi; \
+	  done; \
+	else :; fi
+	@$(NORMAL_UNINSTALL)
+	@list='$(INFO_DEPS)'; \
+	for file in $$list; do \
+	  relfile=`echo "$$file" | sed 's|^.*/||'`; \
+	  relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \
+	  (if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \
+	     echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \
+	     rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \
+	   else :; fi); \
+	done
+
+uninstall-pdf-am:
+	@$(NORMAL_UNINSTALL)
+	@list='$(PDFS)'; test -n "$(pdfdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(pdfdir)/$$f"; \
+	done
+
+uninstall-ps-am:
+	@$(NORMAL_UNINSTALL)
+	@list='$(PSS)'; test -n "$(psdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(psdir)/$$f"; \
+	done
+
+dist-info: $(INFO_DEPS)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	list='$(INFO_DEPS)'; \
+	for base in $$list; do \
+	  case $$base in \
+	    $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \
+	  esac; \
+	  if test -f $$base; then d=.; else d=$(srcdir); fi; \
+	  base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \
+	  for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \
+	    if test -f $$file; then \
+	      relfile=`expr "$$file" : "$$d/\(.*\)"`; \
+	      test -f "$(distdir)/$$relfile" || \
+		cp -p $$file "$(distdir)/$$relfile"; \
+	    else :; fi; \
+	  done; \
+	done
+
+mostlyclean-aminfo:
+	-rm -rf libffi.aux libffi.cp libffi.cps libffi.fn libffi.ky libffi.log \
+	  libffi.pg libffi.tmp libffi.toc libffi.tp libffi.vr
+
+clean-aminfo:
+	-test -z "doc/libffi.dvi doc/libffi.pdf doc/libffi.ps doc/libffi.html" \
+	|| rm -rf doc/libffi.dvi doc/libffi.pdf doc/libffi.ps doc/libffi.html
+
+maintainer-clean-aminfo:
+	@list='$(INFO_DEPS)'; for i in $$list; do \
+	  i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \
+	  echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \
+	  rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \
+	done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) fficonfig.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS) fficonfig.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) fficonfig.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS) fficonfig.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(INFO_DEPS) $(LTLIBRARIES) all-multi fficonfig.h \
+		all-local
+installdirs: installdirs-recursive
+installdirs-am:
+	for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+	-rm -f doc/$(am__dirstamp)
+	-rm -f src/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/$(am__dirstamp)
+	-rm -f src/aarch64/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/aarch64/$(am__dirstamp)
+	-rm -f src/alpha/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/alpha/$(am__dirstamp)
+	-rm -f src/arm/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/arm/$(am__dirstamp)
+	-rm -f src/avr32/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/avr32/$(am__dirstamp)
+	-rm -f src/bfin/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/bfin/$(am__dirstamp)
+	-rm -f src/cris/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/cris/$(am__dirstamp)
+	-rm -f src/frv/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/frv/$(am__dirstamp)
+	-rm -f src/ia64/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/ia64/$(am__dirstamp)
+	-rm -f src/m32r/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/m32r/$(am__dirstamp)
+	-rm -f src/m68k/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/m68k/$(am__dirstamp)
+	-rm -f src/mips/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/mips/$(am__dirstamp)
+	-rm -f src/pa/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/pa/$(am__dirstamp)
+	-rm -f src/powerpc/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/powerpc/$(am__dirstamp)
+	-rm -f src/s390/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/s390/$(am__dirstamp)
+	-rm -f src/sh/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/sh/$(am__dirstamp)
+	-rm -f src/sh64/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/sh64/$(am__dirstamp)
+	-rm -f src/sparc/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/sparc/$(am__dirstamp)
+	-rm -f src/tile/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/tile/$(am__dirstamp)
+	-rm -f src/x86/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/x86/$(am__dirstamp)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-multi clean-recursive
+
+clean-am: clean-aminfo clean-generic clean-libtool \
+	clean-noinstLTLIBRARIES clean-toolexeclibLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-multi distclean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/x86/$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-hdr distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am: $(DVIS)
+
+html: html-recursive
+
+html-am: $(HTMLS)
+
+info: info-recursive
+
+info-am: $(INFO_DEPS)
+
+install-data-am: install-info-am
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am: $(DVIS)
+	@$(NORMAL_INSTALL)
+	test -z "$(dvidir)" || $(MKDIR_P) "$(DESTDIR)$(dvidir)"
+	@list='$(DVIS)'; test -n "$(dvidir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dvidir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(dvidir)" || exit $$?; \
+	done
+install-exec-am: install-multi install-toolexeclibLTLIBRARIES
+
+install-html: install-html-recursive
+
+install-html-am: $(HTMLS)
+	@$(NORMAL_INSTALL)
+	test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)"
+	@list='$(HTMLS)'; list2=; test -n "$(htmldir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  $(am__strip_dir) \
+	  if test -d "$$d$$p"; then \
+	    echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \
+	    $(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
+	    echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \
+	    $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f" || exit $$?; \
+	  else \
+	    list2="$$list2 $$d$$p"; \
+	  fi; \
+	done; \
+	test -z "$$list2" || { echo "$$list2" | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \
+	done; }
+install-info: install-info-recursive
+
+install-info-am: $(INFO_DEPS)
+	@$(NORMAL_INSTALL)
+	test -z "$(infodir)" || $(MKDIR_P) "$(DESTDIR)$(infodir)"
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \
+	for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	  esac; \
+	  if test -f $$file; then d=.; else d=$(srcdir); fi; \
+	  file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \
+	  for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \
+	               $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \
+	    if test -f $$ifile; then \
+	      echo "$$ifile"; \
+	    else : ; fi; \
+	  done; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(infodir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(infodir)" || exit $$?; done
+	@$(POST_INSTALL)
+	@if (install-info --version && \
+	     install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \
+	  list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \
+	  for file in $$list; do \
+	    relfile=`echo "$$file" | sed 's|^.*/||'`; \
+	    echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\
+	    install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\
+	  done; \
+	else : ; fi
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am: $(PDFS)
+	@$(NORMAL_INSTALL)
+	test -z "$(pdfdir)" || $(MKDIR_P) "$(DESTDIR)$(pdfdir)"
+	@list='$(PDFS)'; test -n "$(pdfdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pdfdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(pdfdir)" || exit $$?; done
+install-ps: install-ps-recursive
+
+install-ps-am: $(PSS)
+	@$(NORMAL_INSTALL)
+	test -z "$(psdir)" || $(MKDIR_P) "$(DESTDIR)$(psdir)"
+	@list='$(PSS)'; test -n "$(psdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(psdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(psdir)" || exit $$?; done
+installcheck-am:
+
+maintainer-clean: maintainer-clean-multi maintainer-clean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/x86/$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-aminfo \
+	maintainer-clean-generic maintainer-clean-vti
+
+mostlyclean: mostlyclean-multi mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-aminfo mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool mostlyclean-vti
+
+pdf: pdf-recursive
+
+pdf-am: $(PDFS)
+
+ps: ps-recursive
+
+ps-am: $(PSS)
+
+uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
+	uninstall-pdf-am uninstall-ps-am \
+	uninstall-toolexeclibLTLIBRARIES
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all all-multi \
+	clean-multi ctags-recursive distclean-multi install-am \
+	install-multi install-strip maintainer-clean-multi \
+	mostlyclean-multi tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am all-local all-multi am--refresh check check-am \
+	clean clean-aminfo clean-generic clean-libtool clean-multi \
+	clean-noinstLTLIBRARIES clean-toolexeclibLTLIBRARIES ctags \
+	ctags-recursive dist-info distclean distclean-compile \
+	distclean-generic distclean-hdr distclean-libtool \
+	distclean-multi distclean-tags dvi dvi-am html html-am info \
+	info-am install install-am install-data install-data-am \
+	install-dvi install-dvi-am install-exec install-exec-am \
+	install-html install-html-am install-info install-info-am \
+	install-man install-multi install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip \
+	install-toolexeclibLTLIBRARIES installcheck installcheck-am \
+	installdirs installdirs-am maintainer-clean \
+	maintainer-clean-aminfo maintainer-clean-generic \
+	maintainer-clean-multi maintainer-clean-vti mostlyclean \
+	mostlyclean-aminfo mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool mostlyclean-multi mostlyclean-vti pdf \
+	pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+	uninstall-dvi-am uninstall-html-am uninstall-info-am \
+	uninstall-pdf-am uninstall-ps-am \
+	uninstall-toolexeclibLTLIBRARIES
+
+
+all-local: $(STAMP_GENINSRC)
+
+stamp-geninsrc: doc/libffi.info
+	cp -p $(top_builddir)/doc/libffi.info $(srcdir)/doc/libffi.info
+	@touch $@
+
+doc/libffi.info: $(STAMP_BUILD_INFO)
+
+stamp-build-info: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp)
+	$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)/doc -o doc/libffi.info $(srcdir)/doc/libffi.texi
+	@touch $@
+
+# Multilib support.  Automake should provide these on its own.
+all-recursive: all-multi
+install-recursive: install-multi
+mostlyclean-recursive: mostlyclean-multi
+clean-recursive: clean-multi
+distclean-recursive: distclean-multi
+maintainer-clean-recursive: maintainer-clean-multi
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/third_party/gofrontend/libffi/README b/third_party/gofrontend/libffi/README
new file mode 100644
index 0000000..a0fb717
--- /dev/null
+++ b/third_party/gofrontend/libffi/README
@@ -0,0 +1,370 @@
+Status
+======
+
+libffi-3.0.12 was released on XXXXXXX.  Check the libffi web page for
+updates: <URL:http://sourceware.org/libffi/>.
+
+
+What is libffi?
+===============
+
+Compilers for high level languages generate code that follow certain
+conventions. These conventions are necessary, in part, for separate
+compilation to work. One such convention is the "calling
+convention". The "calling convention" is essentially a set of
+assumptions made by the compiler about where function arguments will
+be found on entry to a function. A "calling convention" also specifies
+where the return value for a function is found.
+
+Some programs may not know at the time of compilation what arguments
+are to be passed to a function. For instance, an interpreter may be
+told at run-time about the number and types of arguments used to call
+a given function. Libffi can be used in such programs to provide a
+bridge from the interpreter program to compiled code.
+
+The libffi library provides a portable, high level programming
+interface to various calling conventions. This allows a programmer to
+call any function specified by a call interface description at run
+time.  
+
+FFI stands for Foreign Function Interface.  A foreign function
+interface is the popular name for the interface that allows code
+written in one language to call code written in another language. The
+libffi library really only provides the lowest, machine dependent
+layer of a fully featured foreign function interface. A layer must
+exist above libffi that handles type conversions for values passed
+between the two languages.
+
+
+Supported Platforms
+===================
+
+Libffi has been ported to many different platforms.
+For specific configuration details and testing status, please
+refer to the wiki page here:
+
+ http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
+
+At the time of release, the following basic configurations have been
+tested:
+
+|-----------------+------------------|
+| Architecture    | Operating System |
+|-----------------+------------------|
+| AArch64         | Linux            |
+| Alpha           | Linux            |
+| Alpha           | Tru64            |
+| ARM             | Linux            |
+| ARM             | iOS              |
+| AVR32           | Linux            |
+| Blackfin        | uClinux          |
+| HPPA            | HPUX             |
+| IA-64           | Linux            |
+| M68K            | FreeMiNT         |
+| M68K            | RTEMS            |
+| MIPS            | IRIX             |
+| MIPS            | Linux            |
+| MIPS            | RTEMS            |
+| MIPS64          | Linux            |
+| PowerPC         | AMIGA            |
+| PowerPC         | Linux            |
+| PowerPC         | Mac OSX          |
+| PowerPC         | FreeBSD          |
+| PowerPC64       | Linux            |
+| S390            | Linux            |
+| S390X           | Linux            |
+| SPARC           | Linux            |
+| SPARC           | Solaris          |
+| SPARC64         | Linux            |
+| SPARC64         | FreeBSD          |
+| TILE-Gx/TILEPro | Linux            |
+| X86             | FreeBSD          |
+| X86             | Interix          |
+| X86             | kFreeBSD         |
+| X86             | Linux            |
+| X86             | Mac OSX          |
+| X86             | OpenBSD          |
+| X86             | OS/2             |
+| X86             | Solaris          |
+| X86             | Windows/Cygwin   |
+| X86             | Windows/MingW    |
+| X86-64          | FreeBSD          |
+| X86-64          | Linux            |
+| X86-64          | Linux/x32        |
+| X86-64          | OpenBSD          |
+| X86-64          | Windows/MingW    |
+|-----------------+------------------|
+
+Please send additional platform test results to
+libffi-discuss@sourceware.org and feel free to update the wiki page
+above.
+
+Installing libffi
+=================
+
+First you must configure the distribution for your particular
+system. Go to the directory you wish to build libffi in and run the
+"configure" program found in the root directory of the libffi source
+distribution.
+
+You may want to tell configure where to install the libffi library and
+header files. To do that, use the --prefix configure switch.  Libffi
+will install under /usr/local by default. 
+
+If you want to enable extra run-time debugging checks use the the
+--enable-debug configure switch. This is useful when your program dies
+mysteriously while using libffi. 
+
+Another useful configure switch is --enable-purify-safety. Using this
+will add some extra code which will suppress certain warnings when you
+are using Purify with libffi. Only use this switch when using 
+Purify, as it will slow down the library.
+
+It's also possible to build libffi on Windows platforms with
+Microsoft's Visual C++ compiler.  In this case, use the msvcc.sh
+wrapper script during configuration like so:
+
+path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
+
+For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
+You may also need to specify --build appropriately. When building with MSVC
+under a MingW environment, you may need to remove the line in configure
+that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
+present in MingW, and is not required when using MingW-style paths.)
+
+For iOS builds, the 'libffi.xcodeproj' Xcode project is available.
+
+Configure has many other options. Use "configure --help" to see them all.
+
+Once configure has finished, type "make". Note that you must be using
+GNU make.  You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
+
+To ensure that libffi is working as advertised, type "make check".
+This will require that you have DejaGNU installed.
+
+To install the library and header files, type "make install".
+
+
+History
+=======
+
+See the ChangeLog files for details.
+
+3.0.12 XXX-XX-XX
+	Add Blackfin support.
+	Add TILE-Gx/TILEPro support.
+	Add AArch64 support.
+	Add support for PaX enabled kernels with MPROTECT.
+
+3.0.11 Apr-11-12
+        Lots of build fixes.
+	Add Amiga newer MacOS support.
+	Add support for variadic functions (ffi_prep_cif_var).
+	Add Linux/x32 support.
+	Add thiscall, fastcall and MSVC cdecl support on Windows.
+	Add Amiga and newer MacOS support.
+	Add m68k FreeMiNT support.
+	Integration with iOS' xcode build tools.
+	Fix Octeon and MC68881 support.
+	Fix code pessimizations.
+	Lots of build fixes.
+
+3.0.10 Aug-23-11
+        Add support for Apple's iOS.
+	Add support for ARM VFP ABI.
+        Add RTEMS support for MIPS and M68K.
+	Fix instruction cache clearing problems on
+	  ARM and SPARC.
+	Fix the N64 build on mips-sgi-irix6.5.
+	Enable builds with Microsoft's compiler.
+	Enable x86 builds with Oracle's Solaris compiler.
+	Fix support for calling code compiled with Oracle's Sparc
+	  Solaris compiler.
+	Testsuite fixes for Tru64 Unix.
+	Additional platform support.
+
+3.0.9 Dec-31-09
+        Add AVR32 and win64 ports.  Add ARM softfp support.
+	Many fixes for AIX, Solaris, HP-UX, *BSD.
+	Several PowerPC and x86-64 bug fixes.
+	Build DLL for windows.
+
+3.0.8 Dec-19-08
+        Add *BSD, BeOS, and PA-Linux support.
+
+3.0.7 Nov-11-08
+        Fix for ppc FreeBSD.
+	(thanks to Andreas Tobler)
+
+3.0.6 Jul-17-08
+        Fix for closures on sh.
+	Mark the sh/sh64 stack as non-executable.
+	(both thanks to Kaz Kojima)
+
+3.0.5 Apr-3-08
+        Fix libffi.pc file.
+	Fix #define ARM for IcedTea users.
+	Fix x86 closure bug.
+
+3.0.4 Feb-24-08
+        Fix x86 OpenBSD configury.
+
+3.0.3 Feb-22-08
+        Enable x86 OpenBSD thanks to Thomas Heller, and
+	x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
+	Clean up test instruction in README.
+
+3.0.2 Feb-21-08
+        Improved x86 FreeBSD support.
+	Thanks to Björn König.
+
+3.0.1 Feb-15-08
+        Fix instruction cache flushing bug on MIPS.
+	Thanks to David Daney.
+
+3.0.0 Feb-15-08
+        Many changes, mostly thanks to the GCC project.
+	Cygnus Solutions is now Red Hat.
+
+  [10 years go by...]
+
+1.20 Oct-5-98
+	Raffaele Sena produces ARM port.
+
+1.19 Oct-5-98
+	Fixed x86 long double and long long return support.
+	m68k bug fixes from Andreas Schwab.
+	Patch for DU assembler compatibility for the Alpha from Richard
+	Henderson.
+
+1.18 Apr-17-98
+	Bug fixes and MIPS configuration changes.
+
+1.17 Feb-24-98
+	Bug fixes and m68k port from Andreas Schwab. PowerPC port from
+	Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
+
+1.16 Feb-11-98
+	Richard Henderson produces Alpha port.
+
+1.15 Dec-4-97
+	Fixed an n32 ABI bug. New libtool, auto* support.
+
+1.14 May-13-97
+	libtool is now used to generate shared and static libraries.
+	Fixed a minor portability problem reported by Russ McManus
+	<mcmanr@eq.gs.com>.
+
+1.13 Dec-2-96
+	Added --enable-purify-safety to keep Purify from complaining
+	about certain low level code.
+	Sparc fix for calling functions with < 6 args.
+	Linux x86 a.out fix.
+
+1.12 Nov-22-96
+	Added missing ffi_type_void, needed for supporting void return 
+	types. Fixed test case for non MIPS machines. Cygnus Support 
+	is now Cygnus Solutions. 
+
+1.11 Oct-30-96
+	Added notes about GNU make.
+
+1.10 Oct-29-96
+	Added configuration fix for non GNU compilers.
+
+1.09 Oct-29-96
+	Added --enable-debug configure switch. Clean-ups based on LCLint 
+	feedback. ffi_mips.h is always installed. Many configuration 
+	fixes. Fixed ffitest.c for sparc builds.
+
+1.08 Oct-15-96
+	Fixed n32 problem. Many clean-ups.
+
+1.07 Oct-14-96
+	Gordon Irlam rewrites v8.S again. Bug fixes.
+
+1.06 Oct-14-96
+	Gordon Irlam improved the sparc port. 
+
+1.05 Oct-14-96
+	Interface changes based on feedback.
+
+1.04 Oct-11-96
+	Sparc port complete (modulo struct passing bug).
+
+1.03 Oct-10-96
+	Passing struct args, and returning struct values works for
+	all architectures/calling conventions. Expanded tests.
+
+1.02 Oct-9-96
+	Added SGI n32 support. Fixed bugs in both o32 and Linux support.
+	Added "make test".
+
+1.01 Oct-8-96
+	Fixed float passing bug in mips version. Restructured some
+	of the code. Builds cleanly with SGI tools.
+
+1.00 Oct-7-96
+	First release. No public announcement.
+
+
+Authors & Credits
+=================
+
+libffi was originally written by Anthony Green <green@redhat.com>.
+
+The developers of the GNU Compiler Collection project have made
+innumerable valuable contributions.  See the ChangeLog file for
+details.
+
+Some of the ideas behind libffi were inspired by Gianni Mariani's free
+gencall library for Silicon Graphics machines.
+
+The closure mechanism was designed and implemented by Kresten Krab
+Thorup.
+
+Major processor architecture ports were contributed by the following
+developers:
+
+aarch64		Marcus Shawcroft, James Greenhalgh
+alpha		Richard Henderson
+arm		Raffaele Sena
+blackfin        Alexandre Keunecke I. de Mendonca
+cris		Simon Posnjak, Hans-Peter Nilsson
+frv		Anthony Green
+ia64		Hans Boehm
+m32r		Kazuhiro Inaoka
+m68k		Andreas Schwab
+mips		Anthony Green, Casey Marshall
+mips64		David Daney
+pa		Randolph Chung, Dave Anglin, Andreas Tobler
+powerpc		Geoffrey Keating, Andreas Tobler, 
+			 David Edelsohn, John Hornkvist
+powerpc64	Jakub Jelinek
+s390		Gerhard Tonn, Ulrich Weigand
+sh		Kaz Kojima
+sh64		Kaz Kojima
+sparc		Anthony Green, Gordon Irlam
+tile-gx/tilepro Walter Lee
+x86		Anthony Green, Jon Beniston
+x86-64		Bo Thorsen
+
+Jesper Skov and Andrew Haley both did more than their fair share of
+stepping through the code and tracking down bugs.
+
+Thanks also to Tom Tromey for bug fixes, documentation and
+configuration help.
+
+Thanks to Jim Blandy, who provided some useful feedback on the libffi
+interface.
+
+Andreas Tobler has done a tremendous amount of work on the testsuite.
+
+Alex Oliva solved the executable page problem for SElinux.
+
+The list above is almost certainly incomplete and inaccurate.  I'm
+happy to make corrections or additions upon request.
+
+If you have a problem, or have found a bug, please send a note to the
+author at green@moxielogic.com, or the project mailing list at
+libffi-discuss@sourceware.org.
diff --git a/third_party/gofrontend/libffi/acinclude.m4 b/third_party/gofrontend/libffi/acinclude.m4
new file mode 100644
index 0000000..3e8f8ba
--- /dev/null
+++ b/third_party/gofrontend/libffi/acinclude.m4
@@ -0,0 +1,92 @@
+# mmap(2) blacklisting.  Some platforms provide the mmap library routine
+# but don't support all of the features we need from it.
+AC_DEFUN([AC_FUNC_MMAP_BLACKLIST],
+[
+AC_CHECK_HEADER([sys/mman.h],
+		[libffi_header_sys_mman_h=yes], [libffi_header_sys_mman_h=no])
+AC_CHECK_FUNC([mmap], [libffi_func_mmap=yes], [libffi_func_mmap=no])
+if test "$libffi_header_sys_mman_h" != yes \
+ || test "$libffi_func_mmap" != yes; then
+   ac_cv_func_mmap_file=no
+   ac_cv_func_mmap_dev_zero=no
+   ac_cv_func_mmap_anon=no
+else
+   AC_CACHE_CHECK([whether read-only mmap of a plain file works],
+  ac_cv_func_mmap_file,
+  [# Add a system to this blacklist if
+   # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
+   # memory area containing the same data that you'd get if you applied
+   # read() to the same fd.  The only system known to have a problem here
+   # is VMS, where text files have record structure.
+   case "$host_os" in
+     vms* | ultrix*)
+	ac_cv_func_mmap_file=no ;;
+     *)
+	ac_cv_func_mmap_file=yes;;
+   esac])
+   AC_CACHE_CHECK([whether mmap from /dev/zero works],
+  ac_cv_func_mmap_dev_zero,
+  [# Add a system to this blacklist if it has mmap() but /dev/zero
+   # does not exist, or if mmapping /dev/zero does not give anonymous
+   # zeroed pages with both the following properties:
+   # 1. If you map N consecutive pages in with one call, and then
+   #    unmap any subset of those pages, the pages that were not
+   #    explicitly unmapped remain accessible.
+   # 2. If you map two adjacent blocks of memory and then unmap them
+   #    both at once, they must both go away.
+   # Systems known to be in this category are Windows (all variants),
+   # VMS, and Darwin.
+   case "$host_os" in
+     vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
+	ac_cv_func_mmap_dev_zero=no ;;
+     *)
+	ac_cv_func_mmap_dev_zero=yes;;
+   esac])
+
+   # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
+   AC_CACHE_CHECK([for MAP_ANON(YMOUS)], ac_cv_decl_map_anon,
+    [AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+],
+[int n = MAP_ANONYMOUS;],
+    ac_cv_decl_map_anon=yes,
+    ac_cv_decl_map_anon=no)])
+
+   if test $ac_cv_decl_map_anon = no; then
+     ac_cv_func_mmap_anon=no
+   else
+     AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works],
+     ac_cv_func_mmap_anon,
+  [# Add a system to this blacklist if it has mmap() and MAP_ANON or
+   # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+   # doesn't give anonymous zeroed pages with the same properties listed
+   # above for use of /dev/zero.
+   # Systems known to be in this category are Windows, VMS, and SCO Unix.
+   case "$host_os" in
+     vms* | cygwin* | pe | mingw* | sco* | udk* )
+	ac_cv_func_mmap_anon=no ;;
+     *)
+	ac_cv_func_mmap_anon=yes;;
+   esac])
+   fi
+fi
+
+if test $ac_cv_func_mmap_file = yes; then
+  AC_DEFINE(HAVE_MMAP_FILE, 1,
+	    [Define if read-only mmap of a plain file works.])
+fi
+if test $ac_cv_func_mmap_dev_zero = yes; then
+  AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
+	    [Define if mmap of /dev/zero works.])
+fi
+if test $ac_cv_func_mmap_anon = yes; then
+  AC_DEFINE(HAVE_MMAP_ANON, 1,
+	    [Define if mmap with MAP_ANON(YMOUS) works.])
+fi
+])
diff --git a/third_party/gofrontend/libffi/aclocal.m4 b/third_party/gofrontend/libffi/aclocal.m4
new file mode 100644
index 0000000..93d09b3
--- /dev/null
+++ b/third_party/gofrontend/libffi/aclocal.m4
@@ -0,0 +1,1039 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
+[m4_warning([this file was generated for autoconf 2.64.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.11.1], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# Figure out how to run the assembler.                      -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_PROG_AS
+# ----------
+AC_DEFUN([AM_PROG_AS],
+[# By default we simply use the C compiler to build assembly code.
+AC_REQUIRE([AC_PROG_CC])
+test "${CCAS+set}" = set || CCAS=$CC
+test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
+AC_ARG_VAR([CCAS],      [assembler compiler command (defaults to CC)])
+AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)])
+_AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl
+])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+	[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 10
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+       [$1], UPC,  [depcc="$UPC"  am_compiler_list=],
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 5
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named `Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`AS_DIRNAME("$mf")`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running `make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # When using ansi2knr, U may be empty or an underscore; expand it
+    U=`sed -n 's/^U = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`AS_DIRNAME(["$file"])`
+      AS_MKDIR_P([$dirpart/$fdir])
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+			     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+		  [_AM_DEPENDENCIES(CC)],
+		  [define([AC_PROG_CC],
+			  defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+		  [_AM_DEPENDENCIES(CXX)],
+		  [define([AC_PROG_CXX],
+			  defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+		  [_AM_DEPENDENCIES(OBJC)],
+		  [define([AC_PROG_OBJC],
+			  defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST(install_sh)])
+
+# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless `enable' is passed literally.
+# For symmetry, `disable' may be passed as well.  Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+       [enable], [m4_define([am_maintainer_other], [disable])],
+       [disable], [m4_define([am_maintainer_other], [enable])],
+       [m4_define([am_maintainer_other], [enable])
+        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
+  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+  AC_ARG_ENABLE([maintainer-mode],
+[  --][am_maintainer_other][-maintainer-mode  am_maintainer_other make rules and dependencies not useful
+			  (and sometimes confusing) to the casual installer],
+      [USE_MAINTAINER_MODE=$enableval],
+      [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST([MAINT])dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2009  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_PROG_CC_C_O
+# --------------
+# Like AC_PROG_CC_C_O, but changed for automake.
+AC_DEFUN([AM_PROG_CC_C_O],
+[AC_REQUIRE([AC_PROG_CC_C_O])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
+eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
+if test "$am_t" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+dnl Make sure AC_PROG_CC is never called again, or it will override our
+dnl setting of CC.
+m4_define([AC_PROG_CC],
+          [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p.  We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+  [[\\/$]]* | ?:[[\\/]]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
+    AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([../config/acx.m4])
+m4_include([../config/asmcfi.m4])
+m4_include([../config/depstand.m4])
+m4_include([../config/lead-dot.m4])
+m4_include([../config/multi.m4])
+m4_include([../config/override.m4])
+m4_include([../libtool.m4])
+m4_include([../ltoptions.m4])
+m4_include([../ltsugar.m4])
+m4_include([../ltversion.m4])
+m4_include([../lt~obsolete.m4])
+m4_include([acinclude.m4])
diff --git a/third_party/gofrontend/libffi/build-ios.sh b/third_party/gofrontend/libffi/build-ios.sh
new file mode 100755
index 0000000..3dea242
--- /dev/null
+++ b/third_party/gofrontend/libffi/build-ios.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+PLATFORM_IOS=/Developer/Platforms/iPhoneOS.platform/
+PLATFORM_IOS_SIM=/Developer/Platforms/iPhoneSimulator.platform/
+SDK_IOS_VERSION="4.2"
+MIN_IOS_VERSION="3.0"
+OUTPUT_DIR="universal-ios"
+
+build_target () {
+    local platform=$1
+    local sdk=$2
+    local arch=$3
+    local triple=$4
+    local builddir=$5
+
+    mkdir -p "${builddir}"
+    pushd "${builddir}"
+    export CC="${platform}"/Developer/usr/bin/gcc-4.2
+    export CFLAGS="-arch ${arch} -isysroot ${sdk} -miphoneos-version-min=${MIN_IOS_VERSION}"
+    ../configure --host=${triple} && make
+    popd
+}
+
+# Build all targets
+build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv6 arm-apple-darwin10 armv6-ios
+build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv7 arm-apple-darwin10 armv7-ios
+build_target "${PLATFORM_IOS_SIM}" "${PLATFORM_IOS_SIM}/Developer/SDKs/iPhoneSimulator${SDK_IOS_VERSION}.sdk/" i386 i386-apple-darwin10 i386-ios-sim
+
+# Create universal output directories
+mkdir -p "${OUTPUT_DIR}"
+mkdir -p "${OUTPUT_DIR}/include"
+mkdir -p "${OUTPUT_DIR}/include/armv6"
+mkdir -p "${OUTPUT_DIR}/include/armv7"
+mkdir -p "${OUTPUT_DIR}/include/i386"
+
+# Create the universal binary
+lipo -create armv6-ios/.libs/libffi.a armv7-ios/.libs/libffi.a i386-ios-sim/.libs/libffi.a -output "${OUTPUT_DIR}/libffi.a"
+
+# Copy in the headers
+copy_headers () {
+    local src=$1
+    local dest=$2
+
+    # Fix non-relative header reference
+    sed 's/<ffitarget.h>/"ffitarget.h"/' < "${src}/include/ffi.h" > "${dest}/ffi.h"
+    cp "${src}/include/ffitarget.h" "${dest}"
+}
+
+copy_headers armv6-ios "${OUTPUT_DIR}/include/armv6"
+copy_headers armv7-ios "${OUTPUT_DIR}/include/armv7"
+copy_headers i386-ios-sim "${OUTPUT_DIR}/include/i386"
+
+# Create top-level header
+(
+cat << EOF
+#ifdef __arm__
+  #include <arm/arch.h>
+  #ifdef _ARM_ARCH_6
+    #include "include/armv6/ffi.h"
+  #elif _ARM_ARCH_7
+    #include "include/armv7/ffi.h"
+  #endif
+#elif defined(__i386__)
+  #include "include/i386/ffi.h"
+#endif
+EOF
+) > "${OUTPUT_DIR}/ffi.h"
diff --git a/third_party/gofrontend/libffi/configure b/third_party/gofrontend/libffi/configure
new file mode 100755
index 0000000..4c53cf9
--- /dev/null
+++ b/third_party/gofrontend/libffi/configure
@@ -0,0 +1,15476 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.64 for libffi 3.0.11.
+#
+# Report bugs to <http://gcc.gnu.org/bugs.html>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
+# Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+
+  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  # We cannot yet assume a decent shell, so we have to provide a
+	# neutralization value for shells without unset; and this also
+	# works around shells that cannot unset nonexistent variables.
+	BASH_ENV=/dev/null
+	ENV=/dev/null
+	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+	export CONFIG_SHELL
+	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: http://gcc.gnu.org/bugs.html about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='libffi'
+PACKAGE_TARNAME='libffi'
+PACKAGE_VERSION='3.0.11'
+PACKAGE_STRING='libffi 3.0.11'
+PACKAGE_BUGREPORT='http://gcc.gnu.org/bugs.html'
+PACKAGE_URL=''
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+toolexeclibdir
+toolexecdir
+FFI_DEBUG_FALSE
+FFI_DEBUG_TRUE
+TARGETDIR
+TARGET
+FFI_EXEC_TRAMPOLINE_TABLE
+FFI_EXEC_TRAMPOLINE_TABLE_FALSE
+FFI_EXEC_TRAMPOLINE_TABLE_TRUE
+HAVE_LONG_DOUBLE_VARIANT
+HAVE_LONG_DOUBLE
+ALLOCA
+TILE_FALSE
+TILE_TRUE
+PA64_HPUX_FALSE
+PA64_HPUX_TRUE
+PA_HPUX_FALSE
+PA_HPUX_TRUE
+PA_LINUX_FALSE
+PA_LINUX_TRUE
+SH64_FALSE
+SH64_TRUE
+SH_FALSE
+SH_TRUE
+X86_64_FALSE
+X86_64_TRUE
+S390_FALSE
+S390_TRUE
+FRV_FALSE
+FRV_TRUE
+LIBFFI_CRIS_FALSE
+LIBFFI_CRIS_TRUE
+AVR32_FALSE
+AVR32_TRUE
+ARM_FALSE
+ARM_TRUE
+AARCH64_FALSE
+AARCH64_TRUE
+POWERPC_FREEBSD_FALSE
+POWERPC_FREEBSD_TRUE
+POWERPC_DARWIN_FALSE
+POWERPC_DARWIN_TRUE
+POWERPC_AIX_FALSE
+POWERPC_AIX_TRUE
+POWERPC_FALSE
+POWERPC_TRUE
+M68K_FALSE
+M68K_TRUE
+M32R_FALSE
+M32R_TRUE
+IA64_FALSE
+IA64_TRUE
+ALPHA_FALSE
+ALPHA_TRUE
+X86_DARWIN_FALSE
+X86_DARWIN_TRUE
+X86_WIN64_FALSE
+X86_WIN64_TRUE
+X86_WIN32_FALSE
+X86_WIN32_TRUE
+X86_FREEBSD_FALSE
+X86_FREEBSD_TRUE
+X86_FALSE
+X86_TRUE
+SPARC_FALSE
+SPARC_TRUE
+BFIN_FALSE
+BFIN_TRUE
+MIPS_FALSE
+MIPS_TRUE
+AM_LTLDFLAGS
+AM_RUNTESTFLAGS
+TESTSUBDIR_FALSE
+TESTSUBDIR_TRUE
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+CPP
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+RANLIB
+AR
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+LIBTOOL
+am__fastdepCCAS_FALSE
+am__fastdepCCAS_TRUE
+CCASDEPMODE
+CCASFLAGS
+CCAS
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+GENINSRC_FALSE
+GENINSRC_TRUE
+BUILD_INFO_FALSE
+BUILD_INFO_TRUE
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+multi_basedir
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_multilib
+enable_generated_files_in_srcdir
+enable_dependency_tracking
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+with_gnu_ld
+enable_libtool_lock
+enable_maintainer_mode
+enable_pax_emutramp
+enable_debug
+enable_structs
+enable_raw_api
+enable_purify_safety
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CCAS
+CCASFLAGS
+CPP
+CPPFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)	ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information."
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures libffi 3.0.11 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/libffi]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of libffi 3.0.11:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-multilib       build many library versions (default)
+  --enable-generated-files-in-srcdir
+                          put copies of generated files in source dir intended
+                          for creating source tarballs for users without
+                          texinfo bison or flex
+  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-maintainer-mode  enable make rules and dependencies not useful
+			  (and sometimes confusing) to the casual installer
+  --enable-pax_emutramp       enable pax emulated trampolines, for we can't use PROT_EXEC
+  --enable-debug          debugging mode
+  --disable-structs       omit code for struct support
+  --disable-raw-api       make the raw api unavailable
+  --enable-purify-safety  purify-safe mode
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-pic              try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CCAS        assembler compiler command (defaults to CC)
+  CCASFLAGS   assembler compiler flags (defaults to CFLAGS)
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <http://gcc.gnu.org/bugs.html>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+libffi configure 3.0.11
+generated by GNU Autoconf 2.64
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( cat <<\_ASBOX
+## ------------------------------------------- ##
+## Report this to http://gcc.gnu.org/bugs.html ##
+## ------------------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
+# --------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_c_compute_int ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if test "$cross_compiling" = yes; then
+    # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid; break
+else
+  as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=$ac_mid; break
+else
+  as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  ac_lo= ac_hi=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid
+else
+  as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in #((
+?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
+'') ac_retval=1 ;;
+esac
+  else
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+static long int longval () { return $2; }
+static unsigned long int ulongval () { return $2; }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (($2) < 0)
+    {
+      long int i = longval ();
+      if (i != ($2))
+	return 1;
+      fprintf (f, "%ld", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ($2))
+	return 1;
+      fprintf (f, "%lu", i);
+    }
+  /* Do not output a trailing newline, as this causes \r\n confusion
+     on some platforms.  */
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  echo >>conftest.val; read $3 <conftest.val; ac_retval=0
+else
+  ac_retval=1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f conftest.val
+
+  fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_compute_int
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by libffi $as_me 3.0.11, which was
+generated by GNU Autoconf 2.64.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+ac_config_headers="$ac_config_headers fficonfig.h"
+
+
+# Default to --enable-multilib
+# Check whether --enable-multilib was given.
+if test "${enable_multilib+set}" = set; then :
+  enableval=$enable_multilib; case "$enableval" in
+  yes) multilib=yes ;;
+  no)  multilib=no ;;
+  *)   as_fn_error "bad value $enableval for multilib option" "$LINENO" 5 ;;
+ esac
+else
+  multilib=yes
+fi
+
+
+# We may get other options which we leave undocumented:
+# --with-target-subdir, --with-multisrctop, --with-multisubdir
+# See config-ml.in if you want the gory details.
+
+if test "$srcdir" = "."; then
+  if test "$with_target_subdir" != "."; then
+    multi_basedir="$srcdir/$with_multisrctop../.."
+  else
+    multi_basedir="$srcdir/$with_multisrctop.."
+  fi
+else
+  multi_basedir="$srcdir/.."
+fi
+
+
+# Even if the default multilib is not a cross compilation,
+# it may be that some of the other multilibs are.
+if test $cross_compiling = no && test $multilib = yes \
+   && test "x${with_multisubdir}" != x ; then
+   cross_compiling=maybe
+fi
+
+ac_config_commands="$ac_config_commands default-1"
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  for ac_t in install-sh install.sh shtool; do
+    if test -f "$ac_dir/$ac_t"; then
+      ac_aux_dir=$ac_dir
+      ac_install_sh="$ac_aux_dir/$ac_t -c"
+      break 2
+    fi
+  done
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if test "${ac_cv_target+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+target_alias=${target_alias-$host_alias}
+
+. ${srcdir}/configure.host
+
+am__api_version='1.11'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
+    as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      as_fn_error "ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+  [\\/$]* | ?:[\\/]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='libffi'
+ VERSION='3.0.11'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+# See if makeinfo has been installed and is modern enough
+# that we can use it.
+
+  # Extract the first word of "makeinfo", so it can be a program name with args.
+set dummy makeinfo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_MAKEINFO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$MAKEINFO"; then
+  ac_cv_prog_MAKEINFO="$MAKEINFO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_MAKEINFO="makeinfo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+MAKEINFO=$ac_cv_prog_MAKEINFO
+if test -n "$MAKEINFO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKEINFO" >&5
+$as_echo "$MAKEINFO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  if test -n "$MAKEINFO"; then
+    # Found it, now check the version.
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for modern makeinfo" >&5
+$as_echo_n "checking for modern makeinfo... " >&6; }
+if test "${gcc_cv_prog_makeinfo_modern+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_prog_version=`eval $MAKEINFO --version 2>&1 |
+                                     sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'`
+
+                    case $ac_prog_version in
+                      '')  gcc_cv_prog_makeinfo_modern=no;;
+                      4.[4-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*)  gcc_cv_prog_makeinfo_modern=yes;;
+                      *)   gcc_cv_prog_makeinfo_modern=no;;
+                    esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_prog_makeinfo_modern" >&5
+$as_echo "$gcc_cv_prog_makeinfo_modern" >&6; }
+  else
+    gcc_cv_prog_makeinfo_modern=no
+  fi
+  if test $gcc_cv_prog_makeinfo_modern = no; then
+    MAKEINFO="${CONFIG_SHELL-/bin/sh} $ac_aux_dir/missing makeinfo"
+  fi
+
+ if test $gcc_cv_prog_makeinfo_modern = "yes"; then
+  BUILD_INFO_TRUE=
+  BUILD_INFO_FALSE='#'
+else
+  BUILD_INFO_TRUE='#'
+  BUILD_INFO_FALSE=
+fi
+
+
+# We would like our source tree to be readonly. However when releases or
+# pre-releases are generated, the flex/bison generated files as well as the
+# various formats of manuals need to be included along with the rest of the
+# sources.  Therefore we have --enable-generated-files-in-srcdir to do
+# just that.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking generated-files-in-srcdir" >&5
+$as_echo_n "checking generated-files-in-srcdir... " >&6; }
+# Check whether --enable-generated-files-in-srcdir was given.
+if test "${enable_generated_files_in_srcdir+set}" = set; then :
+  enableval=$enable_generated_files_in_srcdir; case "$enableval" in
+ yes) enable_generated_files_in_srcdir=yes ;;
+ no)  enable_generated_files_in_srcdir=no ;;
+ *)   as_fn_error "Unknown argument to enable/disable version-specific libs" "$LINENO" 5;;
+ esac
+else
+  enable_generated_files_in_srcdir=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_generated_files_in_srcdir" >&5
+$as_echo "$enable_generated_files_in_srcdir" >&6; }
+ if test "$enable_generated_files_in_srcdir" = yes; then
+  GENINSRC_TRUE=
+  GENINSRC_FALSE='#'
+else
+  GENINSRC_TRUE='#'
+  GENINSRC_FALSE=
+fi
+
+
+# The same as in boehm-gc and libstdc++. Have to borrow it from there.
+# We must force CC to /not/ be precious variables; otherwise
+# the wrong, non-multilib-adjusted value will be used in multilibs.
+# As a side effect, we have to subst CFLAGS ourselves.
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    rm -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then :
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "C compiler cannot create executables
+See \`config.log' for more details." "$LINENO" 5; }; }
+fi
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+
+
+
+# By default we simply use the C compiler to build assembly code.
+
+test "${CCAS+set}" = set || CCAS=$CC
+test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
+
+
+
+depcc="$CCAS"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CCAS_dependencies_compiler_type+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CCAS_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CCAS_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CCAS_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CCAS_dependencies_compiler_type" >&6; }
+CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CCAS_dependencies_compiler_type" = gcc3; then
+  am__fastdepCCAS_TRUE=
+  am__fastdepCCAS_FALSE='#'
+else
+  am__fastdepCCAS_TRUE='#'
+  am__fastdepCCAS_FALSE=
+fi
+
+
+if test "x$CC" != xcc; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5
+$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5
+$as_echo_n "checking whether cc understands -c and -o together... " >&6; }
+fi
+set dummy $CC; ac_cc=`$as_echo "$2" |
+		      sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+# Make sure it works both with $CC and with simple cc.
+# We do the test twice because some compilers refuse to overwrite an
+# existing .o file with -o, though they will create one.
+ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+rm -f conftest2.*
+if { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } &&
+   test -f conftest2.$ac_objext && { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; };
+then
+  eval ac_cv_prog_cc_${ac_cc}_c_o=yes
+  if test "x$CC" != xcc; then
+    # Test first that cc exists at all.
+    if { ac_try='cc -c conftest.$ac_ext >&5'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+      ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+      rm -f conftest2.*
+      if { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } &&
+	 test -f conftest2.$ac_objext && { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; };
+      then
+	# cc works too.
+	:
+      else
+	# cc exists but doesn't like -o.
+	eval ac_cv_prog_cc_${ac_cc}_c_o=no
+      fi
+    fi
+  fi
+else
+  eval ac_cv_prog_cc_${ac_cc}_c_o=no
+fi
+rm -f core conftest*
+
+fi
+if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h
+
+fi
+
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
+if test "$am_t" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+
+
+case `pwd` in
+  *\ * | *\	*)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.2.7a'
+macro_revision='1.3134'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`print -r -- -n 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO ""
+}
+
+case "$ECHO" in
+  printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+  print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+  *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if test "${ac_cv_path_SED+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if test "${ac_cv_path_FGREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+   then ac_cv_path_FGREP="$GREP -F"
+   else
+     if test -z "$FGREP"; then
+  ac_path_FGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in fgrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+  # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'FGREP' >> "conftest.nl"
+    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_FGREP="$ac_path_FGREP"
+      ac_path_FGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_FGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_FGREP"; then
+    as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_FGREP=$FGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if test "${lt_cv_path_NM+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+	*/dev/null* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in dumpbin "link -dump"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DUMPBIN+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DUMPBIN"; then
+  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$DUMPBIN" && break
+  done
+fi
+if test -z "$DUMPBIN"; then
+  ac_ct_DUMPBIN=$DUMPBIN
+  for ac_prog in dumpbin "link -dump"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DUMPBIN"; then
+  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_DUMPBIN" && break
+done
+
+  if test "x$ac_ct_DUMPBIN" = x; then
+    DUMPBIN=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DUMPBIN=$ac_ct_DUMPBIN
+  fi
+fi
+
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if test "${lt_cv_nm_interface+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+  cat conftest.out >&5
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[	 ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \
+	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OBJDUMP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if test "${lt_cv_deplibs_check_method+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_AR="ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDEGRST]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK '"\
+"     {last_section=section; section=\$ 3};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+const struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_save_LIBS="$LIBS"
+	  lt_save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$lt_save_LIBS"
+	  CFLAGS="$lt_save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&5
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE="32"
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE="64"
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    case `/usr/bin/file conftest.o` in
+	      *x86-64*)
+		LD="${LD-ld} -m elf32_x86_64"
+		;;
+	      *)
+		LD="${LD-ld} -m elf_i386"
+		;;
+	    esac
+	    ;;
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if test "${lt_cv_cc_needs_belf+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_cc_needs_belf=yes
+else
+  lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+  case $host_os in
+    rhapsody* | darwin*)
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DSYMUTIL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_NMEDIT+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+  ac_ct_NMEDIT=$NMEDIT
+  # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_NMEDIT"; then
+  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_NMEDIT="nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_NMEDIT" = x; then
+    NMEDIT=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    NMEDIT=$ac_ct_NMEDIT
+  fi
+else
+  NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_LIPO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LIPO"; then
+  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+  ac_ct_LIPO=$LIPO
+  # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_LIPO"; then
+  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_LIPO="lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_LIPO" = x; then
+    LIPO=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIPO=$ac_ct_LIPO
+  fi
+else
+  LIPO="$ac_cv_prog_LIPO"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL"; then
+  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+  ac_ct_OTOOL=$OTOOL
+  # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL"; then
+  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OTOOL="otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL" = x; then
+    OTOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL=$ac_ct_OTOOL
+  fi
+else
+  OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL64+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL64"; then
+  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+  ac_ct_OTOOL64=$OTOOL64
+  # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL64"; then
+  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OTOOL64="otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL64" = x; then
+    OTOOL64=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL64=$ac_ct_OTOOL64
+  fi
+else
+  OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if test "${lt_cv_apple_cc_single_mod+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&5
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if test "${lt_cv_ld_exported_symbols_list+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_ld_exported_symbols_list=yes
+else
+  lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+$as_echo_n "checking for -force_load linker flag... " >&6; }
+if test "${lt_cv_ld_force_load+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+      echo "$AR cru libconftest.a conftest.o" >&5
+      $AR cru libconftest.a conftest.o 2>&5
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then
+	lt_cv_ld_force_load=yes
+      else
+	cat conftest.err >&5
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+$as_echo "$lt_cv_ld_force_load" >&6; }
+    case $host_os in
+    rhapsody* | darwin1.[012])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+	10.[012]*)
+	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+	10.*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in dlfcn.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+# Set options
+
+
+
+        enable_dlopen=no
+
+
+  enable_win32_dll=no
+
+
+            # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+  # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+  withval=$with_pic; pic_mode="$withval"
+else
+  pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+  # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if test "${lt_cv_objdir+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+  case $cc_basename in
+  nvcc*)
+    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+  *)
+    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+  esac
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+
+
+
+  lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      lt_prog_compiler_wl='-Xlinker '
+      lt_prog_compiler_pic='-Xcompiler -fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      else
+	lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-KPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='--shared'
+	lt_prog_compiler_static='--static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fpic'
+	lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-qpic'
+	lt_prog_compiler_static='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ F* | *Sun*Fortran*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl=''
+	  ;;
+	*Sun\ C*)
+	  # Sun C 5.9
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Wl,'
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+	lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+	lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	lt_prog_compiler_pic='-Kconform_pic'
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5
+$as_echo "$lt_prog_compiler_pic" >&6; }
+
+
+
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if test "${lt_cv_prog_compiler_pic_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test "${lt_cv_prog_compiler_static_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  always_export_symbols=no
+  archive_cmds=
+  archive_expsym_cmds=
+  compiler_needs_object=no
+  enable_shared_with_static_runtimes=no
+  export_dynamic_flag_spec=
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic=no
+  hardcode_direct=no
+  hardcode_direct_absolute=no
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_flag_spec_ld=
+  hardcode_libdir_separator=
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  inherit_rpath=no
+  link_all_deplibs=unknown
+  module_cmds=
+  module_expsym_cmds=
+  old_archive_from_new_cmds=
+  old_archive_from_expsyms_cmds=
+  thread_safe_flag_spec=
+  whole_archive_flag_spec=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+	  *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	allow_undefined_flag=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      export_dynamic_flag_spec='${wl}--export-all-symbols'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    haiku*)
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      link_all_deplibs=yes
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  whole_archive_flag_spec=
+	  tmp_sharedflag='--shared' ;;
+	xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf* | bgf* | bgxlf* | mpixlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+	  hardcode_libdir_flag_spec=
+	  hardcode_libdir_flag_spec_ld='-rpath $libdir'
+	  archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        ld_shlibs=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    ld_shlibs=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	# Also, AIX nm treats weak defined symbols like other global
+	# defined symbols, whereas GNU nm marks them as "W".
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_direct_absolute=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      file_list_spec='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[012]|aix4.[012].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  hardcode_direct=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L=yes
+	  hardcode_libdir_flag_spec='-L$libdir'
+	  hardcode_libdir_separator=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      export_dynamic_flag_spec='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+	  allow_undefined_flag="-z nodefs"
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+	 hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  no_undefined_flag=' ${wl}-bernotok'
+	  allow_undefined_flag=' ${wl}-berok'
+	  if test "$with_gnu_ld" = yes; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    whole_archive_flag_spec='$convenience'
+	  fi
+	  archive_cmds_need_lc=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec=' '
+      allow_undefined_flag=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_from_new_cmds='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes=yes
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc=no
+  hardcode_direct=no
+  hardcode_automatic=yes
+  hardcode_shlibpath_var=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+  else
+    whole_archive_flag_spec=''
+  fi
+  link_all_deplibs=yes
+  allow_undefined_flag="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+  else
+  ld_shlibs=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_flag_spec_ld='+b $libdir'
+	hardcode_libdir_separator=:
+	hardcode_direct=yes
+	hardcode_direct_absolute=yes
+	export_dynamic_flag_spec='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+
+	  # Older versions of the 11.00 compiler do not understand -b yet
+	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+$as_echo_n "checking if $CC understands -b... " >&6; }
+if test "${lt_cv_prog_compiler__b+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler__b=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS -b"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler__b=yes
+       fi
+     else
+       lt_cv_prog_compiler__b=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+$as_echo "$lt_cv_prog_compiler__b" >&6; }
+
+if test x"$lt_cv_prog_compiler__b" = xyes; then
+    archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_separator=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  hardcode_direct=no
+	  hardcode_shlibpath_var=no
+	  ;;
+	*)
+	  hardcode_direct=yes
+	  hardcode_direct_absolute=yes
+	  export_dynamic_flag_spec='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  hardcode_minus_L=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+        save_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo(void) {}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+        LDFLAGS="$save_LDFLAGS"
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      inherit_rpath=yes
+      link_all_deplibs=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	hardcode_direct=yes
+	hardcode_shlibpath_var=no
+	hardcode_direct_absolute=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	  export_dynamic_flag_spec='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+	     archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     hardcode_libdir_flag_spec='-R$libdir'
+	     ;;
+	   *)
+	     archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  reload_cmds='$CC -r -o $output$reload_objs'
+	  hardcode_direct=no
+        ;;
+	motorola)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_shlibpath_var=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='${wl}-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='${wl}-z,text'
+      allow_undefined_flag='${wl}-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-R,$libdir'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	export_dynamic_flag_spec='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if test "${lt_cv_archive_cmds_need_lc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl
+	  pic_flag=$lt_prog_compiler_pic
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag
+	  allow_undefined_flag=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	  then
+	    lt_cv_archive_cmds_need_lc=no
+	  else
+	    lt_cv_archive_cmds_need_lc=yes
+	  fi
+	  allow_undefined_flag=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([A-Za-z]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[23].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+haiku*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  if test "${lt_cv_shlibpath_overrides_runpath+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+  lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+   test -n "$runpath_var" ||
+   test "X$hardcode_automatic" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink ||
+   test "$inherit_rpath" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+  if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+    ;;
+
+  *)
+    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = x""yes; then :
+  lt_cv_dlopen="shl_load"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_shl_load=yes
+else
+  ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = x""yes; then :
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_svld_dlopen=yes
+else
+  ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_dld_link=yes
+else
+  ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = x""yes; then :
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line 10910 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+void fnord () __attribute__((visibility("default")));
+#endif
+
+void fnord () { int i=42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line 11016 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+void fnord () __attribute__((visibility("default")));
+#endif
+
+void fnord () { int i=42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+    ;;
+  *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+  # Report which library types will actually be built
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[4-9]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+
+
+
+
+
+
+
+
+
+
+
+        ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+    # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+   if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+for ac_header in sys/mman.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_mman_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_MMAN_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in mmap
+do :
+  ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap"
+if test "x$ac_cv_func_mmap" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MMAP 1
+_ACEOF
+
+fi
+done
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_mman_h" = x""yes; then :
+  libffi_header_sys_mman_h=yes
+else
+  libffi_header_sys_mman_h=no
+fi
+
+
+ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap"
+if test "x$ac_cv_func_mmap" = x""yes; then :
+  libffi_func_mmap=yes
+else
+  libffi_func_mmap=no
+fi
+
+if test "$libffi_header_sys_mman_h" != yes \
+ || test "$libffi_func_mmap" != yes; then
+   ac_cv_func_mmap_file=no
+   ac_cv_func_mmap_dev_zero=no
+   ac_cv_func_mmap_anon=no
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether read-only mmap of a plain file works" >&5
+$as_echo_n "checking whether read-only mmap of a plain file works... " >&6; }
+if test "${ac_cv_func_mmap_file+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  # Add a system to this blacklist if
+   # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
+   # memory area containing the same data that you'd get if you applied
+   # read() to the same fd.  The only system known to have a problem here
+   # is VMS, where text files have record structure.
+   case "$host_os" in
+     vms* | ultrix*)
+	ac_cv_func_mmap_file=no ;;
+     *)
+	ac_cv_func_mmap_file=yes;;
+   esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_file" >&5
+$as_echo "$ac_cv_func_mmap_file" >&6; }
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap from /dev/zero works" >&5
+$as_echo_n "checking whether mmap from /dev/zero works... " >&6; }
+if test "${ac_cv_func_mmap_dev_zero+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  # Add a system to this blacklist if it has mmap() but /dev/zero
+   # does not exist, or if mmapping /dev/zero does not give anonymous
+   # zeroed pages with both the following properties:
+   # 1. If you map N consecutive pages in with one call, and then
+   #    unmap any subset of those pages, the pages that were not
+   #    explicitly unmapped remain accessible.
+   # 2. If you map two adjacent blocks of memory and then unmap them
+   #    both at once, they must both go away.
+   # Systems known to be in this category are Windows (all variants),
+   # VMS, and Darwin.
+   case "$host_os" in
+     vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
+	ac_cv_func_mmap_dev_zero=no ;;
+     *)
+	ac_cv_func_mmap_dev_zero=yes;;
+   esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_dev_zero" >&5
+$as_echo "$ac_cv_func_mmap_dev_zero" >&6; }
+
+   # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MAP_ANON(YMOUS)" >&5
+$as_echo_n "checking for MAP_ANON(YMOUS)... " >&6; }
+if test "${ac_cv_decl_map_anon+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+int
+main ()
+{
+int n = MAP_ANONYMOUS;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_decl_map_anon=yes
+else
+  ac_cv_decl_map_anon=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_map_anon" >&5
+$as_echo "$ac_cv_decl_map_anon" >&6; }
+
+   if test $ac_cv_decl_map_anon = no; then
+     ac_cv_func_mmap_anon=no
+   else
+     { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap with MAP_ANON(YMOUS) works" >&5
+$as_echo_n "checking whether mmap with MAP_ANON(YMOUS) works... " >&6; }
+if test "${ac_cv_func_mmap_anon+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  # Add a system to this blacklist if it has mmap() and MAP_ANON or
+   # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+   # doesn't give anonymous zeroed pages with the same properties listed
+   # above for use of /dev/zero.
+   # Systems known to be in this category are Windows, VMS, and SCO Unix.
+   case "$host_os" in
+     vms* | cygwin* | pe | mingw* | sco* | udk* )
+	ac_cv_func_mmap_anon=no ;;
+     *)
+	ac_cv_func_mmap_anon=yes;;
+   esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_anon" >&5
+$as_echo "$ac_cv_func_mmap_anon" >&6; }
+   fi
+fi
+
+if test $ac_cv_func_mmap_file = yes; then
+
+$as_echo "#define HAVE_MMAP_FILE 1" >>confdefs.h
+
+fi
+if test $ac_cv_func_mmap_dev_zero = yes; then
+
+$as_echo "#define HAVE_MMAP_DEV_ZERO 1" >>confdefs.h
+
+fi
+if test $ac_cv_func_mmap_anon = yes; then
+
+$as_echo "#define HAVE_MMAP_ANON 1" >>confdefs.h
+
+fi
+
+
+ if test -d $srcdir/testsuite; then
+  TESTSUBDIR_TRUE=
+  TESTSUBDIR_FALSE='#'
+else
+  TESTSUBDIR_TRUE='#'
+  TESTSUBDIR_FALSE=
+fi
+
+
+TARGETDIR="unknown"
+HAVE_LONG_DOUBLE_VARIANT=0
+case "$host" in
+  aarch64*-*-*)
+	TARGET=AARCH64; TARGETDIR=aarch64
+	;;
+
+  alpha*-*-*)
+	TARGET=ALPHA; TARGETDIR=alpha;
+	# Support 128-bit long double, changeable via command-line switch.
+	HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
+	;;
+
+  arm*-*-*)
+	TARGET=ARM; TARGETDIR=arm
+	;;
+
+  amd64-*-freebsd* | amd64-*-openbsd*)
+	TARGET=X86_64; TARGETDIR=x86
+  	;;
+
+  amd64-*-freebsd*)
+	TARGET=X86_64; TARGETDIR=x86
+	;;
+
+  avr32*-*-*)
+	TARGET=AVR32; TARGETDIR=avr32
+	;;
+
+  bfin*)
+  	TARGET=BFIN; TARGETDIR=bfin
+  	;;
+
+  cris-*-*)
+	TARGET=LIBFFI_CRIS; TARGETDIR=cris
+	;;
+
+  frv-*-*)
+	TARGET=FRV; TARGETDIR=frv
+	;;
+
+  hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
+	TARGET=PA_LINUX; TARGETDIR=pa
+	;;
+  hppa*64-*-hpux*)
+	TARGET=PA64_HPUX; TARGETDIR=pa
+	;;
+  hppa*-*-hpux*)
+	TARGET=PA_HPUX; TARGETDIR=pa
+	;;
+
+  i?86-*-freebsd* | i?86-*-openbsd*)
+	TARGET=X86_FREEBSD; TARGETDIR=x86
+	;;
+  i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*)
+	TARGET=X86_WIN32; TARGETDIR=x86
+	# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
+	# We must also check with_cross_host to decide if this is a native
+	# or cross-build and select where to install dlls appropriately.
+	if test -n "$with_cross_host" &&
+	   test x"$with_cross_host" != x"no"; then
+	  AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
+	else
+	  AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
+	fi
+	;;
+  i?86-*-darwin*)
+	TARGET=X86_DARWIN; TARGETDIR=x86
+	;;
+  i?86-*-solaris2.1[0-9]*)
+	TARGET=X86_64; TARGETDIR=x86
+	;;
+  i?86-*-*)
+	TARGET=X86_64; TARGETDIR=x86
+	;;
+
+  ia64*-*-*)
+	TARGET=IA64; TARGETDIR=ia64
+	;;
+
+  m32r*-*-*)
+	TARGET=M32R; TARGETDIR=m32r
+	;;
+
+  m68k-*-*)
+	TARGET=M68K; TARGETDIR=m68k
+	;;
+
+  mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
+	TARGET=MIPS; TARGETDIR=mips
+	;;
+  mips*-*-linux* | mips*-*-openbsd*)
+	# Support 128-bit long double for NewABI.
+	HAVE_LONG_DOUBLE='defined(__mips64)'
+	TARGET=MIPS; TARGETDIR=mips
+	;;
+
+  powerpc*-*-linux* | powerpc-*-sysv*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	HAVE_LONG_DOUBLE_VARIANT=1
+	;;
+  powerpc-*-amigaos*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+  powerpc-*-beos*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+  powerpc-*-darwin* | powerpc64-*-darwin*)
+	TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
+	;;
+  powerpc-*-aix* | rs6000-*-aix*)
+	TARGET=POWERPC_AIX; TARGETDIR=powerpc
+	;;
+  powerpc-*-freebsd* | powerpc-*-openbsd*)
+	TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
+	HAVE_LONG_DOUBLE_VARIANT=1
+	;;
+  powerpc64-*-freebsd*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+  powerpc*-*-rtems*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+
+  s390-*-* | s390x-*-*)
+	TARGET=S390; TARGETDIR=s390
+	;;
+
+  sh-*-* | sh[34]*-*-*)
+	TARGET=SH; TARGETDIR=sh
+	;;
+  sh64-*-* | sh5*-*-*)
+	TARGET=SH64; TARGETDIR=sh64
+	;;
+
+  sparc*-*-*)
+	TARGET=SPARC; TARGETDIR=sparc
+	;;
+
+  tile*-*)
+        TARGET=TILE; TARGETDIR=tile
+        ;;
+
+  x86_64-*-darwin*)
+	TARGET=X86_DARWIN; TARGETDIR=x86
+	;;
+
+  x86_64-*-cygwin* | x86_64-*-mingw*)
+	TARGET=X86_WIN64; TARGETDIR=x86
+	# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
+	# We must also check with_cross_host to decide if this is a native
+	# or cross-build and select where to install dlls appropriately.
+	if test -n "$with_cross_host" &&
+	   test x"$with_cross_host" != x"no"; then
+	  AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
+	else
+	  AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
+	fi
+	;;
+
+  x86_64-*-*)
+	TARGET=X86_64; TARGETDIR=x86
+	;;
+esac
+
+
+
+
+if test $TARGETDIR = unknown; then
+  as_fn_error "\"libffi has not been ported to $host.\"" "$LINENO" 5
+fi
+
+ if test x$TARGET = xMIPS; then
+  MIPS_TRUE=
+  MIPS_FALSE='#'
+else
+  MIPS_TRUE='#'
+  MIPS_FALSE=
+fi
+
+ if test x$TARGET = xBFIN; then
+  BFIN_TRUE=
+  BFIN_FALSE='#'
+else
+  BFIN_TRUE='#'
+  BFIN_FALSE=
+fi
+
+ if test x$TARGET = xSPARC; then
+  SPARC_TRUE=
+  SPARC_FALSE='#'
+else
+  SPARC_TRUE='#'
+  SPARC_FALSE=
+fi
+
+ if test x$TARGET = xX86; then
+  X86_TRUE=
+  X86_FALSE='#'
+else
+  X86_TRUE='#'
+  X86_FALSE=
+fi
+
+ if test x$TARGET = xX86_FREEBSD; then
+  X86_FREEBSD_TRUE=
+  X86_FREEBSD_FALSE='#'
+else
+  X86_FREEBSD_TRUE='#'
+  X86_FREEBSD_FALSE=
+fi
+
+ if test x$TARGET = xX86_WIN32; then
+  X86_WIN32_TRUE=
+  X86_WIN32_FALSE='#'
+else
+  X86_WIN32_TRUE='#'
+  X86_WIN32_FALSE=
+fi
+
+ if test x$TARGET = xX86_WIN64; then
+  X86_WIN64_TRUE=
+  X86_WIN64_FALSE='#'
+else
+  X86_WIN64_TRUE='#'
+  X86_WIN64_FALSE=
+fi
+
+ if test x$TARGET = xX86_DARWIN; then
+  X86_DARWIN_TRUE=
+  X86_DARWIN_FALSE='#'
+else
+  X86_DARWIN_TRUE='#'
+  X86_DARWIN_FALSE=
+fi
+
+ if test x$TARGET = xALPHA; then
+  ALPHA_TRUE=
+  ALPHA_FALSE='#'
+else
+  ALPHA_TRUE='#'
+  ALPHA_FALSE=
+fi
+
+ if test x$TARGET = xIA64; then
+  IA64_TRUE=
+  IA64_FALSE='#'
+else
+  IA64_TRUE='#'
+  IA64_FALSE=
+fi
+
+ if test x$TARGET = xM32R; then
+  M32R_TRUE=
+  M32R_FALSE='#'
+else
+  M32R_TRUE='#'
+  M32R_FALSE=
+fi
+
+ if test x$TARGET = xM68K; then
+  M68K_TRUE=
+  M68K_FALSE='#'
+else
+  M68K_TRUE='#'
+  M68K_FALSE=
+fi
+
+ if test x$TARGET = xPOWERPC; then
+  POWERPC_TRUE=
+  POWERPC_FALSE='#'
+else
+  POWERPC_TRUE='#'
+  POWERPC_FALSE=
+fi
+
+ if test x$TARGET = xPOWERPC_AIX; then
+  POWERPC_AIX_TRUE=
+  POWERPC_AIX_FALSE='#'
+else
+  POWERPC_AIX_TRUE='#'
+  POWERPC_AIX_FALSE=
+fi
+
+ if test x$TARGET = xPOWERPC_DARWIN; then
+  POWERPC_DARWIN_TRUE=
+  POWERPC_DARWIN_FALSE='#'
+else
+  POWERPC_DARWIN_TRUE='#'
+  POWERPC_DARWIN_FALSE=
+fi
+
+ if test x$TARGET = xPOWERPC_FREEBSD; then
+  POWERPC_FREEBSD_TRUE=
+  POWERPC_FREEBSD_FALSE='#'
+else
+  POWERPC_FREEBSD_TRUE='#'
+  POWERPC_FREEBSD_FALSE=
+fi
+
+ if test x$TARGET = xAARCH64; then
+  AARCH64_TRUE=
+  AARCH64_FALSE='#'
+else
+  AARCH64_TRUE='#'
+  AARCH64_FALSE=
+fi
+
+ if test x$TARGET = xARM; then
+  ARM_TRUE=
+  ARM_FALSE='#'
+else
+  ARM_TRUE='#'
+  ARM_FALSE=
+fi
+
+ if test x$TARGET = xAVR32; then
+  AVR32_TRUE=
+  AVR32_FALSE='#'
+else
+  AVR32_TRUE='#'
+  AVR32_FALSE=
+fi
+
+ if test x$TARGET = xLIBFFI_CRIS; then
+  LIBFFI_CRIS_TRUE=
+  LIBFFI_CRIS_FALSE='#'
+else
+  LIBFFI_CRIS_TRUE='#'
+  LIBFFI_CRIS_FALSE=
+fi
+
+ if test x$TARGET = xFRV; then
+  FRV_TRUE=
+  FRV_FALSE='#'
+else
+  FRV_TRUE='#'
+  FRV_FALSE=
+fi
+
+ if test x$TARGET = xS390; then
+  S390_TRUE=
+  S390_FALSE='#'
+else
+  S390_TRUE='#'
+  S390_FALSE=
+fi
+
+ if test x$TARGET = xX86_64; then
+  X86_64_TRUE=
+  X86_64_FALSE='#'
+else
+  X86_64_TRUE='#'
+  X86_64_FALSE=
+fi
+
+ if test x$TARGET = xSH; then
+  SH_TRUE=
+  SH_FALSE='#'
+else
+  SH_TRUE='#'
+  SH_FALSE=
+fi
+
+ if test x$TARGET = xSH64; then
+  SH64_TRUE=
+  SH64_FALSE='#'
+else
+  SH64_TRUE='#'
+  SH64_FALSE=
+fi
+
+ if test x$TARGET = xPA_LINUX; then
+  PA_LINUX_TRUE=
+  PA_LINUX_FALSE='#'
+else
+  PA_LINUX_TRUE='#'
+  PA_LINUX_FALSE=
+fi
+
+ if test x$TARGET = xPA_HPUX; then
+  PA_HPUX_TRUE=
+  PA_HPUX_FALSE='#'
+else
+  PA_HPUX_TRUE='#'
+  PA_HPUX_FALSE=
+fi
+
+ if test x$TARGET = xPA64_HPUX; then
+  PA64_HPUX_TRUE=
+  PA64_HPUX_FALSE='#'
+else
+  PA64_HPUX_TRUE='#'
+  PA64_HPUX_FALSE=
+fi
+
+ if test x$TARGET = xTILE; then
+  TILE_TRUE=
+  TILE_FALSE='#'
+else
+  TILE_TRUE='#'
+  TILE_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+for ac_func in memcpy
+do :
+  ac_fn_c_check_func "$LINENO" "memcpy" "ac_cv_func_memcpy"
+if test "x$ac_cv_func_memcpy" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MEMCPY 1
+_ACEOF
+
+fi
+done
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5
+$as_echo_n "checking for working alloca.h... " >&6; }
+if test "${ac_cv_working_alloca_h+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+			  if (p) return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_working_alloca_h=yes
+else
+  ac_cv_working_alloca_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5
+$as_echo "$ac_cv_working_alloca_h" >&6; }
+if test $ac_cv_working_alloca_h = yes; then
+
+$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5
+$as_echo_n "checking for alloca... " >&6; }
+if test "${ac_cv_func_alloca_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+				    if (p) return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_func_alloca_works=yes
+else
+  ac_cv_func_alloca_works=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5
+$as_echo "$ac_cv_func_alloca_works" >&6; }
+
+if test $ac_cv_func_alloca_works = yes; then
+
+$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h
+
+else
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble.  Some versions do not even contain alloca or
+# contain a buggy version.  If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=\${LIBOBJDIR}alloca.$ac_objext
+
+$as_echo "#define C_ALLOCA 1" >>confdefs.h
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5
+$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; }
+if test "${ac_cv_os_cray+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if defined CRAY && ! defined CRAY2
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "webecray" >/dev/null 2>&1; then :
+  ac_cv_os_cray=yes
+else
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5
+$as_echo "$ac_cv_os_cray" >&6; }
+if test $ac_cv_os_cray = yes; then
+  for ac_func in _getb67 GETB67 getb67; do
+    as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+    break
+fi
+
+  done
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5
+$as_echo_n "checking stack direction for C alloca... " >&6; }
+if test "${ac_cv_c_stack_direction+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_c_stack_direction=0
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+  return find_stack_direction () < 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_stack_direction=1
+else
+  ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5
+$as_echo "$ac_cv_c_stack_direction" >&6; }
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of double" >&5
+$as_echo_n "checking size of double... " >&6; }
+if test "${ac_cv_sizeof_double+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (double))" "ac_cv_sizeof_double"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_double" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (double)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_double=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_double" >&5
+$as_echo "$ac_cv_sizeof_double" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_DOUBLE $ac_cv_sizeof_double
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long double" >&5
+$as_echo_n "checking size of long double... " >&6; }
+if test "${ac_cv_sizeof_long_double+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long double))" "ac_cv_sizeof_long_double"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_long_double" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (long double)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_long_double=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_double" >&5
+$as_echo "$ac_cv_sizeof_long_double" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_DOUBLE $ac_cv_sizeof_long_double
+_ACEOF
+
+
+
+# Also AC_SUBST this variable for ffi.h.
+if test -z "$HAVE_LONG_DOUBLE"; then
+  HAVE_LONG_DOUBLE=0
+  if test $ac_cv_sizeof_long_double != 0; then
+    if test $HAVE_LONG_DOUBLE_VARIANT != 0; then
+
+$as_echo "#define HAVE_LONG_DOUBLE_VARIANT 1" >>confdefs.h
+
+      HAVE_LONG_DOUBLE=1
+    else
+      if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
+        HAVE_LONG_DOUBLE=1
+
+$as_echo "#define HAVE_LONG_DOUBLE 1" >>confdefs.h
+
+      fi
+    fi
+  fi
+fi
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_bigendian=unknown
+    # See if we're dealing with a universal compiler.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __APPLE_CC__
+	       not a universal capable compiler
+	     #endif
+	     typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+	# Check for potential -arch flags.  It is not universal unless
+	# there are at least two -arch flags with different values.
+	ac_arch=
+	ac_prev=
+	for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+	 if test -n "$ac_prev"; then
+	   case $ac_word in
+	     i?86 | x86_64 | ppc | ppc64)
+	       if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+		 ac_arch=$ac_word
+	       else
+		 ac_cv_c_bigendian=universal
+		 break
+	       fi
+	       ;;
+	   esac
+	   ac_prev=
+	 elif test "x$ac_word" = "x-arch"; then
+	   ac_prev=arch
+	 fi
+       done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if sys/param.h defines the BYTE_ORDER macro.
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+	     #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+		     && LITTLE_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+		#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to _BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # Compile a test program.
+      if test "$cross_compiling" = yes; then :
+  # Try to guess by grepping values from an object file.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+short int ascii_mm[] =
+		  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+		short int ascii_ii[] =
+		  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+		int use_ascii (int i) {
+		  return ascii_mm[i] + ascii_ii[i];
+		}
+		short int ebcdic_ii[] =
+		  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+		short int ebcdic_mm[] =
+		  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+		int use_ebcdic (int i) {
+		  return ebcdic_mm[i] + ebcdic_ii[i];
+		}
+		extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+	      ac_cv_c_bigendian=yes
+	    fi
+	    if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+	      if test "$ac_cv_c_bigendian" = unknown; then
+		ac_cv_c_bigendian=no
+	      else
+		# finding both strings is unlikely to happen, but who knows?
+		ac_cv_c_bigendian=unknown
+	      fi
+	    fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+	     /* Are we little or big endian?  From Harbison&Steele.  */
+	     union
+	     {
+	       long int l;
+	       char c[sizeof (long int)];
+	     } u;
+	     u.l = 1;
+	     return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_bigendian=no
+else
+  ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+   yes)
+     $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+   no)
+      ;; #(
+   universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+     ;; #(
+   *)
+     as_fn_error "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler .cfi pseudo-op support" >&5
+$as_echo_n "checking assembler .cfi pseudo-op support... " >&6; }
+if test "${gcc_cv_as_cfi_pseudo_op+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    gcc_cv_as_cfi_pseudo_op=unknown
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+asm (".cfi_startproc\n\t.cfi_endproc");
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  gcc_cv_as_cfi_pseudo_op=yes
+else
+  gcc_cv_as_cfi_pseudo_op=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_cfi_pseudo_op" >&5
+$as_echo "$gcc_cv_as_cfi_pseudo_op" >&6; }
+ if test "x$gcc_cv_as_cfi_pseudo_op" = xyes; then
+
+$as_echo "#define HAVE_AS_CFI_PSEUDO_OP 1" >>confdefs.h
+
+ fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -Qunused-arguments" >&5
+$as_echo_n "checking if compiler supports -Qunused-arguments... " >&6; }
+if test "${libffi_cv_c_unused_arguments+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -Qunused-arguments"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libffi_cv_c_unused_arguments=yes
+else
+  libffi_cv_c_unused_arguments=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS=$CFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_c_unused_arguments" >&5
+$as_echo "$libffi_cv_c_unused_arguments" >&6; }
+
+if test x$TARGET = xSPARC; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler and linker support unaligned pc related relocs" >&5
+$as_echo_n "checking assembler and linker support unaligned pc related relocs... " >&6; }
+if test "${libffi_cv_as_sparc_ua_pcrel+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+	save_CFLAGS="$CFLAGS"
+	save_LDFLAGS="$LDFLAGS"
+	CFLAGS="$CFLAGS -fpic"
+	LDFLAGS="$LDFLAGS -shared"
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libffi_cv_as_sparc_ua_pcrel=yes
+else
+  libffi_cv_as_sparc_ua_pcrel=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	CFLAGS="$save_CFLAGS"
+	LDFLAGS="$save_LDFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_sparc_ua_pcrel" >&5
+$as_echo "$libffi_cv_as_sparc_ua_pcrel" >&6; }
+    if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
+
+$as_echo "#define HAVE_AS_SPARC_UA_PCREL 1" >>confdefs.h
+
+    fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler .register pseudo-op support" >&5
+$as_echo_n "checking assembler .register pseudo-op support... " >&6; }
+if test "${libffi_cv_as_register_pseudo_op+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       libffi_cv_as_register_pseudo_op=unknown
+       # Check if we have .register
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+asm (".register %g2, #scratch");
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libffi_cv_as_register_pseudo_op=yes
+else
+  libffi_cv_as_register_pseudo_op=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_register_pseudo_op" >&5
+$as_echo "$libffi_cv_as_register_pseudo_op" >&6; }
+    if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
+
+$as_echo "#define HAVE_AS_REGISTER_PSEUDO_OP 1" >>confdefs.h
+
+    fi
+fi
+
+if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports pc related relocs" >&5
+$as_echo_n "checking assembler supports pc related relocs... " >&6; }
+if test "${libffi_cv_as_x86_pcrel+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+	libffi_cv_as_x86_pcrel=yes
+	echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
+	CFLAGS_hold=$CFLAGS
+	if test "$libffi_cv_c_unused_arguments" = yes; then
+	    CFLAGS="$CFLAGS -Qunused-arguments"
+	fi
+	if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
+	    libffi_cv_as_x86_pcrel=no
+	fi
+	CFLAGS=$CFLAGS_hold
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_x86_pcrel" >&5
+$as_echo "$libffi_cv_as_x86_pcrel" >&6; }
+    if test "x$libffi_cv_as_x86_pcrel" = xyes; then
+
+$as_echo "#define HAVE_AS_X86_PCREL 1" >>confdefs.h
+
+    fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler .ascii pseudo-op support" >&5
+$as_echo_n "checking assembler .ascii pseudo-op support... " >&6; }
+if test "${libffi_cv_as_ascii_pseudo_op+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       libffi_cv_as_ascii_pseudo_op=unknown
+       # Check if we have .ascii
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+asm (".ascii \\"string\\"");
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libffi_cv_as_ascii_pseudo_op=yes
+else
+  libffi_cv_as_ascii_pseudo_op=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_ascii_pseudo_op" >&5
+$as_echo "$libffi_cv_as_ascii_pseudo_op" >&6; }
+    if test "x$libffi_cv_as_ascii_pseudo_op" = xyes; then
+
+$as_echo "#define HAVE_AS_ASCII_PSEUDO_OP 1" >>confdefs.h
+
+    fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler .string pseudo-op support" >&5
+$as_echo_n "checking assembler .string pseudo-op support... " >&6; }
+if test "${libffi_cv_as_string_pseudo_op+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       libffi_cv_as_string_pseudo_op=unknown
+       # Check if we have .string
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+asm (".string \\"string\\"");
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libffi_cv_as_string_pseudo_op=yes
+else
+  libffi_cv_as_string_pseudo_op=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_string_pseudo_op" >&5
+$as_echo "$libffi_cv_as_string_pseudo_op" >&6; }
+    if test "x$libffi_cv_as_string_pseudo_op" = xyes; then
+
+$as_echo "#define HAVE_AS_STRING_PSEUDO_OP 1" >>confdefs.h
+
+    fi
+fi
+
+# On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC.
+# Check whether --enable-pax_emutramp was given.
+if test "${enable_pax_emutramp+set}" = set; then :
+  enableval=$enable_pax_emutramp; if test "$enable_pax_emutramp" = "yes"; then
+
+$as_echo "#define FFI_MMAP_EXEC_EMUTRAMP_PAX 1" >>confdefs.h
+
+  fi
+fi
+
+
+FFI_EXEC_TRAMPOLINE_TABLE=0
+case "$target" in
+     *arm*-apple-darwin*)
+       FFI_EXEC_TRAMPOLINE_TABLE=1
+
+$as_echo "#define FFI_EXEC_TRAMPOLINE_TABLE 1" >>confdefs.h
+
+     ;;
+     *-apple-darwin1* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*)
+
+$as_echo "#define FFI_MMAP_EXEC_WRIT 1" >>confdefs.h
+
+     ;;
+esac
+ if test x$FFI_EXEC_TRAMPOLINE_TABLE = x1; then
+  FFI_EXEC_TRAMPOLINE_TABLE_TRUE=
+  FFI_EXEC_TRAMPOLINE_TABLE_FALSE='#'
+else
+  FFI_EXEC_TRAMPOLINE_TABLE_TRUE='#'
+  FFI_EXEC_TRAMPOLINE_TABLE_FALSE=
+fi
+
+
+
+if test x$TARGET = xX86_64; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports unwind section type" >&5
+$as_echo_n "checking assembler supports unwind section type... " >&6; }
+if test "${libffi_cv_as_x86_64_unwind_section_type+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+	libffi_cv_as_x86_64_unwind_section_type=yes
+	echo '.section .eh_frame,"a",@unwind' > conftest.s
+	CFLAGS_hold=$CFLAGS
+	if test "$libffi_cv_c_unused_arguments" = yes; then
+	    CFLAGS="$CFLAGS -Qunused-arguments"
+	fi
+	if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
+	    libffi_cv_as_x86_64_unwind_section_type=no
+	fi
+	CFLAGS=$CFLAGS_hold
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_x86_64_unwind_section_type" >&5
+$as_echo "$libffi_cv_as_x86_64_unwind_section_type" >&6; }
+    if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then
+
+$as_echo "#define HAVE_AS_X86_64_UNWIND_SECTION_TYPE 1" >>confdefs.h
+
+    fi
+fi
+
+if test "x$GCC" = "xyes"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether .eh_frame section should be read-only" >&5
+$as_echo_n "checking whether .eh_frame section should be read-only... " >&6; }
+if test "${libffi_cv_ro_eh_frame+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  	libffi_cv_ro_eh_frame=no
+  	echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
+  	if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
+  	    if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
+  		libffi_cv_ro_eh_frame=yes
+  	    elif grep '.section.*eh_frame.*#alloc' conftest.c \
+  		 | grep -v '#write' > /dev/null; then
+  		libffi_cv_ro_eh_frame=yes
+  	    fi
+  	fi
+  	rm -f conftest.*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_ro_eh_frame" >&5
+$as_echo "$libffi_cv_ro_eh_frame" >&6; }
+  if test "x$libffi_cv_ro_eh_frame" = xyes; then
+
+$as_echo "#define HAVE_RO_EH_FRAME 1" >>confdefs.h
+
+
+$as_echo "#define EH_FRAME_FLAGS \"a\"" >>confdefs.h
+
+  else
+
+$as_echo "#define EH_FRAME_FLAGS \"aw\"" >>confdefs.h
+
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((visibility(\"hidden\")))" >&5
+$as_echo_n "checking for __attribute__((visibility(\"hidden\")))... " >&6; }
+if test "${libffi_cv_hidden_visibility_attribute+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  	echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1  ; }' > conftest.c
+  	libffi_cv_hidden_visibility_attribute=no
+  	if { ac_try='${CC-cc} -Werror -S conftest.c -o conftest.s 1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+  	    if grep '\.hidden.*foo' conftest.s >/dev/null; then
+  		libffi_cv_hidden_visibility_attribute=yes
+  	    fi
+  	fi
+  	rm -f conftest.*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_hidden_visibility_attribute" >&5
+$as_echo "$libffi_cv_hidden_visibility_attribute" >&6; }
+  if test $libffi_cv_hidden_visibility_attribute = yes; then
+
+$as_echo "#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1" >>confdefs.h
+
+  fi
+fi
+
+
+
+
+
+
+
+
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then :
+  enableval=$enable_debug; if test "$enable_debug" = "yes"; then
+
+$as_echo "#define FFI_DEBUG 1" >>confdefs.h
+
+  fi
+fi
+
+ if test "$enable_debug" = "yes"; then
+  FFI_DEBUG_TRUE=
+  FFI_DEBUG_FALSE='#'
+else
+  FFI_DEBUG_TRUE='#'
+  FFI_DEBUG_FALSE=
+fi
+
+
+# Check whether --enable-structs was given.
+if test "${enable_structs+set}" = set; then :
+  enableval=$enable_structs; if test "$enable_structs" = "no"; then
+
+$as_echo "#define FFI_NO_STRUCTS 1" >>confdefs.h
+
+  fi
+fi
+
+
+# Check whether --enable-raw-api was given.
+if test "${enable_raw_api+set}" = set; then :
+  enableval=$enable_raw_api; if test "$enable_raw_api" = "no"; then
+
+$as_echo "#define FFI_NO_RAW_API 1" >>confdefs.h
+
+  fi
+fi
+
+
+# Check whether --enable-purify-safety was given.
+if test "${enable_purify_safety+set}" = set; then :
+  enableval=$enable_purify_safety; if test "$enable_purify_safety" = "yes"; then
+
+$as_echo "#define USING_PURIFY 1" >>confdefs.h
+
+  fi
+fi
+
+
+if test -n "$with_cross_host" &&
+   test x"$with_cross_host" != x"no"; then
+  toolexecdir='$(exec_prefix)/$(target_alias)'
+  toolexeclibdir='$(toolexecdir)/lib'
+else
+  toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
+  toolexeclibdir='$(libdir)'
+fi
+multi_os_directory=`$CC -print-multi-os-directory`
+case $multi_os_directory in
+  .) ;; # Avoid trailing /.
+  *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
+esac
+
+
+
+if test "${multilib}" = "yes"; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+ac_config_commands="$ac_config_commands include"
+
+ac_config_commands="$ac_config_commands src"
+
+
+ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h"
+
+
+ac_config_files="$ac_config_files include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${BUILD_INFO_TRUE}" && test -z "${BUILD_INFO_FALSE}"; then
+  as_fn_error "conditional \"BUILD_INFO\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${GENINSRC_TRUE}" && test -z "${GENINSRC_FALSE}"; then
+  as_fn_error "conditional \"GENINSRC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  as_fn_error "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then
+  as_fn_error "conditional \"am__fastdepCCAS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+  as_fn_error "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${TESTSUBDIR_TRUE}" && test -z "${TESTSUBDIR_FALSE}"; then
+  as_fn_error "conditional \"TESTSUBDIR\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MIPS_TRUE}" && test -z "${MIPS_FALSE}"; then
+  as_fn_error "conditional \"MIPS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BFIN_TRUE}" && test -z "${BFIN_FALSE}"; then
+  as_fn_error "conditional \"BFIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${SPARC_TRUE}" && test -z "${SPARC_FALSE}"; then
+  as_fn_error "conditional \"SPARC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${X86_TRUE}" && test -z "${X86_FALSE}"; then
+  as_fn_error "conditional \"X86\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${X86_FREEBSD_TRUE}" && test -z "${X86_FREEBSD_FALSE}"; then
+  as_fn_error "conditional \"X86_FREEBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${X86_WIN32_TRUE}" && test -z "${X86_WIN32_FALSE}"; then
+  as_fn_error "conditional \"X86_WIN32\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${X86_WIN64_TRUE}" && test -z "${X86_WIN64_FALSE}"; then
+  as_fn_error "conditional \"X86_WIN64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${X86_DARWIN_TRUE}" && test -z "${X86_DARWIN_FALSE}"; then
+  as_fn_error "conditional \"X86_DARWIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ALPHA_TRUE}" && test -z "${ALPHA_FALSE}"; then
+  as_fn_error "conditional \"ALPHA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${IA64_TRUE}" && test -z "${IA64_FALSE}"; then
+  as_fn_error "conditional \"IA64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${M32R_TRUE}" && test -z "${M32R_FALSE}"; then
+  as_fn_error "conditional \"M32R\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${M68K_TRUE}" && test -z "${M68K_FALSE}"; then
+  as_fn_error "conditional \"M68K\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${POWERPC_TRUE}" && test -z "${POWERPC_FALSE}"; then
+  as_fn_error "conditional \"POWERPC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${POWERPC_AIX_TRUE}" && test -z "${POWERPC_AIX_FALSE}"; then
+  as_fn_error "conditional \"POWERPC_AIX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${POWERPC_DARWIN_TRUE}" && test -z "${POWERPC_DARWIN_FALSE}"; then
+  as_fn_error "conditional \"POWERPC_DARWIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${POWERPC_FREEBSD_TRUE}" && test -z "${POWERPC_FREEBSD_FALSE}"; then
+  as_fn_error "conditional \"POWERPC_FREEBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${AARCH64_TRUE}" && test -z "${AARCH64_FALSE}"; then
+  as_fn_error "conditional \"AARCH64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ARM_TRUE}" && test -z "${ARM_FALSE}"; then
+  as_fn_error "conditional \"ARM\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${AVR32_TRUE}" && test -z "${AVR32_FALSE}"; then
+  as_fn_error "conditional \"AVR32\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBFFI_CRIS_TRUE}" && test -z "${LIBFFI_CRIS_FALSE}"; then
+  as_fn_error "conditional \"LIBFFI_CRIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${FRV_TRUE}" && test -z "${FRV_FALSE}"; then
+  as_fn_error "conditional \"FRV\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${S390_TRUE}" && test -z "${S390_FALSE}"; then
+  as_fn_error "conditional \"S390\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${X86_64_TRUE}" && test -z "${X86_64_FALSE}"; then
+  as_fn_error "conditional \"X86_64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${SH_TRUE}" && test -z "${SH_FALSE}"; then
+  as_fn_error "conditional \"SH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${SH64_TRUE}" && test -z "${SH64_FALSE}"; then
+  as_fn_error "conditional \"SH64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PA_LINUX_TRUE}" && test -z "${PA_LINUX_FALSE}"; then
+  as_fn_error "conditional \"PA_LINUX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PA_HPUX_TRUE}" && test -z "${PA_HPUX_FALSE}"; then
+  as_fn_error "conditional \"PA_HPUX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PA64_HPUX_TRUE}" && test -z "${PA64_HPUX_FALSE}"; then
+  as_fn_error "conditional \"PA64_HPUX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${TILE_TRUE}" && test -z "${TILE_FALSE}"; then
+  as_fn_error "conditional \"TILE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+if test -z "${FFI_EXEC_TRAMPOLINE_TABLE_TRUE}" && test -z "${FFI_EXEC_TRAMPOLINE_TABLE_FALSE}"; then
+  as_fn_error "conditional \"FFI_EXEC_TRAMPOLINE_TABLE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${FFI_DEBUG_TRUE}" && test -z "${FFI_DEBUG_FALSE}"; then
+  as_fn_error "conditional \"FFI_DEBUG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by libffi $as_me 3.0.11, which was
+generated by GNU Autoconf 2.64.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_links="$ac_config_links"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration links:
+$config_links
+
+Configuration commands:
+$config_commands
+
+Report bugs to <http://gcc.gnu.org/bugs.html>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+libffi config.status 3.0.11
+configured by $0, generated by GNU Autoconf 2.64,
+  with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+
+srcdir="$srcdir"
+host="$host"
+target="$target"
+with_multisubdir="$with_multisubdir"
+with_multisrctop="$with_multisrctop"
+with_target_subdir="$with_target_subdir"
+ac_configure_args="${multilib_arg} ${ac_configure_args}"
+multi_basedir="$multi_basedir"
+CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+CC="$CC"
+CXX="$CXX"
+GFORTRAN="$GFORTRAN"
+GCJ="$GCJ"
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+fix_srcfile_path='`$ECHO "$fix_srcfile_path" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in SHELL \
+ECHO \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+AR \
+AR_FLAGS \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_wl \
+lt_prog_compiler_pic \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_flag_spec_ld \
+hardcode_libdir_separator \
+fix_srcfile_path \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'
+
+
+
+TARGETDIR="$TARGETDIR"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "fficonfig.h") CONFIG_HEADERS="$CONFIG_HEADERS fficonfig.h" ;;
+    "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "include") CONFIG_COMMANDS="$CONFIG_COMMANDS include" ;;
+    "src") CONFIG_COMMANDS="$CONFIG_COMMANDS src" ;;
+    "include/ffitarget.h") CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETDIR/ffitarget.h" ;;
+    "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+    "include/ffi.h") CONFIG_FILES="$CONFIG_FILES include/ffi.h" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;;
+    "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
+
+  *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\).*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\).*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || as_fn_error "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_t"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS  :L $CONFIG_LINKS  :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+    } >"$tmp/config.h" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$tmp/config.h" "$ac_file" \
+	|| as_fn_error "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+  :L)
+  #
+  # CONFIG_LINK
+  #
+
+  if test "$ac_source" = "$ac_file" && test "$srcdir" = '.'; then
+    :
+  else
+    # Prefer the file from the source tree if names are identical.
+    if test "$ac_source" = "$ac_file" || test ! -r "$ac_source"; then
+      ac_source=$srcdir/$ac_source
+    fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: linking $ac_source to $ac_file" >&5
+$as_echo "$as_me: linking $ac_source to $ac_file" >&6;}
+
+    if test ! -r "$ac_source"; then
+      as_fn_error "$ac_source: file not found" "$LINENO" 5
+    fi
+    rm -f "$ac_file"
+
+    # Try a relative symlink, then a hard link, then a copy.
+    case $srcdir in
+    [\\/$]* | ?:[\\/]* ) ac_rel_source=$ac_source ;;
+	*) ac_rel_source=$ac_top_build_prefix$ac_source ;;
+    esac
+    ln -s "$ac_rel_source" "$ac_file" 2>/dev/null ||
+      ln "$ac_source" "$ac_file" 2>/dev/null ||
+      cp -p "$ac_source" "$ac_file" ||
+      as_fn_error "cannot link or copy $ac_source to $ac_file" "$LINENO" 5
+  fi
+ ;;
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "default-1":C)
+# Only add multilib support code if we just rebuilt the top-level
+# Makefile.
+case " $CONFIG_FILES " in
+ *" Makefile "*)
+   ac_file=Makefile . ${multi_basedir}/config-ml.in
+   ;;
+esac ;;
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named `Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$mf" : 'X\(//\)[^/]' \| \
+	 X"$mf" : 'X\(//\)$' \| \
+	 X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running `make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # When using ansi2knr, U may be empty or an underscore; expand it
+    U=`sed -n 's/^U = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$file" : 'X\(//\)[^/]' \| \
+	 X"$file" : 'X\(//\)$' \| \
+	 X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      as_dir=$dirpart/$fdir; as_fn_mkdir_p
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+ ;;
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=""
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking.  This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  case $xsi_shell in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+  func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+  # positional parameters, so assign one to ordinary parameter first.
+  func_stripname_result=${3}
+  func_stripname_result=${func_stripname_result#"${1}"}
+  func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=${1%%=*}
+  func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  case ${1} in
+    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+    *)    func_lo2o_result=${1} ;;
+  esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=$(( $* ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=${#1}
+}
+
+_LT_EOF
+    ;;
+  *) # Bourne compatible functions.
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result=`$ECHO "${1}" | $SED "$basename"`
+}
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+  case ${2} in
+    .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+    *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+  esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[^=]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=`$ECHO "${1}" | $SED "$my_sed_long_opt"`
+  func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=`expr "$@"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$1+=\$2"
+}
+_LT_EOF
+    ;;
+  *)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$1=\$$1\$2"
+}
+
+_LT_EOF
+    ;;
+  esac
+
+
+  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+ ;;
+    "include":C) test -d include || mkdir include ;;
+    "src":C)
+test -d src || mkdir src
+test -d src/$TARGETDIR || mkdir src/$TARGETDIR
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit $?
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/third_party/gofrontend/libffi/configure.ac b/third_party/gofrontend/libffi/configure.ac
new file mode 100644
index 0000000..97d2641
--- /dev/null
+++ b/third_party/gofrontend/libffi/configure.ac
@@ -0,0 +1,549 @@
+dnl Process this with autoconf to create configure
+
+AC_PREREQ(2.64)
+
+AC_INIT([libffi], [3.0.11], [http://gcc.gnu.org/bugs.html])
+AC_CONFIG_HEADERS([fficonfig.h])
+
+AM_ENABLE_MULTILIB(, ..)
+
+AC_CANONICAL_SYSTEM
+target_alias=${target_alias-$host_alias}
+
+. ${srcdir}/configure.host
+
+AM_INIT_AUTOMAKE([no-dist])
+
+# See if makeinfo has been installed and is modern enough
+# that we can use it.
+ACX_CHECK_PROG_VER([MAKEINFO], [makeinfo], [--version],
+                   [GNU texinfo.* \([0-9][0-9.]*\)],
+                   [4.[4-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*])
+AM_CONDITIONAL(BUILD_INFO, test $gcc_cv_prog_makeinfo_modern = "yes")
+
+# We would like our source tree to be readonly. However when releases or
+# pre-releases are generated, the flex/bison generated files as well as the
+# various formats of manuals need to be included along with the rest of the
+# sources.  Therefore we have --enable-generated-files-in-srcdir to do
+# just that.
+AC_MSG_CHECKING(generated-files-in-srcdir)
+AC_ARG_ENABLE(generated-files-in-srcdir,
+AS_HELP_STRING([--enable-generated-files-in-srcdir],
+ [put copies of generated files in source dir intended for creating source tarballs for users without texinfo bison or flex]),
+[case "$enableval" in
+ yes) enable_generated_files_in_srcdir=yes ;;
+ no)  enable_generated_files_in_srcdir=no ;;
+ *)   AC_MSG_ERROR([Unknown argument to enable/disable version-specific libs]);;
+ esac],
+[enable_generated_files_in_srcdir=no])
+AC_MSG_RESULT($enable_generated_files_in_srcdir)
+AM_CONDITIONAL(GENINSRC, test "$enable_generated_files_in_srcdir" = yes)
+
+# The same as in boehm-gc and libstdc++. Have to borrow it from there.
+# We must force CC to /not/ be precious variables; otherwise
+# the wrong, non-multilib-adjusted value will be used in multilibs.
+# As a side effect, we have to subst CFLAGS ourselves.
+
+m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
+m4_define([_AC_ARG_VAR_PRECIOUS],[])
+AC_PROG_CC
+m4_rename_force([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
+
+AC_SUBST(CFLAGS)
+
+AM_PROG_AS
+AM_PROG_CC_C_O
+AC_PROG_LIBTOOL
+
+AM_MAINTAINER_MODE
+
+AC_CHECK_HEADERS(sys/mman.h)
+AC_CHECK_FUNCS(mmap)
+AC_FUNC_MMAP_BLACKLIST
+
+dnl The -no-testsuite modules omit the test subdir.
+AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
+
+TARGETDIR="unknown"
+HAVE_LONG_DOUBLE_VARIANT=0
+case "$host" in
+  aarch64*-*-*)
+	TARGET=AARCH64; TARGETDIR=aarch64
+	;;
+
+  alpha*-*-*)
+	TARGET=ALPHA; TARGETDIR=alpha;
+	# Support 128-bit long double, changeable via command-line switch.
+	HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
+	;;
+
+  arm*-*-*)
+	TARGET=ARM; TARGETDIR=arm
+	;;
+
+  amd64-*-freebsd* | amd64-*-openbsd*)
+	TARGET=X86_64; TARGETDIR=x86
+  	;;
+
+  amd64-*-freebsd*)
+	TARGET=X86_64; TARGETDIR=x86
+	;;
+
+  avr32*-*-*)
+	TARGET=AVR32; TARGETDIR=avr32
+	;;
+
+  bfin*)
+  	TARGET=BFIN; TARGETDIR=bfin
+  	;;
+
+  cris-*-*)
+	TARGET=LIBFFI_CRIS; TARGETDIR=cris
+	;;
+
+  frv-*-*)
+	TARGET=FRV; TARGETDIR=frv
+	;;
+
+  hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
+	TARGET=PA_LINUX; TARGETDIR=pa
+	;;
+  hppa*64-*-hpux*)
+	TARGET=PA64_HPUX; TARGETDIR=pa
+	;;
+  hppa*-*-hpux*)
+	TARGET=PA_HPUX; TARGETDIR=pa
+	;;
+
+  i?86-*-freebsd* | i?86-*-openbsd*)
+	TARGET=X86_FREEBSD; TARGETDIR=x86
+	;;
+  i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*)
+	TARGET=X86_WIN32; TARGETDIR=x86
+	# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
+	# We must also check with_cross_host to decide if this is a native
+	# or cross-build and select where to install dlls appropriately.
+	if test -n "$with_cross_host" &&
+	   test x"$with_cross_host" != x"no"; then
+	  AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
+	else
+	  AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
+	fi
+	;;
+  i?86-*-darwin*)
+	TARGET=X86_DARWIN; TARGETDIR=x86
+	;;
+  i?86-*-solaris2.1[[0-9]]*)
+	TARGET=X86_64; TARGETDIR=x86
+	;;
+  i?86-*-*)
+	TARGET=X86_64; TARGETDIR=x86
+	;;
+
+  ia64*-*-*)
+	TARGET=IA64; TARGETDIR=ia64
+	;;
+
+  m32r*-*-*)
+	TARGET=M32R; TARGETDIR=m32r
+	;;
+
+  m68k-*-*)
+	TARGET=M68K; TARGETDIR=m68k
+	;;
+
+  mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
+	TARGET=MIPS; TARGETDIR=mips
+	;;
+  mips*-*-linux* | mips*-*-openbsd*)
+	# Support 128-bit long double for NewABI.
+	HAVE_LONG_DOUBLE='defined(__mips64)'
+	TARGET=MIPS; TARGETDIR=mips
+	;;
+
+  powerpc*-*-linux* | powerpc-*-sysv*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	HAVE_LONG_DOUBLE_VARIANT=1
+	;;
+  powerpc-*-amigaos*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+  powerpc-*-beos*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+  powerpc-*-darwin* | powerpc64-*-darwin*)
+	TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
+	;;
+  powerpc-*-aix* | rs6000-*-aix*)
+	TARGET=POWERPC_AIX; TARGETDIR=powerpc
+	;;
+  powerpc-*-freebsd* | powerpc-*-openbsd*)
+	TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
+	HAVE_LONG_DOUBLE_VARIANT=1
+	;;
+  powerpc64-*-freebsd*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+  powerpc*-*-rtems*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+
+  s390-*-* | s390x-*-*)
+	TARGET=S390; TARGETDIR=s390
+	;;
+
+  sh-*-* | sh[[34]]*-*-*)
+	TARGET=SH; TARGETDIR=sh
+	;;
+  sh64-*-* | sh5*-*-*)
+	TARGET=SH64; TARGETDIR=sh64
+	;;
+
+  sparc*-*-*)
+	TARGET=SPARC; TARGETDIR=sparc
+	;;
+
+  tile*-*)
+        TARGET=TILE; TARGETDIR=tile
+        ;;
+
+  x86_64-*-darwin*)
+	TARGET=X86_DARWIN; TARGETDIR=x86
+	;;
+
+  x86_64-*-cygwin* | x86_64-*-mingw*)
+	TARGET=X86_WIN64; TARGETDIR=x86
+	# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
+	# We must also check with_cross_host to decide if this is a native
+	# or cross-build and select where to install dlls appropriately.
+	if test -n "$with_cross_host" &&
+	   test x"$with_cross_host" != x"no"; then
+	  AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
+	else
+	  AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
+	fi
+	;;
+
+  x86_64-*-*)
+	TARGET=X86_64; TARGETDIR=x86
+	;;
+esac
+
+AC_SUBST(AM_RUNTESTFLAGS)
+AC_SUBST(AM_LTLDFLAGS)
+
+if test $TARGETDIR = unknown; then
+  AC_MSG_ERROR(["libffi has not been ported to $host."])
+fi
+
+AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
+AM_CONDITIONAL(BFIN, test x$TARGET = xBFIN)
+AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
+AM_CONDITIONAL(X86, test x$TARGET = xX86)
+AM_CONDITIONAL(X86_FREEBSD, test x$TARGET = xX86_FREEBSD)
+AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
+AM_CONDITIONAL(X86_WIN64, test x$TARGET = xX86_WIN64)
+AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
+AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
+AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
+AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
+AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
+AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
+AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
+AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
+AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
+AM_CONDITIONAL(AARCH64, test x$TARGET = xAARCH64)
+AM_CONDITIONAL(ARM, test x$TARGET = xARM)
+AM_CONDITIONAL(AVR32, test x$TARGET = xAVR32)
+AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
+AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
+AM_CONDITIONAL(S390, test x$TARGET = xS390)
+AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
+AM_CONDITIONAL(SH, test x$TARGET = xSH)
+AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
+AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
+AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
+AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
+AM_CONDITIONAL(TILE, test x$TARGET = xTILE)
+
+AC_HEADER_STDC
+AC_CHECK_FUNCS(memcpy)
+AC_FUNC_ALLOCA
+
+AC_CHECK_SIZEOF(double)
+AC_CHECK_SIZEOF(long double)
+
+# Also AC_SUBST this variable for ffi.h.
+if test -z "$HAVE_LONG_DOUBLE"; then
+  HAVE_LONG_DOUBLE=0
+  if test $ac_cv_sizeof_long_double != 0; then
+    if test $HAVE_LONG_DOUBLE_VARIANT != 0; then
+      AC_DEFINE(HAVE_LONG_DOUBLE_VARIANT, 1, [Define if you support more than one size of the long double type])
+      HAVE_LONG_DOUBLE=1
+    else
+      if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
+        HAVE_LONG_DOUBLE=1
+        AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the long double type and it is bigger than a double])
+      fi
+    fi
+  fi
+fi
+AC_SUBST(HAVE_LONG_DOUBLE)
+AC_SUBST(HAVE_LONG_DOUBLE_VARIANT)
+
+AC_C_BIGENDIAN
+
+GCC_AS_CFI_PSEUDO_OP
+
+AC_CACHE_CHECK([if compiler supports -Qunused-arguments],
+[libffi_cv_c_unused_arguments],
+[CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -Qunused-arguments"
+AC_COMPILE_IFELSE([[int i;]],
+[libffi_cv_c_unused_arguments=yes],
+[libffi_cv_c_unused_arguments=no])
+CFLAGS=$CFLAGS_hold])
+
+if test x$TARGET = xSPARC; then
+    AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
+	libffi_cv_as_sparc_ua_pcrel, [
+	save_CFLAGS="$CFLAGS"
+	save_LDFLAGS="$LDFLAGS"
+	CFLAGS="$CFLAGS -fpic"
+	LDFLAGS="$LDFLAGS -shared"
+	AC_TRY_LINK([asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");],,
+		    [libffi_cv_as_sparc_ua_pcrel=yes],
+		    [libffi_cv_as_sparc_ua_pcrel=no])
+	CFLAGS="$save_CFLAGS"
+	LDFLAGS="$save_LDFLAGS"])
+    if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
+	AC_DEFINE(HAVE_AS_SPARC_UA_PCREL, 1,
+		  [Define if your assembler and linker support unaligned PC relative relocs.])
+    fi
+
+    AC_CACHE_CHECK([assembler .register pseudo-op support],
+       libffi_cv_as_register_pseudo_op, [
+       libffi_cv_as_register_pseudo_op=unknown
+       # Check if we have .register
+       AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
+		       [libffi_cv_as_register_pseudo_op=yes],
+		       [libffi_cv_as_register_pseudo_op=no])
+    ])
+    if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
+       AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1,
+	       [Define if your assembler supports .register.])
+    fi
+fi
+
+if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then
+    AC_CACHE_CHECK([assembler supports pc related relocs],
+	libffi_cv_as_x86_pcrel, [
+	libffi_cv_as_x86_pcrel=yes
+	echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
+	CFLAGS_hold=$CFLAGS
+	if test "$libffi_cv_c_unused_arguments" = yes; then
+	    CFLAGS="$CFLAGS -Qunused-arguments"
+	fi
+	if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
+	    libffi_cv_as_x86_pcrel=no
+	fi
+	CFLAGS=$CFLAGS_hold
+	])
+    if test "x$libffi_cv_as_x86_pcrel" = xyes; then
+	AC_DEFINE(HAVE_AS_X86_PCREL, 1,
+		  [Define if your assembler supports PC relative relocs.])
+    fi
+
+    AC_CACHE_CHECK([assembler .ascii pseudo-op support],
+       libffi_cv_as_ascii_pseudo_op, [
+       libffi_cv_as_ascii_pseudo_op=unknown
+       # Check if we have .ascii
+       AC_TRY_COMPILE([asm (".ascii \\"string\\"");],,
+		       [libffi_cv_as_ascii_pseudo_op=yes],
+		       [libffi_cv_as_ascii_pseudo_op=no])
+    ])
+    if test "x$libffi_cv_as_ascii_pseudo_op" = xyes; then
+       AC_DEFINE(HAVE_AS_ASCII_PSEUDO_OP, 1,
+	       [Define if your assembler supports .ascii.])
+    fi
+
+    AC_CACHE_CHECK([assembler .string pseudo-op support],
+       libffi_cv_as_string_pseudo_op, [
+       libffi_cv_as_string_pseudo_op=unknown
+       # Check if we have .string
+       AC_TRY_COMPILE([asm (".string \\"string\\"");],,
+		       [libffi_cv_as_string_pseudo_op=yes],
+		       [libffi_cv_as_string_pseudo_op=no])
+    ])
+    if test "x$libffi_cv_as_string_pseudo_op" = xyes; then
+       AC_DEFINE(HAVE_AS_STRING_PSEUDO_OP, 1,
+	       [Define if your assembler supports .string.])
+    fi
+fi
+
+# On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC.
+AC_ARG_ENABLE(pax_emutramp,
+  [  --enable-pax_emutramp       enable pax emulated trampolines, for we can't use PROT_EXEC],
+  if test "$enable_pax_emutramp" = "yes"; then
+    AC_DEFINE(FFI_MMAP_EXEC_EMUTRAMP_PAX, 1,
+      [Define this if you want to enable pax emulated trampolines])
+  fi)
+
+FFI_EXEC_TRAMPOLINE_TABLE=0
+case "$target" in
+     *arm*-apple-darwin*)
+       FFI_EXEC_TRAMPOLINE_TABLE=1
+       AC_DEFINE(FFI_EXEC_TRAMPOLINE_TABLE, 1,
+                 [Cannot use PROT_EXEC on this target, so, we revert to
+                   alternative means])
+     ;;
+     *-apple-darwin1* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*)
+       AC_DEFINE(FFI_MMAP_EXEC_WRIT, 1,
+                 [Cannot use malloc on this target, so, we revert to
+                   alternative means])
+     ;;
+esac
+AM_CONDITIONAL(FFI_EXEC_TRAMPOLINE_TABLE, test x$FFI_EXEC_TRAMPOLINE_TABLE = x1)
+AC_SUBST(FFI_EXEC_TRAMPOLINE_TABLE)
+
+if test x$TARGET = xX86_64; then
+    AC_CACHE_CHECK([assembler supports unwind section type],
+	libffi_cv_as_x86_64_unwind_section_type, [
+	libffi_cv_as_x86_64_unwind_section_type=yes
+	echo '.section .eh_frame,"a",@unwind' > conftest.s
+	CFLAGS_hold=$CFLAGS
+	if test "$libffi_cv_c_unused_arguments" = yes; then
+	    CFLAGS="$CFLAGS -Qunused-arguments"
+	fi
+	if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
+	    libffi_cv_as_x86_64_unwind_section_type=no
+	fi
+	CFLAGS=$CFLAGS_hold
+	])
+    if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then
+	AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
+		  [Define if your assembler supports unwind section type.])
+    fi
+fi
+
+if test "x$GCC" = "xyes"; then
+  AC_CACHE_CHECK([whether .eh_frame section should be read-only],
+      libffi_cv_ro_eh_frame, [
+  	libffi_cv_ro_eh_frame=no
+  	echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
+  	if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
+  	    if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
+  		libffi_cv_ro_eh_frame=yes
+  	    elif grep '.section.*eh_frame.*#alloc' conftest.c \
+  		 | grep -v '#write' > /dev/null; then
+  		libffi_cv_ro_eh_frame=yes
+  	    fi
+  	fi
+  	rm -f conftest.*
+      ])
+  if test "x$libffi_cv_ro_eh_frame" = xyes; then
+      AC_DEFINE(HAVE_RO_EH_FRAME, 1,
+  	      [Define if .eh_frame sections should be read-only.])
+      AC_DEFINE(EH_FRAME_FLAGS, "a",
+  	      [Define to the flags needed for the .section .eh_frame directive.  ])
+  else
+      AC_DEFINE(EH_FRAME_FLAGS, "aw",
+  	      [Define to the flags needed for the .section .eh_frame directive.  ])
+  fi
+
+  AC_CACHE_CHECK([for __attribute__((visibility("hidden")))],
+      libffi_cv_hidden_visibility_attribute, [
+  	echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1  ; }' > conftest.c
+  	libffi_cv_hidden_visibility_attribute=no
+  	if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
+  	    if grep '\.hidden.*foo' conftest.s >/dev/null; then
+  		libffi_cv_hidden_visibility_attribute=yes
+  	    fi
+  	fi
+  	rm -f conftest.*
+      ])
+  if test $libffi_cv_hidden_visibility_attribute = yes; then
+      AC_DEFINE(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE, 1,
+  	      [Define if __attribute__((visibility("hidden"))) is supported.])
+  fi
+fi
+
+AH_BOTTOM([
+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name) .hidden name
+#else
+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
+#endif
+#else
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name)
+#else
+#define FFI_HIDDEN
+#endif
+#endif
+])
+
+AC_SUBST(TARGET)
+AC_SUBST(TARGETDIR)
+
+AC_SUBST(SHELL)
+
+AC_ARG_ENABLE(debug,
+[  --enable-debug          debugging mode],
+  if test "$enable_debug" = "yes"; then
+    AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.])
+  fi)
+AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
+
+AC_ARG_ENABLE(structs,
+[  --disable-structs       omit code for struct support],
+  if test "$enable_structs" = "no"; then
+    AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
+  fi)
+
+AC_ARG_ENABLE(raw-api,
+[  --disable-raw-api       make the raw api unavailable],
+  if test "$enable_raw_api" = "no"; then
+    AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
+  fi)
+
+AC_ARG_ENABLE(purify-safety,
+[  --enable-purify-safety  purify-safe mode],
+  if test "$enable_purify_safety" = "yes"; then
+    AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.])
+  fi)
+
+if test -n "$with_cross_host" &&
+   test x"$with_cross_host" != x"no"; then
+  toolexecdir='$(exec_prefix)/$(target_alias)'
+  toolexeclibdir='$(toolexecdir)/lib'
+else
+  toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
+  toolexeclibdir='$(libdir)'
+fi
+multi_os_directory=`$CC -print-multi-os-directory`
+case $multi_os_directory in
+  .) ;; # Avoid trailing /.
+  *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
+esac
+AC_SUBST(toolexecdir)
+AC_SUBST(toolexeclibdir)
+
+if test "${multilib}" = "yes"; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+AC_CONFIG_COMMANDS(include, [test -d include || mkdir include])
+AC_CONFIG_COMMANDS(src, [
+test -d src || mkdir src
+test -d src/$TARGETDIR || mkdir src/$TARGETDIR
+], [TARGETDIR="$TARGETDIR"])
+
+AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
+
+AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile)
+
+AC_OUTPUT
diff --git a/third_party/gofrontend/libffi/configure.host b/third_party/gofrontend/libffi/configure.host
new file mode 100644
index 0000000..f52457b
--- /dev/null
+++ b/third_party/gofrontend/libffi/configure.host
@@ -0,0 +1,11 @@
+# configure.host
+#
+# This shell script handles all host based configuration for libffi.
+# 
+
+# THIS TABLE IS SORTED.  KEEP IT THAT WAY.
+case "${host}" in
+  frv*-elf)
+    LDFLAGS=`echo $LDFLAGS | sed "s/\-B[^ ]*libgloss\/frv\///"`\ -B`pwd`/../libgloss/frv/
+    ;;
+esac
diff --git a/third_party/gofrontend/libffi/doc/libffi.texi b/third_party/gofrontend/libffi/doc/libffi.texi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/gofrontend/libffi/doc/libffi.texi
diff --git a/third_party/gofrontend/libffi/doc/stamp-vti b/third_party/gofrontend/libffi/doc/stamp-vti
new file mode 100644
index 0000000..b9b2131
--- /dev/null
+++ b/third_party/gofrontend/libffi/doc/stamp-vti
@@ -0,0 +1,4 @@
+@set UPDATED 6 March 2012
+@set UPDATED-MONTH March 2012
+@set EDITION 3.0.11
+@set VERSION 3.0.11
diff --git a/third_party/gofrontend/libffi/doc/version.texi b/third_party/gofrontend/libffi/doc/version.texi
new file mode 100644
index 0000000..b9b2131
--- /dev/null
+++ b/third_party/gofrontend/libffi/doc/version.texi
@@ -0,0 +1,4 @@
+@set UPDATED 6 March 2012
+@set UPDATED-MONTH March 2012
+@set EDITION 3.0.11
+@set VERSION 3.0.11
diff --git a/third_party/gofrontend/libffi/fficonfig.h.in b/third_party/gofrontend/libffi/fficonfig.h.in
new file mode 100644
index 0000000..19d66d0
--- /dev/null
+++ b/third_party/gofrontend/libffi/fficonfig.h.in
@@ -0,0 +1,202 @@
+/* fficonfig.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to the flags needed for the .section .eh_frame directive. */
+#undef EH_FRAME_FLAGS
+
+/* Define this if you want extra debugging. */
+#undef FFI_DEBUG
+
+/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
+#undef FFI_EXEC_TRAMPOLINE_TABLE
+
+/* Define this if you want to enable pax emulated trampolines */
+#undef FFI_MMAP_EXEC_EMUTRAMP_PAX
+
+/* Cannot use malloc on this target, so, we revert to alternative means */
+#undef FFI_MMAP_EXEC_WRIT
+
+/* Define this is you do not want support for the raw API. */
+#undef FFI_NO_RAW_API
+
+/* Define this is you do not want support for aggregate types. */
+#undef FFI_NO_STRUCTS
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#undef HAVE_ALLOCA_H
+
+/* Define if your assembler supports .ascii. */
+#undef HAVE_AS_ASCII_PSEUDO_OP
+
+/* Define if your assembler supports .cfi_* directives. */
+#undef HAVE_AS_CFI_PSEUDO_OP
+
+/* Define if your assembler supports .register. */
+#undef HAVE_AS_REGISTER_PSEUDO_OP
+
+/* Define if your assembler and linker support unaligned PC relative relocs.
+   */
+#undef HAVE_AS_SPARC_UA_PCREL
+
+/* Define if your assembler supports .string. */
+#undef HAVE_AS_STRING_PSEUDO_OP
+
+/* Define if your assembler supports unwind section type. */
+#undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE
+
+/* Define if your assembler supports PC relative relocs. */
+#undef HAVE_AS_X86_PCREL
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define if __attribute__((visibility("hidden"))) is supported. */
+#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if you have the long double type and it is bigger than a double */
+#undef HAVE_LONG_DOUBLE
+
+/* Define if you support more than one size of the long double type */
+#undef HAVE_LONG_DOUBLE_VARIANT
+
+/* Define to 1 if you have the `memcpy' function. */
+#undef HAVE_MEMCPY
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* Define if mmap with MAP_ANON(YMOUS) works. */
+#undef HAVE_MMAP_ANON
+
+/* Define if mmap of /dev/zero works. */
+#undef HAVE_MMAP_DEV_ZERO
+
+/* Define if read-only mmap of a plain file works. */
+#undef HAVE_MMAP_FILE
+
+/* Define if .eh_frame sections should be read-only. */
+#undef HAVE_RO_EH_FRAME
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of `double', as computed by sizeof. */
+#undef SIZEOF_DOUBLE
+
+/* The size of `long double', as computed by sizeof. */
+#undef SIZEOF_LONG_DOUBLE
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define this if you are using Purify and want to suppress spurious messages.
+   */
+#undef USING_PURIFY
+
+/* Version number of package */
+#undef VERSION
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+#  undef WORDS_BIGENDIAN
+# endif
+#endif
+
+
+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name) .hidden name
+#else
+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
+#endif
+#else
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name)
+#else
+#define FFI_HIDDEN
+#endif
+#endif
+
diff --git a/third_party/gofrontend/libffi/generate-ios-source-and-headers.py b/third_party/gofrontend/libffi/generate-ios-source-and-headers.py
new file mode 100644
index 0000000..c2bca73
--- /dev/null
+++ b/third_party/gofrontend/libffi/generate-ios-source-and-headers.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+import subprocess
+import re
+import os
+import errno
+import collections
+import sys
+
+class Platform(object):
+    pass
+
+sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)')
+
+def sdkinfo(sdkname):
+    ret = {}
+    for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout:
+        kv = line.strip().split(': ', 1)
+        if len(kv) == 2:
+            k,v = kv
+            ret[k] = v
+    return ret
+
+sim_sdk_info = sdkinfo('iphonesimulator')
+device_sdk_info = sdkinfo('iphoneos')
+
+def latest_sdks():
+    latest_sim = None
+    latest_device = None
+    for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout:
+        match = sdk_re.match(line)
+        if match:
+            if 'Simulator' in line:
+                latest_sim = match.group(1)
+            elif 'iOS' in line:
+                latest_device = match.group(1)
+
+    return latest_sim, latest_device
+
+sim_sdk, device_sdk = latest_sdks()
+
+class simulator_platform(Platform):
+    sdk='iphonesimulator'
+    arch = 'i386'
+    name = 'simulator'
+    triple = 'i386-apple-darwin10'
+    sdkroot = sim_sdk_info['Path']
+
+    prefix = "#if !defined(__arm__) && defined(__i386__)\n\n"
+    suffix = "\n\n#endif"
+
+class device_platform(Platform):
+    sdk='iphoneos'
+    name = 'ios'
+    arch = 'armv7'
+    triple = 'arm-apple-darwin10'
+    sdkroot = device_sdk_info['Path']
+
+    prefix = "#ifdef __arm__\n\n"
+    suffix = "\n\n#endif"
+
+
+def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
+    if not os.path.exists(dst_dir):
+        os.makedirs(dst_dir)
+
+    out_filename = filename
+
+    if file_suffix:
+        split_name = os.path.splitext(filename)
+        out_filename =  "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
+
+    with open(os.path.join(src_dir, filename)) as in_file:
+        with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
+            if prefix:
+                out_file.write(prefix)
+
+            out_file.write(in_file.read())
+
+            if suffix:
+                out_file.write(suffix)
+
+headers_seen = collections.defaultdict(set)
+
+def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None):
+    for root, dirs, files in os.walk(src_dir, followlinks=True):
+        relroot = os.path.relpath(root,src_dir)
+
+        def move_dir(arch, prefix='', suffix='', files=[]):
+            for file in files:
+                file_suffix = None
+                if file.endswith('.h'):
+                    if dest_include_dir:
+                        file_suffix = arch
+                        if arch:
+                            headers_seen[file].add(arch)
+                        move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix)
+
+                elif dest_dir:
+                    outroot = os.path.join(dest_dir, relroot)
+                    move_file(root, outroot, file, prefix=prefix, suffix=suffix)
+
+        if relroot == '.':
+            move_dir(arch=arch,
+                     files=files,
+                     prefix=prefix,
+                     suffix=suffix)
+        elif relroot == 'arm':
+            move_dir(arch='arm',
+                     prefix="#ifdef __arm__\n\n",
+                     suffix="\n\n#endif",
+                     files=files)
+        elif relroot == 'x86':
+            move_dir(arch='i386',
+                     prefix="#if !defined(__arm__) && defined(__i386__)\n\n",
+                     suffix="\n\n#endif",
+                     files=files)
+
+def build_target(platform):
+    def xcrun_cmd(cmd):
+        return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip()
+
+    build_dir = 'build_' + platform.name
+    if not os.path.exists(build_dir):
+        os.makedirs(build_dir)
+        env = dict(CC=xcrun_cmd('clang'),
+                   LD=xcrun_cmd('ld'),
+                   CFLAGS='-arch %s -isysroot %s -miphoneos-version-min=4.0' % (platform.arch, platform.sdkroot))
+        working_dir=os.getcwd()
+        try:
+            os.chdir(build_dir)
+            subprocess.check_call(['../configure', '-host', platform.triple], env=env)
+            move_source_tree('.', None, '../ios/include',
+                             arch=platform.arch,
+                             prefix=platform.prefix,
+                             suffix=platform.suffix)
+            move_source_tree('./include', None, '../ios/include',
+                            arch=platform.arch,
+                            prefix=platform.prefix,
+                            suffix=platform.suffix)
+        finally:
+            os.chdir(working_dir)
+
+        for header_name, archs in headers_seen.iteritems():
+            basename, suffix = os.path.splitext(header_name)
+
+def main():
+    move_source_tree('src', 'ios/src', 'ios/include')
+    move_source_tree('include', None, 'ios/include')
+    build_target(simulator_platform)
+    build_target(device_platform)
+
+    for header_name, archs in headers_seen.iteritems():
+        basename, suffix = os.path.splitext(header_name)
+        with open(os.path.join('ios/include', header_name), 'w') as header:
+            for arch in archs:
+                header.write('#include <%s_%s%s>\n' % (basename, arch, suffix))
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/gofrontend/libffi/generate-osx-source-and-headers.py b/third_party/gofrontend/libffi/generate-osx-source-and-headers.py
new file mode 100644
index 0000000..64313c1
--- /dev/null
+++ b/third_party/gofrontend/libffi/generate-osx-source-and-headers.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+import subprocess
+import re
+import os
+import errno
+import collections
+import sys
+
+class Platform(object):
+    pass
+
+sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)')
+
+def sdkinfo(sdkname):
+    ret = {}
+    for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout:
+        kv = line.strip().split(': ', 1)
+        if len(kv) == 2:
+            k,v = kv
+            ret[k] = v
+    return ret
+
+desktop_sdk_info = sdkinfo('macosx')
+
+def latest_sdks():
+    latest_desktop = None
+    for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout:
+        match = sdk_re.match(line)
+        if match:
+            if 'OS X' in line:
+                latest_desktop = match.group(1)
+
+    return latest_desktop
+
+desktop_sdk = latest_sdks()
+
+class desktop_platform_32(Platform):
+    sdk='macosx'
+    arch = 'i386'
+    name = 'mac32'
+    triple = 'i386-apple-darwin10'
+    sdkroot = desktop_sdk_info['Path']
+
+    prefix = "#if defined(__i386__) && !defined(__x86_64__)\n\n"
+    suffix = "\n\n#endif"
+
+class desktop_platform_64(Platform):
+    sdk='macosx'
+    arch = 'x86_64'
+    name = 'mac'
+    triple = 'x86_64-apple-darwin10'
+    sdkroot = desktop_sdk_info['Path']
+
+    prefix = "#if !defined(__i386__) && defined(__x86_64__)\n\n"
+    suffix = "\n\n#endif"
+
+def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
+    if not os.path.exists(dst_dir):
+        os.makedirs(dst_dir)
+
+    out_filename = filename
+
+    if file_suffix:
+        split_name = os.path.splitext(filename)
+        out_filename =  "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
+
+    with open(os.path.join(src_dir, filename)) as in_file:
+        with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
+            if prefix:
+                out_file.write(prefix)
+
+            out_file.write(in_file.read())
+
+            if suffix:
+                out_file.write(suffix)
+
+headers_seen = collections.defaultdict(set)
+
+def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None):
+    for root, dirs, files in os.walk(src_dir, followlinks=True):
+        relroot = os.path.relpath(root,src_dir)
+
+        def move_dir(arch, prefix='', suffix='', files=[]):
+            for file in files:
+                file_suffix = None
+                if file.endswith('.h'):
+                    if dest_include_dir:
+                        file_suffix = arch
+                        if arch:
+                            headers_seen[file].add(arch)
+                        move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix)
+
+                elif dest_dir:
+                    outroot = os.path.join(dest_dir, relroot)
+                    move_file(root, outroot, file, prefix=prefix, suffix=suffix)
+
+        if relroot == '.':
+            move_dir(arch=arch,
+                     files=files,
+                     prefix=prefix,
+                     suffix=suffix)
+        elif relroot == 'x86':
+            move_dir(arch='i386',
+                     prefix="#if defined(__i386__) && !defined(__x86_64__)\n\n",
+                     suffix="\n\n#endif",
+                     files=files)
+            move_dir(arch='x86_64',
+                     prefix="#if !defined(__i386__) && defined(__x86_64__)\n\n",
+                     suffix="\n\n#endif",
+                     files=files)
+
+def build_target(platform):
+    def xcrun_cmd(cmd):
+        return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip()
+
+    build_dir = 'build_' + platform.name
+    if not os.path.exists(build_dir):
+        os.makedirs(build_dir)
+        env = dict(CC=xcrun_cmd('clang'),
+                   LD=xcrun_cmd('ld'),
+                   CFLAGS='-arch %s -isysroot %s -mmacosx-version-min=10.6' % (platform.arch, platform.sdkroot))
+        working_dir=os.getcwd()
+        try:
+            os.chdir(build_dir)
+            subprocess.check_call(['../configure', '-host', platform.triple], env=env)
+            move_source_tree('.', None, '../osx/include',
+                             arch=platform.arch,
+                             prefix=platform.prefix,
+                             suffix=platform.suffix)
+            move_source_tree('./include', None, '../osx/include',
+                             arch=platform.arch,
+                             prefix=platform.prefix,
+                             suffix=platform.suffix)
+        finally:
+            os.chdir(working_dir)
+
+        for header_name, archs in headers_seen.iteritems():
+            basename, suffix = os.path.splitext(header_name)
+
+def main():
+    move_source_tree('src', 'osx/src', 'osx/include')
+    move_source_tree('include', None, 'osx/include')
+    build_target(desktop_platform_32)
+    build_target(desktop_platform_64)
+
+    for header_name, archs in headers_seen.iteritems():
+        basename, suffix = os.path.splitext(header_name)
+        with open(os.path.join('osx/include', header_name), 'w') as header:
+            for arch in archs:
+                header.write('#include <%s_%s%s>\n' % (basename, arch, suffix))
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/gofrontend/libffi/include/Makefile.am b/third_party/gofrontend/libffi/include/Makefile.am
new file mode 100644
index 0000000..f11151e
--- /dev/null
+++ b/third_party/gofrontend/libffi/include/Makefile.am
@@ -0,0 +1,12 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS=foreign
+
+DISTCLEANFILES=ffitarget.h
+EXTRA_DIST=ffi.h.in ffi_common.h
+
+# Where generated headers like ffitarget.h get installed.
+gcc_version   := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+toollibffidir := $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
+
+toollibffi_HEADERS = ffi.h ffitarget.h
diff --git a/third_party/gofrontend/libffi/include/Makefile.in b/third_party/gofrontend/libffi/include/Makefile.in
new file mode 100644
index 0000000..c923bf2
--- /dev/null
+++ b/third_party/gofrontend/libffi/include/Makefile.in
@@ -0,0 +1,451 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = include
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(srcdir)/ffi.h.in $(toollibffi_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+	$(top_srcdir)/../config/asmcfi.m4 \
+	$(top_srcdir)/../config/depstand.m4 \
+	$(top_srcdir)/../config/lead-dot.m4 \
+	$(top_srcdir)/../config/multi.m4 \
+	$(top_srcdir)/../config/override.m4 \
+	$(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \
+	$(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
+	$(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/fficonfig.h
+CONFIG_CLEAN_FILES = ffi.h ffitarget.h
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(toollibffidir)"
+HEADERS = $(toollibffi_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_LTLDFLAGS = @AM_LTLDFLAGS@
+AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
+HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARGET = @TARGET@
+TARGETDIR = @TARGETDIR@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign
+DISTCLEANFILES = ffitarget.h
+EXTRA_DIST = ffi.h.in ffi_common.h
+
+# Where generated headers like ffitarget.h get installed.
+gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+toollibffidir := $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
+toollibffi_HEADERS = ffi.h ffitarget.h
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign include/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+ffi.h: $(top_builddir)/config.status $(srcdir)/ffi.h.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-toollibffiHEADERS: $(toollibffi_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(toollibffidir)" || $(MKDIR_P) "$(DESTDIR)$(toollibffidir)"
+	@list='$(toollibffi_HEADERS)'; test -n "$(toollibffidir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(toollibffidir)'"; \
+	  $(INSTALL_HEADER) $$files "$(DESTDIR)$(toollibffidir)" || exit $$?; \
+	done
+
+uninstall-toollibffiHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toollibffi_HEADERS)'; test -n "$(toollibffidir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toollibffidir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toollibffidir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(toollibffidir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+	-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-toollibffiHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-toollibffiHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool ctags distclean distclean-generic \
+	distclean-libtool distclean-tags dvi dvi-am html html-am info \
+	info-am install install-am install-data install-data-am \
+	install-dvi install-dvi-am install-exec install-exec-am \
+	install-html install-html-am install-info install-info-am \
+	install-man install-pdf install-pdf-am install-ps \
+	install-ps-am install-strip install-toollibffiHEADERS \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am uninstall-toollibffiHEADERS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/third_party/gofrontend/libffi/include/ffi.h.in b/third_party/gofrontend/libffi/include/ffi.h.in
new file mode 100644
index 0000000..380673b
--- /dev/null
+++ b/third_party/gofrontend/libffi/include/ffi.h.in
@@ -0,0 +1,448 @@
+/* -----------------------------------------------------------------*-C-*-
+   libffi @VERSION@ - Copyright (c) 2011 Anthony Green
+                    - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person
+   obtaining a copy of this software and associated documentation
+   files (the ``Software''), to deal in the Software without
+   restriction, including without limitation the rights to use, copy,
+   modify, merge, publish, distribute, sublicense, and/or sell copies
+   of the Software, and to permit persons to whom the Software is
+   furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be
+   included in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------
+   The basic API is described in the README file.
+
+   The raw API is designed to bypass some of the argument packing
+   and unpacking on architectures for which it can be avoided.
+
+   The closure API allows interpreted functions to be packaged up
+   inside a C function pointer, so that they can be called as C functions,
+   with no understanding on the client side that they are interpreted.
+   It can also be used in other cases in which it is necessary to package
+   up a user specified parameter and a function pointer as a single
+   function pointer.
+
+   The closure API must be implemented in order to get its functionality,
+   e.g. for use by gij.  Routines are provided to emulate the raw API
+   if the underlying platform doesn't allow faster implementation.
+
+   More details on the raw and cloure API can be found in:
+
+   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
+
+   and
+
+   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
+   -------------------------------------------------------------------- */
+
+#ifndef LIBFFI_H
+#define LIBFFI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Specify which architecture libffi is configured for. */
+#ifndef @TARGET@
+#define @TARGET@
+#endif
+
+/* ---- System configuration information --------------------------------- */
+
+#include <ffitarget.h>
+
+#ifndef LIBFFI_ASM
+
+#ifdef _MSC_VER
+#define __attribute__(X)
+#endif
+
+#include <stddef.h>
+#include <limits.h>
+
+/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
+   But we can find it either under the correct ANSI name, or under GNU
+   C's internal name.  */
+
+#define FFI_64_BIT_MAX 9223372036854775807
+
+#ifdef LONG_LONG_MAX
+# define FFI_LONG_LONG_MAX LONG_LONG_MAX
+#else
+# ifdef LLONG_MAX
+#  define FFI_LONG_LONG_MAX LLONG_MAX
+#  ifdef _AIX52 /* or newer has C99 LLONG_MAX */
+#   undef FFI_64_BIT_MAX
+#   define FFI_64_BIT_MAX 9223372036854775807LL
+#  endif /* _AIX52 or newer */
+# else
+#  ifdef __GNUC__
+#   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
+#  endif
+#  ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
+#   ifndef __PPC64__
+#    if defined (__IBMC__) || defined (__IBMCPP__)
+#     define FFI_LONG_LONG_MAX LONGLONG_MAX
+#    endif
+#   endif /* __PPC64__ */
+#   undef  FFI_64_BIT_MAX
+#   define FFI_64_BIT_MAX 9223372036854775807LL
+#  endif
+# endif
+#endif
+
+/* The closure code assumes that this works on pointers, i.e. a size_t	*/
+/* can hold a pointer.							*/
+
+typedef struct _ffi_type
+{
+  size_t size;
+  unsigned short alignment;
+  unsigned short type;
+  struct _ffi_type **elements;
+} ffi_type;
+
+#ifndef LIBFFI_HIDE_BASIC_TYPES
+#if SCHAR_MAX == 127
+# define ffi_type_uchar                ffi_type_uint8
+# define ffi_type_schar                ffi_type_sint8
+#else
+ #error "char size not supported"
+#endif
+
+#if SHRT_MAX == 32767
+# define ffi_type_ushort       ffi_type_uint16
+# define ffi_type_sshort       ffi_type_sint16
+#elif SHRT_MAX == 2147483647
+# define ffi_type_ushort       ffi_type_uint32
+# define ffi_type_sshort       ffi_type_sint32
+#else
+ #error "short size not supported"
+#endif
+
+#if INT_MAX == 32767
+# define ffi_type_uint         ffi_type_uint16
+# define ffi_type_sint         ffi_type_sint16
+#elif INT_MAX == 2147483647
+# define ffi_type_uint         ffi_type_uint32
+# define ffi_type_sint         ffi_type_sint32
+#elif INT_MAX == 9223372036854775807
+# define ffi_type_uint         ffi_type_uint64
+# define ffi_type_sint         ffi_type_sint64
+#else
+ #error "int size not supported"
+#endif
+
+#if LONG_MAX == 2147483647
+# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
+ #error "no 64-bit data type supported"
+# endif
+#elif LONG_MAX != FFI_64_BIT_MAX
+ #error "long size not supported"
+#endif
+
+#if LONG_MAX == 2147483647
+# define ffi_type_ulong        ffi_type_uint32
+# define ffi_type_slong        ffi_type_sint32
+#elif LONG_MAX == FFI_64_BIT_MAX
+# define ffi_type_ulong        ffi_type_uint64
+# define ffi_type_slong        ffi_type_sint64
+#else
+ #error "long size not supported"
+#endif
+
+/* These are defined in types.c */
+extern ffi_type ffi_type_void;
+extern ffi_type ffi_type_uint8;
+extern ffi_type ffi_type_sint8;
+extern ffi_type ffi_type_uint16;
+extern ffi_type ffi_type_sint16;
+extern ffi_type ffi_type_uint32;
+extern ffi_type ffi_type_sint32;
+extern ffi_type ffi_type_uint64;
+extern ffi_type ffi_type_sint64;
+extern ffi_type ffi_type_float;
+extern ffi_type ffi_type_double;
+extern ffi_type ffi_type_pointer;
+
+#if @HAVE_LONG_DOUBLE@
+extern ffi_type ffi_type_longdouble;
+#else
+#define ffi_type_longdouble ffi_type_double
+#endif
+#endif /* LIBFFI_HIDE_BASIC_TYPES */
+
+typedef enum {
+  FFI_OK = 0,
+  FFI_BAD_TYPEDEF,
+  FFI_BAD_ABI
+} ffi_status;
+
+typedef unsigned FFI_TYPE;
+
+typedef struct {
+  ffi_abi abi;
+  unsigned nargs;
+  ffi_type **arg_types;
+  ffi_type *rtype;
+  unsigned bytes;
+  unsigned flags;
+#ifdef FFI_EXTRA_CIF_FIELDS
+  FFI_EXTRA_CIF_FIELDS;
+#endif
+} ffi_cif;
+
+#if HAVE_LONG_DOUBLE_VARIANT
+/* Used to adjust size/alignment of ffi types.  */
+void ffi_prep_types (ffi_abi abi);
+# endif
+
+/* Used internally, but overridden by some architectures */
+ffi_status ffi_prep_cif_core(ffi_cif *cif,
+			     ffi_abi abi,
+			     unsigned int isvariadic,
+			     unsigned int nfixedargs,
+			     unsigned int ntotalargs,
+			     ffi_type *rtype,
+			     ffi_type **atypes);
+
+/* ---- Definitions for the raw API -------------------------------------- */
+
+#ifndef FFI_SIZEOF_ARG
+# if LONG_MAX == 2147483647
+#  define FFI_SIZEOF_ARG        4
+# elif LONG_MAX == FFI_64_BIT_MAX
+#  define FFI_SIZEOF_ARG        8
+# endif
+#endif
+
+#ifndef FFI_SIZEOF_JAVA_RAW
+#  define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
+#endif
+
+typedef union {
+  ffi_sarg  sint;
+  ffi_arg   uint;
+  float	    flt;
+  char      data[FFI_SIZEOF_ARG];
+  void*     ptr;
+} ffi_raw;
+
+#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
+/* This is a special case for mips64/n32 ABI (and perhaps others) where
+   sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8.  */
+typedef union {
+  signed int	sint;
+  unsigned int	uint;
+  float		flt;
+  char		data[FFI_SIZEOF_JAVA_RAW];
+  void*		ptr;
+} ffi_java_raw;
+#else
+typedef ffi_raw ffi_java_raw;
+#endif
+
+
+void ffi_raw_call (ffi_cif *cif,
+		   void (*fn)(void),
+		   void *rvalue,
+		   ffi_raw *avalue);
+
+void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
+void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
+size_t ffi_raw_size (ffi_cif *cif);
+
+/* This is analogous to the raw API, except it uses Java parameter	*/
+/* packing, even on 64-bit machines.  I.e. on 64-bit machines		*/
+/* longs and doubles are followed by an empty 64-bit word.		*/
+
+void ffi_java_raw_call (ffi_cif *cif,
+			void (*fn)(void),
+			void *rvalue,
+			ffi_java_raw *avalue);
+
+void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
+void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
+size_t ffi_java_raw_size (ffi_cif *cif);
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#if FFI_CLOSURES
+
+#ifdef _MSC_VER
+__declspec(align(8))
+#endif
+typedef struct {
+  char tramp[FFI_TRAMPOLINE_SIZE];
+  ffi_cif   *cif;
+  void     (*fun)(ffi_cif*,void*,void**,void*);
+  void      *user_data;
+#ifdef __GNUC__
+} ffi_closure __attribute__((aligned (8)));
+#else
+} ffi_closure;
+# ifdef __sgi
+#  pragma pack 0
+# endif
+#endif
+
+void *ffi_closure_alloc (size_t size, void **code);
+void ffi_closure_free (void *);
+
+ffi_status
+ffi_prep_closure (ffi_closure*,
+		  ffi_cif *,
+		  void (*fun)(ffi_cif*,void*,void**,void*),
+		  void *user_data);
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure*,
+		      ffi_cif *,
+		      void (*fun)(ffi_cif*,void*,void**,void*),
+		      void *user_data,
+		      void*codeloc);
+
+#ifdef __sgi
+# pragma pack 8
+#endif
+typedef struct {
+  char tramp[FFI_TRAMPOLINE_SIZE];
+
+  ffi_cif   *cif;
+
+#if !FFI_NATIVE_RAW_API
+
+  /* if this is enabled, then a raw closure has the same layout 
+     as a regular closure.  We use this to install an intermediate 
+     handler to do the transaltion, void** -> ffi_raw*. */
+
+  void     (*translate_args)(ffi_cif*,void*,void**,void*);
+  void      *this_closure;
+
+#endif
+
+  void     (*fun)(ffi_cif*,void*,ffi_raw*,void*);
+  void      *user_data;
+
+} ffi_raw_closure;
+
+typedef struct {
+  char tramp[FFI_TRAMPOLINE_SIZE];
+
+  ffi_cif   *cif;
+
+#if !FFI_NATIVE_RAW_API
+
+  /* if this is enabled, then a raw closure has the same layout 
+     as a regular closure.  We use this to install an intermediate 
+     handler to do the transaltion, void** -> ffi_raw*. */
+
+  void     (*translate_args)(ffi_cif*,void*,void**,void*);
+  void      *this_closure;
+
+#endif
+
+  void     (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
+  void      *user_data;
+
+} ffi_java_raw_closure;
+
+ffi_status
+ffi_prep_raw_closure (ffi_raw_closure*,
+		      ffi_cif *cif,
+		      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+		      void *user_data);
+
+ffi_status
+ffi_prep_raw_closure_loc (ffi_raw_closure*,
+			  ffi_cif *cif,
+			  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+			  void *user_data,
+			  void *codeloc);
+
+ffi_status
+ffi_prep_java_raw_closure (ffi_java_raw_closure*,
+		           ffi_cif *cif,
+		           void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
+		           void *user_data);
+
+ffi_status
+ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
+			       ffi_cif *cif,
+			       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
+			       void *user_data,
+			       void *codeloc);
+
+#endif /* FFI_CLOSURES */
+
+/* ---- Public interface definition -------------------------------------- */
+
+ffi_status ffi_prep_cif(ffi_cif *cif,
+			ffi_abi abi,
+			unsigned int nargs,
+			ffi_type *rtype,
+			ffi_type **atypes);
+
+ffi_status ffi_prep_cif_var(ffi_cif *cif,
+			    ffi_abi abi,
+			    unsigned int nfixedargs,
+			    unsigned int ntotalargs,
+			    ffi_type *rtype,
+			    ffi_type **atypes);
+
+void ffi_call(ffi_cif *cif,
+	      void (*fn)(void),
+	      void *rvalue,
+	      void **avalue);
+
+/* Useful for eliminating compiler warnings */
+#define FFI_FN(f) ((void (*)(void))f)
+
+/* ---- Definitions shared with assembly code ---------------------------- */
+
+#endif
+
+/* If these change, update src/mips/ffitarget.h. */
+#define FFI_TYPE_VOID       0    
+#define FFI_TYPE_INT        1
+#define FFI_TYPE_FLOAT      2    
+#define FFI_TYPE_DOUBLE     3
+#if @HAVE_LONG_DOUBLE@
+#define FFI_TYPE_LONGDOUBLE 4
+#else
+#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
+#endif
+#define FFI_TYPE_UINT8      5   
+#define FFI_TYPE_SINT8      6
+#define FFI_TYPE_UINT16     7 
+#define FFI_TYPE_SINT16     8
+#define FFI_TYPE_UINT32     9
+#define FFI_TYPE_SINT32     10
+#define FFI_TYPE_UINT64     11
+#define FFI_TYPE_SINT64     12
+#define FFI_TYPE_STRUCT     13
+#define FFI_TYPE_POINTER    14
+
+/* This should always refer to the last type code (for sanity checks) */
+#define FFI_TYPE_LAST       FFI_TYPE_POINTER
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/third_party/gofrontend/libffi/include/ffi_common.h b/third_party/gofrontend/libffi/include/ffi_common.h
new file mode 100644
index 0000000..c179d68
--- /dev/null
+++ b/third_party/gofrontend/libffi/include/ffi_common.h
@@ -0,0 +1,128 @@
+/* -----------------------------------------------------------------------
+   ffi_common.h - Copyright (C) 2011, 2012  Anthony Green
+                  Copyright (C) 2007  Free Software Foundation, Inc
+                  Copyright (c) 1996  Red Hat, Inc.
+                  
+   Common internal definitions and macros. Only necessary for building
+   libffi.
+   ----------------------------------------------------------------------- */
+
+#ifndef FFI_COMMON_H
+#define FFI_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <fficonfig.h>
+
+/* Do not move this. Some versions of AIX are very picky about where
+   this is positioned. */
+#ifdef __GNUC__
+/* mingw64 defines this already in malloc.h. */
+#ifndef alloca
+# define alloca __builtin_alloca
+#endif
+# define MAYBE_UNUSED __attribute__((__unused__))
+#else
+# define MAYBE_UNUSED
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca /* predefined by HP cc +Olibcalls */
+#    ifdef _MSC_VER
+#     define alloca _alloca
+#    else
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+/* Check for the existence of memcpy. */
+#if STDC_HEADERS
+# include <string.h>
+#else
+# ifndef HAVE_MEMCPY
+#  define memcpy(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#if defined(FFI_DEBUG)
+#include <stdio.h>
+#endif
+
+#ifdef FFI_DEBUG
+void ffi_assert(char *expr, char *file, int line);
+void ffi_stop_here(void);
+void ffi_type_test(ffi_type *a, char *file, int line);
+
+#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
+#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
+#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
+#else
+#define FFI_ASSERT(x)
+#define FFI_ASSERT_AT(x, f, l)
+#define FFI_ASSERT_VALID_TYPE(x)
+#endif
+
+#define ALIGN(v, a)  (((((size_t) (v))-1) | ((a)-1))+1)
+#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a)
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
+	 unsigned int nfixedargs, unsigned int ntotalargs);
+
+/* Extended cif, used in callback from assembly routine */
+typedef struct
+{
+  ffi_cif *cif;
+  void *rvalue;
+  void **avalue;
+} extended_cif;
+
+/* Terse sized type definitions.  */
+#if defined(_MSC_VER) || defined(__sgi)
+typedef unsigned char UINT8;
+typedef signed char   SINT8;
+typedef unsigned short UINT16;
+typedef signed short   SINT16;
+typedef unsigned int UINT32;
+typedef signed int   SINT32;
+# ifdef _MSC_VER
+typedef unsigned __int64 UINT64;
+typedef signed __int64   SINT64;
+# else
+# include <inttypes.h>
+typedef uint64_t UINT64;
+typedef int64_t  SINT64;
+# endif
+#else
+typedef unsigned int UINT8  __attribute__((__mode__(__QI__)));
+typedef signed int   SINT8  __attribute__((__mode__(__QI__)));
+typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
+typedef signed int   SINT16 __attribute__((__mode__(__HI__)));
+typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
+typedef signed int   SINT32 __attribute__((__mode__(__SI__)));
+typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
+typedef signed int   SINT64 __attribute__((__mode__(__DI__)));
+#endif
+
+typedef float FLOAT32;
+
+#ifndef __GNUC__
+#define __builtin_expect(x, expected_value) (x)
+#endif
+#define LIKELY(x)    __builtin_expect(!!(x),1)
+#define UNLIKELY(x)  __builtin_expect((x)!=0,0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/third_party/gofrontend/libffi/libffi.xcodeproj/project.pbxproj b/third_party/gofrontend/libffi/libffi.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..14c39a2
--- /dev/null
+++ b/third_party/gofrontend/libffi/libffi.xcodeproj/project.pbxproj
@@ -0,0 +1,579 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		6C43CBDC1534F76F00162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBBD1534F76F00162364 /* ffi.c */; };
+		6C43CBDD1534F76F00162364 /* sysv.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBBF1534F76F00162364 /* sysv.S */; };
+		6C43CBDE1534F76F00162364 /* trampoline.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBC01534F76F00162364 /* trampoline.S */; };
+		6C43CBE61534F76F00162364 /* darwin.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBC91534F76F00162364 /* darwin.S */; };
+		6C43CBE81534F76F00162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBCB1534F76F00162364 /* ffi.c */; };
+		6C43CC1F1534F77800162364 /* darwin.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC051534F77800162364 /* darwin.S */; };
+		6C43CC201534F77800162364 /* darwin64.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC061534F77800162364 /* darwin64.S */; };
+		6C43CC211534F77800162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC071534F77800162364 /* ffi.c */; };
+		6C43CC221534F77800162364 /* ffi64.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC081534F77800162364 /* ffi64.c */; };
+		6C43CC2F1534F7BE00162364 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC281534F7BE00162364 /* closures.c */; };
+		6C43CC301534F7BE00162364 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC281534F7BE00162364 /* closures.c */; };
+		6C43CC351534F7BE00162364 /* java_raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2B1534F7BE00162364 /* java_raw_api.c */; };
+		6C43CC361534F7BE00162364 /* java_raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2B1534F7BE00162364 /* java_raw_api.c */; };
+		6C43CC371534F7BE00162364 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2C1534F7BE00162364 /* prep_cif.c */; };
+		6C43CC381534F7BE00162364 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2C1534F7BE00162364 /* prep_cif.c */; };
+		6C43CC391534F7BE00162364 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2D1534F7BE00162364 /* raw_api.c */; };
+		6C43CC3A1534F7BE00162364 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2D1534F7BE00162364 /* raw_api.c */; };
+		6C43CC3B1534F7BE00162364 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2E1534F7BE00162364 /* types.c */; };
+		6C43CC3C1534F7BE00162364 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2E1534F7BE00162364 /* types.c */; };
+		6C43CC971535032600162364 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8D1535032600162364 /* ffi.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CC981535032600162364 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8E1535032600162364 /* ffi_common.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CC991535032600162364 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8F1535032600162364 /* ffi_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CC9A1535032600162364 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC901535032600162364 /* ffi_x86_64.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CC9B1535032600162364 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC911535032600162364 /* fficonfig.h */; };
+		6C43CC9C1535032600162364 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC921535032600162364 /* fficonfig_i386.h */; };
+		6C43CC9D1535032600162364 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC931535032600162364 /* fficonfig_x86_64.h */; };
+		6C43CC9E1535032600162364 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC941535032600162364 /* ffitarget.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CC9F1535032600162364 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC951535032600162364 /* ffitarget_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CCA01535032600162364 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC961535032600162364 /* ffitarget_x86_64.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CCAD1535039600162364 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA21535039600162364 /* ffi.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CCAE1535039600162364 /* ffi_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA31535039600162364 /* ffi_armv7.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CCAF1535039600162364 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA41535039600162364 /* ffi_common.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CCB01535039600162364 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA51535039600162364 /* ffi_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CCB11535039600162364 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA61535039600162364 /* fficonfig.h */; };
+		6C43CCB21535039600162364 /* fficonfig_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA71535039600162364 /* fficonfig_armv7.h */; };
+		6C43CCB31535039600162364 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA81535039600162364 /* fficonfig_i386.h */; };
+		6C43CCB41535039600162364 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA91535039600162364 /* ffitarget.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CCB51535039600162364 /* ffitarget_arm.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAA1535039600162364 /* ffitarget_arm.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CCB61535039600162364 /* ffitarget_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAB1535039600162364 /* ffitarget_armv7.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6C43CCB71535039600162364 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAC1535039600162364 /* ffitarget_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		6C43CB3D1534E9D100162364 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		6C43CBBD1534F76F00162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
+		6C43CBBF1534F76F00162364 /* sysv.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv.S; sourceTree = "<group>"; };
+		6C43CBC01534F76F00162364 /* trampoline.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline.S; sourceTree = "<group>"; };
+		6C43CBC91534F76F00162364 /* darwin.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin.S; sourceTree = "<group>"; };
+		6C43CBCB1534F76F00162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
+		6C43CC051534F77800162364 /* darwin.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin.S; sourceTree = "<group>"; };
+		6C43CC061534F77800162364 /* darwin64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64.S; sourceTree = "<group>"; };
+		6C43CC071534F77800162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
+		6C43CC081534F77800162364 /* ffi64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64.c; sourceTree = "<group>"; };
+		6C43CC281534F7BE00162364 /* closures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = closures.c; path = src/closures.c; sourceTree = SOURCE_ROOT; };
+		6C43CC2B1534F7BE00162364 /* java_raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = java_raw_api.c; path = src/java_raw_api.c; sourceTree = SOURCE_ROOT; };
+		6C43CC2C1534F7BE00162364 /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = prep_cif.c; path = src/prep_cif.c; sourceTree = SOURCE_ROOT; };
+		6C43CC2D1534F7BE00162364 /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = raw_api.c; path = src/raw_api.c; sourceTree = SOURCE_ROOT; };
+		6C43CC2E1534F7BE00162364 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = types.c; path = src/types.c; sourceTree = SOURCE_ROOT; };
+		6C43CC8D1535032600162364 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
+		6C43CC8E1535032600162364 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
+		6C43CC8F1535032600162364 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
+		6C43CC901535032600162364 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
+		6C43CC911535032600162364 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
+		6C43CC921535032600162364 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
+		6C43CC931535032600162364 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
+		6C43CC941535032600162364 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
+		6C43CC951535032600162364 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
+		6C43CC961535032600162364 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
+		6C43CCA21535039600162364 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
+		6C43CCA31535039600162364 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = "<group>"; };
+		6C43CCA41535039600162364 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
+		6C43CCA51535039600162364 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
+		6C43CCA61535039600162364 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
+		6C43CCA71535039600162364 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = "<group>"; };
+		6C43CCA81535039600162364 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
+		6C43CCA91535039600162364 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
+		6C43CCAA1535039600162364 /* ffitarget_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm.h; sourceTree = "<group>"; };
+		6C43CCAB1535039600162364 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = "<group>"; };
+		6C43CCAC1535039600162364 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
+		F6F980BA147386130008F121 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		6C43CB3A1534E9D100162364 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F6F980B7147386130008F121 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		6C43CBAF1534F76F00162364 /* iOS */ = {
+			isa = PBXGroup;
+			children = (
+				6C43CCA11535039600162364 /* include */,
+				6C43CBBB1534F76F00162364 /* src */,
+			);
+			name = iOS;
+			path = ios;
+			sourceTree = "<group>";
+		};
+		6C43CBBB1534F76F00162364 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				6C43CBC81534F76F00162364 /* x86 */,
+				6C43CBBC1534F76F00162364 /* arm */,
+			);
+			path = src;
+			sourceTree = "<group>";
+		};
+		6C43CBBC1534F76F00162364 /* arm */ = {
+			isa = PBXGroup;
+			children = (
+				6C43CBBD1534F76F00162364 /* ffi.c */,
+				6C43CBBF1534F76F00162364 /* sysv.S */,
+				6C43CBC01534F76F00162364 /* trampoline.S */,
+			);
+			path = arm;
+			sourceTree = "<group>";
+		};
+		6C43CBC81534F76F00162364 /* x86 */ = {
+			isa = PBXGroup;
+			children = (
+				6C43CBC91534F76F00162364 /* darwin.S */,
+				6C43CBCB1534F76F00162364 /* ffi.c */,
+			);
+			path = x86;
+			sourceTree = "<group>";
+		};
+		6C43CBF01534F77800162364 /* OS X */ = {
+			isa = PBXGroup;
+			children = (
+				6C43CC8C1535032600162364 /* include */,
+				6C43CBFC1534F77800162364 /* src */,
+			);
+			name = "OS X";
+			path = osx;
+			sourceTree = "<group>";
+		};
+		6C43CBFC1534F77800162364 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				6C43CC041534F77800162364 /* x86 */,
+			);
+			path = src;
+			sourceTree = "<group>";
+		};
+		6C43CC041534F77800162364 /* x86 */ = {
+			isa = PBXGroup;
+			children = (
+				6C43CC051534F77800162364 /* darwin.S */,
+				6C43CC061534F77800162364 /* darwin64.S */,
+				6C43CC071534F77800162364 /* ffi.c */,
+				6C43CC081534F77800162364 /* ffi64.c */,
+			);
+			path = x86;
+			sourceTree = "<group>";
+		};
+		6C43CC3D1534F7C400162364 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				6C43CC281534F7BE00162364 /* closures.c */,
+				6C43CC2B1534F7BE00162364 /* java_raw_api.c */,
+				6C43CC2C1534F7BE00162364 /* prep_cif.c */,
+				6C43CC2D1534F7BE00162364 /* raw_api.c */,
+				6C43CC2E1534F7BE00162364 /* types.c */,
+			);
+			name = src;
+			path = ios;
+			sourceTree = "<group>";
+		};
+		6C43CC8C1535032600162364 /* include */ = {
+			isa = PBXGroup;
+			children = (
+				6C43CC8D1535032600162364 /* ffi.h */,
+				6C43CC8E1535032600162364 /* ffi_common.h */,
+				6C43CC8F1535032600162364 /* ffi_i386.h */,
+				6C43CC901535032600162364 /* ffi_x86_64.h */,
+				6C43CC911535032600162364 /* fficonfig.h */,
+				6C43CC921535032600162364 /* fficonfig_i386.h */,
+				6C43CC931535032600162364 /* fficonfig_x86_64.h */,
+				6C43CC941535032600162364 /* ffitarget.h */,
+				6C43CC951535032600162364 /* ffitarget_i386.h */,
+				6C43CC961535032600162364 /* ffitarget_x86_64.h */,
+			);
+			path = include;
+			sourceTree = "<group>";
+		};
+		6C43CCA11535039600162364 /* include */ = {
+			isa = PBXGroup;
+			children = (
+				6C43CCA21535039600162364 /* ffi.h */,
+				6C43CCA31535039600162364 /* ffi_armv7.h */,
+				6C43CCA41535039600162364 /* ffi_common.h */,
+				6C43CCA51535039600162364 /* ffi_i386.h */,
+				6C43CCA61535039600162364 /* fficonfig.h */,
+				6C43CCA71535039600162364 /* fficonfig_armv7.h */,
+				6C43CCA81535039600162364 /* fficonfig_i386.h */,
+				6C43CCA91535039600162364 /* ffitarget.h */,
+				6C43CCAA1535039600162364 /* ffitarget_arm.h */,
+				6C43CCAB1535039600162364 /* ffitarget_armv7.h */,
+				6C43CCAC1535039600162364 /* ffitarget_i386.h */,
+			);
+			path = include;
+			sourceTree = "<group>";
+		};
+		F6B0839514721EE50031D8A1 = {
+			isa = PBXGroup;
+			children = (
+				6C43CC3D1534F7C400162364 /* src */,
+				6C43CBAF1534F76F00162364 /* iOS */,
+				6C43CBF01534F77800162364 /* OS X */,
+				F6F980C6147386260008F121 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		F6F980C6147386260008F121 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				F6F980BA147386130008F121 /* libffi.a */,
+				6C43CB3D1534E9D100162364 /* libffi.a */,
+			);
+			name = Products;
+			path = ../..;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		6C43CB3B1534E9D100162364 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				6C43CC971535032600162364 /* ffi.h in Headers */,
+				6C43CC981535032600162364 /* ffi_common.h in Headers */,
+				6C43CC991535032600162364 /* ffi_i386.h in Headers */,
+				6C43CC9A1535032600162364 /* ffi_x86_64.h in Headers */,
+				6C43CC9E1535032600162364 /* ffitarget.h in Headers */,
+				6C43CC9F1535032600162364 /* ffitarget_i386.h in Headers */,
+				6C43CCA01535032600162364 /* ffitarget_x86_64.h in Headers */,
+				6C43CC9B1535032600162364 /* fficonfig.h in Headers */,
+				6C43CC9C1535032600162364 /* fficonfig_i386.h in Headers */,
+				6C43CC9D1535032600162364 /* fficonfig_x86_64.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F6F980B8147386130008F121 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				6C43CCAD1535039600162364 /* ffi.h in Headers */,
+				6C43CCAE1535039600162364 /* ffi_armv7.h in Headers */,
+				6C43CCAF1535039600162364 /* ffi_common.h in Headers */,
+				6C43CCB01535039600162364 /* ffi_i386.h in Headers */,
+				6C43CCB41535039600162364 /* ffitarget.h in Headers */,
+				6C43CCB51535039600162364 /* ffitarget_arm.h in Headers */,
+				6C43CCB61535039600162364 /* ffitarget_armv7.h in Headers */,
+				6C43CCB71535039600162364 /* ffitarget_i386.h in Headers */,
+				6C43CCB11535039600162364 /* fficonfig.h in Headers */,
+				6C43CCB21535039600162364 /* fficonfig_armv7.h in Headers */,
+				6C43CCB31535039600162364 /* fficonfig_i386.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		6C43CB3C1534E9D100162364 /* libffi OS X */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 6C43CB4A1534E9D100162364 /* Build configuration list for PBXNativeTarget "libffi OS X" */;
+			buildPhases = (
+				6C43CC401534FF3B00162364 /* Generate Source and Headers */,
+				6C43CB391534E9D100162364 /* Sources */,
+				6C43CB3A1534E9D100162364 /* Frameworks */,
+				6C43CB3B1534E9D100162364 /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "libffi OS X";
+			productName = "ffi OS X";
+			productReference = 6C43CB3D1534E9D100162364 /* libffi.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		F6F980B9147386130008F121 /* libffi iOS */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = F6F980C4147386130008F121 /* Build configuration list for PBXNativeTarget "libffi iOS" */;
+			buildPhases = (
+				6C43CC3E1534F8E200162364 /* Generate Trampoline */,
+				6C43CC3F1534FF1B00162364 /* Generate Source and Headers */,
+				F6F980B6147386130008F121 /* Sources */,
+				F6F980B7147386130008F121 /* Frameworks */,
+				F6F980B8147386130008F121 /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "libffi iOS";
+			productName = ffi;
+			productReference = F6F980BA147386130008F121 /* libffi.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		F6B0839714721EE50031D8A1 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0430;
+			};
+			buildConfigurationList = F6B0839A14721EE50031D8A1 /* Build configuration list for PBXProject "libffi" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = F6B0839514721EE50031D8A1;
+			productRefGroup = F6B0839514721EE50031D8A1;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				F6F980B9147386130008F121 /* libffi iOS */,
+				6C43CB3C1534E9D100162364 /* libffi OS X */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		6C43CC3E1534F8E200162364 /* Generate Trampoline */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Generate Trampoline";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /usr/bin/python;
+			shellScript = "import subprocess\nimport re\nimport os\nimport errno\nimport sys\n\ndef main():\n    with open('src/arm/trampoline.S', 'w') as tramp_out:\n        p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out)\n        p.wait()\n\nif __name__ == '__main__':\n    main()";
+		};
+		6C43CC3F1534FF1B00162364 /* Generate Source and Headers */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Generate Source and Headers";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "/usr/bin/python generate-ios-source-and-headers.py";
+		};
+		6C43CC401534FF3B00162364 /* Generate Source and Headers */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Generate Source and Headers";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "/usr/bin/python generate-osx-source-and-headers.py";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		6C43CB391534E9D100162364 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				6C43CC1F1534F77800162364 /* darwin.S in Sources */,
+				6C43CC201534F77800162364 /* darwin64.S in Sources */,
+				6C43CC211534F77800162364 /* ffi.c in Sources */,
+				6C43CC221534F77800162364 /* ffi64.c in Sources */,
+				6C43CC301534F7BE00162364 /* closures.c in Sources */,
+				6C43CC361534F7BE00162364 /* java_raw_api.c in Sources */,
+				6C43CC381534F7BE00162364 /* prep_cif.c in Sources */,
+				6C43CC3A1534F7BE00162364 /* raw_api.c in Sources */,
+				6C43CC3C1534F7BE00162364 /* types.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F6F980B6147386130008F121 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				6C43CBDC1534F76F00162364 /* ffi.c in Sources */,
+				6C43CBDD1534F76F00162364 /* sysv.S in Sources */,
+				6C43CBDE1534F76F00162364 /* trampoline.S in Sources */,
+				6C43CBE61534F76F00162364 /* darwin.S in Sources */,
+				6C43CBE81534F76F00162364 /* ffi.c in Sources */,
+				6C43CC2F1534F7BE00162364 /* closures.c in Sources */,
+				6C43CC351534F7BE00162364 /* java_raw_api.c in Sources */,
+				6C43CC371534F7BE00162364 /* prep_cif.c in Sources */,
+				6C43CC391534F7BE00162364 /* raw_api.c in Sources */,
+				6C43CC3B1534F7BE00162364 /* types.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		6C43CB4B1534E9D100162364 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				DSTROOT = /tmp/ffi.dst;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
+				);
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.6;
+				ONLY_ACTIVE_ARCH = YES;
+				PRODUCT_NAME = ffi;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		6C43CB4C1534E9D100162364 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				DSTROOT = /tmp/ffi.dst;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
+				);
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.6;
+				PRODUCT_NAME = ffi;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		F6B083AB14721EE50031D8A1 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				COPY_PHASE_STRIP = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VALUE = NO;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = ios/include;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		F6B083AC14721EE50031D8A1 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				COPY_PHASE_STRIP = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VALUE = NO;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = ios/include;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		F6F980C2147386130008F121 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = (
+					armv6,
+					armv7,
+				);
+				DSTROOT = /tmp/ffi.dst;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_THUMB_SUPPORT = NO;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.0;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_NAME = ffi;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		F6F980C3147386130008F121 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = (
+					armv6,
+					armv7,
+				);
+				DSTROOT = /tmp/ffi.dst;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_THUMB_SUPPORT = NO;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.0;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_NAME = ffi;
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		6C43CB4A1534E9D100162364 /* Build configuration list for PBXNativeTarget "libffi OS X" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				6C43CB4B1534E9D100162364 /* Debug */,
+				6C43CB4C1534E9D100162364 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		F6B0839A14721EE50031D8A1 /* Build configuration list for PBXProject "libffi" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F6B083AB14721EE50031D8A1 /* Debug */,
+				F6B083AC14721EE50031D8A1 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		F6F980C4147386130008F121 /* Build configuration list for PBXNativeTarget "libffi iOS" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F6F980C2147386130008F121 /* Debug */,
+				F6F980C3147386130008F121 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = F6B0839714721EE50031D8A1 /* Project object */;
+}
diff --git a/third_party/gofrontend/libffi/libtool-version b/third_party/gofrontend/libffi/libtool-version
new file mode 100644
index 0000000..6753286
--- /dev/null
+++ b/third_party/gofrontend/libffi/libtool-version
@@ -0,0 +1,6 @@
+# This file is used to maintain libtool version info for libffi.  See
+# the libtool manual to understand the meaning of the fields.  This is
+# a separate file so that version updates don't involve re-running
+# automake.
+# CURRENT:REVISION:AGE
+4:1:0
diff --git a/third_party/gofrontend/libffi/man/Makefile.am b/third_party/gofrontend/libffi/man/Makefile.am
new file mode 100644
index 0000000..afcbfb6
--- /dev/null
+++ b/third_party/gofrontend/libffi/man/Makefile.am
@@ -0,0 +1,8 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS=foreign
+
+EXTRA_DIST = ffi.3 ffi_call.3 ffi_prep_cif.3 ffi_prep_cif_var.3
+
+man_MANS = ffi.3 ffi_call.3 ffi_prep_cif.3 ffi_prep_cif_var.3
+
diff --git a/third_party/gofrontend/libffi/man/Makefile.in b/third_party/gofrontend/libffi/man/Makefile.in
new file mode 100644
index 0000000..743e67b
--- /dev/null
+++ b/third_party/gofrontend/libffi/man/Makefile.in
@@ -0,0 +1,414 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = man
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+	$(top_srcdir)/../config/asmcfi.m4 \
+	$(top_srcdir)/../config/depstand.m4 \
+	$(top_srcdir)/../config/lead-dot.m4 \
+	$(top_srcdir)/../config/multi.m4 \
+	$(top_srcdir)/../config/override.m4 \
+	$(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \
+	$(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
+	$(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/fficonfig.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+man3dir = $(mandir)/man3
+am__installdirs = "$(DESTDIR)$(man3dir)"
+NROFF = nroff
+MANS = $(man_MANS)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_LTLDFLAGS = @AM_LTLDFLAGS@
+AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
+HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARGET = @TARGET@
+TARGETDIR = @TARGETDIR@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign
+EXTRA_DIST = ffi.3 ffi_call.3 ffi_prep_cif.3 ffi_prep_cif_var.3
+man_MANS = ffi.3 ffi_call.3 ffi_prep_cif.3 ffi_prep_cif_var.3
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign man/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign man/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-man3: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)"
+	@list=''; test -n "$(man3dir)" || exit 0; \
+	{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.3[a-z]*$$/p'; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man3:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man3dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.3[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	test -z "$$files" || { \
+	  echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \
+	  cd "$(DESTDIR)$(man3dir)" && rm -f $$files; }
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+check-am: all-am
+check: check-am
+all-am: Makefile $(MANS)
+installdirs:
+	for dir in "$(DESTDIR)$(man3dir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man3
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man
+
+uninstall-man: uninstall-man3
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+	distclean distclean-generic distclean-libtool dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-man3 install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+	uninstall-man uninstall-man3
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/third_party/gofrontend/libffi/man/ffi.3 b/third_party/gofrontend/libffi/man/ffi.3
new file mode 100644
index 0000000..1f1d303
--- /dev/null
+++ b/third_party/gofrontend/libffi/man/ffi.3
@@ -0,0 +1,41 @@
+.Dd February 15, 2008
+.Dt FFI 3
+.Sh NAME
+.Nm FFI
+.Nd Foreign Function Interface
+.Sh LIBRARY
+libffi, -lffi
+.Sh SYNOPSIS
+.In ffi.h
+.Ft ffi_status
+.Fo ffi_prep_cif
+.Fa "ffi_cif *cif"
+.Fa "ffi_abi abi"
+.Fa "unsigned int nargs"
+.Fa "ffi_type *rtype"
+.Fa "ffi_type **atypes"
+.Fc
+.Ft void
+.Fo ffi_prep_cif_var
+.Fa "ffi_cif *cif"
+.Fa "ffi_abi abi"
+.Fa "unsigned int nfixedargs"
+.Fa "unsigned int ntotalargs"
+.Fa "ffi_type *rtype"
+.Fa "ffi_type **atypes"
+.Fc
+.Ft void
+.Fo ffi_call
+.Fa "ffi_cif *cif"
+.Fa "void (*fn)(void)"
+.Fa "void *rvalue"
+.Fa "void **avalue"
+.Fc
+.Sh DESCRIPTION
+The foreign function interface provides a mechanism by which a function can
+generate a call to another function at runtime without requiring knowledge of
+the called function's interface at compile time.
+.Sh SEE ALSO
+.Xr ffi_prep_cif 3 ,
+.Xr ffi_prep_cif_var 3 ,
+.Xr ffi_call 3
diff --git a/third_party/gofrontend/libffi/man/ffi_call.3 b/third_party/gofrontend/libffi/man/ffi_call.3
new file mode 100644
index 0000000..5351513
--- /dev/null
+++ b/third_party/gofrontend/libffi/man/ffi_call.3
@@ -0,0 +1,103 @@
+.Dd February 15, 2008
+.Dt ffi_call 3
+.Sh NAME
+.Nm ffi_call
+.Nd Invoke a foreign function.
+.Sh SYNOPSIS
+.In ffi.h
+.Ft void
+.Fo ffi_call
+.Fa "ffi_cif *cif"
+.Fa "void (*fn)(void)"
+.Fa "void *rvalue"
+.Fa "void **avalue"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm ffi_call
+function provides a simple mechanism for invoking a function without
+requiring knowledge of the function's interface at compile time.
+.Fa fn
+is called with the values retrieved from the pointers in the
+.Fa avalue
+array. The return value from
+.Fa fn
+is placed in storage pointed to by
+.Fa rvalue .
+.Fa cif
+contains information describing the data types, sizes and alignments of the
+arguments to and return value from
+.Fa fn ,
+and must be initialized with
+.Nm ffi_prep_cif
+before it is used with
+.Nm ffi_call .
+.Pp
+.Fa rvalue
+must point to storage that is sizeof(ffi_arg) or larger for non-floating point
+types. For smaller-sized return value types, the
+.Nm ffi_arg
+or
+.Nm ffi_sarg
+integral type must be used to hold
+the return value.
+.Sh EXAMPLES
+.Bd -literal
+#include <ffi.h>
+#include <stdio.h>
+
+unsigned char
+foo(unsigned int, float);
+
+int
+main(int argc, const char **argv)
+{
+    ffi_cif cif;
+    ffi_type *arg_types[2];
+    void *arg_values[2];
+    ffi_status status;
+
+    // Because the return value from foo() is smaller than sizeof(long), it
+    // must be passed as ffi_arg or ffi_sarg.
+    ffi_arg result;
+
+    // Specify the data type of each argument. Available types are defined
+    // in <ffi/ffi.h>.
+    arg_types[0] = &ffi_type_uint;
+    arg_types[1] = &ffi_type_float;
+
+    // Prepare the ffi_cif structure.
+    if ((status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
+        2, &ffi_type_uint8, arg_types)) != FFI_OK)
+    {
+        // Handle the ffi_status error.
+    }
+
+    // Specify the values of each argument.
+    unsigned int arg1 = 42;
+    float arg2 = 5.1;
+
+    arg_values[0] = &arg1;
+    arg_values[1] = &arg2;
+
+    // Invoke the function.
+    ffi_call(&cif, FFI_FN(foo), &result, arg_values);
+
+    // The ffi_arg 'result' now contains the unsigned char returned from foo(),
+    // which can be accessed by a typecast.
+    printf("result is %hhu", (unsigned char)result);
+
+    return 0;
+}
+
+// The target function.
+unsigned char
+foo(unsigned int x, float y)
+{
+    unsigned char result = x - y;
+    return result;
+}
+.Ed
+.Sh SEE ALSO
+.Xr ffi 3 ,
+.Xr ffi_prep_cif 3
diff --git a/third_party/gofrontend/libffi/man/ffi_prep_cif.3 b/third_party/gofrontend/libffi/man/ffi_prep_cif.3
new file mode 100644
index 0000000..e1bdbd7
--- /dev/null
+++ b/third_party/gofrontend/libffi/man/ffi_prep_cif.3
@@ -0,0 +1,70 @@
+.Dd February 15, 2008
+.Dt ffi_prep_cif 3
+.Sh NAME
+.Nm ffi_prep_cif
+.Nd Prepare a
+.Nm ffi_cif
+structure for use with
+.Nm ffi_call 
+.
+.Sh SYNOPSIS
+.In ffi.h
+.Ft ffi_status
+.Fo ffi_prep_cif
+.Fa "ffi_cif *cif"
+.Fa "ffi_abi abi"
+.Fa "unsigned int nargs"
+.Fa "ffi_type *rtype"
+.Fa "ffi_type **atypes"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm ffi_prep_cif
+function prepares a
+.Nm ffi_cif
+structure for use with 
+.Nm ffi_call
+.
+.Fa abi
+specifies a set of calling conventions to use.
+.Fa atypes
+is an array of
+.Fa nargs
+pointers to
+.Nm ffi_type
+structs that describe the data type, size and alignment of each argument.
+.Fa rtype
+points to an
+.Nm ffi_type
+that describes the data type, size and alignment of the
+return value. Note that to call a variadic function
+.Nm ffi_prep_cif_var
+must be used instead.
+.Sh RETURN VALUES
+Upon successful completion,
+.Nm ffi_prep_cif
+returns
+.Nm FFI_OK .
+It will return
+.Nm FFI_BAD_TYPEDEF
+if
+.Fa cif
+is
+.Nm NULL
+or
+.Fa atypes
+or
+.Fa rtype
+is malformed. If
+.Fa abi
+does not refer to a valid ABI,
+.Nm FFI_BAD_ABI
+will be returned. Available ABIs are
+defined in
+.Nm <ffitarget.h>
+.
+.Sh SEE ALSO
+.Xr ffi 3 ,
+.Xr ffi_call 3 ,
+.Xr ffi_prep_cif_var 3
+
diff --git a/third_party/gofrontend/libffi/man/ffi_prep_cif_var.3 b/third_party/gofrontend/libffi/man/ffi_prep_cif_var.3
new file mode 100644
index 0000000..7e19d0b
--- /dev/null
+++ b/third_party/gofrontend/libffi/man/ffi_prep_cif_var.3
@@ -0,0 +1,73 @@
+.Dd January 25, 2011
+.Dt ffi_prep_cif_var 3
+.Sh NAME
+.Nm ffi_prep_cif_var
+.Nd Prepare a
+.Nm ffi_cif
+structure for use with
+.Nm ffi_call
+for variadic functions.
+.Sh SYNOPSIS
+.In ffi.h
+.Ft ffi_status
+.Fo ffi_prep_cif_var
+.Fa "ffi_cif *cif"
+.Fa "ffi_abi abi"
+.Fa "unsigned int nfixedargs"
+.Fa "unsigned int ntotalargs"
+.Fa "ffi_type *rtype"
+.Fa "ffi_type **atypes"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm ffi_prep_cif_var
+function prepares a
+.Nm ffi_cif
+structure for use with
+.Nm ffi_call
+for variadic functions.
+.Fa abi
+specifies a set of calling conventions to use.
+.Fa atypes
+is an array of
+.Fa ntotalargs
+pointers to
+.Nm ffi_type
+structs that describe the data type, size and alignment of each argument.
+.Fa rtype
+points to an
+.Nm ffi_type
+that describes the data type, size and alignment of the
+return value.
+.Fa nfixedargs
+must contain the number of fixed (non-variadic) arguments.
+Note that to call a non-variadic function
+.Nm ffi_prep_cif
+must be used.
+.Sh RETURN VALUES
+Upon successful completion,
+.Nm ffi_prep_cif_var
+returns
+.Nm FFI_OK .
+It will return
+.Nm FFI_BAD_TYPEDEF
+if
+.Fa cif
+is
+.Nm NULL
+or
+.Fa atypes
+or
+.Fa rtype
+is malformed. If
+.Fa abi
+does not refer to a valid ABI,
+.Nm FFI_BAD_ABI
+will be returned. Available ABIs are
+defined in
+.Nm <ffitarget.h>
+.
+.Sh SEE ALSO
+.Xr ffi 3 ,
+.Xr ffi_call 3 ,
+.Xr ffi_prep_cif 3
diff --git a/third_party/gofrontend/libffi/mdate-sh b/third_party/gofrontend/libffi/mdate-sh
new file mode 100644
index 0000000..e631b22
--- /dev/null
+++ b/third_party/gofrontend/libffi/mdate-sh
@@ -0,0 +1,205 @@
+#!/bin/sh
+# Get modification time of a file or directory and pretty-print it.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1995, 1996, 1997, 2003, 2004, 2005, 2007, 2009 Free
+# Software Foundation, Inc.
+# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case $1 in
+  '')
+     echo "$0: No file.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: mdate-sh [--help] [--version] FILE
+
+Pretty-print the modification time of FILE.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "mdate-sh $scriptversion"
+    exit $?
+    ;;
+esac
+
+# Prevent date giving response in another language.
+LANG=C
+export LANG
+LC_ALL=C
+export LC_ALL
+LC_TIME=C
+export LC_TIME
+
+# GNU ls changes its time format in response to the TIME_STYLE
+# variable.  Since we cannot assume `unset' works, revert this
+# variable to its documented default.
+if test "${TIME_STYLE+set}" = set; then
+  TIME_STYLE=posix-long-iso
+  export TIME_STYLE
+fi
+
+save_arg1=$1
+
+# Find out how to get the extended ls output of a file or directory.
+if ls -L /dev/null 1>/dev/null 2>&1; then
+  ls_command='ls -L -l -d'
+else
+  ls_command='ls -l -d'
+fi
+# Avoid user/group names that might have spaces, when possible.
+if ls -n /dev/null 1>/dev/null 2>&1; then
+  ls_command="$ls_command -n"
+fi
+
+# A `ls -l' line looks as follows on OS/2.
+#  drwxrwx---        0 Aug 11  2001 foo
+# This differs from Unix, which adds ownership information.
+#  drwxrwx---   2 root  root      4096 Aug 11  2001 foo
+#
+# To find the date, we split the line on spaces and iterate on words
+# until we find a month.  This cannot work with files whose owner is a
+# user named `Jan', or `Feb', etc.  However, it's unlikely that `/'
+# will be owned by a user whose name is a month.  So we first look at
+# the extended ls output of the root directory to decide how many
+# words should be skipped to get the date.
+
+# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below.
+set x`$ls_command /`
+
+# Find which argument is the month.
+month=
+command=
+until test $month
+do
+  shift
+  # Add another shift to the command.
+  command="$command shift;"
+  case $1 in
+    Jan) month=January; nummonth=1;;
+    Feb) month=February; nummonth=2;;
+    Mar) month=March; nummonth=3;;
+    Apr) month=April; nummonth=4;;
+    May) month=May; nummonth=5;;
+    Jun) month=June; nummonth=6;;
+    Jul) month=July; nummonth=7;;
+    Aug) month=August; nummonth=8;;
+    Sep) month=September; nummonth=9;;
+    Oct) month=October; nummonth=10;;
+    Nov) month=November; nummonth=11;;
+    Dec) month=December; nummonth=12;;
+  esac
+done
+
+# Get the extended ls output of the file or directory.
+set dummy x`eval "$ls_command \"\$save_arg1\""`
+
+# Remove all preceding arguments
+eval $command
+
+# Because of the dummy argument above, month is in $2.
+#
+# On a POSIX system, we should have
+#
+# $# = 5
+# $1 = file size
+# $2 = month
+# $3 = day
+# $4 = year or time
+# $5 = filename
+#
+# On Darwin 7.7.0 and 7.6.0, we have
+#
+# $# = 4
+# $1 = day
+# $2 = month
+# $3 = year or time
+# $4 = filename
+
+# Get the month.
+case $2 in
+  Jan) month=January; nummonth=1;;
+  Feb) month=February; nummonth=2;;
+  Mar) month=March; nummonth=3;;
+  Apr) month=April; nummonth=4;;
+  May) month=May; nummonth=5;;
+  Jun) month=June; nummonth=6;;
+  Jul) month=July; nummonth=7;;
+  Aug) month=August; nummonth=8;;
+  Sep) month=September; nummonth=9;;
+  Oct) month=October; nummonth=10;;
+  Nov) month=November; nummonth=11;;
+  Dec) month=December; nummonth=12;;
+esac
+
+case $3 in
+  ???*) day=$1;;
+  *) day=$3; shift;;
+esac
+
+# Here we have to deal with the problem that the ls output gives either
+# the time of day or the year.
+case $3 in
+  *:*) set `date`; eval year=\$$#
+       case $2 in
+	 Jan) nummonthtod=1;;
+	 Feb) nummonthtod=2;;
+	 Mar) nummonthtod=3;;
+	 Apr) nummonthtod=4;;
+	 May) nummonthtod=5;;
+	 Jun) nummonthtod=6;;
+	 Jul) nummonthtod=7;;
+	 Aug) nummonthtod=8;;
+	 Sep) nummonthtod=9;;
+	 Oct) nummonthtod=10;;
+	 Nov) nummonthtod=11;;
+	 Dec) nummonthtod=12;;
+       esac
+       # For the first six month of the year the time notation can also
+       # be used for files modified in the last year.
+       if (expr $nummonth \> $nummonthtod) > /dev/null;
+       then
+	 year=`expr $year - 1`
+       fi;;
+  *) year=$3;;
+esac
+
+# The result.
+echo $day $month $year
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/third_party/gofrontend/libffi/src/aarch64/ffi.c b/third_party/gofrontend/libffi/src/aarch64/ffi.c
new file mode 100644
index 0000000..1405665
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/aarch64/ffi.c
@@ -0,0 +1,1076 @@
+/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+``Software''), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include <stdio.h>
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* Stack alignment requirement in bytes */
+#define AARCH64_STACK_ALIGN 16
+
+#define N_X_ARG_REG 8
+#define N_V_ARG_REG 8
+
+#define AARCH64_FFI_WITH_V (1 << AARCH64_FFI_WITH_V_BIT)
+
+union _d
+{
+  UINT64 d;
+  UINT32 s[2];
+};
+
+struct call_context
+{
+  UINT64 x [AARCH64_N_XREG];
+  struct
+  {
+    union _d d[2];
+  } v [AARCH64_N_VREG];
+};
+
+static void *
+get_x_addr (struct call_context *context, unsigned n)
+{
+  return &context->x[n];
+}
+
+static void *
+get_s_addr (struct call_context *context, unsigned n)
+{
+#if defined __AARCH64EB__
+  return &context->v[n].d[1].s[1];
+#else
+  return &context->v[n].d[0].s[0];
+#endif
+}
+
+static void *
+get_d_addr (struct call_context *context, unsigned n)
+{
+#if defined __AARCH64EB__
+  return &context->v[n].d[1];
+#else
+  return &context->v[n].d[0];
+#endif
+}
+
+static void *
+get_v_addr (struct call_context *context, unsigned n)
+{
+  return &context->v[n];
+}
+
+/* Return the memory location at which a basic type would reside
+   were it to have been stored in register n.  */
+
+static void *
+get_basic_type_addr (unsigned short type, struct call_context *context,
+		     unsigned n)
+{
+  switch (type)
+    {
+    case FFI_TYPE_FLOAT:
+      return get_s_addr (context, n);
+    case FFI_TYPE_DOUBLE:
+      return get_d_addr (context, n);
+    case FFI_TYPE_LONGDOUBLE:
+      return get_v_addr (context, n);
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_INT:
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      return get_x_addr (context, n);
+    default:
+      FFI_ASSERT (0);
+      return NULL;
+    }
+}
+
+/* Return the alignment width for each of the basic types.  */
+
+static size_t
+get_basic_type_alignment (unsigned short type)
+{
+  switch (type)
+    {
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      return sizeof (UINT64);
+    case FFI_TYPE_LONGDOUBLE:
+      return sizeof (long double);
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      return sizeof (UINT64);
+
+    default:
+      FFI_ASSERT (0);
+      return 0;
+    }
+}
+
+/* Return the size in bytes for each of the basic types.  */
+
+static size_t
+get_basic_type_size (unsigned short type)
+{
+  switch (type)
+    {
+    case FFI_TYPE_FLOAT:
+      return sizeof (UINT32);
+    case FFI_TYPE_DOUBLE:
+      return sizeof (UINT64);
+    case FFI_TYPE_LONGDOUBLE:
+      return sizeof (long double);
+    case FFI_TYPE_UINT8:
+      return sizeof (UINT8);
+    case FFI_TYPE_SINT8:
+      return sizeof (SINT8);
+    case FFI_TYPE_UINT16:
+      return sizeof (UINT16);
+    case FFI_TYPE_SINT16:
+      return sizeof (SINT16);
+    case FFI_TYPE_UINT32:
+      return sizeof (UINT32);
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+      return sizeof (SINT32);
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_UINT64:
+      return sizeof (UINT64);
+    case FFI_TYPE_SINT64:
+      return sizeof (SINT64);
+
+    default:
+      FFI_ASSERT (0);
+      return 0;
+    }
+}
+
+extern void
+ffi_call_SYSV (unsigned (*)(struct call_context *context, unsigned char *,
+			    extended_cif *),
+               struct call_context *context,
+               extended_cif *,
+               unsigned,
+               void (*fn)(void));
+
+extern void
+ffi_closure_SYSV (ffi_closure *);
+
+/* Test for an FFI floating point representation.  */
+
+static unsigned
+is_floating_type (unsigned short type)
+{
+  return (type == FFI_TYPE_FLOAT || type == FFI_TYPE_DOUBLE
+	  || type == FFI_TYPE_LONGDOUBLE);
+}
+
+/* Test for a homogeneous structure.  */
+
+static unsigned short
+get_homogeneous_type (ffi_type *ty)
+{
+  if (ty->type == FFI_TYPE_STRUCT && ty->elements)
+    {
+      unsigned i;
+      unsigned short candidate_type
+	= get_homogeneous_type (ty->elements[0]);
+      for (i =1; ty->elements[i]; i++)
+	{
+	  unsigned short iteration_type = 0;
+	  /* If we have a nested struct, we must find its homogeneous type.
+	     If that fits with our candidate type, we are still
+	     homogeneous.  */
+	  if (ty->elements[i]->type == FFI_TYPE_STRUCT
+	      && ty->elements[i]->elements)
+	    {
+	      iteration_type = get_homogeneous_type (ty->elements[i]);
+	    }
+	  else
+	    {
+	      iteration_type = ty->elements[i]->type;
+	    }
+
+	  /* If we are not homogeneous, return FFI_TYPE_STRUCT.  */
+	  if (candidate_type != iteration_type)
+	    return FFI_TYPE_STRUCT;
+	}
+      return candidate_type;
+    }
+
+  /* Base case, we have no more levels of nesting, so we
+     are a basic type, and so, trivially homogeneous in that type.  */
+  return ty->type;
+}
+
+/* Determine the number of elements within a STRUCT.
+
+   Note, we must handle nested structs.
+
+   If ty is not a STRUCT this function will return 0.  */
+
+static unsigned
+element_count (ffi_type *ty)
+{
+  if (ty->type == FFI_TYPE_STRUCT && ty->elements)
+    {
+      unsigned n;
+      unsigned elems = 0;
+      for (n = 0; ty->elements[n]; n++)
+	{
+	  if (ty->elements[n]->type == FFI_TYPE_STRUCT
+	      && ty->elements[n]->elements)
+	    elems += element_count (ty->elements[n]);
+	  else
+	    elems++;
+	}
+      return elems;
+    }
+  return 0;
+}
+
+/* Test for a homogeneous floating point aggregate.
+
+   A homogeneous floating point aggregate is a homogeneous aggregate of
+   a half- single- or double- precision floating point type with one
+   to four elements.  Note that this includes nested structs of the
+   basic type.  */
+
+static int
+is_hfa (ffi_type *ty)
+{
+  if (ty->type == FFI_TYPE_STRUCT
+      && ty->elements[0]
+      && is_floating_type (get_homogeneous_type (ty)))
+    {
+      unsigned n = element_count (ty);
+      return n >= 1 && n <= 4;
+    }
+  return 0;
+}
+
+/* Test if an ffi_type is a candidate for passing in a register.
+
+   This test does not check that sufficient registers of the
+   appropriate class are actually available, merely that IFF
+   sufficient registers are available then the argument will be passed
+   in register(s).
+
+   Note that an ffi_type that is deemed to be a register candidate
+   will always be returned in registers.
+
+   Returns 1 if a register candidate else 0.  */
+
+static int
+is_register_candidate (ffi_type *ty)
+{
+  switch (ty->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_LONGDOUBLE:
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT64:
+      return 1;
+
+    case FFI_TYPE_STRUCT:
+      if (is_hfa (ty))
+        {
+          return 1;
+        }
+      else if (ty->size > 16)
+        {
+          /* Too large. Will be replaced with a pointer to memory. The
+             pointer MAY be passed in a register, but the value will
+             not. This test specifically fails since the argument will
+             never be passed by value in registers. */
+          return 0;
+        }
+      else
+        {
+          /* Might be passed in registers depending on the number of
+             registers required. */
+          return (ty->size + 7) / 8 < N_X_ARG_REG;
+        }
+      break;
+
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+
+  return 0;
+}
+
+/* Test if an ffi_type argument or result is a candidate for a vector
+   register.  */
+
+static int
+is_v_register_candidate (ffi_type *ty)
+{
+  return is_floating_type (ty->type)
+	   || (ty->type == FFI_TYPE_STRUCT && is_hfa (ty));
+}
+
+/* Representation of the procedure call argument marshalling
+   state.
+
+   The terse state variable names match the names used in the AARCH64
+   PCS. */
+
+struct arg_state
+{
+  unsigned ngrn;                /* Next general-purpose register number. */
+  unsigned nsrn;                /* Next vector register number. */
+  unsigned nsaa;                /* Next stack offset. */
+};
+
+/* Initialize a procedure call argument marshalling state.  */
+static void
+arg_init (struct arg_state *state, unsigned call_frame_size)
+{
+  state->ngrn = 0;
+  state->nsrn = 0;
+  state->nsaa = 0;
+}
+
+/* Return the number of available consecutive core argument
+   registers.  */
+
+static unsigned
+available_x (struct arg_state *state)
+{
+  return N_X_ARG_REG - state->ngrn;
+}
+
+/* Return the number of available consecutive vector argument
+   registers.  */
+
+static unsigned
+available_v (struct arg_state *state)
+{
+  return N_V_ARG_REG - state->nsrn;
+}
+
+static void *
+allocate_to_x (struct call_context *context, struct arg_state *state)
+{
+  FFI_ASSERT (state->ngrn < N_X_ARG_REG)
+  return get_x_addr (context, (state->ngrn)++);
+}
+
+static void *
+allocate_to_s (struct call_context *context, struct arg_state *state)
+{
+  FFI_ASSERT (state->nsrn < N_V_ARG_REG)
+  return get_s_addr (context, (state->nsrn)++);
+}
+
+static void *
+allocate_to_d (struct call_context *context, struct arg_state *state)
+{
+  FFI_ASSERT (state->nsrn < N_V_ARG_REG)
+  return get_d_addr (context, (state->nsrn)++);
+}
+
+static void *
+allocate_to_v (struct call_context *context, struct arg_state *state)
+{
+  FFI_ASSERT (state->nsrn < N_V_ARG_REG)
+  return get_v_addr (context, (state->nsrn)++);
+}
+
+/* Allocate an aligned slot on the stack and return a pointer to it.  */
+static void *
+allocate_to_stack (struct arg_state *state, void *stack, unsigned alignment,
+		   unsigned size)
+{
+  void *allocation;
+
+  /* Round up the NSAA to the larger of 8 or the natural
+     alignment of the argument's type.  */
+  state->nsaa = ALIGN (state->nsaa, alignment);
+  state->nsaa = ALIGN (state->nsaa, alignment);
+  state->nsaa = ALIGN (state->nsaa, 8);
+
+  allocation = stack + state->nsaa;
+
+  state->nsaa += size;
+  return allocation;
+}
+
+static void
+copy_basic_type (void *dest, void *source, unsigned short type)
+{
+  /* This is neccessary to ensure that basic types are copied
+     sign extended to 64-bits as libffi expects.  */
+  switch (type)
+    {
+    case FFI_TYPE_FLOAT:
+      *(float *) dest = *(float *) source;
+      break;
+    case FFI_TYPE_DOUBLE:
+      *(double *) dest = *(double *) source;
+      break;
+    case FFI_TYPE_LONGDOUBLE:
+      *(long double *) dest = *(long double *) source;
+      break;
+    case FFI_TYPE_UINT8:
+      *(ffi_arg *) dest = *(UINT8 *) source;
+      break;
+    case FFI_TYPE_SINT8:
+      *(ffi_sarg *) dest = *(SINT8 *) source;
+      break;
+    case FFI_TYPE_UINT16:
+      *(ffi_arg *) dest = *(UINT16 *) source;
+      break;
+    case FFI_TYPE_SINT16:
+      *(ffi_sarg *) dest = *(SINT16 *) source;
+      break;
+    case FFI_TYPE_UINT32:
+      *(ffi_arg *) dest = *(UINT32 *) source;
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+      *(ffi_sarg *) dest = *(SINT32 *) source;
+      break;
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_UINT64:
+      *(ffi_arg *) dest = *(UINT64 *) source;
+      break;
+    case FFI_TYPE_SINT64:
+      *(ffi_sarg *) dest = *(SINT64 *) source;
+      break;
+
+    default:
+      FFI_ASSERT (0);
+    }
+}
+
+static void
+copy_hfa_to_reg_or_stack (void *memory,
+			  ffi_type *ty,
+			  struct call_context *context,
+			  unsigned char *stack,
+			  struct arg_state *state)
+{
+  unsigned elems = element_count (ty);
+  if (available_v (state) < elems)
+    {
+      /* There are insufficient V registers. Further V register allocations
+	 are prevented, the NSAA is adjusted (by allocate_to_stack ())
+	 and the argument is copied to memory at the adjusted NSAA.  */
+      state->nsrn = N_V_ARG_REG;
+      memcpy (allocate_to_stack (state, stack, ty->alignment, ty->size),
+	      memory,
+	      ty->size);
+    }
+  else
+    {
+      int i;
+      unsigned short type = get_homogeneous_type (ty);
+      unsigned elems = element_count (ty);
+      for (i = 0; i < elems; i++)
+	{
+	  void *reg = allocate_to_v (context, state);
+	  copy_basic_type (reg, memory, type);
+	  memory += get_basic_type_size (type);
+	}
+    }
+}
+
+/* Either allocate an appropriate register for the argument type, or if
+   none are available, allocate a stack slot and return a pointer
+   to the allocated space.  */
+
+static void *
+allocate_to_register_or_stack (struct call_context *context,
+			       unsigned char *stack,
+			       struct arg_state *state,
+			       unsigned short type)
+{
+  size_t alignment = get_basic_type_alignment (type);
+  size_t size = alignment;
+  switch (type)
+    {
+    case FFI_TYPE_FLOAT:
+      /* This is the only case for which the allocated stack size
+	 should not match the alignment of the type.  */
+      size = sizeof (UINT32);
+      /* Fall through.  */
+    case FFI_TYPE_DOUBLE:
+      if (state->nsrn < N_V_ARG_REG)
+	return allocate_to_d (context, state);
+      state->nsrn = N_V_ARG_REG;
+      break;
+    case FFI_TYPE_LONGDOUBLE:
+      if (state->nsrn < N_V_ARG_REG)
+	return allocate_to_v (context, state);
+      state->nsrn = N_V_ARG_REG;
+      break;
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_INT:
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      if (state->ngrn < N_X_ARG_REG)
+	return allocate_to_x (context, state);
+      state->ngrn = N_X_ARG_REG;
+      break;
+    default:
+      FFI_ASSERT (0);
+    }
+
+    return allocate_to_stack (state, stack, alignment, size);
+}
+
+/* Copy a value to an appropriate register, or if none are
+   available, to the stack.  */
+
+static void
+copy_to_register_or_stack (struct call_context *context,
+			   unsigned char *stack,
+			   struct arg_state *state,
+			   void *value,
+			   unsigned short type)
+{
+  copy_basic_type (
+	  allocate_to_register_or_stack (context, stack, state, type),
+	  value,
+	  type);
+}
+
+/* Marshall the arguments from FFI representation to procedure call
+   context and stack.  */
+
+static unsigned
+aarch64_prep_args (struct call_context *context, unsigned char *stack,
+		   extended_cif *ecif)
+{
+  int i;
+  struct arg_state state;
+
+  arg_init (&state, ALIGN(ecif->cif->bytes, 16));
+
+  for (i = 0; i < ecif->cif->nargs; i++)
+    {
+      ffi_type *ty = ecif->cif->arg_types[i];
+      switch (ty->type)
+	{
+	case FFI_TYPE_VOID:
+	  FFI_ASSERT (0);
+	  break;
+
+	/* If the argument is a basic type the argument is allocated to an
+	   appropriate register, or if none are available, to the stack.  */
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_LONGDOUBLE:
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_INT:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_POINTER:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	  copy_to_register_or_stack (context, stack, &state,
+				     ecif->avalue[i], ty->type);
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  if (is_hfa (ty))
+	    {
+	      copy_hfa_to_reg_or_stack (ecif->avalue[i], ty, context,
+					stack, &state);
+	    }
+	  else if (ty->size > 16)
+	    {
+	      /* If the argument is a composite type that is larger than 16
+		 bytes, then the argument has been copied to memory, and
+		 the argument is replaced by a pointer to the copy.  */
+
+	      copy_to_register_or_stack (context, stack, &state,
+					 &(ecif->avalue[i]), FFI_TYPE_POINTER);
+	    }
+	  else if (available_x (&state) >= (ty->size + 7) / 8)
+	    {
+	      /* If the argument is a composite type and the size in
+		 double-words is not more than the number of available
+		 X registers, then the argument is copied into consecutive
+		 X registers.  */
+	      int j;
+	      for (j = 0; j < (ty->size + 7) / 8; j++)
+		{
+		  memcpy (allocate_to_x (context, &state),
+			  &(((UINT64 *) ecif->avalue[i])[j]),
+			  sizeof (UINT64));
+		}
+	    }
+	  else
+	    {
+	      /* Otherwise, there are insufficient X registers. Further X
+		 register allocations are prevented, the NSAA is adjusted
+		 (by allocate_to_stack ()) and the argument is copied to
+		 memory at the adjusted NSAA.  */
+	      state.ngrn = N_X_ARG_REG;
+
+	      memcpy (allocate_to_stack (&state, stack, ty->alignment,
+					 ty->size), ecif->avalue + i, ty->size);
+	    }
+	  break;
+
+	default:
+	  FFI_ASSERT (0);
+	  break;
+	}
+    }
+
+  return ecif->cif->aarch64_flags;
+}
+
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  /* Round the stack up to a multiple of the stack alignment requirement. */
+  cif->bytes =
+    (cif->bytes + (AARCH64_STACK_ALIGN - 1)) & ~ (AARCH64_STACK_ALIGN - 1);
+
+  /* Initialize our flags. We are interested if this CIF will touch a
+     vector register, if so we will enable context save and load to
+     those registers, otherwise not. This is intended to be friendly
+     to lazy float context switching in the kernel.  */
+  cif->aarch64_flags = 0;
+
+  if (is_v_register_candidate (cif->rtype))
+    {
+      cif->aarch64_flags |= AARCH64_FFI_WITH_V;
+    }
+  else
+    {
+      int i;
+      for (i = 0; i < cif->nargs; i++)
+        if (is_v_register_candidate (cif->arg_types[i]))
+          {
+            cif->aarch64_flags |= AARCH64_FFI_WITH_V;
+            break;
+          }
+    }
+
+  return FFI_OK;
+}
+
+/* Call a function with the provided arguments and capture the return
+   value.  */
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  ecif.rvalue = rvalue;
+
+  switch (cif->abi)
+    {
+    case FFI_SYSV:
+      {
+        struct call_context context;
+	unsigned stack_bytes;
+
+	/* Figure out the total amount of stack space we need, the
+	   above call frame space needs to be 16 bytes aligned to
+	   ensure correct alignment of the first object inserted in
+	   that space hence the ALIGN applied to cif->bytes.*/
+	stack_bytes = ALIGN(cif->bytes, 16);
+
+	memset (&context, 0, sizeof (context));
+        if (is_register_candidate (cif->rtype))
+          {
+            ffi_call_SYSV (aarch64_prep_args, &context, &ecif, stack_bytes, fn);
+            switch (cif->rtype->type)
+              {
+              case FFI_TYPE_VOID:
+              case FFI_TYPE_FLOAT:
+              case FFI_TYPE_DOUBLE:
+              case FFI_TYPE_LONGDOUBLE:
+              case FFI_TYPE_UINT8:
+              case FFI_TYPE_SINT8:
+              case FFI_TYPE_UINT16:
+              case FFI_TYPE_SINT16:
+              case FFI_TYPE_UINT32:
+              case FFI_TYPE_SINT32:
+              case FFI_TYPE_POINTER:
+              case FFI_TYPE_UINT64:
+              case FFI_TYPE_INT:
+              case FFI_TYPE_SINT64:
+		{
+		  void *addr = get_basic_type_addr (cif->rtype->type,
+						    &context, 0);
+		  copy_basic_type (rvalue, addr, cif->rtype->type);
+		  break;
+		}
+
+              case FFI_TYPE_STRUCT:
+                if (is_hfa (cif->rtype))
+		  {
+		    int j;
+		    unsigned short type = get_homogeneous_type (cif->rtype);
+		    unsigned elems = element_count (cif->rtype);
+		    for (j = 0; j < elems; j++)
+		      {
+			void *reg = get_basic_type_addr (type, &context, j);
+			copy_basic_type (rvalue, reg, type);
+			rvalue += get_basic_type_size (type);
+		      }
+		  }
+                else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
+                  {
+                    unsigned size = ALIGN (cif->rtype->size, sizeof (UINT64));
+                    memcpy (rvalue, get_x_addr (&context, 0), size);
+                  }
+                else
+                  {
+                    FFI_ASSERT (0);
+                  }
+                break;
+
+              default:
+                FFI_ASSERT (0);
+                break;
+              }
+          }
+        else
+          {
+            memcpy (get_x_addr (&context, 8), &rvalue, sizeof (UINT64));
+            ffi_call_SYSV (aarch64_prep_args, &context, &ecif,
+			   stack_bytes, fn);
+          }
+        break;
+      }
+
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+}
+
+static unsigned char trampoline [] =
+{ 0x70, 0x00, 0x00, 0x58,	/* ldr	x16, 1f	*/
+  0x91, 0x00, 0x00, 0x10,	/* adr	x17, 2f	*/
+  0x00, 0x02, 0x1f, 0xd6	/* br	x16	*/
+};
+
+/* Build a trampoline.  */
+
+#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS)			\
+  ({unsigned char *__tramp = (unsigned char*)(TRAMP);			\
+    UINT64  __fun = (UINT64)(FUN);					\
+    UINT64  __ctx = (UINT64)(CTX);					\
+    UINT64  __flags = (UINT64)(FLAGS);					\
+    memcpy (__tramp, trampoline, sizeof (trampoline));			\
+    memcpy (__tramp + 12, &__fun, sizeof (__fun));			\
+    memcpy (__tramp + 20, &__ctx, sizeof (__ctx));			\
+    memcpy (__tramp + 28, &__flags, sizeof (__flags));			\
+    __clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE);		\
+  })
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+                      ffi_cif* cif,
+                      void (*fun)(ffi_cif*,void*,void**,void*),
+                      void *user_data,
+                      void *codeloc)
+{
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_SYSV, codeloc,
+		       cif->aarch64_flags);
+
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+/* Primary handler to setup and invoke a function within a closure.
+
+   A closure when invoked enters via the assembler wrapper
+   ffi_closure_SYSV(). The wrapper allocates a call context on the
+   stack, saves the interesting registers (from the perspective of
+   the calling convention) into the context then passes control to
+   ffi_closure_SYSV_inner() passing the saved context and a pointer to
+   the stack at the point ffi_closure_SYSV() was invoked.
+
+   On the return path the assembler wrapper will reload call context
+   regsiters.
+
+   ffi_closure_SYSV_inner() marshalls the call context into ffi value
+   desriptors, invokes the wrapped function, then marshalls the return
+   value back into the call context.  */
+
+void
+ffi_closure_SYSV_inner (ffi_closure *closure, struct call_context *context,
+			void *stack)
+{
+  ffi_cif *cif = closure->cif;
+  void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
+  void *rvalue = NULL;
+  int i;
+  struct arg_state state;
+
+  arg_init (&state, ALIGN(cif->bytes, 16));
+
+  for (i = 0; i < cif->nargs; i++)
+    {
+      ffi_type *ty = cif->arg_types[i];
+
+      switch (ty->type)
+	{
+	case FFI_TYPE_VOID:
+	  FFI_ASSERT (0);
+	  break;
+
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_INT:
+	case FFI_TYPE_POINTER:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	case  FFI_TYPE_FLOAT:
+	case  FFI_TYPE_DOUBLE:
+	case  FFI_TYPE_LONGDOUBLE:
+	  avalue[i] = allocate_to_register_or_stack (context, stack,
+						     &state, ty->type);
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  if (is_hfa (ty))
+	    {
+	      unsigned n = element_count (ty);
+	      if (available_v (&state) < n)
+		{
+		  state.nsrn = N_V_ARG_REG;
+		  avalue[i] = allocate_to_stack (&state, stack, ty->alignment,
+						 ty->size);
+		}
+	      else
+		{
+		  switch (get_homogeneous_type (ty))
+		    {
+		    case FFI_TYPE_FLOAT:
+		      {
+			/* Eeek! We need a pointer to the structure,
+			   however the homogeneous float elements are
+			   being passed in individual S registers,
+			   therefore the structure is not represented as
+			   a contiguous sequence of bytes in our saved
+			   register context. We need to fake up a copy
+			   of the structure layed out in memory
+			   correctly. The fake can be tossed once the
+			   closure function has returned hence alloca()
+			   is sufficient. */
+			int j;
+			UINT32 *p = avalue[i] = alloca (ty->size);
+			for (j = 0; j < element_count (ty); j++)
+			  memcpy (&p[j],
+				  allocate_to_s (context, &state),
+				  sizeof (*p));
+			break;
+		      }
+
+		    case FFI_TYPE_DOUBLE:
+		      {
+			/* Eeek! We need a pointer to the structure,
+			   however the homogeneous float elements are
+			   being passed in individual S registers,
+			   therefore the structure is not represented as
+			   a contiguous sequence of bytes in our saved
+			   register context. We need to fake up a copy
+			   of the structure layed out in memory
+			   correctly. The fake can be tossed once the
+			   closure function has returned hence alloca()
+			   is sufficient. */
+			int j;
+			UINT64 *p = avalue[i] = alloca (ty->size);
+			for (j = 0; j < element_count (ty); j++)
+			  memcpy (&p[j],
+				  allocate_to_d (context, &state),
+				  sizeof (*p));
+			break;
+		      }
+
+		    case FFI_TYPE_LONGDOUBLE:
+			  memcpy (&avalue[i],
+				  allocate_to_v (context, &state),
+				  sizeof (*avalue));
+		      break;
+
+		    default:
+		      FFI_ASSERT (0);
+		      break;
+		    }
+		}
+	    }
+	  else if (ty->size > 16)
+	    {
+	      /* Replace Composite type of size greater than 16 with a
+		 pointer.  */
+	      memcpy (&avalue[i],
+		      allocate_to_register_or_stack (context, stack,
+						     &state, FFI_TYPE_POINTER),
+		      sizeof (avalue[i]));
+	    }
+	  else if (available_x (&state) >= (ty->size + 7) / 8)
+	    {
+	      avalue[i] = get_x_addr (context, state.ngrn);
+	      state.ngrn += (ty->size + 7) / 8;
+	    }
+	  else
+	    {
+	      state.ngrn = N_X_ARG_REG;
+
+	      avalue[i] = allocate_to_stack (&state, stack, ty->alignment,
+					     ty->size);
+	    }
+	  break;
+
+	default:
+	  FFI_ASSERT (0);
+	  break;
+	}
+    }
+
+  /* Figure out where the return value will be passed, either in
+     registers or in a memory block allocated by the caller and passed
+     in x8.  */
+
+  if (is_register_candidate (cif->rtype))
+    {
+      /* Register candidates are *always* returned in registers. */
+
+      /* Allocate a scratchpad for the return value, we will let the
+         callee scrible the result into the scratch pad then move the
+         contents into the appropriate return value location for the
+         call convention.  */
+      rvalue = alloca (cif->rtype->size);
+      (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+      /* Copy the return value into the call context so that it is returned
+         as expected to our caller.  */
+      switch (cif->rtype->type)
+        {
+        case FFI_TYPE_VOID:
+          break;
+
+        case FFI_TYPE_UINT8:
+        case FFI_TYPE_UINT16:
+        case FFI_TYPE_UINT32:
+        case FFI_TYPE_POINTER:
+        case FFI_TYPE_UINT64:
+        case FFI_TYPE_SINT8:
+        case FFI_TYPE_SINT16:
+        case FFI_TYPE_INT:
+        case FFI_TYPE_SINT32:
+        case FFI_TYPE_SINT64:
+        case FFI_TYPE_FLOAT:
+        case FFI_TYPE_DOUBLE:
+        case FFI_TYPE_LONGDOUBLE:
+	  {
+	    void *addr = get_basic_type_addr (cif->rtype->type, context, 0);
+	    copy_basic_type (addr, rvalue, cif->rtype->type);
+            break;
+	  }
+        case FFI_TYPE_STRUCT:
+          if (is_hfa (cif->rtype))
+	    {
+	      int i;
+	      unsigned short type = get_homogeneous_type (cif->rtype);
+	      unsigned elems = element_count (cif->rtype);
+	      for (i = 0; i < elems; i++)
+		{
+		  void *reg = get_basic_type_addr (type, context, i);
+		  copy_basic_type (reg, rvalue, type);
+		  rvalue += get_basic_type_size (type);
+		}
+	    }
+          else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
+            {
+              unsigned size = ALIGN (cif->rtype->size, sizeof (UINT64)) ;
+              memcpy (get_x_addr (context, 0), rvalue, size);
+            }
+          else
+            {
+              FFI_ASSERT (0);
+            }
+          break;
+        default:
+          FFI_ASSERT (0);
+          break;
+        }
+    }
+  else
+    {
+      memcpy (&rvalue, get_x_addr (context, 8), sizeof (UINT64));
+      (closure->fun) (cif, rvalue, avalue, closure->user_data);
+    }
+}
+
diff --git a/third_party/gofrontend/libffi/src/aarch64/ffitarget.h b/third_party/gofrontend/libffi/src/aarch64/ffitarget.h
new file mode 100644
index 0000000..6f1a348
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/aarch64/ffitarget.h
@@ -0,0 +1,59 @@
+/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+``Software''), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long ffi_arg;
+typedef signed long ffi_sarg;
+
+typedef enum ffi_abi
+  {
+    FFI_FIRST_ABI = 0,
+    FFI_SYSV,
+    FFI_LAST_ABI,
+    FFI_DEFAULT_ABI = FFI_SYSV
+  } ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 36
+#define FFI_NATIVE_RAW_API 0
+
+/* ---- Internal ---- */
+
+
+#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags
+
+#define AARCH64_FFI_WITH_V_BIT 0
+
+#define AARCH64_N_XREG 32
+#define AARCH64_N_VREG 32
+#define AARCH64_CALL_CONTEXT_SIZE (AARCH64_N_XREG * 8 + AARCH64_N_VREG * 16)
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/aarch64/sysv.S b/third_party/gofrontend/libffi/src/aarch64/sysv.S
new file mode 100644
index 0000000..ffb16f8
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/aarch64/sysv.S
@@ -0,0 +1,307 @@
+/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+``Software''), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+#define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
+#define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
+#define cfi_restore(reg)		.cfi_restore reg
+#define cfi_def_cfa_register(reg)	.cfi_def_cfa_register reg
+
+        .text
+        .globl ffi_call_SYSV
+        .type ffi_call_SYSV, #function
+
+/* ffi_call_SYSV()
+
+   Create a stack frame, setup an argument context, call the callee
+   and extract the result.
+
+   The maximum required argument stack size is provided,
+   ffi_call_SYSV() allocates that stack space then calls the
+   prepare_fn to populate register context and stack.  The
+   argument passing registers are loaded from the register
+   context and the callee called, on return the register passing
+   register are saved back to the context.  Our caller will
+   extract the return value from the final state of the saved
+   register context.
+
+   Prototype:
+
+   extern unsigned
+   ffi_call_SYSV (void (*)(struct call_context *context, unsigned char *,
+			   extended_cif *),
+                  struct call_context *context,
+                  extended_cif *,
+                  unsigned required_stack_size,
+                  void (*fn)(void));
+
+   Therefore on entry we have:
+
+   x0 prepare_fn
+   x1 &context
+   x2 &ecif
+   x3 bytes
+   x4 fn
+
+   This function uses the following stack frame layout:
+
+   ==
+                saved x30(lr)
+   x29(fp)->    saved x29(fp)
+                saved x24
+                saved x23
+                saved x22
+   sp'    ->    saved x21
+                ...
+   sp     ->    (constructed callee stack arguments)
+   ==
+
+   Voila! */
+
+#define ffi_call_SYSV_FS (8 * 4)
+
+        .cfi_startproc
+ffi_call_SYSV:
+        stp     x29, x30, [sp, #-16]!
+	cfi_adjust_cfa_offset (16)
+        cfi_rel_offset (x29, 0)
+        cfi_rel_offset (x30, 8)
+
+        mov     x29, sp
+	cfi_def_cfa_register (x29)
+        sub     sp, sp, #ffi_call_SYSV_FS
+
+        stp     x21, x22, [sp, 0]
+        cfi_rel_offset (x21, 0 - ffi_call_SYSV_FS)
+        cfi_rel_offset (x22, 8 - ffi_call_SYSV_FS)
+
+        stp     x23, x24, [sp, 16]
+        cfi_rel_offset (x23, 16 - ffi_call_SYSV_FS)
+        cfi_rel_offset (x24, 24 - ffi_call_SYSV_FS)
+
+        mov     x21, x1
+        mov     x22, x2
+        mov     x24, x4
+
+        /* Allocate the stack space for the actual arguments, many
+           arguments will be passed in registers, but we assume
+           worst case and allocate sufficient stack for ALL of
+           the arguments.  */
+        sub     sp, sp, x3
+
+        /* unsigned (*prepare_fn) (struct call_context *context,
+				   unsigned char *stack, extended_cif *ecif);
+	 */
+        mov     x23, x0
+        mov     x0, x1
+        mov     x1, sp
+        /* x2 already in place */
+        blr     x23
+
+        /* Preserve the flags returned.  */
+        mov     x23, x0
+
+        /* Figure out if we should touch the vector registers.  */
+        tbz     x23, #AARCH64_FFI_WITH_V_BIT, 1f
+
+        /* Load the vector argument passing registers.  */
+        ldp     q0, q1, [x21, #8*32 +  0]
+        ldp     q2, q3, [x21, #8*32 + 32]
+        ldp     q4, q5, [x21, #8*32 + 64]
+        ldp     q6, q7, [x21, #8*32 + 96]
+1:
+        /* Load the core argument passing registers.  */
+        ldp     x0, x1, [x21,  #0]
+        ldp     x2, x3, [x21, #16]
+        ldp     x4, x5, [x21, #32]
+        ldp     x6, x7, [x21, #48]
+
+        /* Don't forget x8 which may be holding the address of a return buffer.
+	 */
+        ldr     x8,     [x21, #8*8]
+
+        blr     x24
+
+        /* Save the core argument passing registers.  */
+        stp     x0, x1, [x21,  #0]
+        stp     x2, x3, [x21, #16]
+        stp     x4, x5, [x21, #32]
+        stp     x6, x7, [x21, #48]
+
+        /* Note nothing useful ever comes back in x8!  */
+
+        /* Figure out if we should touch the vector registers.  */
+        tbz     x23, #AARCH64_FFI_WITH_V_BIT, 1f
+
+        /* Save the vector argument passing registers.  */
+        stp     q0, q1, [x21, #8*32 + 0]
+        stp     q2, q3, [x21, #8*32 + 32]
+        stp     q4, q5, [x21, #8*32 + 64]
+        stp     q6, q7, [x21, #8*32 + 96]
+1:
+        /* All done, unwind our stack frame.  */
+        ldp     x21, x22, [x29,  # - ffi_call_SYSV_FS]
+        cfi_restore (x21)
+        cfi_restore (x22)
+
+        ldp     x23, x24, [x29,  # - ffi_call_SYSV_FS + 16]
+        cfi_restore (x23)
+        cfi_restore (x24)
+
+        mov     sp, x29
+	cfi_def_cfa_register (sp)
+
+        ldp     x29, x30, [sp], #16
+	cfi_adjust_cfa_offset (-16)
+        cfi_restore (x29)
+        cfi_restore (x30)
+
+        ret
+
+        .cfi_endproc
+        .size ffi_call_SYSV, .-ffi_call_SYSV
+
+#define ffi_closure_SYSV_FS (8 * 2 + AARCH64_CALL_CONTEXT_SIZE)
+
+/* ffi_closure_SYSV
+
+   Closure invocation glue. This is the low level code invoked directly by
+   the closure trampoline to setup and call a closure.
+
+   On entry x17 points to a struct trampoline_data, x16 has been clobbered
+   all other registers are preserved.
+
+   We allocate a call context and save the argument passing registers,
+   then invoked the generic C ffi_closure_SYSV_inner() function to do all
+   the real work, on return we load the result passing registers back from
+   the call context.
+
+   On entry
+
+   extern void
+   ffi_closure_SYSV (struct trampoline_data *);
+
+   struct trampoline_data
+   {
+        UINT64 *ffi_closure;
+        UINT64 flags;
+   };
+
+   This function uses the following stack frame layout:
+
+   ==
+                saved x30(lr)
+   x29(fp)->    saved x29(fp)
+                saved x22
+                saved x21
+                ...
+   sp     ->    call_context
+   ==
+
+   Voila!  */
+
+        .text
+        .globl ffi_closure_SYSV
+        .cfi_startproc
+ffi_closure_SYSV:
+        stp     x29, x30, [sp, #-16]!
+	cfi_adjust_cfa_offset (16)
+        cfi_rel_offset (x29, 0)
+        cfi_rel_offset (x30, 8)
+
+        mov     x29, sp
+        cfi_def_cfa_register (x29)
+
+        sub     sp, sp, #ffi_closure_SYSV_FS
+
+        stp     x21, x22, [x29, #-16]
+        cfi_rel_offset (x21, -16)
+        cfi_rel_offset (x22, -8)
+
+        /* Load x21 with &call_context.  */
+        mov     x21, sp
+        /* Preserve our struct trampoline_data *  */
+        mov     x22, x17
+
+        /* Save the rest of the argument passing registers.  */
+        stp     x0, x1, [x21, #0]
+        stp     x2, x3, [x21, #16]
+        stp     x4, x5, [x21, #32]
+        stp     x6, x7, [x21, #48]
+        /* Don't forget we may have been given a result scratch pad address.
+	 */
+        str     x8,     [x21, #64]
+
+        /* Figure out if we should touch the vector registers.  */
+        ldr     x0, [x22, #8]
+        tbz     x0, #AARCH64_FFI_WITH_V_BIT, 1f
+
+        /* Save the argument passing vector registers.  */
+        stp     q0, q1, [x21, #8*32 + 0]
+        stp     q2, q3, [x21, #8*32 + 32]
+        stp     q4, q5, [x21, #8*32 + 64]
+        stp     q6, q7, [x21, #8*32 + 96]
+1:
+        /* Load &ffi_closure..  */
+        ldr     x0, [x22, #0]
+        mov     x1, x21
+        /* Compute the location of the stack at the point that the
+           trampoline was called.  */
+        add     x2, x29, #16
+
+        bl      ffi_closure_SYSV_inner
+
+        /* Figure out if we should touch the vector registers.  */
+        ldr     x0, [x22, #8]
+        tbz     x0, #AARCH64_FFI_WITH_V_BIT, 1f
+
+        /* Load the result passing vector registers.  */
+        ldp     q0, q1, [x21, #8*32 + 0]
+        ldp     q2, q3, [x21, #8*32 + 32]
+        ldp     q4, q5, [x21, #8*32 + 64]
+        ldp     q6, q7, [x21, #8*32 + 96]
+1:
+        /* Load the result passing core registers.  */
+        ldp     x0, x1, [x21,  #0]
+        ldp     x2, x3, [x21, #16]
+        ldp     x4, x5, [x21, #32]
+        ldp     x6, x7, [x21, #48]
+        /* Note nothing usefull is returned in x8.  */
+
+        /* We are done, unwind our frame.  */
+        ldp     x21, x22, [x29,  #-16]
+        cfi_restore (x21)
+        cfi_restore (x22)
+
+        mov     sp, x29
+        cfi_def_cfa_register (sp)
+
+        ldp     x29, x30, [sp], #16
+	cfi_adjust_cfa_offset (-16)
+        cfi_restore (x29)
+        cfi_restore (x30)
+
+        ret
+        .cfi_endproc
+        .size ffi_closure_SYSV, .-ffi_closure_SYSV
diff --git a/third_party/gofrontend/libffi/src/alpha/ffi.c b/third_party/gofrontend/libffi/src/alpha/ffi.c
new file mode 100644
index 0000000..cf0a730
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/alpha/ffi.c
@@ -0,0 +1,287 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2012  Anthony Green
+           Copyright (c) 1998, 2001, 2007, 2008  Red Hat, Inc.
+   
+   Alpha Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
+   all further uses in this file will refer to the 128-bit type.  */
+#if defined(__LONG_DOUBLE_128__)
+# if FFI_TYPE_LONGDOUBLE != 4
+#  error FFI_TYPE_LONGDOUBLE out of date
+# endif
+#else
+# undef FFI_TYPE_LONGDOUBLE
+# define FFI_TYPE_LONGDOUBLE 4
+#endif
+
+extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void))
+  FFI_HIDDEN;
+extern void ffi_closure_osf(void) FFI_HIDDEN;
+
+
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Adjust cif->bytes to represent a minimum 6 words for the temporary
+     register argument loading area.  */
+  if (cif->bytes < 6*FFI_SIZEOF_ARG)
+    cif->bytes = 6*FFI_SIZEOF_ARG;
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = cif->rtype->type;
+      break;
+
+    case FFI_TYPE_LONGDOUBLE:
+      /* 128-bit long double is returned in memory, like a struct.  */
+      cif->flags = FFI_TYPE_STRUCT;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+  
+  return FFI_OK;
+}
+
+
+void
+ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  unsigned long *stack, *argp;
+  long i, avn;
+  ffi_type **arg_types;
+  
+  /* If the return value is a struct and we don't have a return
+     value address then we need to make one.  */
+  if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT)
+    rvalue = alloca(cif->rtype->size);
+
+  /* Allocate the space for the arguments, plus 4 words of temp
+     space for ffi_call_osf.  */
+  argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
+
+  if (cif->flags == FFI_TYPE_STRUCT)
+    *(void **) argp++ = rvalue;
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  while (i < avn)
+    {
+      size_t size = (*arg_types)->size;
+
+      switch ((*arg_types)->type)
+	{
+	case FFI_TYPE_SINT8:
+	  *(SINT64 *) argp = *(SINT8 *)(* avalue);
+	  break;
+		  
+	case FFI_TYPE_UINT8:
+	  *(SINT64 *) argp = *(UINT8 *)(* avalue);
+	  break;
+		  
+	case FFI_TYPE_SINT16:
+	  *(SINT64 *) argp = *(SINT16 *)(* avalue);
+	  break;
+		  
+	case FFI_TYPE_UINT16:
+	  *(SINT64 *) argp = *(UINT16 *)(* avalue);
+	  break;
+		  
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	  /* Note that unsigned 32-bit quantities are sign extended.  */
+	  *(SINT64 *) argp = *(SINT32 *)(* avalue);
+	  break;
+		  
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_POINTER:
+	  *(UINT64 *) argp = *(UINT64 *)(* avalue);
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  if (argp - stack < 6)
+	    {
+	      /* Note the conversion -- all the fp regs are loaded as
+		 doubles.  The in-register format is the same.  */
+	      *(double *) argp = *(float *)(* avalue);
+	    }
+	  else
+	    *(float *) argp = *(float *)(* avalue);
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  *(double *) argp = *(double *)(* avalue);
+	  break;
+
+	case FFI_TYPE_LONGDOUBLE:
+	  /* 128-bit long double is passed by reference.  */
+	  *(long double **) argp = (long double *)(* avalue);
+	  size = sizeof (long double *);
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  memcpy(argp, *avalue, (*arg_types)->size);
+	  break;
+
+	default:
+	  FFI_ASSERT(0);
+	}
+
+      argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+      i++, arg_types++, avalue++;
+    }
+
+  ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
+}
+
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  unsigned int *tramp;
+
+  if (cif->abi != FFI_OSF)
+    return FFI_BAD_ABI;
+
+  tramp = (unsigned int *) &closure->tramp[0];
+  tramp[0] = 0x47fb0401;	/* mov $27,$1		*/
+  tramp[1] = 0xa77b0010;	/* ldq $27,16($27)	*/
+  tramp[2] = 0x6bfb0000;	/* jmp $31,($27),0	*/
+  tramp[3] = 0x47ff041f;	/* nop			*/
+  *(void **) &tramp[4] = ffi_closure_osf;
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Flush the Icache.
+
+     Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal
+     instead, since both Compaq as and gas can handle it.
+
+     0x86 is PAL_imb in Tru64 UNIX <alpha/pal.h>.  */
+  asm volatile ("call_pal 0x86" : : : "memory");
+
+  return FFI_OK;
+}
+
+
+long FFI_HIDDEN
+ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
+{
+  ffi_cif *cif;
+  void **avalue;
+  ffi_type **arg_types;
+  long i, avn, argn;
+
+  cif = closure->cif;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  argn = 0;
+
+  /* Copy the caller's structure return address to that the closure
+     returns the data directly to the caller.  */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *) argp[0];
+      argn = 1;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+  
+  /* Grab the addresses of the arguments from the stack frame.  */
+  while (i < avn)
+    {
+      size_t size = arg_types[i]->size;
+
+      switch (arg_types[i]->type)
+	{
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_POINTER:
+	case FFI_TYPE_STRUCT:
+	  avalue[i] = &argp[argn];
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  if (argn < 6)
+	    {
+	      /* Floats coming from registers need conversion from double
+	         back to float format.  */
+	      *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
+	      avalue[i] = &argp[argn - 6];
+	    }
+	  else
+	    avalue[i] = &argp[argn];
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
+	  break;
+
+	case FFI_TYPE_LONGDOUBLE:
+	  /* 128-bit long double is passed by reference.  */
+	  avalue[i] = (long double *) argp[argn];
+	  size = sizeof (long double *);
+	  break;
+
+	default:
+	  FFI_ASSERT (0);
+	}
+
+      argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+      i++;
+    }
+
+  /* Invoke the closure.  */
+  closure->fun (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_osf how to perform return type promotions.  */
+  return cif->rtype->type;
+}
diff --git a/third_party/gofrontend/libffi/src/alpha/ffitarget.h b/third_party/gofrontend/libffi/src/alpha/ffitarget.h
new file mode 100644
index 0000000..af145bc
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/alpha/ffitarget.h
@@ -0,0 +1,53 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for Alpha.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_OSF,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_OSF
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 24
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/alpha/osf.S b/third_party/gofrontend/libffi/src/alpha/osf.S
new file mode 100644
index 0000000..6b9f4df
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/alpha/osf.S
@@ -0,0 +1,387 @@
+/* -----------------------------------------------------------------------
+   osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat
+   
+   Alpha/OSF Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+	.arch ev6
+	.text
+
+/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
+		 void *raddr, void (*fnaddr)(void));
+
+   Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
+   for this function.  This has been allocated by ffi_call.  We also
+   deallocate some of the stack that has been alloca'd.  */
+
+	.align	3
+	.globl	ffi_call_osf
+	.ent	ffi_call_osf
+	FFI_HIDDEN(ffi_call_osf)
+
+ffi_call_osf:
+	.frame	$15, 32, $26, 0
+	.mask   0x4008000, -32
+$LFB1:
+	addq	$16,$17,$1
+	mov	$16, $30
+	stq	$26, 0($1)
+	stq	$15, 8($1)
+	stq	$18, 16($1)
+	mov	$1, $15
+$LCFI1:
+	.prologue 0
+
+	stq	$19, 24($1)
+	mov	$20, $27
+
+	# Load up all of the (potential) argument registers.
+	ldq	$16, 0($30)
+	ldt	$f16, 0($30)
+	ldt	$f17, 8($30)
+	ldq	$17, 8($30)
+	ldt	$f18, 16($30)
+	ldq	$18, 16($30)
+	ldt	$f19, 24($30)
+	ldq	$19, 24($30)
+	ldt	$f20, 32($30)
+	ldq	$20, 32($30)
+	ldt	$f21, 40($30)
+	ldq	$21, 40($30)
+
+	# Deallocate the register argument area.
+	lda	$30, 48($30)
+
+	jsr	$26, ($27), 0
+	ldgp	$29, 0($26)
+
+	# If the return value pointer is NULL, assume no return value.
+	ldq	$19, 24($15)
+	ldq	$18, 16($15)
+	ldq	$26, 0($15)
+$LCFI2:
+	beq	$19, $noretval
+
+	# Store the return value out in the proper type.
+	cmpeq	$18, FFI_TYPE_INT, $1
+	bne	$1, $retint
+	cmpeq	$18, FFI_TYPE_FLOAT, $2
+	bne	$2, $retfloat
+	cmpeq	$18, FFI_TYPE_DOUBLE, $3
+	bne	$3, $retdouble
+
+	.align	3
+$noretval:
+	ldq	$15, 8($15)
+	ret
+
+	.align	4
+$retint:
+	stq	$0, 0($19)
+	nop
+	ldq	$15, 8($15)
+	ret
+
+	.align	4
+$retfloat:
+	sts	$f0, 0($19)
+	nop
+	ldq	$15, 8($15)
+	ret
+
+	.align	4
+$retdouble:
+	stt	$f0, 0($19)
+	nop
+	ldq	$15, 8($15)
+	ret
+$LFE1:
+
+	.end	ffi_call_osf
+
+/* ffi_closure_osf(...)
+
+   Receives the closure argument in $1.   */
+
+	.align	3
+	.globl	ffi_closure_osf
+	.ent	ffi_closure_osf
+	FFI_HIDDEN(ffi_closure_osf)
+
+ffi_closure_osf:
+	.frame	$30, 16*8, $26, 0
+	.mask	0x4000000, -16*8
+$LFB2:
+	ldgp	$29, 0($27)
+	subq	$30, 16*8, $30
+$LCFI5:
+	stq	$26, 0($30)
+$LCFI6:
+	.prologue 1
+
+	# Store all of the potential argument registers in va_list format.
+	stt	$f16, 4*8($30)
+	stt	$f17, 5*8($30)
+	stt	$f18, 6*8($30)
+	stt	$f19, 7*8($30)
+	stt	$f20, 8*8($30)
+	stt	$f21, 9*8($30)
+	stq	$16, 10*8($30)
+	stq	$17, 11*8($30)
+	stq	$18, 12*8($30)
+	stq	$19, 13*8($30)
+	stq	$20, 14*8($30)
+	stq	$21, 15*8($30)
+
+	# Call ffi_closure_osf_inner to do the bulk of the work.
+	mov	$1, $16
+	lda	$17, 2*8($30)
+	lda	$18, 10*8($30)
+	jsr	$26, ffi_closure_osf_inner
+	ldgp	$29, 0($26)
+	ldq	$26, 0($30)
+
+	# Load up the return value in the proper type.
+	lda	$1, $load_table
+	s4addq	$0, $1, $1
+	ldl	$1, 0($1)
+	addq	$1, $29, $1
+	jmp	$31, ($1), $load_32
+
+	.align 4
+$load_none:
+	addq	$30, 16*8, $30
+	ret
+
+	.align 4
+$load_float:
+	lds	$f0, 16($30)
+	nop
+	addq	$30, 16*8, $30
+	ret
+
+	.align 4
+$load_double:
+	ldt	$f0, 16($30)
+	nop
+	addq	$30, 16*8, $30
+	ret
+
+	.align 4
+$load_u8:
+#ifdef __alpha_bwx__
+	ldbu	$0, 16($30)
+	nop
+#else
+	ldq	$0, 16($30)
+	and	$0, 255, $0
+#endif
+	addq	$30, 16*8, $30
+	ret
+
+	.align 4
+$load_s8:
+#ifdef __alpha_bwx__
+	ldbu	$0, 16($30)
+	sextb	$0, $0
+#else
+	ldq	$0, 16($30)
+	sll	$0, 56, $0
+	sra	$0, 56, $0
+#endif
+	addq	$30, 16*8, $30
+	ret
+
+	.align 4
+$load_u16:
+#ifdef __alpha_bwx__
+	ldwu	$0, 16($30)
+	nop
+#else
+	ldq	$0, 16($30)
+	zapnot	$0, 3, $0
+#endif
+	addq	$30, 16*8, $30
+	ret
+
+	.align 4
+$load_s16:
+#ifdef __alpha_bwx__
+	ldwu	$0, 16($30)
+	sextw	$0, $0
+#else
+	ldq	$0, 16($30)
+	sll	$0, 48, $0
+	sra	$0, 48, $0
+#endif
+	addq	$30, 16*8, $30
+	ret
+
+	.align 4
+$load_32:
+	ldl	$0, 16($30)
+	nop
+	addq	$30, 16*8, $30
+	ret
+
+	.align 4
+$load_64:
+	ldq	$0, 16($30)
+	nop
+	addq	$30, 16*8, $30
+	ret
+$LFE2:
+
+	.end	ffi_closure_osf
+
+#ifdef __ELF__
+.section .rodata
+#else
+.rdata
+#endif
+$load_table:
+	.gprel32 $load_none	# FFI_TYPE_VOID
+	.gprel32 $load_32	# FFI_TYPE_INT
+	.gprel32 $load_float	# FFI_TYPE_FLOAT
+	.gprel32 $load_double	# FFI_TYPE_DOUBLE
+	.gprel32 $load_none	# FFI_TYPE_LONGDOUBLE
+	.gprel32 $load_u8	# FFI_TYPE_UINT8
+	.gprel32 $load_s8	# FFI_TYPE_SINT8
+	.gprel32 $load_u16	# FFI_TYPE_UINT16
+	.gprel32 $load_s16	# FFI_TYPE_SINT16
+	.gprel32 $load_32	# FFI_TYPE_UINT32
+	.gprel32 $load_32	# FFI_TYPE_SINT32
+	.gprel32 $load_64	# FFI_TYPE_UINT64
+	.gprel32 $load_64	# FFI_TYPE_SINT64
+	.gprel32 $load_none	# FFI_TYPE_STRUCT
+	.gprel32 $load_64	# FFI_TYPE_POINTER
+
+/* Assert that the table above is in sync with ffi.h.  */
+
+#if	   FFI_TYPE_FLOAT != 2		\
+	|| FFI_TYPE_DOUBLE != 3		\
+	|| FFI_TYPE_UINT8 != 5		\
+	|| FFI_TYPE_SINT8 != 6		\
+	|| FFI_TYPE_UINT16 != 7		\
+	|| FFI_TYPE_SINT16 != 8		\
+	|| FFI_TYPE_UINT32 != 9		\
+	|| FFI_TYPE_SINT32 != 10	\
+	|| FFI_TYPE_UINT64 != 11	\
+	|| FFI_TYPE_SINT64 != 12	\
+	|| FFI_TYPE_STRUCT != 13	\
+	|| FFI_TYPE_POINTER != 14	\
+	|| FFI_TYPE_LAST != 14
+#error "osf.S out of sync with ffi.h"
+#endif
+
+#ifdef __ELF__
+# define UA_SI		.4byte
+# define FDE_ENCODING	0x1b	/* pcrel sdata4 */
+# define FDE_ENCODE(X)	.4byte X-.
+# define FDE_ARANGE(X)	.4byte X
+#elif defined __osf__
+# define UA_SI		.align 0; .long
+# define FDE_ENCODING	0x50	/* aligned absolute */
+# define FDE_ENCODE(X)	.align 3; .quad X
+# define FDE_ARANGE(X)	.align 0; .quad X
+#endif
+
+#ifdef __ELF__
+	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
+#elif defined __osf__
+	.data
+	.align 3
+	.globl _GLOBAL__F_ffi_call_osf
+_GLOBAL__F_ffi_call_osf:
+#endif
+__FRAME_BEGIN__:
+	UA_SI	$LECIE1-$LSCIE1	# Length of Common Information Entry
+$LSCIE1:
+	UA_SI	0x0		# CIE Identifier Tag
+	.byte	0x1		# CIE Version
+	.ascii "zR\0"		# CIE Augmentation
+	.byte	0x1		# uleb128 0x1; CIE Code Alignment Factor
+	.byte	0x78		# sleb128 -8; CIE Data Alignment Factor
+	.byte	26		# CIE RA Column
+	.byte	0x1		# uleb128 0x1; Augmentation size
+	.byte	FDE_ENCODING	# FDE Encoding
+	.byte	0xc		# DW_CFA_def_cfa
+	.byte	30		# uleb128 column 30
+	.byte	0		# uleb128 offset 0
+	.align 3
+$LECIE1:
+$LSFDE1:
+	UA_SI	$LEFDE1-$LASFDE1		# FDE Length
+$LASFDE1:
+	UA_SI	$LASFDE1-__FRAME_BEGIN__	# FDE CIE offset
+	FDE_ENCODE($LFB1)			# FDE initial location
+	FDE_ARANGE($LFE1-$LFB1)			# FDE address range
+	.byte	0x0		# uleb128 0x0; Augmentation size
+
+	.byte	0x4		# DW_CFA_advance_loc4
+	UA_SI	$LCFI1-$LFB1
+	.byte	0x9a		# DW_CFA_offset, column 26
+	.byte	4		# uleb128 4*-8
+	.byte	0x8f		# DW_CFA_offset, column 15
+	.byte	0x3		# uleb128 3*-8
+	.byte	0xc		# DW_CFA_def_cfa
+	.byte	15		# uleb128 column 15
+	.byte	32		# uleb128 offset 32
+
+	.byte	0x4		# DW_CFA_advance_loc4
+	UA_SI	$LCFI2-$LCFI1
+	.byte	0xda		# DW_CFA_restore, column 26
+	.align 3
+$LEFDE1:
+
+$LSFDE3:
+	UA_SI	$LEFDE3-$LASFDE3		# FDE Length
+$LASFDE3:
+	UA_SI	$LASFDE3-__FRAME_BEGIN__	# FDE CIE offset
+	FDE_ENCODE($LFB2)			# FDE initial location
+	FDE_ARANGE($LFE2-$LFB2)			# FDE address range
+	.byte	0x0		# uleb128 0x0; Augmentation size
+
+	.byte	0x4		# DW_CFA_advance_loc4
+	UA_SI	$LCFI5-$LFB2
+	.byte	0xe		# DW_CFA_def_cfa_offset
+	.byte	0x80,0x1	# uleb128 128
+
+	.byte	0x4		# DW_CFA_advance_loc4
+	UA_SI	$LCFI6-$LCFI5
+	.byte	0x9a		# DW_CFA_offset, column 26
+	.byte	16		# uleb128 offset 16*-8
+	.align 3
+$LEFDE3:
+#if defined __osf__
+	.align 0
+	.long	0		# End of Table
+#endif
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/arm/ffi.c b/third_party/gofrontend/libffi/src/arm/ffi.c
new file mode 100644
index 0000000..3ccceb9
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/arm/ffi.c
@@ -0,0 +1,756 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2011 Timothy Wall
+           Copyright (c) 2011 Plausible Labs Cooperative, Inc.
+           Copyright (c) 2011 Anthony Green
+	   Copyright (c) 2011 Free Software Foundation
+           Copyright (c) 1998, 2008, 2011  Red Hat, Inc.
+	   
+   ARM Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* Forward declares. */
+static int vfp_type_p (ffi_type *);
+static void layout_vfp_args (ffi_cif *);
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments
+   
+   The vfp_space parameter is the load area for VFP regs, the return
+   value is cif->vfp_used (word bitset of VFP regs used for passing
+   arguments). These are only used for the VFP hard-float ABI.
+*/
+int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space)
+{
+  register unsigned int i, vi = 0;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
+    *(void **) argp = ecif->rvalue;
+    argp += 4;
+  }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+      size_t alignment;
+
+      /* Allocated in VFP registers. */
+      if (ecif->cif->abi == FFI_VFP
+	  && vi < ecif->cif->vfp_nargs && vfp_type_p (*p_arg))
+	{
+	  float* vfp_slot = vfp_space + ecif->cif->vfp_args[vi++];
+	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
+	    *((float*)vfp_slot) = *((float*)*p_argv);
+	  else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+	    *((double*)vfp_slot) = *((double*)*p_argv);
+	  else
+	    memcpy(vfp_slot, *p_argv, (*p_arg)->size);
+	  p_argv++;
+	  continue;
+	}
+
+      /* Align if necessary */
+      alignment = (*p_arg)->alignment;
+#ifdef _WIN32_WCE
+      if (alignment > 4)
+	alignment = 4;
+#endif
+      if ((alignment - 1) & (unsigned) argp) {
+	argp = (char *) ALIGN(argp, alignment);
+      }
+
+      if ((*p_arg)->type == FFI_TYPE_STRUCT)
+	argp = (char *) ALIGN(argp, 4);
+
+	  z = (*p_arg)->size;
+	  if (z < sizeof(int))
+	    {
+	      z = sizeof(int);
+	      switch ((*p_arg)->type)
+		{
+		case FFI_TYPE_SINT8:
+		  *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+		  break;
+		  
+		case FFI_TYPE_UINT8:
+		  *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+		  break;
+		  
+		case FFI_TYPE_SINT16:
+		  *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+		  break;
+		  
+		case FFI_TYPE_UINT16:
+		  *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+		  break;
+		  
+		case FFI_TYPE_STRUCT:
+		  memcpy(argp, *p_argv, (*p_arg)->size);
+		  break;
+
+		default:
+		  FFI_ASSERT(0);
+		}
+	    }
+	  else if (z == sizeof(int))
+	    {
+	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+	    }
+	  else
+	    {
+	      memcpy(argp, *p_argv, z);
+	    }
+	  p_argv++;
+	  argp += z;
+    }
+
+  /* Indicate the VFP registers used. */
+  return ecif->cif->vfp_used;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int type_code;
+  /* Round the stack up to a multiple of 8 bytes.  This isn't needed 
+     everywhere, but it is on some platforms, and it doesn't harm anything
+     when it isn't needed.  */
+  cif->bytes = (cif->bytes + 7) & ~7;
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = (unsigned) FFI_TYPE_SINT64;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->abi == FFI_VFP
+	  && (type_code = vfp_type_p (cif->rtype)) != 0)
+	{
+	  /* A Composite Type passed in VFP registers, either
+	     FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */
+	  cif->flags = (unsigned) type_code;
+	}
+      else if (cif->rtype->size <= 4)
+	/* A Composite Type not larger than 4 bytes is returned in r0.  */
+	cif->flags = (unsigned)FFI_TYPE_INT;
+      else
+	/* A Composite Type larger than 4 bytes, or whose size cannot
+	   be determined statically ... is stored in memory at an
+	   address passed [in r0].  */
+	cif->flags = (unsigned)FFI_TYPE_STRUCT;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  /* Map out the register placements of VFP register args.
+     The VFP hard-float calling conventions are slightly more sophisticated than
+     the base calling conventions, so we do it here instead of in ffi_prep_args(). */
+  if (cif->abi == FFI_VFP)
+    layout_vfp_args (cif);
+
+  return FFI_OK;
+}
+
+/* Perform machine dependent cif processing for variadic calls */
+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
+				    unsigned int nfixedargs,
+				    unsigned int ntotalargs)
+{
+  /* VFP variadic calls actually use the SYSV ABI */
+  if (cif->abi == FFI_VFP)
+	cif->abi = FFI_SYSV;
+
+  return ffi_prep_cif_machdep(cif);
+}
+
+/* Prototypes for assembly functions, in sysv.S */
+extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
+extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
+
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  int small_struct = (cif->flags == FFI_TYPE_INT 
+		      && cif->rtype->type == FFI_TYPE_STRUCT);
+  int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
+		    || cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  unsigned int temp;
+  
+  /* If the return value is a struct and we don't have a return	*/
+  /* value address then we need to make one		        */
+
+  if ((rvalue == NULL) && 
+      (cif->flags == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else if (small_struct)
+    ecif.rvalue = &temp;
+  else if (vfp_struct)
+    {
+      /* Largest case is double x 4. */
+      ecif.rvalue = alloca(32);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
+      break;
+
+    case FFI_VFP:
+#ifdef __ARM_EABI__
+      ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
+      break;
+#endif
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+  if (small_struct)
+    memcpy (rvalue, &temp, cif->rtype->size);
+  else if (vfp_struct)
+    memcpy (rvalue, ecif.rvalue, cif->rtype->size);
+}
+
+/** private members **/
+
+static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
+					 void** args, ffi_cif* cif, float *vfp_stack);
+
+void ffi_closure_SYSV (ffi_closure *);
+
+void ffi_closure_VFP (ffi_closure *);
+
+/* This function is jumped to by the trampoline */
+
+unsigned int
+ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
+     ffi_closure *closure;
+     void **respp;
+     void *args;
+     void *vfp_args;
+{
+  // our various things...
+  ffi_cif       *cif;
+  void         **arg_area;
+
+  cif         = closure->cif;
+  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+
+  /* this call will initialize ARG_AREA, such that each
+   * element in that array points to the corresponding 
+   * value on the stack; and if the function returns
+   * a structure, it will re-set RESP to point to the
+   * structure return address.  */
+
+  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
+
+  (closure->fun) (cif, *respp, arg_area, closure->user_data);
+
+  return cif->flags;
+}
+
+/*@-exportheader@*/
+static void 
+ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
+			    void **avalue, ffi_cif *cif,
+			    /* Used only under VFP hard-float ABI. */
+			    float *vfp_stack)
+/*@=exportheader@*/
+{
+  register unsigned int i, vi = 0;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if ( cif->flags == FFI_TYPE_STRUCT ) {
+    *rvalue = *(void **) argp;
+    argp += 4;
+  }
+
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+    {
+      size_t z;
+      size_t alignment;
+  
+      if (cif->abi == FFI_VFP
+	  && vi < cif->vfp_nargs && vfp_type_p (*p_arg))
+	{
+	  *p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]);
+	  continue;
+	}
+
+      alignment = (*p_arg)->alignment;
+      if (alignment < 4)
+	alignment = 4;
+#ifdef _WIN32_WCE
+      else
+	if (alignment > 4)
+	  alignment = 4;
+#endif
+      /* Align if necessary */
+      if ((alignment - 1) & (unsigned) argp) {
+	argp = (char *) ALIGN(argp, alignment);
+      }
+
+      z = (*p_arg)->size;
+
+      /* because we're little endian, this is what it turns into.   */
+
+      *p_argv = (void*) argp;
+
+      p_argv++;
+      argp += z;
+    }
+  
+  return;
+}
+
+/* How to make a trampoline.  */
+
+extern unsigned int ffi_arm_trampoline[3];
+
+#if FFI_EXEC_TRAMPOLINE_TABLE
+
+#include <mach/mach.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern void *ffi_closure_trampoline_table_page;
+
+typedef struct ffi_trampoline_table ffi_trampoline_table;
+typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
+
+struct ffi_trampoline_table {
+  /* contigious writable and executable pages */
+  vm_address_t config_page;
+  vm_address_t trampoline_page;
+
+  /* free list tracking */
+  uint16_t free_count;
+  ffi_trampoline_table_entry *free_list;
+  ffi_trampoline_table_entry *free_list_pool;
+
+  ffi_trampoline_table *prev;
+  ffi_trampoline_table *next;
+};
+
+struct ffi_trampoline_table_entry {
+  void *(*trampoline)();
+  ffi_trampoline_table_entry *next;
+};
+
+/* Override the standard architecture trampoline size */
+// XXX TODO - Fix
+#undef FFI_TRAMPOLINE_SIZE
+#define FFI_TRAMPOLINE_SIZE 12
+
+/* The trampoline configuration is placed at 4080 bytes prior to the trampoline's entry point */
+#define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080));
+
+/* The first 16 bytes of the config page are unused, as they are unaddressable from the trampoline page. */
+#define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16
+
+/* Total number of trampolines that fit in one trampoline table */
+#define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE)
+
+static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER;
+static ffi_trampoline_table *ffi_trampoline_tables = NULL;
+
+static ffi_trampoline_table *
+ffi_trampoline_table_alloc ()
+{
+  ffi_trampoline_table *table = NULL;
+
+  /* Loop until we can allocate two contigious pages */
+  while (table == NULL) {
+    vm_address_t config_page = 0x0;
+    kern_return_t kt;
+
+    /* Try to allocate two pages */
+    kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE);
+    if (kt != KERN_SUCCESS) {
+      fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+      break;
+    }
+
+    /* Now drop the second half of the allocation to make room for the trampoline table */
+    vm_address_t trampoline_page = config_page+PAGE_SIZE;
+    kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
+    if (kt != KERN_SUCCESS) {
+      fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+      break;
+    }
+
+    /* Remap the trampoline table to directly follow the config page */
+    vm_prot_t cur_prot;
+    vm_prot_t max_prot;
+
+    kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE);
+
+    /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
+    if (kt != KERN_SUCCESS) {
+      /* Log unexpected failures */
+      if (kt != KERN_NO_SPACE) {
+        fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+      }
+
+      vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
+      continue;
+    }
+
+    /* We have valid trampoline and config pages */
+    table = calloc (1, sizeof(ffi_trampoline_table));
+    table->free_count = FFI_TRAMPOLINE_COUNT;
+    table->config_page = config_page;
+    table->trampoline_page = trampoline_page;
+
+    /* Create and initialize the free list */
+    table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry));
+
+    uint16_t i;
+    for (i = 0; i < table->free_count; i++) {
+      ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
+      entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
+
+      if (i < table->free_count - 1)
+        entry->next = &table->free_list_pool[i+1];
+    }
+
+    table->free_list = table->free_list_pool;
+  }
+
+  return table;
+}
+
+void *
+ffi_closure_alloc (size_t size, void **code)
+{
+  /* Create the closure */
+  ffi_closure *closure = malloc(size);
+  if (closure == NULL)
+    return NULL;
+
+  pthread_mutex_lock(&ffi_trampoline_lock);
+
+  /* Check for an active trampoline table with available entries. */
+  ffi_trampoline_table *table = ffi_trampoline_tables;
+  if (table == NULL || table->free_list == NULL) {
+    table = ffi_trampoline_table_alloc ();
+    if (table == NULL) {
+      free(closure);
+      return NULL;
+    }
+
+    /* Insert the new table at the top of the list */
+    table->next = ffi_trampoline_tables;
+    if (table->next != NULL)
+        table->next->prev = table;
+
+    ffi_trampoline_tables = table;
+  }
+
+  /* Claim the free entry */
+  ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
+  ffi_trampoline_tables->free_list = entry->next;
+  ffi_trampoline_tables->free_count--;
+  entry->next = NULL;
+
+  pthread_mutex_unlock(&ffi_trampoline_lock);
+
+  /* Initialize the return values */
+  *code = entry->trampoline;
+  closure->trampoline_table = table;
+  closure->trampoline_table_entry = entry;
+
+  return closure;
+}
+
+void
+ffi_closure_free (void *ptr)
+{
+  ffi_closure *closure = ptr;
+
+  pthread_mutex_lock(&ffi_trampoline_lock);
+
+  /* Fetch the table and entry references */
+  ffi_trampoline_table *table = closure->trampoline_table;
+  ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
+
+  /* Return the entry to the free list */
+  entry->next = table->free_list;
+  table->free_list = entry;
+  table->free_count++;
+
+  /* If all trampolines within this table are free, and at least one other table exists, deallocate
+   * the table */
+  if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) {
+    /* Remove from the list */
+    if (table->prev != NULL)
+      table->prev->next = table->next;
+
+    if (table->next != NULL)
+      table->next->prev = table->prev;
+
+    /* Deallocate pages */
+    kern_return_t kt;
+    kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
+    if (kt != KERN_SUCCESS)
+      fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+
+    kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
+    if (kt != KERN_SUCCESS)
+      fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+
+    /* Deallocate free list */
+    free (table->free_list_pool);
+    free (table);
+  } else if (ffi_trampoline_tables != table) {
+    /* Otherwise, bump this table to the top of the list */
+    table->prev = NULL;
+    table->next = ffi_trampoline_tables;
+    if (ffi_trampoline_tables != NULL)
+      ffi_trampoline_tables->prev = table;
+
+    ffi_trampoline_tables = table;
+  }
+
+  pthread_mutex_unlock (&ffi_trampoline_lock);
+
+  /* Free the closure */
+  free (closure);
+}
+
+#else
+
+#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX)				\
+({ unsigned char *__tramp = (unsigned char*)(TRAMP);			\
+   unsigned int  __fun = (unsigned int)(FUN);				\
+   unsigned int  __ctx = (unsigned int)(CTX);				\
+   unsigned char *insns = (unsigned char *)(CTX);                       \
+   memcpy (__tramp, ffi_arm_trampoline, sizeof ffi_arm_trampoline);     \
+   *(unsigned int*) &__tramp[12] = __ctx;				\
+   *(unsigned int*) &__tramp[16] = __fun;				\
+   __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping.  */ \
+   __clear_cache(insns, insns + 3 * sizeof (unsigned int));             \
+                                                 /* Clear instruction   \
+                                                    mapping.  */        \
+ })
+
+#endif
+
+/* the cif must already be prep'ed */
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*,void*,void**,void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  void (*closure_func)(ffi_closure*) = NULL;
+
+  if (cif->abi == FFI_SYSV)
+    closure_func = &ffi_closure_SYSV;
+#ifdef __ARM_EABI__
+  else if (cif->abi == FFI_VFP)
+    closure_func = &ffi_closure_VFP;
+#endif
+  else
+    return FFI_BAD_ABI;
+    
+#if FFI_EXEC_TRAMPOLINE_TABLE
+  void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
+  config[0] = closure;
+  config[1] = closure_func;
+#else
+  FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
+		       closure_func,  \
+		       codeloc);
+#endif
+
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+/* Below are routines for VFP hard-float support. */
+
+static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
+{
+  switch (t->type)
+    {
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      *elt = (int) t->type;
+      *elnum = 1;
+      return 1;
+
+    case FFI_TYPE_STRUCT_VFP_FLOAT:
+      *elt = FFI_TYPE_FLOAT;
+      *elnum = t->size / sizeof (float);
+      return 1;
+
+    case FFI_TYPE_STRUCT_VFP_DOUBLE:
+      *elt = FFI_TYPE_DOUBLE;
+      *elnum = t->size / sizeof (double);
+      return 1;
+
+    case FFI_TYPE_STRUCT:;
+      {
+	int base_elt = 0, total_elnum = 0;
+	ffi_type **el = t->elements;
+	while (*el)
+	  {
+	    int el_elt = 0, el_elnum = 0;
+	    if (! rec_vfp_type_p (*el, &el_elt, &el_elnum)
+		|| (base_elt && base_elt != el_elt)
+		|| total_elnum + el_elnum > 4)
+	      return 0;
+	    base_elt = el_elt;
+	    total_elnum += el_elnum;
+	    el++;
+	  }
+	*elnum = total_elnum;
+	*elt = base_elt;
+	return 1;
+      }
+    default: ;
+    }
+  return 0;
+}
+
+static int vfp_type_p (ffi_type *t)
+{
+  int elt, elnum;
+  if (rec_vfp_type_p (t, &elt, &elnum))
+    {
+      if (t->type == FFI_TYPE_STRUCT)
+	{
+	  if (elnum == 1)
+	    t->type = elt;
+	  else
+	    t->type = (elt == FFI_TYPE_FLOAT
+		       ? FFI_TYPE_STRUCT_VFP_FLOAT
+		       : FFI_TYPE_STRUCT_VFP_DOUBLE);
+	}
+      return (int) t->type;
+    }
+  return 0;
+}
+
+static void place_vfp_arg (ffi_cif *cif, ffi_type *t)
+{
+  int reg = cif->vfp_reg_free;
+  int nregs = t->size / sizeof (float);
+  int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT
+		|| t->type == FFI_TYPE_FLOAT) ? 1 : 2);
+  /* Align register number. */
+  if ((reg & 1) && align == 2)
+    reg++;
+  while (reg + nregs <= 16)
+    {
+      int s, new_used = 0;
+      for (s = reg; s < reg + nregs; s++)
+	{
+	  new_used |= (1 << s);
+	  if (cif->vfp_used & (1 << s))
+	    {
+	      reg += align;
+	      goto next_reg;
+	    }
+	}
+      /* Found regs to allocate. */
+      cif->vfp_used |= new_used;
+      cif->vfp_args[cif->vfp_nargs++] = reg;
+
+      /* Update vfp_reg_free. */
+      if (cif->vfp_used & (1 << cif->vfp_reg_free))
+	{
+	  reg += nregs;
+	  while (cif->vfp_used & (1 << reg))
+	    reg += 1;
+	  cif->vfp_reg_free = reg;
+	}
+      return;
+    next_reg: ;
+    }
+}
+
+static void layout_vfp_args (ffi_cif *cif)
+{
+  int i;
+  /* Init VFP fields */
+  cif->vfp_used = 0;
+  cif->vfp_nargs = 0;
+  cif->vfp_reg_free = 0;
+  memset (cif->vfp_args, -1, 16); /* Init to -1. */
+
+  for (i = 0; i < cif->nargs; i++)
+    {
+      ffi_type *t = cif->arg_types[i];
+      if (vfp_type_p (t))
+	place_vfp_arg (cif, t);
+    }
+}
diff --git a/third_party/gofrontend/libffi/src/arm/ffitarget.h b/third_party/gofrontend/libffi/src/arm/ffitarget.h
new file mode 100644
index 0000000..26d494d
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/arm/ffitarget.h
@@ -0,0 +1,71 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 2010  CodeSourcery
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+
+   Target configuration macros for ARM.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_VFP,
+  FFI_LAST_ABI,
+#ifdef __ARM_PCS_VFP
+  FFI_DEFAULT_ABI = FFI_VFP,
+#else
+  FFI_DEFAULT_ABI = FFI_SYSV,
+#endif
+} ffi_abi;
+#endif
+
+#define FFI_EXTRA_CIF_FIELDS			\
+  int vfp_used;					\
+  short vfp_reg_free, vfp_nargs;		\
+  signed char vfp_args[16]			\
+
+/* Internally used. */
+#define FFI_TYPE_STRUCT_VFP_FLOAT  (FFI_TYPE_LAST + 1)
+#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
+
+#define FFI_TARGET_SPECIFIC_VARIADIC
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 20
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/arm/gentramp.sh b/third_party/gofrontend/libffi/src/arm/gentramp.sh
new file mode 100755
index 0000000..74f0b86
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/arm/gentramp.sh
@@ -0,0 +1,118 @@
+#!/bin/sh
+
+# -----------------------------------------------------------------------
+#  gentramp.sh - Copyright (c) 2010, Plausible Labs Cooperative, Inc.
+#  
+#  ARM Trampoline Page Generator
+#
+#  Permission is hereby granted, free of charge, to any person obtaining
+#  a copy of this software and associated documentation files (the
+#  ``Software''), to deal in the Software without restriction, including
+#  without limitation the rights to use, copy, modify, merge, publish,
+#  distribute, sublicense, and/or sell copies of the Software, and to
+#  permit persons to whom the Software is furnished to do so, subject to
+#  the following conditions:
+#
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+#  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+#  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+#  -----------------------------------------------------------------------
+
+PROGNAME=$0
+
+# Each trampoline is exactly 3 instructions, or 12 bytes. If any of these values change,
+# the entire arm trampoline implementation must be updated to match, too.
+
+# Size of an individual trampoline, in bytes
+TRAMPOLINE_SIZE=12
+
+# Page size, in bytes
+PAGE_SIZE=4096
+
+# Compute the size of the reachable config page; The first 16 bytes of the config page
+# are unreachable due to our maximum pc-relative ldr offset.
+PAGE_AVAIL=`expr $PAGE_SIZE - 16`
+
+# Compute the number of of available trampolines. 
+TRAMPOLINE_COUNT=`expr $PAGE_AVAIL / $TRAMPOLINE_SIZE`
+
+header () {
+    echo "# GENERATED CODE - DO NOT EDIT"
+    echo "# This file was generated by $PROGNAME"
+    echo ""
+
+    # Write out the license header
+cat << EOF
+#  Copyright (c) 2010, Plausible Labs Cooperative, Inc.
+#  
+#  Permission is hereby granted, free of charge, to any person obtaining
+#  a copy of this software and associated documentation files (the
+#  ``Software''), to deal in the Software without restriction, including
+#  without limitation the rights to use, copy, modify, merge, publish,
+#  distribute, sublicense, and/or sell copies of the Software, and to
+#  permit persons to whom the Software is furnished to do so, subject to
+#  the following conditions:
+#
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+#  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+#  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+#  -----------------------------------------------------------------------
+
+EOF
+
+    # Write out the trampoline table, aligned to the page boundary
+    echo ".text"
+    echo ".align 12"
+    echo ".globl _ffi_closure_trampoline_table_page"
+    echo "_ffi_closure_trampoline_table_page:"
+}
+
+
+# WARNING - Don't modify the trampoline code size without also updating the relevent libffi code
+trampoline () {
+    cat << END
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+END
+}
+
+main () {
+    # Write out the header
+    header
+
+    # Write out the trampolines
+    local i=0
+    while [ $i -lt ${TRAMPOLINE_COUNT} ]; do
+        trampoline
+        local i=`expr $i + 1`
+    done
+}
+
+main
diff --git a/third_party/gofrontend/libffi/src/arm/sysv.S b/third_party/gofrontend/libffi/src/arm/sysv.S
new file mode 100644
index 0000000..fb38cd6
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/arm/sysv.S
@@ -0,0 +1,505 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
+	    Copyright (c) 2011 Plausible Labs Cooperative, Inc.
+   
+   ARM Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+#ifdef __USER_LABEL_PREFIX__
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels.  */
+#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+#else
+#define CNAME(x) x
+#endif
+#ifdef __APPLE__
+#define ENTRY(x) .globl _##x; _##x:
+#else
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif /* __APPLE__ */
+#endif
+
+#ifdef __ELF__
+#define LSYM(x) .x
+#else
+#define LSYM(x) x
+#endif
+
+/* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI
+  Function Call Guide */
+#ifdef __APPLE__
+#define __SOFTFP__
+#endif
+
+/* We need a better way of testing for this, but for now, this is all 
+   we can do.  */
+@ This selects the minimum architecture level required.
+#define __ARM_ARCH__ 3
+
+#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 4
+#endif
+        
+#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+	|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+	|| defined(__ARM_ARCH_5TEJ__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 5
+#endif
+
+#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+        || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
+        || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
+	|| defined(__ARM_ARCH_6M__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 6
+#endif
+
+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
+        || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
+	|| defined(__ARM_ARCH_7EM__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 7
+#endif
+
+#if __ARM_ARCH__ >= 5
+# define call_reg(x)	blx	x
+#elif defined (__ARM_ARCH_4T__)
+# define call_reg(x)	mov	lr, pc ; bx	x
+# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
+#  define __INTERWORKING__
+# endif
+#else
+# define call_reg(x)	mov	lr, pc ; mov	pc, x
+#endif
+
+/* Conditionally compile unwinder directives.  */
+#ifdef __ARM_EABI__
+#define UNWIND
+#else
+#define UNWIND @
+#endif	
+
+	
+#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+.macro	ARM_FUNC_START name
+	.text
+	.align 0
+	.thumb
+	.thumb_func
+#ifdef __APPLE__
+	ENTRY($0)
+#else
+	ENTRY(\name)
+#endif
+	bx	pc
+	nop
+	.arm
+	UNWIND .fnstart
+/* A hook to tell gdb that we've switched to ARM mode.  Also used to call
+   directly from other local arm routines.  */
+#ifdef __APPLE__
+_L__$0:
+#else
+_L__\name:
+#endif
+.endm
+#else
+.macro	ARM_FUNC_START name
+	.text
+	.align 0
+	.arm
+#ifdef __APPLE__
+	ENTRY($0)
+#else
+	ENTRY(\name)
+#endif
+	UNWIND .fnstart
+.endm
+#endif
+
+.macro	RETLDM	regs=, cond=, dirn=ia
+#if defined (__INTERWORKING__)
+	.ifc "\regs",""
+	ldr\cond	lr, [sp], #4
+	.else
+	ldm\cond\dirn	sp!, {\regs, lr}
+	.endif
+	bx\cond	lr
+#else
+	.ifc "\regs",""
+	ldr\cond	pc, [sp], #4
+	.else
+	ldm\cond\dirn	sp!, {\regs, pc}
+	.endif
+#endif
+.endm
+
+	@ r0:   ffi_prep_args
+	@ r1:   &ecif
+	@ r2:   cif->bytes
+	@ r3:   fig->flags
+	@ sp+0: ecif.rvalue
+
+	@ This assumes we are using gas.
+ARM_FUNC_START ffi_call_SYSV
+	@ Save registers
+        stmfd	sp!, {r0-r3, fp, lr}
+	UNWIND .save	{r0-r3, fp, lr}
+	mov	fp, sp
+
+	UNWIND .setfp	fp, sp
+
+	@ Make room for all of the new args.
+	sub	sp, fp, r2
+
+	@ Place all of the ffi_prep_args in position
+	mov	r0, sp
+	@     r1 already set
+
+	@ Call ffi_prep_args(stack, &ecif)
+	bl	CNAME(ffi_prep_args)
+
+	@ move first 4 parameters in registers
+	ldmia	sp, {r0-r3}
+
+	@ and adjust stack
+	sub	lr, fp, sp	@ cif->bytes == fp - sp
+	ldr	ip, [fp]	@ load fn() in advance
+	cmp	lr, #16
+	movhs	lr, #16
+	add	sp, sp, lr
+
+	@ call (fn) (...)
+	call_reg(ip)
+	
+	@ Remove the space we pushed for the args
+	mov	sp, fp
+
+	@ Load r2 with the pointer to storage for the return value
+	ldr	r2, [sp, #24]
+
+	@ Load r3 with the return type code 
+	ldr	r3, [sp, #12]
+
+	@ If the return value pointer is NULL, assume no return value.
+	cmp	r2, #0
+	beq	LSYM(Lepilogue)
+
+@ return INT
+	cmp	r3, #FFI_TYPE_INT
+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
+	cmpne	r3, #FFI_TYPE_FLOAT
+#endif
+	streq	r0, [r2]
+	beq	LSYM(Lepilogue)
+
+	@ return INT64
+	cmp	r3, #FFI_TYPE_SINT64
+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
+	cmpne	r3, #FFI_TYPE_DOUBLE
+#endif
+	stmeqia	r2, {r0, r1}
+
+#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
+	beq	LSYM(Lepilogue)
+
+@ return FLOAT
+	cmp	r3, #FFI_TYPE_FLOAT
+	stfeqs	f0, [r2]
+	beq	LSYM(Lepilogue)
+
+@ return DOUBLE or LONGDOUBLE
+	cmp	r3, #FFI_TYPE_DOUBLE
+	stfeqd	f0, [r2]
+#endif
+
+LSYM(Lepilogue):
+#if defined (__INTERWORKING__)
+	ldmia   sp!, {r0-r3,fp, lr}
+	bx	lr
+#else
+	ldmia   sp!, {r0-r3,fp, pc}
+#endif
+
+.ffi_call_SYSV_end:
+	UNWIND .fnend
+#ifdef __ELF__
+        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+#endif
+
+
+/*
+	unsigned int FFI_HIDDEN
+	ffi_closure_SYSV_inner (closure, respp, args)
+	     ffi_closure *closure;
+	     void **respp;
+  	     void *args;
+*/
+
+ARM_FUNC_START ffi_closure_SYSV
+	UNWIND .pad #16
+	add	ip, sp, #16
+	stmfd	sp!, {ip, lr}
+	UNWIND .save	{r0, lr}
+	add	r2, sp, #8
+	UNWIND .pad #16
+	sub	sp, sp, #16
+	str	sp, [sp, #8]
+	add	r1, sp, #8
+	bl	CNAME(ffi_closure_SYSV_inner)
+	cmp	r0, #FFI_TYPE_INT
+	beq	.Lretint
+
+	cmp	r0, #FFI_TYPE_FLOAT
+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
+	beq	.Lretint
+#else
+	beq	.Lretfloat
+#endif
+
+	cmp	r0, #FFI_TYPE_DOUBLE
+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
+	beq	.Lretlonglong
+#else
+	beq	.Lretdouble
+#endif
+
+	cmp	r0, #FFI_TYPE_LONGDOUBLE
+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
+	beq	.Lretlonglong
+#else
+	beq	.Lretlongdouble
+#endif
+
+	cmp	r0, #FFI_TYPE_SINT64
+	beq	.Lretlonglong
+.Lclosure_epilogue:
+	add	sp, sp, #16
+	ldmfd	sp, {sp, pc}
+.Lretint:
+	ldr	r0, [sp]
+	b	.Lclosure_epilogue
+.Lretlonglong:
+	ldr	r0, [sp]
+	ldr	r1, [sp, #4]
+	b	.Lclosure_epilogue
+
+#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
+.Lretfloat:
+	ldfs	f0, [sp]
+	b	.Lclosure_epilogue
+.Lretdouble:
+	ldfd	f0, [sp]
+	b	.Lclosure_epilogue
+.Lretlongdouble:
+	ldfd	f0, [sp]
+	b	.Lclosure_epilogue
+#endif
+
+.ffi_closure_SYSV_end:
+	UNWIND .fnend
+#ifdef __ELF__
+        .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+#endif
+
+
+/* Below are VFP hard-float ABI call and closure implementations.
+   Add VFP FPU directive here. This is only compiled into the library
+   under EABI.  */
+#ifdef __ARM_EABI__
+	.fpu	vfp
+
+	@ r0:   fn
+	@ r1:   &ecif
+	@ r2:   cif->bytes
+	@ r3:   fig->flags
+	@ sp+0: ecif.rvalue
+
+ARM_FUNC_START ffi_call_VFP
+	@ Save registers
+        stmfd	sp!, {r0-r3, fp, lr}
+	UNWIND .save	{r0-r3, fp, lr}
+	mov	fp, sp
+	UNWIND .setfp	fp, sp
+
+	@ Make room for all of the new args.
+	sub	sp, sp, r2
+
+	@ Make room for loading VFP args
+	sub	sp, sp, #64
+
+	@ Place all of the ffi_prep_args in position
+	mov	r0, sp
+	@     r1 already set
+	sub	r2, fp, #64   @ VFP scratch space
+
+	@ Call ffi_prep_args(stack, &ecif, vfp_space)
+	bl	CNAME(ffi_prep_args)
+
+	@ Load VFP register args if needed
+	cmp	r0, #0
+	beq	LSYM(Lbase_args)
+
+	@ Load only d0 if possible
+	cmp	r0, #3
+	sub	ip, fp, #64
+	flddle	d0, [ip]
+	fldmiadgt	ip, {d0-d7}
+
+LSYM(Lbase_args):
+	@ move first 4 parameters in registers
+	ldmia	sp, {r0-r3}
+
+	@ and adjust stack
+	sub	lr, ip, sp	@ cif->bytes == (fp - 64) - sp
+	ldr	ip, [fp]	@ load fn() in advance
+        cmp	lr, #16
+	movhs	lr, #16
+        add	sp, sp, lr
+
+	@ call (fn) (...)
+	call_reg(ip)
+
+	@ Remove the space we pushed for the args
+	mov	sp, fp
+
+	@ Load r2 with the pointer to storage for
+	@ the return value
+	ldr	r2, [sp, #24]
+
+	@ Load r3 with the return type code 
+	ldr	r3, [sp, #12]
+
+	@ If the return value pointer is NULL,
+	@ assume no return value.
+	cmp	r2, #0
+	beq	LSYM(Lepilogue_vfp)
+
+	cmp	r3, #FFI_TYPE_INT
+	streq	r0, [r2]
+	beq	LSYM(Lepilogue_vfp)
+
+	cmp	r3, #FFI_TYPE_SINT64
+	stmeqia	r2, {r0, r1}
+	beq	LSYM(Lepilogue_vfp)
+
+	cmp	r3, #FFI_TYPE_FLOAT
+	fstseq	s0, [r2]
+	beq	LSYM(Lepilogue_vfp)
+	
+	cmp	r3, #FFI_TYPE_DOUBLE
+	fstdeq	d0, [r2]
+	beq	LSYM(Lepilogue_vfp)
+
+	cmp	r3, #FFI_TYPE_STRUCT_VFP_FLOAT
+	cmpne	r3, #FFI_TYPE_STRUCT_VFP_DOUBLE
+	fstmiadeq	r2, {d0-d3}
+
+LSYM(Lepilogue_vfp):
+	RETLDM	"r0-r3,fp"
+
+.ffi_call_VFP_end:
+	UNWIND .fnend
+        .size    CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)
+
+
+ARM_FUNC_START ffi_closure_VFP
+	fstmfdd	sp!, {d0-d7}
+	@ r0-r3, then d0-d7
+	UNWIND .pad #80
+	add	ip, sp, #80
+	stmfd	sp!, {ip, lr}
+	UNWIND .save	{r0, lr}
+	add	r2, sp, #72
+	add	r3, sp, #8
+	UNWIND .pad #72
+	sub	sp, sp, #72
+	str	sp, [sp, #64]
+	add	r1, sp, #64
+	bl	CNAME(ffi_closure_SYSV_inner)
+
+	cmp	r0, #FFI_TYPE_INT
+	beq	.Lretint_vfp
+
+	cmp	r0, #FFI_TYPE_FLOAT
+	beq	.Lretfloat_vfp
+
+	cmp	r0, #FFI_TYPE_DOUBLE
+	cmpne	r0, #FFI_TYPE_LONGDOUBLE
+	beq	.Lretdouble_vfp
+
+	cmp	r0, #FFI_TYPE_SINT64
+	beq	.Lretlonglong_vfp
+
+	cmp	r0, #FFI_TYPE_STRUCT_VFP_FLOAT
+	beq	.Lretfloat_struct_vfp
+
+	cmp	r0, #FFI_TYPE_STRUCT_VFP_DOUBLE
+	beq	.Lretdouble_struct_vfp
+	
+.Lclosure_epilogue_vfp:
+	add	sp, sp, #72
+	ldmfd	sp, {sp, pc}
+
+.Lretfloat_vfp:
+	flds	s0, [sp]
+	b	.Lclosure_epilogue_vfp
+.Lretdouble_vfp:
+	fldd	d0, [sp]
+	b	.Lclosure_epilogue_vfp
+.Lretint_vfp:
+	ldr	r0, [sp]
+	b	.Lclosure_epilogue_vfp
+.Lretlonglong_vfp:
+	ldmia	sp, {r0, r1}
+	b	.Lclosure_epilogue_vfp
+.Lretfloat_struct_vfp:
+	fldmiad	sp, {d0-d1}
+	b	.Lclosure_epilogue_vfp
+.Lretdouble_struct_vfp:
+	fldmiad	sp, {d0-d3}
+	b	.Lclosure_epilogue_vfp
+
+.ffi_closure_VFP_end:
+	UNWIND .fnend
+        .size    CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)
+#endif
+
+ENTRY(ffi_arm_trampoline)
+	stmfd sp!, {r0-r3}
+	ldr r0, [pc]
+	ldr pc, [pc]
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",%progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/arm/trampoline.S b/third_party/gofrontend/libffi/src/arm/trampoline.S
new file mode 100644
index 0000000..935e8de
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/arm/trampoline.S
@@ -0,0 +1,4450 @@
+# GENERATED CODE - DO NOT EDIT
+# This file was generated by src/arm/gentramp.sh
+
+#  Copyright (c) 2010, Plausible Labs Cooperative, Inc.
+#  
+#  Permission is hereby granted, free of charge, to any person obtaining
+#  a copy of this software and associated documentation files (the
+#  Software''), to deal in the Software without restriction, including
+#  without limitation the rights to use, copy, modify, merge, publish,
+#  distribute, sublicense, and/or sell copies of the Software, and to
+#  permit persons to whom the Software is furnished to do so, subject to
+#  the following conditions:
+#
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED AS IS'', WITHOUT WARRANTY OF ANY KIND,
+#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+#  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+#  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+#  -----------------------------------------------------------------------
+
+.text
+.align 12
+.globl _ffi_closure_trampoline_table_page
+_ffi_closure_trampoline_table_page:
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
+
+    // trampoline
+    // Save to stack
+    stmfd sp!, {r0-r3}
+
+    // Load the context argument from the config page.
+    // This places the first usable config value at _ffi_closure_trampoline_table-4080
+    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
+    ldr r0, [pc, #-4092]
+
+    // Load the jump address from the config page.
+    ldr pc, [pc, #-4092]
+
diff --git a/third_party/gofrontend/libffi/src/avr32/ffi.c b/third_party/gofrontend/libffi/src/avr32/ffi.c
new file mode 100644
index 0000000..3d43397
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/avr32/ffi.c
@@ -0,0 +1,423 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2011  Anthony Green
+           Copyright (c) 2009  Bradley Smith <brad@brad-smith.co.uk>
+
+   AVR32 Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <asm/unistd.h>
+
+/* #define DEBUG */
+
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+    unsigned int, unsigned int, unsigned int*, unsigned int,
+    void (*fn)(void));
+extern void ffi_closure_SYSV (ffi_closure *);
+
+unsigned int pass_struct_on_stack(ffi_type *type)
+{
+    if(type->type != FFI_TYPE_STRUCT)
+        return 0;
+
+    if(type->alignment < type->size &&
+        !(type->size == 4 || type->size == 8) &&
+        !(type->size == 8 && type->alignment >= 4))
+        return 1;
+
+    if(type->size == 3 || type->size == 5 || type->size == 6 ||
+        type->size == 7)
+        return 1;
+
+    return 0;
+}
+
+/* ffi_prep_args is called by the assembly routine once stack space
+ * has been allocated for the function's arguments
+ *
+ * This is annoyingly complex since we need to keep track of used
+ * registers.
+ */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+    unsigned int i;
+    void **p_argv;
+    ffi_type **p_arg;
+    char *reg_base = stack;
+    char *stack_base = stack + 20;
+    unsigned int stack_offset = 0;
+    unsigned int reg_mask = 0;
+
+    p_argv = ecif->avalue;
+
+    /* If cif->flags is struct then we know it's not passed in registers */
+    if(ecif->cif->flags == FFI_TYPE_STRUCT)
+    {
+        *(void**)reg_base = ecif->rvalue;
+        reg_mask |= 1;
+    }
+
+    for(i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
+        i++, p_arg++)
+    {
+        size_t z = (*p_arg)->size;
+        int alignment = (*p_arg)->alignment;
+        int type = (*p_arg)->type;
+        char *addr = 0;
+
+        if(z % 4 != 0)
+            z += (4 - z % 4);
+
+        if(reg_mask != 0x1f)
+        {
+            if(pass_struct_on_stack(*p_arg))
+            {
+                addr = stack_base + stack_offset;
+                stack_offset += z;
+            }
+            else if(z == sizeof(int))
+            {
+                char index = 0;
+
+                while((reg_mask >> index) & 1)
+                    index++;
+
+                addr = reg_base + (index * 4);
+                reg_mask |= (1 << index);
+            }
+            else if(z == 2 * sizeof(int))
+            {
+                if(!((reg_mask >> 1) & 1))
+                {
+                    addr = reg_base + 4;
+                    reg_mask |= (3 << 1);
+                }
+                else if(!((reg_mask >> 3) & 1))
+                {
+                    addr = reg_base + 12;
+                    reg_mask |= (3 << 3);
+                }
+            }
+        }
+
+        if(!addr)
+        {
+            addr = stack_base + stack_offset;
+            stack_offset += z;
+        }
+
+        if(type == FFI_TYPE_STRUCT && (*p_arg)->elements[1] == NULL)
+            type = (*p_arg)->elements[0]->type;
+
+        switch(type)
+        {
+        case FFI_TYPE_UINT8:
+            *(unsigned int *)addr = (unsigned int)*(UINT8 *)(*p_argv);
+            break;
+        case FFI_TYPE_SINT8:
+            *(signed int *)addr = (signed int)*(SINT8 *)(*p_argv);
+            break;
+        case FFI_TYPE_UINT16:
+            *(unsigned int *)addr = (unsigned int)*(UINT16 *)(*p_argv);
+            break;
+        case FFI_TYPE_SINT16:
+            *(signed int *)addr = (signed int)*(SINT16 *)(*p_argv);
+            break;
+        default:
+            memcpy(addr, *p_argv, z);
+        }
+
+        p_argv++;
+    }
+
+#ifdef DEBUG
+    /* Debugging */
+    for(i = 0; i < 5; i++)
+    {
+        if((reg_mask & (1 << i)) == 0)
+            printf("r%d: (unused)\n", 12 - i);
+        else
+            printf("r%d: 0x%08x\n", 12 - i, ((unsigned int*)reg_base)[i]);
+    }
+
+    for(i = 0; i < stack_offset / 4; i++)
+    {
+        printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack_base)[i]);
+    }
+#endif
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+    /* Round the stack up to a multiple of 8 bytes.  This isn't needed
+     * everywhere, but it is on some platforms, and it doesn't harm
+     * anything when it isn't needed. */
+    cif->bytes = (cif->bytes + 7) & ~7;
+
+    /* Flag to indicate that he return value is in fact a struct */
+    cif->rstruct_flag = 0;
+
+    /* Set the return type flag */
+    switch(cif->rtype->type)
+    {
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT8:
+        cif->flags = (unsigned)FFI_TYPE_UINT8;
+        break;
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT16:
+        cif->flags = (unsigned)FFI_TYPE_UINT16;
+        break;
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_POINTER:
+        cif->flags = (unsigned)FFI_TYPE_UINT32;
+        break;
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+        cif->flags = (unsigned)FFI_TYPE_UINT64;
+        break;
+    case FFI_TYPE_STRUCT:
+        cif->rstruct_flag = 1;
+        if(!pass_struct_on_stack(cif->rtype))
+        {
+            if(cif->rtype->size <= 1)
+                cif->flags = (unsigned)FFI_TYPE_UINT8;
+            else if(cif->rtype->size <= 2)
+                cif->flags = (unsigned)FFI_TYPE_UINT16;
+            else if(cif->rtype->size <= 4)
+                cif->flags = (unsigned)FFI_TYPE_UINT32;
+            else if(cif->rtype->size <= 8)
+                cif->flags = (unsigned)FFI_TYPE_UINT64;
+            else
+                cif->flags = (unsigned)cif->rtype->type;
+        }
+        else
+            cif->flags = (unsigned)cif->rtype->type;
+        break;
+    default:
+        cif->flags = (unsigned)cif->rtype->type;
+        break;
+    }
+
+    return FFI_OK;
+}
+
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+    extended_cif ecif;
+
+    unsigned int size = 0, i = 0;
+    ffi_type **p_arg;
+
+    ecif.cif = cif;
+    ecif.avalue = avalue;
+
+    for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++)
+        size += (*p_arg)->size + (4 - (*p_arg)->size % 4);
+
+    /* If the return value is a struct and we don't have a return value
+     * address then we need to make one */
+
+    /* If cif->flags is struct then it's not suitable for registers */
+    if((rvalue == NULL) && (cif->flags == FFI_TYPE_STRUCT))
+        ecif.rvalue = alloca(cif->rtype->size);
+    else
+        ecif.rvalue = rvalue;
+
+    switch(cif->abi)
+    {
+    case FFI_SYSV:
+        ffi_call_SYSV(ffi_prep_args, &ecif, size, cif->flags,
+            ecif.rvalue, cif->rstruct_flag, fn);
+        break;
+    default:
+        FFI_ASSERT(0);
+        break;
+    }
+}
+
+static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
+    void **avalue, ffi_cif *cif)
+{
+    register unsigned int i, reg_mask = 0;
+    register void **p_argv;
+    register ffi_type **p_arg;
+    register char *reg_base = stack;
+    register char *stack_base = stack + 20;
+    register unsigned int stack_offset = 0;
+
+#ifdef DEBUG
+    /* Debugging */
+    for(i = 0; i < cif->nargs + 7; i++)
+    {
+        printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack)[i]);
+    }
+#endif
+
+    /* If cif->flags is struct then we know it's not passed in registers */
+    if(cif->flags == FFI_TYPE_STRUCT)
+    {
+        *rvalue = *(void **)reg_base;
+        reg_mask |= 1;
+    }
+
+    p_argv = avalue;
+
+    for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++)
+    {
+        size_t z = (*p_arg)->size;
+        int alignment = (*p_arg)->alignment;
+
+        *p_argv = 0;
+
+        if(z % 4 != 0)
+            z += (4 - z % 4);
+
+        if(reg_mask != 0x1f)
+        {
+            if(pass_struct_on_stack(*p_arg))
+            {
+                *p_argv = (void*)stack_base + stack_offset;
+                stack_offset += z;
+            }
+            else if(z <= sizeof(int))
+            {
+                char index = 0;
+
+                while((reg_mask >> index) & 1)
+                    index++;
+
+                *p_argv = (void*)reg_base + (index * 4);
+                reg_mask |= (1 << index);
+            }
+            else if(z == 2 * sizeof(int))
+            {
+                if(!((reg_mask >> 1) & 1))
+                {
+                    *p_argv = (void*)reg_base + 4;
+                    reg_mask |= (3 << 1);
+                }
+                else if(!((reg_mask >> 3) & 1))
+                {
+                    *p_argv = (void*)reg_base + 12;
+                    reg_mask |= (3 << 3);
+                }
+            }
+        }
+
+        if(!*p_argv)
+        {
+            *p_argv = (void*)stack_base + stack_offset;
+            stack_offset += z;
+        }
+
+        if((*p_arg)->type != FFI_TYPE_STRUCT ||
+            (*p_arg)->elements[1] == NULL)
+        {
+            if(alignment == 1)
+                **(unsigned int**)p_argv <<= 24;
+            else if(alignment == 2)
+                **(unsigned int**)p_argv <<= 16;
+        }
+
+        p_argv++;
+    }
+
+#ifdef DEBUG
+    /* Debugging */
+    for(i = 0; i < cif->nargs; i++)
+    {
+        printf("sp+%d: 0x%08x\n", i*4, *(((unsigned int**)avalue)[i]));
+    }
+#endif
+}
+
+/* This function is jumped to by the trampoline */
+
+unsigned int ffi_closure_SYSV_inner(ffi_closure *closure, void **respp,
+    void *args)
+{
+    ffi_cif *cif;
+    void **arg_area;
+    unsigned int i, size = 0;
+    ffi_type **p_arg;
+
+    cif = closure->cif;
+
+    for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++)
+        size += (*p_arg)->size + (4 - (*p_arg)->size % 4);
+
+    arg_area = (void **)alloca(size);
+
+    /* this call will initialize ARG_AREA, such that each element in that
+     * array points to the corresponding value on the stack; and if the
+     * function returns a structure, it will re-set RESP to point to the
+     * structure return address. */
+
+    ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
+
+    (closure->fun)(cif, *respp, arg_area, closure->user_data);
+
+    return cif->flags;
+}
+
+ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
+    void (*fun)(ffi_cif*, void*, void**, void*), void *user_data,
+    void *codeloc)
+{
+    if (cif->abi != FFI_SYSV)
+      return FFI_BAD_ABI;
+
+    unsigned char *__tramp = (unsigned char*)(&closure->tramp[0]);
+    unsigned int  __fun = (unsigned int)(&ffi_closure_SYSV);
+    unsigned int  __ctx = (unsigned int)(codeloc);
+    unsigned int  __rstruct_flag = (unsigned int)(cif->rstruct_flag);
+    unsigned int  __inner = (unsigned int)(&ffi_closure_SYSV_inner);
+    *(unsigned int*) &__tramp[0] = 0xebcd1f00;    /* pushm  r8-r12 */
+    *(unsigned int*) &__tramp[4] = 0xfefc0010;    /* ld.w   r12, pc[16] */
+    *(unsigned int*) &__tramp[8] = 0xfefb0010;    /* ld.w   r11, pc[16] */
+    *(unsigned int*) &__tramp[12] = 0xfefa0010;   /* ld.w   r10, pc[16] */
+    *(unsigned int*) &__tramp[16] = 0xfeff0010;   /* ld.w   pc, pc[16] */
+    *(unsigned int*) &__tramp[20] = __ctx;
+    *(unsigned int*) &__tramp[24] = __rstruct_flag;
+    *(unsigned int*) &__tramp[28] = __inner;
+    *(unsigned int*) &__tramp[32] = __fun;
+    syscall(__NR_cacheflush, 0, (&__tramp[0]), 36);
+
+    closure->cif = cif;
+    closure->user_data = user_data;
+    closure->fun  = fun;
+
+    return FFI_OK;
+}
+
diff --git a/third_party/gofrontend/libffi/src/avr32/ffitarget.h b/third_party/gofrontend/libffi/src/avr32/ffitarget.h
new file mode 100644
index 0000000..d0c7586
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/avr32/ffitarget.h
@@ -0,0 +1,55 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 2009  Bradley Smith <brad@brad-smith.co.uk>
+   Target configuration macros for AVR32.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+#define FFI_EXTRA_CIF_FIELDS unsigned int rstruct_flag
+
+/* Definitions for closures */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 36
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/avr32/sysv.S b/third_party/gofrontend/libffi/src/avr32/sysv.S
new file mode 100644
index 0000000..a984b3c
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/avr32/sysv.S
@@ -0,0 +1,208 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2009  Bradley Smith <brad@brad-smith.co.uk>
+
+   AVR32 Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+   --------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+    /* r12:  ffi_prep_args
+     * r11:  &ecif
+     * r10:  size
+     * r9:   cif->flags
+     * r8:   ecif.rvalue
+     * sp+0: cif->rstruct_flag
+     * sp+4: fn */
+
+    .text
+    .align  1
+    .globl  ffi_call_SYSV
+    .type   ffi_call_SYSV, @function
+ffi_call_SYSV:
+    stm     --sp, r0,r1,lr
+    stm     --sp, r8-r12
+    mov     r0, sp
+
+    /* Make room for all of the new args. */
+    sub     sp, r10
+    /* Pad to make way for potential skipped registers */
+    sub     sp, 20
+
+    /* Call ffi_prep_args(stack, &ecif). */
+    /* r11 already set */
+    mov     r1, r12
+    mov     r12, sp
+    icall   r1
+
+    /* Save new argument size */
+    mov     r1, r12
+
+    /* Move first 5 parameters in registers. */
+    ldm     sp++, r8-r12
+
+    /* call (fn) (...). */
+    ld.w    r1, r0[36]
+    icall   r1
+
+    /* Remove the space we pushed for the args. */
+    mov     sp, r0
+
+    /* Load r1 with the rstruct flag. */
+    ld.w    r1, sp[32]
+
+    /* Load r9 with the return type code. */
+    ld.w    r9, sp[12]
+
+    /* Load r8 with the return value pointer. */
+    ld.w    r8, sp[16]
+
+    /* If the return value pointer is NULL, assume no return value. */
+    cp.w    r8, 0
+    breq    .Lend
+
+    /* Check if return type is actually a struct */
+    cp.w    r1, 0
+    breq    1f
+
+    /* Return 8bit */
+    cp.w    r9, FFI_TYPE_UINT8
+    breq    .Lstore8
+
+    /* Return 16bit */
+    cp.w    r9, FFI_TYPE_UINT16
+    breq    .Lstore16
+
+1:
+    /* Return 32bit */
+    cp.w    r9, FFI_TYPE_UINT32
+    breq    .Lstore32
+    cp.w    r9, FFI_TYPE_UINT16
+    breq    .Lstore32
+    cp.w    r9, FFI_TYPE_UINT8
+    breq    .Lstore32
+
+    /* Return 64bit */
+    cp.w    r9, FFI_TYPE_UINT64
+    breq    .Lstore64
+
+    /* Didn't match anything */
+    bral    .Lend
+
+.Lstore64:
+    st.w    r8[0], r11
+    st.w    r8[4], r10
+    bral    .Lend
+
+.Lstore32:
+    st.w    r8[0], r12
+    bral    .Lend
+
+.Lstore16:
+    st.h    r8[0], r12
+    bral    .Lend
+
+.Lstore8:
+    st.b    r8[0], r12
+    bral    .Lend
+
+.Lend:
+    sub     sp, -20
+    ldm     sp++, r0,r1,pc
+
+    .size   ffi_call_SYSV, . - ffi_call_SYSV
+
+
+    /* r12:  __ctx
+     * r11:  __rstruct_flag
+     * r10:  __inner */
+
+    .align  1
+    .globl  ffi_closure_SYSV
+    .type   ffi_closure_SYSV, @function
+ffi_closure_SYSV:
+    stm     --sp, r0,lr
+    mov     r0, r11
+    mov     r8, r10
+    sub     r10, sp, -8
+    sub     sp, 12
+    st.w    sp[8], sp
+    sub     r11, sp, -8
+    icall   r8
+
+    /* Check if return type is actually a struct */
+    cp.w    r0, 0
+    breq    1f
+
+    /* Return 8bit */
+    cp.w    r12, FFI_TYPE_UINT8
+    breq    .Lget8
+
+    /* Return 16bit */
+    cp.w    r12, FFI_TYPE_UINT16
+    breq    .Lget16
+
+1:
+    /* Return 32bit */
+    cp.w    r12, FFI_TYPE_UINT32
+    breq    .Lget32
+    cp.w    r12, FFI_TYPE_UINT16
+    breq    .Lget32
+    cp.w    r12, FFI_TYPE_UINT8
+    breq    .Lget32
+
+    /* Return 64bit */
+    cp.w    r12, FFI_TYPE_UINT64
+    breq    .Lget64
+
+    /* Didn't match anything */
+    bral    .Lclend
+
+.Lget64:
+    ld.w    r11, sp[0]
+    ld.w    r10, sp[4]
+    bral    .Lclend
+
+.Lget32:
+    ld.w    r12, sp[0]
+    bral    .Lclend
+
+.Lget16:
+    ld.uh   r12, sp[0]
+    bral    .Lclend
+
+.Lget8:
+    ld.ub   r12, sp[0]
+    bral    .Lclend
+
+.Lclend:
+    sub     sp, -12
+    ldm     sp++, r0,lr
+    sub     sp, -20
+    mov     pc, lr
+
+    .size   ffi_closure_SYSV, . - ffi_closure_SYSV
+
+#if defined __ELF__ && defined __linux__
+    .section    .note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/bfin/ffi.c b/third_party/gofrontend/libffi/src/bfin/ffi.c
new file mode 100644
index 0000000..0beccc1
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/bfin/ffi.c
@@ -0,0 +1,195 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2012  Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
+
+   Blackfin Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Maximum number of GPRs available for argument passing.  */
+#define MAX_GPRARGS 3
+
+/*
+ * Return types
+ */
+#define FFIBFIN_RET_VOID 0
+#define FFIBFIN_RET_BYTE 1
+#define FFIBFIN_RET_HALFWORD 2
+#define FFIBFIN_RET_INT64 3
+#define FFIBFIN_RET_INT32 4
+
+/*====================================================================*/
+/*                          PROTOTYPE          *
+ /*====================================================================*/
+void ffi_prep_args(unsigned char *, extended_cif *);
+
+/*====================================================================*/
+/*                          Externals                                 */
+/*                          (Assembly)                                */
+/*====================================================================*/
+
+extern void ffi_call_SYSV(unsigned, extended_cif *, void(*)(unsigned char *, extended_cif *), unsigned, void *, void(*fn)(void));
+
+/*====================================================================*/
+/*                          Implementation                            */
+/*                                                            */
+/*====================================================================*/
+
+
+/*
+ * This function calculates the return type (size) based on type.
+ */
+
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+   /* --------------------------------------*
+    *   Return handling                *
+    * --------------------------------------*/
+   switch (cif->rtype->type) {
+      case FFI_TYPE_VOID:
+         cif->flags = FFIBFIN_RET_VOID;
+         break;
+      case FFI_TYPE_UINT16:
+      case FFI_TYPE_SINT16:
+         cif->flags = FFIBFIN_RET_HALFWORD;
+         break;
+      case FFI_TYPE_UINT8:
+         cif->flags = FFIBFIN_RET_BYTE;
+         break;
+      case FFI_TYPE_INT:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_FLOAT:
+      case FFI_TYPE_POINTER:
+      case FFI_TYPE_SINT8:
+         cif->flags = FFIBFIN_RET_INT32;
+         break;
+      case FFI_TYPE_SINT64:
+      case FFI_TYPE_UINT64:
+      case FFI_TYPE_DOUBLE:
+          cif->flags = FFIBFIN_RET_INT64;
+          break;
+      case FFI_TYPE_STRUCT:
+         if (cif->rtype->size <= 4){
+        	 cif->flags = FFIBFIN_RET_INT32;
+         }else if (cif->rtype->size == 8){
+        	 cif->flags = FFIBFIN_RET_INT64;
+         }else{
+        	 //it will return via a hidden pointer in P0
+        	 cif->flags = FFIBFIN_RET_VOID;
+         }
+         break;
+      default:
+         FFI_ASSERT(0);
+         break;
+   }
+   return FFI_OK;
+}
+
+/*
+ * This will prepare the arguments and will call the assembly routine
+ * cif = the call interface
+ * fn = the function to be called
+ * rvalue = the return value
+ * avalue = the arguments
+ */
+void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue)
+{
+   int ret_type = cif->flags;
+   extended_cif ecif;
+   ecif.cif = cif;
+   ecif.avalue = avalue;
+   ecif.rvalue = rvalue;
+
+   switch (cif->abi) {
+      case FFI_SYSV:
+         ffi_call_SYSV(cif->bytes, &ecif, ffi_prep_args, ret_type, ecif.rvalue, fn);
+         break;
+      default:
+         FFI_ASSERT(0);
+         break;
+   }
+}
+
+
+/*
+* This function prepares the parameters (copies them from the ecif to the stack)
+*  to call the function (ffi_prep_args is called by the assembly routine in file
+*  sysv.S, which also calls the actual function)
+*/
+void ffi_prep_args(unsigned char *stack, extended_cif *ecif)
+{
+   register unsigned int i = 0;
+   void **p_argv;
+   unsigned char *argp;
+   ffi_type **p_arg;
+   argp = stack;
+   p_argv = ecif->avalue;
+   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+        (i != 0);
+        i--, p_arg++) {
+      size_t z;
+      z = (*p_arg)->size;
+      if (z < sizeof(int)) {
+         z = sizeof(int);
+         switch ((*p_arg)->type) {
+            case FFI_TYPE_SINT8: {
+                  signed char v = *(SINT8 *)(* p_argv);
+                  signed int t = v;
+                  *(signed int *) argp = t;
+               }
+               break;
+            case FFI_TYPE_UINT8: {
+                  unsigned char v = *(UINT8 *)(* p_argv);
+                  unsigned int t = v;
+                  *(unsigned int *) argp = t;
+               }
+               break;
+            case FFI_TYPE_SINT16:
+               *(signed int *) argp = (signed int) * (SINT16 *)(* p_argv);
+               break;
+            case FFI_TYPE_UINT16:
+               *(unsigned int *) argp = (unsigned int) * (UINT16 *)(* p_argv);
+               break;
+            case FFI_TYPE_STRUCT:
+               memcpy(argp, *p_argv, (*p_arg)->size);
+               break;
+            default:
+               FFI_ASSERT(0);
+               break;
+         }
+      } else if (z == sizeof(int)) {
+         *(unsigned int *) argp = (unsigned int) * (UINT32 *)(* p_argv);
+      } else {
+         memcpy(argp, *p_argv, z);
+      }
+      p_argv++;
+      argp += z;
+   }
+}
+
+
+
diff --git a/third_party/gofrontend/libffi/src/bfin/ffitarget.h b/third_party/gofrontend/libffi/src/bfin/ffitarget.h
new file mode 100644
index 0000000..2175c01
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/bfin/ffitarget.h
@@ -0,0 +1,43 @@
+/* -----------------------------------------------------------------------
+   ffitarget.h - Copyright (c) 2012  Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
+
+   Blackfin Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed 	 long          ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+#endif
+
diff --git a/third_party/gofrontend/libffi/src/bfin/sysv.S b/third_party/gofrontend/libffi/src/bfin/sysv.S
new file mode 100644
index 0000000..ae7a152
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/bfin/sysv.S
@@ -0,0 +1,177 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2012  Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
+
+   Blackfin Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+.align 4
+
+	/*
+	 There is a "feature" in the bfin toolchain that it puts a _ before funcion names
+	 that's why the function here it's called _ffi_call_SYSV and not ffi_call_SYSV
+	 */
+	.global _ffi_call_SYSV;
+	.type _ffi_call_SYSV, STT_FUNC;
+	.func ffi_call_SYSV
+
+	/*
+	cif->bytes  	= R0	(fp+8)
+	&ecif			= R1	(fp+12)
+	ffi_prep_args	= R2	(fp+16)
+	ret_type		= stack (fp+20)
+	ecif.rvalue		= stack (fp+24)
+	fn				= stack	(fp+28)
+					  got	(fp+32)
+    There is room for improvement here (we can use temporary registers
+        instead of saving the values in the memory)
+	REGS:
+		P5 => Stack pointer (function arguments)
+		R5 => cif->bytes
+		R4 => ret->type
+
+		FP-20 = P3
+		FP-16 = SP (parameters area)
+		FP-12 = SP (temp)
+		FP-08 = function return part 1 [R0]
+		FP-04 = function return part 2 [R1]
+	*/
+
+_ffi_call_SYSV:
+.prologue:
+	LINK 20;
+	[FP-20] = P3;
+	[FP+8] = R0;
+	[FP+12] = R1;
+	[FP+16] = R2;
+
+.allocate_stack:
+	//alocate cif->bytes into the stack
+	R1 = [FP+8];
+	R0 = SP;
+	R0 = R0 - R1;
+	R1 = 4;
+	R0 = R0 - R1;
+	[FP-12] = SP;
+	SP = R0;
+	[FP-16] = SP;
+
+.call_prep_args:
+	//get the addr of prep_args
+	P0 = [P3 + _ffi_prep_args@FUNCDESC_GOT17M4];
+	P1 = [P0];
+	P3 = [P0+4];
+	R0 = [FP-16];//SP (parameter area)
+	R1 = [FP+12];//ecif
+	call (P1);
+
+.call_user_function:
+	//ajust SP so as to allow the user function access the parameters on the stack
+	SP = [FP-16]; //point to function parameters
+	R0 = [SP];
+	R1 = [SP+4];
+	R2 = [SP+8];
+	//load user function address
+	P0 = FP;
+	P0 +=28;
+	P1 = [P0];
+	P1 = [P1];
+	P3 = [P0+4];
+	/*
+		For functions returning aggregate values (struct) occupying more than 8 bytes,
+		the caller allocates the return value object on the stack and the address
+		of this object is passed to the callee as a hidden argument in register P0.
+	*/
+	P0 = [FP+24];
+
+	call (P1);
+	SP = [FP-12];
+.compute_return:
+	P2 = [FP-20];
+	[FP-8] = R0;
+	[FP-4] = R1;
+
+	R0 = [FP+20];
+	R1 = R0 << 2;
+
+	R0 = [P2+.rettable@GOT17M4];
+	R0 = R1 + R0;
+	P2 = R0;
+	R1 = [P2];
+
+	P2 = [FP+-20];
+	R0 = [P2+.rettable@GOT17M4];
+	R0 = R1 + R0;
+	P2 = R0;
+	R0 = [FP-8];
+	R1 = [FP-4];
+	jump (P2);
+
+/*
+#define FFIBFIN_RET_VOID 0
+#define FFIBFIN_RET_BYTE 1
+#define FFIBFIN_RET_HALFWORD 2
+#define FFIBFIN_RET_INT64 3
+#define FFIBFIN_RET_INT32 4
+*/
+.align 4
+.align 4
+.rettable:
+	.dd .epilogue - .rettable
+	.dd	.rbyte - .rettable;
+	.dd	.rhalfword - .rettable;
+	.dd	.rint64 - .rettable;
+	.dd	.rint32 - .rettable;
+
+.rbyte:
+	P0 = [FP+24];
+	R0 = R0.B (Z);
+	[P0] = R0;
+	JUMP .epilogue
+.rhalfword:
+	P0 = [FP+24];
+	R0 = R0.L;
+	[P0] = R0;
+	JUMP .epilogue
+.rint64:
+	P0 = [FP+24];// &rvalue
+	[P0] = R0;
+	[P0+4] = R1;
+	JUMP .epilogue
+.rint32:
+	P0 = [FP+24];
+	[P0] = R0;
+.epilogue:
+	R0 = [FP+8];
+	R1 = [FP+12];
+	R2 = [FP+16];
+	P3 = [FP-20];
+	UNLINK;
+	RTS;
+
+.size _ffi_call_SYSV,.-_ffi_call_SYSV;
+.endfunc
diff --git a/third_party/gofrontend/libffi/src/closures.c b/third_party/gofrontend/libffi/src/closures.c
new file mode 100644
index 0000000..6298d6f
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/closures.c
@@ -0,0 +1,644 @@
+/* -----------------------------------------------------------------------
+   closures.c - Copyright (c) 2007, 2009, 2010  Red Hat, Inc.
+                Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc
+                Copyright (c) 2011 Plausible Labs Cooperative, Inc.
+
+   Code to allocate and deallocate memory for closures.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#if defined __linux__ && !defined _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
+# if __gnu_linux__
+/* This macro indicates it may be forbidden to map anonymous memory
+   with both write and execute permission.  Code compiled when this
+   option is defined will attempt to map such pages once, but if it
+   fails, it falls back to creating a temporary file in a writable and
+   executable filesystem and mapping pages from it into separate
+   locations in the virtual memory space, one location writable and
+   another executable.  */
+#  define FFI_MMAP_EXEC_WRIT 1
+#  define HAVE_MNTENT 1
+# endif
+# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)
+/* Windows systems may have Data Execution Protection (DEP) enabled, 
+   which requires the use of VirtualMalloc/VirtualFree to alloc/free
+   executable memory. */
+#  define FFI_MMAP_EXEC_WRIT 1
+# endif
+#endif
+
+#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
+# ifdef __linux__
+/* When defined to 1 check for SELinux and if SELinux is active,
+   don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
+   might cause audit messages.  */
+#  define FFI_MMAP_EXEC_SELINUX 1
+# endif
+#endif
+
+#if FFI_CLOSURES
+
+# if FFI_EXEC_TRAMPOLINE_TABLE
+
+// Per-target implementation; It's unclear what can reasonable be shared between two OS/architecture implementations.
+
+# elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */
+
+#define USE_LOCKS 1
+#define USE_DL_PREFIX 1
+#ifdef __GNUC__
+#ifndef USE_BUILTIN_FFS
+#define USE_BUILTIN_FFS 1
+#endif
+#endif
+
+/* We need to use mmap, not sbrk.  */
+#define HAVE_MORECORE 0
+
+/* We could, in theory, support mremap, but it wouldn't buy us anything.  */
+#define HAVE_MREMAP 0
+
+/* We have no use for this, so save some code and data.  */
+#define NO_MALLINFO 1
+
+/* We need all allocations to be in regular segments, otherwise we
+   lose track of the corresponding code address.  */
+#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
+
+/* Don't allocate more than a page unless needed.  */
+#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize)
+
+#if FFI_CLOSURE_TEST
+/* Don't release single pages, to avoid a worst-case scenario of
+   continuously allocating and releasing single pages, but release
+   pairs of pages, which should do just as well given that allocations
+   are likely to be small.  */
+#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize)
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#if !defined(X86_WIN32) && !defined(X86_WIN64)
+#ifdef HAVE_MNTENT
+#include <mntent.h>
+#endif /* HAVE_MNTENT */
+#include <sys/param.h>
+#include <pthread.h>
+
+/* We don't want sys/mman.h to be included after we redefine mmap and
+   dlmunmap.  */
+#include <sys/mman.h>
+#define LACKS_SYS_MMAN_H 1
+
+#if FFI_MMAP_EXEC_SELINUX
+#include <sys/statfs.h>
+#include <stdlib.h>
+
+static int selinux_enabled = -1;
+
+static int
+selinux_enabled_check (void)
+{
+  struct statfs sfs;
+  FILE *f;
+  char *buf = NULL;
+  size_t len = 0;
+
+  if (statfs ("/selinux", &sfs) >= 0
+      && (unsigned int) sfs.f_type == 0xf97cff8cU)
+    return 1;
+  f = fopen ("/proc/mounts", "r");
+  if (f == NULL)
+    return 0;
+  while (getline (&buf, &len, f) >= 0)
+    {
+      char *p = strchr (buf, ' ');
+      if (p == NULL)
+        break;
+      p = strchr (p + 1, ' ');
+      if (p == NULL)
+        break;
+      if (strncmp (p + 1, "selinuxfs ", 10) == 0)
+        {
+          free (buf);
+          fclose (f);
+          return 1;
+        }
+    }
+  free (buf);
+  fclose (f);
+  return 0;
+}
+
+#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \
+			      : (selinux_enabled = selinux_enabled_check ()))
+
+#else
+
+#define is_selinux_enabled() 0
+
+#endif /* !FFI_MMAP_EXEC_SELINUX */
+
+/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */
+#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
+#include <stdlib.h>
+
+static int emutramp_enabled = -1;
+
+static int
+emutramp_enabled_check (void)
+{
+  if (getenv ("FFI_DISABLE_EMUTRAMP") == NULL)
+    return 1;
+  else
+    return 0;
+}
+
+#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
+                               : (emutramp_enabled = emutramp_enabled_check ()))
+#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
+
+#elif defined (__CYGWIN__) || defined(__INTERIX)
+
+#include <sys/mman.h>
+
+/* Cygwin is Linux-like, but not quite that Linux-like.  */
+#define is_selinux_enabled() 0
+
+#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
+
+#ifndef FFI_MMAP_EXEC_EMUTRAMP_PAX
+#define is_emutramp_enabled() 0
+#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
+
+/* Declare all functions defined in dlmalloc.c as static.  */
+static void *dlmalloc(size_t);
+static void dlfree(void*);
+static void *dlcalloc(size_t, size_t) MAYBE_UNUSED;
+static void *dlrealloc(void *, size_t) MAYBE_UNUSED;
+static void *dlmemalign(size_t, size_t) MAYBE_UNUSED;
+static void *dlvalloc(size_t) MAYBE_UNUSED;
+static int dlmallopt(int, int) MAYBE_UNUSED;
+static size_t dlmalloc_footprint(void) MAYBE_UNUSED;
+static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED;
+static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED;
+static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED;
+static void *dlpvalloc(size_t) MAYBE_UNUSED;
+static int dlmalloc_trim(size_t) MAYBE_UNUSED;
+static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
+static void dlmalloc_stats(void) MAYBE_UNUSED;
+
+#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
+/* Use these for mmap and munmap within dlmalloc.c.  */
+static void *dlmmap(void *, size_t, int, int, int, off_t);
+static int dlmunmap(void *, size_t);
+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
+
+#define mmap dlmmap
+#define munmap dlmunmap
+
+#include "dlmalloc.c"
+
+#undef mmap
+#undef munmap
+
+#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
+
+/* A mutex used to synchronize access to *exec* variables in this file.  */
+static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* A file descriptor of a temporary file from which we'll map
+   executable pages.  */
+static int execfd = -1;
+
+/* The amount of space already allocated from the temporary file.  */
+static size_t execsize = 0;
+
+/* Open a temporary file name, and immediately unlink it.  */
+static int
+open_temp_exec_file_name (char *name)
+{
+  int fd = mkstemp (name);
+
+  if (fd != -1)
+    unlink (name);
+
+  return fd;
+}
+
+/* Open a temporary file in the named directory.  */
+static int
+open_temp_exec_file_dir (const char *dir)
+{
+  static const char suffix[] = "/ffiXXXXXX";
+  int lendir = strlen (dir);
+  char *tempname = __builtin_alloca (lendir + sizeof (suffix));
+
+  if (!tempname)
+    return -1;
+
+  memcpy (tempname, dir, lendir);
+  memcpy (tempname + lendir, suffix, sizeof (suffix));
+
+  return open_temp_exec_file_name (tempname);
+}
+
+/* Open a temporary file in the directory in the named environment
+   variable.  */
+static int
+open_temp_exec_file_env (const char *envvar)
+{
+  const char *value = getenv (envvar);
+
+  if (!value)
+    return -1;
+
+  return open_temp_exec_file_dir (value);
+}
+
+#ifdef HAVE_MNTENT
+/* Open a temporary file in an executable and writable mount point
+   listed in the mounts file.  Subsequent calls with the same mounts
+   keep searching for mount points in the same file.  Providing NULL
+   as the mounts file closes the file.  */
+static int
+open_temp_exec_file_mnt (const char *mounts)
+{
+  static const char *last_mounts;
+  static FILE *last_mntent;
+
+  if (mounts != last_mounts)
+    {
+      if (last_mntent)
+	endmntent (last_mntent);
+
+      last_mounts = mounts;
+
+      if (mounts)
+	last_mntent = setmntent (mounts, "r");
+      else
+	last_mntent = NULL;
+    }
+
+  if (!last_mntent)
+    return -1;
+
+  for (;;)
+    {
+      int fd;
+      struct mntent mnt;
+      char buf[MAXPATHLEN * 3];
+
+      if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)) == NULL)
+	return -1;
+
+      if (hasmntopt (&mnt, "ro")
+	  || hasmntopt (&mnt, "noexec")
+	  || access (mnt.mnt_dir, W_OK))
+	continue;
+
+      fd = open_temp_exec_file_dir (mnt.mnt_dir);
+
+      if (fd != -1)
+	return fd;
+    }
+}
+#endif /* HAVE_MNTENT */
+
+/* Instructions to look for a location to hold a temporary file that
+   can be mapped in for execution.  */
+static struct
+{
+  int (*func)(const char *);
+  const char *arg;
+  int repeat;
+} open_temp_exec_file_opts[] = {
+  { open_temp_exec_file_env, "TMPDIR", 0 },
+  { open_temp_exec_file_dir, "/tmp", 0 },
+  { open_temp_exec_file_dir, "/var/tmp", 0 },
+  { open_temp_exec_file_dir, "/dev/shm", 0 },
+  { open_temp_exec_file_env, "HOME", 0 },
+#ifdef HAVE_MNTENT
+  { open_temp_exec_file_mnt, "/etc/mtab", 1 },
+  { open_temp_exec_file_mnt, "/proc/mounts", 1 },
+#endif /* HAVE_MNTENT */
+};
+
+/* Current index into open_temp_exec_file_opts.  */
+static int open_temp_exec_file_opts_idx = 0;
+
+/* Reset a current multi-call func, then advances to the next entry.
+   If we're at the last, go back to the first and return nonzero,
+   otherwise return zero.  */
+static int
+open_temp_exec_file_opts_next (void)
+{
+  if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
+    open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL);
+
+  open_temp_exec_file_opts_idx++;
+  if (open_temp_exec_file_opts_idx
+      == (sizeof (open_temp_exec_file_opts)
+	  / sizeof (*open_temp_exec_file_opts)))
+    {
+      open_temp_exec_file_opts_idx = 0;
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Return a file descriptor of a temporary zero-sized file in a
+   writable and exexutable filesystem.  */
+static int
+open_temp_exec_file (void)
+{
+  int fd;
+
+  do
+    {
+      fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func
+	(open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg);
+
+      if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat
+	  || fd == -1)
+	{
+	  if (open_temp_exec_file_opts_next ())
+	    break;
+	}
+    }
+  while (fd == -1);
+
+  return fd;
+}
+
+/* Map in a chunk of memory from the temporary exec file into separate
+   locations in the virtual memory address space, one writable and one
+   executable.  Returns the address of the writable portion, after
+   storing an offset to the corresponding executable portion at the
+   last word of the requested chunk.  */
+static void *
+dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset)
+{
+  void *ptr;
+
+  if (execfd == -1)
+    {
+      open_temp_exec_file_opts_idx = 0;
+    retry_open:
+      execfd = open_temp_exec_file ();
+      if (execfd == -1)
+	return MFAIL;
+    }
+
+  offset = execsize;
+
+  if (ftruncate (execfd, offset + length))
+    return MFAIL;
+
+  flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS);
+  flags |= MAP_SHARED;
+
+  ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC,
+	      flags, execfd, offset);
+  if (ptr == MFAIL)
+    {
+      if (!offset)
+	{
+	  close (execfd);
+	  goto retry_open;
+	}
+      ftruncate (execfd, offset);
+      return MFAIL;
+    }
+  else if (!offset
+	   && open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
+    open_temp_exec_file_opts_next ();
+
+  start = mmap (start, length, prot, flags, execfd, offset);
+
+  if (start == MFAIL)
+    {
+      munmap (ptr, length);
+      ftruncate (execfd, offset);
+      return start;
+    }
+
+  mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start;
+
+  execsize += length;
+
+  return start;
+}
+
+/* Map in a writable and executable chunk of memory if possible.
+   Failing that, fall back to dlmmap_locked.  */
+static void *
+dlmmap (void *start, size_t length, int prot,
+	int flags, int fd, off_t offset)
+{
+  void *ptr;
+
+  assert (start == NULL && length % malloc_getpagesize == 0
+	  && prot == (PROT_READ | PROT_WRITE)
+	  && flags == (MAP_PRIVATE | MAP_ANONYMOUS)
+	  && fd == -1 && offset == 0);
+
+#if FFI_CLOSURE_TEST
+  printf ("mapping in %zi\n", length);
+#endif
+
+  if (execfd == -1 && is_emutramp_enabled ())
+    {
+      ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset);
+      return ptr;
+    }
+
+  if (execfd == -1 && !is_selinux_enabled ())
+    {
+      ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
+
+      if (ptr != MFAIL || (errno != EPERM && errno != EACCES))
+	/* Cool, no need to mess with separate segments.  */
+	return ptr;
+
+      /* If MREMAP_DUP is ever introduced and implemented, try mmap
+	 with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with
+	 MREMAP_DUP and prot at this point.  */
+    }
+
+  if (execsize == 0 || execfd == -1)
+    {
+      pthread_mutex_lock (&open_temp_exec_file_mutex);
+      ptr = dlmmap_locked (start, length, prot, flags, offset);
+      pthread_mutex_unlock (&open_temp_exec_file_mutex);
+
+      return ptr;
+    }
+
+  return dlmmap_locked (start, length, prot, flags, offset);
+}
+
+/* Release memory at the given address, as well as the corresponding
+   executable page if it's separate.  */
+static int
+dlmunmap (void *start, size_t length)
+{
+  /* We don't bother decreasing execsize or truncating the file, since
+     we can't quite tell whether we're unmapping the end of the file.
+     We don't expect frequent deallocation anyway.  If we did, we
+     could locate pages in the file by writing to the pages being
+     deallocated and checking that the file contents change.
+     Yuck.  */
+  msegmentptr seg = segment_holding (gm, start);
+  void *code;
+
+#if FFI_CLOSURE_TEST
+  printf ("unmapping %zi\n", length);
+#endif
+
+  if (seg && (code = add_segment_exec_offset (start, seg)) != start)
+    {
+      int ret = munmap (code, length);
+      if (ret)
+	return ret;
+    }
+
+  return munmap (start, length);
+}
+
+#if FFI_CLOSURE_FREE_CODE
+/* Return segment holding given code address.  */
+static msegmentptr
+segment_holding_code (mstate m, char* addr)
+{
+  msegmentptr sp = &m->seg;
+  for (;;) {
+    if (addr >= add_segment_exec_offset (sp->base, sp)
+	&& addr < add_segment_exec_offset (sp->base, sp) + sp->size)
+      return sp;
+    if ((sp = sp->next) == 0)
+      return 0;
+  }
+}
+#endif
+
+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
+
+/* Allocate a chunk of memory with the given size.  Returns a pointer
+   to the writable address, and sets *CODE to the executable
+   corresponding virtual address.  */
+void *
+ffi_closure_alloc (size_t size, void **code)
+{
+  void *ptr;
+
+  if (!code)
+    return NULL;
+
+  ptr = dlmalloc (size);
+
+  if (ptr)
+    {
+      msegmentptr seg = segment_holding (gm, ptr);
+
+      *code = add_segment_exec_offset (ptr, seg);
+    }
+
+  return ptr;
+}
+
+/* Release a chunk of memory allocated with ffi_closure_alloc.  If
+   FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the
+   writable or the executable address given.  Otherwise, only the
+   writable address can be provided here.  */
+void
+ffi_closure_free (void *ptr)
+{
+#if FFI_CLOSURE_FREE_CODE
+  msegmentptr seg = segment_holding_code (gm, ptr);
+
+  if (seg)
+    ptr = sub_segment_exec_offset (ptr, seg);
+#endif
+
+  dlfree (ptr);
+}
+
+
+#if FFI_CLOSURE_TEST
+/* Do some internal sanity testing to make sure allocation and
+   deallocation of pages are working as intended.  */
+int main ()
+{
+  void *p[3];
+#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0)
+#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0)
+  GET (0, malloc_getpagesize / 2);
+  GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*));
+  PUT (1);
+  GET (1, 2 * malloc_getpagesize);
+  GET (2, malloc_getpagesize / 2);
+  PUT (1);
+  PUT (0);
+  PUT (2);
+  return 0;
+}
+#endif /* FFI_CLOSURE_TEST */
+# else /* ! FFI_MMAP_EXEC_WRIT */
+
+/* On many systems, memory returned by malloc is writable and
+   executable, so just use it.  */
+
+#include <stdlib.h>
+
+void *
+ffi_closure_alloc (size_t size, void **code)
+{
+  if (!code)
+    return NULL;
+
+  return *code = malloc (size);
+}
+
+void
+ffi_closure_free (void *ptr)
+{
+  free (ptr);
+}
+
+# endif /* ! FFI_MMAP_EXEC_WRIT */
+#endif /* FFI_CLOSURES */
diff --git a/third_party/gofrontend/libffi/src/cris/ffi.c b/third_party/gofrontend/libffi/src/cris/ffi.c
new file mode 100644
index 0000000..aaca5b1
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/cris/ffi.c
@@ -0,0 +1,386 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Cygnus Solutions
+           Copyright (c) 2004 Simon Posnjak
+	   Copyright (c) 2005 Axis Communications AB
+	   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   CRIS Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
+
+static ffi_status
+initialize_aggregate_packed_struct (ffi_type * arg)
+{
+  ffi_type **ptr;
+
+  FFI_ASSERT (arg != NULL);
+
+  FFI_ASSERT (arg->elements != NULL);
+  FFI_ASSERT (arg->size == 0);
+  FFI_ASSERT (arg->alignment == 0);
+
+  ptr = &(arg->elements[0]);
+
+  while ((*ptr) != NULL)
+    {
+      if (((*ptr)->size == 0)
+	  && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
+	return FFI_BAD_TYPEDEF;
+
+      FFI_ASSERT (ffi_type_test ((*ptr)));
+
+      arg->size += (*ptr)->size;
+
+      arg->alignment = (arg->alignment > (*ptr)->alignment) ?
+	arg->alignment : (*ptr)->alignment;
+
+      ptr++;
+    }
+
+  if (arg->size == 0)
+    return FFI_BAD_TYPEDEF;
+  else
+    return FFI_OK;
+}
+
+int
+ffi_prep_args (char *stack, extended_cif * ecif)
+{
+  unsigned int i;
+  unsigned int struct_count = 0;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  argp = stack;
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0); i--, p_arg++)
+    {
+      size_t z;
+
+      switch ((*p_arg)->type)
+	{
+	case FFI_TYPE_STRUCT:
+	  {
+	    z = (*p_arg)->size;
+	    if (z <= 4)
+	      {
+		memcpy (argp, *p_argv, z);
+		z = 4;
+	      }
+	    else if (z <= 8)
+	      {
+		memcpy (argp, *p_argv, z);
+		z = 8;
+	      }
+	    else
+	      {
+		unsigned int uiLocOnStack;
+		z = sizeof (void *);
+		uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
+		struct_count = struct_count + (*p_arg)->size;
+		*(unsigned int *) argp =
+		  (unsigned int) (UINT32 *) (stack + uiLocOnStack);
+		memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
+	      }
+	    break;
+	  }
+	default:
+	  z = (*p_arg)->size;
+	  if (z < sizeof (int))
+	    {
+	      switch ((*p_arg)->type)
+		{
+		case FFI_TYPE_SINT8:
+		  *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
+		  break;
+
+		case FFI_TYPE_UINT8:
+		  *(unsigned int *) argp =
+		    (unsigned int) *(UINT8 *) (*p_argv);
+		  break;
+
+		case FFI_TYPE_SINT16:
+		  *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
+		  break;
+
+		case FFI_TYPE_UINT16:
+		  *(unsigned int *) argp =
+		    (unsigned int) *(UINT16 *) (*p_argv);
+		  break;
+
+		default:
+		  FFI_ASSERT (0);
+		}
+	      z = sizeof (int);
+	    }
+	  else if (z == sizeof (int))
+	    *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
+	  else
+	    memcpy (argp, *p_argv, z);
+	  break;
+	}
+      p_argv++;
+      argp += z;
+    }
+
+  return (struct_count);
+}
+
+ffi_status FFI_HIDDEN
+ffi_prep_cif_core (ffi_cif * cif,
+	           ffi_abi abi, unsigned int isvariadic,
+		   unsigned int nfixedargs, unsigned int ntotalargs,
+	           ffi_type * rtype, ffi_type ** atypes)
+{
+  unsigned bytes = 0;
+  unsigned int i;
+  ffi_type **ptr;
+
+  FFI_ASSERT (cif != NULL);
+  FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
+  FFI_ASSERT(nfixedargs <= ntotalargs);
+  FFI_ASSERT (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI);
+
+  cif->abi = abi;
+  cif->arg_types = atypes;
+  cif->nargs = ntotalargs;
+  cif->rtype = rtype;
+
+  cif->flags = 0;
+
+  if ((cif->rtype->size == 0)
+      && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
+    return FFI_BAD_TYPEDEF;
+
+  FFI_ASSERT_VALID_TYPE (cif->rtype);
+
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+      if (((*ptr)->size == 0)
+	  && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
+	return FFI_BAD_TYPEDEF;
+
+      FFI_ASSERT_VALID_TYPE (*ptr);
+
+      if (((*ptr)->alignment - 1) & bytes)
+	bytes = ALIGN (bytes, (*ptr)->alignment);
+      if ((*ptr)->type == FFI_TYPE_STRUCT)
+	{
+	  if ((*ptr)->size > 8)
+	    {
+	      bytes += (*ptr)->size;
+	      bytes += sizeof (void *);
+	    }
+	  else
+	    {
+	      if ((*ptr)->size > 4)
+		bytes += 8;
+	      else
+		bytes += 4;
+	    }
+	}
+      else
+	bytes += STACK_ARG_SIZE ((*ptr)->size);
+    }
+
+  cif->bytes = bytes;
+
+  return ffi_prep_cif_machdep (cif);
+}
+
+ffi_status
+ffi_prep_cif_machdep (ffi_cif * cif)
+{
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
+			   extended_cif *,
+			   unsigned, unsigned, unsigned *, void (*fn) ())
+     __attribute__ ((__visibility__ ("hidden")));
+
+void
+ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca (cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi)
+    {
+    case FFI_SYSV:
+      ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
+		     cif->flags, ecif.rvalue, fn);
+      break;
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+}
+
+/* Because the following variables are not exported outside libffi, we
+   mark them hidden.  */
+
+/* Assembly code for the jump stub.  */
+extern const char ffi_cris_trampoline_template[]
+ __attribute__ ((__visibility__ ("hidden")));
+
+/* Offset into ffi_cris_trampoline_template of where to put the
+   ffi_prep_closure_inner function.  */
+extern const int ffi_cris_trampoline_fn_offset
+ __attribute__ ((__visibility__ ("hidden")));
+
+/* Offset into ffi_cris_trampoline_template of where to put the
+   closure data.  */
+extern const int ffi_cris_trampoline_closure_offset
+ __attribute__ ((__visibility__ ("hidden")));
+
+/* This function is sibling-called (jumped to) by the closure
+   trampoline.  We get R10..R13 at PARAMS[0..3] and a copy of [SP] at
+   PARAMS[4] to simplify handling of a straddling parameter.  A copy
+   of R9 is at PARAMS[5] and SP at PARAMS[6].  These parameters are
+   put at the appropriate place in CLOSURE which is then executed and
+   the return value is passed back to the caller.  */
+
+static unsigned long long
+ffi_prep_closure_inner (void **params, ffi_closure* closure)
+{
+  char *register_args = (char *) params;
+  void *struct_ret = params[5];
+  char *stack_args = params[6];
+  char *ptr = register_args;
+  ffi_cif *cif = closure->cif;
+  ffi_type **arg_types = cif->arg_types;
+
+  /* Max room needed is number of arguments as 64-bit values.  */
+  void **avalue = alloca (closure->cif->nargs * sizeof(void *));
+  int i;
+  int doing_regs;
+  long long llret = 0;
+
+  /* Find the address of each argument.  */
+  for (i = 0, doing_regs = 1; i < cif->nargs; i++)
+    {
+      /* Types up to and including 8 bytes go by-value.  */
+      if (arg_types[i]->size <= 4)
+	{
+	  avalue[i] = ptr;
+	  ptr += 4;
+	}
+      else if (arg_types[i]->size <= 8)
+	{
+	  avalue[i] = ptr;
+	  ptr += 8;
+	}
+      else
+	{
+	  FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
+
+	  /* Passed by-reference, so copy the pointer.  */
+	  avalue[i] = *(void **) ptr;
+	  ptr += 4;
+	}
+
+      /* If we've handled more arguments than fit in registers, start
+	 looking at the those passed on the stack.  Step over the
+	 first one if we had a straddling parameter.  */
+      if (doing_regs && ptr >= register_args + 4*4)
+	{
+	  ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
+	  doing_regs = 0;
+	}
+    }
+
+  /* Invoke the closure.  */
+  (closure->fun) (cif,
+
+		  cif->rtype->type == FFI_TYPE_STRUCT
+		  /* The caller allocated space for the return
+		     structure, and passed a pointer to this space in
+		     R9.  */
+		  ? struct_ret
+
+		  /* We take advantage of being able to ignore that
+		     the high part isn't set if the return value is
+		     not in R10:R11, but in R10 only.  */
+		  : (void *) &llret,
+
+		  avalue, closure->user_data);
+
+  return llret;
+}
+
+/* API function: Prepare the trampoline.  */
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif *, void *, void **, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  void *innerfn = ffi_prep_closure_inner;
+  FFI_ASSERT (cif->abi == FFI_SYSV);
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+  memcpy (closure->tramp, ffi_cris_trampoline_template,
+	  FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE);
+  memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
+	  &innerfn, sizeof (void *));
+  memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
+	  &codeloc, sizeof (void *));
+
+  return FFI_OK;
+}
diff --git a/third_party/gofrontend/libffi/src/cris/ffitarget.h b/third_party/gofrontend/libffi/src/cris/ffitarget.h
new file mode 100644
index 0000000..b837e97
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/cris/ffitarget.h
@@ -0,0 +1,56 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for CRIS.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE 36
+#define FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE (7*4)
+#define FFI_TRAMPOLINE_SIZE \
+ (FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE + FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE)
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/cris/sysv.S b/third_party/gofrontend/libffi/src/cris/sysv.S
new file mode 100644
index 0000000..79abaee
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/cris/sysv.S
@@ -0,0 +1,215 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2004 Simon Posnjak
+	    Copyright (c) 2005 Axis Communications AB
+
+   CRIS Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <ffi.h>
+#define CONCAT(x,y) x ## y
+#define XCONCAT(x,y) CONCAT (x, y)
+#define L(x) XCONCAT (__USER_LABEL_PREFIX__, x)
+
+	.text
+
+	;; OK, when we get called we should have this (according to
+	;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3).
+	;;
+	;; R10:	 ffi_prep_args (func. pointer)
+	;; R11:  &ecif
+	;; R12:  cif->bytes
+	;; R13:  fig->flags
+	;; sp+0: ecif.rvalue
+	;; sp+4: fn (function pointer to the function that we need to call)
+
+	.globl  L(ffi_call_SYSV)
+	.type   L(ffi_call_SYSV),@function
+	.hidden	L(ffi_call_SYSV)
+
+L(ffi_call_SYSV):
+	;; Save the regs to the stack.
+	push $srp
+	;; Used for stack pointer saving.
+	push $r6
+	;; Used for function address pointer.
+	push $r7
+	;; Used for stack pointer saving.
+	push $r8
+	;; We save fig->flags to stack we will need them after we
+	;; call The Function.
+	push $r13
+
+	;; Saving current stack pointer.
+	move.d $sp,$r8
+	move.d $sp,$r6
+
+	;; Move address of ffi_prep_args to r13.
+	move.d $r10,$r13
+
+	;; Make room on the stack for the args of fn.
+	sub.d  $r12,$sp
+
+	;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are:
+	;; 	r10 <-- stack pointer
+	;; 	r11 <-- &ecif (already there)
+	move.d $sp,$r10
+
+	;; Call the function.
+	jsr $r13
+
+	;; Save the size of the structures which are passed on stack.
+	move.d $r10,$r7
+
+	;; Move first four args in to r10..r13.
+	move.d [$sp+0],$r10
+	move.d [$sp+4],$r11
+	move.d [$sp+8],$r12
+	move.d [$sp+12],$r13
+
+	;; Adjust the stack and check if any parameters are given on stack.
+	addq 16,$sp
+	sub.d $r7,$r6
+	cmp.d $sp,$r6
+
+	bpl go_on
+	nop
+
+go_on_no_params_on_stack:
+	move.d $r6,$sp
+
+go_on:
+	;; Discover if we need to put rval address in to r9.
+	move.d [$r8+0],$r7
+	cmpq FFI_TYPE_STRUCT,$r7
+	bne call_now
+	nop
+
+	;; Move rval address to $r9.
+	move.d [$r8+20],$r9
+
+call_now:
+	;; Move address of The Function in to r7.
+	move.d [$r8+24],$r7
+
+	;; Call The Function.
+	jsr $r7
+
+	;; Reset stack.
+	move.d $r8,$sp
+
+	;; Load rval type (fig->flags) in to r13.
+	pop $r13
+
+	;; Detect rval type.
+	cmpq FFI_TYPE_VOID,$r13
+	beq epilogue
+
+	cmpq FFI_TYPE_STRUCT,$r13
+	beq epilogue
+
+	cmpq FFI_TYPE_DOUBLE,$r13
+	beq return_double_or_longlong
+
+	cmpq FFI_TYPE_UINT64,$r13
+	beq return_double_or_longlong
+
+	cmpq FFI_TYPE_SINT64,$r13
+	beq return_double_or_longlong
+	nop
+
+	;; Just return the 32 bit value.
+	ba return
+	nop
+
+return_double_or_longlong:
+	;; Load half of the rval to r10 and the other half to r11.
+	move.d [$sp+16],$r13
+	move.d $r10,[$r13]
+	addq 4,$r13
+	move.d $r11,[$r13]
+	ba epilogue
+	nop
+
+return:
+	;; Load the rval to r10.
+	move.d [$sp+16],$r13
+	move.d $r10,[$r13]
+
+epilogue:
+	pop $r8
+	pop $r7
+	pop $r6
+	Jump [$sp+]
+
+	.size   ffi_call_SYSV,.-ffi_call_SYSV
+
+/* Save R10..R13 into an array, somewhat like varargs.  Copy the next
+   argument too, to simplify handling of any straddling parameter.
+   Save R9 and SP after those.  Jump to function handling the rest.
+   Since this is a template, copied and the main function filled in by
+   the user.  */
+
+	.globl	L(ffi_cris_trampoline_template)
+	.type	L(ffi_cris_trampoline_template),@function
+	.hidden	L(ffi_cris_trampoline_template)
+
+L(ffi_cris_trampoline_template):
+0:
+	/* The value we get for "PC" is right after the prefix instruction,
+	   two bytes from the beginning, i.e. 0b+2. */
+	move.d $r10,[$pc+2f-(0b+2)]
+	move.d $pc,$r10
+1:
+	addq 2f-1b+4,$r10
+	move.d $r11,[$r10+]
+	move.d $r12,[$r10+]
+	move.d $r13,[$r10+]
+	move.d [$sp],$r11
+	move.d $r11,[$r10+]
+	move.d $r9,[$r10+]
+	move.d $sp,[$r10+]
+	subq FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE,$r10
+	move.d 0,$r11
+3:
+        jump 0
+2:
+	.size	ffi_cris_trampoline_template,.-0b
+
+/* This macro create a constant usable as "extern const int \name" in
+   C from within libffi, when \name has no prefix decoration.  */
+
+	.macro const name,value
+	.globl	\name
+	.type	\name,@object
+	.hidden	\name
+\name:
+	.dword  \value
+	.size	\name,4
+	.endm
+
+/* Constants for offsets within the trampoline.  We could do this with
+   just symbols, avoiding memory contents and memory accesses, but the
+   C usage code would look a bit stranger.  */
+
+	const L(ffi_cris_trampoline_fn_offset),2b-4-0b
+	const L(ffi_cris_trampoline_closure_offset),3b-4-0b
diff --git a/third_party/gofrontend/libffi/src/debug.c b/third_party/gofrontend/libffi/src/debug.c
new file mode 100644
index 0000000..51dcfcf
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/debug.c
@@ -0,0 +1,59 @@
+/* -----------------------------------------------------------------------
+   debug.c - Copyright (c) 1996 Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* General debugging routines */
+
+void ffi_stop_here(void)
+{
+  /* This function is only useful for debugging purposes.
+     Place a breakpoint on ffi_stop_here to be notified of
+     significant events. */
+}
+
+/* This function should only be called via the FFI_ASSERT() macro */
+
+void ffi_assert(char *expr, char *file, int line)
+{
+  fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line);
+  ffi_stop_here();
+  abort();
+}
+
+/* Perform a sanity check on an ffi_type structure */
+
+void ffi_type_test(ffi_type *a, char *file, int line)
+{
+  FFI_ASSERT_AT(a != NULL, file, line);
+
+  FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
+  FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
+  FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
+  FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
+
+}
diff --git a/third_party/gofrontend/libffi/src/dlmalloc.c b/third_party/gofrontend/libffi/src/dlmalloc.c
new file mode 100644
index 0000000..5c9f9c2
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/dlmalloc.c
@@ -0,0 +1,5161 @@
+/*
+  This is a version (aka dlmalloc) of malloc/free/realloc written by
+  Doug Lea and released to the public domain, as explained at
+  http://creativecommons.org/licenses/publicdomain.  Send questions,
+  comments, complaints, performance data, etc to dl@cs.oswego.edu
+
+* Version 2.8.3 Thu Sep 22 11:16:15 2005  Doug Lea  (dl at gee)
+
+   Note: There may be an updated version of this malloc obtainable at
+           ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+         Check before installing!
+
+* Quickstart
+
+  This library is all in one file to simplify the most common usage:
+  ftp it, compile it (-O3), and link it into another program. All of
+  the compile-time options default to reasonable values for use on
+  most platforms.  You might later want to step through various
+  compile-time and dynamic tuning options.
+
+  For convenience, an include file for code using this malloc is at:
+     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h
+  You don't really need this .h file unless you call functions not
+  defined in your system include files.  The .h file contains only the
+  excerpts from this file needed for using this malloc on ANSI C/C++
+  systems, so long as you haven't changed compile-time options about
+  naming and tuning parameters.  If you do, then you can create your
+  own malloc.h that does include all settings by cutting at the point
+  indicated below. Note that you may already by default be using a C
+  library containing a malloc that is based on some version of this
+  malloc (for example in linux). You might still want to use the one
+  in this file to customize settings or to avoid overheads associated
+  with library versions.
+
+* Vital statistics:
+
+  Supported pointer/size_t representation:       4 or 8 bytes
+       size_t MUST be an unsigned type of the same width as
+       pointers. (If you are using an ancient system that declares
+       size_t as a signed type, or need it to be a different width
+       than pointers, you can use a previous release of this malloc
+       (e.g. 2.7.2) supporting these.)
+
+  Alignment:                                     8 bytes (default)
+       This suffices for nearly all current machines and C compilers.
+       However, you can define MALLOC_ALIGNMENT to be wider than this
+       if necessary (up to 128bytes), at the expense of using more space.
+
+  Minimum overhead per allocated chunk:   4 or  8 bytes (if 4byte sizes)
+                                          8 or 16 bytes (if 8byte sizes)
+       Each malloced chunk has a hidden word of overhead holding size
+       and status information, and additional cross-check word
+       if FOOTERS is defined.
+
+  Minimum allocated size: 4-byte ptrs:  16 bytes    (including overhead)
+                          8-byte ptrs:  32 bytes    (including overhead)
+
+       Even a request for zero bytes (i.e., malloc(0)) returns a
+       pointer to something of the minimum allocatable size.
+       The maximum overhead wastage (i.e., number of extra bytes
+       allocated than were requested in malloc) is less than or equal
+       to the minimum size, except for requests >= mmap_threshold that
+       are serviced via mmap(), where the worst case wastage is about
+       32 bytes plus the remainder from a system page (the minimal
+       mmap unit); typically 4096 or 8192 bytes.
+
+  Security: static-safe; optionally more or less
+       The "security" of malloc refers to the ability of malicious
+       code to accentuate the effects of errors (for example, freeing
+       space that is not currently malloc'ed or overwriting past the
+       ends of chunks) in code that calls malloc.  This malloc
+       guarantees not to modify any memory locations below the base of
+       heap, i.e., static variables, even in the presence of usage
+       errors.  The routines additionally detect most improper frees
+       and reallocs.  All this holds as long as the static bookkeeping
+       for malloc itself is not corrupted by some other means.  This
+       is only one aspect of security -- these checks do not, and
+       cannot, detect all possible programming errors.
+
+       If FOOTERS is defined nonzero, then each allocated chunk
+       carries an additional check word to verify that it was malloced
+       from its space.  These check words are the same within each
+       execution of a program using malloc, but differ across
+       executions, so externally crafted fake chunks cannot be
+       freed. This improves security by rejecting frees/reallocs that
+       could corrupt heap memory, in addition to the checks preventing
+       writes to statics that are always on.  This may further improve
+       security at the expense of time and space overhead.  (Note that
+       FOOTERS may also be worth using with MSPACES.)
+
+       By default detected errors cause the program to abort (calling
+       "abort()"). You can override this to instead proceed past
+       errors by defining PROCEED_ON_ERROR.  In this case, a bad free
+       has no effect, and a malloc that encounters a bad address
+       caused by user overwrites will ignore the bad address by
+       dropping pointers and indices to all known memory. This may
+       be appropriate for programs that should continue if at all
+       possible in the face of programming errors, although they may
+       run out of memory because dropped memory is never reclaimed.
+
+       If you don't like either of these options, you can define
+       CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
+       else. And if if you are sure that your program using malloc has
+       no errors or vulnerabilities, you can define INSECURE to 1,
+       which might (or might not) provide a small performance improvement.
+
+  Thread-safety: NOT thread-safe unless USE_LOCKS defined
+       When USE_LOCKS is defined, each public call to malloc, free,
+       etc is surrounded with either a pthread mutex or a win32
+       spinlock (depending on WIN32). This is not especially fast, and
+       can be a major bottleneck.  It is designed only to provide
+       minimal protection in concurrent environments, and to provide a
+       basis for extensions.  If you are using malloc in a concurrent
+       program, consider instead using ptmalloc, which is derived from
+       a version of this malloc. (See http://www.malloc.de).
+
+  System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
+       This malloc can use unix sbrk or any emulation (invoked using
+       the CALL_MORECORE macro) and/or mmap/munmap or any emulation
+       (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
+       memory.  On most unix systems, it tends to work best if both
+       MORECORE and MMAP are enabled.  On Win32, it uses emulations
+       based on VirtualAlloc. It also uses common C library functions
+       like memset.
+
+  Compliance: I believe it is compliant with the Single Unix Specification
+       (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
+       others as well.
+
+* Overview of algorithms
+
+  This is not the fastest, most space-conserving, most portable, or
+  most tunable malloc ever written. However it is among the fastest
+  while also being among the most space-conserving, portable and
+  tunable.  Consistent balance across these factors results in a good
+  general-purpose allocator for malloc-intensive programs.
+
+  In most ways, this malloc is a best-fit allocator. Generally, it
+  chooses the best-fitting existing chunk for a request, with ties
+  broken in approximately least-recently-used order. (This strategy
+  normally maintains low fragmentation.) However, for requests less
+  than 256bytes, it deviates from best-fit when there is not an
+  exactly fitting available chunk by preferring to use space adjacent
+  to that used for the previous small request, as well as by breaking
+  ties in approximately most-recently-used order. (These enhance
+  locality of series of small allocations.)  And for very large requests
+  (>= 256Kb by default), it relies on system memory mapping
+  facilities, if supported.  (This helps avoid carrying around and
+  possibly fragmenting memory used only for large chunks.)
+
+  All operations (except malloc_stats and mallinfo) have execution
+  times that are bounded by a constant factor of the number of bits in
+  a size_t, not counting any clearing in calloc or copying in realloc,
+  or actions surrounding MORECORE and MMAP that have times
+  proportional to the number of non-contiguous regions returned by
+  system allocation routines, which is often just 1.
+
+  The implementation is not very modular and seriously overuses
+  macros. Perhaps someday all C compilers will do as good a job
+  inlining modular code as can now be done by brute-force expansion,
+  but now, enough of them seem not to.
+
+  Some compilers issue a lot of warnings about code that is
+  dead/unreachable only on some platforms, and also about intentional
+  uses of negation on unsigned types. All known cases of each can be
+  ignored.
+
+  For a longer but out of date high-level description, see
+     http://gee.cs.oswego.edu/dl/html/malloc.html
+
+* MSPACES
+  If MSPACES is defined, then in addition to malloc, free, etc.,
+  this file also defines mspace_malloc, mspace_free, etc. These
+  are versions of malloc routines that take an "mspace" argument
+  obtained using create_mspace, to control all internal bookkeeping.
+  If ONLY_MSPACES is defined, only these versions are compiled.
+  So if you would like to use this allocator for only some allocations,
+  and your system malloc for others, you can compile with
+  ONLY_MSPACES and then do something like...
+    static mspace mymspace = create_mspace(0,0); // for example
+    #define mymalloc(bytes)  mspace_malloc(mymspace, bytes)
+
+  (Note: If you only need one instance of an mspace, you can instead
+  use "USE_DL_PREFIX" to relabel the global malloc.)
+
+  You can similarly create thread-local allocators by storing
+  mspaces as thread-locals. For example:
+    static __thread mspace tlms = 0;
+    void*  tlmalloc(size_t bytes) {
+      if (tlms == 0) tlms = create_mspace(0, 0);
+      return mspace_malloc(tlms, bytes);
+    }
+    void  tlfree(void* mem) { mspace_free(tlms, mem); }
+
+  Unless FOOTERS is defined, each mspace is completely independent.
+  You cannot allocate from one and free to another (although
+  conformance is only weakly checked, so usage errors are not always
+  caught). If FOOTERS is defined, then each chunk carries around a tag
+  indicating its originating mspace, and frees are directed to their
+  originating spaces.
+
+ -------------------------  Compile-time options ---------------------------
+
+Be careful in setting #define values for numerical constants of type
+size_t. On some systems, literal values are not automatically extended
+to size_t precision unless they are explicitly casted.
+
+WIN32                    default: defined if _WIN32 defined
+  Defining WIN32 sets up defaults for MS environment and compilers.
+  Otherwise defaults are for unix.
+
+MALLOC_ALIGNMENT         default: (size_t)8
+  Controls the minimum alignment for malloc'ed chunks.  It must be a
+  power of two and at least 8, even on machines for which smaller
+  alignments would suffice. It may be defined as larger than this
+  though. Note however that code and data structures are optimized for
+  the case of 8-byte alignment.
+
+MSPACES                  default: 0 (false)
+  If true, compile in support for independent allocation spaces.
+  This is only supported if HAVE_MMAP is true.
+
+ONLY_MSPACES             default: 0 (false)
+  If true, only compile in mspace versions, not regular versions.
+
+USE_LOCKS                default: 0 (false)
+  Causes each call to each public routine to be surrounded with
+  pthread or WIN32 mutex lock/unlock. (If set true, this can be
+  overridden on a per-mspace basis for mspace versions.)
+
+FOOTERS                  default: 0
+  If true, provide extra checking and dispatching by placing
+  information in the footers of allocated chunks. This adds
+  space and time overhead.
+
+INSECURE                 default: 0
+  If true, omit checks for usage errors and heap space overwrites.
+
+USE_DL_PREFIX            default: NOT defined
+  Causes compiler to prefix all public routines with the string 'dl'.
+  This can be useful when you only want to use this malloc in one part
+  of a program, using your regular system malloc elsewhere.
+
+ABORT                    default: defined as abort()
+  Defines how to abort on failed checks.  On most systems, a failed
+  check cannot die with an "assert" or even print an informative
+  message, because the underlying print routines in turn call malloc,
+  which will fail again.  Generally, the best policy is to simply call
+  abort(). It's not very useful to do more than this because many
+  errors due to overwriting will show up as address faults (null, odd
+  addresses etc) rather than malloc-triggered checks, so will also
+  abort.  Also, most compilers know that abort() does not return, so
+  can better optimize code conditionally calling it.
+
+PROCEED_ON_ERROR           default: defined as 0 (false)
+  Controls whether detected bad addresses cause them to bypassed
+  rather than aborting. If set, detected bad arguments to free and
+  realloc are ignored. And all bookkeeping information is zeroed out
+  upon a detected overwrite of freed heap space, thus losing the
+  ability to ever return it from malloc again, but enabling the
+  application to proceed. If PROCEED_ON_ERROR is defined, the
+  static variable malloc_corruption_error_count is compiled in
+  and can be examined to see if errors have occurred. This option
+  generates slower code than the default abort policy.
+
+DEBUG                    default: NOT defined
+  The DEBUG setting is mainly intended for people trying to modify
+  this code or diagnose problems when porting to new platforms.
+  However, it may also be able to better isolate user errors than just
+  using runtime checks.  The assertions in the check routines spell
+  out in more detail the assumptions and invariants underlying the
+  algorithms.  The checking is fairly extensive, and will slow down
+  execution noticeably. Calling malloc_stats or mallinfo with DEBUG
+  set will attempt to check every non-mmapped allocated and free chunk
+  in the course of computing the summaries.
+
+ABORT_ON_ASSERT_FAILURE   default: defined as 1 (true)
+  Debugging assertion failures can be nearly impossible if your
+  version of the assert macro causes malloc to be called, which will
+  lead to a cascade of further failures, blowing the runtime stack.
+  ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
+  which will usually make debugging easier.
+
+MALLOC_FAILURE_ACTION     default: sets errno to ENOMEM, or no-op on win32
+  The action to take before "return 0" when malloc fails to be able to
+  return memory because there is none available.
+
+HAVE_MORECORE             default: 1 (true) unless win32 or ONLY_MSPACES
+  True if this system supports sbrk or an emulation of it.
+
+MORECORE                  default: sbrk
+  The name of the sbrk-style system routine to call to obtain more
+  memory.  See below for guidance on writing custom MORECORE
+  functions. The type of the argument to sbrk/MORECORE varies across
+  systems.  It cannot be size_t, because it supports negative
+  arguments, so it is normally the signed type of the same width as
+  size_t (sometimes declared as "intptr_t").  It doesn't much matter
+  though. Internally, we only call it with arguments less than half
+  the max value of a size_t, which should work across all reasonable
+  possibilities, although sometimes generating compiler warnings.  See
+  near the end of this file for guidelines for creating a custom
+  version of MORECORE.
+
+MORECORE_CONTIGUOUS       default: 1 (true)
+  If true, take advantage of fact that consecutive calls to MORECORE
+  with positive arguments always return contiguous increasing
+  addresses.  This is true of unix sbrk. It does not hurt too much to
+  set it true anyway, since malloc copes with non-contiguities.
+  Setting it false when definitely non-contiguous saves time
+  and possibly wasted space it would take to discover this though.
+
+MORECORE_CANNOT_TRIM      default: NOT defined
+  True if MORECORE cannot release space back to the system when given
+  negative arguments. This is generally necessary only if you are
+  using a hand-crafted MORECORE function that cannot handle negative
+  arguments.
+
+HAVE_MMAP                 default: 1 (true)
+  True if this system supports mmap or an emulation of it.  If so, and
+  HAVE_MORECORE is not true, MMAP is used for all system
+  allocation. If set and HAVE_MORECORE is true as well, MMAP is
+  primarily used to directly allocate very large blocks. It is also
+  used as a backup strategy in cases where MORECORE fails to provide
+  space from system. Note: A single call to MUNMAP is assumed to be
+  able to unmap memory that may have be allocated using multiple calls
+  to MMAP, so long as they are adjacent.
+
+HAVE_MREMAP               default: 1 on linux, else 0
+  If true realloc() uses mremap() to re-allocate large blocks and
+  extend or shrink allocation spaces.
+
+MMAP_CLEARS               default: 1 on unix
+  True if mmap clears memory so calloc doesn't need to. This is true
+  for standard unix mmap using /dev/zero.
+
+USE_BUILTIN_FFS            default: 0 (i.e., not used)
+  Causes malloc to use the builtin ffs() function to compute indices.
+  Some compilers may recognize and intrinsify ffs to be faster than the
+  supplied C version. Also, the case of x86 using gcc is special-cased
+  to an asm instruction, so is already as fast as it can be, and so
+  this setting has no effect. (On most x86s, the asm version is only
+  slightly faster than the C version.)
+
+malloc_getpagesize         default: derive from system includes, or 4096.
+  The system page size. To the extent possible, this malloc manages
+  memory from the system in page-size units.  This may be (and
+  usually is) a function rather than a constant. This is ignored
+  if WIN32, where page size is determined using getSystemInfo during
+  initialization.
+
+USE_DEV_RANDOM             default: 0 (i.e., not used)
+  Causes malloc to use /dev/random to initialize secure magic seed for
+  stamping footers. Otherwise, the current time is used.
+
+NO_MALLINFO                default: 0
+  If defined, don't compile "mallinfo". This can be a simple way
+  of dealing with mismatches between system declarations and
+  those in this file.
+
+MALLINFO_FIELD_TYPE        default: size_t
+  The type of the fields in the mallinfo struct. This was originally
+  defined as "int" in SVID etc, but is more usefully defined as
+  size_t. The value is used only if  HAVE_USR_INCLUDE_MALLOC_H is not set
+
+REALLOC_ZERO_BYTES_FREES    default: not defined
+  This should be set if a call to realloc with zero bytes should 
+  be the same as a call to free. Some people think it should. Otherwise, 
+  since this malloc returns a unique pointer for malloc(0), so does 
+  realloc(p, 0).
+
+LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
+LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H,  LACKS_ERRNO_H
+LACKS_STDLIB_H                default: NOT defined unless on WIN32
+  Define these if your system does not have these header files.
+  You might need to manually insert some of the declarations they provide.
+
+DEFAULT_GRANULARITY        default: page size if MORECORE_CONTIGUOUS,
+                                system_info.dwAllocationGranularity in WIN32,
+                                otherwise 64K.
+      Also settable using mallopt(M_GRANULARITY, x)
+  The unit for allocating and deallocating memory from the system.  On
+  most systems with contiguous MORECORE, there is no reason to
+  make this more than a page. However, systems with MMAP tend to
+  either require or encourage larger granularities.  You can increase
+  this value to prevent system allocation functions to be called so
+  often, especially if they are slow.  The value must be at least one
+  page and must be a power of two.  Setting to 0 causes initialization
+  to either page size or win32 region size.  (Note: In previous
+  versions of malloc, the equivalent of this option was called
+  "TOP_PAD")
+
+DEFAULT_TRIM_THRESHOLD    default: 2MB
+      Also settable using mallopt(M_TRIM_THRESHOLD, x)
+  The maximum amount of unused top-most memory to keep before
+  releasing via malloc_trim in free().  Automatic trimming is mainly
+  useful in long-lived programs using contiguous MORECORE.  Because
+  trimming via sbrk can be slow on some systems, and can sometimes be
+  wasteful (in cases where programs immediately afterward allocate
+  more large chunks) the value should be high enough so that your
+  overall system performance would improve by releasing this much
+  memory.  As a rough guide, you might set to a value close to the
+  average size of a process (program) running on your system.
+  Releasing this much memory would allow such a process to run in
+  memory.  Generally, it is worth tuning trim thresholds when a
+  program undergoes phases where several large chunks are allocated
+  and released in ways that can reuse each other's storage, perhaps
+  mixed with phases where there are no such chunks at all. The trim
+  value must be greater than page size to have any useful effect.  To
+  disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
+  some people use of mallocing a huge space and then freeing it at
+  program startup, in an attempt to reserve system memory, doesn't
+  have the intended effect under automatic trimming, since that memory
+  will immediately be returned to the system.
+
+DEFAULT_MMAP_THRESHOLD       default: 256K
+      Also settable using mallopt(M_MMAP_THRESHOLD, x)
+  The request size threshold for using MMAP to directly service a
+  request. Requests of at least this size that cannot be allocated
+  using already-existing space will be serviced via mmap.  (If enough
+  normal freed space already exists it is used instead.)  Using mmap
+  segregates relatively large chunks of memory so that they can be
+  individually obtained and released from the host system. A request
+  serviced through mmap is never reused by any other request (at least
+  not directly; the system may just so happen to remap successive
+  requests to the same locations).  Segregating space in this way has
+  the benefits that: Mmapped space can always be individually released
+  back to the system, which helps keep the system level memory demands
+  of a long-lived program low.  Also, mapped memory doesn't become
+  `locked' between other chunks, as can happen with normally allocated
+  chunks, which means that even trimming via malloc_trim would not
+  release them.  However, it has the disadvantage that the space
+  cannot be reclaimed, consolidated, and then used to service later
+  requests, as happens with normal chunks.  The advantages of mmap
+  nearly always outweigh disadvantages for "large" chunks, but the
+  value of "large" may vary across systems.  The default is an
+  empirically derived value that works well in most systems. You can
+  disable mmap by setting to MAX_SIZE_T.
+
+*/
+
+#ifndef WIN32
+#ifdef _WIN32
+#define WIN32 1
+#endif  /* _WIN32 */
+#endif  /* WIN32 */
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#define HAVE_MMAP 1
+#define HAVE_MORECORE 0
+#define LACKS_UNISTD_H
+#define LACKS_SYS_PARAM_H
+#define LACKS_SYS_MMAN_H
+#define LACKS_STRING_H
+#define LACKS_STRINGS_H
+#define LACKS_SYS_TYPES_H
+#define LACKS_ERRNO_H
+#define MALLOC_FAILURE_ACTION
+#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */
+#endif  /* WIN32 */
+
+#ifdef __OS2__
+#define INCL_DOS
+#include <os2.h>
+#define HAVE_MMAP 1
+#define HAVE_MORECORE 0
+#define LACKS_SYS_MMAN_H
+#endif  /* __OS2__ */
+
+#if defined(DARWIN) || defined(_DARWIN)
+/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
+#ifndef HAVE_MORECORE
+#define HAVE_MORECORE 0
+#define HAVE_MMAP 1
+#endif  /* HAVE_MORECORE */
+#endif  /* DARWIN */
+
+#ifndef LACKS_SYS_TYPES_H
+#include <sys/types.h>  /* For size_t */
+#endif  /* LACKS_SYS_TYPES_H */
+
+/* The maximum possible size_t value has all bits set */
+#define MAX_SIZE_T           (~(size_t)0)
+
+#ifndef ONLY_MSPACES
+#define ONLY_MSPACES 0
+#endif  /* ONLY_MSPACES */
+#ifndef MSPACES
+#if ONLY_MSPACES
+#define MSPACES 1
+#else   /* ONLY_MSPACES */
+#define MSPACES 0
+#endif  /* ONLY_MSPACES */
+#endif  /* MSPACES */
+#ifndef MALLOC_ALIGNMENT
+#define MALLOC_ALIGNMENT ((size_t)8U)
+#endif  /* MALLOC_ALIGNMENT */
+#ifndef FOOTERS
+#define FOOTERS 0
+#endif  /* FOOTERS */
+#ifndef ABORT
+#define ABORT  abort()
+#endif  /* ABORT */
+#ifndef ABORT_ON_ASSERT_FAILURE
+#define ABORT_ON_ASSERT_FAILURE 1
+#endif  /* ABORT_ON_ASSERT_FAILURE */
+#ifndef PROCEED_ON_ERROR
+#define PROCEED_ON_ERROR 0
+#endif  /* PROCEED_ON_ERROR */
+#ifndef USE_LOCKS
+#define USE_LOCKS 0
+#endif  /* USE_LOCKS */
+#ifndef INSECURE
+#define INSECURE 0
+#endif  /* INSECURE */
+#ifndef HAVE_MMAP
+#define HAVE_MMAP 1
+#endif  /* HAVE_MMAP */
+#ifndef MMAP_CLEARS
+#define MMAP_CLEARS 1
+#endif  /* MMAP_CLEARS */
+#ifndef HAVE_MREMAP
+#ifdef linux
+#define HAVE_MREMAP 1
+#else   /* linux */
+#define HAVE_MREMAP 0
+#endif  /* linux */
+#endif  /* HAVE_MREMAP */
+#ifndef MALLOC_FAILURE_ACTION
+#define MALLOC_FAILURE_ACTION  errno = ENOMEM;
+#endif  /* MALLOC_FAILURE_ACTION */
+#ifndef HAVE_MORECORE
+#if ONLY_MSPACES
+#define HAVE_MORECORE 0
+#else   /* ONLY_MSPACES */
+#define HAVE_MORECORE 1
+#endif  /* ONLY_MSPACES */
+#endif  /* HAVE_MORECORE */
+#if !HAVE_MORECORE
+#define MORECORE_CONTIGUOUS 0
+#else   /* !HAVE_MORECORE */
+#ifndef MORECORE
+#define MORECORE sbrk
+#endif  /* MORECORE */
+#ifndef MORECORE_CONTIGUOUS
+#define MORECORE_CONTIGUOUS 1
+#endif  /* MORECORE_CONTIGUOUS */
+#endif  /* HAVE_MORECORE */
+#ifndef DEFAULT_GRANULARITY
+#if MORECORE_CONTIGUOUS
+#define DEFAULT_GRANULARITY (0)  /* 0 means to compute in init_mparams */
+#else   /* MORECORE_CONTIGUOUS */
+#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
+#endif  /* MORECORE_CONTIGUOUS */
+#endif  /* DEFAULT_GRANULARITY */
+#ifndef DEFAULT_TRIM_THRESHOLD
+#ifndef MORECORE_CANNOT_TRIM
+#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
+#else   /* MORECORE_CANNOT_TRIM */
+#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
+#endif  /* MORECORE_CANNOT_TRIM */
+#endif  /* DEFAULT_TRIM_THRESHOLD */
+#ifndef DEFAULT_MMAP_THRESHOLD
+#if HAVE_MMAP
+#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
+#else   /* HAVE_MMAP */
+#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
+#endif  /* HAVE_MMAP */
+#endif  /* DEFAULT_MMAP_THRESHOLD */
+#ifndef USE_BUILTIN_FFS
+#define USE_BUILTIN_FFS 0
+#endif  /* USE_BUILTIN_FFS */
+#ifndef USE_DEV_RANDOM
+#define USE_DEV_RANDOM 0
+#endif  /* USE_DEV_RANDOM */
+#ifndef NO_MALLINFO
+#define NO_MALLINFO 0
+#endif  /* NO_MALLINFO */
+#ifndef MALLINFO_FIELD_TYPE
+#define MALLINFO_FIELD_TYPE size_t
+#endif  /* MALLINFO_FIELD_TYPE */
+
+/*
+  mallopt tuning options.  SVID/XPG defines four standard parameter
+  numbers for mallopt, normally defined in malloc.h.  None of these
+  are used in this malloc, so setting them has no effect. But this
+  malloc does support the following options.
+*/
+
+#define M_TRIM_THRESHOLD     (-1)
+#define M_GRANULARITY        (-2)
+#define M_MMAP_THRESHOLD     (-3)
+
+/* ------------------------ Mallinfo declarations ------------------------ */
+
+#if !NO_MALLINFO
+/*
+  This version of malloc supports the standard SVID/XPG mallinfo
+  routine that returns a struct containing usage properties and
+  statistics. It should work on any system that has a
+  /usr/include/malloc.h defining struct mallinfo.  The main
+  declaration needed is the mallinfo struct that is returned (by-copy)
+  by mallinfo().  The malloinfo struct contains a bunch of fields that
+  are not even meaningful in this version of malloc.  These fields are
+  are instead filled by mallinfo() with other numbers that might be of
+  interest.
+
+  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
+  /usr/include/malloc.h file that includes a declaration of struct
+  mallinfo.  If so, it is included; else a compliant version is
+  declared below.  These must be precisely the same for mallinfo() to
+  work.  The original SVID version of this struct, defined on most
+  systems with mallinfo, declares all fields as ints. But some others
+  define as unsigned long. If your system defines the fields using a
+  type of different width than listed here, you MUST #include your
+  system version and #define HAVE_USR_INCLUDE_MALLOC_H.
+*/
+
+/* #define HAVE_USR_INCLUDE_MALLOC_H */
+
+#ifdef HAVE_USR_INCLUDE_MALLOC_H
+#include "/usr/include/malloc.h"
+#else /* HAVE_USR_INCLUDE_MALLOC_H */
+
+/* HP-UX's stdlib.h redefines mallinfo unless _STRUCT_MALLINFO is defined */
+#define _STRUCT_MALLINFO
+
+struct mallinfo {
+  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system */
+  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */
+  MALLINFO_FIELD_TYPE smblks;   /* always 0 */
+  MALLINFO_FIELD_TYPE hblks;    /* always 0 */
+  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */
+  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */
+  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */
+  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
+  MALLINFO_FIELD_TYPE fordblks; /* total free space */
+  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
+};
+
+#endif /* HAVE_USR_INCLUDE_MALLOC_H */
+#endif /* NO_MALLINFO */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if !ONLY_MSPACES
+
+/* ------------------- Declarations of public routines ------------------- */
+
+#ifndef USE_DL_PREFIX
+#define dlcalloc               calloc
+#define dlfree                 free
+#define dlmalloc               malloc
+#define dlmemalign             memalign
+#define dlrealloc              realloc
+#define dlvalloc               valloc
+#define dlpvalloc              pvalloc
+#define dlmallinfo             mallinfo
+#define dlmallopt              mallopt
+#define dlmalloc_trim          malloc_trim
+#define dlmalloc_stats         malloc_stats
+#define dlmalloc_usable_size   malloc_usable_size
+#define dlmalloc_footprint     malloc_footprint
+#define dlmalloc_max_footprint malloc_max_footprint
+#define dlindependent_calloc   independent_calloc
+#define dlindependent_comalloc independent_comalloc
+#endif /* USE_DL_PREFIX */
+
+
+/*
+  malloc(size_t n)
+  Returns a pointer to a newly allocated chunk of at least n bytes, or
+  null if no space is available, in which case errno is set to ENOMEM
+  on ANSI C systems.
+
+  If n is zero, malloc returns a minimum-sized chunk. (The minimum
+  size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
+  systems.)  Note that size_t is an unsigned type, so calls with
+  arguments that would be negative if signed are interpreted as
+  requests for huge amounts of space, which will often fail. The
+  maximum supported value of n differs across systems, but is in all
+  cases less than the maximum representable value of a size_t.
+*/
+void* dlmalloc(size_t);
+
+/*
+  free(void* p)
+  Releases the chunk of memory pointed to by p, that had been previously
+  allocated using malloc or a related routine such as realloc.
+  It has no effect if p is null. If p was not malloced or already
+  freed, free(p) will by default cause the current program to abort.
+*/
+void  dlfree(void*);
+
+/*
+  calloc(size_t n_elements, size_t element_size);
+  Returns a pointer to n_elements * element_size bytes, with all locations
+  set to zero.
+*/
+void* dlcalloc(size_t, size_t);
+
+/*
+  realloc(void* p, size_t n)
+  Returns a pointer to a chunk of size n that contains the same data
+  as does chunk p up to the minimum of (n, p's size) bytes, or null
+  if no space is available.
+
+  The returned pointer may or may not be the same as p. The algorithm
+  prefers extending p in most cases when possible, otherwise it
+  employs the equivalent of a malloc-copy-free sequence.
+
+  If p is null, realloc is equivalent to malloc.
+
+  If space is not available, realloc returns null, errno is set (if on
+  ANSI) and p is NOT freed.
+
+  if n is for fewer bytes than already held by p, the newly unused
+  space is lopped off and freed if possible.  realloc with a size
+  argument of zero (re)allocates a minimum-sized chunk.
+
+  The old unix realloc convention of allowing the last-free'd chunk
+  to be used as an argument to realloc is not supported.
+*/
+
+void* dlrealloc(void*, size_t);
+
+/*
+  memalign(size_t alignment, size_t n);
+  Returns a pointer to a newly allocated chunk of n bytes, aligned
+  in accord with the alignment argument.
+
+  The alignment argument should be a power of two. If the argument is
+  not a power of two, the nearest greater power is used.
+  8-byte alignment is guaranteed by normal malloc calls, so don't
+  bother calling memalign with an argument of 8 or less.
+
+  Overreliance on memalign is a sure way to fragment space.
+*/
+void* dlmemalign(size_t, size_t);
+
+/*
+  valloc(size_t n);
+  Equivalent to memalign(pagesize, n), where pagesize is the page
+  size of the system. If the pagesize is unknown, 4096 is used.
+*/
+void* dlvalloc(size_t);
+
+/*
+  mallopt(int parameter_number, int parameter_value)
+  Sets tunable parameters The format is to provide a
+  (parameter-number, parameter-value) pair.  mallopt then sets the
+  corresponding parameter to the argument value if it can (i.e., so
+  long as the value is meaningful), and returns 1 if successful else
+  0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,
+  normally defined in malloc.h.  None of these are use in this malloc,
+  so setting them has no effect. But this malloc also supports other
+  options in mallopt. See below for details.  Briefly, supported
+  parameters are as follows (listed defaults are for "typical"
+  configurations).
+
+  Symbol            param #  default    allowed param values
+  M_TRIM_THRESHOLD     -1   2*1024*1024   any   (MAX_SIZE_T disables)
+  M_GRANULARITY        -2     page size   any power of 2 >= page size
+  M_MMAP_THRESHOLD     -3      256*1024   any   (or 0 if no MMAP support)
+*/
+int dlmallopt(int, int);
+
+/*
+  malloc_footprint();
+  Returns the number of bytes obtained from the system.  The total
+  number of bytes allocated by malloc, realloc etc., is less than this
+  value. Unlike mallinfo, this function returns only a precomputed
+  result, so can be called frequently to monitor memory consumption.
+  Even if locks are otherwise defined, this function does not use them,
+  so results might not be up to date.
+*/
+size_t dlmalloc_footprint(void);
+
+/*
+  malloc_max_footprint();
+  Returns the maximum number of bytes obtained from the system. This
+  value will be greater than current footprint if deallocated space
+  has been reclaimed by the system. The peak number of bytes allocated
+  by malloc, realloc etc., is less than this value. Unlike mallinfo,
+  this function returns only a precomputed result, so can be called
+  frequently to monitor memory consumption.  Even if locks are
+  otherwise defined, this function does not use them, so results might
+  not be up to date.
+*/
+size_t dlmalloc_max_footprint(void);
+
+#if !NO_MALLINFO
+/*
+  mallinfo()
+  Returns (by copy) a struct containing various summary statistics:
+
+  arena:     current total non-mmapped bytes allocated from system
+  ordblks:   the number of free chunks
+  smblks:    always zero.
+  hblks:     current number of mmapped regions
+  hblkhd:    total bytes held in mmapped regions
+  usmblks:   the maximum total allocated space. This will be greater
+                than current total if trimming has occurred.
+  fsmblks:   always zero
+  uordblks:  current total allocated space (normal or mmapped)
+  fordblks:  total free space
+  keepcost:  the maximum number of bytes that could ideally be released
+               back to system via malloc_trim. ("ideally" means that
+               it ignores page restrictions etc.)
+
+  Because these fields are ints, but internal bookkeeping may
+  be kept as longs, the reported values may wrap around zero and
+  thus be inaccurate.
+*/
+struct mallinfo dlmallinfo(void);
+#endif /* NO_MALLINFO */
+
+/*
+  independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
+
+  independent_calloc is similar to calloc, but instead of returning a
+  single cleared space, it returns an array of pointers to n_elements
+  independent elements that can hold contents of size elem_size, each
+  of which starts out cleared, and can be independently freed,
+  realloc'ed etc. The elements are guaranteed to be adjacently
+  allocated (this is not guaranteed to occur with multiple callocs or
+  mallocs), which may also improve cache locality in some
+  applications.
+
+  The "chunks" argument is optional (i.e., may be null, which is
+  probably the most typical usage). If it is null, the returned array
+  is itself dynamically allocated and should also be freed when it is
+  no longer needed. Otherwise, the chunks array must be of at least
+  n_elements in length. It is filled in with the pointers to the
+  chunks.
+
+  In either case, independent_calloc returns this pointer array, or
+  null if the allocation failed.  If n_elements is zero and "chunks"
+  is null, it returns a chunk representing an array with zero elements
+  (which should be freed if not wanted).
+
+  Each element must be individually freed when it is no longer
+  needed. If you'd like to instead be able to free all at once, you
+  should instead use regular calloc and assign pointers into this
+  space to represent elements.  (In this case though, you cannot
+  independently free elements.)
+
+  independent_calloc simplifies and speeds up implementations of many
+  kinds of pools.  It may also be useful when constructing large data
+  structures that initially have a fixed number of fixed-sized nodes,
+  but the number is not known at compile time, and some of the nodes
+  may later need to be freed. For example:
+
+  struct Node { int item; struct Node* next; };
+
+  struct Node* build_list() {
+    struct Node** pool;
+    int n = read_number_of_nodes_needed();
+    if (n <= 0) return 0;
+    pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
+    if (pool == 0) die();
+    // organize into a linked list...
+    struct Node* first = pool[0];
+    for (i = 0; i < n-1; ++i)
+      pool[i]->next = pool[i+1];
+    free(pool);     // Can now free the array (or not, if it is needed later)
+    return first;
+  }
+*/
+void** dlindependent_calloc(size_t, size_t, void**);
+
+/*
+  independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
+
+  independent_comalloc allocates, all at once, a set of n_elements
+  chunks with sizes indicated in the "sizes" array.    It returns
+  an array of pointers to these elements, each of which can be
+  independently freed, realloc'ed etc. The elements are guaranteed to
+  be adjacently allocated (this is not guaranteed to occur with
+  multiple callocs or mallocs), which may also improve cache locality
+  in some applications.
+
+  The "chunks" argument is optional (i.e., may be null). If it is null
+  the returned array is itself dynamically allocated and should also
+  be freed when it is no longer needed. Otherwise, the chunks array
+  must be of at least n_elements in length. It is filled in with the
+  pointers to the chunks.
+
+  In either case, independent_comalloc returns this pointer array, or
+  null if the allocation failed.  If n_elements is zero and chunks is
+  null, it returns a chunk representing an array with zero elements
+  (which should be freed if not wanted).
+
+  Each element must be individually freed when it is no longer
+  needed. If you'd like to instead be able to free all at once, you
+  should instead use a single regular malloc, and assign pointers at
+  particular offsets in the aggregate space. (In this case though, you
+  cannot independently free elements.)
+
+  independent_comallac differs from independent_calloc in that each
+  element may have a different size, and also that it does not
+  automatically clear elements.
+
+  independent_comalloc can be used to speed up allocation in cases
+  where several structs or objects must always be allocated at the
+  same time.  For example:
+
+  struct Head { ... }
+  struct Foot { ... }
+
+  void send_message(char* msg) {
+    int msglen = strlen(msg);
+    size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
+    void* chunks[3];
+    if (independent_comalloc(3, sizes, chunks) == 0)
+      die();
+    struct Head* head = (struct Head*)(chunks[0]);
+    char*        body = (char*)(chunks[1]);
+    struct Foot* foot = (struct Foot*)(chunks[2]);
+    // ...
+  }
+
+  In general though, independent_comalloc is worth using only for
+  larger values of n_elements. For small values, you probably won't
+  detect enough difference from series of malloc calls to bother.
+
+  Overuse of independent_comalloc can increase overall memory usage,
+  since it cannot reuse existing noncontiguous small chunks that
+  might be available for some of the elements.
+*/
+void** dlindependent_comalloc(size_t, size_t*, void**);
+
+
+/*
+  pvalloc(size_t n);
+  Equivalent to valloc(minimum-page-that-holds(n)), that is,
+  round up n to nearest pagesize.
+ */
+void*  dlpvalloc(size_t);
+
+/*
+  malloc_trim(size_t pad);
+
+  If possible, gives memory back to the system (via negative arguments
+  to sbrk) if there is unused memory at the `high' end of the malloc
+  pool or in unused MMAP segments. You can call this after freeing
+  large blocks of memory to potentially reduce the system-level memory
+  requirements of a program. However, it cannot guarantee to reduce
+  memory. Under some allocation patterns, some large free blocks of
+  memory will be locked between two used chunks, so they cannot be
+  given back to the system.
+
+  The `pad' argument to malloc_trim represents the amount of free
+  trailing space to leave untrimmed. If this argument is zero, only
+  the minimum amount of memory to maintain internal data structures
+  will be left. Non-zero arguments can be supplied to maintain enough
+  trailing space to service future expected allocations without having
+  to re-obtain memory from the system.
+
+  Malloc_trim returns 1 if it actually released any memory, else 0.
+*/
+int  dlmalloc_trim(size_t);
+
+/*
+  malloc_usable_size(void* p);
+
+  Returns the number of bytes you can actually use in
+  an allocated chunk, which may be more than you requested (although
+  often not) due to alignment and minimum size constraints.
+  You can use this many bytes without worrying about
+  overwriting other allocated objects. This is not a particularly great
+  programming practice. malloc_usable_size can be more useful in
+  debugging and assertions, for example:
+
+  p = malloc(n);
+  assert(malloc_usable_size(p) >= 256);
+*/
+size_t dlmalloc_usable_size(void*);
+
+/*
+  malloc_stats();
+  Prints on stderr the amount of space obtained from the system (both
+  via sbrk and mmap), the maximum amount (which may be more than
+  current if malloc_trim and/or munmap got called), and the current
+  number of bytes allocated via malloc (or realloc, etc) but not yet
+  freed. Note that this is the number of bytes allocated, not the
+  number requested. It will be larger than the number requested
+  because of alignment and bookkeeping overhead. Because it includes
+  alignment wastage as being in use, this figure may be greater than
+  zero even when no user-level chunks are allocated.
+
+  The reported current and maximum system memory can be inaccurate if
+  a program makes other calls to system memory allocation functions
+  (normally sbrk) outside of malloc.
+
+  malloc_stats prints only the most commonly interesting statistics.
+  More information can be obtained by calling mallinfo.
+*/
+void  dlmalloc_stats(void);
+
+#endif /* ONLY_MSPACES */
+
+#if MSPACES
+
+/*
+  mspace is an opaque type representing an independent
+  region of space that supports mspace_malloc, etc.
+*/
+typedef void* mspace;
+
+/*
+  create_mspace creates and returns a new independent space with the
+  given initial capacity, or, if 0, the default granularity size.  It
+  returns null if there is no system memory available to create the
+  space.  If argument locked is non-zero, the space uses a separate
+  lock to control access. The capacity of the space will grow
+  dynamically as needed to service mspace_malloc requests.  You can
+  control the sizes of incremental increases of this space by
+  compiling with a different DEFAULT_GRANULARITY or dynamically
+  setting with mallopt(M_GRANULARITY, value).
+*/
+mspace create_mspace(size_t capacity, int locked);
+
+/*
+  destroy_mspace destroys the given space, and attempts to return all
+  of its memory back to the system, returning the total number of
+  bytes freed. After destruction, the results of access to all memory
+  used by the space become undefined.
+*/
+size_t destroy_mspace(mspace msp);
+
+/*
+  create_mspace_with_base uses the memory supplied as the initial base
+  of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
+  space is used for bookkeeping, so the capacity must be at least this
+  large. (Otherwise 0 is returned.) When this initial space is
+  exhausted, additional memory will be obtained from the system.
+  Destroying this space will deallocate all additionally allocated
+  space (if possible) but not the initial base.
+*/
+mspace create_mspace_with_base(void* base, size_t capacity, int locked);
+
+/*
+  mspace_malloc behaves as malloc, but operates within
+  the given space.
+*/
+void* mspace_malloc(mspace msp, size_t bytes);
+
+/*
+  mspace_free behaves as free, but operates within
+  the given space.
+
+  If compiled with FOOTERS==1, mspace_free is not actually needed.
+  free may be called instead of mspace_free because freed chunks from
+  any space are handled by their originating spaces.
+*/
+void mspace_free(mspace msp, void* mem);
+
+/*
+  mspace_realloc behaves as realloc, but operates within
+  the given space.
+
+  If compiled with FOOTERS==1, mspace_realloc is not actually
+  needed.  realloc may be called instead of mspace_realloc because
+  realloced chunks from any space are handled by their originating
+  spaces.
+*/
+void* mspace_realloc(mspace msp, void* mem, size_t newsize);
+
+/*
+  mspace_calloc behaves as calloc, but operates within
+  the given space.
+*/
+void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
+
+/*
+  mspace_memalign behaves as memalign, but operates within
+  the given space.
+*/
+void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
+
+/*
+  mspace_independent_calloc behaves as independent_calloc, but
+  operates within the given space.
+*/
+void** mspace_independent_calloc(mspace msp, size_t n_elements,
+                                 size_t elem_size, void* chunks[]);
+
+/*
+  mspace_independent_comalloc behaves as independent_comalloc, but
+  operates within the given space.
+*/
+void** mspace_independent_comalloc(mspace msp, size_t n_elements,
+                                   size_t sizes[], void* chunks[]);
+
+/*
+  mspace_footprint() returns the number of bytes obtained from the
+  system for this space.
+*/
+size_t mspace_footprint(mspace msp);
+
+/*
+  mspace_max_footprint() returns the peak number of bytes obtained from the
+  system for this space.
+*/
+size_t mspace_max_footprint(mspace msp);
+
+
+#if !NO_MALLINFO
+/*
+  mspace_mallinfo behaves as mallinfo, but reports properties of
+  the given space.
+*/
+struct mallinfo mspace_mallinfo(mspace msp);
+#endif /* NO_MALLINFO */
+
+/*
+  mspace_malloc_stats behaves as malloc_stats, but reports
+  properties of the given space.
+*/
+void mspace_malloc_stats(mspace msp);
+
+/*
+  mspace_trim behaves as malloc_trim, but
+  operates within the given space.
+*/
+int mspace_trim(mspace msp, size_t pad);
+
+/*
+  An alias for mallopt.
+*/
+int mspace_mallopt(int, int);
+
+#endif /* MSPACES */
+
+#ifdef __cplusplus
+};  /* end of extern "C" */
+#endif /* __cplusplus */
+
+/*
+  ========================================================================
+  To make a fully customizable malloc.h header file, cut everything
+  above this line, put into file malloc.h, edit to suit, and #include it
+  on the next line, as well as in programs that use this malloc.
+  ========================================================================
+*/
+
+/* #include "malloc.h" */
+
+/*------------------------------ internal #includes ---------------------- */
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4146 ) /* no "unsigned" warnings */
+#endif /* _MSC_VER */
+
+#include <stdio.h>       /* for printing in malloc_stats */
+
+#ifndef LACKS_ERRNO_H
+#include <errno.h>       /* for MALLOC_FAILURE_ACTION */
+#endif /* LACKS_ERRNO_H */
+#if FOOTERS
+#include <time.h>        /* for magic initialization */
+#endif /* FOOTERS */
+#ifndef LACKS_STDLIB_H
+#include <stdlib.h>      /* for abort() */
+#endif /* LACKS_STDLIB_H */
+#ifdef DEBUG
+#if ABORT_ON_ASSERT_FAILURE
+#define assert(x) if(!(x)) ABORT
+#else /* ABORT_ON_ASSERT_FAILURE */
+#include <assert.h>
+#endif /* ABORT_ON_ASSERT_FAILURE */
+#else  /* DEBUG */
+#define assert(x)
+#endif /* DEBUG */
+#ifndef LACKS_STRING_H
+#include <string.h>      /* for memset etc */
+#endif  /* LACKS_STRING_H */
+#if USE_BUILTIN_FFS
+#ifndef LACKS_STRINGS_H
+#include <strings.h>     /* for ffs */
+#endif /* LACKS_STRINGS_H */
+#endif /* USE_BUILTIN_FFS */
+#if HAVE_MMAP
+#ifndef LACKS_SYS_MMAN_H
+#include <sys/mman.h>    /* for mmap */
+#endif /* LACKS_SYS_MMAN_H */
+#ifndef LACKS_FCNTL_H
+#include <fcntl.h>
+#endif /* LACKS_FCNTL_H */
+#endif /* HAVE_MMAP */
+#if HAVE_MORECORE
+#ifndef LACKS_UNISTD_H
+#include <unistd.h>     /* for sbrk */
+#else /* LACKS_UNISTD_H */
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
+extern void*     sbrk(ptrdiff_t);
+#endif /* FreeBSD etc */
+#endif /* LACKS_UNISTD_H */
+#endif /* HAVE_MMAP */
+
+#ifndef WIN32
+#ifndef malloc_getpagesize
+#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
+#    ifndef _SC_PAGE_SIZE
+#      define _SC_PAGE_SIZE _SC_PAGESIZE
+#    endif
+#  endif
+#  ifdef _SC_PAGE_SIZE
+#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
+#  else
+#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
+       extern size_t getpagesize();
+#      define malloc_getpagesize getpagesize()
+#    else
+#      ifdef WIN32 /* use supplied emulation of getpagesize */
+#        define malloc_getpagesize getpagesize()
+#      else
+#        ifndef LACKS_SYS_PARAM_H
+#          include <sys/param.h>
+#        endif
+#        ifdef EXEC_PAGESIZE
+#          define malloc_getpagesize EXEC_PAGESIZE
+#        else
+#          ifdef NBPG
+#            ifndef CLSIZE
+#              define malloc_getpagesize NBPG
+#            else
+#              define malloc_getpagesize (NBPG * CLSIZE)
+#            endif
+#          else
+#            ifdef NBPC
+#              define malloc_getpagesize NBPC
+#            else
+#              ifdef PAGESIZE
+#                define malloc_getpagesize PAGESIZE
+#              else /* just guess */
+#                define malloc_getpagesize ((size_t)4096U)
+#              endif
+#            endif
+#          endif
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+#endif
+
+/* ------------------- size_t and alignment properties -------------------- */
+
+/* The byte and bit size of a size_t */
+#define SIZE_T_SIZE         (sizeof(size_t))
+#define SIZE_T_BITSIZE      (sizeof(size_t) << 3)
+
+/* Some constants coerced to size_t */
+/* Annoying but necessary to avoid errors on some plaftorms */
+#define SIZE_T_ZERO         ((size_t)0)
+#define SIZE_T_ONE          ((size_t)1)
+#define SIZE_T_TWO          ((size_t)2)
+#define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)
+#define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)
+#define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
+#define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)
+
+/* The bit mask value corresponding to MALLOC_ALIGNMENT */
+#define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)
+
+/* True if address a has acceptable alignment */
+#define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
+
+/* the number of bytes to offset an address to align it */
+#define align_offset(A)\
+ ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
+  ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
+
+/* -------------------------- MMAP preliminaries ------------------------- */
+
+/*
+   If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
+   checks to fail so compiler optimizer can delete code rather than
+   using so many "#if"s.
+*/
+
+
+/* MORECORE and MMAP must return MFAIL on failure */
+#define MFAIL                ((void*)(MAX_SIZE_T))
+#define CMFAIL               ((char*)(MFAIL)) /* defined for convenience */
+
+#if !HAVE_MMAP
+#define IS_MMAPPED_BIT       (SIZE_T_ZERO)
+#define USE_MMAP_BIT         (SIZE_T_ZERO)
+#define CALL_MMAP(s)         MFAIL
+#define CALL_MUNMAP(a, s)    (-1)
+#define DIRECT_MMAP(s)       MFAIL
+
+#else /* HAVE_MMAP */
+#define IS_MMAPPED_BIT       (SIZE_T_ONE)
+#define USE_MMAP_BIT         (SIZE_T_ONE)
+
+#if !defined(WIN32) && !defined (__OS2__)
+#define CALL_MUNMAP(a, s)    munmap((a), (s))
+#define MMAP_PROT            (PROT_READ|PROT_WRITE)
+#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+#define MAP_ANONYMOUS        MAP_ANON
+#endif /* MAP_ANON */
+#ifdef MAP_ANONYMOUS
+#define MMAP_FLAGS           (MAP_PRIVATE|MAP_ANONYMOUS)
+#define CALL_MMAP(s)         mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
+#else /* MAP_ANONYMOUS */
+/*
+   Nearly all versions of mmap support MAP_ANONYMOUS, so the following
+   is unlikely to be needed, but is supplied just in case.
+*/
+#define MMAP_FLAGS           (MAP_PRIVATE)
+static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
+#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
+           (dev_zero_fd = open("/dev/zero", O_RDWR), \
+            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
+            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
+#endif /* MAP_ANONYMOUS */
+
+#define DIRECT_MMAP(s)       CALL_MMAP(s)
+
+#elif defined(__OS2__)
+
+/* OS/2 MMAP via DosAllocMem */
+static void* os2mmap(size_t size) {
+  void* ptr;
+  if (DosAllocMem(&ptr, size, OBJ_ANY|PAG_COMMIT|PAG_READ|PAG_WRITE) &&
+      DosAllocMem(&ptr, size, PAG_COMMIT|PAG_READ|PAG_WRITE))
+    return MFAIL;
+  return ptr;
+}
+
+#define os2direct_mmap(n)     os2mmap(n)
+
+/* This function supports releasing coalesed segments */
+static int os2munmap(void* ptr, size_t size) {
+  while (size) {
+    ULONG ulSize = size;
+    ULONG ulFlags = 0;
+    if (DosQueryMem(ptr, &ulSize, &ulFlags) != 0)
+      return -1;
+    if ((ulFlags & PAG_BASE) == 0 ||(ulFlags & PAG_COMMIT) == 0 ||
+        ulSize > size)
+      return -1;
+    if (DosFreeMem(ptr) != 0)
+      return -1;
+    ptr = ( void * ) ( ( char * ) ptr + ulSize );
+    size -= ulSize;
+  }
+  return 0;
+}
+
+#define CALL_MMAP(s)         os2mmap(s)
+#define CALL_MUNMAP(a, s)    os2munmap((a), (s))
+#define DIRECT_MMAP(s)       os2direct_mmap(s)
+
+#else /* WIN32 */
+
+/* Win32 MMAP via VirtualAlloc */
+static void* win32mmap(size_t size) {
+  void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+  return (ptr != 0)? ptr: MFAIL;
+}
+
+/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
+static void* win32direct_mmap(size_t size) {
+  void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
+                           PAGE_EXECUTE_READWRITE);
+  return (ptr != 0)? ptr: MFAIL;
+}
+
+/* This function supports releasing coalesed segments */
+static int win32munmap(void* ptr, size_t size) {
+  MEMORY_BASIC_INFORMATION minfo;
+  char* cptr = ptr;
+  while (size) {
+    if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
+      return -1;
+    if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
+        minfo.State != MEM_COMMIT || minfo.RegionSize > size)
+      return -1;
+    if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
+      return -1;
+    cptr += minfo.RegionSize;
+    size -= minfo.RegionSize;
+  }
+  return 0;
+}
+
+#define CALL_MMAP(s)         win32mmap(s)
+#define CALL_MUNMAP(a, s)    win32munmap((a), (s))
+#define DIRECT_MMAP(s)       win32direct_mmap(s)
+#endif /* WIN32 */
+#endif /* HAVE_MMAP */
+
+#if HAVE_MMAP && HAVE_MREMAP
+#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
+#else  /* HAVE_MMAP && HAVE_MREMAP */
+#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
+#endif /* HAVE_MMAP && HAVE_MREMAP */
+
+#if HAVE_MORECORE
+#define CALL_MORECORE(S)     MORECORE(S)
+#else  /* HAVE_MORECORE */
+#define CALL_MORECORE(S)     MFAIL
+#endif /* HAVE_MORECORE */
+
+/* mstate bit set if continguous morecore disabled or failed */
+#define USE_NONCONTIGUOUS_BIT (4U)
+
+/* segment bit set in create_mspace_with_base */
+#define EXTERN_BIT            (8U)
+
+
+/* --------------------------- Lock preliminaries ------------------------ */
+
+#if USE_LOCKS
+
+/*
+  When locks are defined, there are up to two global locks:
+
+  * If HAVE_MORECORE, morecore_mutex protects sequences of calls to
+    MORECORE.  In many cases sys_alloc requires two calls, that should
+    not be interleaved with calls by other threads.  This does not
+    protect against direct calls to MORECORE by other threads not
+    using this lock, so there is still code to cope the best we can on
+    interference.
+
+  * magic_init_mutex ensures that mparams.magic and other
+    unique mparams values are initialized only once.
+*/
+
+#if !defined(WIN32) && !defined(__OS2__)
+/* By default use posix locks */
+#include <pthread.h>
+#define MLOCK_T pthread_mutex_t
+#define INITIAL_LOCK(l)      pthread_mutex_init(l, NULL)
+#define ACQUIRE_LOCK(l)      pthread_mutex_lock(l)
+#define RELEASE_LOCK(l)      pthread_mutex_unlock(l)
+
+#if HAVE_MORECORE
+static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif /* HAVE_MORECORE */
+
+static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#elif defined(__OS2__)
+#define MLOCK_T HMTX
+#define INITIAL_LOCK(l)      DosCreateMutexSem(0, l, 0, FALSE)
+#define ACQUIRE_LOCK(l)      DosRequestMutexSem(*l, SEM_INDEFINITE_WAIT)
+#define RELEASE_LOCK(l)      DosReleaseMutexSem(*l)
+#if HAVE_MORECORE
+static MLOCK_T morecore_mutex;
+#endif /* HAVE_MORECORE */
+static MLOCK_T magic_init_mutex;
+
+#else /* WIN32 */
+/*
+   Because lock-protected regions have bounded times, and there
+   are no recursive lock calls, we can use simple spinlocks.
+*/
+
+#define MLOCK_T long
+static int win32_acquire_lock (MLOCK_T *sl) {
+  for (;;) {
+#ifdef InterlockedCompareExchangePointer
+    if (!InterlockedCompareExchange(sl, 1, 0))
+      return 0;
+#else  /* Use older void* version */
+    if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0))
+      return 0;
+#endif /* InterlockedCompareExchangePointer */
+    Sleep (0);
+  }
+}
+
+static void win32_release_lock (MLOCK_T *sl) {
+  InterlockedExchange (sl, 0);
+}
+
+#define INITIAL_LOCK(l)      *(l)=0
+#define ACQUIRE_LOCK(l)      win32_acquire_lock(l)
+#define RELEASE_LOCK(l)      win32_release_lock(l)
+#if HAVE_MORECORE
+static MLOCK_T morecore_mutex;
+#endif /* HAVE_MORECORE */
+static MLOCK_T magic_init_mutex;
+#endif /* WIN32 */
+
+#define USE_LOCK_BIT               (2U)
+#else  /* USE_LOCKS */
+#define USE_LOCK_BIT               (0U)
+#define INITIAL_LOCK(l)
+#endif /* USE_LOCKS */
+
+#if USE_LOCKS && HAVE_MORECORE
+#define ACQUIRE_MORECORE_LOCK()    ACQUIRE_LOCK(&morecore_mutex);
+#define RELEASE_MORECORE_LOCK()    RELEASE_LOCK(&morecore_mutex);
+#else /* USE_LOCKS && HAVE_MORECORE */
+#define ACQUIRE_MORECORE_LOCK()
+#define RELEASE_MORECORE_LOCK()
+#endif /* USE_LOCKS && HAVE_MORECORE */
+
+#if USE_LOCKS
+#define ACQUIRE_MAGIC_INIT_LOCK()  ACQUIRE_LOCK(&magic_init_mutex);
+#define RELEASE_MAGIC_INIT_LOCK()  RELEASE_LOCK(&magic_init_mutex);
+#else  /* USE_LOCKS */
+#define ACQUIRE_MAGIC_INIT_LOCK()
+#define RELEASE_MAGIC_INIT_LOCK()
+#endif /* USE_LOCKS */
+
+
+/* -----------------------  Chunk representations ------------------------ */
+
+/*
+  (The following includes lightly edited explanations by Colin Plumb.)
+
+  The malloc_chunk declaration below is misleading (but accurate and
+  necessary).  It declares a "view" into memory allowing access to
+  necessary fields at known offsets from a given base.
+
+  Chunks of memory are maintained using a `boundary tag' method as
+  originally described by Knuth.  (See the paper by Paul Wilson
+  ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
+  techniques.)  Sizes of free chunks are stored both in the front of
+  each chunk and at the end.  This makes consolidating fragmented
+  chunks into bigger chunks fast.  The head fields also hold bits
+  representing whether chunks are free or in use.
+
+  Here are some pictures to make it clearer.  They are "exploded" to
+  show that the state of a chunk can be thought of as extending from
+  the high 31 bits of the head field of its header through the
+  prev_foot and PINUSE_BIT bit of the following chunk header.
+
+  A chunk that's in use looks like:
+
+   chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+           | Size of previous chunk (if P = 1)                             |
+           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
+         | Size of this chunk                                         1| +-+
+   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         |                                                               |
+         +-                                                             -+
+         |                                                               |
+         +-                                                             -+
+         |                                                               :
+         +-      size - sizeof(size_t) available payload bytes          -+
+         :                                                               |
+ chunk-> +-                                                             -+
+         |                                                               |
+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
+       | Size of next chunk (may or may not be in use)               | +-+
+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+    And if it's free, it looks like this:
+
+   chunk-> +-                                                             -+
+           | User payload (must be in use, or we would have merged!)       |
+           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
+         | Size of this chunk                                         0| +-+
+   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         | Next pointer                                                  |
+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         | Prev pointer                                                  |
+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         |                                                               :
+         +-      size - sizeof(struct chunk) unused bytes               -+
+         :                                                               |
+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         | Size of this chunk                                            |
+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
+       | Size of next chunk (must be in use, or we would have merged)| +-+
+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                                                               :
+       +- User payload                                                -+
+       :                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+                                                                     |0|
+                                                                     +-+
+  Note that since we always merge adjacent free chunks, the chunks
+  adjacent to a free chunk must be in use.
+
+  Given a pointer to a chunk (which can be derived trivially from the
+  payload pointer) we can, in O(1) time, find out whether the adjacent
+  chunks are free, and if so, unlink them from the lists that they
+  are on and merge them with the current chunk.
+
+  Chunks always begin on even word boundaries, so the mem portion
+  (which is returned to the user) is also on an even word boundary, and
+  thus at least double-word aligned.
+
+  The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
+  chunk size (which is always a multiple of two words), is an in-use
+  bit for the *previous* chunk.  If that bit is *clear*, then the
+  word before the current chunk size contains the previous chunk
+  size, and can be used to find the front of the previous chunk.
+  The very first chunk allocated always has this bit set, preventing
+  access to non-existent (or non-owned) memory. If pinuse is set for
+  any given chunk, then you CANNOT determine the size of the
+  previous chunk, and might even get a memory addressing fault when
+  trying to do so.
+
+  The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
+  the chunk size redundantly records whether the current chunk is
+  inuse. This redundancy enables usage checks within free and realloc,
+  and reduces indirection when freeing and consolidating chunks.
+
+  Each freshly allocated chunk must have both cinuse and pinuse set.
+  That is, each allocated chunk borders either a previously allocated
+  and still in-use chunk, or the base of its memory arena. This is
+  ensured by making all allocations from the the `lowest' part of any
+  found chunk.  Further, no free chunk physically borders another one,
+  so each free chunk is known to be preceded and followed by either
+  inuse chunks or the ends of memory.
+
+  Note that the `foot' of the current chunk is actually represented
+  as the prev_foot of the NEXT chunk. This makes it easier to
+  deal with alignments etc but can be very confusing when trying
+  to extend or adapt this code.
+
+  The exceptions to all this are
+
+     1. The special chunk `top' is the top-most available chunk (i.e.,
+        the one bordering the end of available memory). It is treated
+        specially.  Top is never included in any bin, is used only if
+        no other chunk is available, and is released back to the
+        system if it is very large (see M_TRIM_THRESHOLD).  In effect,
+        the top chunk is treated as larger (and thus less well
+        fitting) than any other available chunk.  The top chunk
+        doesn't update its trailing size field since there is no next
+        contiguous chunk that would have to index off it. However,
+        space is still allocated for it (TOP_FOOT_SIZE) to enable
+        separation or merging when space is extended.
+
+     3. Chunks allocated via mmap, which have the lowest-order bit
+        (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set
+        PINUSE_BIT in their head fields.  Because they are allocated
+        one-by-one, each must carry its own prev_foot field, which is
+        also used to hold the offset this chunk has within its mmapped
+        region, which is needed to preserve alignment. Each mmapped
+        chunk is trailed by the first two fields of a fake next-chunk
+        for sake of usage checks.
+
+*/
+
+struct malloc_chunk {
+  size_t               prev_foot;  /* Size of previous chunk (if free).  */
+  size_t               head;       /* Size and inuse bits. */
+  struct malloc_chunk* fd;         /* double links -- used only if free. */
+  struct malloc_chunk* bk;
+};
+
+typedef struct malloc_chunk  mchunk;
+typedef struct malloc_chunk* mchunkptr;
+typedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */
+typedef unsigned int bindex_t;         /* Described below */
+typedef unsigned int binmap_t;         /* Described below */
+typedef unsigned int flag_t;           /* The type of various bit flag sets */
+
+/* ------------------- Chunks sizes and alignments ----------------------- */
+
+#define MCHUNK_SIZE         (sizeof(mchunk))
+
+#if FOOTERS
+#define CHUNK_OVERHEAD      (TWO_SIZE_T_SIZES)
+#else /* FOOTERS */
+#define CHUNK_OVERHEAD      (SIZE_T_SIZE)
+#endif /* FOOTERS */
+
+/* MMapped chunks need a second word of overhead ... */
+#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
+/* ... and additional padding for fake next-chunk at foot */
+#define MMAP_FOOT_PAD       (FOUR_SIZE_T_SIZES)
+
+/* The smallest size we can malloc is an aligned minimal chunk */
+#define MIN_CHUNK_SIZE\
+  ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
+
+/* conversion from malloc headers to user pointers, and back */
+#define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))
+#define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
+/* chunk associated with aligned address A */
+#define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))
+
+/* Bounds on request (not chunk) sizes. */
+#define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)
+#define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
+
+/* pad request bytes into a usable size */
+#define pad_request(req) \
+   (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
+
+/* pad request, checking for minimum (but not maximum) */
+#define request2size(req) \
+  (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
+
+
+/* ------------------ Operations on head and foot fields ----------------- */
+
+/*
+  The head field of a chunk is or'ed with PINUSE_BIT when previous
+  adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
+  use. If the chunk was obtained with mmap, the prev_foot field has
+  IS_MMAPPED_BIT set, otherwise holding the offset of the base of the
+  mmapped region to the base of the chunk.
+*/
+
+#define PINUSE_BIT          (SIZE_T_ONE)
+#define CINUSE_BIT          (SIZE_T_TWO)
+#define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)
+
+/* Head value for fenceposts */
+#define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)
+
+/* extraction of fields from head words */
+#define cinuse(p)           ((p)->head & CINUSE_BIT)
+#define pinuse(p)           ((p)->head & PINUSE_BIT)
+#define chunksize(p)        ((p)->head & ~(INUSE_BITS))
+
+#define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)
+#define clear_cinuse(p)     ((p)->head &= ~CINUSE_BIT)
+
+/* Treat space at ptr +/- offset as a chunk */
+#define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
+#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
+
+/* Ptr to next or previous physical malloc_chunk. */
+#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS)))
+#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
+
+/* extract next chunk's pinuse bit */
+#define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)
+
+/* Get/set size at footer */
+#define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)
+#define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
+
+/* Set size, pinuse bit, and foot */
+#define set_size_and_pinuse_of_free_chunk(p, s)\
+  ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
+
+/* Set size, pinuse bit, foot, and clear next pinuse */
+#define set_free_with_pinuse(p, s, n)\
+  (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
+
+#define is_mmapped(p)\
+  (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
+
+/* Get the internal overhead associated with chunk p */
+#define overhead_for(p)\
+ (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
+
+/* Return true if malloced space is not necessarily cleared */
+#if MMAP_CLEARS
+#define calloc_must_clear(p) (!is_mmapped(p))
+#else /* MMAP_CLEARS */
+#define calloc_must_clear(p) (1)
+#endif /* MMAP_CLEARS */
+
+/* ---------------------- Overlaid data structures ----------------------- */
+
+/*
+  When chunks are not in use, they are treated as nodes of either
+  lists or trees.
+
+  "Small"  chunks are stored in circular doubly-linked lists, and look
+  like this:
+
+    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Size of previous chunk                            |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    `head:' |             Size of chunk, in bytes                         |P|
+      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Forward pointer to next chunk in list             |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Back pointer to previous chunk in list            |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Unused space (may be 0 bytes long)                .
+            .                                                               .
+            .                                                               |
+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    `foot:' |             Size of chunk, in bytes                           |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+  Larger chunks are kept in a form of bitwise digital trees (aka
+  tries) keyed on chunksizes.  Because malloc_tree_chunks are only for
+  free chunks greater than 256 bytes, their size doesn't impose any
+  constraints on user chunk sizes.  Each node looks like:
+
+    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Size of previous chunk                            |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    `head:' |             Size of chunk, in bytes                         |P|
+      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Forward pointer to next chunk of same size        |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Back pointer to previous chunk of same size       |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Pointer to left child (child[0])                  |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Pointer to right child (child[1])                 |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Pointer to parent                                 |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             bin index of this chunk                           |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Unused space                                      .
+            .                                                               |
+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    `foot:' |             Size of chunk, in bytes                           |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+  Each tree holding treenodes is a tree of unique chunk sizes.  Chunks
+  of the same size are arranged in a circularly-linked list, with only
+  the oldest chunk (the next to be used, in our FIFO ordering)
+  actually in the tree.  (Tree members are distinguished by a non-null
+  parent pointer.)  If a chunk with the same size an an existing node
+  is inserted, it is linked off the existing node using pointers that
+  work in the same way as fd/bk pointers of small chunks.
+
+  Each tree contains a power of 2 sized range of chunk sizes (the
+  smallest is 0x100 <= x < 0x180), which is is divided in half at each
+  tree level, with the chunks in the smaller half of the range (0x100
+  <= x < 0x140 for the top nose) in the left subtree and the larger
+  half (0x140 <= x < 0x180) in the right subtree.  This is, of course,
+  done by inspecting individual bits.
+
+  Using these rules, each node's left subtree contains all smaller
+  sizes than its right subtree.  However, the node at the root of each
+  subtree has no particular ordering relationship to either.  (The
+  dividing line between the subtree sizes is based on trie relation.)
+  If we remove the last chunk of a given size from the interior of the
+  tree, we need to replace it with a leaf node.  The tree ordering
+  rules permit a node to be replaced by any leaf below it.
+
+  The smallest chunk in a tree (a common operation in a best-fit
+  allocator) can be found by walking a path to the leftmost leaf in
+  the tree.  Unlike a usual binary tree, where we follow left child
+  pointers until we reach a null, here we follow the right child
+  pointer any time the left one is null, until we reach a leaf with
+  both child pointers null. The smallest chunk in the tree will be
+  somewhere along that path.
+
+  The worst case number of steps to add, find, or remove a node is
+  bounded by the number of bits differentiating chunks within
+  bins. Under current bin calculations, this ranges from 6 up to 21
+  (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
+  is of course much better.
+*/
+
+struct malloc_tree_chunk {
+  /* The first four fields must be compatible with malloc_chunk */
+  size_t                    prev_foot;
+  size_t                    head;
+  struct malloc_tree_chunk* fd;
+  struct malloc_tree_chunk* bk;
+
+  struct malloc_tree_chunk* child[2];
+  struct malloc_tree_chunk* parent;
+  bindex_t                  index;
+};
+
+typedef struct malloc_tree_chunk  tchunk;
+typedef struct malloc_tree_chunk* tchunkptr;
+typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
+
+/* A little helper macro for trees */
+#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
+
+/* ----------------------------- Segments -------------------------------- */
+
+/*
+  Each malloc space may include non-contiguous segments, held in a
+  list headed by an embedded malloc_segment record representing the
+  top-most space. Segments also include flags holding properties of
+  the space. Large chunks that are directly allocated by mmap are not
+  included in this list. They are instead independently created and
+  destroyed without otherwise keeping track of them.
+
+  Segment management mainly comes into play for spaces allocated by
+  MMAP.  Any call to MMAP might or might not return memory that is
+  adjacent to an existing segment.  MORECORE normally contiguously
+  extends the current space, so this space is almost always adjacent,
+  which is simpler and faster to deal with. (This is why MORECORE is
+  used preferentially to MMAP when both are available -- see
+  sys_alloc.)  When allocating using MMAP, we don't use any of the
+  hinting mechanisms (inconsistently) supported in various
+  implementations of unix mmap, or distinguish reserving from
+  committing memory. Instead, we just ask for space, and exploit
+  contiguity when we get it.  It is probably possible to do
+  better than this on some systems, but no general scheme seems
+  to be significantly better.
+
+  Management entails a simpler variant of the consolidation scheme
+  used for chunks to reduce fragmentation -- new adjacent memory is
+  normally prepended or appended to an existing segment. However,
+  there are limitations compared to chunk consolidation that mostly
+  reflect the fact that segment processing is relatively infrequent
+  (occurring only when getting memory from system) and that we
+  don't expect to have huge numbers of segments:
+
+  * Segments are not indexed, so traversal requires linear scans.  (It
+    would be possible to index these, but is not worth the extra
+    overhead and complexity for most programs on most platforms.)
+  * New segments are only appended to old ones when holding top-most
+    memory; if they cannot be prepended to others, they are held in
+    different segments.
+
+  Except for the top-most segment of an mstate, each segment record
+  is kept at the tail of its segment. Segments are added by pushing
+  segment records onto the list headed by &mstate.seg for the
+  containing mstate.
+
+  Segment flags control allocation/merge/deallocation policies:
+  * If EXTERN_BIT set, then we did not allocate this segment,
+    and so should not try to deallocate or merge with others.
+    (This currently holds only for the initial segment passed
+    into create_mspace_with_base.)
+  * If IS_MMAPPED_BIT set, the segment may be merged with
+    other surrounding mmapped segments and trimmed/de-allocated
+    using munmap.
+  * If neither bit is set, then the segment was obtained using
+    MORECORE so can be merged with surrounding MORECORE'd segments
+    and deallocated/trimmed using MORECORE with negative arguments.
+*/
+
+struct malloc_segment {
+  char*        base;             /* base address */
+  size_t       size;             /* allocated size */
+  struct malloc_segment* next;   /* ptr to next segment */
+#if FFI_MMAP_EXEC_WRIT
+  /* The mmap magic is supposed to store the address of the executable
+     segment at the very end of the requested block.  */
+
+# define mmap_exec_offset(b,s) (*(ptrdiff_t*)((b)+(s)-sizeof(ptrdiff_t)))
+
+  /* We can only merge segments if their corresponding executable
+     segments are at identical offsets.  */
+# define check_segment_merge(S,b,s) \
+  (mmap_exec_offset((b),(s)) == (S)->exec_offset)
+
+# define add_segment_exec_offset(p,S) ((char*)(p) + (S)->exec_offset)
+# define sub_segment_exec_offset(p,S) ((char*)(p) - (S)->exec_offset)
+
+  /* The removal of sflags only works with HAVE_MORECORE == 0.  */
+
+# define get_segment_flags(S)   (IS_MMAPPED_BIT)
+# define set_segment_flags(S,v) \
+  (((v) != IS_MMAPPED_BIT) ? (ABORT, (v)) :				\
+   (((S)->exec_offset =							\
+     mmap_exec_offset((S)->base, (S)->size)),				\
+    (mmap_exec_offset((S)->base + (S)->exec_offset, (S)->size) !=	\
+     (S)->exec_offset) ? (ABORT, (v)) :					\
+   (mmap_exec_offset((S)->base, (S)->size) = 0), (v)))
+
+  /* We use an offset here, instead of a pointer, because then, when
+     base changes, we don't have to modify this.  On architectures
+     with segmented addresses, this might not work.  */
+  ptrdiff_t    exec_offset;
+#else
+
+# define get_segment_flags(S)   ((S)->sflags)
+# define set_segment_flags(S,v) ((S)->sflags = (v))
+# define check_segment_merge(S,b,s) (1)
+
+  flag_t       sflags;           /* mmap and extern flag */
+#endif
+};
+
+#define is_mmapped_segment(S)  (get_segment_flags(S) & IS_MMAPPED_BIT)
+#define is_extern_segment(S)   (get_segment_flags(S) & EXTERN_BIT)
+
+typedef struct malloc_segment  msegment;
+typedef struct malloc_segment* msegmentptr;
+
+/* ---------------------------- malloc_state ----------------------------- */
+
+/*
+   A malloc_state holds all of the bookkeeping for a space.
+   The main fields are:
+
+  Top
+    The topmost chunk of the currently active segment. Its size is
+    cached in topsize.  The actual size of topmost space is
+    topsize+TOP_FOOT_SIZE, which includes space reserved for adding
+    fenceposts and segment records if necessary when getting more
+    space from the system.  The size at which to autotrim top is
+    cached from mparams in trim_check, except that it is disabled if
+    an autotrim fails.
+
+  Designated victim (dv)
+    This is the preferred chunk for servicing small requests that
+    don't have exact fits.  It is normally the chunk split off most
+    recently to service another small request.  Its size is cached in
+    dvsize. The link fields of this chunk are not maintained since it
+    is not kept in a bin.
+
+  SmallBins
+    An array of bin headers for free chunks.  These bins hold chunks
+    with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
+    chunks of all the same size, spaced 8 bytes apart.  To simplify
+    use in double-linked lists, each bin header acts as a malloc_chunk
+    pointing to the real first node, if it exists (else pointing to
+    itself).  This avoids special-casing for headers.  But to avoid
+    waste, we allocate only the fd/bk pointers of bins, and then use
+    repositioning tricks to treat these as the fields of a chunk.
+
+  TreeBins
+    Treebins are pointers to the roots of trees holding a range of
+    sizes. There are 2 equally spaced treebins for each power of two
+    from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
+    larger.
+
+  Bin maps
+    There is one bit map for small bins ("smallmap") and one for
+    treebins ("treemap).  Each bin sets its bit when non-empty, and
+    clears the bit when empty.  Bit operations are then used to avoid
+    bin-by-bin searching -- nearly all "search" is done without ever
+    looking at bins that won't be selected.  The bit maps
+    conservatively use 32 bits per map word, even if on 64bit system.
+    For a good description of some of the bit-based techniques used
+    here, see Henry S. Warren Jr's book "Hacker's Delight" (and
+    supplement at http://hackersdelight.org/). Many of these are
+    intended to reduce the branchiness of paths through malloc etc, as
+    well as to reduce the number of memory locations read or written.
+
+  Segments
+    A list of segments headed by an embedded malloc_segment record
+    representing the initial space.
+
+  Address check support
+    The least_addr field is the least address ever obtained from
+    MORECORE or MMAP. Attempted frees and reallocs of any address less
+    than this are trapped (unless INSECURE is defined).
+
+  Magic tag
+    A cross-check field that should always hold same value as mparams.magic.
+
+  Flags
+    Bits recording whether to use MMAP, locks, or contiguous MORECORE
+
+  Statistics
+    Each space keeps track of current and maximum system memory
+    obtained via MORECORE or MMAP.
+
+  Locking
+    If USE_LOCKS is defined, the "mutex" lock is acquired and released
+    around every public call using this mspace.
+*/
+
+/* Bin types, widths and sizes */
+#define NSMALLBINS        (32U)
+#define NTREEBINS         (32U)
+#define SMALLBIN_SHIFT    (3U)
+#define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)
+#define TREEBIN_SHIFT     (8U)
+#define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)
+#define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)
+#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
+
+struct malloc_state {
+  binmap_t   smallmap;
+  binmap_t   treemap;
+  size_t     dvsize;
+  size_t     topsize;
+  char*      least_addr;
+  mchunkptr  dv;
+  mchunkptr  top;
+  size_t     trim_check;
+  size_t     magic;
+  mchunkptr  smallbins[(NSMALLBINS+1)*2];
+  tbinptr    treebins[NTREEBINS];
+  size_t     footprint;
+  size_t     max_footprint;
+  flag_t     mflags;
+#if USE_LOCKS
+  MLOCK_T    mutex;     /* locate lock among fields that rarely change */
+#endif /* USE_LOCKS */
+  msegment   seg;
+};
+
+typedef struct malloc_state*    mstate;
+
+/* ------------- Global malloc_state and malloc_params ------------------- */
+
+/*
+  malloc_params holds global properties, including those that can be
+  dynamically set using mallopt. There is a single instance, mparams,
+  initialized in init_mparams.
+*/
+
+struct malloc_params {
+  size_t magic;
+  size_t page_size;
+  size_t granularity;
+  size_t mmap_threshold;
+  size_t trim_threshold;
+  flag_t default_mflags;
+};
+
+static struct malloc_params mparams;
+
+/* The global malloc_state used for all non-"mspace" calls */
+static struct malloc_state _gm_;
+#define gm                 (&_gm_)
+#define is_global(M)       ((M) == &_gm_)
+#define is_initialized(M)  ((M)->top != 0)
+
+/* -------------------------- system alloc setup ------------------------- */
+
+/* Operations on mflags */
+
+#define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)
+#define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)
+#define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)
+
+#define use_mmap(M)           ((M)->mflags &   USE_MMAP_BIT)
+#define enable_mmap(M)        ((M)->mflags |=  USE_MMAP_BIT)
+#define disable_mmap(M)       ((M)->mflags &= ~USE_MMAP_BIT)
+
+#define use_noncontiguous(M)  ((M)->mflags &   USE_NONCONTIGUOUS_BIT)
+#define disable_contiguous(M) ((M)->mflags |=  USE_NONCONTIGUOUS_BIT)
+
+#define set_lock(M,L)\
+ ((M)->mflags = (L)?\
+  ((M)->mflags | USE_LOCK_BIT) :\
+  ((M)->mflags & ~USE_LOCK_BIT))
+
+/* page-align a size */
+#define page_align(S)\
+ (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))
+
+/* granularity-align a size */
+#define granularity_align(S)\
+  (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))
+
+#define is_page_aligned(S)\
+   (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
+#define is_granularity_aligned(S)\
+   (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
+
+/*  True if segment S holds address A */
+#define segment_holds(S, A)\
+  ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
+
+/* Return segment holding given address */
+static msegmentptr segment_holding(mstate m, char* addr) {
+  msegmentptr sp = &m->seg;
+  for (;;) {
+    if (addr >= sp->base && addr < sp->base + sp->size)
+      return sp;
+    if ((sp = sp->next) == 0)
+      return 0;
+  }
+}
+
+/* Return true if segment contains a segment link */
+static int has_segment_link(mstate m, msegmentptr ss) {
+  msegmentptr sp = &m->seg;
+  for (;;) {
+    if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
+      return 1;
+    if ((sp = sp->next) == 0)
+      return 0;
+  }
+}
+
+#ifndef MORECORE_CANNOT_TRIM
+#define should_trim(M,s)  ((s) > (M)->trim_check)
+#else  /* MORECORE_CANNOT_TRIM */
+#define should_trim(M,s)  (0)
+#endif /* MORECORE_CANNOT_TRIM */
+
+/*
+  TOP_FOOT_SIZE is padding at the end of a segment, including space
+  that may be needed to place segment records and fenceposts when new
+  noncontiguous segments are added.
+*/
+#define TOP_FOOT_SIZE\
+  (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
+
+
+/* -------------------------------  Hooks -------------------------------- */
+
+/*
+  PREACTION should be defined to return 0 on success, and nonzero on
+  failure. If you are not using locking, you can redefine these to do
+  anything you like.
+*/
+
+#if USE_LOCKS
+
+/* Ensure locks are initialized */
+#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())
+
+#define PREACTION(M)  ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
+#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
+#else /* USE_LOCKS */
+
+#ifndef PREACTION
+#define PREACTION(M) (0)
+#endif  /* PREACTION */
+
+#ifndef POSTACTION
+#define POSTACTION(M)
+#endif  /* POSTACTION */
+
+#endif /* USE_LOCKS */
+
+/*
+  CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
+  USAGE_ERROR_ACTION is triggered on detected bad frees and
+  reallocs. The argument p is an address that might have triggered the
+  fault. It is ignored by the two predefined actions, but might be
+  useful in custom actions that try to help diagnose errors.
+*/
+
+#if PROCEED_ON_ERROR
+
+/* A count of the number of corruption errors causing resets */
+int malloc_corruption_error_count;
+
+/* default corruption action */
+static void reset_on_error(mstate m);
+
+#define CORRUPTION_ERROR_ACTION(m)  reset_on_error(m)
+#define USAGE_ERROR_ACTION(m, p)
+
+#else /* PROCEED_ON_ERROR */
+
+#ifndef CORRUPTION_ERROR_ACTION
+#define CORRUPTION_ERROR_ACTION(m) ABORT
+#endif /* CORRUPTION_ERROR_ACTION */
+
+#ifndef USAGE_ERROR_ACTION
+#define USAGE_ERROR_ACTION(m,p) ABORT
+#endif /* USAGE_ERROR_ACTION */
+
+#endif /* PROCEED_ON_ERROR */
+
+/* -------------------------- Debugging setup ---------------------------- */
+
+#if ! DEBUG
+
+#define check_free_chunk(M,P)
+#define check_inuse_chunk(M,P)
+#define check_malloced_chunk(M,P,N)
+#define check_mmapped_chunk(M,P)
+#define check_malloc_state(M)
+#define check_top_chunk(M,P)
+
+#else /* DEBUG */
+#define check_free_chunk(M,P)       do_check_free_chunk(M,P)
+#define check_inuse_chunk(M,P)      do_check_inuse_chunk(M,P)
+#define check_top_chunk(M,P)        do_check_top_chunk(M,P)
+#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
+#define check_mmapped_chunk(M,P)    do_check_mmapped_chunk(M,P)
+#define check_malloc_state(M)       do_check_malloc_state(M)
+
+static void   do_check_any_chunk(mstate m, mchunkptr p);
+static void   do_check_top_chunk(mstate m, mchunkptr p);
+static void   do_check_mmapped_chunk(mstate m, mchunkptr p);
+static void   do_check_inuse_chunk(mstate m, mchunkptr p);
+static void   do_check_free_chunk(mstate m, mchunkptr p);
+static void   do_check_malloced_chunk(mstate m, void* mem, size_t s);
+static void   do_check_tree(mstate m, tchunkptr t);
+static void   do_check_treebin(mstate m, bindex_t i);
+static void   do_check_smallbin(mstate m, bindex_t i);
+static void   do_check_malloc_state(mstate m);
+static int    bin_find(mstate m, mchunkptr x);
+static size_t traverse_and_check(mstate m);
+#endif /* DEBUG */
+
+/* ---------------------------- Indexing Bins ---------------------------- */
+
+#define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
+#define small_index(s)      ((s)  >> SMALLBIN_SHIFT)
+#define small_index2size(i) ((i)  << SMALLBIN_SHIFT)
+#define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))
+
+/* addressing by index. See above about smallbin repositioning */
+#define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
+#define treebin_at(M,i)     (&((M)->treebins[i]))
+
+/* assign tree index for size S to variable I */
+#if defined(__GNUC__) && defined(i386)
+#define compute_tree_index(S, I)\
+{\
+  size_t X = S >> TREEBIN_SHIFT;\
+  if (X == 0)\
+    I = 0;\
+  else if (X > 0xFFFF)\
+    I = NTREEBINS-1;\
+  else {\
+    unsigned int K;\
+    __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm"  (X));\
+    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
+  }\
+}
+#else /* GNUC */
+#define compute_tree_index(S, I)\
+{\
+  size_t X = S >> TREEBIN_SHIFT;\
+  if (X == 0)\
+    I = 0;\
+  else if (X > 0xFFFF)\
+    I = NTREEBINS-1;\
+  else {\
+    unsigned int Y = (unsigned int)X;\
+    unsigned int N = ((Y - 0x100) >> 16) & 8;\
+    unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
+    N += K;\
+    N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
+    K = 14 - N + ((Y <<= K) >> 15);\
+    I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
+  }\
+}
+#endif /* GNUC */
+
+/* Bit representing maximum resolved size in a treebin at i */
+#define bit_for_tree_index(i) \
+   (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
+
+/* Shift placing maximum resolved bit in a treebin at i as sign bit */
+#define leftshift_for_tree_index(i) \
+   ((i == NTREEBINS-1)? 0 : \
+    ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
+
+/* The size of the smallest chunk held in bin with index i */
+#define minsize_for_tree_index(i) \
+   ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \
+   (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
+
+
+/* ------------------------ Operations on bin maps ----------------------- */
+
+/* bit corresponding to given index */
+#define idx2bit(i)              ((binmap_t)(1) << (i))
+
+/* Mark/Clear bits with given index */
+#define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))
+#define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))
+#define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))
+
+#define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))
+#define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))
+#define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))
+
+/* index corresponding to given bit */
+
+#if defined(__GNUC__) && defined(i386)
+#define compute_bit2idx(X, I)\
+{\
+  unsigned int J;\
+  __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\
+  I = (bindex_t)J;\
+}
+
+#else /* GNUC */
+#if  USE_BUILTIN_FFS
+#define compute_bit2idx(X, I) I = ffs(X)-1
+
+#else /* USE_BUILTIN_FFS */
+#define compute_bit2idx(X, I)\
+{\
+  unsigned int Y = X - 1;\
+  unsigned int K = Y >> (16-4) & 16;\
+  unsigned int N = K;        Y >>= K;\
+  N += K = Y >> (8-3) &  8;  Y >>= K;\
+  N += K = Y >> (4-2) &  4;  Y >>= K;\
+  N += K = Y >> (2-1) &  2;  Y >>= K;\
+  N += K = Y >> (1-0) &  1;  Y >>= K;\
+  I = (bindex_t)(N + Y);\
+}
+#endif /* USE_BUILTIN_FFS */
+#endif /* GNUC */
+
+/* isolate the least set bit of a bitmap */
+#define least_bit(x)         ((x) & -(x))
+
+/* mask with all bits to left of least bit of x on */
+#define left_bits(x)         ((x<<1) | -(x<<1))
+
+/* mask with all bits to left of or equal to least bit of x on */
+#define same_or_left_bits(x) ((x) | -(x))
+
+
+/* ----------------------- Runtime Check Support ------------------------- */
+
+/*
+  For security, the main invariant is that malloc/free/etc never
+  writes to a static address other than malloc_state, unless static
+  malloc_state itself has been corrupted, which cannot occur via
+  malloc (because of these checks). In essence this means that we
+  believe all pointers, sizes, maps etc held in malloc_state, but
+  check all of those linked or offsetted from other embedded data
+  structures.  These checks are interspersed with main code in a way
+  that tends to minimize their run-time cost.
+
+  When FOOTERS is defined, in addition to range checking, we also
+  verify footer fields of inuse chunks, which can be used guarantee
+  that the mstate controlling malloc/free is intact.  This is a
+  streamlined version of the approach described by William Robertson
+  et al in "Run-time Detection of Heap-based Overflows" LISA'03
+  http://www.usenix.org/events/lisa03/tech/robertson.html The footer
+  of an inuse chunk holds the xor of its mstate and a random seed,
+  that is checked upon calls to free() and realloc().  This is
+  (probablistically) unguessable from outside the program, but can be
+  computed by any code successfully malloc'ing any chunk, so does not
+  itself provide protection against code that has already broken
+  security through some other means.  Unlike Robertson et al, we
+  always dynamically check addresses of all offset chunks (previous,
+  next, etc). This turns out to be cheaper than relying on hashes.
+*/
+
+#if !INSECURE
+/* Check if address a is at least as high as any from MORECORE or MMAP */
+#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
+/* Check if address of next chunk n is higher than base chunk p */
+#define ok_next(p, n)    ((char*)(p) < (char*)(n))
+/* Check if p has its cinuse bit on */
+#define ok_cinuse(p)     cinuse(p)
+/* Check if p has its pinuse bit on */
+#define ok_pinuse(p)     pinuse(p)
+
+#else /* !INSECURE */
+#define ok_address(M, a) (1)
+#define ok_next(b, n)    (1)
+#define ok_cinuse(p)     (1)
+#define ok_pinuse(p)     (1)
+#endif /* !INSECURE */
+
+#if (FOOTERS && !INSECURE)
+/* Check if (alleged) mstate m has expected magic field */
+#define ok_magic(M)      ((M)->magic == mparams.magic)
+#else  /* (FOOTERS && !INSECURE) */
+#define ok_magic(M)      (1)
+#endif /* (FOOTERS && !INSECURE) */
+
+
+/* In gcc, use __builtin_expect to minimize impact of checks */
+#if !INSECURE
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define RTCHECK(e)  __builtin_expect(e, 1)
+#else /* GNUC */
+#define RTCHECK(e)  (e)
+#endif /* GNUC */
+#else /* !INSECURE */
+#define RTCHECK(e)  (1)
+#endif /* !INSECURE */
+
+/* macros to set up inuse chunks with or without footers */
+
+#if !FOOTERS
+
+#define mark_inuse_foot(M,p,s)
+
+/* Set cinuse bit and pinuse bit of next chunk */
+#define set_inuse(M,p,s)\
+  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
+  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
+
+/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
+#define set_inuse_and_pinuse(M,p,s)\
+  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
+  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
+
+/* Set size, cinuse and pinuse bit of this chunk */
+#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
+  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
+
+#else /* FOOTERS */
+
+/* Set foot of inuse chunk to be xor of mstate and seed */
+#define mark_inuse_foot(M,p,s)\
+  (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
+
+#define get_mstate_for(p)\
+  ((mstate)(((mchunkptr)((char*)(p) +\
+    (chunksize(p))))->prev_foot ^ mparams.magic))
+
+#define set_inuse(M,p,s)\
+  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
+  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
+  mark_inuse_foot(M,p,s))
+
+#define set_inuse_and_pinuse(M,p,s)\
+  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
+  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
+ mark_inuse_foot(M,p,s))
+
+#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
+  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
+  mark_inuse_foot(M, p, s))
+
+#endif /* !FOOTERS */
+
+/* ---------------------------- setting mparams -------------------------- */
+
+/* Initialize mparams */
+static int init_mparams(void) {
+  if (mparams.page_size == 0) {
+    size_t s;
+
+    mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
+    mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
+#if MORECORE_CONTIGUOUS
+    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
+#else  /* MORECORE_CONTIGUOUS */
+    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
+#endif /* MORECORE_CONTIGUOUS */
+
+#if (FOOTERS && !INSECURE)
+    {
+#if USE_DEV_RANDOM
+      int fd;
+      unsigned char buf[sizeof(size_t)];
+      /* Try to use /dev/urandom, else fall back on using time */
+      if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
+          read(fd, buf, sizeof(buf)) == sizeof(buf)) {
+        s = *((size_t *) buf);
+        close(fd);
+      }
+      else
+#endif /* USE_DEV_RANDOM */
+        s = (size_t)(time(0) ^ (size_t)0x55555555U);
+
+      s |= (size_t)8U;    /* ensure nonzero */
+      s &= ~(size_t)7U;   /* improve chances of fault for bad values */
+
+    }
+#else /* (FOOTERS && !INSECURE) */
+    s = (size_t)0x58585858U;
+#endif /* (FOOTERS && !INSECURE) */
+    ACQUIRE_MAGIC_INIT_LOCK();
+    if (mparams.magic == 0) {
+      mparams.magic = s;
+      /* Set up lock for main malloc area */
+      INITIAL_LOCK(&gm->mutex);
+      gm->mflags = mparams.default_mflags;
+    }
+    RELEASE_MAGIC_INIT_LOCK();
+
+#if !defined(WIN32) && !defined(__OS2__)
+    mparams.page_size = malloc_getpagesize;
+    mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
+                           DEFAULT_GRANULARITY : mparams.page_size);
+#elif defined (__OS2__)
+ /* if low-memory is used, os2munmap() would break
+    if it were anything other than 64k */
+    mparams.page_size = 4096u;
+    mparams.granularity = 65536u;
+#else /* WIN32 */
+    {
+      SYSTEM_INFO system_info;
+      GetSystemInfo(&system_info);
+      mparams.page_size = system_info.dwPageSize;
+      mparams.granularity = system_info.dwAllocationGranularity;
+    }
+#endif /* WIN32 */
+
+    /* Sanity-check configuration:
+       size_t must be unsigned and as wide as pointer type.
+       ints must be at least 4 bytes.
+       alignment must be at least 8.
+       Alignment, min chunk size, and page size must all be powers of 2.
+    */
+    if ((sizeof(size_t) != sizeof(char*)) ||
+        (MAX_SIZE_T < MIN_CHUNK_SIZE)  ||
+        (sizeof(int) < 4)  ||
+        (MALLOC_ALIGNMENT < (size_t)8U) ||
+        ((MALLOC_ALIGNMENT    & (MALLOC_ALIGNMENT-SIZE_T_ONE))    != 0) ||
+        ((MCHUNK_SIZE         & (MCHUNK_SIZE-SIZE_T_ONE))         != 0) ||
+        ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||
+        ((mparams.page_size   & (mparams.page_size-SIZE_T_ONE))   != 0))
+      ABORT;
+  }
+  return 0;
+}
+
+/* support for mallopt */
+static int change_mparam(int param_number, int value) {
+  size_t val = (size_t)value;
+  init_mparams();
+  switch(param_number) {
+  case M_TRIM_THRESHOLD:
+    mparams.trim_threshold = val;
+    return 1;
+  case M_GRANULARITY:
+    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
+      mparams.granularity = val;
+      return 1;
+    }
+    else
+      return 0;
+  case M_MMAP_THRESHOLD:
+    mparams.mmap_threshold = val;
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+#if DEBUG
+/* ------------------------- Debugging Support --------------------------- */
+
+/* Check properties of any chunk, whether free, inuse, mmapped etc  */
+static void do_check_any_chunk(mstate m, mchunkptr p) {
+  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
+  assert(ok_address(m, p));
+}
+
+/* Check properties of top chunk */
+static void do_check_top_chunk(mstate m, mchunkptr p) {
+  msegmentptr sp = segment_holding(m, (char*)p);
+  size_t  sz = chunksize(p);
+  assert(sp != 0);
+  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
+  assert(ok_address(m, p));
+  assert(sz == m->topsize);
+  assert(sz > 0);
+  assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
+  assert(pinuse(p));
+  assert(!next_pinuse(p));
+}
+
+/* Check properties of (inuse) mmapped chunks */
+static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
+  size_t  sz = chunksize(p);
+  size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
+  assert(is_mmapped(p));
+  assert(use_mmap(m));
+  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
+  assert(ok_address(m, p));
+  assert(!is_small(sz));
+  assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
+  assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
+  assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
+}
+
+/* Check properties of inuse chunks */
+static void do_check_inuse_chunk(mstate m, mchunkptr p) {
+  do_check_any_chunk(m, p);
+  assert(cinuse(p));
+  assert(next_pinuse(p));
+  /* If not pinuse and not mmapped, previous chunk has OK offset */
+  assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
+  if (is_mmapped(p))
+    do_check_mmapped_chunk(m, p);
+}
+
+/* Check properties of free chunks */
+static void do_check_free_chunk(mstate m, mchunkptr p) {
+  size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
+  mchunkptr next = chunk_plus_offset(p, sz);
+  do_check_any_chunk(m, p);
+  assert(!cinuse(p));
+  assert(!next_pinuse(p));
+  assert (!is_mmapped(p));
+  if (p != m->dv && p != m->top) {
+    if (sz >= MIN_CHUNK_SIZE) {
+      assert((sz & CHUNK_ALIGN_MASK) == 0);
+      assert(is_aligned(chunk2mem(p)));
+      assert(next->prev_foot == sz);
+      assert(pinuse(p));
+      assert (next == m->top || cinuse(next));
+      assert(p->fd->bk == p);
+      assert(p->bk->fd == p);
+    }
+    else  /* markers are always of size SIZE_T_SIZE */
+      assert(sz == SIZE_T_SIZE);
+  }
+}
+
+/* Check properties of malloced chunks at the point they are malloced */
+static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
+  if (mem != 0) {
+    mchunkptr p = mem2chunk(mem);
+    size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
+    do_check_inuse_chunk(m, p);
+    assert((sz & CHUNK_ALIGN_MASK) == 0);
+    assert(sz >= MIN_CHUNK_SIZE);
+    assert(sz >= s);
+    /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
+    assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
+  }
+}
+
+/* Check a tree and its subtrees.  */
+static void do_check_tree(mstate m, tchunkptr t) {
+  tchunkptr head = 0;
+  tchunkptr u = t;
+  bindex_t tindex = t->index;
+  size_t tsize = chunksize(t);
+  bindex_t idx;
+  compute_tree_index(tsize, idx);
+  assert(tindex == idx);
+  assert(tsize >= MIN_LARGE_SIZE);
+  assert(tsize >= minsize_for_tree_index(idx));
+  assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
+
+  do { /* traverse through chain of same-sized nodes */
+    do_check_any_chunk(m, ((mchunkptr)u));
+    assert(u->index == tindex);
+    assert(chunksize(u) == tsize);
+    assert(!cinuse(u));
+    assert(!next_pinuse(u));
+    assert(u->fd->bk == u);
+    assert(u->bk->fd == u);
+    if (u->parent == 0) {
+      assert(u->child[0] == 0);
+      assert(u->child[1] == 0);
+    }
+    else {
+      assert(head == 0); /* only one node on chain has parent */
+      head = u;
+      assert(u->parent != u);
+      assert (u->parent->child[0] == u ||
+              u->parent->child[1] == u ||
+              *((tbinptr*)(u->parent)) == u);
+      if (u->child[0] != 0) {
+        assert(u->child[0]->parent == u);
+        assert(u->child[0] != u);
+        do_check_tree(m, u->child[0]);
+      }
+      if (u->child[1] != 0) {
+        assert(u->child[1]->parent == u);
+        assert(u->child[1] != u);
+        do_check_tree(m, u->child[1]);
+      }
+      if (u->child[0] != 0 && u->child[1] != 0) {
+        assert(chunksize(u->child[0]) < chunksize(u->child[1]));
+      }
+    }
+    u = u->fd;
+  } while (u != t);
+  assert(head != 0);
+}
+
+/*  Check all the chunks in a treebin.  */
+static void do_check_treebin(mstate m, bindex_t i) {
+  tbinptr* tb = treebin_at(m, i);
+  tchunkptr t = *tb;
+  int empty = (m->treemap & (1U << i)) == 0;
+  if (t == 0)
+    assert(empty);
+  if (!empty)
+    do_check_tree(m, t);
+}
+
+/*  Check all the chunks in a smallbin.  */
+static void do_check_smallbin(mstate m, bindex_t i) {
+  sbinptr b = smallbin_at(m, i);
+  mchunkptr p = b->bk;
+  unsigned int empty = (m->smallmap & (1U << i)) == 0;
+  if (p == b)
+    assert(empty);
+  if (!empty) {
+    for (; p != b; p = p->bk) {
+      size_t size = chunksize(p);
+      mchunkptr q;
+      /* each chunk claims to be free */
+      do_check_free_chunk(m, p);
+      /* chunk belongs in bin */
+      assert(small_index(size) == i);
+      assert(p->bk == b || chunksize(p->bk) == chunksize(p));
+      /* chunk is followed by an inuse chunk */
+      q = next_chunk(p);
+      if (q->head != FENCEPOST_HEAD)
+        do_check_inuse_chunk(m, q);
+    }
+  }
+}
+
+/* Find x in a bin. Used in other check functions. */
+static int bin_find(mstate m, mchunkptr x) {
+  size_t size = chunksize(x);
+  if (is_small(size)) {
+    bindex_t sidx = small_index(size);
+    sbinptr b = smallbin_at(m, sidx);
+    if (smallmap_is_marked(m, sidx)) {
+      mchunkptr p = b;
+      do {
+        if (p == x)
+          return 1;
+      } while ((p = p->fd) != b);
+    }
+  }
+  else {
+    bindex_t tidx;
+    compute_tree_index(size, tidx);
+    if (treemap_is_marked(m, tidx)) {
+      tchunkptr t = *treebin_at(m, tidx);
+      size_t sizebits = size << leftshift_for_tree_index(tidx);
+      while (t != 0 && chunksize(t) != size) {
+        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
+        sizebits <<= 1;
+      }
+      if (t != 0) {
+        tchunkptr u = t;
+        do {
+          if (u == (tchunkptr)x)
+            return 1;
+        } while ((u = u->fd) != t);
+      }
+    }
+  }
+  return 0;
+}
+
+/* Traverse each chunk and check it; return total */
+static size_t traverse_and_check(mstate m) {
+  size_t sum = 0;
+  if (is_initialized(m)) {
+    msegmentptr s = &m->seg;
+    sum += m->topsize + TOP_FOOT_SIZE;
+    while (s != 0) {
+      mchunkptr q = align_as_chunk(s->base);
+      mchunkptr lastq = 0;
+      assert(pinuse(q));
+      while (segment_holds(s, q) &&
+             q != m->top && q->head != FENCEPOST_HEAD) {
+        sum += chunksize(q);
+        if (cinuse(q)) {
+          assert(!bin_find(m, q));
+          do_check_inuse_chunk(m, q);
+        }
+        else {
+          assert(q == m->dv || bin_find(m, q));
+          assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
+          do_check_free_chunk(m, q);
+        }
+        lastq = q;
+        q = next_chunk(q);
+      }
+      s = s->next;
+    }
+  }
+  return sum;
+}
+
+/* Check all properties of malloc_state. */
+static void do_check_malloc_state(mstate m) {
+  bindex_t i;
+  size_t total;
+  /* check bins */
+  for (i = 0; i < NSMALLBINS; ++i)
+    do_check_smallbin(m, i);
+  for (i = 0; i < NTREEBINS; ++i)
+    do_check_treebin(m, i);
+
+  if (m->dvsize != 0) { /* check dv chunk */
+    do_check_any_chunk(m, m->dv);
+    assert(m->dvsize == chunksize(m->dv));
+    assert(m->dvsize >= MIN_CHUNK_SIZE);
+    assert(bin_find(m, m->dv) == 0);
+  }
+
+  if (m->top != 0) {   /* check top chunk */
+    do_check_top_chunk(m, m->top);
+    assert(m->topsize == chunksize(m->top));
+    assert(m->topsize > 0);
+    assert(bin_find(m, m->top) == 0);
+  }
+
+  total = traverse_and_check(m);
+  assert(total <= m->footprint);
+  assert(m->footprint <= m->max_footprint);
+}
+#endif /* DEBUG */
+
+/* ----------------------------- statistics ------------------------------ */
+
+#if !NO_MALLINFO
+static struct mallinfo internal_mallinfo(mstate m) {
+  struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+  if (!PREACTION(m)) {
+    check_malloc_state(m);
+    if (is_initialized(m)) {
+      size_t nfree = SIZE_T_ONE; /* top always free */
+      size_t mfree = m->topsize + TOP_FOOT_SIZE;
+      size_t sum = mfree;
+      msegmentptr s = &m->seg;
+      while (s != 0) {
+        mchunkptr q = align_as_chunk(s->base);
+        while (segment_holds(s, q) &&
+               q != m->top && q->head != FENCEPOST_HEAD) {
+          size_t sz = chunksize(q);
+          sum += sz;
+          if (!cinuse(q)) {
+            mfree += sz;
+            ++nfree;
+          }
+          q = next_chunk(q);
+        }
+        s = s->next;
+      }
+
+      nm.arena    = sum;
+      nm.ordblks  = nfree;
+      nm.hblkhd   = m->footprint - sum;
+      nm.usmblks  = m->max_footprint;
+      nm.uordblks = m->footprint - mfree;
+      nm.fordblks = mfree;
+      nm.keepcost = m->topsize;
+    }
+
+    POSTACTION(m);
+  }
+  return nm;
+}
+#endif /* !NO_MALLINFO */
+
+static void internal_malloc_stats(mstate m) {
+  if (!PREACTION(m)) {
+    size_t maxfp = 0;
+    size_t fp = 0;
+    size_t used = 0;
+    check_malloc_state(m);
+    if (is_initialized(m)) {
+      msegmentptr s = &m->seg;
+      maxfp = m->max_footprint;
+      fp = m->footprint;
+      used = fp - (m->topsize + TOP_FOOT_SIZE);
+
+      while (s != 0) {
+        mchunkptr q = align_as_chunk(s->base);
+        while (segment_holds(s, q) &&
+               q != m->top && q->head != FENCEPOST_HEAD) {
+          if (!cinuse(q))
+            used -= chunksize(q);
+          q = next_chunk(q);
+        }
+        s = s->next;
+      }
+    }
+
+    fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
+    fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
+    fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
+
+    POSTACTION(m);
+  }
+}
+
+/* ----------------------- Operations on smallbins ----------------------- */
+
+/*
+  Various forms of linking and unlinking are defined as macros.  Even
+  the ones for trees, which are very long but have very short typical
+  paths.  This is ugly but reduces reliance on inlining support of
+  compilers.
+*/
+
+/* Link a free chunk into a smallbin  */
+#define insert_small_chunk(M, P, S) {\
+  bindex_t I  = small_index(S);\
+  mchunkptr B = smallbin_at(M, I);\
+  mchunkptr F = B;\
+  assert(S >= MIN_CHUNK_SIZE);\
+  if (!smallmap_is_marked(M, I))\
+    mark_smallmap(M, I);\
+  else if (RTCHECK(ok_address(M, B->fd)))\
+    F = B->fd;\
+  else {\
+    CORRUPTION_ERROR_ACTION(M);\
+  }\
+  B->fd = P;\
+  F->bk = P;\
+  P->fd = F;\
+  P->bk = B;\
+}
+
+/* Unlink a chunk from a smallbin  */
+#define unlink_small_chunk(M, P, S) {\
+  mchunkptr F = P->fd;\
+  mchunkptr B = P->bk;\
+  bindex_t I = small_index(S);\
+  assert(P != B);\
+  assert(P != F);\
+  assert(chunksize(P) == small_index2size(I));\
+  if (F == B)\
+    clear_smallmap(M, I);\
+  else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
+                   (B == smallbin_at(M,I) || ok_address(M, B)))) {\
+    F->bk = B;\
+    B->fd = F;\
+  }\
+  else {\
+    CORRUPTION_ERROR_ACTION(M);\
+  }\
+}
+
+/* Unlink the first chunk from a smallbin */
+#define unlink_first_small_chunk(M, B, P, I) {\
+  mchunkptr F = P->fd;\
+  assert(P != B);\
+  assert(P != F);\
+  assert(chunksize(P) == small_index2size(I));\
+  if (B == F)\
+    clear_smallmap(M, I);\
+  else if (RTCHECK(ok_address(M, F))) {\
+    B->fd = F;\
+    F->bk = B;\
+  }\
+  else {\
+    CORRUPTION_ERROR_ACTION(M);\
+  }\
+}
+
+/* Replace dv node, binning the old one */
+/* Used only when dvsize known to be small */
+#define replace_dv(M, P, S) {\
+  size_t DVS = M->dvsize;\
+  if (DVS != 0) {\
+    mchunkptr DV = M->dv;\
+    assert(is_small(DVS));\
+    insert_small_chunk(M, DV, DVS);\
+  }\
+  M->dvsize = S;\
+  M->dv = P;\
+}
+
+/* ------------------------- Operations on trees ------------------------- */
+
+/* Insert chunk into tree */
+#define insert_large_chunk(M, X, S) {\
+  tbinptr* H;\
+  bindex_t I;\
+  compute_tree_index(S, I);\
+  H = treebin_at(M, I);\
+  X->index = I;\
+  X->child[0] = X->child[1] = 0;\
+  if (!treemap_is_marked(M, I)) {\
+    mark_treemap(M, I);\
+    *H = X;\
+    X->parent = (tchunkptr)H;\
+    X->fd = X->bk = X;\
+  }\
+  else {\
+    tchunkptr T = *H;\
+    size_t K = S << leftshift_for_tree_index(I);\
+    for (;;) {\
+      if (chunksize(T) != S) {\
+        tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
+        K <<= 1;\
+        if (*C != 0)\
+          T = *C;\
+        else if (RTCHECK(ok_address(M, C))) {\
+          *C = X;\
+          X->parent = T;\
+          X->fd = X->bk = X;\
+          break;\
+        }\
+        else {\
+          CORRUPTION_ERROR_ACTION(M);\
+          break;\
+        }\
+      }\
+      else {\
+        tchunkptr F = T->fd;\
+        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
+          T->fd = F->bk = X;\
+          X->fd = F;\
+          X->bk = T;\
+          X->parent = 0;\
+          break;\
+        }\
+        else {\
+          CORRUPTION_ERROR_ACTION(M);\
+          break;\
+        }\
+      }\
+    }\
+  }\
+}
+
+/*
+  Unlink steps:
+
+  1. If x is a chained node, unlink it from its same-sized fd/bk links
+     and choose its bk node as its replacement.
+  2. If x was the last node of its size, but not a leaf node, it must
+     be replaced with a leaf node (not merely one with an open left or
+     right), to make sure that lefts and rights of descendents
+     correspond properly to bit masks.  We use the rightmost descendent
+     of x.  We could use any other leaf, but this is easy to locate and
+     tends to counteract removal of leftmosts elsewhere, and so keeps
+     paths shorter than minimally guaranteed.  This doesn't loop much
+     because on average a node in a tree is near the bottom.
+  3. If x is the base of a chain (i.e., has parent links) relink
+     x's parent and children to x's replacement (or null if none).
+*/
+
+#define unlink_large_chunk(M, X) {\
+  tchunkptr XP = X->parent;\
+  tchunkptr R;\
+  if (X->bk != X) {\
+    tchunkptr F = X->fd;\
+    R = X->bk;\
+    if (RTCHECK(ok_address(M, F))) {\
+      F->bk = R;\
+      R->fd = F;\
+    }\
+    else {\
+      CORRUPTION_ERROR_ACTION(M);\
+    }\
+  }\
+  else {\
+    tchunkptr* RP;\
+    if (((R = *(RP = &(X->child[1]))) != 0) ||\
+        ((R = *(RP = &(X->child[0]))) != 0)) {\
+      tchunkptr* CP;\
+      while ((*(CP = &(R->child[1])) != 0) ||\
+             (*(CP = &(R->child[0])) != 0)) {\
+        R = *(RP = CP);\
+      }\
+      if (RTCHECK(ok_address(M, RP)))\
+        *RP = 0;\
+      else {\
+        CORRUPTION_ERROR_ACTION(M);\
+      }\
+    }\
+  }\
+  if (XP != 0) {\
+    tbinptr* H = treebin_at(M, X->index);\
+    if (X == *H) {\
+      if ((*H = R) == 0) \
+        clear_treemap(M, X->index);\
+    }\
+    else if (RTCHECK(ok_address(M, XP))) {\
+      if (XP->child[0] == X) \
+        XP->child[0] = R;\
+      else \
+        XP->child[1] = R;\
+    }\
+    else\
+      CORRUPTION_ERROR_ACTION(M);\
+    if (R != 0) {\
+      if (RTCHECK(ok_address(M, R))) {\
+        tchunkptr C0, C1;\
+        R->parent = XP;\
+        if ((C0 = X->child[0]) != 0) {\
+          if (RTCHECK(ok_address(M, C0))) {\
+            R->child[0] = C0;\
+            C0->parent = R;\
+          }\
+          else\
+            CORRUPTION_ERROR_ACTION(M);\
+        }\
+        if ((C1 = X->child[1]) != 0) {\
+          if (RTCHECK(ok_address(M, C1))) {\
+            R->child[1] = C1;\
+            C1->parent = R;\
+          }\
+          else\
+            CORRUPTION_ERROR_ACTION(M);\
+        }\
+      }\
+      else\
+        CORRUPTION_ERROR_ACTION(M);\
+    }\
+  }\
+}
+
+/* Relays to large vs small bin operations */
+
+#define insert_chunk(M, P, S)\
+  if (is_small(S)) insert_small_chunk(M, P, S)\
+  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
+
+#define unlink_chunk(M, P, S)\
+  if (is_small(S)) unlink_small_chunk(M, P, S)\
+  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
+
+
+/* Relays to internal calls to malloc/free from realloc, memalign etc */
+
+#if ONLY_MSPACES
+#define internal_malloc(m, b) mspace_malloc(m, b)
+#define internal_free(m, mem) mspace_free(m,mem);
+#else /* ONLY_MSPACES */
+#if MSPACES
+#define internal_malloc(m, b)\
+   (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
+#define internal_free(m, mem)\
+   if (m == gm) dlfree(mem); else mspace_free(m,mem);
+#else /* MSPACES */
+#define internal_malloc(m, b) dlmalloc(b)
+#define internal_free(m, mem) dlfree(mem)
+#endif /* MSPACES */
+#endif /* ONLY_MSPACES */
+
+/* -----------------------  Direct-mmapping chunks ----------------------- */
+
+/*
+  Directly mmapped chunks are set up with an offset to the start of
+  the mmapped region stored in the prev_foot field of the chunk. This
+  allows reconstruction of the required argument to MUNMAP when freed,
+  and also allows adjustment of the returned chunk to meet alignment
+  requirements (especially in memalign).  There is also enough space
+  allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain
+  the PINUSE bit so frees can be checked.
+*/
+
+/* Malloc using mmap */
+static void* mmap_alloc(mstate m, size_t nb) {
+  size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
+  if (mmsize > nb) {     /* Check for wrap around 0 */
+    char* mm = (char*)(DIRECT_MMAP(mmsize));
+    if (mm != CMFAIL) {
+      size_t offset = align_offset(chunk2mem(mm));
+      size_t psize = mmsize - offset - MMAP_FOOT_PAD;
+      mchunkptr p = (mchunkptr)(mm + offset);
+      p->prev_foot = offset | IS_MMAPPED_BIT;
+      (p)->head = (psize|CINUSE_BIT);
+      mark_inuse_foot(m, p, psize);
+      chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
+      chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
+
+      if (mm < m->least_addr)
+        m->least_addr = mm;
+      if ((m->footprint += mmsize) > m->max_footprint)
+        m->max_footprint = m->footprint;
+      assert(is_aligned(chunk2mem(p)));
+      check_mmapped_chunk(m, p);
+      return chunk2mem(p);
+    }
+  }
+  return 0;
+}
+
+/* Realloc using mmap */
+static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
+  size_t oldsize = chunksize(oldp);
+  if (is_small(nb)) /* Can't shrink mmap regions below small size */
+    return 0;
+  /* Keep old chunk if big enough but not too big */
+  if (oldsize >= nb + SIZE_T_SIZE &&
+      (oldsize - nb) <= (mparams.granularity << 1))
+    return oldp;
+  else {
+    size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
+    size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
+    size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
+                                         CHUNK_ALIGN_MASK);
+    char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
+                                  oldmmsize, newmmsize, 1);
+    if (cp != CMFAIL) {
+      mchunkptr newp = (mchunkptr)(cp + offset);
+      size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
+      newp->head = (psize|CINUSE_BIT);
+      mark_inuse_foot(m, newp, psize);
+      chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
+      chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
+
+      if (cp < m->least_addr)
+        m->least_addr = cp;
+      if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
+        m->max_footprint = m->footprint;
+      check_mmapped_chunk(m, newp);
+      return newp;
+    }
+  }
+  return 0;
+}
+
+/* -------------------------- mspace management -------------------------- */
+
+/* Initialize top chunk and its size */
+static void init_top(mstate m, mchunkptr p, size_t psize) {
+  /* Ensure alignment */
+  size_t offset = align_offset(chunk2mem(p));
+  p = (mchunkptr)((char*)p + offset);
+  psize -= offset;
+
+  m->top = p;
+  m->topsize = psize;
+  p->head = psize | PINUSE_BIT;
+  /* set size of fake trailing chunk holding overhead space only once */
+  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
+  m->trim_check = mparams.trim_threshold; /* reset on each update */
+}
+
+/* Initialize bins for a new mstate that is otherwise zeroed out */
+static void init_bins(mstate m) {
+  /* Establish circular links for smallbins */
+  bindex_t i;
+  for (i = 0; i < NSMALLBINS; ++i) {
+    sbinptr bin = smallbin_at(m,i);
+    bin->fd = bin->bk = bin;
+  }
+}
+
+#if PROCEED_ON_ERROR
+
+/* default corruption action */
+static void reset_on_error(mstate m) {
+  int i;
+  ++malloc_corruption_error_count;
+  /* Reinitialize fields to forget about all memory */
+  m->smallbins = m->treebins = 0;
+  m->dvsize = m->topsize = 0;
+  m->seg.base = 0;
+  m->seg.size = 0;
+  m->seg.next = 0;
+  m->top = m->dv = 0;
+  for (i = 0; i < NTREEBINS; ++i)
+    *treebin_at(m, i) = 0;
+  init_bins(m);
+}
+#endif /* PROCEED_ON_ERROR */
+
+/* Allocate chunk and prepend remainder with chunk in successor base. */
+static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
+                           size_t nb) {
+  mchunkptr p = align_as_chunk(newbase);
+  mchunkptr oldfirst = align_as_chunk(oldbase);
+  size_t psize = (char*)oldfirst - (char*)p;
+  mchunkptr q = chunk_plus_offset(p, nb);
+  size_t qsize = psize - nb;
+  set_size_and_pinuse_of_inuse_chunk(m, p, nb);
+
+  assert((char*)oldfirst > (char*)q);
+  assert(pinuse(oldfirst));
+  assert(qsize >= MIN_CHUNK_SIZE);
+
+  /* consolidate remainder with first chunk of old base */
+  if (oldfirst == m->top) {
+    size_t tsize = m->topsize += qsize;
+    m->top = q;
+    q->head = tsize | PINUSE_BIT;
+    check_top_chunk(m, q);
+  }
+  else if (oldfirst == m->dv) {
+    size_t dsize = m->dvsize += qsize;
+    m->dv = q;
+    set_size_and_pinuse_of_free_chunk(q, dsize);
+  }
+  else {
+    if (!cinuse(oldfirst)) {
+      size_t nsize = chunksize(oldfirst);
+      unlink_chunk(m, oldfirst, nsize);
+      oldfirst = chunk_plus_offset(oldfirst, nsize);
+      qsize += nsize;
+    }
+    set_free_with_pinuse(q, qsize, oldfirst);
+    insert_chunk(m, q, qsize);
+    check_free_chunk(m, q);
+  }
+
+  check_malloced_chunk(m, chunk2mem(p), nb);
+  return chunk2mem(p);
+}
+
+
+/* Add a segment to hold a new noncontiguous region */
+static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
+  /* Determine locations and sizes of segment, fenceposts, old top */
+  char* old_top = (char*)m->top;
+  msegmentptr oldsp = segment_holding(m, old_top);
+  char* old_end = oldsp->base + oldsp->size;
+  size_t ssize = pad_request(sizeof(struct malloc_segment));
+  char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
+  size_t offset = align_offset(chunk2mem(rawsp));
+  char* asp = rawsp + offset;
+  char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
+  mchunkptr sp = (mchunkptr)csp;
+  msegmentptr ss = (msegmentptr)(chunk2mem(sp));
+  mchunkptr tnext = chunk_plus_offset(sp, ssize);
+  mchunkptr p = tnext;
+  int nfences = 0;
+
+  /* reset top to new space */
+  init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
+
+  /* Set up segment record */
+  assert(is_aligned(ss));
+  set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
+  *ss = m->seg; /* Push current record */
+  m->seg.base = tbase;
+  m->seg.size = tsize;
+  set_segment_flags(&m->seg, mmapped);
+  m->seg.next = ss;
+
+  /* Insert trailing fenceposts */
+  for (;;) {
+    mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
+    p->head = FENCEPOST_HEAD;
+    ++nfences;
+    if ((char*)(&(nextp->head)) < old_end)
+      p = nextp;
+    else
+      break;
+  }
+  assert(nfences >= 2);
+
+  /* Insert the rest of old top into a bin as an ordinary free chunk */
+  if (csp != old_top) {
+    mchunkptr q = (mchunkptr)old_top;
+    size_t psize = csp - old_top;
+    mchunkptr tn = chunk_plus_offset(q, psize);
+    set_free_with_pinuse(q, psize, tn);
+    insert_chunk(m, q, psize);
+  }
+
+  check_top_chunk(m, m->top);
+}
+
+/* -------------------------- System allocation -------------------------- */
+
+/* Get memory from system using MORECORE or MMAP */
+static void* sys_alloc(mstate m, size_t nb) {
+  char* tbase = CMFAIL;
+  size_t tsize = 0;
+  flag_t mmap_flag = 0;
+
+  init_mparams();
+
+  /* Directly map large chunks */
+  if (use_mmap(m) && nb >= mparams.mmap_threshold) {
+    void* mem = mmap_alloc(m, nb);
+    if (mem != 0)
+      return mem;
+  }
+
+  /*
+    Try getting memory in any of three ways (in most-preferred to
+    least-preferred order):
+    1. A call to MORECORE that can normally contiguously extend memory.
+       (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
+       or main space is mmapped or a previous contiguous call failed)
+    2. A call to MMAP new space (disabled if not HAVE_MMAP).
+       Note that under the default settings, if MORECORE is unable to
+       fulfill a request, and HAVE_MMAP is true, then mmap is
+       used as a noncontiguous system allocator. This is a useful backup
+       strategy for systems with holes in address spaces -- in this case
+       sbrk cannot contiguously expand the heap, but mmap may be able to
+       find space.
+    3. A call to MORECORE that cannot usually contiguously extend memory.
+       (disabled if not HAVE_MORECORE)
+  */
+
+  if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
+    char* br = CMFAIL;
+    msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
+    size_t asize = 0;
+    ACQUIRE_MORECORE_LOCK();
+
+    if (ss == 0) {  /* First time through or recovery */
+      char* base = (char*)CALL_MORECORE(0);
+      if (base != CMFAIL) {
+        asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
+        /* Adjust to end on a page boundary */
+        if (!is_page_aligned(base))
+          asize += (page_align((size_t)base) - (size_t)base);
+        /* Can't call MORECORE if size is negative when treated as signed */
+        if (asize < HALF_MAX_SIZE_T &&
+            (br = (char*)(CALL_MORECORE(asize))) == base) {
+          tbase = base;
+          tsize = asize;
+        }
+      }
+    }
+    else {
+      /* Subtract out existing available top space from MORECORE request. */
+      asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE);
+      /* Use mem here only if it did continuously extend old space */
+      if (asize < HALF_MAX_SIZE_T &&
+          (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
+        tbase = br;
+        tsize = asize;
+      }
+    }
+
+    if (tbase == CMFAIL) {    /* Cope with partial failure */
+      if (br != CMFAIL) {    /* Try to use/extend the space we did get */
+        if (asize < HALF_MAX_SIZE_T &&
+            asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
+          size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize);
+          if (esize < HALF_MAX_SIZE_T) {
+            char* end = (char*)CALL_MORECORE(esize);
+            if (end != CMFAIL)
+              asize += esize;
+            else {            /* Can't use; try to release */
+              (void)CALL_MORECORE(-asize);
+              br = CMFAIL;
+            }
+          }
+        }
+      }
+      if (br != CMFAIL) {    /* Use the space we did get */
+        tbase = br;
+        tsize = asize;
+      }
+      else
+        disable_contiguous(m); /* Don't try contiguous path in the future */
+    }
+
+    RELEASE_MORECORE_LOCK();
+  }
+
+  if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
+    size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
+    size_t rsize = granularity_align(req);
+    if (rsize > nb) { /* Fail if wraps around zero */
+      char* mp = (char*)(CALL_MMAP(rsize));
+      if (mp != CMFAIL) {
+        tbase = mp;
+        tsize = rsize;
+        mmap_flag = IS_MMAPPED_BIT;
+      }
+    }
+  }
+
+  if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
+    size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
+    if (asize < HALF_MAX_SIZE_T) {
+      char* br = CMFAIL;
+      char* end = CMFAIL;
+      ACQUIRE_MORECORE_LOCK();
+      br = (char*)(CALL_MORECORE(asize));
+      end = (char*)(CALL_MORECORE(0));
+      RELEASE_MORECORE_LOCK();
+      if (br != CMFAIL && end != CMFAIL && br < end) {
+        size_t ssize = end - br;
+        if (ssize > nb + TOP_FOOT_SIZE) {
+          tbase = br;
+          tsize = ssize;
+        }
+      }
+    }
+  }
+
+  if (tbase != CMFAIL) {
+
+    if ((m->footprint += tsize) > m->max_footprint)
+      m->max_footprint = m->footprint;
+
+    if (!is_initialized(m)) { /* first-time initialization */
+      m->seg.base = m->least_addr = tbase;
+      m->seg.size = tsize;
+      set_segment_flags(&m->seg, mmap_flag);
+      m->magic = mparams.magic;
+      init_bins(m);
+      if (is_global(m)) 
+        init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
+      else {
+        /* Offset top by embedded malloc_state */
+        mchunkptr mn = next_chunk(mem2chunk(m));
+        init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
+      }
+    }
+
+    else {
+      /* Try to merge with an existing segment */
+      msegmentptr sp = &m->seg;
+      while (sp != 0 && tbase != sp->base + sp->size)
+        sp = sp->next;
+      if (sp != 0 &&
+          !is_extern_segment(sp) &&
+	  check_segment_merge(sp, tbase, tsize) &&
+          (get_segment_flags(sp) & IS_MMAPPED_BIT) == mmap_flag &&
+          segment_holds(sp, m->top)) { /* append */
+        sp->size += tsize;
+        init_top(m, m->top, m->topsize + tsize);
+      }
+      else {
+        if (tbase < m->least_addr)
+          m->least_addr = tbase;
+        sp = &m->seg;
+        while (sp != 0 && sp->base != tbase + tsize)
+          sp = sp->next;
+        if (sp != 0 &&
+            !is_extern_segment(sp) &&
+	    check_segment_merge(sp, tbase, tsize) &&
+            (get_segment_flags(sp) & IS_MMAPPED_BIT) == mmap_flag) {
+          char* oldbase = sp->base;
+          sp->base = tbase;
+          sp->size += tsize;
+          return prepend_alloc(m, tbase, oldbase, nb);
+        }
+        else
+          add_segment(m, tbase, tsize, mmap_flag);
+      }
+    }
+
+    if (nb < m->topsize) { /* Allocate from new or extended top space */
+      size_t rsize = m->topsize -= nb;
+      mchunkptr p = m->top;
+      mchunkptr r = m->top = chunk_plus_offset(p, nb);
+      r->head = rsize | PINUSE_BIT;
+      set_size_and_pinuse_of_inuse_chunk(m, p, nb);
+      check_top_chunk(m, m->top);
+      check_malloced_chunk(m, chunk2mem(p), nb);
+      return chunk2mem(p);
+    }
+  }
+
+  MALLOC_FAILURE_ACTION;
+  return 0;
+}
+
+/* -----------------------  system deallocation -------------------------- */
+
+/* Unmap and unlink any mmapped segments that don't contain used chunks */
+static size_t release_unused_segments(mstate m) {
+  size_t released = 0;
+  msegmentptr pred = &m->seg;
+  msegmentptr sp = pred->next;
+  while (sp != 0) {
+    char* base = sp->base;
+    size_t size = sp->size;
+    msegmentptr next = sp->next;
+    if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
+      mchunkptr p = align_as_chunk(base);
+      size_t psize = chunksize(p);
+      /* Can unmap if first chunk holds entire segment and not pinned */
+      if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
+        tchunkptr tp = (tchunkptr)p;
+        assert(segment_holds(sp, (char*)sp));
+        if (p == m->dv) {
+          m->dv = 0;
+          m->dvsize = 0;
+        }
+        else {
+          unlink_large_chunk(m, tp);
+        }
+        if (CALL_MUNMAP(base, size) == 0) {
+          released += size;
+          m->footprint -= size;
+          /* unlink obsoleted record */
+          sp = pred;
+          sp->next = next;
+        }
+        else { /* back out if cannot unmap */
+          insert_large_chunk(m, tp, psize);
+        }
+      }
+    }
+    pred = sp;
+    sp = next;
+  }
+  return released;
+}
+
+static int sys_trim(mstate m, size_t pad) {
+  size_t released = 0;
+  if (pad < MAX_REQUEST && is_initialized(m)) {
+    pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
+
+    if (m->topsize > pad) {
+      /* Shrink top space in granularity-size units, keeping at least one */
+      size_t unit = mparams.granularity;
+      size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
+                      SIZE_T_ONE) * unit;
+      msegmentptr sp = segment_holding(m, (char*)m->top);
+
+      if (!is_extern_segment(sp)) {
+        if (is_mmapped_segment(sp)) {
+          if (HAVE_MMAP &&
+              sp->size >= extra &&
+              !has_segment_link(m, sp)) { /* can't shrink if pinned */
+            size_t newsize = sp->size - extra;
+            /* Prefer mremap, fall back to munmap */
+            if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
+                (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
+              released = extra;
+            }
+          }
+        }
+        else if (HAVE_MORECORE) {
+          if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
+            extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
+          ACQUIRE_MORECORE_LOCK();
+          {
+            /* Make sure end of memory is where we last set it. */
+            char* old_br = (char*)(CALL_MORECORE(0));
+            if (old_br == sp->base + sp->size) {
+              char* rel_br = (char*)(CALL_MORECORE(-extra));
+              char* new_br = (char*)(CALL_MORECORE(0));
+              if (rel_br != CMFAIL && new_br < old_br)
+                released = old_br - new_br;
+            }
+          }
+          RELEASE_MORECORE_LOCK();
+        }
+      }
+
+      if (released != 0) {
+        sp->size -= released;
+        m->footprint -= released;
+        init_top(m, m->top, m->topsize - released);
+        check_top_chunk(m, m->top);
+      }
+    }
+
+    /* Unmap any unused mmapped segments */
+    if (HAVE_MMAP) 
+      released += release_unused_segments(m);
+
+    /* On failure, disable autotrim to avoid repeated failed future calls */
+    if (released == 0)
+      m->trim_check = MAX_SIZE_T;
+  }
+
+  return (released != 0)? 1 : 0;
+}
+
+/* ---------------------------- malloc support --------------------------- */
+
+/* allocate a large request from the best fitting chunk in a treebin */
+static void* tmalloc_large(mstate m, size_t nb) {
+  tchunkptr v = 0;
+  size_t rsize = -nb; /* Unsigned negation */
+  tchunkptr t;
+  bindex_t idx;
+  compute_tree_index(nb, idx);
+
+  if ((t = *treebin_at(m, idx)) != 0) {
+    /* Traverse tree for this bin looking for node with size == nb */
+    size_t sizebits = nb << leftshift_for_tree_index(idx);
+    tchunkptr rst = 0;  /* The deepest untaken right subtree */
+    for (;;) {
+      tchunkptr rt;
+      size_t trem = chunksize(t) - nb;
+      if (trem < rsize) {
+        v = t;
+        if ((rsize = trem) == 0)
+          break;
+      }
+      rt = t->child[1];
+      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
+      if (rt != 0 && rt != t)
+        rst = rt;
+      if (t == 0) {
+        t = rst; /* set t to least subtree holding sizes > nb */
+        break;
+      }
+      sizebits <<= 1;
+    }
+  }
+
+  if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
+    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
+    if (leftbits != 0) {
+      bindex_t i;
+      binmap_t leastbit = least_bit(leftbits);
+      compute_bit2idx(leastbit, i);
+      t = *treebin_at(m, i);
+    }
+  }
+
+  while (t != 0) { /* find smallest of tree or subtree */
+    size_t trem = chunksize(t) - nb;
+    if (trem < rsize) {
+      rsize = trem;
+      v = t;
+    }
+    t = leftmost_child(t);
+  }
+
+  /*  If dv is a better fit, return 0 so malloc will use it */
+  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
+    if (RTCHECK(ok_address(m, v))) { /* split */
+      mchunkptr r = chunk_plus_offset(v, nb);
+      assert(chunksize(v) == rsize + nb);
+      if (RTCHECK(ok_next(v, r))) {
+        unlink_large_chunk(m, v);
+        if (rsize < MIN_CHUNK_SIZE)
+          set_inuse_and_pinuse(m, v, (rsize + nb));
+        else {
+          set_size_and_pinuse_of_inuse_chunk(m, v, nb);
+          set_size_and_pinuse_of_free_chunk(r, rsize);
+          insert_chunk(m, r, rsize);
+        }
+        return chunk2mem(v);
+      }
+    }
+    CORRUPTION_ERROR_ACTION(m);
+  }
+  return 0;
+}
+
+/* allocate a small request from the best fitting chunk in a treebin */
+static void* tmalloc_small(mstate m, size_t nb) {
+  tchunkptr t, v;
+  size_t rsize;
+  bindex_t i;
+  binmap_t leastbit = least_bit(m->treemap);
+  compute_bit2idx(leastbit, i);
+
+  v = t = *treebin_at(m, i);
+  rsize = chunksize(t) - nb;
+
+  while ((t = leftmost_child(t)) != 0) {
+    size_t trem = chunksize(t) - nb;
+    if (trem < rsize) {
+      rsize = trem;
+      v = t;
+    }
+  }
+
+  if (RTCHECK(ok_address(m, v))) {
+    mchunkptr r = chunk_plus_offset(v, nb);
+    assert(chunksize(v) == rsize + nb);
+    if (RTCHECK(ok_next(v, r))) {
+      unlink_large_chunk(m, v);
+      if (rsize < MIN_CHUNK_SIZE)
+        set_inuse_and_pinuse(m, v, (rsize + nb));
+      else {
+        set_size_and_pinuse_of_inuse_chunk(m, v, nb);
+        set_size_and_pinuse_of_free_chunk(r, rsize);
+        replace_dv(m, r, rsize);
+      }
+      return chunk2mem(v);
+    }
+  }
+
+  CORRUPTION_ERROR_ACTION(m);
+  return 0;
+}
+
+/* --------------------------- realloc support --------------------------- */
+
+static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
+  if (bytes >= MAX_REQUEST) {
+    MALLOC_FAILURE_ACTION;
+    return 0;
+  }
+  if (!PREACTION(m)) {
+    mchunkptr oldp = mem2chunk(oldmem);
+    size_t oldsize = chunksize(oldp);
+    mchunkptr next = chunk_plus_offset(oldp, oldsize);
+    mchunkptr newp = 0;
+    void* extra = 0;
+
+    /* Try to either shrink or extend into top. Else malloc-copy-free */
+
+    if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
+                ok_next(oldp, next) && ok_pinuse(next))) {
+      size_t nb = request2size(bytes);
+      if (is_mmapped(oldp))
+        newp = mmap_resize(m, oldp, nb);
+      else if (oldsize >= nb) { /* already big enough */
+        size_t rsize = oldsize - nb;
+        newp = oldp;
+        if (rsize >= MIN_CHUNK_SIZE) {
+          mchunkptr remainder = chunk_plus_offset(newp, nb);
+          set_inuse(m, newp, nb);
+          set_inuse(m, remainder, rsize);
+          extra = chunk2mem(remainder);
+        }
+      }
+      else if (next == m->top && oldsize + m->topsize > nb) {
+        /* Expand into top */
+        size_t newsize = oldsize + m->topsize;
+        size_t newtopsize = newsize - nb;
+        mchunkptr newtop = chunk_plus_offset(oldp, nb);
+        set_inuse(m, oldp, nb);
+        newtop->head = newtopsize |PINUSE_BIT;
+        m->top = newtop;
+        m->topsize = newtopsize;
+        newp = oldp;
+      }
+    }
+    else {
+      USAGE_ERROR_ACTION(m, oldmem);
+      POSTACTION(m);
+      return 0;
+    }
+
+    POSTACTION(m);
+
+    if (newp != 0) {
+      if (extra != 0) {
+        internal_free(m, extra);
+      }
+      check_inuse_chunk(m, newp);
+      return chunk2mem(newp);
+    }
+    else {
+      void* newmem = internal_malloc(m, bytes);
+      if (newmem != 0) {
+        size_t oc = oldsize - overhead_for(oldp);
+        memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
+        internal_free(m, oldmem);
+      }
+      return newmem;
+    }
+  }
+  return 0;
+}
+
+/* --------------------------- memalign support -------------------------- */
+
+static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
+  if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */
+    return internal_malloc(m, bytes);
+  if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
+    alignment = MIN_CHUNK_SIZE;
+  if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
+    size_t a = MALLOC_ALIGNMENT << 1;
+    while (a < alignment) a <<= 1;
+    alignment = a;
+  }
+  
+  if (bytes >= MAX_REQUEST - alignment) {
+    if (m != 0)  { /* Test isn't needed but avoids compiler warning */
+      MALLOC_FAILURE_ACTION;
+    }
+  }
+  else {
+    size_t nb = request2size(bytes);
+    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
+    char* mem = (char*)internal_malloc(m, req);
+    if (mem != 0) {
+      void* leader = 0;
+      void* trailer = 0;
+      mchunkptr p = mem2chunk(mem);
+
+      if (PREACTION(m)) return 0;
+      if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
+        /*
+          Find an aligned spot inside chunk.  Since we need to give
+          back leading space in a chunk of at least MIN_CHUNK_SIZE, if
+          the first calculation places us at a spot with less than
+          MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
+          We've allocated enough total room so that this is always
+          possible.
+        */
+        char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
+                                                       alignment -
+                                                       SIZE_T_ONE)) &
+                                             -alignment));
+        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
+          br : br+alignment;
+        mchunkptr newp = (mchunkptr)pos;
+        size_t leadsize = pos - (char*)(p);
+        size_t newsize = chunksize(p) - leadsize;
+
+        if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
+          newp->prev_foot = p->prev_foot + leadsize;
+          newp->head = (newsize|CINUSE_BIT);
+        }
+        else { /* Otherwise, give back leader, use the rest */
+          set_inuse(m, newp, newsize);
+          set_inuse(m, p, leadsize);
+          leader = chunk2mem(p);
+        }
+        p = newp;
+      }
+
+      /* Give back spare room at the end */
+      if (!is_mmapped(p)) {
+        size_t size = chunksize(p);
+        if (size > nb + MIN_CHUNK_SIZE) {
+          size_t remainder_size = size - nb;
+          mchunkptr remainder = chunk_plus_offset(p, nb);
+          set_inuse(m, p, nb);
+          set_inuse(m, remainder, remainder_size);
+          trailer = chunk2mem(remainder);
+        }
+      }
+
+      assert (chunksize(p) >= nb);
+      assert((((size_t)(chunk2mem(p))) % alignment) == 0);
+      check_inuse_chunk(m, p);
+      POSTACTION(m);
+      if (leader != 0) {
+        internal_free(m, leader);
+      }
+      if (trailer != 0) {
+        internal_free(m, trailer);
+      }
+      return chunk2mem(p);
+    }
+  }
+  return 0;
+}
+
+/* ------------------------ comalloc/coalloc support --------------------- */
+
+static void** ialloc(mstate m,
+                     size_t n_elements,
+                     size_t* sizes,
+                     int opts,
+                     void* chunks[]) {
+  /*
+    This provides common support for independent_X routines, handling
+    all of the combinations that can result.
+
+    The opts arg has:
+    bit 0 set if all elements are same size (using sizes[0])
+    bit 1 set if elements should be zeroed
+  */
+
+  size_t    element_size;   /* chunksize of each element, if all same */
+  size_t    contents_size;  /* total size of elements */
+  size_t    array_size;     /* request size of pointer array */
+  void*     mem;            /* malloced aggregate space */
+  mchunkptr p;              /* corresponding chunk */
+  size_t    remainder_size; /* remaining bytes while splitting */
+  void**    marray;         /* either "chunks" or malloced ptr array */
+  mchunkptr array_chunk;    /* chunk for malloced ptr array */
+  flag_t    was_enabled;    /* to disable mmap */
+  size_t    size;
+  size_t    i;
+
+  /* compute array length, if needed */
+  if (chunks != 0) {
+    if (n_elements == 0)
+      return chunks; /* nothing to do */
+    marray = chunks;
+    array_size = 0;
+  }
+  else {
+    /* if empty req, must still return chunk representing empty array */
+    if (n_elements == 0)
+      return (void**)internal_malloc(m, 0);
+    marray = 0;
+    array_size = request2size(n_elements * (sizeof(void*)));
+  }
+
+  /* compute total element size */
+  if (opts & 0x1) { /* all-same-size */
+    element_size = request2size(*sizes);
+    contents_size = n_elements * element_size;
+  }
+  else { /* add up all the sizes */
+    element_size = 0;
+    contents_size = 0;
+    for (i = 0; i != n_elements; ++i)
+      contents_size += request2size(sizes[i]);
+  }
+
+  size = contents_size + array_size;
+
+  /*
+     Allocate the aggregate chunk.  First disable direct-mmapping so
+     malloc won't use it, since we would not be able to later
+     free/realloc space internal to a segregated mmap region.
+  */
+  was_enabled = use_mmap(m);
+  disable_mmap(m);
+  mem = internal_malloc(m, size - CHUNK_OVERHEAD);
+  if (was_enabled)
+    enable_mmap(m);
+  if (mem == 0)
+    return 0;
+
+  if (PREACTION(m)) return 0;
+  p = mem2chunk(mem);
+  remainder_size = chunksize(p);
+
+  assert(!is_mmapped(p));
+
+  if (opts & 0x2) {       /* optionally clear the elements */
+    memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
+  }
+
+  /* If not provided, allocate the pointer array as final part of chunk */
+  if (marray == 0) {
+    size_t  array_chunk_size;
+    array_chunk = chunk_plus_offset(p, contents_size);
+    array_chunk_size = remainder_size - contents_size;
+    marray = (void**) (chunk2mem(array_chunk));
+    set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
+    remainder_size = contents_size;
+  }
+
+  /* split out elements */
+  for (i = 0; ; ++i) {
+    marray[i] = chunk2mem(p);
+    if (i != n_elements-1) {
+      if (element_size != 0)
+        size = element_size;
+      else
+        size = request2size(sizes[i]);
+      remainder_size -= size;
+      set_size_and_pinuse_of_inuse_chunk(m, p, size);
+      p = chunk_plus_offset(p, size);
+    }
+    else { /* the final element absorbs any overallocation slop */
+      set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
+      break;
+    }
+  }
+
+#if DEBUG
+  if (marray != chunks) {
+    /* final element must have exactly exhausted chunk */
+    if (element_size != 0) {
+      assert(remainder_size == element_size);
+    }
+    else {
+      assert(remainder_size == request2size(sizes[i]));
+    }
+    check_inuse_chunk(m, mem2chunk(marray));
+  }
+  for (i = 0; i != n_elements; ++i)
+    check_inuse_chunk(m, mem2chunk(marray[i]));
+
+#endif /* DEBUG */
+
+  POSTACTION(m);
+  return marray;
+}
+
+
+/* -------------------------- public routines ---------------------------- */
+
+#if !ONLY_MSPACES
+
+void* dlmalloc(size_t bytes) {
+  /*
+     Basic algorithm:
+     If a small request (< 256 bytes minus per-chunk overhead):
+       1. If one exists, use a remainderless chunk in associated smallbin.
+          (Remainderless means that there are too few excess bytes to
+          represent as a chunk.)
+       2. If it is big enough, use the dv chunk, which is normally the
+          chunk adjacent to the one used for the most recent small request.
+       3. If one exists, split the smallest available chunk in a bin,
+          saving remainder in dv.
+       4. If it is big enough, use the top chunk.
+       5. If available, get memory from system and use it
+     Otherwise, for a large request:
+       1. Find the smallest available binned chunk that fits, and use it
+          if it is better fitting than dv chunk, splitting if necessary.
+       2. If better fitting than any binned chunk, use the dv chunk.
+       3. If it is big enough, use the top chunk.
+       4. If request size >= mmap threshold, try to directly mmap this chunk.
+       5. If available, get memory from system and use it
+
+     The ugly goto's here ensure that postaction occurs along all paths.
+  */
+
+  if (!PREACTION(gm)) {
+    void* mem;
+    size_t nb;
+    if (bytes <= MAX_SMALL_REQUEST) {
+      bindex_t idx;
+      binmap_t smallbits;
+      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
+      idx = small_index(nb);
+      smallbits = gm->smallmap >> idx;
+
+      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
+        mchunkptr b, p;
+        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
+        b = smallbin_at(gm, idx);
+        p = b->fd;
+        assert(chunksize(p) == small_index2size(idx));
+        unlink_first_small_chunk(gm, b, p, idx);
+        set_inuse_and_pinuse(gm, p, small_index2size(idx));
+        mem = chunk2mem(p);
+        check_malloced_chunk(gm, mem, nb);
+        goto postaction;
+      }
+
+      else if (nb > gm->dvsize) {
+        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
+          mchunkptr b, p, r;
+          size_t rsize;
+          bindex_t i;
+          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
+          binmap_t leastbit = least_bit(leftbits);
+          compute_bit2idx(leastbit, i);
+          b = smallbin_at(gm, i);
+          p = b->fd;
+          assert(chunksize(p) == small_index2size(i));
+          unlink_first_small_chunk(gm, b, p, i);
+          rsize = small_index2size(i) - nb;
+          /* Fit here cannot be remainderless if 4byte sizes */
+          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
+            set_inuse_and_pinuse(gm, p, small_index2size(i));
+          else {
+            set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
+            r = chunk_plus_offset(p, nb);
+            set_size_and_pinuse_of_free_chunk(r, rsize);
+            replace_dv(gm, r, rsize);
+          }
+          mem = chunk2mem(p);
+          check_malloced_chunk(gm, mem, nb);
+          goto postaction;
+        }
+
+        else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
+          check_malloced_chunk(gm, mem, nb);
+          goto postaction;
+        }
+      }
+    }
+    else if (bytes >= MAX_REQUEST)
+      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
+    else {
+      nb = pad_request(bytes);
+      if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
+        check_malloced_chunk(gm, mem, nb);
+        goto postaction;
+      }
+    }
+
+    if (nb <= gm->dvsize) {
+      size_t rsize = gm->dvsize - nb;
+      mchunkptr p = gm->dv;
+      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
+        mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
+        gm->dvsize = rsize;
+        set_size_and_pinuse_of_free_chunk(r, rsize);
+        set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
+      }
+      else { /* exhaust dv */
+        size_t dvs = gm->dvsize;
+        gm->dvsize = 0;
+        gm->dv = 0;
+        set_inuse_and_pinuse(gm, p, dvs);
+      }
+      mem = chunk2mem(p);
+      check_malloced_chunk(gm, mem, nb);
+      goto postaction;
+    }
+
+    else if (nb < gm->topsize) { /* Split top */
+      size_t rsize = gm->topsize -= nb;
+      mchunkptr p = gm->top;
+      mchunkptr r = gm->top = chunk_plus_offset(p, nb);
+      r->head = rsize | PINUSE_BIT;
+      set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
+      mem = chunk2mem(p);
+      check_top_chunk(gm, gm->top);
+      check_malloced_chunk(gm, mem, nb);
+      goto postaction;
+    }
+
+    mem = sys_alloc(gm, nb);
+
+  postaction:
+    POSTACTION(gm);
+    return mem;
+  }
+
+  return 0;
+}
+
+void dlfree(void* mem) {
+  /*
+     Consolidate freed chunks with preceding or succeeding bordering
+     free chunks, if they exist, and then place in a bin.  Intermixed
+     with special cases for top, dv, mmapped chunks, and usage errors.
+  */
+
+  if (mem != 0) {
+    mchunkptr p  = mem2chunk(mem);
+#if FOOTERS
+    mstate fm = get_mstate_for(p);
+    if (!ok_magic(fm)) {
+      USAGE_ERROR_ACTION(fm, p);
+      return;
+    }
+#else /* FOOTERS */
+#define fm gm
+#endif /* FOOTERS */
+    if (!PREACTION(fm)) {
+      check_inuse_chunk(fm, p);
+      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
+        size_t psize = chunksize(p);
+        mchunkptr next = chunk_plus_offset(p, psize);
+        if (!pinuse(p)) {
+          size_t prevsize = p->prev_foot;
+          if ((prevsize & IS_MMAPPED_BIT) != 0) {
+            prevsize &= ~IS_MMAPPED_BIT;
+            psize += prevsize + MMAP_FOOT_PAD;
+            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
+              fm->footprint -= psize;
+            goto postaction;
+          }
+          else {
+            mchunkptr prev = chunk_minus_offset(p, prevsize);
+            psize += prevsize;
+            p = prev;
+            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
+              if (p != fm->dv) {
+                unlink_chunk(fm, p, prevsize);
+              }
+              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
+                fm->dvsize = psize;
+                set_free_with_pinuse(p, psize, next);
+                goto postaction;
+              }
+            }
+            else
+              goto erroraction;
+          }
+        }
+
+        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
+          if (!cinuse(next)) {  /* consolidate forward */
+            if (next == fm->top) {
+              size_t tsize = fm->topsize += psize;
+              fm->top = p;
+              p->head = tsize | PINUSE_BIT;
+              if (p == fm->dv) {
+                fm->dv = 0;
+                fm->dvsize = 0;
+              }
+              if (should_trim(fm, tsize))
+                sys_trim(fm, 0);
+              goto postaction;
+            }
+            else if (next == fm->dv) {
+              size_t dsize = fm->dvsize += psize;
+              fm->dv = p;
+              set_size_and_pinuse_of_free_chunk(p, dsize);
+              goto postaction;
+            }
+            else {
+              size_t nsize = chunksize(next);
+              psize += nsize;
+              unlink_chunk(fm, next, nsize);
+              set_size_and_pinuse_of_free_chunk(p, psize);
+              if (p == fm->dv) {
+                fm->dvsize = psize;
+                goto postaction;
+              }
+            }
+          }
+          else
+            set_free_with_pinuse(p, psize, next);
+          insert_chunk(fm, p, psize);
+          check_free_chunk(fm, p);
+          goto postaction;
+        }
+      }
+    erroraction:
+      USAGE_ERROR_ACTION(fm, p);
+    postaction:
+      POSTACTION(fm);
+    }
+  }
+#if !FOOTERS
+#undef fm
+#endif /* FOOTERS */
+}
+
+void* dlcalloc(size_t n_elements, size_t elem_size) {
+  void* mem;
+  size_t req = 0;
+  if (n_elements != 0) {
+    req = n_elements * elem_size;
+    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
+        (req / n_elements != elem_size))
+      req = MAX_SIZE_T; /* force downstream failure on overflow */
+  }
+  mem = dlmalloc(req);
+  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
+    memset(mem, 0, req);
+  return mem;
+}
+
+void* dlrealloc(void* oldmem, size_t bytes) {
+  if (oldmem == 0)
+    return dlmalloc(bytes);
+#ifdef REALLOC_ZERO_BYTES_FREES
+  if (bytes == 0) {
+    dlfree(oldmem);
+    return 0;
+  }
+#endif /* REALLOC_ZERO_BYTES_FREES */
+  else {
+#if ! FOOTERS
+    mstate m = gm;
+#else /* FOOTERS */
+    mstate m = get_mstate_for(mem2chunk(oldmem));
+    if (!ok_magic(m)) {
+      USAGE_ERROR_ACTION(m, oldmem);
+      return 0;
+    }
+#endif /* FOOTERS */
+    return internal_realloc(m, oldmem, bytes);
+  }
+}
+
+void* dlmemalign(size_t alignment, size_t bytes) {
+  return internal_memalign(gm, alignment, bytes);
+}
+
+void** dlindependent_calloc(size_t n_elements, size_t elem_size,
+                                 void* chunks[]) {
+  size_t sz = elem_size; /* serves as 1-element array */
+  return ialloc(gm, n_elements, &sz, 3, chunks);
+}
+
+void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
+                                   void* chunks[]) {
+  return ialloc(gm, n_elements, sizes, 0, chunks);
+}
+
+void* dlvalloc(size_t bytes) {
+  size_t pagesz;
+  init_mparams();
+  pagesz = mparams.page_size;
+  return dlmemalign(pagesz, bytes);
+}
+
+void* dlpvalloc(size_t bytes) {
+  size_t pagesz;
+  init_mparams();
+  pagesz = mparams.page_size;
+  return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
+}
+
+int dlmalloc_trim(size_t pad) {
+  int result = 0;
+  if (!PREACTION(gm)) {
+    result = sys_trim(gm, pad);
+    POSTACTION(gm);
+  }
+  return result;
+}
+
+size_t dlmalloc_footprint(void) {
+  return gm->footprint;
+}
+
+size_t dlmalloc_max_footprint(void) {
+  return gm->max_footprint;
+}
+
+#if !NO_MALLINFO
+struct mallinfo dlmallinfo(void) {
+  return internal_mallinfo(gm);
+}
+#endif /* NO_MALLINFO */
+
+void dlmalloc_stats() {
+  internal_malloc_stats(gm);
+}
+
+size_t dlmalloc_usable_size(void* mem) {
+  if (mem != 0) {
+    mchunkptr p = mem2chunk(mem);
+    if (cinuse(p))
+      return chunksize(p) - overhead_for(p);
+  }
+  return 0;
+}
+
+int dlmallopt(int param_number, int value) {
+  return change_mparam(param_number, value);
+}
+
+#endif /* !ONLY_MSPACES */
+
+/* ----------------------------- user mspaces ---------------------------- */
+
+#if MSPACES
+
+static mstate init_user_mstate(char* tbase, size_t tsize) {
+  size_t msize = pad_request(sizeof(struct malloc_state));
+  mchunkptr mn;
+  mchunkptr msp = align_as_chunk(tbase);
+  mstate m = (mstate)(chunk2mem(msp));
+  memset(m, 0, msize);
+  INITIAL_LOCK(&m->mutex);
+  msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
+  m->seg.base = m->least_addr = tbase;
+  m->seg.size = m->footprint = m->max_footprint = tsize;
+  m->magic = mparams.magic;
+  m->mflags = mparams.default_mflags;
+  disable_contiguous(m);
+  init_bins(m);
+  mn = next_chunk(mem2chunk(m));
+  init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
+  check_top_chunk(m, m->top);
+  return m;
+}
+
+mspace create_mspace(size_t capacity, int locked) {
+  mstate m = 0;
+  size_t msize = pad_request(sizeof(struct malloc_state));
+  init_mparams(); /* Ensure pagesize etc initialized */
+
+  if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
+    size_t rs = ((capacity == 0)? mparams.granularity :
+                 (capacity + TOP_FOOT_SIZE + msize));
+    size_t tsize = granularity_align(rs);
+    char* tbase = (char*)(CALL_MMAP(tsize));
+    if (tbase != CMFAIL) {
+      m = init_user_mstate(tbase, tsize);
+      set_segment_flags(&m->seg, IS_MMAPPED_BIT);
+      set_lock(m, locked);
+    }
+  }
+  return (mspace)m;
+}
+
+mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
+  mstate m = 0;
+  size_t msize = pad_request(sizeof(struct malloc_state));
+  init_mparams(); /* Ensure pagesize etc initialized */
+
+  if (capacity > msize + TOP_FOOT_SIZE &&
+      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
+    m = init_user_mstate((char*)base, capacity);
+    set_segment_flags(&m->seg, EXTERN_BIT);
+    set_lock(m, locked);
+  }
+  return (mspace)m;
+}
+
+size_t destroy_mspace(mspace msp) {
+  size_t freed = 0;
+  mstate ms = (mstate)msp;
+  if (ok_magic(ms)) {
+    msegmentptr sp = &ms->seg;
+    while (sp != 0) {
+      char* base = sp->base;
+      size_t size = sp->size;
+      flag_t flag = get_segment_flags(sp);
+      sp = sp->next;
+      if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
+          CALL_MUNMAP(base, size) == 0)
+        freed += size;
+    }
+  }
+  else {
+    USAGE_ERROR_ACTION(ms,ms);
+  }
+  return freed;
+}
+
+/*
+  mspace versions of routines are near-clones of the global
+  versions. This is not so nice but better than the alternatives.
+*/
+
+
+void* mspace_malloc(mspace msp, size_t bytes) {
+  mstate ms = (mstate)msp;
+  if (!ok_magic(ms)) {
+    USAGE_ERROR_ACTION(ms,ms);
+    return 0;
+  }
+  if (!PREACTION(ms)) {
+    void* mem;
+    size_t nb;
+    if (bytes <= MAX_SMALL_REQUEST) {
+      bindex_t idx;
+      binmap_t smallbits;
+      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
+      idx = small_index(nb);
+      smallbits = ms->smallmap >> idx;
+
+      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
+        mchunkptr b, p;
+        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
+        b = smallbin_at(ms, idx);
+        p = b->fd;
+        assert(chunksize(p) == small_index2size(idx));
+        unlink_first_small_chunk(ms, b, p, idx);
+        set_inuse_and_pinuse(ms, p, small_index2size(idx));
+        mem = chunk2mem(p);
+        check_malloced_chunk(ms, mem, nb);
+        goto postaction;
+      }
+
+      else if (nb > ms->dvsize) {
+        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
+          mchunkptr b, p, r;
+          size_t rsize;
+          bindex_t i;
+          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
+          binmap_t leastbit = least_bit(leftbits);
+          compute_bit2idx(leastbit, i);
+          b = smallbin_at(ms, i);
+          p = b->fd;
+          assert(chunksize(p) == small_index2size(i));
+          unlink_first_small_chunk(ms, b, p, i);
+          rsize = small_index2size(i) - nb;
+          /* Fit here cannot be remainderless if 4byte sizes */
+          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
+            set_inuse_and_pinuse(ms, p, small_index2size(i));
+          else {
+            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
+            r = chunk_plus_offset(p, nb);
+            set_size_and_pinuse_of_free_chunk(r, rsize);
+            replace_dv(ms, r, rsize);
+          }
+          mem = chunk2mem(p);
+          check_malloced_chunk(ms, mem, nb);
+          goto postaction;
+        }
+
+        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
+          check_malloced_chunk(ms, mem, nb);
+          goto postaction;
+        }
+      }
+    }
+    else if (bytes >= MAX_REQUEST)
+      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
+    else {
+      nb = pad_request(bytes);
+      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
+        check_malloced_chunk(ms, mem, nb);
+        goto postaction;
+      }
+    }
+
+    if (nb <= ms->dvsize) {
+      size_t rsize = ms->dvsize - nb;
+      mchunkptr p = ms->dv;
+      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
+        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
+        ms->dvsize = rsize;
+        set_size_and_pinuse_of_free_chunk(r, rsize);
+        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
+      }
+      else { /* exhaust dv */
+        size_t dvs = ms->dvsize;
+        ms->dvsize = 0;
+        ms->dv = 0;
+        set_inuse_and_pinuse(ms, p, dvs);
+      }
+      mem = chunk2mem(p);
+      check_malloced_chunk(ms, mem, nb);
+      goto postaction;
+    }
+
+    else if (nb < ms->topsize) { /* Split top */
+      size_t rsize = ms->topsize -= nb;
+      mchunkptr p = ms->top;
+      mchunkptr r = ms->top = chunk_plus_offset(p, nb);
+      r->head = rsize | PINUSE_BIT;
+      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
+      mem = chunk2mem(p);
+      check_top_chunk(ms, ms->top);
+      check_malloced_chunk(ms, mem, nb);
+      goto postaction;
+    }
+
+    mem = sys_alloc(ms, nb);
+
+  postaction:
+    POSTACTION(ms);
+    return mem;
+  }
+
+  return 0;
+}
+
+void mspace_free(mspace msp, void* mem) {
+  if (mem != 0) {
+    mchunkptr p  = mem2chunk(mem);
+#if FOOTERS
+    mstate fm = get_mstate_for(p);
+#else /* FOOTERS */
+    mstate fm = (mstate)msp;
+#endif /* FOOTERS */
+    if (!ok_magic(fm)) {
+      USAGE_ERROR_ACTION(fm, p);
+      return;
+    }
+    if (!PREACTION(fm)) {
+      check_inuse_chunk(fm, p);
+      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
+        size_t psize = chunksize(p);
+        mchunkptr next = chunk_plus_offset(p, psize);
+        if (!pinuse(p)) {
+          size_t prevsize = p->prev_foot;
+          if ((prevsize & IS_MMAPPED_BIT) != 0) {
+            prevsize &= ~IS_MMAPPED_BIT;
+            psize += prevsize + MMAP_FOOT_PAD;
+            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
+              fm->footprint -= psize;
+            goto postaction;
+          }
+          else {
+            mchunkptr prev = chunk_minus_offset(p, prevsize);
+            psize += prevsize;
+            p = prev;
+            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
+              if (p != fm->dv) {
+                unlink_chunk(fm, p, prevsize);
+              }
+              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
+                fm->dvsize = psize;
+                set_free_with_pinuse(p, psize, next);
+                goto postaction;
+              }
+            }
+            else
+              goto erroraction;
+          }
+        }
+
+        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
+          if (!cinuse(next)) {  /* consolidate forward */
+            if (next == fm->top) {
+              size_t tsize = fm->topsize += psize;
+              fm->top = p;
+              p->head = tsize | PINUSE_BIT;
+              if (p == fm->dv) {
+                fm->dv = 0;
+                fm->dvsize = 0;
+              }
+              if (should_trim(fm, tsize))
+                sys_trim(fm, 0);
+              goto postaction;
+            }
+            else if (next == fm->dv) {
+              size_t dsize = fm->dvsize += psize;
+              fm->dv = p;
+              set_size_and_pinuse_of_free_chunk(p, dsize);
+              goto postaction;
+            }
+            else {
+              size_t nsize = chunksize(next);
+              psize += nsize;
+              unlink_chunk(fm, next, nsize);
+              set_size_and_pinuse_of_free_chunk(p, psize);
+              if (p == fm->dv) {
+                fm->dvsize = psize;
+                goto postaction;
+              }
+            }
+          }
+          else
+            set_free_with_pinuse(p, psize, next);
+          insert_chunk(fm, p, psize);
+          check_free_chunk(fm, p);
+          goto postaction;
+        }
+      }
+    erroraction:
+      USAGE_ERROR_ACTION(fm, p);
+    postaction:
+      POSTACTION(fm);
+    }
+  }
+}
+
+void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
+  void* mem;
+  size_t req = 0;
+  mstate ms = (mstate)msp;
+  if (!ok_magic(ms)) {
+    USAGE_ERROR_ACTION(ms,ms);
+    return 0;
+  }
+  if (n_elements != 0) {
+    req = n_elements * elem_size;
+    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
+        (req / n_elements != elem_size))
+      req = MAX_SIZE_T; /* force downstream failure on overflow */
+  }
+  mem = internal_malloc(ms, req);
+  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
+    memset(mem, 0, req);
+  return mem;
+}
+
+void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
+  if (oldmem == 0)
+    return mspace_malloc(msp, bytes);
+#ifdef REALLOC_ZERO_BYTES_FREES
+  if (bytes == 0) {
+    mspace_free(msp, oldmem);
+    return 0;
+  }
+#endif /* REALLOC_ZERO_BYTES_FREES */
+  else {
+#if FOOTERS
+    mchunkptr p  = mem2chunk(oldmem);
+    mstate ms = get_mstate_for(p);
+#else /* FOOTERS */
+    mstate ms = (mstate)msp;
+#endif /* FOOTERS */
+    if (!ok_magic(ms)) {
+      USAGE_ERROR_ACTION(ms,ms);
+      return 0;
+    }
+    return internal_realloc(ms, oldmem, bytes);
+  }
+}
+
+void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
+  mstate ms = (mstate)msp;
+  if (!ok_magic(ms)) {
+    USAGE_ERROR_ACTION(ms,ms);
+    return 0;
+  }
+  return internal_memalign(ms, alignment, bytes);
+}
+
+void** mspace_independent_calloc(mspace msp, size_t n_elements,
+                                 size_t elem_size, void* chunks[]) {
+  size_t sz = elem_size; /* serves as 1-element array */
+  mstate ms = (mstate)msp;
+  if (!ok_magic(ms)) {
+    USAGE_ERROR_ACTION(ms,ms);
+    return 0;
+  }
+  return ialloc(ms, n_elements, &sz, 3, chunks);
+}
+
+void** mspace_independent_comalloc(mspace msp, size_t n_elements,
+                                   size_t sizes[], void* chunks[]) {
+  mstate ms = (mstate)msp;
+  if (!ok_magic(ms)) {
+    USAGE_ERROR_ACTION(ms,ms);
+    return 0;
+  }
+  return ialloc(ms, n_elements, sizes, 0, chunks);
+}
+
+int mspace_trim(mspace msp, size_t pad) {
+  int result = 0;
+  mstate ms = (mstate)msp;
+  if (ok_magic(ms)) {
+    if (!PREACTION(ms)) {
+      result = sys_trim(ms, pad);
+      POSTACTION(ms);
+    }
+  }
+  else {
+    USAGE_ERROR_ACTION(ms,ms);
+  }
+  return result;
+}
+
+void mspace_malloc_stats(mspace msp) {
+  mstate ms = (mstate)msp;
+  if (ok_magic(ms)) {
+    internal_malloc_stats(ms);
+  }
+  else {
+    USAGE_ERROR_ACTION(ms,ms);
+  }
+}
+
+size_t mspace_footprint(mspace msp) {
+  size_t result;
+  mstate ms = (mstate)msp;
+  if (ok_magic(ms)) {
+    result = ms->footprint;
+  }
+  USAGE_ERROR_ACTION(ms,ms);
+  return result;
+}
+
+
+size_t mspace_max_footprint(mspace msp) {
+  size_t result;
+  mstate ms = (mstate)msp;
+  if (ok_magic(ms)) {
+    result = ms->max_footprint;
+  }
+  USAGE_ERROR_ACTION(ms,ms);
+  return result;
+}
+
+
+#if !NO_MALLINFO
+struct mallinfo mspace_mallinfo(mspace msp) {
+  mstate ms = (mstate)msp;
+  if (!ok_magic(ms)) {
+    USAGE_ERROR_ACTION(ms,ms);
+  }
+  return internal_mallinfo(ms);
+}
+#endif /* NO_MALLINFO */
+
+int mspace_mallopt(int param_number, int value) {
+  return change_mparam(param_number, value);
+}
+
+#endif /* MSPACES */
+
+/* -------------------- Alternative MORECORE functions ------------------- */
+
+/*
+  Guidelines for creating a custom version of MORECORE:
+
+  * For best performance, MORECORE should allocate in multiples of pagesize.
+  * MORECORE may allocate more memory than requested. (Or even less,
+      but this will usually result in a malloc failure.)
+  * MORECORE must not allocate memory when given argument zero, but
+      instead return one past the end address of memory from previous
+      nonzero call.
+  * For best performance, consecutive calls to MORECORE with positive
+      arguments should return increasing addresses, indicating that
+      space has been contiguously extended.
+  * Even though consecutive calls to MORECORE need not return contiguous
+      addresses, it must be OK for malloc'ed chunks to span multiple
+      regions in those cases where they do happen to be contiguous.
+  * MORECORE need not handle negative arguments -- it may instead
+      just return MFAIL when given negative arguments.
+      Negative arguments are always multiples of pagesize. MORECORE
+      must not misinterpret negative args as large positive unsigned
+      args. You can suppress all such calls from even occurring by defining
+      MORECORE_CANNOT_TRIM,
+
+  As an example alternative MORECORE, here is a custom allocator
+  kindly contributed for pre-OSX macOS.  It uses virtually but not
+  necessarily physically contiguous non-paged memory (locked in,
+  present and won't get swapped out).  You can use it by uncommenting
+  this section, adding some #includes, and setting up the appropriate
+  defines above:
+
+      #define MORECORE osMoreCore
+
+  There is also a shutdown routine that should somehow be called for
+  cleanup upon program exit.
+
+  #define MAX_POOL_ENTRIES 100
+  #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
+  static int next_os_pool;
+  void *our_os_pools[MAX_POOL_ENTRIES];
+
+  void *osMoreCore(int size)
+  {
+    void *ptr = 0;
+    static void *sbrk_top = 0;
+
+    if (size > 0)
+    {
+      if (size < MINIMUM_MORECORE_SIZE)
+         size = MINIMUM_MORECORE_SIZE;
+      if (CurrentExecutionLevel() == kTaskLevel)
+         ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
+      if (ptr == 0)
+      {
+        return (void *) MFAIL;
+      }
+      // save ptrs so they can be freed during cleanup
+      our_os_pools[next_os_pool] = ptr;
+      next_os_pool++;
+      ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
+      sbrk_top = (char *) ptr + size;
+      return ptr;
+    }
+    else if (size < 0)
+    {
+      // we don't currently support shrink behavior
+      return (void *) MFAIL;
+    }
+    else
+    {
+      return sbrk_top;
+    }
+  }
+
+  // cleanup any allocated memory pools
+  // called as last thing before shutting down driver
+
+  void osCleanupMem(void)
+  {
+    void **ptr;
+
+    for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
+      if (*ptr)
+      {
+         PoolDeallocate(*ptr);
+         *ptr = 0;
+      }
+  }
+
+*/
+
+
+/* -----------------------------------------------------------------------
+History:
+    V2.8.3 Thu Sep 22 11:16:32 2005  Doug Lea  (dl at gee)
+      * Add max_footprint functions
+      * Ensure all appropriate literals are size_t
+      * Fix conditional compilation problem for some #define settings
+      * Avoid concatenating segments with the one provided
+        in create_mspace_with_base
+      * Rename some variables to avoid compiler shadowing warnings
+      * Use explicit lock initialization.
+      * Better handling of sbrk interference.
+      * Simplify and fix segment insertion, trimming and mspace_destroy
+      * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
+      * Thanks especially to Dennis Flanagan for help on these.
+
+    V2.8.2 Sun Jun 12 16:01:10 2005  Doug Lea  (dl at gee)
+      * Fix memalign brace error.
+
+    V2.8.1 Wed Jun  8 16:11:46 2005  Doug Lea  (dl at gee)
+      * Fix improper #endif nesting in C++
+      * Add explicit casts needed for C++
+
+    V2.8.0 Mon May 30 14:09:02 2005  Doug Lea  (dl at gee)
+      * Use trees for large bins
+      * Support mspaces
+      * Use segments to unify sbrk-based and mmap-based system allocation,
+        removing need for emulation on most platforms without sbrk.
+      * Default safety checks
+      * Optional footer checks. Thanks to William Robertson for the idea.
+      * Internal code refactoring
+      * Incorporate suggestions and platform-specific changes.
+        Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
+        Aaron Bachmann,  Emery Berger, and others.
+      * Speed up non-fastbin processing enough to remove fastbins.
+      * Remove useless cfree() to avoid conflicts with other apps.
+      * Remove internal memcpy, memset. Compilers handle builtins better.
+      * Remove some options that no one ever used and rename others.
+
+    V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
+      * Fix malloc_state bitmap array misdeclaration
+
+    V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
+      * Allow tuning of FIRST_SORTED_BIN_SIZE
+      * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
+      * Better detection and support for non-contiguousness of MORECORE.
+        Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
+      * Bypass most of malloc if no frees. Thanks To Emery Berger.
+      * Fix freeing of old top non-contiguous chunk im sysmalloc.
+      * Raised default trim and map thresholds to 256K.
+      * Fix mmap-related #defines. Thanks to Lubos Lunak.
+      * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
+      * Branch-free bin calculation
+      * Default trim and mmap thresholds now 256K.
+
+    V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
+      * Introduce independent_comalloc and independent_calloc.
+        Thanks to Michael Pachos for motivation and help.
+      * Make optional .h file available
+      * Allow > 2GB requests on 32bit systems.
+      * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
+        Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
+        and Anonymous.
+      * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
+        helping test this.)
+      * memalign: check alignment arg
+      * realloc: don't try to shift chunks backwards, since this
+        leads to  more fragmentation in some programs and doesn't
+        seem to help in any others.
+      * Collect all cases in malloc requiring system memory into sysmalloc
+      * Use mmap as backup to sbrk
+      * Place all internal state in malloc_state
+      * Introduce fastbins (although similar to 2.5.1)
+      * Many minor tunings and cosmetic improvements
+      * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
+      * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
+        Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
+      * Include errno.h to support default failure action.
+
+    V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
+      * return null for negative arguments
+      * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
+         * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
+          (e.g. WIN32 platforms)
+         * Cleanup header file inclusion for WIN32 platforms
+         * Cleanup code to avoid Microsoft Visual C++ compiler complaints
+         * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
+           memory allocation routines
+         * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
+         * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
+           usage of 'assert' in non-WIN32 code
+         * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
+           avoid infinite loop
+      * Always call 'fREe()' rather than 'free()'
+
+    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
+      * Fixed ordering problem with boundary-stamping
+
+    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
+      * Added pvalloc, as recommended by H.J. Liu
+      * Added 64bit pointer support mainly from Wolfram Gloger
+      * Added anonymously donated WIN32 sbrk emulation
+      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
+      * malloc_extend_top: fix mask error that caused wastage after
+        foreign sbrks
+      * Add linux mremap support code from HJ Liu
+
+    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
+      * Integrated most documentation with the code.
+      * Add support for mmap, with help from
+        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
+      * Use last_remainder in more cases.
+      * Pack bins using idea from  colin@nyx10.cs.du.edu
+      * Use ordered bins instead of best-fit threshhold
+      * Eliminate block-local decls to simplify tracing and debugging.
+      * Support another case of realloc via move into top
+      * Fix error occuring when initial sbrk_base not word-aligned.
+      * Rely on page size for units instead of SBRK_UNIT to
+        avoid surprises about sbrk alignment conventions.
+      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
+        (raymond@es.ele.tue.nl) for the suggestion.
+      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
+      * More precautions for cases where other routines call sbrk,
+        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
+      * Added macros etc., allowing use in linux libc from
+        H.J. Lu (hjl@gnu.ai.mit.edu)
+      * Inverted this history list
+
+    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
+      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
+      * Removed all preallocation code since under current scheme
+        the work required to undo bad preallocations exceeds
+        the work saved in good cases for most test programs.
+      * No longer use return list or unconsolidated bins since
+        no scheme using them consistently outperforms those that don't
+        given above changes.
+      * Use best fit for very large chunks to prevent some worst-cases.
+      * Added some support for debugging
+
+    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
+      * Removed footers when chunks are in use. Thanks to
+        Paul Wilson (wilson@cs.texas.edu) for the suggestion.
+
+    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
+      * Added malloc_trim, with help from Wolfram Gloger
+        (wmglo@Dent.MED.Uni-Muenchen.DE).
+
+    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
+
+    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
+      * realloc: try to expand in both directions
+      * malloc: swap order of clean-bin strategy;
+      * realloc: only conditionally expand backwards
+      * Try not to scavenge used bins
+      * Use bin counts as a guide to preallocation
+      * Occasionally bin return list chunks in first scan
+      * Add a few optimizations from colin@nyx10.cs.du.edu
+
+    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
+      * faster bin computation & slightly different binning
+      * merged all consolidations to one part of malloc proper
+         (eliminating old malloc_find_space & malloc_clean_bin)
+      * Scan 2 returns chunks (not just 1)
+      * Propagate failure in realloc if malloc returns 0
+      * Add stuff to allow compilation on non-ANSI compilers
+          from kpv@research.att.com
+
+    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
+      * removed potential for odd address access in prev_chunk
+      * removed dependency on getpagesize.h
+      * misc cosmetics and a bit more internal documentation
+      * anticosmetics: mangled names in macros to evade debugger strangeness
+      * tested on sparc, hp-700, dec-mips, rs6000
+          with gcc & native cc (hp, dec only) allowing
+          Detlefs & Zorn comparison study (in SIGPLAN Notices.)
+
+    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
+      * Based loosely on libg++-1.2X malloc. (It retains some of the overall
+         structure of old version,  but most details differ.)
+ 
+*/
diff --git a/third_party/gofrontend/libffi/src/frv/eabi.S b/third_party/gofrontend/libffi/src/frv/eabi.S
new file mode 100644
index 0000000..379ea4b
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/frv/eabi.S
@@ -0,0 +1,128 @@
+/* -----------------------------------------------------------------------
+   eabi.S - Copyright (c) 2004  Anthony Green
+   
+   FR-V Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+	.globl ffi_prep_args_EABI
+
+	.text
+	.p2align 4
+	.globl ffi_call_EABI
+	.type ffi_call_EABI, @function
+
+	# gr8 :   ffi_prep_args
+	# gr9 :   &ecif
+	# gr10:   cif->bytes
+	# gr11:   fig->flags
+	# gr12:   ecif.rvalue
+	# gr13:   fn
+	
+ffi_call_EABI:	
+	addi	sp, #-80, sp
+	sti	fp, @(sp, #24)
+	addi	sp, #24, fp
+	movsg	lr, gr5
+
+	/* Make room for the new arguments.  */
+	/* subi	sp, fp, gr10 */
+	
+	/* Store return address and incoming args on stack.  */
+	sti	gr5, @(fp, #8)
+	sti	gr8, @(fp, #-4)
+	sti	gr9, @(fp, #-8)
+	sti	gr10, @(fp, #-12)
+	sti	gr11, @(fp, #-16)
+	sti	gr12, @(fp, #-20)
+	sti	gr13, @(fp, #-24)
+
+	sub     sp, gr10, sp
+	
+	/* Call ffi_prep_args.  */
+	ldi	@(fp, #-4), gr4
+	addi	sp, #0, gr8
+	ldi	@(fp, #-8), gr9
+#ifdef __FRV_FDPIC__
+	ldd	@(gr4, gr0), gr14
+	calll	@(gr14, gr0)
+#else
+	calll	@(gr4, gr0)
+#endif	
+
+	/* ffi_prep_args returns the new stack pointer.  */
+	mov	gr8, gr4
+		
+	ldi	@(sp, #0), gr8
+	ldi	@(sp, #4), gr9
+	ldi	@(sp, #8), gr10
+	ldi	@(sp, #12), gr11
+	ldi	@(sp, #16), gr12
+	ldi	@(sp, #20), gr13
+
+	/* Always copy the return value pointer into the hidden
+	   parameter register.  This is only strictly necessary
+	   when we're returning an aggregate type, but it doesn't
+	   hurt to do this all the time, and it saves a branch.  */
+	ldi	@(fp, #-20), gr3
+
+	/* Use the ffi_prep_args return value for the new sp.  */
+	mov	gr4, sp
+	
+	/* Call the target function.  */
+	ldi	@(fp, -24), gr4
+#ifdef __FRV_FDPIC__
+	ldd	@(gr4, gr0), gr14
+	calll	@(gr14, gr0)
+#else
+	calll	@(gr4, gr0)
+#endif	
+
+	/* Store the result. */
+	ldi	@(fp, #-16), gr10  /* fig->flags */
+	ldi	@(fp, #-20), gr4   /* ecif.rvalue */
+
+	/* Is the return value stored in two registers?  */
+	cmpi	gr10, #8, icc0
+	bne	icc0, 0, .L2
+	/*   Yes, save them.  */
+	sti	gr8, @(gr4, #0)
+	sti	gr9, @(gr4, #4)
+	bra	.L3
+.L2:
+	/* Is the return value a structure?  */
+	cmpi	gr10, #-1, icc0
+	beq	icc0, 0, .L3
+	/*   No, save a 4 byte return value.  */
+	sti	gr8, @(gr4, #0)
+.L3:	
+
+	/* Restore the stack, and return.  */
+	ldi	@(fp, 8), gr5
+	ld	@(fp, gr0), fp
+	addi	sp,#80,sp
+	jmpl	@(gr5,gr0)
+	.size ffi_call_EABI, .-ffi_call_EABI
+	
diff --git a/third_party/gofrontend/libffi/src/frv/ffi.c b/third_party/gofrontend/libffi/src/frv/ffi.c
new file mode 100644
index 0000000..5698c89
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/frv/ffi.c
@@ -0,0 +1,292 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (C) 2004  Anthony Green
+   Copyright (C) 2007  Free Software Foundation, Inc.
+	   Copyright (C) 2008  Red Hat, Inc.
+   
+   FR-V Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void *ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+  register int count = 0;
+
+  p_argv = ecif->avalue;
+  argp = stack;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+      
+      z = (*p_arg)->size;
+
+      if ((*p_arg)->type == FFI_TYPE_STRUCT)
+	{
+	  z = sizeof(void*);
+	  *(void **) argp = *p_argv;
+	} 
+      /*      if ((*p_arg)->type == FFI_TYPE_FLOAT)
+	{
+	  if (count > 24)
+	    {
+	      // This is going on the stack.  Turn it into a double.  
+	      *(double *) argp = (double) *(float*)(* p_argv);
+	      z = sizeof(double);
+	    }
+	  else
+	    *(void **) argp = *(void **)(* p_argv);
+	}  */
+      else if (z < sizeof(int))
+	{
+	  z = sizeof(int);
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+	      break;
+	      
+	    case FFI_TYPE_UINT8:
+	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+	      break;
+	      
+	    case FFI_TYPE_SINT16:
+	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+	      break;
+		  
+	    case FFI_TYPE_UINT16:
+	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+	      break;
+		  
+	    default:
+	      FFI_ASSERT(0);
+	    }
+	}
+      else if (z == sizeof(int))
+	{
+	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+	}
+      else
+	{
+	  memcpy(argp, *p_argv, z);
+	}
+      p_argv++;
+      argp += z;
+      count += z;
+    }
+
+  return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    cif->flags = -1;
+  else
+    cif->flags = cif->rtype->size;
+
+  cif->bytes = ALIGN (cif->bytes, 8);
+
+  return FFI_OK;
+}
+
+extern void ffi_call_EABI(void *(*)(char *, extended_cif *), 
+			  extended_cif *, 
+			  unsigned, unsigned, 
+			  unsigned *, 
+			  void (*fn)(void));
+
+void ffi_call(ffi_cif *cif, 
+	      void (*fn)(void), 
+	      void *rvalue, 
+	      void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return	*/
+  /* value address then we need to make one		        */
+
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+    case FFI_EABI:
+      ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes, 
+		    cif->flags, ecif.rvalue, fn);
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
+		       unsigned arg4, unsigned arg5, unsigned arg6)
+{
+  /* This function is called by a trampoline.  The trampoline stows a
+     pointer to the ffi_closure object in gr7.  We must save this
+     pointer in a place that will persist while we do our work.  */
+  register ffi_closure *creg __asm__ ("gr7");
+  ffi_closure *closure = creg;
+
+  /* Arguments that don't fit in registers are found on the stack
+     at a fixed offset above the current frame pointer.  */
+  register char *frame_pointer __asm__ ("fp");
+  char *stack_args = frame_pointer + 16;
+
+  /* Lay the register arguments down in a continuous chunk of memory.  */
+  unsigned register_args[6] =
+    { arg1, arg2, arg3, arg4, arg5, arg6 };
+
+  ffi_cif *cif = closure->cif;
+  ffi_type **arg_types = cif->arg_types;
+  void **avalue = alloca (cif->nargs * sizeof(void *));
+  char *ptr = (char *) register_args;
+  int i;
+
+  /* Find the address of each argument.  */
+  for (i = 0; i < cif->nargs; i++)
+    {
+      switch (arg_types[i]->type)
+	{
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	  avalue[i] = ptr + 3;
+	  break;
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	  avalue[i] = ptr + 2;
+	  break;
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_FLOAT:
+	  avalue[i] = ptr;
+	  break;
+	case FFI_TYPE_STRUCT:
+	  avalue[i] = *(void**)ptr;
+	  break;
+	default:
+	  /* This is an 8-byte value.  */
+	  avalue[i] = ptr;
+	  ptr += 4;
+	  break;
+	}
+      ptr += 4;
+
+      /* If we've handled more arguments than fit in registers,
+	 start looking at the those passed on the stack.  */
+      if (ptr == ((char *)register_args + (6*4)))
+	ptr = stack_args;
+    }
+
+  /* Invoke the closure.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      /* The caller allocates space for the return structure, and
+       passes a pointer to this space in gr3.  Use this value directly
+       as the return value.  */
+      register void *return_struct_ptr __asm__("gr3");
+      (closure->fun) (cif, return_struct_ptr, avalue, closure->user_data);
+    }
+  else
+    {
+      /* Allocate space for the return value and call the function.  */
+      long long rvalue;
+      (closure->fun) (cif, &rvalue, avalue, closure->user_data);
+
+      /* Functions return 4-byte or smaller results in gr8.  8-byte
+	 values also use gr9.  We fill the both, even for small return
+	 values, just to avoid a branch.  */ 
+      asm ("ldi  @(%0, #0), gr8" : : "r" (&rvalue));
+      asm ("ldi  @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1]));
+    }
+}
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+  unsigned long fn = (long) ffi_closure_eabi;
+  unsigned long cls = (long) codeloc;
+#ifdef __FRV_FDPIC__
+  register void *got __asm__("gr15");
+#endif
+  int i;
+
+  fn = (unsigned long) ffi_closure_eabi;
+
+#ifdef __FRV_FDPIC__
+  tramp[0] = &((unsigned int *)codeloc)[2];
+  tramp[1] = got;
+  tramp[2] = 0x8cfc0000 + (fn  & 0xffff); /* setlos lo(fn), gr6    */
+  tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7   */
+  tramp[4] = 0x8cf80000 + (fn  >> 16);	  /* sethi hi(fn), gr6     */
+  tramp[5] = 0x8ef80000 + (cls >> 16);    /* sethi hi(cls), gr7    */
+  tramp[6] = 0x9cc86000;                  /* ldi @(gr6, #0), gr14  */
+  tramp[7] = 0x8030e000;                  /* jmpl @(gr14, gr0)     */
+#else
+  tramp[0] = 0x8cfc0000 + (fn  & 0xffff); /* setlos lo(fn), gr6    */
+  tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7   */
+  tramp[2] = 0x8cf80000 + (fn  >> 16);	  /* sethi hi(fn), gr6     */
+  tramp[3] = 0x8ef80000 + (cls >> 16);    /* sethi hi(cls), gr7    */
+  tramp[4] = 0x80300006;                  /* jmpl @(gr0, gr6)      */
+#endif
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Cache flushing.  */
+  for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
+    __asm__ volatile ("dcf @(%0,%1)\n\tici @(%2,%1)" :: "r" (tramp), "r" (i),
+		      "r" (codeloc));
+
+  return FFI_OK;
+}
diff --git a/third_party/gofrontend/libffi/src/frv/ffitarget.h b/third_party/gofrontend/libffi/src/frv/ffitarget.h
new file mode 100644
index 0000000..d42540e
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/frv/ffitarget.h
@@ -0,0 +1,62 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2004  Red Hat, Inc.
+   Target configuration macros for FR-V
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+/* ---- System specific configurations ----------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_EABI,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_EABI
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+#ifdef __FRV_FDPIC__
+/* Trampolines are 8 4-byte instructions long.  */
+#define FFI_TRAMPOLINE_SIZE (8*4)
+#else
+/* Trampolines are 5 4-byte instructions long.  */
+#define FFI_TRAMPOLINE_SIZE (5*4)
+#endif
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/ia64/ffi.c b/third_party/gofrontend/libffi/src/ia64/ffi.c
new file mode 100644
index 0000000..9533ef6
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/ia64/ffi.c
@@ -0,0 +1,586 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc.
+	   Copyright (c) 2000 Hewlett Packard Company
+	   Copyright (c) 2011 Anthony Green
+   
+   IA64 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <float.h>
+
+#include "ia64_flags.h"
+
+/* A 64-bit pointer value.  In LP64 mode, this is effectively a plain
+   pointer.  In ILP32 mode, it's a pointer that's been extended to 
+   64 bits by "addp4".  */
+typedef void *PTR64 __attribute__((mode(DI)));
+
+/* Memory image of fp register contents.  This is the implementation
+   specific format used by ldf.fill/stf.spill.  All we care about is
+   that it wants a 16 byte aligned slot.  */
+typedef struct
+{
+  UINT64 x[2] __attribute__((aligned(16)));
+} fpreg;
+
+
+/* The stack layout given to ffi_call_unix and ffi_closure_unix_inner.  */
+
+struct ia64_args
+{
+  fpreg fp_regs[8];	/* Contents of 8 fp arg registers.  */
+  UINT64 gp_regs[8];	/* Contents of 8 gp arg registers.  */
+  UINT64 other_args[];	/* Arguments passed on stack, variable size.  */
+};
+
+
+/* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes.  */
+
+static inline void *
+endian_adjust (void *addr, size_t len)
+{
+#ifdef __BIG_ENDIAN__
+  return addr + (8 - len);
+#else
+  return addr;
+#endif
+}
+
+/* Store VALUE to ADDR in the current cpu implementation's fp spill format.
+   This is a macro instead of a function, so that it works for all 3 floating
+   point types without type conversions.  Type conversion to long double breaks
+   the denorm support.  */
+
+#define stf_spill(addr, value)	\
+  asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
+
+/* Load a value from ADDR, which is in the current cpu implementation's
+   fp spill format.  As above, this must also be a macro.  */
+
+#define ldf_fill(result, addr)	\
+  asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
+
+/* Return the size of the C type associated with with TYPE.  Which will
+   be one of the FFI_IA64_TYPE_HFA_* values.  */
+
+static size_t
+hfa_type_size (int type)
+{
+  switch (type)
+    {
+    case FFI_IA64_TYPE_HFA_FLOAT:
+      return sizeof(float);
+    case FFI_IA64_TYPE_HFA_DOUBLE:
+      return sizeof(double);
+    case FFI_IA64_TYPE_HFA_LDOUBLE:
+      return sizeof(__float80);
+    default:
+      abort ();
+    }
+}
+
+/* Load from ADDR a value indicated by TYPE.  Which will be one of
+   the FFI_IA64_TYPE_HFA_* values.  */
+
+static void
+hfa_type_load (fpreg *fpaddr, int type, void *addr)
+{
+  switch (type)
+    {
+    case FFI_IA64_TYPE_HFA_FLOAT:
+      stf_spill (fpaddr, *(float *) addr);
+      return;
+    case FFI_IA64_TYPE_HFA_DOUBLE:
+      stf_spill (fpaddr, *(double *) addr);
+      return;
+    case FFI_IA64_TYPE_HFA_LDOUBLE:
+      stf_spill (fpaddr, *(__float80 *) addr);
+      return;
+    default:
+      abort ();
+    }
+}
+
+/* Load VALUE into ADDR as indicated by TYPE.  Which will be one of
+   the FFI_IA64_TYPE_HFA_* values.  */
+
+static void
+hfa_type_store (int type, void *addr, fpreg *fpaddr)
+{
+  switch (type)
+    {
+    case FFI_IA64_TYPE_HFA_FLOAT:
+      {
+	float result;
+	ldf_fill (result, fpaddr);
+	*(float *) addr = result;
+	break;
+      }
+    case FFI_IA64_TYPE_HFA_DOUBLE:
+      {
+	double result;
+	ldf_fill (result, fpaddr);
+	*(double *) addr = result;
+	break;
+      }
+    case FFI_IA64_TYPE_HFA_LDOUBLE:
+      {
+	__float80 result;
+	ldf_fill (result, fpaddr);
+	*(__float80 *) addr = result;
+	break;
+      }
+    default:
+      abort ();
+    }
+}
+
+/* Is TYPE a struct containing floats, doubles, or extended doubles,
+   all of the same fp type?  If so, return the element type.  Return
+   FFI_TYPE_VOID if not.  */
+
+static int
+hfa_element_type (ffi_type *type, int nested)
+{
+  int element = FFI_TYPE_VOID;
+
+  switch (type->type)
+    {
+    case FFI_TYPE_FLOAT:
+      /* We want to return VOID for raw floating-point types, but the
+	 synthetic HFA type if we're nested within an aggregate.  */
+      if (nested)
+	element = FFI_IA64_TYPE_HFA_FLOAT;
+      break;
+
+    case FFI_TYPE_DOUBLE:
+      /* Similarly.  */
+      if (nested)
+	element = FFI_IA64_TYPE_HFA_DOUBLE;
+      break;
+
+    case FFI_TYPE_LONGDOUBLE:
+      /* Similarly, except that that HFA is true for double extended,
+	 but not quad precision.  Both have sizeof == 16, so tell the
+	 difference based on the precision.  */
+      if (LDBL_MANT_DIG == 64 && nested)
+	element = FFI_IA64_TYPE_HFA_LDOUBLE;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      {
+	ffi_type **ptr = &type->elements[0];
+
+	for (ptr = &type->elements[0]; *ptr ; ptr++)
+	  {
+	    int sub_element = hfa_element_type (*ptr, 1);
+	    if (sub_element == FFI_TYPE_VOID)
+	      return FFI_TYPE_VOID;
+
+	    if (element == FFI_TYPE_VOID)
+	      element = sub_element;
+	    else if (element != sub_element)
+	      return FFI_TYPE_VOID;
+	  }
+      }
+      break;
+
+    default:
+      return FFI_TYPE_VOID;
+    }
+
+  return element;
+}
+
+
+/* Perform machine dependent cif processing. */
+
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int flags;
+
+  /* Adjust cif->bytes to include space for the bits of the ia64_args frame
+     that precedes the integer register portion.  The estimate that the
+     generic bits did for the argument space required is good enough for the
+     integer component.  */
+  cif->bytes += offsetof(struct ia64_args, gp_regs[0]);
+  if (cif->bytes < sizeof(struct ia64_args))
+    cif->bytes = sizeof(struct ia64_args);
+
+  /* Set the return type flag. */
+  flags = cif->rtype->type;
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_LONGDOUBLE:
+      /* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision,
+	 and encode quad precision as a two-word integer structure.  */
+      if (LDBL_MANT_DIG != 64)
+	flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8);
+      break;
+
+    case FFI_TYPE_STRUCT:
+      {
+        size_t size = cif->rtype->size;
+  	int hfa_type = hfa_element_type (cif->rtype, 0);
+
+	if (hfa_type != FFI_TYPE_VOID)
+	  {
+	    size_t nelts = size / hfa_type_size (hfa_type);
+	    if (nelts <= 8)
+	      flags = hfa_type | (size << 8);
+	  }
+	else
+	  {
+	    if (size <= 32)
+	      flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8);
+	  }
+      }
+      break;
+
+    default:
+      break;
+    }
+  cif->flags = flags;
+
+  return FFI_OK;
+}
+
+extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64);
+
+void
+ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  struct ia64_args *stack;
+  long i, avn, gpcount, fpcount;
+  ffi_type **p_arg;
+
+  FFI_ASSERT (cif->abi == FFI_UNIX);
+
+  /* If we have no spot for a return value, make one.  */
+  if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID)
+    rvalue = alloca (cif->rtype->size);
+    
+  /* Allocate the stack frame.  */
+  stack = alloca (cif->bytes);
+
+  gpcount = fpcount = 0;
+  avn = cif->nargs;
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      switch ((*p_arg)->type)
+	{
+	case FFI_TYPE_SINT8:
+	  stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i];
+	  break;
+	case FFI_TYPE_UINT8:
+	  stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i];
+	  break;
+	case FFI_TYPE_SINT16:
+	  stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i];
+	  break;
+	case FFI_TYPE_UINT16:
+	  stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i];
+	  break;
+	case FFI_TYPE_SINT32:
+	  stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i];
+	  break;
+	case FFI_TYPE_UINT32:
+	  stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
+	  break;
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	  stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
+	  break;
+
+	case FFI_TYPE_POINTER:
+	  stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i];
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  if (gpcount < 8 && fpcount < 8)
+	    stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]);
+	  {
+	    UINT32 tmp;
+	    memcpy (&tmp, avalue[i], sizeof (UINT32));
+	    stack->gp_regs[gpcount++] = tmp;
+	  }
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  if (gpcount < 8 && fpcount < 8)
+	    stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]);
+	  memcpy (&stack->gp_regs[gpcount++], avalue[i], sizeof (UINT64));
+	  break;
+
+	case FFI_TYPE_LONGDOUBLE:
+	  if (gpcount & 1)
+	    gpcount++;
+	  if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
+	    stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]);
+	  memcpy (&stack->gp_regs[gpcount], avalue[i], 16);
+	  gpcount += 2;
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  {
+	    size_t size = (*p_arg)->size;
+	    size_t align = (*p_arg)->alignment;
+	    int hfa_type = hfa_element_type (*p_arg, 0);
+
+	    FFI_ASSERT (align <= 16);
+	    if (align == 16 && (gpcount & 1))
+	      gpcount++;
+
+	    if (hfa_type != FFI_TYPE_VOID)
+	      {
+		size_t hfa_size = hfa_type_size (hfa_type);
+		size_t offset = 0;
+		size_t gp_offset = gpcount * 8;
+
+		while (fpcount < 8
+		       && offset < size
+		       && gp_offset < 8 * 8)
+		  {
+		    hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
+				   avalue[i] + offset);
+		    offset += hfa_size;
+		    gp_offset += hfa_size;
+		    fpcount += 1;
+		  }
+	      }
+
+	    memcpy (&stack->gp_regs[gpcount], avalue[i], size);
+	    gpcount += (size + 7) / 8;
+	  }
+	  break;
+
+	default:
+	  abort ();
+	}
+    }
+
+  ffi_call_unix (stack, rvalue, fn, cif->flags);
+}
+
+/* Closures represent a pair consisting of a function pointer, and
+   some user data.  A closure is invoked by reinterpreting the closure
+   as a function pointer, and branching to it.  Thus we can make an
+   interpreted function callable as a C function: We turn the
+   interpreter itself, together with a pointer specifying the
+   interpreted procedure, into a closure.
+
+   For IA64, function pointer are already pairs consisting of a code
+   pointer, and a gp pointer.  The latter is needed to access global
+   variables.  Here we set up such a pair as the first two words of
+   the closure (in the "trampoline" area), but we replace the gp
+   pointer with a pointer to the closure itself.  We also add the real
+   gp pointer to the closure.  This allows the function entry code to
+   both retrieve the user data, and to restire the correct gp pointer.  */
+
+extern void ffi_closure_unix ();
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*,void*,void**,void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  /* The layout of a function descriptor.  A C function pointer really 
+     points to one of these.  */
+  struct ia64_fd
+  {
+    UINT64 code_pointer;
+    UINT64 gp;
+  };
+
+  struct ffi_ia64_trampoline_struct
+  {
+    UINT64 code_pointer;	/* Pointer to ffi_closure_unix.  */
+    UINT64 fake_gp;		/* Pointer to closure, installed as gp.  */
+    UINT64 real_gp;		/* Real gp value.  */
+  };
+
+  struct ffi_ia64_trampoline_struct *tramp;
+  struct ia64_fd *fd;
+
+  if (cif->abi != FFI_UNIX)
+    return FFI_BAD_ABI;
+
+  tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
+  fd = (struct ia64_fd *)(void *)ffi_closure_unix;
+
+  tramp->code_pointer = fd->code_pointer;
+  tramp->real_gp = fd->gp;
+  tramp->fake_gp = (UINT64)(PTR64)codeloc;
+  closure->cif = cif;
+  closure->user_data = user_data;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
+
+
+UINT64
+ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
+			void *rvalue, void *r8)
+{
+  ffi_cif *cif;
+  void **avalue;
+  ffi_type **p_arg;
+  long i, avn, gpcount, fpcount;
+
+  cif = closure->cif;
+  avn = cif->nargs;
+  avalue = alloca (avn * sizeof (void *));
+
+  /* If the structure return value is passed in memory get that location
+     from r8 so as to pass the value directly back to the caller.  */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    rvalue = r8;
+
+  gpcount = fpcount = 0;
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      switch ((*p_arg)->type)
+	{
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	  avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1);
+	  break;
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	  avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2);
+	  break;
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	  avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4);
+	  break;
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	  avalue[i] = &stack->gp_regs[gpcount++];
+	  break;
+	case FFI_TYPE_POINTER:
+	  avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*));
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  if (gpcount < 8 && fpcount < 8)
+	    {
+	      fpreg *addr = &stack->fp_regs[fpcount++];
+	      float result;
+	      avalue[i] = addr;
+	      ldf_fill (result, addr);
+	      *(float *)addr = result;
+	    }
+	  else
+	    avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
+	  gpcount++;
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  if (gpcount < 8 && fpcount < 8)
+	    {
+	      fpreg *addr = &stack->fp_regs[fpcount++];
+	      double result;
+	      avalue[i] = addr;
+	      ldf_fill (result, addr);
+	      *(double *)addr = result;
+	    }
+	  else
+	    avalue[i] = &stack->gp_regs[gpcount];
+	  gpcount++;
+	  break;
+
+	case FFI_TYPE_LONGDOUBLE:
+	  if (gpcount & 1)
+	    gpcount++;
+	  if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
+	    {
+	      fpreg *addr = &stack->fp_regs[fpcount++];
+	      __float80 result;
+	      avalue[i] = addr;
+	      ldf_fill (result, addr);
+	      *(__float80 *)addr = result;
+	    }
+	  else
+	    avalue[i] = &stack->gp_regs[gpcount];
+	  gpcount += 2;
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  {
+	    size_t size = (*p_arg)->size;
+	    size_t align = (*p_arg)->alignment;
+	    int hfa_type = hfa_element_type (*p_arg, 0);
+
+	    FFI_ASSERT (align <= 16);
+	    if (align == 16 && (gpcount & 1))
+	      gpcount++;
+
+	    if (hfa_type != FFI_TYPE_VOID)
+	      {
+		size_t hfa_size = hfa_type_size (hfa_type);
+		size_t offset = 0;
+		size_t gp_offset = gpcount * 8;
+		void *addr = alloca (size);
+
+		avalue[i] = addr;
+
+		while (fpcount < 8
+		       && offset < size
+		       && gp_offset < 8 * 8)
+		  {
+		    hfa_type_store (hfa_type, addr + offset,
+				    &stack->fp_regs[fpcount]);
+		    offset += hfa_size;
+		    gp_offset += hfa_size;
+		    fpcount += 1;
+		  }
+
+		if (offset < size)
+		  memcpy (addr + offset, (char *)stack->gp_regs + gp_offset,
+			  size - offset);
+	      }
+	    else
+	      avalue[i] = &stack->gp_regs[gpcount];
+
+	    gpcount += (size + 7) / 8;
+	  }
+	  break;
+
+	default:
+	  abort ();
+	}
+    }
+
+  closure->fun (cif, rvalue, avalue, closure->user_data);
+
+  return cif->flags;
+}
diff --git a/third_party/gofrontend/libffi/src/ia64/ffitarget.h b/third_party/gofrontend/libffi/src/ia64/ffitarget.h
new file mode 100644
index 0000000..e68cea6
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/ia64/ffitarget.h
@@ -0,0 +1,55 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for IA-64.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long long          ffi_arg;
+typedef signed long long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_UNIX,   	/* Linux and all Unix variants use the same conventions	*/
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_UNIX
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 24  /* Really the following struct, which 	*/
+				/* can be interpreted as a C function	*/
+				/* descriptor:				*/
+
+#endif
+
diff --git a/third_party/gofrontend/libffi/src/ia64/ia64_flags.h b/third_party/gofrontend/libffi/src/ia64/ia64_flags.h
new file mode 100644
index 0000000..9d652ce
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/ia64/ia64_flags.h
@@ -0,0 +1,40 @@
+/* -----------------------------------------------------------------------
+   ia64_flags.h - Copyright (c) 2000 Hewlett Packard Company
+   
+   IA64/unix Foreign Function Interface 
+
+   Original author: Hans Boehm, HP Labs
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+/* "Type" codes used between assembly and C.  When used as a part of
+   a cfi->flags value, the low byte will be these extra type codes,
+   and bits 8-31 will be the actual size of the type.  */
+
+/* Small structures containing N words in integer registers.  */
+#define FFI_IA64_TYPE_SMALL_STRUCT	(FFI_TYPE_LAST + 1)
+
+/* Homogeneous Floating Point Aggregates (HFAs) which are returned
+   in FP registers.  */
+#define FFI_IA64_TYPE_HFA_FLOAT		(FFI_TYPE_LAST + 2)
+#define FFI_IA64_TYPE_HFA_DOUBLE	(FFI_TYPE_LAST + 3)
+#define FFI_IA64_TYPE_HFA_LDOUBLE	(FFI_TYPE_LAST + 4)
diff --git a/third_party/gofrontend/libffi/src/ia64/unix.S b/third_party/gofrontend/libffi/src/ia64/unix.S
new file mode 100644
index 0000000..4d2a86d
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/ia64/unix.S
@@ -0,0 +1,560 @@
+/* -----------------------------------------------------------------------
+   unix.S - Copyright (c) 1998, 2008 Red Hat, Inc.
+            Copyright (c) 2000 Hewlett Packard Company
+   
+   IA64/unix Foreign Function Interface 
+
+   Primary author: Hans Boehm, HP Labs
+
+   Loosely modeled on Cygnus code for other platforms.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+#include "ia64_flags.h"
+
+	.pred.safe_across_calls p1-p5,p16-p63
+.text
+
+/* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
+		      void (*fn)(void), int flags);
+ */
+
+        .align 16
+        .global	ffi_call_unix
+        .proc	ffi_call_unix
+ffi_call_unix:
+	.prologue
+	/* Bit o trickiness.  We actually share a stack frame with ffi_call.
+	   Rely on the fact that ffi_call uses a vframe and don't bother
+	   tracking one here at all.  */
+	.fframe	0
+	.save	ar.pfs, r36 // loc0
+	alloc   loc0 = ar.pfs, 4, 3, 8, 0
+	.save	rp, loc1
+	mov 	loc1 = b0
+	.body
+	add	r16 = 16, in0
+	mov	loc2 = gp
+	mov	r8 = in1
+	;;
+
+	/* Load up all of the argument registers.  */
+	ldf.fill f8 = [in0], 32
+	ldf.fill f9 = [r16], 32
+	;;
+	ldf.fill f10 = [in0], 32
+	ldf.fill f11 = [r16], 32
+	;;
+	ldf.fill f12 = [in0], 32
+	ldf.fill f13 = [r16], 32
+	;;
+	ldf.fill f14 = [in0], 32
+	ldf.fill f15 = [r16], 24
+	;;
+	ld8	out0 = [in0], 16
+	ld8	out1 = [r16], 16
+	;;
+	ld8	out2 = [in0], 16
+	ld8	out3 = [r16], 16
+	;;
+	ld8	out4 = [in0], 16
+	ld8	out5 = [r16], 16
+	;;
+	ld8	out6 = [in0]
+	ld8	out7 = [r16]
+	;;
+
+	/* Deallocate the register save area from the stack frame.  */
+	mov	sp = in0
+
+	/* Call the target function.  */
+	ld8	r16 = [in2], 8
+	;;
+	ld8	gp = [in2]
+	mov	b6 = r16
+	br.call.sptk.many b0 = b6
+	;;
+
+	/* Dispatch to handle return value.  */
+	mov	gp = loc2
+	zxt1	r16 = in3
+	;;
+	mov	ar.pfs = loc0
+	addl	r18 = @ltoffx(.Lst_table), gp
+	;;
+	ld8.mov	r18 = [r18], .Lst_table
+	mov	b0 = loc1
+	;;
+	shladd	r18 = r16, 3, r18
+	;;
+	ld8	r17 = [r18]
+	shr	in3 = in3, 8
+	;;
+	add	r17 = r17, r18
+	;;
+	mov	b6 = r17
+	br	b6
+	;;
+
+.Lst_void:
+	br.ret.sptk.many b0
+	;;
+.Lst_uint8:
+	zxt1	r8 = r8
+	;;
+	st8	[in1] = r8
+	br.ret.sptk.many b0
+	;;
+.Lst_sint8:
+	sxt1	r8 = r8
+	;;
+	st8	[in1] = r8
+	br.ret.sptk.many b0
+	;;
+.Lst_uint16:
+	zxt2	r8 = r8
+	;;
+	st8	[in1] = r8
+	br.ret.sptk.many b0
+	;;
+.Lst_sint16:
+	sxt2	r8 = r8
+	;;
+	st8	[in1] = r8
+	br.ret.sptk.many b0
+	;;
+.Lst_uint32:
+	zxt4	r8 = r8
+	;;
+	st8	[in1] = r8
+	br.ret.sptk.many b0
+	;;
+.Lst_sint32:
+	sxt4	r8 = r8
+	;;
+	st8	[in1] = r8
+	br.ret.sptk.many b0
+	;;
+.Lst_int64:
+	st8	[in1] = r8
+	br.ret.sptk.many b0
+	;;
+.Lst_float:
+	stfs	[in1] = f8
+	br.ret.sptk.many b0
+	;;
+.Lst_double:
+	stfd	[in1] = f8
+	br.ret.sptk.many b0
+	;;
+.Lst_ldouble:
+	stfe	[in1] = f8
+	br.ret.sptk.many b0
+	;;
+
+.Lst_small_struct:
+	add	sp = -16, sp
+	cmp.lt	p6, p0 = 8, in3
+	cmp.lt	p7, p0 = 16, in3
+	cmp.lt	p8, p0 = 24, in3
+	;;
+	add	r16 = 8, sp
+	add	r17 = 16, sp
+	add	r18 = 24, sp
+	;;
+	st8	[sp] = r8
+(p6)	st8	[r16] = r9
+	mov	out0 = in1
+(p7)	st8	[r17] = r10
+(p8)	st8	[r18] = r11
+	mov	out1 = sp
+	mov	out2 = in3
+	br.call.sptk.many b0 = memcpy#
+	;;
+	mov	ar.pfs = loc0
+	mov	b0 = loc1
+	mov	gp = loc2
+	br.ret.sptk.many b0
+
+.Lst_hfa_float:
+	add	r16 = 4, in1
+	cmp.lt	p6, p0 = 4, in3
+	;;
+	stfs	[in1] = f8, 8
+(p6)	stfs	[r16] = f9, 8
+	cmp.lt	p7, p0 = 8, in3
+	cmp.lt	p8, p0 = 12, in3
+	;;
+(p7)	stfs	[in1] = f10, 8
+(p8)	stfs	[r16] = f11, 8
+	cmp.lt	p9, p0 = 16, in3
+	cmp.lt	p10, p0 = 20, in3
+	;;
+(p9)	stfs	[in1] = f12, 8
+(p10)	stfs	[r16] = f13, 8
+	cmp.lt	p6, p0 = 24, in3
+	cmp.lt	p7, p0 = 28, in3
+	;;
+(p6)	stfs	[in1] = f14
+(p7)	stfs	[r16] = f15
+	br.ret.sptk.many b0
+	;;
+
+.Lst_hfa_double:
+	add	r16 = 8, in1
+	cmp.lt	p6, p0 = 8, in3
+	;;
+	stfd	[in1] = f8, 16
+(p6)	stfd	[r16] = f9, 16
+	cmp.lt	p7, p0 = 16, in3
+	cmp.lt	p8, p0 = 24, in3
+	;;
+(p7)	stfd	[in1] = f10, 16
+(p8)	stfd	[r16] = f11, 16
+	cmp.lt	p9, p0 = 32, in3
+	cmp.lt	p10, p0 = 40, in3
+	;;
+(p9)	stfd	[in1] = f12, 16
+(p10)	stfd	[r16] = f13, 16
+	cmp.lt	p6, p0 = 48, in3
+	cmp.lt	p7, p0 = 56, in3
+	;;
+(p6)	stfd	[in1] = f14
+(p7)	stfd	[r16] = f15
+	br.ret.sptk.many b0
+	;;
+
+.Lst_hfa_ldouble:
+	add	r16 = 16, in1
+	cmp.lt	p6, p0 = 16, in3
+	;;
+	stfe	[in1] = f8, 32
+(p6)	stfe	[r16] = f9, 32
+	cmp.lt	p7, p0 = 32, in3
+	cmp.lt	p8, p0 = 48, in3
+	;;
+(p7)	stfe	[in1] = f10, 32
+(p8)	stfe	[r16] = f11, 32
+	cmp.lt	p9, p0 = 64, in3
+	cmp.lt	p10, p0 = 80, in3
+	;;
+(p9)	stfe	[in1] = f12, 32
+(p10)	stfe	[r16] = f13, 32
+	cmp.lt	p6, p0 = 96, in3
+	cmp.lt	p7, p0 = 112, in3
+	;;
+(p6)	stfe	[in1] = f14
+(p7)	stfe	[r16] = f15
+	br.ret.sptk.many b0
+	;;
+
+        .endp ffi_call_unix
+
+        .align 16
+        .global ffi_closure_unix
+        .proc ffi_closure_unix
+
+#define FRAME_SIZE	(8*16 + 8*8 + 8*16)
+
+ffi_closure_unix:
+	.prologue
+	.save	ar.pfs, r40 // loc0
+	alloc   loc0 = ar.pfs, 8, 4, 4, 0
+	.fframe	FRAME_SIZE
+	add	r12 = -FRAME_SIZE, r12
+	.save	rp, loc1
+	mov	loc1 = b0
+	.save	ar.unat, loc2
+	mov	loc2 = ar.unat
+	.body
+
+	/* Retrieve closure pointer and real gp.  */
+#ifdef _ILP32
+	addp4	out0 = 0, gp
+	addp4	gp = 16, gp
+#else
+	mov	out0 = gp
+	add	gp = 16, gp
+#endif
+	;;
+	ld8	gp = [gp]
+
+	/* Spill all of the possible argument registers.  */
+	add	r16 = 16 + 8*16, sp
+	add	r17 = 16 + 8*16 + 16, sp
+	;;
+	stf.spill [r16] = f8, 32
+	stf.spill [r17] = f9, 32
+	mov	loc3 = gp
+	;;
+	stf.spill [r16] = f10, 32
+	stf.spill [r17] = f11, 32
+	;;
+	stf.spill [r16] = f12, 32
+	stf.spill [r17] = f13, 32
+	;;
+	stf.spill [r16] = f14, 32
+	stf.spill [r17] = f15, 24
+	;;
+	.mem.offset 0, 0
+	st8.spill [r16] = in0, 16
+	.mem.offset 8, 0
+	st8.spill [r17] = in1, 16
+	add	out1 = 16 + 8*16, sp
+	;;
+	.mem.offset 0, 0
+	st8.spill [r16] = in2, 16
+	.mem.offset 8, 0
+	st8.spill [r17] = in3, 16
+	add	out2 = 16, sp
+	;;
+	.mem.offset 0, 0
+	st8.spill [r16] = in4, 16
+	.mem.offset 8, 0
+	st8.spill [r17] = in5, 16
+	mov	out3 = r8
+	;;
+	.mem.offset 0, 0
+	st8.spill [r16] = in6
+	.mem.offset 8, 0
+	st8.spill [r17] = in7
+
+	/* Invoke ffi_closure_unix_inner for the hard work.  */
+	br.call.sptk.many b0 = ffi_closure_unix_inner
+	;;
+
+	/* Dispatch to handle return value.  */
+	mov	gp = loc3
+	zxt1	r16 = r8
+	;;
+	addl	r18 = @ltoffx(.Lld_table), gp
+	mov	ar.pfs = loc0
+	;;
+	ld8.mov	r18 = [r18], .Lld_table
+	mov	b0 = loc1
+	;;
+	shladd	r18 = r16, 3, r18
+	mov	ar.unat = loc2
+	;;
+	ld8	r17 = [r18]
+	shr	r8 = r8, 8
+	;;
+	add	r17 = r17, r18
+	add	r16 = 16, sp
+	;;
+	mov	b6 = r17
+	br	b6
+	;;
+	.label_state 1
+
+.Lld_void:
+	.restore sp
+	add	sp = FRAME_SIZE, sp
+	br.ret.sptk.many b0
+	;;
+.Lld_int:
+	.body
+	.copy_state 1
+	ld8	r8 = [r16]
+	.restore sp
+	add	sp = FRAME_SIZE, sp
+	br.ret.sptk.many b0
+	;;
+.Lld_float:
+	.body
+	.copy_state 1
+	ldfs	f8 = [r16]
+	.restore sp
+	add	sp = FRAME_SIZE, sp
+	br.ret.sptk.many b0
+	;;
+.Lld_double:
+	.body
+	.copy_state 1
+	ldfd	f8 = [r16]
+	.restore sp
+	add	sp = FRAME_SIZE, sp
+	br.ret.sptk.many b0
+	;;
+.Lld_ldouble:
+	.body
+	.copy_state 1
+	ldfe	f8 = [r16]
+	.restore sp
+	add	sp = FRAME_SIZE, sp
+	br.ret.sptk.many b0
+	;;
+
+.Lld_small_struct:
+	.body
+	.copy_state 1
+	add	r17 = 8, r16
+	cmp.lt	p6, p0 = 8, r8
+	cmp.lt	p7, p0 = 16, r8
+	cmp.lt	p8, p0 = 24, r8
+	;;
+	ld8	r8 = [r16], 16
+(p6)	ld8	r9 = [r17], 16
+	;;
+(p7)	ld8	r10 = [r16]
+(p8)	ld8	r11 = [r17]
+	.restore sp
+	add	sp = FRAME_SIZE, sp
+	br.ret.sptk.many b0
+	;;
+
+.Lld_hfa_float:
+	.body
+	.copy_state 1
+	add	r17 = 4, r16
+	cmp.lt	p6, p0 = 4, r8
+	;;
+	ldfs	f8 = [r16], 8
+(p6)	ldfs	f9 = [r17], 8
+	cmp.lt	p7, p0 = 8, r8
+	cmp.lt	p8, p0 = 12, r8
+	;;
+(p7)	ldfs	f10 = [r16], 8
+(p8)	ldfs	f11 = [r17], 8
+	cmp.lt	p9, p0 = 16, r8
+	cmp.lt	p10, p0 = 20, r8
+	;;
+(p9)	ldfs	f12 = [r16], 8
+(p10)	ldfs	f13 = [r17], 8
+	cmp.lt	p6, p0 = 24, r8
+	cmp.lt	p7, p0 = 28, r8
+	;;
+(p6)	ldfs	f14 = [r16]
+(p7)	ldfs	f15 = [r17]
+	.restore sp
+	add	sp = FRAME_SIZE, sp
+	br.ret.sptk.many b0
+	;;
+
+.Lld_hfa_double:
+	.body
+	.copy_state 1
+	add	r17 = 8, r16
+	cmp.lt	p6, p0 = 8, r8
+	;;
+	ldfd	f8 = [r16], 16
+(p6)	ldfd	f9 = [r17], 16
+	cmp.lt	p7, p0 = 16, r8
+	cmp.lt	p8, p0 = 24, r8
+	;;
+(p7)	ldfd	f10 = [r16], 16
+(p8)	ldfd	f11 = [r17], 16
+	cmp.lt	p9, p0 = 32, r8
+	cmp.lt	p10, p0 = 40, r8
+	;;
+(p9)	ldfd	f12 = [r16], 16
+(p10)	ldfd	f13 = [r17], 16
+	cmp.lt	p6, p0 = 48, r8
+	cmp.lt	p7, p0 = 56, r8
+	;;
+(p6)	ldfd	f14 = [r16]
+(p7)	ldfd	f15 = [r17]
+	.restore sp
+	add	sp = FRAME_SIZE, sp
+	br.ret.sptk.many b0
+	;;
+
+.Lld_hfa_ldouble:
+	.body
+	.copy_state 1
+	add	r17 = 16, r16
+	cmp.lt	p6, p0 = 16, r8
+	;;
+	ldfe	f8 = [r16], 32
+(p6)	ldfe	f9 = [r17], 32
+	cmp.lt	p7, p0 = 32, r8
+	cmp.lt	p8, p0 = 48, r8
+	;;
+(p7)	ldfe	f10 = [r16], 32
+(p8)	ldfe	f11 = [r17], 32
+	cmp.lt	p9, p0 = 64, r8
+	cmp.lt	p10, p0 = 80, r8
+	;;
+(p9)	ldfe	f12 = [r16], 32
+(p10)	ldfe	f13 = [r17], 32
+	cmp.lt	p6, p0 = 96, r8
+	cmp.lt	p7, p0 = 112, r8
+	;;
+(p6)	ldfe	f14 = [r16]
+(p7)	ldfe	f15 = [r17]
+	.restore sp
+	add	sp = FRAME_SIZE, sp
+	br.ret.sptk.many b0
+	;;
+
+	.endp	ffi_closure_unix
+
+	.section .rodata
+	.align	8
+.Lst_table:
+	data8	@pcrel(.Lst_void)		// FFI_TYPE_VOID
+	data8	@pcrel(.Lst_sint32)		// FFI_TYPE_INT
+	data8	@pcrel(.Lst_float)		// FFI_TYPE_FLOAT
+	data8	@pcrel(.Lst_double)		// FFI_TYPE_DOUBLE
+	data8	@pcrel(.Lst_ldouble)		// FFI_TYPE_LONGDOUBLE
+	data8	@pcrel(.Lst_uint8)		// FFI_TYPE_UINT8
+	data8	@pcrel(.Lst_sint8)		// FFI_TYPE_SINT8
+	data8	@pcrel(.Lst_uint16)		// FFI_TYPE_UINT16
+	data8	@pcrel(.Lst_sint16)		// FFI_TYPE_SINT16
+	data8	@pcrel(.Lst_uint32)		// FFI_TYPE_UINT32
+	data8	@pcrel(.Lst_sint32)		// FFI_TYPE_SINT32
+	data8	@pcrel(.Lst_int64)		// FFI_TYPE_UINT64
+	data8	@pcrel(.Lst_int64)		// FFI_TYPE_SINT64
+	data8	@pcrel(.Lst_void)		// FFI_TYPE_STRUCT
+	data8	@pcrel(.Lst_int64)		// FFI_TYPE_POINTER
+	data8 	@pcrel(.Lst_small_struct)	// FFI_IA64_TYPE_SMALL_STRUCT
+	data8	@pcrel(.Lst_hfa_float)		// FFI_IA64_TYPE_HFA_FLOAT
+	data8	@pcrel(.Lst_hfa_double)		// FFI_IA64_TYPE_HFA_DOUBLE
+	data8	@pcrel(.Lst_hfa_ldouble)	// FFI_IA64_TYPE_HFA_LDOUBLE
+
+.Lld_table:
+	data8	@pcrel(.Lld_void)		// FFI_TYPE_VOID
+	data8	@pcrel(.Lld_int)		// FFI_TYPE_INT
+	data8	@pcrel(.Lld_float)		// FFI_TYPE_FLOAT
+	data8	@pcrel(.Lld_double)		// FFI_TYPE_DOUBLE
+	data8	@pcrel(.Lld_ldouble)		// FFI_TYPE_LONGDOUBLE
+	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT8
+	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT8
+	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT16
+	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT16
+	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT32
+	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT32
+	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT64
+	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT64
+	data8	@pcrel(.Lld_void)		// FFI_TYPE_STRUCT
+	data8	@pcrel(.Lld_int)		// FFI_TYPE_POINTER
+	data8 	@pcrel(.Lld_small_struct)	// FFI_IA64_TYPE_SMALL_STRUCT
+	data8	@pcrel(.Lld_hfa_float)		// FFI_IA64_TYPE_HFA_FLOAT
+	data8	@pcrel(.Lld_hfa_double)		// FFI_IA64_TYPE_HFA_DOUBLE
+	data8	@pcrel(.Lld_hfa_ldouble)	// FFI_IA64_TYPE_HFA_LDOUBLE
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/java_raw_api.c b/third_party/gofrontend/libffi/src/java_raw_api.c
new file mode 100644
index 0000000..d8e79ea
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/java_raw_api.c
@@ -0,0 +1,356 @@
+/* -----------------------------------------------------------------------
+   java_raw_api.c - Copyright (c) 1999, 2007, 2008  Red Hat, Inc.
+
+   Cloned from raw_api.c
+
+   Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
+   Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
+
+   $Id $
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+/* This defines a Java- and 64-bit specific variant of the raw API.	*/
+/* It assumes that "raw" argument blocks look like Java stacks on a	*/
+/* 64-bit machine.  Arguments that can be stored in a single stack	*/
+/* stack slots (longs, doubles) occupy 128 bits, but only the first	*/
+/* 64 bits are actually used.						*/
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+
+#if !defined(NO_JAVA_RAW_API)
+
+size_t
+ffi_java_raw_size (ffi_cif *cif)
+{
+  size_t result = 0;
+  int i;
+
+  ffi_type **at = cif->arg_types;
+
+  for (i = cif->nargs-1; i >= 0; i--, at++)
+    {
+      switch((*at) -> type) {
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_DOUBLE:
+	  result += 2 * FFI_SIZEOF_JAVA_RAW;
+	  break;
+	case FFI_TYPE_STRUCT:
+	  /* No structure parameters in Java.	*/
+	  abort();
+	default:
+	  result += FFI_SIZEOF_JAVA_RAW;
+      }
+    }
+
+  return result;
+}
+
+
+void
+ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+#if WORDS_BIGENDIAN
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {
+      switch ((*tp)->type)
+	{
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT8:
+	  *args = (void*) ((char*)(raw++) + 3);
+	  break;
+
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT16:
+	  *args = (void*) ((char*)(raw++) + 2);
+	  break;
+
+#if FFI_SIZEOF_JAVA_RAW == 8
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_DOUBLE:
+	  *args = (void *)raw;
+	  raw += 2;
+	  break;
+#endif
+
+	case FFI_TYPE_POINTER:
+	  *args = (void*) &(raw++)->ptr;
+	  break;
+
+	default:
+	  *args = raw;
+	  raw +=
+	    ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
+	}
+    }
+
+#else /* WORDS_BIGENDIAN */
+
+#if !PDP
+
+  /* then assume little endian */
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {
+#if FFI_SIZEOF_JAVA_RAW == 8
+      switch((*tp)->type) {
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_DOUBLE:
+	  *args = (void*) raw;
+	  raw += 2;
+	  break;
+	default:
+	  *args = (void*) raw++;
+      }
+#else /* FFI_SIZEOF_JAVA_RAW != 8 */
+	*args = (void*) raw;
+	raw +=
+	  ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
+#endif /* FFI_SIZEOF_JAVA_RAW == 8 */
+    }
+
+#else
+#error "pdp endian not supported"
+#endif /* ! PDP */
+
+#endif /* WORDS_BIGENDIAN */
+}
+
+void
+ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {
+      switch ((*tp)->type)
+	{
+	case FFI_TYPE_UINT8:
+#if WORDS_BIGENDIAN
+	  *(UINT32*)(raw++) = *(UINT8*) (*args);
+#else
+	  (raw++)->uint = *(UINT8*) (*args);
+#endif
+	  break;
+
+	case FFI_TYPE_SINT8:
+#if WORDS_BIGENDIAN
+	  *(SINT32*)(raw++) = *(SINT8*) (*args);
+#else
+	  (raw++)->sint = *(SINT8*) (*args);
+#endif
+	  break;
+
+	case FFI_TYPE_UINT16:
+#if WORDS_BIGENDIAN
+	  *(UINT32*)(raw++) = *(UINT16*) (*args);
+#else
+	  (raw++)->uint = *(UINT16*) (*args);
+#endif
+	  break;
+
+	case FFI_TYPE_SINT16:
+#if WORDS_BIGENDIAN
+	  *(SINT32*)(raw++) = *(SINT16*) (*args);
+#else
+	  (raw++)->sint = *(SINT16*) (*args);
+#endif
+	  break;
+
+	case FFI_TYPE_UINT32:
+#if WORDS_BIGENDIAN
+	  *(UINT32*)(raw++) = *(UINT32*) (*args);
+#else
+	  (raw++)->uint = *(UINT32*) (*args);
+#endif
+	  break;
+
+	case FFI_TYPE_SINT32:
+#if WORDS_BIGENDIAN
+	  *(SINT32*)(raw++) = *(SINT32*) (*args);
+#else
+	  (raw++)->sint = *(SINT32*) (*args);
+#endif
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  (raw++)->flt = *(FLOAT32*) (*args);
+	  break;
+
+#if FFI_SIZEOF_JAVA_RAW == 8
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_DOUBLE:
+	  raw->uint = *(UINT64*) (*args);
+	  raw += 2;
+	  break;
+#endif
+
+	case FFI_TYPE_POINTER:
+	  (raw++)->ptr = **(void***) args;
+	  break;
+
+	default:
+#if FFI_SIZEOF_JAVA_RAW == 8
+	  FFI_ASSERT(0);	/* Should have covered all cases */
+#else
+	  memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
+	  raw +=
+	    ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
+#endif
+	}
+    }
+}
+
+#if !FFI_NATIVE_RAW_API
+
+static void
+ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
+{
+#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_UINT32:
+      *(UINT64 *)rvalue <<= 32;
+      break;
+
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_INT:
+#if FFI_SIZEOF_JAVA_RAW == 4
+    case FFI_TYPE_POINTER:
+#endif
+      *(SINT64 *)rvalue <<= 32;
+      break;
+
+    default:
+      break;
+    }
+#endif
+}
+
+static void
+ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
+{
+#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_UINT32:
+      *(UINT64 *)rvalue >>= 32;
+      break;
+
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_INT:
+      *(SINT64 *)rvalue >>= 32;
+      break;
+
+    default:
+      break;
+    }
+#endif
+}
+
+/* This is a generic definition of ffi_raw_call, to be used if the
+ * native system does not provide a machine-specific implementation.
+ * Having this, allows code to be written for the raw API, without
+ * the need for system-specific code to handle input in that format;
+ * these following couple of functions will handle the translation forth
+ * and back automatically. */
+
+void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue,
+			ffi_java_raw *raw)
+{
+  void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
+  ffi_java_raw_to_ptrarray (cif, raw, avalue);
+  ffi_call (cif, fn, rvalue, avalue);
+  ffi_java_rvalue_to_raw (cif, rvalue);
+}
+
+#if FFI_CLOSURES		/* base system provides closures */
+
+static void
+ffi_java_translate_args (ffi_cif *cif, void *rvalue,
+		    void **avalue, void *user_data)
+{
+  ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif));
+  ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
+
+  ffi_java_ptrarray_to_raw (cif, avalue, raw);
+  (*cl->fun) (cif, rvalue, (ffi_raw*)raw, cl->user_data);
+  ffi_java_raw_to_rvalue (cif, rvalue);
+}
+
+ffi_status
+ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl,
+			       ffi_cif *cif,
+			       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
+			       void *user_data,
+			       void *codeloc)
+{
+  ffi_status status;
+
+  status = ffi_prep_closure_loc ((ffi_closure*) cl,
+				 cif,
+				 &ffi_java_translate_args,
+				 codeloc,
+				 codeloc);
+  if (status == FFI_OK)
+    {
+      cl->fun       = fun;
+      cl->user_data = user_data;
+    }
+
+  return status;
+}
+
+/* Again, here is the generic version of ffi_prep_raw_closure, which
+ * will install an intermediate "hub" for translation of arguments from
+ * the pointer-array format, to the raw format */
+
+ffi_status
+ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
+			   ffi_cif *cif,
+			   void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
+			   void *user_data)
+{
+  return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
+}
+
+#endif /* FFI_CLOSURES */
+#endif /* !FFI_NATIVE_RAW_API */
+#endif /* !NO_JAVA_RAW_API */
diff --git a/third_party/gofrontend/libffi/src/m32r/ffi.c b/third_party/gofrontend/libffi/src/m32r/ffi.c
new file mode 100644
index 0000000..3000063
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/m32r/ffi.c
@@ -0,0 +1,232 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2004  Renesas Technology
+           Copyright (c) 2008  Red Hat, Inc.
+   
+   M32R Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack
+   space has been allocated for the function's arguments.  */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  unsigned int i;
+  int tmp;
+  unsigned int avn;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  tmp = 0;
+  argp = stack;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += 4;
+    }
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0) && (avn != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary.  */
+      if (((*p_arg)->alignment - 1) & (unsigned) argp)
+	argp = (char *) ALIGN (argp, (*p_arg)->alignment);
+
+      if (avn != 0) 
+	{
+	  avn--;
+	  z = (*p_arg)->size;
+	  if (z < sizeof (int))
+	    {
+	      z = sizeof (int);
+
+	      switch ((*p_arg)->type)
+		{
+		case FFI_TYPE_SINT8:
+		  *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+		  break;
+		  
+		case FFI_TYPE_UINT8:
+		  *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+		  break;
+		  
+		case FFI_TYPE_SINT16:
+		  *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+		  break;
+		  
+		case FFI_TYPE_UINT16:
+		  *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+		  break;
+		  
+		case FFI_TYPE_STRUCT:
+	  	  z = (*p_arg)->size;
+	  	  if ((*p_arg)->alignment != 1)
+		    memcpy (argp, *p_argv, z);
+		  else
+		    memcpy (argp + 4 - z, *p_argv, z);
+	  	  z = sizeof (int);
+		  break;
+
+		default:
+		  FFI_ASSERT(0);
+		}
+	    }
+	  else if (z == sizeof (int))
+	    {
+	       *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+	    }
+	  else
+	    {
+	      if ((*p_arg)->type == FFI_TYPE_STRUCT)
+	        {
+		  if (z > 8)
+		    {
+		      *(unsigned int *) argp = (unsigned int)(void *)(* p_argv);
+		      z = sizeof(void *);
+		    }
+		  else
+		    {
+	              memcpy(argp, *p_argv, z);
+		      z = 8;
+		    }
+	        }
+	      else
+	        {
+		  /* Double or long long 64bit.  */
+	          memcpy (argp, *p_argv, z);
+	        }
+	    }
+	  p_argv++;
+	  argp += z;
+	}
+    }
+  
+  return;
+}
+
+/* Perform machine dependent cif processing.  */
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Set the return type flag.  */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->rtype->size <= 4)
+	cif->flags = FFI_TYPE_INT;
+
+      else if (cif->rtype->size <= 8)
+	cif->flags = FFI_TYPE_DOUBLE;
+
+      else
+	cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = FFI_TYPE_DOUBLE;
+      break;
+
+    case FFI_TYPE_FLOAT:
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+			  unsigned, unsigned, unsigned *, void (*fn)(void));
+
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have
+     a return value address then we need to make one.  */
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca (cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;    
+  
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
+		    cif->flags, ecif.rvalue, fn);
+      if (cif->rtype->type == FFI_TYPE_STRUCT)
+	{
+	  int size = cif->rtype->size;
+	  int align = cif->rtype->alignment;
+
+	  if (size < 4)
+	    {
+	      if (align == 1)
+	        *(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
+	    }
+	  else if (4 < size && size < 8)
+	    {
+	      if (align == 1)
+		{
+		  memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
+		}
+	      else if (align == 2)
+		{
+		  if (size & 1)
+		    size += 1;
+
+		  if (size != 8)
+		    memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
+		}
+	    }
+	}
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
diff --git a/third_party/gofrontend/libffi/src/m32r/ffitarget.h b/third_party/gofrontend/libffi/src/m32r/ffitarget.h
new file mode 100644
index 0000000..6c34801
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/m32r/ffitarget.h
@@ -0,0 +1,53 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 2004  Renesas Technology.
+   Target configuration macros for M32R.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi
+  {
+    FFI_FIRST_ABI = 0,
+    FFI_SYSV,
+    FFI_LAST_ABI,
+    FFI_DEFAULT_ABI = FFI_SYSV
+  } ffi_abi;
+#endif
+
+#define FFI_CLOSURES 		0
+#define FFI_TRAMPOLINE_SIZE	24
+#define FFI_NATIVE_RAW_API 	0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/m32r/sysv.S b/third_party/gofrontend/libffi/src/m32r/sysv.S
new file mode 100644
index 0000000..06b75c2
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/m32r/sysv.S
@@ -0,0 +1,121 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2004 Renesas Technology
+   
+   M32R Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+/* XXX these lose for some platforms, I'm sure.  */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x)! .type CNAME(x),%function! CNAME(x):
+#endif
+
+.text
+
+	/* R0:   ffi_prep_args */
+	/* R1:   &ecif */
+	/* R2:   cif->bytes */
+	/* R3:   fig->flags */
+	/* sp+0: ecif.rvalue */
+	/* sp+4: fn */
+
+	/* This assumes we are using gas.  */
+ENTRY(ffi_call_SYSV)
+	/* Save registers.  */
+	push	fp
+	push	lr
+	push	r3
+	push	r2
+	push	r1
+	push	r0
+	mv	fp, sp
+
+	/* Make room for all of the new args.  */
+	sub	sp, r2
+
+	/* Place all of the ffi_prep_args in position.  */
+	mv	lr, r0	
+	mv	r0, sp
+	/* R1 already set.  */
+
+	/* And call.  */
+	jl	lr
+
+	/* Move first 4 parameters in registers...  */
+	ld	r0, @(0,sp)
+	ld	r1, @(4,sp)
+	ld	r2, @(8,sp)
+        ld	r3, @(12,sp)
+
+	/* ...and adjust the stack.  */
+	ld	lr, @(8,fp)
+        cmpi	lr, #16
+	bc	adjust_stack
+	ldi	lr, #16
+adjust_stack:
+        add	sp, lr
+
+	/* Call the function.  */
+	ld	lr, @(28,fp)
+	jl	lr	
+
+	/* Remove the space we pushed for the args.  */
+	mv	sp, fp	
+
+	/* Load R2 with the pointer to storage for the return value.  */
+	ld	r2, @(24,sp)
+
+	/* Load R3 with the return type code.  */
+	ld	r3, @(12,sp)
+
+	/* If the return value pointer is NULL, assume no return value.  */
+	beqz	r2, epilogue
+
+	/* Return INT.  */
+	ldi	r4, #FFI_TYPE_INT
+	bne	r3, r4, return_double
+	st	r0, @r2	
+	bra	epilogue
+
+return_double:
+	/* Return DOUBLE or LONGDOUBLE.  */
+	ldi	r4, #FFI_TYPE_DOUBLE
+	bne	r3, r4, epilogue
+	st	r0, @r2	
+	st	r1, @(4,r2)
+
+epilogue:
+	pop	r0
+	pop	r1
+	pop	r2
+	pop	r3
+	pop	lr
+	pop	fp
+        jmp lr
+
+.ffi_call_SYSV_end:
+        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
diff --git a/third_party/gofrontend/libffi/src/m68k/ffi.c b/third_party/gofrontend/libffi/src/m68k/ffi.c
new file mode 100644
index 0000000..37a0784
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/m68k/ffi.c
@@ -0,0 +1,352 @@
+/* -----------------------------------------------------------------------
+   ffi.c
+
+   m68k Foreign Function Interface
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef __rtems__
+void rtems_cache_flush_multiple_data_lines( const void *, size_t );
+#else
+#include <sys/syscall.h>
+#ifdef __MINT__
+#include <mint/mintbind.h>
+#include <mint/ssystem.h>
+#else
+#include <asm/cachectl.h>
+#endif
+#endif
+
+void ffi_call_SYSV (extended_cif *,
+		    unsigned, unsigned,
+		    void *, void (*fn) ());
+void *ffi_prep_args (void *stack, extended_cif *ecif);
+void ffi_closure_SYSV (ffi_closure *);
+void ffi_closure_struct_SYSV (ffi_closure *);
+unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
+				     void *resp, void *args);
+
+/* ffi_prep_args is called by the assembly routine once stack space has
+   been allocated for the function's arguments.  */
+
+void *
+ffi_prep_args (void *stack, extended_cif *ecif)
+{
+  unsigned int i;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+  void *struct_value_ptr;
+
+  argp = stack;
+
+  if (
+#ifdef __MINT__
+      (ecif->cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
+#endif
+      (((ecif->cif->rtype->type == FFI_TYPE_STRUCT)
+        && !ecif->cif->flags)))
+    struct_value_ptr = ecif->rvalue;
+  else
+    struct_value_ptr = NULL;
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i != 0;
+       i--, p_arg++)
+    {
+      size_t z = (*p_arg)->size;
+      int type = (*p_arg)->type;
+
+      if (z < sizeof (int))
+	{
+	  switch (type)
+	    {
+	    case FFI_TYPE_SINT8:
+	      *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_UINT8:
+	      *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_SINT16:
+	      *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_UINT16:
+	      *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_STRUCT:
+#ifdef __MINT__
+	      if (z == 1 || z == 2)
+		memcpy (argp + 2, *p_argv, z);
+              else
+		memcpy (argp, *p_argv, z);
+#else
+	      memcpy (argp + sizeof (int) - z, *p_argv, z);
+#endif
+	      break;
+
+	    default:
+	      FFI_ASSERT (0);
+	    }
+	  z = sizeof (int);
+	}
+      else
+	{
+	  memcpy (argp, *p_argv, z);
+
+	  /* Align if necessary.  */
+	  if ((sizeof(int) - 1) & z)
+	    z = ALIGN(z, sizeof(int));
+	}
+
+      p_argv++;
+      argp += z;
+    }
+
+  return struct_value_ptr;
+}
+
+#define CIF_FLAGS_INT		1
+#define CIF_FLAGS_DINT		2
+#define CIF_FLAGS_FLOAT		4
+#define CIF_FLAGS_DOUBLE	8
+#define CIF_FLAGS_LDOUBLE	16
+#define CIF_FLAGS_POINTER	32
+#define CIF_FLAGS_STRUCT1	64
+#define CIF_FLAGS_STRUCT2	128
+
+/* Perform machine dependent cif processing */
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+      cif->flags = 0;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT &&
+          cif->rtype->elements[1])
+        {
+          cif->flags = 0;
+          break;
+        }
+
+      switch (cif->rtype->size)
+	{
+	case 1:
+#ifdef __MINT__
+	  cif->flags = CIF_FLAGS_STRUCT2;
+#else
+	  cif->flags = CIF_FLAGS_STRUCT1;
+#endif
+	  break;
+	case 2:
+	  cif->flags = CIF_FLAGS_STRUCT2;
+	  break;
+#ifdef __MINT__
+	case 3:
+#endif
+	case 4:
+	  cif->flags = CIF_FLAGS_INT;
+	  break;
+#ifdef __MINT__
+	case 7:
+#endif
+	case 8:
+	  cif->flags = CIF_FLAGS_DINT;
+	  break;
+	default:
+	  cif->flags = 0;
+	  break;
+	}
+      break;
+
+    case FFI_TYPE_FLOAT:
+      cif->flags = CIF_FLAGS_FLOAT;
+      break;
+
+    case FFI_TYPE_DOUBLE:
+      cif->flags = CIF_FLAGS_DOUBLE;
+      break;
+
+#if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
+    case FFI_TYPE_LONGDOUBLE:
+#ifdef __MINT__
+      cif->flags = 0;
+#else
+      cif->flags = CIF_FLAGS_LDOUBLE;
+#endif
+      break;
+#endif
+
+    case FFI_TYPE_POINTER:
+      cif->flags = CIF_FLAGS_POINTER;
+      break;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = CIF_FLAGS_DINT;
+      break;
+
+    default:
+      cif->flags = CIF_FLAGS_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+void
+ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have a return value
+     address then we need to make one.  */
+
+  if (rvalue == NULL
+      && cif->rtype->type == FFI_TYPE_STRUCT
+      && cif->rtype->size > 8)
+    ecif.rvalue = alloca (cif->rtype->size);
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi)
+    {
+    case FFI_SYSV:
+      ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
+		     ecif.rvalue, fn);
+      break;
+
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+}
+
+static void
+ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
+{
+  unsigned int i;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  argp = stack;
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+#ifdef __MINT__
+      if (cif->flags &&
+          cif->rtype->type == FFI_TYPE_STRUCT &&
+          (z == 1 || z == 2))
+ 	{
+	  *p_argv = (void *) (argp + 2);
+
+	  z = 4;
+	}
+      else
+      if (cif->flags &&
+          cif->rtype->type == FFI_TYPE_STRUCT &&
+          (z == 3 || z == 4))
+ 	{
+	  *p_argv = (void *) (argp);
+
+	  z = 4;
+	}
+      else
+#endif
+      if (z <= 4)
+	{
+	  *p_argv = (void *) (argp + 4 - z);
+
+	  z = 4;
+	}
+      else
+	{
+	  *p_argv = (void *) argp;
+
+	  /* Align if necessary */
+	  if ((sizeof(int) - 1) & z)
+	    z = ALIGN(z, sizeof(int));
+	}
+
+      p_argv++;
+      argp += z;
+    }
+}
+
+unsigned int
+ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
+{
+  ffi_cif *cif;
+  void **arg_area;
+
+  cif = closure->cif;
+  arg_area = (void**) alloca (cif->nargs * sizeof (void *));
+
+  ffi_prep_incoming_args_SYSV(args, arg_area, cif);
+
+  (closure->fun) (cif, resp, arg_area, closure->user_data);
+
+  return cif->flags;
+}
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*,void*,void**,void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  *(unsigned short *)closure->tramp = 0x207c;
+  *(void **)(closure->tramp + 2) = codeloc;
+  *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
+
+  if (
+#ifdef __MINT__
+      (cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
+#endif
+      (((cif->rtype->type == FFI_TYPE_STRUCT)
+         && !cif->flags)))
+    *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
+  else
+    *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
+
+#ifdef __rtems__
+  rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE );
+#elif defined(__MINT__)
+  Ssystem(S_FLUSHCACHE, codeloc, FFI_TRAMPOLINE_SIZE);
+#else
+  syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
+	  FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
+#endif
+
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
diff --git a/third_party/gofrontend/libffi/src/m68k/ffitarget.h b/third_party/gofrontend/libffi/src/m68k/ffitarget.h
new file mode 100644
index 0000000..e81dde2
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/m68k/ffitarget.h
@@ -0,0 +1,54 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for Motorola 68K.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 16
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/third_party/gofrontend/libffi/src/m68k/sysv.S b/third_party/gofrontend/libffi/src/m68k/sysv.S
new file mode 100644
index 0000000..f6f4ef9
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/m68k/sysv.S
@@ -0,0 +1,285 @@
+/* -----------------------------------------------------------------------
+	
+   sysv.S - Copyright (c) 2012 Alan Hourihane
+	    Copyright (c) 1998, 2012 Andreas Schwab
+	    Copyright (c) 2008 Red Hat, Inc. 
+   
+   m68k Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+#ifdef HAVE_AS_CFI_PSEUDO_OP
+#define CFI_STARTPROC()		.cfi_startproc
+#define CFI_OFFSET(reg,off)	.cfi_offset	reg,off
+#define CFI_DEF_CFA(reg,off)	.cfi_def_cfa	reg,off
+#define CFI_ENDPROC()		.cfi_endproc
+#else
+#define CFI_STARTPROC()
+#define CFI_OFFSET(reg,off)
+#define CFI_DEF_CFA(reg,off)
+#define CFI_ENDPROC()
+#endif
+
+#ifdef __MINT__
+#define CALLFUNC(funcname) _ ## funcname
+#else
+#define CALLFUNC(funcname) funcname
+#endif
+
+	.text
+
+	.globl	CALLFUNC(ffi_call_SYSV)
+	.type	CALLFUNC(ffi_call_SYSV),@function
+	.align	4
+
+CALLFUNC(ffi_call_SYSV):
+	CFI_STARTPROC()
+	link	%fp,#0
+	CFI_OFFSET(14,-8)
+	CFI_DEF_CFA(14,8)
+	move.l	%d2,-(%sp)
+	CFI_OFFSET(2,-12)
+
+	| Make room for all of the new args.
+	sub.l	12(%fp),%sp
+
+	| Call ffi_prep_args
+	move.l	8(%fp),-(%sp)
+	pea	4(%sp)
+#if !defined __PIC__
+	jsr	CALLFUNC(ffi_prep_args)
+#else
+	bsr.l	CALLFUNC(ffi_prep_args@PLTPC)
+#endif
+	addq.l	#8,%sp	
+
+	| Pass pointer to struct value, if any
+#ifdef __MINT__
+	move.l	%d0,%a1
+#else
+	move.l	%a0,%a1
+#endif
+
+	| Call the function
+	move.l	24(%fp),%a0
+	jsr	(%a0)
+
+	| Remove the space we pushed for the args
+	add.l	12(%fp),%sp
+
+	| Load the pointer to storage for the return value
+	move.l	20(%fp),%a1
+
+	| Load the return type code 
+	move.l	16(%fp),%d2
+
+	| If the return value pointer is NULL, assume no return value.
+	| NOTE: On the mc68000, tst on an address register is not supported.
+#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
+	cmp.w	#0, %a1
+#else
+	tst.l	%a1
+#endif
+	jbeq	noretval
+
+	btst	#0,%d2
+	jbeq	retlongint
+	move.l	%d0,(%a1)
+	jbra	epilogue
+
+retlongint:
+	btst	#1,%d2
+	jbeq	retfloat
+	move.l	%d0,(%a1)
+	move.l	%d1,4(%a1)
+	jbra	epilogue
+
+retfloat:
+	btst	#2,%d2
+	jbeq	retdouble
+#if defined(__MC68881__) || defined(__HAVE_68881__)
+	fmove.s	%fp0,(%a1)
+#else
+	move.l	%d0,(%a1)
+#endif
+	jbra	epilogue
+
+retdouble:
+	btst	#3,%d2
+	jbeq	retlongdouble
+#if defined(__MC68881__) || defined(__HAVE_68881__)
+	fmove.d	%fp0,(%a1)
+#else
+	move.l	%d0,(%a1)+
+	move.l	%d1,(%a1)
+#endif
+	jbra	epilogue
+
+retlongdouble:
+	btst	#4,%d2
+	jbeq	retpointer
+#if defined(__MC68881__) || defined(__HAVE_68881__)
+	fmove.x	%fp0,(%a1)
+#else
+	move.l	%d0,(%a1)+
+	move.l	%d1,(%a1)+
+	move.l	%d2,(%a1)
+#endif
+	jbra	epilogue
+
+retpointer:
+	btst	#5,%d2
+	jbeq	retstruct1
+#ifdef __MINT__
+	move.l	%d0,(%a1)
+#else
+	move.l	%a0,(%a1)
+#endif
+	jbra	epilogue
+
+retstruct1:
+	btst	#6,%d2
+	jbeq	retstruct2
+	move.b	%d0,(%a1)
+	jbra	epilogue
+
+retstruct2:
+	btst	#7,%d2
+	jbeq	noretval
+	move.w	%d0,(%a1)
+
+noretval:
+epilogue:
+	move.l	(%sp)+,%d2
+	unlk	%fp
+	rts
+	CFI_ENDPROC()
+	.size	CALLFUNC(ffi_call_SYSV),.-CALLFUNC(ffi_call_SYSV)
+
+	.globl	CALLFUNC(ffi_closure_SYSV)
+	.type	CALLFUNC(ffi_closure_SYSV), @function
+	.align	4
+
+CALLFUNC(ffi_closure_SYSV):
+	CFI_STARTPROC()
+	link	%fp,#-12
+	CFI_OFFSET(14,-8)
+	CFI_DEF_CFA(14,8)
+	move.l	%sp,-12(%fp)
+	pea	8(%fp)
+	pea	-12(%fp)
+	move.l	%a0,-(%sp)
+#if !defined __PIC__
+	jsr	CALLFUNC(ffi_closure_SYSV_inner)
+#else
+	bsr.l	CALLFUNC(ffi_closure_SYSV_inner@PLTPC)
+#endif
+
+	lsr.l	#1,%d0
+	jne	1f
+	jcc	.Lcls_epilogue
+	move.l	-12(%fp),%d0
+.Lcls_epilogue:
+	unlk	%fp
+	rts
+1:
+	lea	-12(%fp),%a0
+	lsr.l	#2,%d0
+	jne	1f
+	jcs	.Lcls_ret_float
+	move.l	(%a0)+,%d0
+	move.l	(%a0),%d1
+	jra	.Lcls_epilogue
+.Lcls_ret_float:
+#if defined(__MC68881__) || defined(__HAVE_68881__)
+	fmove.s	(%a0),%fp0
+#else
+	move.l	(%a0),%d0
+#endif
+	jra	.Lcls_epilogue
+1:
+	lsr.l	#2,%d0
+	jne	1f
+	jcs	.Lcls_ret_ldouble
+#if defined(__MC68881__) || defined(__HAVE_68881__)
+	fmove.d	(%a0),%fp0
+#else
+	move.l	(%a0)+,%d0
+	move.l	(%a0),%d1
+#endif
+	jra	.Lcls_epilogue
+.Lcls_ret_ldouble:
+#if defined(__MC68881__) || defined(__HAVE_68881__)
+	fmove.x	(%a0),%fp0
+#else
+	move.l	(%a0)+,%d0
+	move.l	(%a0)+,%d1
+	move.l	(%a0),%d2
+#endif
+	jra	.Lcls_epilogue
+1:
+	lsr.l	#2,%d0
+	jne	.Lcls_ret_struct2
+	jcs	.Lcls_ret_struct1
+	move.l	(%a0),%a0
+	move.l	%a0,%d0
+	jra	.Lcls_epilogue
+.Lcls_ret_struct1:
+	move.b	(%a0),%d0
+	jra	.Lcls_epilogue
+.Lcls_ret_struct2:
+	move.w	(%a0),%d0
+	jra	.Lcls_epilogue
+	CFI_ENDPROC()
+
+	.size	CALLFUNC(ffi_closure_SYSV),.-CALLFUNC(ffi_closure_SYSV)
+
+	.globl	CALLFUNC(ffi_closure_struct_SYSV)
+	.type	CALLFUNC(ffi_closure_struct_SYSV), @function
+	.align	4
+
+CALLFUNC(ffi_closure_struct_SYSV):
+	CFI_STARTPROC()
+	link	%fp,#0
+	CFI_OFFSET(14,-8)
+	CFI_DEF_CFA(14,8)
+	move.l	%sp,-12(%fp)
+	pea	8(%fp)
+	move.l	%a1,-(%sp)
+	move.l	%a0,-(%sp)
+#if !defined __PIC__
+	jsr	CALLFUNC(ffi_closure_SYSV_inner)
+#else
+	bsr.l	CALLFUNC(ffi_closure_SYSV_inner@PLTPC)
+#endif
+	unlk	%fp
+	rts
+	CFI_ENDPROC()
+	.size	CALLFUNC(ffi_closure_struct_SYSV),.-CALLFUNC(ffi_closure_struct_SYSV)
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/mips/ffi.c b/third_party/gofrontend/libffi/src/mips/ffi.c
new file mode 100644
index 0000000..03121e3
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/mips/ffi.c
@@ -0,0 +1,1043 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2011  Anthony Green
+           Copyright (c) 2008  David Daney
+           Copyright (c) 1996, 2007, 2008, 2011  Red Hat, Inc.
+   
+   MIPS Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+#ifdef __GNUC__
+#  if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
+#    define USE__BUILTIN___CLEAR_CACHE 1
+#  endif
+#endif
+
+#ifndef USE__BUILTIN___CLEAR_CACHE
+#  if defined(__OpenBSD__)
+#    include <mips64/sysarch.h>
+#  else
+#    include <sys/cachectl.h>
+#  endif
+#endif
+
+#ifdef FFI_DEBUG
+# define FFI_MIPS_STOP_HERE() ffi_stop_here()
+#else
+# define FFI_MIPS_STOP_HERE() do {} while(0)
+#endif
+
+#ifdef FFI_MIPS_N32
+#define FIX_ARGP \
+FFI_ASSERT(argp <= &stack[bytes]); \
+if (argp == &stack[bytes]) \
+{ \
+  argp = stack; \
+  FFI_MIPS_STOP_HERE(); \
+}
+#else
+#define FIX_ARGP 
+#endif
+
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+static void ffi_prep_args(char *stack, 
+			  extended_cif *ecif,
+			  int bytes,
+			  int flags)
+{
+  int i;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+#ifdef FFI_MIPS_N32
+  /* If more than 8 double words are used, the remainder go
+     on the stack. We reorder stuff on the stack here to 
+     support this easily. */
+  if (bytes > 8 * sizeof(ffi_arg))
+    argp = &stack[bytes - (8 * sizeof(ffi_arg))];
+  else
+    argp = stack;
+#else
+  argp = stack;
+#endif
+
+  memset(stack, 0, bytes);
+
+#ifdef FFI_MIPS_N32
+  if ( ecif->cif->rstruct_flag != 0 )
+#else
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
+#endif  
+    {
+      *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
+      argp += sizeof(ffi_arg);
+      FIX_ARGP;
+    }
+
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++)
+    {
+      size_t z;
+      unsigned int a;
+
+      /* Align if necessary.  */
+      a = (*p_arg)->alignment;
+      if (a < sizeof(ffi_arg))
+        a = sizeof(ffi_arg);
+      
+      if ((a - 1) & (unsigned long) argp)
+	{
+	  argp = (char *) ALIGN(argp, a);
+	  FIX_ARGP;
+	}
+
+      z = (*p_arg)->size;
+      if (z <= sizeof(ffi_arg))
+	{
+          int type = (*p_arg)->type;
+	  z = sizeof(ffi_arg);
+
+          /* The size of a pointer depends on the ABI */
+          if (type == FFI_TYPE_POINTER)
+            type = (ecif->cif->abi == FFI_N64
+		    || ecif->cif->abi == FFI_N64_SOFT_FLOAT)
+	      ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
+
+	if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT
+		      || ecif->cif->abi == FFI_N64_SOFT_FLOAT))
+	  {
+	    switch (type)
+	      {
+	      case FFI_TYPE_FLOAT:
+		type = FFI_TYPE_UINT32;
+		break;
+	      case FFI_TYPE_DOUBLE:
+		type = FFI_TYPE_UINT64;
+		break;
+	      default:
+		break;
+	      }
+	  }
+	  switch (type)
+	    {
+	      case FFI_TYPE_SINT8:
+		*(ffi_arg *)argp = *(SINT8 *)(* p_argv);
+		break;
+
+	      case FFI_TYPE_UINT8:
+		*(ffi_arg *)argp = *(UINT8 *)(* p_argv);
+		break;
+		  
+	      case FFI_TYPE_SINT16:
+		*(ffi_arg *)argp = *(SINT16 *)(* p_argv);
+		break;
+		  
+	      case FFI_TYPE_UINT16:
+		*(ffi_arg *)argp = *(UINT16 *)(* p_argv);
+		break;
+		  
+	      case FFI_TYPE_SINT32:
+		*(ffi_arg *)argp = *(SINT32 *)(* p_argv);
+		break;
+		  
+	      case FFI_TYPE_UINT32:
+		*(ffi_arg *)argp = *(UINT32 *)(* p_argv);
+		break;
+
+	      /* This can only happen with 64bit slots.  */
+	      case FFI_TYPE_FLOAT:
+		*(float *) argp = *(float *)(* p_argv);
+		break;
+
+	      /* Handle structures.  */
+	      default:
+		memcpy(argp, *p_argv, (*p_arg)->size);
+		break;
+	    }
+	}
+      else
+	{
+#ifdef FFI_MIPS_O32
+	  memcpy(argp, *p_argv, z);
+#else
+	  {
+	    unsigned long end = (unsigned long) argp + z;
+	    unsigned long cap = (unsigned long) stack + bytes;
+
+	    /* Check if the data will fit within the register space.
+	       Handle it if it doesn't.  */
+
+	    if (end <= cap)
+	      memcpy(argp, *p_argv, z);
+	    else
+	      {
+		unsigned long portion = cap - (unsigned long)argp;
+
+		memcpy(argp, *p_argv, portion);
+		argp = stack;
+                z -= portion;
+		memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
+                       z);
+	      }
+	  }
+#endif
+      }
+      p_argv++;
+      argp += z;
+      FIX_ARGP;
+    }
+}
+
+#ifdef FFI_MIPS_N32
+
+/* The n32 spec says that if "a chunk consists solely of a double 
+   float field (but not a double, which is part of a union), it
+   is passed in a floating point register. Any other chunk is
+   passed in an integer register". This code traverses structure
+   definitions and generates the appropriate flags. */
+
+static unsigned
+calc_n32_struct_flags(int soft_float, ffi_type *arg,
+		      unsigned *loc, unsigned *arg_reg)
+{
+  unsigned flags = 0;
+  unsigned index = 0;
+
+  ffi_type *e;
+
+  if (soft_float)
+    return 0;
+
+  while ((e = arg->elements[index]))
+    {
+      /* Align this object.  */
+      *loc = ALIGN(*loc, e->alignment);
+      if (e->type == FFI_TYPE_DOUBLE)
+	{
+          /* Already aligned to FFI_SIZEOF_ARG.  */
+          *arg_reg = *loc / FFI_SIZEOF_ARG;
+          if (*arg_reg > 7)
+            break;
+	  flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
+          *loc += e->size;
+	}
+      else
+        *loc += e->size;
+      index++;
+    }
+  /* Next Argument register at alignment of FFI_SIZEOF_ARG.  */
+  *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+
+  return flags;
+}
+
+static unsigned
+calc_n32_return_struct_flags(int soft_float, ffi_type *arg)
+{
+  unsigned flags = 0;
+  unsigned small = FFI_TYPE_SMALLSTRUCT;
+  ffi_type *e;
+
+  /* Returning structures under n32 is a tricky thing.
+     A struct with only one or two floating point fields 
+     is returned in $f0 (and $f2 if necessary). Any other
+     struct results at most 128 bits are returned in $2
+     (the first 64 bits) and $3 (remainder, if necessary).
+     Larger structs are handled normally. */
+  
+  if (arg->size > 16)
+    return 0;
+
+  if (arg->size > 8)
+    small = FFI_TYPE_SMALLSTRUCT2;
+
+  e = arg->elements[0];
+
+  if (e->type == FFI_TYPE_DOUBLE)
+    flags = FFI_TYPE_DOUBLE;
+  else if (e->type == FFI_TYPE_FLOAT)
+    flags = FFI_TYPE_FLOAT;
+
+  if (flags && (e = arg->elements[1]))
+    {
+      if (e->type == FFI_TYPE_DOUBLE)
+	flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
+      else if (e->type == FFI_TYPE_FLOAT)
+	flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
+      else 
+	return small;
+
+      if (flags && (arg->elements[2]))
+	{
+	  /* There are three arguments and the first two are 
+	     floats! This must be passed the old way. */
+	  return small;
+	}
+      if (soft_float)
+	flags += FFI_TYPE_STRUCT_SOFT;
+    }
+  else
+    if (!flags)
+      return small;
+
+  return flags;
+}
+
+#endif
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  cif->flags = 0;
+
+#ifdef FFI_MIPS_O32
+  /* Set the flags necessary for O32 processing.  FFI_O32_SOFT_FLOAT
+   * does not have special handling for floating point args.
+   */
+
+  if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
+    {
+      if (cif->nargs > 0)
+	{
+	  switch ((cif->arg_types)[0]->type)
+	    {
+	    case FFI_TYPE_FLOAT:
+	    case FFI_TYPE_DOUBLE:
+	      cif->flags += (cif->arg_types)[0]->type;
+	      break;
+	      
+	    default:
+	      break;
+	    }
+
+	  if (cif->nargs > 1)
+	    {
+	      /* Only handle the second argument if the first
+		 is a float or double. */
+	      if (cif->flags)
+		{
+		  switch ((cif->arg_types)[1]->type)
+		    {
+		    case FFI_TYPE_FLOAT:
+		    case FFI_TYPE_DOUBLE:
+		      cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
+		      break;
+		      
+		    default:
+		      break;
+		    }
+		}
+	    }
+	}
+    }
+      
+  /* Set the return type flag */
+
+  if (cif->abi == FFI_O32_SOFT_FLOAT)
+    {
+      switch (cif->rtype->type)
+        {
+        case FFI_TYPE_VOID:
+        case FFI_TYPE_STRUCT:
+          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
+          break;
+
+        case FFI_TYPE_SINT64:
+        case FFI_TYPE_UINT64:
+        case FFI_TYPE_DOUBLE:
+          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
+          break;
+      
+        case FFI_TYPE_FLOAT:
+        default:
+          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
+          break;
+        }
+    }
+  else
+    {
+      /* FFI_O32 */      
+      switch (cif->rtype->type)
+        {
+        case FFI_TYPE_VOID:
+        case FFI_TYPE_STRUCT:
+        case FFI_TYPE_FLOAT:
+        case FFI_TYPE_DOUBLE:
+          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
+          break;
+
+        case FFI_TYPE_SINT64:
+        case FFI_TYPE_UINT64:
+          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
+          break;
+      
+        default:
+          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
+          break;
+        }
+    }
+#endif
+
+#ifdef FFI_MIPS_N32
+  /* Set the flags necessary for N32 processing */
+  {
+    int type;
+    unsigned arg_reg = 0;
+    unsigned loc = 0;
+    unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
+    unsigned index = 0;
+
+    unsigned struct_flags = 0;
+    int soft_float = (cif->abi == FFI_N32_SOFT_FLOAT
+		      || cif->abi == FFI_N64_SOFT_FLOAT);
+
+    if (cif->rtype->type == FFI_TYPE_STRUCT)
+      {
+	struct_flags = calc_n32_return_struct_flags(soft_float, cif->rtype);
+
+	if (struct_flags == 0)
+	  {
+	    /* This means that the structure is being passed as
+	       a hidden argument */
+
+	    arg_reg = 1;
+	    count = (cif->nargs < 7) ? cif->nargs : 7;
+
+	    cif->rstruct_flag = !0;
+	  }
+	else
+	    cif->rstruct_flag = 0;
+      }
+    else
+      cif->rstruct_flag = 0;
+
+    while (count-- > 0 && arg_reg < 8)
+      {
+	type = (cif->arg_types)[index]->type;
+	if (soft_float)
+	  {
+	    switch (type)
+	      {
+	      case FFI_TYPE_FLOAT:
+		type = FFI_TYPE_UINT32;
+		break;
+	      case FFI_TYPE_DOUBLE:
+		type = FFI_TYPE_UINT64;
+		break;
+	      default:
+		break;
+	      }
+	  }
+	switch (type)
+	  {
+	  case FFI_TYPE_FLOAT:
+	  case FFI_TYPE_DOUBLE:
+	    cif->flags +=
+              ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
+	    arg_reg++;
+	    break;
+          case FFI_TYPE_LONGDOUBLE:
+            /* Align it.  */
+            arg_reg = ALIGN(arg_reg, 2);
+            /* Treat it as two adjacent doubles.  */
+	    if (soft_float) 
+	      {
+		arg_reg += 2;
+	      }
+	    else
+	      {
+		cif->flags +=
+		  (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
+		arg_reg++;
+		cif->flags +=
+		  (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
+		arg_reg++;
+	      }
+            break;
+
+	  case FFI_TYPE_STRUCT:
+            loc = arg_reg * FFI_SIZEOF_ARG;
+	    cif->flags += calc_n32_struct_flags(soft_float,
+						(cif->arg_types)[index],
+						&loc, &arg_reg);
+	    break;
+
+	  default:
+	    arg_reg++;
+            break;
+	  }
+
+	index++;
+      }
+
+  /* Set the return type flag */
+    switch (cif->rtype->type)
+      {
+      case FFI_TYPE_STRUCT:
+	{
+	  if (struct_flags == 0)
+	    {
+	      /* The structure is returned through a hidden
+		 first argument. Do nothing, 'cause FFI_TYPE_VOID 
+		 is 0 */
+	    }
+	  else
+	    {
+	      /* The structure is returned via some tricky
+		 mechanism */
+	      cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
+	      cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
+	    }
+	  break;
+	}
+      
+      case FFI_TYPE_VOID:
+	/* Do nothing, 'cause FFI_TYPE_VOID is 0 */
+	break;
+
+      case FFI_TYPE_POINTER:
+	if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32)
+	  cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
+	else
+	  cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
+	break;
+
+      case FFI_TYPE_FLOAT:
+	if (soft_float)
+	  {
+	    cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
+	    break;
+	  }
+	/* else fall through */
+      case FFI_TYPE_DOUBLE:
+	if (soft_float)
+	  cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
+	else
+	  cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
+	break;
+
+      case FFI_TYPE_LONGDOUBLE:
+	/* Long double is returned as if it were a struct containing
+	   two doubles.  */
+	if (soft_float)
+	  {
+	    cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
+	    cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8));
+ 	  }
+	else
+	  {
+	    cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
+	    cif->flags += (FFI_TYPE_DOUBLE
+			   + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
+					      << (4 + (FFI_FLAG_BITS * 8));
+	  }
+	break;
+      default:
+	cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
+	break;
+      }
+  }
+#endif
+  
+  return FFI_OK;
+}
+
+/* Low level routine for calling O32 functions */
+extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), 
+			extended_cif *, unsigned, 
+			unsigned, unsigned *, void (*)(void));
+
+/* Low level routine for calling N32 functions */
+extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), 
+			extended_cif *, unsigned, 
+			unsigned, void *, void (*)(void));
+
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return	*/
+  /* value address then we need to make one		        */
+  
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    ecif.rvalue = alloca(cif->rtype->size);
+  else
+    ecif.rvalue = rvalue;
+    
+  switch (cif->abi) 
+    {
+#ifdef FFI_MIPS_O32
+    case FFI_O32:
+    case FFI_O32_SOFT_FLOAT:
+      ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, 
+		   cif->flags, ecif.rvalue, fn);
+      break;
+#endif
+
+#ifdef FFI_MIPS_N32
+    case FFI_N32:
+    case FFI_N32_SOFT_FLOAT:
+    case FFI_N64:
+    case FFI_N64_SOFT_FLOAT:
+      {
+        int copy_rvalue = 0;
+	int copy_offset = 0;
+        char *rvalue_copy = ecif.rvalue;
+        if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
+          {
+            /* For structures smaller than 16 bytes we clobber memory
+               in 8 byte increments.  Make a copy so we don't clobber
+               the callers memory outside of the struct bounds.  */
+            rvalue_copy = alloca(16);
+            copy_rvalue = 1;
+          }
+	else if (cif->rtype->type == FFI_TYPE_FLOAT
+		 && (cif->abi == FFI_N64_SOFT_FLOAT
+		     || cif->abi == FFI_N32_SOFT_FLOAT))
+	  {
+	    rvalue_copy = alloca (8);
+	    copy_rvalue = 1;
+#if defined(__MIPSEB__) || defined(_MIPSEB)
+	    copy_offset = 4;
+#endif
+	  }
+        ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
+                     cif->flags, rvalue_copy, fn);
+        if (copy_rvalue)
+          memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size);
+      }
+      break;
+#endif
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#if FFI_CLOSURES
+#if defined(FFI_MIPS_O32)
+extern void ffi_closure_O32(void);
+#else
+extern void ffi_closure_N32(void);
+#endif /* FFI_MIPS_O32 */
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure *closure,
+		      ffi_cif *cif,
+		      void (*fun)(ffi_cif*,void*,void**,void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+  void * fn;
+  char *clear_location = (char *) codeloc;
+
+#if defined(FFI_MIPS_O32)
+  if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT)
+    return FFI_BAD_ABI;
+  fn = ffi_closure_O32;
+#else
+#if _MIPS_SIM ==_ABIN32
+  if (cif->abi != FFI_N32
+      && cif->abi != FFI_N32_SOFT_FLOAT)
+    return FFI_BAD_ABI;
+#else
+  if (cif->abi != FFI_N64
+      && cif->abi != FFI_N64_SOFT_FLOAT)
+    return FFI_BAD_ABI;
+#endif
+  fn = ffi_closure_N32;
+#endif /* FFI_MIPS_O32 */
+
+#if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
+  /* lui  $25,high(fn) */
+  tramp[0] = 0x3c190000 | ((unsigned)fn >> 16);
+  /* ori  $25,low(fn)  */
+  tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff);
+  /* lui  $12,high(codeloc) */
+  tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16);
+  /* jr   $25          */
+  tramp[3] = 0x03200008;
+  /* ori  $12,low(codeloc)  */
+  tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff);
+#else
+  /* N64 has a somewhat larger trampoline.  */
+  /* lui  $25,high(fn) */
+  tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48);
+  /* lui  $12,high(codeloc) */
+  tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48);
+  /* ori  $25,mid-high(fn)  */
+  tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff);
+  /* ori  $12,mid-high(codeloc)  */
+  tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff);
+  /* dsll $25,$25,16 */
+  tramp[4] = 0x0019cc38;
+  /* dsll $12,$12,16 */
+  tramp[5] = 0x000c6438;
+  /* ori  $25,mid-low(fn)  */
+  tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff);
+  /* ori  $12,mid-low(codeloc)  */
+  tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff);
+  /* dsll $25,$25,16 */
+  tramp[8] = 0x0019cc38;
+  /* dsll $12,$12,16 */
+  tramp[9] = 0x000c6438;
+  /* ori  $25,low(fn)  */
+  tramp[10] = 0x37390000 | ((unsigned long)fn  & 0xffff);
+  /* jr   $25          */
+  tramp[11] = 0x03200008;
+  /* ori  $12,low(codeloc)  */
+  tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff);
+
+#endif
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+#ifdef USE__BUILTIN___CLEAR_CACHE
+  __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE);
+#else
+  cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE);
+#endif
+  return FFI_OK;
+}
+
+/*
+ * Decodes the arguments to a function, which will be stored on the
+ * stack. AR is the pointer to the beginning of the integer arguments
+ * (and, depending upon the arguments, some floating-point arguments
+ * as well). FPR is a pointer to the area where floating point
+ * registers have been saved, if any.
+ *
+ * RVALUE is the location where the function return value will be
+ * stored. CLOSURE is the prepared closure to invoke.
+ *
+ * This function should only be called from assembly, which is in
+ * turn called from a trampoline.
+ *
+ * Returns the function return type.
+ *
+ * Based on the similar routine for sparc.
+ */
+int
+ffi_closure_mips_inner_O32 (ffi_closure *closure,
+			    void *rvalue, ffi_arg *ar,
+			    double *fpr)
+{
+  ffi_cif *cif;
+  void **avaluep;
+  ffi_arg *avalue;
+  ffi_type **arg_types;
+  int i, avn, argn, seen_int;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (ffi_arg));
+  avaluep = alloca (cif->nargs * sizeof (ffi_arg));
+
+  seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
+  argn = 0;
+
+  if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *)(UINT32)ar[0];
+      argn = 1;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  while (i < avn)
+    {
+      if (i < 2 && !seen_int &&
+	  (arg_types[i]->type == FFI_TYPE_FLOAT ||
+	   arg_types[i]->type == FFI_TYPE_DOUBLE ||
+	   arg_types[i]->type == FFI_TYPE_LONGDOUBLE))
+	{
+#if defined(__MIPSEB__) || defined(_MIPSEB)
+	  if (arg_types[i]->type == FFI_TYPE_FLOAT)
+	    avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
+	  else
+#endif
+	    avaluep[i] = (char *) &fpr[i];
+	}
+      else
+	{
+	  if (arg_types[i]->alignment == 8 && (argn & 0x1))
+	    argn++;
+	  switch (arg_types[i]->type)
+	    {
+	      case FFI_TYPE_SINT8:
+		avaluep[i] = &avalue[i];
+		*(SINT8 *) &avalue[i] = (SINT8) ar[argn];
+		break;
+
+	      case FFI_TYPE_UINT8:
+		avaluep[i] = &avalue[i];
+		*(UINT8 *) &avalue[i] = (UINT8) ar[argn];
+		break;
+		  
+	      case FFI_TYPE_SINT16:
+		avaluep[i] = &avalue[i];
+		*(SINT16 *) &avalue[i] = (SINT16) ar[argn];
+		break;
+		  
+	      case FFI_TYPE_UINT16:
+		avaluep[i] = &avalue[i];
+		*(UINT16 *) &avalue[i] = (UINT16) ar[argn];
+		break;
+
+	      default:
+		avaluep[i] = (char *) &ar[argn];
+		break;
+	    }
+	  seen_int = 1;
+	}
+      argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+      i++;
+    }
+
+  /* Invoke the closure. */
+  (closure->fun) (cif, rvalue, avaluep, closure->user_data);
+
+  if (cif->abi == FFI_O32_SOFT_FLOAT)
+    {
+      switch (cif->rtype->type)
+        {
+        case FFI_TYPE_FLOAT:
+          return FFI_TYPE_INT;
+        case FFI_TYPE_DOUBLE:
+          return FFI_TYPE_UINT64;
+        default:
+          return cif->rtype->type;
+        }
+    }
+  else
+    {
+      return cif->rtype->type;
+    }
+}
+
+#if defined(FFI_MIPS_N32)
+
+static void
+copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
+                int argn, unsigned arg_offset, ffi_arg *ar,
+                ffi_arg *fpr, int soft_float)
+{
+  ffi_type **elt_typep = type->elements;
+  while(*elt_typep)
+    {
+      ffi_type *elt_type = *elt_typep;
+      unsigned o;
+      char *tp;
+      char *argp;
+      char *fpp;
+
+      o = ALIGN(offset, elt_type->alignment);
+      arg_offset += o - offset;
+      offset = o;
+      argn += arg_offset / sizeof(ffi_arg);
+      arg_offset = arg_offset % sizeof(ffi_arg);
+
+      argp = (char *)(ar + argn);
+      fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
+
+      tp = target + offset;
+
+      if (elt_type->type == FFI_TYPE_DOUBLE && !soft_float)
+        *(double *)tp = *(double *)fpp;
+      else
+        memcpy(tp, argp + arg_offset, elt_type->size);
+
+      offset += elt_type->size;
+      arg_offset += elt_type->size;
+      elt_typep++;
+      argn += arg_offset / sizeof(ffi_arg);
+      arg_offset = arg_offset % sizeof(ffi_arg);
+    }
+}
+
+/*
+ * Decodes the arguments to a function, which will be stored on the
+ * stack. AR is the pointer to the beginning of the integer
+ * arguments. FPR is a pointer to the area where floating point
+ * registers have been saved.
+ *
+ * RVALUE is the location where the function return value will be
+ * stored. CLOSURE is the prepared closure to invoke.
+ *
+ * This function should only be called from assembly, which is in
+ * turn called from a trampoline.
+ *
+ * Returns the function return flags.
+ *
+ */
+int
+ffi_closure_mips_inner_N32 (ffi_closure *closure,
+			    void *rvalue, ffi_arg *ar,
+			    ffi_arg *fpr)
+{
+  ffi_cif *cif;
+  void **avaluep;
+  ffi_arg *avalue;
+  ffi_type **arg_types;
+  int i, avn, argn;
+  int soft_float;
+  ffi_arg *argp;
+
+  cif = closure->cif;
+  soft_float = cif->abi == FFI_N64_SOFT_FLOAT
+    || cif->abi == FFI_N32_SOFT_FLOAT;
+  avalue = alloca (cif->nargs * sizeof (ffi_arg));
+  avaluep = alloca (cif->nargs * sizeof (ffi_arg));
+
+  argn = 0;
+
+  if (cif->rstruct_flag)
+    {
+#if _MIPS_SIM==_ABIN32
+      rvalue = (void *)(UINT32)ar[0];
+#else /* N64 */
+      rvalue = (void *)ar[0];
+#endif
+      argn = 1;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  while (i < avn)
+    {
+      if (arg_types[i]->type == FFI_TYPE_FLOAT
+	  || arg_types[i]->type == FFI_TYPE_DOUBLE
+	  || arg_types[i]->type == FFI_TYPE_LONGDOUBLE)
+        {
+          argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn;
+          if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((unsigned)argp & (arg_types[i]->alignment-1)))
+            {
+              argp=(ffi_arg*)ALIGN(argp,arg_types[i]->alignment);
+              argn++;
+            }
+#if defined(__MIPSEB__) || defined(_MIPSEB)
+          if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
+            avaluep[i] = ((char *) argp) + sizeof (float);
+          else
+#endif
+            avaluep[i] = (char *) argp;
+        }
+      else
+        {
+          unsigned type = arg_types[i]->type;
+
+          if (arg_types[i]->alignment > sizeof(ffi_arg))
+            argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
+
+          argp = ar + argn;
+
+          /* The size of a pointer depends on the ABI */
+          if (type == FFI_TYPE_POINTER)
+            type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT)
+	      ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
+
+	  if (soft_float && type ==  FFI_TYPE_FLOAT)
+	    type = FFI_TYPE_UINT32;
+
+          switch (type)
+            {
+            case FFI_TYPE_SINT8:
+              avaluep[i] = &avalue[i];
+              *(SINT8 *) &avalue[i] = (SINT8) *argp;
+              break;
+
+            case FFI_TYPE_UINT8:
+              avaluep[i] = &avalue[i];
+              *(UINT8 *) &avalue[i] = (UINT8) *argp;
+              break;
+
+            case FFI_TYPE_SINT16:
+              avaluep[i] = &avalue[i];
+              *(SINT16 *) &avalue[i] = (SINT16) *argp;
+              break;
+
+            case FFI_TYPE_UINT16:
+              avaluep[i] = &avalue[i];
+              *(UINT16 *) &avalue[i] = (UINT16) *argp;
+              break;
+
+            case FFI_TYPE_SINT32:
+              avaluep[i] = &avalue[i];
+              *(SINT32 *) &avalue[i] = (SINT32) *argp;
+              break;
+
+            case FFI_TYPE_UINT32:
+              avaluep[i] = &avalue[i];
+              *(UINT32 *) &avalue[i] = (UINT32) *argp;
+              break;
+
+            case FFI_TYPE_STRUCT:
+              if (argn < 8)
+                {
+                  /* Allocate space for the struct as at least part of
+                     it was passed in registers.  */
+                  avaluep[i] = alloca(arg_types[i]->size);
+                  copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
+                                  argn, 0, ar, fpr, soft_float);
+
+                  break;
+                }
+              /* Else fall through.  */
+            default:
+              avaluep[i] = (char *) argp;
+              break;
+            }
+        }
+      argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
+      i++;
+    }
+
+  /* Invoke the closure. */
+  (closure->fun) (cif, rvalue, avaluep, closure->user_data);
+
+  return cif->flags >> (FFI_FLAG_BITS * 8);
+}
+
+#endif /* FFI_MIPS_N32 */
+
+#endif /* FFI_CLOSURES */
diff --git a/third_party/gofrontend/libffi/src/mips/ffitarget.h b/third_party/gofrontend/libffi/src/mips/ffitarget.h
new file mode 100644
index 0000000..717d659
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/mips/ffitarget.h
@@ -0,0 +1,247 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for MIPS.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifdef linux
+# include <asm/sgidefs.h>
+#elif defined(__rtems__)
+/*
+ * Subprogram calling convention - copied from sgidefs.h
+ */
+#define _MIPS_SIM_ABI32		1
+#define _MIPS_SIM_NABI32	2
+#define _MIPS_SIM_ABI64		3
+#elif !defined(__OpenBSD__)
+# include <sgidefs.h>
+#endif
+
+#  ifndef _ABIN32
+#    define _ABIN32 _MIPS_SIM_NABI32
+#  endif
+#  ifndef _ABI64
+#    define _ABI64 _MIPS_SIM_ABI64
+#  endif
+#  ifndef _ABIO32
+#    define _ABIO32 _MIPS_SIM_ABI32
+#  endif
+
+#if !defined(_MIPS_SIM)
+# error -- something is very wrong --
+#else
+#  if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64))
+#    define FFI_MIPS_N32
+#  else
+#    if (_MIPS_SIM==_ABIO32 && defined(_ABIO32))
+#      define FFI_MIPS_O32
+#    else
+#     error -- this is an unsupported platform --
+#    endif
+#  endif
+#endif
+
+#ifdef FFI_MIPS_O32
+/* O32 stack frames have 32bit integer args */
+#  define FFI_SIZEOF_ARG    4
+#else
+/* N32 and N64 frames have 64bit integer args */
+#  define FFI_SIZEOF_ARG    8
+#  if _MIPS_SIM == _ABIN32
+#    define FFI_SIZEOF_JAVA_RAW  4
+#  endif
+#endif
+
+#define FFI_FLAG_BITS 2
+
+/* SGI's strange assembler requires that we multiply by 4 rather 
+   than shift left by FFI_FLAG_BITS */
+
+#define FFI_ARGS_D   FFI_TYPE_DOUBLE
+#define FFI_ARGS_F   FFI_TYPE_FLOAT
+#define FFI_ARGS_DD  FFI_TYPE_DOUBLE * 4 + FFI_TYPE_DOUBLE
+#define FFI_ARGS_FF  FFI_TYPE_FLOAT * 4 +  FFI_TYPE_FLOAT
+#define FFI_ARGS_FD  FFI_TYPE_DOUBLE * 4 + FFI_TYPE_FLOAT
+#define FFI_ARGS_DF  FFI_TYPE_FLOAT * 4 + FFI_TYPE_DOUBLE
+
+/* Needed for N32 structure returns */
+#define FFI_TYPE_SMALLSTRUCT  FFI_TYPE_UINT8
+#define FFI_TYPE_SMALLSTRUCT2 FFI_TYPE_SINT8
+
+#if 0
+/* The SGI assembler can't handle this.. */
+#define FFI_TYPE_STRUCT_DD (( FFI_ARGS_DD ) << 4) + FFI_TYPE_STRUCT
+/* (and so on) */
+#else
+/* ...so we calculate these by hand! */
+#define FFI_TYPE_STRUCT_D      61
+#define FFI_TYPE_STRUCT_F      45
+#define FFI_TYPE_STRUCT_DD     253
+#define FFI_TYPE_STRUCT_FF     173
+#define FFI_TYPE_STRUCT_FD     237
+#define FFI_TYPE_STRUCT_DF     189
+#define FFI_TYPE_STRUCT_SMALL  93
+#define FFI_TYPE_STRUCT_SMALL2 109
+
+/* and for n32 soft float, add 16 * 2^4 */
+#define FFI_TYPE_STRUCT_D_SOFT      317
+#define FFI_TYPE_STRUCT_F_SOFT      301
+#define FFI_TYPE_STRUCT_DD_SOFT     509
+#define FFI_TYPE_STRUCT_FF_SOFT     429
+#define FFI_TYPE_STRUCT_FD_SOFT     493
+#define FFI_TYPE_STRUCT_DF_SOFT     445
+#define FFI_TYPE_STRUCT_SOFT        16
+#endif
+
+#ifdef LIBFFI_ASM
+#define v0 $2
+#define v1 $3
+#define a0 $4
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#define a4 $8		
+#define a5 $9		
+#define a6 $10		
+#define a7 $11		
+#define t0 $8
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12		
+#define t5 $13
+#define t6 $14	
+#define t7 $15
+#define t8 $24
+#define t9 $25
+#define ra $31		
+
+#ifdef FFI_MIPS_O32
+# define REG_L	lw
+# define REG_S	sw
+# define SUBU	subu
+# define ADDU	addu
+# define SRL	srl
+# define LI	li
+#else /* !FFI_MIPS_O32 */
+# define REG_L	ld
+# define REG_S	sd
+# define SUBU	dsubu
+# define ADDU	daddu
+# define SRL	dsrl
+# define LI 	dli
+# if (_MIPS_SIM==_ABI64)
+#  define LA dla
+#  define EH_FRAME_ALIGN 3
+#  define FDE_ADDR_BYTES .8byte
+# else
+#  define LA la
+#  define EH_FRAME_ALIGN 2
+#  define FDE_ADDR_BYTES .4byte
+# endif /* _MIPS_SIM==_ABI64 */
+#endif /* !FFI_MIPS_O32 */
+#else /* !LIBFFI_ASM */
+# ifdef __GNUC__
+#  ifdef FFI_MIPS_O32
+/* O32 stack frames have 32bit integer args */
+typedef unsigned int     ffi_arg __attribute__((__mode__(__SI__)));
+typedef signed   int     ffi_sarg __attribute__((__mode__(__SI__)));
+#else
+/* N32 and N64 frames have 64bit integer args */
+typedef unsigned int     ffi_arg __attribute__((__mode__(__DI__)));
+typedef signed   int     ffi_sarg __attribute__((__mode__(__DI__)));
+#  endif
+# else
+#  ifdef FFI_MIPS_O32
+/* O32 stack frames have 32bit integer args */
+typedef __uint32_t ffi_arg;
+typedef __int32_t ffi_sarg;
+#  else
+/* N32 and N64 frames have 64bit integer args */
+typedef __uint64_t ffi_arg;
+typedef __int64_t ffi_sarg;
+#  endif
+# endif /* __GNUC__ */
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_O32,
+  FFI_N32,
+  FFI_N64,
+  FFI_O32_SOFT_FLOAT,
+  FFI_N32_SOFT_FLOAT,
+  FFI_N64_SOFT_FLOAT,
+  FFI_LAST_ABI,
+
+#ifdef FFI_MIPS_O32
+#ifdef __mips_soft_float
+  FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT
+#else
+  FFI_DEFAULT_ABI = FFI_O32
+#endif
+#else
+# if _MIPS_SIM==_ABI64
+#  ifdef __mips_soft_float
+  FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT
+#  else
+  FFI_DEFAULT_ABI = FFI_N64
+#  endif
+# else
+#  ifdef __mips_soft_float
+  FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT
+#  else
+  FFI_DEFAULT_ABI = FFI_N32
+#  endif
+# endif
+#endif
+} ffi_abi;
+
+#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag
+#endif /* !LIBFFI_ASM */
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#if defined(FFI_MIPS_O32)
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 20
+#else
+/* N32/N64. */
+# define FFI_CLOSURES 1
+#if _MIPS_SIM==_ABI64
+#define FFI_TRAMPOLINE_SIZE 52
+#else
+#define FFI_TRAMPOLINE_SIZE 20
+#endif
+#endif /* FFI_MIPS_O32 */
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/third_party/gofrontend/libffi/src/mips/n32.S b/third_party/gofrontend/libffi/src/mips/n32.S
new file mode 100644
index 0000000..ff4bbce
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/mips/n32.S
@@ -0,0 +1,592 @@
+/* -----------------------------------------------------------------------
+   n32.S - Copyright (c) 1996, 1998, 2005, 2007, 2009, 2010  Red Hat, Inc.
+   
+   MIPS Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+/* Only build this code if we are compiling for n32 */	
+
+#if defined(FFI_MIPS_N32)
+
+#define callback a0
+#define bytes	 a2
+#define flags	 a3
+#define raddr    a4
+#define fn       a5
+
+#define SIZEOF_FRAME	( 8 * FFI_SIZEOF_ARG )
+
+#ifdef __GNUC__
+	.abicalls
+#endif
+	.set mips4
+	.text
+	.align	2
+	.globl	ffi_call_N32
+	.ent	ffi_call_N32
+ffi_call_N32:	
+.LFB3:
+	.frame	$fp, SIZEOF_FRAME, ra
+	.mask	0xc0000000,-FFI_SIZEOF_ARG
+	.fmask	0x00000000,0
+
+	# Prologue
+	SUBU	$sp, SIZEOF_FRAME			# Frame size
+.LCFI0:
+	REG_S	$fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp)	# Save frame pointer
+	REG_S	ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)	# Save return address
+.LCFI1:
+	move	$fp, $sp
+.LCFI3:
+	move	t9, callback	# callback function pointer
+	REG_S	bytes, 2*FFI_SIZEOF_ARG($fp) # bytes
+	REG_S	flags, 3*FFI_SIZEOF_ARG($fp) # flags
+	REG_S	raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
+	REG_S	fn,    5*FFI_SIZEOF_ARG($fp) # fn
+
+	# Allocate at least 4 words in the argstack
+	move	v0, bytes
+	bge	bytes, 4 * FFI_SIZEOF_ARG, bigger	
+	LI	v0, 4 * FFI_SIZEOF_ARG
+	b	sixteen
+
+	bigger:	
+	ADDU	t4, v0, 2 * FFI_SIZEOF_ARG -1	# make sure it is aligned 
+	and	v0, t4, -2 * FFI_SIZEOF_ARG		# to a proper boundry.
+
+sixteen:
+	SUBU	$sp, $sp, v0	# move the stack pointer to reflect the
+				# arg space
+
+	move	a0, $sp         # 4 * FFI_SIZEOF_ARG
+	ADDU	a3, $fp, 3 * FFI_SIZEOF_ARG
+
+	# Call ffi_prep_args
+	jal	t9
+	
+	# Copy the stack pointer to t9
+	move	t9, $sp
+	
+	# Fix the stack if there are more than 8 64bit slots worth
+	# of arguments.
+
+	# Load the number of bytes
+	REG_L	t6, 2*FFI_SIZEOF_ARG($fp)
+
+	# Is it bigger than 8 * FFI_SIZEOF_ARG?
+	daddiu	t8, t6, -(8 * FFI_SIZEOF_ARG)
+	bltz	t8, loadregs
+
+	ADDU	t9, t9, t8
+	
+loadregs:	
+
+	REG_L	t6, 3*FFI_SIZEOF_ARG($fp)  # load the flags word into t6.
+
+	and	t4, t6, ((1<<FFI_FLAG_BITS)-1)
+	bnez	t4, arg1_floatp
+	REG_L	a0, 0*FFI_SIZEOF_ARG(t9)
+	b	arg1_next
+arg1_floatp:	
+	bne	t4, FFI_TYPE_FLOAT, arg1_doublep
+	l.s	$f12, 0*FFI_SIZEOF_ARG(t9)
+	b	arg1_next
+arg1_doublep:	
+	l.d	$f12, 0*FFI_SIZEOF_ARG(t9)
+arg1_next:	
+	
+	SRL	t4, t6, 1*FFI_FLAG_BITS
+	and	t4, ((1<<FFI_FLAG_BITS)-1)
+	bnez	t4, arg2_floatp
+	REG_L	a1, 1*FFI_SIZEOF_ARG(t9)
+	b	arg2_next
+arg2_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg2_doublep
+	l.s	$f13, 1*FFI_SIZEOF_ARG(t9)	
+	b	arg2_next
+arg2_doublep:	
+	l.d	$f13, 1*FFI_SIZEOF_ARG(t9)	
+arg2_next:	
+	
+	SRL	t4, t6, 2*FFI_FLAG_BITS
+	and	t4, ((1<<FFI_FLAG_BITS)-1)
+	bnez	t4, arg3_floatp
+	REG_L	a2, 2*FFI_SIZEOF_ARG(t9)
+	b	arg3_next
+arg3_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg3_doublep
+	l.s	$f14, 2*FFI_SIZEOF_ARG(t9)	
+	b	arg3_next
+arg3_doublep:	
+	l.d	$f14, 2*FFI_SIZEOF_ARG(t9)	
+arg3_next:	
+	
+	SRL	t4, t6, 3*FFI_FLAG_BITS
+	and	t4, ((1<<FFI_FLAG_BITS)-1)
+	bnez	t4, arg4_floatp
+	REG_L	a3, 3*FFI_SIZEOF_ARG(t9)
+	b	arg4_next
+arg4_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg4_doublep
+	l.s	$f15, 3*FFI_SIZEOF_ARG(t9)	
+	b	arg4_next
+arg4_doublep:	
+	l.d	$f15, 3*FFI_SIZEOF_ARG(t9)	
+arg4_next:	
+	
+	SRL	t4, t6, 4*FFI_FLAG_BITS
+	and	t4, ((1<<FFI_FLAG_BITS)-1)
+	bnez	t4, arg5_floatp
+	REG_L	a4, 4*FFI_SIZEOF_ARG(t9)
+	b	arg5_next
+arg5_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg5_doublep
+	l.s	$f16, 4*FFI_SIZEOF_ARG(t9)	
+	b	arg5_next
+arg5_doublep:	
+	l.d	$f16, 4*FFI_SIZEOF_ARG(t9)	
+arg5_next:	
+	
+	SRL	t4, t6, 5*FFI_FLAG_BITS
+	and	t4, ((1<<FFI_FLAG_BITS)-1)
+	bnez	t4, arg6_floatp
+	REG_L	a5, 5*FFI_SIZEOF_ARG(t9)
+	b	arg6_next
+arg6_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg6_doublep
+	l.s	$f17, 5*FFI_SIZEOF_ARG(t9)	
+	b	arg6_next
+arg6_doublep:	
+	l.d	$f17, 5*FFI_SIZEOF_ARG(t9)	
+arg6_next:	
+	
+	SRL	t4, t6, 6*FFI_FLAG_BITS
+	and	t4, ((1<<FFI_FLAG_BITS)-1)
+	bnez	t4, arg7_floatp
+	REG_L	a6, 6*FFI_SIZEOF_ARG(t9)
+	b	arg7_next
+arg7_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg7_doublep
+	l.s	$f18, 6*FFI_SIZEOF_ARG(t9)	
+	b	arg7_next
+arg7_doublep:	
+	l.d	$f18, 6*FFI_SIZEOF_ARG(t9)	
+arg7_next:	
+	
+	SRL	t4, t6, 7*FFI_FLAG_BITS
+	and	t4, ((1<<FFI_FLAG_BITS)-1)
+	bnez	t4, arg8_floatp
+	REG_L	a7, 7*FFI_SIZEOF_ARG(t9)
+	b	arg8_next
+arg8_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg8_doublep
+ 	l.s	$f19, 7*FFI_SIZEOF_ARG(t9)	
+	b	arg8_next
+arg8_doublep:	
+ 	l.d	$f19, 7*FFI_SIZEOF_ARG(t9)	
+arg8_next:	
+
+callit:		
+	# Load the function pointer
+	REG_L	t9, 5*FFI_SIZEOF_ARG($fp)
+
+	# If the return value pointer is NULL, assume no return value.
+	REG_L	t5, 4*FFI_SIZEOF_ARG($fp)
+	beqz	t5, noretval
+
+	# Shift the return type flag over
+	SRL	t6, 8*FFI_FLAG_BITS
+
+	beq	t6, FFI_TYPE_SINT32, retint	
+	bne     t6, FFI_TYPE_INT, retfloat
+retint:
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	REG_S	v0, 0(t4)
+	b	epilogue
+
+retfloat:
+	bne     t6, FFI_TYPE_FLOAT, retdouble
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	s.s	$f0, 0(t4)
+	b	epilogue
+
+retdouble:	
+	bne	t6, FFI_TYPE_DOUBLE, retstruct_d
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	s.d	$f0, 0(t4)
+	b	epilogue
+
+retstruct_d:	
+	bne	t6, FFI_TYPE_STRUCT_D, retstruct_f
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	s.d	$f0, 0(t4)
+	b	epilogue
+	
+retstruct_f:	
+	bne	t6, FFI_TYPE_STRUCT_F, retstruct_d_d
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	s.s	$f0, 0(t4)
+	b	epilogue
+	
+retstruct_d_d:	
+	bne	t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	s.d	$f0, 0(t4)
+	s.d	$f2, 8(t4)
+	b	epilogue
+	
+retstruct_f_f:	
+	bne	t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	s.s	$f0, 0(t4)
+	s.s	$f2, 4(t4)
+	b	epilogue
+	
+retstruct_d_f:	
+	bne	t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	s.d	$f0, 0(t4)
+	s.s	$f2, 8(t4)
+	b	epilogue
+	
+retstruct_f_d:	
+	bne	t6, FFI_TYPE_STRUCT_FD, retstruct_d_soft
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	s.s	$f0, 0(t4)
+	s.d	$f2, 8(t4)
+	b	epilogue
+
+retstruct_d_soft:
+	bne	t6, FFI_TYPE_STRUCT_D_SOFT, retstruct_f_soft
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	sd	v0, 0(t4)
+	b	epilogue
+	
+retstruct_f_soft:	
+	bne	t6, FFI_TYPE_STRUCT_F_SOFT, retstruct_d_d_soft
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	sw	v0, 0(t4)
+	b	epilogue
+	
+retstruct_d_d_soft:	
+	bne	t6, FFI_TYPE_STRUCT_DD_SOFT, retstruct_f_f_soft
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	sd	v0, 0(t4)
+	sd	v1, 8(t4)
+	b	epilogue
+	
+retstruct_f_f_soft:	
+	bne	t6, FFI_TYPE_STRUCT_FF_SOFT, retstruct_d_f_soft
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	sw	v0, 0(t4)
+	sw	v1, 4(t4)
+	b	epilogue
+	
+retstruct_d_f_soft:	
+	bne	t6, FFI_TYPE_STRUCT_DF_SOFT, retstruct_f_d_soft
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	sd	v0, 0(t4)
+	sw	v1, 8(t4)
+	b	epilogue
+	
+retstruct_f_d_soft:	
+	bne	t6, FFI_TYPE_STRUCT_FD_SOFT, retstruct_small
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	sw	v0, 0(t4)
+	sd	v1, 8(t4)
+	b	epilogue
+	
+retstruct_small:	
+	bne	t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	REG_S	v0, 0(t4)
+	b	epilogue
+	
+retstruct_small2:	
+	bne	t6, FFI_TYPE_STRUCT_SMALL2, retstruct
+	jal	t9
+	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
+	REG_S	v0, 0(t4)
+	REG_S	v1, 8(t4)
+	b	epilogue
+	
+retstruct:	
+noretval:	
+	jal	t9
+	
+	# Epilogue
+epilogue:	
+	move	$sp, $fp	
+	REG_L	$fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
+	REG_L	ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)  # Restore return address
+	ADDU	$sp, SIZEOF_FRAME		      # Fix stack pointer
+	j	ra
+
+.LFE3:
+	.end	ffi_call_N32
+
+/* ffi_closure_N32. Expects address of the passed-in ffi_closure in t0
+   ($12). Stores any arguments passed in registers onto the stack,
+   then calls ffi_closure_mips_inner_N32, which then decodes
+   them.
+	
+	Stack layout:
+
+	20 - Start of parameters, original sp
+	19 - Called function a7 save
+	18 - Called function a6 save
+	17 - Called function a5 save
+	16 - Called function a4 save
+	15 - Called function a3 save
+	14 - Called function a2 save
+	13 - Called function a1 save
+	12 - Called function a0 save
+	11 - Called function f19
+	10 - Called function f18
+	 9 - Called function f17
+	 8 - Called function f16
+	 7 - Called function f15
+         6 - Called function f14
+         5 - Called function f13
+         4 - Called function f12
+	 3 - return value high (v1 or $f2)
+	 2 - return value low (v0 or $f0)
+	 1 - ra save
+	 0 - gp save our sp  points here
+	 */
+
+#define SIZEOF_FRAME2	(20 * FFI_SIZEOF_ARG)
+	
+#define A7_OFF2		(19 * FFI_SIZEOF_ARG)
+#define A6_OFF2		(18 * FFI_SIZEOF_ARG)
+#define A5_OFF2		(17 * FFI_SIZEOF_ARG)
+#define A4_OFF2		(16 * FFI_SIZEOF_ARG)
+#define A3_OFF2		(15 * FFI_SIZEOF_ARG)
+#define A2_OFF2		(14 * FFI_SIZEOF_ARG)
+#define A1_OFF2		(13 * FFI_SIZEOF_ARG)
+#define A0_OFF2		(12 * FFI_SIZEOF_ARG)	
+
+#define F19_OFF2	(11 * FFI_SIZEOF_ARG)
+#define F18_OFF2	(10 * FFI_SIZEOF_ARG)
+#define F17_OFF2	(9  * FFI_SIZEOF_ARG)
+#define F16_OFF2	(8  * FFI_SIZEOF_ARG)
+#define F15_OFF2	(7  * FFI_SIZEOF_ARG)
+#define F14_OFF2	(6  * FFI_SIZEOF_ARG)
+#define F13_OFF2	(5  * FFI_SIZEOF_ARG)
+#define F12_OFF2	(4  * FFI_SIZEOF_ARG)
+
+#define V1_OFF2		(3  * FFI_SIZEOF_ARG)
+#define V0_OFF2		(2  * FFI_SIZEOF_ARG)
+
+#define RA_OFF2		(1  * FFI_SIZEOF_ARG)
+#define GP_OFF2		(0  * FFI_SIZEOF_ARG)
+
+	.align	2
+	.globl	ffi_closure_N32
+	.ent	ffi_closure_N32
+ffi_closure_N32:
+.LFB2:
+	.frame	$sp, SIZEOF_FRAME2, ra
+	.mask	0x90000000,-(SIZEOF_FRAME2 - RA_OFF2)
+	.fmask	0x00000000,0
+	SUBU	$sp, SIZEOF_FRAME2
+.LCFI5:
+	.cpsetup t9, GP_OFF2, ffi_closure_N32
+	REG_S	ra, RA_OFF2($sp)	# Save return address
+.LCFI6:
+	# Store all possible argument registers. If there are more than
+	# fit in registers, then they were stored on the stack.
+	REG_S	a0, A0_OFF2($sp)
+	REG_S	a1, A1_OFF2($sp)
+	REG_S	a2, A2_OFF2($sp)
+	REG_S	a3, A3_OFF2($sp)
+	REG_S	a4, A4_OFF2($sp)
+	REG_S	a5, A5_OFF2($sp)
+	REG_S	a6, A6_OFF2($sp)
+	REG_S	a7, A7_OFF2($sp)
+
+	# Store all possible float/double registers.
+	s.d	$f12, F12_OFF2($sp)
+	s.d	$f13, F13_OFF2($sp)
+	s.d	$f14, F14_OFF2($sp)
+	s.d	$f15, F15_OFF2($sp)
+	s.d	$f16, F16_OFF2($sp)
+	s.d	$f17, F17_OFF2($sp)
+	s.d	$f18, F18_OFF2($sp)
+	s.d	$f19, F19_OFF2($sp)
+
+	# Call ffi_closure_mips_inner_N32 to do the real work.
+	LA	t9, ffi_closure_mips_inner_N32
+	move	a0, $12	 # Pointer to the ffi_closure
+	ADDU	a1, $sp, V0_OFF2
+	ADDU	a2, $sp, A0_OFF2
+	ADDU	a3, $sp, F12_OFF2
+	jalr	t9
+
+	# Return flags are in v0
+	bne     v0, FFI_TYPE_SINT32, cls_retint
+	lw	v0, V0_OFF2($sp)
+	b	cls_epilogue
+
+cls_retint:
+	bne     v0, FFI_TYPE_INT, cls_retfloat
+	REG_L	v0, V0_OFF2($sp)
+	b	cls_epilogue
+
+cls_retfloat:
+	bne     v0, FFI_TYPE_FLOAT, cls_retdouble
+	l.s	$f0, V0_OFF2($sp)
+	b	cls_epilogue
+
+cls_retdouble:	
+	bne	v0, FFI_TYPE_DOUBLE, cls_retstruct_d
+	l.d	$f0, V0_OFF2($sp)
+	b	cls_epilogue
+
+cls_retstruct_d:	
+	bne	v0, FFI_TYPE_STRUCT_D, cls_retstruct_f
+	l.d	$f0, V0_OFF2($sp)
+	b	cls_epilogue
+	
+cls_retstruct_f:	
+	bne	v0, FFI_TYPE_STRUCT_F, cls_retstruct_d_d
+	l.s	$f0, V0_OFF2($sp)
+	b	cls_epilogue
+	
+cls_retstruct_d_d:	
+	bne	v0, FFI_TYPE_STRUCT_DD, cls_retstruct_f_f
+	l.d	$f0, V0_OFF2($sp)
+	l.d	$f2, V1_OFF2($sp)
+	b	cls_epilogue
+	
+cls_retstruct_f_f:	
+	bne	v0, FFI_TYPE_STRUCT_FF, cls_retstruct_d_f
+	l.s	$f0, V0_OFF2($sp)
+	l.s	$f2, V1_OFF2($sp)
+	b	cls_epilogue
+	
+cls_retstruct_d_f:	
+	bne	v0, FFI_TYPE_STRUCT_DF, cls_retstruct_f_d
+	l.d	$f0, V0_OFF2($sp)
+	l.s	$f2, V1_OFF2($sp)
+	b	cls_epilogue
+	
+cls_retstruct_f_d:	
+	bne	v0, FFI_TYPE_STRUCT_FD, cls_retstruct_small2
+	l.s	$f0, V0_OFF2($sp)
+	l.d	$f2, V1_OFF2($sp)
+	b	cls_epilogue
+	
+cls_retstruct_small2:	
+	REG_L	v0, V0_OFF2($sp)
+	REG_L	v1, V1_OFF2($sp)
+	
+	# Epilogue
+cls_epilogue:	
+	REG_L	ra,  RA_OFF2($sp)	 # Restore return address
+	.cpreturn
+	ADDU	$sp, SIZEOF_FRAME2
+	j	ra
+.LFE2:	
+	.end	ffi_closure_N32
+
+#ifdef __GNUC__
+        .section        .eh_frame,"aw",@progbits
+.Lframe1:
+        .4byte  .LECIE1-.LSCIE1		# length
+.LSCIE1:
+        .4byte  0x0			# CIE
+        .byte   0x1			# Version 1
+        .ascii  "\000"			# Augmentation
+        .uleb128 0x1			# Code alignment 1
+        .sleb128 -4			# Data alignment -4
+        .byte   0x1f			# Return Address $31
+        .byte   0xc			# DW_CFA_def_cfa
+        .uleb128 0x1d			# in $sp
+        .uleb128 0x0			# offset 0
+        .align  EH_FRAME_ALIGN
+.LECIE1:
+
+.LSFDE1:
+        .4byte  .LEFDE1-.LASFDE1	# length.
+.LASFDE1:
+        .4byte  .LASFDE1-.Lframe1	# CIE_pointer.
+        FDE_ADDR_BYTES  .LFB3		# initial_location.
+        FDE_ADDR_BYTES  .LFE3-.LFB3	# address_range.
+        .byte   0x4			# DW_CFA_advance_loc4
+        .4byte  .LCFI0-.LFB3		# to .LCFI0
+        .byte   0xe			# DW_CFA_def_cfa_offset
+        .uleb128 SIZEOF_FRAME		# adjust stack.by SIZEOF_FRAME
+        .byte   0x4			# DW_CFA_advance_loc4
+        .4byte  .LCFI1-.LCFI0		# to .LCFI1
+        .byte   0x9e			# DW_CFA_offset of $fp
+        .uleb128 2*FFI_SIZEOF_ARG/4	# 
+        .byte   0x9f			# DW_CFA_offset of ra
+        .uleb128 1*FFI_SIZEOF_ARG/4	# 
+        .byte   0x4			# DW_CFA_advance_loc4
+        .4byte  .LCFI3-.LCFI1		# to .LCFI3
+        .byte   0xd			# DW_CFA_def_cfa_register
+        .uleb128 0x1e			# in $fp
+        .align  EH_FRAME_ALIGN
+.LEFDE1:
+.LSFDE3:
+	.4byte	.LEFDE3-.LASFDE3	# length
+.LASFDE3:
+	.4byte	.LASFDE3-.Lframe1	# CIE_pointer.
+	FDE_ADDR_BYTES	.LFB2		# initial_location.
+	FDE_ADDR_BYTES	.LFE2-.LFB2	# address_range.
+	.byte	0x4			# DW_CFA_advance_loc4
+	.4byte	.LCFI5-.LFB2		# to .LCFI5
+	.byte	0xe			# DW_CFA_def_cfa_offset
+	.uleb128 SIZEOF_FRAME2		# adjust stack.by SIZEOF_FRAME
+	.byte	0x4			# DW_CFA_advance_loc4
+	.4byte	.LCFI6-.LCFI5		# to .LCFI6
+	.byte	0x9c			# DW_CFA_offset of $gp ($28)
+	.uleb128 (SIZEOF_FRAME2 - GP_OFF2)/4
+	.byte	0x9f			# DW_CFA_offset of ra ($31)
+	.uleb128 (SIZEOF_FRAME2 - RA_OFF2)/4
+	.align	EH_FRAME_ALIGN
+.LEFDE3:
+#endif /* __GNUC__ */	
+	
+#endif
diff --git a/third_party/gofrontend/libffi/src/mips/o32.S b/third_party/gofrontend/libffi/src/mips/o32.S
new file mode 100644
index 0000000..eb27981
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/mips/o32.S
@@ -0,0 +1,381 @@
+/* -----------------------------------------------------------------------
+   o32.S - Copyright (c) 1996, 1998, 2005  Red Hat, Inc.
+   
+   MIPS Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+/* Only build this code if we are compiling for o32 */	
+
+#if defined(FFI_MIPS_O32)
+	
+#define callback a0
+#define bytes	 a2
+#define flags	 a3
+		
+#define SIZEOF_FRAME	(4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG)
+#define A3_OFF		(SIZEOF_FRAME + 3 * FFI_SIZEOF_ARG)
+#define FP_OFF		(SIZEOF_FRAME - 2 * FFI_SIZEOF_ARG)
+#define RA_OFF		(SIZEOF_FRAME - 1 * FFI_SIZEOF_ARG)
+
+	.abicalls
+	.text
+	.align	2
+	.globl	ffi_call_O32
+	.ent	ffi_call_O32
+ffi_call_O32:	
+$LFB0:
+	# Prologue
+	SUBU	$sp, SIZEOF_FRAME	# Frame size
+$LCFI0:
+	REG_S	$fp, FP_OFF($sp)	# Save frame pointer
+$LCFI1:
+	REG_S	ra, RA_OFF($sp)		# Save return address
+$LCFI2:
+	move	$fp, $sp
+
+$LCFI3:
+	move	t9, callback		# callback function pointer
+	REG_S	flags, A3_OFF($fp)	# flags
+
+	# Allocate at least 4 words in the argstack
+	LI	v0, 4 * FFI_SIZEOF_ARG
+	blt	bytes, v0, sixteen
+
+	ADDU	v0, bytes, 7	# make sure it is aligned 
+	and	v0, -8		# to an 8 byte boundry
+
+sixteen:
+	SUBU	$sp, v0		# move the stack pointer to reflect the
+				# arg space
+
+	ADDU	a0, $sp, 4 * FFI_SIZEOF_ARG
+
+	jalr	t9
+	
+	REG_L	t0, A3_OFF($fp)		# load the flags word
+	SRL	t2, t0, 4		# shift our arg info
+	and     t0, ((1<<4)-1)          # mask out the return type
+		
+	ADDU	$sp, 4 * FFI_SIZEOF_ARG		# adjust $sp to new args
+
+	bnez	t0, pass_d			# make it quick for int
+	REG_L	a0, 0*FFI_SIZEOF_ARG($sp)	# just go ahead and load the
+	REG_L	a1, 1*FFI_SIZEOF_ARG($sp)	# four regs.
+	REG_L	a2, 2*FFI_SIZEOF_ARG($sp)
+	REG_L	a3, 3*FFI_SIZEOF_ARG($sp)
+	b	call_it
+
+pass_d:
+	bne	t0, FFI_ARGS_D, pass_f
+	l.d	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
+	REG_L	a2,   2*FFI_SIZEOF_ARG($sp)	# passing a double
+	REG_L	a3,   3*FFI_SIZEOF_ARG($sp)
+	b	call_it
+
+pass_f:	
+	bne	t0, FFI_ARGS_F, pass_d_d
+	l.s	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
+	REG_L	a1,   1*FFI_SIZEOF_ARG($sp)	# passing a float
+	REG_L	a2,   2*FFI_SIZEOF_ARG($sp)
+	REG_L	a3,   3*FFI_SIZEOF_ARG($sp)
+	b	call_it		
+
+pass_d_d:		
+	bne	t0, FFI_ARGS_DD, pass_f_f
+	l.d	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
+	l.d	$f14, 2*FFI_SIZEOF_ARG($sp)	# passing two doubles
+	b	call_it
+
+pass_f_f:	
+	bne	t0, FFI_ARGS_FF, pass_d_f
+	l.s	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
+	l.s	$f14, 1*FFI_SIZEOF_ARG($sp)	# passing two floats
+	REG_L	a2,   2*FFI_SIZEOF_ARG($sp)
+	REG_L	a3,   3*FFI_SIZEOF_ARG($sp)
+	b	call_it
+
+pass_d_f:		
+	bne	t0, FFI_ARGS_DF, pass_f_d
+	l.d	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
+	l.s	$f14, 2*FFI_SIZEOF_ARG($sp)	# passing double and float
+	REG_L	a3,   3*FFI_SIZEOF_ARG($sp)
+	b	call_it
+
+pass_f_d:		
+ # assume that the only other combination must be float then double
+ #	bne	t0, FFI_ARGS_F_D, call_it
+	l.s	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
+	l.d	$f14, 2*FFI_SIZEOF_ARG($sp)	# passing double and float
+
+call_it:	
+	# Load the function pointer
+	REG_L	t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp)
+
+	# If the return value pointer is NULL, assume no return value.
+	REG_L	t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+	beqz	t1, noretval
+
+	bne     t2, FFI_TYPE_INT, retlonglong
+	jalr	t9
+	REG_L	t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+	REG_S	v0, 0(t0)
+	b	epilogue
+
+retlonglong:
+	# Really any 64-bit int, signed or not.
+	bne	t2, FFI_TYPE_UINT64, retfloat
+	jalr	t9
+	REG_L	t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+	REG_S	v1, 4(t0)
+	REG_S	v0, 0(t0)
+	b	epilogue
+
+retfloat:
+	bne     t2, FFI_TYPE_FLOAT, retdouble
+	jalr	t9
+	REG_L	t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+	s.s	$f0, 0(t0)
+	b	epilogue
+
+retdouble:	
+	bne	t2, FFI_TYPE_DOUBLE, noretval
+	jalr	t9
+	REG_L	t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+	s.d	$f0, 0(t0)
+	b	epilogue
+	
+noretval:	
+	jalr	t9
+	
+	# Epilogue
+epilogue:	
+	move	$sp, $fp	
+	REG_L	$fp, FP_OFF($sp)	# Restore frame pointer
+	REG_L	ra, RA_OFF($sp)		# Restore return address
+	ADDU	$sp, SIZEOF_FRAME	# Fix stack pointer
+	j	ra
+
+$LFE0:
+	.end	ffi_call_O32
+
+
+/* ffi_closure_O32. Expects address of the passed-in ffi_closure
+	in t4 ($12). Stores any arguments passed in registers onto the
+	stack, then calls ffi_closure_mips_inner_O32, which
+	then decodes them.
+	
+	Stack layout:
+
+	 3 - a3 save
+	 2 - a2 save
+	 1 - a1 save
+	 0 - a0 save, original sp
+	-1 - ra save
+	-2 - fp save
+	-3 - $16 (s0) save
+	-4 - cprestore
+	-5 - return value high (v1)
+	-6 - return value low (v0)
+	-7 - f14 (le high, be low)
+	-8 - f14 (le low, be high)
+	-9 - f12 (le high, be low)
+       -10 - f12 (le low, be high)
+       -11 - Called function a3 save
+       -12 - Called function a2 save
+       -13 - Called function a1 save
+       -14 - Called function a0 save, our sp and fp point here
+	 */
+	
+#define SIZEOF_FRAME2	(14 * FFI_SIZEOF_ARG)
+#define A3_OFF2		(SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG)
+#define A2_OFF2		(SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
+#define A1_OFF2		(SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG)
+#define A0_OFF2		(SIZEOF_FRAME2 + 0 * FFI_SIZEOF_ARG)
+#define RA_OFF2		(SIZEOF_FRAME2 - 1 * FFI_SIZEOF_ARG)
+#define FP_OFF2		(SIZEOF_FRAME2 - 2 * FFI_SIZEOF_ARG)
+#define S0_OFF2		(SIZEOF_FRAME2 - 3 * FFI_SIZEOF_ARG)
+#define GP_OFF2		(SIZEOF_FRAME2 - 4 * FFI_SIZEOF_ARG)
+#define V1_OFF2		(SIZEOF_FRAME2 - 5 * FFI_SIZEOF_ARG)
+#define V0_OFF2		(SIZEOF_FRAME2 - 6 * FFI_SIZEOF_ARG)
+#define FA_1_1_OFF2	(SIZEOF_FRAME2 - 7 * FFI_SIZEOF_ARG)
+#define FA_1_0_OFF2	(SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG)
+#define FA_0_1_OFF2	(SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG)
+#define FA_0_0_OFF2	(SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG)
+
+	.text
+	.align	2
+	.globl	ffi_closure_O32
+	.ent	ffi_closure_O32
+ffi_closure_O32:
+$LFB1:
+	# Prologue
+	.frame	$fp, SIZEOF_FRAME2, ra
+	.set	noreorder
+	.cpload	t9
+	.set	reorder
+	SUBU	$sp, SIZEOF_FRAME2
+	.cprestore GP_OFF2
+$LCFI4:
+	REG_S	$16, S0_OFF2($sp)	 # Save s0
+	REG_S	$fp, FP_OFF2($sp)	 # Save frame pointer
+	REG_S	ra, RA_OFF2($sp)	 # Save return address
+$LCFI6:
+	move	$fp, $sp
+
+$LCFI7:
+	# Store all possible argument registers. If there are more than
+	# four arguments, then they are stored above where we put a3.
+	REG_S	a0, A0_OFF2($fp)
+	REG_S	a1, A1_OFF2($fp)
+	REG_S	a2, A2_OFF2($fp)
+	REG_S	a3, A3_OFF2($fp)
+
+	# Load ABI enum to s0
+	REG_L	$16, 20($12)	# cif pointer follows tramp.
+	REG_L	$16, 0($16)	# abi is first member.
+
+	li	$13, 1		# FFI_O32
+	bne	$16, $13, 1f	# Skip fp save if FFI_O32_SOFT_FLOAT
+	
+	# Store all possible float/double registers.
+	s.d	$f12, FA_0_0_OFF2($fp)
+	s.d	$f14, FA_1_0_OFF2($fp)
+1:	
+	# Call ffi_closure_mips_inner_O32 to do the work.
+	la	t9, ffi_closure_mips_inner_O32
+	move	a0, $12	 # Pointer to the ffi_closure
+	addu	a1, $fp, V0_OFF2
+	addu	a2, $fp, A0_OFF2
+	addu	a3, $fp, FA_0_0_OFF2
+	jalr	t9
+
+	# Load the return value into the appropriate register.
+	move	$8, $2
+	li	$9, FFI_TYPE_VOID
+	beq	$8, $9, closure_done
+
+	li	$13, 1		# FFI_O32
+	bne	$16, $13, 1f	# Skip fp restore if FFI_O32_SOFT_FLOAT
+
+	li	$9, FFI_TYPE_FLOAT
+	l.s	$f0, V0_OFF2($fp)
+	beq	$8, $9, closure_done
+
+	li	$9, FFI_TYPE_DOUBLE
+	l.d	$f0, V0_OFF2($fp)
+	beq	$8, $9, closure_done
+1:	
+	REG_L	$3, V1_OFF2($fp)
+	REG_L	$2, V0_OFF2($fp)
+
+closure_done:
+	# Epilogue
+	move	$sp, $fp
+	REG_L	$16, S0_OFF2($sp)	 # Restore s0
+	REG_L	$fp, FP_OFF2($sp)	 # Restore frame pointer
+	REG_L	ra,  RA_OFF2($sp)	 # Restore return address
+	ADDU	$sp, SIZEOF_FRAME2
+	j	ra
+$LFE1:
+	.end	ffi_closure_O32
+
+/* DWARF-2 unwind info. */
+
+	.section	.eh_frame,"a",@progbits
+$Lframe0:
+	.4byte	$LECIE0-$LSCIE0	 # Length of Common Information Entry
+$LSCIE0:
+	.4byte	0x0	 # CIE Identifier Tag
+	.byte	0x1	 # CIE Version
+	.ascii "zR\0"	 # CIE Augmentation
+	.uleb128 0x1	 # CIE Code Alignment Factor
+	.sleb128 4	 # CIE Data Alignment Factor
+	.byte	0x1f	 # CIE RA Column
+	.uleb128 0x1	 # Augmentation size
+	.byte	0x00	 # FDE Encoding (absptr)
+	.byte	0xc	 # DW_CFA_def_cfa
+	.uleb128 0x1d
+	.uleb128 0x0
+	.align	2
+$LECIE0:
+$LSFDE0:
+	.4byte	$LEFDE0-$LASFDE0	 # FDE Length
+$LASFDE0:
+	.4byte	$LASFDE0-$Lframe0	 # FDE CIE offset
+	.4byte	$LFB0	 # FDE initial location
+	.4byte	$LFE0-$LFB0	 # FDE address range
+	.uleb128 0x0	 # Augmentation size
+	.byte	0x4	 # DW_CFA_advance_loc4
+	.4byte	$LCFI0-$LFB0
+	.byte	0xe	 # DW_CFA_def_cfa_offset
+	.uleb128 0x18
+	.byte	0x4	 # DW_CFA_advance_loc4
+	.4byte	$LCFI2-$LCFI0
+	.byte	0x11	 # DW_CFA_offset_extended_sf
+	.uleb128 0x1e	 # $fp
+	.sleb128 -2	 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
+	.byte	0x11	 # DW_CFA_offset_extended_sf
+	.uleb128 0x1f	 # $ra
+	.sleb128 -1	 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
+	.byte	0x4	 # DW_CFA_advance_loc4
+	.4byte	$LCFI3-$LCFI2
+	.byte	0xc	 # DW_CFA_def_cfa
+	.uleb128 0x1e
+	.uleb128 0x18
+	.align	2
+$LEFDE0:
+$LSFDE1:
+	.4byte	$LEFDE1-$LASFDE1	 # FDE Length
+$LASFDE1:
+	.4byte	$LASFDE1-$Lframe0	 # FDE CIE offset
+	.4byte	$LFB1	 # FDE initial location
+	.4byte	$LFE1-$LFB1	 # FDE address range
+	.uleb128 0x0	 # Augmentation size
+	.byte	0x4	 # DW_CFA_advance_loc4
+	.4byte	$LCFI4-$LFB1
+	.byte	0xe	 # DW_CFA_def_cfa_offset
+	.uleb128 0x38
+	.byte	0x4	 # DW_CFA_advance_loc4
+	.4byte	$LCFI6-$LCFI4
+	.byte	0x11	 # DW_CFA_offset_extended_sf
+	.uleb128 0x10	 # $16
+	.sleb128 -3	 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)
+	.byte	0x11	 # DW_CFA_offset_extended_sf
+	.uleb128 0x1e	 # $fp
+	.sleb128 -2	 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
+	.byte	0x11	 # DW_CFA_offset_extended_sf
+	.uleb128 0x1f	 # $ra
+	.sleb128 -1	 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
+	.byte	0x4	 # DW_CFA_advance_loc4
+	.4byte	$LCFI7-$LCFI6
+	.byte	0xc	 # DW_CFA_def_cfa
+	.uleb128 0x1e
+	.uleb128 0x38
+	.align	2
+$LEFDE1:
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/pa/ffi.c b/third_party/gofrontend/libffi/src/pa/ffi.c
new file mode 100644
index 0000000..4ce2bc6
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/pa/ffi.c
@@ -0,0 +1,719 @@
+/* -----------------------------------------------------------------------
+   ffi.c - (c) 2011 Anthony Green
+           (c) 2008 Red Hat, Inc.
+	   (c) 2006 Free Software Foundation, Inc.
+           (c) 2003-2004 Randolph Chung <tausq@debian.org>
+           
+   HPPA Foreign Function Interface
+   HP-UX PA ABI support 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#define ROUND_UP(v, a)  (((size_t)(v) + (a) - 1) & ~((a) - 1))
+
+#define MIN_STACK_SIZE  64
+#define FIRST_ARG_SLOT  9
+#define DEBUG_LEVEL   0
+
+#define fldw(addr, fpreg) \
+  __asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
+#define fstw(fpreg, addr) \
+  __asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
+#define fldd(addr, fpreg) \
+  __asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
+#define fstd(fpreg, addr) \
+  __asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
+
+#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
+
+static inline int ffi_struct_type(ffi_type *t)
+{
+  size_t sz = t->size;
+
+  /* Small structure results are passed in registers,
+     larger ones are passed by pointer.  Note that
+     small structures of size 2, 4 and 8 differ from
+     the corresponding integer types in that they have
+     different alignment requirements.  */
+
+  if (sz <= 1)
+    return FFI_TYPE_UINT8;
+  else if (sz == 2)
+    return FFI_TYPE_SMALL_STRUCT2;
+  else if (sz == 3)
+    return FFI_TYPE_SMALL_STRUCT3;
+  else if (sz == 4)
+    return FFI_TYPE_SMALL_STRUCT4;
+  else if (sz == 5)
+    return FFI_TYPE_SMALL_STRUCT5;
+  else if (sz == 6)
+    return FFI_TYPE_SMALL_STRUCT6;
+  else if (sz == 7)
+    return FFI_TYPE_SMALL_STRUCT7;
+  else if (sz <= 8)
+    return FFI_TYPE_SMALL_STRUCT8;
+  else
+    return FFI_TYPE_STRUCT; /* else, we pass it by pointer.  */
+}
+
+/* PA has a downward growing stack, which looks like this:
+
+   Offset
+	[ Variable args ]
+   SP = (4*(n+9))       arg word N
+   ...
+   SP-52                arg word 4
+	[ Fixed args ]
+   SP-48                arg word 3
+   SP-44                arg word 2
+   SP-40                arg word 1
+   SP-36                arg word 0
+	[ Frame marker ]
+   ...
+   SP-20                RP
+   SP-4                 previous SP
+
+   The first four argument words on the stack are reserved for use by
+   the callee.  Instead, the general and floating registers replace
+   the first four argument slots.  Non FP arguments are passed solely
+   in the general registers.  FP arguments are passed in both general
+   and floating registers when using libffi.
+
+   Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
+   Non-FP 64-bit args are passed in register pairs, starting
+   on an odd numbered register (i.e. r25+r26 and r23+r24).
+   FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
+   FP 64-bit arguments are passed in fr5 and fr7.
+
+   The registers are allocated in the same manner as stack slots.
+   This allows the callee to save its arguments on the stack if
+   necessary:
+
+   arg word 3 -> gr23 or fr7L
+   arg word 2 -> gr24 or fr6L or fr7R
+   arg word 1 -> gr25 or fr5L
+   arg word 0 -> gr26 or fr4L or fr5R
+
+   Note that fr4R and fr6R are never used for arguments (i.e.,
+   doubles are not passed in fr4 or fr6).
+
+   The rest of the arguments are passed on the stack starting at SP-52,
+   but 64-bit arguments need to be aligned to an 8-byte boundary
+
+   This means we can have holes either in the register allocation,
+   or in the stack.  */
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments
+
+   The following code will put everything into the stack frame
+   (which was allocated by the asm routine), and on return
+   the asm routine will load the arguments that should be
+   passed by register into the appropriate registers
+
+   NOTE: We load floating point args in this function... that means we
+   assume gcc will not mess with fp regs in here.  */
+
+void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
+{
+  register unsigned int i;
+  register ffi_type **p_arg;
+  register void **p_argv;
+  unsigned int slot = FIRST_ARG_SLOT;
+  char *dest_cpy;
+  size_t len;
+
+  debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
+	ecif, bytes);
+
+  p_arg = ecif->cif->arg_types;
+  p_argv = ecif->avalue;
+
+  for (i = 0; i < ecif->cif->nargs; i++)
+    {
+      int type = (*p_arg)->type;
+
+      switch (type)
+	{
+	case FFI_TYPE_SINT8:
+	  *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_UINT8:
+	  *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_SINT16:
+	  *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_UINT16:
+	  *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_POINTER:
+	  debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
+		slot);
+	  *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	  /* Align slot for 64-bit type.  */
+	  slot += (slot & 1) ? 1 : 2;
+	  *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  /* First 4 args go in fr4L - fr7L.  */
+	  debug(3, "Storing UINT32(float) in slot %u\n", slot);
+	  *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
+	  switch (slot - FIRST_ARG_SLOT)
+	    {
+	    /* First 4 args go in fr4L - fr7L.  */
+	    case 0: fldw(stack - slot, fr4); break;
+	    case 1: fldw(stack - slot, fr5); break;
+	    case 2: fldw(stack - slot, fr6); break;
+	    case 3: fldw(stack - slot, fr7); break;
+	    }
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  /* Align slot for 64-bit type.  */
+	  slot += (slot & 1) ? 1 : 2;
+	  debug(3, "Storing UINT64(double) at slot %u\n", slot);
+	  *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
+	  switch (slot - FIRST_ARG_SLOT)
+	    {
+	      /* First 2 args go in fr5, fr7.  */
+	      case 1: fldd(stack - slot, fr5); break;
+	      case 3: fldd(stack - slot, fr7); break;
+	    }
+	  break;
+
+#ifdef PA_HPUX
+	case FFI_TYPE_LONGDOUBLE:
+	  /* Long doubles are passed in the same manner as structures
+	     larger than 8 bytes.  */
+	  *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
+	  break;
+#endif
+
+	case FFI_TYPE_STRUCT:
+
+	  /* Structs smaller or equal than 4 bytes are passed in one
+	     register. Structs smaller or equal 8 bytes are passed in two
+	     registers. Larger structures are passed by pointer.  */
+
+	  len = (*p_arg)->size;
+	  if (len <= 4)
+	    {
+	      dest_cpy = (char *)(stack - slot) + 4 - len;
+	      memcpy(dest_cpy, (char *)*p_argv, len);
+	    }
+	  else if (len <= 8)
+	    {
+	      slot += (slot & 1) ? 1 : 2;
+	      dest_cpy = (char *)(stack - slot) + 8 - len;
+	      memcpy(dest_cpy, (char *)*p_argv, len);
+	    }
+	  else
+	    *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
+	  break;
+
+	default:
+	  FFI_ASSERT(0);
+	}
+
+      slot++;
+      p_arg++;
+      p_argv++;
+    }
+
+  /* Make sure we didn't mess up and scribble on the stack.  */
+  {
+    unsigned int n;
+
+    debug(5, "Stack setup:\n");
+    for (n = 0; n < (bytes + 3) / 4; n++)
+      {
+	if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
+	debug(5, "%08x ", *(stack - n));
+      }
+    debug(5, "\n");
+  }
+
+  FFI_ASSERT(slot * 4 <= bytes);
+
+  return;
+}
+
+static void ffi_size_stack_pa32(ffi_cif *cif)
+{
+  ffi_type **ptr;
+  int i;
+  int z = 0; /* # stack slots */
+
+  for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
+    {
+      int type = (*ptr)->type;
+
+      switch (type)
+	{
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	  z += 2 + (z & 1); /* must start on even regs, so we may waste one */
+	  break;
+
+#ifdef PA_HPUX
+	case FFI_TYPE_LONGDOUBLE:
+#endif
+	case FFI_TYPE_STRUCT:
+	  z += 1; /* pass by ptr, callee will copy */
+	  break;
+
+	default: /* <= 32-bit values */
+	  z++;
+	}
+    }
+
+  /* We can fit up to 6 args in the default 64-byte stack frame,
+     if we need more, we need more stack.  */
+  if (z <= 6)
+    cif->bytes = MIN_STACK_SIZE; /* min stack size */
+  else
+    cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
+
+  debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
+}
+
+/* Perform machine dependent cif processing.  */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+#ifdef PA_HPUX
+    case FFI_TYPE_LONGDOUBLE:
+      /* Long doubles are treated like a structure.  */
+      cif->flags = FFI_TYPE_STRUCT;
+      break;
+#endif
+
+    case FFI_TYPE_STRUCT:
+      /* For the return type we have to check the size of the structures.
+	 If the size is smaller or equal 4 bytes, the result is given back
+	 in one register. If the size is smaller or equal 8 bytes than we
+	 return the result in two registers. But if the size is bigger than
+	 8 bytes, we work with pointers.  */
+      cif->flags = ffi_struct_type(cif->rtype);
+      break;
+
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      cif->flags = FFI_TYPE_UINT64;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  /* Lucky us, because of the unique PA ABI we get to do our
+     own stack sizing.  */
+  switch (cif->abi)
+    {
+    case FFI_PA32:
+      ffi_size_stack_pa32(cif);
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
+			  extended_cif *, unsigned, unsigned, unsigned *,
+			  void (*fn)(void));
+
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have a return
+     value address then we need to make one.  */
+
+  if (rvalue == NULL
+#ifdef PA_HPUX
+      && (cif->rtype->type == FFI_TYPE_STRUCT
+	  || cif->rtype->type == FFI_TYPE_LONGDOUBLE))
+#else
+      && cif->rtype->type == FFI_TYPE_STRUCT)
+#endif
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+
+  switch (cif->abi)
+    {
+    case FFI_PA32:
+      debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
+      ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
+		     cif->flags, ecif.rvalue, fn);
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#if FFI_CLOSURES
+/* This is more-or-less an inverse of ffi_call -- we have arguments on
+   the stack, and we need to fill them into a cif structure and invoke
+   the user function. This really ought to be in asm to make sure
+   the compiler doesn't do things we don't expect.  */
+ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
+{
+  ffi_cif *cif;
+  void **avalue;
+  void *rvalue;
+  UINT32 ret[2]; /* function can return up to 64-bits in registers */
+  ffi_type **p_arg;
+  char *tmp;
+  int i, avn;
+  unsigned int slot = FIRST_ARG_SLOT;
+  register UINT32 r28 asm("r28");
+
+  cif = closure->cif;
+
+  /* If returning via structure, callee will write to our pointer.  */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    rvalue = (void *)r28;
+  else
+    rvalue = &ret[0];
+
+  avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
+  avn = cif->nargs;
+  p_arg = cif->arg_types;
+
+  for (i = 0; i < avn; i++)
+    {
+      int type = (*p_arg)->type;
+
+      switch (type)
+	{
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_POINTER:
+	  avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
+	  break;
+
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	  slot += (slot & 1) ? 1 : 2;
+	  avalue[i] = (void *)(stack - slot);
+	  break;
+
+	case FFI_TYPE_FLOAT:
+#ifdef PA_LINUX
+	  /* The closure call is indirect.  In Linux, floating point
+	     arguments in indirect calls with a prototype are passed
+	     in the floating point registers instead of the general
+	     registers.  So, we need to replace what was previously
+	     stored in the current slot with the value in the
+	     corresponding floating point register.  */
+	  switch (slot - FIRST_ARG_SLOT)
+	    {
+	    case 0: fstw(fr4, (void *)(stack - slot)); break;
+	    case 1: fstw(fr5, (void *)(stack - slot)); break;
+	    case 2: fstw(fr6, (void *)(stack - slot)); break;
+	    case 3: fstw(fr7, (void *)(stack - slot)); break;
+	    }
+#endif
+	  avalue[i] = (void *)(stack - slot);
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  slot += (slot & 1) ? 1 : 2;
+#ifdef PA_LINUX
+	  /* See previous comment for FFI_TYPE_FLOAT.  */
+	  switch (slot - FIRST_ARG_SLOT)
+	    {
+	    case 1: fstd(fr5, (void *)(stack - slot)); break;
+	    case 3: fstd(fr7, (void *)(stack - slot)); break;
+	    }
+#endif
+	  avalue[i] = (void *)(stack - slot);
+	  break;
+
+#ifdef PA_HPUX
+	case FFI_TYPE_LONGDOUBLE:
+	  /* Long doubles are treated like a big structure.  */
+	  avalue[i] = (void *) *(stack - slot);
+	  break;
+#endif
+
+	case FFI_TYPE_STRUCT:
+	  /* Structs smaller or equal than 4 bytes are passed in one
+	     register. Structs smaller or equal 8 bytes are passed in two
+	     registers. Larger structures are passed by pointer.  */
+	  if((*p_arg)->size <= 4)
+	    {
+	      avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
+		(*p_arg)->size;
+	    }
+	  else if ((*p_arg)->size <= 8)
+	    {
+	      slot += (slot & 1) ? 1 : 2;
+	      avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
+		(*p_arg)->size;
+	    }
+	  else
+	    avalue[i] = (void *) *(stack - slot);
+	  break;
+
+	default:
+	  FFI_ASSERT(0);
+	}
+
+      slot++;
+      p_arg++;
+    }
+
+  /* Invoke the closure.  */
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
+	ret[1]);
+
+  /* Store the result using the lower 2 bytes of the flags.  */
+  switch (cif->flags)
+    {
+    case FFI_TYPE_UINT8:
+      *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
+      break;
+    case FFI_TYPE_SINT8:
+      *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
+      break;
+    case FFI_TYPE_UINT16:
+      *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
+      break;
+    case FFI_TYPE_SINT16:
+      *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+      *(stack - FIRST_ARG_SLOT) = ret[0];
+      break;
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      *(stack - FIRST_ARG_SLOT) = ret[0];
+      *(stack - FIRST_ARG_SLOT - 1) = ret[1];
+      break;
+
+    case FFI_TYPE_DOUBLE:
+      fldd(rvalue, fr4);
+      break;
+
+    case FFI_TYPE_FLOAT:
+      fldw(rvalue, fr4);
+      break;
+
+    case FFI_TYPE_STRUCT:
+      /* Don't need a return value, done by caller.  */
+      break;
+
+    case FFI_TYPE_SMALL_STRUCT2:
+    case FFI_TYPE_SMALL_STRUCT3:
+    case FFI_TYPE_SMALL_STRUCT4:
+      tmp = (void*)(stack -  FIRST_ARG_SLOT);
+      tmp += 4 - cif->rtype->size;
+      memcpy((void*)tmp, &ret[0], cif->rtype->size);
+      break;
+
+    case FFI_TYPE_SMALL_STRUCT5:
+    case FFI_TYPE_SMALL_STRUCT6:
+    case FFI_TYPE_SMALL_STRUCT7:
+    case FFI_TYPE_SMALL_STRUCT8:
+      {
+	unsigned int ret2[2];
+	int off;
+
+	/* Right justify ret[0] and ret[1] */
+	switch (cif->flags)
+	  {
+	    case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
+	    case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
+	    case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
+	    default: off = 0; break;
+	  }
+
+	memset (ret2, 0, sizeof (ret2));
+	memcpy ((char *)ret2 + off, ret, 8 - off);
+
+	*(stack - FIRST_ARG_SLOT) = ret2[0];
+	*(stack - FIRST_ARG_SLOT - 1) = ret2[1];
+      }
+      break;
+
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_VOID:
+      break;
+
+    default:
+      debug(0, "assert with cif->flags: %d\n",cif->flags);
+      FFI_ASSERT(0);
+      break;
+    }
+  return FFI_OK;
+}
+
+/* Fill in a closure to refer to the specified fun and user_data.
+   cif specifies the argument and result types for fun.
+   The cif must already be prep'ed.  */
+
+extern void ffi_closure_pa32(void);
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*,void*,void**,void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  UINT32 *tramp = (UINT32 *)(closure->tramp);
+#ifdef PA_HPUX
+  UINT32 *tmp;
+#endif
+
+  if (cif->abi != FFI_PA32)
+    return FFI_BAD_ABI;
+
+  /* Make a small trampoline that will branch to our
+     handler function. Use PC-relative addressing.  */
+
+#ifdef PA_LINUX
+  tramp[0] = 0xeaa00000; /* b,l .+8,%r21        ; %r21 <- pc+8 */
+  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21    ; mask priv bits */
+  tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1    ; load plabel */
+  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21   ; get closure addr */
+  tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22     ; address of handler */
+  tramp[5] = 0xeac0c000; /* bv%r0(%r22)         ; branch to handler */
+  tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19     ; GP of handler */
+  tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
+
+  /* Flush d/icache -- have to flush up 2 two lines because of
+     alignment.  */
+  __asm__ volatile(
+		   "fdc 0(%0)\n\t"
+		   "fdc %1(%0)\n\t"
+		   "fic 0(%%sr4, %0)\n\t"
+		   "fic %1(%%sr4, %0)\n\t"
+		   "sync\n\t"
+		   "nop\n\t"
+		   "nop\n\t"
+		   "nop\n\t"
+		   "nop\n\t"
+		   "nop\n\t"
+		   "nop\n\t"
+		   "nop\n"
+		   :
+		   : "r"((unsigned long)tramp & ~31),
+		     "r"(32 /* stride */)
+		   : "memory");
+#endif
+
+#ifdef PA_HPUX
+  tramp[0] = 0xeaa00000; /* b,l .+8,%r21        ; %r21 <- pc+8  */
+  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21    ; mask priv bits  */
+  tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1    ; load plabel  */
+  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21   ; get closure addr  */
+  tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22     ; address of handler  */
+  tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20   ; load space id  */
+  tramp[6] = 0x00141820; /* mtsp %r20,%sr0      ; into %sr0  */
+  tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22)     ; branch to handler  */
+  tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19     ; GP of handler  */
+  tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
+
+  /* Flush d/icache -- have to flush three lines because of alignment.  */
+  __asm__ volatile(
+		   "copy %1,%0\n\t"
+		   "fdc,m %2(%0)\n\t"
+		   "fdc,m %2(%0)\n\t"
+		   "fdc,m %2(%0)\n\t"
+		   "ldsid (%1),%0\n\t"
+		   "mtsp %0,%%sr0\n\t"
+		   "copy %1,%0\n\t"
+		   "fic,m %2(%%sr0,%0)\n\t"
+		   "fic,m %2(%%sr0,%0)\n\t"
+		   "fic,m %2(%%sr0,%0)\n\t"
+		   "sync\n\t"
+		   "nop\n\t"
+		   "nop\n\t"
+		   "nop\n\t"
+		   "nop\n\t"
+		   "nop\n\t"
+		   "nop\n\t"
+		   "nop\n"
+		   : "=&r" ((unsigned long)tmp)
+		   : "r" ((unsigned long)tramp & ~31),
+		     "r" (32/* stride */)
+		   : "memory");
+#endif
+
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+#endif
diff --git a/third_party/gofrontend/libffi/src/pa/ffitarget.h b/third_party/gofrontend/libffi/src/pa/ffitarget.h
new file mode 100644
index 0000000..5e364d3
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/pa/ffitarget.h
@@ -0,0 +1,83 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for hppa.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+/* ---- System specific configurations ----------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+
+#ifdef PA_LINUX
+  FFI_PA32,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_PA32
+#endif
+
+#ifdef PA_HPUX
+  FFI_PA32,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_PA32
+#endif
+
+#ifdef PA64_HPUX
+#error "PA64_HPUX FFI is not yet implemented"
+  FFI_PA64,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_PA64
+#endif
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+#ifdef PA_LINUX
+#define FFI_TRAMPOLINE_SIZE 32
+#else
+#define FFI_TRAMPOLINE_SIZE 40
+#endif
+
+#define FFI_TYPE_SMALL_STRUCT2 -1
+#define FFI_TYPE_SMALL_STRUCT3 -2
+#define FFI_TYPE_SMALL_STRUCT4 -3
+#define FFI_TYPE_SMALL_STRUCT5 -4
+#define FFI_TYPE_SMALL_STRUCT6 -5
+#define FFI_TYPE_SMALL_STRUCT7 -6
+#define FFI_TYPE_SMALL_STRUCT8 -7
+#endif
diff --git a/third_party/gofrontend/libffi/src/pa/hpux32.S b/third_party/gofrontend/libffi/src/pa/hpux32.S
new file mode 100644
index 0000000..40528ba
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/pa/hpux32.S
@@ -0,0 +1,368 @@
+/* -----------------------------------------------------------------------
+   hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc.
+	                (c) 2008 Red Hat, Inc.
+   based on src/pa/linux.S
+
+   HP-UX PA Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+	.LEVEL 1.1
+	.SPACE	$PRIVATE$
+	.IMPORT	$global$,DATA
+	.IMPORT	$$dyncall,MILLICODE
+	.SUBSPA	$DATA$
+	.align	4
+
+	/* void ffi_call_pa32(void (*)(char *, extended_cif *),
+			       extended_cif *ecif,
+			       unsigned bytes,
+			       unsigned flags,
+			       unsigned *rvalue,
+			       void (*fn)(void));
+	 */
+
+	.export	ffi_call_pa32,ENTRY,PRIV_LEV=3
+	.import	ffi_prep_args_pa32,CODE
+
+	.SPACE	$TEXT$
+	.SUBSPA $CODE$
+	.align	4
+
+L$FB1
+ffi_call_pa32
+	.proc
+	.callinfo	FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
+	.entry
+	stw	%rp, -20(%sp)
+	copy	%r3, %r1
+L$CFI11
+	copy	%sp, %r3
+L$CFI12
+
+	/* Setup the stack for calling prep_args...
+	   We want the stack to look like this:
+
+	   [ Previous stack                            ] <- %r3
+
+	   [ 64-bytes register save area               ] <- %r4
+
+	   [ Stack space for actual call, passed as    ] <- %arg0
+	   [     arg0 to ffi_prep_args_pa32           ]
+
+	   [ Stack for calling prep_args               ] <- %sp
+	 */
+
+	stwm	%r1, 64(%sp)
+	stw	%r4, 12(%r3)
+L$CFI13
+	copy	%sp, %r4
+
+	addl	%arg2, %r4, %arg0	; arg stack
+	stw	%arg3, -48(%r3)		; save flags we need it later
+
+	/* Call prep_args:
+	   %arg0(stack) -- set up above
+	   %arg1(ecif)  -- same as incoming param
+	   %arg2(bytes) -- same as incoming param */
+	bl	ffi_prep_args_pa32,%r2
+	ldo	64(%arg0), %sp
+	ldo	-64(%sp), %sp
+
+	/* now %sp should point where %arg0 was pointing.  */
+
+	/* Load the arguments that should be passed in registers
+	   The fp args are loaded by the prep_args function.  */
+	ldw	-36(%sp), %arg0
+	ldw	-40(%sp), %arg1
+	ldw	-44(%sp), %arg2
+	ldw	-48(%sp), %arg3
+
+	/* in case the function is going to return a structure
+	   we need to give it a place to put the result.  */
+	ldw	-52(%r3), %ret0		; %ret0 <- rvalue
+	ldw	-56(%r3), %r22		; %r22 <- function to call
+	bl	$$dyncall, %r31		; Call the user function
+	copy	%r31, %rp
+
+	/* Prepare to store the result; we need to recover flags and rvalue.  */
+	ldw	-48(%r3), %r21		; r21 <- flags
+	ldw	-52(%r3), %r20		; r20 <- rvalue
+
+	/* Store the result according to the return type.  The most
+	   likely types should come first.  */
+
+L$checkint
+	comib,<>,n FFI_TYPE_INT, %r21, L$checkint8
+	b	L$done
+	stw	%ret0, 0(%r20)
+
+L$checkint8
+	comib,<>,n FFI_TYPE_UINT8, %r21, L$checkint16
+	b	L$done
+	stb	%ret0, 0(%r20)
+
+L$checkint16
+	comib,<>,n FFI_TYPE_UINT16, %r21, L$checkdbl
+	b	L$done
+	sth	%ret0, 0(%r20)
+
+L$checkdbl
+	comib,<>,n FFI_TYPE_DOUBLE, %r21, L$checkfloat
+	b	L$done
+	fstd	%fr4,0(%r20)
+
+L$checkfloat
+	comib,<>,n FFI_TYPE_FLOAT, %r21, L$checkll
+	b	L$done
+	fstw	%fr4L,0(%r20)
+
+L$checkll
+	comib,<>,n FFI_TYPE_UINT64, %r21, L$checksmst2
+	stw	%ret0, 0(%r20)
+	b	L$done
+	stw	%ret1, 4(%r20)
+
+L$checksmst2
+	comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, L$checksmst3
+	/* 2-byte structs are returned in ret0 as ????xxyy.  */
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	L$done
+	stb	%ret0, 0(%r20)
+
+L$checksmst3
+	comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, L$checksmst4
+	/* 3-byte structs are returned in ret0 as ??xxyyzz.  */
+	extru	%ret0, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	L$done
+	stb	%ret0, 0(%r20)
+
+L$checksmst4
+	comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, L$checksmst5
+	/* 4-byte structs are returned in ret0 as wwxxyyzz.  */
+	extru	%ret0, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	L$done
+	stb	%ret0, 0(%r20)
+
+L$checksmst5
+	comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, L$checksmst6
+	/* 5 byte values are returned right justified:
+	      ret0     ret1
+	   5: ??????aa bbccddee */
+	stbs,ma	%ret0, 1(%r20)
+	extru	%ret1, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	L$done
+	stb	%ret1, 0(%r20)
+
+L$checksmst6
+	comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, L$checksmst7
+	/* 6 byte values are returned right justified:
+	      ret0     ret1
+	   6: ????aabb ccddeeff */
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	stbs,ma	%ret0, 1(%r20)
+	extru	%ret1, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	L$done
+	stb	%ret1, 0(%r20)
+
+L$checksmst7
+	comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, L$checksmst8
+	/* 7 byte values are returned right justified:
+	      ret0     ret1
+	   7: ??aabbcc ddeeffgg */
+	extru	%ret0, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	stbs,ma	%ret0, 1(%r20)
+	extru	%ret1, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	L$done
+	stb	%ret1, 0(%r20)
+
+L$checksmst8
+	comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, L$done
+	/* 8 byte values are returned right justified:
+	      ret0     ret1
+	   8: aabbccdd eeffgghh */
+	extru	%ret0, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	stbs,ma	%ret0, 1(%r20)
+	extru	%ret1, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	stb	%ret1, 0(%r20)
+
+L$done
+	/* all done, return */
+	copy	%r4, %sp	; pop arg stack
+	ldw	12(%r3), %r4
+	ldwm	-64(%sp), %r3	; .. and pop stack
+	ldw	-20(%sp), %rp
+	bv	%r0(%rp)
+	nop
+	.exit
+	.procend
+L$FE1
+
+	/* void ffi_closure_pa32(void);
+	   Called with closure argument in %r21 */
+
+	.SPACE $TEXT$
+	.SUBSPA $CODE$
+	.export ffi_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR
+	.import ffi_closure_inner_pa32,CODE
+	.align 4
+L$FB2
+ffi_closure_pa32
+	.proc
+	.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
+	.entry
+
+	stw	%rp, -20(%sp)
+	copy	%r3, %r1
+L$CFI21
+	copy	%sp, %r3
+L$CFI22
+	stwm	%r1, 64(%sp)
+
+	/* Put arguments onto the stack and call ffi_closure_inner.  */
+	stw	%arg0, -36(%r3)
+	stw	%arg1, -40(%r3)
+	stw	%arg2, -44(%r3)
+	stw	%arg3, -48(%r3)
+
+	copy	%r21, %arg0
+	bl	ffi_closure_inner_pa32, %r2
+	copy    %r3, %arg1
+	ldwm	-64(%sp), %r3
+	ldw	-20(%sp), %rp
+	ldw	-36(%sp), %ret0
+	bv	%r0(%rp)
+	ldw	-40(%sp), %ret1
+	.exit
+	.procend
+L$FE2:
+
+	.SPACE $PRIVATE$
+	.SUBSPA $DATA$
+
+	.align 4
+	.EXPORT _GLOBAL__F_ffi_call_pa32,DATA
+_GLOBAL__F_ffi_call_pa32
+L$frame1:
+	.word   L$ECIE1-L$SCIE1 ;# Length of Common Information Entry
+L$SCIE1:
+	.word   0x0     ;# CIE Identifier Tag
+	.byte   0x1     ;# CIE Version
+	.ascii "\0"     ;# CIE Augmentation
+	.uleb128 0x1    ;# CIE Code Alignment Factor
+	.sleb128 4      ;# CIE Data Alignment Factor
+	.byte   0x2     ;# CIE RA Column
+	.byte   0xc     ;# DW_CFA_def_cfa
+	.uleb128 0x1e
+	.uleb128 0x0
+	.align 4
+L$ECIE1:
+L$SFDE1:
+	.word   L$EFDE1-L$ASFDE1        ;# FDE Length
+L$ASFDE1:
+	.word   L$ASFDE1-L$frame1       ;# FDE CIE offset
+	.word   L$FB1   ;# FDE initial location
+	.word   L$FE1-L$FB1     ;# FDE address range
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   L$CFI11-L$FB1
+	.byte	0x83	;# DW_CFA_offset, column 0x3
+	.uleb128 0x0
+	.byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
+	.uleb128 0x2
+	.sleb128 -5
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   L$CFI12-L$CFI11
+	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
+	.uleb128 0x3
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   L$CFI13-L$CFI12
+	.byte	0x84	;# DW_CFA_offset, column 0x4
+	.uleb128 0x3
+
+	.align 4
+L$EFDE1:
+
+L$SFDE2:
+	.word   L$EFDE2-L$ASFDE2        ;# FDE Length
+L$ASFDE2:
+	.word   L$ASFDE2-L$frame1       ;# FDE CIE offset
+	.word   L$FB2   ;# FDE initial location
+	.word   L$FE2-L$FB2     ;# FDE address range
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   L$CFI21-L$FB2
+	.byte   0x83    ;# DW_CFA_offset, column 0x3
+	.uleb128 0x0
+	.byte   0x11    ;# DW_CFA_offset_extended_sf
+	.uleb128 0x2
+	.sleb128 -5
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   L$CFI22-L$CFI21
+	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
+	.uleb128 0x3
+
+	.align 4
+L$EFDE2:
diff --git a/third_party/gofrontend/libffi/src/pa/linux.S b/third_party/gofrontend/libffi/src/pa/linux.S
new file mode 100644
index 0000000..f11ae76
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/pa/linux.S
@@ -0,0 +1,357 @@
+/* -----------------------------------------------------------------------
+   linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
+	     (c) 2008 Red Hat, Inc.
+
+   HPPA Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+	.text
+	.level 1.1
+	.align 4
+
+	/* void ffi_call_pa32(void (*)(char *, extended_cif *),
+			       extended_cif *ecif,
+			       unsigned bytes,
+			       unsigned flags,
+			       unsigned *rvalue,
+			       void (*fn)(void));
+	 */
+
+	.export ffi_call_pa32,code
+	.import ffi_prep_args_pa32,code
+
+	.type ffi_call_pa32, @function
+.LFB1:
+ffi_call_pa32:
+	.proc
+	.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
+	.entry
+	stw %rp, -20(%sp)
+	copy %r3, %r1
+.LCFI11:
+
+	copy %sp, %r3
+.LCFI12:
+
+	/* Setup the stack for calling prep_args...
+	   We want the stack to look like this:
+
+	   [ Previous stack                            ] <- %r3
+
+	   [ 64-bytes register save area               ] <- %r4
+
+	   [ Stack space for actual call, passed as    ] <- %arg0
+	   [     arg0 to ffi_prep_args_pa32           ]
+
+	   [ Stack for calling prep_args               ] <- %sp
+	 */
+
+	stwm %r1, 64(%sp)
+	stw %r4, 12(%r3)
+.LCFI13:
+	copy %sp, %r4
+
+	addl %arg2, %r4, %arg0      /* arg stack */
+	stw %arg3, -48(%r3)         /* save flags; we need it later */
+
+	/* Call prep_args:
+	   %arg0(stack) -- set up above
+	   %arg1(ecif) -- same as incoming param
+	   %arg2(bytes) -- same as incoming param */
+	bl ffi_prep_args_pa32,%r2
+	ldo 64(%arg0), %sp
+	ldo -64(%sp), %sp
+
+	/* now %sp should point where %arg0 was pointing.  */
+
+	/* Load the arguments that should be passed in registers
+	   The fp args were loaded by the prep_args function.  */
+	ldw -36(%sp), %arg0
+	ldw -40(%sp), %arg1
+	ldw -44(%sp), %arg2
+	ldw -48(%sp), %arg3
+
+	/* in case the function is going to return a structure
+	   we need to give it a place to put the result.  */
+	ldw -52(%r3), %ret0                     /* %ret0 <- rvalue */
+	ldw -56(%r3), %r22                      /* %r22 <- function to call */
+	bl $$dyncall, %r31                      /* Call the user function */
+	copy %r31, %rp
+
+	/* Prepare to store the result; we need to recover flags and rvalue.  */
+	ldw -48(%r3), %r21                      /* r21 <- flags */
+	ldw -52(%r3), %r20                      /* r20 <- rvalue */
+
+	/* Store the result according to the return type.  */
+
+.Lcheckint:
+	comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
+	b	.Ldone
+	stw	%ret0, 0(%r20)
+
+.Lcheckint8:
+	comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
+	b	.Ldone
+	stb	%ret0, 0(%r20)
+
+.Lcheckint16:
+	comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
+	b	.Ldone
+	sth	%ret0, 0(%r20)
+
+.Lcheckdbl:
+	comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
+	b	.Ldone
+	fstd	%fr4,0(%r20)
+
+.Lcheckfloat:
+	comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
+	b	.Ldone
+	fstw	%fr4L,0(%r20)
+
+.Lcheckll:
+	comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
+	stw	%ret0, 0(%r20)
+	b	.Ldone
+	stw	%ret1, 4(%r20)
+
+.Lchecksmst2:
+	comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
+	/* 2-byte structs are returned in ret0 as ????xxyy.  */
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	.Ldone
+	stb	%ret0, 0(%r20)
+
+.Lchecksmst3:
+	comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
+	/* 3-byte structs are returned in ret0 as ??xxyyzz.  */
+	extru	%ret0, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	.Ldone
+	stb	%ret0, 0(%r20)
+
+.Lchecksmst4:
+	comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
+	/* 4-byte structs are returned in ret0 as wwxxyyzz.  */
+	extru	%ret0, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	.Ldone
+	stb	%ret0, 0(%r20)
+
+.Lchecksmst5:
+	comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
+	/* 5 byte values are returned right justified:
+	      ret0     ret1
+	   5: ??????aa bbccddee */
+	stbs,ma	%ret0, 1(%r20)
+	extru	%ret1, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	.Ldone
+	stb	%ret1, 0(%r20)
+
+.Lchecksmst6:
+	comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
+	/* 6 byte values are returned right justified:
+	      ret0     ret1
+	   6: ????aabb ccddeeff */
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	stbs,ma	%ret0, 1(%r20)
+	extru	%ret1, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	.Ldone
+	stb	%ret1, 0(%r20)
+
+.Lchecksmst7:
+	comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
+	/* 7 byte values are returned right justified:
+	      ret0     ret1
+	   7: ??aabbcc ddeeffgg */
+	extru	%ret0, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	stbs,ma	%ret0, 1(%r20)
+	extru	%ret1, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	b	.Ldone
+	stb	%ret1, 0(%r20)
+
+.Lchecksmst8:
+	comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
+	/* 8 byte values are returned right justified:
+	      ret0     ret1
+	   8: aabbccdd eeffgghh */
+	extru	%ret0, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret0, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	stbs,ma	%ret0, 1(%r20)
+	extru	%ret1, 7, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 15, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	extru	%ret1, 23, 8, %r22
+	stbs,ma	%r22, 1(%r20)
+	stb	%ret1, 0(%r20)
+
+.Ldone:
+	/* all done, return */
+	copy %r4, %sp                           /* pop arg stack */
+	ldw 12(%r3), %r4
+	ldwm -64(%sp), %r3                      /* .. and pop stack */
+	ldw -20(%sp), %rp
+	bv %r0(%rp)
+	nop
+	.exit
+	.procend
+.LFE1:
+
+	/* void ffi_closure_pa32(void);
+	   Called with closure argument in %r21 */
+	.export ffi_closure_pa32,code
+	.import ffi_closure_inner_pa32,code
+
+	.type ffi_closure_pa32, @function
+.LFB2:
+ffi_closure_pa32:
+	.proc
+	.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
+	.entry
+
+	stw %rp, -20(%sp)
+.LCFI20:
+	copy %r3, %r1
+.LCFI21:
+	copy %sp, %r3
+.LCFI22:
+	stwm %r1, 64(%sp)
+
+	/* Put arguments onto the stack and call ffi_closure_inner.  */
+	stw %arg0, -36(%r3)
+	stw %arg1, -40(%r3)
+	stw %arg2, -44(%r3)
+	stw %arg3, -48(%r3)
+
+	copy %r21, %arg0
+	bl ffi_closure_inner_pa32, %r2
+	copy %r3, %arg1
+
+	ldwm -64(%sp), %r3
+	ldw -20(%sp), %rp
+	ldw -36(%sp), %ret0
+	bv %r0(%r2)
+	ldw -40(%sp), %ret1
+
+	.exit
+	.procend
+.LFE2:
+
+	.section        ".eh_frame",EH_FRAME_FLAGS,@progbits
+.Lframe1:
+	.word   .LECIE1-.LSCIE1 ;# Length of Common Information Entry
+.LSCIE1:
+	.word   0x0     ;# CIE Identifier Tag
+	.byte   0x1     ;# CIE Version
+	.ascii "\0"     ;# CIE Augmentation
+	.uleb128 0x1    ;# CIE Code Alignment Factor
+	.sleb128 4      ;# CIE Data Alignment Factor
+	.byte   0x2     ;# CIE RA Column
+	.byte   0xc     ;# DW_CFA_def_cfa
+	.uleb128 0x1e
+	.uleb128 0x0
+	.align 4
+.LECIE1:
+.LSFDE1:
+	.word   .LEFDE1-.LASFDE1        ;# FDE Length
+.LASFDE1:
+	.word   .LASFDE1-.Lframe1       ;# FDE CIE offset
+	.word   .LFB1   ;# FDE initial location
+	.word   .LFE1-.LFB1     ;# FDE address range
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   .LCFI11-.LFB1
+	.byte	0x83	;# DW_CFA_offset, column 0x3
+	.uleb128 0x0
+	.byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
+	.uleb128 0x2
+	.sleb128 -5
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   .LCFI12-.LCFI11
+	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
+	.uleb128 0x3
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   .LCFI13-.LCFI12
+	.byte	0x84	;# DW_CFA_offset, column 0x4
+	.uleb128 0x3
+
+	.align 4
+.LEFDE1:
+
+.LSFDE2:
+	.word   .LEFDE2-.LASFDE2        ;# FDE Length
+.LASFDE2:
+	.word   .LASFDE2-.Lframe1       ;# FDE CIE offset
+	.word   .LFB2   ;# FDE initial location
+	.word   .LFE2-.LFB2     ;# FDE address range
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   .LCFI21-.LFB2
+	.byte   0x83    ;# DW_CFA_offset, column 0x3
+	.uleb128 0x0
+	.byte   0x11    ;# DW_CFA_offset_extended_sf
+	.uleb128 0x2
+	.sleb128 -5
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   .LCFI22-.LCFI21
+	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
+	.uleb128 0x3
+
+	.align 4
+.LEFDE2:
diff --git a/third_party/gofrontend/libffi/src/powerpc/aix.S b/third_party/gofrontend/libffi/src/powerpc/aix.S
new file mode 100644
index 0000000..213f2db
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/aix.S
@@ -0,0 +1,328 @@
+/* -----------------------------------------------------------------------
+   aix.S - Copyright (c) 2002, 2009 Free Software Foundation, Inc.
+   based on darwin.S by John Hornkvist
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+	.set r0,0
+	.set r1,1
+	.set r2,2
+	.set r3,3
+	.set r4,4
+	.set r5,5
+	.set r6,6
+	.set r7,7
+	.set r8,8
+	.set r9,9
+	.set r10,10
+	.set r11,11
+	.set r12,12
+	.set r13,13
+	.set r14,14
+	.set r15,15
+	.set r16,16
+	.set r17,17
+	.set r18,18
+	.set r19,19
+	.set r20,20
+	.set r21,21
+	.set r22,22
+	.set r23,23
+	.set r24,24
+	.set r25,25
+	.set r26,26
+	.set r27,27
+	.set r28,28
+	.set r29,29
+	.set r30,30
+	.set r31,31
+	.set f0,0
+	.set f1,1
+	.set f2,2
+	.set f3,3
+	.set f4,4
+	.set f5,5
+	.set f6,6
+	.set f7,7
+	.set f8,8
+	.set f9,9
+	.set f10,10
+	.set f11,11
+	.set f12,12
+	.set f13,13
+	.set f14,14
+	.set f15,15
+	.set f16,16
+	.set f17,17
+	.set f18,18
+	.set f19,19
+	.set f20,20
+	.set f21,21
+
+	.extern .ffi_prep_args
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#define JUMPTARGET(name) name
+#define L(x) x
+	.file "aix.S"
+	.toc
+
+	/* void ffi_call_AIX(extended_cif *ecif, unsigned long bytes,
+	 *		     unsigned int flags, unsigned int *rvalue,
+	 *		     void (*fn)(),
+	 *		     void (*prep_args)(extended_cif*, unsigned *const));
+	 * r3=ecif, r4=bytes, r5=flags, r6=rvalue, r7=fn, r8=prep_args
+	 */
+
+.csect .text[PR]
+	.align 2
+	.globl ffi_call_AIX
+	.globl .ffi_call_AIX
+.csect ffi_call_AIX[DS]
+ffi_call_AIX:
+#ifdef __64BIT__
+	.llong .ffi_call_AIX, TOC[tc0], 0
+	.csect .text[PR]
+.ffi_call_AIX:
+	/* Save registers we use.  */
+	mflr	r0
+
+	std	r28,-32(r1)
+	std	r29,-24(r1)
+	std	r30,-16(r1)
+	std	r31, -8(r1)
+
+	std	r0, 16(r1)
+	mr	r28, r1		/* our AP.  */
+	stdux	r1, r1, r4
+
+	/* Save arguments over call...  */
+	mr	r31, r5	/* flags, */
+	mr	r30, r6	/* rvalue, */
+	mr	r29, r7	/* function address.  */
+	std	r2, 40(r1)
+
+	/* Call ffi_prep_args.  */
+	mr	r4, r1
+	bl	.ffi_prep_args
+	nop
+
+	/* Now do the call.  */
+	ld	r0, 0(r29)
+	ld	r2, 8(r29)
+	ld	r11, 16(r29)
+	/* Set up cr1 with bits 4-7 of the flags.  */
+	mtcrf	0x40, r31
+	mtctr	r0
+	/* Load all those argument registers.  */
+	// We have set up a nice stack frame, just load it into registers.
+	ld	r3, 40+(1*8)(r1)
+	ld	r4, 40+(2*8)(r1)
+	ld	r5, 40+(3*8)(r1)
+	ld	r6, 40+(4*8)(r1)
+	nop
+	ld	r7, 40+(5*8)(r1)
+	ld	r8, 40+(6*8)(r1)
+	ld	r9, 40+(7*8)(r1)
+	ld	r10,40+(8*8)(r1)
+
+L1:
+	/* Load all the FP registers.  */
+	bf	6,L2 // 2f + 0x18
+	lfd	f1,-32-(13*8)(r28)
+	lfd	f2,-32-(12*8)(r28)
+	lfd	f3,-32-(11*8)(r28)
+	lfd	f4,-32-(10*8)(r28)
+	nop
+	lfd	f5,-32-(9*8)(r28)
+	lfd	f6,-32-(8*8)(r28)
+	lfd	f7,-32-(7*8)(r28)
+	lfd	f8,-32-(6*8)(r28)
+	nop
+	lfd	f9,-32-(5*8)(r28)
+	lfd	f10,-32-(4*8)(r28)
+	lfd	f11,-32-(3*8)(r28)
+	lfd	f12,-32-(2*8)(r28)
+	nop
+	lfd	f13,-32-(1*8)(r28)
+
+L2:
+	/* Make the call.  */
+	bctrl
+	ld	r2, 40(r1)
+
+	/* Now, deal with the return value.  */
+	mtcrf	0x01, r31
+
+	bt	30, L(done_return_value)
+	bt	29, L(fp_return_value)
+	std	r3, 0(r30)
+
+	/* Fall through...  */
+
+L(done_return_value):
+	/* Restore the registers we used and return.  */
+	mr	r1, r28
+	ld	r0, 16(r28)
+	ld	r28, -32(r1)
+	mtlr	r0
+	ld	r29, -24(r1)
+	ld	r30, -16(r1)
+	ld	r31, -8(r1)
+	blr
+
+L(fp_return_value):
+	bf	28, L(float_return_value)
+	stfd	f1, 0(r30)
+	bf	31, L(done_return_value)
+	stfd	f2, 8(r30)
+	b	L(done_return_value)
+L(float_return_value):
+	stfs	f1, 0(r30)
+	b	L(done_return_value)
+
+#else /* ! __64BIT__ */
+	
+	.long .ffi_call_AIX, TOC[tc0], 0
+	.csect .text[PR]
+.ffi_call_AIX:
+	/* Save registers we use.  */
+	mflr	r0
+
+	stw	r28,-16(r1)
+	stw	r29,-12(r1)
+	stw	r30, -8(r1)
+	stw	r31, -4(r1)
+
+	stw	r0, 8(r1)
+	mr	r28, r1		/* out AP.  */
+	stwux	r1, r1, r4
+
+	/* Save arguments over call...  */
+	mr	r31, r5	/* flags, */
+	mr	r30, r6	/* rvalue, */
+	mr	r29, r7	/* function address, */
+	stw	r2, 20(r1)
+
+	/* Call ffi_prep_args.  */
+	mr	r4, r1
+	bl	.ffi_prep_args
+	nop
+
+	/* Now do the call.  */
+	lwz	r0, 0(r29)
+	lwz	r2, 4(r29)
+	lwz	r11, 8(r29)
+	/* Set up cr1 with bits 4-7 of the flags.  */
+	mtcrf	0x40, r31
+	mtctr	r0
+	/* Load all those argument registers.  */
+	// We have set up a nice stack frame, just load it into registers.
+	lwz	r3, 20+(1*4)(r1)
+	lwz	r4, 20+(2*4)(r1)
+	lwz	r5, 20+(3*4)(r1)
+	lwz	r6, 20+(4*4)(r1)
+	nop
+	lwz	r7, 20+(5*4)(r1)
+	lwz	r8, 20+(6*4)(r1)
+	lwz	r9, 20+(7*4)(r1)
+	lwz	r10,20+(8*4)(r1)
+
+L1:
+	/* Load all the FP registers.  */
+	bf	6,L2 // 2f + 0x18
+	lfd	f1,-16-(13*8)(r28)
+	lfd	f2,-16-(12*8)(r28)
+	lfd	f3,-16-(11*8)(r28)
+	lfd	f4,-16-(10*8)(r28)
+	nop
+	lfd	f5,-16-(9*8)(r28)
+	lfd	f6,-16-(8*8)(r28)
+	lfd	f7,-16-(7*8)(r28)
+	lfd	f8,-16-(6*8)(r28)
+	nop
+	lfd	f9,-16-(5*8)(r28)
+	lfd	f10,-16-(4*8)(r28)
+	lfd	f11,-16-(3*8)(r28)
+	lfd	f12,-16-(2*8)(r28)
+	nop
+	lfd	f13,-16-(1*8)(r28)
+
+L2:
+	/* Make the call.  */
+	bctrl
+	lwz	r2, 20(r1)
+
+	/* Now, deal with the return value.  */
+	mtcrf	0x01, r31
+
+	bt	30, L(done_return_value)
+	bt	29, L(fp_return_value)
+	stw	r3, 0(r30)
+	bf	28, L(done_return_value)
+	stw	r4, 4(r30)
+
+	/* Fall through...  */
+
+L(done_return_value):
+	/* Restore the registers we used and return.  */
+	mr	r1, r28
+	lwz	r0, 8(r28)
+	lwz	r28,-16(r1)
+	mtlr	r0
+	lwz	r29,-12(r1)
+	lwz	r30, -8(r1)
+	lwz	r31, -4(r1)
+	blr
+
+L(fp_return_value):
+	bf	28, L(float_return_value)
+	stfd	f1, 0(r30)
+	b	L(done_return_value)
+L(float_return_value):
+	stfs	f1, 0(r30)
+	b	L(done_return_value)
+#endif
+	.long 0
+	.byte 0,0,0,1,128,4,0,0
+//END(ffi_call_AIX)
+
+.csect .text[PR]
+	.align 2
+	.globl ffi_call_DARWIN
+	.globl .ffi_call_DARWIN
+.csect ffi_call_DARWIN[DS]
+ffi_call_DARWIN:
+#ifdef __64BIT__
+	.llong .ffi_call_DARWIN, TOC[tc0], 0
+#else
+	.long .ffi_call_DARWIN, TOC[tc0], 0
+#endif
+	.csect .text[PR]
+.ffi_call_DARWIN:
+	blr
+	.long 0
+	.byte 0,0,0,0,0,0,0,0
+//END(ffi_call_DARWIN)
diff --git a/third_party/gofrontend/libffi/src/powerpc/aix_closure.S b/third_party/gofrontend/libffi/src/powerpc/aix_closure.S
new file mode 100644
index 0000000..aabd3c3
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/aix_closure.S
@@ -0,0 +1,447 @@
+/* -----------------------------------------------------------------------
+   aix_closure.S - Copyright (c) 2002, 2003, 2009 Free Software Foundation, Inc.
+   based on darwin_closure.S
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+	.set r0,0
+	.set r1,1
+	.set r2,2
+	.set r3,3
+	.set r4,4
+	.set r5,5
+	.set r6,6
+	.set r7,7
+	.set r8,8
+	.set r9,9
+	.set r10,10
+	.set r11,11
+	.set r12,12
+	.set r13,13
+	.set r14,14
+	.set r15,15
+	.set r16,16
+	.set r17,17
+	.set r18,18
+	.set r19,19
+	.set r20,20
+	.set r21,21
+	.set r22,22
+	.set r23,23
+	.set r24,24
+	.set r25,25
+	.set r26,26
+	.set r27,27
+	.set r28,28
+	.set r29,29
+	.set r30,30
+	.set r31,31
+	.set f0,0
+	.set f1,1
+	.set f2,2
+	.set f3,3
+	.set f4,4
+	.set f5,5
+	.set f6,6
+	.set f7,7
+	.set f8,8
+	.set f9,9
+	.set f10,10
+	.set f11,11
+	.set f12,12
+	.set f13,13
+	.set f14,14
+	.set f15,15
+	.set f16,16
+	.set f17,17
+	.set f18,18
+	.set f19,19
+	.set f20,20
+	.set f21,21
+
+	.extern .ffi_closure_helper_DARWIN
+
+#define LIBFFI_ASM
+#define JUMPTARGET(name) name
+#define L(x) x
+	.file "aix_closure.S"
+	.toc
+LC..60:
+	.tc L..60[TC],L..60
+	.csect .text[PR]
+	.align 2
+
+.csect .text[PR]
+	.align 2
+	.globl ffi_closure_ASM
+	.globl .ffi_closure_ASM
+.csect ffi_closure_ASM[DS]
+ffi_closure_ASM:
+#ifdef __64BIT__
+	.llong .ffi_closure_ASM, TOC[tc0], 0
+	.csect .text[PR]
+.ffi_closure_ASM:
+/* we want to build up an area for the parameters passed */
+/* in registers (both floating point and integer) */
+
+	/* we store gpr 3 to gpr 10 (aligned to 4)
+	in the parents outgoing area  */
+	std   r3, 48+(0*8)(r1)
+	std   r4, 48+(1*8)(r1)
+	std   r5, 48+(2*8)(r1)
+	std   r6, 48+(3*8)(r1)
+	mflr  r0
+
+	std   r7, 48+(4*8)(r1)
+	std   r8, 48+(5*8)(r1)
+	std   r9, 48+(6*8)(r1)
+	std   r10, 48+(7*8)(r1)
+	std   r0, 16(r1)	/* save the return address */
+
+
+	/* 48  Bytes (Linkage Area) */
+	/* 64  Bytes (params) */
+	/* 16  Bytes (result) */
+	/* 104 Bytes (13*8 from FPR) */
+	/* 8   Bytes (alignment) */
+	/* 240 Bytes */
+
+	stdu  r1, -240(r1)	/* skip over caller save area
+				   keep stack aligned to 16  */
+
+	/* next save fpr 1 to fpr 13 (aligned to 8) */
+	stfd  f1, 128+(0*8)(r1)
+	stfd  f2, 128+(1*8)(r1)
+	stfd  f3, 128+(2*8)(r1)
+	stfd  f4, 128+(3*8)(r1)
+	stfd  f5, 128+(4*8)(r1)
+	stfd  f6, 128+(5*8)(r1)
+	stfd  f7, 128+(6*8)(r1)
+	stfd  f8, 128+(7*8)(r1)
+	stfd  f9, 128+(8*8)(r1)
+	stfd  f10, 128+(9*8)(r1)
+	stfd  f11, 128+(10*8)(r1)
+	stfd  f12, 128+(11*8)(r1)
+	stfd  f13, 128+(12*8)(r1)
+
+	/* set up registers for the routine that actually does the work */
+	/* get the context pointer from the trampoline */
+	mr r3, r11
+
+	/* now load up the pointer to the result storage */
+	addi r4, r1, 112
+
+	/* now load up the pointer to the saved gpr registers */
+	addi r5, r1, 288
+
+	/* now load up the pointer to the saved fpr registers */
+	addi r6, r1, 128
+
+	/* make the call */
+	bl .ffi_closure_helper_DARWIN
+	nop
+
+	/* now r3 contains the return type */
+	/* so use it to look up in a table */
+	/* so we know how to deal with each type */
+
+	/* look up the proper starting point in table  */
+	/* by using return type as offset */
+	lhz	r3, 10(r3)	/* load type from return type */
+	ld	r4, LC..60(2)	/* get address of jump table */
+	sldi	r3, r3, 4	/* now multiply return type by 16 */
+	ld	r0, 240+16(r1)	/* load return address */
+	add	r3, r3, r4	/* add contents of table to table address */
+	mtctr	r3
+	bctr			/* jump to it */
+
+/* Each fragment must be exactly 16 bytes long (4 instructions).
+   Align to 16 byte boundary for cache and dispatch efficiency.  */
+	.align 4
+
+L..60:
+/* case FFI_TYPE_VOID */
+	mtlr r0
+	addi r1, r1, 240
+	blr
+	nop
+
+/* case FFI_TYPE_INT */
+	lwa r3, 112+4(r1)
+	mtlr r0
+	addi r1, r1, 240
+	blr
+
+/* case FFI_TYPE_FLOAT */
+	lfs f1, 112+0(r1)
+	mtlr r0
+	addi r1, r1, 240
+	blr
+
+/* case FFI_TYPE_DOUBLE */
+	lfd f1, 112+0(r1)
+	mtlr r0
+	addi r1, r1, 240
+	blr
+
+/* case FFI_TYPE_LONGDOUBLE */
+	lfd f1, 112+0(r1)
+	mtlr r0
+	lfd f2, 112+8(r1)
+	b L..finish
+
+/* case FFI_TYPE_UINT8 */
+	lbz r3, 112+7(r1)
+	mtlr r0
+	addi r1, r1, 240
+	blr
+
+/* case FFI_TYPE_SINT8 */
+	lbz r3, 112+7(r1)
+	mtlr r0
+	extsb r3, r3
+	b L..finish
+
+/* case FFI_TYPE_UINT16 */
+	lhz r3, 112+6(r1)
+	mtlr r0
+L..finish:
+	addi r1, r1, 240
+	blr
+
+/* case FFI_TYPE_SINT16 */
+	lha r3, 112+6(r1)
+	mtlr r0
+	addi r1, r1, 240
+	blr
+
+/* case FFI_TYPE_UINT32 */
+	lwz r3, 112+4(r1)
+	mtlr r0
+	addi r1, r1, 240
+	blr
+
+/* case FFI_TYPE_SINT32 */
+	lwa r3, 112+4(r1)
+	mtlr r0
+	addi r1, r1, 240
+	blr
+
+/* case FFI_TYPE_UINT64 */
+	ld r3, 112+0(r1)
+	mtlr r0
+	addi r1, r1, 240
+	blr
+
+/* case FFI_TYPE_SINT64 */
+	ld r3, 112+0(r1)
+	mtlr r0
+	addi r1, r1, 240
+	blr
+
+/* case FFI_TYPE_STRUCT */
+	mtlr r0
+	addi r1, r1, 240
+	blr
+	nop
+
+/* case FFI_TYPE_POINTER */
+	ld r3, 112+0(r1)
+	mtlr r0
+	addi r1, r1, 240
+	blr
+
+#else /* ! __64BIT__ */
+	
+	.long .ffi_closure_ASM, TOC[tc0], 0
+	.csect .text[PR]
+.ffi_closure_ASM:
+/* we want to build up an area for the parameters passed */
+/* in registers (both floating point and integer) */
+
+	/* we store gpr 3 to gpr 10 (aligned to 4)
+	in the parents outgoing area  */
+	stw   r3, 24+(0*4)(r1)
+	stw   r4, 24+(1*4)(r1)
+	stw   r5, 24+(2*4)(r1)
+	stw   r6, 24+(3*4)(r1)
+	mflr  r0
+
+	stw   r7, 24+(4*4)(r1)
+	stw   r8, 24+(5*4)(r1)
+	stw   r9, 24+(6*4)(r1)
+	stw   r10, 24+(7*4)(r1)
+	stw   r0, 8(r1)
+
+	/* 24 Bytes (Linkage Area) */
+	/* 32 Bytes (params) */
+	/* 16  Bytes (result) */
+	/* 104 Bytes (13*8 from FPR) */
+	/* 176 Bytes */
+
+	stwu  r1, -176(r1)	/* skip over caller save area
+				   keep stack aligned to 16  */
+
+	/* next save fpr 1 to fpr 13 (aligned to 8) */
+	stfd  f1, 72+(0*8)(r1)
+	stfd  f2, 72+(1*8)(r1)
+	stfd  f3, 72+(2*8)(r1)
+	stfd  f4, 72+(3*8)(r1)
+	stfd  f5, 72+(4*8)(r1)
+	stfd  f6, 72+(5*8)(r1)
+	stfd  f7, 72+(6*8)(r1)
+	stfd  f8, 72+(7*8)(r1)
+	stfd  f9, 72+(8*8)(r1)
+	stfd  f10, 72+(9*8)(r1)
+	stfd  f11, 72+(10*8)(r1)
+	stfd  f12, 72+(11*8)(r1)
+	stfd  f13, 72+(12*8)(r1)
+
+	/* set up registers for the routine that actually does the work */
+	/* get the context pointer from the trampoline */
+	mr r3, r11
+
+	/* now load up the pointer to the result storage */
+	addi r4, r1, 56
+
+	/* now load up the pointer to the saved gpr registers */
+	addi r5, r1, 200
+
+	/* now load up the pointer to the saved fpr registers */
+	addi r6, r1, 72
+
+	/* make the call */
+	bl .ffi_closure_helper_DARWIN
+	nop
+
+	/* now r3 contains the return type */
+	/* so use it to look up in a table */
+	/* so we know how to deal with each type */
+
+	/* look up the proper starting point in table  */
+	/* by using return type as offset */
+	lhz	r3, 6(r3)	/* load type from return type */
+	lwz	r4, LC..60(2)	/* get address of jump table */
+	slwi	r3, r3, 4	/* now multiply return type by 16 */
+	lwz	r0, 176+8(r1)	/* load return address */
+	add	r3, r3, r4	/* add contents of table to table address */
+	mtctr	r3
+	bctr			/* jump to it */
+
+/* Each fragment must be exactly 16 bytes long (4 instructions).
+   Align to 16 byte boundary for cache and dispatch efficiency.  */
+	.align 4
+
+L..60:
+/* case FFI_TYPE_VOID */
+	mtlr r0
+	addi r1, r1, 176
+	blr
+	nop
+
+/* case FFI_TYPE_INT */
+	lwz r3, 56+0(r1)
+	mtlr r0
+	addi r1, r1, 176
+	blr
+
+/* case FFI_TYPE_FLOAT */
+	lfs f1, 56+0(r1)
+	mtlr r0
+	addi r1, r1, 176
+	blr
+
+/* case FFI_TYPE_DOUBLE */
+	lfd f1, 56+0(r1)
+	mtlr r0
+	addi r1, r1, 176
+	blr
+
+/* case FFI_TYPE_LONGDOUBLE */
+	lfd f1, 56+0(r1)
+	mtlr r0
+	lfd f2, 56+8(r1)
+	b L..finish
+
+/* case FFI_TYPE_UINT8 */
+	lbz r3, 56+3(r1)
+	mtlr r0
+	addi r1, r1, 176
+	blr
+
+/* case FFI_TYPE_SINT8 */
+	lbz r3, 56+3(r1)
+	mtlr r0
+	extsb r3, r3
+	b L..finish
+
+/* case FFI_TYPE_UINT16 */
+	lhz r3, 56+2(r1)
+	mtlr r0
+	addi r1, r1, 176
+	blr
+
+/* case FFI_TYPE_SINT16 */
+	lha r3, 56+2(r1)
+	mtlr r0
+	addi r1, r1, 176
+	blr
+
+/* case FFI_TYPE_UINT32 */
+	lwz r3, 56+0(r1)
+	mtlr r0
+	addi r1, r1, 176
+	blr
+
+/* case FFI_TYPE_SINT32 */
+	lwz r3, 56+0(r1)
+	mtlr r0
+	addi r1, r1, 176
+	blr
+
+/* case FFI_TYPE_UINT64 */
+	lwz r3, 56+0(r1)
+	mtlr r0
+	lwz r4, 56+4(r1)
+	b L..finish
+
+/* case FFI_TYPE_SINT64 */
+	lwz r3, 56+0(r1)
+	mtlr r0
+	lwz r4, 56+4(r1)
+	b L..finish
+
+/* case FFI_TYPE_STRUCT */
+	mtlr r0
+	addi r1, r1, 176
+	blr
+	nop
+
+/* case FFI_TYPE_POINTER */
+	lwz r3, 56+0(r1)
+	mtlr r0
+L..finish:
+	addi r1, r1, 176
+	blr
+#endif
+/* END(ffi_closure_ASM) */
diff --git a/third_party/gofrontend/libffi/src/powerpc/asm.h b/third_party/gofrontend/libffi/src/powerpc/asm.h
new file mode 100644
index 0000000..994f62d
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/asm.h
@@ -0,0 +1,125 @@
+/* -----------------------------------------------------------------------
+   asm.h - Copyright (c) 1998 Geoffrey Keating
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define ASM_GLOBAL_DIRECTIVE .globl
+
+
+#define C_SYMBOL_NAME(name) name
+/* Macro for a label.  */
+#ifdef	__STDC__
+#define C_LABEL(name)		name##:
+#else
+#define C_LABEL(name)		name/**/:
+#endif
+
+/* This seems to always be the case on PPC.  */
+#define ALIGNARG(log2) log2
+/* For ELF we need the `.type' directive to make shared libs work right.  */
+#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
+
+/* If compiled for profiling, call `_mcount' at the start of each function.  */
+#ifdef	PROF
+/* The mcount code relies on the return address being on the stack
+   to locate our caller and so it can restore it; so store one just
+   for its benefit.  */
+#ifdef PIC
+#define CALL_MCOUNT							      \
+  .pushsection;								      \
+  .section ".data";							      \
+  .align ALIGNARG(2);							      \
+0:.long 0;								      \
+  .previous;								      \
+  mflr  %r0;								      \
+  stw   %r0,4(%r1);							      \
+  bl    _GLOBAL_OFFSET_TABLE_@local-4;					      \
+  mflr  %r11;								      \
+  lwz   %r0,0b@got(%r11);						      \
+  bl    JUMPTARGET(_mcount);
+#else  /* PIC */
+#define CALL_MCOUNT							      \
+  .section ".data";							      \
+  .align ALIGNARG(2);							      \
+0:.long 0;								      \
+  .previous;								      \
+  mflr  %r0;								      \
+  lis   %r11,0b@ha;							      \
+  stw   %r0,4(%r1);							      \
+  addi  %r0,%r11,0b@l;							      \
+  bl    JUMPTARGET(_mcount);
+#endif /* PIC */
+#else  /* PROF */
+#define CALL_MCOUNT		/* Do nothing.  */
+#endif /* PROF */
+
+#define	ENTRY(name)							      \
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);				      \
+  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function)			      \
+  .align ALIGNARG(2);							      \
+  C_LABEL(name)								      \
+  CALL_MCOUNT
+
+#define EALIGN_W_0  /* No words to insert.  */
+#define EALIGN_W_1  nop
+#define EALIGN_W_2  nop;nop
+#define EALIGN_W_3  nop;nop;nop
+#define EALIGN_W_4  EALIGN_W_3;nop
+#define EALIGN_W_5  EALIGN_W_4;nop
+#define EALIGN_W_6  EALIGN_W_5;nop
+#define EALIGN_W_7  EALIGN_W_6;nop
+
+/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes
+   past a 2^align boundary.  */
+#ifdef PROF
+#define EALIGN(name, alignt, words)					      \
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);				      \
+  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function)			      \
+  .align ALIGNARG(2);							      \
+  C_LABEL(name)								      \
+  CALL_MCOUNT								      \
+  b 0f;									      \
+  .align ALIGNARG(alignt);						      \
+  EALIGN_W_##words;							      \
+  0:
+#else /* PROF */
+#define EALIGN(name, alignt, words)					      \
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);				      \
+  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function)			      \
+  .align ALIGNARG(alignt);						      \
+  EALIGN_W_##words;							      \
+  C_LABEL(name)
+#endif
+
+#define END(name)							      \
+  ASM_SIZE_DIRECTIVE(name)
+
+#ifdef PIC
+#define JUMPTARGET(name) name##@plt
+#else
+#define JUMPTARGET(name) name
+#endif
+
+/* Local labels stripped out by the linker.  */
+#define L(x) .L##x
diff --git a/third_party/gofrontend/libffi/src/powerpc/darwin.S b/third_party/gofrontend/libffi/src/powerpc/darwin.S
new file mode 100644
index 0000000..4f987dc
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/darwin.S
@@ -0,0 +1,383 @@
+/* -----------------------------------------------------------------------
+   darwin.S - Copyright (c) 2000 John Hornkvist
+	      Copyright (c) 2004, 2010 Free Software Foundation, Inc.
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#if defined(__ppc64__)
+#define MODE_CHOICE(x, y) y
+#else
+#define MODE_CHOICE(x, y) x
+#endif
+
+#define machine_choice	MODE_CHOICE(ppc7400,ppc64)
+
+; Define some pseudo-opcodes for size-independent load & store of GPRs ...
+#define lgu		MODE_CHOICE(lwzu, ldu)
+#define lg		MODE_CHOICE(lwz,ld)
+#define sg		MODE_CHOICE(stw,std)
+#define sgu		MODE_CHOICE(stwu,stdu)
+#define sgux		MODE_CHOICE(stwux,stdux)
+
+; ... and the size of GPRs and their storage indicator.
+#define GPR_BYTES	MODE_CHOICE(4,8)
+#define LOG2_GPR_BYTES	MODE_CHOICE(2,3)	/* log2(GPR_BYTES) */
+#define g_long		MODE_CHOICE(long, quad)	/* usage is ".g_long" */
+
+; From the ABI doc: "Mac OS X ABI Function Call Guide" Version 2009-02-04.
+#define LINKAGE_SIZE	MODE_CHOICE(24,48)
+#define PARAM_AREA	MODE_CHOICE(32,64)
+#define SAVED_LR_OFFSET	MODE_CHOICE(8,16)	/* save position for lr */
+
+/* If there is any FP stuff we make space for all of the regs.  */
+#define SAVED_FPR_COUNT 13
+#define FPR_SIZE	8
+#define RESULT_BYTES	16
+
+/* This should be kept in step with the same value in ffi_darwin.c.  */
+#define ASM_NEEDS_REGISTERS 4
+#define SAVE_REGS_SIZE (ASM_NEEDS_REGISTERS * GPR_BYTES)
+
+#include <fficonfig.h>
+#include <ffi.h>
+
+#define JUMPTARGET(name) name
+#define L(x) x
+
+	.text
+	.align 2
+	.globl _ffi_prep_args
+
+	.align 2
+	.globl _ffi_call_DARWIN
+
+	/* We arrive here with:
+	   r3 = ptr to extended cif.
+	   r4 = -bytes.
+	   r5 = cif flags.
+	   r6 = ptr to return value.
+	   r7 = fn pointer (user func).
+	   r8 = fn pointer (ffi_prep_args).
+	   r9 = ffi_type* for the ret val.  */
+
+_ffi_call_DARWIN:
+Lstartcode:
+	mr   	r12,r8	/* We only need r12 until the call,
+			   so it does not have to be saved.  */
+LFB1:
+	/* Save the old stack pointer as AP.  */
+	mr	r8,r1
+LCFI0:
+	
+	/* Save the retval type in parents frame.  */
+	sg	r9,(LINKAGE_SIZE+6*GPR_BYTES)(r8)
+
+	/* Allocate the stack space we need.  */
+	sgux	r1,r1,r4
+
+	/* Save registers we use.  */
+	mflr	r9
+	sg	r9,SAVED_LR_OFFSET(r8)
+
+	sg	r28,-(4 * GPR_BYTES)(r8)	
+	sg	r29,-(3 * GPR_BYTES)(r8)
+	sg	r30,-(2 * GPR_BYTES)(r8)
+	sg	r31,-(    GPR_BYTES)(r8)
+
+#if !defined(POWERPC_DARWIN)
+	/* The TOC slot is reserved in the Darwin ABI and r2 is volatile.  */
+	sg	r2,(5 * GPR_BYTES)(r1)
+#endif
+
+LCFI1:
+
+	/* Save arguments over call.  */
+	mr	r31,r5	/* flags,  */
+	mr	r30,r6	/* rvalue,  */
+	mr	r29,r7	/* function address,  */
+	mr	r28,r8	/* our AP.  */
+LCFI2:
+	/* Call ffi_prep_args. r3 = extended cif, r4 = stack ptr copy.  */
+	mr	r4,r1
+	li	r9,0
+
+	mtctr	r12 /* r12 holds address of _ffi_prep_args.  */
+	bctrl
+
+#if !defined(POWERPC_DARWIN)
+	/* The TOC slot is reserved in the Darwin ABI and r2 is volatile.  */
+	lg     r2,(5 * GPR_BYTES)(r1)
+#endif
+	/* Now do the call.
+	   Set up cr1 with bits 4-7 of the flags.  */
+	mtcrf	0x40,r31
+	/* Get the address to call into CTR.  */
+	mtctr	r29
+	/* Load all those argument registers.
+	   We have set up a nice stack frame, just load it into registers.  */
+	lg     r3, (LINKAGE_SIZE                )(r1)
+	lg     r4, (LINKAGE_SIZE +     GPR_BYTES)(r1)
+	lg     r5, (LINKAGE_SIZE + 2 * GPR_BYTES)(r1)
+	lg     r6, (LINKAGE_SIZE + 3 * GPR_BYTES)(r1)
+	nop
+	lg     r7, (LINKAGE_SIZE + 4 * GPR_BYTES)(r1)
+	lg     r8, (LINKAGE_SIZE + 5 * GPR_BYTES)(r1)
+	lg     r9, (LINKAGE_SIZE + 6 * GPR_BYTES)(r1)
+	lg     r10,(LINKAGE_SIZE + 7 * GPR_BYTES)(r1)
+
+L1:
+	/* ... Load all the FP registers.  */
+	bf	6,L2	/* No floats to load.  */
+	lfd	f1, -SAVE_REGS_SIZE-(13*FPR_SIZE)(r28)
+	lfd	f2, -SAVE_REGS_SIZE-(12*FPR_SIZE)(r28)
+	lfd	f3, -SAVE_REGS_SIZE-(11*FPR_SIZE)(r28)
+	lfd	f4, -SAVE_REGS_SIZE-(10*FPR_SIZE)(r28)
+	nop
+	lfd	f5, -SAVE_REGS_SIZE-( 9*FPR_SIZE)(r28)
+	lfd	f6, -SAVE_REGS_SIZE-( 8*FPR_SIZE)(r28)
+	lfd	f7, -SAVE_REGS_SIZE-( 7*FPR_SIZE)(r28)
+	lfd	f8, -SAVE_REGS_SIZE-( 6*FPR_SIZE)(r28)
+	nop
+	lfd     f9, -SAVE_REGS_SIZE-( 5*FPR_SIZE)(r28)
+	lfd     f10,-SAVE_REGS_SIZE-( 4*FPR_SIZE)(r28)
+	lfd     f11,-SAVE_REGS_SIZE-( 3*FPR_SIZE)(r28)
+	lfd     f12,-SAVE_REGS_SIZE-( 2*FPR_SIZE)(r28)
+	nop
+	lfd     f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28)
+
+L2:
+	mr	r12,r29	/* Put the target address in r12 as specified.  */
+	mtctr  	r12
+	nop
+	nop
+
+	/* Make the call.  */
+	bctrl
+
+	/* Now, deal with the return value.  */
+
+	/* m64 structure returns can occupy the same set of registers as
+	   would be used to pass such a structure as arg0 - so take care 
+	   not to step on any possibly hot regs.  */
+
+	/* Get the flags.. */
+	mtcrf	0x03,r31 ; we need c6 & cr7 now.
+	; FLAG_RETURNS_NOTHING also covers struct ret-by-ref.
+	bt	30,L(done_return_value)	  ; FLAG_RETURNS_NOTHING
+	bf	27,L(scalar_return_value) ; not FLAG_RETURNS_STRUCT
+	
+	/* OK, so we have a struct.  */
+#if defined(__ppc64__)
+	bt	31,L(maybe_return_128) ; FLAG_RETURNS_128BITS, special case 
+
+	/* OK, we have to map the return back to a mem struct.
+	   We are about to trample the parents param area, so recover the
+	   return type.  r29 is free, since the call is done.  */
+	lg	r29,(LINKAGE_SIZE + 6 * GPR_BYTES)(r28)
+
+	sg	r3, (LINKAGE_SIZE                )(r28)
+	sg	r4, (LINKAGE_SIZE +     GPR_BYTES)(r28)
+	sg	r5, (LINKAGE_SIZE + 2 * GPR_BYTES)(r28)
+	sg	r6, (LINKAGE_SIZE + 3 * GPR_BYTES)(r28)
+	nop
+	sg	r7, (LINKAGE_SIZE + 4 * GPR_BYTES)(r28)
+	sg	r8, (LINKAGE_SIZE + 5 * GPR_BYTES)(r28)
+	sg	r9, (LINKAGE_SIZE + 6 * GPR_BYTES)(r28)
+	sg	r10,(LINKAGE_SIZE + 7 * GPR_BYTES)(r28)
+	/* OK, so do the block move - we trust that memcpy will not trample
+	   the fprs...  */
+	mr 	r3,r30 ; dest
+	addi	r4,r28,LINKAGE_SIZE ; source
+	/* The size is a size_t, should be long.  */
+	lg	r5,0(r29)
+	/* Figure out small structs */
+	cmpi	0,r5,4
+	bgt	L3	; 1, 2 and 4 bytes have special rules.
+	cmpi	0,r5,3
+	beq	L3	; not 3
+	addi	r4,r4,8
+	subf	r4,r5,r4
+L3:
+	bl	_memcpy
+	
+	/* ... do we need the FP registers? - recover the flags.. */
+	mtcrf	0x03,r31 ; we need c6 & cr7 now.
+	bf	29,L(done_return_value)	/* No floats in the struct.  */
+	stfd	f1, -SAVE_REGS_SIZE-(13*FPR_SIZE)(r28)
+	stfd	f2, -SAVE_REGS_SIZE-(12*FPR_SIZE)(r28)
+	stfd	f3, -SAVE_REGS_SIZE-(11*FPR_SIZE)(r28)
+	stfd	f4, -SAVE_REGS_SIZE-(10*FPR_SIZE)(r28)
+	nop
+	stfd	f5, -SAVE_REGS_SIZE-( 9*FPR_SIZE)(r28)
+	stfd	f6, -SAVE_REGS_SIZE-( 8*FPR_SIZE)(r28)
+	stfd	f7, -SAVE_REGS_SIZE-( 7*FPR_SIZE)(r28)
+	stfd	f8, -SAVE_REGS_SIZE-( 6*FPR_SIZE)(r28)
+	nop
+	stfd	f9, -SAVE_REGS_SIZE-( 5*FPR_SIZE)(r28)
+	stfd	f10,-SAVE_REGS_SIZE-( 4*FPR_SIZE)(r28)
+	stfd	f11,-SAVE_REGS_SIZE-( 3*FPR_SIZE)(r28)
+	stfd	f12,-SAVE_REGS_SIZE-( 2*FPR_SIZE)(r28)
+	nop
+	stfd	f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28)
+
+	mr	r3,r29	; ffi_type *
+	mr	r4,r30	; dest
+	addi	r5,r28,-SAVE_REGS_SIZE-(13*FPR_SIZE) ; fprs
+	xor	r6,r6,r6
+	sg	r6,(LINKAGE_SIZE + 7 * GPR_BYTES)(r28)
+	addi	r6,r28,(LINKAGE_SIZE + 7 * GPR_BYTES) ; point to a zeroed counter.
+	bl 	_darwin64_struct_floats_to_mem
+
+	b L(done_return_value)
+#else
+	stw	r3,0(r30) ; m32 the only struct return in reg is 4 bytes.
+#endif
+	b L(done_return_value)
+
+L(fp_return_value):
+	/* Do we have long double to store?  */
+	bf	31,L(fd_return_value) ; FLAG_RETURNS_128BITS
+	stfd	f1,0(r30)
+	stfd	f2,FPR_SIZE(r30)
+	b	L(done_return_value)
+
+L(fd_return_value):
+	/* Do we have double to store?  */
+	bf	28,L(float_return_value)
+	stfd	f1,0(r30)
+	b	L(done_return_value)
+
+L(float_return_value):
+	/* We only have a float to store.  */
+	stfs	f1,0(r30)
+	b	L(done_return_value)
+
+L(scalar_return_value):
+	bt	29,L(fp_return_value)	; FLAG_RETURNS_FP
+	; ffi_arg is defined as unsigned long. 
+	sg	r3,0(r30)		; Save the reg.
+	bf	28,L(done_return_value) ; not FLAG_RETURNS_64BITS 
+
+#if defined(__ppc64__)
+L(maybe_return_128):
+	std	r3,0(r30)
+	bf	31,L(done_return_value) ; not FLAG_RETURNS_128BITS 
+	std	r4,8(r30)
+#else
+	stw	r4,4(r30)
+#endif
+
+	/* Fall through.  */
+	/* We want this at the end to simplify eh epilog computation.  */
+
+L(done_return_value):
+	/* Restore the registers we used and return.  */
+	lg	r29,SAVED_LR_OFFSET(r28)
+	; epilog
+	lg	r31,-(1 * GPR_BYTES)(r28)
+	mtlr	r29
+	lg	r30,-(2 * GPR_BYTES)(r28)
+	lg	r29,-(3 * GPR_BYTES)(r28)
+	lg	r28,-(4 * GPR_BYTES)(r28)
+	lg	r1,0(r1)
+	blr
+LFE1:
+	.align	1
+/* END(_ffi_call_DARWIN)  */
+
+/* Provide a null definition of _ffi_call_AIX.  */
+	.text
+	.globl _ffi_call_AIX
+	.align 2
+_ffi_call_AIX:
+	blr
+/* END(_ffi_call_AIX)  */
+
+/* EH stuff.  */
+
+#define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78)
+
+	.static_data
+	.align LOG2_GPR_BYTES
+LLFB0$non_lazy_ptr:
+	.g_long Lstartcode
+
+	.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+	.set	L$set$0,LECIE1-LSCIE1
+	.long	L$set$0	; Length of Common Information Entry
+LSCIE1:
+	.long	0x0	; CIE Identifier Tag
+	.byte	0x1	; CIE Version
+	.ascii	"zR\0"	; CIE Augmentation
+	.byte	0x1	; uleb128 0x1; CIE Code Alignment Factor
+	.byte	EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
+	.byte	0x41	; CIE RA Column
+	.byte	0x1	; uleb128 0x1; Augmentation size
+	.byte	0x10	; FDE Encoding (indirect pcrel)
+	.byte	0xc	; DW_CFA_def_cfa
+	.byte	0x1	; uleb128 0x1
+	.byte	0x0	; uleb128 0x0
+	.align	LOG2_GPR_BYTES
+LECIE1:
+
+	.globl _ffi_call_DARWIN.eh
+_ffi_call_DARWIN.eh:
+LSFDE1:
+	.set	L$set$1,LEFDE1-LASFDE1
+	.long	L$set$1	; FDE Length
+LASFDE1:
+	.long	LASFDE1-EH_frame1 ; FDE CIE offset
+	.g_long	LLFB0$non_lazy_ptr-.	; FDE initial location
+	.set	L$set$3,LFE1-Lstartcode
+	.g_long	L$set$3	; FDE address range
+	.byte   0x0     ; uleb128 0x0; Augmentation size
+	.byte	0x4	; DW_CFA_advance_loc4
+	.set	L$set$4,LCFI0-Lstartcode
+	.long	L$set$4
+	.byte	0xd	; DW_CFA_def_cfa_register
+	.byte	0x08	; uleb128 0x08
+	.byte	0x4	; DW_CFA_advance_loc4
+	.set	L$set$5,LCFI1-LCFI0
+	.long	L$set$5
+	.byte   0x11    ; DW_CFA_offset_extended_sf
+	.byte	0x41	; uleb128 0x41
+	.byte   0x7e    ; sleb128 -2
+	.byte	0x9f	; DW_CFA_offset, column 0x1f
+	.byte	0x1	; uleb128 0x1
+	.byte	0x9e	; DW_CFA_offset, column 0x1e
+	.byte	0x2	; uleb128 0x2
+	.byte	0x9d	; DW_CFA_offset, column 0x1d
+	.byte	0x3	; uleb128 0x3
+	.byte	0x9c	; DW_CFA_offset, column 0x1c
+	.byte	0x4	; uleb128 0x4
+	.byte	0x4	; DW_CFA_advance_loc4
+	.set	L$set$6,LCFI2-LCFI1
+	.long	L$set$6
+	.byte	0xd	; DW_CFA_def_cfa_register
+	.byte	0x1c	; uleb128 0x1c
+	.align LOG2_GPR_BYTES
+LEFDE1:
+	.align 1
+
diff --git a/third_party/gofrontend/libffi/src/powerpc/darwin_closure.S b/third_party/gofrontend/libffi/src/powerpc/darwin_closure.S
new file mode 100644
index 0000000..3f6790f
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/darwin_closure.S
@@ -0,0 +1,576 @@
+/* -----------------------------------------------------------------------
+   darwin_closure.S - Copyright (c) 2002, 2003, 2004, 2010, 
+   Free Software Foundation, Inc. 
+   based on ppc_closure.S
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#define L(x) x
+
+#if defined(__ppc64__)
+#define MODE_CHOICE(x, y) y
+#else
+#define MODE_CHOICE(x, y) x
+#endif
+
+#define machine_choice	MODE_CHOICE(ppc7400,ppc64)
+
+; Define some pseudo-opcodes for size-independent load & store of GPRs ...
+#define lgu		MODE_CHOICE(lwzu, ldu)
+#define lg		MODE_CHOICE(lwz,ld)
+#define sg		MODE_CHOICE(stw,std)
+#define sgu		MODE_CHOICE(stwu,stdu)
+
+; ... and the size of GPRs and their storage indicator.
+#define GPR_BYTES	MODE_CHOICE(4,8)
+#define LOG2_GPR_BYTES	MODE_CHOICE(2,3)	/* log2(GPR_BYTES) */
+#define g_long		MODE_CHOICE(long, quad)	/* usage is ".g_long" */
+
+; From the ABI doc: "Mac OS X ABI Function Call Guide" Version 2009-02-04.
+#define LINKAGE_SIZE	MODE_CHOICE(24,48)
+#define PARAM_AREA	MODE_CHOICE(32,64)
+
+#define SAVED_CR_OFFSET	MODE_CHOICE(4,8)	/* save position for CR */
+#define SAVED_LR_OFFSET	MODE_CHOICE(8,16)	/* save position for lr */
+
+/* WARNING: if ffi_type is changed... here be monsters.  
+   Offsets of items within the result type.  */
+#define FFI_TYPE_TYPE	MODE_CHOICE(6,10)
+#define FFI_TYPE_ELEM	MODE_CHOICE(8,16)
+
+#define SAVED_FPR_COUNT 13
+#define FPR_SIZE	8
+/* biggest m64 struct ret is 8GPRS + 13FPRS = 168 bytes - rounded to 16bytes = 176. */
+#define RESULT_BYTES	MODE_CHOICE(16,176)
+
+; The whole stack frame **MUST** be 16byte-aligned.
+#define SAVE_SIZE (((LINKAGE_SIZE+PARAM_AREA+SAVED_FPR_COUNT*FPR_SIZE+RESULT_BYTES)+15) & -16LL)
+#define PAD_SIZE (SAVE_SIZE-(LINKAGE_SIZE+PARAM_AREA+SAVED_FPR_COUNT*FPR_SIZE+RESULT_BYTES))
+
+#define PARENT_PARM_BASE (SAVE_SIZE+LINKAGE_SIZE)
+#define FP_SAVE_BASE (LINKAGE_SIZE+PARAM_AREA)
+
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
+; We no longer need the pic symbol stub for Darwin >= 9.
+#define BLCLS_HELP _ffi_closure_helper_DARWIN
+#define STRUCT_RETVALUE_P _darwin64_struct_ret_by_value_p
+#define PASS_STR_FLOATS _darwin64_pass_struct_floats
+#undef WANT_STUB
+#else
+#define BLCLS_HELP L_ffi_closure_helper_DARWIN$stub
+#define STRUCT_RETVALUE_P L_darwin64_struct_ret_by_value_p$stub
+#define PASS_STR_FLOATS L_darwin64_pass_struct_floats$stub
+#define WANT_STUB
+#endif
+
+/* m32/m64
+
+   The stack layout looks like this:
+
+   |   Additional params...			| |     Higher address
+   ~						~ ~
+   |   Parameters      (at least 8*4/8=32/64)	| | NUM_GPR_ARG_REGISTERS
+   |--------------------------------------------| |
+   |   TOC=R2 (AIX) Reserved (Darwin)   4/8	| |
+   |--------------------------------------------| |
+   |   Reserved                       2*4/8	| |
+   |--------------------------------------------| |
+   |   Space for callee`s LR		4/8	| |
+   |--------------------------------------------| |
+   |   Saved CR [low word for m64]      4/8	| |
+   |--------------------------------------------| |
+   |   Current backchain pointer	4/8	|-/ Parent`s frame.
+   |--------------------------------------------| <+ <<< on entry to
+   |   Result Bytes		       16/176	| |
+   |--------------------------------------------| |
+   ~   padding to 16-byte alignment		~ ~
+   |--------------------------------------------| |
+   |   NUM_FPR_ARG_REGISTERS slots		| |
+   |   here fp13 .. fp1		       13*8	| |
+   |--------------------------------------------| |
+   |   R3..R10			  8*4/8=32/64	| | NUM_GPR_ARG_REGISTERS
+   |--------------------------------------------| |
+   |   TOC=R2 (AIX) Reserved (Darwin)   4/8	| |
+   |--------------------------------------------| |	stack	|
+   |   Reserved [compiler,binder]     2*4/8	| |	grows	|
+   |--------------------------------------------| |	down	V
+   |   Space for callees LR		4/8	| |
+   |--------------------------------------------| |	lower addresses
+   |   Saved CR [low word for m64]      4/8	| |
+   |--------------------------------------------| |     stack pointer here
+   |   Current backchain pointer	4/8	|-/	during
+   |--------------------------------------------|   <<<	call.
+
+*/
+
+	.file	"darwin_closure.S"
+
+	.machine machine_choice
+
+	.text
+	.globl _ffi_closure_ASM
+	.align LOG2_GPR_BYTES
+_ffi_closure_ASM:
+LFB1:
+Lstartcode:
+	mflr	r0			/* extract return address  */
+	sg	r0,SAVED_LR_OFFSET(r1)	/* save the return address  */
+LCFI0:
+	sgu	r1,-SAVE_SIZE(r1)	/* skip over caller save area
+					keep stack aligned to 16.  */
+LCFI1:
+	/* We want to build up an area for the parameters passed
+	   in registers. (both floating point and integer)  */
+
+	/* Put gpr 3 to gpr 10 in the parents outgoing area...
+	   ... the remainder of any params that overflowed the regs will
+	   follow here.  */
+	sg	r3, (PARENT_PARM_BASE                )(r1)
+	sg	r4, (PARENT_PARM_BASE + GPR_BYTES    )(r1)
+	sg	r5, (PARENT_PARM_BASE + GPR_BYTES * 2)(r1)
+	sg	r6, (PARENT_PARM_BASE + GPR_BYTES * 3)(r1)
+	sg	r7, (PARENT_PARM_BASE + GPR_BYTES * 4)(r1)
+	sg	r8, (PARENT_PARM_BASE + GPR_BYTES * 5)(r1)
+	sg	r9, (PARENT_PARM_BASE + GPR_BYTES * 6)(r1)
+	sg	r10,(PARENT_PARM_BASE + GPR_BYTES * 7)(r1)
+
+	/* We save fpr 1 to fpr 14 in our own save frame.  */
+	stfd	f1, (FP_SAVE_BASE                 )(r1)
+	stfd	f2, (FP_SAVE_BASE +  FPR_SIZE     )(r1)
+	stfd	f3, (FP_SAVE_BASE +  FPR_SIZE * 2 )(r1)
+	stfd	f4, (FP_SAVE_BASE +  FPR_SIZE * 3 )(r1)
+	stfd	f5, (FP_SAVE_BASE +  FPR_SIZE * 4 )(r1)
+	stfd	f6, (FP_SAVE_BASE +  FPR_SIZE * 5 )(r1)
+	stfd	f7, (FP_SAVE_BASE +  FPR_SIZE * 6 )(r1)
+	stfd	f8, (FP_SAVE_BASE +  FPR_SIZE * 7 )(r1)
+	stfd	f9, (FP_SAVE_BASE +  FPR_SIZE * 8 )(r1)
+	stfd	f10,(FP_SAVE_BASE +  FPR_SIZE * 9 )(r1)
+	stfd	f11,(FP_SAVE_BASE +  FPR_SIZE * 10)(r1)
+	stfd	f12,(FP_SAVE_BASE +  FPR_SIZE * 11)(r1)
+	stfd	f13,(FP_SAVE_BASE +  FPR_SIZE * 12)(r1)
+
+	/* Set up registers for the routine that actually does the work
+	   get the context pointer from the trampoline.  */
+	mr	r3,r11
+
+	/* Now load up the pointer to the result storage.  */
+	addi	r4,r1,(SAVE_SIZE-RESULT_BYTES)
+
+	/* Now load up the pointer to the saved gpr registers.  */
+	addi	r5,r1,PARENT_PARM_BASE
+
+	/* Now load up the pointer to the saved fpr registers.  */
+	addi	r6,r1,FP_SAVE_BASE
+
+	/* Make the call.  */
+	bl	BLCLS_HELP
+
+	/* r3 contains the rtype pointer... save it since we will need
+	   it later.  */
+	sg	r3,LINKAGE_SIZE(r1)	; ffi_type * result_type
+	lg	r0,0(r3)		; size => r0
+	lhz	r3,FFI_TYPE_TYPE(r3)	; type => r3
+
+	/* The helper will have intercepted struture returns and inserted
+	   the caller`s destination address for structs returned by ref.  */
+
+	/* r3 contains the return type  so use it to look up in a table
+	   so we know how to deal with each type.  */
+
+	addi	r5,r1,(SAVE_SIZE-RESULT_BYTES) /* Otherwise, our return is here.  */
+	bl	Lget_ret_type0_addr	/* Get pointer to Lret_type0 into LR.  */
+	mflr	r4			/* Move to r4.  */
+	slwi	r3,r3,4			/* Now multiply return type by 16.  */
+	add	r3,r3,r4		/* Add contents of table to table address.  */
+	mtctr	r3
+	bctr			 	 /* Jump to it.  */
+LFE1:
+/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
+   (4 instructions). For cache effectiveness we align to a 16 byte boundary
+   first.  */
+
+	.align 4
+
+	nop
+	nop
+	nop
+Lget_ret_type0_addr:
+	blrl
+
+/* case FFI_TYPE_VOID  */
+Lret_type0:
+	b	Lfinish
+	nop
+	nop
+	nop
+
+/* case FFI_TYPE_INT  */
+Lret_type1:
+	lg	r3,0(r5)
+	b	Lfinish
+	nop
+	nop
+
+/* case FFI_TYPE_FLOAT  */
+Lret_type2:
+	lfs	f1,0(r5)
+	b	Lfinish
+	nop
+	nop
+
+/* case FFI_TYPE_DOUBLE  */
+Lret_type3:
+	lfd	f1,0(r5)
+	b	Lfinish
+	nop
+	nop
+
+/* case FFI_TYPE_LONGDOUBLE  */
+Lret_type4:
+	lfd	f1,0(r5)
+	lfd	f2,8(r5)
+	b	Lfinish
+	nop
+
+/* case FFI_TYPE_UINT8  */
+Lret_type5:
+#if defined(__ppc64__)
+	lbz	r3,7(r5)
+#else
+	lbz	r3,3(r5)
+#endif
+	b	Lfinish
+	nop
+	nop
+
+/* case FFI_TYPE_SINT8  */
+Lret_type6:
+#if defined(__ppc64__)
+	lbz	r3,7(r5)
+#else
+	lbz	r3,3(r5)
+#endif
+	extsb	r3,r3
+	b	Lfinish
+	nop
+
+/* case FFI_TYPE_UINT16  */
+Lret_type7:
+#if defined(__ppc64__)
+	lhz	r3,6(r5)
+#else
+	lhz	r3,2(r5)
+#endif
+	b	Lfinish
+	nop
+	nop
+
+/* case FFI_TYPE_SINT16  */
+Lret_type8:
+#if defined(__ppc64__)
+	lha	r3,6(r5)
+#else
+	lha	r3,2(r5)
+#endif
+	b	Lfinish
+	nop
+	nop
+
+/* case FFI_TYPE_UINT32  */
+Lret_type9:
+#if defined(__ppc64__)
+	lwz	r3,4(r5)
+#else
+	lwz	r3,0(r5)
+#endif
+	b	Lfinish
+	nop
+	nop
+
+/* case FFI_TYPE_SINT32  */
+Lret_type10:
+#if defined(__ppc64__)
+	lwz	r3,4(r5)
+#else
+	lwz	r3,0(r5)
+#endif
+	b	Lfinish
+	nop
+	nop
+
+/* case FFI_TYPE_UINT64  */
+Lret_type11:
+#if defined(__ppc64__)
+	lg	r3,0(r5)
+	b	Lfinish
+	nop
+#else
+	lwz	r3,0(r5)
+	lwz	r4,4(r5)
+	b	Lfinish
+#endif
+	nop
+
+/* case FFI_TYPE_SINT64  */
+Lret_type12:
+#if defined(__ppc64__)
+	lg	r3,0(r5)
+	b	Lfinish
+	nop
+#else
+	lwz	r3,0(r5)
+	lwz	r4,4(r5)
+	b	Lfinish
+#endif
+	nop
+
+/* case FFI_TYPE_STRUCT  */
+Lret_type13:
+#if defined(__ppc64__)
+	lg	r3,0(r5)		; we need at least this...
+	cmpi	0,r0,4
+	bgt	Lstructend		; not a special small case
+	b	Lsmallstruct		; see if we need more.
+#else
+	cmpi	0,r0,4
+	bgt	Lfinish		; not by value
+	lg	r3,0(r5)
+	b	Lfinish
+#endif
+/* case FFI_TYPE_POINTER  */
+Lret_type14:
+	lg	r3,0(r5)
+	b	Lfinish
+	nop
+	nop
+
+#if defined(__ppc64__)
+Lsmallstruct:
+	beq	Lfour			; continuation of Lret13.
+	cmpi	0,r0,3
+	beq	Lfinish			; don`t adjust this - can`t be any floats here...
+	srdi	r3,r3,48
+	cmpi	0,r0,2
+	beq	Lfinish			; .. or here ..
+	srdi	r3,r3,8
+	b 	Lfinish			; .. or here.
+
+Lfour:
+	lg	r6,LINKAGE_SIZE(r1)	; get the result type
+	lg	r6,FFI_TYPE_ELEM(r6)	; elements array pointer
+	lg	r6,0(r6)		; first element
+	lhz	r0,FFI_TYPE_TYPE(r6)	; OK go the type
+	cmpi	0,r0,2			; FFI_TYPE_FLOAT
+	bne	Lfourint
+	lfs	f1,0(r5)		; just one float in the struct.
+	b 	Lfinish
+
+Lfourint:
+	srdi	r3,r3,32		; four bytes.
+	b 	Lfinish
+
+Lstructend:
+	lg	r3,LINKAGE_SIZE(r1)	; get the result type
+	bl	STRUCT_RETVALUE_P
+	cmpi	0,r3,0
+	beq	Lfinish			; nope.
+	/* Recover a pointer to the results.  */
+	addi	r11,r1,(SAVE_SIZE-RESULT_BYTES)
+	lg	r3,0(r11)		; we need at least this...
+	lg	r4,8(r11)
+	cmpi	0,r0,16
+	beq	Lfinish		; special case 16 bytes we don't consider floats.
+
+	/* OK, frustratingly, the process of saving the struct to mem might have
+	   messed with the FPRs, so we have to re-load them :(.
+	   We`ll use our FPRs space again - calling: 
+	   void darwin64_pass_struct_floats (ffi_type *s, char *src, 
+					     unsigned *nfpr, double **fprs) 
+	   We`ll temporarily pinch the first two slots of the param area for local
+	   vars used by the routine.  */
+	xor	r6,r6,r6
+	addi	r5,r1,PARENT_PARM_BASE		; some space
+	sg	r6,0(r5)			; *nfpr zeroed.
+	addi	r6,r5,8				; **fprs
+	addi	r3,r1,FP_SAVE_BASE		; pointer to FPRs space
+	sg	r3,0(r6)
+	mr	r4,r11				; the struct is here...
+	lg	r3,LINKAGE_SIZE(r1)		; ffi_type * result_type.
+	bl	PASS_STR_FLOATS			; get struct floats into FPR save space.
+	/* See if we used any floats  */
+	lwz	r0,(SAVE_SIZE-RESULT_BYTES)(r1)	
+	cmpi	0,r0,0
+	beq	Lstructints			; nope.
+	/* OK load `em up... */
+	lfd	f1, (FP_SAVE_BASE                 )(r1)
+	lfd	f2, (FP_SAVE_BASE +  FPR_SIZE     )(r1)
+	lfd	f3, (FP_SAVE_BASE +  FPR_SIZE * 2 )(r1)
+	lfd	f4, (FP_SAVE_BASE +  FPR_SIZE * 3 )(r1)
+	lfd	f5, (FP_SAVE_BASE +  FPR_SIZE * 4 )(r1)
+	lfd	f6, (FP_SAVE_BASE +  FPR_SIZE * 5 )(r1)
+	lfd	f7, (FP_SAVE_BASE +  FPR_SIZE * 6 )(r1)
+	lfd	f8, (FP_SAVE_BASE +  FPR_SIZE * 7 )(r1)
+	lfd	f9, (FP_SAVE_BASE +  FPR_SIZE * 8 )(r1)
+	lfd	f10,(FP_SAVE_BASE +  FPR_SIZE * 9 )(r1)
+	lfd	f11,(FP_SAVE_BASE +  FPR_SIZE * 10)(r1)
+	lfd	f12,(FP_SAVE_BASE +  FPR_SIZE * 11)(r1)
+	lfd	f13,(FP_SAVE_BASE +  FPR_SIZE * 12)(r1)
+
+	/* point back at our saved struct.  */
+Lstructints:
+	addi	r11,r1,(SAVE_SIZE-RESULT_BYTES)
+	lg	r3,0(r11)			; we end up picking the
+	lg	r4,8(r11)			; first two again.
+	lg	r5,16(r11)
+	lg	r6,24(r11)
+	lg	r7,32(r11)
+	lg	r8,40(r11)
+	lg	r9,48(r11)
+	lg	r10,56(r11)
+#endif
+
+/* case done  */
+Lfinish:
+	addi	r1,r1,SAVE_SIZE		/* Restore stack pointer.  */
+	lg	r0,SAVED_LR_OFFSET(r1)	/* Get return address.  */
+	mtlr	r0			/* Reset link register.  */
+	blr
+Lendcode:
+	.align 1
+	
+/* END(ffi_closure_ASM)  */
+
+/* EH frame stuff.  */
+#define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78)
+/* 176, 400 */
+#define EH_FRAME_OFFSETA MODE_CHOICE(176,0x90)
+#define EH_FRAME_OFFSETB MODE_CHOICE(1,3)
+
+	.static_data
+	.align LOG2_GPR_BYTES
+LLFB1$non_lazy_ptr:
+	.g_long Lstartcode
+
+	.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+	.set	L$set$0,LECIE1-LSCIE1
+	.long	L$set$0	; Length of Common Information Entry
+LSCIE1:
+	.long	0x0	; CIE Identifier Tag
+	.byte	0x1	; CIE Version
+	.ascii	"zR\0"	; CIE Augmentation
+	.byte	0x1	; uleb128 0x1; CIE Code Alignment Factor
+	.byte	EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
+	.byte	0x41	; CIE RA Column
+	.byte	0x1	; uleb128 0x1; Augmentation size
+	.byte	0x10	; FDE Encoding (indirect pcrel)
+	.byte	0xc	; DW_CFA_def_cfa
+	.byte	0x1	; uleb128 0x1
+	.byte	0x0	; uleb128 0x0
+	.align	LOG2_GPR_BYTES
+LECIE1:
+	.globl _ffi_closure_ASM.eh
+_ffi_closure_ASM.eh:
+LSFDE1:
+	.set	L$set$1,LEFDE1-LASFDE1
+	.long	L$set$1	; FDE Length
+
+LASFDE1:
+	.long	LASFDE1-EH_frame1	; FDE CIE offset
+	.g_long	LLFB1$non_lazy_ptr-.	; FDE initial location
+	.set	L$set$3,LFE1-Lstartcode
+	.g_long	L$set$3	; FDE address range
+	.byte   0x0     ; uleb128 0x0; Augmentation size
+	.byte	0x4	; DW_CFA_advance_loc4
+	.set	L$set$3,LCFI1-LCFI0
+	.long	L$set$3
+	.byte	0xe	; DW_CFA_def_cfa_offset
+	.byte	EH_FRAME_OFFSETA,EH_FRAME_OFFSETB	; uleb128 176,1/190,3
+	.byte	0x4	; DW_CFA_advance_loc4
+	.set	L$set$4,LCFI0-Lstartcode
+	.long	L$set$4
+	.byte   0x11    ; DW_CFA_offset_extended_sf
+	.byte	0x41	; uleb128 0x41
+	.byte   0x7e    ; sleb128 -2
+	.align	LOG2_GPR_BYTES
+LEFDE1:
+	.align 	1
+
+#ifdef WANT_STUB
+	.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+	.align 5
+L_ffi_closure_helper_DARWIN$stub:
+	.indirect_symbol _ffi_closure_helper_DARWIN
+	mflr r0
+	bcl 20,31,"L00000000001$spb"
+"L00000000001$spb":
+	mflr r11
+	addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L00000000001$spb")
+	mtlr r0
+	lwzu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L00000000001$spb")(r11)
+	mtctr r12
+	bctr
+	.lazy_symbol_pointer
+L_ffi_closure_helper_DARWIN$lazy_ptr:
+	.indirect_symbol _ffi_closure_helper_DARWIN
+	.g_long	dyld_stub_binding_helper
+
+#if defined(__ppc64__)
+	.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+	.align 5
+L_darwin64_struct_ret_by_value_p$stub:
+	.indirect_symbol _darwin64_struct_ret_by_value_p
+	mflr r0
+	bcl 20,31,"L00000000002$spb"
+"L00000000002$spb":
+	mflr r11
+	addis r11,r11,ha16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L00000000002$spb")
+	mtlr r0
+	lwzu r12,lo16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L00000000002$spb")(r11)
+	mtctr r12
+	bctr
+	.lazy_symbol_pointer
+L_darwin64_struct_ret_by_value_p$lazy_ptr:
+	.indirect_symbol _darwin64_struct_ret_by_value_p
+	.g_long	dyld_stub_binding_helper
+
+	.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+	.align 5
+L_darwin64_pass_struct_floats$stub:
+	.indirect_symbol _darwin64_pass_struct_floats
+	mflr r0
+	bcl 20,31,"L00000000003$spb"
+"L00000000003$spb":
+	mflr r11
+	addis r11,r11,ha16(L_darwin64_pass_struct_floats$lazy_ptr-"L00000000003$spb")
+	mtlr r0
+	lwzu r12,lo16(L_darwin64_pass_struct_floats$lazy_ptr-"L00000000003$spb")(r11)
+	mtctr r12
+	bctr
+	.lazy_symbol_pointer
+L_darwin64_pass_struct_floats$lazy_ptr:
+	.indirect_symbol _darwin64_pass_struct_floats
+	.g_long	dyld_stub_binding_helper
+#  endif
+#endif
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffi.c b/third_party/gofrontend/libffi/src/powerpc/ffi.c
new file mode 100644
index 0000000..efb441b
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/ffi.c
@@ -0,0 +1,141 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (C) 2013 IBM
+           Copyright (C) 2011 Anthony Green
+           Copyright (C) 2011 Kyle Moffett
+           Copyright (C) 2008 Red Hat, Inc
+           Copyright (C) 2007, 2008 Free Software Foundation, Inc
+	   Copyright (c) 1998 Geoffrey Keating
+
+   PowerPC Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include "ffi.h"
+#include "ffi_common.h"
+#include "ffi_powerpc.h"
+
+#if HAVE_LONG_DOUBLE_VARIANT
+/* Adjust ffi_type_longdouble.  */
+void FFI_HIDDEN
+ffi_prep_types (ffi_abi abi)
+{
+# if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+#  ifdef POWERPC64
+  ffi_prep_types_linux64 (abi);
+#  else
+  ffi_prep_types_sysv (abi);
+#  endif
+# endif
+}
+#endif
+
+/* Perform machine dependent cif processing */
+ffi_status FFI_HIDDEN
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+#ifdef POWERPC64
+  return ffi_prep_cif_linux64 (cif);
+#else
+  return ffi_prep_cif_sysv (cif);
+#endif
+}
+
+ffi_status FFI_HIDDEN
+ffi_prep_cif_machdep_var (ffi_cif *cif,
+			  unsigned int nfixedargs MAYBE_UNUSED,
+			  unsigned int ntotalargs MAYBE_UNUSED)
+{
+#ifdef POWERPC64
+  return ffi_prep_cif_linux64_var (cif, nfixedargs, ntotalargs);
+#else
+  return ffi_prep_cif_sysv (cif);
+#endif
+}
+
+void
+ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  /* The final SYSV ABI says that structures smaller or equal 8 bytes
+     are returned in r3/r4.  A draft ABI used by linux instead returns
+     them in memory.
+
+     We bounce-buffer SYSV small struct return values so that sysv.S
+     can write r3 and r4 to memory without worrying about struct size.
+   
+     For ELFv2 ABI, use a bounce buffer for homogeneous structs too,
+     for similar reasons.  */
+  unsigned long smst_buffer[8];
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  ecif.rvalue = rvalue;
+  if ((cif->flags & FLAG_RETURNS_SMST) != 0)
+    ecif.rvalue = smst_buffer;
+  /* Ensure that we have a valid struct return value.
+     FIXME: Isn't this just papering over a user problem?  */
+  else if (!rvalue && cif->rtype->type == FFI_TYPE_STRUCT)
+    ecif.rvalue = alloca (cif->rtype->size);
+
+#ifdef POWERPC64
+  ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
+#else
+  ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
+#endif
+
+  /* Check for a bounce-buffered return value */
+  if (rvalue && ecif.rvalue == smst_buffer)
+    {
+      unsigned int rsize = cif->rtype->size;
+#ifndef __LITTLE_ENDIAN__
+      /* The SYSV ABI returns a structure of up to 4 bytes in size
+	 left-padded in r3.  */
+# ifndef POWERPC64
+      if (rsize <= 4)
+	memcpy (rvalue, (char *) smst_buffer + 4 - rsize, rsize);
+      else
+# endif
+	/* The SYSV ABI returns a structure of up to 8 bytes in size
+	   left-padded in r3/r4, and the ELFv2 ABI similarly returns a
+	   structure of up to 8 bytes in size left-padded in r3.  */
+	if (rsize <= 8)
+	  memcpy (rvalue, (char *) smst_buffer + 8 - rsize, rsize);
+	else
+#endif
+	  memcpy (rvalue, smst_buffer, rsize);
+    }
+}
+
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure *closure,
+		      ffi_cif *cif,
+		      void (*fun) (ffi_cif *, void *, void **, void *),
+		      void *user_data,
+		      void *codeloc)
+{
+#ifdef POWERPC64
+  return ffi_prep_closure_loc_linux64 (closure, cif, fun, user_data, codeloc);
+#else
+  return ffi_prep_closure_loc_sysv (closure, cif, fun, user_data, codeloc);
+#endif
+}
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffi_darwin.c b/third_party/gofrontend/libffi/src/powerpc/ffi_darwin.c
new file mode 100644
index 0000000..dd897f4
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/ffi_darwin.c
@@ -0,0 +1,1359 @@
+/* -----------------------------------------------------------------------
+   ffi_darwin.c
+
+   Copyright (C) 1998 Geoffrey Keating
+   Copyright (C) 2001 John Hornkvist
+   Copyright (C) 2002, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   FFI support for Darwin and AIX.
+   
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+extern void ffi_closure_ASM (void);
+
+enum {
+  /* The assembly depends on these exact flags.  
+     For Darwin64 (when FLAG_RETURNS_STRUCT is set):
+       FLAG_RETURNS_FP indicates that the structure embeds FP data.
+       FLAG_RETURNS_128BITS signals a special struct size that is not
+       expanded for float content.  */
+  FLAG_RETURNS_128BITS	= 1 << (31-31), /* These go in cr7  */
+  FLAG_RETURNS_NOTHING	= 1 << (31-30),
+  FLAG_RETURNS_FP	= 1 << (31-29),
+  FLAG_RETURNS_64BITS	= 1 << (31-28),
+
+  FLAG_RETURNS_STRUCT	= 1 << (31-27), /* This goes in cr6  */
+
+  FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
+  FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI  */
+  FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
+  FLAG_RETVAL_REFERENCE = 1 << (31- 4)
+};
+
+/* About the DARWIN ABI.  */
+enum {
+  NUM_GPR_ARG_REGISTERS = 8,
+  NUM_FPR_ARG_REGISTERS = 13,
+  LINKAGE_AREA_GPRS = 6
+};
+
+enum { ASM_NEEDS_REGISTERS = 4 }; /* r28-r31 */
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments.
+   
+   m32/m64
+
+   The stack layout we want looks like this:
+
+   |   Return address from ffi_call_DARWIN      |	higher addresses
+   |--------------------------------------------|
+   |   Previous backchain pointer	4/8	|	stack pointer here
+   |--------------------------------------------|<+ <<<	on entry to
+   |   ASM_NEEDS_REGISTERS=r28-r31   4*(4/8)	| |	ffi_call_DARWIN
+   |--------------------------------------------| |
+   |   When we have any FP activity... the	| |
+   |   FPRs occupy NUM_FPR_ARG_REGISTERS slots	| |
+   |   here fp13 .. fp1 from high to low addr.	| |
+   ~						~ ~
+   |   Parameters      (at least 8*4/8=32/64)	| | NUM_GPR_ARG_REGISTERS
+   |--------------------------------------------| |
+   |   TOC=R2 (AIX) Reserved (Darwin)   4/8	| |
+   |--------------------------------------------| |	stack	|
+   |   Reserved                       2*4/8	| |	grows	|
+   |--------------------------------------------| |	down	V
+   |   Space for callee's LR		4/8	| |
+   |--------------------------------------------| |	lower addresses
+   |   Saved CR [low word for m64]      4/8	| |
+   |--------------------------------------------| |     stack pointer here
+   |   Current backchain pointer	4/8	|-/	during
+   |--------------------------------------------|   <<<	ffi_call_DARWIN
+
+   */
+
+#if defined(POWERPC_DARWIN64)
+static void
+darwin64_pass_struct_by_value 
+  (ffi_type *, char *, unsigned, unsigned *, double **, unsigned long **);
+#endif
+
+/* This depends on GPR_SIZE = sizeof (unsigned long) */
+
+void
+ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
+{
+  const unsigned bytes = ecif->cif->bytes;
+  const unsigned flags = ecif->cif->flags;
+  const unsigned nargs = ecif->cif->nargs;
+#if !defined(POWERPC_DARWIN64) 
+  const ffi_abi abi = ecif->cif->abi;
+#endif
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long));
+
+  /* 'fpr_base' points at the space for fpr1, and grows upwards as
+     we use FPR registers.  */
+  double *fpr_base = (double *) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
+  int gp_count = 0, fparg_count = 0;
+
+  /* 'next_arg' grows up as we put parameters in it.  */
+  unsigned long *next_arg = stack + LINKAGE_AREA_GPRS; /* 6 reserved positions.  */
+
+  int i;
+  double double_tmp;
+  void **p_argv = ecif->avalue;
+  unsigned long gprvalue;
+  ffi_type** ptr = ecif->cif->arg_types;
+#if !defined(POWERPC_DARWIN64) 
+  char *dest_cpy;
+#endif
+  unsigned size_al = 0;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT(((unsigned) (char *) stack & 0xF) == 0);
+  FFI_ASSERT(((unsigned) (char *) stacktop & 0xF) == 0);
+  FFI_ASSERT((bytes & 0xF) == 0);
+
+  /* Deal with return values that are actually pass-by-reference.
+     Rule:
+     Return values are referenced by r3, so r4 is the first parameter.  */
+
+  if (flags & FLAG_RETVAL_REFERENCE)
+    *next_arg++ = (unsigned long) (char *) ecif->rvalue;
+
+  /* Now for the arguments.  */
+  for (i = nargs; i > 0; i--, ptr++, p_argv++)
+    {
+      switch ((*ptr)->type)
+	{
+	/* If a floating-point parameter appears before all of the general-
+	   purpose registers are filled, the corresponding GPRs that match
+	   the size of the floating-point parameter are skipped.  */
+	case FFI_TYPE_FLOAT:
+	  double_tmp = *(float *) *p_argv;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS)
+	    *fpr_base++ = double_tmp;
+#if defined(POWERPC_DARWIN)
+	  *(float *)next_arg = *(float *) *p_argv;
+#else
+	  *(double *)next_arg = double_tmp;
+#endif
+	  next_arg++;
+	  gp_count++;
+	  fparg_count++;
+	  FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  double_tmp = *(double *) *p_argv;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS)
+	    *fpr_base++ = double_tmp;
+	  *(double *)next_arg = double_tmp;
+#ifdef POWERPC64
+	  next_arg++;
+	  gp_count++;
+#else
+	  next_arg += 2;
+	  gp_count += 2;
+#endif
+	  fparg_count++;
+	  FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+	  break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+	case FFI_TYPE_LONGDOUBLE:
+#  if defined(POWERPC64) && !defined(POWERPC_DARWIN64)
+	  /* ??? This will exceed the regs count when the value starts at fp13
+	     and it will not put the extra bit on the stack.  */
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS)
+	    *(long double *) fpr_base++ = *(long double *) *p_argv;
+	  else
+	    *(long double *) next_arg = *(long double *) *p_argv;
+	  next_arg += 2;
+	  fparg_count += 2;
+#  else
+	  double_tmp = ((double *) *p_argv)[0];
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS)
+	    *fpr_base++ = double_tmp;
+	  *(double *) next_arg = double_tmp;
+#    if defined(POWERPC_DARWIN64)
+	  next_arg++;
+	  gp_count++;
+#    else
+	  next_arg += 2;
+	  gp_count += 2;
+#    endif
+	  fparg_count++;
+	  double_tmp = ((double *) *p_argv)[1];
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS)
+	    *fpr_base++ = double_tmp;
+	  *(double *) next_arg = double_tmp;
+#    if defined(POWERPC_DARWIN64)
+	  next_arg++;
+	  gp_count++;
+#    else
+	  next_arg += 2;
+	  gp_count += 2;
+#    endif
+	  fparg_count++;
+#  endif
+	  FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+	  break;
+#endif
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+#ifdef POWERPC64
+	  gprvalue = *(long long *) *p_argv;
+	  goto putgpr;
+#else
+	  *(long long *) next_arg = *(long long *) *p_argv;
+	  next_arg += 2;
+	  gp_count += 2;
+#endif
+	  break;
+	case FFI_TYPE_POINTER:
+	  gprvalue = *(unsigned long *) *p_argv;
+	  goto putgpr;
+	case FFI_TYPE_UINT8:
+	  gprvalue = *(unsigned char *) *p_argv;
+	  goto putgpr;
+	case FFI_TYPE_SINT8:
+	  gprvalue = *(signed char *) *p_argv;
+	  goto putgpr;
+	case FFI_TYPE_UINT16:
+	  gprvalue = *(unsigned short *) *p_argv;
+	  goto putgpr;
+	case FFI_TYPE_SINT16:
+	  gprvalue = *(signed short *) *p_argv;
+	  goto putgpr;
+
+	case FFI_TYPE_STRUCT:
+	  size_al = (*ptr)->size;
+#if defined(POWERPC_DARWIN64)
+	  next_arg = (unsigned long *)ALIGN((char *)next_arg, (*ptr)->alignment);
+	  darwin64_pass_struct_by_value (*ptr, (char *) *p_argv, 
+					 (unsigned) size_al,
+					 (unsigned int *) &fparg_count,
+					 &fpr_base, &next_arg);
+#else
+	  dest_cpy = (char *) next_arg;
+
+	  /* If the first member of the struct is a double, then include enough
+	     padding in the struct size to align it to double-word.  */
+	  if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
+	    size_al = ALIGN((*ptr)->size, 8);
+
+#  if defined(POWERPC64) 
+	  FFI_ASSERT (abi != FFI_DARWIN);
+	  memcpy ((char *) dest_cpy, (char *) *p_argv, size_al);
+	  next_arg += (size_al + 7) / 8;
+#  else
+	  /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
+	     SI 4 bytes) are aligned as if they were those modes.
+	     Structures with 3 byte in size are padded upwards.  */
+	  if (size_al < 3 && abi == FFI_DARWIN)
+	    dest_cpy += 4 - size_al;
+
+	  memcpy((char *) dest_cpy, (char *) *p_argv, size_al);
+	  next_arg += (size_al + 3) / 4;
+#  endif
+#endif
+	  break;
+
+	case FFI_TYPE_INT:
+	case FFI_TYPE_SINT32:
+	  gprvalue = *(signed int *) *p_argv;
+	  goto putgpr;
+
+	case FFI_TYPE_UINT32:
+	  gprvalue = *(unsigned int *) *p_argv;
+	putgpr:
+	  *next_arg++ = gprvalue;
+	  gp_count++;
+	  break;
+	default:
+	  break;
+	}
+    }
+
+  /* Check that we didn't overrun the stack...  */
+  //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
+  //FFI_ASSERT((unsigned *)fpr_base
+  //	     <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+  //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
+}
+
+#if defined(POWERPC_DARWIN64)
+
+/* See if we can put some of the struct into fprs.
+   This should not be called for structures of size 16 bytes, since these are not
+   broken out this way.  */
+static void
+darwin64_scan_struct_for_floats (ffi_type *s, unsigned *nfpr)
+{
+  int i;
+
+  FFI_ASSERT (s->type == FFI_TYPE_STRUCT)
+
+  for (i = 0; s->elements[i] != NULL; i++)
+    {
+      ffi_type *p = s->elements[i];
+      switch (p->type)
+	{
+	  case FFI_TYPE_STRUCT:
+	    darwin64_scan_struct_for_floats (p, nfpr);
+	    break;
+	  case FFI_TYPE_LONGDOUBLE:
+	    (*nfpr) += 2;
+	    break;
+	  case FFI_TYPE_DOUBLE:
+	  case FFI_TYPE_FLOAT:
+	    (*nfpr) += 1;
+	    break;
+	  default:
+	    break;    
+	}
+    }
+}
+
+static int
+darwin64_struct_size_exceeds_gprs_p (ffi_type *s, char *src, unsigned *nfpr)
+{
+  unsigned struct_offset=0, i;
+
+  for (i = 0; s->elements[i] != NULL; i++)
+    {
+      char *item_base;
+      ffi_type *p = s->elements[i];
+      /* Find the start of this item (0 for the first one).  */
+      if (i > 0)
+        struct_offset = ALIGN(struct_offset, p->alignment);
+
+      item_base = src + struct_offset;
+
+      switch (p->type)
+	{
+	  case FFI_TYPE_STRUCT:
+	    if (darwin64_struct_size_exceeds_gprs_p (p, item_base, nfpr))
+	      return 1;
+	    break;
+	  case FFI_TYPE_LONGDOUBLE:
+	    if (*nfpr >= NUM_FPR_ARG_REGISTERS)
+	      return 1;
+	    (*nfpr) += 1;
+	    item_base += 8;
+	  /* FALL THROUGH */
+	  case FFI_TYPE_DOUBLE:
+	    if (*nfpr >= NUM_FPR_ARG_REGISTERS)
+	      return 1;
+	    (*nfpr) += 1;
+	    break;
+	  case FFI_TYPE_FLOAT:
+	    if (*nfpr >= NUM_FPR_ARG_REGISTERS)
+	      return 1;
+	    (*nfpr) += 1;
+	    break;
+	  default:
+	    /* If we try and place any item, that is non-float, once we've
+	       exceeded the 8 GPR mark, then we can't fit the struct.  */
+	    if ((unsigned long)item_base >= 8*8) 
+	      return 1;
+	    break;    
+	}
+      /* now count the size of what we just used.  */
+      struct_offset += p->size;
+    }
+  return 0;
+}
+
+/* Can this struct be returned by value?  */
+int 
+darwin64_struct_ret_by_value_p (ffi_type *s)
+{
+  unsigned nfp = 0;
+
+  FFI_ASSERT (s && s->type == FFI_TYPE_STRUCT);
+  
+  /* The largest structure we can return is 8long + 13 doubles.  */
+  if (s->size > 168)
+    return 0;
+  
+  /* We can't pass more than 13 floats.  */
+  darwin64_scan_struct_for_floats (s, &nfp);
+  if (nfp > 13)
+    return 0;
+  
+  /* If there are not too many floats, and the struct is
+     small enough to accommodate in the GPRs, then it must be OK.  */
+  if (s->size <= 64)
+    return 1;
+  
+  /* Well, we have to look harder.  */
+  nfp = 0;
+  if (darwin64_struct_size_exceeds_gprs_p (s, NULL, &nfp))
+    return 0;
+  
+  return 1;
+}
+
+void
+darwin64_pass_struct_floats (ffi_type *s, char *src, 
+			     unsigned *nfpr, double **fprs)
+{
+  int i;
+  double *fpr_base = *fprs;
+  unsigned struct_offset = 0;
+
+  /* We don't assume anything about the alignment of the source.  */
+  for (i = 0; s->elements[i] != NULL; i++)
+    {
+      char *item_base;
+      ffi_type *p = s->elements[i];
+      /* Find the start of this item (0 for the first one).  */
+      if (i > 0)
+        struct_offset = ALIGN(struct_offset, p->alignment);
+      item_base = src + struct_offset;
+
+      switch (p->type)
+	{
+	  case FFI_TYPE_STRUCT:
+	    darwin64_pass_struct_floats (p, item_base, nfpr,
+					   &fpr_base);
+	    break;
+	  case FFI_TYPE_LONGDOUBLE:
+	    if (*nfpr < NUM_FPR_ARG_REGISTERS)
+	      *fpr_base++ = *(double *)item_base;
+	    (*nfpr) += 1;
+	    item_base += 8;
+	  /* FALL THROUGH */
+	  case FFI_TYPE_DOUBLE:
+	    if (*nfpr < NUM_FPR_ARG_REGISTERS)
+	      *fpr_base++ = *(double *)item_base;
+	    (*nfpr) += 1;
+	    break;
+	  case FFI_TYPE_FLOAT:
+	    if (*nfpr < NUM_FPR_ARG_REGISTERS)
+	      *fpr_base++ = (double) *(float *)item_base;
+	    (*nfpr) += 1;
+	    break;
+	  default:
+	    break;    
+	}
+      /* now count the size of what we just used.  */
+      struct_offset += p->size;
+    }
+  /* Update the scores.  */
+  *fprs = fpr_base;
+}
+
+/* Darwin64 special rules.
+   Break out a struct into params and float registers.  */
+static void
+darwin64_pass_struct_by_value (ffi_type *s, char *src, unsigned size,
+			       unsigned *nfpr, double **fprs, unsigned long **arg)
+{
+  unsigned long *next_arg = *arg;
+  char *dest_cpy = (char *)next_arg;
+
+  FFI_ASSERT (s->type == FFI_TYPE_STRUCT)
+
+  if (!size)
+    return;
+
+  /* First... special cases.  */
+  if (size < 3
+      || (size == 4 
+	  && s->elements[0] 
+	  && s->elements[0]->type != FFI_TYPE_FLOAT))
+    {
+      /* Must be at least one GPR, padding is unspecified in value, 
+	 let's make it zero.  */
+      *next_arg = 0UL; 
+      dest_cpy += 8 - size;
+      memcpy ((char *) dest_cpy, src, size);
+      next_arg++;
+    }
+  else if (size == 16)
+    {
+      memcpy ((char *) dest_cpy, src, size);
+      next_arg += 2;
+    }
+  else
+    {
+      /* now the general case, we consider embedded floats.  */
+      memcpy ((char *) dest_cpy, src, size);
+      darwin64_pass_struct_floats (s, src, nfpr, fprs);
+      next_arg += (size+7)/8;
+    }
+    
+  *arg = next_arg;
+}
+
+double *
+darwin64_struct_floats_to_mem (ffi_type *s, char *dest, double *fprs, unsigned *nf)
+{
+  int i;
+  unsigned struct_offset = 0;
+
+  /* We don't assume anything about the alignment of the source.  */
+  for (i = 0; s->elements[i] != NULL; i++)
+    {
+      char *item_base;
+      ffi_type *p = s->elements[i];
+      /* Find the start of this item (0 for the first one).  */
+      if (i > 0)
+        struct_offset = ALIGN(struct_offset, p->alignment);
+      item_base = dest + struct_offset;
+
+      switch (p->type)
+	{
+	  case FFI_TYPE_STRUCT:
+	    fprs = darwin64_struct_floats_to_mem (p, item_base, fprs, nf);
+	    break;
+	  case FFI_TYPE_LONGDOUBLE:
+	    if (*nf < NUM_FPR_ARG_REGISTERS)
+	      {
+		*(double *)item_base = *fprs++ ;
+		(*nf) += 1;
+	      }
+	    item_base += 8;
+	  /* FALL THROUGH */
+	  case FFI_TYPE_DOUBLE:
+	    if (*nf < NUM_FPR_ARG_REGISTERS)
+	      {
+		*(double *)item_base = *fprs++ ;
+		(*nf) += 1;
+	      }
+	    break;
+	  case FFI_TYPE_FLOAT:
+	    if (*nf < NUM_FPR_ARG_REGISTERS)
+	      {
+		*(float *)item_base = (float) *fprs++ ;
+		(*nf) += 1;
+	      }
+	    break;
+	  default:
+	    break;    
+	}
+      /* now count the size of what we just used.  */
+      struct_offset += p->size;
+    }
+  return fprs;
+}
+
+#endif
+
+/* Adjust the size of S to be correct for Darwin.
+   On Darwin m32, the first field of a structure has natural alignment.  
+   On Darwin m64, all fields have natural alignment.  */
+
+static void
+darwin_adjust_aggregate_sizes (ffi_type *s)
+{
+  int i;
+
+  if (s->type != FFI_TYPE_STRUCT)
+    return;
+
+  s->size = 0;
+  for (i = 0; s->elements[i] != NULL; i++)
+    {
+      ffi_type *p;
+      int align;
+      
+      p = s->elements[i];
+      if (p->type == FFI_TYPE_STRUCT)
+	darwin_adjust_aggregate_sizes (p);
+#if defined(POWERPC_DARWIN64)
+      /* Natural alignment for all items.  */
+      align = p->alignment;
+#else
+      /* Natrual alignment for the first item... */
+      if (i == 0)
+	align = p->alignment;
+      else if (p->alignment == 16 || p->alignment < 4)
+	/* .. subsequent items with vector or align < 4 have natural align.  */
+	align = p->alignment;
+      else
+	/* .. or align is 4.  */
+	align = 4;
+#endif
+      /* Pad, if necessary, before adding the current item.  */
+      s->size = ALIGN(s->size, align) + p->size;
+    }
+  
+  s->size = ALIGN(s->size, s->alignment);
+  
+  /* This should not be necessary on m64, but harmless.  */
+  if (s->elements[0]->type == FFI_TYPE_UINT64
+      || s->elements[0]->type == FFI_TYPE_SINT64
+      || s->elements[0]->type == FFI_TYPE_DOUBLE
+      || s->elements[0]->alignment == 8)
+    s->alignment = s->alignment > 8 ? s->alignment : 8;
+  /* Do not add additional tail padding.  */
+}
+
+/* Adjust the size of S to be correct for AIX.
+   Word-align double unless it is the first member of a structure.  */
+
+static void
+aix_adjust_aggregate_sizes (ffi_type *s)
+{
+  int i;
+
+  if (s->type != FFI_TYPE_STRUCT)
+    return;
+
+  s->size = 0;
+  for (i = 0; s->elements[i] != NULL; i++)
+    {
+      ffi_type *p;
+      int align;
+      
+      p = s->elements[i];
+      aix_adjust_aggregate_sizes (p);
+      align = p->alignment;
+      if (i != 0 && p->type == FFI_TYPE_DOUBLE)
+	align = 4;
+      s->size = ALIGN(s->size, align) + p->size;
+    }
+  
+  s->size = ALIGN(s->size, s->alignment);
+  
+  if (s->elements[0]->type == FFI_TYPE_UINT64
+      || s->elements[0]->type == FFI_TYPE_SINT64
+      || s->elements[0]->type == FFI_TYPE_DOUBLE
+      || s->elements[0]->alignment == 8)
+    s->alignment = s->alignment > 8 ? s->alignment : 8;
+  /* Do not add additional tail padding.  */
+}
+
+/* Perform machine dependent cif processing.  */
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  /* All this is for the DARWIN ABI.  */
+  unsigned i;
+  ffi_type **ptr;
+  unsigned bytes;
+  unsigned fparg_count = 0, intarg_count = 0;
+  unsigned flags = 0;
+  unsigned size_al = 0;
+
+  /* All the machine-independent calculation of cif->bytes will be wrong.
+     All the calculation of structure sizes will also be wrong.
+     Redo the calculation for DARWIN.  */
+
+  if (cif->abi == FFI_DARWIN)
+    {
+      darwin_adjust_aggregate_sizes (cif->rtype);
+      for (i = 0; i < cif->nargs; i++)
+	darwin_adjust_aggregate_sizes (cif->arg_types[i]);
+    }
+
+  if (cif->abi == FFI_AIX)
+    {
+      aix_adjust_aggregate_sizes (cif->rtype);
+      for (i = 0; i < cif->nargs; i++)
+	aix_adjust_aggregate_sizes (cif->arg_types[i]);
+    }
+
+  /* Space for the frame pointer, callee's LR, CR, etc, and for
+     the asm's temp regs.  */
+
+  bytes = (LINKAGE_AREA_GPRS + ASM_NEEDS_REGISTERS) * sizeof(unsigned long);
+
+  /* Return value handling.  
+    The rules m32 are as follows:
+     - 32-bit (or less) integer values are returned in gpr3;
+     - structures of size <= 4 bytes also returned in gpr3;
+     - 64-bit integer values [??? and structures between 5 and 8 bytes] are
+       returned in gpr3 and gpr4;
+     - Single/double FP values are returned in fpr1;
+     - Long double FP (if not equivalent to double) values are returned in
+       fpr1 and fpr2;
+     m64:
+     - 64-bit or smaller integral values are returned in GPR3
+     - Single/double FP values are returned in fpr1;
+     - Long double FP values are returned in fpr1 and fpr2;
+     m64 Structures:
+     - If the structure could be accommodated in registers were it to be the
+       first argument to a routine, then it is returned in those registers.
+     m32/m64 structures otherwise:
+     - Larger structures values are allocated space and a pointer is passed
+       as the first argument.  */
+  switch (cif->rtype->type)
+    {
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+      flags |= FLAG_RETURNS_128BITS;
+      flags |= FLAG_RETURNS_FP;
+      break;
+#endif
+
+    case FFI_TYPE_DOUBLE:
+      flags |= FLAG_RETURNS_64BITS;
+      /* Fall through.  */
+    case FFI_TYPE_FLOAT:
+      flags |= FLAG_RETURNS_FP;
+      break;
+
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+#ifdef POWERPC64
+    case FFI_TYPE_POINTER:
+#endif
+      flags |= FLAG_RETURNS_64BITS;
+      break;
+
+    case FFI_TYPE_STRUCT:
+#if defined(POWERPC_DARWIN64)
+      {
+	/* Can we fit the struct into regs?  */
+	if (darwin64_struct_ret_by_value_p (cif->rtype))
+	  {
+	    unsigned nfpr = 0;
+	    flags |= FLAG_RETURNS_STRUCT;
+	    if (cif->rtype->size != 16)
+	      darwin64_scan_struct_for_floats (cif->rtype, &nfpr) ;
+	    else
+	      flags |= FLAG_RETURNS_128BITS;
+	    /* Will be 0 for 16byte struct.  */
+	    if (nfpr)
+	      flags |= FLAG_RETURNS_FP;
+	  }
+	else /* By ref. */
+	  {
+	    flags |= FLAG_RETVAL_REFERENCE;
+	    flags |= FLAG_RETURNS_NOTHING;
+	    intarg_count++;
+	  }
+      }
+#elif defined(DARWIN_PPC)
+      if (cif->rtype->size <= 4)
+	flags |= FLAG_RETURNS_STRUCT;
+      else /* else by reference.  */
+	{
+	  flags |= FLAG_RETVAL_REFERENCE;
+	  flags |= FLAG_RETURNS_NOTHING;
+	  intarg_count++;
+	}
+#else /* assume we pass by ref.  */
+      flags |= FLAG_RETVAL_REFERENCE;
+      flags |= FLAG_RETURNS_NOTHING;
+      intarg_count++;
+#endif
+      break;
+    case FFI_TYPE_VOID:
+      flags |= FLAG_RETURNS_NOTHING;
+      break;
+
+    default:
+      /* Returns 32-bit integer, or similar.  Nothing to do here.  */
+      break;
+    }
+
+  /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
+     first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
+     goes on the stack.  
+     ??? Structures are passed as a pointer to a copy of the structure. 
+     Stuff on the stack needs to keep proper alignment.  
+     For m64 the count is effectively of half-GPRs.  */
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+      unsigned align_words;
+      switch ((*ptr)->type)
+	{
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+	  fparg_count++;
+#if !defined(POWERPC_DARWIN64)
+	  /* If this FP arg is going on the stack, it must be
+	     8-byte-aligned.  */
+	  if (fparg_count > NUM_FPR_ARG_REGISTERS
+	      && (intarg_count & 0x01) != 0)
+	    intarg_count++;
+#endif
+	  break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  fparg_count += 2;
+	  /* If this FP arg is going on the stack, it must be
+	     16-byte-aligned.  */
+	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+#if defined (POWERPC64)
+	    intarg_count = ALIGN(intarg_count, 2);
+#else
+	    intarg_count = ALIGN(intarg_count, 4);
+#endif
+	  break;
+#endif
+
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+#if defined(POWERPC64)
+	  intarg_count++;
+#else
+	  /* 'long long' arguments are passed as two words, but
+	     either both words must fit in registers or both go
+	     on the stack.  If they go on the stack, they must
+	     be 8-byte-aligned.  */
+	  if (intarg_count == NUM_GPR_ARG_REGISTERS-1
+	      || (intarg_count >= NUM_GPR_ARG_REGISTERS 
+	          && (intarg_count & 0x01) != 0))
+	    intarg_count++;
+	  intarg_count += 2;
+#endif
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  size_al = (*ptr)->size;
+#if defined(POWERPC_DARWIN64)
+	  align_words = (*ptr)->alignment >> 3;
+	  if (align_words)
+	    intarg_count = ALIGN(intarg_count, align_words);
+	  /* Base size of the struct.  */
+	  intarg_count += (size_al + 7) / 8;
+	  /* If 16 bytes then don't worry about floats.  */
+	  if (size_al != 16)
+	    /* Scan through for floats to be placed in regs.  */
+	    darwin64_scan_struct_for_floats (*ptr, &fparg_count) ;
+#else
+	  align_words = (*ptr)->alignment >> 2;
+	  if (align_words)
+	    intarg_count = ALIGN(intarg_count, align_words);
+	  /* If the first member of the struct is a double, then align
+	     the struct to double-word. 
+	  if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
+	    size_al = ALIGN((*ptr)->size, 8); */
+#  ifdef POWERPC64
+	  intarg_count += (size_al + 7) / 8;
+#  else
+	  intarg_count += (size_al + 3) / 4;
+#  endif
+#endif
+	  break;
+
+	default:
+	  /* Everything else is passed as a 4-byte word in a GPR, either
+	     the object itself or a pointer to it.  */
+	  intarg_count++;
+	  break;
+	}
+    }
+
+  if (fparg_count != 0)
+    flags |= FLAG_FP_ARGUMENTS;
+
+#if defined(POWERPC_DARWIN64)
+  /* Space to image the FPR registers, if needed - which includes when they might be
+     used in a struct return.  */
+  if (fparg_count != 0 
+      || ((flags & FLAG_RETURNS_STRUCT)
+	   && (flags & FLAG_RETURNS_FP)))
+    bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
+#else
+  /* Space for the FPR registers, if needed.  */
+  if (fparg_count != 0)
+    bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
+#endif
+
+  /* Stack space.  */
+#ifdef POWERPC64
+  if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS)
+    bytes += (intarg_count + fparg_count) * sizeof(long);
+#else
+  if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
+    bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
+#endif
+  else
+    bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
+
+  /* The stack space allocated needs to be a multiple of 16 bytes.  */
+  bytes = ALIGN(bytes, 16) ;
+
+  cif->flags = flags;
+  cif->bytes = bytes;
+
+  return FFI_OK;
+}
+
+extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *,
+			 void (*fn)(void), void (*fn2)(void));
+
+extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *,
+			    void (*fn)(void), void (*fn2)(void), ffi_type*);
+
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have a return
+     value address then we need to make one.  */
+
+  if ((rvalue == NULL) &&
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca (cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi)
+    {
+    case FFI_AIX:
+      ffi_call_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
+		   FFI_FN(ffi_prep_args));
+      break;
+    case FFI_DARWIN:
+      ffi_call_DARWIN(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
+		      FFI_FN(ffi_prep_args), cif->rtype);
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+static void flush_icache(char *);
+static void flush_range(char *, int);
+
+/* The layout of a function descriptor.  A C function pointer really
+   points to one of these.  */
+
+typedef struct aix_fd_struct {
+  void *code_pointer;
+  void *toc;
+} aix_fd;
+
+/* here I'd like to add the stack frame layout we use in darwin_closure.S
+   and aix_closure.S
+
+   m32/m64
+
+   The stack layout looks like this:
+
+   |   Additional params...			| |     Higher address
+   ~						~ ~
+   |   Parameters      (at least 8*4/8=32/64)	| | NUM_GPR_ARG_REGISTERS
+   |--------------------------------------------| |
+   |   TOC=R2 (AIX) Reserved (Darwin)   4/8	| |
+   |--------------------------------------------| |
+   |   Reserved                       2*4/8	| |
+   |--------------------------------------------| |
+   |   Space for callee's LR		4/8	| |
+   |--------------------------------------------| |
+   |   Saved CR [low word for m64]      4/8	| |
+   |--------------------------------------------| |
+   |   Current backchain pointer	4/8	|-/ Parent's frame.
+   |--------------------------------------------| <+ <<< on entry to ffi_closure_ASM
+   |   Result Bytes			16	| |
+   |--------------------------------------------| |
+   ~   padding to 16-byte alignment		~ ~
+   |--------------------------------------------| |
+   |   NUM_FPR_ARG_REGISTERS slots		| |
+   |   here fp13 .. fp1		       13*8	| |
+   |--------------------------------------------| |
+   |   R3..R10			  8*4/8=32/64	| | NUM_GPR_ARG_REGISTERS
+   |--------------------------------------------| |
+   |   TOC=R2 (AIX) Reserved (Darwin)   4/8	| |
+   |--------------------------------------------| |	stack	|
+   |   Reserved [compiler,binder]     2*4/8	| |	grows	|
+   |--------------------------------------------| |	down	V
+   |   Space for callee's LR		4/8	| |
+   |--------------------------------------------| |	lower addresses
+   |   Saved CR [low word for m64]      4/8	| |
+   |--------------------------------------------| |     stack pointer here
+   |   Current backchain pointer	4/8	|-/	during
+   |--------------------------------------------|   <<<	ffi_closure_ASM.
+
+*/
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  unsigned int *tramp;
+  struct ffi_aix_trampoline_struct *tramp_aix;
+  aix_fd *fd;
+
+  switch (cif->abi)
+    {
+      case FFI_DARWIN:
+
+	FFI_ASSERT (cif->abi == FFI_DARWIN);
+
+	tramp = (unsigned int *) &closure->tramp[0];
+#if defined(POWERPC_DARWIN64)
+	tramp[0] = 0x7c0802a6;  /*   mflr    r0  */
+	tramp[1] = 0x429f0015;  /*   bcl-    20,4*cr7+so,  +0x18 (L1)  */
+	/* We put the addresses here.  */
+	tramp[6] = 0x7d6802a6;  /*L1:   mflr    r11  */
+	tramp[7] = 0xe98b0000;  /*   ld     r12,0(r11) function address  */
+	tramp[8] = 0x7c0803a6;  /*   mtlr    r0   */
+	tramp[9] = 0x7d8903a6;  /*   mtctr   r12  */
+	tramp[10] = 0xe96b0008;  /*   lwz     r11,8(r11) static chain  */
+	tramp[11] = 0x4e800420;  /*   bctr  */
+
+	*((unsigned long *)&tramp[2]) = (unsigned long) ffi_closure_ASM; /* function  */
+	*((unsigned long *)&tramp[4]) = (unsigned long) codeloc; /* context  */
+#else
+	tramp[0] = 0x7c0802a6;  /*   mflr    r0  */
+	tramp[1] = 0x429f000d;  /*   bcl-    20,4*cr7+so,0x10  */
+	tramp[4] = 0x7d6802a6;  /*   mflr    r11  */
+	tramp[5] = 0x818b0000;  /*   lwz     r12,0(r11) function address  */
+	tramp[6] = 0x7c0803a6;  /*   mtlr    r0   */
+	tramp[7] = 0x7d8903a6;  /*   mtctr   r12  */
+	tramp[8] = 0x816b0004;  /*   lwz     r11,4(r11) static chain  */
+	tramp[9] = 0x4e800420;  /*   bctr  */
+	tramp[2] = (unsigned long) ffi_closure_ASM; /* function  */
+	tramp[3] = (unsigned long) codeloc; /* context  */
+#endif
+	closure->cif = cif;
+	closure->fun = fun;
+	closure->user_data = user_data;
+
+	/* Flush the icache. Only necessary on Darwin.  */
+	flush_range(codeloc, FFI_TRAMPOLINE_SIZE);
+
+	break;
+
+    case FFI_AIX:
+
+      tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
+      fd = (aix_fd *)(void *)ffi_closure_ASM;
+
+      FFI_ASSERT (cif->abi == FFI_AIX);
+
+      tramp_aix->code_pointer = fd->code_pointer;
+      tramp_aix->toc = fd->toc;
+      tramp_aix->static_chain = codeloc;
+      closure->cif = cif;
+      closure->fun = fun;
+      closure->user_data = user_data;
+      break;
+
+    default:
+      return FFI_BAD_ABI;
+      break;
+    }
+  return FFI_OK;
+}
+
+static void
+flush_icache(char *addr)
+{
+#ifndef _AIX
+  __asm__ volatile (
+		"dcbf 0,%0\n"
+		"\tsync\n"
+		"\ticbi 0,%0\n"
+		"\tsync\n"
+		"\tisync"
+		: : "r"(addr) : "memory");
+#endif
+}
+
+static void
+flush_range(char * addr1, int size)
+{
+#define MIN_LINE_SIZE 32
+  int i;
+  for (i = 0; i < size; i += MIN_LINE_SIZE)
+    flush_icache(addr1+i);
+  flush_icache(addr1+size-1);
+}
+
+typedef union
+{
+  float f;
+  double d;
+} ffi_dblfl;
+
+ffi_type *
+ffi_closure_helper_DARWIN (ffi_closure *, void *,
+			   unsigned long *, ffi_dblfl *);
+
+/* Basically the trampoline invokes ffi_closure_ASM, and on
+   entry, r11 holds the address of the closure.
+   After storing the registers that could possibly contain
+   parameters to be passed into the stack frame and setting
+   up space for a return value, ffi_closure_ASM invokes the
+   following helper function to do most of the work.  */
+
+ffi_type *
+ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
+			   unsigned long *pgr, ffi_dblfl *pfr)
+{
+  /* rvalue is the pointer to space for return value in closure assembly
+     pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
+     pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM.  */
+
+  typedef double ldbits[2];
+
+  union ldu
+  {
+    ldbits lb;
+    long double ld;
+  };
+
+  void **          avalue;
+  ffi_type **      arg_types;
+  long             i, avn;
+  ffi_cif *        cif;
+  ffi_dblfl *      end_pfr = pfr + NUM_FPR_ARG_REGISTERS;
+  unsigned         size_al;
+#if defined(POWERPC_DARWIN64)
+  unsigned 	   fpsused = 0;
+#endif
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof(void *));
+
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+#if defined(POWERPC_DARWIN64)
+      if (!darwin64_struct_ret_by_value_p (cif->rtype))
+	{
+    	  /* Won't fit into the regs - return by ref.  */
+	  rvalue = (void *) *pgr;
+	  pgr++;
+	}
+#elif defined(DARWIN_PPC)
+      if (cif->rtype->size > 4)
+	{
+	  rvalue = (void *) *pgr;
+	  pgr++;
+	}
+#else /* assume we return by ref.  */
+      rvalue = (void *) *pgr;
+      pgr++;
+#endif
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  while (i < avn)
+    {
+      switch (arg_types[i]->type)
+	{
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+#if  defined(POWERPC64)
+	  avalue[i] = (char *) pgr + 7;
+#else
+	  avalue[i] = (char *) pgr + 3;
+#endif
+	  pgr++;
+	  break;
+
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+#if  defined(POWERPC64)
+	  avalue[i] = (char *) pgr + 6;
+#else
+	  avalue[i] = (char *) pgr + 2;
+#endif
+	  pgr++;
+	  break;
+
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+#if  defined(POWERPC64)
+	  avalue[i] = (char *) pgr + 4;
+#else
+	case FFI_TYPE_POINTER:
+	  avalue[i] = pgr;
+#endif
+	  pgr++;
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  size_al = arg_types[i]->size;
+#if defined(POWERPC_DARWIN64)
+	  pgr = (unsigned long *)ALIGN((char *)pgr, arg_types[i]->alignment);
+	  if (size_al < 3 || size_al == 4)
+	    {
+	      avalue[i] = ((char *)pgr)+8-size_al;
+	      if (arg_types[i]->elements[0]->type == FFI_TYPE_FLOAT
+		  && fpsused < NUM_FPR_ARG_REGISTERS)
+		{
+		  *(float *)pgr = (float) *(double *)pfr;
+		  pfr++;
+		  fpsused++;
+		}
+	    }
+	  else 
+	    {
+	      if (size_al != 16)
+		pfr = (ffi_dblfl *) 
+		    darwin64_struct_floats_to_mem (arg_types[i], (char *)pgr,
+						   (double *)pfr, &fpsused);
+	      avalue[i] = pgr;
+	    }
+	  pgr += (size_al + 7) / 8;
+#else
+	  /* If the first member of the struct is a double, then align
+	     the struct to double-word.  */
+	  if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
+	    size_al = ALIGN(arg_types[i]->size, 8);
+#  if defined(POWERPC64)
+	  FFI_ASSERT (cif->abi != FFI_DARWIN);
+	  avalue[i] = pgr;
+	  pgr += (size_al + 7) / 8;
+#  else
+	  /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
+	     SI 4 bytes) are aligned as if they were those modes.  */
+	  if (size_al < 3 && cif->abi == FFI_DARWIN)
+	    avalue[i] = (char*) pgr + 4 - size_al;
+	  else
+	    avalue[i] = pgr;
+	  pgr += (size_al + 3) / 4;
+#  endif
+#endif
+	  break;
+
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+#if  defined(POWERPC64)
+	case FFI_TYPE_POINTER:
+	  avalue[i] = pgr;
+	  pgr++;
+	  break;
+#else
+	  /* Long long ints are passed in two gpr's.  */
+	  avalue[i] = pgr;
+	  pgr += 2;
+	  break;
+#endif
+
+	case FFI_TYPE_FLOAT:
+	  /* A float value consumes a GPR.
+	     There are 13 64bit floating point registers.  */
+	  if (pfr < end_pfr)
+	    {
+	      double temp = pfr->d;
+	      pfr->f = (float) temp;
+	      avalue[i] = pfr;
+	      pfr++;
+	    }
+	  else
+	    {
+	      avalue[i] = pgr;
+	    }
+	  pgr++;
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  /* A double value consumes two GPRs.
+	     There are 13 64bit floating point registers.  */
+	  if (pfr < end_pfr)
+	    {
+	      avalue[i] = pfr;
+	      pfr++;
+	    }
+	  else
+	    {
+	      avalue[i] = pgr;
+	    }
+#ifdef POWERPC64
+	  pgr++;
+#else
+	  pgr += 2;
+#endif
+	  break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+	case FFI_TYPE_LONGDOUBLE:
+#ifdef POWERPC64
+	  if (pfr + 1 < end_pfr)
+	    {
+	      avalue[i] = pfr;
+	      pfr += 2;
+	    }
+	  else
+	    {
+	      if (pfr < end_pfr)
+		{
+		  *pgr = *(unsigned long *) pfr;
+		  pfr++;
+		}
+	      avalue[i] = pgr;
+	    }
+	  pgr += 2;
+#else  /* POWERPC64 */
+	  /* A long double value consumes four GPRs and two FPRs.
+	     There are 13 64bit floating point registers.  */
+	  if (pfr + 1 < end_pfr)
+	    {
+	      avalue[i] = pfr;
+	      pfr += 2;
+	    }
+	  /* Here we have the situation where one part of the long double
+	     is stored in fpr13 and the other part is already on the stack.
+	     We use a union to pass the long double to avalue[i].  */
+	  else if (pfr + 1 == end_pfr)
+	    {
+	      union ldu temp_ld;
+	      memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
+	      memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
+	      avalue[i] = &temp_ld.ld;
+	      pfr++;
+	    }
+	  else
+	    {
+	      avalue[i] = pgr;
+	    }
+	  pgr += 4;
+#endif  /* POWERPC64 */
+	  break;
+#endif
+	default:
+	  FFI_ASSERT(0);
+	}
+      i++;
+    }
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_ASM to perform return type promotions.  */
+  return cif->rtype;
+}
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffi_linux64.c b/third_party/gofrontend/libffi/src/powerpc/ffi_linux64.c
new file mode 100644
index 0000000..33f24b3
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/ffi_linux64.c
@@ -0,0 +1,942 @@
+/* -----------------------------------------------------------------------
+   ffi_linux64.c - Copyright (C) 2013 IBM
+                   Copyright (C) 2011 Anthony Green
+                   Copyright (C) 2011 Kyle Moffett
+                   Copyright (C) 2008 Red Hat, Inc
+                   Copyright (C) 2007, 2008 Free Software Foundation, Inc
+                   Copyright (c) 1998 Geoffrey Keating
+
+   PowerPC Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include "ffi.h"
+
+#ifdef POWERPC64
+#include "ffi_common.h"
+#include "ffi_powerpc.h"
+
+
+/* About the LINUX64 ABI.  */
+enum {
+  NUM_GPR_ARG_REGISTERS64 = 8,
+  NUM_FPR_ARG_REGISTERS64 = 13
+};
+enum { ASM_NEEDS_REGISTERS64 = 4 };
+
+
+#if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+/* Adjust size of ffi_type_longdouble.  */
+void FFI_HIDDEN
+ffi_prep_types_linux64 (ffi_abi abi)
+{
+  if ((abi & (FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128)) == FFI_LINUX)
+    {
+      ffi_type_longdouble.size = 8;
+      ffi_type_longdouble.alignment = 8;
+    }
+  else
+    {
+      ffi_type_longdouble.size = 16;
+      ffi_type_longdouble.alignment = 16;
+    }
+}
+#endif
+
+
+#if _CALL_ELF == 2
+static unsigned int
+discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
+{
+  switch (t->type)
+    {
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      *elnum = 1;
+      return (int) t->type;
+
+    case FFI_TYPE_STRUCT:;
+      {
+	unsigned int base_elt = 0, total_elnum = 0;
+	ffi_type **el = t->elements;
+	while (*el)
+	  {
+	    unsigned int el_elt, el_elnum = 0;
+	    el_elt = discover_homogeneous_aggregate (*el, &el_elnum);
+	    if (el_elt == 0
+		|| (base_elt && base_elt != el_elt))
+	      return 0;
+	    base_elt = el_elt;
+	    total_elnum += el_elnum;
+	    if (total_elnum > 8)
+	      return 0;
+	    el++;
+	  }
+	*elnum = total_elnum;
+	return base_elt;
+      }
+
+    default:
+      return 0;
+    }
+}
+#endif
+
+
+/* Perform machine dependent cif processing */
+static ffi_status
+ffi_prep_cif_linux64_core (ffi_cif *cif)
+{
+  ffi_type **ptr;
+  unsigned bytes;
+  unsigned i, fparg_count = 0, intarg_count = 0;
+  unsigned flags = cif->flags;
+#if _CALL_ELF == 2
+  unsigned int elt, elnum;
+#endif
+
+#if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE
+  /* If compiled without long double support..  */
+  if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
+    return FFI_BAD_ABI;
+#endif
+
+  /* The machine-independent calculation of cif->bytes doesn't work
+     for us.  Redo the calculation.  */
+#if _CALL_ELF == 2
+  /* Space for backchain, CR, LR, TOC and the asm's temp regs.  */
+  bytes = (4 + ASM_NEEDS_REGISTERS64) * sizeof (long);
+
+  /* Space for the general registers.  */
+  bytes += NUM_GPR_ARG_REGISTERS64 * sizeof (long);
+#else
+  /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
+     regs.  */
+  bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long);
+
+  /* Space for the mandatory parm save area and general registers.  */
+  bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
+#endif
+
+  /* Return value handling.  */
+  switch (cif->rtype->type)
+    {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+      if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
+	flags |= FLAG_RETURNS_128BITS;
+      /* Fall through.  */
+#endif
+    case FFI_TYPE_DOUBLE:
+      flags |= FLAG_RETURNS_64BITS;
+      /* Fall through.  */
+    case FFI_TYPE_FLOAT:
+      flags |= FLAG_RETURNS_FP;
+      break;
+
+    case FFI_TYPE_UINT128:
+      flags |= FLAG_RETURNS_128BITS;
+      /* Fall through.  */
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      flags |= FLAG_RETURNS_64BITS;
+      break;
+
+    case FFI_TYPE_STRUCT:
+#if _CALL_ELF == 2
+      elt = discover_homogeneous_aggregate (cif->rtype, &elnum);
+      if (elt)
+	{
+	  if (elt == FFI_TYPE_DOUBLE)
+	    flags |= FLAG_RETURNS_64BITS;
+	  flags |= FLAG_RETURNS_FP | FLAG_RETURNS_SMST;
+	  break;
+	}
+      if (cif->rtype->size <= 16)
+	{
+	  flags |= FLAG_RETURNS_SMST;
+	  break;
+	}
+#endif
+      intarg_count++;
+      flags |= FLAG_RETVAL_REFERENCE;
+      /* Fall through.  */
+    case FFI_TYPE_VOID:
+      flags |= FLAG_RETURNS_NOTHING;
+      break;
+
+    default:
+      /* Returns 32-bit integer, or similar.  Nothing to do here.  */
+      break;
+    }
+
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+      unsigned int align;
+
+      switch ((*ptr)->type)
+	{
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
+	    {
+	      fparg_count++;
+	      intarg_count++;
+	    }
+	  /* Fall through.  */
+#endif
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_FLOAT:
+	  fparg_count++;
+	  intarg_count++;
+	  if (fparg_count > NUM_FPR_ARG_REGISTERS64)
+	    flags |= FLAG_ARG_NEEDS_PSAVE;
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  if ((cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0)
+	    {
+	      align = (*ptr)->alignment;
+	      if (align > 16)
+		align = 16;
+	      align = align / 8;
+	      if (align > 1)
+		intarg_count = ALIGN (intarg_count, align);
+	    }
+	  intarg_count += ((*ptr)->size + 7) / 8;
+#if _CALL_ELF == 2
+	  elt = discover_homogeneous_aggregate (*ptr, &elnum);
+	  if (elt)
+	    {
+	      fparg_count += elnum;
+	      if (fparg_count > NUM_FPR_ARG_REGISTERS64)
+		flags |= FLAG_ARG_NEEDS_PSAVE;
+	    }
+	  else
+#endif
+	    {
+	      if (intarg_count > NUM_GPR_ARG_REGISTERS64)
+		flags |= FLAG_ARG_NEEDS_PSAVE;
+	    }
+	  break;
+
+	case FFI_TYPE_POINTER:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_INT:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT8:
+	  /* Everything else is passed as a 8-byte word in a GPR, either
+	     the object itself or a pointer to it.  */
+	  intarg_count++;
+	  if (intarg_count > NUM_GPR_ARG_REGISTERS64)
+	    flags |= FLAG_ARG_NEEDS_PSAVE;
+	  break;
+	default:
+	  FFI_ASSERT (0);
+	}
+    }
+
+  if (fparg_count != 0)
+    flags |= FLAG_FP_ARGUMENTS;
+  if (intarg_count > 4)
+    flags |= FLAG_4_GPR_ARGUMENTS;
+
+  /* Space for the FPR registers, if needed.  */
+  if (fparg_count != 0)
+    bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
+
+  /* Stack space.  */
+#if _CALL_ELF == 2
+  if ((flags & FLAG_ARG_NEEDS_PSAVE) != 0)
+    bytes += intarg_count * sizeof (long);
+#else
+  if (intarg_count > NUM_GPR_ARG_REGISTERS64)
+    bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long);
+#endif
+
+  /* The stack space allocated needs to be a multiple of 16 bytes.  */
+  bytes = (bytes + 15) & ~0xF;
+
+  cif->flags = flags;
+  cif->bytes = bytes;
+
+  return FFI_OK;
+}
+
+ffi_status FFI_HIDDEN
+ffi_prep_cif_linux64 (ffi_cif *cif)
+{
+  if ((cif->abi & FFI_LINUX) != 0)
+    cif->nfixedargs = cif->nargs;
+#if _CALL_ELF != 2
+  else if (cif->abi == FFI_COMPAT_LINUX64)
+    {
+      /* This call is from old code.  Don't touch cif->nfixedargs
+	 since old code will be using a smaller cif.  */
+      cif->flags |= FLAG_COMPAT;
+      /* Translate to new abi value.  */
+      cif->abi = FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128;
+    }
+#endif
+  else
+    return FFI_BAD_ABI;
+  return ffi_prep_cif_linux64_core (cif);
+}
+
+ffi_status FFI_HIDDEN
+ffi_prep_cif_linux64_var (ffi_cif *cif,
+			  unsigned int nfixedargs,
+			  unsigned int ntotalargs MAYBE_UNUSED)
+{
+  if ((cif->abi & FFI_LINUX) != 0)
+    cif->nfixedargs = nfixedargs;
+#if _CALL_ELF != 2
+  else if (cif->abi == FFI_COMPAT_LINUX64)
+    {
+      /* This call is from old code.  Don't touch cif->nfixedargs
+	 since old code will be using a smaller cif.  */
+      cif->flags |= FLAG_COMPAT;
+      /* Translate to new abi value.  */
+      cif->abi = FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128;
+    }
+#endif
+  else
+    return FFI_BAD_ABI;
+#if _CALL_ELF == 2
+  cif->flags |= FLAG_ARG_NEEDS_PSAVE;
+#endif
+  return ffi_prep_cif_linux64_core (cif);
+}
+
+
+/* ffi_prep_args64 is called by the assembly routine once stack space
+   has been allocated for the function's arguments.
+
+   The stack layout we want looks like this:
+
+   |   Ret addr from ffi_call_LINUX64	8bytes	|	higher addresses
+   |--------------------------------------------|
+   |   CR save area			8bytes	|
+   |--------------------------------------------|
+   |   Previous backchain pointer	8	|	stack pointer here
+   |--------------------------------------------|<+ <<<	on entry to
+   |   Saved r28-r31			4*8	| |	ffi_call_LINUX64
+   |--------------------------------------------| |
+   |   GPR registers r3-r10		8*8	| |
+   |--------------------------------------------| |
+   |   FPR registers f1-f13 (optional)	13*8	| |
+   |--------------------------------------------| |
+   |   Parameter save area		        | |
+   |--------------------------------------------| |
+   |   TOC save area			8	| |
+   |--------------------------------------------| |	stack	|
+   |   Linker doubleword		8	| |	grows	|
+   |--------------------------------------------| |	down	V
+   |   Compiler doubleword		8	| |
+   |--------------------------------------------| |	lower addresses
+   |   Space for callee's LR		8	| |
+   |--------------------------------------------| |
+   |   CR save area			8	| |
+   |--------------------------------------------| |	stack pointer here
+   |   Current backchain pointer	8	|-/	during
+   |--------------------------------------------|   <<<	ffi_call_LINUX64
+
+*/
+
+void FFI_HIDDEN
+ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
+{
+  const unsigned long bytes = ecif->cif->bytes;
+  const unsigned long flags = ecif->cif->flags;
+
+  typedef union
+  {
+    char *c;
+    unsigned long *ul;
+    float *f;
+    double *d;
+    size_t p;
+  } valp;
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  valp stacktop;
+
+  /* 'next_arg' points at the space for gpr3, and grows upwards as
+     we use GPR registers, then continues at rest.  */
+  valp gpr_base;
+  valp gpr_end;
+  valp rest;
+  valp next_arg;
+
+  /* 'fpr_base' points at the space for fpr3, and grows upwards as
+     we use FPR registers.  */
+  valp fpr_base;
+  unsigned int fparg_count;
+
+  unsigned int i, words, nargs, nfixedargs;
+  ffi_type **ptr;
+  double double_tmp;
+  union
+  {
+    void **v;
+    char **c;
+    signed char **sc;
+    unsigned char **uc;
+    signed short **ss;
+    unsigned short **us;
+    signed int **si;
+    unsigned int **ui;
+    unsigned long **ul;
+    float **f;
+    double **d;
+  } p_argv;
+  unsigned long gprvalue;
+  unsigned long align;
+
+  stacktop.c = (char *) stack + bytes;
+  gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
+  gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64;
+#if _CALL_ELF == 2
+  rest.ul = stack + 4 + NUM_GPR_ARG_REGISTERS64;
+#else
+  rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64;
+#endif
+  fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64;
+  fparg_count = 0;
+  next_arg.ul = gpr_base.ul;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
+  FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
+  FFI_ASSERT ((bytes & 0xF) == 0);
+
+  /* Deal with return values that are actually pass-by-reference.  */
+  if (flags & FLAG_RETVAL_REFERENCE)
+    *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue;
+
+  /* Now for the arguments.  */
+  p_argv.v = ecif->avalue;
+  nargs = ecif->cif->nargs;
+#if _CALL_ELF != 2
+  nfixedargs = (unsigned) -1;
+  if ((flags & FLAG_COMPAT) == 0)
+#endif
+    nfixedargs = ecif->cif->nfixedargs;
+  for (ptr = ecif->cif->arg_types, i = 0;
+       i < nargs;
+       i++, ptr++, p_argv.v++)
+    {
+#if _CALL_ELF == 2
+      unsigned int elt, elnum;
+#endif
+
+      switch ((*ptr)->type)
+	{
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  if ((ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
+	    {
+	      double_tmp = (*p_argv.d)[0];
+	      if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+		{
+		  *fpr_base.d++ = double_tmp;
+# if _CALL_ELF != 2
+		  if ((flags & FLAG_COMPAT) != 0)
+		    *next_arg.d = double_tmp;
+# endif
+		}
+	      else
+		*next_arg.d = double_tmp;
+	      if (++next_arg.ul == gpr_end.ul)
+		next_arg.ul = rest.ul;
+	      fparg_count++;
+	      double_tmp = (*p_argv.d)[1];
+	      if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+		{
+		  *fpr_base.d++ = double_tmp;
+# if _CALL_ELF != 2
+		  if ((flags & FLAG_COMPAT) != 0)
+		    *next_arg.d = double_tmp;
+# endif
+		}
+	      else
+		*next_arg.d = double_tmp;
+	      if (++next_arg.ul == gpr_end.ul)
+		next_arg.ul = rest.ul;
+	      fparg_count++;
+	      FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
+	      FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+	      break;
+	    }
+	  /* Fall through.  */
+#endif
+	case FFI_TYPE_DOUBLE:
+	  double_tmp = **p_argv.d;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+	    {
+	      *fpr_base.d++ = double_tmp;
+#if _CALL_ELF != 2
+	      if ((flags & FLAG_COMPAT) != 0)
+		*next_arg.d = double_tmp;
+#endif
+	    }
+	  else
+	    *next_arg.d = double_tmp;
+	  if (++next_arg.ul == gpr_end.ul)
+	    next_arg.ul = rest.ul;
+	  fparg_count++;
+	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  double_tmp = **p_argv.f;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+	    {
+	      *fpr_base.d++ = double_tmp;
+#if _CALL_ELF != 2
+	      if ((flags & FLAG_COMPAT) != 0)
+		*next_arg.f = (float) double_tmp;
+#endif
+	    }
+	  else
+	    *next_arg.f = (float) double_tmp;
+	  if (++next_arg.ul == gpr_end.ul)
+	    next_arg.ul = rest.ul;
+	  fparg_count++;
+	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  if ((ecif->cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0)
+	    {
+	      align = (*ptr)->alignment;
+	      if (align > 16)
+		align = 16;
+	      if (align > 1)
+		next_arg.p = ALIGN (next_arg.p, align);
+	    }
+#if _CALL_ELF == 2
+	  elt = discover_homogeneous_aggregate (*ptr, &elnum);
+	  if (elt)
+	    {
+	      union {
+		void *v;
+		float *f;
+		double *d;
+	      } arg;
+
+	      arg.v = *p_argv.v;
+	      if (elt == FFI_TYPE_FLOAT)
+		{
+		  do
+		    {
+		      double_tmp = *arg.f++;
+		      if (fparg_count < NUM_FPR_ARG_REGISTERS64
+			  && i < nfixedargs)
+			*fpr_base.d++ = double_tmp;
+		      else
+			*next_arg.f = (float) double_tmp;
+		      if (++next_arg.f == gpr_end.f)
+			next_arg.f = rest.f;
+		      fparg_count++;
+		    }
+		  while (--elnum != 0);
+		  if ((next_arg.p & 3) != 0)
+		    {
+		      if (++next_arg.f == gpr_end.f)
+			next_arg.f = rest.f;
+		    }
+		}
+	      else
+		do
+		  {
+		    double_tmp = *arg.d++;
+		    if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+		      *fpr_base.d++ = double_tmp;
+		    else
+		      *next_arg.d = double_tmp;
+		    if (++next_arg.d == gpr_end.d)
+		      next_arg.d = rest.d;
+		    fparg_count++;
+		  }
+		while (--elnum != 0);
+	    }
+	  else
+#endif
+	    {
+	      words = ((*ptr)->size + 7) / 8;
+	      if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
+		{
+		  size_t first = gpr_end.c - next_arg.c;
+		  memcpy (next_arg.c, *p_argv.c, first);
+		  memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first);
+		  next_arg.c = rest.c + words * 8 - first;
+		}
+	      else
+		{
+		  char *where = next_arg.c;
+
+#ifndef __LITTLE_ENDIAN__
+		  /* Structures with size less than eight bytes are passed
+		     left-padded.  */
+		  if ((*ptr)->size < 8)
+		    where += 8 - (*ptr)->size;
+#endif
+		  memcpy (where, *p_argv.c, (*ptr)->size);
+		  next_arg.ul += words;
+		  if (next_arg.ul == gpr_end.ul)
+		    next_arg.ul = rest.ul;
+		}
+	    }
+	  break;
+
+	case FFI_TYPE_UINT8:
+	  gprvalue = **p_argv.uc;
+	  goto putgpr;
+	case FFI_TYPE_SINT8:
+	  gprvalue = **p_argv.sc;
+	  goto putgpr;
+	case FFI_TYPE_UINT16:
+	  gprvalue = **p_argv.us;
+	  goto putgpr;
+	case FFI_TYPE_SINT16:
+	  gprvalue = **p_argv.ss;
+	  goto putgpr;
+	case FFI_TYPE_UINT32:
+	  gprvalue = **p_argv.ui;
+	  goto putgpr;
+	case FFI_TYPE_INT:
+	case FFI_TYPE_SINT32:
+	  gprvalue = **p_argv.si;
+	  goto putgpr;
+
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_POINTER:
+	  gprvalue = **p_argv.ul;
+	putgpr:
+	  *next_arg.ul++ = gprvalue;
+	  if (next_arg.ul == gpr_end.ul)
+	    next_arg.ul = rest.ul;
+	  break;
+	}
+    }
+
+  FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS
+	      || (next_arg.ul >= gpr_base.ul
+		  && next_arg.ul <= gpr_base.ul + 4));
+}
+
+
+#if _CALL_ELF == 2
+#define MIN_CACHE_LINE_SIZE 8
+
+static void
+flush_icache (char *wraddr, char *xaddr, int size)
+{
+  int i;
+  for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
+    __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
+		      : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
+  __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
+		    : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
+		    : "memory");
+}
+#endif
+
+ffi_status
+ffi_prep_closure_loc_linux64 (ffi_closure *closure,
+			      ffi_cif *cif,
+			      void (*fun) (ffi_cif *, void *, void **, void *),
+			      void *user_data,
+			      void *codeloc)
+{
+#if _CALL_ELF == 2
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+
+  if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI)
+    return FFI_BAD_ABI;
+
+  tramp[0] = 0xe96c0018;	/* 0:	ld	11,2f-0b(12)	*/
+  tramp[1] = 0xe98c0010;	/*	ld	12,1f-0b(12)	*/
+  tramp[2] = 0x7d8903a6;	/*	mtctr	12		*/
+  tramp[3] = 0x4e800420;	/*	bctr			*/
+				/* 1:	.quad	function_addr	*/
+				/* 2:	.quad	context		*/
+  *(void **) &tramp[4] = (void *) ffi_closure_LINUX64;
+  *(void **) &tramp[6] = codeloc;
+  flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
+#else
+  void **tramp = (void **) &closure->tramp[0];
+
+  if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI)
+    return FFI_BAD_ABI;
+
+  /* Copy function address and TOC from ffi_closure_LINUX64.  */
+  memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
+  tramp[2] = codeloc;
+#endif
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
+
+
+int FFI_HIDDEN
+ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
+			    unsigned long *pst, ffi_dblfl *pfr)
+{
+  /* rvalue is the pointer to space for return value in closure assembly */
+  /* pst is the pointer to parameter save area
+     (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
+  /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
+
+  void **avalue;
+  ffi_type **arg_types;
+  unsigned long i, avn, nfixedargs;
+  ffi_cif *cif;
+  ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
+  unsigned long align;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (void *));
+
+  /* Copy the caller's structure return value address so that the
+     closure returns the data directly to the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+      && (cif->flags & FLAG_RETURNS_SMST) == 0)
+    {
+      rvalue = (void *) *pst;
+      pst++;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+#if _CALL_ELF != 2
+  nfixedargs = (unsigned) -1;
+  if ((cif->flags & FLAG_COMPAT) == 0)
+#endif
+    nfixedargs = cif->nfixedargs;
+  arg_types = cif->arg_types;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  while (i < avn)
+    {
+      unsigned int elt, elnum;
+
+      switch (arg_types[i]->type)
+	{
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+#ifndef __LITTLE_ENDIAN__
+	  avalue[i] = (char *) pst + 7;
+	  pst++;
+	  break;
+#endif
+
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+#ifndef __LITTLE_ENDIAN__
+	  avalue[i] = (char *) pst + 6;
+	  pst++;
+	  break;
+#endif
+
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+#ifndef __LITTLE_ENDIAN__
+	  avalue[i] = (char *) pst + 4;
+	  pst++;
+	  break;
+#endif
+
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_POINTER:
+	  avalue[i] = pst;
+	  pst++;
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  if ((cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0)
+	    {
+	      align = arg_types[i]->alignment;
+	      if (align > 16)
+		align = 16;
+	      if (align > 1)
+		pst = (unsigned long *) ALIGN ((size_t) pst, align);
+	    }
+	  elt = 0;
+#if _CALL_ELF == 2
+	  elt = discover_homogeneous_aggregate (arg_types[i], &elnum);
+#endif
+	  if (elt)
+	    {
+	      union {
+		void *v;
+		unsigned long *ul;
+		float *f;
+		double *d;
+		size_t p;
+	      } to, from;
+
+	      /* Repackage the aggregate from its parts.  The
+		 aggregate size is not greater than the space taken by
+		 the registers so store back to the register/parameter
+		 save arrays.  */
+	      if (pfr + elnum <= end_pfr)
+		to.v = pfr;
+	      else
+		to.v = pst;
+
+	      avalue[i] = to.v;
+	      from.ul = pst;
+	      if (elt == FFI_TYPE_FLOAT)
+		{
+		  do
+		    {
+		      if (pfr < end_pfr && i < nfixedargs)
+			{
+			  *to.f = (float) pfr->d;
+			  pfr++;
+			}
+		      else
+			*to.f = *from.f;
+		      to.f++;
+		      from.f++;
+		    }
+		  while (--elnum != 0);
+		}
+	      else
+		{
+		  do
+		    {
+		      if (pfr < end_pfr && i < nfixedargs)
+			{
+			  *to.d = pfr->d;
+			  pfr++;
+			}
+		      else
+			*to.d = *from.d;
+		      to.d++;
+		      from.d++;
+		    }
+		  while (--elnum != 0);
+		}
+	    }
+	  else
+	    {
+#ifndef __LITTLE_ENDIAN__
+	      /* Structures with size less than eight bytes are passed
+		 left-padded.  */
+	      if (arg_types[i]->size < 8)
+		avalue[i] = (char *) pst + 8 - arg_types[i]->size;
+	      else
+#endif
+		avalue[i] = pst;
+	    }
+	  pst += (arg_types[i]->size + 7) / 8;
+	  break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
+	    {
+	      if (pfr + 1 < end_pfr && i + 1 < nfixedargs)
+		{
+		  avalue[i] = pfr;
+		  pfr += 2;
+		}
+	      else
+		{
+		  if (pfr < end_pfr && i < nfixedargs)
+		    {
+		      /* Passed partly in f13 and partly on the stack.
+			 Move it all to the stack.  */
+		      *pst = *(unsigned long *) pfr;
+		      pfr++;
+		    }
+		  avalue[i] = pst;
+		}
+	      pst += 2;
+	      break;
+	    }
+	  /* Fall through.  */
+#endif
+	case FFI_TYPE_DOUBLE:
+	  /* On the outgoing stack all values are aligned to 8 */
+	  /* there are 13 64bit floating point registers */
+
+	  if (pfr < end_pfr && i < nfixedargs)
+	    {
+	      avalue[i] = pfr;
+	      pfr++;
+	    }
+	  else
+	    avalue[i] = pst;
+	  pst++;
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  if (pfr < end_pfr && i < nfixedargs)
+	    {
+	      /* Float values are stored as doubles in the
+		 ffi_closure_LINUX64 code.  Fix them here.  */
+	      pfr->f = (float) pfr->d;
+	      avalue[i] = pfr;
+	      pfr++;
+	    }
+	  else
+	    avalue[i] = pst;
+	  pst++;
+	  break;
+
+	default:
+	  FFI_ASSERT (0);
+	}
+
+      i++;
+    }
+
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_LINUX64 how to perform return type promotions.  */
+  if ((cif->flags & FLAG_RETURNS_SMST) != 0)
+    {
+      if ((cif->flags & FLAG_RETURNS_FP) == 0)
+	return FFI_V2_TYPE_SMALL_STRUCT + cif->rtype->size - 1;
+      else if ((cif->flags & FLAG_RETURNS_64BITS) != 0)
+	return FFI_V2_TYPE_DOUBLE_HOMOG;
+      else
+	return FFI_V2_TYPE_FLOAT_HOMOG;
+    }
+  return cif->rtype->type;
+}
+#endif
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffi_powerpc.h b/third_party/gofrontend/libffi/src/powerpc/ffi_powerpc.h
new file mode 100644
index 0000000..2e61653
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/ffi_powerpc.h
@@ -0,0 +1,77 @@
+/* -----------------------------------------------------------------------
+   ffi_powerpc.h - Copyright (C) 2013 IBM
+                   Copyright (C) 2011 Anthony Green
+                   Copyright (C) 2011 Kyle Moffett
+                   Copyright (C) 2008 Red Hat, Inc
+                   Copyright (C) 2007, 2008 Free Software Foundation, Inc
+                   Copyright (c) 1998 Geoffrey Keating
+
+   PowerPC Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+enum {
+  /* The assembly depends on these exact flags.  */
+  /* These go in cr7 */
+  FLAG_RETURNS_SMST	= 1 << (31-31), /* Used for FFI_SYSV small structs.  */
+  FLAG_RETURNS_NOTHING  = 1 << (31-30),
+  FLAG_RETURNS_FP       = 1 << (31-29),
+  FLAG_RETURNS_64BITS   = 1 << (31-28),
+
+  /* This goes in cr6 */
+  FLAG_RETURNS_128BITS  = 1 << (31-27),
+
+  FLAG_COMPAT		= 1 << (31- 8), /* Not used by assembly */
+
+  /* These go in cr1 */
+  FLAG_ARG_NEEDS_COPY   = 1 << (31- 7), /* Used by sysv code */
+  FLAG_ARG_NEEDS_PSAVE  = FLAG_ARG_NEEDS_COPY, /* Used by linux64 code */
+  FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI */
+  FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
+  FLAG_RETVAL_REFERENCE = 1 << (31- 4)
+};
+
+typedef union
+{
+  float f;
+  double d;
+} ffi_dblfl;
+
+void FFI_HIDDEN ffi_closure_SYSV (void);
+void FFI_HIDDEN ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
+			      void (*)(void));
+
+void FFI_HIDDEN ffi_prep_types_sysv (ffi_abi);
+ffi_status FFI_HIDDEN ffi_prep_cif_sysv (ffi_cif *);
+int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *,
+					ffi_dblfl *, unsigned long *);
+
+void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long, unsigned long,
+				 unsigned long *, void (*)(void));
+void FFI_HIDDEN ffi_closure_LINUX64 (void);
+
+void FFI_HIDDEN ffi_prep_types_linux64 (ffi_abi);
+ffi_status FFI_HIDDEN ffi_prep_cif_linux64 (ffi_cif *);
+ffi_status FFI_HIDDEN ffi_prep_cif_linux64_var (ffi_cif *, unsigned int,
+						unsigned int);
+void FFI_HIDDEN ffi_prep_args64 (extended_cif *, unsigned long *const);
+int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
+					   unsigned long *, ffi_dblfl *);
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffi_sysv.c b/third_party/gofrontend/libffi/src/powerpc/ffi_sysv.c
new file mode 100644
index 0000000..fbe85fe
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/ffi_sysv.c
@@ -0,0 +1,931 @@
+/* -----------------------------------------------------------------------
+   ffi_sysv.c - Copyright (C) 2013 IBM
+                Copyright (C) 2011 Anthony Green
+                Copyright (C) 2011 Kyle Moffett
+                Copyright (C) 2008 Red Hat, Inc
+                Copyright (C) 2007, 2008 Free Software Foundation, Inc
+                Copyright (c) 1998 Geoffrey Keating
+
+   PowerPC Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include "ffi.h"
+
+#ifndef POWERPC64
+#include "ffi_common.h"
+#include "ffi_powerpc.h"
+
+
+/* About the SYSV ABI.  */
+#define ASM_NEEDS_REGISTERS 4
+#define NUM_GPR_ARG_REGISTERS 8
+#define NUM_FPR_ARG_REGISTERS 8
+
+
+#if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+/* Adjust size of ffi_type_longdouble.  */
+void FFI_HIDDEN
+ffi_prep_types_sysv (ffi_abi abi)
+{
+  if ((abi & (FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128)) == FFI_SYSV)
+    {
+      ffi_type_longdouble.size = 8;
+      ffi_type_longdouble.alignment = 8;
+    }
+  else
+    {
+      ffi_type_longdouble.size = 16;
+      ffi_type_longdouble.alignment = 16;
+    }
+}
+#endif
+
+/* Transform long double, double and float to other types as per abi.  */
+static int
+translate_float (int abi, int type)
+{
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+  if (type == FFI_TYPE_LONGDOUBLE
+      && (abi & FFI_SYSV_LONG_DOUBLE_128) == 0)
+    type = FFI_TYPE_DOUBLE;
+#endif
+  if ((abi & FFI_SYSV_SOFT_FLOAT) != 0)
+    {
+      if (type == FFI_TYPE_FLOAT)
+	type = FFI_TYPE_UINT32;
+      else if (type == FFI_TYPE_DOUBLE)
+	type = FFI_TYPE_UINT64;
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      else if (type == FFI_TYPE_LONGDOUBLE)
+	type = FFI_TYPE_UINT128;
+    }
+  else if ((abi & FFI_SYSV_IBM_LONG_DOUBLE) == 0)
+    {
+      if (type == FFI_TYPE_LONGDOUBLE)
+	type = FFI_TYPE_STRUCT;
+#endif
+    }
+  return type;
+}
+
+/* Perform machine dependent cif processing */
+static ffi_status
+ffi_prep_cif_sysv_core (ffi_cif *cif)
+{
+  ffi_type **ptr;
+  unsigned bytes;
+  unsigned i, fparg_count = 0, intarg_count = 0;
+  unsigned flags = cif->flags;
+  unsigned struct_copy_size = 0;
+  unsigned type = cif->rtype->type;
+  unsigned size = cif->rtype->size;
+
+  /* The machine-independent calculation of cif->bytes doesn't work
+     for us.  Redo the calculation.  */
+
+  /* Space for the frame pointer, callee's LR, and the asm's temp regs.  */
+  bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int);
+
+  /* Space for the GPR registers.  */
+  bytes += NUM_GPR_ARG_REGISTERS * sizeof (int);
+
+  /* Return value handling.  The rules for SYSV are as follows:
+     - 32-bit (or less) integer values are returned in gpr3;
+     - Structures of size <= 4 bytes also returned in gpr3;
+     - 64-bit integer values and structures between 5 and 8 bytes are returned
+     in gpr3 and gpr4;
+     - Larger structures are allocated space and a pointer is passed as
+     the first argument.
+     - Single/double FP values are returned in fpr1;
+     - long doubles (if not equivalent to double) are returned in
+     fpr1,fpr2 for Linux and as for large structs for SysV.  */
+
+  type = translate_float (cif->abi, type);
+
+  switch (type)
+    {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+      flags |= FLAG_RETURNS_128BITS;
+      /* Fall through.  */
+#endif
+    case FFI_TYPE_DOUBLE:
+      flags |= FLAG_RETURNS_64BITS;
+      /* Fall through.  */
+    case FFI_TYPE_FLOAT:
+      flags |= FLAG_RETURNS_FP;
+#ifdef __NO_FPRS__
+      return FFI_BAD_ABI;
+#endif
+      break;
+
+    case FFI_TYPE_UINT128:
+      flags |= FLAG_RETURNS_128BITS;
+      /* Fall through.  */
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      flags |= FLAG_RETURNS_64BITS;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      /* The final SYSV ABI says that structures smaller or equal 8 bytes
+	 are returned in r3/r4.  A draft ABI used by linux instead
+	 returns them in memory.  */
+      if ((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8)
+	{
+	  flags |= FLAG_RETURNS_SMST;
+	  break;
+	}
+      intarg_count++;
+      flags |= FLAG_RETVAL_REFERENCE;
+      /* Fall through.  */
+    case FFI_TYPE_VOID:
+      flags |= FLAG_RETURNS_NOTHING;
+      break;
+
+    default:
+      /* Returns 32-bit integer, or similar.  Nothing to do here.  */
+      break;
+    }
+
+  /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
+     first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
+     goes on the stack.  Structures and long doubles (if not equivalent
+     to double) are passed as a pointer to a copy of the structure.
+     Stuff on the stack needs to keep proper alignment.  */
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+      unsigned short typenum = (*ptr)->type;
+
+      typenum = translate_float (cif->abi, typenum);
+
+      switch (typenum)
+	{
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  fparg_count++;
+	  /* Fall thru */
+#endif
+	case FFI_TYPE_DOUBLE:
+	  fparg_count++;
+	  /* If this FP arg is going on the stack, it must be
+	     8-byte-aligned.  */
+	  if (fparg_count > NUM_FPR_ARG_REGISTERS
+	      && intarg_count >= NUM_GPR_ARG_REGISTERS
+	      && intarg_count % 2 != 0)
+	    intarg_count++;
+#ifdef __NO_FPRS__
+	  return FFI_BAD_ABI;
+#endif
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  fparg_count++;
+#ifdef __NO_FPRS__
+	  return FFI_BAD_ABI;
+#endif
+	  break;
+
+	case FFI_TYPE_UINT128:
+	  /* A long double in FFI_LINUX_SOFT_FLOAT can use only a set
+	     of four consecutive gprs. If we do not have enough, we
+	     have to adjust the intarg_count value.  */
+	  if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
+	      && intarg_count < NUM_GPR_ARG_REGISTERS)
+	    intarg_count = NUM_GPR_ARG_REGISTERS;
+	  intarg_count += 4;
+	  break;
+
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	  /* 'long long' arguments are passed as two words, but
+	     either both words must fit in registers or both go
+	     on the stack.  If they go on the stack, they must
+	     be 8-byte-aligned.
+
+	     Also, only certain register pairs can be used for
+	     passing long long int -- specifically (r3,r4), (r5,r6),
+	     (r7,r8), (r9,r10).  */
+	  if (intarg_count == NUM_GPR_ARG_REGISTERS-1
+	      || intarg_count % 2 != 0)
+	    intarg_count++;
+	  intarg_count += 2;
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  /* We must allocate space for a copy of these to enforce
+	     pass-by-value.  Pad the space up to a multiple of 16
+	     bytes (the maximum alignment required for anything under
+	     the SYSV ABI).  */
+	  struct_copy_size += ((*ptr)->size + 15) & ~0xF;
+	  /* Fall through (allocate space for the pointer).  */
+
+	case FFI_TYPE_POINTER:
+	case FFI_TYPE_INT:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT8:
+	  /* Everything else is passed as a 4-byte word in a GPR, either
+	     the object itself or a pointer to it.  */
+	  intarg_count++;
+	  break;
+
+	default:
+	  FFI_ASSERT (0);
+	}
+    }
+
+  if (fparg_count != 0)
+    flags |= FLAG_FP_ARGUMENTS;
+  if (intarg_count > 4)
+    flags |= FLAG_4_GPR_ARGUMENTS;
+  if (struct_copy_size != 0)
+    flags |= FLAG_ARG_NEEDS_COPY;
+
+  /* Space for the FPR registers, if needed.  */
+  if (fparg_count != 0)
+    bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
+
+  /* Stack space.  */
+  if (intarg_count > NUM_GPR_ARG_REGISTERS)
+    bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
+  if (fparg_count > NUM_FPR_ARG_REGISTERS)
+    bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
+
+  /* The stack space allocated needs to be a multiple of 16 bytes.  */
+  bytes = (bytes + 15) & ~0xF;
+
+  /* Add in the space for the copied structures.  */
+  bytes += struct_copy_size;
+
+  cif->flags = flags;
+  cif->bytes = bytes;
+
+  return FFI_OK;
+}
+
+ffi_status FFI_HIDDEN
+ffi_prep_cif_sysv (ffi_cif *cif)
+{
+  if ((cif->abi & FFI_SYSV) == 0)
+    {
+      /* This call is from old code.  Translate to new ABI values.  */
+      cif->flags |= FLAG_COMPAT;
+      switch (cif->abi)
+	{
+	default:
+	  return FFI_BAD_ABI;
+
+	case FFI_COMPAT_SYSV:
+	  cif->abi = FFI_SYSV | FFI_SYSV_STRUCT_RET | FFI_SYSV_LONG_DOUBLE_128;
+	  break;
+
+	case FFI_COMPAT_GCC_SYSV:
+	  cif->abi = FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128;
+	  break;
+
+	case FFI_COMPAT_LINUX:
+	  cif->abi = (FFI_SYSV | FFI_SYSV_IBM_LONG_DOUBLE
+		      | FFI_SYSV_LONG_DOUBLE_128);
+	  break;
+
+	case FFI_COMPAT_LINUX_SOFT_FLOAT:
+	  cif->abi = (FFI_SYSV | FFI_SYSV_SOFT_FLOAT | FFI_SYSV_IBM_LONG_DOUBLE
+		      | FFI_SYSV_LONG_DOUBLE_128);
+	  break;
+	}
+    }
+  return ffi_prep_cif_sysv_core (cif);
+}
+
+/* ffi_prep_args_SYSV is called by the assembly routine once stack space
+   has been allocated for the function's arguments.
+
+   The stack layout we want looks like this:
+
+   |   Return address from ffi_call_SYSV 4bytes	|	higher addresses
+   |--------------------------------------------|
+   |   Previous backchain pointer	4	|       stack pointer here
+   |--------------------------------------------|<+ <<<	on entry to
+   |   Saved r28-r31			4*4	| |	ffi_call_SYSV
+   |--------------------------------------------| |
+   |   GPR registers r3-r10		8*4	| |	ffi_call_SYSV
+   |--------------------------------------------| |
+   |   FPR registers f1-f8 (optional)	8*8	| |
+   |--------------------------------------------| |	stack	|
+   |   Space for copied structures		| |	grows	|
+   |--------------------------------------------| |	down    V
+   |   Parameters that didn't fit in registers  | |
+   |--------------------------------------------| |	lower addresses
+   |   Space for callee's LR		4	| |
+   |--------------------------------------------| |	stack pointer here
+   |   Current backchain pointer	4	|-/	during
+   |--------------------------------------------|   <<<	ffi_call_SYSV
+
+*/
+
+void FFI_HIDDEN
+ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
+{
+  const unsigned bytes = ecif->cif->bytes;
+  const unsigned flags = ecif->cif->flags;
+
+  typedef union
+  {
+    char *c;
+    unsigned *u;
+    long long *ll;
+    float *f;
+    double *d;
+  } valp;
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  valp stacktop;
+
+  /* 'gpr_base' points at the space for gpr3, and grows upwards as
+     we use GPR registers.  */
+  valp gpr_base;
+  int intarg_count;
+
+#ifndef __NO_FPRS__
+  /* 'fpr_base' points at the space for fpr1, and grows upwards as
+     we use FPR registers.  */
+  valp fpr_base;
+  int fparg_count;
+#endif
+
+  /* 'copy_space' grows down as we put structures in it.  It should
+     stay 16-byte aligned.  */
+  valp copy_space;
+
+  /* 'next_arg' grows up as we put parameters in it.  */
+  valp next_arg;
+
+  int i;
+  ffi_type **ptr;
+#ifndef __NO_FPRS__
+  double double_tmp;
+#endif
+  union
+  {
+    void **v;
+    char **c;
+    signed char **sc;
+    unsigned char **uc;
+    signed short **ss;
+    unsigned short **us;
+    unsigned int **ui;
+    long long **ll;
+    float **f;
+    double **d;
+  } p_argv;
+  size_t struct_copy_size;
+  unsigned gprvalue;
+
+  stacktop.c = (char *) stack + bytes;
+  gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
+  intarg_count = 0;
+#ifndef __NO_FPRS__
+  fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
+  fparg_count = 0;
+  copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
+#else
+  copy_space.c = gpr_base.c;
+#endif
+  next_arg.u = stack + 2;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
+  FFI_ASSERT (((unsigned long) copy_space.c & 0xF) == 0);
+  FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
+  FFI_ASSERT ((bytes & 0xF) == 0);
+  FFI_ASSERT (copy_space.c >= next_arg.c);
+
+  /* Deal with return values that are actually pass-by-reference.  */
+  if (flags & FLAG_RETVAL_REFERENCE)
+    {
+      *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue;
+      intarg_count++;
+    }
+
+  /* Now for the arguments.  */
+  p_argv.v = ecif->avalue;
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv.v++)
+    {
+      unsigned int typenum = (*ptr)->type;
+
+      typenum = translate_float (ecif->cif->abi, typenum);
+
+      /* Now test the translated value */
+      switch (typenum)
+	{
+#ifndef __NO_FPRS__
+# if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  double_tmp = (*p_argv.d)[0];
+
+	  if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
+	    {
+	      if (intarg_count >= NUM_GPR_ARG_REGISTERS
+		  && intarg_count % 2 != 0)
+		{
+		  intarg_count++;
+		  next_arg.u++;
+		}
+	      *next_arg.d = double_tmp;
+	      next_arg.u += 2;
+	      double_tmp = (*p_argv.d)[1];
+	      *next_arg.d = double_tmp;
+	      next_arg.u += 2;
+	    }
+	  else
+	    {
+	      *fpr_base.d++ = double_tmp;
+	      double_tmp = (*p_argv.d)[1];
+	      *fpr_base.d++ = double_tmp;
+	    }
+
+	  fparg_count += 2;
+	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+	  break;
+# endif
+	case FFI_TYPE_DOUBLE:
+	  double_tmp = **p_argv.d;
+
+	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+	    {
+	      if (intarg_count >= NUM_GPR_ARG_REGISTERS
+		  && intarg_count % 2 != 0)
+		{
+		  intarg_count++;
+		  next_arg.u++;
+		}
+	      *next_arg.d = double_tmp;
+	      next_arg.u += 2;
+	    }
+	  else
+	    *fpr_base.d++ = double_tmp;
+	  fparg_count++;
+	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  double_tmp = **p_argv.f;
+	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+	    {
+	      *next_arg.f = (float) double_tmp;
+	      next_arg.u += 1;
+	      intarg_count++;
+	    }
+	  else
+	    *fpr_base.d++ = double_tmp;
+	  fparg_count++;
+	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+	  break;
+#endif /* have FPRs */
+
+	case FFI_TYPE_UINT128:
+	  /* The soft float ABI for long doubles works like this, a long double
+	     is passed in four consecutive GPRs if available.  A maximum of 2
+	     long doubles can be passed in gprs.  If we do not have 4 GPRs
+	     left, the long double is passed on the stack, 4-byte aligned.  */
+	  {
+	    unsigned int int_tmp;
+	    unsigned int ii;
+	    if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
+	      {
+		if (intarg_count < NUM_GPR_ARG_REGISTERS)
+		  intarg_count = NUM_GPR_ARG_REGISTERS;
+		for (ii = 0; ii < 4; ii++)
+		  {
+		    int_tmp = (*p_argv.ui)[ii];
+		    *next_arg.u++ = int_tmp;
+		  }
+	      }
+	    else
+	      {
+		for (ii = 0; ii < 4; ii++)
+		  {
+		    int_tmp = (*p_argv.ui)[ii];
+		    *gpr_base.u++ = int_tmp;
+		  }
+	      }
+	    intarg_count += 4;
+	    break;
+	  }
+
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	  if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
+	    intarg_count++;
+	  if (intarg_count >= NUM_GPR_ARG_REGISTERS)
+	    {
+	      if (intarg_count % 2 != 0)
+		{
+		  intarg_count++;
+		  next_arg.u++;
+		}
+	      *next_arg.ll = **p_argv.ll;
+	      next_arg.u += 2;
+	    }
+	  else
+	    {
+	      /* The abi states only certain register pairs can be
+		 used for passing long long int specifically (r3,r4),
+		 (r5,r6), (r7,r8), (r9,r10).  If next arg is long long
+		 but not correct starting register of pair then skip
+		 until the proper starting register.  */
+	      if (intarg_count % 2 != 0)
+		{
+		  intarg_count ++;
+		  gpr_base.u++;
+		}
+	      *gpr_base.ll++ = **p_argv.ll;
+	    }
+	  intarg_count += 2;
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  struct_copy_size = ((*ptr)->size + 15) & ~0xF;
+	  copy_space.c -= struct_copy_size;
+	  memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
+
+	  gprvalue = (unsigned long) copy_space.c;
+
+	  FFI_ASSERT (copy_space.c > next_arg.c);
+	  FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY);
+	  goto putgpr;
+
+	case FFI_TYPE_UINT8:
+	  gprvalue = **p_argv.uc;
+	  goto putgpr;
+	case FFI_TYPE_SINT8:
+	  gprvalue = **p_argv.sc;
+	  goto putgpr;
+	case FFI_TYPE_UINT16:
+	  gprvalue = **p_argv.us;
+	  goto putgpr;
+	case FFI_TYPE_SINT16:
+	  gprvalue = **p_argv.ss;
+	  goto putgpr;
+
+	case FFI_TYPE_INT:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_POINTER:
+
+	  gprvalue = **p_argv.ui;
+
+	putgpr:
+	  if (intarg_count >= NUM_GPR_ARG_REGISTERS)
+	    *next_arg.u++ = gprvalue;
+	  else
+	    *gpr_base.u++ = gprvalue;
+	  intarg_count++;
+	  break;
+	}
+    }
+
+  /* Check that we didn't overrun the stack...  */
+  FFI_ASSERT (copy_space.c >= next_arg.c);
+  FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
+  /* The assert below is testing that the number of integer arguments agrees
+     with the number found in ffi_prep_cif_machdep().  However, intarg_count
+     is incremented whenever we place an FP arg on the stack, so account for
+     that before our assert test.  */
+#ifndef __NO_FPRS__
+  if (fparg_count > NUM_FPR_ARG_REGISTERS)
+    intarg_count -= fparg_count - NUM_FPR_ARG_REGISTERS;
+  FFI_ASSERT (fpr_base.u
+	      <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+#endif
+  FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
+}
+
+#define MIN_CACHE_LINE_SIZE 8
+
+static void
+flush_icache (char *wraddr, char *xaddr, int size)
+{
+  int i;
+  for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
+    __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
+		      : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
+  __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
+		    : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
+		    : "memory");
+}
+
+ffi_status FFI_HIDDEN
+ffi_prep_closure_loc_sysv (ffi_closure *closure,
+			   ffi_cif *cif,
+			   void (*fun) (ffi_cif *, void *, void **, void *),
+			   void *user_data,
+			   void *codeloc)
+{
+  unsigned int *tramp;
+
+  if (cif->abi < FFI_SYSV || cif->abi >= FFI_LAST_ABI)
+    return FFI_BAD_ABI;
+
+  tramp = (unsigned int *) &closure->tramp[0];
+  tramp[0] = 0x7c0802a6;  /*   mflr    r0 */
+  tramp[1] = 0x4800000d;  /*   bl      10 <trampoline_initial+0x10> */
+  tramp[4] = 0x7d6802a6;  /*   mflr    r11 */
+  tramp[5] = 0x7c0803a6;  /*   mtlr    r0 */
+  tramp[6] = 0x800b0000;  /*   lwz     r0,0(r11) */
+  tramp[7] = 0x816b0004;  /*   lwz     r11,4(r11) */
+  tramp[8] = 0x7c0903a6;  /*   mtctr   r0 */
+  tramp[9] = 0x4e800420;  /*   bctr */
+  *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
+  *(void **) &tramp[3] = codeloc;                   /* context */
+
+  /* Flush the icache.  */
+  flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
+
+/* Basically the trampoline invokes ffi_closure_SYSV, and on
+   entry, r11 holds the address of the closure.
+   After storing the registers that could possibly contain
+   parameters to be passed into the stack frame and setting
+   up space for a return value, ffi_closure_SYSV invokes the
+   following helper function to do most of the work.  */
+
+int
+ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
+			 unsigned long *pgr, ffi_dblfl *pfr,
+			 unsigned long *pst)
+{
+  /* rvalue is the pointer to space for return value in closure assembly */
+  /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
+  /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV  */
+  /* pst is the pointer to outgoing parameter stack in original caller */
+
+  void **          avalue;
+  ffi_type **      arg_types;
+  long             i, avn;
+#ifndef __NO_FPRS__
+  long             nf = 0;   /* number of floating registers already used */
+#endif
+  long             ng = 0;   /* number of general registers already used */
+
+  ffi_cif *cif = closure->cif;
+  unsigned       size     = cif->rtype->size;
+  unsigned short rtypenum = cif->rtype->type;
+
+  avalue = alloca (cif->nargs * sizeof (void *));
+
+  /* First translate for softfloat/nonlinux */
+  rtypenum = translate_float (cif->abi, rtypenum);
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.
+     For FFI_SYSV the result is passed in r3/r4 if the struct size is less
+     or equal 8 bytes.  */
+  if (rtypenum == FFI_TYPE_STRUCT
+      && !((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8))
+    {
+      rvalue = (void *) *pgr;
+      ng++;
+      pgr++;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  while (i < avn) {
+    unsigned short typenum = arg_types[i]->type;
+
+    /* We may need to handle some values depending on ABI.  */
+    typenum = translate_float (cif->abi, typenum);
+
+    switch (typenum)
+      {
+#ifndef __NO_FPRS__
+      case FFI_TYPE_FLOAT:
+	/* Unfortunately float values are stored as doubles
+	   in the ffi_closure_SYSV code (since we don't check
+	   the type in that routine).  */
+	if (nf < NUM_FPR_ARG_REGISTERS)
+	  {
+	    /* FIXME? here we are really changing the values
+	       stored in the original calling routines outgoing
+	       parameter stack.  This is probably a really
+	       naughty thing to do but...  */
+	    double temp = pfr->d;
+	    pfr->f = (float) temp;
+	    avalue[i] = pfr;
+	    nf++;
+	    pfr++;
+	  }
+	else
+	  {
+	    avalue[i] = pst;
+	    pst += 1;
+	  }
+	break;
+
+      case FFI_TYPE_DOUBLE:
+	if (nf < NUM_FPR_ARG_REGISTERS)
+	  {
+	    avalue[i] = pfr;
+	    nf++;
+	    pfr++;
+	  }
+	else
+	  {
+	    if (((long) pst) & 4)
+	      pst++;
+	    avalue[i] = pst;
+	    pst += 2;
+	  }
+	break;
+
+# if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      case FFI_TYPE_LONGDOUBLE:
+	if (nf < NUM_FPR_ARG_REGISTERS - 1)
+	  {
+	    avalue[i] = pfr;
+	    pfr += 2;
+	    nf += 2;
+	  }
+	else
+	  {
+	    if (((long) pst) & 4)
+	      pst++;
+	    avalue[i] = pst;
+	    pst += 4;
+	    nf = 8;
+	  }
+	break;
+# endif
+#endif
+
+      case FFI_TYPE_UINT128:
+	/* Test if for the whole long double, 4 gprs are available.
+	   otherwise the stuff ends up on the stack.  */
+	if (ng < NUM_GPR_ARG_REGISTERS - 3)
+	  {
+	    avalue[i] = pgr;
+	    pgr += 4;
+	    ng += 4;
+	  }
+	else
+	  {
+	    avalue[i] = pst;
+	    pst += 4;
+	    ng = 8+4;
+	  }
+	break;
+
+      case FFI_TYPE_SINT8:
+      case FFI_TYPE_UINT8:
+#ifndef __LITTLE_ENDIAN__
+	if (ng < NUM_GPR_ARG_REGISTERS)
+	  {
+	    avalue[i] = (char *) pgr + 3;
+	    ng++;
+	    pgr++;
+	  }
+	else
+	  {
+	    avalue[i] = (char *) pst + 3;
+	    pst++;
+	  }
+	break;
+#endif
+
+      case FFI_TYPE_SINT16:
+      case FFI_TYPE_UINT16:
+#ifndef __LITTLE_ENDIAN__
+	if (ng < NUM_GPR_ARG_REGISTERS)
+	  {
+	    avalue[i] = (char *) pgr + 2;
+	    ng++;
+	    pgr++;
+	  }
+	else
+	  {
+	    avalue[i] = (char *) pst + 2;
+	    pst++;
+	  }
+	break;
+#endif
+
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_POINTER:
+	if (ng < NUM_GPR_ARG_REGISTERS)
+	  {
+	    avalue[i] = pgr;
+	    ng++;
+	    pgr++;
+	  }
+	else
+	  {
+	    avalue[i] = pst;
+	    pst++;
+	  }
+	break;
+
+      case FFI_TYPE_STRUCT:
+	/* Structs are passed by reference. The address will appear in a
+	   gpr if it is one of the first 8 arguments.  */
+	if (ng < NUM_GPR_ARG_REGISTERS)
+	  {
+	    avalue[i] = (void *) *pgr;
+	    ng++;
+	    pgr++;
+	  }
+	else
+	  {
+	    avalue[i] = (void *) *pst;
+	    pst++;
+	  }
+	break;
+
+      case FFI_TYPE_SINT64:
+      case FFI_TYPE_UINT64:
+	/* Passing long long ints are complex, they must
+	   be passed in suitable register pairs such as
+	   (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
+	   and if the entire pair aren't available then the outgoing
+	   parameter stack is used for both but an alignment of 8
+	   must will be kept.  So we must either look in pgr
+	   or pst to find the correct address for this type
+	   of parameter.  */
+	if (ng < NUM_GPR_ARG_REGISTERS - 1)
+	  {
+	    if (ng & 1)
+	      {
+		/* skip r4, r6, r8 as starting points */
+		ng++;
+		pgr++;
+	      }
+	    avalue[i] = pgr;
+	    ng += 2;
+	    pgr += 2;
+	  }
+	else
+	  {
+	    if (((long) pst) & 4)
+	      pst++;
+	    avalue[i] = pst;
+	    pst += 2;
+	    ng = NUM_GPR_ARG_REGISTERS;
+	  }
+	break;
+
+      default:
+	FFI_ASSERT (0);
+      }
+
+    i++;
+  }
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.
+     Because the FFI_SYSV ABI returns the structures <= 8 bytes in
+     r3/r4 we have to tell ffi_closure_SYSV how to treat them.  We
+     combine the base type FFI_SYSV_TYPE_SMALL_STRUCT with the size of
+     the struct less one.  We never have a struct with size zero.
+     See the comment in ffitarget.h about ordering.  */
+  if (rtypenum == FFI_TYPE_STRUCT
+      && (cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8)
+    return FFI_SYSV_TYPE_SMALL_STRUCT - 1 + size;
+  return rtypenum;
+}
+#endif
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffitarget.h b/third_party/gofrontend/libffi/src/powerpc/ffitarget.h
new file mode 100644
index 0000000..b47b0f5
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/ffitarget.h
@@ -0,0 +1,183 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+
+   Target configuration macros for PowerPC.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+/* ---- System specific configurations ----------------------------------- */
+
+#if defined (POWERPC) && defined (__powerpc64__)	/* linux64 */
+#ifndef POWERPC64
+#define POWERPC64
+#endif
+#elif defined (POWERPC_DARWIN) && defined (__ppc64__)	/* Darwin64 */
+#ifndef POWERPC64
+#define POWERPC64
+#endif
+#ifndef POWERPC_DARWIN64
+#define POWERPC_DARWIN64
+#endif
+#elif defined (POWERPC_AIX) && defined (__64BIT__)	/* AIX64 */
+#ifndef POWERPC64
+#define POWERPC64
+#endif
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+
+#if defined (POWERPC_AIX)
+  FFI_AIX,
+  FFI_DARWIN,
+  FFI_DEFAULT_ABI = FFI_AIX,
+  FFI_LAST_ABI
+
+#elif defined (POWERPC_DARWIN)
+  FFI_AIX,
+  FFI_DARWIN,
+  FFI_DEFAULT_ABI = FFI_DARWIN,
+  FFI_LAST_ABI
+
+#else
+  /* The FFI_COMPAT values are used by old code.  Since libffi may be
+     a shared library we have to support old values for backwards
+     compatibility.  */
+  FFI_COMPAT_SYSV,
+  FFI_COMPAT_GCC_SYSV,
+  FFI_COMPAT_LINUX64,
+  FFI_COMPAT_LINUX,
+  FFI_COMPAT_LINUX_SOFT_FLOAT,
+
+# if defined (POWERPC64)
+  /* This bit, always set in new code, must not be set in any of the
+     old FFI_COMPAT values that might be used for 64-bit linux.  We
+     only need worry about FFI_COMPAT_LINUX64, but to be safe avoid
+     all old values.  */
+  FFI_LINUX = 8,
+  /* This and following bits can reuse FFI_COMPAT values.  */
+  FFI_LINUX_STRUCT_ALIGN = 1,
+  FFI_LINUX_LONG_DOUBLE_128 = 2,
+  FFI_DEFAULT_ABI = (FFI_LINUX
+#  ifdef __STRUCT_PARM_ALIGN__
+		     | FFI_LINUX_STRUCT_ALIGN
+#  endif
+#  ifdef __LONG_DOUBLE_128__
+		     | FFI_LINUX_LONG_DOUBLE_128
+#  endif
+		     ),
+  FFI_LAST_ABI = 12
+
+# else
+  /* This bit, always set in new code, must not be set in any of the
+     old FFI_COMPAT values that might be used for 32-bit linux/sysv/bsd.  */
+  FFI_SYSV = 8,
+  /* This and following bits can reuse FFI_COMPAT values.  */
+  FFI_SYSV_SOFT_FLOAT = 1,
+  FFI_SYSV_STRUCT_RET = 2,
+  FFI_SYSV_IBM_LONG_DOUBLE = 4,
+  FFI_SYSV_LONG_DOUBLE_128 = 16,
+
+  FFI_DEFAULT_ABI = (FFI_SYSV
+#  ifdef __NO_FPRS__
+		     | FFI_SYSV_SOFT_FLOAT
+#  endif
+#  if (defined (__SVR4_STRUCT_RETURN)					\
+       || defined (POWERPC_FREEBSD) && !defined (__AIX_STRUCT_RETURN))
+		     | FFI_SYSV_STRUCT_RET
+#  endif
+#  if __LDBL_MANT_DIG__ == 106
+		     | FFI_SYSV_IBM_LONG_DOUBLE
+#  endif
+#  ifdef __LONG_DOUBLE_128__
+		     | FFI_SYSV_LONG_DOUBLE_128
+#  endif
+		     ),
+  FFI_LAST_ABI = 32
+# endif
+#endif
+
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+#if defined (POWERPC) || defined (POWERPC_FREEBSD)
+# define FFI_TARGET_SPECIFIC_VARIADIC 1
+# define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs
+#endif
+
+/* For additional types like the below, take care about the order in
+   ppc_closures.S. They must follow after the FFI_TYPE_LAST.  */
+
+/* Needed for soft-float long-double-128 support.  */
+#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
+
+/* Needed for FFI_SYSV small structure returns.  */
+#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
+
+/* Used by ELFv2 for homogenous structure returns.  */
+#define FFI_V2_TYPE_FLOAT_HOMOG		(FFI_TYPE_LAST + 1)
+#define FFI_V2_TYPE_DOUBLE_HOMOG	(FFI_TYPE_LAST + 2)
+#define FFI_V2_TYPE_SMALL_STRUCT	(FFI_TYPE_LAST + 3)
+
+#if _CALL_ELF == 2
+# define FFI_TRAMPOLINE_SIZE 32
+#else
+# if defined(POWERPC64) || defined(POWERPC_AIX)
+#  if defined(POWERPC_DARWIN64)
+#    define FFI_TRAMPOLINE_SIZE 48
+#  else
+#    define FFI_TRAMPOLINE_SIZE 24
+#  endif
+# else /* POWERPC || POWERPC_AIX */
+#  define FFI_TRAMPOLINE_SIZE 40
+# endif
+#endif
+
+#ifndef LIBFFI_ASM
+#if defined(POWERPC_DARWIN) || defined(POWERPC_AIX)
+struct ffi_aix_trampoline_struct {
+    void * code_pointer;	/* Pointer to ffi_closure_ASM */
+    void * toc;			/* TOC */
+    void * static_chain;	/* Pointer to closure */
+};
+#endif
+#endif
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/powerpc/linux64.S b/third_party/gofrontend/libffi/src/powerpc/linux64.S
new file mode 100644
index 0000000..d2acb70
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/linux64.S
@@ -0,0 +1,261 @@
+/* -----------------------------------------------------------------------
+   sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
+	    Copyright (c) 2008 Red Hat, Inc.
+
+   PowerPC64 Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+#ifdef POWERPC64
+	.hidden	ffi_call_LINUX64
+	.globl	ffi_call_LINUX64
+# if _CALL_ELF == 2
+	.text
+ffi_call_LINUX64:
+	addis	%r2, %r12, .TOC.-ffi_call_LINUX64@ha
+	addi	%r2, %r2, .TOC.-ffi_call_LINUX64@l
+	.localentry ffi_call_LINUX64, . - ffi_call_LINUX64
+# else
+	.section	".opd","aw"
+	.align	3
+ffi_call_LINUX64:
+#  ifdef _CALL_LINUX
+	.quad	.L.ffi_call_LINUX64,.TOC.@tocbase,0
+	.type	ffi_call_LINUX64,@function
+	.text
+.L.ffi_call_LINUX64:
+#  else
+	.hidden	.ffi_call_LINUX64
+	.globl	.ffi_call_LINUX64
+	.quad	.ffi_call_LINUX64,.TOC.@tocbase,0
+	.size	ffi_call_LINUX64,24
+	.type	.ffi_call_LINUX64,@function
+	.text
+.ffi_call_LINUX64:
+#  endif
+# endif
+.LFB1:
+	mflr	%r0
+	std	%r28, -32(%r1)
+	std	%r29, -24(%r1)
+	std	%r30, -16(%r1)
+	std	%r31, -8(%r1)
+	std	%r0, 16(%r1)
+
+	mr	%r28, %r1	/* our AP.  */
+.LCFI0:
+	stdux	%r1, %r1, %r4
+	mr	%r31, %r5	/* flags, */
+	mr	%r30, %r6	/* rvalue, */
+	mr	%r29, %r7	/* function address.  */
+/* Save toc pointer, not for the ffi_prep_args64 call, but for the later
+   bctrl function call.  */
+# if _CALL_ELF == 2
+	std	%r2, 24(%r1)
+# else
+	std	%r2, 40(%r1)
+# endif
+
+	/* Call ffi_prep_args64.  */
+	mr	%r4, %r1
+# if defined _CALL_LINUX || _CALL_ELF == 2
+	bl	ffi_prep_args64
+# else
+	bl	.ffi_prep_args64
+# endif
+
+# if _CALL_ELF == 2
+	mr	%r12, %r29
+# else
+	ld	%r12, 0(%r29)
+	ld	%r2, 8(%r29)
+	ld	%r11, 16(%r29)
+# endif
+	/* Now do the call.  */
+	/* Set up cr1 with bits 4-7 of the flags.  */
+	mtcrf	0x40, %r31
+
+	/* Get the address to call into CTR.  */
+	mtctr	%r12
+	/* Load all those argument registers.  */
+	ld	%r3, -32-(8*8)(%r28)
+	ld	%r4, -32-(7*8)(%r28)
+	ld	%r5, -32-(6*8)(%r28)
+	ld	%r6, -32-(5*8)(%r28)
+	bf-	5, 1f
+	ld	%r7, -32-(4*8)(%r28)
+	ld	%r8, -32-(3*8)(%r28)
+	ld	%r9, -32-(2*8)(%r28)
+	ld	%r10, -32-(1*8)(%r28)
+1:
+
+	/* Load all the FP registers.  */
+	bf-	6, 2f
+	lfd	%f1, -32-(21*8)(%r28)
+	lfd	%f2, -32-(20*8)(%r28)
+	lfd	%f3, -32-(19*8)(%r28)
+	lfd	%f4, -32-(18*8)(%r28)
+	lfd	%f5, -32-(17*8)(%r28)
+	lfd	%f6, -32-(16*8)(%r28)
+	lfd	%f7, -32-(15*8)(%r28)
+	lfd	%f8, -32-(14*8)(%r28)
+	lfd	%f9, -32-(13*8)(%r28)
+	lfd	%f10, -32-(12*8)(%r28)
+	lfd	%f11, -32-(11*8)(%r28)
+	lfd	%f12, -32-(10*8)(%r28)
+	lfd	%f13, -32-(9*8)(%r28)
+2:
+
+	/* Make the call.  */
+	bctrl
+
+	/* This must follow the call immediately, the unwinder
+	   uses this to find out if r2 has been saved or not.  */
+# if _CALL_ELF == 2
+	ld	%r2, 24(%r1)
+# else
+	ld	%r2, 40(%r1)
+# endif
+
+	/* Now, deal with the return value.  */
+	mtcrf	0x01, %r31
+	bt	31, .Lstruct_return_value
+	bt	30, .Ldone_return_value
+	bt	29, .Lfp_return_value
+	std	%r3, 0(%r30)
+	/* Fall through...  */
+
+.Ldone_return_value:
+	/* Restore the registers we used and return.  */
+	mr	%r1, %r28
+	ld	%r0, 16(%r28)
+	ld	%r28, -32(%r28)
+	mtlr	%r0
+	ld	%r29, -24(%r1)
+	ld	%r30, -16(%r1)
+	ld	%r31, -8(%r1)
+	blr
+
+.Lfp_return_value:
+	bf	28, .Lfloat_return_value
+	stfd	%f1, 0(%r30)
+	mtcrf	0x02, %r31 /* cr6  */
+	bf	27, .Ldone_return_value
+	stfd	%f2, 8(%r30)
+	b	.Ldone_return_value
+.Lfloat_return_value:
+	stfs	%f1, 0(%r30)
+	b	.Ldone_return_value
+
+.Lstruct_return_value:
+	bf	29, .Lsmall_struct
+	bf	28, .Lfloat_homog_return_value
+	stfd	%f1, 0(%r30)
+	stfd	%f2, 8(%r30)
+	stfd	%f3, 16(%r30)
+	stfd	%f4, 24(%r30)
+	stfd	%f5, 32(%r30)
+	stfd	%f6, 40(%r30)
+	stfd	%f7, 48(%r30)
+	stfd	%f8, 56(%r30)
+	b	.Ldone_return_value
+
+.Lfloat_homog_return_value:
+	stfs	%f1, 0(%r30)
+	stfs	%f2, 4(%r30)
+	stfs	%f3, 8(%r30)
+	stfs	%f4, 12(%r30)
+	stfs	%f5, 16(%r30)
+	stfs	%f6, 20(%r30)
+	stfs	%f7, 24(%r30)
+	stfs	%f8, 28(%r30)
+	b	.Ldone_return_value
+
+.Lsmall_struct:
+	std	%r3, 0(%r30)
+	std	%r4, 8(%r30)
+	b	.Ldone_return_value
+
+.LFE1:
+	.long	0
+	.byte	0,12,0,1,128,4,0,0
+# if _CALL_ELF == 2
+	.size	ffi_call_LINUX64,.-ffi_call_LINUX64
+# else
+#  ifdef _CALL_LINUX
+	.size	ffi_call_LINUX64,.-.L.ffi_call_LINUX64
+#  else
+	.size	.ffi_call_LINUX64,.-.ffi_call_LINUX64
+#  endif
+# endif
+
+	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
+.LSCIE1:
+	.4byte	0x0	 # CIE Identifier Tag
+	.byte	0x1	 # CIE Version
+	.ascii "zR\0"	 # CIE Augmentation
+	.uleb128 0x1	 # CIE Code Alignment Factor
+	.sleb128 -8	 # CIE Data Alignment Factor
+	.byte	0x41	 # CIE RA Column
+	.uleb128 0x1	 # Augmentation size
+	.byte	0x14	 # FDE Encoding (pcrel udata8)
+	.byte	0xc	 # DW_CFA_def_cfa
+	.uleb128 0x1
+	.uleb128 0x0
+	.align 3
+.LECIE1:
+.LSFDE1:
+	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
+.LASFDE1:
+	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
+	.8byte	.LFB1-.	 # FDE initial location
+	.8byte	.LFE1-.LFB1	 # FDE address range
+	.uleb128 0x0	 # Augmentation size
+	.byte	0x2	 # DW_CFA_advance_loc1
+	.byte	.LCFI0-.LFB1
+	.byte	0xd	 # DW_CFA_def_cfa_register
+	.uleb128 0x1c
+	.byte	0x11	 # DW_CFA_offset_extended_sf
+	.uleb128 0x41
+	.sleb128 -2
+	.byte	0x9f	 # DW_CFA_offset, column 0x1f
+	.uleb128 0x1
+	.byte	0x9e	 # DW_CFA_offset, column 0x1e
+	.uleb128 0x2
+	.byte	0x9d	 # DW_CFA_offset, column 0x1d
+	.uleb128 0x3
+	.byte	0x9c	 # DW_CFA_offset, column 0x1c
+	.uleb128 0x4
+	.align 3
+.LEFDE1:
+
+#endif
+
+#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/powerpc/linux64_closure.S b/third_party/gofrontend/libffi/src/powerpc/linux64_closure.S
new file mode 100644
index 0000000..1d80a39
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/linux64_closure.S
@@ -0,0 +1,388 @@
+/* -----------------------------------------------------------------------
+   sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
+	    Copyright (c) 2008 Red Hat, Inc.
+
+   PowerPC64 Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+	.file	"linux64_closure.S"
+
+#ifdef POWERPC64
+	FFI_HIDDEN (ffi_closure_LINUX64)
+	.globl  ffi_closure_LINUX64
+# if _CALL_ELF == 2
+	.text
+ffi_closure_LINUX64:
+	addis	%r2, %r12, .TOC.-ffi_closure_LINUX64@ha
+	addi	%r2, %r2, .TOC.-ffi_closure_LINUX64@l
+	.localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
+# else
+	.section        ".opd","aw"
+	.align  3
+ffi_closure_LINUX64:
+#  ifdef _CALL_LINUX
+	.quad   .L.ffi_closure_LINUX64,.TOC.@tocbase,0
+	.type   ffi_closure_LINUX64,@function
+	.text
+.L.ffi_closure_LINUX64:
+#  else
+	FFI_HIDDEN (.ffi_closure_LINUX64)
+	.globl  .ffi_closure_LINUX64
+	.quad   .ffi_closure_LINUX64,.TOC.@tocbase,0
+	.size   ffi_closure_LINUX64,24
+	.type   .ffi_closure_LINUX64,@function
+	.text
+.ffi_closure_LINUX64:
+#  endif
+# endif
+
+# if _CALL_ELF == 2
+#  32 byte special reg save area + 64 byte parm save area
+#  + 64 byte retval area + 13*8 fpr save area + round to 16
+#  define STACKFRAME 272
+#  define PARMSAVE 32
+#  define RETVAL PARMSAVE+64
+# else
+#  48 bytes special reg save area + 64 bytes parm save area
+#  + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
+#  define STACKFRAME 240
+#  define PARMSAVE 48
+#  define RETVAL PARMSAVE+64
+# endif
+
+.LFB1:
+# if _CALL_ELF == 2
+	ld	%r12, FFI_TRAMPOLINE_SIZE(%r11)		# closure->cif
+	mflr	%r0
+	lwz	%r12, 28(%r12)				# cif->flags
+	mtcrf	0x40, %r12
+	addi	%r12, %r1, PARMSAVE
+	bt	7, .Lparmsave
+	# Our caller has not allocated a parameter save area.
+	# We need to allocate one here and use it to pass gprs to
+	# ffi_closure_helper_LINUX64.
+	addi	%r12, %r1, -STACKFRAME+PARMSAVE
+.Lparmsave:
+	std	%r0, 16(%r1)
+	# Save general regs into parm save area
+	std	%r3, 0(%r12)
+	std	%r4, 8(%r12)
+	std	%r5, 16(%r12)
+	std	%r6, 24(%r12)
+	std	%r7, 32(%r12)
+	std	%r8, 40(%r12)
+	std	%r9, 48(%r12)
+	std	%r10, 56(%r12)
+
+	# load up the pointer to the parm save area
+	mr	%r5, %r12
+# else
+	mflr	%r0
+	# Save general regs into parm save area
+	# This is the parameter save area set up by our caller.
+	std	%r3, PARMSAVE+0(%r1)
+	std	%r4, PARMSAVE+8(%r1)
+	std	%r5, PARMSAVE+16(%r1)
+	std	%r6, PARMSAVE+24(%r1)
+	std	%r7, PARMSAVE+32(%r1)
+	std	%r8, PARMSAVE+40(%r1)
+	std	%r9, PARMSAVE+48(%r1)
+	std	%r10, PARMSAVE+56(%r1)
+
+	std	%r0, 16(%r1)
+
+	# load up the pointer to the parm save area
+	addi	%r5, %r1, PARMSAVE
+# endif
+
+	# next save fpr 1 to fpr 13
+	stfd	%f1, -104+(0*8)(%r1)
+	stfd	%f2, -104+(1*8)(%r1)
+	stfd	%f3, -104+(2*8)(%r1)
+	stfd	%f4, -104+(3*8)(%r1)
+	stfd	%f5, -104+(4*8)(%r1)
+	stfd	%f6, -104+(5*8)(%r1)
+	stfd	%f7, -104+(6*8)(%r1)
+	stfd	%f8, -104+(7*8)(%r1)
+	stfd	%f9, -104+(8*8)(%r1)
+	stfd	%f10, -104+(9*8)(%r1)
+	stfd	%f11, -104+(10*8)(%r1)
+	stfd	%f12, -104+(11*8)(%r1)
+	stfd	%f13, -104+(12*8)(%r1)
+
+	# load up the pointer to the saved fpr registers */
+	addi	%r6, %r1, -104
+
+	# load up the pointer to the result storage
+	addi	%r4, %r1, -STACKFRAME+RETVAL
+
+	stdu	%r1, -STACKFRAME(%r1)
+.LCFI0:
+
+	# get the context pointer from the trampoline
+	mr	%r3, %r11
+
+	# make the call
+# if defined _CALL_LINUX || _CALL_ELF == 2
+	bl ffi_closure_helper_LINUX64
+# else
+	bl .ffi_closure_helper_LINUX64
+# endif
+.Lret:
+
+	# now r3 contains the return type
+	# so use it to look up in a table
+	# so we know how to deal with each type
+
+	# look up the proper starting point in table
+	# by using return type as offset
+	ld %r0, STACKFRAME+16(%r1)
+	cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
+	bge .Lsmall
+	mflr %r4		# move address of .Lret to r4
+	sldi %r3, %r3, 4	# now multiply return type by 16
+	addi %r4, %r4, .Lret_type0 - .Lret
+	add %r3, %r3, %r4	# add contents of table to table address
+	mtctr %r3
+	bctr			# jump to it
+
+# Each of the ret_typeX code fragments has to be exactly 16 bytes long
+# (4 instructions). For cache effectiveness we align to a 16 byte boundary
+# first.
+	.align 4
+
+.Lret_type0:
+# case FFI_TYPE_VOID
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+	nop
+# case FFI_TYPE_INT
+# ifdef __LITTLE_ENDIAN__
+	lwa %r3, RETVAL+0(%r1)
+# else
+	lwa %r3, RETVAL+4(%r1)
+# endif
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_TYPE_FLOAT
+	lfs %f1, RETVAL+0(%r1)
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_TYPE_DOUBLE
+	lfd %f1, RETVAL+0(%r1)
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_TYPE_LONGDOUBLE
+	lfd %f1, RETVAL+0(%r1)
+	mtlr %r0
+	lfd %f2, RETVAL+8(%r1)
+	b .Lfinish
+# case FFI_TYPE_UINT8
+# ifdef __LITTLE_ENDIAN__
+	lbz %r3, RETVAL+0(%r1)
+# else
+	lbz %r3, RETVAL+7(%r1)
+# endif
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_TYPE_SINT8
+# ifdef __LITTLE_ENDIAN__
+	lbz %r3, RETVAL+0(%r1)
+# else
+	lbz %r3, RETVAL+7(%r1)
+# endif
+	extsb %r3,%r3
+	mtlr %r0
+	b .Lfinish
+# case FFI_TYPE_UINT16
+# ifdef __LITTLE_ENDIAN__
+	lhz %r3, RETVAL+0(%r1)
+# else
+	lhz %r3, RETVAL+6(%r1)
+# endif
+	mtlr %r0
+.Lfinish:
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_TYPE_SINT16
+# ifdef __LITTLE_ENDIAN__
+	lha %r3, RETVAL+0(%r1)
+# else
+	lha %r3, RETVAL+6(%r1)
+# endif
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_TYPE_UINT32
+# ifdef __LITTLE_ENDIAN__
+	lwz %r3, RETVAL+0(%r1)
+# else
+	lwz %r3, RETVAL+4(%r1)
+# endif
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_TYPE_SINT32
+# ifdef __LITTLE_ENDIAN__
+	lwa %r3, RETVAL+0(%r1)
+# else
+	lwa %r3, RETVAL+4(%r1)
+# endif
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_TYPE_UINT64
+	ld %r3, RETVAL+0(%r1)
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_TYPE_SINT64
+	ld %r3, RETVAL+0(%r1)
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_TYPE_STRUCT
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+	nop
+# case FFI_TYPE_POINTER
+	ld %r3, RETVAL+0(%r1)
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_V2_TYPE_FLOAT_HOMOG
+	lfs %f1, RETVAL+0(%r1)
+	lfs %f2, RETVAL+4(%r1)
+	lfs %f3, RETVAL+8(%r1)
+	b .Lmorefloat
+# case FFI_V2_TYPE_DOUBLE_HOMOG
+	lfd %f1, RETVAL+0(%r1)
+	lfd %f2, RETVAL+8(%r1)
+	lfd %f3, RETVAL+16(%r1)
+	lfd %f4, RETVAL+24(%r1)
+	mtlr %r0
+	lfd %f5, RETVAL+32(%r1)
+	lfd %f6, RETVAL+40(%r1)
+	lfd %f7, RETVAL+48(%r1)
+	lfd %f8, RETVAL+56(%r1)
+	addi %r1, %r1, STACKFRAME
+	blr
+.Lmorefloat:
+	lfs %f4, RETVAL+12(%r1)
+	mtlr %r0
+	lfs %f5, RETVAL+16(%r1)
+	lfs %f6, RETVAL+20(%r1)
+	lfs %f7, RETVAL+24(%r1)
+	lfs %f8, RETVAL+28(%r1)
+	addi %r1, %r1, STACKFRAME
+	blr
+.Lsmall:
+# ifdef __LITTLE_ENDIAN__
+	ld %r3,RETVAL+0(%r1)
+	mtlr %r0
+	ld %r4,RETVAL+8(%r1)
+	addi %r1, %r1, STACKFRAME
+	blr
+# else
+	# A struct smaller than a dword is returned in the low bits of r3
+	# ie. right justified.  Larger structs are passed left justified
+	# in r3 and r4.  The return value area on the stack will have
+	# the structs as they are usually stored in memory.
+	cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
+	neg %r5, %r3
+	ld %r3,RETVAL+0(%r1)
+	blt .Lsmalldown
+	mtlr %r0
+	ld %r4,RETVAL+8(%r1)
+	addi %r1, %r1, STACKFRAME
+	blr
+.Lsmalldown:
+	addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
+	mtlr %r0
+	sldi %r5, %r5, 3
+	addi %r1, %r1, STACKFRAME
+	srd %r3, %r3, %r5
+	blr
+# endif
+
+.LFE1:
+	.long	0
+	.byte	0,12,0,1,128,0,0,0
+# if _CALL_ELF == 2
+	.size	ffi_closure_LINUX64,.-ffi_closure_LINUX64
+# else
+#  ifdef _CALL_LINUX
+	.size	ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
+#  else
+	.size	.ffi_closure_LINUX64,.-.ffi_closure_LINUX64
+#  endif
+# endif
+
+	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
+.LSCIE1:
+	.4byte	0x0	 # CIE Identifier Tag
+	.byte	0x1	 # CIE Version
+	.ascii "zR\0"	 # CIE Augmentation
+	.uleb128 0x1	 # CIE Code Alignment Factor
+	.sleb128 -8	 # CIE Data Alignment Factor
+	.byte	0x41	 # CIE RA Column
+	.uleb128 0x1	 # Augmentation size
+	.byte	0x14	 # FDE Encoding (pcrel udata8)
+	.byte	0xc	 # DW_CFA_def_cfa
+	.uleb128 0x1
+	.uleb128 0x0
+	.align 3
+.LECIE1:
+.LSFDE1:
+	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
+.LASFDE1:
+	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
+	.8byte	.LFB1-.	 # FDE initial location
+	.8byte	.LFE1-.LFB1	 # FDE address range
+	.uleb128 0x0	 # Augmentation size
+	.byte	0x2	 # DW_CFA_advance_loc1
+	.byte	.LCFI0-.LFB1
+	.byte	0xe	 # DW_CFA_def_cfa_offset
+	.uleb128 STACKFRAME
+	.byte	0x11	 # DW_CFA_offset_extended_sf
+	.uleb128 0x41
+	.sleb128 -2
+	.align 3
+.LEFDE1:
+
+#endif
+
+#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/powerpc/ppc_closure.S b/third_party/gofrontend/libffi/src/powerpc/ppc_closure.S
new file mode 100644
index 0000000..0507128
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/ppc_closure.S
@@ -0,0 +1,384 @@
+/* -----------------------------------------------------------------------
+   sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
+	    Copyright (c) 2008 Red Hat, Inc.
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#include <powerpc/asm.h>
+
+	.file   "ppc_closure.S"
+
+#ifndef POWERPC64
+
+ENTRY(ffi_closure_SYSV)
+.LFB1:
+	stwu %r1,-144(%r1)
+.LCFI0:
+	mflr %r0
+.LCFI1:
+	stw %r0,148(%r1)
+
+# we want to build up an areas for the parameters passed
+# in registers (both floating point and integer)
+
+	# so first save gpr 3 to gpr 10 (aligned to 4)
+	stw   %r3, 16(%r1)
+	stw   %r4, 20(%r1)
+	stw   %r5, 24(%r1)
+	stw   %r6, 28(%r1)
+	stw   %r7, 32(%r1)
+	stw   %r8, 36(%r1)
+	stw   %r9, 40(%r1)
+	stw   %r10,44(%r1)
+
+#ifndef __NO_FPRS__
+	# next save fpr 1 to fpr 8 (aligned to 8)
+	stfd  %f1, 48(%r1)
+	stfd  %f2, 56(%r1)
+	stfd  %f3, 64(%r1)
+	stfd  %f4, 72(%r1)
+	stfd  %f5, 80(%r1)
+	stfd  %f6, 88(%r1)
+	stfd  %f7, 96(%r1)
+	stfd  %f8, 104(%r1)
+#endif
+
+	# set up registers for the routine that actually does the work
+	# get the context pointer from the trampoline
+	mr %r3,%r11
+
+	# now load up the pointer to the result storage
+	addi %r4,%r1,112
+
+	# now load up the pointer to the saved gpr registers
+	addi %r5,%r1,16
+
+	# now load up the pointer to the saved fpr registers */
+	addi %r6,%r1,48
+
+	# now load up the pointer to the outgoing parameter
+	# stack in the previous frame
+	# i.e. the previous frame pointer + 8
+	addi %r7,%r1,152
+
+	# make the call
+	bl ffi_closure_helper_SYSV@local
+.Lret:
+	# now r3 contains the return type
+	# so use it to look up in a table
+	# so we know how to deal with each type
+
+	# look up the proper starting point in table
+	# by using return type as offset
+
+	mflr %r4		# move address of .Lret to r4
+	slwi %r3,%r3,4		# now multiply return type by 16
+	addi %r4, %r4, .Lret_type0 - .Lret
+	lwz %r0,148(%r1)
+	add %r3,%r3,%r4		# add contents of table to table address
+	mtctr %r3
+	bctr			# jump to it
+.LFE1:
+
+# Each of the ret_typeX code fragments has to be exactly 16 bytes long
+# (4 instructions). For cache effectiveness we align to a 16 byte boundary
+# first.
+	.align 4
+# case FFI_TYPE_VOID
+.Lret_type0:
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+	nop
+
+# case FFI_TYPE_INT
+	lwz %r3,112+0(%r1)
+	mtlr %r0
+.Lfinish:
+	addi %r1,%r1,144
+	blr
+
+# case FFI_TYPE_FLOAT
+#ifndef __NO_FPRS__
+	lfs %f1,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+#else
+	nop
+	nop
+	nop
+#endif
+	blr
+
+# case FFI_TYPE_DOUBLE
+#ifndef __NO_FPRS__
+	lfd %f1,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+#else
+	nop
+	nop
+	nop
+#endif
+	blr
+
+# case FFI_TYPE_LONGDOUBLE
+#ifndef __NO_FPRS__
+	lfd %f1,112+0(%r1)
+	lfd %f2,112+8(%r1)
+	mtlr %r0
+	b .Lfinish
+#else
+	nop
+	nop
+	nop
+	blr
+#endif
+
+# case FFI_TYPE_UINT8
+#ifdef __LITTLE_ENDIAN__
+	lbz %r3,112+0(%r1)
+#else
+	lbz %r3,112+3(%r1)
+#endif
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+# case FFI_TYPE_SINT8
+#ifdef __LITTLE_ENDIAN__
+	lbz %r3,112+0(%r1)
+#else
+	lbz %r3,112+3(%r1)
+#endif
+	extsb %r3,%r3
+	mtlr %r0
+	b .Lfinish
+
+# case FFI_TYPE_UINT16
+#ifdef __LITTLE_ENDIAN__
+	lhz %r3,112+0(%r1)
+#else
+	lhz %r3,112+2(%r1)
+#endif
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+# case FFI_TYPE_SINT16
+#ifdef __LITTLE_ENDIAN__
+	lha %r3,112+0(%r1)
+#else
+	lha %r3,112+2(%r1)
+#endif
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+# case FFI_TYPE_UINT32
+	lwz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+# case FFI_TYPE_SINT32
+	lwz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+# case FFI_TYPE_UINT64
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+	mtlr %r0
+	b .Lfinish
+
+# case FFI_TYPE_SINT64
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+	mtlr %r0
+	b .Lfinish
+
+# case FFI_TYPE_STRUCT
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+	nop
+
+# case FFI_TYPE_POINTER
+	lwz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+# case FFI_TYPE_UINT128
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+	lwz %r5,112+8(%r1)
+	b .Luint128
+
+# The return types below are only used when the ABI type is FFI_SYSV.
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
+	lbz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
+	lhz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
+	lwz %r3,112+0(%r1)
+#ifdef __LITTLE_ENDIAN__
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+#else
+	srwi %r3,%r3,8
+	mtlr %r0
+	b .Lfinish
+#endif
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
+	lwz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+#ifdef __LITTLE_ENDIAN__
+	mtlr %r0
+	b .Lfinish
+#else
+	li %r5,24
+	b .Lstruct567
+#endif
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+#ifdef __LITTLE_ENDIAN__
+	mtlr %r0
+	b .Lfinish
+#else
+	li %r5,16
+	b .Lstruct567
+#endif
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+#ifdef __LITTLE_ENDIAN__
+	mtlr %r0
+	b .Lfinish
+#else
+	li %r5,8
+	b .Lstruct567
+#endif
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+	mtlr %r0
+	b .Lfinish
+
+#ifndef __LITTLE_ENDIAN__
+.Lstruct567:
+	subfic %r6,%r5,32
+	srw %r4,%r4,%r5
+	slw %r6,%r3,%r6
+	srw %r3,%r3,%r5
+	or %r4,%r6,%r4
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+#endif
+
+.Luint128:
+	lwz %r6,112+12(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+END(ffi_closure_SYSV)
+
+	.section	".eh_frame",EH_FRAME_FLAGS,@progbits
+.Lframe1:
+	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
+.LSCIE1:
+	.4byte	0x0	 # CIE Identifier Tag
+	.byte	0x1	 # CIE Version
+#if defined _RELOCATABLE || defined __PIC__
+	.ascii "zR\0"	 # CIE Augmentation
+#else
+	.ascii "\0"	 # CIE Augmentation
+#endif
+	.uleb128 0x1	 # CIE Code Alignment Factor
+	.sleb128 -4	 # CIE Data Alignment Factor
+	.byte	0x41	 # CIE RA Column
+#if defined _RELOCATABLE || defined __PIC__
+	.uleb128 0x1	 # Augmentation size
+	.byte	0x1b	 # FDE Encoding (pcrel sdata4)
+#endif
+	.byte	0xc	 # DW_CFA_def_cfa
+	.uleb128 0x1
+	.uleb128 0x0
+	.align 2
+.LECIE1:
+.LSFDE1:
+	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
+.LASFDE1:
+	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
+#if defined _RELOCATABLE || defined __PIC__
+	.4byte	.LFB1-.	 # FDE initial location
+#else
+	.4byte	.LFB1	 # FDE initial location
+#endif
+	.4byte	.LFE1-.LFB1	 # FDE address range
+#if defined _RELOCATABLE || defined __PIC__
+	.uleb128 0x0	 # Augmentation size
+#endif
+	.byte	0x4	 # DW_CFA_advance_loc4
+	.4byte	.LCFI0-.LFB1
+	.byte	0xe	 # DW_CFA_def_cfa_offset
+	.uleb128 144
+	.byte	0x4	 # DW_CFA_advance_loc4
+	.4byte	.LCFI1-.LCFI0
+	.byte	0x11	 # DW_CFA_offset_extended_sf
+	.uleb128 0x41
+	.sleb128 -1
+	.align 2
+.LEFDE1:
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
+#endif
diff --git a/third_party/gofrontend/libffi/src/powerpc/sysv.S b/third_party/gofrontend/libffi/src/powerpc/sysv.S
new file mode 100644
index 0000000..fed2380
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/powerpc/sysv.S
@@ -0,0 +1,220 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 1998 Geoffrey Keating
+   Copyright (C) 2007 Free Software Foundation, Inc
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#include <powerpc/asm.h>
+
+#ifndef POWERPC64
+	.globl ffi_prep_args_SYSV
+ENTRY(ffi_call_SYSV)
+.LFB1:
+	/* Save the old stack pointer as AP.  */
+	mr	%r8,%r1
+
+.LCFI0:
+	/* Allocate the stack space we need.  */
+	stwux	%r1,%r1,%r4
+	/* Save registers we use.  */
+	mflr	%r9
+	stw	%r28,-16(%r8)
+.LCFI1:
+	stw	%r29,-12(%r8)
+.LCFI2:
+	stw	%r30, -8(%r8)
+.LCFI3:
+	stw	%r31, -4(%r8)
+.LCFI4:
+	stw	%r9,   4(%r8)
+.LCFI5:
+
+	/* Save arguments over call...  */
+	mr	%r31,%r5	/* flags, */
+	mr	%r30,%r6	/* rvalue, */
+	mr	%r29,%r7	/* function address, */
+	mr	%r28,%r8	/* our AP. */
+.LCFI6:
+
+	/* Call ffi_prep_args_SYSV.  */
+	mr	%r4,%r1
+	bl	ffi_prep_args_SYSV@local
+
+	/* Now do the call.  */
+	/* Set up cr1 with bits 4-7 of the flags.  */
+	mtcrf	0x40,%r31
+	/* Get the address to call into CTR.  */
+	mtctr	%r29
+	/* Load all those argument registers.  */
+	lwz	%r3,-16-(8*4)(%r28)
+	lwz	%r4,-16-(7*4)(%r28)
+	lwz	%r5,-16-(6*4)(%r28)
+	lwz	%r6,-16-(5*4)(%r28)
+	bf-	5,1f
+	nop
+	lwz	%r7,-16-(4*4)(%r28)
+	lwz	%r8,-16-(3*4)(%r28)
+	lwz	%r9,-16-(2*4)(%r28)
+	lwz	%r10,-16-(1*4)(%r28)
+	nop
+1:
+
+#ifndef __NO_FPRS__
+	/* Load all the FP registers.  */
+	bf-	6,2f
+	lfd	%f1,-16-(8*4)-(8*8)(%r28)
+	lfd	%f2,-16-(8*4)-(7*8)(%r28)
+	lfd	%f3,-16-(8*4)-(6*8)(%r28)
+	lfd	%f4,-16-(8*4)-(5*8)(%r28)
+	nop
+	lfd	%f5,-16-(8*4)-(4*8)(%r28)
+	lfd	%f6,-16-(8*4)-(3*8)(%r28)
+	lfd	%f7,-16-(8*4)-(2*8)(%r28)
+	lfd	%f8,-16-(8*4)-(1*8)(%r28)
+#endif
+2:
+
+	/* Make the call.  */
+	bctrl
+
+	/* Now, deal with the return value.  */
+	mtcrf	0x01,%r31 /* cr7  */
+	bt-	31,L(small_struct_return_value)
+	bt-	30,L(done_return_value)
+#ifndef __NO_FPRS__
+	bt-	29,L(fp_return_value)
+#endif
+	stw	%r3,0(%r30)
+	bf+	28,L(done_return_value)
+	stw	%r4,4(%r30)
+	mtcrf	0x02,%r31 /* cr6  */
+	bf	27,L(done_return_value)
+	stw     %r5,8(%r30)
+	stw	%r6,12(%r30)
+	/* Fall through...  */
+
+L(done_return_value):
+	/* Restore the registers we used and return.  */
+	lwz	%r9,   4(%r28)
+	lwz	%r31, -4(%r28)
+	mtlr	%r9
+	lwz	%r30, -8(%r28)
+	lwz	%r29,-12(%r28)
+	lwz	%r28,-16(%r28)
+	lwz	%r1,0(%r1)
+	blr
+
+#ifndef __NO_FPRS__
+L(fp_return_value):
+	bf	28,L(float_return_value)
+	stfd	%f1,0(%r30)
+	mtcrf   0x02,%r31 /* cr6  */
+	bf	27,L(done_return_value)
+	stfd	%f2,8(%r30)
+	b	L(done_return_value)
+L(float_return_value):
+	stfs	%f1,0(%r30)
+	b	L(done_return_value)
+#endif
+
+L(small_struct_return_value):
+	/*
+	 * The C code always allocates a properly-aligned 8-byte bounce
+	 * buffer to make this assembly code very simple.  Just write out
+	 * r3 and r4 to the buffer to allow the C code to handle the rest.
+	 */
+	stw %r3, 0(%r30)
+	stw %r4, 4(%r30)
+	b L(done_return_value)
+
+.LFE1:
+END(ffi_call_SYSV)
+
+      .section	".eh_frame",EH_FRAME_FLAGS,@progbits
+.Lframe1:
+      .4byte    .LECIE1-.LSCIE1  /*  Length of Common Information Entry */
+.LSCIE1:
+      .4byte    0x0      /*  CIE Identifier Tag */
+      .byte     0x1      /*  CIE Version */
+#if defined _RELOCATABLE || defined __PIC__
+      .ascii	"zR\0"   /*  CIE Augmentation */
+#else
+      .ascii	"\0"	 /*  CIE Augmentation */
+#endif
+      .uleb128  0x1      /*  CIE Code Alignment Factor */
+      .sleb128  -4	 /*  CIE Data Alignment Factor */
+      .byte     0x41     /*  CIE RA Column */
+#if defined _RELOCATABLE || defined __PIC__
+      .uleb128  0x1      /*  Augmentation size */
+      .byte	0x1b	 /*  FDE Encoding (pcrel sdata4) */
+#endif
+      .byte     0xc      /*  DW_CFA_def_cfa */
+      .uleb128  0x1
+      .uleb128  0x0
+      .align 2
+.LECIE1:
+.LSFDE1:
+      .4byte    .LEFDE1-.LASFDE1         /*  FDE Length */
+.LASFDE1:
+      .4byte    .LASFDE1-.Lframe1         /*  FDE CIE offset */
+#if defined _RELOCATABLE || defined __PIC__
+      .4byte    .LFB1-.  /*  FDE initial location */
+#else
+      .4byte    .LFB1    /*  FDE initial location */
+#endif
+      .4byte    .LFE1-.LFB1      /*  FDE address range */
+#if defined _RELOCATABLE || defined __PIC__
+      .uleb128  0x0	 /*  Augmentation size */
+#endif
+      .byte     0x4      /*  DW_CFA_advance_loc4 */
+      .4byte    .LCFI0-.LFB1
+      .byte     0xd      /*  DW_CFA_def_cfa_register */
+      .uleb128  0x08
+      .byte     0x4      /*  DW_CFA_advance_loc4 */
+      .4byte    .LCFI5-.LCFI0
+      .byte     0x11     /*  DW_CFA_offset_extended_sf */
+      .uleb128  0x41
+      .sleb128  -1
+      .byte     0x9f     /*  DW_CFA_offset, column 0x1f */
+      .uleb128  0x1
+      .byte     0x9e     /*  DW_CFA_offset, column 0x1e */
+      .uleb128  0x2
+      .byte     0x9d     /*  DW_CFA_offset, column 0x1d */
+      .uleb128  0x3
+      .byte     0x9c     /*  DW_CFA_offset, column 0x1c */
+      .uleb128  0x4
+      .byte     0x4      /*  DW_CFA_advance_loc4 */
+      .4byte    .LCFI6-.LCFI5
+      .byte     0xd      /*  DW_CFA_def_cfa_register */
+      .uleb128  0x1c
+      .align 2
+.LEFDE1:
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
+#endif
diff --git a/third_party/gofrontend/libffi/src/prep_cif.c b/third_party/gofrontend/libffi/src/prep_cif.c
new file mode 100644
index 0000000..866ed34
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/prep_cif.c
@@ -0,0 +1,233 @@
+/* -----------------------------------------------------------------------
+   prep_cif.c - Copyright (c) 2011, 2012  Anthony Green
+                Copyright (c) 1996, 1998, 2007  Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+
+/* Round up to FFI_SIZEOF_ARG. */
+
+#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
+
+/* Perform machine independent initialization of aggregate type
+   specifications. */
+
+static ffi_status initialize_aggregate(ffi_type *arg)
+{
+  ffi_type **ptr;
+
+  if (UNLIKELY(arg == NULL || arg->elements == NULL))
+    return FFI_BAD_TYPEDEF;
+
+  arg->size = 0;
+  arg->alignment = 0;
+
+  ptr = &(arg->elements[0]);
+
+  if (UNLIKELY(ptr == 0))
+    return FFI_BAD_TYPEDEF;
+
+  while ((*ptr) != NULL)
+    {
+      if (UNLIKELY(((*ptr)->size == 0)
+		    && (initialize_aggregate((*ptr)) != FFI_OK)))
+	return FFI_BAD_TYPEDEF;
+
+      /* Perform a sanity check on the argument type */
+      FFI_ASSERT_VALID_TYPE(*ptr);
+
+      arg->size = ALIGN(arg->size, (*ptr)->alignment);
+      arg->size += (*ptr)->size;
+
+      arg->alignment = (arg->alignment > (*ptr)->alignment) ?
+	arg->alignment : (*ptr)->alignment;
+
+      ptr++;
+    }
+
+  /* Structure size includes tail padding.  This is important for
+     structures that fit in one register on ABIs like the PowerPC64
+     Linux ABI that right justify small structs in a register.
+     It's also needed for nested structure layout, for example
+     struct A { long a; char b; }; struct B { struct A x; char y; };
+     should find y at an offset of 2*sizeof(long) and result in a
+     total size of 3*sizeof(long).  */
+  arg->size = ALIGN (arg->size, arg->alignment);
+
+  if (arg->size == 0)
+    return FFI_BAD_TYPEDEF;
+  else
+    return FFI_OK;
+}
+
+#ifndef __CRIS__
+/* The CRIS ABI specifies structure elements to have byte
+   alignment only, so it completely overrides this functions,
+   which assumes "natural" alignment and padding.  */
+
+/* Perform machine independent ffi_cif preparation, then call
+   machine dependent routine. */
+
+/* For non variadic functions isvariadic should be 0 and
+   nfixedargs==ntotalargs.
+
+   For variadic calls, isvariadic should be 1 and nfixedargs
+   and ntotalargs set as appropriate. nfixedargs must always be >=1 */
+
+
+ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
+			     unsigned int isvariadic,
+                             unsigned int nfixedargs,
+                             unsigned int ntotalargs,
+			     ffi_type *rtype, ffi_type **atypes)
+{
+  unsigned bytes = 0;
+  unsigned int i;
+  ffi_type **ptr;
+
+  FFI_ASSERT(cif != NULL);
+  FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
+  FFI_ASSERT(nfixedargs <= ntotalargs);
+
+#ifndef X86_WIN32
+  if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
+    return FFI_BAD_ABI;
+#else
+  if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI || abi == FFI_THISCALL))
+    return FFI_BAD_ABI;
+#endif
+
+  cif->abi = abi;
+  cif->arg_types = atypes;
+  cif->nargs = ntotalargs;
+  cif->rtype = rtype;
+
+  cif->flags = 0;
+
+#if HAVE_LONG_DOUBLE_VARIANT
+  ffi_prep_types (abi);
+#endif
+
+  /* Initialize the return type if necessary */
+  if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
+    return FFI_BAD_TYPEDEF;
+
+  /* Perform a sanity check on the return type */
+  FFI_ASSERT_VALID_TYPE(cif->rtype);
+
+  /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
+#if !defined M68K && !defined X86_ANY && !defined S390 && !defined PA
+  /* Make space for the return structure pointer */
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+#ifdef SPARC
+      && (cif->abi != FFI_V9 || cif->rtype->size > 32)
+#endif
+#ifdef TILE
+      && (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
+#endif
+     )
+    bytes = STACK_ARG_SIZE(sizeof(void*));
+#endif
+
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+
+      /* Initialize any uninitialized aggregate type definitions */
+      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+	return FFI_BAD_TYPEDEF;
+
+      /* Perform a sanity check on the argument type, do this
+	 check after the initialization.  */
+      FFI_ASSERT_VALID_TYPE(*ptr);
+
+#if !defined X86_ANY && !defined S390 && !defined PA
+#ifdef SPARC
+      if (((*ptr)->type == FFI_TYPE_STRUCT
+	   && ((*ptr)->size > 16 || cif->abi != FFI_V9))
+	  || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
+	      && cif->abi != FFI_V9))
+	bytes += sizeof(void*);
+      else
+#endif
+	{
+	  /* Add any padding if necessary */
+	  if (((*ptr)->alignment - 1) & bytes)
+	    bytes = ALIGN(bytes, (*ptr)->alignment);
+
+#ifdef TILE
+	  if (bytes < 10 * FFI_SIZEOF_ARG &&
+	      bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG)
+	    {
+	      /* An argument is never split between the 10 parameter
+		 registers and the stack.  */
+	      bytes = 10 * FFI_SIZEOF_ARG;
+	    }
+#endif
+
+	  bytes += STACK_ARG_SIZE((*ptr)->size);
+	}
+#endif
+    }
+
+  cif->bytes = bytes;
+
+  /* Perform machine dependent cif processing */
+#ifdef FFI_TARGET_SPECIFIC_VARIADIC
+  if (isvariadic)
+	return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
+#endif
+
+  return ffi_prep_cif_machdep(cif);
+}
+#endif /* not __CRIS__ */
+
+ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
+			     ffi_type *rtype, ffi_type **atypes)
+{
+  return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
+}
+
+ffi_status ffi_prep_cif_var(ffi_cif *cif,
+                            ffi_abi abi,
+                            unsigned int nfixedargs,
+                            unsigned int ntotalargs,
+                            ffi_type *rtype,
+                            ffi_type **atypes)
+{
+  return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
+}
+
+#if FFI_CLOSURES
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+		  ffi_cif* cif,
+		  void (*fun)(ffi_cif*,void*,void**,void*),
+		  void *user_data)
+{
+  return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
+}
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/raw_api.c b/third_party/gofrontend/libffi/src/raw_api.c
new file mode 100644
index 0000000..ce21372
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/raw_api.c
@@ -0,0 +1,254 @@
+/* -----------------------------------------------------------------------
+   raw_api.c - Copyright (c) 1999, 2008  Red Hat, Inc.
+
+   Author: Kresten Krab Thorup <krab@gnu.org>
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+/* This file defines generic functions for use with the raw api. */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#if !FFI_NO_RAW_API
+
+size_t
+ffi_raw_size (ffi_cif *cif)
+{
+  size_t result = 0;
+  int i;
+
+  ffi_type **at = cif->arg_types;
+
+  for (i = cif->nargs-1; i >= 0; i--, at++)
+    {
+#if !FFI_NO_STRUCTS
+      if ((*at)->type == FFI_TYPE_STRUCT)
+	result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
+      else
+#endif
+	result += ALIGN ((*at)->size, FFI_SIZEOF_ARG);
+    }
+
+  return result;
+}
+
+
+void
+ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+#if WORDS_BIGENDIAN
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {	  
+      switch ((*tp)->type)
+	{
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT8:
+	  *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
+	  break;
+	  
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT16:
+	  *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
+	  break;
+
+#if FFI_SIZEOF_ARG >= 4	  
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	  *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
+	  break;
+#endif
+	
+#if !FFI_NO_STRUCTS  
+	case FFI_TYPE_STRUCT:
+	  *args = (raw++)->ptr;
+	  break;
+#endif
+
+	case FFI_TYPE_POINTER:
+	  *args = (void*) &(raw++)->ptr;
+	  break;
+	  
+	default:
+	  *args = raw;
+	  raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+	}
+    }
+
+#else /* WORDS_BIGENDIAN */
+
+#if !PDP
+
+  /* then assume little endian */
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {	  
+#if !FFI_NO_STRUCTS
+      if ((*tp)->type == FFI_TYPE_STRUCT)
+	{
+	  *args = (raw++)->ptr;
+	}
+      else
+#endif
+	{
+	  *args = (void*) raw;
+	  raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
+	}
+    }
+
+#else
+#error "pdp endian not supported"
+#endif /* ! PDP */
+
+#endif /* WORDS_BIGENDIAN */
+}
+
+void
+ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {	  
+      switch ((*tp)->type)
+	{
+	case FFI_TYPE_UINT8:
+	  (raw++)->uint = *(UINT8*) (*args);
+	  break;
+
+	case FFI_TYPE_SINT8:
+	  (raw++)->sint = *(SINT8*) (*args);
+	  break;
+
+	case FFI_TYPE_UINT16:
+	  (raw++)->uint = *(UINT16*) (*args);
+	  break;
+
+	case FFI_TYPE_SINT16:
+	  (raw++)->sint = *(SINT16*) (*args);
+	  break;
+
+#if FFI_SIZEOF_ARG >= 4
+	case FFI_TYPE_UINT32:
+	  (raw++)->uint = *(UINT32*) (*args);
+	  break;
+
+	case FFI_TYPE_SINT32:
+	  (raw++)->sint = *(SINT32*) (*args);
+	  break;
+#endif
+
+#if !FFI_NO_STRUCTS
+	case FFI_TYPE_STRUCT:
+	  (raw++)->ptr = *args;
+	  break;
+#endif
+
+	case FFI_TYPE_POINTER:
+	  (raw++)->ptr = **(void***) args;
+	  break;
+
+	default:
+	  memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
+	  raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+	}
+    }
+}
+
+#if !FFI_NATIVE_RAW_API
+
+
+/* This is a generic definition of ffi_raw_call, to be used if the
+ * native system does not provide a machine-specific implementation.
+ * Having this, allows code to be written for the raw API, without
+ * the need for system-specific code to handle input in that format;
+ * these following couple of functions will handle the translation forth
+ * and back automatically. */
+
+void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw)
+{
+  void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
+  ffi_raw_to_ptrarray (cif, raw, avalue);
+  ffi_call (cif, fn, rvalue, avalue);
+}
+
+#if FFI_CLOSURES		/* base system provides closures */
+
+static void
+ffi_translate_args (ffi_cif *cif, void *rvalue,
+		    void **avalue, void *user_data)
+{
+  ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
+  ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
+
+  ffi_ptrarray_to_raw (cif, avalue, raw);
+  (*cl->fun) (cif, rvalue, raw, cl->user_data);
+}
+
+ffi_status
+ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
+			  ffi_cif *cif,
+			  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+			  void *user_data,
+			  void *codeloc)
+{
+  ffi_status status;
+
+  status = ffi_prep_closure_loc ((ffi_closure*) cl,
+				 cif,
+				 &ffi_translate_args,
+				 codeloc,
+				 codeloc);
+  if (status == FFI_OK)
+    {
+      cl->fun       = fun;
+      cl->user_data = user_data;
+    }
+
+  return status;
+}
+
+#endif /* FFI_CLOSURES */
+#endif /* !FFI_NATIVE_RAW_API */
+
+#if FFI_CLOSURES
+
+/* Again, here is the generic version of ffi_prep_raw_closure, which
+ * will install an intermediate "hub" for translation of arguments from
+ * the pointer-array format, to the raw format */
+
+ffi_status
+ffi_prep_raw_closure (ffi_raw_closure* cl,
+		      ffi_cif *cif,
+		      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+		      void *user_data)
+{
+  return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
+}
+
+#endif /* FFI_CLOSURES */
+
+#endif /* !FFI_NO_RAW_API */
diff --git a/third_party/gofrontend/libffi/src/s390/ffi.c b/third_party/gofrontend/libffi/src/s390/ffi.c
new file mode 100644
index 0000000..8adb5bc
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/s390/ffi.c
@@ -0,0 +1,781 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2000, 2007 Software AG
+           Copyright (c) 2008 Red Hat, Inc
+ 
+   S390 Foreign Function Interface
+ 
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+ 
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+ 
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+/*====================================================================*/
+/*                          Includes                                  */
+/*                          --------                                  */
+/*====================================================================*/
+ 
+#include <ffi.h>
+#include <ffi_common.h>
+ 
+#include <stdlib.h>
+#include <stdio.h>
+ 
+/*====================== End of Includes =============================*/
+ 
+/*====================================================================*/
+/*                           Defines                                  */
+/*                           -------                                  */
+/*====================================================================*/
+
+/* Maximum number of GPRs available for argument passing.  */ 
+#define MAX_GPRARGS 5
+
+/* Maximum number of FPRs available for argument passing.  */ 
+#ifdef __s390x__
+#define MAX_FPRARGS 4
+#else
+#define MAX_FPRARGS 2
+#endif
+
+/* Round to multiple of 16.  */
+#define ROUND_SIZE(size) (((size) + 15) & ~15)
+
+/* If these values change, sysv.S must be adapted!  */
+#define FFI390_RET_VOID		0
+#define FFI390_RET_STRUCT	1
+#define FFI390_RET_FLOAT	2
+#define FFI390_RET_DOUBLE	3
+#define FFI390_RET_INT32	4
+#define FFI390_RET_INT64	5
+
+/*===================== End of Defines ===============================*/
+ 
+/*====================================================================*/
+/*                          Prototypes                                */
+/*                          ----------                                */
+/*====================================================================*/
+ 
+static void ffi_prep_args (unsigned char *, extended_cif *);
+void
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+__attribute__ ((visibility ("hidden")))
+#endif
+ffi_closure_helper_SYSV (ffi_closure *, unsigned long *, 
+			 unsigned long long *, unsigned long *);
+
+/*====================== End of Prototypes ===========================*/
+ 
+/*====================================================================*/
+/*                          Externals                                 */
+/*                          ---------                                 */
+/*====================================================================*/
+ 
+extern void ffi_call_SYSV(unsigned,
+			  extended_cif *,
+			  void (*)(unsigned char *, extended_cif *),
+			  unsigned,
+			  void *,
+			  void (*fn)(void));
+
+extern void ffi_closure_SYSV(void);
+ 
+/*====================== End of Externals ============================*/
+ 
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_check_struct_type.                                  */
+/*                                                                    */
+/* Function - Determine if a structure can be passed within a         */
+/*            general purpose or floating point register.             */
+/*                                                                    */
+/*====================================================================*/
+ 
+static int
+ffi_check_struct_type (ffi_type *arg)
+{
+  size_t size = arg->size;
+
+  /* If the struct has just one element, look at that element
+     to find out whether to consider the struct as floating point.  */
+  while (arg->type == FFI_TYPE_STRUCT 
+         && arg->elements[0] && !arg->elements[1])
+    arg = arg->elements[0];
+
+  /* Structs of size 1, 2, 4, and 8 are passed in registers,
+     just like the corresponding int/float types.  */
+  switch (size)
+    {
+      case 1:
+        return FFI_TYPE_UINT8;
+
+      case 2:
+        return FFI_TYPE_UINT16;
+
+      case 4:
+	if (arg->type == FFI_TYPE_FLOAT)
+          return FFI_TYPE_FLOAT;
+	else
+	  return FFI_TYPE_UINT32;
+
+      case 8:
+	if (arg->type == FFI_TYPE_DOUBLE)
+          return FFI_TYPE_DOUBLE;
+	else
+	  return FFI_TYPE_UINT64;
+
+      default:
+	break;
+    }
+
+  /* Other structs are passed via a pointer to the data.  */
+  return FFI_TYPE_POINTER;
+}
+ 
+/*======================== End of Routine ============================*/
+ 
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_prep_args.                                          */
+/*                                                                    */
+/* Function - Prepare parameters for call to function.                */
+/*                                                                    */
+/* ffi_prep_args is called by the assembly routine once stack space   */
+/* has been allocated for the function's arguments.                   */
+/*                                                                    */
+/*====================================================================*/
+ 
+static void
+ffi_prep_args (unsigned char *stack, extended_cif *ecif)
+{
+  /* The stack space will be filled with those areas:
+
+	FPR argument register save area     (highest addresses)
+	GPR argument register save area
+	temporary struct copies
+	overflow argument area              (lowest addresses)
+
+     We set up the following pointers:
+
+        p_fpr: bottom of the FPR area (growing upwards)
+	p_gpr: bottom of the GPR area (growing upwards)
+	p_ov: bottom of the overflow area (growing upwards)
+	p_struct: top of the struct copy area (growing downwards)
+
+     All areas are kept aligned to twice the word size.  */
+
+  int gpr_off = ecif->cif->bytes;
+  int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
+
+  unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
+  unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
+  unsigned char *p_struct = (unsigned char *)p_gpr;
+  unsigned long *p_ov = (unsigned long *)stack;
+
+  int n_fpr = 0;
+  int n_gpr = 0;
+  int n_ov = 0;
+
+  ffi_type **ptr;
+  void **p_argv = ecif->avalue;
+  int i;
+ 
+  /* If we returning a structure then we set the first parameter register
+     to the address of where we are returning this structure.  */
+
+  if (ecif->cif->flags == FFI390_RET_STRUCT)
+    p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
+
+  /* Now for the arguments.  */
+ 
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv++)
+    {
+      void *arg = *p_argv;
+      int type = (*ptr)->type;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      /* 16-byte long double is passed like a struct.  */
+      if (type == FFI_TYPE_LONGDOUBLE)
+	type = FFI_TYPE_STRUCT;
+#endif
+
+      /* Check how a structure type is passed.  */
+      if (type == FFI_TYPE_STRUCT)
+	{
+	  type = ffi_check_struct_type (*ptr);
+
+	  /* If we pass the struct via pointer, copy the data.  */
+	  if (type == FFI_TYPE_POINTER)
+	    {
+	      p_struct -= ROUND_SIZE ((*ptr)->size);
+	      memcpy (p_struct, (char *)arg, (*ptr)->size);
+	      arg = &p_struct;
+	    }
+	}
+
+      /* Now handle all primitive int/pointer/float data types.  */
+      switch (type) 
+	{
+	  case FFI_TYPE_DOUBLE:
+	    if (n_fpr < MAX_FPRARGS)
+	      p_fpr[n_fpr++] = *(unsigned long long *) arg;
+	    else
+#ifdef __s390x__
+	      p_ov[n_ov++] = *(unsigned long *) arg;
+#else
+	      p_ov[n_ov++] = ((unsigned long *) arg)[0],
+	      p_ov[n_ov++] = ((unsigned long *) arg)[1];
+#endif
+	    break;
+	
+	  case FFI_TYPE_FLOAT:
+	    if (n_fpr < MAX_FPRARGS)
+	      p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
+	    else
+	      p_ov[n_ov++] = *(unsigned int *) arg;
+	    break;
+
+	  case FFI_TYPE_POINTER:
+	    if (n_gpr < MAX_GPRARGS)
+	      p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg;
+	    else
+	      p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg;
+	    break;
+ 
+	  case FFI_TYPE_UINT64:
+	  case FFI_TYPE_SINT64:
+#ifdef __s390x__
+	    if (n_gpr < MAX_GPRARGS)
+	      p_gpr[n_gpr++] = *(unsigned long *) arg;
+	    else
+	      p_ov[n_ov++] = *(unsigned long *) arg;
+#else
+	    if (n_gpr == MAX_GPRARGS-1)
+	      n_gpr = MAX_GPRARGS;
+	    if (n_gpr < MAX_GPRARGS)
+	      p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
+	      p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
+	    else
+	      p_ov[n_ov++] = ((unsigned long *) arg)[0],
+	      p_ov[n_ov++] = ((unsigned long *) arg)[1];
+#endif
+	    break;
+ 
+	  case FFI_TYPE_UINT32:
+	    if (n_gpr < MAX_GPRARGS)
+	      p_gpr[n_gpr++] = *(unsigned int *) arg;
+	    else
+	      p_ov[n_ov++] = *(unsigned int *) arg;
+	    break;
+ 
+	  case FFI_TYPE_INT:
+	  case FFI_TYPE_SINT32:
+	    if (n_gpr < MAX_GPRARGS)
+	      p_gpr[n_gpr++] = *(signed int *) arg;
+	    else
+	      p_ov[n_ov++] = *(signed int *) arg;
+	    break;
+ 
+	  case FFI_TYPE_UINT16:
+	    if (n_gpr < MAX_GPRARGS)
+	      p_gpr[n_gpr++] = *(unsigned short *) arg;
+	    else
+	      p_ov[n_ov++] = *(unsigned short *) arg;
+	    break;
+ 
+	  case FFI_TYPE_SINT16:
+	    if (n_gpr < MAX_GPRARGS)
+	      p_gpr[n_gpr++] = *(signed short *) arg;
+	    else
+	      p_ov[n_ov++] = *(signed short *) arg;
+	    break;
+
+	  case FFI_TYPE_UINT8:
+	    if (n_gpr < MAX_GPRARGS)
+	      p_gpr[n_gpr++] = *(unsigned char *) arg;
+	    else
+	      p_ov[n_ov++] = *(unsigned char *) arg;
+	    break;
+ 
+	  case FFI_TYPE_SINT8:
+	    if (n_gpr < MAX_GPRARGS)
+	      p_gpr[n_gpr++] = *(signed char *) arg;
+	    else
+	      p_ov[n_ov++] = *(signed char *) arg;
+	    break;
+ 
+	  default:
+	    FFI_ASSERT (0);
+	    break;
+        }
+    }
+}
+
+/*======================== End of Routine ============================*/
+ 
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_prep_cif_machdep.                                   */
+/*                                                                    */
+/* Function - Perform machine dependent CIF processing.               */
+/*                                                                    */
+/*====================================================================*/
+ 
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  size_t struct_size = 0;
+  int n_gpr = 0;
+  int n_fpr = 0;
+  int n_ov = 0;
+
+  ffi_type **ptr;
+  int i;
+
+  /* Determine return value handling.  */ 
+
+  switch (cif->rtype->type)
+    {
+      /* Void is easy.  */
+      case FFI_TYPE_VOID:
+	cif->flags = FFI390_RET_VOID;
+	break;
+
+      /* Structures are returned via a hidden pointer.  */
+      case FFI_TYPE_STRUCT:
+	cif->flags = FFI390_RET_STRUCT;
+	n_gpr++;  /* We need one GPR to pass the pointer.  */
+	break; 
+
+      /* Floating point values are returned in fpr 0.  */
+      case FFI_TYPE_FLOAT:
+	cif->flags = FFI390_RET_FLOAT;
+	break;
+
+      case FFI_TYPE_DOUBLE:
+	cif->flags = FFI390_RET_DOUBLE;
+	break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      case FFI_TYPE_LONGDOUBLE:
+	cif->flags = FFI390_RET_STRUCT;
+	n_gpr++;
+	break;
+#endif
+      /* Integer values are returned in gpr 2 (and gpr 3
+	 for 64-bit values on 31-bit machines).  */
+      case FFI_TYPE_UINT64:
+      case FFI_TYPE_SINT64:
+	cif->flags = FFI390_RET_INT64;
+	break;
+
+      case FFI_TYPE_POINTER:
+      case FFI_TYPE_INT:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_UINT16:
+      case FFI_TYPE_SINT16:
+      case FFI_TYPE_UINT8:
+      case FFI_TYPE_SINT8:
+	/* These are to be extended to word size.  */
+#ifdef __s390x__
+	cif->flags = FFI390_RET_INT64;
+#else
+	cif->flags = FFI390_RET_INT32;
+#endif
+	break;
+ 
+      default:
+        FFI_ASSERT (0);
+        break;
+    }
+
+  /* Now for the arguments.  */
+ 
+  for (ptr = cif->arg_types, i = cif->nargs;
+       i > 0;
+       i--, ptr++)
+    {
+      int type = (*ptr)->type;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      /* 16-byte long double is passed like a struct.  */
+      if (type == FFI_TYPE_LONGDOUBLE)
+	type = FFI_TYPE_STRUCT;
+#endif
+
+      /* Check how a structure type is passed.  */
+      if (type == FFI_TYPE_STRUCT)
+	{
+	  type = ffi_check_struct_type (*ptr);
+
+	  /* If we pass the struct via pointer, we must reserve space
+	     to copy its data for proper call-by-value semantics.  */
+	  if (type == FFI_TYPE_POINTER)
+	    struct_size += ROUND_SIZE ((*ptr)->size);
+	}
+
+      /* Now handle all primitive int/float data types.  */
+      switch (type) 
+	{
+	  /* The first MAX_FPRARGS floating point arguments
+	     go in FPRs, the rest overflow to the stack.  */
+
+	  case FFI_TYPE_DOUBLE:
+	    if (n_fpr < MAX_FPRARGS)
+	      n_fpr++;
+	    else
+	      n_ov += sizeof (double) / sizeof (long);
+	    break;
+	
+	  case FFI_TYPE_FLOAT:
+	    if (n_fpr < MAX_FPRARGS)
+	      n_fpr++;
+	    else
+	      n_ov++;
+	    break;
+
+	  /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
+	     if one is still available, or else on the stack.  If only one
+	     register is free, skip the register (it won't be used for any 
+	     subsequent argument either).  */
+	      
+#ifndef __s390x__
+	  case FFI_TYPE_UINT64:
+	  case FFI_TYPE_SINT64:
+	    if (n_gpr == MAX_GPRARGS-1)
+	      n_gpr = MAX_GPRARGS;
+	    if (n_gpr < MAX_GPRARGS)
+	      n_gpr += 2;
+	    else
+	      n_ov += 2;
+	    break;
+#endif
+
+	  /* Everything else is passed in GPRs (until MAX_GPRARGS
+	     have been used) or overflows to the stack.  */
+
+	  default: 
+	    if (n_gpr < MAX_GPRARGS)
+	      n_gpr++;
+	    else
+	      n_ov++;
+	    break;
+        }
+    }
+
+  /* Total stack space as required for overflow arguments
+     and temporary structure copies.  */
+
+  cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
+ 
+  return FFI_OK;
+}
+ 
+/*======================== End of Routine ============================*/
+ 
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_call.                                               */
+/*                                                                    */
+/* Function - Call the FFI routine.                                   */
+/*                                                                    */
+/*====================================================================*/
+ 
+void
+ffi_call(ffi_cif *cif,
+	 void (*fn)(void),
+	 void *rvalue,
+	 void **avalue)
+{
+  int ret_type = cif->flags;
+  extended_cif ecif;
+ 
+  ecif.cif    = cif;
+  ecif.avalue = avalue;
+  ecif.rvalue = rvalue;
+
+  /* If we don't have a return value, we need to fake one.  */
+  if (rvalue == NULL)
+    {
+      if (ret_type == FFI390_RET_STRUCT)
+	ecif.rvalue = alloca (cif->rtype->size);
+      else
+	ret_type = FFI390_RET_VOID;
+    } 
+
+  switch (cif->abi)
+    {
+      case FFI_SYSV:
+        ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
+		       ret_type, ecif.rvalue, fn);
+        break;
+ 
+      default:
+        FFI_ASSERT (0);
+        break;
+    }
+}
+ 
+/*======================== End of Routine ============================*/
+
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_closure_helper_SYSV.                                */
+/*                                                                    */
+/* Function - Call a FFI closure target function.                     */
+/*                                                                    */
+/*====================================================================*/
+ 
+void
+ffi_closure_helper_SYSV (ffi_closure *closure,
+			 unsigned long *p_gpr,
+			 unsigned long long *p_fpr,
+			 unsigned long *p_ov)
+{
+  unsigned long long ret_buffer;
+
+  void *rvalue = &ret_buffer;
+  void **avalue;
+  void **p_arg;
+
+  int n_gpr = 0;
+  int n_fpr = 0;
+  int n_ov = 0;
+
+  ffi_type **ptr;
+  int i;
+
+  /* Allocate buffer for argument list pointers.  */
+
+  p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
+
+  /* If we returning a structure, pass the structure address 
+     directly to the target function.  Otherwise, have the target 
+     function store the return value to the GPR save area.  */
+
+  if (closure->cif->flags == FFI390_RET_STRUCT)
+    rvalue = (void *) p_gpr[n_gpr++];
+
+  /* Now for the arguments.  */
+
+  for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
+       i > 0;
+       i--, p_arg++, ptr++)
+    {
+      int deref_struct_pointer = 0;
+      int type = (*ptr)->type;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      /* 16-byte long double is passed like a struct.  */
+      if (type == FFI_TYPE_LONGDOUBLE)
+	type = FFI_TYPE_STRUCT;
+#endif
+
+      /* Check how a structure type is passed.  */
+      if (type == FFI_TYPE_STRUCT)
+	{
+	  type = ffi_check_struct_type (*ptr);
+
+	  /* If we pass the struct via pointer, remember to 
+	     retrieve the pointer later.  */
+	  if (type == FFI_TYPE_POINTER)
+	    deref_struct_pointer = 1;
+	}
+
+      /* Pointers are passed like UINTs of the same size.  */
+      if (type == FFI_TYPE_POINTER)
+#ifdef __s390x__
+	type = FFI_TYPE_UINT64;
+#else
+	type = FFI_TYPE_UINT32;
+#endif
+
+      /* Now handle all primitive int/float data types.  */
+      switch (type) 
+	{
+	  case FFI_TYPE_DOUBLE:
+	    if (n_fpr < MAX_FPRARGS)
+	      *p_arg = &p_fpr[n_fpr++];
+	    else
+	      *p_arg = &p_ov[n_ov], 
+	      n_ov += sizeof (double) / sizeof (long);
+	    break;
+	
+	  case FFI_TYPE_FLOAT:
+	    if (n_fpr < MAX_FPRARGS)
+	      *p_arg = &p_fpr[n_fpr++];
+	    else
+	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
+	    break;
+ 
+	  case FFI_TYPE_UINT64:
+	  case FFI_TYPE_SINT64:
+#ifdef __s390x__
+	    if (n_gpr < MAX_GPRARGS)
+	      *p_arg = &p_gpr[n_gpr++];
+	    else
+	      *p_arg = &p_ov[n_ov++];
+#else
+	    if (n_gpr == MAX_GPRARGS-1)
+	      n_gpr = MAX_GPRARGS;
+	    if (n_gpr < MAX_GPRARGS)
+	      *p_arg = &p_gpr[n_gpr], n_gpr += 2;
+	    else
+	      *p_arg = &p_ov[n_ov], n_ov += 2;
+#endif
+	    break;
+ 
+	  case FFI_TYPE_INT:
+	  case FFI_TYPE_UINT32:
+	  case FFI_TYPE_SINT32:
+	    if (n_gpr < MAX_GPRARGS)
+	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4;
+	    else
+	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
+	    break;
+ 
+	  case FFI_TYPE_UINT16:
+	  case FFI_TYPE_SINT16:
+	    if (n_gpr < MAX_GPRARGS)
+	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2;
+	    else
+	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2;
+	    break;
+
+	  case FFI_TYPE_UINT8:
+	  case FFI_TYPE_SINT8:
+	    if (n_gpr < MAX_GPRARGS)
+	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1;
+	    else
+	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
+	    break;
+ 
+	  default:
+	    FFI_ASSERT (0);
+	    break;
+        }
+
+      /* If this is a struct passed via pointer, we need to
+	 actually retrieve that pointer.  */
+      if (deref_struct_pointer)
+	*p_arg = *(void **)*p_arg;
+    }
+
+
+  /* Call the target function.  */
+  (closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
+
+  /* Convert the return value.  */
+  switch (closure->cif->rtype->type)
+    {
+      /* Void is easy, and so is struct.  */
+      case FFI_TYPE_VOID:
+      case FFI_TYPE_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      case FFI_TYPE_LONGDOUBLE:
+#endif
+	break;
+
+      /* Floating point values are returned in fpr 0.  */
+      case FFI_TYPE_FLOAT:
+	p_fpr[0] = (long long) *(unsigned int *) rvalue << 32;
+	break;
+
+      case FFI_TYPE_DOUBLE:
+	p_fpr[0] = *(unsigned long long *) rvalue;
+	break;
+
+      /* Integer values are returned in gpr 2 (and gpr 3
+	 for 64-bit values on 31-bit machines).  */
+      case FFI_TYPE_UINT64:
+      case FFI_TYPE_SINT64:
+#ifdef __s390x__
+	p_gpr[0] = *(unsigned long *) rvalue;
+#else
+	p_gpr[0] = ((unsigned long *) rvalue)[0],
+	p_gpr[1] = ((unsigned long *) rvalue)[1];
+#endif
+	break;
+
+      case FFI_TYPE_POINTER:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_UINT16:
+      case FFI_TYPE_UINT8:
+	p_gpr[0] = *(unsigned long *) rvalue;
+	break;
+
+      case FFI_TYPE_INT:
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_SINT16:
+      case FFI_TYPE_SINT8:
+	p_gpr[0] = *(signed long *) rvalue;
+	break;
+
+      default:
+        FFI_ASSERT (0);
+        break;
+    }
+}
+ 
+/*======================== End of Routine ============================*/
+
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_prep_closure_loc.                                   */
+/*                                                                    */
+/* Function - Prepare a FFI closure.                                  */
+/*                                                                    */
+/*====================================================================*/
+ 
+ffi_status
+ffi_prep_closure_loc (ffi_closure *closure,
+		      ffi_cif *cif,
+		      void (*fun) (ffi_cif *, void *, void **, void *),
+		      void *user_data,
+		      void *codeloc)
+{
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+#ifndef __s390x__
+  *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
+  *(short *)&closure->tramp [2] = 0x9801;   /* lm %r0,%r1,6(%r1) */
+  *(short *)&closure->tramp [4] = 0x1006;
+  *(short *)&closure->tramp [6] = 0x07f1;   /* br %r1 */
+  *(long  *)&closure->tramp [8] = (long)codeloc;
+  *(long  *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
+#else
+  *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
+  *(short *)&closure->tramp [2] = 0xeb01;   /* lmg %r0,%r1,14(%r1) */
+  *(short *)&closure->tramp [4] = 0x100e;
+  *(short *)&closure->tramp [6] = 0x0004;
+  *(short *)&closure->tramp [8] = 0x07f1;   /* br %r1 */
+  *(long  *)&closure->tramp[16] = (long)codeloc;
+  *(long  *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
+#endif 
+ 
+  closure->cif = cif;
+  closure->user_data = user_data;
+  closure->fun = fun;
+ 
+  return FFI_OK;
+}
+
+/*======================== End of Routine ============================*/
+ 
diff --git a/third_party/gofrontend/libffi/src/s390/ffitarget.h b/third_party/gofrontend/libffi/src/s390/ffitarget.h
new file mode 100644
index 0000000..97fa5c4
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/s390/ffitarget.h
@@ -0,0 +1,67 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for S390.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#if defined (__s390x__)
+#ifndef S390X
+#define S390X
+#endif
+#endif
+
+/* ---- System specific configurations ----------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#ifdef S390X
+#define FFI_TRAMPOLINE_SIZE 32
+#else
+#define FFI_TRAMPOLINE_SIZE 16
+#endif
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/third_party/gofrontend/libffi/src/s390/sysv.S b/third_party/gofrontend/libffi/src/s390/sysv.S
new file mode 100644
index 0000000..4731a31
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/s390/sysv.S
@@ -0,0 +1,434 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2000 Software AG
+            Copyright (c) 2008 Red Hat, Inc.
+ 
+   S390 Foreign Function Interface
+ 
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+ 
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+ 
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+#ifndef __s390x__
+ 
+.text
+
+	# r2:	cif->bytes
+	# r3:	&ecif
+	# r4:	ffi_prep_args
+	# r5:	ret_type
+	# r6:	ecif.rvalue
+	# ov:	fn 
+ 
+	# This assumes we are using gas.
+	.globl	ffi_call_SYSV
+	.type	ffi_call_SYSV,%function
+ffi_call_SYSV:
+.LFB1:
+	stm	%r6,%r15,24(%r15)		# Save registers
+.LCFI0:
+	basr	%r13,0				# Set up base register
+.Lbase:
+	lr	%r11,%r15			# Set up frame pointer
+.LCFI1:
+	sr	%r15,%r2
+	ahi	%r15,-96-48			# Allocate stack
+	lr	%r8,%r6				# Save ecif.rvalue
+	sr	%r9,%r9
+	ic	%r9,.Ltable-.Lbase(%r13,%r5)	# Load epilog address
+	l	%r7,96(%r11)			# Load function address
+	st	%r11,0(%r15)			# Set up back chain
+	ahi	%r11,-48			# Register save area
+.LCFI2:
+
+	la	%r2,96(%r15)			# Save area
+						# r3 already holds &ecif
+	basr	%r14,%r4			# Call ffi_prep_args
+
+	lm	%r2,%r6,0(%r11)			# Load arguments
+	ld	%f0,32(%r11)
+	ld	%f2,40(%r11)
+	la	%r14,0(%r13,%r9)		# Set return address
+	br	%r7				# ... and call function
+
+.LretNone:					# Return void
+	l	%r4,48+56(%r11)
+	lm	%r6,%r15,48+24(%r11)
+	br	%r4
+
+.LretFloat:
+	l	%r4,48+56(%r11)
+	ste	%f0,0(%r8)			# Return float
+	lm	%r6,%r15,48+24(%r11)
+	br	%r4
+ 
+.LretDouble:
+	l	%r4,48+56(%r11)
+	std	%f0,0(%r8)			# Return double
+	lm	%r6,%r15,48+24(%r11)
+	br	%r4
+
+.LretInt32:
+	l	%r4,48+56(%r11)
+	st	%r2,0(%r8)			# Return int
+	lm	%r6,%r15,48+24(%r11)
+	br	%r4
+ 
+.LretInt64:
+	l	%r4,48+56(%r11)
+	stm	%r2,%r3,0(%r8)			# Return long long
+	lm	%r6,%r15,48+24(%r11)
+	br	%r4
+ 
+.Ltable:
+	.byte	.LretNone-.Lbase		# FFI390_RET_VOID
+	.byte	.LretNone-.Lbase		# FFI390_RET_STRUCT
+	.byte	.LretFloat-.Lbase		# FFI390_RET_FLOAT
+	.byte	.LretDouble-.Lbase		# FFI390_RET_DOUBLE
+	.byte	.LretInt32-.Lbase		# FFI390_RET_INT32
+	.byte	.LretInt64-.Lbase		# FFI390_RET_INT64
+
+.LFE1: 
+.ffi_call_SYSV_end:
+	.size	 ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+
+
+	.globl	ffi_closure_SYSV
+	.type	ffi_closure_SYSV,%function
+ffi_closure_SYSV:
+.LFB2:
+	stm	%r12,%r15,48(%r15)		# Save registers
+.LCFI10:
+	basr	%r13,0				# Set up base register
+.Lcbase:
+	stm	%r2,%r6,8(%r15)			# Save arguments
+	std	%f0,64(%r15)
+	std	%f2,72(%r15)
+	lr	%r1,%r15			# Set up stack frame
+	ahi	%r15,-96
+.LCFI11:
+	l	%r12,.Lchelper-.Lcbase(%r13)	# Get helper function
+	lr	%r2,%r0				# Closure
+	la	%r3,8(%r1)			# GPRs
+	la	%r4,64(%r1)			# FPRs
+	la	%r5,96(%r1)			# Overflow
+	st	%r1,0(%r15)			# Set up back chain
+
+	bas	%r14,0(%r12,%r13)		# Call helper
+
+	l	%r4,96+56(%r15)
+	ld	%f0,96+64(%r15)			# Load return registers
+	lm	%r2,%r3,96+8(%r15)
+	lm	%r12,%r15,96+48(%r15)
+	br	%r4
+
+	.align 4
+.Lchelper:
+	.long	ffi_closure_helper_SYSV-.Lcbase
+
+.LFE2: 
+
+.ffi_closure_SYSV_end:
+	.size	 ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
+
+
+	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+	.4byte	.LECIE1-.LSCIE1	# Length of Common Information Entry
+.LSCIE1:
+	.4byte	0x0	# CIE Identifier Tag
+	.byte	0x1	# CIE Version
+	.ascii "zR\0"	# CIE Augmentation
+	.uleb128 0x1	# CIE Code Alignment Factor
+	.sleb128 -4	# CIE Data Alignment Factor
+	.byte	0xe	# CIE RA Column
+	.uleb128 0x1	# Augmentation size
+	.byte	0x1b	# FDE Encoding (pcrel sdata4)
+	.byte	0xc	# DW_CFA_def_cfa
+	.uleb128 0xf
+	.uleb128 0x60
+	.align	4
+.LECIE1:
+.LSFDE1:
+	.4byte	.LEFDE1-.LASFDE1	# FDE Length
+.LASFDE1:
+	.4byte	.LASFDE1-.Lframe1	# FDE CIE offset
+	.4byte	.LFB1-.	# FDE initial location
+	.4byte	.LFE1-.LFB1	# FDE address range
+	.uleb128 0x0	# Augmentation size
+	.byte	0x4	# DW_CFA_advance_loc4
+	.4byte	.LCFI0-.LFB1
+	.byte	0x8f	# DW_CFA_offset, column 0xf
+	.uleb128 0x9
+	.byte	0x8e	# DW_CFA_offset, column 0xe
+	.uleb128 0xa
+	.byte	0x8d	# DW_CFA_offset, column 0xd
+	.uleb128 0xb
+	.byte	0x8c	# DW_CFA_offset, column 0xc
+	.uleb128 0xc
+	.byte	0x8b	# DW_CFA_offset, column 0xb
+	.uleb128 0xd
+	.byte	0x8a	# DW_CFA_offset, column 0xa
+	.uleb128 0xe
+	.byte	0x89	# DW_CFA_offset, column 0x9
+	.uleb128 0xf
+	.byte	0x88	# DW_CFA_offset, column 0x8
+	.uleb128 0x10
+	.byte	0x87	# DW_CFA_offset, column 0x7
+	.uleb128 0x11
+	.byte	0x86	# DW_CFA_offset, column 0x6
+	.uleb128 0x12
+	.byte	0x4	# DW_CFA_advance_loc4
+	.4byte	.LCFI1-.LCFI0
+	.byte	0xd	# DW_CFA_def_cfa_register
+	.uleb128 0xb
+	.byte	0x4	# DW_CFA_advance_loc4
+	.4byte	.LCFI2-.LCFI1
+	.byte	0xe	# DW_CFA_def_cfa_offset
+	.uleb128 0x90
+	.align	4
+.LEFDE1:
+.LSFDE2:
+	.4byte	.LEFDE2-.LASFDE2	# FDE Length
+.LASFDE2:
+	.4byte	.LASFDE2-.Lframe1	# FDE CIE offset
+	.4byte	.LFB2-.	# FDE initial location
+	.4byte	.LFE2-.LFB2	# FDE address range
+	.uleb128 0x0	# Augmentation size
+	.byte	0x4	# DW_CFA_advance_loc4
+	.4byte	.LCFI10-.LFB2
+	.byte	0x8f	# DW_CFA_offset, column 0xf
+	.uleb128 0x9
+	.byte	0x8e	# DW_CFA_offset, column 0xe
+	.uleb128 0xa
+	.byte	0x8d	# DW_CFA_offset, column 0xd
+	.uleb128 0xb
+	.byte	0x8c	# DW_CFA_offset, column 0xc
+	.uleb128 0xc
+	.byte	0x4	# DW_CFA_advance_loc4
+	.4byte	.LCFI11-.LCFI10
+	.byte	0xe	# DW_CFA_def_cfa_offset
+	.uleb128 0xc0
+	.align	4
+.LEFDE2:
+
+#else
+ 
+.text
+ 
+	# r2:	cif->bytes
+	# r3:	&ecif
+	# r4:	ffi_prep_args
+	# r5:	ret_type
+	# r6:	ecif.rvalue
+	# ov:	fn 
+ 
+	# This assumes we are using gas.
+	.globl	ffi_call_SYSV
+	.type	ffi_call_SYSV,%function
+ffi_call_SYSV:
+.LFB1:
+	stmg	%r6,%r15,48(%r15)		# Save registers
+.LCFI0:
+	larl	%r13,.Lbase			# Set up base register
+	lgr	%r11,%r15			# Set up frame pointer
+.LCFI1:
+	sgr	%r15,%r2
+	aghi	%r15,-160-80			# Allocate stack
+	lgr	%r8,%r6				# Save ecif.rvalue
+	llgc	%r9,.Ltable-.Lbase(%r13,%r5)	# Load epilog address
+	lg	%r7,160(%r11)			# Load function address
+	stg	%r11,0(%r15)			# Set up back chain
+	aghi	%r11,-80			# Register save area
+.LCFI2:
+
+	la	%r2,160(%r15)			# Save area
+						# r3 already holds &ecif
+	basr	%r14,%r4			# Call ffi_prep_args
+
+	lmg	%r2,%r6,0(%r11)			# Load arguments
+	ld	%f0,48(%r11)
+	ld	%f2,56(%r11)
+	ld	%f4,64(%r11)
+	ld	%f6,72(%r11)
+	la	%r14,0(%r13,%r9)		# Set return address
+	br	%r7				# ... and call function
+
+.Lbase:
+.LretNone:					# Return void
+	lg	%r4,80+112(%r11)
+	lmg	%r6,%r15,80+48(%r11)
+	br	%r4
+
+.LretFloat:
+	lg	%r4,80+112(%r11)
+	ste	%f0,0(%r8)			# Return float
+	lmg	%r6,%r15,80+48(%r11)
+	br	%r4
+ 
+.LretDouble:
+	lg	%r4,80+112(%r11)
+	std	%f0,0(%r8)			# Return double
+	lmg	%r6,%r15,80+48(%r11)
+	br	%r4
+
+.LretInt32:
+	lg	%r4,80+112(%r11)
+	st	%r2,0(%r8)			# Return int
+	lmg	%r6,%r15,80+48(%r11)
+	br	%r4
+ 
+.LretInt64:
+	lg	%r4,80+112(%r11)
+	stg	%r2,0(%r8)			# Return long
+	lmg	%r6,%r15,80+48(%r11)
+	br	%r4
+ 
+.Ltable:
+	.byte	.LretNone-.Lbase		# FFI390_RET_VOID
+	.byte	.LretNone-.Lbase		# FFI390_RET_STRUCT
+	.byte	.LretFloat-.Lbase		# FFI390_RET_FLOAT
+	.byte	.LretDouble-.Lbase		# FFI390_RET_DOUBLE
+	.byte	.LretInt32-.Lbase		# FFI390_RET_INT32
+	.byte	.LretInt64-.Lbase		# FFI390_RET_INT64
+
+.LFE1: 
+.ffi_call_SYSV_end:
+	.size	 ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+
+
+	.globl	ffi_closure_SYSV
+	.type	ffi_closure_SYSV,%function
+ffi_closure_SYSV:
+.LFB2:
+	stmg	%r14,%r15,112(%r15)		# Save registers
+.LCFI10:
+	stmg	%r2,%r6,16(%r15)		# Save arguments
+	std	%f0,128(%r15)
+	std	%f2,136(%r15)
+	std	%f4,144(%r15)
+	std	%f6,152(%r15)
+	lgr	%r1,%r15			# Set up stack frame
+	aghi	%r15,-160
+.LCFI11:
+	lgr	%r2,%r0				# Closure
+	la	%r3,16(%r1)			# GPRs
+	la	%r4,128(%r1)			# FPRs
+	la	%r5,160(%r1)			# Overflow
+	stg	%r1,0(%r15)			# Set up back chain
+
+	brasl	%r14,ffi_closure_helper_SYSV	# Call helper
+
+	lg	%r14,160+112(%r15)
+	ld	%f0,160+128(%r15)		# Load return registers
+	lg	%r2,160+16(%r15)
+	la	%r15,160(%r15)
+	br	%r14
+.LFE2: 
+
+.ffi_closure_SYSV_end:
+	.size	 ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
+
+
+
+	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+	.4byte	.LECIE1-.LSCIE1	# Length of Common Information Entry
+.LSCIE1:
+	.4byte	0x0	# CIE Identifier Tag
+	.byte	0x1	# CIE Version
+	.ascii "zR\0"	# CIE Augmentation
+	.uleb128 0x1	# CIE Code Alignment Factor
+	.sleb128 -8	# CIE Data Alignment Factor
+	.byte	0xe	# CIE RA Column
+	.uleb128 0x1	# Augmentation size
+	.byte	0x1b	# FDE Encoding (pcrel sdata4)
+	.byte	0xc	# DW_CFA_def_cfa
+	.uleb128 0xf
+	.uleb128 0xa0
+	.align	8
+.LECIE1:
+.LSFDE1:
+	.4byte	.LEFDE1-.LASFDE1	# FDE Length
+.LASFDE1:
+	.4byte	.LASFDE1-.Lframe1	# FDE CIE offset
+	.4byte	.LFB1-.	# FDE initial location
+	.4byte	.LFE1-.LFB1	# FDE address range
+	.uleb128 0x0	# Augmentation size
+	.byte	0x4	# DW_CFA_advance_loc4
+	.4byte	.LCFI0-.LFB1
+	.byte	0x8f	# DW_CFA_offset, column 0xf
+	.uleb128 0x5
+	.byte	0x8e	# DW_CFA_offset, column 0xe
+	.uleb128 0x6
+	.byte	0x8d	# DW_CFA_offset, column 0xd
+	.uleb128 0x7
+	.byte	0x8c	# DW_CFA_offset, column 0xc
+	.uleb128 0x8
+	.byte	0x8b	# DW_CFA_offset, column 0xb
+	.uleb128 0x9
+	.byte	0x8a	# DW_CFA_offset, column 0xa
+	.uleb128 0xa
+	.byte	0x89	# DW_CFA_offset, column 0x9
+	.uleb128 0xb
+	.byte	0x88	# DW_CFA_offset, column 0x8
+	.uleb128 0xc
+	.byte	0x87	# DW_CFA_offset, column 0x7
+	.uleb128 0xd
+	.byte	0x86	# DW_CFA_offset, column 0x6
+	.uleb128 0xe
+	.byte	0x4	# DW_CFA_advance_loc4
+	.4byte	.LCFI1-.LCFI0
+	.byte	0xd	# DW_CFA_def_cfa_register
+	.uleb128 0xb
+	.byte	0x4	# DW_CFA_advance_loc4
+	.4byte	.LCFI2-.LCFI1
+	.byte	0xe	# DW_CFA_def_cfa_offset
+	.uleb128 0xf0
+	.align	8
+.LEFDE1:
+.LSFDE2:
+	.4byte	.LEFDE2-.LASFDE2	# FDE Length
+.LASFDE2:
+	.4byte	.LASFDE2-.Lframe1	# FDE CIE offset
+	.4byte	.LFB2-.	# FDE initial location
+	.4byte	.LFE2-.LFB2	# FDE address range
+	.uleb128 0x0	# Augmentation size
+	.byte	0x4	# DW_CFA_advance_loc4
+	.4byte	.LCFI10-.LFB2
+	.byte	0x8f	# DW_CFA_offset, column 0xf
+	.uleb128 0x5
+	.byte	0x8e	# DW_CFA_offset, column 0xe
+	.uleb128 0x6
+	.byte	0x4	# DW_CFA_advance_loc4
+	.4byte	.LCFI11-.LCFI10
+	.byte	0xe	# DW_CFA_def_cfa_offset
+	.uleb128 0x140
+	.align	8
+.LEFDE2:
+
+#endif
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/sh/ffi.c b/third_party/gofrontend/libffi/src/sh/ffi.c
new file mode 100644
index 0000000..3515b91
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sh/ffi.c
@@ -0,0 +1,717 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2002-2008, 2012 Kaz Kojima
+           Copyright (c) 2008 Red Hat, Inc.
+   
+   SuperH Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+#define NGREGARG 4
+#if defined(__SH4__)
+#define NFREGARG 8
+#endif
+
+#if defined(__HITACHI__)
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
+#else
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
+#endif
+
+/* If the structure has essentialy an unique element, return its type.  */
+static int
+simple_type (ffi_type *arg)
+{
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+  else if (arg->elements[1])
+    return FFI_TYPE_STRUCT;
+
+  return simple_type (arg->elements[0]);
+}
+
+static int
+return_type (ffi_type *arg)
+{
+  unsigned short type;
+
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+
+  type = simple_type (arg->elements[0]);
+  if (! arg->elements[1])
+    {
+      switch (type)
+	{
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	  return FFI_TYPE_INT;
+
+	default:
+	  return type;
+	}
+    }
+
+  /* gcc uses r0/r1 pair for some kind of structures.  */
+  if (arg->size <= 2 * sizeof (int))
+    {
+      int i = 0;
+      ffi_type *e;
+
+      while ((e = arg->elements[i++]))
+	{
+	  type = simple_type (e);
+	  switch (type)
+	    {
+	    case FFI_TYPE_SINT32:
+	    case FFI_TYPE_UINT32:
+	    case FFI_TYPE_INT:
+	    case FFI_TYPE_FLOAT:
+	      return FFI_TYPE_UINT64;
+
+	    default:
+	      break;
+	    }
+	}
+    }
+
+  return FFI_TYPE_STRUCT;
+}
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register int tmp;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+  int greg, ireg;
+#if defined(__SH4__)
+  int freg = 0;
+#endif
+
+  tmp = 0;
+  argp = stack;
+
+  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += 4;
+      ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
+    }
+  else
+    ireg = 0;
+
+  /* Set arguments for registers.  */
+  greg = ireg;
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+	{
+	  if (greg++ >= NGREGARG)
+	    continue;
+
+	  z = sizeof(int);
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+	      break;
+  
+	    case FFI_TYPE_UINT8:
+	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+	      break;
+  
+	    case FFI_TYPE_SINT16:
+	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+	      break;
+  
+	    case FFI_TYPE_UINT16:
+	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+	      break;
+  
+	    case FFI_TYPE_STRUCT:
+	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+	      break;
+
+	    default:
+	      FFI_ASSERT(0);
+	    }
+	  argp += z;
+	}
+      else if (z == sizeof(int))
+	{
+#if defined(__SH4__)
+	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
+	    {
+	      if (freg++ >= NFREGARG)
+		continue;
+	    }
+	  else
+#endif
+	    {
+	      if (greg++ >= NGREGARG)
+		continue;
+	    }
+	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+	  argp += z;
+	}
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+	{
+	  if (freg + 1 >= NFREGARG)
+	    continue;
+	  freg = (freg + 1) & ~1;
+	  freg += 2;
+	  memcpy (argp, *p_argv, z);
+	  argp += z;
+	}
+#endif
+      else
+	{
+	  int n = (z + sizeof (int) - 1) / sizeof (int);
+#if defined(__SH4__)
+	  if (greg + n - 1 >= NGREGARG)
+	    continue;
+#else
+	  if (greg >= NGREGARG)
+	    continue;
+#endif
+	  greg += n;
+	  memcpy (argp, *p_argv, z);
+	  argp += n * sizeof (int);
+	}
+    }
+
+  /* Set arguments on stack.  */
+  greg = ireg;
+#if defined(__SH4__)
+  freg = 0;
+#endif
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+	{
+	  if (greg++ < NGREGARG)
+	    continue;
+
+	  z = sizeof(int);
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+	      break;
+  
+	    case FFI_TYPE_UINT8:
+	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+	      break;
+  
+	    case FFI_TYPE_SINT16:
+	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+	      break;
+  
+	    case FFI_TYPE_UINT16:
+	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+	      break;
+  
+	    case FFI_TYPE_STRUCT:
+	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+	      break;
+
+	    default:
+	      FFI_ASSERT(0);
+	    }
+	  argp += z;
+	}
+      else if (z == sizeof(int))
+	{
+#if defined(__SH4__)
+	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
+	    {
+	      if (freg++ < NFREGARG)
+		continue;
+	    }
+	  else
+#endif
+	    {
+	      if (greg++ < NGREGARG)
+		continue;
+	    }
+	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+	  argp += z;
+	}
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+	{
+	  if (freg + 1 < NFREGARG)
+	    {
+	      freg = (freg + 1) & ~1;
+	      freg += 2;
+	      continue;
+	    }
+	  memcpy (argp, *p_argv, z);
+	  argp += z;
+	}
+#endif
+      else
+	{
+	  int n = (z + sizeof (int) - 1) / sizeof (int);
+	  if (greg + n - 1 < NGREGARG)
+	    {
+	      greg += n;
+	      continue;
+	    }
+#if (! defined(__SH4__))
+	  else if (greg < NGREGARG)
+	    {
+	      greg = NGREGARG;
+	      continue;
+	    }
+#endif
+	  memcpy (argp, *p_argv, z);
+	  argp += n * sizeof (int);
+	}
+    }
+
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int i, j;
+  int size, type;
+  int n, m;
+  int greg;
+#if defined(__SH4__)
+  int freg = 0;
+#endif
+
+  cif->flags = 0;
+
+  greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
+	  STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
+
+#if defined(__SH4__)
+  for (i = j = 0; i < cif->nargs && j < 12; i++)
+    {
+      type = (cif->arg_types)[i]->type;
+      switch (type)
+	{
+	case FFI_TYPE_FLOAT:
+	  if (freg >= NFREGARG)
+	    continue;
+	  freg++;
+	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
+	  j++;
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  if ((freg + 1) >= NFREGARG)
+	    continue;
+	  freg = (freg + 1) & ~1;
+	  freg += 2;
+	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
+	  j++;
+	  break;
+	      
+	default:
+	  size = (cif->arg_types)[i]->size;
+	  n = (size + sizeof (int) - 1) / sizeof (int);
+	  if (greg + n - 1 >= NGREGARG)
+		continue;
+	  greg += n;
+	  for (m = 0; m < n; m++)
+	    cif->flags += FFI_TYPE_INT << (2 * j++);
+	  break;
+	}
+    }
+#else
+  for (i = j = 0; i < cif->nargs && j < 4; i++)
+    {
+      size = (cif->arg_types)[i]->size;
+      n = (size + sizeof (int) - 1) / sizeof (int);
+      if (greg >= NGREGARG)
+	continue;
+      else if (greg + n - 1 >= NGREGARG)
+	n = NGREGARG - greg;
+      greg += n;
+      for (m = 0; m < n; m++)
+        cif->flags += FFI_TYPE_INT << (2 * j++);
+    }
+#endif
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_STRUCT:
+      cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
+      break;
+
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags += (unsigned) cif->rtype->type << 24;
+      break;
+
+    default:
+      cif->flags += FFI_TYPE_INT << 24;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+			  unsigned, unsigned, unsigned *, void (*fn)(void));
+
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+  UINT64 trvalue;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return	*/
+  /* value address then we need to make one		        */
+
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    ecif.rvalue = &trvalue;
+  else if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
+		    fn);
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+
+  if (rvalue
+      && cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    memcpy (rvalue, &trvalue, cif->rtype->size);
+}
+
+extern void ffi_closure_SYSV (void);
+#if defined(__SH4__)
+extern void __ic_invalidate (void *line);
+#endif
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  unsigned int *tramp;
+  unsigned int insn;
+
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  tramp = (unsigned int *) &closure->tramp[0];
+  /* Set T bit if the function returns a struct pointed with R2.  */
+  insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
+	  ? 0x0018 /* sett */
+	  : 0x0008 /* clrt */);
+
+#ifdef __LITTLE_ENDIAN__
+  tramp[0] = 0xd301d102;
+  tramp[1] = 0x0000412b | (insn << 16);
+#else
+  tramp[0] = 0xd102d301;
+  tramp[1] = 0x412b0000 | insn;
+#endif
+  *(void **) &tramp[2] = (void *)codeloc;          /* ctx */
+  *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+#if defined(__SH4__)
+  /* Flush the icache.  */
+  __ic_invalidate(codeloc);
+#endif
+
+  return FFI_OK;
+}
+
+/* Basically the trampoline invokes ffi_closure_SYSV, and on 
+ * entry, r3 holds the address of the closure.
+ * After storing the registers that could possibly contain
+ * parameters to be passed into the stack frame and setting
+ * up space for a return value, ffi_closure_SYSV invokes the 
+ * following helper function to do most of the work.
+ */
+
+#ifdef __LITTLE_ENDIAN__
+#define OFS_INT8	0
+#define OFS_INT16	0
+#else
+#define OFS_INT8	3
+#define OFS_INT16	2
+#endif
+
+int
+ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, 
+			 unsigned long *pgr, unsigned long *pfr, 
+			 unsigned long *pst)
+{
+  void **avalue;
+  ffi_type **p_arg;
+  int i, avn;
+  int ireg, greg = 0;
+#if defined(__SH4__)
+  int freg = 0;
+#endif
+  ffi_cif *cif; 
+
+  cif = closure->cif;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
+    {
+      rvalue = (void *) *pgr++;
+      ireg = 1;
+    }
+  else
+    ireg = 0;
+
+  cif = closure->cif;
+  greg = ireg;
+  avn = cif->nargs;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+	{
+	  if (greg++ >= NGREGARG)
+	    continue;
+
+	  z = sizeof(int);
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	    case FFI_TYPE_UINT8:
+	      avalue[i] = (((char *)pgr) + OFS_INT8);
+	      break;
+  
+	    case FFI_TYPE_SINT16:
+	    case FFI_TYPE_UINT16:
+	      avalue[i] = (((char *)pgr) + OFS_INT16);
+	      break;
+  
+	    case FFI_TYPE_STRUCT:
+	      avalue[i] = pgr;
+	      break;
+
+	    default:
+	      FFI_ASSERT(0);
+	    }
+	  pgr++;
+	}
+      else if (z == sizeof(int))
+	{
+#if defined(__SH4__)
+	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
+	    {
+	      if (freg++ >= NFREGARG)
+		continue;
+	      avalue[i] = pfr;
+	      pfr++;
+	    }
+	  else
+#endif
+	    {
+	      if (greg++ >= NGREGARG)
+		continue;
+	      avalue[i] = pgr;
+	      pgr++;
+	    }
+	}
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+	{
+	  if (freg + 1 >= NFREGARG)
+	    continue;
+	  if (freg & 1)
+	    pfr++;
+	  freg = (freg + 1) & ~1;
+	  freg += 2;
+	  avalue[i] = pfr;
+	  pfr += 2;
+	}
+#endif
+      else
+	{
+	  int n = (z + sizeof (int) - 1) / sizeof (int);
+#if defined(__SH4__)
+	  if (greg + n - 1 >= NGREGARG)
+	    continue;
+#else
+	  if (greg >= NGREGARG)
+	    continue;
+#endif
+	  greg += n;
+	  avalue[i] = pgr;
+	  pgr += n;
+	}
+    }
+
+  greg = ireg;
+#if defined(__SH4__)
+  freg = 0;
+#endif
+
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+	{
+	  if (greg++ < NGREGARG)
+	    continue;
+
+	  z = sizeof(int);
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	    case FFI_TYPE_UINT8:
+	      avalue[i] = (((char *)pst) + OFS_INT8);
+	      break;
+  
+	    case FFI_TYPE_SINT16:
+	    case FFI_TYPE_UINT16:
+	      avalue[i] = (((char *)pst) + OFS_INT16);
+	      break;
+  
+	    case FFI_TYPE_STRUCT:
+	      avalue[i] = pst;
+	      break;
+
+	    default:
+	      FFI_ASSERT(0);
+	    }
+	  pst++;
+	}
+      else if (z == sizeof(int))
+	{
+#if defined(__SH4__)
+	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
+	    {
+	      if (freg++ < NFREGARG)
+		continue;
+	    }
+	  else
+#endif
+	    {
+	      if (greg++ < NGREGARG)
+		continue;
+	    }
+	  avalue[i] = pst;
+	  pst++;
+	}
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+	{
+	  if (freg + 1 < NFREGARG)
+	    {
+	      freg = (freg + 1) & ~1;
+	      freg += 2;
+	      continue;
+	    }
+	  avalue[i] = pst;
+	  pst += 2;
+	}
+#endif
+      else
+	{
+	  int n = (z + sizeof (int) - 1) / sizeof (int);
+	  if (greg + n - 1 < NGREGARG)
+	    {
+	      greg += n;
+	      continue;
+	    }
+#if (! defined(__SH4__))
+	  else if (greg < NGREGARG)
+	    {
+	      greg += n;
+	      pst += greg - NGREGARG;
+	      continue;
+	    }
+#endif
+	  avalue[i] = pst;
+	  pst += n;
+	}
+    }
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
+  return return_type (cif->rtype);
+}
diff --git a/third_party/gofrontend/libffi/src/sh/ffitarget.h b/third_party/gofrontend/libffi/src/sh/ffitarget.h
new file mode 100644
index 0000000..a36bf42
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sh/ffitarget.h
@@ -0,0 +1,54 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012 Anthony Green
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for SuperH.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 16
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/third_party/gofrontend/libffi/src/sh/sysv.S b/third_party/gofrontend/libffi/src/sh/sysv.S
new file mode 100644
index 0000000..5be7516
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sh/sysv.S
@@ -0,0 +1,850 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2002, 2003, 2004, 2006, 2008 Kaz Kojima
+   
+   SuperH Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+/* XXX these lose for some platforms, I'm sure. */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif
+
+#if defined(__HITACHI__)
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
+#else
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
+#endif
+
+.text
+
+	# r4:	ffi_prep_args
+	# r5:	&ecif
+	# r6:	bytes
+	# r7:	flags
+	# sp+0: rvalue
+	# sp+4: fn
+
+	# This assumes we are using gas.
+ENTRY(ffi_call_SYSV)
+	# Save registers
+.LFB1:
+	mov.l	r8,@-r15
+.LCFI0:
+	mov.l	r9,@-r15
+.LCFI1:
+	mov.l	r10,@-r15
+.LCFI2:
+	mov.l	r12,@-r15
+.LCFI3:
+	mov.l	r14,@-r15
+.LCFI4:
+	sts.l	pr,@-r15
+.LCFI5:
+	mov	r15,r14
+.LCFI6:
+#if defined(__SH4__)
+	mov	r6,r8
+	mov	r7,r9
+
+	sub	r6,r15
+	add	#-16,r15
+	mov	#~7,r0
+	and	r0,r15
+
+	mov	r4,r0
+	jsr	@r0
+	 mov	r15,r4
+
+	mov	r9,r1
+	shlr8	r9
+	shlr8	r9
+	shlr8	r9
+
+	mov	#FFI_TYPE_STRUCT,r2
+	cmp/eq	r2,r9
+	bf	1f
+#if STRUCT_VALUE_ADDRESS_WITH_ARG
+ 	mov.l	@r15+,r4
+	bra	2f
+	 mov	#5,r2
+#else
+ 	mov.l	@r15+,r10
+#endif
+1:
+	mov	#4,r2
+2:
+	mov	#4,r3
+
+L_pass:
+	cmp/pl	r8
+	bf	L_call_it
+
+	mov	r1,r0
+	and	#3,r0
+
+L_pass_d:
+	cmp/eq	#FFI_TYPE_DOUBLE,r0
+	bf	L_pass_f
+
+	mov	r3,r0
+	and	#1,r0
+	tst	r0,r0
+	bt	1f
+	add	#1,r3
+1:
+	mov	#12,r0
+	cmp/hs	r0,r3
+	bt/s	3f
+	 shlr2	r1
+	bsr	L_pop_d
+	 nop
+3:
+	add	#2,r3
+	bra	L_pass
+	 add	#-8,r8
+
+L_pop_d:
+	mov	r3,r0
+	add	r0,r0
+	add	r3,r0
+	add	#-12,r0
+	braf	r0
+	 nop
+#ifdef __LITTLE_ENDIAN__
+	fmov.s	@r15+,fr5
+	rts
+	 fmov.s	@r15+,fr4
+	fmov.s	@r15+,fr7
+	rts
+	 fmov.s	@r15+,fr6
+	fmov.s	@r15+,fr9
+	rts
+	 fmov.s	@r15+,fr8
+	fmov.s	@r15+,fr11
+	rts
+	 fmov.s	@r15+,fr10
+#else
+	fmov.s	@r15+,fr4
+	rts
+	 fmov.s	@r15+,fr5
+	fmov.s	@r15+,fr6
+	rts
+	 fmov.s	@r15+,fr7
+	fmov.s	@r15+,fr8
+	rts
+	 fmov.s	@r15+,fr9
+	fmov.s	@r15+,fr10
+	rts
+	 fmov.s	@r15+,fr11
+#endif
+
+L_pass_f:
+	cmp/eq	#FFI_TYPE_FLOAT,r0
+	bf	L_pass_i
+
+	mov	#12,r0
+	cmp/hs	r0,r3
+	bt/s	2f
+	 shlr2	r1
+	bsr	L_pop_f
+	 nop
+2:
+	add	#1,r3
+	bra	L_pass
+	 add	#-4,r8
+
+L_pop_f:
+	mov	r3,r0
+	shll2	r0
+	add	#-16,r0
+	braf	r0
+	 nop
+#ifdef __LITTLE_ENDIAN__
+	rts
+	 fmov.s	@r15+,fr5
+	rts
+	 fmov.s	@r15+,fr4
+	rts
+	 fmov.s	@r15+,fr7
+	rts
+	 fmov.s	@r15+,fr6
+	rts
+	 fmov.s	@r15+,fr9
+	rts
+	 fmov.s	@r15+,fr8
+	rts
+	 fmov.s	@r15+,fr11
+	rts
+	 fmov.s	@r15+,fr10
+#else
+	rts
+	 fmov.s	@r15+,fr4
+	rts
+	 fmov.s	@r15+,fr5
+	rts
+	 fmov.s	@r15+,fr6
+	rts
+	 fmov.s	@r15+,fr7
+	rts
+	 fmov.s	@r15+,fr8
+	rts
+	 fmov.s	@r15+,fr9
+	rts
+	 fmov.s	@r15+,fr10
+	rts
+	 fmov.s	@r15+,fr11
+#endif
+
+L_pass_i:
+	cmp/eq	#FFI_TYPE_INT,r0
+	bf	L_call_it
+
+	mov	#8,r0
+	cmp/hs	r0,r2
+	bt/s	2f
+	 shlr2	r1
+	bsr	L_pop_i
+	 nop
+2:
+	add	#1,r2
+	bra	L_pass
+	 add	#-4,r8
+
+L_pop_i:
+	mov	r2,r0
+	shll2	r0
+	add	#-16,r0
+	braf	r0
+	 nop
+	rts
+	 mov.l	@r15+,r4
+	rts
+	 mov.l	@r15+,r5
+	rts
+	 mov.l	@r15+,r6
+	rts
+	 mov.l	@r15+,r7
+
+L_call_it:
+	# call function
+#if (! STRUCT_VALUE_ADDRESS_WITH_ARG)
+	mov	r10, r2
+#endif
+	mov.l  @(28,r14),r1
+	jsr    @r1
+	 nop
+
+L_ret_d:
+	mov	#FFI_TYPE_DOUBLE,r2
+	cmp/eq	r2,r9
+	bf	L_ret_ll
+
+	mov.l	@(24,r14),r1
+#ifdef __LITTLE_ENDIAN__
+	fmov.s	fr1,@r1
+	add	#4,r1
+	bra	L_epilogue
+	 fmov.s	fr0,@r1
+#else
+	fmov.s	fr0,@r1
+	add	#4,r1
+	bra	L_epilogue
+	 fmov.s	fr1,@r1
+#endif
+
+L_ret_ll:
+	mov	#FFI_TYPE_SINT64,r2
+	cmp/eq	r2,r9
+	bt/s	1f
+	 mov	#FFI_TYPE_UINT64,r2
+	cmp/eq	r2,r9
+	bf	L_ret_f
+
+1:
+	mov.l	@(24,r14),r2
+	mov.l	r0,@r2
+	bra	L_epilogue
+	 mov.l	r1,@(4,r2)
+
+L_ret_f:
+	mov	#FFI_TYPE_FLOAT,r2
+	cmp/eq	r2,r9
+	bf	L_ret_i
+
+	mov.l	@(24,r14),r1
+	bra	L_epilogue
+	 fmov.s	fr0,@r1
+
+L_ret_i:
+	mov	#FFI_TYPE_INT,r2
+	cmp/eq	r2,r9
+	bf	L_epilogue
+
+	mov.l	@(24,r14),r1
+	bra	L_epilogue
+	 mov.l	r0,@r1
+
+L_epilogue:
+	# Remove the space we pushed for the args
+	mov   r14,r15
+
+	lds.l  @r15+,pr
+	mov.l  @r15+,r14
+	mov.l  @r15+,r12
+	mov.l  @r15+,r10
+	mov.l  @r15+,r9
+	rts
+	 mov.l  @r15+,r8
+#else
+	mov	r6,r8
+	mov	r7,r9
+
+	sub	r6,r15
+	add	#-16,r15
+	mov	#~7,r0
+	and	r0,r15
+
+	mov	r4,r0
+	jsr	@r0
+	 mov	r15,r4
+
+	mov	r9,r3
+	shlr8	r9
+	shlr8	r9
+	shlr8	r9
+
+	mov	#FFI_TYPE_STRUCT,r2
+	cmp/eq	r2,r9
+	bf	1f
+#if STRUCT_VALUE_ADDRESS_WITH_ARG
+	mov.l	@r15+,r4
+	bra	2f
+	 mov	#5,r2
+#else
+	mov.l	@r15+,r10
+#endif
+1:
+	mov	#4,r2
+2:
+
+L_pass:
+	cmp/pl	r8
+	bf	L_call_it
+
+	mov	r3,r0
+	and	#3,r0
+
+L_pass_d:
+	cmp/eq	#FFI_TYPE_DOUBLE,r0
+	bf	L_pass_i
+
+	mov	r15,r0
+	and	#7,r0
+	tst	r0,r0
+	bt	1f
+	add	#4,r15
+1:
+	mov	#8,r0
+	cmp/hs	r0,r2
+	bt/s	2f
+	 shlr2	r3
+	bsr	L_pop_d
+	 nop
+2:
+	add	#2,r2
+	bra	L_pass
+	 add	#-8,r8
+
+L_pop_d:
+	mov	r2,r0
+	add	r0,r0
+	add	r2,r0
+	add	#-12,r0
+	add	r0,r0
+	braf	r0
+	 nop
+	mov.l	@r15+,r4
+	rts
+	 mov.l	@r15+,r5
+	mov.l	@r15+,r5
+	rts
+	 mov.l	@r15+,r6
+	mov.l	@r15+,r6
+	rts
+	 mov.l	@r15+,r7
+	rts
+	 mov.l	@r15+,r7
+
+L_pass_i:
+	cmp/eq	#FFI_TYPE_INT,r0
+	bf	L_call_it
+
+	mov	#8,r0
+	cmp/hs	r0,r2
+	bt/s	2f
+	 shlr2	r3
+	bsr	L_pop_i
+	 nop
+2:
+	add	#1,r2
+	bra	L_pass
+	 add	#-4,r8
+
+L_pop_i:
+	mov	r2,r0
+	shll2	r0
+	add	#-16,r0
+	braf	r0
+	 nop
+	rts
+	 mov.l	@r15+,r4
+	rts
+	 mov.l	@r15+,r5
+	rts
+	 mov.l	@r15+,r6
+	rts
+	 mov.l	@r15+,r7
+
+L_call_it:
+	# call function
+#if (! STRUCT_VALUE_ADDRESS_WITH_ARG)
+	mov	r10, r2
+#endif
+	mov.l  @(28,r14),r1
+	jsr    @r1
+	 nop
+
+L_ret_d:
+	mov	#FFI_TYPE_DOUBLE,r2
+	cmp/eq	r2,r9
+	bf	L_ret_ll
+
+	mov.l	@(24,r14),r2
+	mov.l	r0,@r2
+	bra	L_epilogue
+	 mov.l	r1,@(4,r2)
+
+L_ret_ll:
+	mov	#FFI_TYPE_SINT64,r2
+	cmp/eq	r2,r9
+	bt/s	1f
+	 mov	#FFI_TYPE_UINT64,r2
+	cmp/eq	r2,r9
+	bf	L_ret_i
+
+1:
+	mov.l	@(24,r14),r2
+	mov.l	r0,@r2
+	bra	L_epilogue
+	 mov.l	r1,@(4,r2)
+
+L_ret_i:
+	mov	#FFI_TYPE_FLOAT,r2
+	cmp/eq	r2,r9
+	bt	1f
+	mov	#FFI_TYPE_INT,r2
+	cmp/eq	r2,r9
+	bf	L_epilogue
+1:
+	mov.l	@(24,r14),r1
+	bra	L_epilogue
+	 mov.l	r0,@r1
+
+L_epilogue:
+	# Remove the space we pushed for the args
+	mov   r14,r15
+
+	lds.l  @r15+,pr
+	mov.l  @r15+,r14
+	mov.l  @r15+,r12
+	mov.l  @r15+,r10
+	mov.l  @r15+,r9
+	rts
+	 mov.l  @r15+,r8
+#endif
+.LFE1:
+.ffi_call_SYSV_end:
+        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
+.globl	ffi_closure_helper_SYSV
+
+ENTRY(ffi_closure_SYSV)
+.LFB2:
+	mov.l	r7,@-r15
+.LCFI7:
+	mov.l	r6,@-r15
+.LCFI8:
+	mov.l	r5,@-r15
+.LCFI9:
+	mov.l	r4,@-r15
+.LCFIA:
+	mov.l	r14,@-r15
+.LCFIB:
+	sts.l	pr,@-r15
+
+	/* Stack layout:	
+	   xx bytes (on stack parameters)
+	   16 bytes (register parameters)
+	    4 bytes (saved frame pointer)
+	    4 bytes (saved return address)
+	   32 bytes (floating register parameters, SH-4 only)
+	    8 bytes (result)
+	    4 bytes (pad)
+	    4 bytes (5th arg)
+	   <- new stack pointer
+	*/
+.LCFIC:
+#if defined(__SH4__)
+	add	#-48,r15
+#else
+	add	#-16,r15
+#endif
+.LCFID:
+	mov	r15,r14
+.LCFIE:
+
+#if defined(__SH4__)
+	mov	r14,r1
+	add	#48,r1
+#ifdef __LITTLE_ENDIAN__
+	fmov.s	fr10,@-r1
+	fmov.s	fr11,@-r1
+	fmov.s	fr8,@-r1
+	fmov.s	fr9,@-r1
+	fmov.s	fr6,@-r1
+	fmov.s	fr7,@-r1
+	fmov.s	fr4,@-r1
+	fmov.s	fr5,@-r1
+#else
+	fmov.s	fr11,@-r1
+	fmov.s	fr10,@-r1
+	fmov.s	fr9,@-r1
+	fmov.s	fr8,@-r1
+	fmov.s	fr7,@-r1
+	fmov.s	fr6,@-r1
+	fmov.s	fr5,@-r1
+	fmov.s	fr4,@-r1
+#endif
+	mov	r1,r7
+	mov	r14,r6
+	add	#56,r6
+#else
+	mov	r14,r6
+	add	#24,r6
+#endif
+
+	bt/s	10f
+	 mov	r2, r5
+	mov	r14,r1
+	add	#8,r1
+	mov	r1,r5
+10:
+
+	mov	r14,r1
+#if defined(__SH4__)
+	add	#72,r1
+#else
+	add	#40,r1
+#endif
+	mov.l	r1,@r14
+
+#ifdef PIC
+	mov.l	L_got,r1
+	mova	L_got,r0
+	add	r0,r1
+	mov.l	L_helper,r0
+	add	r1,r0
+#else
+	mov.l	L_helper,r0
+#endif
+	jsr	@r0
+	 mov	r3,r4
+
+	shll	r0
+	mov	r0,r1
+	mova	L_table,r0
+	add	r1,r0
+	mov.w	@r0,r0
+	mov	r14,r2
+	braf	r0
+	 add	#8,r2
+0:
+	.align 2
+#ifdef PIC
+L_got:
+	.long	_GLOBAL_OFFSET_TABLE_
+L_helper:
+	.long	ffi_closure_helper_SYSV@GOTOFF
+#else
+L_helper:
+	.long	ffi_closure_helper_SYSV
+#endif
+L_table:
+	.short L_case_v - 0b	/* FFI_TYPE_VOID */
+	.short L_case_i - 0b	/* FFI_TYPE_INT */
+#if defined(__SH4__)
+	.short L_case_f - 0b	/* FFI_TYPE_FLOAT */
+	.short L_case_d - 0b	/* FFI_TYPE_DOUBLE */
+	.short L_case_d - 0b	/* FFI_TYPE_LONGDOUBLE */
+#else
+	.short L_case_i - 0b	/* FFI_TYPE_FLOAT */
+	.short L_case_ll - 0b	/* FFI_TYPE_DOUBLE */
+	.short L_case_ll - 0b	/* FFI_TYPE_LONGDOUBLE */
+#endif
+	.short L_case_uq - 0b	/* FFI_TYPE_UINT8 */
+	.short L_case_q - 0b	/* FFI_TYPE_SINT8 */
+	.short L_case_uh - 0b	/* FFI_TYPE_UINT16 */
+	.short L_case_h - 0b	/* FFI_TYPE_SINT16 */
+	.short L_case_i - 0b	/* FFI_TYPE_UINT32 */
+	.short L_case_i - 0b	/* FFI_TYPE_SINT32 */
+	.short L_case_ll - 0b	/* FFI_TYPE_UINT64 */
+	.short L_case_ll - 0b	/* FFI_TYPE_SINT64 */
+	.short L_case_v - 0b	/* FFI_TYPE_STRUCT */
+	.short L_case_i - 0b	/* FFI_TYPE_POINTER */
+
+#if defined(__SH4__)
+L_case_d:
+#ifdef __LITTLE_ENDIAN__
+	fmov.s	@r2+,fr1
+	bra	L_case_v
+	 fmov.s	@r2,fr0
+#else
+	fmov.s	@r2+,fr0
+	bra	L_case_v
+	 fmov.s	@r2,fr1
+#endif
+
+L_case_f:
+	bra	L_case_v
+	 fmov.s	@r2,fr0
+#endif
+	
+L_case_ll:
+	mov.l	@r2+,r0
+	bra	L_case_v
+	 mov.l	@r2,r1
+	
+L_case_i:
+	bra	L_case_v
+	 mov.l	@r2,r0
+	
+L_case_q:
+#ifdef __LITTLE_ENDIAN__
+#else
+	add	#3,r2
+#endif
+	bra	L_case_v
+	 mov.b	@r2,r0
+
+L_case_uq:
+#ifdef __LITTLE_ENDIAN__
+#else
+	add	#3,r2
+#endif
+	mov.b	@r2,r0
+	bra	L_case_v
+	 extu.b r0,r0
+
+L_case_h:
+#ifdef __LITTLE_ENDIAN__
+#else
+	add	#2,r2
+#endif
+	bra	L_case_v
+	 mov.w	@r2,r0
+
+L_case_uh:
+#ifdef __LITTLE_ENDIAN__
+#else
+	add	#2,r2
+#endif
+	mov.w	@r2,r0
+	extu.w	r0,r0
+	/* fall through */
+
+L_case_v:
+#if defined(__SH4__)
+	add	#48,r15
+#else
+	add	#16,r15
+#endif
+	lds.l	@r15+,pr
+	mov.l	@r15+,r14
+	rts
+	 add	#16,r15
+.LFE2:
+.ffi_closure_SYSV_end:
+        .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
+
+	.section	".eh_frame","aw",@progbits
+__FRAME_BEGIN__:
+	.4byte	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
+.LSCIE1:
+	.4byte	0x0	/* CIE Identifier Tag */
+	.byte	0x1	/* CIE Version */
+#ifdef PIC
+	.ascii "zR\0"	/* CIE Augmentation */
+#else
+	.byte	0x0	/* CIE Augmentation */
+#endif
+	.byte	0x1	/* uleb128 0x1; CIE Code Alignment Factor */
+	.byte	0x7c	/* sleb128 -4; CIE Data Alignment Factor */
+	.byte	0x11	/* CIE RA Column */
+#ifdef PIC
+	.uleb128 0x1	/* Augmentation size */
+	.byte	0x10	/* FDE Encoding (pcrel) */
+#endif
+	.byte	0xc	/* DW_CFA_def_cfa */
+	.byte	0xf	/* uleb128 0xf */
+	.byte	0x0	/* uleb128 0x0 */
+	.align	2
+.LECIE1:
+.LSFDE1:
+	.4byte	.LEFDE1-.LASFDE1	/* FDE Length */
+.LASFDE1:
+	.4byte	.LASFDE1-__FRAME_BEGIN__	/* FDE CIE offset */
+#ifdef PIC
+	.4byte	.LFB1-.	/* FDE initial location */
+#else
+	.4byte	.LFB1	/* FDE initial location */
+#endif
+	.4byte	.LFE1-.LFB1	 /* FDE address range */
+#ifdef PIC
+	.uleb128 0x0	/* Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFI0-.LFB1
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x4	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFI1-.LCFI0
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x8	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFI2-.LCFI1
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0xc	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFI3-.LCFI2
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x10	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFI4-.LCFI3
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x14	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFI5-.LCFI4
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x18	/* uleb128 0x4 */
+	.byte	0x91	/* DW_CFA_offset, column 0x11 */
+	.byte	0x6	/* uleb128 0x6 */
+	.byte	0x8e	/* DW_CFA_offset, column 0xe */
+	.byte	0x5	/* uleb128 0x5 */
+	.byte	0x8c	/* DW_CFA_offset, column 0xc */
+	.byte	0x4	/* uleb128 0x4 */
+	.byte	0x8a	/* DW_CFA_offset, column 0xa */
+	.byte	0x3	/* uleb128 0x3 */
+	.byte	0x89	/* DW_CFA_offset, column 0x9 */
+	.byte	0x2	/* uleb128 0x2 */
+	.byte	0x88	/* DW_CFA_offset, column 0x8 */
+	.byte	0x1	/* uleb128 0x1 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFI6-.LCFI5
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0xe	/* uleb128 0xe */
+	.align	2
+.LEFDE1:
+
+.LSFDE3:
+	.4byte	.LEFDE3-.LASFDE3	/* FDE Length */
+.LASFDE3:
+	.4byte	.LASFDE3-__FRAME_BEGIN__	/* FDE CIE offset */
+#ifdef PIC
+	.4byte	.LFB2-.	/* FDE initial location */
+#else
+	.4byte	.LFB2	/* FDE initial location */
+#endif
+	.4byte	.LFE2-.LFB2	 /* FDE address range */
+#ifdef PIC
+	.uleb128 0x0	/* Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFI7-.LFB2
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x4	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFI8-.LCFI7
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x8	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFI9-.LCFI8
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0xc	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFIA-.LCFI9
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x10	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFIB-.LCFIA
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x14	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFIC-.LCFIB
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x18	/* uleb128 0x4 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFID-.LCFIC
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+#if defined(__SH4__)
+	.byte	24+48	/* uleb128 24+48 */
+#else
+	.byte	24+16	/* uleb128 24+16 */
+#endif
+	.byte	0x91	/* DW_CFA_offset, column 0x11 */
+	.byte	0x6	/* uleb128 0x6 */
+	.byte	0x8e	/* DW_CFA_offset, column 0xe */
+	.byte	0x5	/* uleb128 0x5 */
+	.byte	0x84	/* DW_CFA_offset, column 0x4 */
+	.byte	0x4	/* uleb128 0x4 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 */
+	.byte	0x3	/* uleb128 0x3 */
+	.byte	0x86	/* DW_CFA_offset, column 0x6 */
+	.byte	0x2	/* uleb128 0x2 */
+	.byte	0x87	/* DW_CFA_offset, column 0x7 */
+	.byte	0x1	/* uleb128 0x1 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	.LCFIE-.LCFID
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0xe	/* uleb128 0xe */
+	.align	2
+.LEFDE3:
diff --git a/third_party/gofrontend/libffi/src/sh64/ffi.c b/third_party/gofrontend/libffi/src/sh64/ffi.c
new file mode 100644
index 0000000..123b87a
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sh64/ffi.c
@@ -0,0 +1,469 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2003, 2004, 2006, 2007, 2012 Kaz Kojima
+           Copyright (c) 2008 Anthony Green
+   
+   SuperH SHmedia Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+#define NGREGARG 8
+#define NFREGARG 12
+
+static int
+return_type (ffi_type *arg)
+{
+
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+
+  /* gcc uses r2 if the result can be packed in on register.  */
+  if (arg->size <= sizeof (UINT8))
+    return FFI_TYPE_UINT8;
+  else if (arg->size <= sizeof (UINT16))
+    return FFI_TYPE_UINT16;
+  else if (arg->size <= sizeof (UINT32))
+    return FFI_TYPE_UINT32;
+  else if (arg->size <= sizeof (UINT64))
+    return FFI_TYPE_UINT64;
+
+  return FFI_TYPE_STRUCT;
+}
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += sizeof (UINT64);
+    }
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
+    {
+      size_t z;
+      int align;
+
+      z = (*p_arg)->size;
+      align = (*p_arg)->alignment;
+      if (z < sizeof (UINT32))
+	{
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	      *(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv);
+	      break;
+  
+	    case FFI_TYPE_UINT8:
+	      *(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv);
+	      break;
+  
+	    case FFI_TYPE_SINT16:
+	      *(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv);
+	      break;
+  
+	    case FFI_TYPE_UINT16:
+	      *(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv);
+	      break;
+  
+	    case FFI_TYPE_STRUCT:
+	      memcpy (argp, *p_argv, z);
+	      break;
+
+	    default:
+	      FFI_ASSERT(0);
+	    }
+	  argp += sizeof (UINT64);
+	}
+      else if (z == sizeof (UINT32) && align == sizeof (UINT32))
+	{
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_INT:
+	    case FFI_TYPE_SINT32:
+	      *(SINT64 *) argp = (SINT64) *(SINT32 *) (*p_argv);
+	      break;
+
+	    case FFI_TYPE_FLOAT:
+	    case FFI_TYPE_POINTER:
+	    case FFI_TYPE_UINT32:
+	    case FFI_TYPE_STRUCT:
+	      *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
+	      break;
+
+	    default:
+	      FFI_ASSERT(0);
+	      break;
+	    }
+	  argp += sizeof (UINT64);
+	}
+      else if (z == sizeof (UINT64)
+	       && align == sizeof (UINT64)
+	       && ((int) *p_argv & (sizeof (UINT64) - 1)) == 0)
+	{
+	  *(UINT64 *) argp = *(UINT64 *) (*p_argv);
+	  argp += sizeof (UINT64);
+	}
+      else
+	{
+	  int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
+
+	  memcpy (argp, *p_argv, z);
+	  argp += n * sizeof (UINT64);
+	}
+    }
+
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int i, j;
+  int size, type;
+  int n, m;
+  int greg;
+  int freg;
+  int fpair = -1;
+
+  greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
+  freg = 0;
+  cif->flags2 = 0;
+
+  for (i = j = 0; i < cif->nargs; i++)
+    {
+      type = (cif->arg_types)[i]->type;
+      switch (type)
+	{
+	case FFI_TYPE_FLOAT:
+	  greg++;
+	  cif->bytes += sizeof (UINT64) - sizeof (float);
+	  if (freg >= NFREGARG - 1)
+	    continue;
+	  if (fpair < 0)
+	    {
+	      fpair = freg;
+	      freg += 2;
+	    }
+	  else
+	    fpair = -1;
+	  cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG)
+	    continue;
+	  if ((freg + 1) < NFREGARG)
+	    {
+	      freg += 2;
+	      cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
+	    }
+	  else
+	    cif->flags2 += FFI_TYPE_INT << (2 * j++);
+	  break;
+	      
+	default:
+	  size = (cif->arg_types)[i]->size;
+	  if (size < sizeof (UINT64))
+	    cif->bytes += sizeof (UINT64) - size;
+	  n = (size + sizeof (UINT64) - 1) / sizeof (UINT64);
+	  if (greg >= NGREGARG)
+	    continue;
+	  else if (greg + n - 1 >= NGREGARG)
+	    greg = NGREGARG;
+	  else
+	    greg += n;
+	  for (m = 0; m < n; m++)
+	    cif->flags2 += FFI_TYPE_INT << (2 * j++);
+	  break;
+	}
+    }
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_STRUCT:
+      cif->flags = return_type (cif->rtype);
+      break;
+
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = cif->rtype->type;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), 
+			  /*@out@*/ extended_cif *, 
+			  unsigned, unsigned, long long,
+			  /*@out@*/ unsigned *, 
+			  void (*fn)(void));
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif, 
+	      void (*fn)(void), 
+	      /*@out@*/ void *rvalue, 
+	      /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+  UINT64 trvalue;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return	*/
+  /* value address then we need to make one		        */
+
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    ecif.rvalue = &trvalue;
+  else if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, cif->flags2,
+		    ecif.rvalue, fn);
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+
+  if (rvalue
+      && cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    memcpy (rvalue, &trvalue, cif->rtype->size);
+}
+
+extern void ffi_closure_SYSV (void);
+extern void __ic_invalidate (void *line);
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure *closure,
+		      ffi_cif *cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  unsigned int *tramp;
+
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  tramp = (unsigned int *) &closure->tramp[0];
+  /* Since ffi_closure is an aligned object, the ffi trampoline is
+     called as an SHcompact code.  Sigh.
+     SHcompact part:
+     mova @(1,pc),r0; add #1,r0; jmp @r0; nop;
+     SHmedia part:
+     movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0
+     movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63  */
+#ifdef __LITTLE_ENDIAN__
+  tramp[0] = 0x7001c701;
+  tramp[1] = 0x0009402b;
+#else
+  tramp[0] = 0xc7017001;
+  tramp[1] = 0x402b0009;
+#endif
+  tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
+  tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
+  tramp[4] = 0x6bf10600;
+  tramp[5] = 0xcc000010 | (((UINT32) codeloc) >> 16) << 10;
+  tramp[6] = 0xc8000010 | (((UINT32) codeloc) & 0xffff) << 10;
+  tramp[7] = 0x4401fff0;
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Flush the icache.  */
+  asm volatile ("ocbwb %0,0; synco; icbi %1,0; synci" : : "r" (tramp),
+		"r"(codeloc));
+
+  return FFI_OK;
+}
+
+/* Basically the trampoline invokes ffi_closure_SYSV, and on 
+ * entry, r3 holds the address of the closure.
+ * After storing the registers that could possibly contain
+ * parameters to be passed into the stack frame and setting
+ * up space for a return value, ffi_closure_SYSV invokes the 
+ * following helper function to do most of the work.
+ */
+
+int
+ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue, 
+			 UINT64 *pgr, UINT64 *pfr, UINT64 *pst)
+{
+  void **avalue;
+  ffi_type **p_arg;
+  int i, avn;
+  int greg, freg;
+  ffi_cif *cif;
+  int fpair = -1;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (void *));
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.  */
+  if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
+    {
+      rvalue = (UINT64 *) *pgr;
+      greg = 1;
+    }
+  else
+    greg = 0;
+
+  freg = 0;
+  cif = closure->cif;
+  avn = cif->nargs;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      size_t z;
+      void *p;
+
+      z = (*p_arg)->size;
+      if (z < sizeof (UINT32))
+	{
+	  p = pgr + greg++;
+
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	    case FFI_TYPE_UINT8:
+	    case FFI_TYPE_SINT16:
+	    case FFI_TYPE_UINT16:
+	    case FFI_TYPE_STRUCT:
+#ifdef __LITTLE_ENDIAN__
+	      avalue[i] = p;
+#else
+	      avalue[i] = ((char *) p) + sizeof (UINT32) - z;
+#endif
+	      break;
+
+	    default:
+	      FFI_ASSERT(0);
+	    }
+	}
+      else if (z == sizeof (UINT32))
+	{
+	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
+	    {
+	      if (freg < NFREGARG - 1)
+		{
+		  if (fpair >= 0)
+		    {
+		      avalue[i] = (UINT32 *) pfr + fpair;
+		      fpair = -1;
+		    }
+		  else
+		    {
+#ifdef __LITTLE_ENDIAN__
+		      fpair = freg;
+		      avalue[i] = (UINT32 *) pfr + (1 ^ freg);
+#else
+		      fpair = 1 ^ freg;
+		      avalue[i] = (UINT32 *) pfr + freg;
+#endif
+		      freg += 2;
+		    }
+		}
+	      else
+#ifdef __LITTLE_ENDIAN__
+		avalue[i] = pgr + greg;
+#else
+		avalue[i] = (UINT32 *) (pgr + greg) + 1;
+#endif
+	    }
+	  else
+#ifdef __LITTLE_ENDIAN__
+	    avalue[i] = pgr + greg;
+#else
+	    avalue[i] = (UINT32 *) (pgr + greg) + 1;
+#endif
+	  greg++;
+	}
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+	{
+	  if (freg + 1 >= NFREGARG)
+	    avalue[i] = pgr + greg;
+	  else
+	    {
+	      avalue[i] = pfr + (freg >> 1);
+	      freg += 2;
+	    }
+	  greg++;
+	}
+      else
+	{
+	  int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
+
+	  avalue[i] = pgr + greg;
+	  greg += n;
+	}
+    }
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
+  return return_type (cif->rtype);
+}
+
diff --git a/third_party/gofrontend/libffi/src/sh64/ffitarget.h b/third_party/gofrontend/libffi/src/sh64/ffitarget.h
new file mode 100644
index 0000000..08a6fe9
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sh64/ffitarget.h
@@ -0,0 +1,58 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for SuperH - SHmedia.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+
+#define FFI_EXTRA_CIF_FIELDS long long flags2
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 32
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/third_party/gofrontend/libffi/src/sh64/sysv.S b/third_party/gofrontend/libffi/src/sh64/sysv.S
new file mode 100644
index 0000000..c4587d5
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sh64/sysv.S
@@ -0,0 +1,539 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2003, 2004, 2006, 2008 Kaz Kojima
+   
+   SuperH SHmedia Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+ 
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+/* XXX these lose for some platforms, I'm sure. */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif
+
+#ifdef __LITTLE_ENDIAN__
+#define OFS_FLT	0
+#else
+#define OFS_FLT	4
+#endif
+
+	.section	.text..SHmedia32,"ax"
+
+	# r2:	ffi_prep_args
+	# r3:	&ecif
+	# r4:	bytes
+	# r5:	flags
+	# r6:	flags2
+	# r7:	rvalue
+	# r8:	fn
+
+	# This assumes we are using gas.
+	.align	5
+ENTRY(ffi_call_SYSV)
+	# Save registers
+.LFB1:
+	addi.l	r15, -48, r15
+.LCFI0:
+	st.q	r15, 40, r32
+	st.q	r15, 32, r31
+	st.q	r15, 24, r30
+	st.q	r15, 16, r29
+	st.q	r15, 8, r28
+	st.l	r15, 4, r18
+	st.l	r15, 0, r14
+.LCFI1:
+	add.l	r15, r63, r14
+.LCFI2:
+#	add	r4, r63, r28
+	add	r5, r63, r29
+	add	r6, r63, r30
+	add	r7, r63, r31
+	add	r8, r63, r32
+
+	addi	r4, (64 + 7), r4
+	andi	r4, ~7, r4
+	sub.l	r15, r4, r15
+
+	ptabs/l	r2, tr0
+	add	r15, r63, r2
+	blink	tr0, r18
+
+	addi	r15, 64, r22
+	movi	0, r0
+	movi	0, r1
+	movi	-1, r23
+
+	pt/l	1f, tr1
+	bnei/l	r29, FFI_TYPE_STRUCT, tr1
+	ld.l	r15, 0, r19
+	addi	r15, 8, r15
+	addi	r0, 1, r0
+1:
+
+.L_pass:
+	andi	r30, 3, r20
+	shlri	r30, 2, r30
+
+	pt/l	.L_call_it, tr0
+	pt/l	.L_pass_i, tr1
+	pt/l	.L_pass_f, tr2
+
+	beqi/l	r20, FFI_TYPE_VOID, tr0
+	beqi/l	r20, FFI_TYPE_INT, tr1
+	beqi/l	r20, FFI_TYPE_FLOAT, tr2
+
+.L_pass_d:
+	addi	r0, 1, r0
+	pt/l	3f, tr0
+	movi	12, r20
+	bge/l	r1, r20, tr0
+
+	pt/l	.L_pop_d, tr1
+	pt/l	2f, tr0
+	blink	tr1, r63
+2:
+	addi.l	r15, 8, r15
+3:
+	pt/l	.L_pass, tr0
+	addi	r1, 2, r1
+	blink	tr0, r63
+
+.L_pop_d:
+	pt/l	.L_pop_d_tbl, tr1
+	gettr	tr1, r20
+	shlli	r1, 2, r21
+	add	r20, r21, r20
+	ptabs/l	r20, tr1
+	blink	tr1, r63
+
+.L_pop_d_tbl:
+	fld.d	r15, 0, dr0
+	blink	tr0, r63
+	fld.d	r15, 0, dr2
+	blink	tr0, r63
+	fld.d	r15, 0, dr4
+	blink	tr0, r63
+	fld.d	r15, 0, dr6
+	blink	tr0, r63
+	fld.d	r15, 0, dr8
+	blink	tr0, r63
+	fld.d	r15, 0, dr10
+	blink	tr0, r63
+
+.L_pass_f:
+	addi	r0, 1, r0
+	pt/l	3f, tr0
+	movi	12, r20
+	bge/l	r1, r20, tr0
+
+	pt/l	.L_pop_f, tr1
+	pt/l	2f, tr0
+	blink	tr1, r63
+2:
+	addi.l	r15, 8, r15
+3:
+	pt/l	.L_pass, tr0
+	blink	tr0, r63
+
+.L_pop_f:
+	pt/l	.L_pop_f_tbl, tr1
+	pt/l	5f, tr2
+	gettr	tr1, r20
+	bge/l	r23, r63, tr2
+	add	r1, r63, r23 
+	shlli	r1, 3, r21
+	addi	r1, 2, r1
+	add	r20, r21, r20
+	ptabs/l	r20, tr1
+	blink	tr1, r63
+5:
+	addi	r23, 1, r21
+	movi	-1, r23
+	shlli	r21, 3, r21
+	add	r20, r21, r20
+	ptabs/l	r20, tr1
+	blink	tr1, r63
+
+.L_pop_f_tbl:
+	fld.s	r15, OFS_FLT, fr0
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr1
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr2
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr3
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr4
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr5
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr6
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr7
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr8
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr9
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr10
+	blink	tr0, r63
+	fld.s	r15, OFS_FLT, fr11
+	blink	tr0, r63
+
+.L_pass_i:
+	pt/l	3f, tr0
+	movi	8, r20
+	bge/l	r0, r20, tr0
+
+	pt/l	.L_pop_i, tr1
+	pt/l	2f, tr0
+	blink	tr1, r63
+2:
+	addi.l	r15, 8, r15
+3:
+	pt/l	.L_pass, tr0
+	addi	r0, 1, r0
+	blink	tr0, r63
+
+.L_pop_i:
+	pt/l	.L_pop_i_tbl, tr1
+	gettr	tr1, r20
+	shlli	r0, 3, r21
+	add	r20, r21, r20
+	ptabs/l	r20, tr1
+	blink	tr1, r63
+
+.L_pop_i_tbl:
+	ld.q	r15, 0, r2
+	blink	tr0, r63
+	ld.q	r15, 0, r3
+	blink	tr0, r63
+	ld.q	r15, 0, r4
+	blink	tr0, r63
+	ld.q	r15, 0, r5
+	blink	tr0, r63
+	ld.q	r15, 0, r6
+	blink	tr0, r63
+	ld.q	r15, 0, r7
+	blink	tr0, r63
+	ld.q	r15, 0, r8
+	blink	tr0, r63
+	ld.q	r15, 0, r9
+	blink	tr0, r63
+
+.L_call_it:
+	# call function
+	pt/l	1f, tr1
+	bnei/l	r29, FFI_TYPE_STRUCT, tr1
+	add	r19, r63, r2
+1:
+	add	r22, r63, r15
+	ptabs/l	r32, tr0
+	blink	tr0, r18
+
+	pt/l	.L_ret_i, tr0
+	pt/l	.L_ret_ll, tr1
+	pt/l	.L_ret_d, tr2
+	pt/l	.L_ret_f, tr3
+	pt/l	.L_epilogue, tr4
+
+	beqi/l	r29, FFI_TYPE_INT, tr0
+	beqi/l	r29, FFI_TYPE_UINT32, tr0
+	beqi/l	r29, FFI_TYPE_SINT64, tr1
+	beqi/l	r29, FFI_TYPE_UINT64, tr1
+	beqi/l	r29, FFI_TYPE_DOUBLE, tr2
+	beqi/l	r29, FFI_TYPE_FLOAT, tr3
+
+	pt/l	.L_ret_q, tr0
+	pt/l	.L_ret_h, tr1
+
+	beqi/l	r29, FFI_TYPE_UINT8, tr0
+	beqi/l	r29, FFI_TYPE_UINT16, tr1
+	blink	tr4, r63
+
+.L_ret_d:
+	fst.d	r31, 0, dr0
+	blink	tr4, r63
+
+.L_ret_ll:
+	st.q	r31, 0, r2
+	blink	tr4, r63
+
+.L_ret_f:
+	fst.s	r31, OFS_FLT, fr0
+	blink	tr4, r63
+
+.L_ret_q:
+	st.b	r31, 0, r2
+	blink	tr4, r63
+
+.L_ret_h:
+	st.w	r31, 0, r2
+	blink	tr4, r63
+
+.L_ret_i:
+	st.l	r31, 0, r2
+	# Fall
+
+.L_epilogue:
+	# Remove the space we pushed for the args
+	add	r14, r63, r15
+
+	ld.l	r15, 0, r14
+	ld.l	r15, 4, r18
+	ld.q	r15, 8, r28
+	ld.q	r15, 16, r29
+	ld.q	r15, 24, r30
+	ld.q	r15, 32, r31
+	ld.q	r15, 40, r32
+	addi.l	r15, 48, r15
+	ptabs	r18, tr0
+	blink	tr0, r63
+
+.LFE1:
+.ffi_call_SYSV_end:
+	.size	 CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
+	.align	5
+ENTRY(ffi_closure_SYSV)
+.LFB2:
+	addi.l	r15, -136, r15
+.LCFI3:
+	st.l	r15, 12, r18
+	st.l	r15, 8, r14
+	st.l	r15, 4, r12
+.LCFI4:
+	add	r15, r63, r14
+.LCFI5:
+	/* Stack layout:	
+	   ...
+	   64 bytes (register parameters)
+	   48 bytes (floating register parameters)
+	    8 bytes (result)
+	    4 bytes (r18)
+	    4 bytes (r14)
+	    4 bytes (r12)
+	    4 bytes (for align)
+	   <- new stack pointer
+	*/
+	fst.d	r14, 24, dr0
+	fst.d	r14, 32, dr2
+	fst.d	r14, 40, dr4
+	fst.d	r14, 48, dr6
+	fst.d	r14, 56, dr8
+	fst.d	r14, 64, dr10
+	st.q	r14, 72, r2
+	st.q	r14, 80, r3
+	st.q	r14, 88, r4
+	st.q	r14, 96, r5
+	st.q	r14, 104, r6
+	st.q	r14, 112, r7
+	st.q	r14, 120, r8
+	st.q	r14, 128, r9
+
+	add	r1, r63, r2
+	addi	r14, 16, r3
+	addi	r14, 72, r4
+	addi	r14, 24, r5
+	addi	r14, 136, r6
+#ifdef PIC
+	movi	(((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12
+        shori	((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12
+.LPCS0:	ptrel/u r12, tr0
+	movi	((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1
+	gettr	tr0, r12
+	ldx.l	r1, r12, r1
+	ptabs	r1, tr0
+#else
+	pt/l	ffi_closure_helper_SYSV, tr0
+#endif
+	blink	tr0, r18
+
+	shlli	r2, 1, r1
+        movi    (((datalabel .L_table) >> 16) & 65535), r2
+        shori   ((datalabel .L_table) & 65535), r2
+        ldx.w   r2, r1, r1
+        add     r1, r2, r1
+	pt/l	.L_case_v, tr1
+        ptabs   r1, tr0
+        blink   tr0, r63
+
+        .align 2
+.L_table:
+	.word	.L_case_v - datalabel .L_table	/* FFI_TYPE_VOID */
+	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_INT */
+	.word	.L_case_f - datalabel .L_table	/* FFI_TYPE_FLOAT */
+	.word	.L_case_d - datalabel .L_table	/* FFI_TYPE_DOUBLE */
+	.word	.L_case_d - datalabel .L_table	/* FFI_TYPE_LONGDOUBLE */
+	.word	.L_case_uq - datalabel .L_table	/* FFI_TYPE_UINT8 */
+	.word	.L_case_q - datalabel .L_table	/* FFI_TYPE_SINT8 */
+	.word	.L_case_uh - datalabel .L_table	/* FFI_TYPE_UINT16 */
+	.word	.L_case_h - datalabel .L_table	/* FFI_TYPE_SINT16 */
+	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_UINT32 */
+	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_SINT32 */
+	.word	.L_case_ll - datalabel .L_table	/* FFI_TYPE_UINT64 */
+	.word	.L_case_ll - datalabel .L_table	/* FFI_TYPE_SINT64 */
+	.word	.L_case_v - datalabel .L_table	/* FFI_TYPE_STRUCT */
+	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_POINTER */
+
+        .align 2
+.L_case_d:
+	fld.d	r14, 16, dr0
+	blink	tr1, r63
+.L_case_f:
+	fld.s	r14, 16, fr0
+	blink	tr1, r63
+.L_case_ll:
+	ld.q	r14, 16, r2
+	blink	tr1, r63
+.L_case_i:
+	ld.l	r14, 16, r2
+	blink	tr1, r63
+.L_case_q:
+	ld.b	r14, 16, r2
+	blink	tr1, r63
+.L_case_uq:
+	ld.ub	r14, 16, r2
+	blink	tr1, r63
+.L_case_h:
+	ld.w	r14, 16, r2
+	blink	tr1, r63
+.L_case_uh:
+	ld.uw	r14, 16, r2
+	blink	tr1, r63
+.L_case_v:
+	add.l	r14, r63, r15
+	ld.l	r15, 4, r12
+	ld.l	r15, 8, r14
+	ld.l	r15, 12, r18
+	addi.l	r15, 136, r15
+	ptabs	r18, tr0
+	blink	tr0, r63
+
+.LFE2:
+.ffi_closure_SYSV_end:
+	.size	 CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
+
+	.section	".eh_frame","aw",@progbits
+__FRAME_BEGIN__:
+	.4byte	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
+.LSCIE1:
+	.4byte	0x0	/* CIE Identifier Tag */
+	.byte	0x1	/* CIE Version */
+#ifdef PIC
+	.ascii "zR\0"	/* CIE Augmentation */
+#else
+	.byte	0x0	/* CIE Augmentation */
+#endif
+	.uleb128 0x1	/* CIE Code Alignment Factor */
+	.sleb128 -4	/* CIE Data Alignment Factor */
+	.byte	0x12	/* CIE RA Column */
+#ifdef PIC
+	.uleb128 0x1	/* Augmentation size */
+	.byte	0x10	/* FDE Encoding (pcrel) */
+#endif
+	.byte	0xc	/* DW_CFA_def_cfa */
+	.uleb128 0xf
+	.uleb128 0x0
+	.align	2
+.LECIE1:
+.LSFDE1:
+	.4byte	datalabel .LEFDE1-datalabel .LASFDE1	/* FDE Length */
+.LASFDE1:
+	.4byte	datalabel .LASFDE1-datalabel __FRAME_BEGIN__
+#ifdef PIC
+	.4byte	.LFB1-.	/* FDE initial location */
+#else
+	.4byte	.LFB1	/* FDE initial location */
+#endif
+	.4byte	datalabel .LFE1-datalabel .LFB1	/* FDE address range */
+#ifdef PIC
+	.uleb128 0x0	/* Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	datalabel .LCFI0-datalabel .LFB1
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.uleb128 0x30
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	datalabel .LCFI1-datalabel .LCFI0
+	.byte   0x8e	/* DW_CFA_offset, column 0xe */
+	.uleb128 0xc
+	.byte   0x92	/* DW_CFA_offset, column 0x12 */
+	.uleb128 0xb
+	.byte   0x9c	/* DW_CFA_offset, column 0x1c */
+	.uleb128 0xa
+	.byte   0x9d	/* DW_CFA_offset, column 0x1d */
+	.uleb128 0x8
+	.byte   0x9e	/* DW_CFA_offset, column 0x1e */
+	.uleb128 0x6
+	.byte   0x9f	/* DW_CFA_offset, column 0x1f */
+	.uleb128 0x4
+	.byte   0xa0	/* DW_CFA_offset, column 0x20 */
+	.uleb128 0x2
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	datalabel .LCFI2-datalabel .LCFI1
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.uleb128 0xe
+	.align	2
+.LEFDE1:
+
+.LSFDE3:
+	.4byte	datalabel .LEFDE3-datalabel .LASFDE3	/* FDE Length */
+.LASFDE3:
+	.4byte	datalabel .LASFDE3-datalabel __FRAME_BEGIN__
+#ifdef PIC
+	.4byte	.LFB2-.	/* FDE initial location */
+#else
+	.4byte	.LFB2	/* FDE initial location */
+#endif
+	.4byte	datalabel .LFE2-datalabel .LFB2	/* FDE address range */
+#ifdef PIC
+	.uleb128 0x0	/* Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	datalabel .LCFI3-datalabel .LFB2
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.uleb128 0x88
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	datalabel .LCFI4-datalabel .LCFI3
+	.byte   0x8c	/* DW_CFA_offset, column 0xc */
+	.uleb128 0x21
+	.byte   0x8e	/* DW_CFA_offset, column 0xe */
+	.uleb128 0x20
+	.byte   0x92	/* DW_CFA_offset, column 0x12 */
+	.uleb128 0x1f
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.4byte	datalabel .LCFI5-datalabel .LCFI4
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.uleb128 0xe
+	.align	2
+.LEFDE3:
diff --git a/third_party/gofrontend/libffi/src/sparc/ffi.c b/third_party/gofrontend/libffi/src/sparc/ffi.c
new file mode 100644
index 0000000..77e3822
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sparc/ffi.c
@@ -0,0 +1,723 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2011 Anthony Green
+           Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
+
+   SPARC Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+#ifdef SPARC64
+
+int
+ffi_prep_args_v9(char *stack, extended_cif *ecif)
+{
+  int i, ret = 0;
+  int tmp;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  tmp = 0;
+
+  /* Skip 16 words for the window save area */
+  argp = stack + 16*sizeof(long long);
+
+#ifdef USING_PURIFY
+  /* Purify will probably complain in our assembly routine, unless we
+     zero out this memory. */
+
+  ((long long*)argp)[0] = 0;
+  ((long long*)argp)[1] = 0;
+  ((long long*)argp)[2] = 0;
+  ((long long*)argp)[3] = 0;
+  ((long long*)argp)[4] = 0;
+  ((long long*)argp)[5] = 0;
+#endif
+
+  p_argv = ecif->avalue;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
+      ecif->cif->rtype->size > 32)
+    {
+      *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
+      argp += sizeof(long long);
+      tmp = 1;
+    }
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
+       i++, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      switch ((*p_arg)->type)
+	{
+	case FFI_TYPE_STRUCT:
+	  if (z > 16)
+	    {
+	      /* For structures larger than 16 bytes we pass reference.  */
+	      *(unsigned long long *) argp = (unsigned long)* p_argv;
+	      argp += sizeof(long long);
+	      tmp++;
+	      p_argv++;
+	      continue;
+	    }
+	  /* FALLTHROUGH */
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+#endif
+	  ret = 1; /* We should promote into FP regs as well as integer.  */
+	  break;
+	}
+      if (z < sizeof(long long))
+	{
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	      *(signed long long *) argp = *(SINT8 *)(* p_argv);
+	      break;
+
+	    case FFI_TYPE_UINT8:
+	      *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
+	      break;
+
+	    case FFI_TYPE_SINT16:
+	      *(signed long long *) argp = *(SINT16 *)(* p_argv);
+	      break;
+
+	    case FFI_TYPE_UINT16:
+	      *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
+	      break;
+
+	    case FFI_TYPE_SINT32:
+	      *(signed long long *) argp = *(SINT32 *)(* p_argv);
+	      break;
+
+	    case FFI_TYPE_UINT32:
+	      *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
+	      break;
+
+	    case FFI_TYPE_FLOAT:
+	      *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
+	      break;
+
+	    case FFI_TYPE_STRUCT:
+	      memcpy(argp, *p_argv, z);
+	      break;
+
+	    default:
+	      FFI_ASSERT(0);
+	    }
+	  z = sizeof(long long);
+	  tmp++;
+	}
+      else if (z == sizeof(long long))
+	{
+	  memcpy(argp, *p_argv, z);
+	  z = sizeof(long long);
+	  tmp++;
+	}
+      else
+	{
+	  if ((tmp & 1) && (*p_arg)->alignment > 8)
+	    {
+	      tmp++;
+	      argp += sizeof(long long);
+	    }
+	  memcpy(argp, *p_argv, z);
+	  z = 2 * sizeof(long long);
+	  tmp += 2;
+	}
+      p_argv++;
+      argp += z;
+    }
+
+  return ret;
+}
+
+#else
+
+void
+ffi_prep_args_v8(char *stack, extended_cif *ecif)
+{
+  int i;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  /* Skip 16 words for the window save area */
+  argp = stack + 16*sizeof(int);
+
+  /* This should only really be done when we are returning a structure,
+     however, it's faster just to do it all the time...
+
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
+  *(int *) argp = (long)ecif->rvalue;
+
+  /* And 1 word for the  structure return value. */
+  argp += sizeof(int);
+
+#ifdef USING_PURIFY
+  /* Purify will probably complain in our assembly routine, unless we
+     zero out this memory. */
+
+  ((int*)argp)[0] = 0;
+  ((int*)argp)[1] = 0;
+  ((int*)argp)[2] = 0;
+  ((int*)argp)[3] = 0;
+  ((int*)argp)[4] = 0;
+  ((int*)argp)[5] = 0;
+#endif
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
+    {
+      size_t z;
+
+	  if ((*p_arg)->type == FFI_TYPE_STRUCT
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	      || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
+#endif
+	      )
+	    {
+	      *(unsigned int *) argp = (unsigned long)(* p_argv);
+	      z = sizeof(int);
+	    }
+	  else
+	    {
+	      z = (*p_arg)->size;
+	      if (z < sizeof(int))
+		{
+		  z = sizeof(int);
+		  switch ((*p_arg)->type)
+		    {
+		    case FFI_TYPE_SINT8:
+		      *(signed int *) argp = *(SINT8 *)(* p_argv);
+		      break;
+		      
+		    case FFI_TYPE_UINT8:
+		      *(unsigned int *) argp = *(UINT8 *)(* p_argv);
+		      break;
+		      
+		    case FFI_TYPE_SINT16:
+		      *(signed int *) argp = *(SINT16 *)(* p_argv);
+		      break;
+		      
+		    case FFI_TYPE_UINT16:
+		      *(unsigned int *) argp = *(UINT16 *)(* p_argv);
+		      break;
+
+		    default:
+		      FFI_ASSERT(0);
+		    }
+		}
+	      else
+		{
+		  memcpy(argp, *p_argv, z);
+		}
+	    }
+	  p_argv++;
+	  argp += z;
+    }
+  
+  return;
+}
+
+#endif
+
+/* Perform machine dependent cif processing */
+
+static
+ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
+{
+  int wordsize;
+
+  if (!V9_ABI_P (cif->abi))
+    {
+      wordsize = 4;
+
+      /* If we are returning a struct, this will already have been added.
+	 Otherwise we need to add it because it's always got to be there! */
+
+      if (cif->rtype->type != FFI_TYPE_STRUCT)
+	cif->bytes += wordsize;
+
+      /* sparc call frames require that space is allocated for 6 args,
+	 even if they aren't used. Make that space if necessary. */
+  
+      if (cif->bytes < 4*6+4)
+	cif->bytes = 4*6+4;
+    }
+  else
+    {
+      wordsize = 8;
+
+      /* sparc call frames require that space is allocated for 6 args,
+	 even if they aren't used. Make that space if necessary. */
+  
+      if (cif->bytes < 8*6)
+	cif->bytes = 8*6;
+    }
+
+  /* Adjust cif->bytes. to include 16 words for the window save area,
+     and maybe the struct/union return pointer area, */
+
+  cif->bytes += 16 * wordsize;
+
+  /* The stack must be 2 word aligned, so round bytes up
+     appropriately. */
+
+  cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+#endif
+      cif->flags = cif->rtype->type;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (V9_ABI_P (cif->abi) && cif->rtype->size > 32)
+	cif->flags = FFI_TYPE_VOID;
+      else
+	cif->flags = FFI_TYPE_STRUCT;
+      break;
+
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT16:
+      if (V9_ABI_P (cif->abi))
+	cif->flags = FFI_TYPE_INT;
+      else
+	cif->flags = cif->rtype->type;
+      break;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      if (V9_ABI_P (cif->abi))
+	cif->flags = FFI_TYPE_INT;
+      else
+	cif->flags = FFI_TYPE_SINT64;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+  return FFI_OK;
+}
+
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+#ifdef SPARC64
+  if (cif->abi != FFI_COMPAT_V9)
+    cif->nfixedargs = cif->nargs;
+#endif
+  return ffi_prep_cif_machdep_core (cif);
+}
+
+ffi_status
+ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs,
+			 unsigned int ntotalargs)
+{
+#ifdef SPARC64
+  if (cif->abi != FFI_COMPAT_V9)
+    cif->nfixedargs = nfixedargs;
+#endif
+  return ffi_prep_cif_machdep_core (cif);
+}
+
+#ifdef SPARC64
+
+int
+ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
+{
+  ffi_type **ptr = &arg->elements[0];
+
+  while (*ptr != NULL)
+    {
+      if (off & ((*ptr)->alignment - 1))
+	off = ALIGN(off, (*ptr)->alignment);
+
+      switch ((*ptr)->type)
+	{
+	case FFI_TYPE_STRUCT:
+	  off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt);
+	  off = ALIGN(off, FFI_SIZEOF_ARG);
+	  break;
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+#endif
+	  memmove(ret + off, flt + off, (*ptr)->size);
+	  off += (*ptr)->size;
+	  break;
+	default:
+	  memmove(ret + off, intg + off, (*ptr)->size);
+	  off += (*ptr)->size;
+	  break;
+	}
+      ptr++;
+    }
+  return off;
+}
+
+#endif
+
+#ifdef SPARC64
+extern int ffi_call_v9(void *, extended_cif *, unsigned, 
+		       unsigned, unsigned *, void (*fn)(void));
+#else
+extern int ffi_call_v8(void *, extended_cif *, unsigned, 
+		       unsigned, unsigned *, void (*fn)(void));
+#endif
+
+void
+ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+#ifdef SPARC64
+  void *rval = rvalue;
+#endif
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  ecif.rvalue = rvalue;
+
+  /* If the return value is a struct and we don't have a return value address,
+     then we need to make one.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      if (ecif.rvalue == NULL)
+	ecif.rvalue = alloca(cif->rtype->size);
+
+#ifdef SPARC64
+      if (cif->rtype->size <= 32)
+	rval = alloca(64);
+      else
+	rval = NULL;
+#endif
+    }
+
+  switch (cif->abi) 
+    {
+    case FFI_V8:
+    case FFI_V8PLUS:
+#ifdef SPARC64
+      /* We don't yet support calling 32bit code from 64bit */
+      FFI_ASSERT(0);
+#else
+      if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	  || cif->flags == FFI_TYPE_LONGDOUBLE
+#endif
+	  ))
+	{
+	  /* For v8, we need an "unimp" with size of returning struct */
+	  /* behind "call", so we alloc some executable space for it. */
+	  /* l7 is used, we need to make sure v8.S doesn't use %l7.   */
+	  unsigned int *call_struct = NULL;
+	  ffi_closure_alloc(32, (void **)&call_struct);
+	  if (call_struct)
+	    {
+	      unsigned long f = (unsigned long)fn;
+	      call_struct[0] = 0xae10001f;		 /* mov   %i7, %l7	 */
+	      call_struct[1] = 0xbe10000f;		 /* mov   %o7, %i7	 */
+	      call_struct[2] = 0x03000000 | f >> 10;     /* sethi %hi(fn), %g1	 */
+	      call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */
+	      call_struct[4] = 0x01000000;		 /* nop			 */
+	      if (cif->rtype->size < 0x7f)
+		call_struct[5] = cif->rtype->size;	 /* unimp		 */
+	      else
+		call_struct[5] = 0x01000000;	     	 /* nop			 */
+	      call_struct[6] = 0x81c7e008;		 /* ret			 */
+	      call_struct[7] = 0xbe100017;		 /* mov   %l7, %i7	 */
+	      asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : :
+			    "r" (call_struct) : "memory");
+	      /* SPARC v8 requires 5 instructions for flush to be visible */
+	      asm volatile ("nop; nop; nop; nop; nop");
+	      ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
+			  cif->flags, rvalue, (void (*)(void)) call_struct);
+	      ffi_closure_free(call_struct);
+	    }
+	  else
+	    {
+	      ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
+			  cif->flags, rvalue, fn);
+	    }
+	}
+      else
+	{
+	  ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
+		      cif->flags, rvalue, fn);
+	}
+#endif
+      break;
+    case FFI_COMPAT_V9:
+    case FFI_V9:
+#ifdef SPARC64
+      ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes, cif->flags, rval, fn);
+      if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
+	ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval,
+			     ((char *)rval)+32);
+#else
+      /* And vice versa */
+      FFI_ASSERT(0);
+#endif
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+
+#ifdef SPARC64
+extern void ffi_closure_v9(void);
+#else
+extern void ffi_closure_v8(void);
+#endif
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+  unsigned long fn;
+#ifdef SPARC64
+  /* Trampoline address is equal to the closure address.  We take advantage
+     of that to reduce the trampoline size by 8 bytes. */
+  if (!V9_ABI_P (cif->abi))
+    return FFI_BAD_ABI;
+  fn = (unsigned long) ffi_closure_v9;
+  tramp[0] = 0x83414000;	/* rd	%pc, %g1	*/
+  tramp[1] = 0xca586010;	/* ldx	[%g1+16], %g5	*/
+  tramp[2] = 0x81c14000;	/* jmp	%g5		*/
+  tramp[3] = 0x01000000;	/* nop			*/
+  *((unsigned long *) &tramp[4]) = fn;
+#else
+  unsigned long ctx = (unsigned long) codeloc;
+  if (!V8_ABI_P (cif->abi))
+    return FFI_BAD_ABI;
+  fn = (unsigned long) ffi_closure_v8;
+  tramp[0] = 0x03000000 | fn >> 10;	/* sethi %hi(fn), %g1	*/
+  tramp[1] = 0x05000000 | ctx >> 10;	/* sethi %hi(ctx), %g2	*/
+  tramp[2] = 0x81c06000 | (fn & 0x3ff);	/* jmp   %g1+%lo(fn)	*/
+  tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or    %g2, %lo(ctx)	*/
+#endif
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Flush the Icache.  closure is 8 bytes aligned.  */
+#ifdef SPARC64
+  asm volatile ("flush	%0; flush %0+8" : : "r" (closure) : "memory");
+#else
+  asm volatile ("iflush	%0; iflush %0+8" : : "r" (closure) : "memory");
+  /* SPARC v8 requires 5 instructions for flush to be visible */
+  asm volatile ("nop; nop; nop; nop; nop");
+#endif
+
+  return FFI_OK;
+}
+
+#ifdef SPARC64
+
+int
+ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue,
+			   unsigned long *gpr, double *fpr)
+{
+  ffi_cif *cif;
+  ffi_type **arg_types;
+  void **avalue;
+  int i, argn, fp_slot_max;
+
+  cif = closure->cif;
+  arg_types = cif->arg_types;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  /* Copy the caller's structure return address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->flags == FFI_TYPE_VOID && cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *) gpr[0];
+      /* Skip the structure return address.  */
+      argn = 1;
+    }
+  else
+    argn = 0;
+
+  fp_slot_max = 16 - argn;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0; i < cif->nargs; i++)
+    {
+      /* If the function is variadic, FP arguments are passed in FP
+	 registers only if the corresponding parameter is named.  */
+      const int named
+	= (cif->abi == FFI_COMPAT_V9 ? 1 : i < cif->nfixedargs);
+
+      if (arg_types[i]->type == FFI_TYPE_STRUCT)
+	{
+	  if (arg_types[i]->size > 16)
+	    {
+	      /* Straight copy of invisible reference.  */
+	      avalue[i] = (void *)gpr[argn++];
+	    }
+	  else
+	    {
+	      /* Left-justify.  */
+	      ffi_v9_layout_struct(arg_types[i],
+				   0,
+				   (char *) &gpr[argn],
+				   (char *) &gpr[argn],
+				   named
+				   ? (char *) &fpr[argn]
+				   : (char *) &gpr[argn]);
+	      avalue[i] = &gpr[argn];
+	      argn
+	        += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+	    }
+	}
+      else
+	{
+	  /* Right-justify.  */
+	  argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+
+	  /* Align on a 16-byte boundary.  */
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	  if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
+	    argn++;
+#endif
+	  if (i < fp_slot_max
+	      && named
+	      && (arg_types[i]->type == FFI_TYPE_FLOAT
+		  || arg_types[i]->type == FFI_TYPE_DOUBLE
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+		  || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
+#endif
+		  ))
+	    avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
+	  else
+	    avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
+	}
+    }
+
+  /* Invoke the closure.  */
+  closure->fun (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_sparc how to perform return type promotions.  */
+  return cif->rtype->type;
+}
+
+#else
+
+int
+ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue,
+			   unsigned long *gpr, unsigned long *scratch)
+{
+  ffi_cif *cif;
+  ffi_type **arg_types;
+  void **avalue;
+  int i, argn;
+
+  cif = closure->cif;
+  arg_types = cif->arg_types;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  /* Copy the caller's structure return address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->flags == FFI_TYPE_STRUCT
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE  
+      || cif->flags == FFI_TYPE_LONGDOUBLE
+#endif
+     )
+    rvalue = (void *) gpr[0];
+
+  /* Always skip the structure return address.  */
+  argn = 1;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0; i < cif->nargs; i++)
+    {
+      if (arg_types[i]->type == FFI_TYPE_STRUCT
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	  || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
+#endif
+         )
+	{
+	  /* Straight copy of invisible reference.  */
+	  avalue[i] = (void *)gpr[argn++];
+	}
+      else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
+	       || arg_types[i]->type == FFI_TYPE_SINT64
+	       || arg_types[i]->type == FFI_TYPE_UINT64)
+	       /* gpr is 8-byte aligned.  */
+	       && (argn % 2) != 0)
+	{
+	  /* Align on a 8-byte boundary.  */
+	  scratch[0] = gpr[argn];
+	  scratch[1] = gpr[argn+1];
+	  avalue[i] = scratch;
+	  scratch -= 2;
+	  argn += 2;
+	}
+      else
+	{
+	  /* Always right-justify.  */
+	  argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+	  avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
+	}
+    }
+
+  /* Invoke the closure.  */
+  closure->fun (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_sparc how to perform return type promotions.  */
+  return cif->rtype->type;
+}
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/sparc/ffitarget.h b/third_party/gofrontend/libffi/src/sparc/ffitarget.h
new file mode 100644
index 0000000..6489ac0
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sparc/ffitarget.h
@@ -0,0 +1,87 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for SPARC.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+/* ---- System specific configurations ----------------------------------- */
+
+#if defined(__arch64__) || defined(__sparcv9)
+#ifndef SPARC64
+#define SPARC64
+#endif
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_V8,
+  FFI_V8PLUS,
+  /* See below for the COMPAT_V9 rationale.  */
+  FFI_COMPAT_V9,
+  FFI_V9,
+  FFI_LAST_ABI,
+#ifdef SPARC64
+  FFI_DEFAULT_ABI = FFI_V9
+#else
+  FFI_DEFAULT_ABI = FFI_V8
+#endif
+} ffi_abi;
+#endif
+
+#define V8_ABI_P(abi) ((abi) == FFI_V8 || (abi) == FFI_V8PLUS)
+#define V9_ABI_P(abi) ((abi) == FFI_COMPAT_V9 || (abi) == FFI_V9)
+
+#define FFI_TARGET_SPECIFIC_VARIADIC 1
+
+/* The support of variadic functions was broken in the original implementation
+   of the FFI_V9 ABI.  This has been fixed by adding one extra field to the
+   CIF structure (nfixedargs field), which means that the ABI of libffi itself
+   has changed.  In order to support applications using the original ABI, we
+   have renamed FFI_V9 into FFI_COMPAT_V9 and defined a new FFI_V9 value.  */
+#ifdef SPARC64
+#define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#ifdef SPARC64
+#define FFI_TRAMPOLINE_SIZE 24
+#else
+#define FFI_TRAMPOLINE_SIZE 16
+#endif
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/sparc/v8.S b/third_party/gofrontend/libffi/src/sparc/v8.S
new file mode 100644
index 0000000..7ec6e1c
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sparc/v8.S
@@ -0,0 +1,316 @@
+/* -----------------------------------------------------------------------
+   v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
+
+   SPARC Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+#ifndef SPARC64
+
+#define STACKFRAME 96		/* Minimum stack framesize for SPARC */
+#define ARGS (64+4)		/* Offset of register area in frame */
+
+.text
+        .align 8
+.globl ffi_call_v8
+.globl _ffi_call_v8
+
+ffi_call_v8:
+_ffi_call_v8:
+.LLFB1:
+	save	%sp, -STACKFRAME, %sp
+.LLCFI0:
+	
+	sub	%sp, %i2, %sp	! alloca() space in stack for frame to set up
+	add	%sp, STACKFRAME, %l0	! %l0 has start of 
+					! frame to set up
+
+	mov	%l0, %o0	! call routine to set up frame
+	call	%i0
+	mov	%i1, %o1	! (delay)
+
+	ld	[%l0+ARGS], %o0	! call foreign function
+	ld	[%l0+ARGS+4], %o1
+	ld	[%l0+ARGS+8], %o2
+	ld	[%l0+ARGS+12], %o3
+	ld	[%l0+ARGS+16], %o4
+	ld	[%l0+ARGS+20], %o5
+	call	%i5
+	mov	%l0, %sp	! (delay) switch to frame
+	nop			! STRUCT returning functions skip 12 instead of 8 bytes
+
+	! If the return value pointer is NULL, assume no return value.
+	tst	%i4
+	bz	done
+	nop
+
+	cmp	%i3, FFI_TYPE_INT
+	be,a	done
+	st	%o0, [%i4]	! (delay)
+
+	cmp	%i3, FFI_TYPE_FLOAT
+	be,a	done
+	st	%f0, [%i4+0]	! (delay)
+
+	cmp	%i3, FFI_TYPE_DOUBLE
+	be,a	double
+	st	%f0, [%i4+0]	! (delay)
+
+	cmp	%i3, FFI_TYPE_SINT8
+	be,a	sint8
+	sll	%o0, 24, %o0	! (delay)
+
+	cmp	%i3, FFI_TYPE_UINT8
+	be,a	uint8
+	sll	%o0, 24, %o0	! (delay)
+
+	cmp	%i3, FFI_TYPE_SINT16
+	be,a	sint16
+	sll	%o0, 16, %o0	! (delay)
+
+	cmp	%i3, FFI_TYPE_UINT16
+	be,a	uint16
+	sll	%o0, 16, %o0	! (delay)
+
+	cmp	%i3, FFI_TYPE_SINT64
+	be,a	longlong
+	st	%o0, [%i4+0]	! (delay)
+done:
+	ret
+	restore
+
+double:
+	st	%f1, [%i4+4]
+	ret
+	restore
+
+sint8:
+	sra	%o0, 24, %o0
+	st	%o0, [%i4+0]
+	ret
+	restore
+
+uint8:
+	srl	%o0, 24, %o0
+	st	%o0, [%i4+0]
+	ret
+	restore
+
+sint16:
+	sra	%o0, 16, %o0
+	st	%o0, [%i4+0]
+	ret
+	restore
+
+uint16:
+	srl	%o0, 16, %o0
+	st	%o0, [%i4+0]
+	ret
+	restore
+
+longlong:
+	st	%o1, [%i4+4]
+	ret
+	restore
+.LLFE1:
+
+.ffi_call_v8_end:
+	.size	ffi_call_v8,.ffi_call_v8_end-ffi_call_v8
+
+
+#undef STACKFRAME
+#define	STACKFRAME	104	/* 16*4 register window +
+				   1*4 struct return +	
+				   6*4 args backing store +
+				   3*4 locals */
+
+/* ffi_closure_v8(...)
+
+   Receives the closure argument in %g2.   */
+
+	.text
+	.align 8
+	.globl ffi_closure_v8
+
+ffi_closure_v8:
+#ifdef HAVE_AS_REGISTER_PSEUDO_OP
+		.register	%g2, #scratch
+#endif
+.LLFB2:
+	! Reserve frame space for all arguments in case
+	! we need to align them on a 8-byte boundary.
+	ld	[%g2+FFI_TRAMPOLINE_SIZE], %g1
+	ld	[%g1+4], %g1
+	sll	%g1, 3, %g1
+	add	%g1, STACKFRAME, %g1
+	! %g1 == STACKFRAME + 8*nargs
+	neg	%g1
+	save	%sp, %g1, %sp
+.LLCFI1:
+
+	! Store all of the potential argument registers in va_list format.
+	st	%i0, [%fp+68+0]
+	st	%i1, [%fp+68+4]
+	st	%i2, [%fp+68+8]
+	st	%i3, [%fp+68+12]
+	st	%i4, [%fp+68+16]
+	st	%i5, [%fp+68+20]
+
+	! Call ffi_closure_sparc_inner to do the bulk of the work.
+	mov	%g2, %o0
+	add	%fp, -8, %o1
+	add	%fp,  64, %o2
+	call	ffi_closure_sparc_inner_v8
+	 add	%fp, -16, %o3
+
+	! Load up the return value in the proper type.
+	! See ffi_prep_cif_machdep for the list of cases.
+	cmp	%o0, FFI_TYPE_VOID
+	be	done1
+
+	cmp	%o0, FFI_TYPE_INT
+	be	done1
+	 ld	[%fp-8], %i0
+
+	cmp	%o0, FFI_TYPE_FLOAT
+	be,a	done1
+	 ld	[%fp-8], %f0
+
+	cmp	%o0, FFI_TYPE_DOUBLE
+	be,a	done1
+	 ldd	[%fp-8], %f0
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	cmp	%o0, FFI_TYPE_LONGDOUBLE
+	be	done2
+#endif
+
+	cmp	%o0, FFI_TYPE_STRUCT
+	be	done2
+
+	cmp	%o0, FFI_TYPE_SINT64
+	be,a	done1
+	 ldd	[%fp-8], %i0
+
+	ld	[%fp-8], %i0
+done1:
+	jmp	%i7+8
+	 restore
+done2:
+	! Skip 'unimp'.
+	jmp	%i7+12
+	 restore
+.LLFE2:
+
+.ffi_closure_v8_end:
+	.size	ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8
+
+#ifdef SPARC64
+#define WS 8
+#define nword	xword
+#define uanword	uaxword
+#else
+#define WS 4
+#define nword	long
+#define uanword	uaword
+#endif
+
+#ifdef HAVE_RO_EH_FRAME
+	.section	".eh_frame",#alloc
+#else
+	.section	".eh_frame",#alloc,#write
+#endif
+.LLframe1:
+	.uaword	.LLECIE1-.LLSCIE1	! Length of Common Information Entry
+.LLSCIE1:
+	.uaword	0x0	! CIE Identifier Tag
+	.byte	0x1	! CIE Version
+	.ascii "zR\0"	! CIE Augmentation
+	.byte	0x1	! uleb128 0x1; CIE Code Alignment Factor
+	.byte	0x80-WS	! sleb128 -WS; CIE Data Alignment Factor
+	.byte	0xf	! CIE RA Column
+	.byte	0x1	! uleb128 0x1; Augmentation size
+#ifdef HAVE_AS_SPARC_UA_PCREL
+	.byte	0x1b	! FDE Encoding (pcrel sdata4)
+#else
+	.byte	0x50	! FDE Encoding (aligned absolute)
+#endif
+	.byte	0xc	! DW_CFA_def_cfa
+	.byte	0xe	! uleb128 0xe
+	.byte	0x0	! uleb128 0x0
+	.align	WS
+.LLECIE1:
+.LLSFDE1:
+	.uaword	.LLEFDE1-.LLASFDE1	! FDE Length
+.LLASFDE1:
+	.uaword	.LLASFDE1-.LLframe1	! FDE CIE offset
+#ifdef HAVE_AS_SPARC_UA_PCREL
+	.uaword	%r_disp32(.LLFB1)
+	.uaword	.LLFE1-.LLFB1	! FDE address range
+#else
+	.align	WS
+	.nword	.LLFB1
+	.uanword .LLFE1-.LLFB1	! FDE address range
+#endif
+	.byte	0x0	! uleb128 0x0; Augmentation size
+	.byte	0x4	! DW_CFA_advance_loc4
+	.uaword	.LLCFI0-.LLFB1
+	.byte	0xd	! DW_CFA_def_cfa_register
+	.byte	0x1e	! uleb128 0x1e
+	.byte	0x2d	! DW_CFA_GNU_window_save
+	.byte	0x9	! DW_CFA_register
+	.byte	0xf	! uleb128 0xf
+	.byte	0x1f	! uleb128 0x1f
+	.align	WS
+.LLEFDE1:
+.LLSFDE2:
+	.uaword	.LLEFDE2-.LLASFDE2	! FDE Length
+.LLASFDE2:
+	.uaword	.LLASFDE2-.LLframe1	! FDE CIE offset
+#ifdef HAVE_AS_SPARC_UA_PCREL
+	.uaword	%r_disp32(.LLFB2)
+	.uaword	.LLFE2-.LLFB2	! FDE address range
+#else
+	.align	WS
+	.nword	.LLFB2
+	.uanword .LLFE2-.LLFB2	! FDE address range
+#endif
+	.byte	0x0	! uleb128 0x0; Augmentation size
+	.byte	0x4	! DW_CFA_advance_loc4
+	.uaword	.LLCFI1-.LLFB2
+	.byte	0xd	! DW_CFA_def_cfa_register
+	.byte	0x1e	! uleb128 0x1e
+	.byte	0x2d	! DW_CFA_GNU_window_save
+	.byte	0x9	! DW_CFA_register
+	.byte	0xf	! uleb128 0xf
+	.byte	0x1f	! uleb128 0x1f
+	.align	WS
+.LLEFDE2:
+#endif
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/sparc/v9.S b/third_party/gofrontend/libffi/src/sparc/v9.S
new file mode 100644
index 0000000..2c97673
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sparc/v9.S
@@ -0,0 +1,305 @@
+/* -----------------------------------------------------------------------
+   v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
+
+   SPARC 64-bit Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+#ifdef SPARC64
+
+#define STACKFRAME 176		/* Minimum stack framesize for SPARC 64-bit */
+#define STACK_BIAS 2047
+#define ARGS (128)		/* Offset of register area in frame */
+
+.text
+        .align 8
+.globl ffi_call_v9
+.globl _ffi_call_v9
+
+ffi_call_v9:
+_ffi_call_v9:
+.LLFB1:
+	save	%sp, -STACKFRAME, %sp
+.LLCFI0:
+	
+	sub	%sp, %i2, %sp	! alloca() space in stack for frame to set up
+	add	%sp, STACKFRAME+STACK_BIAS, %l0	! %l0 has start of 
+						! frame to set up
+
+	mov	%l0, %o0	! call routine to set up frame
+	call	%i0
+	 mov	%i1, %o1	! (delay)
+	brz,pt	%o0, 1f
+	 ldx	[%l0+ARGS], %o0	! call foreign function
+
+	ldd	[%l0+ARGS], %f0
+	ldd	[%l0+ARGS+8], %f2
+	ldd	[%l0+ARGS+16], %f4
+	ldd	[%l0+ARGS+24], %f6
+	ldd	[%l0+ARGS+32], %f8
+	ldd	[%l0+ARGS+40], %f10
+	ldd	[%l0+ARGS+48], %f12
+	ldd	[%l0+ARGS+56], %f14
+	ldd	[%l0+ARGS+64], %f16
+	ldd	[%l0+ARGS+72], %f18
+	ldd	[%l0+ARGS+80], %f20
+	ldd	[%l0+ARGS+88], %f22
+	ldd	[%l0+ARGS+96], %f24
+	ldd	[%l0+ARGS+104], %f26
+	ldd	[%l0+ARGS+112], %f28
+	ldd	[%l0+ARGS+120], %f30
+
+1:	ldx	[%l0+ARGS+8], %o1
+	ldx	[%l0+ARGS+16], %o2
+	ldx	[%l0+ARGS+24], %o3
+	ldx	[%l0+ARGS+32], %o4
+	ldx	[%l0+ARGS+40], %o5
+	call	%i5
+	 sub	%l0, STACK_BIAS, %sp	! (delay) switch to frame
+
+	! If the return value pointer is NULL, assume no return value.
+	brz,pn	%i4, done
+	 nop
+
+	cmp	%i3, FFI_TYPE_INT
+	be,a,pt	%icc, done
+	 stx	%o0, [%i4+0]	! (delay)
+
+	cmp	%i3, FFI_TYPE_FLOAT
+	be,a,pn	%icc, done
+	 st	%f0, [%i4+0]	! (delay)
+
+	cmp	%i3, FFI_TYPE_DOUBLE
+	be,a,pn	%icc, done
+	 std	%f0, [%i4+0]	! (delay)
+
+	cmp	%i3, FFI_TYPE_STRUCT
+	be,pn	%icc, dostruct
+
+	cmp	%i3, FFI_TYPE_LONGDOUBLE
+	bne,pt	%icc, done
+	 nop
+	std	%f0, [%i4+0]
+	std	%f2, [%i4+8]
+
+done:	ret
+	 restore
+
+dostruct:
+	/* This will not work correctly for unions. */
+	stx	%o0, [%i4+0]
+	stx	%o1, [%i4+8]
+	stx	%o2, [%i4+16]
+	stx	%o3, [%i4+24]
+	std	%f0, [%i4+32]
+	std	%f2, [%i4+40]
+	std	%f4, [%i4+48]
+	std	%f6, [%i4+56]
+	ret
+	 restore
+.LLFE1:
+
+.ffi_call_v9_end:
+	.size	ffi_call_v9,.ffi_call_v9_end-ffi_call_v9
+
+
+#undef STACKFRAME
+#define	STACKFRAME	 336	/* 16*8 register window +
+				   6*8 args backing store +
+				   20*8 locals */
+#define	FP		%fp+STACK_BIAS
+
+/* ffi_closure_v9(...)
+
+   Receives the closure argument in %g1.   */
+
+	.text
+	.align 8
+	.globl ffi_closure_v9
+
+ffi_closure_v9:
+.LLFB2:
+	save	%sp, -STACKFRAME, %sp
+.LLCFI1:
+
+	! Store all of the potential argument registers in va_list format.
+	stx	%i0, [FP+128+0]
+	stx	%i1, [FP+128+8]
+	stx	%i2, [FP+128+16]
+	stx	%i3, [FP+128+24]
+	stx	%i4, [FP+128+32]
+	stx	%i5, [FP+128+40]
+
+	! Store possible floating point argument registers too.
+	std	%f0,  [FP-128]
+	std	%f2,  [FP-120]
+	std	%f4,  [FP-112]
+	std	%f6,  [FP-104]
+	std	%f8,  [FP-96]
+	std	%f10, [FP-88]
+	std     %f12, [FP-80]
+	std     %f14, [FP-72]
+	std     %f16, [FP-64]
+	std     %f18, [FP-56]
+	std     %f20, [FP-48]
+	std     %f22, [FP-40]
+	std     %f24, [FP-32]
+	std     %f26, [FP-24]
+	std     %f28, [FP-16]
+	std     %f30, [FP-8]
+
+	! Call ffi_closure_sparc_inner to do the bulk of the work.
+	mov	%g1, %o0
+	add	%fp, STACK_BIAS-160, %o1
+	add	%fp, STACK_BIAS+128, %o2
+	call	ffi_closure_sparc_inner_v9
+	 add	%fp, STACK_BIAS-128, %o3
+
+	! Load up the return value in the proper type.
+	! See ffi_prep_cif_machdep for the list of cases.
+	cmp	%o0, FFI_TYPE_VOID
+	be,pn	%icc, done1
+
+	cmp	%o0, FFI_TYPE_INT
+	be,pn	%icc, integer
+
+	cmp	%o0, FFI_TYPE_FLOAT
+	be,a,pn	%icc, done1
+	 ld	[FP-160], %f0
+
+	cmp	%o0, FFI_TYPE_DOUBLE
+	be,a,pn	%icc, done1
+	 ldd	[FP-160], %f0
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	cmp	%o0, FFI_TYPE_LONGDOUBLE
+	be,a,pn	%icc, longdouble1
+	 ldd	[FP-160], %f0
+#endif
+
+	! FFI_TYPE_STRUCT
+	ldx	[FP-152], %i1
+	ldx	[FP-144], %i2
+	ldx	[FP-136], %i3
+	ldd	[FP-160], %f0
+	ldd	[FP-152], %f2
+	ldd	[FP-144], %f4
+	ldd	[FP-136], %f6
+
+integer:
+	ldx	[FP-160], %i0
+
+done1:
+	ret
+	 restore
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+longdouble1:
+	ldd	[FP-152], %f2
+	ret
+	 restore
+#endif
+.LLFE2:
+
+.ffi_closure_v9_end:
+	.size	ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9
+
+#ifdef HAVE_RO_EH_FRAME
+	.section	".eh_frame",#alloc
+#else
+	.section	".eh_frame",#alloc,#write
+#endif
+.LLframe1:
+	.uaword	.LLECIE1-.LLSCIE1	! Length of Common Information Entry
+.LLSCIE1:
+	.uaword	0x0	! CIE Identifier Tag
+	.byte	0x1	! CIE Version
+	.ascii "zR\0"	! CIE Augmentation
+	.byte	0x1	! uleb128 0x1; CIE Code Alignment Factor
+	.byte	0x78	! sleb128 -8; CIE Data Alignment Factor
+	.byte	0xf	! CIE RA Column
+	.byte	0x1	! uleb128 0x1; Augmentation size
+#ifdef HAVE_AS_SPARC_UA_PCREL
+	.byte	0x1b	! FDE Encoding (pcrel sdata4)
+#else
+	.byte	0x50	! FDE Encoding (aligned absolute)
+#endif
+	.byte	0xc	! DW_CFA_def_cfa
+	.byte	0xe	! uleb128 0xe
+	.byte	0xff,0xf	! uleb128 0x7ff
+	.align 8
+.LLECIE1:
+.LLSFDE1:
+	.uaword	.LLEFDE1-.LLASFDE1	! FDE Length
+.LLASFDE1:
+	.uaword	.LLASFDE1-.LLframe1	! FDE CIE offset
+#ifdef HAVE_AS_SPARC_UA_PCREL
+	.uaword	%r_disp32(.LLFB1)
+	.uaword	.LLFE1-.LLFB1		! FDE address range
+#else
+	.align 8
+	.xword	.LLFB1
+	.uaxword	.LLFE1-.LLFB1	! FDE address range
+#endif
+	.byte	0x0	! uleb128 0x0; Augmentation size
+	.byte	0x4	! DW_CFA_advance_loc4
+	.uaword	.LLCFI0-.LLFB1
+	.byte	0xd	! DW_CFA_def_cfa_register
+	.byte	0x1e	! uleb128 0x1e
+	.byte	0x2d	! DW_CFA_GNU_window_save
+	.byte	0x9	! DW_CFA_register
+	.byte	0xf	! uleb128 0xf
+	.byte	0x1f	! uleb128 0x1f
+	.align 8
+.LLEFDE1:
+.LLSFDE2:
+	.uaword	.LLEFDE2-.LLASFDE2	! FDE Length
+.LLASFDE2:
+	.uaword	.LLASFDE2-.LLframe1	! FDE CIE offset
+#ifdef HAVE_AS_SPARC_UA_PCREL
+	.uaword	%r_disp32(.LLFB2)
+	.uaword	.LLFE2-.LLFB2		! FDE address range
+#else
+	.align 8
+	.xword	.LLFB2
+	.uaxword	.LLFE2-.LLFB2	! FDE address range
+#endif
+	.byte	0x0	! uleb128 0x0; Augmentation size
+	.byte	0x4	! DW_CFA_advance_loc4
+	.uaword	.LLCFI1-.LLFB2
+	.byte	0xd	! DW_CFA_def_cfa_register
+	.byte	0x1e	! uleb128 0x1e
+	.byte	0x2d	! DW_CFA_GNU_window_save
+	.byte	0x9	! DW_CFA_register
+	.byte	0xf	! uleb128 0xf
+	.byte	0x1f	! uleb128 0x1f
+	.align 8
+.LLEFDE2:
+#endif
+
+#ifdef __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/tile/ffi.c b/third_party/gofrontend/libffi/src/tile/ffi.c
new file mode 100644
index 0000000..3a94469
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/tile/ffi.c
@@ -0,0 +1,355 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2012 Tilera Corp.
+
+   TILE Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <arch/abi.h>
+#include <arch/icache.h>
+#include <arch/opcode.h>
+
+
+/* The first 10 registers are used to pass arguments and return values. */
+#define NUM_ARG_REGS 10
+
+/* Performs a raw function call with the given NUM_ARG_REGS register arguments
+   and the specified additional stack arguments (if any). */
+extern void ffi_call_tile(ffi_sarg reg_args[NUM_ARG_REGS],
+                          const ffi_sarg *stack_args,
+                          size_t stack_args_bytes,
+                          void (*fnaddr)(void))
+  FFI_HIDDEN;
+
+/* This handles the raw call from the closure stub, cleaning up the
+   parameters and delegating to ffi_closure_tile_inner. */
+extern void ffi_closure_tile(void) FFI_HIDDEN;
+
+
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* We always allocate room for all registers. Even if we don't
+     use them as parameters, they get returned in the same array
+     as struct return values so we need to make room. */
+  if (cif->bytes < NUM_ARG_REGS * FFI_SIZEOF_ARG)
+    cif->bytes = NUM_ARG_REGS * FFI_SIZEOF_ARG;
+
+  if (cif->rtype->size > NUM_ARG_REGS * FFI_SIZEOF_ARG)
+    cif->flags = FFI_TYPE_STRUCT;
+  else
+    cif->flags = FFI_TYPE_INT;
+
+  /* Nothing to do. */
+  return FFI_OK;
+}
+
+
+static long
+assign_to_ffi_arg(ffi_sarg *out, void *in, const ffi_type *type,
+                  int write_to_reg)
+{
+  switch (type->type)
+    {
+    case FFI_TYPE_SINT8:
+      *out = *(SINT8 *)in;
+      return 1;
+
+    case FFI_TYPE_UINT8:
+      *out = *(UINT8 *)in;
+      return 1;
+
+    case FFI_TYPE_SINT16:
+      *out = *(SINT16 *)in;
+      return 1;
+
+    case FFI_TYPE_UINT16:
+      *out = *(UINT16 *)in;
+      return 1;
+
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+#ifndef __LP64__
+    case FFI_TYPE_POINTER:
+#endif
+      /* Note that even unsigned 32-bit quantities are sign extended
+         on tilegx when stored in a register.  */
+      *out = *(SINT32 *)in;
+      return 1;
+
+    case FFI_TYPE_FLOAT:
+#ifdef __tilegx__
+      if (write_to_reg)
+        {
+          /* Properly sign extend the value.  */
+          union { float f; SINT32 s32; } val;
+          val.f = *(float *)in;
+          *out = val.s32;
+        }
+      else
+#endif
+        {
+          *(float *)out = *(float *)in;
+        }
+      return 1;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_DOUBLE:
+#ifdef __LP64__
+    case FFI_TYPE_POINTER:
+#endif
+      *(UINT64 *)out = *(UINT64 *)in;
+      return sizeof(UINT64) / FFI_SIZEOF_ARG;
+
+    case FFI_TYPE_STRUCT:
+      memcpy(out, in, type->size);
+      return (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
+
+    case FFI_TYPE_VOID:
+      /* Must be a return type. Nothing to do. */
+      return 0;
+
+    default:
+      FFI_ASSERT(0);
+      return -1;
+    }
+}
+
+
+void
+ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  ffi_sarg * const arg_mem = alloca(cif->bytes);
+  ffi_sarg * const reg_args = arg_mem;
+  ffi_sarg * const stack_args = &reg_args[NUM_ARG_REGS];
+  ffi_sarg *argp = arg_mem;
+  ffi_type ** const arg_types = cif->arg_types;
+  const long num_args = cif->nargs;
+  long i;
+
+  if (cif->flags == FFI_TYPE_STRUCT)
+    {
+      /* Pass a hidden pointer to the return value. We make sure there
+         is scratch space for the callee to store the return value even if
+         our caller doesn't care about it. */
+      *argp++ = (intptr_t)(rvalue ? rvalue : alloca(cif->rtype->size));
+
+      /* No more work needed to return anything. */
+      rvalue = NULL;
+    }
+
+  for (i = 0; i < num_args; i++)
+    {
+      ffi_type *type = arg_types[i];
+      void * const arg_in = avalue[i];
+      ptrdiff_t arg_word = argp - arg_mem;
+
+#ifndef __tilegx__
+      /* Doubleword-aligned values are always in an even-number register
+         pair, or doubleword-aligned stack slot if out of registers. */
+      long align = arg_word & (type->alignment > FFI_SIZEOF_ARG);
+      argp += align;
+      arg_word += align;
+#endif
+
+      if (type->type == FFI_TYPE_STRUCT)
+        {
+          const size_t arg_size_in_words =
+            (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
+
+          if (arg_word < NUM_ARG_REGS &&
+              arg_word + arg_size_in_words > NUM_ARG_REGS)
+            {
+              /* Args are not allowed to span registers and the stack. */
+              argp = stack_args;
+            }
+
+          memcpy(argp, arg_in, type->size);
+          argp += arg_size_in_words;
+        }
+      else
+        {
+          argp += assign_to_ffi_arg(argp, arg_in, arg_types[i], 1);
+        }
+    }
+
+  /* Actually do the call. */
+  ffi_call_tile(reg_args, stack_args,
+                cif->bytes - (NUM_ARG_REGS * FFI_SIZEOF_ARG), fn);
+
+  if (rvalue != NULL)
+    assign_to_ffi_arg(rvalue, reg_args, cif->rtype, 0);
+}
+
+
+/* Template code for closure. */
+extern const UINT64 ffi_template_tramp_tile[] FFI_HIDDEN;
+
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure *closure,
+                      ffi_cif *cif,
+                      void (*fun)(ffi_cif*, void*, void**, void*),
+                      void *user_data,
+                      void *codeloc)
+{
+#ifdef __tilegx__
+  /* TILE-Gx */
+  SINT64 c;
+  SINT64 h;
+  int s;
+  UINT64 *out;
+
+  if (cif->abi != FFI_UNIX)
+    return FFI_BAD_ABI;
+
+  out = (UINT64 *)closure->tramp;
+
+  c = (intptr_t)closure;
+  h = (intptr_t)ffi_closure_tile;
+  s = 0;
+
+  /* Find the smallest shift count that doesn't lose information
+     (i.e. no need to explicitly insert high bits of the address that
+     are just the sign extension of the low bits). */
+  while ((c >> s) != (SINT16)(c >> s) || (h >> s) != (SINT16)(h >> s))
+    s += 16;
+
+#define OPS(a, b, shift) \
+  (create_Imm16_X0((a) >> (shift)) | create_Imm16_X1((b) >> (shift)))
+
+  /* Emit the moveli. */
+  *out++ = ffi_template_tramp_tile[0] | OPS(c, h, s);
+  for (s -= 16; s >= 0; s -= 16)
+    *out++ = ffi_template_tramp_tile[1] | OPS(c, h, s);
+
+#undef OPS
+
+  *out++ = ffi_template_tramp_tile[2];
+
+#else
+  /* TILEPro */
+  UINT64 *out;
+  intptr_t delta;
+
+  if (cif->abi != FFI_UNIX)
+    return FFI_BAD_ABI;
+
+  out = (UINT64 *)closure->tramp;
+  delta = (intptr_t)ffi_closure_tile - (intptr_t)codeloc;
+
+  *out++ = ffi_template_tramp_tile[0] | create_JOffLong_X1(delta >> 3);
+#endif
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  invalidate_icache(closure->tramp, (char *)out - closure->tramp,
+                    getpagesize());
+
+  return FFI_OK;
+}
+
+
+/* This is called by the assembly wrapper for closures. This does
+   all of the work. On entry reg_args[0] holds the values the registers
+   had when the closure was invoked. On return reg_args[1] holds the register
+   values to be returned to the caller (many of which may be garbage). */
+void FFI_HIDDEN
+ffi_closure_tile_inner(ffi_closure *closure,
+                       ffi_sarg reg_args[2][NUM_ARG_REGS],
+                       ffi_sarg *stack_args)
+{
+  ffi_cif * const cif = closure->cif;
+  void ** const avalue = alloca(cif->nargs * sizeof(void *));
+  void *rvalue;
+  ffi_type ** const arg_types = cif->arg_types;
+  ffi_sarg * const reg_args_in = reg_args[0];
+  ffi_sarg * const reg_args_out = reg_args[1];
+  ffi_sarg * argp;
+  long i, arg_word, nargs = cif->nargs;
+  /* Use a union to guarantee proper alignment for double. */
+  union { ffi_sarg arg[NUM_ARG_REGS]; double d; UINT64 u64; } closure_ret;
+
+  /* Start out reading register arguments. */
+  argp = reg_args_in;
+
+  /* Copy the caller's structure return address to that the closure
+     returns the data directly to the caller.  */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    {
+      /* Return by reference via hidden pointer. */
+      rvalue = (void *)(intptr_t)*argp++;
+      arg_word = 1;
+    }
+  else
+    {
+      /* Return the value in registers. */
+      rvalue = &closure_ret;
+      arg_word = 0;
+    }
+
+  /* Grab the addresses of the arguments. */
+  for (i = 0; i < nargs; i++)
+    {
+      ffi_type * const type = arg_types[i];
+      const size_t arg_size_in_words =
+        (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
+
+#ifndef __tilegx__
+      /* Doubleword-aligned values are always in an even-number register
+         pair, or doubleword-aligned stack slot if out of registers. */
+      long align = arg_word & (type->alignment > FFI_SIZEOF_ARG);
+      argp += align;
+      arg_word += align;
+#endif
+
+      if (arg_word == NUM_ARG_REGS ||
+          (arg_word < NUM_ARG_REGS &&
+           arg_word + arg_size_in_words > NUM_ARG_REGS))
+        {
+          /* Switch to reading arguments from the stack. */
+          argp = stack_args;
+          arg_word = NUM_ARG_REGS;
+        }
+
+      avalue[i] = argp;
+      argp += arg_size_in_words;
+      arg_word += arg_size_in_words;
+    }
+
+  /* Invoke the closure.  */
+  closure->fun(cif, rvalue, avalue, closure->user_data);
+
+  if (cif->flags != FFI_TYPE_STRUCT)
+    {
+      /* Canonicalize for register representation. */
+      assign_to_ffi_arg(reg_args_out, &closure_ret, cif->rtype, 1);
+    }
+}
diff --git a/third_party/gofrontend/libffi/src/tile/ffitarget.h b/third_party/gofrontend/libffi/src/tile/ffitarget.h
new file mode 100644
index 0000000..679fb5d
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/tile/ffitarget.h
@@ -0,0 +1,65 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012 Tilera Corp.
+   Target configuration macros for TILE.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+
+#include <arch/abi.h>
+
+typedef uint_reg_t ffi_arg;
+typedef int_reg_t  ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_UNIX,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_UNIX
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+#define FFI_CLOSURES 1
+
+#ifdef __tilegx__
+/* We always pass 8-byte values, even in -m32 mode. */
+# define FFI_SIZEOF_ARG 8
+# ifdef __LP64__
+#  define FFI_TRAMPOLINE_SIZE (8 * 5)  /* 5 bundles */
+# else
+#  define FFI_TRAMPOLINE_SIZE (8 * 3)  /* 3 bundles */
+# endif
+#else
+# define FFI_SIZEOF_ARG 4
+# define FFI_TRAMPOLINE_SIZE 8 /* 1 bundle */
+#endif
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/tile/tile.S b/third_party/gofrontend/libffi/src/tile/tile.S
new file mode 100644
index 0000000..a186e1f
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/tile/tile.S
@@ -0,0 +1,360 @@
+/* -----------------------------------------------------------------------
+   tile.S - Copyright (c) 2011 Tilera Corp.
+
+   Tilera TILEPro and TILE-Gx Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+/* Number of bytes in a register. */
+#define REG_SIZE FFI_SIZEOF_ARG
+
+/* Number of bytes in stack linkage area for backtracing.
+
+   A note about the ABI: on entry to a procedure, sp points to a stack
+   slot where it must spill the return address if it's not a leaf.
+   REG_SIZE bytes beyond that is a slot owned by the caller which
+   contains the sp value that the caller had when it was originally
+   entered (i.e. the caller's frame pointer). */
+#define LINKAGE_SIZE (2 * REG_SIZE)
+
+/* The first 10 registers are used to pass arguments and return values. */
+#define NUM_ARG_REGS 10
+
+#ifdef __tilegx__
+#define SW st
+#define LW ld
+#define BGZT bgtzt
+#else
+#define SW sw
+#define LW lw
+#define BGZT bgzt
+#endif
+
+
+/* void ffi_call_tile (int_reg_t reg_args[NUM_ARG_REGS],
+                       const int_reg_t *stack_args,
+                       unsigned long stack_args_bytes,
+                       void (*fnaddr)(void));
+
+        On entry, REG_ARGS contain the outgoing register values,
+        and STACK_ARGS containts STACK_ARG_BYTES of additional values
+        to be passed on the stack. If STACK_ARG_BYTES is zero, then
+        STACK_ARGS is ignored.
+
+        When the invoked function returns, the values of r0-r9 are
+        blindly stored back into REG_ARGS for the caller to examine. */
+
+        .section .text.ffi_call_tile, "ax", @progbits
+        .align  8
+        .globl  ffi_call_tile
+        FFI_HIDDEN(ffi_call_tile)
+ffi_call_tile:
+
+/* Incoming arguments. */
+#define REG_ARGS                r0
+#define INCOMING_STACK_ARGS     r1
+#define STACK_ARG_BYTES         r2
+#define ORIG_FNADDR             r3
+
+/* Temporary values. */
+#define FRAME_SIZE              r10
+#define TMP                     r11
+#define TMP2                    r12
+#define OUTGOING_STACK_ARGS     r13
+#define REG_ADDR_PTR            r14
+#define RETURN_REG_ADDR         r15
+#define FNADDR                  r16
+
+        .cfi_startproc
+        {
+         /* Save return address. */
+         SW     sp, lr
+         .cfi_offset lr, 0
+         /* Prepare to spill incoming r52. */
+         addi   TMP, sp, -REG_SIZE
+         /* Increase frame size to have room to spill r52 and REG_ARGS.
+            The +7 is to round up mod 8. */
+         addi   FRAME_SIZE, STACK_ARG_BYTES, \
+                REG_SIZE + REG_SIZE + LINKAGE_SIZE + 7
+        }
+        {
+         /* Round stack frame size to a multiple of 8 to satisfy ABI. */
+         andi   FRAME_SIZE, FRAME_SIZE, -8
+         /* Compute where to spill REG_ARGS value. */
+         addi   TMP2, sp, -(REG_SIZE * 2)
+        }
+        {
+         /* Spill incoming r52. */
+         SW     TMP, r52
+         .cfi_offset r52, -REG_SIZE
+         /* Set up our frame pointer. */
+         move   r52, sp
+         .cfi_def_cfa_register r52
+         /* Push stack frame. */
+         sub    sp, sp, FRAME_SIZE
+        }
+        {
+         /* Prepare to set up stack linkage. */
+         addi   TMP, sp, REG_SIZE
+         /* Prepare to memcpy stack args. */
+         addi   OUTGOING_STACK_ARGS, sp, LINKAGE_SIZE
+         /* Save REG_ARGS which we will need after we call the subroutine. */
+         SW     TMP2, REG_ARGS
+        }
+        {
+         /* Set up linkage info to hold incoming stack pointer. */
+         SW     TMP, r52
+        }
+        {
+         /* Skip stack args memcpy if we don't have any stack args (common). */
+         blezt  STACK_ARG_BYTES, .Ldone_stack_args_memcpy
+        }
+
+.Lmemcpy_stack_args:
+        {
+         /* Load incoming argument from stack_args. */
+         LW     TMP, INCOMING_STACK_ARGS
+         addi   INCOMING_STACK_ARGS, INCOMING_STACK_ARGS, REG_SIZE
+        }
+        {
+         /* Store stack argument into outgoing stack argument area. */
+         SW     OUTGOING_STACK_ARGS, TMP
+         addi   OUTGOING_STACK_ARGS, OUTGOING_STACK_ARGS, REG_SIZE
+         addi   STACK_ARG_BYTES, STACK_ARG_BYTES, -REG_SIZE
+        }
+        {
+         BGZT   STACK_ARG_BYTES, .Lmemcpy_stack_args
+        }
+.Ldone_stack_args_memcpy:
+
+        {
+         /* Copy aside ORIG_FNADDR so we can overwrite its register. */
+         move   FNADDR, ORIG_FNADDR
+         /* Prepare to load argument registers. */
+         addi   REG_ADDR_PTR, r0, REG_SIZE
+         /* Load outgoing r0. */
+         LW     r0, r0
+        }
+
+        /* Load up argument registers from the REG_ARGS array. */
+#define LOAD_REG(REG, PTR) \
+        { \
+         LW     REG, PTR ; \
+         addi   PTR, PTR, REG_SIZE \
+        }
+
+        LOAD_REG(r1, REG_ADDR_PTR)
+        LOAD_REG(r2, REG_ADDR_PTR)
+        LOAD_REG(r3, REG_ADDR_PTR)
+        LOAD_REG(r4, REG_ADDR_PTR)
+        LOAD_REG(r5, REG_ADDR_PTR)
+        LOAD_REG(r6, REG_ADDR_PTR)
+        LOAD_REG(r7, REG_ADDR_PTR)
+        LOAD_REG(r8, REG_ADDR_PTR)
+        LOAD_REG(r9, REG_ADDR_PTR)
+
+        {
+         /* Call the subroutine. */
+         jalr   FNADDR
+        }
+
+        {
+         /* Restore original lr. */
+         LW     lr, r52
+         /* Prepare to recover ARGS, which we spilled earlier. */
+         addi   TMP, r52, -(2 * REG_SIZE)
+        }
+        {
+         /* Restore ARGS, so we can fill it in with the return regs r0-r9. */
+         LW     RETURN_REG_ADDR, TMP
+         /* Prepare to restore original r52. */
+         addi   TMP, r52, -REG_SIZE
+        }
+
+        {
+         /* Pop stack frame. */
+         move   sp, r52
+         /* Restore original r52. */
+         LW     r52, TMP
+        }
+
+#define STORE_REG(REG, PTR) \
+        { \
+         SW     PTR, REG ; \
+         addi   PTR, PTR, REG_SIZE \
+        }
+
+        /* Return all register values by reference. */
+        STORE_REG(r0, RETURN_REG_ADDR)
+        STORE_REG(r1, RETURN_REG_ADDR)
+        STORE_REG(r2, RETURN_REG_ADDR)
+        STORE_REG(r3, RETURN_REG_ADDR)
+        STORE_REG(r4, RETURN_REG_ADDR)
+        STORE_REG(r5, RETURN_REG_ADDR)
+        STORE_REG(r6, RETURN_REG_ADDR)
+        STORE_REG(r7, RETURN_REG_ADDR)
+        STORE_REG(r8, RETURN_REG_ADDR)
+        STORE_REG(r9, RETURN_REG_ADDR)
+
+        {
+         jrp    lr
+        }
+
+        .cfi_endproc
+        .size ffi_call_tile, .-ffi_call_tile
+
+/* ffi_closure_tile(...)
+
+   On entry, lr points to the closure plus 8 bytes, and r10
+   contains the actual return address.
+
+   This function simply dumps all register parameters into a stack array
+   and passes the closure, the registers array, and the stack arguments
+   to C code that does all of the actual closure processing. */
+
+        .section .text.ffi_closure_tile, "ax", @progbits
+        .align  8
+        .globl  ffi_closure_tile
+        FFI_HIDDEN(ffi_closure_tile)
+
+        .cfi_startproc
+/* Room to spill all NUM_ARG_REGS incoming registers, plus frame linkage. */
+#define CLOSURE_FRAME_SIZE (((NUM_ARG_REGS * REG_SIZE * 2 + LINKAGE_SIZE) + 7) & -8)
+ffi_closure_tile:
+        {
+#ifdef __tilegx__
+         st     sp, lr
+         .cfi_offset lr, 0
+#else
+         /* Save return address (in r10 due to closure stub wrapper). */
+         SW     sp, r10
+         .cfi_return_column r10
+         .cfi_offset r10, 0
+#endif
+         /* Compute address for stack frame linkage. */
+         addli   r10, sp, -(CLOSURE_FRAME_SIZE - REG_SIZE)
+        }
+        {
+         /* Save incoming stack pointer in linkage area. */
+         SW     r10, sp
+         .cfi_offset sp, -(CLOSURE_FRAME_SIZE - REG_SIZE)
+         /* Push a new stack frame. */
+         addli   sp, sp, -CLOSURE_FRAME_SIZE
+         .cfi_adjust_cfa_offset CLOSURE_FRAME_SIZE
+        }
+
+        {
+         /* Create pointer to where to start spilling registers. */
+         addi   r10, sp, LINKAGE_SIZE
+        }
+
+        /* Spill all the incoming registers. */
+        STORE_REG(r0, r10)
+        STORE_REG(r1, r10)
+        STORE_REG(r2, r10)
+        STORE_REG(r3, r10)
+        STORE_REG(r4, r10)
+        STORE_REG(r5, r10)
+        STORE_REG(r6, r10)
+        STORE_REG(r7, r10)
+        STORE_REG(r8, r10)
+        {
+         /* Save r9. */
+         SW     r10, r9
+#ifdef __tilegx__
+         /* Pointer to closure is passed in r11. */
+         move  r0, r11
+#else
+         /* Compute pointer to the closure object. Because the closure
+            starts with a "jal ffi_closure_tile", we can just take the
+            value of lr (a phony return address pointing into the closure)
+            and subtract 8. */
+         addi   r0, lr, -8
+#endif
+         /* Compute a pointer to the register arguments we just spilled. */
+         addi   r1, sp, LINKAGE_SIZE
+        }
+        {
+         /* Compute a pointer to the extra stack arguments (if any). */
+         addli   r2, sp, CLOSURE_FRAME_SIZE + LINKAGE_SIZE
+         /* Call C code to deal with all of the grotty details. */
+         jal    ffi_closure_tile_inner
+        }
+        {
+         addli   r10, sp, CLOSURE_FRAME_SIZE
+        }
+        {
+         /* Restore the return address. */
+         LW     lr, r10
+         /* Compute pointer to registers array. */
+         addli   r10, sp, LINKAGE_SIZE + (NUM_ARG_REGS * REG_SIZE)
+        }
+        /* Return all the register values, which C code may have set. */
+        LOAD_REG(r0, r10)
+        LOAD_REG(r1, r10)
+        LOAD_REG(r2, r10)
+        LOAD_REG(r3, r10)
+        LOAD_REG(r4, r10)
+        LOAD_REG(r5, r10)
+        LOAD_REG(r6, r10)
+        LOAD_REG(r7, r10)
+        LOAD_REG(r8, r10)
+        LOAD_REG(r9, r10)
+        {
+         /* Pop the frame. */
+         addli   sp, sp, CLOSURE_FRAME_SIZE
+         jrp    lr
+        }
+
+        .cfi_endproc
+        .size   ffi_closure_tile, . - ffi_closure_tile
+
+
+/* What follows are code template instructions that get copied to the
+   closure trampoline by ffi_prep_closure_loc.  The zeroed operands
+   get replaced by their proper values at runtime. */
+
+        .section .text.ffi_template_tramp_tile, "ax", @progbits
+        .align  8
+        .globl  ffi_template_tramp_tile
+        FFI_HIDDEN(ffi_template_tramp_tile)
+ffi_template_tramp_tile:
+#ifdef __tilegx__
+        {
+          moveli r11, 0 /* backpatched to address of containing closure. */
+          moveli r10, 0 /* backpatched to ffi_closure_tile. */
+        }
+        /* Note: the following bundle gets generated multiple times
+           depending on the pointer value (esp. useful for -m32 mode). */
+        { shl16insli r11, r11, 0 ; shl16insli r10, r10, 0 }
+        { info 2+8 /* for backtracer: -> pc in lr, frame size 0 */ ; jr r10 }
+#else
+        /* 'jal .' yields a PC-relative offset of zero so we can OR in the
+           right offset at runtime. */
+        { move r10, lr ; jal . /* ffi_closure_tile */ }
+#endif
+
+        .size   ffi_template_tramp_tile, . - ffi_template_tramp_tile
diff --git a/third_party/gofrontend/libffi/src/types.c b/third_party/gofrontend/libffi/src/types.c
new file mode 100644
index 0000000..0de5994
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/types.c
@@ -0,0 +1,92 @@
+/* -----------------------------------------------------------------------
+   types.c - Copyright (c) 1996, 1998  Red Hat, Inc.
+   
+   Predefined ffi_types needed by libffi.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+/* Hide the basic type definitions from the header file, so that we
+   can redefine them here as "const".  */
+#define LIBFFI_HIDE_BASIC_TYPES
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+/* Type definitions */
+
+#define FFI_TYPEDEF(name, type, id)		\
+struct struct_align_##name {			\
+  char c;					\
+  type x;					\
+};						\
+const ffi_type ffi_type_##name = {		\
+  sizeof(type),					\
+  offsetof(struct struct_align_##name, x),	\
+  id, NULL					\
+}
+
+#define FFI_NONCONST_TYPEDEF(name, type, id)	\
+struct struct_align_##name {			\
+  char c;					\
+  type x;					\
+};						\
+ffi_type ffi_type_##name = {			\
+  sizeof(type),					\
+  offsetof(struct struct_align_##name, x),	\
+  id, NULL					\
+}
+
+/* Size and alignment are fake here. They must not be 0. */
+const ffi_type ffi_type_void = {
+  1, 1, FFI_TYPE_VOID, NULL
+};
+
+FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8);
+FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8);
+FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16);
+FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16);
+FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32);
+FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32);
+FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64);
+FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64);
+
+FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER);
+
+FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT);
+FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE);
+
+#ifdef __alpha__
+/* Even if we're not configured to default to 128-bit long double, 
+   maintain binary compatibility, as -mlong-double-128 can be used
+   at any time.  */
+/* Validate the hard-coded number below.  */
+# if defined(__LONG_DOUBLE_128__) && FFI_TYPE_LONGDOUBLE != 4
+#  error FFI_TYPE_LONGDOUBLE out of date
+# endif
+const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL };
+#elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+# if HAVE_LONG_DOUBLE_VARIANT
+FFI_NONCONST_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE);
+# else
+FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE);
+# endif
+#endif
diff --git a/third_party/gofrontend/libffi/src/x86/darwin.S b/third_party/gofrontend/libffi/src/x86/darwin.S
new file mode 100644
index 0000000..8f0f070
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/darwin.S
@@ -0,0 +1,444 @@
+/* -----------------------------------------------------------------------
+   darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005  Red Hat, Inc.
+	Copyright (C) 2008  Free Software Foundation, Inc.
+
+   X86 Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   -----------------------------------------------------------------------
+   */
+
+#ifndef __x86_64__
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+
+.globl _ffi_prep_args
+
+	.align 4
+.globl _ffi_call_SYSV
+
+_ffi_call_SYSV:
+.LFB1:
+        pushl %ebp
+.LCFI0:
+        movl  %esp,%ebp
+.LCFI1:
+        subl $8,%esp
+	/* Make room for all of the new args.  */
+	movl  16(%ebp),%ecx
+	subl  %ecx,%esp
+
+	movl  %esp,%eax
+
+	/* Place all of the ffi_prep_args in position  */
+	subl  $8,%esp
+	pushl 12(%ebp)
+	pushl %eax
+	call  *8(%ebp)
+
+	/* Return stack to previous state and call the function  */
+	addl  $16,%esp	
+
+	call  *28(%ebp)
+
+	/* Load %ecx with the return type code  */
+	movl  20(%ebp),%ecx	
+
+	/* Protect %esi.  We're going to pop it in the epilogue.  */
+	pushl %esi
+
+	/* If the return value pointer is NULL, assume no return value.  */
+	cmpl  $0,24(%ebp)
+	jne  0f
+
+	/* Even if there is no space for the return value, we are 
+	   obliged to handle floating-point values.  */
+	cmpl  $FFI_TYPE_FLOAT,%ecx
+	jne   noretval
+	fstp  %st(0)
+
+	jmp   epilogue
+0:
+	.align 4
+	call 1f
+.Lstore_table:
+	.long   noretval-.Lstore_table		/* FFI_TYPE_VOID */
+	.long   retint-.Lstore_table		/* FFI_TYPE_INT */
+	.long   retfloat-.Lstore_table		/* FFI_TYPE_FLOAT */
+	.long   retdouble-.Lstore_table		/* FFI_TYPE_DOUBLE */
+	.long   retlongdouble-.Lstore_table     /* FFI_TYPE_LONGDOUBLE */
+	.long   retuint8-.Lstore_table		/* FFI_TYPE_UINT8 */
+	.long   retsint8-.Lstore_table		/* FFI_TYPE_SINT8 */
+	.long   retuint16-.Lstore_table		/* FFI_TYPE_UINT16 */
+	.long   retsint16-.Lstore_table		/* FFI_TYPE_SINT16 */
+	.long   retint-.Lstore_table		/* FFI_TYPE_UINT32 */
+	.long   retint-.Lstore_table		/* FFI_TYPE_SINT32 */
+	.long   retint64-.Lstore_table		/* FFI_TYPE_UINT64 */
+	.long   retint64-.Lstore_table		/* FFI_TYPE_SINT64 */
+	.long   retstruct-.Lstore_table		/* FFI_TYPE_STRUCT */
+	.long   retint-.Lstore_table		/* FFI_TYPE_POINTER */
+	.long   retstruct1b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_1B */
+	.long   retstruct2b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_2B */
+1:
+	pop  %esi
+	add  (%esi, %ecx, 4), %esi
+	jmp  *%esi
+
+	/* Sign/zero extend as appropriate.  */
+retsint8:
+	movsbl  %al, %eax
+	jmp  retint
+
+retsint16:
+	movswl  %ax, %eax
+	jmp  retint
+
+retuint8:
+	movzbl  %al, %eax
+	jmp  retint
+
+retuint16:
+	movzwl  %ax, %eax
+	jmp  retint
+
+retfloat:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx
+	fstps (%ecx)
+	jmp   epilogue
+
+retdouble:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx
+	fstpl (%ecx)
+	jmp   epilogue
+
+retlongdouble:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx
+	fstpt (%ecx)
+	jmp   epilogue
+
+retint64:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx
+	movl  %eax,0(%ecx)
+	movl  %edx,4(%ecx)
+	jmp   epilogue
+
+retstruct1b:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx
+	movb  %al,0(%ecx)
+	jmp   epilogue
+
+retstruct2b:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx
+	movw  %ax,0(%ecx)
+	jmp   epilogue
+
+retint:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx
+	movl  %eax,0(%ecx)
+
+retstruct:
+	/* Nothing to do!  */
+
+noretval:
+epilogue:
+	popl %esi
+	movl %ebp,%esp
+	popl %ebp
+	ret
+
+.LFE1:
+.ffi_call_SYSV_end:
+
+	.align	4
+FFI_HIDDEN (ffi_closure_SYSV)
+.globl _ffi_closure_SYSV
+
+_ffi_closure_SYSV:
+.LFB2:
+	pushl	%ebp
+.LCFI2:
+	movl	%esp, %ebp
+.LCFI3:
+	subl	$40, %esp
+	leal	-24(%ebp), %edx
+	movl	%edx, -12(%ebp)	/* resp */
+	leal	8(%ebp), %edx
+	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
+	leal	-12(%ebp), %edx
+	movl	%edx, (%esp)	/* &resp */
+	movl	%ebx, 8(%esp)
+.LCFI7:
+	call	L_ffi_closure_SYSV_inner$stub
+	movl	8(%esp), %ebx
+	movl	-12(%ebp), %ecx
+	cmpl	$FFI_TYPE_INT, %eax
+	je	.Lcls_retint
+
+	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
+	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
+	cmpl	$FFI_TYPE_UINT64, %eax
+	jge	0f
+	cmpl	$FFI_TYPE_UINT8, %eax
+	jge	.Lcls_retint
+
+0:	cmpl	$FFI_TYPE_FLOAT, %eax
+	je	.Lcls_retfloat
+	cmpl	$FFI_TYPE_DOUBLE, %eax
+	je	.Lcls_retdouble
+	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
+	je	.Lcls_retldouble
+	cmpl	$FFI_TYPE_SINT64, %eax
+	je	.Lcls_retllong
+	cmpl	$FFI_TYPE_SMALL_STRUCT_1B, %eax
+	je	.Lcls_retstruct1b
+	cmpl	$FFI_TYPE_SMALL_STRUCT_2B, %eax
+	je	.Lcls_retstruct2b
+	cmpl	$FFI_TYPE_STRUCT, %eax
+	je	.Lcls_retstruct
+.Lcls_epilogue:
+	movl	%ebp, %esp
+	popl	%ebp
+	ret
+.Lcls_retint:
+	movl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+.Lcls_retfloat:
+	flds	(%ecx)
+	jmp	.Lcls_epilogue
+.Lcls_retdouble:
+	fldl	(%ecx)
+	jmp	.Lcls_epilogue
+.Lcls_retldouble:
+	fldt	(%ecx)
+	jmp	.Lcls_epilogue
+.Lcls_retllong:
+	movl	(%ecx), %eax
+	movl	4(%ecx), %edx
+	jmp	.Lcls_epilogue
+.Lcls_retstruct1b:
+	movsbl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+.Lcls_retstruct2b:
+	movswl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+.Lcls_retstruct:
+	lea -8(%ebp),%esp
+	movl	%ebp, %esp
+	popl	%ebp
+	ret $4
+.LFE2:
+
+#if !FFI_NO_RAW_API
+
+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
+#define CIF_FLAGS_OFFSET 20
+
+	.align	4
+FFI_HIDDEN (ffi_closure_raw_SYSV)
+.globl _ffi_closure_raw_SYSV
+
+_ffi_closure_raw_SYSV:
+.LFB3:
+	pushl	%ebp
+.LCFI4:
+	movl	%esp, %ebp
+.LCFI5:
+	pushl	%esi
+.LCFI6:
+	subl	$36, %esp
+	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
+	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
+	movl	%edx, 12(%esp)	/* user_data */
+	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
+	movl	%edx, 8(%esp)	/* raw_args */
+	leal	-24(%ebp), %edx
+	movl	%edx, 4(%esp)	/* &res */
+	movl	%esi, (%esp)	/* cif */
+	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
+	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
+	cmpl	$FFI_TYPE_INT, %eax
+	je	.Lrcls_retint
+
+	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
+	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
+	cmpl	$FFI_TYPE_UINT64, %eax
+	jge	0f
+	cmpl	$FFI_TYPE_UINT8, %eax
+	jge	.Lrcls_retint
+0:
+	cmpl	$FFI_TYPE_FLOAT, %eax
+	je	.Lrcls_retfloat
+	cmpl	$FFI_TYPE_DOUBLE, %eax
+	je	.Lrcls_retdouble
+	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
+	je	.Lrcls_retldouble
+	cmpl	$FFI_TYPE_SINT64, %eax
+	je	.Lrcls_retllong
+.Lrcls_epilogue:
+	addl	$36, %esp
+	popl	%esi
+	popl	%ebp
+	ret
+.Lrcls_retint:
+	movl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+.Lrcls_retfloat:
+	flds	-24(%ebp)
+	jmp	.Lrcls_epilogue
+.Lrcls_retdouble:
+	fldl	-24(%ebp)
+	jmp	.Lrcls_epilogue
+.Lrcls_retldouble:
+	fldt	-24(%ebp)
+	jmp	.Lrcls_epilogue
+.Lrcls_retllong:
+	movl	-24(%ebp), %eax
+	movl	-20(%ebp), %edx
+	jmp	.Lrcls_epilogue
+.LFE3:
+#endif
+
+.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
+L_ffi_closure_SYSV_inner$stub:
+	.indirect_symbol _ffi_closure_SYSV_inner
+	hlt ; hlt ; hlt ; hlt ; hlt
+
+
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+	.set	L$set$0,LECIE1-LSCIE1
+	.long	L$set$0
+LSCIE1:
+	.long	0x0
+	.byte	0x1
+	.ascii "zR\0"
+	.byte	0x1
+	.byte	0x7c
+	.byte	0x8
+	.byte	0x1
+	.byte	0x10
+	.byte	0xc
+	.byte	0x5
+	.byte	0x4
+	.byte	0x88
+	.byte	0x1
+	.align 2
+LECIE1:
+.globl _ffi_call_SYSV.eh
+_ffi_call_SYSV.eh:
+LSFDE1:
+	.set	L$set$1,LEFDE1-LASFDE1
+	.long	L$set$1
+LASFDE1:
+	.long	LASFDE1-EH_frame1
+	.long	.LFB1-.
+	.set L$set$2,.LFE1-.LFB1
+	.long L$set$2
+	.byte	0x0
+	.byte	0x4
+	.set L$set$3,.LCFI0-.LFB1
+	.long L$set$3
+	.byte	0xe
+	.byte	0x8
+	.byte	0x84
+	.byte	0x2
+	.byte	0x4
+	.set L$set$4,.LCFI1-.LCFI0
+	.long L$set$4
+	.byte	0xd
+	.byte	0x4
+	.align 2
+LEFDE1:
+.globl _ffi_closure_SYSV.eh
+_ffi_closure_SYSV.eh:
+LSFDE2:
+	.set	L$set$5,LEFDE2-LASFDE2
+	.long	L$set$5
+LASFDE2:
+	.long	LASFDE2-EH_frame1
+	.long	.LFB2-.
+	.set L$set$6,.LFE2-.LFB2
+	.long L$set$6
+	.byte	0x0
+	.byte	0x4
+	.set L$set$7,.LCFI2-.LFB2
+	.long L$set$7
+	.byte	0xe
+	.byte	0x8
+	.byte	0x84
+	.byte	0x2
+	.byte	0x4
+	.set L$set$8,.LCFI3-.LCFI2
+	.long L$set$8
+	.byte	0xd
+	.byte	0x4
+	.align 2
+LEFDE2:
+
+#if !FFI_NO_RAW_API
+
+.globl _ffi_closure_raw_SYSV.eh
+_ffi_closure_raw_SYSV.eh:
+LSFDE3:
+	.set	L$set$10,LEFDE3-LASFDE3
+	.long	L$set$10
+LASFDE3:
+	.long	LASFDE3-EH_frame1
+	.long	.LFB3-.
+	.set L$set$11,.LFE3-.LFB3
+	.long L$set$11
+	.byte	0x0
+	.byte	0x4
+	.set L$set$12,.LCFI4-.LFB3
+	.long L$set$12
+	.byte	0xe
+	.byte	0x8
+	.byte	0x84
+	.byte	0x2
+	.byte	0x4
+	.set L$set$13,.LCFI5-.LCFI4
+	.long L$set$13
+	.byte	0xd
+	.byte	0x4
+	.byte	0x4
+	.set L$set$14,.LCFI6-.LCFI5
+	.long L$set$14
+	.byte	0x85
+	.byte	0x3
+	.align 2
+LEFDE3:
+
+#endif
+
+#endif /* ifndef __x86_64__ */
diff --git a/third_party/gofrontend/libffi/src/x86/darwin64.S b/third_party/gofrontend/libffi/src/x86/darwin64.S
new file mode 100644
index 0000000..2f7394e
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/darwin64.S
@@ -0,0 +1,416 @@
+/* -----------------------------------------------------------------------
+   darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc.
+	        Copyright (c) 2008 Red Hat, Inc.
+   derived from unix64.S
+
+   x86-64 Foreign Function Interface for Darwin.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifdef __x86_64__
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+	.file "darwin64.S"
+.text
+
+/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
+		    void *raddr, void (*fnaddr)(void));
+
+   Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
+   for this function.  This has been allocated by ffi_call.  We also
+   deallocate some of the stack that has been alloca'd.  */
+
+	.align	3
+	.globl	_ffi_call_unix64
+
+_ffi_call_unix64:
+LUW0:
+	movq	(%rsp), %r10		/* Load return address.  */
+	leaq	(%rdi, %rsi), %rax	/* Find local stack base.  */
+	movq	%rdx, (%rax)		/* Save flags.  */
+	movq	%rcx, 8(%rax)		/* Save raddr.  */
+	movq	%rbp, 16(%rax)		/* Save old frame pointer.  */
+	movq	%r10, 24(%rax)		/* Relocate return address.  */
+	movq	%rax, %rbp		/* Finalize local stack frame.  */
+LUW1:
+	movq	%rdi, %r10		/* Save a copy of the register area. */
+	movq	%r8, %r11		/* Save a copy of the target fn.  */
+	movl	%r9d, %eax		/* Set number of SSE registers.  */
+
+	/* Load up all argument registers.  */
+	movq	(%r10), %rdi
+	movq	8(%r10), %rsi
+	movq	16(%r10), %rdx
+	movq	24(%r10), %rcx
+	movq	32(%r10), %r8
+	movq	40(%r10), %r9
+	testl	%eax, %eax
+	jnz	Lload_sse
+Lret_from_load_sse:
+
+	/* Deallocate the reg arg area.  */
+	leaq	176(%r10), %rsp
+
+	/* Call the user function.  */
+	call	*%r11
+
+	/* Deallocate stack arg area; local stack frame in redzone.  */
+	leaq	24(%rbp), %rsp
+
+	movq	0(%rbp), %rcx		/* Reload flags.  */
+	movq	8(%rbp), %rdi		/* Reload raddr.  */
+	movq	16(%rbp), %rbp		/* Reload old frame pointer.  */
+LUW2:
+
+	/* The first byte of the flags contains the FFI_TYPE.  */
+	movzbl	%cl, %r10d
+	leaq	Lstore_table(%rip), %r11
+	movslq	(%r11, %r10, 4), %r10
+	addq	%r11, %r10
+	jmp	*%r10
+
+Lstore_table:
+	.long	Lst_void-Lstore_table		/* FFI_TYPE_VOID */
+	.long	Lst_sint32-Lstore_table		/* FFI_TYPE_INT */
+	.long	Lst_float-Lstore_table		/* FFI_TYPE_FLOAT */
+	.long	Lst_double-Lstore_table		/* FFI_TYPE_DOUBLE */
+	.long	Lst_ldouble-Lstore_table	/* FFI_TYPE_LONGDOUBLE */
+	.long	Lst_uint8-Lstore_table		/* FFI_TYPE_UINT8 */
+	.long	Lst_sint8-Lstore_table		/* FFI_TYPE_SINT8 */
+	.long	Lst_uint16-Lstore_table		/* FFI_TYPE_UINT16 */
+	.long	Lst_sint16-Lstore_table		/* FFI_TYPE_SINT16 */
+	.long	Lst_uint32-Lstore_table		/* FFI_TYPE_UINT32 */
+	.long	Lst_sint32-Lstore_table		/* FFI_TYPE_SINT32 */
+	.long	Lst_int64-Lstore_table		/* FFI_TYPE_UINT64 */
+	.long	Lst_int64-Lstore_table		/* FFI_TYPE_SINT64 */
+	.long	Lst_struct-Lstore_table		/* FFI_TYPE_STRUCT */
+	.long	Lst_int64-Lstore_table		/* FFI_TYPE_POINTER */
+
+	.text
+	.align	3
+Lst_void:
+	ret
+	.align	3
+Lst_uint8:
+	movzbq	%al, %rax
+	movq	%rax, (%rdi)
+	ret
+	.align	3
+Lst_sint8:
+	movsbq	%al, %rax
+	movq	%rax, (%rdi)
+	ret
+	.align	3
+Lst_uint16:
+	movzwq	%ax, %rax
+	movq	%rax, (%rdi)
+	.align	3
+Lst_sint16:
+	movswq	%ax, %rax
+	movq	%rax, (%rdi)
+	ret
+	.align	3
+Lst_uint32:
+	movl	%eax, %eax
+	movq	%rax, (%rdi)
+	.align	3
+Lst_sint32:
+	cltq
+	movq	%rax, (%rdi)
+	ret
+	.align	3
+Lst_int64:
+	movq	%rax, (%rdi)
+	ret
+	.align	3
+Lst_float:
+	movss	%xmm0, (%rdi)
+	ret
+	.align	3
+Lst_double:
+	movsd	%xmm0, (%rdi)
+	ret
+Lst_ldouble:
+	fstpt	(%rdi)
+	ret
+	.align	3
+Lst_struct:
+	leaq	-20(%rsp), %rsi		/* Scratch area in redzone.  */
+
+	/* We have to locate the values now, and since we don't want to
+	   write too much data into the user's return value, we spill the
+	   value to a 16 byte scratch area first.  Bits 8, 9, and 10
+	   control where the values are located.  Only one of the three
+	   bits will be set; see ffi_prep_cif_machdep for the pattern.  */
+	movd	%xmm0, %r10
+	movd	%xmm1, %r11
+	testl	$0x100, %ecx
+	cmovnz	%rax, %rdx
+	cmovnz	%r10, %rax
+	testl	$0x200, %ecx
+	cmovnz	%r10, %rdx
+	testl	$0x400, %ecx
+	cmovnz	%r10, %rax
+	cmovnz	%r11, %rdx
+	movq	%rax, (%rsi)
+	movq	%rdx, 8(%rsi)
+
+	/* Bits 12-31 contain the true size of the structure.  Copy from
+	   the scratch area to the true destination.  */
+	shrl	$12, %ecx
+	rep movsb
+	ret
+
+	/* Many times we can avoid loading any SSE registers at all.
+	   It's not worth an indirect jump to load the exact set of
+	   SSE registers needed; zero or all is a good compromise.  */
+	.align	3
+LUW3:
+Lload_sse:
+	movdqa	48(%r10), %xmm0
+	movdqa	64(%r10), %xmm1
+	movdqa	80(%r10), %xmm2
+	movdqa	96(%r10), %xmm3
+	movdqa	112(%r10), %xmm4
+	movdqa	128(%r10), %xmm5
+	movdqa	144(%r10), %xmm6
+	movdqa	160(%r10), %xmm7
+	jmp	Lret_from_load_sse
+
+LUW4:
+	.align	3
+	.globl	_ffi_closure_unix64
+
+_ffi_closure_unix64:
+LUW5:
+	/* The carry flag is set by the trampoline iff SSE registers
+	   are used.  Don't clobber it before the branch instruction.  */
+	leaq    -200(%rsp), %rsp
+LUW6:
+	movq	%rdi, (%rsp)
+	movq    %rsi, 8(%rsp)
+	movq    %rdx, 16(%rsp)
+	movq    %rcx, 24(%rsp)
+	movq    %r8, 32(%rsp)
+	movq    %r9, 40(%rsp)
+	jc      Lsave_sse
+Lret_from_save_sse:
+
+	movq	%r10, %rdi
+	leaq	176(%rsp), %rsi
+	movq	%rsp, %rdx
+	leaq	208(%rsp), %rcx
+	call	_ffi_closure_unix64_inner
+
+	/* Deallocate stack frame early; return value is now in redzone.  */
+	addq	$200, %rsp
+LUW7:
+
+	/* The first byte of the return value contains the FFI_TYPE.  */
+	movzbl	%al, %r10d
+	leaq	Lload_table(%rip), %r11
+	movslq	(%r11, %r10, 4), %r10
+	addq	%r11, %r10
+	jmp	*%r10
+
+Lload_table:
+	.long	Lld_void-Lload_table		/* FFI_TYPE_VOID */
+	.long	Lld_int32-Lload_table		/* FFI_TYPE_INT */
+	.long	Lld_float-Lload_table		/* FFI_TYPE_FLOAT */
+	.long	Lld_double-Lload_table		/* FFI_TYPE_DOUBLE */
+	.long	Lld_ldouble-Lload_table		/* FFI_TYPE_LONGDOUBLE */
+	.long	Lld_int8-Lload_table		/* FFI_TYPE_UINT8 */
+	.long	Lld_int8-Lload_table		/* FFI_TYPE_SINT8 */
+	.long	Lld_int16-Lload_table		/* FFI_TYPE_UINT16 */
+	.long	Lld_int16-Lload_table		/* FFI_TYPE_SINT16 */
+	.long	Lld_int32-Lload_table		/* FFI_TYPE_UINT32 */
+	.long	Lld_int32-Lload_table		/* FFI_TYPE_SINT32 */
+	.long	Lld_int64-Lload_table		/* FFI_TYPE_UINT64 */
+	.long	Lld_int64-Lload_table		/* FFI_TYPE_SINT64 */
+	.long	Lld_struct-Lload_table		/* FFI_TYPE_STRUCT */
+	.long	Lld_int64-Lload_table		/* FFI_TYPE_POINTER */
+
+	.text
+	.align	3
+Lld_void:
+	ret
+	.align	3
+Lld_int8:
+	movzbl	-24(%rsp), %eax
+	ret
+	.align	3
+Lld_int16:
+	movzwl	-24(%rsp), %eax
+	ret
+	.align	3
+Lld_int32:
+	movl	-24(%rsp), %eax
+	ret
+	.align	3
+Lld_int64:
+	movq	-24(%rsp), %rax
+	ret
+	.align	3
+Lld_float:
+	movss	-24(%rsp), %xmm0
+	ret
+	.align	3
+Lld_double:
+	movsd	-24(%rsp), %xmm0
+	ret
+	.align	3
+Lld_ldouble:
+	fldt	-24(%rsp)
+	ret
+	.align	3
+Lld_struct:
+	/* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
+	   %rax/%xmm0, %xmm0/%xmm1.  We collapse two by always loading
+	   both rdx and xmm1 with the second word.  For the remaining,
+	   bit 8 set means xmm0 gets the second word, and bit 9 means
+	   that rax gets the second word.  */
+	movq	-24(%rsp), %rcx
+	movq	-16(%rsp), %rdx
+	movq	-16(%rsp), %xmm1
+	testl	$0x100, %eax
+	cmovnz	%rdx, %rcx
+	movd	%rcx, %xmm0
+	testl	$0x200, %eax
+	movq	-24(%rsp), %rax
+	cmovnz	%rdx, %rax
+	ret
+
+	/* See the comment above Lload_sse; the same logic applies here.  */
+	.align	3
+LUW8:
+Lsave_sse:
+	movdqa	%xmm0, 48(%rsp)
+	movdqa	%xmm1, 64(%rsp)
+	movdqa	%xmm2, 80(%rsp)
+	movdqa	%xmm3, 96(%rsp)
+	movdqa	%xmm4, 112(%rsp)
+	movdqa	%xmm5, 128(%rsp)
+	movdqa	%xmm6, 144(%rsp)
+	movdqa	%xmm7, 160(%rsp)
+	jmp	Lret_from_save_sse
+
+LUW9:
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+	.set	L$set$0,LECIE1-LSCIE1		/* CIE Length */
+	.long	L$set$0
+LSCIE1:
+	.long	0x0		/* CIE Identifier Tag */
+	.byte	0x1		/* CIE Version */
+	.ascii	"zR\0"		/* CIE Augmentation */
+	.byte	0x1		/* uleb128 0x1; CIE Code Alignment Factor */
+	.byte	0x78		/* sleb128 -8; CIE Data Alignment Factor */
+	.byte	0x10		/* CIE RA Column */
+	.byte	0x1		/* uleb128 0x1; Augmentation size */
+	.byte	0x10		/* FDE Encoding (pcrel sdata4) */
+	.byte	0xc		/* DW_CFA_def_cfa, %rsp offset 8 */
+	.byte	0x7		/* uleb128 0x7 */
+	.byte	0x8		/* uleb128 0x8 */
+	.byte	0x90		/* DW_CFA_offset, column 0x10 */
+	.byte	0x1
+	.align	3
+LECIE1:
+	.globl _ffi_call_unix64.eh
+_ffi_call_unix64.eh:
+LSFDE1:
+	.set	L$set$1,LEFDE1-LASFDE1	/* FDE Length */
+	.long	L$set$1
+LASFDE1:
+	.long	LASFDE1-EH_frame1	/* FDE CIE offset */
+	.quad	LUW0-.			/* FDE initial location */
+	.set	L$set$2,LUW4-LUW0	/* FDE address range */
+	.quad	L$set$2
+	.byte	0x0			/* Augmentation size */
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.set	L$set$3,LUW1-LUW0
+	.long	L$set$3
+
+	/* New stack frame based off rbp.  This is a itty bit of unwind
+	   trickery in that the CFA *has* changed.  There is no easy way
+	   to describe it correctly on entry to the function.  Fortunately,
+	   it doesn't matter too much since at all points we can correctly
+	   unwind back to ffi_call.  Note that the location to which we
+	   moved the return address is (the new) CFA-8, so from the
+	   perspective of the unwind info, it hasn't moved.  */
+	.byte	0xc			/* DW_CFA_def_cfa, %rbp offset 32 */
+	.byte	0x6
+	.byte	0x20
+	.byte	0x80+6			/* DW_CFA_offset, %rbp offset 2*-8 */
+	.byte	0x2
+	.byte	0xa			/* DW_CFA_remember_state */
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.set	L$set$4,LUW2-LUW1
+	.long	L$set$4
+	.byte	0xc			/* DW_CFA_def_cfa, %rsp offset 8 */
+	.byte	0x7
+	.byte	0x8
+	.byte	0xc0+6			/* DW_CFA_restore, %rbp */
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.set	L$set$5,LUW3-LUW2
+	.long	L$set$5
+	.byte	0xb			/* DW_CFA_restore_state */
+
+	.align	3
+LEFDE1:
+	.globl _ffi_closure_unix64.eh
+_ffi_closure_unix64.eh:
+LSFDE3:
+	.set	L$set$6,LEFDE3-LASFDE3	/* FDE Length */
+	.long	L$set$6
+LASFDE3:
+	.long	LASFDE3-EH_frame1	/* FDE CIE offset */
+	.quad	LUW5-.			/* FDE initial location */
+	.set	L$set$7,LUW9-LUW5	/* FDE address range */
+	.quad	L$set$7
+	.byte	0x0			/* Augmentation size */
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.set	L$set$8,LUW6-LUW5
+	.long	L$set$8
+	.byte	0xe			/* DW_CFA_def_cfa_offset */
+	.byte	208,1			/* uleb128 208 */
+	.byte	0xa			/* DW_CFA_remember_state */
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.set	L$set$9,LUW7-LUW6
+	.long	L$set$9
+	.byte	0xe			/* DW_CFA_def_cfa_offset */
+	.byte	0x8
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.set	L$set$10,LUW8-LUW7
+	.long	L$set$10
+	.byte	0xb			/* DW_CFA_restore_state */
+
+	.align	3
+LEFDE3:
+	.subsections_via_symbols
+
+#endif /* __x86_64__ */
diff --git a/third_party/gofrontend/libffi/src/x86/ffi.c b/third_party/gofrontend/libffi/src/x86/ffi.c
new file mode 100644
index 0000000..6338de2
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/ffi.c
@@ -0,0 +1,843 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008  Red Hat, Inc.
+           Copyright (c) 2002  Ranjit Mathew
+           Copyright (c) 2002  Bo Thorsen
+           Copyright (c) 2002  Roger Sayle
+           Copyright (C) 2008, 2010  Free Software Foundation, Inc.
+
+   x86 Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__)
+
+#ifdef _WIN64
+#include <windows.h>
+#endif
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+#ifdef X86_WIN32
+  size_t p_stack_args[2];
+  void *p_stack_data[2];
+  char *argp2 = stack;
+  int stack_args_count = 0;
+  int cabi = ecif->cif->abi;
+#endif
+
+  argp = stack;
+
+  if ((ecif->cif->flags == FFI_TYPE_STRUCT
+       || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
+#ifdef X86_WIN64
+      && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
+          && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
+#endif
+      )
+    {
+      *(void **) argp = ecif->rvalue;
+#ifdef X86_WIN32
+      /* For fastcall/thiscall this is first register-passed
+         argument.  */
+      if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
+	{
+	  p_stack_args[stack_args_count] = sizeof (void*);
+	  p_stack_data[stack_args_count] = argp;
+	  ++stack_args_count;
+	}
+#endif
+      argp += sizeof(void*);
+    }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i != 0;
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(void*) - 1) & (size_t) argp)
+        argp = (char *) ALIGN(argp, sizeof(void*));
+
+      z = (*p_arg)->size;
+#ifdef X86_WIN64
+      if (z > sizeof(ffi_arg)
+          || ((*p_arg)->type == FFI_TYPE_STRUCT
+              && (z != 1 && z != 2 && z != 4 && z != 8))
+#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
+          || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
+#endif
+          )
+        {
+          z = sizeof(ffi_arg);
+          *(void **)argp = *p_argv;
+        }
+      else if ((*p_arg)->type == FFI_TYPE_FLOAT)
+        {
+          memcpy(argp, *p_argv, z);
+        }
+      else
+#endif
+      if (z < sizeof(ffi_arg))
+        {
+          z = sizeof(ffi_arg);
+          switch ((*p_arg)->type)
+            {
+            case FFI_TYPE_SINT8:
+              *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_UINT8:
+              *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_SINT16:
+              *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_UINT16:
+              *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_SINT32:
+              *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_UINT32:
+              *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_STRUCT:
+              *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
+              break;
+
+            default:
+              FFI_ASSERT(0);
+            }
+        }
+      else
+        {
+          memcpy(argp, *p_argv, z);
+        }
+
+#ifdef X86_WIN32
+    /* For thiscall/fastcall convention register-passed arguments
+       are the first two none-floating-point arguments with a size
+       smaller or equal to sizeof (void*).  */
+    if ((cabi == FFI_THISCALL && stack_args_count < 1)
+        || (cabi == FFI_FASTCALL && stack_args_count < 2))
+      {
+	if (z <= 4
+	    && ((*p_arg)->type != FFI_TYPE_FLOAT
+	        && (*p_arg)->type != FFI_TYPE_STRUCT))
+	  {
+	    p_stack_args[stack_args_count] = z;
+	    p_stack_data[stack_args_count] = argp;
+	    ++stack_args_count;
+	  }
+      }
+#endif
+      p_argv++;
+#ifdef X86_WIN64
+      argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
+#else
+      argp += z;
+#endif
+    }
+
+#ifdef X86_WIN32
+  /* We need to move the register-passed arguments for thiscall/fastcall
+     on top of stack, so that those can be moved to registers ecx/edx by
+     call-handler.  */
+  if (stack_args_count > 0)
+    {
+      size_t zz = (p_stack_args[0] + 3) & ~3;
+      char *h;
+
+      /* Move first argument to top-stack position.  */
+      if (p_stack_data[0] != argp2)
+	{
+	  h = alloca (zz + 1);
+	  memcpy (h, p_stack_data[0], zz);
+	  memmove (argp2 + zz, argp2,
+	           (size_t) ((char *) p_stack_data[0] - (char*)argp2));
+	  memcpy (argp2, h, zz);
+	}
+
+      argp2 += zz;
+      --stack_args_count;
+      if (zz > 4)
+	stack_args_count = 0;
+
+      /* If we have a second argument, then move it on top
+         after the first one.  */
+      if (stack_args_count > 0 && p_stack_data[1] != argp2)
+	{
+	  zz = p_stack_args[1];
+	  zz = (zz + 3) & ~3;
+	  h = alloca (zz + 1);
+	  h = alloca (zz + 1);
+	  memcpy (h, p_stack_data[1], zz);
+	  memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
+	  memcpy (argp2, h, zz);
+	}
+    }
+#endif
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  unsigned int i;
+  ffi_type **ptr;
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_SINT16:
+#ifdef X86_WIN64
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+#endif
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+#ifndef X86_WIN64
+#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+#endif
+#endif
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_UINT64:
+#ifdef X86_WIN64
+    case FFI_TYPE_POINTER:
+#endif
+      cif->flags = FFI_TYPE_SINT64;
+      break;
+
+    case FFI_TYPE_STRUCT:
+#ifndef X86
+      if (cif->rtype->size == 1)
+        {
+          cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
+        }
+      else if (cif->rtype->size == 2)
+        {
+          cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
+        }
+      else if (cif->rtype->size == 4)
+        {
+#ifdef X86_WIN64
+          cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
+#else
+          cif->flags = FFI_TYPE_INT; /* same as int type */
+#endif
+        }
+      else if (cif->rtype->size == 8)
+        {
+          cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
+        }
+      else
+#endif
+        {
+#ifdef X86_WIN32
+          if (cif->abi == FFI_MS_CDECL)
+            cif->flags = FFI_TYPE_MS_STRUCT;
+          else
+#endif
+            cif->flags = FFI_TYPE_STRUCT;
+          /* allocate space for return value pointer */
+          cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
+        }
+      break;
+
+    default:
+#ifdef X86_WIN64
+      cif->flags = FFI_TYPE_SINT64;
+      break;
+    case FFI_TYPE_INT:
+      cif->flags = FFI_TYPE_SINT32;
+#else
+      cif->flags = FFI_TYPE_INT;
+#endif
+      break;
+    }
+
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+      if (((*ptr)->alignment - 1) & cif->bytes)
+        cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
+      cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
+    }
+
+#ifdef X86_WIN64
+  /* ensure space for storing four registers */
+  cif->bytes += 4 * sizeof(ffi_arg);
+#endif
+
+#ifdef X86_DARWIN
+  cif->bytes = (cif->bytes + 15) & ~0xF;
+#endif
+
+  return FFI_OK;
+}
+
+#ifdef X86_WIN64
+extern int
+ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
+               unsigned, unsigned, unsigned *, void (*fn)(void));
+#elif defined(X86_WIN32)
+extern void
+ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
+               unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
+#else
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+                          unsigned, unsigned, unsigned *, void (*fn)(void));
+#endif
+
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return */
+  /* value address then we need to make one                     */
+
+#ifdef X86_WIN64
+  if (rvalue == NULL
+      && cif->flags == FFI_TYPE_STRUCT
+      && cif->rtype->size != 1 && cif->rtype->size != 2
+      && cif->rtype->size != 4 && cif->rtype->size != 8)
+    {
+      ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
+    }
+#else
+  if (rvalue == NULL
+      && (cif->flags == FFI_TYPE_STRUCT
+          || cif->flags == FFI_TYPE_MS_STRUCT))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+#endif
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+#ifdef X86_WIN64
+    case FFI_WIN64:
+      ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
+                     cif->flags, ecif.rvalue, fn);
+      break;
+#elif defined(X86_WIN32)
+    case FFI_SYSV:
+    case FFI_STDCALL:
+    case FFI_MS_CDECL:
+      ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
+		     ecif.rvalue, fn);
+      break;
+    case FFI_THISCALL:
+    case FFI_FASTCALL:
+      {
+	unsigned int abi = cif->abi;
+	unsigned int i, passed_regs = 0;
+
+	if (cif->flags == FFI_TYPE_STRUCT)
+	  ++passed_regs;
+
+	for (i=0; i < cif->nargs && passed_regs < 2;i++)
+	  {
+	    size_t sz;
+
+	    if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
+	        || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
+	      continue;
+	    sz = (cif->arg_types[i]->size + 3) & ~3;
+	    if (sz == 0 || sz > 4)
+	      continue;
+	    ++passed_regs;
+	  }
+	if (passed_regs < 2 && abi == FFI_FASTCALL)
+	  abi = FFI_THISCALL;
+	if (passed_regs < 1 && abi == FFI_THISCALL)
+	  abi = FFI_STDCALL;
+        ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
+                       ecif.rvalue, fn);
+      }
+      break;
+#else
+    case FFI_SYSV:
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
+                    fn);
+      break;
+#endif
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+
+/** private members **/
+
+/* The following __attribute__((regparm(1))) decorations will have no effect
+   on MSVC - standard cdecl convention applies. */
+static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
+                                         void** args, ffi_cif* cif);
+void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
+     __attribute__ ((regparm(1)));
+unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
+     __attribute__ ((regparm(1)));
+void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
+     __attribute__ ((regparm(1)));
+#ifdef X86_WIN32
+void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
+     __attribute__ ((regparm(1)));
+void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
+     __attribute__ ((regparm(1)));
+void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
+     __attribute__ ((regparm(1)));
+#endif
+#ifdef X86_WIN64
+void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
+#endif
+
+/* This function is jumped to by the trampoline */
+
+#ifdef X86_WIN64
+void * FFI_HIDDEN
+ffi_closure_win64_inner (ffi_closure *closure, void *args) {
+  ffi_cif       *cif;
+  void         **arg_area;
+  void          *result;
+  void          *resp = &result;
+
+  cif         = closure->cif;
+  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+
+  /* this call will initialize ARG_AREA, such that each
+   * element in that array points to the corresponding 
+   * value on the stack; and if the function returns
+   * a structure, it will change RESP to point to the
+   * structure return address.  */
+
+  ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
+  
+  (closure->fun) (cif, resp, arg_area, closure->user_data);
+
+  /* The result is returned in rax.  This does the right thing for
+     result types except for floats; we have to 'mov xmm0, rax' in the
+     caller to correct this.
+     TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
+  */
+  return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
+}
+
+#else
+unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
+ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
+{
+  /* our various things...  */
+  ffi_cif       *cif;
+  void         **arg_area;
+
+  cif         = closure->cif;
+  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+
+  /* this call will initialize ARG_AREA, such that each
+   * element in that array points to the corresponding 
+   * value on the stack; and if the function returns
+   * a structure, it will change RESP to point to the
+   * structure return address.  */
+
+  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
+
+  (closure->fun) (cif, *respp, arg_area, closure->user_data);
+
+  return cif->flags;
+}
+#endif /* !X86_WIN64 */
+
+static void
+ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
+                            ffi_cif *cif)
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+#ifdef X86_WIN64
+  if (cif->rtype->size > sizeof(ffi_arg)
+      || (cif->flags == FFI_TYPE_STRUCT
+          && (cif->rtype->size != 1 && cif->rtype->size != 2
+              && cif->rtype->size != 4 && cif->rtype->size != 8))) {
+    *rvalue = *(void **) argp;
+    argp += sizeof(void *);
+  }
+#else
+  if ( cif->flags == FFI_TYPE_STRUCT
+       || cif->flags == FFI_TYPE_MS_STRUCT ) {
+    *rvalue = *(void **) argp;
+    argp += sizeof(void *);
+  }
+#endif
+
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(void*) - 1) & (size_t) argp) {
+        argp = (char *) ALIGN(argp, sizeof(void*));
+      }
+
+#ifdef X86_WIN64
+      if ((*p_arg)->size > sizeof(ffi_arg)
+          || ((*p_arg)->type == FFI_TYPE_STRUCT
+              && ((*p_arg)->size != 1 && (*p_arg)->size != 2
+                  && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
+        {
+          z = sizeof(void *);
+          *p_argv = *(void **)argp;
+        }
+      else
+#endif
+        {
+          z = (*p_arg)->size;
+          
+          /* because we're little endian, this is what it turns into.   */
+          
+          *p_argv = (void*) argp;
+        }
+          
+      p_argv++;
+#ifdef X86_WIN64
+      argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
+#else
+      argp += z;
+#endif
+    }
+  
+  return;
+}
+
+#define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+   void*  __fun = (void*)(FUN); \
+   void*  __ctx = (void*)(CTX); \
+   *(unsigned char*) &__tramp[0] = 0x41; \
+   *(unsigned char*) &__tramp[1] = 0xbb; \
+   *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
+   *(unsigned char*) &__tramp[6] = 0x48; \
+   *(unsigned char*) &__tramp[7] = 0xb8; \
+   *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
+   *(unsigned char *)  &__tramp[16] = 0x49; \
+   *(unsigned char *)  &__tramp[17] = 0xba; \
+   *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
+   *(unsigned char *)  &__tramp[26] = 0x41; \
+   *(unsigned char *)  &__tramp[27] = 0xff; \
+   *(unsigned char *)  &__tramp[28] = 0xe2; /* jmp %r10 */ \
+ }
+
+/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
+
+#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+   unsigned int  __fun = (unsigned int)(FUN); \
+   unsigned int  __ctx = (unsigned int)(CTX); \
+   unsigned int  __dis = __fun - (__ctx + 10);  \
+   *(unsigned char*) &__tramp[0] = 0xb8; \
+   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
+   *(unsigned char *)  &__tramp[5] = 0xe9; \
+   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
+ }
+
+#define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \
+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+   unsigned int  __fun = (unsigned int)(FUN); \
+   unsigned int  __ctx = (unsigned int)(CTX); \
+   unsigned int  __dis = __fun - (__ctx + 49);  \
+   unsigned short __size = (unsigned short)(SIZE); \
+   *(unsigned int *) &__tramp[0] = 0x8324048b;	/* mov (%esp), %eax */ \
+   *(unsigned int *) &__tramp[4] = 0x4c890cec;	/* sub $12, %esp */ \
+   *(unsigned int *) &__tramp[8] = 0x04890424;	/* mov %ecx, 4(%esp) */ \
+   *(unsigned char*) &__tramp[12] = 0x24;	/* mov %eax, (%esp) */ \
+   *(unsigned char*) &__tramp[13] = 0xb8; \
+   *(unsigned int *) &__tramp[14] = __size;	/* mov __size, %eax */ \
+   *(unsigned int *) &__tramp[18] = 0x08244c8d;	/* lea 8(%esp), %ecx */ \
+   *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
+   *(unsigned short*) &__tramp[26] = 0x0b74;	/* jz 1f */ \
+   *(unsigned int *) &__tramp[28] = 0x8908518b;	/* 2b: mov 8(%ecx), %edx */ \
+   *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
+   *(unsigned char*) &__tramp[36] = 0x48;	/* dec %eax */ \
+   *(unsigned short*) &__tramp[37] = 0xf575;	/* jnz 2b ; 1f: */ \
+   *(unsigned char*) &__tramp[39] = 0xb8; \
+   *(unsigned int*)  &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
+   *(unsigned char *)  &__tramp[44] = 0xe8; \
+   *(unsigned int*)  &__tramp[45] = __dis; /* call __fun  */ \
+   *(unsigned char*)  &__tramp[49] = 0xc2; /* ret  */ \
+   *(unsigned short*)  &__tramp[50] = (__size + 8); /* ret (__size + 8)  */ \
+ }
+
+#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+   unsigned int  __fun = (unsigned int)(FUN); \
+   unsigned int  __ctx = (unsigned int)(CTX); \
+   unsigned int  __dis = __fun - (__ctx + 10); \
+   unsigned short __size = (unsigned short)(SIZE); \
+   *(unsigned char*) &__tramp[0] = 0xb8; \
+   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
+   *(unsigned char *)  &__tramp[5] = 0xe8; \
+   *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
+   *(unsigned char *)  &__tramp[10] = 0xc2; \
+   *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
+ }
+
+/* the cif must already be prep'ed */
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+                      ffi_cif* cif,
+                      void (*fun)(ffi_cif*,void*,void**,void*),
+                      void *user_data,
+                      void *codeloc)
+{
+#ifdef X86_WIN64
+#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
+#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
+  if (cif->abi == FFI_WIN64) 
+    {
+      int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
+      FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
+                                 &ffi_closure_win64,
+                                 codeloc, mask);
+      /* make sure we can execute here */
+    }
+#else
+  if (cif->abi == FFI_SYSV)
+    {
+      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
+                           &ffi_closure_SYSV,
+                           (void*)codeloc);
+    }
+#ifdef X86_WIN32
+  else if (cif->abi == FFI_THISCALL)
+    {
+      FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
+				    &ffi_closure_THISCALL,
+				    (void*)codeloc,
+				    cif->bytes);
+    }
+  else if (cif->abi == FFI_STDCALL)
+    {
+      FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
+                                   &ffi_closure_STDCALL,
+                                   (void*)codeloc, cif->bytes);
+    }
+  else if (cif->abi == FFI_MS_CDECL)
+    {
+      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
+                           &ffi_closure_SYSV,
+                           (void*)codeloc);
+    }
+#endif /* X86_WIN32 */
+#endif /* !X86_WIN64 */
+  else
+    {
+      return FFI_BAD_ABI;
+    }
+    
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+/* ------- Native raw API support -------------------------------- */
+
+#if !FFI_NO_RAW_API
+
+ffi_status
+ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
+                          ffi_cif* cif,
+                          void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                          void *user_data,
+                          void *codeloc)
+{
+  int i;
+
+  if (cif->abi != FFI_SYSV) {
+#ifdef X86_WIN32
+    if (cif->abi != FFI_THISCALL)
+#endif
+    return FFI_BAD_ABI;
+  }
+
+  /* we currently don't support certain kinds of arguments for raw
+     closures.  This should be implemented by a separate assembly
+     language routine, since it would require argument processing,
+     something we don't do now for performance.  */
+
+  for (i = cif->nargs-1; i >= 0; i--)
+    {
+      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
+      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
+    }
+  
+#ifdef X86_WIN32
+  if (cif->abi == FFI_SYSV)
+    {
+#endif
+  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
+                       codeloc);
+#ifdef X86_WIN32
+    }
+  else if (cif->abi == FFI_THISCALL)
+    {
+      FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
+				    codeloc, cif->bytes);
+    }
+#endif
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+static void 
+ffi_prep_args_raw(char *stack, extended_cif *ecif)
+{
+  memcpy (stack, ecif->avalue, ecif->cif->bytes);
+}
+
+/* we borrow this routine from libffi (it must be changed, though, to
+ * actually call the function passed in the first argument.  as of
+ * libffi-1.20, this is not the case.)
+ */
+
+void
+ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
+{
+  extended_cif ecif;
+  void **avalue = (void **)fake_avalue;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return */
+  /* value address then we need to make one                     */
+
+  if (rvalue == NULL
+      && (cif->flags == FFI_TYPE_STRUCT
+          || cif->flags == FFI_TYPE_MS_STRUCT))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+#ifdef X86_WIN32
+    case FFI_SYSV:
+    case FFI_STDCALL:
+    case FFI_MS_CDECL:
+      ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
+		     ecif.rvalue, fn);
+      break;
+    case FFI_THISCALL:
+    case FFI_FASTCALL:
+      {
+	unsigned int abi = cif->abi;
+	unsigned int i, passed_regs = 0;
+
+	if (cif->flags == FFI_TYPE_STRUCT)
+	  ++passed_regs;
+
+	for (i=0; i < cif->nargs && passed_regs < 2;i++)
+	  {
+	    size_t sz;
+
+	    if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
+	        || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
+	      continue;
+	    sz = (cif->arg_types[i]->size + 3) & ~3;
+	    if (sz == 0 || sz > 4)
+	      continue;
+	    ++passed_regs;
+	  }
+	if (passed_regs < 2 && abi == FFI_FASTCALL)
+	  cif->abi = abi = FFI_THISCALL;
+	if (passed_regs < 1 && abi == FFI_THISCALL)
+	  cif->abi = abi = FFI_STDCALL;
+        ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
+                       ecif.rvalue, fn);
+      }
+      break;
+#else
+    case FFI_SYSV:
+      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
+                    ecif.rvalue, fn);
+      break;
+#endif
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#endif
+
+#endif /* !__x86_64__  || X86_WIN64 */
+
diff --git a/third_party/gofrontend/libffi/src/x86/ffi64.c b/third_party/gofrontend/libffi/src/x86/ffi64.c
new file mode 100644
index 0000000..1daa1c0
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/ffi64.c
@@ -0,0 +1,643 @@
+/* -----------------------------------------------------------------------
+   ffi64.c - Copyright (c) 20011  Anthony Green
+             Copyright (c) 2008, 2010  Red Hat, Inc.
+             Copyright (c) 2002, 2007  Bo Thorsen <bo@suse.de>
+             
+   x86-64 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#ifdef __x86_64__
+
+#define MAX_GPR_REGS 6
+#define MAX_SSE_REGS 8
+
+#ifdef __INTEL_COMPILER
+#define UINT128 __m128
+#else
+#define UINT128 __int128_t
+#endif
+
+struct register_args
+{
+  /* Registers for argument passing.  */
+  UINT64 gpr[MAX_GPR_REGS];
+  UINT128 sse[MAX_SSE_REGS];
+};
+
+extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
+			     void *raddr, void (*fnaddr)(void), unsigned ssecount);
+
+/* All reference to register classes here is identical to the code in
+   gcc/config/i386/i386.c. Do *not* change one without the other.  */
+
+/* Register class used for passing given 64bit part of the argument.
+   These represent classes as documented by the PS ABI, with the
+   exception of SSESF, SSEDF classes, that are basically SSE class,
+   just gcc will use SF or DFmode move instead of DImode to avoid
+   reformatting penalties.
+
+   Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
+   whenever possible (upper half does contain padding).  */
+enum x86_64_reg_class
+  {
+    X86_64_NO_CLASS,
+    X86_64_INTEGER_CLASS,
+    X86_64_INTEGERSI_CLASS,
+    X86_64_SSE_CLASS,
+    X86_64_SSESF_CLASS,
+    X86_64_SSEDF_CLASS,
+    X86_64_SSEUP_CLASS,
+    X86_64_X87_CLASS,
+    X86_64_X87UP_CLASS,
+    X86_64_COMPLEX_X87_CLASS,
+    X86_64_MEMORY_CLASS
+  };
+
+#define MAX_CLASSES 4
+
+#define SSE_CLASS_P(X)	((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
+
+/* x86-64 register passing implementation.  See x86-64 ABI for details.  Goal
+   of this code is to classify each 8bytes of incoming argument by the register
+   class and assign registers accordingly.  */
+
+/* Return the union class of CLASS1 and CLASS2.
+   See the x86-64 PS ABI for details.  */
+
+static enum x86_64_reg_class
+merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
+{
+  /* Rule #1: If both classes are equal, this is the resulting class.  */
+  if (class1 == class2)
+    return class1;
+
+  /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
+     the other class.  */
+  if (class1 == X86_64_NO_CLASS)
+    return class2;
+  if (class2 == X86_64_NO_CLASS)
+    return class1;
+
+  /* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  */
+  if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
+    return X86_64_MEMORY_CLASS;
+
+  /* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  */
+  if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
+      || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
+    return X86_64_INTEGERSI_CLASS;
+  if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
+      || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
+    return X86_64_INTEGER_CLASS;
+
+  /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
+     MEMORY is used.  */
+  if (class1 == X86_64_X87_CLASS
+      || class1 == X86_64_X87UP_CLASS
+      || class1 == X86_64_COMPLEX_X87_CLASS
+      || class2 == X86_64_X87_CLASS
+      || class2 == X86_64_X87UP_CLASS
+      || class2 == X86_64_COMPLEX_X87_CLASS)
+    return X86_64_MEMORY_CLASS;
+
+  /* Rule #6: Otherwise class SSE is used.  */
+  return X86_64_SSE_CLASS;
+}
+
+/* Classify the argument of type TYPE and mode MODE.
+   CLASSES will be filled by the register class used to pass each word
+   of the operand.  The number of words is returned.  In case the parameter
+   should be passed in memory, 0 is returned. As a special case for zero
+   sized containers, classes[0] will be NO_CLASS and 1 is returned.
+
+   See the x86-64 PS ABI for details.
+*/
+static int
+classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
+		   size_t byte_offset)
+{
+  switch (type->type)
+    {
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_POINTER:
+      {
+	int size = byte_offset + type->size;
+
+	if (size <= 4)
+	  {
+	    classes[0] = X86_64_INTEGERSI_CLASS;
+	    return 1;
+	  }
+	else if (size <= 8)
+	  {
+	    classes[0] = X86_64_INTEGER_CLASS;
+	    return 1;
+	  }
+	else if (size <= 12)
+	  {
+	    classes[0] = X86_64_INTEGER_CLASS;
+	    classes[1] = X86_64_INTEGERSI_CLASS;
+	    return 2;
+	  }
+	else if (size <= 16)
+	  {
+	    classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
+	    return 2;
+	  }
+	else
+	  FFI_ASSERT (0);
+      }
+    case FFI_TYPE_FLOAT:
+      if (!(byte_offset % 8))
+	classes[0] = X86_64_SSESF_CLASS;
+      else
+	classes[0] = X86_64_SSE_CLASS;
+      return 1;
+    case FFI_TYPE_DOUBLE:
+      classes[0] = X86_64_SSEDF_CLASS;
+      return 1;
+    case FFI_TYPE_LONGDOUBLE:
+      classes[0] = X86_64_X87_CLASS;
+      classes[1] = X86_64_X87UP_CLASS;
+      return 2;
+    case FFI_TYPE_STRUCT:
+      {
+	const int UNITS_PER_WORD = 8;
+	int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+	ffi_type **ptr; 
+	int i;
+	enum x86_64_reg_class subclasses[MAX_CLASSES];
+
+	/* If the struct is larger than 32 bytes, pass it on the stack.  */
+	if (type->size > 32)
+	  return 0;
+
+	for (i = 0; i < words; i++)
+	  classes[i] = X86_64_NO_CLASS;
+
+	/* Zero sized arrays or structures are NO_CLASS.  We return 0 to
+	   signalize memory class, so handle it as special case.  */
+	if (!words)
+	  {
+	    classes[0] = X86_64_NO_CLASS;
+	    return 1;
+	  }
+
+	/* Merge the fields of structure.  */
+	for (ptr = type->elements; *ptr != NULL; ptr++)
+	  {
+	    int num;
+
+	    byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
+
+	    num = classify_argument (*ptr, subclasses, byte_offset % 8);
+	    if (num == 0)
+	      return 0;
+	    for (i = 0; i < num; i++)
+	      {
+		int pos = byte_offset / 8;
+		classes[i + pos] =
+		  merge_classes (subclasses[i], classes[i + pos]);
+	      }
+
+	    byte_offset += (*ptr)->size;
+	  }
+
+	if (words > 2)
+	  {
+	    /* When size > 16 bytes, if the first one isn't
+	       X86_64_SSE_CLASS or any other ones aren't
+	       X86_64_SSEUP_CLASS, everything should be passed in
+	       memory.  */
+	    if (classes[0] != X86_64_SSE_CLASS)
+	      return 0;
+
+	    for (i = 1; i < words; i++)
+	      if (classes[i] != X86_64_SSEUP_CLASS)
+		return 0;
+	  }
+
+	/* Final merger cleanup.  */
+	for (i = 0; i < words; i++)
+	  {
+	    /* If one class is MEMORY, everything should be passed in
+	       memory.  */
+	    if (classes[i] == X86_64_MEMORY_CLASS)
+	      return 0;
+
+	    /* The X86_64_SSEUP_CLASS should be always preceded by
+	       X86_64_SSE_CLASS or X86_64_SSEUP_CLASS.  */
+	    if (classes[i] == X86_64_SSEUP_CLASS
+		&& classes[i - 1] != X86_64_SSE_CLASS
+		&& classes[i - 1] != X86_64_SSEUP_CLASS)
+	      {
+		/* The first one should never be X86_64_SSEUP_CLASS.  */
+		FFI_ASSERT (i != 0);
+		classes[i] = X86_64_SSE_CLASS;
+	      }
+
+	    /*  If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
+		everything should be passed in memory.  */
+	    if (classes[i] == X86_64_X87UP_CLASS
+		&& (classes[i - 1] != X86_64_X87_CLASS))
+	      {
+		/* The first one should never be X86_64_X87UP_CLASS.  */
+		FFI_ASSERT (i != 0);
+		return 0;
+	      }
+	  }
+	return words;
+      }
+
+    default:
+      FFI_ASSERT(0);
+    }
+  return 0; /* Never reached.  */
+}
+
+/* Examine the argument and return set number of register required in each
+   class.  Return zero iff parameter should be passed in memory, otherwise
+   the number of registers.  */
+
+static int
+examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
+		  _Bool in_return, int *pngpr, int *pnsse)
+{
+  int i, n, ngpr, nsse;
+
+  n = classify_argument (type, classes, 0);
+  if (n == 0)
+    return 0;
+
+  ngpr = nsse = 0;
+  for (i = 0; i < n; ++i)
+    switch (classes[i])
+      {
+      case X86_64_INTEGER_CLASS:
+      case X86_64_INTEGERSI_CLASS:
+	ngpr++;
+	break;
+      case X86_64_SSE_CLASS:
+      case X86_64_SSESF_CLASS:
+      case X86_64_SSEDF_CLASS:
+	nsse++;
+	break;
+      case X86_64_NO_CLASS:
+      case X86_64_SSEUP_CLASS:
+	break;
+      case X86_64_X87_CLASS:
+      case X86_64_X87UP_CLASS:
+      case X86_64_COMPLEX_X87_CLASS:
+	return in_return != 0;
+      default:
+	abort ();
+      }
+
+  *pngpr = ngpr;
+  *pnsse = nsse;
+
+  return n;
+}
+
+/* Perform machine dependent cif processing.  */
+
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  int gprcount, ssecount, i, avn, n, ngpr, nsse, flags;
+  enum x86_64_reg_class classes[MAX_CLASSES];
+  size_t bytes;
+
+  gprcount = ssecount = 0;
+
+  flags = cif->rtype->type;
+  if (flags != FFI_TYPE_VOID)
+    {
+      n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
+      if (n == 0)
+	{
+	  /* The return value is passed in memory.  A pointer to that
+	     memory is the first argument.  Allocate a register for it.  */
+	  gprcount++;
+	  /* We don't have to do anything in asm for the return.  */
+	  flags = FFI_TYPE_VOID;
+	}
+      else if (flags == FFI_TYPE_STRUCT)
+	{
+	  /* Mark which registers the result appears in.  */
+	  _Bool sse0 = SSE_CLASS_P (classes[0]);
+	  _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
+	  if (sse0 && !sse1)
+	    flags |= 1 << 8;
+	  else if (!sse0 && sse1)
+	    flags |= 1 << 9;
+	  else if (sse0 && sse1)
+	    flags |= 1 << 10;
+	  /* Mark the true size of the structure.  */
+	  flags |= cif->rtype->size << 12;
+	}
+    }
+
+  /* Go over all arguments and determine the way they should be passed.
+     If it's in a register and there is space for it, let that be so. If
+     not, add it's size to the stack byte count.  */
+  for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
+    {
+      if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
+	  || gprcount + ngpr > MAX_GPR_REGS
+	  || ssecount + nsse > MAX_SSE_REGS)
+	{
+	  long align = cif->arg_types[i]->alignment;
+
+	  if (align < 8)
+	    align = 8;
+
+	  bytes = ALIGN (bytes, align);
+	  bytes += cif->arg_types[i]->size;
+	}
+      else
+	{
+	  gprcount += ngpr;
+	  ssecount += nsse;
+	}
+    }
+  if (ssecount)
+    flags |= 1 << 11;
+  cif->flags = flags;
+  cif->bytes = ALIGN (bytes, 8);
+
+  return FFI_OK;
+}
+
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  enum x86_64_reg_class classes[MAX_CLASSES];
+  char *stack, *argp;
+  ffi_type **arg_types;
+  int gprcount, ssecount, ngpr, nsse, i, avn;
+  _Bool ret_in_memory;
+  struct register_args *reg_args;
+
+  /* Can't call 32-bit mode from 64-bit mode.  */
+  FFI_ASSERT (cif->abi == FFI_UNIX64);
+
+  /* If the return value is a struct and we don't have a return value
+     address then we need to make one.  Note the setting of flags to
+     VOID above in ffi_prep_cif_machdep.  */
+  ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
+		   && (cif->flags & 0xff) == FFI_TYPE_VOID);
+  if (rvalue == NULL && ret_in_memory)
+    rvalue = alloca (cif->rtype->size);
+
+  /* Allocate the space for the arguments, plus 4 words of temp space.  */
+  stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
+  reg_args = (struct register_args *) stack;
+  argp = stack + sizeof (struct register_args);
+
+  gprcount = ssecount = 0;
+
+  /* If the return value is passed in memory, add the pointer as the
+     first integer argument.  */
+  if (ret_in_memory)
+    reg_args->gpr[gprcount++] = (unsigned long) rvalue;
+
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  for (i = 0; i < avn; ++i)
+    {
+      size_t size = arg_types[i]->size;
+      int n;
+
+      n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
+      if (n == 0
+	  || gprcount + ngpr > MAX_GPR_REGS
+	  || ssecount + nsse > MAX_SSE_REGS)
+	{
+	  long align = arg_types[i]->alignment;
+
+	  /* Stack arguments are *always* at least 8 byte aligned.  */
+	  if (align < 8)
+	    align = 8;
+
+	  /* Pass this argument in memory.  */
+	  argp = (void *) ALIGN (argp, align);
+	  memcpy (argp, avalue[i], size);
+	  argp += size;
+	}
+      else
+	{
+	  /* The argument is passed entirely in registers.  */
+	  char *a = (char *) avalue[i];
+	  int j;
+
+	  for (j = 0; j < n; j++, a += 8, size -= 8)
+	    {
+	      switch (classes[j])
+		{
+		case X86_64_INTEGER_CLASS:
+		case X86_64_INTEGERSI_CLASS:
+		  reg_args->gpr[gprcount] = 0;
+		  memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);
+		  gprcount++;
+		  break;
+		case X86_64_SSE_CLASS:
+		case X86_64_SSEDF_CLASS:
+		  reg_args->sse[ssecount++] = *(UINT64 *) a;
+		  break;
+		case X86_64_SSESF_CLASS:
+		  reg_args->sse[ssecount++] = *(UINT32 *) a;
+		  break;
+		default:
+		  abort();
+		}
+	    }
+	}
+    }
+
+  ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
+		   cif->flags, rvalue, fn, ssecount);
+}
+
+
+extern void ffi_closure_unix64(void);
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  volatile unsigned short *tramp;
+
+  /* Sanity check on the cif ABI.  */
+  {
+    int abi = cif->abi;
+    if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)))
+      return FFI_BAD_ABI;
+  }
+
+  tramp = (volatile unsigned short *) &closure->tramp[0];
+
+  tramp[0] = 0xbb49;		/* mov <code>, %r11	*/
+  *((unsigned long long * volatile) &tramp[1])
+    = (unsigned long) ffi_closure_unix64;
+  tramp[5] = 0xba49;		/* mov <data>, %r10	*/
+  *((unsigned long long * volatile) &tramp[6])
+    = (unsigned long) codeloc;
+
+  /* Set the carry bit iff the function uses any sse registers.
+     This is clc or stc, together with the first byte of the jmp.  */
+  tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
+
+  tramp[11] = 0xe3ff;			/* jmp *%r11    */
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
+
+int
+ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
+			 struct register_args *reg_args, char *argp)
+{
+  ffi_cif *cif;
+  void **avalue;
+  ffi_type **arg_types;
+  long i, avn;
+  int gprcount, ssecount, ngpr, nsse;
+  int ret;
+
+  cif = closure->cif;
+  avalue = alloca(cif->nargs * sizeof(void *));
+  gprcount = ssecount = 0;
+
+  ret = cif->rtype->type;
+  if (ret != FFI_TYPE_VOID)
+    {
+      enum x86_64_reg_class classes[MAX_CLASSES];
+      int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
+      if (n == 0)
+	{
+	  /* The return value goes in memory.  Arrange for the closure
+	     return value to go directly back to the original caller.  */
+	  rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++];
+	  /* We don't have to do anything in asm for the return.  */
+	  ret = FFI_TYPE_VOID;
+	}
+      else if (ret == FFI_TYPE_STRUCT && n == 2)
+	{
+	  /* Mark which register the second word of the structure goes in.  */
+	  _Bool sse0 = SSE_CLASS_P (classes[0]);
+	  _Bool sse1 = SSE_CLASS_P (classes[1]);
+	  if (!sse0 && sse1)
+	    ret |= 1 << 8;
+	  else if (sse0 && !sse1)
+	    ret |= 1 << 9;
+	}
+    }
+
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+  
+  for (i = 0; i < avn; ++i)
+    {
+      enum x86_64_reg_class classes[MAX_CLASSES];
+      int n;
+
+      n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
+      if (n == 0
+	  || gprcount + ngpr > MAX_GPR_REGS
+	  || ssecount + nsse > MAX_SSE_REGS)
+	{
+	  long align = arg_types[i]->alignment;
+
+	  /* Stack arguments are *always* at least 8 byte aligned.  */
+	  if (align < 8)
+	    align = 8;
+
+	  /* Pass this argument in memory.  */
+	  argp = (void *) ALIGN (argp, align);
+	  avalue[i] = argp;
+	  argp += arg_types[i]->size;
+	}
+      /* If the argument is in a single register, or two consecutive
+	 integer registers, then we can use that address directly.  */
+      else if (n == 1
+	       || (n == 2 && !(SSE_CLASS_P (classes[0])
+			       || SSE_CLASS_P (classes[1]))))
+	{
+	  /* The argument is in a single register.  */
+	  if (SSE_CLASS_P (classes[0]))
+	    {
+	      avalue[i] = &reg_args->sse[ssecount];
+	      ssecount += n;
+	    }
+	  else
+	    {
+	      avalue[i] = &reg_args->gpr[gprcount];
+	      gprcount += n;
+	    }
+	}
+      /* Otherwise, allocate space to make them consecutive.  */
+      else
+	{
+	  char *a = alloca (16);
+	  int j;
+
+	  avalue[i] = a;
+	  for (j = 0; j < n; j++, a += 8)
+	    {
+	      if (SSE_CLASS_P (classes[j]))
+		memcpy (a, &reg_args->sse[ssecount++], 8);
+	      else
+		memcpy (a, &reg_args->gpr[gprcount++], 8);
+	    }
+	}
+    }
+
+  /* Invoke the closure.  */
+  closure->fun (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell assembly how to perform return type promotions.  */
+  return ret;
+}
+
+#endif /* __x86_64__ */
diff --git a/third_party/gofrontend/libffi/src/x86/ffitarget.h b/third_party/gofrontend/libffi/src/x86/ffitarget.h
new file mode 100644
index 0000000..46f294c
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/ffitarget.h
@@ -0,0 +1,140 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 1996-2003, 2010  Red Hat, Inc.
+                 Copyright (C) 2008  Free Software Foundation, Inc.
+
+   Target configuration macros for x86 and x86-64.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+/* ---- System specific configurations ----------------------------------- */
+
+/* For code common to all platforms on x86 and x86_64. */
+#define X86_ANY
+
+#if defined (X86_64) && defined (__i386__)
+#undef X86_64
+#define X86
+#endif
+
+#ifdef X86_WIN64
+#define FFI_SIZEOF_ARG 8
+#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */
+#endif
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+#ifdef X86_WIN64
+#ifdef _MSC_VER
+typedef unsigned __int64       ffi_arg;
+typedef __int64                ffi_sarg;
+#else
+typedef unsigned long long     ffi_arg;
+typedef long long              ffi_sarg;
+#endif
+#else
+#if defined __x86_64__ && defined __ILP32__
+#define FFI_SIZEOF_ARG 8
+#define FFI_SIZEOF_JAVA_RAW  4
+typedef unsigned long long     ffi_arg;
+typedef long long              ffi_sarg;
+#else
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+#endif
+#endif
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+
+  /* ---- Intel x86 Win32 ---------- */
+#ifdef X86_WIN32
+  FFI_SYSV,
+  FFI_STDCALL,
+  FFI_THISCALL,
+  FFI_FASTCALL,
+  FFI_MS_CDECL,
+  FFI_LAST_ABI,
+#ifdef _MSC_VER
+  FFI_DEFAULT_ABI = FFI_MS_CDECL
+#else
+  FFI_DEFAULT_ABI = FFI_SYSV
+#endif
+
+#elif defined(X86_WIN64)
+  FFI_WIN64,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_WIN64
+
+#else
+  /* ---- Intel x86 and AMD x86-64 - */
+  FFI_SYSV,
+  FFI_UNIX64,   /* Unix variants all use the same ABI for x86-64  */
+  FFI_LAST_ABI,
+#if defined(__i386__) || defined(__i386)
+  FFI_DEFAULT_ABI = FFI_SYSV
+#else
+  FFI_DEFAULT_ABI = FFI_UNIX64
+#endif
+#endif
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
+#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
+#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3)
+#define FFI_TYPE_MS_STRUCT       (FFI_TYPE_LAST + 4)
+
+#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
+#define FFI_TRAMPOLINE_SIZE 24
+#define FFI_NATIVE_RAW_API 0
+#else
+#ifdef X86_WIN32
+#define FFI_TRAMPOLINE_SIZE 52
+#else
+#ifdef X86_WIN64
+#define FFI_TRAMPOLINE_SIZE 29
+#define FFI_NATIVE_RAW_API 0
+#define FFI_NO_RAW_API 1
+#else
+#define FFI_TRAMPOLINE_SIZE 10
+#endif
+#endif
+#ifndef X86_WIN64
+#define FFI_NATIVE_RAW_API 1	/* x86 has native raw api support */
+#endif
+#endif
+
+#endif
+
diff --git a/third_party/gofrontend/libffi/src/x86/freebsd.S b/third_party/gofrontend/libffi/src/x86/freebsd.S
new file mode 100644
index 0000000..afde513
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/freebsd.S
@@ -0,0 +1,458 @@
+/* -----------------------------------------------------------------------
+   freebsd.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005  Red Hat, Inc.
+	       Copyright (c) 2008  Björn König
+	
+   X86 Foreign Function Interface for FreeBSD
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+----------------------------------------------------------------------- */
+
+#ifndef __x86_64__
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+
+.globl ffi_prep_args
+
+	.align 4
+.globl ffi_call_SYSV
+        .type    ffi_call_SYSV,@function
+
+ffi_call_SYSV:
+.LFB1:
+        pushl %ebp
+.LCFI0:
+        movl  %esp,%ebp
+.LCFI1:
+	/* Make room for all of the new args.  */
+	movl  16(%ebp),%ecx
+	subl  %ecx,%esp
+
+	movl  %esp,%eax
+
+	/* Place all of the ffi_prep_args in position  */
+	pushl 12(%ebp)
+	pushl %eax
+	call  *8(%ebp)
+
+	/* Return stack to previous state and call the function  */
+	addl  $8,%esp	
+
+	call  *28(%ebp)
+
+	/* Load %ecx with the return type code  */
+	movl  20(%ebp),%ecx	
+
+	/* Protect %esi.  We're going to pop it in the epilogue.  */
+	pushl %esi
+
+	/* If the return value pointer is NULL, assume no return value.  */
+	cmpl  $0,24(%ebp)
+	jne  0f
+
+	/* Even if there is no space for the return value, we are 
+	   obliged to handle floating-point values.  */
+	cmpl  $FFI_TYPE_FLOAT,%ecx
+	jne   noretval
+	fstp  %st(0)
+
+        jmp   epilogue
+
+0:
+	call  1f
+
+.Lstore_table:
+	.long	noretval-.Lstore_table	/* FFI_TYPE_VOID */
+	.long	retint-.Lstore_table	/* FFI_TYPE_INT */
+	.long	retfloat-.Lstore_table	/* FFI_TYPE_FLOAT */
+	.long	retdouble-.Lstore_table	/* FFI_TYPE_DOUBLE */
+	.long	retlongdouble-.Lstore_table	/* FFI_TYPE_LONGDOUBLE */
+	.long	retuint8-.Lstore_table	/* FFI_TYPE_UINT8 */
+	.long	retsint8-.Lstore_table	/* FFI_TYPE_SINT8 */
+	.long	retuint16-.Lstore_table	/* FFI_TYPE_UINT16 */
+	.long	retsint16-.Lstore_table	/* FFI_TYPE_SINT16 */
+	.long	retint-.Lstore_table	/* FFI_TYPE_UINT32 */
+	.long	retint-.Lstore_table	/* FFI_TYPE_SINT32 */
+	.long	retint64-.Lstore_table	/* FFI_TYPE_UINT64 */
+	.long	retint64-.Lstore_table	/* FFI_TYPE_SINT64 */
+	.long	retstruct-.Lstore_table	/* FFI_TYPE_STRUCT */
+	.long	retint-.Lstore_table	/* FFI_TYPE_POINTER */
+	.long   retstruct1b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_1B */
+	.long   retstruct2b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_2B */
+
+1:
+	pop  %esi
+	add  (%esi, %ecx, 4), %esi
+	jmp  *%esi
+
+	/* Sign/zero extend as appropriate.  */
+retsint8:
+	movsbl  %al, %eax
+	jmp  retint
+
+retsint16:
+	movswl  %ax, %eax
+	jmp  retint
+
+retuint8:
+	movzbl  %al, %eax
+	jmp  retint
+
+retuint16:
+	movzwl  %ax, %eax
+	jmp  retint
+
+retfloat:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	fstps (%ecx)
+	jmp   epilogue
+
+retdouble:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	fstpl (%ecx)
+	jmp   epilogue
+
+retlongdouble:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	fstpt (%ecx)
+	jmp   epilogue
+	
+retint64:	
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	movl  %eax,0(%ecx)
+	movl  %edx,4(%ecx)
+	jmp   epilogue
+	
+retstruct1b:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx
+	movb  %al,0(%ecx)
+	jmp   epilogue
+
+retstruct2b:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx
+	movw  %ax,0(%ecx)
+	jmp   epilogue
+
+retint:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	movl  %eax,0(%ecx)
+
+retstruct:
+	/* Nothing to do!  */
+
+noretval:
+epilogue:
+        popl %esi
+        movl %ebp,%esp
+        popl %ebp
+        ret
+.LFE1:
+.ffi_call_SYSV_end:
+        .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+
+	.align	4
+FFI_HIDDEN (ffi_closure_SYSV)
+.globl ffi_closure_SYSV
+	.type	ffi_closure_SYSV, @function
+
+ffi_closure_SYSV:
+.LFB2:
+	pushl	%ebp
+.LCFI2:
+	movl	%esp, %ebp
+.LCFI3:
+	subl	$40, %esp
+	leal	-24(%ebp), %edx
+	movl	%edx, -12(%ebp)	/* resp */
+	leal	8(%ebp), %edx
+	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
+	leal	-12(%ebp), %edx
+	movl	%edx, (%esp)	/* &resp */
+#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__
+	call	ffi_closure_SYSV_inner
+#else
+	movl	%ebx, 8(%esp)
+.LCFI7:
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	call	ffi_closure_SYSV_inner@PLT
+	movl	8(%esp), %ebx
+#endif
+	movl	-12(%ebp), %ecx
+	cmpl	$FFI_TYPE_INT, %eax
+	je	.Lcls_retint
+
+	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
+	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
+	cmpl	$FFI_TYPE_UINT64, %eax
+	jge	0f
+	cmpl	$FFI_TYPE_UINT8, %eax
+	jge	.Lcls_retint
+	
+0:	cmpl	$FFI_TYPE_FLOAT, %eax
+	je	.Lcls_retfloat
+	cmpl	$FFI_TYPE_DOUBLE, %eax
+	je	.Lcls_retdouble
+	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
+	je	.Lcls_retldouble
+	cmpl	$FFI_TYPE_SINT64, %eax
+	je	.Lcls_retllong
+	cmpl	$FFI_TYPE_SMALL_STRUCT_1B, %eax
+	je	.Lcls_retstruct1b
+	cmpl	$FFI_TYPE_SMALL_STRUCT_2B, %eax
+	je	.Lcls_retstruct2b
+	cmpl	$FFI_TYPE_STRUCT, %eax
+	je	.Lcls_retstruct
+.Lcls_epilogue:
+	movl	%ebp, %esp
+	popl	%ebp
+	ret
+.Lcls_retint:
+	movl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+.Lcls_retfloat:
+	flds	(%ecx)
+	jmp	.Lcls_epilogue
+.Lcls_retdouble:
+	fldl	(%ecx)
+	jmp	.Lcls_epilogue
+.Lcls_retldouble:
+	fldt	(%ecx)
+	jmp	.Lcls_epilogue
+.Lcls_retllong:
+	movl	(%ecx), %eax
+	movl	4(%ecx), %edx
+	jmp	.Lcls_epilogue
+.Lcls_retstruct1b:
+	movsbl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+.Lcls_retstruct2b:
+	movswl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+.Lcls_retstruct:
+	movl	%ebp, %esp
+	popl	%ebp
+	ret	$4
+.LFE2:
+	.size	ffi_closure_SYSV, .-ffi_closure_SYSV
+
+#if !FFI_NO_RAW_API
+
+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
+#define CIF_FLAGS_OFFSET 20
+
+	.align	4
+FFI_HIDDEN (ffi_closure_raw_SYSV)
+.globl ffi_closure_raw_SYSV
+	.type	ffi_closure_raw_SYSV, @function
+
+ffi_closure_raw_SYSV:
+.LFB3:
+	pushl	%ebp
+.LCFI4:
+	movl	%esp, %ebp
+.LCFI5:
+	pushl	%esi
+.LCFI6:
+	subl	$36, %esp
+	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
+	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
+	movl	%edx, 12(%esp)	/* user_data */
+	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
+	movl	%edx, 8(%esp)	/* raw_args */
+	leal	-24(%ebp), %edx
+	movl	%edx, 4(%esp)	/* &res */
+	movl	%esi, (%esp)	/* cif */
+	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
+	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
+	cmpl	$FFI_TYPE_INT, %eax
+	je	.Lrcls_retint
+
+	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
+	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
+	cmpl	$FFI_TYPE_UINT64, %eax
+	jge	0f
+	cmpl	$FFI_TYPE_UINT8, %eax
+	jge	.Lrcls_retint
+0:
+	cmpl	$FFI_TYPE_FLOAT, %eax
+	je	.Lrcls_retfloat
+	cmpl	$FFI_TYPE_DOUBLE, %eax
+	je	.Lrcls_retdouble
+	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
+	je	.Lrcls_retldouble
+	cmpl	$FFI_TYPE_SINT64, %eax
+	je	.Lrcls_retllong
+.Lrcls_epilogue:
+	addl	$36, %esp
+	popl	%esi
+	popl	%ebp
+	ret
+.Lrcls_retint:
+	movl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+.Lrcls_retfloat:
+	flds	-24(%ebp)
+	jmp	.Lrcls_epilogue
+.Lrcls_retdouble:
+	fldl	-24(%ebp)
+	jmp	.Lrcls_epilogue
+.Lrcls_retldouble:
+	fldt	-24(%ebp)
+	jmp	.Lrcls_epilogue
+.Lrcls_retllong:
+	movl	-24(%ebp), %eax
+	movl	-20(%ebp), %edx
+	jmp	.Lrcls_epilogue
+.LFE3:
+	.size	ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV
+#endif
+
+	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
+.LSCIE1:
+	.long	0x0	/* CIE Identifier Tag */
+	.byte	0x1	/* CIE Version */
+#ifdef __PIC__
+	.ascii "zR\0"	/* CIE Augmentation */
+#else
+	.ascii "\0"	/* CIE Augmentation */
+#endif
+	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
+	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
+	.byte	0x8	/* CIE RA Column */
+#ifdef __PIC__
+	.byte	0x1	/* .uleb128 0x1; Augmentation size */
+	.byte	0x1b	/* FDE Encoding (pcrel sdata4) */
+#endif
+	.byte	0xc	/* DW_CFA_def_cfa */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x88	/* DW_CFA_offset, column 0x8 */
+	.byte	0x1	/* .uleb128 0x1 */
+	.align 4
+.LECIE1:
+.LSFDE1:
+	.long	.LEFDE1-.LASFDE1	/* FDE Length */
+.LASFDE1:
+	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
+#ifdef __PIC__
+	.long	.LFB1-.	/* FDE initial location */
+#else
+	.long	.LFB1	/* FDE initial location */
+#endif
+	.long	.LFE1-.LFB1	/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI0-.LFB1
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 */
+	.byte	0x2	/* .uleb128 0x2 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI1-.LCFI0
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0x5	/* .uleb128 0x5 */
+	.align 4
+.LEFDE1:
+.LSFDE2:
+	.long	.LEFDE2-.LASFDE2	/* FDE Length */
+.LASFDE2:
+	.long	.LASFDE2-.Lframe1	/* FDE CIE offset */
+#ifdef __PIC__
+	.long	.LFB2-.	/* FDE initial location */
+#else
+	.long	.LFB2
+#endif
+	.long	.LFE2-.LFB2	/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI2-.LFB2
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 */
+	.byte	0x2	/* .uleb128 0x2 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI3-.LCFI2
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0x5	/* .uleb128 0x5 */
+#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI7-.LCFI3
+	.byte	0x83	/* DW_CFA_offset, column 0x3 */
+	.byte	0xa	/* .uleb128 0xa */
+#endif
+	.align 4
+.LEFDE2:
+
+#if !FFI_NO_RAW_API
+
+.LSFDE3:
+	.long	.LEFDE3-.LASFDE3	/* FDE Length */
+.LASFDE3:
+	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
+#ifdef __PIC__
+	.long	.LFB3-.	/* FDE initial location */
+#else
+	.long	.LFB3
+#endif
+	.long	.LFE3-.LFB3	/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI4-.LFB3
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 */
+	.byte	0x2	/* .uleb128 0x2 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI5-.LCFI4
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0x5	/* .uleb128 0x5 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI6-.LCFI5
+	.byte	0x86	/* DW_CFA_offset, column 0x6 */
+	.byte	0x3	/* .uleb128 0x3 */
+	.align 4
+.LEFDE3:
+
+#endif
+
+#endif /* ifndef __x86_64__ */
diff --git a/third_party/gofrontend/libffi/src/x86/sysv.S b/third_party/gofrontend/libffi/src/x86/sysv.S
new file mode 100644
index 0000000..f108dd8
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/sysv.S
@@ -0,0 +1,468 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 1996, 1998, 2001-2003, 2005, 2008, 2010  Red Hat, Inc.
+   
+   X86 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef __x86_64__
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+
+.globl ffi_prep_args
+
+	.align 4
+.globl ffi_call_SYSV
+        .type    ffi_call_SYSV,@function
+
+ffi_call_SYSV:
+.LFB1:
+        pushl %ebp
+.LCFI0:
+        movl  %esp,%ebp
+.LCFI1:
+	/* Make room for all of the new args.  */
+	movl  16(%ebp),%ecx
+	subl  %ecx,%esp
+
+        /* Align the stack pointer to 16-bytes */
+        andl  $0xfffffff0, %esp
+
+	movl  %esp,%eax
+
+	/* Place all of the ffi_prep_args in position  */
+	pushl 12(%ebp)
+	pushl %eax
+	call  *8(%ebp)
+
+	/* Return stack to previous state and call the function  */
+	addl  $8,%esp	
+
+	call  *28(%ebp)
+
+	/* Load %ecx with the return type code  */
+	movl  20(%ebp),%ecx	
+
+	/* Protect %esi.  We're going to pop it in the epilogue.  */
+	pushl %esi
+
+	/* If the return value pointer is NULL, assume no return value.  */
+	cmpl  $0,24(%ebp)
+	jne  0f
+
+	/* Even if there is no space for the return value, we are 
+	   obliged to handle floating-point values.  */
+	cmpl  $FFI_TYPE_FLOAT,%ecx
+	jne   noretval
+	fstp  %st(0)
+
+        jmp   epilogue
+
+0:
+	call  1f
+
+.Lstore_table:
+	.long	noretval-.Lstore_table	/* FFI_TYPE_VOID */
+	.long	retint-.Lstore_table	/* FFI_TYPE_INT */
+	.long	retfloat-.Lstore_table	/* FFI_TYPE_FLOAT */
+	.long	retdouble-.Lstore_table	/* FFI_TYPE_DOUBLE */
+	.long	retlongdouble-.Lstore_table	/* FFI_TYPE_LONGDOUBLE */
+	.long	retuint8-.Lstore_table	/* FFI_TYPE_UINT8 */
+	.long	retsint8-.Lstore_table	/* FFI_TYPE_SINT8 */
+	.long	retuint16-.Lstore_table	/* FFI_TYPE_UINT16 */
+	.long	retsint16-.Lstore_table	/* FFI_TYPE_SINT16 */
+	.long	retint-.Lstore_table	/* FFI_TYPE_UINT32 */
+	.long	retint-.Lstore_table	/* FFI_TYPE_SINT32 */
+	.long	retint64-.Lstore_table	/* FFI_TYPE_UINT64 */
+	.long	retint64-.Lstore_table	/* FFI_TYPE_SINT64 */
+	.long	retstruct-.Lstore_table	/* FFI_TYPE_STRUCT */
+	.long	retint-.Lstore_table	/* FFI_TYPE_POINTER */
+
+1:
+	pop  %esi
+	add  (%esi, %ecx, 4), %esi
+	jmp  *%esi
+
+	/* Sign/zero extend as appropriate.  */
+retsint8:
+	movsbl  %al, %eax
+	jmp  retint
+
+retsint16:
+	movswl  %ax, %eax
+	jmp  retint
+
+retuint8:
+	movzbl  %al, %eax
+	jmp  retint
+
+retuint16:
+	movzwl  %ax, %eax
+	jmp  retint
+
+retfloat:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	fstps (%ecx)
+	jmp   epilogue
+
+retdouble:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	fstpl (%ecx)
+	jmp   epilogue
+
+retlongdouble:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	fstpt (%ecx)
+	jmp   epilogue
+	
+retint64:	
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	movl  %eax,0(%ecx)
+	movl  %edx,4(%ecx)
+	jmp   epilogue
+	
+retint:
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	movl  %eax,0(%ecx)
+
+retstruct:
+	/* Nothing to do!  */
+
+noretval:
+epilogue:
+        popl %esi
+        movl %ebp,%esp
+        popl %ebp
+        ret
+.LFE1:
+.ffi_call_SYSV_end:
+        .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+
+	.align	4
+FFI_HIDDEN (ffi_closure_SYSV)
+.globl ffi_closure_SYSV
+	.type	ffi_closure_SYSV, @function
+
+ffi_closure_SYSV:
+.LFB2:
+	pushl	%ebp
+.LCFI2:
+	movl	%esp, %ebp
+.LCFI3:
+	subl	$40, %esp
+	leal	-24(%ebp), %edx
+	movl	%edx, -12(%ebp)	/* resp */
+	leal	8(%ebp), %edx
+	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
+	leal	-12(%ebp), %edx
+	movl	%edx, (%esp)	/* &resp */
+#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__
+	call	ffi_closure_SYSV_inner
+#else
+	movl	%ebx, 8(%esp)
+.LCFI7:
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	call	ffi_closure_SYSV_inner@PLT
+	movl	8(%esp), %ebx
+#endif
+	movl	-12(%ebp), %ecx
+	cmpl	$FFI_TYPE_INT, %eax
+	je	.Lcls_retint
+
+	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
+	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
+	cmpl	$FFI_TYPE_UINT64, %eax
+	jge	0f
+	cmpl	$FFI_TYPE_UINT8, %eax
+	jge	.Lcls_retint
+	
+0:	cmpl	$FFI_TYPE_FLOAT, %eax
+	je	.Lcls_retfloat
+	cmpl	$FFI_TYPE_DOUBLE, %eax
+	je	.Lcls_retdouble
+	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
+	je	.Lcls_retldouble
+	cmpl	$FFI_TYPE_SINT64, %eax
+	je	.Lcls_retllong
+	cmpl	$FFI_TYPE_STRUCT, %eax
+	je	.Lcls_retstruct
+.Lcls_epilogue:
+	movl	%ebp, %esp
+	popl	%ebp
+	ret
+.Lcls_retint:
+	movl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+.Lcls_retfloat:
+	flds	(%ecx)
+	jmp	.Lcls_epilogue
+.Lcls_retdouble:
+	fldl	(%ecx)
+	jmp	.Lcls_epilogue
+.Lcls_retldouble:
+	fldt	(%ecx)
+	jmp	.Lcls_epilogue
+.Lcls_retllong:
+	movl	(%ecx), %eax
+	movl	4(%ecx), %edx
+	jmp	.Lcls_epilogue
+.Lcls_retstruct:
+	movl	%ebp, %esp
+	popl	%ebp
+	ret	$4
+.LFE2:
+	.size	ffi_closure_SYSV, .-ffi_closure_SYSV
+
+#if !FFI_NO_RAW_API
+
+/* Precalculate for e.g. the Solaris 10/x86 assembler.  */
+#if FFI_TRAMPOLINE_SIZE == 10
+#define RAW_CLOSURE_CIF_OFFSET 12
+#define RAW_CLOSURE_FUN_OFFSET 16
+#define RAW_CLOSURE_USER_DATA_OFFSET 20
+#elif FFI_TRAMPOLINE_SIZE == 24
+#define RAW_CLOSURE_CIF_OFFSET 24
+#define RAW_CLOSURE_FUN_OFFSET 28
+#define RAW_CLOSURE_USER_DATA_OFFSET 32
+#else
+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
+#endif
+#define CIF_FLAGS_OFFSET 20
+
+	.align	4
+FFI_HIDDEN (ffi_closure_raw_SYSV)
+.globl ffi_closure_raw_SYSV
+	.type	ffi_closure_raw_SYSV, @function
+
+ffi_closure_raw_SYSV:
+.LFB3:
+	pushl	%ebp
+.LCFI4:
+	movl	%esp, %ebp
+.LCFI5:
+	pushl	%esi
+.LCFI6:
+	subl	$36, %esp
+	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
+	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
+	movl	%edx, 12(%esp)	/* user_data */
+	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
+	movl	%edx, 8(%esp)	/* raw_args */
+	leal	-24(%ebp), %edx
+	movl	%edx, 4(%esp)	/* &res */
+	movl	%esi, (%esp)	/* cif */
+	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
+	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
+	cmpl	$FFI_TYPE_INT, %eax
+	je	.Lrcls_retint
+
+	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
+	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
+	cmpl	$FFI_TYPE_UINT64, %eax
+	jge	0f
+	cmpl	$FFI_TYPE_UINT8, %eax
+	jge	.Lrcls_retint
+0:
+	cmpl	$FFI_TYPE_FLOAT, %eax
+	je	.Lrcls_retfloat
+	cmpl	$FFI_TYPE_DOUBLE, %eax
+	je	.Lrcls_retdouble
+	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
+	je	.Lrcls_retldouble
+	cmpl	$FFI_TYPE_SINT64, %eax
+	je	.Lrcls_retllong
+.Lrcls_epilogue:
+	addl	$36, %esp
+	popl	%esi
+	popl	%ebp
+	ret
+.Lrcls_retint:
+	movl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+.Lrcls_retfloat:
+	flds	-24(%ebp)
+	jmp	.Lrcls_epilogue
+.Lrcls_retdouble:
+	fldl	-24(%ebp)
+	jmp	.Lrcls_epilogue
+.Lrcls_retldouble:
+	fldt	-24(%ebp)
+	jmp	.Lrcls_epilogue
+.Lrcls_retllong:
+	movl	-24(%ebp), %eax
+	movl	-20(%ebp), %edx
+	jmp	.Lrcls_epilogue
+.LFE3:
+	.size	ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV
+#endif
+
+#if defined __PIC__
+# if defined __sun__ && defined __svr4__
+/* 32-bit Solaris 2/x86 uses datarel encoding for PIC.  GNU ld before 2.22
+   doesn't correctly sort .eh_frame_hdr with mixed encodings, so match this.  */
+#  define FDE_ENCODING		0x30	/* datarel */
+#  define FDE_ENCODE(X)		X@GOTOFF
+# else
+#  define FDE_ENCODING		0x1b	/* pcrel sdata4 */
+#  if defined HAVE_AS_X86_PCREL
+#   define FDE_ENCODE(X)	X-.
+#  else
+#   define FDE_ENCODE(X)	X@rel
+#  endif
+# endif
+#else
+# define FDE_ENCODING		0	/* absolute */
+# define FDE_ENCODE(X)		X
+#endif
+
+	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
+.LSCIE1:
+	.long	0x0	/* CIE Identifier Tag */
+	.byte	0x1	/* CIE Version */
+#ifdef HAVE_AS_ASCII_PSEUDO_OP
+#ifdef __PIC__
+	.ascii "zR\0"	/* CIE Augmentation */
+#else
+	.ascii "\0"	/* CIE Augmentation */
+#endif
+#elif defined HAVE_AS_STRING_PSEUDO_OP
+#ifdef __PIC__
+	.string "zR"	/* CIE Augmentation */
+#else
+	.string ""	/* CIE Augmentation */
+#endif
+#else
+#error missing .ascii/.string
+#endif
+	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
+	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
+	.byte	0x8	/* CIE RA Column */
+#ifdef __PIC__
+	.byte	0x1	/* .uleb128 0x1; Augmentation size */
+	.byte	FDE_ENCODING
+#endif
+	.byte	0xc	/* DW_CFA_def_cfa */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x88	/* DW_CFA_offset, column 0x8 */
+	.byte	0x1	/* .uleb128 0x1 */
+	.align 4
+.LECIE1:
+.LSFDE1:
+	.long	.LEFDE1-.LASFDE1	/* FDE Length */
+.LASFDE1:
+	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
+	.long	FDE_ENCODE(.LFB1)	/* FDE initial location */
+	.long	.LFE1-.LFB1		/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI0-.LFB1
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 */
+	.byte	0x2	/* .uleb128 0x2 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI1-.LCFI0
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0x5	/* .uleb128 0x5 */
+	.align 4
+.LEFDE1:
+.LSFDE2:
+	.long	.LEFDE2-.LASFDE2	/* FDE Length */
+.LASFDE2:
+	.long	.LASFDE2-.Lframe1	/* FDE CIE offset */
+	.long	FDE_ENCODE(.LFB2)	/* FDE initial location */
+	.long	.LFE2-.LFB2		/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI2-.LFB2
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 */
+	.byte	0x2	/* .uleb128 0x2 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI3-.LCFI2
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0x5	/* .uleb128 0x5 */
+#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI7-.LCFI3
+	.byte	0x83	/* DW_CFA_offset, column 0x3 */
+	.byte	0xa	/* .uleb128 0xa */
+#endif
+	.align 4
+.LEFDE2:
+
+#if !FFI_NO_RAW_API
+
+.LSFDE3:
+	.long	.LEFDE3-.LASFDE3	/* FDE Length */
+.LASFDE3:
+	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
+	.long	FDE_ENCODE(.LFB3)	/* FDE initial location */
+	.long	.LFE3-.LFB3		/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI4-.LFB3
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 */
+	.byte	0x2	/* .uleb128 0x2 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI5-.LCFI4
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0x5	/* .uleb128 0x5 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI6-.LCFI5
+	.byte	0x86	/* DW_CFA_offset, column 0x6 */
+	.byte	0x3	/* .uleb128 0x3 */
+	.align 4
+.LEFDE3:
+
+#endif
+
+#endif /* ifndef __x86_64__ */
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/x86/unix64.S b/third_party/gofrontend/libffi/src/x86/unix64.S
new file mode 100644
index 0000000..7a6619a
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/unix64.S
@@ -0,0 +1,426 @@
+/* -----------------------------------------------------------------------
+   unix64.S - Copyright (c) 2002  Bo Thorsen <bo@suse.de>
+	      Copyright (c) 2008  Red Hat, Inc
+
+   x86-64 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifdef __x86_64__
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+
+/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
+	            void *raddr, void (*fnaddr)(void));
+
+   Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
+   for this function.  This has been allocated by ffi_call.  We also
+   deallocate some of the stack that has been alloca'd.  */
+
+	.align	2
+	.globl	ffi_call_unix64
+	.type	ffi_call_unix64,@function
+
+ffi_call_unix64:
+.LUW0:
+	movq	(%rsp), %r10		/* Load return address.  */
+	leaq	(%rdi, %rsi), %rax	/* Find local stack base.  */
+	movq	%rdx, (%rax)		/* Save flags.  */
+	movq	%rcx, 8(%rax)		/* Save raddr.  */
+	movq	%rbp, 16(%rax)		/* Save old frame pointer.  */
+	movq	%r10, 24(%rax)		/* Relocate return address.  */
+	movq	%rax, %rbp		/* Finalize local stack frame.  */
+.LUW1:
+	movq	%rdi, %r10		/* Save a copy of the register area. */
+	movq	%r8, %r11		/* Save a copy of the target fn.  */
+	movl	%r9d, %eax		/* Set number of SSE registers.  */
+
+	/* Load up all argument registers.  */
+	movq	(%r10), %rdi
+	movq	8(%r10), %rsi
+	movq	16(%r10), %rdx
+	movq	24(%r10), %rcx
+	movq	32(%r10), %r8
+	movq	40(%r10), %r9
+	testl	%eax, %eax
+	jnz	.Lload_sse
+.Lret_from_load_sse:
+
+	/* Deallocate the reg arg area.  */
+	leaq	176(%r10), %rsp
+
+	/* Call the user function.  */
+	call	*%r11
+
+	/* Deallocate stack arg area; local stack frame in redzone.  */
+	leaq	24(%rbp), %rsp
+
+	movq	0(%rbp), %rcx		/* Reload flags.  */
+	movq	8(%rbp), %rdi		/* Reload raddr.  */
+	movq	16(%rbp), %rbp		/* Reload old frame pointer.  */
+.LUW2:
+
+	/* The first byte of the flags contains the FFI_TYPE.  */
+	movzbl	%cl, %r10d
+	leaq	.Lstore_table(%rip), %r11
+	movslq	(%r11, %r10, 4), %r10
+	addq	%r11, %r10
+	jmp	*%r10
+
+.Lstore_table:
+	.long	.Lst_void-.Lstore_table		/* FFI_TYPE_VOID */
+	.long	.Lst_sint32-.Lstore_table	/* FFI_TYPE_INT */
+	.long	.Lst_float-.Lstore_table	/* FFI_TYPE_FLOAT */
+	.long	.Lst_double-.Lstore_table	/* FFI_TYPE_DOUBLE */
+	.long	.Lst_ldouble-.Lstore_table	/* FFI_TYPE_LONGDOUBLE */
+	.long	.Lst_uint8-.Lstore_table	/* FFI_TYPE_UINT8 */
+	.long	.Lst_sint8-.Lstore_table	/* FFI_TYPE_SINT8 */
+	.long	.Lst_uint16-.Lstore_table	/* FFI_TYPE_UINT16 */
+	.long	.Lst_sint16-.Lstore_table	/* FFI_TYPE_SINT16 */
+	.long	.Lst_uint32-.Lstore_table	/* FFI_TYPE_UINT32 */
+	.long	.Lst_sint32-.Lstore_table	/* FFI_TYPE_SINT32 */
+	.long	.Lst_int64-.Lstore_table	/* FFI_TYPE_UINT64 */
+	.long	.Lst_int64-.Lstore_table	/* FFI_TYPE_SINT64 */
+	.long	.Lst_struct-.Lstore_table	/* FFI_TYPE_STRUCT */
+	.long	.Lst_int64-.Lstore_table	/* FFI_TYPE_POINTER */
+
+	.align 2
+.Lst_void:
+	ret
+	.align 2
+
+.Lst_uint8:
+	movzbq	%al, %rax
+	movq	%rax, (%rdi)
+	ret
+	.align 2
+.Lst_sint8:
+	movsbq	%al, %rax
+	movq	%rax, (%rdi)
+	ret
+	.align 2
+.Lst_uint16:
+	movzwq	%ax, %rax
+	movq	%rax, (%rdi)
+	.align 2
+.Lst_sint16:
+	movswq	%ax, %rax
+	movq	%rax, (%rdi)
+	ret
+	.align 2
+.Lst_uint32:
+	movl	%eax, %eax
+	movq	%rax, (%rdi)
+	.align 2
+.Lst_sint32:
+	cltq
+	movq	%rax, (%rdi)
+	ret
+	.align 2
+.Lst_int64:
+	movq	%rax, (%rdi)
+	ret
+
+	.align 2
+.Lst_float:
+	movss	%xmm0, (%rdi)
+	ret
+	.align 2
+.Lst_double:
+	movsd	%xmm0, (%rdi)
+	ret
+.Lst_ldouble:
+	fstpt	(%rdi)
+	ret
+
+	.align 2
+.Lst_struct:
+	leaq	-20(%rsp), %rsi		/* Scratch area in redzone.  */
+
+	/* We have to locate the values now, and since we don't want to
+	   write too much data into the user's return value, we spill the
+	   value to a 16 byte scratch area first.  Bits 8, 9, and 10
+	   control where the values are located.  Only one of the three
+	   bits will be set; see ffi_prep_cif_machdep for the pattern.  */
+	movd	%xmm0, %r10
+	movd	%xmm1, %r11
+	testl	$0x100, %ecx
+	cmovnz	%rax, %rdx
+	cmovnz	%r10, %rax
+	testl	$0x200, %ecx
+	cmovnz	%r10, %rdx
+	testl	$0x400, %ecx
+	cmovnz	%r10, %rax
+	cmovnz	%r11, %rdx
+	movq	%rax, (%rsi)
+	movq	%rdx, 8(%rsi)
+
+	/* Bits 12-31 contain the true size of the structure.  Copy from
+	   the scratch area to the true destination.  */
+	shrl	$12, %ecx
+	rep movsb
+	ret
+
+	/* Many times we can avoid loading any SSE registers at all.
+	   It's not worth an indirect jump to load the exact set of
+	   SSE registers needed; zero or all is a good compromise.  */
+	.align 2
+.LUW3:
+.Lload_sse:
+	movdqa	48(%r10), %xmm0
+	movdqa	64(%r10), %xmm1
+	movdqa	80(%r10), %xmm2
+	movdqa	96(%r10), %xmm3
+	movdqa	112(%r10), %xmm4
+	movdqa	128(%r10), %xmm5
+	movdqa	144(%r10), %xmm6
+	movdqa	160(%r10), %xmm7
+	jmp	.Lret_from_load_sse
+
+.LUW4:
+	.size    ffi_call_unix64,.-ffi_call_unix64
+
+	.align	2
+	.globl ffi_closure_unix64
+	.type	ffi_closure_unix64,@function
+
+ffi_closure_unix64:
+.LUW5:
+	/* The carry flag is set by the trampoline iff SSE registers
+	   are used.  Don't clobber it before the branch instruction.  */
+	leaq    -200(%rsp), %rsp
+.LUW6:
+	movq	%rdi, (%rsp)
+	movq    %rsi, 8(%rsp)
+	movq    %rdx, 16(%rsp)
+	movq    %rcx, 24(%rsp)
+	movq    %r8, 32(%rsp)
+	movq    %r9, 40(%rsp)
+	jc      .Lsave_sse
+.Lret_from_save_sse:
+
+	movq	%r10, %rdi
+	leaq	176(%rsp), %rsi
+	movq	%rsp, %rdx
+	leaq	208(%rsp), %rcx
+	call	ffi_closure_unix64_inner@PLT
+
+	/* Deallocate stack frame early; return value is now in redzone.  */
+	addq	$200, %rsp
+.LUW7:
+
+	/* The first byte of the return value contains the FFI_TYPE.  */
+	movzbl	%al, %r10d
+	leaq	.Lload_table(%rip), %r11
+	movslq	(%r11, %r10, 4), %r10
+	addq	%r11, %r10
+	jmp	*%r10
+
+.Lload_table:
+	.long	.Lld_void-.Lload_table		/* FFI_TYPE_VOID */
+	.long	.Lld_int32-.Lload_table		/* FFI_TYPE_INT */
+	.long	.Lld_float-.Lload_table		/* FFI_TYPE_FLOAT */
+	.long	.Lld_double-.Lload_table	/* FFI_TYPE_DOUBLE */
+	.long	.Lld_ldouble-.Lload_table	/* FFI_TYPE_LONGDOUBLE */
+	.long	.Lld_int8-.Lload_table		/* FFI_TYPE_UINT8 */
+	.long	.Lld_int8-.Lload_table		/* FFI_TYPE_SINT8 */
+	.long	.Lld_int16-.Lload_table		/* FFI_TYPE_UINT16 */
+	.long	.Lld_int16-.Lload_table		/* FFI_TYPE_SINT16 */
+	.long	.Lld_int32-.Lload_table		/* FFI_TYPE_UINT32 */
+	.long	.Lld_int32-.Lload_table		/* FFI_TYPE_SINT32 */
+	.long	.Lld_int64-.Lload_table		/* FFI_TYPE_UINT64 */
+	.long	.Lld_int64-.Lload_table		/* FFI_TYPE_SINT64 */
+	.long	.Lld_struct-.Lload_table	/* FFI_TYPE_STRUCT */
+	.long	.Lld_int64-.Lload_table		/* FFI_TYPE_POINTER */
+
+	.align 2
+.Lld_void:
+	ret
+
+	.align 2
+.Lld_int8:
+	movzbl	-24(%rsp), %eax
+	ret
+	.align 2
+.Lld_int16:
+	movzwl	-24(%rsp), %eax
+	ret
+	.align 2
+.Lld_int32:
+	movl	-24(%rsp), %eax
+	ret
+	.align 2
+.Lld_int64:
+	movq	-24(%rsp), %rax
+	ret
+
+	.align 2
+.Lld_float:
+	movss	-24(%rsp), %xmm0
+	ret
+	.align 2
+.Lld_double:
+	movsd	-24(%rsp), %xmm0
+	ret
+	.align 2
+.Lld_ldouble:
+	fldt	-24(%rsp)
+	ret
+
+	.align 2
+.Lld_struct:
+	/* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
+	   %rax/%xmm0, %xmm0/%xmm1.  We collapse two by always loading
+	   both rdx and xmm1 with the second word.  For the remaining,
+	   bit 8 set means xmm0 gets the second word, and bit 9 means
+	   that rax gets the second word.  */
+	movq	-24(%rsp), %rcx
+	movq	-16(%rsp), %rdx
+	movq	-16(%rsp), %xmm1
+	testl	$0x100, %eax
+	cmovnz	%rdx, %rcx
+	movd	%rcx, %xmm0
+	testl	$0x200, %eax
+	movq	-24(%rsp), %rax
+	cmovnz	%rdx, %rax
+	ret
+
+	/* See the comment above .Lload_sse; the same logic applies here.  */
+	.align 2
+.LUW8:
+.Lsave_sse:
+	movdqa	%xmm0, 48(%rsp)
+	movdqa	%xmm1, 64(%rsp)
+	movdqa	%xmm2, 80(%rsp)
+	movdqa	%xmm3, 96(%rsp)
+	movdqa	%xmm4, 112(%rsp)
+	movdqa	%xmm5, 128(%rsp)
+	movdqa	%xmm6, 144(%rsp)
+	movdqa	%xmm7, 160(%rsp)
+	jmp	.Lret_from_save_sse
+
+.LUW9:
+	.size	ffi_closure_unix64,.-ffi_closure_unix64
+
+#ifdef HAVE_AS_X86_64_UNWIND_SECTION_TYPE
+	.section	.eh_frame,"a",@unwind
+#else
+	.section	.eh_frame,"a",@progbits
+#endif
+.Lframe1:
+	.long	.LECIE1-.LSCIE1		/* CIE Length */
+.LSCIE1:
+	.long	0			/* CIE Identifier Tag */
+	.byte	1			/* CIE Version */
+	.ascii "zR\0"			/* CIE Augmentation */
+	.uleb128 1			/* CIE Code Alignment Factor */
+	.sleb128 -8			/* CIE Data Alignment Factor */
+	.byte	0x10			/* CIE RA Column */
+	.uleb128 1			/* Augmentation size */
+	.byte	0x1b			/* FDE Encoding (pcrel sdata4) */
+	.byte	0xc			/* DW_CFA_def_cfa, %rsp offset 8 */
+	.uleb128 7
+	.uleb128 8
+	.byte	0x80+16			/* DW_CFA_offset, %rip offset 1*-8 */
+	.uleb128 1
+	.align 8
+.LECIE1:
+.LSFDE1:
+	.long	.LEFDE1-.LASFDE1	/* FDE Length */
+.LASFDE1:
+	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
+#if HAVE_AS_X86_PCREL
+	.long	.LUW0-.			/* FDE initial location */
+#else
+	.long	.LUW0@rel
+#endif
+	.long	.LUW4-.LUW0		/* FDE address range */
+	.uleb128 0x0			/* Augmentation size */
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.long	.LUW1-.LUW0
+
+	/* New stack frame based off rbp.  This is a itty bit of unwind
+	   trickery in that the CFA *has* changed.  There is no easy way
+	   to describe it correctly on entry to the function.  Fortunately,
+	   it doesn't matter too much since at all points we can correctly
+	   unwind back to ffi_call.  Note that the location to which we
+	   moved the return address is (the new) CFA-8, so from the
+	   perspective of the unwind info, it hasn't moved.  */
+	.byte	0xc			/* DW_CFA_def_cfa, %rbp offset 32 */
+	.uleb128 6
+	.uleb128 32
+	.byte	0x80+6			/* DW_CFA_offset, %rbp offset 2*-8 */
+	.uleb128 2
+	.byte	0xa			/* DW_CFA_remember_state */
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.long	.LUW2-.LUW1
+	.byte	0xc			/* DW_CFA_def_cfa, %rsp offset 8 */
+	.uleb128 7
+	.uleb128 8
+	.byte	0xc0+6			/* DW_CFA_restore, %rbp */
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.long	.LUW3-.LUW2
+	.byte	0xb			/* DW_CFA_restore_state */
+
+	.align 8
+.LEFDE1:
+.LSFDE3:
+	.long	.LEFDE3-.LASFDE3	/* FDE Length */
+.LASFDE3:
+	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
+#if HAVE_AS_X86_PCREL
+	.long	.LUW5-.			/* FDE initial location */
+#else
+	.long	.LUW5@rel
+#endif
+	.long	.LUW9-.LUW5		/* FDE address range */
+	.uleb128 0x0			/* Augmentation size */
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.long	.LUW6-.LUW5
+	.byte	0xe			/* DW_CFA_def_cfa_offset */
+	.uleb128 208
+	.byte	0xa			/* DW_CFA_remember_state */
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.long	.LUW7-.LUW6
+	.byte	0xe			/* DW_CFA_def_cfa_offset */
+	.uleb128 8
+
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.long	.LUW8-.LUW7
+	.byte	0xb			/* DW_CFA_restore_state */
+
+	.align 8
+.LEFDE3:
+
+#endif /* __x86_64__ */
+
+#if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libffi/src/x86/win32.S b/third_party/gofrontend/libffi/src/x86/win32.S
new file mode 100644
index 0000000..24b7bbd
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/win32.S
@@ -0,0 +1,1201 @@
+/* -----------------------------------------------------------------------
+   win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009  Red Hat, Inc.
+	     Copyright (c) 2001  John Beniton
+	     Copyright (c) 2002  Ranjit Mathew
+	     Copyright (c) 2009  Daniel Witte
+			
+ 
+   X86 Foreign Function Interface
+ 
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+ 
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+ 
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   -----------------------------------------------------------------------
+   */
+ 
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+#ifdef _MSC_VER
+
+.386
+.MODEL FLAT, C
+
+EXTRN ffi_closure_SYSV_inner:NEAR
+
+_TEXT SEGMENT
+
+ffi_call_win32 PROC NEAR,
+    ffi_prep_args : NEAR PTR DWORD,
+    ecif          : NEAR PTR DWORD,
+    cif_abi       : DWORD,
+    cif_bytes     : DWORD,
+    cif_flags     : DWORD,
+    rvalue        : NEAR PTR DWORD,
+    fn            : NEAR PTR DWORD
+
+        ;; Make room for all of the new args.
+        mov  ecx, cif_bytes
+        sub  esp, ecx
+
+        mov  eax, esp
+
+        ;; Place all of the ffi_prep_args in position
+        push ecif
+        push eax
+        call ffi_prep_args
+
+        ;; Return stack to previous state and call the function
+        add  esp, 8
+
+	;; Handle thiscall and fastcall
+	cmp cif_abi, 3 ;; FFI_THISCALL
+	jz do_thiscall
+	cmp cif_abi, 4 ;; FFI_FASTCALL
+	jnz do_stdcall
+	mov ecx, DWORD PTR [esp]
+	mov edx, DWORD PTR [esp+4]
+	add esp, 8
+	jmp do_stdcall
+do_thiscall:
+	mov ecx, DWORD PTR [esp]
+	add esp, 4
+do_stdcall:
+        call fn
+
+        ;; cdecl:   we restore esp in the epilogue, so there's no need to
+        ;;          remove the space we pushed for the args.
+        ;; stdcall: the callee has already cleaned the stack.
+
+        ;; Load ecx with the return type code
+        mov  ecx, cif_flags
+
+        ;; If the return value pointer is NULL, assume no return value.
+        cmp  rvalue, 0
+        jne  ca_jumptable
+
+        ;; Even if there is no space for the return value, we are
+        ;; obliged to handle floating-point values.
+        cmp  ecx, FFI_TYPE_FLOAT
+        jne  ca_epilogue
+        fstp st(0)
+
+        jmp  ca_epilogue
+
+ca_jumptable:
+        jmp  [ca_jumpdata + 4 * ecx]
+ca_jumpdata:
+        ;; Do not insert anything here between label and jump table.
+        dd offset ca_epilogue       ;; FFI_TYPE_VOID
+        dd offset ca_retint         ;; FFI_TYPE_INT
+        dd offset ca_retfloat       ;; FFI_TYPE_FLOAT
+        dd offset ca_retdouble      ;; FFI_TYPE_DOUBLE
+        dd offset ca_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
+        dd offset ca_retuint8       ;; FFI_TYPE_UINT8
+        dd offset ca_retsint8       ;; FFI_TYPE_SINT8
+        dd offset ca_retuint16      ;; FFI_TYPE_UINT16
+        dd offset ca_retsint16      ;; FFI_TYPE_SINT16
+        dd offset ca_retint         ;; FFI_TYPE_UINT32
+        dd offset ca_retint         ;; FFI_TYPE_SINT32
+        dd offset ca_retint64       ;; FFI_TYPE_UINT64
+        dd offset ca_retint64       ;; FFI_TYPE_SINT64
+        dd offset ca_epilogue       ;; FFI_TYPE_STRUCT
+        dd offset ca_retint         ;; FFI_TYPE_POINTER
+        dd offset ca_retstruct1b    ;; FFI_TYPE_SMALL_STRUCT_1B
+        dd offset ca_retstruct2b    ;; FFI_TYPE_SMALL_STRUCT_2B
+        dd offset ca_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
+        dd offset ca_epilogue       ;; FFI_TYPE_MS_STRUCT
+
+        /* Sign/zero extend as appropriate.  */
+ca_retuint8:
+        movzx eax, al
+        jmp   ca_retint
+
+ca_retsint8:
+        movsx eax, al
+        jmp   ca_retint
+
+ca_retuint16:
+        movzx eax, ax
+        jmp   ca_retint
+
+ca_retsint16:
+        movsx eax, ax
+        jmp   ca_retint
+
+ca_retint:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        mov   [ecx + 0], eax
+        jmp   ca_epilogue
+
+ca_retint64:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        mov   [ecx + 0], eax
+        mov   [ecx + 4], edx
+        jmp   ca_epilogue
+
+ca_retfloat:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        fstp  DWORD PTR [ecx]
+        jmp   ca_epilogue
+
+ca_retdouble:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        fstp  QWORD PTR [ecx]
+        jmp   ca_epilogue
+
+ca_retlongdouble:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        fstp  TBYTE PTR [ecx]
+        jmp   ca_epilogue
+
+ca_retstruct1b:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        mov   [ecx + 0], al
+        jmp   ca_epilogue
+
+ca_retstruct2b:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        mov   [ecx + 0], ax
+        jmp   ca_epilogue
+
+ca_epilogue:
+        ;; Epilogue code is autogenerated.
+        ret
+ffi_call_win32 ENDP
+
+ffi_closure_THISCALL PROC NEAR FORCEFRAME
+	sub	esp, 40
+	lea	edx, [ebp -24]
+	mov	[ebp - 12], edx	/* resp */
+	lea	edx, [ebp + 12]  /* account for stub return address on stack */
+	jmp	stub
+ffi_closure_THISCALL ENDP
+
+ffi_closure_SYSV PROC NEAR FORCEFRAME
+    ;; the ffi_closure ctx is passed in eax by the trampoline.
+
+        sub  esp, 40
+        lea  edx, [ebp - 24]
+        mov  [ebp - 12], edx         ;; resp
+        lea  edx, [ebp + 8]
+stub::
+        mov  [esp + 8], edx          ;; args
+        lea  edx, [ebp - 12]
+        mov  [esp + 4], edx          ;; &resp
+        mov  [esp], eax              ;; closure
+        call ffi_closure_SYSV_inner
+        mov  ecx, [ebp - 12]
+
+cs_jumptable:
+        jmp  [cs_jumpdata + 4 * eax]
+cs_jumpdata:
+        ;; Do not insert anything here between the label and jump table.
+        dd offset cs_epilogue       ;; FFI_TYPE_VOID
+        dd offset cs_retint         ;; FFI_TYPE_INT
+        dd offset cs_retfloat       ;; FFI_TYPE_FLOAT
+        dd offset cs_retdouble      ;; FFI_TYPE_DOUBLE
+        dd offset cs_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
+        dd offset cs_retuint8       ;; FFI_TYPE_UINT8
+        dd offset cs_retsint8       ;; FFI_TYPE_SINT8
+        dd offset cs_retuint16      ;; FFI_TYPE_UINT16
+        dd offset cs_retsint16      ;; FFI_TYPE_SINT16
+        dd offset cs_retint         ;; FFI_TYPE_UINT32
+        dd offset cs_retint         ;; FFI_TYPE_SINT32
+        dd offset cs_retint64       ;; FFI_TYPE_UINT64
+        dd offset cs_retint64       ;; FFI_TYPE_SINT64
+        dd offset cs_retstruct      ;; FFI_TYPE_STRUCT
+        dd offset cs_retint         ;; FFI_TYPE_POINTER
+        dd offset cs_retsint8       ;; FFI_TYPE_SMALL_STRUCT_1B
+        dd offset cs_retsint16      ;; FFI_TYPE_SMALL_STRUCT_2B
+        dd offset cs_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
+        dd offset cs_retmsstruct    ;; FFI_TYPE_MS_STRUCT
+
+cs_retuint8:
+        movzx eax, BYTE PTR [ecx]
+        jmp   cs_epilogue
+
+cs_retsint8:
+        movsx eax, BYTE PTR [ecx]
+        jmp   cs_epilogue
+
+cs_retuint16:
+        movzx eax, WORD PTR [ecx]
+        jmp   cs_epilogue
+
+cs_retsint16:
+        movsx eax, WORD PTR [ecx]
+        jmp   cs_epilogue
+
+cs_retint:
+        mov   eax, [ecx]
+        jmp   cs_epilogue
+
+cs_retint64:
+        mov   eax, [ecx + 0]
+        mov   edx, [ecx + 4]
+        jmp   cs_epilogue
+
+cs_retfloat:
+        fld   DWORD PTR [ecx]
+        jmp   cs_epilogue
+
+cs_retdouble:
+        fld   QWORD PTR [ecx]
+        jmp   cs_epilogue
+
+cs_retlongdouble:
+        fld   TBYTE PTR [ecx]
+        jmp   cs_epilogue
+
+cs_retstruct:
+        ;; Caller expects us to pop struct return value pointer hidden arg.
+        ;; Epilogue code is autogenerated.
+        ret	4
+
+cs_retmsstruct:
+        ;; Caller expects us to return a pointer to the real return value.
+        mov   eax, ecx
+        ;; Caller doesn't expects us to pop struct return value pointer hidden arg.
+        jmp   cs_epilogue
+
+cs_epilogue:
+        ;; Epilogue code is autogenerated.
+        ret
+ffi_closure_SYSV ENDP
+
+#if !FFI_NO_RAW_API
+
+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
+#define CIF_FLAGS_OFFSET 20
+
+ffi_closure_raw_THISCALL PROC NEAR USES esi FORCEFRAME
+	sub esp, 36
+	mov  esi, [eax + RAW_CLOSURE_CIF_OFFSET]        ;; closure->cif
+	mov  edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET]  ;; closure->user_data
+	mov [esp + 12], edx
+	lea edx, [ebp + 12]
+	jmp stubraw
+ffi_closure_raw_THISCALL ENDP
+
+ffi_closure_raw_SYSV PROC NEAR USES esi FORCEFRAME
+    ;; the ffi_closure ctx is passed in eax by the trampoline.
+
+        sub  esp, 40
+        mov  esi, [eax + RAW_CLOSURE_CIF_OFFSET]        ;; closure->cif
+        mov  edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET]  ;; closure->user_data
+        mov  [esp + 12], edx                            ;; user_data
+        lea  edx, [ebp + 8]
+stubraw::
+        mov  [esp + 8], edx                             ;; raw_args
+        lea  edx, [ebp - 24]
+        mov  [esp + 4], edx                             ;; &res
+        mov  [esp], esi                                 ;; cif
+        call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET]   ;; closure->fun
+        mov  eax, [esi + CIF_FLAGS_OFFSET]              ;; cif->flags
+        lea  ecx, [ebp - 24]
+
+cr_jumptable:
+        jmp  [cr_jumpdata + 4 * eax]
+cr_jumpdata:
+        ;; Do not insert anything here between the label and jump table.
+        dd offset cr_epilogue       ;; FFI_TYPE_VOID
+        dd offset cr_retint         ;; FFI_TYPE_INT
+        dd offset cr_retfloat       ;; FFI_TYPE_FLOAT
+        dd offset cr_retdouble      ;; FFI_TYPE_DOUBLE
+        dd offset cr_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
+        dd offset cr_retuint8       ;; FFI_TYPE_UINT8
+        dd offset cr_retsint8       ;; FFI_TYPE_SINT8
+        dd offset cr_retuint16      ;; FFI_TYPE_UINT16
+        dd offset cr_retsint16      ;; FFI_TYPE_SINT16
+        dd offset cr_retint         ;; FFI_TYPE_UINT32
+        dd offset cr_retint         ;; FFI_TYPE_SINT32
+        dd offset cr_retint64       ;; FFI_TYPE_UINT64
+        dd offset cr_retint64       ;; FFI_TYPE_SINT64
+        dd offset cr_epilogue       ;; FFI_TYPE_STRUCT
+        dd offset cr_retint         ;; FFI_TYPE_POINTER
+        dd offset cr_retsint8       ;; FFI_TYPE_SMALL_STRUCT_1B
+        dd offset cr_retsint16      ;; FFI_TYPE_SMALL_STRUCT_2B
+        dd offset cr_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
+        dd offset cr_epilogue       ;; FFI_TYPE_MS_STRUCT
+
+cr_retuint8:
+        movzx eax, BYTE PTR [ecx]
+        jmp   cr_epilogue
+
+cr_retsint8:
+        movsx eax, BYTE PTR [ecx]
+        jmp   cr_epilogue
+
+cr_retuint16:
+        movzx eax, WORD PTR [ecx]
+        jmp   cr_epilogue
+
+cr_retsint16:
+        movsx eax, WORD PTR [ecx]
+        jmp   cr_epilogue
+
+cr_retint:
+        mov   eax, [ecx]
+        jmp   cr_epilogue
+
+cr_retint64:
+        mov   eax, [ecx + 0]
+        mov   edx, [ecx + 4]
+        jmp   cr_epilogue
+
+cr_retfloat:
+        fld   DWORD PTR [ecx]
+        jmp   cr_epilogue
+
+cr_retdouble:
+        fld   QWORD PTR [ecx]
+        jmp   cr_epilogue
+
+cr_retlongdouble:
+        fld   TBYTE PTR [ecx]
+        jmp   cr_epilogue
+
+cr_epilogue:
+        ;; Epilogue code is autogenerated.
+        ret
+ffi_closure_raw_SYSV ENDP
+
+#endif /* !FFI_NO_RAW_API */
+
+ffi_closure_STDCALL PROC NEAR FORCEFRAME
+    ;; the ffi_closure ctx is passed in eax by the trampoline.
+
+        sub  esp, 40
+        lea  edx, [ebp - 24]
+        mov  [ebp - 12], edx         ;; resp
+        lea  edx, [ebp + 12]         ;; account for stub return address on stack
+        mov  [esp + 8], edx          ;; args
+        lea  edx, [ebp - 12]
+        mov  [esp + 4], edx          ;; &resp
+        mov  [esp], eax              ;; closure
+        call ffi_closure_SYSV_inner
+        mov  ecx, [ebp - 12]
+
+cd_jumptable:
+        jmp  [cd_jumpdata + 4 * eax]
+cd_jumpdata:
+        ;; Do not insert anything here between the label and jump table.
+        dd offset cd_epilogue       ;; FFI_TYPE_VOID
+        dd offset cd_retint         ;; FFI_TYPE_INT
+        dd offset cd_retfloat       ;; FFI_TYPE_FLOAT
+        dd offset cd_retdouble      ;; FFI_TYPE_DOUBLE
+        dd offset cd_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
+        dd offset cd_retuint8       ;; FFI_TYPE_UINT8
+        dd offset cd_retsint8       ;; FFI_TYPE_SINT8
+        dd offset cd_retuint16      ;; FFI_TYPE_UINT16
+        dd offset cd_retsint16      ;; FFI_TYPE_SINT16
+        dd offset cd_retint         ;; FFI_TYPE_UINT32
+        dd offset cd_retint         ;; FFI_TYPE_SINT32
+        dd offset cd_retint64       ;; FFI_TYPE_UINT64
+        dd offset cd_retint64       ;; FFI_TYPE_SINT64
+        dd offset cd_epilogue       ;; FFI_TYPE_STRUCT
+        dd offset cd_retint         ;; FFI_TYPE_POINTER
+        dd offset cd_retsint8       ;; FFI_TYPE_SMALL_STRUCT_1B
+        dd offset cd_retsint16      ;; FFI_TYPE_SMALL_STRUCT_2B
+        dd offset cd_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
+
+cd_retuint8:
+        movzx eax, BYTE PTR [ecx]
+        jmp   cd_epilogue
+
+cd_retsint8:
+        movsx eax, BYTE PTR [ecx]
+        jmp   cd_epilogue
+
+cd_retuint16:
+        movzx eax, WORD PTR [ecx]
+        jmp   cd_epilogue
+
+cd_retsint16:
+        movsx eax, WORD PTR [ecx]
+        jmp   cd_epilogue
+
+cd_retint:
+        mov   eax, [ecx]
+        jmp   cd_epilogue
+
+cd_retint64:
+        mov   eax, [ecx + 0]
+        mov   edx, [ecx + 4]
+        jmp   cd_epilogue
+
+cd_retfloat:
+        fld   DWORD PTR [ecx]
+        jmp   cd_epilogue
+
+cd_retdouble:
+        fld   QWORD PTR [ecx]
+        jmp   cd_epilogue
+
+cd_retlongdouble:
+        fld   TBYTE PTR [ecx]
+        jmp   cd_epilogue
+
+cd_epilogue:
+        ;; Epilogue code is autogenerated.
+        ret
+ffi_closure_STDCALL ENDP
+
+_TEXT ENDS
+END
+
+#else
+
+	.text
+ 
+        # This assumes we are using gas.
+        .balign 16
+	.globl	_ffi_call_win32
+#ifndef __OS2__
+	.def	_ffi_call_win32;	.scl	2;	.type	32;	.endef
+#endif
+_ffi_call_win32:
+.LFB1:
+        pushl %ebp
+.LCFI0:
+        movl  %esp,%ebp
+.LCFI1:
+        # Make room for all of the new args.
+        movl  20(%ebp),%ecx                                                     
+        subl  %ecx,%esp
+ 
+        movl  %esp,%eax
+ 
+        # Place all of the ffi_prep_args in position
+        pushl 12(%ebp)
+        pushl %eax
+        call  *8(%ebp)
+ 
+        # Return stack to previous state and call the function
+        addl  $8,%esp
+
+	# Handle fastcall and thiscall
+	cmpl $3, 16(%ebp)  # FFI_THISCALL
+	jz .do_thiscall
+	cmpl $4, 16(%ebp) # FFI_FASTCALL
+	jnz .do_fncall
+	movl (%esp), %ecx
+	movl 4(%esp), %edx
+	addl $8, %esp
+	jmp .do_fncall
+.do_thiscall:
+	movl (%esp), %ecx
+	addl $4, %esp
+
+.do_fncall:
+	 
+        # FIXME: Align the stack to a 128-bit boundary to avoid
+        # potential performance hits.
+
+        call  *32(%ebp)
+ 
+        # stdcall functions pop arguments off the stack themselves
+
+        # Load %ecx with the return type code
+        movl  24(%ebp),%ecx
+ 
+        # If the return value pointer is NULL, assume no return value.
+        cmpl  $0,28(%ebp)
+        jne   0f
+ 
+        # Even if there is no space for the return value, we are
+        # obliged to handle floating-point values.
+        cmpl  $FFI_TYPE_FLOAT,%ecx
+        jne   .Lnoretval
+        fstp  %st(0)
+ 
+        jmp   .Lepilogue
+
+0:
+	call	1f
+	# Do not insert anything here between the call and the jump table.
+.Lstore_table:
+	.long	.Lnoretval		/* FFI_TYPE_VOID */
+	.long	.Lretint		/* FFI_TYPE_INT */
+	.long	.Lretfloat		/* FFI_TYPE_FLOAT */
+	.long	.Lretdouble		/* FFI_TYPE_DOUBLE */
+	.long	.Lretlongdouble		/* FFI_TYPE_LONGDOUBLE */
+	.long	.Lretuint8		/* FFI_TYPE_UINT8 */
+	.long	.Lretsint8		/* FFI_TYPE_SINT8 */
+	.long	.Lretuint16		/* FFI_TYPE_UINT16 */
+	.long	.Lretsint16		/* FFI_TYPE_SINT16 */
+	.long	.Lretint		/* FFI_TYPE_UINT32 */
+	.long	.Lretint		/* FFI_TYPE_SINT32 */
+	.long	.Lretint64		/* FFI_TYPE_UINT64 */
+	.long	.Lretint64		/* FFI_TYPE_SINT64 */
+	.long	.Lretstruct		/* FFI_TYPE_STRUCT */
+	.long	.Lretint		/* FFI_TYPE_POINTER */
+	.long	.Lretstruct1b		/* FFI_TYPE_SMALL_STRUCT_1B */
+	.long	.Lretstruct2b		/* FFI_TYPE_SMALL_STRUCT_2B */
+	.long	.Lretstruct4b		/* FFI_TYPE_SMALL_STRUCT_4B */
+	.long	.Lretstruct		/* FFI_TYPE_MS_STRUCT */
+1:
+	add	%ecx, %ecx
+	add	%ecx, %ecx
+	add	(%esp),%ecx
+	add	$4, %esp
+	jmp	*(%ecx)
+
+	/* Sign/zero extend as appropriate.  */
+.Lretsint8:
+	movsbl	%al, %eax
+	jmp	.Lretint
+
+.Lretsint16:
+	movswl	%ax, %eax
+	jmp	.Lretint
+
+.Lretuint8:
+	movzbl	%al, %eax
+	jmp	.Lretint
+
+.Lretuint16:
+	movzwl	%ax, %eax
+	jmp	.Lretint
+
+.Lretint:
+        # Load %ecx with the pointer to storage for the return value
+        movl  28(%ebp),%ecx
+        movl  %eax,0(%ecx)
+        jmp   .Lepilogue
+ 
+.Lretfloat:
+         # Load %ecx with the pointer to storage for the return value
+        movl  28(%ebp),%ecx
+        fstps (%ecx)
+        jmp   .Lepilogue
+ 
+.Lretdouble:
+        # Load %ecx with the pointer to storage for the return value
+        movl  28(%ebp),%ecx
+        fstpl (%ecx)
+        jmp   .Lepilogue
+ 
+.Lretlongdouble:
+        # Load %ecx with the pointer to storage for the return value
+        movl  28(%ebp),%ecx
+        fstpt (%ecx)
+        jmp   .Lepilogue
+ 
+.Lretint64:
+        # Load %ecx with the pointer to storage for the return value
+        movl  28(%ebp),%ecx
+        movl  %eax,0(%ecx)
+        movl  %edx,4(%ecx)
+	jmp   .Lepilogue
+
+.Lretstruct1b:
+        # Load %ecx with the pointer to storage for the return value
+        movl  28(%ebp),%ecx
+        movb  %al,0(%ecx)
+        jmp   .Lepilogue
+ 
+.Lretstruct2b:
+        # Load %ecx with the pointer to storage for the return value
+        movl  28(%ebp),%ecx
+        movw  %ax,0(%ecx)
+        jmp   .Lepilogue
+
+.Lretstruct4b:
+        # Load %ecx with the pointer to storage for the return value
+        movl  28(%ebp),%ecx
+        movl  %eax,0(%ecx)
+        jmp   .Lepilogue
+
+.Lretstruct:
+        # Nothing to do!
+ 
+.Lnoretval:
+.Lepilogue:
+        movl %ebp,%esp
+        popl %ebp
+        ret
+.ffi_call_win32_end:
+        .balign 16
+	.globl	_ffi_closure_THISCALL
+#ifndef __OS2__
+	.def	_ffi_closure_THISCALL;	.scl	2;	.type	32;	.endef
+#endif
+_ffi_closure_THISCALL:
+	pushl	%ebp
+	movl	%esp, %ebp
+	subl	$40, %esp
+	leal	-24(%ebp), %edx
+	movl	%edx, -12(%ebp)	/* resp */
+	leal	12(%ebp), %edx  /* account for stub return address on stack */
+	jmp	.stub
+.LFE1:
+
+        # This assumes we are using gas.
+        .balign 16
+	.globl	_ffi_closure_SYSV
+#ifndef __OS2__
+	.def	_ffi_closure_SYSV;	.scl	2;	.type	32;	.endef
+#endif
+_ffi_closure_SYSV:
+.LFB3:
+	pushl	%ebp
+.LCFI4:
+	movl	%esp, %ebp
+.LCFI5:
+	subl	$40, %esp
+	leal	-24(%ebp), %edx
+	movl	%edx, -12(%ebp)	/* resp */
+	leal	8(%ebp), %edx
+.stub:
+	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
+	leal	-12(%ebp), %edx
+	movl	%edx, (%esp)	/* &resp */
+	call	_ffi_closure_SYSV_inner
+	movl	-12(%ebp), %ecx
+
+0:
+	call	1f
+	# Do not insert anything here between the call and the jump table.
+.Lcls_store_table:
+	.long	.Lcls_noretval		/* FFI_TYPE_VOID */
+	.long	.Lcls_retint		/* FFI_TYPE_INT */
+	.long	.Lcls_retfloat		/* FFI_TYPE_FLOAT */
+	.long	.Lcls_retdouble		/* FFI_TYPE_DOUBLE */
+	.long	.Lcls_retldouble	/* FFI_TYPE_LONGDOUBLE */
+	.long	.Lcls_retuint8		/* FFI_TYPE_UINT8 */
+	.long	.Lcls_retsint8		/* FFI_TYPE_SINT8 */
+	.long	.Lcls_retuint16		/* FFI_TYPE_UINT16 */
+	.long	.Lcls_retsint16		/* FFI_TYPE_SINT16 */
+	.long	.Lcls_retint		/* FFI_TYPE_UINT32 */
+	.long	.Lcls_retint		/* FFI_TYPE_SINT32 */
+	.long	.Lcls_retllong		/* FFI_TYPE_UINT64 */
+	.long	.Lcls_retllong		/* FFI_TYPE_SINT64 */
+	.long	.Lcls_retstruct		/* FFI_TYPE_STRUCT */
+	.long	.Lcls_retint		/* FFI_TYPE_POINTER */
+	.long	.Lcls_retstruct1	/* FFI_TYPE_SMALL_STRUCT_1B */
+	.long	.Lcls_retstruct2	/* FFI_TYPE_SMALL_STRUCT_2B */
+	.long	.Lcls_retstruct4	/* FFI_TYPE_SMALL_STRUCT_4B */
+	.long	.Lcls_retmsstruct	/* FFI_TYPE_MS_STRUCT */
+
+1:
+	add	%eax, %eax
+	add	%eax, %eax
+	add	(%esp),%eax
+	add	$4, %esp
+	jmp	*(%eax)
+
+	/* Sign/zero extend as appropriate.  */
+.Lcls_retsint8:
+	movsbl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+
+.Lcls_retsint16:
+	movswl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+
+.Lcls_retuint8:
+	movzbl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+
+.Lcls_retuint16:
+	movzwl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+
+.Lcls_retint:
+	movl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+
+.Lcls_retfloat:
+	flds	(%ecx)
+	jmp	.Lcls_epilogue
+
+.Lcls_retdouble:
+	fldl	(%ecx)
+	jmp	.Lcls_epilogue
+
+.Lcls_retldouble:
+	fldt	(%ecx)
+	jmp	.Lcls_epilogue
+
+.Lcls_retllong:
+	movl	(%ecx), %eax
+	movl	4(%ecx), %edx
+	jmp	.Lcls_epilogue
+
+.Lcls_retstruct1:
+	movsbl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+
+.Lcls_retstruct2:
+	movswl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+
+.Lcls_retstruct4:
+	movl	(%ecx), %eax
+	jmp	.Lcls_epilogue
+
+.Lcls_retstruct:
+        # Caller expects us to pop struct return value pointer hidden arg.
+	movl	%ebp, %esp
+	popl	%ebp
+	ret	$0x4
+
+.Lcls_retmsstruct:
+	# Caller expects us to return a pointer to the real return value.
+	mov	%ecx, %eax
+	# Caller doesn't expects us to pop struct return value pointer hidden arg.
+	jmp	.Lcls_epilogue
+
+.Lcls_noretval:
+.Lcls_epilogue:
+	movl	%ebp, %esp
+	popl	%ebp
+	ret
+.ffi_closure_SYSV_end:
+.LFE3:
+
+#if !FFI_NO_RAW_API
+
+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
+#define CIF_FLAGS_OFFSET 20
+        .balign 16
+	.globl	_ffi_closure_raw_THISCALL
+#ifndef __OS2__
+	.def	_ffi_closure_raw_THISCALL;	.scl	2;	.type	32;	.endef
+#endif
+_ffi_closure_raw_THISCALL:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%esi
+	subl	$36, %esp
+	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
+	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
+	movl	%edx, 12(%esp)	/* user_data */
+	leal	12(%ebp), %edx	/* __builtin_dwarf_cfa () */
+	jmp	.stubraw
+        # This assumes we are using gas.
+        .balign 16
+	.globl	_ffi_closure_raw_SYSV
+#ifndef __OS2__
+	.def	_ffi_closure_raw_SYSV;	.scl	2;	.type	32;	.endef
+#endif
+_ffi_closure_raw_SYSV:
+.LFB4:
+	pushl	%ebp
+.LCFI6:
+	movl	%esp, %ebp
+.LCFI7:
+	pushl	%esi
+.LCFI8:
+	subl	$36, %esp
+	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
+	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
+	movl	%edx, 12(%esp)	/* user_data */
+	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
+.stubraw:
+	movl	%edx, 8(%esp)	/* raw_args */
+	leal	-24(%ebp), %edx
+	movl	%edx, 4(%esp)	/* &res */
+	movl	%esi, (%esp)	/* cif */
+	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
+	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
+0:
+	call	1f
+	# Do not insert anything here between the call and the jump table.
+.Lrcls_store_table:
+	.long	.Lrcls_noretval		/* FFI_TYPE_VOID */
+	.long	.Lrcls_retint		/* FFI_TYPE_INT */
+	.long	.Lrcls_retfloat		/* FFI_TYPE_FLOAT */
+	.long	.Lrcls_retdouble	/* FFI_TYPE_DOUBLE */
+	.long	.Lrcls_retldouble	/* FFI_TYPE_LONGDOUBLE */
+	.long	.Lrcls_retuint8		/* FFI_TYPE_UINT8 */
+	.long	.Lrcls_retsint8		/* FFI_TYPE_SINT8 */
+	.long	.Lrcls_retuint16	/* FFI_TYPE_UINT16 */
+	.long	.Lrcls_retsint16	/* FFI_TYPE_SINT16 */
+	.long	.Lrcls_retint		/* FFI_TYPE_UINT32 */
+	.long	.Lrcls_retint		/* FFI_TYPE_SINT32 */
+	.long	.Lrcls_retllong		/* FFI_TYPE_UINT64 */
+	.long	.Lrcls_retllong		/* FFI_TYPE_SINT64 */
+	.long	.Lrcls_retstruct	/* FFI_TYPE_STRUCT */
+	.long	.Lrcls_retint		/* FFI_TYPE_POINTER */
+	.long	.Lrcls_retstruct1	/* FFI_TYPE_SMALL_STRUCT_1B */
+	.long	.Lrcls_retstruct2	/* FFI_TYPE_SMALL_STRUCT_2B */
+	.long	.Lrcls_retstruct4	/* FFI_TYPE_SMALL_STRUCT_4B */
+	.long	.Lrcls_retstruct	/* FFI_TYPE_MS_STRUCT */
+1:
+	add	%eax, %eax
+	add	%eax, %eax
+	add	(%esp),%eax
+	add	$4, %esp
+	jmp	*(%eax)
+
+	/* Sign/zero extend as appropriate.  */
+.Lrcls_retsint8:
+	movsbl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retsint16:
+	movswl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retuint8:
+	movzbl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retuint16:
+	movzwl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retint:
+	movl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retfloat:
+	flds	-24(%ebp)
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retdouble:
+	fldl	-24(%ebp)
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retldouble:
+	fldt	-24(%ebp)
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retllong:
+	movl	-24(%ebp), %eax
+	movl	-20(%ebp), %edx
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retstruct1:
+	movsbl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retstruct2:
+	movswl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retstruct4:
+	movl	-24(%ebp), %eax
+	jmp	.Lrcls_epilogue
+
+.Lrcls_retstruct:
+	# Nothing to do!
+
+.Lrcls_noretval:
+.Lrcls_epilogue:
+	addl	$36, %esp
+	popl	%esi
+	popl	%ebp
+	ret
+.ffi_closure_raw_SYSV_end:
+.LFE4:
+
+#endif /* !FFI_NO_RAW_API */
+
+        # This assumes we are using gas.
+	.balign	16
+	.globl	_ffi_closure_STDCALL
+#ifndef __OS2__
+	.def	_ffi_closure_STDCALL;	.scl	2;	.type	32;	.endef
+#endif
+_ffi_closure_STDCALL:
+.LFB5:
+	pushl	%ebp
+.LCFI9:
+	movl	%esp, %ebp
+.LCFI10:
+	subl	$40, %esp
+	leal	-24(%ebp), %edx
+	movl	%edx, -12(%ebp)	/* resp */
+	leal	12(%ebp), %edx  /* account for stub return address on stack */
+	movl	%edx, 4(%esp)	/* args */
+	leal	-12(%ebp), %edx
+	movl	%edx, (%esp)	/* &resp */
+	call	_ffi_closure_SYSV_inner
+	movl	-12(%ebp), %ecx
+0:
+	call	1f
+	# Do not insert anything here between the call and the jump table.
+.Lscls_store_table:
+	.long	.Lscls_noretval		/* FFI_TYPE_VOID */
+	.long	.Lscls_retint		/* FFI_TYPE_INT */
+	.long	.Lscls_retfloat		/* FFI_TYPE_FLOAT */
+	.long	.Lscls_retdouble	/* FFI_TYPE_DOUBLE */
+	.long	.Lscls_retldouble	/* FFI_TYPE_LONGDOUBLE */
+	.long	.Lscls_retuint8		/* FFI_TYPE_UINT8 */
+	.long	.Lscls_retsint8		/* FFI_TYPE_SINT8 */
+	.long	.Lscls_retuint16	/* FFI_TYPE_UINT16 */
+	.long	.Lscls_retsint16	/* FFI_TYPE_SINT16 */
+	.long	.Lscls_retint		/* FFI_TYPE_UINT32 */
+	.long	.Lscls_retint		/* FFI_TYPE_SINT32 */
+	.long	.Lscls_retllong		/* FFI_TYPE_UINT64 */
+	.long	.Lscls_retllong		/* FFI_TYPE_SINT64 */
+	.long	.Lscls_retstruct	/* FFI_TYPE_STRUCT */
+	.long	.Lscls_retint		/* FFI_TYPE_POINTER */
+	.long	.Lscls_retstruct1	/* FFI_TYPE_SMALL_STRUCT_1B */
+	.long	.Lscls_retstruct2	/* FFI_TYPE_SMALL_STRUCT_2B */
+	.long	.Lscls_retstruct4	/* FFI_TYPE_SMALL_STRUCT_4B */
+1:
+	add	%eax, %eax
+	add	%eax, %eax
+	add	(%esp),%eax
+	add	$4, %esp
+	jmp	*(%eax)
+
+	/* Sign/zero extend as appropriate.  */
+.Lscls_retsint8:
+	movsbl	(%ecx), %eax
+	jmp	.Lscls_epilogue
+
+.Lscls_retsint16:
+	movswl	(%ecx), %eax
+	jmp	.Lscls_epilogue
+
+.Lscls_retuint8:
+	movzbl	(%ecx), %eax
+	jmp	.Lscls_epilogue
+
+.Lscls_retuint16:
+	movzwl	(%ecx), %eax
+	jmp	.Lscls_epilogue
+
+.Lscls_retint:
+	movl	(%ecx), %eax
+	jmp	.Lscls_epilogue
+
+.Lscls_retfloat:
+	flds	(%ecx)
+	jmp	.Lscls_epilogue
+
+.Lscls_retdouble:
+	fldl	(%ecx)
+	jmp	.Lscls_epilogue
+
+.Lscls_retldouble:
+	fldt	(%ecx)
+	jmp	.Lscls_epilogue
+
+.Lscls_retllong:
+	movl	(%ecx), %eax
+	movl	4(%ecx), %edx
+	jmp	.Lscls_epilogue
+
+.Lscls_retstruct1:
+	movsbl	(%ecx), %eax
+	jmp	.Lscls_epilogue
+
+.Lscls_retstruct2:
+	movswl	(%ecx), %eax
+	jmp	.Lscls_epilogue
+
+.Lscls_retstruct4:
+	movl	(%ecx), %eax
+	jmp	.Lscls_epilogue
+
+.Lscls_retstruct:
+	# Nothing to do!
+
+.Lscls_noretval:
+.Lscls_epilogue:
+	movl	%ebp, %esp
+	popl	%ebp
+	ret
+.ffi_closure_STDCALL_end:
+.LFE5:
+
+#ifndef __OS2__
+	.section	.eh_frame,"w"
+#endif
+.Lframe1:
+.LSCIE1:
+	.long	.LECIE1-.LASCIE1  /* Length of Common Information Entry */
+.LASCIE1:
+	.long	0x0	/* CIE Identifier Tag */
+	.byte	0x1	/* CIE Version */
+#ifdef __PIC__
+	.ascii "zR\0"	/* CIE Augmentation */
+#else
+	.ascii "\0"	/* CIE Augmentation */
+#endif
+	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
+	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
+	.byte	0x8	/* CIE RA Column */
+#ifdef __PIC__
+	.byte	0x1	/* .uleb128 0x1; Augmentation size */
+	.byte	0x1b	/* FDE Encoding (pcrel sdata4) */
+#endif
+	.byte	0xc	/* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x88	/* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */
+	.byte	0x1	/* .uleb128 0x1 */
+	.align 4
+.LECIE1:
+
+.LSFDE1:
+	.long	.LEFDE1-.LASFDE1	/* FDE Length */
+.LASFDE1:
+	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
+#if defined __PIC__ && defined HAVE_AS_X86_PCREL
+	.long	.LFB1-.	/* FDE initial location */
+#else
+	.long	.LFB1
+#endif
+	.long	.LFE1-.LFB1	/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	/* DW_CFA_xxx CFI instructions go here.  */
+
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI0-.LFB1
+	.byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
+	.byte	0x2	/* .uleb128 0x2 */
+
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI1-.LCFI0
+	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
+	.byte	0x5	/* .uleb128 0x5 */
+
+	/* End of DW_CFA_xxx CFI instructions.  */
+	.align 4
+.LEFDE1:
+
+
+.LSFDE3:
+	.long	.LEFDE3-.LASFDE3	/* FDE Length */
+.LASFDE3:
+	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
+#if defined __PIC__ && defined HAVE_AS_X86_PCREL
+	.long	.LFB3-.	/* FDE initial location */
+#else
+	.long	.LFB3
+#endif
+	.long	.LFE3-.LFB3	/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	/* DW_CFA_xxx CFI instructions go here.  */
+
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI4-.LFB3
+	.byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
+	.byte	0x2	/* .uleb128 0x2 */
+
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI5-.LCFI4
+	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
+	.byte	0x5	/* .uleb128 0x5 */
+
+	/* End of DW_CFA_xxx CFI instructions.  */
+	.align 4
+.LEFDE3:
+
+#if !FFI_NO_RAW_API
+
+.LSFDE4:
+	.long	.LEFDE4-.LASFDE4	/* FDE Length */
+.LASFDE4:
+	.long	.LASFDE4-.Lframe1	/* FDE CIE offset */
+#if defined __PIC__ && defined HAVE_AS_X86_PCREL
+	.long	.LFB4-.	/* FDE initial location */
+#else
+	.long	.LFB4
+#endif
+	.long	.LFE4-.LFB4	/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	/* DW_CFA_xxx CFI instructions go here.  */
+
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI6-.LFB4
+	.byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
+	.byte	0x2	/* .uleb128 0x2 */
+
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI7-.LCFI6
+	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
+	.byte	0x5	/* .uleb128 0x5 */
+
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI8-.LCFI7
+	.byte	0x86	/* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */
+	.byte	0x3	/* .uleb128 0x3 */
+
+	/* End of DW_CFA_xxx CFI instructions.  */
+	.align 4
+.LEFDE4:
+
+#endif /* !FFI_NO_RAW_API */
+
+.LSFDE5:
+	.long	.LEFDE5-.LASFDE5	/* FDE Length */
+.LASFDE5:
+	.long	.LASFDE5-.Lframe1	/* FDE CIE offset */
+#if defined __PIC__ && defined HAVE_AS_X86_PCREL
+	.long	.LFB5-.	/* FDE initial location */
+#else
+	.long	.LFB5
+#endif
+	.long	.LFE5-.LFB5	/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	/* DW_CFA_xxx CFI instructions go here.  */
+
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI9-.LFB5
+	.byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
+	.byte	0x2	/* .uleb128 0x2 */
+
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI10-.LCFI9
+	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
+	.byte	0x5	/* .uleb128 0x5 */
+
+	/* End of DW_CFA_xxx CFI instructions.  */
+	.align 4
+.LEFDE5:
+
+#endif /* !_MSC_VER */
+
diff --git a/third_party/gofrontend/libffi/src/x86/win64.S b/third_party/gofrontend/libffi/src/x86/win64.S
new file mode 100644
index 0000000..687f97c
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/win64.S
@@ -0,0 +1,520 @@
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+/* Constants for ffi_call_win64 */
+#define STACK 0
+#define PREP_ARGS_FN 32
+#define ECIF 40
+#define CIF_BYTES 48
+#define CIF_FLAGS 56
+#define RVALUE 64
+#define FN 72
+
+/* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *),
+		   extended_cif *ecif, unsigned bytes, unsigned flags,
+		   unsigned *rvalue, void (*fn)());
+ */
+
+#ifdef _MSC_VER
+PUBLIC	ffi_call_win64
+
+EXTRN	__chkstk:NEAR
+EXTRN	ffi_closure_win64_inner:NEAR
+
+_TEXT	SEGMENT
+
+;;; ffi_closure_win64 will be called with these registers set:
+;;;    rax points to 'closure'
+;;;    r11 contains a bit mask that specifies which of the
+;;;    first four parameters are float or double
+;;;
+;;; It must move the parameters passed in registers to their stack location,
+;;; call ffi_closure_win64_inner for the actual work, then return the result.
+;;;
+ffi_closure_win64 PROC FRAME
+	;; copy register arguments onto stack
+	test	r11, 1
+	jne	first_is_float
+	mov	QWORD PTR [rsp+8], rcx
+	jmp	second
+first_is_float:
+	movlpd	QWORD PTR [rsp+8], xmm0
+
+second:
+	test	r11, 2
+	jne	second_is_float
+	mov	QWORD PTR [rsp+16], rdx
+	jmp	third
+second_is_float:
+	movlpd	QWORD PTR [rsp+16], xmm1
+
+third:
+	test	r11, 4
+	jne	third_is_float
+	mov	QWORD PTR [rsp+24], r8
+	jmp	fourth
+third_is_float:
+	movlpd	QWORD PTR [rsp+24], xmm2
+
+fourth:
+	test	r11, 8
+	jne	fourth_is_float
+	mov	QWORD PTR [rsp+32], r9
+	jmp	done
+fourth_is_float:
+	movlpd	QWORD PTR [rsp+32], xmm3
+
+done:
+	.ALLOCSTACK 40
+	sub	rsp, 40
+	.ENDPROLOG
+	mov	rcx, rax	; context is first parameter
+	mov	rdx, rsp	; stack is second parameter
+	add	rdx, 48		; point to start of arguments
+	mov	rax, ffi_closure_win64_inner
+	call	rax		; call the real closure function
+	add	rsp, 40
+	movd	xmm0, rax	; If the closure returned a float,
+				; ffi_closure_win64_inner wrote it to rax
+	ret	0
+ffi_closure_win64 ENDP
+
+ffi_call_win64 PROC FRAME
+	;; copy registers onto stack
+	mov	QWORD PTR [rsp+32], r9
+	mov	QWORD PTR [rsp+24], r8
+	mov	QWORD PTR [rsp+16], rdx
+	mov	QWORD PTR [rsp+8], rcx
+	.PUSHREG rbp
+	push	rbp
+	.ALLOCSTACK 48
+	sub	rsp, 48					; 00000030H
+	.SETFRAME rbp, 32
+	lea	rbp, QWORD PTR [rsp+32]
+	.ENDPROLOG
+
+	mov	eax, DWORD PTR CIF_BYTES[rbp]
+	add	rax, 15
+	and	rax, -16
+	call	__chkstk
+	sub	rsp, rax
+	lea	rax, QWORD PTR [rsp+32]
+	mov	QWORD PTR STACK[rbp], rax
+
+	mov	rdx, QWORD PTR ECIF[rbp]
+	mov	rcx, QWORD PTR STACK[rbp]
+	call	QWORD PTR PREP_ARGS_FN[rbp]
+
+	mov	rsp, QWORD PTR STACK[rbp]
+
+	movlpd	xmm3, QWORD PTR [rsp+24]
+	movd	r9, xmm3
+
+	movlpd	xmm2, QWORD PTR [rsp+16]
+	movd	r8, xmm2
+
+	movlpd	xmm1, QWORD PTR [rsp+8]
+	movd	rdx, xmm1
+
+	movlpd	xmm0, QWORD PTR [rsp]
+	movd	rcx, xmm0
+
+	call	QWORD PTR FN[rbp]
+ret_struct4b$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B
+ 	jne	ret_struct2b$
+
+	mov	rcx, QWORD PTR RVALUE[rbp]
+	mov	DWORD PTR [rcx], eax
+	jmp	ret_void$
+
+ret_struct2b$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B
+ 	jne	ret_struct1b$
+
+	mov	rcx, QWORD PTR RVALUE[rbp]
+	mov	WORD PTR [rcx], ax
+	jmp	ret_void$
+
+ret_struct1b$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B
+ 	jne	ret_uint8$
+
+	mov	rcx, QWORD PTR RVALUE[rbp]
+	mov	BYTE PTR [rcx], al
+	jmp	ret_void$
+
+ret_uint8$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8
+ 	jne	ret_sint8$
+
+	mov	rcx, QWORD PTR RVALUE[rbp]
+	movzx   rax, al
+	mov	QWORD PTR [rcx], rax
+	jmp	ret_void$
+
+ret_sint8$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8
+ 	jne	ret_uint16$
+
+	mov	rcx, QWORD PTR RVALUE[rbp]
+	movsx   rax, al
+	mov	QWORD PTR [rcx], rax
+	jmp	ret_void$
+
+ret_uint16$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16
+ 	jne	ret_sint16$
+
+	mov	rcx, QWORD PTR RVALUE[rbp]
+	movzx   rax, ax
+	mov	QWORD PTR [rcx], rax
+	jmp	SHORT ret_void$
+
+ret_sint16$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16
+ 	jne	ret_uint32$
+
+	mov	rcx, QWORD PTR RVALUE[rbp]
+	movsx   rax, ax
+	mov	QWORD PTR [rcx], rax
+	jmp	SHORT ret_void$
+
+ret_uint32$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32
+ 	jne	ret_sint32$
+
+	mov	rcx, QWORD PTR RVALUE[rbp]
+	mov     eax, eax
+	mov	QWORD PTR [rcx], rax
+	jmp	SHORT ret_void$
+
+ret_sint32$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32
+ 	jne	ret_float$
+
+	mov	rcx, QWORD PTR RVALUE[rbp]
+	cdqe
+	mov	QWORD PTR [rcx], rax
+	jmp	SHORT ret_void$
+
+ret_float$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT
+ 	jne	SHORT ret_double$
+
+ 	mov	rax, QWORD PTR RVALUE[rbp]
+ 	movss	DWORD PTR [rax], xmm0
+ 	jmp	SHORT ret_void$
+
+ret_double$:
+ 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE
+ 	jne	SHORT ret_uint64$
+
+ 	mov	rax, QWORD PTR RVALUE[rbp]
+ 	movlpd	QWORD PTR [rax], xmm0
+ 	jmp	SHORT ret_void$
+
+ret_uint64$:
+  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT64
+  	jne	SHORT ret_sint64$
+
+ 	mov	rcx, QWORD PTR RVALUE[rbp]
+ 	mov	QWORD PTR [rcx], rax
+ 	jmp	SHORT ret_void$
+
+ret_sint64$:
+  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64
+  	jne	SHORT ret_pointer$
+
+ 	mov	rcx, QWORD PTR RVALUE[rbp]
+ 	mov	QWORD PTR [rcx], rax
+ 	jmp	SHORT ret_void$
+
+ret_pointer$:
+  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_POINTER
+  	jne	SHORT ret_int$
+
+ 	mov	rcx, QWORD PTR RVALUE[rbp]
+ 	mov	QWORD PTR [rcx], rax
+ 	jmp	SHORT ret_void$
+
+ret_int$:
+  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_INT
+  	jne	SHORT ret_void$
+
+	mov	rcx, QWORD PTR RVALUE[rbp]
+	cdqe
+	mov	QWORD PTR [rcx], rax
+ 	jmp	SHORT ret_void$
+
+ret_void$:
+	xor	rax, rax
+
+	lea	rsp, QWORD PTR [rbp+16]
+	pop	rbp
+	ret	0
+ffi_call_win64 ENDP
+_TEXT	ENDS
+END
+
+#else
+
+#ifdef SYMBOL_UNDERSCORE
+#define SYMBOL_NAME(name) _##name
+#else
+#define SYMBOL_NAME(name) name
+#endif
+
+.text
+
+.extern SYMBOL_NAME(ffi_closure_win64_inner)
+
+# ffi_closure_win64 will be called with these registers set:
+#    rax points to 'closure'
+#    r11 contains a bit mask that specifies which of the
+#    first four parameters are float or double
+#
+# It must move the parameters passed in registers to their stack location,
+# call ffi_closure_win64_inner for the actual work, then return the result.
+#
+	.balign 16
+	.globl SYMBOL_NAME(ffi_closure_win64)
+	.seh_proc SYMBOL_NAME(ffi_closure_win64)
+SYMBOL_NAME(ffi_closure_win64):
+	# copy register arguments onto stack
+	test	$1,%r11
+	jne	.Lfirst_is_float
+	mov	%rcx, 8(%rsp)
+	jmp	.Lsecond
+.Lfirst_is_float:
+	movlpd	%xmm0, 8(%rsp)
+
+.Lsecond:
+	test	$2, %r11
+	jne	.Lsecond_is_float
+	mov	%rdx, 16(%rsp)
+	jmp	.Lthird
+.Lsecond_is_float:
+	movlpd	%xmm1, 16(%rsp)
+
+.Lthird:
+	test	$4, %r11
+	jne	.Lthird_is_float
+	mov	%r8,24(%rsp)
+	jmp	.Lfourth
+.Lthird_is_float:
+	movlpd	%xmm2, 24(%rsp)
+
+.Lfourth:
+	test	$8, %r11
+	jne	.Lfourth_is_float
+	mov	%r9, 32(%rsp)
+	jmp	.Ldone
+.Lfourth_is_float:
+	movlpd	%xmm3, 32(%rsp)
+
+.Ldone:
+	.seh_stackalloc 40
+	sub	$40, %rsp
+	.seh_endprologue
+	mov	%rax, %rcx	# context is first parameter
+	mov	%rsp, %rdx	# stack is second parameter
+	add	$48, %rdx	# point to start of arguments
+	leaq	SYMBOL_NAME(ffi_closure_win64_inner)(%rip), %rax
+	callq	*%rax		# call the real closure function
+	add	$40, %rsp
+	movq	%rax, %xmm0	# If the closure returned a float,
+				# ffi_closure_win64_inner wrote it to rax
+	retq
+	.seh_endproc
+
+	.balign 16
+	.globl	SYMBOL_NAME(ffi_call_win64)
+	.seh_proc SYMBOL_NAME(ffi_call_win64)
+SYMBOL_NAME(ffi_call_win64):
+	# copy registers onto stack
+	mov	%r9,32(%rsp)
+	mov	%r8,24(%rsp)
+	mov	%rdx,16(%rsp)
+	mov	%rcx,8(%rsp)
+	.seh_pushreg rbp
+	push	%rbp
+	.seh_stackalloc 48
+	sub	$48,%rsp
+	.seh_setframe rbp, 32
+	lea	32(%rsp),%rbp
+	.seh_endprologue
+
+	mov	CIF_BYTES(%rbp),%eax
+	add	$15, %rax
+	and	$-16, %rax
+	cmpq	$0x1000, %rax
+	jb	Lch_done
+Lch_probe:
+	subq	$0x1000,%rsp
+	orl	$0x0, (%rsp)
+	subq	$0x1000,%rax
+	cmpq	$0x1000,%rax
+	ja	Lch_probe
+Lch_done:
+	subq	%rax, %rsp
+	orl	$0x0, (%rsp)
+	lea	32(%rsp), %rax
+	mov	%rax, STACK(%rbp)
+
+	mov	ECIF(%rbp), %rdx
+	mov	STACK(%rbp), %rcx
+	callq	*PREP_ARGS_FN(%rbp)
+
+	mov	STACK(%rbp), %rsp
+
+	movlpd	24(%rsp), %xmm3
+	movd	%xmm3, %r9
+
+	movlpd	16(%rsp), %xmm2
+	movd	%xmm2, %r8
+
+	movlpd	8(%rsp), %xmm1
+	movd	%xmm1, %rdx
+
+	movlpd	(%rsp), %xmm0
+	movd	%xmm0, %rcx
+
+	callq	*FN(%rbp)
+.Lret_struct4b:
+ 	cmpl	$FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp)
+ 	jne .Lret_struct2b
+
+	mov	RVALUE(%rbp), %rcx
+	mov	%eax, (%rcx)
+	jmp	.Lret_void
+
+.Lret_struct2b:
+	cmpl	$FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp)
+	jne .Lret_struct1b
+
+	mov	RVALUE(%rbp), %rcx
+	mov	%ax, (%rcx)
+	jmp .Lret_void
+
+.Lret_struct1b:
+	cmpl	$FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp)
+	jne .Lret_uint8
+
+	mov	RVALUE(%rbp), %rcx
+	mov	%al, (%rcx)
+	jmp .Lret_void
+
+.Lret_uint8:
+	cmpl	$FFI_TYPE_UINT8, CIF_FLAGS(%rbp)
+	jne .Lret_sint8
+
+	mov     RVALUE(%rbp), %rcx
+	movzbq  %al, %rax
+	movq    %rax, (%rcx)
+	jmp .Lret_void
+
+.Lret_sint8:
+	cmpl	$FFI_TYPE_SINT8, CIF_FLAGS(%rbp)
+	jne .Lret_uint16
+
+	mov     RVALUE(%rbp), %rcx
+	movsbq  %al, %rax
+	movq    %rax, (%rcx)
+	jmp .Lret_void
+
+.Lret_uint16:
+	cmpl	$FFI_TYPE_UINT16, CIF_FLAGS(%rbp)
+	jne .Lret_sint16
+
+	mov     RVALUE(%rbp), %rcx
+	movzwq  %ax, %rax
+	movq    %rax, (%rcx)
+	jmp .Lret_void
+
+.Lret_sint16:
+	cmpl	$FFI_TYPE_SINT16, CIF_FLAGS(%rbp)
+	jne .Lret_uint32
+
+	mov     RVALUE(%rbp), %rcx
+	movswq  %ax, %rax
+	movq    %rax, (%rcx)
+	jmp .Lret_void
+
+.Lret_uint32:
+	cmpl	$FFI_TYPE_UINT32, CIF_FLAGS(%rbp)
+	jne .Lret_sint32
+
+	mov     RVALUE(%rbp), %rcx
+	movl    %eax, %eax
+	movq    %rax, (%rcx)
+	jmp .Lret_void
+
+.Lret_sint32:
+ 	cmpl	$FFI_TYPE_SINT32, CIF_FLAGS(%rbp)
+ 	jne	.Lret_float
+
+	mov	RVALUE(%rbp), %rcx
+	cltq
+	movq	%rax, (%rcx)
+	jmp	.Lret_void
+
+.Lret_float:
+ 	cmpl	$FFI_TYPE_FLOAT, CIF_FLAGS(%rbp)
+ 	jne	.Lret_double
+
+ 	mov	RVALUE(%rbp), %rax
+ 	movss	%xmm0, (%rax)
+ 	jmp	.Lret_void
+
+.Lret_double:
+ 	cmpl	$FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp)
+ 	jne	.Lret_uint64
+
+ 	mov	RVALUE(%rbp), %rax
+ 	movlpd	%xmm0, (%rax)
+ 	jmp	.Lret_void
+
+.Lret_uint64:
+  	cmpl	$FFI_TYPE_UINT64, CIF_FLAGS(%rbp)
+ 	jne	.Lret_sint64
+
+ 	mov	RVALUE(%rbp), %rcx
+ 	mov	%rax, (%rcx)
+ 	jmp	.Lret_void
+
+.Lret_sint64:
+  	cmpl	$FFI_TYPE_SINT64, CIF_FLAGS(%rbp)
+  	jne	.Lret_pointer
+
+ 	mov	RVALUE(%rbp), %rcx
+ 	mov	%rax, (%rcx)
+ 	jmp	.Lret_void
+
+.Lret_pointer:
+  	cmpl	$FFI_TYPE_POINTER, CIF_FLAGS(%rbp)
+  	jne	.Lret_int
+
+ 	mov	RVALUE(%rbp), %rcx
+ 	mov	%rax, (%rcx)
+ 	jmp	.Lret_void
+
+.Lret_int:
+  	cmpl	$FFI_TYPE_INT, CIF_FLAGS(%rbp)
+  	jne	.Lret_void
+
+	mov	RVALUE(%rbp), %rcx
+	cltq
+	movq	%rax, (%rcx)
+	jmp	.Lret_void
+
+.Lret_void:
+	xor	%rax, %rax
+
+	lea	16(%rbp), %rsp
+	pop	%rbp
+	retq
+	.seh_endproc
+#endif /* !_MSC_VER */
+
diff --git a/third_party/gofrontend/libffi/stamp-h.in b/third_party/gofrontend/libffi/stamp-h.in
new file mode 100644
index 0000000..9788f70
--- /dev/null
+++ b/third_party/gofrontend/libffi/stamp-h.in
@@ -0,0 +1 @@
+timestamp
diff --git a/third_party/gofrontend/libffi/testsuite/Makefile.am b/third_party/gofrontend/libffi/testsuite/Makefile.am
new file mode 100644
index 0000000..146fdf9
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/Makefile.am
@@ -0,0 +1,85 @@
+## Process this file with automake to produce Makefile.in.
+
+AUTOMAKE_OPTIONS = foreign dejagnu
+
+# Setup the testing framework, if you have one
+EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
+            echo $(top_builddir)/../expect/expect ; \
+          else echo expect ; fi`
+
+RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
+	       echo $(top_srcdir)/../dejagnu/runtest ; \
+	    else echo runtest; fi`
+
+AM_RUNTESTFLAGS =
+
+CLEANFILES = *.exe core* *.log *.sum
+
+EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c \
+libffi.call/cls_align_longdouble_split.c libffi.call/closure_loc_fn0.c \
+libffi.call/cls_schar.c libffi.call/closure_fn1.c \
+libffi.call/many2_win32.c libffi.call/return_ul.c \
+libffi.call/cls_align_double.c libffi.call/return_fl2.c \
+libffi.call/cls_1_1byte.c libffi.call/cls_64byte.c \
+libffi.call/nested_struct7.c libffi.call/cls_align_sint32.c \
+libffi.call/nested_struct2.c libffi.call/ffitest.h \
+libffi.call/nested_struct4.c libffi.call/cls_multi_ushort.c \
+libffi.call/struct3.c libffi.call/cls_3byte1.c \
+libffi.call/cls_16byte.c libffi.call/struct8.c \
+libffi.call/nested_struct8.c libffi.call/cls_multi_sshort.c \
+libffi.call/cls_3byte2.c libffi.call/fastthis2_win32.c \
+libffi.call/cls_pointer.c libffi.call/err_bad_typedef.c \
+libffi.call/cls_4_1byte.c libffi.call/cls_9byte2.c \
+libffi.call/cls_multi_schar.c libffi.call/stret_medium2.c \
+libffi.call/cls_5_1_byte.c libffi.call/call.exp \
+libffi.call/cls_double.c libffi.call/cls_align_sint16.c \
+libffi.call/cls_uint.c libffi.call/return_ll1.c \
+libffi.call/nested_struct3.c libffi.call/cls_20byte1.c \
+libffi.call/closure_fn4.c libffi.call/cls_uchar.c \
+libffi.call/struct2.c libffi.call/cls_7byte.c libffi.call/strlen.c \
+libffi.call/many.c libffi.call/testclosure.c libffi.call/return_fl.c \
+libffi.call/struct5.c libffi.call/cls_12byte.c \
+libffi.call/cls_multi_sshortchar.c \
+libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c \
+libffi.call/return_fl3.c libffi.call/stret_medium.c \
+libffi.call/nested_struct6.c libffi.call/a.out \
+libffi.call/closure_fn3.c libffi.call/float3.c libffi.call/many2.c \
+libffi.call/closure_stdcall.c libffi.call/cls_align_uint16.c \
+libffi.call/cls_9byte1.c libffi.call/closure_fn6.c \
+libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c \
+libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c \
+libffi.call/cls_sshort.c libffi.call/many_win32.c \
+libffi.call/nested_struct.c libffi.call/cls_20byte.c \
+libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c \
+libffi.call/return_uc.c libffi.call/closure_thiscall.c \
+libffi.call/cls_18byte.c libffi.call/cls_8byte.c \
+libffi.call/promotion.c libffi.call/struct1_win32.c \
+libffi.call/return_dbl.c libffi.call/cls_24byte.c \
+libffi.call/struct4.c libffi.call/cls_6byte.c \
+libffi.call/cls_align_uint32.c libffi.call/float.c \
+libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c \
+libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c \
+libffi.call/cls_align_float.c libffi.call/return_fl1.c \
+libffi.call/nested_struct10.c libffi.call/nested_struct5.c \
+libffi.call/fastthis1_win32.c libffi.call/cls_align_sint64.c \
+libffi.call/stret_large2.c libffi.call/return_sl.c \
+libffi.call/closure_fn0.c libffi.call/cls_5byte.c \
+libffi.call/cls_2byte.c libffi.call/float2.c \
+libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c \
+libffi.call/stret_large.c libffi.call/cls_ulonglong.c \
+libffi.call/cls_ushort.c libffi.call/nested_struct1.c \
+libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c \
+libffi.call/cls_float.c libffi.call/cls_pointer_stack.c \
+libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c \
+libffi.call/struct1.c libffi.call/nested_struct9.c \
+libffi.call/huge_struct.c libffi.call/problem1.c libffi.call/float4.c \
+libffi.call/fastthis3_win32.c libffi.call/return_ldl.c \
+libffi.call/strlen2_win32.c libffi.call/closure_fn5.c \
+libffi.call/struct2_win32.c libffi.call/struct6.c \
+libffi.call/return_ll.c libffi.call/struct9.c libffi.call/return_sc.c \
+libffi.call/struct7.c libffi.call/cls_align_uint64.c \
+libffi.call/cls_4byte.c libffi.call/strlen_win32.c \
+libffi.call/cls_6_1_byte.c libffi.call/cls_7_1_byte.c \
+libffi.special/unwindtest.cc libffi.special/special.exp \
+libffi.special/unwindtest_ffi_call.cc libffi.special/ffitestcxx.h \
+lib/wrapper.exp lib/target-libpath.exp lib/libffi.exp
diff --git a/third_party/gofrontend/libffi/testsuite/Makefile.in b/third_party/gofrontend/libffi/testsuite/Makefile.in
new file mode 100644
index 0000000..808d4cb
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/Makefile.in
@@ -0,0 +1,466 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = testsuite
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+	$(top_srcdir)/../config/asmcfi.m4 \
+	$(top_srcdir)/../config/depstand.m4 \
+	$(top_srcdir)/../config/lead-dot.m4 \
+	$(top_srcdir)/../config/multi.m4 \
+	$(top_srcdir)/../config/override.m4 \
+	$(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \
+	$(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
+	$(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/fficonfig.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DEJATOOL = $(PACKAGE)
+RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_LTLDFLAGS = @AM_LTLDFLAGS@
+AM_RUNTESTFLAGS = 
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
+HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARGET = @TARGET@
+TARGETDIR = @TARGETDIR@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign dejagnu
+
+# Setup the testing framework, if you have one
+EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
+            echo $(top_builddir)/../expect/expect ; \
+          else echo expect ; fi`
+
+RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
+	       echo $(top_srcdir)/../dejagnu/runtest ; \
+	    else echo runtest; fi`
+
+CLEANFILES = *.exe core* *.log *.sum
+EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c \
+libffi.call/cls_align_longdouble_split.c libffi.call/closure_loc_fn0.c \
+libffi.call/cls_schar.c libffi.call/closure_fn1.c \
+libffi.call/many2_win32.c libffi.call/return_ul.c \
+libffi.call/cls_align_double.c libffi.call/return_fl2.c \
+libffi.call/cls_1_1byte.c libffi.call/cls_64byte.c \
+libffi.call/nested_struct7.c libffi.call/cls_align_sint32.c \
+libffi.call/nested_struct2.c libffi.call/ffitest.h \
+libffi.call/nested_struct4.c libffi.call/cls_multi_ushort.c \
+libffi.call/struct3.c libffi.call/cls_3byte1.c \
+libffi.call/cls_16byte.c libffi.call/struct8.c \
+libffi.call/nested_struct8.c libffi.call/cls_multi_sshort.c \
+libffi.call/cls_3byte2.c libffi.call/fastthis2_win32.c \
+libffi.call/cls_pointer.c libffi.call/err_bad_typedef.c \
+libffi.call/cls_4_1byte.c libffi.call/cls_9byte2.c \
+libffi.call/cls_multi_schar.c libffi.call/stret_medium2.c \
+libffi.call/cls_5_1_byte.c libffi.call/call.exp \
+libffi.call/cls_double.c libffi.call/cls_align_sint16.c \
+libffi.call/cls_uint.c libffi.call/return_ll1.c \
+libffi.call/nested_struct3.c libffi.call/cls_20byte1.c \
+libffi.call/closure_fn4.c libffi.call/cls_uchar.c \
+libffi.call/struct2.c libffi.call/cls_7byte.c libffi.call/strlen.c \
+libffi.call/many.c libffi.call/testclosure.c libffi.call/return_fl.c \
+libffi.call/struct5.c libffi.call/cls_12byte.c \
+libffi.call/cls_multi_sshortchar.c \
+libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c \
+libffi.call/return_fl3.c libffi.call/stret_medium.c \
+libffi.call/nested_struct6.c libffi.call/a.out \
+libffi.call/closure_fn3.c libffi.call/float3.c libffi.call/many2.c \
+libffi.call/closure_stdcall.c libffi.call/cls_align_uint16.c \
+libffi.call/cls_9byte1.c libffi.call/closure_fn6.c \
+libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c \
+libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c \
+libffi.call/cls_sshort.c libffi.call/many_win32.c \
+libffi.call/nested_struct.c libffi.call/cls_20byte.c \
+libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c \
+libffi.call/return_uc.c libffi.call/closure_thiscall.c \
+libffi.call/cls_18byte.c libffi.call/cls_8byte.c \
+libffi.call/promotion.c libffi.call/struct1_win32.c \
+libffi.call/return_dbl.c libffi.call/cls_24byte.c \
+libffi.call/struct4.c libffi.call/cls_6byte.c \
+libffi.call/cls_align_uint32.c libffi.call/float.c \
+libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c \
+libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c \
+libffi.call/cls_align_float.c libffi.call/return_fl1.c \
+libffi.call/nested_struct10.c libffi.call/nested_struct5.c \
+libffi.call/fastthis1_win32.c libffi.call/cls_align_sint64.c \
+libffi.call/stret_large2.c libffi.call/return_sl.c \
+libffi.call/closure_fn0.c libffi.call/cls_5byte.c \
+libffi.call/cls_2byte.c libffi.call/float2.c \
+libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c \
+libffi.call/stret_large.c libffi.call/cls_ulonglong.c \
+libffi.call/cls_ushort.c libffi.call/nested_struct1.c \
+libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c \
+libffi.call/cls_float.c libffi.call/cls_pointer_stack.c \
+libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c \
+libffi.call/struct1.c libffi.call/nested_struct9.c \
+libffi.call/huge_struct.c libffi.call/problem1.c libffi.call/float4.c \
+libffi.call/fastthis3_win32.c libffi.call/return_ldl.c \
+libffi.call/strlen2_win32.c libffi.call/closure_fn5.c \
+libffi.call/struct2_win32.c libffi.call/struct6.c \
+libffi.call/return_ll.c libffi.call/struct9.c libffi.call/return_sc.c \
+libffi.call/struct7.c libffi.call/cls_align_uint64.c \
+libffi.call/cls_4byte.c libffi.call/strlen_win32.c \
+libffi.call/cls_6_1_byte.c libffi.call/cls_7_1_byte.c \
+libffi.special/unwindtest.cc libffi.special/special.exp \
+libffi.special/unwindtest_ffi_call.cc libffi.special/ffitestcxx.h \
+lib/wrapper.exp lib/target-libpath.exp lib/libffi.exp
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign testsuite/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+check-DEJAGNU: site.exp
+	srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \
+	EXPECT=$(EXPECT); export EXPECT; \
+	runtest=$(RUNTEST); \
+	if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+	  exit_status=0; l='$(DEJATOOL)'; for tool in $$l; do \
+	    if $$runtest $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \
+	    then :; else exit_status=1; fi; \
+	  done; \
+	else echo "WARNING: could not find \`runtest'" 1>&2; :;\
+	fi; \
+	exit $$exit_status
+site.exp: Makefile
+	@echo 'Making a new site.exp file...'
+	@echo '## these variables are automatically generated by make ##' >site.tmp
+	@echo '# Do not edit here.  If you wish to override these values' >>site.tmp
+	@echo '# edit the last section' >>site.tmp
+	@echo 'set srcdir $(srcdir)' >>site.tmp
+	@echo "set objdir `pwd`" >>site.tmp
+	@echo 'set build_alias "$(build_alias)"' >>site.tmp
+	@echo 'set build_triplet $(build_triplet)' >>site.tmp
+	@echo 'set host_alias "$(host_alias)"' >>site.tmp
+	@echo 'set host_triplet $(host_triplet)' >>site.tmp
+	@echo 'set target_alias "$(target_alias)"' >>site.tmp
+	@echo 'set target_triplet $(target_triplet)' >>site.tmp
+	@echo '## All variables above are generated by configure. Do Not Edit ##' >>site.tmp
+	@test ! -f site.exp || \
+	  sed '1,/^## All variables above are.*##/ d' site.exp >> site.tmp
+	@-rm -f site.bak
+	@test ! -f site.exp || mv site.exp site.bak
+	@mv site.tmp site.exp
+
+distclean-DEJAGNU:
+	-rm -f site.exp site.bak
+	-l='$(DEJATOOL)'; for tool in $$l; do \
+	  rm -f $$tool.sum $$tool.log; \
+	done
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-DEJAGNU distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: all all-am check check-DEJAGNU check-am clean clean-generic \
+	clean-libtool distclean distclean-DEJAGNU distclean-generic \
+	distclean-libtool dvi dvi-am html html-am info info-am install \
+	install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn0.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn0.c
new file mode 100644
index 0000000..a579ff6
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn0.c
@@ -0,0 +1,89 @@
+/* Area:	closure_call
+   Purpose:	Check multiple values passing from different type.
+		Also, exceed the limit of gpr and fpr registers on PowerPC
+		Darwin.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void
+closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)(*(int *)args[1]) +
+    (int)(*(unsigned long long *)args[2]) + (int)*(int *)args[3] +
+    (int)(*(signed short *)args[4]) +
+    (int)(*(unsigned long long *)args[5]) +
+    (int)*(int *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(int *)args[14]) +  *(int *)args[15] + (intptr_t)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+	 (int)*(unsigned long long *)args[0], (int)(*(int *)args[1]),
+	 (int)(*(unsigned long long *)args[2]),
+	 (int)*(int *)args[3], (int)(*(signed short *)args[4]),
+	 (int)(*(unsigned long long *)args[5]),
+	 (int)*(int *)args[6], (int)(*(int *)args[7]),
+	 (int)(*(double *)args[8]), (int)*(int *)args[9],
+	 (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+	 (int)*(int *)args[12], (int)(*(int *)args[13]),
+	 (int)(*(int *)args[14]),*(int *)args[15],
+	 (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_test_type0)(unsigned long long, int, unsigned long long,
+				  int, signed short, unsigned long long, int,
+				  int, double, int, int, float, int, int,
+				  int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void * code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = &ffi_type_sint;
+  cl_arg_types[2] = &ffi_type_uint64;
+  cl_arg_types[3] = &ffi_type_sint;
+  cl_arg_types[4] = &ffi_type_sshort;
+  cl_arg_types[5] = &ffi_type_uint64;
+  cl_arg_types[6] = &ffi_type_sint;
+  cl_arg_types[7] = &ffi_type_sint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_sint;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_sint;
+  cl_arg_types[14] = &ffi_type_sint;
+  cl_arg_types[15] = &ffi_type_sint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn0,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*((closure_test_type0)code))
+    (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13,
+     19, 21, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+     exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn1.c
new file mode 100644
index 0000000..9123173
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn1.c
@@ -0,0 +1,81 @@
+/* Area:	closure_call.
+   Purpose:	Check multiple values passing from different type.
+		Also, exceed the limit of gpr and fpr registers on PowerPC
+		Darwin.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+
+static void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(float *)args[0] +(int)(*(float *)args[1]) +
+    (int)(*(float *)args[2]) + (int)*(float *)args[3] +
+    (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) +
+    (int)*(float *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double*)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(int *)args[14]) + *(int *)args[15] + (intptr_t)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+	 (int)*(float *)args[0], (int)(*(float *)args[1]),
+	 (int)(*(float *)args[2]), (int)*(float *)args[3],
+	 (int)(*(signed short *)args[4]), (int)(*(float *)args[5]),
+	 (int)*(float *)args[6], (int)(*(int *)args[7]),
+	 (int)(*(double *)args[8]), (int)*(int *)args[9],
+	 (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+	 (int)*(int *)args[12], (int)(*(int *)args[13]),
+	 (int)(*(int *)args[14]), *(int *)args[15],
+	 (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
+}
+
+typedef int (*closure_test_type1)(float, float, float, float, signed short,
+				  float, float, int, double, int, int, float,
+				  int, int, int, int);
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  cl_arg_types[0] = &ffi_type_float;
+  cl_arg_types[1] = &ffi_type_float;
+  cl_arg_types[2] = &ffi_type_float;
+  cl_arg_types[3] = &ffi_type_float;
+  cl_arg_types[4] = &ffi_type_sshort;
+  cl_arg_types[5] = &ffi_type_float;
+  cl_arg_types[6] = &ffi_type_float;
+  cl_arg_types[7] = &ffi_type_sint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_sint;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_sint;
+  cl_arg_types[14] = &ffi_type_sint;
+  cl_arg_types[15] = &ffi_type_sint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn1,
+                             (void *) 3 /* userdata */, code)  == FFI_OK);
+
+  res = (*((closure_test_type1)code))
+    (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13,
+     19, 21, 1);
+  /* { dg-output "1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 255" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn2.c
new file mode 100644
index 0000000..08ff9d9
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn2.c
@@ -0,0 +1,81 @@
+/* Area:	closure_call
+   Purpose:	Check multiple values passing from different type.
+		Also, exceed the limit of gpr and fpr registers on PowerPC
+		Darwin.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void closure_test_fn2(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(double *)args[0] +(int)(*(double *)args[1]) +
+    (int)(*(double *)args[2]) + (int)*(double *)args[3] +
+    (int)(*(signed short *)args[4]) + (int)(*(double *)args[5]) +
+    (int)*(double *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(float *)args[13]) +
+    (int)(*(int *)args[14]) + *(int *)args[15] + (intptr_t)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+	 (int)*(double *)args[0], (int)(*(double *)args[1]),
+	 (int)(*(double *)args[2]), (int)*(double *)args[3],
+	 (int)(*(signed short *)args[4]), (int)(*(double *)args[5]),
+	 (int)*(double *)args[6], (int)(*(int *)args[7]),
+	 (int)(*(double*)args[8]), (int)*(int *)args[9],
+	 (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+	 (int)*(int *)args[12], (int)(*(float *)args[13]),
+	 (int)(*(int *)args[14]), *(int *)args[15], (int)(intptr_t)userdata,
+	 (int)*(ffi_arg *)resp);
+}
+
+typedef int (*closure_test_type2)(double, double, double, double, signed short,
+				  double, double, int, double, int, int, float,
+				  int, float, int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  cl_arg_types[0] = &ffi_type_double;
+  cl_arg_types[1] = &ffi_type_double;
+  cl_arg_types[2] = &ffi_type_double;
+  cl_arg_types[3] = &ffi_type_double;
+  cl_arg_types[4] = &ffi_type_sshort;
+  cl_arg_types[5] = &ffi_type_double;
+  cl_arg_types[6] = &ffi_type_double;
+  cl_arg_types[7] = &ffi_type_sint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_sint;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_float;
+  cl_arg_types[14] = &ffi_type_sint;
+  cl_arg_types[15] = &ffi_type_sint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn2,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*((closure_test_type2)code))
+    (1, 2, 3, 4, 127, 5, 6, 8, 9, 10, 11, 12.0, 13,
+     19.0, 21, 1);
+  /* { dg-output "1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 255" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn3.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn3.c
new file mode 100644
index 0000000..9b54d80
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn3.c
@@ -0,0 +1,82 @@
+/* Area:	closure_call
+   Purpose:	Check multiple values passing from different type.
+		Also, exceed the limit of gpr and fpr registers on PowerPC
+		Darwin.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void closure_test_fn3(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata)
+ {
+   *(ffi_arg*)resp =
+     (int)*(float *)args[0] +(int)(*(float *)args[1]) +
+     (int)(*(float *)args[2]) + (int)*(float *)args[3] +
+     (int)(*(float *)args[4]) + (int)(*(float *)args[5]) +
+     (int)*(float *)args[6] + (int)(*(float *)args[7]) +
+     (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+     (int)(*(float *)args[10]) + (int)(*(float *)args[11]) +
+     (int)*(int *)args[12] + (int)(*(float *)args[13]) +
+     (int)(*(float *)args[14]) +  *(int *)args[15] + (intptr_t)userdata;
+
+   printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+	  (int)*(float *)args[0], (int)(*(float *)args[1]),
+	  (int)(*(float *)args[2]), (int)*(float *)args[3],
+	  (int)(*(float *)args[4]), (int)(*(float *)args[5]),
+	  (int)*(float *)args[6], (int)(*(float *)args[7]),
+	  (int)(*(double *)args[8]), (int)*(int *)args[9],
+	  (int)(*(float *)args[10]), (int)(*(float *)args[11]),
+	  (int)*(int *)args[12], (int)(*(float *)args[13]),
+	  (int)(*(float *)args[14]), *(int *)args[15], (int)(intptr_t)userdata,
+	  (int)*(ffi_arg *)resp);
+
+ }
+
+typedef int (*closure_test_type3)(float, float, float, float, float, float,
+				  float, float, double, int, float, float, int,
+				  float, float, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  cl_arg_types[0] = &ffi_type_float;
+  cl_arg_types[1] = &ffi_type_float;
+  cl_arg_types[2] = &ffi_type_float;
+  cl_arg_types[3] = &ffi_type_float;
+  cl_arg_types[4] = &ffi_type_float;
+  cl_arg_types[5] = &ffi_type_float;
+  cl_arg_types[6] = &ffi_type_float;
+  cl_arg_types[7] = &ffi_type_float;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_sint;
+  cl_arg_types[10] = &ffi_type_float;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_float;
+  cl_arg_types[14] = &ffi_type_float;
+  cl_arg_types[15] = &ffi_type_sint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn3,
+                             (void *) 3 /* userdata */, code)  == FFI_OK);
+
+  res = (*((closure_test_type3)code))
+    (1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9, 10, 11.11, 12.0, 13,
+     19.19, 21.21, 1);
+  /* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 19 21 1 3: 135" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 135" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn4.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn4.c
new file mode 100644
index 0000000..d4a1530
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn4.c
@@ -0,0 +1,89 @@
+/* Area:	closure_call
+   Purpose:	Check multiple long long values passing.
+		Also, exceed the limit of gpr and fpr registers on PowerPC
+		Darwin.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20031026	 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static void
+closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)*(unsigned long long *)args[1] +
+    (int)*(unsigned long long *)args[2] + (int)*(unsigned long long *)args[3] +
+    (int)*(unsigned long long *)args[4] + (int)*(unsigned long long *)args[5] +
+    (int)*(unsigned long long *)args[6] + (int)*(unsigned long long *)args[7] +
+    (int)*(unsigned long long *)args[8] + (int)*(unsigned long long *)args[9] +
+    (int)*(unsigned long long *)args[10] +
+    (int)*(unsigned long long *)args[11] +
+    (int)*(unsigned long long *)args[12] +
+    (int)*(unsigned long long *)args[13] +
+    (int)*(unsigned long long *)args[14] +
+    *(int *)args[15] + (intptr_t)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+	 (int)*(unsigned long long *)args[0],
+	 (int)*(unsigned long long *)args[1],
+	 (int)*(unsigned long long *)args[2],
+	 (int)*(unsigned long long *)args[3],
+	 (int)*(unsigned long long *)args[4],
+	 (int)*(unsigned long long *)args[5],
+	 (int)*(unsigned long long *)args[6],
+	 (int)*(unsigned long long *)args[7],
+	 (int)*(unsigned long long *)args[8],
+	 (int)*(unsigned long long *)args[9],
+	 (int)*(unsigned long long *)args[10],
+	 (int)*(unsigned long long *)args[11],
+	 (int)*(unsigned long long *)args[12],
+	 (int)*(unsigned long long *)args[13],
+	 (int)*(unsigned long long *)args[14],
+	 *(int *)args[15],
+	 (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_test_type0)(unsigned long long, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  unsigned long long, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int i, res;
+
+  for (i = 0; i < 15; i++) {
+    cl_arg_types[i] = &ffi_type_uint64;
+  }
+  cl_arg_types[15] = &ffi_type_sint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn0,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*((closure_test_type0)code))
+    (1LL, 2LL, 3LL, 4LL, 127LL, 429LL, 7LL, 8LL, 9LL, 10LL, 11LL, 12LL,
+     13LL, 19LL, 21LL, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn5.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn5.c
new file mode 100644
index 0000000..9907442
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn5.c
@@ -0,0 +1,92 @@
+/* Area:	closure_call
+   Purpose:	Check multiple long long values passing.
+		Exceed the limit of gpr registers on PowerPC
+		Darwin.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20031026	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void
+closure_test_fn5(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)*(unsigned long long *)args[1] +
+    (int)*(unsigned long long *)args[2] + (int)*(unsigned long long *)args[3] +
+    (int)*(unsigned long long *)args[4] + (int)*(unsigned long long *)args[5] +
+    (int)*(unsigned long long *)args[6] + (int)*(unsigned long long *)args[7] +
+    (int)*(unsigned long long *)args[8] + (int)*(unsigned long long *)args[9] +
+    (int)*(int *)args[10] +
+    (int)*(unsigned long long *)args[11] +
+    (int)*(unsigned long long *)args[12] +
+    (int)*(unsigned long long *)args[13] +
+    (int)*(unsigned long long *)args[14] +
+    *(int *)args[15] + (intptr_t)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+	 (int)*(unsigned long long *)args[0],
+	 (int)*(unsigned long long *)args[1],
+	 (int)*(unsigned long long *)args[2],
+	 (int)*(unsigned long long *)args[3],
+	 (int)*(unsigned long long *)args[4],
+	 (int)*(unsigned long long *)args[5],
+	 (int)*(unsigned long long *)args[6],
+	 (int)*(unsigned long long *)args[7],
+	 (int)*(unsigned long long *)args[8],
+	 (int)*(unsigned long long *)args[9],
+	 (int)*(int *)args[10],
+	 (int)*(unsigned long long *)args[11],
+	 (int)*(unsigned long long *)args[12],
+	 (int)*(unsigned long long *)args[13],
+	 (int)*(unsigned long long *)args[14],
+	 *(int *)args[15],
+	 (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_test_type0)(unsigned long long, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  int, unsigned long long,
+				  unsigned long long, unsigned long long,
+				  unsigned long long, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int i, res;
+
+  for (i = 0; i < 10; i++) {
+    cl_arg_types[i] = &ffi_type_uint64;
+  }
+  cl_arg_types[10] = &ffi_type_sint;
+  for (i = 11; i < 15; i++) {
+    cl_arg_types[i] = &ffi_type_uint64;
+  }
+  cl_arg_types[15] = &ffi_type_sint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn5,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*((closure_test_type0)code))
+    (1LL, 2LL, 3LL, 4LL, 127LL, 429LL, 7LL, 8LL, 9LL, 10LL, 11, 12LL,
+     13LL, 19LL, 21LL, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn6.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn6.c
new file mode 100644
index 0000000..73c54fd
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_fn6.c
@@ -0,0 +1,90 @@
+/* Area:	closure_call
+   Purpose:	Check multiple values passing from different type.
+		Also, exceed the limit of gpr and fpr registers on PowerPC.
+   Limitations:	none.
+   PR:		PR23404
+   Originator:	<andreast@gcc.gnu.org> 20050830	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void
+closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] +
+    (int)(*(unsigned long long *)args[1]) +
+    (int)(*(unsigned long long *)args[2]) +
+    (int)*(unsigned long long *)args[3] +
+    (int)(*(int *)args[4]) + (int)(*(double *)args[5]) +
+    (int)*(double *)args[6] + (int)(*(float *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(double *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(double *)args[14]) +  (int)*(double *)args[15] +
+    (intptr_t)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+	 (int)*(unsigned long long  *)args[0],
+	 (int)(*(unsigned long long  *)args[1]),
+	 (int)(*(unsigned long long  *)args[2]),
+	 (int)*(unsigned long long  *)args[3],
+	 (int)(*(int *)args[4]), (int)(*(double *)args[5]),
+	 (int)*(double *)args[6], (int)(*(float *)args[7]),
+	 (int)(*(double *)args[8]), (int)*(double *)args[9],
+	 (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+	 (int)*(int *)args[12], (int)(*(int *)args[13]),
+	 (int)(*(double *)args[14]), (int)(*(double *)args[15]),
+	 (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_test_type0)(unsigned long long,
+				  unsigned long long,
+				  unsigned long long,
+				  unsigned long long,
+				  int, double, double, float, double, double,
+				  int, float, int, int, double, double);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = &ffi_type_uint64;
+  cl_arg_types[2] = &ffi_type_uint64;
+  cl_arg_types[3] = &ffi_type_uint64;
+  cl_arg_types[4] = &ffi_type_sint;
+  cl_arg_types[5] = &ffi_type_double;
+  cl_arg_types[6] = &ffi_type_double;
+  cl_arg_types[7] = &ffi_type_float;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_double;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_sint;
+  cl_arg_types[14] = &ffi_type_double;
+  cl_arg_types[15] = &ffi_type_double;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn0,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*((closure_test_type0)code))
+    (1, 2, 3, 4, 127, 429., 7., 8., 9.5, 10., 11, 12., 13,
+     19, 21., 1.);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_loc_fn0.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_loc_fn0.c
new file mode 100644
index 0000000..b3afa0b
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_loc_fn0.c
@@ -0,0 +1,95 @@
+/* Area:	closure_call
+   Purpose:	Check multiple values passing from different type.
+		Also, exceed the limit of gpr and fpr registers on PowerPC
+		Darwin.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void
+closure_loc_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)(*(int *)args[1]) +
+    (int)(*(unsigned long long *)args[2]) + (int)*(int *)args[3] +
+    (int)(*(signed short *)args[4]) +
+    (int)(*(unsigned long long *)args[5]) +
+    (int)*(int *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(int *)args[14]) +  *(int *)args[15] + (intptr_t)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+	 (int)*(unsigned long long *)args[0], (int)(*(int *)args[1]),
+	 (int)(*(unsigned long long *)args[2]),
+	 (int)*(int *)args[3], (int)(*(signed short *)args[4]),
+	 (int)(*(unsigned long long *)args[5]),
+	 (int)*(int *)args[6], (int)(*(int *)args[7]),
+	 (int)(*(double *)args[8]), (int)*(int *)args[9],
+	 (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+	 (int)*(int *)args[12], (int)(*(int *)args[13]),
+	 (int)(*(int *)args[14]),*(int *)args[15],
+	 (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_loc_test_type0)(unsigned long long, int, unsigned long long,
+				  int, signed short, unsigned long long, int,
+				  int, double, int, int, float, int, int,
+				  int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int res;
+  void *codeloc;
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = &ffi_type_sint;
+  cl_arg_types[2] = &ffi_type_uint64;
+  cl_arg_types[3] = &ffi_type_sint;
+  cl_arg_types[4] = &ffi_type_sshort;
+  cl_arg_types[5] = &ffi_type_uint64;
+  cl_arg_types[6] = &ffi_type_sint;
+  cl_arg_types[7] = &ffi_type_sint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_sint;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_sint;
+  cl_arg_types[14] = &ffi_type_sint;
+  cl_arg_types[15] = &ffi_type_sint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  pcl = ffi_closure_alloc(sizeof(ffi_closure), &codeloc);
+  CHECK(pcl != NULL);
+  CHECK(codeloc != NULL);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_loc_test_fn0,
+			 (void *) 3 /* userdata */, codeloc) == FFI_OK);
+  
+  CHECK(memcmp(pcl, codeloc, sizeof(*pcl)) == 0);
+
+  res = (*((closure_loc_test_type0)codeloc))
+    (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13,
+     19, 21, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+     exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_stdcall.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_stdcall.c
new file mode 100644
index 0000000..1407f02
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_stdcall.c
@@ -0,0 +1,72 @@
+/* Area:	closure_call (stdcall convention)
+   Purpose:	Check handling when caller expects stdcall callee
+   Limitations:	none.
+   PR:		none.
+   Originator:	<twalljava@dev.java.net> */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+#include "ffitest.h"
+
+static void
+closure_test_stdcall(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(int *)args[0] + (int)(*(int *)args[1])
+    + (int)(*(int *)args[2])  + (int)(*(int *)args[3])
+    + (int)(intptr_t)userdata;
+
+  printf("%d %d %d %d: %d\n",
+	 (int)*(int *)args[0], (int)(*(int *)args[1]),
+	 (int)(*(int *)args[2]), (int)(*(int *)args[3]),
+         (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (__stdcall *closure_test_type0)(int, int, int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+  void* sp_pre;
+  void* sp_post;
+  char buf[1024];
+
+  cl_arg_types[0] = &ffi_type_uint;
+  cl_arg_types[1] = &ffi_type_uint;
+  cl_arg_types[2] = &ffi_type_uint;
+  cl_arg_types[3] = &ffi_type_uint;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 4,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_stdcall,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+#ifdef _MSC_VER
+  __asm { mov sp_pre, esp }
+#else
+  asm volatile (" movl %%esp,%0" : "=g" (sp_pre));
+#endif
+  res = (*(closure_test_type0)code)(0, 1, 2, 3);
+#ifdef _MSC_VER
+  __asm { mov sp_post, esp }
+#else
+  asm volatile (" movl %%esp,%0" : "=g" (sp_post));
+#endif
+  /* { dg-output "0 1 2 3: 9" } */
+
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 9" } */
+
+  sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post);
+  printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf));
+  /* { dg-output "\nstack pointer match" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_thiscall.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_thiscall.c
new file mode 100644
index 0000000..0f93649
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_thiscall.c
@@ -0,0 +1,72 @@
+/* Area:	closure_call (thiscall convention)
+   Purpose:	Check handling when caller expects thiscall callee
+   Limitations:	none.
+   PR:		none.
+   Originator:	<ktietz@redhat.com> */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+#include "ffitest.h"
+
+static void
+closure_test_thiscall(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		      void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(int *)args[0] + (int)(*(int *)args[1])
+    + (int)(*(int *)args[2])  + (int)(*(int *)args[3])
+    + (int)(intptr_t)userdata;
+
+  printf("%d %d %d %d: %d\n",
+	 (int)*(int *)args[0], (int)(*(int *)args[1]),
+	 (int)(*(int *)args[2]), (int)(*(int *)args[3]),
+         (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (__thiscall *closure_test_type0)(int, int, int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+  void* sp_pre;
+  void* sp_post;
+  char buf[1024];
+
+  cl_arg_types[0] = &ffi_type_uint;
+  cl_arg_types[1] = &ffi_type_uint;
+  cl_arg_types[2] = &ffi_type_uint;
+  cl_arg_types[3] = &ffi_type_uint;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_THISCALL, 4,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_thiscall,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+#ifdef _MSC_VER
+  __asm { mov sp_pre, esp }
+#else
+  asm volatile (" movl %%esp,%0" : "=g" (sp_pre));
+#endif
+  res = (*(closure_test_type0)code)(0, 1, 2, 3);
+#ifdef _MSC_VER
+  __asm { mov sp_post, esp }
+#else
+  asm volatile (" movl %%esp,%0" : "=g" (sp_post));
+#endif
+  /* { dg-output "0 1 2 3: 9" } */
+
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 9" } */
+
+  sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post);
+  printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf));
+  /* { dg-output "\nstack pointer match" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_12byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_12byte.c
new file mode 100644
index 0000000..ea0825d
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_12byte.c
@@ -0,0 +1,94 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_12byte {
+  int a;
+  int b;
+  int c;
+} cls_struct_12byte;
+
+cls_struct_12byte cls_struct_12byte_fn(struct cls_struct_12byte b1,
+			    struct cls_struct_12byte b2)
+{
+  struct cls_struct_12byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+  result.c = b1.c + b2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", b1.a, b1.b, b1.c, b2.a, b2.b, b2.c,
+	 result.a, result.b, result.c);
+
+  return result;
+}
+
+static void cls_struct_12byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+				 void** args , void* userdata __UNUSED__)
+{
+  struct cls_struct_12byte b1, b2;
+
+  b1 = *(struct cls_struct_12byte*)(args[0]);
+  b2 = *(struct cls_struct_12byte*)(args[1]);
+
+  *(cls_struct_12byte*)resp = cls_struct_12byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_12byte h_dbl = { 7, 4, 9 };
+  struct cls_struct_12byte j_dbl = { 1, 5, 3 };
+  struct cls_struct_12byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_sint;
+  cls_struct_fields[1] = &ffi_type_sint;
+  cls_struct_fields[2] = &ffi_type_sint;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &h_dbl;
+  args_dbl[1] = &j_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_12byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "7 4 9 1 5 3: 8 9 12" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 8 9 12" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_12byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+
+  res_dbl = ((cls_struct_12byte(*)(cls_struct_12byte, cls_struct_12byte))(code))(h_dbl, j_dbl);
+  /* { dg-output "\n7 4 9 1 5 3: 8 9 12" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 8 9 12" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_16byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_16byte.c
new file mode 100644
index 0000000..89a08a2
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_16byte.c
@@ -0,0 +1,95 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_16byte {
+  int a;
+  double b;
+  int c;
+} cls_struct_16byte;
+
+cls_struct_16byte cls_struct_16byte_fn(struct cls_struct_16byte b1,
+			    struct cls_struct_16byte b2)
+{
+  struct cls_struct_16byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+  result.c = b1.c + b2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", b1.a, b1.b, b1.c, b2.a, b2.b, b2.c,
+	 result.a, result.b, result.c);
+
+  return result;
+}
+
+static void cls_struct_16byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+				 void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_16byte b1, b2;
+
+  b1 = *(struct cls_struct_16byte*)(args[0]);
+  b2 = *(struct cls_struct_16byte*)(args[1]);
+
+  *(cls_struct_16byte*)resp = cls_struct_16byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_16byte h_dbl = { 7, 8.0, 9 };
+  struct cls_struct_16byte j_dbl = { 1, 9.0, 3 };
+  struct cls_struct_16byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_sint;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_sint;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &h_dbl;
+  args_dbl[1] = &j_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_16byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "7 8 9 1 9 3: 8 17 12" } */
+  printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 8 17 12" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0.0;
+  res_dbl.c = 0;
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_16byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_16byte(*)(cls_struct_16byte, cls_struct_16byte))(code))(h_dbl, j_dbl);
+  /* { dg-output "\n7 8 9 1 9 3: 8 17 12" } */
+  printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 8 17 12" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_18byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_18byte.c
new file mode 100644
index 0000000..9f75da8
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_18byte.c
@@ -0,0 +1,96 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Double alignment check on darwin.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030915	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_18byte {
+  double a;
+  unsigned char b;
+  unsigned char c;
+  double d;
+} cls_struct_18byte;
+
+cls_struct_18byte cls_struct_18byte_fn(struct cls_struct_18byte a1,
+			    struct cls_struct_18byte a2)
+{
+  struct cls_struct_18byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+
+  printf("%g %d %d %g %g %d %d %g: %g %d %d %g\n", a1.a, a1.b, a1.c, a1.d,
+	 a2.a, a2.b, a2.c, a2.d,
+	 result.a, result.b, result.c, result.d);
+  return result;
+}
+
+static void
+cls_struct_18byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_18byte a1, a2;
+
+  a1 = *(struct cls_struct_18byte*)(args[0]);
+  a2 = *(struct cls_struct_18byte*)(args[1]);
+
+  *(cls_struct_18byte*)resp = cls_struct_18byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+  struct cls_struct_18byte g_dbl = { 1.0, 127, 126, 3.0 };
+  struct cls_struct_18byte f_dbl = { 4.0, 125, 124, 5.0 };
+  struct cls_struct_18byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_double;
+  cls_struct_fields[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_18byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 127 126 3 4 125 124 5: 5 252 250 8" } */
+  printf("res: %g %d %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 5 252 250 8" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_18byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_18byte(*)(cls_struct_18byte, cls_struct_18byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n1 127 126 3 4 125 124 5: 5 252 250 8" } */
+  printf("res: %g %d %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 5 252 250 8" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_19byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_19byte.c
new file mode 100644
index 0000000..278794b
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_19byte.c
@@ -0,0 +1,102 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Double alignment check on darwin.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030915	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_19byte {
+  double a;
+  unsigned char b;
+  unsigned char c;
+  double d;
+  unsigned char e;
+} cls_struct_19byte;
+
+cls_struct_19byte cls_struct_19byte_fn(struct cls_struct_19byte a1,
+			    struct cls_struct_19byte a2)
+{
+  struct cls_struct_19byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+
+
+  printf("%g %d %d %g %d %g %d %d %g %d: %g %d %d %g %d\n",
+	 a1.a, a1.b, a1.c, a1.d, a1.e,
+	 a2.a, a2.b, a2.c, a2.d, a2.e,
+	 result.a, result.b, result.c, result.d, result.e);
+  return result;
+}
+
+static void
+cls_struct_19byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_19byte a1, a2;
+
+  a1 = *(struct cls_struct_19byte*)(args[0]);
+  a2 = *(struct cls_struct_19byte*)(args[1]);
+
+  *(cls_struct_19byte*)resp = cls_struct_19byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[6];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+  struct cls_struct_19byte g_dbl = { 1.0, 127, 126, 3.0, 120 };
+  struct cls_struct_19byte f_dbl = { 4.0, 125, 124, 5.0, 119 };
+  struct cls_struct_19byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_double;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_19byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 127 126 3 120 4 125 124 5 119: 5 252 250 8 239" } */
+  printf("res: %g %d %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 5 252 250 8 239" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_19byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_19byte(*)(cls_struct_19byte, cls_struct_19byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n1 127 126 3 120 4 125 124 5 119: 5 252 250 8 239" } */
+  printf("res: %g %d %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 5 252 250 8 239" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_1_1byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_1_1byte.c
new file mode 100644
index 0000000..82492c0
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_1_1byte.c
@@ -0,0 +1,89 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Especially with small structures which may fit in one
+		register. Depending on the ABI.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030902	 */
+
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_1_1byte {
+  unsigned char a;
+} cls_struct_1_1byte;
+
+cls_struct_1_1byte cls_struct_1_1byte_fn(struct cls_struct_1_1byte a1,
+			    struct cls_struct_1_1byte a2)
+{
+  struct cls_struct_1_1byte result;
+
+  result.a = a1.a + a2.a;
+
+  printf("%d %d: %d\n", a1.a, a2.a, result.a);
+
+  return  result;
+}
+
+static void
+cls_struct_1_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		      void* userdata __UNUSED__)
+{
+
+  struct cls_struct_1_1byte a1, a2;
+
+  a1 = *(struct cls_struct_1_1byte*)(args[0]);
+  a2 = *(struct cls_struct_1_1byte*)(args[1]);
+
+  *(cls_struct_1_1byte*)resp = cls_struct_1_1byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[2];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_1_1byte g_dbl = { 12 };
+  struct cls_struct_1_1byte f_dbl = { 178 };
+  struct cls_struct_1_1byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_1_1byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 178: 190" } */
+  printf("res: %d\n", res_dbl.a);
+  /* { dg-output "\nres: 190" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_1_1byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_1_1byte(*)(cls_struct_1_1byte, cls_struct_1_1byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 178: 190" } */
+  printf("res: %d\n", res_dbl.a);
+  /* { dg-output "\nres: 190" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_20byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_20byte.c
new file mode 100644
index 0000000..3f8bb28
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_20byte.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_20byte {
+  double a;
+  double b;
+  int c;
+} cls_struct_20byte;
+
+cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1,
+			    struct cls_struct_20byte a2)
+{
+  struct cls_struct_20byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%g %g %d %g %g %d: %g %g %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c,
+	 result.a, result.b, result.c);
+  return result;
+}
+
+static void
+cls_struct_20byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_20byte a1, a2;
+
+  a1 = *(struct cls_struct_20byte*)(args[0]);
+  a2 = *(struct cls_struct_20byte*)(args[1]);
+
+  *(cls_struct_20byte*)resp = cls_struct_20byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_20byte g_dbl = { 1.0, 2.0, 3 };
+  struct cls_struct_20byte f_dbl = { 4.0, 5.0, 7 };
+  struct cls_struct_20byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_sint;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_20byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 2 3 4 5 7: 5 7 10" } */
+  printf("res: %g %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 5 7 10" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_20byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */
+  printf("res: %g %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 5 7 10" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_20byte1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_20byte1.c
new file mode 100644
index 0000000..6562727
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_20byte1.c
@@ -0,0 +1,93 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_20byte {
+  int a;
+  double b;
+  double c;
+} cls_struct_20byte;
+
+cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1,
+			    struct cls_struct_20byte a2)
+{
+  struct cls_struct_20byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %g %d %g %g: %d %g %g\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c,
+	 result.a, result.b, result.c);
+  return result;
+}
+
+static void
+cls_struct_20byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_20byte a1, a2;
+
+  a1 = *(struct cls_struct_20byte*)(args[0]);
+  a2 = *(struct cls_struct_20byte*)(args[1]);
+
+  *(cls_struct_20byte*)resp = cls_struct_20byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+  struct cls_struct_20byte g_dbl = { 1, 2.0, 3.0 };
+  struct cls_struct_20byte f_dbl = { 4, 5.0, 7.0 };
+  struct cls_struct_20byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_sint;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_double;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_20byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 2 3 4 5 7: 5 7 10" } */
+  printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 5 7 10" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_20byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */
+  printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 5 7 10" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_24byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_24byte.c
new file mode 100644
index 0000000..1d82f6e
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_24byte.c
@@ -0,0 +1,113 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_24byte {
+  double a;
+  double b;
+  int c;
+  float d;
+} cls_struct_24byte;
+
+cls_struct_24byte cls_struct_24byte_fn(struct cls_struct_24byte b0,
+			    struct cls_struct_24byte b1,
+			    struct cls_struct_24byte b2,
+			    struct cls_struct_24byte b3)
+{
+  struct cls_struct_24byte result;
+
+  result.a = b0.a + b1.a + b2.a + b3.a;
+  result.b = b0.b + b1.b + b2.b + b3.b;
+  result.c = b0.c + b1.c + b2.c + b3.c;
+  result.d = b0.d + b1.d + b2.d + b3.d;
+
+  printf("%g %g %d %g %g %g %d %g %g %g %d %g %g %g %d %g: %g %g %d %g\n",
+	 b0.a, b0.b, b0.c, b0.d,
+	 b1.a, b1.b, b1.c, b1.d,
+	 b2.a, b2.b, b2.c, b2.d,
+	 b3.a, b3.b, b3.c, b2.d,
+	 result.a, result.b, result.c, result.d);
+
+  return result;
+}
+
+static void
+cls_struct_24byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_24byte b0, b1, b2, b3;
+
+  b0 = *(struct cls_struct_24byte*)(args[0]);
+  b1 = *(struct cls_struct_24byte*)(args[1]);
+  b2 = *(struct cls_struct_24byte*)(args[2]);
+  b3 = *(struct cls_struct_24byte*)(args[3]);
+
+  *(cls_struct_24byte*)resp = cls_struct_24byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_24byte e_dbl = { 9.0, 2.0, 6, 5.0 };
+  struct cls_struct_24byte f_dbl = { 1.0, 2.0, 3, 7.0 };
+  struct cls_struct_24byte g_dbl = { 4.0, 5.0, 7, 9.0 };
+  struct cls_struct_24byte h_dbl = { 8.0, 6.0, 1, 4.0 };
+  struct cls_struct_24byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_sint;
+  cls_struct_fields[3] = &ffi_type_float;
+  cls_struct_fields[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = &cls_struct_type;
+  dbl_arg_types[3] = &cls_struct_type;
+  dbl_arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = &h_dbl;
+  args_dbl[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_24byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */
+  printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 22 15 17 25" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_24byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_24byte(*)(cls_struct_24byte,
+				   cls_struct_24byte,
+				   cls_struct_24byte,
+				   cls_struct_24byte))
+	     (code))(e_dbl, f_dbl, g_dbl, h_dbl);
+  /* { dg-output "\n9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */
+  printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 22 15 17 25" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_2byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_2byte.c
new file mode 100644
index 0000000..81bb0a6
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_2byte.c
@@ -0,0 +1,90 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Especially with small structures which may fit in one
+		register. Depending on the ABI.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_2byte {
+  unsigned char a;
+  unsigned char b;
+} cls_struct_2byte;
+
+cls_struct_2byte cls_struct_2byte_fn(struct cls_struct_2byte a1,
+			    struct cls_struct_2byte a2)
+{
+  struct cls_struct_2byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_2byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_2byte a1, a2;
+
+  a1 = *(struct cls_struct_2byte*)(args[0]);
+  a2 = *(struct cls_struct_2byte*)(args[1]);
+
+  *(cls_struct_2byte*)resp = cls_struct_2byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_2byte g_dbl = { 12, 127 };
+  struct cls_struct_2byte f_dbl = { 1, 13 };
+  struct cls_struct_2byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_2byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 127 1 13: 13 140" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 13 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_2byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_2byte(*)(cls_struct_2byte, cls_struct_2byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 127 1 13: 13 140" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 13 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_3_1byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_3_1byte.c
new file mode 100644
index 0000000..b782746
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_3_1byte.c
@@ -0,0 +1,95 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Especially with small structures which may fit in one
+		register. Depending on the ABI.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030902	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_3_1byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+} cls_struct_3_1byte;
+
+cls_struct_3_1byte cls_struct_3_1byte_fn(struct cls_struct_3_1byte a1,
+			    struct cls_struct_3_1byte a2)
+{
+  struct cls_struct_3_1byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c,
+	 a2.a, a2.b, a2.c,
+	 result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_3_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		      void* userdata __UNUSED__)
+{
+
+  struct cls_struct_3_1byte a1, a2;
+
+  a1 = *(struct cls_struct_3_1byte*)(args[0]);
+  a2 = *(struct cls_struct_3_1byte*)(args[1]);
+
+  *(cls_struct_3_1byte*)resp = cls_struct_3_1byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_3_1byte g_dbl = { 12, 13, 14 };
+  struct cls_struct_3_1byte f_dbl = { 178, 179, 180 };
+  struct cls_struct_3_1byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_3_1byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 13 14 178 179 180: 190 192 194" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 190 192 194" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3_1byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_3_1byte(*)(cls_struct_3_1byte, cls_struct_3_1byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 13 14 178 179 180: 190 192 194" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 190 192 194" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_3byte1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_3byte1.c
new file mode 100644
index 0000000..a02c463
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_3byte1.c
@@ -0,0 +1,90 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Especially with small structures which may fit in one
+		register. Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_3byte {
+  unsigned short a;
+  unsigned char b;
+} cls_struct_3byte;
+
+cls_struct_3byte cls_struct_3byte_fn(struct cls_struct_3byte a1,
+			    struct cls_struct_3byte a2)
+{
+  struct cls_struct_3byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_3byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_3byte a1, a2;
+
+  a1 = *(struct cls_struct_3byte*)(args[0]);
+  a2 = *(struct cls_struct_3byte*)(args[1]);
+
+  *(cls_struct_3byte*)resp = cls_struct_3byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_3byte g_dbl = { 12, 119 };
+  struct cls_struct_3byte f_dbl = { 1, 15 };
+  struct cls_struct_3byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_ushort;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_3byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 119 1 15: 13 134" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 13 134" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_3byte(*)(cls_struct_3byte, cls_struct_3byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 119 1 15: 13 134" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 13 134" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_3byte2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_3byte2.c
new file mode 100644
index 0000000..c7251ce
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_3byte2.c
@@ -0,0 +1,90 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Especially with small structures which may fit in one
+		register. Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_3byte_1 {
+  unsigned char a;
+  unsigned short b;
+} cls_struct_3byte_1;
+
+cls_struct_3byte_1 cls_struct_3byte_fn1(struct cls_struct_3byte_1 a1,
+			    struct cls_struct_3byte_1 a2)
+{
+  struct cls_struct_3byte_1 result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_3byte_gn1(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+
+  struct cls_struct_3byte_1 a1, a2;
+
+  a1 = *(struct cls_struct_3byte_1*)(args[0]);
+  a2 = *(struct cls_struct_3byte_1*)(args[1]);
+
+  *(cls_struct_3byte_1*)resp = cls_struct_3byte_fn1(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_3byte_1 g_dbl = { 15, 125 };
+  struct cls_struct_3byte_1 f_dbl = { 9, 19 };
+  struct cls_struct_3byte_1 res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_3byte_fn1), &res_dbl, args_dbl);
+  /* { dg-output "15 125 9 19: 24 144" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 24 144" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3byte_gn1, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_3byte_1(*)(cls_struct_3byte_1, cls_struct_3byte_1))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n15 125 9 19: 24 144" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 24 144" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_4_1byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_4_1byte.c
new file mode 100644
index 0000000..2d6d8b6
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_4_1byte.c
@@ -0,0 +1,98 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Especially with small structures which may fit in one
+		register. Depending on the ABI.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030902	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_4_1byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+} cls_struct_4_1byte;
+
+cls_struct_4_1byte cls_struct_4_1byte_fn(struct cls_struct_4_1byte a1,
+			    struct cls_struct_4_1byte a2)
+{
+  struct cls_struct_4_1byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
+	 a2.a, a2.b, a2.c, a2.d,
+	 result.a, result.b, result.c, result.d);
+
+  return  result;
+}
+
+static void
+cls_struct_4_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		      void* userdata __UNUSED__)
+{
+
+  struct cls_struct_4_1byte a1, a2;
+
+  a1 = *(struct cls_struct_4_1byte*)(args[0]);
+  a2 = *(struct cls_struct_4_1byte*)(args[1]);
+
+  *(cls_struct_4_1byte*)resp = cls_struct_4_1byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_4_1byte g_dbl = { 12, 13, 14, 15 };
+  struct cls_struct_4_1byte f_dbl = { 178, 179, 180, 181 };
+  struct cls_struct_4_1byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_4_1byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 13 14 15 178 179 180 181: 190 192 194 196" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 190 192 194 196" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_4_1byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_4_1byte(*)(cls_struct_4_1byte, cls_struct_4_1byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 13 14 15 178 179 180 181: 190 192 194 196" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 190 192 194 196" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_4byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_4byte.c
new file mode 100644
index 0000000..4ac3787
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_4byte.c
@@ -0,0 +1,90 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_4byte {
+  unsigned short a;
+  unsigned short b;
+} cls_struct_4byte;
+
+cls_struct_4byte cls_struct_4byte_fn(struct cls_struct_4byte a1,
+			    struct cls_struct_4byte a2)
+{
+  struct cls_struct_4byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_4byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_4byte a1, a2;
+
+  a1 = *(struct cls_struct_4byte*)(args[0]);
+  a2 = *(struct cls_struct_4byte*)(args[1]);
+
+  *(cls_struct_4byte*)resp = cls_struct_4byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_4byte g_dbl = { 127, 120 };
+  struct cls_struct_4byte f_dbl = { 12, 128 };
+  struct cls_struct_4byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_ushort;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_4byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 12 128: 139 248" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 139 248" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_4byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_4byte(*)(cls_struct_4byte, cls_struct_4byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 12 128: 139 248" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 139 248" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_5_1_byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_5_1_byte.c
new file mode 100644
index 0000000..ad9d51c
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_5_1_byte.c
@@ -0,0 +1,109 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050708	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_5byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+  unsigned char e;
+} cls_struct_5byte;
+
+cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1,
+			    struct cls_struct_5byte a2)
+{
+  struct cls_struct_5byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+
+  printf("%d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d\n",
+	 a1.a, a1.b, a1.c, a1.d, a1.e,
+	 a2.a, a2.b, a2.c, a2.d, a2.e,
+	 result.a, result.b, result.c, result.d, result.e);
+
+  return  result;
+}
+
+static void
+cls_struct_5byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_5byte a1, a2;
+
+  a1 = *(struct cls_struct_5byte*)(args[0]);
+  a2 = *(struct cls_struct_5byte*)(args[1]);
+
+  *(cls_struct_5byte*)resp = cls_struct_5byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[6];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_5byte g_dbl = { 127, 120, 1, 3, 4 };
+  struct cls_struct_5byte f_dbl = { 12, 128, 9, 3, 4 };
+  struct cls_struct_5byte res_dbl = { 0, 0, 0, 0, 0 };
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_5byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 3 4 12 128 9 3 4: 139 248 10 6 8" } */
+  printf("res: %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 139 248 10 6 8" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+  res_dbl.d = 0;
+  res_dbl.e = 0;
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_5byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_5byte(*)(cls_struct_5byte, cls_struct_5byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 3 4 12 128 9 3 4: 139 248 10 6 8" } */
+  printf("res: %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 139 248 10 6 8" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_5byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_5byte.c
new file mode 100644
index 0000000..4e0c000
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_5byte.c
@@ -0,0 +1,98 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_5byte {
+  unsigned short a;
+  unsigned short b;
+  unsigned char c;
+} cls_struct_5byte;
+
+cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1,
+			    struct cls_struct_5byte a2)
+{
+  struct cls_struct_5byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c,
+	 a2.a, a2.b, a2.c,
+	 result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_5byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_5byte a1, a2;
+
+  a1 = *(struct cls_struct_5byte*)(args[0]);
+  a2 = *(struct cls_struct_5byte*)(args[1]);
+
+  *(cls_struct_5byte*)resp = cls_struct_5byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_5byte g_dbl = { 127, 120, 1 };
+  struct cls_struct_5byte f_dbl = { 12, 128, 9 };
+  struct cls_struct_5byte res_dbl = { 0, 0, 0 };
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_ushort;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_5byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 12 128 9: 139 248 10" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 139 248 10" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_5byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_5byte(*)(cls_struct_5byte, cls_struct_5byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 12 128 9: 139 248 10" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 139 248 10" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_64byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_64byte.c
new file mode 100644
index 0000000..a55edc2
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_64byte.c
@@ -0,0 +1,124 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check bigger struct which overlaps
+		the gp and fp register count on Darwin/AIX/ppc64.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_64byte {
+  double a;
+  double b;
+  double c;
+  double d;
+  double e;
+  double f;
+  double g;
+  double h;
+} cls_struct_64byte;
+
+cls_struct_64byte cls_struct_64byte_fn(struct cls_struct_64byte b0,
+			    struct cls_struct_64byte b1,
+			    struct cls_struct_64byte b2,
+			    struct cls_struct_64byte b3)
+{
+  struct cls_struct_64byte result;
+
+  result.a = b0.a + b1.a + b2.a + b3.a;
+  result.b = b0.b + b1.b + b2.b + b3.b;
+  result.c = b0.c + b1.c + b2.c + b3.c;
+  result.d = b0.d + b1.d + b2.d + b3.d;
+  result.e = b0.e + b1.e + b2.e + b3.e;
+  result.f = b0.f + b1.f + b2.f + b3.f;
+  result.g = b0.g + b1.g + b2.g + b3.g;
+  result.h = b0.h + b1.h + b2.h + b3.h;
+
+  printf("%g %g %g %g %g %g %g %g\n", result.a, result.b, result.c,
+	 result.d, result.e, result.f, result.g, result.h);
+
+  return result;
+}
+
+static void
+cls_struct_64byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_64byte b0, b1, b2, b3;
+
+  b0 = *(struct cls_struct_64byte*)(args[0]);
+  b1 = *(struct cls_struct_64byte*)(args[1]);
+  b2 = *(struct cls_struct_64byte*)(args[2]);
+  b3 = *(struct cls_struct_64byte*)(args[3]);
+
+  *(cls_struct_64byte*)resp = cls_struct_64byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[9];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_64byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0 };
+  struct cls_struct_64byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0 };
+  struct cls_struct_64byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0 };
+  struct cls_struct_64byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0 };
+  struct cls_struct_64byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_double;
+  cls_struct_fields[3] = &ffi_type_double;
+  cls_struct_fields[4] = &ffi_type_double;
+  cls_struct_fields[5] = &ffi_type_double;
+  cls_struct_fields[6] = &ffi_type_double;
+  cls_struct_fields[7] = &ffi_type_double;
+  cls_struct_fields[8] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = &cls_struct_type;
+  dbl_arg_types[3] = &cls_struct_type;
+  dbl_arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = &h_dbl;
+  args_dbl[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_64byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "22 15 17 25 6 13 19 18" } */
+  printf("res: %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h);
+  /* { dg-output "\nres: 22 15 17 25 6 13 19 18" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_64byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_64byte(*)(cls_struct_64byte,
+				   cls_struct_64byte,
+				   cls_struct_64byte,
+				   cls_struct_64byte))
+	     (code))(e_dbl, f_dbl, g_dbl, h_dbl);
+  /* { dg-output "\n22 15 17 25 6 13 19 18" } */
+  printf("res: %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h);
+  /* { dg-output "\nres: 22 15 17 25 6 13 19 18" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_6_1_byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_6_1_byte.c
new file mode 100644
index 0000000..b4dcdba
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_6_1_byte.c
@@ -0,0 +1,113 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050708	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_6byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+  unsigned char e;
+  unsigned char f;
+} cls_struct_6byte;
+
+cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1,
+			    struct cls_struct_6byte a2)
+{
+  struct cls_struct_6byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+  result.f = a1.f + a2.f;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d %d\n",
+	 a1.a, a1.b, a1.c, a1.d, a1.e, a1.f,
+	 a2.a, a2.b, a2.c, a2.d, a2.e, a2.f,
+	 result.a, result.b, result.c, result.d, result.e, result.f);
+
+  return  result;
+}
+
+static void
+cls_struct_6byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_6byte a1, a2;
+
+  a1 = *(struct cls_struct_6byte*)(args[0]);
+  a2 = *(struct cls_struct_6byte*)(args[1]);
+
+  *(cls_struct_6byte*)resp = cls_struct_6byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[7];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_6byte g_dbl = { 127, 120, 1, 3, 4, 5 };
+  struct cls_struct_6byte f_dbl = { 12, 128, 9, 3, 4, 5 };
+  struct cls_struct_6byte res_dbl = { 0, 0, 0, 0, 0, 0 };
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = &ffi_type_uchar;
+  cls_struct_fields[6] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_6byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 3 4 5 12 128 9 3 4 5: 139 248 10 6 8 10" } */
+  printf("res: %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f);
+  /* { dg-output "\nres: 139 248 10 6 8 10" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+  res_dbl.d = 0;
+  res_dbl.e = 0;
+  res_dbl.f = 0;
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_6byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_6byte(*)(cls_struct_6byte, cls_struct_6byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 3 4 5 12 128 9 3 4 5: 139 248 10 6 8 10" } */
+  printf("res: %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f);
+  /* { dg-output "\nres: 139 248 10 6 8 10" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_6byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_6byte.c
new file mode 100644
index 0000000..7406780
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_6byte.c
@@ -0,0 +1,99 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_6byte {
+  unsigned short a;
+  unsigned short b;
+  unsigned char c;
+  unsigned char d;
+} cls_struct_6byte;
+
+cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1,
+			    struct cls_struct_6byte a2)
+{
+  struct cls_struct_6byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
+	 a2.a, a2.b, a2.c, a2.d,
+	 result.a, result.b, result.c, result.d);
+
+  return  result;
+}
+
+static void
+cls_struct_6byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_6byte a1, a2;
+
+  a1 = *(struct cls_struct_6byte*)(args[0]);
+  a2 = *(struct cls_struct_6byte*)(args[1]);
+
+  *(cls_struct_6byte*)resp = cls_struct_6byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_6byte g_dbl = { 127, 120, 1, 128 };
+  struct cls_struct_6byte f_dbl = { 12, 128, 9, 127 };
+  struct cls_struct_6byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_ushort;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_6byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 128 12 128 9 127: 139 248 10 255" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 139 248 10 255" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_6byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_6byte(*)(cls_struct_6byte, cls_struct_6byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 128 12 128 9 127: 139 248 10 255" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 139 248 10 255" } */
+
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_7_1_byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_7_1_byte.c
new file mode 100644
index 0000000..14a7e96
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_7_1_byte.c
@@ -0,0 +1,117 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050708	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_7byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+  unsigned char e;
+  unsigned char f;
+  unsigned char g;
+} cls_struct_7byte;
+
+cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1,
+			    struct cls_struct_7byte a2)
+{
+  struct cls_struct_7byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+  result.f = a1.f + a2.f;
+  result.g = a1.g + a2.g;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d %d %d\n",
+	 a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+	 a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
+	 result.a, result.b, result.c, result.d, result.e, result.f, result.g);
+
+  return  result;
+}
+
+static void
+cls_struct_7byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_7byte a1, a2;
+
+  a1 = *(struct cls_struct_7byte*)(args[0]);
+  a2 = *(struct cls_struct_7byte*)(args[1]);
+
+  *(cls_struct_7byte*)resp = cls_struct_7byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[8];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_7byte g_dbl = { 127, 120, 1, 3, 4, 5, 6 };
+  struct cls_struct_7byte f_dbl = { 12, 128, 9, 3, 4, 5, 6 };
+  struct cls_struct_7byte res_dbl = { 0, 0, 0, 0, 0, 0, 0 };
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = &ffi_type_uchar;
+  cls_struct_fields[6] = &ffi_type_uchar;
+  cls_struct_fields[7] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_7byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 3 4 5 6 12 128 9 3 4 5 6: 139 248 10 6 8 10 12" } */
+  printf("res: %d %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+  /* { dg-output "\nres: 139 248 10 6 8 10 12" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+  res_dbl.d = 0;
+  res_dbl.e = 0;
+  res_dbl.f = 0;
+  res_dbl.g = 0;
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_7byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 3 4 5 6 12 128 9 3 4 5 6: 139 248 10 6 8 10 12" } */
+  printf("res: %d %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+  /* { dg-output "\nres: 139 248 10 6 8 10 12" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_7byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_7byte.c
new file mode 100644
index 0000000..1645cc6
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_7byte.c
@@ -0,0 +1,97 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_7byte {
+  unsigned short a;
+  unsigned short b;
+  unsigned char c;
+  unsigned short d;
+} cls_struct_7byte;
+
+cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1,
+			    struct cls_struct_7byte a2)
+{
+  struct cls_struct_7byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
+	 a2.a, a2.b, a2.c, a2.d,
+	 result.a, result.b, result.c, result.d);
+
+  return  result;
+}
+
+static void
+cls_struct_7byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_7byte a1, a2;
+
+  a1 = *(struct cls_struct_7byte*)(args[0]);
+  a2 = *(struct cls_struct_7byte*)(args[1]);
+
+  *(cls_struct_7byte*)resp = cls_struct_7byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_7byte g_dbl = { 127, 120, 1, 254 };
+  struct cls_struct_7byte f_dbl = { 12, 128, 9, 255 };
+  struct cls_struct_7byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_ushort;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_ushort;
+  cls_struct_fields[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_7byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 254 12 128 9 255: 139 248 10 509" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 139 248 10 509" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_7byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 254 12 128 9 255: 139 248 10 509" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 139 248 10 509" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_8byte.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_8byte.c
new file mode 100644
index 0000000..f6c1ea5
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_8byte.c
@@ -0,0 +1,88 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_8byte {
+  int a;
+  float b;
+} cls_struct_8byte;
+
+cls_struct_8byte cls_struct_8byte_fn(struct cls_struct_8byte a1,
+			    struct cls_struct_8byte a2)
+{
+  struct cls_struct_8byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %g %d %g: %d %g\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_8byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_8byte a1, a2;
+
+  a1 = *(struct cls_struct_8byte*)(args[0]);
+  a2 = *(struct cls_struct_8byte*)(args[1]);
+
+  *(cls_struct_8byte*)resp = cls_struct_8byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_8byte g_dbl = { 1, 2.0 };
+  struct cls_struct_8byte f_dbl = { 4, 5.0 };
+  struct cls_struct_8byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_sint;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_8byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 2 4 5: 5 7" } */
+  printf("res: %d %g\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 5 7" } */
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_8byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_8byte(*)(cls_struct_8byte, cls_struct_8byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n1 2 4 5: 5 7" } */
+  printf("res: %d %g\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 5 7" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_9byte1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_9byte1.c
new file mode 100644
index 0000000..0b85722
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_9byte1.c
@@ -0,0 +1,90 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Darwin/AIX do double-word
+		alignment of the struct if the first element is a double.
+		Check that it does not here.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030914	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_9byte {
+  int a;
+  double b;
+} cls_struct_9byte;
+
+cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1,
+			    struct cls_struct_9byte b2)
+{
+  struct cls_struct_9byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+
+  printf("%d %g %d %g: %d %g\n", b1.a, b1.b,  b2.a, b2.b,
+	 result.a, result.b);
+
+  return result;
+}
+
+static void cls_struct_9byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+				void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_9byte b1, b2;
+
+  b1 = *(struct cls_struct_9byte*)(args[0]);
+  b2 = *(struct cls_struct_9byte*)(args[1]);
+
+  *(cls_struct_9byte*)resp = cls_struct_9byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+  struct cls_struct_9byte h_dbl = { 7, 8.0};
+  struct cls_struct_9byte j_dbl = { 1, 9.0};
+  struct cls_struct_9byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_sint;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &h_dbl;
+  args_dbl[1] = &j_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_9byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "7 8 1 9: 8 17" } */
+  printf("res: %d %g\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 8 17" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_9byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_9byte(*)(cls_struct_9byte, cls_struct_9byte))(code))(h_dbl, j_dbl);
+  /* { dg-output "\n7 8 1 9: 8 17" } */
+  printf("res: %d %g\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 8 17" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_9byte2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_9byte2.c
new file mode 100644
index 0000000..edf991d
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_9byte2.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Darwin/AIX do double-word
+		alignment of the struct if the first element is a double.
+		Check that it does here.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030914	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_9byte {
+  double a;
+  int b;
+} cls_struct_9byte;
+
+cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1,
+			    struct cls_struct_9byte b2)
+{
+  struct cls_struct_9byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+
+  printf("%g %d %g %d: %g %d\n", b1.a, b1.b,  b2.a, b2.b,
+	 result.a, result.b);
+
+  return result;
+}
+
+static void cls_struct_9byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+				void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_9byte b1, b2;
+
+  b1 = *(struct cls_struct_9byte*)(args[0]);
+  b2 = *(struct cls_struct_9byte*)(args[1]);
+
+  *(cls_struct_9byte*)resp = cls_struct_9byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+  struct cls_struct_9byte h_dbl = { 7.0, 8};
+  struct cls_struct_9byte j_dbl = { 1.0, 9};
+  struct cls_struct_9byte res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_sint;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &h_dbl;
+  args_dbl[1] = &j_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_9byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "7 8 1 9: 8 17" } */
+  printf("res: %g %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 8 17" } */
+
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_9byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_9byte(*)(cls_struct_9byte, cls_struct_9byte))(code))(h_dbl, j_dbl);
+  /* { dg-output "\n7 8 1 9: 8 17" } */
+  printf("res: %g %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 8 17" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_double.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_double.c
new file mode 100644
index 0000000..aad5f3c
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_double.c
@@ -0,0 +1,93 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  double b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_float.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_float.c
new file mode 100644
index 0000000..37e0855
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_float.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  float b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, (double)a1.b, a1.c, a2.a, (double)a2.b, a2.c, result.a, (double)result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble.c
new file mode 100644
index 0000000..b3322d8
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble.c
@@ -0,0 +1,92 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of long double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  long double b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, (double)a1.b, a1.c, a2.a, (double)a2.b, a2.c, result.a, (double)result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_longdouble;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split.c
new file mode 100644
index 0000000..15f9365
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split.c
@@ -0,0 +1,134 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of long double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
+/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  long double a;
+  long double b;
+  long double c;
+  long double d;
+  long double e;
+  long double f;
+  long double g;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(
+	cls_struct_align	a1,
+	cls_struct_align	a2)
+{
+	struct cls_struct_align r;
+
+	r.a = a1.a + a2.a;
+	r.b = a1.b + a2.b;
+	r.c = a1.c + a2.c;
+	r.d = a1.d + a2.d;
+	r.e = a1.e + a2.e;
+	r.f = a1.f + a2.f;
+	r.g = a1.g + a2.g;
+
+	printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg: "
+		"%Lg %Lg %Lg %Lg %Lg %Lg %Lg\n",
+		a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+		a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
+		r.a, r.b, r.c, r.d, r.e, r.f, r.g);
+
+	return r;
+}
+
+cls_struct_align cls_struct_align_fn2(
+	cls_struct_align	a1)
+{
+	struct cls_struct_align r;
+
+	r.a = a1.a + 1;
+	r.b = a1.b + 1;
+	r.c = a1.c + 1;
+	r.d = a1.d + 1;
+	r.e = a1.e + 1;
+	r.f = a1.f + 1;
+	r.g = a1.g + 1;
+
+	printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg: "
+		"%Lg %Lg %Lg %Lg %Lg %Lg %Lg\n",
+		a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+		r.a, r.b, r.c, r.d, r.e, r.f, r.g);
+
+	return r;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, 
+		    void* userdata __UNUSED__)
+{
+	struct cls_struct_align a1, a2;
+
+	a1 = *(struct cls_struct_align*)(args[0]);
+	a2 = *(struct cls_struct_align*)(args[1]);
+
+	*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[3];
+	ffi_type* cls_struct_fields[8];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[3];
+
+	struct cls_struct_align g_dbl = { 1, 2, 3, 4, 5, 6, 7 };
+	struct cls_struct_align f_dbl = { 8, 9, 10, 11, 12, 13, 14 };
+	struct cls_struct_align res_dbl;
+
+	cls_struct_type.size = 0;
+	cls_struct_type.alignment = 0;
+	cls_struct_type.type = FFI_TYPE_STRUCT;
+	cls_struct_type.elements = cls_struct_fields;
+
+	cls_struct_fields[0] = &ffi_type_longdouble;
+	cls_struct_fields[1] = &ffi_type_longdouble;
+	cls_struct_fields[2] = &ffi_type_longdouble;
+	cls_struct_fields[3] = &ffi_type_longdouble;
+	cls_struct_fields[4] = &ffi_type_longdouble;
+	cls_struct_fields[5] = &ffi_type_longdouble;
+	cls_struct_fields[6] = &ffi_type_longdouble;
+	cls_struct_fields[7] = NULL;
+
+	dbl_arg_types[0] = &cls_struct_type;
+	dbl_arg_types[1] = &cls_struct_type;
+	dbl_arg_types[2] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		dbl_arg_types) == FFI_OK);
+
+	args_dbl[0] = &g_dbl;
+	args_dbl[1] = &f_dbl;
+	args_dbl[2] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+	/* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+	printf("res: %Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+	/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+	/* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+	printf("res: %Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+	/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c
new file mode 100644
index 0000000..ca1c356
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c
@@ -0,0 +1,117 @@
+/*	Area:			ffi_call, closure_call
+	Purpose:		Check structure alignment of long double.
+	Limitations:	none.
+	PR:				none.
+	Originator:		Blake Chaffin	6/18/2007
+*/
+
+/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-do run { xfail strongarm*-*-* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
+/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  long double a;
+  long double b;
+  long double c;
+  long double d;
+  long double e;
+  double f;
+  long double g;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(
+	cls_struct_align	a1,
+	cls_struct_align	a2)
+{
+	struct cls_struct_align r;
+
+	r.a = a1.a + a2.a;
+	r.b = a1.b + a2.b;
+	r.c = a1.c + a2.c;
+	r.d = a1.d + a2.d;
+	r.e = a1.e + a2.e;
+	r.f = a1.f + a2.f;
+	r.g = a1.g + a2.g;
+
+	printf("%Lg %Lg %Lg %Lg %Lg %g %Lg %Lg %Lg %Lg %Lg %Lg %g %Lg: "
+		"%Lg %Lg %Lg %Lg %Lg %g %Lg\n",
+		a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+		a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
+		r.a, r.b, r.c, r.d, r.e, r.f, r.g);
+
+	return r;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, 
+		    void* userdata __UNUSED__)
+{
+	struct cls_struct_align a1, a2;
+
+	a1 = *(struct cls_struct_align*)(args[0]);
+	a2 = *(struct cls_struct_align*)(args[1]);
+
+	*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[3];
+	ffi_type* cls_struct_fields[8];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[3];
+
+	struct cls_struct_align g_dbl = { 1, 2, 3, 4, 5, 6, 7 };
+	struct cls_struct_align f_dbl = { 8, 9, 10, 11, 12, 13, 14 };
+	struct cls_struct_align res_dbl;
+
+	cls_struct_type.size = 0;
+	cls_struct_type.alignment = 0;
+	cls_struct_type.type = FFI_TYPE_STRUCT;
+	cls_struct_type.elements = cls_struct_fields;
+
+	cls_struct_fields[0] = &ffi_type_longdouble;
+	cls_struct_fields[1] = &ffi_type_longdouble;
+	cls_struct_fields[2] = &ffi_type_longdouble;
+	cls_struct_fields[3] = &ffi_type_longdouble;
+	cls_struct_fields[4] = &ffi_type_longdouble;
+	cls_struct_fields[5] = &ffi_type_double;
+	cls_struct_fields[6] = &ffi_type_longdouble;
+	cls_struct_fields[7] = NULL;
+
+	dbl_arg_types[0] = &cls_struct_type;
+	dbl_arg_types[1] = &cls_struct_type;
+	dbl_arg_types[2] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		dbl_arg_types) == FFI_OK);
+
+	args_dbl[0] = &g_dbl;
+	args_dbl[1] = &f_dbl;
+	args_dbl[2] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+	/* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+	printf("res: %Lg %Lg %Lg %Lg %Lg %g %Lg\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+	/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+	/* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+	printf("res: %Lg %Lg %Lg %Lg %Lg %g %Lg\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+	/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+  exit(0);
+}
+
+
+
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_pointer.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_pointer.c
new file mode 100644
index 0000000..8fbf36a
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_pointer.c
@@ -0,0 +1,95 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of pointer.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  void *b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = (void *)((uintptr_t)a1.b + (uintptr_t)a2.b);
+  result.c = a1.c + a2.c;
+
+  printf("%d %" PRIuPTR " %d %d %" PRIuPTR " %d: %d %" PRIuPTR " %d\n", 
+         a1.a, (uintptr_t)a1.b, a1.c,
+	 a2.a, (uintptr_t)a2.b, a2.c,
+         result.a, (uintptr_t)result.b,
+	 result.c);
+
+  return result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_align g_dbl = { 12, (void *)4951, 127 };
+  struct cls_struct_align f_dbl = { 1, (void *)9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_pointer;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %" PRIuPTR " %d\n", res_dbl.a, (uintptr_t)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %" PRIuPTR " %d\n", res_dbl.a, (uintptr_t)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_sint16.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_sint16.c
new file mode 100644
index 0000000..039b874
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_sint16.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of sint16.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  signed short b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_sshort;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_sint32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_sint32.c
new file mode 100644
index 0000000..c96c6d1
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_sint32.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of sint32.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  signed int b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_sint;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_sint64.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_sint64.c
new file mode 100644
index 0000000..9aa7bdd
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_sint64.c
@@ -0,0 +1,92 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of sint64.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  signed long long b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %" PRIdLL " %d %d %" PRIdLL " %d: %d %" PRIdLL " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_sint64;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_uint16.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_uint16.c
new file mode 100644
index 0000000..97620b7
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_uint16.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of uint16.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  unsigned short b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_uint32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_uint32.c
new file mode 100644
index 0000000..5766fad
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_uint32.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of uint32.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  unsigned int b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uint;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_uint64.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_uint64.c
new file mode 100644
index 0000000..a52cb89
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_uint64.c
@@ -0,0 +1,93 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of uint64.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+
+/* { dg-do run } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  unsigned long long b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %" PRIdLL " %d %d %" PRIdLL " %d: %d %" PRIdLL " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uint64;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_dbls_struct.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_dbls_struct.c
new file mode 100644
index 0000000..d663791
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_dbls_struct.c
@@ -0,0 +1,66 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check double arguments in structs.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/23/2007	*/
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+typedef struct Dbls {
+	double x;
+	double y;
+} Dbls;
+
+void
+closure_test_fn(Dbls p)
+{
+	printf("%.1f %.1f\n", p.x, p.y);
+}
+
+void
+closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+		void** args, void* userdata __UNUSED__)
+{
+	closure_test_fn(*(Dbls*)args[0]);
+}
+
+int main(int argc __UNUSED__, char** argv __UNUSED__)
+{
+	ffi_cif cif;
+
+        void *code;
+	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	ffi_type*		cl_arg_types[1];
+
+	ffi_type	ts1_type;
+	ffi_type*	ts1_type_elements[4];
+
+	Dbls arg = { 1.0, 2.0 };
+
+	ts1_type.size = 0;
+	ts1_type.alignment = 0;
+	ts1_type.type = FFI_TYPE_STRUCT;
+	ts1_type.elements = ts1_type_elements;
+
+	ts1_type_elements[0] = &ffi_type_double;
+	ts1_type_elements[1] = &ffi_type_double;
+	ts1_type_elements[2] = NULL;
+
+	cl_arg_types[0] = &ts1_type;
+
+	/* Initialize the cif */
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+				 &ffi_type_void, cl_arg_types) == FFI_OK);
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK);
+
+	((void*(*)(Dbls))(code))(arg);
+	/* { dg-output "1.0 2.0\n" } */
+
+	closure_test_fn(arg);
+	/* { dg-output "1.0 2.0\n" } */
+
+	return 0;
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_double.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_double.c
new file mode 100644
index 0000000..84ad4cb
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_double.c
@@ -0,0 +1,43 @@
+/* Area:	closure_call
+   Purpose:	Check return value double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_double_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			      void* userdata __UNUSED__)
+ {
+   *(double *)resp = *(double *)args[0];
+
+   printf("%f: %f\n",*(double *)args[0],
+	  *(double *)resp);
+ }
+typedef double (*cls_ret_double)(double);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  double res;
+
+  cl_arg_types[0] = &ffi_type_double;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_double, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_double_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_double)code))(21474.789);
+  /* { dg-output "21474.789000: 21474.789000" } */
+  printf("res: %.6f\n", res);
+  /* { dg-output "\nres: 21474.789000" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_double_va.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_double_va.c
new file mode 100644
index 0000000..e077f92
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_double_va.c
@@ -0,0 +1,61 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Test doubles passed in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	 */
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+/* { dg-output "" { xfail mips-sgi-irix6* } } PR libffi/46660 */
+
+#include "ffitest.h"
+
+static void
+cls_double_va_fn(ffi_cif* cif __UNUSED__, void* resp, 
+		 void** args, void* userdata __UNUSED__)
+{
+	char*	format		= *(char**)args[0];
+	double	doubleValue	= *(double*)args[1];
+
+	*(ffi_arg*)resp = printf(format, doubleValue);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args[3];
+	ffi_type* arg_types[3];
+
+	char*	format		= "%.1f\n";
+	double	doubleArg	= 7;
+	ffi_arg	res			= 0;
+
+	arg_types[0] = &ffi_type_pointer;
+	arg_types[1] = &ffi_type_double;
+	arg_types[2] = NULL;
+
+	/* This printf call is variadic */
+	CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
+			       arg_types) == FFI_OK);
+
+	args[0] = &format;
+	args[1] = &doubleArg;
+	args[2] = NULL;
+
+	ffi_call(&cif, FFI_FN(printf), &res, args);
+	/* { dg-output "7.0" } */
+	printf("res: %d\n", (int) res);
+	/* { dg-output "\nres: 4" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_double_va_fn, NULL,
+				   code) == FFI_OK);
+
+	res = ((int(*)(char*, ...))(code))(format, doubleArg);
+	/* { dg-output "\n7.0" } */
+	printf("res: %d\n", (int) res);
+	/* { dg-output "\nres: 4" } */
+
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_float.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_float.c
new file mode 100644
index 0000000..0090fed
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_float.c
@@ -0,0 +1,42 @@
+/* Area:	closure_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_float_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata __UNUSED__)
+ {
+   *(float *)resp = *(float *)args[0];
+
+   printf("%g: %g\n",*(float *)args[0],
+	  *(float *)resp);
+ }
+
+typedef float (*cls_ret_float)(float);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  float res;
+
+  cl_arg_types[0] = &ffi_type_float;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_float, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_float_fn, NULL, code)  == FFI_OK);
+  res = ((((cls_ret_float)code)(-2122.12)));
+  /* { dg-output "\\-2122.12: \\-2122.12" } */
+  printf("res: %.6f\n", res);
+  /* { dg-output "\nres: \-2122.120117" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_longdouble.c
new file mode 100644
index 0000000..e6bac1f
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_longdouble.c
@@ -0,0 +1,105 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check long double arguments.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin	*/
+
+/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-do run { xfail arm*-*-* strongarm*-*-* xscale*-*-* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
+/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+
+#include "ffitest.h"
+
+long double cls_ldouble_fn(
+	long double	a1,
+	long double	a2,
+	long double	a3,
+	long double	a4,
+	long double	a5,
+	long double	a6,
+	long double	a7,
+	long double	a8)
+{
+	long double	r = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;
+
+	printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg: %Lg\n",
+		a1, a2, a3, a4, a5, a6, a7, a8, r);
+
+	return r;
+}
+
+static void
+cls_ldouble_gn(ffi_cif* cif __UNUSED__, void* resp, 
+	       void** args, void* userdata __UNUSED__)
+{
+	long double	a1	= *(long double*)args[0];
+	long double	a2	= *(long double*)args[1];
+	long double	a3	= *(long double*)args[2];
+	long double	a4	= *(long double*)args[3];
+	long double	a5	= *(long double*)args[4];
+	long double	a6	= *(long double*)args[5];
+	long double	a7	= *(long double*)args[6];
+	long double	a8	= *(long double*)args[7];
+
+	*(long double*)resp = cls_ldouble_fn(
+		a1, a2, a3, a4, a5, a6, a7, a8);
+}
+
+int main(void)
+{
+	ffi_cif	cif;
+        void* code;
+	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void*			args[9];
+	ffi_type*		arg_types[9];
+	long double		res	= 0;
+
+	long double	arg1	= 1;
+	long double	arg2	= 2;
+	long double	arg3	= 3;
+	long double	arg4	= 4;
+	long double	arg5	= 5;
+	long double	arg6	= 6;
+	long double	arg7	= 7;
+	long double	arg8	= 8;
+
+	arg_types[0] = &ffi_type_longdouble;
+	arg_types[1] = &ffi_type_longdouble;
+	arg_types[2] = &ffi_type_longdouble;
+	arg_types[3] = &ffi_type_longdouble;
+	arg_types[4] = &ffi_type_longdouble;
+	arg_types[5] = &ffi_type_longdouble;
+	arg_types[6] = &ffi_type_longdouble;
+	arg_types[7] = &ffi_type_longdouble;
+	arg_types[8] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 8, &ffi_type_longdouble,
+		arg_types) == FFI_OK);
+
+	args[0] = &arg1;
+	args[1] = &arg2;
+	args[2] = &arg3;
+	args[3] = &arg4;
+	args[4] = &arg5;
+	args[5] = &arg6;
+	args[6] = &arg7;
+	args[7] = &arg8;
+	args[8] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_ldouble_fn), &res, args);
+	/* { dg-output "1 2 3 4 5 6 7 8: 36" } */
+	printf("res: %Lg\n", res);
+	/* { dg-output "\nres: 36" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ldouble_gn, NULL, code) == FFI_OK);
+
+	res = ((long double(*)(long double, long double, long double, long double,
+		long double, long double, long double, long double))(code))(arg1, arg2,
+		arg3, arg4, arg5, arg6, arg7, arg8);
+	/* { dg-output "\n1 2 3 4 5 6 7 8: 36" } */
+	printf("res: %Lg\n", res);
+	/* { dg-output "\nres: 36" } */
+
+	return 0;
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_longdouble_va.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_longdouble_va.c
new file mode 100644
index 0000000..39b438b
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_longdouble_va.c
@@ -0,0 +1,61 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Test long doubles passed in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	 */
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+/* { dg-output "" { xfail avr32*-*-* x86_64-*-mingw* } } */
+/* { dg-output "" { xfail mips-sgi-irix6* } } PR libffi/46660 */
+
+#include "ffitest.h"
+
+static void
+cls_longdouble_va_fn(ffi_cif* cif __UNUSED__, void* resp, 
+		     void** args, void* userdata __UNUSED__)
+{
+	char*		format	= *(char**)args[0];
+	long double	ldValue	= *(long double*)args[1];
+
+	*(ffi_arg*)resp = printf(format, ldValue);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args[3];
+	ffi_type* arg_types[3];
+
+	char*		format	= "%.1Lf\n";
+	long double	ldArg	= 7;
+	ffi_arg		res		= 0;
+
+	arg_types[0] = &ffi_type_pointer;
+	arg_types[1] = &ffi_type_longdouble;
+	arg_types[2] = NULL;
+
+	/* This printf call is variadic */
+	CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
+			       arg_types) == FFI_OK);
+
+	args[0] = &format;
+	args[1] = &ldArg;
+	args[2] = NULL;
+
+	ffi_call(&cif, FFI_FN(printf), &res, args);
+	/* { dg-output "7.0" } */
+	printf("res: %d\n", (int) res);
+	/* { dg-output "\nres: 4" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL,
+				   code) == FFI_OK);
+
+	res = ((int(*)(char*, ...))(code))(format, ldArg);
+	/* { dg-output "\n7.0" } */
+	printf("res: %d\n", (int) res);
+	/* { dg-output "\nres: 4" } */
+
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_schar.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_schar.c
new file mode 100644
index 0000000..71df7b6
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_schar.c
@@ -0,0 +1,74 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check passing of multiple signed char values.
+   Limitations:	none.
+   PR:		PR13221.
+   Originator:	<hos@tamanegi.org> 20031129  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+signed char test_func_fn(signed char a1, signed char a2)
+{
+  signed char result;
+
+  result = a1 + a2;
+
+  printf("%d %d: %d\n", a1, a2, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  signed char a1, a2;
+
+  a1 = *(signed char *)avals[0];
+  a2 = *(signed char *)avals[1];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2);
+
+}
+
+typedef signed char (*test_type)(signed char, signed char);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[3];
+  ffi_type * cl_arg_types[3];
+  ffi_arg res_call;
+  signed char a, b, res_closure;
+
+  a = 2;
+  b = 125;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = NULL;
+
+  cl_arg_types[0] = &ffi_type_schar;
+  cl_arg_types[1] = &ffi_type_schar;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_schar, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "2 125: 127" } */
+  printf("res: %d\n", (signed char)res_call);
+  /* { dg-output "\nres: 127" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(2, 125);
+  /* { dg-output "\n2 125: 127" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 127" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_sshort.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_sshort.c
new file mode 100644
index 0000000..4c39153
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_sshort.c
@@ -0,0 +1,74 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check passing of multiple signed short values.
+   Limitations:	none.
+   PR:		PR13221.
+   Originator:	<andreast@gcc.gnu.org> 20031129  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+signed short test_func_fn(signed short a1, signed short a2)
+{
+  signed short result;
+
+  result = a1 + a2;
+
+  printf("%d %d: %d\n", a1, a2, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  signed short a1, a2;
+
+  a1 = *(signed short *)avals[0];
+  a2 = *(signed short *)avals[1];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2);
+
+}
+
+typedef signed short (*test_type)(signed short, signed short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[3];
+  ffi_type * cl_arg_types[3];
+  ffi_arg res_call;
+  unsigned short a, b, res_closure;
+
+  a = 2;
+  b = 32765;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = NULL;
+
+  cl_arg_types[0] = &ffi_type_sshort;
+  cl_arg_types[1] = &ffi_type_sshort;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_sshort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "2 32765: 32767" } */
+  printf("res: %d\n", (unsigned short)res_call);
+  /* { dg-output "\nres: 32767" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(2, 32765);
+  /* { dg-output "\n2 32765: 32767" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 32767" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_sshortchar.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_sshortchar.c
new file mode 100644
index 0000000..1c3aeb5
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_sshortchar.c
@@ -0,0 +1,86 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check passing of multiple signed short/char values.
+   Limitations:	none.
+   PR:		PR13221.
+   Originator:	<andreast@gcc.gnu.org> 20031129  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+signed short test_func_fn(signed char a1, signed short a2,
+			  signed char a3, signed short a4)
+{
+  signed short result;
+
+  result = a1 + a2 + a3 + a4;
+
+  printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  signed char a1, a3;
+  signed short a2, a4;
+
+  a1 = *(signed char *)avals[0];
+  a2 = *(signed short *)avals[1];
+  a3 = *(signed char *)avals[2];
+  a4 = *(signed short *)avals[3];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4);
+
+}
+
+typedef signed short (*test_type)(signed char, signed short,
+				  signed char, signed short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[5];
+  ffi_type * cl_arg_types[5];
+  ffi_arg res_call;
+  signed char a, c;
+  signed short b, d, res_closure;
+
+  a = 1;
+  b = 32765;
+  c = 127;
+  d = -128;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = &c;
+  args_dbl[3] = &d;
+  args_dbl[4] = NULL;
+
+  cl_arg_types[0] = &ffi_type_schar;
+  cl_arg_types[1] = &ffi_type_sshort;
+  cl_arg_types[2] = &ffi_type_schar;
+  cl_arg_types[3] = &ffi_type_sshort;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_sshort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "1 32765 127 -128: 32765" } */
+  printf("res: %d\n", (signed short)res_call);
+  /* { dg-output "\nres: 32765" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(1, 32765, 127, -128);
+  /* { dg-output "\n1 32765 127 -128: 32765" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 32765" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_uchar.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_uchar.c
new file mode 100644
index 0000000..009c02c
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_uchar.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check passing of multiple unsigned char values.
+   Limitations:	none.
+   PR:		PR13221.
+   Originator:	<andreast@gcc.gnu.org> 20031129  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+unsigned char test_func_fn(unsigned char a1, unsigned char a2,
+			   unsigned char a3, unsigned char a4)
+{
+  unsigned char result;
+
+  result = a1 + a2 + a3 + a4;
+
+  printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  unsigned char a1, a2, a3, a4;
+
+  a1 = *(unsigned char *)avals[0];
+  a2 = *(unsigned char *)avals[1];
+  a3 = *(unsigned char *)avals[2];
+  a4 = *(unsigned char *)avals[3];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4);
+
+}
+
+typedef unsigned char (*test_type)(unsigned char, unsigned char,
+				   unsigned char, unsigned char);
+
+void test_func(ffi_cif *cif __UNUSED__, void *rval __UNUSED__, void **avals,
+	       void *data __UNUSED__)
+{
+  printf("%d %d %d %d\n", *(unsigned char *)avals[0],
+	 *(unsigned char *)avals[1], *(unsigned char *)avals[2],
+	 *(unsigned char *)avals[3]);
+}
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[5];
+  ffi_type * cl_arg_types[5];
+  ffi_arg res_call;
+  unsigned char a, b, c, d, res_closure;
+
+  a = 1;
+  b = 2;
+  c = 127;
+  d = 125;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = &c;
+  args_dbl[3] = &d;
+  args_dbl[4] = NULL;
+
+  cl_arg_types[0] = &ffi_type_uchar;
+  cl_arg_types[1] = &ffi_type_uchar;
+  cl_arg_types[2] = &ffi_type_uchar;
+  cl_arg_types[3] = &ffi_type_uchar;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_uchar, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "1 2 127 125: 255" } */
+  printf("res: %d\n", (unsigned char)res_call);
+  /* { dg-output "\nres: 255" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(1, 2, 127, 125);
+  /* { dg-output "\n1 2 127 125: 255" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 255" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_ushort.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_ushort.c
new file mode 100644
index 0000000..dd10ca7
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_ushort.c
@@ -0,0 +1,74 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check passing of multiple unsigned short values.
+   Limitations:	none.
+   PR:		PR13221.
+   Originator:	<andreast@gcc.gnu.org> 20031129  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+unsigned short test_func_fn(unsigned short a1, unsigned short a2)
+{
+  unsigned short result;
+
+  result = a1 + a2;
+
+  printf("%d %d: %d\n", a1, a2, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  unsigned short a1, a2;
+
+  a1 = *(unsigned short *)avals[0];
+  a2 = *(unsigned short *)avals[1];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2);
+
+}
+
+typedef unsigned short (*test_type)(unsigned short, unsigned short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[3];
+  ffi_type * cl_arg_types[3];
+  ffi_arg res_call;
+  unsigned short a, b, res_closure;
+
+  a = 2;
+  b = 32765;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = NULL;
+
+  cl_arg_types[0] = &ffi_type_ushort;
+  cl_arg_types[1] = &ffi_type_ushort;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_ushort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "2 32765: 32767" } */
+  printf("res: %d\n", (unsigned short)res_call);
+  /* { dg-output "\nres: 32767" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(2, 32765);
+  /* { dg-output "\n2 32765: 32767" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 32767" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_ushortchar.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_ushortchar.c
new file mode 100644
index 0000000..2588e97
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_multi_ushortchar.c
@@ -0,0 +1,86 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check passing of multiple unsigned short/char values.
+   Limitations:	none.
+   PR:		PR13221.
+   Originator:	<andreast@gcc.gnu.org> 20031129  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+unsigned short test_func_fn(unsigned char a1, unsigned short a2,
+			    unsigned char a3, unsigned short a4)
+{
+  unsigned short result;
+
+  result = a1 + a2 + a3 + a4;
+
+  printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  unsigned char a1, a3;
+  unsigned short a2, a4;
+
+  a1 = *(unsigned char *)avals[0];
+  a2 = *(unsigned short *)avals[1];
+  a3 = *(unsigned char *)avals[2];
+  a4 = *(unsigned short *)avals[3];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4);
+
+}
+
+typedef unsigned short (*test_type)(unsigned char, unsigned short,
+				   unsigned char, unsigned short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[5];
+  ffi_type * cl_arg_types[5];
+  ffi_arg res_call;
+  unsigned char a, c;
+  unsigned short b, d, res_closure;
+
+  a = 1;
+  b = 2;
+  c = 127;
+  d = 128;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = &c;
+  args_dbl[3] = &d;
+  args_dbl[4] = NULL;
+
+  cl_arg_types[0] = &ffi_type_uchar;
+  cl_arg_types[1] = &ffi_type_ushort;
+  cl_arg_types[2] = &ffi_type_uchar;
+  cl_arg_types[3] = &ffi_type_ushort;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_ushort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "1 2 127 128: 258" } */
+  printf("res: %d\n", (unsigned short)res_call);
+  /* { dg-output "\nres: 258" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(1, 2, 127, 128);
+  /* { dg-output "\n1 2 127 128: 258" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 258" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer.c
new file mode 100644
index 0000000..cf03993
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer.c
@@ -0,0 +1,74 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check pointer arguments.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+void* cls_pointer_fn(void* a1, void* a2)
+{
+	void*	result	= (void*)((intptr_t)a1 + (intptr_t)a2);
+
+	printf("0x%08x 0x%08x: 0x%08x\n", 
+	       (unsigned int)(uintptr_t) a1,
+               (unsigned int)(uintptr_t) a2,
+               (unsigned int)(uintptr_t) result);
+
+	return result;
+}
+
+static void
+cls_pointer_gn(ffi_cif* cif __UNUSED__, void* resp, 
+	       void** args, void* userdata __UNUSED__)
+{
+	void*	a1	= *(void**)(args[0]);
+	void*	a2	= *(void**)(args[1]);
+
+	*(void**)resp = cls_pointer_fn(a1, a2);
+}
+
+int main (void)
+{
+	ffi_cif	cif;
+        void *code;
+	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void*			args[3];
+//	ffi_type		cls_pointer_type;
+	ffi_type*		arg_types[3];
+
+/*	cls_pointer_type.size = sizeof(void*);
+	cls_pointer_type.alignment = 0;
+	cls_pointer_type.type = FFI_TYPE_POINTER;
+	cls_pointer_type.elements = NULL;*/
+
+	void*	arg1	= (void*)0x12345678;
+	void*	arg2	= (void*)0x89abcdef;
+	ffi_arg	res		= 0;
+
+	arg_types[0] = &ffi_type_pointer;
+	arg_types[1] = &ffi_type_pointer;
+	arg_types[2] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer,
+		arg_types) == FFI_OK);
+
+	args[0] = &arg1;
+	args[1] = &arg2;
+	args[2] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_pointer_fn), &res, args);
+	/* { dg-output "0x12345678 0x89abcdef: 0x9be02467" } */
+	printf("res: 0x%08x\n", (unsigned int) res);
+	/* { dg-output "\nres: 0x9be02467" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_pointer_gn, NULL, code) == FFI_OK);
+
+	res = (ffi_arg)(uintptr_t)((void*(*)(void*, void*))(code))(arg1, arg2);
+	/* { dg-output "\n0x12345678 0x89abcdef: 0x9be02467" } */
+	printf("res: 0x%08x\n", (unsigned int) res);
+	/* { dg-output "\nres: 0x9be02467" } */
+
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer_stack.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer_stack.c
new file mode 100644
index 0000000..e31139e
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer_stack.c
@@ -0,0 +1,142 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check pointer arguments across multiple hideous stack frames.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/7/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static	long dummyVar;
+
+long dummy_func(
+	long double a1, char b1,
+	long double a2, char b2,
+	long double a3, char b3,
+	long double a4, char b4)
+{
+	return a1 + b1 + a2 + b2 + a3 + b3 + a4 + b4;
+}
+
+void* cls_pointer_fn2(void* a1, void* a2)
+{
+	long double	trample1	= (intptr_t)a1 + (intptr_t)a2;
+	char		trample2	= ((char*)&a1)[0] + ((char*)&a2)[0];
+	long double	trample3	= (intptr_t)trample1 + (intptr_t)a1;
+	char		trample4	= trample2 + ((char*)&a1)[1];
+	long double	trample5	= (intptr_t)trample3 + (intptr_t)a2;
+	char		trample6	= trample4 + ((char*)&a2)[1];
+	long double	trample7	= (intptr_t)trample5 + (intptr_t)trample1;
+	char		trample8	= trample6 + trample2;
+	void*		result;
+
+	dummyVar	= dummy_func(trample1, trample2, trample3, trample4,
+		trample5, trample6, trample7, trample8);
+
+	result	= (void*)((intptr_t)a1 + (intptr_t)a2);
+
+	printf("0x%08x 0x%08x: 0x%08x\n", 
+	       (unsigned int)(uintptr_t) a1,
+               (unsigned int)(uintptr_t) a2,
+               (unsigned int)(uintptr_t) result);
+
+	return result;
+}
+
+void* cls_pointer_fn1(void* a1, void* a2)
+{
+	long double	trample1	= (intptr_t)a1 + (intptr_t)a2;
+	char		trample2	= ((char*)&a1)[0] + ((char*)&a2)[0];
+	long double	trample3	= (intptr_t)trample1 + (intptr_t)a1;
+	char		trample4	= trample2 + ((char*)&a1)[1];
+	long double	trample5	= (intptr_t)trample3 + (intptr_t)a2;
+	char		trample6	= trample4 + ((char*)&a2)[1];
+	long double	trample7	= (intptr_t)trample5 + (intptr_t)trample1;
+	char		trample8	= trample6 + trample2;
+	void*		result;
+
+	dummyVar	= dummy_func(trample1, trample2, trample3, trample4,
+		trample5, trample6, trample7, trample8);
+
+	result	= (void*)((intptr_t)a1 + (intptr_t)a2);
+
+	printf("0x%08x 0x%08x: 0x%08x\n",
+               (unsigned int)(intptr_t) a1,
+               (unsigned int)(intptr_t) a2,
+               (unsigned int)(intptr_t) result);
+
+	result	= cls_pointer_fn2(result, a1);
+
+	return result;
+}
+
+static void
+cls_pointer_gn(ffi_cif* cif __UNUSED__, void* resp, 
+	       void** args, void* userdata __UNUSED__)
+{
+	void*	a1	= *(void**)(args[0]);
+	void*	a2	= *(void**)(args[1]);
+
+	long double	trample1	= (intptr_t)a1 + (intptr_t)a2;
+	char		trample2	= ((char*)&a1)[0] + ((char*)&a2)[0];
+	long double	trample3	= (intptr_t)trample1 + (intptr_t)a1;
+	char		trample4	= trample2 + ((char*)&a1)[1];
+	long double	trample5	= (intptr_t)trample3 + (intptr_t)a2;
+	char		trample6	= trample4 + ((char*)&a2)[1];
+	long double	trample7	= (intptr_t)trample5 + (intptr_t)trample1;
+	char		trample8	= trample6 + trample2;
+
+	dummyVar	= dummy_func(trample1, trample2, trample3, trample4,
+		trample5, trample6, trample7, trample8);
+
+	*(void**)resp = cls_pointer_fn1(a1, a2);
+}
+
+int main (void)
+{
+	ffi_cif	cif;
+        void *code;
+	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void*			args[3];
+//	ffi_type		cls_pointer_type;
+	ffi_type*		arg_types[3];
+
+/*	cls_pointer_type.size = sizeof(void*);
+	cls_pointer_type.alignment = 0;
+	cls_pointer_type.type = FFI_TYPE_POINTER;
+	cls_pointer_type.elements = NULL;*/
+
+	void*	arg1	= (void*)0x01234567;
+	void*	arg2	= (void*)0x89abcdef;
+	ffi_arg	res		= 0;
+
+	arg_types[0] = &ffi_type_pointer;
+	arg_types[1] = &ffi_type_pointer;
+	arg_types[2] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer,
+		arg_types) == FFI_OK);
+
+	args[0] = &arg1;
+	args[1] = &arg2;
+	args[2] = NULL;
+
+	printf("\n");
+	ffi_call(&cif, FFI_FN(cls_pointer_fn1), &res, args);
+
+	printf("res: 0x%08x\n", (unsigned int) res);
+	// { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" }
+	// { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" }
+	// { dg-output "\nres: 0x8bf258bd" }
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_pointer_gn, NULL, code) == FFI_OK);
+
+	res = (ffi_arg)(uintptr_t)((void*(*)(void*, void*))(code))(arg1, arg2);
+
+	printf("res: 0x%08x\n", (unsigned int) res);
+	// { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" }
+	// { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" }
+	// { dg-output "\nres: 0x8bf258bd" }
+
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_schar.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_schar.c
new file mode 100644
index 0000000..82986b1
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_schar.c
@@ -0,0 +1,44 @@
+/* Area:	closure_call
+   Purpose:	Check return value schar.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20031108	 */
+
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_schar_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(signed char *)args[0];
+  printf("%d: %d\n",*(signed char *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef signed char (*cls_ret_schar)(signed char);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  signed char res;
+
+  cl_arg_types[0] = &ffi_type_schar;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_schar, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_schar_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_schar)code))(127);
+  /* { dg-output "127: 127" } */
+  printf("res: %d\n", res);
+  /* { dg-output "\nres: 127" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_sint.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_sint.c
new file mode 100644
index 0000000..c7e13b7
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_sint.c
@@ -0,0 +1,42 @@
+/* Area:	closure_call
+   Purpose:	Check return value sint32.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20031108	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_sint_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			    void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(signed int *)args[0];
+  printf("%d: %d\n",*(signed int *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef signed int (*cls_ret_sint)(signed int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  signed int res;
+
+  cl_arg_types[0] = &ffi_type_sint;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_sint_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_sint)code))(65534);
+  /* { dg-output "65534: 65534" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 65534" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_sshort.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_sshort.c
new file mode 100644
index 0000000..846d57e
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_sshort.c
@@ -0,0 +1,42 @@
+/* Area:	closure_call
+   Purpose:	Check return value sshort.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20031108	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_sshort_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			      void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(signed short *)args[0];
+  printf("%d: %d\n",*(signed short *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef signed short (*cls_ret_sshort)(signed short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  signed short res;
+
+  cl_arg_types[0] = &ffi_type_sshort;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_sshort, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_sshort_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_sshort)code))(255);
+  /* { dg-output "255: 255" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 255" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_struct_va1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_struct_va1.c
new file mode 100644
index 0000000..7262d63
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_struct_va1.c
@@ -0,0 +1,114 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Test doubles passed in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	 */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+#include "ffitest.h"
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static void
+test_fn (ffi_cif* cif __UNUSED__, void* resp,
+	 void** args, void* userdata __UNUSED__)
+{
+  int n = *(int*)args[0];
+  struct small_tag s1 = * (struct small_tag *) args[1];
+  struct large_tag l1 = * (struct large_tag *) args[2];
+  struct small_tag s2 = * (struct small_tag *) args[3];
+
+  printf ("%d %d %d %d %d %d %d %d %d %d\n", n, s1.a, s1.b,
+	  l1.a, l1.b, l1.c, l1.d, l1.e,
+	  s2.a, s2.b);
+  * (ffi_arg*) resp = 42;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc (sizeof (ffi_closure), &code);
+  ffi_type* arg_types[5];
+
+  ffi_arg res = 0;
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int si;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint,
+			 arg_types) == FFI_OK);
+
+  si = 4;
+  s1.a = 5;
+  s1.b = 6;
+
+  s2.a = 20;
+  s2.b = 21;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_fn, NULL, code) == FFI_OK);
+
+  res = ((int (*)(int, ...))(code))(si, s1, l1, s2);
+  // { dg-output "4 5 6 10 11 12 13 14 20 21" }
+  printf("res: %d\n", (int) res);
+  // { dg-output "\nres: 42" }
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uchar.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uchar.c
new file mode 100644
index 0000000..c1317e7
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uchar.c
@@ -0,0 +1,42 @@
+/* Area:	closure_call
+   Purpose:	Check return value uchar.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_uchar_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(unsigned char *)args[0];
+  printf("%d: %d\n",*(unsigned char *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef unsigned char (*cls_ret_uchar)(unsigned char);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  unsigned char res;
+
+  cl_arg_types[0] = &ffi_type_uchar;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_uchar, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_uchar_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_uchar)code))(127);
+  /* { dg-output "127: 127" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 127" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uchar_va.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uchar_va.c
new file mode 100644
index 0000000..6491c5b
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uchar_va.c
@@ -0,0 +1,44 @@
+/* Area:	closure_call
+   Purpose:	Test anonymous unsigned char argument.
+   Limitations:	none.
+   PR:		none.
+   Originator:	ARM Ltd. */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef unsigned char T;
+
+static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			 void* userdata __UNUSED__)
+ {
+   *(ffi_arg *)resp = *(T *)args[0];
+
+   printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]);
+ }
+
+typedef T (*cls_ret_T)(T, ...);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[3];
+  T res;
+
+  cl_arg_types[0] = &ffi_type_uchar;
+  cl_arg_types[1] = &ffi_type_uchar;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
+			 &ffi_type_uchar, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
+  res = ((((cls_ret_T)code)(67, 4)));
+  /* { dg-output "67: 67 4" } */
+  printf("res: %d\n", res);
+  /* { dg-output "\nres: 67" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uint.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uint.c
new file mode 100644
index 0000000..885cff5
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uint.c
@@ -0,0 +1,43 @@
+/* Area:	closure_call
+   Purpose:	Check return value uint.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_uint_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			    void* userdata __UNUSED__)
+{
+  *(ffi_arg *)resp = *(unsigned int *)args[0];
+
+  printf("%d: %d\n",*(unsigned int *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef unsigned int (*cls_ret_uint)(unsigned int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  unsigned int res;
+
+  cl_arg_types[0] = &ffi_type_uint;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_uint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_uint_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_uint)code))(2147483647);
+  /* { dg-output "2147483647: 2147483647" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 2147483647" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uint_va.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uint_va.c
new file mode 100644
index 0000000..b04cfd1
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_uint_va.c
@@ -0,0 +1,45 @@
+/* Area:	closure_call
+   Purpose:	Test anonymous unsigned int argument.
+   Limitations:	none.
+   PR:		none.
+   Originator:	ARM Ltd. */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+typedef unsigned int T;
+
+static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			 void* userdata __UNUSED__)
+ {
+   *(ffi_arg *)resp = *(T *)args[0];
+
+   printf("%d: %d %d\n", (int)*(ffi_arg *)resp, *(T *)args[0], *(T *)args[1]);
+ }
+
+typedef T (*cls_ret_T)(T, ...);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[3];
+  T res;
+
+  cl_arg_types[0] = &ffi_type_uint;
+  cl_arg_types[1] = &ffi_type_uint;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
+			 &ffi_type_uint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
+  res = ((((cls_ret_T)code)(67, 4)));
+  /* { dg-output "67: 67 4" } */
+  printf("res: %d\n", res);
+  /* { dg-output "\nres: 67" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ulong_va.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ulong_va.c
new file mode 100644
index 0000000..0315082
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ulong_va.c
@@ -0,0 +1,45 @@
+/* Area:	closure_call
+   Purpose:	Test anonymous unsigned long argument.
+   Limitations:	none.
+   PR:		none.
+   Originator:	ARM Ltd. */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+typedef unsigned long T;
+
+static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			 void* userdata __UNUSED__)
+ {
+   *(T *)resp = *(T *)args[0];
+
+   printf("%ld: %ld %ld\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
+ }
+
+typedef T (*cls_ret_T)(T, ...);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[3];
+  T res;
+
+  cl_arg_types[0] = &ffi_type_ulong;
+  cl_arg_types[1] = &ffi_type_ulong;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
+			 &ffi_type_ulong, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
+  res = ((((cls_ret_T)code)(67, 4)));
+  /* { dg-output "67: 67 4" } */
+  printf("res: %ld\n", res);
+  /* { dg-output "\nres: 67" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ulonglong.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ulonglong.c
new file mode 100644
index 0000000..235ab44
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ulonglong.c
@@ -0,0 +1,47 @@
+/* Area:	closure_call
+   Purpose:	Check return value long long.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#include "ffitest.h"
+
+static void cls_ret_ulonglong_fn(ffi_cif* cif __UNUSED__, void* resp,
+				 void** args, void* userdata __UNUSED__)
+{
+  *(unsigned long long *)resp=  *(unsigned long long *)args[0];
+
+  printf("%" PRIuLL ": %" PRIuLL "\n",*(unsigned long long *)args[0],
+	 *(unsigned long long *)(resp));
+}
+typedef unsigned long long (*cls_ret_ulonglong)(unsigned long long);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  unsigned long long res;
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_uint64, cl_arg_types) == FFI_OK);
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_ulonglong_fn, NULL, code)  == FFI_OK);
+  res = (*((cls_ret_ulonglong)code))(214LL);
+  /* { dg-output "214: 214" } */
+  printf("res: %" PRIdLL "\n", res);
+  /* { dg-output "\nres: 214" } */
+
+  res = (*((cls_ret_ulonglong)code))(9223372035854775808LL);
+  /* { dg-output "\n9223372035854775808: 9223372035854775808" } */
+  printf("res: %" PRIdLL "\n", res);
+  /* { dg-output "\nres: 9223372035854775808" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ushort.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ushort.c
new file mode 100644
index 0000000..a00100e
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ushort.c
@@ -0,0 +1,43 @@
+/* Area:	closure_call
+   Purpose:	Check return value ushort.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_ushort_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			      void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(unsigned short *)args[0];
+
+  printf("%d: %d\n",*(unsigned short *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef unsigned short (*cls_ret_ushort)(unsigned short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  unsigned short res;
+
+  cl_arg_types[0] = &ffi_type_ushort;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_ushort, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_ushort_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_ushort)code))(65535);
+  /* { dg-output "65535: 65535" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 65535" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ushort_va.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ushort_va.c
new file mode 100644
index 0000000..37aa106
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ushort_va.c
@@ -0,0 +1,44 @@
+/* Area:	closure_call
+   Purpose:	Test anonymous unsigned short argument.
+   Limitations:	none.
+   PR:		none.
+   Originator:	ARM Ltd. */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef unsigned short T;
+
+static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			 void* userdata __UNUSED__)
+ {
+   *(ffi_arg *)resp = *(T *)args[0];
+
+   printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]);
+ }
+
+typedef T (*cls_ret_T)(T, ...);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[3];
+  T res;
+
+  cl_arg_types[0] = &ffi_type_ushort;
+  cl_arg_types[1] = &ffi_type_ushort;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
+			 &ffi_type_ushort, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
+  res = ((((cls_ret_T)code)(67, 4)));
+  /* { dg-output "67: 67 4" } */
+  printf("res: %d\n", res);
+  /* { dg-output "\nres: 67" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/err_bad_abi.c b/third_party/gofrontend/libffi/testsuite/libffi.call/err_bad_abi.c
new file mode 100644
index 0000000..f5a7317
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/err_bad_abi.c
@@ -0,0 +1,36 @@
+/* Area:		ffi_prep_cif, ffi_prep_closure
+   Purpose:		Test error return for bad ABIs.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static void
+dummy_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__, 
+	 void** args __UNUSED__, void* userdata __UNUSED__)
+{}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	ffi_type* arg_types[1];
+
+	arg_types[0] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, 255, 0, &ffi_type_void,
+		arg_types) == FFI_BAD_ABI);
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &ffi_type_void,
+		arg_types) == FFI_OK);
+
+	cif.abi= 255;
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, dummy_fn, NULL, code) == FFI_BAD_ABI);
+
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/err_bad_typedef.c b/third_party/gofrontend/libffi/testsuite/libffi.call/err_bad_typedef.c
new file mode 100644
index 0000000..bf60161
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/err_bad_typedef.c
@@ -0,0 +1,26 @@
+/* Area:		ffi_prep_cif
+   Purpose:		Test error return for bad typedefs.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+int main (void)
+{
+	ffi_cif cif;
+	ffi_type* arg_types[1];
+
+	ffi_type	badType	= ffi_type_void;
+
+	arg_types[0] = NULL;
+
+	badType.size = 0;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &badType,
+		arg_types) == FFI_BAD_TYPEDEF);
+
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis1_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis1_win32.c
new file mode 100644
index 0000000..cbc4724
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis1_win32.c
@@ -0,0 +1,50 @@
+/* Area:	ffi_call
+   Purpose:	Check fastcall fct call on X86_WIN32 systems.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+
+#include "ffitest.h"
+
+static size_t __FASTCALL__ my_fastcall_f(char *s, float a)
+{
+  return (size_t) ((int) strlen(s) + (int) a);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  char *s;
+  float v2;
+  args[0] = &ffi_type_pointer;
+  args[1] = &ffi_type_float;
+  values[0] = (void*) &s;
+  values[1] = (void*) &v2;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 2,
+		       &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  v2 = 0.0;
+  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  CHECK(rint == 1);
+  
+  s = "1234567";
+  v2 = -1.0;
+  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  CHECK(rint == 6);
+  
+  s = "1234567890123456789012345";
+  v2 = 1.0;
+  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  CHECK(rint == 26);
+  
+  printf("fastcall fct1 tests passed\n");
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis2_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis2_win32.c
new file mode 100644
index 0000000..7bdd0e1
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis2_win32.c
@@ -0,0 +1,50 @@
+/* Area:	ffi_call
+   Purpose:	Check fastcall fct call on X86_WIN32 systems.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+
+#include "ffitest.h"
+
+static size_t __FASTCALL__ my_fastcall_f(float a, char *s)
+{
+  return (size_t) ((int) strlen(s) + (int) a);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  char *s;
+  float v2;
+  args[1] = &ffi_type_pointer;
+  args[0] = &ffi_type_float;
+  values[1] = (void*) &s;
+  values[0] = (void*) &v2;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 2,
+		       &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  v2 = 0.0;
+  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  CHECK(rint == 1);
+  
+  s = "1234567";
+  v2 = -1.0;
+  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  CHECK(rint == 6);
+  
+  s = "1234567890123456789012345";
+  v2 = 1.0;
+  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  CHECK(rint == 26);
+  
+  printf("fastcall fct2 tests passed\n");
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis3_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis3_win32.c
new file mode 100644
index 0000000..b5d606d
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis3_win32.c
@@ -0,0 +1,56 @@
+/* Area:	ffi_call
+   Purpose:	Check fastcall f call on X86_WIN32 systems.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+
+#include "ffitest.h"
+
+static size_t __FASTCALL__ my_fastcall_f(float a, char *s, int i)
+{
+  return (size_t) ((int) strlen(s) + (int) a + i);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  char *s;
+  int v1;
+  float v2;
+  args[2] = &ffi_type_sint;
+  args[1] = &ffi_type_pointer;
+  args[0] = &ffi_type_float;
+  values[2] = (void*) &v1;
+  values[1] = (void*) &s;
+  values[0] = (void*) &v2;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 3,
+		       &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  v1 = 1;
+  v2 = 0.0;
+  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  CHECK(rint == 2);
+  
+  s = "1234567";
+  v2 = -1.0;
+  v1 = -2;
+  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  CHECK(rint == 4);
+  
+  s = "1234567890123456789012345";
+  v2 = 1.0;
+  v1 = 2;
+  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  CHECK(rint == 28);
+  
+  printf("fastcall fct3 tests passed\n");
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/ffitest.h b/third_party/gofrontend/libffi/testsuite/libffi.call/ffitest.h
new file mode 100644
index 0000000..d81d4da
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/ffitest.h
@@ -0,0 +1,170 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ffi.h>
+#include "fficonfig.h"
+
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#if defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#define MAX_ARGS 256
+
+#define CHECK(x) !(x) ? abort() : 0
+
+/* Define __UNUSED__ that also other compilers than gcc can run the tests.  */
+#undef __UNUSED__
+#if defined(__GNUC__)
+#define __UNUSED__ __attribute__((__unused__))
+#else
+#define __UNUSED__
+#endif
+
+/* Define __FASTCALL__ so that other compilers than gcc can run the tests.  */
+#undef __FASTCALL__
+#if defined _MSC_VER
+#define __FASTCALL__ __fastcall
+#else
+#define __FASTCALL__ __attribute__((fastcall))
+#endif
+
+/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
+   file open.  */
+#ifdef HAVE_MMAP_ANON
+# undef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
+#  define MAP_ANONYMOUS MAP_ANON
+# endif
+# define USING_MMAP
+
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+# define USING_MMAP
+
+#endif
+
+/* MinGW kludge.  */
+#ifdef _WIN64
+#define PRIdLL "I64d"
+#define PRIuLL "I64u"
+#else
+#define PRIdLL "lld"
+#define PRIuLL "llu"
+#endif
+
+/* Tru64 UNIX kludge.  */
+#if defined(__alpha__) && defined(__osf__)
+/* Tru64 UNIX V4.0 doesn't support %lld/%lld, but long is 64-bit.  */
+#undef PRIdLL
+#define PRIdLL "ld"
+#undef PRIuLL
+#define PRIuLL "lu"
+#define PRId8 "hd"
+#define PRIu8 "hu"
+#define PRId64 "ld"
+#define PRIu64 "lu"
+#define PRIuPTR "lu"
+#endif
+
+/* PA HP-UX kludge.  */
+#if defined(__hppa__) && defined(__hpux__) && !defined(PRIuPTR)
+#define PRIuPTR "lu"
+#endif
+
+/* IRIX kludge.  */
+#if defined(__sgi)
+/* IRIX 6.5 <inttypes.h> provides all definitions, but only for C99
+   compilations.  */
+#define PRId8 "hhd"
+#define PRIu8 "hhu"
+#if (_MIPS_SZLONG == 32)
+#define PRId64 "lld"
+#define PRIu64 "llu"
+#endif
+/* This doesn't match <inttypes.h>, which always has "lld" here, but the
+   arguments are uint64_t, int64_t, which are unsigned long, long for
+   64-bit in <sgidefs.h>.  */
+#if (_MIPS_SZLONG == 64)
+#define PRId64 "ld"
+#define PRIu64 "lu"
+#endif
+/* This doesn't match <inttypes.h>, which has "u" here, but the arguments
+   are uintptr_t, which is always unsigned long.  */
+#define PRIuPTR "lu"
+#endif
+
+/* Solaris < 10 kludge.  */
+#if defined(__sun__) && defined(__svr4__) && !defined(PRIuPTR)
+#if defined(__arch64__) || defined (__x86_64__)
+#define PRIuPTR "lu"
+#else
+#define PRIuPTR "u"
+#endif
+#endif
+
+/* MSVC kludge.  */
+#if defined _MSC_VER
+#define PRIuPTR "lu"
+#define PRIu8 "u"
+#define PRId8 "d"
+#define PRIu64 "I64u"
+#define PRId64 "I64d"
+#endif
+
+#ifdef USING_MMAP
+static inline void *
+allocate_mmap (size_t size)
+{
+  void *page;
+#if defined (HAVE_MMAP_DEV_ZERO)
+  static int dev_zero_fd = -1;
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+  if (dev_zero_fd == -1)
+    {
+      dev_zero_fd = open ("/dev/zero", O_RDONLY);
+      if (dev_zero_fd == -1)
+	{
+	  perror ("open /dev/zero: %m");
+	  exit (1);
+	}
+    }
+#endif
+
+
+#ifdef HAVE_MMAP_ANON
+  page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+	       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#endif
+#ifdef HAVE_MMAP_DEV_ZERO
+  page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+	       MAP_PRIVATE, dev_zero_fd, 0);
+#endif
+
+  if (page == (void *) MAP_FAILED)
+    {
+      perror ("virtual memory exhausted");
+      exit (1);
+    }
+
+  return page;
+}
+
+#endif
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/float.c b/third_party/gofrontend/libffi/testsuite/libffi.call/float.c
new file mode 100644
index 0000000..fbc272d
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/float.c
@@ -0,0 +1,59 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static int floating(int a, float b, double c, long double d)
+{
+  int i;
+
+  i = (int) ((float)a/b + ((float)c/(float)d));
+
+  return i;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  float f;
+  signed int si1;
+  double d;
+  long double ld;
+
+  args[0] = &ffi_type_sint;
+  values[0] = &si1;
+  args[1] = &ffi_type_float;
+  values[1] = &f;
+  args[2] = &ffi_type_double;
+  values[2] = &d;
+  args[3] = &ffi_type_longdouble;
+  values[3] = &ld;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_sint, args) == FFI_OK);
+
+  si1 = 6;
+  f = 3.14159;
+  d = (double)1.0/(double)3.0;
+  ld = 2.71828182846L;
+
+  floating (si1, f, d, ld);
+
+  ffi_call(&cif, FFI_FN(floating), &rint, values);
+
+  printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld));
+
+  CHECK((int)rint == floating(si1, f, d, ld));
+
+  exit (0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/float1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/float1.c
new file mode 100644
index 0000000..991d059
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/float1.c
@@ -0,0 +1,58 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include "float.h"
+
+typedef union
+{
+  double d;
+  unsigned char c[sizeof (double)];
+} value_type;
+
+#define CANARY 0xba
+
+static double dblit(float f)
+{
+  return f/3.0;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float f;
+  value_type result[2];
+  unsigned int i;
+
+  args[0] = &ffi_type_float;
+  values[0] = &f;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_double, args) == FFI_OK);
+
+  f = 3.14159;
+
+  /* Put a canary in the return array.  This is a regression test for
+     a buffer overrun.  */
+  memset(result[1].c, CANARY, sizeof (double));
+
+  ffi_call(&cif, FFI_FN(dblit), &result[0].d, values);
+
+  /* These are not always the same!! Check for a reasonable delta */
+
+  CHECK(result[0].d - dblit(f) < DBL_EPSILON);
+
+  /* Check the canary.  */
+  for (i = 0; i < sizeof (double); ++i)
+    CHECK(result[1].c[i] == CANARY);
+
+  exit(0);
+
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/float2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/float2.c
new file mode 100644
index 0000000..a0b296c
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/float2.c
@@ -0,0 +1,58 @@
+/* Area:	ffi_call
+   Purpose:	Check return value long double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-excess-errors "fails" { target x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+
+#include "ffitest.h"
+#include "float.h"
+
+static long double ldblit(float f)
+{
+  return (long double) (((long double) f)/ (long double) 3.0);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float f;
+  long double ld;
+
+  args[0] = &ffi_type_float;
+  values[0] = &f;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_longdouble, args) == FFI_OK);
+
+  f = 3.14159;
+
+#if 1
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+  printf ("%Lf\n", ldblit(f));
+#endif
+  ld = 666;
+  ffi_call(&cif, FFI_FN(ldblit), &ld, values);
+
+#if 1
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+  printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
+#endif
+
+  /* These are not always the same!! Check for a reasonable delta */
+  if (ld - ldblit(f) < LDBL_EPSILON)
+    puts("long double return value tests ok!");
+  else
+    CHECK(0);
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/float3.c b/third_party/gofrontend/libffi/testsuite/libffi.call/float3.c
new file mode 100644
index 0000000..76bd5f2
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/float3.c
@@ -0,0 +1,72 @@
+/* Area:	ffi_call
+   Purpose:	Check float arguments with different orders.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+#include "float.h"
+
+static double floating_1(float a, double b, long double c)
+{
+  return (double) a + b + (double) c;
+}
+
+static double floating_2(long double a, double b, float c)
+{
+  return (double) a + b + (double) c;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double rd;
+
+  float f;
+  double d;
+  long double ld;
+
+  args[0] = &ffi_type_float;
+  values[0] = &f;
+  args[1] = &ffi_type_double;
+  values[1] = &d;
+  args[2] = &ffi_type_longdouble;
+  values[2] = &ld;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &ffi_type_double, args) == FFI_OK);
+
+  f = 3.14159;
+  d = (double)1.0/(double)3.0;
+  ld = 2.71828182846L;
+
+  floating_1 (f, d, ld);
+
+  ffi_call(&cif, FFI_FN(floating_1), &rd, values);
+
+  CHECK(rd - floating_1(f, d, ld) < DBL_EPSILON);
+
+  args[0] = &ffi_type_longdouble;
+  values[0] = &ld;
+  args[1] = &ffi_type_double;
+  values[1] = &d;
+  args[2] = &ffi_type_float;
+  values[2] = &f;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &ffi_type_double, args) == FFI_OK);
+
+  floating_2 (ld, d, f);
+
+  ffi_call(&cif, FFI_FN(floating_2), &rd, values);
+
+  CHECK(rd - floating_2(ld, d, f) < DBL_EPSILON);
+
+  exit (0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/float4.c b/third_party/gofrontend/libffi/testsuite/libffi.call/float4.c
new file mode 100644
index 0000000..0dd6d85
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/float4.c
@@ -0,0 +1,62 @@
+/* Area:	ffi_call
+   Purpose:	Check denorm double value.
+   Limitations:	none.
+   PR:		PR26483.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+/* { dg-options "-mieee" { target alpha*-*-* } } */
+
+#include "ffitest.h"
+#include "float.h"
+
+typedef union
+{
+  double d;
+  unsigned char c[sizeof (double)];
+} value_type;
+
+#define CANARY 0xba
+
+static double dblit(double d)
+{
+  return d;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double d;
+  value_type result[2];
+  unsigned int i;
+
+  args[0] = &ffi_type_double;
+  values[0] = &d;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_double, args) == FFI_OK);
+  
+  d = DBL_MIN / 2;
+  
+  /* Put a canary in the return array.  This is a regression test for
+     a buffer overrun.  */
+  memset(result[1].c, CANARY, sizeof (double));
+
+  ffi_call(&cif, FFI_FN(dblit), &result[0].d, values);
+  
+  /* The standard delta check doesn't work for denorms.  Since we didn't do
+     any arithmetic, we should get the original result back, and hence an
+     exact check should be OK here.  */
+ 
+  CHECK(result[0].d == dblit(d));
+
+  /* Check the canary.  */
+  for (i = 0; i < sizeof (double); ++i)
+    CHECK(result[1].c[i] == CANARY);
+
+  exit(0);
+
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/float_va.c b/third_party/gofrontend/libffi/testsuite/libffi.call/float_va.c
new file mode 100644
index 0000000..aae158e
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/float_va.c
@@ -0,0 +1,107 @@
+/* Area:        fp and variadics
+   Purpose:     check fp inputs and returns work on variadics, even the fixed params
+   Limitations: None
+   PR:          none
+   Originator:  <david.gilbert@linaro.org> 2011-01-25
+
+   Intended to stress the difference in ABI on ARM vfp
+*/
+
+/* { dg-do run } */
+
+#include <stdarg.h>
+
+#include "ffitest.h"
+
+/* prints out all the parameters, and returns the sum of them all.
+ * 'x' is the number of variadic parameters all of which are double in this test
+ */
+double float_va_fn(unsigned int x, double y,...)
+{
+  double total=0.0;
+  va_list ap;
+  unsigned int i;
+
+  total+=(double)x;
+  total+=y;
+
+  printf("%u: %.1f :", x, y);
+
+  va_start(ap, y);
+  for(i=0;i<x;i++)
+  {
+    double arg=va_arg(ap, double);
+    total+=arg;
+    printf(" %d:%.1f ", i, arg);
+  }
+  va_end(ap);
+
+  printf(" total: %.1f\n", total);
+
+  return total;
+}
+
+int main (void)
+{
+  ffi_cif    cif;
+
+  ffi_type    *arg_types[5];
+  void        *values[5];
+  double        doubles[5];
+  unsigned int firstarg;
+  double        resfp;
+
+  /* First test, pass float_va_fn(0,2.0) - note there are no actual
+   * variadic parameters, but it's declared variadic so the ABI may be
+   * different. */
+  /* Call it statically and then via ffi */
+  resfp=float_va_fn(0,2.0);
+  // { dg-output "0: 2.0 : total: 2.0" }
+  printf("compiled: %.1f\n", resfp);
+  // { dg-output "\ncompiled: 2.0" }
+
+  arg_types[0] = &ffi_type_uint;
+  arg_types[1] = &ffi_type_double;
+  arg_types[2] = NULL;
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 2,
+        &ffi_type_double, arg_types) == FFI_OK);
+
+  firstarg = 0;
+  doubles[0] = 2.0;
+  values[0] = &firstarg;
+  values[1] = &doubles[0];
+  ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
+  // { dg-output "\n0: 2.0 : total: 2.0" }
+  printf("ffi: %.1f\n", resfp);
+  // { dg-output "\nffi: 2.0" }
+
+  /* Second test, float_va_fn(2,2.0,3.0,4.0), now with variadic params */
+  /* Call it statically and then via ffi */
+  resfp=float_va_fn(2,2.0,3.0,4.0);
+  // { dg-output "\n2: 2.0 : 0:3.0  1:4.0  total: 11.0" }
+  printf("compiled: %.1f\n", resfp);
+  // { dg-output "\ncompiled: 11.0" }
+
+  arg_types[0] = &ffi_type_uint;
+  arg_types[1] = &ffi_type_double;
+  arg_types[2] = &ffi_type_double;
+  arg_types[3] = &ffi_type_double;
+  arg_types[4] = NULL;
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 4,
+        &ffi_type_double, arg_types) == FFI_OK);
+
+  firstarg = 2;
+  doubles[0] = 2.0;
+  doubles[1] = 3.0;
+  doubles[2] = 4.0;
+  values[0] = &firstarg;
+  values[1] = &doubles[0];
+  values[2] = &doubles[1];
+  values[3] = &doubles[2];
+  ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
+  // { dg-output "\n2: 2.0 : 0:3.0  1:4.0  total: 11.0" }
+  printf("ffi: %.1f\n", resfp);
+  // { dg-output "\nffi: 11.0" }
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/huge_struct.c b/third_party/gofrontend/libffi/testsuite/libffi.call/huge_struct.c
new file mode 100644
index 0000000..380fedf
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/huge_struct.c
@@ -0,0 +1,342 @@
+/*	Area:			ffi_call, closure_call
+	Purpose:		Check large structure returns.
+	Limitations:	none.
+	PR:				none.
+	Originator:		Blake Chaffin	6/18/2007
+*/
+
+/* { dg-excess-errors "" { target x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
+/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+
+#include "ffitest.h"
+
+typedef	struct BigStruct{
+	uint8_t		a;
+	int8_t		b;
+	uint16_t	c;
+	int16_t		d;
+	uint32_t	e;
+	int32_t		f;
+	uint64_t	g;
+	int64_t		h;
+	float		i;
+	double		j;
+	long double	k;
+	char*		l;
+	uint8_t		m;
+	int8_t		n;
+	uint16_t	o;
+	int16_t		p;
+	uint32_t	q;
+	int32_t		r;
+	uint64_t	s;
+	int64_t		t;
+	float		u;
+	double		v;
+	long double	w;
+	char*		x;
+	uint8_t		y;
+	int8_t		z;
+	uint16_t	aa;
+	int16_t		bb;
+	uint32_t	cc;
+	int32_t		dd;
+	uint64_t	ee;
+	int64_t		ff;
+	float		gg;
+	double		hh;
+	long double	ii;
+	char*		jj;
+	uint8_t		kk;
+	int8_t		ll;
+	uint16_t	mm;
+	int16_t		nn;
+	uint32_t	oo;
+	int32_t		pp;
+	uint64_t	qq;
+	int64_t		rr;
+	float		ss;
+	double		tt;
+	long double	uu;
+	char*		vv;
+	uint8_t		ww;
+	int8_t		xx;
+} BigStruct;
+
+BigStruct
+test_large_fn(
+	uint8_t		ui8_1,
+	int8_t		si8_1,
+	uint16_t	ui16_1,
+	int16_t		si16_1,
+	uint32_t	ui32_1,
+	int32_t		si32_1,
+	uint64_t	ui64_1,
+	int64_t		si64_1,
+	float		f_1,
+	double		d_1,
+	long double	ld_1,
+	char*		p_1,
+	uint8_t		ui8_2,
+	int8_t		si8_2,
+	uint16_t	ui16_2,
+	int16_t		si16_2,
+	uint32_t	ui32_2,
+	int32_t		si32_2,
+	uint64_t	ui64_2,
+	int64_t		si64_2,
+	float		f_2,
+	double		d_2,
+	long double	ld_2,
+	char*		p_2,
+	uint8_t		ui8_3,
+	int8_t		si8_3,
+	uint16_t	ui16_3,
+	int16_t		si16_3,
+	uint32_t	ui32_3,
+	int32_t		si32_3,
+	uint64_t	ui64_3,
+	int64_t		si64_3,
+	float		f_3,
+	double		d_3,
+	long double	ld_3,
+	char*		p_3,
+	uint8_t		ui8_4,
+	int8_t		si8_4,
+	uint16_t	ui16_4,
+	int16_t		si16_4,
+	uint32_t	ui32_4,
+	int32_t		si32_4,
+	uint64_t	ui64_4,
+	int64_t		si64_4,
+	float		f_4,
+	double		d_4,
+	long double	ld_4,
+	char*		p_4,
+	uint8_t		ui8_5,
+	int8_t		si8_5)
+{
+	BigStruct	retVal	= {
+		ui8_1 + 1, si8_1 + 1, ui16_1 + 1, si16_1 + 1, ui32_1 + 1, si32_1 + 1,
+			ui64_1 + 1, si64_1 + 1, f_1 + 1, d_1 + 1, ld_1 + 1, (char*)((intptr_t)p_1 + 1), 
+		ui8_2 + 2, si8_2 + 2, ui16_2 + 2, si16_2 + 2, ui32_2 + 2, si32_2 + 2,
+			ui64_2 + 2, si64_2 + 2, f_2 + 2, d_2 + 2, ld_2 + 2, (char*)((intptr_t)p_2 + 2), 
+		ui8_3 + 3, si8_3 + 3, ui16_3 + 3, si16_3 + 3, ui32_3 + 3, si32_3 + 3,
+			ui64_3 + 3, si64_3 + 3, f_3 + 3, d_3 + 3, ld_3 + 3, (char*)((intptr_t)p_3 + 3), 
+		ui8_4 + 4, si8_4 + 4, ui16_4 + 4, si16_4 + 4, ui32_4 + 4, si32_4 + 4,
+			ui64_4 + 4, si64_4 + 4, f_4 + 4, d_4 + 4, ld_4 + 4, (char*)((intptr_t)p_4 + 4), 
+		ui8_5 + 5, si8_5 + 5};
+
+	printf("%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 ": "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n",
+	       ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, (unsigned long)p_1,
+		ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, (unsigned long)p_2,
+		ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, (unsigned long)p_3,
+		ui8_4, si8_4, ui16_4, si16_4, ui32_4, si32_4, ui64_4, si64_4, f_4, d_4, ld_4, (unsigned long)p_4, ui8_5, si8_5,
+		retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
+	       retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l,
+		retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
+	       retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, (unsigned long)retVal.x,
+		retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
+	       retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
+		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
+	       retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
+
+	return	retVal;
+}
+
+static void
+cls_large_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+	uint8_t		ui8_1	= *(uint8_t*)args[0];
+	int8_t		si8_1	= *(int8_t*)args[1];
+	uint16_t	ui16_1	= *(uint16_t*)args[2];
+	int16_t		si16_1	= *(int16_t*)args[3];
+	uint32_t	ui32_1	= *(uint32_t*)args[4];
+	int32_t		si32_1	= *(int32_t*)args[5];
+	uint64_t	ui64_1	= *(uint64_t*)args[6];
+	int64_t		si64_1	= *(int64_t*)args[7];
+	float		f_1		= *(float*)args[8];
+	double		d_1		= *(double*)args[9];
+	long double	ld_1	= *(long double*)args[10];
+	char*		p_1		= *(char**)args[11];
+	uint8_t		ui8_2	= *(uint8_t*)args[12];
+	int8_t		si8_2	= *(int8_t*)args[13];
+	uint16_t	ui16_2	= *(uint16_t*)args[14];
+	int16_t		si16_2	= *(int16_t*)args[15];
+	uint32_t	ui32_2	= *(uint32_t*)args[16];
+	int32_t		si32_2	= *(int32_t*)args[17];
+	uint64_t	ui64_2	= *(uint64_t*)args[18];
+	int64_t		si64_2	= *(int64_t*)args[19];
+	float		f_2		= *(float*)args[20];
+	double		d_2		= *(double*)args[21];
+	long double	ld_2	= *(long double*)args[22];
+	char*		p_2		= *(char**)args[23];
+	uint8_t		ui8_3	= *(uint8_t*)args[24];
+	int8_t		si8_3	= *(int8_t*)args[25];
+	uint16_t	ui16_3	= *(uint16_t*)args[26];
+	int16_t		si16_3	= *(int16_t*)args[27];
+	uint32_t	ui32_3	= *(uint32_t*)args[28];
+	int32_t		si32_3	= *(int32_t*)args[29];
+	uint64_t	ui64_3	= *(uint64_t*)args[30];
+	int64_t		si64_3	= *(int64_t*)args[31];
+	float		f_3		= *(float*)args[32];
+	double		d_3		= *(double*)args[33];
+	long double	ld_3	= *(long double*)args[34];
+	char*		p_3		= *(char**)args[35];
+	uint8_t		ui8_4	= *(uint8_t*)args[36];
+	int8_t		si8_4	= *(int8_t*)args[37];
+	uint16_t	ui16_4	= *(uint16_t*)args[38];
+	int16_t		si16_4	= *(int16_t*)args[39];
+	uint32_t	ui32_4	= *(uint32_t*)args[40];
+	int32_t		si32_4	= *(int32_t*)args[41];
+	uint64_t	ui64_4	= *(uint64_t*)args[42];
+	int64_t		si64_4	= *(int64_t*)args[43];
+	float		f_4		= *(float*)args[44];
+	double		d_4		= *(double*)args[45];
+	long double	ld_4	= *(long double*)args[46];
+	char*		p_4		= *(char**)args[47];
+	uint8_t		ui8_5	= *(uint8_t*)args[48];
+	int8_t		si8_5	= *(int8_t*)args[49];
+
+	*(BigStruct*)resp = test_large_fn(
+		ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, p_1,
+		ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, p_2,
+		ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, p_3,
+		ui8_4, si8_4, ui16_4, si16_4, ui32_4, si32_4, ui64_4, si64_4, f_4, d_4, ld_4, p_4,
+		ui8_5, si8_5);
+}
+
+int
+main(int argc __UNUSED__, const char** argv __UNUSED__)
+{
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+
+	ffi_cif		cif;
+	ffi_type*	argTypes[51];
+	void*		argValues[51];
+
+	ffi_type	ret_struct_type;
+	ffi_type*	st_fields[51];
+	BigStruct	retVal;
+
+	uint8_t		ui8		= 1;
+	int8_t		si8		= 2;
+	uint16_t	ui16	= 3;
+	int16_t		si16	= 4;
+	uint32_t	ui32	= 5;
+	int32_t		si32	= 6;
+	uint64_t	ui64	= 7;
+	int64_t		si64	= 8;
+	float		f		= 9;
+	double		d		= 10;
+	long double	ld		= 11;
+	char*		p		= (char*)0x12345678;
+
+	memset (&retVal, 0, sizeof(retVal));
+
+	ret_struct_type.size = 0;
+	ret_struct_type.alignment = 0;
+	ret_struct_type.type = FFI_TYPE_STRUCT;
+	ret_struct_type.elements = st_fields;
+
+	st_fields[0]	= st_fields[12]	= st_fields[24]	= st_fields[36]	= st_fields[48]	= &ffi_type_uint8;
+	st_fields[1]	= st_fields[13]	= st_fields[25]	= st_fields[37]	= st_fields[49]	= &ffi_type_sint8;
+	st_fields[2]	= st_fields[14]	= st_fields[26]	= st_fields[38]	= &ffi_type_uint16;
+	st_fields[3]	= st_fields[15]	= st_fields[27]	= st_fields[39]	= &ffi_type_sint16;
+	st_fields[4]	= st_fields[16]	= st_fields[28]	= st_fields[40]	= &ffi_type_uint32;
+	st_fields[5]	= st_fields[17]	= st_fields[29]	= st_fields[41]	= &ffi_type_sint32;
+	st_fields[6]	= st_fields[18]	= st_fields[30]	= st_fields[42]	= &ffi_type_uint64;
+	st_fields[7]	= st_fields[19]	= st_fields[31]	= st_fields[43]	= &ffi_type_sint64;
+	st_fields[8]	= st_fields[20]	= st_fields[32]	= st_fields[44]	= &ffi_type_float;
+	st_fields[9]	= st_fields[21]	= st_fields[33]	= st_fields[45]	= &ffi_type_double;
+	st_fields[10]	= st_fields[22]	= st_fields[34]	= st_fields[46]	= &ffi_type_longdouble;
+	st_fields[11]	= st_fields[23]	= st_fields[35]	= st_fields[47]	= &ffi_type_pointer;
+
+	st_fields[50] = NULL;
+
+	argTypes[0]		= argTypes[12]	= argTypes[24]	= argTypes[36]	= argTypes[48]	= &ffi_type_uint8;
+	argValues[0]	= argValues[12]	= argValues[24]	= argValues[36]	= argValues[48]	= &ui8;
+	argTypes[1]		= argTypes[13]	= argTypes[25]	= argTypes[37]	= argTypes[49]	= &ffi_type_sint8;
+	argValues[1]	= argValues[13]	= argValues[25]	= argValues[37]	= argValues[49]	= &si8;
+	argTypes[2]		= argTypes[14]	= argTypes[26]	= argTypes[38]	= &ffi_type_uint16;
+	argValues[2]	= argValues[14]	= argValues[26]	= argValues[38]	= &ui16;
+	argTypes[3]		= argTypes[15]	= argTypes[27]	= argTypes[39]	= &ffi_type_sint16;
+	argValues[3]	= argValues[15]	= argValues[27]	= argValues[39]	= &si16;
+	argTypes[4]		= argTypes[16]	= argTypes[28]	= argTypes[40]	= &ffi_type_uint32;
+	argValues[4]	= argValues[16]	= argValues[28]	= argValues[40]	= &ui32;
+	argTypes[5]		= argTypes[17]	= argTypes[29]	= argTypes[41]	= &ffi_type_sint32;
+	argValues[5]	= argValues[17]	= argValues[29]	= argValues[41]	= &si32;
+	argTypes[6]		= argTypes[18]	= argTypes[30]	= argTypes[42]	= &ffi_type_uint64;
+	argValues[6]	= argValues[18]	= argValues[30]	= argValues[42]	= &ui64;
+	argTypes[7]		= argTypes[19]	= argTypes[31]	= argTypes[43]	= &ffi_type_sint64;
+	argValues[7]	= argValues[19]	= argValues[31]	= argValues[43]	= &si64;
+	argTypes[8]		= argTypes[20]	= argTypes[32]	= argTypes[44]	= &ffi_type_float;
+	argValues[8]	= argValues[20]	= argValues[32]	= argValues[44]	= &f;
+	argTypes[9]		= argTypes[21]	= argTypes[33]	= argTypes[45]	= &ffi_type_double;
+	argValues[9]	= argValues[21]	= argValues[33]	= argValues[45]	= &d;
+	argTypes[10]	= argTypes[22]	= argTypes[34]	= argTypes[46]	= &ffi_type_longdouble;
+	argValues[10]	= argValues[22]	= argValues[34]	= argValues[46]	= &ld;
+	argTypes[11]	= argTypes[23]	= argTypes[35]	= argTypes[47]	= &ffi_type_pointer;
+	argValues[11]	= argValues[23]	= argValues[35]	= argValues[47]	= &p;
+
+	argTypes[50]	= NULL;
+	argValues[50]	= NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 50, &ret_struct_type, argTypes) == FFI_OK);
+
+	ffi_call(&cif, FFI_FN(test_large_fn), &retVal, argValues);
+	// { dg-output "1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+	printf("res: %" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n",
+		retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
+	       retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l,
+		retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
+	       retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, (unsigned long)retVal.x,
+		retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
+	       retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
+		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
+	       retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
+	// { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_large_fn, NULL, code) == FFI_OK);
+
+	retVal	= ((BigStruct(*)(
+		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+		uint8_t, int8_t))(code))(
+		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+		ui8, si8);
+	// { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+	printf("res: %" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n",
+		retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
+	       retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l,
+		retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
+	       retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, (unsigned long)retVal.x,
+		retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
+	       retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
+		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
+	       retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
+	// { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+
+    return 0;
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/many.c b/third_party/gofrontend/libffi/testsuite/libffi.call/many.c
new file mode 100644
index 0000000..4869ba9
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/many.c
@@ -0,0 +1,69 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+#include <float.h>
+
+static float many(float f1,
+		  float f2,
+		  float f3,
+		  float f4,
+		  float f5,
+		  float f6,
+		  float f7,
+		  float f8,
+		  float f9,
+		  float f10,
+		  float f11,
+		  float f12,
+		  float f13)
+{
+#if 0
+  printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
+	 (double) f1, (double) f2, (double) f3, (double) f4, (double) f5, 
+	 (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
+	 (double) f11, (double) f12, (double) f13);
+#endif
+
+  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[13];
+  void *values[13];
+  float fa[13];
+  float f, ff;
+  int i;
+
+  for (i = 0; i < 13; i++)
+    {
+      args[i] = &ffi_type_float;
+      values[i] = &fa[i];
+      fa[i] = (float) i;
+    }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
+		       &ffi_type_float, args) == FFI_OK);
+
+    ffi_call(&cif, FFI_FN(many), &f, values);
+
+    ff =  many(fa[0], fa[1],
+	       fa[2], fa[3],
+	       fa[4], fa[5],
+	       fa[6], fa[7],
+	       fa[8], fa[9],
+	       fa[10],fa[11],fa[12]);
+
+    if (f - ff < FLT_EPSILON)
+      exit(0);
+    else
+      abort();
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/many2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/many2.c
new file mode 100644
index 0000000..1077159
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/many2.c
@@ -0,0 +1,54 @@
+/* Area:        ffi_call
+   Purpose:     Check uint8_t arguments.
+   Limitations: none.
+   PR:          PR45677.
+   Originator:  Dan Witte <dwitte@gmail.com> 20100916  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+#define NARGS 7
+
+typedef unsigned char u8;
+
+__attribute__((noinline)) uint8_t
+foo (uint8_t a, uint8_t b, uint8_t c, uint8_t d,
+     uint8_t e, uint8_t f, uint8_t g)
+{
+  return a + b + c + d + e + f + g;
+}
+
+uint8_t
+bar (uint8_t a, uint8_t b, uint8_t c, uint8_t d,
+     uint8_t e, uint8_t f, uint8_t g)
+{
+  return foo (a, b, c, d, e, f, g);
+}
+
+int
+main (void)
+{
+  ffi_type *ffitypes[NARGS];
+  int i;
+  ffi_cif cif;
+  ffi_arg result = 0;
+  uint8_t args[NARGS];
+  void *argptrs[NARGS];
+
+  for (i = 0; i < NARGS; ++i)
+    ffitypes[i] = &ffi_type_uint8;
+
+  CHECK (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, NARGS,
+		       &ffi_type_uint8, ffitypes) == FFI_OK);
+
+  for (i = 0; i < NARGS; ++i)
+    {
+      args[i] = i;
+      argptrs[i] = &args[i];
+    }
+  ffi_call (&cif, FFI_FN (bar), &result, argptrs);
+
+  CHECK (result == 21);
+  return 0;
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/many2_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/many2_win32.c
new file mode 100644
index 0000000..4adbe4d
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/many2_win32.c
@@ -0,0 +1,63 @@
+/* Area:	ffi_call
+   Purpose:	Check stdcall many call on X86_WIN32 systems.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+
+#include "ffitest.h"
+#include <float.h>
+
+static float __attribute__((fastcall)) fastcall_many(float f1,
+						   float f2,
+						   float f3,
+						   float f4,
+						   float f5,
+						   float f6,
+						   float f7,
+						   float f8,
+						   float f9,
+						   float f10,
+						   float f11,
+						   float f12,
+						   float f13)
+{
+  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[13];
+  void *values[13];
+  float fa[13];
+  float f, ff;
+  unsigned long ul;
+
+  for (ul = 0; ul < 13; ul++)
+    {
+      args[ul] = &ffi_type_float;
+      values[ul] = &fa[ul];
+	fa[ul] = (float) ul;
+    }
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 13,
+		     &ffi_type_float, args) == FFI_OK);
+
+  ff =  fastcall_many(fa[0], fa[1],
+		     fa[2], fa[3],
+		     fa[4], fa[5],
+		     fa[6], fa[7],
+		     fa[8], fa[9],
+		     fa[10], fa[11], fa[12]);
+
+  ffi_call(&cif, FFI_FN(fastcall_many), &f, values);
+
+  if (f - ff < FLT_EPSILON)
+    printf("fastcall many arg tests ok!\n");
+  else
+    CHECK(0);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/many_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/many_win32.c
new file mode 100644
index 0000000..1b26332
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/many_win32.c
@@ -0,0 +1,63 @@
+/* Area:	ffi_call
+   Purpose:	Check stdcall many call on X86_WIN32 systems.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+
+#include "ffitest.h"
+#include <float.h>
+
+static float __attribute__((stdcall)) stdcall_many(float f1,
+						   float f2,
+						   float f3,
+						   float f4,
+						   float f5,
+						   float f6,
+						   float f7,
+						   float f8,
+						   float f9,
+						   float f10,
+						   float f11,
+						   float f12,
+						   float f13)
+{
+  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[13];
+  void *values[13];
+  float fa[13];
+  float f, ff;
+  unsigned long ul;
+
+  for (ul = 0; ul < 13; ul++)
+    {
+      args[ul] = &ffi_type_float;
+      values[ul] = &fa[ul];
+	fa[ul] = (float) ul;
+    }
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 13,
+		     &ffi_type_float, args) == FFI_OK);
+
+  ff =  stdcall_many(fa[0], fa[1],
+		     fa[2], fa[3],
+		     fa[4], fa[5],
+		     fa[6], fa[7],
+		     fa[8], fa[9],
+		     fa[10], fa[11], fa[12]);
+
+  ffi_call(&cif, FFI_FN(stdcall_many), &f, values);
+
+  if (f - ff < FLT_EPSILON)
+    printf("stdcall many arg tests ok!\n");
+  else
+    CHECK(0);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/negint.c b/third_party/gofrontend/libffi/testsuite/libffi.call/negint.c
new file mode 100644
index 0000000..3168113
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/negint.c
@@ -0,0 +1,53 @@
+/* Area:	ffi_call
+   Purpose:	Check that negative integers are passed correctly.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+/* { dg-options -O2 } */
+
+#include "ffitest.h"
+
+static int checking(int a, short b, signed char c)
+{
+
+  return (a < 0 && b < 0 && c < 0);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  signed int si;
+  signed short ss;
+  signed char sc;
+
+  args[0] = &ffi_type_sint;
+  values[0] = &si;
+  args[1] = &ffi_type_sshort;
+  values[1] = &ss;
+  args[2] = &ffi_type_schar;
+  values[2] = &sc;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &ffi_type_sint, args) == FFI_OK);
+
+  si = -6;
+  ss = -12;
+  sc = -1;
+
+  checking (si, ss, sc);
+
+  ffi_call(&cif, FFI_FN(checking), &rint, values);
+
+  printf ("%d vs %d\n", (int)rint, checking (si, ss, sc));
+
+  CHECK(rint != 0);
+
+  exit (0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct.c
new file mode 100644
index 0000000..c15e3a0
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct.c
@@ -0,0 +1,152 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_16byte1 {
+  double a;
+  float b;
+  int c;
+} cls_struct_16byte1;
+
+typedef struct cls_struct_16byte2 {
+  int ii;
+  double dd;
+  float ff;
+} cls_struct_16byte2;
+
+typedef struct cls_struct_combined {
+  cls_struct_16byte1 d;
+  cls_struct_16byte2 e;
+} cls_struct_combined;
+
+cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0,
+			    struct cls_struct_16byte2 b1,
+			    struct cls_struct_combined b2)
+{
+  struct cls_struct_combined result;
+
+  result.d.a = b0.a + b1.dd + b2.d.a;
+  result.d.b = b0.b + b1.ff + b2.d.b;
+  result.d.c = b0.c + b1.ii + b2.d.c;
+  result.e.ii = b0.c + b1.ii + b2.e.ii;
+  result.e.dd = b0.a + b1.dd + b2.e.dd;
+  result.e.ff = b0.b + b1.ff + b2.e.ff;
+
+  printf("%g %g %d %d %g %g %g %g %d %d %g %g: %g %g %d %d %g %g\n",
+	 b0.a, b0.b, b0.c,
+	 b1.ii, b1.dd, b1.ff,
+	 b2.d.a, b2.d.b, b2.d.c,
+	 b2.e.ii, b2.e.dd, b2.e.ff,
+	 result.d.a, result.d.b, result.d.c,
+	 result.e.ii, result.e.dd, result.e.ff);
+
+  return result;
+}
+
+static void
+cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		       void* userdata __UNUSED__)
+{
+  struct cls_struct_16byte1 b0;
+  struct cls_struct_16byte2 b1;
+  struct cls_struct_combined b2;
+
+  b0 = *(struct cls_struct_16byte1*)(args[0]);
+  b1 = *(struct cls_struct_16byte2*)(args[1]);
+  b2 = *(struct cls_struct_combined*)(args[2]);
+
+
+  *(cls_struct_combined*)resp = cls_struct_combined_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type* cls_struct_fields1[5];
+  ffi_type* cls_struct_fields2[5];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_16byte1 e_dbl = { 9.0, 2.0, 6};
+  struct cls_struct_16byte2 f_dbl = { 1, 2.0, 3.0};
+  struct cls_struct_combined g_dbl = {{4.0, 5.0, 6},
+				      {3, 1.0, 8.0}};
+  struct cls_struct_combined res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = &ffi_type_sint;
+  cls_struct_fields[3] = NULL;
+
+  cls_struct_fields1[0] = &ffi_type_sint;
+  cls_struct_fields1[1] = &ffi_type_double;
+  cls_struct_fields1[2] = &ffi_type_float;
+  cls_struct_fields1[3] = NULL;
+
+  cls_struct_fields2[0] = &cls_struct_type;
+  cls_struct_fields2[1] = &cls_struct_type1;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type2,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_combined_fn), &res_dbl, args_dbl);
+  /* { dg-output "9 2 6 1 2 3 4 5 6 3 1 8: 15 10 13 10 12 13" } */
+  CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
+  CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
+  CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
+  CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
+  CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
+  CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_combined(*)(cls_struct_16byte1,
+				     cls_struct_16byte2,
+				     cls_struct_combined))
+	     (code))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n9 2 6 1 2 3 4 5 6 3 1 8: 15 10 13 10 12 13" } */
+  CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
+  CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
+  CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
+  CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
+  CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
+  CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct1.c
new file mode 100644
index 0000000..1087f7b
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct1.c
@@ -0,0 +1,161 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_16byte1 {
+  double a;
+  float b;
+  int c;
+} cls_struct_16byte1;
+
+typedef struct cls_struct_16byte2 {
+  int ii;
+  double dd;
+  float ff;
+} cls_struct_16byte2;
+
+typedef struct cls_struct_combined {
+  cls_struct_16byte1 d;
+  cls_struct_16byte2 e;
+} cls_struct_combined;
+
+cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0,
+					   struct cls_struct_16byte2 b1,
+					   struct cls_struct_combined b2,
+					   struct cls_struct_16byte1 b3)
+{
+  struct cls_struct_combined result;
+
+  result.d.a = b0.a + b1.dd + b2.d.a;
+  result.d.b = b0.b + b1.ff + b2.d.b;
+  result.d.c = b0.c + b1.ii + b2.d.c;
+  result.e.ii = b0.c + b1.ii + b2.e.ii;
+  result.e.dd = b0.a + b1.dd + b2.e.dd;
+  result.e.ff = b0.b + b1.ff + b2.e.ff;
+
+  printf("%g %g %d %d %g %g %g %g %d %d %g %g %g %g %d: %g %g %d %d %g %g\n",
+	 b0.a, b0.b, b0.c,
+	 b1.ii, b1.dd, b1.ff,
+	 b2.d.a, b2.d.b, b2.d.c,
+	 b2.e.ii, b2.e.dd, b2.e.ff,
+	 b3.a, b3.b, b3.c,
+	 result.d.a, result.d.b, result.d.c,
+	 result.e.ii, result.e.dd, result.e.ff);
+
+  return result;
+}
+
+static void
+cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		       void* userdata __UNUSED__)
+{
+  struct cls_struct_16byte1 b0;
+  struct cls_struct_16byte2 b1;
+  struct cls_struct_combined b2;
+  struct cls_struct_16byte1 b3;
+
+  b0 = *(struct cls_struct_16byte1*)(args[0]);
+  b1 = *(struct cls_struct_16byte2*)(args[1]);
+  b2 = *(struct cls_struct_combined*)(args[2]);
+  b3 = *(struct cls_struct_16byte1*)(args[3]);
+
+
+  *(cls_struct_combined*)resp = cls_struct_combined_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type* cls_struct_fields1[5];
+  ffi_type* cls_struct_fields2[5];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_16byte1 e_dbl = { 9.0, 2.0, 6};
+  struct cls_struct_16byte2 f_dbl = { 1, 2.0, 3.0};
+  struct cls_struct_combined g_dbl = {{4.0, 5.0, 6},
+				      {3, 1.0, 8.0}};
+  struct cls_struct_16byte1 h_dbl = { 3.0, 2.0, 4};
+  struct cls_struct_combined res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = &ffi_type_sint;
+  cls_struct_fields[3] = NULL;
+
+  cls_struct_fields1[0] = &ffi_type_sint;
+  cls_struct_fields1[1] = &ffi_type_double;
+  cls_struct_fields1[2] = &ffi_type_float;
+  cls_struct_fields1[3] = NULL;
+
+  cls_struct_fields2[0] = &cls_struct_type;
+  cls_struct_fields2[1] = &cls_struct_type1;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = &cls_struct_type;
+  dbl_arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type2,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = &h_dbl;
+  args_dbl[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_combined_fn), &res_dbl, args_dbl);
+  /* { dg-output "9 2 6 1 2 3 4 5 6 3 1 8 3 2 4: 15 10 13 10 12 13" } */
+  CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
+  CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
+  CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
+  CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
+  CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
+  CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_combined(*)(cls_struct_16byte1,
+				     cls_struct_16byte2,
+				     cls_struct_combined,
+				     cls_struct_16byte1))
+	     (code))(e_dbl, f_dbl, g_dbl, h_dbl);
+  /* { dg-output "\n9 2 6 1 2 3 4 5 6 3 1 8 3 2 4: 15 10 13 10 12 13" } */
+  CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
+  CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
+  CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
+  CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
+  CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
+  CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
+  //  CHECK( 1 == 0);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct10.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct10.c
new file mode 100644
index 0000000..34a74e7
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct10.c
@@ -0,0 +1,133 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  unsigned char y;
+  struct A x;
+  unsigned int z;
+} B;
+
+typedef struct C {
+  unsigned long long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b3.z + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y, b3.z, (int)b4.d, b4.e,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[4];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = { 99, {12LL , 127}, 255};
+  struct C g_dbl = { 2LL, 9};
+
+  struct B res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  cls_struct_fields[0] = &ffi_type_uint64;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &ffi_type_uchar;
+  cls_struct_fields1[1] = &cls_struct_type;
+  cls_struct_fields1[2] = &ffi_type_uint;
+  cls_struct_fields1[3] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_uint64;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 255 2 9: 270 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 255 2 9: 270 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct11.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct11.c
new file mode 100644
index 0000000..fce6948
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct11.c
@@ -0,0 +1,121 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check parameter passing with nested structs
+		of a single type.  This tests the special cases
+		for homogenous floating-point aggregates in the
+		AArch64 PCS.
+   Limitations:	none.
+   PR:		none.
+   Originator:  ARM Ltd.  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  float a_x;
+  float a_y;
+} A;
+
+typedef struct B {
+  float b_x;
+  float b_y;
+} B;
+
+typedef struct C {
+  A a;
+  B b;
+} C;
+
+static C C_fn (int x, int y, int z, C source, int i, int j, int k)
+{
+  C result;
+  result.a.a_x = source.a.a_x;
+  result.a.a_y = source.a.a_y;
+  result.b.b_x = source.b.b_x;
+  result.b.b_y = source.b.b_y;
+
+  printf ("%d, %d, %d, %d, %d, %d\n", x, y, z, i, j, k);
+
+  printf ("%.1f, %.1f, %.1f, %.1f, "
+	  "%.1f, %.1f, %.1f, %.1f\n",
+	  source.a.a_x, source.a.a_y,
+	  source.b.b_x, source.b.b_y,
+	  result.a.a_x, result.a.a_y,
+	  result.b.b_x, result.b.b_y);
+
+  return result;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+
+  ffi_type* struct_fields_source_a[3];
+  ffi_type* struct_fields_source_b[3];
+  ffi_type* struct_fields_source_c[3];
+  ffi_type* arg_types[8];
+
+  ffi_type struct_type_a, struct_type_b, struct_type_c;
+
+  struct A source_fld_a = {1.0, 2.0};
+  struct B source_fld_b = {4.0, 8.0};
+  int k = 1;
+
+  struct C result;
+  struct C source = {source_fld_a, source_fld_b};
+
+  struct_type_a.size = 0;
+  struct_type_a.alignment = 0;
+  struct_type_a.type = FFI_TYPE_STRUCT;
+  struct_type_a.elements = struct_fields_source_a;
+
+  struct_type_b.size = 0;
+  struct_type_b.alignment = 0;
+  struct_type_b.type = FFI_TYPE_STRUCT;
+  struct_type_b.elements = struct_fields_source_b;
+
+  struct_type_c.size = 0;
+  struct_type_c.alignment = 0;
+  struct_type_c.type = FFI_TYPE_STRUCT;
+  struct_type_c.elements = struct_fields_source_c;
+
+  struct_fields_source_a[0] = &ffi_type_float;
+  struct_fields_source_a[1] = &ffi_type_float;
+  struct_fields_source_a[2] = NULL;
+
+  struct_fields_source_b[0] = &ffi_type_float;
+  struct_fields_source_b[1] = &ffi_type_float;
+  struct_fields_source_b[2] = NULL;
+
+  struct_fields_source_c[0] = &struct_type_a;
+  struct_fields_source_c[1] = &struct_type_b;
+  struct_fields_source_c[2] = NULL;
+
+  arg_types[0] = &ffi_type_sint32;
+  arg_types[1] = &ffi_type_sint32;
+  arg_types[2] = &ffi_type_sint32;
+  arg_types[3] = &struct_type_c;
+  arg_types[4] = &ffi_type_sint32;
+  arg_types[5] = &ffi_type_sint32;
+  arg_types[6] = &ffi_type_sint32;
+  arg_types[7] = NULL;
+
+  void *args[7];
+  args[0] = &k;
+  args[1] = &k;
+  args[2] = &k;
+  args[3] = &source;
+  args[4] = &k;
+  args[5] = &k;
+  args[6] = &k;
+  CHECK (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, 7, &struct_type_c,
+		       arg_types) == FFI_OK);
+
+  ffi_call (&cif, FFI_FN (C_fn), &result, args);
+  /* { dg-output "1, 1, 1, 1, 1, 1\n" } */
+  /* { dg-output "1.0, 2.0, 4.0, 8.0, 1.0, 2.0, 4.0, 8.0" } */
+  CHECK (result.a.a_x == source.a.a_x);
+  CHECK (result.a.a_y == source.a.a_y);
+  CHECK (result.b.b_x == source.b.b_x);
+  CHECK (result.b.b_y == source.b.b_y);
+  exit (0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct2.c
new file mode 100644
index 0000000..69268cd
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct2.c
@@ -0,0 +1,110 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030911	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+B B_fn(struct A b0, struct B b1)
+{
+  struct B result;
+
+  result.x.a = b0.a + b1.x.a;
+  result.x.b = b0.b + b1.x.b + b1.y;
+  result.y = b0.b + b1.x.b;
+
+  printf("%lu %d %lu %d %d: %lu %d %d\n", b0.a, b0.b, b1.x.a, b1.x.b, b1.y,
+	 result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+  struct A e_dbl = { 1, 7};
+  struct B f_dbl = {{12 , 127}, 99};
+
+  struct B res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_fields[0] = &ffi_type_ulong;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct3.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct3.c
new file mode 100644
index 0000000..ab18cad
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct3.c
@@ -0,0 +1,111 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030911	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+B B_fn(struct A b0, struct B b1)
+{
+  struct B result;
+
+  result.x.a = b0.a + b1.x.a;
+  result.x.b = b0.b + b1.x.b + b1.y;
+  result.y = b0.b + b1.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b0.a, b0.b,
+	 (int)b1.x.a, b1.x.b, b1.y,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = {{12LL , 127}, 99};
+
+  struct B res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_fields[0] = &ffi_type_uint64;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct4.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct4.c
new file mode 100644
index 0000000..2ffb4d6
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct4.c
@@ -0,0 +1,111 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		PR 25630.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  double a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a;
+  result.x.b = b2.b + b3.x.b + b3.y;
+  result.y = b2.b + b3.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+  struct A e_dbl = { 1.0, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+
+  struct B res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct5.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct5.c
new file mode 100644
index 0000000..6c79845
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct5.c
@@ -0,0 +1,112 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  long double a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a;
+  result.x.b = b2.b + b3.x.b + b3.y;
+  result.y = b2.b + b3.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+  struct A e_dbl = { 1.0, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+
+  struct B res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_fields[0] = &ffi_type_longdouble;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct6.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct6.c
new file mode 100644
index 0000000..59d3579
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct6.c
@@ -0,0 +1,131 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		PR 25630.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  double a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+typedef struct C {
+  long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+  struct A e_dbl = { 1.0, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+  struct C g_dbl = { 2, 9};
+
+  struct B res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_slong;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct7.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct7.c
new file mode 100644
index 0000000..27595e6
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct7.c
@@ -0,0 +1,111 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a;
+  result.x.b = b2.b + b3.x.b + b3.y;
+  result.y = b2.b + b3.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+
+  struct B res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_fields[0] = &ffi_type_uint64;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct8.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct8.c
new file mode 100644
index 0000000..0e6c682
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct8.c
@@ -0,0 +1,131 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+typedef struct C {
+  unsigned long long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = {{12LL , 127}, 99};
+  struct C g_dbl = { 2LL, 9};
+
+  struct B res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  cls_struct_fields[0] = &ffi_type_uint64;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_uint64;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct9.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct9.c
new file mode 100644
index 0000000..5f7ac67
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct9.c
@@ -0,0 +1,131 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned char a;
+  unsigned long long b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+typedef struct C {
+  unsigned long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d: %d %d %d\n", b2.a, (int)b2.b,
+	 b3.x.a, (int)b3.x.b, b3.y, (int)b4.d, b4.e,
+	 result.x.a, (int)result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+  struct A e_dbl = { 1, 7LL};
+  struct B f_dbl = {{12.0 , 127}, 99};
+  struct C g_dbl = { 2, 9};
+
+  struct B res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uint64;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_ulong;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/problem1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/problem1.c
new file mode 100644
index 0000000..6a91555
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/problem1.c
@@ -0,0 +1,90 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct my_ffi_struct {
+  double a;
+  double b;
+  double c;
+} my_ffi_struct;
+
+my_ffi_struct callee(struct my_ffi_struct a1, struct my_ffi_struct a2)
+{
+  struct my_ffi_struct result;
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+
+  printf("%g %g %g %g %g %g: %g %g %g\n", a1.a, a1.b, a1.c,
+	 a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return result;
+}
+
+void stub(ffi_cif* cif __UNUSED__, void* resp, void** args,
+	  void* userdata __UNUSED__)
+{
+  struct my_ffi_struct a1;
+  struct my_ffi_struct a2;
+
+  a1 = *(struct my_ffi_struct*)(args[0]);
+  a2 = *(struct my_ffi_struct*)(args[1]);
+
+  *(my_ffi_struct *)resp = callee(a1, a2);
+}
+
+
+int main(void)
+{
+  ffi_type* my_ffi_struct_fields[4];
+  ffi_type my_ffi_struct_type;
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args[4];
+  ffi_type* arg_types[3];
+
+  struct my_ffi_struct g = { 1.0, 2.0, 3.0 };
+  struct my_ffi_struct f = { 1.0, 2.0, 3.0 };
+  struct my_ffi_struct res;
+
+  my_ffi_struct_type.size = 0;
+  my_ffi_struct_type.alignment = 0;
+  my_ffi_struct_type.type = FFI_TYPE_STRUCT;
+  my_ffi_struct_type.elements = my_ffi_struct_fields;
+
+  my_ffi_struct_fields[0] = &ffi_type_double;
+  my_ffi_struct_fields[1] = &ffi_type_double;
+  my_ffi_struct_fields[2] = &ffi_type_double;
+  my_ffi_struct_fields[3] = NULL;
+
+  arg_types[0] = &my_ffi_struct_type;
+  arg_types[1] = &my_ffi_struct_type;
+  arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &my_ffi_struct_type,
+		     arg_types) == FFI_OK);
+
+  args[0] = &g;
+  args[1] = &f;
+  args[2] = NULL;
+  ffi_call(&cif, FFI_FN(callee), &res, args);
+  /* { dg-output "1 2 3 1 2 3: 2 4 6" } */
+  printf("res: %g %g %g\n", res.a, res.b, res.c);
+  /* { dg-output "\nres: 2 4 6" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, stub, NULL, code) == FFI_OK);
+
+  res = ((my_ffi_struct(*)(struct my_ffi_struct, struct my_ffi_struct))(code))(g, f);
+  /* { dg-output "\n1 2 3 1 2 3: 2 4 6" } */
+  printf("res: %g %g %g\n", res.a, res.b, res.c);
+  /* { dg-output "\nres: 2 4 6" } */
+
+  exit(0);;
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/promotion.c b/third_party/gofrontend/libffi/testsuite/libffi.call/promotion.c
new file mode 100644
index 0000000..4456161
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/promotion.c
@@ -0,0 +1,59 @@
+/* Area:	ffi_call
+   Purpose:	Promotion test.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static int promotion(signed char sc, signed short ss,
+		     unsigned char uc, unsigned short us)
+{
+  int r = (int) sc + (int) ss + (int) uc + (int) us;
+
+  return r;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  signed char sc;
+  unsigned char uc;
+  signed short ss;
+  unsigned short us;
+  unsigned long ul;
+
+  args[0] = &ffi_type_schar;
+  args[1] = &ffi_type_sshort;
+  args[2] = &ffi_type_uchar;
+  args[3] = &ffi_type_ushort;
+  values[0] = &sc;
+  values[1] = &ss;
+  values[2] = &uc;
+  values[3] = &us;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_sint, args) == FFI_OK);
+
+  us = 0;
+  ul = 0;
+
+  for (sc = (signed char) -127;
+       sc <= (signed char) 120; sc += 1)
+    for (ss = -30000; ss <= 30000; ss += 10000)
+      for (uc = (unsigned char) 0;
+	   uc <= (unsigned char) 200; uc += 20)
+	for (us = 0; us <= 60000; us += 10000)
+	  {
+	    ul++;
+	    ffi_call(&cif, FFI_FN(promotion), &rint, values);
+	    CHECK((int)rint == (signed char) sc + (signed short) ss +
+		  (unsigned char) uc + (unsigned short) us);
+	  }
+  printf("%lu promotion tests run\n", ul);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/pyobjc-tc.c b/third_party/gofrontend/libffi/testsuite/libffi.call/pyobjc-tc.c
new file mode 100644
index 0000000..e29bd6c
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/pyobjc-tc.c
@@ -0,0 +1,114 @@
+/* Area:	ffi_call
+   Purpose:	Check different structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	Ronald Oussoren <oussoren@cistron.nl> 20030824	*/
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct Point {
+	float x;
+	float y;
+} Point;
+
+typedef struct Size {
+	float h;
+	float w;
+} Size;
+
+typedef struct Rect {
+	Point o;
+	Size  s;
+} Rect;
+
+int doit(int o, char* s, Point p, Rect r, int last)
+{
+	printf("CALLED WITH %d %s {%f %f} {{%f %f} {%f %f}} %d\n",
+		o, s, p.x, p.y, r.o.x, r.o.y, r.s.h, r.s.w, last);
+	return 42;
+}
+
+
+int main(void)
+{
+	ffi_type point_type;
+	ffi_type size_type;
+	ffi_type rect_type;
+	ffi_cif cif;
+	ffi_type* arglist[6];
+	void* values[6];
+	int r;
+
+	/*
+	 *  First set up FFI types for the 3 struct types
+	 */
+
+	point_type.size = 0; /*sizeof(Point);*/
+	point_type.alignment = 0; /*__alignof__(Point);*/
+	point_type.type = FFI_TYPE_STRUCT;
+	point_type.elements = malloc(3 * sizeof(ffi_type*));
+	point_type.elements[0] = &ffi_type_float;
+	point_type.elements[1] = &ffi_type_float;
+	point_type.elements[2] = NULL;
+
+	size_type.size = 0;/* sizeof(Size);*/
+	size_type.alignment = 0;/* __alignof__(Size);*/
+	size_type.type = FFI_TYPE_STRUCT;
+	size_type.elements = malloc(3 * sizeof(ffi_type*));
+	size_type.elements[0] = &ffi_type_float;
+	size_type.elements[1] = &ffi_type_float;
+	size_type.elements[2] = NULL;
+
+	rect_type.size = 0;/*sizeof(Rect);*/
+	rect_type.alignment =0;/* __alignof__(Rect);*/
+	rect_type.type = FFI_TYPE_STRUCT;
+	rect_type.elements = malloc(3 * sizeof(ffi_type*));
+	rect_type.elements[0] = &point_type;
+	rect_type.elements[1] = &size_type;
+	rect_type.elements[2] = NULL;
+
+	/*
+	 * Create a CIF
+	 */
+	arglist[0] = &ffi_type_sint;
+	arglist[1] = &ffi_type_pointer;
+	arglist[2] = &point_type;
+	arglist[3] = &rect_type;
+	arglist[4] = &ffi_type_sint;
+	arglist[5] = NULL;
+
+	r = ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
+			5, &ffi_type_sint, arglist);
+	if (r != FFI_OK) {
+		abort();
+	}
+
+
+	/* And call the function through the CIF */
+
+	{
+	Point p = { 1.0, 2.0 };
+	Rect  r = { { 9.0, 10.0}, { -1.0, -2.0 } };
+	int   o = 0;
+	int   l = 42;
+	char* m = "myMethod";
+	ffi_arg result;
+
+	values[0] = &o;
+	values[1] = &m;
+	values[2] = &p;
+	values[3] = &r;
+	values[4] = &l;
+	values[5] = NULL;
+
+	printf("CALLING WITH %d %s {%f %f} {{%f %f} {%f %f}} %d\n",
+		o, m, p.x, p.y, r.o.x, r.o.y, r.s.h, r.s.w, l);
+
+	ffi_call(&cif, FFI_FN(doit), &result, values);
+
+	printf ("The result is %d\n", (int)result);
+
+	}
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl.c
new file mode 100644
index 0000000..1aab403
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl.c
@@ -0,0 +1,35 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl)
+{
+  return 2 * dbl;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double dbl, rdbl;
+
+  args[0] = &ffi_type_double;
+  values[0] = &dbl;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_double, args) == FFI_OK);
+
+  for (dbl = -127.3; dbl <  127; dbl++)
+    {
+      ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+      printf ("%f vs %f\n", rdbl, return_dbl(dbl));
+      CHECK(rdbl == 2 * dbl);
+    }
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl1.c
new file mode 100644
index 0000000..0ea5d50
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl1.c
@@ -0,0 +1,43 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl1, float fl2, unsigned int in3, double dbl4)
+{
+  return dbl1 + fl2 + in3 + dbl4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double dbl1, dbl4, rdbl;
+  float fl2;
+  unsigned int in3;
+  args[0] = &ffi_type_double;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_uint;
+  args[3] = &ffi_type_double;
+  values[0] = &dbl1;
+  values[1] = &fl2;
+  values[2] = &in3;
+  values[3] = &dbl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_double, args) == FFI_OK);
+  dbl1 = 127.0;
+  fl2 = 128.0;
+  in3 = 255;
+  dbl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+  printf ("%f vs %f\n", rdbl, return_dbl(dbl1, fl2, in3, dbl4));
+  CHECK(rdbl ==  dbl1 + fl2 + in3 + dbl4);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl2.c
new file mode 100644
index 0000000..b3818f8
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl2.c
@@ -0,0 +1,42 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl1, double dbl2, unsigned int in3, double dbl4)
+{
+  return dbl1 + dbl2 + in3 + dbl4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double dbl1, dbl2, dbl4, rdbl;
+  unsigned int in3;
+  args[0] = &ffi_type_double;
+  args[1] = &ffi_type_double;
+  args[2] = &ffi_type_uint;
+  args[3] = &ffi_type_double;
+  values[0] = &dbl1;
+  values[1] = &dbl2;
+  values[2] = &in3;
+  values[3] = &dbl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_double, args) == FFI_OK);
+  dbl1 = 127.0;
+  dbl2 = 128.0;
+  in3 = 255;
+  dbl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+  printf ("%f vs %f\n", rdbl, return_dbl(dbl1, dbl2, in3, dbl4));
+  CHECK(rdbl ==  dbl1 + dbl2 + in3 + dbl4);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl.c
new file mode 100644
index 0000000..fb8a09e
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl.c
@@ -0,0 +1,35 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl)
+{
+  return 2 * fl;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl, rfl;
+
+  args[0] = &ffi_type_float;
+  values[0] = &fl;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_float, args) == FFI_OK);
+
+  for (fl = -127.0; fl <  127; fl++)
+    {
+      ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+      printf ("%f vs %f\n", rfl, return_fl(fl));
+      CHECK(rfl ==  2 * fl);
+    }
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl1.c
new file mode 100644
index 0000000..c3d92c2
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl1.c
@@ -0,0 +1,36 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl1, float fl2)
+{
+  return fl1 + fl2;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl1, fl2, rfl;
+
+  args[0] = &ffi_type_float;
+  args[1] = &ffi_type_float;
+  values[0] = &fl1;
+  values[1] = &fl2;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_float, args) == FFI_OK);
+  fl1 = 127.0;
+  fl2 = 128.0;
+
+  ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+  printf ("%f vs %f\n", rfl, return_fl(fl1, fl2));
+  CHECK(rfl ==  fl1 + fl2);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl2.c
new file mode 100644
index 0000000..ddb976c
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl2.c
@@ -0,0 +1,49 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+/* Use volatile float to avoid false negative on ix86.  See PR target/323.  */
+static float return_fl(float fl1, float fl2, float fl3, float fl4)
+{
+  volatile float sum;
+
+  sum = fl1 + fl2 + fl3 + fl4;
+  return sum;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl1, fl2, fl3, fl4, rfl;
+  volatile float sum;
+
+  args[0] = &ffi_type_float;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_float;
+  args[3] = &ffi_type_float;
+  values[0] = &fl1;
+  values[1] = &fl2;
+  values[2] = &fl3;
+  values[3] = &fl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_float, args) == FFI_OK);
+  fl1 = 127.0;
+  fl2 = 128.0;
+  fl3 = 255.1;
+  fl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+  printf ("%f vs %f\n", rfl, return_fl(fl1, fl2, fl3, fl4));
+
+  sum = fl1 + fl2 + fl3 + fl4;
+  CHECK(rfl == sum);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl3.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl3.c
new file mode 100644
index 0000000..c37877b
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_fl3.c
@@ -0,0 +1,42 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl1, float fl2, unsigned int in3, float fl4)
+{
+  return fl1 + fl2 + in3 + fl4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl1, fl2, fl4, rfl;
+  unsigned int in3;
+  args[0] = &ffi_type_float;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_uint;
+  args[3] = &ffi_type_float;
+  values[0] = &fl1;
+  values[1] = &fl2;
+  values[2] = &in3;
+  values[3] = &fl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_float, args) == FFI_OK);
+  fl1 = 127.0;
+  fl2 = 128.0;
+  in3 = 255;
+  fl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+  printf ("%f vs %f\n", rfl, return_fl(fl1, fl2, in3, fl4));
+  CHECK(rfl ==  fl1 + fl2 + in3 + fl4);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_ldl.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_ldl.c
new file mode 100644
index 0000000..5c2fe65
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_ldl.c
@@ -0,0 +1,34 @@
+/* Area:	ffi_call
+   Purpose:	Check return value long double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20071113  */
+
+/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+#include "ffitest.h"
+
+static long double return_ldl(long double ldl)
+{
+  return 2*ldl;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  long double ldl, rldl;
+
+  args[0] = &ffi_type_longdouble;
+  values[0] = &ldl;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_longdouble, args) == FFI_OK);
+
+  for (ldl = -127.0; ldl <  127.0; ldl++)
+    {
+      ffi_call(&cif, FFI_FN(return_ldl), &rldl, values);
+      CHECK(rldl ==  2 * ldl);
+    }
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_ll.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_ll.c
new file mode 100644
index 0000000..ea4a1e4
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_ll.c
@@ -0,0 +1,41 @@
+/* Area:	ffi_call
+   Purpose:	Check return value long long.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static long long return_ll(long long ll)
+{
+  return ll;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  long long rlonglong;
+  long long ll;
+
+  args[0] = &ffi_type_sint64;
+  values[0] = &ll;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_sint64, args) == FFI_OK);
+
+  for (ll = 0LL; ll < 100LL; ll++)
+    {
+      ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+      CHECK(rlonglong == ll);
+    }
+
+  for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
+    {
+      ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+      CHECK(rlonglong == ll);
+    }
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_ll1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_ll1.c
new file mode 100644
index 0000000..593e8a3
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_ll1.c
@@ -0,0 +1,43 @@
+/* Area:	ffi_call
+   Purpose:	Check if long long are passed in the corresponding regs on ppc.
+   Limitations:	none.
+   PR:		20104.
+   Originator:	<andreast@gcc.gnu.org> 20050222  */
+
+/* { dg-do run } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#include "ffitest.h"
+static long long return_ll(int ll0, long long ll1, int ll2)
+{
+  return ll0 + ll1 + ll2;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  long long rlonglong;
+  long long ll1;
+  unsigned ll0, ll2;
+
+  args[0] = &ffi_type_sint;
+  args[1] = &ffi_type_sint64;
+  args[2] = &ffi_type_sint;
+  values[0] = &ll0;
+  values[1] = &ll1;
+  values[2] = &ll2;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &ffi_type_sint64, args) == FFI_OK);
+
+  ll0 = 11111111;
+  ll1 = 11111111111000LL;
+  ll2 = 11111111;
+
+  ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+  printf("res: %" PRIdLL ", %" PRIdLL "\n", rlonglong, ll0 + ll1 + ll2);
+  /* { dg-output "res: 11111133333222, 11111133333222" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_sc.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_sc.c
new file mode 100644
index 0000000..a36cf3e
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_sc.c
@@ -0,0 +1,36 @@
+/* Area:	ffi_call
+   Purpose:	Check return value signed char.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static signed char return_sc(signed char sc)
+{
+  return sc;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  signed char sc;
+
+  args[0] = &ffi_type_schar;
+  values[0] = &sc;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_schar, args) == FFI_OK);
+
+  for (sc = (signed char) -127;
+       sc < (signed char) 127; sc++)
+    {
+      ffi_call(&cif, FFI_FN(return_sc), &rint, values);
+      CHECK((signed char)rint == sc);
+    }
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_sl.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_sl.c
new file mode 100644
index 0000000..f0fd345
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_sl.c
@@ -0,0 +1,38 @@
+/* Area:	ffi_call
+   Purpose:	Check if long as return type is handled correctly.
+   Limitations:	none.
+   PR:		none.
+ */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static long return_sl(long l1, long l2)
+{
+  return l1 - l2;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg res;
+  unsigned long l1, l2;
+
+  args[0] = &ffi_type_slong;
+  args[1] = &ffi_type_slong;
+  values[0] = &l1;
+  values[1] = &l2;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_slong, args) == FFI_OK);
+
+  l1 = 1073741823L;
+  l2 = 1073741824L;
+
+  ffi_call(&cif, FFI_FN(return_sl), &res, values);
+  printf("res: %ld, %ld\n", (long)res, l1 - l2);
+  /* { dg-output "res: -1, -1" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_uc.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_uc.c
new file mode 100644
index 0000000..07c45de
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_uc.c
@@ -0,0 +1,38 @@
+/* Area:	ffi_call
+   Purpose:	Check return value unsigned char.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static unsigned char return_uc(unsigned char uc)
+{
+  return uc;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  unsigned char uc;
+
+  args[0] = &ffi_type_uchar;
+  values[0] = &uc;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_uchar, args) == FFI_OK);
+
+  for (uc = (unsigned char) '\x00';
+       uc < (unsigned char) '\xff'; uc++)
+    {
+      ffi_call(&cif, FFI_FN(return_uc), &rint, values);
+      CHECK(rint == (signed int) uc);
+    }
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_ul.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_ul.c
new file mode 100644
index 0000000..12b266f
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_ul.c
@@ -0,0 +1,38 @@
+/* Area:	ffi_call
+   Purpose:	Check if unsigned long as return type is handled correctly.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<kaffeetisch at gmx dot de> 20060724  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static unsigned long return_ul(unsigned long ul1, unsigned long ul2)
+{
+  return ul1 + ul2;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg res;
+  unsigned long ul1, ul2;
+
+  args[0] = &ffi_type_ulong;
+  args[1] = &ffi_type_ulong;
+  values[0] = &ul1;
+  values[1] = &ul2;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_ulong, args) == FFI_OK);
+
+  ul1 = 1073741823L;
+  ul2 = 1073741824L;
+
+  ffi_call(&cif, FFI_FN(return_ul), &res, values);
+  printf("res: %lu, %lu\n", (unsigned long)res, ul1 + ul2);
+  /* { dg-output "res: 2147483647, 2147483647" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large.c b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large.c
new file mode 100644
index 0000000..f32938c
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large.c
@@ -0,0 +1,145 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check structure returning with different structure size.
+				Depending on the ABI. Check bigger struct which overlaps
+				the gp and fp register count on Darwin/AIX/ppc64.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin	6/21/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-*  } } */
+#include "ffitest.h"
+
+// 13 FPRs: 104 bytes
+// 14 FPRs: 112 bytes
+
+typedef struct struct_108byte {
+	double a;
+	double b;
+	double c;
+	double d;
+	double e;
+	double f;
+	double g;
+	double h;
+	double i;
+	double j;
+	double k;
+	double l;
+	double m;
+	int n;
+} struct_108byte;
+
+struct_108byte cls_struct_108byte_fn(
+	struct_108byte b0,
+	struct_108byte b1,
+	struct_108byte b2,
+	struct_108byte b3)
+{
+	struct_108byte	result;
+
+	result.a = b0.a + b1.a + b2.a + b3.a;
+	result.b = b0.b + b1.b + b2.b + b3.b;
+	result.c = b0.c + b1.c + b2.c + b3.c;
+	result.d = b0.d + b1.d + b2.d + b3.d;
+	result.e = b0.e + b1.e + b2.e + b3.e;
+	result.f = b0.f + b1.f + b2.f + b3.f;
+	result.g = b0.g + b1.g + b2.g + b3.g;
+	result.h = b0.h + b1.h + b2.h + b3.h;
+	result.i = b0.i + b1.i + b2.i + b3.i;
+	result.j = b0.j + b1.j + b2.j + b3.j;
+	result.k = b0.k + b1.k + b2.k + b3.k;
+	result.l = b0.l + b1.l + b2.l + b3.l;
+	result.m = b0.m + b1.m + b2.m + b3.m;
+	result.n = b0.n + b1.n + b2.n + b3.n;
+
+	printf("%g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", result.a, result.b, result.c,
+		result.d, result.e, result.f, result.g, result.h, result.i,
+		result.j, result.k, result.l, result.m, result.n);
+
+	return result;
+}
+
+static void
+cls_struct_108byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+	struct_108byte	b0, b1, b2, b3;
+
+	b0 = *(struct_108byte*)(args[0]);
+	b1 = *(struct_108byte*)(args[1]);
+	b2 = *(struct_108byte*)(args[2]);
+	b3 = *(struct_108byte*)(args[3]);
+
+	*(struct_108byte*)resp = cls_struct_108byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[5];
+	ffi_type* cls_struct_fields[15];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[5];
+
+	struct_108byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 1.0, 2.0, 3.0, 7.0, 2.0, 7 };
+	struct_108byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0, 5.0, 7.0, 9.0, 1.0, 4 };
+	struct_108byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 8.0, 6.0, 1.0, 4.0, 0.0, 3 };
+	struct_108byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 9.0, 2.0, 6.0, 5.0, 3.0, 2 };
+	struct_108byte res_dbl;
+
+	cls_struct_type.size = 0;
+	cls_struct_type.alignment = 0;
+	cls_struct_type.type = FFI_TYPE_STRUCT;
+	cls_struct_type.elements = cls_struct_fields;
+
+	cls_struct_fields[0] = &ffi_type_double;
+	cls_struct_fields[1] = &ffi_type_double;
+	cls_struct_fields[2] = &ffi_type_double;
+	cls_struct_fields[3] = &ffi_type_double;
+	cls_struct_fields[4] = &ffi_type_double;
+	cls_struct_fields[5] = &ffi_type_double;
+	cls_struct_fields[6] = &ffi_type_double;
+	cls_struct_fields[7] = &ffi_type_double;
+	cls_struct_fields[8] = &ffi_type_double;
+	cls_struct_fields[9] = &ffi_type_double;
+	cls_struct_fields[10] = &ffi_type_double;
+	cls_struct_fields[11] = &ffi_type_double;
+	cls_struct_fields[12] = &ffi_type_double;
+	cls_struct_fields[13] = &ffi_type_sint32;
+	cls_struct_fields[14] = NULL;
+
+	dbl_arg_types[0] = &cls_struct_type;
+	dbl_arg_types[1] = &cls_struct_type;
+	dbl_arg_types[2] = &cls_struct_type;
+	dbl_arg_types[3] = &cls_struct_type;
+	dbl_arg_types[4] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+		dbl_arg_types) == FFI_OK);
+
+	args_dbl[0] = &e_dbl;
+	args_dbl[1] = &f_dbl;
+	args_dbl[2] = &g_dbl;
+	args_dbl[3] = &h_dbl;
+	args_dbl[4] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_struct_108byte_fn), &res_dbl, args_dbl);
+	/* { dg-output "22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
+		res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_108byte_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((struct_108byte(*)(struct_108byte, struct_108byte,
+		struct_108byte, struct_108byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
+	/* { dg-output "\n22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
+		res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large2.c
new file mode 100644
index 0000000..3b0ef9a
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large2.c
@@ -0,0 +1,148 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check structure returning with different structure size.
+				Depending on the ABI. Check bigger struct which overlaps
+				the gp and fp register count on Darwin/AIX/ppc64.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin	6/21/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-*  } } */
+#include "ffitest.h"
+
+// 13 FPRs: 104 bytes
+// 14 FPRs: 112 bytes
+
+typedef struct struct_116byte {
+	double a;
+	double b;
+	double c;
+	double d;
+	double e;
+	double f;
+	double g;
+	double h;
+	double i;
+	double j;
+	double k;
+	double l;
+	double m;
+	double n;
+	int o;
+} struct_116byte;
+
+struct_116byte cls_struct_116byte_fn(
+	struct_116byte b0,
+	struct_116byte b1,
+	struct_116byte b2,
+	struct_116byte b3)
+{
+	struct_116byte	result;
+
+	result.a = b0.a + b1.a + b2.a + b3.a;
+	result.b = b0.b + b1.b + b2.b + b3.b;
+	result.c = b0.c + b1.c + b2.c + b3.c;
+	result.d = b0.d + b1.d + b2.d + b3.d;
+	result.e = b0.e + b1.e + b2.e + b3.e;
+	result.f = b0.f + b1.f + b2.f + b3.f;
+	result.g = b0.g + b1.g + b2.g + b3.g;
+	result.h = b0.h + b1.h + b2.h + b3.h;
+	result.i = b0.i + b1.i + b2.i + b3.i;
+	result.j = b0.j + b1.j + b2.j + b3.j;
+	result.k = b0.k + b1.k + b2.k + b3.k;
+	result.l = b0.l + b1.l + b2.l + b3.l;
+	result.m = b0.m + b1.m + b2.m + b3.m;
+	result.n = b0.n + b1.n + b2.n + b3.n;
+	result.o = b0.o + b1.o + b2.o + b3.o;
+
+	printf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", result.a, result.b, result.c,
+		result.d, result.e, result.f, result.g, result.h, result.i,
+		result.j, result.k, result.l, result.m, result.n, result.o);
+
+	return result;
+}
+
+static void
+cls_struct_116byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+	struct_116byte	b0, b1, b2, b3;
+
+	b0 = *(struct_116byte*)(args[0]);
+	b1 = *(struct_116byte*)(args[1]);
+	b2 = *(struct_116byte*)(args[2]);
+	b3 = *(struct_116byte*)(args[3]);
+
+	*(struct_116byte*)resp = cls_struct_116byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[5];
+	ffi_type* cls_struct_fields[16];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[5];
+
+	struct_116byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 7 };
+	struct_116byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0, 5.0, 7.0, 9.0, 1.0, 6.0, 4 };
+	struct_116byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 8.0, 6.0, 1.0, 4.0, 0.0, 7.0, 3 };
+	struct_116byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 9.0, 2.0, 6.0, 5.0, 3.0, 8.0, 2 };
+	struct_116byte res_dbl;
+
+	cls_struct_type.size = 0;
+	cls_struct_type.alignment = 0;
+	cls_struct_type.type = FFI_TYPE_STRUCT;
+	cls_struct_type.elements = cls_struct_fields;
+
+	cls_struct_fields[0] = &ffi_type_double;
+	cls_struct_fields[1] = &ffi_type_double;
+	cls_struct_fields[2] = &ffi_type_double;
+	cls_struct_fields[3] = &ffi_type_double;
+	cls_struct_fields[4] = &ffi_type_double;
+	cls_struct_fields[5] = &ffi_type_double;
+	cls_struct_fields[6] = &ffi_type_double;
+	cls_struct_fields[7] = &ffi_type_double;
+	cls_struct_fields[8] = &ffi_type_double;
+	cls_struct_fields[9] = &ffi_type_double;
+	cls_struct_fields[10] = &ffi_type_double;
+	cls_struct_fields[11] = &ffi_type_double;
+	cls_struct_fields[12] = &ffi_type_double;
+	cls_struct_fields[13] = &ffi_type_double;
+	cls_struct_fields[14] = &ffi_type_sint32;
+	cls_struct_fields[15] = NULL;
+
+	dbl_arg_types[0] = &cls_struct_type;
+	dbl_arg_types[1] = &cls_struct_type;
+	dbl_arg_types[2] = &cls_struct_type;
+	dbl_arg_types[3] = &cls_struct_type;
+	dbl_arg_types[4] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+		dbl_arg_types) == FFI_OK);
+
+	args_dbl[0] = &e_dbl;
+	args_dbl[1] = &f_dbl;
+	args_dbl[2] = &g_dbl;
+	args_dbl[3] = &h_dbl;
+	args_dbl[4] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_struct_116byte_fn), &res_dbl, args_dbl);
+	/* { dg-output "22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
+		res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n, res_dbl.o);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_116byte_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((struct_116byte(*)(struct_116byte, struct_116byte,
+		struct_116byte, struct_116byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
+	/* { dg-output "\n22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
+		res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n, res_dbl.o);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/stret_medium.c b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_medium.c
new file mode 100644
index 0000000..973ee02
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_medium.c
@@ -0,0 +1,124 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check structure returning with different structure size.
+				Depending on the ABI. Check bigger struct which overlaps
+				the gp and fp register count on Darwin/AIX/ppc64.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin	6/21/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-*  } } */
+#include "ffitest.h"
+
+typedef struct struct_72byte {
+	double a;
+	double b;
+	double c;
+	double d;
+	double e;
+	double f;
+	double g;
+	double h;
+	double i;
+} struct_72byte;
+
+struct_72byte cls_struct_72byte_fn(
+	struct_72byte b0,
+	struct_72byte b1,
+	struct_72byte b2,
+	struct_72byte b3)
+{
+	struct_72byte	result;
+
+	result.a = b0.a + b1.a + b2.a + b3.a;
+	result.b = b0.b + b1.b + b2.b + b3.b;
+	result.c = b0.c + b1.c + b2.c + b3.c;
+	result.d = b0.d + b1.d + b2.d + b3.d;
+	result.e = b0.e + b1.e + b2.e + b3.e;
+	result.f = b0.f + b1.f + b2.f + b3.f;
+	result.g = b0.g + b1.g + b2.g + b3.g;
+	result.h = b0.h + b1.h + b2.h + b3.h;
+	result.i = b0.i + b1.i + b2.i + b3.i;
+
+	printf("%g %g %g %g %g %g %g %g %g\n", result.a, result.b, result.c,
+		result.d, result.e, result.f, result.g, result.h, result.i);
+
+	return result;
+}
+
+static void
+cls_struct_72byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+	struct_72byte	b0, b1, b2, b3;
+
+	b0 = *(struct_72byte*)(args[0]);
+	b1 = *(struct_72byte*)(args[1]);
+	b2 = *(struct_72byte*)(args[2]);
+	b3 = *(struct_72byte*)(args[3]);
+
+	*(struct_72byte*)resp = cls_struct_72byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[5];
+	ffi_type* cls_struct_fields[10];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[5];
+
+	struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7.0 };
+	struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0 };
+	struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3.0 };
+	struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2.0 };
+	struct_72byte res_dbl;
+
+	cls_struct_type.size = 0;
+	cls_struct_type.alignment = 0;
+	cls_struct_type.type = FFI_TYPE_STRUCT;
+	cls_struct_type.elements = cls_struct_fields;
+
+	cls_struct_fields[0] = &ffi_type_double;
+	cls_struct_fields[1] = &ffi_type_double;
+	cls_struct_fields[2] = &ffi_type_double;
+	cls_struct_fields[3] = &ffi_type_double;
+	cls_struct_fields[4] = &ffi_type_double;
+	cls_struct_fields[5] = &ffi_type_double;
+	cls_struct_fields[6] = &ffi_type_double;
+	cls_struct_fields[7] = &ffi_type_double;
+	cls_struct_fields[8] = &ffi_type_double;
+	cls_struct_fields[9] = NULL;
+
+	dbl_arg_types[0] = &cls_struct_type;
+	dbl_arg_types[1] = &cls_struct_type;
+	dbl_arg_types[2] = &cls_struct_type;
+	dbl_arg_types[3] = &cls_struct_type;
+	dbl_arg_types[4] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+		dbl_arg_types) == FFI_OK);
+
+	args_dbl[0] = &e_dbl;
+	args_dbl[1] = &f_dbl;
+	args_dbl[2] = &g_dbl;
+	args_dbl[3] = &h_dbl;
+	args_dbl[4] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_struct_72byte_fn), &res_dbl, args_dbl);
+	/* { dg-output "22 15 17 25 6 13 19 18 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
+		res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_72byte_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte,
+		struct_72byte, struct_72byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
+	/* { dg-output "\n22 15 17 25 6 13 19 18 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
+		res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/stret_medium2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_medium2.c
new file mode 100644
index 0000000..84323d1
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_medium2.c
@@ -0,0 +1,125 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check structure returning with different structure size.
+				Depending on the ABI. Check bigger struct which overlaps
+				the gp and fp register count on Darwin/AIX/ppc64.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin	6/21/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-*  } } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#include "ffitest.h"
+
+typedef struct struct_72byte {
+	double a;
+	double b;
+	double c;
+	double d;
+	double e;
+	double f;
+	double g;
+	double h;
+	long long i;
+} struct_72byte;
+
+struct_72byte cls_struct_72byte_fn(
+	struct_72byte b0,
+	struct_72byte b1,
+	struct_72byte b2,
+	struct_72byte b3)
+{
+	struct_72byte	result;
+
+	result.a = b0.a + b1.a + b2.a + b3.a;
+	result.b = b0.b + b1.b + b2.b + b3.b;
+	result.c = b0.c + b1.c + b2.c + b3.c;
+	result.d = b0.d + b1.d + b2.d + b3.d;
+	result.e = b0.e + b1.e + b2.e + b3.e;
+	result.f = b0.f + b1.f + b2.f + b3.f;
+	result.g = b0.g + b1.g + b2.g + b3.g;
+	result.h = b0.h + b1.h + b2.h + b3.h;
+	result.i = b0.i + b1.i + b2.i + b3.i;
+
+	printf("%g %g %g %g %g %g %g %g %" PRIdLL "\n", result.a, result.b, result.c,
+		result.d, result.e, result.f, result.g, result.h, result.i);
+
+	return result;
+}
+
+static void
+cls_struct_72byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+	struct_72byte	b0, b1, b2, b3;
+
+	b0 = *(struct_72byte*)(args[0]);
+	b1 = *(struct_72byte*)(args[1]);
+	b2 = *(struct_72byte*)(args[2]);
+	b3 = *(struct_72byte*)(args[3]);
+
+	*(struct_72byte*)resp = cls_struct_72byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[5];
+	ffi_type* cls_struct_fields[10];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[5];
+
+	struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7 };
+	struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4 };
+	struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3 };
+	struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2 };
+	struct_72byte res_dbl;
+
+	cls_struct_type.size = 0;
+	cls_struct_type.alignment = 0;
+	cls_struct_type.type = FFI_TYPE_STRUCT;
+	cls_struct_type.elements = cls_struct_fields;
+
+	cls_struct_fields[0] = &ffi_type_double;
+	cls_struct_fields[1] = &ffi_type_double;
+	cls_struct_fields[2] = &ffi_type_double;
+	cls_struct_fields[3] = &ffi_type_double;
+	cls_struct_fields[4] = &ffi_type_double;
+	cls_struct_fields[5] = &ffi_type_double;
+	cls_struct_fields[6] = &ffi_type_double;
+	cls_struct_fields[7] = &ffi_type_double;
+	cls_struct_fields[8] = &ffi_type_sint64;
+	cls_struct_fields[9] = NULL;
+
+	dbl_arg_types[0] = &cls_struct_type;
+	dbl_arg_types[1] = &cls_struct_type;
+	dbl_arg_types[2] = &cls_struct_type;
+	dbl_arg_types[3] = &cls_struct_type;
+	dbl_arg_types[4] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+		dbl_arg_types) == FFI_OK);
+
+	args_dbl[0] = &e_dbl;
+	args_dbl[1] = &f_dbl;
+	args_dbl[2] = &g_dbl;
+	args_dbl[3] = &h_dbl;
+	args_dbl[4] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_struct_72byte_fn), &res_dbl, args_dbl);
+	/* { dg-output "22 15 17 25 6 13 19 18 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %" PRIdLL "\n", res_dbl.a, res_dbl.b, res_dbl.c,
+		res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_72byte_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte,
+		struct_72byte, struct_72byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
+	/* { dg-output "\n22 15 17 25 6 13 19 18 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %" PRIdLL "\n", res_dbl.a, res_dbl.b, res_dbl.c,
+		res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+	exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/strlen.c b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen.c
new file mode 100644
index 0000000..3de45de
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen.c
@@ -0,0 +1,44 @@
+/* Area:	ffi_call
+   Purpose:	Check strlen function call.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static size_t my_strlen(char *s)
+{
+  return (strlen(s));
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  char *s;
+
+  args[0] = &ffi_type_pointer;
+  values[0] = (void*) &s;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		     &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+  CHECK(rint == 1);
+  
+  s = "1234567";
+  ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+  CHECK(rint == 7);
+  
+  s = "1234567890123456789012345";
+  ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+  CHECK(rint == 25);
+  
+  exit (0);
+}
+  
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/strlen2_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen2_win32.c
new file mode 100644
index 0000000..0d81061
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen2_win32.c
@@ -0,0 +1,44 @@
+/* Area:	ffi_call
+   Purpose:	Check fastcall strlen call on X86_WIN32 systems.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+
+#include "ffitest.h"
+
+static size_t __FASTCALL__ my_fastcall_strlen(char *s)
+{
+  return (strlen(s));
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  char *s;
+  args[0] = &ffi_type_pointer;
+  values[0] = (void*) &s;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1,
+		       &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values);
+  CHECK(rint == 1);
+  
+  s = "1234567";
+  ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values);
+  CHECK(rint == 7);
+  
+  s = "1234567890123456789012345";
+  ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values);
+  CHECK(rint == 25);
+  
+  printf("fastcall strlen tests passed\n");
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/strlen_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen_win32.c
new file mode 100644
index 0000000..6fbcc87
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen_win32.c
@@ -0,0 +1,44 @@
+/* Area:	ffi_call
+   Purpose:	Check stdcall strlen call on X86_WIN32 systems.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+
+#include "ffitest.h"
+
+static size_t __attribute__((stdcall)) my_stdcall_strlen(char *s)
+{
+  return (strlen(s));
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  char *s;
+  args[0] = &ffi_type_pointer;
+  values[0] = (void*) &s;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 1,
+		       &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
+  CHECK(rint == 1);
+  
+  s = "1234567";
+  ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
+  CHECK(rint == 7);
+  
+  s = "1234567890123456789012345";
+  ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
+  CHECK(rint == 25);
+  
+  printf("stdcall strlen tests passed\n");
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct1.c
new file mode 100644
index 0000000..bfc23f6
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct1.c
@@ -0,0 +1,67 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  unsigned char uc;
+  double d;
+  unsigned int ui;
+} test_structure_1;
+
+static test_structure_1 struct1(test_structure_1 ts)
+{
+  ts.uc++;
+  ts.d--;
+  ts.ui++;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts1_type;
+  ffi_type *ts1_type_elements[4];
+
+  test_structure_1 ts1_arg;
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_1 *ts1_result =
+    (test_structure_1 *) malloc (sizeof(test_structure_1));
+
+  ts1_type.size = 0;
+  ts1_type.alignment = 0;
+  ts1_type.type = FFI_TYPE_STRUCT;
+  ts1_type.elements = ts1_type_elements;
+  ts1_type_elements[0] = &ffi_type_uchar;
+  ts1_type_elements[1] = &ffi_type_double;
+  ts1_type_elements[2] = &ffi_type_uint;
+  ts1_type_elements[3] = NULL;
+  
+  args[0] = &ts1_type;
+  values[0] = &ts1_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		     &ts1_type, args) == FFI_OK);
+  
+  ts1_arg.uc = '\x01';
+  ts1_arg.d = 3.14159;
+  ts1_arg.ui = 555;
+
+  ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+  
+  CHECK(ts1_result->ui == 556);
+  CHECK(ts1_result->d == 3.14159 - 1);
+ 
+  free (ts1_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct1_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct1_win32.c
new file mode 100644
index 0000000..b756f5a
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct1_win32.c
@@ -0,0 +1,67 @@
+/* Area:	ffi_call
+   Purpose:	Check structures with fastcall/thiscall convention.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+#include "ffitest.h"
+
+typedef struct
+{
+  unsigned char uc;
+  double d;
+  unsigned int ui;
+} test_structure_1;
+
+static test_structure_1 __FASTCALL__ struct1(test_structure_1 ts)
+{
+  ts.uc++;
+  ts.d--;
+  ts.ui++;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts1_type;
+  ffi_type *ts1_type_elements[4];
+
+  test_structure_1 ts1_arg;
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_1 *ts1_result =
+    (test_structure_1 *) malloc (sizeof(test_structure_1));
+
+  ts1_type.size = 0;
+  ts1_type.alignment = 0;
+  ts1_type.type = FFI_TYPE_STRUCT;
+  ts1_type.elements = ts1_type_elements;
+  ts1_type_elements[0] = &ffi_type_uchar;
+  ts1_type_elements[1] = &ffi_type_double;
+  ts1_type_elements[2] = &ffi_type_uint;
+  ts1_type_elements[3] = NULL;
+  
+  args[0] = &ts1_type;
+  values[0] = &ts1_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1, 
+		     &ts1_type, args) == FFI_OK);
+  
+  ts1_arg.uc = '\x01';
+  ts1_arg.d = 3.14159;
+  ts1_arg.ui = 555;
+
+  ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+  
+  CHECK(ts1_result->ui == 556);
+  CHECK(ts1_result->d == 3.14159 - 1);
+ 
+  free (ts1_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct2.c
new file mode 100644
index 0000000..d85385e
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct2.c
@@ -0,0 +1,67 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  double d1;
+  double d2;
+} test_structure_2;
+
+static test_structure_2 struct2(test_structure_2 ts)
+{
+  ts.d1--;
+  ts.d2--;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  test_structure_2 ts2_arg;
+  ffi_type ts2_type;
+  ffi_type *ts2_type_elements[3];
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_2 *ts2_result =
+    (test_structure_2 *) malloc (sizeof(test_structure_2));
+
+  ts2_type.size = 0;
+  ts2_type.alignment = 0;
+  ts2_type.type = FFI_TYPE_STRUCT;
+  ts2_type.elements = ts2_type_elements;
+  ts2_type_elements[0] = &ffi_type_double;
+  ts2_type_elements[1] = &ffi_type_double;
+  ts2_type_elements[2] = NULL;
+
+  args[0] = &ts2_type;
+  values[0] = &ts2_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts2_type, args) == FFI_OK);
+  
+  ts2_arg.d1 = 5.55;
+  ts2_arg.d2 = 6.66;
+  
+  printf ("%g\n", ts2_arg.d1);
+  printf ("%g\n", ts2_arg.d2);
+  
+  ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
+  
+  printf ("%g\n", ts2_result->d1);
+  printf ("%g\n", ts2_result->d2);
+  
+  CHECK(ts2_result->d1 == 5.55 - 1);
+  CHECK(ts2_result->d2 == 6.66 - 1);
+  
+  free (ts2_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct2_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct2_win32.c
new file mode 100644
index 0000000..5d02285
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct2_win32.c
@@ -0,0 +1,67 @@
+/* Area:	ffi_call
+   Purpose:	Check structures in fastcall/stdcall function
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+#include "ffitest.h"
+
+typedef struct
+{
+  double d1;
+  double d2;
+} test_structure_2;
+
+static test_structure_2 __FASTCALL__ struct2(test_structure_2 ts)
+{
+  ts.d1--;
+  ts.d2--;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  test_structure_2 ts2_arg;
+  ffi_type ts2_type;
+  ffi_type *ts2_type_elements[3];
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_2 *ts2_result =
+    (test_structure_2 *) malloc (sizeof(test_structure_2));
+
+  ts2_type.size = 0;
+  ts2_type.alignment = 0;
+  ts2_type.type = FFI_TYPE_STRUCT;
+  ts2_type.elements = ts2_type_elements;
+  ts2_type_elements[0] = &ffi_type_double;
+  ts2_type_elements[1] = &ffi_type_double;
+  ts2_type_elements[2] = NULL;
+
+  args[0] = &ts2_type;
+  values[0] = &ts2_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1, &ts2_type, args) == FFI_OK);
+  
+  ts2_arg.d1 = 5.55;
+  ts2_arg.d2 = 6.66;
+  
+  printf ("%g\n", ts2_arg.d1);
+  printf ("%g\n", ts2_arg.d2);
+  
+  ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
+  
+  printf ("%g\n", ts2_result->d1);
+  printf ("%g\n", ts2_result->d2);
+  
+  CHECK(ts2_result->d1 == 5.55 - 1);
+  CHECK(ts2_result->d2 == 6.66 - 1);
+  
+  free (ts2_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct3.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct3.c
new file mode 100644
index 0000000..de883c2
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct3.c
@@ -0,0 +1,60 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  int si;
+} test_structure_3;
+
+static test_structure_3 struct3(test_structure_3 ts)
+{
+  ts.si = -(ts.si*2);
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  int compare_value;
+  ffi_type ts3_type;
+  ffi_type *ts3_type_elements[2];
+
+  test_structure_3 ts3_arg;
+  test_structure_3 *ts3_result =
+    (test_structure_3 *) malloc (sizeof(test_structure_3));
+
+  ts3_type.size = 0;
+  ts3_type.alignment = 0;
+  ts3_type.type = FFI_TYPE_STRUCT;
+  ts3_type.elements = ts3_type_elements;
+  ts3_type_elements[0] = &ffi_type_sint;
+  ts3_type_elements[1] = NULL;
+
+  args[0] = &ts3_type;
+  values[0] = &ts3_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		     &ts3_type, args) == FFI_OK);
+  
+  ts3_arg.si = -123;
+  compare_value = ts3_arg.si;
+  
+  ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
+  
+  printf ("%d %d\n", ts3_result->si, -(compare_value*2));
+  
+  CHECK(ts3_result->si == -(compare_value*2));
+ 
+  free (ts3_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct4.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct4.c
new file mode 100644
index 0000000..48e0349
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct4.c
@@ -0,0 +1,64 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  unsigned ui1;
+  unsigned ui2;
+  unsigned ui3;
+} test_structure_4;
+
+static test_structure_4 struct4(test_structure_4 ts)
+{
+  ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts4_type;
+  ffi_type *ts4_type_elements[4];  
+
+  test_structure_4 ts4_arg;
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_4 *ts4_result =
+    (test_structure_4 *) malloc (sizeof(test_structure_4));
+
+  ts4_type.size = 0;
+  ts4_type.alignment = 0;
+  ts4_type.type = FFI_TYPE_STRUCT;
+  ts4_type.elements = ts4_type_elements;
+  ts4_type_elements[0] = &ffi_type_uint;
+  ts4_type_elements[1] = &ffi_type_uint;
+  ts4_type_elements[2] = &ffi_type_uint;
+  ts4_type_elements[3] = NULL;
+
+  args[0] = &ts4_type;
+  values[0] = &ts4_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts4_type, args) == FFI_OK);
+  
+  ts4_arg.ui1 = 2;
+  ts4_arg.ui2 = 3;
+  ts4_arg.ui3 = 4;
+  
+  ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
+  
+  CHECK(ts4_result->ui3 == 2U * 3U * 4U);
+ 
+  
+  free (ts4_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct5.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct5.c
new file mode 100644
index 0000000..28b1f0c
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct5.c
@@ -0,0 +1,66 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+  char c1;
+  char c2;
+} test_structure_5;
+
+static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
+{
+  ts1.c1 += ts2.c1;
+  ts1.c2 -= ts2.c2;
+  
+  return ts1;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts5_type;
+  ffi_type *ts5_type_elements[3];
+
+  test_structure_5 ts5_arg1, ts5_arg2;
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_5 *ts5_result =
+    (test_structure_5 *) malloc (sizeof(test_structure_5));
+
+  ts5_type.size = 0;
+  ts5_type.alignment = 0;
+  ts5_type.type = FFI_TYPE_STRUCT;
+  ts5_type.elements = ts5_type_elements;
+  ts5_type_elements[0] = &ffi_type_schar;
+  ts5_type_elements[1] = &ffi_type_schar;
+  ts5_type_elements[2] = NULL;
+
+  args[0] = &ts5_type;
+  args[1] = &ts5_type;
+  values[0] = &ts5_arg1;
+  values[1] = &ts5_arg2;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ts5_type, args) == FFI_OK);
+  
+  ts5_arg1.c1 = 2;
+  ts5_arg1.c2 = 6;
+  ts5_arg2.c1 = 5;
+  ts5_arg2.c2 = 3;
+  
+  ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
+  
+  CHECK(ts5_result->c1 == 7); 
+  CHECK(ts5_result->c2 == 3);
+  
+  
+  free (ts5_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct6.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct6.c
new file mode 100644
index 0000000..0e26746
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct6.c
@@ -0,0 +1,64 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+  float f;
+  double d;
+} test_structure_6;
+
+static test_structure_6 struct6 (test_structure_6 ts)
+{
+  ts.f += 1;
+  ts.d += 1;
+  
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts6_type;
+  ffi_type *ts6_type_elements[3];
+
+  test_structure_6 ts6_arg;
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_6 *ts6_result =
+    (test_structure_6 *) malloc (sizeof(test_structure_6));
+
+  ts6_type.size = 0;
+  ts6_type.alignment = 0;
+  ts6_type.type = FFI_TYPE_STRUCT;
+  ts6_type.elements = ts6_type_elements;
+  ts6_type_elements[0] = &ffi_type_float;
+  ts6_type_elements[1] = &ffi_type_double;
+  ts6_type_elements[2] = NULL;
+
+  args[0] = &ts6_type;
+  values[0] = &ts6_arg;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts6_type, args) == FFI_OK);
+  
+  ts6_arg.f = 5.55f;
+  ts6_arg.d = 6.66;
+  
+  printf ("%g\n", ts6_arg.f);
+  printf ("%g\n", ts6_arg.d);
+
+  ffi_call(&cif, FFI_FN(struct6), ts6_result, values);
+    
+  CHECK(ts6_result->f == 5.55f + 1);
+  CHECK(ts6_result->d == 6.66 + 1);
+    
+  free (ts6_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct7.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct7.c
new file mode 100644
index 0000000..8f2bbfd
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct7.c
@@ -0,0 +1,74 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+  float f1;
+  float f2;
+  double d;
+} test_structure_7;
+
+static test_structure_7 struct7 (test_structure_7 ts)
+{
+  ts.f1 += 1;
+  ts.f2 += 1;
+  ts.d += 1;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts7_type;
+  ffi_type *ts7_type_elements[4];
+
+  test_structure_7 ts7_arg;
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_7 *ts7_result =
+    (test_structure_7 *) malloc (sizeof(test_structure_7));
+
+  ts7_type.size = 0;
+  ts7_type.alignment = 0;
+  ts7_type.type = FFI_TYPE_STRUCT;
+  ts7_type.elements = ts7_type_elements;
+  ts7_type_elements[0] = &ffi_type_float;
+  ts7_type_elements[1] = &ffi_type_float;
+  ts7_type_elements[2] = &ffi_type_double;
+  ts7_type_elements[3] = NULL;
+
+  args[0] = &ts7_type;
+  values[0] = &ts7_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts7_type, args) == FFI_OK);
+  
+  ts7_arg.f1 = 5.55f;
+  ts7_arg.f2 = 55.5f;
+  ts7_arg.d = 6.66;
+
+  printf ("%g\n", ts7_arg.f1);
+  printf ("%g\n", ts7_arg.f2);
+  printf ("%g\n", ts7_arg.d);
+  
+  ffi_call(&cif, FFI_FN(struct7), ts7_result, values);
+
+  printf ("%g\n", ts7_result->f1);
+  printf ("%g\n", ts7_result->f2);
+  printf ("%g\n", ts7_result->d);
+  
+  CHECK(ts7_result->f1 == 5.55f + 1);
+  CHECK(ts7_result->f2 == 55.5f + 1);
+  CHECK(ts7_result->d == 6.66 + 1);
+  
+  free (ts7_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct8.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct8.c
new file mode 100644
index 0000000..266e1f0
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct8.c
@@ -0,0 +1,81 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+  float f1;
+  float f2;
+  float f3;
+  float f4;
+} test_structure_8;
+
+static test_structure_8 struct8 (test_structure_8 ts)
+{
+  ts.f1 += 1;
+  ts.f2 += 1;
+  ts.f3 += 1;
+  ts.f4 += 1;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts8_type;
+  ffi_type *ts8_type_elements[5];
+
+  test_structure_8 ts8_arg;
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_8 *ts8_result =
+    (test_structure_8 *) malloc (sizeof(test_structure_8));
+
+  ts8_type.size = 0;
+  ts8_type.alignment = 0;
+  ts8_type.type = FFI_TYPE_STRUCT;
+  ts8_type.elements = ts8_type_elements;
+  ts8_type_elements[0] = &ffi_type_float;
+  ts8_type_elements[1] = &ffi_type_float;
+  ts8_type_elements[2] = &ffi_type_float;
+  ts8_type_elements[3] = &ffi_type_float;
+  ts8_type_elements[4] = NULL;
+
+  args[0] = &ts8_type;
+  values[0] = &ts8_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts8_type, args) == FFI_OK);
+  
+  ts8_arg.f1 = 5.55f;
+  ts8_arg.f2 = 55.5f;
+  ts8_arg.f3 = -5.55f;
+  ts8_arg.f4 = -55.5f;
+
+  printf ("%g\n", ts8_arg.f1);
+  printf ("%g\n", ts8_arg.f2);
+  printf ("%g\n", ts8_arg.f3);
+  printf ("%g\n", ts8_arg.f4);
+  
+  ffi_call(&cif, FFI_FN(struct8), ts8_result, values);
+
+  printf ("%g\n", ts8_result->f1);
+  printf ("%g\n", ts8_result->f2);
+  printf ("%g\n", ts8_result->f3);
+  printf ("%g\n", ts8_result->f4);
+  
+  CHECK(ts8_result->f1 == 5.55f + 1);
+  CHECK(ts8_result->f2 == 55.5f + 1);
+  CHECK(ts8_result->f3 == -5.55f + 1);
+  CHECK(ts8_result->f4 == -55.5f + 1);
+  
+  free (ts8_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct9.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct9.c
new file mode 100644
index 0000000..efeb716
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct9.c
@@ -0,0 +1,68 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  float f;
+  int i;
+} test_structure_9;
+
+static test_structure_9 struct9 (test_structure_9 ts)
+{
+  ts.f += 1;
+  ts.i += 1;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts9_type;
+  ffi_type *ts9_type_elements[3];
+
+  test_structure_9 ts9_arg;
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_9 *ts9_result =
+    (test_structure_9 *) malloc (sizeof(test_structure_9));
+
+  ts9_type.size = 0;
+  ts9_type.alignment = 0;
+  ts9_type.type = FFI_TYPE_STRUCT;
+  ts9_type.elements = ts9_type_elements;
+  ts9_type_elements[0] = &ffi_type_float;
+  ts9_type_elements[1] = &ffi_type_sint;
+  ts9_type_elements[2] = NULL;
+
+  args[0] = &ts9_type;
+  values[0] = &ts9_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts9_type, args) == FFI_OK);
+  
+  ts9_arg.f = 5.55f;
+  ts9_arg.i = 5;
+  
+  printf ("%g\n", ts9_arg.f);
+  printf ("%d\n", ts9_arg.i);
+  
+  ffi_call(&cif, FFI_FN(struct9), ts9_result, values);
+
+  printf ("%g\n", ts9_result->f);
+  printf ("%d\n", ts9_result->i);
+  
+  CHECK(ts9_result->f == 5.55f + 1);
+  CHECK(ts9_result->i == 5 + 1);
+
+  free (ts9_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/testclosure.c b/third_party/gofrontend/libffi/testsuite/libffi.call/testclosure.c
new file mode 100644
index 0000000..ca31056
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/testclosure.c
@@ -0,0 +1,70 @@
+/* Area:	closure_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		41908.
+   Originator:	<rfm@gnu.org> 20091102	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_combined {
+  float a;
+  float b;
+  float c;
+  float d;
+} cls_struct_combined;
+
+void cls_struct_combined_fn(struct cls_struct_combined arg)
+{
+  printf("%g %g %g %g\n",
+	 arg.a, arg.b,
+	 arg.c, arg.d);
+  fflush(stdout);
+}
+
+static void
+cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+        void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_combined a0;
+
+  a0 = *(struct cls_struct_combined*)(args[0]);
+
+  cls_struct_combined_fn(a0);
+}
+
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type* cls_struct_fields0[5];
+  ffi_type cls_struct_type0;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_combined g_dbl = {4.0, 5.0, 1.0, 8.0};
+
+  cls_struct_type0.size = 0;
+  cls_struct_type0.alignment = 0;
+  cls_struct_type0.type = FFI_TYPE_STRUCT;
+  cls_struct_type0.elements = cls_struct_fields0;
+
+  cls_struct_fields0[0] = &ffi_type_float;
+  cls_struct_fields0[1] = &ffi_type_float;
+  cls_struct_fields0[2] = &ffi_type_float;
+  cls_struct_fields0[3] = &ffi_type_float;
+  cls_struct_fields0[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type0;
+  dbl_arg_types[1] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_void,
+		     dbl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK);
+
+  ((void(*)(cls_struct_combined)) (code))(g_dbl);
+  /* { dg-output "4 5 1 8" } */
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/uninitialized.c b/third_party/gofrontend/libffi/testsuite/libffi.call/uninitialized.c
new file mode 100644
index 0000000..f00d830
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/uninitialized.c
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  unsigned char uc;
+  double d;
+  unsigned int ui;
+} test_structure_1;
+
+static test_structure_1 struct1(test_structure_1 ts)
+{
+  ts.uc++;
+  ts.d--;
+  ts.ui++;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts1_type;
+  ffi_type *ts1_type_elements[4];
+
+  memset(&cif, 1, sizeof(cif));
+  ts1_type.size = 0;
+  ts1_type.alignment = 0;
+  ts1_type.type = FFI_TYPE_STRUCT;
+  ts1_type.elements = ts1_type_elements;
+  ts1_type_elements[0] = &ffi_type_uchar;
+  ts1_type_elements[1] = &ffi_type_double;
+  ts1_type_elements[2] = &ffi_type_uint;
+  ts1_type_elements[3] = NULL;
+
+  test_structure_1 ts1_arg;
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_1 *ts1_result =
+    (test_structure_1 *) malloc (sizeof(test_structure_1));
+
+  args[0] = &ts1_type;
+  values[0] = &ts1_arg;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ts1_type, args) == FFI_OK);
+
+  ts1_arg.uc = '\x01';
+  ts1_arg.d = 3.14159;
+  ts1_arg.ui = 555;
+
+  ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+
+  CHECK(ts1_result->ui == 556);
+  CHECK(ts1_result->d == 3.14159 - 1);
+
+  free (ts1_result);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/va_1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/va_1.c
new file mode 100644
index 0000000..7f96809
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/va_1.c
@@ -0,0 +1,196 @@
+/* Area:		ffi_call
+   Purpose:		Test passing struct in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator:	        ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static int
+test_fn (int n, ...)
+{
+  va_list ap;
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l;
+  unsigned char uc;
+  signed char sc;
+  unsigned short us;
+  signed short ss;
+  unsigned int ui;
+  signed int si;
+  unsigned long ul;
+  signed long sl;
+  float f;
+  double d;
+
+  va_start (ap, n);
+  s1 = va_arg (ap, struct small_tag);
+  l = va_arg (ap, struct large_tag);
+  s2 = va_arg (ap, struct small_tag);
+
+  uc = va_arg (ap, unsigned);
+  sc = va_arg (ap, signed);
+
+  us = va_arg (ap, unsigned);
+  ss = va_arg (ap, signed);
+
+  ui = va_arg (ap, unsigned int);
+  si = va_arg (ap, signed int);
+
+  ul = va_arg (ap, unsigned long);
+  sl = va_arg (ap, signed long);
+
+  f = va_arg (ap, double);	/* C standard promotes float->double
+				   when anonymous */
+  d = va_arg (ap, double);
+
+  printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n",
+	  s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+	  s2.a, s2.b,
+	  uc, sc,
+	  us, ss,
+	  ui, si,
+	  ul, sl,
+	  f, d);
+  va_end (ap);
+  return n + 1;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void* args[15];
+  ffi_type* arg_types[15];
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int n;
+  ffi_arg res;
+
+  unsigned char uc;
+  signed char sc;
+  unsigned short us;
+  signed short ss;
+  unsigned int ui;
+  signed int si;
+  unsigned long ul;
+  signed long sl;
+  double d1;
+  double f1;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = &ffi_type_uchar;
+  arg_types[5] = &ffi_type_schar;
+  arg_types[6] = &ffi_type_ushort;
+  arg_types[7] = &ffi_type_sshort;
+  arg_types[8] = &ffi_type_uint;
+  arg_types[9] = &ffi_type_sint;
+  arg_types[10] = &ffi_type_ulong;
+  arg_types[11] = &ffi_type_slong;
+  arg_types[12] = &ffi_type_double;
+  arg_types[13] = &ffi_type_double;
+  arg_types[14] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK);
+
+  s1.a = 5;
+  s1.b = 6;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  s2.a = 7;
+  s2.b = 8;
+
+  n = 41;
+
+  uc = 9;
+  sc = 10;
+  us = 11;
+  ss = 12;
+  ui = 13;
+  si = 14;
+  ul = 15;
+  sl = 16;
+  f1 = 2.12;
+  d1 = 3.13;
+
+  args[0] = &n;
+  args[1] = &s1;
+  args[2] = &l1;
+  args[3] = &s2;
+  args[4] = &uc;
+  args[5] = &sc;
+  args[6] = &us;
+  args[7] = &ss;
+  args[8] = &ui;
+  args[9] = &si;
+  args[10] = &ul;
+  args[11] = &sl;
+  args[12] = &f1;
+  args[13] = &d1;
+  args[14] = NULL;
+
+  ffi_call(&cif, FFI_FN(test_fn), &res, args);
+  /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */
+  printf("res: %d\n", (int) res);
+  /* { dg-output "\nres: 42" } */
+
+  return 0;
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct1.c
new file mode 100644
index 0000000..e645206
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct1.c
@@ -0,0 +1,121 @@
+/* Area:		ffi_call
+   Purpose:		Test passing struct in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator: ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static int
+test_fn (int n, ...)
+{
+  va_list ap;
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l;
+
+  va_start (ap, n);
+  s1 = va_arg (ap, struct small_tag);
+  l = va_arg (ap, struct large_tag);
+  s2 = va_arg (ap, struct small_tag);
+  printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+	  s2.a, s2.b);
+  va_end (ap);
+  return n + 1;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void* args[5];
+  ffi_type* arg_types[5];
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int n;
+  ffi_arg res;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint, arg_types) == FFI_OK);
+
+  s1.a = 5;
+  s1.b = 6;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  s2.a = 7;
+  s2.b = 8;
+
+  n = 41;
+
+  args[0] = &n;
+  args[1] = &s1;
+  args[2] = &l1;
+  args[3] = &s2;
+  args[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(test_fn), &res, args);
+  /* { dg-output "5 6 10 11 12 13 14 7 8" } */
+  printf("res: %d\n", (int) res);
+  /* { dg-output "\nres: 42" } */
+
+  return 0;
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct2.c
new file mode 100644
index 0000000..56f5b9c
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct2.c
@@ -0,0 +1,123 @@
+/* Area:		ffi_call
+   Purpose:		Test passing struct in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator: ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static struct small_tag
+test_fn (int n, ...)
+{
+  va_list ap;
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l;
+
+  va_start (ap, n);
+  s1 = va_arg (ap, struct small_tag);
+  l = va_arg (ap, struct large_tag);
+  s2 = va_arg (ap, struct small_tag);
+  printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+	  s2.a, s2.b);
+  va_end (ap);
+  s1.a += s2.a;
+  s1.b += s2.b;
+  return s1;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void* args[5];
+  ffi_type* arg_types[5];
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int n;
+  struct small_tag res;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &s_type, arg_types) == FFI_OK);
+
+  s1.a = 5;
+  s1.b = 6;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  s2.a = 7;
+  s2.b = 8;
+
+  n = 41;
+
+  args[0] = &n;
+  args[1] = &s1;
+  args[2] = &l1;
+  args[3] = &s2;
+  args[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(test_fn), &res, args);
+  /* { dg-output "5 6 10 11 12 13 14 7 8" } */
+  printf("res: %d %d\n", res.a, res.b);
+  /* { dg-output "\nres: 12 14" } */
+
+  return 0;
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct3.c b/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct3.c
new file mode 100644
index 0000000..9a27e7f
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct3.c
@@ -0,0 +1,125 @@
+/* Area:		ffi_call
+   Purpose:		Test passing struct in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator:	ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static struct large_tag
+test_fn (int n, ...)
+{
+  va_list ap;
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l;
+
+  va_start (ap, n);
+  s1 = va_arg (ap, struct small_tag);
+  l = va_arg (ap, struct large_tag);
+  s2 = va_arg (ap, struct small_tag);
+  printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+	  s2.a, s2.b);
+  va_end (ap);
+  l.a += s1.a;
+  l.b += s1.b;
+  l.c += s2.a;
+  l.d += s2.b;
+  return l;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void* args[5];
+  ffi_type* arg_types[5];
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int n;
+  struct large_tag res;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &l_type, arg_types) == FFI_OK);
+
+  s1.a = 5;
+  s1.b = 6;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  s2.a = 7;
+  s2.b = 8;
+
+  n = 41;
+
+  args[0] = &n;
+  args[1] = &s1;
+  args[2] = &l1;
+  args[3] = &s2;
+  args[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(test_fn), &res, args);
+  /* { dg-output "5 6 10 11 12 13 14 7 8" } */
+  printf("res: %d %d %d %d %d\n", res.a, res.b, res.c, res.d, res.e);
+  /* { dg-output "\nres: 15 17 19 21 14" } */
+
+  return 0;
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.special/ffitestcxx.h b/third_party/gofrontend/libffi/testsuite/libffi.special/ffitestcxx.h
new file mode 100644
index 0000000..83f5442
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.special/ffitestcxx.h
@@ -0,0 +1,96 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ffi.h>
+#include "fficonfig.h"
+
+#define MAX_ARGS 256
+
+
+/* Define __UNUSED__ that also other compilers than gcc can run the tests.  */
+#undef __UNUSED__
+#if defined(__GNUC__)
+#define __UNUSED__ __attribute__((__unused__))
+#else
+#define __UNUSED__
+#endif
+
+#define CHECK(x) (!(x) ? abort() : (void)0)
+
+/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
+   file open.  */
+#ifdef HAVE_MMAP_ANON
+# undef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
+#  define MAP_ANONYMOUS MAP_ANON
+# endif
+# define USING_MMAP
+
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+# define USING_MMAP
+
+#endif
+
+
+/* MinGW kludge.  */
+#ifdef _WIN64
+#define PRIdLL "I64d"
+#define PRIuLL "I64u"
+#else
+#define PRIdLL "lld"
+#define PRIuLL "llu"
+#endif
+
+#ifdef USING_MMAP
+static inline void *
+allocate_mmap (size_t size)
+{
+  void *page;
+#if defined (HAVE_MMAP_DEV_ZERO)
+  static int dev_zero_fd = -1;
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+  if (dev_zero_fd == -1)
+    {
+      dev_zero_fd = open ("/dev/zero", O_RDONLY);
+      if (dev_zero_fd == -1)
+	{
+	  perror ("open /dev/zero: %m");
+	  exit (1);
+	}
+    }
+#endif
+
+
+#ifdef HAVE_MMAP_ANON
+  page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+	       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#endif
+#ifdef HAVE_MMAP_DEV_ZERO
+  page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+	       MAP_PRIVATE, dev_zero_fd, 0);
+#endif
+
+  if (page == (char *) MAP_FAILED)
+    {
+      perror ("virtual memory exhausted");
+      exit (1);
+    }
+
+  return page;
+}
+
+#endif
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.special/unwindtest.cc b/third_party/gofrontend/libffi/testsuite/libffi.special/unwindtest.cc
new file mode 100644
index 0000000..d7ffd4a
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.special/unwindtest.cc
@@ -0,0 +1,124 @@
+/* Area:	ffi_closure, unwind info
+   Purpose:	Check if the unwind information is passed correctly.
+   Limitations:	none.
+   PR:		none.
+   Originator:	Jeff Sturm <jsturm@one-point.com>  */
+
+/* { dg-do run } */
+#include "ffitestcxx.h"
+
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#if defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+void
+closure_test_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+		void** args __UNUSED__, void* userdata __UNUSED__)
+{
+  throw 9;
+}
+
+typedef void (*closure_test_type)();
+
+void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp,
+		      void** args, void* userdata __UNUSED__)
+ {
+    *(ffi_arg*)resp =
+      (int)*(float *)args[0] +(int)(*(float *)args[1]) +
+      (int)(*(float *)args[2]) + (int)*(float *)args[3] +
+      (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) +
+      (int)*(float *)args[6] + (int)(*(int *)args[7]) +
+      (int)(*(double*)args[8]) + (int)*(int *)args[9] +
+      (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+      (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+      (int)(*(int *)args[14]) + *(int *)args[15] + (int)(intptr_t)userdata;
+
+    printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+	   (int)*(float *)args[0], (int)(*(float *)args[1]),
+	   (int)(*(float *)args[2]), (int)*(float *)args[3],
+	   (int)(*(signed short *)args[4]), (int)(*(float *)args[5]),
+	   (int)*(float *)args[6], (int)(*(int *)args[7]),
+	   (int)(*(double *)args[8]), (int)*(int *)args[9],
+	   (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+	   (int)*(int *)args[12], (int)(*(int *)args[13]),
+	   (int)(*(int *)args[14]), *(int *)args[15],
+	   (int)(intptr_t)userdata, (int)*(ffi_arg*)resp);
+
+    throw (int)*(ffi_arg*)resp;
+}
+
+typedef int (*closure_test_type1)(float, float, float, float, signed short,
+				  float, float, int, double, int, int, float,
+				  int, int, int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = (ffi_closure *)ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+
+  {
+    cl_arg_types[1] = NULL;
+
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0,
+		       &ffi_type_void, cl_arg_types) == FFI_OK);
+    CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn, NULL, code) == FFI_OK);
+
+    try
+      {
+	(*((closure_test_type)(code)))();
+      } catch (int exception_code)
+      {
+	CHECK(exception_code == 9);
+      }
+
+    printf("part one OK\n");
+    /* { dg-output "part one OK" } */
+    }
+
+    {
+
+      cl_arg_types[0] = &ffi_type_float;
+      cl_arg_types[1] = &ffi_type_float;
+      cl_arg_types[2] = &ffi_type_float;
+      cl_arg_types[3] = &ffi_type_float;
+      cl_arg_types[4] = &ffi_type_sshort;
+      cl_arg_types[5] = &ffi_type_float;
+      cl_arg_types[6] = &ffi_type_float;
+      cl_arg_types[7] = &ffi_type_uint;
+      cl_arg_types[8] = &ffi_type_double;
+      cl_arg_types[9] = &ffi_type_uint;
+      cl_arg_types[10] = &ffi_type_uint;
+      cl_arg_types[11] = &ffi_type_float;
+      cl_arg_types[12] = &ffi_type_uint;
+      cl_arg_types[13] = &ffi_type_uint;
+      cl_arg_types[14] = &ffi_type_uint;
+      cl_arg_types[15] = &ffi_type_uint;
+      cl_arg_types[16] = NULL;
+
+      /* Initialize the cif */
+      CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+			 &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+      CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn1,
+                                 (void *) 3 /* userdata */, code)  == FFI_OK);
+      try
+	{
+	  (*((closure_test_type1)code))
+	    (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13,
+	     19, 21, 1);
+	  /* { dg-output "\n1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */
+	} catch (int exception_code)
+	{
+	  CHECK(exception_code == 255);
+	}
+      printf("part two OK\n");
+      /* { dg-output "\npart two OK" } */
+    }
+    exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc b/third_party/gofrontend/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc
new file mode 100644
index 0000000..29739cd
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc
@@ -0,0 +1,53 @@
+/* Area:	ffi_call, unwind info
+   Purpose:	Check if the unwind information is passed correctly.
+   Limitations:	none.
+   PR:		none.
+   Originator:	Andreas Tobler <andreast@gcc.gnu.org> 20061213  */
+
+/* { dg-do run } */
+#include "ffitestcxx.h"
+
+static int checking(int a __UNUSED__, short b __UNUSED__,
+		    signed char c __UNUSED__)
+{
+  throw 9;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  signed int si;
+  signed short ss;
+  signed char sc;
+
+  args[0] = &ffi_type_sint;
+  values[0] = &si;
+  args[1] = &ffi_type_sshort;
+  values[1] = &ss;
+  args[2] = &ffi_type_schar;
+  values[2] = &sc;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &ffi_type_sint, args) == FFI_OK);
+
+  si = -6;
+  ss = -12;
+  sc = -1;
+  {
+    try
+      {
+	ffi_call(&cif, FFI_FN(checking), &rint, values);
+      } catch (int exception_code)
+      {
+	CHECK(exception_code == 9);
+      }
+    printf("part one OK\n");
+    /* { dg-output "part one OK" } */
+  }
+  exit(0);
+}
diff --git a/third_party/gofrontend/libgcc/unwind-pe.h b/third_party/gofrontend/libgcc/unwind-pe.h
new file mode 100644
index 0000000..a460d55
--- /dev/null
+++ b/third_party/gofrontend/libgcc/unwind-pe.h
@@ -0,0 +1,201 @@
+//===----------------------------- unwind-pe.h ----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+// Pointer-Encoding decoder. Derived from:
+//   - libcxxabi/src/Unwind/dwarf2.h
+//   - libcxxabi/src/Unwind/AddressSpace.h
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef UNWIND_PE_H
+#define UNWIND_PE_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+// FSF exception handling Pointer-Encoding constants
+// Used in CFI augmentation by GCC
+enum {
+  DW_EH_PE_ptr       = 0x00,
+  DW_EH_PE_uleb128   = 0x01,
+  DW_EH_PE_udata2    = 0x02,
+  DW_EH_PE_udata4    = 0x03,
+  DW_EH_PE_udata8    = 0x04,
+  DW_EH_PE_signed    = 0x08,
+  DW_EH_PE_sleb128   = 0x09,
+  DW_EH_PE_sdata2    = 0x0A,
+  DW_EH_PE_sdata4    = 0x0B,
+  DW_EH_PE_sdata8    = 0x0C,
+  DW_EH_PE_absptr    = 0x00,
+  DW_EH_PE_pcrel     = 0x10,
+  DW_EH_PE_textrel   = 0x20,
+  DW_EH_PE_datarel   = 0x30,
+  DW_EH_PE_funcrel   = 0x40,
+  DW_EH_PE_aligned   = 0x50,
+  DW_EH_PE_indirect  = 0x80,
+  DW_EH_PE_omit      = 0xFF
+};
+
+/// Read a ULEB128 into a 64-bit word.
+static uint64_t unw_getULEB128(uintptr_t *addr) {
+  const uint8_t *p = (uint8_t *)*addr;
+  uint64_t result = 0;
+  int bit = 0;
+  do {
+    uint64_t b;
+
+    b = *p & 0x7f;
+
+    if (bit >= 64 || b << bit >> bit != b) {
+      assert(!"malformed uleb128 expression");
+    } else {
+      result |= b << bit;
+      bit += 7;
+    }
+  } while (*p++ >= 0x80);
+  *addr = (uintptr_t) p;
+  return result;
+}
+
+/// Read a SLEB128 into a 64-bit word.
+static int64_t unw_getSLEB128(uintptr_t *addr) {
+  const uint8_t *p = (uint8_t *)addr;
+  int64_t result = 0;
+  int bit = 0;
+  uint8_t byte;
+  do {
+    byte = *p++;
+    result |= ((byte & 0x7f) << bit);
+    bit += 7;
+  } while (byte & 0x80);
+  // sign extend negative numbers
+  if ((byte & 0x40) != 0)
+    result |= (-1LL) << bit;
+  *addr = (uintptr_t) p;
+  return result;
+}
+
+static uint16_t unw_get16(uintptr_t addr) {
+  uint16_t val;
+  memcpy(&val, (void *)addr, sizeof(val));
+  return val;
+}
+
+static uint32_t unw_get32(uintptr_t addr) {
+  uint32_t val;
+  memcpy(&val, (void *)addr, sizeof(val));
+  return val;
+}
+
+static uint64_t unw_get64(uintptr_t addr) {
+  uint64_t val;
+  memcpy(&val, (void *)addr, sizeof(val));
+  return val;
+}
+
+static uintptr_t unw_getP(uintptr_t addr) {
+  if (sizeof(uintptr_t) == 8)
+    return unw_get64(addr);
+  else
+    return unw_get32(addr);
+}
+
+static const unsigned char *read_uleb128(const unsigned char *p,
+                                         _uleb128_t *ret) {
+  uintptr_t addr = (uintptr_t)p;
+  *ret = unw_getULEB128(&addr);
+  return (unsigned char *)addr;
+}
+
+static const unsigned char *read_encoded_value(struct _Unwind_Context *ctx,
+                                               unsigned char encoding,
+                                               const unsigned char *p,
+                                               _Unwind_Ptr *ret) {
+  uintptr_t addr = (uintptr_t)p;
+  uintptr_t startAddr = addr;
+  uintptr_t result;
+
+  (void)ctx;
+
+  // first get value
+  switch (encoding & 0x0F) {
+  case DW_EH_PE_ptr:
+    result = unw_getP(addr);
+    p += sizeof(uintptr_t);
+    break;
+  case DW_EH_PE_uleb128:
+    result = (uintptr_t)unw_getULEB128(&addr);
+    p = (const unsigned char *)addr;
+    break;
+  case DW_EH_PE_udata2:
+    result = unw_get16(addr);
+    p += 2;
+    break;
+  case DW_EH_PE_udata4:
+    result = unw_get32(addr);
+    p += 4;
+    break;
+  case DW_EH_PE_udata8:
+    result = (uintptr_t)unw_get64(addr);
+    p += 8;
+    break;
+  case DW_EH_PE_sleb128:
+    result = (uintptr_t)unw_getSLEB128(&addr);
+    p = (const unsigned char *)addr;
+    break;
+  case DW_EH_PE_sdata2:
+    // Sign extend from signed 16-bit value.
+    result = (uintptr_t)(int16_t)unw_get16(addr);
+    p += 2;
+    break;
+  case DW_EH_PE_sdata4:
+    // Sign extend from signed 32-bit value.
+    result = (uintptr_t)(int32_t)unw_get32(addr);
+    p += 4;
+    break;
+  case DW_EH_PE_sdata8:
+    result = (uintptr_t)unw_get64(addr);
+    p += 8;
+    break;
+  default:
+    assert(!"unknown pointer encoding");
+  }
+
+  // then add relative offset
+  switch (encoding & 0x70) {
+  case DW_EH_PE_absptr:
+    // do nothing
+    break;
+  case DW_EH_PE_pcrel:
+    result += startAddr;
+    break;
+  case DW_EH_PE_textrel:
+    assert(!"DW_EH_PE_textrel pointer encoding not supported");
+    break;
+  case DW_EH_PE_datarel:
+    assert(!"DW_EH_PE_datarel pointer encoding not supported");
+    break;
+  case DW_EH_PE_funcrel:
+    assert(!"DW_EH_PE_funcrel pointer encoding not supported");
+    break;
+  case DW_EH_PE_aligned:
+    assert(!"DW_EH_PE_aligned pointer encoding not supported");
+    break;
+  default:
+    assert(!"unknown pointer encoding");
+    break;
+  }
+
+  if (encoding & DW_EH_PE_indirect)
+    result = unw_getP(result);
+
+  *ret = result;
+  return p;
+}
+
+#endif  // UNWIND_PE_H
diff --git a/third_party/gofrontend/libgo/LICENSE b/third_party/gofrontend/libgo/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/third_party/gofrontend/libgo/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/gofrontend/libgo/MERGE b/third_party/gofrontend/libgo/MERGE
new file mode 100644
index 0000000..99d3367
--- /dev/null
+++ b/third_party/gofrontend/libgo/MERGE
@@ -0,0 +1,4 @@
+f44017549ff9
+
+The first line of this file holds the Mercurial revision number of the
+last merge done from the master library sources.
diff --git a/third_party/gofrontend/libgo/Makefile.am b/third_party/gofrontend/libgo/Makefile.am
new file mode 100644
index 0000000..c6ee01b
--- /dev/null
+++ b/third_party/gofrontend/libgo/Makefile.am
@@ -0,0 +1,3912 @@
+# Makefile.am -- Go library Makefile.
+
+# 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.
+
+# Process this file with autoreconf to produce Makefile.in.
+
+# Go support.
+SUFFIXES = .c .go .gox .o .obj .lo .a
+
+if LIBGO_IS_RTEMS
+subdirs = testsuite
+endif
+
+SUBDIRS = ${subdirs}
+
+gcc_version := $(shell $(GOC) -dumpversion)
+
+MAINT_CHARSET = latin1
+
+mkinstalldirs = $(SHELL) $(toplevel_srcdir)/mkinstalldirs
+PWD_COMMAND = $${PWDCMD-pwd}
+STAMP = echo timestamp >
+
+toolexecdir = $(glibgo_toolexecdir)
+toolexeclibdir = $(glibgo_toolexeclibdir)
+toolexeclibgodir = $(nover_glibgo_toolexeclibdir)/go/$(gcc_version)/$(target_alias)
+
+LIBFFI = @LIBFFI@
+LIBFFIINCS = @LIBFFIINCS@
+
+LIBATOMIC = @LIBATOMIC@
+
+WARN_CFLAGS = $(WARN_FLAGS) $(WERROR)
+
+# -I/-D flags to pass when compiling.
+AM_CPPFLAGS = -I $(srcdir)/runtime $(LIBFFIINCS) $(PTHREAD_CFLAGS)
+
+ACLOCAL_AMFLAGS = -I ./config -I ../config
+
+AM_CFLAGS = -fexceptions -fnon-call-exceptions -fplan9-extensions \
+	$(SPLIT_STACK) $(WARN_CFLAGS) \
+	$(STRINGOPS_FLAG) $(OSCFLAGS) \
+	-I $(srcdir)/../libgcc -I $(srcdir)/../libbacktrace \
+	-I $(MULTIBUILDTOP)../../gcc/include
+
+if USING_SPLIT_STACK
+AM_LDFLAGS = -XCClinker $(SPLIT_STACK)
+endif
+
+# Multilib support.
+MAKEOVERRIDES=
+
+# Work around what appears to be a GNU make  handling MAKEFLAGS
+# values defined in terms of make variables, as is the case for CC and
+# friends when we are called from the top level Makefile.
+AM_MAKEFLAGS = \
+	"AR_FLAGS=$(AR_FLAGS)" \
+	"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+	"CC_FOR_TARGET=$(CC_FOR_TARGET)" \
+	"CFLAGS=$(CFLAGS)" \
+	"CXXFLAGS=$(CXXFLAGS)" \
+	"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+	"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+	"GOC_FOR_TARGET=$(GOC_FOR_TARGET)" \
+	"GOC=$(GOC)" \
+	"GOCFLAGS=$(GOCFLAGS)" \
+	"INSTALL=$(INSTALL)" \
+	"INSTALL_DATA=$(INSTALL_DATA)" \
+	"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+	"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+	"LDFLAGS=$(LDFLAGS)" \
+	"LIBCFLAGS=$(LIBCFLAGS)" \
+	"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+	"MAKE=$(MAKE)" \
+	"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+	"PICFLAG=$(PICFLAG)" \
+	"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+	"SHELL=$(SHELL)" \
+	"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+	"exec_prefix=$(exec_prefix)" \
+	"infodir=$(infodir)" \
+	"libdir=$(libdir)" \
+	"includedir=$(includedir)" \
+	"prefix=$(prefix)" \
+	"tooldir=$(tooldir)" \
+	"gxx_include_dir=$(gxx_include_dir)" \
+	"AR=$(AR)" \
+	"AS=$(AS)" \
+	"LD=$(LD)" \
+	"RANLIB=$(RANLIB)" \
+	"NM=$(NM)" \
+	"NM_FOR_BUILD=$(NM_FOR_BUILD)" \
+	"NM_FOR_TARGET=$(NM_FOR_TARGET)" \
+	"DESTDIR=$(DESTDIR)" \
+	"WERROR=$(WERROR)"
+
+# Subdir rules rely on $(FLAGS_TO_PASS)
+FLAGS_TO_PASS = $(AM_MAKEFLAGS)
+
+if GOC_IS_LLGO
+toolexeclib_LTLIBRARIES = libgo-llgo.la
+toolexeclib_LIBRARIES = libgobegin-llgo.a
+else
+toolexeclib_LTLIBRARIES = libgo.la
+toolexeclib_LIBRARIES = libgobegin.a
+endif
+
+toolexeclibgo_DATA = \
+	bufio.gox \
+	bytes.gox \
+	crypto.gox \
+	encoding.gox \
+	errors.gox \
+	expvar.gox \
+	flag.gox \
+	fmt.gox \
+	hash.gox \
+	html.gox \
+	image.gox \
+	io.gox \
+	log.gox \
+	math.gox \
+	mime.gox \
+	net.gox \
+	os.gox \
+	path.gox \
+	reflect.gox \
+	regexp.gox \
+	runtime.gox \
+	sort.gox \
+	strconv.gox \
+	strings.gox \
+	sync.gox \
+	syscall.gox \
+	testing.gox \
+	time.gox \
+	unicode.gox
+
+toolexeclibgoarchivedir = $(toolexeclibgodir)/archive
+
+toolexeclibgoarchive_DATA = \
+	archive/tar.gox \
+	archive/zip.gox
+
+toolexeclibgocompressdir = $(toolexeclibgodir)/compress
+
+toolexeclibgocompress_DATA = \
+	compress/bzip2.gox \
+	compress/flate.gox \
+	compress/gzip.gox \
+	compress/lzw.gox \
+	compress/zlib.gox
+
+toolexeclibgocontainerdir = $(toolexeclibgodir)/container
+
+toolexeclibgocontainer_DATA = \
+	container/heap.gox \
+	container/list.gox \
+	container/ring.gox
+
+toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
+
+toolexeclibgocrypto_DATA = \
+	crypto/aes.gox \
+	crypto/cipher.gox \
+	crypto/des.gox \
+	crypto/dsa.gox \
+	crypto/ecdsa.gox \
+	crypto/elliptic.gox \
+	crypto/hmac.gox \
+	crypto/md5.gox \
+	crypto/rand.gox \
+	crypto/rc4.gox \
+	crypto/rsa.gox \
+	crypto/sha1.gox \
+	crypto/sha256.gox \
+	crypto/sha512.gox \
+	crypto/subtle.gox \
+	crypto/tls.gox \
+	crypto/x509.gox
+
+toolexeclibgocryptox509dir = $(toolexeclibgocryptodir)/x509
+
+toolexeclibgocryptox509_DATA = \
+	crypto/x509/pkix.gox
+
+toolexeclibgodatabasedir = $(toolexeclibgodir)/database
+
+toolexeclibgodatabase_DATA = \
+	database/sql.gox
+
+toolexeclibgodatabasesqldir = $(toolexeclibgodatabasedir)/sql
+
+toolexeclibgodatabasesql_DATA = \
+	database/sql/driver.gox
+
+toolexeclibgodebugdir = $(toolexeclibgodir)/debug
+
+toolexeclibgodebug_DATA = \
+	debug/dwarf.gox \
+	debug/elf.gox \
+	debug/gosym.gox \
+	debug/macho.gox \
+	debug/pe.gox \
+	debug/plan9obj.gox
+
+toolexeclibgoencodingdir = $(toolexeclibgodir)/encoding
+
+toolexeclibgoencoding_DATA = \
+	encoding/ascii85.gox \
+	encoding/asn1.gox \
+	encoding/base32.gox \
+	encoding/base64.gox \
+	encoding/binary.gox \
+	encoding/csv.gox \
+	encoding/gob.gox \
+	encoding/hex.gox \
+	encoding/json.gox \
+	encoding/pem.gox \
+	encoding/xml.gox
+
+toolexeclibgoexpdir = $(toolexeclibgodir)/exp
+
+toolexeclibgoexp_DATA = \
+	exp/proxy.gox \
+	exp/terminal.gox
+
+toolexeclibgogodir = $(toolexeclibgodir)/go
+
+toolexeclibgogo_DATA = \
+	go/ast.gox \
+	go/build.gox \
+	go/doc.gox \
+	go/format.gox \
+	go/parser.gox \
+	go/printer.gox \
+	go/scanner.gox \
+	go/token.gox
+
+toolexeclibgohashdir = $(toolexeclibgodir)/hash
+
+toolexeclibgohash_DATA = \
+	hash/adler32.gox \
+	hash/crc32.gox \
+	hash/crc64.gox \
+	hash/fnv.gox
+
+toolexeclibgohtmldir = $(toolexeclibgodir)/html
+
+toolexeclibgohtml_DATA = \
+	html/template.gox
+
+toolexeclibgoimagedir = $(toolexeclibgodir)/image
+
+toolexeclibgoimage_DATA = \
+	image/color.gox \
+	image/draw.gox \
+	image/gif.gox \
+	image/jpeg.gox \
+	image/png.gox
+
+toolexeclibgoimagecolordir = $(toolexeclibgoimagedir)/color
+
+toolexeclibgoimagecolor_DATA = \
+	image/color/palette.gox
+
+toolexeclibgoindexdir = $(toolexeclibgodir)/index
+
+toolexeclibgoindex_DATA = \
+	index/suffixarray.gox
+
+toolexeclibgoiodir = $(toolexeclibgodir)/io
+
+toolexeclibgoio_DATA = \
+	io/ioutil.gox
+
+toolexeclibgologdir = $(toolexeclibgodir)/log
+
+toolexeclibgolog_DATA = \
+	log/syslog.gox
+
+toolexeclibgomathdir = $(toolexeclibgodir)/math
+
+toolexeclibgomath_DATA = \
+	math/big.gox \
+	math/cmplx.gox \
+	math/rand.gox
+
+toolexeclibgomimedir = $(toolexeclibgodir)/mime
+
+toolexeclibgomime_DATA = \
+	mime/multipart.gox
+
+toolexeclibgonetdir = $(toolexeclibgodir)/net
+
+toolexeclibgonet_DATA = \
+	net/http.gox \
+	net/mail.gox \
+	net/rpc.gox \
+	net/smtp.gox \
+	net/textproto.gox \
+	net/url.gox
+
+toolexeclibgonethttpdir = $(toolexeclibgonetdir)/http
+
+toolexeclibgonethttp_DATA = \
+	net/http/cgi.gox \
+	net/http/cookiejar.gox \
+	net/http/fcgi.gox \
+	net/http/httptest.gox \
+	net/http/httputil.gox \
+	net/http/pprof.gox
+
+toolexeclibgonetrpcdir = $(toolexeclibgonetdir)/rpc
+
+toolexeclibgonetrpc_DATA = \
+	net/rpc/jsonrpc.gox
+
+toolexeclibgoolddir = $(toolexeclibgodir)/old
+
+toolexeclibgoold_DATA = \
+	old/regexp.gox \
+	old/template.gox
+
+toolexeclibgoosdir = $(toolexeclibgodir)/os
+
+toolexeclibgoos_DATA = \
+	os/exec.gox \
+	os/signal.gox \
+	os/user.gox
+
+toolexeclibgopathdir = $(toolexeclibgodir)/path
+
+toolexeclibgopath_DATA = \
+	path/filepath.gox
+
+toolexeclibgoregexpdir = $(toolexeclibgodir)/regexp
+
+toolexeclibgoregexp_DATA = \
+	regexp/syntax.gox
+
+toolexeclibgoruntimedir = $(toolexeclibgodir)/runtime
+
+toolexeclibgoruntime_DATA = \
+	runtime/debug.gox \
+	runtime/pprof.gox
+
+toolexeclibgosyncdir = $(toolexeclibgodir)/sync
+
+toolexeclibgosync_DATA = \
+	sync/atomic.gox
+
+toolexeclibgotestingdir = $(toolexeclibgodir)/testing
+
+toolexeclibgotesting_DATA = \
+	testing/iotest.gox \
+	testing/quick.gox
+
+toolexeclibgotextdir = $(toolexeclibgodir)/text
+
+toolexeclibgotext_DATA = \
+	text/scanner.gox \
+	text/tabwriter.gox \
+	text/template.gox
+
+toolexeclibgotexttemplatedir = $(toolexeclibgotextdir)/template
+
+toolexeclibgotexttemplate_DATA = \
+	text/template/parse.gox
+
+toolexeclibgounicodedir = $(toolexeclibgodir)/unicode
+
+toolexeclibgounicode_DATA = \
+	unicode/utf16.gox \
+	unicode/utf8.gox
+
+if HAVE_SYS_MMAN_H
+runtime_mem_file = runtime/mem.c
+else
+runtime_mem_file = runtime/mem_posix_memalign.c
+endif
+
+if LIBGO_IS_RTEMS
+rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
+else
+rtems_task_variable_add_file =
+endif
+
+if LIBGO_IS_LINUX
+runtime_lock_files = runtime/lock_futex.c runtime/thread-linux.c
+else
+runtime_lock_files = runtime/lock_sema.c runtime/thread-sema.c
+endif
+
+if LIBGO_IS_LINUX
+runtime_getncpu_file = runtime/getncpu-linux.c
+else
+if LIBGO_IS_DARWIN
+runtime_getncpu_file = runtime/getncpu-bsd.c
+else
+if LIBGO_IS_IRIX
+runtime_getncpu_file = runtime/getncpu-irix.c
+else
+if LIBGO_IS_SOLARIS
+runtime_getncpu_file = runtime/getncpu-solaris.c
+else
+if LIBGO_IS_FREEBSD
+runtime_getncpu_file = runtime/getncpu-bsd.c
+else
+if LIBGO_IS_NETBSD
+runtime_getncpu_file = runtime/getncpu-bsd.c
+else
+runtime_getncpu_file = runtime/getncpu-none.c
+endif
+endif
+endif
+endif
+endif
+endif
+
+if LIBGO_IS_LINUX
+runtime_netpoll_files = runtime/netpoll_epoll.c
+else
+if LIBGO_IS_SOLARIS
+runtime_netpoll_files = runtime/netpoll_select.c
+else
+runtime_netpoll_files = runtime/netpoll_kqueue.c
+endif
+endif
+
+runtime_files = \
+	runtime/go-append.c \
+	runtime/go-assert.c \
+	runtime/go-assert-interface.c \
+	runtime/go-byte-array-to-string.c \
+	runtime/go-breakpoint.c \
+	runtime/go-caller.c \
+	runtime/go-callers.c \
+	runtime/go-can-convert-interface.c \
+	runtime/go-cdiv.c \
+	runtime/go-cgo.c \
+	runtime/go-check-interface.c \
+	runtime/go-construct-map.c \
+	runtime/go-convert-interface.c \
+	runtime/go-copy.c \
+	runtime/go-defer.c \
+	runtime/go-deferred-recover.c \
+	runtime/go-eface-compare.c \
+	runtime/go-eface-val-compare.c \
+	runtime/go-ffi.c \
+	runtime/go-fieldtrack.c \
+	runtime/go-int-array-to-string.c \
+	runtime/go-int-to-string.c \
+	runtime/go-interface-compare.c \
+	runtime/go-interface-eface-compare.c \
+	runtime/go-interface-val-compare.c \
+	runtime/go-make-slice.c \
+	runtime/go-map-delete.c \
+	runtime/go-map-index.c \
+	runtime/go-map-len.c \
+	runtime/go-map-range.c \
+	runtime/go-matherr.c \
+	runtime/go-memcmp.c \
+	runtime/go-nanotime.c \
+	runtime/go-now.c \
+	runtime/go-new-map.c \
+	runtime/go-new.c \
+	runtime/go-nosys.c \
+	runtime/go-panic.c \
+	runtime/go-print.c \
+	runtime/go-recover.c \
+	runtime/go-reflect-call.c \
+	runtime/go-reflect-map.c \
+	runtime/go-rune.c \
+	runtime/go-runtime-error.c \
+	runtime/go-setenv.c \
+	runtime/go-signal.c \
+	runtime/go-strcmp.c \
+	runtime/go-string-to-byte-array.c \
+	runtime/go-string-to-int-array.c \
+	runtime/go-strplus.c \
+	runtime/go-strslice.c \
+	runtime/go-traceback.c \
+	runtime/go-type-complex.c \
+	runtime/go-type-eface.c \
+	runtime/go-type-error.c \
+	runtime/go-type-float.c \
+	runtime/go-type-identity.c \
+	runtime/go-type-interface.c \
+	runtime/go-type-string.c \
+	runtime/go-typedesc-equal.c \
+	runtime/go-unsafe-new.c \
+	runtime/go-unsafe-newarray.c \
+	runtime/go-unsafe-pointer.c \
+	runtime/go-unwind.c \
+	runtime/go-varargs.c \
+	runtime/env_posix.c \
+	runtime/heapdump.c \
+	$(runtime_lock_files) \
+	runtime/mcache.c \
+	runtime/mcentral.c \
+	$(runtime_mem_file) \
+	runtime/mfixalloc.c \
+	runtime/mgc0.c \
+	runtime/mheap.c \
+	runtime/msize.c \
+	$(runtime_netpoll_files) \
+	runtime/panic.c \
+	runtime/parfor.c \
+	runtime/print.c \
+	runtime/proc.c \
+	runtime/runtime.c \
+	runtime/signal_unix.c \
+	runtime/thread.c \
+	runtime/yield.c \
+	$(rtems_task_variable_add_file) \
+	chan.c \
+	cpuprof.c \
+	go-iface.c \
+	lfstack.c \
+	malloc.c \
+	map.c \
+	mprof.c \
+	netpoll.c \
+	rdebug.c \
+	reflect.c \
+	runtime1.c \
+	sema.c \
+	sigqueue.c \
+	string.c \
+	time.c \
+	$(runtime_getncpu_file)
+
+goc2c.$(OBJEXT): runtime/goc2c.c
+	$(CC_FOR_BUILD) -c $(CFLAGS_FOR_BUILD) $<
+
+goc2c: goc2c.$(OBJEXT)
+	$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $@ $<
+
+malloc.c: $(srcdir)/runtime/malloc.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+mprof.c: $(srcdir)/runtime/mprof.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+netpoll.c: $(srcdir)/runtime/netpoll.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+reflect.c: $(srcdir)/runtime/reflect.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+runtime1.c: $(srcdir)/runtime/runtime1.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+sema.c: $(srcdir)/runtime/sema.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+sigqueue.c: $(srcdir)/runtime/sigqueue.goc goc2c
+	./goc2c --go-pkgpath os_signal $< > $@.tmp
+	mv -f $@.tmp $@
+
+time.c: $(srcdir)/runtime/time.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+%.c: $(srcdir)/runtime/%.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+go_bufio_files = \
+	go/bufio/bufio.go \
+	go/bufio/scan.go
+
+go_bytes_files = \
+	go/bytes/buffer.go \
+	go/bytes/bytes.go \
+	go/bytes/bytes_decl.go \
+	go/bytes/reader.go
+go_bytes_c_files = \
+	go/bytes/indexbyte.c
+
+go_crypto_files = \
+	go/crypto/crypto.go
+
+go_encoding_files = \
+	go/encoding/encoding.go
+
+go_errors_files = \
+	go/errors/errors.go
+
+go_expvar_files = \
+	go/expvar/expvar.go
+
+go_flag_files = \
+	go/flag/flag.go
+
+go_fmt_files = \
+	go/fmt/doc.go \
+	go/fmt/format.go \
+	go/fmt/print.go \
+	go/fmt/scan.go
+
+go_hash_files = \
+	go/hash/hash.go
+
+go_html_files = \
+	go/html/entity.go \
+	go/html/escape.go
+
+go_image_files = \
+	go/image/format.go \
+	go/image/geom.go \
+	go/image/image.go \
+	go/image/names.go \
+	go/image/ycbcr.go
+
+go_io_files = \
+	go/io/multi.go \
+	go/io/io.go \
+	go/io/pipe.go
+
+go_log_files = \
+	go/log/log.go
+
+go_math_files = \
+	go/math/abs.go \
+	go/math/acosh.go \
+	go/math/asin.go \
+	go/math/asinh.go \
+	go/math/atan.go \
+	go/math/atanh.go \
+	go/math/atan2.go \
+	go/math/bits.go \
+	go/math/cbrt.go \
+	go/math/const.go \
+	go/math/copysign.go \
+	go/math/dim.go \
+	go/math/erf.go \
+	go/math/exp.go \
+	go/math/expm1.go \
+	go/math/floor.go \
+	go/math/frexp.go \
+	go/math/gamma.go \
+	go/math/hypot.go \
+	go/math/j0.go \
+	go/math/j1.go \
+	go/math/jn.go \
+	go/math/ldexp.go \
+	go/math/lgamma.go \
+	go/math/log.go \
+	go/math/log1p.go \
+	go/math/log10.go \
+	go/math/logb.go \
+	go/math/mod.go \
+	go/math/modf.go \
+	go/math/nextafter.go \
+	go/math/pow.go \
+	go/math/pow10.go \
+	go/math/remainder.go \
+	go/math/signbit.go \
+	go/math/sin.go \
+	go/math/sincos.go \
+	go/math/sinh.go \
+	go/math/sqrt.go \
+	go/math/tan.go \
+	go/math/tanh.go \
+	go/math/unsafe.go
+
+go_mime_files = \
+	go/mime/grammar.go \
+	go/mime/mediatype.go \
+	go/mime/type.go \
+	go/mime/type_unix.go
+
+if LIBGO_IS_LINUX
+go_net_cgo_file = go/net/cgo_linux.go
+go_net_sock_file = go/net/sock_linux.go
+go_net_sockopt_file = go/net/sockopt_linux.go
+go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
+else
+if LIBGO_IS_IRIX
+go_net_cgo_file = go/net/cgo_linux.go
+go_net_sock_file = go/net/sock_linux.go
+go_net_sockopt_file = go/net/sockopt_linux.go
+go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
+else
+if LIBGO_IS_SOLARIS
+go_net_cgo_file = go/net/cgo_linux.go
+go_net_sock_file = go/net/sock_solaris.go
+go_net_sockopt_file = go/net/sockopt_solaris.go
+go_net_sockoptip_file = go/net/sockoptip_stub.go
+else
+if LIBGO_IS_FREEBSD
+go_net_cgo_file = go/net/cgo_bsd.go
+go_net_sock_file = go/net/sock_bsd.go
+go_net_sockopt_file = go/net/sockopt_bsd.go
+go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
+else
+if LIBGO_IS_NETBSD
+go_net_cgo_file = go/net/cgo_netbsd.go
+go_net_sock_file = go/net/sock_bsd.go
+go_net_sockopt_file = go/net/sockopt_bsd.go
+go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
+else
+go_net_cgo_file = go/net/cgo_bsd.go
+go_net_sock_file = go/net/sock_bsd.go
+go_net_sockopt_file = go/net/sockopt_bsd.go
+go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
+endif
+endif
+endif
+endif
+endif
+
+if LIBGO_IS_LINUX
+go_net_sendfile_file = go/net/sendfile_linux.go
+else
+if LIBGO_IS_FREEBSD
+go_net_sendfile_file = go/net/sendfile_freebsd.go
+else
+if LIBGO_IS_DRAGONFLY
+go_net_sendfile_file = go/net/sendfile_dragonfly.go
+else
+go_net_sendfile_file = go/net/sendfile_stub.go
+endif
+endif
+endif
+
+if LIBGO_IS_LINUX
+go_net_interface_file = go/net/interface_linux.go
+else
+if LIBGO_IS_NETBSD
+go_net_interface_file = go/net/interface_netbsd.go
+else
+if LIBGO_IS_DRAGONFLY
+go_net_interface_file = go/net/interface_dragonfly.go
+else
+go_net_interface_file = go/net/interface_stub.go
+endif
+endif
+endif
+
+if LIBGO_IS_LINUX
+go_net_cloexec_file = go/net/sock_cloexec.go
+else
+go_net_cloexec_file = go/net/sys_cloexec.go
+endif
+
+if LIBGO_IS_OPENBSD
+go_net_tcpsockopt_file = go/net/tcpsockopt_openbsd.go
+else
+if LIBGO_IS_DARWIN
+go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go
+else
+if LIBGO_IS_SOLARIS
+go_net_tcpsockopt_file = go/net/tcpsockopt_solaris.go
+else
+if LIBGO_IS_DRAGONFLY
+go_net_tcpsockopt_file = go/net/tcpsockopt_dragonfly.go
+else
+go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go
+endif
+endif
+endif
+endif
+
+go_net_files = \
+	go/net/cgo_unix.go \
+	$(go_net_cgo_file) \
+	$(go_net_cloexec_file) \
+	go/net/dial.go \
+	go/net/dnsclient.go \
+	go/net/dnsclient_unix.go \
+	go/net/dnsconfig_unix.go \
+	go/net/dnsmsg.go \
+	go/net/fd_mutex.go \
+	go/net/fd_unix.go \
+	go/net/file_unix.go \
+	go/net/hosts.go \
+	go/net/interface.go \
+	$(go_net_interface_file) \
+	go/net/ip.go \
+	go/net/iprawsock.go \
+	go/net/iprawsock_posix.go \
+	go/net/ipsock.go \
+	go/net/ipsock_posix.go \
+	go/net/lookup.go \
+	go/net/lookup_unix.go \
+	go/net/mac.go \
+	go/net/net.go \
+	go/net/parse.go \
+	go/net/pipe.go \
+	go/net/fd_poll_runtime.go \
+	go/net/port.go \
+	go/net/port_unix.go \
+	go/net/race0.go \
+	$(go_net_sendfile_file) \
+	go/net/singleflight.go \
+	go/net/sock_posix.go \
+	$(go_net_sock_file) \
+	go/net/sockopt_posix.go \
+	$(go_net_sockopt_file) \
+	$(go_net_sockoptip_file) \
+	go/net/tcpsock.go \
+	go/net/tcpsock_posix.go \
+	go/net/tcpsockopt_posix.go \
+	$(go_net_tcpsockopt_file) \
+	go/net/udpsock.go \
+	go/net/udpsock_posix.go \
+	go/net/unixsock.go \
+	go/net/unixsock_posix.go
+
+if LIBGO_IS_SOLARIS
+if LIBGO_IS_386
+go_os_dir_file = go/os/dir_largefile.go
+else
+if LIBGO_IS_SPARC
+go_os_dir_file = go/os/dir_largefile.go
+else
+go_os_dir_file = go/os/dir_regfile.go
+endif
+endif
+else
+if LIBGO_IS_LINUX
+go_os_dir_file = go/os/dir_largefile.go
+else
+go_os_dir_file = go/os/dir_regfile.go
+endif
+endif
+
+if LIBGO_IS_DARWIN
+go_os_getwd_file = go/os/getwd_darwin.go
+else
+go_os_getwd_file =
+endif
+
+if LIBGO_IS_LINUX
+go_os_sys_file = go/os/sys_linux.go
+else
+if LIBGO_IS_SOLARIS
+go_os_sys_file = go/os/sys_uname.go
+else
+if LIBGO_IS_IRIX
+go_os_sys_file = go/os/sys_uname.go
+else
+if LIBGO_IS_RTEMS
+go_os_sys_file = go/os/sys_uname.go
+else
+go_os_sys_file = go/os/sys_bsd.go
+endif
+endif
+endif
+endif
+
+if LIBGO_IS_FREEBSD
+go_os_cloexec_file = go/os/sys_freebsd.go
+else
+if LIBGO_IS_DARWIN
+go_os_cloexec_file = go/os/sys_darwin.go
+else
+go_os_cloexec_file = go/os/sys_unix.go
+endif
+endif
+
+if LIBGO_IS_SOLARIS
+go_os_stat_file = go/os/stat_solaris.go
+else
+if LIBGO_IS_LINUX
+go_os_stat_file = go/os/stat_atim.go
+else
+if LIBGO_IS_OPENBSD
+go_os_stat_file = go/os/stat_atim.go
+else
+if LIBGO_IS_DARWIN
+go_os_stat_file = go/os/stat_atimespec.go
+else
+if LIBGO_IS_FREEBSD
+go_os_stat_file = go/os/stat_atimespec.go
+else
+if LIBGO_IS_NETBSD
+go_os_stat_file = go/os/stat_atimespec.go
+else
+if LIBGO_IS_DRAGONFLY
+go_os_stat_file = go/os/stat_dragonfly.go
+else
+go_os_stat_file = go/os/stat.go
+endif
+endif
+endif
+endif
+endif
+endif
+endif
+
+if LIBGO_IS_LINUX
+go_os_pipe_file = go/os/pipe_linux.go
+else
+go_os_pipe_file = go/os/pipe_bsd.go
+endif
+
+go_os_files = \
+	$(go_os_dir_file) \
+	go/os/dir.go \
+	go/os/doc.go \
+	go/os/env.go \
+	go/os/error.go \
+	go/os/error_unix.go \
+	go/os/exec.go \
+	go/os/exec_posix.go \
+	go/os/exec_unix.go \
+	go/os/file.go \
+	go/os/file_posix.go \
+	go/os/file_unix.go \
+	go/os/getwd.go \
+	$(go_os_getwd_file) \
+	go/os/path.go \
+	go/os/path_unix.go \
+	$(go_os_pipe_file) \
+	go/os/proc.go \
+	$(go_os_stat_file) \
+	go/os/str.go \
+	$(go_os_sys_file) \
+	$(go_os_cloexec_file) \
+	go/os/types.go \
+	go/os/types_notwin.go
+
+go_path_files = \
+	go/path/match.go \
+	go/path/path.go
+
+if LIBGO_IS_X86_64
+go_reflect_makefunc_file = \
+	go/reflect/makefuncgo_amd64.go
+go_reflect_makefunc_s_file = \
+	go/reflect/makefunc_amd64.S
+else
+if LIBGO_IS_386
+go_reflect_makefunc_file = \
+	go/reflect/makefuncgo_386.go
+go_reflect_makefunc_s_file = \
+	go/reflect/makefunc_386.S
+else
+if LIBGO_IS_S390
+go_reflect_makefunc_file = \
+	go/reflect/makefuncgo_s390.go
+go_reflect_makefunc_s_file = \
+	go/reflect/makefunc_s390.c
+else
+if LIBGO_IS_S390X
+go_reflect_makefunc_file = \
+	go/reflect/makefuncgo_s390x.go \
+	go/reflect/makefuncgo_s390.go
+go_reflect_makefunc_s_file = \
+	go/reflect/makefunc_s390.c
+else
+go_reflect_makefunc_file =
+go_reflect_makefunc_s_file = \
+	go/reflect/makefunc_dummy.c
+endif
+endif
+endif
+endif
+
+go_reflect_files = \
+	go/reflect/deepequal.go \
+	go/reflect/makefunc.go \
+	go/reflect/makefunc_ffi.go \
+	$(go_reflect_makefunc_file) \
+	go/reflect/type.go \
+	go/reflect/value.go
+go_reflect_makefunc_c_file = \
+	go/reflect/makefunc_ffi_c.c
+
+go_regexp_files = \
+	go/regexp/exec.go \
+	go/regexp/onepass.go \
+	go/regexp/regexp.go
+
+go_net_rpc_files = \
+	go/net/rpc/client.go \
+	go/net/rpc/debug.go \
+	go/net/rpc/server.go
+
+go_runtime_files = \
+	go/runtime/compiler.go \
+	go/runtime/debug.go \
+	go/runtime/error.go \
+	go/runtime/extern.go \
+	go/runtime/mem.go \
+	go/runtime/softfloat64.go \
+	go/runtime/type.go \
+	version.go
+
+version.go: s-version; @true
+s-version: Makefile
+	rm -f version.go.tmp
+	echo "package runtime" > version.go.tmp
+	echo 'const defaultGoroot = "$(prefix)"' >> version.go.tmp
+	echo 'const theVersion = "'`$(GOC) --version | sed 1q`'"' >> version.go.tmp
+	echo 'const theGoarch = "'$(GOARCH)'"' >> version.go.tmp
+	echo 'const theGoos = "'$(GOOS)'"' >> version.go.tmp
+	$(SHELL) $(srcdir)/../move-if-change version.go.tmp version.go
+	$(STAMP) $@
+
+go_sort_files = \
+	go/sort/search.go \
+	go/sort/sort.go
+
+go_strconv_files = \
+	go/strconv/atob.go \
+	go/strconv/atof.go \
+	go/strconv/atoi.go \
+	go/strconv/decimal.go \
+	go/strconv/extfloat.go \
+	go/strconv/ftoa.go \
+	go/strconv/isprint.go \
+	go/strconv/itoa.go \
+	go/strconv/quote.go
+
+go_strings_files = \
+	go/strings/reader.go \
+	go/strings/replace.go \
+	go/strings/search.go \
+	go/strings/strings.go \
+	go/strings/strings_decl.go
+go_strings_c_files = \
+	go/strings/indexbyte.c
+
+go_sync_files = \
+	go/sync/cond.go \
+	go/sync/mutex.go \
+	go/sync/once.go \
+	go/sync/pool.go \
+	go/sync/race0.go \
+	go/sync/runtime.go \
+	go/sync/rwmutex.go \
+	go/sync/waitgroup.go
+
+if LIBGO_IS_SOLARIS
+go_syslog_file = go/log/syslog/syslog_libc.go
+else
+if LIBGO_IS_IRIX
+go_syslog_file = go/log/syslog/syslog_libc.go
+else
+go_syslog_file = go/log/syslog/syslog_unix.go
+endif
+endif
+
+go_log_syslog_files = \
+	go/log/syslog/syslog.go \
+	$(go_syslog_file)
+go_syslog_c_files = \
+	go/log/syslog/syslog_c.c
+
+go_testing_files = \
+	go/testing/allocs.go \
+	go/testing/benchmark.go \
+	go/testing/cover.go \
+	go/testing/example.go \
+	go/testing/testing.go
+
+go_time_files = \
+	go/time/format.go \
+	go/time/sleep.go \
+	go/time/sys_unix.go \
+	go/time/tick.go \
+	go/time/time.go \
+	go/time/zoneinfo.go \
+	go/time/zoneinfo_read.go \
+	go/time/zoneinfo_unix.go
+
+go_unicode_files = \
+	go/unicode/casetables.go \
+	go/unicode/digit.go \
+	go/unicode/graphic.go \
+	go/unicode/letter.go \
+	go/unicode/tables.go
+
+if LIBGO_IS_LINUX
+archive_tar_atim_file = go/archive/tar/stat_atim.go
+endif
+if LIBGO_IS_OPENBSD
+archive_tar_atim_file = go/archive/tar/stat_atim.go
+endif
+if LIBGO_IS_SOLARIS
+archive_tar_atim_file = go/archive/tar/stat_atim.go
+endif
+if LIBGO_IS_DARWIN
+archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+endif
+if LIBGO_IS_FREEBSD
+archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+endif
+if LIBGO_IS_NETBSD
+archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+endif
+
+go_archive_tar_files = \
+	go/archive/tar/common.go \
+	go/archive/tar/reader.go \
+	go/archive/tar/stat_unix.go \
+	go/archive/tar/writer.go \
+	$(archive_tar_atim_file)
+
+go_archive_zip_files = \
+	go/archive/zip/reader.go \
+	go/archive/zip/register.go \
+	go/archive/zip/struct.go \
+	go/archive/zip/writer.go
+
+go_compress_bzip2_files = \
+	go/compress/bzip2/bit_reader.go \
+	go/compress/bzip2/bzip2.go \
+	go/compress/bzip2/huffman.go \
+	go/compress/bzip2/move_to_front.go
+
+go_compress_flate_files = \
+	go/compress/flate/copy.go \
+	go/compress/flate/deflate.go \
+	go/compress/flate/fixedhuff.go \
+	go/compress/flate/huffman_bit_writer.go \
+	go/compress/flate/huffman_code.go \
+	go/compress/flate/inflate.go \
+	go/compress/flate/reverse_bits.go \
+	go/compress/flate/token.go
+
+go_compress_gzip_files = \
+	go/compress/gzip/gzip.go \
+	go/compress/gzip/gunzip.go
+
+go_compress_lzw_files = \
+	go/compress/lzw/reader.go \
+	go/compress/lzw/writer.go
+
+go_compress_zlib_files = \
+	go/compress/zlib/reader.go \
+	go/compress/zlib/writer.go
+
+go_container_heap_files = \
+	go/container/heap/heap.go
+
+go_container_list_files = \
+	go/container/list/list.go
+
+go_container_ring_files = \
+	go/container/ring/ring.go
+
+go_crypto_aes_files = \
+	go/crypto/aes/block.go \
+	go/crypto/aes/cipher.go \
+	go/crypto/aes/cipher_generic.go \
+	go/crypto/aes/const.go
+go_crypto_cipher_files = \
+	go/crypto/cipher/cbc.go \
+	go/crypto/cipher/cfb.go \
+	go/crypto/cipher/cipher.go \
+	go/crypto/cipher/ctr.go \
+	go/crypto/cipher/gcm.go \
+	go/crypto/cipher/io.go \
+	go/crypto/cipher/ofb.go \
+	go/crypto/cipher/xor.go
+go_crypto_des_files = \
+	go/crypto/des/block.go \
+	go/crypto/des/cipher.go \
+	go/crypto/des/const.go
+go_crypto_dsa_files = \
+	go/crypto/dsa/dsa.go
+go_crypto_ecdsa_files = \
+	go/crypto/ecdsa/ecdsa.go
+go_crypto_elliptic_files = \
+	go/crypto/elliptic/elliptic.go \
+	go/crypto/elliptic/p224.go \
+	go/crypto/elliptic/p256.go
+go_crypto_hmac_files = \
+	go/crypto/hmac/hmac.go
+go_crypto_md5_files = \
+	go/crypto/md5/md5.go \
+	go/crypto/md5/md5block.go \
+	go/crypto/md5/md5block_generic.go
+go_crypto_rand_files = \
+	go/crypto/rand/rand.go \
+	go/crypto/rand/rand_unix.go \
+	go/crypto/rand/util.go
+go_crypto_rc4_files = \
+	go/crypto/rc4/rc4.go \
+	go/crypto/rc4/rc4_ref.go
+go_crypto_rsa_files = \
+	go/crypto/rsa/pkcs1v15.go \
+	go/crypto/rsa/pss.go \
+	go/crypto/rsa/rsa.go
+go_crypto_sha1_files = \
+	go/crypto/sha1/sha1.go \
+	go/crypto/sha1/sha1block.go \
+	go/crypto/sha1/sha1block_generic.go
+go_crypto_sha256_files = \
+	go/crypto/sha256/sha256.go \
+	go/crypto/sha256/sha256block.go
+go_crypto_sha512_files = \
+	go/crypto/sha512/sha512.go \
+	go/crypto/sha512/sha512block.go
+go_crypto_subtle_files = \
+	go/crypto/subtle/constant_time.go
+go_crypto_tls_files = \
+	go/crypto/tls/alert.go \
+	go/crypto/tls/cipher_suites.go \
+	go/crypto/tls/common.go \
+	go/crypto/tls/conn.go \
+	go/crypto/tls/handshake_client.go \
+	go/crypto/tls/handshake_messages.go \
+	go/crypto/tls/handshake_server.go \
+	go/crypto/tls/key_agreement.go \
+	go/crypto/tls/prf.go \
+	go/crypto/tls/ticket.go \
+	go/crypto/tls/tls.go
+go_crypto_x509_files = \
+	go/crypto/x509/cert_pool.go \
+	go/crypto/x509/pem_decrypt.go \
+	go/crypto/x509/pkcs1.go \
+	go/crypto/x509/pkcs8.go \
+	go/crypto/x509/root.go \
+	go/crypto/x509/root_unix.go \
+	go/crypto/x509/sec1.go \
+	go/crypto/x509/verify.go \
+	go/crypto/x509/x509.go
+
+go_crypto_x509_pkix_files = \
+	go/crypto/x509/pkix/pkix.go
+
+go_database_sql_files = \
+	go/database/sql/convert.go \
+	go/database/sql/sql.go
+
+go_database_sql_driver_files = \
+	go/database/sql/driver/driver.go \
+	go/database/sql/driver/types.go
+
+go_debug_dwarf_files = \
+	go/debug/dwarf/buf.go \
+	go/debug/dwarf/const.go \
+	go/debug/dwarf/entry.go \
+	go/debug/dwarf/line.go \
+	go/debug/dwarf/open.go \
+	go/debug/dwarf/type.go \
+	go/debug/dwarf/typeunit.go \
+	go/debug/dwarf/unit.go
+go_debug_elf_files = \
+	go/debug/elf/elf.go \
+	go/debug/elf/file.go
+go_debug_gosym_files = \
+	go/debug/gosym/pclntab.go \
+	go/debug/gosym/symtab.go
+go_debug_macho_files = \
+	go/debug/macho/fat.go \
+	go/debug/macho/file.go \
+	go/debug/macho/macho.go
+go_debug_pe_files = \
+	go/debug/pe/file.go \
+	go/debug/pe/pe.go
+go_debug_plan9obj_files = \
+	go/debug/plan9obj/file.go \
+	go/debug/plan9obj/plan9obj.go
+
+go_encoding_ascii85_files = \
+	go/encoding/ascii85/ascii85.go
+go_encoding_asn1_files = \
+	go/encoding/asn1/asn1.go \
+	go/encoding/asn1/common.go \
+	go/encoding/asn1/marshal.go
+go_encoding_base32_files = \
+	go/encoding/base32/base32.go
+go_encoding_base64_files = \
+	go/encoding/base64/base64.go
+go_encoding_binary_files = \
+	go/encoding/binary/binary.go \
+	go/encoding/binary/varint.go
+go_encoding_csv_files = \
+	go/encoding/csv/reader.go \
+	go/encoding/csv/writer.go
+go_encoding_gob_files = \
+	go/encoding/gob/decode.go \
+	go/encoding/gob/decoder.go \
+	go/encoding/gob/doc.go \
+	go/encoding/gob/encode.go \
+	go/encoding/gob/encoder.go \
+	go/encoding/gob/error.go \
+	go/encoding/gob/type.go
+go_encoding_hex_files = \
+	go/encoding/hex/hex.go
+go_encoding_json_files = \
+	go/encoding/json/decode.go \
+	go/encoding/json/encode.go \
+	go/encoding/json/fold.go \
+	go/encoding/json/indent.go \
+	go/encoding/json/scanner.go \
+	go/encoding/json/stream.go \
+	go/encoding/json/tags.go
+go_encoding_pem_files = \
+	go/encoding/pem/pem.go
+go_encoding_xml_files = \
+	go/encoding/xml/marshal.go \
+	go/encoding/xml/read.go \
+	go/encoding/xml/typeinfo.go \
+	go/encoding/xml/xml.go
+
+go_exp_proxy_files = \
+	go/exp/proxy/direct.go \
+	go/exp/proxy/per_host.go \
+	go/exp/proxy/proxy.go \
+	go/exp/proxy/socks5.go
+go_exp_terminal_files = \
+	go/exp/terminal/terminal.go \
+	go/exp/terminal/util.go
+
+go_go_ast_files = \
+	go/go/ast/ast.go \
+	go/go/ast/commentmap.go \
+	go/go/ast/filter.go \
+	go/go/ast/import.go \
+	go/go/ast/print.go \
+	go/go/ast/resolve.go \
+	go/go/ast/scope.go \
+	go/go/ast/walk.go
+go_go_build_files = \
+	go/go/build/build.go \
+	go/go/build/doc.go \
+	go/go/build/read.go \
+	go/go/build/syslist.go
+go_go_doc_files = \
+	go/go/doc/comment.go \
+	go/go/doc/doc.go \
+	go/go/doc/example.go \
+	go/go/doc/exports.go \
+	go/go/doc/filter.go \
+	go/go/doc/reader.go \
+	go/go/doc/synopsis.go
+go_go_format_files = \
+	go/go/format/format.go
+go_go_parser_files = \
+	go/go/parser/interface.go \
+	go/go/parser/parser.go
+go_go_printer_files = \
+	go/go/printer/nodes.go \
+	go/go/printer/printer.go
+go_go_scanner_files = \
+	go/go/scanner/errors.go \
+	go/go/scanner/scanner.go
+go_go_token_files = \
+	go/go/token/position.go \
+	go/go/token/serialize.go \
+	go/go/token/token.go
+
+go_hash_adler32_files = \
+	go/hash/adler32/adler32.go
+go_hash_crc32_files = \
+	go/hash/crc32/crc32.go \
+	go/hash/crc32/crc32_generic.go
+go_hash_crc64_files = \
+	go/hash/crc64/crc64.go
+go_hash_fnv_files = \
+	go/hash/fnv/fnv.go
+
+go_html_template_files = \
+	go/html/template/attr.go \
+	go/html/template/content.go \
+	go/html/template/context.go \
+	go/html/template/css.go \
+	go/html/template/doc.go \
+	go/html/template/error.go \
+	go/html/template/escape.go \
+	go/html/template/html.go \
+	go/html/template/js.go \
+	go/html/template/template.go \
+	go/html/template/transition.go \
+	go/html/template/url.go
+
+go_image_color_files = \
+	go/image/color/color.go \
+	go/image/color/ycbcr.go
+
+go_image_color_palette_files = \
+	go/image/color/palette/palette.go
+
+go_image_draw_files = \
+	go/image/draw/draw.go
+
+go_image_gif_files = \
+	go/image/gif/reader.go \
+	go/image/gif/writer.go
+
+go_image_jpeg_files = \
+	go/image/jpeg/fdct.go \
+	go/image/jpeg/huffman.go \
+	go/image/jpeg/idct.go \
+	go/image/jpeg/reader.go \
+	go/image/jpeg/scan.go \
+	go/image/jpeg/writer.go
+
+go_image_png_files = \
+	go/image/png/paeth.go \
+	go/image/png/reader.go \
+	go/image/png/writer.go
+
+go_index_suffixarray_files = \
+	go/index/suffixarray/qsufsort.go \
+	go/index/suffixarray/suffixarray.go
+
+go_io_ioutil_files = \
+	go/io/ioutil/ioutil.go \
+	go/io/ioutil/tempfile.go
+
+go_math_big_files = \
+	go/math/big/arith.go \
+	go/math/big/int.go \
+	go/math/big/nat.go \
+	go/math/big/rat.go
+go_math_cmplx_files = \
+	go/math/cmplx/abs.go \
+	go/math/cmplx/asin.go \
+	go/math/cmplx/conj.go \
+	go/math/cmplx/exp.go \
+	go/math/cmplx/isinf.go \
+	go/math/cmplx/isnan.go \
+	go/math/cmplx/log.go \
+	go/math/cmplx/phase.go \
+	go/math/cmplx/polar.go \
+	go/math/cmplx/pow.go \
+	go/math/cmplx/rect.go \
+	go/math/cmplx/sin.go \
+	go/math/cmplx/sqrt.go \
+	go/math/cmplx/tan.go
+go_math_rand_files = \
+	go/math/rand/exp.go \
+	go/math/rand/normal.go \
+	go/math/rand/rand.go \
+	go/math/rand/rng.go \
+	go/math/rand/zipf.go
+
+go_mime_multipart_files = \
+	go/mime/multipart/formdata.go \
+	go/mime/multipart/multipart.go \
+	go/mime/multipart/quotedprintable.go \
+	go/mime/multipart/writer.go
+
+go_net_http_files = \
+	go/net/http/chunked.go \
+	go/net/http/client.go \
+	go/net/http/cookie.go \
+	go/net/http/filetransport.go \
+	go/net/http/fs.go \
+	go/net/http/header.go \
+	go/net/http/jar.go \
+	go/net/http/lex.go \
+	go/net/http/request.go \
+	go/net/http/response.go \
+	go/net/http/server.go \
+	go/net/http/sniff.go \
+	go/net/http/status.go \
+	go/net/http/transfer.go \
+	go/net/http/transport.go
+go_net_mail_files = \
+	go/net/mail/message.go
+go_net_smtp_files = \
+	go/net/smtp/auth.go \
+	go/net/smtp/smtp.go
+go_net_textproto_files = \
+	go/net/textproto/header.go \
+	go/net/textproto/pipeline.go \
+	go/net/textproto/reader.go \
+	go/net/textproto/textproto.go \
+	go/net/textproto/writer.go
+go_net_url_files = \
+	go/net/url/url.go
+
+go_net_http_cgi_files = \
+	go/net/http/cgi/child.go \
+	go/net/http/cgi/host.go
+go_net_http_cookiejar_files = \
+	go/net/http/cookiejar/jar.go \
+	go/net/http/cookiejar/punycode.go
+go_net_http_fcgi_files = \
+	go/net/http/fcgi/child.go \
+	go/net/http/fcgi/fcgi.go
+go_net_http_httptest_files = \
+	go/net/http/httptest/recorder.go \
+	go/net/http/httptest/server.go
+go_net_http_pprof_files = \
+	go/net/http/pprof/pprof.go
+go_net_http_httputil_files = \
+	go/net/http/httputil/chunked.go \
+	go/net/http/httputil/dump.go \
+	go/net/http/httputil/httputil.go \
+	go/net/http/httputil/persist.go \
+	go/net/http/httputil/reverseproxy.go
+
+
+go_old_regexp_files = \
+	go/old/regexp/regexp.go
+go_old_template_files = \
+	go/old/template/doc.go \
+	go/old/template/execute.go \
+	go/old/template/format.go \
+	go/old/template/parse.go
+
+go_os_exec_files = \
+	go/os/exec/exec.go \
+	go/os/exec/lp_unix.go
+
+go_os_signal_files = \
+	go/os/signal/signal.go \
+	go/os/signal/signal_unix.go
+
+if LIBGO_IS_SOLARIS
+os_user_decls_file = go/os/user/decls_solaris.go
+else
+os_user_decls_file = go/os/user/decls_unix.go
+endif
+
+go_os_user_files = \
+	go/os/user/lookup.go \
+	go/os/user/lookup_unix.go \
+	go/os/user/user.go \
+	$(os_user_decls_file)
+
+go_path_filepath_files = \
+	go/path/filepath/match.go \
+	go/path/filepath/path.go \
+	go/path/filepath/path_unix.go \
+	go/path/filepath/symlink.go
+
+go_regexp_syntax_files = \
+	go/regexp/syntax/compile.go \
+	go/regexp/syntax/doc.go \
+	go/regexp/syntax/parse.go \
+	go/regexp/syntax/perl_groups.go \
+	go/regexp/syntax/prog.go \
+	go/regexp/syntax/regexp.go \
+	go/regexp/syntax/simplify.go
+
+go_net_rpc_jsonrpc_files = \
+	go/net/rpc/jsonrpc/client.go \
+	go/net/rpc/jsonrpc/server.go
+
+go_runtime_debug_files = \
+	go/runtime/debug/garbage.go \
+	go/runtime/debug/stack.go
+go_runtime_pprof_files = \
+	go/runtime/pprof/pprof.go
+
+go_text_tabwriter_files = \
+	go/text/tabwriter/tabwriter.go
+go_text_template_files = \
+	go/text/template/doc.go \
+	go/text/template/exec.go \
+	go/text/template/funcs.go \
+	go/text/template/helper.go \
+	go/text/template/template.go
+go_text_template_parse_files = \
+	go/text/template/parse/lex.go \
+	go/text/template/parse/node.go \
+	go/text/template/parse/parse.go
+
+go_sync_atomic_files = \
+	go/sync/atomic/doc.go
+go_sync_atomic_c_files = \
+	go/sync/atomic/atomic.c
+
+go_testing_iotest_files = \
+	go/testing/iotest/logger.go \
+	go/testing/iotest/reader.go \
+	go/testing/iotest/writer.go
+go_testing_quick_files = \
+	go/testing/quick/quick.go
+
+go_text_scanner_files = \
+	go/text/scanner/scanner.go
+
+go_unicode_utf16_files = \
+	go/unicode/utf16/utf16.go
+go_unicode_utf8_files = \
+	go/unicode/utf8/utf8.go
+
+# Define Syscall and Syscall6.
+if LIBGO_IS_RTEMS
+syscall_syscall_file = go/syscall/syscall_stubs.go
+else
+syscall_syscall_file = go/syscall/syscall_unix.go
+endif
+
+# Define ForkExec and Exec.
+if LIBGO_IS_RTEMS
+syscall_exec_file = go/syscall/exec_stubs.go
+syscall_exec_os_file =
+else
+if LIBGO_IS_LINUX
+syscall_exec_file = go/syscall/exec_unix.go
+syscall_exec_os_file = go/syscall/exec_linux.go
+else
+syscall_exec_file = go/syscall/exec_unix.go
+syscall_exec_os_file = go/syscall/exec_bsd.go
+endif
+endif
+
+# Define Wait4.
+if LIBGO_IS_RTEMS
+syscall_wait_file =
+else
+if HAVE_WAIT4
+syscall_wait_file = go/syscall/libcall_wait4.go
+else
+syscall_wait_file = go/syscall/libcall_waitpid.go
+endif
+endif
+
+# Support for pulling apart wait status.
+if LIBGO_IS_RTEMS
+syscall_wait_c_file =
+else
+syscall_wait_c_file = go/syscall/wait.c
+endif
+
+# Define Sleep.
+if LIBGO_IS_RTEMS
+syscall_sleep_file = go/syscall/sleep_rtems.go
+else
+syscall_sleep_file = go/syscall/sleep_select.go
+endif
+
+# Define Errstr.
+if LIBGO_IS_LINUX
+syscall_errstr_file = go/syscall/errstr_linux.go
+else
+if LIBGO_IS_RTEMS
+syscall_errstr_file = go/syscall/errstr_linux.go
+else
+if HAVE_STRERROR_R
+syscall_errstr_file = go/syscall/errstr.go
+else
+syscall_errstr_file = go/syscall/errstr_nor.go
+endif
+endif
+endif
+
+# Declare libc functions that vary for largefile systems.
+if LIBGO_IS_LINUX
+# Always use lseek64 on GNU/Linux.
+syscall_size_file = go/syscall/libcall_posix_largefile.go
+else # !LIBGO_IS_LINUX
+if LIBGO_IS_SOLARIS
+if LIBGO_IS_386
+# Use lseek64 on 32-bit Solaris/x86.
+syscall_size_file = go/syscall/libcall_posix_largefile.go
+else # !LIBGO_IS_386
+if LIBGO_IS_SPARC
+# Use lseek64 on 32-bit Solaris/SPARC.
+syscall_size_file = go/syscall/libcall_posix_largefile.go
+else # !LIBGO_IS_386 && !LIBGO_IS_SPARC
+# Use lseek on 64-bit Solaris.
+syscall_size_file = go/syscall/libcall_posix_regfile.go
+endif # !LIBGO_IS_386 && !LIBGO_IS_SPARC
+endif # !LIBGO_IS_SOLARIS
+else # !LIBGO_IS_LINUX && !LIBGO_IS_SOLARIS
+# Use lseek by default.
+syscall_size_file = go/syscall/libcall_posix_regfile.go
+endif # !LIBGO_IS_SOLARIS
+endif # !LIBGO_IS_LINUX
+
+# Define socket sizes and types.
+if LIBGO_IS_LINUX
+syscall_socket_file = go/syscall/socket_linux.go epoll.go
+else
+if LIBGO_IS_SOLARIS
+syscall_socket_file = go/syscall/socket_solaris.go
+else
+if LIBGO_IS_IRIX
+syscall_socket_file = go/syscall/socket_irix.go
+else
+syscall_socket_file = go/syscall/socket_bsd.go
+endif
+endif
+endif
+
+# Define socket functions.
+if LIBGO_IS_SOLARIS
+syscall_socket_os_file = go/syscall/socket_xnet.go
+else
+syscall_socket_os_file = go/syscall/socket_posix.go
+endif
+
+# Support for uname.
+if LIBGO_IS_SOLARIS
+if LIBGO_IS_386
+# 32-bit Solaris 2/x86 needs _nuname, handled in libcall_solaris_386.go.
+syscall_uname_file =
+else # !LIBGO_IS_386 && LIBGO_IS_SOLARIS
+syscall_uname_file = go/syscall/libcall_uname.go
+endif
+else # !LIBGO_IS_SOLARIS
+syscall_uname_file = go/syscall/libcall_uname.go
+endif
+
+# GNU/Linux specific socket control messages.
+if LIBGO_IS_LINUX
+syscall_sockcmsg_file = go/syscall/sockcmsg_linux.go
+else
+syscall_sockcmsg_file =
+endif
+
+# Support for netlink sockets and messages.
+if LIBGO_IS_LINUX
+syscall_netlink_file = go/syscall/netlink_linux.go
+else
+syscall_netlink_file =
+endif
+
+# GNU/Linux specific socket filters.
+if LIBGO_IS_LINUX
+syscall_lsf_file = go/syscall/lsf_linux.go
+else
+syscall_lsf_file =
+endif
+
+# GNU/Linux specific utimesnano support.
+if LIBGO_IS_LINUX
+syscall_utimesnano_file = go/syscall/libcall_linux_utimesnano.go
+else
+syscall_utimesnano_file = go/syscall/libcall_posix_utimesnano.go
+endif
+
+# Test files.
+if LIBGO_IS_LINUX
+syscall_creds_test_file = go/syscall/creds_test.go
+else
+syscall_creds_test_file =
+endif
+
+go_base_syscall_files = \
+	go/syscall/env_unix.go \
+	go/syscall/syscall_errno.go \
+	go/syscall/libcall_support.go \
+	go/syscall/libcall_posix.go \
+	go/syscall/race0.go \
+	go/syscall/socket.go \
+	go/syscall/sockcmsg_unix.go \
+	go/syscall/str.go \
+	go/syscall/syscall.go \
+	$(syscall_sockcmsg_file) \
+	$(syscall_syscall_file) \
+	$(syscall_exec_file) \
+	$(syscall_exec_os_file) \
+	$(syscall_wait_file) \
+	$(syscall_sleep_file) \
+	$(syscall_errstr_file) \
+	$(syscall_size_file) \
+	$(syscall_socket_file) \
+	$(syscall_socket_os_file) \
+	$(syscall_uname_file) \
+	$(syscall_netlink_file) \
+	$(syscall_lsf_file) \
+	$(syscall_utimesnano_file) \
+	$(GO_LIBCALL_OS_FILE) \
+	$(GO_LIBCALL_OS_ARCH_FILE) \
+	$(GO_SYSCALL_OS_FILE) \
+	$(GO_SYSCALL_OS_ARCH_FILE)
+
+go_syscall_files = \
+	$(go_base_syscall_files) \
+	libcalls.go \
+	sysinfo.go \
+	syscall_arch.go
+go_syscall_c_files = \
+	go/syscall/errno.c \
+	go/syscall/signame.c \
+	$(syscall_wait_c_file)
+
+go_syscall_test_files = \
+	$(syscall_creds_test_file) \
+	go/syscall/mmap_unix_test.go \
+	go/syscall/syscall_test.go \
+	go/syscall/syscall_unix_test.go
+
+libcalls.go: s-libcalls; @true
+s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files)
+	rm -f libcalls.go.tmp
+	files=`echo $^ | sed -e 's/libcalls-list//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \
+	$(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp
+	$(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go
+	$(STAMP) $@
+
+libcalls-list: s-libcalls-list; @true
+s-libcalls-list: Makefile
+	rm -f libcalls-list.tmp
+	echo $(go_base_syscall_files) > libcalls-list.tmp
+	$(SHELL) $(srcdir)/../move-if-change libcalls-list.tmp libcalls-list
+	$(STAMP) $@
+
+syscall_arch.go: s-syscall_arch; @true
+s-syscall_arch: Makefile
+	rm -f syscall_arch.go.tmp
+	echo "package syscall" > syscall_arch.go.tmp
+	echo 'const ARCH = "'$(GOARCH)'"' >> syscall_arch.go.tmp
+	echo 'const OS = "'$(GOOS)'"' >> syscall_arch.go.tmp
+	$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
+	$(STAMP) $@
+
+sysinfo.go: s-sysinfo; @true
+s-sysinfo: $(srcdir)/mksysinfo.sh config.h
+	CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
+	$(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
+	$(STAMP) $@
+
+# The epoll struct has an embedded union and is packed on x86_64,
+# which is too complicated for mksysinfo.sh.  We find the offset of
+# the only field we care about in configure.ac, and generate the
+# struct here.
+epoll.go: s-epoll; @true
+s-epoll: Makefile
+	rm -f epoll.go.tmp
+	echo 'package syscall' > epoll.go.tmp
+	echo 'type EpollEvent struct {' >> epoll.go.tmp
+	echo '	Events uint32' >> epoll.go.tmp
+	case "$(SIZEOF_STRUCT_EPOLL_EVENT),$(STRUCT_EPOLL_EVENT_FD_OFFSET)" in \
+	0,0) echo 1>&2 "*** struct epoll_event data.fd offset unknown"; \
+	   exit 1; ;; \
+	8,4) echo '	Fd int32' >> epoll.go.tmp; ;; \
+	12,4) echo '	Fd int32' >> epoll.go.tmp; \
+	   echo '	Pad [4]byte' >> epoll.go.tmp; ;; \
+	12,8) echo '	Pad [4]byte' >> epoll.go.tmp; \
+	   echo '	Fd int32' >> epoll.go.tmp; ;; \
+	16,8) echo '	Pad [4]byte' >> epoll.go.tmp; \
+	   echo '	Fd int32' >> epoll.go.tmp; \
+	   echo '	Pad2 [4]byte' >> epoll.go.tmp; ;; \
+	*) echo 1>&2 "*** struct epoll_event unsupported"; \
+	   exit 1; ;; \
+	esac
+	echo '}' >> epoll.go.tmp
+	$(SHELL) $(srcdir)/../move-if-change epoll.go.tmp epoll.go
+	$(STAMP) $@
+
+if LIBGO_IS_LINUX
+# os_lib_inotify_lo = os/inotify.lo
+os_lib_inotify_lo =
+else
+os_lib_inotify_lo =
+endif
+
+libgo_go_objs = \
+	bufio.lo \
+	bytes.lo \
+	bytes/index.lo \
+	crypto.lo \
+	encoding.lo \
+	errors.lo \
+	expvar.lo \
+	flag.lo \
+	fmt.lo \
+	hash.lo \
+	html.lo \
+	image.lo \
+	io.lo \
+	log.lo \
+	math.lo \
+	mime.lo \
+	net.lo \
+	os.lo \
+	path.lo \
+	reflect-go.lo \
+	reflect/makefunc.lo \
+	reflect/makefunc_ffi_c.lo \
+	regexp.lo \
+	runtime-go.lo \
+	sort.lo \
+	strconv.lo \
+	strings.lo \
+	strings/index.lo \
+	sync.lo \
+	syscall.lo \
+	syscall/errno.lo \
+	syscall/signame.lo \
+	syscall/wait.lo \
+	testing.lo \
+	time-go.lo \
+	unicode.lo \
+	archive/tar.lo \
+	archive/zip.lo \
+	compress/bzip2.lo \
+	compress/flate.lo \
+	compress/gzip.lo \
+	compress/lzw.lo \
+	compress/zlib.lo \
+	container/heap.lo \
+	container/list.lo \
+	container/ring.lo \
+	crypto/aes.lo \
+	crypto/cipher.lo \
+	crypto/des.lo \
+	crypto/dsa.lo \
+	crypto/ecdsa.lo \
+	crypto/elliptic.lo \
+	crypto/hmac.lo \
+	crypto/md5.lo \
+	crypto/rand.lo \
+	crypto/rc4.lo \
+	crypto/rsa.lo \
+	crypto/sha1.lo \
+	crypto/sha256.lo \
+	crypto/sha512.lo \
+	crypto/subtle.lo \
+	crypto/tls.lo \
+	crypto/x509.lo \
+	crypto/x509/pkix.lo \
+	database/sql.lo \
+	database/sql/driver.lo \
+	debug/dwarf.lo \
+	debug/elf.lo \
+	debug/gosym.lo \
+	debug/macho.lo \
+	debug/pe.lo \
+	debug/plan9obj.lo \
+	encoding/ascii85.lo \
+	encoding/asn1.lo \
+	encoding/base32.lo \
+	encoding/base64.lo \
+	encoding/binary.lo \
+	encoding/csv.lo \
+	encoding/gob.lo \
+	encoding/hex.lo \
+	encoding/json.lo \
+	encoding/pem.lo \
+	encoding/xml.lo \
+	exp/proxy.lo \
+	exp/terminal.lo \
+	html/template.lo \
+	go/ast.lo \
+	go/build.lo \
+	go/doc.lo \
+	go/format.lo \
+	go/parser.lo \
+	go/printer.lo \
+	go/scanner.lo \
+	go/token.lo \
+	hash/adler32.lo \
+	hash/crc32.lo \
+	hash/crc64.lo \
+	hash/fnv.lo \
+	net/http/cgi.lo \
+	net/http/cookiejar.lo \
+	net/http/fcgi.lo \
+	net/http/httptest.lo \
+	net/http/httputil.lo \
+	net/http/pprof.lo \
+	image/color.lo \
+	image/color/palette.lo \
+	image/draw.lo \
+	image/gif.lo \
+	image/jpeg.lo \
+	image/png.lo \
+	index/suffixarray.lo \
+	io/ioutil.lo \
+	log/syslog.lo \
+	log/syslog/syslog_c.lo \
+	math/big.lo \
+	math/cmplx.lo \
+	math/rand.lo \
+	mime/multipart.lo \
+	net/http.lo \
+	net/mail.lo \
+	net/rpc.lo \
+	net/smtp.lo \
+	net/textproto.lo \
+	net/url.lo \
+	old/regexp.lo \
+	old/template.lo \
+	os/exec.lo \
+	$(os_lib_inotify_lo) \
+	os/signal.lo \
+	os/user.lo \
+	path/filepath.lo \
+	regexp/syntax.lo \
+	net/rpc/jsonrpc.lo \
+	runtime/debug.lo \
+	runtime/pprof.lo \
+	sync/atomic.lo \
+	sync/atomic_c.lo \
+	text/scanner.lo \
+	text/tabwriter.lo \
+	text/template.lo \
+	text/template/parse.lo \
+	testing/iotest.lo \
+	testing/quick.lo \
+	unicode/utf16.lo \
+	unicode/utf8.lo
+
+libgo_ldflags = \
+	-version-info $(libtool_VERSION) $(PTHREAD_CFLAGS) $(AM_LDFLAGS)
+
+libgo_libadd = \
+	$(libgo_go_objs) ../libbacktrace/libbacktrace.la \
+	$(LIBATOMIC) $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS)
+
+libgo_la_SOURCES = $(runtime_files)
+libgo_la_LDFLAGS = $(libgo_ldflags)
+libgo_la_LIBADD = $(libgo_libadd)
+
+libgo_llgo_la_SOURCES = $(runtime_files)
+libgo_llgo_la_LDFLAGS = $(libgo_ldflags)
+libgo_llgo_la_LIBADD = $(libgo_libadd)
+
+libgobegin_a_SOURCES = \
+	runtime/go-main.c
+
+libgobegin_llgo_a_SOURCES = \
+	runtime/go-main.c
+
+LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
+
+GOCFLAGS = $(CFLAGS)
+AM_GOCFLAGS = $(STRINGOPS_FLAG)
+GOCOMPILE = $(GOC) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_GOCFLAGS) $(GOCFLAGS)
+
+LTGOCOMPILE = $(LIBTOOL) --tag GO --mode=compile $(GOC) $(INCLUDES) \
+	$(AM_GOCFLAGS) $(GOCFLAGS)
+
+GOLINK = $(LIBTOOL) --tag GO --mode-link $(GOC) \
+	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_GOCFLAGS) $(LTLDFLAGS) -o $@
+
+# Build the dependencies for a Go package.
+BUILDDEPS = \
+	$(MKDIR_P) $(@D); \
+	$(SHELL) $(srcdir)/godeps.sh `echo $@ | sed -e 's/.dep$$//'` $^ > $@.tmp; \
+	mv -f $@.tmp $@
+
+# Build the .go files for a package, generating a .lo file.
+BUILDPACKAGE = \
+	$(MKDIR_P) $(@D); \
+	files=`echo $^ | sed -e 's/[^ ]*\.gox//g'`; \
+	$(LTGOCOMPILE) -I . -c -fgo-pkgpath=`echo $@ | sed -e 's/.lo$$//' -e 's/-go$$//'` -o $@ $$files
+
+GOTESTFLAGS =
+GOBENCH = 
+
+# Check a package.
+CHECK = \
+	GC="$(GOC) $(GOCFLAGS) $($(subst /,_,$@)_GOCFLAGS) -L `${PWD_COMMAND}` -L `${PWD_COMMAND}`/.libs"; \
+	export GC; \
+	GOLIBS="$(MATH_LIBS) $(NET_LIBS) $(LIBS)"; \
+	export GOLIBS; \
+	RUNTESTFLAGS="$(RUNTESTFLAGS)"; \
+	export RUNTESTFLAGS; \
+	MAKE="$(MAKE)"; \
+	export MAKE; \
+	libgccdir=`${GOC} -print-libgcc-file-name | sed -e 's|/[^/]*$$||'`; \
+	LD_LIBRARY_PATH="`${PWD_COMMAND}`/.libs:$${libgccdir}:${LD_LIBRARY_PATH}"; \
+	LD_LIBRARY_PATH=`echo $${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
+	export LD_LIBRARY_PATH; \
+	$(MKDIR_P) $(@D); \
+	rm -f $@-testsum $@-testlog; \
+	if test "$(USE_DEJAGNU)" = "yes"; then \
+	  $(SHELL) $(srcdir)/testsuite/gotest --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
+	elif test "$(GOBENCH)" != ""; then \
+	  $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
+	else \
+	  if $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \
+	    echo "PASS: $(@D)" >> $@-testlog; \
+	    echo "PASS: $(@D)"; \
+	    echo "PASS: $(@D)" > $@-testsum; \
+	  else \
+	    echo "FAIL: $(@D)" >> $@-testlog; \
+	    cat $@-testlog; \
+	    echo "FAIL: $(@D)" > $@-testsum; \
+	    exit 1; \
+	  fi; \
+	fi
+
+# Build all packages before checking any.
+CHECK_DEPS = \
+	$(toolexeclibgo_DATA) \
+	$(toolexeclibgoarchive_DATA) \
+	$(toolexeclibgocompress_DATA) \
+	$(toolexeclibgocontainer_DATA) \
+	$(toolexeclibgocrypto_DATA) \
+	$(toolexeclibgodebug_DATA) \
+	$(toolexeclibgoencoding_DATA) \
+	$(toolexeclibgoexp_DATA) \
+	$(toolexeclibgogo_DATA) \
+	$(toolexeclibgohash_DATA) \
+	$(toolexeclibgoimage_DATA) \
+	$(toolexeclibgoindex_DATA) \
+	$(toolexeclibgoio_DATA) \
+	$(toolexeclibgolog_DATA) \
+	$(toolexeclibgomath_DATA) \
+	$(toolexeclibgomime_DATA) \
+	$(toolexeclibgonet_DATA) \
+	$(toolexeclibgonethttp_DATA) \
+	$(toolexeclibgoos_DATA) \
+	$(toolexeclibgopath_DATA) \
+	$(toolexeclibgorpc_DATA) \
+	$(toolexeclibgoruntime_DATA) \
+	$(toolexeclibgosync_DATA) \
+	$(toolexeclibgotesting_DATA) \
+	$(toolexeclibgotext_DATA) \
+	$(toolexeclibgotexttemplate_DATA) \
+	$(toolexeclibgounicode_DATA)
+
+if GOC_IS_LLGO
+CHECK_DEPS += libgo-llgo.la libgobegin-llgo.a
+else
+CHECK_DEPS += libgo.la libgobegin.a
+endif
+
+@go_include@ bufio.lo.dep
+bufio.lo.dep: $(go_bufio_files)
+	$(BUILDDEPS)
+bufio.lo: $(go_bufio_files)
+	$(BUILDPACKAGE)
+bufio/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: bufio/check
+
+@go_include@ bytes.lo.dep
+bytes.lo.dep: $(go_bytes_files)
+	$(BUILDDEPS)
+bytes.lo: $(go_bytes_files)
+	$(BUILDPACKAGE)
+bytes/index.lo: $(go_bytes_c_files)
+	@$(MKDIR_P) bytes
+	$(LTCOMPILE) -c -o bytes/index.lo $(srcdir)/go/bytes/indexbyte.c
+bytes/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: bytes/check
+
+@go_include@ crypto.lo.dep
+crypto.lo.dep: $(go_crypto_files)
+	$(BUILDDEPS)
+crypto.lo: $(go_crypto_files)
+	$(BUILDPACKAGE)
+crypto/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/check
+
+@go_include@ encoding.lo.dep
+encoding.lo.dep: $(go_encoding_files)
+	$(BUILDDEPS)
+encoding.lo: $(go_encoding_files)
+	$(BUILDPACKAGE)
+encoding/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/check
+
+@go_include@ errors.lo.dep
+errors.lo.dep: $(go_errors_files)
+	$(BUILDDEPS)
+errors.lo: $(go_errors_files)
+	$(BUILDPACKAGE)
+errors/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: errors/check
+
+@go_include@ expvar.lo.dep
+expvar.lo.dep: $(go_expvar_files)
+	$(BUILDDEPS)
+expvar.lo: $(go_expvar_files)
+	$(BUILDPACKAGE)
+expvar/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: expvar/check
+
+@go_include@ flag.lo.dep
+flag.lo.dep: $(go_flag_files)
+	$(BUILDDEPS)
+flag.lo: $(go_flag_files)
+	$(BUILDPACKAGE)
+flag/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: flag/check
+
+@go_include@ fmt.lo.dep
+fmt.lo.dep: $(go_fmt_files)
+	$(BUILDDEPS)
+fmt.lo: $(go_fmt_files)
+	$(BUILDPACKAGE)
+fmt/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: fmt/check
+
+@go_include@ hash.lo.dep
+hash.lo.dep: $(go_hash_files)
+	$(BUILDDEPS)
+hash.lo: $(go_hash_files)
+	$(BUILDPACKAGE)
+hash/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: hash/check
+
+@go_include@ html.lo.dep
+html.lo.dep: $(go_html_files)
+	$(BUILDDEPS)
+html.lo: $(go_html_files)
+	$(BUILDPACKAGE)
+html/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: html/check
+
+@go_include@ image.lo.dep
+image.lo.dep: $(go_image_files)
+	$(BUILDDEPS)
+image.lo: $(go_image_files)
+	$(BUILDPACKAGE)
+image/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/check
+
+@go_include@ io.lo.dep
+io.lo.dep: $(go_io_files)
+	$(BUILDDEPS)
+io.lo: $(go_io_files)
+	$(BUILDPACKAGE)
+io/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: io/check
+
+@go_include@ log.lo.dep
+log.lo.dep: $(go_log_files)
+	$(BUILDDEPS)
+log.lo: $(go_log_files)
+	$(BUILDPACKAGE)
+log/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: log/check
+
+@go_include@ math.lo.dep
+math.lo.dep: $(go_math_files)
+	$(BUILDDEPS)
+math.lo: $(go_math_files)
+	$(MKDIR_P) $(@D)
+	files=`echo $^ | sed -e 's/[^ ]*\.gox//g'`; \
+	$(LTGOCOMPILE) $(MATH_FLAG) -I . -c -fgo-pkgpath=math -o $@ $$files
+math/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: math/check
+
+@go_include@ mime.lo.dep
+mime.lo.dep: $(go_mime_files)
+	$(BUILDDEPS)
+mime.lo: $(go_mime_files)
+	$(BUILDPACKAGE)
+mime/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: mime/check
+
+@go_include@ net.lo.dep
+net.lo.dep: $(go_net_files)
+	$(BUILDDEPS)
+net.lo: $(go_net_files)
+	$(BUILDPACKAGE)
+net/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/check
+
+@go_include@ os.lo.dep
+os.lo.dep: $(go_os_files)
+	$(BUILDDEPS)
+os.lo: $(go_os_files)
+	$(BUILDPACKAGE)
+os/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: os/check
+
+@go_include@ path.lo.dep
+path.lo.dep: $(go_path_files)
+	$(BUILDDEPS)
+path.lo: $(go_path_files)
+	$(BUILDPACKAGE)
+path/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: path/check
+
+@go_include@ reflect-go.lo.dep
+reflect-go.lo.dep: $(go_reflect_files)
+	$(BUILDDEPS)
+reflect-go.lo: $(go_reflect_files)
+	$(BUILDPACKAGE)
+reflect/check: $(CHECK_DEPS)
+	@$(CHECK)
+reflect/makefunc.lo: $(go_reflect_makefunc_s_file)
+	@$(MKDIR_P) reflect
+	$(LTCOMPILE) -c -o $@ $<
+reflect/makefunc_ffi_c.lo: $(go_reflect_makefunc_c_file)
+	@$(MKDIR_P) reflect
+	$(LTCOMPILE) -c -o $@ $<
+.PHONY: reflect/check
+
+@go_include@ regexp.lo.dep
+regexp.lo.dep: $(go_regexp_files)
+	$(BUILDDEPS)
+regexp.lo: $(go_regexp_files)
+	$(BUILDPACKAGE)
+regexp/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: regexp/check
+
+@go_include@ runtime-go.lo.dep
+runtime-go.lo.dep: $(go_runtime_files)
+	$(BUILDDEPS)
+runtime-go.lo: $(go_runtime_files)
+	$(BUILDPACKAGE)
+runtime/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: runtime/check
+
+@go_include@ sort.lo.dep
+sort.lo.dep: $(go_sort_files)
+	$(BUILDDEPS)
+sort.lo: $(go_sort_files)
+	$(BUILDPACKAGE)
+sort/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: sort/check
+
+@go_include@ strconv.lo.dep
+strconv.lo.dep: $(go_strconv_files)
+	$(BUILDDEPS)
+strconv.lo: $(go_strconv_files)
+	$(BUILDPACKAGE)
+strconv/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: strconv/check
+
+@go_include@ strings.lo.dep
+strings.lo.dep: $(go_strings_files)
+	$(BUILDDEPS)
+strings.lo: $(go_strings_files)
+	$(BUILDPACKAGE)
+strings/index.lo: $(go_strings_c_files)
+	@$(MKDIR_P) strings
+	$(LTCOMPILE) -c -o strings/index.lo $(srcdir)/go/strings/indexbyte.c
+strings/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: strings/check
+
+@go_include@ sync.lo.dep
+sync.lo.dep: $(go_sync_files)
+	$(BUILDDEPS)
+sync.lo: $(go_sync_files)
+	$(BUILDPACKAGE)
+sync/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: sync/check
+
+@go_include@ testing.lo.dep
+testing.lo.dep: $(go_testing_files)
+	$(BUILDDEPS)
+testing.lo: $(go_testing_files)
+	$(BUILDPACKAGE)
+testing/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: testing/check
+
+@go_include@ time-go.lo.dep
+time-go.lo.dep: $(go_time_files)
+	$(BUILDDEPS)
+time-go.lo: $(go_time_files)
+	$(BUILDPACKAGE)
+time/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: time/check
+
+@go_include@ unicode.lo.dep
+unicode.lo.dep: $(go_unicode_files)
+	$(BUILDDEPS)
+unicode.lo: $(go_unicode_files)
+	$(BUILDPACKAGE)
+unicode/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: unicode/check
+
+@go_include@ archive/tar.lo.dep
+archive/tar.lo.dep: $(go_archive_tar_files)
+	$(BUILDDEPS)
+archive/tar.lo: $(go_archive_tar_files)
+	$(BUILDPACKAGE)
+archive/tar/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: archive/tar/check
+
+@go_include@ archive/zip.lo.dep
+archive/zip.lo.dep: $(go_archive_zip_files)
+	$(BUILDDEPS)
+archive/zip.lo: $(go_archive_zip_files)
+	$(BUILDPACKAGE)
+archive/zip/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: archive/zip/check
+
+@go_include@ compress/bzip2.lo.dep
+compress/bzip2.lo.dep: $(go_compress_bzip2_files)
+	$(BUILDDEPS)
+compress/bzip2.lo: $(go_compress_bzip2_files)
+	$(BUILDPACKAGE)
+compress/bzip2/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: compress/bzip2/check
+
+@go_include@ compress/flate.lo.dep
+compress/flate.lo.dep: $(go_compress_flate_files)
+	$(BUILDDEPS)
+compress/flate.lo: $(go_compress_flate_files)
+	$(BUILDPACKAGE)
+compress/flate/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: compress/flate/check
+
+@go_include@ compress/gzip.lo.dep
+compress/gzip.lo.dep: $(go_compress_gzip_files)
+	$(BUILDDEPS)
+compress/gzip.lo: $(go_compress_gzip_files)
+	$(BUILDPACKAGE)
+compress/gzip/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: compress/gzip/check
+
+@go_include@ compress/lzw.lo.dep
+compress/lzw.lo.dep: $(go_compress_lzw_files)
+	$(BUILDDEPS)
+compress/lzw.lo: $(go_compress_lzw_files)
+	$(BUILDPACKAGE)
+compress/lzw/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: compress/lzw/check
+
+@go_include@ compress/zlib.lo.dep
+compress/zlib.lo.dep: $(go_compress_zlib_files)
+	$(BUILDDEPS)
+compress/zlib.lo: $(go_compress_zlib_files)
+	$(BUILDPACKAGE)
+compress/zlib/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: compress/zlib/check
+
+@go_include@ container/heap.lo.dep
+container/heap.lo.dep: $(go_container_heap_files)
+	$(BUILDDEPS)
+container/heap.lo: $(go_container_heap_files)
+	$(BUILDPACKAGE)
+container/heap/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: container/heap/check
+
+@go_include@ container/list.lo.dep
+container/list.lo.dep: $(go_container_list_files)
+	$(BUILDDEPS)
+container/list.lo: $(go_container_list_files)
+	$(BUILDPACKAGE)
+container/list/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: container/list/check
+
+@go_include@ container/ring.lo.dep
+container/ring.lo.dep: $(go_container_ring_files)
+	$(BUILDDEPS)
+container/ring.lo: $(go_container_ring_files)
+	$(BUILDPACKAGE)
+container/ring/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: container/ring/check
+
+@go_include@ crypto/aes.lo.dep
+crypto/aes.lo.dep: $(go_crypto_aes_files)
+	$(BUILDDEPS)
+crypto/aes.lo: $(go_crypto_aes_files)
+	$(BUILDPACKAGE)
+crypto/aes/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/aes/check
+
+@go_include@ crypto/cipher.lo.dep
+crypto/cipher.lo.dep: $(go_crypto_cipher_files)
+	$(BUILDDEPS)
+crypto/cipher.lo: $(go_crypto_cipher_files)
+	$(BUILDPACKAGE)
+crypto/cipher/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/cipher/check
+
+@go_include@ crypto/des.lo.dep
+crypto/des.lo.dep: $(go_crypto_des_files)
+	$(BUILDDEPS)
+crypto/des.lo: $(go_crypto_des_files)
+	$(BUILDPACKAGE)
+crypto/des/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/des/check
+
+@go_include@ crypto/dsa.lo.dep
+crypto/dsa.lo.dep: $(go_crypto_dsa_files)
+	$(BUILDDEPS)
+crypto/dsa.lo: $(go_crypto_dsa_files)
+	$(BUILDPACKAGE)
+crypto/dsa/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/dsa/check
+
+@go_include@ crypto/ecdsa.lo.dep
+crypto/ecdsa.lo.dep: $(go_crypto_ecdsa_files)
+	$(BUILDDEPS)
+crypto/ecdsa.lo: $(go_crypto_ecdsa_files)
+	$(BUILDPACKAGE)
+crypto/ecdsa/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/ecdsa/check
+
+@go_include@ crypto/elliptic.lo.dep
+crypto/elliptic.lo.dep: $(go_crypto_elliptic_files)
+	$(BUILDDEPS)
+crypto/elliptic.lo: $(go_crypto_elliptic_files)
+	$(BUILDPACKAGE)
+crypto/elliptic/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/elliptic/check
+
+@go_include@ crypto/hmac.lo.dep
+crypto/hmac.lo.dep: $(go_crypto_hmac_files)
+	$(BUILDDEPS)
+crypto/hmac.lo: $(go_crypto_hmac_files)
+	$(BUILDPACKAGE)
+crypto/hmac/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/hmac/check
+
+@go_include@ crypto/md5.lo.dep
+crypto/md5.lo.dep: $(go_crypto_md5_files)
+	$(BUILDDEPS)
+crypto/md5.lo: $(go_crypto_md5_files)
+	$(BUILDPACKAGE)
+crypto/md5/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/md5/check
+
+@go_include@ crypto/rand.lo.dep
+crypto/rand.lo.dep: $(go_crypto_rand_files)
+	$(BUILDDEPS)
+crypto/rand.lo: $(go_crypto_rand_files)
+	$(BUILDPACKAGE)
+crypto/rand/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/rand/check
+
+@go_include@ crypto/rc4.lo.dep
+crypto/rc4.lo.dep: $(go_crypto_rc4_files)
+	$(BUILDDEPS)
+crypto/rc4.lo: $(go_crypto_rc4_files)
+	$(BUILDPACKAGE)
+crypto/rc4/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/rc4/check
+
+@go_include@ crypto/rsa.lo.dep
+crypto/rsa.lo.dep: $(go_crypto_rsa_files)
+	$(BUILDDEPS)
+crypto/rsa.lo: $(go_crypto_rsa_files)
+	$(BUILDPACKAGE)
+crypto/rsa/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/rsa/check
+
+@go_include@ crypto/sha1.lo.dep
+crypto/sha1.lo.dep: $(go_crypto_sha1_files)
+	$(BUILDDEPS)
+crypto/sha1.lo: $(go_crypto_sha1_files)
+	$(BUILDPACKAGE)
+crypto/sha1/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/sha1/check
+
+@go_include@ crypto/sha256.lo.dep
+crypto/sha256.lo.dep: $(go_crypto_sha256_files)
+	$(BUILDDEPS)
+crypto/sha256.lo: $(go_crypto_sha256_files)
+	$(BUILDPACKAGE)
+crypto/sha256/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/sha256/check
+
+@go_include@ crypto/sha512.lo.dep
+crypto/sha512.lo.dep: $(go_crypto_sha512_files)
+	$(BUILDDEPS)
+crypto/sha512.lo: $(go_crypto_sha512_files)
+	$(BUILDPACKAGE)
+crypto/sha512/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/sha512/check
+
+@go_include@ crypto/subtle.lo.dep
+crypto/subtle.lo.dep: $(go_crypto_subtle_files)
+	$(BUILDDEPS)
+crypto/subtle.lo: $(go_crypto_subtle_files)
+	$(BUILDPACKAGE)
+crypto/subtle/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/subtle/check
+
+@go_include@ crypto/tls.lo.dep
+crypto/tls.lo.dep: $(go_crypto_tls_files)
+	$(BUILDDEPS)
+crypto/tls.lo: $(go_crypto_tls_files)
+	$(BUILDPACKAGE)
+crypto/tls/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/tls/check
+
+@go_include@ crypto/x509.lo.dep
+crypto/x509.lo.dep: $(go_crypto_x509_files)
+	$(BUILDDEPS)
+crypto/x509.lo: $(go_crypto_x509_files)
+	$(BUILDPACKAGE)
+crypto/x509/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/x509/check
+
+@go_include@ crypto/x509/pkix.lo.dep
+crypto/x509/pkix.lo.dep: $(go_crypto_x509_pkix_files)
+	$(BUILDDEPS)
+crypto/x509/pkix.lo: $(go_crypto_x509_pkix_files)
+	$(BUILDPACKAGE)
+crypto/x509/pkix/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/x509/pkix/check
+
+@go_include@ database/sql.lo.dep
+database/sql.lo.dep: $(go_database_sql_files)
+	$(BUILDDEPS)
+database/sql.lo: $(go_database_sql_files)
+	$(BUILDPACKAGE)
+database/sql/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: database/sql/check
+
+@go_include@ database/sql/driver.lo.dep
+database/sql/driver.lo.dep: $(go_database_sql_driver_files)
+	$(BUILDDEPS)
+database/sql/driver.lo: $(go_database_sql_driver_files)
+	$(BUILDPACKAGE)
+database/sql/driver/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: database/sql/driver/check
+
+@go_include@ debug/dwarf.lo.dep
+debug/dwarf.lo.dep: $(go_debug_dwarf_files)
+	$(BUILDDEPS)
+debug/dwarf.lo: $(go_debug_dwarf_files)
+	$(BUILDPACKAGE)
+debug/dwarf/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/dwarf/check
+
+@go_include@ debug/elf.lo.dep
+debug/elf.lo.dep: $(go_debug_elf_files)
+	$(BUILDDEPS)
+debug/elf.lo: $(go_debug_elf_files)
+	$(BUILDPACKAGE)
+debug/elf/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/elf/check
+
+@go_include@ debug/gosym.lo.dep
+debug/gosym.lo.dep: $(go_debug_gosym_files)
+	$(BUILDDEPS)
+debug/gosym.lo: $(go_debug_gosym_files)
+	$(BUILDPACKAGE)
+debug/gosym/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/gosym/check
+
+@go_include@ debug/macho.lo.dep
+debug/macho.lo.dep: $(go_debug_macho_files)
+	$(BUILDDEPS)
+debug/macho.lo: $(go_debug_macho_files)
+	$(BUILDPACKAGE)
+debug/macho/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/macho/check
+
+@go_include@ debug/pe.lo.dep
+debug/pe.lo.dep: $(go_debug_pe_files)
+	$(BUILDDEPS)
+debug/pe.lo: $(go_debug_pe_files)
+	$(BUILDPACKAGE)
+debug/pe/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/pe/check
+
+@go_include@ debug/plan9obj.lo.dep
+debug/plan9obj.lo.dep: $(go_debug_plan9obj_files)
+	$(BUILDDEPS)
+debug/plan9obj.lo: $(go_debug_plan9obj_files)
+	$(BUILDPACKAGE)
+debug/plan9obj/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/plan9obj/check
+
+@go_include@ encoding/asn1.lo.dep
+encoding/asn1.lo.dep: $(go_encoding_asn1_files)
+	$(BUILDDEPS)
+encoding/asn1.lo: $(go_encoding_asn1_files)
+	$(BUILDPACKAGE)
+encoding/asn1/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/asn1/check
+
+@go_include@ encoding/ascii85.lo.dep
+encoding/ascii85.lo.dep: $(go_encoding_ascii85_files)
+	$(BUILDDEPS)
+encoding/ascii85.lo: $(go_encoding_ascii85_files)
+	$(BUILDPACKAGE)
+encoding/ascii85/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/ascii85/check
+
+@go_include@ encoding/base32.lo.dep
+encoding/base32.lo.dep: $(go_encoding_base32_files)
+	$(BUILDDEPS)
+encoding/base32.lo: $(go_encoding_base32_files)
+	$(BUILDPACKAGE)
+encoding/base32/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/base32/check
+
+@go_include@ encoding/base64.lo.dep
+encoding/base64.lo.dep: $(go_encoding_base64_files)
+	$(BUILDDEPS)
+encoding/base64.lo: $(go_encoding_base64_files)
+	$(BUILDPACKAGE)
+encoding/base64/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/base64/check
+
+@go_include@ encoding/binary.lo.dep
+encoding/binary.lo.dep: $(go_encoding_binary_files)
+	$(BUILDDEPS)
+encoding/binary.lo: $(go_encoding_binary_files)
+	$(BUILDPACKAGE)
+encoding/binary/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/binary/check
+
+@go_include@ encoding/csv.lo.dep
+encoding/csv.lo.dep: $(go_encoding_csv_files)
+	$(BUILDDEPS)
+encoding/csv.lo: $(go_encoding_csv_files)
+	$(BUILDPACKAGE)
+encoding/csv/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/csv/check
+
+@go_include@ encoding/gob.lo.dep
+encoding/gob.lo.dep: $(go_encoding_gob_files)
+	$(BUILDDEPS)
+encoding/gob.lo: $(go_encoding_gob_files)
+	$(BUILDPACKAGE)
+encoding/gob/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/gob/check
+
+@go_include@ encoding/hex.lo.dep
+encoding/hex.lo.dep: $(go_encoding_hex_files)
+	$(BUILDDEPS)
+encoding/hex.lo: $(go_encoding_hex_files)
+	$(BUILDPACKAGE)
+encoding/hex/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/hex/check
+
+@go_include@ encoding/json.lo.dep
+encoding/json.lo.dep: $(go_encoding_json_files)
+	$(BUILDDEPS)
+encoding/json.lo: $(go_encoding_json_files)
+	$(BUILDPACKAGE)
+encoding/json/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/json/check
+
+@go_include@ encoding/pem.lo.dep
+encoding/pem.lo.dep: $(go_encoding_pem_files)
+	$(BUILDDEPS)
+encoding/pem.lo: $(go_encoding_pem_files)
+	$(BUILDPACKAGE)
+encoding/pem/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/pem/check
+
+@go_include@ encoding/xml.lo.dep
+encoding/xml.lo.dep: $(go_encoding_xml_files)
+	$(BUILDDEPS)
+encoding/xml.lo: $(go_encoding_xml_files)
+	$(BUILDPACKAGE)
+encoding/xml/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/xml/check
+
+@go_include@ exp/proxy.lo.dep
+exp/proxy.lo.dep: $(go_exp_proxy_files)
+	$(BUILDDEPS)
+exp/proxy.lo: $(go_exp_proxy_files)
+	$(BUILDPACKAGE)
+exp/proxy/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: exp/proxy/check
+
+@go_include@ exp/terminal.lo.dep
+exp/terminal.lo.dep: $(go_exp_terminal_files)
+	$(BUILDDEPS)
+exp/terminal.lo: $(go_exp_terminal_files)
+	$(BUILDPACKAGE)
+exp/terminal/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: exp/terminal/check
+
+@go_include@ html/template.lo.dep
+html/template.lo.dep: $(go_html_template_files)
+	$(BUILDDEPS)
+html/template.lo: $(go_html_template_files)
+	$(BUILDPACKAGE)
+html/template/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: html/template/check
+
+@go_include@ go/ast.lo.dep
+go/ast.lo.dep: $(go_go_ast_files)
+	$(BUILDDEPS)
+go/ast.lo: $(go_go_ast_files)
+	$(BUILDPACKAGE)
+go/ast/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/ast/check
+
+@go_include@ go/build.lo.dep
+go/build.lo.dep: $(go_go_build_files)
+	$(BUILDDEPS)
+go/build.lo: $(go_go_build_files)
+	$(BUILDPACKAGE)
+go/build/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/build/check
+
+@go_include@ go/doc.lo.dep
+go/doc.lo.dep: $(go_go_doc_files)
+	$(BUILDDEPS)
+go/doc.lo: $(go_go_doc_files)
+	$(BUILDPACKAGE)
+go/doc/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/doc/check
+
+@go_include@ go/format.lo.dep
+go/format.lo.dep: $(go_go_format_files)
+	$(BUILDDEPS)
+go/format.lo: $(go_go_format_files)
+	$(BUILDPACKAGE)
+go/format/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/format/check
+
+@go_include@ go/parser.lo.dep
+go/parser.lo.dep: $(go_go_parser_files)
+	$(BUILDDEPS)
+go/parser.lo: $(go_go_parser_files)
+	$(BUILDPACKAGE)
+go/parser/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/parser/check
+
+@go_include@ go/printer.lo.dep
+go/printer.lo.dep: $(go_go_printer_files)
+	$(BUILDDEPS)
+go/printer.lo: $(go_go_printer_files)
+	$(BUILDPACKAGE)
+go/printer/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/printer/check
+
+@go_include@ go/scanner.lo.dep
+go/scanner.lo.dep: $(go_go_scanner_files)
+	$(BUILDDEPS)
+go/scanner.lo: $(go_go_scanner_files)
+	$(BUILDPACKAGE)
+go/scanner/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/scanner/check
+
+@go_include@ go/token.lo.dep
+go/token.lo.dep: $(go_go_token_files)
+	$(BUILDDEPS)
+go/token.lo: $(go_go_token_files)
+	$(BUILDPACKAGE)
+go/token/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/token/check
+
+@go_include@ hash/adler32.lo.dep
+hash/adler32.lo.dep: $(go_hash_adler32_files)
+	$(BUILDDEPS)
+hash/adler32.lo: $(go_hash_adler32_files)
+	$(BUILDPACKAGE)
+hash/adler32/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: hash/adler32/check
+
+@go_include@ hash/crc32.lo.dep
+hash/crc32.lo.dep: $(go_hash_crc32_files)
+	$(BUILDDEPS)
+hash/crc32.lo: $(go_hash_crc32_files)
+	$(BUILDPACKAGE)
+hash/crc32/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: hash/crc32/check
+
+@go_include@ hash/crc64.lo.dep
+hash/crc64.lo.dep: $(go_hash_crc64_files)
+	$(BUILDDEPS)
+hash/crc64.lo: $(go_hash_crc64_files)
+	$(BUILDPACKAGE)
+hash/crc64/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: hash/crc64/check
+
+@go_include@ hash/fnv.lo.dep
+hash/fnv.lo.dep: $(go_hash_fnv_files)
+	$(BUILDDEPS)
+hash/fnv.lo: $(go_hash_fnv_files)
+	$(BUILDPACKAGE)
+hash/fnv/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: hash/fnv/check
+
+@go_include@ image/color.lo.dep
+image/color.lo.dep: $(go_image_color_files)
+	$(BUILDDEPS)
+image/color.lo: $(go_image_color_files)
+	$(BUILDPACKAGE)
+image/color/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/color/check
+
+@go_include@ image/color/palette.lo.dep
+image/color/palette.lo.dep: $(go_image_color_palette_files)
+	$(BUILDDEPS)
+image/color/palette.lo: $(go_image_color_palette_files)
+	$(BUILDPACKAGE)
+image/color/palette/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/color/palette/check
+
+@go_include@ image/draw.lo.dep
+image/draw.lo.dep: $(go_image_draw_files)
+	$(BUILDDEPS)
+image/draw.lo: $(go_image_draw_files)
+	$(BUILDPACKAGE)
+image/draw/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/draw/check
+
+@go_include@ image/gif.lo.dep
+image/gif.lo.dep: $(go_image_gif_files)
+	$(BUILDDEPS)
+image/gif.lo: $(go_image_gif_files)
+	$(BUILDPACKAGE)
+image/gif/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/gif/check
+
+@go_include@ image/jpeg.lo.dep
+image/jpeg.lo.dep: $(go_image_jpeg_files)
+	$(BUILDDEPS)
+image/jpeg.lo: $(go_image_jpeg_files)
+	$(BUILDPACKAGE)
+image/jpeg/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/jpeg/check
+
+@go_include@ image/png.lo.dep
+image/png.lo.dep: $(go_image_png_files)
+	$(BUILDDEPS)
+image/png.lo: $(go_image_png_files)
+	$(BUILDPACKAGE)
+image/png/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/png/check
+
+@go_include@ index/suffixarray.lo.dep
+index/suffixarray.lo.dep: $(go_index_suffixarray_files)
+	$(BUILDDEPS)
+index/suffixarray.lo: $(go_index_suffixarray_files)
+	$(BUILDPACKAGE)
+index/suffixarray/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: index/suffixarray/check
+
+@go_include@ io/ioutil.lo.dep
+io/ioutil.lo.dep: $(go_io_ioutil_files)
+	$(BUILDDEPS)
+io/ioutil.lo: $(go_io_ioutil_files)
+	$(BUILDPACKAGE)
+io/ioutil/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: io/ioutil/check
+
+@go_include@ log/syslog.lo.dep
+log/syslog.lo.dep: $(go_log_syslog_files)
+	$(BUILDDEPS)
+log/syslog.lo: $(go_log_syslog_files)
+	$(BUILDPACKAGE)
+log/syslog/syslog_c.lo: $(go_syslog_c_files) log/syslog.lo
+	@$(MKDIR_P) log/syslog
+	$(LTCOMPILE) -c -o $@ $(srcdir)/go/log/syslog/syslog_c.c
+log/syslog/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: log/syslog/check
+
+@go_include@ math/big.lo.dep
+math/big.lo.dep: $(go_math_big_files)
+	$(BUILDDEPS)
+math/big.lo: $(go_math_big_files)
+	$(BUILDPACKAGE)
+math/big/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: math/big/check
+
+@go_include@ math/cmplx.lo.dep
+math/cmplx.lo.dep: $(go_math_cmplx_files)
+	$(BUILDDEPS)
+math/cmplx.lo: $(go_math_cmplx_files)
+	$(BUILDPACKAGE)
+math/cmplx/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: math/cmplx/check
+
+@go_include@ math/rand.lo.dep
+math/rand.lo.dep: $(go_math_rand_files)
+	$(BUILDDEPS)
+math/rand.lo: $(go_math_rand_files)
+	$(BUILDPACKAGE)
+math/rand/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: math/rand/check
+
+@go_include@ mime/multipart.lo.dep
+mime/multipart.lo.dep: $(go_mime_multipart_files)
+	$(BUILDDEPS)
+mime/multipart.lo: $(go_mime_multipart_files)
+	$(BUILDPACKAGE)
+mime/multipart/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: mime/multipart/check
+
+@go_include@ net/http.lo.dep
+net/http.lo.dep: $(go_net_http_files)
+	$(BUILDDEPS)
+net/http.lo: $(go_net_http_files)
+	$(BUILDPACKAGE)
+net/http/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/http/check
+
+@go_include@ net/mail.lo.dep
+net/mail.lo.dep: $(go_net_mail_files)
+	$(BUILDDEPS)
+net/mail.lo: $(go_net_mail_files)
+	$(BUILDPACKAGE)
+net/mail/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/mail/check
+
+@go_include@ net/rpc.lo.dep
+net/rpc.lo.dep: $(go_net_rpc_files)
+	$(BUILDDEPS)
+net/rpc.lo: $(go_net_rpc_files)
+	$(BUILDPACKAGE)
+net/rpc/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/rpc/check
+
+@go_include@ net/smtp.lo.dep
+net/smtp.lo.dep: $(go_net_smtp_files)
+	$(BUILDDEPS)
+net/smtp.lo: $(go_net_smtp_files)
+	$(BUILDPACKAGE)
+net/smtp/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/smtp/check
+
+@go_include@ net/url.lo.dep
+net/url.lo.dep: $(go_net_url_files)
+	$(BUILDDEPS)
+net/url.lo: $(go_net_url_files)
+	$(BUILDPACKAGE)
+net/url/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/url/check
+
+@go_include@ net/textproto.lo.dep
+net/textproto.lo.dep: $(go_net_textproto_files)
+	$(BUILDDEPS)
+net/textproto.lo: $(go_net_textproto_files)
+	$(BUILDPACKAGE)
+net/textproto/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/textproto/check
+
+@go_include@ net/http/cgi.lo.dep
+net/http/cgi.lo.dep: $(go_net_http_cgi_files)
+	$(BUILDDEPS)
+net/http/cgi.lo: $(go_net_http_cgi_files)
+	$(BUILDPACKAGE)
+net/http/cgi/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/http/cgi/check
+
+@go_include@ net/http/cookiejar.lo.dep
+net/http/cookiejar.lo.dep: $(go_net_http_cookiejar_files)
+	$(BUILDDEPS)
+net/http/cookiejar.lo: $(go_net_http_cookiejar_files)
+	$(BUILDPACKAGE)
+net/http/cookiejar/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/http/cookiejar/check
+
+@go_include@ net/http/fcgi.lo.dep
+net/http/fcgi.lo.dep: $(go_net_http_fcgi_files)
+	$(BUILDDEPS)
+net/http/fcgi.lo: $(go_net_http_fcgi_files)
+	$(BUILDPACKAGE)
+net/http/fcgi/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/http/fcgi/check
+
+@go_include@ net/http/httptest.lo.dep
+net/http/httptest.lo.dep: $(go_net_http_httptest_files)
+	$(BUILDDEPS)
+net/http/httptest.lo: $(go_net_http_httptest_files)
+	$(BUILDPACKAGE)
+net/http/httptest/check: $(check_deps)
+	@$(CHECK)
+.PHONY: net/http/httptest/check
+
+@go_include@ net/http/httputil.lo.dep
+net/http/httputil.lo.dep: $(go_net_http_httputil_files)
+	$(BUILDDEPS)
+net/http/httputil.lo: $(go_net_http_httputil_files)
+	$(BUILDPACKAGE)
+net/http/httputil/check: $(check_deps)
+	@$(CHECK)
+.PHONY: net/http/httputil/check
+
+@go_include@ net/http/pprof.lo.dep
+net/http/pprof.lo.dep: $(go_net_http_pprof_files)
+	$(BUILDDEPS)
+net/http/pprof.lo: $(go_net_http_pprof_files)
+	$(BUILDPACKAGE)
+net/http/pprof/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/http/pprof/check
+
+@go_include@ net/rpc/jsonrpc.lo.dep
+net/rpc/jsonrpc.lo.dep: $(go_net_rpc_jsonrpc_files)
+	$(BUILDDEPS)
+net/rpc/jsonrpc.lo: $(go_net_rpc_jsonrpc_files)
+	$(BUILDPACKAGE)
+net/rpc/jsonrpc/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/rpc/jsonrpc/check
+
+@go_include@ old/regexp.lo.dep
+old/regexp.lo.dep: $(go_old_regexp_files)
+	$(BUILDDEPS)
+old/regexp.lo: $(go_old_regexp_files)
+	$(BUILDPACKAGE)
+old/regexp/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: old/regexp/check
+
+@go_include@ old/template.lo.dep
+old/template.lo.dep: $(go_old_template_files)
+	$(BUILDDEPS)
+old/template.lo: $(go_old_template_files)
+	$(BUILDPACKAGE)
+old/template/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: old/template/check
+
+@go_include@ os/exec.lo.dep
+os/exec.lo.dep: $(go_os_exec_files)
+	$(BUILDDEPS)
+os/exec.lo: $(go_os_exec_files)
+	$(BUILDPACKAGE)
+os/exec/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: os/exec/check
+
+@go_include@ os/signal.lo.dep
+os/signal.lo.dep: $(go_os_signal_files)
+	$(BUILDDEPS)
+os/signal.lo: $(go_os_signal_files)
+	$(BUILDPACKAGE)
+os/signal/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: os/signal/check
+
+@go_include@ os/user.lo.dep
+os/user.lo.dep: $(go_os_user_files)
+	$(BUILDDEPS)
+os/user.lo: $(go_os_user_files)
+	$(BUILDPACKAGE)
+os/user/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: os/user/check
+
+@go_include@ path/filepath.lo.dep
+path/filepath.lo.dep: $(go_path_filepath_files)
+	$(BUILDDEPS)
+path/filepath.lo: $(go_path_filepath_files)
+	$(BUILDPACKAGE)
+path/filepath/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: path/filepath/check
+
+@go_include@ regexp/syntax.lo.dep
+regexp/syntax.lo.dep: $(go_regexp_syntax_files)
+	$(BUILDDEPS)
+regexp/syntax.lo: $(go_regexp_syntax_files)
+	$(BUILDPACKAGE)
+regexp/syntax/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: regexp/syntax/check
+
+@go_include@ runtime/debug.lo.dep
+runtime/debug.lo.dep: $(go_runtime_debug_files)
+	$(BUILDDEPS)
+runtime/debug.lo: $(go_runtime_debug_files)
+	$(BUILDPACKAGE)
+runtime/debug/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: runtime/debug/check
+
+@go_include@ runtime/pprof.lo.dep
+runtime/pprof.lo.dep: $(go_runtime_pprof_files)
+	$(BUILDDEPS)
+runtime/pprof.lo: $(go_runtime_pprof_files)
+	$(BUILDPACKAGE)
+runtime/pprof/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: runtime/pprof/check
+# At least for now, we need -static-libgo for this test, because
+# otherwise we can't get the line numbers.
+runtime_pprof_check_GOCFLAGS = -static-libgo
+
+@go_include@ sync/atomic.lo.dep
+sync/atomic.lo.dep: $(go_sync_atomic_files)
+	$(BUILDDEPS)
+sync/atomic.lo: $(go_sync_atomic_files)
+	$(BUILDPACKAGE)
+sync/atomic_c.lo: $(go_sync_atomic_c_files) sync/atomic.lo
+	$(LTCOMPILE) -c -o $@ $(srcdir)/go/sync/atomic/atomic.c
+sync/atomic/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: sync/atomic/check
+
+@go_include@ text/scanner.lo.dep
+text/scanner.lo.dep: $(go_text_scanner_files)
+	$(BUILDDEPS)
+text/scanner.lo: $(go_text_scanner_files)
+	$(BUILDPACKAGE)
+text/scanner/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: text/scanner/check
+
+@go_include@ text/tabwriter.lo.dep
+text/tabwriter.lo.dep: $(go_text_tabwriter_files)
+	$(BUILDDEPS)
+text/tabwriter.lo: $(go_text_tabwriter_files)
+	$(BUILDPACKAGE)
+text/tabwriter/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: text/tabwriter/check
+
+@go_include@ text/template.lo.dep
+text/template.lo.dep: $(go_text_template_files)
+	$(BUILDDEPS)
+text/template.lo: $(go_text_template_files)
+	$(BUILDPACKAGE)
+text/template/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: text/template/check
+
+@go_include@ text/template/parse.lo.dep
+text/template/parse.lo.dep: $(go_text_template_parse_files)
+	$(BUILDDEPS)
+text/template/parse.lo: $(go_text_template_parse_files)
+	$(BUILDPACKAGE)
+text/template/parse/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: text/template/parse/check
+
+@go_include@ testing/iotest.lo.dep
+testing/iotest.lo.dep: $(go_testing_iotest_files)
+	$(BUILDDEPS)
+testing/iotest.lo: $(go_testing_iotest_files)
+	$(BUILDPACKAGE)
+testing/iotest/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: testing/iotest/check
+
+@go_include@ testing/quick.lo.dep
+testing/quick.lo.dep: $(go_testing_quick_files)
+	$(BUILDDEPS)
+testing/quick.lo: $(go_testing_quick_files)
+	$(BUILDPACKAGE)
+testing/quick/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: testing/quick/check
+
+@go_include@ unicode/utf16.lo.dep
+unicode/utf16.lo.dep: $(go_unicode_utf16_files)
+	$(BUILDDEPS)
+unicode/utf16.lo: $(go_unicode_utf16_files)
+	$(BUILDPACKAGE)
+unicode/utf16/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: unicode/utf16/check
+
+@go_include@ unicode/utf8.lo.dep
+unicode/utf8.lo.dep: $(go_unicode_utf8_files)
+	$(BUILDDEPS)
+unicode/utf8.lo: $(go_unicode_utf8_files)
+	$(BUILDPACKAGE)
+unicode/utf8/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: unicode/utf8/check
+
+@go_include@ syscall.lo.dep
+syscall.lo.dep: $(go_syscall_files)
+	$(BUILDDEPS)
+syscall.lo: $(go_syscall_files)
+	$(BUILDPACKAGE)
+syscall/errno.lo: go/syscall/errno.c
+	@$(MKDIR_P) syscall
+	$(LTCOMPILE) -c -o $@ $<
+syscall/signame.lo: go/syscall/signame.c
+	@$(MKDIR_P) syscall
+	$(LTCOMPILE) -c -o $@ $<
+syscall/wait.lo: go/syscall/wait.c
+	@$(MKDIR_P) syscall
+	$(LTCOMPILE) -c -o $@ $<
+syscall/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: syscall/check
+
+# How to build a .gox file from a .lo file.
+BUILDGOX = \
+	f=`echo $< | sed -e 's/.lo$$/.o/'`; \
+	$(OBJCOPY) -j .go_export $$f $@.tmp && mv -f $@.tmp $@
+
+bufio.gox: bufio.lo
+	$(BUILDGOX)
+bytes.gox: bytes.lo
+	$(BUILDGOX)
+crypto.gox: crypto.lo
+	$(BUILDGOX)
+encoding.gox: encoding.lo
+	$(BUILDGOX)
+errors.gox: errors.lo
+	$(BUILDGOX)
+expvar.gox: expvar.lo
+	$(BUILDGOX)
+flag.gox: flag.lo
+	$(BUILDGOX)
+fmt.gox: fmt.lo
+	$(BUILDGOX)
+hash.gox: hash.lo
+	$(BUILDGOX)
+html.gox: html.lo
+	$(BUILDGOX)
+image.gox: image.lo
+	$(BUILDGOX)
+io.gox: io.lo
+	$(BUILDGOX)
+log.gox: log.lo
+	$(BUILDGOX)
+math.gox: math.lo
+	$(BUILDGOX)
+mime.gox: mime.lo
+	$(BUILDGOX)
+net.gox: net.lo
+	$(BUILDGOX)
+os.gox: os.lo
+	$(BUILDGOX)
+path.gox: path.lo
+	$(BUILDGOX)
+reflect.gox: reflect-go.lo
+	$(BUILDGOX)
+regexp.gox: regexp.lo
+	$(BUILDGOX)
+runtime.gox: runtime-go.lo
+	$(BUILDGOX)
+sort.gox: sort.lo
+	$(BUILDGOX)
+strconv.gox: strconv.lo
+	$(BUILDGOX)
+strings.gox: strings.lo
+	$(BUILDGOX)
+sync.gox: sync.lo
+	$(BUILDGOX)
+syscall.gox: syscall.lo
+	$(BUILDGOX)
+testing.gox: testing.lo
+	$(BUILDGOX)
+time.gox: time-go.lo
+	$(BUILDGOX)
+unicode.gox: unicode.lo
+	$(BUILDGOX)
+
+archive/tar.gox: archive/tar.lo
+	$(BUILDGOX)
+archive/zip.gox: archive/zip.lo
+	$(BUILDGOX)
+
+compress/bzip2.gox: compress/bzip2.lo
+	$(BUILDGOX)
+compress/flate.gox: compress/flate.lo
+	$(BUILDGOX)
+compress/gzip.gox: compress/gzip.lo
+	$(BUILDGOX)
+compress/lzw.gox: compress/lzw.lo
+	$(BUILDGOX)
+compress/zlib.gox: compress/zlib.lo
+	$(BUILDGOX)
+
+container/heap.gox: container/heap.lo
+	$(BUILDGOX)
+container/list.gox: container/list.lo
+	$(BUILDGOX)
+container/ring.gox: container/ring.lo
+	$(BUILDGOX)
+
+crypto/aes.gox: crypto/aes.lo
+	$(BUILDGOX)
+crypto/cipher.gox: crypto/cipher.lo
+	$(BUILDGOX)
+crypto/des.gox: crypto/des.lo
+	$(BUILDGOX)
+crypto/dsa.gox: crypto/dsa.lo
+	$(BUILDGOX)
+crypto/ecdsa.gox: crypto/ecdsa.lo	
+	$(BUILDGOX)
+crypto/elliptic.gox: crypto/elliptic.lo
+	$(BUILDGOX)
+crypto/hmac.gox: crypto/hmac.lo
+	$(BUILDGOX)
+crypto/md5.gox: crypto/md5.lo
+	$(BUILDGOX)
+crypto/rand.gox: crypto/rand.lo
+	$(BUILDGOX)
+crypto/rc4.gox: crypto/rc4.lo
+	$(BUILDGOX)
+crypto/rsa.gox: crypto/rsa.lo
+	$(BUILDGOX)
+crypto/sha1.gox: crypto/sha1.lo
+	$(BUILDGOX)
+crypto/sha256.gox: crypto/sha256.lo
+	$(BUILDGOX)
+crypto/sha512.gox: crypto/sha512.lo
+	$(BUILDGOX)
+crypto/subtle.gox: crypto/subtle.lo
+	$(BUILDGOX)
+crypto/tls.gox: crypto/tls.lo
+	$(BUILDGOX)
+crypto/x509.gox: crypto/x509.lo
+	$(BUILDGOX)
+
+crypto/x509/pkix.gox: crypto/x509/pkix.lo
+	$(BUILDGOX)
+
+database/sql.gox: database/sql.lo
+	$(BUILDGOX)
+
+database/sql/driver.gox: database/sql/driver.lo
+	$(BUILDGOX)
+
+debug/dwarf.gox: debug/dwarf.lo
+	$(BUILDGOX)
+debug/elf.gox: debug/elf.lo
+	$(BUILDGOX)
+debug/gosym.gox: debug/gosym.lo
+	$(BUILDGOX)
+debug/macho.gox: debug/macho.lo
+	$(BUILDGOX)
+debug/pe.gox: debug/pe.lo
+	$(BUILDGOX)
+debug/plan9obj.gox: debug/plan9obj.lo
+	$(BUILDGOX)
+
+encoding/ascii85.gox: encoding/ascii85.lo
+	$(BUILDGOX)
+encoding/asn1.gox: encoding/asn1.lo
+	$(BUILDGOX)
+encoding/base32.gox: encoding/base32.lo
+	$(BUILDGOX)
+encoding/base64.gox: encoding/base64.lo
+	$(BUILDGOX)
+encoding/binary.gox: encoding/binary.lo
+	$(BUILDGOX)
+encoding/csv.gox: encoding/csv.lo
+	$(BUILDGOX)
+encoding/gob.gox: encoding/gob.lo
+	$(BUILDGOX)
+encoding/hex.gox: encoding/hex.lo
+	$(BUILDGOX)
+encoding/json.gox: encoding/json.lo
+	$(BUILDGOX)
+encoding/pem.gox: encoding/pem.lo
+	$(BUILDGOX)
+encoding/xml.gox: encoding/xml.lo
+	$(BUILDGOX)
+
+exp/proxy.gox: exp/proxy.lo
+	$(BUILDGOX)
+exp/terminal.gox: exp/terminal.lo
+	$(BUILDGOX)
+
+html/template.gox: html/template.lo
+	$(BUILDGOX)
+
+go/ast.gox: go/ast.lo
+	$(BUILDGOX)
+go/build.gox: go/build.lo
+	$(BUILDGOX)
+go/doc.gox: go/doc.lo
+	$(BUILDGOX)
+go/format.gox: go/format.lo
+	$(BUILDGOX)
+go/parser.gox: go/parser.lo
+	$(BUILDGOX)
+go/printer.gox: go/printer.lo
+	$(BUILDGOX)
+go/scanner.gox: go/scanner.lo
+	$(BUILDGOX)
+go/token.gox: go/token.lo
+	$(BUILDGOX)
+
+hash/adler32.gox: hash/adler32.lo
+	$(BUILDGOX)
+hash/crc32.gox: hash/crc32.lo
+	$(BUILDGOX)
+hash/crc64.gox: hash/crc64.lo
+	$(BUILDGOX)
+hash/fnv.gox: hash/fnv.lo
+	$(BUILDGOX)
+
+image/color.gox: image/color.lo
+	$(BUILDGOX)
+image/draw.gox: image/draw.lo
+	$(BUILDGOX)
+image/gif.gox: image/gif.lo
+	$(BUILDGOX)
+image/jpeg.gox: image/jpeg.lo
+	$(BUILDGOX)
+image/png.gox: image/png.lo
+	$(BUILDGOX)
+
+image/color/palette.gox: image/color/palette.lo
+	$(BUILDGOX)
+
+index/suffixarray.gox: index/suffixarray.lo
+	$(BUILDGOX)
+
+io/ioutil.gox: io/ioutil.lo
+	$(BUILDGOX)
+
+log/syslog.gox: log/syslog.lo
+	$(BUILDGOX)
+
+math/big.gox: math/big.lo
+	$(BUILDGOX)
+math/cmplx.gox: math/cmplx.lo
+	$(BUILDGOX)
+math/rand.gox: math/rand.lo
+	$(BUILDGOX)
+
+mime/multipart.gox: mime/multipart.lo
+	$(BUILDGOX)
+
+net/http.gox: net/http.lo
+	$(BUILDGOX)
+net/mail.gox: net/mail.lo
+	$(BUILDGOX)
+net/rpc.gox: net/rpc.lo
+	$(BUILDGOX)
+net/smtp.gox: net/smtp.lo
+	$(BUILDGOX)
+net/textproto.gox: net/textproto.lo
+	$(BUILDGOX)
+net/url.gox: net/url.lo
+	$(BUILDGOX)
+
+net/http/cgi.gox: net/http/cgi.lo
+	$(BUILDGOX)
+net/http/cookiejar.gox: net/http/cookiejar.lo
+	$(BUILDGOX)
+net/http/fcgi.gox: net/http/fcgi.lo
+	$(BUILDGOX)
+net/http/httptest.gox: net/http/httptest.lo
+	$(BUILDGOX)
+net/http/httputil.gox: net/http/httputil.lo
+	$(BUILDGOX)
+net/http/pprof.gox: net/http/pprof.lo
+	$(BUILDGOX)
+
+net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo
+	$(BUILDGOX)
+
+old/regexp.gox: old/regexp.lo
+	$(BUILDGOX)
+old/template.gox: old/template.lo
+	$(BUILDGOX)
+
+os/exec.gox: os/exec.lo
+	$(BUILDGOX)
+os/signal.gox: os/signal.lo
+	$(BUILDGOX)
+os/user.gox: os/user.lo
+	$(BUILDGOX)
+
+path/filepath.gox: path/filepath.lo
+	$(BUILDGOX)
+
+regexp/syntax.gox: regexp/syntax.lo
+	$(BUILDGOX)
+
+runtime/debug.gox: runtime/debug.lo
+	$(BUILDGOX)
+runtime/pprof.gox: runtime/pprof.lo
+	$(BUILDGOX)
+
+sync/atomic.gox: sync/atomic.lo
+	$(BUILDGOX)
+
+text/scanner.gox: text/scanner.lo
+	$(BUILDGOX)
+text/tabwriter.gox: text/tabwriter.lo
+	$(BUILDGOX)
+text/template.gox: text/template.lo
+	$(BUILDGOX)
+text/template/parse.gox: text/template/parse.lo
+	$(BUILDGOX)
+
+testing/iotest.gox: testing/iotest.lo
+	$(BUILDGOX)
+testing/quick.gox: testing/quick.lo
+	$(BUILDGOX)
+
+unicode/utf16.gox: unicode/utf16.lo
+	$(BUILDGOX)
+unicode/utf8.gox: unicode/utf8.lo
+	$(BUILDGOX)
+
+TEST_PACKAGES = \
+	bufio/check \
+	bytes/check \
+	errors/check \
+	expvar/check \
+	flag/check \
+	fmt/check \
+	html/check \
+	image/check \
+	io/check \
+	log/check \
+	math/check \
+	mime/check \
+	net/check \
+	os/check \
+	path/check \
+	reflect/check \
+	regexp/check \
+	runtime/check \
+	sort/check \
+	strconv/check \
+	strings/check \
+	sync/check \
+	syscall/check \
+	time/check \
+	unicode/check \
+	archive/tar/check \
+	archive/zip/check \
+	compress/bzip2/check \
+	compress/flate/check \
+	compress/gzip/check \
+	compress/lzw/check \
+	compress/zlib/check \
+	container/heap/check \
+	container/list/check \
+	container/ring/check \
+	crypto/aes/check \
+	crypto/cipher/check \
+	crypto/des/check \
+	crypto/dsa/check \
+	crypto/ecdsa/check \
+	crypto/elliptic/check \
+	crypto/hmac/check \
+	crypto/md5/check \
+	crypto/rand/check \
+	crypto/rc4/check \
+	crypto/rsa/check \
+	crypto/sha1/check \
+	crypto/sha256/check \
+	crypto/sha512/check \
+	crypto/subtle/check \
+	crypto/tls/check \
+	crypto/x509/check \
+	database/sql/check \
+	database/sql/driver/check \
+	debug/dwarf/check \
+	debug/elf/check \
+	debug/macho/check \
+	debug/pe/check \
+	debug/plan9obj/check \
+	encoding/ascii85/check \
+	encoding/asn1/check \
+	encoding/base32/check \
+	encoding/base64/check \
+	encoding/binary/check \
+	encoding/csv/check \
+	encoding/gob/check \
+	encoding/hex/check \
+	encoding/json/check \
+	encoding/pem/check \
+	encoding/xml/check \
+	exp/proxy/check \
+	exp/terminal/check \
+	html/template/check \
+	go/ast/check \
+	$(go_build_check_omitted_since_it_calls_6g) \
+	go/doc/check \
+	go/format/check \
+	go/parser/check \
+	go/printer/check \
+	go/scanner/check \
+	go/token/check \
+	hash/adler32/check \
+	hash/crc32/check \
+	hash/crc64/check \
+	hash/fnv/check \
+	image/color/check \
+	image/draw/check \
+	image/jpeg/check \
+	image/png/check \
+	index/suffixarray/check \
+	io/ioutil/check \
+	log/syslog/check \
+	math/big/check \
+	math/cmplx/check \
+	math/rand/check \
+	mime/multipart/check \
+	net/http/check \
+	net/http/cgi/check \
+	net/http/cookiejar/check \
+	net/http/fcgi/check \
+	net/http/httptest/check \
+	net/http/httputil/check \
+	net/mail/check \
+	net/rpc/check \
+	net/smtp/check \
+	net/textproto/check \
+	net/url/check \
+	net/rpc/jsonrpc/check \
+	old/regexp/check \
+	old/template/check \
+	os/exec/check \
+	os/signal/check \
+	os/user/check \
+	path/filepath/check \
+	regexp/syntax/check \
+	runtime/pprof/check \
+	sync/atomic/check \
+	text/scanner/check \
+	text/tabwriter/check \
+	text/template/check \
+	text/template/parse/check \
+	testing/quick/check \
+	unicode/utf16/check \
+	unicode/utf8/check
+
+check: check-tail
+check-recursive: check-head
+
+check-head:
+	@echo "Test Run By $${USER} on `date`" > libgo.head
+	@echo "Native configuration is $(host_triplet)" >> libgo.head
+	@echo >> libgo.head
+	@echo "		=== libgo tests ===" >> libgo.head
+	@echo >> libgo.head
+
+check-tail: check-recursive check-multi
+	@if test "$(USE_DEJAGNU)" = "yes"; then \
+	  exit 0; \
+	fi; \
+	lib=`${PWD_COMMAND} | sed -e 's,^.*/\([^/][^/]*\)$$,\1,'`; \
+	for dir in . $(MULTIDIRS); do \
+	  mv ../$${dir}/$${lib}/libgo.sum ../$${dir}/$${lib}/libgo.sum.sep; \
+	  mv ../$${dir}/$${lib}/libgo.log ../$${dir}/$${lib}/libgo.log.sep; \
+	done; \
+	mv libgo.head libgo.sum; \
+	cp libgo.sum libgo.log; \
+	echo "Schedule of variations:" >> libgo.sum; \
+	for dir in . $(MULTIDIRS); do \
+	  multidir=../$${dir}/$${lib}; \
+	  multivar=`cat $${multidir}/libgo.var`; \
+	  echo "    $${multivar}" >> libgo.sum; \
+	done; \
+	echo >> libgo.sum; \
+	pass=0; fail=0; untested=0; \
+	for dir in . $(MULTIDIRS); do \
+	  multidir=../$${dir}/$${lib}; \
+	  multivar=`cat $${multidir}/libgo.var`; \
+	  echo "Running target $${multivar}" >> libgo.sum; \
+	  echo "Running $(srcdir)/libgo.exp ..." >> libgo.sum; \
+	  cat $${multidir}/libgo.sum.sep >> libgo.sum; \
+	  cat $${multidir}/libgo.log.sep >> libgo.log; \
+	  if test -n "${MULTIDIRS}"; then \
+	    echo "		=== libgo Summary for $${multivar} ===" >> libgo.sum; \
+	    echo >> libgo.sum; \
+	  fi; \
+	  p=`grep -c PASS $${multidir}/libgo.sum.sep`; \
+	  pass=`expr $$pass + $$p`; \
+	  if test "$$p" -ne "0" && test -n "${MULTIDIRS}"; then \
+	    echo "# of expected passes		$$p" >> libgo.sum; \
+	  fi; \
+	  p=`grep -c FAIL $${multidir}/libgo.sum.sep`; \
+	  fail=`expr $$fail + $$p`; \
+	  if test "$$p" -ne "0" && test -n "${MULTIDIRS}"; then \
+	    echo "# of unexpected failures	$$p" >> libgo.sum; \
+	  fi; \
+	  p=`grep -c UNTESTED $${multidir}/libgo.sum.sep`; \
+	  untested=`expr $$untested + $$p`; \
+	  if test "$$p" -ne "0" && test -n "${MULTIDIRS}"; then \
+	    echo "# of untested testcases		$$p" >> libgo.sum; \
+	  fi; \
+	done; \
+	echo >> libgo.sum; \
+	echo "		=== libgo Summary ===" >> libgo.sum; \
+	echo >> libgo.sum; \
+	if test "$$pass" -ne "0"; then \
+	  echo "# of expected passes		$$pass" >> libgo.sum; \
+	fi; \
+	if test "$$fail" -ne "0"; then \
+	  echo "# of unexpected failures	$$fail" >> libgo.sum; \
+	fi; \
+	if test "$$untested" -ne "0"; then \
+	  echo "# of untested testcases		$$untested" >> libgo.sum; \
+	fi; \
+	echo `echo $(GOC) | sed -e 's/ .*//'`  `$(GOC) -v 2>&1 | grep " version" | sed -n -e 's/.* \(version.*$$\)/\1/p'` >> libgo.sum; \
+	echo >> libgo.log; \
+	echo "runtest completed at `date`" >> libgo.log; \
+	if test "$$fail" -ne "0"; then \
+	  status=1; \
+	else \
+	  status=0; \
+	fi; \
+	exit $$status
+
+check-am:
+	@rm -f libgo.sum libgo.log libgo.tail
+	@multivar="unix"; \
+	[ -z "$(MULTIFLAGS)" ] || multivar="$${multivar}/$(MULTIFLAGS)"; \
+	echo "$${multivar}" > libgo.var
+	@for f in $(TEST_PACKAGES); do \
+	   rm -f $$f-testsum $$f-testlog; \
+	 done
+	-@$(MAKE) -k $(TEST_PACKAGES)
+	@for f in $(TEST_PACKAGES); do \
+	  if test -f $$f-testsum; then \
+	    cat $$f-testsum >> libgo.sum; \
+	  fi; \
+	  if test -f $$f-testlog; then \
+	    cat $$f-testlog >> libgo.log; \
+	  fi; \
+	done
+
+check-multi:
+	$(MULTIDO) $(AM_MAKEFLAGS) DO=check-am multi-do # $(MAKE)
+
+bench:
+	-@$(MAKE) -k $(TEST_PACKAGES) GOBENCH=.
+
+MOSTLYCLEAN_FILES = libgo.head libgo.sum.sep libgo.log.sep
+
+mostlyclean-local:
+	find . -name '*.lo' -print | xargs $(LIBTOOL) --mode=clean rm -f
+	find . -name '*.$(OBJEXT)' -print | xargs rm -f
+	find . -name '*-testsum' -print | xargs rm -f
+	find . -name '*-testlog' -print | xargs rm -f
+
+CLEANFILES = *.go *.gox goc2c *.c s-version libgo.sum libgo.log
+
+clean-local:
+	find . -name '*.la' -print | xargs $(LIBTOOL) --mode=clean rm -f
+	find . -name '*.a' -print | xargs rm -f
diff --git a/third_party/gofrontend/libgo/Makefile.in b/third_party/gofrontend/libgo/Makefile.in
new file mode 100644
index 0000000..f42c8f9
--- /dev/null
+++ b/third_party/gofrontend/libgo/Makefile.in
@@ -0,0 +1,6116 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am -- Go library Makefile.
+
+# 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.
+
+# Process this file with autoreconf to produce Makefile.in.
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@GOC_IS_LLGO_TRUE@am__append_1 = libgo-llgo.la libgobegin-llgo.a
+@GOC_IS_LLGO_FALSE@am__append_2 = libgo.la libgobegin.a
+subdir = .
+DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/configure $(am__configure_deps) \
+	$(srcdir)/config.h.in $(srcdir)/../mkinstalldirs \
+	$(srcdir)/../depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
+	$(top_srcdir)/../config/lead-dot.m4 \
+	$(top_srcdir)/../config/multi.m4 \
+	$(top_srcdir)/../config/override.m4 \
+	$(top_srcdir)/../config/unwind_ipinfo.m4 \
+	$(top_srcdir)/config/go.m4 $(top_srcdir)/config/libtool.m4 \
+	$(top_srcdir)/config/ltoptions.m4 \
+	$(top_srcdir)/config/ltsugar.m4 \
+	$(top_srcdir)/config/ltversion.m4 \
+	$(top_srcdir)/config/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
+	"$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" \
+	"$(DESTDIR)$(toolexeclibgoarchivedir)" \
+	"$(DESTDIR)$(toolexeclibgocompressdir)" \
+	"$(DESTDIR)$(toolexeclibgocontainerdir)" \
+	"$(DESTDIR)$(toolexeclibgocryptodir)" \
+	"$(DESTDIR)$(toolexeclibgocryptox509dir)" \
+	"$(DESTDIR)$(toolexeclibgodatabasedir)" \
+	"$(DESTDIR)$(toolexeclibgodatabasesqldir)" \
+	"$(DESTDIR)$(toolexeclibgodebugdir)" \
+	"$(DESTDIR)$(toolexeclibgoencodingdir)" \
+	"$(DESTDIR)$(toolexeclibgoexpdir)" \
+	"$(DESTDIR)$(toolexeclibgogodir)" \
+	"$(DESTDIR)$(toolexeclibgohashdir)" \
+	"$(DESTDIR)$(toolexeclibgohtmldir)" \
+	"$(DESTDIR)$(toolexeclibgoimagedir)" \
+	"$(DESTDIR)$(toolexeclibgoimagecolordir)" \
+	"$(DESTDIR)$(toolexeclibgoindexdir)" \
+	"$(DESTDIR)$(toolexeclibgoiodir)" \
+	"$(DESTDIR)$(toolexeclibgologdir)" \
+	"$(DESTDIR)$(toolexeclibgomathdir)" \
+	"$(DESTDIR)$(toolexeclibgomimedir)" \
+	"$(DESTDIR)$(toolexeclibgonetdir)" \
+	"$(DESTDIR)$(toolexeclibgonethttpdir)" \
+	"$(DESTDIR)$(toolexeclibgonetrpcdir)" \
+	"$(DESTDIR)$(toolexeclibgoolddir)" \
+	"$(DESTDIR)$(toolexeclibgoosdir)" \
+	"$(DESTDIR)$(toolexeclibgopathdir)" \
+	"$(DESTDIR)$(toolexeclibgoregexpdir)" \
+	"$(DESTDIR)$(toolexeclibgoruntimedir)" \
+	"$(DESTDIR)$(toolexeclibgosyncdir)" \
+	"$(DESTDIR)$(toolexeclibgotestingdir)" \
+	"$(DESTDIR)$(toolexeclibgotextdir)" \
+	"$(DESTDIR)$(toolexeclibgotexttemplatedir)" \
+	"$(DESTDIR)$(toolexeclibgounicodedir)"
+LIBRARIES = $(toolexeclib_LIBRARIES)
+ARFLAGS = cru
+libgobegin_llgo_a_AR = $(AR) $(ARFLAGS)
+libgobegin_llgo_a_LIBADD =
+am_libgobegin_llgo_a_OBJECTS = go-main.$(OBJEXT)
+libgobegin_llgo_a_OBJECTS = $(am_libgobegin_llgo_a_OBJECTS)
+libgobegin_a_AR = $(AR) $(ARFLAGS)
+libgobegin_a_LIBADD =
+am_libgobegin_a_OBJECTS = go-main.$(OBJEXT)
+libgobegin_a_OBJECTS = $(am_libgobegin_a_OBJECTS)
+LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
+	encoding.lo errors.lo expvar.lo flag.lo fmt.lo hash.lo html.lo \
+	image.lo io.lo log.lo math.lo mime.lo net.lo os.lo path.lo \
+	reflect-go.lo reflect/makefunc.lo reflect/makefunc_ffi_c.lo \
+	regexp.lo runtime-go.lo sort.lo strconv.lo strings.lo \
+	strings/index.lo sync.lo syscall.lo syscall/errno.lo \
+	syscall/signame.lo syscall/wait.lo testing.lo time-go.lo \
+	unicode.lo archive/tar.lo archive/zip.lo compress/bzip2.lo \
+	compress/flate.lo compress/gzip.lo compress/lzw.lo \
+	compress/zlib.lo container/heap.lo container/list.lo \
+	container/ring.lo crypto/aes.lo crypto/cipher.lo crypto/des.lo \
+	crypto/dsa.lo crypto/ecdsa.lo crypto/elliptic.lo \
+	crypto/hmac.lo crypto/md5.lo crypto/rand.lo crypto/rc4.lo \
+	crypto/rsa.lo crypto/sha1.lo crypto/sha256.lo crypto/sha512.lo \
+	crypto/subtle.lo crypto/tls.lo crypto/x509.lo \
+	crypto/x509/pkix.lo database/sql.lo database/sql/driver.lo \
+	debug/dwarf.lo debug/elf.lo debug/gosym.lo debug/macho.lo \
+	debug/pe.lo debug/plan9obj.lo encoding/ascii85.lo \
+	encoding/asn1.lo encoding/base32.lo encoding/base64.lo \
+	encoding/binary.lo encoding/csv.lo encoding/gob.lo \
+	encoding/hex.lo encoding/json.lo encoding/pem.lo \
+	encoding/xml.lo exp/proxy.lo exp/terminal.lo html/template.lo \
+	go/ast.lo go/build.lo go/doc.lo go/format.lo go/parser.lo \
+	go/printer.lo go/scanner.lo go/token.lo hash/adler32.lo \
+	hash/crc32.lo hash/crc64.lo hash/fnv.lo net/http/cgi.lo \
+	net/http/cookiejar.lo net/http/fcgi.lo net/http/httptest.lo \
+	net/http/httputil.lo net/http/pprof.lo image/color.lo \
+	image/color/palette.lo image/draw.lo image/gif.lo \
+	image/jpeg.lo image/png.lo index/suffixarray.lo io/ioutil.lo \
+	log/syslog.lo log/syslog/syslog_c.lo math/big.lo math/cmplx.lo \
+	math/rand.lo mime/multipart.lo net/http.lo net/mail.lo \
+	net/rpc.lo net/smtp.lo net/textproto.lo net/url.lo \
+	old/regexp.lo old/template.lo os/exec.lo $(am__DEPENDENCIES_1) \
+	os/signal.lo os/user.lo path/filepath.lo regexp/syntax.lo \
+	net/rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
+	sync/atomic.lo sync/atomic_c.lo text/scanner.lo \
+	text/tabwriter.lo text/template.lo text/template/parse.lo \
+	testing/iotest.lo testing/quick.lo unicode/utf16.lo \
+	unicode/utf8.lo
+am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2) \
+	../libbacktrace/libbacktrace.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_3)
+@LIBGO_IS_LINUX_FALSE@am__objects_1 = lock_sema.lo thread-sema.lo
+@LIBGO_IS_LINUX_TRUE@am__objects_1 = lock_futex.lo thread-linux.lo
+@HAVE_SYS_MMAN_H_FALSE@am__objects_2 = mem_posix_memalign.lo
+@HAVE_SYS_MMAN_H_TRUE@am__objects_2 = mem.lo
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = netpoll_kqueue.lo
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_3 = netpoll_select.lo
+@LIBGO_IS_LINUX_TRUE@am__objects_3 = netpoll_epoll.lo
+@LIBGO_IS_RTEMS_TRUE@am__objects_4 = rtems-task-variable-add.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-none.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-bsd.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-bsd.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_5 = getncpu-solaris.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_5 = getncpu-irix.lo
+@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_5 =  \
+@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@	getncpu-bsd.lo
+@LIBGO_IS_LINUX_TRUE@am__objects_5 = getncpu-linux.lo
+am__objects_6 = go-append.lo go-assert.lo go-assert-interface.lo \
+	go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \
+	go-callers.lo go-can-convert-interface.lo go-cdiv.lo go-cgo.lo \
+	go-check-interface.lo go-construct-map.lo \
+	go-convert-interface.lo go-copy.lo go-defer.lo \
+	go-deferred-recover.lo go-eface-compare.lo \
+	go-eface-val-compare.lo go-ffi.lo go-fieldtrack.lo \
+	go-int-array-to-string.lo go-int-to-string.lo \
+	go-interface-compare.lo go-interface-eface-compare.lo \
+	go-interface-val-compare.lo go-make-slice.lo go-map-delete.lo \
+	go-map-index.lo go-map-len.lo go-map-range.lo go-matherr.lo \
+	go-memcmp.lo go-nanotime.lo go-now.lo go-new-map.lo go-new.lo \
+	go-nosys.lo go-panic.lo go-print.lo go-recover.lo \
+	go-reflect-call.lo go-reflect-map.lo go-rune.lo \
+	go-runtime-error.lo go-setenv.lo go-signal.lo go-strcmp.lo \
+	go-string-to-byte-array.lo go-string-to-int-array.lo \
+	go-strplus.lo go-strslice.lo go-traceback.lo \
+	go-type-complex.lo go-type-eface.lo go-type-error.lo \
+	go-type-float.lo go-type-identity.lo go-type-interface.lo \
+	go-type-string.lo go-typedesc-equal.lo go-unsafe-new.lo \
+	go-unsafe-newarray.lo go-unsafe-pointer.lo go-unwind.lo \
+	go-varargs.lo env_posix.lo heapdump.lo $(am__objects_1) \
+	mcache.lo mcentral.lo $(am__objects_2) mfixalloc.lo mgc0.lo \
+	mheap.lo msize.lo $(am__objects_3) panic.lo parfor.lo print.lo \
+	proc.lo runtime.lo signal_unix.lo thread.lo yield.lo \
+	$(am__objects_4) chan.lo cpuprof.lo go-iface.lo lfstack.lo \
+	malloc.lo map.lo mprof.lo netpoll.lo rdebug.lo reflect.lo \
+	runtime1.lo sema.lo sigqueue.lo string.lo time.lo \
+	$(am__objects_5)
+am_libgo_llgo_la_OBJECTS = $(am__objects_6)
+libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS)
+libgo_llgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(libgo_llgo_la_LDFLAGS) $(LDFLAGS) -o $@
+@GOC_IS_LLGO_TRUE@am_libgo_llgo_la_rpath = -rpath $(toolexeclibdir)
+libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_3)
+am_libgo_la_OBJECTS = $(am__objects_6)
+libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
+libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libgo_la_LDFLAGS) \
+	$(LDFLAGS) -o $@
+@GOC_IS_LLGO_FALSE@am_libgo_la_rpath = -rpath $(toolexeclibdir)
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/../depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libgobegin_llgo_a_SOURCES) $(libgobegin_a_SOURCES) \
+	$(libgo_llgo_la_SOURCES) $(libgo_la_SOURCES)
+MULTISRCTOP = 
+MULTIBUILDTOP = 
+MULTIDIRS = 
+MULTISUBDIR = 
+MULTIDO = true
+MULTICLEAN = true
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
+	$(toolexeclibgocompress_DATA) $(toolexeclibgocontainer_DATA) \
+	$(toolexeclibgocrypto_DATA) $(toolexeclibgocryptox509_DATA) \
+	$(toolexeclibgodatabase_DATA) $(toolexeclibgodatabasesql_DATA) \
+	$(toolexeclibgodebug_DATA) $(toolexeclibgoencoding_DATA) \
+	$(toolexeclibgoexp_DATA) $(toolexeclibgogo_DATA) \
+	$(toolexeclibgohash_DATA) $(toolexeclibgohtml_DATA) \
+	$(toolexeclibgoimage_DATA) $(toolexeclibgoimagecolor_DATA) \
+	$(toolexeclibgoindex_DATA) $(toolexeclibgoio_DATA) \
+	$(toolexeclibgolog_DATA) $(toolexeclibgomath_DATA) \
+	$(toolexeclibgomime_DATA) $(toolexeclibgonet_DATA) \
+	$(toolexeclibgonethttp_DATA) $(toolexeclibgonetrpc_DATA) \
+	$(toolexeclibgoold_DATA) $(toolexeclibgoos_DATA) \
+	$(toolexeclibgopath_DATA) $(toolexeclibgoregexp_DATA) \
+	$(toolexeclibgoruntime_DATA) $(toolexeclibgosync_DATA) \
+	$(toolexeclibgotesting_DATA) $(toolexeclibgotext_DATA) \
+	$(toolexeclibgotexttemplate_DATA) $(toolexeclibgounicode_DATA)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+	$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = testsuite
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GOARCH = @GOARCH@
+GOC = @GOC@
+GOCFLAGS = $(CFLAGS)
+GOOS = @GOOS@
+GO_LIBCALL_OS_ARCH_FILE = @GO_LIBCALL_OS_ARCH_FILE@
+GO_LIBCALL_OS_FILE = @GO_LIBCALL_OS_FILE@
+GO_SYSCALL_OS_ARCH_FILE = @GO_SYSCALL_OS_ARCH_FILE@
+GO_SYSCALL_OS_FILE = @GO_SYSCALL_OS_FILE@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBATOMIC = @LIBATOMIC@
+LIBFFI = @LIBFFI@
+LIBFFIINCS = @LIBFFIINCS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MATH_FLAG = @MATH_FLAG@
+MATH_LIBS = @MATH_LIBS@
+MKDIR_P = @MKDIR_P@
+NET_LIBS = @NET_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJCOPY = @OBJCOPY@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OSCFLAGS = @OSCFLAGS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SIZEOF_STRUCT_EPOLL_EVENT = @SIZEOF_STRUCT_EPOLL_EVENT@
+SPLIT_STACK = @SPLIT_STACK@
+STRINGOPS_FLAG = @STRINGOPS_FLAG@
+STRIP = @STRIP@
+STRUCT_EPOLL_EVENT_FD_OFFSET = @STRUCT_EPOLL_EVENT_FD_OFFSET@
+USE_DEJAGNU = @USE_DEJAGNU@
+VERSION = @VERSION@
+WARN_FLAGS = @WARN_FLAGS@
+WERROR = @WERROR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
+exec_prefix = @exec_prefix@
+glibgo_toolexecdir = @glibgo_toolexecdir@
+glibgo_toolexeclibdir = @glibgo_toolexeclibdir@
+go_include = @go_include@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libtool_VERSION = @libtool_VERSION@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+nover_glibgo_toolexeclibdir = @nover_glibgo_toolexeclibdir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# Go support.
+SUFFIXES = .c .go .gox .o .obj .lo .a
+@LIBGO_IS_RTEMS_TRUE@subdirs = testsuite
+SUBDIRS = ${subdirs}
+gcc_version := $(shell $(GOC) -dumpversion)
+MAINT_CHARSET = latin1
+mkinstalldirs = $(SHELL) $(toplevel_srcdir)/mkinstalldirs
+PWD_COMMAND = $${PWDCMD-pwd}
+STAMP = echo timestamp >
+toolexecdir = $(glibgo_toolexecdir)
+toolexeclibdir = $(glibgo_toolexeclibdir)
+toolexeclibgodir = $(nover_glibgo_toolexeclibdir)/go/$(gcc_version)/$(target_alias)
+WARN_CFLAGS = $(WARN_FLAGS) $(WERROR)
+
+# -I/-D flags to pass when compiling.
+AM_CPPFLAGS = -I $(srcdir)/runtime $(LIBFFIINCS) $(PTHREAD_CFLAGS)
+ACLOCAL_AMFLAGS = -I ./config -I ../config
+AM_CFLAGS = -fexceptions -fnon-call-exceptions -fplan9-extensions \
+	$(SPLIT_STACK) $(WARN_CFLAGS) \
+	$(STRINGOPS_FLAG) $(OSCFLAGS) \
+	-I $(srcdir)/../libgcc -I $(srcdir)/../libbacktrace \
+	-I $(MULTIBUILDTOP)../../gcc/include
+
+@USING_SPLIT_STACK_TRUE@AM_LDFLAGS = -XCClinker $(SPLIT_STACK)
+
+# Multilib support.
+MAKEOVERRIDES = 
+
+# Work around what appears to be a GNU make  handling MAKEFLAGS
+# values defined in terms of make variables, as is the case for CC and
+# friends when we are called from the top level Makefile.
+AM_MAKEFLAGS = \
+	"AR_FLAGS=$(AR_FLAGS)" \
+	"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+	"CC_FOR_TARGET=$(CC_FOR_TARGET)" \
+	"CFLAGS=$(CFLAGS)" \
+	"CXXFLAGS=$(CXXFLAGS)" \
+	"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+	"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+	"GOC_FOR_TARGET=$(GOC_FOR_TARGET)" \
+	"GOC=$(GOC)" \
+	"GOCFLAGS=$(GOCFLAGS)" \
+	"INSTALL=$(INSTALL)" \
+	"INSTALL_DATA=$(INSTALL_DATA)" \
+	"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+	"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+	"LDFLAGS=$(LDFLAGS)" \
+	"LIBCFLAGS=$(LIBCFLAGS)" \
+	"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+	"MAKE=$(MAKE)" \
+	"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+	"PICFLAG=$(PICFLAG)" \
+	"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+	"SHELL=$(SHELL)" \
+	"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+	"exec_prefix=$(exec_prefix)" \
+	"infodir=$(infodir)" \
+	"libdir=$(libdir)" \
+	"includedir=$(includedir)" \
+	"prefix=$(prefix)" \
+	"tooldir=$(tooldir)" \
+	"gxx_include_dir=$(gxx_include_dir)" \
+	"AR=$(AR)" \
+	"AS=$(AS)" \
+	"LD=$(LD)" \
+	"RANLIB=$(RANLIB)" \
+	"NM=$(NM)" \
+	"NM_FOR_BUILD=$(NM_FOR_BUILD)" \
+	"NM_FOR_TARGET=$(NM_FOR_TARGET)" \
+	"DESTDIR=$(DESTDIR)" \
+	"WERROR=$(WERROR)"
+
+
+# Subdir rules rely on $(FLAGS_TO_PASS)
+FLAGS_TO_PASS = $(AM_MAKEFLAGS)
+@GOC_IS_LLGO_FALSE@toolexeclib_LTLIBRARIES = libgo.la
+@GOC_IS_LLGO_TRUE@toolexeclib_LTLIBRARIES = libgo-llgo.la
+@GOC_IS_LLGO_FALSE@toolexeclib_LIBRARIES = libgobegin.a
+@GOC_IS_LLGO_TRUE@toolexeclib_LIBRARIES = libgobegin-llgo.a
+toolexeclibgo_DATA = \
+	bufio.gox \
+	bytes.gox \
+	crypto.gox \
+	encoding.gox \
+	errors.gox \
+	expvar.gox \
+	flag.gox \
+	fmt.gox \
+	hash.gox \
+	html.gox \
+	image.gox \
+	io.gox \
+	log.gox \
+	math.gox \
+	mime.gox \
+	net.gox \
+	os.gox \
+	path.gox \
+	reflect.gox \
+	regexp.gox \
+	runtime.gox \
+	sort.gox \
+	strconv.gox \
+	strings.gox \
+	sync.gox \
+	syscall.gox \
+	testing.gox \
+	time.gox \
+	unicode.gox
+
+toolexeclibgoarchivedir = $(toolexeclibgodir)/archive
+toolexeclibgoarchive_DATA = \
+	archive/tar.gox \
+	archive/zip.gox
+
+toolexeclibgocompressdir = $(toolexeclibgodir)/compress
+toolexeclibgocompress_DATA = \
+	compress/bzip2.gox \
+	compress/flate.gox \
+	compress/gzip.gox \
+	compress/lzw.gox \
+	compress/zlib.gox
+
+toolexeclibgocontainerdir = $(toolexeclibgodir)/container
+toolexeclibgocontainer_DATA = \
+	container/heap.gox \
+	container/list.gox \
+	container/ring.gox
+
+toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
+toolexeclibgocrypto_DATA = \
+	crypto/aes.gox \
+	crypto/cipher.gox \
+	crypto/des.gox \
+	crypto/dsa.gox \
+	crypto/ecdsa.gox \
+	crypto/elliptic.gox \
+	crypto/hmac.gox \
+	crypto/md5.gox \
+	crypto/rand.gox \
+	crypto/rc4.gox \
+	crypto/rsa.gox \
+	crypto/sha1.gox \
+	crypto/sha256.gox \
+	crypto/sha512.gox \
+	crypto/subtle.gox \
+	crypto/tls.gox \
+	crypto/x509.gox
+
+toolexeclibgocryptox509dir = $(toolexeclibgocryptodir)/x509
+toolexeclibgocryptox509_DATA = \
+	crypto/x509/pkix.gox
+
+toolexeclibgodatabasedir = $(toolexeclibgodir)/database
+toolexeclibgodatabase_DATA = \
+	database/sql.gox
+
+toolexeclibgodatabasesqldir = $(toolexeclibgodatabasedir)/sql
+toolexeclibgodatabasesql_DATA = \
+	database/sql/driver.gox
+
+toolexeclibgodebugdir = $(toolexeclibgodir)/debug
+toolexeclibgodebug_DATA = \
+	debug/dwarf.gox \
+	debug/elf.gox \
+	debug/gosym.gox \
+	debug/macho.gox \
+	debug/pe.gox \
+	debug/plan9obj.gox
+
+toolexeclibgoencodingdir = $(toolexeclibgodir)/encoding
+toolexeclibgoencoding_DATA = \
+	encoding/ascii85.gox \
+	encoding/asn1.gox \
+	encoding/base32.gox \
+	encoding/base64.gox \
+	encoding/binary.gox \
+	encoding/csv.gox \
+	encoding/gob.gox \
+	encoding/hex.gox \
+	encoding/json.gox \
+	encoding/pem.gox \
+	encoding/xml.gox
+
+toolexeclibgoexpdir = $(toolexeclibgodir)/exp
+toolexeclibgoexp_DATA = \
+	exp/proxy.gox \
+	exp/terminal.gox
+
+toolexeclibgogodir = $(toolexeclibgodir)/go
+toolexeclibgogo_DATA = \
+	go/ast.gox \
+	go/build.gox \
+	go/doc.gox \
+	go/format.gox \
+	go/parser.gox \
+	go/printer.gox \
+	go/scanner.gox \
+	go/token.gox
+
+toolexeclibgohashdir = $(toolexeclibgodir)/hash
+toolexeclibgohash_DATA = \
+	hash/adler32.gox \
+	hash/crc32.gox \
+	hash/crc64.gox \
+	hash/fnv.gox
+
+toolexeclibgohtmldir = $(toolexeclibgodir)/html
+toolexeclibgohtml_DATA = \
+	html/template.gox
+
+toolexeclibgoimagedir = $(toolexeclibgodir)/image
+toolexeclibgoimage_DATA = \
+	image/color.gox \
+	image/draw.gox \
+	image/gif.gox \
+	image/jpeg.gox \
+	image/png.gox
+
+toolexeclibgoimagecolordir = $(toolexeclibgoimagedir)/color
+toolexeclibgoimagecolor_DATA = \
+	image/color/palette.gox
+
+toolexeclibgoindexdir = $(toolexeclibgodir)/index
+toolexeclibgoindex_DATA = \
+	index/suffixarray.gox
+
+toolexeclibgoiodir = $(toolexeclibgodir)/io
+toolexeclibgoio_DATA = \
+	io/ioutil.gox
+
+toolexeclibgologdir = $(toolexeclibgodir)/log
+toolexeclibgolog_DATA = \
+	log/syslog.gox
+
+toolexeclibgomathdir = $(toolexeclibgodir)/math
+toolexeclibgomath_DATA = \
+	math/big.gox \
+	math/cmplx.gox \
+	math/rand.gox
+
+toolexeclibgomimedir = $(toolexeclibgodir)/mime
+toolexeclibgomime_DATA = \
+	mime/multipart.gox
+
+toolexeclibgonetdir = $(toolexeclibgodir)/net
+toolexeclibgonet_DATA = \
+	net/http.gox \
+	net/mail.gox \
+	net/rpc.gox \
+	net/smtp.gox \
+	net/textproto.gox \
+	net/url.gox
+
+toolexeclibgonethttpdir = $(toolexeclibgonetdir)/http
+toolexeclibgonethttp_DATA = \
+	net/http/cgi.gox \
+	net/http/cookiejar.gox \
+	net/http/fcgi.gox \
+	net/http/httptest.gox \
+	net/http/httputil.gox \
+	net/http/pprof.gox
+
+toolexeclibgonetrpcdir = $(toolexeclibgonetdir)/rpc
+toolexeclibgonetrpc_DATA = \
+	net/rpc/jsonrpc.gox
+
+toolexeclibgoolddir = $(toolexeclibgodir)/old
+toolexeclibgoold_DATA = \
+	old/regexp.gox \
+	old/template.gox
+
+toolexeclibgoosdir = $(toolexeclibgodir)/os
+toolexeclibgoos_DATA = \
+	os/exec.gox \
+	os/signal.gox \
+	os/user.gox
+
+toolexeclibgopathdir = $(toolexeclibgodir)/path
+toolexeclibgopath_DATA = \
+	path/filepath.gox
+
+toolexeclibgoregexpdir = $(toolexeclibgodir)/regexp
+toolexeclibgoregexp_DATA = \
+	regexp/syntax.gox
+
+toolexeclibgoruntimedir = $(toolexeclibgodir)/runtime
+toolexeclibgoruntime_DATA = \
+	runtime/debug.gox \
+	runtime/pprof.gox
+
+toolexeclibgosyncdir = $(toolexeclibgodir)/sync
+toolexeclibgosync_DATA = \
+	sync/atomic.gox
+
+toolexeclibgotestingdir = $(toolexeclibgodir)/testing
+toolexeclibgotesting_DATA = \
+	testing/iotest.gox \
+	testing/quick.gox
+
+toolexeclibgotextdir = $(toolexeclibgodir)/text
+toolexeclibgotext_DATA = \
+	text/scanner.gox \
+	text/tabwriter.gox \
+	text/template.gox
+
+toolexeclibgotexttemplatedir = $(toolexeclibgotextdir)/template
+toolexeclibgotexttemplate_DATA = \
+	text/template/parse.gox
+
+toolexeclibgounicodedir = $(toolexeclibgodir)/unicode
+toolexeclibgounicode_DATA = \
+	unicode/utf16.gox \
+	unicode/utf8.gox
+
+@HAVE_SYS_MMAN_H_FALSE@runtime_mem_file = runtime/mem_posix_memalign.c
+@HAVE_SYS_MMAN_H_TRUE@runtime_mem_file = runtime/mem.c
+@LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file = 
+@LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
+@LIBGO_IS_LINUX_FALSE@runtime_lock_files = runtime/lock_sema.c runtime/thread-sema.c
+@LIBGO_IS_LINUX_TRUE@runtime_lock_files = runtime/lock_futex.c runtime/thread-linux.c
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-none.c
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@runtime_getncpu_file = runtime/getncpu-solaris.c
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_getncpu_file = runtime/getncpu-irix.c
+@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
+@LIBGO_IS_LINUX_TRUE@runtime_getncpu_file = runtime/getncpu-linux.c
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_netpoll_files = runtime/netpoll_kqueue.c
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@runtime_netpoll_files = runtime/netpoll_select.c
+@LIBGO_IS_LINUX_TRUE@runtime_netpoll_files = runtime/netpoll_epoll.c
+runtime_files = \
+	runtime/go-append.c \
+	runtime/go-assert.c \
+	runtime/go-assert-interface.c \
+	runtime/go-byte-array-to-string.c \
+	runtime/go-breakpoint.c \
+	runtime/go-caller.c \
+	runtime/go-callers.c \
+	runtime/go-can-convert-interface.c \
+	runtime/go-cdiv.c \
+	runtime/go-cgo.c \
+	runtime/go-check-interface.c \
+	runtime/go-construct-map.c \
+	runtime/go-convert-interface.c \
+	runtime/go-copy.c \
+	runtime/go-defer.c \
+	runtime/go-deferred-recover.c \
+	runtime/go-eface-compare.c \
+	runtime/go-eface-val-compare.c \
+	runtime/go-ffi.c \
+	runtime/go-fieldtrack.c \
+	runtime/go-int-array-to-string.c \
+	runtime/go-int-to-string.c \
+	runtime/go-interface-compare.c \
+	runtime/go-interface-eface-compare.c \
+	runtime/go-interface-val-compare.c \
+	runtime/go-make-slice.c \
+	runtime/go-map-delete.c \
+	runtime/go-map-index.c \
+	runtime/go-map-len.c \
+	runtime/go-map-range.c \
+	runtime/go-matherr.c \
+	runtime/go-memcmp.c \
+	runtime/go-nanotime.c \
+	runtime/go-now.c \
+	runtime/go-new-map.c \
+	runtime/go-new.c \
+	runtime/go-nosys.c \
+	runtime/go-panic.c \
+	runtime/go-print.c \
+	runtime/go-recover.c \
+	runtime/go-reflect-call.c \
+	runtime/go-reflect-map.c \
+	runtime/go-rune.c \
+	runtime/go-runtime-error.c \
+	runtime/go-setenv.c \
+	runtime/go-signal.c \
+	runtime/go-strcmp.c \
+	runtime/go-string-to-byte-array.c \
+	runtime/go-string-to-int-array.c \
+	runtime/go-strplus.c \
+	runtime/go-strslice.c \
+	runtime/go-traceback.c \
+	runtime/go-type-complex.c \
+	runtime/go-type-eface.c \
+	runtime/go-type-error.c \
+	runtime/go-type-float.c \
+	runtime/go-type-identity.c \
+	runtime/go-type-interface.c \
+	runtime/go-type-string.c \
+	runtime/go-typedesc-equal.c \
+	runtime/go-unsafe-new.c \
+	runtime/go-unsafe-newarray.c \
+	runtime/go-unsafe-pointer.c \
+	runtime/go-unwind.c \
+	runtime/go-varargs.c \
+	runtime/env_posix.c \
+	runtime/heapdump.c \
+	$(runtime_lock_files) \
+	runtime/mcache.c \
+	runtime/mcentral.c \
+	$(runtime_mem_file) \
+	runtime/mfixalloc.c \
+	runtime/mgc0.c \
+	runtime/mheap.c \
+	runtime/msize.c \
+	$(runtime_netpoll_files) \
+	runtime/panic.c \
+	runtime/parfor.c \
+	runtime/print.c \
+	runtime/proc.c \
+	runtime/runtime.c \
+	runtime/signal_unix.c \
+	runtime/thread.c \
+	runtime/yield.c \
+	$(rtems_task_variable_add_file) \
+	chan.c \
+	cpuprof.c \
+	go-iface.c \
+	lfstack.c \
+	malloc.c \
+	map.c \
+	mprof.c \
+	netpoll.c \
+	rdebug.c \
+	reflect.c \
+	runtime1.c \
+	sema.c \
+	sigqueue.c \
+	string.c \
+	time.c \
+	$(runtime_getncpu_file)
+
+go_bufio_files = \
+	go/bufio/bufio.go \
+	go/bufio/scan.go
+
+go_bytes_files = \
+	go/bytes/buffer.go \
+	go/bytes/bytes.go \
+	go/bytes/bytes_decl.go \
+	go/bytes/reader.go
+
+go_bytes_c_files = \
+	go/bytes/indexbyte.c
+
+go_crypto_files = \
+	go/crypto/crypto.go
+
+go_encoding_files = \
+	go/encoding/encoding.go
+
+go_errors_files = \
+	go/errors/errors.go
+
+go_expvar_files = \
+	go/expvar/expvar.go
+
+go_flag_files = \
+	go/flag/flag.go
+
+go_fmt_files = \
+	go/fmt/doc.go \
+	go/fmt/format.go \
+	go/fmt/print.go \
+	go/fmt/scan.go
+
+go_hash_files = \
+	go/hash/hash.go
+
+go_html_files = \
+	go/html/entity.go \
+	go/html/escape.go
+
+go_image_files = \
+	go/image/format.go \
+	go/image/geom.go \
+	go/image/image.go \
+	go/image/names.go \
+	go/image/ycbcr.go
+
+go_io_files = \
+	go/io/multi.go \
+	go/io/io.go \
+	go/io/pipe.go
+
+go_log_files = \
+	go/log/log.go
+
+go_math_files = \
+	go/math/abs.go \
+	go/math/acosh.go \
+	go/math/asin.go \
+	go/math/asinh.go \
+	go/math/atan.go \
+	go/math/atanh.go \
+	go/math/atan2.go \
+	go/math/bits.go \
+	go/math/cbrt.go \
+	go/math/const.go \
+	go/math/copysign.go \
+	go/math/dim.go \
+	go/math/erf.go \
+	go/math/exp.go \
+	go/math/expm1.go \
+	go/math/floor.go \
+	go/math/frexp.go \
+	go/math/gamma.go \
+	go/math/hypot.go \
+	go/math/j0.go \
+	go/math/j1.go \
+	go/math/jn.go \
+	go/math/ldexp.go \
+	go/math/lgamma.go \
+	go/math/log.go \
+	go/math/log1p.go \
+	go/math/log10.go \
+	go/math/logb.go \
+	go/math/mod.go \
+	go/math/modf.go \
+	go/math/nextafter.go \
+	go/math/pow.go \
+	go/math/pow10.go \
+	go/math/remainder.go \
+	go/math/signbit.go \
+	go/math/sin.go \
+	go/math/sincos.go \
+	go/math/sinh.go \
+	go/math/sqrt.go \
+	go/math/tan.go \
+	go/math/tanh.go \
+	go/math/unsafe.go
+
+go_mime_files = \
+	go/mime/grammar.go \
+	go/mime/mediatype.go \
+	go/mime/type.go \
+	go/mime/type_unix.go
+
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_netbsd.go
+@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_cgo_file = go/net/cgo_linux.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cgo_file = go/net/cgo_linux.go
+@LIBGO_IS_LINUX_TRUE@go_net_cgo_file = go/net/cgo_linux.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
+@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sock_file = go/net/sock_solaris.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sock_file = go/net/sock_linux.go
+@LIBGO_IS_LINUX_TRUE@go_net_sock_file = go/net/sock_linux.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go
+@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockopt_file = go/net/sockopt_solaris.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockopt_file = go/net/sockopt_linux.go
+@LIBGO_IS_LINUX_TRUE@go_net_sockopt_file = go/net/sockopt_linux.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
+@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_stub.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
+@LIBGO_IS_LINUX_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
+@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go
+@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_dragonfly.go
+@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_freebsd.go
+@LIBGO_IS_LINUX_TRUE@go_net_sendfile_file = go/net/sendfile_linux.go
+@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_stub.go
+@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_dragonfly.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@go_net_interface_file = go/net/interface_netbsd.go
+@LIBGO_IS_LINUX_TRUE@go_net_interface_file = go/net/interface_linux.go
+@LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sys_cloexec.go
+@LIBGO_IS_LINUX_TRUE@go_net_cloexec_file = go/net/sock_cloexec.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_dragonfly.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_solaris.go
+@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_OPENBSD_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go
+@LIBGO_IS_OPENBSD_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_openbsd.go
+go_net_files = \
+	go/net/cgo_unix.go \
+	$(go_net_cgo_file) \
+	$(go_net_cloexec_file) \
+	go/net/dial.go \
+	go/net/dnsclient.go \
+	go/net/dnsclient_unix.go \
+	go/net/dnsconfig_unix.go \
+	go/net/dnsmsg.go \
+	go/net/fd_mutex.go \
+	go/net/fd_unix.go \
+	go/net/file_unix.go \
+	go/net/hosts.go \
+	go/net/interface.go \
+	$(go_net_interface_file) \
+	go/net/ip.go \
+	go/net/iprawsock.go \
+	go/net/iprawsock_posix.go \
+	go/net/ipsock.go \
+	go/net/ipsock_posix.go \
+	go/net/lookup.go \
+	go/net/lookup_unix.go \
+	go/net/mac.go \
+	go/net/net.go \
+	go/net/parse.go \
+	go/net/pipe.go \
+	go/net/fd_poll_runtime.go \
+	go/net/port.go \
+	go/net/port_unix.go \
+	go/net/race0.go \
+	$(go_net_sendfile_file) \
+	go/net/singleflight.go \
+	go/net/sock_posix.go \
+	$(go_net_sock_file) \
+	go/net/sockopt_posix.go \
+	$(go_net_sockopt_file) \
+	$(go_net_sockoptip_file) \
+	go/net/tcpsock.go \
+	go/net/tcpsock_posix.go \
+	go/net/tcpsockopt_posix.go \
+	$(go_net_tcpsockopt_file) \
+	go/net/udpsock.go \
+	go/net/udpsock_posix.go \
+	go/net/unixsock.go \
+	go/net/unixsock_posix.go
+
+@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@go_os_dir_file = go/os/dir_regfile.go
+@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@go_os_dir_file = go/os/dir_largefile.go
+@LIBGO_IS_386_TRUE@@LIBGO_IS_SOLARIS_TRUE@go_os_dir_file = go/os/dir_largefile.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_dir_file = go/os/dir_regfile.go
+@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_os_dir_file = go/os/dir_largefile.go
+@LIBGO_IS_DARWIN_FALSE@go_os_getwd_file = 
+@LIBGO_IS_DARWIN_TRUE@go_os_getwd_file = go/os/getwd_darwin.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_sys_file = go/os/sys_bsd.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_os_sys_file = go/os/sys_uname.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_sys_file = go/os/sys_uname.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_os_sys_file = go/os/sys_uname.go
+@LIBGO_IS_LINUX_TRUE@go_os_sys_file = go/os/sys_linux.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@go_os_cloexec_file = go/os/sys_unix.go
+@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_FREEBSD_FALSE@go_os_cloexec_file = go/os/sys_darwin.go
+@LIBGO_IS_FREEBSD_TRUE@go_os_cloexec_file = go/os/sys_freebsd.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_dragonfly.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atimespec.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atimespec.go
+@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atimespec.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_OPENBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atim.go
+@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atim.go
+@LIBGO_IS_SOLARIS_TRUE@go_os_stat_file = go/os/stat_solaris.go
+@LIBGO_IS_LINUX_FALSE@go_os_pipe_file = go/os/pipe_bsd.go
+@LIBGO_IS_LINUX_TRUE@go_os_pipe_file = go/os/pipe_linux.go
+go_os_files = \
+	$(go_os_dir_file) \
+	go/os/dir.go \
+	go/os/doc.go \
+	go/os/env.go \
+	go/os/error.go \
+	go/os/error_unix.go \
+	go/os/exec.go \
+	go/os/exec_posix.go \
+	go/os/exec_unix.go \
+	go/os/file.go \
+	go/os/file_posix.go \
+	go/os/file_unix.go \
+	go/os/getwd.go \
+	$(go_os_getwd_file) \
+	go/os/path.go \
+	go/os/path_unix.go \
+	$(go_os_pipe_file) \
+	go/os/proc.go \
+	$(go_os_stat_file) \
+	go/os/str.go \
+	$(go_os_sys_file) \
+	$(go_os_cloexec_file) \
+	go/os/types.go \
+	go/os/types_notwin.go
+
+go_path_files = \
+	go/path/match.go \
+	go/path/path.go
+
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_FALSE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = 
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = \
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefuncgo_s390x.go \
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefuncgo_s390.go
+
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = \
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390_TRUE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefuncgo_s390.go
+
+@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = \
+@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefuncgo_386.go
+
+@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_file = \
+@LIBGO_IS_X86_64_TRUE@	go/reflect/makefuncgo_amd64.go
+
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_FALSE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_FALSE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefunc_dummy.c
+
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefunc_s390.c
+
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
+@LIBGO_IS_386_FALSE@@LIBGO_IS_S390_TRUE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefunc_s390.c
+
+@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
+@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefunc_386.S
+
+@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_s_file = \
+@LIBGO_IS_X86_64_TRUE@	go/reflect/makefunc_amd64.S
+
+go_reflect_files = \
+	go/reflect/deepequal.go \
+	go/reflect/makefunc.go \
+	go/reflect/makefunc_ffi.go \
+	$(go_reflect_makefunc_file) \
+	go/reflect/type.go \
+	go/reflect/value.go
+
+go_reflect_makefunc_c_file = \
+	go/reflect/makefunc_ffi_c.c
+
+go_regexp_files = \
+	go/regexp/exec.go \
+	go/regexp/onepass.go \
+	go/regexp/regexp.go
+
+go_net_rpc_files = \
+	go/net/rpc/client.go \
+	go/net/rpc/debug.go \
+	go/net/rpc/server.go
+
+go_runtime_files = \
+	go/runtime/compiler.go \
+	go/runtime/debug.go \
+	go/runtime/error.go \
+	go/runtime/extern.go \
+	go/runtime/mem.go \
+	go/runtime/softfloat64.go \
+	go/runtime/type.go \
+	version.go
+
+go_sort_files = \
+	go/sort/search.go \
+	go/sort/sort.go
+
+go_strconv_files = \
+	go/strconv/atob.go \
+	go/strconv/atof.go \
+	go/strconv/atoi.go \
+	go/strconv/decimal.go \
+	go/strconv/extfloat.go \
+	go/strconv/ftoa.go \
+	go/strconv/isprint.go \
+	go/strconv/itoa.go \
+	go/strconv/quote.go
+
+go_strings_files = \
+	go/strings/reader.go \
+	go/strings/replace.go \
+	go/strings/search.go \
+	go/strings/strings.go \
+	go/strings/strings_decl.go
+
+go_strings_c_files = \
+	go/strings/indexbyte.c
+
+go_sync_files = \
+	go/sync/cond.go \
+	go/sync/mutex.go \
+	go/sync/once.go \
+	go/sync/pool.go \
+	go/sync/race0.go \
+	go/sync/runtime.go \
+	go/sync/rwmutex.go \
+	go/sync/waitgroup.go
+
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_syslog_file = go/log/syslog/syslog_unix.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_syslog_file = go/log/syslog/syslog_libc.go
+@LIBGO_IS_SOLARIS_TRUE@go_syslog_file = go/log/syslog/syslog_libc.go
+go_log_syslog_files = \
+	go/log/syslog/syslog.go \
+	$(go_syslog_file)
+
+go_syslog_c_files = \
+	go/log/syslog/syslog_c.c
+
+go_testing_files = \
+	go/testing/allocs.go \
+	go/testing/benchmark.go \
+	go/testing/cover.go \
+	go/testing/example.go \
+	go/testing/testing.go
+
+go_time_files = \
+	go/time/format.go \
+	go/time/sleep.go \
+	go/time/sys_unix.go \
+	go/time/tick.go \
+	go/time/time.go \
+	go/time/zoneinfo.go \
+	go/time/zoneinfo_read.go \
+	go/time/zoneinfo_unix.go
+
+go_unicode_files = \
+	go/unicode/casetables.go \
+	go/unicode/digit.go \
+	go/unicode/graphic.go \
+	go/unicode/letter.go \
+	go/unicode/tables.go
+
+@LIBGO_IS_DARWIN_TRUE@archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+@LIBGO_IS_FREEBSD_TRUE@archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+@LIBGO_IS_LINUX_TRUE@archive_tar_atim_file = go/archive/tar/stat_atim.go
+@LIBGO_IS_NETBSD_TRUE@archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+@LIBGO_IS_OPENBSD_TRUE@archive_tar_atim_file = go/archive/tar/stat_atim.go
+@LIBGO_IS_SOLARIS_TRUE@archive_tar_atim_file = go/archive/tar/stat_atim.go
+go_archive_tar_files = \
+	go/archive/tar/common.go \
+	go/archive/tar/reader.go \
+	go/archive/tar/stat_unix.go \
+	go/archive/tar/writer.go \
+	$(archive_tar_atim_file)
+
+go_archive_zip_files = \
+	go/archive/zip/reader.go \
+	go/archive/zip/register.go \
+	go/archive/zip/struct.go \
+	go/archive/zip/writer.go
+
+go_compress_bzip2_files = \
+	go/compress/bzip2/bit_reader.go \
+	go/compress/bzip2/bzip2.go \
+	go/compress/bzip2/huffman.go \
+	go/compress/bzip2/move_to_front.go
+
+go_compress_flate_files = \
+	go/compress/flate/copy.go \
+	go/compress/flate/deflate.go \
+	go/compress/flate/fixedhuff.go \
+	go/compress/flate/huffman_bit_writer.go \
+	go/compress/flate/huffman_code.go \
+	go/compress/flate/inflate.go \
+	go/compress/flate/reverse_bits.go \
+	go/compress/flate/token.go
+
+go_compress_gzip_files = \
+	go/compress/gzip/gzip.go \
+	go/compress/gzip/gunzip.go
+
+go_compress_lzw_files = \
+	go/compress/lzw/reader.go \
+	go/compress/lzw/writer.go
+
+go_compress_zlib_files = \
+	go/compress/zlib/reader.go \
+	go/compress/zlib/writer.go
+
+go_container_heap_files = \
+	go/container/heap/heap.go
+
+go_container_list_files = \
+	go/container/list/list.go
+
+go_container_ring_files = \
+	go/container/ring/ring.go
+
+go_crypto_aes_files = \
+	go/crypto/aes/block.go \
+	go/crypto/aes/cipher.go \
+	go/crypto/aes/cipher_generic.go \
+	go/crypto/aes/const.go
+
+go_crypto_cipher_files = \
+	go/crypto/cipher/cbc.go \
+	go/crypto/cipher/cfb.go \
+	go/crypto/cipher/cipher.go \
+	go/crypto/cipher/ctr.go \
+	go/crypto/cipher/gcm.go \
+	go/crypto/cipher/io.go \
+	go/crypto/cipher/ofb.go \
+	go/crypto/cipher/xor.go
+
+go_crypto_des_files = \
+	go/crypto/des/block.go \
+	go/crypto/des/cipher.go \
+	go/crypto/des/const.go
+
+go_crypto_dsa_files = \
+	go/crypto/dsa/dsa.go
+
+go_crypto_ecdsa_files = \
+	go/crypto/ecdsa/ecdsa.go
+
+go_crypto_elliptic_files = \
+	go/crypto/elliptic/elliptic.go \
+	go/crypto/elliptic/p224.go \
+	go/crypto/elliptic/p256.go
+
+go_crypto_hmac_files = \
+	go/crypto/hmac/hmac.go
+
+go_crypto_md5_files = \
+	go/crypto/md5/md5.go \
+	go/crypto/md5/md5block.go \
+	go/crypto/md5/md5block_generic.go
+
+go_crypto_rand_files = \
+	go/crypto/rand/rand.go \
+	go/crypto/rand/rand_unix.go \
+	go/crypto/rand/util.go
+
+go_crypto_rc4_files = \
+	go/crypto/rc4/rc4.go \
+	go/crypto/rc4/rc4_ref.go
+
+go_crypto_rsa_files = \
+	go/crypto/rsa/pkcs1v15.go \
+	go/crypto/rsa/pss.go \
+	go/crypto/rsa/rsa.go
+
+go_crypto_sha1_files = \
+	go/crypto/sha1/sha1.go \
+	go/crypto/sha1/sha1block.go \
+	go/crypto/sha1/sha1block_generic.go
+
+go_crypto_sha256_files = \
+	go/crypto/sha256/sha256.go \
+	go/crypto/sha256/sha256block.go
+
+go_crypto_sha512_files = \
+	go/crypto/sha512/sha512.go \
+	go/crypto/sha512/sha512block.go
+
+go_crypto_subtle_files = \
+	go/crypto/subtle/constant_time.go
+
+go_crypto_tls_files = \
+	go/crypto/tls/alert.go \
+	go/crypto/tls/cipher_suites.go \
+	go/crypto/tls/common.go \
+	go/crypto/tls/conn.go \
+	go/crypto/tls/handshake_client.go \
+	go/crypto/tls/handshake_messages.go \
+	go/crypto/tls/handshake_server.go \
+	go/crypto/tls/key_agreement.go \
+	go/crypto/tls/prf.go \
+	go/crypto/tls/ticket.go \
+	go/crypto/tls/tls.go
+
+go_crypto_x509_files = \
+	go/crypto/x509/cert_pool.go \
+	go/crypto/x509/pem_decrypt.go \
+	go/crypto/x509/pkcs1.go \
+	go/crypto/x509/pkcs8.go \
+	go/crypto/x509/root.go \
+	go/crypto/x509/root_unix.go \
+	go/crypto/x509/sec1.go \
+	go/crypto/x509/verify.go \
+	go/crypto/x509/x509.go
+
+go_crypto_x509_pkix_files = \
+	go/crypto/x509/pkix/pkix.go
+
+go_database_sql_files = \
+	go/database/sql/convert.go \
+	go/database/sql/sql.go
+
+go_database_sql_driver_files = \
+	go/database/sql/driver/driver.go \
+	go/database/sql/driver/types.go
+
+go_debug_dwarf_files = \
+	go/debug/dwarf/buf.go \
+	go/debug/dwarf/const.go \
+	go/debug/dwarf/entry.go \
+	go/debug/dwarf/line.go \
+	go/debug/dwarf/open.go \
+	go/debug/dwarf/type.go \
+	go/debug/dwarf/typeunit.go \
+	go/debug/dwarf/unit.go
+
+go_debug_elf_files = \
+	go/debug/elf/elf.go \
+	go/debug/elf/file.go
+
+go_debug_gosym_files = \
+	go/debug/gosym/pclntab.go \
+	go/debug/gosym/symtab.go
+
+go_debug_macho_files = \
+	go/debug/macho/fat.go \
+	go/debug/macho/file.go \
+	go/debug/macho/macho.go
+
+go_debug_pe_files = \
+	go/debug/pe/file.go \
+	go/debug/pe/pe.go
+
+go_debug_plan9obj_files = \
+	go/debug/plan9obj/file.go \
+	go/debug/plan9obj/plan9obj.go
+
+go_encoding_ascii85_files = \
+	go/encoding/ascii85/ascii85.go
+
+go_encoding_asn1_files = \
+	go/encoding/asn1/asn1.go \
+	go/encoding/asn1/common.go \
+	go/encoding/asn1/marshal.go
+
+go_encoding_base32_files = \
+	go/encoding/base32/base32.go
+
+go_encoding_base64_files = \
+	go/encoding/base64/base64.go
+
+go_encoding_binary_files = \
+	go/encoding/binary/binary.go \
+	go/encoding/binary/varint.go
+
+go_encoding_csv_files = \
+	go/encoding/csv/reader.go \
+	go/encoding/csv/writer.go
+
+go_encoding_gob_files = \
+	go/encoding/gob/decode.go \
+	go/encoding/gob/decoder.go \
+	go/encoding/gob/doc.go \
+	go/encoding/gob/encode.go \
+	go/encoding/gob/encoder.go \
+	go/encoding/gob/error.go \
+	go/encoding/gob/type.go
+
+go_encoding_hex_files = \
+	go/encoding/hex/hex.go
+
+go_encoding_json_files = \
+	go/encoding/json/decode.go \
+	go/encoding/json/encode.go \
+	go/encoding/json/fold.go \
+	go/encoding/json/indent.go \
+	go/encoding/json/scanner.go \
+	go/encoding/json/stream.go \
+	go/encoding/json/tags.go
+
+go_encoding_pem_files = \
+	go/encoding/pem/pem.go
+
+go_encoding_xml_files = \
+	go/encoding/xml/marshal.go \
+	go/encoding/xml/read.go \
+	go/encoding/xml/typeinfo.go \
+	go/encoding/xml/xml.go
+
+go_exp_proxy_files = \
+	go/exp/proxy/direct.go \
+	go/exp/proxy/per_host.go \
+	go/exp/proxy/proxy.go \
+	go/exp/proxy/socks5.go
+
+go_exp_terminal_files = \
+	go/exp/terminal/terminal.go \
+	go/exp/terminal/util.go
+
+go_go_ast_files = \
+	go/go/ast/ast.go \
+	go/go/ast/commentmap.go \
+	go/go/ast/filter.go \
+	go/go/ast/import.go \
+	go/go/ast/print.go \
+	go/go/ast/resolve.go \
+	go/go/ast/scope.go \
+	go/go/ast/walk.go
+
+go_go_build_files = \
+	go/go/build/build.go \
+	go/go/build/doc.go \
+	go/go/build/read.go \
+	go/go/build/syslist.go
+
+go_go_doc_files = \
+	go/go/doc/comment.go \
+	go/go/doc/doc.go \
+	go/go/doc/example.go \
+	go/go/doc/exports.go \
+	go/go/doc/filter.go \
+	go/go/doc/reader.go \
+	go/go/doc/synopsis.go
+
+go_go_format_files = \
+	go/go/format/format.go
+
+go_go_parser_files = \
+	go/go/parser/interface.go \
+	go/go/parser/parser.go
+
+go_go_printer_files = \
+	go/go/printer/nodes.go \
+	go/go/printer/printer.go
+
+go_go_scanner_files = \
+	go/go/scanner/errors.go \
+	go/go/scanner/scanner.go
+
+go_go_token_files = \
+	go/go/token/position.go \
+	go/go/token/serialize.go \
+	go/go/token/token.go
+
+go_hash_adler32_files = \
+	go/hash/adler32/adler32.go
+
+go_hash_crc32_files = \
+	go/hash/crc32/crc32.go \
+	go/hash/crc32/crc32_generic.go
+
+go_hash_crc64_files = \
+	go/hash/crc64/crc64.go
+
+go_hash_fnv_files = \
+	go/hash/fnv/fnv.go
+
+go_html_template_files = \
+	go/html/template/attr.go \
+	go/html/template/content.go \
+	go/html/template/context.go \
+	go/html/template/css.go \
+	go/html/template/doc.go \
+	go/html/template/error.go \
+	go/html/template/escape.go \
+	go/html/template/html.go \
+	go/html/template/js.go \
+	go/html/template/template.go \
+	go/html/template/transition.go \
+	go/html/template/url.go
+
+go_image_color_files = \
+	go/image/color/color.go \
+	go/image/color/ycbcr.go
+
+go_image_color_palette_files = \
+	go/image/color/palette/palette.go
+
+go_image_draw_files = \
+	go/image/draw/draw.go
+
+go_image_gif_files = \
+	go/image/gif/reader.go \
+	go/image/gif/writer.go
+
+go_image_jpeg_files = \
+	go/image/jpeg/fdct.go \
+	go/image/jpeg/huffman.go \
+	go/image/jpeg/idct.go \
+	go/image/jpeg/reader.go \
+	go/image/jpeg/scan.go \
+	go/image/jpeg/writer.go
+
+go_image_png_files = \
+	go/image/png/paeth.go \
+	go/image/png/reader.go \
+	go/image/png/writer.go
+
+go_index_suffixarray_files = \
+	go/index/suffixarray/qsufsort.go \
+	go/index/suffixarray/suffixarray.go
+
+go_io_ioutil_files = \
+	go/io/ioutil/ioutil.go \
+	go/io/ioutil/tempfile.go
+
+go_math_big_files = \
+	go/math/big/arith.go \
+	go/math/big/int.go \
+	go/math/big/nat.go \
+	go/math/big/rat.go
+
+go_math_cmplx_files = \
+	go/math/cmplx/abs.go \
+	go/math/cmplx/asin.go \
+	go/math/cmplx/conj.go \
+	go/math/cmplx/exp.go \
+	go/math/cmplx/isinf.go \
+	go/math/cmplx/isnan.go \
+	go/math/cmplx/log.go \
+	go/math/cmplx/phase.go \
+	go/math/cmplx/polar.go \
+	go/math/cmplx/pow.go \
+	go/math/cmplx/rect.go \
+	go/math/cmplx/sin.go \
+	go/math/cmplx/sqrt.go \
+	go/math/cmplx/tan.go
+
+go_math_rand_files = \
+	go/math/rand/exp.go \
+	go/math/rand/normal.go \
+	go/math/rand/rand.go \
+	go/math/rand/rng.go \
+	go/math/rand/zipf.go
+
+go_mime_multipart_files = \
+	go/mime/multipart/formdata.go \
+	go/mime/multipart/multipart.go \
+	go/mime/multipart/quotedprintable.go \
+	go/mime/multipart/writer.go
+
+go_net_http_files = \
+	go/net/http/chunked.go \
+	go/net/http/client.go \
+	go/net/http/cookie.go \
+	go/net/http/filetransport.go \
+	go/net/http/fs.go \
+	go/net/http/header.go \
+	go/net/http/jar.go \
+	go/net/http/lex.go \
+	go/net/http/request.go \
+	go/net/http/response.go \
+	go/net/http/server.go \
+	go/net/http/sniff.go \
+	go/net/http/status.go \
+	go/net/http/transfer.go \
+	go/net/http/transport.go
+
+go_net_mail_files = \
+	go/net/mail/message.go
+
+go_net_smtp_files = \
+	go/net/smtp/auth.go \
+	go/net/smtp/smtp.go
+
+go_net_textproto_files = \
+	go/net/textproto/header.go \
+	go/net/textproto/pipeline.go \
+	go/net/textproto/reader.go \
+	go/net/textproto/textproto.go \
+	go/net/textproto/writer.go
+
+go_net_url_files = \
+	go/net/url/url.go
+
+go_net_http_cgi_files = \
+	go/net/http/cgi/child.go \
+	go/net/http/cgi/host.go
+
+go_net_http_cookiejar_files = \
+	go/net/http/cookiejar/jar.go \
+	go/net/http/cookiejar/punycode.go
+
+go_net_http_fcgi_files = \
+	go/net/http/fcgi/child.go \
+	go/net/http/fcgi/fcgi.go
+
+go_net_http_httptest_files = \
+	go/net/http/httptest/recorder.go \
+	go/net/http/httptest/server.go
+
+go_net_http_pprof_files = \
+	go/net/http/pprof/pprof.go
+
+go_net_http_httputil_files = \
+	go/net/http/httputil/chunked.go \
+	go/net/http/httputil/dump.go \
+	go/net/http/httputil/httputil.go \
+	go/net/http/httputil/persist.go \
+	go/net/http/httputil/reverseproxy.go
+
+go_old_regexp_files = \
+	go/old/regexp/regexp.go
+
+go_old_template_files = \
+	go/old/template/doc.go \
+	go/old/template/execute.go \
+	go/old/template/format.go \
+	go/old/template/parse.go
+
+go_os_exec_files = \
+	go/os/exec/exec.go \
+	go/os/exec/lp_unix.go
+
+go_os_signal_files = \
+	go/os/signal/signal.go \
+	go/os/signal/signal_unix.go
+
+@LIBGO_IS_SOLARIS_FALSE@os_user_decls_file = go/os/user/decls_unix.go
+@LIBGO_IS_SOLARIS_TRUE@os_user_decls_file = go/os/user/decls_solaris.go
+go_os_user_files = \
+	go/os/user/lookup.go \
+	go/os/user/lookup_unix.go \
+	go/os/user/user.go \
+	$(os_user_decls_file)
+
+go_path_filepath_files = \
+	go/path/filepath/match.go \
+	go/path/filepath/path.go \
+	go/path/filepath/path_unix.go \
+	go/path/filepath/symlink.go
+
+go_regexp_syntax_files = \
+	go/regexp/syntax/compile.go \
+	go/regexp/syntax/doc.go \
+	go/regexp/syntax/parse.go \
+	go/regexp/syntax/perl_groups.go \
+	go/regexp/syntax/prog.go \
+	go/regexp/syntax/regexp.go \
+	go/regexp/syntax/simplify.go
+
+go_net_rpc_jsonrpc_files = \
+	go/net/rpc/jsonrpc/client.go \
+	go/net/rpc/jsonrpc/server.go
+
+go_runtime_debug_files = \
+	go/runtime/debug/garbage.go \
+	go/runtime/debug/stack.go
+
+go_runtime_pprof_files = \
+	go/runtime/pprof/pprof.go
+
+go_text_tabwriter_files = \
+	go/text/tabwriter/tabwriter.go
+
+go_text_template_files = \
+	go/text/template/doc.go \
+	go/text/template/exec.go \
+	go/text/template/funcs.go \
+	go/text/template/helper.go \
+	go/text/template/template.go
+
+go_text_template_parse_files = \
+	go/text/template/parse/lex.go \
+	go/text/template/parse/node.go \
+	go/text/template/parse/parse.go
+
+go_sync_atomic_files = \
+	go/sync/atomic/doc.go
+
+go_sync_atomic_c_files = \
+	go/sync/atomic/atomic.c
+
+go_testing_iotest_files = \
+	go/testing/iotest/logger.go \
+	go/testing/iotest/reader.go \
+	go/testing/iotest/writer.go
+
+go_testing_quick_files = \
+	go/testing/quick/quick.go
+
+go_text_scanner_files = \
+	go/text/scanner/scanner.go
+
+go_unicode_utf16_files = \
+	go/unicode/utf16/utf16.go
+
+go_unicode_utf8_files = \
+	go/unicode/utf8/utf8.go
+
+@LIBGO_IS_RTEMS_FALSE@syscall_syscall_file = go/syscall/syscall_unix.go
+
+# Define Syscall and Syscall6.
+@LIBGO_IS_RTEMS_TRUE@syscall_syscall_file = go/syscall/syscall_stubs.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_exec_file = go/syscall/exec_unix.go
+@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_exec_file = go/syscall/exec_unix.go
+
+# Define ForkExec and Exec.
+@LIBGO_IS_RTEMS_TRUE@syscall_exec_file = go/syscall/exec_stubs.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_exec_os_file = go/syscall/exec_bsd.go
+@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_exec_os_file = go/syscall/exec_linux.go
+@LIBGO_IS_RTEMS_TRUE@syscall_exec_os_file = 
+@HAVE_WAIT4_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_wait_file = go/syscall/libcall_waitpid.go
+@HAVE_WAIT4_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_wait_file = go/syscall/libcall_wait4.go
+
+# Define Wait4.
+@LIBGO_IS_RTEMS_TRUE@syscall_wait_file = 
+@LIBGO_IS_RTEMS_FALSE@syscall_wait_c_file = go/syscall/wait.c
+
+# Support for pulling apart wait status.
+@LIBGO_IS_RTEMS_TRUE@syscall_wait_c_file = 
+@LIBGO_IS_RTEMS_FALSE@syscall_sleep_file = go/syscall/sleep_select.go
+
+# Define Sleep.
+@LIBGO_IS_RTEMS_TRUE@syscall_sleep_file = go/syscall/sleep_rtems.go
+@HAVE_STRERROR_R_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = go/syscall/errstr_nor.go
+@HAVE_STRERROR_R_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = go/syscall/errstr.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_TRUE@syscall_errstr_file = go/syscall/errstr_linux.go
+
+# Define Errstr.
+@LIBGO_IS_LINUX_TRUE@syscall_errstr_file = go/syscall/errstr_linux.go
+# Use lseek on 64-bit Solaris.
+@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@syscall_size_file = go/syscall/libcall_posix_regfile.go
+# Use lseek64 on 32-bit Solaris/SPARC.
+@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go
+# Use lseek64 on 32-bit Solaris/x86.
+@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go
+# Use lseek by default.
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_size_file = go/syscall/libcall_posix_regfile.go
+
+# Declare libc functions that vary for largefile systems.
+# Always use lseek64 on GNU/Linux.
+@LIBGO_IS_LINUX_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_file = go/syscall/socket_bsd.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_file = go/syscall/socket_irix.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_socket_file = go/syscall/socket_solaris.go
+
+# Define socket sizes and types.
+@LIBGO_IS_LINUX_TRUE@syscall_socket_file = go/syscall/socket_linux.go epoll.go
+@LIBGO_IS_SOLARIS_FALSE@syscall_socket_os_file = go/syscall/socket_posix.go
+
+# Define socket functions.
+@LIBGO_IS_SOLARIS_TRUE@syscall_socket_os_file = go/syscall/socket_xnet.go
+@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = go/syscall/libcall_uname.go
+
+# Support for uname.
+# 32-bit Solaris 2/x86 needs _nuname, handled in libcall_solaris_386.go.
+@LIBGO_IS_386_TRUE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = 
+@LIBGO_IS_SOLARIS_FALSE@syscall_uname_file = go/syscall/libcall_uname.go
+@LIBGO_IS_LINUX_FALSE@syscall_sockcmsg_file = 
+
+# GNU/Linux specific socket control messages.
+@LIBGO_IS_LINUX_TRUE@syscall_sockcmsg_file = go/syscall/sockcmsg_linux.go
+@LIBGO_IS_LINUX_FALSE@syscall_netlink_file = 
+
+# Support for netlink sockets and messages.
+@LIBGO_IS_LINUX_TRUE@syscall_netlink_file = go/syscall/netlink_linux.go
+@LIBGO_IS_LINUX_FALSE@syscall_lsf_file = 
+
+# GNU/Linux specific socket filters.
+@LIBGO_IS_LINUX_TRUE@syscall_lsf_file = go/syscall/lsf_linux.go
+@LIBGO_IS_LINUX_FALSE@syscall_utimesnano_file = go/syscall/libcall_posix_utimesnano.go
+
+# GNU/Linux specific utimesnano support.
+@LIBGO_IS_LINUX_TRUE@syscall_utimesnano_file = go/syscall/libcall_linux_utimesnano.go
+@LIBGO_IS_LINUX_FALSE@syscall_creds_test_file = 
+
+# Test files.
+@LIBGO_IS_LINUX_TRUE@syscall_creds_test_file = go/syscall/creds_test.go
+go_base_syscall_files = \
+	go/syscall/env_unix.go \
+	go/syscall/syscall_errno.go \
+	go/syscall/libcall_support.go \
+	go/syscall/libcall_posix.go \
+	go/syscall/race0.go \
+	go/syscall/socket.go \
+	go/syscall/sockcmsg_unix.go \
+	go/syscall/str.go \
+	go/syscall/syscall.go \
+	$(syscall_sockcmsg_file) \
+	$(syscall_syscall_file) \
+	$(syscall_exec_file) \
+	$(syscall_exec_os_file) \
+	$(syscall_wait_file) \
+	$(syscall_sleep_file) \
+	$(syscall_errstr_file) \
+	$(syscall_size_file) \
+	$(syscall_socket_file) \
+	$(syscall_socket_os_file) \
+	$(syscall_uname_file) \
+	$(syscall_netlink_file) \
+	$(syscall_lsf_file) \
+	$(syscall_utimesnano_file) \
+	$(GO_LIBCALL_OS_FILE) \
+	$(GO_LIBCALL_OS_ARCH_FILE) \
+	$(GO_SYSCALL_OS_FILE) \
+	$(GO_SYSCALL_OS_ARCH_FILE)
+
+go_syscall_files = \
+	$(go_base_syscall_files) \
+	libcalls.go \
+	sysinfo.go \
+	syscall_arch.go
+
+go_syscall_c_files = \
+	go/syscall/errno.c \
+	go/syscall/signame.c \
+	$(syscall_wait_c_file)
+
+go_syscall_test_files = \
+	$(syscall_creds_test_file) \
+	go/syscall/mmap_unix_test.go \
+	go/syscall/syscall_test.go \
+	go/syscall/syscall_unix_test.go
+
+@LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo = 
+
+# os_lib_inotify_lo = os/inotify.lo
+@LIBGO_IS_LINUX_TRUE@os_lib_inotify_lo = 
+libgo_go_objs = \
+	bufio.lo \
+	bytes.lo \
+	bytes/index.lo \
+	crypto.lo \
+	encoding.lo \
+	errors.lo \
+	expvar.lo \
+	flag.lo \
+	fmt.lo \
+	hash.lo \
+	html.lo \
+	image.lo \
+	io.lo \
+	log.lo \
+	math.lo \
+	mime.lo \
+	net.lo \
+	os.lo \
+	path.lo \
+	reflect-go.lo \
+	reflect/makefunc.lo \
+	reflect/makefunc_ffi_c.lo \
+	regexp.lo \
+	runtime-go.lo \
+	sort.lo \
+	strconv.lo \
+	strings.lo \
+	strings/index.lo \
+	sync.lo \
+	syscall.lo \
+	syscall/errno.lo \
+	syscall/signame.lo \
+	syscall/wait.lo \
+	testing.lo \
+	time-go.lo \
+	unicode.lo \
+	archive/tar.lo \
+	archive/zip.lo \
+	compress/bzip2.lo \
+	compress/flate.lo \
+	compress/gzip.lo \
+	compress/lzw.lo \
+	compress/zlib.lo \
+	container/heap.lo \
+	container/list.lo \
+	container/ring.lo \
+	crypto/aes.lo \
+	crypto/cipher.lo \
+	crypto/des.lo \
+	crypto/dsa.lo \
+	crypto/ecdsa.lo \
+	crypto/elliptic.lo \
+	crypto/hmac.lo \
+	crypto/md5.lo \
+	crypto/rand.lo \
+	crypto/rc4.lo \
+	crypto/rsa.lo \
+	crypto/sha1.lo \
+	crypto/sha256.lo \
+	crypto/sha512.lo \
+	crypto/subtle.lo \
+	crypto/tls.lo \
+	crypto/x509.lo \
+	crypto/x509/pkix.lo \
+	database/sql.lo \
+	database/sql/driver.lo \
+	debug/dwarf.lo \
+	debug/elf.lo \
+	debug/gosym.lo \
+	debug/macho.lo \
+	debug/pe.lo \
+	debug/plan9obj.lo \
+	encoding/ascii85.lo \
+	encoding/asn1.lo \
+	encoding/base32.lo \
+	encoding/base64.lo \
+	encoding/binary.lo \
+	encoding/csv.lo \
+	encoding/gob.lo \
+	encoding/hex.lo \
+	encoding/json.lo \
+	encoding/pem.lo \
+	encoding/xml.lo \
+	exp/proxy.lo \
+	exp/terminal.lo \
+	html/template.lo \
+	go/ast.lo \
+	go/build.lo \
+	go/doc.lo \
+	go/format.lo \
+	go/parser.lo \
+	go/printer.lo \
+	go/scanner.lo \
+	go/token.lo \
+	hash/adler32.lo \
+	hash/crc32.lo \
+	hash/crc64.lo \
+	hash/fnv.lo \
+	net/http/cgi.lo \
+	net/http/cookiejar.lo \
+	net/http/fcgi.lo \
+	net/http/httptest.lo \
+	net/http/httputil.lo \
+	net/http/pprof.lo \
+	image/color.lo \
+	image/color/palette.lo \
+	image/draw.lo \
+	image/gif.lo \
+	image/jpeg.lo \
+	image/png.lo \
+	index/suffixarray.lo \
+	io/ioutil.lo \
+	log/syslog.lo \
+	log/syslog/syslog_c.lo \
+	math/big.lo \
+	math/cmplx.lo \
+	math/rand.lo \
+	mime/multipart.lo \
+	net/http.lo \
+	net/mail.lo \
+	net/rpc.lo \
+	net/smtp.lo \
+	net/textproto.lo \
+	net/url.lo \
+	old/regexp.lo \
+	old/template.lo \
+	os/exec.lo \
+	$(os_lib_inotify_lo) \
+	os/signal.lo \
+	os/user.lo \
+	path/filepath.lo \
+	regexp/syntax.lo \
+	net/rpc/jsonrpc.lo \
+	runtime/debug.lo \
+	runtime/pprof.lo \
+	sync/atomic.lo \
+	sync/atomic_c.lo \
+	text/scanner.lo \
+	text/tabwriter.lo \
+	text/template.lo \
+	text/template/parse.lo \
+	testing/iotest.lo \
+	testing/quick.lo \
+	unicode/utf16.lo \
+	unicode/utf8.lo
+
+libgo_ldflags = \
+	-version-info $(libtool_VERSION) $(PTHREAD_CFLAGS) $(AM_LDFLAGS)
+
+libgo_libadd = \
+	$(libgo_go_objs) ../libbacktrace/libbacktrace.la \
+	$(LIBATOMIC) $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS)
+
+libgo_la_SOURCES = $(runtime_files)
+libgo_la_LDFLAGS = $(libgo_ldflags)
+libgo_la_LIBADD = $(libgo_libadd)
+libgo_llgo_la_SOURCES = $(runtime_files)
+libgo_llgo_la_LDFLAGS = $(libgo_ldflags)
+libgo_llgo_la_LIBADD = $(libgo_libadd)
+libgobegin_a_SOURCES = \
+	runtime/go-main.c
+
+libgobegin_llgo_a_SOURCES = \
+	runtime/go-main.c
+
+LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
+AM_GOCFLAGS = $(STRINGOPS_FLAG)
+GOCOMPILE = $(GOC) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_GOCFLAGS) $(GOCFLAGS)
+LTGOCOMPILE = $(LIBTOOL) --tag GO --mode=compile $(GOC) $(INCLUDES) \
+	$(AM_GOCFLAGS) $(GOCFLAGS)
+
+GOLINK = $(LIBTOOL) --tag GO --mode-link $(GOC) \
+	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_GOCFLAGS) $(LTLDFLAGS) -o $@
+
+
+# Build the dependencies for a Go package.
+BUILDDEPS = \
+	$(MKDIR_P) $(@D); \
+	$(SHELL) $(srcdir)/godeps.sh `echo $@ | sed -e 's/.dep$$//'` $^ > $@.tmp; \
+	mv -f $@.tmp $@
+
+
+# Build the .go files for a package, generating a .lo file.
+BUILDPACKAGE = \
+	$(MKDIR_P) $(@D); \
+	files=`echo $^ | sed -e 's/[^ ]*\.gox//g'`; \
+	$(LTGOCOMPILE) -I . -c -fgo-pkgpath=`echo $@ | sed -e 's/.lo$$//' -e 's/-go$$//'` -o $@ $$files
+
+GOTESTFLAGS = 
+GOBENCH = 
+
+# Check a package.
+CHECK = \
+	GC="$(GOC) $(GOCFLAGS) $($(subst /,_,$@)_GOCFLAGS) -L `${PWD_COMMAND}` -L `${PWD_COMMAND}`/.libs"; \
+	export GC; \
+	GOLIBS="$(MATH_LIBS) $(NET_LIBS) $(LIBS)"; \
+	export GOLIBS; \
+	RUNTESTFLAGS="$(RUNTESTFLAGS)"; \
+	export RUNTESTFLAGS; \
+	MAKE="$(MAKE)"; \
+	export MAKE; \
+	libgccdir=`${GOC} -print-libgcc-file-name | sed -e 's|/[^/]*$$||'`; \
+	LD_LIBRARY_PATH="`${PWD_COMMAND}`/.libs:$${libgccdir}:${LD_LIBRARY_PATH}"; \
+	LD_LIBRARY_PATH=`echo $${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
+	export LD_LIBRARY_PATH; \
+	$(MKDIR_P) $(@D); \
+	rm -f $@-testsum $@-testlog; \
+	if test "$(USE_DEJAGNU)" = "yes"; then \
+	  $(SHELL) $(srcdir)/testsuite/gotest --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
+	elif test "$(GOBENCH)" != ""; then \
+	  $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
+	else \
+	  if $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \
+	    echo "PASS: $(@D)" >> $@-testlog; \
+	    echo "PASS: $(@D)"; \
+	    echo "PASS: $(@D)" > $@-testsum; \
+	  else \
+	    echo "FAIL: $(@D)" >> $@-testlog; \
+	    cat $@-testlog; \
+	    echo "FAIL: $(@D)" > $@-testsum; \
+	    exit 1; \
+	  fi; \
+	fi
+
+
+# Build all packages before checking any.
+CHECK_DEPS = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
+	$(toolexeclibgocompress_DATA) $(toolexeclibgocontainer_DATA) \
+	$(toolexeclibgocrypto_DATA) $(toolexeclibgodebug_DATA) \
+	$(toolexeclibgoencoding_DATA) $(toolexeclibgoexp_DATA) \
+	$(toolexeclibgogo_DATA) $(toolexeclibgohash_DATA) \
+	$(toolexeclibgoimage_DATA) $(toolexeclibgoindex_DATA) \
+	$(toolexeclibgoio_DATA) $(toolexeclibgolog_DATA) \
+	$(toolexeclibgomath_DATA) $(toolexeclibgomime_DATA) \
+	$(toolexeclibgonet_DATA) $(toolexeclibgonethttp_DATA) \
+	$(toolexeclibgoos_DATA) $(toolexeclibgopath_DATA) \
+	$(toolexeclibgorpc_DATA) $(toolexeclibgoruntime_DATA) \
+	$(toolexeclibgosync_DATA) $(toolexeclibgotesting_DATA) \
+	$(toolexeclibgotext_DATA) $(toolexeclibgotexttemplate_DATA) \
+	$(toolexeclibgounicode_DATA) $(am__append_1) $(am__append_2)
+# At least for now, we need -static-libgo for this test, because
+# otherwise we can't get the line numbers.
+runtime_pprof_check_GOCFLAGS = -static-libgo
+
+# How to build a .gox file from a .lo file.
+BUILDGOX = \
+	f=`echo $< | sed -e 's/.lo$$/.o/'`; \
+	$(OBJCOPY) -j .go_export $$f $@.tmp && mv -f $@.tmp $@
+
+TEST_PACKAGES = \
+	bufio/check \
+	bytes/check \
+	errors/check \
+	expvar/check \
+	flag/check \
+	fmt/check \
+	html/check \
+	image/check \
+	io/check \
+	log/check \
+	math/check \
+	mime/check \
+	net/check \
+	os/check \
+	path/check \
+	reflect/check \
+	regexp/check \
+	runtime/check \
+	sort/check \
+	strconv/check \
+	strings/check \
+	sync/check \
+	syscall/check \
+	time/check \
+	unicode/check \
+	archive/tar/check \
+	archive/zip/check \
+	compress/bzip2/check \
+	compress/flate/check \
+	compress/gzip/check \
+	compress/lzw/check \
+	compress/zlib/check \
+	container/heap/check \
+	container/list/check \
+	container/ring/check \
+	crypto/aes/check \
+	crypto/cipher/check \
+	crypto/des/check \
+	crypto/dsa/check \
+	crypto/ecdsa/check \
+	crypto/elliptic/check \
+	crypto/hmac/check \
+	crypto/md5/check \
+	crypto/rand/check \
+	crypto/rc4/check \
+	crypto/rsa/check \
+	crypto/sha1/check \
+	crypto/sha256/check \
+	crypto/sha512/check \
+	crypto/subtle/check \
+	crypto/tls/check \
+	crypto/x509/check \
+	database/sql/check \
+	database/sql/driver/check \
+	debug/dwarf/check \
+	debug/elf/check \
+	debug/macho/check \
+	debug/pe/check \
+	debug/plan9obj/check \
+	encoding/ascii85/check \
+	encoding/asn1/check \
+	encoding/base32/check \
+	encoding/base64/check \
+	encoding/binary/check \
+	encoding/csv/check \
+	encoding/gob/check \
+	encoding/hex/check \
+	encoding/json/check \
+	encoding/pem/check \
+	encoding/xml/check \
+	exp/proxy/check \
+	exp/terminal/check \
+	html/template/check \
+	go/ast/check \
+	$(go_build_check_omitted_since_it_calls_6g) \
+	go/doc/check \
+	go/format/check \
+	go/parser/check \
+	go/printer/check \
+	go/scanner/check \
+	go/token/check \
+	hash/adler32/check \
+	hash/crc32/check \
+	hash/crc64/check \
+	hash/fnv/check \
+	image/color/check \
+	image/draw/check \
+	image/jpeg/check \
+	image/png/check \
+	index/suffixarray/check \
+	io/ioutil/check \
+	log/syslog/check \
+	math/big/check \
+	math/cmplx/check \
+	math/rand/check \
+	mime/multipart/check \
+	net/http/check \
+	net/http/cgi/check \
+	net/http/cookiejar/check \
+	net/http/fcgi/check \
+	net/http/httptest/check \
+	net/http/httputil/check \
+	net/mail/check \
+	net/rpc/check \
+	net/smtp/check \
+	net/textproto/check \
+	net/url/check \
+	net/rpc/jsonrpc/check \
+	old/regexp/check \
+	old/template/check \
+	os/exec/check \
+	os/signal/check \
+	os/user/check \
+	path/filepath/check \
+	regexp/syntax/check \
+	runtime/pprof/check \
+	sync/atomic/check \
+	text/scanner/check \
+	text/tabwriter/check \
+	text/template/check \
+	text/template/parse/check \
+	testing/quick/check \
+	unicode/utf16/check \
+	unicode/utf8/check
+
+MOSTLYCLEAN_FILES = libgo.head libgo.sum.sep libgo.log.sep
+CLEANFILES = *.go *.gox goc2c *.c s-version libgo.sum libgo.log
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .go .gox .o .obj .lo .a
+am--refresh:
+	@:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	$(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+	else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+install-toolexeclibLIBRARIES: $(toolexeclib_LIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)"
+	@list='$(toolexeclib_LIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(INSTALL_DATA) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \
+	  $(INSTALL_DATA) $$list2 "$(DESTDIR)$(toolexeclibdir)" || exit $$?; }
+	@$(POST_INSTALL)
+	@list='$(toolexeclib_LIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+	for p in $$list; do \
+	  if test -f $$p; then \
+	    $(am__strip_dir) \
+	    echo " ( cd '$(DESTDIR)$(toolexeclibdir)' && $(RANLIB) $$f )"; \
+	    ( cd "$(DESTDIR)$(toolexeclibdir)" && $(RANLIB) $$f ) || exit $$?; \
+	  else :; fi; \
+	done
+
+uninstall-toolexeclibLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclib_LIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibdir)' && rm -f "$$files" )"; \
+	cd "$(DESTDIR)$(toolexeclibdir)" && rm -f $$files
+
+clean-toolexeclibLIBRARIES:
+	-test -z "$(toolexeclib_LIBRARIES)" || rm -f $(toolexeclib_LIBRARIES)
+libgobegin-llgo.a: $(libgobegin_llgo_a_OBJECTS) $(libgobegin_llgo_a_DEPENDENCIES) 
+	-rm -f libgobegin-llgo.a
+	$(libgobegin_llgo_a_AR) libgobegin-llgo.a $(libgobegin_llgo_a_OBJECTS) $(libgobegin_llgo_a_LIBADD)
+	$(RANLIB) libgobegin-llgo.a
+libgobegin.a: $(libgobegin_a_OBJECTS) $(libgobegin_a_DEPENDENCIES) 
+	-rm -f libgobegin.a
+	$(libgobegin_a_AR) libgobegin.a $(libgobegin_a_OBJECTS) $(libgobegin_a_LIBADD)
+	$(RANLIB) libgobegin.a
+install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)"
+	@list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(toolexeclibdir)"; \
+	}
+
+uninstall-toolexeclibLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$f"; \
+	done
+
+clean-toolexeclibLTLIBRARIES:
+	-test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES)
+	@list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libgo-llgo.la: $(libgo_llgo_la_OBJECTS) $(libgo_llgo_la_DEPENDENCIES) 
+	$(libgo_llgo_la_LINK) $(am_libgo_llgo_la_rpath) $(libgo_llgo_la_OBJECTS) $(libgo_llgo_la_LIBADD) $(LIBS)
+libgo.la: $(libgo_la_OBJECTS) $(libgo_la_DEPENDENCIES) 
+	$(libgo_la_LINK) $(am_libgo_la_rpath) $(libgo_la_OBJECTS) $(libgo_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chan.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpuprof.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env_posix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-bsd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-irix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-linux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-none.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-solaris.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-append.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-assert-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-assert.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-breakpoint.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-byte-array-to-string.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-caller.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-callers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-can-convert-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cdiv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cgo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-check-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-construct-map.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-convert-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-copy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-defer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-deferred-recover.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-eface-compare.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-eface-val-compare.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-fieldtrack.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-iface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-int-array-to-string.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-int-to-string.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-compare.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-eface-compare.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-val-compare.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-make-slice.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-delete.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-index.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-len.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-range.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-matherr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-memcmp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-nanotime.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new-map.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-nosys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-now.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-panic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-print.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-recover.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-call.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-map.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rune.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-runtime-error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-setenv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-signal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strcmp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-string-to-byte-array.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-string-to-int-array.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strplus.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strslice.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-traceback.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-complex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-eface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-float.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-identity.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-string.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-typedesc-equal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-new.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-newarray.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-pointer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unwind.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-varargs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heapdump.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lfstack.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_futex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_sema.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcentral.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem_posix_memalign.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mfixalloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mgc0.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mheap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mprof.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msize.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll_epoll.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll_kqueue.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll_select.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parfor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rdebug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reflect.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtems-task-variable-add.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sema.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signal_unix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigqueue.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread-linux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread-sema.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yield.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+go-main.o: runtime/go-main.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-main.o -MD -MP -MF $(DEPDIR)/go-main.Tpo -c -o go-main.o `test -f 'runtime/go-main.c' || echo '$(srcdir)/'`runtime/go-main.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-main.Tpo $(DEPDIR)/go-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-main.c' object='go-main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-main.o `test -f 'runtime/go-main.c' || echo '$(srcdir)/'`runtime/go-main.c
+
+go-main.obj: runtime/go-main.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-main.obj -MD -MP -MF $(DEPDIR)/go-main.Tpo -c -o go-main.obj `if test -f 'runtime/go-main.c'; then $(CYGPATH_W) 'runtime/go-main.c'; else $(CYGPATH_W) '$(srcdir)/runtime/go-main.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-main.Tpo $(DEPDIR)/go-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-main.c' object='go-main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-main.obj `if test -f 'runtime/go-main.c'; then $(CYGPATH_W) 'runtime/go-main.c'; else $(CYGPATH_W) '$(srcdir)/runtime/go-main.c'; fi`
+
+go-append.lo: runtime/go-append.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-append.lo -MD -MP -MF $(DEPDIR)/go-append.Tpo -c -o go-append.lo `test -f 'runtime/go-append.c' || echo '$(srcdir)/'`runtime/go-append.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-append.Tpo $(DEPDIR)/go-append.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-append.c' object='go-append.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-append.lo `test -f 'runtime/go-append.c' || echo '$(srcdir)/'`runtime/go-append.c
+
+go-assert.lo: runtime/go-assert.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-assert.lo -MD -MP -MF $(DEPDIR)/go-assert.Tpo -c -o go-assert.lo `test -f 'runtime/go-assert.c' || echo '$(srcdir)/'`runtime/go-assert.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-assert.Tpo $(DEPDIR)/go-assert.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-assert.c' object='go-assert.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-assert.lo `test -f 'runtime/go-assert.c' || echo '$(srcdir)/'`runtime/go-assert.c
+
+go-assert-interface.lo: runtime/go-assert-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-assert-interface.lo -MD -MP -MF $(DEPDIR)/go-assert-interface.Tpo -c -o go-assert-interface.lo `test -f 'runtime/go-assert-interface.c' || echo '$(srcdir)/'`runtime/go-assert-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-assert-interface.Tpo $(DEPDIR)/go-assert-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-assert-interface.c' object='go-assert-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-assert-interface.lo `test -f 'runtime/go-assert-interface.c' || echo '$(srcdir)/'`runtime/go-assert-interface.c
+
+go-byte-array-to-string.lo: runtime/go-byte-array-to-string.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-byte-array-to-string.lo -MD -MP -MF $(DEPDIR)/go-byte-array-to-string.Tpo -c -o go-byte-array-to-string.lo `test -f 'runtime/go-byte-array-to-string.c' || echo '$(srcdir)/'`runtime/go-byte-array-to-string.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-byte-array-to-string.Tpo $(DEPDIR)/go-byte-array-to-string.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-byte-array-to-string.c' object='go-byte-array-to-string.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-byte-array-to-string.lo `test -f 'runtime/go-byte-array-to-string.c' || echo '$(srcdir)/'`runtime/go-byte-array-to-string.c
+
+go-breakpoint.lo: runtime/go-breakpoint.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-breakpoint.lo -MD -MP -MF $(DEPDIR)/go-breakpoint.Tpo -c -o go-breakpoint.lo `test -f 'runtime/go-breakpoint.c' || echo '$(srcdir)/'`runtime/go-breakpoint.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-breakpoint.Tpo $(DEPDIR)/go-breakpoint.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-breakpoint.c' object='go-breakpoint.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-breakpoint.lo `test -f 'runtime/go-breakpoint.c' || echo '$(srcdir)/'`runtime/go-breakpoint.c
+
+go-caller.lo: runtime/go-caller.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-caller.lo -MD -MP -MF $(DEPDIR)/go-caller.Tpo -c -o go-caller.lo `test -f 'runtime/go-caller.c' || echo '$(srcdir)/'`runtime/go-caller.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-caller.Tpo $(DEPDIR)/go-caller.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-caller.c' object='go-caller.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-caller.lo `test -f 'runtime/go-caller.c' || echo '$(srcdir)/'`runtime/go-caller.c
+
+go-callers.lo: runtime/go-callers.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-callers.lo -MD -MP -MF $(DEPDIR)/go-callers.Tpo -c -o go-callers.lo `test -f 'runtime/go-callers.c' || echo '$(srcdir)/'`runtime/go-callers.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-callers.Tpo $(DEPDIR)/go-callers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-callers.c' object='go-callers.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-callers.lo `test -f 'runtime/go-callers.c' || echo '$(srcdir)/'`runtime/go-callers.c
+
+go-can-convert-interface.lo: runtime/go-can-convert-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-can-convert-interface.lo -MD -MP -MF $(DEPDIR)/go-can-convert-interface.Tpo -c -o go-can-convert-interface.lo `test -f 'runtime/go-can-convert-interface.c' || echo '$(srcdir)/'`runtime/go-can-convert-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-can-convert-interface.Tpo $(DEPDIR)/go-can-convert-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-can-convert-interface.c' object='go-can-convert-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-can-convert-interface.lo `test -f 'runtime/go-can-convert-interface.c' || echo '$(srcdir)/'`runtime/go-can-convert-interface.c
+
+go-cdiv.lo: runtime/go-cdiv.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-cdiv.lo -MD -MP -MF $(DEPDIR)/go-cdiv.Tpo -c -o go-cdiv.lo `test -f 'runtime/go-cdiv.c' || echo '$(srcdir)/'`runtime/go-cdiv.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-cdiv.Tpo $(DEPDIR)/go-cdiv.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-cdiv.c' object='go-cdiv.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-cdiv.lo `test -f 'runtime/go-cdiv.c' || echo '$(srcdir)/'`runtime/go-cdiv.c
+
+go-cgo.lo: runtime/go-cgo.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-cgo.lo -MD -MP -MF $(DEPDIR)/go-cgo.Tpo -c -o go-cgo.lo `test -f 'runtime/go-cgo.c' || echo '$(srcdir)/'`runtime/go-cgo.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-cgo.Tpo $(DEPDIR)/go-cgo.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-cgo.c' object='go-cgo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-cgo.lo `test -f 'runtime/go-cgo.c' || echo '$(srcdir)/'`runtime/go-cgo.c
+
+go-check-interface.lo: runtime/go-check-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-check-interface.lo -MD -MP -MF $(DEPDIR)/go-check-interface.Tpo -c -o go-check-interface.lo `test -f 'runtime/go-check-interface.c' || echo '$(srcdir)/'`runtime/go-check-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-check-interface.Tpo $(DEPDIR)/go-check-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-check-interface.c' object='go-check-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-check-interface.lo `test -f 'runtime/go-check-interface.c' || echo '$(srcdir)/'`runtime/go-check-interface.c
+
+go-construct-map.lo: runtime/go-construct-map.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-construct-map.lo -MD -MP -MF $(DEPDIR)/go-construct-map.Tpo -c -o go-construct-map.lo `test -f 'runtime/go-construct-map.c' || echo '$(srcdir)/'`runtime/go-construct-map.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-construct-map.Tpo $(DEPDIR)/go-construct-map.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-construct-map.c' object='go-construct-map.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-construct-map.lo `test -f 'runtime/go-construct-map.c' || echo '$(srcdir)/'`runtime/go-construct-map.c
+
+go-convert-interface.lo: runtime/go-convert-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-convert-interface.lo -MD -MP -MF $(DEPDIR)/go-convert-interface.Tpo -c -o go-convert-interface.lo `test -f 'runtime/go-convert-interface.c' || echo '$(srcdir)/'`runtime/go-convert-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-convert-interface.Tpo $(DEPDIR)/go-convert-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-convert-interface.c' object='go-convert-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-convert-interface.lo `test -f 'runtime/go-convert-interface.c' || echo '$(srcdir)/'`runtime/go-convert-interface.c
+
+go-copy.lo: runtime/go-copy.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-copy.lo -MD -MP -MF $(DEPDIR)/go-copy.Tpo -c -o go-copy.lo `test -f 'runtime/go-copy.c' || echo '$(srcdir)/'`runtime/go-copy.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-copy.Tpo $(DEPDIR)/go-copy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-copy.c' object='go-copy.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-copy.lo `test -f 'runtime/go-copy.c' || echo '$(srcdir)/'`runtime/go-copy.c
+
+go-defer.lo: runtime/go-defer.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-defer.lo -MD -MP -MF $(DEPDIR)/go-defer.Tpo -c -o go-defer.lo `test -f 'runtime/go-defer.c' || echo '$(srcdir)/'`runtime/go-defer.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-defer.Tpo $(DEPDIR)/go-defer.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-defer.c' object='go-defer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-defer.lo `test -f 'runtime/go-defer.c' || echo '$(srcdir)/'`runtime/go-defer.c
+
+go-deferred-recover.lo: runtime/go-deferred-recover.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-deferred-recover.lo -MD -MP -MF $(DEPDIR)/go-deferred-recover.Tpo -c -o go-deferred-recover.lo `test -f 'runtime/go-deferred-recover.c' || echo '$(srcdir)/'`runtime/go-deferred-recover.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-deferred-recover.Tpo $(DEPDIR)/go-deferred-recover.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-deferred-recover.c' object='go-deferred-recover.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-deferred-recover.lo `test -f 'runtime/go-deferred-recover.c' || echo '$(srcdir)/'`runtime/go-deferred-recover.c
+
+go-eface-compare.lo: runtime/go-eface-compare.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-eface-compare.lo -MD -MP -MF $(DEPDIR)/go-eface-compare.Tpo -c -o go-eface-compare.lo `test -f 'runtime/go-eface-compare.c' || echo '$(srcdir)/'`runtime/go-eface-compare.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-eface-compare.Tpo $(DEPDIR)/go-eface-compare.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-eface-compare.c' object='go-eface-compare.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-eface-compare.lo `test -f 'runtime/go-eface-compare.c' || echo '$(srcdir)/'`runtime/go-eface-compare.c
+
+go-eface-val-compare.lo: runtime/go-eface-val-compare.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-eface-val-compare.lo -MD -MP -MF $(DEPDIR)/go-eface-val-compare.Tpo -c -o go-eface-val-compare.lo `test -f 'runtime/go-eface-val-compare.c' || echo '$(srcdir)/'`runtime/go-eface-val-compare.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-eface-val-compare.Tpo $(DEPDIR)/go-eface-val-compare.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-eface-val-compare.c' object='go-eface-val-compare.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-eface-val-compare.lo `test -f 'runtime/go-eface-val-compare.c' || echo '$(srcdir)/'`runtime/go-eface-val-compare.c
+
+go-ffi.lo: runtime/go-ffi.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-ffi.lo -MD -MP -MF $(DEPDIR)/go-ffi.Tpo -c -o go-ffi.lo `test -f 'runtime/go-ffi.c' || echo '$(srcdir)/'`runtime/go-ffi.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-ffi.Tpo $(DEPDIR)/go-ffi.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-ffi.c' object='go-ffi.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-ffi.lo `test -f 'runtime/go-ffi.c' || echo '$(srcdir)/'`runtime/go-ffi.c
+
+go-fieldtrack.lo: runtime/go-fieldtrack.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-fieldtrack.lo -MD -MP -MF $(DEPDIR)/go-fieldtrack.Tpo -c -o go-fieldtrack.lo `test -f 'runtime/go-fieldtrack.c' || echo '$(srcdir)/'`runtime/go-fieldtrack.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-fieldtrack.Tpo $(DEPDIR)/go-fieldtrack.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-fieldtrack.c' object='go-fieldtrack.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-fieldtrack.lo `test -f 'runtime/go-fieldtrack.c' || echo '$(srcdir)/'`runtime/go-fieldtrack.c
+
+go-int-array-to-string.lo: runtime/go-int-array-to-string.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-int-array-to-string.lo -MD -MP -MF $(DEPDIR)/go-int-array-to-string.Tpo -c -o go-int-array-to-string.lo `test -f 'runtime/go-int-array-to-string.c' || echo '$(srcdir)/'`runtime/go-int-array-to-string.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-int-array-to-string.Tpo $(DEPDIR)/go-int-array-to-string.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-int-array-to-string.c' object='go-int-array-to-string.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-int-array-to-string.lo `test -f 'runtime/go-int-array-to-string.c' || echo '$(srcdir)/'`runtime/go-int-array-to-string.c
+
+go-int-to-string.lo: runtime/go-int-to-string.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-int-to-string.lo -MD -MP -MF $(DEPDIR)/go-int-to-string.Tpo -c -o go-int-to-string.lo `test -f 'runtime/go-int-to-string.c' || echo '$(srcdir)/'`runtime/go-int-to-string.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-int-to-string.Tpo $(DEPDIR)/go-int-to-string.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-int-to-string.c' object='go-int-to-string.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-int-to-string.lo `test -f 'runtime/go-int-to-string.c' || echo '$(srcdir)/'`runtime/go-int-to-string.c
+
+go-interface-compare.lo: runtime/go-interface-compare.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-interface-compare.lo -MD -MP -MF $(DEPDIR)/go-interface-compare.Tpo -c -o go-interface-compare.lo `test -f 'runtime/go-interface-compare.c' || echo '$(srcdir)/'`runtime/go-interface-compare.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-interface-compare.Tpo $(DEPDIR)/go-interface-compare.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-interface-compare.c' object='go-interface-compare.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-interface-compare.lo `test -f 'runtime/go-interface-compare.c' || echo '$(srcdir)/'`runtime/go-interface-compare.c
+
+go-interface-eface-compare.lo: runtime/go-interface-eface-compare.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-interface-eface-compare.lo -MD -MP -MF $(DEPDIR)/go-interface-eface-compare.Tpo -c -o go-interface-eface-compare.lo `test -f 'runtime/go-interface-eface-compare.c' || echo '$(srcdir)/'`runtime/go-interface-eface-compare.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-interface-eface-compare.Tpo $(DEPDIR)/go-interface-eface-compare.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-interface-eface-compare.c' object='go-interface-eface-compare.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-interface-eface-compare.lo `test -f 'runtime/go-interface-eface-compare.c' || echo '$(srcdir)/'`runtime/go-interface-eface-compare.c
+
+go-interface-val-compare.lo: runtime/go-interface-val-compare.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-interface-val-compare.lo -MD -MP -MF $(DEPDIR)/go-interface-val-compare.Tpo -c -o go-interface-val-compare.lo `test -f 'runtime/go-interface-val-compare.c' || echo '$(srcdir)/'`runtime/go-interface-val-compare.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-interface-val-compare.Tpo $(DEPDIR)/go-interface-val-compare.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-interface-val-compare.c' object='go-interface-val-compare.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-interface-val-compare.lo `test -f 'runtime/go-interface-val-compare.c' || echo '$(srcdir)/'`runtime/go-interface-val-compare.c
+
+go-make-slice.lo: runtime/go-make-slice.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-make-slice.lo -MD -MP -MF $(DEPDIR)/go-make-slice.Tpo -c -o go-make-slice.lo `test -f 'runtime/go-make-slice.c' || echo '$(srcdir)/'`runtime/go-make-slice.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-make-slice.Tpo $(DEPDIR)/go-make-slice.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-make-slice.c' object='go-make-slice.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-make-slice.lo `test -f 'runtime/go-make-slice.c' || echo '$(srcdir)/'`runtime/go-make-slice.c
+
+go-map-delete.lo: runtime/go-map-delete.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-map-delete.lo -MD -MP -MF $(DEPDIR)/go-map-delete.Tpo -c -o go-map-delete.lo `test -f 'runtime/go-map-delete.c' || echo '$(srcdir)/'`runtime/go-map-delete.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-map-delete.Tpo $(DEPDIR)/go-map-delete.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-map-delete.c' object='go-map-delete.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-map-delete.lo `test -f 'runtime/go-map-delete.c' || echo '$(srcdir)/'`runtime/go-map-delete.c
+
+go-map-index.lo: runtime/go-map-index.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-map-index.lo -MD -MP -MF $(DEPDIR)/go-map-index.Tpo -c -o go-map-index.lo `test -f 'runtime/go-map-index.c' || echo '$(srcdir)/'`runtime/go-map-index.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-map-index.Tpo $(DEPDIR)/go-map-index.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-map-index.c' object='go-map-index.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-map-index.lo `test -f 'runtime/go-map-index.c' || echo '$(srcdir)/'`runtime/go-map-index.c
+
+go-map-len.lo: runtime/go-map-len.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-map-len.lo -MD -MP -MF $(DEPDIR)/go-map-len.Tpo -c -o go-map-len.lo `test -f 'runtime/go-map-len.c' || echo '$(srcdir)/'`runtime/go-map-len.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-map-len.Tpo $(DEPDIR)/go-map-len.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-map-len.c' object='go-map-len.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-map-len.lo `test -f 'runtime/go-map-len.c' || echo '$(srcdir)/'`runtime/go-map-len.c
+
+go-map-range.lo: runtime/go-map-range.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-map-range.lo -MD -MP -MF $(DEPDIR)/go-map-range.Tpo -c -o go-map-range.lo `test -f 'runtime/go-map-range.c' || echo '$(srcdir)/'`runtime/go-map-range.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-map-range.Tpo $(DEPDIR)/go-map-range.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-map-range.c' object='go-map-range.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-map-range.lo `test -f 'runtime/go-map-range.c' || echo '$(srcdir)/'`runtime/go-map-range.c
+
+go-matherr.lo: runtime/go-matherr.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-matherr.lo -MD -MP -MF $(DEPDIR)/go-matherr.Tpo -c -o go-matherr.lo `test -f 'runtime/go-matherr.c' || echo '$(srcdir)/'`runtime/go-matherr.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-matherr.Tpo $(DEPDIR)/go-matherr.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-matherr.c' object='go-matherr.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-matherr.lo `test -f 'runtime/go-matherr.c' || echo '$(srcdir)/'`runtime/go-matherr.c
+
+go-memcmp.lo: runtime/go-memcmp.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-memcmp.lo -MD -MP -MF $(DEPDIR)/go-memcmp.Tpo -c -o go-memcmp.lo `test -f 'runtime/go-memcmp.c' || echo '$(srcdir)/'`runtime/go-memcmp.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-memcmp.Tpo $(DEPDIR)/go-memcmp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-memcmp.c' object='go-memcmp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-memcmp.lo `test -f 'runtime/go-memcmp.c' || echo '$(srcdir)/'`runtime/go-memcmp.c
+
+go-nanotime.lo: runtime/go-nanotime.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-nanotime.lo -MD -MP -MF $(DEPDIR)/go-nanotime.Tpo -c -o go-nanotime.lo `test -f 'runtime/go-nanotime.c' || echo '$(srcdir)/'`runtime/go-nanotime.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-nanotime.Tpo $(DEPDIR)/go-nanotime.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-nanotime.c' object='go-nanotime.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-nanotime.lo `test -f 'runtime/go-nanotime.c' || echo '$(srcdir)/'`runtime/go-nanotime.c
+
+go-now.lo: runtime/go-now.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-now.lo -MD -MP -MF $(DEPDIR)/go-now.Tpo -c -o go-now.lo `test -f 'runtime/go-now.c' || echo '$(srcdir)/'`runtime/go-now.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-now.Tpo $(DEPDIR)/go-now.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-now.c' object='go-now.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-now.lo `test -f 'runtime/go-now.c' || echo '$(srcdir)/'`runtime/go-now.c
+
+go-new-map.lo: runtime/go-new-map.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-new-map.lo -MD -MP -MF $(DEPDIR)/go-new-map.Tpo -c -o go-new-map.lo `test -f 'runtime/go-new-map.c' || echo '$(srcdir)/'`runtime/go-new-map.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-new-map.Tpo $(DEPDIR)/go-new-map.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-new-map.c' object='go-new-map.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-new-map.lo `test -f 'runtime/go-new-map.c' || echo '$(srcdir)/'`runtime/go-new-map.c
+
+go-new.lo: runtime/go-new.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-new.lo -MD -MP -MF $(DEPDIR)/go-new.Tpo -c -o go-new.lo `test -f 'runtime/go-new.c' || echo '$(srcdir)/'`runtime/go-new.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-new.Tpo $(DEPDIR)/go-new.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-new.c' object='go-new.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-new.lo `test -f 'runtime/go-new.c' || echo '$(srcdir)/'`runtime/go-new.c
+
+go-nosys.lo: runtime/go-nosys.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-nosys.lo -MD -MP -MF $(DEPDIR)/go-nosys.Tpo -c -o go-nosys.lo `test -f 'runtime/go-nosys.c' || echo '$(srcdir)/'`runtime/go-nosys.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-nosys.Tpo $(DEPDIR)/go-nosys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-nosys.c' object='go-nosys.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-nosys.lo `test -f 'runtime/go-nosys.c' || echo '$(srcdir)/'`runtime/go-nosys.c
+
+go-panic.lo: runtime/go-panic.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-panic.lo -MD -MP -MF $(DEPDIR)/go-panic.Tpo -c -o go-panic.lo `test -f 'runtime/go-panic.c' || echo '$(srcdir)/'`runtime/go-panic.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-panic.Tpo $(DEPDIR)/go-panic.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-panic.c' object='go-panic.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-panic.lo `test -f 'runtime/go-panic.c' || echo '$(srcdir)/'`runtime/go-panic.c
+
+go-print.lo: runtime/go-print.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-print.lo -MD -MP -MF $(DEPDIR)/go-print.Tpo -c -o go-print.lo `test -f 'runtime/go-print.c' || echo '$(srcdir)/'`runtime/go-print.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-print.Tpo $(DEPDIR)/go-print.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-print.c' object='go-print.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-print.lo `test -f 'runtime/go-print.c' || echo '$(srcdir)/'`runtime/go-print.c
+
+go-recover.lo: runtime/go-recover.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-recover.lo -MD -MP -MF $(DEPDIR)/go-recover.Tpo -c -o go-recover.lo `test -f 'runtime/go-recover.c' || echo '$(srcdir)/'`runtime/go-recover.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-recover.Tpo $(DEPDIR)/go-recover.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-recover.c' object='go-recover.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-recover.lo `test -f 'runtime/go-recover.c' || echo '$(srcdir)/'`runtime/go-recover.c
+
+go-reflect-call.lo: runtime/go-reflect-call.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-reflect-call.lo -MD -MP -MF $(DEPDIR)/go-reflect-call.Tpo -c -o go-reflect-call.lo `test -f 'runtime/go-reflect-call.c' || echo '$(srcdir)/'`runtime/go-reflect-call.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-reflect-call.Tpo $(DEPDIR)/go-reflect-call.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-reflect-call.c' object='go-reflect-call.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-reflect-call.lo `test -f 'runtime/go-reflect-call.c' || echo '$(srcdir)/'`runtime/go-reflect-call.c
+
+go-reflect-map.lo: runtime/go-reflect-map.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-reflect-map.lo -MD -MP -MF $(DEPDIR)/go-reflect-map.Tpo -c -o go-reflect-map.lo `test -f 'runtime/go-reflect-map.c' || echo '$(srcdir)/'`runtime/go-reflect-map.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-reflect-map.Tpo $(DEPDIR)/go-reflect-map.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-reflect-map.c' object='go-reflect-map.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-reflect-map.lo `test -f 'runtime/go-reflect-map.c' || echo '$(srcdir)/'`runtime/go-reflect-map.c
+
+go-rune.lo: runtime/go-rune.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rune.lo -MD -MP -MF $(DEPDIR)/go-rune.Tpo -c -o go-rune.lo `test -f 'runtime/go-rune.c' || echo '$(srcdir)/'`runtime/go-rune.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-rune.Tpo $(DEPDIR)/go-rune.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-rune.c' object='go-rune.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-rune.lo `test -f 'runtime/go-rune.c' || echo '$(srcdir)/'`runtime/go-rune.c
+
+go-runtime-error.lo: runtime/go-runtime-error.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-runtime-error.lo -MD -MP -MF $(DEPDIR)/go-runtime-error.Tpo -c -o go-runtime-error.lo `test -f 'runtime/go-runtime-error.c' || echo '$(srcdir)/'`runtime/go-runtime-error.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-runtime-error.Tpo $(DEPDIR)/go-runtime-error.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-runtime-error.c' object='go-runtime-error.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-runtime-error.lo `test -f 'runtime/go-runtime-error.c' || echo '$(srcdir)/'`runtime/go-runtime-error.c
+
+go-setenv.lo: runtime/go-setenv.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-setenv.lo -MD -MP -MF $(DEPDIR)/go-setenv.Tpo -c -o go-setenv.lo `test -f 'runtime/go-setenv.c' || echo '$(srcdir)/'`runtime/go-setenv.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-setenv.Tpo $(DEPDIR)/go-setenv.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-setenv.c' object='go-setenv.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-setenv.lo `test -f 'runtime/go-setenv.c' || echo '$(srcdir)/'`runtime/go-setenv.c
+
+go-signal.lo: runtime/go-signal.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-signal.lo -MD -MP -MF $(DEPDIR)/go-signal.Tpo -c -o go-signal.lo `test -f 'runtime/go-signal.c' || echo '$(srcdir)/'`runtime/go-signal.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-signal.Tpo $(DEPDIR)/go-signal.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-signal.c' object='go-signal.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-signal.lo `test -f 'runtime/go-signal.c' || echo '$(srcdir)/'`runtime/go-signal.c
+
+go-strcmp.lo: runtime/go-strcmp.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-strcmp.lo -MD -MP -MF $(DEPDIR)/go-strcmp.Tpo -c -o go-strcmp.lo `test -f 'runtime/go-strcmp.c' || echo '$(srcdir)/'`runtime/go-strcmp.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-strcmp.Tpo $(DEPDIR)/go-strcmp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-strcmp.c' object='go-strcmp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-strcmp.lo `test -f 'runtime/go-strcmp.c' || echo '$(srcdir)/'`runtime/go-strcmp.c
+
+go-string-to-byte-array.lo: runtime/go-string-to-byte-array.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-string-to-byte-array.lo -MD -MP -MF $(DEPDIR)/go-string-to-byte-array.Tpo -c -o go-string-to-byte-array.lo `test -f 'runtime/go-string-to-byte-array.c' || echo '$(srcdir)/'`runtime/go-string-to-byte-array.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-string-to-byte-array.Tpo $(DEPDIR)/go-string-to-byte-array.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-string-to-byte-array.c' object='go-string-to-byte-array.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-string-to-byte-array.lo `test -f 'runtime/go-string-to-byte-array.c' || echo '$(srcdir)/'`runtime/go-string-to-byte-array.c
+
+go-string-to-int-array.lo: runtime/go-string-to-int-array.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-string-to-int-array.lo -MD -MP -MF $(DEPDIR)/go-string-to-int-array.Tpo -c -o go-string-to-int-array.lo `test -f 'runtime/go-string-to-int-array.c' || echo '$(srcdir)/'`runtime/go-string-to-int-array.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-string-to-int-array.Tpo $(DEPDIR)/go-string-to-int-array.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-string-to-int-array.c' object='go-string-to-int-array.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-string-to-int-array.lo `test -f 'runtime/go-string-to-int-array.c' || echo '$(srcdir)/'`runtime/go-string-to-int-array.c
+
+go-strplus.lo: runtime/go-strplus.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-strplus.lo -MD -MP -MF $(DEPDIR)/go-strplus.Tpo -c -o go-strplus.lo `test -f 'runtime/go-strplus.c' || echo '$(srcdir)/'`runtime/go-strplus.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-strplus.Tpo $(DEPDIR)/go-strplus.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-strplus.c' object='go-strplus.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-strplus.lo `test -f 'runtime/go-strplus.c' || echo '$(srcdir)/'`runtime/go-strplus.c
+
+go-strslice.lo: runtime/go-strslice.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-strslice.lo -MD -MP -MF $(DEPDIR)/go-strslice.Tpo -c -o go-strslice.lo `test -f 'runtime/go-strslice.c' || echo '$(srcdir)/'`runtime/go-strslice.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-strslice.Tpo $(DEPDIR)/go-strslice.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-strslice.c' object='go-strslice.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-strslice.lo `test -f 'runtime/go-strslice.c' || echo '$(srcdir)/'`runtime/go-strslice.c
+
+go-traceback.lo: runtime/go-traceback.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-traceback.lo -MD -MP -MF $(DEPDIR)/go-traceback.Tpo -c -o go-traceback.lo `test -f 'runtime/go-traceback.c' || echo '$(srcdir)/'`runtime/go-traceback.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-traceback.Tpo $(DEPDIR)/go-traceback.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-traceback.c' object='go-traceback.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-traceback.lo `test -f 'runtime/go-traceback.c' || echo '$(srcdir)/'`runtime/go-traceback.c
+
+go-type-complex.lo: runtime/go-type-complex.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-complex.lo -MD -MP -MF $(DEPDIR)/go-type-complex.Tpo -c -o go-type-complex.lo `test -f 'runtime/go-type-complex.c' || echo '$(srcdir)/'`runtime/go-type-complex.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-type-complex.Tpo $(DEPDIR)/go-type-complex.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-type-complex.c' object='go-type-complex.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-complex.lo `test -f 'runtime/go-type-complex.c' || echo '$(srcdir)/'`runtime/go-type-complex.c
+
+go-type-eface.lo: runtime/go-type-eface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-eface.lo -MD -MP -MF $(DEPDIR)/go-type-eface.Tpo -c -o go-type-eface.lo `test -f 'runtime/go-type-eface.c' || echo '$(srcdir)/'`runtime/go-type-eface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-type-eface.Tpo $(DEPDIR)/go-type-eface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-type-eface.c' object='go-type-eface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-eface.lo `test -f 'runtime/go-type-eface.c' || echo '$(srcdir)/'`runtime/go-type-eface.c
+
+go-type-error.lo: runtime/go-type-error.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-error.lo -MD -MP -MF $(DEPDIR)/go-type-error.Tpo -c -o go-type-error.lo `test -f 'runtime/go-type-error.c' || echo '$(srcdir)/'`runtime/go-type-error.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-type-error.Tpo $(DEPDIR)/go-type-error.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-type-error.c' object='go-type-error.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-error.lo `test -f 'runtime/go-type-error.c' || echo '$(srcdir)/'`runtime/go-type-error.c
+
+go-type-float.lo: runtime/go-type-float.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-float.lo -MD -MP -MF $(DEPDIR)/go-type-float.Tpo -c -o go-type-float.lo `test -f 'runtime/go-type-float.c' || echo '$(srcdir)/'`runtime/go-type-float.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-type-float.Tpo $(DEPDIR)/go-type-float.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-type-float.c' object='go-type-float.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-float.lo `test -f 'runtime/go-type-float.c' || echo '$(srcdir)/'`runtime/go-type-float.c
+
+go-type-identity.lo: runtime/go-type-identity.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-identity.lo -MD -MP -MF $(DEPDIR)/go-type-identity.Tpo -c -o go-type-identity.lo `test -f 'runtime/go-type-identity.c' || echo '$(srcdir)/'`runtime/go-type-identity.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-type-identity.Tpo $(DEPDIR)/go-type-identity.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-type-identity.c' object='go-type-identity.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-identity.lo `test -f 'runtime/go-type-identity.c' || echo '$(srcdir)/'`runtime/go-type-identity.c
+
+go-type-interface.lo: runtime/go-type-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-interface.lo -MD -MP -MF $(DEPDIR)/go-type-interface.Tpo -c -o go-type-interface.lo `test -f 'runtime/go-type-interface.c' || echo '$(srcdir)/'`runtime/go-type-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-type-interface.Tpo $(DEPDIR)/go-type-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-type-interface.c' object='go-type-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-interface.lo `test -f 'runtime/go-type-interface.c' || echo '$(srcdir)/'`runtime/go-type-interface.c
+
+go-type-string.lo: runtime/go-type-string.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-string.lo -MD -MP -MF $(DEPDIR)/go-type-string.Tpo -c -o go-type-string.lo `test -f 'runtime/go-type-string.c' || echo '$(srcdir)/'`runtime/go-type-string.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-type-string.Tpo $(DEPDIR)/go-type-string.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-type-string.c' object='go-type-string.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-string.lo `test -f 'runtime/go-type-string.c' || echo '$(srcdir)/'`runtime/go-type-string.c
+
+go-typedesc-equal.lo: runtime/go-typedesc-equal.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-typedesc-equal.lo -MD -MP -MF $(DEPDIR)/go-typedesc-equal.Tpo -c -o go-typedesc-equal.lo `test -f 'runtime/go-typedesc-equal.c' || echo '$(srcdir)/'`runtime/go-typedesc-equal.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-typedesc-equal.Tpo $(DEPDIR)/go-typedesc-equal.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-typedesc-equal.c' object='go-typedesc-equal.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-typedesc-equal.lo `test -f 'runtime/go-typedesc-equal.c' || echo '$(srcdir)/'`runtime/go-typedesc-equal.c
+
+go-unsafe-new.lo: runtime/go-unsafe-new.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-unsafe-new.lo -MD -MP -MF $(DEPDIR)/go-unsafe-new.Tpo -c -o go-unsafe-new.lo `test -f 'runtime/go-unsafe-new.c' || echo '$(srcdir)/'`runtime/go-unsafe-new.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-unsafe-new.Tpo $(DEPDIR)/go-unsafe-new.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-unsafe-new.c' object='go-unsafe-new.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-unsafe-new.lo `test -f 'runtime/go-unsafe-new.c' || echo '$(srcdir)/'`runtime/go-unsafe-new.c
+
+go-unsafe-newarray.lo: runtime/go-unsafe-newarray.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-unsafe-newarray.lo -MD -MP -MF $(DEPDIR)/go-unsafe-newarray.Tpo -c -o go-unsafe-newarray.lo `test -f 'runtime/go-unsafe-newarray.c' || echo '$(srcdir)/'`runtime/go-unsafe-newarray.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-unsafe-newarray.Tpo $(DEPDIR)/go-unsafe-newarray.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-unsafe-newarray.c' object='go-unsafe-newarray.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-unsafe-newarray.lo `test -f 'runtime/go-unsafe-newarray.c' || echo '$(srcdir)/'`runtime/go-unsafe-newarray.c
+
+go-unsafe-pointer.lo: runtime/go-unsafe-pointer.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-unsafe-pointer.lo -MD -MP -MF $(DEPDIR)/go-unsafe-pointer.Tpo -c -o go-unsafe-pointer.lo `test -f 'runtime/go-unsafe-pointer.c' || echo '$(srcdir)/'`runtime/go-unsafe-pointer.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-unsafe-pointer.Tpo $(DEPDIR)/go-unsafe-pointer.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-unsafe-pointer.c' object='go-unsafe-pointer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-unsafe-pointer.lo `test -f 'runtime/go-unsafe-pointer.c' || echo '$(srcdir)/'`runtime/go-unsafe-pointer.c
+
+go-unwind.lo: runtime/go-unwind.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-unwind.lo -MD -MP -MF $(DEPDIR)/go-unwind.Tpo -c -o go-unwind.lo `test -f 'runtime/go-unwind.c' || echo '$(srcdir)/'`runtime/go-unwind.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-unwind.Tpo $(DEPDIR)/go-unwind.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-unwind.c' object='go-unwind.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-unwind.lo `test -f 'runtime/go-unwind.c' || echo '$(srcdir)/'`runtime/go-unwind.c
+
+go-varargs.lo: runtime/go-varargs.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-varargs.lo -MD -MP -MF $(DEPDIR)/go-varargs.Tpo -c -o go-varargs.lo `test -f 'runtime/go-varargs.c' || echo '$(srcdir)/'`runtime/go-varargs.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/go-varargs.Tpo $(DEPDIR)/go-varargs.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/go-varargs.c' object='go-varargs.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-varargs.lo `test -f 'runtime/go-varargs.c' || echo '$(srcdir)/'`runtime/go-varargs.c
+
+env_posix.lo: runtime/env_posix.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT env_posix.lo -MD -MP -MF $(DEPDIR)/env_posix.Tpo -c -o env_posix.lo `test -f 'runtime/env_posix.c' || echo '$(srcdir)/'`runtime/env_posix.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/env_posix.Tpo $(DEPDIR)/env_posix.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/env_posix.c' object='env_posix.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o env_posix.lo `test -f 'runtime/env_posix.c' || echo '$(srcdir)/'`runtime/env_posix.c
+
+heapdump.lo: runtime/heapdump.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT heapdump.lo -MD -MP -MF $(DEPDIR)/heapdump.Tpo -c -o heapdump.lo `test -f 'runtime/heapdump.c' || echo '$(srcdir)/'`runtime/heapdump.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/heapdump.Tpo $(DEPDIR)/heapdump.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/heapdump.c' object='heapdump.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o heapdump.lo `test -f 'runtime/heapdump.c' || echo '$(srcdir)/'`runtime/heapdump.c
+
+lock_sema.lo: runtime/lock_sema.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lock_sema.lo -MD -MP -MF $(DEPDIR)/lock_sema.Tpo -c -o lock_sema.lo `test -f 'runtime/lock_sema.c' || echo '$(srcdir)/'`runtime/lock_sema.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/lock_sema.Tpo $(DEPDIR)/lock_sema.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/lock_sema.c' object='lock_sema.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lock_sema.lo `test -f 'runtime/lock_sema.c' || echo '$(srcdir)/'`runtime/lock_sema.c
+
+thread-sema.lo: runtime/thread-sema.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread-sema.lo -MD -MP -MF $(DEPDIR)/thread-sema.Tpo -c -o thread-sema.lo `test -f 'runtime/thread-sema.c' || echo '$(srcdir)/'`runtime/thread-sema.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/thread-sema.Tpo $(DEPDIR)/thread-sema.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/thread-sema.c' object='thread-sema.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread-sema.lo `test -f 'runtime/thread-sema.c' || echo '$(srcdir)/'`runtime/thread-sema.c
+
+lock_futex.lo: runtime/lock_futex.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lock_futex.lo -MD -MP -MF $(DEPDIR)/lock_futex.Tpo -c -o lock_futex.lo `test -f 'runtime/lock_futex.c' || echo '$(srcdir)/'`runtime/lock_futex.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/lock_futex.Tpo $(DEPDIR)/lock_futex.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/lock_futex.c' object='lock_futex.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lock_futex.lo `test -f 'runtime/lock_futex.c' || echo '$(srcdir)/'`runtime/lock_futex.c
+
+thread-linux.lo: runtime/thread-linux.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread-linux.lo -MD -MP -MF $(DEPDIR)/thread-linux.Tpo -c -o thread-linux.lo `test -f 'runtime/thread-linux.c' || echo '$(srcdir)/'`runtime/thread-linux.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/thread-linux.Tpo $(DEPDIR)/thread-linux.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/thread-linux.c' object='thread-linux.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread-linux.lo `test -f 'runtime/thread-linux.c' || echo '$(srcdir)/'`runtime/thread-linux.c
+
+mcache.lo: runtime/mcache.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mcache.lo -MD -MP -MF $(DEPDIR)/mcache.Tpo -c -o mcache.lo `test -f 'runtime/mcache.c' || echo '$(srcdir)/'`runtime/mcache.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mcache.Tpo $(DEPDIR)/mcache.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/mcache.c' object='mcache.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mcache.lo `test -f 'runtime/mcache.c' || echo '$(srcdir)/'`runtime/mcache.c
+
+mcentral.lo: runtime/mcentral.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mcentral.lo -MD -MP -MF $(DEPDIR)/mcentral.Tpo -c -o mcentral.lo `test -f 'runtime/mcentral.c' || echo '$(srcdir)/'`runtime/mcentral.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mcentral.Tpo $(DEPDIR)/mcentral.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/mcentral.c' object='mcentral.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mcentral.lo `test -f 'runtime/mcentral.c' || echo '$(srcdir)/'`runtime/mcentral.c
+
+mem_posix_memalign.lo: runtime/mem_posix_memalign.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mem_posix_memalign.lo -MD -MP -MF $(DEPDIR)/mem_posix_memalign.Tpo -c -o mem_posix_memalign.lo `test -f 'runtime/mem_posix_memalign.c' || echo '$(srcdir)/'`runtime/mem_posix_memalign.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mem_posix_memalign.Tpo $(DEPDIR)/mem_posix_memalign.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/mem_posix_memalign.c' object='mem_posix_memalign.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mem_posix_memalign.lo `test -f 'runtime/mem_posix_memalign.c' || echo '$(srcdir)/'`runtime/mem_posix_memalign.c
+
+mem.lo: runtime/mem.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mem.lo -MD -MP -MF $(DEPDIR)/mem.Tpo -c -o mem.lo `test -f 'runtime/mem.c' || echo '$(srcdir)/'`runtime/mem.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mem.Tpo $(DEPDIR)/mem.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/mem.c' object='mem.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mem.lo `test -f 'runtime/mem.c' || echo '$(srcdir)/'`runtime/mem.c
+
+mfixalloc.lo: runtime/mfixalloc.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mfixalloc.lo -MD -MP -MF $(DEPDIR)/mfixalloc.Tpo -c -o mfixalloc.lo `test -f 'runtime/mfixalloc.c' || echo '$(srcdir)/'`runtime/mfixalloc.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mfixalloc.Tpo $(DEPDIR)/mfixalloc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/mfixalloc.c' object='mfixalloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mfixalloc.lo `test -f 'runtime/mfixalloc.c' || echo '$(srcdir)/'`runtime/mfixalloc.c
+
+mgc0.lo: runtime/mgc0.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mgc0.lo -MD -MP -MF $(DEPDIR)/mgc0.Tpo -c -o mgc0.lo `test -f 'runtime/mgc0.c' || echo '$(srcdir)/'`runtime/mgc0.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mgc0.Tpo $(DEPDIR)/mgc0.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/mgc0.c' object='mgc0.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mgc0.lo `test -f 'runtime/mgc0.c' || echo '$(srcdir)/'`runtime/mgc0.c
+
+mheap.lo: runtime/mheap.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mheap.lo -MD -MP -MF $(DEPDIR)/mheap.Tpo -c -o mheap.lo `test -f 'runtime/mheap.c' || echo '$(srcdir)/'`runtime/mheap.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mheap.Tpo $(DEPDIR)/mheap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/mheap.c' object='mheap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mheap.lo `test -f 'runtime/mheap.c' || echo '$(srcdir)/'`runtime/mheap.c
+
+msize.lo: runtime/msize.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT msize.lo -MD -MP -MF $(DEPDIR)/msize.Tpo -c -o msize.lo `test -f 'runtime/msize.c' || echo '$(srcdir)/'`runtime/msize.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/msize.Tpo $(DEPDIR)/msize.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/msize.c' object='msize.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msize.lo `test -f 'runtime/msize.c' || echo '$(srcdir)/'`runtime/msize.c
+
+netpoll_kqueue.lo: runtime/netpoll_kqueue.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netpoll_kqueue.lo -MD -MP -MF $(DEPDIR)/netpoll_kqueue.Tpo -c -o netpoll_kqueue.lo `test -f 'runtime/netpoll_kqueue.c' || echo '$(srcdir)/'`runtime/netpoll_kqueue.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/netpoll_kqueue.Tpo $(DEPDIR)/netpoll_kqueue.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/netpoll_kqueue.c' object='netpoll_kqueue.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netpoll_kqueue.lo `test -f 'runtime/netpoll_kqueue.c' || echo '$(srcdir)/'`runtime/netpoll_kqueue.c
+
+netpoll_select.lo: runtime/netpoll_select.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netpoll_select.lo -MD -MP -MF $(DEPDIR)/netpoll_select.Tpo -c -o netpoll_select.lo `test -f 'runtime/netpoll_select.c' || echo '$(srcdir)/'`runtime/netpoll_select.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/netpoll_select.Tpo $(DEPDIR)/netpoll_select.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/netpoll_select.c' object='netpoll_select.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netpoll_select.lo `test -f 'runtime/netpoll_select.c' || echo '$(srcdir)/'`runtime/netpoll_select.c
+
+netpoll_epoll.lo: runtime/netpoll_epoll.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netpoll_epoll.lo -MD -MP -MF $(DEPDIR)/netpoll_epoll.Tpo -c -o netpoll_epoll.lo `test -f 'runtime/netpoll_epoll.c' || echo '$(srcdir)/'`runtime/netpoll_epoll.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/netpoll_epoll.Tpo $(DEPDIR)/netpoll_epoll.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/netpoll_epoll.c' object='netpoll_epoll.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netpoll_epoll.lo `test -f 'runtime/netpoll_epoll.c' || echo '$(srcdir)/'`runtime/netpoll_epoll.c
+
+panic.lo: runtime/panic.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT panic.lo -MD -MP -MF $(DEPDIR)/panic.Tpo -c -o panic.lo `test -f 'runtime/panic.c' || echo '$(srcdir)/'`runtime/panic.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/panic.Tpo $(DEPDIR)/panic.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/panic.c' object='panic.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o panic.lo `test -f 'runtime/panic.c' || echo '$(srcdir)/'`runtime/panic.c
+
+parfor.lo: runtime/parfor.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT parfor.lo -MD -MP -MF $(DEPDIR)/parfor.Tpo -c -o parfor.lo `test -f 'runtime/parfor.c' || echo '$(srcdir)/'`runtime/parfor.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/parfor.Tpo $(DEPDIR)/parfor.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/parfor.c' object='parfor.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o parfor.lo `test -f 'runtime/parfor.c' || echo '$(srcdir)/'`runtime/parfor.c
+
+print.lo: runtime/print.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT print.lo -MD -MP -MF $(DEPDIR)/print.Tpo -c -o print.lo `test -f 'runtime/print.c' || echo '$(srcdir)/'`runtime/print.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/print.Tpo $(DEPDIR)/print.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/print.c' object='print.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o print.lo `test -f 'runtime/print.c' || echo '$(srcdir)/'`runtime/print.c
+
+proc.lo: runtime/proc.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT proc.lo -MD -MP -MF $(DEPDIR)/proc.Tpo -c -o proc.lo `test -f 'runtime/proc.c' || echo '$(srcdir)/'`runtime/proc.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/proc.Tpo $(DEPDIR)/proc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/proc.c' object='proc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proc.lo `test -f 'runtime/proc.c' || echo '$(srcdir)/'`runtime/proc.c
+
+runtime.lo: runtime/runtime.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT runtime.lo -MD -MP -MF $(DEPDIR)/runtime.Tpo -c -o runtime.lo `test -f 'runtime/runtime.c' || echo '$(srcdir)/'`runtime/runtime.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/runtime.Tpo $(DEPDIR)/runtime.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/runtime.c' object='runtime.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o runtime.lo `test -f 'runtime/runtime.c' || echo '$(srcdir)/'`runtime/runtime.c
+
+signal_unix.lo: runtime/signal_unix.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT signal_unix.lo -MD -MP -MF $(DEPDIR)/signal_unix.Tpo -c -o signal_unix.lo `test -f 'runtime/signal_unix.c' || echo '$(srcdir)/'`runtime/signal_unix.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/signal_unix.Tpo $(DEPDIR)/signal_unix.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/signal_unix.c' object='signal_unix.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o signal_unix.lo `test -f 'runtime/signal_unix.c' || echo '$(srcdir)/'`runtime/signal_unix.c
+
+thread.lo: runtime/thread.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread.lo -MD -MP -MF $(DEPDIR)/thread.Tpo -c -o thread.lo `test -f 'runtime/thread.c' || echo '$(srcdir)/'`runtime/thread.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/thread.Tpo $(DEPDIR)/thread.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/thread.c' object='thread.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread.lo `test -f 'runtime/thread.c' || echo '$(srcdir)/'`runtime/thread.c
+
+yield.lo: runtime/yield.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT yield.lo -MD -MP -MF $(DEPDIR)/yield.Tpo -c -o yield.lo `test -f 'runtime/yield.c' || echo '$(srcdir)/'`runtime/yield.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/yield.Tpo $(DEPDIR)/yield.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/yield.c' object='yield.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o yield.lo `test -f 'runtime/yield.c' || echo '$(srcdir)/'`runtime/yield.c
+
+rtems-task-variable-add.lo: runtime/rtems-task-variable-add.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rtems-task-variable-add.lo -MD -MP -MF $(DEPDIR)/rtems-task-variable-add.Tpo -c -o rtems-task-variable-add.lo `test -f 'runtime/rtems-task-variable-add.c' || echo '$(srcdir)/'`runtime/rtems-task-variable-add.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/rtems-task-variable-add.Tpo $(DEPDIR)/rtems-task-variable-add.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/rtems-task-variable-add.c' object='rtems-task-variable-add.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rtems-task-variable-add.lo `test -f 'runtime/rtems-task-variable-add.c' || echo '$(srcdir)/'`runtime/rtems-task-variable-add.c
+
+getncpu-none.lo: runtime/getncpu-none.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getncpu-none.lo -MD -MP -MF $(DEPDIR)/getncpu-none.Tpo -c -o getncpu-none.lo `test -f 'runtime/getncpu-none.c' || echo '$(srcdir)/'`runtime/getncpu-none.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/getncpu-none.Tpo $(DEPDIR)/getncpu-none.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/getncpu-none.c' object='getncpu-none.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getncpu-none.lo `test -f 'runtime/getncpu-none.c' || echo '$(srcdir)/'`runtime/getncpu-none.c
+
+getncpu-bsd.lo: runtime/getncpu-bsd.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getncpu-bsd.lo -MD -MP -MF $(DEPDIR)/getncpu-bsd.Tpo -c -o getncpu-bsd.lo `test -f 'runtime/getncpu-bsd.c' || echo '$(srcdir)/'`runtime/getncpu-bsd.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/getncpu-bsd.Tpo $(DEPDIR)/getncpu-bsd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/getncpu-bsd.c' object='getncpu-bsd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getncpu-bsd.lo `test -f 'runtime/getncpu-bsd.c' || echo '$(srcdir)/'`runtime/getncpu-bsd.c
+
+getncpu-solaris.lo: runtime/getncpu-solaris.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getncpu-solaris.lo -MD -MP -MF $(DEPDIR)/getncpu-solaris.Tpo -c -o getncpu-solaris.lo `test -f 'runtime/getncpu-solaris.c' || echo '$(srcdir)/'`runtime/getncpu-solaris.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/getncpu-solaris.Tpo $(DEPDIR)/getncpu-solaris.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/getncpu-solaris.c' object='getncpu-solaris.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getncpu-solaris.lo `test -f 'runtime/getncpu-solaris.c' || echo '$(srcdir)/'`runtime/getncpu-solaris.c
+
+getncpu-irix.lo: runtime/getncpu-irix.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getncpu-irix.lo -MD -MP -MF $(DEPDIR)/getncpu-irix.Tpo -c -o getncpu-irix.lo `test -f 'runtime/getncpu-irix.c' || echo '$(srcdir)/'`runtime/getncpu-irix.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/getncpu-irix.Tpo $(DEPDIR)/getncpu-irix.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/getncpu-irix.c' object='getncpu-irix.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getncpu-irix.lo `test -f 'runtime/getncpu-irix.c' || echo '$(srcdir)/'`runtime/getncpu-irix.c
+
+getncpu-linux.lo: runtime/getncpu-linux.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getncpu-linux.lo -MD -MP -MF $(DEPDIR)/getncpu-linux.Tpo -c -o getncpu-linux.lo `test -f 'runtime/getncpu-linux.c' || echo '$(srcdir)/'`runtime/getncpu-linux.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/getncpu-linux.Tpo $(DEPDIR)/getncpu-linux.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='runtime/getncpu-linux.c' object='getncpu-linux.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getncpu-linux.lo `test -f 'runtime/getncpu-linux.c' || echo '$(srcdir)/'`runtime/getncpu-linux.c
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool config.lt
+
+# GNU Make needs to see an explicit $(MAKE) variable in the command it
+# runs to enable its job server during parallel builds.  Hence the
+# comments below.
+all-multi:
+	$(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE)
+install-multi:
+	$(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE)
+
+mostlyclean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE)
+clean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE)
+distclean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE)
+maintainer-clean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE)
+install-toolexeclibgoDATA: $(toolexeclibgo_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgodir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgodir)"
+	@list='$(toolexeclibgo_DATA)'; test -n "$(toolexeclibgodir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgodir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgodir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgo_DATA)'; test -n "$(toolexeclibgodir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgodir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgodir)" && rm -f $$files
+install-toolexeclibgoarchiveDATA: $(toolexeclibgoarchive_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoarchivedir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoarchivedir)"
+	@list='$(toolexeclibgoarchive_DATA)'; test -n "$(toolexeclibgoarchivedir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoarchivedir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoarchivedir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoarchiveDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoarchive_DATA)'; test -n "$(toolexeclibgoarchivedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoarchivedir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoarchivedir)" && rm -f $$files
+install-toolexeclibgocompressDATA: $(toolexeclibgocompress_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgocompressdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgocompressdir)"
+	@list='$(toolexeclibgocompress_DATA)'; test -n "$(toolexeclibgocompressdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgocompressdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgocompressdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgocompressDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgocompress_DATA)'; test -n "$(toolexeclibgocompressdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgocompressdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgocompressdir)" && rm -f $$files
+install-toolexeclibgocontainerDATA: $(toolexeclibgocontainer_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgocontainerdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgocontainerdir)"
+	@list='$(toolexeclibgocontainer_DATA)'; test -n "$(toolexeclibgocontainerdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgocontainerdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgocontainerdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgocontainerDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgocontainer_DATA)'; test -n "$(toolexeclibgocontainerdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgocontainerdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgocontainerdir)" && rm -f $$files
+install-toolexeclibgocryptoDATA: $(toolexeclibgocrypto_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgocryptodir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgocryptodir)"
+	@list='$(toolexeclibgocrypto_DATA)'; test -n "$(toolexeclibgocryptodir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgocryptodir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgocryptodir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgocryptoDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgocrypto_DATA)'; test -n "$(toolexeclibgocryptodir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgocryptodir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgocryptodir)" && rm -f $$files
+install-toolexeclibgocryptox509DATA: $(toolexeclibgocryptox509_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgocryptox509dir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgocryptox509dir)"
+	@list='$(toolexeclibgocryptox509_DATA)'; test -n "$(toolexeclibgocryptox509dir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgocryptox509dir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgocryptox509dir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgocryptox509DATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgocryptox509_DATA)'; test -n "$(toolexeclibgocryptox509dir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgocryptox509dir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgocryptox509dir)" && rm -f $$files
+install-toolexeclibgodatabaseDATA: $(toolexeclibgodatabase_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgodatabasedir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgodatabasedir)"
+	@list='$(toolexeclibgodatabase_DATA)'; test -n "$(toolexeclibgodatabasedir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgodatabasedir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgodatabasedir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgodatabaseDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgodatabase_DATA)'; test -n "$(toolexeclibgodatabasedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgodatabasedir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgodatabasedir)" && rm -f $$files
+install-toolexeclibgodatabasesqlDATA: $(toolexeclibgodatabasesql_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgodatabasesqldir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgodatabasesqldir)"
+	@list='$(toolexeclibgodatabasesql_DATA)'; test -n "$(toolexeclibgodatabasesqldir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgodatabasesqldir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgodatabasesqldir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgodatabasesqlDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgodatabasesql_DATA)'; test -n "$(toolexeclibgodatabasesqldir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgodatabasesqldir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgodatabasesqldir)" && rm -f $$files
+install-toolexeclibgodebugDATA: $(toolexeclibgodebug_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgodebugdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgodebugdir)"
+	@list='$(toolexeclibgodebug_DATA)'; test -n "$(toolexeclibgodebugdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgodebugdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgodebugdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgodebugDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgodebug_DATA)'; test -n "$(toolexeclibgodebugdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgodebugdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgodebugdir)" && rm -f $$files
+install-toolexeclibgoencodingDATA: $(toolexeclibgoencoding_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoencodingdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoencodingdir)"
+	@list='$(toolexeclibgoencoding_DATA)'; test -n "$(toolexeclibgoencodingdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoencodingdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoencodingdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoencodingDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoencoding_DATA)'; test -n "$(toolexeclibgoencodingdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoencodingdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoencodingdir)" && rm -f $$files
+install-toolexeclibgoexpDATA: $(toolexeclibgoexp_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoexpdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoexpdir)"
+	@list='$(toolexeclibgoexp_DATA)'; test -n "$(toolexeclibgoexpdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoexpdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoexpdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoexpDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoexp_DATA)'; test -n "$(toolexeclibgoexpdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoexpdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoexpdir)" && rm -f $$files
+install-toolexeclibgogoDATA: $(toolexeclibgogo_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgogodir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgogodir)"
+	@list='$(toolexeclibgogo_DATA)'; test -n "$(toolexeclibgogodir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgogodir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgogodir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgogoDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgogo_DATA)'; test -n "$(toolexeclibgogodir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgogodir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgogodir)" && rm -f $$files
+install-toolexeclibgohashDATA: $(toolexeclibgohash_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgohashdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgohashdir)"
+	@list='$(toolexeclibgohash_DATA)'; test -n "$(toolexeclibgohashdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgohashdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgohashdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgohashDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgohash_DATA)'; test -n "$(toolexeclibgohashdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgohashdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgohashdir)" && rm -f $$files
+install-toolexeclibgohtmlDATA: $(toolexeclibgohtml_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgohtmldir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgohtmldir)"
+	@list='$(toolexeclibgohtml_DATA)'; test -n "$(toolexeclibgohtmldir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgohtmldir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgohtmldir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgohtmlDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgohtml_DATA)'; test -n "$(toolexeclibgohtmldir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgohtmldir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgohtmldir)" && rm -f $$files
+install-toolexeclibgoimageDATA: $(toolexeclibgoimage_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoimagedir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoimagedir)"
+	@list='$(toolexeclibgoimage_DATA)'; test -n "$(toolexeclibgoimagedir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoimagedir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoimagedir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoimageDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoimage_DATA)'; test -n "$(toolexeclibgoimagedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoimagedir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoimagedir)" && rm -f $$files
+install-toolexeclibgoimagecolorDATA: $(toolexeclibgoimagecolor_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoimagecolordir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoimagecolordir)"
+	@list='$(toolexeclibgoimagecolor_DATA)'; test -n "$(toolexeclibgoimagecolordir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoimagecolordir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoimagecolordir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoimagecolorDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoimagecolor_DATA)'; test -n "$(toolexeclibgoimagecolordir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoimagecolordir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoimagecolordir)" && rm -f $$files
+install-toolexeclibgoindexDATA: $(toolexeclibgoindex_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoindexdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoindexdir)"
+	@list='$(toolexeclibgoindex_DATA)'; test -n "$(toolexeclibgoindexdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoindexdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoindexdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoindexDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoindex_DATA)'; test -n "$(toolexeclibgoindexdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoindexdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoindexdir)" && rm -f $$files
+install-toolexeclibgoioDATA: $(toolexeclibgoio_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoiodir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoiodir)"
+	@list='$(toolexeclibgoio_DATA)'; test -n "$(toolexeclibgoiodir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoiodir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoiodir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoioDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoio_DATA)'; test -n "$(toolexeclibgoiodir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoiodir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoiodir)" && rm -f $$files
+install-toolexeclibgologDATA: $(toolexeclibgolog_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgologdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgologdir)"
+	@list='$(toolexeclibgolog_DATA)'; test -n "$(toolexeclibgologdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgologdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgologdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgologDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgolog_DATA)'; test -n "$(toolexeclibgologdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgologdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgologdir)" && rm -f $$files
+install-toolexeclibgomathDATA: $(toolexeclibgomath_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgomathdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgomathdir)"
+	@list='$(toolexeclibgomath_DATA)'; test -n "$(toolexeclibgomathdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgomathdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgomathdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgomathDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgomath_DATA)'; test -n "$(toolexeclibgomathdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgomathdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgomathdir)" && rm -f $$files
+install-toolexeclibgomimeDATA: $(toolexeclibgomime_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgomimedir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgomimedir)"
+	@list='$(toolexeclibgomime_DATA)'; test -n "$(toolexeclibgomimedir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgomimedir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgomimedir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgomimeDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgomime_DATA)'; test -n "$(toolexeclibgomimedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgomimedir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgomimedir)" && rm -f $$files
+install-toolexeclibgonetDATA: $(toolexeclibgonet_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgonetdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgonetdir)"
+	@list='$(toolexeclibgonet_DATA)'; test -n "$(toolexeclibgonetdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgonetdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgonetdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgonetDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgonet_DATA)'; test -n "$(toolexeclibgonetdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgonetdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgonetdir)" && rm -f $$files
+install-toolexeclibgonethttpDATA: $(toolexeclibgonethttp_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgonethttpdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgonethttpdir)"
+	@list='$(toolexeclibgonethttp_DATA)'; test -n "$(toolexeclibgonethttpdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgonethttpdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgonethttpdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgonethttpDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgonethttp_DATA)'; test -n "$(toolexeclibgonethttpdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgonethttpdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgonethttpdir)" && rm -f $$files
+install-toolexeclibgonetrpcDATA: $(toolexeclibgonetrpc_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgonetrpcdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgonetrpcdir)"
+	@list='$(toolexeclibgonetrpc_DATA)'; test -n "$(toolexeclibgonetrpcdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgonetrpcdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgonetrpcdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgonetrpcDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgonetrpc_DATA)'; test -n "$(toolexeclibgonetrpcdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgonetrpcdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgonetrpcdir)" && rm -f $$files
+install-toolexeclibgooldDATA: $(toolexeclibgoold_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoolddir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoolddir)"
+	@list='$(toolexeclibgoold_DATA)'; test -n "$(toolexeclibgoolddir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoolddir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoolddir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgooldDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoold_DATA)'; test -n "$(toolexeclibgoolddir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoolddir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoolddir)" && rm -f $$files
+install-toolexeclibgoosDATA: $(toolexeclibgoos_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoosdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoosdir)"
+	@list='$(toolexeclibgoos_DATA)'; test -n "$(toolexeclibgoosdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoosdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoosdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoosDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoos_DATA)'; test -n "$(toolexeclibgoosdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoosdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoosdir)" && rm -f $$files
+install-toolexeclibgopathDATA: $(toolexeclibgopath_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgopathdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgopathdir)"
+	@list='$(toolexeclibgopath_DATA)'; test -n "$(toolexeclibgopathdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgopathdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgopathdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgopathDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgopath_DATA)'; test -n "$(toolexeclibgopathdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgopathdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgopathdir)" && rm -f $$files
+install-toolexeclibgoregexpDATA: $(toolexeclibgoregexp_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoregexpdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoregexpdir)"
+	@list='$(toolexeclibgoregexp_DATA)'; test -n "$(toolexeclibgoregexpdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoregexpdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoregexpdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoregexpDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoregexp_DATA)'; test -n "$(toolexeclibgoregexpdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoregexpdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoregexpdir)" && rm -f $$files
+install-toolexeclibgoruntimeDATA: $(toolexeclibgoruntime_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgoruntimedir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoruntimedir)"
+	@list='$(toolexeclibgoruntime_DATA)'; test -n "$(toolexeclibgoruntimedir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoruntimedir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoruntimedir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgoruntimeDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgoruntime_DATA)'; test -n "$(toolexeclibgoruntimedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgoruntimedir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgoruntimedir)" && rm -f $$files
+install-toolexeclibgosyncDATA: $(toolexeclibgosync_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgosyncdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgosyncdir)"
+	@list='$(toolexeclibgosync_DATA)'; test -n "$(toolexeclibgosyncdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgosyncdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgosyncdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgosyncDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgosync_DATA)'; test -n "$(toolexeclibgosyncdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgosyncdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgosyncdir)" && rm -f $$files
+install-toolexeclibgotestingDATA: $(toolexeclibgotesting_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgotestingdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgotestingdir)"
+	@list='$(toolexeclibgotesting_DATA)'; test -n "$(toolexeclibgotestingdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgotestingdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgotestingdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgotestingDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgotesting_DATA)'; test -n "$(toolexeclibgotestingdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgotestingdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgotestingdir)" && rm -f $$files
+install-toolexeclibgotextDATA: $(toolexeclibgotext_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgotextdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgotextdir)"
+	@list='$(toolexeclibgotext_DATA)'; test -n "$(toolexeclibgotextdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgotextdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgotextdir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgotextDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgotext_DATA)'; test -n "$(toolexeclibgotextdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgotextdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgotextdir)" && rm -f $$files
+install-toolexeclibgotexttemplateDATA: $(toolexeclibgotexttemplate_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgotexttemplatedir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgotexttemplatedir)"
+	@list='$(toolexeclibgotexttemplate_DATA)'; test -n "$(toolexeclibgotexttemplatedir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgotexttemplatedir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgotexttemplatedir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgotexttemplateDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgotexttemplate_DATA)'; test -n "$(toolexeclibgotexttemplatedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgotexttemplatedir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgotexttemplatedir)" && rm -f $$files
+install-toolexeclibgounicodeDATA: $(toolexeclibgounicode_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(toolexeclibgounicodedir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgounicodedir)"
+	@list='$(toolexeclibgounicode_DATA)'; test -n "$(toolexeclibgounicodedir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgounicodedir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgounicodedir)" || exit $$?; \
+	done
+
+uninstall-toolexeclibgounicodeDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(toolexeclibgounicode_DATA)'; test -n "$(toolexeclibgounicodedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(toolexeclibgounicodedir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(toolexeclibgounicodedir)" && rm -f $$files
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) all-multi $(DATA) \
+		config.h
+installdirs: installdirs-recursive
+installdirs-am:
+	for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohtmldir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoimagecolordir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgologdir)" "$(DESTDIR)$(toolexeclibgomathdir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgonethttpdir)" "$(DESTDIR)$(toolexeclibgonetrpcdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotextdir)" "$(DESTDIR)$(toolexeclibgotexttemplatedir)" "$(DESTDIR)$(toolexeclibgounicodedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-multi clean-recursive
+
+clean-am: clean-generic clean-libtool clean-local \
+	clean-toolexeclibLIBRARIES clean-toolexeclibLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-multi distclean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-hdr distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-multi install-toolexeclibLIBRARIES \
+	install-toolexeclibLTLIBRARIES install-toolexeclibgoDATA \
+	install-toolexeclibgoarchiveDATA \
+	install-toolexeclibgocompressDATA \
+	install-toolexeclibgocontainerDATA \
+	install-toolexeclibgocryptoDATA \
+	install-toolexeclibgocryptox509DATA \
+	install-toolexeclibgodatabaseDATA \
+	install-toolexeclibgodatabasesqlDATA \
+	install-toolexeclibgodebugDATA \
+	install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \
+	install-toolexeclibgogoDATA install-toolexeclibgohashDATA \
+	install-toolexeclibgohtmlDATA install-toolexeclibgoimageDATA \
+	install-toolexeclibgoimagecolorDATA \
+	install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
+	install-toolexeclibgologDATA install-toolexeclibgomathDATA \
+	install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \
+	install-toolexeclibgonethttpDATA \
+	install-toolexeclibgonetrpcDATA install-toolexeclibgooldDATA \
+	install-toolexeclibgoosDATA install-toolexeclibgopathDATA \
+	install-toolexeclibgoregexpDATA \
+	install-toolexeclibgoruntimeDATA install-toolexeclibgosyncDATA \
+	install-toolexeclibgotestingDATA install-toolexeclibgotextDATA \
+	install-toolexeclibgotexttemplateDATA \
+	install-toolexeclibgounicodeDATA
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-multi maintainer-clean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-multi mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool mostlyclean-local
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-toolexeclibLIBRARIES \
+	uninstall-toolexeclibLTLIBRARIES uninstall-toolexeclibgoDATA \
+	uninstall-toolexeclibgoarchiveDATA \
+	uninstall-toolexeclibgocompressDATA \
+	uninstall-toolexeclibgocontainerDATA \
+	uninstall-toolexeclibgocryptoDATA \
+	uninstall-toolexeclibgocryptox509DATA \
+	uninstall-toolexeclibgodatabaseDATA \
+	uninstall-toolexeclibgodatabasesqlDATA \
+	uninstall-toolexeclibgodebugDATA \
+	uninstall-toolexeclibgoencodingDATA \
+	uninstall-toolexeclibgoexpDATA uninstall-toolexeclibgogoDATA \
+	uninstall-toolexeclibgohashDATA \
+	uninstall-toolexeclibgohtmlDATA \
+	uninstall-toolexeclibgoimageDATA \
+	uninstall-toolexeclibgoimagecolorDATA \
+	uninstall-toolexeclibgoindexDATA uninstall-toolexeclibgoioDATA \
+	uninstall-toolexeclibgologDATA uninstall-toolexeclibgomathDATA \
+	uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \
+	uninstall-toolexeclibgonethttpDATA \
+	uninstall-toolexeclibgonetrpcDATA \
+	uninstall-toolexeclibgooldDATA uninstall-toolexeclibgoosDATA \
+	uninstall-toolexeclibgopathDATA \
+	uninstall-toolexeclibgoregexpDATA \
+	uninstall-toolexeclibgoruntimeDATA \
+	uninstall-toolexeclibgosyncDATA \
+	uninstall-toolexeclibgotestingDATA \
+	uninstall-toolexeclibgotextDATA \
+	uninstall-toolexeclibgotexttemplateDATA \
+	uninstall-toolexeclibgounicodeDATA
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all all-multi \
+	clean-multi ctags-recursive distclean-multi install-am \
+	install-multi install-strip maintainer-clean-multi \
+	mostlyclean-multi tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am all-multi am--refresh check check-am clean \
+	clean-generic clean-libtool clean-local clean-multi \
+	clean-toolexeclibLIBRARIES clean-toolexeclibLTLIBRARIES ctags \
+	ctags-recursive distclean distclean-compile distclean-generic \
+	distclean-hdr distclean-libtool distclean-multi distclean-tags \
+	dvi dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man install-multi \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip install-toolexeclibLIBRARIES \
+	install-toolexeclibLTLIBRARIES install-toolexeclibgoDATA \
+	install-toolexeclibgoarchiveDATA \
+	install-toolexeclibgocompressDATA \
+	install-toolexeclibgocontainerDATA \
+	install-toolexeclibgocryptoDATA \
+	install-toolexeclibgocryptox509DATA \
+	install-toolexeclibgodatabaseDATA \
+	install-toolexeclibgodatabasesqlDATA \
+	install-toolexeclibgodebugDATA \
+	install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \
+	install-toolexeclibgogoDATA install-toolexeclibgohashDATA \
+	install-toolexeclibgohtmlDATA install-toolexeclibgoimageDATA \
+	install-toolexeclibgoimagecolorDATA \
+	install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
+	install-toolexeclibgologDATA install-toolexeclibgomathDATA \
+	install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \
+	install-toolexeclibgonethttpDATA \
+	install-toolexeclibgonetrpcDATA install-toolexeclibgooldDATA \
+	install-toolexeclibgoosDATA install-toolexeclibgopathDATA \
+	install-toolexeclibgoregexpDATA \
+	install-toolexeclibgoruntimeDATA install-toolexeclibgosyncDATA \
+	install-toolexeclibgotestingDATA install-toolexeclibgotextDATA \
+	install-toolexeclibgotexttemplateDATA \
+	install-toolexeclibgounicodeDATA installcheck installcheck-am \
+	installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic maintainer-clean-multi mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	mostlyclean-local mostlyclean-multi pdf pdf-am ps ps-am tags \
+	tags-recursive uninstall uninstall-am \
+	uninstall-toolexeclibLIBRARIES \
+	uninstall-toolexeclibLTLIBRARIES uninstall-toolexeclibgoDATA \
+	uninstall-toolexeclibgoarchiveDATA \
+	uninstall-toolexeclibgocompressDATA \
+	uninstall-toolexeclibgocontainerDATA \
+	uninstall-toolexeclibgocryptoDATA \
+	uninstall-toolexeclibgocryptox509DATA \
+	uninstall-toolexeclibgodatabaseDATA \
+	uninstall-toolexeclibgodatabasesqlDATA \
+	uninstall-toolexeclibgodebugDATA \
+	uninstall-toolexeclibgoencodingDATA \
+	uninstall-toolexeclibgoexpDATA uninstall-toolexeclibgogoDATA \
+	uninstall-toolexeclibgohashDATA \
+	uninstall-toolexeclibgohtmlDATA \
+	uninstall-toolexeclibgoimageDATA \
+	uninstall-toolexeclibgoimagecolorDATA \
+	uninstall-toolexeclibgoindexDATA uninstall-toolexeclibgoioDATA \
+	uninstall-toolexeclibgologDATA uninstall-toolexeclibgomathDATA \
+	uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \
+	uninstall-toolexeclibgonethttpDATA \
+	uninstall-toolexeclibgonetrpcDATA \
+	uninstall-toolexeclibgooldDATA uninstall-toolexeclibgoosDATA \
+	uninstall-toolexeclibgopathDATA \
+	uninstall-toolexeclibgoregexpDATA \
+	uninstall-toolexeclibgoruntimeDATA \
+	uninstall-toolexeclibgosyncDATA \
+	uninstall-toolexeclibgotestingDATA \
+	uninstall-toolexeclibgotextDATA \
+	uninstall-toolexeclibgotexttemplateDATA \
+	uninstall-toolexeclibgounicodeDATA
+
+
+goc2c.$(OBJEXT): runtime/goc2c.c
+	$(CC_FOR_BUILD) -c $(CFLAGS_FOR_BUILD) $<
+
+goc2c: goc2c.$(OBJEXT)
+	$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $@ $<
+
+malloc.c: $(srcdir)/runtime/malloc.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+mprof.c: $(srcdir)/runtime/mprof.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+netpoll.c: $(srcdir)/runtime/netpoll.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+reflect.c: $(srcdir)/runtime/reflect.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+runtime1.c: $(srcdir)/runtime/runtime1.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+sema.c: $(srcdir)/runtime/sema.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+sigqueue.c: $(srcdir)/runtime/sigqueue.goc goc2c
+	./goc2c --go-pkgpath os_signal $< > $@.tmp
+	mv -f $@.tmp $@
+
+time.c: $(srcdir)/runtime/time.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+%.c: $(srcdir)/runtime/%.goc goc2c
+	./goc2c $< > $@.tmp
+	mv -f $@.tmp $@
+
+version.go: s-version; @true
+s-version: Makefile
+	rm -f version.go.tmp
+	echo "package runtime" > version.go.tmp
+	echo 'const defaultGoroot = "$(prefix)"' >> version.go.tmp
+	echo 'const theVersion = "'`$(GOC) --version | sed 1q`'"' >> version.go.tmp
+	echo 'const theGoarch = "'$(GOARCH)'"' >> version.go.tmp
+	echo 'const theGoos = "'$(GOOS)'"' >> version.go.tmp
+	$(SHELL) $(srcdir)/../move-if-change version.go.tmp version.go
+	$(STAMP) $@
+
+libcalls.go: s-libcalls; @true
+s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files)
+	rm -f libcalls.go.tmp
+	files=`echo $^ | sed -e 's/libcalls-list//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \
+	$(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp
+	$(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go
+	$(STAMP) $@
+
+libcalls-list: s-libcalls-list; @true
+s-libcalls-list: Makefile
+	rm -f libcalls-list.tmp
+	echo $(go_base_syscall_files) > libcalls-list.tmp
+	$(SHELL) $(srcdir)/../move-if-change libcalls-list.tmp libcalls-list
+	$(STAMP) $@
+
+syscall_arch.go: s-syscall_arch; @true
+s-syscall_arch: Makefile
+	rm -f syscall_arch.go.tmp
+	echo "package syscall" > syscall_arch.go.tmp
+	echo 'const ARCH = "'$(GOARCH)'"' >> syscall_arch.go.tmp
+	echo 'const OS = "'$(GOOS)'"' >> syscall_arch.go.tmp
+	$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
+	$(STAMP) $@
+
+sysinfo.go: s-sysinfo; @true
+s-sysinfo: $(srcdir)/mksysinfo.sh config.h
+	CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
+	$(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
+	$(STAMP) $@
+
+# The epoll struct has an embedded union and is packed on x86_64,
+# which is too complicated for mksysinfo.sh.  We find the offset of
+# the only field we care about in configure.ac, and generate the
+# struct here.
+epoll.go: s-epoll; @true
+s-epoll: Makefile
+	rm -f epoll.go.tmp
+	echo 'package syscall' > epoll.go.tmp
+	echo 'type EpollEvent struct {' >> epoll.go.tmp
+	echo '	Events uint32' >> epoll.go.tmp
+	case "$(SIZEOF_STRUCT_EPOLL_EVENT),$(STRUCT_EPOLL_EVENT_FD_OFFSET)" in \
+	0,0) echo 1>&2 "*** struct epoll_event data.fd offset unknown"; \
+	   exit 1; ;; \
+	8,4) echo '	Fd int32' >> epoll.go.tmp; ;; \
+	12,4) echo '	Fd int32' >> epoll.go.tmp; \
+	   echo '	Pad [4]byte' >> epoll.go.tmp; ;; \
+	12,8) echo '	Pad [4]byte' >> epoll.go.tmp; \
+	   echo '	Fd int32' >> epoll.go.tmp; ;; \
+	16,8) echo '	Pad [4]byte' >> epoll.go.tmp; \
+	   echo '	Fd int32' >> epoll.go.tmp; \
+	   echo '	Pad2 [4]byte' >> epoll.go.tmp; ;; \
+	*) echo 1>&2 "*** struct epoll_event unsupported"; \
+	   exit 1; ;; \
+	esac
+	echo '}' >> epoll.go.tmp
+	$(SHELL) $(srcdir)/../move-if-change epoll.go.tmp epoll.go
+	$(STAMP) $@
+
+@go_include@ bufio.lo.dep
+bufio.lo.dep: $(go_bufio_files)
+	$(BUILDDEPS)
+bufio.lo: $(go_bufio_files)
+	$(BUILDPACKAGE)
+bufio/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: bufio/check
+
+@go_include@ bytes.lo.dep
+bytes.lo.dep: $(go_bytes_files)
+	$(BUILDDEPS)
+bytes.lo: $(go_bytes_files)
+	$(BUILDPACKAGE)
+bytes/index.lo: $(go_bytes_c_files)
+	@$(MKDIR_P) bytes
+	$(LTCOMPILE) -c -o bytes/index.lo $(srcdir)/go/bytes/indexbyte.c
+bytes/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: bytes/check
+
+@go_include@ crypto.lo.dep
+crypto.lo.dep: $(go_crypto_files)
+	$(BUILDDEPS)
+crypto.lo: $(go_crypto_files)
+	$(BUILDPACKAGE)
+crypto/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/check
+
+@go_include@ encoding.lo.dep
+encoding.lo.dep: $(go_encoding_files)
+	$(BUILDDEPS)
+encoding.lo: $(go_encoding_files)
+	$(BUILDPACKAGE)
+encoding/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/check
+
+@go_include@ errors.lo.dep
+errors.lo.dep: $(go_errors_files)
+	$(BUILDDEPS)
+errors.lo: $(go_errors_files)
+	$(BUILDPACKAGE)
+errors/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: errors/check
+
+@go_include@ expvar.lo.dep
+expvar.lo.dep: $(go_expvar_files)
+	$(BUILDDEPS)
+expvar.lo: $(go_expvar_files)
+	$(BUILDPACKAGE)
+expvar/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: expvar/check
+
+@go_include@ flag.lo.dep
+flag.lo.dep: $(go_flag_files)
+	$(BUILDDEPS)
+flag.lo: $(go_flag_files)
+	$(BUILDPACKAGE)
+flag/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: flag/check
+
+@go_include@ fmt.lo.dep
+fmt.lo.dep: $(go_fmt_files)
+	$(BUILDDEPS)
+fmt.lo: $(go_fmt_files)
+	$(BUILDPACKAGE)
+fmt/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: fmt/check
+
+@go_include@ hash.lo.dep
+hash.lo.dep: $(go_hash_files)
+	$(BUILDDEPS)
+hash.lo: $(go_hash_files)
+	$(BUILDPACKAGE)
+hash/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: hash/check
+
+@go_include@ html.lo.dep
+html.lo.dep: $(go_html_files)
+	$(BUILDDEPS)
+html.lo: $(go_html_files)
+	$(BUILDPACKAGE)
+html/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: html/check
+
+@go_include@ image.lo.dep
+image.lo.dep: $(go_image_files)
+	$(BUILDDEPS)
+image.lo: $(go_image_files)
+	$(BUILDPACKAGE)
+image/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/check
+
+@go_include@ io.lo.dep
+io.lo.dep: $(go_io_files)
+	$(BUILDDEPS)
+io.lo: $(go_io_files)
+	$(BUILDPACKAGE)
+io/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: io/check
+
+@go_include@ log.lo.dep
+log.lo.dep: $(go_log_files)
+	$(BUILDDEPS)
+log.lo: $(go_log_files)
+	$(BUILDPACKAGE)
+log/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: log/check
+
+@go_include@ math.lo.dep
+math.lo.dep: $(go_math_files)
+	$(BUILDDEPS)
+math.lo: $(go_math_files)
+	$(MKDIR_P) $(@D)
+	files=`echo $^ | sed -e 's/[^ ]*\.gox//g'`; \
+	$(LTGOCOMPILE) $(MATH_FLAG) -I . -c -fgo-pkgpath=math -o $@ $$files
+math/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: math/check
+
+@go_include@ mime.lo.dep
+mime.lo.dep: $(go_mime_files)
+	$(BUILDDEPS)
+mime.lo: $(go_mime_files)
+	$(BUILDPACKAGE)
+mime/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: mime/check
+
+@go_include@ net.lo.dep
+net.lo.dep: $(go_net_files)
+	$(BUILDDEPS)
+net.lo: $(go_net_files)
+	$(BUILDPACKAGE)
+net/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/check
+
+@go_include@ os.lo.dep
+os.lo.dep: $(go_os_files)
+	$(BUILDDEPS)
+os.lo: $(go_os_files)
+	$(BUILDPACKAGE)
+os/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: os/check
+
+@go_include@ path.lo.dep
+path.lo.dep: $(go_path_files)
+	$(BUILDDEPS)
+path.lo: $(go_path_files)
+	$(BUILDPACKAGE)
+path/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: path/check
+
+@go_include@ reflect-go.lo.dep
+reflect-go.lo.dep: $(go_reflect_files)
+	$(BUILDDEPS)
+reflect-go.lo: $(go_reflect_files)
+	$(BUILDPACKAGE)
+reflect/check: $(CHECK_DEPS)
+	@$(CHECK)
+reflect/makefunc.lo: $(go_reflect_makefunc_s_file)
+	@$(MKDIR_P) reflect
+	$(LTCOMPILE) -c -o $@ $<
+reflect/makefunc_ffi_c.lo: $(go_reflect_makefunc_c_file)
+	@$(MKDIR_P) reflect
+	$(LTCOMPILE) -c -o $@ $<
+.PHONY: reflect/check
+
+@go_include@ regexp.lo.dep
+regexp.lo.dep: $(go_regexp_files)
+	$(BUILDDEPS)
+regexp.lo: $(go_regexp_files)
+	$(BUILDPACKAGE)
+regexp/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: regexp/check
+
+@go_include@ runtime-go.lo.dep
+runtime-go.lo.dep: $(go_runtime_files)
+	$(BUILDDEPS)
+runtime-go.lo: $(go_runtime_files)
+	$(BUILDPACKAGE)
+runtime/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: runtime/check
+
+@go_include@ sort.lo.dep
+sort.lo.dep: $(go_sort_files)
+	$(BUILDDEPS)
+sort.lo: $(go_sort_files)
+	$(BUILDPACKAGE)
+sort/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: sort/check
+
+@go_include@ strconv.lo.dep
+strconv.lo.dep: $(go_strconv_files)
+	$(BUILDDEPS)
+strconv.lo: $(go_strconv_files)
+	$(BUILDPACKAGE)
+strconv/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: strconv/check
+
+@go_include@ strings.lo.dep
+strings.lo.dep: $(go_strings_files)
+	$(BUILDDEPS)
+strings.lo: $(go_strings_files)
+	$(BUILDPACKAGE)
+strings/index.lo: $(go_strings_c_files)
+	@$(MKDIR_P) strings
+	$(LTCOMPILE) -c -o strings/index.lo $(srcdir)/go/strings/indexbyte.c
+strings/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: strings/check
+
+@go_include@ sync.lo.dep
+sync.lo.dep: $(go_sync_files)
+	$(BUILDDEPS)
+sync.lo: $(go_sync_files)
+	$(BUILDPACKAGE)
+sync/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: sync/check
+
+@go_include@ testing.lo.dep
+testing.lo.dep: $(go_testing_files)
+	$(BUILDDEPS)
+testing.lo: $(go_testing_files)
+	$(BUILDPACKAGE)
+testing/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: testing/check
+
+@go_include@ time-go.lo.dep
+time-go.lo.dep: $(go_time_files)
+	$(BUILDDEPS)
+time-go.lo: $(go_time_files)
+	$(BUILDPACKAGE)
+time/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: time/check
+
+@go_include@ unicode.lo.dep
+unicode.lo.dep: $(go_unicode_files)
+	$(BUILDDEPS)
+unicode.lo: $(go_unicode_files)
+	$(BUILDPACKAGE)
+unicode/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: unicode/check
+
+@go_include@ archive/tar.lo.dep
+archive/tar.lo.dep: $(go_archive_tar_files)
+	$(BUILDDEPS)
+archive/tar.lo: $(go_archive_tar_files)
+	$(BUILDPACKAGE)
+archive/tar/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: archive/tar/check
+
+@go_include@ archive/zip.lo.dep
+archive/zip.lo.dep: $(go_archive_zip_files)
+	$(BUILDDEPS)
+archive/zip.lo: $(go_archive_zip_files)
+	$(BUILDPACKAGE)
+archive/zip/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: archive/zip/check
+
+@go_include@ compress/bzip2.lo.dep
+compress/bzip2.lo.dep: $(go_compress_bzip2_files)
+	$(BUILDDEPS)
+compress/bzip2.lo: $(go_compress_bzip2_files)
+	$(BUILDPACKAGE)
+compress/bzip2/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: compress/bzip2/check
+
+@go_include@ compress/flate.lo.dep
+compress/flate.lo.dep: $(go_compress_flate_files)
+	$(BUILDDEPS)
+compress/flate.lo: $(go_compress_flate_files)
+	$(BUILDPACKAGE)
+compress/flate/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: compress/flate/check
+
+@go_include@ compress/gzip.lo.dep
+compress/gzip.lo.dep: $(go_compress_gzip_files)
+	$(BUILDDEPS)
+compress/gzip.lo: $(go_compress_gzip_files)
+	$(BUILDPACKAGE)
+compress/gzip/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: compress/gzip/check
+
+@go_include@ compress/lzw.lo.dep
+compress/lzw.lo.dep: $(go_compress_lzw_files)
+	$(BUILDDEPS)
+compress/lzw.lo: $(go_compress_lzw_files)
+	$(BUILDPACKAGE)
+compress/lzw/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: compress/lzw/check
+
+@go_include@ compress/zlib.lo.dep
+compress/zlib.lo.dep: $(go_compress_zlib_files)
+	$(BUILDDEPS)
+compress/zlib.lo: $(go_compress_zlib_files)
+	$(BUILDPACKAGE)
+compress/zlib/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: compress/zlib/check
+
+@go_include@ container/heap.lo.dep
+container/heap.lo.dep: $(go_container_heap_files)
+	$(BUILDDEPS)
+container/heap.lo: $(go_container_heap_files)
+	$(BUILDPACKAGE)
+container/heap/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: container/heap/check
+
+@go_include@ container/list.lo.dep
+container/list.lo.dep: $(go_container_list_files)
+	$(BUILDDEPS)
+container/list.lo: $(go_container_list_files)
+	$(BUILDPACKAGE)
+container/list/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: container/list/check
+
+@go_include@ container/ring.lo.dep
+container/ring.lo.dep: $(go_container_ring_files)
+	$(BUILDDEPS)
+container/ring.lo: $(go_container_ring_files)
+	$(BUILDPACKAGE)
+container/ring/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: container/ring/check
+
+@go_include@ crypto/aes.lo.dep
+crypto/aes.lo.dep: $(go_crypto_aes_files)
+	$(BUILDDEPS)
+crypto/aes.lo: $(go_crypto_aes_files)
+	$(BUILDPACKAGE)
+crypto/aes/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/aes/check
+
+@go_include@ crypto/cipher.lo.dep
+crypto/cipher.lo.dep: $(go_crypto_cipher_files)
+	$(BUILDDEPS)
+crypto/cipher.lo: $(go_crypto_cipher_files)
+	$(BUILDPACKAGE)
+crypto/cipher/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/cipher/check
+
+@go_include@ crypto/des.lo.dep
+crypto/des.lo.dep: $(go_crypto_des_files)
+	$(BUILDDEPS)
+crypto/des.lo: $(go_crypto_des_files)
+	$(BUILDPACKAGE)
+crypto/des/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/des/check
+
+@go_include@ crypto/dsa.lo.dep
+crypto/dsa.lo.dep: $(go_crypto_dsa_files)
+	$(BUILDDEPS)
+crypto/dsa.lo: $(go_crypto_dsa_files)
+	$(BUILDPACKAGE)
+crypto/dsa/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/dsa/check
+
+@go_include@ crypto/ecdsa.lo.dep
+crypto/ecdsa.lo.dep: $(go_crypto_ecdsa_files)
+	$(BUILDDEPS)
+crypto/ecdsa.lo: $(go_crypto_ecdsa_files)
+	$(BUILDPACKAGE)
+crypto/ecdsa/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/ecdsa/check
+
+@go_include@ crypto/elliptic.lo.dep
+crypto/elliptic.lo.dep: $(go_crypto_elliptic_files)
+	$(BUILDDEPS)
+crypto/elliptic.lo: $(go_crypto_elliptic_files)
+	$(BUILDPACKAGE)
+crypto/elliptic/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/elliptic/check
+
+@go_include@ crypto/hmac.lo.dep
+crypto/hmac.lo.dep: $(go_crypto_hmac_files)
+	$(BUILDDEPS)
+crypto/hmac.lo: $(go_crypto_hmac_files)
+	$(BUILDPACKAGE)
+crypto/hmac/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/hmac/check
+
+@go_include@ crypto/md5.lo.dep
+crypto/md5.lo.dep: $(go_crypto_md5_files)
+	$(BUILDDEPS)
+crypto/md5.lo: $(go_crypto_md5_files)
+	$(BUILDPACKAGE)
+crypto/md5/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/md5/check
+
+@go_include@ crypto/rand.lo.dep
+crypto/rand.lo.dep: $(go_crypto_rand_files)
+	$(BUILDDEPS)
+crypto/rand.lo: $(go_crypto_rand_files)
+	$(BUILDPACKAGE)
+crypto/rand/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/rand/check
+
+@go_include@ crypto/rc4.lo.dep
+crypto/rc4.lo.dep: $(go_crypto_rc4_files)
+	$(BUILDDEPS)
+crypto/rc4.lo: $(go_crypto_rc4_files)
+	$(BUILDPACKAGE)
+crypto/rc4/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/rc4/check
+
+@go_include@ crypto/rsa.lo.dep
+crypto/rsa.lo.dep: $(go_crypto_rsa_files)
+	$(BUILDDEPS)
+crypto/rsa.lo: $(go_crypto_rsa_files)
+	$(BUILDPACKAGE)
+crypto/rsa/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/rsa/check
+
+@go_include@ crypto/sha1.lo.dep
+crypto/sha1.lo.dep: $(go_crypto_sha1_files)
+	$(BUILDDEPS)
+crypto/sha1.lo: $(go_crypto_sha1_files)
+	$(BUILDPACKAGE)
+crypto/sha1/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/sha1/check
+
+@go_include@ crypto/sha256.lo.dep
+crypto/sha256.lo.dep: $(go_crypto_sha256_files)
+	$(BUILDDEPS)
+crypto/sha256.lo: $(go_crypto_sha256_files)
+	$(BUILDPACKAGE)
+crypto/sha256/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/sha256/check
+
+@go_include@ crypto/sha512.lo.dep
+crypto/sha512.lo.dep: $(go_crypto_sha512_files)
+	$(BUILDDEPS)
+crypto/sha512.lo: $(go_crypto_sha512_files)
+	$(BUILDPACKAGE)
+crypto/sha512/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/sha512/check
+
+@go_include@ crypto/subtle.lo.dep
+crypto/subtle.lo.dep: $(go_crypto_subtle_files)
+	$(BUILDDEPS)
+crypto/subtle.lo: $(go_crypto_subtle_files)
+	$(BUILDPACKAGE)
+crypto/subtle/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/subtle/check
+
+@go_include@ crypto/tls.lo.dep
+crypto/tls.lo.dep: $(go_crypto_tls_files)
+	$(BUILDDEPS)
+crypto/tls.lo: $(go_crypto_tls_files)
+	$(BUILDPACKAGE)
+crypto/tls/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/tls/check
+
+@go_include@ crypto/x509.lo.dep
+crypto/x509.lo.dep: $(go_crypto_x509_files)
+	$(BUILDDEPS)
+crypto/x509.lo: $(go_crypto_x509_files)
+	$(BUILDPACKAGE)
+crypto/x509/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/x509/check
+
+@go_include@ crypto/x509/pkix.lo.dep
+crypto/x509/pkix.lo.dep: $(go_crypto_x509_pkix_files)
+	$(BUILDDEPS)
+crypto/x509/pkix.lo: $(go_crypto_x509_pkix_files)
+	$(BUILDPACKAGE)
+crypto/x509/pkix/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: crypto/x509/pkix/check
+
+@go_include@ database/sql.lo.dep
+database/sql.lo.dep: $(go_database_sql_files)
+	$(BUILDDEPS)
+database/sql.lo: $(go_database_sql_files)
+	$(BUILDPACKAGE)
+database/sql/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: database/sql/check
+
+@go_include@ database/sql/driver.lo.dep
+database/sql/driver.lo.dep: $(go_database_sql_driver_files)
+	$(BUILDDEPS)
+database/sql/driver.lo: $(go_database_sql_driver_files)
+	$(BUILDPACKAGE)
+database/sql/driver/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: database/sql/driver/check
+
+@go_include@ debug/dwarf.lo.dep
+debug/dwarf.lo.dep: $(go_debug_dwarf_files)
+	$(BUILDDEPS)
+debug/dwarf.lo: $(go_debug_dwarf_files)
+	$(BUILDPACKAGE)
+debug/dwarf/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/dwarf/check
+
+@go_include@ debug/elf.lo.dep
+debug/elf.lo.dep: $(go_debug_elf_files)
+	$(BUILDDEPS)
+debug/elf.lo: $(go_debug_elf_files)
+	$(BUILDPACKAGE)
+debug/elf/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/elf/check
+
+@go_include@ debug/gosym.lo.dep
+debug/gosym.lo.dep: $(go_debug_gosym_files)
+	$(BUILDDEPS)
+debug/gosym.lo: $(go_debug_gosym_files)
+	$(BUILDPACKAGE)
+debug/gosym/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/gosym/check
+
+@go_include@ debug/macho.lo.dep
+debug/macho.lo.dep: $(go_debug_macho_files)
+	$(BUILDDEPS)
+debug/macho.lo: $(go_debug_macho_files)
+	$(BUILDPACKAGE)
+debug/macho/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/macho/check
+
+@go_include@ debug/pe.lo.dep
+debug/pe.lo.dep: $(go_debug_pe_files)
+	$(BUILDDEPS)
+debug/pe.lo: $(go_debug_pe_files)
+	$(BUILDPACKAGE)
+debug/pe/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/pe/check
+
+@go_include@ debug/plan9obj.lo.dep
+debug/plan9obj.lo.dep: $(go_debug_plan9obj_files)
+	$(BUILDDEPS)
+debug/plan9obj.lo: $(go_debug_plan9obj_files)
+	$(BUILDPACKAGE)
+debug/plan9obj/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: debug/plan9obj/check
+
+@go_include@ encoding/asn1.lo.dep
+encoding/asn1.lo.dep: $(go_encoding_asn1_files)
+	$(BUILDDEPS)
+encoding/asn1.lo: $(go_encoding_asn1_files)
+	$(BUILDPACKAGE)
+encoding/asn1/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/asn1/check
+
+@go_include@ encoding/ascii85.lo.dep
+encoding/ascii85.lo.dep: $(go_encoding_ascii85_files)
+	$(BUILDDEPS)
+encoding/ascii85.lo: $(go_encoding_ascii85_files)
+	$(BUILDPACKAGE)
+encoding/ascii85/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/ascii85/check
+
+@go_include@ encoding/base32.lo.dep
+encoding/base32.lo.dep: $(go_encoding_base32_files)
+	$(BUILDDEPS)
+encoding/base32.lo: $(go_encoding_base32_files)
+	$(BUILDPACKAGE)
+encoding/base32/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/base32/check
+
+@go_include@ encoding/base64.lo.dep
+encoding/base64.lo.dep: $(go_encoding_base64_files)
+	$(BUILDDEPS)
+encoding/base64.lo: $(go_encoding_base64_files)
+	$(BUILDPACKAGE)
+encoding/base64/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/base64/check
+
+@go_include@ encoding/binary.lo.dep
+encoding/binary.lo.dep: $(go_encoding_binary_files)
+	$(BUILDDEPS)
+encoding/binary.lo: $(go_encoding_binary_files)
+	$(BUILDPACKAGE)
+encoding/binary/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/binary/check
+
+@go_include@ encoding/csv.lo.dep
+encoding/csv.lo.dep: $(go_encoding_csv_files)
+	$(BUILDDEPS)
+encoding/csv.lo: $(go_encoding_csv_files)
+	$(BUILDPACKAGE)
+encoding/csv/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/csv/check
+
+@go_include@ encoding/gob.lo.dep
+encoding/gob.lo.dep: $(go_encoding_gob_files)
+	$(BUILDDEPS)
+encoding/gob.lo: $(go_encoding_gob_files)
+	$(BUILDPACKAGE)
+encoding/gob/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/gob/check
+
+@go_include@ encoding/hex.lo.dep
+encoding/hex.lo.dep: $(go_encoding_hex_files)
+	$(BUILDDEPS)
+encoding/hex.lo: $(go_encoding_hex_files)
+	$(BUILDPACKAGE)
+encoding/hex/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/hex/check
+
+@go_include@ encoding/json.lo.dep
+encoding/json.lo.dep: $(go_encoding_json_files)
+	$(BUILDDEPS)
+encoding/json.lo: $(go_encoding_json_files)
+	$(BUILDPACKAGE)
+encoding/json/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/json/check
+
+@go_include@ encoding/pem.lo.dep
+encoding/pem.lo.dep: $(go_encoding_pem_files)
+	$(BUILDDEPS)
+encoding/pem.lo: $(go_encoding_pem_files)
+	$(BUILDPACKAGE)
+encoding/pem/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/pem/check
+
+@go_include@ encoding/xml.lo.dep
+encoding/xml.lo.dep: $(go_encoding_xml_files)
+	$(BUILDDEPS)
+encoding/xml.lo: $(go_encoding_xml_files)
+	$(BUILDPACKAGE)
+encoding/xml/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: encoding/xml/check
+
+@go_include@ exp/proxy.lo.dep
+exp/proxy.lo.dep: $(go_exp_proxy_files)
+	$(BUILDDEPS)
+exp/proxy.lo: $(go_exp_proxy_files)
+	$(BUILDPACKAGE)
+exp/proxy/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: exp/proxy/check
+
+@go_include@ exp/terminal.lo.dep
+exp/terminal.lo.dep: $(go_exp_terminal_files)
+	$(BUILDDEPS)
+exp/terminal.lo: $(go_exp_terminal_files)
+	$(BUILDPACKAGE)
+exp/terminal/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: exp/terminal/check
+
+@go_include@ html/template.lo.dep
+html/template.lo.dep: $(go_html_template_files)
+	$(BUILDDEPS)
+html/template.lo: $(go_html_template_files)
+	$(BUILDPACKAGE)
+html/template/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: html/template/check
+
+@go_include@ go/ast.lo.dep
+go/ast.lo.dep: $(go_go_ast_files)
+	$(BUILDDEPS)
+go/ast.lo: $(go_go_ast_files)
+	$(BUILDPACKAGE)
+go/ast/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/ast/check
+
+@go_include@ go/build.lo.dep
+go/build.lo.dep: $(go_go_build_files)
+	$(BUILDDEPS)
+go/build.lo: $(go_go_build_files)
+	$(BUILDPACKAGE)
+go/build/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/build/check
+
+@go_include@ go/doc.lo.dep
+go/doc.lo.dep: $(go_go_doc_files)
+	$(BUILDDEPS)
+go/doc.lo: $(go_go_doc_files)
+	$(BUILDPACKAGE)
+go/doc/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/doc/check
+
+@go_include@ go/format.lo.dep
+go/format.lo.dep: $(go_go_format_files)
+	$(BUILDDEPS)
+go/format.lo: $(go_go_format_files)
+	$(BUILDPACKAGE)
+go/format/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/format/check
+
+@go_include@ go/parser.lo.dep
+go/parser.lo.dep: $(go_go_parser_files)
+	$(BUILDDEPS)
+go/parser.lo: $(go_go_parser_files)
+	$(BUILDPACKAGE)
+go/parser/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/parser/check
+
+@go_include@ go/printer.lo.dep
+go/printer.lo.dep: $(go_go_printer_files)
+	$(BUILDDEPS)
+go/printer.lo: $(go_go_printer_files)
+	$(BUILDPACKAGE)
+go/printer/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/printer/check
+
+@go_include@ go/scanner.lo.dep
+go/scanner.lo.dep: $(go_go_scanner_files)
+	$(BUILDDEPS)
+go/scanner.lo: $(go_go_scanner_files)
+	$(BUILDPACKAGE)
+go/scanner/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/scanner/check
+
+@go_include@ go/token.lo.dep
+go/token.lo.dep: $(go_go_token_files)
+	$(BUILDDEPS)
+go/token.lo: $(go_go_token_files)
+	$(BUILDPACKAGE)
+go/token/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: go/token/check
+
+@go_include@ hash/adler32.lo.dep
+hash/adler32.lo.dep: $(go_hash_adler32_files)
+	$(BUILDDEPS)
+hash/adler32.lo: $(go_hash_adler32_files)
+	$(BUILDPACKAGE)
+hash/adler32/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: hash/adler32/check
+
+@go_include@ hash/crc32.lo.dep
+hash/crc32.lo.dep: $(go_hash_crc32_files)
+	$(BUILDDEPS)
+hash/crc32.lo: $(go_hash_crc32_files)
+	$(BUILDPACKAGE)
+hash/crc32/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: hash/crc32/check
+
+@go_include@ hash/crc64.lo.dep
+hash/crc64.lo.dep: $(go_hash_crc64_files)
+	$(BUILDDEPS)
+hash/crc64.lo: $(go_hash_crc64_files)
+	$(BUILDPACKAGE)
+hash/crc64/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: hash/crc64/check
+
+@go_include@ hash/fnv.lo.dep
+hash/fnv.lo.dep: $(go_hash_fnv_files)
+	$(BUILDDEPS)
+hash/fnv.lo: $(go_hash_fnv_files)
+	$(BUILDPACKAGE)
+hash/fnv/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: hash/fnv/check
+
+@go_include@ image/color.lo.dep
+image/color.lo.dep: $(go_image_color_files)
+	$(BUILDDEPS)
+image/color.lo: $(go_image_color_files)
+	$(BUILDPACKAGE)
+image/color/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/color/check
+
+@go_include@ image/color/palette.lo.dep
+image/color/palette.lo.dep: $(go_image_color_palette_files)
+	$(BUILDDEPS)
+image/color/palette.lo: $(go_image_color_palette_files)
+	$(BUILDPACKAGE)
+image/color/palette/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/color/palette/check
+
+@go_include@ image/draw.lo.dep
+image/draw.lo.dep: $(go_image_draw_files)
+	$(BUILDDEPS)
+image/draw.lo: $(go_image_draw_files)
+	$(BUILDPACKAGE)
+image/draw/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/draw/check
+
+@go_include@ image/gif.lo.dep
+image/gif.lo.dep: $(go_image_gif_files)
+	$(BUILDDEPS)
+image/gif.lo: $(go_image_gif_files)
+	$(BUILDPACKAGE)
+image/gif/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/gif/check
+
+@go_include@ image/jpeg.lo.dep
+image/jpeg.lo.dep: $(go_image_jpeg_files)
+	$(BUILDDEPS)
+image/jpeg.lo: $(go_image_jpeg_files)
+	$(BUILDPACKAGE)
+image/jpeg/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/jpeg/check
+
+@go_include@ image/png.lo.dep
+image/png.lo.dep: $(go_image_png_files)
+	$(BUILDDEPS)
+image/png.lo: $(go_image_png_files)
+	$(BUILDPACKAGE)
+image/png/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: image/png/check
+
+@go_include@ index/suffixarray.lo.dep
+index/suffixarray.lo.dep: $(go_index_suffixarray_files)
+	$(BUILDDEPS)
+index/suffixarray.lo: $(go_index_suffixarray_files)
+	$(BUILDPACKAGE)
+index/suffixarray/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: index/suffixarray/check
+
+@go_include@ io/ioutil.lo.dep
+io/ioutil.lo.dep: $(go_io_ioutil_files)
+	$(BUILDDEPS)
+io/ioutil.lo: $(go_io_ioutil_files)
+	$(BUILDPACKAGE)
+io/ioutil/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: io/ioutil/check
+
+@go_include@ log/syslog.lo.dep
+log/syslog.lo.dep: $(go_log_syslog_files)
+	$(BUILDDEPS)
+log/syslog.lo: $(go_log_syslog_files)
+	$(BUILDPACKAGE)
+log/syslog/syslog_c.lo: $(go_syslog_c_files) log/syslog.lo
+	@$(MKDIR_P) log/syslog
+	$(LTCOMPILE) -c -o $@ $(srcdir)/go/log/syslog/syslog_c.c
+log/syslog/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: log/syslog/check
+
+@go_include@ math/big.lo.dep
+math/big.lo.dep: $(go_math_big_files)
+	$(BUILDDEPS)
+math/big.lo: $(go_math_big_files)
+	$(BUILDPACKAGE)
+math/big/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: math/big/check
+
+@go_include@ math/cmplx.lo.dep
+math/cmplx.lo.dep: $(go_math_cmplx_files)
+	$(BUILDDEPS)
+math/cmplx.lo: $(go_math_cmplx_files)
+	$(BUILDPACKAGE)
+math/cmplx/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: math/cmplx/check
+
+@go_include@ math/rand.lo.dep
+math/rand.lo.dep: $(go_math_rand_files)
+	$(BUILDDEPS)
+math/rand.lo: $(go_math_rand_files)
+	$(BUILDPACKAGE)
+math/rand/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: math/rand/check
+
+@go_include@ mime/multipart.lo.dep
+mime/multipart.lo.dep: $(go_mime_multipart_files)
+	$(BUILDDEPS)
+mime/multipart.lo: $(go_mime_multipart_files)
+	$(BUILDPACKAGE)
+mime/multipart/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: mime/multipart/check
+
+@go_include@ net/http.lo.dep
+net/http.lo.dep: $(go_net_http_files)
+	$(BUILDDEPS)
+net/http.lo: $(go_net_http_files)
+	$(BUILDPACKAGE)
+net/http/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/http/check
+
+@go_include@ net/mail.lo.dep
+net/mail.lo.dep: $(go_net_mail_files)
+	$(BUILDDEPS)
+net/mail.lo: $(go_net_mail_files)
+	$(BUILDPACKAGE)
+net/mail/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/mail/check
+
+@go_include@ net/rpc.lo.dep
+net/rpc.lo.dep: $(go_net_rpc_files)
+	$(BUILDDEPS)
+net/rpc.lo: $(go_net_rpc_files)
+	$(BUILDPACKAGE)
+net/rpc/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/rpc/check
+
+@go_include@ net/smtp.lo.dep
+net/smtp.lo.dep: $(go_net_smtp_files)
+	$(BUILDDEPS)
+net/smtp.lo: $(go_net_smtp_files)
+	$(BUILDPACKAGE)
+net/smtp/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/smtp/check
+
+@go_include@ net/url.lo.dep
+net/url.lo.dep: $(go_net_url_files)
+	$(BUILDDEPS)
+net/url.lo: $(go_net_url_files)
+	$(BUILDPACKAGE)
+net/url/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/url/check
+
+@go_include@ net/textproto.lo.dep
+net/textproto.lo.dep: $(go_net_textproto_files)
+	$(BUILDDEPS)
+net/textproto.lo: $(go_net_textproto_files)
+	$(BUILDPACKAGE)
+net/textproto/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/textproto/check
+
+@go_include@ net/http/cgi.lo.dep
+net/http/cgi.lo.dep: $(go_net_http_cgi_files)
+	$(BUILDDEPS)
+net/http/cgi.lo: $(go_net_http_cgi_files)
+	$(BUILDPACKAGE)
+net/http/cgi/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/http/cgi/check
+
+@go_include@ net/http/cookiejar.lo.dep
+net/http/cookiejar.lo.dep: $(go_net_http_cookiejar_files)
+	$(BUILDDEPS)
+net/http/cookiejar.lo: $(go_net_http_cookiejar_files)
+	$(BUILDPACKAGE)
+net/http/cookiejar/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/http/cookiejar/check
+
+@go_include@ net/http/fcgi.lo.dep
+net/http/fcgi.lo.dep: $(go_net_http_fcgi_files)
+	$(BUILDDEPS)
+net/http/fcgi.lo: $(go_net_http_fcgi_files)
+	$(BUILDPACKAGE)
+net/http/fcgi/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/http/fcgi/check
+
+@go_include@ net/http/httptest.lo.dep
+net/http/httptest.lo.dep: $(go_net_http_httptest_files)
+	$(BUILDDEPS)
+net/http/httptest.lo: $(go_net_http_httptest_files)
+	$(BUILDPACKAGE)
+net/http/httptest/check: $(check_deps)
+	@$(CHECK)
+.PHONY: net/http/httptest/check
+
+@go_include@ net/http/httputil.lo.dep
+net/http/httputil.lo.dep: $(go_net_http_httputil_files)
+	$(BUILDDEPS)
+net/http/httputil.lo: $(go_net_http_httputil_files)
+	$(BUILDPACKAGE)
+net/http/httputil/check: $(check_deps)
+	@$(CHECK)
+.PHONY: net/http/httputil/check
+
+@go_include@ net/http/pprof.lo.dep
+net/http/pprof.lo.dep: $(go_net_http_pprof_files)
+	$(BUILDDEPS)
+net/http/pprof.lo: $(go_net_http_pprof_files)
+	$(BUILDPACKAGE)
+net/http/pprof/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/http/pprof/check
+
+@go_include@ net/rpc/jsonrpc.lo.dep
+net/rpc/jsonrpc.lo.dep: $(go_net_rpc_jsonrpc_files)
+	$(BUILDDEPS)
+net/rpc/jsonrpc.lo: $(go_net_rpc_jsonrpc_files)
+	$(BUILDPACKAGE)
+net/rpc/jsonrpc/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: net/rpc/jsonrpc/check
+
+@go_include@ old/regexp.lo.dep
+old/regexp.lo.dep: $(go_old_regexp_files)
+	$(BUILDDEPS)
+old/regexp.lo: $(go_old_regexp_files)
+	$(BUILDPACKAGE)
+old/regexp/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: old/regexp/check
+
+@go_include@ old/template.lo.dep
+old/template.lo.dep: $(go_old_template_files)
+	$(BUILDDEPS)
+old/template.lo: $(go_old_template_files)
+	$(BUILDPACKAGE)
+old/template/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: old/template/check
+
+@go_include@ os/exec.lo.dep
+os/exec.lo.dep: $(go_os_exec_files)
+	$(BUILDDEPS)
+os/exec.lo: $(go_os_exec_files)
+	$(BUILDPACKAGE)
+os/exec/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: os/exec/check
+
+@go_include@ os/signal.lo.dep
+os/signal.lo.dep: $(go_os_signal_files)
+	$(BUILDDEPS)
+os/signal.lo: $(go_os_signal_files)
+	$(BUILDPACKAGE)
+os/signal/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: os/signal/check
+
+@go_include@ os/user.lo.dep
+os/user.lo.dep: $(go_os_user_files)
+	$(BUILDDEPS)
+os/user.lo: $(go_os_user_files)
+	$(BUILDPACKAGE)
+os/user/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: os/user/check
+
+@go_include@ path/filepath.lo.dep
+path/filepath.lo.dep: $(go_path_filepath_files)
+	$(BUILDDEPS)
+path/filepath.lo: $(go_path_filepath_files)
+	$(BUILDPACKAGE)
+path/filepath/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: path/filepath/check
+
+@go_include@ regexp/syntax.lo.dep
+regexp/syntax.lo.dep: $(go_regexp_syntax_files)
+	$(BUILDDEPS)
+regexp/syntax.lo: $(go_regexp_syntax_files)
+	$(BUILDPACKAGE)
+regexp/syntax/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: regexp/syntax/check
+
+@go_include@ runtime/debug.lo.dep
+runtime/debug.lo.dep: $(go_runtime_debug_files)
+	$(BUILDDEPS)
+runtime/debug.lo: $(go_runtime_debug_files)
+	$(BUILDPACKAGE)
+runtime/debug/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: runtime/debug/check
+
+@go_include@ runtime/pprof.lo.dep
+runtime/pprof.lo.dep: $(go_runtime_pprof_files)
+	$(BUILDDEPS)
+runtime/pprof.lo: $(go_runtime_pprof_files)
+	$(BUILDPACKAGE)
+runtime/pprof/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: runtime/pprof/check
+
+@go_include@ sync/atomic.lo.dep
+sync/atomic.lo.dep: $(go_sync_atomic_files)
+	$(BUILDDEPS)
+sync/atomic.lo: $(go_sync_atomic_files)
+	$(BUILDPACKAGE)
+sync/atomic_c.lo: $(go_sync_atomic_c_files) sync/atomic.lo
+	$(LTCOMPILE) -c -o $@ $(srcdir)/go/sync/atomic/atomic.c
+sync/atomic/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: sync/atomic/check
+
+@go_include@ text/scanner.lo.dep
+text/scanner.lo.dep: $(go_text_scanner_files)
+	$(BUILDDEPS)
+text/scanner.lo: $(go_text_scanner_files)
+	$(BUILDPACKAGE)
+text/scanner/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: text/scanner/check
+
+@go_include@ text/tabwriter.lo.dep
+text/tabwriter.lo.dep: $(go_text_tabwriter_files)
+	$(BUILDDEPS)
+text/tabwriter.lo: $(go_text_tabwriter_files)
+	$(BUILDPACKAGE)
+text/tabwriter/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: text/tabwriter/check
+
+@go_include@ text/template.lo.dep
+text/template.lo.dep: $(go_text_template_files)
+	$(BUILDDEPS)
+text/template.lo: $(go_text_template_files)
+	$(BUILDPACKAGE)
+text/template/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: text/template/check
+
+@go_include@ text/template/parse.lo.dep
+text/template/parse.lo.dep: $(go_text_template_parse_files)
+	$(BUILDDEPS)
+text/template/parse.lo: $(go_text_template_parse_files)
+	$(BUILDPACKAGE)
+text/template/parse/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: text/template/parse/check
+
+@go_include@ testing/iotest.lo.dep
+testing/iotest.lo.dep: $(go_testing_iotest_files)
+	$(BUILDDEPS)
+testing/iotest.lo: $(go_testing_iotest_files)
+	$(BUILDPACKAGE)
+testing/iotest/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: testing/iotest/check
+
+@go_include@ testing/quick.lo.dep
+testing/quick.lo.dep: $(go_testing_quick_files)
+	$(BUILDDEPS)
+testing/quick.lo: $(go_testing_quick_files)
+	$(BUILDPACKAGE)
+testing/quick/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: testing/quick/check
+
+@go_include@ unicode/utf16.lo.dep
+unicode/utf16.lo.dep: $(go_unicode_utf16_files)
+	$(BUILDDEPS)
+unicode/utf16.lo: $(go_unicode_utf16_files)
+	$(BUILDPACKAGE)
+unicode/utf16/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: unicode/utf16/check
+
+@go_include@ unicode/utf8.lo.dep
+unicode/utf8.lo.dep: $(go_unicode_utf8_files)
+	$(BUILDDEPS)
+unicode/utf8.lo: $(go_unicode_utf8_files)
+	$(BUILDPACKAGE)
+unicode/utf8/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: unicode/utf8/check
+
+@go_include@ syscall.lo.dep
+syscall.lo.dep: $(go_syscall_files)
+	$(BUILDDEPS)
+syscall.lo: $(go_syscall_files)
+	$(BUILDPACKAGE)
+syscall/errno.lo: go/syscall/errno.c
+	@$(MKDIR_P) syscall
+	$(LTCOMPILE) -c -o $@ $<
+syscall/signame.lo: go/syscall/signame.c
+	@$(MKDIR_P) syscall
+	$(LTCOMPILE) -c -o $@ $<
+syscall/wait.lo: go/syscall/wait.c
+	@$(MKDIR_P) syscall
+	$(LTCOMPILE) -c -o $@ $<
+syscall/check: $(CHECK_DEPS)
+	@$(CHECK)
+.PHONY: syscall/check
+
+bufio.gox: bufio.lo
+	$(BUILDGOX)
+bytes.gox: bytes.lo
+	$(BUILDGOX)
+crypto.gox: crypto.lo
+	$(BUILDGOX)
+encoding.gox: encoding.lo
+	$(BUILDGOX)
+errors.gox: errors.lo
+	$(BUILDGOX)
+expvar.gox: expvar.lo
+	$(BUILDGOX)
+flag.gox: flag.lo
+	$(BUILDGOX)
+fmt.gox: fmt.lo
+	$(BUILDGOX)
+hash.gox: hash.lo
+	$(BUILDGOX)
+html.gox: html.lo
+	$(BUILDGOX)
+image.gox: image.lo
+	$(BUILDGOX)
+io.gox: io.lo
+	$(BUILDGOX)
+log.gox: log.lo
+	$(BUILDGOX)
+math.gox: math.lo
+	$(BUILDGOX)
+mime.gox: mime.lo
+	$(BUILDGOX)
+net.gox: net.lo
+	$(BUILDGOX)
+os.gox: os.lo
+	$(BUILDGOX)
+path.gox: path.lo
+	$(BUILDGOX)
+reflect.gox: reflect-go.lo
+	$(BUILDGOX)
+regexp.gox: regexp.lo
+	$(BUILDGOX)
+runtime.gox: runtime-go.lo
+	$(BUILDGOX)
+sort.gox: sort.lo
+	$(BUILDGOX)
+strconv.gox: strconv.lo
+	$(BUILDGOX)
+strings.gox: strings.lo
+	$(BUILDGOX)
+sync.gox: sync.lo
+	$(BUILDGOX)
+syscall.gox: syscall.lo
+	$(BUILDGOX)
+testing.gox: testing.lo
+	$(BUILDGOX)
+time.gox: time-go.lo
+	$(BUILDGOX)
+unicode.gox: unicode.lo
+	$(BUILDGOX)
+
+archive/tar.gox: archive/tar.lo
+	$(BUILDGOX)
+archive/zip.gox: archive/zip.lo
+	$(BUILDGOX)
+
+compress/bzip2.gox: compress/bzip2.lo
+	$(BUILDGOX)
+compress/flate.gox: compress/flate.lo
+	$(BUILDGOX)
+compress/gzip.gox: compress/gzip.lo
+	$(BUILDGOX)
+compress/lzw.gox: compress/lzw.lo
+	$(BUILDGOX)
+compress/zlib.gox: compress/zlib.lo
+	$(BUILDGOX)
+
+container/heap.gox: container/heap.lo
+	$(BUILDGOX)
+container/list.gox: container/list.lo
+	$(BUILDGOX)
+container/ring.gox: container/ring.lo
+	$(BUILDGOX)
+
+crypto/aes.gox: crypto/aes.lo
+	$(BUILDGOX)
+crypto/cipher.gox: crypto/cipher.lo
+	$(BUILDGOX)
+crypto/des.gox: crypto/des.lo
+	$(BUILDGOX)
+crypto/dsa.gox: crypto/dsa.lo
+	$(BUILDGOX)
+crypto/ecdsa.gox: crypto/ecdsa.lo	
+	$(BUILDGOX)
+crypto/elliptic.gox: crypto/elliptic.lo
+	$(BUILDGOX)
+crypto/hmac.gox: crypto/hmac.lo
+	$(BUILDGOX)
+crypto/md5.gox: crypto/md5.lo
+	$(BUILDGOX)
+crypto/rand.gox: crypto/rand.lo
+	$(BUILDGOX)
+crypto/rc4.gox: crypto/rc4.lo
+	$(BUILDGOX)
+crypto/rsa.gox: crypto/rsa.lo
+	$(BUILDGOX)
+crypto/sha1.gox: crypto/sha1.lo
+	$(BUILDGOX)
+crypto/sha256.gox: crypto/sha256.lo
+	$(BUILDGOX)
+crypto/sha512.gox: crypto/sha512.lo
+	$(BUILDGOX)
+crypto/subtle.gox: crypto/subtle.lo
+	$(BUILDGOX)
+crypto/tls.gox: crypto/tls.lo
+	$(BUILDGOX)
+crypto/x509.gox: crypto/x509.lo
+	$(BUILDGOX)
+
+crypto/x509/pkix.gox: crypto/x509/pkix.lo
+	$(BUILDGOX)
+
+database/sql.gox: database/sql.lo
+	$(BUILDGOX)
+
+database/sql/driver.gox: database/sql/driver.lo
+	$(BUILDGOX)
+
+debug/dwarf.gox: debug/dwarf.lo
+	$(BUILDGOX)
+debug/elf.gox: debug/elf.lo
+	$(BUILDGOX)
+debug/gosym.gox: debug/gosym.lo
+	$(BUILDGOX)
+debug/macho.gox: debug/macho.lo
+	$(BUILDGOX)
+debug/pe.gox: debug/pe.lo
+	$(BUILDGOX)
+debug/plan9obj.gox: debug/plan9obj.lo
+	$(BUILDGOX)
+
+encoding/ascii85.gox: encoding/ascii85.lo
+	$(BUILDGOX)
+encoding/asn1.gox: encoding/asn1.lo
+	$(BUILDGOX)
+encoding/base32.gox: encoding/base32.lo
+	$(BUILDGOX)
+encoding/base64.gox: encoding/base64.lo
+	$(BUILDGOX)
+encoding/binary.gox: encoding/binary.lo
+	$(BUILDGOX)
+encoding/csv.gox: encoding/csv.lo
+	$(BUILDGOX)
+encoding/gob.gox: encoding/gob.lo
+	$(BUILDGOX)
+encoding/hex.gox: encoding/hex.lo
+	$(BUILDGOX)
+encoding/json.gox: encoding/json.lo
+	$(BUILDGOX)
+encoding/pem.gox: encoding/pem.lo
+	$(BUILDGOX)
+encoding/xml.gox: encoding/xml.lo
+	$(BUILDGOX)
+
+exp/proxy.gox: exp/proxy.lo
+	$(BUILDGOX)
+exp/terminal.gox: exp/terminal.lo
+	$(BUILDGOX)
+
+html/template.gox: html/template.lo
+	$(BUILDGOX)
+
+go/ast.gox: go/ast.lo
+	$(BUILDGOX)
+go/build.gox: go/build.lo
+	$(BUILDGOX)
+go/doc.gox: go/doc.lo
+	$(BUILDGOX)
+go/format.gox: go/format.lo
+	$(BUILDGOX)
+go/parser.gox: go/parser.lo
+	$(BUILDGOX)
+go/printer.gox: go/printer.lo
+	$(BUILDGOX)
+go/scanner.gox: go/scanner.lo
+	$(BUILDGOX)
+go/token.gox: go/token.lo
+	$(BUILDGOX)
+
+hash/adler32.gox: hash/adler32.lo
+	$(BUILDGOX)
+hash/crc32.gox: hash/crc32.lo
+	$(BUILDGOX)
+hash/crc64.gox: hash/crc64.lo
+	$(BUILDGOX)
+hash/fnv.gox: hash/fnv.lo
+	$(BUILDGOX)
+
+image/color.gox: image/color.lo
+	$(BUILDGOX)
+image/draw.gox: image/draw.lo
+	$(BUILDGOX)
+image/gif.gox: image/gif.lo
+	$(BUILDGOX)
+image/jpeg.gox: image/jpeg.lo
+	$(BUILDGOX)
+image/png.gox: image/png.lo
+	$(BUILDGOX)
+
+image/color/palette.gox: image/color/palette.lo
+	$(BUILDGOX)
+
+index/suffixarray.gox: index/suffixarray.lo
+	$(BUILDGOX)
+
+io/ioutil.gox: io/ioutil.lo
+	$(BUILDGOX)
+
+log/syslog.gox: log/syslog.lo
+	$(BUILDGOX)
+
+math/big.gox: math/big.lo
+	$(BUILDGOX)
+math/cmplx.gox: math/cmplx.lo
+	$(BUILDGOX)
+math/rand.gox: math/rand.lo
+	$(BUILDGOX)
+
+mime/multipart.gox: mime/multipart.lo
+	$(BUILDGOX)
+
+net/http.gox: net/http.lo
+	$(BUILDGOX)
+net/mail.gox: net/mail.lo
+	$(BUILDGOX)
+net/rpc.gox: net/rpc.lo
+	$(BUILDGOX)
+net/smtp.gox: net/smtp.lo
+	$(BUILDGOX)
+net/textproto.gox: net/textproto.lo
+	$(BUILDGOX)
+net/url.gox: net/url.lo
+	$(BUILDGOX)
+
+net/http/cgi.gox: net/http/cgi.lo
+	$(BUILDGOX)
+net/http/cookiejar.gox: net/http/cookiejar.lo
+	$(BUILDGOX)
+net/http/fcgi.gox: net/http/fcgi.lo
+	$(BUILDGOX)
+net/http/httptest.gox: net/http/httptest.lo
+	$(BUILDGOX)
+net/http/httputil.gox: net/http/httputil.lo
+	$(BUILDGOX)
+net/http/pprof.gox: net/http/pprof.lo
+	$(BUILDGOX)
+
+net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo
+	$(BUILDGOX)
+
+old/regexp.gox: old/regexp.lo
+	$(BUILDGOX)
+old/template.gox: old/template.lo
+	$(BUILDGOX)
+
+os/exec.gox: os/exec.lo
+	$(BUILDGOX)
+os/signal.gox: os/signal.lo
+	$(BUILDGOX)
+os/user.gox: os/user.lo
+	$(BUILDGOX)
+
+path/filepath.gox: path/filepath.lo
+	$(BUILDGOX)
+
+regexp/syntax.gox: regexp/syntax.lo
+	$(BUILDGOX)
+
+runtime/debug.gox: runtime/debug.lo
+	$(BUILDGOX)
+runtime/pprof.gox: runtime/pprof.lo
+	$(BUILDGOX)
+
+sync/atomic.gox: sync/atomic.lo
+	$(BUILDGOX)
+
+text/scanner.gox: text/scanner.lo
+	$(BUILDGOX)
+text/tabwriter.gox: text/tabwriter.lo
+	$(BUILDGOX)
+text/template.gox: text/template.lo
+	$(BUILDGOX)
+text/template/parse.gox: text/template/parse.lo
+	$(BUILDGOX)
+
+testing/iotest.gox: testing/iotest.lo
+	$(BUILDGOX)
+testing/quick.gox: testing/quick.lo
+	$(BUILDGOX)
+
+unicode/utf16.gox: unicode/utf16.lo
+	$(BUILDGOX)
+unicode/utf8.gox: unicode/utf8.lo
+	$(BUILDGOX)
+
+check: check-tail
+check-recursive: check-head
+
+check-head:
+	@echo "Test Run By $${USER} on `date`" > libgo.head
+	@echo "Native configuration is $(host_triplet)" >> libgo.head
+	@echo >> libgo.head
+	@echo "		=== libgo tests ===" >> libgo.head
+	@echo >> libgo.head
+
+check-tail: check-recursive check-multi
+	@if test "$(USE_DEJAGNU)" = "yes"; then \
+	  exit 0; \
+	fi; \
+	lib=`${PWD_COMMAND} | sed -e 's,^.*/\([^/][^/]*\)$$,\1,'`; \
+	for dir in . $(MULTIDIRS); do \
+	  mv ../$${dir}/$${lib}/libgo.sum ../$${dir}/$${lib}/libgo.sum.sep; \
+	  mv ../$${dir}/$${lib}/libgo.log ../$${dir}/$${lib}/libgo.log.sep; \
+	done; \
+	mv libgo.head libgo.sum; \
+	cp libgo.sum libgo.log; \
+	echo "Schedule of variations:" >> libgo.sum; \
+	for dir in . $(MULTIDIRS); do \
+	  multidir=../$${dir}/$${lib}; \
+	  multivar=`cat $${multidir}/libgo.var`; \
+	  echo "    $${multivar}" >> libgo.sum; \
+	done; \
+	echo >> libgo.sum; \
+	pass=0; fail=0; untested=0; \
+	for dir in . $(MULTIDIRS); do \
+	  multidir=../$${dir}/$${lib}; \
+	  multivar=`cat $${multidir}/libgo.var`; \
+	  echo "Running target $${multivar}" >> libgo.sum; \
+	  echo "Running $(srcdir)/libgo.exp ..." >> libgo.sum; \
+	  cat $${multidir}/libgo.sum.sep >> libgo.sum; \
+	  cat $${multidir}/libgo.log.sep >> libgo.log; \
+	  if test -n "${MULTIDIRS}"; then \
+	    echo "		=== libgo Summary for $${multivar} ===" >> libgo.sum; \
+	    echo >> libgo.sum; \
+	  fi; \
+	  p=`grep -c PASS $${multidir}/libgo.sum.sep`; \
+	  pass=`expr $$pass + $$p`; \
+	  if test "$$p" -ne "0" && test -n "${MULTIDIRS}"; then \
+	    echo "# of expected passes		$$p" >> libgo.sum; \
+	  fi; \
+	  p=`grep -c FAIL $${multidir}/libgo.sum.sep`; \
+	  fail=`expr $$fail + $$p`; \
+	  if test "$$p" -ne "0" && test -n "${MULTIDIRS}"; then \
+	    echo "# of unexpected failures	$$p" >> libgo.sum; \
+	  fi; \
+	  p=`grep -c UNTESTED $${multidir}/libgo.sum.sep`; \
+	  untested=`expr $$untested + $$p`; \
+	  if test "$$p" -ne "0" && test -n "${MULTIDIRS}"; then \
+	    echo "# of untested testcases		$$p" >> libgo.sum; \
+	  fi; \
+	done; \
+	echo >> libgo.sum; \
+	echo "		=== libgo Summary ===" >> libgo.sum; \
+	echo >> libgo.sum; \
+	if test "$$pass" -ne "0"; then \
+	  echo "# of expected passes		$$pass" >> libgo.sum; \
+	fi; \
+	if test "$$fail" -ne "0"; then \
+	  echo "# of unexpected failures	$$fail" >> libgo.sum; \
+	fi; \
+	if test "$$untested" -ne "0"; then \
+	  echo "# of untested testcases		$$untested" >> libgo.sum; \
+	fi; \
+	echo `echo $(GOC) | sed -e 's/ .*//'`  `$(GOC) -v 2>&1 | grep " version" | sed -n -e 's/.* \(version.*$$\)/\1/p'` >> libgo.sum; \
+	echo >> libgo.log; \
+	echo "runtest completed at `date`" >> libgo.log; \
+	if test "$$fail" -ne "0"; then \
+	  status=1; \
+	else \
+	  status=0; \
+	fi; \
+	exit $$status
+
+check-am:
+	@rm -f libgo.sum libgo.log libgo.tail
+	@multivar="unix"; \
+	[ -z "$(MULTIFLAGS)" ] || multivar="$${multivar}/$(MULTIFLAGS)"; \
+	echo "$${multivar}" > libgo.var
+	@for f in $(TEST_PACKAGES); do \
+	   rm -f $$f-testsum $$f-testlog; \
+	 done
+	-@$(MAKE) -k $(TEST_PACKAGES)
+	@for f in $(TEST_PACKAGES); do \
+	  if test -f $$f-testsum; then \
+	    cat $$f-testsum >> libgo.sum; \
+	  fi; \
+	  if test -f $$f-testlog; then \
+	    cat $$f-testlog >> libgo.log; \
+	  fi; \
+	done
+
+check-multi:
+	$(MULTIDO) $(AM_MAKEFLAGS) DO=check-am multi-do # $(MAKE)
+
+bench:
+	-@$(MAKE) -k $(TEST_PACKAGES) GOBENCH=.
+
+mostlyclean-local:
+	find . -name '*.lo' -print | xargs $(LIBTOOL) --mode=clean rm -f
+	find . -name '*.$(OBJEXT)' -print | xargs rm -f
+	find . -name '*-testsum' -print | xargs rm -f
+	find . -name '*-testlog' -print | xargs rm -f
+
+clean-local:
+	find . -name '*.la' -print | xargs $(LIBTOOL) --mode=clean rm -f
+	find . -name '*.a' -print | xargs rm -f
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/third_party/gofrontend/libgo/PATENTS b/third_party/gofrontend/libgo/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/third_party/gofrontend/libgo/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go.  This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation.  If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/third_party/gofrontend/libgo/README b/third_party/gofrontend/libgo/README
new file mode 100644
index 0000000..732c352
--- /dev/null
+++ b/third_party/gofrontend/libgo/README
@@ -0,0 +1,45 @@
+See ../README.
+
+This is the runtime support library for the Go programming language.
+This library is intended for use with the Go frontend.
+
+The library has only been tested on GNU/Linux using glibc.  It should
+not be difficult to port to other operating systems.
+
+The library has only been tested on x86/x86_64 systems.  It should not
+be difficult to port to other architectures.
+
+Directories:
+
+go
+  A copy of the Go library from http://golang.org/, with a few
+  changes for gccgo.  Notably, the reflection interface is different.
+
+runtime
+  Runtime functions, written in C, which are called directly by the
+  compiler or by the library.
+
+syscalls
+  System call support.
+
+Contributing
+============
+
+To contribute patches to the files in this directory, please see
+http://golang.org/doc/gccgo_contribute.html .
+
+The master copy of these files is hosted at
+http://code.google.com/p/gofrontend .  Changes to these files require
+signing a Google contributor license agreement.  If you are the
+copyright holder, you will need to agree to the individual contributor
+license agreement at
+http://code.google.com/legal/individual-cla-v1.0.html.  This agreement
+can be completed online.
+
+If your organization is the copyright holder, the organization will
+need to agree to the corporate contributor license agreement at
+http://code.google.com/legal/corporate-cla-v1.0.html.
+
+If the copyright holder for your code has already completed the
+agreement in connection with another Google open source project, it
+does not need to be completed again.
diff --git a/third_party/gofrontend/libgo/README.gcc b/third_party/gofrontend/libgo/README.gcc
new file mode 100644
index 0000000..d5aabb0
--- /dev/null
+++ b/third_party/gofrontend/libgo/README.gcc
@@ -0,0 +1,7 @@
+The files in this directory are mirrored from the gofrontend project
+hosted at http://code.google.com/p/gofrontend.  These files are the
+ones in the libgo subdirectory of that project.
+
+By default, the networking tests are not run.  In order to run all the
+libgo tests, you need to define the environment variable
+GCCGO_RUN_ALL_TESTS to a non-empty string.
diff --git a/third_party/gofrontend/libgo/aclocal.m4 b/third_party/gofrontend/libgo/aclocal.m4
new file mode 100644
index 0000000..ca453c6
--- /dev/null
+++ b/third_party/gofrontend/libgo/aclocal.m4
@@ -0,0 +1,981 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
+[m4_warning([this file was generated for autoconf 2.64.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.11.1], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+	[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 10
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+       [$1], UPC,  [depcc="$UPC"  am_compiler_list=],
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 5
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named `Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`AS_DIRNAME("$mf")`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running `make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # When using ansi2knr, U may be empty or an underscore; expand it
+    U=`sed -n 's/^U = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`AS_DIRNAME(["$file"])`
+      AS_MKDIR_P([$dirpart/$fdir])
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+			     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+		  [_AM_DEPENDENCIES(CC)],
+		  [define([AC_PROG_CC],
+			  defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+		  [_AM_DEPENDENCIES(CXX)],
+		  [define([AC_PROG_CXX],
+			  defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+		  [_AM_DEPENDENCIES(OBJC)],
+		  [define([AC_PROG_OBJC],
+			  defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST(install_sh)])
+
+# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless `enable' is passed literally.
+# For symmetry, `disable' may be passed as well.  Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+       [enable], [m4_define([am_maintainer_other], [disable])],
+       [disable], [m4_define([am_maintainer_other], [enable])],
+       [m4_define([am_maintainer_other], [enable])
+        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
+  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+  AC_ARG_ENABLE([maintainer-mode],
+[  --][am_maintainer_other][-maintainer-mode  am_maintainer_other make rules and dependencies not useful
+			  (and sometimes confusing) to the casual installer],
+      [USE_MAINTAINER_MODE=$enableval],
+      [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST([MAINT])dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2009  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p.  We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+  [[\\/$]]* | ?:[[\\/]]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
+    AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([../config/depstand.m4])
+m4_include([../config/lead-dot.m4])
+m4_include([../config/multi.m4])
+m4_include([../config/override.m4])
+m4_include([../config/unwind_ipinfo.m4])
+m4_include([config/go.m4])
+m4_include([config/libtool.m4])
+m4_include([config/ltoptions.m4])
+m4_include([config/ltsugar.m4])
+m4_include([config/ltversion.m4])
+m4_include([config/lt~obsolete.m4])
diff --git a/third_party/gofrontend/libgo/config.h.in b/third_party/gofrontend/libgo/config.h.in
new file mode 100644
index 0000000..9e622c6
--- /dev/null
+++ b/third_party/gofrontend/libgo/config.h.in
@@ -0,0 +1,399 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Define to the flags needed for the .section .eh_frame directive. */
+#undef EH_FRAME_FLAGS
+
+/* Define to 1 if you have the `accept4' function. */
+#undef HAVE_ACCEPT4
+
+/* Define to 1 if you have the `acosl' function. */
+#undef HAVE_ACOSL
+
+/* Define to 1 if you have the `asinl' function. */
+#undef HAVE_ASINL
+
+/* Define if your assembler supports GNU comdat group syntax. */
+#undef HAVE_AS_COMDAT_GAS
+
+/* Define if your assembler supports unwind section type. */
+#undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE
+
+/* Define if your assembler supports PC relative relocs. */
+#undef HAVE_AS_X86_PCREL
+
+/* Define to 1 if you have the `atan2l' function. */
+#undef HAVE_ATAN2L
+
+/* Define to 1 if you have the `atanl' function. */
+#undef HAVE_ATANL
+
+/* Define to 1 if you have the `cosl' function. */
+#undef HAVE_COSL
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `dl_iterate_phdr' function. */
+#undef HAVE_DL_ITERATE_PHDR
+
+/* Define to 1 if you have the `dup3' function. */
+#undef HAVE_DUP3
+
+/* Define to 1 if you have the `epoll_create1' function. */
+#undef HAVE_EPOLL_CREATE1
+
+/* Define to 1 if you have the `expl' function. */
+#undef HAVE_EXPL
+
+/* Define to 1 if you have the `expm1l' function. */
+#undef HAVE_EXPM1L
+
+/* Define to 1 if you have the `faccessat' function. */
+#undef HAVE_FACCESSAT
+
+/* Define to 1 if you have the `fallocate' function. */
+#undef HAVE_FALLOCATE
+
+/* Define to 1 if you have the `fchmodat' function. */
+#undef HAVE_FCHMODAT
+
+/* Define to 1 if you have the `fchownat' function. */
+#undef HAVE_FCHOWNAT
+
+/* Define to 1 if you have the `futimesat' function. */
+#undef HAVE_FUTIMESAT
+
+/* Define if _Unwind_GetIPInfo is available. */
+#undef HAVE_GETIPINFO
+
+/* Define to 1 if you have the `getxattr' function. */
+#undef HAVE_GETXATTR
+
+/* Define to 1 if you have the `inotify_add_watch' function. */
+#undef HAVE_INOTIFY_ADD_WATCH
+
+/* Define to 1 if you have the `inotify_init' function. */
+#undef HAVE_INOTIFY_INIT
+
+/* Define to 1 if you have the `inotify_init1' function. */
+#undef HAVE_INOTIFY_INIT1
+
+/* Define to 1 if you have the `inotify_rm_watch' function. */
+#undef HAVE_INOTIFY_RM_WATCH
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `ldexpl' function. */
+#undef HAVE_LDEXPL
+
+/* Define to 1 if you have the <linux/ether.h> header file. */
+#undef HAVE_LINUX_ETHER_H
+
+/* Define to 1 if you have the <linux/filter.h> header file. */
+#undef HAVE_LINUX_FILTER_H
+
+/* Define to 1 if you have the <linux/fs.h> header file. */
+#undef HAVE_LINUX_FS_H
+
+/* Define to 1 if you have the <linux/if_addr.h> header file. */
+#undef HAVE_LINUX_IF_ADDR_H
+
+/* Define to 1 if you have the <linux/if_ether.h> header file. */
+#undef HAVE_LINUX_IF_ETHER_H
+
+/* Define to 1 if you have the <linux/if_tun.h> header file. */
+#undef HAVE_LINUX_IF_TUN_H
+
+/* Define to 1 if you have the <linux/netlink.h> header file. */
+#undef HAVE_LINUX_NETLINK_H
+
+/* Define to 1 if you have the <linux/reboot.h> header file. */
+#undef HAVE_LINUX_REBOOT_H
+
+/* Define to 1 if you have the <linux/rtnetlink.h> header file. */
+#undef HAVE_LINUX_RTNETLINK_H
+
+/* Define to 1 if you have the `listxattr' function. */
+#undef HAVE_LISTXATTR
+
+/* Define to 1 if the system has the type `loff_t'. */
+#undef HAVE_LOFF_T
+
+/* Define to 1 if you have the `log10l' function. */
+#undef HAVE_LOG10L
+
+/* Define to 1 if you have the `log1pl' function. */
+#undef HAVE_LOG1PL
+
+/* Define to 1 if you have the `logl' function. */
+#undef HAVE_LOGL
+
+/* Define to 1 if you have the `matherr' function. */
+#undef HAVE_MATHERR
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mincore' function. */
+#undef HAVE_MINCORE
+
+/* Define to 1 if you have the `mkdirat' function. */
+#undef HAVE_MKDIRAT
+
+/* Define to 1 if you have the `mknodat' function. */
+#undef HAVE_MKNODAT
+
+/* Define to 1 if you have the <netinet/icmp6.h> header file. */
+#undef HAVE_NETINET_ICMP6_H
+
+/* Define to 1 if you have the <netinet/if_ether.h> header file. */
+#undef HAVE_NETINET_IF_ETHER_H
+
+/* Define to 1 if you have the <netinet/in_syst.h> header file. */
+#undef HAVE_NETINET_IN_SYST_H
+
+/* Define to 1 if you have the <netinet/ip.h> header file. */
+#undef HAVE_NETINET_IP_H
+
+/* Define to 1 if you have the <netinet/ip_mroute.h> header file. */
+#undef HAVE_NETINET_IP_MROUTE_H
+
+/* Define to 1 if you have the <netpacket/packet.h> header file. */
+#undef HAVE_NETPACKET_PACKET_H
+
+/* Define to 1 if you have the <net/if_arp.h> header file. */
+#undef HAVE_NET_IF_ARP_H
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
+/* Define to 1 if you have the <net/route.h> header file. */
+#undef HAVE_NET_ROUTE_H
+
+/* Define to 1 if the system has the type `off64_t'. */
+#undef HAVE_OFF64_T
+
+/* Define to 1 if you have the `open64' function. */
+#undef HAVE_OPEN64
+
+/* Define to 1 if you have the `openat' function. */
+#undef HAVE_OPENAT
+
+/* Define to 1 if you have the `pipe2' function. */
+#undef HAVE_PIPE2
+
+/* Define to 1 if you have the `removexattr' function. */
+#undef HAVE_REMOVEXATTR
+
+/* Define to 1 if you have the `renameat' function. */
+#undef HAVE_RENAMEAT
+
+/* Define to 1 if you have the <sched.h> header file. */
+#undef HAVE_SCHED_H
+
+/* Define to 1 if you have the `sem_timedwait' function. */
+#undef HAVE_SEM_TIMEDWAIT
+
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the `setxattr' function. */
+#undef HAVE_SETXATTR
+
+/* Define to 1 if you have the `sinl' function. */
+#undef HAVE_SINL
+
+/* Define to 1 if you have the `splice' function. */
+#undef HAVE_SPLICE
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strerror_r' function. */
+#undef HAVE_STRERROR_R
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strsignal' function. */
+#undef HAVE_STRSIGNAL
+
+/* Define to 1 if <math.h> defines struct exception */
+#undef HAVE_STRUCT_EXCEPTION
+
+/* Define to 1 if the compiler provides the __sync_add_and_fetch function for
+   uint64 */
+#undef HAVE_SYNC_ADD_AND_FETCH_8
+
+/* Define to 1 if the compiler provides the __sync_bool_compare_and_swap
+   function for uint32 */
+#undef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
+
+/* Define to 1 if the compiler provides the __sync_bool_compare_and_swap
+   function for uint64 */
+#undef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8
+
+/* Define to 1 if the compiler provides the __sync_fetch_and_add function for
+   uint32 */
+#undef HAVE_SYNC_FETCH_AND_ADD_4
+
+/* Define to 1 if you have the `sync_file_range' function. */
+#undef HAVE_SYNC_FILE_RANGE
+
+/* Define to 1 if you have the <syscall.h> header file. */
+#undef HAVE_SYSCALL_H
+
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+#undef HAVE_SYS_EPOLL_H
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define to 1 if you have the <sys/inotify.h> header file. */
+#undef HAVE_SYS_INOTIFY_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#undef HAVE_SYS_MOUNT_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define to 1 if you have the <sys/ptrace.h> header file. */
+#undef HAVE_SYS_PTRACE_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/statfs.h> header file. */
+#undef HAVE_SYS_STATFS_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
+/* Define to 1 if you have the <sys/sysinfo.h> header file. */
+#undef HAVE_SYS_SYSINFO_H
+
+/* Define to 1 if you have the <sys/timex.h> header file. */
+#undef HAVE_SYS_TIMEX_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/user.h> header file. */
+#undef HAVE_SYS_USER_H
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+#undef HAVE_SYS_UTSNAME_H
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+#undef HAVE_SYS_VFS_H
+
+/* Define to 1 if you have the `tanl' function. */
+#undef HAVE_TANL
+
+/* Define to 1 if you have the `tee' function. */
+#undef HAVE_TEE
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `unlinkat' function. */
+#undef HAVE_UNLINKAT
+
+/* Define to 1 if you have the `unshare' function. */
+#undef HAVE_UNSHARE
+
+/* Define to 1 if you have the <ustat.h> header file and it works. */
+#undef HAVE_USTAT_H
+
+/* Define to 1 if you have the `utimensat' function. */
+#undef HAVE_UTIMENSAT
+
+/* Define to 1 if you have the <utime.h> header file. */
+#undef HAVE_UTIME_H
+
+/* Define to 1 if you have the `wait4' function. */
+#undef HAVE_WAIT4
+
+/* Define if the C++ compiler is configured for setjmp/longjmp exceptions. */
+#undef LIBGO_SJLJ_EXCEPTIONS
+
+/* Define if the linker support split stack adjustments */
+#undef LINKER_SUPPORTS_SPLIT_STACK
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define if setcontext clobbers TLS variables */
+#undef SETCONTEXT_CLOBBERS_TLS
+
+/* The size of `void *', as computed by sizeof. */
+#undef SIZEOF_VOID_P
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if we're to use libffi. */
+#undef USE_LIBFFI
+
+/* Define if the compiler supports -fsplit-stack */
+#undef USING_SPLIT_STACK
+
+/* Version number of package */
+#undef VERSION
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+#  undef WORDS_BIGENDIAN
+# endif
+#endif
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
diff --git a/third_party/gofrontend/libgo/config/README b/third_party/gofrontend/libgo/config/README
new file mode 100644
index 0000000..06e8bf5
--- /dev/null
+++ b/third_party/gofrontend/libgo/config/README
@@ -0,0 +1,2 @@
+This directory holds files needed temporarily until Go support is
+added to autoconf and libtool.
diff --git a/third_party/gofrontend/libgo/config/go.m4 b/third_party/gofrontend/libgo/config/go.m4
new file mode 100644
index 0000000..65a27cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/config/go.m4
@@ -0,0 +1,92 @@
+dnl acinclude.m4 -- configure macros
+
+dnl Copyright 2009 The Go Authors. All rights reserved.
+dnl Use of this source code is governed by a BSD-style
+dnl license that can be found in the LICENSE file.
+
+dnl Go support--this could be in autoconf.
+dnl This version is probably autoconf 2.64 specific.
+
+AC_LANG_DEFINE([Go], [go], [GO], [],
+[ac_ext=go
+ac_compile='$GOC -c $GOCFLAGS conftest.$ac_ext >&AS_MESSAGE_LOG_FD'
+ac_link='$GOC -o conftest$ac_exeext $GOCFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&AS_MESSAGE_LOG_FD'
+ac_compile_gnu=yes
+])
+
+AU_DEFUN([AC_LANG_GO], [AC_LANG(Go)])
+
+m4_define([AC_LANG_PROGRAM(Go)],
+[package main
+$1
+func main() {
+$2
+}])
+
+m4_define([AC_LANG_IO_PROGRAM(Go)],
+[AC_LANG_PROGRAM([import "os"],
+[if f, err := os.Open("conftest.out", os.O_WRONLY), err != nil {
+	os.Exit(1);
+ }
+ if err := f.Close(); err != nil {
+	os.Exit(1);
+ }
+ os.Exit(0);
+])])
+
+m4_define([AC_LANG_CALL(Go)],
+[AC_LANG_PROGRAM([$1
+m4_if([$2], [main], ,
+[func $2();])],[$2();])])
+
+m4_define([AC_LANG_FUNC_LINK_TRY(Go)],
+[AC_LANG_PROGRAM(
+[func $1() int;
+var f := $1;
+], [return f();])])
+
+m4_define([AC_LANG_BOOL_COMPILE_TRY(Go)],
+[AC_LANG_PROGRAM([$1], [var test_array @<:@1 - 2 * !($2)@:>@;
+test_array @<:@0@:>@ = 0
+])])
+
+m4_define([AC_LANG_INT_SAVE(Go)],
+[AC_LANG_PROGRAM([$1
+import os
+func longval() long { return $2 }
+func ulongval() ulong { return $2 }],
+[panic("unimplemented")])])
+
+AC_DEFUN([AC_LANG_COMPILER(Go)],
+[AC_REQUIRE([AC_PROG_GO])])
+
+AN_MAKEVAR([GOC], [AC_PROG_GO])
+AN_PROGRAM([gccgo], [AC_PROG_GO])
+AC_DEFUN([AC_PROG_GO],
+[AC_LANG_PUSH(Go)dnl
+AC_ARG_VAR([GOC],   [Go compiler command])dnl
+AC_ARG_VAR([GOCFLAGS], [Go compiler flags])dnl
+_AC_ARG_VAR_LDFLAGS()dnl
+m4_ifval([$1],
+      [AC_CHECK_TOOLS(GOC, [$1])],
+[AC_CHECK_TOOL(GOC, gccgo)
+if test -z "$GOC"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [$ac_tool_prefix}gccgo])
+  fi
+fi
+if test -z "$GOC"; then
+  AC_CHECK_PROG(GOC, gccgo, gccgo, , , gccgo)
+fi
+])
+
+# Provide some information about the compiler.
+_AS_ECHO_LOG([checking for _AC_LANG compiler version])
+set X $ac_compile
+ac_compiler=$[2]
+_AC_DO_LIMIT([$ac_compiler --version >&AS_MESSAGE_LOG_FD])
+m4_expand_once([_AC_COMPILER_EXEEXT])[]dnl
+m4_expand_once([_AC_COMPILER_OBJEXT])[]dnl
+GOCFLAGS="-g -O2"
+AC_LANG_POP(Go)dnl
+])# AC_PROG_GO
diff --git a/third_party/gofrontend/libgo/config/libtool.m4 b/third_party/gofrontend/libgo/config/libtool.m4
new file mode 100644
index 0000000..f700594
--- /dev/null
+++ b/third_party/gofrontend/libgo/config/libtool.m4
@@ -0,0 +1,7518 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+])
+
+# serial 56 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+       [m4_default([$3],
+		   [m4_fatal([Libtool version $1 or higher is required],
+		             63)])],
+       [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+  *\ * | *\	*)
+    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
+AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+m4_defun([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+  case $cc_temp in
+    compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+    distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    _LT_PATH_MAGIC
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PREPARE_SED_QUOTE_VARS
+# --------------------------
+# Define a few sed substitution that help us do robust quoting.
+m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+[# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+])
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from `configure', and `config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
+# `config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain="$ac_aux_dir/ltmain.sh"
+])# _LT_PROG_LTMAIN
+
+
+## ------------------------------------- ##
+## Accumulate code for creating libtool. ##
+## ------------------------------------- ##
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the `libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+## ------------------------ ##
+## FIXME: Eliminate VARNAME ##
+## ------------------------ ##
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME.  Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+	[m4_ifval([$1], [$1], [$2])])
+    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+    m4_ifval([$4],
+	[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+    lt_dict_add_subkey([lt_decl_dict], [$2],
+	[tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+  [0], [m4_fatal([$0: too few arguments: $#])],
+  [1], [m4_fatal([$0: too few arguments: $#: $1])],
+  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+     m4_if([$2], [],
+	   m4_quote(lt_decl_varnames),
+	m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+			lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to `config.status' so that its
+# declaration there will have the same value as in `configure'.  VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly.  In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+#    <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags="_LT_TAGS"dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+#    # Some comment about what VAR is for.
+#    visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+					   [description])))[]dnl
+m4_pushdef([_libtool_name],
+    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+    [0], [_libtool_name=[$]$1],
+    [1], [_libtool_name=$lt_[]$1],
+    [2], [_libtool_name=$lt_[]$1],
+    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
+# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into `config.status', and then the shell code to quote escape them in
+# for loops in `config.status'.  Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+	dnl If the libtool generation code has been placed in $CONFIG_LT,
+	dnl instead of duplicating it all over again into config.status,
+	dnl then we will have config.status run $CONFIG_LT later, so it
+	dnl needs to know what name is stored there:
+        [AC_CONFIG_COMMANDS([libtool],
+            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+    dnl If the libtool generation code is destined for config.status,
+    dnl expand the accumulated commands and init code now:
+    [AC_CONFIG_COMMANDS([libtool],
+        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$[]1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+# ------------------------------------
+# Generate a child script FILE with all initialization necessary to
+# reuse the environment learned by the parent script, and make the
+# file executable.  If COMMENT is supplied, it is inserted after the
+# `#!' sequence but before initialization text begins.  After this
+# macro, additional text can be appended to FILE to form the body of
+# the child script.  The macro ends with non-zero status if the
+# file could not be fully written (such as if the disk is full).
+m4_ifdef([AS_INIT_GENERATED],
+[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+[m4_defun([_LT_GENERATED_FILE_INIT],
+[m4_require([AS_PREPARE])]dnl
+[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+[lt_write_fail=0
+cat >$1 <<_ASEOF || lt_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+$2
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$1 <<\_ASEOF || lt_write_fail=1
+AS_SHELL_SANITIZE
+_AS_PREPARE
+exec AS_MESSAGE_FD>&1
+_ASEOF
+test $lt_write_fail = 0 && chmod +x $1[]dnl
+m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+[# Run this file to recreate a libtool stub with the current configuration.])
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+lt_cl_silent=false
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+  echo
+  AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+\`$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+  -h, --help      print this help, then exit
+  -V, --version   print version number, then exit
+  -q, --quiet     do not print progress messages
+  -d, --debug     don't remove temporary files
+
+Report bugs to <bug-libtool@gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test $[#] != 0
+do
+  case $[1] in
+    --version | --v* | -V )
+      echo "$lt_cl_version"; exit 0 ;;
+    --help | --h* | -h )
+      echo "$lt_cl_help"; exit 0 ;;
+    --debug | --d* | -d )
+      debug=: ;;
+    --quiet | --q* | --silent | --s* | -q )
+      lt_cl_silent=: ;;
+
+    -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try \`$[0] --help' for more information.]) ;;
+
+    *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try \`$[0] --help' for more information.]) ;;
+  esac
+  shift
+done
+
+if $lt_cl_silent; then
+  exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure.  Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+lt_cl_success=:
+test "$silent" = yes &&
+  lt_config_lt_args="$lt_config_lt_args --quiet"
+exec AS_MESSAGE_LOG_FD>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec AS_MESSAGE_LOG_FD>>config.log
+$lt_cl_success || AS_EXIT(1)
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars.  Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+  m4_if(_LT_TAG, [C], [
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+  _LT_PROG_LTMAIN
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  _LT_PROG_XSI_SHELLFNS
+
+  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+  [C],			[_LT_LANG(C)],
+  [C++],		[_LT_LANG(CXX)],
+  [Go],			[_LT_LANG(GO)],
+  [Java],		[_LT_LANG(GCJ)],
+  [Fortran 77],		[_LT_LANG(F77)],
+  [Fortran],		[_LT_LANG(FC)],
+  [Windows Resource],	[_LT_LANG(RC)],
+  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+    [_LT_LANG($1)],
+    [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+  [LT_SUPPORTED_TAG([$1])dnl
+  m4_append([_LT_TAGS], [$1 ])dnl
+  m4_define([_LT_LANG_]$1[_enabled], [])dnl
+  _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+  [LT_LANG(CXX)],
+  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+  [LT_LANG(F77)],
+  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+  [LT_LANG(FC)],
+  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+  [LT_LANG(GCJ)],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+    [LT_LANG(GCJ)],
+    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+      [LT_LANG(GCJ)],
+      [m4_ifdef([AC_PROG_GCJ],
+	[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([A][M_PROG_GCJ],
+	[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([LT_PROG_GCJ],
+	[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([AC_PROG_GO],
+  [LT_LANG(GO)],
+  [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+  [LT_LANG(RC)],
+  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+  case $host_os in
+    rhapsody* | darwin*)
+    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+    AC_CHECK_TOOL([LIPO], [lipo], [:])
+    AC_CHECK_TOOL([OTOOL], [otool], [:])
+    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+    _LT_DECL([], [DSYMUTIL], [1],
+      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+    _LT_DECL([], [NMEDIT], [1],
+      [Tool to change global to local symbols on Mac OS X])
+    _LT_DECL([], [LIPO], [1],
+      [Tool to manipulate fat objects and archives on Mac OS X])
+    _LT_DECL([], [OTOOL], [1],
+      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+    _LT_DECL([], [OTOOL64], [1],
+      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+      [lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&AS_MESSAGE_LOG_FD
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi])
+    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+      [lt_cv_ld_exported_symbols_list],
+      [lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+	[lt_cv_ld_exported_symbols_list=yes],
+	[lt_cv_ld_exported_symbols_list=no])
+	LDFLAGS="$save_LDFLAGS"
+    ])
+    AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+      [lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+      echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+      $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then
+	lt_cv_ld_force_load=yes
+      else
+	cat conftest.err >&AS_MESSAGE_LOG_FD
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+    ])
+    case $host_os in
+    rhapsody* | darwin1.[[012]])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+	10.[[012]][[,.]]*)
+	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+	10.*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES
+# --------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_automatic, $1)=yes
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+  else
+    _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+  fi
+  _LT_TAGVAR(link_all_deplibs, $1)=yes
+  _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+    m4_if([$1], [CXX],
+[   if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+      _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+    fi
+],[])
+  else
+  _LT_TAGVAR(ld_shlibs, $1)=no
+  fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX
+# -----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[m4_divert_text([M4SH-INIT], [$1
+])])# _LT_SHELL_INIT
+
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Find how we can fake an echo command that does not interpret backslash.
+# In particular, with Autoconf 2.60 or later we add some code to the start
+# of the generated configure script which will find a shell with a builtin
+# printf (which we can use as an echo command).
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+AC_MSG_CHECKING([how to print strings])
+# Test print first, because it will be a builtin if present.
+if test "X`print -r -- -n 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$[]1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*" 
+}
+
+case "$ECHO" in
+  printf*) AC_MSG_RESULT([printf]) ;;
+  print*) AC_MSG_RESULT([print -r]) ;;
+  *) AC_MSG_RESULT([cat]) ;;
+esac
+
+m4_ifdef([_AS_DETECT_SUGGESTED],
+[_AS_DETECT_SUGGESTED([
+  test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test "X`printf %s $ECHO`" = "X$ECHO" \
+      || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
+
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+  [AS_HELP_STRING([--disable-libtool-lock],
+    [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE="32"
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE="64"
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    case `/usr/bin/file conftest.o` in
+	      *x86-64*)
+		LD="${LD-ld} -m elf32_x86_64"
+		;;
+	      *)
+		LD="${LD-ld} -m elf_i386"
+		;;
+	    esac
+	    ;;
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+])# _LT_ENABLE_LOCK
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[AC_CHECK_TOOL(AR, ar, false)
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1])
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+    [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+    [Commands used to build an old-style archive])
+_LT_DECL([], [lock_old_archive_extraction], [0],
+    [Whether to use a lock for old archive extraction])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#		[OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       $2=yes
+     fi
+   fi
+   $RM conftest*
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$5], , :, [$5])
+else
+    m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                  [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $3"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         $2=yes
+       fi
+     else
+       $2=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$4], , :, [$4])
+else
+    m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[	 ]]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \
+	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+    [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+void fnord () __attribute__((visibility("default")));
+#endif
+
+void fnord () { int i=42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}]
+_LT_EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_dlunknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+    ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+	  [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+	    [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
+	[AC_CHECK_FUNC([dlopen],
+	      [lt_cv_dlopen="dlopen"],
+	  [AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+	    [AC_CHECK_LIB([svld], [dlopen],
+		  [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+	      [AC_CHECK_LIB([dld], [dld_link],
+		    [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
+	      ])
+	    ])
+	  ])
+	])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+	  lt_cv_dlopen_self, [dnl
+	  _LT_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+	    lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+	  lt_cv_dlopen_self_static, [dnl
+	  _LT_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+	    lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+	 [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+	 [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+	 [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+	[Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links="nottested"
+if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+         [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
+  [Define to the sub-directory in which libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+   test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+     test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
+   test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+    [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      AC_MSG_RESULT([yes])
+    else
+      AC_MSG_RESULT([no])
+    fi
+    ;;
+  *)
+    AC_MSG_RESULT([no])
+    ;;
+  esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+	[], [
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([[A-Za-z]]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[[4-9]]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[[45]]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+m4_if([$1], [],[
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[23]].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+haiku*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[[3-9]]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+    [lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+	 LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+      [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+	 [lt_cv_shlibpath_overrides_runpath=yes])])
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+    ])
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[[89]] | openbsd2.[[89]].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+    [Variables whose values should be saved in libtool wrapper scripts and
+    restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+    [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+    [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+    [[List of archive names.  First name is the real one, the rest are links.
+    The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+    [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [install_override_mode], [1],
+    [Permission mode override for installation of shared libraries])
+_LT_DECL([], [postinstall_cmds], [2],
+    [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+    [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+    [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+    [[As "finish_cmds", except a single script fragment to be evaled but
+    not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+    [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+    [Compile-time system search path for libraries])
+_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
+    [Run-time system search path for libraries])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program which can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="m4_if([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+	 [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program which can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
+
+AC_ARG_WITH([gnu-ld],
+    [AS_HELP_STRING([--with-gnu-ld],
+	[assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_TAGDECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[[3-9]]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+    [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+    [Command to use when deplibs_check_method == "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+	*/dev/null* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi])
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+  AC_SUBST([DUMPBIN])
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+  [lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
+  cat conftest.out >&AS_MESSAGE_LOG_FD
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+  case $cc_basename in
+  nvcc*)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+  esac
+
+  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+	[Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris*)
+  symcode='[[BDRT]]'
+  ;;
+sco3.2v5*)
+  symcode='[[DT]]'
+  ;;
+sysv4.2uw2*)
+  symcode='[[DT]]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[[ABDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK ['"\
+"     {last_section=section; section=\$ 3};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx]"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+const struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_save_LIBS="$LIBS"
+	  lt_save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+	  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$lt_save_LIBS"
+	  CFLAGS="$lt_save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+    [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+    [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_c_name_address],
+    [lt_cv_sys_global_symbol_to_c_name_address], [1],
+    [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+    [Transform the output of nm in a C name address pair when lib prefix is needed])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+m4_if([$1], [CXX], [
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+    *qnx* | *nto*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix[[4-9]]*)
+	# All AIX code is PIC.
+	if test "$host_cpu" = ia64; then
+	  # AIX 5 now supports IA64 processor
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	else
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+	fi
+	;;
+      chorus*)
+	case $cc_basename in
+	cxch68*)
+	  # Green Hills C++ Compiler
+	  # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+	  ;;
+	esac
+	;;
+      dgux*)
+	case $cc_basename in
+	  ec++*)
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  ghcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      freebsd* | dragonfly*)
+	# FreeBSD uses GNU C++
+	;;
+      hpux9* | hpux10* | hpux11*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+	    if test "$host_cpu" != ia64; then
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	    fi
+	    ;;
+	  aCC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+	    case $host_cpu in
+	    hppa*64*|ia64*)
+	      # +Z the default
+	      ;;
+	    *)
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	      ;;
+	    esac
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      interix*)
+	# This is c89, which is MS Visual C++ (no shared libs)
+	# Anyone wants to do a port?
+	;;
+      irix5* | irix6* | nonstopux*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    # CC pic flag -KPIC is the default.
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      linux* | k*bsd*-gnu | kopensolaris*-gnu)
+	case $cc_basename in
+	  KCC*)
+	    # KAI C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    ;;
+	  ecpc* )
+	    # old Intel C++ for x86_64 which still supported -KPIC.
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	    ;;
+	  icpc* )
+	    # Intel C++, used to be incompatible with GCC.
+	    # ICC 10 doesn't accept -KPIC any more.
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	    ;;
+	  pgCC* | pgcpp*)
+	    # Portland Group C++ compiler
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  cxx*)
+	    # Compaq C++
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+	    # IBM XL 8.0, 9.0 on PPC and BlueGene
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+      lynxos*)
+	;;
+      m88k*)
+	;;
+      mvs*)
+	case $cc_basename in
+	  cxx*)
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      netbsd*)
+	;;
+      *qnx* | *nto*)
+        # QNX uses GNU C++, but need to define -shared option too, otherwise
+        # it will coredump.
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+        ;;
+      osf3* | osf4* | osf5*)
+	case $cc_basename in
+	  KCC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    ;;
+	  RCC*)
+	    # Rational C++ 2.4.1
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  cxx*)
+	    # Digital/Compaq C++
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      psos*)
+	;;
+      solaris*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	    ;;
+	  gcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sunos4*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.x
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  lcc*)
+	    # Lucid
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	esac
+	;;
+      tandem*)
+	case $cc_basename in
+	  NCC*)
+	    # NonStop-UX NCC 3.20
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      vxworks*)
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+	;;
+    esac
+  fi
+],
+[
+  if test "$GCC" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      ccc*)
+        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ F* | *Sun*Fortran*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+	  ;;
+	*Sun\ C*)
+	  # Sun C 5.9
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    rdos*)
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    unicos*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+	[How to pass a linker flag through the compiler])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+	[Additional compiler flags for building library objects])
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+  $lt_tmp_static_flag,
+  [],
+  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+	[Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  case $host_os in
+  aix[[4-9]]*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    # Also, AIX nm treats weak defined symbols like other global defined
+    # symbols, whereas GNU nm marks them as "W".
+    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+  ;;
+  cygwin* | mingw* | cegcc*)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  *)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  esac
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+], [
+  runpath_var=
+  _LT_TAGVAR(allow_undefined_flag, $1)=
+  _LT_TAGVAR(always_export_symbols, $1)=no
+  _LT_TAGVAR(archive_cmds, $1)=
+  _LT_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_TAGVAR(compiler_needs_object, $1)=no
+  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(hardcode_automatic, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(inherit_rpath, $1)=no
+  _LT_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_TAGVAR(module_cmds, $1)=
+  _LT_TAGVAR(module_expsym_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  _LT_TAGVAR(ld_shlibs, $1)=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+	  *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[[3-9]]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=no
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	_LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    haiku*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    interix[[3-9]]*)
+      _LT_TAGVAR(hardcode_direct, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+	  tmp_sharedflag='--shared' ;;
+	xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  _LT_TAGVAR(compiler_needs_object, $1)=yes
+	  ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  _LT_TAGVAR(compiler_needs_object, $1)=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf* | bgf* | bgxlf* | mpixlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+	  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
+      runpath_var=
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	_LT_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix[[4-9]]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	# Also, AIX nm treats weak defined symbols like other global
+	# defined symbols, whereas GNU nm marks them as "W".
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_TAGVAR(archive_cmds, $1)=''
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[[012]]|aix4.[[012]].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  _LT_TAGVAR(hardcode_direct, $1)=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+	  _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 _LT_SYS_MODULE_PATH_AIX
+	 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+	  _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+	  if test "$with_gnu_ld" = yes; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	  fi
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[[45]]*)
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+      # FIXME: Should let the user specify the lib program.
+      _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      ;;
+
+    darwin* | rhapsody*)
+      _LT_DARWIN_LINKER_FEATURES($1)
+      ;;
+
+    dgux*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+	_LT_TAGVAR(hardcode_direct, $1)=yes
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	_LT_TAGVAR(hardcode_minus_L, $1)=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	m4_if($1, [], [
+	  # Older versions of the 11.00 compiler do not understand -b yet
+	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+	  _LT_LINKER_OPTION([if $CC understands -b],
+	    _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+	    [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
+	    [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
+	  [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  _LT_TAGVAR(hardcode_direct, $1)=no
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  ;;
+	*)
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+        save_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+        AC_LINK_IFELSE(int foo(void) {},
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+        )
+        LDFLAGS="$save_LDFLAGS"
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(inherit_rpath, $1)=yes
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	_LT_TAGVAR(hardcode_direct, $1)=yes
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+	     _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	     ;;
+	   *)
+	     _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    os2*)
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      else
+	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+	  _LT_TAGVAR(hardcode_direct, $1)=no
+        ;;
+	motorola)
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	_LT_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+    [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $_LT_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+	[lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+	[$RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+	  pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+	  _LT_TAGVAR(allow_undefined_flag, $1)=
+	  if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+	  then
+	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	  else
+	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	  fi
+	  _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+	])
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+    [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+    [enable_shared_with_static_runtimes], [0],
+    [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+    [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+    [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+    [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+    [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+    [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+    [Commands used to build a loadable module if different from building
+    a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+    [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+    [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+    [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+    [Flag to hardcode $libdir into a binary during linking.
+    This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1],
+    [[If ld is used when linking, flag to hardcode $libdir into a binary
+    during linking.  This must work even if $libdir does not exist]])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+    [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary and the resulting library dependency is
+    "absolute", i.e impossible to change by setting ${shlibpath_var} if the
+    library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+    [Set to "yes" if building a shared library automatically hardcodes DIR
+    into the library and all subsequent libraries and executables linked
+    against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+    [Set to yes if linker adds runtime paths of dependent libraries
+    to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+    [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [fix_srcfile_path], [1],
+    [Fix the shell variable $srcfile for the compiler])
+_LT_TAGDECL([], [always_export_symbols], [0],
+    [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+    [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+    [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+    [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+    [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [file_list_spec], [1],
+    [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl    [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_SYS_DYNAMIC_LINKER($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+  LT_SYS_DLOPEN_SELF
+  _LT_CMD_STRIPLIB
+
+  # Report which library types will actually be built
+  AC_MSG_CHECKING([if libtool supports shared libraries])
+  AC_MSG_RESULT([$can_build_shared])
+
+  AC_MSG_CHECKING([whether to build shared libraries])
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[[4-9]]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  AC_MSG_RESULT([$enable_shared])
+
+  AC_MSG_CHECKING([whether to build static libraries])
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  AC_MSG_RESULT([$enable_static])
+
+  _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC="$lt_save_CC"
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  AC_PROG_CXXCPP
+else
+  _lt_caught_CXX_error=yes
+fi
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="int some_variable = 0;"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_LD=$LD
+  lt_save_GCC=$GCC
+  GCC=$GXX
+  lt_save_with_gnu_ld=$with_gnu_ld
+  lt_save_path_LD=$lt_cv_path_LD
+  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+  else
+    $as_unset lt_cv_prog_gnu_ld
+  fi
+  if test -n "${lt_cv_path_LDCXX+set}"; then
+    lt_cv_path_LD=$lt_cv_path_LDCXX
+  else
+    $as_unset lt_cv_path_LD
+  fi
+  test -z "${LDCXX+set}" || LD=$LDCXX
+  CC=${CXX-"c++"}
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    # We don't want -fno-exception when compiling C++ code, so set the
+    # no_builtin_flag separately
+    if test "$GXX" = yes; then
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+    else
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+    fi
+
+    if test "$GXX" = yes; then
+      # Set up default GNU C++ configuration
+
+      LT_PATH_LD
+
+      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+      # archiving commands below assume that GNU ld is being used.
+      if test "$with_gnu_ld" = yes; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+        # If archive_cmds runs LD, not CC, wlarc should be empty
+        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+        #     investigate it a little bit more. (MM)
+        wlarc='${wl}'
+
+        # ancient GNU ld didn't support --whole-archive et. al.
+        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+	  $GREP 'no-whole-archive' > /dev/null; then
+          _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+        else
+          _LT_TAGVAR(whole_archive_flag_spec, $1)=
+        fi
+      else
+        with_gnu_ld=no
+        wlarc=
+
+        # A generic and very simple default shared library creation
+        # command for GNU C++ for the case where it uses the native
+        # linker, instead of GNU ld.  If possible, this setting should
+        # overridden to take advantage of the native linker features on
+        # the platform it is being used on.
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      fi
+
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+    else
+      GXX=no
+      with_gnu_ld=no
+      wlarc=
+    fi
+
+    # PORTME: fill in a description of your system's C++ link characteristics
+    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+    _LT_TAGVAR(ld_shlibs, $1)=yes
+    case $host_os in
+      aix3*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+      aix[[4-9]]*)
+        if test "$host_cpu" = ia64; then
+          # On IA64, the linker does run time linking by default, so we don't
+          # have to do anything special.
+          aix_use_runtimelinking=no
+          exp_sym_flag='-Bexport'
+          no_entry_flag=""
+        else
+          aix_use_runtimelinking=no
+
+          # Test if we are trying to use run time linking or normal
+          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+          # need to do runtime linking.
+          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+	    for ld_flag in $LDFLAGS; do
+	      case $ld_flag in
+	      *-brtl*)
+	        aix_use_runtimelinking=yes
+	        break
+	        ;;
+	      esac
+	    done
+	    ;;
+          esac
+
+          exp_sym_flag='-bexport'
+          no_entry_flag='-bnoentry'
+        fi
+
+        # When large executables or shared objects are built, AIX ld can
+        # have problems creating the table of contents.  If linking a library
+        # or program results in "error TOC overflow" add -mminimal-toc to
+        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+        _LT_TAGVAR(archive_cmds, $1)=''
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+        if test "$GXX" = yes; then
+          case $host_os in aix4.[[012]]|aix4.[[012]].*)
+          # We only want to do this on AIX 4.2 and lower, the check
+          # below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	    # We have reworked collect2
+	    :
+	  else
+	    # We have old collect2
+	    _LT_TAGVAR(hardcode_direct, $1)=unsupported
+	    # It fails to find uninstalled libraries when the uninstalled
+	    # path is not listed in the libpath.  Setting hardcode_minus_L
+	    # to unsupported forces relinking
+	    _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
+          esac
+          shared_flag='-shared'
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag="$shared_flag "'${wl}-G'
+	  fi
+        else
+          # not using gcc
+          if test "$host_cpu" = ia64; then
+	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	  # chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+          else
+	    if test "$aix_use_runtimelinking" = yes; then
+	      shared_flag='${wl}-G'
+	    else
+	      shared_flag='${wl}-bM:SRE'
+	    fi
+          fi
+        fi
+
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+        # It seems that -bexpall does not export symbols beginning with
+        # underscore (_), so it is better to generate a list of symbols to
+	# export.
+        _LT_TAGVAR(always_export_symbols, $1)=yes
+        if test "$aix_use_runtimelinking" = yes; then
+          # Warning - without using the other runtime loading flags (-brtl),
+          # -berok will link without error, but may produce a broken library.
+          _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+          # Determine the default libpath from the value encoded in an empty
+          # executable.
+          _LT_SYS_MODULE_PATH_AIX
+          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+        else
+          if test "$host_cpu" = ia64; then
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+	    _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+          else
+	    # Determine the default libpath from the value encoded in an
+	    # empty executable.
+	    _LT_SYS_MODULE_PATH_AIX
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	    # Warning - without using the other run time loading flags,
+	    # -berok will link without error, but may produce a broken library.
+	    _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+	    _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+	    if test "$with_gnu_ld" = yes; then
+	      # We only use this code for GNU lds that support --whole-archive.
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	    else
+	      # Exported symbols can be pulled into shared objects from archives
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	    fi
+	    _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	    # This is similar to how AIX traditionally builds its shared
+	    # libraries.
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+          fi
+        fi
+        ;;
+
+      beos*)
+	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	  # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	  # support --undefined.  This deserves some investigation.  FIXME
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	else
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+
+      chorus*)
+        case $cc_basename in
+          *)
+	  # FIXME: insert proper C++ library support
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	  ;;
+        esac
+        ;;
+
+      cygwin* | mingw* | pw32* | cegcc*)
+        # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+        # as there is no search path for DLLs.
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
+        _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+        _LT_TAGVAR(always_export_symbols, $1)=no
+        _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+        if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+          # If the export-symbols file already is a .def file (1st line
+          # is EXPORTS), use it as is; otherwise, prepend...
+          _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	    cp $export_symbols $output_objdir/$soname.def;
+          else
+	    echo EXPORTS > $output_objdir/$soname.def;
+	    cat $export_symbols >> $output_objdir/$soname.def;
+          fi~
+          $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+        else
+          _LT_TAGVAR(ld_shlibs, $1)=no
+        fi
+        ;;
+      darwin* | rhapsody*)
+        _LT_DARWIN_LINKER_FEATURES($1)
+	;;
+
+      dgux*)
+        case $cc_basename in
+          ec++*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          ghcx*)
+	    # Green Hills C++ Compiler
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      freebsd2.*)
+        # C++ shared libraries reported to be fairly broken before
+	# switch to ELF
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      freebsd-elf*)
+        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        ;;
+
+      freebsd* | dragonfly*)
+        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+        # conventions
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+        ;;
+
+      gnu*)
+        ;;
+
+      haiku*)
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        ;;
+
+      hpux9*)
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+				             # but as the default
+				             # location of the library.
+
+        case $cc_basename in
+          CC*)
+            # FIXME: insert proper C++ library support
+            _LT_TAGVAR(ld_shlibs, $1)=no
+            ;;
+          aCC*)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            # Commands to make compiler produce verbose output that lists
+            # what "hidden" libraries, object files and flags are used when
+            # linking a shared library.
+            #
+            # There doesn't appear to be a way to prevent this compiler from
+            # explicitly linking system object files so we need to strip them
+            # from the output so that they don't get included in the library
+            # dependencies.
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+            ;;
+          *)
+            if test "$GXX" = yes; then
+              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            else
+              # FIXME: insert proper C++ library support
+              _LT_TAGVAR(ld_shlibs, $1)=no
+            fi
+            ;;
+        esac
+        ;;
+
+      hpux10*|hpux11*)
+        if test $with_gnu_ld = no; then
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	  _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+          case $host_cpu in
+            hppa*64*|ia64*)
+              ;;
+            *)
+	      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+              ;;
+          esac
+        fi
+        case $host_cpu in
+          hppa*64*|ia64*)
+            _LT_TAGVAR(hardcode_direct, $1)=no
+            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+            ;;
+          *)
+            _LT_TAGVAR(hardcode_direct, $1)=yes
+            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+					         # but as the default
+					         # location of the library.
+            ;;
+        esac
+
+        case $cc_basename in
+          CC*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          aCC*)
+	    case $host_cpu in
+	      hppa*64*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      ia64*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      *)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	    esac
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+	    ;;
+          *)
+	    if test "$GXX" = yes; then
+	      if test $with_gnu_ld = no; then
+	        case $host_cpu in
+	          hppa*64*)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          ia64*)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          *)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	        esac
+	      fi
+	    else
+	      # FIXME: insert proper C++ library support
+	      _LT_TAGVAR(ld_shlibs, $1)=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      interix[[3-9]]*)
+	_LT_TAGVAR(hardcode_direct, $1)=no
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+	# Instead, shared libraries are loaded at an image base (0x10000000 by
+	# default) and relocated if they conflict, which is a slow very memory
+	# consuming and fragmenting process.  To avoid this, we pick a random,
+	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	;;
+      irix5* | irix6*)
+        case $cc_basename in
+          CC*)
+	    # SGI C++
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    if test "$GXX" = yes; then
+	      if test "$with_gnu_ld" = no; then
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	      else
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
+	      fi
+	    fi
+	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+	    ;;
+        esac
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(inherit_rpath, $1)=yes
+        ;;
+
+      linux* | k*bsd*-gnu | kopensolaris*-gnu)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+	    ;;
+	  icpc* | ecpc* )
+	    # Intel C++
+	    with_gnu_ld=yes
+	    # version 8.0 and above of icpc choke on multiply defined symbols
+	    # if we add $predep_objects and $postdep_objects, however 7.1 and
+	    # earlier do not add the objects themselves.
+	    case `$CC -V 2>&1` in
+	      *"Version 7."*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	      *)  # Version 8.0 or newer
+	        tmp_idyn=
+	        case $host_cpu in
+		  ia64*) tmp_idyn=' -i_dynamic';;
+		esac
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	    esac
+	    _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	    ;;
+          pgCC* | pgcpp*)
+            # Portland Group C++ compiler
+	    case `$CC -V` in
+	    *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
+	      _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+		compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+	      _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+		$RANLIB $oldlib'
+	      _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+	      ;;
+	    *) # Version 6 and above use weak symbols
+	      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+	      ;;
+	    esac
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+            ;;
+	  cxx*)
+	    # Compaq C++
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+	    runpath_var=LD_RUN_PATH
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+	    ;;
+	  xl* | mpixl* | bgxl*)
+	    # IBM XL 8.0 on PPC, with GNU ld
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    if test "x$supports_anon_versioning" = xyes; then
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+		cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+		echo "local: *; };" >> $output_objdir/$libname.ver~
+		$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+	    fi
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	      _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	      _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+	      # Not sure whether something based on
+	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+	      # would be better.
+	      output_verbose_link_cmd='func_echo_all'
+
+	      # Archives containing C++ object files must be created using
+	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	      # necessary to make sure instantiated templates are included
+	      # in the archive.
+	      _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+
+      lynxos*)
+        # FIXME: insert proper C++ library support
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      m88k*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      mvs*)
+        case $cc_basename in
+          cxx*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+	  *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+	esac
+	;;
+
+      netbsd*)
+        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+	  wlarc=
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	fi
+	# Workaround some broken pre-1.5 toolchains
+	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+	;;
+
+      *nto* | *qnx*)
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+	;;
+
+      openbsd2*)
+        # C++ shared libraries are fairly broken
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      openbsd*)
+	if test -f /usr/libexec/ld.so; then
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+	  fi
+	  output_verbose_link_cmd=func_echo_all
+	else
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+
+      osf3* | osf4* | osf5*)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Archives containing C++ object files must be created using
+	    # the KAI C++ compiler.
+	    case $host in
+	      osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+	      *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+	    esac
+	    ;;
+          RCC*)
+	    # Rational C++ 2.4.1
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          cxx*)
+	    case $host in
+	      osf3*)
+	        _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+		;;
+	      *)
+	        _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+	          echo "-hidden">> $lib.exp~
+	          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
+	          $RM $lib.exp'
+	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+		;;
+	    esac
+
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+	    ;;
+	  *)
+	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	      _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	      case $host in
+	        osf3*)
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+		  ;;
+	        *)
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+		  ;;
+	      esac
+
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	      # Commands to make compiler produce verbose output that lists
+	      # what "hidden" libraries, object files and flags are used when
+	      # linking a shared library.
+	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+	    else
+	      # FIXME: insert proper C++ library support
+	      _LT_TAGVAR(ld_shlibs, $1)=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      psos*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      sunos4*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.x
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          lcc*)
+	    # Lucid
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      solaris*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+	    _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	      $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	    _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	    case $host_os in
+	      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+	      *)
+		# The compiler driver will combine and reorder linker options,
+		# but understands `-z linker_flag'.
+	        # Supported since Solaris 2.6 (maybe 2.5.1?)
+		_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+	        ;;
+	    esac
+	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+	    output_verbose_link_cmd='func_echo_all'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	    ;;
+          gcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+	    # The C++ compiler must be used to create the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    # GNU C++ compiler with Solaris linker
+	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	      _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+		  $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+	      else
+	        # g++ 2.7 appears to require `-G' NOT `-shared' on this
+	        # platform.
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+		  $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+	      fi
+
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+	      case $host_os in
+		solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+		*)
+		  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+		  ;;
+	      esac
+	    fi
+	    ;;
+        esac
+        ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      case $cc_basename in
+        CC*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+      esac
+      ;;
+
+      sysv5* | sco3.2v5* | sco5v6*)
+	# Note: We can NOT use -z defs as we might desire, because we do not
+	# link with -lc, and that would cause any symbols used from libc to
+	# always be unresolved, which means just about no library would
+	# ever link correctly.  If we're not using GNU ld we use -z text
+	# though, which does catch some bad symbols but isn't as heavy-handed
+	# as -z defs.
+	_LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+	_LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+	_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+	_LT_TAGVAR(link_all_deplibs, $1)=yes
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+	runpath_var='LD_RUN_PATH'
+
+	case $cc_basename in
+          CC*)
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+	      '"$_LT_TAGVAR(old_archive_cmds, $1)"
+	    _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+	      '"$_LT_TAGVAR(reload_cmds, $1)"
+	    ;;
+	  *)
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    ;;
+	esac
+      ;;
+
+      tandem*)
+        case $cc_basename in
+          NCC*)
+	    # NonStop-UX NCC 3.20
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      vxworks*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      *)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+    esac
+
+    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+    test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+    _LT_TAGVAR(GCC, $1)="$GXX"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  CC=$lt_save_CC
+  LDCXX=$LD
+  LD=$lt_save_LD
+  GCC=$lt_save_GCC
+  with_gnu_ld=$lt_save_with_gnu_ld
+  lt_cv_path_LDCXX=$lt_cv_path_LD
+  lt_cv_path_LD=$lt_save_path_LD
+  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+_LT_EOF
+], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
+package foo
+func foo() { }
+_LT_EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  for p in `eval "$output_verbose_link_cmd"`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" ||
+          test $p = "-R"; then
+	 prev=$p
+	 continue
+       else
+	 prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 case $p in
+	 -L* | -R*)
+	   # Internal compiler library paths should come after those
+	   # provided the user.  The postdeps already come after the
+	   # user supplied libs so there is no need to process them.
+	   if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+	     _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+	   else
+	     _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+	   fi
+	   ;;
+	 # The "-l" case would never come before the object being
+	 # linked, so don't bother handling this case.
+	 esac
+       else
+	 if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+	   _LT_TAGVAR(postdeps, $1)="${prev}${p}"
+	 else
+	   _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
+	 fi
+       fi
+       ;;
+
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+	 pre_test_object_deps_done=yes
+	 continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+	   _LT_TAGVAR(predep_objects, $1)="$p"
+	 else
+	   _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+	 fi
+       else
+	 if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+	   _LT_TAGVAR(postdep_objects, $1)="$p"
+	 else
+	   _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+	 fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  _LT_TAGVAR(predep_objects,$1)=
+  _LT_TAGVAR(postdep_objects,$1)=
+  _LT_TAGVAR(postdeps,$1)=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+    [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+    [Dependencies to place before and after the objects being linked to
+    create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+    [The library search path used internally by the compiler when linking
+    a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_LANG_PUSH(Fortran 77)
+if test -z "$F77" || test "X$F77" = "Xno"; then
+  _lt_disable_F77=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_F77" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  CC=${F77-"f77"}
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+  GCC=$G77
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+	if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+	  test "$enable_shared" = yes && enable_static=no
+	fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$G77"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC="$lt_save_CC"
+fi # test "$_lt_disable_F77" != yes
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_LANG_PUSH(Fortran)
+
+if test -z "$FC" || test "X$FC" = "Xno"; then
+  _lt_disable_FC=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_FC" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  CC=${FC-"f95"}
+  compiler=$CC
+  GCC=$ac_cv_fc_compiler_gnu
+
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+	if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+	  test "$enable_shared" = yes && enable_static=no
+	fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC="$lt_save_CC"
+fi # test "$_lt_disable_FC" != yes
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC="$lt_save_CC"
+])# _LT_LANG_GCJ_CONFIG
+
+# _LT_LANG_GO_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Go compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GO_CONFIG],
+[AC_REQUIRE([LT_PROG_GO])dnl
+AC_LANG_SAVE
+
+# Source file extension for Go test sources.
+ac_ext=go
+
+# Object file extension for compiled Go test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="package main; func main() { }"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='package main; func main() { }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC="$GCC"
+GCC=yes
+CC=${GOC-"gccgo"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# Go did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC="$lt_save_CC"
+])# _LT_LANG_GO_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+  :
+  _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+    [AC_CHECK_TOOL(GCJ, gcj,)
+      test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+      AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+# LT_PROG_GO
+# -----------
+AC_DEFUN([LT_PROG_GO],
+[AC_CHECK_TOOL(GOC, gccgo,)
+])
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+############################################################
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+AC_MSG_RESULT([$xsi_shell])
+_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
+
+AC_MSG_CHECKING([whether the shell understands "+="])
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+AC_MSG_RESULT([$lt_shell_append])
+_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PROG_XSI_SHELLFNS
+# ---------------------
+# Bourne and XSI compatible variants of some useful shell functions.
+m4_defun([_LT_PROG_XSI_SHELLFNS],
+[case $xsi_shell in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+  func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+  # positional parameters, so assign one to ordinary parameter first.
+  func_stripname_result=${3}
+  func_stripname_result=${func_stripname_result#"${1}"}
+  func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=${1%%=*}
+  func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  case ${1} in
+    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+    *)    func_lo2o_result=${1} ;;
+  esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=$(( $[*] ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=${#1}
+}
+
+_LT_EOF
+    ;;
+  *) # Bourne compatible functions.
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result=`$ECHO "${1}" | $SED "$basename"`
+}
+
+dnl func_dirname_and_basename
+dnl A portable version of this function is already defined in general.m4sh
+dnl so there is no need for it here.
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+  case ${2} in
+    .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+    *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+  esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[[^=]]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=`$ECHO "${1}" | $SED "$my_sed_long_opt"`
+  func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=`$ECHO "${1}" | $SED 's/\.[[^.]]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=`expr "$[@]"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$[1]+=\$[2]"
+}
+_LT_EOF
+    ;;
+  *)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$[1]=\$$[1]\$[2]"
+}
+
+_LT_EOF
+    ;;
+  esac
+])
diff --git a/third_party/gofrontend/libgo/config/ltmain.sh b/third_party/gofrontend/libgo/config/ltmain.sh
new file mode 100644
index 0000000..ce66b44
--- /dev/null
+++ b/third_party/gofrontend/libgo/config/ltmain.sh
@@ -0,0 +1,8636 @@
+# Generated from ltmain.m4sh.
+
+# libtool (GNU libtool 1.3134 2009-11-29) 2.2.7a
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
+# 2007, 2008, 2009 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname [OPTION]... [MODE-ARG]...
+#
+# Provide generalized library-building support services.
+#
+#       --config             show all configuration variables
+#       --debug              enable verbose shell tracing
+#   -n, --dry-run            display commands without modifying any files
+#       --features           display basic configuration information and exit
+#       --mode=MODE          use operation mode MODE
+#       --no-finish          let install mode avoid finish commands
+#       --preserve-dup-deps  don't remove duplicate dependency libraries
+#       --quiet, --silent    don't print informational messages
+#       --no-quiet, --no-silent
+#                            print informational messages (default)
+#       --tag=TAG            use configuration variables from tag TAG
+#   -v, --verbose            print more informational messages than default
+#       --no-verbose         don't print the extra informational messages
+#       --version            print version information
+#   -h, --help, --help-all   print short, long, or detailed help message
+#
+# MODE must be one of the following:
+#
+#         clean              remove files from the build directory
+#         compile            compile a source file into a libtool object
+#         execute            automatically set library path, then run a program
+#         finish             complete the installation of libtool libraries
+#         install            install libraries or executables
+#         link               create a library or an executable
+#         uninstall          remove libraries from an installed directory
+#
+# MODE-ARGS vary depending on the MODE.  When passed as first option,
+# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that.
+# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
+#
+# When reporting a bug, please describe a test case to reproduce it and
+# include the following information:
+#
+#         host-triplet:	$host
+#         shell:		$SHELL
+#         compiler:		$LTCC
+#         compiler flags:		$LTCFLAGS
+#         linker:		$LD (gnu? $with_gnu_ld)
+#         $progname:	(GNU libtool 1.3134 2009-11-29) 2.2.7a
+#         automake:	$automake_version
+#         autoconf:	$autoconf_version
+#
+# Report bugs to <bug-libtool@gnu.org>.
+
+PROGRAM=libtool
+PACKAGE=libtool
+VERSION=2.2.7a
+TIMESTAMP=" 1.3134 2009-11-29"
+package_revision=1.3134
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# NLS nuisances: We save the old values to restore during execute mode.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+lt_user_locale=
+lt_safe_locale=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+          save_$lt_var=\$$lt_var
+          $lt_var=C
+	  export $lt_var
+	  lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
+	  lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
+	fi"
+done
+
+$lt_unset CDPATH
+
+
+
+
+
+
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+
+
+: ${CP="cp -f"}
+: ${ECHO=$as_echo}
+: ${EGREP="/bin/grep -E"}
+: ${FGREP="/bin/grep -F"}
+: ${GREP="/bin/grep"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SED="/mount/endor/wildenhu/local-x86_64/bin/sed"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+: ${Xsed="$SED -e 1s/^X//"}
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77	  # $? = 77 is used to indicate a skipped test to automake.
+
+exit_status=$EXIT_SUCCESS
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" 	$lt_nl"
+
+dirname="s,/[^/]*$,,"
+basename="s,^.*/,,"
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+  func_basename_result=`$ECHO "${1}" | $SED -e "$basename"`
+}
+
+# Generated shell functions inserted here.
+
+# These SED scripts presuppose an absolute path with a trailing slash.
+pathcar='s,^/\([^/]*\).*$,\1,'
+pathcdr='s,^/[^/]*,,'
+removedotparts=':dotsl
+		s@/\./@/@g
+		t dotsl
+		s,/\.$,/,'
+collapseslashes='s@/\{1,\}@/@g'
+finalslash='s,/*$,/,'
+
+# func_normal_abspath PATH
+# Remove doubled-up and trailing slashes, "." path components,
+# and cancel out any ".." path components in PATH after making
+# it an absolute path.
+#             value returned in "$func_normal_abspath_result"
+func_normal_abspath ()
+{
+  # Start from root dir and reassemble the path.
+  func_normal_abspath_result=
+  func_normal_abspath_tpath=$1
+  func_normal_abspath_altnamespace=
+  case $func_normal_abspath_tpath in
+    "")
+      # Empty path, that just means $cwd.
+      func_stripname '' '/' "`pwd`"
+      func_normal_abspath_result=$func_stripname_result
+      return
+    ;;
+    # The next three entries are used to spot a run of precisely
+    # two leading slashes without using negated character classes;
+    # we take advantage of case's first-match behaviour.
+    ///*)
+      # Unusual form of absolute path, do nothing.
+    ;;
+    //*)
+      # Not necessarily an ordinary path; POSIX reserves leading '//'
+      # and for example Cygwin uses it to access remote file shares
+      # over CIFS/SMB, so we conserve a leading double slash if found.
+      func_normal_abspath_altnamespace=/
+    ;;
+    /*)
+      # Absolute path, do nothing.
+    ;;
+    *)
+      # Relative path, prepend $cwd.
+      func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
+    ;;
+  esac
+  # Cancel out all the simple stuff to save iterations.  We also want
+  # the path to end with a slash for ease of parsing, so make sure
+  # there is one (and only one) here.
+  func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"`
+  while :; do
+    # Processed it all yet?
+    if test "$func_normal_abspath_tpath" = / ; then
+      # If we ascended to the root using ".." the result may be empty now.
+      if test -z "$func_normal_abspath_result" ; then
+        func_normal_abspath_result=/
+      fi
+      break
+    fi
+    func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcar"`
+    func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcdr"`
+    # Figure out what to do with it
+    case $func_normal_abspath_tcomponent in
+      "")
+        # Trailing empty path component, ignore it.
+      ;;
+      ..)
+        # Parent dir; strip last assembled component from result.
+        func_dirname "$func_normal_abspath_result"
+        func_normal_abspath_result=$func_dirname_result
+      ;;
+      *)
+        # Actual path component, append it.
+        func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent
+      ;;
+    esac
+  done
+  # Restore leading double-slash if one was found on entry.
+  func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
+}
+
+# func_relative_path SRCDIR DSTDIR
+# generates a relative path from SRCDIR to DSTDIR, with a trailing
+# slash if non-empty, suitable for immediately appending a filename
+# without needing to append a separator.
+#             value returned in "$func_relative_path_result"
+func_relative_path ()
+{
+  func_relative_path_result=
+  func_normal_abspath "$1"
+  func_relative_path_tlibdir=$func_normal_abspath_result
+  func_normal_abspath "$2"
+  func_relative_path_tbindir=$func_normal_abspath_result
+
+  # Ascend the tree starting from libdir
+  while :; do
+    # check if we have found a prefix of bindir
+    case $func_relative_path_tbindir in
+      $func_relative_path_tlibdir)
+        # found an exact match
+        func_relative_path_tcancelled=
+        break
+        ;;
+      $func_relative_path_tlibdir*)
+        # found a matching prefix
+        func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
+        func_relative_path_tcancelled=$func_stripname_result
+        if test -z "$func_relative_path_result"; then
+          func_relative_path_result=.
+        fi
+        break
+        ;;
+      *)
+        func_dirname $func_relative_path_tlibdir
+        func_relative_path_tlibdir=${func_dirname_result}
+        if test "x$func_relative_path_tlibdir" = x ; then
+          # Have to descend all the way to the root!
+          func_relative_path_result=../$func_relative_path_result
+          func_relative_path_tcancelled=$func_relative_path_tbindir
+          break
+        fi
+        func_relative_path_result=../$func_relative_path_result
+        ;;
+    esac
+  done
+
+  # Now calculate path; take care to avoid doubling-up slashes.
+  func_stripname '' '/' "$func_relative_path_result"
+  func_relative_path_result=$func_stripname_result
+  func_stripname '/' '/' "$func_relative_path_tcancelled"
+  if test "x$func_stripname_result" != x ; then
+    func_relative_path_result=${func_relative_path_result}/${func_stripname_result}
+  fi
+
+  # Normalisation. If bindir is libdir, return empty string,
+  # else relative path ending with a slash; either way, target
+  # file name can be directly appended.
+  if test ! -z "$func_relative_path_result"; then
+    func_stripname './' '' "$func_relative_path_result/"
+    func_relative_path_result=$func_stripname_result
+  fi
+}
+
+# The name of this program:
+func_dirname_and_basename "$progpath"
+progname=$func_basename_result
+
+# Make sure we have an absolute path for reexecution:
+case $progpath in
+  [\\/]*|[A-Za-z]:\\*) ;;
+  *[\\/]*)
+     progdir=$func_dirname_result
+     progdir=`cd "$progdir" && pwd`
+     progpath="$progdir/$progname"
+     ;;
+  *)
+     save_IFS="$IFS"
+     IFS=:
+     for progdir in $PATH; do
+       IFS="$save_IFS"
+       test -x "$progdir/$progname" && break
+     done
+     IFS="$save_IFS"
+     test -n "$progdir" || progdir=`pwd`
+     progpath="$progdir/$progname"
+     ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Re-`\' parameter expansions in output of double_quote_subst that were
+# `\'-ed in input to the same.  If an odd number of `\' preceded a '$'
+# in input to double_quote_subst, that '$' was protected from expansion.
+# Since each input `\' is now two `\'s, look for any number of runs of
+# four `\'s followed by two `\'s and then a '$'.  `\' that '$'.
+bs='\\'
+bs2='\\\\'
+bs4='\\\\\\\\'
+dollar='\$'
+sed_double_backslash="\
+  s/$bs4/&\\
+/g
+  s/^$bs2$dollar/$bs&/
+  s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
+  s/\n//g"
+
+# Standard options:
+opt_dry_run=false
+opt_help=false
+opt_quiet=false
+opt_verbose=false
+opt_warning=:
+
+# func_echo arg...
+# Echo program name prefixed message, along with the current mode
+# name if it has been set yet.
+func_echo ()
+{
+    $ECHO "$progname${mode+: }$mode: $*"
+}
+
+# func_verbose arg...
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+    $opt_verbose && func_echo ${1+"$@"}
+
+    # A bug in bash halts the script if the last line of a function
+    # fails when set -e is in force, so we need another command to
+    # work around that:
+    :
+}
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*"
+}
+
+# func_error arg...
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+    $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2
+}
+
+# func_warning arg...
+# Echo program name prefixed warning message to standard error.
+func_warning ()
+{
+    $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2
+
+    # bash bug again:
+    :
+}
+
+# func_fatal_error arg...
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+    func_error ${1+"$@"}
+    exit $EXIT_FAILURE
+}
+
+# func_fatal_help arg...
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+    func_error ${1+"$@"}
+    func_fatal_error "$help"
+}
+help="Try \`$progname --help' for more information."  ## default
+
+
+# func_grep expression filename
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+    $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_mkdir_p directory-path
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+    my_directory_path="$1"
+    my_dir_list=
+
+    if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
+
+      # Protect directory names starting with `-'
+      case $my_directory_path in
+        -*) my_directory_path="./$my_directory_path" ;;
+      esac
+
+      # While some portion of DIR does not yet exist...
+      while test ! -d "$my_directory_path"; do
+        # ...make a list in topmost first order.  Use a colon delimited
+	# list incase some portion of path contains whitespace.
+        my_dir_list="$my_directory_path:$my_dir_list"
+
+        # If the last portion added has no slash in it, the list is done
+        case $my_directory_path in */*) ;; *) break ;; esac
+
+        # ...otherwise throw away the child directory and loop
+        my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"`
+      done
+      my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'`
+
+      save_mkdir_p_IFS="$IFS"; IFS=':'
+      for my_dir in $my_dir_list; do
+	IFS="$save_mkdir_p_IFS"
+        # mkdir can fail with a `File exist' error if two processes
+        # try to create one of the directories concurrently.  Don't
+        # stop in that case!
+        $MKDIR "$my_dir" 2>/dev/null || :
+      done
+      IFS="$save_mkdir_p_IFS"
+
+      # Bail out if we (or some other process) failed to create a directory.
+      test -d "$my_directory_path" || \
+        func_fatal_error "Failed to create \`$1'"
+    fi
+}
+
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$opt_dry_run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+        # Failing that, at least try and use $RANDOM to avoid a race
+        my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+        save_mktempdir_umask=`umask`
+        umask 0077
+        $MKDIR "$my_tmpdir"
+        umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || \
+        func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
+    fi
+
+    $ECHO "$my_tmpdir"
+}
+
+
+# func_quote_for_eval arg
+# Aesthetically quote ARG to be evaled later.
+# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
+# is double-quoted, suitable for a subsequent eval, whereas
+# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
+# which are still active within double quotes backslashified.
+func_quote_for_eval ()
+{
+    case $1 in
+      *[\\\`\"\$]*)
+	func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;;
+      *)
+        func_quote_for_eval_unquoted_result="$1" ;;
+    esac
+
+    case $func_quote_for_eval_unquoted_result in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting, command substitution and and variable
+      # expansion for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
+        ;;
+      *)
+        func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
+    esac
+}
+
+
+# func_quote_for_expand arg
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+    case $1 in
+      *[\\\`\"]*)
+	my_arg=`$ECHO "$1" | $SED \
+	    -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
+      *)
+        my_arg="$1" ;;
+    esac
+
+    case $my_arg in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting and command substitution for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        my_arg="\"$my_arg\""
+        ;;
+    esac
+
+    func_quote_for_expand_result="$my_arg"
+}
+
+
+# func_show_eval cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$my_cmd"
+      my_status=$?
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+# func_show_eval_locale cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.  Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$lt_user_locale
+	    $my_cmd"
+      my_status=$?
+      eval "$lt_safe_locale"
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+
+
+
+# func_version
+# Echo version message to standard output and exit.
+func_version ()
+{
+    $SED -n '/(C)/!b go
+	:more
+	/\./!{
+	  N
+	  s/\n# //
+	  b more
+	}
+	:go
+	/^# '$PROGRAM' (GNU /,/# warranty; / {
+        s/^# //
+	s/^# *$//
+        s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
+        p
+     }' < "$progpath"
+     exit $?
+}
+
+# func_usage
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+    $SED -n '/^# Usage:/,/^#  *-h/ {
+        s/^# //
+	s/^# *$//
+	s/\$progname/'$progname'/
+	p
+    }' < "$progpath"
+    echo
+    $ECHO "run \`$progname --help | more' for full usage"
+    exit $?
+}
+
+# func_help [NOEXIT]
+# Echo long help message to standard output and exit,
+# unless 'noexit' is passed as argument.
+func_help ()
+{
+    $SED -n '/^# Usage:/,/# Report bugs to/ {
+        s/^# //
+	s/^# *$//
+	s*\$progname*'$progname'*
+	s*\$host*'"$host"'*
+	s*\$SHELL*'"$SHELL"'*
+	s*\$LTCC*'"$LTCC"'*
+	s*\$LTCFLAGS*'"$LTCFLAGS"'*
+	s*\$LD*'"$LD"'*
+	s/\$with_gnu_ld/'"$with_gnu_ld"'/
+	s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/
+	s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/
+	p
+     }' < "$progpath"
+    ret=$?
+    if test -z "$1"; then
+      exit $ret
+    fi
+}
+
+# func_missing_arg argname
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+    func_error "missing argument for $1"
+    exit_cmd=exit
+}
+
+exit_cmd=:
+
+
+
+
+
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+# $mode is unset
+nonopt=
+execute_dlfiles=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+opt_dry_run=false
+opt_finish=:
+opt_duplicate_deps=false
+opt_silent=false
+opt_debug=:
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+# func_fatal_configuration arg...
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+    func_error ${1+"$@"}
+    func_error "See the $PACKAGE documentation for more information."
+    func_fatal_error "Fatal configuration error."
+}
+
+
+# func_config
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+    re_begincf='^# ### BEGIN LIBTOOL'
+    re_endcf='^# ### END LIBTOOL'
+
+    # Default configuration.
+    $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+    done
+
+    exit $?
+}
+
+# func_features
+# Display the features supported by this script.
+func_features ()
+{
+    echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      echo "enable shared libraries"
+    else
+      echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      echo "enable static libraries"
+    else
+      echo "disable static libraries"
+    fi
+
+    exit $?
+}
+
+# func_enable_tag tagname
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+  # Global variable:
+  tagname="$1"
+
+  re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+  re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+  sed_extractcf="/$re_begincf/,/$re_endcf/p"
+
+  # Validate tagname.
+  case $tagname in
+    *[!-_A-Za-z0-9,/]*)
+      func_fatal_error "invalid tag name: $tagname"
+      ;;
+  esac
+
+  # Don't test for the "default" C tag, as we know it's
+  # there but not specially marked.
+  case $tagname in
+    CC) ;;
+    *)
+      if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+	taglist="$taglist $tagname"
+
+	# Evaluate the configuration.  Be careful to quote the path
+	# and the sed script, to avoid splitting on whitespace, but
+	# also don't use non-portable quotes within backquotes within
+	# quotes we have to do it in 2 steps:
+	extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+	eval "$extractedcf"
+      else
+	func_error "ignoring unknown tag $tagname"
+      fi
+      ;;
+  esac
+}
+
+# Parse options once, thoroughly.  This comes as soon as possible in
+# the script to make things like `libtool --version' happen quickly.
+{
+
+  # Shorthand for --mode=foo, only valid as the first argument
+  case $1 in
+  clean|clea|cle|cl)
+    shift; set dummy --mode clean ${1+"$@"}; shift
+    ;;
+  compile|compil|compi|comp|com|co|c)
+    shift; set dummy --mode compile ${1+"$@"}; shift
+    ;;
+  execute|execut|execu|exec|exe|ex|e)
+    shift; set dummy --mode execute ${1+"$@"}; shift
+    ;;
+  finish|finis|fini|fin|fi|f)
+    shift; set dummy --mode finish ${1+"$@"}; shift
+    ;;
+  install|instal|insta|inst|ins|in|i)
+    shift; set dummy --mode install ${1+"$@"}; shift
+    ;;
+  link|lin|li|l)
+    shift; set dummy --mode link ${1+"$@"}; shift
+    ;;
+  uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+    shift; set dummy --mode uninstall ${1+"$@"}; shift
+    ;;
+  esac
+
+  # Parse non-mode specific arguments:
+  while test "$#" -gt 0; do
+    opt="$1"
+    shift
+
+    case $opt in
+      --config)		func_config					;;
+
+      --debug)		preserve_args="$preserve_args $opt"
+			func_echo "enabling shell trace mode"
+			opt_debug='set -x'
+			$opt_debug
+			;;
+
+      -dlopen)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			execute_dlfiles="$execute_dlfiles $1"
+			shift
+			;;
+
+      --dry-run | -n)	opt_dry_run=:					;;
+      --features)       func_features					;;
+      --finish)		mode="finish"					;;
+      --no-finish)	opt_finish=false				;;
+
+      --mode)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			case $1 in
+			  # Valid mode arguments:
+			  clean)	;;
+			  compile)	;;
+			  execute)	;;
+			  finish)	;;
+			  install)	;;
+			  link)		;;
+			  relink)	;;
+			  uninstall)	;;
+
+			  # Catch anything else as an error
+			  *) func_error "invalid argument for $opt"
+			     exit_cmd=exit
+			     break
+			     ;;
+		        esac
+
+			mode="$1"
+			shift
+			;;
+
+      --preserve-dup-deps)
+			opt_duplicate_deps=:				;;
+
+      --quiet|--silent)	preserve_args="$preserve_args $opt"
+			opt_silent=:
+			opt_verbose=false
+			;;
+
+      --no-quiet|--no-silent)
+			preserve_args="$preserve_args $opt"
+			opt_silent=false
+			;;
+
+      --verbose| -v)	preserve_args="$preserve_args $opt"
+			opt_silent=false
+			opt_verbose=:
+			;;
+
+      --no-verbose)	preserve_args="$preserve_args $opt"
+			opt_verbose=false
+			;;
+
+      --tag)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			preserve_args="$preserve_args $opt $1"
+			func_enable_tag "$1"	# tagname is set here
+			shift
+			;;
+
+      # Separate optargs to long options:
+      -dlopen=*|--mode=*|--tag=*)
+			func_opt_split "$opt"
+			set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"}
+			shift
+			;;
+
+      -\?|-h)		func_usage					;;
+      --help)		opt_help=:					;;
+      --help-all)	opt_help=': help-all'				;;
+      --version)	func_version					;;
+
+      -*)		func_fatal_help "unrecognized option \`$opt'"	;;
+
+      *)		nonopt="$opt"
+			break
+			;;
+    esac
+  done
+
+
+  case $host in
+    *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* )
+      # don't eliminate duplications in $postdeps and $predeps
+      opt_duplicate_compiler_generated_deps=:
+      ;;
+    *)
+      opt_duplicate_compiler_generated_deps=$opt_duplicate_deps
+      ;;
+  esac
+
+  # Having warned about all mis-specified options, bail out if
+  # anything was wrong.
+  $exit_cmd $EXIT_FAILURE
+}
+
+# func_check_version_match
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+  if test "$package_revision" != "$macro_revision"; then
+    if test "$VERSION" != "$macro_version"; then
+      if test -z "$macro_version"; then
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      else
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      fi
+    else
+      cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+    fi
+
+    exit $EXIT_MISMATCH
+  fi
+}
+
+
+## ----------- ##
+##    Main.    ##
+## ----------- ##
+
+$opt_help || {
+  # Sanity checks first:
+  func_check_version_match
+
+  if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+    func_fatal_configuration "not configured to build any kind of library"
+  fi
+
+  test -z "$mode" && func_fatal_error "error: you must specify a MODE."
+
+
+  # Darwin sucks
+  eval "std_shrext=\"$shrext_cmds\""
+
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    func_error "unrecognized option \`-dlopen'"
+    $ECHO "$help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$progname --help --mode=$mode' for more information."
+}
+
+
+# func_lalib_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+    test -f "$1" &&
+      $SED -e 4q "$1" 2>/dev/null \
+        | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs.  To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway.  Works if `file' does not exist.
+func_lalib_unsafe_p ()
+{
+    lalib_p=no
+    if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+	for lalib_p_l in 1 2 3 4
+	do
+	    read lalib_p_line
+	    case "$lalib_p_line" in
+		\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+	    esac
+	done
+	exec 0<&5 5<&-
+    fi
+    test "$lalib_p" = yes
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+    func_lalib_p "$1"
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+    func_ltwrapper_exec_suffix=
+    case $1 in
+    *.exe) ;;
+    *) func_ltwrapper_exec_suffix=.exe ;;
+    esac
+    $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+    func_ltwrapper_scriptname_result=""
+    if func_ltwrapper_executable_p "$1"; then
+	func_dirname_and_basename "$1" "" "."
+	func_stripname '' '.exe' "$func_basename_result"
+	func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
+    fi
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+    func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+    $opt_debug
+    save_ifs=$IFS; IFS='~'
+    for cmd in $1; do
+      IFS=$save_ifs
+      eval "cmd=\"$cmd\""
+      func_show_eval "$cmd" "${2-:}"
+    done
+    IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)!  Also, sourcing
+# `FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+    $opt_debug
+    case $1 in
+    */* | *\\*)	. "$1" ;;
+    *)		. "./$1" ;;
+    esac
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    $opt_debug
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+        func_quote_for_eval "$arg"
+	CC_quoted="$CC_quoted $func_quote_for_eval_result"
+      done
+      CC_expanded=`func_echo_all $CC`
+      CC_quoted_expanded=`func_echo_all $CC_quoted`
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+      " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+	    CC_quoted=
+	    for arg in $CC; do
+	      # Double-quote args containing other shell metacharacters.
+	      func_quote_for_eval "$arg"
+	      CC_quoted="$CC_quoted $func_quote_for_eval_result"
+	    done
+	    CC_expanded=`func_echo_all $CC`
+	    CC_quoted_expanded=`func_echo_all $CC_quoted`
+	    case "$@ " in
+	    " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+	    " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
+	      # The compiler in the base compile command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  func_echo "unable to infer tagged configuration"
+	  func_fatal_error "specify a tag with \`--tag'"
+#	else
+#	  func_verbose "using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+    write_libobj=${1}
+    if test "$build_libtool_libs" = yes; then
+      write_lobj=\'${2}\'
+    else
+      write_lobj=none
+    fi
+
+    if test "$build_old_libs" = yes; then
+      write_oldobj=\'${3}\'
+    else
+      write_oldobj=none
+    fi
+
+    $opt_dry_run || {
+      cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "${write_libobj}"
+    }
+}
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+    $opt_debug
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+    pie_flag=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+	# do not "continue".  Instead, add this to base_compile
+	lastarg="$arg"
+	arg_mode=normal
+	;;
+
+      target )
+	libobj="$arg"
+	arg_mode=normal
+	continue
+	;;
+
+      normal )
+	# Accept any command-line options.
+	case $arg in
+	-o)
+	  test -n "$libobj" && \
+	    func_fatal_error "you cannot specify \`-o' more than once"
+	  arg_mode=target
+	  continue
+	  ;;
+
+	-pie | -fpie | -fPIE)
+          pie_flag="$pie_flag $arg"
+	  continue
+	  ;;
+
+	-shared | -static | -prefer-pic | -prefer-non-pic)
+	  later="$later $arg"
+	  continue
+	  ;;
+
+	-no-suppress)
+	  suppress_opt=no
+	  continue
+	  ;;
+
+	-Xcompiler)
+	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
+	  continue      #  The current "srcfile" will either be retained or
+	  ;;            #  replaced later.  I would guess that would be a bug.
+
+	-Wc,*)
+	  func_stripname '-Wc,' '' "$arg"
+	  args=$func_stripname_result
+	  lastarg=
+	  save_ifs="$IFS"; IFS=','
+	  for arg in $args; do
+	    IFS="$save_ifs"
+	    func_quote_for_eval "$arg"
+	    lastarg="$lastarg $func_quote_for_eval_result"
+	  done
+	  IFS="$save_ifs"
+	  func_stripname ' ' '' "$lastarg"
+	  lastarg=$func_stripname_result
+
+	  # Add the arguments to base_compile.
+	  base_compile="$base_compile $lastarg"
+	  continue
+	  ;;
+
+	*)
+	  # Accept the current argument as the source file.
+	  # The previous "srcfile" becomes the current argument.
+	  #
+	  lastarg="$srcfile"
+	  srcfile="$arg"
+	  ;;
+	esac  #  case $arg
+	;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      func_quote_for_eval "$lastarg"
+      base_compile="$base_compile $func_quote_for_eval_result"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      func_fatal_error "you must specify an argument for -Xcompile"
+      ;;
+    target)
+      func_fatal_error "you must specify a target with \`-o'"
+      ;;
+    *)
+      # Get the name of the library object.
+      test -z "$libobj" && {
+	func_basename "$srcfile"
+	libobj="$func_basename_result"
+      }
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    case $libobj in
+    *.[cCFSifmso] | \
+    *.ada | *.adb | *.ads | *.asm | \
+    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+    *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
+      func_xform "$libobj"
+      libobj=$func_xform_result
+      ;;
+    esac
+
+    case $libobj in
+    *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+    *)
+      func_fatal_error "cannot determine name of library object from \`$libobj'"
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	continue
+	;;
+
+      -static)
+	build_libtool_libs=no
+	build_old_libs=yes
+	continue
+	;;
+
+      -prefer-pic)
+	pic_mode=yes
+	continue
+	;;
+
+      -prefer-non-pic)
+	pic_mode=no
+	continue
+	;;
+      esac
+    done
+
+    func_quote_for_eval "$libobj"
+    test "X$libobj" != "X$func_quote_for_eval_result" \
+      && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
+      && func_warning "libobj name \`$libobj' may not contain shell special characters."
+    func_dirname_and_basename "$obj" "/" ""
+    objname="$func_basename_result"
+    xdir="$func_dirname_result"
+    lobj=${xdir}$objdir/$objname
+
+    test -z "$base_compile" && \
+      func_fatal_help "you must specify a compilation command"
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2* | cegcc*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+	$ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+      removelist="$removelist $output_obj"
+      $ECHO "$srcfile" > "$lockfile"
+    fi
+
+    $opt_dry_run || $RM $removelist
+    removelist="$removelist $lockfile"
+    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+    if test -n "$fix_srcfile_path"; then
+      eval "srcfile=\"$fix_srcfile_path\""
+    fi
+    func_quote_for_eval "$srcfile"
+    qsrcfile=$func_quote_for_eval_result
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+	command="$base_compile $qsrcfile $pic_flag"
+      else
+	# Don't build PIC code
+	command="$base_compile $qsrcfile"
+      fi
+
+      func_mkdir_p "$xdir$objdir"
+
+      if test -z "$output_obj"; then
+	# Place PIC objects in $objdir
+	command="$command -o $lobj"
+      fi
+
+      func_show_eval_locale "$command"	\
+          'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+	func_show_eval '$MV "$output_obj" "$lobj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+	suppress_output=' >/dev/null 2>&1'
+      fi
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+	# Don't build PIC code
+	command="$base_compile $qsrcfile$pie_flag"
+      else
+	command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+	command="$command -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      func_show_eval_locale "$command" \
+        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+	func_show_eval '$MV "$output_obj" "$obj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+    fi
+
+    $opt_dry_run || {
+      func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+      # Unlock the critical section if it was locked
+      if test "$need_locks" != no; then
+	removelist=$lockfile
+        $RM "$lockfile"
+      fi
+    }
+
+    exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+  test "$mode" = compile && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+    # We need to display help for each of the modes.
+    case $mode in
+      "")
+        # Generic help is extracted from the usage comments
+        # at the start of this file.
+        func_help
+        ;;
+
+      clean)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      compile)
+      $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -no-suppress      do not suppress compiler output for multiple passes
+  -prefer-pic       try to building PIC objects only
+  -prefer-non-pic   try to building non-PIC objects only
+  -shared           do not build a \`.o' file suitable for static linking
+  -static           only build a \`.o' file suitable for static linking
+  -Wc,FLAG          pass FLAG directly to the compiler
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+        ;;
+
+      execute)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+        ;;
+
+      finish)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+        ;;
+
+      install)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+  -inst-prefix-dir PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+        ;;
+
+      link)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -bindir BINDIR    specify path to binaries directory (for systems where
+                    libraries must be found in the PATH setting at runtime)
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -shared           only do dynamic linking of libtool libraries
+  -shrext SUFFIX    override the standard shared library file extension
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+  -weak LIBNAME     declare that the target provides the LIBNAME interface
+  -Wc,FLAG
+  -Xcompiler FLAG   pass linker-specific FLAG directly to the compiler
+  -Wl,FLAG
+  -Xlinker FLAG     pass linker-specific FLAG directly to the linker
+  -XCClinker FLAG   pass link-specific FLAG to the compiler driver (CC)
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+        ;;
+
+      uninstall)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      *)
+        func_fatal_help "invalid operation mode \`$mode'"
+        ;;
+    esac
+
+    echo
+    $ECHO "Try \`$progname --help' for more information about other modes."
+}
+
+# Now that we've collected a possible --mode arg, show help if necessary
+if $opt_help; then
+  if test "$opt_help" = :; then
+    func_mode_help
+  else
+    {
+      func_help noexit
+      for mode in compile link execute install finish uninstall clean; do
+	func_mode_help
+      done
+    } | sed -n '1p; 2,$s/^Usage:/  or: /p'
+    {
+      func_help noexit
+      for mode in compile link execute install finish uninstall clean; do
+	echo
+	func_mode_help
+      done
+    } |
+    sed '1d
+      /^When reporting/,/^Report/{
+	H
+	d
+      }
+      $x
+      /information about other modes/d
+      /more detailed .*MODE/d
+      s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
+  fi
+  exit $?
+fi
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+    $opt_debug
+    # The first argument is the command name.
+    cmd="$nonopt"
+    test -z "$cmd" && \
+      func_fatal_help "you must specify a COMMAND"
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      test -f "$file" \
+	|| func_fatal_help "\`$file' is not a file"
+
+      dir=
+      case $file in
+      *.la)
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$lib' is not a valid libtool archive"
+
+	# Read the libtool library.
+	dlname=
+	library_names=
+	func_source "$file"
+
+	# Skip this library if it cannot be dlopened.
+	if test -z "$dlname"; then
+	  # Warn if it was a shared library.
+	  test -n "$library_names" && \
+	    func_warning "\`$file' was not linked with \`-export-dynamic'"
+	  continue
+	fi
+
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+
+	if test -f "$dir/$objdir/$dlname"; then
+	  dir="$dir/$objdir"
+	else
+	  if test ! -f "$dir/$dlname"; then
+	    func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
+	  fi
+	fi
+	;;
+
+      *.lo)
+	# Just add the directory containing the .lo file.
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+	;;
+
+      *)
+	func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
+	continue
+	;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval test -z \"\$$shlibpath_var\"; then
+	eval $shlibpath_var=\$dir
+      else
+	eval $shlibpath_var=\$dir:\$$shlibpath_var
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -* | *.la | *.lo ) ;;
+      *)
+	# Do a test to see if this is really a libtool program.
+	if func_ltwrapper_script_p "$file"; then
+	  func_source "$file"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	elif func_ltwrapper_executable_p "$file"; then
+	  func_ltwrapper_scriptname "$file"
+	  func_source "$func_ltwrapper_scriptname_result"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	fi
+	;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      func_quote_for_eval "$file"
+      args="$args $func_quote_for_eval_result"
+    done
+
+    if test "X$opt_dry_run" = Xfalse; then
+      if test -n "$shlibpath_var"; then
+	# Export the shlibpath_var.
+	eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+	eval "if test \"\${save_$lt_var+set}\" = set; then
+                $lt_var=\$save_$lt_var; export $lt_var
+	      else
+		$lt_unset $lt_var
+	      fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+	eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+	echo "export $shlibpath_var"
+      fi
+      $ECHO "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$mode" = execute && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+    $opt_debug
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+	libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+	if test -n "$finish_cmds"; then
+	  # Do each command in the finish commands.
+	  func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+	fi
+	if test -n "$finish_eval"; then
+	  # Do the single finish_eval.
+	  eval cmds=\"$finish_eval\"
+	  $opt_dry_run || eval "$cmds" || admincmds="$admincmds
+       $cmds"
+	fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    $opt_silent && exit $EXIT_SUCCESS
+
+    echo "----------------------------------------------------------------------"
+    echo "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      $ECHO "   $libdir"
+    done
+    echo
+    echo "If you ever happen to want to link against installed libraries"
+    echo "in a given directory, LIBDIR, you must either use libtool, and"
+    echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    echo "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      echo "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+      echo "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval "flag=\"$hardcode_libdir_flag_spec\""
+
+      $ECHO "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      $ECHO "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    echo
+
+    echo "See any operating system documentation about shared libraries for"
+    case $host in
+      solaris2.[6789]|solaris2.1[0-9])
+        echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+	echo "pages."
+	;;
+      *)
+        echo "more information, such as the ld(1) and ld.so(8) manual pages."
+        ;;
+    esac
+    echo "----------------------------------------------------------------------"
+    exit $EXIT_SUCCESS
+}
+
+test "$mode" = finish && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+    $opt_debug
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       case $nonopt in *shtool*) :;; *) false;; esac; then
+      # Aesthetically quote it.
+      func_quote_for_eval "$nonopt"
+      install_prog="$func_quote_for_eval_result "
+      arg=$1
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    func_quote_for_eval "$arg"
+    install_prog="$install_prog$func_quote_for_eval_result"
+    install_shared_prog=$install_prog
+    case " $install_prog " in
+      *[\\\ /]cp\ *) install_cp=: ;;
+      *) install_cp=false ;;
+    esac
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    no_mode=:
+    for arg
+    do
+      arg2=
+      if test -n "$dest"; then
+	files="$files $dest"
+	dest=$arg
+	continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f)
+	if $install_cp; then :; else
+	  prev=$arg
+	fi
+	;;
+      -g | -m | -o)
+	prev=$arg
+	;;
+      -s)
+	stripme=" -s"
+	continue
+	;;
+      -*)
+	;;
+      *)
+	# If the previous option needed an argument, then skip it.
+	if test -n "$prev"; then
+	  if test "x$prev" = x-m && test -n "$install_override_mode"; then
+	    arg2=$install_override_mode
+	    no_mode=false
+	  fi
+	  prev=
+	else
+	  dest=$arg
+	  continue
+	fi
+	;;
+      esac
+
+      # Aesthetically quote the argument.
+      func_quote_for_eval "$arg"
+      install_prog="$install_prog $func_quote_for_eval_result"
+      if test -n "$arg2"; then
+	func_quote_for_eval "$arg2"
+      fi
+      install_shared_prog="$install_shared_prog $func_quote_for_eval_result"
+    done
+
+    test -z "$install_prog" && \
+      func_fatal_help "you must specify an install program"
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prev' option requires an argument"
+
+    if test -n "$install_override_mode" && $no_mode; then
+      if $install_cp; then :; else
+	func_quote_for_eval "$install_override_mode"
+	install_shared_prog="$install_shared_prog -m $func_quote_for_eval_result"
+      fi
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+	func_fatal_help "no file or destination specified"
+      else
+	func_fatal_help "you must specify a destination"
+      fi
+    fi
+
+    # Strip any trailing slash from the destination.
+    func_stripname '' '/' "$dest"
+    dest=$func_stripname_result
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      func_dirname_and_basename "$dest" "" "."
+      destdir="$func_dirname_result"
+      destname="$func_basename_result"
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files; shift
+      test "$#" -gt 1 && \
+	func_fatal_help "\`$dest' is not a directory"
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+	case $file in
+	*.lo) ;;
+	*)
+	  func_fatal_help "\`$destdir' must be an absolute directory name"
+	  ;;
+	esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+	# Do the static libraries later.
+	staticlibs="$staticlibs $file"
+	;;
+
+      *.la)
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$file' is not a valid libtool archive"
+
+	library_names=
+	old_library=
+	relink_command=
+	func_source "$file"
+
+	# Add the libdir to current_libdirs if it is the destination.
+	if test "X$destdir" = "X$libdir"; then
+	  case "$current_libdirs " in
+	  *" $libdir "*) ;;
+	  *) current_libdirs="$current_libdirs $libdir" ;;
+	  esac
+	else
+	  # Note the libdir as a future libdir.
+	  case "$future_libdirs " in
+	  *" $libdir "*) ;;
+	  *) future_libdirs="$future_libdirs $libdir" ;;
+	  esac
+	fi
+
+	func_dirname "$file" "/" ""
+	dir="$func_dirname_result"
+	dir="$dir$objdir"
+
+	if test -n "$relink_command"; then
+	  # Determine the prefix the user has applied to our future dir.
+	  inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
+
+	  # Don't allow the user to place us outside of our expected
+	  # location b/c this prevents finding dependent libraries that
+	  # are installed to the same prefix.
+	  # At present, this check doesn't affect windows .dll's that
+	  # are installed into $libdir/../bin (currently, that works fine)
+	  # but it's something to keep an eye on.
+	  test "$inst_prefix_dir" = "$destdir" && \
+	    func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+	  if test -n "$inst_prefix_dir"; then
+	    # Stick the inst_prefix_dir data into the link command.
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	  else
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+	  fi
+
+	  func_warning "relinking \`$file'"
+	  func_show_eval "$relink_command" \
+	    'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+	fi
+
+	# See the names of the shared library.
+	set dummy $library_names; shift
+	if test -n "$1"; then
+	  realname="$1"
+	  shift
+
+	  srcname="$realname"
+	  test -n "$relink_command" && srcname="$realname"T
+
+	  # Install the shared library and build the symlinks.
+	  func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
+	      'exit $?'
+	  tstripme="$stripme"
+	  case $host_os in
+	  cygwin* | mingw* | pw32* | cegcc*)
+	    case $realname in
+	    *.dll.a)
+	      tstripme=""
+	      ;;
+	    esac
+	    ;;
+	  esac
+	  if test -n "$tstripme" && test -n "$striplib"; then
+	    func_show_eval "$striplib $destdir/$realname" 'exit $?'
+	  fi
+
+	  if test "$#" -gt 0; then
+	    # Delete the old symlinks, and create new ones.
+	    # Try `ln -sf' first, because the `ln' binary might depend on
+	    # the symlink we replace!  Solaris /bin/ln does not understand -f,
+	    # so we also need to try rm && ln -s.
+	    for linkname
+	    do
+	      test "$linkname" != "$realname" \
+		&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+	    done
+	  fi
+
+	  # Do each command in the postinstall commands.
+	  lib="$destdir/$realname"
+	  func_execute_cmds "$postinstall_cmds" 'exit $?'
+	fi
+
+	# Install the pseudo-library for information purposes.
+	func_basename "$file"
+	name="$func_basename_result"
+	instname="$dir/$name"i
+	func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+	# Maybe install the static library, too.
+	test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+	;;
+
+      *.lo)
+	# Install (i.e. copy) a libtool object.
+
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# Deduce the name of the destination old-style object file.
+	case $destfile in
+	*.lo)
+	  func_lo2o "$destfile"
+	  staticdest=$func_lo2o_result
+	  ;;
+	*.$objext)
+	  staticdest="$destfile"
+	  destfile=
+	  ;;
+	*)
+	  func_fatal_help "cannot copy a libtool object to \`$destfile'"
+	  ;;
+	esac
+
+	# Install the libtool object if requested.
+	test -n "$destfile" && \
+	  func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+	# Install the old object if enabled.
+	if test "$build_old_libs" = yes; then
+	  # Deduce the name of the old-style object file.
+	  func_lo2o "$file"
+	  staticobj=$func_lo2o_result
+	  func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+	fi
+	exit $EXIT_SUCCESS
+	;;
+
+      *)
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# If the file is missing, and there is a .exe on the end, strip it
+	# because it is most likely a libtool script we actually want to
+	# install
+	stripped_ext=""
+	case $file in
+	  *.exe)
+	    if test ! -f "$file"; then
+	      func_stripname '' '.exe' "$file"
+	      file=$func_stripname_result
+	      stripped_ext=".exe"
+	    fi
+	    ;;
+	esac
+
+	# Do a test to see if this is really a libtool program.
+	case $host in
+	*cygwin* | *mingw*)
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      wrapper=$func_ltwrapper_scriptname_result
+	    else
+	      func_stripname '' '.exe' "$file"
+	      wrapper=$func_stripname_result
+	    fi
+	    ;;
+	*)
+	    wrapper=$file
+	    ;;
+	esac
+	if func_ltwrapper_script_p "$wrapper"; then
+	  notinst_deplibs=
+	  relink_command=
+
+	  func_source "$wrapper"
+
+	  # Check the variables that should have been set.
+	  test -z "$generated_by_libtool_version" && \
+	    func_fatal_error "invalid libtool wrapper script \`$wrapper'"
+
+	  finalize=yes
+	  for lib in $notinst_deplibs; do
+	    # Check to see that each library is installed.
+	    libdir=
+	    if test -f "$lib"; then
+	      func_source "$lib"
+	    fi
+	    libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test
+	    if test -n "$libdir" && test ! -f "$libfile"; then
+	      func_warning "\`$lib' has not been installed in \`$libdir'"
+	      finalize=no
+	    fi
+	  done
+
+	  relink_command=
+	  func_source "$wrapper"
+
+	  outputname=
+	  if test "$fast_install" = no && test -n "$relink_command"; then
+	    $opt_dry_run || {
+	      if test "$finalize" = yes; then
+	        tmpdir=`func_mktempdir`
+		func_basename "$file$stripped_ext"
+		file="$func_basename_result"
+	        outputname="$tmpdir/$file"
+	        # Replace the output file specification.
+	        relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
+
+	        $opt_silent || {
+	          func_quote_for_expand "$relink_command"
+		  eval "func_echo $func_quote_for_expand_result"
+	        }
+	        if eval "$relink_command"; then :
+	          else
+		  func_error "error: relink \`$file' with the above command before installing it"
+		  $opt_dry_run || ${RM}r "$tmpdir"
+		  continue
+	        fi
+	        file="$outputname"
+	      else
+	        func_warning "cannot relink \`$file'"
+	      fi
+	    }
+	  else
+	    # Install the binary that we compiled earlier.
+	    file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
+	  fi
+	fi
+
+	# remove .exe since cygwin /usr/bin/install will append another
+	# one anyway
+	case $install_prog,$host in
+	*/usr/bin/install*,*cygwin*)
+	  case $file:$destfile in
+	  *.exe:*.exe)
+	    # this is ok
+	    ;;
+	  *.exe:*)
+	    destfile=$destfile.exe
+	    ;;
+	  *:*.exe)
+	    func_stripname '' '.exe' "$destfile"
+	    destfile=$func_stripname_result
+	    ;;
+	  esac
+	  ;;
+	esac
+	func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+	$opt_dry_run || if test -n "$outputname"; then
+	  ${RM}r "$tmpdir"
+	fi
+	;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      func_basename "$file"
+      name="$func_basename_result"
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+	func_show_eval "$old_striplib $oldlib" 'exit $?'
+      fi
+
+      # Do each command in the postinstall commands.
+      func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+    done
+
+    test -n "$future_libdirs" && \
+      func_warning "remember to run \`$progname --finish$future_libdirs'"
+
+    if test -n "$current_libdirs" && $opt_finish; then
+      # Maybe just do a dry run.
+      $opt_dry_run && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$mode" = install && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+    $opt_debug
+    my_outputname="$1"
+    my_originator="$2"
+    my_pic_p="${3-no}"
+    my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
+    my_dlsyms=
+
+    if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+      if test -n "$NM" && test -n "$global_symbol_pipe"; then
+	my_dlsyms="${my_outputname}S.c"
+      else
+	func_error "not configured to extract global symbols from dlpreopened files"
+      fi
+    fi
+
+    if test -n "$my_dlsyms"; then
+      case $my_dlsyms in
+      "") ;;
+      *.c)
+	# Discover the nlist of each of the dlfiles.
+	nlist="$output_objdir/${my_outputname}.nm"
+
+	func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+	# Parse the name list into a source file.
+	func_verbose "creating $output_objdir/$my_dlsyms"
+
+	$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#endif
+
+/* External symbol declarations for the compiler. */\
+"
+
+	if test "$dlself" = yes; then
+	  func_verbose "generating symbol list for \`$output'"
+
+	  $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+	  # Add our own program objects to the symbol list.
+	  progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	  for progfile in $progfiles; do
+	    func_verbose "extracting global C symbols from \`$progfile'"
+	    $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'"
+	  done
+
+	  if test -n "$exclude_expsyms"; then
+	    $opt_dry_run || {
+	      $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	      $MV "$nlist"T "$nlist"
+	    }
+	  fi
+
+	  if test -n "$export_symbols_regex"; then
+	    $opt_dry_run || {
+	      $EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T
+	      $MV "$nlist"T "$nlist"
+	    }
+	  fi
+
+	  # Prepare the list of exported symbols
+	  if test -z "$export_symbols"; then
+	    export_symbols="$output_objdir/$outputname.exp"
+	    $opt_dry_run || {
+	      $RM $export_symbols
+	      ${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' < "$nlist" > "$export_symbols"
+	      case $host in
+	      *cygwin* | *mingw* | *cegcc* )
+                echo EXPORTS > "$output_objdir/$outputname.def"
+                cat "$export_symbols" >> "$output_objdir/$outputname.def"
+	        ;;
+	      esac
+	    }
+	  else
+	    $opt_dry_run || {
+	      ${SED} -e 's/\([].[*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/' < "$export_symbols" > "$output_objdir/$outputname.exp"
+	      $GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T
+	      $MV "$nlist"T "$nlist"
+	      case $host in
+	        *cygwin* | *mingw* | *cegcc* )
+	          echo EXPORTS > "$output_objdir/$outputname.def"
+	          cat "$nlist" >> "$output_objdir/$outputname.def"
+	          ;;
+	      esac
+	    }
+	  fi
+	fi
+
+	for dlprefile in $dlprefiles; do
+	  func_verbose "extracting global C symbols from \`$dlprefile'"
+	  func_basename "$dlprefile"
+	  name="$func_basename_result"
+	  $opt_dry_run || {
+	    $ECHO ": $name " >> "$nlist"
+	    eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	  }
+	done
+
+	$opt_dry_run || {
+	  # Make sure we have at least an empty file.
+	  test -f "$nlist" || : > "$nlist"
+
+	  if test -n "$exclude_expsyms"; then
+	    $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	    $MV "$nlist"T "$nlist"
+	  fi
+
+	  # Try sorting and uniquifying the output.
+	  if $GREP -v "^: " < "$nlist" |
+	      if sort -k 3 </dev/null >/dev/null 2>&1; then
+		sort -k 3
+	      else
+		sort +2
+	      fi |
+	      uniq > "$nlist"S; then
+	    :
+	  else
+	    $GREP -v "^: " < "$nlist" > "$nlist"S
+	  fi
+
+	  if test -f "$nlist"S; then
+	    eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+	  else
+	    echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
+	  fi
+
+	  echo >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols.  */
+typedef struct {
+  const char *name;
+  void *address;
+} lt_dlsymlist;
+"
+	  case $host in
+	  *cygwin* | *mingw* | *cegcc* )
+	    echo >> "$output_objdir/$my_dlsyms" "\
+/* DATA imports from DLLs on WIN32 con't be const, because
+   runtime relocations are performed -- see ld's documentation
+   on pseudo-relocs.  */"
+	    lt_dlsym_const= ;;
+	  *osf5*)
+	    echo >> "$output_objdir/$my_dlsyms" "\
+/* This system does not cope well with relocations in const data */"
+	    lt_dlsym_const= ;;
+	  *)
+	    lt_dlsym_const=const ;;
+	  esac
+
+	  echo >> "$output_objdir/$my_dlsyms" "\
+extern $lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];
+$lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{\
+  { \"$my_originator\", (void *) 0 },"
+
+	  case $need_lib_prefix in
+	  no)
+	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  *)
+	    eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  esac
+	  echo >> "$output_objdir/$my_dlsyms" "\
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+	} # !$opt_dry_run
+
+	pic_flag_for_symtable=
+	case "$compile_command " in
+	*" -static "*) ;;
+	*)
+	  case $host in
+	  # compiling the symbol table file with pic_flag works around
+	  # a FreeBSD bug that causes programs to crash when -lm is
+	  # linked before any other PIC object.  But we must not use
+	  # pic_flag when linking with -static.  The problem exists in
+	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+	  *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+	    pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+	  *-*-hpux*)
+	    pic_flag_for_symtable=" $pic_flag"  ;;
+	  *)
+	    if test "X$my_pic_p" != Xno; then
+	      pic_flag_for_symtable=" $pic_flag"
+	    fi
+	    ;;
+	  esac
+	  ;;
+	esac
+	symtab_cflags=
+	for arg in $LTCFLAGS; do
+	  case $arg in
+	  -pie | -fpie | -fPIE) ;;
+	  *) symtab_cflags="$symtab_cflags $arg" ;;
+	  esac
+	done
+
+	# Now compile the dynamic symbol file.
+	func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+	# Clean up the generated files.
+	func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
+
+	# Transform the symbol file into the correct name.
+	symfileobj="$output_objdir/${my_outputname}S.$objext"
+	case $host in
+	*cygwin* | *mingw* | *cegcc* )
+	  if test -f "$output_objdir/$my_outputname.def"; then
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	  else
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  fi
+	  ;;
+	*)
+	  compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  ;;
+	esac
+	;;
+      *)
+	func_fatal_error "unknown suffix for \`$my_dlsyms'"
+	;;
+      esac
+    else
+      # We keep going just in case the user didn't refer to
+      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+      # really was required.
+
+      # Nullify the symbol file.
+      compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
+      finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
+    fi
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+# Despite the name, also deal with 64 bit binaries.
+func_win32_libid ()
+{
+  $opt_debug
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    if $OBJDUMP -f "$1" | $SED -e '10q' 2>/dev/null |
+       $EGREP 'file format (pe-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+      win32_nmres=`$NM -f posix -A "$1" |
+	$SED -n -e '
+	    1,100{
+		/ I /{
+		    s,.*,import,
+		    p
+		    q
+		}
+	    }'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $ECHO "$win32_libid_type"
+}
+
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    $opt_debug
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+    if test "$lock_old_archive_extraction" = yes; then
+      lockfile=$f_ex_an_ar_oldlib.lock
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    fi
+    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
+		   'stat=$?; rm -f "$lockfile"; exit $stat'
+    if test "$lock_old_archive_extraction" = yes; then
+      $opt_dry_run || rm -f "$lockfile"
+    fi
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+    fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    $opt_debug
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+	[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+	*) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      func_basename "$my_xlib"
+      my_xlib="$func_basename_result"
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+	*" $my_xlib_u "*)
+	  func_arith $extracted_serial + 1
+	  extracted_serial=$func_arith_result
+	  my_xlib_u=lt$extracted_serial-$my_xlib ;;
+	*) break ;;
+	esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      func_mkdir_p "$my_xdir"
+
+      case $host in
+      *-darwin*)
+	func_verbose "Extracting $my_xabs"
+	# Do not bother doing anything if just a dry run
+	$opt_dry_run || {
+	  darwin_orig_dir=`pwd`
+	  cd $my_xdir || exit $?
+	  darwin_archive=$my_xabs
+	  darwin_curdir=`pwd`
+	  darwin_base_archive=`basename "$darwin_archive"`
+	  darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+	  if test -n "$darwin_arches"; then
+	    darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+	    darwin_arch=
+	    func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+	    for darwin_arch in  $darwin_arches ; do
+	      func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+	      cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+	      cd "$darwin_curdir"
+	      $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+	    done # $darwin_arches
+            ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
+	    darwin_file=
+	    darwin_files=
+	    for darwin_file in $darwin_filelist; do
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+	      $LIPO -create -output "$darwin_file" $darwin_files
+	    done # $darwin_filelist
+	    $RM -rf unfat-$$
+	    cd "$darwin_orig_dir"
+	  else
+	    cd $darwin_orig_dir
+	    func_extract_an_archive "$my_xdir" "$my_xabs"
+	  fi # $darwin_arches
+	} # !$opt_dry_run
+	;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+	;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+
+    func_extract_archives_result="$my_oldobjs"
+}
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable.  Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take.  If 'yes', then the emitted script
+# will assume that the directory in which it is stored is
+# the $objdir directory.  This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+	func_emit_wrapper_arg1=${1-no}
+
+	$ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='$macro_version'
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$ECHO are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    file=\"\$0\""
+
+    qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
+    $ECHO "\
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+    ECHO=\"$qECHO\"
+  fi\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
+  done
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
+  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+    # special case for '.'
+    if test \"\$thisdir\" = \".\"; then
+      thisdir=\`pwd\`
+    fi
+    # remove .libs from thisdir
+    case \"\$thisdir\" in
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    $objdir )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+	if test "$fast_install" = yes; then
+	  $ECHO "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" ||
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $MKDIR \"\$progdir\"
+    else
+      $RM \"\$progdir/\$file\"
+    fi"
+
+	  $ECHO "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \"\$relink_command\" 2>&1\`; then :
+      else
+	$ECHO \"\$relink_command_output\" >&2
+	$RM \"\$progdir/\$file\"
+	exit 1
+      fi
+    fi
+
+    $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $RM \"\$progdir/\$program\";
+      $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $RM \"\$progdir/\$file\"
+  fi"
+	else
+	  $ECHO "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+	fi
+
+	$ECHO "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+	# Export our shlibpath_var if we have one.
+	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+	  $ECHO "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+	fi
+
+	# fixup the dll searchpath if we need to.
+	if test -n "$dllsearchpath"; then
+	  $ECHO "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+	fi
+
+	$ECHO "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+	case $host in
+	# Backslashes separate directories on plain windows
+	*-*-mingw | *-*-os2* | *-cegcc*)
+	  $ECHO "\
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+	  ;;
+
+	*)
+	  $ECHO "\
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+	  ;;
+	esac
+	$ECHO "\
+      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+    \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+}
+
+
+# func_to_host_path arg
+#
+# Convert paths to host format when used with build tools.
+# Intended for use with "native" mingw (where libtool itself
+# is running under the msys shell), or in the following cross-
+# build environments:
+#    $build          $host
+#    mingw (msys)    mingw  [e.g. native]
+#    cygwin          mingw
+#    *nix + wine     mingw
+# where wine is equipped with the `winepath' executable.
+# In the native mingw case, the (msys) shell automatically
+# converts paths for any non-msys applications it launches,
+# but that facility isn't available from inside the cwrapper.
+# Similar accommodations are necessary for $host mingw and
+# $build cygwin.  Calling this function does no harm for other
+# $host/$build combinations not listed above.
+#
+# ARG is the path (on $build) that should be converted to
+# the proper representation for $host. The result is stored
+# in $func_to_host_path_result.
+func_to_host_path ()
+{
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    case $host in
+      *mingw* )
+        lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+        case $build in
+          *mingw* ) # actually, msys
+            # awkward: cmd appends spaces to result
+            func_to_host_path_result=`( cmd //c echo "$1" ) 2>/dev/null |
+              $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"`
+            ;;
+          *cygwin* )
+            func_to_host_path_result=`cygpath -w "$1" |
+	      $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          * )
+            # Unfortunately, winepath does not exit with a non-zero
+            # error code, so we are forced to check the contents of
+            # stdout. On the other hand, if the command is not
+            # found, the shell will set an exit code of 127 and print
+            # *an error message* to stdout. So we must check for both
+            # error code of zero AND non-empty stdout, which explains
+            # the odd construction:
+            func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null`
+            if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then
+              func_to_host_path_result=`$ECHO "$func_to_host_path_tmp1" |
+                $SED -e "$lt_sed_naive_backslashify"`
+            else
+              # Allow warning below.
+              func_to_host_path_result=
+            fi
+            ;;
+        esac
+        if test -z "$func_to_host_path_result" ; then
+          func_error "Could not determine host path corresponding to"
+          func_error "  \`$1'"
+          func_error "Continuing, but uninstalled executables may not work."
+          # Fallback:
+          func_to_host_path_result="$1"
+        fi
+        ;;
+    esac
+  fi
+}
+# end: func_to_host_path
+
+# func_to_host_pathlist arg
+#
+# Convert pathlists to host format when used with build tools.
+# See func_to_host_path(), above. This function supports the
+# following $build/$host combinations (but does no harm for
+# combinations not listed here):
+#    $build          $host
+#    mingw (msys)    mingw  [e.g. native]
+#    cygwin          mingw
+#    *nix + wine     mingw
+#
+# Path separators are also converted from $build format to
+# $host format. If ARG begins or ends with a path separator
+# character, it is preserved (but converted to $host format)
+# on output.
+#
+# ARG is a pathlist (on $build) that should be converted to
+# the proper representation on $host. The result is stored
+# in $func_to_host_pathlist_result.
+func_to_host_pathlist ()
+{
+  func_to_host_pathlist_result="$1"
+  if test -n "$1"; then
+    case $host in
+      *mingw* )
+        lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+        # Remove leading and trailing path separator characters from
+        # ARG. msys behavior is inconsistent here, cygpath turns them
+        # into '.;' and ';.', and winepath ignores them completely.
+	func_stripname : : "$1"
+        func_to_host_pathlist_tmp1=$func_stripname_result
+        case $build in
+          *mingw* ) # Actually, msys.
+            # Awkward: cmd appends spaces to result.
+            func_to_host_pathlist_result=`
+	      ( cmd //c echo "$func_to_host_pathlist_tmp1" ) 2>/dev/null |
+	      $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"`
+            ;;
+          *cygwin* )
+            func_to_host_pathlist_result=`cygpath -w -p "$func_to_host_pathlist_tmp1" |
+              $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          * )
+            # unfortunately, winepath doesn't convert pathlists
+            func_to_host_pathlist_result=""
+            func_to_host_pathlist_oldIFS=$IFS
+            IFS=:
+            for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do
+              IFS=$func_to_host_pathlist_oldIFS
+              if test -n "$func_to_host_pathlist_f" ; then
+                func_to_host_path "$func_to_host_pathlist_f"
+                if test -n "$func_to_host_path_result" ; then
+                  if test -z "$func_to_host_pathlist_result" ; then
+                    func_to_host_pathlist_result="$func_to_host_path_result"
+                  else
+                    func_append func_to_host_pathlist_result ";$func_to_host_path_result"
+                  fi
+                fi
+              fi
+            done
+            IFS=$func_to_host_pathlist_oldIFS
+            ;;
+        esac
+        if test -z "$func_to_host_pathlist_result"; then
+          func_error "Could not determine the host path(s) corresponding to"
+          func_error "  \`$1'"
+          func_error "Continuing, but uninstalled executables may not work."
+          # Fallback. This may break if $1 contains DOS-style drive
+          # specifications. The fix is not to complicate the expression
+          # below, but for the user to provide a working wine installation
+          # with winepath so that path translation in the cross-to-mingw
+          # case works properly.
+          lt_replace_pathsep_nix_to_dos="s|:|;|g"
+          func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\
+            $SED -e "$lt_replace_pathsep_nix_to_dos"`
+        fi
+        # Now, add the leading and trailing path separators back
+        case "$1" in
+          :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result"
+            ;;
+        esac
+        case "$1" in
+          *: ) func_append func_to_host_pathlist_result ";"
+            ;;
+        esac
+        ;;
+    esac
+  fi
+}
+# end: func_to_host_pathlist
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+	cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "$SHELL $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+	    cat <<"EOF"
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* declarations of non-ANSI functions */
+#if defined(__MINGW32__)
+# ifdef __STRICT_ANSI__
+int _putenv (const char *);
+# endif
+#elif defined(__CYGWIN__)
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+/* #elif defined (other platforms) ... */
+#endif
+
+/* portability defines, excluding path handling macros */
+#if defined(_MSC_VER)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+# define S_IXUSR _S_IEXEC
+# ifndef _INTPTR_T_DEFINED
+#  define _INTPTR_T_DEFINED
+#  define intptr_t int
+# endif
+#elif defined(__MINGW32__)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+#elif defined(__CYGWIN__)
+# define HAVE_SETENV
+# define FOPEN_WB "wb"
+/* #elif defined (other platforms) ... */
+#endif
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+/* path handling portability macros */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+#undef LTWRAPPER_DEBUGPRINTF
+#if defined LT_DEBUGWRAPPER
+# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args
+static void
+ltwrapper_debugprintf (const char *fmt, ...)
+{
+    va_list args;
+    va_start (args, fmt);
+    (void) vfprintf (stderr, fmt, args);
+    va_end (args);
+}
+#else
+# define LTWRAPPER_DEBUGPRINTF(args)
+#endif
+
+const char *program_name = NULL;
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+char **prepare_spawn (char **argv);
+void lt_dump_script (FILE *f);
+EOF
+
+	    cat <<EOF
+const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+	    if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+              func_to_host_pathlist "$temp_rpath"
+	      cat <<EOF
+const char * LIB_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * LIB_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test -n "$dllsearchpath"; then
+              func_to_host_pathlist "$dllsearchpath:"
+	      cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test "$fast_install" = yes; then
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+	    else
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+	    fi
+
+
+	    cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX         "--lt-"
+#define LTWRAPPER_OPTION_PREFIX_LENGTH  5
+
+static const size_t opt_prefix_len         = LTWRAPPER_OPTION_PREFIX_LENGTH;
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+
+static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int  newargc;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *actual_cwrapper_name;
+  char *target_name;
+  char *lt_argv_zero;
+  intptr_t rval = 127;
+
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) argv[0]      : %s\n", argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
+
+  /* very simple arg parsing; don't want to rely on getopt */
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], dumpscript_opt) == 0)
+	{
+EOF
+	    case "$host" in
+	      *mingw* | *cygwin* )
+		# make stdout use "unix" line endings
+		echo "          setmode(1,_O_BINARY);"
+		;;
+	      esac
+
+	    cat <<"EOF"
+	  lt_dump_script (stdout);
+	  return 0;
+	}
+    }
+
+  newargz = XMALLOC (char *, argc + 1);
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal ("Couldn't find %s", argv[0]);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
+			  tmp_pathspec));
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
+			  actual_cwrapper_path));
+  XFREE (tmp_pathspec);
+
+  actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+  /* wrapper name transforms */
+  strendzap (actual_cwrapper_name, ".exe");
+  tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+  XFREE (actual_cwrapper_name);
+  actual_cwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  /* target_name transforms -- use actual target program name; might have lt- prefix */
+  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+  strendzap (target_name, ".exe");
+  tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+  XFREE (target_name);
+  target_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
+			  target_name));
+EOF
+
+	    cat <<EOF
+  newargz[0] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+		    strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+  strcpy (newargz[0], actual_cwrapper_path);
+  strcat (newargz[0], "$objdir");
+  strcat (newargz[0], "/");
+EOF
+
+	    cat <<"EOF"
+  /* stop here, and copy so we don't have to do this twice */
+  tmp_pathspec = xstrdup (newargz[0]);
+
+  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+  strcat (newargz[0], actual_cwrapper_name);
+
+  /* DO want the lt- prefix here if it exists, so use target_name */
+  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+  XFREE (tmp_pathspec);
+  tmp_pathspec = NULL;
+EOF
+
+	    case $host_os in
+	      mingw*)
+	    cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[0], '\\')) != NULL)
+      {
+	*p = '/';
+      }
+    while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+      {
+	*p = '/';
+      }
+  }
+EOF
+	    ;;
+	    esac
+
+	    cat <<"EOF"
+  XFREE (target_name);
+  XFREE (actual_cwrapper_path);
+  XFREE (actual_cwrapper_name);
+
+  lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+  lt_setenv ("DUALCASE", "1");  /* for MSK sh */
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+
+  newargc=0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal ("Unrecognized option in %s namespace: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
+    }
+  newargz[++newargc] = NULL;
+
+  LTWRAPPER_DEBUGPRINTF     (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>")));
+  for (i = 0; i < newargc; i++)
+    {
+      LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d]   : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>")));
+    }
+
+EOF
+
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+  /* execv doesn't actually work on mingw as expected on unix */
+  newargz = prepare_spawn (newargz);
+  rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+  if (rval == -1)
+    {
+      /* failed to start process */
+      LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno));
+      return 127;
+    }
+  return rval;
+EOF
+		;;
+	      *)
+		cat <<"EOF"
+  execv (lt_argv_zero, newargz);
+  return rval; /* =127, but avoids unused variable warning */
+EOF
+		;;
+	    esac
+
+	    cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+  void *p = (void *) malloc (num);
+  if (!p)
+    lt_fatal ("Memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+			  string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable (const char *path)
+{
+  struct stat st;
+
+  LTWRAPPER_DEBUGPRINTF (("(check_executable)  : %s\n",
+			  path ? (*path ? path : "EMPTY!") : "NULL!"));
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0)
+      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+    return 1;
+  else
+    return 0;
+}
+
+int
+make_executable (const char *path)
+{
+  int rval = 0;
+  struct stat st;
+
+  LTWRAPPER_DEBUGPRINTF (("(make_executable)   : %s\n",
+			  path ? (*path ? path : "EMPTY!") : "NULL!"));
+  if ((!path) || (!*path))
+    return 0;
+
+  if (stat (path, &st) >= 0)
+    {
+      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+    }
+  return rval;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise
+   Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+  int has_slash = 0;
+  const char *p;
+  const char *p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char *concat_name;
+
+  LTWRAPPER_DEBUGPRINTF (("(find_executable)   : %s\n",
+			  wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"));
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable (concat_name))
+	return concat_name;
+      XFREE (concat_name);
+    }
+  else
+    {
+#endif
+      if (IS_DIR_SEPARATOR (wrapper[0]))
+	{
+	  concat_name = xstrdup (wrapper);
+	  if (check_executable (concat_name))
+	    return concat_name;
+	  XFREE (concat_name);
+	}
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+    }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+      {
+	has_slash = 1;
+	break;
+      }
+  if (!has_slash)
+    {
+      /* no slashes; search PATH */
+      const char *path = getenv ("PATH");
+      if (path != NULL)
+	{
+	  for (p = path; *p; p = p_next)
+	    {
+	      const char *q;
+	      size_t p_len;
+	      for (q = p; *q; q++)
+		if (IS_PATH_SEPARATOR (*q))
+		  break;
+	      p_len = q - p;
+	      p_next = (*q == '\0' ? q : q + 1);
+	      if (p_len == 0)
+		{
+		  /* empty path: current directory */
+		  if (getcwd (tmp, LT_PATHMAX) == NULL)
+		    lt_fatal ("getcwd failed");
+		  tmp_len = strlen (tmp);
+		  concat_name =
+		    XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, tmp, tmp_len);
+		  concat_name[tmp_len] = '/';
+		  strcpy (concat_name + tmp_len + 1, wrapper);
+		}
+	      else
+		{
+		  concat_name =
+		    XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, p, p_len);
+		  concat_name[p_len] = '/';
+		  strcpy (concat_name + p_len + 1, wrapper);
+		}
+	      if (check_executable (concat_name))
+		return concat_name;
+	      XFREE (concat_name);
+	    }
+	}
+      /* not found in PATH; assume curdir */
+    }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal ("getcwd failed");
+  tmp_len = strlen (tmp);
+  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable (concat_name))
+    return concat_name;
+  XFREE (concat_name);
+  return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+  return xstrdup (pathspec);
+#else
+  char buf[LT_PATHMAX];
+  struct stat s;
+  char *tmp_pathspec = xstrdup (pathspec);
+  char *p;
+  int has_symlinks = 0;
+  while (strlen (tmp_pathspec) && !has_symlinks)
+    {
+      LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n",
+			      tmp_pathspec));
+      if (lstat (tmp_pathspec, &s) == 0)
+	{
+	  if (S_ISLNK (s.st_mode) != 0)
+	    {
+	      has_symlinks = 1;
+	      break;
+	    }
+
+	  /* search backwards for last DIR_SEPARATOR */
+	  p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+	  while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    p--;
+	  if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    {
+	      /* no more DIR_SEPARATORS left */
+	      break;
+	    }
+	  *p = '\0';
+	}
+      else
+	{
+	  char *errstr = strerror (errno);
+	  lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr);
+	}
+    }
+  XFREE (tmp_pathspec);
+
+  if (!has_symlinks)
+    {
+      return xstrdup (pathspec);
+    }
+
+  tmp_pathspec = realpath (pathspec, buf);
+  if (tmp_pathspec == 0)
+    {
+      lt_fatal ("Could not follow symlinks for %s", pathspec);
+    }
+  return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert (str != NULL);
+  assert (pat != NULL);
+
+  len = strlen (str);
+  patlen = strlen (pat);
+
+  if (patlen <= len)
+    {
+      str += len - patlen;
+      if (strcmp (str, pat) == 0)
+	*str = '\0';
+    }
+  return str;
+}
+
+static void
+lt_error_core (int exit_status, const char *mode,
+	       const char *message, va_list ap)
+{
+  fprintf (stderr, "%s: %s: ", program_name, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  va_end (ap);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+  {
+#ifdef HAVE_SETENV
+    /* always make a copy, for consistency with !HAVE_SETENV */
+    char *str = xstrdup (value);
+    setenv (name, str, 1);
+#else
+    int len = strlen (name) + 1 + strlen (value) + 1;
+    char *str = XMALLOC (char, len);
+    sprintf (str, "%s=%s", name, value);
+    if (putenv (str) != EXIT_SUCCESS)
+      {
+        XFREE (str);
+      }
+#endif
+  }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+  char *new_value;
+  if (orig_value && *orig_value)
+    {
+      int orig_value_len = strlen (orig_value);
+      int add_len = strlen (add);
+      new_value = XMALLOC (char, add_len + orig_value_len + 1);
+      if (to_end)
+        {
+          strcpy (new_value, orig_value);
+          strcpy (new_value + orig_value_len, add);
+        }
+      else
+        {
+          strcpy (new_value, add);
+          strcpy (new_value + add_len, orig_value);
+        }
+    }
+  else
+    {
+      new_value = xstrdup (add);
+    }
+  return new_value;
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      /* some systems can't cope with a ':'-terminated path #' */
+      int len = strlen (new_value);
+      while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+        {
+          new_value[len-1] = '\0';
+        }
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+EOF
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+
+/* Prepares an argument vector before calling spawn().
+   Note that spawn() does not by itself call the command interpreter
+     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+         GetVersionEx(&v);
+         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+      }) ? "cmd.exe" : "command.com").
+   Instead it simply concatenates the arguments, separated by ' ', and calls
+   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
+   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+   special way:
+   - Space and tab are interpreted as delimiters. They are not treated as
+     delimiters if they are surrounded by double quotes: "...".
+   - Unescaped double quotes are removed from the input. Their only effect is
+     that within double quotes, space and tab are treated like normal
+     characters.
+   - Backslashes not followed by double quotes are not special.
+   - But 2*n+1 backslashes followed by a double quote become
+     n backslashes followed by a double quote (n >= 0):
+       \" -> "
+       \\\" -> \"
+       \\\\\" -> \\"
+ */
+#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+char **
+prepare_spawn (char **argv)
+{
+  size_t argc;
+  char **new_argv;
+  size_t i;
+
+  /* Count number of arguments.  */
+  for (argc = 0; argv[argc] != NULL; argc++)
+    ;
+
+  /* Allocate new argument vector.  */
+  new_argv = XMALLOC (char *, argc + 1);
+
+  /* Put quoted arguments into the new argument vector.  */
+  for (i = 0; i < argc; i++)
+    {
+      const char *string = argv[i];
+
+      if (string[0] == '\0')
+	new_argv[i] = xstrdup ("\"\"");
+      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+	{
+	  int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+	  size_t length;
+	  unsigned int backslashes;
+	  const char *s;
+	  char *quoted_string;
+	  char *p;
+
+	  length = 0;
+	  backslashes = 0;
+	  if (quote_around)
+	    length++;
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		length += backslashes + 1;
+	      length++;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    length += backslashes + 1;
+
+	  quoted_string = XMALLOC (char, length + 1);
+
+	  p = quoted_string;
+	  backslashes = 0;
+	  if (quote_around)
+	    *p++ = '"';
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		{
+		  unsigned int j;
+		  for (j = backslashes + 1; j > 0; j--)
+		    *p++ = '\\';
+		}
+	      *p++ = c;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    {
+	      unsigned int j;
+	      for (j = backslashes; j > 0; j--)
+		*p++ = '\\';
+	      *p++ = '"';
+	    }
+	  *p = '\0';
+
+	  new_argv[i] = quoted_string;
+	}
+      else
+	new_argv[i] = (char *) string;
+    }
+  new_argv[argc] = NULL;
+
+  return new_argv;
+}
+EOF
+		;;
+	    esac
+
+            cat <<"EOF"
+void lt_dump_script (FILE* f)
+{
+EOF
+	    func_emit_wrapper yes |
+              $SED -e 's/\([\\"]\)/\\\1/g' \
+	           -e 's/^/  fputs ("/' -e 's/$/\\n", f);/'
+
+            cat <<"EOF"
+}
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_win32_import_lib_p ARG
+# True if ARG is an import lib, as indicated by $file_magic_cmd
+func_win32_import_lib_p ()
+{
+    $opt_debug
+    case `eval "$file_magic_cmd \"\$1\" 2>/dev/null" | $SED -e 10q` in
+    *import*) : ;;
+    *) false ;;
+    esac
+}
+
+# func_mode_link arg...
+func_mode_link ()
+{
+    $opt_debug
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args=$nonopt
+    base_compile="$nonopt $@"
+    compile_command=$nonopt
+    finalize_command=$nonopt
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+    new_inherited_linker_flags=
+
+    avoid_version=no
+    bindir=
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+    weak_libs=
+    single_module="${wl}-single_module"
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	break
+	;;
+      -all-static | -static | -static-libtool-libs)
+	case $arg in
+	-all-static)
+	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+	    func_warning "complete static linking is impossible in this configuration"
+	  fi
+	  if test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	-static)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=built
+	  ;;
+	-static-libtool-libs)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	esac
+	build_libtool_libs=no
+	build_old_libs=yes
+	break
+	;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      func_quote_for_eval "$arg"
+      qarg=$func_quote_for_eval_unquoted_result
+      func_append libtool_args " $func_quote_for_eval_result"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+	case $prev in
+	output)
+	  func_append compile_command " @OUTPUT@"
+	  func_append finalize_command " @OUTPUT@"
+	  ;;
+	esac
+
+	case $prev in
+	bindir)
+	  bindir="$arg"
+	  prev=
+	  continue
+	  ;;
+	dlfiles|dlprefiles)
+	  if test "$preload" = no; then
+	    # Add the symbol object into the linking commands.
+	    func_append compile_command " @SYMFILE@"
+	    func_append finalize_command " @SYMFILE@"
+	    preload=yes
+	  fi
+	  case $arg in
+	  *.la | *.lo) ;;  # We handle these cases below.
+	  force)
+	    if test "$dlself" = no; then
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  self)
+	    if test "$prev" = dlprefiles; then
+	      dlself=yes
+	    elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+	      dlself=yes
+	    else
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  *)
+	    if test "$prev" = dlfiles; then
+	      dlfiles="$dlfiles $arg"
+	    else
+	      dlprefiles="$dlprefiles $arg"
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  esac
+	  ;;
+	expsyms)
+	  export_symbols="$arg"
+	  test -f "$arg" \
+	    || func_fatal_error "symbol file \`$arg' does not exist"
+	  prev=
+	  continue
+	  ;;
+	expsyms_regex)
+	  export_symbols_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	framework)
+	  case $host in
+	    *-*-darwin*)
+	      case "$deplibs " in
+		*" $qarg.ltframework "*) ;;
+		*) deplibs="$deplibs $qarg.ltframework" # this is fixed later
+		   ;;
+	      esac
+	      ;;
+	  esac
+	  prev=
+	  continue
+	  ;;
+	inst_prefix)
+	  inst_prefix_dir="$arg"
+	  prev=
+	  continue
+	  ;;
+	objectlist)
+	  if test -f "$arg"; then
+	    save_arg=$arg
+	    moreargs=
+	    for fil in `cat "$save_arg"`
+	    do
+#	      moreargs="$moreargs $fil"
+	      arg=$fil
+	      # A libtool-controlled object.
+
+	      # Check to see that this really is a libtool object.
+	      if func_lalib_unsafe_p "$arg"; then
+		pic_object=
+		non_pic_object=
+
+		# Read the .lo file
+		func_source "$arg"
+
+		if test -z "$pic_object" ||
+		   test -z "$non_pic_object" ||
+		   test "$pic_object" = none &&
+		   test "$non_pic_object" = none; then
+		  func_fatal_error "cannot find name of object for \`$arg'"
+		fi
+
+		# Extract subdirectory from the argument.
+		func_dirname "$arg" "/" ""
+		xdir="$func_dirname_result"
+
+		if test "$pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  pic_object="$xdir$pic_object"
+
+		  if test "$prev" = dlfiles; then
+		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		      dlfiles="$dlfiles $pic_object"
+		      prev=
+		      continue
+		    else
+		      # If libtool objects are unsupported, then we need to preload.
+		      prev=dlprefiles
+		    fi
+		  fi
+
+		  # CHECK ME:  I think I busted this.  -Ossama
+		  if test "$prev" = dlprefiles; then
+		    # Preload the old-style object.
+		    dlprefiles="$dlprefiles $pic_object"
+		    prev=
+		  fi
+
+		  # A PIC object.
+		  func_append libobjs " $pic_object"
+		  arg="$pic_object"
+		fi
+
+		# Non-PIC object.
+		if test "$non_pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  non_pic_object="$xdir$non_pic_object"
+
+		  # A standard non-PIC object
+		  func_append non_pic_objects " $non_pic_object"
+		  if test -z "$pic_object" || test "$pic_object" = none ; then
+		    arg="$non_pic_object"
+		  fi
+		else
+		  # If the PIC object exists, use it instead.
+		  # $xdir was prepended to $pic_object above.
+		  non_pic_object="$pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+		fi
+	      else
+		# Only an error if not doing a dry-run.
+		if $opt_dry_run; then
+		  # Extract subdirectory from the argument.
+		  func_dirname "$arg" "/" ""
+		  xdir="$func_dirname_result"
+
+		  func_lo2o "$arg"
+		  pic_object=$xdir$objdir/$func_lo2o_result
+		  non_pic_object=$xdir$func_lo2o_result
+		  func_append libobjs " $pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+	        else
+		  func_fatal_error "\`$arg' is not a valid libtool object"
+		fi
+	      fi
+	    done
+	  else
+	    func_fatal_error "link input file \`$arg' does not exist"
+	  fi
+	  arg=$save_arg
+	  prev=
+	  continue
+	  ;;
+	precious_regex)
+	  precious_files_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	release)
+	  release="-$arg"
+	  prev=
+	  continue
+	  ;;
+	rpath | xrpath)
+	  # We need an absolute path.
+	  case $arg in
+	  [\\/]* | [A-Za-z]:[\\/]*) ;;
+	  *)
+	    func_fatal_error "only absolute run-paths are allowed"
+	    ;;
+	  esac
+	  if test "$prev" = rpath; then
+	    case "$rpath " in
+	    *" $arg "*) ;;
+	    *) rpath="$rpath $arg" ;;
+	    esac
+	  else
+	    case "$xrpath " in
+	    *" $arg "*) ;;
+	    *) xrpath="$xrpath $arg" ;;
+	    esac
+	  fi
+	  prev=
+	  continue
+	  ;;
+	shrext)
+	  shrext_cmds="$arg"
+	  prev=
+	  continue
+	  ;;
+	weak)
+	  weak_libs="$weak_libs $arg"
+	  prev=
+	  continue
+	  ;;
+	xcclinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xcompiler)
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xlinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $wl$qarg"
+	  prev=
+	  func_append compile_command " $wl$qarg"
+	  func_append finalize_command " $wl$qarg"
+	  continue
+	  ;;
+	*)
+	  eval "$prev=\"\$arg\""
+	  prev=
+	  continue
+	  ;;
+	esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+	if test -n "$link_static_flag"; then
+	  # See comment for -static flag below, for more details.
+	  func_append compile_command " $link_static_flag"
+	  func_append finalize_command " $link_static_flag"
+	fi
+	continue
+	;;
+
+      -allow-undefined)
+	# FIXME: remove this flag sometime in the future.
+	func_fatal_error "\`-allow-undefined' must not be used because it is the default"
+	;;
+
+      -avoid-version)
+	avoid_version=yes
+	continue
+	;;
+
+      -bindir)
+	prev=bindir
+	continue
+	;;
+
+      -dlopen)
+	prev=dlfiles
+	continue
+	;;
+
+      -dlpreopen)
+	prev=dlprefiles
+	continue
+	;;
+
+      -export-dynamic)
+	export_dynamic=yes
+	continue
+	;;
+
+      -export-symbols | -export-symbols-regex)
+	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	  func_fatal_error "more than one -exported-symbols argument is not allowed"
+	fi
+	if test "X$arg" = "X-export-symbols"; then
+	  prev=expsyms
+	else
+	  prev=expsyms_regex
+	fi
+	continue
+	;;
+
+      -framework)
+	prev=framework
+	continue
+	;;
+
+      -inst-prefix-dir)
+	prev=inst_prefix
+	continue
+	;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+	case $with_gcc/$host in
+	no/*-*-irix* | /*-*-irix*)
+	  func_append compile_command " $arg"
+	  func_append finalize_command " $arg"
+	  ;;
+	esac
+	continue
+	;;
+
+      -L*)
+	func_stripname '-L' '' "$arg"
+	dir=$func_stripname_result
+	if test -z "$dir"; then
+	  if test "$#" -gt 0; then
+	    func_fatal_error "require no space between \`-L' and \`$1'"
+	  else
+	    func_fatal_error "need path for \`-L' option"
+	  fi
+	fi
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  absdir=`cd "$dir" && pwd`
+	  test -z "$absdir" && \
+	    func_fatal_error "cannot determine absolute directory name of \`$dir'"
+	  dir="$absdir"
+	  ;;
+	esac
+	case "$deplibs " in
+	*" -L$dir "*) ;;
+	*)
+	  deplibs="$deplibs -L$dir"
+	  lib_search_path="$lib_search_path $dir"
+	  ;;
+	esac
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$dir:"*) ;;
+	  ::) dllsearchpath=$dir;;
+	  *) dllsearchpath="$dllsearchpath:$dir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  esac
+	  ;;
+	esac
+	continue
+	;;
+
+      -l*)
+	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
+	    # These systems don't actually have a C or math library (as such)
+	    continue
+	    ;;
+	  *-*-os2*)
+	    # These systems don't actually have a C library (as such)
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C and math libraries are in the System framework
+	    deplibs="$deplibs System.ltframework"
+	    continue
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-linux*)
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  esac
+	elif test "X$arg" = "X-lc_r"; then
+	 case $host in
+	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	   # Do not include libc_r directly, use -pthread flag.
+	   continue
+	   ;;
+	 esac
+	fi
+	deplibs="$deplibs $arg"
+	continue
+	;;
+
+      -module)
+	module=yes
+	continue
+	;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      # Darwin uses the -arch flag to determine output architecture.
+      -model|-arch|-isysroot)
+	compiler_flags="$compiler_flags $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	prev=xcompiler
+	continue
+	;;
+
+      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+	compiler_flags="$compiler_flags $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	case "$new_inherited_linker_flags " in
+	    *" $arg "*) ;;
+	    * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;;
+	esac
+	continue
+	;;
+
+      -multi_module)
+	single_module="${wl}-multi_module"
+	continue
+	;;
+
+      -no-fast-install)
+	fast_install=no
+	continue
+	;;
+
+      -no-install)
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+	  # The PATH hackery in wrapper scripts is required on Windows
+	  # and Darwin in order for the loader to find any dlls it needs.
+	  func_warning "\`-no-install' is ignored for $host"
+	  func_warning "assuming \`-no-fast-install' instead"
+	  fast_install=no
+	  ;;
+	*) no_install=yes ;;
+	esac
+	continue
+	;;
+
+      -no-undefined)
+	allow_undefined=no
+	continue
+	;;
+
+      -objectlist)
+	prev=objectlist
+	continue
+	;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+	prev=precious_regex
+	continue
+	;;
+
+      -release)
+	prev=release
+	continue
+	;;
+
+      -rpath)
+	prev=rpath
+	continue
+	;;
+
+      -R)
+	prev=xrpath
+	continue
+	;;
+
+      -R*)
+	func_stripname '-R' '' "$arg"
+	dir=$func_stripname_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  func_fatal_error "only absolute run-paths are allowed"
+	  ;;
+	esac
+	case "$xrpath " in
+	*" $dir "*) ;;
+	*) xrpath="$xrpath $dir" ;;
+	esac
+	continue
+	;;
+
+      -shared)
+	# The effects of -shared are defined in a previous loop.
+	continue
+	;;
+
+      -shrext)
+	prev=shrext
+	continue
+	;;
+
+      -static | -static-libtool-libs)
+	# The effects of -static are defined in a previous loop.
+	# We used to do the same as -all-static on platforms that
+	# didn't have a PIC flag, but the assumption that the effects
+	# would be equivalent was wrong.  It would break on at least
+	# Digital Unix and AIX.
+	continue
+	;;
+
+      -thread-safe)
+	thread_safe=yes
+	continue
+	;;
+
+      -version-info)
+	prev=vinfo
+	continue
+	;;
+
+      -version-number)
+	prev=vinfo
+	vinfo_number=yes
+	continue
+	;;
+
+      -weak)
+        prev=weak
+	continue
+	;;
+
+      -Wc,*)
+	func_stripname '-Wc,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  arg="$arg $func_quote_for_eval_result"
+	  compiler_flags="$compiler_flags $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Wl,*)
+	func_stripname '-Wl,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  arg="$arg $wl$func_quote_for_eval_result"
+	  compiler_flags="$compiler_flags $wl$func_quote_for_eval_result"
+	  linker_flags="$linker_flags $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Xcompiler)
+	prev=xcompiler
+	continue
+	;;
+
+      -Xlinker)
+	prev=xlinker
+	continue
+	;;
+
+      -XCClinker)
+	prev=xcclinker
+	continue
+	;;
+
+      # -msg_* for osf cc
+      -msg_*)
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+      # -r[0-9][0-9]* specifies the processor on the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+      # +DA*, +DD* enable 64-bit mode on the HP compiler
+      # -q* pass through compiler args for the IBM compiler
+      # -m*, -t[45]*, -txscale* pass through architecture-specific
+      # compiler args for GCC
+      # -F/path gives path to uninstalled frameworks, gcc on darwin
+      # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
+      # @file GCC response files
+      # -tp=* Portland pgcc target processor selection
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+        func_append compile_command " $arg"
+        func_append finalize_command " $arg"
+        compiler_flags="$compiler_flags $arg"
+        continue
+        ;;
+
+      # Some other compiler flag.
+      -* | +*)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      *.$objext)
+	# A standard object.
+	objs="$objs $arg"
+	;;
+
+      *.lo)
+	# A libtool-controlled object.
+
+	# Check to see that this really is a libtool object.
+	if func_lalib_unsafe_p "$arg"; then
+	  pic_object=
+	  non_pic_object=
+
+	  # Read the .lo file
+	  func_source "$arg"
+
+	  if test -z "$pic_object" ||
+	     test -z "$non_pic_object" ||
+	     test "$pic_object" = none &&
+	     test "$non_pic_object" = none; then
+	    func_fatal_error "cannot find name of object for \`$arg'"
+	  fi
+
+	  # Extract subdirectory from the argument.
+	  func_dirname "$arg" "/" ""
+	  xdir="$func_dirname_result"
+
+	  if test "$pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    pic_object="$xdir$pic_object"
+
+	    if test "$prev" = dlfiles; then
+	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		dlfiles="$dlfiles $pic_object"
+		prev=
+		continue
+	      else
+		# If libtool objects are unsupported, then we need to preload.
+		prev=dlprefiles
+	      fi
+	    fi
+
+	    # CHECK ME:  I think I busted this.  -Ossama
+	    if test "$prev" = dlprefiles; then
+	      # Preload the old-style object.
+	      dlprefiles="$dlprefiles $pic_object"
+	      prev=
+	    fi
+
+	    # A PIC object.
+	    func_append libobjs " $pic_object"
+	    arg="$pic_object"
+	  fi
+
+	  # Non-PIC object.
+	  if test "$non_pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    non_pic_object="$xdir$non_pic_object"
+
+	    # A standard non-PIC object
+	    func_append non_pic_objects " $non_pic_object"
+	    if test -z "$pic_object" || test "$pic_object" = none ; then
+	      arg="$non_pic_object"
+	    fi
+	  else
+	    # If the PIC object exists, use it instead.
+	    # $xdir was prepended to $pic_object above.
+	    non_pic_object="$pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  fi
+	else
+	  # Only an error if not doing a dry-run.
+	  if $opt_dry_run; then
+	    # Extract subdirectory from the argument.
+	    func_dirname "$arg" "/" ""
+	    xdir="$func_dirname_result"
+
+	    func_lo2o "$arg"
+	    pic_object=$xdir$objdir/$func_lo2o_result
+	    non_pic_object=$xdir$func_lo2o_result
+	    func_append libobjs " $pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  else
+	    func_fatal_error "\`$arg' is not a valid libtool object"
+	  fi
+	fi
+	;;
+
+      *.$libext)
+	# An archive.
+	deplibs="$deplibs $arg"
+	old_deplibs="$old_deplibs $arg"
+	continue
+	;;
+
+      *.la)
+	# A libtool-controlled library.
+
+	if test "$prev" = dlfiles; then
+	  # This library was specified with -dlopen.
+	  dlfiles="$dlfiles $arg"
+	  prev=
+	elif test "$prev" = dlprefiles; then
+	  # The library was specified with -dlpreopen.
+	  dlprefiles="$dlprefiles $arg"
+	  prev=
+	else
+	  deplibs="$deplibs $arg"
+	fi
+	continue
+	;;
+
+      # Some other compiler argument.
+      *)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+      fi
+    done # argument parsing loop
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prevarg' option requires an argument"
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval "arg=\"$export_dynamic_flag_spec\""
+      func_append compile_command " $arg"
+      func_append finalize_command " $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    func_basename "$output"
+    outputname="$func_basename_result"
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval "sys_lib_search_path=\"$sys_lib_search_path_spec\""
+    eval "sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\""
+
+    func_dirname "$output" "/" ""
+    output_objdir="$func_dirname_result$objdir"
+    # Create the object directory.
+    func_mkdir_p "$output_objdir"
+
+    # Determine the type of output
+    case $output in
+    "")
+      func_fatal_help "you must specify an output file"
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if $opt_duplicate_deps ; then
+	case "$libs " in
+	*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	esac
+      fi
+      libs="$libs $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if $opt_duplicate_compiler_generated_deps; then
+	for pre_post_dep in $predeps $postdeps; do
+	  case "$pre_post_deps " in
+	  *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+	  esac
+	  pre_post_deps="$pre_post_deps $pre_post_dep"
+	done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+
+    case $linkmode in
+    lib)
+	passes="conv dlpreopen link"
+	for file in $dlfiles $dlprefiles; do
+	  case $file in
+	  *.la) ;;
+	  *)
+	    func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
+	    ;;
+	  esac
+	done
+	;;
+    prog)
+	compile_deplibs=
+	finalize_deplibs=
+	alldeplibs=no
+	newdlfiles=
+	newdlprefiles=
+	passes="conv scan dlopen dlpreopen link"
+	;;
+    *)  passes="conv"
+	;;
+    esac
+
+    for pass in $passes; do
+      # The preopen pass in lib mode reverses $deplibs; put it back here
+      # so that -L comes before libs that need it for instance...
+      if test "$linkmode,$pass" = "lib,link"; then
+	## FIXME: Find the place where the list is rebuilt in the wrong
+	##        order, and fix it there properly
+        tmp_deplibs=
+	for deplib in $deplibs; do
+	  tmp_deplibs="$deplib $tmp_deplibs"
+	done
+	deplibs="$tmp_deplibs"
+      fi
+
+      if test "$linkmode,$pass" = "lib,link" ||
+	 test "$linkmode,$pass" = "prog,scan"; then
+	libs="$deplibs"
+	deplibs=
+      fi
+      if test "$linkmode" = prog; then
+	case $pass in
+	dlopen) libs="$dlfiles" ;;
+	dlpreopen) libs="$dlprefiles" ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+	esac
+      fi
+      if test "$linkmode,$pass" = "lib,dlpreopen"; then
+	# Collect and forward deplibs of preopened libtool libs
+	for lib in $dlprefiles; do
+	  # Ignore non-libtool-libs
+	  dependency_libs=
+	  case $lib in
+	  *.la)	func_source "$lib" ;;
+	  esac
+
+	  # Collect preopened libtool deplibs, except any this library
+	  # has declared as weak libs
+	  for deplib in $dependency_libs; do
+	    func_basename "$deplib"
+            deplib_base=$func_basename_result
+	    case " $weak_libs " in
+	    *" $deplib_base "*) ;;
+	    *) deplibs="$deplibs $deplib" ;;
+	    esac
+	  done
+	done
+	libs="$dlprefiles"
+      fi
+      if test "$pass" = dlopen; then
+	# Collect dlpreopened libraries
+	save_deplibs="$deplibs"
+	deplibs=
+      fi
+
+      for deplib in $libs; do
+	lib=
+	found=no
+	case $deplib in
+	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    compiler_flags="$compiler_flags $deplib"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-l*)
+	  if test "$linkmode" != lib && test "$linkmode" != prog; then
+	    func_warning "\`-l' is ignored for archives/objects"
+	    continue
+	  fi
+	  func_stripname '-l' '' "$deplib"
+	  name=$func_stripname_result
+	  if test "$linkmode" = lib; then
+	    searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+	  else
+	    searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+	  fi
+	  for searchdir in $searchdirs; do
+	    for search_ext in .la $std_shrext .so .a; do
+	      # Search the libtool library
+	      lib="$searchdir/lib${name}${search_ext}"
+	      if test -f "$lib"; then
+		if test "$search_ext" = ".la"; then
+		  found=yes
+		else
+		  found=no
+		fi
+		break 2
+	      fi
+	    done
+	  done
+	  if test "$found" != yes; then
+	    # deplib doesn't seem to be a libtool library
+	    if test "$linkmode,$pass" = "prog,link"; then
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      deplibs="$deplib $deplibs"
+	      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    continue
+	  else # deplib is a libtool library
+	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+	    # We need to do some special things here, and not later.
+	    if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	      case " $predeps $postdeps " in
+	      *" $deplib "*)
+		if func_lalib_p "$lib"; then
+		  library_names=
+		  old_library=
+		  func_source "$lib"
+		  for l in $old_library $library_names; do
+		    ll="$l"
+		  done
+		  if test "X$ll" = "X$old_library" ; then # only static version available
+		    found=no
+		    func_dirname "$lib" "" "."
+		    ladir="$func_dirname_result"
+		    lib=$ladir/$old_library
+		    if test "$linkmode,$pass" = "prog,link"; then
+		      compile_deplibs="$deplib $compile_deplibs"
+		      finalize_deplibs="$deplib $finalize_deplibs"
+		    else
+		      deplibs="$deplib $deplibs"
+		      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+		    fi
+		    continue
+		  fi
+		fi
+		;;
+	      *) ;;
+	      esac
+	    fi
+	  fi
+	  ;; # -l
+	*.ltframework)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    deplibs="$deplib $deplibs"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-L*)
+	  case $linkmode in
+	  lib)
+	    deplibs="$deplib $deplibs"
+	    test "$pass" = conv && continue
+	    newdependency_libs="$deplib $newdependency_libs"
+	    func_stripname '-L' '' "$deplib"
+	    newlib_search_path="$newlib_search_path $func_stripname_result"
+	    ;;
+	  prog)
+	    if test "$pass" = conv; then
+	      deplibs="$deplib $deplibs"
+	      continue
+	    fi
+	    if test "$pass" = scan; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    func_stripname '-L' '' "$deplib"
+	    newlib_search_path="$newlib_search_path $func_stripname_result"
+	    ;;
+	  *)
+	    func_warning "\`-L' is ignored for archives/objects"
+	    ;;
+	  esac # linkmode
+	  continue
+	  ;; # -L
+	-R*)
+	  if test "$pass" = link; then
+	    func_stripname '-R' '' "$deplib"
+	    dir=$func_stripname_result
+	    # Make sure the xrpath contains only unique directories.
+	    case "$xrpath " in
+	    *" $dir "*) ;;
+	    *) xrpath="$xrpath $dir" ;;
+	    esac
+	  fi
+	  deplibs="$deplib $deplibs"
+	  continue
+	  ;;
+	*.la) lib="$deplib" ;;
+	*.$libext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	    continue
+	  fi
+	  case $linkmode in
+	  lib)
+	    # Linking convenience modules into shared libraries is allowed,
+	    # but linking other static libraries is non-portable.
+	    case " $dlpreconveniencelibs " in
+	    *" $deplib "*) ;;
+	    *)
+	      valid_a_lib=no
+	      case $deplibs_check_method in
+		match_pattern*)
+		  set dummy $deplibs_check_method; shift
+		  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+		  if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
+		    | $EGREP "$match_pattern_regex" > /dev/null; then
+		    valid_a_lib=yes
+		  fi
+		;;
+		pass_all)
+		  valid_a_lib=yes
+		;;
+	      esac
+	      if test "$valid_a_lib" != yes; then
+		echo
+		$ECHO "*** Warning: Trying to link with static lib archive $deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because the file extensions .$libext of this argument makes me believe"
+		echo "*** that it is just a static archive that I should not use here."
+	      else
+		echo
+		$ECHO "*** Warning: Linking the shared library $output against the"
+		$ECHO "*** static library $deplib is not portable!"
+		deplibs="$deplib $deplibs"
+	      fi
+	      ;;
+	    esac
+	    continue
+	    ;;
+	  prog)
+	    if test "$pass" != link; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    continue
+	    ;;
+	  esac # linkmode
+	  ;; # *.$libext
+	*.lo | *.$objext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	  elif test "$linkmode" = prog; then
+	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	      # If there is no dlopen support or we're linking statically,
+	      # we need to preload.
+	      newdlprefiles="$newdlprefiles $deplib"
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      newdlfiles="$newdlfiles $deplib"
+	    fi
+	  fi
+	  continue
+	  ;;
+	%DEPLIBS%)
+	  alldeplibs=yes
+	  continue
+	  ;;
+	esac # case $deplib
+
+	if test "$found" = yes || test -f "$lib"; then :
+	else
+	  func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
+	fi
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$lib" \
+	  || func_fatal_error "\`$lib' is not a valid libtool archive"
+
+	func_dirname "$lib" "" "."
+	ladir="$func_dirname_result"
+
+	dlname=
+	dlopen=
+	dlpreopen=
+	libdir=
+	library_names=
+	old_library=
+	inherited_linker_flags=
+	# If the library was installed with an old release of libtool,
+	# it will not redefine variables installed, or shouldnotlink
+	installed=yes
+	shouldnotlink=no
+	avoidtemprpath=
+
+
+	# Read the .la file
+	func_source "$lib"
+
+	# Convert "-framework foo" to "foo.ltframework"
+	if test -n "$inherited_linker_flags"; then
+	  tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
+	  for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+	    case " $new_inherited_linker_flags " in
+	      *" $tmp_inherited_linker_flag "*) ;;
+	      *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";;
+	    esac
+	  done
+	fi
+	dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	if test "$linkmode,$pass" = "lib,link" ||
+	   test "$linkmode,$pass" = "prog,scan" ||
+	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+	  test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+	  test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+	fi
+
+	if test "$pass" = conv; then
+	  # Only check for convenience libraries
+	  deplibs="$lib $deplibs"
+	  if test -z "$libdir"; then
+	    if test -z "$old_library"; then
+	      func_fatal_error "cannot find name of link library for \`$lib'"
+	    fi
+	    # It is a libtool convenience library, so add in its objects.
+	    convenience="$convenience $ladir/$objdir/$old_library"
+	    old_convenience="$old_convenience $ladir/$objdir/$old_library"
+	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
+	    func_fatal_error "\`$lib' is not a convenience library"
+	  fi
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    deplibs="$deplib $deplibs"
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+	  continue
+	fi # $pass = conv
+
+
+	# Get the name of the library we link against.
+	linklib=
+	for l in $old_library $library_names; do
+	  linklib="$l"
+	done
+	if test -z "$linklib"; then
+	  func_fatal_error "cannot find name of link library for \`$lib'"
+	fi
+
+	# This library was specified with -dlopen.
+	if test "$pass" = dlopen; then
+	  if test -z "$libdir"; then
+	    func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
+	  fi
+	  if test -z "$dlname" ||
+	     test "$dlopen_support" != yes ||
+	     test "$build_libtool_libs" = no; then
+	    # If there is no dlname, no dlopen support or we're linking
+	    # statically, we need to preload.  We also need to preload any
+	    # dependent libraries so libltdl's deplib preloader doesn't
+	    # bomb out in the load deplibs phase.
+	    dlprefiles="$dlprefiles $lib $dependency_libs"
+	  else
+	    newdlfiles="$newdlfiles $lib"
+	  fi
+	  continue
+	fi # $pass = dlopen
+
+	# We need an absolute path.
+	case $ladir in
+	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+	*)
+	  abs_ladir=`cd "$ladir" && pwd`
+	  if test -z "$abs_ladir"; then
+	    func_warning "cannot determine absolute directory name of \`$ladir'"
+	    func_warning "passing it literally to the linker, although it might fail"
+	    abs_ladir="$ladir"
+	  fi
+	  ;;
+	esac
+	func_basename "$lib"
+	laname="$func_basename_result"
+
+	# Find the relevant object directory and library name.
+	if test "X$installed" = Xyes; then
+	  if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    func_warning "library \`$lib' was moved."
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    libdir="$abs_ladir"
+	  else
+	    dir="$libdir"
+	    absdir="$libdir"
+	  fi
+	  test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+	else
+	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  else
+	    dir="$ladir/$objdir"
+	    absdir="$abs_ladir/$objdir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  fi
+	fi # $installed = yes
+	func_stripname 'lib' '.la' "$laname"
+	name=$func_stripname_result
+
+	# This library was specified with -dlpreopen.
+	if test "$pass" = dlpreopen; then
+	  if test -z "$libdir" && test "$linkmode" = prog; then
+	    func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
+	  fi
+	  # Prefer using a static library (so that no silly _DYNAMIC symbols
+	  # are required to link).
+	  if test -n "$old_library"; then
+	    newdlprefiles="$newdlprefiles $dir/$old_library"
+	    # Keep a list of preopened convenience libraries to check
+	    # that they are being used correctly in the link pass.
+	    test -z "$libdir" && \
+		dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library"
+	  # Otherwise, use the dlname, so that lt_dlopen finds it.
+	  elif test -n "$dlname"; then
+	    newdlprefiles="$newdlprefiles $dir/$dlname"
+	  else
+	    newdlprefiles="$newdlprefiles $dir/$linklib"
+	  fi
+	fi # $pass = dlpreopen
+
+	if test -z "$libdir"; then
+	  # Link the convenience library
+	  if test "$linkmode" = lib; then
+	    deplibs="$dir/$old_library $deplibs"
+	  elif test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$dir/$old_library $compile_deplibs"
+	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
+	  else
+	    deplibs="$lib $deplibs" # used for prog,scan pass
+	  fi
+	  continue
+	fi
+
+
+	if test "$linkmode" = prog && test "$pass" != link; then
+	  newlib_search_path="$newlib_search_path $ladir"
+	  deplibs="$lib $deplibs"
+
+	  linkalldeplibs=no
+	  if test "$link_all_deplibs" != no || test -z "$library_names" ||
+	     test "$build_libtool_libs" = no; then
+	    linkalldeplibs=yes
+	  fi
+
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    case $deplib in
+	    -L*) func_stripname '-L' '' "$deplib"
+	         newlib_search_path="$newlib_search_path $func_stripname_result"
+		 ;;
+	    esac
+	    # Need to link against all dependency_libs?
+	    if test "$linkalldeplibs" = yes; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      # Need to hardcode shared library paths
+	      # or/and link against static libraries
+	      newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done # for deplib
+	  continue
+	fi # $linkmode = prog...
+
+	if test "$linkmode,$pass" = "prog,link"; then
+	  if test -n "$library_names" &&
+	     { { test "$prefer_static_libs" = no ||
+	         test "$prefer_static_libs,$installed" = "built,yes"; } ||
+	       test -z "$old_library"; }; then
+	    # We need to hardcode the library path
+	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+	      # Make sure the rpath contains only unique directories.
+	      case "$temp_rpath:" in
+	      *"$absdir:"*) ;;
+	      *) temp_rpath="$temp_rpath$absdir:" ;;
+	      esac
+	    fi
+
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi # $linkmode,$pass = prog,link...
+
+	  if test "$alldeplibs" = yes &&
+	     { test "$deplibs_check_method" = pass_all ||
+	       { test "$build_libtool_libs" = yes &&
+		 test -n "$library_names"; }; }; then
+	    # We only need to search for static libraries
+	    continue
+	  fi
+	fi
+
+	link_static=no # Whether the deplib will be linked statically
+	use_static_libs=$prefer_static_libs
+	if test "$use_static_libs" = built && test "$installed" = yes; then
+	  use_static_libs=no
+	fi
+	if test -n "$library_names" &&
+	   { test "$use_static_libs" = no || test -z "$old_library"; }; then
+	  case $host in
+	  *cygwin* | *mingw* | *cegcc*)
+	      # No point in relinking DLLs because paths are not encoded
+	      notinst_deplibs="$notinst_deplibs $lib"
+	      need_relink=no
+	    ;;
+	  *)
+	    if test "$installed" = no; then
+	      notinst_deplibs="$notinst_deplibs $lib"
+	      need_relink=yes
+	    fi
+	    ;;
+	  esac
+	  # This is a shared library
+
+	  # Warn about portability, can't link against -module's on some
+	  # systems (darwin).  Don't bleat about dlopened modules though!
+	  dlopenmodule=""
+	  for dlpremoduletest in $dlprefiles; do
+	    if test "X$dlpremoduletest" = "X$lib"; then
+	      dlopenmodule="$dlpremoduletest"
+	      break
+	    fi
+	  done
+	  if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
+	    echo
+	    if test "$linkmode" = prog; then
+	      $ECHO "*** Warning: Linking the executable $output against the loadable module"
+	    else
+	      $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+	    fi
+	    $ECHO "*** $linklib is not portable!"
+	  fi
+	  if test "$linkmode" = lib &&
+	     test "$hardcode_into_libs" = yes; then
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi
+
+	  if test -n "$old_archive_from_expsyms_cmds"; then
+	    # figure out the soname
+	    set dummy $library_names
+	    shift
+	    realname="$1"
+	    shift
+	    eval "libname=\"$libname_spec\""
+	    # use dlname if we got it. it's perfectly good, no?
+	    if test -n "$dlname"; then
+	      soname="$dlname"
+	    elif test -n "$soname_spec"; then
+	      # bleh windows
+	      case $host in
+	      *cygwin* | mingw* | *cegcc*)
+	        func_arith $current - $age
+		major=$func_arith_result
+		versuffix="-$major"
+		;;
+	      esac
+	      eval "soname=\"$soname_spec\""
+	    else
+	      soname="$realname"
+	    fi
+
+	    # Make a new name for the extract_expsyms_cmds to use
+	    soroot="$soname"
+	    func_basename "$soroot"
+	    soname="$func_basename_result"
+	    func_stripname 'lib' '.dll' "$soname"
+	    newlib=libimp-$func_stripname_result.a
+
+	    # If the library has no export list, then create one now
+	    if test -f "$output_objdir/$soname-def"; then :
+	    else
+	      func_verbose "extracting exported symbol list from \`$soname'"
+	      func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+	    fi
+
+	    # Create $newlib
+	    if test -f "$output_objdir/$newlib"; then :; else
+	      func_verbose "generating import library for \`$soname'"
+	      func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+	    fi
+	    # make sure the library variables are pointing to the new library
+	    dir=$output_objdir
+	    linklib=$newlib
+	  fi # test -n "$old_archive_from_expsyms_cmds"
+
+	  if test "$linkmode" = prog || test "$mode" != relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    lib_linked=yes
+	    case $hardcode_action in
+	    immediate | unsupported)
+	      if test "$hardcode_direct" = no; then
+		add="$dir/$linklib"
+		case $host in
+		  *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+		  *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+		  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+		    *-*-unixware7*) add_dir="-L$dir" ;;
+		  *-*-darwin* )
+		    # if the lib is a (non-dlopened) module then we can not
+		    # link against it, someone is ignoring the earlier warnings
+		    if /usr/bin/file -L $add 2> /dev/null |
+			 $GREP ": [^:]* bundle" >/dev/null ; then
+		      if test "X$dlopenmodule" != "X$lib"; then
+			$ECHO "*** Warning: lib $linklib is a module, not a shared library"
+			if test -z "$old_library" ; then
+			  echo
+			  echo "*** And there doesn't seem to be a static archive available"
+			  echo "*** The link will probably fail, sorry"
+			else
+			  add="$dir/$old_library"
+			fi
+		      elif test -n "$old_library"; then
+			add="$dir/$old_library"
+		      fi
+		    fi
+		esac
+	      elif test "$hardcode_minus_L" = no; then
+		case $host in
+		*-*-sunos*) add_shlibpath="$dir" ;;
+		esac
+		add_dir="-L$dir"
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = no; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    relink)
+	      if test "$hardcode_direct" = yes &&
+	         test "$hardcode_direct_absolute" = no; then
+		add="$dir/$linklib"
+	      elif test "$hardcode_minus_L" = yes; then
+		add_dir="-L$absdir"
+		# Try looking first in the location we're being installed to.
+		if test -n "$inst_prefix_dir"; then
+		  case $libdir in
+		    [\\/]*)
+		      add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		      ;;
+		  esac
+		fi
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = yes; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    *) lib_linked=no ;;
+	    esac
+
+	    if test "$lib_linked" != yes; then
+	      func_fatal_configuration "unsupported hardcode properties"
+	    fi
+
+	    if test -n "$add_shlibpath"; then
+	      case :$compile_shlibpath: in
+	      *":$add_shlibpath:"*) ;;
+	      *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+	      esac
+	    fi
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	      if test "$hardcode_direct" != yes &&
+		 test "$hardcode_minus_L" != yes &&
+		 test "$hardcode_shlibpath_var" = yes; then
+		case :$finalize_shlibpath: in
+		*":$libdir:"*) ;;
+		*) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+		esac
+	      fi
+	    fi
+	  fi
+
+	  if test "$linkmode" = prog || test "$mode" = relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    # Finalize command for both is simple: just hardcode it.
+	    if test "$hardcode_direct" = yes &&
+	       test "$hardcode_direct_absolute" = no; then
+	      add="$libdir/$linklib"
+	    elif test "$hardcode_minus_L" = yes; then
+	      add_dir="-L$libdir"
+	      add="-l$name"
+	    elif test "$hardcode_shlibpath_var" = yes; then
+	      case :$finalize_shlibpath: in
+	      *":$libdir:"*) ;;
+	      *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+	      esac
+	      add="-l$name"
+	    elif test "$hardcode_automatic" = yes; then
+	      if test -n "$inst_prefix_dir" &&
+		 test -f "$inst_prefix_dir$libdir/$linklib" ; then
+		add="$inst_prefix_dir$libdir/$linklib"
+	      else
+		add="$libdir/$linklib"
+	      fi
+	    else
+	      # We cannot seem to hardcode it, guess we'll fake it.
+	      add_dir="-L$libdir"
+	      # Try looking first in the location we're being installed to.
+	      if test -n "$inst_prefix_dir"; then
+		case $libdir in
+		  [\\/]*)
+		    add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		    ;;
+		esac
+	      fi
+	      add="-l$name"
+	    fi
+
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	    fi
+	  fi
+	elif test "$linkmode" = prog; then
+	  # Here we assume that one of hardcode_direct or hardcode_minus_L
+	  # is not unsupported.  This is valid on all known static and
+	  # shared platforms.
+	  if test "$hardcode_direct" != unsupported; then
+	    test -n "$old_library" && linklib="$old_library"
+	    compile_deplibs="$dir/$linklib $compile_deplibs"
+	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
+	  else
+	    compile_deplibs="-l$name -L$dir $compile_deplibs"
+	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+	  fi
+	elif test "$build_libtool_libs" = yes; then
+	  # Not a shared library
+	  if test "$deplibs_check_method" != pass_all; then
+	    # We're trying link a shared library against a static one
+	    # but the system doesn't support it.
+
+	    # Just print a warning and add the library to dependency_libs so
+	    # that the program can be linked against the static library.
+	    echo
+	    $ECHO "*** Warning: This system can not link to static lib archive $lib."
+	    echo "*** I have the capability to make that library automatically link in when"
+	    echo "*** you link to this library.  But I can only do this if you have a"
+	    echo "*** shared version of the library, which you do not appear to have."
+	    if test "$module" = yes; then
+	      echo "*** But as you try to build a module library, libtool will still create "
+	      echo "*** a static module, that should work as long as the dlopening application"
+	      echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+	      if test -z "$global_symbol_pipe"; then
+		echo
+		echo "*** However, this would only work if libtool was able to extract symbol"
+		echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+		echo "*** not find such a program.  So, this module is probably useless."
+		echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	      fi
+	      if test "$build_old_libs" = no; then
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  else
+	    deplibs="$dir/$old_library $deplibs"
+	    link_static=yes
+	  fi
+	fi # link shared/static library?
+
+	if test "$linkmode" = lib; then
+	  if test -n "$dependency_libs" &&
+	     { test "$hardcode_into_libs" != yes ||
+	       test "$build_old_libs" = yes ||
+	       test "$link_static" = yes; }; then
+	    # Extract -R from dependency_libs
+	    temp_deplibs=
+	    for libdir in $dependency_libs; do
+	      case $libdir in
+	      -R*) func_stripname '-R' '' "$libdir"
+	           temp_xrpath=$func_stripname_result
+		   case " $xrpath " in
+		   *" $temp_xrpath "*) ;;
+		   *) xrpath="$xrpath $temp_xrpath";;
+		   esac;;
+	      *) temp_deplibs="$temp_deplibs $libdir";;
+	      esac
+	    done
+	    dependency_libs="$temp_deplibs"
+	  fi
+
+	  newlib_search_path="$newlib_search_path $absdir"
+	  # Link against this library
+	  test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+	  # ... and its dependency_libs
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    newdependency_libs="$deplib $newdependency_libs"
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+
+	  if test "$link_all_deplibs" != no; then
+	    # Add the search paths of all dependency libraries
+	    for deplib in $dependency_libs; do
+	      path=
+	      case $deplib in
+	      -L*) path="$deplib" ;;
+	      *.la)
+	        func_dirname "$deplib" "" "."
+		dir="$func_dirname_result"
+		# We need an absolute path.
+		case $dir in
+		[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+		*)
+		  absdir=`cd "$dir" && pwd`
+		  if test -z "$absdir"; then
+		    func_warning "cannot determine absolute directory name of \`$dir'"
+		    absdir="$dir"
+		  fi
+		  ;;
+		esac
+		if $GREP "^installed=no" $deplib > /dev/null; then
+		case $host in
+		*-*-darwin*)
+		  depdepl=
+		  deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+		  if test -n "$deplibrary_names" ; then
+		    for tmp in $deplibrary_names ; do
+		      depdepl=$tmp
+		    done
+		    if test -f "$absdir/$objdir/$depdepl" ; then
+		      depdepl="$absdir/$objdir/$depdepl"
+		      darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+                      if test -z "$darwin_install_name"; then
+                          darwin_install_name=`${OTOOL64} -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
+                      fi
+		      compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+		      linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}"
+		      path=
+		    fi
+		  fi
+		  ;;
+		*)
+		  path="-L$absdir/$objdir"
+		  ;;
+		esac
+		else
+		  libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		  test -z "$libdir" && \
+		    func_fatal_error "\`$deplib' is not a valid libtool archive"
+		  test "$absdir" != "$libdir" && \
+		    func_warning "\`$deplib' seems to be moved"
+
+		  path="-L$absdir"
+		fi
+		;;
+	      esac
+	      case " $deplibs " in
+	      *" $path "*) ;;
+	      *) deplibs="$path $deplibs" ;;
+	      esac
+	    done
+	  fi # link_all_deplibs != no
+	fi # linkmode = lib
+      done # for deplib in $libs
+      if test "$pass" = link; then
+	if test "$linkmode" = "prog"; then
+	  compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+	  finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+	else
+	  compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	fi
+      fi
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+	# Link the dlpreopened libraries before other libraries
+	for deplib in $save_deplibs; do
+	  deplibs="$deplib $deplibs"
+	done
+      fi
+      if test "$pass" != dlopen; then
+	if test "$pass" != conv; then
+	  # Make sure lib_search_path contains only unique directories.
+	  lib_search_path=
+	  for dir in $newlib_search_path; do
+	    case "$lib_search_path " in
+	    *" $dir "*) ;;
+	    *) lib_search_path="$lib_search_path $dir" ;;
+	    esac
+	  done
+	  newlib_search_path=
+	fi
+
+	if test "$linkmode,$pass" != "prog,link"; then
+	  vars="deplibs"
+	else
+	  vars="compile_deplibs finalize_deplibs"
+	fi
+	for var in $vars dependency_libs; do
+	  # Add libraries to $var in reverse order
+	  eval tmp_libs=\$$var
+	  new_libs=
+	  for deplib in $tmp_libs; do
+	    # FIXME: Pedantically, this is the right thing to do, so
+	    #        that some nasty dependency loop isn't accidentally
+	    #        broken:
+	    #new_libs="$deplib $new_libs"
+	    # Pragmatically, this seems to cause very few problems in
+	    # practice:
+	    case $deplib in
+	    -L*) new_libs="$deplib $new_libs" ;;
+	    -R*) ;;
+	    *)
+	      # And here is the reason: when a library appears more
+	      # than once as an explicit dependence of a library, or
+	      # is implicitly linked in more than once by the
+	      # compiler, it is considered special, and multiple
+	      # occurrences thereof are not removed.  Compare this
+	      # with having the same library being listed as a
+	      # dependency of multiple other libraries: in this case,
+	      # we know (pedantically, we assume) the library does not
+	      # need to be listed more than once, so we keep only the
+	      # last copy.  This is not always right, but it is rare
+	      # enough that we require users that really mean to play
+	      # such unportable linking tricks to link the library
+	      # using -Wl,-lname, so that libtool does not consider it
+	      # for duplicate removal.
+	      case " $specialdeplibs " in
+	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
+	      *)
+		case " $new_libs " in
+		*" $deplib "*) ;;
+		*) new_libs="$deplib $new_libs" ;;
+		esac
+		;;
+	      esac
+	      ;;
+	    esac
+	  done
+	  tmp_libs=
+	  for deplib in $new_libs; do
+	    case $deplib in
+	    -L*)
+	      case " $tmp_libs " in
+	      *" $deplib "*) ;;
+	      *) tmp_libs="$tmp_libs $deplib" ;;
+	      esac
+	      ;;
+	    *) tmp_libs="$tmp_libs $deplib" ;;
+	    esac
+	  done
+	  eval $var=\$tmp_libs
+	done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+	case " $predeps $postdeps $compiler_lib_search_path " in
+	*" $i "*)
+	  i=""
+	  ;;
+	esac
+	if test -n "$i" ; then
+	  tmp_libs="$tmp_libs $i"
+	fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+    fi
+    if test "$linkmode" = prog || test "$linkmode" = lib; then
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for archives"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for archives" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for archives"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for archives"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info/-version-number' is ignored for archives"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for archives"
+
+      test -n "$export_symbols$export_symbols_regex" && \
+	func_warning "\`-export-symbols' is ignored for archives"
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs="$objs$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+	func_stripname 'lib' '.la' "$outputname"
+	name=$func_stripname_result
+	eval "shared_ext=\"$shrext_cmds\""
+	eval "libname=\"$libname_spec\""
+	;;
+      *)
+	test "$module" = no && \
+	  func_fatal_help "libtool library \`$output' must begin with \`lib'"
+
+	if test "$need_lib_prefix" != no; then
+	  # Add the "lib" prefix for modules if required
+	  func_stripname '' '.la' "$outputname"
+	  name=$func_stripname_result
+	  eval "shared_ext=\"$shrext_cmds\""
+	  eval "libname=\"$libname_spec\""
+	else
+	  func_stripname '' '.la' "$outputname"
+	  libname=$func_stripname_result
+	fi
+	;;
+      esac
+
+      if test -n "$objs"; then
+	if test "$deplibs_check_method" != pass_all; then
+	  func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
+	else
+	  echo
+	  $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+	  $ECHO "*** objects $objs is not portable!"
+	  libobjs="$libobjs $objs"
+	fi
+      fi
+
+      test "$dlself" != no && \
+	func_warning "\`-dlopen self' is ignored for libtool libraries"
+
+      set dummy $rpath
+      shift
+      test "$#" -gt 1 && \
+	func_warning "ignoring multiple \`-rpath's for a libtool library"
+
+      install_libdir="$1"
+
+      oldlibs=
+      if test -z "$rpath"; then
+	if test "$build_libtool_libs" = yes; then
+	  # Building a libtool convenience library.
+	  # Some compilers have problems with a `.al' extension so
+	  # convenience libraries should have the same extension an
+	  # archive normally would.
+	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
+	  build_libtool_libs=convenience
+	  build_old_libs=yes
+	fi
+
+	test -n "$vinfo" && \
+	  func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
+
+	test -n "$release" && \
+	  func_warning "\`-release' is ignored for convenience libraries"
+      else
+
+	# Parse the version information argument.
+	save_ifs="$IFS"; IFS=':'
+	set dummy $vinfo 0 0 0
+	shift
+	IFS="$save_ifs"
+
+	test -n "$7" && \
+	  func_fatal_help "too many parameters to \`-version-info'"
+
+	# convert absolute version numbers to libtool ages
+	# this retains compatibility with .la files and attempts
+	# to make the code below a bit more comprehensible
+
+	case $vinfo_number in
+	yes)
+	  number_major="$1"
+	  number_minor="$2"
+	  number_revision="$3"
+	  #
+	  # There are really only two kinds -- those that
+	  # use the current revision as the major version
+	  # and those that subtract age and use age as
+	  # a minor version.  But, then there is irix
+	  # which has an extra 1 added just for fun
+	  #
+	  case $version_type in
+	  darwin|linux|osf|windows|none)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_revision"
+	    ;;
+	  freebsd-aout|freebsd-elf|qnx|sunos)
+	    current="$number_major"
+	    revision="$number_minor"
+	    age="0"
+	    ;;
+	  irix|nonstopux)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_minor"
+	    lt_irix_increment=no
+	    ;;
+	  esac
+	  ;;
+	no)
+	  current="$1"
+	  revision="$2"
+	  age="$3"
+	  ;;
+	esac
+
+	# Check that each of the things are valid numbers.
+	case $current in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "CURRENT \`$current' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $revision in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "REVISION \`$revision' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $age in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "AGE \`$age' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	if test "$age" -gt "$current"; then
+	  func_error "AGE \`$age' is greater than the current interface number \`$current'"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	fi
+
+	# Calculate the version variables.
+	major=
+	versuffix=
+	verstring=
+	case $version_type in
+	none) ;;
+
+	darwin)
+	  # Like Linux, but with the current version available in
+	  # verstring for coding it into the library header
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  # Darwin ld doesn't like 0 for these options...
+	  func_arith $current + 1
+	  minor_current=$func_arith_result
+	  xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+	  ;;
+
+	freebsd-aout)
+	  major=".$current"
+	  versuffix=".$current.$revision";
+	  ;;
+
+	freebsd-elf)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	irix | nonstopux)
+	  if test "X$lt_irix_increment" = "Xno"; then
+	    func_arith $current - $age
+	  else
+	    func_arith $current - $age + 1
+	  fi
+	  major=$func_arith_result
+
+	  case $version_type in
+	    nonstopux) verstring_prefix=nonstopux ;;
+	    *)         verstring_prefix=sgi ;;
+	  esac
+	  verstring="$verstring_prefix$major.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$revision
+	  while test "$loop" -ne 0; do
+	    func_arith $revision - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring_prefix$major.$iface:$verstring"
+	  done
+
+	  # Before this point, $major must not contain `.'.
+	  major=.$major
+	  versuffix="$major.$revision"
+	  ;;
+
+	linux)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  ;;
+
+	osf)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix=".$current.$age.$revision"
+	  verstring="$current.$age.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$age
+	  while test "$loop" -ne 0; do
+	    func_arith $current - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring:${iface}.0"
+	  done
+
+	  # Make executables depend on our current version.
+	  verstring="$verstring:${current}.0"
+	  ;;
+
+	qnx)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	sunos)
+	  major=".$current"
+	  versuffix=".$current.$revision"
+	  ;;
+
+	windows)
+	  # Use '-' rather than '.', since we only want one
+	  # extension on DOS 8.3 filesystems.
+	  func_arith $current - $age
+	  major=$func_arith_result
+	  versuffix="-$major"
+	  ;;
+
+	*)
+	  func_fatal_configuration "unknown library version type \`$version_type'"
+	  ;;
+	esac
+
+	# Clear the version info if we defaulted, and they specified a release.
+	if test -z "$vinfo" && test -n "$release"; then
+	  major=
+	  case $version_type in
+	  darwin)
+	    # we can't check for "0.0" in archive_cmds due to quoting
+	    # problems, so we reset it completely
+	    verstring=
+	    ;;
+	  *)
+	    verstring="0.0"
+	    ;;
+	  esac
+	  if test "$need_version" = no; then
+	    versuffix=
+	  else
+	    versuffix=".0.0"
+	  fi
+	fi
+
+	# Remove version info from name if versioning should be avoided
+	if test "$avoid_version" = yes && test "$need_version" = no; then
+	  major=
+	  versuffix=
+	  verstring=""
+	fi
+
+	# Check to see if the archive will have undefined symbols.
+	if test "$allow_undefined" = yes; then
+	  if test "$allow_undefined_flag" = unsupported; then
+	    func_warning "undefined symbols not allowed in $host shared libraries"
+	    build_libtool_libs=no
+	    build_old_libs=yes
+	  fi
+	else
+	  # Don't allow undefined symbols.
+	  allow_undefined_flag="$no_undefined_flag"
+	fi
+
+      fi
+
+      func_generate_dlsyms "$libname" "$libname" "yes"
+      libobjs="$libobjs $symfileobj"
+      test "X$libobjs" = "X " && libobjs=
+
+      if test "$mode" != relink; then
+	# Remove our outputs, but don't remove object files since they
+	# may have been created when compiling PIC objects.
+	removelist=
+	tempremovelist=`$ECHO "$output_objdir/*"`
+	for p in $tempremovelist; do
+	  case $p in
+	    *.$objext | *.gcno)
+	       ;;
+	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+	       if test "X$precious_files_regex" != "X"; then
+		 if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+		 then
+		   continue
+		 fi
+	       fi
+	       removelist="$removelist $p"
+	       ;;
+	    *) ;;
+	  esac
+	done
+	test -n "$removelist" && \
+	  func_show_eval "${RM}r \$removelist"
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+	oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+	# Transform .lo files to .o files.
+	oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #	lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
+      #	deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
+      #	dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	temp_xrpath=
+	for libdir in $xrpath; do
+	  temp_xrpath="$temp_xrpath -R$libdir"
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+	if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+	  dependency_libs="$temp_xrpath $dependency_libs"
+	fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+	case " $dlprefiles $dlfiles " in
+	*" $lib "*) ;;
+	*) dlfiles="$dlfiles $lib" ;;
+	esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+	case "$dlprefiles " in
+	*" $lib "*) ;;
+	*) dlprefiles="$dlprefiles $lib" ;;
+	esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+	if test -n "$rpath"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
+	    # these systems don't actually have a c library (as such)!
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C library is in the System framework
+	    deplibs="$deplibs System.ltframework"
+	    ;;
+	  *-*-netbsd*)
+	    # Don't link with libc until the a.out ld.so is fixed.
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    ;;
+	  *)
+	    # Add libc to deplibs on all other systems if necessary.
+	    if test "$build_libtool_need_lc" = "yes"; then
+	      deplibs="$deplibs -lc"
+	    fi
+	    ;;
+	  esac
+	fi
+
+	# Transform deplibs into only deplibs that can be linked in shared.
+	name_save=$name
+	libname_save=$libname
+	release_save=$release
+	versuffix_save=$versuffix
+	major_save=$major
+	# I'm not sure if I'm treating the release correctly.  I think
+	# release should show up in the -l (ie -lgmp5) so we don't want to
+	# add it in twice.  Is that correct?
+	release=""
+	versuffix=""
+	major=""
+	newdeplibs=
+	droppeddeps=no
+	case $deplibs_check_method in
+	pass_all)
+	  # Don't check for shared/static.  Everything works.
+	  # This might be a little naive.  We might want to check
+	  # whether the library exists or not.  But this is on
+	  # osf3 & osf4 and I'm not really sure... Just
+	  # implementing what was already the behavior.
+	  newdeplibs=$deplibs
+	  ;;
+	test_compile)
+	  # This code stresses the "libraries are programs" paradigm to its
+	  # limits. Maybe even breaks it.  We compile a program, linking it
+	  # against the deplibs as a proxy for the library.  Then we can check
+	  # whether they linked in statically or dynamically with ldd.
+	  $opt_dry_run || $RM conftest.c
+	  cat > conftest.c <<EOF
+	  int main() { return 0; }
+EOF
+	  $opt_dry_run || $RM conftest
+	  if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+	    ldd_output=`ldd conftest`
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		  case " $predeps $postdeps " in
+		  *" $i "*)
+		    newdeplibs="$newdeplibs $i"
+		    i=""
+		    ;;
+		  esac
+		fi
+		if test -n "$i" ; then
+		  eval "libname=\"$libname_spec\""
+		  eval "deplib_matches=\"$library_names_spec\""
+		  set dummy $deplib_matches; shift
+		  deplib_match=$1
+		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		    newdeplibs="$newdeplibs $i"
+		  else
+		    droppeddeps=yes
+		    echo
+		    $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		    echo "*** I have the capability to make that library automatically link in when"
+		    echo "*** you link to this library.  But I can only do this if you have a"
+		    echo "*** shared version of the library, which I believe you do not have"
+		    echo "*** because a test_compile did reveal that the linker did not use it for"
+		    echo "*** its dynamic dependency list that programs get resolved with at runtime."
+		  fi
+		fi
+		;;
+	      *)
+		newdeplibs="$newdeplibs $i"
+		;;
+	      esac
+	    done
+	  else
+	    # Error occurred in the first compile.  Let's try to salvage
+	    # the situation: Compile a separate program for each library.
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		$opt_dry_run || $RM conftest
+		if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+		  ldd_output=`ldd conftest`
+		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		    case " $predeps $postdeps " in
+		    *" $i "*)
+		      newdeplibs="$newdeplibs $i"
+		      i=""
+		      ;;
+		    esac
+		  fi
+		  if test -n "$i" ; then
+		    eval "libname=\"$libname_spec\""
+		    eval "deplib_matches=\"$library_names_spec\""
+		    set dummy $deplib_matches; shift
+		    deplib_match=$1
+		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		      newdeplibs="$newdeplibs $i"
+		    else
+		      droppeddeps=yes
+		      echo
+		      $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		      echo "*** I have the capability to make that library automatically link in when"
+		      echo "*** you link to this library.  But I can only do this if you have a"
+		      echo "*** shared version of the library, which you do not appear to have"
+		      echo "*** because a test_compile did reveal that the linker did not use this one"
+		      echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+		    fi
+		  fi
+		else
+		  droppeddeps=yes
+		  echo
+		  $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+		  echo "*** make it link in!  You will probably need to install it or some"
+		  echo "*** library that it depends on before this library will be fully"
+		  echo "*** functional.  Installing it before continuing would be even better."
+		fi
+		;;
+	      *)
+		newdeplibs="$newdeplibs $i"
+		;;
+	      esac
+	    done
+	  fi
+	  ;;
+	file_magic*)
+	  set dummy $deplibs_check_method; shift
+	  file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		eval "libname=\"$libname_spec\""
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		      # Follow soft links.
+		      if ls -lLd "$potent_lib" 2>/dev/null |
+			 $GREP " -> " >/dev/null; then
+			continue
+		      fi
+		      # The statement above tries to avoid entering an
+		      # endless loop below, in case of cyclic links.
+		      # We might still enter an endless loop, since a link
+		      # loop can be closed while we follow links,
+		      # but so what?
+		      potlib="$potent_lib"
+		      while test -h "$potlib" 2>/dev/null; do
+			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+			case $potliblink in
+			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+			*) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";;
+			esac
+		      done
+		      if eval "$file_magic_cmd \"\$potlib\"" 2>/dev/null |
+			 $SED -e 10q |
+			 $EGREP "$file_magic_regex" > /dev/null; then
+			newdeplibs="$newdeplibs $a_deplib"
+			a_deplib=""
+			break 2
+		      fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		echo
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a file magic. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	match_pattern*)
+	  set dummy $deplibs_check_method; shift
+	  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		eval "libname=\"$libname_spec\""
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		    potlib="$potent_lib" # see symlink-check above in file_magic test
+		    if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
+		       $EGREP "$match_pattern_regex" > /dev/null; then
+		      newdeplibs="$newdeplibs $a_deplib"
+		      a_deplib=""
+		      break 2
+		    fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		echo
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a regex pattern. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	none | unknown | *)
+	  newdeplibs=""
+	  tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
+	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	    for i in $predeps $postdeps ; do
+	      # can't use Xsed below, because $i might contain '/'
+	      tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"`
+	    done
+	  fi
+	  case $tmp_deplibs in
+	  *[!\	\ ]*)
+	    echo
+	    if test "X$deplibs_check_method" = "Xnone"; then
+	      echo "*** Warning: inter-library dependencies are not supported in this platform."
+	    else
+	      echo "*** Warning: inter-library dependencies are not known to be supported."
+	    fi
+	    echo "*** All declared inter-library dependencies are being dropped."
+	    droppeddeps=yes
+	    ;;
+	  esac
+	  ;;
+	esac
+	versuffix=$versuffix_save
+	major=$major_save
+	release=$release_save
+	libname=$libname_save
+	name=$name_save
+
+	case $host in
+	*-*-rhapsody* | *-*-darwin1.[012])
+	  # On Rhapsody replace the C library with the System framework
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
+	  ;;
+	esac
+
+	if test "$droppeddeps" = yes; then
+	  if test "$module" = yes; then
+	    echo
+	    echo "*** Warning: libtool could not satisfy all declared inter-library"
+	    $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
+	    echo "*** a static module, that should work as long as the dlopening"
+	    echo "*** application is linked with the -dlopen flag."
+	    if test -z "$global_symbol_pipe"; then
+	      echo
+	      echo "*** However, this would only work if libtool was able to extract symbol"
+	      echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+	      echo "*** not find such a program.  So, this module is probably useless."
+	      echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	    fi
+	    if test "$build_old_libs" = no; then
+	      oldlibs="$output_objdir/$libname.$libext"
+	      build_libtool_libs=module
+	      build_old_libs=yes
+	    else
+	      build_libtool_libs=no
+	    fi
+	  else
+	    echo "*** The inter-library dependencies that have been dropped here will be"
+	    echo "*** automatically added whenever a program is linked with this library"
+	    echo "*** or is declared to -dlopen it."
+
+	    if test "$allow_undefined" = no; then
+	      echo
+	      echo "*** Since this library must not contain undefined symbols,"
+	      echo "*** because either the platform does not support them or"
+	      echo "*** it was explicitly requested with -no-undefined,"
+	      echo "*** libtool will only create a static version of it."
+	      if test "$build_old_libs" = no; then
+		oldlibs="$output_objdir/$libname.$libext"
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  fi
+	fi
+	# Done checking deplibs!
+	deplibs=$newdeplibs
+      fi
+      # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+      case $host in
+	*-*-darwin*)
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  ;;
+      esac
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs="$new_libs -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs="$new_libs $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs="$new_libs $deplib" ;;
+	esac
+      done
+      deplibs="$new_libs"
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+	if test "$hardcode_into_libs" = yes; then
+	  # Hardcode the library paths
+	  hardcode_libdirs=
+	  dep_rpath=
+	  rpath="$finalize_rpath"
+	  test "$mode" != relink && rpath="$compile_rpath$rpath"
+	  for libdir in $rpath; do
+	    if test -n "$hardcode_libdir_flag_spec"; then
+	      if test -n "$hardcode_libdir_separator"; then
+		if test -z "$hardcode_libdirs"; then
+		  hardcode_libdirs="$libdir"
+		else
+		  # Just accumulate the unique libdirs.
+		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		    ;;
+		  *)
+		    hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		    ;;
+		  esac
+		fi
+	      else
+		eval "flag=\"$hardcode_libdir_flag_spec\""
+		dep_rpath="$dep_rpath $flag"
+	      fi
+	    elif test -n "$runpath_var"; then
+	      case "$perm_rpath " in
+	      *" $libdir "*) ;;
+	      *) perm_rpath="$perm_rpath $libdir" ;;
+	      esac
+	    fi
+	  done
+	  # Substitute the hardcoded libdirs into the rpath.
+	  if test -n "$hardcode_libdir_separator" &&
+	     test -n "$hardcode_libdirs"; then
+	    libdir="$hardcode_libdirs"
+	    if test -n "$hardcode_libdir_flag_spec_ld"; then
+	      eval "dep_rpath=\"$hardcode_libdir_flag_spec_ld\""
+	    else
+	      eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
+	    fi
+	  fi
+	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
+	    # We should set the runpath_var.
+	    rpath=
+	    for dir in $perm_rpath; do
+	      rpath="$rpath$dir:"
+	    done
+	    eval $runpath_var=\$rpath\$$runpath_var
+	    export $runpath_var
+	  fi
+	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+	fi
+
+	shlibpath="$finalize_shlibpath"
+	test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+	if test -n "$shlibpath"; then
+	  eval $shlibpath_var=\$shlibpath\$$shlibpath_var
+	  export $shlibpath_var
+	fi
+
+	# Get the real and link names of the library.
+	eval "shared_ext=\"$shrext_cmds\""
+	eval "library_names=\"$library_names_spec\""
+	set dummy $library_names
+	shift
+	realname="$1"
+	shift
+
+	if test -n "$soname_spec"; then
+	  eval "soname=\"$soname_spec\""
+	else
+	  soname="$realname"
+	fi
+	if test -z "$dlname"; then
+	  dlname=$soname
+	fi
+
+	lib="$output_objdir/$realname"
+	linknames=
+	for link
+	do
+	  linknames="$linknames $link"
+	done
+
+	# Use standard objects if they are pic
+	test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	test "X$libobjs" = "X " && libobjs=
+
+	delfiles=
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+	  export_symbols="$output_objdir/$libname.uexp"
+	  delfiles="$delfiles $export_symbols"
+	fi
+
+	orig_export_symbols=
+	case $host_os in
+	cygwin* | mingw* | cegcc*)
+	  if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+	    # exporting using user supplied symfile
+	    if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
+	      # and it's NOT already a .def file. Must figure out
+	      # which of the given symbols are data symbols and tag
+	      # them as such. So, trigger use of export_symbols_cmds.
+	      # export_symbols gets reassigned inside the "prepare
+	      # the list of exported symbols" if statement, so the
+	      # include_expsyms logic still works.
+	      orig_export_symbols="$export_symbols"
+	      export_symbols=
+	      always_export_symbols=yes
+	    fi
+	  fi
+	  ;;
+	esac
+
+	# Prepare the list of exported symbols
+	if test -z "$export_symbols"; then
+	  if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+	    func_verbose "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $opt_dry_run || $RM $export_symbols
+	    cmds=$export_symbols_cmds
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $cmds; do
+	      IFS="$save_ifs"
+	      eval "cmd=\"$cmd\""
+	      func_len " $cmd"
+	      len=$func_len_result
+	      if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+		func_show_eval "$cmd" 'exit $?'
+		skipped_export=false
+	      else
+		# The command line is too long to execute in one step.
+		func_verbose "using reloadable object file for export list..."
+		skipped_export=:
+		# Break out early, otherwise skipped_export may be
+		# set to false by a later but shorter cmd.
+		break
+	      fi
+	    done
+	    IFS="$save_ifs"
+	    if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+	fi
+
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  tmp_export_symbols="$export_symbols"
+	  test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	  $opt_dry_run || $ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"
+	fi
+
+	if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
+	  # The given exports_symbols file has to be filtered, so filter it.
+	  func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	  # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	  # 's' commands which not all seds can handle. GNU sed should be fine
+	  # though. Also, the filter scales superlinearly with the number of
+	  # global variables. join(1) would be nice here, but unfortunately
+	  # isn't a blessed tool.
+	  $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	  delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+	  export_symbols=$output_objdir/$libname.def
+	  $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	fi
+
+	tmp_deplibs=
+	for test_deplib in $deplibs; do
+	  case " $convenience " in
+	  *" $test_deplib "*) ;;
+	  *)
+	    tmp_deplibs="$tmp_deplibs $test_deplib"
+	    ;;
+	  esac
+	done
+	deplibs="$tmp_deplibs"
+
+	if test -n "$convenience"; then
+	  if test -n "$whole_archive_flag_spec" &&
+	    test "$compiler_needs_object" = yes &&
+	    test -z "$libobjs"; then
+	    # extract the archives, so we have objects to list.
+	    # TODO: could optimize this to just extract one archive.
+	    whole_archive_flag_spec=
+	  fi
+	  if test -n "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	    eval "libobjs=\"\$libobjs $whole_archive_flag_spec\""
+	    test "X$libobjs" = "X " && libobjs=
+	  else
+	    gentop="$output_objdir/${outputname}x"
+	    generated="$generated $gentop"
+
+	    func_extract_archives $gentop $convenience
+	    libobjs="$libobjs $func_extract_archives_result"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	fi
+
+	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+	  eval "flag=\"$thread_safe_flag_spec\""
+	  linker_flags="$linker_flags $flag"
+	fi
+
+	# Make a backup of the uninstalled library when relinking
+	if test "$mode" = relink; then
+	  $opt_dry_run || (cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U) || exit $?
+	fi
+
+	# Do each of the archive commands.
+	if test "$module" = yes && test -n "$module_cmds" ; then
+	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	    eval "test_cmds=\"$module_expsym_cmds\""
+	    cmds=$module_expsym_cmds
+	  else
+	    eval "test_cmds=\"$module_cmds\""
+	    cmds=$module_cmds
+	  fi
+	else
+	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	    eval "test_cmds=\"$archive_expsym_cmds\""
+	    cmds=$archive_expsym_cmds
+	  else
+	    eval "test_cmds=\"$archive_cmds\""
+	    cmds=$archive_cmds
+	  fi
+	fi
+
+	if test "X$skipped_export" != "X:" &&
+	   func_len " $test_cmds" &&
+	   len=$func_len_result &&
+	   test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
+	else
+	  # The command line is too long to link in one step, link piecewise
+	  # or, if using GNU ld and skipped_export is not :, use a linker
+	  # script.
+
+	  # Save the value of $output and $libobjs because we want to
+	  # use them later.  If we have whole_archive_flag_spec, we
+	  # want to use save_libobjs as it was before
+	  # whole_archive_flag_spec was expanded, because we can't
+	  # assume the linker understands whole_archive_flag_spec.
+	  # This may have to be revisited, in case too many
+	  # convenience libraries get linked in and end up exceeding
+	  # the spec.
+	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	  fi
+	  save_output=$output
+	  func_basename "$output"
+	  output_la=$func_basename_result
+
+	  # Clear the reloadable object creation command queue and
+	  # initialize k to one.
+	  test_cmds=
+	  concat_cmds=
+	  objlist=
+	  last_robj=
+	  k=1
+
+	  if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
+	    output=${output_objdir}/${output_la}.lnkscript
+	    func_verbose "creating GNU ld script: $output"
+	    echo 'INPUT (' > $output
+	    for obj in $save_libobjs
+	    do
+	      $ECHO "$obj" >> $output
+	    done
+	    echo ')' >> $output
+	    delfiles="$delfiles $output"
+	  elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
+	    output=${output_objdir}/${output_la}.lnk
+	    func_verbose "creating linker input file list: $output"
+	    : > $output
+	    set x $save_libobjs
+	    shift
+	    firstobj=
+	    if test "$compiler_needs_object" = yes; then
+	      firstobj="$1 "
+	      shift
+	    fi
+	    for obj
+	    do
+	      $ECHO "$obj" >> $output
+	    done
+	    delfiles="$delfiles $output"
+	    output=$firstobj\"$file_list_spec$output\"
+	  else
+	    if test -n "$save_libobjs"; then
+	      func_verbose "creating reloadable object files..."
+	      output=$output_objdir/$output_la-${k}.$objext
+	      eval "test_cmds=\"$reload_cmds\""
+	      func_len " $test_cmds"
+	      len0=$func_len_result
+	      len=$len0
+
+	      # Loop over the list of objects to be linked.
+	      for obj in $save_libobjs
+	      do
+		func_len " $obj"
+		func_arith $len + $func_len_result
+		len=$func_arith_result
+		if test "X$objlist" = X ||
+		   test "$len" -lt "$max_cmd_len"; then
+		  func_append objlist " $obj"
+		else
+		  # The command $test_cmds is almost too long, add a
+		  # command to the queue.
+		  if test "$k" -eq 1 ; then
+		    # The first file doesn't have a previous command to add.
+		    reload_objs=$objlist
+		    eval "concat_cmds=\"$reload_cmds\""
+		  else
+		    # All subsequent reloadable object files will link in
+		    # the last one created.
+		    reload_objs="$objlist $last_robj"
+		    eval "concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\""
+		  fi
+		  last_robj=$output_objdir/$output_la-${k}.$objext
+		  func_arith $k + 1
+		  k=$func_arith_result
+		  output=$output_objdir/$output_la-${k}.$objext
+		  objlist=" $obj"
+		  func_len " $last_robj"
+		  func_arith $len0 + $func_len_result
+		  len=$func_arith_result
+		fi
+	      done
+	      # Handle the remaining objects by creating one last
+	      # reloadable object file.  All subsequent reloadable object
+	      # files will link in the last one created.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      reload_objs="$objlist $last_robj"
+	      eval "concat_cmds=\"\${concat_cmds}$reload_cmds\""
+	      if test -n "$last_robj"; then
+	        eval "concat_cmds=\"\${concat_cmds}~\$RM $last_robj\""
+	      fi
+	      delfiles="$delfiles $output"
+
+	    else
+	      output=
+	    fi
+
+	    if ${skipped_export-false}; then
+	      func_verbose "generating symbol list for \`$libname.la'"
+	      export_symbols="$output_objdir/$libname.exp"
+	      $opt_dry_run || $RM $export_symbols
+	      libobjs=$output
+	      # Append the command to create the export file.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval "concat_cmds=\"\$concat_cmds$export_symbols_cmds\""
+	      if test -n "$last_robj"; then
+		eval "concat_cmds=\"\$concat_cmds~\$RM $last_robj\""
+	      fi
+	    fi
+
+	    test -n "$save_libobjs" &&
+	      func_verbose "creating a temporary reloadable object file: $output"
+
+	    # Loop through the commands generated above and execute them.
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $concat_cmds; do
+	      IFS="$save_ifs"
+	      $opt_silent || {
+		  func_quote_for_expand "$cmd"
+		  eval "func_echo $func_quote_for_expand_result"
+	      }
+	      $opt_dry_run || eval "$cmd" || {
+		lt_exit=$?
+
+		# Restore the uninstalled library and exit
+		if test "$mode" = relink; then
+		  ( cd "$output_objdir" && \
+		    $RM "${realname}T" && \
+		    $MV "${realname}U" "$realname" )
+		fi
+
+		exit $lt_exit
+	      }
+	    done
+	    IFS="$save_ifs"
+
+	    if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+
+          if ${skipped_export-false}; then
+	    if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	      tmp_export_symbols="$export_symbols"
+	      test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	      $opt_dry_run || $ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"
+	    fi
+
+	    if test -n "$orig_export_symbols"; then
+	      # The given exports_symbols file has to be filtered, so filter it.
+	      func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	      # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	      # 's' commands which not all seds can handle. GNU sed should be fine
+	      # though. Also, the filter scales superlinearly with the number of
+	      # global variables. join(1) would be nice here, but unfortunately
+	      # isn't a blessed tool.
+	      $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	      delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+	      export_symbols=$output_objdir/$libname.def
+	      $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	    fi
+	  fi
+
+	  libobjs=$output
+	  # Restore the value of output.
+	  output=$save_output
+
+	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+	    eval "libobjs=\"\$libobjs $whole_archive_flag_spec\""
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	  # Expand the library linking commands again to reset the
+	  # value of $libobjs for piecewise linking.
+
+	  # Do each of the archive commands.
+	  if test "$module" = yes && test -n "$module_cmds" ; then
+	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	      cmds=$module_expsym_cmds
+	    else
+	      cmds=$module_cmds
+	    fi
+	  else
+	    if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	      cmds=$archive_expsym_cmds
+	    else
+	      cmds=$archive_cmds
+	    fi
+	  fi
+	fi
+
+	if test -n "$delfiles"; then
+	  # Append the command to remove temporary files to $cmds.
+	  eval "cmds=\"\$cmds~\$RM $delfiles\""
+	fi
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  libobjs="$libobjs $func_extract_archives_result"
+	  test "X$libobjs" = "X " && libobjs=
+	fi
+
+	save_ifs="$IFS"; IFS='~'
+	for cmd in $cmds; do
+	  IFS="$save_ifs"
+	  eval "cmd=\"$cmd\""
+	  $opt_silent || {
+	    func_quote_for_expand "$cmd"
+	    eval "func_echo $func_quote_for_expand_result"
+	  }
+	  $opt_dry_run || eval "$cmd" || {
+	    lt_exit=$?
+
+	    # Restore the uninstalled library and exit
+	    if test "$mode" = relink; then
+	      ( cd "$output_objdir" && \
+	        $RM "${realname}T" && \
+		$MV "${realname}U" "$realname" )
+	    fi
+
+	    exit $lt_exit
+	  }
+	done
+	IFS="$save_ifs"
+
+	# Restore the uninstalled library and exit
+	if test "$mode" = relink; then
+	  $opt_dry_run || (cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname) || exit $?
+
+	  if test -n "$convenience"; then
+	    if test -z "$whole_archive_flag_spec"; then
+	      func_show_eval '${RM}r "$gentop"'
+	    fi
+	  fi
+
+	  exit $EXIT_SUCCESS
+	fi
+
+	# Create links to the real library.
+	for linkname in $linknames; do
+	  if test "$realname" != "$linkname"; then
+	    func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+	  fi
+	done
+
+	# If -module or -export-dynamic was specified, set the dlname.
+	if test "$module" = yes || test "$export_dynamic" = yes; then
+	  # On all known operating systems, these are identical.
+	  dlname="$soname"
+	fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for objects"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for objects" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for objects"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for objects"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for objects"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for objects"
+
+      case $output in
+      *.lo)
+	test -n "$objs$old_deplibs" && \
+	  func_fatal_error "cannot build library object \`$output' from non-libtool objects"
+
+	libobj=$output
+	func_lo2o "$libobj"
+	obj=$func_lo2o_result
+	;;
+      *)
+	libobj=
+	obj="$output"
+	;;
+      esac
+
+      # Delete the old objects.
+      $opt_dry_run || $RM $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
+      wl=
+
+      if test -n "$convenience"; then
+	if test -n "$whole_archive_flag_spec"; then
+	  eval "tmp_whole_archive_flags=\"$whole_archive_flag_spec\""
+	  reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
+	else
+	  gentop="$output_objdir/${obj}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $convenience
+	  reload_conv_objs="$reload_objs $func_extract_archives_result"
+	fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      func_execute_cmds "$reload_cmds" 'exit $?'
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	# Create an invalid libtool object if no PIC, so that we don't
+	# accidentally link it into a program.
+	# $show "echo timestamp > $libobj"
+	# $opt_dry_run || echo timestamp > $libobj || exit $?
+	exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+	# Only do commands if we really have different PIC objects.
+	reload_objs="$libobjs $reload_conv_objs"
+	output="$libobj"
+	func_execute_cmds "$reload_cmds" 'exit $?'
+      fi
+
+      if test -n "$gentop"; then
+	func_show_eval '${RM}r "$gentop"'
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+	*cygwin*) func_stripname '' '.exe' "$output"
+	          output=$func_stripname_result.exe;;
+      esac
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for programs"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for programs"
+
+      test "$preload" = yes \
+        && test "$dlopen_support" = unknown \
+	&& test "$dlopen_self" = unknown \
+	&& test "$dlopen_self_static" = unknown && \
+	  func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+	# On Rhapsody replace the C library is the System framework
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	;;
+      esac
+
+      case $host in
+      *-*-darwin*)
+	# Don't allow lazy linking, it breaks C++ global constructors
+	# But is supposedly fixed on 10.4 or later (yay!).
+	if test "$tagname" = CXX ; then
+	  case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+	    10.[0123])
+	      compile_command="$compile_command ${wl}-bind_at_load"
+	      finalize_command="$finalize_command ${wl}-bind_at_load"
+	    ;;
+	  esac
+	fi
+	# Time to change all our "foo.ltframework" stuff back to "-framework foo"
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $compile_deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs="$new_libs -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $compile_deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs="$new_libs $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs="$new_libs $deplib" ;;
+	esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      compile_command="$compile_command $compile_deplibs"
+      finalize_command="$finalize_command $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	for libdir in $rpath $xrpath; do
+	  # This is the magic to use -rpath.
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval "flag=\"$hardcode_libdir_flag_spec\""
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) perm_rpath="$perm_rpath $libdir" ;;
+	  esac
+	fi
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$libdir:"*) ;;
+	  ::) dllsearchpath=$libdir;;
+	  *) dllsearchpath="$dllsearchpath:$libdir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  esac
+	  ;;
+	esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval "rpath=\" $hardcode_libdir_flag_spec\""
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval "flag=\"$hardcode_libdir_flag_spec\""
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$finalize_perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+	  esac
+	fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval "rpath=\" $hardcode_libdir_flag_spec\""
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+	# Transform all the library objects into standard objects.
+	compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+      fi
+
+      func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
+
+      # template prelinking step
+      if test -n "$prelink_cmds"; then
+	func_execute_cmds "$prelink_cmds" 'exit $?'
+      fi
+
+      wrappers_required=yes
+      case $host in
+      *cegcc* | *mingw32ce*)
+        # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+        wrappers_required=no
+        ;;
+      *cygwin* | *mingw* )
+        if test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      *)
+        if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      esac
+      if test "$wrappers_required" = no; then
+	# Replace the output file specification.
+	compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+	link_command="$compile_command$compile_rpath"
+
+	# We have no uninstalled library dependencies, so finalize right now.
+	exit_status=0
+	func_show_eval "$link_command" 'exit_status=$?'
+
+	# Delete the generated files.
+	if test -f "$output_objdir/${outputname}S.${objext}"; then
+	  func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
+	fi
+
+	exit $exit_status
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+	if test -n "$perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+	if test -n "$finalize_perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $finalize_perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+      fi
+
+      if test "$no_install" = yes; then
+	# We don't need to create a wrapper script.
+	link_command="$compile_var$compile_command$compile_rpath"
+	# Replace the output file specification.
+	link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+	# Delete the old output file.
+	$opt_dry_run || $RM $output
+	# Link the executable and exit
+	func_show_eval "$link_command" 'exit $?'
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+	# Fast installation is not supported
+	link_command="$compile_var$compile_command$compile_rpath"
+	relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+	func_warning "this platform does not like uninstalled shared libraries"
+	func_warning "\`$output' will be relinked during installation"
+      else
+	if test "$fast_install" != no; then
+	  link_command="$finalize_var$compile_command$finalize_rpath"
+	  if test "$fast_install" = yes; then
+	    relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
+	  else
+	    # fast_install is set to needless
+	    relink_command=
+	  fi
+	else
+	  link_command="$compile_var$compile_command$compile_rpath"
+	  relink_command="$finalize_var$finalize_command$finalize_rpath"
+	fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      func_show_eval "$link_command" 'exit $?'
+
+      # Now create the wrapper script.
+      func_verbose "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+	# Preserve any variables that may affect compiler behavior
+	for var in $variables_saved_for_relink; do
+	  if eval test -z \"\${$var+set}\"; then
+	    relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	  elif eval var_value=\$$var; test -z "$var_value"; then
+	    relink_command="$var=; export $var; $relink_command"
+	  else
+	    func_quote_for_eval "$var_value"
+	    relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	  fi
+	done
+	relink_command="(cd `pwd`; $relink_command)"
+	relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if not in dry run mode.
+      $opt_dry_run || {
+	# win32 will think the script is a binary if it has
+	# a .exe suffix, so we strip it off here.
+	case $output in
+	  *.exe) func_stripname '' '.exe' "$output"
+	         output=$func_stripname_result ;;
+	esac
+	# test for cygwin because mv fails w/o .exe extensions
+	case $host in
+	  *cygwin*)
+	    exeext=.exe
+	    func_stripname '' '.exe' "$outputname"
+	    outputname=$func_stripname_result ;;
+	  *) exeext= ;;
+	esac
+	case $host in
+	  *cygwin* | *mingw* )
+	    func_dirname_and_basename "$output" "" "."
+	    output_name=$func_basename_result
+	    output_path=$func_dirname_result
+	    cwrappersource="$output_path/$objdir/lt-$output_name.c"
+	    cwrapper="$output_path/$output_name.exe"
+	    $RM $cwrappersource $cwrapper
+	    trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_cwrapperexe_src > $cwrappersource
+
+	    # The wrapper executable is built using the $host compiler,
+	    # because it contains $host paths and files. If cross-
+	    # compiling, it, like the target executable, must be
+	    # executed on the $host or under an emulation environment.
+	    $opt_dry_run || {
+	      $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+	      $STRIP $cwrapper
+	    }
+
+	    # Now, create the wrapper script for func_source use:
+	    func_ltwrapper_scriptname $cwrapper
+	    $RM $func_ltwrapper_scriptname_result
+	    trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+	    $opt_dry_run || {
+	      # note: this script will not be executed, so do not chmod.
+	      if test "x$build" = "x$host" ; then
+		$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+	      else
+		func_emit_wrapper no > $func_ltwrapper_scriptname_result
+	      fi
+	    }
+	  ;;
+	  * )
+	    $RM $output
+	    trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_wrapper no > $output
+	    chmod +x $output
+	  ;;
+	esac
+      }
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+	oldobjs="$libobjs_save $symfileobj"
+	addlibs="$convenience"
+	build_libtool_libs=no
+      else
+	if test "$build_libtool_libs" = module; then
+	  oldobjs="$libobjs_save"
+	  build_libtool_libs=no
+	else
+	  oldobjs="$old_deplibs $non_pic_objects"
+	  if test "$preload" = yes && test -f "$symfileobj"; then
+	    oldobjs="$oldobjs $symfileobj"
+	  fi
+	fi
+	addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+	gentop="$output_objdir/${outputname}x"
+	generated="$generated $gentop"
+
+	func_extract_archives $gentop $addlibs
+	oldobjs="$oldobjs $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+	cmds=$old_archive_from_new_cmds
+      else
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  oldobjs="$oldobjs $func_extract_archives_result"
+	fi
+
+	# POSIX demands no paths to be encoded in archives.  We have
+	# to avoid creating archives with duplicate basenames if we
+	# might have to extract them afterwards, e.g., when creating a
+	# static archive out of a convenience library, or when linking
+	# the entirety of a libtool archive into another (currently
+	# not supported by libtool).
+	if (for obj in $oldobjs
+	    do
+	      func_basename "$obj"
+	      $ECHO "$func_basename_result"
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	  :
+	else
+	  echo "copying selected object files to avoid basename conflicts..."
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+	  func_mkdir_p "$gentop"
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  counter=1
+	  for obj in $save_oldobjs
+	  do
+	    func_basename "$obj"
+	    objbase="$func_basename_result"
+	    case " $oldobjs " in
+	    " ") oldobjs=$obj ;;
+	    *[\ /]"$objbase "*)
+	      while :; do
+		# Make sure we don't pick an alternate name that also
+		# overlaps.
+		newobj=lt$counter-$objbase
+		func_arith $counter + 1
+		counter=$func_arith_result
+		case " $oldobjs " in
+		*[\ /]"$newobj "*) ;;
+		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
+		esac
+	      done
+	      func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+	      oldobjs="$oldobjs $gentop/$newobj"
+	      ;;
+	    *) oldobjs="$oldobjs $obj" ;;
+	    esac
+	  done
+	fi
+	eval "cmds=\"$old_archive_cmds\""
+
+	func_len " $cmds"
+	len=$func_len_result
+	if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  cmds=$old_archive_cmds
+	else
+	  # the command line is too long to link in one step, link in parts
+	  func_verbose "using piecewise archive linking..."
+	  save_RANLIB=$RANLIB
+	  RANLIB=:
+	  objlist=
+	  concat_cmds=
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  # Is there a better way of finding the last object in the list?
+	  for obj in $save_oldobjs
+	  do
+	    last_oldobj=$obj
+	  done
+	  eval "test_cmds=\"$old_archive_cmds\""
+	  func_len " $test_cmds"
+	  len0=$func_len_result
+	  len=$len0
+	  for obj in $save_oldobjs
+	  do
+	    func_len " $obj"
+	    func_arith $len + $func_len_result
+	    len=$func_arith_result
+	    func_append objlist " $obj"
+	    if test "$len" -lt "$max_cmd_len"; then
+	      :
+	    else
+	      # the above command should be used before it gets too long
+	      oldobjs=$objlist
+	      if test "$obj" = "$last_oldobj" ; then
+		RANLIB=$save_RANLIB
+	      fi
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval "concat_cmds=\"\${concat_cmds}$old_archive_cmds\""
+	      objlist=
+	      len=$len0
+	    fi
+	  done
+	  RANLIB=$save_RANLIB
+	  oldobjs=$objlist
+	  if test "X$oldobjs" = "X" ; then
+	    eval "cmds=\"\$concat_cmds\""
+	  else
+	    eval "cmds=\"\$concat_cmds~\$old_archive_cmds\""
+	  fi
+	fi
+      fi
+      func_execute_cmds "$cmds" 'exit $?'
+    done
+
+    test -n "$generated" && \
+      func_show_eval "${RM}r$generated"
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      func_verbose "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+	if eval test -z \"\${$var+set}\"; then
+	  relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	elif eval var_value=\$$var; test -z "$var_value"; then
+	  relink_command="$var=; export $var; $relink_command"
+	else
+	  func_quote_for_eval "$var_value"
+	  relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+	relink_command=
+      fi
+
+      # Only create the output if not a dry run.
+      $opt_dry_run || {
+	for installed in no yes; do
+	  if test "$installed" = yes; then
+	    if test -z "$install_libdir"; then
+	      break
+	    fi
+	    output="$output_objdir/$outputname"i
+	    # Replace all uninstalled libtool libraries with the installed ones
+	    newdependency_libs=
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      *.la)
+		func_basename "$deplib"
+		name="$func_basename_result"
+		libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$deplib' is not a valid libtool archive"
+		newdependency_libs="$newdependency_libs $libdir/$name"
+		;;
+	      *) newdependency_libs="$newdependency_libs $deplib" ;;
+	      esac
+	    done
+	    dependency_libs="$newdependency_libs"
+	    newdlfiles=
+
+	    for lib in $dlfiles; do
+	      case $lib in
+	      *.la)
+	        func_basename "$lib"
+		name="$func_basename_result"
+		libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		newdlfiles="$newdlfiles $libdir/$name"
+		;;
+	      *) newdlfiles="$newdlfiles $lib" ;;
+	      esac
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+	      *.la)
+		# Only pass preopened files to the pseudo-archive (for
+		# eventual linking with the app. that links it) if we
+		# didn't already link the preopened objects directly into
+		# the library:
+		func_basename "$lib"
+		name="$func_basename_result"
+		libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		newdlprefiles="$newdlprefiles $libdir/$name"
+		;;
+	      esac
+	    done
+	    dlprefiles="$newdlprefiles"
+	  else
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlfiles="$newdlfiles $abs"
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlprefiles="$newdlprefiles $abs"
+	    done
+	    dlprefiles="$newdlprefiles"
+	  fi
+	  $RM $output
+	  # place dlname in correct position for cygwin
+	  # In fact, it would be nice if we could use this code for all target
+	  # systems that can't hard-code library paths into their executables
+	  # and that have no shared library path variable independent of PATH,
+	  # but it turns out we can't easily determine that from inspecting
+	  # libtool variables, so we have to hard-code the OSs to which it
+	  # applies here; at the moment, that means platforms that use the PE
+	  # object format with DLL files.  See the long comment at the top of
+	  # tests/bindir.at for full details.
+	  tdlname=$dlname
+	  case $host,$output,$installed,$module,$dlname in
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
+	      # If a -bindir argument was supplied, place the dll there.
+	      if test "x$bindir" != x ;
+	      then
+		func_relative_path "$install_libdir" "$bindir"
+		tdlname=$func_relative_path_result$dlname
+	      else
+		# Otherwise fall back on heuristic.
+		tdlname=../bin/$dlname
+	      fi
+	      ;;
+	  esac
+	  $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+	  if test "$installed" = no && test "$need_relink" = yes; then
+	    $ECHO >> $output "\
+relink_command=\"$relink_command\""
+	  fi
+	done
+      }
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+}
+
+{ test "$mode" = link || test "$mode" = relink; } &&
+    func_mode_link ${1+"$@"}
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+    $opt_debug
+    RM="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) RM="$RM $arg"; rmforce=yes ;;
+      -*) RM="$RM $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    test -z "$RM" && \
+      func_fatal_help "you must specify an RM program"
+
+    rmdirs=
+
+    origobjdir="$objdir"
+    for file in $files; do
+      func_dirname "$file" "" "."
+      dir="$func_dirname_result"
+      if test "X$dir" = X.; then
+	objdir="$origobjdir"
+      else
+	objdir="$dir/$origobjdir"
+      fi
+      func_basename "$file"
+      name="$func_basename_result"
+      test "$mode" = uninstall && objdir="$dir"
+
+      # Remember objdir for removal later, being careful to avoid duplicates
+      if test "$mode" = clean; then
+	case " $rmdirs " in
+	  *" $objdir "*) ;;
+	  *) rmdirs="$rmdirs $objdir" ;;
+	esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if { test -L "$file"; } >/dev/null 2>&1 ||
+	 { test -h "$file"; } >/dev/null 2>&1 ||
+	 test -f "$file"; then
+	:
+      elif test -d "$file"; then
+	exit_status=1
+	continue
+      elif test "$rmforce" = yes; then
+	continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+	# Possibly a libtool archive, so verify it.
+	if func_lalib_p "$file"; then
+	  func_source $dir/$name
+
+	  # Delete the libtool libraries and symlinks.
+	  for n in $library_names; do
+	    rmfiles="$rmfiles $objdir/$n"
+	  done
+	  test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+	  case "$mode" in
+	  clean)
+	    case "  $library_names " in
+	    # "  " in the beginning catches empty $dlname
+	    *" $dlname "*) ;;
+	    *) rmfiles="$rmfiles $objdir/$dlname" ;;
+	    esac
+	    test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+	    ;;
+	  uninstall)
+	    if test -n "$library_names"; then
+	      # Do each command in the postuninstall commands.
+	      func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+
+	    if test -n "$old_library"; then
+	      # Do each command in the old_postuninstall commands.
+	      func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+	    # FIXME: should reinstall the best remaining shared library.
+	    ;;
+	  esac
+	fi
+	;;
+
+      *.lo)
+	# Possibly a libtool object, so verify it.
+	if func_lalib_p "$file"; then
+
+	  # Read the .lo file
+	  func_source $dir/$name
+
+	  # Add PIC object to the list of files to remove.
+	  if test -n "$pic_object" &&
+	     test "$pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$pic_object"
+	  fi
+
+	  # Add non-PIC object to the list of files to remove.
+	  if test -n "$non_pic_object" &&
+	     test "$non_pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$non_pic_object"
+	  fi
+	fi
+	;;
+
+      *)
+	if test "$mode" = clean ; then
+	  noexename=$name
+	  case $file in
+	  *.exe)
+	    func_stripname '' '.exe' "$file"
+	    file=$func_stripname_result
+	    func_stripname '' '.exe' "$name"
+	    noexename=$func_stripname_result
+	    # $file with .exe has already been added to rmfiles,
+	    # add $file without .exe
+	    rmfiles="$rmfiles $file"
+	    ;;
+	  esac
+	  # Do a test to see if this is a libtool program.
+	  if func_ltwrapper_p "$file"; then
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      relink_command=
+	      func_source $func_ltwrapper_scriptname_result
+	      rmfiles="$rmfiles $func_ltwrapper_scriptname_result"
+	    else
+	      relink_command=
+	      func_source $dir/$noexename
+	    fi
+
+	    # note $name still contains .exe if it was in $file originally
+	    # as does the version of $file that was added into $rmfiles
+	    rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+	    if test "$fast_install" = yes && test -n "$relink_command"; then
+	      rmfiles="$rmfiles $objdir/lt-$name"
+	    fi
+	    if test "X$noexename" != "X$name" ; then
+	      rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+	    fi
+	  fi
+	fi
+	;;
+      esac
+      func_show_eval "$RM $rmfiles" 'exit_status=1'
+    done
+    objdir="$origobjdir"
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+	func_show_eval "rmdir $dir >/dev/null 2>&1"
+      fi
+    done
+
+    exit $exit_status
+}
+
+{ test "$mode" = uninstall || test "$mode" = clean; } &&
+    func_mode_uninstall ${1+"$@"}
+
+test -z "$mode" && {
+  help="$generic_help"
+  func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+  func_fatal_help "invalid operation mode \`$mode'"
+
+if test -n "$exec_cmd"; then
+  eval exec "$exec_cmd"
+  exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
+# vi:sw=2
+
diff --git a/third_party/gofrontend/libgo/config/ltoptions.m4 b/third_party/gofrontend/libgo/config/ltoptions.m4
new file mode 100644
index 0000000..5ef12ce
--- /dev/null
+++ b/third_party/gofrontend/libgo/config/ltoptions.m4
@@ -0,0 +1,369 @@
+# Helper functions for option handling.                    -*- Autoconf -*-
+#
+#   Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
+#   Inc.
+#   Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+        _LT_MANGLE_DEFUN([$1], [$2]),
+    [m4_warning([Unknown $1 option `$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+	    [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+		      [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME.  If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+    [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+  dnl
+  dnl Simply set some default values (i.e off) if boolean options were not
+  dnl specified:
+  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+  ])
+  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+  ])
+  dnl
+  dnl If no reference was made to various pairs of opposing options, then
+  dnl we run the default mode handler for the pair.  For example, if neither
+  dnl `shared' nor `disable-shared' was passed, we enable building of shared
+  dnl archives by default:
+  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+  		   [_LT_ENABLE_FAST_INSTALL])
+  ])
+])# _LT_SET_OPTIONS
+
+
+## --------------------------------- ##
+## Macros to handle LT_INIT options. ##
+## --------------------------------- ##
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS],      [1], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the `shared' and
+# `disable-shared' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+	[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+    _LT_DECL([build_libtool_libs], [enable_shared], [0],
+	[Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the `static' and
+# `disable-static' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+	[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+    _LT_DECL([build_old_libs], [enable_static], [0],
+	[Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the `fast-install'
+# and `disable-fast-install' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+	 [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the `pic-only' and `no-pic'
+# LT_INIT options.
+# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+    [AS_HELP_STRING([--with-pic],
+	[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [pic_mode="$withval"],
+    [pic_mode=default])
+
+test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+## ----------------- ##
+## LTDL_INIT Options ##
+## ----------------- ##
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+		 [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+		 [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+		 [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+		 [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+		 [m4_define([_LTDL_TYPE], [convenience])])
diff --git a/third_party/gofrontend/libgo/config/ltsugar.m4 b/third_party/gofrontend/libgo/config/ltsugar.m4
new file mode 100644
index 0000000..9000a05
--- /dev/null
+++ b/third_party/gofrontend/libgo/config/ltsugar.m4
@@ -0,0 +1,123 @@
+# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+       [$#], [2], [[$2]],
+       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59 which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+       [$#], 1, [],
+       [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+	   m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+	     [m4_foreach([_Lt_suffix],
+		]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+	[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+	  [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+		 [lt_append([$1], [$2], [$3])$4],
+		 [$5])],
+	  [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+	m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+	[$5],
+    [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+  [lt_join(m4_quote(m4_default([$4], [[, ]])),
+           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+		      [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
diff --git a/third_party/gofrontend/libgo/config/ltversion.m4 b/third_party/gofrontend/libgo/config/ltversion.m4
new file mode 100644
index 0000000..bf87f77
--- /dev/null
+++ b/third_party/gofrontend/libgo/config/ltversion.m4
@@ -0,0 +1,23 @@
+# ltversion.m4 -- version numbers			-*- Autoconf -*-
+#
+#   Copyright (C) 2004 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# Generated from ltversion.in.
+
+# serial 3134 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.2.7a])
+m4_define([LT_PACKAGE_REVISION], [1.3134])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.2.7a'
+macro_revision='1.3134'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
diff --git a/third_party/gofrontend/libgo/config/lt~obsolete.m4 b/third_party/gofrontend/libgo/config/lt~obsolete.m4
new file mode 100644
index 0000000..bf92b5e
--- /dev/null
+++ b/third_party/gofrontend/libgo/config/lt~obsolete.m4
@@ -0,0 +1,98 @@
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
+#
+#   Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 4 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else.  This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION],	[AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP],		[AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT],		[AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],	[AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN],		[AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR],		[AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL],	[AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN],		[AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER],	[AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK],		[AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],	[AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],	[AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],	[AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR],		[AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR],		[AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],	[AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC],		[AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU],		[AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG],	[AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD],	[AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS],	[AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP],	[AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP],		[AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED],		[AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME],		[AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE],	[AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE],	[AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL],		[AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP],		[AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN],		[AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],	[AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG],		[AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL],	[AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX],		[AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77],		[AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ],		[AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG],	[AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG],	[AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG],	[AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],	[AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG],	[AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG],		[AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C],	[AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS],	[AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+m4_ifndef([_LT_AC_PROG_CXXCPP],		[AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS],	[AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+m4_ifndef([_LT_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_PROG_F77],		[AC_DEFUN([_LT_PROG_F77])])
+m4_ifndef([_LT_PROG_FC],		[AC_DEFUN([_LT_PROG_FC])])
+m4_ifndef([_LT_PROG_CXX],		[AC_DEFUN([_LT_PROG_CXX])])
diff --git a/third_party/gofrontend/libgo/configure b/third_party/gofrontend/libgo/configure
new file mode 100755
index 0000000..3352c0f
--- /dev/null
+++ b/third_party/gofrontend/libgo/configure
@@ -0,0 +1,18221 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.64 for package-unused version-unused.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
+# Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1
+
+  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  # We cannot yet assume a decent shell, so we have to provide a
+	# neutralization value for shells without unset; and this also
+	# works around shells that cannot unset nonexistent variables.
+	BASH_ENV=/dev/null
+	ENV=/dev/null
+	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+	export CONFIG_SHELL
+	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='package-unused'
+PACKAGE_TARNAME='libgo'
+PACKAGE_VERSION='version-unused'
+PACKAGE_STRING='package-unused version-unused'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="Makefile.am"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+STRUCT_EPOLL_EVENT_FD_OFFSET
+SIZEOF_STRUCT_EPOLL_EVENT
+MATH_FLAG
+STRINGOPS_FLAG
+HAVE_WAIT4_FALSE
+HAVE_WAIT4_TRUE
+HAVE_STRERROR_R_FALSE
+HAVE_STRERROR_R_TRUE
+HAVE_SYS_MMAN_H_FALSE
+HAVE_SYS_MMAN_H_TRUE
+PTHREAD_LIBS
+PTHREAD_CFLAGS
+NET_LIBS
+MATH_LIBS
+GOC_IS_LLGO_FALSE
+GOC_IS_LLGO_TRUE
+USING_SPLIT_STACK_FALSE
+USING_SPLIT_STACK_TRUE
+SPLIT_STACK
+OSCFLAGS
+GO_SYSCALL_OS_ARCH_FILE
+GO_SYSCALL_OS_FILE
+GO_LIBCALL_OS_ARCH_FILE
+GO_LIBCALL_OS_FILE
+GOARCH
+LIBGO_IS_X86_64_FALSE
+LIBGO_IS_X86_64_TRUE
+LIBGO_IS_SPARC64_FALSE
+LIBGO_IS_SPARC64_TRUE
+LIBGO_IS_SPARC_FALSE
+LIBGO_IS_SPARC_TRUE
+LIBGO_IS_S390X_FALSE
+LIBGO_IS_S390X_TRUE
+LIBGO_IS_S390_FALSE
+LIBGO_IS_S390_TRUE
+LIBGO_IS_PPC64_FALSE
+LIBGO_IS_PPC64_TRUE
+LIBGO_IS_PPC_FALSE
+LIBGO_IS_PPC_TRUE
+LIBGO_IS_MIPSO64_FALSE
+LIBGO_IS_MIPSO64_TRUE
+LIBGO_IS_MIPSN64_FALSE
+LIBGO_IS_MIPSN64_TRUE
+LIBGO_IS_MIPSN32_FALSE
+LIBGO_IS_MIPSN32_TRUE
+LIBGO_IS_MIPSO32_FALSE
+LIBGO_IS_MIPSO32_TRUE
+LIBGO_IS_MIPS_FALSE
+LIBGO_IS_MIPS_TRUE
+LIBGO_IS_M68K_FALSE
+LIBGO_IS_M68K_TRUE
+LIBGO_IS_ARM64_FALSE
+LIBGO_IS_ARM64_TRUE
+LIBGO_IS_ARM_FALSE
+LIBGO_IS_ARM_TRUE
+LIBGO_IS_ALPHA_FALSE
+LIBGO_IS_ALPHA_TRUE
+LIBGO_IS_386_FALSE
+LIBGO_IS_386_TRUE
+USE_DEJAGNU
+GOOS
+LIBGO_IS_SOLARIS_FALSE
+LIBGO_IS_SOLARIS_TRUE
+LIBGO_IS_RTEMS_FALSE
+LIBGO_IS_RTEMS_TRUE
+LIBGO_IS_DRAGONFLY_FALSE
+LIBGO_IS_DRAGONFLY_TRUE
+LIBGO_IS_OPENBSD_FALSE
+LIBGO_IS_OPENBSD_TRUE
+LIBGO_IS_NETBSD_FALSE
+LIBGO_IS_NETBSD_TRUE
+LIBGO_IS_LINUX_FALSE
+LIBGO_IS_LINUX_TRUE
+LIBGO_IS_IRIX_FALSE
+LIBGO_IS_IRIX_TRUE
+LIBGO_IS_FREEBSD_FALSE
+LIBGO_IS_FREEBSD_TRUE
+LIBGO_IS_DARWIN_FALSE
+LIBGO_IS_DARWIN_TRUE
+go_include
+LIBATOMIC
+LIBFFIINCS
+LIBFFI
+nover_glibgo_toolexeclibdir
+glibgo_toolexeclibdir
+glibgo_toolexecdir
+WERROR
+WARN_FLAGS
+CC_FOR_BUILD
+enable_static
+enable_shared
+CPP
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+AR
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LIBTOOL
+OBJCOPY
+RANLIB
+LD
+FGREP
+EGREP
+GREP
+SED
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+GOCFLAGS
+GOC
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+multi_basedir
+libtool_VERSION
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_multilib
+enable_dependency_tracking
+enable_maintainer_mode
+with_gnu_ld
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+enable_libtool_lock
+enable_werror
+enable_version_specific_runtime_libs
+with_libffi
+with_libatomic
+with_system_libunwind
+enable_sjlj_exceptions
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CPP
+CPPFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)	ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information."
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures package-unused version-unused to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/libgo]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of package-unused version-unused:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-multilib       build many library versions (default)
+  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors
+  --enable-maintainer-mode  enable make rules and dependencies not useful
+			  (and sometimes confusing) to the casual installer
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-werror         turns on -Werror [default=yes]
+  --enable-version-specific-runtime-libs
+                          Specify that runtime libraries should be installed
+                          in a compiler-specific directory
+  --enable-sjlj-exceptions
+                          force use of builtin_setjmp for exceptions
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-pic              try to use only PIC/non-PIC objects [default=use
+                          both]
+  --without-libffi        don't use libffi
+  --without-libatomic     don't use libatomic
+  --with-system-libunwind use installed libunwind
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  GOC         Go compiler command
+  GOCFLAGS    Go compiler flags
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+package-unused configure version-unused
+generated by GNU Autoconf 2.64
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+	 return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+	    return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
+# --------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_c_compute_int ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if test "$cross_compiling" = yes; then
+    # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid; break
+else
+  as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=$ac_mid; break
+else
+  as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  ac_lo= ac_hi=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid
+else
+  as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in #((
+?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
+'') ac_retval=1 ;;
+esac
+  else
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+static long int longval () { return $2; }
+static unsigned long int ulongval () { return $2; }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (($2) < 0)
+    {
+      long int i = longval ();
+      if (i != ($2))
+	return 1;
+      fprintf (f, "%ld", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ($2))
+	return 1;
+      fprintf (f, "%lu", i);
+    }
+  /* Do not output a trailing newline, as this causes \r\n confusion
+     on some platforms.  */
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  echo >>conftest.val; read $3 <conftest.val; ac_retval=0
+else
+  ac_retval=1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f conftest.val
+
+  fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_compute_int
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by package-unused $as_me version-unused, which was
+generated by GNU Autoconf 2.64.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+libtool_VERSION=6:0:0
+
+
+# Default to --enable-multilib
+# Check whether --enable-multilib was given.
+if test "${enable_multilib+set}" = set; then :
+  enableval=$enable_multilib; case "$enableval" in
+  yes) multilib=yes ;;
+  no)  multilib=no ;;
+  *)   as_fn_error "bad value $enableval for multilib option" "$LINENO" 5 ;;
+ esac
+else
+  multilib=yes
+fi
+
+
+# We may get other options which we leave undocumented:
+# --with-target-subdir, --with-multisrctop, --with-multisubdir
+# See config-ml.in if you want the gory details.
+
+if test "$srcdir" = "."; then
+  if test "$with_target_subdir" != "."; then
+    multi_basedir="$srcdir/$with_multisrctop../.."
+  else
+    multi_basedir="$srcdir/$with_multisrctop.."
+  fi
+else
+  multi_basedir="$srcdir/.."
+fi
+
+
+# Even if the default multilib is not a cross compilation,
+# it may be that some of the other multilibs are.
+if test $cross_compiling = no && test $multilib = yes \
+   && test "x${with_multisubdir}" != x ; then
+   cross_compiling=maybe
+fi
+
+ac_config_commands="$ac_config_commands default-1"
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  for ac_t in install-sh install.sh shtool; do
+    if test -f "$ac_dir/$ac_t"; then
+      ac_aux_dir=$ac_dir
+      ac_install_sh="$ac_aux_dir/$ac_t -c"
+      break 2
+    fi
+  done
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if test "${ac_cv_target+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+target_alias=${target_alias-$host_alias}
+
+am__api_version='1.11'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
+    as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      as_fn_error "ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+  [\\/$]* | ?:[\\/]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='libgo'
+ VERSION='version-unused'
+
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    rm -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then :
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "C compiler cannot create executables
+See \`config.log' for more details." "$LINENO" 5; }; }
+fi
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+ac_ext=go
+ac_compile='$GOC -c $GOCFLAGS conftest.$ac_ext >&5'
+ac_link='$GOC -o conftest$ac_exeext $GOCFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compile_gnu=yes
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gccgo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gccgo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_GOC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$GOC"; then
+  ac_cv_prog_GOC="$GOC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_GOC="${ac_tool_prefix}gccgo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+GOC=$ac_cv_prog_GOC
+if test -n "$GOC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GOC" >&5
+$as_echo "$GOC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_GOC"; then
+  ac_ct_GOC=$GOC
+  # Extract the first word of "gccgo", so it can be a program name with args.
+set dummy gccgo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_GOC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_GOC"; then
+  ac_cv_prog_ac_ct_GOC="$ac_ct_GOC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_GOC="gccgo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_GOC=$ac_cv_prog_ac_ct_GOC
+if test -n "$ac_ct_GOC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_GOC" >&5
+$as_echo "$ac_ct_GOC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_GOC" = x; then
+    GOC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    GOC=$ac_ct_GOC
+  fi
+else
+  GOC="$ac_cv_prog_GOC"
+fi
+
+if test -z "$GOC"; then
+  if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}gccgo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gccgo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_GOC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$GOC"; then
+  ac_cv_prog_GOC="$GOC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_GOC="$ac_tool_prefix}gccgo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+GOC=$ac_cv_prog_GOC
+if test -n "$GOC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GOC" >&5
+$as_echo "$GOC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$GOC"; then
+  # Extract the first word of "gccgo", so it can be a program name with args.
+set dummy gccgo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_GOC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$GOC"; then
+  ac_cv_prog_GOC="$GOC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "gccgo"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_GOC="gccgo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_GOC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set GOC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_GOC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+GOC=$ac_cv_prog_GOC
+if test -n "$GOC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GOC" >&5
+$as_echo "$GOC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for Go compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+{ { ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler --version >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    rm -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+GOCFLAGS="-g -O2"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+    # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+   if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if test "${ac_cv_path_SED+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if test "${ac_cv_path_FGREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+   then ac_cv_path_FGREP="$GREP -F"
+   else
+     if test -z "$FGREP"; then
+  ac_path_FGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in fgrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+  # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'FGREP' >> "conftest.nl"
+    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_FGREP="$ac_path_FGREP"
+      ac_path_FGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_FGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_FGREP"; then
+    as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_FGREP=$FGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`print -r -- -n 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO ""
+}
+
+case "$ECHO" in
+  printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+  print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+  *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objcopy; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OBJCOPY+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJCOPY"; then
+  ac_cv_prog_OBJCOPY="$OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OBJCOPY="${ac_tool_prefix}objcopy"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJCOPY=$ac_cv_prog_OBJCOPY
+if test -n "$OBJCOPY"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJCOPY" >&5
+$as_echo "$OBJCOPY" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJCOPY"; then
+  ac_ct_OBJCOPY=$OBJCOPY
+  # Extract the first word of "objcopy", so it can be a program name with args.
+set dummy objcopy; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OBJCOPY+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJCOPY"; then
+  ac_cv_prog_ac_ct_OBJCOPY="$ac_ct_OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OBJCOPY="objcopy"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJCOPY=$ac_cv_prog_ac_ct_OBJCOPY
+if test -n "$ac_ct_OBJCOPY"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJCOPY" >&5
+$as_echo "$ac_ct_OBJCOPY" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJCOPY" = x; then
+    OBJCOPY="missing-objcopy"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJCOPY=$ac_ct_OBJCOPY
+  fi
+else
+  OBJCOPY="$ac_cv_prog_OBJCOPY"
+fi
+
+
+enable_dlopen=yes
+
+
+
+case `pwd` in
+  *\ * | *\	*)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.2.7a'
+macro_revision='1.3134'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if test "${lt_cv_path_NM+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+	*/dev/null* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in dumpbin "link -dump"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DUMPBIN+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DUMPBIN"; then
+  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$DUMPBIN" && break
+  done
+fi
+if test -z "$DUMPBIN"; then
+  ac_ct_DUMPBIN=$DUMPBIN
+  for ac_prog in dumpbin "link -dump"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DUMPBIN"; then
+  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_DUMPBIN" && break
+done
+
+  if test "x$ac_ct_DUMPBIN" = x; then
+    DUMPBIN=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DUMPBIN=$ac_ct_DUMPBIN
+  fi
+fi
+
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if test "${lt_cv_nm_interface+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+  cat conftest.out >&5
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[	 ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \
+	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OBJDUMP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if test "${lt_cv_deplibs_check_method+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_AR="ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDEGRST]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK '"\
+"     {last_section=section; section=\$ 3};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+const struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_save_LIBS="$LIBS"
+	  lt_save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$lt_save_LIBS"
+	  CFLAGS="$lt_save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&5
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE="32"
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE="64"
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    case `/usr/bin/file conftest.o` in
+	      *x86-64*)
+		LD="${LD-ld} -m elf32_x86_64"
+		;;
+	      *)
+		LD="${LD-ld} -m elf_i386"
+		;;
+	    esac
+	    ;;
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if test "${lt_cv_cc_needs_belf+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_cc_needs_belf=yes
+else
+  lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+  case $host_os in
+    rhapsody* | darwin*)
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DSYMUTIL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_NMEDIT+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+  ac_ct_NMEDIT=$NMEDIT
+  # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_NMEDIT"; then
+  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_NMEDIT="nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_NMEDIT" = x; then
+    NMEDIT=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    NMEDIT=$ac_ct_NMEDIT
+  fi
+else
+  NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_LIPO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LIPO"; then
+  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+  ac_ct_LIPO=$LIPO
+  # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_LIPO"; then
+  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_LIPO="lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_LIPO" = x; then
+    LIPO=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIPO=$ac_ct_LIPO
+  fi
+else
+  LIPO="$ac_cv_prog_LIPO"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL"; then
+  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+  ac_ct_OTOOL=$OTOOL
+  # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL"; then
+  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OTOOL="otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL" = x; then
+    OTOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL=$ac_ct_OTOOL
+  fi
+else
+  OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL64+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL64"; then
+  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+  ac_ct_OTOOL64=$OTOOL64
+  # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL64"; then
+  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OTOOL64="otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL64" = x; then
+    OTOOL64=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL64=$ac_ct_OTOOL64
+  fi
+else
+  OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if test "${lt_cv_apple_cc_single_mod+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&5
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if test "${lt_cv_ld_exported_symbols_list+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_ld_exported_symbols_list=yes
+else
+  lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+$as_echo_n "checking for -force_load linker flag... " >&6; }
+if test "${lt_cv_ld_force_load+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+      echo "$AR cru libconftest.a conftest.o" >&5
+      $AR cru libconftest.a conftest.o 2>&5
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then
+	lt_cv_ld_force_load=yes
+      else
+	cat conftest.err >&5
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+$as_echo "$lt_cv_ld_force_load" >&6; }
+    case $host_os in
+    rhapsody* | darwin1.[012])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+	10.[012][,.]*)
+	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+	10.*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in dlfcn.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gccgo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gccgo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_GOC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$GOC"; then
+  ac_cv_prog_GOC="$GOC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_GOC="${ac_tool_prefix}gccgo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+GOC=$ac_cv_prog_GOC
+if test -n "$GOC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GOC" >&5
+$as_echo "$GOC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_GOC"; then
+  ac_ct_GOC=$GOC
+  # Extract the first word of "gccgo", so it can be a program name with args.
+set dummy gccgo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_GOC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_GOC"; then
+  ac_cv_prog_ac_ct_GOC="$ac_ct_GOC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_GOC="gccgo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_GOC=$ac_cv_prog_ac_ct_GOC
+if test -n "$ac_ct_GOC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_GOC" >&5
+$as_echo "$ac_ct_GOC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_GOC" = x; then
+    GOC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    GOC=$ac_ct_GOC
+  fi
+else
+  GOC="$ac_cv_prog_GOC"
+fi
+
+
+
+
+
+
+# Set options
+
+
+
+
+  enable_win32_dll=no
+
+
+            # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+  # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+  withval=$with_pic; pic_mode="$withval"
+else
+  pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+  # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if test "${lt_cv_objdir+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+  case $cc_basename in
+  nvcc*)
+    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+  *)
+    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+  esac
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+
+
+
+  lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      lt_prog_compiler_wl='-Xlinker '
+      lt_prog_compiler_pic='-Xcompiler -fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      else
+	lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-KPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='--shared'
+	lt_prog_compiler_static='--static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fpic'
+	lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-qpic'
+	lt_prog_compiler_static='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ F* | *Sun*Fortran*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl=''
+	  ;;
+	*Sun\ C*)
+	  # Sun C 5.9
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Wl,'
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+	lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+	lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	lt_prog_compiler_pic='-Kconform_pic'
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5
+$as_echo "$lt_prog_compiler_pic" >&6; }
+
+
+
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if test "${lt_cv_prog_compiler_pic_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test "${lt_cv_prog_compiler_static_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  always_export_symbols=no
+  archive_cmds=
+  archive_expsym_cmds=
+  compiler_needs_object=no
+  enable_shared_with_static_runtimes=no
+  export_dynamic_flag_spec=
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic=no
+  hardcode_direct=no
+  hardcode_direct_absolute=no
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_flag_spec_ld=
+  hardcode_libdir_separator=
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  inherit_rpath=no
+  link_all_deplibs=unknown
+  module_cmds=
+  module_expsym_cmds=
+  old_archive_from_new_cmds=
+  old_archive_from_expsyms_cmds=
+  thread_safe_flag_spec=
+  whole_archive_flag_spec=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+	  *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	allow_undefined_flag=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      export_dynamic_flag_spec='${wl}--export-all-symbols'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    haiku*)
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      link_all_deplibs=yes
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  whole_archive_flag_spec=
+	  tmp_sharedflag='--shared' ;;
+	xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf* | bgf* | bgxlf* | mpixlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+	  hardcode_libdir_flag_spec=
+	  hardcode_libdir_flag_spec_ld='-rpath $libdir'
+	  archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        ld_shlibs=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    ld_shlibs=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	# Also, AIX nm treats weak defined symbols like other global
+	# defined symbols, whereas GNU nm marks them as "W".
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_direct_absolute=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      file_list_spec='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[012]|aix4.[012].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  hardcode_direct=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L=yes
+	  hardcode_libdir_flag_spec='-L$libdir'
+	  hardcode_libdir_separator=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      export_dynamic_flag_spec='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+	  allow_undefined_flag="-z nodefs"
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+	 hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  no_undefined_flag=' ${wl}-bernotok'
+	  allow_undefined_flag=' ${wl}-berok'
+	  if test "$with_gnu_ld" = yes; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    whole_archive_flag_spec='$convenience'
+	  fi
+	  archive_cmds_need_lc=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec=' '
+      allow_undefined_flag=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_from_new_cmds='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes=yes
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc=no
+  hardcode_direct=no
+  hardcode_automatic=yes
+  hardcode_shlibpath_var=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+  else
+    whole_archive_flag_spec=''
+  fi
+  link_all_deplibs=yes
+  allow_undefined_flag="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+  else
+  ld_shlibs=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_flag_spec_ld='+b $libdir'
+	hardcode_libdir_separator=:
+	hardcode_direct=yes
+	hardcode_direct_absolute=yes
+	export_dynamic_flag_spec='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+
+	  # Older versions of the 11.00 compiler do not understand -b yet
+	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+$as_echo_n "checking if $CC understands -b... " >&6; }
+if test "${lt_cv_prog_compiler__b+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler__b=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS -b"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler__b=yes
+       fi
+     else
+       lt_cv_prog_compiler__b=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+$as_echo "$lt_cv_prog_compiler__b" >&6; }
+
+if test x"$lt_cv_prog_compiler__b" = xyes; then
+    archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_separator=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  hardcode_direct=no
+	  hardcode_shlibpath_var=no
+	  ;;
+	*)
+	  hardcode_direct=yes
+	  hardcode_direct_absolute=yes
+	  export_dynamic_flag_spec='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  hardcode_minus_L=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+        save_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo(void) {}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+        LDFLAGS="$save_LDFLAGS"
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      inherit_rpath=yes
+      link_all_deplibs=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	hardcode_direct=yes
+	hardcode_shlibpath_var=no
+	hardcode_direct_absolute=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	  export_dynamic_flag_spec='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+	     archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     hardcode_libdir_flag_spec='-R$libdir'
+	     ;;
+	   *)
+	     archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  reload_cmds='$CC -r -o $output$reload_objs'
+	  hardcode_direct=no
+        ;;
+	motorola)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_shlibpath_var=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='${wl}-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='${wl}-z,text'
+      allow_undefined_flag='${wl}-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-R,$libdir'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	export_dynamic_flag_spec='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if test "${lt_cv_archive_cmds_need_lc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl
+	  pic_flag=$lt_prog_compiler_pic
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag
+	  allow_undefined_flag=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	  then
+	    lt_cv_archive_cmds_need_lc=no
+	  else
+	    lt_cv_archive_cmds_need_lc=yes
+	  fi
+	  allow_undefined_flag=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([A-Za-z]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[23].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+haiku*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  if test "${lt_cv_shlibpath_overrides_runpath+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+  lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+   test -n "$runpath_var" ||
+   test "X$hardcode_automatic" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink ||
+   test "$inherit_rpath" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+  if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+    ;;
+
+  *)
+    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = x""yes; then :
+  lt_cv_dlopen="shl_load"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_shl_load=yes
+else
+  ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = x""yes; then :
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_svld_dlopen=yes
+else
+  ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_dld_link=yes
+else
+  ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = x""yes; then :
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line 11122 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+void fnord () __attribute__((visibility("default")));
+#endif
+
+void fnord () { int i=42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line 11228 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+void fnord () __attribute__((visibility("default")));
+#endif
+
+void fnord () { int i=42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+    ;;
+  *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+  # Report which library types will actually be built
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[4-9]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Source file extension for Go test sources.
+ac_ext=go
+
+# Object file extension for compiled Go test sources.
+objext=o
+objext_GO=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="package main; func main() { }"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='package main; func main() { }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC="$GCC"
+GCC=yes
+CC=${GOC-"gccgo"}
+compiler=$CC
+compiler_GO=$CC
+LD_GO="$LD"
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+
+
+# Go did not exist at the time GCC didn't implicitly link libc in.
+archive_cmds_need_lc_GO=no
+
+old_archive_cmds_GO=$old_archive_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag_GO=
+
+if test "$GCC" = yes; then
+  case $cc_basename in
+  nvcc*)
+    lt_prog_compiler_no_builtin_flag_GO=' -Xcompiler -fno-builtin' ;;
+  *)
+    lt_prog_compiler_no_builtin_flag_GO=' -fno-builtin' ;;
+  esac
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag_GO="$lt_prog_compiler_no_builtin_flag_GO -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+  lt_prog_compiler_wl_GO=
+lt_prog_compiler_pic_GO=
+lt_prog_compiler_static_GO=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl_GO='-Wl,'
+    lt_prog_compiler_static_GO='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static_GO='-Bstatic'
+      fi
+      lt_prog_compiler_pic_GO='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic_GO='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            lt_prog_compiler_pic_GO='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic_GO='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic_GO='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static_GO=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic_GO='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared_GO=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic_GO='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic_GO=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic_GO='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      lt_prog_compiler_wl_GO='-Xlinker '
+      lt_prog_compiler_pic_GO='-Xcompiler -fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl_GO='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static_GO='-Bstatic'
+      else
+	lt_prog_compiler_static_GO='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic_GO='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl_GO='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic_GO='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static_GO='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl_GO='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static_GO='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+	lt_prog_compiler_wl_GO='-Wl,'
+	lt_prog_compiler_pic_GO='-KPIC'
+	lt_prog_compiler_static_GO='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	lt_prog_compiler_wl_GO='-Wl,'
+	lt_prog_compiler_pic_GO='-fPIC'
+	lt_prog_compiler_static_GO='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	lt_prog_compiler_wl_GO='-Wl,'
+	lt_prog_compiler_pic_GO='--shared'
+	lt_prog_compiler_static_GO='--static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	lt_prog_compiler_wl_GO='-Wl,'
+	lt_prog_compiler_pic_GO='-fpic'
+	lt_prog_compiler_static_GO='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl_GO='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static_GO='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+	lt_prog_compiler_wl_GO='-Wl,'
+	lt_prog_compiler_pic_GO='-qpic'
+	lt_prog_compiler_static_GO='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ F* | *Sun*Fortran*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  lt_prog_compiler_pic_GO='-KPIC'
+	  lt_prog_compiler_static_GO='-Bstatic'
+	  lt_prog_compiler_wl_GO=''
+	  ;;
+	*Sun\ C*)
+	  # Sun C 5.9
+	  lt_prog_compiler_pic_GO='-KPIC'
+	  lt_prog_compiler_static_GO='-Bstatic'
+	  lt_prog_compiler_wl_GO='-Wl,'
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic_GO='-KPIC'
+      lt_prog_compiler_static_GO='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic_GO='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl_GO='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static_GO='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static_GO='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic_GO='-KPIC'
+      lt_prog_compiler_static_GO='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+	lt_prog_compiler_wl_GO='-Qoption ld ';;
+      *)
+	lt_prog_compiler_wl_GO='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl_GO='-Qoption ld '
+      lt_prog_compiler_pic_GO='-PIC'
+      lt_prog_compiler_static_GO='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl_GO='-Wl,'
+      lt_prog_compiler_pic_GO='-KPIC'
+      lt_prog_compiler_static_GO='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	lt_prog_compiler_pic_GO='-Kconform_pic'
+	lt_prog_compiler_static_GO='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl_GO='-Wl,'
+      lt_prog_compiler_pic_GO='-KPIC'
+      lt_prog_compiler_static_GO='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl_GO='-Wl,'
+      lt_prog_compiler_can_build_shared_GO=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic_GO='-pic'
+      lt_prog_compiler_static_GO='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared_GO=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic_GO=
+    ;;
+  *)
+    lt_prog_compiler_pic_GO="$lt_prog_compiler_pic_GO"
+    ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_GO" >&5
+$as_echo "$lt_prog_compiler_pic_GO" >&6; }
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_GO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_GO works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_GO works... " >&6; }
+if test "${lt_cv_prog_compiler_pic_works_GO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works_GO=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic_GO"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works_GO=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_GO" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works_GO" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works_GO" = xyes; then
+    case $lt_prog_compiler_pic_GO in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic_GO=" $lt_prog_compiler_pic_GO" ;;
+     esac
+else
+    lt_prog_compiler_pic_GO=
+     lt_prog_compiler_can_build_shared_GO=no
+fi
+
+fi
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_GO eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GO\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test "${lt_cv_prog_compiler_static_works_GO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works_GO=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works_GO=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works_GO=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_GO" >&5
+$as_echo "$lt_cv_prog_compiler_static_works_GO" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works_GO" = xyes; then
+    :
+else
+    lt_prog_compiler_static_GO=
+fi
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o_GO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o_GO=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_GO=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_GO" >&5
+$as_echo "$lt_cv_prog_compiler_c_o_GO" >&6; }
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o_GO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o_GO=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_GO=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_GO" >&5
+$as_echo "$lt_cv_prog_compiler_c_o_GO" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_GO" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag_GO=
+  always_export_symbols_GO=no
+  archive_cmds_GO=
+  archive_expsym_cmds_GO=
+  compiler_needs_object_GO=no
+  enable_shared_with_static_runtimes_GO=no
+  export_dynamic_flag_spec_GO=
+  export_symbols_cmds_GO='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic_GO=no
+  hardcode_direct_GO=no
+  hardcode_direct_absolute_GO=no
+  hardcode_libdir_flag_spec_GO=
+  hardcode_libdir_flag_spec_ld_GO=
+  hardcode_libdir_separator_GO=
+  hardcode_minus_L_GO=no
+  hardcode_shlibpath_var_GO=unsupported
+  inherit_rpath_GO=no
+  link_all_deplibs_GO=unknown
+  module_cmds_GO=
+  module_expsym_cmds_GO=
+  old_archive_from_new_cmds_GO=
+  old_archive_from_expsyms_cmds_GO=
+  thread_safe_flag_spec_GO=
+  whole_archive_flag_spec_GO=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms_GO=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms_GO='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs_GO=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+	  *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec_GO='${wl}-rpath ${wl}$libdir'
+    export_dynamic_flag_spec_GO='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec_GO="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec_GO=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	ld_shlibs_GO=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds_GO=''
+        ;;
+      m68k)
+            archive_cmds_GO='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec_GO='-L$libdir'
+            hardcode_minus_L_GO=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	allow_undefined_flag_GO=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	archive_cmds_GO='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	ld_shlibs_GO=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, GO) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec_GO='-L$libdir'
+      export_dynamic_flag_spec_GO='${wl}--export-all-symbols'
+      allow_undefined_flag_GO=unsupported
+      always_export_symbols_GO=no
+      enable_shared_with_static_runtimes_GO=yes
+      export_symbols_cmds_GO='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	archive_expsym_cmds_GO='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	ld_shlibs_GO=no
+      fi
+      ;;
+
+    haiku*)
+      archive_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      link_all_deplibs_GO=yes
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct_GO=no
+      hardcode_shlibpath_var_GO=no
+      hardcode_libdir_flag_spec_GO='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec_GO='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds_GO='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds_GO='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  whole_archive_flag_spec_GO='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  whole_archive_flag_spec_GO='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  whole_archive_flag_spec_GO=
+	  tmp_sharedflag='--shared' ;;
+	xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  whole_archive_flag_spec_GO='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object_GO=yes
+	  ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  whole_archive_flag_spec_GO='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object_GO=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	archive_cmds_GO='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          archive_expsym_cmds_GO='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf* | bgf* | bgxlf* | mpixlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  whole_archive_flag_spec_GO='--whole-archive$convenience --no-whole-archive'
+	  hardcode_libdir_flag_spec_GO=
+	  hardcode_libdir_flag_spec_ld_GO='-rpath $libdir'
+	  archive_cmds_GO='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    archive_expsym_cmds_GO='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        ld_shlibs_GO=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds_GO='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	archive_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	ld_shlibs_GO=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs_GO=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+	ld_shlibs_GO=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    hardcode_libdir_flag_spec_GO='${wl}-rpath ${wl}$libdir'
+	    archive_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    archive_expsym_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    ld_shlibs_GO=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds_GO='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct_GO=yes
+      hardcode_shlibpath_var_GO=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs_GO=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs_GO" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec_GO=
+      export_dynamic_flag_spec_GO=
+      whole_archive_flag_spec_GO=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag_GO=unsupported
+      always_export_symbols_GO=yes
+      archive_expsym_cmds_GO='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L_GO=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	hardcode_direct_GO=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	# Also, AIX nm treats weak defined symbols like other global
+	# defined symbols, whereas GNU nm marks them as "W".
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  export_symbols_cmds_GO='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  export_symbols_cmds_GO='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds_GO=''
+      hardcode_direct_GO=yes
+      hardcode_direct_absolute_GO=yes
+      hardcode_libdir_separator_GO=':'
+      link_all_deplibs_GO=yes
+      file_list_spec_GO='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[012]|aix4.[012].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  hardcode_direct_GO=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L_GO=yes
+	  hardcode_libdir_flag_spec_GO='-L$libdir'
+	  hardcode_libdir_separator_GO=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      export_dynamic_flag_spec_GO='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols_GO=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag_GO='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec_GO='${wl}-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds_GO='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  hardcode_libdir_flag_spec_GO='${wl}-R $libdir:/usr/lib:/lib'
+	  allow_undefined_flag_GO="-z nodefs"
+	  archive_expsym_cmds_GO="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+	 hardcode_libdir_flag_spec_GO='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  no_undefined_flag_GO=' ${wl}-bernotok'
+	  allow_undefined_flag_GO=' ${wl}-berok'
+	  if test "$with_gnu_ld" = yes; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    whole_archive_flag_spec_GO='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    whole_archive_flag_spec_GO='$convenience'
+	  fi
+	  archive_cmds_need_lc_GO=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  archive_expsym_cmds_GO="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds_GO=''
+        ;;
+      m68k)
+            archive_cmds_GO='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec_GO='-L$libdir'
+            hardcode_minus_L_GO=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec_GO=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec_GO=' '
+      allow_undefined_flag_GO=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds_GO='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_from_new_cmds_GO='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds_GO='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path_GO='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes_GO=yes
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc_GO=no
+  hardcode_direct_GO=no
+  hardcode_automatic_GO=yes
+  hardcode_shlibpath_var_GO=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    whole_archive_flag_spec_GO='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+  else
+    whole_archive_flag_spec_GO=''
+  fi
+  link_all_deplibs_GO=yes
+  allow_undefined_flag_GO="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds_GO="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    module_cmds_GO="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    archive_expsym_cmds_GO="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    module_expsym_cmds_GO="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+  else
+  ld_shlibs_GO=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds_GO='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec_GO='-L$libdir'
+      hardcode_shlibpath_var_GO=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds_GO='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec_GO='-R$libdir'
+      hardcode_direct_GO=yes
+      hardcode_shlibpath_var_GO=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      archive_cmds_GO='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct_GO=yes
+      hardcode_minus_L_GO=yes
+      hardcode_shlibpath_var_GO=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds_GO='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec_GO='-R$libdir'
+      hardcode_direct_GO=yes
+      hardcode_shlibpath_var_GO=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	archive_cmds_GO='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	archive_cmds_GO='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec_GO='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator_GO=:
+      hardcode_direct_GO=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L_GO=yes
+      export_dynamic_flag_spec_GO='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	archive_cmds_GO='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds_GO='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec_GO='${wl}+b ${wl}$libdir'
+	hardcode_libdir_flag_spec_ld_GO='+b $libdir'
+	hardcode_libdir_separator_GO=:
+	hardcode_direct_GO=yes
+	hardcode_direct_absolute_GO=yes
+	export_dynamic_flag_spec_GO='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	hardcode_minus_L_GO=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds_GO='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds_GO='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds_GO='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds_GO='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds_GO='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	archive_cmds_GO='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec_GO='${wl}+b ${wl}$libdir'
+	hardcode_libdir_separator_GO=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  hardcode_direct_GO=no
+	  hardcode_shlibpath_var_GO=no
+	  ;;
+	*)
+	  hardcode_direct_GO=yes
+	  hardcode_direct_absolute_GO=yes
+	  export_dynamic_flag_spec_GO='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  hardcode_minus_L_GO=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	archive_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+        save_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo(void) {}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  archive_expsym_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+        LDFLAGS="$save_LDFLAGS"
+      else
+	archive_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds_GO='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc_GO='no'
+      hardcode_libdir_flag_spec_GO='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_GO=:
+      inherit_rpath_GO=yes
+      link_all_deplibs_GO=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds_GO='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	archive_cmds_GO='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec_GO='-R$libdir'
+      hardcode_direct_GO=yes
+      hardcode_shlibpath_var_GO=no
+      ;;
+
+    newsos6)
+      archive_cmds_GO='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct_GO=yes
+      hardcode_libdir_flag_spec_GO='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_GO=:
+      hardcode_shlibpath_var_GO=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	hardcode_direct_GO=yes
+	hardcode_shlibpath_var_GO=no
+	hardcode_direct_absolute_GO=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  archive_cmds_GO='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds_GO='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  hardcode_libdir_flag_spec_GO='${wl}-rpath,$libdir'
+	  export_dynamic_flag_spec_GO='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+	     archive_cmds_GO='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     hardcode_libdir_flag_spec_GO='-R$libdir'
+	     ;;
+	   *)
+	     archive_cmds_GO='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     hardcode_libdir_flag_spec_GO='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	ld_shlibs_GO=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec_GO='-L$libdir'
+      hardcode_minus_L_GO=yes
+      allow_undefined_flag_GO=unsupported
+      archive_cmds_GO='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_from_new_cmds_GO='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	allow_undefined_flag_GO=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds_GO='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	allow_undefined_flag_GO=' -expect_unresolved \*'
+	archive_cmds_GO='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc_GO='no'
+      hardcode_libdir_flag_spec_GO='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_GO=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	allow_undefined_flag_GO=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds_GO='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	hardcode_libdir_flag_spec_GO='${wl}-rpath ${wl}$libdir'
+      else
+	allow_undefined_flag_GO=' -expect_unresolved \*'
+	archive_cmds_GO='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds_GO='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	hardcode_libdir_flag_spec_GO='-rpath $libdir'
+      fi
+      archive_cmds_need_lc_GO='no'
+      hardcode_libdir_separator_GO=:
+      ;;
+
+    solaris*)
+      no_undefined_flag_GO=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	archive_cmds_GO='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds_GO='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  archive_cmds_GO='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  archive_expsym_cmds_GO='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  archive_cmds_GO='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds_GO='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      hardcode_libdir_flag_spec_GO='-R$libdir'
+      hardcode_shlibpath_var_GO=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  whole_archive_flag_spec_GO='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  whole_archive_flag_spec_GO='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      link_all_deplibs_GO=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	archive_cmds_GO='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds_GO='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec_GO='-L$libdir'
+      hardcode_direct_GO=yes
+      hardcode_minus_L_GO=yes
+      hardcode_shlibpath_var_GO=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  archive_cmds_GO='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct_GO=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  archive_cmds_GO='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  reload_cmds_GO='$CC -r -o $output$reload_objs'
+	  hardcode_direct_GO=no
+        ;;
+	motorola)
+	  archive_cmds_GO='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct_GO=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var_GO=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds_GO='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var_GO=no
+      export_dynamic_flag_spec_GO='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	archive_cmds_GO='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_shlibpath_var_GO=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	ld_shlibs_GO=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag_GO='${wl}-z,text'
+      archive_cmds_need_lc_GO=no
+      hardcode_shlibpath_var_GO=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds_GO='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds_GO='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds_GO='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds_GO='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag_GO='${wl}-z,text'
+      allow_undefined_flag_GO='${wl}-z,nodefs'
+      archive_cmds_need_lc_GO=no
+      hardcode_shlibpath_var_GO=no
+      hardcode_libdir_flag_spec_GO='${wl}-R,$libdir'
+      hardcode_libdir_separator_GO=':'
+      link_all_deplibs_GO=yes
+      export_dynamic_flag_spec_GO='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds_GO='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds_GO='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds_GO='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds_GO='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds_GO='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec_GO='-L$libdir'
+      hardcode_shlibpath_var_GO=no
+      ;;
+
+    *)
+      ld_shlibs_GO=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	export_dynamic_flag_spec_GO='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_GO" >&5
+$as_echo "$ld_shlibs_GO" >&6; }
+test "$ld_shlibs_GO" = no && can_build_shared=no
+
+with_gnu_ld_GO=$with_gnu_ld
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_GO" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc_GO=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds_GO in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if test "${lt_cv_archive_cmds_need_lc_GO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl_GO
+	  pic_flag=$lt_prog_compiler_pic_GO
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag_GO
+	  allow_undefined_flag_GO=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_GO 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds_GO 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	  then
+	    lt_cv_archive_cmds_need_lc_GO=no
+	  else
+	    lt_cv_archive_cmds_need_lc_GO=yes
+	  fi
+	  allow_undefined_flag_GO=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_GO" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc_GO" >&6; }
+      archive_cmds_need_lc_GO=$lt_cv_archive_cmds_need_lc_GO
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action_GO=
+if test -n "$hardcode_libdir_flag_spec_GO" ||
+   test -n "$runpath_var_GO" ||
+   test "X$hardcode_automatic_GO" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$hardcode_direct_GO" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, GO)" != no &&
+     test "$hardcode_minus_L_GO" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action_GO=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action_GO=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action_GO=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_GO" >&5
+$as_echo "$hardcode_action_GO" >&6; }
+
+if test "$hardcode_action_GO" = relink ||
+   test "$inherit_rpath_GO" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+GCC=$lt_save_GCC
+CC="$lt_save_CC"
+
+
+
+
+        ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+
+
+
+CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
+
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+
+WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
+
+
+# Check whether --enable-werror was given.
+if test "${enable_werror+set}" = set; then :
+  enableval=$enable_werror;
+fi
+
+if test "x$enable_werror" != "xno"; then
+  WERROR="-Werror"
+fi
+
+
+glibgo_toolexecdir=no
+glibgo_toolexeclibdir=no
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-version-specific-runtime-libs" >&5
+$as_echo_n "checking for --enable-version-specific-runtime-libs... " >&6; }
+# Check whether --enable-version-specific-runtime-libs was given.
+if test "${enable_version_specific_runtime_libs+set}" = set; then :
+  enableval=$enable_version_specific_runtime_libs; case "$enableval" in
+    yes) version_specific_libs=yes ;;
+    no)  version_specific_libs=no ;;
+    *)   as_fn_error "Unknown argument to enable/disable version-specific libs" "$LINENO" 5;;
+   esac
+else
+  version_specific_libs=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $version_specific_libs" >&5
+$as_echo "$version_specific_libs" >&6; }
+
+# Version-specific runtime libs processing.
+if test $version_specific_libs = yes; then
+  glibgo_toolexecdir='${libdir}/gcc/${host_alias}'
+  glibgo_toolexeclibdir='${toolexecdir}/${gcc_version}$(MULTISUBDIR)'
+fi
+
+# Calculate glibgo_toolexecdir, glibgo_toolexeclibdir
+# Install a library built with a cross compiler in tooldir, not libdir.
+if test -n "$with_cross_host" &&
+   test x"$with_cross_host" != x"no"; then
+  nover_glibgo_toolexecdir='${exec_prefix}/${host_alias}'
+  nover_glibgo_toolexeclibdir='${toolexecdir}/lib'
+else
+  nover_glibgo_toolexecdir='${libdir}/gcc/${host_alias}'
+  nover_glibgo_toolexeclibdir='${libdir}'
+fi
+multi_os_directory=`$GOC -print-multi-os-directory`
+case $multi_os_directory in
+  .) ;; # Avoid trailing /.
+  *) nover_glibgo_toolexeclibdir=${nover_glibgo_toolexeclibdir}/${multi_os_directory} ;;
+esac
+
+if test x"$glibgo_toolexecdir" = x"no"; then
+  glibgo_toolexecdir="${nover_glibgo_toolexecdir}"
+  glibgo_toolexeclibdir="${nover_glibgo_toolexeclibdir}"
+fi
+
+
+
+
+
+# See if the user wants to configure without libffi.  Some
+# architectures don't support it.  FIXME: We should set a default
+# based on the host.
+
+# Check whether --with-libffi was given.
+if test "${with_libffi+set}" = set; then :
+  withval=$with_libffi; :
+else
+  with_libffi=${with_libffi_default-yes}
+fi
+
+
+LIBFFI=
+LIBFFIINCS=
+if test "$with_libffi" != no; then
+
+$as_echo "#define USE_LIBFFI 1" >>confdefs.h
+
+   LIBFFI=../libffi/libffi_convenience.la
+   LIBFFIINCS='-I$(top_srcdir)/../libffi/include -I../libffi/include'
+fi
+
+
+
+# See if the user wants to configure without libatomic. This is useful if we are
+# on an architecture for which libgo does not need an atomic support library and
+# libatomic does not support our C compiler.
+
+# Check whether --with-libatomic was given.
+if test "${with_libatomic+set}" = set; then :
+  withval=$with_libatomic; :
+else
+  with_libatomic=${with_libatomic_default-yes}
+fi
+
+
+LIBATOMIC=
+if test "$with_libatomic" != no; then
+   LIBATOMIC=../libatomic/libatomic_convenience.la
+fi
+
+
+# Used to tell GNU make to include a file without telling automake to
+# include it.
+go_include="-include"
+
+
+is_darwin=no
+is_freebsd=no
+is_irix=no
+is_linux=no
+is_netbsd=no
+is_openbsd=no
+is_dragonfly=no
+is_rtems=no
+is_solaris=no
+GOOS=unknown
+case ${host} in
+  *-*-darwin*)   is_darwin=yes;  GOOS=darwin ;;
+  *-*-freebsd*)  is_freebsd=yes; GOOS=freebsd ;;
+  *-*-irix6*)    is_irix=yes;    GOOS=irix ;;
+  *-*-linux*)    is_linux=yes;   GOOS=linux ;;
+  *-*-netbsd*)	 is_netbsd=yes;  GOOS=netbsd ;;
+  *-*-openbsd*)  is_openbsd=yes; GOOS=openbsd ;;
+  *-*-dragonfly*) is_dragonfly=yes; GOOS=dragonfly ;;
+  *-*-rtems*)    is_rtems=yes;   GOOS=rtems ;;
+  *-*-solaris2*) is_solaris=yes; GOOS=solaris ;;
+esac
+ if test $is_darwin = yes; then
+  LIBGO_IS_DARWIN_TRUE=
+  LIBGO_IS_DARWIN_FALSE='#'
+else
+  LIBGO_IS_DARWIN_TRUE='#'
+  LIBGO_IS_DARWIN_FALSE=
+fi
+
+ if test $is_freebsd = yes; then
+  LIBGO_IS_FREEBSD_TRUE=
+  LIBGO_IS_FREEBSD_FALSE='#'
+else
+  LIBGO_IS_FREEBSD_TRUE='#'
+  LIBGO_IS_FREEBSD_FALSE=
+fi
+
+ if test $is_irix = yes; then
+  LIBGO_IS_IRIX_TRUE=
+  LIBGO_IS_IRIX_FALSE='#'
+else
+  LIBGO_IS_IRIX_TRUE='#'
+  LIBGO_IS_IRIX_FALSE=
+fi
+
+ if test $is_linux = yes; then
+  LIBGO_IS_LINUX_TRUE=
+  LIBGO_IS_LINUX_FALSE='#'
+else
+  LIBGO_IS_LINUX_TRUE='#'
+  LIBGO_IS_LINUX_FALSE=
+fi
+
+ if test $is_netbsd = yes; then
+  LIBGO_IS_NETBSD_TRUE=
+  LIBGO_IS_NETBSD_FALSE='#'
+else
+  LIBGO_IS_NETBSD_TRUE='#'
+  LIBGO_IS_NETBSD_FALSE=
+fi
+
+ if test $is_openbsd = yes; then
+  LIBGO_IS_OPENBSD_TRUE=
+  LIBGO_IS_OPENBSD_FALSE='#'
+else
+  LIBGO_IS_OPENBSD_TRUE='#'
+  LIBGO_IS_OPENBSD_FALSE=
+fi
+
+ if test $is_dragonfly = yes; then
+  LIBGO_IS_DRAGONFLY_TRUE=
+  LIBGO_IS_DRAGONFLY_FALSE='#'
+else
+  LIBGO_IS_DRAGONFLY_TRUE='#'
+  LIBGO_IS_DRAGONFLY_FALSE=
+fi
+
+ if test $is_rtems = yes; then
+  LIBGO_IS_RTEMS_TRUE=
+  LIBGO_IS_RTEMS_FALSE='#'
+else
+  LIBGO_IS_RTEMS_TRUE='#'
+  LIBGO_IS_RTEMS_FALSE=
+fi
+
+ if test $is_solaris = yes; then
+  LIBGO_IS_SOLARIS_TRUE=
+  LIBGO_IS_SOLARIS_FALSE='#'
+else
+  LIBGO_IS_SOLARIS_TRUE='#'
+  LIBGO_IS_SOLARIS_FALSE=
+fi
+
+
+
+USE_DEJAGNU=no
+case ${host} in
+  *-*-rtems*) USE_DEJAGNU=yes ;;
+  ${build}) ;;
+  *) USE_DEJAGNU=yes ;;
+esac
+
+
+is_386=no
+is_alpha=no
+is_arm=no
+is_arm64=no
+is_m68k=no
+mips_abi=unknown
+is_ppc=no
+is_ppc64=no
+is_s390=no
+is_s390x=no
+is_sparc=no
+is_sparc64=no
+is_x86_64=no
+GOARCH=unknown
+case ${host} in
+  alpha*-*-*)
+    is_alpha=yes
+    GOARCH=alpha
+    ;;
+  aarch64-*-*)
+    is_arm64=yes
+    GOARCH=arm64
+    ;;
+  arm*-*-* | strongarm*-*-* | ep9312*-*-* | xscale-*-*)
+    is_arm=yes
+    GOARCH=arm
+    ;;
+  i[34567]86-*-* | x86_64-*-*)
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#ifdef __x86_64__
+#error 64-bit
+#endif
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  is_386=yes
+else
+  is_x86_64=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test "$is_386" = "yes"; then
+      GOARCH=386
+    else
+      GOARCH=amd64
+    fi
+    ;;
+  m68k*-*-*)
+    is_m68k=yes
+    GOARCH=m68k
+    ;;
+  mips*-*-*)
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#if _MIPS_SIM != _ABIO32
+#error not o32
+#endif
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  mips_abi="o32"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#if _MIPS_SIM != _ABIN32
+#error not n32
+#endif
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  mips_abi="n32"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#if _MIPS_SIM != _ABI64
+#error not n64
+#endif
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  mips_abi="n64"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#if _MIPS_SIM != _ABIO64
+#error not o64
+#endif
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  mips_abi="o64"
+else
+  as_fn_error "unknown MIPS ABI" "$LINENO" 5
+mips_abi="n32"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    case "$mips_abi" in
+    "o32") GOARCH=mipso32 ;;
+    "n32") GOARCH=mipsn32 ;;
+    "n64") GOARCH=mipsn64 ;;
+    "o64") GOARCH=mipso64 ;;
+    esac
+    ;;
+  rs6000*-*-* | powerpc*-*-*)
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#ifdef _ARCH_PPC64
+#error 64-bit
+#endif
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  is_ppc=yes
+else
+  is_ppc64=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test "$is_ppc" = "yes"; then
+      GOARCH=ppc
+    else
+      GOARCH=ppc64
+    fi
+    ;;
+  s390*-*-*)
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#if defined(__s390x__)
+#error 64-bit
+#endif
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  is_s390=yes
+else
+  is_s390x=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test "$is_s390" = "yes"; then
+      GOARCH=s390
+    else
+      GOARCH=s390x
+    fi
+    ;;
+  sparc*-*-*)
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#if defined(__sparcv9) || defined(__arch64__)
+#error 64-bit
+#endif
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  is_sparc=yes
+else
+  is_sparc64=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test "$is_sparc" = "yes"; then
+      GOARCH=sparc
+    else
+      GOARCH=sparc64
+    fi
+    ;;
+esac
+ if test $is_386 = yes; then
+  LIBGO_IS_386_TRUE=
+  LIBGO_IS_386_FALSE='#'
+else
+  LIBGO_IS_386_TRUE='#'
+  LIBGO_IS_386_FALSE=
+fi
+
+ if test $is_alpha = yes; then
+  LIBGO_IS_ALPHA_TRUE=
+  LIBGO_IS_ALPHA_FALSE='#'
+else
+  LIBGO_IS_ALPHA_TRUE='#'
+  LIBGO_IS_ALPHA_FALSE=
+fi
+
+ if test $is_arm = yes; then
+  LIBGO_IS_ARM_TRUE=
+  LIBGO_IS_ARM_FALSE='#'
+else
+  LIBGO_IS_ARM_TRUE='#'
+  LIBGO_IS_ARM_FALSE=
+fi
+
+ if test $is_arm64 = yes; then
+  LIBGO_IS_ARM64_TRUE=
+  LIBGO_IS_ARM64_FALSE='#'
+else
+  LIBGO_IS_ARM64_TRUE='#'
+  LIBGO_IS_ARM64_FALSE=
+fi
+
+ if test $is_m68k = yes; then
+  LIBGO_IS_M68K_TRUE=
+  LIBGO_IS_M68K_FALSE='#'
+else
+  LIBGO_IS_M68K_TRUE='#'
+  LIBGO_IS_M68K_FALSE=
+fi
+
+ if test $mips_abi != unknown; then
+  LIBGO_IS_MIPS_TRUE=
+  LIBGO_IS_MIPS_FALSE='#'
+else
+  LIBGO_IS_MIPS_TRUE='#'
+  LIBGO_IS_MIPS_FALSE=
+fi
+
+ if test $mips_abi = o32; then
+  LIBGO_IS_MIPSO32_TRUE=
+  LIBGO_IS_MIPSO32_FALSE='#'
+else
+  LIBGO_IS_MIPSO32_TRUE='#'
+  LIBGO_IS_MIPSO32_FALSE=
+fi
+
+ if test $mips_abi = n32; then
+  LIBGO_IS_MIPSN32_TRUE=
+  LIBGO_IS_MIPSN32_FALSE='#'
+else
+  LIBGO_IS_MIPSN32_TRUE='#'
+  LIBGO_IS_MIPSN32_FALSE=
+fi
+
+ if test $mips_abi = n64; then
+  LIBGO_IS_MIPSN64_TRUE=
+  LIBGO_IS_MIPSN64_FALSE='#'
+else
+  LIBGO_IS_MIPSN64_TRUE='#'
+  LIBGO_IS_MIPSN64_FALSE=
+fi
+
+ if test $mips_abi = o64; then
+  LIBGO_IS_MIPSO64_TRUE=
+  LIBGO_IS_MIPSO64_FALSE='#'
+else
+  LIBGO_IS_MIPSO64_TRUE='#'
+  LIBGO_IS_MIPSO64_FALSE=
+fi
+
+ if test $is_ppc = yes; then
+  LIBGO_IS_PPC_TRUE=
+  LIBGO_IS_PPC_FALSE='#'
+else
+  LIBGO_IS_PPC_TRUE='#'
+  LIBGO_IS_PPC_FALSE=
+fi
+
+ if test $is_ppc64 = yes; then
+  LIBGO_IS_PPC64_TRUE=
+  LIBGO_IS_PPC64_FALSE='#'
+else
+  LIBGO_IS_PPC64_TRUE='#'
+  LIBGO_IS_PPC64_FALSE=
+fi
+
+ if test $is_s390 = yes; then
+  LIBGO_IS_S390_TRUE=
+  LIBGO_IS_S390_FALSE='#'
+else
+  LIBGO_IS_S390_TRUE='#'
+  LIBGO_IS_S390_FALSE=
+fi
+
+ if test $is_s390x = yes; then
+  LIBGO_IS_S390X_TRUE=
+  LIBGO_IS_S390X_FALSE='#'
+else
+  LIBGO_IS_S390X_TRUE='#'
+  LIBGO_IS_S390X_FALSE=
+fi
+
+ if test $is_sparc = yes; then
+  LIBGO_IS_SPARC_TRUE=
+  LIBGO_IS_SPARC_FALSE='#'
+else
+  LIBGO_IS_SPARC_TRUE='#'
+  LIBGO_IS_SPARC_FALSE=
+fi
+
+ if test $is_sparc64 = yes; then
+  LIBGO_IS_SPARC64_TRUE=
+  LIBGO_IS_SPARC64_FALSE='#'
+else
+  LIBGO_IS_SPARC64_TRUE='#'
+  LIBGO_IS_SPARC64_FALSE=
+fi
+
+ if test $is_x86_64 = yes; then
+  LIBGO_IS_X86_64_TRUE=
+  LIBGO_IS_X86_64_FALSE='#'
+else
+  LIBGO_IS_X86_64_TRUE='#'
+  LIBGO_IS_X86_64_FALSE=
+fi
+
+
+
+GO_LIBCALL_OS_FILE=
+GO_LIBCALL_OS_ARCH_FILE=
+GO_SYSCALL_OS_FILE=
+GO_SYSCALL_OS_ARCH_FILE=
+if test -f "${srcdir}/go/syscall/libcall_${GOOS}.go"; then
+  GO_LIBCALL_OS_FILE="go/syscall/libcall_${GOOS}.go"
+fi
+if test -f "${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go"; then
+  GO_LIBCALL_OS_ARCH_FILE="go/syscall/libcall_${GOOS}_${GOARCH}.go"
+fi
+if test -f "${srcdir}/go/syscall/syscall_${GOOS}.go"; then
+  GO_SYSCALL_OS_FILE="go/syscall/syscall_${GOOS}.go"
+fi
+if test -f "${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go"; then
+  GO_SYSCALL_OS_ARCH_FILE="go/syscall/syscall_${GOOS}_${GOARCH}.go"
+fi
+
+
+
+
+
+OSCFLAGS="-D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+case "$target" in
+    mips-sgi-irix6.5*)
+	# IRIX 6 needs _XOPEN_SOURCE=500 for the XPG5 version of struct
+	# msghdr in <sys/socket.h>.
+	OSCFLAGS="$OSCFLAGS -D_XOPEN_SOURCE=500"
+	;;
+    *-*-solaris2.1[01])
+	# Solaris 10+ needs this so struct msghdr gets the msg_control
+	# etc. fields in <sys/socket.h> (_XPG4_2).  _XOPEN_SOURCE=600 as
+	# above doesn't work with C99.
+	OSCFLAGS="$OSCFLAGS -std=gnu99 -D_XOPEN_SOURCE=600 -D__EXTENSIONS__"
+	;;
+esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -fsplit-stack is supported" >&5
+$as_echo_n "checking whether -fsplit-stack is supported... " >&6; }
+if test "${libgo_cv_c_split_stack_supported+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -fsplit-stack"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgo_cv_c_split_stack_supported=yes
+else
+  libgo_cv_c_split_stack_supported=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS=$CFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_split_stack_supported" >&5
+$as_echo "$libgo_cv_c_split_stack_supported" >&6; }
+if test "$libgo_cv_c_split_stack_supported" = yes; then
+  SPLIT_STACK=-fsplit-stack
+
+$as_echo "#define USING_SPLIT_STACK 1" >>confdefs.h
+
+else
+  SPLIT_STACK=
+fi
+
+ if test "$libgo_cv_c_split_stack_supported" = yes; then
+  USING_SPLIT_STACK_TRUE=
+  USING_SPLIT_STACK_FALSE='#'
+else
+  USING_SPLIT_STACK_TRUE='#'
+  USING_SPLIT_STACK_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether linker supports split stack" >&5
+$as_echo_n "checking whether linker supports split stack... " >&6; }
+if test "${libgo_cv_c_linker_supports_split_stack+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  libgo_cv_c_linker_supports_split_stack=no
+if $GOC -Wl,--help 2>/dev/null | grep split-stack-adjust-size >/dev/null 2>&1; then
+  libgo_cv_c_linker_supports_split_stack=yes
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_linker_supports_split_stack" >&5
+$as_echo "$libgo_cv_c_linker_supports_split_stack" >&6; }
+if test "$libgo_cv_c_linker_supports_split_stack" = yes; then
+
+$as_echo "#define LINKER_SUPPORTS_SPLIT_STACK 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler is llgo" >&5
+$as_echo_n "checking whether compiler is llgo... " >&6; }
+if test "${libgo_cv_c_goc_is_llgo+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  libgo_cv_c_goc_is_llgo=no
+if $GOC -dumpversion 2>/dev/null | grep llgo >/dev/null 2>&1; then
+  libgo_cv_c_goc_is_llgo=yes
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_goc_is_llgo" >&5
+$as_echo "$libgo_cv_c_goc_is_llgo" >&6; }
+ if test "$libgo_cv_c_goc_is_llgo" = yes; then
+  GOC_IS_LLGO_TRUE=
+  GOC_IS_LLGO_FALSE='#'
+else
+  GOC_IS_LLGO_TRUE='#'
+  GOC_IS_LLGO_FALSE=
+fi
+
+
+MATH_LIBS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqrt in -lm" >&5
+$as_echo_n "checking for sqrt in -lm... " >&6; }
+if test "${ac_cv_lib_m_sqrt+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sqrt ();
+int
+main ()
+{
+return sqrt ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_m_sqrt=yes
+else
+  ac_cv_lib_m_sqrt=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sqrt" >&5
+$as_echo "$ac_cv_lib_m_sqrt" >&6; }
+if test "x$ac_cv_lib_m_sqrt" = x""yes; then :
+  MATH_LIBS=-lm
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket libraries" >&5
+$as_echo_n "checking for socket libraries... " >&6; }
+if test "${libgo_cv_lib_sockets+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  libgo_cv_lib_sockets=
+   libgo_check_both=no
+   ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
+if test "x$ac_cv_func_connect" = x""yes; then :
+  libgo_check_socket=no
+else
+  libgo_check_socket=yes
+fi
+
+   if test "$libgo_check_socket" = "yes"; then
+     unset ac_cv_func_connect
+     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5
+$as_echo_n "checking for main in -lsocket... " >&6; }
+if test "${ac_cv_lib_socket_main+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_socket_main=yes
+else
+  ac_cv_lib_socket_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5
+$as_echo "$ac_cv_lib_socket_main" >&6; }
+if test "x$ac_cv_lib_socket_main" = x""yes; then :
+  libgo_cv_lib_sockets="-lsocket"
+else
+  libgo_check_both=yes
+fi
+
+   fi
+   if test "$libgo_check_both" = "yes"; then
+     libgo_old_libs=$LIBS
+     LIBS="$LIBS -lsocket -lnsl"
+     unset ac_cv_func_accept
+     ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept"
+if test "x$ac_cv_func_accept" = x""yes; then :
+  libgo_check_nsl=no
+		    libgo_cv_lib_sockets="-lsocket -lnsl"
+fi
+
+     unset ac_cv_func_accept
+     LIBS=$libgo_old_libs
+   fi
+   unset ac_cv_func_gethostbyname
+   libgo_old_libs="$LIBS"
+   ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
+if test "x$ac_cv_func_gethostbyname" = x""yes; then :
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5
+$as_echo_n "checking for main in -lnsl... " >&6; }
+if test "${ac_cv_lib_nsl_main+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_nsl_main=yes
+else
+  ac_cv_lib_nsl_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5
+$as_echo "$ac_cv_lib_nsl_main" >&6; }
+if test "x$ac_cv_lib_nsl_main" = x""yes; then :
+  libgo_cv_lib_sockets="$libgo_cv_lib_sockets -lnsl"
+fi
+
+fi
+
+   unset ac_cv_func_gethostbyname
+   LIBS=$libgo_old_libs
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_lib_sockets" >&5
+$as_echo "$libgo_cv_lib_sockets" >&6; }
+NET_LIBS="$libgo_cv_lib_sockets"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -pthread is supported" >&5
+$as_echo_n "checking whether -pthread is supported... " >&6; }
+if test "${libgo_cv_lib_pthread+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -pthread"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgo_cv_lib_pthread=yes
+else
+  libgo_cv_lib_pthread=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS=$CFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_lib_pthread" >&5
+$as_echo "$libgo_cv_lib_pthread" >&6; }
+PTHREAD_CFLAGS=
+if test "$libgo_cv_lib_pthread" = yes; then
+  PTHREAD_CFLAGS=-pthread
+fi
+
+
+PTHREAD_LIBS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
+if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pthread_pthread_create=yes
+else
+  ac_cv_lib_pthread_pthread_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = x""yes; then :
+  PTHREAD_LIBS=-lpthread
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sched_yield" >&5
+$as_echo_n "checking for library containing sched_yield... " >&6; }
+if test "${ac_cv_search_sched_yield+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sched_yield ();
+int
+main ()
+{
+return sched_yield ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' rt; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_sched_yield=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if test "${ac_cv_search_sched_yield+set}" = set; then :
+  break
+fi
+done
+if test "${ac_cv_search_sched_yield+set}" = set; then :
+
+else
+  ac_cv_search_sched_yield=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sched_yield" >&5
+$as_echo "$ac_cv_search_sched_yield" >&6; }
+ac_res=$ac_cv_search_sched_yield
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing nanosleep" >&5
+$as_echo_n "checking for library containing nanosleep... " >&6; }
+if test "${ac_cv_search_nanosleep+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nanosleep ();
+int
+main ()
+{
+return nanosleep ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' rt; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_nanosleep=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if test "${ac_cv_search_nanosleep+set}" = set; then :
+  break
+fi
+done
+if test "${ac_cv_search_nanosleep+set}" = set; then :
+
+else
+  ac_cv_search_nanosleep=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_nanosleep" >&5
+$as_echo "$ac_cv_search_nanosleep" >&6; }
+ac_res=$ac_cv_search_nanosleep
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_bigendian=unknown
+    # See if we're dealing with a universal compiler.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __APPLE_CC__
+	       not a universal capable compiler
+	     #endif
+	     typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+	# Check for potential -arch flags.  It is not universal unless
+	# there are at least two -arch flags with different values.
+	ac_arch=
+	ac_prev=
+	for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+	 if test -n "$ac_prev"; then
+	   case $ac_word in
+	     i?86 | x86_64 | ppc | ppc64)
+	       if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+		 ac_arch=$ac_word
+	       else
+		 ac_cv_c_bigendian=universal
+		 break
+	       fi
+	       ;;
+	   esac
+	   ac_prev=
+	 elif test "x$ac_word" = "x-arch"; then
+	   ac_prev=arch
+	 fi
+       done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if sys/param.h defines the BYTE_ORDER macro.
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+	     #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+		     && LITTLE_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+		#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to _BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # Compile a test program.
+      if test "$cross_compiling" = yes; then :
+  # Try to guess by grepping values from an object file.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+short int ascii_mm[] =
+		  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+		short int ascii_ii[] =
+		  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+		int use_ascii (int i) {
+		  return ascii_mm[i] + ascii_ii[i];
+		}
+		short int ebcdic_ii[] =
+		  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+		short int ebcdic_mm[] =
+		  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+		int use_ebcdic (int i) {
+		  return ebcdic_mm[i] + ebcdic_ii[i];
+		}
+		extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+	      ac_cv_c_bigendian=yes
+	    fi
+	    if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+	      if test "$ac_cv_c_bigendian" = unknown; then
+		ac_cv_c_bigendian=no
+	      else
+		# finding both strings is unlikely to happen, but who knows?
+		ac_cv_c_bigendian=unknown
+	      fi
+	    fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+	     /* Are we little or big endian?  From Harbison&Steele.  */
+	     union
+	     {
+	       long int l;
+	       char c[sizeof (long int)];
+	     } u;
+	     u.l = 1;
+	     return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_bigendian=no
+else
+  ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+   yes)
+     $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+   no)
+      ;; #(
+   universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+     ;; #(
+   *)
+     as_fn_error "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+
+
+
+# Check whether --with-system-libunwind was given.
+if test "${with_system_libunwind+set}" = set; then :
+  withval=$with_system_libunwind;
+fi
+
+  # If system-libunwind was not specifically set, pick a default setting.
+  if test x$with_system_libunwind = x; then
+    case ${target} in
+      ia64-*-hpux*) with_system_libunwind=yes ;;
+      *) with_system_libunwind=no ;;
+    esac
+  fi
+  # Based on system-libunwind and target, do we have ipinfo?
+  if  test x$with_system_libunwind = xyes; then
+    case ${target} in
+      ia64-*-*) have_unwind_getipinfo=no ;;
+      *) have_unwind_getipinfo=yes ;;
+    esac
+  else
+    # Darwin before version 9 does not have _Unwind_GetIPInfo.
+
+    case ${target} in
+      *-*-darwin[3-8]|*-*-darwin[3-8].*) have_unwind_getipinfo=no ;;
+      *) have_unwind_getipinfo=yes ;;
+    esac
+
+  fi
+
+  if test x$have_unwind_getipinfo = xyes; then
+
+$as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h
+
+  fi
+
+
+# Check whether --enable-sjlj-exceptions was given.
+if test "${enable_sjlj_exceptions+set}" = set; then :
+  enableval=$enable_sjlj_exceptions; case "$enableval" in
+   yes|no|auto) ;;
+   *) as_fn_error "unknown argument to --enable-sjlj-exceptions" "$LINENO" 5 ;;
+   esac
+else
+  enable_sjlj_exceptions=auto
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use setjmp/longjmp exceptions" >&5
+$as_echo_n "checking whether to use setjmp/longjmp exceptions... " >&6; }
+if test "${libgo_cv_lib_sjlj_exceptions+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+void bar ();
+void clean (int *);
+void foo ()
+{
+  int i __attribute__ ((cleanup (clean)));
+  bar();
+}
+
+_ACEOF
+CFLAGS_hold=$CFLAGS
+CFLAGS="--save-temps -fexceptions"
+libgo_cv_lib_sjlj_exceptions=unknown
+if ac_fn_c_try_compile; then :
+  if grep _Unwind_SjLj_Resume conftest.s >/dev/null 2>&1; then
+    libgo_cv_lib_sjlj_exceptions=yes
+  elif grep _Unwind_Resume conftest.s >/dev/null 2>&1; then
+    libgo_cv_lib_sjlj_exceptions=no
+  fi
+fi
+CFLAGS=$CFLAGS_hold
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_lib_sjlj_exceptions" >&5
+$as_echo "$libgo_cv_lib_sjlj_exceptions" >&6; }
+
+if test "$enable_sjlj_exceptions" = "auto"; then
+  enable_sjlj_exceptions=$libgo_cv_lib_sjlj_exceptions
+fi
+
+case $enable_sjlj_exceptions in
+yes)
+
+$as_echo "#define LIBGO_SJLJ_EXCEPTIONS 1" >>confdefs.h
+
+  ;;
+no)
+  ;;
+*)
+  as_fn_error "unable to detect exception model" "$LINENO" 5
+  ;;
+esac
+
+for ac_header in sched.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/icmp6.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in linux/filter.h linux/if_addr.h linux/if_ether.h linux/if_tun.h linux/netlink.h linux/rtnetlink.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether <ustat.h> can be used" >&5
+$as_echo_n "checking whether <ustat.h> can be used... " >&6; }
+if test "${libgo_cv_c_ustat_h+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE $OSCFLAGS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#ifdef HAVE_LINUX_FILTER_H
+#include <linux/filter.h>
+#endif
+#include <ustat.h>
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgo_cv_c_ustat_h=yes
+else
+  libgo_cv_c_ustat_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS=$CFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_ustat_h" >&5
+$as_echo "$libgo_cv_c_ustat_h" >&6; }
+if test $libgo_cv_c_ustat_h = yes; then
+
+$as_echo "#define HAVE_USTAT_H 1" >>confdefs.h
+
+fi
+
+ if test "$ac_cv_header_sys_mman_h" = yes; then
+  HAVE_SYS_MMAN_H_TRUE=
+  HAVE_SYS_MMAN_H_FALSE='#'
+else
+  HAVE_SYS_MMAN_H_TRUE='#'
+  HAVE_SYS_MMAN_H_FALSE=
+fi
+
+
+for ac_func in strerror_r strsignal wait4 mincore setenv dl_iterate_phdr
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+ if test "$ac_cv_func_strerror_r" = yes; then
+  HAVE_STRERROR_R_TRUE=
+  HAVE_STRERROR_R_FALSE='#'
+else
+  HAVE_STRERROR_R_TRUE='#'
+  HAVE_STRERROR_R_FALSE=
+fi
+
+ if test "$ac_cv_func_wait4" = yes; then
+  HAVE_WAIT4_TRUE=
+  HAVE_WAIT4_FALSE='#'
+else
+  HAVE_WAIT4_TRUE='#'
+  HAVE_WAIT4_FALSE=
+fi
+
+
+for ac_func in accept4 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat open64 openat pipe2 removexattr renameat setxattr sync_file_range splice tee unlinkat unshare utimensat
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default"
+if test "x$ac_cv_type_off_t" = x""yes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "loff_t" "ac_cv_type_loff_t" "$ac_includes_default"
+if test "x$ac_cv_type_loff_t" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LOFF_T 1
+_ACEOF
+
+
+fi
+
+
+LIBS_hold="$LIBS"
+LIBS="$LIBS -lm"
+for ac_func in cosl expl logl sinl tanl acosl asinl atanl atan2l expm1l ldexpl log10l log1pl
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+LIBS="$LIBS_hold"
+
+CFLAGS_hold="$CFLAGS"
+CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+LIBS_hold="$LIBS"
+LIBS="$LIBS $PTHREAD_LIBS"
+for ac_func in sem_timedwait
+do :
+  ac_fn_c_check_func "$LINENO" "sem_timedwait" "ac_cv_func_sem_timedwait"
+if test "x$ac_cv_func_sem_timedwait" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SEM_TIMEDWAIT 1
+_ACEOF
+
+fi
+done
+
+CFLAGS="$CFLAGS_hold"
+LIBS="$LIBS_hold"
+
+LIBS_hold="$LIBS"
+LIBS="$LIBS $MATH_LIBS"
+for ac_func in matherr
+do :
+  ac_fn_c_check_func "$LINENO" "matherr" "ac_cv_func_matherr"
+if test "x$ac_cv_func_matherr" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MATHERR 1
+_ACEOF
+
+fi
+done
+
+LIBS="$LIBS_hold"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_bool_compare_and_swap_4" >&5
+$as_echo_n "checking for __sync_bool_compare_and_swap_4... " >&6; }
+if test "${libgo_cv_func___sync_bool_compare_and_swap_4+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+typedef unsigned int uint32  __attribute__ ((mode (SI)));
+uint32 i;
+int main() { return __sync_bool_compare_and_swap (&i, 0, 1); }
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libgo_cv_func___sync_bool_compare_and_swap_4=yes
+else
+  libgo_cv_func___sync_bool_compare_and_swap_4=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_func___sync_bool_compare_and_swap_4" >&5
+$as_echo "$libgo_cv_func___sync_bool_compare_and_swap_4" >&6; }
+if test "$libgo_cv_func___sync_bool_compare_and_swap_4" = "yes"; then
+
+$as_echo "#define HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_bool_compare_and_swap_8" >&5
+$as_echo_n "checking for __sync_bool_compare_and_swap_8... " >&6; }
+if test "${libgo_cv_func___sync_bool_compare_and_swap_8+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+typedef unsigned int uint64  __attribute__ ((mode (DI)));
+uint64 i;
+int main() { return __sync_bool_compare_and_swap (&i, 0, 1); }
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libgo_cv_func___sync_bool_compare_and_swap_8=yes
+else
+  libgo_cv_func___sync_bool_compare_and_swap_8=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_func___sync_bool_compare_and_swap_8" >&5
+$as_echo "$libgo_cv_func___sync_bool_compare_and_swap_8" >&6; }
+if test "$libgo_cv_func___sync_bool_compare_and_swap_8" = "yes"; then
+
+$as_echo "#define HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_fetch_and_add_4" >&5
+$as_echo_n "checking for __sync_fetch_and_add_4... " >&6; }
+if test "${libgo_cv_func___sync_fetch_and_add_4+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+typedef unsigned int uint32  __attribute__ ((mode (SI)));
+uint32 i;
+int main() { return __sync_fetch_and_add (&i, 1); }
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libgo_cv_func___sync_fetch_and_add_4=yes
+else
+  libgo_cv_func___sync_fetch_and_add_4=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_func___sync_fetch_and_add_4" >&5
+$as_echo "$libgo_cv_func___sync_fetch_and_add_4" >&6; }
+if test "$libgo_cv_func___sync_fetch_and_add_4" = "yes"; then
+
+$as_echo "#define HAVE_SYNC_FETCH_AND_ADD_4 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_add_and_fetch_8" >&5
+$as_echo_n "checking for __sync_add_and_fetch_8... " >&6; }
+if test "${libgo_cv_func___sync_add_and_fetch_8+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+typedef unsigned int uint64  __attribute__ ((mode (DI)));
+uint64 i;
+int main() { return __sync_add_and_fetch (&i, 1); }
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libgo_cv_func___sync_add_and_fetch_8=yes
+else
+  libgo_cv_func___sync_add_and_fetch_8=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_func___sync_add_and_fetch_8" >&5
+$as_echo "$libgo_cv_func___sync_add_and_fetch_8" >&6; }
+if test "$libgo_cv_func___sync_add_and_fetch_8" = "yes"; then
+
+$as_echo "#define HAVE_SYNC_ADD_AND_FETCH_8 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -minline-all-stringops" >&5
+$as_echo_n "checking whether compiler supports -minline-all-stringops... " >&6; }
+if test "${libgo_cv_c_stringops+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -minline-all-stringops"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgo_cv_c_stringops=yes
+else
+  libgo_cv_c_stringops=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS=$CFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_stringops" >&5
+$as_echo "$libgo_cv_c_stringops" >&6; }
+STRINGOPS_FLAG=
+if test "$libgo_cv_c_stringops" = yes; then
+  STRINGOPS_FLAG=-minline-all-stringops
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -mfancy-math-387" >&5
+$as_echo_n "checking whether compiler supports -mfancy-math-387... " >&6; }
+if test "${libgo_cv_c_fancymath+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -mfancy-math-387"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgo_cv_c_fancymath=yes
+else
+  libgo_cv_c_fancymath=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS=$CFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_fancymath" >&5
+$as_echo "$libgo_cv_c_fancymath" >&6; }
+MATH_FLAG=
+if test "$libgo_cv_c_fancymath" = yes; then
+  MATH_FLAG="-mfancy-math-387 -funsafe-math-optimizations"
+else
+  MATH_FLAG="-ffp-contract=off"
+fi
+
+
+CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE"
+ac_fn_c_check_type "$LINENO" "off64_t" "ac_cv_type_off64_t" "$ac_includes_default"
+if test "x$ac_cv_type_off64_t" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_OFF64_T 1
+_ACEOF
+
+
+fi
+
+CFLAGS=$CFLAGS_hold
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking epoll_event size" >&5
+$as_echo_n "checking epoll_event size... " >&6; }
+if test "${libgo_cv_c_epoll_event_size+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "sizeof (struct epoll_event)" "libgo_cv_c_epoll_event_size"        "#include <sys/epoll.h>"; then :
+
+else
+  libgo_cv_c_epoll_event_size=0
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_epoll_event_size" >&5
+$as_echo "$libgo_cv_c_epoll_event_size" >&6; }
+SIZEOF_STRUCT_EPOLL_EVENT=${libgo_cv_c_epoll_event_size}
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking epoll_event data.fd offset" >&5
+$as_echo_n "checking epoll_event data.fd offset... " >&6; }
+if test "${libgo_cv_c_epoll_event_fd_offset+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "offsetof (struct epoll_event, data.fd)" "libgo_cv_c_epoll_event_fd_offset"        "#include <stddef.h>
+#include <sys/epoll.h>"; then :
+
+else
+  libgo_cv_c_epoll_event_fd_offset=0
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_epoll_event_fd_offset" >&5
+$as_echo "$libgo_cv_c_epoll_event_fd_offset" >&6; }
+STRUCT_EPOLL_EVENT_FD_OFFSET=${libgo_cv_c_epoll_event_fd_offset}
+
+
+ac_fn_c_check_type "$LINENO" "struct exception" "ac_cv_type_struct_exception" "#include <math.h>
+"
+if test "x$ac_cv_type_struct_exception" = x""yes; then :
+  libgo_has_struct_exception=yes
+else
+  libgo_has_struct_exception=no
+fi
+
+if test "$libgo_has_struct_exception" = "yes"; then
+
+$as_echo "#define HAVE_STRUCT_EXCEPTION 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether setcontext clobbers TLS variables" >&5
+$as_echo_n "checking whether setcontext clobbers TLS variables... " >&6; }
+if test "${libgo_cv_lib_setcontext_clobbers_tls+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold="$CFLAGS"
+CFLAGS="$PTHREAD_CFLAGS"
+LIBS_hold="$LIBS"
+LIBS="$LIBS $PTHREAD_LIBS"
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+$as_echo_n "checking size of void *... " >&6; }
+if test "${ac_cv_sizeof_void_p+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_void_p" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (void *)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_void_p=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+$as_echo "$ac_cv_sizeof_void_p" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
+_ACEOF
+
+
+as_fn_arith $ac_cv_sizeof_void_p \* 8 && ptr_type_size=$as_val
+if test "$cross_compiling" = yes; then :
+  case "$target:$ptr_type_size" in
+  i?86-*-solaris2.1[01]:64 | x86_64*-*-solaris2.1[01]:64)
+    libgo_cv_lib_setcontext_clobbers_tls=yes ;;
+  *)
+    libgo_cv_lib_setcontext_clobbers_tls=no ;;
+ esac
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+__thread int tls;
+
+static char stack[10 * 1024 * 1024];
+static ucontext_t c;
+
+/* Called via makecontext/setcontext.  */
+
+static void
+cfn (void)
+{
+  exit (tls);
+}
+
+/* Called via pthread_create.  */
+
+static void *
+tfn (void *dummy)
+{
+  /* The thread should still see this value after calling
+     setcontext.  */
+  tls = 0;
+
+  setcontext (&c);
+
+  /* The call to setcontext should not return.  */
+  abort ();
+}
+
+int
+main ()
+{
+  pthread_t tid;
+
+  /* The thread should not see this value.  */
+  tls = 1;
+
+  if (getcontext (&c) < 0)
+    abort ();
+
+  c.uc_stack.ss_sp = stack;
+#ifdef MAKECONTEXT_STACK_TOP
+  c.uc_stack.ss_sp += sizeof stack;
+#endif
+  c.uc_stack.ss_flags = 0;
+  c.uc_stack.ss_size = sizeof stack;
+  c.uc_link = NULL;
+  makecontext (&c, cfn, 0);
+
+  if (pthread_create (&tid, NULL, tfn, NULL) != 0)
+    abort ();
+
+  if (pthread_join (tid, NULL) != 0)
+    abort ();
+
+  /* The thread should have called exit.  */
+  abort ();
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  libgo_cv_lib_setcontext_clobbers_tls=no
+else
+  libgo_cv_lib_setcontext_clobbers_tls=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+CFLAGS="$CFLAGS_hold"
+LIBS="$LIBS_hold"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_lib_setcontext_clobbers_tls" >&5
+$as_echo "$libgo_cv_lib_setcontext_clobbers_tls" >&6; }
+if test "$libgo_cv_lib_setcontext_clobbers_tls" = "yes"; then
+
+$as_echo "#define SETCONTEXT_CLOBBERS_TLS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether .eh_frame section should be read-only" >&5
+$as_echo_n "checking whether .eh_frame section should be read-only... " >&6; }
+if test "${libgo_cv_ro_eh_frame+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+libgo_cv_ro_eh_frame=no
+echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
+if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
+  if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
+    libgo_cv_ro_eh_frame=yes
+  elif grep '.section.*eh_frame.*#alloc' conftest.c \
+       | grep -v '#write' > /dev/null; then
+    libgo_cv_ro_eh_frame=yes
+  fi
+fi
+rm -f conftest.*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_ro_eh_frame" >&5
+$as_echo "$libgo_cv_ro_eh_frame" >&6; }
+if test "x$libgo_cv_ro_eh_frame" = xyes; then
+
+$as_echo "#define EH_FRAME_FLAGS \"a\"" >>confdefs.h
+
+else
+
+$as_echo "#define EH_FRAME_FLAGS \"aw\"" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -Qunused-arguments" >&5
+$as_echo_n "checking if compiler supports -Qunused-arguments... " >&6; }
+if test "${libgo_cv_c_unused_arguments+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -Qunused-arguments"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgo_cv_c_unused_arguments=yes
+else
+  libgo_cv_c_unused_arguments=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS=$CFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_unused_arguments" >&5
+$as_echo "$libgo_cv_c_unused_arguments" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if assembler supports GNU comdat group syntax" >&5
+$as_echo_n "checking if assembler supports GNU comdat group syntax... " >&6; }
+if test "${libgo_cv_as_comdat_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+echo '.section .text,"axG",@progbits,.foo,comdat' > conftest.s
+CFLAGS_hold=$CFLAGS
+if test "$libgo_cv_c_unused_arguments" = yes; then
+  CFLAGS="$CFLAGS -Qunused-arguments"
+fi
+if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then
+  libgo_cv_as_comdat_gnu=yes
+else
+  libgo_cv_as_comdat_gnu=no
+fi
+CFLAGS=$CFLAGS_hold
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_as_comdat_gnu" >&5
+$as_echo "$libgo_cv_as_comdat_gnu" >&6; }
+if test "x$libgo_cv_as_comdat_gnu" = xyes; then
+
+$as_echo "#define HAVE_AS_COMDAT_GAS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports pc related relocs" >&5
+$as_echo_n "checking assembler supports pc related relocs... " >&6; }
+if test "${libgo_cv_as_x86_pcrel+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+libgo_cv_as_x86_pcrel=yes
+echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
+CFLAGS_hold=$CFLAGS
+if test "$libgo_cv_c_unused_arguments" = yes; then
+  CFLAGS="$CFLAGS -Qunused-arguments"
+fi
+if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
+    libgo_cv_as_x86_pcrel=no
+fi
+CFLAGS=$CFLAGS_hold
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_as_x86_pcrel" >&5
+$as_echo "$libgo_cv_as_x86_pcrel" >&6; }
+if test "x$libgo_cv_as_x86_pcrel" = xyes; then
+
+$as_echo "#define HAVE_AS_X86_PCREL 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports unwind section type" >&5
+$as_echo_n "checking assembler supports unwind section type... " >&6; }
+if test "${libgo_cv_as_x86_64_unwind_section_type+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+libgo_cv_as_x86_64_unwind_section_type=yes
+echo '.section .eh_frame,"a",@unwind' > conftest.s
+CFLAGS_hold=$CFLAGS
+if test "$libgo_cv_c_unused_arguments" = yes; then
+  CFLAGS="$CFLAGS -Qunused-arguments"
+fi
+if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
+    libgo_cv_as_x86_64_unwind_section_type=no
+fi
+CFLAGS=$CFLAGS_hold
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_as_x86_64_unwind_section_type" >&5
+$as_echo "$libgo_cv_as_x86_64_unwind_section_type" >&6; }
+if test "x$libgo_cv_as_x86_64_unwind_section_type" = xyes; then
+
+$as_echo "#define HAVE_AS_X86_64_UNWIND_SECTION_TYPE 1" >>confdefs.h
+
+fi
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+if test ${multilib} = yes; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+ac_config_files="$ac_config_files Makefile testsuite/Makefile"
+
+
+ac_config_commands="$ac_config_commands default"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  as_fn_error "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+  as_fn_error "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_DARWIN_TRUE}" && test -z "${LIBGO_IS_DARWIN_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_DARWIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_FREEBSD_TRUE}" && test -z "${LIBGO_IS_FREEBSD_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_FREEBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_IRIX_TRUE}" && test -z "${LIBGO_IS_IRIX_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_IRIX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_LINUX_TRUE}" && test -z "${LIBGO_IS_LINUX_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_LINUX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_NETBSD_TRUE}" && test -z "${LIBGO_IS_NETBSD_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_NETBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_OPENBSD_TRUE}" && test -z "${LIBGO_IS_OPENBSD_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_OPENBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_DRAGONFLY_TRUE}" && test -z "${LIBGO_IS_DRAGONFLY_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_DRAGONFLY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_RTEMS_TRUE}" && test -z "${LIBGO_IS_RTEMS_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_RTEMS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_SOLARIS_TRUE}" && test -z "${LIBGO_IS_SOLARIS_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_SOLARIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_386_TRUE}" && test -z "${LIBGO_IS_386_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_386\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_ALPHA_TRUE}" && test -z "${LIBGO_IS_ALPHA_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_ALPHA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_ARM_TRUE}" && test -z "${LIBGO_IS_ARM_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_ARM\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_ARM64_TRUE}" && test -z "${LIBGO_IS_ARM64_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_ARM64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_M68K_TRUE}" && test -z "${LIBGO_IS_M68K_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_M68K\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_MIPS_TRUE}" && test -z "${LIBGO_IS_MIPS_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_MIPS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_MIPSO32_TRUE}" && test -z "${LIBGO_IS_MIPSO32_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_MIPSO32\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_MIPSN32_TRUE}" && test -z "${LIBGO_IS_MIPSN32_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_MIPSN32\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_MIPSN64_TRUE}" && test -z "${LIBGO_IS_MIPSN64_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_MIPSN64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_MIPSO64_TRUE}" && test -z "${LIBGO_IS_MIPSO64_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_MIPSO64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_PPC_TRUE}" && test -z "${LIBGO_IS_PPC_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_PPC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_PPC64_TRUE}" && test -z "${LIBGO_IS_PPC64_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_PPC64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_S390_TRUE}" && test -z "${LIBGO_IS_S390_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_S390\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_S390X_TRUE}" && test -z "${LIBGO_IS_S390X_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_S390X\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_SPARC_TRUE}" && test -z "${LIBGO_IS_SPARC_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_SPARC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_SPARC64_TRUE}" && test -z "${LIBGO_IS_SPARC64_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_SPARC64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBGO_IS_X86_64_TRUE}" && test -z "${LIBGO_IS_X86_64_FALSE}"; then
+  as_fn_error "conditional \"LIBGO_IS_X86_64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${USING_SPLIT_STACK_TRUE}" && test -z "${USING_SPLIT_STACK_FALSE}"; then
+  as_fn_error "conditional \"USING_SPLIT_STACK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${GOC_IS_LLGO_TRUE}" && test -z "${GOC_IS_LLGO_FALSE}"; then
+  as_fn_error "conditional \"GOC_IS_LLGO\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+if test -z "${HAVE_SYS_MMAN_H_TRUE}" && test -z "${HAVE_SYS_MMAN_H_FALSE}"; then
+  as_fn_error "conditional \"HAVE_SYS_MMAN_H\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_STRERROR_R_TRUE}" && test -z "${HAVE_STRERROR_R_FALSE}"; then
+  as_fn_error "conditional \"HAVE_STRERROR_R\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_WAIT4_TRUE}" && test -z "${HAVE_WAIT4_FALSE}"; then
+  as_fn_error "conditional \"HAVE_WAIT4\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by package-unused $as_me version-unused, which was
+generated by GNU Autoconf 2.64.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+package-unused config.status version-unused
+configured by $0, generated by GNU Autoconf 2.64,
+  with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+
+srcdir="$srcdir"
+host="$host"
+target="$target"
+with_multisubdir="$with_multisubdir"
+with_multisrctop="$with_multisrctop"
+with_target_subdir="$with_target_subdir"
+ac_configure_args="${multilib_arg} ${ac_configure_args}"
+multi_basedir="$multi_basedir"
+CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+CC="$CC"
+CXX="$CXX"
+GFORTRAN="$GFORTRAN"
+GCJ="$GCJ"
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+fix_srcfile_path='`$ECHO "$fix_srcfile_path" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+LD_GO='`$ECHO "$LD_GO" | $SED "$delay_single_quote_subst"`'
+reload_flag_GO='`$ECHO "$reload_flag_GO" | $SED "$delay_single_quote_subst"`'
+reload_cmds_GO='`$ECHO "$reload_cmds_GO" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds_GO='`$ECHO "$old_archive_cmds_GO" | $SED "$delay_single_quote_subst"`'
+compiler_GO='`$ECHO "$compiler_GO" | $SED "$delay_single_quote_subst"`'
+GCC_GO='`$ECHO "$GCC_GO" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag_GO='`$ECHO "$lt_prog_compiler_no_builtin_flag_GO" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl_GO='`$ECHO "$lt_prog_compiler_wl_GO" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic_GO='`$ECHO "$lt_prog_compiler_pic_GO" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static_GO='`$ECHO "$lt_prog_compiler_static_GO" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o_GO='`$ECHO "$lt_cv_prog_compiler_c_o_GO" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc_GO='`$ECHO "$archive_cmds_need_lc_GO" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes_GO='`$ECHO "$enable_shared_with_static_runtimes_GO" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec_GO='`$ECHO "$export_dynamic_flag_spec_GO" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec_GO='`$ECHO "$whole_archive_flag_spec_GO" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object_GO='`$ECHO "$compiler_needs_object_GO" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds_GO='`$ECHO "$old_archive_from_new_cmds_GO" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds_GO='`$ECHO "$old_archive_from_expsyms_cmds_GO" | $SED "$delay_single_quote_subst"`'
+archive_cmds_GO='`$ECHO "$archive_cmds_GO" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds_GO='`$ECHO "$archive_expsym_cmds_GO" | $SED "$delay_single_quote_subst"`'
+module_cmds_GO='`$ECHO "$module_cmds_GO" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds_GO='`$ECHO "$module_expsym_cmds_GO" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld_GO='`$ECHO "$with_gnu_ld_GO" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag_GO='`$ECHO "$allow_undefined_flag_GO" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag_GO='`$ECHO "$no_undefined_flag_GO" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_GO='`$ECHO "$hardcode_libdir_flag_spec_GO" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld_GO='`$ECHO "$hardcode_libdir_flag_spec_ld_GO" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator_GO='`$ECHO "$hardcode_libdir_separator_GO" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_GO='`$ECHO "$hardcode_direct_GO" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute_GO='`$ECHO "$hardcode_direct_absolute_GO" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L_GO='`$ECHO "$hardcode_minus_L_GO" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var_GO='`$ECHO "$hardcode_shlibpath_var_GO" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic_GO='`$ECHO "$hardcode_automatic_GO" | $SED "$delay_single_quote_subst"`'
+inherit_rpath_GO='`$ECHO "$inherit_rpath_GO" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs_GO='`$ECHO "$link_all_deplibs_GO" | $SED "$delay_single_quote_subst"`'
+fix_srcfile_path_GO='`$ECHO "$fix_srcfile_path_GO" | $SED "$delay_single_quote_subst"`'
+always_export_symbols_GO='`$ECHO "$always_export_symbols_GO" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds_GO='`$ECHO "$export_symbols_cmds_GO" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms_GO='`$ECHO "$exclude_expsyms_GO" | $SED "$delay_single_quote_subst"`'
+include_expsyms_GO='`$ECHO "$include_expsyms_GO" | $SED "$delay_single_quote_subst"`'
+prelink_cmds_GO='`$ECHO "$prelink_cmds_GO" | $SED "$delay_single_quote_subst"`'
+file_list_spec_GO='`$ECHO "$file_list_spec_GO" | $SED "$delay_single_quote_subst"`'
+hardcode_action_GO='`$ECHO "$hardcode_action_GO" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in SED \
+GREP \
+EGREP \
+FGREP \
+SHELL \
+ECHO \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+AR \
+AR_FLAGS \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_wl \
+lt_prog_compiler_pic \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_flag_spec_ld \
+hardcode_libdir_separator \
+fix_srcfile_path \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib \
+LD_GO \
+reload_flag_GO \
+compiler_GO \
+lt_prog_compiler_no_builtin_flag_GO \
+lt_prog_compiler_wl_GO \
+lt_prog_compiler_pic_GO \
+lt_prog_compiler_static_GO \
+lt_cv_prog_compiler_c_o_GO \
+export_dynamic_flag_spec_GO \
+whole_archive_flag_spec_GO \
+compiler_needs_object_GO \
+with_gnu_ld_GO \
+allow_undefined_flag_GO \
+no_undefined_flag_GO \
+hardcode_libdir_flag_spec_GO \
+hardcode_libdir_flag_spec_ld_GO \
+hardcode_libdir_separator_GO \
+fix_srcfile_path_GO \
+exclude_expsyms_GO \
+include_expsyms_GO \
+file_list_spec_GO; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec \
+reload_cmds_GO \
+old_archive_cmds_GO \
+old_archive_from_new_cmds_GO \
+old_archive_from_expsyms_cmds_GO \
+archive_cmds_GO \
+archive_expsym_cmds_GO \
+module_cmds_GO \
+module_expsym_cmds_GO \
+export_symbols_cmds_GO \
+prelink_cmds_GO; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'
+
+
+
+
+
+
+# Variables needed in config.status (file generation) which aren't already
+# passed by autoconf.
+SUBDIRS="$SUBDIRS"
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;;
+    "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
+
+  *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\).*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\).*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || as_fn_error "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_t"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+    } >"$tmp/config.h" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$tmp/config.h" "$ac_file" \
+	|| as_fn_error "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "default-1":C)
+# Only add multilib support code if we just rebuilt the top-level
+# Makefile.
+case " $CONFIG_FILES " in
+ *" Makefile "*)
+   ac_file=Makefile . ${multi_basedir}/config-ml.in
+   ;;
+esac ;;
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named `Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$mf" : 'X\(//\)[^/]' \| \
+	 X"$mf" : 'X\(//\)$' \| \
+	 X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running `make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # When using ansi2knr, U may be empty or an underscore; expand it
+    U=`sed -n 's/^U = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$file" : 'X\(//\)[^/]' \| \
+	 X"$file" : 'X\(//\)$' \| \
+	 X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      as_dir=$dirpart/$fdir; as_fn_mkdir_p
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+ ;;
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags="GO "
+
+# ### BEGIN LIBTOOL CONFIG
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking.  This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  case $xsi_shell in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+  func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+  # positional parameters, so assign one to ordinary parameter first.
+  func_stripname_result=${3}
+  func_stripname_result=${func_stripname_result#"${1}"}
+  func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=${1%%=*}
+  func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  case ${1} in
+    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+    *)    func_lo2o_result=${1} ;;
+  esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=$(( $* ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=${#1}
+}
+
+_LT_EOF
+    ;;
+  *) # Bourne compatible functions.
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result=`$ECHO "${1}" | $SED "$basename"`
+}
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+  case ${2} in
+    .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+    *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+  esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[^=]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=`$ECHO "${1}" | $SED "$my_sed_long_opt"`
+  func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=`expr "$@"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$1+=\$2"
+}
+_LT_EOF
+    ;;
+  *)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$1=\$$1\$2"
+}
+
+_LT_EOF
+    ;;
+  esac
+
+
+  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+
+    cat <<_LT_EOF >> "$ofile"
+
+# ### BEGIN LIBTOOL TAG CONFIG: GO
+
+# The linker used to build libraries.
+LD=$lt_LD_GO
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag_GO
+reload_cmds=$lt_reload_cmds_GO
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds_GO
+
+# A language specific compiler.
+CC=$lt_compiler_GO
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC_GO
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GO
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_GO
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_GO
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_GO
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GO
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_GO
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GO
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GO
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_GO
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object_GO
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GO
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GO
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds_GO
+archive_expsym_cmds=$lt_archive_expsym_cmds_GO
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds_GO
+module_expsym_cmds=$lt_module_expsym_cmds_GO
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld_GO
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_GO
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_GO
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GO
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking.  This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GO
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_GO
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct_GO
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute_GO
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L_GO
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_GO
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic_GO
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath_GO
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_GO
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path_GO
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols_GO
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_GO
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_GO
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_GO
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds_GO
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec_GO
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_GO
+
+# ### END LIBTOOL TAG CONFIG: GO
+_LT_EOF
+
+ ;;
+    "default":C) if test -n "$CONFIG_FILES"; then
+   # Multilibs need MULTISUBDIR defined correctly in certain makefiles so
+   # that multilib installs will end up installed in the correct place.
+   # The testsuite needs it for multilib-aware ABI baseline files.
+   # To work around this not being passed down from config-ml.in ->
+   # srcdir/Makefile.am -> srcdir/{src,libsupc++,...}/Makefile.am, manually
+   # append it here.  Only modify Makefiles that have just been created.
+   #
+   # Also, get rid of this simulated-VPATH thing that automake does.
+   cat > vpsed << \_EOF
+s!`test -f '$<' || echo '$(srcdir)/'`!!
+_EOF
+   for i in $SUBDIRS; do
+    case $CONFIG_FILES in
+     *${i}/Makefile*)
+       #echo "Adding MULTISUBDIR to $i/Makefile"
+       sed -f vpsed $i/Makefile > tmp
+       grep '^MULTISUBDIR =' Makefile >> tmp
+       mv tmp $i/Makefile
+       ;;
+    esac
+   done
+   rm vpsed
+ fi
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit $?
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/third_party/gofrontend/libgo/configure.ac b/third_party/gofrontend/libgo/configure.ac
new file mode 100644
index 0000000..6dac4d6
--- /dev/null
+++ b/third_party/gofrontend/libgo/configure.ac
@@ -0,0 +1,918 @@
+# configure.ac -- Go library configure script.
+
+# 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.
+
+# Process this file with autoreconf to produce configure.
+
+AC_PREREQ(2.64)
+AC_INIT(package-unused, version-unused,, libgo)
+AC_CONFIG_SRCDIR(Makefile.am)
+AC_CONFIG_HEADER(config.h)
+
+libtool_VERSION=6:0:0
+AC_SUBST(libtool_VERSION)
+
+AM_ENABLE_MULTILIB(, ..)
+
+AC_CANONICAL_SYSTEM
+target_alias=${target_alias-$host_alias}
+
+AM_INIT_AUTOMAKE([1.9.3 no-define foreign no-dist -Wall -Wno-portability])
+AH_TEMPLATE(PACKAGE, [Name of package])
+AH_TEMPLATE(VERSION, [Version number of package])
+
+m4_rename([_AC_ARG_VAR_PRECIOUS],[glibgo_PRECIOUS])
+m4_define([_AC_ARG_VAR_PRECIOUS],[])
+AC_PROG_CC
+AC_PROG_GO
+m4_rename_force([glibgo_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
+
+AC_SUBST(CFLAGS)
+
+AM_MAINTAINER_MODE
+
+AC_PROG_LD
+AC_PROG_RANLIB
+AC_CHECK_TOOL(OBJCOPY, objcopy, missing-objcopy)
+
+AC_LIBTOOL_DLOPEN
+AM_PROG_LIBTOOL
+AC_SUBST(enable_shared)
+AC_SUBST(enable_static)
+
+CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
+AC_SUBST(CC_FOR_BUILD)
+
+AC_PROG_AWK
+
+WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
+AC_SUBST(WARN_FLAGS)
+
+AC_ARG_ENABLE(werror, [AS_HELP_STRING([--enable-werror],
+                                      [turns on -Werror @<:@default=yes@:>@])])
+if test "x$enable_werror" != "xno"; then
+  WERROR="-Werror"
+fi
+AC_SUBST(WERROR)
+
+glibgo_toolexecdir=no
+glibgo_toolexeclibdir=no
+
+AC_MSG_CHECKING([for --enable-version-specific-runtime-libs])
+AC_ARG_ENABLE([version-specific-runtime-libs],
+  AC_HELP_STRING([--enable-version-specific-runtime-libs],
+                 [Specify that runtime libraries should be installed in a compiler-specific directory]),
+  [case "$enableval" in
+    yes) version_specific_libs=yes ;;
+    no)  version_specific_libs=no ;;
+    *)   AC_MSG_ERROR([Unknown argument to enable/disable version-specific libs]);;
+   esac],
+  [version_specific_libs=no])
+AC_MSG_RESULT($version_specific_libs)
+
+# Version-specific runtime libs processing.
+if test $version_specific_libs = yes; then
+  glibgo_toolexecdir='${libdir}/gcc/${host_alias}'
+  glibgo_toolexeclibdir='${toolexecdir}/${gcc_version}$(MULTISUBDIR)'
+fi
+
+# Calculate glibgo_toolexecdir, glibgo_toolexeclibdir
+# Install a library built with a cross compiler in tooldir, not libdir.
+if test -n "$with_cross_host" &&
+   test x"$with_cross_host" != x"no"; then
+  nover_glibgo_toolexecdir='${exec_prefix}/${host_alias}'
+  nover_glibgo_toolexeclibdir='${toolexecdir}/lib'
+else
+  nover_glibgo_toolexecdir='${libdir}/gcc/${host_alias}'
+  nover_glibgo_toolexeclibdir='${libdir}'
+fi
+multi_os_directory=`$GOC -print-multi-os-directory`
+case $multi_os_directory in
+  .) ;; # Avoid trailing /.
+  *) nover_glibgo_toolexeclibdir=${nover_glibgo_toolexeclibdir}/${multi_os_directory} ;;
+esac
+
+if test x"$glibgo_toolexecdir" = x"no"; then
+  glibgo_toolexecdir="${nover_glibgo_toolexecdir}"
+  glibgo_toolexeclibdir="${nover_glibgo_toolexeclibdir}"
+fi
+
+AC_SUBST(glibgo_toolexecdir)
+AC_SUBST(glibgo_toolexeclibdir)
+AC_SUBST(nover_glibgo_toolexeclibdir)
+
+# See if the user wants to configure without libffi.  Some
+# architectures don't support it.  FIXME: We should set a default
+# based on the host.
+AC_ARG_WITH(libffi,
+  AS_HELP_STRING([--without-libffi],
+                 [don't use libffi]),
+  [:],
+  [with_libffi=${with_libffi_default-yes}])
+
+LIBFFI=
+LIBFFIINCS=
+if test "$with_libffi" != no; then
+   AC_DEFINE(USE_LIBFFI, 1, [Define if we're to use libffi.])
+   LIBFFI=../libffi/libffi_convenience.la
+   LIBFFIINCS='-I$(top_srcdir)/../libffi/include -I../libffi/include'
+fi
+AC_SUBST(LIBFFI)
+AC_SUBST(LIBFFIINCS)
+
+# See if the user wants to configure without libatomic. This is useful if we are
+# on an architecture for which libgo does not need an atomic support library and
+# libatomic does not support our C compiler.
+AC_ARG_WITH(libatomic,
+  AS_HELP_STRING([--without-libatomic],
+                 [don't use libatomic]),
+  [:],
+  [with_libatomic=${with_libatomic_default-yes}])
+
+LIBATOMIC=
+if test "$with_libatomic" != no; then
+   LIBATOMIC=../libatomic/libatomic_convenience.la
+fi
+AC_SUBST(LIBATOMIC)
+
+# Used to tell GNU make to include a file without telling automake to
+# include it.
+go_include="-include"
+AC_SUBST(go_include)
+
+is_darwin=no
+is_freebsd=no
+is_irix=no
+is_linux=no
+is_netbsd=no
+is_openbsd=no
+is_dragonfly=no
+is_rtems=no
+is_solaris=no
+GOOS=unknown
+case ${host} in
+  *-*-darwin*)   is_darwin=yes;  GOOS=darwin ;;
+  *-*-freebsd*)  is_freebsd=yes; GOOS=freebsd ;;
+  *-*-irix6*)    is_irix=yes;    GOOS=irix ;;
+  *-*-linux*)    is_linux=yes;   GOOS=linux ;;
+  *-*-netbsd*)	 is_netbsd=yes;  GOOS=netbsd ;;
+  *-*-openbsd*)  is_openbsd=yes; GOOS=openbsd ;;
+  *-*-dragonfly*) is_dragonfly=yes; GOOS=dragonfly ;;
+  *-*-rtems*)    is_rtems=yes;   GOOS=rtems ;;
+  *-*-solaris2*) is_solaris=yes; GOOS=solaris ;;
+esac
+AM_CONDITIONAL(LIBGO_IS_DARWIN, test $is_darwin = yes)
+AM_CONDITIONAL(LIBGO_IS_FREEBSD, test $is_freebsd = yes)
+AM_CONDITIONAL(LIBGO_IS_IRIX, test $is_irix = yes)
+AM_CONDITIONAL(LIBGO_IS_LINUX, test $is_linux = yes)
+AM_CONDITIONAL(LIBGO_IS_NETBSD, test $is_netbsd = yes)
+AM_CONDITIONAL(LIBGO_IS_OPENBSD, test $is_openbsd = yes)
+AM_CONDITIONAL(LIBGO_IS_DRAGONFLY, test $is_dragonfly = yes)
+AM_CONDITIONAL(LIBGO_IS_RTEMS, test $is_rtems = yes)
+AM_CONDITIONAL(LIBGO_IS_SOLARIS, test $is_solaris = yes)
+AC_SUBST(GOOS)
+
+dnl Test whether we need to use DejaGNU or whether we can use the
+dnl simpler gotest approach.  We can only use gotest for a native
+dnl build.
+USE_DEJAGNU=no
+case ${host} in
+  *-*-rtems*) USE_DEJAGNU=yes ;;
+  ${build}) ;;
+  *) USE_DEJAGNU=yes ;;
+esac
+AC_SUBST(USE_DEJAGNU)
+
+dnl N.B. Keep in sync with gcc/testsuite/go.test/go-test.exp (go-set-goarch).
+is_386=no
+is_alpha=no
+is_arm=no
+is_arm64=no
+is_m68k=no
+mips_abi=unknown
+is_ppc=no
+is_ppc64=no
+is_s390=no
+is_s390x=no
+is_sparc=no
+is_sparc64=no
+is_x86_64=no
+GOARCH=unknown
+case ${host} in
+  alpha*-*-*)
+    is_alpha=yes
+    GOARCH=alpha
+    ;;
+  aarch64-*-*)
+    is_arm64=yes
+    GOARCH=arm64
+    ;;
+  arm*-*-* | strongarm*-*-* | ep9312*-*-* | xscale-*-*)
+    is_arm=yes
+    GOARCH=arm
+    ;;
+changequote(,)dnl
+  i[34567]86-*-* | x86_64-*-*)
+changequote([,])dnl
+    AC_COMPILE_IFELSE([
+#ifdef __x86_64__
+#error 64-bit
+#endif],
+[is_386=yes], [is_x86_64=yes])
+    if test "$is_386" = "yes"; then
+      GOARCH=386
+    else
+      GOARCH=amd64
+    fi
+    ;;
+  m68k*-*-*)
+    is_m68k=yes
+    GOARCH=m68k
+    ;;
+  mips*-*-*)
+    AC_COMPILE_IFELSE([
+#if _MIPS_SIM != _ABIO32
+#error not o32
+#endif],
+[mips_abi="o32"],
+	[AC_COMPILE_IFELSE([
+#if _MIPS_SIM != _ABIN32
+#error not n32
+#endif],
+[mips_abi="n32"],
+	[AC_COMPILE_IFELSE([
+#if _MIPS_SIM != _ABI64
+#error not n64
+#endif],
+[mips_abi="n64"],
+	[AC_COMPILE_IFELSE([
+#if _MIPS_SIM != _ABIO64
+#error not o64
+#endif],
+[mips_abi="o64"],
+	[AC_MSG_ERROR([unknown MIPS ABI])
+[mips_abi="n32"]])])])])
+    case "$mips_abi" in
+    "o32") GOARCH=mipso32 ;;
+    "n32") GOARCH=mipsn32 ;;
+    "n64") GOARCH=mipsn64 ;;
+    "o64") GOARCH=mipso64 ;;
+    esac
+    ;;
+  rs6000*-*-* | powerpc*-*-*)
+    AC_COMPILE_IFELSE([
+#ifdef _ARCH_PPC64
+#error 64-bit
+#endif],
+[is_ppc=yes], [is_ppc64=yes])
+    if test "$is_ppc" = "yes"; then
+      GOARCH=ppc
+    else
+      GOARCH=ppc64
+    fi
+    ;;
+  s390*-*-*)
+    AC_COMPILE_IFELSE([
+#if defined(__s390x__)
+#error 64-bit
+#endif],
+[is_s390=yes], [is_s390x=yes])
+    if test "$is_s390" = "yes"; then
+      GOARCH=s390
+    else
+      GOARCH=s390x
+    fi
+    ;;
+  sparc*-*-*)
+    AC_COMPILE_IFELSE([
+#if defined(__sparcv9) || defined(__arch64__)
+#error 64-bit
+#endif],
+[is_sparc=yes], [is_sparc64=yes])
+    if test "$is_sparc" = "yes"; then
+      GOARCH=sparc
+    else
+      GOARCH=sparc64
+    fi
+    ;;
+esac
+AM_CONDITIONAL(LIBGO_IS_386, test $is_386 = yes)
+AM_CONDITIONAL(LIBGO_IS_ALPHA, test $is_alpha = yes)
+AM_CONDITIONAL(LIBGO_IS_ARM, test $is_arm = yes)
+AM_CONDITIONAL(LIBGO_IS_ARM64, test $is_arm64 = yes)
+AM_CONDITIONAL(LIBGO_IS_M68K, test $is_m68k = yes)
+AM_CONDITIONAL(LIBGO_IS_MIPS, test $mips_abi != unknown)
+AM_CONDITIONAL(LIBGO_IS_MIPSO32, test $mips_abi = o32)
+AM_CONDITIONAL(LIBGO_IS_MIPSN32, test $mips_abi = n32)
+AM_CONDITIONAL(LIBGO_IS_MIPSN64, test $mips_abi = n64)
+AM_CONDITIONAL(LIBGO_IS_MIPSO64, test $mips_abi = o64)
+AM_CONDITIONAL(LIBGO_IS_PPC, test $is_ppc = yes)
+AM_CONDITIONAL(LIBGO_IS_PPC64, test $is_ppc64 = yes)
+AM_CONDITIONAL(LIBGO_IS_S390, test $is_s390 = yes)
+AM_CONDITIONAL(LIBGO_IS_S390X, test $is_s390x = yes)
+AM_CONDITIONAL(LIBGO_IS_SPARC, test $is_sparc = yes)
+AM_CONDITIONAL(LIBGO_IS_SPARC64, test $is_sparc64 = yes)
+AM_CONDITIONAL(LIBGO_IS_X86_64, test $is_x86_64 = yes)
+AC_SUBST(GOARCH)
+
+dnl Some files are only present when needed for specific architectures.
+GO_LIBCALL_OS_FILE=
+GO_LIBCALL_OS_ARCH_FILE=
+GO_SYSCALL_OS_FILE=
+GO_SYSCALL_OS_ARCH_FILE=
+if test -f "${srcdir}/go/syscall/libcall_${GOOS}.go"; then
+  GO_LIBCALL_OS_FILE="go/syscall/libcall_${GOOS}.go"
+fi
+if test -f "${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go"; then
+  GO_LIBCALL_OS_ARCH_FILE="go/syscall/libcall_${GOOS}_${GOARCH}.go"
+fi
+if test -f "${srcdir}/go/syscall/syscall_${GOOS}.go"; then
+  GO_SYSCALL_OS_FILE="go/syscall/syscall_${GOOS}.go"
+fi
+if test -f "${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go"; then
+  GO_SYSCALL_OS_ARCH_FILE="go/syscall/syscall_${GOOS}_${GOARCH}.go"
+fi
+AC_SUBST(GO_LIBCALL_OS_FILE)
+AC_SUBST(GO_LIBCALL_OS_ARCH_FILE)
+AC_SUBST(GO_SYSCALL_OS_FILE)
+AC_SUBST(GO_SYSCALL_OS_ARCH_FILE)
+
+dnl Special flags used to generate sysinfo.go.
+OSCFLAGS="-D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+case "$target" in
+    mips-sgi-irix6.5*)
+	# IRIX 6 needs _XOPEN_SOURCE=500 for the XPG5 version of struct
+	# msghdr in <sys/socket.h>.
+	OSCFLAGS="$OSCFLAGS -D_XOPEN_SOURCE=500"
+	;;
+    *-*-solaris2.1[[01]])
+	# Solaris 10+ needs this so struct msghdr gets the msg_control
+	# etc. fields in <sys/socket.h> (_XPG4_2).  _XOPEN_SOURCE=600 as
+	# above doesn't work with C99.
+	OSCFLAGS="$OSCFLAGS -std=gnu99 -D_XOPEN_SOURCE=600 -D__EXTENSIONS__"
+	;;
+esac
+AC_SUBST(OSCFLAGS)
+
+dnl Use -fsplit-stack when compiling C code if available.
+AC_CACHE_CHECK([whether -fsplit-stack is supported],
+[libgo_cv_c_split_stack_supported],
+[CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -fsplit-stack"
+AC_COMPILE_IFELSE([[int i;]],
+[libgo_cv_c_split_stack_supported=yes],
+[libgo_cv_c_split_stack_supported=no])
+CFLAGS=$CFLAGS_hold])
+if test "$libgo_cv_c_split_stack_supported" = yes; then
+  SPLIT_STACK=-fsplit-stack
+  AC_DEFINE(USING_SPLIT_STACK, 1,
+		[Define if the compiler supports -fsplit-stack])
+else
+  SPLIT_STACK=
+fi
+AC_SUBST(SPLIT_STACK)
+AM_CONDITIONAL(USING_SPLIT_STACK,
+	test "$libgo_cv_c_split_stack_supported" = yes)
+
+dnl Check whether the linker does stack munging when calling from
+dnl split-stack into non-split-stack code.  We check this by looking
+dnl at the --help output.  FIXME: This is only half right: it's
+dnl possible for the linker to support this for some targets but not
+dnl others.
+AC_CACHE_CHECK([whether linker supports split stack],
+[libgo_cv_c_linker_supports_split_stack],
+[libgo_cv_c_linker_supports_split_stack=no
+if $GOC -Wl,--help 2>/dev/null | grep split-stack-adjust-size >/dev/null 2>&1; then
+  libgo_cv_c_linker_supports_split_stack=yes
+fi])
+if test "$libgo_cv_c_linker_supports_split_stack" = yes; then
+  AC_DEFINE(LINKER_SUPPORTS_SPLIT_STACK, 1,
+	    [Define if the linker support split stack adjustments])
+fi
+
+AC_CACHE_CHECK([whether compiler is llgo],
+[libgo_cv_c_goc_is_llgo],
+[libgo_cv_c_goc_is_llgo=no
+if $GOC -dumpversion 2>/dev/null | grep llgo >/dev/null 2>&1; then
+  libgo_cv_c_goc_is_llgo=yes
+fi])
+AM_CONDITIONAL(GOC_IS_LLGO, test "$libgo_cv_c_goc_is_llgo" = yes)
+
+dnl Test for the -lm library.
+MATH_LIBS=
+AC_CHECK_LIB([m], [sqrt], MATH_LIBS=-lm)
+AC_SUBST(MATH_LIBS)
+
+dnl Test for -lsocket and -lnsl.  Copied from libjava/configure.ac.
+AC_CACHE_CHECK([for socket libraries], libgo_cv_lib_sockets,
+  [libgo_cv_lib_sockets=
+   libgo_check_both=no
+   AC_CHECK_FUNC(connect, libgo_check_socket=no, libgo_check_socket=yes)
+   if test "$libgo_check_socket" = "yes"; then
+     unset ac_cv_func_connect
+     AC_CHECK_LIB(socket, main, libgo_cv_lib_sockets="-lsocket",
+     		  libgo_check_both=yes)
+   fi
+   if test "$libgo_check_both" = "yes"; then
+     libgo_old_libs=$LIBS
+     LIBS="$LIBS -lsocket -lnsl"
+     unset ac_cv_func_accept
+     AC_CHECK_FUNC(accept,
+		   [libgo_check_nsl=no
+		    libgo_cv_lib_sockets="-lsocket -lnsl"])
+     unset ac_cv_func_accept
+     LIBS=$libgo_old_libs
+   fi
+   unset ac_cv_func_gethostbyname
+   libgo_old_libs="$LIBS"
+   AC_CHECK_FUNC(gethostbyname, ,
+		 [AC_CHECK_LIB(nsl, main,
+		 	[libgo_cv_lib_sockets="$libgo_cv_lib_sockets -lnsl"])])
+   unset ac_cv_func_gethostbyname
+   LIBS=$libgo_old_libs
+])
+NET_LIBS="$libgo_cv_lib_sockets"
+AC_SUBST(NET_LIBS)
+
+dnl Test whether the compiler supports the -pthread option.
+AC_CACHE_CHECK([whether -pthread is supported],
+[libgo_cv_lib_pthread],
+[CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -pthread"
+AC_COMPILE_IFELSE([[int i;]],
+[libgo_cv_lib_pthread=yes],
+[libgo_cv_lib_pthread=no])
+CFLAGS=$CFLAGS_hold])
+PTHREAD_CFLAGS=
+if test "$libgo_cv_lib_pthread" = yes; then
+  PTHREAD_CFLAGS=-pthread
+fi
+AC_SUBST(PTHREAD_CFLAGS)
+
+dnl Test for the -lpthread library.
+PTHREAD_LIBS=
+AC_CHECK_LIB([pthread], [pthread_create], PTHREAD_LIBS=-lpthread)
+AC_SUBST(PTHREAD_LIBS)
+
+dnl Test if -lrt is required for sched_yield and/or nanosleep.
+AC_SEARCH_LIBS([sched_yield], [rt])
+AC_SEARCH_LIBS([nanosleep], [rt])
+
+AC_C_BIGENDIAN
+
+GCC_CHECK_UNWIND_GETIPINFO
+
+AC_ARG_ENABLE(sjlj-exceptions,
+  AC_HELP_STRING([--enable-sjlj-exceptions],
+		 [force use of builtin_setjmp for exceptions]),
+  [case "$enableval" in
+   yes|no|auto) ;;
+   *) AC_MSG_ERROR([unknown argument to --enable-sjlj-exceptions]) ;;
+   esac],
+  [enable_sjlj_exceptions=auto])
+
+AC_CACHE_CHECK([whether to use setjmp/longjmp exceptions],
+[libgo_cv_lib_sjlj_exceptions],
+[AC_LANG_CONFTEST(
+  [AC_LANG_SOURCE([
+void bar ();
+void clean (int *);
+void foo ()
+{
+  int i __attribute__ ((cleanup (clean)));
+  bar();
+}
+])])
+CFLAGS_hold=$CFLAGS
+CFLAGS="--save-temps -fexceptions"
+libgo_cv_lib_sjlj_exceptions=unknown
+AS_IF([ac_fn_c_try_compile],
+  [if grep _Unwind_SjLj_Resume conftest.s >/dev/null 2>&1; then
+    libgo_cv_lib_sjlj_exceptions=yes
+  elif grep _Unwind_Resume conftest.s >/dev/null 2>&1; then
+    libgo_cv_lib_sjlj_exceptions=no
+  fi])
+CFLAGS=$CFLAGS_hold
+rm -f conftest*
+])
+
+if test "$enable_sjlj_exceptions" = "auto"; then
+  enable_sjlj_exceptions=$libgo_cv_lib_sjlj_exceptions
+fi
+
+case $enable_sjlj_exceptions in
+yes)
+  AC_DEFINE(LIBGO_SJLJ_EXCEPTIONS, 1,
+	[Define if the C++ compiler is configured for setjmp/longjmp exceptions.])
+  ;;
+no)
+  ;;
+*)
+  AC_MSG_ERROR([unable to detect exception model])
+  ;;
+esac
+
+AC_CHECK_HEADERS(sched.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/icmp6.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h)
+
+AC_CHECK_HEADERS([linux/filter.h linux/if_addr.h linux/if_ether.h linux/if_tun.h linux/netlink.h linux/rtnetlink.h], [], [],
+[#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+])
+
+AC_CACHE_CHECK([whether <ustat.h> can be used],
+[libgo_cv_c_ustat_h],
+[CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE $OSCFLAGS"
+AC_COMPILE_IFELSE(
+[AC_LANG_SOURCE([
+#include <sys/types.h>
+#ifdef HAVE_LINUX_FILTER_H
+#include <linux/filter.h>
+#endif
+#include <ustat.h>
+])], [libgo_cv_c_ustat_h=yes], [libgo_cv_c_ustat_h=no])
+CFLAGS=$CFLAGS_hold])
+if test $libgo_cv_c_ustat_h = yes; then
+  AC_DEFINE(HAVE_USTAT_H, 1,
+    [Define to 1 if you have the <ustat.h> header file and it works.])
+fi
+
+AM_CONDITIONAL(HAVE_SYS_MMAN_H, test "$ac_cv_header_sys_mman_h" = yes)
+
+AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv dl_iterate_phdr)
+AM_CONDITIONAL(HAVE_STRERROR_R, test "$ac_cv_func_strerror_r" = yes)
+AM_CONDITIONAL(HAVE_WAIT4, test "$ac_cv_func_wait4" = yes)
+
+AC_CHECK_FUNCS(accept4 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat open64 openat pipe2 removexattr renameat setxattr sync_file_range splice tee unlinkat unshare utimensat)
+AC_TYPE_OFF_T
+AC_CHECK_TYPES([loff_t])
+
+LIBS_hold="$LIBS"
+LIBS="$LIBS -lm"
+AC_CHECK_FUNCS(cosl expl logl sinl tanl acosl asinl atanl atan2l expm1l ldexpl log10l log1pl)
+LIBS="$LIBS_hold"
+
+CFLAGS_hold="$CFLAGS"
+CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+LIBS_hold="$LIBS"
+LIBS="$LIBS $PTHREAD_LIBS"
+AC_CHECK_FUNCS(sem_timedwait)
+CFLAGS="$CFLAGS_hold"
+LIBS="$LIBS_hold"
+
+LIBS_hold="$LIBS"
+LIBS="$LIBS $MATH_LIBS"
+AC_CHECK_FUNCS(matherr)
+LIBS="$LIBS_hold"
+
+AC_CACHE_CHECK([for __sync_bool_compare_and_swap_4],
+[libgo_cv_func___sync_bool_compare_and_swap_4],
+[AC_LINK_IFELSE([
+typedef unsigned int uint32  __attribute__ ((mode (SI)));
+uint32 i;
+int main() { return __sync_bool_compare_and_swap (&i, 0, 1); }
+],
+[libgo_cv_func___sync_bool_compare_and_swap_4=yes],
+[libgo_cv_func___sync_bool_compare_and_swap_4=no])])
+if test "$libgo_cv_func___sync_bool_compare_and_swap_4" = "yes"; then
+  AC_DEFINE(HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4, 1,
+    [Define to 1 if the compiler provides the __sync_bool_compare_and_swap function for uint32])
+fi
+
+AC_CACHE_CHECK([for __sync_bool_compare_and_swap_8],
+[libgo_cv_func___sync_bool_compare_and_swap_8],
+[AC_LINK_IFELSE([
+typedef unsigned int uint64  __attribute__ ((mode (DI)));
+uint64 i;
+int main() { return __sync_bool_compare_and_swap (&i, 0, 1); }
+],
+[libgo_cv_func___sync_bool_compare_and_swap_8=yes],
+[libgo_cv_func___sync_bool_compare_and_swap_8=no])])
+if test "$libgo_cv_func___sync_bool_compare_and_swap_8" = "yes"; then
+  AC_DEFINE(HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8, 1,
+    [Define to 1 if the compiler provides the __sync_bool_compare_and_swap function for uint64])
+fi
+
+AC_CACHE_CHECK([for __sync_fetch_and_add_4],
+[libgo_cv_func___sync_fetch_and_add_4],
+[AC_LINK_IFELSE([
+typedef unsigned int uint32  __attribute__ ((mode (SI)));
+uint32 i;
+int main() { return __sync_fetch_and_add (&i, 1); }
+],
+[libgo_cv_func___sync_fetch_and_add_4=yes],
+[libgo_cv_func___sync_fetch_and_add_4=no])])
+if test "$libgo_cv_func___sync_fetch_and_add_4" = "yes"; then
+  AC_DEFINE(HAVE_SYNC_FETCH_AND_ADD_4, 1,
+    [Define to 1 if the compiler provides the __sync_fetch_and_add function for uint32])
+fi
+
+AC_CACHE_CHECK([for __sync_add_and_fetch_8],
+[libgo_cv_func___sync_add_and_fetch_8],
+[AC_LINK_IFELSE([
+typedef unsigned int uint64  __attribute__ ((mode (DI)));
+uint64 i;
+int main() { return __sync_add_and_fetch (&i, 1); }
+],
+[libgo_cv_func___sync_add_and_fetch_8=yes],
+[libgo_cv_func___sync_add_and_fetch_8=no])])
+if test "$libgo_cv_func___sync_add_and_fetch_8" = "yes"; then
+  AC_DEFINE(HAVE_SYNC_ADD_AND_FETCH_8, 1,
+    [Define to 1 if the compiler provides the __sync_add_and_fetch function for uint64])
+fi
+
+dnl For x86 we want to use the -minline-all-stringops option to avoid
+dnl forcing a stack split when calling memcpy and friends.
+AC_CACHE_CHECK([whether compiler supports -minline-all-stringops],
+[libgo_cv_c_stringops],
+[CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -minline-all-stringops"
+AC_COMPILE_IFELSE([int i;],
+[libgo_cv_c_stringops=yes],
+[libgo_cv_c_stringops=no])
+CFLAGS=$CFLAGS_hold])
+STRINGOPS_FLAG=
+if test "$libgo_cv_c_stringops" = yes; then
+  STRINGOPS_FLAG=-minline-all-stringops
+fi
+AC_SUBST(STRINGOPS_FLAG)
+
+dnl For x86 we want to compile the math library with -mfancy-math-387
+dnl -funsafe-math-optimizations so that we can use the builtin
+dnl instructions directly.
+AC_CACHE_CHECK([whether compiler supports -mfancy-math-387],
+[libgo_cv_c_fancymath],
+[CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -mfancy-math-387"
+AC_COMPILE_IFELSE([int i;],
+[libgo_cv_c_fancymath=yes],
+[libgo_cv_c_fancymath=no])
+CFLAGS=$CFLAGS_hold])
+MATH_FLAG=
+if test "$libgo_cv_c_fancymath" = yes; then
+  MATH_FLAG="-mfancy-math-387 -funsafe-math-optimizations"
+else
+  MATH_FLAG="-ffp-contract=off"
+fi
+AC_SUBST(MATH_FLAG)
+
+CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE"
+AC_CHECK_TYPES([off64_t])
+CFLAGS=$CFLAGS_hold
+
+dnl Work out the size of the epoll_events struct on GNU/Linux.
+AC_CACHE_CHECK([epoll_event size],
+[libgo_cv_c_epoll_event_size],
+[AC_COMPUTE_INT(libgo_cv_c_epoll_event_size,
+[sizeof (struct epoll_event)],
+[#include <sys/epoll.h>],
+[libgo_cv_c_epoll_event_size=0])])
+SIZEOF_STRUCT_EPOLL_EVENT=${libgo_cv_c_epoll_event_size}
+AC_SUBST(SIZEOF_STRUCT_EPOLL_EVENT)
+
+dnl Work out the offset of the fd field in the epoll_events struct on
+dnl GNU/Linux.
+AC_CACHE_CHECK([epoll_event data.fd offset],
+[libgo_cv_c_epoll_event_fd_offset],
+[AC_COMPUTE_INT(libgo_cv_c_epoll_event_fd_offset,
+[offsetof (struct epoll_event, data.fd)],
+[#include <stddef.h>
+#include <sys/epoll.h>],
+[libgo_cv_c_epoll_event_fd_offset=0])])
+STRUCT_EPOLL_EVENT_FD_OFFSET=${libgo_cv_c_epoll_event_fd_offset}
+AC_SUBST(STRUCT_EPOLL_EVENT_FD_OFFSET)
+
+dnl See if struct exception is defined in <math.h>.
+AC_CHECK_TYPE([struct exception],
+[libgo_has_struct_exception=yes],
+[libgo_has_struct_exception=no],
+[#include <math.h>])
+if test "$libgo_has_struct_exception" = "yes"; then
+  AC_DEFINE(HAVE_STRUCT_EXCEPTION, 1,
+            [Define to 1 if <math.h> defines struct exception])
+fi
+
+dnl See whether setcontext changes the value of TLS variables.
+AC_CACHE_CHECK([whether setcontext clobbers TLS variables],
+[libgo_cv_lib_setcontext_clobbers_tls],
+[CFLAGS_hold="$CFLAGS"
+CFLAGS="$PTHREAD_CFLAGS"
+LIBS_hold="$LIBS"
+LIBS="$LIBS $PTHREAD_LIBS"
+AC_CHECK_SIZEOF([void *])
+AS_VAR_ARITH([ptr_type_size], [$ac_cv_sizeof_void_p \* 8])
+AC_RUN_IFELSE(
+  [AC_LANG_SOURCE([
+#include <pthread.h>
+#include <stdlib.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+__thread int tls;
+
+static char stack[[10 * 1024 * 1024]];
+static ucontext_t c;
+
+/* Called via makecontext/setcontext.  */
+
+static void
+cfn (void)
+{
+  exit (tls);
+}
+
+/* Called via pthread_create.  */
+
+static void *
+tfn (void *dummy)
+{
+  /* The thread should still see this value after calling
+     setcontext.  */
+  tls = 0;
+
+  setcontext (&c);
+
+  /* The call to setcontext should not return.  */
+  abort ();
+}
+
+int
+main ()
+{
+  pthread_t tid;
+
+  /* The thread should not see this value.  */
+  tls = 1;
+
+  if (getcontext (&c) < 0)
+    abort ();
+
+  c.uc_stack.ss_sp = stack;
+#ifdef MAKECONTEXT_STACK_TOP
+  c.uc_stack.ss_sp += sizeof stack;
+#endif
+  c.uc_stack.ss_flags = 0;
+  c.uc_stack.ss_size = sizeof stack;
+  c.uc_link = NULL;
+  makecontext (&c, cfn, 0);
+
+  if (pthread_create (&tid, NULL, tfn, NULL) != 0)
+    abort ();
+
+  if (pthread_join (tid, NULL) != 0)
+    abort ();
+
+  /* The thread should have called exit.  */
+  abort ();
+}
+])],
+[libgo_cv_lib_setcontext_clobbers_tls=no],
+[libgo_cv_lib_setcontext_clobbers_tls=yes],
+[case "$target:$ptr_type_size" in
+  i?86-*-solaris2.1[[01]]:64 | x86_64*-*-solaris2.1[[01]]:64)
+    libgo_cv_lib_setcontext_clobbers_tls=yes ;;
+  *)
+    libgo_cv_lib_setcontext_clobbers_tls=no ;;
+ esac
+])
+CFLAGS="$CFLAGS_hold"
+LIBS="$LIBS_hold"
+])
+if test "$libgo_cv_lib_setcontext_clobbers_tls" = "yes"; then
+  AC_DEFINE(SETCONTEXT_CLOBBERS_TLS, 1,
+	    [Define if setcontext clobbers TLS variables])
+fi
+
+AC_CACHE_CHECK([whether .eh_frame section should be read-only],
+libgo_cv_ro_eh_frame, [
+libgo_cv_ro_eh_frame=no
+echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
+if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
+  if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
+    libgo_cv_ro_eh_frame=yes
+  elif grep '.section.*eh_frame.*#alloc' conftest.c \
+       | grep -v '#write' > /dev/null; then
+    libgo_cv_ro_eh_frame=yes
+  fi
+fi
+rm -f conftest.*
+])
+if test "x$libgo_cv_ro_eh_frame" = xyes; then
+  AC_DEFINE(EH_FRAME_FLAGS, "a",
+	    [Define to the flags needed for the .section .eh_frame directive.])
+else
+  AC_DEFINE(EH_FRAME_FLAGS, "aw",
+	    [Define to the flags needed for the .section .eh_frame directive.])
+fi
+
+AC_CACHE_CHECK([if compiler supports -Qunused-arguments],
+[libgo_cv_c_unused_arguments],
+[CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -Qunused-arguments"
+AC_COMPILE_IFELSE([[int i;]],
+[libgo_cv_c_unused_arguments=yes],
+[libgo_cv_c_unused_arguments=no])
+CFLAGS=$CFLAGS_hold])
+
+AC_CACHE_CHECK([if assembler supports GNU comdat group syntax],
+libgo_cv_as_comdat_gnu, [
+echo '.section .text,"axG",@progbits,.foo,comdat' > conftest.s
+CFLAGS_hold=$CFLAGS
+if test "$libgo_cv_c_unused_arguments" = yes; then
+  CFLAGS="$CFLAGS -Qunused-arguments"
+fi
+if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then
+  libgo_cv_as_comdat_gnu=yes
+else
+  libgo_cv_as_comdat_gnu=no
+fi
+CFLAGS=$CFLAGS_hold
+])
+if test "x$libgo_cv_as_comdat_gnu" = xyes; then
+  AC_DEFINE(HAVE_AS_COMDAT_GAS, 1,
+	    [Define if your assembler supports GNU comdat group syntax.])
+fi
+
+AC_CACHE_CHECK([assembler supports pc related relocs],
+libgo_cv_as_x86_pcrel, [
+libgo_cv_as_x86_pcrel=yes
+echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
+CFLAGS_hold=$CFLAGS
+if test "$libgo_cv_c_unused_arguments" = yes; then
+  CFLAGS="$CFLAGS -Qunused-arguments"
+fi
+if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
+    libgo_cv_as_x86_pcrel=no
+fi
+CFLAGS=$CFLAGS_hold
+])
+if test "x$libgo_cv_as_x86_pcrel" = xyes; then
+  AC_DEFINE(HAVE_AS_X86_PCREL, 1,
+	    [Define if your assembler supports PC relative relocs.])
+fi
+
+AC_CACHE_CHECK([assembler supports unwind section type],
+libgo_cv_as_x86_64_unwind_section_type, [
+libgo_cv_as_x86_64_unwind_section_type=yes
+echo '.section .eh_frame,"a",@unwind' > conftest.s
+CFLAGS_hold=$CFLAGS
+if test "$libgo_cv_c_unused_arguments" = yes; then
+  CFLAGS="$CFLAGS -Qunused-arguments"
+fi
+if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
+    libgo_cv_as_x86_64_unwind_section_type=no
+fi
+CFLAGS=$CFLAGS_hold
+])
+if test "x$libgo_cv_as_x86_64_unwind_section_type" = xyes; then
+  AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
+	    [Define if your assembler supports unwind section type.])
+fi
+
+AC_CACHE_SAVE
+
+if test ${multilib} = yes; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+AC_CONFIG_FILES(Makefile testsuite/Makefile)
+
+AC_CONFIG_COMMANDS([default],
+[if test -n "$CONFIG_FILES"; then
+   # Multilibs need MULTISUBDIR defined correctly in certain makefiles so
+   # that multilib installs will end up installed in the correct place.
+   # The testsuite needs it for multilib-aware ABI baseline files.
+   # To work around this not being passed down from config-ml.in ->
+   # srcdir/Makefile.am -> srcdir/{src,libsupc++,...}/Makefile.am, manually
+   # append it here.  Only modify Makefiles that have just been created.
+   #
+   # Also, get rid of this simulated-VPATH thing that automake does.
+   cat > vpsed << \_EOF
+s!`test -f '$<' || echo '$(srcdir)/'`!!
+_EOF
+   for i in $SUBDIRS; do
+    case $CONFIG_FILES in
+     *${i}/Makefile*)
+       #echo "Adding MULTISUBDIR to $i/Makefile"
+       sed -f vpsed $i/Makefile > tmp
+       grep '^MULTISUBDIR =' Makefile >> tmp
+       mv tmp $i/Makefile
+       ;;
+    esac
+   done
+   rm vpsed
+ fi
+],
+[
+# Variables needed in config.status (file generation) which aren't already
+# passed by autoconf.
+SUBDIRS="$SUBDIRS"
+])
+
+AC_OUTPUT
diff --git a/third_party/gofrontend/libgo/go/archive/tar/common.go b/third_party/gofrontend/libgo/go/archive/tar/common.go
new file mode 100644
index 0000000..e363aa7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/common.go
@@ -0,0 +1,305 @@
+// 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 tar implements access to tar archives.
+// It aims to cover most of the variations, including those produced
+// by GNU and BSD tars.
+//
+// References:
+//   http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5
+//   http://www.gnu.org/software/tar/manual/html_node/Standard.html
+//   http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
+package tar
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"os"
+	"path"
+	"time"
+)
+
+const (
+	blockSize = 512
+
+	// Types
+	TypeReg           = '0'    // regular file
+	TypeRegA          = '\x00' // regular file
+	TypeLink          = '1'    // hard link
+	TypeSymlink       = '2'    // symbolic link
+	TypeChar          = '3'    // character device node
+	TypeBlock         = '4'    // block device node
+	TypeDir           = '5'    // directory
+	TypeFifo          = '6'    // fifo node
+	TypeCont          = '7'    // reserved
+	TypeXHeader       = 'x'    // extended header
+	TypeXGlobalHeader = 'g'    // global extended header
+	TypeGNULongName   = 'L'    // Next file has a long name
+	TypeGNULongLink   = 'K'    // Next file symlinks to a file w/ a long name
+	TypeGNUSparse     = 'S'    // sparse file
+)
+
+// A Header represents a single header in a tar archive.
+// Some fields may not be populated.
+type Header struct {
+	Name       string    // name of header file entry
+	Mode       int64     // permission and mode bits
+	Uid        int       // user id of owner
+	Gid        int       // group id of owner
+	Size       int64     // length in bytes
+	ModTime    time.Time // modified time
+	Typeflag   byte      // type of header entry
+	Linkname   string    // target name of link
+	Uname      string    // user name of owner
+	Gname      string    // group name of owner
+	Devmajor   int64     // major number of character or block device
+	Devminor   int64     // minor number of character or block device
+	AccessTime time.Time // access time
+	ChangeTime time.Time // status change time
+	Xattrs     map[string]string
+}
+
+// File name constants from the tar spec.
+const (
+	fileNameSize       = 100 // Maximum number of bytes in a standard tar name.
+	fileNamePrefixSize = 155 // Maximum number of ustar extension bytes.
+)
+
+// FileInfo returns an os.FileInfo for the Header.
+func (h *Header) FileInfo() os.FileInfo {
+	return headerFileInfo{h}
+}
+
+// headerFileInfo implements os.FileInfo.
+type headerFileInfo struct {
+	h *Header
+}
+
+func (fi headerFileInfo) Size() int64        { return fi.h.Size }
+func (fi headerFileInfo) IsDir() bool        { return fi.Mode().IsDir() }
+func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime }
+func (fi headerFileInfo) Sys() interface{}   { return fi.h }
+
+// Name returns the base name of the file.
+func (fi headerFileInfo) Name() string {
+	if fi.IsDir() {
+		return path.Base(path.Clean(fi.h.Name))
+	}
+	return path.Base(fi.h.Name)
+}
+
+// Mode returns the permission and mode bits for the headerFileInfo.
+func (fi headerFileInfo) Mode() (mode os.FileMode) {
+	// Set file permission bits.
+	mode = os.FileMode(fi.h.Mode).Perm()
+
+	// Set setuid, setgid and sticky bits.
+	if fi.h.Mode&c_ISUID != 0 {
+		// setuid
+		mode |= os.ModeSetuid
+	}
+	if fi.h.Mode&c_ISGID != 0 {
+		// setgid
+		mode |= os.ModeSetgid
+	}
+	if fi.h.Mode&c_ISVTX != 0 {
+		// sticky
+		mode |= os.ModeSticky
+	}
+
+	// Set file mode bits.
+	// clear perm, setuid, setgid and sticky bits.
+	m := os.FileMode(fi.h.Mode) &^ 07777
+	if m == c_ISDIR {
+		// directory
+		mode |= os.ModeDir
+	}
+	if m == c_ISFIFO {
+		// named pipe (FIFO)
+		mode |= os.ModeNamedPipe
+	}
+	if m == c_ISLNK {
+		// symbolic link
+		mode |= os.ModeSymlink
+	}
+	if m == c_ISBLK {
+		// device file
+		mode |= os.ModeDevice
+	}
+	if m == c_ISCHR {
+		// Unix character device
+		mode |= os.ModeDevice
+		mode |= os.ModeCharDevice
+	}
+	if m == c_ISSOCK {
+		// Unix domain socket
+		mode |= os.ModeSocket
+	}
+
+	switch fi.h.Typeflag {
+	case TypeLink, TypeSymlink:
+		// hard link, symbolic link
+		mode |= os.ModeSymlink
+	case TypeChar:
+		// character device node
+		mode |= os.ModeDevice
+		mode |= os.ModeCharDevice
+	case TypeBlock:
+		// block device node
+		mode |= os.ModeDevice
+	case TypeDir:
+		// directory
+		mode |= os.ModeDir
+	case TypeFifo:
+		// fifo node
+		mode |= os.ModeNamedPipe
+	}
+
+	return mode
+}
+
+// sysStat, if non-nil, populates h from system-dependent fields of fi.
+var sysStat func(fi os.FileInfo, h *Header) error
+
+// Mode constants from the tar spec.
+const (
+	c_ISUID  = 04000   // Set uid
+	c_ISGID  = 02000   // Set gid
+	c_ISVTX  = 01000   // Save text (sticky bit)
+	c_ISDIR  = 040000  // Directory
+	c_ISFIFO = 010000  // FIFO
+	c_ISREG  = 0100000 // Regular file
+	c_ISLNK  = 0120000 // Symbolic link
+	c_ISBLK  = 060000  // Block special file
+	c_ISCHR  = 020000  // Character special file
+	c_ISSOCK = 0140000 // Socket
+)
+
+// Keywords for the PAX Extended Header
+const (
+	paxAtime    = "atime"
+	paxCharset  = "charset"
+	paxComment  = "comment"
+	paxCtime    = "ctime" // please note that ctime is not a valid pax header.
+	paxGid      = "gid"
+	paxGname    = "gname"
+	paxLinkpath = "linkpath"
+	paxMtime    = "mtime"
+	paxPath     = "path"
+	paxSize     = "size"
+	paxUid      = "uid"
+	paxUname    = "uname"
+	paxXattr    = "SCHILY.xattr."
+	paxNone     = ""
+)
+
+// FileInfoHeader creates a partially-populated Header from fi.
+// If fi describes a symlink, FileInfoHeader records link as the link target.
+// If fi describes a directory, a slash is appended to the name.
+// Because os.FileInfo's Name method returns only the base name of
+// the file it describes, it may be necessary to modify the Name field
+// of the returned header to provide the full path name of the file.
+func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
+	if fi == nil {
+		return nil, errors.New("tar: FileInfo is nil")
+	}
+	fm := fi.Mode()
+	h := &Header{
+		Name:    fi.Name(),
+		ModTime: fi.ModTime(),
+		Mode:    int64(fm.Perm()), // or'd with c_IS* constants later
+	}
+	switch {
+	case fm.IsRegular():
+		h.Mode |= c_ISREG
+		h.Typeflag = TypeReg
+		h.Size = fi.Size()
+	case fi.IsDir():
+		h.Typeflag = TypeDir
+		h.Mode |= c_ISDIR
+		h.Name += "/"
+	case fm&os.ModeSymlink != 0:
+		h.Typeflag = TypeSymlink
+		h.Mode |= c_ISLNK
+		h.Linkname = link
+	case fm&os.ModeDevice != 0:
+		if fm&os.ModeCharDevice != 0 {
+			h.Mode |= c_ISCHR
+			h.Typeflag = TypeChar
+		} else {
+			h.Mode |= c_ISBLK
+			h.Typeflag = TypeBlock
+		}
+	case fm&os.ModeNamedPipe != 0:
+		h.Typeflag = TypeFifo
+		h.Mode |= c_ISFIFO
+	case fm&os.ModeSocket != 0:
+		h.Mode |= c_ISSOCK
+	default:
+		return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm)
+	}
+	if fm&os.ModeSetuid != 0 {
+		h.Mode |= c_ISUID
+	}
+	if fm&os.ModeSetgid != 0 {
+		h.Mode |= c_ISGID
+	}
+	if fm&os.ModeSticky != 0 {
+		h.Mode |= c_ISVTX
+	}
+	if sysStat != nil {
+		return h, sysStat(fi, h)
+	}
+	return h, nil
+}
+
+var zeroBlock = make([]byte, blockSize)
+
+// POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signed byte values.
+// We compute and return both.
+func checksum(header []byte) (unsigned int64, signed int64) {
+	for i := 0; i < len(header); i++ {
+		if i == 148 {
+			// The chksum field (header[148:156]) is special: it should be treated as space bytes.
+			unsigned += ' ' * 8
+			signed += ' ' * 8
+			i += 7
+			continue
+		}
+		unsigned += int64(header[i])
+		signed += int64(int8(header[i]))
+	}
+	return
+}
+
+type slicer []byte
+
+func (sp *slicer) next(n int) (b []byte) {
+	s := *sp
+	b, *sp = s[0:n], s[n:]
+	return
+}
+
+func isASCII(s string) bool {
+	for _, c := range s {
+		if c >= 0x80 {
+			return false
+		}
+	}
+	return true
+}
+
+func toASCII(s string) string {
+	if isASCII(s) {
+		return s
+	}
+	var buf bytes.Buffer
+	for _, c := range s {
+		if c < 0x80 {
+			buf.WriteByte(byte(c))
+		}
+	}
+	return buf.String()
+}
diff --git a/third_party/gofrontend/libgo/go/archive/tar/reader.go b/third_party/gofrontend/libgo/go/archive/tar/reader.go
new file mode 100644
index 0000000..920a9b0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/reader.go
@@ -0,0 +1,817 @@
+// 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 tar
+
+// TODO(dsymonds):
+//   - pax extensions
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"io/ioutil"
+	"os"
+	"strconv"
+	"strings"
+	"time"
+)
+
+var (
+	ErrHeader = errors.New("archive/tar: invalid tar header")
+)
+
+const maxNanoSecondIntSize = 9
+
+// A Reader provides sequential access to the contents of a tar archive.
+// A tar archive consists of a sequence of files.
+// The Next method advances to the next file in the archive (including the first),
+// and then it can be treated as an io.Reader to access the file's data.
+type Reader struct {
+	r    io.Reader
+	err  error
+	pad  int64          // amount of padding (ignored) after current file entry
+	curr numBytesReader // reader for current file entry
+}
+
+// A numBytesReader is an io.Reader with a numBytes method, returning the number
+// of bytes remaining in the underlying encoded data.
+type numBytesReader interface {
+	io.Reader
+	numBytes() int64
+}
+
+// A regFileReader is a numBytesReader for reading file data from a tar archive.
+type regFileReader struct {
+	r  io.Reader // underlying reader
+	nb int64     // number of unread bytes for current file entry
+}
+
+// A sparseFileReader is a numBytesReader for reading sparse file data from a tar archive.
+type sparseFileReader struct {
+	rfr *regFileReader // reads the sparse-encoded file data
+	sp  []sparseEntry  // the sparse map for the file
+	pos int64          // keeps track of file position
+	tot int64          // total size of the file
+}
+
+// Keywords for GNU sparse files in a PAX extended header
+const (
+	paxGNUSparseNumBlocks = "GNU.sparse.numblocks"
+	paxGNUSparseOffset    = "GNU.sparse.offset"
+	paxGNUSparseNumBytes  = "GNU.sparse.numbytes"
+	paxGNUSparseMap       = "GNU.sparse.map"
+	paxGNUSparseName      = "GNU.sparse.name"
+	paxGNUSparseMajor     = "GNU.sparse.major"
+	paxGNUSparseMinor     = "GNU.sparse.minor"
+	paxGNUSparseSize      = "GNU.sparse.size"
+	paxGNUSparseRealSize  = "GNU.sparse.realsize"
+)
+
+// Keywords for old GNU sparse headers
+const (
+	oldGNUSparseMainHeaderOffset               = 386
+	oldGNUSparseMainHeaderIsExtendedOffset     = 482
+	oldGNUSparseMainHeaderNumEntries           = 4
+	oldGNUSparseExtendedHeaderIsExtendedOffset = 504
+	oldGNUSparseExtendedHeaderNumEntries       = 21
+	oldGNUSparseOffsetSize                     = 12
+	oldGNUSparseNumBytesSize                   = 12
+)
+
+// NewReader creates a new Reader reading from r.
+func NewReader(r io.Reader) *Reader { return &Reader{r: r} }
+
+// Next advances to the next entry in the tar archive.
+func (tr *Reader) Next() (*Header, error) {
+	var hdr *Header
+	if tr.err == nil {
+		tr.skipUnread()
+	}
+	if tr.err != nil {
+		return hdr, tr.err
+	}
+	hdr = tr.readHeader()
+	if hdr == nil {
+		return hdr, tr.err
+	}
+	// Check for PAX/GNU header.
+	switch hdr.Typeflag {
+	case TypeXHeader:
+		//  PAX extended header
+		headers, err := parsePAX(tr)
+		if err != nil {
+			return nil, err
+		}
+		// We actually read the whole file,
+		// but this skips alignment padding
+		tr.skipUnread()
+		hdr = tr.readHeader()
+		mergePAX(hdr, headers)
+
+		// Check for a PAX format sparse file
+		sp, err := tr.checkForGNUSparsePAXHeaders(hdr, headers)
+		if err != nil {
+			tr.err = err
+			return nil, err
+		}
+		if sp != nil {
+			// Current file is a PAX format GNU sparse file.
+			// Set the current file reader to a sparse file reader.
+			tr.curr = &sparseFileReader{rfr: tr.curr.(*regFileReader), sp: sp, tot: hdr.Size}
+		}
+		return hdr, nil
+	case TypeGNULongName:
+		// We have a GNU long name header. Its contents are the real file name.
+		realname, err := ioutil.ReadAll(tr)
+		if err != nil {
+			return nil, err
+		}
+		hdr, err := tr.Next()
+		hdr.Name = cString(realname)
+		return hdr, err
+	case TypeGNULongLink:
+		// We have a GNU long link header.
+		realname, err := ioutil.ReadAll(tr)
+		if err != nil {
+			return nil, err
+		}
+		hdr, err := tr.Next()
+		hdr.Linkname = cString(realname)
+		return hdr, err
+	}
+	return hdr, tr.err
+}
+
+// checkForGNUSparsePAXHeaders checks the PAX headers for GNU sparse headers. If they are found, then
+// this function reads the sparse map and returns it. Unknown sparse formats are ignored, causing the file to
+// be treated as a regular file.
+func (tr *Reader) checkForGNUSparsePAXHeaders(hdr *Header, headers map[string]string) ([]sparseEntry, error) {
+	var sparseFormat string
+
+	// Check for sparse format indicators
+	major, majorOk := headers[paxGNUSparseMajor]
+	minor, minorOk := headers[paxGNUSparseMinor]
+	sparseName, sparseNameOk := headers[paxGNUSparseName]
+	_, sparseMapOk := headers[paxGNUSparseMap]
+	sparseSize, sparseSizeOk := headers[paxGNUSparseSize]
+	sparseRealSize, sparseRealSizeOk := headers[paxGNUSparseRealSize]
+
+	// Identify which, if any, sparse format applies from which PAX headers are set
+	if majorOk && minorOk {
+		sparseFormat = major + "." + minor
+	} else if sparseNameOk && sparseMapOk {
+		sparseFormat = "0.1"
+	} else if sparseSizeOk {
+		sparseFormat = "0.0"
+	} else {
+		// Not a PAX format GNU sparse file.
+		return nil, nil
+	}
+
+	// Check for unknown sparse format
+	if sparseFormat != "0.0" && sparseFormat != "0.1" && sparseFormat != "1.0" {
+		return nil, nil
+	}
+
+	// Update hdr from GNU sparse PAX headers
+	if sparseNameOk {
+		hdr.Name = sparseName
+	}
+	if sparseSizeOk {
+		realSize, err := strconv.ParseInt(sparseSize, 10, 0)
+		if err != nil {
+			return nil, ErrHeader
+		}
+		hdr.Size = realSize
+	} else if sparseRealSizeOk {
+		realSize, err := strconv.ParseInt(sparseRealSize, 10, 0)
+		if err != nil {
+			return nil, ErrHeader
+		}
+		hdr.Size = realSize
+	}
+
+	// Set up the sparse map, according to the particular sparse format in use
+	var sp []sparseEntry
+	var err error
+	switch sparseFormat {
+	case "0.0", "0.1":
+		sp, err = readGNUSparseMap0x1(headers)
+	case "1.0":
+		sp, err = readGNUSparseMap1x0(tr.curr)
+	}
+	return sp, err
+}
+
+// mergePAX merges well known headers according to PAX standard.
+// In general headers with the same name as those found
+// in the header struct overwrite those found in the header
+// struct with higher precision or longer values. Esp. useful
+// for name and linkname fields.
+func mergePAX(hdr *Header, headers map[string]string) error {
+	for k, v := range headers {
+		switch k {
+		case paxPath:
+			hdr.Name = v
+		case paxLinkpath:
+			hdr.Linkname = v
+		case paxGname:
+			hdr.Gname = v
+		case paxUname:
+			hdr.Uname = v
+		case paxUid:
+			uid, err := strconv.ParseInt(v, 10, 0)
+			if err != nil {
+				return err
+			}
+			hdr.Uid = int(uid)
+		case paxGid:
+			gid, err := strconv.ParseInt(v, 10, 0)
+			if err != nil {
+				return err
+			}
+			hdr.Gid = int(gid)
+		case paxAtime:
+			t, err := parsePAXTime(v)
+			if err != nil {
+				return err
+			}
+			hdr.AccessTime = t
+		case paxMtime:
+			t, err := parsePAXTime(v)
+			if err != nil {
+				return err
+			}
+			hdr.ModTime = t
+		case paxCtime:
+			t, err := parsePAXTime(v)
+			if err != nil {
+				return err
+			}
+			hdr.ChangeTime = t
+		case paxSize:
+			size, err := strconv.ParseInt(v, 10, 0)
+			if err != nil {
+				return err
+			}
+			hdr.Size = int64(size)
+		default:
+			if strings.HasPrefix(k, paxXattr) {
+				if hdr.Xattrs == nil {
+					hdr.Xattrs = make(map[string]string)
+				}
+				hdr.Xattrs[k[len(paxXattr):]] = v
+			}
+		}
+	}
+	return nil
+}
+
+// parsePAXTime takes a string of the form %d.%d as described in
+// the PAX specification.
+func parsePAXTime(t string) (time.Time, error) {
+	buf := []byte(t)
+	pos := bytes.IndexByte(buf, '.')
+	var seconds, nanoseconds int64
+	var err error
+	if pos == -1 {
+		seconds, err = strconv.ParseInt(t, 10, 0)
+		if err != nil {
+			return time.Time{}, err
+		}
+	} else {
+		seconds, err = strconv.ParseInt(string(buf[:pos]), 10, 0)
+		if err != nil {
+			return time.Time{}, err
+		}
+		nano_buf := string(buf[pos+1:])
+		// Pad as needed before converting to a decimal.
+		// For example .030 -> .030000000 -> 30000000 nanoseconds
+		if len(nano_buf) < maxNanoSecondIntSize {
+			// Right pad
+			nano_buf += strings.Repeat("0", maxNanoSecondIntSize-len(nano_buf))
+		} else if len(nano_buf) > maxNanoSecondIntSize {
+			// Right truncate
+			nano_buf = nano_buf[:maxNanoSecondIntSize]
+		}
+		nanoseconds, err = strconv.ParseInt(string(nano_buf), 10, 0)
+		if err != nil {
+			return time.Time{}, err
+		}
+	}
+	ts := time.Unix(seconds, nanoseconds)
+	return ts, nil
+}
+
+// parsePAX parses PAX headers.
+// If an extended header (type 'x') is invalid, ErrHeader is returned
+func parsePAX(r io.Reader) (map[string]string, error) {
+	buf, err := ioutil.ReadAll(r)
+	if err != nil {
+		return nil, err
+	}
+
+	// For GNU PAX sparse format 0.0 support.
+	// This function transforms the sparse format 0.0 headers into sparse format 0.1 headers.
+	var sparseMap bytes.Buffer
+
+	headers := make(map[string]string)
+	// Each record is constructed as
+	//     "%d %s=%s\n", length, keyword, value
+	for len(buf) > 0 {
+		// or the header was empty to start with.
+		var sp int
+		// The size field ends at the first space.
+		sp = bytes.IndexByte(buf, ' ')
+		if sp == -1 {
+			return nil, ErrHeader
+		}
+		// Parse the first token as a decimal integer.
+		n, err := strconv.ParseInt(string(buf[:sp]), 10, 0)
+		if err != nil {
+			return nil, ErrHeader
+		}
+		// Extract everything between the decimal and the n -1 on the
+		// beginning to eat the ' ', -1 on the end to skip the newline.
+		var record []byte
+		record, buf = buf[sp+1:n-1], buf[n:]
+		// The first equals is guaranteed to mark the end of the key.
+		// Everything else is value.
+		eq := bytes.IndexByte(record, '=')
+		if eq == -1 {
+			return nil, ErrHeader
+		}
+		key, value := record[:eq], record[eq+1:]
+
+		keyStr := string(key)
+		if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes {
+			// GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map.
+			sparseMap.Write(value)
+			sparseMap.Write([]byte{','})
+		} else {
+			// Normal key. Set the value in the headers map.
+			headers[keyStr] = string(value)
+		}
+	}
+	if sparseMap.Len() != 0 {
+		// Add sparse info to headers, chopping off the extra comma
+		sparseMap.Truncate(sparseMap.Len() - 1)
+		headers[paxGNUSparseMap] = sparseMap.String()
+	}
+	return headers, nil
+}
+
+// cString parses bytes as a NUL-terminated C-style string.
+// If a NUL byte is not found then the whole slice is returned as a string.
+func cString(b []byte) string {
+	n := 0
+	for n < len(b) && b[n] != 0 {
+		n++
+	}
+	return string(b[0:n])
+}
+
+func (tr *Reader) octal(b []byte) int64 {
+	// Check for binary format first.
+	if len(b) > 0 && b[0]&0x80 != 0 {
+		var x int64
+		for i, c := range b {
+			if i == 0 {
+				c &= 0x7f // ignore signal bit in first byte
+			}
+			x = x<<8 | int64(c)
+		}
+		return x
+	}
+
+	// Because unused fields are filled with NULs, we need
+	// to skip leading NULs. Fields may also be padded with
+	// spaces or NULs.
+	// So we remove leading and trailing NULs and spaces to
+	// be sure.
+	b = bytes.Trim(b, " \x00")
+
+	if len(b) == 0 {
+		return 0
+	}
+	x, err := strconv.ParseUint(cString(b), 8, 64)
+	if err != nil {
+		tr.err = err
+	}
+	return int64(x)
+}
+
+// skipUnread skips any unread bytes in the existing file entry, as well as any alignment padding.
+func (tr *Reader) skipUnread() {
+	nr := tr.numBytes() + tr.pad // number of bytes to skip
+	tr.curr, tr.pad = nil, 0
+	if sr, ok := tr.r.(io.Seeker); ok {
+		if _, err := sr.Seek(nr, os.SEEK_CUR); err == nil {
+			return
+		}
+	}
+	_, tr.err = io.CopyN(ioutil.Discard, tr.r, nr)
+}
+
+func (tr *Reader) verifyChecksum(header []byte) bool {
+	if tr.err != nil {
+		return false
+	}
+
+	given := tr.octal(header[148:156])
+	unsigned, signed := checksum(header)
+	return given == unsigned || given == signed
+}
+
+func (tr *Reader) readHeader() *Header {
+	header := make([]byte, blockSize)
+	if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
+		return nil
+	}
+
+	// Two blocks of zero bytes marks the end of the archive.
+	if bytes.Equal(header, zeroBlock[0:blockSize]) {
+		if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
+			return nil
+		}
+		if bytes.Equal(header, zeroBlock[0:blockSize]) {
+			tr.err = io.EOF
+		} else {
+			tr.err = ErrHeader // zero block and then non-zero block
+		}
+		return nil
+	}
+
+	if !tr.verifyChecksum(header) {
+		tr.err = ErrHeader
+		return nil
+	}
+
+	// Unpack
+	hdr := new(Header)
+	s := slicer(header)
+
+	hdr.Name = cString(s.next(100))
+	hdr.Mode = tr.octal(s.next(8))
+	hdr.Uid = int(tr.octal(s.next(8)))
+	hdr.Gid = int(tr.octal(s.next(8)))
+	hdr.Size = tr.octal(s.next(12))
+	hdr.ModTime = time.Unix(tr.octal(s.next(12)), 0)
+	s.next(8) // chksum
+	hdr.Typeflag = s.next(1)[0]
+	hdr.Linkname = cString(s.next(100))
+
+	// The remainder of the header depends on the value of magic.
+	// The original (v7) version of tar had no explicit magic field,
+	// so its magic bytes, like the rest of the block, are NULs.
+	magic := string(s.next(8)) // contains version field as well.
+	var format string
+	switch {
+	case magic[:6] == "ustar\x00": // POSIX tar (1003.1-1988)
+		if string(header[508:512]) == "tar\x00" {
+			format = "star"
+		} else {
+			format = "posix"
+		}
+	case magic == "ustar  \x00": // old GNU tar
+		format = "gnu"
+	}
+
+	switch format {
+	case "posix", "gnu", "star":
+		hdr.Uname = cString(s.next(32))
+		hdr.Gname = cString(s.next(32))
+		devmajor := s.next(8)
+		devminor := s.next(8)
+		if hdr.Typeflag == TypeChar || hdr.Typeflag == TypeBlock {
+			hdr.Devmajor = tr.octal(devmajor)
+			hdr.Devminor = tr.octal(devminor)
+		}
+		var prefix string
+		switch format {
+		case "posix", "gnu":
+			prefix = cString(s.next(155))
+		case "star":
+			prefix = cString(s.next(131))
+			hdr.AccessTime = time.Unix(tr.octal(s.next(12)), 0)
+			hdr.ChangeTime = time.Unix(tr.octal(s.next(12)), 0)
+		}
+		if len(prefix) > 0 {
+			hdr.Name = prefix + "/" + hdr.Name
+		}
+	}
+
+	if tr.err != nil {
+		tr.err = ErrHeader
+		return nil
+	}
+
+	// Maximum value of hdr.Size is 64 GB (12 octal digits),
+	// so there's no risk of int64 overflowing.
+	nb := int64(hdr.Size)
+	tr.pad = -nb & (blockSize - 1) // blockSize is a power of two
+
+	// Set the current file reader.
+	tr.curr = &regFileReader{r: tr.r, nb: nb}
+
+	// Check for old GNU sparse format entry.
+	if hdr.Typeflag == TypeGNUSparse {
+		// Get the real size of the file.
+		hdr.Size = tr.octal(header[483:495])
+
+		// Read the sparse map.
+		sp := tr.readOldGNUSparseMap(header)
+		if tr.err != nil {
+			return nil
+		}
+		// Current file is a GNU sparse file. Update the current file reader.
+		tr.curr = &sparseFileReader{rfr: tr.curr.(*regFileReader), sp: sp, tot: hdr.Size}
+	}
+
+	return hdr
+}
+
+// A sparseEntry holds a single entry in a sparse file's sparse map.
+// A sparse entry indicates the offset and size in a sparse file of a
+// block of data.
+type sparseEntry struct {
+	offset   int64
+	numBytes int64
+}
+
+// readOldGNUSparseMap reads the sparse map as stored in the old GNU sparse format.
+// The sparse map is stored in the tar header if it's small enough. If it's larger than four entries,
+// then one or more extension headers are used to store the rest of the sparse map.
+func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry {
+	isExtended := header[oldGNUSparseMainHeaderIsExtendedOffset] != 0
+	spCap := oldGNUSparseMainHeaderNumEntries
+	if isExtended {
+		spCap += oldGNUSparseExtendedHeaderNumEntries
+	}
+	sp := make([]sparseEntry, 0, spCap)
+	s := slicer(header[oldGNUSparseMainHeaderOffset:])
+
+	// Read the four entries from the main tar header
+	for i := 0; i < oldGNUSparseMainHeaderNumEntries; i++ {
+		offset := tr.octal(s.next(oldGNUSparseOffsetSize))
+		numBytes := tr.octal(s.next(oldGNUSparseNumBytesSize))
+		if tr.err != nil {
+			tr.err = ErrHeader
+			return nil
+		}
+		if offset == 0 && numBytes == 0 {
+			break
+		}
+		sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
+	}
+
+	for isExtended {
+		// There are more entries. Read an extension header and parse its entries.
+		sparseHeader := make([]byte, blockSize)
+		if _, tr.err = io.ReadFull(tr.r, sparseHeader); tr.err != nil {
+			return nil
+		}
+		isExtended = sparseHeader[oldGNUSparseExtendedHeaderIsExtendedOffset] != 0
+		s = slicer(sparseHeader)
+		for i := 0; i < oldGNUSparseExtendedHeaderNumEntries; i++ {
+			offset := tr.octal(s.next(oldGNUSparseOffsetSize))
+			numBytes := tr.octal(s.next(oldGNUSparseNumBytesSize))
+			if tr.err != nil {
+				tr.err = ErrHeader
+				return nil
+			}
+			if offset == 0 && numBytes == 0 {
+				break
+			}
+			sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
+		}
+	}
+	return sp
+}
+
+// readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format version 1.0.
+// The sparse map is stored just before the file data and padded out to the nearest block boundary.
+func readGNUSparseMap1x0(r io.Reader) ([]sparseEntry, error) {
+	buf := make([]byte, 2*blockSize)
+	sparseHeader := buf[:blockSize]
+
+	// readDecimal is a helper function to read a decimal integer from the sparse map
+	// while making sure to read from the file in blocks of size blockSize
+	readDecimal := func() (int64, error) {
+		// Look for newline
+		nl := bytes.IndexByte(sparseHeader, '\n')
+		if nl == -1 {
+			if len(sparseHeader) >= blockSize {
+				// This is an error
+				return 0, ErrHeader
+			}
+			oldLen := len(sparseHeader)
+			newLen := oldLen + blockSize
+			if cap(sparseHeader) < newLen {
+				// There's more header, but we need to make room for the next block
+				copy(buf, sparseHeader)
+				sparseHeader = buf[:newLen]
+			} else {
+				// There's more header, and we can just reslice
+				sparseHeader = sparseHeader[:newLen]
+			}
+
+			// Now that sparseHeader is large enough, read next block
+			if _, err := io.ReadFull(r, sparseHeader[oldLen:newLen]); err != nil {
+				return 0, err
+			}
+
+			// Look for a newline in the new data
+			nl = bytes.IndexByte(sparseHeader[oldLen:newLen], '\n')
+			if nl == -1 {
+				// This is an error
+				return 0, ErrHeader
+			}
+			nl += oldLen // We want the position from the beginning
+		}
+		// Now that we've found a newline, read a number
+		n, err := strconv.ParseInt(string(sparseHeader[:nl]), 10, 0)
+		if err != nil {
+			return 0, ErrHeader
+		}
+
+		// Update sparseHeader to consume this number
+		sparseHeader = sparseHeader[nl+1:]
+		return n, nil
+	}
+
+	// Read the first block
+	if _, err := io.ReadFull(r, sparseHeader); err != nil {
+		return nil, err
+	}
+
+	// The first line contains the number of entries
+	numEntries, err := readDecimal()
+	if err != nil {
+		return nil, err
+	}
+
+	// Read all the entries
+	sp := make([]sparseEntry, 0, numEntries)
+	for i := int64(0); i < numEntries; i++ {
+		// Read the offset
+		offset, err := readDecimal()
+		if err != nil {
+			return nil, err
+		}
+		// Read numBytes
+		numBytes, err := readDecimal()
+		if err != nil {
+			return nil, err
+		}
+
+		sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
+	}
+
+	return sp, nil
+}
+
+// readGNUSparseMap0x1 reads the sparse map as stored in GNU's PAX sparse format version 0.1.
+// The sparse map is stored in the PAX headers.
+func readGNUSparseMap0x1(headers map[string]string) ([]sparseEntry, error) {
+	// Get number of entries
+	numEntriesStr, ok := headers[paxGNUSparseNumBlocks]
+	if !ok {
+		return nil, ErrHeader
+	}
+	numEntries, err := strconv.ParseInt(numEntriesStr, 10, 0)
+	if err != nil {
+		return nil, ErrHeader
+	}
+
+	sparseMap := strings.Split(headers[paxGNUSparseMap], ",")
+
+	// There should be two numbers in sparseMap for each entry
+	if int64(len(sparseMap)) != 2*numEntries {
+		return nil, ErrHeader
+	}
+
+	// Loop through the entries in the sparse map
+	sp := make([]sparseEntry, 0, numEntries)
+	for i := int64(0); i < numEntries; i++ {
+		offset, err := strconv.ParseInt(sparseMap[2*i], 10, 0)
+		if err != nil {
+			return nil, ErrHeader
+		}
+		numBytes, err := strconv.ParseInt(sparseMap[2*i+1], 10, 0)
+		if err != nil {
+			return nil, ErrHeader
+		}
+		sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
+	}
+
+	return sp, nil
+}
+
+// numBytes returns the number of bytes left to read in the current file's entry
+// in the tar archive, or 0 if there is no current file.
+func (tr *Reader) numBytes() int64 {
+	if tr.curr == nil {
+		// No current file, so no bytes
+		return 0
+	}
+	return tr.curr.numBytes()
+}
+
+// Read reads from the current entry in the tar archive.
+// It returns 0, io.EOF when it reaches the end of that entry,
+// until Next is called to advance to the next entry.
+func (tr *Reader) Read(b []byte) (n int, err error) {
+	if tr.curr == nil {
+		return 0, io.EOF
+	}
+	n, err = tr.curr.Read(b)
+	if err != nil && err != io.EOF {
+		tr.err = err
+	}
+	return
+}
+
+func (rfr *regFileReader) Read(b []byte) (n int, err error) {
+	if rfr.nb == 0 {
+		// file consumed
+		return 0, io.EOF
+	}
+	if int64(len(b)) > rfr.nb {
+		b = b[0:rfr.nb]
+	}
+	n, err = rfr.r.Read(b)
+	rfr.nb -= int64(n)
+
+	if err == io.EOF && rfr.nb > 0 {
+		err = io.ErrUnexpectedEOF
+	}
+	return
+}
+
+// numBytes returns the number of bytes left to read in the file's data in the tar archive.
+func (rfr *regFileReader) numBytes() int64 {
+	return rfr.nb
+}
+
+// readHole reads a sparse file hole ending at offset toOffset
+func (sfr *sparseFileReader) readHole(b []byte, toOffset int64) int {
+	n64 := toOffset - sfr.pos
+	if n64 > int64(len(b)) {
+		n64 = int64(len(b))
+	}
+	n := int(n64)
+	for i := 0; i < n; i++ {
+		b[i] = 0
+	}
+	sfr.pos += n64
+	return n
+}
+
+// Read reads the sparse file data in expanded form.
+func (sfr *sparseFileReader) Read(b []byte) (n int, err error) {
+	if len(sfr.sp) == 0 {
+		// No more data fragments to read from.
+		if sfr.pos < sfr.tot {
+			// We're in the last hole
+			n = sfr.readHole(b, sfr.tot)
+			return
+		}
+		// Otherwise, we're at the end of the file
+		return 0, io.EOF
+	}
+	if sfr.pos < sfr.sp[0].offset {
+		// We're in a hole
+		n = sfr.readHole(b, sfr.sp[0].offset)
+		return
+	}
+
+	// We're not in a hole, so we'll read from the next data fragment
+	posInFragment := sfr.pos - sfr.sp[0].offset
+	bytesLeft := sfr.sp[0].numBytes - posInFragment
+	if int64(len(b)) > bytesLeft {
+		b = b[0:bytesLeft]
+	}
+
+	n, err = sfr.rfr.Read(b)
+	sfr.pos += int64(n)
+
+	if int64(n) == bytesLeft {
+		// We're done with this fragment
+		sfr.sp = sfr.sp[1:]
+	}
+
+	if err == io.EOF && sfr.pos < sfr.tot {
+		// We reached the end of the last fragment's data, but there's a final hole
+		err = nil
+	}
+	return
+}
+
+// numBytes returns the number of bytes left to read in the sparse file's
+// sparse-encoded data in the tar archive.
+func (sfr *sparseFileReader) numBytes() int64 {
+	return sfr.rfr.nb
+}
diff --git a/third_party/gofrontend/libgo/go/archive/tar/reader_test.go b/third_party/gofrontend/libgo/go/archive/tar/reader_test.go
new file mode 100644
index 0000000..9601ffe
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/reader_test.go
@@ -0,0 +1,743 @@
+// 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 tar
+
+import (
+	"bytes"
+	"crypto/md5"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+)
+
+type untarTest struct {
+	file    string
+	headers []*Header
+	cksums  []string
+}
+
+var gnuTarTest = &untarTest{
+	file: "testdata/gnu.tar",
+	headers: []*Header{
+		{
+			Name:     "small.txt",
+			Mode:     0640,
+			Uid:      73025,
+			Gid:      5000,
+			Size:     5,
+			ModTime:  time.Unix(1244428340, 0),
+			Typeflag: '0',
+			Uname:    "dsymonds",
+			Gname:    "eng",
+		},
+		{
+			Name:     "small2.txt",
+			Mode:     0640,
+			Uid:      73025,
+			Gid:      5000,
+			Size:     11,
+			ModTime:  time.Unix(1244436044, 0),
+			Typeflag: '0',
+			Uname:    "dsymonds",
+			Gname:    "eng",
+		},
+	},
+	cksums: []string{
+		"e38b27eaccb4391bdec553a7f3ae6b2f",
+		"c65bd2e50a56a2138bf1716f2fd56fe9",
+	},
+}
+
+var sparseTarTest = &untarTest{
+	file: "testdata/sparse-formats.tar",
+	headers: []*Header{
+		{
+			Name:     "sparse-gnu",
+			Mode:     420,
+			Uid:      1000,
+			Gid:      1000,
+			Size:     200,
+			ModTime:  time.Unix(1392395740, 0),
+			Typeflag: 0x53,
+			Linkname: "",
+			Uname:    "david",
+			Gname:    "david",
+			Devmajor: 0,
+			Devminor: 0,
+		},
+		{
+			Name:     "sparse-posix-0.0",
+			Mode:     420,
+			Uid:      1000,
+			Gid:      1000,
+			Size:     200,
+			ModTime:  time.Unix(1392342187, 0),
+			Typeflag: 0x30,
+			Linkname: "",
+			Uname:    "david",
+			Gname:    "david",
+			Devmajor: 0,
+			Devminor: 0,
+		},
+		{
+			Name:     "sparse-posix-0.1",
+			Mode:     420,
+			Uid:      1000,
+			Gid:      1000,
+			Size:     200,
+			ModTime:  time.Unix(1392340456, 0),
+			Typeflag: 0x30,
+			Linkname: "",
+			Uname:    "david",
+			Gname:    "david",
+			Devmajor: 0,
+			Devminor: 0,
+		},
+		{
+			Name:     "sparse-posix-1.0",
+			Mode:     420,
+			Uid:      1000,
+			Gid:      1000,
+			Size:     200,
+			ModTime:  time.Unix(1392337404, 0),
+			Typeflag: 0x30,
+			Linkname: "",
+			Uname:    "david",
+			Gname:    "david",
+			Devmajor: 0,
+			Devminor: 0,
+		},
+		{
+			Name:     "end",
+			Mode:     420,
+			Uid:      1000,
+			Gid:      1000,
+			Size:     4,
+			ModTime:  time.Unix(1392398319, 0),
+			Typeflag: 0x30,
+			Linkname: "",
+			Uname:    "david",
+			Gname:    "david",
+			Devmajor: 0,
+			Devminor: 0,
+		},
+	},
+	cksums: []string{
+		"6f53234398c2449fe67c1812d993012f",
+		"6f53234398c2449fe67c1812d993012f",
+		"6f53234398c2449fe67c1812d993012f",
+		"6f53234398c2449fe67c1812d993012f",
+		"b0061974914468de549a2af8ced10316",
+	},
+}
+
+var untarTests = []*untarTest{
+	gnuTarTest,
+	sparseTarTest,
+	{
+		file: "testdata/star.tar",
+		headers: []*Header{
+			{
+				Name:       "small.txt",
+				Mode:       0640,
+				Uid:        73025,
+				Gid:        5000,
+				Size:       5,
+				ModTime:    time.Unix(1244592783, 0),
+				Typeflag:   '0',
+				Uname:      "dsymonds",
+				Gname:      "eng",
+				AccessTime: time.Unix(1244592783, 0),
+				ChangeTime: time.Unix(1244592783, 0),
+			},
+			{
+				Name:       "small2.txt",
+				Mode:       0640,
+				Uid:        73025,
+				Gid:        5000,
+				Size:       11,
+				ModTime:    time.Unix(1244592783, 0),
+				Typeflag:   '0',
+				Uname:      "dsymonds",
+				Gname:      "eng",
+				AccessTime: time.Unix(1244592783, 0),
+				ChangeTime: time.Unix(1244592783, 0),
+			},
+		},
+	},
+	{
+		file: "testdata/v7.tar",
+		headers: []*Header{
+			{
+				Name:     "small.txt",
+				Mode:     0444,
+				Uid:      73025,
+				Gid:      5000,
+				Size:     5,
+				ModTime:  time.Unix(1244593104, 0),
+				Typeflag: '\x00',
+			},
+			{
+				Name:     "small2.txt",
+				Mode:     0444,
+				Uid:      73025,
+				Gid:      5000,
+				Size:     11,
+				ModTime:  time.Unix(1244593104, 0),
+				Typeflag: '\x00',
+			},
+		},
+	},
+	{
+		file: "testdata/pax.tar",
+		headers: []*Header{
+			{
+				Name:       "a/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
+				Mode:       0664,
+				Uid:        1000,
+				Gid:        1000,
+				Uname:      "shane",
+				Gname:      "shane",
+				Size:       7,
+				ModTime:    time.Unix(1350244992, 23960108),
+				ChangeTime: time.Unix(1350244992, 23960108),
+				AccessTime: time.Unix(1350244992, 23960108),
+				Typeflag:   TypeReg,
+			},
+			{
+				Name:       "a/b",
+				Mode:       0777,
+				Uid:        1000,
+				Gid:        1000,
+				Uname:      "shane",
+				Gname:      "shane",
+				Size:       0,
+				ModTime:    time.Unix(1350266320, 910238425),
+				ChangeTime: time.Unix(1350266320, 910238425),
+				AccessTime: time.Unix(1350266320, 910238425),
+				Typeflag:   TypeSymlink,
+				Linkname:   "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
+			},
+		},
+	},
+	{
+		file: "testdata/nil-uid.tar", // golang.org/issue/5290
+		headers: []*Header{
+			{
+				Name:     "P1050238.JPG.log",
+				Mode:     0664,
+				Uid:      0,
+				Gid:      0,
+				Size:     14,
+				ModTime:  time.Unix(1365454838, 0),
+				Typeflag: TypeReg,
+				Linkname: "",
+				Uname:    "eyefi",
+				Gname:    "eyefi",
+				Devmajor: 0,
+				Devminor: 0,
+			},
+		},
+	},
+	{
+		file: "testdata/xattrs.tar",
+		headers: []*Header{
+			{
+				Name:       "small.txt",
+				Mode:       0644,
+				Uid:        1000,
+				Gid:        10,
+				Size:       5,
+				ModTime:    time.Unix(1386065770, 448252320),
+				Typeflag:   '0',
+				Uname:      "alex",
+				Gname:      "wheel",
+				AccessTime: time.Unix(1389782991, 419875220),
+				ChangeTime: time.Unix(1389782956, 794414986),
+				Xattrs: map[string]string{
+					"user.key":  "value",
+					"user.key2": "value2",
+					// Interestingly, selinux encodes the terminating null inside the xattr
+					"security.selinux": "unconfined_u:object_r:default_t:s0\x00",
+				},
+			},
+			{
+				Name:       "small2.txt",
+				Mode:       0644,
+				Uid:        1000,
+				Gid:        10,
+				Size:       11,
+				ModTime:    time.Unix(1386065770, 449252304),
+				Typeflag:   '0',
+				Uname:      "alex",
+				Gname:      "wheel",
+				AccessTime: time.Unix(1389782991, 419875220),
+				ChangeTime: time.Unix(1386065770, 449252304),
+				Xattrs: map[string]string{
+					"security.selinux": "unconfined_u:object_r:default_t:s0\x00",
+				},
+			},
+		},
+	},
+}
+
+func TestReader(t *testing.T) {
+testLoop:
+	for i, test := range untarTests {
+		f, err := os.Open(test.file)
+		if err != nil {
+			t.Errorf("test %d: Unexpected error: %v", i, err)
+			continue
+		}
+		defer f.Close()
+		tr := NewReader(f)
+		for j, header := range test.headers {
+			hdr, err := tr.Next()
+			if err != nil || hdr == nil {
+				t.Errorf("test %d, entry %d: Didn't get entry: %v", i, j, err)
+				f.Close()
+				continue testLoop
+			}
+			if !reflect.DeepEqual(*hdr, *header) {
+				t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v",
+					i, j, *hdr, *header)
+			}
+		}
+		hdr, err := tr.Next()
+		if err == io.EOF {
+			continue testLoop
+		}
+		if hdr != nil || err != nil {
+			t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, hdr, err)
+		}
+	}
+}
+
+func TestPartialRead(t *testing.T) {
+	f, err := os.Open("testdata/gnu.tar")
+	if err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+	defer f.Close()
+
+	tr := NewReader(f)
+
+	// Read the first four bytes; Next() should skip the last byte.
+	hdr, err := tr.Next()
+	if err != nil || hdr == nil {
+		t.Fatalf("Didn't get first file: %v", err)
+	}
+	buf := make([]byte, 4)
+	if _, err := io.ReadFull(tr, buf); err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+	if expected := []byte("Kilt"); !bytes.Equal(buf, expected) {
+		t.Errorf("Contents = %v, want %v", buf, expected)
+	}
+
+	// Second file
+	hdr, err = tr.Next()
+	if err != nil || hdr == nil {
+		t.Fatalf("Didn't get second file: %v", err)
+	}
+	buf = make([]byte, 6)
+	if _, err := io.ReadFull(tr, buf); err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+	if expected := []byte("Google"); !bytes.Equal(buf, expected) {
+		t.Errorf("Contents = %v, want %v", buf, expected)
+	}
+}
+
+func TestIncrementalRead(t *testing.T) {
+	test := gnuTarTest
+	f, err := os.Open(test.file)
+	if err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+	defer f.Close()
+
+	tr := NewReader(f)
+
+	headers := test.headers
+	cksums := test.cksums
+	nread := 0
+
+	// loop over all files
+	for ; ; nread++ {
+		hdr, err := tr.Next()
+		if hdr == nil || err == io.EOF {
+			break
+		}
+
+		// check the header
+		if !reflect.DeepEqual(*hdr, *headers[nread]) {
+			t.Errorf("Incorrect header:\nhave %+v\nwant %+v",
+				*hdr, headers[nread])
+		}
+
+		// read file contents in little chunks EOF,
+		// checksumming all the way
+		h := md5.New()
+		rdbuf := make([]uint8, 8)
+		for {
+			nr, err := tr.Read(rdbuf)
+			if err == io.EOF {
+				break
+			}
+			if err != nil {
+				t.Errorf("Read: unexpected error %v\n", err)
+				break
+			}
+			h.Write(rdbuf[0:nr])
+		}
+		// verify checksum
+		have := fmt.Sprintf("%x", h.Sum(nil))
+		want := cksums[nread]
+		if want != have {
+			t.Errorf("Bad checksum on file %s:\nhave %+v\nwant %+v", hdr.Name, have, want)
+		}
+	}
+	if nread != len(headers) {
+		t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(headers), nread)
+	}
+}
+
+func TestNonSeekable(t *testing.T) {
+	test := gnuTarTest
+	f, err := os.Open(test.file)
+	if err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+	defer f.Close()
+
+	type readerOnly struct {
+		io.Reader
+	}
+	tr := NewReader(readerOnly{f})
+	nread := 0
+
+	for ; ; nread++ {
+		_, err := tr.Next()
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			t.Fatalf("Unexpected error: %v", err)
+		}
+	}
+
+	if nread != len(test.headers) {
+		t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(test.headers), nread)
+	}
+}
+
+func TestParsePAXHeader(t *testing.T) {
+	paxTests := [][3]string{
+		{"a", "a=name", "10 a=name\n"}, // Test case involving multiple acceptable lengths
+		{"a", "a=name", "9 a=name\n"},  // Test case involving multiple acceptable length
+		{"mtime", "mtime=1350244992.023960108", "30 mtime=1350244992.023960108\n"}}
+	for _, test := range paxTests {
+		key, expected, raw := test[0], test[1], test[2]
+		reader := bytes.NewReader([]byte(raw))
+		headers, err := parsePAX(reader)
+		if err != nil {
+			t.Errorf("Couldn't parse correctly formatted headers: %v", err)
+			continue
+		}
+		if strings.EqualFold(headers[key], expected) {
+			t.Errorf("mtime header incorrectly parsed: got %s, wanted %s", headers[key], expected)
+			continue
+		}
+		trailer := make([]byte, 100)
+		n, err := reader.Read(trailer)
+		if err != io.EOF || n != 0 {
+			t.Error("Buffer wasn't consumed")
+		}
+	}
+	badHeader := bytes.NewReader([]byte("3 somelongkey="))
+	if _, err := parsePAX(badHeader); err != ErrHeader {
+		t.Fatal("Unexpected success when parsing bad header")
+	}
+}
+
+func TestParsePAXTime(t *testing.T) {
+	// Some valid PAX time values
+	timestamps := map[string]time.Time{
+		"1350244992.023960108":  time.Unix(1350244992, 23960108), // The common case
+		"1350244992.02396010":   time.Unix(1350244992, 23960100), // Lower precision value
+		"1350244992.0239601089": time.Unix(1350244992, 23960108), // Higher precision value
+		"1350244992":            time.Unix(1350244992, 0),        // Low precision value
+	}
+	for input, expected := range timestamps {
+		ts, err := parsePAXTime(input)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !ts.Equal(expected) {
+			t.Fatalf("Time parsing failure %s %s", ts, expected)
+		}
+	}
+}
+
+func TestMergePAX(t *testing.T) {
+	hdr := new(Header)
+	// Test a string, integer, and time based value.
+	headers := map[string]string{
+		"path":  "a/b/c",
+		"uid":   "1000",
+		"mtime": "1350244992.023960108",
+	}
+	err := mergePAX(hdr, headers)
+	if err != nil {
+		t.Fatal(err)
+	}
+	want := &Header{
+		Name:    "a/b/c",
+		Uid:     1000,
+		ModTime: time.Unix(1350244992, 23960108),
+	}
+	if !reflect.DeepEqual(hdr, want) {
+		t.Errorf("incorrect merge: got %+v, want %+v", hdr, want)
+	}
+}
+
+func TestSparseEndToEnd(t *testing.T) {
+	test := sparseTarTest
+	f, err := os.Open(test.file)
+	if err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+	defer f.Close()
+
+	tr := NewReader(f)
+
+	headers := test.headers
+	cksums := test.cksums
+	nread := 0
+
+	// loop over all files
+	for ; ; nread++ {
+		hdr, err := tr.Next()
+		if hdr == nil || err == io.EOF {
+			break
+		}
+
+		// check the header
+		if !reflect.DeepEqual(*hdr, *headers[nread]) {
+			t.Errorf("Incorrect header:\nhave %+v\nwant %+v",
+				*hdr, headers[nread])
+		}
+
+		// read and checksum the file data
+		h := md5.New()
+		_, err = io.Copy(h, tr)
+		if err != nil {
+			t.Fatalf("Unexpected error: %v", err)
+		}
+
+		// verify checksum
+		have := fmt.Sprintf("%x", h.Sum(nil))
+		want := cksums[nread]
+		if want != have {
+			t.Errorf("Bad checksum on file %s:\nhave %+v\nwant %+v", hdr.Name, have, want)
+		}
+	}
+	if nread != len(headers) {
+		t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(headers), nread)
+	}
+}
+
+type sparseFileReadTest struct {
+	sparseData []byte
+	sparseMap  []sparseEntry
+	realSize   int64
+	expected   []byte
+}
+
+var sparseFileReadTests = []sparseFileReadTest{
+	{
+		sparseData: []byte("abcde"),
+		sparseMap: []sparseEntry{
+			{offset: 0, numBytes: 2},
+			{offset: 5, numBytes: 3},
+		},
+		realSize: 8,
+		expected: []byte("ab\x00\x00\x00cde"),
+	},
+	{
+		sparseData: []byte("abcde"),
+		sparseMap: []sparseEntry{
+			{offset: 0, numBytes: 2},
+			{offset: 5, numBytes: 3},
+		},
+		realSize: 10,
+		expected: []byte("ab\x00\x00\x00cde\x00\x00"),
+	},
+	{
+		sparseData: []byte("abcde"),
+		sparseMap: []sparseEntry{
+			{offset: 1, numBytes: 3},
+			{offset: 6, numBytes: 2},
+		},
+		realSize: 8,
+		expected: []byte("\x00abc\x00\x00de"),
+	},
+	{
+		sparseData: []byte("abcde"),
+		sparseMap: []sparseEntry{
+			{offset: 1, numBytes: 3},
+			{offset: 6, numBytes: 2},
+		},
+		realSize: 10,
+		expected: []byte("\x00abc\x00\x00de\x00\x00"),
+	},
+	{
+		sparseData: []byte(""),
+		sparseMap:  nil,
+		realSize:   2,
+		expected:   []byte("\x00\x00"),
+	},
+}
+
+func TestSparseFileReader(t *testing.T) {
+	for i, test := range sparseFileReadTests {
+		r := bytes.NewReader(test.sparseData)
+		nb := int64(r.Len())
+		sfr := &sparseFileReader{
+			rfr: &regFileReader{r: r, nb: nb},
+			sp:  test.sparseMap,
+			pos: 0,
+			tot: test.realSize,
+		}
+		if sfr.numBytes() != nb {
+			t.Errorf("test %d: Before reading, sfr.numBytes() = %d, want %d", i, sfr.numBytes(), nb)
+		}
+		buf, err := ioutil.ReadAll(sfr)
+		if err != nil {
+			t.Errorf("test %d: Unexpected error: %v", i, err)
+		}
+		if e := test.expected; !bytes.Equal(buf, e) {
+			t.Errorf("test %d: Contents = %v, want %v", i, buf, e)
+		}
+		if sfr.numBytes() != 0 {
+			t.Errorf("test %d: After draining the reader, numBytes() was nonzero", i)
+		}
+	}
+}
+
+func TestSparseIncrementalRead(t *testing.T) {
+	sparseMap := []sparseEntry{{10, 2}}
+	sparseData := []byte("Go")
+	expected := "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Go\x00\x00\x00\x00\x00\x00\x00\x00"
+
+	r := bytes.NewReader(sparseData)
+	nb := int64(r.Len())
+	sfr := &sparseFileReader{
+		rfr: &regFileReader{r: r, nb: nb},
+		sp:  sparseMap,
+		pos: 0,
+		tot: int64(len(expected)),
+	}
+
+	// We'll read the data 6 bytes at a time, with a hole of size 10 at
+	// the beginning and one of size 8 at the end.
+	var outputBuf bytes.Buffer
+	buf := make([]byte, 6)
+	for {
+		n, err := sfr.Read(buf)
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			t.Errorf("Read: unexpected error %v\n", err)
+		}
+		if n > 0 {
+			_, err := outputBuf.Write(buf[:n])
+			if err != nil {
+				t.Errorf("Write: unexpected error %v\n", err)
+			}
+		}
+	}
+	got := outputBuf.String()
+	if got != expected {
+		t.Errorf("Contents = %v, want %v", got, expected)
+	}
+}
+
+func TestReadGNUSparseMap0x1(t *testing.T) {
+	headers := map[string]string{
+		paxGNUSparseNumBlocks: "4",
+		paxGNUSparseMap:       "0,5,10,5,20,5,30,5",
+	}
+	expected := []sparseEntry{
+		{offset: 0, numBytes: 5},
+		{offset: 10, numBytes: 5},
+		{offset: 20, numBytes: 5},
+		{offset: 30, numBytes: 5},
+	}
+
+	sp, err := readGNUSparseMap0x1(headers)
+	if err != nil {
+		t.Errorf("Unexpected error: %v", err)
+	}
+	if !reflect.DeepEqual(sp, expected) {
+		t.Errorf("Incorrect sparse map: got %v, wanted %v", sp, expected)
+	}
+}
+
+func TestReadGNUSparseMap1x0(t *testing.T) {
+	// This test uses lots of holes so the sparse header takes up more than two blocks
+	numEntries := 100
+	expected := make([]sparseEntry, 0, numEntries)
+	sparseMap := new(bytes.Buffer)
+
+	fmt.Fprintf(sparseMap, "%d\n", numEntries)
+	for i := 0; i < numEntries; i++ {
+		offset := int64(2048 * i)
+		numBytes := int64(1024)
+		expected = append(expected, sparseEntry{offset: offset, numBytes: numBytes})
+		fmt.Fprintf(sparseMap, "%d\n%d\n", offset, numBytes)
+	}
+
+	// Make the header the smallest multiple of blockSize that fits the sparseMap
+	headerBlocks := (sparseMap.Len() + blockSize - 1) / blockSize
+	bufLen := blockSize * headerBlocks
+	buf := make([]byte, bufLen)
+	copy(buf, sparseMap.Bytes())
+
+	// Get an reader to read the sparse map
+	r := bytes.NewReader(buf)
+
+	// Read the sparse map
+	sp, err := readGNUSparseMap1x0(r)
+	if err != nil {
+		t.Errorf("Unexpected error: %v", err)
+	}
+	if !reflect.DeepEqual(sp, expected) {
+		t.Errorf("Incorrect sparse map: got %v, wanted %v", sp, expected)
+	}
+}
+
+func TestUninitializedRead(t *testing.T) {
+	test := gnuTarTest
+	f, err := os.Open(test.file)
+	if err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+	defer f.Close()
+
+	tr := NewReader(f)
+	_, err = tr.Read([]byte{})
+	if err == nil || err != io.EOF {
+		t.Errorf("Unexpected error: %v, wanted %v", err, io.EOF)
+	}
+
+}
diff --git a/third_party/gofrontend/libgo/go/archive/tar/stat_atim.go b/third_party/gofrontend/libgo/go/archive/tar/stat_atim.go
new file mode 100644
index 0000000..cf9cc79
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/stat_atim.go
@@ -0,0 +1,20 @@
+// 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.
+
+// +build linux dragonfly openbsd solaris
+
+package tar
+
+import (
+	"syscall"
+	"time"
+)
+
+func statAtime(st *syscall.Stat_t) time.Time {
+	return time.Unix(st.Atim.Unix())
+}
+
+func statCtime(st *syscall.Stat_t) time.Time {
+	return time.Unix(st.Ctim.Unix())
+}
diff --git a/third_party/gofrontend/libgo/go/archive/tar/stat_atimespec.go b/third_party/gofrontend/libgo/go/archive/tar/stat_atimespec.go
new file mode 100644
index 0000000..6f17dbe
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/stat_atimespec.go
@@ -0,0 +1,20 @@
+// 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.
+
+// +build darwin freebsd netbsd
+
+package tar
+
+import (
+	"syscall"
+	"time"
+)
+
+func statAtime(st *syscall.Stat_t) time.Time {
+	return time.Unix(st.Atimespec.Unix())
+}
+
+func statCtime(st *syscall.Stat_t) time.Time {
+	return time.Unix(st.Ctimespec.Unix())
+}
diff --git a/third_party/gofrontend/libgo/go/archive/tar/stat_unix.go b/third_party/gofrontend/libgo/go/archive/tar/stat_unix.go
new file mode 100644
index 0000000..cb843db
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/stat_unix.go
@@ -0,0 +1,32 @@
+// 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.
+
+// +build linux darwin dragonfly freebsd openbsd netbsd solaris
+
+package tar
+
+import (
+	"os"
+	"syscall"
+)
+
+func init() {
+	sysStat = statUnix
+}
+
+func statUnix(fi os.FileInfo, h *Header) error {
+	sys, ok := fi.Sys().(*syscall.Stat_t)
+	if !ok {
+		return nil
+	}
+	h.Uid = int(sys.Uid)
+	h.Gid = int(sys.Gid)
+	// TODO(bradfitz): populate username & group.  os/user
+	// doesn't cache LookupId lookups, and lacks group
+	// lookup functions.
+	h.AccessTime = statAtime(sys)
+	h.ChangeTime = statCtime(sys)
+	// TODO(bradfitz): major/minor device numbers?
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/archive/tar/tar_test.go b/third_party/gofrontend/libgo/go/archive/tar/tar_test.go
new file mode 100644
index 0000000..ed333f3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/tar_test.go
@@ -0,0 +1,284 @@
+// 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 tar
+
+import (
+	"bytes"
+	"io/ioutil"
+	"os"
+	"path"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+)
+
+func TestFileInfoHeader(t *testing.T) {
+	fi, err := os.Stat("testdata/small.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	h, err := FileInfoHeader(fi, "")
+	if err != nil {
+		t.Fatalf("FileInfoHeader: %v", err)
+	}
+	if g, e := h.Name, "small.txt"; g != e {
+		t.Errorf("Name = %q; want %q", g, e)
+	}
+	if g, e := h.Mode, int64(fi.Mode().Perm())|c_ISREG; g != e {
+		t.Errorf("Mode = %#o; want %#o", g, e)
+	}
+	if g, e := h.Size, int64(5); g != e {
+		t.Errorf("Size = %v; want %v", g, e)
+	}
+	if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) {
+		t.Errorf("ModTime = %v; want %v", g, e)
+	}
+	// FileInfoHeader should error when passing nil FileInfo
+	if _, err := FileInfoHeader(nil, ""); err == nil {
+		t.Fatalf("Expected error when passing nil to FileInfoHeader")
+	}
+}
+
+func TestFileInfoHeaderDir(t *testing.T) {
+	fi, err := os.Stat("testdata")
+	if err != nil {
+		t.Fatal(err)
+	}
+	h, err := FileInfoHeader(fi, "")
+	if err != nil {
+		t.Fatalf("FileInfoHeader: %v", err)
+	}
+	if g, e := h.Name, "testdata/"; g != e {
+		t.Errorf("Name = %q; want %q", g, e)
+	}
+	// Ignoring c_ISGID for golang.org/issue/4867
+	if g, e := h.Mode&^c_ISGID, int64(fi.Mode().Perm())|c_ISDIR; g != e {
+		t.Errorf("Mode = %#o; want %#o", g, e)
+	}
+	if g, e := h.Size, int64(0); g != e {
+		t.Errorf("Size = %v; want %v", g, e)
+	}
+	if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) {
+		t.Errorf("ModTime = %v; want %v", g, e)
+	}
+}
+
+func TestFileInfoHeaderSymlink(t *testing.T) {
+	h, err := FileInfoHeader(symlink{}, "some-target")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, e := h.Name, "some-symlink"; g != e {
+		t.Errorf("Name = %q; want %q", g, e)
+	}
+	if g, e := h.Linkname, "some-target"; g != e {
+		t.Errorf("Linkname = %q; want %q", g, e)
+	}
+}
+
+type symlink struct{}
+
+func (symlink) Name() string       { return "some-symlink" }
+func (symlink) Size() int64        { return 0 }
+func (symlink) Mode() os.FileMode  { return os.ModeSymlink }
+func (symlink) ModTime() time.Time { return time.Time{} }
+func (symlink) IsDir() bool        { return false }
+func (symlink) Sys() interface{}   { return nil }
+
+func TestRoundTrip(t *testing.T) {
+	data := []byte("some file contents")
+
+	var b bytes.Buffer
+	tw := NewWriter(&b)
+	hdr := &Header{
+		Name:    "file.txt",
+		Uid:     1 << 21, // too big for 8 octal digits
+		Size:    int64(len(data)),
+		ModTime: time.Now(),
+	}
+	// tar only supports second precision.
+	hdr.ModTime = hdr.ModTime.Add(-time.Duration(hdr.ModTime.Nanosecond()) * time.Nanosecond)
+	if err := tw.WriteHeader(hdr); err != nil {
+		t.Fatalf("tw.WriteHeader: %v", err)
+	}
+	if _, err := tw.Write(data); err != nil {
+		t.Fatalf("tw.Write: %v", err)
+	}
+	if err := tw.Close(); err != nil {
+		t.Fatalf("tw.Close: %v", err)
+	}
+
+	// Read it back.
+	tr := NewReader(&b)
+	rHdr, err := tr.Next()
+	if err != nil {
+		t.Fatalf("tr.Next: %v", err)
+	}
+	if !reflect.DeepEqual(rHdr, hdr) {
+		t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr)
+	}
+	rData, err := ioutil.ReadAll(tr)
+	if err != nil {
+		t.Fatalf("Read: %v", err)
+	}
+	if !bytes.Equal(rData, data) {
+		t.Errorf("Data mismatch.\n got %q\nwant %q", rData, data)
+	}
+}
+
+type headerRoundTripTest struct {
+	h  *Header
+	fm os.FileMode
+}
+
+func TestHeaderRoundTrip(t *testing.T) {
+	golden := []headerRoundTripTest{
+		// regular file.
+		{
+			h: &Header{
+				Name:     "test.txt",
+				Mode:     0644 | c_ISREG,
+				Size:     12,
+				ModTime:  time.Unix(1360600916, 0),
+				Typeflag: TypeReg,
+			},
+			fm: 0644,
+		},
+		// hard link.
+		{
+			h: &Header{
+				Name:     "hard.txt",
+				Mode:     0644 | c_ISLNK,
+				Size:     0,
+				ModTime:  time.Unix(1360600916, 0),
+				Typeflag: TypeLink,
+			},
+			fm: 0644 | os.ModeSymlink,
+		},
+		// symbolic link.
+		{
+			h: &Header{
+				Name:     "link.txt",
+				Mode:     0777 | c_ISLNK,
+				Size:     0,
+				ModTime:  time.Unix(1360600852, 0),
+				Typeflag: TypeSymlink,
+			},
+			fm: 0777 | os.ModeSymlink,
+		},
+		// character device node.
+		{
+			h: &Header{
+				Name:     "dev/null",
+				Mode:     0666 | c_ISCHR,
+				Size:     0,
+				ModTime:  time.Unix(1360578951, 0),
+				Typeflag: TypeChar,
+			},
+			fm: 0666 | os.ModeDevice | os.ModeCharDevice,
+		},
+		// block device node.
+		{
+			h: &Header{
+				Name:     "dev/sda",
+				Mode:     0660 | c_ISBLK,
+				Size:     0,
+				ModTime:  time.Unix(1360578954, 0),
+				Typeflag: TypeBlock,
+			},
+			fm: 0660 | os.ModeDevice,
+		},
+		// directory.
+		{
+			h: &Header{
+				Name:     "dir/",
+				Mode:     0755 | c_ISDIR,
+				Size:     0,
+				ModTime:  time.Unix(1360601116, 0),
+				Typeflag: TypeDir,
+			},
+			fm: 0755 | os.ModeDir,
+		},
+		// fifo node.
+		{
+			h: &Header{
+				Name:     "dev/initctl",
+				Mode:     0600 | c_ISFIFO,
+				Size:     0,
+				ModTime:  time.Unix(1360578949, 0),
+				Typeflag: TypeFifo,
+			},
+			fm: 0600 | os.ModeNamedPipe,
+		},
+		// setuid.
+		{
+			h: &Header{
+				Name:     "bin/su",
+				Mode:     0755 | c_ISREG | c_ISUID,
+				Size:     23232,
+				ModTime:  time.Unix(1355405093, 0),
+				Typeflag: TypeReg,
+			},
+			fm: 0755 | os.ModeSetuid,
+		},
+		// setguid.
+		{
+			h: &Header{
+				Name:     "group.txt",
+				Mode:     0750 | c_ISREG | c_ISGID,
+				Size:     0,
+				ModTime:  time.Unix(1360602346, 0),
+				Typeflag: TypeReg,
+			},
+			fm: 0750 | os.ModeSetgid,
+		},
+		// sticky.
+		{
+			h: &Header{
+				Name:     "sticky.txt",
+				Mode:     0600 | c_ISREG | c_ISVTX,
+				Size:     7,
+				ModTime:  time.Unix(1360602540, 0),
+				Typeflag: TypeReg,
+			},
+			fm: 0600 | os.ModeSticky,
+		},
+	}
+
+	for i, g := range golden {
+		fi := g.h.FileInfo()
+		h2, err := FileInfoHeader(fi, "")
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		if strings.Contains(fi.Name(), "/") {
+			t.Errorf("FileInfo of %q contains slash: %q", g.h.Name, fi.Name())
+		}
+		name := path.Base(g.h.Name)
+		if fi.IsDir() {
+			name += "/"
+		}
+		if got, want := h2.Name, name; got != want {
+			t.Errorf("i=%d: Name: got %v, want %v", i, got, want)
+		}
+		if got, want := h2.Size, g.h.Size; got != want {
+			t.Errorf("i=%d: Size: got %v, want %v", i, got, want)
+		}
+		if got, want := h2.Mode, g.h.Mode; got != want {
+			t.Errorf("i=%d: Mode: got %o, want %o", i, got, want)
+		}
+		if got, want := fi.Mode(), g.fm; got != want {
+			t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want)
+		}
+		if got, want := h2.ModTime, g.h.ModTime; got != want {
+			t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want)
+		}
+		if sysh, ok := fi.Sys().(*Header); !ok || sysh != g.h {
+			t.Errorf("i=%d: Sys didn't return original *Header", i)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/gnu.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/gnu.tar
new file mode 100644
index 0000000..fc899dc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/gnu.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/nil-uid.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/nil-uid.tar
new file mode 100644
index 0000000..cc9cfaa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/nil-uid.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/pax.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/pax.tar
new file mode 100644
index 0000000..9bc24b6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/pax.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/small.txt b/third_party/gofrontend/libgo/go/archive/tar/testdata/small.txt
new file mode 100644
index 0000000..b249bfc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/small.txt
@@ -0,0 +1 @@
+Kilts
\ No newline at end of file
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/small2.txt b/third_party/gofrontend/libgo/go/archive/tar/testdata/small2.txt
new file mode 100644
index 0000000..394ee3e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/small2.txt
@@ -0,0 +1 @@
+Google.com
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/sparse-formats.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/sparse-formats.tar
new file mode 100644
index 0000000..8bd4e74
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/sparse-formats.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/star.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/star.tar
new file mode 100644
index 0000000..59e2d4e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/star.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/ustar.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/ustar.tar
new file mode 100644
index 0000000..29679d9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/ustar.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/v7.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/v7.tar
new file mode 100644
index 0000000..eb65fc9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/v7.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/writer-big-long.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/writer-big-long.tar
new file mode 100644
index 0000000..5960ee8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/writer-big-long.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/writer-big.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/writer-big.tar
new file mode 100644
index 0000000..753e883
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/writer-big.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/writer.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/writer.tar
new file mode 100644
index 0000000..e6d816a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/writer.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/testdata/xattrs.tar b/third_party/gofrontend/libgo/go/archive/tar/testdata/xattrs.tar
new file mode 100644
index 0000000..9701950
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/testdata/xattrs.tar
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/tar/writer.go b/third_party/gofrontend/libgo/go/archive/tar/writer.go
new file mode 100644
index 0000000..6eff6f6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/writer.go
@@ -0,0 +1,383 @@
+// 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 tar
+
+// TODO(dsymonds):
+// - catch more errors (no first header, etc.)
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"os"
+	"path"
+	"strconv"
+	"strings"
+	"time"
+)
+
+var (
+	ErrWriteTooLong    = errors.New("archive/tar: write too long")
+	ErrFieldTooLong    = errors.New("archive/tar: header field too long")
+	ErrWriteAfterClose = errors.New("archive/tar: write after close")
+	errNameTooLong     = errors.New("archive/tar: name too long")
+	errInvalidHeader   = errors.New("archive/tar: header field too long or contains invalid values")
+)
+
+// A Writer provides sequential writing of a tar archive in POSIX.1 format.
+// A tar archive consists of a sequence of files.
+// Call WriteHeader to begin a new file, and then call Write to supply that file's data,
+// writing at most hdr.Size bytes in total.
+type Writer struct {
+	w          io.Writer
+	err        error
+	nb         int64 // number of unwritten bytes for current file entry
+	pad        int64 // amount of padding to write after current file entry
+	closed     bool
+	usedBinary bool // whether the binary numeric field extension was used
+	preferPax  bool // use pax header instead of binary numeric header
+}
+
+// NewWriter creates a new Writer writing to w.
+func NewWriter(w io.Writer) *Writer { return &Writer{w: w} }
+
+// Flush finishes writing the current file (optional).
+func (tw *Writer) Flush() error {
+	if tw.nb > 0 {
+		tw.err = fmt.Errorf("archive/tar: missed writing %d bytes", tw.nb)
+		return tw.err
+	}
+
+	n := tw.nb + tw.pad
+	for n > 0 && tw.err == nil {
+		nr := n
+		if nr > blockSize {
+			nr = blockSize
+		}
+		var nw int
+		nw, tw.err = tw.w.Write(zeroBlock[0:nr])
+		n -= int64(nw)
+	}
+	tw.nb = 0
+	tw.pad = 0
+	return tw.err
+}
+
+// Write s into b, terminating it with a NUL if there is room.
+// If the value is too long for the field and allowPax is true add a paxheader record instead
+func (tw *Writer) cString(b []byte, s string, allowPax bool, paxKeyword string, paxHeaders map[string]string) {
+	needsPaxHeader := allowPax && len(s) > len(b) || !isASCII(s)
+	if needsPaxHeader {
+		paxHeaders[paxKeyword] = s
+		return
+	}
+	if len(s) > len(b) {
+		if tw.err == nil {
+			tw.err = ErrFieldTooLong
+		}
+		return
+	}
+	ascii := toASCII(s)
+	copy(b, ascii)
+	if len(ascii) < len(b) {
+		b[len(ascii)] = 0
+	}
+}
+
+// Encode x as an octal ASCII string and write it into b with leading zeros.
+func (tw *Writer) octal(b []byte, x int64) {
+	s := strconv.FormatInt(x, 8)
+	// leading zeros, but leave room for a NUL.
+	for len(s)+1 < len(b) {
+		s = "0" + s
+	}
+	tw.cString(b, s, false, paxNone, nil)
+}
+
+// Write x into b, either as octal or as binary (GNUtar/star extension).
+// If the value is too long for the field and writingPax is enabled both for the field and the add a paxheader record instead
+func (tw *Writer) numeric(b []byte, x int64, allowPax bool, paxKeyword string, paxHeaders map[string]string) {
+	// Try octal first.
+	s := strconv.FormatInt(x, 8)
+	if len(s) < len(b) {
+		tw.octal(b, x)
+		return
+	}
+
+	// If it is too long for octal, and pax is preferred, use a pax header
+	if allowPax && tw.preferPax {
+		tw.octal(b, 0)
+		s := strconv.FormatInt(x, 10)
+		paxHeaders[paxKeyword] = s
+		return
+	}
+
+	// Too big: use binary (big-endian).
+	tw.usedBinary = true
+	for i := len(b) - 1; x > 0 && i >= 0; i-- {
+		b[i] = byte(x)
+		x >>= 8
+	}
+	b[0] |= 0x80 // highest bit indicates binary format
+}
+
+var (
+	minTime = time.Unix(0, 0)
+	// There is room for 11 octal digits (33 bits) of mtime.
+	maxTime = minTime.Add((1<<33 - 1) * time.Second)
+)
+
+// WriteHeader writes hdr and prepares to accept the file's contents.
+// WriteHeader calls Flush if it is not the first header.
+// Calling after a Close will return ErrWriteAfterClose.
+func (tw *Writer) WriteHeader(hdr *Header) error {
+	return tw.writeHeader(hdr, true)
+}
+
+// WriteHeader writes hdr and prepares to accept the file's contents.
+// WriteHeader calls Flush if it is not the first header.
+// Calling after a Close will return ErrWriteAfterClose.
+// As this method is called internally by writePax header to allow it to
+// suppress writing the pax header.
+func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
+	if tw.closed {
+		return ErrWriteAfterClose
+	}
+	if tw.err == nil {
+		tw.Flush()
+	}
+	if tw.err != nil {
+		return tw.err
+	}
+
+	// a map to hold pax header records, if any are needed
+	paxHeaders := make(map[string]string)
+
+	// TODO(shanemhansen): we might want to use PAX headers for
+	// subsecond time resolution, but for now let's just capture
+	// too long fields or non ascii characters
+
+	header := make([]byte, blockSize)
+	s := slicer(header)
+
+	// keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
+	pathHeaderBytes := s.next(fileNameSize)
+
+	tw.cString(pathHeaderBytes, hdr.Name, true, paxPath, paxHeaders)
+
+	// Handle out of range ModTime carefully.
+	var modTime int64
+	if !hdr.ModTime.Before(minTime) && !hdr.ModTime.After(maxTime) {
+		modTime = hdr.ModTime.Unix()
+	}
+
+	tw.octal(s.next(8), hdr.Mode)                                   // 100:108
+	tw.numeric(s.next(8), int64(hdr.Uid), true, paxUid, paxHeaders) // 108:116
+	tw.numeric(s.next(8), int64(hdr.Gid), true, paxGid, paxHeaders) // 116:124
+	tw.numeric(s.next(12), hdr.Size, true, paxSize, paxHeaders)     // 124:136
+	tw.numeric(s.next(12), modTime, false, paxNone, nil)            // 136:148 --- consider using pax for finer granularity
+	s.next(8)                                                       // chksum (148:156)
+	s.next(1)[0] = hdr.Typeflag                                     // 156:157
+
+	tw.cString(s.next(100), hdr.Linkname, true, paxLinkpath, paxHeaders)
+
+	copy(s.next(8), []byte("ustar\x0000"))                        // 257:265
+	tw.cString(s.next(32), hdr.Uname, true, paxUname, paxHeaders) // 265:297
+	tw.cString(s.next(32), hdr.Gname, true, paxGname, paxHeaders) // 297:329
+	tw.numeric(s.next(8), hdr.Devmajor, false, paxNone, nil)      // 329:337
+	tw.numeric(s.next(8), hdr.Devminor, false, paxNone, nil)      // 337:345
+
+	// keep a reference to the prefix to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
+	prefixHeaderBytes := s.next(155)
+	tw.cString(prefixHeaderBytes, "", false, paxNone, nil) // 345:500  prefix
+
+	// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
+	if tw.usedBinary {
+		copy(header[257:265], []byte("ustar  \x00"))
+	}
+
+	_, paxPathUsed := paxHeaders[paxPath]
+	// try to use a ustar header when only the name is too long
+	if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
+		suffix := hdr.Name
+		prefix := ""
+		if len(hdr.Name) > fileNameSize && isASCII(hdr.Name) {
+			var err error
+			prefix, suffix, err = tw.splitUSTARLongName(hdr.Name)
+			if err == nil {
+				// ok we can use a ustar long name instead of pax, now correct the fields
+
+				// remove the path field from the pax header. this will suppress the pax header
+				delete(paxHeaders, paxPath)
+
+				// update the path fields
+				tw.cString(pathHeaderBytes, suffix, false, paxNone, nil)
+				tw.cString(prefixHeaderBytes, prefix, false, paxNone, nil)
+
+				// Use the ustar magic if we used ustar long names.
+				if len(prefix) > 0 && !tw.usedBinary {
+					copy(header[257:265], []byte("ustar\x00"))
+				}
+			}
+		}
+	}
+
+	// The chksum field is terminated by a NUL and a space.
+	// This is different from the other octal fields.
+	chksum, _ := checksum(header)
+	tw.octal(header[148:155], chksum)
+	header[155] = ' '
+
+	if tw.err != nil {
+		// problem with header; probably integer too big for a field.
+		return tw.err
+	}
+
+	if allowPax {
+		for k, v := range hdr.Xattrs {
+			paxHeaders[paxXattr+k] = v
+		}
+	}
+
+	if len(paxHeaders) > 0 {
+		if !allowPax {
+			return errInvalidHeader
+		}
+		if err := tw.writePAXHeader(hdr, paxHeaders); err != nil {
+			return err
+		}
+	}
+	tw.nb = int64(hdr.Size)
+	tw.pad = (blockSize - (tw.nb % blockSize)) % blockSize
+
+	_, tw.err = tw.w.Write(header)
+	return tw.err
+}
+
+// writeUSTARLongName splits a USTAR long name hdr.Name.
+// name must be < 256 characters. errNameTooLong is returned
+// if hdr.Name can't be split. The splitting heuristic
+// is compatible with gnu tar.
+func (tw *Writer) splitUSTARLongName(name string) (prefix, suffix string, err error) {
+	length := len(name)
+	if length > fileNamePrefixSize+1 {
+		length = fileNamePrefixSize + 1
+	} else if name[length-1] == '/' {
+		length--
+	}
+	i := strings.LastIndex(name[:length], "/")
+	// nlen contains the resulting length in the name field.
+	// plen contains the resulting length in the prefix field.
+	nlen := len(name) - i - 1
+	plen := i
+	if i <= 0 || nlen > fileNameSize || nlen == 0 || plen > fileNamePrefixSize {
+		err = errNameTooLong
+		return
+	}
+	prefix, suffix = name[:i], name[i+1:]
+	return
+}
+
+// writePaxHeader writes an extended pax header to the
+// archive.
+func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) error {
+	// Prepare extended header
+	ext := new(Header)
+	ext.Typeflag = TypeXHeader
+	// Setting ModTime is required for reader parsing to
+	// succeed, and seems harmless enough.
+	ext.ModTime = hdr.ModTime
+	// The spec asks that we namespace our pseudo files
+	// with the current pid.
+	pid := os.Getpid()
+	dir, file := path.Split(hdr.Name)
+	fullName := path.Join(dir,
+		fmt.Sprintf("PaxHeaders.%d", pid), file)
+
+	ascii := toASCII(fullName)
+	if len(ascii) > 100 {
+		ascii = ascii[:100]
+	}
+	ext.Name = ascii
+	// Construct the body
+	var buf bytes.Buffer
+
+	for k, v := range paxHeaders {
+		fmt.Fprint(&buf, paxHeader(k+"="+v))
+	}
+
+	ext.Size = int64(len(buf.Bytes()))
+	if err := tw.writeHeader(ext, false); err != nil {
+		return err
+	}
+	if _, err := tw.Write(buf.Bytes()); err != nil {
+		return err
+	}
+	if err := tw.Flush(); err != nil {
+		return err
+	}
+	return nil
+}
+
+// paxHeader formats a single pax record, prefixing it with the appropriate length
+func paxHeader(msg string) string {
+	const padding = 2 // Extra padding for space and newline
+	size := len(msg) + padding
+	size += len(strconv.Itoa(size))
+	record := fmt.Sprintf("%d %s\n", size, msg)
+	if len(record) != size {
+		// Final adjustment if adding size increased
+		// the number of digits in size
+		size = len(record)
+		record = fmt.Sprintf("%d %s\n", size, msg)
+	}
+	return record
+}
+
+// Write writes to the current entry in the tar archive.
+// Write returns the error ErrWriteTooLong if more than
+// hdr.Size bytes are written after WriteHeader.
+func (tw *Writer) Write(b []byte) (n int, err error) {
+	if tw.closed {
+		err = ErrWriteTooLong
+		return
+	}
+	overwrite := false
+	if int64(len(b)) > tw.nb {
+		b = b[0:tw.nb]
+		overwrite = true
+	}
+	n, err = tw.w.Write(b)
+	tw.nb -= int64(n)
+	if err == nil && overwrite {
+		err = ErrWriteTooLong
+		return
+	}
+	tw.err = err
+	return
+}
+
+// Close closes the tar archive, flushing any unwritten
+// data to the underlying writer.
+func (tw *Writer) Close() error {
+	if tw.err != nil || tw.closed {
+		return tw.err
+	}
+	tw.Flush()
+	tw.closed = true
+	if tw.err != nil {
+		return tw.err
+	}
+
+	// trailer: two zero blocks
+	for i := 0; i < 2; i++ {
+		_, tw.err = tw.w.Write(zeroBlock)
+		if tw.err != nil {
+			break
+		}
+	}
+	return tw.err
+}
diff --git a/third_party/gofrontend/libgo/go/archive/tar/writer_test.go b/third_party/gofrontend/libgo/go/archive/tar/writer_test.go
new file mode 100644
index 0000000..512fab1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/tar/writer_test.go
@@ -0,0 +1,456 @@
+// 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 tar
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"reflect"
+	"strings"
+	"testing"
+	"testing/iotest"
+	"time"
+)
+
+type writerTestEntry struct {
+	header   *Header
+	contents string
+}
+
+type writerTest struct {
+	file    string // filename of expected output
+	entries []*writerTestEntry
+}
+
+var writerTests = []*writerTest{
+	// The writer test file was produced with this command:
+	// tar (GNU tar) 1.26
+	//   ln -s small.txt link.txt
+	//   tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
+	{
+		file: "testdata/writer.tar",
+		entries: []*writerTestEntry{
+			{
+				header: &Header{
+					Name:     "small.txt",
+					Mode:     0640,
+					Uid:      73025,
+					Gid:      5000,
+					Size:     5,
+					ModTime:  time.Unix(1246508266, 0),
+					Typeflag: '0',
+					Uname:    "dsymonds",
+					Gname:    "eng",
+				},
+				contents: "Kilts",
+			},
+			{
+				header: &Header{
+					Name:     "small2.txt",
+					Mode:     0640,
+					Uid:      73025,
+					Gid:      5000,
+					Size:     11,
+					ModTime:  time.Unix(1245217492, 0),
+					Typeflag: '0',
+					Uname:    "dsymonds",
+					Gname:    "eng",
+				},
+				contents: "Google.com\n",
+			},
+			{
+				header: &Header{
+					Name:     "link.txt",
+					Mode:     0777,
+					Uid:      1000,
+					Gid:      1000,
+					Size:     0,
+					ModTime:  time.Unix(1314603082, 0),
+					Typeflag: '2',
+					Linkname: "small.txt",
+					Uname:    "strings",
+					Gname:    "strings",
+				},
+				// no contents
+			},
+		},
+	},
+	// The truncated test file was produced using these commands:
+	//   dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
+	//   tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
+	{
+		file: "testdata/writer-big.tar",
+		entries: []*writerTestEntry{
+			{
+				header: &Header{
+					Name:     "tmp/16gig.txt",
+					Mode:     0640,
+					Uid:      73025,
+					Gid:      5000,
+					Size:     16 << 30,
+					ModTime:  time.Unix(1254699560, 0),
+					Typeflag: '0',
+					Uname:    "dsymonds",
+					Gname:    "eng",
+				},
+				// fake contents
+				contents: strings.Repeat("\x00", 4<<10),
+			},
+		},
+	},
+	// The truncated test file was produced using these commands:
+	//   dd if=/dev/zero bs=1048576 count=16384 > (longname/)*15 /16gig.txt
+	//   tar -b 1 -c -f- (longname/)*15 /16gig.txt | dd bs=512 count=8 > writer-big-long.tar
+	{
+		file: "testdata/writer-big-long.tar",
+		entries: []*writerTestEntry{
+			{
+				header: &Header{
+					Name:     strings.Repeat("longname/", 15) + "16gig.txt",
+					Mode:     0644,
+					Uid:      1000,
+					Gid:      1000,
+					Size:     16 << 30,
+					ModTime:  time.Unix(1399583047, 0),
+					Typeflag: '0',
+					Uname:    "guillaume",
+					Gname:    "guillaume",
+				},
+				// fake contents
+				contents: strings.Repeat("\x00", 4<<10),
+			},
+		},
+	},
+	// This file was produced using gnu tar 1.17
+	// gnutar  -b 4 --format=ustar (longname/)*15 + file.txt
+	{
+		file: "testdata/ustar.tar",
+		entries: []*writerTestEntry{
+			{
+				header: &Header{
+					Name:     strings.Repeat("longname/", 15) + "file.txt",
+					Mode:     0644,
+					Uid:      0765,
+					Gid:      024,
+					Size:     06,
+					ModTime:  time.Unix(1360135598, 0),
+					Typeflag: '0',
+					Uname:    "shane",
+					Gname:    "staff",
+				},
+				contents: "hello\n",
+			},
+		},
+	},
+}
+
+// Render byte array in a two-character hexadecimal string, spaced for easy visual inspection.
+func bytestr(offset int, b []byte) string {
+	const rowLen = 32
+	s := fmt.Sprintf("%04x ", offset)
+	for _, ch := range b {
+		switch {
+		case '0' <= ch && ch <= '9', 'A' <= ch && ch <= 'Z', 'a' <= ch && ch <= 'z':
+			s += fmt.Sprintf("  %c", ch)
+		default:
+			s += fmt.Sprintf(" %02x", ch)
+		}
+	}
+	return s
+}
+
+// Render a pseudo-diff between two blocks of bytes.
+func bytediff(a []byte, b []byte) string {
+	const rowLen = 32
+	s := fmt.Sprintf("(%d bytes vs. %d bytes)\n", len(a), len(b))
+	for offset := 0; len(a)+len(b) > 0; offset += rowLen {
+		na, nb := rowLen, rowLen
+		if na > len(a) {
+			na = len(a)
+		}
+		if nb > len(b) {
+			nb = len(b)
+		}
+		sa := bytestr(offset, a[0:na])
+		sb := bytestr(offset, b[0:nb])
+		if sa != sb {
+			s += fmt.Sprintf("-%v\n+%v\n", sa, sb)
+		}
+		a = a[na:]
+		b = b[nb:]
+	}
+	return s
+}
+
+func TestWriter(t *testing.T) {
+testLoop:
+	for i, test := range writerTests {
+		expected, err := ioutil.ReadFile(test.file)
+		if err != nil {
+			t.Errorf("test %d: Unexpected error: %v", i, err)
+			continue
+		}
+
+		buf := new(bytes.Buffer)
+		tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB
+		big := false
+		for j, entry := range test.entries {
+			big = big || entry.header.Size > 1<<10
+			if err := tw.WriteHeader(entry.header); err != nil {
+				t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err)
+				continue testLoop
+			}
+			if _, err := io.WriteString(tw, entry.contents); err != nil {
+				t.Errorf("test %d, entry %d: Failed writing contents: %v", i, j, err)
+				continue testLoop
+			}
+		}
+		// Only interested in Close failures for the small tests.
+		if err := tw.Close(); err != nil && !big {
+			t.Errorf("test %d: Failed closing archive: %v", i, err)
+			continue testLoop
+		}
+
+		actual := buf.Bytes()
+		if !bytes.Equal(expected, actual) {
+			t.Errorf("test %d: Incorrect result: (-=expected, +=actual)\n%v",
+				i, bytediff(expected, actual))
+		}
+		if testing.Short() { // The second test is expensive.
+			break
+		}
+	}
+}
+
+func TestPax(t *testing.T) {
+	// Create an archive with a large name
+	fileinfo, err := os.Stat("testdata/small.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	hdr, err := FileInfoHeader(fileinfo, "")
+	if err != nil {
+		t.Fatalf("os.Stat: %v", err)
+	}
+	// Force a PAX long name to be written
+	longName := strings.Repeat("ab", 100)
+	contents := strings.Repeat(" ", int(hdr.Size))
+	hdr.Name = longName
+	var buf bytes.Buffer
+	writer := NewWriter(&buf)
+	if err := writer.WriteHeader(hdr); err != nil {
+		t.Fatal(err)
+	}
+	if _, err = writer.Write([]byte(contents)); err != nil {
+		t.Fatal(err)
+	}
+	if err := writer.Close(); err != nil {
+		t.Fatal(err)
+	}
+	// Simple test to make sure PAX extensions are in effect
+	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+		t.Fatal("Expected at least one PAX header to be written.")
+	}
+	// Test that we can get a long name back out of the archive.
+	reader := NewReader(&buf)
+	hdr, err = reader.Next()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if hdr.Name != longName {
+		t.Fatal("Couldn't recover long file name")
+	}
+}
+
+func TestPaxSymlink(t *testing.T) {
+	// Create an archive with a large linkname
+	fileinfo, err := os.Stat("testdata/small.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	hdr, err := FileInfoHeader(fileinfo, "")
+	hdr.Typeflag = TypeSymlink
+	if err != nil {
+		t.Fatalf("os.Stat:1 %v", err)
+	}
+	// Force a PAX long linkname to be written
+	longLinkname := strings.Repeat("1234567890/1234567890", 10)
+	hdr.Linkname = longLinkname
+
+	hdr.Size = 0
+	var buf bytes.Buffer
+	writer := NewWriter(&buf)
+	if err := writer.WriteHeader(hdr); err != nil {
+		t.Fatal(err)
+	}
+	if err := writer.Close(); err != nil {
+		t.Fatal(err)
+	}
+	// Simple test to make sure PAX extensions are in effect
+	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+		t.Fatal("Expected at least one PAX header to be written.")
+	}
+	// Test that we can get a long name back out of the archive.
+	reader := NewReader(&buf)
+	hdr, err = reader.Next()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if hdr.Linkname != longLinkname {
+		t.Fatal("Couldn't recover long link name")
+	}
+}
+
+func TestPaxNonAscii(t *testing.T) {
+	// Create an archive with non ascii. These should trigger a pax header
+	// because pax headers have a defined utf-8 encoding.
+	fileinfo, err := os.Stat("testdata/small.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	hdr, err := FileInfoHeader(fileinfo, "")
+	if err != nil {
+		t.Fatalf("os.Stat:1 %v", err)
+	}
+
+	// some sample data
+	chineseFilename := "文件名"
+	chineseGroupname := "組"
+	chineseUsername := "用戶名"
+
+	hdr.Name = chineseFilename
+	hdr.Gname = chineseGroupname
+	hdr.Uname = chineseUsername
+
+	contents := strings.Repeat(" ", int(hdr.Size))
+
+	var buf bytes.Buffer
+	writer := NewWriter(&buf)
+	if err := writer.WriteHeader(hdr); err != nil {
+		t.Fatal(err)
+	}
+	if _, err = writer.Write([]byte(contents)); err != nil {
+		t.Fatal(err)
+	}
+	if err := writer.Close(); err != nil {
+		t.Fatal(err)
+	}
+	// Simple test to make sure PAX extensions are in effect
+	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+		t.Fatal("Expected at least one PAX header to be written.")
+	}
+	// Test that we can get a long name back out of the archive.
+	reader := NewReader(&buf)
+	hdr, err = reader.Next()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if hdr.Name != chineseFilename {
+		t.Fatal("Couldn't recover unicode name")
+	}
+	if hdr.Gname != chineseGroupname {
+		t.Fatal("Couldn't recover unicode group")
+	}
+	if hdr.Uname != chineseUsername {
+		t.Fatal("Couldn't recover unicode user")
+	}
+}
+
+func TestPaxXattrs(t *testing.T) {
+	xattrs := map[string]string{
+		"user.key": "value",
+	}
+
+	// Create an archive with an xattr
+	fileinfo, err := os.Stat("testdata/small.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	hdr, err := FileInfoHeader(fileinfo, "")
+	if err != nil {
+		t.Fatalf("os.Stat: %v", err)
+	}
+	contents := "Kilts"
+	hdr.Xattrs = xattrs
+	var buf bytes.Buffer
+	writer := NewWriter(&buf)
+	if err := writer.WriteHeader(hdr); err != nil {
+		t.Fatal(err)
+	}
+	if _, err = writer.Write([]byte(contents)); err != nil {
+		t.Fatal(err)
+	}
+	if err := writer.Close(); err != nil {
+		t.Fatal(err)
+	}
+	// Test that we can get the xattrs back out of the archive.
+	reader := NewReader(&buf)
+	hdr, err = reader.Next()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !reflect.DeepEqual(hdr.Xattrs, xattrs) {
+		t.Fatalf("xattrs did not survive round trip: got %+v, want %+v",
+			hdr.Xattrs, xattrs)
+	}
+}
+
+func TestPAXHeader(t *testing.T) {
+	medName := strings.Repeat("CD", 50)
+	longName := strings.Repeat("AB", 100)
+	paxTests := [][2]string{
+		{paxPath + "=/etc/hosts", "19 path=/etc/hosts\n"},
+		{"a=b", "6 a=b\n"},          // Single digit length
+		{"a=names", "11 a=names\n"}, // Test case involving carries
+		{paxPath + "=" + longName, fmt.Sprintf("210 path=%s\n", longName)},
+		{paxPath + "=" + medName, fmt.Sprintf("110 path=%s\n", medName)}}
+
+	for _, test := range paxTests {
+		key, expected := test[0], test[1]
+		if result := paxHeader(key); result != expected {
+			t.Fatalf("paxHeader: got %s, expected %s", result, expected)
+		}
+	}
+}
+
+func TestUSTARLongName(t *testing.T) {
+	// Create an archive with a path that failed to split with USTAR extension in previous versions.
+	fileinfo, err := os.Stat("testdata/small.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	hdr, err := FileInfoHeader(fileinfo, "")
+	hdr.Typeflag = TypeDir
+	if err != nil {
+		t.Fatalf("os.Stat:1 %v", err)
+	}
+	// Force a PAX long name to be written. The name was taken from a practical example
+	// that fails and replaced ever char through numbers to anonymize the sample.
+	longName := "/0000_0000000/00000-000000000/0000_0000000/00000-0000000000000/0000_0000000/00000-0000000-00000000/0000_0000000/00000000/0000_0000000/000/0000_0000000/00000000v00/0000_0000000/000000/0000_0000000/0000000/0000_0000000/00000y-00/0000/0000/00000000/0x000000/"
+	hdr.Name = longName
+
+	hdr.Size = 0
+	var buf bytes.Buffer
+	writer := NewWriter(&buf)
+	if err := writer.WriteHeader(hdr); err != nil {
+		t.Fatal(err)
+	}
+	if err := writer.Close(); err != nil {
+		t.Fatal(err)
+	}
+	// Test that we can get a long name back out of the archive.
+	reader := NewReader(&buf)
+	hdr, err = reader.Next()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if hdr.Name != longName {
+		t.Fatal("Couldn't recover long name")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/archive/zip/reader.go b/third_party/gofrontend/libgo/go/archive/zip/reader.go
new file mode 100644
index 0000000..80ee030
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/reader.go
@@ -0,0 +1,448 @@
+// Copyright 2010 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 zip
+
+import (
+	"bufio"
+	"encoding/binary"
+	"errors"
+	"hash"
+	"hash/crc32"
+	"io"
+	"os"
+)
+
+var (
+	ErrFormat    = errors.New("zip: not a valid zip file")
+	ErrAlgorithm = errors.New("zip: unsupported compression algorithm")
+	ErrChecksum  = errors.New("zip: checksum error")
+)
+
+type Reader struct {
+	r       io.ReaderAt
+	File    []*File
+	Comment string
+}
+
+type ReadCloser struct {
+	f *os.File
+	Reader
+}
+
+type File struct {
+	FileHeader
+	zipr         io.ReaderAt
+	zipsize      int64
+	headerOffset int64
+}
+
+func (f *File) hasDataDescriptor() bool {
+	return f.Flags&0x8 != 0
+}
+
+// OpenReader will open the Zip file specified by name and return a ReadCloser.
+func OpenReader(name string) (*ReadCloser, error) {
+	f, err := os.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	fi, err := f.Stat()
+	if err != nil {
+		f.Close()
+		return nil, err
+	}
+	r := new(ReadCloser)
+	if err := r.init(f, fi.Size()); err != nil {
+		f.Close()
+		return nil, err
+	}
+	r.f = f
+	return r, nil
+}
+
+// NewReader returns a new Reader reading from r, which is assumed to
+// have the given size in bytes.
+func NewReader(r io.ReaderAt, size int64) (*Reader, error) {
+	zr := new(Reader)
+	if err := zr.init(r, size); err != nil {
+		return nil, err
+	}
+	return zr, nil
+}
+
+func (z *Reader) init(r io.ReaderAt, size int64) error {
+	end, err := readDirectoryEnd(r, size)
+	if err != nil {
+		return err
+	}
+	z.r = r
+	z.File = make([]*File, 0, end.directoryRecords)
+	z.Comment = end.comment
+	rs := io.NewSectionReader(r, 0, size)
+	if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil {
+		return err
+	}
+	buf := bufio.NewReader(rs)
+
+	// The count of files inside a zip is truncated to fit in a uint16.
+	// Gloss over this by reading headers until we encounter
+	// a bad one, and then only report a ErrFormat or UnexpectedEOF if
+	// the file count modulo 65536 is incorrect.
+	for {
+		f := &File{zipr: r, zipsize: size}
+		err = readDirectoryHeader(f, buf)
+		if err == ErrFormat || err == io.ErrUnexpectedEOF {
+			break
+		}
+		if err != nil {
+			return err
+		}
+		z.File = append(z.File, f)
+	}
+	if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here
+		// Return the readDirectoryHeader error if we read
+		// the wrong number of directory entries.
+		return err
+	}
+	return nil
+}
+
+// Close closes the Zip file, rendering it unusable for I/O.
+func (rc *ReadCloser) Close() error {
+	return rc.f.Close()
+}
+
+// DataOffset returns the offset of the file's possibly-compressed
+// data, relative to the beginning of the zip file.
+//
+// Most callers should instead use Open, which transparently
+// decompresses data and verifies checksums.
+func (f *File) DataOffset() (offset int64, err error) {
+	bodyOffset, err := f.findBodyOffset()
+	if err != nil {
+		return
+	}
+	return f.headerOffset + bodyOffset, nil
+}
+
+// Open returns a ReadCloser that provides access to the File's contents.
+// Multiple files may be read concurrently.
+func (f *File) Open() (rc io.ReadCloser, err error) {
+	bodyOffset, err := f.findBodyOffset()
+	if err != nil {
+		return
+	}
+	size := int64(f.CompressedSize64)
+	r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size)
+	dcomp := decompressor(f.Method)
+	if dcomp == nil {
+		err = ErrAlgorithm
+		return
+	}
+	rc = dcomp(r)
+	var desr io.Reader
+	if f.hasDataDescriptor() {
+		desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
+	}
+	rc = &checksumReader{rc, crc32.NewIEEE(), f, desr, nil}
+	return
+}
+
+type checksumReader struct {
+	rc   io.ReadCloser
+	hash hash.Hash32
+	f    *File
+	desr io.Reader // if non-nil, where to read the data descriptor
+	err  error     // sticky error
+}
+
+func (r *checksumReader) Read(b []byte) (n int, err error) {
+	if r.err != nil {
+		return 0, r.err
+	}
+	n, err = r.rc.Read(b)
+	r.hash.Write(b[:n])
+	if err == nil {
+		return
+	}
+	if err == io.EOF {
+		if r.desr != nil {
+			if err1 := readDataDescriptor(r.desr, r.f); err1 != nil {
+				err = err1
+			} else if r.hash.Sum32() != r.f.CRC32 {
+				err = ErrChecksum
+			}
+		} else {
+			// If there's not a data descriptor, we still compare
+			// the CRC32 of what we've read against the file header
+			// or TOC's CRC32, if it seems like it was set.
+			if r.f.CRC32 != 0 && r.hash.Sum32() != r.f.CRC32 {
+				err = ErrChecksum
+			}
+		}
+	}
+	r.err = err
+	return
+}
+
+func (r *checksumReader) Close() error { return r.rc.Close() }
+
+// findBodyOffset does the minimum work to verify the file has a header
+// and returns the file body offset.
+func (f *File) findBodyOffset() (int64, error) {
+	var buf [fileHeaderLen]byte
+	if _, err := f.zipr.ReadAt(buf[:], f.headerOffset); err != nil {
+		return 0, err
+	}
+	b := readBuf(buf[:])
+	if sig := b.uint32(); sig != fileHeaderSignature {
+		return 0, ErrFormat
+	}
+	b = b[22:] // skip over most of the header
+	filenameLen := int(b.uint16())
+	extraLen := int(b.uint16())
+	return int64(fileHeaderLen + filenameLen + extraLen), nil
+}
+
+// readDirectoryHeader attempts to read a directory header from r.
+// It returns io.ErrUnexpectedEOF if it cannot read a complete header,
+// and ErrFormat if it doesn't find a valid header signature.
+func readDirectoryHeader(f *File, r io.Reader) error {
+	var buf [directoryHeaderLen]byte
+	if _, err := io.ReadFull(r, buf[:]); err != nil {
+		return err
+	}
+	b := readBuf(buf[:])
+	if sig := b.uint32(); sig != directoryHeaderSignature {
+		return ErrFormat
+	}
+	f.CreatorVersion = b.uint16()
+	f.ReaderVersion = b.uint16()
+	f.Flags = b.uint16()
+	f.Method = b.uint16()
+	f.ModifiedTime = b.uint16()
+	f.ModifiedDate = b.uint16()
+	f.CRC32 = b.uint32()
+	f.CompressedSize = b.uint32()
+	f.UncompressedSize = b.uint32()
+	f.CompressedSize64 = uint64(f.CompressedSize)
+	f.UncompressedSize64 = uint64(f.UncompressedSize)
+	filenameLen := int(b.uint16())
+	extraLen := int(b.uint16())
+	commentLen := int(b.uint16())
+	b = b[4:] // skipped start disk number and internal attributes (2x uint16)
+	f.ExternalAttrs = b.uint32()
+	f.headerOffset = int64(b.uint32())
+	d := make([]byte, filenameLen+extraLen+commentLen)
+	if _, err := io.ReadFull(r, d); err != nil {
+		return err
+	}
+	f.Name = string(d[:filenameLen])
+	f.Extra = d[filenameLen : filenameLen+extraLen]
+	f.Comment = string(d[filenameLen+extraLen:])
+
+	if len(f.Extra) > 0 {
+		b := readBuf(f.Extra)
+		for len(b) >= 4 { // need at least tag and size
+			tag := b.uint16()
+			size := b.uint16()
+			if int(size) > len(b) {
+				return ErrFormat
+			}
+			if tag == zip64ExtraId {
+				// update directory values from the zip64 extra block
+				eb := readBuf(b[:size])
+				if len(eb) >= 8 {
+					f.UncompressedSize64 = eb.uint64()
+				}
+				if len(eb) >= 8 {
+					f.CompressedSize64 = eb.uint64()
+				}
+				if len(eb) >= 8 {
+					f.headerOffset = int64(eb.uint64())
+				}
+			}
+			b = b[size:]
+		}
+		// Should have consumed the whole header.
+		if len(b) != 0 {
+			return ErrFormat
+		}
+	}
+	return nil
+}
+
+func readDataDescriptor(r io.Reader, f *File) error {
+	var buf [dataDescriptorLen]byte
+
+	// The spec says: "Although not originally assigned a
+	// signature, the value 0x08074b50 has commonly been adopted
+	// as a signature value for the data descriptor record.
+	// Implementers should be aware that ZIP files may be
+	// encountered with or without this signature marking data
+	// descriptors and should account for either case when reading
+	// ZIP files to ensure compatibility."
+	//
+	// dataDescriptorLen includes the size of the signature but
+	// first read just those 4 bytes to see if it exists.
+	if _, err := io.ReadFull(r, buf[:4]); err != nil {
+		return err
+	}
+	off := 0
+	maybeSig := readBuf(buf[:4])
+	if maybeSig.uint32() != dataDescriptorSignature {
+		// No data descriptor signature. Keep these four
+		// bytes.
+		off += 4
+	}
+	if _, err := io.ReadFull(r, buf[off:12]); err != nil {
+		return err
+	}
+	b := readBuf(buf[:12])
+	if b.uint32() != f.CRC32 {
+		return ErrChecksum
+	}
+
+	// The two sizes that follow here can be either 32 bits or 64 bits
+	// but the spec is not very clear on this and different
+	// interpretations has been made causing incompatibilities. We
+	// already have the sizes from the central directory so we can
+	// just ignore these.
+
+	return nil
+}
+
+func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) {
+	// look for directoryEndSignature in the last 1k, then in the last 65k
+	var buf []byte
+	var directoryEndOffset int64
+	for i, bLen := range []int64{1024, 65 * 1024} {
+		if bLen > size {
+			bLen = size
+		}
+		buf = make([]byte, int(bLen))
+		if _, err := r.ReadAt(buf, size-bLen); err != nil && err != io.EOF {
+			return nil, err
+		}
+		if p := findSignatureInBlock(buf); p >= 0 {
+			buf = buf[p:]
+			directoryEndOffset = size - bLen + int64(p)
+			break
+		}
+		if i == 1 || bLen == size {
+			return nil, ErrFormat
+		}
+	}
+
+	// read header into struct
+	b := readBuf(buf[4:]) // skip signature
+	d := &directoryEnd{
+		diskNbr:            uint32(b.uint16()),
+		dirDiskNbr:         uint32(b.uint16()),
+		dirRecordsThisDisk: uint64(b.uint16()),
+		directoryRecords:   uint64(b.uint16()),
+		directorySize:      uint64(b.uint32()),
+		directoryOffset:    uint64(b.uint32()),
+		commentLen:         b.uint16(),
+	}
+	l := int(d.commentLen)
+	if l > len(b) {
+		return nil, errors.New("zip: invalid comment length")
+	}
+	d.comment = string(b[:l])
+
+	p, err := findDirectory64End(r, directoryEndOffset)
+	if err == nil && p >= 0 {
+		err = readDirectory64End(r, p, d)
+	}
+	if err != nil {
+		return nil, err
+	}
+
+	// Make sure directoryOffset points to somewhere in our file.
+	if o := int64(d.directoryOffset); o < 0 || o >= size {
+		return nil, ErrFormat
+	}
+	return d, nil
+}
+
+// findDirectory64End tries to read the zip64 locator just before the
+// directory end and returns the offset of the zip64 directory end if
+// found.
+func findDirectory64End(r io.ReaderAt, directoryEndOffset int64) (int64, error) {
+	locOffset := directoryEndOffset - directory64LocLen
+	if locOffset < 0 {
+		return -1, nil // no need to look for a header outside the file
+	}
+	buf := make([]byte, directory64LocLen)
+	if _, err := r.ReadAt(buf, locOffset); err != nil {
+		return -1, err
+	}
+	b := readBuf(buf)
+	if sig := b.uint32(); sig != directory64LocSignature {
+		return -1, nil
+	}
+	b = b[4:]       // skip number of the disk with the start of the zip64 end of central directory
+	p := b.uint64() // relative offset of the zip64 end of central directory record
+	return int64(p), nil
+}
+
+// readDirectory64End reads the zip64 directory end and updates the
+// directory end with the zip64 directory end values.
+func readDirectory64End(r io.ReaderAt, offset int64, d *directoryEnd) (err error) {
+	buf := make([]byte, directory64EndLen)
+	if _, err := r.ReadAt(buf, offset); err != nil {
+		return err
+	}
+
+	b := readBuf(buf)
+	if sig := b.uint32(); sig != directory64EndSignature {
+		return ErrFormat
+	}
+
+	b = b[12:]                        // skip dir size, version and version needed (uint64 + 2x uint16)
+	d.diskNbr = b.uint32()            // number of this disk
+	d.dirDiskNbr = b.uint32()         // number of the disk with the start of the central directory
+	d.dirRecordsThisDisk = b.uint64() // total number of entries in the central directory on this disk
+	d.directoryRecords = b.uint64()   // total number of entries in the central directory
+	d.directorySize = b.uint64()      // size of the central directory
+	d.directoryOffset = b.uint64()    // offset of start of central directory with respect to the starting disk number
+
+	return nil
+}
+
+func findSignatureInBlock(b []byte) int {
+	for i := len(b) - directoryEndLen; i >= 0; i-- {
+		// defined from directoryEndSignature in struct.go
+		if b[i] == 'P' && b[i+1] == 'K' && b[i+2] == 0x05 && b[i+3] == 0x06 {
+			// n is length of comment
+			n := int(b[i+directoryEndLen-2]) | int(b[i+directoryEndLen-1])<<8
+			if n+directoryEndLen+i <= len(b) {
+				return i
+			}
+		}
+	}
+	return -1
+}
+
+type readBuf []byte
+
+func (b *readBuf) uint16() uint16 {
+	v := binary.LittleEndian.Uint16(*b)
+	*b = (*b)[2:]
+	return v
+}
+
+func (b *readBuf) uint32() uint32 {
+	v := binary.LittleEndian.Uint32(*b)
+	*b = (*b)[4:]
+	return v
+}
+
+func (b *readBuf) uint64() uint64 {
+	v := binary.LittleEndian.Uint64(*b)
+	*b = (*b)[8:]
+	return v
+}
diff --git a/third_party/gofrontend/libgo/go/archive/zip/reader_test.go b/third_party/gofrontend/libgo/go/archive/zip/reader_test.go
new file mode 100644
index 0000000..5652f3a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/reader_test.go
@@ -0,0 +1,510 @@
+// Copyright 2010 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 zip
+
+import (
+	"bytes"
+	"encoding/binary"
+	"encoding/hex"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"regexp"
+	"testing"
+	"time"
+)
+
+type ZipTest struct {
+	Name    string
+	Source  func() (r io.ReaderAt, size int64) // if non-nil, used instead of testdata/<Name> file
+	Comment string
+	File    []ZipTestFile
+	Error   error // the error that Opening this file should return
+}
+
+type ZipTestFile struct {
+	Name       string
+	Content    []byte // if blank, will attempt to compare against File
+	ContentErr error
+	File       string // name of file to compare to (relative to testdata/)
+	Mtime      string // modified time in format "mm-dd-yy hh:mm:ss"
+	Mode       os.FileMode
+}
+
+// Caution: The Mtime values found for the test files should correspond to
+//          the values listed with unzip -l <zipfile>. However, the values
+//          listed by unzip appear to be off by some hours. When creating
+//          fresh test files and testing them, this issue is not present.
+//          The test files were created in Sydney, so there might be a time
+//          zone issue. The time zone information does have to be encoded
+//          somewhere, because otherwise unzip -l could not provide a different
+//          time from what the archive/zip package provides, but there appears
+//          to be no documentation about this.
+
+var tests = []ZipTest{
+	{
+		Name:    "test.zip",
+		Comment: "This is a zipfile comment.",
+		File: []ZipTestFile{
+			{
+				Name:    "test.txt",
+				Content: []byte("This is a test text file.\n"),
+				Mtime:   "09-05-10 12:12:02",
+				Mode:    0644,
+			},
+			{
+				Name:  "gophercolor16x16.png",
+				File:  "gophercolor16x16.png",
+				Mtime: "09-05-10 15:52:58",
+				Mode:  0644,
+			},
+		},
+	},
+	{
+		Name:    "test-trailing-junk.zip",
+		Comment: "This is a zipfile comment.",
+		File: []ZipTestFile{
+			{
+				Name:    "test.txt",
+				Content: []byte("This is a test text file.\n"),
+				Mtime:   "09-05-10 12:12:02",
+				Mode:    0644,
+			},
+			{
+				Name:  "gophercolor16x16.png",
+				File:  "gophercolor16x16.png",
+				Mtime: "09-05-10 15:52:58",
+				Mode:  0644,
+			},
+		},
+	},
+	{
+		Name:   "r.zip",
+		Source: returnRecursiveZip,
+		File: []ZipTestFile{
+			{
+				Name:    "r/r.zip",
+				Content: rZipBytes(),
+				Mtime:   "03-04-10 00:24:16",
+				Mode:    0666,
+			},
+		},
+	},
+	{
+		Name: "symlink.zip",
+		File: []ZipTestFile{
+			{
+				Name:    "symlink",
+				Content: []byte("../target"),
+				Mode:    0777 | os.ModeSymlink,
+			},
+		},
+	},
+	{
+		Name: "readme.zip",
+	},
+	{
+		Name:  "readme.notzip",
+		Error: ErrFormat,
+	},
+	{
+		Name: "dd.zip",
+		File: []ZipTestFile{
+			{
+				Name:    "filename",
+				Content: []byte("This is a test textfile.\n"),
+				Mtime:   "02-02-11 13:06:20",
+				Mode:    0666,
+			},
+		},
+	},
+	{
+		// created in windows XP file manager.
+		Name: "winxp.zip",
+		File: crossPlatform,
+	},
+	{
+		// created by Zip 3.0 under Linux
+		Name: "unix.zip",
+		File: crossPlatform,
+	},
+	{
+		// created by Go, before we wrote the "optional" data
+		// descriptor signatures (which are required by OS X)
+		Name: "go-no-datadesc-sig.zip",
+		File: []ZipTestFile{
+			{
+				Name:    "foo.txt",
+				Content: []byte("foo\n"),
+				Mtime:   "03-08-12 16:59:10",
+				Mode:    0644,
+			},
+			{
+				Name:    "bar.txt",
+				Content: []byte("bar\n"),
+				Mtime:   "03-08-12 16:59:12",
+				Mode:    0644,
+			},
+		},
+	},
+	{
+		// created by Go, after we wrote the "optional" data
+		// descriptor signatures (which are required by OS X)
+		Name: "go-with-datadesc-sig.zip",
+		File: []ZipTestFile{
+			{
+				Name:    "foo.txt",
+				Content: []byte("foo\n"),
+				Mode:    0666,
+			},
+			{
+				Name:    "bar.txt",
+				Content: []byte("bar\n"),
+				Mode:    0666,
+			},
+		},
+	},
+	{
+		Name:   "Bad-CRC32-in-data-descriptor",
+		Source: returnCorruptCRC32Zip,
+		File: []ZipTestFile{
+			{
+				Name:       "foo.txt",
+				Content:    []byte("foo\n"),
+				Mode:       0666,
+				ContentErr: ErrChecksum,
+			},
+			{
+				Name:    "bar.txt",
+				Content: []byte("bar\n"),
+				Mode:    0666,
+			},
+		},
+	},
+	// Tests that we verify (and accept valid) crc32s on files
+	// with crc32s in their file header (not in data descriptors)
+	{
+		Name: "crc32-not-streamed.zip",
+		File: []ZipTestFile{
+			{
+				Name:    "foo.txt",
+				Content: []byte("foo\n"),
+				Mtime:   "03-08-12 16:59:10",
+				Mode:    0644,
+			},
+			{
+				Name:    "bar.txt",
+				Content: []byte("bar\n"),
+				Mtime:   "03-08-12 16:59:12",
+				Mode:    0644,
+			},
+		},
+	},
+	// Tests that we verify (and reject invalid) crc32s on files
+	// with crc32s in their file header (not in data descriptors)
+	{
+		Name:   "crc32-not-streamed.zip",
+		Source: returnCorruptNotStreamedZip,
+		File: []ZipTestFile{
+			{
+				Name:       "foo.txt",
+				Content:    []byte("foo\n"),
+				Mtime:      "03-08-12 16:59:10",
+				Mode:       0644,
+				ContentErr: ErrChecksum,
+			},
+			{
+				Name:    "bar.txt",
+				Content: []byte("bar\n"),
+				Mtime:   "03-08-12 16:59:12",
+				Mode:    0644,
+			},
+		},
+	},
+	{
+		Name: "zip64.zip",
+		File: []ZipTestFile{
+			{
+				Name:    "README",
+				Content: []byte("This small file is in ZIP64 format.\n"),
+				Mtime:   "08-10-12 14:33:32",
+				Mode:    0644,
+			},
+		},
+	},
+	// Another zip64 file with different Extras fields. (golang.org/issue/7069)
+	{
+		Name: "zip64-2.zip",
+		File: []ZipTestFile{
+			{
+				Name:    "README",
+				Content: []byte("This small file is in ZIP64 format.\n"),
+				Mtime:   "08-10-12 14:33:32",
+				Mode:    0644,
+			},
+		},
+	},
+}
+
+var crossPlatform = []ZipTestFile{
+	{
+		Name:    "hello",
+		Content: []byte("world \r\n"),
+		Mode:    0666,
+	},
+	{
+		Name:    "dir/bar",
+		Content: []byte("foo \r\n"),
+		Mode:    0666,
+	},
+	{
+		Name:    "dir/empty/",
+		Content: []byte{},
+		Mode:    os.ModeDir | 0777,
+	},
+	{
+		Name:    "readonly",
+		Content: []byte("important \r\n"),
+		Mode:    0444,
+	},
+}
+
+func TestReader(t *testing.T) {
+	for _, zt := range tests {
+		readTestZip(t, zt)
+	}
+}
+
+func readTestZip(t *testing.T, zt ZipTest) {
+	var z *Reader
+	var err error
+	if zt.Source != nil {
+		rat, size := zt.Source()
+		z, err = NewReader(rat, size)
+	} else {
+		var rc *ReadCloser
+		rc, err = OpenReader(filepath.Join("testdata", zt.Name))
+		if err == nil {
+			defer rc.Close()
+			z = &rc.Reader
+		}
+	}
+	if err != zt.Error {
+		t.Errorf("%s: error=%v, want %v", zt.Name, err, zt.Error)
+		return
+	}
+
+	// bail if file is not zip
+	if err == ErrFormat {
+		return
+	}
+
+	// bail here if no Files expected to be tested
+	// (there may actually be files in the zip, but we don't care)
+	if zt.File == nil {
+		return
+	}
+
+	if z.Comment != zt.Comment {
+		t.Errorf("%s: comment=%q, want %q", zt.Name, z.Comment, zt.Comment)
+	}
+	if len(z.File) != len(zt.File) {
+		t.Fatalf("%s: file count=%d, want %d", zt.Name, len(z.File), len(zt.File))
+	}
+
+	// test read of each file
+	for i, ft := range zt.File {
+		readTestFile(t, zt, ft, z.File[i])
+	}
+
+	// test simultaneous reads
+	n := 0
+	done := make(chan bool)
+	for i := 0; i < 5; i++ {
+		for j, ft := range zt.File {
+			go func(j int, ft ZipTestFile) {
+				readTestFile(t, zt, ft, z.File[j])
+				done <- true
+			}(j, ft)
+			n++
+		}
+	}
+	for ; n > 0; n-- {
+		<-done
+	}
+}
+
+func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
+	if f.Name != ft.Name {
+		t.Errorf("%s: name=%q, want %q", zt.Name, f.Name, ft.Name)
+	}
+
+	if ft.Mtime != "" {
+		mtime, err := time.Parse("01-02-06 15:04:05", ft.Mtime)
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		if ft := f.ModTime(); !ft.Equal(mtime) {
+			t.Errorf("%s: %s: mtime=%s, want %s", zt.Name, f.Name, ft, mtime)
+		}
+	}
+
+	testFileMode(t, zt.Name, f, ft.Mode)
+
+	var b bytes.Buffer
+	r, err := f.Open()
+	if err != nil {
+		t.Errorf("%s: %v", zt.Name, err)
+		return
+	}
+
+	_, err = io.Copy(&b, r)
+	if err != ft.ContentErr {
+		t.Errorf("%s: copying contents: %v (want %v)", zt.Name, err, ft.ContentErr)
+	}
+	if err != nil {
+		return
+	}
+	r.Close()
+
+	size := uint64(f.UncompressedSize)
+	if size == uint32max {
+		size = f.UncompressedSize64
+	}
+	if g := uint64(b.Len()); g != size {
+		t.Errorf("%v: read %v bytes but f.UncompressedSize == %v", f.Name, g, size)
+	}
+
+	var c []byte
+	if ft.Content != nil {
+		c = ft.Content
+	} else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil {
+		t.Error(err)
+		return
+	}
+
+	if b.Len() != len(c) {
+		t.Errorf("%s: len=%d, want %d", f.Name, b.Len(), len(c))
+		return
+	}
+
+	for i, b := range b.Bytes() {
+		if b != c[i] {
+			t.Errorf("%s: content[%d]=%q want %q", f.Name, i, b, c[i])
+			return
+		}
+	}
+}
+
+func testFileMode(t *testing.T, zipName string, f *File, want os.FileMode) {
+	mode := f.Mode()
+	if want == 0 {
+		t.Errorf("%s: %s mode: got %v, want none", zipName, f.Name, mode)
+	} else if mode != want {
+		t.Errorf("%s: %s mode: want %v, got %v", zipName, f.Name, want, mode)
+	}
+}
+
+func TestInvalidFiles(t *testing.T) {
+	const size = 1024 * 70 // 70kb
+	b := make([]byte, size)
+
+	// zeroes
+	_, err := NewReader(bytes.NewReader(b), size)
+	if err != ErrFormat {
+		t.Errorf("zeroes: error=%v, want %v", err, ErrFormat)
+	}
+
+	// repeated directoryEndSignatures
+	sig := make([]byte, 4)
+	binary.LittleEndian.PutUint32(sig, directoryEndSignature)
+	for i := 0; i < size-4; i += 4 {
+		copy(b[i:i+4], sig)
+	}
+	_, err = NewReader(bytes.NewReader(b), size)
+	if err != ErrFormat {
+		t.Errorf("sigs: error=%v, want %v", err, ErrFormat)
+	}
+}
+
+func messWith(fileName string, corrupter func(b []byte)) (r io.ReaderAt, size int64) {
+	data, err := ioutil.ReadFile(filepath.Join("testdata", fileName))
+	if err != nil {
+		panic("Error reading " + fileName + ": " + err.Error())
+	}
+	corrupter(data)
+	return bytes.NewReader(data), int64(len(data))
+}
+
+func returnCorruptCRC32Zip() (r io.ReaderAt, size int64) {
+	return messWith("go-with-datadesc-sig.zip", func(b []byte) {
+		// Corrupt one of the CRC32s in the data descriptor:
+		b[0x2d]++
+	})
+}
+
+func returnCorruptNotStreamedZip() (r io.ReaderAt, size int64) {
+	return messWith("crc32-not-streamed.zip", func(b []byte) {
+		// Corrupt foo.txt's final crc32 byte, in both
+		// the file header and TOC. (0x7e -> 0x7f)
+		b[0x11]++
+		b[0x9d]++
+
+		// TODO(bradfitz): add a new test that only corrupts
+		// one of these values, and verify that that's also an
+		// error. Currently, the reader code doesn't verify the
+		// fileheader and TOC's crc32 match if they're both
+		// non-zero and only the second line above, the TOC,
+		// is what matters.
+	})
+}
+
+// rZipBytes returns the bytes of a recursive zip file, without
+// putting it on disk and triggering certain virus scanners.
+func rZipBytes() []byte {
+	s := `
+0000000 50 4b 03 04 14 00 00 00 08 00 08 03 64 3c f9 f4
+0000010 89 64 48 01 00 00 b8 01 00 00 07 00 00 00 72 2f
+0000020 72 2e 7a 69 70 00 25 00 da ff 50 4b 03 04 14 00
+0000030 00 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00
+0000040 b8 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00
+0000050 2f 00 d0 ff 00 25 00 da ff 50 4b 03 04 14 00 00
+0000060 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 b8
+0000070 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 2f
+0000080 00 d0 ff c2 54 8e 57 39 00 05 00 fa ff c2 54 8e
+0000090 57 39 00 05 00 fa ff 00 05 00 fa ff 00 14 00 eb
+00000a0 ff c2 54 8e 57 39 00 05 00 fa ff 00 05 00 fa ff
+00000b0 00 14 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42
+00000c0 88 21 c4 00 00 14 00 eb ff 42 88 21 c4 00 00 14
+00000d0 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 88 21
+00000e0 c4 00 00 00 00 ff ff 00 00 00 ff ff 00 34 00 cb
+00000f0 ff 42 88 21 c4 00 00 00 00 ff ff 00 00 00 ff ff
+0000100 00 34 00 cb ff 42 e8 21 5e 0f 00 00 00 ff ff 0a
+0000110 f0 66 64 12 61 c0 15 dc e8 a0 48 bf 48 af 2a b3
+0000120 20 c0 9b 95 0d c4 67 04 42 53 06 06 06 40 00 06
+0000130 00 f9 ff 6d 01 00 00 00 00 42 e8 21 5e 0f 00 00
+0000140 00 ff ff 0a f0 66 64 12 61 c0 15 dc e8 a0 48 bf
+0000150 48 af 2a b3 20 c0 9b 95 0d c4 67 04 42 53 06 06
+0000160 06 40 00 06 00 f9 ff 6d 01 00 00 00 00 50 4b 01
+0000170 02 14 00 14 00 00 00 08 00 08 03 64 3c f9 f4 89
+0000180 64 48 01 00 00 b8 01 00 00 07 00 00 00 00 00 00
+0000190 00 00 00 00 00 00 00 00 00 00 00 72 2f 72 2e 7a
+00001a0 69 70 50 4b 05 06 00 00 00 00 01 00 01 00 35 00
+00001b0 00 00 6d 01 00 00 00 00`
+	s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "")
+	s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "")
+	b, err := hex.DecodeString(s)
+	if err != nil {
+		panic(err)
+	}
+	return b
+}
+
+func returnRecursiveZip() (r io.ReaderAt, size int64) {
+	b := rZipBytes()
+	return bytes.NewReader(b), int64(len(b))
+}
diff --git a/third_party/gofrontend/libgo/go/archive/zip/register.go b/third_party/gofrontend/libgo/go/archive/zip/register.go
new file mode 100644
index 0000000..4211ec7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/register.go
@@ -0,0 +1,110 @@
+// Copyright 2010 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 zip
+
+import (
+	"compress/flate"
+	"errors"
+	"io"
+	"io/ioutil"
+	"sync"
+)
+
+// A Compressor returns a compressing writer, writing to the
+// provided writer. On Close, any pending data should be flushed.
+type Compressor func(io.Writer) (io.WriteCloser, error)
+
+// Decompressor is a function that wraps a Reader with a decompressing Reader.
+// The decompressed ReadCloser is returned to callers who open files from
+// within the archive.  These callers are responsible for closing this reader
+// when they're finished reading.
+type Decompressor func(io.Reader) io.ReadCloser
+
+var flateWriterPool sync.Pool
+
+func newFlateWriter(w io.Writer) io.WriteCloser {
+	fw, ok := flateWriterPool.Get().(*flate.Writer)
+	if ok {
+		fw.Reset(w)
+	} else {
+		fw, _ = flate.NewWriter(w, 5)
+	}
+	return &pooledFlateWriter{fw: fw}
+}
+
+type pooledFlateWriter struct {
+	mu sync.Mutex // guards Close and Write
+	fw *flate.Writer
+}
+
+func (w *pooledFlateWriter) Write(p []byte) (n int, err error) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	if w.fw == nil {
+		return 0, errors.New("Write after Close")
+	}
+	return w.fw.Write(p)
+}
+
+func (w *pooledFlateWriter) Close() error {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	var err error
+	if w.fw != nil {
+		err = w.fw.Close()
+		flateWriterPool.Put(w.fw)
+		w.fw = nil
+	}
+	return err
+}
+
+var (
+	mu sync.RWMutex // guards compressor and decompressor maps
+
+	compressors = map[uint16]Compressor{
+		Store:   func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil },
+		Deflate: func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil },
+	}
+
+	decompressors = map[uint16]Decompressor{
+		Store:   ioutil.NopCloser,
+		Deflate: flate.NewReader,
+	}
+)
+
+// RegisterDecompressor allows custom decompressors for a specified method ID.
+func RegisterDecompressor(method uint16, d Decompressor) {
+	mu.Lock()
+	defer mu.Unlock()
+
+	if _, ok := decompressors[method]; ok {
+		panic("decompressor already registered")
+	}
+	decompressors[method] = d
+}
+
+// RegisterCompressor registers custom compressors for a specified method ID.
+// The common methods Store and Deflate are built in.
+func RegisterCompressor(method uint16, comp Compressor) {
+	mu.Lock()
+	defer mu.Unlock()
+
+	if _, ok := compressors[method]; ok {
+		panic("compressor already registered")
+	}
+	compressors[method] = comp
+}
+
+func compressor(method uint16) Compressor {
+	mu.RLock()
+	defer mu.RUnlock()
+	return compressors[method]
+}
+
+func decompressor(method uint16) Decompressor {
+	mu.RLock()
+	defer mu.RUnlock()
+	return decompressors[method]
+}
diff --git a/third_party/gofrontend/libgo/go/archive/zip/struct.go b/third_party/gofrontend/libgo/go/archive/zip/struct.go
new file mode 100644
index 0000000..cb28e83
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/struct.go
@@ -0,0 +1,313 @@
+// Copyright 2010 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 zip provides support for reading and writing ZIP archives.
+
+See: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
+
+This package does not support disk spanning.
+
+A note about ZIP64:
+
+To be backwards compatible the FileHeader has both 32 and 64 bit Size
+fields. The 64 bit fields will always contain the correct value and
+for normal archives both fields will be the same. For files requiring
+the ZIP64 format the 32 bit fields will be 0xffffffff and the 64 bit
+fields must be used instead.
+*/
+package zip
+
+import (
+	"os"
+	"path"
+	"time"
+)
+
+// Compression methods.
+const (
+	Store   uint16 = 0
+	Deflate uint16 = 8
+)
+
+const (
+	fileHeaderSignature      = 0x04034b50
+	directoryHeaderSignature = 0x02014b50
+	directoryEndSignature    = 0x06054b50
+	directory64LocSignature  = 0x07064b50
+	directory64EndSignature  = 0x06064b50
+	dataDescriptorSignature  = 0x08074b50 // de-facto standard; required by OS X Finder
+	fileHeaderLen            = 30         // + filename + extra
+	directoryHeaderLen       = 46         // + filename + extra + comment
+	directoryEndLen          = 22         // + comment
+	dataDescriptorLen        = 16         // four uint32: descriptor signature, crc32, compressed size, size
+	dataDescriptor64Len      = 24         // descriptor with 8 byte sizes
+	directory64LocLen        = 20         //
+	directory64EndLen        = 56         // + extra
+
+	// Constants for the first byte in CreatorVersion
+	creatorFAT    = 0
+	creatorUnix   = 3
+	creatorNTFS   = 11
+	creatorVFAT   = 14
+	creatorMacOSX = 19
+
+	// version numbers
+	zipVersion20 = 20 // 2.0
+	zipVersion45 = 45 // 4.5 (reads and writes zip64 archives)
+
+	// limits for non zip64 files
+	uint16max = (1 << 16) - 1
+	uint32max = (1 << 32) - 1
+
+	// extra header id's
+	zip64ExtraId = 0x0001 // zip64 Extended Information Extra Field
+)
+
+// FileHeader describes a file within a zip file.
+// See the zip spec for details.
+type FileHeader struct {
+	// Name is the name of the file.
+	// It must be a relative path: it must not start with a drive
+	// letter (e.g. C:) or leading slash, and only forward slashes
+	// are allowed.
+	Name string
+
+	CreatorVersion     uint16
+	ReaderVersion      uint16
+	Flags              uint16
+	Method             uint16
+	ModifiedTime       uint16 // MS-DOS time
+	ModifiedDate       uint16 // MS-DOS date
+	CRC32              uint32
+	CompressedSize     uint32 // deprecated; use CompressedSize64
+	UncompressedSize   uint32 // deprecated; use UncompressedSize64
+	CompressedSize64   uint64
+	UncompressedSize64 uint64
+	Extra              []byte
+	ExternalAttrs      uint32 // Meaning depends on CreatorVersion
+	Comment            string
+}
+
+// FileInfo returns an os.FileInfo for the FileHeader.
+func (h *FileHeader) FileInfo() os.FileInfo {
+	return headerFileInfo{h}
+}
+
+// headerFileInfo implements os.FileInfo.
+type headerFileInfo struct {
+	fh *FileHeader
+}
+
+func (fi headerFileInfo) Name() string { return path.Base(fi.fh.Name) }
+func (fi headerFileInfo) Size() int64 {
+	if fi.fh.UncompressedSize64 > 0 {
+		return int64(fi.fh.UncompressedSize64)
+	}
+	return int64(fi.fh.UncompressedSize)
+}
+func (fi headerFileInfo) IsDir() bool        { return fi.Mode().IsDir() }
+func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() }
+func (fi headerFileInfo) Mode() os.FileMode  { return fi.fh.Mode() }
+func (fi headerFileInfo) Sys() interface{}   { return fi.fh }
+
+// FileInfoHeader creates a partially-populated FileHeader from an
+// os.FileInfo.
+// Because os.FileInfo's Name method returns only the base name of
+// the file it describes, it may be necessary to modify the Name field
+// of the returned header to provide the full path name of the file.
+func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
+	size := fi.Size()
+	fh := &FileHeader{
+		Name:               fi.Name(),
+		UncompressedSize64: uint64(size),
+	}
+	fh.SetModTime(fi.ModTime())
+	fh.SetMode(fi.Mode())
+	if fh.UncompressedSize64 > uint32max {
+		fh.UncompressedSize = uint32max
+	} else {
+		fh.UncompressedSize = uint32(fh.UncompressedSize64)
+	}
+	return fh, nil
+}
+
+type directoryEnd struct {
+	diskNbr            uint32 // unused
+	dirDiskNbr         uint32 // unused
+	dirRecordsThisDisk uint64 // unused
+	directoryRecords   uint64
+	directorySize      uint64
+	directoryOffset    uint64 // relative to file
+	commentLen         uint16
+	comment            string
+}
+
+// msDosTimeToTime converts an MS-DOS date and time into a time.Time.
+// The resolution is 2s.
+// See: http://msdn.microsoft.com/en-us/library/ms724247(v=VS.85).aspx
+func msDosTimeToTime(dosDate, dosTime uint16) time.Time {
+	return time.Date(
+		// date bits 0-4: day of month; 5-8: month; 9-15: years since 1980
+		int(dosDate>>9+1980),
+		time.Month(dosDate>>5&0xf),
+		int(dosDate&0x1f),
+
+		// time bits 0-4: second/2; 5-10: minute; 11-15: hour
+		int(dosTime>>11),
+		int(dosTime>>5&0x3f),
+		int(dosTime&0x1f*2),
+		0, // nanoseconds
+
+		time.UTC,
+	)
+}
+
+// timeToMsDosTime converts a time.Time to an MS-DOS date and time.
+// The resolution is 2s.
+// See: http://msdn.microsoft.com/en-us/library/ms724274(v=VS.85).aspx
+func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16) {
+	t = t.In(time.UTC)
+	fDate = uint16(t.Day() + int(t.Month())<<5 + (t.Year()-1980)<<9)
+	fTime = uint16(t.Second()/2 + t.Minute()<<5 + t.Hour()<<11)
+	return
+}
+
+// ModTime returns the modification time in UTC.
+// The resolution is 2s.
+func (h *FileHeader) ModTime() time.Time {
+	return msDosTimeToTime(h.ModifiedDate, h.ModifiedTime)
+}
+
+// SetModTime sets the ModifiedTime and ModifiedDate fields to the given time in UTC.
+// The resolution is 2s.
+func (h *FileHeader) SetModTime(t time.Time) {
+	h.ModifiedDate, h.ModifiedTime = timeToMsDosTime(t)
+}
+
+const (
+	// Unix constants. The specification doesn't mention them,
+	// but these seem to be the values agreed on by tools.
+	s_IFMT   = 0xf000
+	s_IFSOCK = 0xc000
+	s_IFLNK  = 0xa000
+	s_IFREG  = 0x8000
+	s_IFBLK  = 0x6000
+	s_IFDIR  = 0x4000
+	s_IFCHR  = 0x2000
+	s_IFIFO  = 0x1000
+	s_ISUID  = 0x800
+	s_ISGID  = 0x400
+	s_ISVTX  = 0x200
+
+	msdosDir      = 0x10
+	msdosReadOnly = 0x01
+)
+
+// Mode returns the permission and mode bits for the FileHeader.
+func (h *FileHeader) Mode() (mode os.FileMode) {
+	switch h.CreatorVersion >> 8 {
+	case creatorUnix, creatorMacOSX:
+		mode = unixModeToFileMode(h.ExternalAttrs >> 16)
+	case creatorNTFS, creatorVFAT, creatorFAT:
+		mode = msdosModeToFileMode(h.ExternalAttrs)
+	}
+	if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
+		mode |= os.ModeDir
+	}
+	return mode
+}
+
+// SetMode changes the permission and mode bits for the FileHeader.
+func (h *FileHeader) SetMode(mode os.FileMode) {
+	h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8
+	h.ExternalAttrs = fileModeToUnixMode(mode) << 16
+
+	// set MSDOS attributes too, as the original zip does.
+	if mode&os.ModeDir != 0 {
+		h.ExternalAttrs |= msdosDir
+	}
+	if mode&0200 == 0 {
+		h.ExternalAttrs |= msdosReadOnly
+	}
+}
+
+// isZip64 returns true if the file size exceeds the 32 bit limit
+func (fh *FileHeader) isZip64() bool {
+	return fh.CompressedSize64 > uint32max || fh.UncompressedSize64 > uint32max
+}
+
+func msdosModeToFileMode(m uint32) (mode os.FileMode) {
+	if m&msdosDir != 0 {
+		mode = os.ModeDir | 0777
+	} else {
+		mode = 0666
+	}
+	if m&msdosReadOnly != 0 {
+		mode &^= 0222
+	}
+	return mode
+}
+
+func fileModeToUnixMode(mode os.FileMode) uint32 {
+	var m uint32
+	switch mode & os.ModeType {
+	default:
+		m = s_IFREG
+	case os.ModeDir:
+		m = s_IFDIR
+	case os.ModeSymlink:
+		m = s_IFLNK
+	case os.ModeNamedPipe:
+		m = s_IFIFO
+	case os.ModeSocket:
+		m = s_IFSOCK
+	case os.ModeDevice:
+		if mode&os.ModeCharDevice != 0 {
+			m = s_IFCHR
+		} else {
+			m = s_IFBLK
+		}
+	}
+	if mode&os.ModeSetuid != 0 {
+		m |= s_ISUID
+	}
+	if mode&os.ModeSetgid != 0 {
+		m |= s_ISGID
+	}
+	if mode&os.ModeSticky != 0 {
+		m |= s_ISVTX
+	}
+	return m | uint32(mode&0777)
+}
+
+func unixModeToFileMode(m uint32) os.FileMode {
+	mode := os.FileMode(m & 0777)
+	switch m & s_IFMT {
+	case s_IFBLK:
+		mode |= os.ModeDevice
+	case s_IFCHR:
+		mode |= os.ModeDevice | os.ModeCharDevice
+	case s_IFDIR:
+		mode |= os.ModeDir
+	case s_IFIFO:
+		mode |= os.ModeNamedPipe
+	case s_IFLNK:
+		mode |= os.ModeSymlink
+	case s_IFREG:
+		// nothing to do
+	case s_IFSOCK:
+		mode |= os.ModeSocket
+	}
+	if m&s_ISGID != 0 {
+		mode |= os.ModeSetgid
+	}
+	if m&s_ISUID != 0 {
+		mode |= os.ModeSetuid
+	}
+	if m&s_ISVTX != 0 {
+		mode |= os.ModeSticky
+	}
+	return mode
+}
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/crc32-not-streamed.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/crc32-not-streamed.zip
new file mode 100644
index 0000000..f268d88
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/crc32-not-streamed.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/dd.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/dd.zip
new file mode 100644
index 0000000..e53378b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/dd.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/go-no-datadesc-sig.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/go-no-datadesc-sig.zip
new file mode 100644
index 0000000..c3d593f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/go-no-datadesc-sig.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/go-with-datadesc-sig.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/go-with-datadesc-sig.zip
new file mode 100644
index 0000000..bcfe121
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/go-with-datadesc-sig.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/gophercolor16x16.png b/third_party/gofrontend/libgo/go/archive/zip/testdata/gophercolor16x16.png
new file mode 100644
index 0000000..48854ff
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/gophercolor16x16.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/readme.notzip b/third_party/gofrontend/libgo/go/archive/zip/testdata/readme.notzip
new file mode 100644
index 0000000..06668c4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/readme.notzip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/readme.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/readme.zip
new file mode 100644
index 0000000..db3bb90
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/readme.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/symlink.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/symlink.zip
new file mode 100644
index 0000000..af84693
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/symlink.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/test-trailing-junk.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/test-trailing-junk.zip
new file mode 100644
index 0000000..42281b4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/test-trailing-junk.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/test.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/test.zip
new file mode 100644
index 0000000..03890c0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/test.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/unix.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/unix.zip
new file mode 100644
index 0000000..ce1a981
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/unix.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/winxp.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/winxp.zip
new file mode 100644
index 0000000..3919322
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/winxp.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/zip64-2.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/zip64-2.zip
new file mode 100644
index 0000000..f844e35
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/zip64-2.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/testdata/zip64.zip b/third_party/gofrontend/libgo/go/archive/zip/testdata/zip64.zip
new file mode 100644
index 0000000..a2ee1fa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/testdata/zip64.zip
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/archive/zip/writer.go b/third_party/gofrontend/libgo/go/archive/zip/writer.go
new file mode 100644
index 0000000..6c9800a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/writer.go
@@ -0,0 +1,351 @@
+// 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.
+
+package zip
+
+import (
+	"bufio"
+	"encoding/binary"
+	"errors"
+	"hash"
+	"hash/crc32"
+	"io"
+)
+
+// TODO(adg): support zip file comments
+// TODO(adg): support specifying deflate level
+
+// Writer implements a zip file writer.
+type Writer struct {
+	cw     *countWriter
+	dir    []*header
+	last   *fileWriter
+	closed bool
+}
+
+type header struct {
+	*FileHeader
+	offset uint64
+}
+
+// NewWriter returns a new Writer writing a zip file to w.
+func NewWriter(w io.Writer) *Writer {
+	return &Writer{cw: &countWriter{w: bufio.NewWriter(w)}}
+}
+
+// Close finishes writing the zip file by writing the central directory.
+// It does not (and can not) close the underlying writer.
+func (w *Writer) Close() error {
+	if w.last != nil && !w.last.closed {
+		if err := w.last.close(); err != nil {
+			return err
+		}
+		w.last = nil
+	}
+	if w.closed {
+		return errors.New("zip: writer closed twice")
+	}
+	w.closed = true
+
+	// write central directory
+	start := w.cw.count
+	for _, h := range w.dir {
+		var buf [directoryHeaderLen]byte
+		b := writeBuf(buf[:])
+		b.uint32(uint32(directoryHeaderSignature))
+		b.uint16(h.CreatorVersion)
+		b.uint16(h.ReaderVersion)
+		b.uint16(h.Flags)
+		b.uint16(h.Method)
+		b.uint16(h.ModifiedTime)
+		b.uint16(h.ModifiedDate)
+		b.uint32(h.CRC32)
+		if h.isZip64() || h.offset > uint32max {
+			// the file needs a zip64 header. store maxint in both
+			// 32 bit size fields (and offset later) to signal that the
+			// zip64 extra header should be used.
+			b.uint32(uint32max) // compressed size
+			b.uint32(uint32max) // uncompressed size
+
+			// append a zip64 extra block to Extra
+			var buf [28]byte // 2x uint16 + 3x uint64
+			eb := writeBuf(buf[:])
+			eb.uint16(zip64ExtraId)
+			eb.uint16(24) // size = 3x uint64
+			eb.uint64(h.UncompressedSize64)
+			eb.uint64(h.CompressedSize64)
+			eb.uint64(h.offset)
+			h.Extra = append(h.Extra, buf[:]...)
+		} else {
+			b.uint32(h.CompressedSize)
+			b.uint32(h.UncompressedSize)
+		}
+		b.uint16(uint16(len(h.Name)))
+		b.uint16(uint16(len(h.Extra)))
+		b.uint16(uint16(len(h.Comment)))
+		b = b[4:] // skip disk number start and internal file attr (2x uint16)
+		b.uint32(h.ExternalAttrs)
+		if h.offset > uint32max {
+			b.uint32(uint32max)
+		} else {
+			b.uint32(uint32(h.offset))
+		}
+		if _, err := w.cw.Write(buf[:]); err != nil {
+			return err
+		}
+		if _, err := io.WriteString(w.cw, h.Name); err != nil {
+			return err
+		}
+		if _, err := w.cw.Write(h.Extra); err != nil {
+			return err
+		}
+		if _, err := io.WriteString(w.cw, h.Comment); err != nil {
+			return err
+		}
+	}
+	end := w.cw.count
+
+	records := uint64(len(w.dir))
+	size := uint64(end - start)
+	offset := uint64(start)
+
+	if records > uint16max || size > uint32max || offset > uint32max {
+		var buf [directory64EndLen + directory64LocLen]byte
+		b := writeBuf(buf[:])
+
+		// zip64 end of central directory record
+		b.uint32(directory64EndSignature)
+		b.uint64(directory64EndLen)
+		b.uint16(zipVersion45) // version made by
+		b.uint16(zipVersion45) // version needed to extract
+		b.uint32(0)            // number of this disk
+		b.uint32(0)            // number of the disk with the start of the central directory
+		b.uint64(records)      // total number of entries in the central directory on this disk
+		b.uint64(records)      // total number of entries in the central directory
+		b.uint64(size)         // size of the central directory
+		b.uint64(offset)       // offset of start of central directory with respect to the starting disk number
+
+		// zip64 end of central directory locator
+		b.uint32(directory64LocSignature)
+		b.uint32(0)           // number of the disk with the start of the zip64 end of central directory
+		b.uint64(uint64(end)) // relative offset of the zip64 end of central directory record
+		b.uint32(1)           // total number of disks
+
+		if _, err := w.cw.Write(buf[:]); err != nil {
+			return err
+		}
+
+		// store max values in the regular end record to signal that
+		// that the zip64 values should be used instead
+		records = uint16max
+		size = uint32max
+		offset = uint32max
+	}
+
+	// write end record
+	var buf [directoryEndLen]byte
+	b := writeBuf(buf[:])
+	b.uint32(uint32(directoryEndSignature))
+	b = b[4:]                 // skip over disk number and first disk number (2x uint16)
+	b.uint16(uint16(records)) // number of entries this disk
+	b.uint16(uint16(records)) // number of entries total
+	b.uint32(uint32(size))    // size of directory
+	b.uint32(uint32(offset))  // start of directory
+	// skipped size of comment (always zero)
+	if _, err := w.cw.Write(buf[:]); err != nil {
+		return err
+	}
+
+	return w.cw.w.(*bufio.Writer).Flush()
+}
+
+// Create adds a file to the zip file using the provided name.
+// It returns a Writer to which the file contents should be written.
+// The name must be a relative path: it must not start with a drive
+// letter (e.g. C:) or leading slash, and only forward slashes are
+// allowed.
+// The file's contents must be written to the io.Writer before the next
+// call to Create, CreateHeader, or Close.
+func (w *Writer) Create(name string) (io.Writer, error) {
+	header := &FileHeader{
+		Name:   name,
+		Method: Deflate,
+	}
+	return w.CreateHeader(header)
+}
+
+// CreateHeader adds a file to the zip file using the provided FileHeader
+// for the file metadata.
+// It returns a Writer to which the file contents should be written.
+// The file's contents must be written to the io.Writer before the next
+// call to Create, CreateHeader, or Close.
+func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
+	if w.last != nil && !w.last.closed {
+		if err := w.last.close(); err != nil {
+			return nil, err
+		}
+	}
+
+	fh.Flags |= 0x8 // we will write a data descriptor
+
+	fh.CreatorVersion = fh.CreatorVersion&0xff00 | zipVersion20 // preserve compatibility byte
+	fh.ReaderVersion = zipVersion20
+
+	fw := &fileWriter{
+		zipw:      w.cw,
+		compCount: &countWriter{w: w.cw},
+		crc32:     crc32.NewIEEE(),
+	}
+	comp := compressor(fh.Method)
+	if comp == nil {
+		return nil, ErrAlgorithm
+	}
+	var err error
+	fw.comp, err = comp(fw.compCount)
+	if err != nil {
+		return nil, err
+	}
+	fw.rawCount = &countWriter{w: fw.comp}
+
+	h := &header{
+		FileHeader: fh,
+		offset:     uint64(w.cw.count),
+	}
+	w.dir = append(w.dir, h)
+	fw.header = h
+
+	if err := writeHeader(w.cw, fh); err != nil {
+		return nil, err
+	}
+
+	w.last = fw
+	return fw, nil
+}
+
+func writeHeader(w io.Writer, h *FileHeader) error {
+	var buf [fileHeaderLen]byte
+	b := writeBuf(buf[:])
+	b.uint32(uint32(fileHeaderSignature))
+	b.uint16(h.ReaderVersion)
+	b.uint16(h.Flags)
+	b.uint16(h.Method)
+	b.uint16(h.ModifiedTime)
+	b.uint16(h.ModifiedDate)
+	b.uint32(0) // since we are writing a data descriptor crc32,
+	b.uint32(0) // compressed size,
+	b.uint32(0) // and uncompressed size should be zero
+	b.uint16(uint16(len(h.Name)))
+	b.uint16(uint16(len(h.Extra)))
+	if _, err := w.Write(buf[:]); err != nil {
+		return err
+	}
+	if _, err := io.WriteString(w, h.Name); err != nil {
+		return err
+	}
+	_, err := w.Write(h.Extra)
+	return err
+}
+
+type fileWriter struct {
+	*header
+	zipw      io.Writer
+	rawCount  *countWriter
+	comp      io.WriteCloser
+	compCount *countWriter
+	crc32     hash.Hash32
+	closed    bool
+}
+
+func (w *fileWriter) Write(p []byte) (int, error) {
+	if w.closed {
+		return 0, errors.New("zip: write to closed file")
+	}
+	w.crc32.Write(p)
+	return w.rawCount.Write(p)
+}
+
+func (w *fileWriter) close() error {
+	if w.closed {
+		return errors.New("zip: file closed twice")
+	}
+	w.closed = true
+	if err := w.comp.Close(); err != nil {
+		return err
+	}
+
+	// update FileHeader
+	fh := w.header.FileHeader
+	fh.CRC32 = w.crc32.Sum32()
+	fh.CompressedSize64 = uint64(w.compCount.count)
+	fh.UncompressedSize64 = uint64(w.rawCount.count)
+
+	if fh.isZip64() {
+		fh.CompressedSize = uint32max
+		fh.UncompressedSize = uint32max
+		fh.ReaderVersion = zipVersion45 // requires 4.5 - File uses ZIP64 format extensions
+	} else {
+		fh.CompressedSize = uint32(fh.CompressedSize64)
+		fh.UncompressedSize = uint32(fh.UncompressedSize64)
+	}
+
+	// Write data descriptor. This is more complicated than one would
+	// think, see e.g. comments in zipfile.c:putextended() and
+	// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588.
+	// The approach here is to write 8 byte sizes if needed without
+	// adding a zip64 extra in the local header (too late anyway).
+	var buf []byte
+	if fh.isZip64() {
+		buf = make([]byte, dataDescriptor64Len)
+	} else {
+		buf = make([]byte, dataDescriptorLen)
+	}
+	b := writeBuf(buf)
+	b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X
+	b.uint32(fh.CRC32)
+	if fh.isZip64() {
+		b.uint64(fh.CompressedSize64)
+		b.uint64(fh.UncompressedSize64)
+	} else {
+		b.uint32(fh.CompressedSize)
+		b.uint32(fh.UncompressedSize)
+	}
+	_, err := w.zipw.Write(buf)
+	return err
+}
+
+type countWriter struct {
+	w     io.Writer
+	count int64
+}
+
+func (w *countWriter) Write(p []byte) (int, error) {
+	n, err := w.w.Write(p)
+	w.count += int64(n)
+	return n, err
+}
+
+type nopCloser struct {
+	io.Writer
+}
+
+func (w nopCloser) Close() error {
+	return nil
+}
+
+type writeBuf []byte
+
+func (b *writeBuf) uint16(v uint16) {
+	binary.LittleEndian.PutUint16(*b, v)
+	*b = (*b)[2:]
+}
+
+func (b *writeBuf) uint32(v uint32) {
+	binary.LittleEndian.PutUint32(*b, v)
+	*b = (*b)[4:]
+}
+
+func (b *writeBuf) uint64(v uint64) {
+	binary.LittleEndian.PutUint64(*b, v)
+	*b = (*b)[8:]
+}
diff --git a/third_party/gofrontend/libgo/go/archive/zip/writer_test.go b/third_party/gofrontend/libgo/go/archive/zip/writer_test.go
new file mode 100644
index 0000000..4bfa870
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/writer_test.go
@@ -0,0 +1,145 @@
+// 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.
+
+package zip
+
+import (
+	"bytes"
+	"io/ioutil"
+	"math/rand"
+	"os"
+	"testing"
+)
+
+// TODO(adg): a more sophisticated test suite
+
+type WriteTest struct {
+	Name   string
+	Data   []byte
+	Method uint16
+	Mode   os.FileMode
+}
+
+var writeTests = []WriteTest{
+	{
+		Name:   "foo",
+		Data:   []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."),
+		Method: Store,
+		Mode:   0666,
+	},
+	{
+		Name:   "bar",
+		Data:   nil, // large data set in the test
+		Method: Deflate,
+		Mode:   0644,
+	},
+	{
+		Name:   "setuid",
+		Data:   []byte("setuid file"),
+		Method: Deflate,
+		Mode:   0755 | os.ModeSetuid,
+	},
+	{
+		Name:   "setgid",
+		Data:   []byte("setgid file"),
+		Method: Deflate,
+		Mode:   0755 | os.ModeSetgid,
+	},
+	{
+		Name:   "symlink",
+		Data:   []byte("../link/target"),
+		Method: Deflate,
+		Mode:   0755 | os.ModeSymlink,
+	},
+}
+
+func TestWriter(t *testing.T) {
+	largeData := make([]byte, 1<<17)
+	for i := range largeData {
+		largeData[i] = byte(rand.Int())
+	}
+	writeTests[1].Data = largeData
+	defer func() {
+		writeTests[1].Data = nil
+	}()
+
+	// write a zip file
+	buf := new(bytes.Buffer)
+	w := NewWriter(buf)
+
+	for _, wt := range writeTests {
+		testCreate(t, w, &wt)
+	}
+
+	if err := w.Close(); err != nil {
+		t.Fatal(err)
+	}
+
+	// read it back
+	r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
+	if err != nil {
+		t.Fatal(err)
+	}
+	for i, wt := range writeTests {
+		testReadFile(t, r.File[i], &wt)
+	}
+}
+
+func testCreate(t *testing.T, w *Writer, wt *WriteTest) {
+	header := &FileHeader{
+		Name:   wt.Name,
+		Method: wt.Method,
+	}
+	if wt.Mode != 0 {
+		header.SetMode(wt.Mode)
+	}
+	f, err := w.CreateHeader(header)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = f.Write(wt.Data)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func testReadFile(t *testing.T, f *File, wt *WriteTest) {
+	if f.Name != wt.Name {
+		t.Fatalf("File name: got %q, want %q", f.Name, wt.Name)
+	}
+	testFileMode(t, wt.Name, f, wt.Mode)
+	rc, err := f.Open()
+	if err != nil {
+		t.Fatal("opening:", err)
+	}
+	b, err := ioutil.ReadAll(rc)
+	if err != nil {
+		t.Fatal("reading:", err)
+	}
+	err = rc.Close()
+	if err != nil {
+		t.Fatal("closing:", err)
+	}
+	if !bytes.Equal(b, wt.Data) {
+		t.Errorf("File contents %q, want %q", b, wt.Data)
+	}
+}
+
+func BenchmarkCompressedZipGarbage(b *testing.B) {
+	b.ReportAllocs()
+	var buf bytes.Buffer
+	bigBuf := bytes.Repeat([]byte("a"), 1<<20)
+	for i := 0; i < b.N; i++ {
+		buf.Reset()
+		zw := NewWriter(&buf)
+		for j := 0; j < 3; j++ {
+			w, _ := zw.CreateHeader(&FileHeader{
+				Name:   "foo",
+				Method: Deflate,
+			})
+			w.Write(bigBuf)
+		}
+		zw.Close()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/archive/zip/zip_test.go b/third_party/gofrontend/libgo/go/archive/zip/zip_test.go
new file mode 100644
index 0000000..32a16a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/archive/zip/zip_test.go
@@ -0,0 +1,395 @@
+// 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.
+
+// Tests that involve both reading and writing.
+
+package zip
+
+import (
+	"bytes"
+	"fmt"
+	"hash"
+	"io"
+	"io/ioutil"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+)
+
+func TestOver65kFiles(t *testing.T) {
+	buf := new(bytes.Buffer)
+	w := NewWriter(buf)
+	const nFiles = (1 << 16) + 42
+	for i := 0; i < nFiles; i++ {
+		_, err := w.CreateHeader(&FileHeader{
+			Name:   fmt.Sprintf("%d.dat", i),
+			Method: Store, // avoid Issue 6136 and Issue 6138
+		})
+		if err != nil {
+			t.Fatalf("creating file %d: %v", i, err)
+		}
+	}
+	if err := w.Close(); err != nil {
+		t.Fatalf("Writer.Close: %v", err)
+	}
+	s := buf.String()
+	zr, err := NewReader(strings.NewReader(s), int64(len(s)))
+	if err != nil {
+		t.Fatalf("NewReader: %v", err)
+	}
+	if got := len(zr.File); got != nFiles {
+		t.Fatalf("File contains %d files, want %d", got, nFiles)
+	}
+	for i := 0; i < nFiles; i++ {
+		want := fmt.Sprintf("%d.dat", i)
+		if zr.File[i].Name != want {
+			t.Fatalf("File(%d) = %q, want %q", i, zr.File[i].Name, want)
+		}
+	}
+}
+
+func TestModTime(t *testing.T) {
+	var testTime = time.Date(2009, time.November, 10, 23, 45, 58, 0, time.UTC)
+	fh := new(FileHeader)
+	fh.SetModTime(testTime)
+	outTime := fh.ModTime()
+	if !outTime.Equal(testTime) {
+		t.Errorf("times don't match: got %s, want %s", outTime, testTime)
+	}
+}
+
+func testHeaderRoundTrip(fh *FileHeader, wantUncompressedSize uint32, wantUncompressedSize64 uint64, t *testing.T) {
+	fi := fh.FileInfo()
+	fh2, err := FileInfoHeader(fi)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got, want := fh2.Name, fh.Name; got != want {
+		t.Errorf("Name: got %s, want %s\n", got, want)
+	}
+	if got, want := fh2.UncompressedSize, wantUncompressedSize; got != want {
+		t.Errorf("UncompressedSize: got %d, want %d\n", got, want)
+	}
+	if got, want := fh2.UncompressedSize64, wantUncompressedSize64; got != want {
+		t.Errorf("UncompressedSize64: got %d, want %d\n", got, want)
+	}
+	if got, want := fh2.ModifiedTime, fh.ModifiedTime; got != want {
+		t.Errorf("ModifiedTime: got %d, want %d\n", got, want)
+	}
+	if got, want := fh2.ModifiedDate, fh.ModifiedDate; got != want {
+		t.Errorf("ModifiedDate: got %d, want %d\n", got, want)
+	}
+
+	if sysfh, ok := fi.Sys().(*FileHeader); !ok && sysfh != fh {
+		t.Errorf("Sys didn't return original *FileHeader")
+	}
+}
+
+func TestFileHeaderRoundTrip(t *testing.T) {
+	fh := &FileHeader{
+		Name:             "foo.txt",
+		UncompressedSize: 987654321,
+		ModifiedTime:     1234,
+		ModifiedDate:     5678,
+	}
+	testHeaderRoundTrip(fh, fh.UncompressedSize, uint64(fh.UncompressedSize), t)
+}
+
+func TestFileHeaderRoundTrip64(t *testing.T) {
+	fh := &FileHeader{
+		Name:               "foo.txt",
+		UncompressedSize64: 9876543210,
+		ModifiedTime:       1234,
+		ModifiedDate:       5678,
+	}
+	testHeaderRoundTrip(fh, uint32max, fh.UncompressedSize64, t)
+}
+
+type repeatedByte struct {
+	off int64
+	b   byte
+	n   int64
+}
+
+// rleBuffer is a run-length-encoded byte buffer.
+// It's an io.Writer (like a bytes.Buffer) and also an io.ReaderAt,
+// allowing random-access reads.
+type rleBuffer struct {
+	buf []repeatedByte
+}
+
+func (r *rleBuffer) Size() int64 {
+	if len(r.buf) == 0 {
+		return 0
+	}
+	last := &r.buf[len(r.buf)-1]
+	return last.off + last.n
+}
+
+func (r *rleBuffer) Write(p []byte) (n int, err error) {
+	var rp *repeatedByte
+	if len(r.buf) > 0 {
+		rp = &r.buf[len(r.buf)-1]
+		// Fast path, if p is entirely the same byte repeated.
+		if lastByte := rp.b; len(p) > 0 && p[0] == lastByte {
+			all := true
+			for _, b := range p {
+				if b != lastByte {
+					all = false
+					break
+				}
+			}
+			if all {
+				rp.n += int64(len(p))
+				return len(p), nil
+			}
+		}
+	}
+
+	for _, b := range p {
+		if rp == nil || rp.b != b {
+			r.buf = append(r.buf, repeatedByte{r.Size(), b, 1})
+			rp = &r.buf[len(r.buf)-1]
+		} else {
+			rp.n++
+		}
+	}
+	return len(p), nil
+}
+
+func (r *rleBuffer) ReadAt(p []byte, off int64) (n int, err error) {
+	if len(p) == 0 {
+		return
+	}
+	skipParts := sort.Search(len(r.buf), func(i int) bool {
+		part := &r.buf[i]
+		return part.off+part.n > off
+	})
+	parts := r.buf[skipParts:]
+	if len(parts) > 0 {
+		skipBytes := off - parts[0].off
+		for len(parts) > 0 {
+			part := parts[0]
+			for i := skipBytes; i < part.n; i++ {
+				if n == len(p) {
+					return
+				}
+				p[n] = part.b
+				n++
+			}
+			parts = parts[1:]
+			skipBytes = 0
+		}
+	}
+	if n != len(p) {
+		err = io.ErrUnexpectedEOF
+	}
+	return
+}
+
+// Just testing the rleBuffer used in the Zip64 test above. Not used by the zip code.
+func TestRLEBuffer(t *testing.T) {
+	b := new(rleBuffer)
+	var all []byte
+	writes := []string{"abcdeee", "eeeeeee", "eeeefghaaiii"}
+	for _, w := range writes {
+		b.Write([]byte(w))
+		all = append(all, w...)
+	}
+	if len(b.buf) != 10 {
+		t.Fatalf("len(b.buf) = %d; want 10", len(b.buf))
+	}
+
+	for i := 0; i < len(all); i++ {
+		for j := 0; j < len(all)-i; j++ {
+			buf := make([]byte, j)
+			n, err := b.ReadAt(buf, int64(i))
+			if err != nil || n != len(buf) {
+				t.Errorf("ReadAt(%d, %d) = %d, %v; want %d, nil", i, j, n, err, len(buf))
+			}
+			if !bytes.Equal(buf, all[i:i+j]) {
+				t.Errorf("ReadAt(%d, %d) = %q; want %q", i, j, buf, all[i:i+j])
+			}
+		}
+	}
+}
+
+// fakeHash32 is a dummy Hash32 that always returns 0.
+type fakeHash32 struct {
+	hash.Hash32
+}
+
+func (fakeHash32) Write(p []byte) (int, error) { return len(p), nil }
+func (fakeHash32) Sum32() uint32               { return 0 }
+
+func TestZip64(t *testing.T) {
+	if testing.Short() {
+		t.Skip("slow test; skipping")
+	}
+	const size = 1 << 32 // before the "END\n" part
+	testZip64(t, size)
+}
+
+func testZip64(t testing.TB, size int64) {
+	const chunkSize = 1024
+	chunks := int(size / chunkSize)
+	// write 2^32 bytes plus "END\n" to a zip file
+	buf := new(rleBuffer)
+	w := NewWriter(buf)
+	f, err := w.CreateHeader(&FileHeader{
+		Name:   "huge.txt",
+		Method: Store,
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+	f.(*fileWriter).crc32 = fakeHash32{}
+	chunk := make([]byte, chunkSize)
+	for i := range chunk {
+		chunk[i] = '.'
+	}
+	for i := 0; i < chunks; i++ {
+		_, err := f.Write(chunk)
+		if err != nil {
+			t.Fatal("write chunk:", err)
+		}
+	}
+	end := []byte("END\n")
+	_, err = f.Write(end)
+	if err != nil {
+		t.Fatal("write end:", err)
+	}
+	if err := w.Close(); err != nil {
+		t.Fatal(err)
+	}
+
+	// read back zip file and check that we get to the end of it
+	r, err := NewReader(buf, int64(buf.Size()))
+	if err != nil {
+		t.Fatal("reader:", err)
+	}
+	f0 := r.File[0]
+	rc, err := f0.Open()
+	if err != nil {
+		t.Fatal("opening:", err)
+	}
+	rc.(*checksumReader).hash = fakeHash32{}
+	for i := 0; i < chunks; i++ {
+		_, err := io.ReadFull(rc, chunk)
+		if err != nil {
+			t.Fatal("read:", err)
+		}
+	}
+	gotEnd, err := ioutil.ReadAll(rc)
+	if err != nil {
+		t.Fatal("read end:", err)
+	}
+	if !bytes.Equal(gotEnd, end) {
+		t.Errorf("End of zip64 archive %q, want %q", gotEnd, end)
+	}
+	err = rc.Close()
+	if err != nil {
+		t.Fatal("closing:", err)
+	}
+	if size == 1<<32 {
+		if got, want := f0.UncompressedSize, uint32(uint32max); got != want {
+			t.Errorf("UncompressedSize %d, want %d", got, want)
+		}
+	}
+
+	if got, want := f0.UncompressedSize64, uint64(size)+uint64(len(end)); got != want {
+		t.Errorf("UncompressedSize64 %d, want %d", got, want)
+	}
+}
+
+func testInvalidHeader(h *FileHeader, t *testing.T) {
+	var buf bytes.Buffer
+	z := NewWriter(&buf)
+
+	f, err := z.CreateHeader(h)
+	if err != nil {
+		t.Fatalf("error creating header: %v", err)
+	}
+	if _, err := f.Write([]byte("hi")); err != nil {
+		t.Fatalf("error writing content: %v", err)
+	}
+	if err := z.Close(); err != nil {
+		t.Fatalf("error closing zip writer: %v", err)
+	}
+
+	b := buf.Bytes()
+	if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != ErrFormat {
+		t.Fatalf("got %v, expected ErrFormat", err)
+	}
+}
+
+func testValidHeader(h *FileHeader, t *testing.T) {
+	var buf bytes.Buffer
+	z := NewWriter(&buf)
+
+	f, err := z.CreateHeader(h)
+	if err != nil {
+		t.Fatalf("error creating header: %v", err)
+	}
+	if _, err := f.Write([]byte("hi")); err != nil {
+		t.Fatalf("error writing content: %v", err)
+	}
+	if err := z.Close(); err != nil {
+		t.Fatalf("error closing zip writer: %v", err)
+	}
+
+	b := buf.Bytes()
+	if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != nil {
+		t.Fatalf("got %v, expected nil", err)
+	}
+}
+
+// Issue 4302.
+func TestHeaderInvalidTagAndSize(t *testing.T) {
+	const timeFormat = "20060102T150405.000.txt"
+
+	ts := time.Now()
+	filename := ts.Format(timeFormat)
+
+	h := FileHeader{
+		Name:   filename,
+		Method: Deflate,
+		Extra:  []byte(ts.Format(time.RFC3339Nano)), // missing tag and len
+	}
+	h.SetModTime(ts)
+
+	testInvalidHeader(&h, t)
+}
+
+func TestHeaderTooShort(t *testing.T) {
+	h := FileHeader{
+		Name:   "foo.txt",
+		Method: Deflate,
+		Extra:  []byte{zip64ExtraId}, // missing size
+	}
+	testInvalidHeader(&h, t)
+}
+
+// Issue 4393. It is valid to have an extra data header
+// which contains no body.
+func TestZeroLengthHeader(t *testing.T) {
+	h := FileHeader{
+		Name:   "extadata.txt",
+		Method: Deflate,
+		Extra: []byte{
+			85, 84, 5, 0, 3, 154, 144, 195, 77, // tag 21589 size 5
+			85, 120, 0, 0, // tag 30805 size 0
+		},
+	}
+	testValidHeader(&h, t)
+}
+
+// Just benchmarking how fast the Zip64 test above is. Not related to
+// our zip performance, since the test above disabled CRC32 and flate.
+func BenchmarkZip64Test(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		testZip64(b, 1<<26)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/bufio/bufio.go b/third_party/gofrontend/libgo/go/bufio/bufio.go
new file mode 100644
index 0000000..61ef261
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bufio/bufio.go
@@ -0,0 +1,698 @@
+// 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 bufio implements buffered I/O.  It wraps an io.Reader or io.Writer
+// object, creating another object (Reader or Writer) that also implements
+// the interface but provides buffering and some help for textual I/O.
+package bufio
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"unicode/utf8"
+)
+
+const (
+	defaultBufSize = 4096
+)
+
+var (
+	ErrInvalidUnreadByte = errors.New("bufio: invalid use of UnreadByte")
+	ErrInvalidUnreadRune = errors.New("bufio: invalid use of UnreadRune")
+	ErrBufferFull        = errors.New("bufio: buffer full")
+	ErrNegativeCount     = errors.New("bufio: negative count")
+)
+
+// Buffered input.
+
+// Reader implements buffering for an io.Reader object.
+type Reader struct {
+	buf          []byte
+	rd           io.Reader
+	r, w         int
+	err          error
+	lastByte     int
+	lastRuneSize int
+}
+
+const minReadBufferSize = 16
+const maxConsecutiveEmptyReads = 100
+
+// NewReaderSize returns a new Reader whose buffer has at least the specified
+// size. If the argument io.Reader is already a Reader with large enough
+// size, it returns the underlying Reader.
+func NewReaderSize(rd io.Reader, size int) *Reader {
+	// Is it already a Reader?
+	b, ok := rd.(*Reader)
+	if ok && len(b.buf) >= size {
+		return b
+	}
+	if size < minReadBufferSize {
+		size = minReadBufferSize
+	}
+	r := new(Reader)
+	r.reset(make([]byte, size), rd)
+	return r
+}
+
+// NewReader returns a new Reader whose buffer has the default size.
+func NewReader(rd io.Reader) *Reader {
+	return NewReaderSize(rd, defaultBufSize)
+}
+
+// Reset discards any buffered data, resets all state, and switches
+// the buffered reader to read from r.
+func (b *Reader) Reset(r io.Reader) {
+	b.reset(b.buf, r)
+}
+
+func (b *Reader) reset(buf []byte, r io.Reader) {
+	*b = Reader{
+		buf:          buf,
+		rd:           r,
+		lastByte:     -1,
+		lastRuneSize: -1,
+	}
+}
+
+var errNegativeRead = errors.New("bufio: reader returned negative count from Read")
+
+// fill reads a new chunk into the buffer.
+func (b *Reader) fill() {
+	// Slide existing data to beginning.
+	if b.r > 0 {
+		copy(b.buf, b.buf[b.r:b.w])
+		b.w -= b.r
+		b.r = 0
+	}
+
+	if b.w >= len(b.buf) {
+		panic("bufio: tried to fill full buffer")
+	}
+
+	// Read new data: try a limited number of times.
+	for i := maxConsecutiveEmptyReads; i > 0; i-- {
+		n, err := b.rd.Read(b.buf[b.w:])
+		if n < 0 {
+			panic(errNegativeRead)
+		}
+		b.w += n
+		if err != nil {
+			b.err = err
+			return
+		}
+		if n > 0 {
+			return
+		}
+	}
+	b.err = io.ErrNoProgress
+}
+
+func (b *Reader) readErr() error {
+	err := b.err
+	b.err = nil
+	return err
+}
+
+// Peek returns the next n bytes without advancing the reader. The bytes stop
+// being valid at the next read call. If Peek returns fewer than n bytes, it
+// also returns an error explaining why the read is short. The error is
+// ErrBufferFull if n is larger than b's buffer size.
+func (b *Reader) Peek(n int) ([]byte, error) {
+	if n < 0 {
+		return nil, ErrNegativeCount
+	}
+	if n > len(b.buf) {
+		return nil, ErrBufferFull
+	}
+	// 0 <= n <= len(b.buf)
+	for b.w-b.r < n && b.err == nil {
+		b.fill() // b.w-b.r < len(b.buf) => buffer is not full
+	}
+	m := b.w - b.r
+	if m > n {
+		m = n
+	}
+	var err error
+	if m < n {
+		err = b.readErr()
+		if err == nil {
+			err = ErrBufferFull
+		}
+	}
+	return b.buf[b.r : b.r+m], err
+}
+
+// Read reads data into p.
+// It returns the number of bytes read into p.
+// It calls Read at most once on the underlying Reader,
+// hence n may be less than len(p).
+// At EOF, the count will be zero and err will be io.EOF.
+func (b *Reader) Read(p []byte) (n int, err error) {
+	n = len(p)
+	if n == 0 {
+		return 0, b.readErr()
+	}
+	if b.r == b.w {
+		if b.err != nil {
+			return 0, b.readErr()
+		}
+		if len(p) >= len(b.buf) {
+			// Large read, empty buffer.
+			// Read directly into p to avoid copy.
+			n, b.err = b.rd.Read(p)
+			if n < 0 {
+				panic(errNegativeRead)
+			}
+			if n > 0 {
+				b.lastByte = int(p[n-1])
+				b.lastRuneSize = -1
+			}
+			return n, b.readErr()
+		}
+		b.fill() // buffer is empty
+		if b.w == b.r {
+			return 0, b.readErr()
+		}
+	}
+
+	if n > b.w-b.r {
+		n = b.w - b.r
+	}
+	copy(p[0:n], b.buf[b.r:])
+	b.r += n
+	b.lastByte = int(b.buf[b.r-1])
+	b.lastRuneSize = -1
+	return n, nil
+}
+
+// ReadByte reads and returns a single byte.
+// If no byte is available, returns an error.
+func (b *Reader) ReadByte() (c byte, err error) {
+	b.lastRuneSize = -1
+	for b.r == b.w {
+		if b.err != nil {
+			return 0, b.readErr()
+		}
+		b.fill() // buffer is empty
+	}
+	c = b.buf[b.r]
+	b.r++
+	b.lastByte = int(c)
+	return c, nil
+}
+
+// UnreadByte unreads the last byte.  Only the most recently read byte can be unread.
+func (b *Reader) UnreadByte() error {
+	if b.lastByte < 0 || b.r == 0 && b.w > 0 {
+		return ErrInvalidUnreadByte
+	}
+	// b.r > 0 || b.w == 0
+	if b.r > 0 {
+		b.r--
+	} else {
+		// b.r == 0 && b.w == 0
+		b.w = 1
+	}
+	b.buf[b.r] = byte(b.lastByte)
+	b.lastByte = -1
+	b.lastRuneSize = -1
+	return nil
+}
+
+// ReadRune reads a single UTF-8 encoded Unicode character and returns the
+// rune and its size in bytes. If the encoded rune is invalid, it consumes one byte
+// and returns unicode.ReplacementChar (U+FFFD) with a size of 1.
+func (b *Reader) ReadRune() (r rune, size int, err error) {
+	for b.r+utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r:b.w]) && b.err == nil && b.w-b.r < len(b.buf) {
+		b.fill() // b.w-b.r < len(buf) => buffer is not full
+	}
+	b.lastRuneSize = -1
+	if b.r == b.w {
+		return 0, 0, b.readErr()
+	}
+	r, size = rune(b.buf[b.r]), 1
+	if r >= 0x80 {
+		r, size = utf8.DecodeRune(b.buf[b.r:b.w])
+	}
+	b.r += size
+	b.lastByte = int(b.buf[b.r-1])
+	b.lastRuneSize = size
+	return r, size, nil
+}
+
+// UnreadRune unreads the last rune.  If the most recent read operation on
+// the buffer was not a ReadRune, UnreadRune returns an error.  (In this
+// regard it is stricter than UnreadByte, which will unread the last byte
+// from any read operation.)
+func (b *Reader) UnreadRune() error {
+	if b.lastRuneSize < 0 || b.r < b.lastRuneSize {
+		return ErrInvalidUnreadRune
+	}
+	b.r -= b.lastRuneSize
+	b.lastByte = -1
+	b.lastRuneSize = -1
+	return nil
+}
+
+// Buffered returns the number of bytes that can be read from the current buffer.
+func (b *Reader) Buffered() int { return b.w - b.r }
+
+// ReadSlice reads until the first occurrence of delim in the input,
+// returning a slice pointing at the bytes in the buffer.
+// The bytes stop being valid at the next read.
+// If ReadSlice encounters an error before finding a delimiter,
+// it returns all the data in the buffer and the error itself (often io.EOF).
+// ReadSlice fails with error ErrBufferFull if the buffer fills without a delim.
+// Because the data returned from ReadSlice will be overwritten
+// by the next I/O operation, most clients should use
+// ReadBytes or ReadString instead.
+// ReadSlice returns err != nil if and only if line does not end in delim.
+func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
+	for {
+		// Search buffer.
+		if i := bytes.IndexByte(b.buf[b.r:b.w], delim); i >= 0 {
+			line = b.buf[b.r : b.r+i+1]
+			b.r += i + 1
+			break
+		}
+
+		// Pending error?
+		if b.err != nil {
+			line = b.buf[b.r:b.w]
+			b.r = b.w
+			err = b.readErr()
+			break
+		}
+
+		// Buffer full?
+		if n := b.Buffered(); n >= len(b.buf) {
+			b.r = b.w
+			line = b.buf
+			err = ErrBufferFull
+			break
+		}
+
+		b.fill() // buffer is not full
+	}
+
+	// Handle last byte, if any.
+	if i := len(line) - 1; i >= 0 {
+		b.lastByte = int(line[i])
+	}
+
+	return
+}
+
+// ReadLine is a low-level line-reading primitive. Most callers should use
+// ReadBytes('\n') or ReadString('\n') instead or use a Scanner.
+//
+// ReadLine tries to return a single line, not including the end-of-line bytes.
+// If the line was too long for the buffer then isPrefix is set and the
+// beginning of the line is returned. The rest of the line will be returned
+// from future calls. isPrefix will be false when returning the last fragment
+// of the line. The returned buffer is only valid until the next call to
+// ReadLine. ReadLine either returns a non-nil line or it returns an error,
+// never both.
+//
+// The text returned from ReadLine does not include the line end ("\r\n" or "\n").
+// No indication or error is given if the input ends without a final line end.
+// Calling UnreadByte after ReadLine will always unread the last byte read
+// (possibly a character belonging to the line end) even if that byte is not
+// part of the line returned by ReadLine.
+func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) {
+	line, err = b.ReadSlice('\n')
+	if err == ErrBufferFull {
+		// Handle the case where "\r\n" straddles the buffer.
+		if len(line) > 0 && line[len(line)-1] == '\r' {
+			// Put the '\r' back on buf and drop it from line.
+			// Let the next call to ReadLine check for "\r\n".
+			if b.r == 0 {
+				// should be unreachable
+				panic("bufio: tried to rewind past start of buffer")
+			}
+			b.r--
+			line = line[:len(line)-1]
+		}
+		return line, true, nil
+	}
+
+	if len(line) == 0 {
+		if err != nil {
+			line = nil
+		}
+		return
+	}
+	err = nil
+
+	if line[len(line)-1] == '\n' {
+		drop := 1
+		if len(line) > 1 && line[len(line)-2] == '\r' {
+			drop = 2
+		}
+		line = line[:len(line)-drop]
+	}
+	return
+}
+
+// ReadBytes reads until the first occurrence of delim in the input,
+// returning a slice containing the data up to and including the delimiter.
+// If ReadBytes encounters an error before finding a delimiter,
+// it returns the data read before the error and the error itself (often io.EOF).
+// ReadBytes returns err != nil if and only if the returned data does not end in
+// delim.
+// For simple uses, a Scanner may be more convenient.
+func (b *Reader) ReadBytes(delim byte) (line []byte, err error) {
+	// Use ReadSlice to look for array,
+	// accumulating full buffers.
+	var frag []byte
+	var full [][]byte
+	err = nil
+
+	for {
+		var e error
+		frag, e = b.ReadSlice(delim)
+		if e == nil { // got final fragment
+			break
+		}
+		if e != ErrBufferFull { // unexpected error
+			err = e
+			break
+		}
+
+		// Make a copy of the buffer.
+		buf := make([]byte, len(frag))
+		copy(buf, frag)
+		full = append(full, buf)
+	}
+
+	// Allocate new buffer to hold the full pieces and the fragment.
+	n := 0
+	for i := range full {
+		n += len(full[i])
+	}
+	n += len(frag)
+
+	// Copy full pieces and fragment in.
+	buf := make([]byte, n)
+	n = 0
+	for i := range full {
+		n += copy(buf[n:], full[i])
+	}
+	copy(buf[n:], frag)
+	return buf, err
+}
+
+// ReadString reads until the first occurrence of delim in the input,
+// returning a string containing the data up to and including the delimiter.
+// If ReadString encounters an error before finding a delimiter,
+// it returns the data read before the error and the error itself (often io.EOF).
+// ReadString returns err != nil if and only if the returned data does not end in
+// delim.
+// For simple uses, a Scanner may be more convenient.
+func (b *Reader) ReadString(delim byte) (line string, err error) {
+	bytes, err := b.ReadBytes(delim)
+	line = string(bytes)
+	return line, err
+}
+
+// WriteTo implements io.WriterTo.
+func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
+	n, err = b.writeBuf(w)
+	if err != nil {
+		return
+	}
+
+	if r, ok := b.rd.(io.WriterTo); ok {
+		m, err := r.WriteTo(w)
+		n += m
+		return n, err
+	}
+
+	if w, ok := w.(io.ReaderFrom); ok {
+		m, err := w.ReadFrom(b.rd)
+		n += m
+		return n, err
+	}
+
+	if b.w-b.r < len(b.buf) {
+		b.fill() // buffer not full
+	}
+
+	for b.r < b.w {
+		// b.r < b.w => buffer is not empty
+		m, err := b.writeBuf(w)
+		n += m
+		if err != nil {
+			return n, err
+		}
+		b.fill() // buffer is empty
+	}
+
+	if b.err == io.EOF {
+		b.err = nil
+	}
+
+	return n, b.readErr()
+}
+
+// writeBuf writes the Reader's buffer to the writer.
+func (b *Reader) writeBuf(w io.Writer) (int64, error) {
+	n, err := w.Write(b.buf[b.r:b.w])
+	if n < b.r-b.w {
+		panic(errors.New("bufio: writer did not write all data"))
+	}
+	b.r += n
+	return int64(n), err
+}
+
+// buffered output
+
+// Writer implements buffering for an io.Writer object.
+// If an error occurs writing to a Writer, no more data will be
+// accepted and all subsequent writes will return the error.
+// After all data has been written, the client should call the
+// Flush method to guarantee all data has been forwarded to
+// the underlying io.Writer.
+type Writer struct {
+	err error
+	buf []byte
+	n   int
+	wr  io.Writer
+}
+
+// NewWriterSize returns a new Writer whose buffer has at least the specified
+// size. If the argument io.Writer is already a Writer with large enough
+// size, it returns the underlying Writer.
+func NewWriterSize(w io.Writer, size int) *Writer {
+	// Is it already a Writer?
+	b, ok := w.(*Writer)
+	if ok && len(b.buf) >= size {
+		return b
+	}
+	if size <= 0 {
+		size = defaultBufSize
+	}
+	return &Writer{
+		buf: make([]byte, size),
+		wr:  w,
+	}
+}
+
+// NewWriter returns a new Writer whose buffer has the default size.
+func NewWriter(w io.Writer) *Writer {
+	return NewWriterSize(w, defaultBufSize)
+}
+
+// Reset discards any unflushed buffered data, clears any error, and
+// resets b to write its output to w.
+func (b *Writer) Reset(w io.Writer) {
+	b.err = nil
+	b.n = 0
+	b.wr = w
+}
+
+// Flush writes any buffered data to the underlying io.Writer.
+func (b *Writer) Flush() error {
+	err := b.flush()
+	return err
+}
+
+func (b *Writer) flush() error {
+	if b.err != nil {
+		return b.err
+	}
+	if b.n == 0 {
+		return nil
+	}
+	n, err := b.wr.Write(b.buf[0:b.n])
+	if n < b.n && err == nil {
+		err = io.ErrShortWrite
+	}
+	if err != nil {
+		if n > 0 && n < b.n {
+			copy(b.buf[0:b.n-n], b.buf[n:b.n])
+		}
+		b.n -= n
+		b.err = err
+		return err
+	}
+	b.n = 0
+	return nil
+}
+
+// Available returns how many bytes are unused in the buffer.
+func (b *Writer) Available() int { return len(b.buf) - b.n }
+
+// Buffered returns the number of bytes that have been written into the current buffer.
+func (b *Writer) Buffered() int { return b.n }
+
+// Write writes the contents of p into the buffer.
+// It returns the number of bytes written.
+// If nn < len(p), it also returns an error explaining
+// why the write is short.
+func (b *Writer) Write(p []byte) (nn int, err error) {
+	for len(p) > b.Available() && b.err == nil {
+		var n int
+		if b.Buffered() == 0 {
+			// Large write, empty buffer.
+			// Write directly from p to avoid copy.
+			n, b.err = b.wr.Write(p)
+		} else {
+			n = copy(b.buf[b.n:], p)
+			b.n += n
+			b.flush()
+		}
+		nn += n
+		p = p[n:]
+	}
+	if b.err != nil {
+		return nn, b.err
+	}
+	n := copy(b.buf[b.n:], p)
+	b.n += n
+	nn += n
+	return nn, nil
+}
+
+// WriteByte writes a single byte.
+func (b *Writer) WriteByte(c byte) error {
+	if b.err != nil {
+		return b.err
+	}
+	if b.Available() <= 0 && b.flush() != nil {
+		return b.err
+	}
+	b.buf[b.n] = c
+	b.n++
+	return nil
+}
+
+// WriteRune writes a single Unicode code point, returning
+// the number of bytes written and any error.
+func (b *Writer) WriteRune(r rune) (size int, err error) {
+	if r < utf8.RuneSelf {
+		err = b.WriteByte(byte(r))
+		if err != nil {
+			return 0, err
+		}
+		return 1, nil
+	}
+	if b.err != nil {
+		return 0, b.err
+	}
+	n := b.Available()
+	if n < utf8.UTFMax {
+		if b.flush(); b.err != nil {
+			return 0, b.err
+		}
+		n = b.Available()
+		if n < utf8.UTFMax {
+			// Can only happen if buffer is silly small.
+			return b.WriteString(string(r))
+		}
+	}
+	size = utf8.EncodeRune(b.buf[b.n:], r)
+	b.n += size
+	return size, nil
+}
+
+// WriteString writes a string.
+// It returns the number of bytes written.
+// If the count is less than len(s), it also returns an error explaining
+// why the write is short.
+func (b *Writer) WriteString(s string) (int, error) {
+	nn := 0
+	for len(s) > b.Available() && b.err == nil {
+		n := copy(b.buf[b.n:], s)
+		b.n += n
+		nn += n
+		s = s[n:]
+		b.flush()
+	}
+	if b.err != nil {
+		return nn, b.err
+	}
+	n := copy(b.buf[b.n:], s)
+	b.n += n
+	nn += n
+	return nn, nil
+}
+
+// ReadFrom implements io.ReaderFrom.
+func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
+	if b.Buffered() == 0 {
+		if w, ok := b.wr.(io.ReaderFrom); ok {
+			return w.ReadFrom(r)
+		}
+	}
+	var m int
+	for {
+		if b.Available() == 0 {
+			if err1 := b.flush(); err1 != nil {
+				return n, err1
+			}
+		}
+		nr := 0
+		for nr < maxConsecutiveEmptyReads {
+			m, err = r.Read(b.buf[b.n:])
+			if m != 0 || err != nil {
+				break
+			}
+			nr++
+		}
+		if nr == maxConsecutiveEmptyReads {
+			return n, io.ErrNoProgress
+		}
+		b.n += m
+		n += int64(m)
+		if err != nil {
+			break
+		}
+	}
+	if err == io.EOF {
+		// If we filled the buffer exactly, flush pre-emptively.
+		if b.Available() == 0 {
+			err = b.flush()
+		} else {
+			err = nil
+		}
+	}
+	return n, err
+}
+
+// buffered input and output
+
+// ReadWriter stores pointers to a Reader and a Writer.
+// It implements io.ReadWriter.
+type ReadWriter struct {
+	*Reader
+	*Writer
+}
+
+// NewReadWriter allocates a new ReadWriter that dispatches to r and w.
+func NewReadWriter(r *Reader, w *Writer) *ReadWriter {
+	return &ReadWriter{r, w}
+}
diff --git a/third_party/gofrontend/libgo/go/bufio/bufio_test.go b/third_party/gofrontend/libgo/go/bufio/bufio_test.go
new file mode 100644
index 0000000..76d3c8e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bufio/bufio_test.go
@@ -0,0 +1,1417 @@
+// 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 bufio_test
+
+import (
+	. "bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"strings"
+	"testing"
+	"testing/iotest"
+	"time"
+	"unicode/utf8"
+)
+
+// Reads from a reader and rot13s the result.
+type rot13Reader struct {
+	r io.Reader
+}
+
+func newRot13Reader(r io.Reader) *rot13Reader {
+	r13 := new(rot13Reader)
+	r13.r = r
+	return r13
+}
+
+func (r13 *rot13Reader) Read(p []byte) (int, error) {
+	n, err := r13.r.Read(p)
+	if err != nil {
+		return n, err
+	}
+	for i := 0; i < n; i++ {
+		c := p[i] | 0x20 // lowercase byte
+		if 'a' <= c && c <= 'm' {
+			p[i] += 13
+		} else if 'n' <= c && c <= 'z' {
+			p[i] -= 13
+		}
+	}
+	return n, nil
+}
+
+// Call ReadByte to accumulate the text of a file
+func readBytes(buf *Reader) string {
+	var b [1000]byte
+	nb := 0
+	for {
+		c, err := buf.ReadByte()
+		if err == io.EOF {
+			break
+		}
+		if err == nil {
+			b[nb] = c
+			nb++
+		} else if err != iotest.ErrTimeout {
+			panic("Data: " + err.Error())
+		}
+	}
+	return string(b[0:nb])
+}
+
+func TestReaderSimple(t *testing.T) {
+	data := "hello world"
+	b := NewReader(strings.NewReader(data))
+	if s := readBytes(b); s != "hello world" {
+		t.Errorf("simple hello world test failed: got %q", s)
+	}
+
+	b = NewReader(newRot13Reader(strings.NewReader(data)))
+	if s := readBytes(b); s != "uryyb jbeyq" {
+		t.Errorf("rot13 hello world test failed: got %q", s)
+	}
+}
+
+type readMaker struct {
+	name string
+	fn   func(io.Reader) io.Reader
+}
+
+var readMakers = []readMaker{
+	{"full", func(r io.Reader) io.Reader { return r }},
+	{"byte", iotest.OneByteReader},
+	{"half", iotest.HalfReader},
+	{"data+err", iotest.DataErrReader},
+	{"timeout", iotest.TimeoutReader},
+}
+
+// Call ReadString (which ends up calling everything else)
+// to accumulate the text of a file.
+func readLines(b *Reader) string {
+	s := ""
+	for {
+		s1, err := b.ReadString('\n')
+		if err == io.EOF {
+			break
+		}
+		if err != nil && err != iotest.ErrTimeout {
+			panic("GetLines: " + err.Error())
+		}
+		s += s1
+	}
+	return s
+}
+
+// Call Read to accumulate the text of a file
+func reads(buf *Reader, m int) string {
+	var b [1000]byte
+	nb := 0
+	for {
+		n, err := buf.Read(b[nb : nb+m])
+		nb += n
+		if err == io.EOF {
+			break
+		}
+	}
+	return string(b[0:nb])
+}
+
+type bufReader struct {
+	name string
+	fn   func(*Reader) string
+}
+
+var bufreaders = []bufReader{
+	{"1", func(b *Reader) string { return reads(b, 1) }},
+	{"2", func(b *Reader) string { return reads(b, 2) }},
+	{"3", func(b *Reader) string { return reads(b, 3) }},
+	{"4", func(b *Reader) string { return reads(b, 4) }},
+	{"5", func(b *Reader) string { return reads(b, 5) }},
+	{"7", func(b *Reader) string { return reads(b, 7) }},
+	{"bytes", readBytes},
+	{"lines", readLines},
+}
+
+const minReadBufferSize = 16
+
+var bufsizes = []int{
+	0, minReadBufferSize, 23, 32, 46, 64, 93, 128, 1024, 4096,
+}
+
+func TestReader(t *testing.T) {
+	var texts [31]string
+	str := ""
+	all := ""
+	for i := 0; i < len(texts)-1; i++ {
+		texts[i] = str + "\n"
+		all += texts[i]
+		str += string(i%26 + 'a')
+	}
+	texts[len(texts)-1] = all
+
+	for h := 0; h < len(texts); h++ {
+		text := texts[h]
+		for i := 0; i < len(readMakers); i++ {
+			for j := 0; j < len(bufreaders); j++ {
+				for k := 0; k < len(bufsizes); k++ {
+					readmaker := readMakers[i]
+					bufreader := bufreaders[j]
+					bufsize := bufsizes[k]
+					read := readmaker.fn(strings.NewReader(text))
+					buf := NewReaderSize(read, bufsize)
+					s := bufreader.fn(buf)
+					if s != text {
+						t.Errorf("reader=%s fn=%s bufsize=%d want=%q got=%q",
+							readmaker.name, bufreader.name, bufsize, text, s)
+					}
+				}
+			}
+		}
+	}
+}
+
+type zeroReader struct{}
+
+func (zeroReader) Read(p []byte) (int, error) {
+	return 0, nil
+}
+
+func TestZeroReader(t *testing.T) {
+	var z zeroReader
+	r := NewReader(z)
+
+	c := make(chan error)
+	go func() {
+		_, err := r.ReadByte()
+		c <- err
+	}()
+
+	select {
+	case err := <-c:
+		if err == nil {
+			t.Error("error expected")
+		} else if err != io.ErrNoProgress {
+			t.Error("unexpected error:", err)
+		}
+	case <-time.After(time.Second):
+		t.Error("test timed out (endless loop in ReadByte?)")
+	}
+}
+
+// A StringReader delivers its data one string segment at a time via Read.
+type StringReader struct {
+	data []string
+	step int
+}
+
+func (r *StringReader) Read(p []byte) (n int, err error) {
+	if r.step < len(r.data) {
+		s := r.data[r.step]
+		n = copy(p, s)
+		r.step++
+	} else {
+		err = io.EOF
+	}
+	return
+}
+
+func readRuneSegments(t *testing.T, segments []string) {
+	got := ""
+	want := strings.Join(segments, "")
+	r := NewReader(&StringReader{data: segments})
+	for {
+		r, _, err := r.ReadRune()
+		if err != nil {
+			if err != io.EOF {
+				return
+			}
+			break
+		}
+		got += string(r)
+	}
+	if got != want {
+		t.Errorf("segments=%v got=%s want=%s", segments, got, want)
+	}
+}
+
+var segmentList = [][]string{
+	{},
+	{""},
+	{"日", "本語"},
+	{"\u65e5", "\u672c", "\u8a9e"},
+	{"\U000065e5", "\U0000672c", "\U00008a9e"},
+	{"\xe6", "\x97\xa5\xe6", "\x9c\xac\xe8\xaa\x9e"},
+	{"Hello", ", ", "World", "!"},
+	{"Hello", ", ", "", "World", "!"},
+}
+
+func TestReadRune(t *testing.T) {
+	for _, s := range segmentList {
+		readRuneSegments(t, s)
+	}
+}
+
+func TestUnreadRune(t *testing.T) {
+	segments := []string{"Hello, world:", "日本語"}
+	r := NewReader(&StringReader{data: segments})
+	got := ""
+	want := strings.Join(segments, "")
+	// Normal execution.
+	for {
+		r1, _, err := r.ReadRune()
+		if err != nil {
+			if err != io.EOF {
+				t.Error("unexpected error on ReadRune:", err)
+			}
+			break
+		}
+		got += string(r1)
+		// Put it back and read it again.
+		if err = r.UnreadRune(); err != nil {
+			t.Fatal("unexpected error on UnreadRune:", err)
+		}
+		r2, _, err := r.ReadRune()
+		if err != nil {
+			t.Fatal("unexpected error reading after unreading:", err)
+		}
+		if r1 != r2 {
+			t.Fatalf("incorrect rune after unread: got %c, want %c", r1, r2)
+		}
+	}
+	if got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
+
+func TestUnreadByte(t *testing.T) {
+	segments := []string{"Hello, ", "world"}
+	r := NewReader(&StringReader{data: segments})
+	got := ""
+	want := strings.Join(segments, "")
+	// Normal execution.
+	for {
+		b1, err := r.ReadByte()
+		if err != nil {
+			if err != io.EOF {
+				t.Error("unexpected error on ReadByte:", err)
+			}
+			break
+		}
+		got += string(b1)
+		// Put it back and read it again.
+		if err = r.UnreadByte(); err != nil {
+			t.Fatal("unexpected error on UnreadByte:", err)
+		}
+		b2, err := r.ReadByte()
+		if err != nil {
+			t.Fatal("unexpected error reading after unreading:", err)
+		}
+		if b1 != b2 {
+			t.Fatalf("incorrect byte after unread: got %q, want %q", b1, b2)
+		}
+	}
+	if got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
+
+func TestUnreadByteMultiple(t *testing.T) {
+	segments := []string{"Hello, ", "world"}
+	data := strings.Join(segments, "")
+	for n := 0; n <= len(data); n++ {
+		r := NewReader(&StringReader{data: segments})
+		// Read n bytes.
+		for i := 0; i < n; i++ {
+			b, err := r.ReadByte()
+			if err != nil {
+				t.Fatalf("n = %d: unexpected error on ReadByte: %v", n, err)
+			}
+			if b != data[i] {
+				t.Fatalf("n = %d: incorrect byte returned from ReadByte: got %q, want %q", n, b, data[i])
+			}
+		}
+		// Unread one byte if there is one.
+		if n > 0 {
+			if err := r.UnreadByte(); err != nil {
+				t.Errorf("n = %d: unexpected error on UnreadByte: %v", n, err)
+			}
+		}
+		// Test that we cannot unread any further.
+		if err := r.UnreadByte(); err == nil {
+			t.Errorf("n = %d: expected error on UnreadByte", n)
+		}
+	}
+}
+
+func TestUnreadByteOthers(t *testing.T) {
+	// A list of readers to use in conjunction with UnreadByte.
+	var readers = []func(*Reader, byte) ([]byte, error){
+		(*Reader).ReadBytes,
+		(*Reader).ReadSlice,
+		func(r *Reader, delim byte) ([]byte, error) {
+			data, err := r.ReadString(delim)
+			return []byte(data), err
+		},
+		// ReadLine doesn't fit the data/pattern easily
+		// so we leave it out. It should be covered via
+		// the ReadSlice test since ReadLine simply calls
+		// ReadSlice, and it's that function that handles
+		// the last byte.
+	}
+
+	// Try all readers with UnreadByte.
+	for rno, read := range readers {
+		// Some input data that is longer than the minimum reader buffer size.
+		const n = 10
+		var buf bytes.Buffer
+		for i := 0; i < n; i++ {
+			buf.WriteString("abcdefg")
+		}
+
+		r := NewReaderSize(&buf, minReadBufferSize)
+		readTo := func(delim byte, want string) {
+			data, err := read(r, delim)
+			if err != nil {
+				t.Fatalf("#%d: unexpected error reading to %c: %v", rno, delim, err)
+			}
+			if got := string(data); got != want {
+				t.Fatalf("#%d: got %q, want %q", rno, got, want)
+			}
+		}
+
+		// Read the data with occasional UnreadByte calls.
+		for i := 0; i < n; i++ {
+			readTo('d', "abcd")
+			for j := 0; j < 3; j++ {
+				if err := r.UnreadByte(); err != nil {
+					t.Fatalf("#%d: unexpected error on UnreadByte: %v", rno, err)
+				}
+				readTo('d', "d")
+			}
+			readTo('g', "efg")
+		}
+
+		// All data should have been read.
+		_, err := r.ReadByte()
+		if err != io.EOF {
+			t.Errorf("#%d: got error %v; want EOF", rno, err)
+		}
+	}
+}
+
+// Test that UnreadRune fails if the preceding operation was not a ReadRune.
+func TestUnreadRuneError(t *testing.T) {
+	buf := make([]byte, 3) // All runes in this test are 3 bytes long
+	r := NewReader(&StringReader{data: []string{"日本語日本語日本語"}})
+	if r.UnreadRune() == nil {
+		t.Error("expected error on UnreadRune from fresh buffer")
+	}
+	_, _, err := r.ReadRune()
+	if err != nil {
+		t.Error("unexpected error on ReadRune (1):", err)
+	}
+	if err = r.UnreadRune(); err != nil {
+		t.Error("unexpected error on UnreadRune (1):", err)
+	}
+	if r.UnreadRune() == nil {
+		t.Error("expected error after UnreadRune (1)")
+	}
+	// Test error after Read.
+	_, _, err = r.ReadRune() // reset state
+	if err != nil {
+		t.Error("unexpected error on ReadRune (2):", err)
+	}
+	_, err = r.Read(buf)
+	if err != nil {
+		t.Error("unexpected error on Read (2):", err)
+	}
+	if r.UnreadRune() == nil {
+		t.Error("expected error after Read (2)")
+	}
+	// Test error after ReadByte.
+	_, _, err = r.ReadRune() // reset state
+	if err != nil {
+		t.Error("unexpected error on ReadRune (2):", err)
+	}
+	for _ = range buf {
+		_, err = r.ReadByte()
+		if err != nil {
+			t.Error("unexpected error on ReadByte (2):", err)
+		}
+	}
+	if r.UnreadRune() == nil {
+		t.Error("expected error after ReadByte")
+	}
+	// Test error after UnreadByte.
+	_, _, err = r.ReadRune() // reset state
+	if err != nil {
+		t.Error("unexpected error on ReadRune (3):", err)
+	}
+	_, err = r.ReadByte()
+	if err != nil {
+		t.Error("unexpected error on ReadByte (3):", err)
+	}
+	err = r.UnreadByte()
+	if err != nil {
+		t.Error("unexpected error on UnreadByte (3):", err)
+	}
+	if r.UnreadRune() == nil {
+		t.Error("expected error after UnreadByte (3)")
+	}
+}
+
+func TestUnreadRuneAtEOF(t *testing.T) {
+	// UnreadRune/ReadRune should error at EOF (was a bug; used to panic)
+	r := NewReader(strings.NewReader("x"))
+	r.ReadRune()
+	r.ReadRune()
+	r.UnreadRune()
+	_, _, err := r.ReadRune()
+	if err == nil {
+		t.Error("expected error at EOF")
+	} else if err != io.EOF {
+		t.Error("expected EOF; got", err)
+	}
+}
+
+func TestReadWriteRune(t *testing.T) {
+	const NRune = 1000
+	byteBuf := new(bytes.Buffer)
+	w := NewWriter(byteBuf)
+	// Write the runes out using WriteRune
+	buf := make([]byte, utf8.UTFMax)
+	for r := rune(0); r < NRune; r++ {
+		size := utf8.EncodeRune(buf, r)
+		nbytes, err := w.WriteRune(r)
+		if err != nil {
+			t.Fatalf("WriteRune(0x%x) error: %s", r, err)
+		}
+		if nbytes != size {
+			t.Fatalf("WriteRune(0x%x) expected %d, got %d", r, size, nbytes)
+		}
+	}
+	w.Flush()
+
+	r := NewReader(byteBuf)
+	// Read them back with ReadRune
+	for r1 := rune(0); r1 < NRune; r1++ {
+		size := utf8.EncodeRune(buf, r1)
+		nr, nbytes, err := r.ReadRune()
+		if nr != r1 || nbytes != size || err != nil {
+			t.Fatalf("ReadRune(0x%x) got 0x%x,%d not 0x%x,%d (err=%s)", r1, nr, nbytes, r1, size, err)
+		}
+	}
+}
+
+func TestWriter(t *testing.T) {
+	var data [8192]byte
+
+	for i := 0; i < len(data); i++ {
+		data[i] = byte(' ' + i%('~'-' '))
+	}
+	w := new(bytes.Buffer)
+	for i := 0; i < len(bufsizes); i++ {
+		for j := 0; j < len(bufsizes); j++ {
+			nwrite := bufsizes[i]
+			bs := bufsizes[j]
+
+			// Write nwrite bytes using buffer size bs.
+			// Check that the right amount makes it out
+			// and that the data is correct.
+
+			w.Reset()
+			buf := NewWriterSize(w, bs)
+			context := fmt.Sprintf("nwrite=%d bufsize=%d", nwrite, bs)
+			n, e1 := buf.Write(data[0:nwrite])
+			if e1 != nil || n != nwrite {
+				t.Errorf("%s: buf.Write %d = %d, %v", context, nwrite, n, e1)
+				continue
+			}
+			if e := buf.Flush(); e != nil {
+				t.Errorf("%s: buf.Flush = %v", context, e)
+			}
+
+			written := w.Bytes()
+			if len(written) != nwrite {
+				t.Errorf("%s: %d bytes written", context, len(written))
+			}
+			for l := 0; l < len(written); l++ {
+				if written[i] != data[i] {
+					t.Errorf("wrong bytes written")
+					t.Errorf("want=%q", data[0:len(written)])
+					t.Errorf("have=%q", written)
+				}
+			}
+		}
+	}
+}
+
+// Check that write errors are returned properly.
+
+type errorWriterTest struct {
+	n, m   int
+	err    error
+	expect error
+}
+
+func (w errorWriterTest) Write(p []byte) (int, error) {
+	return len(p) * w.n / w.m, w.err
+}
+
+var errorWriterTests = []errorWriterTest{
+	{0, 1, nil, io.ErrShortWrite},
+	{1, 2, nil, io.ErrShortWrite},
+	{1, 1, nil, nil},
+	{0, 1, io.ErrClosedPipe, io.ErrClosedPipe},
+	{1, 2, io.ErrClosedPipe, io.ErrClosedPipe},
+	{1, 1, io.ErrClosedPipe, io.ErrClosedPipe},
+}
+
+func TestWriteErrors(t *testing.T) {
+	for _, w := range errorWriterTests {
+		buf := NewWriter(w)
+		_, e := buf.Write([]byte("hello world"))
+		if e != nil {
+			t.Errorf("Write hello to %v: %v", w, e)
+			continue
+		}
+		// Two flushes, to verify the error is sticky.
+		for i := 0; i < 2; i++ {
+			e = buf.Flush()
+			if e != w.expect {
+				t.Errorf("Flush %d/2 %v: got %v, wanted %v", i+1, w, e, w.expect)
+			}
+		}
+	}
+}
+
+func TestNewReaderSizeIdempotent(t *testing.T) {
+	const BufSize = 1000
+	b := NewReaderSize(strings.NewReader("hello world"), BufSize)
+	// Does it recognize itself?
+	b1 := NewReaderSize(b, BufSize)
+	if b1 != b {
+		t.Error("NewReaderSize did not detect underlying Reader")
+	}
+	// Does it wrap if existing buffer is too small?
+	b2 := NewReaderSize(b, 2*BufSize)
+	if b2 == b {
+		t.Error("NewReaderSize did not enlarge buffer")
+	}
+}
+
+func TestNewWriterSizeIdempotent(t *testing.T) {
+	const BufSize = 1000
+	b := NewWriterSize(new(bytes.Buffer), BufSize)
+	// Does it recognize itself?
+	b1 := NewWriterSize(b, BufSize)
+	if b1 != b {
+		t.Error("NewWriterSize did not detect underlying Writer")
+	}
+	// Does it wrap if existing buffer is too small?
+	b2 := NewWriterSize(b, 2*BufSize)
+	if b2 == b {
+		t.Error("NewWriterSize did not enlarge buffer")
+	}
+}
+
+func TestWriteString(t *testing.T) {
+	const BufSize = 8
+	buf := new(bytes.Buffer)
+	b := NewWriterSize(buf, BufSize)
+	b.WriteString("0")                         // easy
+	b.WriteString("123456")                    // still easy
+	b.WriteString("7890")                      // easy after flush
+	b.WriteString("abcdefghijklmnopqrstuvwxy") // hard
+	b.WriteString("z")
+	if err := b.Flush(); err != nil {
+		t.Error("WriteString", err)
+	}
+	s := "01234567890abcdefghijklmnopqrstuvwxyz"
+	if string(buf.Bytes()) != s {
+		t.Errorf("WriteString wants %q gets %q", s, string(buf.Bytes()))
+	}
+}
+
+func TestBufferFull(t *testing.T) {
+	const longString = "And now, hello, world! It is the time for all good men to come to the aid of their party"
+	buf := NewReaderSize(strings.NewReader(longString), minReadBufferSize)
+	line, err := buf.ReadSlice('!')
+	if string(line) != "And now, hello, " || err != ErrBufferFull {
+		t.Errorf("first ReadSlice(,) = %q, %v", line, err)
+	}
+	line, err = buf.ReadSlice('!')
+	if string(line) != "world!" || err != nil {
+		t.Errorf("second ReadSlice(,) = %q, %v", line, err)
+	}
+}
+
+func TestPeek(t *testing.T) {
+	p := make([]byte, 10)
+	// string is 16 (minReadBufferSize) long.
+	buf := NewReaderSize(strings.NewReader("abcdefghijklmnop"), minReadBufferSize)
+	if s, err := buf.Peek(1); string(s) != "a" || err != nil {
+		t.Fatalf("want %q got %q, err=%v", "a", string(s), err)
+	}
+	if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {
+		t.Fatalf("want %q got %q, err=%v", "abcd", string(s), err)
+	}
+	if _, err := buf.Peek(-1); err != ErrNegativeCount {
+		t.Fatalf("want ErrNegativeCount got %v", err)
+	}
+	if _, err := buf.Peek(32); err != ErrBufferFull {
+		t.Fatalf("want ErrBufFull got %v", err)
+	}
+	if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil {
+		t.Fatalf("want %q got %q, err=%v", "abc", string(p[0:3]), err)
+	}
+	if s, err := buf.Peek(1); string(s) != "d" || err != nil {
+		t.Fatalf("want %q got %q, err=%v", "d", string(s), err)
+	}
+	if s, err := buf.Peek(2); string(s) != "de" || err != nil {
+		t.Fatalf("want %q got %q, err=%v", "de", string(s), err)
+	}
+	if _, err := buf.Read(p[0:3]); string(p[0:3]) != "def" || err != nil {
+		t.Fatalf("want %q got %q, err=%v", "def", string(p[0:3]), err)
+	}
+	if s, err := buf.Peek(4); string(s) != "ghij" || err != nil {
+		t.Fatalf("want %q got %q, err=%v", "ghij", string(s), err)
+	}
+	if _, err := buf.Read(p[0:]); string(p[0:]) != "ghijklmnop" || err != nil {
+		t.Fatalf("want %q got %q, err=%v", "ghijklmnop", string(p[0:minReadBufferSize]), err)
+	}
+	if s, err := buf.Peek(0); string(s) != "" || err != nil {
+		t.Fatalf("want %q got %q, err=%v", "", string(s), err)
+	}
+	if _, err := buf.Peek(1); err != io.EOF {
+		t.Fatalf("want EOF got %v", err)
+	}
+
+	// Test for issue 3022, not exposing a reader's error on a successful Peek.
+	buf = NewReaderSize(dataAndEOFReader("abcd"), 32)
+	if s, err := buf.Peek(2); string(s) != "ab" || err != nil {
+		t.Errorf(`Peek(2) on "abcd", EOF = %q, %v; want "ab", nil`, string(s), err)
+	}
+	if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {
+		t.Errorf(`Peek(4) on "abcd", EOF = %q, %v; want "abcd", nil`, string(s), err)
+	}
+	if n, err := buf.Read(p[0:5]); string(p[0:n]) != "abcd" || err != nil {
+		t.Fatalf("Read after peek = %q, %v; want abcd, EOF", p[0:n], err)
+	}
+	if n, err := buf.Read(p[0:1]); string(p[0:n]) != "" || err != io.EOF {
+		t.Fatalf(`second Read after peek = %q, %v; want "", EOF`, p[0:n], err)
+	}
+}
+
+type dataAndEOFReader string
+
+func (r dataAndEOFReader) Read(p []byte) (int, error) {
+	return copy(p, r), io.EOF
+}
+
+func TestPeekThenUnreadRune(t *testing.T) {
+	// This sequence used to cause a crash.
+	r := NewReader(strings.NewReader("x"))
+	r.ReadRune()
+	r.Peek(1)
+	r.UnreadRune()
+	r.ReadRune() // Used to panic here
+}
+
+var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy")
+var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy")
+var testInputrn = []byte("012\r\n345\r\n678\r\n9ab\r\ncde\r\nfgh\r\nijk\r\nlmn\r\nopq\r\nrst\r\nuvw\r\nxy\r\n\n\r\n")
+
+// TestReader wraps a []byte and returns reads of a specific length.
+type testReader struct {
+	data   []byte
+	stride int
+}
+
+func (t *testReader) Read(buf []byte) (n int, err error) {
+	n = t.stride
+	if n > len(t.data) {
+		n = len(t.data)
+	}
+	if n > len(buf) {
+		n = len(buf)
+	}
+	copy(buf, t.data)
+	t.data = t.data[n:]
+	if len(t.data) == 0 {
+		err = io.EOF
+	}
+	return
+}
+
+func testReadLine(t *testing.T, input []byte) {
+	//for stride := 1; stride < len(input); stride++ {
+	for stride := 1; stride < 2; stride++ {
+		done := 0
+		reader := testReader{input, stride}
+		l := NewReaderSize(&reader, len(input)+1)
+		for {
+			line, isPrefix, err := l.ReadLine()
+			if len(line) > 0 && err != nil {
+				t.Errorf("ReadLine returned both data and error: %s", err)
+			}
+			if isPrefix {
+				t.Errorf("ReadLine returned prefix")
+			}
+			if err != nil {
+				if err != io.EOF {
+					t.Fatalf("Got unknown error: %s", err)
+				}
+				break
+			}
+			if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) {
+				t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line)
+			}
+			done += len(line)
+		}
+		if done != len(testOutput) {
+			t.Errorf("ReadLine didn't return everything: got: %d, want: %d (stride: %d)", done, len(testOutput), stride)
+		}
+	}
+}
+
+func TestReadLine(t *testing.T) {
+	testReadLine(t, testInput)
+	testReadLine(t, testInputrn)
+}
+
+func TestLineTooLong(t *testing.T) {
+	data := make([]byte, 0)
+	for i := 0; i < minReadBufferSize*5/2; i++ {
+		data = append(data, '0'+byte(i%10))
+	}
+	buf := bytes.NewReader(data)
+	l := NewReaderSize(buf, minReadBufferSize)
+	line, isPrefix, err := l.ReadLine()
+	if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {
+		t.Errorf("bad result for first line: got %q want %q %v", line, data[:minReadBufferSize], err)
+	}
+	data = data[len(line):]
+	line, isPrefix, err = l.ReadLine()
+	if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {
+		t.Errorf("bad result for second line: got %q want %q %v", line, data[:minReadBufferSize], err)
+	}
+	data = data[len(line):]
+	line, isPrefix, err = l.ReadLine()
+	if isPrefix || !bytes.Equal(line, data[:minReadBufferSize/2]) || err != nil {
+		t.Errorf("bad result for third line: got %q want %q %v", line, data[:minReadBufferSize/2], err)
+	}
+	line, isPrefix, err = l.ReadLine()
+	if isPrefix || err == nil {
+		t.Errorf("expected no more lines: %x %s", line, err)
+	}
+}
+
+func TestReadAfterLines(t *testing.T) {
+	line1 := "this is line1"
+	restData := "this is line2\nthis is line 3\n"
+	inbuf := bytes.NewReader([]byte(line1 + "\n" + restData))
+	outbuf := new(bytes.Buffer)
+	maxLineLength := len(line1) + len(restData)/2
+	l := NewReaderSize(inbuf, maxLineLength)
+	line, isPrefix, err := l.ReadLine()
+	if isPrefix || err != nil || string(line) != line1 {
+		t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line))
+	}
+	n, err := io.Copy(outbuf, l)
+	if int(n) != len(restData) || err != nil {
+		t.Errorf("bad result for Read: n=%d err=%v", n, err)
+	}
+	if outbuf.String() != restData {
+		t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData)
+	}
+}
+
+func TestReadEmptyBuffer(t *testing.T) {
+	l := NewReaderSize(new(bytes.Buffer), minReadBufferSize)
+	line, isPrefix, err := l.ReadLine()
+	if err != io.EOF {
+		t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
+	}
+}
+
+func TestLinesAfterRead(t *testing.T) {
+	l := NewReaderSize(bytes.NewReader([]byte("foo")), minReadBufferSize)
+	_, err := ioutil.ReadAll(l)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	line, isPrefix, err := l.ReadLine()
+	if err != io.EOF {
+		t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
+	}
+}
+
+func TestReadLineNonNilLineOrError(t *testing.T) {
+	r := NewReader(strings.NewReader("line 1\n"))
+	for i := 0; i < 2; i++ {
+		l, _, err := r.ReadLine()
+		if l != nil && err != nil {
+			t.Fatalf("on line %d/2; ReadLine=%#v, %v; want non-nil line or Error, but not both",
+				i+1, l, err)
+		}
+	}
+}
+
+type readLineResult struct {
+	line     []byte
+	isPrefix bool
+	err      error
+}
+
+var readLineNewlinesTests = []struct {
+	input  string
+	expect []readLineResult
+}{
+	{"012345678901234\r\n012345678901234\r\n", []readLineResult{
+		{[]byte("012345678901234"), true, nil},
+		{nil, false, nil},
+		{[]byte("012345678901234"), true, nil},
+		{nil, false, nil},
+		{nil, false, io.EOF},
+	}},
+	{"0123456789012345\r012345678901234\r", []readLineResult{
+		{[]byte("0123456789012345"), true, nil},
+		{[]byte("\r012345678901234"), true, nil},
+		{[]byte("\r"), false, nil},
+		{nil, false, io.EOF},
+	}},
+}
+
+func TestReadLineNewlines(t *testing.T) {
+	for _, e := range readLineNewlinesTests {
+		testReadLineNewlines(t, e.input, e.expect)
+	}
+}
+
+func testReadLineNewlines(t *testing.T, input string, expect []readLineResult) {
+	b := NewReaderSize(strings.NewReader(input), minReadBufferSize)
+	for i, e := range expect {
+		line, isPrefix, err := b.ReadLine()
+		if !bytes.Equal(line, e.line) {
+			t.Errorf("%q call %d, line == %q, want %q", input, i, line, e.line)
+			return
+		}
+		if isPrefix != e.isPrefix {
+			t.Errorf("%q call %d, isPrefix == %v, want %v", input, i, isPrefix, e.isPrefix)
+			return
+		}
+		if err != e.err {
+			t.Errorf("%q call %d, err == %v, want %v", input, i, err, e.err)
+			return
+		}
+	}
+}
+
+func createTestInput(n int) []byte {
+	input := make([]byte, n)
+	for i := range input {
+		// 101 and 251 are arbitrary prime numbers.
+		// The idea is to create an input sequence
+		// which doesn't repeat too frequently.
+		input[i] = byte(i % 251)
+		if i%101 == 0 {
+			input[i] ^= byte(i / 101)
+		}
+	}
+	return input
+}
+
+func TestReaderWriteTo(t *testing.T) {
+	input := createTestInput(8192)
+	r := NewReader(onlyReader{bytes.NewReader(input)})
+	w := new(bytes.Buffer)
+	if n, err := r.WriteTo(w); err != nil || n != int64(len(input)) {
+		t.Fatalf("r.WriteTo(w) = %d, %v, want %d, nil", n, err, len(input))
+	}
+
+	for i, val := range w.Bytes() {
+		if val != input[i] {
+			t.Errorf("after write: out[%d] = %#x, want %#x", i, val, input[i])
+		}
+	}
+}
+
+type errorWriterToTest struct {
+	rn, wn     int
+	rerr, werr error
+	expected   error
+}
+
+func (r errorWriterToTest) Read(p []byte) (int, error) {
+	return len(p) * r.rn, r.rerr
+}
+
+func (w errorWriterToTest) Write(p []byte) (int, error) {
+	return len(p) * w.wn, w.werr
+}
+
+var errorWriterToTests = []errorWriterToTest{
+	{1, 0, nil, io.ErrClosedPipe, io.ErrClosedPipe},
+	{0, 1, io.ErrClosedPipe, nil, io.ErrClosedPipe},
+	{0, 0, io.ErrUnexpectedEOF, io.ErrClosedPipe, io.ErrClosedPipe},
+	{0, 1, io.EOF, nil, nil},
+}
+
+func TestReaderWriteToErrors(t *testing.T) {
+	for i, rw := range errorWriterToTests {
+		r := NewReader(rw)
+		if _, err := r.WriteTo(rw); err != rw.expected {
+			t.Errorf("r.WriteTo(errorWriterToTests[%d]) = _, %v, want _,%v", i, err, rw.expected)
+		}
+	}
+}
+
+func TestWriterReadFrom(t *testing.T) {
+	ws := []func(io.Writer) io.Writer{
+		func(w io.Writer) io.Writer { return onlyWriter{w} },
+		func(w io.Writer) io.Writer { return w },
+	}
+
+	rs := []func(io.Reader) io.Reader{
+		iotest.DataErrReader,
+		func(r io.Reader) io.Reader { return r },
+	}
+
+	for ri, rfunc := range rs {
+		for wi, wfunc := range ws {
+			input := createTestInput(8192)
+			b := new(bytes.Buffer)
+			w := NewWriter(wfunc(b))
+			r := rfunc(bytes.NewReader(input))
+			if n, err := w.ReadFrom(r); err != nil || n != int64(len(input)) {
+				t.Errorf("ws[%d],rs[%d]: w.ReadFrom(r) = %d, %v, want %d, nil", wi, ri, n, err, len(input))
+				continue
+			}
+			if err := w.Flush(); err != nil {
+				t.Errorf("Flush returned %v", err)
+				continue
+			}
+			if got, want := b.String(), string(input); got != want {
+				t.Errorf("ws[%d], rs[%d]:\ngot  %q\nwant %q\n", wi, ri, got, want)
+			}
+		}
+	}
+}
+
+type errorReaderFromTest struct {
+	rn, wn     int
+	rerr, werr error
+	expected   error
+}
+
+func (r errorReaderFromTest) Read(p []byte) (int, error) {
+	return len(p) * r.rn, r.rerr
+}
+
+func (w errorReaderFromTest) Write(p []byte) (int, error) {
+	return len(p) * w.wn, w.werr
+}
+
+var errorReaderFromTests = []errorReaderFromTest{
+	{0, 1, io.EOF, nil, nil},
+	{1, 1, io.EOF, nil, nil},
+	{0, 1, io.ErrClosedPipe, nil, io.ErrClosedPipe},
+	{0, 0, io.ErrClosedPipe, io.ErrShortWrite, io.ErrClosedPipe},
+	{1, 0, nil, io.ErrShortWrite, io.ErrShortWrite},
+}
+
+func TestWriterReadFromErrors(t *testing.T) {
+	for i, rw := range errorReaderFromTests {
+		w := NewWriter(rw)
+		if _, err := w.ReadFrom(rw); err != rw.expected {
+			t.Errorf("w.ReadFrom(errorReaderFromTests[%d]) = _, %v, want _,%v", i, err, rw.expected)
+		}
+	}
+}
+
+// TestWriterReadFromCounts tests that using io.Copy to copy into a
+// bufio.Writer does not prematurely flush the buffer. For example, when
+// buffering writes to a network socket, excessive network writes should be
+// avoided.
+func TestWriterReadFromCounts(t *testing.T) {
+	var w0 writeCountingDiscard
+	b0 := NewWriterSize(&w0, 1234)
+	b0.WriteString(strings.Repeat("x", 1000))
+	if w0 != 0 {
+		t.Fatalf("write 1000 'x's: got %d writes, want 0", w0)
+	}
+	b0.WriteString(strings.Repeat("x", 200))
+	if w0 != 0 {
+		t.Fatalf("write 1200 'x's: got %d writes, want 0", w0)
+	}
+	io.Copy(b0, onlyReader{strings.NewReader(strings.Repeat("x", 30))})
+	if w0 != 0 {
+		t.Fatalf("write 1230 'x's: got %d writes, want 0", w0)
+	}
+	io.Copy(b0, onlyReader{strings.NewReader(strings.Repeat("x", 9))})
+	if w0 != 1 {
+		t.Fatalf("write 1239 'x's: got %d writes, want 1", w0)
+	}
+
+	var w1 writeCountingDiscard
+	b1 := NewWriterSize(&w1, 1234)
+	b1.WriteString(strings.Repeat("x", 1200))
+	b1.Flush()
+	if w1 != 1 {
+		t.Fatalf("flush 1200 'x's: got %d writes, want 1", w1)
+	}
+	b1.WriteString(strings.Repeat("x", 89))
+	if w1 != 1 {
+		t.Fatalf("write 1200 + 89 'x's: got %d writes, want 1", w1)
+	}
+	io.Copy(b1, onlyReader{strings.NewReader(strings.Repeat("x", 700))})
+	if w1 != 1 {
+		t.Fatalf("write 1200 + 789 'x's: got %d writes, want 1", w1)
+	}
+	io.Copy(b1, onlyReader{strings.NewReader(strings.Repeat("x", 600))})
+	if w1 != 2 {
+		t.Fatalf("write 1200 + 1389 'x's: got %d writes, want 2", w1)
+	}
+	b1.Flush()
+	if w1 != 3 {
+		t.Fatalf("flush 1200 + 1389 'x's: got %d writes, want 3", w1)
+	}
+}
+
+// A writeCountingDiscard is like ioutil.Discard and counts the number of times
+// Write is called on it.
+type writeCountingDiscard int
+
+func (w *writeCountingDiscard) Write(p []byte) (int, error) {
+	*w++
+	return len(p), nil
+}
+
+type negativeReader int
+
+func (r *negativeReader) Read([]byte) (int, error) { return -1, nil }
+
+func TestNegativeRead(t *testing.T) {
+	// should panic with a description pointing at the reader, not at itself.
+	// (should NOT panic with slice index error, for example.)
+	b := NewReader(new(negativeReader))
+	defer func() {
+		switch err := recover().(type) {
+		case nil:
+			t.Fatal("read did not panic")
+		case error:
+			if !strings.Contains(err.Error(), "reader returned negative count from Read") {
+				t.Fatalf("wrong panic: %v", err)
+			}
+		default:
+			t.Fatalf("unexpected panic value: %T(%v)", err, err)
+		}
+	}()
+	b.Read(make([]byte, 100))
+}
+
+var errFake = errors.New("fake error")
+
+type errorThenGoodReader struct {
+	didErr bool
+	nread  int
+}
+
+func (r *errorThenGoodReader) Read(p []byte) (int, error) {
+	r.nread++
+	if !r.didErr {
+		r.didErr = true
+		return 0, errFake
+	}
+	return len(p), nil
+}
+
+func TestReaderClearError(t *testing.T) {
+	r := &errorThenGoodReader{}
+	b := NewReader(r)
+	buf := make([]byte, 1)
+	if _, err := b.Read(nil); err != nil {
+		t.Fatalf("1st nil Read = %v; want nil", err)
+	}
+	if _, err := b.Read(buf); err != errFake {
+		t.Fatalf("1st Read = %v; want errFake", err)
+	}
+	if _, err := b.Read(nil); err != nil {
+		t.Fatalf("2nd nil Read = %v; want nil", err)
+	}
+	if _, err := b.Read(buf); err != nil {
+		t.Fatalf("3rd Read with buffer = %v; want nil", err)
+	}
+	if r.nread != 2 {
+		t.Errorf("num reads = %d; want 2", r.nread)
+	}
+}
+
+// Test for golang.org/issue/5947
+func TestWriterReadFromWhileFull(t *testing.T) {
+	buf := new(bytes.Buffer)
+	w := NewWriterSize(buf, 10)
+
+	// Fill buffer exactly.
+	n, err := w.Write([]byte("0123456789"))
+	if n != 10 || err != nil {
+		t.Fatalf("Write returned (%v, %v), want (10, nil)", n, err)
+	}
+
+	// Use ReadFrom to read in some data.
+	n2, err := w.ReadFrom(strings.NewReader("abcdef"))
+	if n2 != 6 || err != nil {
+		t.Fatalf("ReadFrom returned (%v, %v), want (6, nil)", n2, err)
+	}
+}
+
+type emptyThenNonEmptyReader struct {
+	r io.Reader
+	n int
+}
+
+func (r *emptyThenNonEmptyReader) Read(p []byte) (int, error) {
+	if r.n <= 0 {
+		return r.r.Read(p)
+	}
+	r.n--
+	return 0, nil
+}
+
+// Test for golang.org/issue/7611
+func TestWriterReadFromUntilEOF(t *testing.T) {
+	buf := new(bytes.Buffer)
+	w := NewWriterSize(buf, 5)
+
+	// Partially fill buffer
+	n, err := w.Write([]byte("0123"))
+	if n != 4 || err != nil {
+		t.Fatalf("Write returned (%v, %v), want (4, nil)", n, err)
+	}
+
+	// Use ReadFrom to read in some data.
+	r := &emptyThenNonEmptyReader{r: strings.NewReader("abcd"), n: 3}
+	n2, err := w.ReadFrom(r)
+	if n2 != 4 || err != nil {
+		t.Fatalf("ReadFrom returned (%v, %v), want (4, nil)", n2, err)
+	}
+	w.Flush()
+	if got, want := string(buf.Bytes()), "0123abcd"; got != want {
+		t.Fatalf("buf.Bytes() returned %q, want %q", got, want)
+	}
+}
+
+func TestWriterReadFromErrNoProgress(t *testing.T) {
+	buf := new(bytes.Buffer)
+	w := NewWriterSize(buf, 5)
+
+	// Partially fill buffer
+	n, err := w.Write([]byte("0123"))
+	if n != 4 || err != nil {
+		t.Fatalf("Write returned (%v, %v), want (4, nil)", n, err)
+	}
+
+	// Use ReadFrom to read in some data.
+	r := &emptyThenNonEmptyReader{r: strings.NewReader("abcd"), n: 100}
+	n2, err := w.ReadFrom(r)
+	if n2 != 0 || err != io.ErrNoProgress {
+		t.Fatalf("buf.Bytes() returned (%v, %v), want (0, io.ErrNoProgress)", n2, err)
+	}
+}
+
+func TestReaderReset(t *testing.T) {
+	r := NewReader(strings.NewReader("foo foo"))
+	buf := make([]byte, 3)
+	r.Read(buf)
+	if string(buf) != "foo" {
+		t.Errorf("buf = %q; want foo", buf)
+	}
+	r.Reset(strings.NewReader("bar bar"))
+	all, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(all) != "bar bar" {
+		t.Errorf("ReadAll = %q; want bar bar", all)
+	}
+}
+
+func TestWriterReset(t *testing.T) {
+	var buf1, buf2 bytes.Buffer
+	w := NewWriter(&buf1)
+	w.WriteString("foo")
+	w.Reset(&buf2) // and not flushed
+	w.WriteString("bar")
+	w.Flush()
+	if buf1.String() != "" {
+		t.Errorf("buf1 = %q; want empty", buf1.String())
+	}
+	if buf2.String() != "bar" {
+		t.Errorf("buf2 = %q; want bar", buf2.String())
+	}
+}
+
+// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have.
+type onlyReader struct {
+	io.Reader
+}
+
+// An onlyWriter only implements io.Writer, no matter what other methods the underlying implementation may have.
+type onlyWriter struct {
+	io.Writer
+}
+
+func BenchmarkReaderCopyOptimal(b *testing.B) {
+	// Optimal case is where the underlying reader implements io.WriterTo
+	srcBuf := bytes.NewBuffer(make([]byte, 8192))
+	src := NewReader(srcBuf)
+	dstBuf := new(bytes.Buffer)
+	dst := onlyWriter{dstBuf}
+	for i := 0; i < b.N; i++ {
+		srcBuf.Reset()
+		src.Reset(srcBuf)
+		dstBuf.Reset()
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkReaderCopyUnoptimal(b *testing.B) {
+	// Unoptimal case is where the underlying reader doesn't implement io.WriterTo
+	srcBuf := bytes.NewBuffer(make([]byte, 8192))
+	src := NewReader(onlyReader{srcBuf})
+	dstBuf := new(bytes.Buffer)
+	dst := onlyWriter{dstBuf}
+	for i := 0; i < b.N; i++ {
+		srcBuf.Reset()
+		src.Reset(onlyReader{srcBuf})
+		dstBuf.Reset()
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkReaderCopyNoWriteTo(b *testing.B) {
+	srcBuf := bytes.NewBuffer(make([]byte, 8192))
+	srcReader := NewReader(srcBuf)
+	src := onlyReader{srcReader}
+	dstBuf := new(bytes.Buffer)
+	dst := onlyWriter{dstBuf}
+	for i := 0; i < b.N; i++ {
+		srcBuf.Reset()
+		srcReader.Reset(srcBuf)
+		dstBuf.Reset()
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkReaderWriteToOptimal(b *testing.B) {
+	const bufSize = 16 << 10
+	buf := make([]byte, bufSize)
+	r := bytes.NewReader(buf)
+	srcReader := NewReaderSize(onlyReader{r}, 1<<10)
+	if _, ok := ioutil.Discard.(io.ReaderFrom); !ok {
+		b.Fatal("ioutil.Discard doesn't support ReaderFrom")
+	}
+	for i := 0; i < b.N; i++ {
+		r.Seek(0, 0)
+		srcReader.Reset(onlyReader{r})
+		n, err := srcReader.WriteTo(ioutil.Discard)
+		if err != nil {
+			b.Fatal(err)
+		}
+		if n != bufSize {
+			b.Fatalf("n = %d; want %d", n, bufSize)
+		}
+	}
+}
+
+func BenchmarkWriterCopyOptimal(b *testing.B) {
+	// Optimal case is where the underlying writer implements io.ReaderFrom
+	srcBuf := bytes.NewBuffer(make([]byte, 8192))
+	src := onlyReader{srcBuf}
+	dstBuf := new(bytes.Buffer)
+	dst := NewWriter(dstBuf)
+	for i := 0; i < b.N; i++ {
+		srcBuf.Reset()
+		dstBuf.Reset()
+		dst.Reset(dstBuf)
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkWriterCopyUnoptimal(b *testing.B) {
+	srcBuf := bytes.NewBuffer(make([]byte, 8192))
+	src := onlyReader{srcBuf}
+	dstBuf := new(bytes.Buffer)
+	dst := NewWriter(onlyWriter{dstBuf})
+	for i := 0; i < b.N; i++ {
+		srcBuf.Reset()
+		dstBuf.Reset()
+		dst.Reset(onlyWriter{dstBuf})
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkWriterCopyNoReadFrom(b *testing.B) {
+	srcBuf := bytes.NewBuffer(make([]byte, 8192))
+	src := onlyReader{srcBuf}
+	dstBuf := new(bytes.Buffer)
+	dstWriter := NewWriter(dstBuf)
+	dst := onlyWriter{dstWriter}
+	for i := 0; i < b.N; i++ {
+		srcBuf.Reset()
+		dstBuf.Reset()
+		dstWriter.Reset(dstBuf)
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkReaderEmpty(b *testing.B) {
+	b.ReportAllocs()
+	str := strings.Repeat("x", 16<<10)
+	for i := 0; i < b.N; i++ {
+		br := NewReader(strings.NewReader(str))
+		n, err := io.Copy(ioutil.Discard, br)
+		if err != nil {
+			b.Fatal(err)
+		}
+		if n != int64(len(str)) {
+			b.Fatal("wrong length")
+		}
+	}
+}
+
+func BenchmarkWriterEmpty(b *testing.B) {
+	b.ReportAllocs()
+	str := strings.Repeat("x", 1<<10)
+	bs := []byte(str)
+	for i := 0; i < b.N; i++ {
+		bw := NewWriter(ioutil.Discard)
+		bw.Flush()
+		bw.WriteByte('a')
+		bw.Flush()
+		bw.WriteRune('B')
+		bw.Flush()
+		bw.Write(bs)
+		bw.Flush()
+		bw.WriteString(str)
+		bw.Flush()
+	}
+}
+
+func BenchmarkWriterFlush(b *testing.B) {
+	b.ReportAllocs()
+	bw := NewWriter(ioutil.Discard)
+	str := strings.Repeat("x", 50)
+	for i := 0; i < b.N; i++ {
+		bw.WriteString(str)
+		bw.Flush()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/bufio/example_test.go b/third_party/gofrontend/libgo/go/bufio/example_test.go
new file mode 100644
index 0000000..3da9141
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bufio/example_test.go
@@ -0,0 +1,82 @@
+// Copyright 2013 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 bufio_test
+
+import (
+	"bufio"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+)
+
+func ExampleWriter() {
+	w := bufio.NewWriter(os.Stdout)
+	fmt.Fprint(w, "Hello, ")
+	fmt.Fprint(w, "world!")
+	w.Flush() // Don't forget to flush!
+	// Output: Hello, world!
+}
+
+// The simplest use of a Scanner, to read standard input as a set of lines.
+func ExampleScanner_lines() {
+	scanner := bufio.NewScanner(os.Stdin)
+	for scanner.Scan() {
+		fmt.Println(scanner.Text()) // Println will add back the final '\n'
+	}
+	if err := scanner.Err(); err != nil {
+		fmt.Fprintln(os.Stderr, "reading standard input:", err)
+	}
+}
+
+// Use a Scanner to implement a simple word-count utility by scanning the
+// input as a sequence of space-delimited tokens.
+func ExampleScanner_words() {
+	// An artificial input source.
+	const input = "Now is the winter of our discontent,\nMade glorious summer by this sun of York.\n"
+	scanner := bufio.NewScanner(strings.NewReader(input))
+	// Set the split function for the scanning operation.
+	scanner.Split(bufio.ScanWords)
+	// Count the words.
+	count := 0
+	for scanner.Scan() {
+		count++
+	}
+	if err := scanner.Err(); err != nil {
+		fmt.Fprintln(os.Stderr, "reading input:", err)
+	}
+	fmt.Printf("%d\n", count)
+	// Output: 15
+}
+
+// Use a Scanner with a custom split function (built by wrapping ScanWords) to validate
+// 32-bit decimal input.
+func ExampleScanner_custom() {
+	// An artificial input source.
+	const input = "1234 5678 1234567901234567890"
+	scanner := bufio.NewScanner(strings.NewReader(input))
+	// Create a custom split function by wrapping the existing ScanWords function.
+	split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
+		advance, token, err = bufio.ScanWords(data, atEOF)
+		if err == nil && token != nil {
+			_, err = strconv.ParseInt(string(token), 10, 32)
+		}
+		return
+	}
+	// Set the split function for the scanning operation.
+	scanner.Split(split)
+	// Validate the input
+	for scanner.Scan() {
+		fmt.Printf("%s\n", scanner.Text())
+	}
+
+	if err := scanner.Err(); err != nil {
+		fmt.Printf("Invalid input: %s", err)
+	}
+	// Output:
+	// 1234
+	// 5678
+	// Invalid input: strconv.ParseInt: parsing "1234567901234567890": value out of range
+}
diff --git a/third_party/gofrontend/libgo/go/bufio/export_test.go b/third_party/gofrontend/libgo/go/bufio/export_test.go
new file mode 100644
index 0000000..3d3bb27
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bufio/export_test.go
@@ -0,0 +1,27 @@
+// Copyright 2013 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 bufio
+
+// Exported for testing only.
+import (
+	"unicode/utf8"
+)
+
+var IsSpace = isSpace
+
+func (s *Scanner) MaxTokenSize(n int) {
+	if n < utf8.UTFMax || n > 1e9 {
+		panic("bad max token size")
+	}
+	if n < len(s.buf) {
+		s.buf = make([]byte, n)
+	}
+	s.maxTokenSize = n
+}
+
+// ErrOrEOF is like Err, but returns EOF. Used to test a corner case.
+func (s *Scanner) ErrOrEOF() error {
+	return s.err
+}
diff --git a/third_party/gofrontend/libgo/go/bufio/scan.go b/third_party/gofrontend/libgo/go/bufio/scan.go
new file mode 100644
index 0000000..715ce07
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bufio/scan.go
@@ -0,0 +1,346 @@
+// Copyright 2013 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 bufio
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"unicode/utf8"
+)
+
+// Scanner provides a convenient interface for reading data such as
+// a file of newline-delimited lines of text. Successive calls to
+// the Scan method will step through the 'tokens' of a file, skipping
+// the bytes between the tokens. The specification of a token is
+// defined by a split function of type SplitFunc; the default split
+// function breaks the input into lines with line termination stripped. Split
+// functions are defined in this package for scanning a file into
+// lines, bytes, UTF-8-encoded runes, and space-delimited words. The
+// client may instead provide a custom split function.
+//
+// Scanning stops unrecoverably at EOF, the first I/O error, or a token too
+// large to fit in the buffer. When a scan stops, the reader may have
+// advanced arbitrarily far past the last token. Programs that need more
+// control over error handling or large tokens, or must run sequential scans
+// on a reader, should use bufio.Reader instead.
+//
+type Scanner struct {
+	r            io.Reader // The reader provided by the client.
+	split        SplitFunc // The function to split the tokens.
+	maxTokenSize int       // Maximum size of a token; modified by tests.
+	token        []byte    // Last token returned by split.
+	buf          []byte    // Buffer used as argument to split.
+	start        int       // First non-processed byte in buf.
+	end          int       // End of data in buf.
+	err          error     // Sticky error.
+}
+
+// SplitFunc is the signature of the split function used to tokenize the
+// input. The arguments are an initial substring of the remaining unprocessed
+// data and a flag, atEOF, that reports whether the Reader has no more data
+// to give. The return values are the number of bytes to advance the input
+// and the next token to return to the user, plus an error, if any. If the
+// data does not yet hold a complete token, for instance if it has no newline
+// while scanning lines, SplitFunc can return (0, nil, nil) to signal the
+// Scanner to read more data into the slice and try again with a longer slice
+// starting at the same point in the input.
+//
+// If the returned error is non-nil, scanning stops and the error
+// is returned to the client.
+//
+// The function is never called with an empty data slice unless atEOF
+// is true. If atEOF is true, however, data may be non-empty and,
+// as always, holds unprocessed text.
+type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
+
+// Errors returned by Scanner.
+var (
+	ErrTooLong         = errors.New("bufio.Scanner: token too long")
+	ErrNegativeAdvance = errors.New("bufio.Scanner: SplitFunc returns negative advance count")
+	ErrAdvanceTooFar   = errors.New("bufio.Scanner: SplitFunc returns advance count beyond input")
+)
+
+const (
+	// Maximum size used to buffer a token. The actual maximum token size
+	// may be smaller as the buffer may need to include, for instance, a newline.
+	MaxScanTokenSize = 64 * 1024
+)
+
+// NewScanner returns a new Scanner to read from r.
+// The split function defaults to ScanLines.
+func NewScanner(r io.Reader) *Scanner {
+	return &Scanner{
+		r:            r,
+		split:        ScanLines,
+		maxTokenSize: MaxScanTokenSize,
+		buf:          make([]byte, 4096), // Plausible starting size; needn't be large.
+	}
+}
+
+// Err returns the first non-EOF error that was encountered by the Scanner.
+func (s *Scanner) Err() error {
+	if s.err == io.EOF {
+		return nil
+	}
+	return s.err
+}
+
+// Bytes returns the most recent token generated by a call to Scan.
+// The underlying array may point to data that will be overwritten
+// by a subsequent call to Scan. It does no allocation.
+func (s *Scanner) Bytes() []byte {
+	return s.token
+}
+
+// Text returns the most recent token generated by a call to Scan
+// as a newly allocated string holding its bytes.
+func (s *Scanner) Text() string {
+	return string(s.token)
+}
+
+// Scan advances the Scanner to the next token, which will then be
+// available through the Bytes or Text method. It returns false when the
+// scan stops, either by reaching the end of the input or an error.
+// After Scan returns false, the Err method will return any error that
+// occurred during scanning, except that if it was io.EOF, Err
+// will return nil.
+func (s *Scanner) Scan() bool {
+	// Loop until we have a token.
+	for {
+		// See if we can get a token with what we already have.
+		if s.end > s.start {
+			advance, token, err := s.split(s.buf[s.start:s.end], s.err != nil)
+			if err != nil {
+				s.setErr(err)
+				return false
+			}
+			if !s.advance(advance) {
+				return false
+			}
+			s.token = token
+			if token != nil {
+				return true
+			}
+		}
+		// We cannot generate a token with what we are holding.
+		// If we've already hit EOF or an I/O error, we are done.
+		if s.err != nil {
+			// Shut it down.
+			s.start = 0
+			s.end = 0
+			return false
+		}
+		// Must read more data.
+		// First, shift data to beginning of buffer if there's lots of empty space
+		// or space is needed.
+		if s.start > 0 && (s.end == len(s.buf) || s.start > len(s.buf)/2) {
+			copy(s.buf, s.buf[s.start:s.end])
+			s.end -= s.start
+			s.start = 0
+		}
+		// Is the buffer full? If so, resize.
+		if s.end == len(s.buf) {
+			if len(s.buf) >= s.maxTokenSize {
+				s.setErr(ErrTooLong)
+				return false
+			}
+			newSize := len(s.buf) * 2
+			if newSize > s.maxTokenSize {
+				newSize = s.maxTokenSize
+			}
+			newBuf := make([]byte, newSize)
+			copy(newBuf, s.buf[s.start:s.end])
+			s.buf = newBuf
+			s.end -= s.start
+			s.start = 0
+			continue
+		}
+		// Finally we can read some input. Make sure we don't get stuck with
+		// a misbehaving Reader. Officially we don't need to do this, but let's
+		// be extra careful: Scanner is for safe, simple jobs.
+		for loop := 0; ; {
+			n, err := s.r.Read(s.buf[s.end:len(s.buf)])
+			s.end += n
+			if err != nil {
+				s.setErr(err)
+				break
+			}
+			if n > 0 {
+				break
+			}
+			loop++
+			if loop > maxConsecutiveEmptyReads {
+				s.setErr(io.ErrNoProgress)
+				break
+			}
+		}
+	}
+}
+
+// advance consumes n bytes of the buffer. It reports whether the advance was legal.
+func (s *Scanner) advance(n int) bool {
+	if n < 0 {
+		s.setErr(ErrNegativeAdvance)
+		return false
+	}
+	if n > s.end-s.start {
+		s.setErr(ErrAdvanceTooFar)
+		return false
+	}
+	s.start += n
+	return true
+}
+
+// setErr records the first error encountered.
+func (s *Scanner) setErr(err error) {
+	if s.err == nil || s.err == io.EOF {
+		s.err = err
+	}
+}
+
+// Split sets the split function for the Scanner. If called, it must be
+// called before Scan. The default split function is ScanLines.
+func (s *Scanner) Split(split SplitFunc) {
+	s.split = split
+}
+
+// Split functions
+
+// ScanBytes is a split function for a Scanner that returns each byte as a token.
+func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
+	if atEOF && len(data) == 0 {
+		return 0, nil, nil
+	}
+	return 1, data[0:1], nil
+}
+
+var errorRune = []byte(string(utf8.RuneError))
+
+// ScanRunes is a split function for a Scanner that returns each
+// UTF-8-encoded rune as a token. The sequence of runes returned is
+// equivalent to that from a range loop over the input as a string, which
+// means that erroneous UTF-8 encodings translate to U+FFFD = "\xef\xbf\xbd".
+// Because of the Scan interface, this makes it impossible for the client to
+// distinguish correctly encoded replacement runes from encoding errors.
+func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error) {
+	if atEOF && len(data) == 0 {
+		return 0, nil, nil
+	}
+
+	// Fast path 1: ASCII.
+	if data[0] < utf8.RuneSelf {
+		return 1, data[0:1], nil
+	}
+
+	// Fast path 2: Correct UTF-8 decode without error.
+	_, width := utf8.DecodeRune(data)
+	if width > 1 {
+		// It's a valid encoding. Width cannot be one for a correctly encoded
+		// non-ASCII rune.
+		return width, data[0:width], nil
+	}
+
+	// We know it's an error: we have width==1 and implicitly r==utf8.RuneError.
+	// Is the error because there wasn't a full rune to be decoded?
+	// FullRune distinguishes correctly between erroneous and incomplete encodings.
+	if !atEOF && !utf8.FullRune(data) {
+		// Incomplete; get more bytes.
+		return 0, nil, nil
+	}
+
+	// We have a real UTF-8 encoding error. Return a properly encoded error rune
+	// but advance only one byte. This matches the behavior of a range loop over
+	// an incorrectly encoded string.
+	return 1, errorRune, nil
+}
+
+// dropCR drops a terminal \r from the data.
+func dropCR(data []byte) []byte {
+	if len(data) > 0 && data[len(data)-1] == '\r' {
+		return data[0 : len(data)-1]
+	}
+	return data
+}
+
+// ScanLines is a split function for a Scanner that returns each line of
+// text, stripped of any trailing end-of-line marker. The returned line may
+// be empty. The end-of-line marker is one optional carriage return followed
+// by one mandatory newline. In regular expression notation, it is `\r?\n`.
+// The last non-empty line of input will be returned even if it has no
+// newline.
+func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
+	if atEOF && len(data) == 0 {
+		return 0, nil, nil
+	}
+	if i := bytes.IndexByte(data, '\n'); i >= 0 {
+		// We have a full newline-terminated line.
+		return i + 1, dropCR(data[0:i]), nil
+	}
+	// If we're at EOF, we have a final, non-terminated line. Return it.
+	if atEOF {
+		return len(data), dropCR(data), nil
+	}
+	// Request more data.
+	return 0, nil, nil
+}
+
+// isSpace reports whether the character is a Unicode white space character.
+// We avoid dependency on the unicode package, but check validity of the implementation
+// in the tests.
+func isSpace(r rune) bool {
+	if r <= '\u00FF' {
+		// Obvious ASCII ones: \t through \r plus space. Plus two Latin-1 oddballs.
+		switch r {
+		case ' ', '\t', '\n', '\v', '\f', '\r':
+			return true
+		case '\u0085', '\u00A0':
+			return true
+		}
+		return false
+	}
+	// High-valued ones.
+	if '\u2000' <= r && r <= '\u200a' {
+		return true
+	}
+	switch r {
+	case '\u1680', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000':
+		return true
+	}
+	return false
+}
+
+// ScanWords is a split function for a Scanner that returns each
+// space-separated word of text, with surrounding spaces deleted. It will
+// never return an empty string. The definition of space is set by
+// unicode.IsSpace.
+func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) {
+	// Skip leading spaces.
+	start := 0
+	for width := 0; start < len(data); start += width {
+		var r rune
+		r, width = utf8.DecodeRune(data[start:])
+		if !isSpace(r) {
+			break
+		}
+	}
+	if atEOF && len(data) == 0 {
+		return 0, nil, nil
+	}
+	// Scan until space, marking end of word.
+	for width, i := 0, start; i < len(data); i += width {
+		var r rune
+		r, width = utf8.DecodeRune(data[i:])
+		if isSpace(r) {
+			return i + width, data[start:i], nil
+		}
+	}
+	// If we're at EOF, we have a final, non-empty, non-terminated word. Return it.
+	if atEOF && len(data) > start {
+		return len(data), data[start:], nil
+	}
+	// Request more data.
+	return 0, nil, nil
+}
diff --git a/third_party/gofrontend/libgo/go/bufio/scan_test.go b/third_party/gofrontend/libgo/go/bufio/scan_test.go
new file mode 100644
index 0000000..0db7cad
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bufio/scan_test.go
@@ -0,0 +1,406 @@
+// Copyright 2013 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 bufio_test
+
+import (
+	. "bufio"
+	"bytes"
+	"errors"
+	"io"
+	"strings"
+	"testing"
+	"unicode"
+	"unicode/utf8"
+)
+
+// Test white space table matches the Unicode definition.
+func TestSpace(t *testing.T) {
+	for r := rune(0); r <= utf8.MaxRune; r++ {
+		if IsSpace(r) != unicode.IsSpace(r) {
+			t.Fatalf("white space property disagrees: %#U should be %t", r, unicode.IsSpace(r))
+		}
+	}
+}
+
+var scanTests = []string{
+	"",
+	"a",
+	"¼",
+	"☹",
+	"\x81",   // UTF-8 error
+	"\uFFFD", // correctly encoded RuneError
+	"abcdefgh",
+	"abc def\n\t\tgh    ",
+	"abc¼☹\x81\uFFFD日本語\x82abc",
+}
+
+func TestScanByte(t *testing.T) {
+	for n, test := range scanTests {
+		buf := strings.NewReader(test)
+		s := NewScanner(buf)
+		s.Split(ScanBytes)
+		var i int
+		for i = 0; s.Scan(); i++ {
+			if b := s.Bytes(); len(b) != 1 || b[0] != test[i] {
+				t.Errorf("#%d: %d: expected %q got %q", n, i, test, b)
+			}
+		}
+		if i != len(test) {
+			t.Errorf("#%d: termination expected at %d; got %d", n, len(test), i)
+		}
+		err := s.Err()
+		if err != nil {
+			t.Errorf("#%d: %v", n, err)
+		}
+	}
+}
+
+// Test that the rune splitter returns same sequence of runes (not bytes) as for range string.
+func TestScanRune(t *testing.T) {
+	for n, test := range scanTests {
+		buf := strings.NewReader(test)
+		s := NewScanner(buf)
+		s.Split(ScanRunes)
+		var i, runeCount int
+		var expect rune
+		// Use a string range loop to validate the sequence of runes.
+		for i, expect = range string(test) {
+			if !s.Scan() {
+				break
+			}
+			runeCount++
+			got, _ := utf8.DecodeRune(s.Bytes())
+			if got != expect {
+				t.Errorf("#%d: %d: expected %q got %q", n, i, expect, got)
+			}
+		}
+		if s.Scan() {
+			t.Errorf("#%d: scan ran too long, got %q", n, s.Text())
+		}
+		testRuneCount := utf8.RuneCountInString(test)
+		if runeCount != testRuneCount {
+			t.Errorf("#%d: termination expected at %d; got %d", n, testRuneCount, runeCount)
+		}
+		err := s.Err()
+		if err != nil {
+			t.Errorf("#%d: %v", n, err)
+		}
+	}
+}
+
+var wordScanTests = []string{
+	"",
+	" ",
+	"\n",
+	"a",
+	" a ",
+	"abc def",
+	" abc def ",
+	" abc\tdef\nghi\rjkl\fmno\vpqr\u0085stu\u00a0\n",
+}
+
+// Test that the word splitter returns the same data as strings.Fields.
+func TestScanWords(t *testing.T) {
+	for n, test := range wordScanTests {
+		buf := strings.NewReader(test)
+		s := NewScanner(buf)
+		s.Split(ScanWords)
+		words := strings.Fields(test)
+		var wordCount int
+		for wordCount = 0; wordCount < len(words); wordCount++ {
+			if !s.Scan() {
+				break
+			}
+			got := s.Text()
+			if got != words[wordCount] {
+				t.Errorf("#%d: %d: expected %q got %q", n, wordCount, words[wordCount], got)
+			}
+		}
+		if s.Scan() {
+			t.Errorf("#%d: scan ran too long, got %q", n, s.Text())
+		}
+		if wordCount != len(words) {
+			t.Errorf("#%d: termination expected at %d; got %d", n, len(words), wordCount)
+		}
+		err := s.Err()
+		if err != nil {
+			t.Errorf("#%d: %v", n, err)
+		}
+	}
+}
+
+// slowReader is a reader that returns only a few bytes at a time, to test the incremental
+// reads in Scanner.Scan.
+type slowReader struct {
+	max int
+	buf io.Reader
+}
+
+func (sr *slowReader) Read(p []byte) (n int, err error) {
+	if len(p) > sr.max {
+		p = p[0:sr.max]
+	}
+	return sr.buf.Read(p)
+}
+
+// genLine writes to buf a predictable but non-trivial line of text of length
+// n, including the terminal newline and an occasional carriage return.
+// If addNewline is false, the \r and \n are not emitted.
+func genLine(buf *bytes.Buffer, lineNum, n int, addNewline bool) {
+	buf.Reset()
+	doCR := lineNum%5 == 0
+	if doCR {
+		n--
+	}
+	for i := 0; i < n-1; i++ { // Stop early for \n.
+		c := 'a' + byte(lineNum+i)
+		if c == '\n' || c == '\r' { // Don't confuse us.
+			c = 'N'
+		}
+		buf.WriteByte(c)
+	}
+	if addNewline {
+		if doCR {
+			buf.WriteByte('\r')
+		}
+		buf.WriteByte('\n')
+	}
+	return
+}
+
+// Test the line splitter, including some carriage returns but no long lines.
+func TestScanLongLines(t *testing.T) {
+	const smallMaxTokenSize = 256 // Much smaller for more efficient testing.
+	// Build a buffer of lots of line lengths up to but not exceeding smallMaxTokenSize.
+	tmp := new(bytes.Buffer)
+	buf := new(bytes.Buffer)
+	lineNum := 0
+	j := 0
+	for i := 0; i < 2*smallMaxTokenSize; i++ {
+		genLine(tmp, lineNum, j, true)
+		if j < smallMaxTokenSize {
+			j++
+		} else {
+			j--
+		}
+		buf.Write(tmp.Bytes())
+		lineNum++
+	}
+	s := NewScanner(&slowReader{1, buf})
+	s.Split(ScanLines)
+	s.MaxTokenSize(smallMaxTokenSize)
+	j = 0
+	for lineNum := 0; s.Scan(); lineNum++ {
+		genLine(tmp, lineNum, j, false)
+		if j < smallMaxTokenSize {
+			j++
+		} else {
+			j--
+		}
+		line := tmp.String() // We use the string-valued token here, for variety.
+		if s.Text() != line {
+			t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Text(), line)
+		}
+	}
+	err := s.Err()
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+// Test that the line splitter errors out on a long line.
+func TestScanLineTooLong(t *testing.T) {
+	const smallMaxTokenSize = 256 // Much smaller for more efficient testing.
+	// Build a buffer of lots of line lengths up to but not exceeding smallMaxTokenSize.
+	tmp := new(bytes.Buffer)
+	buf := new(bytes.Buffer)
+	lineNum := 0
+	j := 0
+	for i := 0; i < 2*smallMaxTokenSize; i++ {
+		genLine(tmp, lineNum, j, true)
+		j++
+		buf.Write(tmp.Bytes())
+		lineNum++
+	}
+	s := NewScanner(&slowReader{3, buf})
+	s.Split(ScanLines)
+	s.MaxTokenSize(smallMaxTokenSize)
+	j = 0
+	for lineNum := 0; s.Scan(); lineNum++ {
+		genLine(tmp, lineNum, j, false)
+		if j < smallMaxTokenSize {
+			j++
+		} else {
+			j--
+		}
+		line := tmp.Bytes()
+		if !bytes.Equal(s.Bytes(), line) {
+			t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Bytes(), line)
+		}
+	}
+	err := s.Err()
+	if err != ErrTooLong {
+		t.Fatalf("expected ErrTooLong; got %s", err)
+	}
+}
+
+// Test that the line splitter handles a final line without a newline.
+func testNoNewline(text string, lines []string, t *testing.T) {
+	buf := strings.NewReader(text)
+	s := NewScanner(&slowReader{7, buf})
+	s.Split(ScanLines)
+	for lineNum := 0; s.Scan(); lineNum++ {
+		line := lines[lineNum]
+		if s.Text() != line {
+			t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Bytes(), line)
+		}
+	}
+	err := s.Err()
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+var noNewlineLines = []string{
+	"abcdefghijklmn\nopqrstuvwxyz",
+}
+
+// Test that the line splitter handles a final line without a newline.
+func TestScanLineNoNewline(t *testing.T) {
+	const text = "abcdefghijklmn\nopqrstuvwxyz"
+	lines := []string{
+		"abcdefghijklmn",
+		"opqrstuvwxyz",
+	}
+	testNoNewline(text, lines, t)
+}
+
+// Test that the line splitter handles a final line with a carriage return but no newline.
+func TestScanLineReturnButNoNewline(t *testing.T) {
+	const text = "abcdefghijklmn\nopqrstuvwxyz\r"
+	lines := []string{
+		"abcdefghijklmn",
+		"opqrstuvwxyz",
+	}
+	testNoNewline(text, lines, t)
+}
+
+// Test that the line splitter handles a final empty line.
+func TestScanLineEmptyFinalLine(t *testing.T) {
+	const text = "abcdefghijklmn\nopqrstuvwxyz\n\n"
+	lines := []string{
+		"abcdefghijklmn",
+		"opqrstuvwxyz",
+		"",
+	}
+	testNoNewline(text, lines, t)
+}
+
+// Test that the line splitter handles a final empty line with a carriage return but no newline.
+func TestScanLineEmptyFinalLineWithCR(t *testing.T) {
+	const text = "abcdefghijklmn\nopqrstuvwxyz\n\r"
+	lines := []string{
+		"abcdefghijklmn",
+		"opqrstuvwxyz",
+		"",
+	}
+	testNoNewline(text, lines, t)
+}
+
+var testError = errors.New("testError")
+
+// Test the correct error is returned when the split function errors out.
+func TestSplitError(t *testing.T) {
+	// Create a split function that delivers a little data, then a predictable error.
+	numSplits := 0
+	const okCount = 7
+	errorSplit := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
+		if atEOF {
+			panic("didn't get enough data")
+		}
+		if numSplits >= okCount {
+			return 0, nil, testError
+		}
+		numSplits++
+		return 1, data[0:1], nil
+	}
+	// Read the data.
+	const text = "abcdefghijklmnopqrstuvwxyz"
+	buf := strings.NewReader(text)
+	s := NewScanner(&slowReader{1, buf})
+	s.Split(errorSplit)
+	var i int
+	for i = 0; s.Scan(); i++ {
+		if len(s.Bytes()) != 1 || text[i] != s.Bytes()[0] {
+			t.Errorf("#%d: expected %q got %q", i, text[i], s.Bytes()[0])
+		}
+	}
+	// Check correct termination location and error.
+	if i != okCount {
+		t.Errorf("unexpected termination; expected %d tokens got %d", okCount, i)
+	}
+	err := s.Err()
+	if err != testError {
+		t.Fatalf("expected %q got %v", testError, err)
+	}
+}
+
+// Test that an EOF is overridden by a user-generated scan error.
+func TestErrAtEOF(t *testing.T) {
+	s := NewScanner(strings.NewReader("1 2 33"))
+	// This spitter will fail on last entry, after s.err==EOF.
+	split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
+		advance, token, err = ScanWords(data, atEOF)
+		if len(token) > 1 {
+			if s.ErrOrEOF() != io.EOF {
+				t.Fatal("not testing EOF")
+			}
+			err = testError
+		}
+		return
+	}
+	s.Split(split)
+	for s.Scan() {
+	}
+	if s.Err() != testError {
+		t.Fatal("wrong error:", s.Err())
+	}
+}
+
+// Test for issue 5268.
+type alwaysError struct{}
+
+func (alwaysError) Read(p []byte) (int, error) {
+	return 0, io.ErrUnexpectedEOF
+}
+
+func TestNonEOFWithEmptyRead(t *testing.T) {
+	scanner := NewScanner(alwaysError{})
+	for scanner.Scan() {
+		t.Fatal("read should fail")
+	}
+	err := scanner.Err()
+	if err != io.ErrUnexpectedEOF {
+		t.Errorf("unexpected error: %v", err)
+	}
+}
+
+// Test that Scan finishes if we have endless empty reads.
+type endlessZeros struct{}
+
+func (endlessZeros) Read(p []byte) (int, error) {
+	return 0, nil
+}
+
+func TestBadReader(t *testing.T) {
+	scanner := NewScanner(endlessZeros{})
+	for scanner.Scan() {
+		t.Fatal("read should fail")
+	}
+	err := scanner.Err()
+	if err != io.ErrNoProgress {
+		t.Errorf("unexpected error: %v", err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/builtin/builtin.go b/third_party/gofrontend/libgo/go/builtin/builtin.go
new file mode 100644
index 0000000..51550a4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/builtin/builtin.go
@@ -0,0 +1,256 @@
+// 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.
+
+/*
+	Package builtin provides documentation for Go's predeclared identifiers.
+	The items documented here are not actually in package builtin
+	but their descriptions here allow godoc to present documentation
+	for the language's special identifiers.
+*/
+package builtin
+
+// bool is the set of boolean values, true and false.
+type bool bool
+
+// true and false are the two untyped boolean values.
+const (
+	true  = 0 == 0 // Untyped bool.
+	false = 0 != 0 // Untyped bool.
+)
+
+// uint8 is the set of all unsigned 8-bit integers.
+// Range: 0 through 255.
+type uint8 uint8
+
+// uint16 is the set of all unsigned 16-bit integers.
+// Range: 0 through 65535.
+type uint16 uint16
+
+// uint32 is the set of all unsigned 32-bit integers.
+// Range: 0 through 4294967295.
+type uint32 uint32
+
+// uint64 is the set of all unsigned 64-bit integers.
+// Range: 0 through 18446744073709551615.
+type uint64 uint64
+
+// int8 is the set of all signed 8-bit integers.
+// Range: -128 through 127.
+type int8 int8
+
+// int16 is the set of all signed 16-bit integers.
+// Range: -32768 through 32767.
+type int16 int16
+
+// int32 is the set of all signed 32-bit integers.
+// Range: -2147483648 through 2147483647.
+type int32 int32
+
+// int64 is the set of all signed 64-bit integers.
+// Range: -9223372036854775808 through 9223372036854775807.
+type int64 int64
+
+// float32 is the set of all IEEE-754 32-bit floating-point numbers.
+type float32 float32
+
+// float64 is the set of all IEEE-754 64-bit floating-point numbers.
+type float64 float64
+
+// complex64 is the set of all complex numbers with float32 real and
+// imaginary parts.
+type complex64 complex64
+
+// complex128 is the set of all complex numbers with float64 real and
+// imaginary parts.
+type complex128 complex128
+
+// string is the set of all strings of 8-bit bytes, conventionally but not
+// necessarily representing UTF-8-encoded text. A string may be empty, but
+// not nil. Values of string type are immutable.
+type string string
+
+// int is a signed integer type that is at least 32 bits in size. It is a
+// distinct type, however, and not an alias for, say, int32.
+type int int
+
+// uint is an unsigned integer type that is at least 32 bits in size. It is a
+// distinct type, however, and not an alias for, say, uint32.
+type uint uint
+
+// uintptr is an integer type that is large enough to hold the bit pattern of
+// any pointer.
+type uintptr uintptr
+
+// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
+// used, by convention, to distinguish byte values from 8-bit unsigned
+// integer values.
+type byte byte
+
+// rune is an alias for int32 and is equivalent to int32 in all ways. It is
+// used, by convention, to distinguish character values from integer values.
+type rune rune
+
+// iota is a predeclared identifier representing the untyped integer ordinal
+// number of the current const specification in a (usually parenthesized)
+// const declaration. It is zero-indexed.
+const iota = 0 // Untyped int.
+
+// nil is a predeclared identifier representing the zero value for a
+// pointer, channel, func, interface, map, or slice type.
+var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
+
+// Type is here for the purposes of documentation only. It is a stand-in
+// for any Go type, but represents the same type for any given function
+// invocation.
+type Type int
+
+// Type1 is here for the purposes of documentation only. It is a stand-in
+// for any Go type, but represents the same type for any given function
+// invocation.
+type Type1 int
+
+// IntegerType is here for the purposes of documentation only. It is a stand-in
+// for any integer type: int, uint, int8 etc.
+type IntegerType int
+
+// FloatType is here for the purposes of documentation only. It is a stand-in
+// for either float type: float32 or float64.
+type FloatType float32
+
+// ComplexType is here for the purposes of documentation only. It is a
+// stand-in for either complex type: complex64 or complex128.
+type ComplexType complex64
+
+// The append built-in function appends elements to the end of a slice. If
+// it has sufficient capacity, the destination is resliced to accommodate the
+// new elements. If it does not, a new underlying array will be allocated.
+// Append returns the updated slice. It is therefore necessary to store the
+// result of append, often in the variable holding the slice itself:
+//	slice = append(slice, elem1, elem2)
+//	slice = append(slice, anotherSlice...)
+// As a special case, it is legal to append a string to a byte slice, like this:
+//	slice = append([]byte("hello "), "world"...)
+func append(slice []Type, elems ...Type) []Type
+
+// The copy built-in function copies elements from a source slice into a
+// destination slice. (As a special case, it also will copy bytes from a
+// string to a slice of bytes.) The source and destination may overlap. Copy
+// returns the number of elements copied, which will be the minimum of
+// len(src) and len(dst).
+func copy(dst, src []Type) int
+
+// The delete built-in function deletes the element with the specified key
+// (m[key]) from the map. If m is nil or there is no such element, delete
+// is a no-op.
+func delete(m map[Type]Type1, key Type)
+
+// The len built-in function returns the length of v, according to its type:
+//	Array: the number of elements in v.
+//	Pointer to array: the number of elements in *v (even if v is nil).
+//	Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
+//	String: the number of bytes in v.
+//	Channel: the number of elements queued (unread) in the channel buffer;
+//	if v is nil, len(v) is zero.
+func len(v Type) int
+
+// The cap built-in function returns the capacity of v, according to its type:
+//	Array: the number of elements in v (same as len(v)).
+//	Pointer to array: the number of elements in *v (same as len(v)).
+//	Slice: the maximum length the slice can reach when resliced;
+//	if v is nil, cap(v) is zero.
+//	Channel: the channel buffer capacity, in units of elements;
+//	if v is nil, cap(v) is zero.
+func cap(v Type) int
+
+// The make built-in function allocates and initializes an object of type
+// slice, map, or chan (only). Like new, the first argument is a type, not a
+// value. Unlike new, make's return type is the same as the type of its
+// argument, not a pointer to it. The specification of the result depends on
+// the type:
+//	Slice: The size specifies the length. The capacity of the slice is
+//	equal to its length. A second integer argument may be provided to
+//	specify a different capacity; it must be no smaller than the
+//	length, so make([]int, 0, 10) allocates a slice of length 0 and
+//	capacity 10.
+//	Map: An initial allocation is made according to the size but the
+//	resulting map has length 0. The size may be omitted, in which case
+//	a small starting size is allocated.
+//	Channel: The channel's buffer is initialized with the specified
+//	buffer capacity. If zero, or the size is omitted, the channel is
+//	unbuffered.
+func make(Type, size IntegerType) Type
+
+// The new built-in function allocates memory. The first argument is a type,
+// not a value, and the value returned is a pointer to a newly
+// allocated zero value of that type.
+func new(Type) *Type
+
+// The complex built-in function constructs a complex value from two
+// floating-point values. The real and imaginary parts must be of the same
+// size, either float32 or float64 (or assignable to them), and the return
+// value will be the corresponding complex type (complex64 for float32,
+// complex128 for float64).
+func complex(r, i FloatType) ComplexType
+
+// The real built-in function returns the real part of the complex number c.
+// The return value will be floating point type corresponding to the type of c.
+func real(c ComplexType) FloatType
+
+// The imag built-in function returns the imaginary part of the complex
+// number c. The return value will be floating point type corresponding to
+// the type of c.
+func imag(c ComplexType) FloatType
+
+// The close built-in function closes a channel, which must be either
+// bidirectional or send-only. It should be executed only by the sender,
+// never the receiver, and has the effect of shutting down the channel after
+// the last sent value is received. After the last value has been received
+// from a closed channel c, any receive from c will succeed without
+// blocking, returning the zero value for the channel element. The form
+//	x, ok := <-c
+// will also set ok to false for a closed channel.
+func close(c chan<- Type)
+
+// The panic built-in function stops normal execution of the current
+// goroutine. When a function F calls panic, normal execution of F stops
+// immediately. Any functions whose execution was deferred by F are run in
+// the usual way, and then F returns to its caller. To the caller G, the
+// invocation of F then behaves like a call to panic, terminating G's
+// execution and running any deferred functions. This continues until all
+// functions in the executing goroutine have stopped, in reverse order. At
+// that point, the program is terminated and the error condition is reported,
+// including the value of the argument to panic. This termination sequence
+// is called panicking and can be controlled by the built-in function
+// recover.
+func panic(v interface{})
+
+// The recover built-in function allows a program to manage behavior of a
+// panicking goroutine. Executing a call to recover inside a deferred
+// function (but not any function called by it) stops the panicking sequence
+// by restoring normal execution and retrieves the error value passed to the
+// call of panic. If recover is called outside the deferred function it will
+// not stop a panicking sequence. In this case, or when the goroutine is not
+// panicking, or if the argument supplied to panic was nil, recover returns
+// nil. Thus the return value from recover reports whether the goroutine is
+// panicking.
+func recover() interface{}
+
+// The print built-in function formats its arguments in an implementation-
+// specific way and writes the result to standard error.
+// Print is useful for bootstrapping and debugging; it is not guaranteed
+// to stay in the language.
+func print(args ...Type)
+
+// The println built-in function formats its arguments in an implementation-
+// specific way and writes the result to standard error.
+// Spaces are always added between arguments and a newline is appended.
+// Println is useful for bootstrapping and debugging; it is not guaranteed
+// to stay in the language.
+func println(args ...Type)
+
+// The error built-in interface type is the conventional interface for
+// representing an error condition, with the nil value representing no error.
+type error interface {
+	Error() string
+}
diff --git a/third_party/gofrontend/libgo/go/bytes/buffer.go b/third_party/gofrontend/libgo/go/bytes/buffer.go
new file mode 100644
index 0000000..46ca1d5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/buffer.go
@@ -0,0 +1,412 @@
+// 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 bytes
+
+// Simple byte buffer for marshaling data.
+
+import (
+	"errors"
+	"io"
+	"unicode/utf8"
+)
+
+// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
+// The zero value for Buffer is an empty buffer ready to use.
+type Buffer struct {
+	buf       []byte            // contents are the bytes buf[off : len(buf)]
+	off       int               // read at &buf[off], write at &buf[len(buf)]
+	runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune
+	bootstrap [64]byte          // memory to hold first slice; helps small buffers (Printf) avoid allocation.
+	lastRead  readOp            // last read operation, so that Unread* can work correctly.
+}
+
+// The readOp constants describe the last action performed on
+// the buffer, so that UnreadRune and UnreadByte can
+// check for invalid usage.
+type readOp int
+
+const (
+	opInvalid  readOp = iota // Non-read operation.
+	opReadRune               // Read rune.
+	opRead                   // Any other read operation.
+)
+
+// ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer.
+var ErrTooLarge = errors.New("bytes.Buffer: too large")
+
+// Bytes returns a slice of the contents of the unread portion of the buffer;
+// len(b.Bytes()) == b.Len().  If the caller changes the contents of the
+// returned slice, the contents of the buffer will change provided there
+// are no intervening method calls on the Buffer.
+func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }
+
+// String returns the contents of the unread portion of the buffer
+// as a string.  If the Buffer is a nil pointer, it returns "<nil>".
+func (b *Buffer) String() string {
+	if b == nil {
+		// Special case, useful in debugging.
+		return "<nil>"
+	}
+	return string(b.buf[b.off:])
+}
+
+// Len returns the number of bytes of the unread portion of the buffer;
+// b.Len() == len(b.Bytes()).
+func (b *Buffer) Len() int { return len(b.buf) - b.off }
+
+// Truncate discards all but the first n unread bytes from the buffer.
+// It panics if n is negative or greater than the length of the buffer.
+func (b *Buffer) Truncate(n int) {
+	b.lastRead = opInvalid
+	switch {
+	case n < 0 || n > b.Len():
+		panic("bytes.Buffer: truncation out of range")
+	case n == 0:
+		// Reuse buffer space.
+		b.off = 0
+	}
+	b.buf = b.buf[0 : b.off+n]
+}
+
+// Reset resets the buffer so it has no content.
+// b.Reset() is the same as b.Truncate(0).
+func (b *Buffer) Reset() { b.Truncate(0) }
+
+// grow grows the buffer to guarantee space for n more bytes.
+// It returns the index where bytes should be written.
+// If the buffer can't grow it will panic with ErrTooLarge.
+func (b *Buffer) grow(n int) int {
+	m := b.Len()
+	// If buffer is empty, reset to recover space.
+	if m == 0 && b.off != 0 {
+		b.Truncate(0)
+	}
+	if len(b.buf)+n > cap(b.buf) {
+		var buf []byte
+		if b.buf == nil && n <= len(b.bootstrap) {
+			buf = b.bootstrap[0:]
+		} else if m+n <= cap(b.buf)/2 {
+			// We can slide things down instead of allocating a new
+			// slice. We only need m+n <= cap(b.buf) to slide, but
+			// we instead let capacity get twice as large so we
+			// don't spend all our time copying.
+			copy(b.buf[:], b.buf[b.off:])
+			buf = b.buf[:m]
+		} else {
+			// not enough space anywhere
+			buf = makeSlice(2*cap(b.buf) + n)
+			copy(buf, b.buf[b.off:])
+		}
+		b.buf = buf
+		b.off = 0
+	}
+	b.buf = b.buf[0 : b.off+m+n]
+	return b.off + m
+}
+
+// Grow grows the buffer's capacity, if necessary, to guarantee space for
+// another n bytes. After Grow(n), at least n bytes can be written to the
+// buffer without another allocation.
+// If n is negative, Grow will panic.
+// If the buffer can't grow it will panic with ErrTooLarge.
+func (b *Buffer) Grow(n int) {
+	if n < 0 {
+		panic("bytes.Buffer.Grow: negative count")
+	}
+	m := b.grow(n)
+	b.buf = b.buf[0:m]
+}
+
+// Write appends the contents of p to the buffer, growing the buffer as
+// needed. The return value n is the length of p; err is always nil. If the
+// buffer becomes too large, Write will panic with ErrTooLarge.
+func (b *Buffer) Write(p []byte) (n int, err error) {
+	b.lastRead = opInvalid
+	m := b.grow(len(p))
+	return copy(b.buf[m:], p), nil
+}
+
+// WriteString appends the contents of s to the buffer, growing the buffer as
+// needed. The return value n is the length of s; err is always nil. If the
+// buffer becomes too large, WriteString will panic with ErrTooLarge.
+func (b *Buffer) WriteString(s string) (n int, err error) {
+	b.lastRead = opInvalid
+	m := b.grow(len(s))
+	return copy(b.buf[m:], s), nil
+}
+
+// MinRead is the minimum slice size passed to a Read call by
+// Buffer.ReadFrom.  As long as the Buffer has at least MinRead bytes beyond
+// what is required to hold the contents of r, ReadFrom will not grow the
+// underlying buffer.
+const MinRead = 512
+
+// ReadFrom reads data from r until EOF and appends it to the buffer, growing
+// the buffer as needed. The return value n is the number of bytes read. Any
+// error except io.EOF encountered during the read is also returned. If the
+// buffer becomes too large, ReadFrom will panic with ErrTooLarge.
+func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
+	b.lastRead = opInvalid
+	// If buffer is empty, reset to recover space.
+	if b.off >= len(b.buf) {
+		b.Truncate(0)
+	}
+	for {
+		if free := cap(b.buf) - len(b.buf); free < MinRead {
+			// not enough space at end
+			newBuf := b.buf
+			if b.off+free < MinRead {
+				// not enough space using beginning of buffer;
+				// double buffer capacity
+				newBuf = makeSlice(2*cap(b.buf) + MinRead)
+			}
+			copy(newBuf, b.buf[b.off:])
+			b.buf = newBuf[:len(b.buf)-b.off]
+			b.off = 0
+		}
+		m, e := r.Read(b.buf[len(b.buf):cap(b.buf)])
+		b.buf = b.buf[0 : len(b.buf)+m]
+		n += int64(m)
+		if e == io.EOF {
+			break
+		}
+		if e != nil {
+			return n, e
+		}
+	}
+	return n, nil // err is EOF, so return nil explicitly
+}
+
+// makeSlice allocates a slice of size n. If the allocation fails, it panics
+// with ErrTooLarge.
+func makeSlice(n int) []byte {
+	// If the make fails, give a known error.
+	defer func() {
+		if recover() != nil {
+			panic(ErrTooLarge)
+		}
+	}()
+	return make([]byte, n)
+}
+
+// WriteTo writes data to w until the buffer is drained or an error occurs.
+// The return value n is the number of bytes written; it always fits into an
+// int, but it is int64 to match the io.WriterTo interface. Any error
+// encountered during the write is also returned.
+func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
+	b.lastRead = opInvalid
+	if b.off < len(b.buf) {
+		nBytes := b.Len()
+		m, e := w.Write(b.buf[b.off:])
+		if m > nBytes {
+			panic("bytes.Buffer.WriteTo: invalid Write count")
+		}
+		b.off += m
+		n = int64(m)
+		if e != nil {
+			return n, e
+		}
+		// all bytes should have been written, by definition of
+		// Write method in io.Writer
+		if m != nBytes {
+			return n, io.ErrShortWrite
+		}
+	}
+	// Buffer is now empty; reset.
+	b.Truncate(0)
+	return
+}
+
+// WriteByte appends the byte c to the buffer, growing the buffer as needed.
+// The returned error is always nil, but is included to match bufio.Writer's
+// WriteByte. If the buffer becomes too large, WriteByte will panic with
+// ErrTooLarge.
+func (b *Buffer) WriteByte(c byte) error {
+	b.lastRead = opInvalid
+	m := b.grow(1)
+	b.buf[m] = c
+	return nil
+}
+
+// WriteRune appends the UTF-8 encoding of Unicode code point r to the
+// buffer, returning its length and an error, which is always nil but is
+// included to match bufio.Writer's WriteRune. The buffer is grown as needed;
+// if it becomes too large, WriteRune will panic with ErrTooLarge.
+func (b *Buffer) WriteRune(r rune) (n int, err error) {
+	if r < utf8.RuneSelf {
+		b.WriteByte(byte(r))
+		return 1, nil
+	}
+	n = utf8.EncodeRune(b.runeBytes[0:], r)
+	b.Write(b.runeBytes[0:n])
+	return n, nil
+}
+
+// Read reads the next len(p) bytes from the buffer or until the buffer
+// is drained.  The return value n is the number of bytes read.  If the
+// buffer has no data to return, err is io.EOF (unless len(p) is zero);
+// otherwise it is nil.
+func (b *Buffer) Read(p []byte) (n int, err error) {
+	b.lastRead = opInvalid
+	if b.off >= len(b.buf) {
+		// Buffer is empty, reset to recover space.
+		b.Truncate(0)
+		if len(p) == 0 {
+			return
+		}
+		return 0, io.EOF
+	}
+	n = copy(p, b.buf[b.off:])
+	b.off += n
+	if n > 0 {
+		b.lastRead = opRead
+	}
+	return
+}
+
+// Next returns a slice containing the next n bytes from the buffer,
+// advancing the buffer as if the bytes had been returned by Read.
+// If there are fewer than n bytes in the buffer, Next returns the entire buffer.
+// The slice is only valid until the next call to a read or write method.
+func (b *Buffer) Next(n int) []byte {
+	b.lastRead = opInvalid
+	m := b.Len()
+	if n > m {
+		n = m
+	}
+	data := b.buf[b.off : b.off+n]
+	b.off += n
+	if n > 0 {
+		b.lastRead = opRead
+	}
+	return data
+}
+
+// ReadByte reads and returns the next byte from the buffer.
+// If no byte is available, it returns error io.EOF.
+func (b *Buffer) ReadByte() (c byte, err error) {
+	b.lastRead = opInvalid
+	if b.off >= len(b.buf) {
+		// Buffer is empty, reset to recover space.
+		b.Truncate(0)
+		return 0, io.EOF
+	}
+	c = b.buf[b.off]
+	b.off++
+	b.lastRead = opRead
+	return c, nil
+}
+
+// ReadRune reads and returns the next UTF-8-encoded
+// Unicode code point from the buffer.
+// If no bytes are available, the error returned is io.EOF.
+// If the bytes are an erroneous UTF-8 encoding, it
+// consumes one byte and returns U+FFFD, 1.
+func (b *Buffer) ReadRune() (r rune, size int, err error) {
+	b.lastRead = opInvalid
+	if b.off >= len(b.buf) {
+		// Buffer is empty, reset to recover space.
+		b.Truncate(0)
+		return 0, 0, io.EOF
+	}
+	b.lastRead = opReadRune
+	c := b.buf[b.off]
+	if c < utf8.RuneSelf {
+		b.off++
+		return rune(c), 1, nil
+	}
+	r, n := utf8.DecodeRune(b.buf[b.off:])
+	b.off += n
+	return r, n, nil
+}
+
+// UnreadRune unreads the last rune returned by ReadRune.
+// If the most recent read or write operation on the buffer was
+// not a ReadRune, UnreadRune returns an error.  (In this regard
+// it is stricter than UnreadByte, which will unread the last byte
+// from any read operation.)
+func (b *Buffer) UnreadRune() error {
+	if b.lastRead != opReadRune {
+		return errors.New("bytes.Buffer: UnreadRune: previous operation was not ReadRune")
+	}
+	b.lastRead = opInvalid
+	if b.off > 0 {
+		_, n := utf8.DecodeLastRune(b.buf[0:b.off])
+		b.off -= n
+	}
+	return nil
+}
+
+// UnreadByte unreads the last byte returned by the most recent
+// read operation.  If write has happened since the last read, UnreadByte
+// returns an error.
+func (b *Buffer) UnreadByte() error {
+	if b.lastRead != opReadRune && b.lastRead != opRead {
+		return errors.New("bytes.Buffer: UnreadByte: previous operation was not a read")
+	}
+	b.lastRead = opInvalid
+	if b.off > 0 {
+		b.off--
+	}
+	return nil
+}
+
+// ReadBytes reads until the first occurrence of delim in the input,
+// returning a slice containing the data up to and including the delimiter.
+// If ReadBytes encounters an error before finding a delimiter,
+// it returns the data read before the error and the error itself (often io.EOF).
+// ReadBytes returns err != nil if and only if the returned data does not end in
+// delim.
+func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
+	slice, err := b.readSlice(delim)
+	// return a copy of slice. The buffer's backing array may
+	// be overwritten by later calls.
+	line = append(line, slice...)
+	return
+}
+
+// readSlice is like ReadBytes but returns a reference to internal buffer data.
+func (b *Buffer) readSlice(delim byte) (line []byte, err error) {
+	i := IndexByte(b.buf[b.off:], delim)
+	end := b.off + i + 1
+	if i < 0 {
+		end = len(b.buf)
+		err = io.EOF
+	}
+	line = b.buf[b.off:end]
+	b.off = end
+	b.lastRead = opRead
+	return line, err
+}
+
+// ReadString reads until the first occurrence of delim in the input,
+// returning a string containing the data up to and including the delimiter.
+// If ReadString encounters an error before finding a delimiter,
+// it returns the data read before the error and the error itself (often io.EOF).
+// ReadString returns err != nil if and only if the returned data does not end
+// in delim.
+func (b *Buffer) ReadString(delim byte) (line string, err error) {
+	slice, err := b.readSlice(delim)
+	return string(slice), err
+}
+
+// NewBuffer creates and initializes a new Buffer using buf as its initial
+// contents.  It is intended to prepare a Buffer to read existing data.  It
+// can also be used to size the internal buffer for writing. To do that,
+// buf should have the desired capacity but a length of zero.
+//
+// In most cases, new(Buffer) (or just declaring a Buffer variable) is
+// sufficient to initialize a Buffer.
+func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
+
+// NewBufferString creates and initializes a new Buffer using string s as its
+// initial contents. It is intended to prepare a buffer to read an existing
+// string.
+//
+// In most cases, new(Buffer) (or just declaring a Buffer variable) is
+// sufficient to initialize a Buffer.
+func NewBufferString(s string) *Buffer {
+	return &Buffer{buf: []byte(s)}
+}
diff --git a/third_party/gofrontend/libgo/go/bytes/buffer_test.go b/third_party/gofrontend/libgo/go/bytes/buffer_test.go
new file mode 100644
index 0000000..75145b0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/buffer_test.go
@@ -0,0 +1,527 @@
+// 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 bytes_test
+
+import (
+	. "bytes"
+	"io"
+	"math/rand"
+	"runtime"
+	"testing"
+	"unicode/utf8"
+)
+
+const N = 10000      // make this bigger for a larger (and slower) test
+var data string      // test data for write tests
+var testBytes []byte // test data; same as data but as a slice.
+
+func init() {
+	testBytes = make([]byte, N)
+	for i := 0; i < N; i++ {
+		testBytes[i] = 'a' + byte(i%26)
+	}
+	data = string(testBytes)
+}
+
+// Verify that contents of buf match the string s.
+func check(t *testing.T, testname string, buf *Buffer, s string) {
+	bytes := buf.Bytes()
+	str := buf.String()
+	if buf.Len() != len(bytes) {
+		t.Errorf("%s: buf.Len() == %d, len(buf.Bytes()) == %d", testname, buf.Len(), len(bytes))
+	}
+
+	if buf.Len() != len(str) {
+		t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d", testname, buf.Len(), len(str))
+	}
+
+	if buf.Len() != len(s) {
+		t.Errorf("%s: buf.Len() == %d, len(s) == %d", testname, buf.Len(), len(s))
+	}
+
+	if string(bytes) != s {
+		t.Errorf("%s: string(buf.Bytes()) == %q, s == %q", testname, string(bytes), s)
+	}
+}
+
+// Fill buf through n writes of string fus.
+// The initial contents of buf corresponds to the string s;
+// the result is the final contents of buf returned as a string.
+func fillString(t *testing.T, testname string, buf *Buffer, s string, n int, fus string) string {
+	check(t, testname+" (fill 1)", buf, s)
+	for ; n > 0; n-- {
+		m, err := buf.WriteString(fus)
+		if m != len(fus) {
+			t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fus))
+		}
+		if err != nil {
+			t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err)
+		}
+		s += fus
+		check(t, testname+" (fill 4)", buf, s)
+	}
+	return s
+}
+
+// Fill buf through n writes of byte slice fub.
+// The initial contents of buf corresponds to the string s;
+// the result is the final contents of buf returned as a string.
+func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub []byte) string {
+	check(t, testname+" (fill 1)", buf, s)
+	for ; n > 0; n-- {
+		m, err := buf.Write(fub)
+		if m != len(fub) {
+			t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fub))
+		}
+		if err != nil {
+			t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err)
+		}
+		s += string(fub)
+		check(t, testname+" (fill 4)", buf, s)
+	}
+	return s
+}
+
+func TestNewBuffer(t *testing.T) {
+	buf := NewBuffer(testBytes)
+	check(t, "NewBuffer", buf, data)
+}
+
+func TestNewBufferString(t *testing.T) {
+	buf := NewBufferString(data)
+	check(t, "NewBufferString", buf, data)
+}
+
+// Empty buf through repeated reads into fub.
+// The initial contents of buf corresponds to the string s.
+func empty(t *testing.T, testname string, buf *Buffer, s string, fub []byte) {
+	check(t, testname+" (empty 1)", buf, s)
+
+	for {
+		n, err := buf.Read(fub)
+		if n == 0 {
+			break
+		}
+		if err != nil {
+			t.Errorf(testname+" (empty 2): err should always be nil, found err == %s", err)
+		}
+		s = s[n:]
+		check(t, testname+" (empty 3)", buf, s)
+	}
+
+	check(t, testname+" (empty 4)", buf, "")
+}
+
+func TestBasicOperations(t *testing.T) {
+	var buf Buffer
+
+	for i := 0; i < 5; i++ {
+		check(t, "TestBasicOperations (1)", &buf, "")
+
+		buf.Reset()
+		check(t, "TestBasicOperations (2)", &buf, "")
+
+		buf.Truncate(0)
+		check(t, "TestBasicOperations (3)", &buf, "")
+
+		n, err := buf.Write([]byte(data[0:1]))
+		if n != 1 {
+			t.Errorf("wrote 1 byte, but n == %d", n)
+		}
+		if err != nil {
+			t.Errorf("err should always be nil, but err == %s", err)
+		}
+		check(t, "TestBasicOperations (4)", &buf, "a")
+
+		buf.WriteByte(data[1])
+		check(t, "TestBasicOperations (5)", &buf, "ab")
+
+		n, err = buf.Write([]byte(data[2:26]))
+		if n != 24 {
+			t.Errorf("wrote 25 bytes, but n == %d", n)
+		}
+		check(t, "TestBasicOperations (6)", &buf, string(data[0:26]))
+
+		buf.Truncate(26)
+		check(t, "TestBasicOperations (7)", &buf, string(data[0:26]))
+
+		buf.Truncate(20)
+		check(t, "TestBasicOperations (8)", &buf, string(data[0:20]))
+
+		empty(t, "TestBasicOperations (9)", &buf, string(data[0:20]), make([]byte, 5))
+		empty(t, "TestBasicOperations (10)", &buf, "", make([]byte, 100))
+
+		buf.WriteByte(data[1])
+		c, err := buf.ReadByte()
+		if err != nil {
+			t.Error("ReadByte unexpected eof")
+		}
+		if c != data[1] {
+			t.Errorf("ReadByte wrong value c=%v", c)
+		}
+		c, err = buf.ReadByte()
+		if err == nil {
+			t.Error("ReadByte unexpected not eof")
+		}
+	}
+}
+
+func TestLargeStringWrites(t *testing.T) {
+	var buf Buffer
+	limit := 30
+	if testing.Short() {
+		limit = 9
+	}
+	for i := 3; i < limit; i += 3 {
+		s := fillString(t, "TestLargeWrites (1)", &buf, "", 5, data)
+		empty(t, "TestLargeStringWrites (2)", &buf, s, make([]byte, len(data)/i))
+	}
+	check(t, "TestLargeStringWrites (3)", &buf, "")
+}
+
+func TestLargeByteWrites(t *testing.T) {
+	var buf Buffer
+	limit := 30
+	if testing.Short() {
+		limit = 9
+	}
+	for i := 3; i < limit; i += 3 {
+		s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, testBytes)
+		empty(t, "TestLargeByteWrites (2)", &buf, s, make([]byte, len(data)/i))
+	}
+	check(t, "TestLargeByteWrites (3)", &buf, "")
+}
+
+func TestLargeStringReads(t *testing.T) {
+	var buf Buffer
+	for i := 3; i < 30; i += 3 {
+		s := fillString(t, "TestLargeReads (1)", &buf, "", 5, data[0:len(data)/i])
+		empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data)))
+	}
+	check(t, "TestLargeStringReads (3)", &buf, "")
+}
+
+func TestLargeByteReads(t *testing.T) {
+	var buf Buffer
+	for i := 3; i < 30; i += 3 {
+		s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
+		empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data)))
+	}
+	check(t, "TestLargeByteReads (3)", &buf, "")
+}
+
+func TestMixedReadsAndWrites(t *testing.T) {
+	var buf Buffer
+	s := ""
+	for i := 0; i < 50; i++ {
+		wlen := rand.Intn(len(data))
+		if i%2 == 0 {
+			s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0:wlen])
+		} else {
+			s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testBytes[0:wlen])
+		}
+
+		rlen := rand.Intn(len(data))
+		fub := make([]byte, rlen)
+		n, _ := buf.Read(fub)
+		s = s[n:]
+	}
+	empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len()))
+}
+
+func TestNil(t *testing.T) {
+	var b *Buffer
+	if b.String() != "<nil>" {
+		t.Errorf("expected <nil>; got %q", b.String())
+	}
+}
+
+func TestReadFrom(t *testing.T) {
+	var buf Buffer
+	for i := 3; i < 30; i += 3 {
+		s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
+		var b Buffer
+		b.ReadFrom(&buf)
+		empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(data)))
+	}
+}
+
+func TestWriteTo(t *testing.T) {
+	var buf Buffer
+	for i := 3; i < 30; i += 3 {
+		s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
+		var b Buffer
+		buf.WriteTo(&b)
+		empty(t, "TestWriteTo (2)", &b, s, make([]byte, len(data)))
+	}
+}
+
+func TestRuneIO(t *testing.T) {
+	const NRune = 1000
+	// Built a test slice while we write the data
+	b := make([]byte, utf8.UTFMax*NRune)
+	var buf Buffer
+	n := 0
+	for r := rune(0); r < NRune; r++ {
+		size := utf8.EncodeRune(b[n:], r)
+		nbytes, err := buf.WriteRune(r)
+		if err != nil {
+			t.Fatalf("WriteRune(%U) error: %s", r, err)
+		}
+		if nbytes != size {
+			t.Fatalf("WriteRune(%U) expected %d, got %d", r, size, nbytes)
+		}
+		n += size
+	}
+	b = b[0:n]
+
+	// Check the resulting bytes
+	if !Equal(buf.Bytes(), b) {
+		t.Fatalf("incorrect result from WriteRune: %q not %q", buf.Bytes(), b)
+	}
+
+	p := make([]byte, utf8.UTFMax)
+	// Read it back with ReadRune
+	for r := rune(0); r < NRune; r++ {
+		size := utf8.EncodeRune(p, r)
+		nr, nbytes, err := buf.ReadRune()
+		if nr != r || nbytes != size || err != nil {
+			t.Fatalf("ReadRune(%U) got %U,%d not %U,%d (err=%s)", r, nr, nbytes, r, size, err)
+		}
+	}
+
+	// Check that UnreadRune works
+	buf.Reset()
+	buf.Write(b)
+	for r := rune(0); r < NRune; r++ {
+		r1, size, _ := buf.ReadRune()
+		if err := buf.UnreadRune(); err != nil {
+			t.Fatalf("UnreadRune(%U) got error %q", r, err)
+		}
+		r2, nbytes, err := buf.ReadRune()
+		if r1 != r2 || r1 != r || nbytes != size || err != nil {
+			t.Fatalf("ReadRune(%U) after UnreadRune got %U,%d not %U,%d (err=%s)", r, r2, nbytes, r, size, err)
+		}
+	}
+}
+
+func TestNext(t *testing.T) {
+	b := []byte{0, 1, 2, 3, 4}
+	tmp := make([]byte, 5)
+	for i := 0; i <= 5; i++ {
+		for j := i; j <= 5; j++ {
+			for k := 0; k <= 6; k++ {
+				// 0 <= i <= j <= 5; 0 <= k <= 6
+				// Check that if we start with a buffer
+				// of length j at offset i and ask for
+				// Next(k), we get the right bytes.
+				buf := NewBuffer(b[0:j])
+				n, _ := buf.Read(tmp[0:i])
+				if n != i {
+					t.Fatalf("Read %d returned %d", i, n)
+				}
+				bb := buf.Next(k)
+				want := k
+				if want > j-i {
+					want = j - i
+				}
+				if len(bb) != want {
+					t.Fatalf("in %d,%d: len(Next(%d)) == %d", i, j, k, len(bb))
+				}
+				for l, v := range bb {
+					if v != byte(l+i) {
+						t.Fatalf("in %d,%d: Next(%d)[%d] = %d, want %d", i, j, k, l, v, l+i)
+					}
+				}
+			}
+		}
+	}
+}
+
+var readBytesTests = []struct {
+	buffer   string
+	delim    byte
+	expected []string
+	err      error
+}{
+	{"", 0, []string{""}, io.EOF},
+	{"a\x00", 0, []string{"a\x00"}, nil},
+	{"abbbaaaba", 'b', []string{"ab", "b", "b", "aaab"}, nil},
+	{"hello\x01world", 1, []string{"hello\x01"}, nil},
+	{"foo\nbar", 0, []string{"foo\nbar"}, io.EOF},
+	{"alpha\nbeta\ngamma\n", '\n', []string{"alpha\n", "beta\n", "gamma\n"}, nil},
+	{"alpha\nbeta\ngamma", '\n', []string{"alpha\n", "beta\n", "gamma"}, io.EOF},
+}
+
+func TestReadBytes(t *testing.T) {
+	for _, test := range readBytesTests {
+		buf := NewBufferString(test.buffer)
+		var err error
+		for _, expected := range test.expected {
+			var bytes []byte
+			bytes, err = buf.ReadBytes(test.delim)
+			if string(bytes) != expected {
+				t.Errorf("expected %q, got %q", expected, bytes)
+			}
+			if err != nil {
+				break
+			}
+		}
+		if err != test.err {
+			t.Errorf("expected error %v, got %v", test.err, err)
+		}
+	}
+}
+
+func TestReadString(t *testing.T) {
+	for _, test := range readBytesTests {
+		buf := NewBufferString(test.buffer)
+		var err error
+		for _, expected := range test.expected {
+			var s string
+			s, err = buf.ReadString(test.delim)
+			if s != expected {
+				t.Errorf("expected %q, got %q", expected, s)
+			}
+			if err != nil {
+				break
+			}
+		}
+		if err != test.err {
+			t.Errorf("expected error %v, got %v", test.err, err)
+		}
+	}
+}
+
+func BenchmarkReadString(b *testing.B) {
+	const n = 32 << 10
+
+	data := make([]byte, n)
+	data[n-1] = 'x'
+	b.SetBytes(int64(n))
+	for i := 0; i < b.N; i++ {
+		buf := NewBuffer(data)
+		_, err := buf.ReadString('x')
+		if err != nil {
+			b.Fatal(err)
+		}
+	}
+}
+
+func TestGrow(t *testing.T) {
+	x := []byte{'x'}
+	y := []byte{'y'}
+	tmp := make([]byte, 72)
+	for _, startLen := range []int{0, 100, 1000, 10000, 100000} {
+		xBytes := Repeat(x, startLen)
+		for _, growLen := range []int{0, 100, 1000, 10000, 100000} {
+			buf := NewBuffer(xBytes)
+			// If we read, this affects buf.off, which is good to test.
+			readBytes, _ := buf.Read(tmp)
+			buf.Grow(growLen)
+			yBytes := Repeat(y, growLen)
+			// Check no allocation occurs in write, as long as we're single-threaded.
+			var m1, m2 runtime.MemStats
+			runtime.ReadMemStats(&m1)
+			buf.Write(yBytes)
+			runtime.ReadMemStats(&m2)
+			if runtime.GOMAXPROCS(-1) == 1 && m1.Mallocs != m2.Mallocs {
+				t.Errorf("allocation occurred during write")
+			}
+			// Check that buffer has correct data.
+			if !Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) {
+				t.Errorf("bad initial data at %d %d", startLen, growLen)
+			}
+			if !Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) {
+				t.Errorf("bad written data at %d %d", startLen, growLen)
+			}
+		}
+	}
+}
+
+// Was a bug: used to give EOF reading empty slice at EOF.
+func TestReadEmptyAtEOF(t *testing.T) {
+	b := new(Buffer)
+	slice := make([]byte, 0)
+	n, err := b.Read(slice)
+	if err != nil {
+		t.Errorf("read error: %v", err)
+	}
+	if n != 0 {
+		t.Errorf("wrong count; got %d want 0", n)
+	}
+}
+
+func TestUnreadByte(t *testing.T) {
+	b := new(Buffer)
+	b.WriteString("abcdefghijklmnopqrstuvwxyz")
+
+	_, err := b.ReadBytes('m')
+	if err != nil {
+		t.Fatalf("ReadBytes: %v", err)
+	}
+
+	err = b.UnreadByte()
+	if err != nil {
+		t.Fatalf("UnreadByte: %v", err)
+	}
+	c, err := b.ReadByte()
+	if err != nil {
+		t.Fatalf("ReadByte: %v", err)
+	}
+	if c != 'm' {
+		t.Errorf("ReadByte = %q; want %q", c, 'm')
+	}
+}
+
+// Tests that we occasionally compact. Issue 5154.
+func TestBufferGrowth(t *testing.T) {
+	var b Buffer
+	buf := make([]byte, 1024)
+	b.Write(buf[0:1])
+	var cap0 int
+	for i := 0; i < 5<<10; i++ {
+		b.Write(buf)
+		b.Read(buf)
+		if i == 0 {
+			cap0 = b.Cap()
+		}
+	}
+	cap1 := b.Cap()
+	// (*Buffer).grow allows for 2x capacity slop before sliding,
+	// so set our error threshold at 3x.
+	if cap1 > cap0*3 {
+		t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0)
+	}
+}
+
+// From Issue 5154.
+func BenchmarkBufferNotEmptyWriteRead(b *testing.B) {
+	buf := make([]byte, 1024)
+	for i := 0; i < b.N; i++ {
+		var b Buffer
+		b.Write(buf[0:1])
+		for i := 0; i < 5<<10; i++ {
+			b.Write(buf)
+			b.Read(buf)
+		}
+	}
+}
+
+// Check that we don't compact too often. From Issue 5154.
+func BenchmarkBufferFullSmallReads(b *testing.B) {
+	buf := make([]byte, 1024)
+	for i := 0; i < b.N; i++ {
+		var b Buffer
+		b.Write(buf)
+		for b.Len()+20 < b.Cap() {
+			b.Write(buf[:10])
+		}
+		for i := 0; i < 5<<10; i++ {
+			b.Read(buf[:1])
+			b.Write(buf[:1])
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/bytes/bytes.go b/third_party/gofrontend/libgo/go/bytes/bytes.go
new file mode 100644
index 0000000..0c53e4c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/bytes.go
@@ -0,0 +1,697 @@
+// 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 bytes implements functions for the manipulation of byte slices.
+// It is analogous to the facilities of the strings package.
+package bytes
+
+import (
+	"unicode"
+	"unicode/utf8"
+)
+
+func equalPortable(a, b []byte) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i, c := range a {
+		if c != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// explode splits s into a slice of UTF-8 sequences, one per Unicode character (still slices of bytes),
+// up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes.
+func explode(s []byte, n int) [][]byte {
+	if n <= 0 {
+		n = len(s)
+	}
+	a := make([][]byte, n)
+	var size int
+	na := 0
+	for len(s) > 0 {
+		if na+1 >= n {
+			a[na] = s
+			na++
+			break
+		}
+		_, size = utf8.DecodeRune(s)
+		a[na] = s[0:size]
+		s = s[size:]
+		na++
+	}
+	return a[0:na]
+}
+
+// Count counts the number of non-overlapping instances of sep in s.
+func Count(s, sep []byte) int {
+	n := len(sep)
+	if n == 0 {
+		return utf8.RuneCount(s) + 1
+	}
+	if n > len(s) {
+		return 0
+	}
+	count := 0
+	c := sep[0]
+	i := 0
+	t := s[:len(s)-n+1]
+	for i < len(t) {
+		if t[i] != c {
+			o := IndexByte(t[i:], c)
+			if o < 0 {
+				break
+			}
+			i += o
+		}
+		if n == 1 || Equal(s[i:i+n], sep) {
+			count++
+			i += n
+			continue
+		}
+		i++
+	}
+	return count
+}
+
+// Contains reports whether subslice is within b.
+func Contains(b, subslice []byte) bool {
+	return Index(b, subslice) != -1
+}
+
+// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
+func Index(s, sep []byte) int {
+	n := len(sep)
+	if n == 0 {
+		return 0
+	}
+	if n > len(s) {
+		return -1
+	}
+	c := sep[0]
+	if n == 1 {
+		return IndexByte(s, c)
+	}
+	i := 0
+	t := s[:len(s)-n+1]
+	for i < len(t) {
+		if t[i] != c {
+			o := IndexByte(t[i:], c)
+			if o < 0 {
+				break
+			}
+			i += o
+		}
+		if Equal(s[i:i+n], sep) {
+			return i
+		}
+		i++
+	}
+	return -1
+}
+
+func indexBytePortable(s []byte, c byte) int {
+	for i, b := range s {
+		if b == c {
+			return i
+		}
+	}
+	return -1
+}
+
+// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
+func LastIndex(s, sep []byte) int {
+	n := len(sep)
+	if n == 0 {
+		return len(s)
+	}
+	c := sep[0]
+	for i := len(s) - n; i >= 0; i-- {
+		if s[i] == c && (n == 1 || Equal(s[i:i+n], sep)) {
+			return i
+		}
+	}
+	return -1
+}
+
+// IndexRune interprets s as a sequence of UTF-8-encoded Unicode code points.
+// It returns the byte index of the first occurrence in s of the given rune.
+// It returns -1 if rune is not present in s.
+func IndexRune(s []byte, r rune) int {
+	for i := 0; i < len(s); {
+		r1, size := utf8.DecodeRune(s[i:])
+		if r == r1 {
+			return i
+		}
+		i += size
+	}
+	return -1
+}
+
+// IndexAny interprets s as a sequence of UTF-8-encoded Unicode code points.
+// It returns the byte index of the first occurrence in s of any of the Unicode
+// code points in chars.  It returns -1 if chars is empty or if there is no code
+// point in common.
+func IndexAny(s []byte, chars string) int {
+	if len(chars) > 0 {
+		var r rune
+		var width int
+		for i := 0; i < len(s); i += width {
+			r = rune(s[i])
+			if r < utf8.RuneSelf {
+				width = 1
+			} else {
+				r, width = utf8.DecodeRune(s[i:])
+			}
+			for _, ch := range chars {
+				if r == ch {
+					return i
+				}
+			}
+		}
+	}
+	return -1
+}
+
+// LastIndexAny interprets s as a sequence of UTF-8-encoded Unicode code
+// points.  It returns the byte index of the last occurrence in s of any of
+// the Unicode code points in chars.  It returns -1 if chars is empty or if
+// there is no code point in common.
+func LastIndexAny(s []byte, chars string) int {
+	if len(chars) > 0 {
+		for i := len(s); i > 0; {
+			r, size := utf8.DecodeLastRune(s[0:i])
+			i -= size
+			for _, ch := range chars {
+				if r == ch {
+					return i
+				}
+			}
+		}
+	}
+	return -1
+}
+
+// Generic split: splits after each instance of sep,
+// including sepSave bytes of sep in the subslices.
+func genSplit(s, sep []byte, sepSave, n int) [][]byte {
+	if n == 0 {
+		return nil
+	}
+	if len(sep) == 0 {
+		return explode(s, n)
+	}
+	if n < 0 {
+		n = Count(s, sep) + 1
+	}
+	c := sep[0]
+	start := 0
+	a := make([][]byte, n)
+	na := 0
+	for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ {
+		if s[i] == c && (len(sep) == 1 || Equal(s[i:i+len(sep)], sep)) {
+			a[na] = s[start : i+sepSave]
+			na++
+			start = i + len(sep)
+			i += len(sep) - 1
+		}
+	}
+	a[na] = s[start:]
+	return a[0 : na+1]
+}
+
+// SplitN slices s into subslices separated by sep and returns a slice of
+// the subslices between those separators.
+// If sep is empty, SplitN splits after each UTF-8 sequence.
+// The count determines the number of subslices to return:
+//   n > 0: at most n subslices; the last subslice will be the unsplit remainder.
+//   n == 0: the result is nil (zero subslices)
+//   n < 0: all subslices
+func SplitN(s, sep []byte, n int) [][]byte { return genSplit(s, sep, 0, n) }
+
+// SplitAfterN slices s into subslices after each instance of sep and
+// returns a slice of those subslices.
+// If sep is empty, SplitAfterN splits after each UTF-8 sequence.
+// The count determines the number of subslices to return:
+//   n > 0: at most n subslices; the last subslice will be the unsplit remainder.
+//   n == 0: the result is nil (zero subslices)
+//   n < 0: all subslices
+func SplitAfterN(s, sep []byte, n int) [][]byte {
+	return genSplit(s, sep, len(sep), n)
+}
+
+// Split slices s into all subslices separated by sep and returns a slice of
+// the subslices between those separators.
+// If sep is empty, Split splits after each UTF-8 sequence.
+// It is equivalent to SplitN with a count of -1.
+func Split(s, sep []byte) [][]byte { return genSplit(s, sep, 0, -1) }
+
+// SplitAfter slices s into all subslices after each instance of sep and
+// returns a slice of those subslices.
+// If sep is empty, SplitAfter splits after each UTF-8 sequence.
+// It is equivalent to SplitAfterN with a count of -1.
+func SplitAfter(s, sep []byte) [][]byte {
+	return genSplit(s, sep, len(sep), -1)
+}
+
+// Fields splits the slice s around each instance of one or more consecutive white space
+// characters, returning a slice of subslices of s or an empty list if s contains only white space.
+func Fields(s []byte) [][]byte {
+	return FieldsFunc(s, unicode.IsSpace)
+}
+
+// FieldsFunc interprets s as a sequence of UTF-8-encoded Unicode code points.
+// It splits the slice s at each run of code points c satisfying f(c) and
+// returns a slice of subslices of s.  If all code points in s satisfy f(c), or
+// len(s) == 0, an empty slice is returned.
+func FieldsFunc(s []byte, f func(rune) bool) [][]byte {
+	n := 0
+	inField := false
+	for i := 0; i < len(s); {
+		r, size := utf8.DecodeRune(s[i:])
+		wasInField := inField
+		inField = !f(r)
+		if inField && !wasInField {
+			n++
+		}
+		i += size
+	}
+
+	a := make([][]byte, n)
+	na := 0
+	fieldStart := -1
+	for i := 0; i <= len(s) && na < n; {
+		r, size := utf8.DecodeRune(s[i:])
+		if fieldStart < 0 && size > 0 && !f(r) {
+			fieldStart = i
+			i += size
+			continue
+		}
+		if fieldStart >= 0 && (size == 0 || f(r)) {
+			a[na] = s[fieldStart:i]
+			na++
+			fieldStart = -1
+		}
+		if size == 0 {
+			break
+		}
+		i += size
+	}
+	return a[0:na]
+}
+
+// Join concatenates the elements of s to create a new byte slice. The separator
+// sep is placed between elements in the resulting slice.
+func Join(s [][]byte, sep []byte) []byte {
+	if len(s) == 0 {
+		return []byte{}
+	}
+	if len(s) == 1 {
+		// Just return a copy.
+		return append([]byte(nil), s[0]...)
+	}
+	n := len(sep) * (len(s) - 1)
+	for _, v := range s {
+		n += len(v)
+	}
+
+	b := make([]byte, n)
+	bp := copy(b, s[0])
+	for _, v := range s[1:] {
+		bp += copy(b[bp:], sep)
+		bp += copy(b[bp:], v)
+	}
+	return b
+}
+
+// HasPrefix tests whether the byte slice s begins with prefix.
+func HasPrefix(s, prefix []byte) bool {
+	return len(s) >= len(prefix) && Equal(s[0:len(prefix)], prefix)
+}
+
+// HasSuffix tests whether the byte slice s ends with suffix.
+func HasSuffix(s, suffix []byte) bool {
+	return len(s) >= len(suffix) && Equal(s[len(s)-len(suffix):], suffix)
+}
+
+// Map returns a copy of the byte slice s with all its characters modified
+// according to the mapping function. If mapping returns a negative value, the character is
+// dropped from the string with no replacement.  The characters in s and the
+// output are interpreted as UTF-8-encoded Unicode code points.
+func Map(mapping func(r rune) rune, s []byte) []byte {
+	// In the worst case, the slice can grow when mapped, making
+	// things unpleasant.  But it's so rare we barge in assuming it's
+	// fine.  It could also shrink but that falls out naturally.
+	maxbytes := len(s) // length of b
+	nbytes := 0        // number of bytes encoded in b
+	b := make([]byte, maxbytes)
+	for i := 0; i < len(s); {
+		wid := 1
+		r := rune(s[i])
+		if r >= utf8.RuneSelf {
+			r, wid = utf8.DecodeRune(s[i:])
+		}
+		r = mapping(r)
+		if r >= 0 {
+			rl := utf8.RuneLen(r)
+			if rl < 0 {
+				rl = len(string(utf8.RuneError))
+			}
+			if nbytes+rl > maxbytes {
+				// Grow the buffer.
+				maxbytes = maxbytes*2 + utf8.UTFMax
+				nb := make([]byte, maxbytes)
+				copy(nb, b[0:nbytes])
+				b = nb
+			}
+			nbytes += utf8.EncodeRune(b[nbytes:maxbytes], r)
+		}
+		i += wid
+	}
+	return b[0:nbytes]
+}
+
+// Repeat returns a new byte slice consisting of count copies of b.
+func Repeat(b []byte, count int) []byte {
+	nb := make([]byte, len(b)*count)
+	bp := 0
+	for i := 0; i < count; i++ {
+		bp += copy(nb[bp:], b)
+	}
+	return nb
+}
+
+// ToUpper returns a copy of the byte slice s with all Unicode letters mapped to their upper case.
+func ToUpper(s []byte) []byte { return Map(unicode.ToUpper, s) }
+
+// ToLower returns a copy of the byte slice s with all Unicode letters mapped to their lower case.
+func ToLower(s []byte) []byte { return Map(unicode.ToLower, s) }
+
+// ToTitle returns a copy of the byte slice s with all Unicode letters mapped to their title case.
+func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
+
+// ToUpperSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
+// upper case, giving priority to the special casing rules.
+func ToUpperSpecial(_case unicode.SpecialCase, s []byte) []byte {
+	return Map(func(r rune) rune { return _case.ToUpper(r) }, s)
+}
+
+// ToLowerSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
+// lower case, giving priority to the special casing rules.
+func ToLowerSpecial(_case unicode.SpecialCase, s []byte) []byte {
+	return Map(func(r rune) rune { return _case.ToLower(r) }, s)
+}
+
+// ToTitleSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
+// title case, giving priority to the special casing rules.
+func ToTitleSpecial(_case unicode.SpecialCase, s []byte) []byte {
+	return Map(func(r rune) rune { return _case.ToTitle(r) }, s)
+}
+
+// isSeparator reports whether the rune could mark a word boundary.
+// TODO: update when package unicode captures more of the properties.
+func isSeparator(r rune) bool {
+	// ASCII alphanumerics and underscore are not separators
+	if r <= 0x7F {
+		switch {
+		case '0' <= r && r <= '9':
+			return false
+		case 'a' <= r && r <= 'z':
+			return false
+		case 'A' <= r && r <= 'Z':
+			return false
+		case r == '_':
+			return false
+		}
+		return true
+	}
+	// Letters and digits are not separators
+	if unicode.IsLetter(r) || unicode.IsDigit(r) {
+		return false
+	}
+	// Otherwise, all we can do for now is treat spaces as separators.
+	return unicode.IsSpace(r)
+}
+
+// Title returns a copy of s with all Unicode letters that begin words
+// mapped to their title case.
+//
+// BUG: The rule Title uses for word boundaries does not handle Unicode punctuation properly.
+func Title(s []byte) []byte {
+	// Use a closure here to remember state.
+	// Hackish but effective. Depends on Map scanning in order and calling
+	// the closure once per rune.
+	prev := ' '
+	return Map(
+		func(r rune) rune {
+			if isSeparator(prev) {
+				prev = r
+				return unicode.ToTitle(r)
+			}
+			prev = r
+			return r
+		},
+		s)
+}
+
+// TrimLeftFunc returns a subslice of s by slicing off all leading UTF-8-encoded
+// Unicode code points c that satisfy f(c).
+func TrimLeftFunc(s []byte, f func(r rune) bool) []byte {
+	i := indexFunc(s, f, false)
+	if i == -1 {
+		return nil
+	}
+	return s[i:]
+}
+
+// TrimRightFunc returns a subslice of s by slicing off all trailing UTF-8
+// encoded Unicode code points c that satisfy f(c).
+func TrimRightFunc(s []byte, f func(r rune) bool) []byte {
+	i := lastIndexFunc(s, f, false)
+	if i >= 0 && s[i] >= utf8.RuneSelf {
+		_, wid := utf8.DecodeRune(s[i:])
+		i += wid
+	} else {
+		i++
+	}
+	return s[0:i]
+}
+
+// TrimFunc returns a subslice of s by slicing off all leading and trailing
+// UTF-8-encoded Unicode code points c that satisfy f(c).
+func TrimFunc(s []byte, f func(r rune) bool) []byte {
+	return TrimRightFunc(TrimLeftFunc(s, f), f)
+}
+
+// TrimPrefix returns s without the provided leading prefix string.
+// If s doesn't start with prefix, s is returned unchanged.
+func TrimPrefix(s, prefix []byte) []byte {
+	if HasPrefix(s, prefix) {
+		return s[len(prefix):]
+	}
+	return s
+}
+
+// TrimSuffix returns s without the provided trailing suffix string.
+// If s doesn't end with suffix, s is returned unchanged.
+func TrimSuffix(s, suffix []byte) []byte {
+	if HasSuffix(s, suffix) {
+		return s[:len(s)-len(suffix)]
+	}
+	return s
+}
+
+// IndexFunc interprets s as a sequence of UTF-8-encoded Unicode code points.
+// It returns the byte index in s of the first Unicode
+// code point satisfying f(c), or -1 if none do.
+func IndexFunc(s []byte, f func(r rune) bool) int {
+	return indexFunc(s, f, true)
+}
+
+// LastIndexFunc interprets s as a sequence of UTF-8-encoded Unicode code points.
+// It returns the byte index in s of the last Unicode
+// code point satisfying f(c), or -1 if none do.
+func LastIndexFunc(s []byte, f func(r rune) bool) int {
+	return lastIndexFunc(s, f, true)
+}
+
+// indexFunc is the same as IndexFunc except that if
+// truth==false, the sense of the predicate function is
+// inverted.
+func indexFunc(s []byte, f func(r rune) bool, truth bool) int {
+	start := 0
+	for start < len(s) {
+		wid := 1
+		r := rune(s[start])
+		if r >= utf8.RuneSelf {
+			r, wid = utf8.DecodeRune(s[start:])
+		}
+		if f(r) == truth {
+			return start
+		}
+		start += wid
+	}
+	return -1
+}
+
+// lastIndexFunc is the same as LastIndexFunc except that if
+// truth==false, the sense of the predicate function is
+// inverted.
+func lastIndexFunc(s []byte, f func(r rune) bool, truth bool) int {
+	for i := len(s); i > 0; {
+		r, size := rune(s[i-1]), 1
+		if r >= utf8.RuneSelf {
+			r, size = utf8.DecodeLastRune(s[0:i])
+		}
+		i -= size
+		if f(r) == truth {
+			return i
+		}
+	}
+	return -1
+}
+
+func makeCutsetFunc(cutset string) func(r rune) bool {
+	return func(r rune) bool {
+		for _, c := range cutset {
+			if c == r {
+				return true
+			}
+		}
+		return false
+	}
+}
+
+// Trim returns a subslice of s by slicing off all leading and
+// trailing UTF-8-encoded Unicode code points contained in cutset.
+func Trim(s []byte, cutset string) []byte {
+	return TrimFunc(s, makeCutsetFunc(cutset))
+}
+
+// TrimLeft returns a subslice of s by slicing off all leading
+// UTF-8-encoded Unicode code points contained in cutset.
+func TrimLeft(s []byte, cutset string) []byte {
+	return TrimLeftFunc(s, makeCutsetFunc(cutset))
+}
+
+// TrimRight returns a subslice of s by slicing off all trailing
+// UTF-8-encoded Unicode code points that are contained in cutset.
+func TrimRight(s []byte, cutset string) []byte {
+	return TrimRightFunc(s, makeCutsetFunc(cutset))
+}
+
+// TrimSpace returns a subslice of s by slicing off all leading and
+// trailing white space, as defined by Unicode.
+func TrimSpace(s []byte) []byte {
+	return TrimFunc(s, unicode.IsSpace)
+}
+
+// Runes returns a slice of runes (Unicode code points) equivalent to s.
+func Runes(s []byte) []rune {
+	t := make([]rune, utf8.RuneCount(s))
+	i := 0
+	for len(s) > 0 {
+		r, l := utf8.DecodeRune(s)
+		t[i] = r
+		i++
+		s = s[l:]
+	}
+	return t
+}
+
+// Replace returns a copy of the slice s with the first n
+// non-overlapping instances of old replaced by new.
+// If n < 0, there is no limit on the number of replacements.
+func Replace(s, old, new []byte, n int) []byte {
+	m := 0
+	if n != 0 {
+		// Compute number of replacements.
+		m = Count(s, old)
+	}
+	if m == 0 {
+		// Just return a copy.
+		return append([]byte(nil), s...)
+	}
+	if n < 0 || m < n {
+		n = m
+	}
+
+	// Apply replacements to buffer.
+	t := make([]byte, len(s)+n*(len(new)-len(old)))
+	w := 0
+	start := 0
+	for i := 0; i < n; i++ {
+		j := start
+		if len(old) == 0 {
+			if i > 0 {
+				_, wid := utf8.DecodeRune(s[start:])
+				j += wid
+			}
+		} else {
+			j += Index(s[start:], old)
+		}
+		w += copy(t[w:], s[start:j])
+		w += copy(t[w:], new)
+		start = j + len(old)
+	}
+	w += copy(t[w:], s[start:])
+	return t[0:w]
+}
+
+// EqualFold reports whether s and t, interpreted as UTF-8 strings,
+// are equal under Unicode case-folding.
+func EqualFold(s, t []byte) bool {
+	for len(s) != 0 && len(t) != 0 {
+		// Extract first rune from each.
+		var sr, tr rune
+		if s[0] < utf8.RuneSelf {
+			sr, s = rune(s[0]), s[1:]
+		} else {
+			r, size := utf8.DecodeRune(s)
+			sr, s = r, s[size:]
+		}
+		if t[0] < utf8.RuneSelf {
+			tr, t = rune(t[0]), t[1:]
+		} else {
+			r, size := utf8.DecodeRune(t)
+			tr, t = r, t[size:]
+		}
+
+		// If they match, keep going; if not, return false.
+
+		// Easy case.
+		if tr == sr {
+			continue
+		}
+
+		// Make sr < tr to simplify what follows.
+		if tr < sr {
+			tr, sr = sr, tr
+		}
+		// Fast check for ASCII.
+		if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
+			// ASCII, and sr is upper case.  tr must be lower case.
+			if tr == sr+'a'-'A' {
+				continue
+			}
+			return false
+		}
+
+		// General case.  SimpleFold(x) returns the next equivalent rune > x
+		// or wraps around to smaller values.
+		r := unicode.SimpleFold(sr)
+		for r != sr && r < tr {
+			r = unicode.SimpleFold(r)
+		}
+		if r == tr {
+			continue
+		}
+		return false
+	}
+
+	// One string is empty.  Are both?
+	return len(s) == len(t)
+}
diff --git a/third_party/gofrontend/libgo/go/bytes/bytes_decl.go b/third_party/gofrontend/libgo/go/bytes/bytes_decl.go
new file mode 100644
index 0000000..617d748
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/bytes_decl.go
@@ -0,0 +1,24 @@
+// Copyright 2010 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 bytes
+
+//go:noescape
+
+// IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s.
+func IndexByte(s []byte, c byte) int // ../runtime/asm_$GOARCH.s
+
+//go:noescape
+
+// Equal returns a boolean reporting whether a and b
+// are the same length and contain the same bytes.
+// A nil argument is equivalent to an empty slice.
+func Equal(a, b []byte) bool // ../runtime/asm_$GOARCH.s
+
+//go:noescape
+
+// Compare returns an integer comparing two byte slices lexicographically.
+// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
+// A nil argument is equivalent to an empty slice.
+func Compare(a, b []byte) int // ../runtime/noasm_arm.goc or ../runtime/asm_{386,amd64}.s
diff --git a/third_party/gofrontend/libgo/go/bytes/bytes_test.go b/third_party/gofrontend/libgo/go/bytes/bytes_test.go
new file mode 100644
index 0000000..394dd7a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/bytes_test.go
@@ -0,0 +1,1234 @@
+// 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 bytes_test
+
+import (
+	. "bytes"
+	"math/rand"
+	"reflect"
+	"testing"
+	"unicode"
+	"unicode/utf8"
+)
+
+func eq(a, b []string) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i := 0; i < len(a); i++ {
+		if a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func sliceOfString(s [][]byte) []string {
+	result := make([]string, len(s))
+	for i, v := range s {
+		result[i] = string(v)
+	}
+	return result
+}
+
+// For ease of reading, the test cases use strings that are converted to byte
+// slices before invoking the functions.
+
+var abcd = "abcd"
+var faces = "☺☻☹"
+var commas = "1,2,3,4"
+var dots = "1....2....3....4"
+
+type BinOpTest struct {
+	a string
+	b string
+	i int
+}
+
+var equalTests = []struct {
+	a, b []byte
+	i    int
+}{
+	{[]byte(""), []byte(""), 0},
+	{[]byte("a"), []byte(""), 1},
+	{[]byte(""), []byte("a"), -1},
+	{[]byte("abc"), []byte("abc"), 0},
+	{[]byte("ab"), []byte("abc"), -1},
+	{[]byte("abc"), []byte("ab"), 1},
+	{[]byte("x"), []byte("ab"), 1},
+	{[]byte("ab"), []byte("x"), -1},
+	{[]byte("x"), []byte("a"), 1},
+	{[]byte("b"), []byte("x"), -1},
+	// test runtime·memeq's chunked implementation
+	{[]byte("abcdefgh"), []byte("abcdefgh"), 0},
+	{[]byte("abcdefghi"), []byte("abcdefghi"), 0},
+	{[]byte("abcdefghi"), []byte("abcdefghj"), -1},
+	// nil tests
+	{nil, nil, 0},
+	{[]byte(""), nil, 0},
+	{nil, []byte(""), 0},
+	{[]byte("a"), nil, 1},
+	{nil, []byte("a"), -1},
+}
+
+func TestEqual(t *testing.T) {
+	for _, tt := range compareTests {
+		eql := Equal(tt.a, tt.b)
+		if eql != (tt.i == 0) {
+			t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)
+		}
+		eql = EqualPortable(tt.a, tt.b)
+		if eql != (tt.i == 0) {
+			t.Errorf(`EqualPortable(%q, %q) = %v`, tt.a, tt.b, eql)
+		}
+	}
+}
+
+func TestEqualExhaustive(t *testing.T) {
+	var size = 128
+	if testing.Short() {
+		size = 32
+	}
+	a := make([]byte, size)
+	b := make([]byte, size)
+	b_init := make([]byte, size)
+	// randomish but deterministic data
+	for i := 0; i < size; i++ {
+		a[i] = byte(17 * i)
+		b_init[i] = byte(23*i + 100)
+	}
+
+	for len := 0; len <= size; len++ {
+		for x := 0; x <= size-len; x++ {
+			for y := 0; y <= size-len; y++ {
+				copy(b, b_init)
+				copy(b[y:y+len], a[x:x+len])
+				if !Equal(a[x:x+len], b[y:y+len]) || !Equal(b[y:y+len], a[x:x+len]) {
+					t.Errorf("Equal(%d, %d, %d) = false", len, x, y)
+				}
+			}
+		}
+	}
+}
+
+// make sure Equal returns false for minimally different strings.  The data
+// is all zeros except for a single one in one location.
+func TestNotEqual(t *testing.T) {
+	var size = 128
+	if testing.Short() {
+		size = 32
+	}
+	a := make([]byte, size)
+	b := make([]byte, size)
+
+	for len := 0; len <= size; len++ {
+		for x := 0; x <= size-len; x++ {
+			for y := 0; y <= size-len; y++ {
+				for diffpos := x; diffpos < x+len; diffpos++ {
+					a[diffpos] = 1
+					if Equal(a[x:x+len], b[y:y+len]) || Equal(b[y:y+len], a[x:x+len]) {
+						t.Errorf("NotEqual(%d, %d, %d, %d) = true", len, x, y, diffpos)
+					}
+					a[diffpos] = 0
+				}
+			}
+		}
+	}
+}
+
+var indexTests = []BinOpTest{
+	{"", "", 0},
+	{"", "a", -1},
+	{"", "foo", -1},
+	{"fo", "foo", -1},
+	{"foo", "baz", -1},
+	{"foo", "foo", 0},
+	{"oofofoofooo", "f", 2},
+	{"oofofoofooo", "foo", 4},
+	{"barfoobarfoo", "foo", 3},
+	{"foo", "", 0},
+	{"foo", "o", 1},
+	{"abcABCabc", "A", 3},
+	// cases with one byte strings - test IndexByte and special case in Index()
+	{"", "a", -1},
+	{"x", "a", -1},
+	{"x", "x", 0},
+	{"abc", "a", 0},
+	{"abc", "b", 1},
+	{"abc", "c", 2},
+	{"abc", "x", -1},
+	{"barfoobarfooyyyzzzyyyzzzyyyzzzyyyxxxzzzyyy", "x", 33},
+	{"foofyfoobarfoobar", "y", 4},
+	{"oooooooooooooooooooooo", "r", -1},
+}
+
+var lastIndexTests = []BinOpTest{
+	{"", "", 0},
+	{"", "a", -1},
+	{"", "foo", -1},
+	{"fo", "foo", -1},
+	{"foo", "foo", 0},
+	{"foo", "f", 0},
+	{"oofofoofooo", "f", 7},
+	{"oofofoofooo", "foo", 7},
+	{"barfoobarfoo", "foo", 9},
+	{"foo", "", 3},
+	{"foo", "o", 2},
+	{"abcABCabc", "A", 3},
+	{"abcABCabc", "a", 6},
+}
+
+var indexAnyTests = []BinOpTest{
+	{"", "", -1},
+	{"", "a", -1},
+	{"", "abc", -1},
+	{"a", "", -1},
+	{"a", "a", 0},
+	{"aaa", "a", 0},
+	{"abc", "xyz", -1},
+	{"abc", "xcz", 2},
+	{"ab☺c", "x☺yz", 2},
+	{"aRegExp*", ".(|)*+?^$[]", 7},
+	{dots + dots + dots, " ", -1},
+}
+
+var lastIndexAnyTests = []BinOpTest{
+	{"", "", -1},
+	{"", "a", -1},
+	{"", "abc", -1},
+	{"a", "", -1},
+	{"a", "a", 0},
+	{"aaa", "a", 2},
+	{"abc", "xyz", -1},
+	{"abc", "ab", 1},
+	{"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
+	{"a.RegExp*", ".(|)*+?^$[]", 8},
+	{dots + dots + dots, " ", -1},
+}
+
+var indexRuneTests = []BinOpTest{
+	{"", "a", -1},
+	{"", "☺", -1},
+	{"foo", "☹", -1},
+	{"foo", "o", 1},
+	{"foo☺bar", "☺", 3},
+	{"foo☺☻☹bar", "☹", 9},
+}
+
+// Execute f on each test case.  funcName should be the name of f; it's used
+// in failure reports.
+func runIndexTests(t *testing.T, f func(s, sep []byte) int, funcName string, testCases []BinOpTest) {
+	for _, test := range testCases {
+		a := []byte(test.a)
+		b := []byte(test.b)
+		actual := f(a, b)
+		if actual != test.i {
+			t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, b, actual, test.i)
+		}
+	}
+}
+
+func runIndexAnyTests(t *testing.T, f func(s []byte, chars string) int, funcName string, testCases []BinOpTest) {
+	for _, test := range testCases {
+		a := []byte(test.a)
+		actual := f(a, test.b)
+		if actual != test.i {
+			t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, test.b, actual, test.i)
+		}
+	}
+}
+
+func TestIndex(t *testing.T)     { runIndexTests(t, Index, "Index", indexTests) }
+func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }
+func TestIndexAny(t *testing.T)  { runIndexAnyTests(t, IndexAny, "IndexAny", indexAnyTests) }
+func TestLastIndexAny(t *testing.T) {
+	runIndexAnyTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests)
+}
+
+func TestIndexByte(t *testing.T) {
+	for _, tt := range indexTests {
+		if len(tt.b) != 1 {
+			continue
+		}
+		a := []byte(tt.a)
+		b := tt.b[0]
+		pos := IndexByte(a, b)
+		if pos != tt.i {
+			t.Errorf(`IndexByte(%q, '%c') = %v`, tt.a, b, pos)
+		}
+		posp := IndexBytePortable(a, b)
+		if posp != tt.i {
+			t.Errorf(`indexBytePortable(%q, '%c') = %v`, tt.a, b, posp)
+		}
+	}
+}
+
+// test a larger buffer with different sizes and alignments
+func TestIndexByteBig(t *testing.T) {
+	var n = 1024
+	if testing.Short() {
+		n = 128
+	}
+	b := make([]byte, n)
+	for i := 0; i < n; i++ {
+		// different start alignments
+		b1 := b[i:]
+		for j := 0; j < len(b1); j++ {
+			b1[j] = 'x'
+			pos := IndexByte(b1, 'x')
+			if pos != j {
+				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
+			}
+			b1[j] = 0
+			pos = IndexByte(b1, 'x')
+			if pos != -1 {
+				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
+			}
+		}
+		// different end alignments
+		b1 = b[:i]
+		for j := 0; j < len(b1); j++ {
+			b1[j] = 'x'
+			pos := IndexByte(b1, 'x')
+			if pos != j {
+				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
+			}
+			b1[j] = 0
+			pos = IndexByte(b1, 'x')
+			if pos != -1 {
+				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
+			}
+		}
+		// different start and end alignments
+		b1 = b[i/2 : n-(i+1)/2]
+		for j := 0; j < len(b1); j++ {
+			b1[j] = 'x'
+			pos := IndexByte(b1, 'x')
+			if pos != j {
+				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
+			}
+			b1[j] = 0
+			pos = IndexByte(b1, 'x')
+			if pos != -1 {
+				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
+			}
+		}
+	}
+}
+
+func TestIndexRune(t *testing.T) {
+	for _, tt := range indexRuneTests {
+		a := []byte(tt.a)
+		r, _ := utf8.DecodeRuneInString(tt.b)
+		pos := IndexRune(a, r)
+		if pos != tt.i {
+			t.Errorf(`IndexRune(%q, '%c') = %v`, tt.a, r, pos)
+		}
+	}
+}
+
+var bmbuf []byte
+
+func BenchmarkIndexByte32(b *testing.B)          { bmIndexByte(b, IndexByte, 32) }
+func BenchmarkIndexByte4K(b *testing.B)          { bmIndexByte(b, IndexByte, 4<<10) }
+func BenchmarkIndexByte4M(b *testing.B)          { bmIndexByte(b, IndexByte, 4<<20) }
+func BenchmarkIndexByte64M(b *testing.B)         { bmIndexByte(b, IndexByte, 64<<20) }
+func BenchmarkIndexBytePortable32(b *testing.B)  { bmIndexByte(b, IndexBytePortable, 32) }
+func BenchmarkIndexBytePortable4K(b *testing.B)  { bmIndexByte(b, IndexBytePortable, 4<<10) }
+func BenchmarkIndexBytePortable4M(b *testing.B)  { bmIndexByte(b, IndexBytePortable, 4<<20) }
+func BenchmarkIndexBytePortable64M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 64<<20) }
+
+func bmIndexByte(b *testing.B, index func([]byte, byte) int, n int) {
+	if len(bmbuf) < n {
+		bmbuf = make([]byte, n)
+	}
+	b.SetBytes(int64(n))
+	buf := bmbuf[0:n]
+	buf[n-1] = 'x'
+	for i := 0; i < b.N; i++ {
+		j := index(buf, 'x')
+		if j != n-1 {
+			b.Fatal("bad index", j)
+		}
+	}
+	buf[n-1] = '\x00'
+}
+
+func BenchmarkEqual0(b *testing.B) {
+	var buf [4]byte
+	buf1 := buf[0:0]
+	buf2 := buf[1:1]
+	for i := 0; i < b.N; i++ {
+		eq := Equal(buf1, buf2)
+		if !eq {
+			b.Fatal("bad equal")
+		}
+	}
+}
+
+func BenchmarkEqual1(b *testing.B)           { bmEqual(b, Equal, 1) }
+func BenchmarkEqual6(b *testing.B)           { bmEqual(b, Equal, 6) }
+func BenchmarkEqual9(b *testing.B)           { bmEqual(b, Equal, 9) }
+func BenchmarkEqual15(b *testing.B)          { bmEqual(b, Equal, 15) }
+func BenchmarkEqual16(b *testing.B)          { bmEqual(b, Equal, 16) }
+func BenchmarkEqual20(b *testing.B)          { bmEqual(b, Equal, 20) }
+func BenchmarkEqual32(b *testing.B)          { bmEqual(b, Equal, 32) }
+func BenchmarkEqual4K(b *testing.B)          { bmEqual(b, Equal, 4<<10) }
+func BenchmarkEqual4M(b *testing.B)          { bmEqual(b, Equal, 4<<20) }
+func BenchmarkEqual64M(b *testing.B)         { bmEqual(b, Equal, 64<<20) }
+func BenchmarkEqualPort1(b *testing.B)       { bmEqual(b, EqualPortable, 1) }
+func BenchmarkEqualPort6(b *testing.B)       { bmEqual(b, EqualPortable, 6) }
+func BenchmarkEqualPort32(b *testing.B)      { bmEqual(b, EqualPortable, 32) }
+func BenchmarkEqualPort4K(b *testing.B)      { bmEqual(b, EqualPortable, 4<<10) }
+func BenchmarkEqualPortable4M(b *testing.B)  { bmEqual(b, EqualPortable, 4<<20) }
+func BenchmarkEqualPortable64M(b *testing.B) { bmEqual(b, EqualPortable, 64<<20) }
+
+func bmEqual(b *testing.B, equal func([]byte, []byte) bool, n int) {
+	if len(bmbuf) < 2*n {
+		bmbuf = make([]byte, 2*n)
+	}
+	b.SetBytes(int64(n))
+	buf1 := bmbuf[0:n]
+	buf2 := bmbuf[n : 2*n]
+	buf1[n-1] = 'x'
+	buf2[n-1] = 'x'
+	for i := 0; i < b.N; i++ {
+		eq := equal(buf1, buf2)
+		if !eq {
+			b.Fatal("bad equal")
+		}
+	}
+	buf1[n-1] = '\x00'
+	buf2[n-1] = '\x00'
+}
+
+func BenchmarkIndex32(b *testing.B)  { bmIndex(b, Index, 32) }
+func BenchmarkIndex4K(b *testing.B)  { bmIndex(b, Index, 4<<10) }
+func BenchmarkIndex4M(b *testing.B)  { bmIndex(b, Index, 4<<20) }
+func BenchmarkIndex64M(b *testing.B) { bmIndex(b, Index, 64<<20) }
+
+func bmIndex(b *testing.B, index func([]byte, []byte) int, n int) {
+	if len(bmbuf) < n {
+		bmbuf = make([]byte, n)
+	}
+	b.SetBytes(int64(n))
+	buf := bmbuf[0:n]
+	buf[n-1] = 'x'
+	for i := 0; i < b.N; i++ {
+		j := index(buf, buf[n-7:])
+		if j != n-7 {
+			b.Fatal("bad index", j)
+		}
+	}
+	buf[n-1] = '\x00'
+}
+
+func BenchmarkIndexEasy32(b *testing.B)  { bmIndexEasy(b, Index, 32) }
+func BenchmarkIndexEasy4K(b *testing.B)  { bmIndexEasy(b, Index, 4<<10) }
+func BenchmarkIndexEasy4M(b *testing.B)  { bmIndexEasy(b, Index, 4<<20) }
+func BenchmarkIndexEasy64M(b *testing.B) { bmIndexEasy(b, Index, 64<<20) }
+
+func bmIndexEasy(b *testing.B, index func([]byte, []byte) int, n int) {
+	if len(bmbuf) < n {
+		bmbuf = make([]byte, n)
+	}
+	b.SetBytes(int64(n))
+	buf := bmbuf[0:n]
+	buf[n-1] = 'x'
+	buf[n-7] = 'x'
+	for i := 0; i < b.N; i++ {
+		j := index(buf, buf[n-7:])
+		if j != n-7 {
+			b.Fatal("bad index", j)
+		}
+	}
+	buf[n-1] = '\x00'
+	buf[n-7] = '\x00'
+}
+
+func BenchmarkCount32(b *testing.B)  { bmCount(b, Count, 32) }
+func BenchmarkCount4K(b *testing.B)  { bmCount(b, Count, 4<<10) }
+func BenchmarkCount4M(b *testing.B)  { bmCount(b, Count, 4<<20) }
+func BenchmarkCount64M(b *testing.B) { bmCount(b, Count, 64<<20) }
+
+func bmCount(b *testing.B, count func([]byte, []byte) int, n int) {
+	if len(bmbuf) < n {
+		bmbuf = make([]byte, n)
+	}
+	b.SetBytes(int64(n))
+	buf := bmbuf[0:n]
+	buf[n-1] = 'x'
+	for i := 0; i < b.N; i++ {
+		j := count(buf, buf[n-7:])
+		if j != 1 {
+			b.Fatal("bad count", j)
+		}
+	}
+	buf[n-1] = '\x00'
+}
+
+func BenchmarkCountEasy32(b *testing.B)  { bmCountEasy(b, Count, 32) }
+func BenchmarkCountEasy4K(b *testing.B)  { bmCountEasy(b, Count, 4<<10) }
+func BenchmarkCountEasy4M(b *testing.B)  { bmCountEasy(b, Count, 4<<20) }
+func BenchmarkCountEasy64M(b *testing.B) { bmCountEasy(b, Count, 64<<20) }
+
+func bmCountEasy(b *testing.B, count func([]byte, []byte) int, n int) {
+	if len(bmbuf) < n {
+		bmbuf = make([]byte, n)
+	}
+	b.SetBytes(int64(n))
+	buf := bmbuf[0:n]
+	buf[n-1] = 'x'
+	buf[n-7] = 'x'
+	for i := 0; i < b.N; i++ {
+		j := count(buf, buf[n-7:])
+		if j != 1 {
+			b.Fatal("bad count", j)
+		}
+	}
+	buf[n-1] = '\x00'
+	buf[n-7] = '\x00'
+}
+
+type ExplodeTest struct {
+	s string
+	n int
+	a []string
+}
+
+var explodetests = []ExplodeTest{
+	{"", -1, []string{}},
+	{abcd, -1, []string{"a", "b", "c", "d"}},
+	{faces, -1, []string{"☺", "☻", "☹"}},
+	{abcd, 2, []string{"a", "bcd"}},
+}
+
+func TestExplode(t *testing.T) {
+	for _, tt := range explodetests {
+		a := SplitN([]byte(tt.s), nil, tt.n)
+		result := sliceOfString(a)
+		if !eq(result, tt.a) {
+			t.Errorf(`Explode("%s", %d) = %v; want %v`, tt.s, tt.n, result, tt.a)
+			continue
+		}
+		s := Join(a, []byte{})
+		if string(s) != tt.s {
+			t.Errorf(`Join(Explode("%s", %d), "") = "%s"`, tt.s, tt.n, s)
+		}
+	}
+}
+
+type SplitTest struct {
+	s   string
+	sep string
+	n   int
+	a   []string
+}
+
+var splittests = []SplitTest{
+	{abcd, "a", 0, nil},
+	{abcd, "a", -1, []string{"", "bcd"}},
+	{abcd, "z", -1, []string{"abcd"}},
+	{abcd, "", -1, []string{"a", "b", "c", "d"}},
+	{commas, ",", -1, []string{"1", "2", "3", "4"}},
+	{dots, "...", -1, []string{"1", ".2", ".3", ".4"}},
+	{faces, "☹", -1, []string{"☺☻", ""}},
+	{faces, "~", -1, []string{faces}},
+	{faces, "", -1, []string{"☺", "☻", "☹"}},
+	{"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}},
+	{"1 2", " ", 3, []string{"1", "2"}},
+	{"123", "", 2, []string{"1", "23"}},
+	{"123", "", 17, []string{"1", "2", "3"}},
+}
+
+func TestSplit(t *testing.T) {
+	for _, tt := range splittests {
+		a := SplitN([]byte(tt.s), []byte(tt.sep), tt.n)
+		result := sliceOfString(a)
+		if !eq(result, tt.a) {
+			t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
+			continue
+		}
+		if tt.n == 0 {
+			continue
+		}
+		s := Join(a, []byte(tt.sep))
+		if string(s) != tt.s {
+			t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
+		}
+		if tt.n < 0 {
+			b := Split([]byte(tt.s), []byte(tt.sep))
+			if !reflect.DeepEqual(a, b) {
+				t.Errorf("Split disagrees withSplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
+			}
+		}
+		if len(a) > 0 {
+			in, out := a[0], s
+			if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] {
+				t.Errorf("Join(%#v, %q) didn't copy", a, tt.sep)
+			}
+		}
+	}
+}
+
+var splitaftertests = []SplitTest{
+	{abcd, "a", -1, []string{"a", "bcd"}},
+	{abcd, "z", -1, []string{"abcd"}},
+	{abcd, "", -1, []string{"a", "b", "c", "d"}},
+	{commas, ",", -1, []string{"1,", "2,", "3,", "4"}},
+	{dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}},
+	{faces, "☹", -1, []string{"☺☻☹", ""}},
+	{faces, "~", -1, []string{faces}},
+	{faces, "", -1, []string{"☺", "☻", "☹"}},
+	{"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}},
+	{"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}},
+	{"1 2", " ", 3, []string{"1 ", "2"}},
+	{"123", "", 2, []string{"1", "23"}},
+	{"123", "", 17, []string{"1", "2", "3"}},
+}
+
+func TestSplitAfter(t *testing.T) {
+	for _, tt := range splitaftertests {
+		a := SplitAfterN([]byte(tt.s), []byte(tt.sep), tt.n)
+		result := sliceOfString(a)
+		if !eq(result, tt.a) {
+			t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
+			continue
+		}
+		s := Join(a, nil)
+		if string(s) != tt.s {
+			t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
+		}
+		if tt.n < 0 {
+			b := SplitAfter([]byte(tt.s), []byte(tt.sep))
+			if !reflect.DeepEqual(a, b) {
+				t.Errorf("SplitAfter disagrees withSplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
+			}
+		}
+	}
+}
+
+type FieldsTest struct {
+	s string
+	a []string
+}
+
+var fieldstests = []FieldsTest{
+	{"", []string{}},
+	{" ", []string{}},
+	{" \t ", []string{}},
+	{"  abc  ", []string{"abc"}},
+	{"1 2 3 4", []string{"1", "2", "3", "4"}},
+	{"1  2  3  4", []string{"1", "2", "3", "4"}},
+	{"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}},
+	{"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}},
+	{"\u2000\u2001\u2002", []string{}},
+	{"\n™\t™\n", []string{"™", "™"}},
+	{faces, []string{faces}},
+}
+
+func TestFields(t *testing.T) {
+	for _, tt := range fieldstests {
+		a := Fields([]byte(tt.s))
+		result := sliceOfString(a)
+		if !eq(result, tt.a) {
+			t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a)
+			continue
+		}
+	}
+}
+
+func TestFieldsFunc(t *testing.T) {
+	for _, tt := range fieldstests {
+		a := FieldsFunc([]byte(tt.s), unicode.IsSpace)
+		result := sliceOfString(a)
+		if !eq(result, tt.a) {
+			t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a)
+			continue
+		}
+	}
+	pred := func(c rune) bool { return c == 'X' }
+	var fieldsFuncTests = []FieldsTest{
+		{"", []string{}},
+		{"XX", []string{}},
+		{"XXhiXXX", []string{"hi"}},
+		{"aXXbXXXcX", []string{"a", "b", "c"}},
+	}
+	for _, tt := range fieldsFuncTests {
+		a := FieldsFunc([]byte(tt.s), pred)
+		result := sliceOfString(a)
+		if !eq(result, tt.a) {
+			t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a)
+		}
+	}
+}
+
+// Test case for any function which accepts and returns a byte slice.
+// For ease of creation, we write the byte slices as strings.
+type StringTest struct {
+	in, out string
+}
+
+var upperTests = []StringTest{
+	{"", ""},
+	{"abc", "ABC"},
+	{"AbC123", "ABC123"},
+	{"azAZ09_", "AZAZ09_"},
+	{"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
+}
+
+var lowerTests = []StringTest{
+	{"", ""},
+	{"abc", "abc"},
+	{"AbC123", "abc123"},
+	{"azAZ09_", "azaz09_"},
+	{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
+}
+
+const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
+
+var trimSpaceTests = []StringTest{
+	{"", ""},
+	{"abc", "abc"},
+	{space + "abc" + space, "abc"},
+	{" ", ""},
+	{" \t\r\n \t\t\r\r\n\n ", ""},
+	{" \t\r\n x\t\t\r\r\n\n ", "x"},
+	{" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"},
+	{"1 \t\r\n2", "1 \t\r\n2"},
+	{" x\x80", "x\x80"},
+	{" x\xc0", "x\xc0"},
+	{"x \xc0\xc0 ", "x \xc0\xc0"},
+	{"x \xc0", "x \xc0"},
+	{"x \xc0 ", "x \xc0"},
+	{"x \xc0\xc0 ", "x \xc0\xc0"},
+	{"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"},
+	{"x ☺ ", "x ☺"},
+}
+
+// Execute f on each test case.  funcName should be the name of f; it's used
+// in failure reports.
+func runStringTests(t *testing.T, f func([]byte) []byte, funcName string, testCases []StringTest) {
+	for _, tc := range testCases {
+		actual := string(f([]byte(tc.in)))
+		if actual != tc.out {
+			t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
+		}
+	}
+}
+
+func tenRunes(r rune) string {
+	runes := make([]rune, 10)
+	for i := range runes {
+		runes[i] = r
+	}
+	return string(runes)
+}
+
+// User-defined self-inverse mapping function
+func rot13(r rune) rune {
+	const step = 13
+	if r >= 'a' && r <= 'z' {
+		return ((r - 'a' + step) % 26) + 'a'
+	}
+	if r >= 'A' && r <= 'Z' {
+		return ((r - 'A' + step) % 26) + 'A'
+	}
+	return r
+}
+
+func TestMap(t *testing.T) {
+	// Run a couple of awful growth/shrinkage tests
+	a := tenRunes('a')
+
+	// 1.  Grow.  This triggers two reallocations in Map.
+	maxRune := func(r rune) rune { return unicode.MaxRune }
+	m := Map(maxRune, []byte(a))
+	expect := tenRunes(unicode.MaxRune)
+	if string(m) != expect {
+		t.Errorf("growing: expected %q got %q", expect, m)
+	}
+
+	// 2. Shrink
+	minRune := func(r rune) rune { return 'a' }
+	m = Map(minRune, []byte(tenRunes(unicode.MaxRune)))
+	expect = a
+	if string(m) != expect {
+		t.Errorf("shrinking: expected %q got %q", expect, m)
+	}
+
+	// 3. Rot13
+	m = Map(rot13, []byte("a to zed"))
+	expect = "n gb mrq"
+	if string(m) != expect {
+		t.Errorf("rot13: expected %q got %q", expect, m)
+	}
+
+	// 4. Rot13^2
+	m = Map(rot13, Map(rot13, []byte("a to zed")))
+	expect = "a to zed"
+	if string(m) != expect {
+		t.Errorf("rot13: expected %q got %q", expect, m)
+	}
+
+	// 5. Drop
+	dropNotLatin := func(r rune) rune {
+		if unicode.Is(unicode.Latin, r) {
+			return r
+		}
+		return -1
+	}
+	m = Map(dropNotLatin, []byte("Hello, 세계"))
+	expect = "Hello"
+	if string(m) != expect {
+		t.Errorf("drop: expected %q got %q", expect, m)
+	}
+
+	// 6. Invalid rune
+	invalidRune := func(r rune) rune {
+		return utf8.MaxRune + 1
+	}
+	m = Map(invalidRune, []byte("x"))
+	expect = "\uFFFD"
+	if string(m) != expect {
+		t.Errorf("invalidRune: expected %q got %q", expect, m)
+	}
+}
+
+func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) }
+
+func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) }
+
+func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
+
+type RepeatTest struct {
+	in, out string
+	count   int
+}
+
+var RepeatTests = []RepeatTest{
+	{"", "", 0},
+	{"", "", 1},
+	{"", "", 2},
+	{"-", "", 0},
+	{"-", "-", 1},
+	{"-", "----------", 10},
+	{"abc ", "abc abc abc ", 3},
+}
+
+func TestRepeat(t *testing.T) {
+	for _, tt := range RepeatTests {
+		tin := []byte(tt.in)
+		tout := []byte(tt.out)
+		a := Repeat(tin, tt.count)
+		if !Equal(a, tout) {
+			t.Errorf("Repeat(%q, %d) = %q; want %q", tin, tt.count, a, tout)
+			continue
+		}
+	}
+}
+
+func runesEqual(a, b []rune) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i, r := range a {
+		if r != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+type RunesTest struct {
+	in    string
+	out   []rune
+	lossy bool
+}
+
+var RunesTests = []RunesTest{
+	{"", []rune{}, false},
+	{" ", []rune{32}, false},
+	{"ABC", []rune{65, 66, 67}, false},
+	{"abc", []rune{97, 98, 99}, false},
+	{"\u65e5\u672c\u8a9e", []rune{26085, 26412, 35486}, false},
+	{"ab\x80c", []rune{97, 98, 0xFFFD, 99}, true},
+	{"ab\xc0c", []rune{97, 98, 0xFFFD, 99}, true},
+}
+
+func TestRunes(t *testing.T) {
+	for _, tt := range RunesTests {
+		tin := []byte(tt.in)
+		a := Runes(tin)
+		if !runesEqual(a, tt.out) {
+			t.Errorf("Runes(%q) = %v; want %v", tin, a, tt.out)
+			continue
+		}
+		if !tt.lossy {
+			// can only test reassembly if we didn't lose information
+			s := string(a)
+			if s != tt.in {
+				t.Errorf("string(Runes(%q)) = %x; want %x", tin, s, tin)
+			}
+		}
+	}
+}
+
+type TrimTest struct {
+	f            string
+	in, arg, out string
+}
+
+var trimTests = []TrimTest{
+	{"Trim", "abba", "a", "bb"},
+	{"Trim", "abba", "ab", ""},
+	{"TrimLeft", "abba", "ab", ""},
+	{"TrimRight", "abba", "ab", ""},
+	{"TrimLeft", "abba", "a", "bba"},
+	{"TrimRight", "abba", "a", "abb"},
+	{"Trim", "<tag>", "<>", "tag"},
+	{"Trim", "* listitem", " *", "listitem"},
+	{"Trim", `"quote"`, `"`, "quote"},
+	{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
+	//empty string tests
+	{"Trim", "abba", "", "abba"},
+	{"Trim", "", "123", ""},
+	{"Trim", "", "", ""},
+	{"TrimLeft", "abba", "", "abba"},
+	{"TrimLeft", "", "123", ""},
+	{"TrimLeft", "", "", ""},
+	{"TrimRight", "abba", "", "abba"},
+	{"TrimRight", "", "123", ""},
+	{"TrimRight", "", "", ""},
+	{"TrimRight", "☺\xc0", "☺", "☺\xc0"},
+	{"TrimPrefix", "aabb", "a", "abb"},
+	{"TrimPrefix", "aabb", "b", "aabb"},
+	{"TrimSuffix", "aabb", "a", "aabb"},
+	{"TrimSuffix", "aabb", "b", "aab"},
+}
+
+func TestTrim(t *testing.T) {
+	for _, tc := range trimTests {
+		name := tc.f
+		var f func([]byte, string) []byte
+		var fb func([]byte, []byte) []byte
+		switch name {
+		case "Trim":
+			f = Trim
+		case "TrimLeft":
+			f = TrimLeft
+		case "TrimRight":
+			f = TrimRight
+		case "TrimPrefix":
+			fb = TrimPrefix
+		case "TrimSuffix":
+			fb = TrimSuffix
+		default:
+			t.Errorf("Undefined trim function %s", name)
+		}
+		var actual string
+		if f != nil {
+			actual = string(f([]byte(tc.in), tc.arg))
+		} else {
+			actual = string(fb([]byte(tc.in), []byte(tc.arg)))
+		}
+		if actual != tc.out {
+			t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
+		}
+	}
+}
+
+type predicate struct {
+	f    func(r rune) bool
+	name string
+}
+
+var isSpace = predicate{unicode.IsSpace, "IsSpace"}
+var isDigit = predicate{unicode.IsDigit, "IsDigit"}
+var isUpper = predicate{unicode.IsUpper, "IsUpper"}
+var isValidRune = predicate{
+	func(r rune) bool {
+		return r != utf8.RuneError
+	},
+	"IsValidRune",
+}
+
+type TrimFuncTest struct {
+	f       predicate
+	in, out string
+}
+
+func not(p predicate) predicate {
+	return predicate{
+		func(r rune) bool {
+			return !p.f(r)
+		},
+		"not " + p.name,
+	}
+}
+
+var trimFuncTests = []TrimFuncTest{
+	{isSpace, space + " hello " + space, "hello"},
+	{isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
+	{isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
+	{not(isSpace), "hello" + space + "hello", space},
+	{not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"},
+	{isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"},
+	{not(isValidRune), "\xc0a\xc0", "a"},
+}
+
+func TestTrimFunc(t *testing.T) {
+	for _, tc := range trimFuncTests {
+		actual := string(TrimFunc([]byte(tc.in), tc.f.f))
+		if actual != tc.out {
+			t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out)
+		}
+	}
+}
+
+type IndexFuncTest struct {
+	in          string
+	f           predicate
+	first, last int
+}
+
+var indexFuncTests = []IndexFuncTest{
+	{"", isValidRune, -1, -1},
+	{"abc", isDigit, -1, -1},
+	{"0123", isDigit, 0, 3},
+	{"a1b", isDigit, 1, 1},
+	{space, isSpace, 0, len(space) - 3}, // last rune in space is 3 bytes
+	{"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit, 0, 18},
+	{"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper, 0, 34},
+	{"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit), 8, 12},
+
+	// tests of invalid UTF-8
+	{"\x801", isDigit, 1, 1},
+	{"\x80abc", isDigit, -1, -1},
+	{"\xc0a\xc0", isValidRune, 1, 1},
+	{"\xc0a\xc0", not(isValidRune), 0, 2},
+	{"\xc0☺\xc0", not(isValidRune), 0, 4},
+	{"\xc0☺\xc0\xc0", not(isValidRune), 0, 5},
+	{"ab\xc0a\xc0cd", not(isValidRune), 2, 4},
+	{"a\xe0\x80cd", not(isValidRune), 1, 2},
+}
+
+func TestIndexFunc(t *testing.T) {
+	for _, tc := range indexFuncTests {
+		first := IndexFunc([]byte(tc.in), tc.f.f)
+		if first != tc.first {
+			t.Errorf("IndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, first, tc.first)
+		}
+		last := LastIndexFunc([]byte(tc.in), tc.f.f)
+		if last != tc.last {
+			t.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, last, tc.last)
+		}
+	}
+}
+
+type ReplaceTest struct {
+	in       string
+	old, new string
+	n        int
+	out      string
+}
+
+var ReplaceTests = []ReplaceTest{
+	{"hello", "l", "L", 0, "hello"},
+	{"hello", "l", "L", -1, "heLLo"},
+	{"hello", "x", "X", -1, "hello"},
+	{"", "x", "X", -1, ""},
+	{"radar", "r", "<r>", -1, "<r>ada<r>"},
+	{"", "", "<>", -1, "<>"},
+	{"banana", "a", "<>", -1, "b<>n<>n<>"},
+	{"banana", "a", "<>", 1, "b<>nana"},
+	{"banana", "a", "<>", 1000, "b<>n<>n<>"},
+	{"banana", "an", "<>", -1, "b<><>a"},
+	{"banana", "ana", "<>", -1, "b<>na"},
+	{"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"},
+	{"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"},
+	{"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"},
+	{"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"},
+	{"banana", "", "<>", 1, "<>banana"},
+	{"banana", "a", "a", -1, "banana"},
+	{"banana", "a", "a", 1, "banana"},
+	{"☺☻☹", "", "<>", -1, "<>☺<>☻<>☹<>"},
+}
+
+func TestReplace(t *testing.T) {
+	for _, tt := range ReplaceTests {
+		in := append([]byte(tt.in), "<spare>"...)
+		in = in[:len(tt.in)]
+		out := Replace(in, []byte(tt.old), []byte(tt.new), tt.n)
+		if s := string(out); s != tt.out {
+			t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out)
+		}
+		if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] {
+			t.Errorf("Replace(%q, %q, %q, %d) didn't copy", tt.in, tt.old, tt.new, tt.n)
+		}
+	}
+}
+
+type TitleTest struct {
+	in, out string
+}
+
+var TitleTests = []TitleTest{
+	{"", ""},
+	{"a", "A"},
+	{" aaa aaa aaa ", " Aaa Aaa Aaa "},
+	{" Aaa Aaa Aaa ", " Aaa Aaa Aaa "},
+	{"123a456", "123a456"},
+	{"double-blind", "Double-Blind"},
+	{"ÿøû", "Ÿøû"},
+	{"with_underscore", "With_underscore"},
+	{"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"},
+}
+
+func TestTitle(t *testing.T) {
+	for _, tt := range TitleTests {
+		if s := string(Title([]byte(tt.in))); s != tt.out {
+			t.Errorf("Title(%q) = %q, want %q", tt.in, s, tt.out)
+		}
+	}
+}
+
+var ToTitleTests = []TitleTest{
+	{"", ""},
+	{"a", "A"},
+	{" aaa aaa aaa ", " AAA AAA AAA "},
+	{" Aaa Aaa Aaa ", " AAA AAA AAA "},
+	{"123a456", "123A456"},
+	{"double-blind", "DOUBLE-BLIND"},
+	{"ÿøû", "ŸØÛ"},
+}
+
+func TestToTitle(t *testing.T) {
+	for _, tt := range ToTitleTests {
+		if s := string(ToTitle([]byte(tt.in))); s != tt.out {
+			t.Errorf("ToTitle(%q) = %q, want %q", tt.in, s, tt.out)
+		}
+	}
+}
+
+var EqualFoldTests = []struct {
+	s, t string
+	out  bool
+}{
+	{"abc", "abc", true},
+	{"ABcd", "ABcd", true},
+	{"123abc", "123ABC", true},
+	{"αβδ", "ΑΒΔ", true},
+	{"abc", "xyz", false},
+	{"abc", "XYZ", false},
+	{"abcdefghijk", "abcdefghijX", false},
+	{"abcdefghijk", "abcdefghij\u212A", true},
+	{"abcdefghijK", "abcdefghij\u212A", true},
+	{"abcdefghijkz", "abcdefghij\u212Ay", false},
+	{"abcdefghijKz", "abcdefghij\u212Ay", false},
+}
+
+func TestEqualFold(t *testing.T) {
+	for _, tt := range EqualFoldTests {
+		if out := EqualFold([]byte(tt.s), []byte(tt.t)); out != tt.out {
+			t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out)
+		}
+		if out := EqualFold([]byte(tt.t), []byte(tt.s)); out != tt.out {
+			t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out)
+		}
+	}
+}
+
+func TestBufferGrowNegative(t *testing.T) {
+	defer func() {
+		if err := recover(); err == nil {
+			t.Fatal("Grow(-1) should have panicked")
+		}
+	}()
+	var b Buffer
+	b.Grow(-1)
+}
+
+func TestBufferTruncateNegative(t *testing.T) {
+	defer func() {
+		if err := recover(); err == nil {
+			t.Fatal("Truncate(-1) should have panicked")
+		}
+	}()
+	var b Buffer
+	b.Truncate(-1)
+}
+
+func TestBufferTruncateOutOfRange(t *testing.T) {
+	defer func() {
+		if err := recover(); err == nil {
+			t.Fatal("Truncate(20) should have panicked")
+		}
+	}()
+	var b Buffer
+	b.Write(make([]byte, 10))
+	b.Truncate(20)
+}
+
+var containsTests = []struct {
+	b, subslice []byte
+	want        bool
+}{
+	{[]byte("hello"), []byte("hel"), true},
+	{[]byte("日本語"), []byte("日本"), true},
+	{[]byte("hello"), []byte("Hello, world"), false},
+	{[]byte("東京"), []byte("京東"), false},
+}
+
+func TestContains(t *testing.T) {
+	for _, tt := range containsTests {
+		if got := Contains(tt.b, tt.subslice); got != tt.want {
+			t.Errorf("Contains(%q, %q) = %v, want %v", tt.b, tt.subslice, got, tt.want)
+		}
+	}
+}
+
+var makeFieldsInput = func() []byte {
+	x := make([]byte, 1<<20)
+	// Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
+	for i := range x {
+		switch rand.Intn(10) {
+		case 0:
+			x[i] = ' '
+		case 1:
+			if i > 0 && x[i-1] == 'x' {
+				copy(x[i-1:], "χ")
+				break
+			}
+			fallthrough
+		default:
+			x[i] = 'x'
+		}
+	}
+	return x
+}
+
+var fieldsInput = makeFieldsInput()
+
+func BenchmarkFields(b *testing.B) {
+	b.SetBytes(int64(len(fieldsInput)))
+	for i := 0; i < b.N; i++ {
+		Fields(fieldsInput)
+	}
+}
+
+func BenchmarkFieldsFunc(b *testing.B) {
+	b.SetBytes(int64(len(fieldsInput)))
+	for i := 0; i < b.N; i++ {
+		FieldsFunc(fieldsInput, unicode.IsSpace)
+	}
+}
+
+func BenchmarkTrimSpace(b *testing.B) {
+	s := []byte("  Some text.  \n")
+	for i := 0; i < b.N; i++ {
+		TrimSpace(s)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/bytes/compare_test.go b/third_party/gofrontend/libgo/go/bytes/compare_test.go
new file mode 100644
index 0000000..6352237
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/compare_test.go
@@ -0,0 +1,208 @@
+// Copyright 2013 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 bytes_test
+
+import (
+	. "bytes"
+	"testing"
+)
+
+var compareTests = []struct {
+	a, b []byte
+	i    int
+}{
+	{[]byte(""), []byte(""), 0},
+	{[]byte("a"), []byte(""), 1},
+	{[]byte(""), []byte("a"), -1},
+	{[]byte("abc"), []byte("abc"), 0},
+	{[]byte("ab"), []byte("abc"), -1},
+	{[]byte("abc"), []byte("ab"), 1},
+	{[]byte("x"), []byte("ab"), 1},
+	{[]byte("ab"), []byte("x"), -1},
+	{[]byte("x"), []byte("a"), 1},
+	{[]byte("b"), []byte("x"), -1},
+	// test runtime·memeq's chunked implementation
+	{[]byte("abcdefgh"), []byte("abcdefgh"), 0},
+	{[]byte("abcdefghi"), []byte("abcdefghi"), 0},
+	{[]byte("abcdefghi"), []byte("abcdefghj"), -1},
+	// nil tests
+	{nil, nil, 0},
+	{[]byte(""), nil, 0},
+	{nil, []byte(""), 0},
+	{[]byte("a"), nil, 1},
+	{nil, []byte("a"), -1},
+}
+
+func TestCompare(t *testing.T) {
+	for _, tt := range compareTests {
+		cmp := Compare(tt.a, tt.b)
+		if cmp != tt.i {
+			t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
+		}
+	}
+}
+
+func TestCompareIdenticalSlice(t *testing.T) {
+	var b = []byte("Hello Gophers!")
+	if Compare(b, b) != 0 {
+		t.Error("b != b")
+	}
+	if Compare(b, b[:1]) != 1 {
+		t.Error("b > b[:1] failed")
+	}
+}
+
+func TestCompareBytes(t *testing.T) {
+	n := 128
+	a := make([]byte, n+1)
+	b := make([]byte, n+1)
+	for len := 0; len < 128; len++ {
+		// randomish but deterministic data.  No 0 or 255.
+		for i := 0; i < len; i++ {
+			a[i] = byte(1 + 31*i%254)
+			b[i] = byte(1 + 31*i%254)
+		}
+		// data past the end is different
+		for i := len; i <= n; i++ {
+			a[i] = 8
+			b[i] = 9
+		}
+		cmp := Compare(a[:len], b[:len])
+		if cmp != 0 {
+			t.Errorf(`CompareIdentical(%d) = %d`, len, cmp)
+		}
+		if len > 0 {
+			cmp = Compare(a[:len-1], b[:len])
+			if cmp != -1 {
+				t.Errorf(`CompareAshorter(%d) = %d`, len, cmp)
+			}
+			cmp = Compare(a[:len], b[:len-1])
+			if cmp != 1 {
+				t.Errorf(`CompareBshorter(%d) = %d`, len, cmp)
+			}
+		}
+		for k := 0; k < len; k++ {
+			b[k] = a[k] - 1
+			cmp = Compare(a[:len], b[:len])
+			if cmp != 1 {
+				t.Errorf(`CompareAbigger(%d,%d) = %d`, len, k, cmp)
+			}
+			b[k] = a[k] + 1
+			cmp = Compare(a[:len], b[:len])
+			if cmp != -1 {
+				t.Errorf(`CompareBbigger(%d,%d) = %d`, len, k, cmp)
+			}
+			b[k] = a[k]
+		}
+	}
+}
+
+func BenchmarkCompareBytesEqual(b *testing.B) {
+	b1 := []byte("Hello Gophers!")
+	b2 := []byte("Hello Gophers!")
+	for i := 0; i < b.N; i++ {
+		if Compare(b1, b2) != 0 {
+			b.Fatal("b1 != b2")
+		}
+	}
+}
+
+func BenchmarkCompareBytesToNil(b *testing.B) {
+	b1 := []byte("Hello Gophers!")
+	var b2 []byte
+	for i := 0; i < b.N; i++ {
+		if Compare(b1, b2) != 1 {
+			b.Fatal("b1 > b2 failed")
+		}
+	}
+}
+
+func BenchmarkCompareBytesEmpty(b *testing.B) {
+	b1 := []byte("")
+	b2 := b1
+	for i := 0; i < b.N; i++ {
+		if Compare(b1, b2) != 0 {
+			b.Fatal("b1 != b2")
+		}
+	}
+}
+
+func BenchmarkCompareBytesIdentical(b *testing.B) {
+	b1 := []byte("Hello Gophers!")
+	b2 := b1
+	for i := 0; i < b.N; i++ {
+		if Compare(b1, b2) != 0 {
+			b.Fatal("b1 != b2")
+		}
+	}
+}
+
+func BenchmarkCompareBytesSameLength(b *testing.B) {
+	b1 := []byte("Hello Gophers!")
+	b2 := []byte("Hello, Gophers")
+	for i := 0; i < b.N; i++ {
+		if Compare(b1, b2) != -1 {
+			b.Fatal("b1 < b2 failed")
+		}
+	}
+}
+
+func BenchmarkCompareBytesDifferentLength(b *testing.B) {
+	b1 := []byte("Hello Gophers!")
+	b2 := []byte("Hello, Gophers!")
+	for i := 0; i < b.N; i++ {
+		if Compare(b1, b2) != -1 {
+			b.Fatal("b1 < b2 failed")
+		}
+	}
+}
+
+func BenchmarkCompareBytesBigUnaligned(b *testing.B) {
+	b.StopTimer()
+	b1 := make([]byte, 0, 1<<20)
+	for len(b1) < 1<<20 {
+		b1 = append(b1, "Hello Gophers!"...)
+	}
+	b2 := append([]byte("hello"), b1...)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if Compare(b1, b2[len("hello"):]) != 0 {
+			b.Fatal("b1 != b2")
+		}
+	}
+	b.SetBytes(int64(len(b1)))
+}
+
+func BenchmarkCompareBytesBig(b *testing.B) {
+	b.StopTimer()
+	b1 := make([]byte, 0, 1<<20)
+	for len(b1) < 1<<20 {
+		b1 = append(b1, "Hello Gophers!"...)
+	}
+	b2 := append([]byte{}, b1...)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if Compare(b1, b2) != 0 {
+			b.Fatal("b1 != b2")
+		}
+	}
+	b.SetBytes(int64(len(b1)))
+}
+
+func BenchmarkCompareBytesBigIdentical(b *testing.B) {
+	b.StopTimer()
+	b1 := make([]byte, 0, 1<<20)
+	for len(b1) < 1<<20 {
+		b1 = append(b1, "Hello Gophers!"...)
+	}
+	b2 := b1
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if Compare(b1, b2) != 0 {
+			b.Fatal("b1 != b2")
+		}
+	}
+	b.SetBytes(int64(len(b1)))
+}
diff --git a/third_party/gofrontend/libgo/go/bytes/equal_test.go b/third_party/gofrontend/libgo/go/bytes/equal_test.go
new file mode 100644
index 0000000..1bf19a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/equal_test.go
@@ -0,0 +1,47 @@
+// Copyright 2013 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.
+//
+// +build linux
+
+package bytes_test
+
+import (
+	. "bytes"
+	"syscall"
+	"testing"
+	"unsafe"
+)
+
+// This file tests the situation where memeq is checking
+// data very near to a page boundary.  We want to make sure
+// equal does not read across the boundary and cause a page
+// fault where it shouldn't.
+
+// This test runs only on linux.  The code being tested is
+// not OS-specific, so it does not need to be tested on all
+// operating systems.
+
+func TestEqualNearPageBoundary(t *testing.T) {
+	pagesize := syscall.Getpagesize()
+	b := make([]byte, 4*pagesize)
+	i := pagesize
+	for ; uintptr(unsafe.Pointer(&b[i]))%uintptr(pagesize) != 0; i++ {
+	}
+	syscall.Mprotect(b[i-pagesize:i], 0)
+	syscall.Mprotect(b[i+pagesize:i+2*pagesize], 0)
+	defer syscall.Mprotect(b[i-pagesize:i], syscall.PROT_READ|syscall.PROT_WRITE)
+	defer syscall.Mprotect(b[i+pagesize:i+2*pagesize], syscall.PROT_READ|syscall.PROT_WRITE)
+
+	// both of these should fault
+	//pagesize += int(b[i-1])
+	//pagesize += int(b[i+pagesize])
+
+	for j := 0; j < pagesize; j++ {
+		b[i+j] = 'A'
+	}
+	for j := 0; j <= pagesize; j++ {
+		Equal(b[i:i+j], b[i+pagesize-j:i+pagesize])
+		Equal(b[i+pagesize-j:i+pagesize], b[i:i+j])
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/bytes/example_test.go b/third_party/gofrontend/libgo/go/bytes/example_test.go
new file mode 100644
index 0000000..ad2dbc6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/example_test.go
@@ -0,0 +1,85 @@
+// 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.
+
+package bytes_test
+
+import (
+	"bytes"
+	"encoding/base64"
+	"fmt"
+	"io"
+	"os"
+	"sort"
+)
+
+func ExampleBuffer() {
+	var b bytes.Buffer // A Buffer needs no initialization.
+	b.Write([]byte("Hello "))
+	fmt.Fprintf(&b, "world!")
+	b.WriteTo(os.Stdout)
+	// Output: Hello world!
+}
+
+func ExampleBuffer_reader() {
+	// A Buffer can turn a string or a []byte into an io.Reader.
+	buf := bytes.NewBufferString("R29waGVycyBydWxlIQ==")
+	dec := base64.NewDecoder(base64.StdEncoding, buf)
+	io.Copy(os.Stdout, dec)
+	// Output: Gophers rule!
+}
+
+func ExampleCompare() {
+	// Interpret Compare's result by comparing it to zero.
+	var a, b []byte
+	if bytes.Compare(a, b) < 0 {
+		// a less b
+	}
+	if bytes.Compare(a, b) <= 0 {
+		// a less or equal b
+	}
+	if bytes.Compare(a, b) > 0 {
+		// a greater b
+	}
+	if bytes.Compare(a, b) >= 0 {
+		// a greater or equal b
+	}
+
+	// Prefer Equal to Compare for equality comparisons.
+	if bytes.Equal(a, b) {
+		// a equal b
+	}
+	if !bytes.Equal(a, b) {
+		// a not equal b
+	}
+}
+
+func ExampleCompare_search() {
+	// Binary search to find a matching byte slice.
+	var needle []byte
+	var haystack [][]byte // Assume sorted
+	i := sort.Search(len(haystack), func(i int) bool {
+		// Return haystack[i] >= needle.
+		return bytes.Compare(haystack[i], needle) >= 0
+	})
+	if i < len(haystack) && bytes.Equal(haystack[i], needle) {
+		// Found it!
+	}
+}
+
+func ExampleTrimSuffix() {
+	var b = []byte("Hello, goodbye, etc!")
+	b = bytes.TrimSuffix(b, []byte("goodbye, etc!"))
+	b = bytes.TrimSuffix(b, []byte("gopher"))
+	b = append(b, bytes.TrimSuffix([]byte("world!"), []byte("x!"))...)
+	os.Stdout.Write(b)
+	// Output: Hello, world!
+}
+
+func ExampleTrimPrefix() {
+	var b = []byte("Goodbye,, world!")
+	b = bytes.TrimPrefix(b, []byte("Goodbye,"))
+	b = bytes.TrimPrefix(b, []byte("See ya,"))
+	fmt.Printf("Hello%s", b)
+	// Output: Hello, world!
+}
diff --git a/third_party/gofrontend/libgo/go/bytes/export_test.go b/third_party/gofrontend/libgo/go/bytes/export_test.go
new file mode 100644
index 0000000..3b915d5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/export_test.go
@@ -0,0 +1,13 @@
+// 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 bytes
+
+// Export func for testing
+var IndexBytePortable = indexBytePortable
+var EqualPortable = equalPortable
+
+func (b *Buffer) Cap() int {
+	return cap(b.buf)
+}
diff --git a/third_party/gofrontend/libgo/go/bytes/indexbyte.c b/third_party/gofrontend/libgo/go/bytes/indexbyte.c
new file mode 100644
index 0000000..b248108
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/indexbyte.c
@@ -0,0 +1,73 @@
+/* indexbyte.c -- implement bytes.IndexByte for Go.
+
+   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.  */
+
+#include <stddef.h>
+
+#include "runtime.h"
+#include "array.h"
+
+/* This is in C so that the compiler can optimize it appropriately.
+   We deliberately don't split the stack in case it does call the
+   library function, which shouldn't need much stack space.  */
+
+intgo IndexByte (struct __go_open_array, char)
+  __asm__ (GOSYM_PREFIX "bytes.IndexByte")
+  __attribute__ ((no_split_stack));
+
+intgo
+IndexByte (struct __go_open_array s, char b)
+{
+  char *p;
+
+  p = __builtin_memchr (s.__values, b, s.__count);
+  if (p == NULL)
+    return -1;
+  return p - (char *) s.__values;
+}
+
+/* Comparison.  */
+
+_Bool Equal (struct __go_open_array a, struct __go_open_array b)
+  __asm__ (GOSYM_PREFIX "bytes.Equal")
+  __attribute__ ((no_split_stack));
+
+_Bool
+Equal (struct __go_open_array a, struct __go_open_array b)
+{
+  if (a.__count != b.__count)
+    return 0;
+  return __builtin_memcmp (a.__values, b.__values, a.__count) == 0;
+}
+
+intgo Compare (struct __go_open_array a, struct __go_open_array b)
+  __asm__ (GOSYM_PREFIX "bytes.Compare")
+  __attribute__ ((no_split_stack));
+
+intgo
+Compare (struct __go_open_array a, struct __go_open_array b)
+{
+  intgo len;
+
+  len = a.__count;
+  if (len > b.__count)
+    len = b.__count;
+  if (len > 0)
+    {
+      intgo ret;
+
+      ret = __builtin_memcmp (a.__values, b.__values, len);
+      if (ret < 0)
+	return -1;
+      else if (ret > 0)
+	return 1;
+    }
+  if (a.__count < b.__count)
+    return -1;
+  else if (a.__count > b.__count)
+    return 1;
+  else
+    return 0;
+}
diff --git a/third_party/gofrontend/libgo/go/bytes/reader.go b/third_party/gofrontend/libgo/go/bytes/reader.go
new file mode 100644
index 0000000..d2d40fa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/reader.go
@@ -0,0 +1,144 @@
+// 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 bytes
+
+import (
+	"errors"
+	"io"
+	"unicode/utf8"
+)
+
+// A Reader implements the io.Reader, io.ReaderAt, io.WriterTo, io.Seeker,
+// io.ByteScanner, and io.RuneScanner interfaces by reading from
+// a byte slice.
+// Unlike a Buffer, a Reader is read-only and supports seeking.
+type Reader struct {
+	s        []byte
+	i        int64 // current reading index
+	prevRune int   // index of previous rune; or < 0
+}
+
+// Len returns the number of bytes of the unread portion of the
+// slice.
+func (r *Reader) Len() int {
+	if r.i >= int64(len(r.s)) {
+		return 0
+	}
+	return int(int64(len(r.s)) - r.i)
+}
+
+func (r *Reader) Read(b []byte) (n int, err error) {
+	if len(b) == 0 {
+		return 0, nil
+	}
+	if r.i >= int64(len(r.s)) {
+		return 0, io.EOF
+	}
+	r.prevRune = -1
+	n = copy(b, r.s[r.i:])
+	r.i += int64(n)
+	return
+}
+
+func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
+	// cannot modify state - see io.ReaderAt
+	if off < 0 {
+		return 0, errors.New("bytes.Reader.ReadAt: negative offset")
+	}
+	if off >= int64(len(r.s)) {
+		return 0, io.EOF
+	}
+	n = copy(b, r.s[off:])
+	if n < len(b) {
+		err = io.EOF
+	}
+	return
+}
+
+func (r *Reader) ReadByte() (b byte, err error) {
+	r.prevRune = -1
+	if r.i >= int64(len(r.s)) {
+		return 0, io.EOF
+	}
+	b = r.s[r.i]
+	r.i++
+	return
+}
+
+func (r *Reader) UnreadByte() error {
+	r.prevRune = -1
+	if r.i <= 0 {
+		return errors.New("bytes.Reader.UnreadByte: at beginning of slice")
+	}
+	r.i--
+	return nil
+}
+
+func (r *Reader) ReadRune() (ch rune, size int, err error) {
+	if r.i >= int64(len(r.s)) {
+		r.prevRune = -1
+		return 0, 0, io.EOF
+	}
+	r.prevRune = int(r.i)
+	if c := r.s[r.i]; c < utf8.RuneSelf {
+		r.i++
+		return rune(c), 1, nil
+	}
+	ch, size = utf8.DecodeRune(r.s[r.i:])
+	r.i += int64(size)
+	return
+}
+
+func (r *Reader) UnreadRune() error {
+	if r.prevRune < 0 {
+		return errors.New("bytes.Reader.UnreadRune: previous operation was not ReadRune")
+	}
+	r.i = int64(r.prevRune)
+	r.prevRune = -1
+	return nil
+}
+
+// Seek implements the io.Seeker interface.
+func (r *Reader) Seek(offset int64, whence int) (int64, error) {
+	r.prevRune = -1
+	var abs int64
+	switch whence {
+	case 0:
+		abs = offset
+	case 1:
+		abs = int64(r.i) + offset
+	case 2:
+		abs = int64(len(r.s)) + offset
+	default:
+		return 0, errors.New("bytes.Reader.Seek: invalid whence")
+	}
+	if abs < 0 {
+		return 0, errors.New("bytes.Reader.Seek: negative position")
+	}
+	r.i = abs
+	return abs, nil
+}
+
+// WriteTo implements the io.WriterTo interface.
+func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
+	r.prevRune = -1
+	if r.i >= int64(len(r.s)) {
+		return 0, nil
+	}
+	b := r.s[r.i:]
+	m, err := w.Write(b)
+	if m > len(b) {
+		panic("bytes.Reader.WriteTo: invalid Write count")
+	}
+	r.i += int64(m)
+	n = int64(m)
+	if m != len(b) && err == nil {
+		err = io.ErrShortWrite
+	}
+	return
+}
+
+// NewReader returns a new Reader reading from b.
+func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }
diff --git a/third_party/gofrontend/libgo/go/bytes/reader_test.go b/third_party/gofrontend/libgo/go/bytes/reader_test.go
new file mode 100644
index 0000000..d3dce53
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/bytes/reader_test.go
@@ -0,0 +1,246 @@
+// 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 bytes_test
+
+import (
+	. "bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"sync"
+	"testing"
+)
+
+func TestReader(t *testing.T) {
+	r := NewReader([]byte("0123456789"))
+	tests := []struct {
+		off     int64
+		seek    int
+		n       int
+		want    string
+		wantpos int64
+		seekerr string
+	}{
+		{seek: os.SEEK_SET, off: 0, n: 20, want: "0123456789"},
+		{seek: os.SEEK_SET, off: 1, n: 1, want: "1"},
+		{seek: os.SEEK_CUR, off: 1, wantpos: 3, n: 2, want: "34"},
+		{seek: os.SEEK_SET, off: -1, seekerr: "bytes.Reader.Seek: negative position"},
+		{seek: os.SEEK_SET, off: 1 << 33, wantpos: 1 << 33},
+		{seek: os.SEEK_CUR, off: 1, wantpos: 1<<33 + 1},
+		{seek: os.SEEK_SET, n: 5, want: "01234"},
+		{seek: os.SEEK_CUR, n: 5, want: "56789"},
+		{seek: os.SEEK_END, off: -1, n: 1, wantpos: 9, want: "9"},
+	}
+
+	for i, tt := range tests {
+		pos, err := r.Seek(tt.off, tt.seek)
+		if err == nil && tt.seekerr != "" {
+			t.Errorf("%d. want seek error %q", i, tt.seekerr)
+			continue
+		}
+		if err != nil && err.Error() != tt.seekerr {
+			t.Errorf("%d. seek error = %q; want %q", i, err.Error(), tt.seekerr)
+			continue
+		}
+		if tt.wantpos != 0 && tt.wantpos != pos {
+			t.Errorf("%d. pos = %d, want %d", i, pos, tt.wantpos)
+		}
+		buf := make([]byte, tt.n)
+		n, err := r.Read(buf)
+		if err != nil {
+			t.Errorf("%d. read = %v", i, err)
+			continue
+		}
+		got := string(buf[:n])
+		if got != tt.want {
+			t.Errorf("%d. got %q; want %q", i, got, tt.want)
+		}
+	}
+}
+
+func TestReadAfterBigSeek(t *testing.T) {
+	r := NewReader([]byte("0123456789"))
+	if _, err := r.Seek(1<<31+5, os.SEEK_SET); err != nil {
+		t.Fatal(err)
+	}
+	if n, err := r.Read(make([]byte, 10)); n != 0 || err != io.EOF {
+		t.Errorf("Read = %d, %v; want 0, EOF", n, err)
+	}
+}
+
+func TestReaderAt(t *testing.T) {
+	r := NewReader([]byte("0123456789"))
+	tests := []struct {
+		off     int64
+		n       int
+		want    string
+		wanterr interface{}
+	}{
+		{0, 10, "0123456789", nil},
+		{1, 10, "123456789", io.EOF},
+		{1, 9, "123456789", nil},
+		{11, 10, "", io.EOF},
+		{0, 0, "", nil},
+		{-1, 0, "", "bytes.Reader.ReadAt: negative offset"},
+	}
+	for i, tt := range tests {
+		b := make([]byte, tt.n)
+		rn, err := r.ReadAt(b, tt.off)
+		got := string(b[:rn])
+		if got != tt.want {
+			t.Errorf("%d. got %q; want %q", i, got, tt.want)
+		}
+		if fmt.Sprintf("%v", err) != fmt.Sprintf("%v", tt.wanterr) {
+			t.Errorf("%d. got error = %v; want %v", i, err, tt.wanterr)
+		}
+	}
+}
+
+func TestReaderAtConcurrent(t *testing.T) {
+	// Test for the race detector, to verify ReadAt doesn't mutate
+	// any state.
+	r := NewReader([]byte("0123456789"))
+	var wg sync.WaitGroup
+	for i := 0; i < 5; i++ {
+		wg.Add(1)
+		go func(i int) {
+			defer wg.Done()
+			var buf [1]byte
+			r.ReadAt(buf[:], int64(i))
+		}(i)
+	}
+	wg.Wait()
+}
+
+func TestEmptyReaderConcurrent(t *testing.T) {
+	// Test for the race detector, to verify a Read that doesn't yield any bytes
+	// is okay to use from multiple goroutines. This was our historic behavior.
+	// See golang.org/issue/7856
+	r := NewReader([]byte{})
+	var wg sync.WaitGroup
+	for i := 0; i < 5; i++ {
+		wg.Add(2)
+		go func() {
+			defer wg.Done()
+			var buf [1]byte
+			r.Read(buf[:])
+		}()
+		go func() {
+			defer wg.Done()
+			r.Read(nil)
+		}()
+	}
+	wg.Wait()
+}
+
+func TestReaderWriteTo(t *testing.T) {
+	for i := 0; i < 30; i += 3 {
+		var l int
+		if i > 0 {
+			l = len(data) / i
+		}
+		s := data[:l]
+		r := NewReader(testBytes[:l])
+		var b Buffer
+		n, err := r.WriteTo(&b)
+		if expect := int64(len(s)); n != expect {
+			t.Errorf("got %v; want %v", n, expect)
+		}
+		if err != nil {
+			t.Errorf("for length %d: got error = %v; want nil", l, err)
+		}
+		if b.String() != s {
+			t.Errorf("got string %q; want %q", b.String(), s)
+		}
+		if r.Len() != 0 {
+			t.Errorf("reader contains %v bytes; want 0", r.Len())
+		}
+	}
+}
+
+func TestReaderLen(t *testing.T) {
+	const data = "hello world"
+	r := NewReader([]byte(data))
+	if got, want := r.Len(), 11; got != want {
+		t.Errorf("r.Len(): got %d, want %d", got, want)
+	}
+	if n, err := r.Read(make([]byte, 10)); err != nil || n != 10 {
+		t.Errorf("Read failed: read %d %v", n, err)
+	}
+	if got, want := r.Len(), 1; got != want {
+		t.Errorf("r.Len(): got %d, want %d", got, want)
+	}
+	if n, err := r.Read(make([]byte, 1)); err != nil || n != 1 {
+		t.Errorf("Read failed: read %d %v", n, err)
+	}
+	if got, want := r.Len(), 0; got != want {
+		t.Errorf("r.Len(): got %d, want %d", got, want)
+	}
+}
+
+var UnreadRuneErrorTests = []struct {
+	name string
+	f    func(*Reader)
+}{
+	{"Read", func(r *Reader) { r.Read([]byte{0}) }},
+	{"ReadByte", func(r *Reader) { r.ReadByte() }},
+	{"UnreadRune", func(r *Reader) { r.UnreadRune() }},
+	{"Seek", func(r *Reader) { r.Seek(0, 1) }},
+	{"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }},
+}
+
+func TestUnreadRuneError(t *testing.T) {
+	for _, tt := range UnreadRuneErrorTests {
+		reader := NewReader([]byte("0123456789"))
+		if _, _, err := reader.ReadRune(); err != nil {
+			// should not happen
+			t.Fatal(err)
+		}
+		tt.f(reader)
+		err := reader.UnreadRune()
+		if err == nil {
+			t.Errorf("Unreading after %s: expected error", tt.name)
+		}
+	}
+}
+
+func TestReaderDoubleUnreadRune(t *testing.T) {
+	buf := NewBuffer([]byte("groucho"))
+	if _, _, err := buf.ReadRune(); err != nil {
+		// should not happen
+		t.Fatal(err)
+	}
+	if err := buf.UnreadByte(); err != nil {
+		// should not happen
+		t.Fatal(err)
+	}
+	if err := buf.UnreadByte(); err == nil {
+		t.Fatal("UnreadByte: expected error, got nil")
+	}
+}
+
+// verify that copying from an empty reader always has the same results,
+// regardless of the presence of a WriteTo method.
+func TestReaderCopyNothing(t *testing.T) {
+	type nErr struct {
+		n   int64
+		err error
+	}
+	type justReader struct {
+		io.Reader
+	}
+	type justWriter struct {
+		io.Writer
+	}
+	discard := justWriter{ioutil.Discard} // hide ReadFrom
+
+	var with, withOut nErr
+	with.n, with.err = io.Copy(discard, NewReader(nil))
+	withOut.n, withOut.err = io.Copy(discard, justReader{NewReader(nil)})
+	if with != withOut {
+		t.Errorf("behavior differs: with = %#v; without: %#v", with, withOut)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/bzip2/bit_reader.go b/third_party/gofrontend/libgo/go/compress/bzip2/bit_reader.go
new file mode 100644
index 0000000..32d1036
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/bzip2/bit_reader.go
@@ -0,0 +1,90 @@
+// 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.
+
+package bzip2
+
+import (
+	"bufio"
+	"io"
+)
+
+// bitReader wraps an io.Reader and provides the ability to read values,
+// bit-by-bit, from it. Its Read* methods don't return the usual error
+// because the error handling was verbose. Instead, any error is kept and can
+// be checked afterwards.
+type bitReader struct {
+	r    io.ByteReader
+	n    uint64
+	bits uint
+	err  error
+}
+
+// newBitReader returns a new bitReader reading from r. If r is not
+// already an io.ByteReader, it will be converted via a bufio.Reader.
+func newBitReader(r io.Reader) bitReader {
+	byter, ok := r.(io.ByteReader)
+	if !ok {
+		byter = bufio.NewReader(r)
+	}
+	return bitReader{r: byter}
+}
+
+// ReadBits64 reads the given number of bits and returns them in the
+// least-significant part of a uint64. In the event of an error, it returns 0
+// and the error can be obtained by calling Err().
+func (br *bitReader) ReadBits64(bits uint) (n uint64) {
+	for bits > br.bits {
+		b, err := br.r.ReadByte()
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		if err != nil {
+			br.err = err
+			return 0
+		}
+		br.n <<= 8
+		br.n |= uint64(b)
+		br.bits += 8
+	}
+
+	// br.n looks like this (assuming that br.bits = 14 and bits = 6):
+	// Bit: 111111
+	//      5432109876543210
+	//
+	//         (6 bits, the desired output)
+	//        |-----|
+	//        V     V
+	//      0101101101001110
+	//        ^            ^
+	//        |------------|
+	//           br.bits (num valid bits)
+	//
+	// This the next line right shifts the desired bits into the
+	// least-significant places and masks off anything above.
+	n = (br.n >> (br.bits - bits)) & ((1 << bits) - 1)
+	br.bits -= bits
+	return
+}
+
+func (br *bitReader) ReadBits(bits uint) (n int) {
+	n64 := br.ReadBits64(bits)
+	return int(n64)
+}
+
+func (br *bitReader) ReadBit() bool {
+	n := br.ReadBits(1)
+	return n != 0
+}
+
+func (br *bitReader) TryReadBit() (bit byte, ok bool) {
+	if br.bits > 0 {
+		br.bits--
+		return byte(br.n>>br.bits) & 1, true
+	}
+	return 0, false
+}
+
+func (br *bitReader) Err() error {
+	return br.err
+}
diff --git a/third_party/gofrontend/libgo/go/compress/bzip2/bzip2.go b/third_party/gofrontend/libgo/go/compress/bzip2/bzip2.go
new file mode 100644
index 0000000..82e30c7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/bzip2/bzip2.go
@@ -0,0 +1,484 @@
+// 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.
+
+// Package bzip2 implements bzip2 decompression.
+package bzip2
+
+import "io"
+
+// There's no RFC for bzip2. I used the Wikipedia page for reference and a lot
+// of guessing: http://en.wikipedia.org/wiki/Bzip2
+// The source code to pyflate was useful for debugging:
+// http://www.paul.sladen.org/projects/pyflate
+
+// A StructuralError is returned when the bzip2 data is found to be
+// syntactically invalid.
+type StructuralError string
+
+func (s StructuralError) Error() string {
+	return "bzip2 data invalid: " + string(s)
+}
+
+// A reader decompresses bzip2 compressed data.
+type reader struct {
+	br           bitReader
+	fileCRC      uint32
+	blockCRC     uint32
+	wantBlockCRC uint32
+	setupDone    bool // true if we have parsed the bzip2 header.
+	blockSize    int  // blockSize in bytes, i.e. 900 * 1024.
+	eof          bool
+	buf          []byte    // stores Burrows-Wheeler transformed data.
+	c            [256]uint // the `C' array for the inverse BWT.
+	tt           []uint32  // mirrors the `tt' array in the bzip2 source and contains the P array in the upper 24 bits.
+	tPos         uint32    // Index of the next output byte in tt.
+
+	preRLE      []uint32 // contains the RLE data still to be processed.
+	preRLEUsed  int      // number of entries of preRLE used.
+	lastByte    int      // the last byte value seen.
+	byteRepeats uint     // the number of repeats of lastByte seen.
+	repeats     uint     // the number of copies of lastByte to output.
+}
+
+// NewReader returns an io.Reader which decompresses bzip2 data from r.
+func NewReader(r io.Reader) io.Reader {
+	bz2 := new(reader)
+	bz2.br = newBitReader(r)
+	return bz2
+}
+
+const bzip2FileMagic = 0x425a // "BZ"
+const bzip2BlockMagic = 0x314159265359
+const bzip2FinalMagic = 0x177245385090
+
+// setup parses the bzip2 header.
+func (bz2 *reader) setup(needMagic bool) error {
+	br := &bz2.br
+
+	if needMagic {
+		magic := br.ReadBits(16)
+		if magic != bzip2FileMagic {
+			return StructuralError("bad magic value")
+		}
+	}
+
+	t := br.ReadBits(8)
+	if t != 'h' {
+		return StructuralError("non-Huffman entropy encoding")
+	}
+
+	level := br.ReadBits(8)
+	if level < '1' || level > '9' {
+		return StructuralError("invalid compression level")
+	}
+
+	bz2.fileCRC = 0
+	bz2.blockSize = 100 * 1024 * (int(level) - '0')
+	if bz2.blockSize > len(bz2.tt) {
+		bz2.tt = make([]uint32, bz2.blockSize)
+	}
+	return nil
+}
+
+func (bz2 *reader) Read(buf []byte) (n int, err error) {
+	if bz2.eof {
+		return 0, io.EOF
+	}
+
+	if !bz2.setupDone {
+		err = bz2.setup(true)
+		brErr := bz2.br.Err()
+		if brErr != nil {
+			err = brErr
+		}
+		if err != nil {
+			return 0, err
+		}
+		bz2.setupDone = true
+	}
+
+	n, err = bz2.read(buf)
+	brErr := bz2.br.Err()
+	if brErr != nil {
+		err = brErr
+	}
+	return
+}
+
+func (bz2 *reader) readFromBlock(buf []byte) int {
+	// bzip2 is a block based compressor, except that it has a run-length
+	// preprocessing step. The block based nature means that we can
+	// preallocate fixed-size buffers and reuse them. However, the RLE
+	// preprocessing would require allocating huge buffers to store the
+	// maximum expansion. Thus we process blocks all at once, except for
+	// the RLE which we decompress as required.
+	n := 0
+	for (bz2.repeats > 0 || bz2.preRLEUsed < len(bz2.preRLE)) && n < len(buf) {
+		// We have RLE data pending.
+
+		// The run-length encoding works like this:
+		// Any sequence of four equal bytes is followed by a length
+		// byte which contains the number of repeats of that byte to
+		// include. (The number of repeats can be zero.) Because we are
+		// decompressing on-demand our state is kept in the reader
+		// object.
+
+		if bz2.repeats > 0 {
+			buf[n] = byte(bz2.lastByte)
+			n++
+			bz2.repeats--
+			if bz2.repeats == 0 {
+				bz2.lastByte = -1
+			}
+			continue
+		}
+
+		bz2.tPos = bz2.preRLE[bz2.tPos]
+		b := byte(bz2.tPos)
+		bz2.tPos >>= 8
+		bz2.preRLEUsed++
+
+		if bz2.byteRepeats == 3 {
+			bz2.repeats = uint(b)
+			bz2.byteRepeats = 0
+			continue
+		}
+
+		if bz2.lastByte == int(b) {
+			bz2.byteRepeats++
+		} else {
+			bz2.byteRepeats = 0
+		}
+		bz2.lastByte = int(b)
+
+		buf[n] = b
+		n++
+	}
+
+	return n
+}
+
+func (bz2 *reader) read(buf []byte) (int, error) {
+	for {
+		n := bz2.readFromBlock(buf)
+		if n > 0 {
+			bz2.blockCRC = updateCRC(bz2.blockCRC, buf[:n])
+			return n, nil
+		}
+
+		// End of block. Check CRC.
+		if bz2.blockCRC != bz2.wantBlockCRC {
+			bz2.br.err = StructuralError("block checksum mismatch")
+			return 0, bz2.br.err
+		}
+
+		// Find next block.
+		br := &bz2.br
+		switch br.ReadBits64(48) {
+		default:
+			return 0, StructuralError("bad magic value found")
+
+		case bzip2BlockMagic:
+			// Start of block.
+			err := bz2.readBlock()
+			if err != nil {
+				return 0, err
+			}
+
+		case bzip2FinalMagic:
+			// Check end-of-file CRC.
+			wantFileCRC := uint32(br.ReadBits64(32))
+			if br.err != nil {
+				return 0, br.err
+			}
+			if bz2.fileCRC != wantFileCRC {
+				br.err = StructuralError("file checksum mismatch")
+				return 0, br.err
+			}
+
+			// Skip ahead to byte boundary.
+			// Is there a file concatenated to this one?
+			// It would start with BZ.
+			if br.bits%8 != 0 {
+				br.ReadBits(br.bits % 8)
+			}
+			b, err := br.r.ReadByte()
+			if err == io.EOF {
+				br.err = io.EOF
+				bz2.eof = true
+				return 0, io.EOF
+			}
+			if err != nil {
+				br.err = err
+				return 0, err
+			}
+			z, err := br.r.ReadByte()
+			if err != nil {
+				if err == io.EOF {
+					err = io.ErrUnexpectedEOF
+				}
+				br.err = err
+				return 0, err
+			}
+			if b != 'B' || z != 'Z' {
+				return 0, StructuralError("bad magic value in continuation file")
+			}
+			if err := bz2.setup(false); err != nil {
+				return 0, err
+			}
+		}
+	}
+}
+
+// readBlock reads a bzip2 block. The magic number should already have been consumed.
+func (bz2 *reader) readBlock() (err error) {
+	br := &bz2.br
+	bz2.wantBlockCRC = uint32(br.ReadBits64(32)) // skip checksum. TODO: check it if we can figure out what it is.
+	bz2.blockCRC = 0
+	bz2.fileCRC = (bz2.fileCRC<<1 | bz2.fileCRC>>31) ^ bz2.wantBlockCRC
+	randomized := br.ReadBits(1)
+	if randomized != 0 {
+		return StructuralError("deprecated randomized files")
+	}
+	origPtr := uint(br.ReadBits(24))
+
+	// If not every byte value is used in the block (i.e., it's text) then
+	// the symbol set is reduced. The symbols used are stored as a
+	// two-level, 16x16 bitmap.
+	symbolRangeUsedBitmap := br.ReadBits(16)
+	symbolPresent := make([]bool, 256)
+	numSymbols := 0
+	for symRange := uint(0); symRange < 16; symRange++ {
+		if symbolRangeUsedBitmap&(1<<(15-symRange)) != 0 {
+			bits := br.ReadBits(16)
+			for symbol := uint(0); symbol < 16; symbol++ {
+				if bits&(1<<(15-symbol)) != 0 {
+					symbolPresent[16*symRange+symbol] = true
+					numSymbols++
+				}
+			}
+		}
+	}
+
+	// A block uses between two and six different Huffman trees.
+	numHuffmanTrees := br.ReadBits(3)
+	if numHuffmanTrees < 2 || numHuffmanTrees > 6 {
+		return StructuralError("invalid number of Huffman trees")
+	}
+
+	// The Huffman tree can switch every 50 symbols so there's a list of
+	// tree indexes telling us which tree to use for each 50 symbol block.
+	numSelectors := br.ReadBits(15)
+	treeIndexes := make([]uint8, numSelectors)
+
+	// The tree indexes are move-to-front transformed and stored as unary
+	// numbers.
+	mtfTreeDecoder := newMTFDecoderWithRange(numHuffmanTrees)
+	for i := range treeIndexes {
+		c := 0
+		for {
+			inc := br.ReadBits(1)
+			if inc == 0 {
+				break
+			}
+			c++
+		}
+		if c >= numHuffmanTrees {
+			return StructuralError("tree index too large")
+		}
+		treeIndexes[i] = uint8(mtfTreeDecoder.Decode(c))
+	}
+
+	// The list of symbols for the move-to-front transform is taken from
+	// the previously decoded symbol bitmap.
+	symbols := make([]byte, numSymbols)
+	nextSymbol := 0
+	for i := 0; i < 256; i++ {
+		if symbolPresent[i] {
+			symbols[nextSymbol] = byte(i)
+			nextSymbol++
+		}
+	}
+	mtf := newMTFDecoder(symbols)
+
+	numSymbols += 2 // to account for RUNA and RUNB symbols
+	huffmanTrees := make([]huffmanTree, numHuffmanTrees)
+
+	// Now we decode the arrays of code-lengths for each tree.
+	lengths := make([]uint8, numSymbols)
+	for i := 0; i < numHuffmanTrees; i++ {
+		// The code lengths are delta encoded from a 5-bit base value.
+		length := br.ReadBits(5)
+		for j := 0; j < numSymbols; j++ {
+			for {
+				if !br.ReadBit() {
+					break
+				}
+				if br.ReadBit() {
+					length--
+				} else {
+					length++
+				}
+			}
+			if length < 0 || length > 20 {
+				return StructuralError("Huffman length out of range")
+			}
+			lengths[j] = uint8(length)
+		}
+		huffmanTrees[i], err = newHuffmanTree(lengths)
+		if err != nil {
+			return err
+		}
+	}
+
+	selectorIndex := 1 // the next tree index to use
+	currentHuffmanTree := huffmanTrees[treeIndexes[0]]
+	bufIndex := 0 // indexes bz2.buf, the output buffer.
+	// The output of the move-to-front transform is run-length encoded and
+	// we merge the decoding into the Huffman parsing loop. These two
+	// variables accumulate the repeat count. See the Wikipedia page for
+	// details.
+	repeat := 0
+	repeat_power := 0
+
+	// The `C' array (used by the inverse BWT) needs to be zero initialized.
+	for i := range bz2.c {
+		bz2.c[i] = 0
+	}
+
+	decoded := 0 // counts the number of symbols decoded by the current tree.
+	for {
+		if decoded == 50 {
+			currentHuffmanTree = huffmanTrees[treeIndexes[selectorIndex]]
+			selectorIndex++
+			decoded = 0
+		}
+
+		v := currentHuffmanTree.Decode(br)
+		decoded++
+
+		if v < 2 {
+			// This is either the RUNA or RUNB symbol.
+			if repeat == 0 {
+				repeat_power = 1
+			}
+			repeat += repeat_power << v
+			repeat_power <<= 1
+
+			// This limit of 2 million comes from the bzip2 source
+			// code. It prevents repeat from overflowing.
+			if repeat > 2*1024*1024 {
+				return StructuralError("repeat count too large")
+			}
+			continue
+		}
+
+		if repeat > 0 {
+			// We have decoded a complete run-length so we need to
+			// replicate the last output symbol.
+			if repeat > bz2.blockSize-bufIndex {
+				return StructuralError("repeats past end of block")
+			}
+			for i := 0; i < repeat; i++ {
+				b := byte(mtf.First())
+				bz2.tt[bufIndex] = uint32(b)
+				bz2.c[b]++
+				bufIndex++
+			}
+			repeat = 0
+		}
+
+		if int(v) == numSymbols-1 {
+			// This is the EOF symbol. Because it's always at the
+			// end of the move-to-front list, and never gets moved
+			// to the front, it has this unique value.
+			break
+		}
+
+		// Since two metasymbols (RUNA and RUNB) have values 0 and 1,
+		// one would expect |v-2| to be passed to the MTF decoder.
+		// However, the front of the MTF list is never referenced as 0,
+		// it's always referenced with a run-length of 1. Thus 0
+		// doesn't need to be encoded and we have |v-1| in the next
+		// line.
+		b := byte(mtf.Decode(int(v - 1)))
+		if bufIndex >= bz2.blockSize {
+			return StructuralError("data exceeds block size")
+		}
+		bz2.tt[bufIndex] = uint32(b)
+		bz2.c[b]++
+		bufIndex++
+	}
+
+	if origPtr >= uint(bufIndex) {
+		return StructuralError("origPtr out of bounds")
+	}
+
+	// We have completed the entropy decoding. Now we can perform the
+	// inverse BWT and setup the RLE buffer.
+	bz2.preRLE = bz2.tt[:bufIndex]
+	bz2.preRLEUsed = 0
+	bz2.tPos = inverseBWT(bz2.preRLE, origPtr, bz2.c[:])
+	bz2.lastByte = -1
+	bz2.byteRepeats = 0
+	bz2.repeats = 0
+
+	return nil
+}
+
+// inverseBWT implements the inverse Burrows-Wheeler transform as described in
+// http://www.hpl.hp.com/techreports/Compaq-DEC/SRC-RR-124.pdf, section 4.2.
+// In that document, origPtr is called `I' and c is the `C' array after the
+// first pass over the data. It's an argument here because we merge the first
+// pass with the Huffman decoding.
+//
+// This also implements the `single array' method from the bzip2 source code
+// which leaves the output, still shuffled, in the bottom 8 bits of tt with the
+// index of the next byte in the top 24-bits. The index of the first byte is
+// returned.
+func inverseBWT(tt []uint32, origPtr uint, c []uint) uint32 {
+	sum := uint(0)
+	for i := 0; i < 256; i++ {
+		sum += c[i]
+		c[i] = sum - c[i]
+	}
+
+	for i := range tt {
+		b := tt[i] & 0xff
+		tt[c[b]] |= uint32(i) << 8
+		c[b]++
+	}
+
+	return tt[origPtr] >> 8
+}
+
+// This is a standard CRC32 like in hash/crc32 except that all the shifts are reversed,
+// causing the bits in the input to be processed in the reverse of the usual order.
+
+var crctab [256]uint32
+
+func init() {
+	const poly = 0x04C11DB7
+	for i := range crctab {
+		crc := uint32(i) << 24
+		for j := 0; j < 8; j++ {
+			if crc&0x80000000 != 0 {
+				crc = (crc << 1) ^ poly
+			} else {
+				crc <<= 1
+			}
+		}
+		crctab[i] = crc
+	}
+}
+
+// updateCRC updates the crc value to incorporate the data in b.
+// The initial value is 0.
+func updateCRC(val uint32, b []byte) uint32 {
+	crc := ^val
+	for _, v := range b {
+		crc = crctab[byte(crc>>24)^v] ^ (crc << 8)
+	}
+	return ^crc
+}
diff --git a/third_party/gofrontend/libgo/go/compress/bzip2/bzip2_test.go b/third_party/gofrontend/libgo/go/compress/bzip2/bzip2_test.go
new file mode 100644
index 0000000..727249d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/bzip2/bzip2_test.go
@@ -0,0 +1,363 @@
+// 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.
+
+package bzip2
+
+import (
+	"bytes"
+	"encoding/base64"
+	"encoding/hex"
+	"io"
+	"io/ioutil"
+	"testing"
+)
+
+func TestBitReader(t *testing.T) {
+	buf := bytes.NewReader([]byte{0xaa})
+	br := newBitReader(buf)
+	if n := br.ReadBits(1); n != 1 {
+		t.Errorf("read 1 wrong")
+	}
+	if n := br.ReadBits(1); n != 0 {
+		t.Errorf("read 2 wrong")
+	}
+	if n := br.ReadBits(1); n != 1 {
+		t.Errorf("read 3 wrong")
+	}
+	if n := br.ReadBits(1); n != 0 {
+		t.Errorf("read 4 wrong")
+	}
+}
+
+func TestBitReaderLarge(t *testing.T) {
+	buf := bytes.NewReader([]byte{0x12, 0x34, 0x56, 0x78})
+	br := newBitReader(buf)
+	if n := br.ReadBits(32); n != 0x12345678 {
+		t.Errorf("got: %x want: %x", n, 0x12345678)
+	}
+}
+
+func readerFromHex(s string) io.Reader {
+	data, err := hex.DecodeString(s)
+	if err != nil {
+		panic("readerFromHex: bad input")
+	}
+	return bytes.NewReader(data)
+}
+
+func decompressHex(s string) (out []byte, err error) {
+	r := NewReader(readerFromHex(s))
+	return ioutil.ReadAll(r)
+}
+
+func TestHelloWorldBZ2(t *testing.T) {
+	out, err := decompressHex(helloWorldBZ2Hex)
+	if err != nil {
+		t.Errorf("error from Read: %s", err)
+		return
+	}
+
+	if !bytes.Equal(helloWorld, out) {
+		t.Errorf("got %x, want %x", out, helloWorld)
+	}
+}
+
+func TestConcat(t *testing.T) {
+	out, err := decompressHex(helloWorldBZ2Hex + helloWorldBZ2Hex)
+	if err != nil {
+		t.Errorf("error from Read: %s", err)
+		return
+	}
+
+	hello2 := bytes.Repeat(helloWorld, 2)
+	if !bytes.Equal(hello2, out) {
+		t.Errorf("got %x, want %x", out, hello2)
+	}
+}
+
+func testZeros(t *testing.T, inHex string, n int) {
+	out, err := decompressHex(inHex)
+	if err != nil {
+		t.Errorf("error from Read: %s", err)
+		return
+	}
+
+	expected := make([]byte, n)
+
+	if !bytes.Equal(expected, out) {
+		allZeros := true
+		for _, b := range out {
+			if b != 0 {
+				allZeros = false
+				break
+			}
+		}
+		t.Errorf("incorrect result, got %d bytes (allZeros: %t)", len(out), allZeros)
+	}
+}
+
+func Test32Zeros(t *testing.T) {
+	testZeros(t, thirtyTwoZerosBZ2Hex, 32)
+}
+
+func Test1MBZeros(t *testing.T) {
+	testZeros(t, oneMBZerosBZ2Hex, 1024*1024)
+}
+
+func testRandomData(t *testing.T, compressedHex, uncompressedHex string) {
+	out, err := decompressHex(compressedHex)
+	if err != nil {
+		t.Errorf("error from Read: %s", err)
+		return
+	}
+
+	expected, _ := hex.DecodeString(uncompressedHex)
+
+	if !bytes.Equal(out, expected) {
+		t.Errorf("incorrect result\ngot:  %x\nwant: %x", out, expected)
+	}
+}
+
+func TestRandomData1(t *testing.T) {
+	testRandomData(t, randBZ2Hex, randHex)
+}
+
+func TestRandomData2(t *testing.T) {
+	// This test involves several repeated bytes in the output, but they
+	// should trigger RLE decoding.
+	testRandomData(t, rand2BZ2Hex, rand2Hex)
+}
+
+func TestRandomData3(t *testing.T) {
+	// This test uses the full range of symbols.
+	testRandomData(t, rand3BZ2Hex, rand3Hex)
+}
+
+func Test1MBSawtooth(t *testing.T) {
+	out, err := decompressHex(oneMBSawtoothBZ2Hex)
+	if err != nil {
+		t.Errorf("error from Read: %s", err)
+		return
+	}
+
+	expected := make([]byte, 1024*1024)
+
+	for i := range expected {
+		expected[i] = byte(i)
+	}
+
+	if !bytes.Equal(out, expected) {
+		t.Error("incorrect result")
+	}
+}
+
+const helloWorldBZ2Hex = "425a68393141592653594eece83600000251800010400006449080200031064c4101a7a9a580bb9431f8bb9229c28482776741b0"
+
+var helloWorld = []byte("hello world\n")
+
+const thirtyTwoZerosBZ2Hex = "425a6839314159265359b5aa5098000000600040000004200021008283177245385090b5aa5098"
+const oneMBZerosBZ2Hex = "425a683931415926535938571ce50008084000c0040008200030cc0529a60806c4201e2ee48a70a12070ae39ca"
+
+const randBZ2Hex = "425a6839314159265359905d990d0001957fffffffffffafffffffffffffffffbfff6fffdfffffffffffffffffffffffffffffc002b6dd75676ed5b77720098320d11a64626981323d4da47a83131a13d09e8040f534cd4f4d27a464d193008cd09804601347a980026350c9886234d36864193d1351b44c136919e90340d26127a4cd264c32023009898981310c0344c340027a8303427a99a04c00003534c230d034f5006468d268cf54d36a3009a69a62626261311b40026013d34201a6934c9a604c98ca6c8460989fa9346234d30d3469a2604fd4131a7aa6d0046043d4c62098479269e89e835190d018d4c046001a11e801a0264792321932308c43a130688c260d46686804cd01a9e80981193684c6a68c00000004c4c20c04627a4c0000260003400d04c0681a01334026009a6f48041466132581ec5212b081d96b0effc16543e2228b052fcd30f2567ee8d970e0f10aabca68dd8270591c376cfc1baae0dba00aaff2d6caf6b211322c997cc18eaee5927f75185336bf907021324c71626c1dd20e22b9b0977f05d0f901eaa51db9fbaf7c603b4c87bc82890e6dd7e61d0079e27ec050dd788fd958152061cd01e222f9547cb9efc465d775b6fc98bac7d387bffd151ae09dadf19494f7a638e2eae58e550faba5fe6820ea520eb986096de4e527d80def3ba625e71fbefdcf7e7844e0a25d29b52dcd1344fca083737d42692aab38d230485f3c8ed54c2ed31f15cf0270c8143765b10b92157233fa1dfe0d7ce8ffe70b8b8f7250071701dfe9f1c94de362c9031455951c93eb098a6b50ee45c6131fefc3b6f9643e21f4adc59497138e246f5c57d834aa67c4f10d8bd8b3908d8130dd7388409c299a268eab3664fa4907c5c31574874bd8d388a4ab22b339660804e53e1b8d05867d40e3082560608d35d5d2c6054e8bab23da28f61f83efd41d25529ad6ea15fb50505cacfabb0902166427354ca3830a2c8415f21b19e592690fbe447020d685a4bcd16ecc4ff1a1c0e572627d0ef6265c008a43fc243240541061ed7840606be466d1c0dac2c53250ed567507d926c844154560d631960c65e15157829b2c7f16859f111a3a8cb72bf24ffa57a680c3be67b1be67c8dd8aea73ac2437a78df5b686d427080ebc01bd30b71a49f6ea31dc0f08e4849e38face96717690239538bc08b6cc5aa8d467cb9c36aa83d40ac7e58bddbfa185b22065e89a86c0145569d9e23726651aec49e31588d70f40fe9a4449dcf4f89eac220171e9c938e803dc195679651004b79ad33cc0c13aeeba5941b33ffeeb8fbe16e76c7811445c67b4269c90479433ddf9e8ed1d00c166b6c17217fb22c3ef1b0c1c7e28e185446a111c37f1ea6c07a59fbcc6546ecc6968d36ba58bc5489a5640647e426b0c39350cb6f07d5dc7a717648c4ec7f841467597ae1f65f408fd2d9940a4b1b860b3c9ae351dcae0b4425f7e8538710f2e40b7f70d13b51ac05ccc6ecda8264a88cad2d721d18132a9b9110a9e759c2483c77dcefc7e464ec88588174cb0c9abff93230ea0bed8decdd8ed8bfe2b5df0a253803678df04fab44c03b9ab7cc97d6e6d6fd0c4c840ce0efc498436f453bbb181603459471f2b588724592b222ec990614db530e10cadd84705621cfdd9261fa44a5f5806a2d74b575056b3c915255c65678f9c16e6dc00a99180fef1a840aff0e842ac02731080cc92782538360a60a727991013984da4fad95f79d5030677b7528d076b2483685fca4429edf804682fdc110dfc2f7c30e23e20a72e039108a0ad6fdee2f76985a4b4be4f5afc6101bf9d5042b657a05dc914e1424241766434"
+const randHex = "c95138082bdf2b9bfa5b1072b23f729735d42c785eeb94320fb14c265b9c2ca421d01a3db986df1ac2acde5a0e6bf955d6f95e61261540905928e195f1a66644cc7f37281744fff4dc6df35566a494c41a8167151950eb74f5fc45f85ad0e5ed28b49adfe218aa7ec1707e8e1d55825f61f72beda3b4c006b8c9188d7336a5d875329b1b58c27cc4e89ecbae02c7712400c39dd131d2c6de82e2863da51d472bdfb21ecce62cc9cf769ed28aedc7583d755da45a0d90874bda269dd53283a9bdfd05f95fc8e9a304bb338ea1a2111894678c18134f17d31a15d9bfc1237894650f3e715e2548639ecbddb845cfe4a46a7b3a3c540f48629488e8c869f1e9f3f4c552243a8105b20eb8e264994214349dae83b165fd6c2a5b8e83fce09fc0a80d3281c8d53a9a08095bd19cbc1388df23975646ed259e003d39261ee68cbece8bcf32971f7fe7e588e8ba8f5e8597909abaea693836a79a1964050ed910a45a0f13a58cd2d3ae18992c5b23082407fd920d0bf01e33118a017bb5e39f44931346845af52128f7965206759433a346034ea481671f501280067567619f5ecef6cded077f92ed7f3b3ce8e308c80f34ba06939e9303f91b4318c8c1dd4cc223c1f057ac0c91211c629cd30e46ee9ec1d9fd493086b7bc2bc83e33f08749a5d430b0ed4f79d70f481940c9b0930b16321886a0df4fa5a1465d5208c7d3494a7987d9a5e42aa256f0c9523947f8318d0ef0af3d59a45cfc2418d0785c9a548b32b81e7de18be7d55a69a4c156bbb3d7579c0ac8e9c72b24646e54b0d0e8725f8f49fb44ae3c6b9d0287be118586255a90a4a83483ed0328518037e52aa959c5748ed83e13023e532306be98b8288da306bbb040bcf5d92176f84a9306dc6b274b040370b61d71fde58dd6d20e6fee348eae0c54bd0a5a487b2d005f329794f2a902c296af0a4c1f638f63292a1fa18e006c1b1838636f4de71c73635b25660d32e88a0917e1a5677f6a02ca65585b82cbd99fb4badbfa97a585da1e6cadf6737b4ec6ca33f245d66ee6a9fae6785d69b003c17b9fc6ec34fe5824ab8caae5e8e14dc6f9e116e7bf4a60c04388783c8ae929e1b46b3ef3bbe81b38f2fa6da771bf39dfba2374d3d2ed356b8e2c42081d885a91a3afb2f31986d2f9873354c48cf5448492c32e62385af423aa4f83db6d1b2669650379a1134b0a04cbca0862d6f9743c791cbb527d36cd5d1f0fc7f503831c8bd1b7a0ef8ae1a5ed1155dfdd9e32b6bb33138112d3d476b802179cb85a2a6c354ccfed2f31604fbd8d6ec4baf9f1c8454f72c6588c06a7df3178c43a6970bfa02dd6f74cb5ec3b63f9eddaa17db5cbf27fac6de8e57c384afd0954179f7b5690c3bee42abc4fa79b4b12101a9cf5f0b9aecdda945def0bd04163237247d3539850e123fe18139f316fa0256d5bd2faa8"
+
+const oneMBSawtoothBZ2Hex = "425a683931415926535971931ea00006ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe007de00000000000000024c00130001300000000000000000000000000000000000000000000000000000000126000980009800000000000000000000000000000000000000000000000000000000930004c0004c000000000000000000000000000000000000000000000000000000004980026000260000000000000000000000000000000000000000000000000000000009aaaaa0000000000000000000000000000000000000000000000000000000000000000498002600026000000000000000000000000000000000000000000000000000000007fc42271980d044c0a822607411304a08982d044c1a82260f411308a08984d044c2a82261741130ca08986d044c3a82261f411310a08988d044c4a822627411314a0898ad044c5a82262f411318a0898cd044c6a82263741131ca0898ed044c7a82263f411320a08990d044c8a822647411324a08992d044c9a82264f411328a08994d044caa82265741132ca08996d044cba82265f411330a08998d044cca822667411334a0899ad044cda82266f411338a0899cd044cea82267741133ca0899ed044cfa82267f411340a089a0d044d0a822687411344a089a2d044d1a82268f411348a089a4d044d2a82269741134ca089a6d044d3a82269f411350a089a8d044d4a8226a7411354a089aad044d5a8226af411358a089acd044d6a8226b741135ca089aed044d7a8226bf411360a089b0d044d8a8226c7411364a089b2d044d9a8226cf411368a089b4d044daa8226d741136ca089b6d044dba8226df411370a089b8d044dca8226e7411374a089bad044dda8226ef411378a089bcd044dea8226f741137ca089bed044dfa8226ff411380a089c0d044e0a822707411384a089c2d044e1a82270f411388a089c4d044e2a82271741138ca089c59089c69089c71089c79089c81089c89089c91089c99089ca1089ca9089cb1089cb9089cc1089cc9089cd1089cd9089ce1089ce9089cf1089cf9089d01089d09089d11089d19089d21089d29089d31089d39089d41089d49089d51089d59089d61089d69089d71089d79089d81089d89089d91089d99089da1089da9089db1089db9089dc1089dc9089dd1089dd9089de1089de9089df1089df9089e01089e09089e11089e19089e21089e29089e31089e39089e41089e49089e51089e59089e61089e69089e71089e79089e81089e89089e91089e99089ea1089ea9089eb1089eb9089ec1089ec9089ed1089ed9089ee1089ee9089ef1089ef9089f01089f09089f11089f19089f21089f29089f31089f39089f41089f49089f51089f59089f61089f69089f71089f79089f81089f89089f91089f99089fa1089fa9089fb1089fb9089fc1089fc9089fd1089fd9089fe1089fe9089ff1089ff98a0ac9329acf23ba884804fdd3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0034f800000000000024c00130001300000000000000000000000000000000000000000000000000000000126000980009800000000000000000000000000000000000000000000000000000000930004c0004c000000000000000000000000000000000000000000000000000000004980026000260000000000000000000000000000000000000000000000000000000024c0013000130000000000000000000000000000000000000000000000000000000002955540000000000000000000000000000000000000000000000000000000000000001ff108c00846024230221181908c108460a4230621183908c20846124230a21185908c308461a4230e21187908c40846224231221189908c508462a423162118b908c60846324231a2118d908c708463a4231e2118f908c80846424232221191908c908464a4232621193908ca0846524232a21195908cb08465a4232e21197908cc0846624233221199908cd08466a423362119b908ce0846724233a2119d908cf08467a4233e2119f908d008468242342211a1908d108468a42346211a3908d20846924234a211a5908d308469a4234e211a7908d40846a242352211a9908d50846aa42356211ab908d60846b24235a211ad908d70846ba4235e211af908d80846c242362211b1908d90846ca42366211b3908da0846d24236a211b5908db0846da4236e211b7908dc0846e242372211b9908dd0846ea42376211bb908de0846f24237a211bd908df0846fa4237e211bf908e008470242382211c1908e108470a42386211c3908e20847124238a211c5908e2f8c211c6c8471d211c7c84721211c8c84725211c9c84729211cac8472d211cbc84731211ccc84735211cdc84739211cec8473d211cfc84741211d0c84745211d1c84749211d2c8474d211d3c84751211d4c84755211d5c84759211d6c8475d211d7c84761211d8c84765211d9c84769211dac8476d211dbc84771211dcc84775211ddc84779211dec8477d211dfc84781211e0c84785211e1c84789211e2c8478d211e3c84791211e4c84795211e5c84799211e6c8479d211e7c847a1211e8c847a5211e9c847a9211eac847ad211ebc847b1211ecc847b5211edc847b9211eec847bd211efc847c1211f0c847c5211f1c847c9211f2c847cd211f3c847d1211f4c847d5211f5c847d9211f6c847dd211f7c847e1211f8c847e5211f9c847e9211fac847ed211fbc847f1211fcc847f5211fdc847f9211fec847fd211ff8bb9229c284803a8b6248"
+
+const rand2BZ2Hex = "425a6839314159265359d992d0f60000137dfe84020310091c1e280e100e042801099210094806c0110002e70806402000546034000034000000f2830000032000d3403264049270eb7a9280d308ca06ad28f6981bee1bf8160727c7364510d73a1e123083421b63f031f63993a0f40051fbf177245385090d992d0f60"
+const rand2Hex = "92d5652616ac444a4a04af1a8a3964aca0450d43d6cf233bd03233f4ba92f8719e6c2a2bd4f5f88db07ecd0da3a33b263483db9b2c158786ad6363be35d17335ba"
+
+const rand3BZ2Hex = "425a68393141592653593be669d00000327ffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffc002b3b2b1b6e2bae400004c00132300004c0d268c004c08c0130026001a008683234c0684c34008c230261a04c0260064d07a8d00034000d27a1268c9931a8d327a3427a41faa69ea0da264c1a34219326869b51b49a6469a3268c689fa53269a62794687a9a68f5189994c9e487a8f534fd49a3d34043629e8c93d04da4f4648d30d4f44d3234c4d3023d0840680984d309934c234d3131a000640984f536a6132601300130130c8d00d04d1841ea7a8d31a02609b40023460010c01a34d4c1a0d04d3069306810034d0d0d4c0046130d034d0131a9a64d321804c68003400098344c13000991808c0001a00000000098004d3d4da4604c47a13012140aadf8d673c922c607ef6212a8c0403adea4b28aee578900e653b9cdeb8d11e6b838815f3ebaad5a01c5408d84a332170aff8734d4e06612d3c2889f31925fb89e33561f5100ae89b1f7047102e729373d3667e58d73aaa80fa7be368a1cc2dadd81d81ec8e1b504bd772ca31d03649269b01ceddaca07bf3d4eba24de141be3f86f93601e03714c0f64654671684f9f9528626fd4e1b76753dc0c54b842486b8d59d8ab314e86ca818e7a1f079463cbbd70d9b79b283c7edc419406311022e4be98c2c1374df9cdde2d008ce1d00e5f06ad1024baf555631f70831fc1023034e62be7c4bcb648caf276963ffa20e96bb50377fe1c113da0db4625b50741c35a058edb009c6ee5dbf93b8a6b060eec568180e8db791b82aab96cbf4326ca98361461379425ba8dcc347be670bdba7641883e5526ae3d833f6e9cb9bac9557747c79e206151072f7f0071dff3880411846f66bf4075c7462f302b53cb3400a74cf35652ad5641ed33572fd54e7ed7f85f58a0acba89327e7c6be5c58cb71528b99df2431f1d0358f8d28d81d95292da631fb06701decabb205fac59ff0fb1df536afc681eece6ea658c4d9eaa45f1342aa1ff70bdaff2ddaf25ec88c22f12829a0553db1ec2505554cb17d7b282e213a5a2aa30431ded2bce665bb199d023840832fedb2c0c350a27291407ff77440792872137df281592e82076a05c64c345ffb058c64f7f7c207ef78420b7010520610f17e302cc4dfcfaef72a0ed091aab4b541eb0531bbe941ca2f792bf7b31ca6162882b68054a8470115bc2c19f2df2023f7800432b39b04d3a304e8085ba3f1f0ca5b1ba4d38d339e6084de979cdea6d0e244c6c9fa0366bd890621e3d30846f5e8497e21597b8f29bbf52c961a485dfbea647600da0fc1f25ce4d203a8352ece310c39073525044e7ac46acf2ed9120bae1b4f6f02364abfe343f80b290983160c103557af1c68416480d024cc31b6c06cfec011456f1e95c420a12b48b1c3fe220c2879a982fb099948ac440db844b9a112a5188c7783fd3b19593290785f908d95c9db4b280bafe89c1313aeec24772046d9bc089645f0d182a21184e143823c5f52de50e5d7e98d3d7ab56f5413bbccd1415c9bcff707def475b643fb7f29842582104d4cc1dbaaca8f10a2f44273c339e0984f2b1e06ab2f0771db01fafa8142298345f3196f23e5847bda024034b6f59b11c29e981c881456e40d211929fd4f766200258aad8212016322bd5c605790dcfdf1bd2a93d99c9b8f498722d311d7eae7ff420496a31804c55f4759a7b13aaaf5f7ce006c3a8a998897d5e0a504398c2b627852545baf440798bcc5cc049357cf3f17d9771e4528a1af3d77dc794a11346e1bdf5efe37a405b127b4c43b616d61fbc5dc914e14240ef99a7400"
+const rand3Hex = "1744b384d68c042371244e13500d4bfb98c6244e3d71a5b700224420b59c593553f33bd786e3d0ce31626f511bc985f59d1a88aa38ba8ad6218d306abee60dd9172540232b95be1af146c69e72e5fde667a090dc3f93bdc5c5af0ab80acdbaa7a505f628c59dc0247b31a439cacf5010a94376d71521df08c178b02fb96fdb1809144ea38c68536187c53201fea8631fb0a880b4451ccdca7cc61f6aafca21cc7449d920599db61789ac3b1e164b3390124f95022aeea39ccca3ec1053f4fa10de2978e2861ea58e477085c2220021a0927aa94c5d0006b5055abba340e4f9eba22e969978dfd18e278a8b89d877328ae34268bc0174cfe211954c0036f078025217d1269fac1932a03b05a0b616012271bbe1fb554171c7a59b196d8a4479f45a77931b5d97aaf6c0c673cbe597b79b96e2a0c1eae2e66e46ccc8c85798e23ffe972ebdaa3f6caea243c004e60321eb47cd79137d78fd0613be606feacc5b3637bdc96a89c13746db8cad886f3ccf912b2178c823bcac395f06d28080269bdca2debf3419c66c690fd1adcfbd53e32e79443d7a42511a84cb22ca94fffad9149275a075b2f8ae0b021dcde9bf62b102db920733b897560518b06e1ad7f4b03458493ddaa7f4fa2c1609f7a1735aeeb1b3e2cea3ab45fc376323cc91873b7e9c90d07c192e38d3f5dfc9bfab1fd821c854da9e607ea596c391c7ec4161c6c4493929a8176badaa5a5af7211c623f29643a937677d3df0da9266181b7c4da5dd40376db677fe8f4a1dc456adf6f33c1e37cec471dd318c2647644fe52f93707a77da7d1702380a80e14cc0fdce7bf2eed48a529090bae0388ee277ce6c7018c5fb00b88362554362205c641f0d0fab94fd5b8357b5ff08b207fee023709bc126ec90cfb17c006754638f8186aaeb1265e80be0c1189ec07d01d5f6f96cb9ce82744147d18490de7dc72862f42f024a16968891a356f5e7e0e695d8c933ba5b5e43ad4c4ade5399bc2cae9bb6189b7870d7f22956194d277f28b10e01c10c6ffe3e065f7e2d6d056aa790db5649ca84dc64c35566c0af1b68c32b5b7874aaa66467afa44f40e9a0846a07ae75360a641dd2acc69d93219b2891f190621511e62a27f5e4fbe641ece1fa234fc7e9a74f48d2a760d82160d9540f649256b169d1fed6fbefdc491126530f3cbad7913e19fbd7aa53b1e243fbf28d5f38c10ebd77c8b986775975cc1d619efb27cdcd733fa1ca36cffe9c0a33cc9f02463c91a886601fd349efee85ef1462065ef9bd2c8f533220ad93138b8382d5938103ab25b2d9af8ae106e1211eb9b18793fba033900c809c02cd6d17e2f3e6fc84dae873411f8e87c3f0a8f1765b7825d185ce3730f299c3028d4a62da9ee95c2b870fb70c79370d485f9d5d9acb78926d20444033d960524d2776dc31988ec7c0dbf23b9905d"
+
+const (
+	digits = iota
+	twain
+)
+
+var testfiles = []string{
+	// Digits is the digits of the irrational number e. Its decimal representation
+	// does not repeat, but there are only 10 possible digits, so it should be
+	// reasonably compressible.
+	digits: "testdata/e.txt.bz2",
+	// Twain is Project Gutenberg's edition of Mark Twain's classic English novel.
+	twain: "testdata/Mark.Twain-Tom.Sawyer.txt.bz2",
+}
+
+func benchmarkDecode(b *testing.B, testfile int) {
+	compressed, err := ioutil.ReadFile(testfiles[testfile])
+	if err != nil {
+		b.Fatal(err)
+	}
+	b.SetBytes(int64(len(compressed)))
+	for i := 0; i < b.N; i++ {
+		r := bytes.NewReader(compressed)
+		io.Copy(ioutil.Discard, NewReader(r))
+	}
+}
+
+func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
+func BenchmarkDecodeTwain(b *testing.B)  { benchmarkDecode(b, twain) }
+
+func TestBufferOverrun(t *testing.T) {
+	// Tests https://code.google.com/p/go/issues/detail?id=5747.
+	buffer := bytes.NewReader([]byte(bufferOverrunBase64))
+	decoder := base64.NewDecoder(base64.StdEncoding, buffer)
+	decompressor := NewReader(decoder)
+	// This shouldn't panic.
+	ioutil.ReadAll(decompressor)
+}
+
+var bufferOverrunBase64 string = `
+QlpoNTFBWSZTWTzyiGcACMP/////////////////////////////////3/7f3///
+////4N/fCZODak2Xo44GIHZgkGzDRbFAuwAAKoFV7T6AO6qwA6APb6s2rOoAkAAD
+oACUoDtndh0iQAPkAAAAaPWihQoCgr5t97Obju21ChQB0NBm3RbA7apXrRoBooAA
+AhA+IAHWl2Us3O7t9yieb3udvd76+4+fd33nd3HO1bVvfcGRne6+3vfPvfc++995
+w7k973eJhasLVec970tzDNXdX28LoPXZ3H3K9z0s5ufWAfes49d5594c3dUYtI+2
++h1dvtpRa+uvrVEAG9bl893RVEN7cWvroSqWjPMGgAQi7Gq8TJSgKKdjKFBIB9Ae
+LqWxleu715eXe7ml9e5098Z6G1vr7t1QZ6ot76YzPd3j7333t2ql2Chm7XrA9ICQ
+VF77z3rVBWqkSXtlfb099hyezAr6USbGpICTSCFAaqHrKo+tUnm32rpE4Ue+t2mj
+bKUeipEqwc93EdhhTwmQpOhhesC9iqDSPNTWYNSnUtBdm1nsA0nqqNd7OWwDXtFL
+ONmmA6Ubke26I9UblvWIPR5VOWOnctai443URunnDy77uVC59OfRvezlDu33Z7Ly
+3NNuuHW63088xu3t3NHZhkZbG7tXRlj00qOtbaXTJUUdspTbABR9R6EUwQAEAAAA
+EMEwRpoAAAABMmhoAAjBNNAaCMhponpoGpgJpk9TEyp6niGKZkAaAEfqMQ09U80p
++pMGSCKngIAAAAgAAg0AAJhGgABGCEaaTyTKeNI1PE0wkj01GajMSNPSZGnqbU9T
+anlPUNAHqGQ0DQAMg9TamgAAYRU/IAAICAmjQJgjQBMEwp5DTSaaYmhTeqfplPID
+U1T9TynoU82pT1NPU/VP0j1NHqRpk9TTR7SnqaNNGmmQAaAD1Aeo0PSAAAAaaBiK
+eBAQBGgIABGQA0AmBNNBoaAgaJmpglPEyYap6npiTT0agGjJjUaaDTQAAAAAAM1A
+9QAaAAAADU8iEAQAEyAJk0NNNJgIZTJ5E00YSemiaZNGm1MpGNJ+lPU9qm9U2RDM
+oY0EzJB6h6nqDID1NMBDDRpo1AGNAjCMmhkMgaYSJIgAAAQyAAEyBoATECCNhTT0
+U/IZAmCM1DSTxkzUE8p6NDaGiZGJqntTFHvUyU9qPQp7Kn5GgKNPU9QAGg9QAAA3
+wz0Pk/g/m/m9P9H4vxv2+dH3gCS8nhbbbbbYxtgNsBsG0m2MbG0NNtsbYNsaY0wb
+bBibGmm22mxptNpsaGNDTY02JsG0MY0xg2MaYNNDbGwG0L5vsK/F9DO+EAA447Kq
+p7Wdf6Y+5c20T7DfHyMXIzRKrZexw72uiQI+y55vOe52xpqbCLC2uR20JdER7Zvr
+7ufuKb6zhiBxLuj0eA27v8RpMLucw9Ohwcizi2wrpt+yU1FdpM7ZYPcwS3XTef+A
+Wzjxwhdrgw3aH1LeC1eZW900x8V9Nv4hTPXp4l067P/4ANVZFF/imOe/d5bdueam
+/DFFokQWnFaU+ZqLBCM+d0PialJQWnLqRQZk/KhfbbYc2pCUTgffcSYbrCM1N+8l
+HU6gSz+h2GJXs+tbrNviL83M97X0vcTn/F82P8wen8/3/h3sHY+sf9CSej9ThYTV
+3lQ+FUHpfpGD4kv7dYMV995dpDX/y3xR8FoXx1bjUxBTNxuutwQ/h/Eedn9wpn6w
+E3+ND8YhN1HSriIxRE/6uFyMv6/oC6Elarw3aHMMqHJkGiiz6tejmvnYLQa+Qm6G
+deZ7jXTZV6NlpocgDnRdimS06bTYSkvPAL/xoWNLkX6N6VljU0dfKSBmm2uZE/xu
+sutQ1EdP7GdjhglIq4xlOFUFEQpmX+xx7R8y6c0GSAaqusOjNZwxZRudOvmXm1tZ
+T+YnbeB2ir9eiHNrtJNSLD/J/WDyuQpwBUtLKo0krccY/wIILP7f86teb9Z/9oyz
+OX05qEWbObfhpRw+9+rCvp/35ML8KX3aHaI0n+tudbFRsV5FLW+Oa8ruLN4peyVL
+DWjTHrXNthq/s7zAJYMeFJZkZt5mT9rfpH+5g3nc+piOSZ+J5nHtOnKI7Ff8Xl+j
+0t76XTNucCHQ6whav1OHdF53TY5wuv5OzvrdnxoId8fTyUvERr0ERINu/8XxZZ5f
+B5/kTZ8bBO0wv54Jp+ED/GQI8lZHzIQCP3vfQhwnCTj9TvITic7P4mYLDbH3fyzR
+i+6EajCcpXLWSGf+ZXkOrWspDWDhXtEKas0v3UqWksqgY1rTj45krX4KihN+daXs
+pZl5WPlta5p06CX6Xm2SfzqkMw12/3ix1bpnnZ+kFeBNX7A+E9zzG6OZaN78GOpl
+9Ht/eZn9PqWdav852zr0zqkDK2H5IjdvNah+b1YVGdQGzwR4Nw+f13yEKnV+y66W
+djfq7zWp7m5w+hzfv+Ly8O7oet5Vvd8/wQvO7qzOZ2vjf9X8Tj8PnMb/nc/nKqRR
++ml4UEhOOwfCeJEEI109CMYSh91iAJqPjMyH6KjrPD7W25llZVcREYNCTg6htbQt
+M38wYoquCWP6tdKYlVIv14xTNUeUf4El/FunCf6csZkmv+9tfWx7t59wuKIa3saU
+tZs9M+3HFOZtz3OLg/Unoaj9BYazYqA78xBU9tZzrtmF/rQL9CGJt90o/oYnSfcS
+SL3haaw351LXWQ1XOsv1SmH3v6ymuxEpPPnEDmBELaTYsvvMIWJsmPZFFww++Kd7
+s/Jo0JFeUU7uNtI+gVosAIpVVuWfI/9tOIycz7I5Z7zjV+NR2OuZbYtW5F08KX4o
+2k/xuJIchcNFPtxPfw9dkDgscRbMckyFMrzuZ3IvrcGzk0J6iI5ytrv37bGpAXMz
+WK9mMMPebepNevmLjjo/QWoM968Sjv7ldlPS5AinHcXwsFv6dmmh8lJt7UOJWoKu
+lMD1cB2ksIGpMdv8iuqR42Rn/kn+17BhhUZcwDBaUXVdX6bKW7fxlUYbq+mlqIcf
+a9v8HF87M9ANbi9bq9onf9TD7nQ6Xf6vZci8TBPX+/GI0He6j31fTVQYW+NsQxvO
+J8xrx+e58CCLQNjxeIyPt+F+qk/QMiXw+LyxGVkV/XcGQT9X03jSDP6beJ5QG1JW
+9Q3qLv/YixWI7gPV9Mrhf2oRYTc/9KLFRhkE3SjKOTKuSSBKQ24fI+hEznamH71D
+66Hwez8/0et7AtTv9zvamv2OD5He6fMV4k+ePl6+qPfO5CdHtK+eCDZL5+4f5yrl
+gTcRFiq8fXbc5IaI5fbbc1KMM/2T0Mr7+Hwaco6FtXm0fmhCgTZRqY4pKiEIfmaz
+QwHNOOCrtMJ2VwsyMumt7xsOolGnizRev6lILH43qPcczQM7Gc5zRin80YvFt1Qm
+h/57Z0auR2h0fuX50MBO4XQ+26y5l6v4j902R66c0j3z2KHstKQ04J/h6LbuNQE4
+D6cu/lyfK69DxxX8wb8XaQkMUcJdo1LzqUGDAb3Kfn/A3P/JYc99MO9qv67+SxWb
+wYTyqKdWTd+1KbR/Rcn0Io5zI/QquX7FA1bxfMytjQ/X+l0fh0Pf+Hx97meH4fQL
+7/T8/sdTm9Tn8nELvedyhydLlPPTScINdXyLIq9wgIJr4fWPbp9ZhFh/56fdSgOG
+HDXg+gkXsN2Rddr4HQ5P3u+RhLzmSjhzoqY5EsPC4QvRlX9JXjB84rPV5USR66qa
+/kjw4156GJnzoXtydKJE53t6PHfZWO+3ujsfI6iAdshc7OFzGXiZB9PtItKodhYq
+nABkTKdcpu4+TOpf9h5piX5slsaBjkeTnj/Ba02ilboQfcDVigxrYn/iTH5ySWUW
+/lHtg78s5UZM8sErwhNe3N3w+6ZOMnU+5i86/xFNtqZfDdXTGy1H3PzGbdtZXYT+
+Ixx2vpwBYzbPVYHxKosM5rPiVmcTllI9nuoSfeh9ib4foFWauOpvdmhBDqpTpKTX
+u8EO2l2Z195G2RIV7TlKSxGWjR5sl/nALu1uzBeLd9zpSujzMTd1uTX9Qk/Q1S+r
+vaW6bm8qqPO4jb6Wx6XIkm321nrIF6Ae25d1+Dpv/P5G4NoLd2j6/EtENC3FeR5z
+oo7bA+tI8yEQRhiF0z1FlJXLD5ZbhNNWQm/j/IbzRfh8JtOFZU7ruShLvHXysW9S
+9V909tr9jn8/E/Hb5N/1NVNHnZu2HIUvJvHJiHd2ucmeI9PWUMnppmE65GQ5E9xV
+ZRlGEH0X85EvmHyEupkMrCC0oMv9RCq+/H8gcfpe00Hs/S+regT5p58cyYomh93v
+qvuw/A06BE/wzJESuYbN9pqYpoXqXFemW1NksHEJ2w+PYMJ27WJyD5FpaXB85VaW
+qMOhDfO8E3QdH8ybyKt/UgI8/tDGpFbyOlaVdIv1FXJhoLp8soAA4Djg6/KZ066N
+ZFYuS8WdjpSZGP4/Lw+1yaXlzNznc/k2uHe2uXP3uFuPcHx+Dm44utxldoO1uBPy
++jzOs14+MIgOjOHMVNqAbMd8fUedLlhJMCfMtm4uz01enLNKcMrtLlPIR37Yukh1
+YEMXYpm7eU4XU+j+Jj3pDyaXtXs+p1fWfTN/cy9/Oxs4umUXQ4uHh1kObtayDJ56
+/QMxiHobjHNKuKfMxsrYEwN+QVIyVjAwMDYuMjQ1AAA9IwJniiBLRkZDAAAXt0Ja
+aDQxQVkmU1lZtwytAACLf///////////////////+//////v//////////bv78//
+/+AXO133uwO2xB2UxIvbKXrCqCoURUBL2ytFI82AFdcOwMhVTHtk5rD3szEVNYD4
+aIQINCaMRoTaSn7SbSMJiYmEwieTEp+psqbMCp+VNPaFNpqbBNR7UmanlPUeKfqm
+j1PU0/VPU08o9Q9EeKHlPJtKbYqeTCYhN6U9T1NH6mp+lPyoGNTI/Knkyg1MggAg
+CaMEyQnqZoaaRtRtJpppppoDaTR6hpphGh6mmgHpMQBpkGTTEAAaAAAA00AZDag0
+ADIBkGgABqemiRNTI0k8aU0PRGRoAZlP0UAAAGgAAAyAADQaAAAaAAAAAAAAAAAA
+AaAAAAM0kgRBJ5MlPFP1Gj0jTTTUaekxNAbUGjTQMgaZANNAAAAaAADTQAAAAAAA
+ANAA0AAANADQ0QAAAAAAAAAaGgAAAAAAABoA0AAA0AAAAAAAAAAAAANAAAAAkSEI
+aTRpomp5DUxNNDTJPTKaep6T09Kemmo2JG0aTQ9ENogaaGhkABo0NHqaBoDTI0DC
+Gj0gNAMhoDQ9QMQNAGQAaDDwyMPIMlbG1vhRBTFo6JksSupgpAjPbY0ec02IGXjb
+eS+FBsh01+O4ZOaD+srUZCFaT4DRjVDLx7uKIsFtESIDUg1ZkhyCSYov05C00MtR
+BdNNa/AYPGOQZWcs+VegXOPrkushFbZ3mBoRD6WamClkpBaHZrUhUl02bIfRXX4w
+b3/9cW9nHDVxh2qFBxqgRKfmq7/Jc/tdJk05nVrGbckGVy2PnIy30CDhpWmqrSot
+K2bOnX0NbP1iy2cd0Na0ZmbRstm4MzMzbbMySTd35F7f+zPP8DC+NJLYcakkkkRd
+NZlupJt3OMFoDAD2g+N3FAMCydhIpoRHRQAdFI5nNg4ugEXHCYxkMyGCwtaJmial
+y0IMlpSYYM/weXNJAhFqS0GNmvaPEtYGjbvaucMdklOTmBX1vfVAkTYB1uXCSK64
+UNIixOqRKLuRCFtqIQtgwqaFrCkIYbbewErWABa+VGADWsJXJjfx5SJViLuwiGXq
+Ru6vCuwmU5CJiJz3UiBpmLv0r2wskxUhY4tzPVGQ9RMXJl65eLSNwZVwaSyGZ9Cm
+A3jztQUUpFeUryBTskW95iVwRMFrhBCwZBAFJBZvhMEMNoDJJlUoIhQkAkjbExp2
+YZio+ZYeAZUwmH1qUbdQixmxf0+61+aVgJ1hwxsO1yG3hFx4pfjc09ITVht0pG8u
+FtVFhPa1KE0gTRUSVXywkITucqk0Waz5Fs6qJpVHYdNrbYRFxnFsQGY1qmsTLjK6
+4QX5Rddo6krM/Bx9CqIAKq4CzVQYHrmIAd2EBhYmwVYwLvhzKIUrc2EirnGIvyuD
+O4YZDSwsVTA0BpVvUOjDErkCraBoSutcKwUSSLGhVvNYHLz3klgZD++wWsa/swLw
+gvNDY2De+sncOv8X2lq4HD95ZdwPuTIMXCwSbg4RrIqv+L0y6F17pqDecyQYPEj3
+iN/0BBeWZlJAyBMi5U3Q1zAlsK8IlDhaXGmvZrgISq5CfNjmUgxDeMggOKqxu4sI
+OrilS49Lkl1J3u3GjXTuH+rX+4ccyFAQnizCpPClcY77F59j63S6fr5vr+y99tuO
+7Ox7Wg/ljwhdyaK4xMmXczeJbx7x07htJNtC4xcQfAtvzeznLrN6MN/ILIBOI65I
+qIA2D5fHHj1XN4aN6TvOjWDaSbSWqxCSCvXUpzkNJAkWXAuTwF8k5uSJvQj/rVo0
+hAhEMEIYkCRGx9AX+byIuXWlLMbbVeliHNUL5AQYmNwLFu4SkmGD+UWtBMyVHQOQ
+ss0ggoVKSKOBUgnVS6ljt7WE1qXqJJ4QA1pEwYNLEaguEE1LtPNoVr5WzjbSbWPk
+V9OW3y9IneUDLoIV5pAkEFTEFGFVjeTFxtpzBBfGgycBxVCdz8eESBIzsamRchAa
+TQunQH8DHnpfod9QuAuRvc7JBlKUCYmCjMvynLcxIFohxCaYrDvGw4QbXZB7oWQ7
+hpoGlz23ayDfB8NrRRzdilsEQyQniu9ASLQg7RrGZnoTr1ai12IbCEUCGdFq03P5
+nBnRFAGmisQGcyykV9gKtcVMWLhCuVmXg86dndn7slUpRNSSEAU20oaWIm1maFTu
+E0DT4gTbg0nuhjtz3kNOz+i7sBm0bkXjxQWuLqlZEmp60ZTyRZJDUqKSEKg6hqcy
+ERxdU22CSNOO10RYUUiDVpKhPNdKTOIE1thp02sBNoNTFSht8WJtaBQ09qN3jd5r
+dOLX4IA5fevRyCCzDgRXfV4wzik4KROjmxmTMglBySlIMEzcXehnDXCRiZSlvwA2
+0YsIOROcm4UrIRFxJHctJH7OdN5u1aHVHb5UaLHpv48NgmFRE56KTSoaWunqm2st
+S0mrAdOiqcR12PWVbdVRJKcQ0DQuhwlAPcRtpxN3D4kbXJjToSYJIFw406G2CSaK
+jQMIJPZGlQmgyFhoCSzeGS1VSq5SKKQQxs5RqKUcVUNY57YUETb4mXzV84SPngKi
+nsce0mXByZq5BKUA9puHZWLNwQIYuDaJUNgG+E01E3pDYVNLKYQ0hsVesgV5gZY0
+htDsRdGtm0+iGnkN6+Ea9YJtUZNAkx2GgSoix12nTW0avTUfxR3oYcpvZ7IdtABE
+UhBcjG4qZtDZsS1JQHys243vhLaDTSvvTeBiJA2tmokqECTBcSOCAGkAxMKlVAva
+4IsLRaBBqhxDbcGtgdw03mFcLUaFuhtKuuEIEkUleJQwby/zwu9uvvZK4xTV+ECM
+a8lmzxKmqkBggYK1+xPdbmJclm6tSZhE/OSJtCEjs+unJIQkT9hCWgBJqGMS07Eh
+AJNmBiuVEVdTyjkIJkavuZmx2sJF13htgEZUCC23lZFOE6gWbM9WyYNJTM8yCQrb
+0Sx3OQvBML5cRATAQkSQkAJOAhoxpQkNi4ZiEVDbdtJAME0RXNDXGHA3M3Q0mm1o
+IEwbWpaM1DQCSMbGRCAu3iRIQiT6RlBpT1n3tfwvUXz3gIVlx3mEximY/kZW1kNG
+sgEJIrBisaEoGYPJ+1CQUYFBw+eGEHJQBpNHjErXUJY2iWHQ30hXwFBuMSxQ2lB5
+bg+/LX3euG6HsHUB1lFvBvaiaBrITVwkCTa1d0s9CHZCiDZjbWReKyrpPE2oSa7o
+LPrR4BJvys9ttjUpzETSSMxh8vsr9dXTwKBtK+1xCTGDQmNIaE29HmHdS5GSxpya
+MismcAUSEgSxHBrKtgsZzduG7vHZn16l3kFkVITtENIzS2JsiBwFTDlhgexsjBHv
+5HXOYxHBzoSDCcPZ0ctvkY9aS5XpoQuFYkGJgCsqjJZeUMNUEpDSbKcnUc1PifIA
+CbR2UoXawBlspkEBr9HBfvUi/MUakZVOf1WKYrqSaIXce62JOyhJLq3qJBloTA0F
+VbILEtM+heFmNRCFt70GJrExVJri0ArYbCRbADSGDBpBXxxb/6fo+s3C7uaL7RjM
+LV2IQBNrAJrKFeJwTsPnxbAsemirUx2lk1kaxschzdK4TQNJN5wQnolIFg401OZ4
+2na11LnT3lR+1k1TMJhiAjXMk0F1ooHnYlt9LKfJ3ZIOmeY+2l9bUQHWFNGyEyfj
+EAcu3kpGLq0Ez7XOS+EpAASRQTAYMATfVQibHLTT30zG732+pNe9za1JNt8sNJYn
+RjWuJ6jL5ILV0rcd9vT7X9fObvcXitpvJ2XBJE+PhX2HaTkyWeF9pwnlQNrTe9hV
+tzhA+ihZrDrHNmLcQjZbnv/IMubqq8egxY80t5n6vZ6U5TR6U9uZJvai1xtqAyCR
+NWkW52m00rDTEuO6BA4q2RHDWwbETF55rRsWLIgNW9qJCyMHPbTM/dMBmWMQSMxz
+4M2pRzt47SICxA327UqSCEERqMFybmYi3nUxePtLgHYplqRiw4ynMbXd/kiQ0LE0
+PKJSSCXA42ymziCpAxNWflzpzQdJZusahRFr6t6m+4p273/Taj7k+hZyNgBAgXAY
+8F7pTts6orLb8IA6o4TOwkwQYmKvKu9VwMrE7+GUhVIAgY9a8DyQMiDBkEAwh7S1
+KgCBfao8DK1CwSS8Z3WjL5MEgt93z2koUQCD/YxMBppiCMp7SDVSmkkIHptfGpeh
+t+M13Ccv1tavIASFiaQl6rBz3K4N3DSGwNkCibrvEAC0fQirOWnc4NVbcLKpFG1l
+NQXF/eqdT79wq1Mvlap3QSCLhcD2D3fCkKVWid4aSjtp9FOX1Uaf7P9eT93zd9Sv
+mj2yNLRUGzyI/0oONNSzmmkvJ5Cq2X2CdldIWMGZO57RJ8oyATAWTQmRmNkfh0Sx
+uuR/J9oUsomVy1AEntc0dlPivkqBkBqrxU3j5PnWkaI3ZRGc0gg9spCQEISh4xEU
+pMhVrnmDQLfLP8Ouqpx917MAw7hkjQk6BJFTAbXDsz3LSHIxo/gB8qrA1vbvdZZh
+LtR0frJdfdppX8nAQX/TAxOQ8+H6yw8a9i7/zJEfSYIhop59N/fhcWW2F14cj2Xc
+fyHaZ04lTO4uPnly91jwuFPaREuZVp8AxImIhlkxkAN61tWdWG7tEbaCgszh6VIz
+ThFnHo2Vi8SQXPrXCN7J9Tc9ZYiAYqoThV/u6SYsea5aZL8deOvKBQCgZZuIxX1z
+4EnfcqG176vY4VqMBIC4pMJz0WcHJYqN+j7BiwGoMBwExrIdTB7q4XIFLotcIpS0
+1MqyVsesvoQq7WObmGQXdMliMirSLcDuSx8Qy+4pIBgGDIyMp1qbonnGdcHYvU8S
+O0A8s/iua5oFdNZTWvbVI4FUH9sKcLiB3/fIAF+sB4n8q6L+UCfmbPcAo/crQ6b3
+HqhDBMY9J0q/jdz9GNYZ/1fbXdkUqAQKFePhtzJDRBZba27+LPQNMCcrHMq06F1T
+4QmLmkHt7LxB2pAczUO+T2O9bHEw/HWw+dYf2MoRDUw=
+`
diff --git a/third_party/gofrontend/libgo/go/compress/bzip2/huffman.go b/third_party/gofrontend/libgo/go/compress/bzip2/huffman.go
new file mode 100644
index 0000000..75a6223
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/bzip2/huffman.go
@@ -0,0 +1,251 @@
+// 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.
+
+package bzip2
+
+import "sort"
+
+// A huffmanTree is a binary tree which is navigated, bit-by-bit to reach a
+// symbol.
+type huffmanTree struct {
+	// nodes contains all the non-leaf nodes in the tree. nodes[0] is the
+	// root of the tree and nextNode contains the index of the next element
+	// of nodes to use when the tree is being constructed.
+	nodes    []huffmanNode
+	nextNode int
+}
+
+// A huffmanNode is a node in the tree. left and right contain indexes into the
+// nodes slice of the tree. If left or right is invalidNodeValue then the child
+// is a left node and its value is in leftValue/rightValue.
+//
+// The symbols are uint16s because bzip2 encodes not only MTF indexes in the
+// tree, but also two magic values for run-length encoding and an EOF symbol.
+// Thus there are more than 256 possible symbols.
+type huffmanNode struct {
+	left, right           uint16
+	leftValue, rightValue uint16
+}
+
+// invalidNodeValue is an invalid index which marks a leaf node in the tree.
+const invalidNodeValue = 0xffff
+
+// Decode reads bits from the given bitReader and navigates the tree until a
+// symbol is found.
+func (t *huffmanTree) Decode(br *bitReader) (v uint16) {
+	nodeIndex := uint16(0) // node 0 is the root of the tree.
+
+	for {
+		node := &t.nodes[nodeIndex]
+		bit, ok := br.TryReadBit()
+		if !ok && br.ReadBit() {
+			bit = 1
+		}
+		// bzip2 encodes left as a true bit.
+		if bit != 0 {
+			// left
+			if node.left == invalidNodeValue {
+				return node.leftValue
+			}
+			nodeIndex = node.left
+		} else {
+			// right
+			if node.right == invalidNodeValue {
+				return node.rightValue
+			}
+			nodeIndex = node.right
+		}
+	}
+}
+
+// newHuffmanTree builds a Huffman tree from a slice containing the code
+// lengths of each symbol. The maximum code length is 32 bits.
+func newHuffmanTree(lengths []uint8) (huffmanTree, error) {
+	// There are many possible trees that assign the same code length to
+	// each symbol (consider reflecting a tree down the middle, for
+	// example). Since the code length assignments determine the
+	// efficiency of the tree, each of these trees is equally good. In
+	// order to minimize the amount of information needed to build a tree
+	// bzip2 uses a canonical tree so that it can be reconstructed given
+	// only the code length assignments.
+
+	if len(lengths) < 2 {
+		panic("newHuffmanTree: too few symbols")
+	}
+
+	var t huffmanTree
+
+	// First we sort the code length assignments by ascending code length,
+	// using the symbol value to break ties.
+	pairs := huffmanSymbolLengthPairs(make([]huffmanSymbolLengthPair, len(lengths)))
+	for i, length := range lengths {
+		pairs[i].value = uint16(i)
+		pairs[i].length = length
+	}
+
+	sort.Sort(pairs)
+
+	// Now we assign codes to the symbols, starting with the longest code.
+	// We keep the codes packed into a uint32, at the most-significant end.
+	// So branches are taken from the MSB downwards. This makes it easy to
+	// sort them later.
+	code := uint32(0)
+	length := uint8(32)
+
+	codes := huffmanCodes(make([]huffmanCode, len(lengths)))
+	for i := len(pairs) - 1; i >= 0; i-- {
+		if length > pairs[i].length {
+			// If the code length decreases we shift in order to
+			// zero any bits beyond the end of the code.
+			length >>= 32 - pairs[i].length
+			length <<= 32 - pairs[i].length
+			length = pairs[i].length
+		}
+		codes[i].code = code
+		codes[i].codeLen = length
+		codes[i].value = pairs[i].value
+		// We need to 'increment' the code, which means treating |code|
+		// like a |length| bit number.
+		code += 1 << (32 - length)
+	}
+
+	// Now we can sort by the code so that the left half of each branch are
+	// grouped together, recursively.
+	sort.Sort(codes)
+
+	t.nodes = make([]huffmanNode, len(codes))
+	_, err := buildHuffmanNode(&t, codes, 0)
+	return t, err
+}
+
+// huffmanSymbolLengthPair contains a symbol and its code length.
+type huffmanSymbolLengthPair struct {
+	value  uint16
+	length uint8
+}
+
+// huffmanSymbolLengthPair is used to provide an interface for sorting.
+type huffmanSymbolLengthPairs []huffmanSymbolLengthPair
+
+func (h huffmanSymbolLengthPairs) Len() int {
+	return len(h)
+}
+
+func (h huffmanSymbolLengthPairs) Less(i, j int) bool {
+	if h[i].length < h[j].length {
+		return true
+	}
+	if h[i].length > h[j].length {
+		return false
+	}
+	if h[i].value < h[j].value {
+		return true
+	}
+	return false
+}
+
+func (h huffmanSymbolLengthPairs) Swap(i, j int) {
+	h[i], h[j] = h[j], h[i]
+}
+
+// huffmanCode contains a symbol, its code and code length.
+type huffmanCode struct {
+	code    uint32
+	codeLen uint8
+	value   uint16
+}
+
+// huffmanCodes is used to provide an interface for sorting.
+type huffmanCodes []huffmanCode
+
+func (n huffmanCodes) Len() int {
+	return len(n)
+}
+
+func (n huffmanCodes) Less(i, j int) bool {
+	return n[i].code < n[j].code
+}
+
+func (n huffmanCodes) Swap(i, j int) {
+	n[i], n[j] = n[j], n[i]
+}
+
+// buildHuffmanNode takes a slice of sorted huffmanCodes and builds a node in
+// the Huffman tree at the given level. It returns the index of the newly
+// constructed node.
+func buildHuffmanNode(t *huffmanTree, codes []huffmanCode, level uint32) (nodeIndex uint16, err error) {
+	test := uint32(1) << (31 - level)
+
+	// We have to search the list of codes to find the divide between the left and right sides.
+	firstRightIndex := len(codes)
+	for i, code := range codes {
+		if code.code&test != 0 {
+			firstRightIndex = i
+			break
+		}
+	}
+
+	left := codes[:firstRightIndex]
+	right := codes[firstRightIndex:]
+
+	if len(left) == 0 || len(right) == 0 {
+		// There is a superfluous level in the Huffman tree indicating
+		// a bug in the encoder. However, this bug has been observed in
+		// the wild so we handle it.
+
+		// If this function was called recursively then we know that
+		// len(codes) >= 2 because, otherwise, we would have hit the
+		// "leaf node" case, below, and not recursed.
+		//
+		// However, for the initial call it's possible that len(codes)
+		// is zero or one. Both cases are invalid because a zero length
+		// tree cannot encode anything and a length-1 tree can only
+		// encode EOF and so is superfluous. We reject both.
+		if len(codes) < 2 {
+			return 0, StructuralError("empty Huffman tree")
+		}
+
+		// In this case the recursion doesn't always reduce the length
+		// of codes so we need to ensure termination via another
+		// mechanism.
+		if level == 31 {
+			// Since len(codes) >= 2 the only way that the values
+			// can match at all 32 bits is if they are equal, which
+			// is invalid. This ensures that we never enter
+			// infinite recursion.
+			return 0, StructuralError("equal symbols in Huffman tree")
+		}
+
+		if len(left) == 0 {
+			return buildHuffmanNode(t, right, level+1)
+		}
+		return buildHuffmanNode(t, left, level+1)
+	}
+
+	nodeIndex = uint16(t.nextNode)
+	node := &t.nodes[t.nextNode]
+	t.nextNode++
+
+	if len(left) == 1 {
+		// leaf node
+		node.left = invalidNodeValue
+		node.leftValue = left[0].value
+	} else {
+		node.left, err = buildHuffmanNode(t, left, level+1)
+	}
+
+	if err != nil {
+		return
+	}
+
+	if len(right) == 1 {
+		// leaf node
+		node.right = invalidNodeValue
+		node.rightValue = right[0].value
+	} else {
+		node.right, err = buildHuffmanNode(t, right, level+1)
+	}
+
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/compress/bzip2/move_to_front.go b/third_party/gofrontend/libgo/go/compress/bzip2/move_to_front.go
new file mode 100644
index 0000000..b7e75a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/bzip2/move_to_front.go
@@ -0,0 +1,98 @@
+// 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.
+
+package bzip2
+
+// moveToFrontDecoder implements a move-to-front list. Such a list is an
+// efficient way to transform a string with repeating elements into one with
+// many small valued numbers, which is suitable for entropy encoding. It works
+// by starting with an initial list of symbols and references symbols by their
+// index into that list. When a symbol is referenced, it's moved to the front
+// of the list. Thus, a repeated symbol ends up being encoded with many zeros,
+// as the symbol will be at the front of the list after the first access.
+type moveToFrontDecoder struct {
+	// Rather than actually keep the list in memory, the symbols are stored
+	// as a circular, double linked list with the symbol indexed by head
+	// at the front of the list.
+	symbols [256]byte
+	next    [256]uint8
+	prev    [256]uint8
+	head    uint8
+	len     int
+}
+
+// newMTFDecoder creates a move-to-front decoder with an explicit initial list
+// of symbols.
+func newMTFDecoder(symbols []byte) *moveToFrontDecoder {
+	if len(symbols) > 256 {
+		panic("too many symbols")
+	}
+
+	m := new(moveToFrontDecoder)
+	copy(m.symbols[:], symbols)
+	m.len = len(symbols)
+	m.threadLinkedList()
+	return m
+}
+
+// newMTFDecoderWithRange creates a move-to-front decoder with an initial
+// symbol list of 0...n-1.
+func newMTFDecoderWithRange(n int) *moveToFrontDecoder {
+	if n > 256 {
+		panic("newMTFDecoderWithRange: cannot have > 256 symbols")
+	}
+
+	m := new(moveToFrontDecoder)
+	for i := 0; i < n; i++ {
+		m.symbols[byte(i)] = byte(i)
+	}
+	m.len = n
+	m.threadLinkedList()
+	return m
+}
+
+// threadLinkedList creates the initial linked-list pointers.
+func (m *moveToFrontDecoder) threadLinkedList() {
+	if m.len == 0 {
+		return
+	}
+
+	m.prev[0] = uint8(m.len - 1)
+
+	for i := byte(0); int(i) < m.len-1; i++ {
+		m.next[i] = uint8(i + 1)
+		m.prev[i+1] = uint8(i)
+	}
+
+	m.next[m.len-1] = 0
+}
+
+func (m *moveToFrontDecoder) Decode(n int) (b byte) {
+	// Most of the time, n will be zero so it's worth dealing with this
+	// simple case.
+	if n == 0 {
+		return m.symbols[m.head]
+	}
+
+	i := m.head
+	for j := 0; j < n; j++ {
+		i = m.next[i]
+	}
+	b = m.symbols[i]
+
+	m.next[m.prev[i]] = m.next[i]
+	m.prev[m.next[i]] = m.prev[i]
+	m.next[i] = m.head
+	m.prev[i] = m.prev[m.head]
+	m.next[m.prev[m.head]] = i
+	m.prev[m.head] = i
+	m.head = i
+
+	return
+}
+
+// First returns the symbol at the front of the list.
+func (m *moveToFrontDecoder) First() byte {
+	return m.symbols[m.head]
+}
diff --git a/third_party/gofrontend/libgo/go/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 b/third_party/gofrontend/libgo/go/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2
new file mode 100644
index 0000000..0bd61a6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/compress/bzip2/testdata/e.txt.bz2 b/third_party/gofrontend/libgo/go/compress/bzip2/testdata/e.txt.bz2
new file mode 100644
index 0000000..65bf3b4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/bzip2/testdata/e.txt.bz2
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/compress/flate/copy.go b/third_party/gofrontend/libgo/go/compress/flate/copy.go
new file mode 100644
index 0000000..a3200a8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/copy.go
@@ -0,0 +1,32 @@
+// 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 flate
+
+// forwardCopy is like the built-in copy function except that it always goes
+// forward from the start, even if the dst and src overlap.
+// It is equivalent to:
+//   for i := 0; i < n; i++ {
+//     mem[dst+i] = mem[src+i]
+//   }
+func forwardCopy(mem []byte, dst, src, n int) {
+	if dst <= src {
+		copy(mem[dst:dst+n], mem[src:src+n])
+		return
+	}
+	for {
+		if dst >= src+n {
+			copy(mem[dst:dst+n], mem[src:src+n])
+			return
+		}
+		// There is some forward overlap.  The destination
+		// will be filled with a repeated pattern of mem[src:src+k].
+		// We copy one instance of the pattern here, then repeat.
+		// Each time around this loop k will double.
+		k := dst - src
+		copy(mem[dst:dst+k], mem[src:src+k])
+		n -= k
+		dst += k
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/copy_test.go b/third_party/gofrontend/libgo/go/compress/flate/copy_test.go
new file mode 100644
index 0000000..2011b15
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/copy_test.go
@@ -0,0 +1,54 @@
+// 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 flate
+
+import (
+	"testing"
+)
+
+func TestForwardCopy(t *testing.T) {
+	testCases := []struct {
+		dst0, dst1 int
+		src0, src1 int
+		want       string
+	}{
+		{0, 9, 0, 9, "012345678"},
+		{0, 5, 4, 9, "45678"},
+		{4, 9, 0, 5, "01230"},
+		{1, 6, 3, 8, "34567"},
+		{3, 8, 1, 6, "12121"},
+		{0, 9, 3, 6, "345"},
+		{3, 6, 0, 9, "012"},
+		{1, 6, 0, 9, "00000"},
+		{0, 4, 7, 8, "7"},
+		{0, 1, 6, 8, "6"},
+		{4, 4, 6, 9, ""},
+		{2, 8, 6, 6, ""},
+		{0, 0, 0, 0, ""},
+	}
+	for _, tc := range testCases {
+		b := []byte("0123456789")
+		n := tc.dst1 - tc.dst0
+		if tc.src1-tc.src0 < n {
+			n = tc.src1 - tc.src0
+		}
+		forwardCopy(b, tc.dst0, tc.src0, n)
+		got := string(b[tc.dst0 : tc.dst0+n])
+		if got != tc.want {
+			t.Errorf("dst=b[%d:%d], src=b[%d:%d]: got %q, want %q",
+				tc.dst0, tc.dst1, tc.src0, tc.src1, got, tc.want)
+		}
+		// Check that the bytes outside of dst[:n] were not modified.
+		for i, x := range b {
+			if i >= tc.dst0 && i < tc.dst0+n {
+				continue
+			}
+			if int(x) != '0'+i {
+				t.Errorf("dst=b[%d:%d], src=b[%d:%d]: copy overrun at b[%d]: got '%c', want '%c'",
+					tc.dst0, tc.dst1, tc.src0, tc.src1, i, x, '0'+i)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/deflate.go b/third_party/gofrontend/libgo/go/compress/flate/deflate.go
new file mode 100644
index 0000000..8c79df0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/deflate.go
@@ -0,0 +1,571 @@
+// 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 flate
+
+import (
+	"fmt"
+	"io"
+	"math"
+)
+
+const (
+	NoCompression      = 0
+	BestSpeed          = 1
+	fastCompression    = 3
+	BestCompression    = 9
+	DefaultCompression = -1
+	logWindowSize      = 15
+	windowSize         = 1 << logWindowSize
+	windowMask         = windowSize - 1
+	logMaxOffsetSize   = 15  // Standard DEFLATE
+	minMatchLength     = 3   // The smallest match that the compressor looks for
+	maxMatchLength     = 258 // The longest match for the compressor
+	minOffsetSize      = 1   // The shortest offset that makes any sense
+
+	// The maximum number of tokens we put into a single flat block, just too
+	// stop things from getting too large.
+	maxFlateBlockTokens = 1 << 14
+	maxStoreBlockSize   = 65535
+	hashBits            = 17
+	hashSize            = 1 << hashBits
+	hashMask            = (1 << hashBits) - 1
+	hashShift           = (hashBits + minMatchLength - 1) / minMatchLength
+	maxHashOffset       = 1 << 24
+
+	skipNever = math.MaxInt32
+)
+
+type compressionLevel struct {
+	good, lazy, nice, chain, fastSkipHashing int
+}
+
+var levels = []compressionLevel{
+	{}, // 0
+	// For levels 1-3 we don't bother trying with lazy matches
+	{3, 0, 8, 4, 4},
+	{3, 0, 16, 8, 5},
+	{3, 0, 32, 32, 6},
+	// Levels 4-9 use increasingly more lazy matching
+	// and increasingly stringent conditions for "good enough".
+	{4, 4, 16, 16, skipNever},
+	{8, 16, 32, 32, skipNever},
+	{8, 16, 128, 128, skipNever},
+	{8, 32, 128, 256, skipNever},
+	{32, 128, 258, 1024, skipNever},
+	{32, 258, 258, 4096, skipNever},
+}
+
+type compressor struct {
+	compressionLevel
+
+	w *huffmanBitWriter
+
+	// compression algorithm
+	fill func(*compressor, []byte) int // copy data to window
+	step func(*compressor)             // process window
+	sync bool                          // requesting flush
+
+	// Input hash chains
+	// hashHead[hashValue] contains the largest inputIndex with the specified hash value
+	// If hashHead[hashValue] is within the current window, then
+	// hashPrev[hashHead[hashValue] & windowMask] contains the previous index
+	// with the same hash value.
+	chainHead  int
+	hashHead   []int
+	hashPrev   []int
+	hashOffset int
+
+	// input window: unprocessed data is window[index:windowEnd]
+	index         int
+	window        []byte
+	windowEnd     int
+	blockStart    int  // window index where current tokens start
+	byteAvailable bool // if true, still need to process window[index-1].
+
+	// queued output tokens
+	tokens []token
+
+	// deflate state
+	length         int
+	offset         int
+	hash           int
+	maxInsertIndex int
+	err            error
+}
+
+func (d *compressor) fillDeflate(b []byte) int {
+	if d.index >= 2*windowSize-(minMatchLength+maxMatchLength) {
+		// shift the window by windowSize
+		copy(d.window, d.window[windowSize:2*windowSize])
+		d.index -= windowSize
+		d.windowEnd -= windowSize
+		if d.blockStart >= windowSize {
+			d.blockStart -= windowSize
+		} else {
+			d.blockStart = math.MaxInt32
+		}
+		d.hashOffset += windowSize
+		if d.hashOffset > maxHashOffset {
+			delta := d.hashOffset - 1
+			d.hashOffset -= delta
+			d.chainHead -= delta
+			for i, v := range d.hashPrev {
+				if v > delta {
+					d.hashPrev[i] -= delta
+				} else {
+					d.hashPrev[i] = 0
+				}
+			}
+			for i, v := range d.hashHead {
+				if v > delta {
+					d.hashHead[i] -= delta
+				} else {
+					d.hashHead[i] = 0
+				}
+			}
+		}
+	}
+	n := copy(d.window[d.windowEnd:], b)
+	d.windowEnd += n
+	return n
+}
+
+func (d *compressor) writeBlock(tokens []token, index int, eof bool) error {
+	if index > 0 || eof {
+		var window []byte
+		if d.blockStart <= index {
+			window = d.window[d.blockStart:index]
+		}
+		d.blockStart = index
+		d.w.writeBlock(tokens, eof, window)
+		return d.w.err
+	}
+	return nil
+}
+
+// Try to find a match starting at index whose length is greater than prevSize.
+// We only look at chainCount possibilities before giving up.
+func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) {
+	minMatchLook := maxMatchLength
+	if lookahead < minMatchLook {
+		minMatchLook = lookahead
+	}
+
+	win := d.window[0 : pos+minMatchLook]
+
+	// We quit when we get a match that's at least nice long
+	nice := len(win) - pos
+	if d.nice < nice {
+		nice = d.nice
+	}
+
+	// If we've got a match that's good enough, only look in 1/4 the chain.
+	tries := d.chain
+	length = prevLength
+	if length >= d.good {
+		tries >>= 2
+	}
+
+	w0 := win[pos]
+	w1 := win[pos+1]
+	wEnd := win[pos+length]
+	minIndex := pos - windowSize
+
+	for i := prevHead; tries > 0; tries-- {
+		if w0 == win[i] && w1 == win[i+1] && wEnd == win[i+length] {
+			// The hash function ensures that if win[i] and win[i+1] match, win[i+2] matches
+
+			n := 3
+			for pos+n < len(win) && win[i+n] == win[pos+n] {
+				n++
+			}
+			if n > length && (n > 3 || pos-i <= 4096) {
+				length = n
+				offset = pos - i
+				ok = true
+				if n >= nice {
+					// The match is good enough that we don't try to find a better one.
+					break
+				}
+				wEnd = win[pos+n]
+			}
+		}
+		if i == minIndex {
+			// hashPrev[i & windowMask] has already been overwritten, so stop now.
+			break
+		}
+		if i = d.hashPrev[i&windowMask] - d.hashOffset; i < minIndex || i < 0 {
+			break
+		}
+	}
+	return
+}
+
+func (d *compressor) writeStoredBlock(buf []byte) error {
+	if d.w.writeStoredHeader(len(buf), false); d.w.err != nil {
+		return d.w.err
+	}
+	d.w.writeBytes(buf)
+	return d.w.err
+}
+
+func (d *compressor) initDeflate() {
+	d.hashHead = make([]int, hashSize)
+	d.hashPrev = make([]int, windowSize)
+	d.window = make([]byte, 2*windowSize)
+	d.hashOffset = 1
+	d.tokens = make([]token, 0, maxFlateBlockTokens+1)
+	d.length = minMatchLength - 1
+	d.offset = 0
+	d.byteAvailable = false
+	d.index = 0
+	d.hash = 0
+	d.chainHead = -1
+}
+
+func (d *compressor) deflate() {
+	if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync {
+		return
+	}
+
+	d.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
+	if d.index < d.maxInsertIndex {
+		d.hash = int(d.window[d.index])<<hashShift + int(d.window[d.index+1])
+	}
+
+Loop:
+	for {
+		if d.index > d.windowEnd {
+			panic("index > windowEnd")
+		}
+		lookahead := d.windowEnd - d.index
+		if lookahead < minMatchLength+maxMatchLength {
+			if !d.sync {
+				break Loop
+			}
+			if d.index > d.windowEnd {
+				panic("index > windowEnd")
+			}
+			if lookahead == 0 {
+				// Flush current output block if any.
+				if d.byteAvailable {
+					// There is still one pending token that needs to be flushed
+					d.tokens = append(d.tokens, literalToken(uint32(d.window[d.index-1])))
+					d.byteAvailable = false
+				}
+				if len(d.tokens) > 0 {
+					if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+						return
+					}
+					d.tokens = d.tokens[:0]
+				}
+				break Loop
+			}
+		}
+		if d.index < d.maxInsertIndex {
+			// Update the hash
+			d.hash = (d.hash<<hashShift + int(d.window[d.index+2])) & hashMask
+			d.chainHead = d.hashHead[d.hash]
+			d.hashPrev[d.index&windowMask] = d.chainHead
+			d.hashHead[d.hash] = d.index + d.hashOffset
+		}
+		prevLength := d.length
+		prevOffset := d.offset
+		d.length = minMatchLength - 1
+		d.offset = 0
+		minIndex := d.index - windowSize
+		if minIndex < 0 {
+			minIndex = 0
+		}
+
+		if d.chainHead-d.hashOffset >= minIndex &&
+			(d.fastSkipHashing != skipNever && lookahead > minMatchLength-1 ||
+				d.fastSkipHashing == skipNever && lookahead > prevLength && prevLength < d.lazy) {
+			if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
+				d.length = newLength
+				d.offset = newOffset
+			}
+		}
+		if d.fastSkipHashing != skipNever && d.length >= minMatchLength ||
+			d.fastSkipHashing == skipNever && prevLength >= minMatchLength && d.length <= prevLength {
+			// There was a match at the previous step, and the current match is
+			// not better. Output the previous match.
+			if d.fastSkipHashing != skipNever {
+				d.tokens = append(d.tokens, matchToken(uint32(d.length-minMatchLength), uint32(d.offset-minOffsetSize)))
+			} else {
+				d.tokens = append(d.tokens, matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize)))
+			}
+			// Insert in the hash table all strings up to the end of the match.
+			// index and index-1 are already inserted. If there is not enough
+			// lookahead, the last two strings are not inserted into the hash
+			// table.
+			if d.length <= d.fastSkipHashing {
+				var newIndex int
+				if d.fastSkipHashing != skipNever {
+					newIndex = d.index + d.length
+				} else {
+					newIndex = d.index + prevLength - 1
+				}
+				for d.index++; d.index < newIndex; d.index++ {
+					if d.index < d.maxInsertIndex {
+						d.hash = (d.hash<<hashShift + int(d.window[d.index+2])) & hashMask
+						// Get previous value with the same hash.
+						// Our chain should point to the previous value.
+						d.hashPrev[d.index&windowMask] = d.hashHead[d.hash]
+						// Set the head of the hash chain to us.
+						d.hashHead[d.hash] = d.index + d.hashOffset
+					}
+				}
+				if d.fastSkipHashing == skipNever {
+					d.byteAvailable = false
+					d.length = minMatchLength - 1
+				}
+			} else {
+				// For matches this long, we don't bother inserting each individual
+				// item into the table.
+				d.index += d.length
+				if d.index < d.maxInsertIndex {
+					d.hash = (int(d.window[d.index])<<hashShift + int(d.window[d.index+1]))
+				}
+			}
+			if len(d.tokens) == maxFlateBlockTokens {
+				// The block includes the current character
+				if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+					return
+				}
+				d.tokens = d.tokens[:0]
+			}
+		} else {
+			if d.fastSkipHashing != skipNever || d.byteAvailable {
+				i := d.index - 1
+				if d.fastSkipHashing != skipNever {
+					i = d.index
+				}
+				d.tokens = append(d.tokens, literalToken(uint32(d.window[i])))
+				if len(d.tokens) == maxFlateBlockTokens {
+					if d.err = d.writeBlock(d.tokens, i+1, false); d.err != nil {
+						return
+					}
+					d.tokens = d.tokens[:0]
+				}
+			}
+			d.index++
+			if d.fastSkipHashing == skipNever {
+				d.byteAvailable = true
+			}
+		}
+	}
+}
+
+func (d *compressor) fillStore(b []byte) int {
+	n := copy(d.window[d.windowEnd:], b)
+	d.windowEnd += n
+	return n
+}
+
+func (d *compressor) store() {
+	if d.windowEnd > 0 {
+		d.err = d.writeStoredBlock(d.window[:d.windowEnd])
+	}
+	d.windowEnd = 0
+}
+
+func (d *compressor) write(b []byte) (n int, err error) {
+	n = len(b)
+	b = b[d.fill(d, b):]
+	for len(b) > 0 {
+		d.step(d)
+		b = b[d.fill(d, b):]
+	}
+	return n, d.err
+}
+
+func (d *compressor) syncFlush() error {
+	d.sync = true
+	d.step(d)
+	if d.err == nil {
+		d.w.writeStoredHeader(0, false)
+		d.w.flush()
+		d.err = d.w.err
+	}
+	d.sync = false
+	return d.err
+}
+
+func (d *compressor) init(w io.Writer, level int) (err error) {
+	d.w = newHuffmanBitWriter(w)
+
+	switch {
+	case level == NoCompression:
+		d.window = make([]byte, maxStoreBlockSize)
+		d.fill = (*compressor).fillStore
+		d.step = (*compressor).store
+	case level == DefaultCompression:
+		level = 6
+		fallthrough
+	case 1 <= level && level <= 9:
+		d.compressionLevel = levels[level]
+		d.initDeflate()
+		d.fill = (*compressor).fillDeflate
+		d.step = (*compressor).deflate
+	default:
+		return fmt.Errorf("flate: invalid compression level %d: want value in range [-1, 9]", level)
+	}
+	return nil
+}
+
+var zeroes [32]int
+var bzeroes [256]byte
+
+func (d *compressor) reset(w io.Writer) {
+	d.w.reset(w)
+	d.sync = false
+	d.err = nil
+	switch d.compressionLevel.chain {
+	case 0:
+		// level was NoCompression.
+		for i := range d.window {
+			d.window[i] = 0
+		}
+		d.windowEnd = 0
+	default:
+		d.chainHead = -1
+		for s := d.hashHead; len(s) > 0; {
+			n := copy(s, zeroes[:])
+			s = s[n:]
+		}
+		for s := d.hashPrev; len(s) > 0; s = s[len(zeroes):] {
+			copy(s, zeroes[:])
+		}
+		d.hashOffset = 1
+
+		d.index, d.windowEnd = 0, 0
+		for s := d.window; len(s) > 0; {
+			n := copy(s, bzeroes[:])
+			s = s[n:]
+		}
+		d.blockStart, d.byteAvailable = 0, false
+
+		d.tokens = d.tokens[:maxFlateBlockTokens+1]
+		for i := 0; i <= maxFlateBlockTokens; i++ {
+			d.tokens[i] = 0
+		}
+		d.tokens = d.tokens[:0]
+		d.length = minMatchLength - 1
+		d.offset = 0
+		d.hash = 0
+		d.maxInsertIndex = 0
+	}
+}
+
+func (d *compressor) close() error {
+	d.sync = true
+	d.step(d)
+	if d.err != nil {
+		return d.err
+	}
+	if d.w.writeStoredHeader(0, true); d.w.err != nil {
+		return d.w.err
+	}
+	d.w.flush()
+	return d.w.err
+}
+
+// NewWriter returns a new Writer compressing data at the given level.
+// Following zlib, levels range from 1 (BestSpeed) to 9 (BestCompression);
+// higher levels typically run slower but compress more. Level 0
+// (NoCompression) does not attempt any compression; it only adds the
+// necessary DEFLATE framing. Level -1 (DefaultCompression) uses the default
+// compression level.
+//
+// If level is in the range [-1, 9] then the error returned will be nil.
+// Otherwise the error returned will be non-nil.
+func NewWriter(w io.Writer, level int) (*Writer, error) {
+	var dw Writer
+	if err := dw.d.init(w, level); err != nil {
+		return nil, err
+	}
+	return &dw, nil
+}
+
+// NewWriterDict is like NewWriter but initializes the new
+// Writer with a preset dictionary.  The returned Writer behaves
+// as if the dictionary had been written to it without producing
+// any compressed output.  The compressed data written to w
+// can only be decompressed by a Reader initialized with the
+// same dictionary.
+func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) {
+	dw := &dictWriter{w, false}
+	zw, err := NewWriter(dw, level)
+	if err != nil {
+		return nil, err
+	}
+	zw.Write(dict)
+	zw.Flush()
+	dw.enabled = true
+	zw.dict = append(zw.dict, dict...) // duplicate dictionary for Reset method.
+	return zw, err
+}
+
+type dictWriter struct {
+	w       io.Writer
+	enabled bool
+}
+
+func (w *dictWriter) Write(b []byte) (n int, err error) {
+	if w.enabled {
+		return w.w.Write(b)
+	}
+	return len(b), nil
+}
+
+// A Writer takes data written to it and writes the compressed
+// form of that data to an underlying writer (see NewWriter).
+type Writer struct {
+	d    compressor
+	dict []byte
+}
+
+// Write writes data to w, which will eventually write the
+// compressed form of data to its underlying writer.
+func (w *Writer) Write(data []byte) (n int, err error) {
+	return w.d.write(data)
+}
+
+// Flush flushes any pending compressed data to the underlying writer.
+// It is useful mainly in compressed network protocols, to ensure that
+// a remote reader has enough data to reconstruct a packet.
+// Flush does not return until the data has been written.
+// If the underlying writer returns an error, Flush returns that error.
+//
+// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
+func (w *Writer) Flush() error {
+	// For more about flushing:
+	// http://www.bolet.org/~pornin/deflate-flush.html
+	return w.d.syncFlush()
+}
+
+// Close flushes and closes the writer.
+func (w *Writer) Close() error {
+	return w.d.close()
+}
+
+// Reset discards the writer's state and makes it equivalent to
+// the result of NewWriter or NewWriterDict called with dst
+// and w's level and dictionary.
+func (w *Writer) Reset(dst io.Writer) {
+	if dw, ok := w.d.w.w.(*dictWriter); ok {
+		// w was created with NewWriterDict
+		dw.w = dst
+		w.d.reset(dw)
+		dw.enabled = false
+		w.Write(w.dict)
+		w.Flush()
+		dw.enabled = true
+	} else {
+		// w was created with NewWriter
+		w.d.reset(dst)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/deflate_test.go b/third_party/gofrontend/libgo/go/compress/flate/deflate_test.go
new file mode 100644
index 0000000..730234c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/deflate_test.go
@@ -0,0 +1,490 @@
+// 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 flate
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"reflect"
+	"sync"
+	"testing"
+)
+
+type deflateTest struct {
+	in    []byte
+	level int
+	out   []byte
+}
+
+type deflateInflateTest struct {
+	in []byte
+}
+
+type reverseBitsTest struct {
+	in       uint16
+	bitCount uint8
+	out      uint16
+}
+
+var deflateTests = []*deflateTest{
+	{[]byte{}, 0, []byte{1, 0, 0, 255, 255}},
+	{[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}},
+	{[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}},
+	{[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}},
+
+	{[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
+		[]byte{0, 8, 0, 247, 255, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0, 0, 255, 255},
+	},
+	{[]byte{}, 1, []byte{1, 0, 0, 255, 255}},
+	{[]byte{0x11}, 1, []byte{18, 4, 4, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x12}, 1, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 1, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
+	{[]byte{}, 9, []byte{1, 0, 0, 255, 255}},
+	{[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
+}
+
+var deflateInflateTests = []*deflateInflateTest{
+	{[]byte{}},
+	{[]byte{0x11}},
+	{[]byte{0x11, 0x12}},
+	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
+	{[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
+	{largeDataChunk()},
+}
+
+var reverseBitsTests = []*reverseBitsTest{
+	{1, 1, 1},
+	{1, 2, 2},
+	{1, 3, 4},
+	{1, 4, 8},
+	{1, 5, 16},
+	{17, 5, 17},
+	{257, 9, 257},
+	{29, 5, 23},
+}
+
+func largeDataChunk() []byte {
+	result := make([]byte, 100000)
+	for i := range result {
+		result[i] = byte(i * i & 0xFF)
+	}
+	return result
+}
+
+func TestDeflate(t *testing.T) {
+	for _, h := range deflateTests {
+		var buf bytes.Buffer
+		w, err := NewWriter(&buf, h.level)
+		if err != nil {
+			t.Errorf("NewWriter: %v", err)
+			continue
+		}
+		w.Write(h.in)
+		w.Close()
+		if !bytes.Equal(buf.Bytes(), h.out) {
+			t.Errorf("Deflate(%d, %x) = %x, want %x", h.level, h.in, buf.Bytes(), h.out)
+		}
+	}
+}
+
+// A sparseReader returns a stream consisting of 0s followed by 1<<16 1s.
+// This tests missing hash references in a very large input.
+type sparseReader struct {
+	l   int64
+	cur int64
+}
+
+func (r *sparseReader) Read(b []byte) (n int, err error) {
+	if r.cur >= r.l {
+		return 0, io.EOF
+	}
+	n = len(b)
+	cur := r.cur + int64(n)
+	if cur > r.l {
+		n -= int(cur - r.l)
+		cur = r.l
+	}
+	for i := range b[0:n] {
+		if r.cur+int64(i) >= r.l-1<<16 {
+			b[i] = 1
+		} else {
+			b[i] = 0
+		}
+	}
+	r.cur = cur
+	return
+}
+
+func TestVeryLongSparseChunk(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping sparse chunk during short test")
+	}
+	w, err := NewWriter(ioutil.Discard, 1)
+	if err != nil {
+		t.Errorf("NewWriter: %v", err)
+		return
+	}
+	if _, err = io.Copy(w, &sparseReader{l: 23E8}); err != nil {
+		t.Errorf("Compress failed: %v", err)
+		return
+	}
+}
+
+type syncBuffer struct {
+	buf    bytes.Buffer
+	mu     sync.RWMutex
+	closed bool
+	ready  chan bool
+}
+
+func newSyncBuffer() *syncBuffer {
+	return &syncBuffer{ready: make(chan bool, 1)}
+}
+
+func (b *syncBuffer) Read(p []byte) (n int, err error) {
+	for {
+		b.mu.RLock()
+		n, err = b.buf.Read(p)
+		b.mu.RUnlock()
+		if n > 0 || b.closed {
+			return
+		}
+		<-b.ready
+	}
+}
+
+func (b *syncBuffer) signal() {
+	select {
+	case b.ready <- true:
+	default:
+	}
+}
+
+func (b *syncBuffer) Write(p []byte) (n int, err error) {
+	n, err = b.buf.Write(p)
+	b.signal()
+	return
+}
+
+func (b *syncBuffer) WriteMode() {
+	b.mu.Lock()
+}
+
+func (b *syncBuffer) ReadMode() {
+	b.mu.Unlock()
+	b.signal()
+}
+
+func (b *syncBuffer) Close() error {
+	b.closed = true
+	b.signal()
+	return nil
+}
+
+func testSync(t *testing.T, level int, input []byte, name string) {
+	if len(input) == 0 {
+		return
+	}
+
+	t.Logf("--testSync %d, %d, %s", level, len(input), name)
+	buf := newSyncBuffer()
+	buf1 := new(bytes.Buffer)
+	buf.WriteMode()
+	w, err := NewWriter(io.MultiWriter(buf, buf1), level)
+	if err != nil {
+		t.Errorf("NewWriter: %v", err)
+		return
+	}
+	r := NewReader(buf)
+
+	// Write half the input and read back.
+	for i := 0; i < 2; i++ {
+		var lo, hi int
+		if i == 0 {
+			lo, hi = 0, (len(input)+1)/2
+		} else {
+			lo, hi = (len(input)+1)/2, len(input)
+		}
+		t.Logf("#%d: write %d-%d", i, lo, hi)
+		if _, err := w.Write(input[lo:hi]); err != nil {
+			t.Errorf("testSync: write: %v", err)
+			return
+		}
+		if i == 0 {
+			if err := w.Flush(); err != nil {
+				t.Errorf("testSync: flush: %v", err)
+				return
+			}
+		} else {
+			if err := w.Close(); err != nil {
+				t.Errorf("testSync: close: %v", err)
+			}
+		}
+		buf.ReadMode()
+		out := make([]byte, hi-lo+1)
+		m, err := io.ReadAtLeast(r, out, hi-lo)
+		t.Logf("#%d: read %d", i, m)
+		if m != hi-lo || err != nil {
+			t.Errorf("testSync/%d (%d, %d, %s): read %d: %d, %v (%d left)", i, level, len(input), name, hi-lo, m, err, buf.buf.Len())
+			return
+		}
+		if !bytes.Equal(input[lo:hi], out[:hi-lo]) {
+			t.Errorf("testSync/%d: read wrong bytes: %x vs %x", i, input[lo:hi], out[:hi-lo])
+			return
+		}
+		// This test originally checked that after reading
+		// the first half of the input, there was nothing left
+		// in the read buffer (buf.buf.Len() != 0) but that is
+		// not necessarily the case: the write Flush may emit
+		// some extra framing bits that are not necessary
+		// to process to obtain the first half of the uncompressed
+		// data.  The test ran correctly most of the time, because
+		// the background goroutine had usually read even
+		// those extra bits by now, but it's not a useful thing to
+		// check.
+		buf.WriteMode()
+	}
+	buf.ReadMode()
+	out := make([]byte, 10)
+	if n, err := r.Read(out); n > 0 || err != io.EOF {
+		t.Errorf("testSync (%d, %d, %s): final Read: %d, %v (hex: %x)", level, len(input), name, n, err, out[0:n])
+	}
+	if buf.buf.Len() != 0 {
+		t.Errorf("testSync (%d, %d, %s): extra data at end", level, len(input), name)
+	}
+	r.Close()
+
+	// stream should work for ordinary reader too
+	r = NewReader(buf1)
+	out, err = ioutil.ReadAll(r)
+	if err != nil {
+		t.Errorf("testSync: read: %s", err)
+		return
+	}
+	r.Close()
+	if !bytes.Equal(input, out) {
+		t.Errorf("testSync: decompress(compress(data)) != data: level=%d input=%s", level, name)
+	}
+}
+
+func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) {
+	var buffer bytes.Buffer
+	w, err := NewWriter(&buffer, level)
+	if err != nil {
+		t.Errorf("NewWriter: %v", err)
+		return
+	}
+	w.Write(input)
+	w.Close()
+	if limit > 0 && buffer.Len() > limit {
+		t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit)
+		return
+	}
+	r := NewReader(&buffer)
+	out, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Errorf("read: %s", err)
+		return
+	}
+	r.Close()
+	if !bytes.Equal(input, out) {
+		t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name)
+		return
+	}
+	testSync(t, level, input, name)
+}
+
+func testToFromWithLimit(t *testing.T, input []byte, name string, limit [10]int) {
+	for i := 0; i < 10; i++ {
+		testToFromWithLevelAndLimit(t, i, input, name, limit[i])
+	}
+}
+
+func TestDeflateInflate(t *testing.T) {
+	for i, h := range deflateInflateTests {
+		testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [10]int{})
+	}
+}
+
+func TestReverseBits(t *testing.T) {
+	for _, h := range reverseBitsTests {
+		if v := reverseBits(h.in, h.bitCount); v != h.out {
+			t.Errorf("reverseBits(%v,%v) = %v, want %v",
+				h.in, h.bitCount, v, h.out)
+		}
+	}
+}
+
+type deflateInflateStringTest struct {
+	filename string
+	label    string
+	limit    [10]int
+}
+
+var deflateInflateStringTests = []deflateInflateStringTest{
+	{
+		"../testdata/e.txt",
+		"2.718281828...",
+		[...]int{100018, 50650, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790},
+	},
+	{
+		"../testdata/Mark.Twain-Tom.Sawyer.txt",
+		"Mark.Twain-Tom.Sawyer",
+		[...]int{407330, 187598, 180361, 172974, 169160, 163476, 160936, 160506, 160295, 160295},
+	},
+}
+
+func TestDeflateInflateString(t *testing.T) {
+	for _, test := range deflateInflateStringTests {
+		gold, err := ioutil.ReadFile(test.filename)
+		if err != nil {
+			t.Error(err)
+		}
+		testToFromWithLimit(t, gold, test.label, test.limit)
+		if testing.Short() {
+			break
+		}
+	}
+}
+
+func TestReaderDict(t *testing.T) {
+	const (
+		dict = "hello world"
+		text = "hello again world"
+	)
+	var b bytes.Buffer
+	w, err := NewWriter(&b, 5)
+	if err != nil {
+		t.Fatalf("NewWriter: %v", err)
+	}
+	w.Write([]byte(dict))
+	w.Flush()
+	b.Reset()
+	w.Write([]byte(text))
+	w.Close()
+
+	r := NewReaderDict(&b, []byte(dict))
+	data, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(data) != "hello again world" {
+		t.Fatalf("read returned %q want %q", string(data), text)
+	}
+}
+
+func TestWriterDict(t *testing.T) {
+	const (
+		dict = "hello world"
+		text = "hello again world"
+	)
+	var b bytes.Buffer
+	w, err := NewWriter(&b, 5)
+	if err != nil {
+		t.Fatalf("NewWriter: %v", err)
+	}
+	w.Write([]byte(dict))
+	w.Flush()
+	b.Reset()
+	w.Write([]byte(text))
+	w.Close()
+
+	var b1 bytes.Buffer
+	w, _ = NewWriterDict(&b1, 5, []byte(dict))
+	w.Write([]byte(text))
+	w.Close()
+
+	if !bytes.Equal(b1.Bytes(), b.Bytes()) {
+		t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes())
+	}
+}
+
+// See http://code.google.com/p/go/issues/detail?id=2508
+func TestRegression2508(t *testing.T) {
+	if testing.Short() {
+		t.Logf("test disabled with -short")
+		return
+	}
+	w, err := NewWriter(ioutil.Discard, 1)
+	if err != nil {
+		t.Fatalf("NewWriter: %v", err)
+	}
+	buf := make([]byte, 1024)
+	for i := 0; i < 131072; i++ {
+		if _, err := w.Write(buf); err != nil {
+			t.Fatalf("writer failed: %v", err)
+		}
+	}
+	w.Close()
+}
+
+func TestWriterReset(t *testing.T) {
+	for level := 0; level <= 9; level++ {
+		if testing.Short() && level > 1 {
+			break
+		}
+		w, err := NewWriter(ioutil.Discard, level)
+		if err != nil {
+			t.Fatalf("NewWriter: %v", err)
+		}
+		buf := []byte("hello world")
+		for i := 0; i < 1024; i++ {
+			w.Write(buf)
+		}
+		w.Reset(ioutil.Discard)
+
+		wref, err := NewWriter(ioutil.Discard, level)
+		if err != nil {
+			t.Fatalf("NewWriter: %v", err)
+		}
+
+		// DeepEqual doesn't compare functions.
+		w.d.fill, wref.d.fill = nil, nil
+		w.d.step, wref.d.step = nil, nil
+		if !reflect.DeepEqual(w, wref) {
+			t.Errorf("level %d Writer not reset after Reset", level)
+		}
+	}
+	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, NoCompression) })
+	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, DefaultCompression) })
+	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, BestCompression) })
+	dict := []byte("we are the world")
+	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, NoCompression, dict) })
+	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, DefaultCompression, dict) })
+	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, BestCompression, dict) })
+}
+
+func testResetOutput(t *testing.T, newWriter func(w io.Writer) (*Writer, error)) {
+	buf := new(bytes.Buffer)
+	w, err := newWriter(buf)
+	if err != nil {
+		t.Fatalf("NewWriter: %v", err)
+	}
+	b := []byte("hello world")
+	for i := 0; i < 1024; i++ {
+		w.Write(b)
+	}
+	w.Close()
+	out1 := buf.String()
+
+	buf2 := new(bytes.Buffer)
+	w.Reset(buf2)
+	for i := 0; i < 1024; i++ {
+		w.Write(b)
+	}
+	w.Close()
+	out2 := buf2.String()
+
+	if out1 != out2 {
+		t.Errorf("got %q, expected %q", out2, out1)
+	}
+	t.Logf("got %d bytes", len(out1))
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/fixedhuff.go b/third_party/gofrontend/libgo/go/compress/flate/fixedhuff.go
new file mode 100644
index 0000000..9be3d53
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/fixedhuff.go
@@ -0,0 +1,78 @@
+// Copyright 2013 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 flate
+
+// autogenerated by gen.go, DO NOT EDIT
+
+var fixedHuffmanDecoder = huffmanDecoder{
+	7,
+	[huffmanNumChunks]uint32{
+		0x1007, 0x0508, 0x0108, 0x1188, 0x1107, 0x0708, 0x0308, 0x0c09,
+		0x1087, 0x0608, 0x0208, 0x0a09, 0x0008, 0x0808, 0x0408, 0x0e09,
+		0x1047, 0x0588, 0x0188, 0x0909, 0x1147, 0x0788, 0x0388, 0x0d09,
+		0x10c7, 0x0688, 0x0288, 0x0b09, 0x0088, 0x0888, 0x0488, 0x0f09,
+		0x1027, 0x0548, 0x0148, 0x11c8, 0x1127, 0x0748, 0x0348, 0x0c89,
+		0x10a7, 0x0648, 0x0248, 0x0a89, 0x0048, 0x0848, 0x0448, 0x0e89,
+		0x1067, 0x05c8, 0x01c8, 0x0989, 0x1167, 0x07c8, 0x03c8, 0x0d89,
+		0x10e7, 0x06c8, 0x02c8, 0x0b89, 0x00c8, 0x08c8, 0x04c8, 0x0f89,
+		0x1017, 0x0528, 0x0128, 0x11a8, 0x1117, 0x0728, 0x0328, 0x0c49,
+		0x1097, 0x0628, 0x0228, 0x0a49, 0x0028, 0x0828, 0x0428, 0x0e49,
+		0x1057, 0x05a8, 0x01a8, 0x0949, 0x1157, 0x07a8, 0x03a8, 0x0d49,
+		0x10d7, 0x06a8, 0x02a8, 0x0b49, 0x00a8, 0x08a8, 0x04a8, 0x0f49,
+		0x1037, 0x0568, 0x0168, 0x11e8, 0x1137, 0x0768, 0x0368, 0x0cc9,
+		0x10b7, 0x0668, 0x0268, 0x0ac9, 0x0068, 0x0868, 0x0468, 0x0ec9,
+		0x1077, 0x05e8, 0x01e8, 0x09c9, 0x1177, 0x07e8, 0x03e8, 0x0dc9,
+		0x10f7, 0x06e8, 0x02e8, 0x0bc9, 0x00e8, 0x08e8, 0x04e8, 0x0fc9,
+		0x1007, 0x0518, 0x0118, 0x1198, 0x1107, 0x0718, 0x0318, 0x0c29,
+		0x1087, 0x0618, 0x0218, 0x0a29, 0x0018, 0x0818, 0x0418, 0x0e29,
+		0x1047, 0x0598, 0x0198, 0x0929, 0x1147, 0x0798, 0x0398, 0x0d29,
+		0x10c7, 0x0698, 0x0298, 0x0b29, 0x0098, 0x0898, 0x0498, 0x0f29,
+		0x1027, 0x0558, 0x0158, 0x11d8, 0x1127, 0x0758, 0x0358, 0x0ca9,
+		0x10a7, 0x0658, 0x0258, 0x0aa9, 0x0058, 0x0858, 0x0458, 0x0ea9,
+		0x1067, 0x05d8, 0x01d8, 0x09a9, 0x1167, 0x07d8, 0x03d8, 0x0da9,
+		0x10e7, 0x06d8, 0x02d8, 0x0ba9, 0x00d8, 0x08d8, 0x04d8, 0x0fa9,
+		0x1017, 0x0538, 0x0138, 0x11b8, 0x1117, 0x0738, 0x0338, 0x0c69,
+		0x1097, 0x0638, 0x0238, 0x0a69, 0x0038, 0x0838, 0x0438, 0x0e69,
+		0x1057, 0x05b8, 0x01b8, 0x0969, 0x1157, 0x07b8, 0x03b8, 0x0d69,
+		0x10d7, 0x06b8, 0x02b8, 0x0b69, 0x00b8, 0x08b8, 0x04b8, 0x0f69,
+		0x1037, 0x0578, 0x0178, 0x11f8, 0x1137, 0x0778, 0x0378, 0x0ce9,
+		0x10b7, 0x0678, 0x0278, 0x0ae9, 0x0078, 0x0878, 0x0478, 0x0ee9,
+		0x1077, 0x05f8, 0x01f8, 0x09e9, 0x1177, 0x07f8, 0x03f8, 0x0de9,
+		0x10f7, 0x06f8, 0x02f8, 0x0be9, 0x00f8, 0x08f8, 0x04f8, 0x0fe9,
+		0x1007, 0x0508, 0x0108, 0x1188, 0x1107, 0x0708, 0x0308, 0x0c19,
+		0x1087, 0x0608, 0x0208, 0x0a19, 0x0008, 0x0808, 0x0408, 0x0e19,
+		0x1047, 0x0588, 0x0188, 0x0919, 0x1147, 0x0788, 0x0388, 0x0d19,
+		0x10c7, 0x0688, 0x0288, 0x0b19, 0x0088, 0x0888, 0x0488, 0x0f19,
+		0x1027, 0x0548, 0x0148, 0x11c8, 0x1127, 0x0748, 0x0348, 0x0c99,
+		0x10a7, 0x0648, 0x0248, 0x0a99, 0x0048, 0x0848, 0x0448, 0x0e99,
+		0x1067, 0x05c8, 0x01c8, 0x0999, 0x1167, 0x07c8, 0x03c8, 0x0d99,
+		0x10e7, 0x06c8, 0x02c8, 0x0b99, 0x00c8, 0x08c8, 0x04c8, 0x0f99,
+		0x1017, 0x0528, 0x0128, 0x11a8, 0x1117, 0x0728, 0x0328, 0x0c59,
+		0x1097, 0x0628, 0x0228, 0x0a59, 0x0028, 0x0828, 0x0428, 0x0e59,
+		0x1057, 0x05a8, 0x01a8, 0x0959, 0x1157, 0x07a8, 0x03a8, 0x0d59,
+		0x10d7, 0x06a8, 0x02a8, 0x0b59, 0x00a8, 0x08a8, 0x04a8, 0x0f59,
+		0x1037, 0x0568, 0x0168, 0x11e8, 0x1137, 0x0768, 0x0368, 0x0cd9,
+		0x10b7, 0x0668, 0x0268, 0x0ad9, 0x0068, 0x0868, 0x0468, 0x0ed9,
+		0x1077, 0x05e8, 0x01e8, 0x09d9, 0x1177, 0x07e8, 0x03e8, 0x0dd9,
+		0x10f7, 0x06e8, 0x02e8, 0x0bd9, 0x00e8, 0x08e8, 0x04e8, 0x0fd9,
+		0x1007, 0x0518, 0x0118, 0x1198, 0x1107, 0x0718, 0x0318, 0x0c39,
+		0x1087, 0x0618, 0x0218, 0x0a39, 0x0018, 0x0818, 0x0418, 0x0e39,
+		0x1047, 0x0598, 0x0198, 0x0939, 0x1147, 0x0798, 0x0398, 0x0d39,
+		0x10c7, 0x0698, 0x0298, 0x0b39, 0x0098, 0x0898, 0x0498, 0x0f39,
+		0x1027, 0x0558, 0x0158, 0x11d8, 0x1127, 0x0758, 0x0358, 0x0cb9,
+		0x10a7, 0x0658, 0x0258, 0x0ab9, 0x0058, 0x0858, 0x0458, 0x0eb9,
+		0x1067, 0x05d8, 0x01d8, 0x09b9, 0x1167, 0x07d8, 0x03d8, 0x0db9,
+		0x10e7, 0x06d8, 0x02d8, 0x0bb9, 0x00d8, 0x08d8, 0x04d8, 0x0fb9,
+		0x1017, 0x0538, 0x0138, 0x11b8, 0x1117, 0x0738, 0x0338, 0x0c79,
+		0x1097, 0x0638, 0x0238, 0x0a79, 0x0038, 0x0838, 0x0438, 0x0e79,
+		0x1057, 0x05b8, 0x01b8, 0x0979, 0x1157, 0x07b8, 0x03b8, 0x0d79,
+		0x10d7, 0x06b8, 0x02b8, 0x0b79, 0x00b8, 0x08b8, 0x04b8, 0x0f79,
+		0x1037, 0x0578, 0x0178, 0x11f8, 0x1137, 0x0778, 0x0378, 0x0cf9,
+		0x10b7, 0x0678, 0x0278, 0x0af9, 0x0078, 0x0878, 0x0478, 0x0ef9,
+		0x1077, 0x05f8, 0x01f8, 0x09f9, 0x1177, 0x07f8, 0x03f8, 0x0df9,
+		0x10f7, 0x06f8, 0x02f8, 0x0bf9, 0x00f8, 0x08f8, 0x04f8, 0x0ff9,
+	},
+	nil, 0,
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/flate_test.go b/third_party/gofrontend/libgo/go/compress/flate/flate_test.go
new file mode 100644
index 0000000..0687663
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/flate_test.go
@@ -0,0 +1,62 @@
+// 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.
+
+// This test tests some internals of the flate package.
+// The tests in package compress/gzip serve as the
+// end-to-end test of the decompressor.
+
+package flate
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestUncompressedSource(t *testing.T) {
+	decoder := NewReader(bytes.NewReader([]byte{0x01, 0x01, 0x00, 0xfe, 0xff, 0x11}))
+	output := make([]byte, 1)
+	n, error := decoder.Read(output)
+	if n != 1 || error != nil {
+		t.Fatalf("decoder.Read() = %d, %v, want 1, nil", n, error)
+	}
+	if output[0] != 0x11 {
+		t.Errorf("output[0] = %x, want 0x11", output[0])
+	}
+}
+
+// The following test should not panic.
+func TestIssue5915(t *testing.T) {
+	bits := []int{4, 0, 0, 6, 4, 3, 2, 3, 3, 4, 4, 5, 0, 0, 0, 0, 5, 5, 6,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 6, 0, 11, 0, 8, 0, 6, 6, 10, 8}
+	h := new(huffmanDecoder)
+	ok := h.init(bits)
+	if ok == true {
+		t.Fatalf("Given sequence of bits is bad, and should not succeed.")
+	}
+}
+
+// The following test should not panic.
+func TestIssue5962(t *testing.T) {
+	bits := []int{4, 0, 0, 6, 4, 3, 2, 3, 3, 4, 4, 5, 0, 0, 0, 0,
+		5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}
+	h := new(huffmanDecoder)
+	ok := h.init(bits)
+	if ok == true {
+		t.Fatalf("Given sequence of bits is bad, and should not succeed.")
+	}
+}
+
+// The following test should not panic.
+func TestIssue6255(t *testing.T) {
+	bits1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11}
+	bits2 := []int{11, 13}
+	h := new(huffmanDecoder)
+	if !h.init(bits1) {
+		t.Fatalf("Given sequence of bits is good and should succeed.")
+	}
+	if h.init(bits2) {
+		t.Fatalf("Given sequence of bits is bad and should not succeed.")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/gen.go b/third_party/gofrontend/libgo/go/compress/flate/gen.go
new file mode 100644
index 0000000..1427557
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/gen.go
@@ -0,0 +1,165 @@
+// 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.
+
+// +build ignore
+
+// This program generates fixedhuff.go
+// Invoke as
+//
+//      go run gen.go |gofmt >fixedhuff.go
+
+package main
+
+import (
+	"fmt"
+)
+
+const maxCodeLen = 16
+
+// Note: the definition of the huffmanDecoder struct is copied from
+// inflate.go, as it is private to the implementation.
+
+// chunk & 15 is number of bits
+// chunk >> 4 is value, including table link
+
+const (
+	huffmanChunkBits  = 9
+	huffmanNumChunks  = 1 << huffmanChunkBits
+	huffmanCountMask  = 15
+	huffmanValueShift = 4
+)
+
+type huffmanDecoder struct {
+	min      int                      // the minimum code length
+	chunks   [huffmanNumChunks]uint32 // chunks as described above
+	links    [][]uint32               // overflow links
+	linkMask uint32                   // mask the width of the link table
+}
+
+// Initialize Huffman decoding tables from array of code lengths.
+func (h *huffmanDecoder) init(bits []int) bool {
+	// Count number of codes of each length,
+	// compute min and max length.
+	var count [maxCodeLen]int
+	var min, max int
+	for _, n := range bits {
+		if n == 0 {
+			continue
+		}
+		if min == 0 || n < min {
+			min = n
+		}
+		if n > max {
+			max = n
+		}
+		count[n]++
+	}
+	if max == 0 {
+		return false
+	}
+
+	h.min = min
+	var linkBits uint
+	var numLinks int
+	if max > huffmanChunkBits {
+		linkBits = uint(max) - huffmanChunkBits
+		numLinks = 1 << linkBits
+		h.linkMask = uint32(numLinks - 1)
+	}
+	code := 0
+	var nextcode [maxCodeLen]int
+	for i := min; i <= max; i++ {
+		if i == huffmanChunkBits+1 {
+			// create link tables
+			link := code >> 1
+			h.links = make([][]uint32, huffmanNumChunks-link)
+			for j := uint(link); j < huffmanNumChunks; j++ {
+				reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8
+				reverse >>= uint(16 - huffmanChunkBits)
+				off := j - uint(link)
+				h.chunks[reverse] = uint32(off<<huffmanValueShift + uint(i))
+				h.links[off] = make([]uint32, 1<<linkBits)
+			}
+		}
+		n := count[i]
+		nextcode[i] = code
+		code += n
+		code <<= 1
+	}
+
+	for i, n := range bits {
+		if n == 0 {
+			continue
+		}
+		code := nextcode[n]
+		nextcode[n]++
+		chunk := uint32(i<<huffmanValueShift | n)
+		reverse := int(reverseByte[code>>8]) | int(reverseByte[code&0xff])<<8
+		reverse >>= uint(16 - n)
+		if n <= huffmanChunkBits {
+			for off := reverse; off < huffmanNumChunks; off += 1 << uint(n) {
+				h.chunks[off] = chunk
+			}
+		} else {
+			linktab := h.links[h.chunks[reverse&(huffmanNumChunks-1)]>>huffmanValueShift]
+			reverse >>= huffmanChunkBits
+			for off := reverse; off < numLinks; off += 1 << uint(n-huffmanChunkBits) {
+				linktab[off] = chunk
+			}
+		}
+	}
+	return true
+}
+
+func main() {
+	var h huffmanDecoder
+	var bits [288]int
+	initReverseByte()
+	for i := 0; i < 144; i++ {
+		bits[i] = 8
+	}
+	for i := 144; i < 256; i++ {
+		bits[i] = 9
+	}
+	for i := 256; i < 280; i++ {
+		bits[i] = 7
+	}
+	for i := 280; i < 288; i++ {
+		bits[i] = 8
+	}
+	h.init(bits[:])
+	fmt.Println("package flate")
+	fmt.Println()
+	fmt.Println("// autogenerated by gen.go, DO NOT EDIT")
+	fmt.Println()
+	fmt.Println("var fixedHuffmanDecoder = huffmanDecoder{")
+	fmt.Printf("\t%d,\n", h.min)
+	fmt.Println("\t[huffmanNumChunks]uint32{")
+	for i := 0; i < huffmanNumChunks; i++ {
+		if i&7 == 0 {
+			fmt.Printf("\t\t")
+		} else {
+			fmt.Printf(" ")
+		}
+		fmt.Printf("0x%04x,", h.chunks[i])
+		if i&7 == 7 {
+			fmt.Println()
+		}
+	}
+	fmt.Println("\t},")
+	fmt.Println("\tnil, 0,")
+	fmt.Println("}")
+}
+
+var reverseByte [256]byte
+
+func initReverseByte() {
+	for x := 0; x < 256; x++ {
+		var result byte
+		for i := uint(0); i < 8; i++ {
+			result |= byte(((x >> i) & 1) << (7 - i))
+		}
+		reverseByte[x] = result
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/huffman_bit_writer.go b/third_party/gofrontend/libgo/go/compress/flate/huffman_bit_writer.go
new file mode 100644
index 0000000..b182a71
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/huffman_bit_writer.go
@@ -0,0 +1,517 @@
+// 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 flate
+
+import (
+	"io"
+	"math"
+)
+
+const (
+	// The largest offset code.
+	offsetCodeCount = 30
+
+	// The special code used to mark the end of a block.
+	endBlockMarker = 256
+
+	// The first length code.
+	lengthCodesStart = 257
+
+	// The number of codegen codes.
+	codegenCodeCount = 19
+	badCode          = 255
+)
+
+// The number of extra bits needed by length code X - LENGTH_CODES_START.
+var lengthExtraBits = []int8{
+	/* 257 */ 0, 0, 0,
+	/* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
+	/* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
+	/* 280 */ 4, 5, 5, 5, 5, 0,
+}
+
+// The length indicated by length code X - LENGTH_CODES_START.
+var lengthBase = []uint32{
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 10,
+	12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+	64, 80, 96, 112, 128, 160, 192, 224, 255,
+}
+
+// offset code word extra bits.
+var offsetExtraBits = []int8{
+	0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
+	4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
+	9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
+	/* extended window */
+	14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20,
+}
+
+var offsetBase = []uint32{
+	/* normal deflate */
+	0x000000, 0x000001, 0x000002, 0x000003, 0x000004,
+	0x000006, 0x000008, 0x00000c, 0x000010, 0x000018,
+	0x000020, 0x000030, 0x000040, 0x000060, 0x000080,
+	0x0000c0, 0x000100, 0x000180, 0x000200, 0x000300,
+	0x000400, 0x000600, 0x000800, 0x000c00, 0x001000,
+	0x001800, 0x002000, 0x003000, 0x004000, 0x006000,
+
+	/* extended window */
+	0x008000, 0x00c000, 0x010000, 0x018000, 0x020000,
+	0x030000, 0x040000, 0x060000, 0x080000, 0x0c0000,
+	0x100000, 0x180000, 0x200000, 0x300000,
+}
+
+// The odd order in which the codegen code sizes are written.
+var codegenOrder = []uint32{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
+
+type huffmanBitWriter struct {
+	w io.Writer
+	// Data waiting to be written is bytes[0:nbytes]
+	// and then the low nbits of bits.
+	bits            uint32
+	nbits           uint32
+	bytes           [64]byte
+	nbytes          int
+	literalFreq     []int32
+	offsetFreq      []int32
+	codegen         []uint8
+	codegenFreq     []int32
+	literalEncoding *huffmanEncoder
+	offsetEncoding  *huffmanEncoder
+	codegenEncoding *huffmanEncoder
+	err             error
+}
+
+func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
+	return &huffmanBitWriter{
+		w:               w,
+		literalFreq:     make([]int32, maxLit),
+		offsetFreq:      make([]int32, offsetCodeCount),
+		codegen:         make([]uint8, maxLit+offsetCodeCount+1),
+		codegenFreq:     make([]int32, codegenCodeCount),
+		literalEncoding: newHuffmanEncoder(maxLit),
+		offsetEncoding:  newHuffmanEncoder(offsetCodeCount),
+		codegenEncoding: newHuffmanEncoder(codegenCodeCount),
+	}
+}
+
+func (w *huffmanBitWriter) reset(writer io.Writer) {
+	w.w = writer
+	w.bits, w.nbits, w.nbytes, w.err = 0, 0, 0, nil
+	w.bytes = [64]byte{}
+	for i := range w.codegen {
+		w.codegen[i] = 0
+	}
+	for _, s := range [...][]int32{w.literalFreq, w.offsetFreq, w.codegenFreq} {
+		for i := range s {
+			s[i] = 0
+		}
+	}
+	for _, enc := range [...]*huffmanEncoder{
+		w.literalEncoding,
+		w.offsetEncoding,
+		w.codegenEncoding} {
+		for i := range enc.code {
+			enc.code[i] = 0
+		}
+		for i := range enc.codeBits {
+			enc.codeBits[i] = 0
+		}
+	}
+}
+
+func (w *huffmanBitWriter) flushBits() {
+	if w.err != nil {
+		w.nbits = 0
+		return
+	}
+	bits := w.bits
+	w.bits >>= 16
+	w.nbits -= 16
+	n := w.nbytes
+	w.bytes[n] = byte(bits)
+	w.bytes[n+1] = byte(bits >> 8)
+	if n += 2; n >= len(w.bytes) {
+		_, w.err = w.w.Write(w.bytes[0:])
+		n = 0
+	}
+	w.nbytes = n
+}
+
+func (w *huffmanBitWriter) flush() {
+	if w.err != nil {
+		w.nbits = 0
+		return
+	}
+	n := w.nbytes
+	if w.nbits > 8 {
+		w.bytes[n] = byte(w.bits)
+		w.bits >>= 8
+		w.nbits -= 8
+		n++
+	}
+	if w.nbits > 0 {
+		w.bytes[n] = byte(w.bits)
+		w.nbits = 0
+		n++
+	}
+	w.bits = 0
+	_, w.err = w.w.Write(w.bytes[0:n])
+	w.nbytes = 0
+}
+
+func (w *huffmanBitWriter) writeBits(b, nb int32) {
+	w.bits |= uint32(b) << w.nbits
+	if w.nbits += uint32(nb); w.nbits >= 16 {
+		w.flushBits()
+	}
+}
+
+func (w *huffmanBitWriter) writeBytes(bytes []byte) {
+	if w.err != nil {
+		return
+	}
+	n := w.nbytes
+	if w.nbits == 8 {
+		w.bytes[n] = byte(w.bits)
+		w.nbits = 0
+		n++
+	}
+	if w.nbits != 0 {
+		w.err = InternalError("writeBytes with unfinished bits")
+		return
+	}
+	if n != 0 {
+		_, w.err = w.w.Write(w.bytes[0:n])
+		if w.err != nil {
+			return
+		}
+	}
+	w.nbytes = 0
+	_, w.err = w.w.Write(bytes)
+}
+
+// RFC 1951 3.2.7 specifies a special run-length encoding for specifying
+// the literal and offset lengths arrays (which are concatenated into a single
+// array).  This method generates that run-length encoding.
+//
+// The result is written into the codegen array, and the frequencies
+// of each code is written into the codegenFreq array.
+// Codes 0-15 are single byte codes. Codes 16-18 are followed by additional
+// information.  Code badCode is an end marker
+//
+//  numLiterals      The number of literals in literalEncoding
+//  numOffsets       The number of offsets in offsetEncoding
+func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
+	for i := range w.codegenFreq {
+		w.codegenFreq[i] = 0
+	}
+	// Note that we are using codegen both as a temporary variable for holding
+	// a copy of the frequencies, and as the place where we put the result.
+	// This is fine because the output is always shorter than the input used
+	// so far.
+	codegen := w.codegen // cache
+	// Copy the concatenated code sizes to codegen.  Put a marker at the end.
+	copy(codegen[0:numLiterals], w.literalEncoding.codeBits)
+	copy(codegen[numLiterals:numLiterals+numOffsets], w.offsetEncoding.codeBits)
+	codegen[numLiterals+numOffsets] = badCode
+
+	size := codegen[0]
+	count := 1
+	outIndex := 0
+	for inIndex := 1; size != badCode; inIndex++ {
+		// INVARIANT: We have seen "count" copies of size that have not yet
+		// had output generated for them.
+		nextSize := codegen[inIndex]
+		if nextSize == size {
+			count++
+			continue
+		}
+		// We need to generate codegen indicating "count" of size.
+		if size != 0 {
+			codegen[outIndex] = size
+			outIndex++
+			w.codegenFreq[size]++
+			count--
+			for count >= 3 {
+				n := 6
+				if n > count {
+					n = count
+				}
+				codegen[outIndex] = 16
+				outIndex++
+				codegen[outIndex] = uint8(n - 3)
+				outIndex++
+				w.codegenFreq[16]++
+				count -= n
+			}
+		} else {
+			for count >= 11 {
+				n := 138
+				if n > count {
+					n = count
+				}
+				codegen[outIndex] = 18
+				outIndex++
+				codegen[outIndex] = uint8(n - 11)
+				outIndex++
+				w.codegenFreq[18]++
+				count -= n
+			}
+			if count >= 3 {
+				// count >= 3 && count <= 10
+				codegen[outIndex] = 17
+				outIndex++
+				codegen[outIndex] = uint8(count - 3)
+				outIndex++
+				w.codegenFreq[17]++
+				count = 0
+			}
+		}
+		count--
+		for ; count >= 0; count-- {
+			codegen[outIndex] = size
+			outIndex++
+			w.codegenFreq[size]++
+		}
+		// Set up invariant for next time through the loop.
+		size = nextSize
+		count = 1
+	}
+	// Marker indicating the end of the codegen.
+	codegen[outIndex] = badCode
+}
+
+func (w *huffmanBitWriter) writeCode(code *huffmanEncoder, literal uint32) {
+	if w.err != nil {
+		return
+	}
+	w.writeBits(int32(code.code[literal]), int32(code.codeBits[literal]))
+}
+
+// Write the header of a dynamic Huffman block to the output stream.
+//
+//  numLiterals  The number of literals specified in codegen
+//  numOffsets   The number of offsets specified in codegen
+//  numCodegens  The number of codegens used in codegen
+func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, numCodegens int, isEof bool) {
+	if w.err != nil {
+		return
+	}
+	var firstBits int32 = 4
+	if isEof {
+		firstBits = 5
+	}
+	w.writeBits(firstBits, 3)
+	w.writeBits(int32(numLiterals-257), 5)
+	w.writeBits(int32(numOffsets-1), 5)
+	w.writeBits(int32(numCodegens-4), 4)
+
+	for i := 0; i < numCodegens; i++ {
+		value := w.codegenEncoding.codeBits[codegenOrder[i]]
+		w.writeBits(int32(value), 3)
+	}
+
+	i := 0
+	for {
+		var codeWord int = int(w.codegen[i])
+		i++
+		if codeWord == badCode {
+			break
+		}
+		// The low byte contains the actual code to generate.
+		w.writeCode(w.codegenEncoding, uint32(codeWord))
+
+		switch codeWord {
+		case 16:
+			w.writeBits(int32(w.codegen[i]), 2)
+			i++
+			break
+		case 17:
+			w.writeBits(int32(w.codegen[i]), 3)
+			i++
+			break
+		case 18:
+			w.writeBits(int32(w.codegen[i]), 7)
+			i++
+			break
+		}
+	}
+}
+
+func (w *huffmanBitWriter) writeStoredHeader(length int, isEof bool) {
+	if w.err != nil {
+		return
+	}
+	var flag int32
+	if isEof {
+		flag = 1
+	}
+	w.writeBits(flag, 3)
+	w.flush()
+	w.writeBits(int32(length), 16)
+	w.writeBits(int32(^uint16(length)), 16)
+}
+
+func (w *huffmanBitWriter) writeFixedHeader(isEof bool) {
+	if w.err != nil {
+		return
+	}
+	// Indicate that we are a fixed Huffman block
+	var value int32 = 2
+	if isEof {
+		value = 3
+	}
+	w.writeBits(value, 3)
+}
+
+func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
+	if w.err != nil {
+		return
+	}
+	for i := range w.literalFreq {
+		w.literalFreq[i] = 0
+	}
+	for i := range w.offsetFreq {
+		w.offsetFreq[i] = 0
+	}
+
+	n := len(tokens)
+	tokens = tokens[0 : n+1]
+	tokens[n] = endBlockMarker
+
+	for _, t := range tokens {
+		switch t.typ() {
+		case literalType:
+			w.literalFreq[t.literal()]++
+		case matchType:
+			length := t.length()
+			offset := t.offset()
+			w.literalFreq[lengthCodesStart+lengthCode(length)]++
+			w.offsetFreq[offsetCode(offset)]++
+		}
+	}
+
+	// get the number of literals
+	numLiterals := len(w.literalFreq)
+	for w.literalFreq[numLiterals-1] == 0 {
+		numLiterals--
+	}
+	// get the number of offsets
+	numOffsets := len(w.offsetFreq)
+	for numOffsets > 0 && w.offsetFreq[numOffsets-1] == 0 {
+		numOffsets--
+	}
+	if numOffsets == 0 {
+		// We haven't found a single match. If we want to go with the dynamic encoding,
+		// we should count at least one offset to be sure that the offset huffman tree could be encoded.
+		w.offsetFreq[0] = 1
+		numOffsets = 1
+	}
+
+	w.literalEncoding.generate(w.literalFreq, 15)
+	w.offsetEncoding.generate(w.offsetFreq, 15)
+
+	storedBytes := 0
+	if input != nil {
+		storedBytes = len(input)
+	}
+	var extraBits int64
+	var storedSize int64 = math.MaxInt64
+	if storedBytes <= maxStoreBlockSize && input != nil {
+		storedSize = int64((storedBytes + 5) * 8)
+		// We only bother calculating the costs of the extra bits required by
+		// the length of offset fields (which will be the same for both fixed
+		// and dynamic encoding), if we need to compare those two encodings
+		// against stored encoding.
+		for lengthCode := lengthCodesStart + 8; lengthCode < numLiterals; lengthCode++ {
+			// First eight length codes have extra size = 0.
+			extraBits += int64(w.literalFreq[lengthCode]) * int64(lengthExtraBits[lengthCode-lengthCodesStart])
+		}
+		for offsetCode := 4; offsetCode < numOffsets; offsetCode++ {
+			// First four offset codes have extra size = 0.
+			extraBits += int64(w.offsetFreq[offsetCode]) * int64(offsetExtraBits[offsetCode])
+		}
+	}
+
+	// Figure out smallest code.
+	// Fixed Huffman baseline.
+	var size = int64(3) +
+		fixedLiteralEncoding.bitLength(w.literalFreq) +
+		fixedOffsetEncoding.bitLength(w.offsetFreq) +
+		extraBits
+	var literalEncoding = fixedLiteralEncoding
+	var offsetEncoding = fixedOffsetEncoding
+
+	// Dynamic Huffman?
+	var numCodegens int
+
+	// Generate codegen and codegenFrequencies, which indicates how to encode
+	// the literalEncoding and the offsetEncoding.
+	w.generateCodegen(numLiterals, numOffsets)
+	w.codegenEncoding.generate(w.codegenFreq, 7)
+	numCodegens = len(w.codegenFreq)
+	for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 {
+		numCodegens--
+	}
+	dynamicHeader := int64(3+5+5+4+(3*numCodegens)) +
+		w.codegenEncoding.bitLength(w.codegenFreq) +
+		int64(extraBits) +
+		int64(w.codegenFreq[16]*2) +
+		int64(w.codegenFreq[17]*3) +
+		int64(w.codegenFreq[18]*7)
+	dynamicSize := dynamicHeader +
+		w.literalEncoding.bitLength(w.literalFreq) +
+		w.offsetEncoding.bitLength(w.offsetFreq)
+
+	if dynamicSize < size {
+		size = dynamicSize
+		literalEncoding = w.literalEncoding
+		offsetEncoding = w.offsetEncoding
+	}
+
+	// Stored bytes?
+	if storedSize < size {
+		w.writeStoredHeader(storedBytes, eof)
+		w.writeBytes(input[0:storedBytes])
+		return
+	}
+
+	// Huffman.
+	if literalEncoding == fixedLiteralEncoding {
+		w.writeFixedHeader(eof)
+	} else {
+		w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof)
+	}
+	for _, t := range tokens {
+		switch t.typ() {
+		case literalType:
+			w.writeCode(literalEncoding, t.literal())
+			break
+		case matchType:
+			// Write the length
+			length := t.length()
+			lengthCode := lengthCode(length)
+			w.writeCode(literalEncoding, lengthCode+lengthCodesStart)
+			extraLengthBits := int32(lengthExtraBits[lengthCode])
+			if extraLengthBits > 0 {
+				extraLength := int32(length - lengthBase[lengthCode])
+				w.writeBits(extraLength, extraLengthBits)
+			}
+			// Write the offset
+			offset := t.offset()
+			offsetCode := offsetCode(offset)
+			w.writeCode(offsetEncoding, offsetCode)
+			extraOffsetBits := int32(offsetExtraBits[offsetCode])
+			if extraOffsetBits > 0 {
+				extraOffset := int32(offset - offsetBase[offsetCode])
+				w.writeBits(extraOffset, extraOffsetBits)
+			}
+			break
+		default:
+			panic("unknown token type: " + string(t))
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/huffman_code.go b/third_party/gofrontend/libgo/go/compress/flate/huffman_code.go
new file mode 100644
index 0000000..3b9fce4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/huffman_code.go
@@ -0,0 +1,323 @@
+// 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 flate
+
+import (
+	"math"
+	"sort"
+)
+
+type huffmanEncoder struct {
+	codeBits []uint8
+	code     []uint16
+}
+
+type literalNode struct {
+	literal uint16
+	freq    int32
+}
+
+// A levelInfo describes the state of the constructed tree for a given depth.
+type levelInfo struct {
+	// Our level.  for better printing
+	level int32
+
+	// The frequency of the last node at this level
+	lastFreq int32
+
+	// The frequency of the next character to add to this level
+	nextCharFreq int32
+
+	// The frequency of the next pair (from level below) to add to this level.
+	// Only valid if the "needed" value of the next lower level is 0.
+	nextPairFreq int32
+
+	// The number of chains remaining to generate for this level before moving
+	// up to the next level
+	needed int32
+}
+
+func maxNode() literalNode { return literalNode{math.MaxUint16, math.MaxInt32} }
+
+func newHuffmanEncoder(size int) *huffmanEncoder {
+	return &huffmanEncoder{make([]uint8, size), make([]uint16, size)}
+}
+
+// Generates a HuffmanCode corresponding to the fixed literal table
+func generateFixedLiteralEncoding() *huffmanEncoder {
+	h := newHuffmanEncoder(maxLit)
+	codeBits := h.codeBits
+	code := h.code
+	var ch uint16
+	for ch = 0; ch < maxLit; ch++ {
+		var bits uint16
+		var size uint8
+		switch {
+		case ch < 144:
+			// size 8, 000110000  .. 10111111
+			bits = ch + 48
+			size = 8
+			break
+		case ch < 256:
+			// size 9, 110010000 .. 111111111
+			bits = ch + 400 - 144
+			size = 9
+			break
+		case ch < 280:
+			// size 7, 0000000 .. 0010111
+			bits = ch - 256
+			size = 7
+			break
+		default:
+			// size 8, 11000000 .. 11000111
+			bits = ch + 192 - 280
+			size = 8
+		}
+		codeBits[ch] = size
+		code[ch] = reverseBits(bits, size)
+	}
+	return h
+}
+
+func generateFixedOffsetEncoding() *huffmanEncoder {
+	h := newHuffmanEncoder(30)
+	codeBits := h.codeBits
+	code := h.code
+	for ch := uint16(0); ch < 30; ch++ {
+		codeBits[ch] = 5
+		code[ch] = reverseBits(ch, 5)
+	}
+	return h
+}
+
+var fixedLiteralEncoding *huffmanEncoder = generateFixedLiteralEncoding()
+var fixedOffsetEncoding *huffmanEncoder = generateFixedOffsetEncoding()
+
+func (h *huffmanEncoder) bitLength(freq []int32) int64 {
+	var total int64
+	for i, f := range freq {
+		if f != 0 {
+			total += int64(f) * int64(h.codeBits[i])
+		}
+	}
+	return total
+}
+
+const maxBitsLimit = 16
+
+// Return the number of literals assigned to each bit size in the Huffman encoding
+//
+// This method is only called when list.length >= 3
+// The cases of 0, 1, and 2 literals are handled by special case code.
+//
+// list  An array of the literals with non-zero frequencies
+//             and their associated frequencies.  The array is in order of increasing
+//             frequency, and has as its last element a special element with frequency
+//             MaxInt32
+// maxBits     The maximum number of bits that should be used to encode any literal.
+//             Must be less than 16.
+// return      An integer array in which array[i] indicates the number of literals
+//             that should be encoded in i bits.
+func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 {
+	if maxBits >= maxBitsLimit {
+		panic("flate: maxBits too large")
+	}
+	n := int32(len(list))
+	list = list[0 : n+1]
+	list[n] = maxNode()
+
+	// The tree can't have greater depth than n - 1, no matter what.  This
+	// saves a little bit of work in some small cases
+	if maxBits > n-1 {
+		maxBits = n - 1
+	}
+
+	// Create information about each of the levels.
+	// A bogus "Level 0" whose sole purpose is so that
+	// level1.prev.needed==0.  This makes level1.nextPairFreq
+	// be a legitimate value that never gets chosen.
+	var levels [maxBitsLimit]levelInfo
+	// leafCounts[i] counts the number of literals at the left
+	// of ancestors of the rightmost node at level i.
+	// leafCounts[i][j] is the number of literals at the left
+	// of the level j ancestor.
+	var leafCounts [maxBitsLimit][maxBitsLimit]int32
+
+	for level := int32(1); level <= maxBits; level++ {
+		// For every level, the first two items are the first two characters.
+		// We initialize the levels as if we had already figured this out.
+		levels[level] = levelInfo{
+			level:        level,
+			lastFreq:     list[1].freq,
+			nextCharFreq: list[2].freq,
+			nextPairFreq: list[0].freq + list[1].freq,
+		}
+		leafCounts[level][level] = 2
+		if level == 1 {
+			levels[level].nextPairFreq = math.MaxInt32
+		}
+	}
+
+	// We need a total of 2*n - 2 items at top level and have already generated 2.
+	levels[maxBits].needed = 2*n - 4
+
+	level := maxBits
+	for {
+		l := &levels[level]
+		if l.nextPairFreq == math.MaxInt32 && l.nextCharFreq == math.MaxInt32 {
+			// We've run out of both leafs and pairs.
+			// End all calculations for this level.
+			// To make sure we never come back to this level or any lower level,
+			// set nextPairFreq impossibly large.
+			l.needed = 0
+			levels[level+1].nextPairFreq = math.MaxInt32
+			level++
+			continue
+		}
+
+		prevFreq := l.lastFreq
+		if l.nextCharFreq < l.nextPairFreq {
+			// The next item on this row is a leaf node.
+			n := leafCounts[level][level] + 1
+			l.lastFreq = l.nextCharFreq
+			// Lower leafCounts are the same of the previous node.
+			leafCounts[level][level] = n
+			l.nextCharFreq = list[n].freq
+		} else {
+			// The next item on this row is a pair from the previous row.
+			// nextPairFreq isn't valid until we generate two
+			// more values in the level below
+			l.lastFreq = l.nextPairFreq
+			// Take leaf counts from the lower level, except counts[level] remains the same.
+			copy(leafCounts[level][:level], leafCounts[level-1][:level])
+			levels[l.level-1].needed = 2
+		}
+
+		if l.needed--; l.needed == 0 {
+			// We've done everything we need to do for this level.
+			// Continue calculating one level up.  Fill in nextPairFreq
+			// of that level with the sum of the two nodes we've just calculated on
+			// this level.
+			if l.level == maxBits {
+				// All done!
+				break
+			}
+			levels[l.level+1].nextPairFreq = prevFreq + l.lastFreq
+			level++
+		} else {
+			// If we stole from below, move down temporarily to replenish it.
+			for levels[level-1].needed > 0 {
+				level--
+			}
+		}
+	}
+
+	// Somethings is wrong if at the end, the top level is null or hasn't used
+	// all of the leaves.
+	if leafCounts[maxBits][maxBits] != n {
+		panic("leafCounts[maxBits][maxBits] != n")
+	}
+
+	bitCount := make([]int32, maxBits+1)
+	bits := 1
+	counts := &leafCounts[maxBits]
+	for level := maxBits; level > 0; level-- {
+		// chain.leafCount gives the number of literals requiring at least "bits"
+		// bits to encode.
+		bitCount[bits] = counts[level] - counts[level-1]
+		bits++
+	}
+	return bitCount
+}
+
+// Look at the leaves and assign them a bit count and an encoding as specified
+// in RFC 1951 3.2.2
+func (h *huffmanEncoder) assignEncodingAndSize(bitCount []int32, list []literalNode) {
+	code := uint16(0)
+	for n, bits := range bitCount {
+		code <<= 1
+		if n == 0 || bits == 0 {
+			continue
+		}
+		// The literals list[len(list)-bits] .. list[len(list)-bits]
+		// are encoded using "bits" bits, and get the values
+		// code, code + 1, ....  The code values are
+		// assigned in literal order (not frequency order).
+		chunk := list[len(list)-int(bits):]
+		sortByLiteral(chunk)
+		for _, node := range chunk {
+			h.codeBits[node.literal] = uint8(n)
+			h.code[node.literal] = reverseBits(code, uint8(n))
+			code++
+		}
+		list = list[0 : len(list)-int(bits)]
+	}
+}
+
+// Update this Huffman Code object to be the minimum code for the specified frequency count.
+//
+// freq  An array of frequencies, in which frequency[i] gives the frequency of literal i.
+// maxBits  The maximum number of bits to use for any literal.
+func (h *huffmanEncoder) generate(freq []int32, maxBits int32) {
+	list := make([]literalNode, len(freq)+1)
+	// Number of non-zero literals
+	count := 0
+	// Set list to be the set of all non-zero literals and their frequencies
+	for i, f := range freq {
+		if f != 0 {
+			list[count] = literalNode{uint16(i), f}
+			count++
+		} else {
+			h.codeBits[i] = 0
+		}
+	}
+	// If freq[] is shorter than codeBits[], fill rest of codeBits[] with zeros
+	h.codeBits = h.codeBits[0:len(freq)]
+	list = list[0:count]
+	if count <= 2 {
+		// Handle the small cases here, because they are awkward for the general case code.  With
+		// two or fewer literals, everything has bit length 1.
+		for i, node := range list {
+			// "list" is in order of increasing literal value.
+			h.codeBits[node.literal] = 1
+			h.code[node.literal] = uint16(i)
+		}
+		return
+	}
+	sortByFreq(list)
+
+	// Get the number of literals for each bit count
+	bitCount := h.bitCounts(list, maxBits)
+	// And do the assignment
+	h.assignEncodingAndSize(bitCount, list)
+}
+
+type literalNodeSorter struct {
+	a    []literalNode
+	less func(i, j int) bool
+}
+
+func (s literalNodeSorter) Len() int { return len(s.a) }
+
+func (s literalNodeSorter) Less(i, j int) bool {
+	return s.less(i, j)
+}
+
+func (s literalNodeSorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] }
+
+func sortByFreq(a []literalNode) {
+	s := &literalNodeSorter{a, func(i, j int) bool {
+		if a[i].freq == a[j].freq {
+			return a[i].literal < a[j].literal
+		}
+		return a[i].freq < a[j].freq
+	}}
+	sort.Sort(s)
+}
+
+func sortByLiteral(a []literalNode) {
+	s := &literalNodeSorter{a, func(i, j int) bool { return a[i].literal < a[j].literal }}
+	sort.Sort(s)
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/inflate.go b/third_party/gofrontend/libgo/go/compress/flate/inflate.go
new file mode 100644
index 0000000..ce4923e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/inflate.go
@@ -0,0 +1,708 @@
+// 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 flate implements the DEFLATE compressed data format, described in
+// RFC 1951.  The gzip and zlib packages implement access to DEFLATE-based file
+// formats.
+package flate
+
+import (
+	"bufio"
+	"io"
+	"strconv"
+)
+
+const (
+	maxCodeLen = 16    // max length of Huffman code
+	maxHist    = 32768 // max history required
+	// The next three numbers come from the RFC, section 3.2.7.
+	maxLit   = 286
+	maxDist  = 32
+	numCodes = 19 // number of codes in Huffman meta-code
+)
+
+// A CorruptInputError reports the presence of corrupt input at a given offset.
+type CorruptInputError int64
+
+func (e CorruptInputError) Error() string {
+	return "flate: corrupt input before offset " + strconv.FormatInt(int64(e), 10)
+}
+
+// An InternalError reports an error in the flate code itself.
+type InternalError string
+
+func (e InternalError) Error() string { return "flate: internal error: " + string(e) }
+
+// A ReadError reports an error encountered while reading input.
+type ReadError struct {
+	Offset int64 // byte offset where error occurred
+	Err    error // error returned by underlying Read
+}
+
+func (e *ReadError) Error() string {
+	return "flate: read error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
+}
+
+// A WriteError reports an error encountered while writing output.
+type WriteError struct {
+	Offset int64 // byte offset where error occurred
+	Err    error // error returned by underlying Write
+}
+
+func (e *WriteError) Error() string {
+	return "flate: write error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
+}
+
+// Note that much of the implementation of huffmanDecoder is also copied
+// into gen.go (in package main) for the purpose of precomputing the
+// fixed huffman tables so they can be included statically.
+
+// The data structure for decoding Huffman tables is based on that of
+// zlib. There is a lookup table of a fixed bit width (huffmanChunkBits),
+// For codes smaller than the table width, there are multiple entries
+// (each combination of trailing bits has the same value). For codes
+// larger than the table width, the table contains a link to an overflow
+// table. The width of each entry in the link table is the maximum code
+// size minus the chunk width.
+
+// Note that you can do a lookup in the table even without all bits
+// filled. Since the extra bits are zero, and the DEFLATE Huffman codes
+// have the property that shorter codes come before longer ones, the
+// bit length estimate in the result is a lower bound on the actual
+// number of bits.
+
+// chunk & 15 is number of bits
+// chunk >> 4 is value, including table link
+
+const (
+	huffmanChunkBits  = 9
+	huffmanNumChunks  = 1 << huffmanChunkBits
+	huffmanCountMask  = 15
+	huffmanValueShift = 4
+)
+
+type huffmanDecoder struct {
+	min      int                      // the minimum code length
+	chunks   [huffmanNumChunks]uint32 // chunks as described above
+	links    [][]uint32               // overflow links
+	linkMask uint32                   // mask the width of the link table
+}
+
+// Initialize Huffman decoding tables from array of code lengths.
+func (h *huffmanDecoder) init(bits []int) bool {
+	if h.min != 0 {
+		*h = huffmanDecoder{}
+	}
+
+	// Count number of codes of each length,
+	// compute min and max length.
+	var count [maxCodeLen]int
+	var min, max int
+	for _, n := range bits {
+		if n == 0 {
+			continue
+		}
+		if min == 0 || n < min {
+			min = n
+		}
+		if n > max {
+			max = n
+		}
+		count[n]++
+	}
+	if max == 0 {
+		return false
+	}
+
+	h.min = min
+	var linkBits uint
+	var numLinks int
+	if max > huffmanChunkBits {
+		linkBits = uint(max) - huffmanChunkBits
+		numLinks = 1 << linkBits
+		h.linkMask = uint32(numLinks - 1)
+	}
+	code := 0
+	var nextcode [maxCodeLen]int
+	for i := min; i <= max; i++ {
+		if i == huffmanChunkBits+1 {
+			// create link tables
+			link := code >> 1
+			if huffmanNumChunks < link {
+				return false
+			}
+			h.links = make([][]uint32, huffmanNumChunks-link)
+			for j := uint(link); j < huffmanNumChunks; j++ {
+				reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8
+				reverse >>= uint(16 - huffmanChunkBits)
+				off := j - uint(link)
+				h.chunks[reverse] = uint32(off<<huffmanValueShift + uint(i))
+				h.links[off] = make([]uint32, 1<<linkBits)
+			}
+		}
+		n := count[i]
+		nextcode[i] = code
+		code += n
+		code <<= 1
+	}
+
+	for i, n := range bits {
+		if n == 0 {
+			continue
+		}
+		code := nextcode[n]
+		nextcode[n]++
+		chunk := uint32(i<<huffmanValueShift | n)
+		reverse := int(reverseByte[code>>8]) | int(reverseByte[code&0xff])<<8
+		reverse >>= uint(16 - n)
+		if n <= huffmanChunkBits {
+			for off := reverse; off < huffmanNumChunks; off += 1 << uint(n) {
+				h.chunks[off] = chunk
+			}
+		} else {
+			value := h.chunks[reverse&(huffmanNumChunks-1)] >> huffmanValueShift
+			if value >= uint32(len(h.links)) {
+				return false
+			}
+			linktab := h.links[value]
+			reverse >>= huffmanChunkBits
+			for off := reverse; off < numLinks; off += 1 << uint(n-huffmanChunkBits) {
+				linktab[off] = chunk
+			}
+		}
+	}
+	return true
+}
+
+// The actual read interface needed by NewReader.
+// If the passed in io.Reader does not also have ReadByte,
+// the NewReader will introduce its own buffering.
+type Reader interface {
+	io.Reader
+	io.ByteReader
+}
+
+// Decompress state.
+type decompressor struct {
+	// Input source.
+	r       Reader
+	roffset int64
+	woffset int64
+
+	// Input bits, in top of b.
+	b  uint32
+	nb uint
+
+	// Huffman decoders for literal/length, distance.
+	h1, h2 huffmanDecoder
+
+	// Length arrays used to define Huffman codes.
+	bits     *[maxLit + maxDist]int
+	codebits *[numCodes]int
+
+	// Output history, buffer.
+	hist  *[maxHist]byte
+	hp    int  // current output position in buffer
+	hw    int  // have written hist[0:hw] already
+	hfull bool // buffer has filled at least once
+
+	// Temporary buffer (avoids repeated allocation).
+	buf [4]byte
+
+	// Next step in the decompression,
+	// and decompression state.
+	step     func(*decompressor)
+	final    bool
+	err      error
+	toRead   []byte
+	hl, hd   *huffmanDecoder
+	copyLen  int
+	copyDist int
+}
+
+func (f *decompressor) nextBlock() {
+	if f.final {
+		if f.hw != f.hp {
+			f.flush((*decompressor).nextBlock)
+			return
+		}
+		f.err = io.EOF
+		return
+	}
+	for f.nb < 1+2 {
+		if f.err = f.moreBits(); f.err != nil {
+			return
+		}
+	}
+	f.final = f.b&1 == 1
+	f.b >>= 1
+	typ := f.b & 3
+	f.b >>= 2
+	f.nb -= 1 + 2
+	switch typ {
+	case 0:
+		f.dataBlock()
+	case 1:
+		// compressed, fixed Huffman tables
+		f.hl = &fixedHuffmanDecoder
+		f.hd = nil
+		f.huffmanBlock()
+	case 2:
+		// compressed, dynamic Huffman tables
+		if f.err = f.readHuffman(); f.err != nil {
+			break
+		}
+		f.hl = &f.h1
+		f.hd = &f.h2
+		f.huffmanBlock()
+	default:
+		// 3 is reserved.
+		f.err = CorruptInputError(f.roffset)
+	}
+}
+
+func (f *decompressor) Read(b []byte) (int, error) {
+	for {
+		if len(f.toRead) > 0 {
+			n := copy(b, f.toRead)
+			f.toRead = f.toRead[n:]
+			return n, nil
+		}
+		if f.err != nil {
+			return 0, f.err
+		}
+		f.step(f)
+	}
+}
+
+func (f *decompressor) Close() error {
+	if f.err == io.EOF {
+		return nil
+	}
+	return f.err
+}
+
+// RFC 1951 section 3.2.7.
+// Compression with dynamic Huffman codes
+
+var codeOrder = [...]int{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
+
+func (f *decompressor) readHuffman() error {
+	// HLIT[5], HDIST[5], HCLEN[4].
+	for f.nb < 5+5+4 {
+		if err := f.moreBits(); err != nil {
+			return err
+		}
+	}
+	nlit := int(f.b&0x1F) + 257
+	if nlit > maxLit {
+		return CorruptInputError(f.roffset)
+	}
+	f.b >>= 5
+	ndist := int(f.b&0x1F) + 1
+	// maxDist is 32, so ndist is always valid.
+	f.b >>= 5
+	nclen := int(f.b&0xF) + 4
+	// numCodes is 19, so nclen is always valid.
+	f.b >>= 4
+	f.nb -= 5 + 5 + 4
+
+	// (HCLEN+4)*3 bits: code lengths in the magic codeOrder order.
+	for i := 0; i < nclen; i++ {
+		for f.nb < 3 {
+			if err := f.moreBits(); err != nil {
+				return err
+			}
+		}
+		f.codebits[codeOrder[i]] = int(f.b & 0x7)
+		f.b >>= 3
+		f.nb -= 3
+	}
+	for i := nclen; i < len(codeOrder); i++ {
+		f.codebits[codeOrder[i]] = 0
+	}
+	if !f.h1.init(f.codebits[0:]) {
+		return CorruptInputError(f.roffset)
+	}
+
+	// HLIT + 257 code lengths, HDIST + 1 code lengths,
+	// using the code length Huffman code.
+	for i, n := 0, nlit+ndist; i < n; {
+		x, err := f.huffSym(&f.h1)
+		if err != nil {
+			return err
+		}
+		if x < 16 {
+			// Actual length.
+			f.bits[i] = x
+			i++
+			continue
+		}
+		// Repeat previous length or zero.
+		var rep int
+		var nb uint
+		var b int
+		switch x {
+		default:
+			return InternalError("unexpected length code")
+		case 16:
+			rep = 3
+			nb = 2
+			if i == 0 {
+				return CorruptInputError(f.roffset)
+			}
+			b = f.bits[i-1]
+		case 17:
+			rep = 3
+			nb = 3
+			b = 0
+		case 18:
+			rep = 11
+			nb = 7
+			b = 0
+		}
+		for f.nb < nb {
+			if err := f.moreBits(); err != nil {
+				return err
+			}
+		}
+		rep += int(f.b & uint32(1<<nb-1))
+		f.b >>= nb
+		f.nb -= nb
+		if i+rep > n {
+			return CorruptInputError(f.roffset)
+		}
+		for j := 0; j < rep; j++ {
+			f.bits[i] = b
+			i++
+		}
+	}
+
+	if !f.h1.init(f.bits[0:nlit]) || !f.h2.init(f.bits[nlit:nlit+ndist]) {
+		return CorruptInputError(f.roffset)
+	}
+
+	return nil
+}
+
+// Decode a single Huffman block from f.
+// hl and hd are the Huffman states for the lit/length values
+// and the distance values, respectively.  If hd == nil, using the
+// fixed distance encoding associated with fixed Huffman blocks.
+func (f *decompressor) huffmanBlock() {
+	for {
+		v, err := f.huffSym(f.hl)
+		if err != nil {
+			f.err = err
+			return
+		}
+		var n uint // number of bits extra
+		var length int
+		switch {
+		case v < 256:
+			f.hist[f.hp] = byte(v)
+			f.hp++
+			if f.hp == len(f.hist) {
+				// After the flush, continue this loop.
+				f.flush((*decompressor).huffmanBlock)
+				return
+			}
+			continue
+		case v == 256:
+			// Done with huffman block; read next block.
+			f.step = (*decompressor).nextBlock
+			return
+		// otherwise, reference to older data
+		case v < 265:
+			length = v - (257 - 3)
+			n = 0
+		case v < 269:
+			length = v*2 - (265*2 - 11)
+			n = 1
+		case v < 273:
+			length = v*4 - (269*4 - 19)
+			n = 2
+		case v < 277:
+			length = v*8 - (273*8 - 35)
+			n = 3
+		case v < 281:
+			length = v*16 - (277*16 - 67)
+			n = 4
+		case v < 285:
+			length = v*32 - (281*32 - 131)
+			n = 5
+		default:
+			length = 258
+			n = 0
+		}
+		if n > 0 {
+			for f.nb < n {
+				if err = f.moreBits(); err != nil {
+					f.err = err
+					return
+				}
+			}
+			length += int(f.b & uint32(1<<n-1))
+			f.b >>= n
+			f.nb -= n
+		}
+
+		var dist int
+		if f.hd == nil {
+			for f.nb < 5 {
+				if err = f.moreBits(); err != nil {
+					f.err = err
+					return
+				}
+			}
+			dist = int(reverseByte[(f.b&0x1F)<<3])
+			f.b >>= 5
+			f.nb -= 5
+		} else {
+			if dist, err = f.huffSym(f.hd); err != nil {
+				f.err = err
+				return
+			}
+		}
+
+		switch {
+		case dist < 4:
+			dist++
+		case dist >= 30:
+			f.err = CorruptInputError(f.roffset)
+			return
+		default:
+			nb := uint(dist-2) >> 1
+			// have 1 bit in bottom of dist, need nb more.
+			extra := (dist & 1) << nb
+			for f.nb < nb {
+				if err = f.moreBits(); err != nil {
+					f.err = err
+					return
+				}
+			}
+			extra |= int(f.b & uint32(1<<nb-1))
+			f.b >>= nb
+			f.nb -= nb
+			dist = 1<<(nb+1) + 1 + extra
+		}
+
+		// Copy history[-dist:-dist+length] into output.
+		if dist > len(f.hist) {
+			f.err = InternalError("bad history distance")
+			return
+		}
+
+		// No check on length; encoding can be prescient.
+		if !f.hfull && dist > f.hp {
+			f.err = CorruptInputError(f.roffset)
+			return
+		}
+
+		f.copyLen, f.copyDist = length, dist
+		if f.copyHist() {
+			return
+		}
+	}
+}
+
+// copyHist copies f.copyLen bytes from f.hist (f.copyDist bytes ago) to itself.
+// It reports whether the f.hist buffer is full.
+func (f *decompressor) copyHist() bool {
+	p := f.hp - f.copyDist
+	if p < 0 {
+		p += len(f.hist)
+	}
+	for f.copyLen > 0 {
+		n := f.copyLen
+		if x := len(f.hist) - f.hp; n > x {
+			n = x
+		}
+		if x := len(f.hist) - p; n > x {
+			n = x
+		}
+		forwardCopy(f.hist[:], f.hp, p, n)
+		p += n
+		f.hp += n
+		f.copyLen -= n
+		if f.hp == len(f.hist) {
+			// After flush continue copying out of history.
+			f.flush((*decompressor).copyHuff)
+			return true
+		}
+		if p == len(f.hist) {
+			p = 0
+		}
+	}
+	return false
+}
+
+func (f *decompressor) copyHuff() {
+	if f.copyHist() {
+		return
+	}
+	f.huffmanBlock()
+}
+
+// Copy a single uncompressed data block from input to output.
+func (f *decompressor) dataBlock() {
+	// Uncompressed.
+	// Discard current half-byte.
+	f.nb = 0
+	f.b = 0
+
+	// Length then ones-complement of length.
+	nr, err := io.ReadFull(f.r, f.buf[0:4])
+	f.roffset += int64(nr)
+	if err != nil {
+		f.err = &ReadError{f.roffset, err}
+		return
+	}
+	n := int(f.buf[0]) | int(f.buf[1])<<8
+	nn := int(f.buf[2]) | int(f.buf[3])<<8
+	if uint16(nn) != uint16(^n) {
+		f.err = CorruptInputError(f.roffset)
+		return
+	}
+
+	if n == 0 {
+		// 0-length block means sync
+		f.flush((*decompressor).nextBlock)
+		return
+	}
+
+	f.copyLen = n
+	f.copyData()
+}
+
+// copyData copies f.copyLen bytes from the underlying reader into f.hist.
+// It pauses for reads when f.hist is full.
+func (f *decompressor) copyData() {
+	n := f.copyLen
+	for n > 0 {
+		m := len(f.hist) - f.hp
+		if m > n {
+			m = n
+		}
+		m, err := io.ReadFull(f.r, f.hist[f.hp:f.hp+m])
+		f.roffset += int64(m)
+		if err != nil {
+			f.err = &ReadError{f.roffset, err}
+			return
+		}
+		n -= m
+		f.hp += m
+		if f.hp == len(f.hist) {
+			f.copyLen = n
+			f.flush((*decompressor).copyData)
+			return
+		}
+	}
+	f.step = (*decompressor).nextBlock
+}
+
+func (f *decompressor) setDict(dict []byte) {
+	if len(dict) > len(f.hist) {
+		// Will only remember the tail.
+		dict = dict[len(dict)-len(f.hist):]
+	}
+
+	f.hp = copy(f.hist[:], dict)
+	if f.hp == len(f.hist) {
+		f.hp = 0
+		f.hfull = true
+	}
+	f.hw = f.hp
+}
+
+func (f *decompressor) moreBits() error {
+	c, err := f.r.ReadByte()
+	if err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		return err
+	}
+	f.roffset++
+	f.b |= uint32(c) << f.nb
+	f.nb += 8
+	return nil
+}
+
+// Read the next Huffman-encoded symbol from f according to h.
+func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) {
+	n := uint(h.min)
+	for {
+		for f.nb < n {
+			if err := f.moreBits(); err != nil {
+				return 0, err
+			}
+		}
+		chunk := h.chunks[f.b&(huffmanNumChunks-1)]
+		n = uint(chunk & huffmanCountMask)
+		if n > huffmanChunkBits {
+			chunk = h.links[chunk>>huffmanValueShift][(f.b>>huffmanChunkBits)&h.linkMask]
+			n = uint(chunk & huffmanCountMask)
+			if n == 0 {
+				f.err = CorruptInputError(f.roffset)
+				return 0, f.err
+			}
+		}
+		if n <= f.nb {
+			f.b >>= n
+			f.nb -= n
+			return int(chunk >> huffmanValueShift), nil
+		}
+	}
+}
+
+// Flush any buffered output to the underlying writer.
+func (f *decompressor) flush(step func(*decompressor)) {
+	f.toRead = f.hist[f.hw:f.hp]
+	f.woffset += int64(f.hp - f.hw)
+	f.hw = f.hp
+	if f.hp == len(f.hist) {
+		f.hp = 0
+		f.hw = 0
+		f.hfull = true
+	}
+	f.step = step
+}
+
+func makeReader(r io.Reader) Reader {
+	if rr, ok := r.(Reader); ok {
+		return rr
+	}
+	return bufio.NewReader(r)
+}
+
+// NewReader returns a new ReadCloser that can be used
+// to read the uncompressed version of r.  It is the caller's
+// responsibility to call Close on the ReadCloser when
+// finished reading.
+func NewReader(r io.Reader) io.ReadCloser {
+	var f decompressor
+	f.bits = new([maxLit + maxDist]int)
+	f.codebits = new([numCodes]int)
+	f.r = makeReader(r)
+	f.hist = new([maxHist]byte)
+	f.step = (*decompressor).nextBlock
+	return &f
+}
+
+// NewReaderDict is like NewReader but initializes the reader
+// with a preset dictionary.  The returned Reader behaves as if
+// the uncompressed data stream started with the given dictionary,
+// which has already been read.  NewReaderDict is typically used
+// to read data compressed by NewWriterDict.
+func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser {
+	var f decompressor
+	f.r = makeReader(r)
+	f.hist = new([maxHist]byte)
+	f.bits = new([maxLit + maxDist]int)
+	f.codebits = new([numCodes]int)
+	f.step = (*decompressor).nextBlock
+	f.setDict(dict)
+	return &f
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/reader_test.go b/third_party/gofrontend/libgo/go/compress/flate/reader_test.go
new file mode 100644
index 0000000..a62ef74
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/reader_test.go
@@ -0,0 +1,96 @@
+// 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 flate
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+func TestNlitOutOfRange(t *testing.T) {
+	// Trying to decode this bogus flate data, which has a Huffman table
+	// with nlit=288, should not panic.
+	io.Copy(ioutil.Discard, NewReader(strings.NewReader(
+		"\xfc\xfe\x36\xe7\x5e\x1c\xef\xb3\x55\x58\x77\xb6\x56\xb5\x43\xf4"+
+			"\x6f\xf2\xd2\xe6\x3d\x99\xa0\x85\x8c\x48\xeb\xf8\xda\x83\x04\x2a"+
+			"\x75\xc4\xf8\x0f\x12\x11\xb9\xb4\x4b\x09\xa0\xbe\x8b\x91\x4c")))
+}
+
+const (
+	digits = iota
+	twain
+)
+
+var testfiles = []string{
+	// Digits is the digits of the irrational number e. Its decimal representation
+	// does not repeat, but there are only 10 possible digits, so it should be
+	// reasonably compressible.
+	digits: "../testdata/e.txt",
+	// Twain is Project Gutenberg's edition of Mark Twain's classic English novel.
+	twain: "../testdata/Mark.Twain-Tom.Sawyer.txt",
+}
+
+func benchmarkDecode(b *testing.B, testfile, level, n int) {
+	b.ReportAllocs()
+	b.StopTimer()
+	b.SetBytes(int64(n))
+	buf0, err := ioutil.ReadFile(testfiles[testfile])
+	if err != nil {
+		b.Fatal(err)
+	}
+	if len(buf0) == 0 {
+		b.Fatalf("test file %q has no data", testfiles[testfile])
+	}
+	compressed := new(bytes.Buffer)
+	w, err := NewWriter(compressed, level)
+	if err != nil {
+		b.Fatal(err)
+	}
+	for i := 0; i < n; i += len(buf0) {
+		if len(buf0) > n-i {
+			buf0 = buf0[:n-i]
+		}
+		io.Copy(w, bytes.NewReader(buf0))
+	}
+	w.Close()
+	buf1 := compressed.Bytes()
+	buf0, compressed, w = nil, nil, nil
+	runtime.GC()
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		io.Copy(ioutil.Discard, NewReader(bytes.NewReader(buf1)))
+	}
+}
+
+// These short names are so that gofmt doesn't break the BenchmarkXxx function
+// bodies below over multiple lines.
+const (
+	speed    = BestSpeed
+	default_ = DefaultCompression
+	compress = BestCompression
+)
+
+func BenchmarkDecodeDigitsSpeed1e4(b *testing.B)    { benchmarkDecode(b, digits, speed, 1e4) }
+func BenchmarkDecodeDigitsSpeed1e5(b *testing.B)    { benchmarkDecode(b, digits, speed, 1e5) }
+func BenchmarkDecodeDigitsSpeed1e6(b *testing.B)    { benchmarkDecode(b, digits, speed, 1e6) }
+func BenchmarkDecodeDigitsDefault1e4(b *testing.B)  { benchmarkDecode(b, digits, default_, 1e4) }
+func BenchmarkDecodeDigitsDefault1e5(b *testing.B)  { benchmarkDecode(b, digits, default_, 1e5) }
+func BenchmarkDecodeDigitsDefault1e6(b *testing.B)  { benchmarkDecode(b, digits, default_, 1e6) }
+func BenchmarkDecodeDigitsCompress1e4(b *testing.B) { benchmarkDecode(b, digits, compress, 1e4) }
+func BenchmarkDecodeDigitsCompress1e5(b *testing.B) { benchmarkDecode(b, digits, compress, 1e5) }
+func BenchmarkDecodeDigitsCompress1e6(b *testing.B) { benchmarkDecode(b, digits, compress, 1e6) }
+func BenchmarkDecodeTwainSpeed1e4(b *testing.B)     { benchmarkDecode(b, twain, speed, 1e4) }
+func BenchmarkDecodeTwainSpeed1e5(b *testing.B)     { benchmarkDecode(b, twain, speed, 1e5) }
+func BenchmarkDecodeTwainSpeed1e6(b *testing.B)     { benchmarkDecode(b, twain, speed, 1e6) }
+func BenchmarkDecodeTwainDefault1e4(b *testing.B)   { benchmarkDecode(b, twain, default_, 1e4) }
+func BenchmarkDecodeTwainDefault1e5(b *testing.B)   { benchmarkDecode(b, twain, default_, 1e5) }
+func BenchmarkDecodeTwainDefault1e6(b *testing.B)   { benchmarkDecode(b, twain, default_, 1e6) }
+func BenchmarkDecodeTwainCompress1e4(b *testing.B)  { benchmarkDecode(b, twain, compress, 1e4) }
+func BenchmarkDecodeTwainCompress1e5(b *testing.B)  { benchmarkDecode(b, twain, compress, 1e5) }
+func BenchmarkDecodeTwainCompress1e6(b *testing.B)  { benchmarkDecode(b, twain, compress, 1e6) }
diff --git a/third_party/gofrontend/libgo/go/compress/flate/reverse_bits.go b/third_party/gofrontend/libgo/go/compress/flate/reverse_bits.go
new file mode 100644
index 0000000..c1a0272
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/reverse_bits.go
@@ -0,0 +1,48 @@
+// 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 flate
+
+var reverseByte = [256]byte{
+	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+}
+
+func reverseUint16(v uint16) uint16 {
+	return uint16(reverseByte[v>>8]) | uint16(reverseByte[v&0xFF])<<8
+}
+
+func reverseBits(number uint16, bitLength byte) uint16 {
+	return reverseUint16(number << uint8(16-bitLength))
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/token.go b/third_party/gofrontend/libgo/go/compress/flate/token.go
new file mode 100644
index 0000000..4d49176
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/token.go
@@ -0,0 +1,102 @@
+// 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 flate
+
+const (
+	// 2 bits:   type   0 = literal  1=EOF  2=Match   3=Unused
+	// 8 bits:   xlength = length - MIN_MATCH_LENGTH
+	// 22 bits   xoffset = offset - MIN_OFFSET_SIZE, or literal
+	lengthShift = 22
+	offsetMask  = 1<<lengthShift - 1
+	typeMask    = 3 << 30
+	literalType = 0 << 30
+	matchType   = 1 << 30
+)
+
+// The length code for length X (MIN_MATCH_LENGTH <= X <= MAX_MATCH_LENGTH)
+// is lengthCodes[length - MIN_MATCH_LENGTH]
+var lengthCodes = [...]uint32{
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
+	9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+	13, 13, 13, 13, 14, 14, 14, 14, 15, 15,
+	15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+	17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
+	18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+	19, 19, 19, 19, 20, 20, 20, 20, 20, 20,
+	20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+	22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+	23, 23, 23, 23, 23, 23, 23, 23, 24, 24,
+	24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+	26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+	26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+	26, 26, 26, 26, 27, 27, 27, 27, 27, 27,
+	27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+	27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+	27, 27, 27, 27, 27, 28,
+}
+
+var offsetCodes = [...]uint32{
+	0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
+	10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+	11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+	12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+	12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+	14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+	14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+	14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+	14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+	15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+	15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+	15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+	15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+}
+
+type token uint32
+
+// Convert a literal into a literal token.
+func literalToken(literal uint32) token { return token(literalType + literal) }
+
+// Convert a < xlength, xoffset > pair into a match token.
+func matchToken(xlength uint32, xoffset uint32) token {
+	return token(matchType + xlength<<lengthShift + xoffset)
+}
+
+// Returns the type of a token
+func (t token) typ() uint32 { return uint32(t) & typeMask }
+
+// Returns the literal of a literal token
+func (t token) literal() uint32 { return uint32(t - literalType) }
+
+// Returns the extra offset of a match token
+func (t token) offset() uint32 { return uint32(t) & offsetMask }
+
+func (t token) length() uint32 { return uint32((t - matchType) >> lengthShift) }
+
+func lengthCode(len uint32) uint32 { return lengthCodes[len] }
+
+// Returns the offset code corresponding to a specific offset
+func offsetCode(off uint32) uint32 {
+	const n = uint32(len(offsetCodes))
+	switch {
+	case off < n:
+		return offsetCodes[off]
+	case off>>7 < n:
+		return offsetCodes[off>>7] + 14
+	default:
+		return offsetCodes[off>>14] + 28
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/flate/writer_test.go b/third_party/gofrontend/libgo/go/compress/flate/writer_test.go
new file mode 100644
index 0000000..5843177
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/flate/writer_test.go
@@ -0,0 +1,60 @@
+// 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 flate
+
+import (
+	"io/ioutil"
+	"runtime"
+	"testing"
+)
+
+func benchmarkEncoder(b *testing.B, testfile, level, n int) {
+	b.StopTimer()
+	b.SetBytes(int64(n))
+	buf0, err := ioutil.ReadFile(testfiles[testfile])
+	if err != nil {
+		b.Fatal(err)
+	}
+	if len(buf0) == 0 {
+		b.Fatalf("test file %q has no data", testfiles[testfile])
+	}
+	buf1 := make([]byte, n)
+	for i := 0; i < n; i += len(buf0) {
+		if len(buf0) > n-i {
+			buf0 = buf0[:n-i]
+		}
+		copy(buf1[i:], buf0)
+	}
+	buf0 = nil
+	runtime.GC()
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		w, err := NewWriter(ioutil.Discard, level)
+		if err != nil {
+			b.Fatal(err)
+		}
+		w.Write(buf1)
+		w.Close()
+	}
+}
+
+func BenchmarkEncodeDigitsSpeed1e4(b *testing.B)    { benchmarkEncoder(b, digits, speed, 1e4) }
+func BenchmarkEncodeDigitsSpeed1e5(b *testing.B)    { benchmarkEncoder(b, digits, speed, 1e5) }
+func BenchmarkEncodeDigitsSpeed1e6(b *testing.B)    { benchmarkEncoder(b, digits, speed, 1e6) }
+func BenchmarkEncodeDigitsDefault1e4(b *testing.B)  { benchmarkEncoder(b, digits, default_, 1e4) }
+func BenchmarkEncodeDigitsDefault1e5(b *testing.B)  { benchmarkEncoder(b, digits, default_, 1e5) }
+func BenchmarkEncodeDigitsDefault1e6(b *testing.B)  { benchmarkEncoder(b, digits, default_, 1e6) }
+func BenchmarkEncodeDigitsCompress1e4(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e4) }
+func BenchmarkEncodeDigitsCompress1e5(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e5) }
+func BenchmarkEncodeDigitsCompress1e6(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e6) }
+func BenchmarkEncodeTwainSpeed1e4(b *testing.B)     { benchmarkEncoder(b, twain, speed, 1e4) }
+func BenchmarkEncodeTwainSpeed1e5(b *testing.B)     { benchmarkEncoder(b, twain, speed, 1e5) }
+func BenchmarkEncodeTwainSpeed1e6(b *testing.B)     { benchmarkEncoder(b, twain, speed, 1e6) }
+func BenchmarkEncodeTwainDefault1e4(b *testing.B)   { benchmarkEncoder(b, twain, default_, 1e4) }
+func BenchmarkEncodeTwainDefault1e5(b *testing.B)   { benchmarkEncoder(b, twain, default_, 1e5) }
+func BenchmarkEncodeTwainDefault1e6(b *testing.B)   { benchmarkEncoder(b, twain, default_, 1e6) }
+func BenchmarkEncodeTwainCompress1e4(b *testing.B)  { benchmarkEncoder(b, twain, compress, 1e4) }
+func BenchmarkEncodeTwainCompress1e5(b *testing.B)  { benchmarkEncoder(b, twain, compress, 1e5) }
+func BenchmarkEncodeTwainCompress1e6(b *testing.B)  { benchmarkEncoder(b, twain, compress, 1e6) }
diff --git a/third_party/gofrontend/libgo/go/compress/gzip/gunzip.go b/third_party/gofrontend/libgo/go/compress/gzip/gunzip.go
new file mode 100644
index 0000000..4f398b1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/gzip/gunzip.go
@@ -0,0 +1,255 @@
+// 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 gzip implements reading and writing of gzip format compressed files,
+// as specified in RFC 1952.
+package gzip
+
+import (
+	"bufio"
+	"compress/flate"
+	"errors"
+	"hash"
+	"hash/crc32"
+	"io"
+	"time"
+)
+
+const (
+	gzipID1     = 0x1f
+	gzipID2     = 0x8b
+	gzipDeflate = 8
+	flagText    = 1 << 0
+	flagHdrCrc  = 1 << 1
+	flagExtra   = 1 << 2
+	flagName    = 1 << 3
+	flagComment = 1 << 4
+)
+
+func makeReader(r io.Reader) flate.Reader {
+	if rr, ok := r.(flate.Reader); ok {
+		return rr
+	}
+	return bufio.NewReader(r)
+}
+
+var (
+	// ErrChecksum is returned when reading GZIP data that has an invalid checksum.
+	ErrChecksum = errors.New("gzip: invalid checksum")
+	// ErrHeader is returned when reading GZIP data that has an invalid header.
+	ErrHeader = errors.New("gzip: invalid header")
+)
+
+// The gzip file stores a header giving metadata about the compressed file.
+// That header is exposed as the fields of the Writer and Reader structs.
+type Header struct {
+	Comment string    // comment
+	Extra   []byte    // "extra data"
+	ModTime time.Time // modification time
+	Name    string    // file name
+	OS      byte      // operating system type
+}
+
+// A Reader is an io.Reader that can be read to retrieve
+// uncompressed data from a gzip-format compressed file.
+//
+// In general, a gzip file can be a concatenation of gzip files,
+// each with its own header.  Reads from the Reader
+// return the concatenation of the uncompressed data of each.
+// Only the first header is recorded in the Reader fields.
+//
+// Gzip files store a length and checksum of the uncompressed data.
+// The Reader will return a ErrChecksum when Read
+// reaches the end of the uncompressed data if it does not
+// have the expected length or checksum.  Clients should treat data
+// returned by Read as tentative until they receive the io.EOF
+// marking the end of the data.
+type Reader struct {
+	Header
+	r            flate.Reader
+	decompressor io.ReadCloser
+	digest       hash.Hash32
+	size         uint32
+	flg          byte
+	buf          [512]byte
+	err          error
+}
+
+// NewReader creates a new Reader reading the given reader.
+// The implementation buffers input and may read more data than necessary from r.
+// It is the caller's responsibility to call Close on the Reader when done.
+func NewReader(r io.Reader) (*Reader, error) {
+	z := new(Reader)
+	z.r = makeReader(r)
+	z.digest = crc32.NewIEEE()
+	if err := z.readHeader(true); err != nil {
+		return nil, err
+	}
+	return z, nil
+}
+
+// Reset discards the Reader z's state and makes it equivalent to the
+// result of its original state from NewReader, but reading from r instead.
+// This permits reusing a Reader rather than allocating a new one.
+func (z *Reader) Reset(r io.Reader) error {
+	z.r = makeReader(r)
+	if z.digest == nil {
+		z.digest = crc32.NewIEEE()
+	} else {
+		z.digest.Reset()
+	}
+	z.size = 0
+	z.err = nil
+	return z.readHeader(true)
+}
+
+// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
+func get4(p []byte) uint32 {
+	return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
+}
+
+func (z *Reader) readString() (string, error) {
+	var err error
+	needconv := false
+	for i := 0; ; i++ {
+		if i >= len(z.buf) {
+			return "", ErrHeader
+		}
+		z.buf[i], err = z.r.ReadByte()
+		if err != nil {
+			return "", err
+		}
+		if z.buf[i] > 0x7f {
+			needconv = true
+		}
+		if z.buf[i] == 0 {
+			// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
+			if needconv {
+				s := make([]rune, 0, i)
+				for _, v := range z.buf[0:i] {
+					s = append(s, rune(v))
+				}
+				return string(s), nil
+			}
+			return string(z.buf[0:i]), nil
+		}
+	}
+}
+
+func (z *Reader) read2() (uint32, error) {
+	_, err := io.ReadFull(z.r, z.buf[0:2])
+	if err != nil {
+		return 0, err
+	}
+	return uint32(z.buf[0]) | uint32(z.buf[1])<<8, nil
+}
+
+func (z *Reader) readHeader(save bool) error {
+	_, err := io.ReadFull(z.r, z.buf[0:10])
+	if err != nil {
+		return err
+	}
+	if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate {
+		return ErrHeader
+	}
+	z.flg = z.buf[3]
+	if save {
+		z.ModTime = time.Unix(int64(get4(z.buf[4:8])), 0)
+		// z.buf[8] is xfl, ignored
+		z.OS = z.buf[9]
+	}
+	z.digest.Reset()
+	z.digest.Write(z.buf[0:10])
+
+	if z.flg&flagExtra != 0 {
+		n, err := z.read2()
+		if err != nil {
+			return err
+		}
+		data := make([]byte, n)
+		if _, err = io.ReadFull(z.r, data); err != nil {
+			return err
+		}
+		if save {
+			z.Extra = data
+		}
+	}
+
+	var s string
+	if z.flg&flagName != 0 {
+		if s, err = z.readString(); err != nil {
+			return err
+		}
+		if save {
+			z.Name = s
+		}
+	}
+
+	if z.flg&flagComment != 0 {
+		if s, err = z.readString(); err != nil {
+			return err
+		}
+		if save {
+			z.Comment = s
+		}
+	}
+
+	if z.flg&flagHdrCrc != 0 {
+		n, err := z.read2()
+		if err != nil {
+			return err
+		}
+		sum := z.digest.Sum32() & 0xFFFF
+		if n != sum {
+			return ErrHeader
+		}
+	}
+
+	z.digest.Reset()
+	z.decompressor = flate.NewReader(z.r)
+	return nil
+}
+
+func (z *Reader) Read(p []byte) (n int, err error) {
+	if z.err != nil {
+		return 0, z.err
+	}
+	if len(p) == 0 {
+		return 0, nil
+	}
+
+	n, err = z.decompressor.Read(p)
+	z.digest.Write(p[0:n])
+	z.size += uint32(n)
+	if n != 0 || err != io.EOF {
+		z.err = err
+		return
+	}
+
+	// Finished file; check checksum + size.
+	if _, err := io.ReadFull(z.r, z.buf[0:8]); err != nil {
+		z.err = err
+		return 0, err
+	}
+	crc32, isize := get4(z.buf[0:4]), get4(z.buf[4:8])
+	sum := z.digest.Sum32()
+	if sum != crc32 || isize != z.size {
+		z.err = ErrChecksum
+		return 0, z.err
+	}
+
+	// File is ok; is there another?
+	if err = z.readHeader(false); err != nil {
+		z.err = err
+		return
+	}
+
+	// Yes.  Reset and read from it.
+	z.digest.Reset()
+	z.size = 0
+	return z.Read(p)
+}
+
+// Close closes the Reader. It does not close the underlying io.Reader.
+func (z *Reader) Close() error { return z.decompressor.Close() }
diff --git a/third_party/gofrontend/libgo/go/compress/gzip/gunzip_test.go b/third_party/gofrontend/libgo/go/compress/gzip/gunzip_test.go
new file mode 100644
index 0000000..2471038
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/gzip/gunzip_test.go
@@ -0,0 +1,369 @@
+// 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 gzip
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+	"os"
+	"testing"
+	"time"
+)
+
+type gunzipTest struct {
+	name string
+	desc string
+	raw  string
+	gzip []byte
+	err  error
+}
+
+var gunzipTests = []gunzipTest{
+	{ // has 1 empty fixed-huffman block
+		"empty.txt",
+		"empty.txt",
+		"",
+		[]byte{
+			0x1f, 0x8b, 0x08, 0x08, 0xf7, 0x5e, 0x14, 0x4a,
+			0x00, 0x03, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e,
+			0x74, 0x78, 0x74, 0x00, 0x03, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		nil,
+	},
+	{ // has 1 non-empty fixed huffman block
+		"hello.txt",
+		"hello.txt",
+		"hello world\n",
+		[]byte{
+			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
+			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
+			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
+			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
+			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
+			0x00, 0x00,
+		},
+		nil,
+	},
+	{ // concatenation
+		"hello.txt",
+		"hello.txt x2",
+		"hello world\n" +
+			"hello world\n",
+		[]byte{
+			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
+			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
+			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
+			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
+			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
+			0x00, 0x00,
+			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
+			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
+			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
+			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
+			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
+			0x00, 0x00,
+		},
+		nil,
+	},
+	{ // has a fixed huffman block with some length-distance pairs
+		"shesells.txt",
+		"shesells.txt",
+		"she sells seashells by the seashore\n",
+		[]byte{
+			0x1f, 0x8b, 0x08, 0x08, 0x72, 0x66, 0x8b, 0x4a,
+			0x00, 0x03, 0x73, 0x68, 0x65, 0x73, 0x65, 0x6c,
+			0x6c, 0x73, 0x2e, 0x74, 0x78, 0x74, 0x00, 0x2b,
+			0xce, 0x48, 0x55, 0x28, 0x4e, 0xcd, 0xc9, 0x29,
+			0x06, 0x92, 0x89, 0xc5, 0x19, 0x60, 0x56, 0x52,
+			0xa5, 0x42, 0x09, 0x58, 0x18, 0x28, 0x90, 0x5f,
+			0x94, 0xca, 0x05, 0x00, 0x76, 0xb0, 0x3b, 0xeb,
+			0x24, 0x00, 0x00, 0x00,
+		},
+		nil,
+	},
+	{ // has dynamic huffman blocks
+		"gettysburg",
+		"gettysburg",
+		"  Four score and seven years ago our fathers brought forth on\n" +
+			"this continent, a new nation, conceived in Liberty, and dedicated\n" +
+			"to the proposition that all men are created equal.\n" +
+			"  Now we are engaged in a great Civil War, testing whether that\n" +
+			"nation, or any nation so conceived and so dedicated, can long\n" +
+			"endure.\n" +
+			"  We are met on a great battle-field of that war.\n" +
+			"  We have come to dedicate a portion of that field, as a final\n" +
+			"resting place for those who here gave their lives that that\n" +
+			"nation might live.  It is altogether fitting and proper that\n" +
+			"we should do this.\n" +
+			"  But, in a larger sense, we can not dedicate — we can not\n" +
+			"consecrate — we can not hallow — this ground.\n" +
+			"  The brave men, living and dead, who struggled here, have\n" +
+			"consecrated it, far above our poor power to add or detract.\n" +
+			"The world will little note, nor long remember what we say here,\n" +
+			"but it can never forget what they did here.\n" +
+			"  It is for us the living, rather, to be dedicated here to the\n" +
+			"unfinished work which they who fought here have thus far so\n" +
+			"nobly advanced.  It is rather for us to be here dedicated to\n" +
+			"the great task remaining before us — that from these honored\n" +
+			"dead we take increased devotion to that cause for which they\n" +
+			"gave the last full measure of devotion —\n" +
+			"  that we here highly resolve that these dead shall not have\n" +
+			"died in vain — that this nation, under God, shall have a new\n" +
+			"birth of freedom — and that government of the people, by the\n" +
+			"people, for the people, shall not perish from this earth.\n" +
+			"\n" +
+			"Abraham Lincoln, November 19, 1863, Gettysburg, Pennsylvania\n",
+		[]byte{
+			0x1f, 0x8b, 0x08, 0x08, 0xd1, 0x12, 0x2b, 0x4a,
+			0x00, 0x03, 0x67, 0x65, 0x74, 0x74, 0x79, 0x73,
+			0x62, 0x75, 0x72, 0x67, 0x00, 0x65, 0x54, 0xcd,
+			0x6e, 0xd4, 0x30, 0x10, 0xbe, 0xfb, 0x29, 0xe6,
+			0x01, 0x42, 0xa5, 0x0a, 0x09, 0xc1, 0x11, 0x90,
+			0x40, 0x48, 0xa8, 0xe2, 0x80, 0xd4, 0xf3, 0x24,
+			0x9e, 0x24, 0x56, 0xbd, 0x9e, 0xc5, 0x76, 0x76,
+			0x95, 0x1b, 0x0f, 0xc1, 0x13, 0xf2, 0x24, 0x7c,
+			0x63, 0x77, 0x9b, 0x4a, 0x5c, 0xaa, 0x6e, 0x6c,
+			0xcf, 0x7c, 0x7f, 0x33, 0x44, 0x5f, 0x74, 0xcb,
+			0x54, 0x26, 0xcd, 0x42, 0x9c, 0x3c, 0x15, 0xb9,
+			0x48, 0xa2, 0x5d, 0x38, 0x17, 0xe2, 0x45, 0xc9,
+			0x4e, 0x67, 0xae, 0xab, 0xe0, 0xf7, 0x98, 0x75,
+			0x5b, 0xd6, 0x4a, 0xb3, 0xe6, 0xba, 0x92, 0x26,
+			0x57, 0xd7, 0x50, 0x68, 0xd2, 0x54, 0x43, 0x92,
+			0x54, 0x07, 0x62, 0x4a, 0x72, 0xa5, 0xc4, 0x35,
+			0x68, 0x1a, 0xec, 0x60, 0x92, 0x70, 0x11, 0x4f,
+			0x21, 0xd1, 0xf7, 0x30, 0x4a, 0xae, 0xfb, 0xd0,
+			0x9a, 0x78, 0xf1, 0x61, 0xe2, 0x2a, 0xde, 0x55,
+			0x25, 0xd4, 0xa6, 0x73, 0xd6, 0xb3, 0x96, 0x60,
+			0xef, 0xf0, 0x9b, 0x2b, 0x71, 0x8c, 0x74, 0x02,
+			0x10, 0x06, 0xac, 0x29, 0x8b, 0xdd, 0x25, 0xf9,
+			0xb5, 0x71, 0xbc, 0x73, 0x44, 0x0f, 0x7a, 0xa5,
+			0xab, 0xb4, 0x33, 0x49, 0x0b, 0x2f, 0xbd, 0x03,
+			0xd3, 0x62, 0x17, 0xe9, 0x73, 0xb8, 0x84, 0x48,
+			0x8f, 0x9c, 0x07, 0xaa, 0x52, 0x00, 0x6d, 0xa1,
+			0xeb, 0x2a, 0xc6, 0xa0, 0x95, 0x76, 0x37, 0x78,
+			0x9a, 0x81, 0x65, 0x7f, 0x46, 0x4b, 0x45, 0x5f,
+			0xe1, 0x6d, 0x42, 0xe8, 0x01, 0x13, 0x5c, 0x38,
+			0x51, 0xd4, 0xb4, 0x38, 0x49, 0x7e, 0xcb, 0x62,
+			0x28, 0x1e, 0x3b, 0x82, 0x93, 0x54, 0x48, 0xf1,
+			0xd2, 0x7d, 0xe4, 0x5a, 0xa3, 0xbc, 0x99, 0x83,
+			0x44, 0x4f, 0x3a, 0x77, 0x36, 0x57, 0xce, 0xcf,
+			0x2f, 0x56, 0xbe, 0x80, 0x90, 0x9e, 0x84, 0xea,
+			0x51, 0x1f, 0x8f, 0xcf, 0x90, 0xd4, 0x60, 0xdc,
+			0x5e, 0xb4, 0xf7, 0x10, 0x0b, 0x26, 0xe0, 0xff,
+			0xc4, 0xd1, 0xe5, 0x67, 0x2e, 0xe7, 0xc8, 0x93,
+			0x98, 0x05, 0xb8, 0xa8, 0x45, 0xc0, 0x4d, 0x09,
+			0xdc, 0x84, 0x16, 0x2b, 0x0d, 0x9a, 0x21, 0x53,
+			0x04, 0x8b, 0xd2, 0x0b, 0xbd, 0xa2, 0x4c, 0xa7,
+			0x60, 0xee, 0xd9, 0xe1, 0x1d, 0xd1, 0xb7, 0x4a,
+			0x30, 0x8f, 0x63, 0xd5, 0xa5, 0x8b, 0x33, 0x87,
+			0xda, 0x1a, 0x18, 0x79, 0xf3, 0xe3, 0xa6, 0x17,
+			0x94, 0x2e, 0xab, 0x6e, 0xa0, 0xe3, 0xcd, 0xac,
+			0x50, 0x8c, 0xca, 0xa7, 0x0d, 0x76, 0x37, 0xd1,
+			0x23, 0xe7, 0x05, 0x57, 0x8b, 0xa4, 0x22, 0x83,
+			0xd9, 0x62, 0x52, 0x25, 0xad, 0x07, 0xbb, 0xbf,
+			0xbf, 0xff, 0xbc, 0xfa, 0xee, 0x20, 0x73, 0x91,
+			0x29, 0xff, 0x7f, 0x02, 0x71, 0x62, 0x84, 0xb5,
+			0xf6, 0xb5, 0x25, 0x6b, 0x41, 0xde, 0x92, 0xb7,
+			0x76, 0x3f, 0x91, 0x91, 0x31, 0x1b, 0x41, 0x84,
+			0x62, 0x30, 0x0a, 0x37, 0xa4, 0x5e, 0x18, 0x3a,
+			0x99, 0x08, 0xa5, 0xe6, 0x6d, 0x59, 0x22, 0xec,
+			0x33, 0x39, 0x86, 0x26, 0xf5, 0xab, 0x66, 0xc8,
+			0x08, 0x20, 0xcf, 0x0c, 0xd7, 0x47, 0x45, 0x21,
+			0x0b, 0xf6, 0x59, 0xd5, 0xfe, 0x5c, 0x8d, 0xaa,
+			0x12, 0x7b, 0x6f, 0xa1, 0xf0, 0x52, 0x33, 0x4f,
+			0xf5, 0xce, 0x59, 0xd3, 0xab, 0x66, 0x10, 0xbf,
+			0x06, 0xc4, 0x31, 0x06, 0x73, 0xd6, 0x80, 0xa2,
+			0x78, 0xc2, 0x45, 0xcb, 0x03, 0x65, 0x39, 0xc9,
+			0x09, 0xd1, 0x06, 0x04, 0x33, 0x1a, 0x5a, 0xf1,
+			0xde, 0x01, 0xb8, 0x71, 0x83, 0xc4, 0xb5, 0xb3,
+			0xc3, 0x54, 0x65, 0x33, 0x0d, 0x5a, 0xf7, 0x9b,
+			0x90, 0x7c, 0x27, 0x1f, 0x3a, 0x58, 0xa3, 0xd8,
+			0xfd, 0x30, 0x5f, 0xb7, 0xd2, 0x66, 0xa2, 0x93,
+			0x1c, 0x28, 0xb7, 0xe9, 0x1b, 0x0c, 0xe1, 0x28,
+			0x47, 0x26, 0xbb, 0xe9, 0x7d, 0x7e, 0xdc, 0x96,
+			0x10, 0x92, 0x50, 0x56, 0x7c, 0x06, 0xe2, 0x27,
+			0xb4, 0x08, 0xd3, 0xda, 0x7b, 0x98, 0x34, 0x73,
+			0x9f, 0xdb, 0xf6, 0x62, 0xed, 0x31, 0x41, 0x13,
+			0xd3, 0xa2, 0xa8, 0x4b, 0x3a, 0xc6, 0x1d, 0xe4,
+			0x2f, 0x8c, 0xf8, 0xfb, 0x97, 0x64, 0xf4, 0xb6,
+			0x2f, 0x80, 0x5a, 0xf3, 0x56, 0xe0, 0x40, 0x50,
+			0xd5, 0x19, 0xd0, 0x1e, 0xfc, 0xca, 0xe5, 0xc9,
+			0xd4, 0x60, 0x00, 0x81, 0x2e, 0xa3, 0xcc, 0xb6,
+			0x52, 0xf0, 0xb4, 0xdb, 0x69, 0x99, 0xce, 0x7a,
+			0x32, 0x4c, 0x08, 0xed, 0xaa, 0x10, 0x10, 0xe3,
+			0x6f, 0xee, 0x99, 0x68, 0x95, 0x9f, 0x04, 0x71,
+			0xb2, 0x49, 0x2f, 0x62, 0xa6, 0x5e, 0xb4, 0xef,
+			0x02, 0xed, 0x4f, 0x27, 0xde, 0x4a, 0x0f, 0xfd,
+			0xc1, 0xcc, 0xdd, 0x02, 0x8f, 0x08, 0x16, 0x54,
+			0xdf, 0xda, 0xca, 0xe0, 0x82, 0xf1, 0xb4, 0x31,
+			0x7a, 0xa9, 0x81, 0xfe, 0x90, 0xb7, 0x3e, 0xdb,
+			0xd3, 0x35, 0xc0, 0x20, 0x80, 0x33, 0x46, 0x4a,
+			0x63, 0xab, 0xd1, 0x0d, 0x29, 0xd2, 0xe2, 0x84,
+			0xb8, 0xdb, 0xfa, 0xe9, 0x89, 0x44, 0x86, 0x7c,
+			0xe8, 0x0b, 0xe6, 0x02, 0x6a, 0x07, 0x9b, 0x96,
+			0xd0, 0xdb, 0x2e, 0x41, 0x4c, 0xa1, 0xd5, 0x57,
+			0x45, 0x14, 0xfb, 0xe3, 0xa6, 0x72, 0x5b, 0x87,
+			0x6e, 0x0c, 0x6d, 0x5b, 0xce, 0xe0, 0x2f, 0xe2,
+			0x21, 0x81, 0x95, 0xb0, 0xe8, 0xb6, 0x32, 0x0b,
+			0xb2, 0x98, 0x13, 0x52, 0x5d, 0xfb, 0xec, 0x63,
+			0x17, 0x8a, 0x9e, 0x23, 0x22, 0x36, 0xee, 0xcd,
+			0xda, 0xdb, 0xcf, 0x3e, 0xf1, 0xc7, 0xf1, 0x01,
+			0x12, 0x93, 0x0a, 0xeb, 0x6f, 0xf2, 0x02, 0x15,
+			0x96, 0x77, 0x5d, 0xef, 0x9c, 0xfb, 0x88, 0x91,
+			0x59, 0xf9, 0x84, 0xdd, 0x9b, 0x26, 0x8d, 0x80,
+			0xf9, 0x80, 0x66, 0x2d, 0xac, 0xf7, 0x1f, 0x06,
+			0xba, 0x7f, 0xff, 0xee, 0xed, 0x40, 0x5f, 0xa5,
+			0xd6, 0xbd, 0x8c, 0x5b, 0x46, 0xd2, 0x7e, 0x48,
+			0x4a, 0x65, 0x8f, 0x08, 0x42, 0x60, 0xf7, 0x0f,
+			0xb9, 0x16, 0x0b, 0x0c, 0x1a, 0x06, 0x00, 0x00,
+		},
+		nil,
+	},
+	{ // has 1 non-empty fixed huffman block then garbage
+		"hello.txt",
+		"hello.txt + garbage",
+		"hello world\n",
+		[]byte{
+			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
+			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
+			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
+			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
+			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
+			0x00, 0x00, 'g', 'a', 'r', 'b', 'a', 'g', 'e', '!', '!', '!',
+		},
+		ErrHeader,
+	},
+	{ // has 1 non-empty fixed huffman block not enough header
+		"hello.txt",
+		"hello.txt + garbage",
+		"hello world\n",
+		[]byte{
+			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
+			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
+			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
+			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
+			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
+			0x00, 0x00, gzipID1,
+		},
+		io.ErrUnexpectedEOF,
+	},
+	{ // has 1 non-empty fixed huffman block but corrupt checksum
+		"hello.txt",
+		"hello.txt + corrupt checksum",
+		"hello world\n",
+		[]byte{
+			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
+			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
+			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
+			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
+			0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x00,
+			0x00, 0x00,
+		},
+		ErrChecksum,
+	},
+	{ // has 1 non-empty fixed huffman block but corrupt size
+		"hello.txt",
+		"hello.txt + corrupt size",
+		"hello world\n",
+		[]byte{
+			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
+			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
+			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
+			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
+			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0xff, 0x00,
+			0x00, 0x00,
+		},
+		ErrChecksum,
+	},
+}
+
+func TestDecompressor(t *testing.T) {
+	b := new(bytes.Buffer)
+	for _, tt := range gunzipTests {
+		in := bytes.NewReader(tt.gzip)
+		gzip, err := NewReader(in)
+		if err != nil {
+			t.Errorf("%s: NewReader: %s", tt.name, err)
+			continue
+		}
+		defer gzip.Close()
+		if tt.name != gzip.Name {
+			t.Errorf("%s: got name %s", tt.name, gzip.Name)
+		}
+		b.Reset()
+		n, err := io.Copy(b, gzip)
+		if err != tt.err {
+			t.Errorf("%s: io.Copy: %v want %v", tt.name, err, tt.err)
+		}
+		s := b.String()
+		if s != tt.raw {
+			t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.name, n, s, len(tt.raw), tt.raw)
+		}
+
+		// Test Reader Reset.
+		in = bytes.NewReader(tt.gzip)
+		err = gzip.Reset(in)
+		if err != nil {
+			t.Errorf("%s: Reset: %s", tt.name, err)
+			continue
+		}
+		if tt.name != gzip.Name {
+			t.Errorf("%s: got name %s", tt.name, gzip.Name)
+		}
+		b.Reset()
+		n, err = io.Copy(b, gzip)
+		if err != tt.err {
+			t.Errorf("%s: io.Copy: %v want %v", tt.name, err, tt.err)
+		}
+		s = b.String()
+		if s != tt.raw {
+			t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.name, n, s, len(tt.raw), tt.raw)
+		}
+	}
+}
+
+func TestIssue6550(t *testing.T) {
+	f, err := os.Open("testdata/issue6550.gz")
+	if err != nil {
+		t.Fatal(err)
+	}
+	gzip, err := NewReader(f)
+	if err != nil {
+		t.Fatalf("NewReader(testdata/issue6550.gz): %v", err)
+	}
+	defer gzip.Close()
+	done := make(chan bool, 1)
+	go func() {
+		_, err := io.Copy(ioutil.Discard, gzip)
+		if err == nil {
+			t.Errorf("Copy succeeded")
+		} else {
+			t.Logf("Copy failed (correctly): %v", err)
+		}
+		done <- true
+	}()
+	select {
+	case <-time.After(1 * time.Second):
+		t.Errorf("Copy hung")
+	case <-done:
+		// ok
+	}
+}
+
+func TestInitialReset(t *testing.T) {
+	var r Reader
+	if err := r.Reset(bytes.NewReader(gunzipTests[1].gzip)); err != nil {
+		t.Error(err)
+	}
+	var buf bytes.Buffer
+	if _, err := io.Copy(&buf, &r); err != nil {
+		t.Error(err)
+	}
+	if s := buf.String(); s != gunzipTests[1].raw {
+		t.Errorf("got %q want %q", s, gunzipTests[1].raw)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/gzip/gzip.go b/third_party/gofrontend/libgo/go/compress/gzip/gzip.go
new file mode 100644
index 0000000..5131d12
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/gzip/gzip.go
@@ -0,0 +1,272 @@
+// Copyright 2010 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 gzip
+
+import (
+	"compress/flate"
+	"errors"
+	"fmt"
+	"hash"
+	"hash/crc32"
+	"io"
+)
+
+// These constants are copied from the flate package, so that code that imports
+// "compress/gzip" does not also have to import "compress/flate".
+const (
+	NoCompression      = flate.NoCompression
+	BestSpeed          = flate.BestSpeed
+	BestCompression    = flate.BestCompression
+	DefaultCompression = flate.DefaultCompression
+)
+
+// A Writer is an io.WriteCloser.
+// Writes to a Writer are compressed and written to w.
+type Writer struct {
+	Header
+	w           io.Writer
+	level       int
+	wroteHeader bool
+	compressor  *flate.Writer
+	digest      hash.Hash32
+	size        uint32
+	closed      bool
+	buf         [10]byte
+	err         error
+}
+
+// NewWriter returns a new Writer.
+// Writes to the returned writer are compressed and written to w.
+//
+// It is the caller's responsibility to call Close on the WriteCloser when done.
+// Writes may be buffered and not flushed until Close.
+//
+// Callers that wish to set the fields in Writer.Header must do so before
+// the first call to Write or Close. The Comment and Name header fields are
+// UTF-8 strings in Go, but the underlying format requires NUL-terminated ISO
+// 8859-1 (Latin-1). NUL or non-Latin-1 runes in those strings will lead to an
+// error on Write.
+func NewWriter(w io.Writer) *Writer {
+	z, _ := NewWriterLevel(w, DefaultCompression)
+	return z
+}
+
+// NewWriterLevel is like NewWriter but specifies the compression level instead
+// of assuming DefaultCompression.
+//
+// The compression level can be DefaultCompression, NoCompression, or any
+// integer value between BestSpeed and BestCompression inclusive. The error
+// returned will be nil if the level is valid.
+func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
+	if level < DefaultCompression || level > BestCompression {
+		return nil, fmt.Errorf("gzip: invalid compression level: %d", level)
+	}
+	z := new(Writer)
+	z.init(w, level)
+	return z, nil
+}
+
+func (z *Writer) init(w io.Writer, level int) {
+	digest := z.digest
+	if digest != nil {
+		digest.Reset()
+	} else {
+		digest = crc32.NewIEEE()
+	}
+	compressor := z.compressor
+	if compressor != nil {
+		compressor.Reset(w)
+	}
+	*z = Writer{
+		Header: Header{
+			OS: 255, // unknown
+		},
+		w:          w,
+		level:      level,
+		digest:     digest,
+		compressor: compressor,
+	}
+}
+
+// Reset discards the Writer z's state and makes it equivalent to the
+// result of its original state from NewWriter or NewWriterLevel, but
+// writing to w instead. This permits reusing a Writer rather than
+// allocating a new one.
+func (z *Writer) Reset(w io.Writer) {
+	z.init(w, z.level)
+}
+
+// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
+func put2(p []byte, v uint16) {
+	p[0] = uint8(v >> 0)
+	p[1] = uint8(v >> 8)
+}
+
+func put4(p []byte, v uint32) {
+	p[0] = uint8(v >> 0)
+	p[1] = uint8(v >> 8)
+	p[2] = uint8(v >> 16)
+	p[3] = uint8(v >> 24)
+}
+
+// writeBytes writes a length-prefixed byte slice to z.w.
+func (z *Writer) writeBytes(b []byte) error {
+	if len(b) > 0xffff {
+		return errors.New("gzip.Write: Extra data is too large")
+	}
+	put2(z.buf[0:2], uint16(len(b)))
+	_, err := z.w.Write(z.buf[0:2])
+	if err != nil {
+		return err
+	}
+	_, err = z.w.Write(b)
+	return err
+}
+
+// writeString writes a UTF-8 string s in GZIP's format to z.w.
+// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
+func (z *Writer) writeString(s string) (err error) {
+	// GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII.
+	needconv := false
+	for _, v := range s {
+		if v == 0 || v > 0xff {
+			return errors.New("gzip.Write: non-Latin-1 header string")
+		}
+		if v > 0x7f {
+			needconv = true
+		}
+	}
+	if needconv {
+		b := make([]byte, 0, len(s))
+		for _, v := range s {
+			b = append(b, byte(v))
+		}
+		_, err = z.w.Write(b)
+	} else {
+		_, err = io.WriteString(z.w, s)
+	}
+	if err != nil {
+		return err
+	}
+	// GZIP strings are NUL-terminated.
+	z.buf[0] = 0
+	_, err = z.w.Write(z.buf[0:1])
+	return err
+}
+
+// Write writes a compressed form of p to the underlying io.Writer. The
+// compressed bytes are not necessarily flushed until the Writer is closed.
+func (z *Writer) Write(p []byte) (int, error) {
+	if z.err != nil {
+		return 0, z.err
+	}
+	var n int
+	// Write the GZIP header lazily.
+	if !z.wroteHeader {
+		z.wroteHeader = true
+		z.buf[0] = gzipID1
+		z.buf[1] = gzipID2
+		z.buf[2] = gzipDeflate
+		z.buf[3] = 0
+		if z.Extra != nil {
+			z.buf[3] |= 0x04
+		}
+		if z.Name != "" {
+			z.buf[3] |= 0x08
+		}
+		if z.Comment != "" {
+			z.buf[3] |= 0x10
+		}
+		put4(z.buf[4:8], uint32(z.ModTime.Unix()))
+		if z.level == BestCompression {
+			z.buf[8] = 2
+		} else if z.level == BestSpeed {
+			z.buf[8] = 4
+		} else {
+			z.buf[8] = 0
+		}
+		z.buf[9] = z.OS
+		n, z.err = z.w.Write(z.buf[0:10])
+		if z.err != nil {
+			return n, z.err
+		}
+		if z.Extra != nil {
+			z.err = z.writeBytes(z.Extra)
+			if z.err != nil {
+				return n, z.err
+			}
+		}
+		if z.Name != "" {
+			z.err = z.writeString(z.Name)
+			if z.err != nil {
+				return n, z.err
+			}
+		}
+		if z.Comment != "" {
+			z.err = z.writeString(z.Comment)
+			if z.err != nil {
+				return n, z.err
+			}
+		}
+		if z.compressor == nil {
+			z.compressor, _ = flate.NewWriter(z.w, z.level)
+		}
+	}
+	z.size += uint32(len(p))
+	z.digest.Write(p)
+	n, z.err = z.compressor.Write(p)
+	return n, z.err
+}
+
+// Flush flushes any pending compressed data to the underlying writer.
+//
+// It is useful mainly in compressed network protocols, to ensure that
+// a remote reader has enough data to reconstruct a packet. Flush does
+// not return until the data has been written. If the underlying
+// writer returns an error, Flush returns that error.
+//
+// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
+func (z *Writer) Flush() error {
+	if z.err != nil {
+		return z.err
+	}
+	if z.closed {
+		return nil
+	}
+	if !z.wroteHeader {
+		z.Write(nil)
+		if z.err != nil {
+			return z.err
+		}
+	}
+	z.err = z.compressor.Flush()
+	return z.err
+}
+
+// Close closes the Writer, flushing any unwritten data to the underlying
+// io.Writer, but does not close the underlying io.Writer.
+func (z *Writer) Close() error {
+	if z.err != nil {
+		return z.err
+	}
+	if z.closed {
+		return nil
+	}
+	z.closed = true
+	if !z.wroteHeader {
+		z.Write(nil)
+		if z.err != nil {
+			return z.err
+		}
+	}
+	z.err = z.compressor.Close()
+	if z.err != nil {
+		return z.err
+	}
+	put4(z.buf[0:4], z.digest.Sum32())
+	put4(z.buf[4:8], z.size)
+	_, z.err = z.w.Write(z.buf[0:8])
+	return z.err
+}
diff --git a/third_party/gofrontend/libgo/go/compress/gzip/gzip_test.go b/third_party/gofrontend/libgo/go/compress/gzip/gzip_test.go
new file mode 100644
index 0000000..09271b2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/gzip/gzip_test.go
@@ -0,0 +1,231 @@
+// Copyright 2010 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 gzip
+
+import (
+	"bufio"
+	"bytes"
+	"io/ioutil"
+	"testing"
+	"time"
+)
+
+// TestEmpty tests that an empty payload still forms a valid GZIP stream.
+func TestEmpty(t *testing.T) {
+	buf := new(bytes.Buffer)
+
+	if err := NewWriter(buf).Close(); err != nil {
+		t.Fatalf("Writer.Close: %v", err)
+	}
+
+	r, err := NewReader(buf)
+	if err != nil {
+		t.Fatalf("NewReader: %v", err)
+	}
+	b, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Fatalf("ReadAll: %v", err)
+	}
+	if len(b) != 0 {
+		t.Fatalf("got %d bytes, want 0", len(b))
+	}
+	if err := r.Close(); err != nil {
+		t.Fatalf("Reader.Close: %v", err)
+	}
+}
+
+// TestRoundTrip tests that gzipping and then gunzipping is the identity
+// function.
+func TestRoundTrip(t *testing.T) {
+	buf := new(bytes.Buffer)
+
+	w := NewWriter(buf)
+	w.Comment = "comment"
+	w.Extra = []byte("extra")
+	w.ModTime = time.Unix(1e8, 0)
+	w.Name = "name"
+	if _, err := w.Write([]byte("payload")); err != nil {
+		t.Fatalf("Write: %v", err)
+	}
+	if err := w.Close(); err != nil {
+		t.Fatalf("Writer.Close: %v", err)
+	}
+
+	r, err := NewReader(buf)
+	if err != nil {
+		t.Fatalf("NewReader: %v", err)
+	}
+	b, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Fatalf("ReadAll: %v", err)
+	}
+	if string(b) != "payload" {
+		t.Fatalf("payload is %q, want %q", string(b), "payload")
+	}
+	if r.Comment != "comment" {
+		t.Fatalf("comment is %q, want %q", r.Comment, "comment")
+	}
+	if string(r.Extra) != "extra" {
+		t.Fatalf("extra is %q, want %q", r.Extra, "extra")
+	}
+	if r.ModTime.Unix() != 1e8 {
+		t.Fatalf("mtime is %d, want %d", r.ModTime.Unix(), uint32(1e8))
+	}
+	if r.Name != "name" {
+		t.Fatalf("name is %q, want %q", r.Name, "name")
+	}
+	if err := r.Close(); err != nil {
+		t.Fatalf("Reader.Close: %v", err)
+	}
+}
+
+// TestLatin1 tests the internal functions for converting to and from Latin-1.
+func TestLatin1(t *testing.T) {
+	latin1 := []byte{0xc4, 'u', 0xdf, 'e', 'r', 'u', 'n', 'g', 0}
+	utf8 := "Äußerung"
+	z := Reader{r: bufio.NewReader(bytes.NewReader(latin1))}
+	s, err := z.readString()
+	if err != nil {
+		t.Fatalf("readString: %v", err)
+	}
+	if s != utf8 {
+		t.Fatalf("read latin-1: got %q, want %q", s, utf8)
+	}
+
+	buf := bytes.NewBuffer(make([]byte, 0, len(latin1)))
+	c := Writer{w: buf}
+	if err = c.writeString(utf8); err != nil {
+		t.Fatalf("writeString: %v", err)
+	}
+	s = buf.String()
+	if s != string(latin1) {
+		t.Fatalf("write utf-8: got %q, want %q", s, string(latin1))
+	}
+}
+
+// TestLatin1RoundTrip tests that metadata that is representable in Latin-1
+// survives a round trip.
+func TestLatin1RoundTrip(t *testing.T) {
+	testCases := []struct {
+		name string
+		ok   bool
+	}{
+		{"", true},
+		{"ASCII is OK", true},
+		{"unless it contains a NUL\x00", false},
+		{"no matter where \x00 occurs", false},
+		{"\x00\x00\x00", false},
+		{"Látin-1 also passes (U+00E1)", true},
+		{"but LĀtin Extended-A (U+0100) does not", false},
+		{"neither does 日本語", false},
+		{"invalid UTF-8 also \xffails", false},
+		{"\x00 as does Látin-1 with NUL", false},
+	}
+	for _, tc := range testCases {
+		buf := new(bytes.Buffer)
+
+		w := NewWriter(buf)
+		w.Name = tc.name
+		err := w.Close()
+		if (err == nil) != tc.ok {
+			t.Errorf("Writer.Close: name = %q, err = %v", tc.name, err)
+			continue
+		}
+		if !tc.ok {
+			continue
+		}
+
+		r, err := NewReader(buf)
+		if err != nil {
+			t.Errorf("NewReader: %v", err)
+			continue
+		}
+		_, err = ioutil.ReadAll(r)
+		if err != nil {
+			t.Errorf("ReadAll: %v", err)
+			continue
+		}
+		if r.Name != tc.name {
+			t.Errorf("name is %q, want %q", r.Name, tc.name)
+			continue
+		}
+		if err := r.Close(); err != nil {
+			t.Errorf("Reader.Close: %v", err)
+			continue
+		}
+	}
+}
+
+func TestWriterFlush(t *testing.T) {
+	buf := new(bytes.Buffer)
+
+	w := NewWriter(buf)
+	w.Comment = "comment"
+	w.Extra = []byte("extra")
+	w.ModTime = time.Unix(1e8, 0)
+	w.Name = "name"
+
+	n0 := buf.Len()
+	if n0 != 0 {
+		t.Fatalf("buffer size = %d before writes; want 0", n0)
+	}
+
+	if err := w.Flush(); err != nil {
+		t.Fatal(err)
+	}
+
+	n1 := buf.Len()
+	if n1 == 0 {
+		t.Fatal("no data after first flush")
+	}
+
+	w.Write([]byte("x"))
+
+	n2 := buf.Len()
+	if n1 != n2 {
+		t.Fatalf("after writing a single byte, size changed from %d to %d; want no change", n1, n2)
+	}
+
+	if err := w.Flush(); err != nil {
+		t.Fatal(err)
+	}
+
+	n3 := buf.Len()
+	if n2 == n3 {
+		t.Fatal("Flush didn't flush any data")
+	}
+}
+
+// Multiple gzip files concatenated form a valid gzip file.
+func TestConcat(t *testing.T) {
+	var buf bytes.Buffer
+	w := NewWriter(&buf)
+	w.Write([]byte("hello "))
+	w.Close()
+	w = NewWriter(&buf)
+	w.Write([]byte("world\n"))
+	w.Close()
+
+	r, err := NewReader(&buf)
+	data, err := ioutil.ReadAll(r)
+	if string(data) != "hello world\n" || err != nil {
+		t.Fatalf("ReadAll = %q, %v, want %q, nil", data, err, "hello world")
+	}
+}
+
+func TestWriterReset(t *testing.T) {
+	buf := new(bytes.Buffer)
+	buf2 := new(bytes.Buffer)
+	z := NewWriter(buf)
+	msg := []byte("hello world")
+	z.Write(msg)
+	z.Close()
+	z.Reset(buf2)
+	z.Write(msg)
+	z.Close()
+	if buf.String() != buf2.String() {
+		t.Errorf("buf2 %q != original buf of %q", buf2.String(), buf.String())
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/gzip/testdata/issue6550.gz b/third_party/gofrontend/libgo/go/compress/gzip/testdata/issue6550.gz
new file mode 100644
index 0000000..57972b6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/gzip/testdata/issue6550.gz
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/compress/lzw/reader.go b/third_party/gofrontend/libgo/go/compress/lzw/reader.go
new file mode 100644
index 0000000..ef59699
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/lzw/reader.go
@@ -0,0 +1,253 @@
+// 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.
+
+// Package lzw implements the Lempel-Ziv-Welch compressed data format,
+// described in T. A. Welch, ``A Technique for High-Performance Data
+// Compression'', Computer, 17(6) (June 1984), pp 8-19.
+//
+// In particular, it implements LZW as used by the GIF, TIFF and PDF file
+// formats, which means variable-width codes up to 12 bits and the first
+// two non-literal codes are a clear code and an EOF code.
+package lzw
+
+// TODO(nigeltao): check that TIFF and PDF use LZW in the same way as GIF,
+// modulo LSB/MSB packing order.
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// Order specifies the bit ordering in an LZW data stream.
+type Order int
+
+const (
+	// LSB means Least Significant Bits first, as used in the GIF file format.
+	LSB Order = iota
+	// MSB means Most Significant Bits first, as used in the TIFF and PDF
+	// file formats.
+	MSB
+)
+
+const (
+	maxWidth           = 12
+	decoderInvalidCode = 0xffff
+	flushBuffer        = 1 << maxWidth
+)
+
+// decoder is the state from which the readXxx method converts a byte
+// stream into a code stream.
+type decoder struct {
+	r        io.ByteReader
+	bits     uint32
+	nBits    uint
+	width    uint
+	read     func(*decoder) (uint16, error) // readLSB or readMSB
+	litWidth int                            // width in bits of literal codes
+	err      error
+
+	// The first 1<<litWidth codes are literal codes.
+	// The next two codes mean clear and EOF.
+	// Other valid codes are in the range [lo, hi] where lo := clear + 2,
+	// with the upper bound incrementing on each code seen.
+	// overflow is the code at which hi overflows the code width.
+	// last is the most recently seen code, or decoderInvalidCode.
+	clear, eof, hi, overflow, last uint16
+
+	// Each code c in [lo, hi] expands to two or more bytes. For c != hi:
+	//   suffix[c] is the last of these bytes.
+	//   prefix[c] is the code for all but the last byte.
+	//   This code can either be a literal code or another code in [lo, c).
+	// The c == hi case is a special case.
+	suffix [1 << maxWidth]uint8
+	prefix [1 << maxWidth]uint16
+
+	// output is the temporary output buffer.
+	// Literal codes are accumulated from the start of the buffer.
+	// Non-literal codes decode to a sequence of suffixes that are first
+	// written right-to-left from the end of the buffer before being copied
+	// to the start of the buffer.
+	// It is flushed when it contains >= 1<<maxWidth bytes,
+	// so that there is always room to decode an entire code.
+	output [2 * 1 << maxWidth]byte
+	o      int    // write index into output
+	toRead []byte // bytes to return from Read
+}
+
+// readLSB returns the next code for "Least Significant Bits first" data.
+func (d *decoder) readLSB() (uint16, error) {
+	for d.nBits < d.width {
+		x, err := d.r.ReadByte()
+		if err != nil {
+			return 0, err
+		}
+		d.bits |= uint32(x) << d.nBits
+		d.nBits += 8
+	}
+	code := uint16(d.bits & (1<<d.width - 1))
+	d.bits >>= d.width
+	d.nBits -= d.width
+	return code, nil
+}
+
+// readMSB returns the next code for "Most Significant Bits first" data.
+func (d *decoder) readMSB() (uint16, error) {
+	for d.nBits < d.width {
+		x, err := d.r.ReadByte()
+		if err != nil {
+			return 0, err
+		}
+		d.bits |= uint32(x) << (24 - d.nBits)
+		d.nBits += 8
+	}
+	code := uint16(d.bits >> (32 - d.width))
+	d.bits <<= d.width
+	d.nBits -= d.width
+	return code, nil
+}
+
+func (d *decoder) Read(b []byte) (int, error) {
+	for {
+		if len(d.toRead) > 0 {
+			n := copy(b, d.toRead)
+			d.toRead = d.toRead[n:]
+			return n, nil
+		}
+		if d.err != nil {
+			return 0, d.err
+		}
+		d.decode()
+	}
+}
+
+// decode decompresses bytes from r and leaves them in d.toRead.
+// read specifies how to decode bytes into codes.
+// litWidth is the width in bits of literal codes.
+func (d *decoder) decode() {
+	// Loop over the code stream, converting codes into decompressed bytes.
+	for {
+		code, err := d.read(d)
+		if err != nil {
+			if err == io.EOF {
+				err = io.ErrUnexpectedEOF
+			}
+			d.err = err
+			return
+		}
+		switch {
+		case code < d.clear:
+			// We have a literal code.
+			d.output[d.o] = uint8(code)
+			d.o++
+			if d.last != decoderInvalidCode {
+				// Save what the hi code expands to.
+				d.suffix[d.hi] = uint8(code)
+				d.prefix[d.hi] = d.last
+			}
+		case code == d.clear:
+			d.width = 1 + uint(d.litWidth)
+			d.hi = d.eof
+			d.overflow = 1 << d.width
+			d.last = decoderInvalidCode
+			continue
+		case code == d.eof:
+			d.flush()
+			d.err = io.EOF
+			return
+		case code <= d.hi:
+			c, i := code, len(d.output)-1
+			if code == d.hi {
+				// code == hi is a special case which expands to the last expansion
+				// followed by the head of the last expansion. To find the head, we walk
+				// the prefix chain until we find a literal code.
+				c = d.last
+				for c >= d.clear {
+					c = d.prefix[c]
+				}
+				d.output[i] = uint8(c)
+				i--
+				c = d.last
+			}
+			// Copy the suffix chain into output and then write that to w.
+			for c >= d.clear {
+				d.output[i] = d.suffix[c]
+				i--
+				c = d.prefix[c]
+			}
+			d.output[i] = uint8(c)
+			d.o += copy(d.output[d.o:], d.output[i:])
+			if d.last != decoderInvalidCode {
+				// Save what the hi code expands to.
+				d.suffix[d.hi] = uint8(c)
+				d.prefix[d.hi] = d.last
+			}
+		default:
+			d.err = errors.New("lzw: invalid code")
+			return
+		}
+		d.last, d.hi = code, d.hi+1
+		if d.hi >= d.overflow {
+			if d.width == maxWidth {
+				d.last = decoderInvalidCode
+			} else {
+				d.width++
+				d.overflow <<= 1
+			}
+		}
+		if d.o >= flushBuffer {
+			d.flush()
+			return
+		}
+	}
+}
+
+func (d *decoder) flush() {
+	d.toRead = d.output[:d.o]
+	d.o = 0
+}
+
+var errClosed = errors.New("compress/lzw: reader/writer is closed")
+
+func (d *decoder) Close() error {
+	d.err = errClosed // in case any Reads come along
+	return nil
+}
+
+// NewReader creates a new io.ReadCloser.
+// Reads from the returned io.ReadCloser read and decompress data from r.
+// It is the caller's responsibility to call Close on the ReadCloser when
+// finished reading.
+// The number of bits to use for literal codes, litWidth, must be in the
+// range [2,8] and is typically 8.
+func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser {
+	d := new(decoder)
+	switch order {
+	case LSB:
+		d.read = (*decoder).readLSB
+	case MSB:
+		d.read = (*decoder).readMSB
+	default:
+		d.err = errors.New("lzw: unknown order")
+		return d
+	}
+	if litWidth < 2 || 8 < litWidth {
+		d.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth)
+		return d
+	}
+	if br, ok := r.(io.ByteReader); ok {
+		d.r = br
+	} else {
+		d.r = bufio.NewReader(r)
+	}
+	d.litWidth = litWidth
+	d.width = 1 + uint(litWidth)
+	d.clear = uint16(1) << uint(litWidth)
+	d.eof, d.hi = d.clear+1, d.clear+1
+	d.overflow = uint16(1) << d.width
+	d.last = decoderInvalidCode
+
+	return d
+}
diff --git a/third_party/gofrontend/libgo/go/compress/lzw/reader_test.go b/third_party/gofrontend/libgo/go/compress/lzw/reader_test.go
new file mode 100644
index 0000000..9006c91
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/lzw/reader_test.go
@@ -0,0 +1,152 @@
+// 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.
+
+package lzw
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+	"runtime"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+type lzwTest struct {
+	desc       string
+	raw        string
+	compressed string
+	err        error
+}
+
+var lzwTests = []lzwTest{
+	{
+		"empty;LSB;8",
+		"",
+		"\x01\x01",
+		nil,
+	},
+	{
+		"empty;MSB;8",
+		"",
+		"\x80\x80",
+		nil,
+	},
+	{
+		"tobe;LSB;7",
+		"TOBEORNOTTOBEORTOBEORNOT",
+		"\x54\x4f\x42\x45\x4f\x52\x4e\x4f\x54\x82\x84\x86\x8b\x85\x87\x89\x81",
+		nil,
+	},
+	{
+		"tobe;LSB;8",
+		"TOBEORNOTTOBEORTOBEORNOT",
+		"\x54\x9e\x08\x29\xf2\x44\x8a\x93\x27\x54\x04\x12\x34\xb8\xb0\xe0\xc1\x84\x01\x01",
+		nil,
+	},
+	{
+		"tobe;MSB;7",
+		"TOBEORNOTTOBEORTOBEORNOT",
+		"\x54\x4f\x42\x45\x4f\x52\x4e\x4f\x54\x82\x84\x86\x8b\x85\x87\x89\x81",
+		nil,
+	},
+	{
+		"tobe;MSB;8",
+		"TOBEORNOTTOBEORTOBEORNOT",
+		"\x2a\x13\xc8\x44\x52\x79\x48\x9c\x4f\x2a\x40\xa0\x90\x68\x5c\x16\x0f\x09\x80\x80",
+		nil,
+	},
+	{
+		"tobe-truncated;LSB;8",
+		"TOBEORNOTTOBEORTOBEORNOT",
+		"\x54\x9e\x08\x29\xf2\x44\x8a\x93\x27\x54\x04",
+		io.ErrUnexpectedEOF,
+	},
+	// This example comes from http://en.wikipedia.org/wiki/Graphics_Interchange_Format.
+	{
+		"gif;LSB;8",
+		"\x28\xff\xff\xff\x28\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+		"\x00\x51\xfc\x1b\x28\x70\xa0\xc1\x83\x01\x01",
+		nil,
+	},
+	// This example comes from http://compgroups.net/comp.lang.ruby/Decompressing-LZW-compression-from-PDF-file
+	{
+		"pdf;MSB;8",
+		"-----A---B",
+		"\x80\x0b\x60\x50\x22\x0c\x0c\x85\x01",
+		nil,
+	},
+}
+
+func TestReader(t *testing.T) {
+	var b bytes.Buffer
+	for _, tt := range lzwTests {
+		d := strings.Split(tt.desc, ";")
+		var order Order
+		switch d[1] {
+		case "LSB":
+			order = LSB
+		case "MSB":
+			order = MSB
+		default:
+			t.Errorf("%s: bad order %q", tt.desc, d[1])
+		}
+		litWidth, _ := strconv.Atoi(d[2])
+		rc := NewReader(strings.NewReader(tt.compressed), order, litWidth)
+		defer rc.Close()
+		b.Reset()
+		n, err := io.Copy(&b, rc)
+		if err != nil {
+			if err != tt.err {
+				t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err)
+			}
+			continue
+		}
+		s := b.String()
+		if s != tt.raw {
+			t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.desc, n, s, len(tt.raw), tt.raw)
+		}
+	}
+}
+
+func benchmarkDecoder(b *testing.B, n int) {
+	b.StopTimer()
+	b.SetBytes(int64(n))
+	buf0, err := ioutil.ReadFile("../testdata/e.txt")
+	if err != nil {
+		b.Fatal(err)
+	}
+	if len(buf0) == 0 {
+		b.Fatalf("test file has no data")
+	}
+	compressed := new(bytes.Buffer)
+	w := NewWriter(compressed, LSB, 8)
+	for i := 0; i < n; i += len(buf0) {
+		if len(buf0) > n-i {
+			buf0 = buf0[:n-i]
+		}
+		w.Write(buf0)
+	}
+	w.Close()
+	buf1 := compressed.Bytes()
+	buf0, compressed, w = nil, nil, nil
+	runtime.GC()
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		io.Copy(ioutil.Discard, NewReader(bytes.NewReader(buf1), LSB, 8))
+	}
+}
+
+func BenchmarkDecoder1e4(b *testing.B) {
+	benchmarkDecoder(b, 1e4)
+}
+
+func BenchmarkDecoder1e5(b *testing.B) {
+	benchmarkDecoder(b, 1e5)
+}
+
+func BenchmarkDecoder1e6(b *testing.B) {
+	benchmarkDecoder(b, 1e6)
+}
diff --git a/third_party/gofrontend/libgo/go/compress/lzw/writer.go b/third_party/gofrontend/libgo/go/compress/lzw/writer.go
new file mode 100644
index 0000000..961b25f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/lzw/writer.go
@@ -0,0 +1,262 @@
+// 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.
+
+package lzw
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// A writer is a buffered, flushable writer.
+type writer interface {
+	io.ByteWriter
+	Flush() error
+}
+
+// An errWriteCloser is an io.WriteCloser that always returns a given error.
+type errWriteCloser struct {
+	err error
+}
+
+func (e *errWriteCloser) Write([]byte) (int, error) {
+	return 0, e.err
+}
+
+func (e *errWriteCloser) Close() error {
+	return e.err
+}
+
+const (
+	// A code is a 12 bit value, stored as a uint32 when encoding to avoid
+	// type conversions when shifting bits.
+	maxCode     = 1<<12 - 1
+	invalidCode = 1<<32 - 1
+	// There are 1<<12 possible codes, which is an upper bound on the number of
+	// valid hash table entries at any given point in time. tableSize is 4x that.
+	tableSize = 4 * 1 << 12
+	tableMask = tableSize - 1
+	// A hash table entry is a uint32. Zero is an invalid entry since the
+	// lower 12 bits of a valid entry must be a non-literal code.
+	invalidEntry = 0
+)
+
+// encoder is LZW compressor.
+type encoder struct {
+	// w is the writer that compressed bytes are written to.
+	w writer
+	// order, write, bits, nBits and width are the state for
+	// converting a code stream into a byte stream.
+	order Order
+	write func(*encoder, uint32) error
+	bits  uint32
+	nBits uint
+	width uint
+	// litWidth is the width in bits of literal codes.
+	litWidth uint
+	// hi is the code implied by the next code emission.
+	// overflow is the code at which hi overflows the code width.
+	hi, overflow uint32
+	// savedCode is the accumulated code at the end of the most recent Write
+	// call. It is equal to invalidCode if there was no such call.
+	savedCode uint32
+	// err is the first error encountered during writing. Closing the encoder
+	// will make any future Write calls return errClosed
+	err error
+	// table is the hash table from 20-bit keys to 12-bit values. Each table
+	// entry contains key<<12|val and collisions resolve by linear probing.
+	// The keys consist of a 12-bit code prefix and an 8-bit byte suffix.
+	// The values are a 12-bit code.
+	table [tableSize]uint32
+}
+
+// writeLSB writes the code c for "Least Significant Bits first" data.
+func (e *encoder) writeLSB(c uint32) error {
+	e.bits |= c << e.nBits
+	e.nBits += e.width
+	for e.nBits >= 8 {
+		if err := e.w.WriteByte(uint8(e.bits)); err != nil {
+			return err
+		}
+		e.bits >>= 8
+		e.nBits -= 8
+	}
+	return nil
+}
+
+// writeMSB writes the code c for "Most Significant Bits first" data.
+func (e *encoder) writeMSB(c uint32) error {
+	e.bits |= c << (32 - e.width - e.nBits)
+	e.nBits += e.width
+	for e.nBits >= 8 {
+		if err := e.w.WriteByte(uint8(e.bits >> 24)); err != nil {
+			return err
+		}
+		e.bits <<= 8
+		e.nBits -= 8
+	}
+	return nil
+}
+
+// errOutOfCodes is an internal error that means that the encoder has run out
+// of unused codes and a clear code needs to be sent next.
+var errOutOfCodes = errors.New("lzw: out of codes")
+
+// incHi increments e.hi and checks for both overflow and running out of
+// unused codes. In the latter case, incHi sends a clear code, resets the
+// encoder state and returns errOutOfCodes.
+func (e *encoder) incHi() error {
+	e.hi++
+	if e.hi == e.overflow {
+		e.width++
+		e.overflow <<= 1
+	}
+	if e.hi == maxCode {
+		clear := uint32(1) << e.litWidth
+		if err := e.write(e, clear); err != nil {
+			return err
+		}
+		e.width = uint(e.litWidth) + 1
+		e.hi = clear + 1
+		e.overflow = clear << 1
+		for i := range e.table {
+			e.table[i] = invalidEntry
+		}
+		return errOutOfCodes
+	}
+	return nil
+}
+
+// Write writes a compressed representation of p to e's underlying writer.
+func (e *encoder) Write(p []byte) (n int, err error) {
+	if e.err != nil {
+		return 0, e.err
+	}
+	if len(p) == 0 {
+		return 0, nil
+	}
+	n = len(p)
+	litMask := uint32(1<<e.litWidth - 1)
+	code := e.savedCode
+	if code == invalidCode {
+		// The first code sent is always a literal code.
+		code, p = uint32(p[0])&litMask, p[1:]
+	}
+loop:
+	for _, x := range p {
+		literal := uint32(x) & litMask
+		key := code<<8 | literal
+		// If there is a hash table hit for this key then we continue the loop
+		// and do not emit a code yet.
+		hash := (key>>12 ^ key) & tableMask
+		for h, t := hash, e.table[hash]; t != invalidEntry; {
+			if key == t>>12 {
+				code = t & maxCode
+				continue loop
+			}
+			h = (h + 1) & tableMask
+			t = e.table[h]
+		}
+		// Otherwise, write the current code, and literal becomes the start of
+		// the next emitted code.
+		if e.err = e.write(e, code); e.err != nil {
+			return 0, e.err
+		}
+		code = literal
+		// Increment e.hi, the next implied code. If we run out of codes, reset
+		// the encoder state (including clearing the hash table) and continue.
+		if err1 := e.incHi(); err1 != nil {
+			if err1 == errOutOfCodes {
+				continue
+			}
+			e.err = err1
+			return 0, e.err
+		}
+		// Otherwise, insert key -> e.hi into the map that e.table represents.
+		for {
+			if e.table[hash] == invalidEntry {
+				e.table[hash] = (key << 12) | e.hi
+				break
+			}
+			hash = (hash + 1) & tableMask
+		}
+	}
+	e.savedCode = code
+	return n, nil
+}
+
+// Close closes the encoder, flushing any pending output. It does not close or
+// flush e's underlying writer.
+func (e *encoder) Close() error {
+	if e.err != nil {
+		if e.err == errClosed {
+			return nil
+		}
+		return e.err
+	}
+	// Make any future calls to Write return errClosed.
+	e.err = errClosed
+	// Write the savedCode if valid.
+	if e.savedCode != invalidCode {
+		if err := e.write(e, e.savedCode); err != nil {
+			return err
+		}
+		if err := e.incHi(); err != nil && err != errOutOfCodes {
+			return err
+		}
+	}
+	// Write the eof code.
+	eof := uint32(1)<<e.litWidth + 1
+	if err := e.write(e, eof); err != nil {
+		return err
+	}
+	// Write the final bits.
+	if e.nBits > 0 {
+		if e.order == MSB {
+			e.bits >>= 24
+		}
+		if err := e.w.WriteByte(uint8(e.bits)); err != nil {
+			return err
+		}
+	}
+	return e.w.Flush()
+}
+
+// NewWriter creates a new io.WriteCloser.
+// Writes to the returned io.WriteCloser are compressed and written to w.
+// It is the caller's responsibility to call Close on the WriteCloser when
+// finished writing.
+// The number of bits to use for literal codes, litWidth, must be in the
+// range [2,8] and is typically 8.
+func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser {
+	var write func(*encoder, uint32) error
+	switch order {
+	case LSB:
+		write = (*encoder).writeLSB
+	case MSB:
+		write = (*encoder).writeMSB
+	default:
+		return &errWriteCloser{errors.New("lzw: unknown order")}
+	}
+	if litWidth < 2 || 8 < litWidth {
+		return &errWriteCloser{fmt.Errorf("lzw: litWidth %d out of range", litWidth)}
+	}
+	bw, ok := w.(writer)
+	if !ok {
+		bw = bufio.NewWriter(w)
+	}
+	lw := uint(litWidth)
+	return &encoder{
+		w:         bw,
+		order:     order,
+		write:     write,
+		width:     1 + lw,
+		litWidth:  lw,
+		hi:        1<<lw + 1,
+		overflow:  1 << (lw + 1),
+		savedCode: invalidCode,
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/lzw/writer_test.go b/third_party/gofrontend/libgo/go/compress/lzw/writer_test.go
new file mode 100644
index 0000000..3e4e6de
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/lzw/writer_test.go
@@ -0,0 +1,144 @@
+// 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.
+
+package lzw
+
+import (
+	"io"
+	"io/ioutil"
+	"os"
+	"runtime"
+	"testing"
+)
+
+var filenames = []string{
+	"../testdata/e.txt",
+	"../testdata/pi.txt",
+}
+
+// testFile tests that compressing and then decompressing the given file with
+// the given options yields equivalent bytes to the original file.
+func testFile(t *testing.T, fn string, order Order, litWidth int) {
+	// Read the file, as golden output.
+	golden, err := os.Open(fn)
+	if err != nil {
+		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
+		return
+	}
+	defer golden.Close()
+
+	// Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
+	raw, err := os.Open(fn)
+	if err != nil {
+		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
+		return
+	}
+
+	piper, pipew := io.Pipe()
+	defer piper.Close()
+	go func() {
+		defer raw.Close()
+		defer pipew.Close()
+		lzww := NewWriter(pipew, order, litWidth)
+		defer lzww.Close()
+		var b [4096]byte
+		for {
+			n, err0 := raw.Read(b[:])
+			if err0 != nil && err0 != io.EOF {
+				t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err0)
+				return
+			}
+			_, err1 := lzww.Write(b[:n])
+			if err1 != nil {
+				t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err1)
+				return
+			}
+			if err0 == io.EOF {
+				break
+			}
+		}
+	}()
+	lzwr := NewReader(piper, order, litWidth)
+	defer lzwr.Close()
+
+	// Compare the two.
+	b0, err0 := ioutil.ReadAll(golden)
+	b1, err1 := ioutil.ReadAll(lzwr)
+	if err0 != nil {
+		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err0)
+		return
+	}
+	if err1 != nil {
+		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err1)
+		return
+	}
+	if len(b1) != len(b0) {
+		t.Errorf("%s (order=%d litWidth=%d): length mismatch %d != %d", fn, order, litWidth, len(b1), len(b0))
+		return
+	}
+	for i := 0; i < len(b0); i++ {
+		if b1[i] != b0[i] {
+			t.Errorf("%s (order=%d litWidth=%d): mismatch at %d, 0x%02x != 0x%02x\n", fn, order, litWidth, i, b1[i], b0[i])
+			return
+		}
+	}
+}
+
+func TestWriter(t *testing.T) {
+	for _, filename := range filenames {
+		for _, order := range [...]Order{LSB, MSB} {
+			// The test data "2.71828 etcetera" is ASCII text requiring at least 6 bits.
+			for _, litWidth := range [...]int{6, 7, 8} {
+				testFile(t, filename, order, litWidth)
+			}
+		}
+	}
+}
+
+func TestWriterReturnValues(t *testing.T) {
+	w := NewWriter(ioutil.Discard, LSB, 8)
+	n, err := w.Write([]byte("asdf"))
+	if n != 4 || err != nil {
+		t.Errorf("got %d, %v, want 4, nil", n, err)
+	}
+}
+
+func benchmarkEncoder(b *testing.B, n int) {
+	b.StopTimer()
+	b.SetBytes(int64(n))
+	buf0, err := ioutil.ReadFile("../testdata/e.txt")
+	if err != nil {
+		b.Fatal(err)
+	}
+	if len(buf0) == 0 {
+		b.Fatalf("test file has no data")
+	}
+	buf1 := make([]byte, n)
+	for i := 0; i < n; i += len(buf0) {
+		if len(buf0) > n-i {
+			buf0 = buf0[:n-i]
+		}
+		copy(buf1[i:], buf0)
+	}
+	buf0 = nil
+	runtime.GC()
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		w := NewWriter(ioutil.Discard, LSB, 8)
+		w.Write(buf1)
+		w.Close()
+	}
+}
+
+func BenchmarkEncoder1e4(b *testing.B) {
+	benchmarkEncoder(b, 1e4)
+}
+
+func BenchmarkEncoder1e5(b *testing.B) {
+	benchmarkEncoder(b, 1e5)
+}
+
+func BenchmarkEncoder1e6(b *testing.B) {
+	benchmarkEncoder(b, 1e6)
+}
diff --git a/third_party/gofrontend/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt b/third_party/gofrontend/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt
new file mode 100644
index 0000000..c97da7e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt
@@ -0,0 +1,8858 @@
+The Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
+by Mark Twain (Samuel Clemens)
+
+This eBook is for the use of anyone anywhere at no cost and with
+almost no restrictions whatsoever.  You may copy it, give it away or
+re-use it under the terms of the Project Gutenberg License included
+with this eBook or online at www.gutenberg.net
+
+
+Title: The Adventures of Tom Sawyer, Complete
+
+Author: Mark Twain (Samuel Clemens)
+
+Release Date: August 20, 2006 [EBook #74]
+[Last updated: May 3, 2011]
+
+Language: English
+
+
+*** START OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
+
+
+
+
+Produced by David Widger. The previous edition was updated by Jose
+Menendez.
+
+
+
+
+
+                   THE ADVENTURES OF TOM SAWYER
+                                BY
+                            MARK TWAIN
+                     (Samuel Langhorne Clemens)
+
+
+
+
+                           P R E F A C E
+
+MOST of the adventures recorded in this book really occurred; one or
+two were experiences of my own, the rest those of boys who were
+schoolmates of mine. Huck Finn is drawn from life; Tom Sawyer also, but
+not from an individual--he is a combination of the characteristics of
+three boys whom I knew, and therefore belongs to the composite order of
+architecture.
+
+The odd superstitions touched upon were all prevalent among children
+and slaves in the West at the period of this story--that is to say,
+thirty or forty years ago.
+
+Although my book is intended mainly for the entertainment of boys and
+girls, I hope it will not be shunned by men and women on that account,
+for part of my plan has been to try to pleasantly remind adults of what
+they once were themselves, and of how they felt and thought and talked,
+and what queer enterprises they sometimes engaged in.
+
+                                                            THE AUTHOR.
+
+HARTFORD, 1876.
+
+
+
+                          T O M   S A W Y E R
+
+
+
+CHAPTER I
+
+"TOM!"
+
+No answer.
+
+"TOM!"
+
+No answer.
+
+"What's gone with that boy,  I wonder? You TOM!"
+
+No answer.
+
+The old lady pulled her spectacles down and looked over them about the
+room; then she put them up and looked out under them. She seldom or
+never looked THROUGH them for so small a thing as a boy; they were her
+state pair, the pride of her heart, and were built for "style," not
+service--she could have seen through a pair of stove-lids just as well.
+She looked perplexed for a moment, and then said, not fiercely, but
+still loud enough for the furniture to hear:
+
+"Well, I lay if I get hold of you I'll--"
+
+She did not finish, for by this time she was bending down and punching
+under the bed with the broom, and so she needed breath to punctuate the
+punches with. She resurrected nothing but the cat.
+
+"I never did see the beat of that boy!"
+
+She went to the open door and stood in it and looked out among the
+tomato vines and "jimpson" weeds that constituted the garden. No Tom.
+So she lifted up her voice at an angle calculated for distance and
+shouted:
+
+"Y-o-u-u TOM!"
+
+There was a slight noise behind her and she turned just in time to
+seize a small boy by the slack of his roundabout and arrest his flight.
+
+"There! I might 'a' thought of that closet. What you been doing in
+there?"
+
+"Nothing."
+
+"Nothing! Look at your hands. And look at your mouth. What IS that
+truck?"
+
+"I don't know, aunt."
+
+"Well, I know. It's jam--that's what it is. Forty times I've said if
+you didn't let that jam alone I'd skin you. Hand me that switch."
+
+The switch hovered in the air--the peril was desperate--
+
+"My! Look behind you, aunt!"
+
+The old lady whirled round, and snatched her skirts out of danger. The
+lad fled on the instant, scrambled up the high board-fence, and
+disappeared over it.
+
+His aunt Polly stood surprised a moment, and then broke into a gentle
+laugh.
+
+"Hang the boy, can't I never learn anything? Ain't he played me tricks
+enough like that for me to be looking out for him by this time? But old
+fools is the biggest fools there is. Can't learn an old dog new tricks,
+as the saying is. But my goodness, he never plays them alike, two days,
+and how is a body to know what's coming? He 'pears to know just how
+long he can torment me before I get my dander up, and he knows if he
+can make out to put me off for a minute or make me laugh, it's all down
+again and I can't hit him a lick. I ain't doing my duty by that boy,
+and that's the Lord's truth, goodness knows. Spare the rod and spile
+the child, as the Good Book says. I'm a laying up sin and suffering for
+us both, I know. He's full of the Old Scratch, but laws-a-me! he's my
+own dead sister's boy, poor thing, and I ain't got the heart to lash
+him, somehow. Every time I let him off, my conscience does hurt me so,
+and every time I hit him my old heart most breaks. Well-a-well, man
+that is born of woman is of few days and full of trouble, as the
+Scripture says, and I reckon it's so. He'll play hookey this evening, *
+and [* Southwestern for "afternoon"] I'll just be obleeged to make him
+work, to-morrow, to punish him. It's mighty hard to make him work
+Saturdays, when all the boys is having holiday, but he hates work more
+than he hates anything else, and I've GOT to do some of my duty by him,
+or I'll be the ruination of the child."
+
+Tom did play hookey, and he had a very good time. He got back home
+barely in season to help Jim, the small colored boy, saw next-day's
+wood and split the kindlings before supper--at least he was there in
+time to tell his adventures to Jim while Jim did three-fourths of the
+work. Tom's younger brother (or rather half-brother) Sid was already
+through with his part of the work (picking up chips), for he was a
+quiet boy, and had no adventurous, troublesome ways.
+
+While Tom was eating his supper, and stealing sugar as opportunity
+offered, Aunt Polly asked him questions that were full of guile, and
+very deep--for she wanted to trap him into damaging revealments. Like
+many other simple-hearted souls, it was her pet vanity to believe she
+was endowed with a talent for dark and mysterious diplomacy, and she
+loved to contemplate her most transparent devices as marvels of low
+cunning. Said she:
+
+"Tom, it was middling warm in school, warn't it?"
+
+"Yes'm."
+
+"Powerful warm, warn't it?"
+
+"Yes'm."
+
+"Didn't you want to go in a-swimming, Tom?"
+
+A bit of a scare shot through Tom--a touch of uncomfortable suspicion.
+He searched Aunt Polly's face, but it told him nothing. So he said:
+
+"No'm--well, not very much."
+
+The old lady reached out her hand and felt Tom's shirt, and said:
+
+"But you ain't too warm now, though." And it flattered her to reflect
+that she had discovered that the shirt was dry without anybody knowing
+that that was what she had in her mind. But in spite of her, Tom knew
+where the wind lay, now. So he forestalled what might be the next move:
+
+"Some of us pumped on our heads--mine's damp yet. See?"
+
+Aunt Polly was vexed to think she had overlooked that bit of
+circumstantial evidence, and missed a trick. Then she had a new
+inspiration:
+
+"Tom, you didn't have to undo your shirt collar where I sewed it, to
+pump on your head, did you? Unbutton your jacket!"
+
+The trouble vanished out of Tom's face. He opened his jacket. His
+shirt collar was securely sewed.
+
+"Bother! Well, go 'long with you. I'd made sure you'd played hookey
+and been a-swimming. But I forgive ye, Tom. I reckon you're a kind of a
+singed cat, as the saying is--better'n you look. THIS time."
+
+She was half sorry her sagacity had miscarried, and half glad that Tom
+had stumbled into obedient conduct for once.
+
+But Sidney said:
+
+"Well, now, if I didn't think you sewed his collar with white thread,
+but it's black."
+
+"Why, I did sew it with white! Tom!"
+
+But Tom did not wait for the rest. As he went out at the door he said:
+
+"Siddy, I'll lick you for that."
+
+In a safe place Tom examined two large needles which were thrust into
+the lapels of his jacket, and had thread bound about them--one needle
+carried white thread and the other black. He said:
+
+"She'd never noticed if it hadn't been for Sid. Confound it! sometimes
+she sews it with white, and sometimes she sews it with black. I wish to
+geeminy she'd stick to one or t'other--I can't keep the run of 'em. But
+I bet you I'll lam Sid for that. I'll learn him!"
+
+He was not the Model Boy of the village. He knew the model boy very
+well though--and loathed him.
+
+Within two minutes, or even less, he had forgotten all his troubles.
+Not because his troubles were one whit less heavy and bitter to him
+than a man's are to a man, but because a new and powerful interest bore
+them down and drove them out of his mind for the time--just as men's
+misfortunes are forgotten in the excitement of new enterprises. This
+new interest was a valued novelty in whistling, which he had just
+acquired from a negro, and he was suffering to practise it undisturbed.
+It consisted in a peculiar bird-like turn, a sort of liquid warble,
+produced by touching the tongue to the roof of the mouth at short
+intervals in the midst of the music--the reader probably remembers how
+to do it, if he has ever been a boy. Diligence and attention soon gave
+him the knack of it, and he strode down the street with his mouth full
+of harmony and his soul full of gratitude. He felt much as an
+astronomer feels who has discovered a new planet--no doubt, as far as
+strong, deep, unalloyed pleasure is concerned, the advantage was with
+the boy, not the astronomer.
+
+The summer evenings were long. It was not dark, yet. Presently Tom
+checked his whistle. A stranger was before him--a boy a shade larger
+than himself. A new-comer of any age or either sex was an impressive
+curiosity in the poor little shabby village of St. Petersburg. This boy
+was well dressed, too--well dressed on a week-day. This was simply
+astounding. His cap was a dainty thing, his close-buttoned blue cloth
+roundabout was new and natty, and so were his pantaloons. He had shoes
+on--and it was only Friday. He even wore a necktie, a bright bit of
+ribbon. He had a citified air about him that ate into Tom's vitals. The
+more Tom stared at the splendid marvel, the higher he turned up his
+nose at his finery and the shabbier and shabbier his own outfit seemed
+to him to grow. Neither boy spoke. If one moved, the other moved--but
+only sidewise, in a circle; they kept face to face and eye to eye all
+the time. Finally Tom said:
+
+"I can lick you!"
+
+"I'd like to see you try it."
+
+"Well, I can do it."
+
+"No you can't, either."
+
+"Yes I can."
+
+"No you can't."
+
+"I can."
+
+"You can't."
+
+"Can!"
+
+"Can't!"
+
+An uncomfortable pause. Then Tom said:
+
+"What's your name?"
+
+"'Tisn't any of your business, maybe."
+
+"Well I 'low I'll MAKE it my business."
+
+"Well why don't you?"
+
+"If you say much, I will."
+
+"Much--much--MUCH. There now."
+
+"Oh, you think you're mighty smart, DON'T you? I could lick you with
+one hand tied behind me, if I wanted to."
+
+"Well why don't you DO it? You SAY you can do it."
+
+"Well I WILL, if you fool with me."
+
+"Oh yes--I've seen whole families in the same fix."
+
+"Smarty! You think you're SOME, now, DON'T you? Oh, what a hat!"
+
+"You can lump that hat if you don't like it. I dare you to knock it
+off--and anybody that'll take a dare will suck eggs."
+
+"You're a liar!"
+
+"You're another."
+
+"You're a fighting liar and dasn't take it up."
+
+"Aw--take a walk!"
+
+"Say--if you give me much more of your sass I'll take and bounce a
+rock off'n your head."
+
+"Oh, of COURSE you will."
+
+"Well I WILL."
+
+"Well why don't you DO it then? What do you keep SAYING you will for?
+Why don't you DO it? It's because you're afraid."
+
+"I AIN'T afraid."
+
+"You are."
+
+"I ain't."
+
+"You are."
+
+Another pause, and more eying and sidling around each other. Presently
+they were shoulder to shoulder. Tom said:
+
+"Get away from here!"
+
+"Go away yourself!"
+
+"I won't."
+
+"I won't either."
+
+So they stood, each with a foot placed at an angle as a brace, and
+both shoving with might and main, and glowering at each other with
+hate. But neither could get an advantage. After struggling till both
+were hot and flushed, each relaxed his strain with watchful caution,
+and Tom said:
+
+"You're a coward and a pup. I'll tell my big brother on you, and he
+can thrash you with his little finger, and I'll make him do it, too."
+
+"What do I care for your big brother? I've got a brother that's bigger
+than he is--and what's more, he can throw him over that fence, too."
+[Both brothers were imaginary.]
+
+"That's a lie."
+
+"YOUR saying so don't make it so."
+
+Tom drew a line in the dust with his big toe, and said:
+
+"I dare you to step over that, and I'll lick you till you can't stand
+up. Anybody that'll take a dare will steal sheep."
+
+The new boy stepped over promptly, and said:
+
+"Now you said you'd do it, now let's see you do it."
+
+"Don't you crowd me now; you better look out."
+
+"Well, you SAID you'd do it--why don't you do it?"
+
+"By jingo! for two cents I WILL do it."
+
+The new boy took two broad coppers out of his pocket and held them out
+with derision. Tom struck them to the ground. In an instant both boys
+were rolling and tumbling in the dirt, gripped together like cats; and
+for the space of a minute they tugged and tore at each other's hair and
+clothes, punched and scratched each other's nose, and covered
+themselves with dust and glory. Presently the confusion took form, and
+through the fog of battle Tom appeared, seated astride the new boy, and
+pounding him with his fists. "Holler 'nuff!" said he.
+
+The boy only struggled to free himself. He was crying--mainly from rage.
+
+"Holler 'nuff!"--and the pounding went on.
+
+At last the stranger got out a smothered "'Nuff!" and Tom let him up
+and said:
+
+"Now that'll learn you. Better look out who you're fooling with next
+time."
+
+The new boy went off brushing the dust from his clothes, sobbing,
+snuffling, and occasionally looking back and shaking his head and
+threatening what he would do to Tom the "next time he caught him out."
+To which Tom responded with jeers, and started off in high feather, and
+as soon as his back was turned the new boy snatched up a stone, threw
+it and hit him between the shoulders and then turned tail and ran like
+an antelope. Tom chased the traitor home, and thus found out where he
+lived. He then held a position at the gate for some time, daring the
+enemy to come outside, but the enemy only made faces at him through the
+window and declined. At last the enemy's mother appeared, and called
+Tom a bad, vicious, vulgar child, and ordered him away. So he went
+away; but he said he "'lowed" to "lay" for that boy.
+
+He got home pretty late that night, and when he climbed cautiously in
+at the window, he uncovered an ambuscade, in the person of his aunt;
+and when she saw the state his clothes were in her resolution to turn
+his Saturday holiday into captivity at hard labor became adamantine in
+its firmness.
+
+
+
+CHAPTER II
+
+SATURDAY morning was come, and all the summer world was bright and
+fresh, and brimming with life. There was a song in every heart; and if
+the heart was young the music issued at the lips. There was cheer in
+every face and a spring in every step. The locust-trees were in bloom
+and the fragrance of the blossoms filled the air. Cardiff Hill, beyond
+the village and above it, was green with vegetation and it lay just far
+enough away to seem a Delectable Land, dreamy, reposeful, and inviting.
+
+Tom appeared on the sidewalk with a bucket of whitewash and a
+long-handled brush. He surveyed the fence, and all gladness left him and
+a deep melancholy settled down upon his spirit. Thirty yards of board
+fence nine feet high. Life to him seemed hollow, and existence but a
+burden. Sighing, he dipped his brush and passed it along the topmost
+plank; repeated the operation; did it again; compared the insignificant
+whitewashed streak with the far-reaching continent of unwhitewashed
+fence, and sat down on a tree-box discouraged. Jim came skipping out at
+the gate with a tin pail, and singing Buffalo Gals. Bringing water from
+the town pump had always been hateful work in Tom's eyes, before, but
+now it did not strike him so. He remembered that there was company at
+the pump. White, mulatto, and negro boys and girls were always there
+waiting their turns, resting, trading playthings, quarrelling,
+fighting, skylarking. And he remembered that although the pump was only
+a hundred and fifty yards off, Jim never got back with a bucket of
+water under an hour--and even then somebody generally had to go after
+him. Tom said:
+
+"Say, Jim, I'll fetch the water if you'll whitewash some."
+
+Jim shook his head and said:
+
+"Can't, Mars Tom. Ole missis, she tole me I got to go an' git dis
+water an' not stop foolin' roun' wid anybody. She say she spec' Mars
+Tom gwine to ax me to whitewash, an' so she tole me go 'long an' 'tend
+to my own business--she 'lowed SHE'D 'tend to de whitewashin'."
+
+"Oh, never you mind what she said, Jim. That's the way she always
+talks. Gimme the bucket--I won't be gone only a a minute. SHE won't
+ever know."
+
+"Oh, I dasn't, Mars Tom. Ole missis she'd take an' tar de head off'n
+me. 'Deed she would."
+
+"SHE! She never licks anybody--whacks 'em over the head with her
+thimble--and who cares for that, I'd like to know. She talks awful, but
+talk don't hurt--anyways it don't if she don't cry. Jim, I'll give you
+a marvel. I'll give you a white alley!"
+
+Jim began to waver.
+
+"White alley, Jim! And it's a bully taw."
+
+"My! Dat's a mighty gay marvel, I tell you! But Mars Tom I's powerful
+'fraid ole missis--"
+
+"And besides, if you will I'll show you my sore toe."
+
+Jim was only human--this attraction was too much for him. He put down
+his pail, took the white alley, and bent over the toe with absorbing
+interest while the bandage was being unwound. In another moment he was
+flying down the street with his pail and a tingling rear, Tom was
+whitewashing with vigor, and Aunt Polly was retiring from the field
+with a slipper in her hand and triumph in her eye.
+
+But Tom's energy did not last. He began to think of the fun he had
+planned for this day, and his sorrows multiplied. Soon the free boys
+would come tripping along on all sorts of delicious expeditions, and
+they would make a world of fun of him for having to work--the very
+thought of it burnt him like fire. He got out his worldly wealth and
+examined it--bits of toys, marbles, and trash; enough to buy an
+exchange of WORK, maybe, but not half enough to buy so much as half an
+hour of pure freedom. So he returned his straitened means to his
+pocket, and gave up the idea of trying to buy the boys. At this dark
+and hopeless moment an inspiration burst upon him! Nothing less than a
+great, magnificent inspiration.
+
+He took up his brush and went tranquilly to work. Ben Rogers hove in
+sight presently--the very boy, of all boys, whose ridicule he had been
+dreading. Ben's gait was the hop-skip-and-jump--proof enough that his
+heart was light and his anticipations high. He was eating an apple, and
+giving a long, melodious whoop, at intervals, followed by a deep-toned
+ding-dong-dong, ding-dong-dong, for he was personating a steamboat. As
+he drew near, he slackened speed, took the middle of the street, leaned
+far over to starboard and rounded to ponderously and with laborious
+pomp and circumstance--for he was personating the Big Missouri, and
+considered himself to be drawing nine feet of water. He was boat and
+captain and engine-bells combined, so he had to imagine himself
+standing on his own hurricane-deck giving the orders and executing them:
+
+"Stop her, sir! Ting-a-ling-ling!" The headway ran almost out, and he
+drew up slowly toward the sidewalk.
+
+"Ship up to back! Ting-a-ling-ling!" His arms straightened and
+stiffened down his sides.
+
+"Set her back on the stabboard! Ting-a-ling-ling! Chow! ch-chow-wow!
+Chow!" His right hand, meantime, describing stately circles--for it was
+representing a forty-foot wheel.
+
+"Let her go back on the labboard! Ting-a-lingling! Chow-ch-chow-chow!"
+The left hand began to describe circles.
+
+"Stop the stabboard! Ting-a-ling-ling! Stop the labboard! Come ahead
+on the stabboard! Stop her! Let your outside turn over slow!
+Ting-a-ling-ling! Chow-ow-ow! Get out that head-line! LIVELY now!
+Come--out with your spring-line--what're you about there! Take a turn
+round that stump with the bight of it! Stand by that stage, now--let her
+go! Done with the engines, sir! Ting-a-ling-ling! SH'T! S'H'T! SH'T!"
+(trying the gauge-cocks).
+
+Tom went on whitewashing--paid no attention to the steamboat. Ben
+stared a moment and then said: "Hi-YI! YOU'RE up a stump, ain't you!"
+
+No answer. Tom surveyed his last touch with the eye of an artist, then
+he gave his brush another gentle sweep and surveyed the result, as
+before. Ben ranged up alongside of him. Tom's mouth watered for the
+apple, but he stuck to his work. Ben said:
+
+"Hello, old chap, you got to work, hey?"
+
+Tom wheeled suddenly and said:
+
+"Why, it's you, Ben! I warn't noticing."
+
+"Say--I'm going in a-swimming, I am. Don't you wish you could? But of
+course you'd druther WORK--wouldn't you? Course you would!"
+
+Tom contemplated the boy a bit, and said:
+
+"What do you call work?"
+
+"Why, ain't THAT work?"
+
+Tom resumed his whitewashing, and answered carelessly:
+
+"Well, maybe it is, and maybe it ain't. All I know, is, it suits Tom
+Sawyer."
+
+"Oh come, now, you don't mean to let on that you LIKE it?"
+
+The brush continued to move.
+
+"Like it? Well, I don't see why I oughtn't to like it. Does a boy get
+a chance to whitewash a fence every day?"
+
+That put the thing in a new light. Ben stopped nibbling his apple. Tom
+swept his brush daintily back and forth--stepped back to note the
+effect--added a touch here and there--criticised the effect again--Ben
+watching every move and getting more and more interested, more and more
+absorbed. Presently he said:
+
+"Say, Tom, let ME whitewash a little."
+
+Tom considered, was about to consent; but he altered his mind:
+
+"No--no--I reckon it wouldn't hardly do, Ben. You see, Aunt Polly's
+awful particular about this fence--right here on the street, you know
+--but if it was the back fence I wouldn't mind and SHE wouldn't. Yes,
+she's awful particular about this fence; it's got to be done very
+careful; I reckon there ain't one boy in a thousand, maybe two
+thousand, that can do it the way it's got to be done."
+
+"No--is that so? Oh come, now--lemme just try. Only just a little--I'd
+let YOU, if you was me, Tom."
+
+"Ben, I'd like to, honest injun; but Aunt Polly--well, Jim wanted to
+do it, but she wouldn't let him; Sid wanted to do it, and she wouldn't
+let Sid. Now don't you see how I'm fixed? If you was to tackle this
+fence and anything was to happen to it--"
+
+"Oh, shucks, I'll be just as careful. Now lemme try. Say--I'll give
+you the core of my apple."
+
+"Well, here--No, Ben, now don't. I'm afeard--"
+
+"I'll give you ALL of it!"
+
+Tom gave up the brush with reluctance in his face, but alacrity in his
+heart. And while the late steamer Big Missouri worked and sweated in
+the sun, the retired artist sat on a barrel in the shade close by,
+dangled his legs, munched his apple, and planned the slaughter of more
+innocents. There was no lack of material; boys happened along every
+little while; they came to jeer, but remained to whitewash. By the time
+Ben was fagged out, Tom had traded the next chance to Billy Fisher for
+a kite, in good repair; and when he played out, Johnny Miller bought in
+for a dead rat and a string to swing it with--and so on, and so on,
+hour after hour. And when the middle of the afternoon came, from being
+a poor poverty-stricken boy in the morning, Tom was literally rolling
+in wealth. He had besides the things before mentioned, twelve marbles,
+part of a jews-harp, a piece of blue bottle-glass to look through, a
+spool cannon, a key that wouldn't unlock anything, a fragment of chalk,
+a glass stopper of a decanter, a tin soldier, a couple of tadpoles, six
+fire-crackers, a kitten with only one eye, a brass doorknob, a
+dog-collar--but no dog--the handle of a knife, four pieces of
+orange-peel, and a dilapidated old window sash.
+
+He had had a nice, good, idle time all the while--plenty of company
+--and the fence had three coats of whitewash on it! If he hadn't run out
+of whitewash he would have bankrupted every boy in the village.
+
+Tom said to himself that it was not such a hollow world, after all. He
+had discovered a great law of human action, without knowing it--namely,
+that in order to make a man or a boy covet a thing, it is only
+necessary to make the thing difficult to attain. If he had been a great
+and wise philosopher, like the writer of this book, he would now have
+comprehended that Work consists of whatever a body is OBLIGED to do,
+and that Play consists of whatever a body is not obliged to do. And
+this would help him to understand why constructing artificial flowers
+or performing on a tread-mill is work, while rolling ten-pins or
+climbing Mont Blanc is only amusement. There are wealthy gentlemen in
+England who drive four-horse passenger-coaches twenty or thirty miles
+on a daily line, in the summer, because the privilege costs them
+considerable money; but if they were offered wages for the service,
+that would turn it into work and then they would resign.
+
+The boy mused awhile over the substantial change which had taken place
+in his worldly circumstances, and then wended toward headquarters to
+report.
+
+
+
+CHAPTER III
+
+TOM presented himself before Aunt Polly, who was sitting by an open
+window in a pleasant rearward apartment, which was bedroom,
+breakfast-room, dining-room, and library, combined. The balmy summer
+air, the restful quiet, the odor of the flowers, and the drowsing murmur
+of the bees had had their effect, and she was nodding over her knitting
+--for she had no company but the cat, and it was asleep in her lap. Her
+spectacles were propped up on her gray head for safety. She had thought
+that of course Tom had deserted long ago, and she wondered at seeing him
+place himself in her power again in this intrepid way. He said: "Mayn't
+I go and play now, aunt?"
+
+"What, a'ready? How much have you done?"
+
+"It's all done, aunt."
+
+"Tom, don't lie to me--I can't bear it."
+
+"I ain't, aunt; it IS all done."
+
+Aunt Polly placed small trust in such evidence. She went out to see
+for herself; and she would have been content to find twenty per cent.
+of Tom's statement true. When she found the entire fence whitewashed,
+and not only whitewashed but elaborately coated and recoated, and even
+a streak added to the ground, her astonishment was almost unspeakable.
+She said:
+
+"Well, I never! There's no getting round it, you can work when you're
+a mind to, Tom." And then she diluted the compliment by adding, "But
+it's powerful seldom you're a mind to, I'm bound to say. Well, go 'long
+and play; but mind you get back some time in a week, or I'll tan you."
+
+She was so overcome by the splendor of his achievement that she took
+him into the closet and selected a choice apple and delivered it to
+him, along with an improving lecture upon the added value and flavor a
+treat took to itself when it came without sin through virtuous effort.
+And while she closed with a happy Scriptural flourish, he "hooked" a
+doughnut.
+
+Then he skipped out, and saw Sid just starting up the outside stairway
+that led to the back rooms on the second floor. Clods were handy and
+the air was full of them in a twinkling. They raged around Sid like a
+hail-storm; and before Aunt Polly could collect her surprised faculties
+and sally to the rescue, six or seven clods had taken personal effect,
+and Tom was over the fence and gone. There was a gate, but as a general
+thing he was too crowded for time to make use of it. His soul was at
+peace, now that he had settled with Sid for calling attention to his
+black thread and getting him into trouble.
+
+Tom skirted the block, and came round into a muddy alley that led by
+the back of his aunt's cow-stable. He presently got safely beyond the
+reach of capture and punishment, and hastened toward the public square
+of the village, where two "military" companies of boys had met for
+conflict, according to previous appointment. Tom was General of one of
+these armies, Joe Harper (a bosom friend) General of the other. These
+two great commanders did not condescend to fight in person--that being
+better suited to the still smaller fry--but sat together on an eminence
+and conducted the field operations by orders delivered through
+aides-de-camp. Tom's army won a great victory, after a long and
+hard-fought battle. Then the dead were counted, prisoners exchanged,
+the terms of the next disagreement agreed upon, and the day for the
+necessary battle appointed; after which the armies fell into line and
+marched away, and Tom turned homeward alone.
+
+As he was passing by the house where Jeff Thatcher lived, he saw a new
+girl in the garden--a lovely little blue-eyed creature with yellow hair
+plaited into two long-tails, white summer frock and embroidered
+pantalettes. The fresh-crowned hero fell without firing a shot. A
+certain Amy Lawrence vanished out of his heart and left not even a
+memory of herself behind. He had thought he loved her to distraction;
+he had regarded his passion as adoration; and behold it was only a poor
+little evanescent partiality. He had been months winning her; she had
+confessed hardly a week ago; he had been the happiest and the proudest
+boy in the world only seven short days, and here in one instant of time
+she had gone out of his heart like a casual stranger whose visit is
+done.
+
+He worshipped this new angel with furtive eye, till he saw that she
+had discovered him; then he pretended he did not know she was present,
+and began to "show off" in all sorts of absurd boyish ways, in order to
+win her admiration. He kept up this grotesque foolishness for some
+time; but by-and-by, while he was in the midst of some dangerous
+gymnastic performances, he glanced aside and saw that the little girl
+was wending her way toward the house. Tom came up to the fence and
+leaned on it, grieving, and hoping she would tarry yet awhile longer.
+She halted a moment on the steps and then moved toward the door. Tom
+heaved a great sigh as she put her foot on the threshold. But his face
+lit up, right away, for she tossed a pansy over the fence a moment
+before she disappeared.
+
+The boy ran around and stopped within a foot or two of the flower, and
+then shaded his eyes with his hand and began to look down street as if
+he had discovered something of interest going on in that direction.
+Presently he picked up a straw and began trying to balance it on his
+nose, with his head tilted far back; and as he moved from side to side,
+in his efforts, he edged nearer and nearer toward the pansy; finally
+his bare foot rested upon it, his pliant toes closed upon it, and he
+hopped away with the treasure and disappeared round the corner. But
+only for a minute--only while he could button the flower inside his
+jacket, next his heart--or next his stomach, possibly, for he was not
+much posted in anatomy, and not hypercritical, anyway.
+
+He returned, now, and hung about the fence till nightfall, "showing
+off," as before; but the girl never exhibited herself again, though Tom
+comforted himself a little with the hope that she had been near some
+window, meantime, and been aware of his attentions. Finally he strode
+home reluctantly, with his poor head full of visions.
+
+All through supper his spirits were so high that his aunt wondered
+"what had got into the child." He took a good scolding about clodding
+Sid, and did not seem to mind it in the least. He tried to steal sugar
+under his aunt's very nose, and got his knuckles rapped for it. He said:
+
+"Aunt, you don't whack Sid when he takes it."
+
+"Well, Sid don't torment a body the way you do. You'd be always into
+that sugar if I warn't watching you."
+
+Presently she stepped into the kitchen, and Sid, happy in his
+immunity, reached for the sugar-bowl--a sort of glorying over Tom which
+was wellnigh unbearable. But Sid's fingers slipped and the bowl dropped
+and broke. Tom was in ecstasies. In such ecstasies that he even
+controlled his tongue and was silent. He said to himself that he would
+not speak a word, even when his aunt came in, but would sit perfectly
+still till she asked who did the mischief; and then he would tell, and
+there would be nothing so good in the world as to see that pet model
+"catch it." He was so brimful of exultation that he could hardly hold
+himself when the old lady came back and stood above the wreck
+discharging lightnings of wrath from over her spectacles. He said to
+himself, "Now it's coming!" And the next instant he was sprawling on
+the floor! The potent palm was uplifted to strike again when Tom cried
+out:
+
+"Hold on, now, what 'er you belting ME for?--Sid broke it!"
+
+Aunt Polly paused, perplexed, and Tom looked for healing pity. But
+when she got her tongue again, she only said:
+
+"Umf! Well, you didn't get a lick amiss, I reckon. You been into some
+other audacious mischief when I wasn't around, like enough."
+
+Then her conscience reproached her, and she yearned to say something
+kind and loving; but she judged that this would be construed into a
+confession that she had been in the wrong, and discipline forbade that.
+So she kept silence, and went about her affairs with a troubled heart.
+Tom sulked in a corner and exalted his woes. He knew that in her heart
+his aunt was on her knees to him, and he was morosely gratified by the
+consciousness of it. He would hang out no signals, he would take notice
+of none. He knew that a yearning glance fell upon him, now and then,
+through a film of tears, but he refused recognition of it. He pictured
+himself lying sick unto death and his aunt bending over him beseeching
+one little forgiving word, but he would turn his face to the wall, and
+die with that word unsaid. Ah, how would she feel then? And he pictured
+himself brought home from the river, dead, with his curls all wet, and
+his sore heart at rest. How she would throw herself upon him, and how
+her tears would fall like rain, and her lips pray God to give her back
+her boy and she would never, never abuse him any more! But he would lie
+there cold and white and make no sign--a poor little sufferer, whose
+griefs were at an end. He so worked upon his feelings with the pathos
+of these dreams, that he had to keep swallowing, he was so like to
+choke; and his eyes swam in a blur of water, which overflowed when he
+winked, and ran down and trickled from the end of his nose. And such a
+luxury to him was this petting of his sorrows, that he could not bear
+to have any worldly cheeriness or any grating delight intrude upon it;
+it was too sacred for such contact; and so, presently, when his cousin
+Mary danced in, all alive with the joy of seeing home again after an
+age-long visit of one week to the country, he got up and moved in
+clouds and darkness out at one door as she brought song and sunshine in
+at the other.
+
+He wandered far from the accustomed haunts of boys, and sought
+desolate places that were in harmony with his spirit. A log raft in the
+river invited him, and he seated himself on its outer edge and
+contemplated the dreary vastness of the stream, wishing, the while,
+that he could only be drowned, all at once and unconsciously, without
+undergoing the uncomfortable routine devised by nature. Then he thought
+of his flower. He got it out, rumpled and wilted, and it mightily
+increased his dismal felicity. He wondered if she would pity him if she
+knew? Would she cry, and wish that she had a right to put her arms
+around his neck and comfort him? Or would she turn coldly away like all
+the hollow world? This picture brought such an agony of pleasurable
+suffering that he worked it over and over again in his mind and set it
+up in new and varied lights, till he wore it threadbare. At last he
+rose up sighing and departed in the darkness.
+
+About half-past nine or ten o'clock he came along the deserted street
+to where the Adored Unknown lived; he paused a moment; no sound fell
+upon his listening ear; a candle was casting a dull glow upon the
+curtain of a second-story window. Was the sacred presence there? He
+climbed the fence, threaded his stealthy way through the plants, till
+he stood under that window; he looked up at it long, and with emotion;
+then he laid him down on the ground under it, disposing himself upon
+his back, with his hands clasped upon his breast and holding his poor
+wilted flower. And thus he would die--out in the cold world, with no
+shelter over his homeless head, no friendly hand to wipe the
+death-damps from his brow, no loving face to bend pityingly over him
+when the great agony came. And thus SHE would see him when she looked
+out upon the glad morning, and oh! would she drop one little tear upon
+his poor, lifeless form, would she heave one little sigh to see a bright
+young life so rudely blighted, so untimely cut down?
+
+The window went up, a maid-servant's discordant voice profaned the
+holy calm, and a deluge of water drenched the prone martyr's remains!
+
+The strangling hero sprang up with a relieving snort. There was a whiz
+as of a missile in the air, mingled with the murmur of a curse, a sound
+as of shivering glass followed, and a small, vague form went over the
+fence and shot away in the gloom.
+
+Not long after, as Tom, all undressed for bed, was surveying his
+drenched garments by the light of a tallow dip, Sid woke up; but if he
+had any dim idea of making any "references to allusions," he thought
+better of it and held his peace, for there was danger in Tom's eye.
+
+Tom turned in without the added vexation of prayers, and Sid made
+mental note of the omission.
+
+
+
+CHAPTER IV
+
+THE sun rose upon a tranquil world, and beamed down upon the peaceful
+village like a benediction. Breakfast over, Aunt Polly had family
+worship: it began with a prayer built from the ground up of solid
+courses of Scriptural quotations, welded together with a thin mortar of
+originality; and from the summit of this she delivered a grim chapter
+of the Mosaic Law, as from Sinai.
+
+Then Tom girded up his loins, so to speak, and went to work to "get
+his verses." Sid had learned his lesson days before. Tom bent all his
+energies to the memorizing of five verses, and he chose part of the
+Sermon on the Mount, because he could find no verses that were shorter.
+At the end of half an hour Tom had a vague general idea of his lesson,
+but no more, for his mind was traversing the whole field of human
+thought, and his hands were busy with distracting recreations. Mary
+took his book to hear him recite, and he tried to find his way through
+the fog:
+
+"Blessed are the--a--a--"
+
+"Poor"--
+
+"Yes--poor; blessed are the poor--a--a--"
+
+"In spirit--"
+
+"In spirit; blessed are the poor in spirit, for they--they--"
+
+"THEIRS--"
+
+"For THEIRS. Blessed are the poor in spirit, for theirs is the kingdom
+of heaven. Blessed are they that mourn, for they--they--"
+
+"Sh--"
+
+"For they--a--"
+
+"S, H, A--"
+
+"For they S, H--Oh, I don't know what it is!"
+
+"SHALL!"
+
+"Oh, SHALL! for they shall--for they shall--a--a--shall mourn--a--a--
+blessed are they that shall--they that--a--they that shall mourn, for
+they shall--a--shall WHAT? Why don't you tell me, Mary?--what do you
+want to be so mean for?"
+
+"Oh, Tom, you poor thick-headed thing, I'm not teasing you. I wouldn't
+do that. You must go and learn it again. Don't you be discouraged, Tom,
+you'll manage it--and if you do, I'll give you something ever so nice.
+There, now, that's a good boy."
+
+"All right! What is it, Mary, tell me what it is."
+
+"Never you mind, Tom. You know if I say it's nice, it is nice."
+
+"You bet you that's so, Mary. All right, I'll tackle it again."
+
+And he did "tackle it again"--and under the double pressure of
+curiosity and prospective gain he did it with such spirit that he
+accomplished a shining success. Mary gave him a brand-new "Barlow"
+knife worth twelve and a half cents; and the convulsion of delight that
+swept his system shook him to his foundations. True, the knife would
+not cut anything, but it was a "sure-enough" Barlow, and there was
+inconceivable grandeur in that--though where the Western boys ever got
+the idea that such a weapon could possibly be counterfeited to its
+injury is an imposing mystery and will always remain so, perhaps. Tom
+contrived to scarify the cupboard with it, and was arranging to begin
+on the bureau, when he was called off to dress for Sunday-school.
+
+Mary gave him a tin basin of water and a piece of soap, and he went
+outside the door and set the basin on a little bench there; then he
+dipped the soap in the water and laid it down; turned up his sleeves;
+poured out the water on the ground, gently, and then entered the
+kitchen and began to wipe his face diligently on the towel behind the
+door. But Mary removed the towel and said:
+
+"Now ain't you ashamed, Tom. You mustn't be so bad. Water won't hurt
+you."
+
+Tom was a trifle disconcerted. The basin was refilled, and this time
+he stood over it a little while, gathering resolution; took in a big
+breath and began. When he entered the kitchen presently, with both eyes
+shut and groping for the towel with his hands, an honorable testimony
+of suds and water was dripping from his face. But when he emerged from
+the towel, he was not yet satisfactory, for the clean territory stopped
+short at his chin and his jaws, like a mask; below and beyond this line
+there was a dark expanse of unirrigated soil that spread downward in
+front and backward around his neck. Mary took him in hand, and when she
+was done with him he was a man and a brother, without distinction of
+color, and his saturated hair was neatly brushed, and its short curls
+wrought into a dainty and symmetrical general effect. [He privately
+smoothed out the curls, with labor and difficulty, and plastered his
+hair close down to his head; for he held curls to be effeminate, and
+his own filled his life with bitterness.] Then Mary got out a suit of
+his clothing that had been used only on Sundays during two years--they
+were simply called his "other clothes"--and so by that we know the
+size of his wardrobe. The girl "put him to rights" after he had dressed
+himself; she buttoned his neat roundabout up to his chin, turned his
+vast shirt collar down over his shoulders, brushed him off and crowned
+him with his speckled straw hat. He now looked exceedingly improved and
+uncomfortable. He was fully as uncomfortable as he looked; for there
+was a restraint about whole clothes and cleanliness that galled him. He
+hoped that Mary would forget his shoes, but the hope was blighted; she
+coated them thoroughly with tallow, as was the custom, and brought them
+out. He lost his temper and said he was always being made to do
+everything he didn't want to do. But Mary said, persuasively:
+
+"Please, Tom--that's a good boy."
+
+So he got into the shoes snarling. Mary was soon ready, and the three
+children set out for Sunday-school--a place that Tom hated with his
+whole heart; but Sid and Mary were fond of it.
+
+Sabbath-school hours were from nine to half-past ten; and then church
+service. Two of the children always remained for the sermon
+voluntarily, and the other always remained too--for stronger reasons.
+The church's high-backed, uncushioned pews would seat about three
+hundred persons; the edifice was but a small, plain affair, with a sort
+of pine board tree-box on top of it for a steeple. At the door Tom
+dropped back a step and accosted a Sunday-dressed comrade:
+
+"Say, Billy, got a yaller ticket?"
+
+"Yes."
+
+"What'll you take for her?"
+
+"What'll you give?"
+
+"Piece of lickrish and a fish-hook."
+
+"Less see 'em."
+
+Tom exhibited. They were satisfactory, and the property changed hands.
+Then Tom traded a couple of white alleys for three red tickets, and
+some small trifle or other for a couple of blue ones. He waylaid other
+boys as they came, and went on buying tickets of various colors ten or
+fifteen minutes longer. He entered the church, now, with a swarm of
+clean and noisy boys and girls, proceeded to his seat and started a
+quarrel with the first boy that came handy. The teacher, a grave,
+elderly man, interfered; then turned his back a moment and Tom pulled a
+boy's hair in the next bench, and was absorbed in his book when the boy
+turned around; stuck a pin in another boy, presently, in order to hear
+him say "Ouch!" and got a new reprimand from his teacher. Tom's whole
+class were of a pattern--restless, noisy, and troublesome. When they
+came to recite their lessons, not one of them knew his verses
+perfectly, but had to be prompted all along. However, they worried
+through, and each got his reward--in small blue tickets, each with a
+passage of Scripture on it; each blue ticket was pay for two verses of
+the recitation. Ten blue tickets equalled a red one, and could be
+exchanged for it; ten red tickets equalled a yellow one; for ten yellow
+tickets the superintendent gave a very plainly bound Bible (worth forty
+cents in those easy times) to the pupil. How many of my readers would
+have the industry and application to memorize two thousand verses, even
+for a Dore Bible? And yet Mary had acquired two Bibles in this way--it
+was the patient work of two years--and a boy of German parentage had
+won four or five. He once recited three thousand verses without
+stopping; but the strain upon his mental faculties was too great, and
+he was little better than an idiot from that day forth--a grievous
+misfortune for the school, for on great occasions, before company, the
+superintendent (as Tom expressed it) had always made this boy come out
+and "spread himself." Only the older pupils managed to keep their
+tickets and stick to their tedious work long enough to get a Bible, and
+so the delivery of one of these prizes was a rare and noteworthy
+circumstance; the successful pupil was so great and conspicuous for
+that day that on the spot every scholar's heart was fired with a fresh
+ambition that often lasted a couple of weeks. It is possible that Tom's
+mental stomach had never really hungered for one of those prizes, but
+unquestionably his entire being had for many a day longed for the glory
+and the eclat that came with it.
+
+In due course the superintendent stood up in front of the pulpit, with
+a closed hymn-book in his hand and his forefinger inserted between its
+leaves, and commanded attention. When a Sunday-school superintendent
+makes his customary little speech, a hymn-book in the hand is as
+necessary as is the inevitable sheet of music in the hand of a singer
+who stands forward on the platform and sings a solo at a concert
+--though why, is a mystery: for neither the hymn-book nor the sheet of
+music is ever referred to by the sufferer. This superintendent was a
+slim creature of thirty-five, with a sandy goatee and short sandy hair;
+he wore a stiff standing-collar whose upper edge almost reached his
+ears and whose sharp points curved forward abreast the corners of his
+mouth--a fence that compelled a straight lookout ahead, and a turning
+of the whole body when a side view was required; his chin was propped
+on a spreading cravat which was as broad and as long as a bank-note,
+and had fringed ends; his boot toes were turned sharply up, in the
+fashion of the day, like sleigh-runners--an effect patiently and
+laboriously produced by the young men by sitting with their toes
+pressed against a wall for hours together. Mr. Walters was very earnest
+of mien, and very sincere and honest at heart; and he held sacred
+things and places in such reverence, and so separated them from worldly
+matters, that unconsciously to himself his Sunday-school voice had
+acquired a peculiar intonation which was wholly absent on week-days. He
+began after this fashion:
+
+"Now, children, I want you all to sit up just as straight and pretty
+as you can and give me all your attention for a minute or two. There
+--that is it. That is the way good little boys and girls should do. I see
+one little girl who is looking out of the window--I am afraid she
+thinks I am out there somewhere--perhaps up in one of the trees making
+a speech to the little birds. [Applausive titter.] I want to tell you
+how good it makes me feel to see so many bright, clean little faces
+assembled in a place like this, learning to do right and be good." And
+so forth and so on. It is not necessary to set down the rest of the
+oration. It was of a pattern which does not vary, and so it is familiar
+to us all.
+
+The latter third of the speech was marred by the resumption of fights
+and other recreations among certain of the bad boys, and by fidgetings
+and whisperings that extended far and wide, washing even to the bases
+of isolated and incorruptible rocks like Sid and Mary. But now every
+sound ceased suddenly, with the subsidence of Mr. Walters' voice, and
+the conclusion of the speech was received with a burst of silent
+gratitude.
+
+A good part of the whispering had been occasioned by an event which
+was more or less rare--the entrance of visitors: lawyer Thatcher,
+accompanied by a very feeble and aged man; a fine, portly, middle-aged
+gentleman with iron-gray hair; and a dignified lady who was doubtless
+the latter's wife. The lady was leading a child. Tom had been restless
+and full of chafings and repinings; conscience-smitten, too--he could
+not meet Amy Lawrence's eye, he could not brook her loving gaze. But
+when he saw this small new-comer his soul was all ablaze with bliss in
+a moment. The next moment he was "showing off" with all his might
+--cuffing boys, pulling hair, making faces--in a word, using every art
+that seemed likely to fascinate a girl and win her applause. His
+exaltation had but one alloy--the memory of his humiliation in this
+angel's garden--and that record in sand was fast washing out, under
+the waves of happiness that were sweeping over it now.
+
+The visitors were given the highest seat of honor, and as soon as Mr.
+Walters' speech was finished, he introduced them to the school. The
+middle-aged man turned out to be a prodigious personage--no less a one
+than the county judge--altogether the most august creation these
+children had ever looked upon--and they wondered what kind of material
+he was made of--and they half wanted to hear him roar, and were half
+afraid he might, too. He was from Constantinople, twelve miles away--so
+he had travelled, and seen the world--these very eyes had looked upon
+the county court-house--which was said to have a tin roof. The awe
+which these reflections inspired was attested by the impressive silence
+and the ranks of staring eyes. This was the great Judge Thatcher,
+brother of their own lawyer. Jeff Thatcher immediately went forward, to
+be familiar with the great man and be envied by the school. It would
+have been music to his soul to hear the whisperings:
+
+"Look at him, Jim! He's a going up there. Say--look! he's a going to
+shake hands with him--he IS shaking hands with him! By jings, don't you
+wish you was Jeff?"
+
+Mr. Walters fell to "showing off," with all sorts of official
+bustlings and activities, giving orders, delivering judgments,
+discharging directions here, there, everywhere that he could find a
+target. The librarian "showed off"--running hither and thither with his
+arms full of books and making a deal of the splutter and fuss that
+insect authority delights in. The young lady teachers "showed off"
+--bending sweetly over pupils that were lately being boxed, lifting
+pretty warning fingers at bad little boys and patting good ones
+lovingly. The young gentlemen teachers "showed off" with small
+scoldings and other little displays of authority and fine attention to
+discipline--and most of the teachers, of both sexes, found business up
+at the library, by the pulpit; and it was business that frequently had
+to be done over again two or three times (with much seeming vexation).
+The little girls "showed off" in various ways, and the little boys
+"showed off" with such diligence that the air was thick with paper wads
+and the murmur of scufflings. And above it all the great man sat and
+beamed a majestic judicial smile upon all the house, and warmed himself
+in the sun of his own grandeur--for he was "showing off," too.
+
+There was only one thing wanting to make Mr. Walters' ecstasy
+complete, and that was a chance to deliver a Bible-prize and exhibit a
+prodigy. Several pupils had a few yellow tickets, but none had enough
+--he had been around among the star pupils inquiring. He would have given
+worlds, now, to have that German lad back again with a sound mind.
+
+And now at this moment, when hope was dead, Tom Sawyer came forward
+with nine yellow tickets, nine red tickets, and ten blue ones, and
+demanded a Bible. This was a thunderbolt out of a clear sky. Walters
+was not expecting an application from this source for the next ten
+years. But there was no getting around it--here were the certified
+checks, and they were good for their face. Tom was therefore elevated
+to a place with the Judge and the other elect, and the great news was
+announced from headquarters. It was the most stunning surprise of the
+decade, and so profound was the sensation that it lifted the new hero
+up to the judicial one's altitude, and the school had two marvels to
+gaze upon in place of one. The boys were all eaten up with envy--but
+those that suffered the bitterest pangs were those who perceived too
+late that they themselves had contributed to this hated splendor by
+trading tickets to Tom for the wealth he had amassed in selling
+whitewashing privileges. These despised themselves, as being the dupes
+of a wily fraud, a guileful snake in the grass.
+
+The prize was delivered to Tom with as much effusion as the
+superintendent could pump up under the circumstances; but it lacked
+somewhat of the true gush, for the poor fellow's instinct taught him
+that there was a mystery here that could not well bear the light,
+perhaps; it was simply preposterous that this boy had warehoused two
+thousand sheaves of Scriptural wisdom on his premises--a dozen would
+strain his capacity, without a doubt.
+
+Amy Lawrence was proud and glad, and she tried to make Tom see it in
+her face--but he wouldn't look. She wondered; then she was just a grain
+troubled; next a dim suspicion came and went--came again; she watched;
+a furtive glance told her worlds--and then her heart broke, and she was
+jealous, and angry, and the tears came and she hated everybody. Tom
+most of all (she thought).
+
+Tom was introduced to the Judge; but his tongue was tied, his breath
+would hardly come, his heart quaked--partly because of the awful
+greatness of the man, but mainly because he was her parent. He would
+have liked to fall down and worship him, if it were in the dark. The
+Judge put his hand on Tom's head and called him a fine little man, and
+asked him what his name was. The boy stammered, gasped, and got it out:
+
+"Tom."
+
+"Oh, no, not Tom--it is--"
+
+"Thomas."
+
+"Ah, that's it. I thought there was more to it, maybe. That's very
+well. But you've another one I daresay, and you'll tell it to me, won't
+you?"
+
+"Tell the gentleman your other name, Thomas," said Walters, "and say
+sir. You mustn't forget your manners."
+
+"Thomas Sawyer--sir."
+
+"That's it! That's a good boy. Fine boy. Fine, manly little fellow.
+Two thousand verses is a great many--very, very great many. And you
+never can be sorry for the trouble you took to learn them; for
+knowledge is worth more than anything there is in the world; it's what
+makes great men and good men; you'll be a great man and a good man
+yourself, some day, Thomas, and then you'll look back and say, It's all
+owing to the precious Sunday-school privileges of my boyhood--it's all
+owing to my dear teachers that taught me to learn--it's all owing to
+the good superintendent, who encouraged me, and watched over me, and
+gave me a beautiful Bible--a splendid elegant Bible--to keep and have
+it all for my own, always--it's all owing to right bringing up! That is
+what you will say, Thomas--and you wouldn't take any money for those
+two thousand verses--no indeed you wouldn't. And now you wouldn't mind
+telling me and this lady some of the things you've learned--no, I know
+you wouldn't--for we are proud of little boys that learn. Now, no
+doubt you know the names of all the twelve disciples. Won't you tell us
+the names of the first two that were appointed?"
+
+Tom was tugging at a button-hole and looking sheepish. He blushed,
+now, and his eyes fell. Mr. Walters' heart sank within him. He said to
+himself, it is not possible that the boy can answer the simplest
+question--why DID the Judge ask him? Yet he felt obliged to speak up
+and say:
+
+"Answer the gentleman, Thomas--don't be afraid."
+
+Tom still hung fire.
+
+"Now I know you'll tell me," said the lady. "The names of the first
+two disciples were--"
+
+"DAVID AND GOLIAH!"
+
+Let us draw the curtain of charity over the rest of the scene.
+
+
+
+CHAPTER V
+
+ABOUT half-past ten the cracked bell of the small church began to
+ring, and presently the people began to gather for the morning sermon.
+The Sunday-school children distributed themselves about the house and
+occupied pews with their parents, so as to be under supervision. Aunt
+Polly came, and Tom and Sid and Mary sat with her--Tom being placed
+next the aisle, in order that he might be as far away from the open
+window and the seductive outside summer scenes as possible. The crowd
+filed up the aisles: the aged and needy postmaster, who had seen better
+days; the mayor and his wife--for they had a mayor there, among other
+unnecessaries; the justice of the peace; the widow Douglass, fair,
+smart, and forty, a generous, good-hearted soul and well-to-do, her
+hill mansion the only palace in the town, and the most hospitable and
+much the most lavish in the matter of festivities that St. Petersburg
+could boast; the bent and venerable Major and Mrs. Ward; lawyer
+Riverson, the new notable from a distance; next the belle of the
+village, followed by a troop of lawn-clad and ribbon-decked young
+heart-breakers; then all the young clerks in town in a body--for they
+had stood in the vestibule sucking their cane-heads, a circling wall of
+oiled and simpering admirers, till the last girl had run their gantlet;
+and last of all came the Model Boy, Willie Mufferson, taking as heedful
+care of his mother as if she were cut glass. He always brought his
+mother to church, and was the pride of all the matrons. The boys all
+hated him, he was so good. And besides, he had been "thrown up to them"
+so much. His white handkerchief was hanging out of his pocket behind, as
+usual on Sundays--accidentally. Tom had no handkerchief, and he looked
+upon boys who had as snobs.
+
+The congregation being fully assembled, now, the bell rang once more,
+to warn laggards and stragglers, and then a solemn hush fell upon the
+church which was only broken by the tittering and whispering of the
+choir in the gallery. The choir always tittered and whispered all
+through service. There was once a church choir that was not ill-bred,
+but I have forgotten where it was, now. It was a great many years ago,
+and I can scarcely remember anything about it, but I think it was in
+some foreign country.
+
+The minister gave out the hymn, and read it through with a relish, in
+a peculiar style which was much admired in that part of the country.
+His voice began on a medium key and climbed steadily up till it reached
+a certain point, where it bore with strong emphasis upon the topmost
+word and then plunged down as if from a spring-board:
+
+  Shall I be car-ri-ed toe the skies, on flow'ry BEDS of ease,
+
+  Whilst others fight to win the prize, and sail thro' BLOODY seas?
+
+He was regarded as a wonderful reader. At church "sociables" he was
+always called upon to read poetry; and when he was through, the ladies
+would lift up their hands and let them fall helplessly in their laps,
+and "wall" their eyes, and shake their heads, as much as to say, "Words
+cannot express it; it is too beautiful, TOO beautiful for this mortal
+earth."
+
+After the hymn had been sung, the Rev. Mr. Sprague turned himself into
+a bulletin-board, and read off "notices" of meetings and societies and
+things till it seemed that the list would stretch out to the crack of
+doom--a queer custom which is still kept up in America, even in cities,
+away here in this age of abundant newspapers. Often, the less there is
+to justify a traditional custom, the harder it is to get rid of it.
+
+And now the minister prayed. A good, generous prayer it was, and went
+into details: it pleaded for the church, and the little children of the
+church; for the other churches of the village; for the village itself;
+for the county; for the State; for the State officers; for the United
+States; for the churches of the United States; for Congress; for the
+President; for the officers of the Government; for poor sailors, tossed
+by stormy seas; for the oppressed millions groaning under the heel of
+European monarchies and Oriental despotisms; for such as have the light
+and the good tidings, and yet have not eyes to see nor ears to hear
+withal; for the heathen in the far islands of the sea; and closed with
+a supplication that the words he was about to speak might find grace
+and favor, and be as seed sown in fertile ground, yielding in time a
+grateful harvest of good. Amen.
+
+There was a rustling of dresses, and the standing congregation sat
+down. The boy whose history this book relates did not enjoy the prayer,
+he only endured it--if he even did that much. He was restive all
+through it; he kept tally of the details of the prayer, unconsciously
+--for he was not listening, but he knew the ground of old, and the
+clergyman's regular route over it--and when a little trifle of new
+matter was interlarded, his ear detected it and his whole nature
+resented it; he considered additions unfair, and scoundrelly. In the
+midst of the prayer a fly had lit on the back of the pew in front of
+him and tortured his spirit by calmly rubbing its hands together,
+embracing its head with its arms, and polishing it so vigorously that
+it seemed to almost part company with the body, and the slender thread
+of a neck was exposed to view; scraping its wings with its hind legs
+and smoothing them to its body as if they had been coat-tails; going
+through its whole toilet as tranquilly as if it knew it was perfectly
+safe. As indeed it was; for as sorely as Tom's hands itched to grab for
+it they did not dare--he believed his soul would be instantly destroyed
+if he did such a thing while the prayer was going on. But with the
+closing sentence his hand began to curve and steal forward; and the
+instant the "Amen" was out the fly was a prisoner of war. His aunt
+detected the act and made him let it go.
+
+The minister gave out his text and droned along monotonously through
+an argument that was so prosy that many a head by and by began to nod
+--and yet it was an argument that dealt in limitless fire and brimstone
+and thinned the predestined elect down to a company so small as to be
+hardly worth the saving. Tom counted the pages of the sermon; after
+church he always knew how many pages there had been, but he seldom knew
+anything else about the discourse. However, this time he was really
+interested for a little while. The minister made a grand and moving
+picture of the assembling together of the world's hosts at the
+millennium when the lion and the lamb should lie down together and a
+little child should lead them. But the pathos, the lesson, the moral of
+the great spectacle were lost upon the boy; he only thought of the
+conspicuousness of the principal character before the on-looking
+nations; his face lit with the thought, and he said to himself that he
+wished he could be that child, if it was a tame lion.
+
+Now he lapsed into suffering again, as the dry argument was resumed.
+Presently he bethought him of a treasure he had and got it out. It was
+a large black beetle with formidable jaws--a "pinchbug," he called it.
+It was in a percussion-cap box. The first thing the beetle did was to
+take him by the finger. A natural fillip followed, the beetle went
+floundering into the aisle and lit on its back, and the hurt finger
+went into the boy's mouth. The beetle lay there working its helpless
+legs, unable to turn over. Tom eyed it, and longed for it; but it was
+safe out of his reach. Other people uninterested in the sermon found
+relief in the beetle, and they eyed it too. Presently a vagrant poodle
+dog came idling along, sad at heart, lazy with the summer softness and
+the quiet, weary of captivity, sighing for change. He spied the beetle;
+the drooping tail lifted and wagged. He surveyed the prize; walked
+around it; smelt at it from a safe distance; walked around it again;
+grew bolder, and took a closer smell; then lifted his lip and made a
+gingerly snatch at it, just missing it; made another, and another;
+began to enjoy the diversion; subsided to his stomach with the beetle
+between his paws, and continued his experiments; grew weary at last,
+and then indifferent and absent-minded. His head nodded, and little by
+little his chin descended and touched the enemy, who seized it. There
+was a sharp yelp, a flirt of the poodle's head, and the beetle fell a
+couple of yards away, and lit on its back once more. The neighboring
+spectators shook with a gentle inward joy, several faces went behind
+fans and handkerchiefs, and Tom was entirely happy. The dog looked
+foolish, and probably felt so; but there was resentment in his heart,
+too, and a craving for revenge. So he went to the beetle and began a
+wary attack on it again; jumping at it from every point of a circle,
+lighting with his fore-paws within an inch of the creature, making even
+closer snatches at it with his teeth, and jerking his head till his
+ears flapped again. But he grew tired once more, after a while; tried
+to amuse himself with a fly but found no relief; followed an ant
+around, with his nose close to the floor, and quickly wearied of that;
+yawned, sighed, forgot the beetle entirely, and sat down on it. Then
+there was a wild yelp of agony and the poodle went sailing up the
+aisle; the yelps continued, and so did the dog; he crossed the house in
+front of the altar; he flew down the other aisle; he crossed before the
+doors; he clamored up the home-stretch; his anguish grew with his
+progress, till presently he was but a woolly comet moving in its orbit
+with the gleam and the speed of light. At last the frantic sufferer
+sheered from its course, and sprang into its master's lap; he flung it
+out of the window, and the voice of distress quickly thinned away and
+died in the distance.
+
+By this time the whole church was red-faced and suffocating with
+suppressed laughter, and the sermon had come to a dead standstill. The
+discourse was resumed presently, but it went lame and halting, all
+possibility of impressiveness being at an end; for even the gravest
+sentiments were constantly being received with a smothered burst of
+unholy mirth, under cover of some remote pew-back, as if the poor
+parson had said a rarely facetious thing. It was a genuine relief to
+the whole congregation when the ordeal was over and the benediction
+pronounced.
+
+Tom Sawyer went home quite cheerful, thinking to himself that there
+was some satisfaction about divine service when there was a bit of
+variety in it. He had but one marring thought; he was willing that the
+dog should play with his pinchbug, but he did not think it was upright
+in him to carry it off.
+
+
+
+CHAPTER VI
+
+MONDAY morning found Tom Sawyer miserable. Monday morning always found
+him so--because it began another week's slow suffering in school. He
+generally began that day with wishing he had had no intervening
+holiday, it made the going into captivity and fetters again so much
+more odious.
+
+Tom lay thinking. Presently it occurred to him that he wished he was
+sick; then he could stay home from school. Here was a vague
+possibility. He canvassed his system. No ailment was found, and he
+investigated again. This time he thought he could detect colicky
+symptoms, and he began to encourage them with considerable hope. But
+they soon grew feeble, and presently died wholly away. He reflected
+further. Suddenly he discovered something. One of his upper front teeth
+was loose. This was lucky; he was about to begin to groan, as a
+"starter," as he called it, when it occurred to him that if he came
+into court with that argument, his aunt would pull it out, and that
+would hurt. So he thought he would hold the tooth in reserve for the
+present, and seek further. Nothing offered for some little time, and
+then he remembered hearing the doctor tell about a certain thing that
+laid up a patient for two or three weeks and threatened to make him
+lose a finger. So the boy eagerly drew his sore toe from under the
+sheet and held it up for inspection. But now he did not know the
+necessary symptoms. However, it seemed well worth while to chance it,
+so he fell to groaning with considerable spirit.
+
+But Sid slept on unconscious.
+
+Tom groaned louder, and fancied that he began to feel pain in the toe.
+
+No result from Sid.
+
+Tom was panting with his exertions by this time. He took a rest and
+then swelled himself up and fetched a succession of admirable groans.
+
+Sid snored on.
+
+Tom was aggravated. He said, "Sid, Sid!" and shook him. This course
+worked well, and Tom began to groan again. Sid yawned, stretched, then
+brought himself up on his elbow with a snort, and began to stare at
+Tom. Tom went on groaning. Sid said:
+
+"Tom! Say, Tom!" [No response.] "Here, Tom! TOM! What is the matter,
+Tom?" And he shook him and looked in his face anxiously.
+
+Tom moaned out:
+
+"Oh, don't, Sid. Don't joggle me."
+
+"Why, what's the matter, Tom? I must call auntie."
+
+"No--never mind. It'll be over by and by, maybe. Don't call anybody."
+
+"But I must! DON'T groan so, Tom, it's awful. How long you been this
+way?"
+
+"Hours. Ouch! Oh, don't stir so, Sid, you'll kill me."
+
+"Tom, why didn't you wake me sooner? Oh, Tom, DON'T! It makes my
+flesh crawl to hear you. Tom, what is the matter?"
+
+"I forgive you everything, Sid. [Groan.] Everything you've ever done
+to me. When I'm gone--"
+
+"Oh, Tom, you ain't dying, are you? Don't, Tom--oh, don't. Maybe--"
+
+"I forgive everybody, Sid. [Groan.] Tell 'em so, Sid. And Sid, you
+give my window-sash and my cat with one eye to that new girl that's
+come to town, and tell her--"
+
+But Sid had snatched his clothes and gone. Tom was suffering in
+reality, now, so handsomely was his imagination working, and so his
+groans had gathered quite a genuine tone.
+
+Sid flew down-stairs and said:
+
+"Oh, Aunt Polly, come! Tom's dying!"
+
+"Dying!"
+
+"Yes'm. Don't wait--come quick!"
+
+"Rubbage! I don't believe it!"
+
+But she fled up-stairs, nevertheless, with Sid and Mary at her heels.
+And her face grew white, too, and her lip trembled. When she reached
+the bedside she gasped out:
+
+"You, Tom! Tom, what's the matter with you?"
+
+"Oh, auntie, I'm--"
+
+"What's the matter with you--what is the matter with you, child?"
+
+"Oh, auntie, my sore toe's mortified!"
+
+The old lady sank down into a chair and laughed a little, then cried a
+little, then did both together. This restored her and she said:
+
+"Tom, what a turn you did give me. Now you shut up that nonsense and
+climb out of this."
+
+The groans ceased and the pain vanished from the toe. The boy felt a
+little foolish, and he said:
+
+"Aunt Polly, it SEEMED mortified, and it hurt so I never minded my
+tooth at all."
+
+"Your tooth, indeed! What's the matter with your tooth?"
+
+"One of them's loose, and it aches perfectly awful."
+
+"There, there, now, don't begin that groaning again. Open your mouth.
+Well--your tooth IS loose, but you're not going to die about that.
+Mary, get me a silk thread, and a chunk of fire out of the kitchen."
+
+Tom said:
+
+"Oh, please, auntie, don't pull it out. It don't hurt any more. I wish
+I may never stir if it does. Please don't, auntie. I don't want to stay
+home from school."
+
+"Oh, you don't, don't you? So all this row was because you thought
+you'd get to stay home from school and go a-fishing? Tom, Tom, I love
+you so, and you seem to try every way you can to break my old heart
+with your outrageousness." By this time the dental instruments were
+ready. The old lady made one end of the silk thread fast to Tom's tooth
+with a loop and tied the other to the bedpost. Then she seized the
+chunk of fire and suddenly thrust it almost into the boy's face. The
+tooth hung dangling by the bedpost, now.
+
+But all trials bring their compensations. As Tom wended to school
+after breakfast, he was the envy of every boy he met because the gap in
+his upper row of teeth enabled him to expectorate in a new and
+admirable way. He gathered quite a following of lads interested in the
+exhibition; and one that had cut his finger and had been a centre of
+fascination and homage up to this time, now found himself suddenly
+without an adherent, and shorn of his glory. His heart was heavy, and
+he said with a disdain which he did not feel that it wasn't anything to
+spit like Tom Sawyer; but another boy said, "Sour grapes!" and he
+wandered away a dismantled hero.
+
+Shortly Tom came upon the juvenile pariah of the village, Huckleberry
+Finn, son of the town drunkard. Huckleberry was cordially hated and
+dreaded by all the mothers of the town, because he was idle and lawless
+and vulgar and bad--and because all their children admired him so, and
+delighted in his forbidden society, and wished they dared to be like
+him. Tom was like the rest of the respectable boys, in that he envied
+Huckleberry his gaudy outcast condition, and was under strict orders
+not to play with him. So he played with him every time he got a chance.
+Huckleberry was always dressed in the cast-off clothes of full-grown
+men, and they were in perennial bloom and fluttering with rags. His hat
+was a vast ruin with a wide crescent lopped out of its brim; his coat,
+when he wore one, hung nearly to his heels and had the rearward buttons
+far down the back; but one suspender supported his trousers; the seat
+of the trousers bagged low and contained nothing, the fringed legs
+dragged in the dirt when not rolled up.
+
+Huckleberry came and went, at his own free will. He slept on doorsteps
+in fine weather and in empty hogsheads in wet; he did not have to go to
+school or to church, or call any being master or obey anybody; he could
+go fishing or swimming when and where he chose, and stay as long as it
+suited him; nobody forbade him to fight; he could sit up as late as he
+pleased; he was always the first boy that went barefoot in the spring
+and the last to resume leather in the fall; he never had to wash, nor
+put on clean clothes; he could swear wonderfully. In a word, everything
+that goes to make life precious that boy had. So thought every
+harassed, hampered, respectable boy in St. Petersburg.
+
+Tom hailed the romantic outcast:
+
+"Hello, Huckleberry!"
+
+"Hello yourself, and see how you like it."
+
+"What's that you got?"
+
+"Dead cat."
+
+"Lemme see him, Huck. My, he's pretty stiff. Where'd you get him?"
+
+"Bought him off'n a boy."
+
+"What did you give?"
+
+"I give a blue ticket and a bladder that I got at the slaughter-house."
+
+"Where'd you get the blue ticket?"
+
+"Bought it off'n Ben Rogers two weeks ago for a hoop-stick."
+
+"Say--what is dead cats good for, Huck?"
+
+"Good for? Cure warts with."
+
+"No! Is that so? I know something that's better."
+
+"I bet you don't. What is it?"
+
+"Why, spunk-water."
+
+"Spunk-water! I wouldn't give a dern for spunk-water."
+
+"You wouldn't, wouldn't you? D'you ever try it?"
+
+"No, I hain't. But Bob Tanner did."
+
+"Who told you so!"
+
+"Why, he told Jeff Thatcher, and Jeff told Johnny Baker, and Johnny
+told Jim Hollis, and Jim told Ben Rogers, and Ben told a nigger, and
+the nigger told me. There now!"
+
+"Well, what of it? They'll all lie. Leastways all but the nigger. I
+don't know HIM. But I never see a nigger that WOULDN'T lie. Shucks! Now
+you tell me how Bob Tanner done it, Huck."
+
+"Why, he took and dipped his hand in a rotten stump where the
+rain-water was."
+
+"In the daytime?"
+
+"Certainly."
+
+"With his face to the stump?"
+
+"Yes. Least I reckon so."
+
+"Did he say anything?"
+
+"I don't reckon he did. I don't know."
+
+"Aha! Talk about trying to cure warts with spunk-water such a blame
+fool way as that! Why, that ain't a-going to do any good. You got to go
+all by yourself, to the middle of the woods, where you know there's a
+spunk-water stump, and just as it's midnight you back up against the
+stump and jam your hand in and say:
+
+  'Barley-corn, barley-corn, injun-meal shorts,
+   Spunk-water, spunk-water, swaller these warts,'
+
+and then walk away quick, eleven steps, with your eyes shut, and then
+turn around three times and walk home without speaking to anybody.
+Because if you speak the charm's busted."
+
+"Well, that sounds like a good way; but that ain't the way Bob Tanner
+done."
+
+"No, sir, you can bet he didn't, becuz he's the wartiest boy in this
+town; and he wouldn't have a wart on him if he'd knowed how to work
+spunk-water. I've took off thousands of warts off of my hands that way,
+Huck. I play with frogs so much that I've always got considerable many
+warts. Sometimes I take 'em off with a bean."
+
+"Yes, bean's good. I've done that."
+
+"Have you? What's your way?"
+
+"You take and split the bean, and cut the wart so as to get some
+blood, and then you put the blood on one piece of the bean and take and
+dig a hole and bury it 'bout midnight at the crossroads in the dark of
+the moon, and then you burn up the rest of the bean. You see that piece
+that's got the blood on it will keep drawing and drawing, trying to
+fetch the other piece to it, and so that helps the blood to draw the
+wart, and pretty soon off she comes."
+
+"Yes, that's it, Huck--that's it; though when you're burying it if you
+say 'Down bean; off wart; come no more to bother me!' it's better.
+That's the way Joe Harper does, and he's been nearly to Coonville and
+most everywheres. But say--how do you cure 'em with dead cats?"
+
+"Why, you take your cat and go and get in the graveyard 'long about
+midnight when somebody that was wicked has been buried; and when it's
+midnight a devil will come, or maybe two or three, but you can't see
+'em, you can only hear something like the wind, or maybe hear 'em talk;
+and when they're taking that feller away, you heave your cat after 'em
+and say, 'Devil follow corpse, cat follow devil, warts follow cat, I'm
+done with ye!' That'll fetch ANY wart."
+
+"Sounds right. D'you ever try it, Huck?"
+
+"No, but old Mother Hopkins told me."
+
+"Well, I reckon it's so, then. Becuz they say she's a witch."
+
+"Say! Why, Tom, I KNOW she is. She witched pap. Pap says so his own
+self. He come along one day, and he see she was a-witching him, so he
+took up a rock, and if she hadn't dodged, he'd a got her. Well, that
+very night he rolled off'n a shed wher' he was a layin drunk, and broke
+his arm."
+
+"Why, that's awful. How did he know she was a-witching him?"
+
+"Lord, pap can tell, easy. Pap says when they keep looking at you
+right stiddy, they're a-witching you. Specially if they mumble. Becuz
+when they mumble they're saying the Lord's Prayer backards."
+
+"Say, Hucky, when you going to try the cat?"
+
+"To-night. I reckon they'll come after old Hoss Williams to-night."
+
+"But they buried him Saturday. Didn't they get him Saturday night?"
+
+"Why, how you talk! How could their charms work till midnight?--and
+THEN it's Sunday. Devils don't slosh around much of a Sunday, I don't
+reckon."
+
+"I never thought of that. That's so. Lemme go with you?"
+
+"Of course--if you ain't afeard."
+
+"Afeard! 'Tain't likely. Will you meow?"
+
+"Yes--and you meow back, if you get a chance. Last time, you kep' me
+a-meowing around till old Hays went to throwing rocks at me and says
+'Dern that cat!' and so I hove a brick through his window--but don't
+you tell."
+
+"I won't. I couldn't meow that night, becuz auntie was watching me,
+but I'll meow this time. Say--what's that?"
+
+"Nothing but a tick."
+
+"Where'd you get him?"
+
+"Out in the woods."
+
+"What'll you take for him?"
+
+"I don't know. I don't want to sell him."
+
+"All right. It's a mighty small tick, anyway."
+
+"Oh, anybody can run a tick down that don't belong to them. I'm
+satisfied with it. It's a good enough tick for me."
+
+"Sho, there's ticks a plenty. I could have a thousand of 'em if I
+wanted to."
+
+"Well, why don't you? Becuz you know mighty well you can't. This is a
+pretty early tick, I reckon. It's the first one I've seen this year."
+
+"Say, Huck--I'll give you my tooth for him."
+
+"Less see it."
+
+Tom got out a bit of paper and carefully unrolled it. Huckleberry
+viewed it wistfully. The temptation was very strong. At last he said:
+
+"Is it genuwyne?"
+
+Tom lifted his lip and showed the vacancy.
+
+"Well, all right," said Huckleberry, "it's a trade."
+
+Tom enclosed the tick in the percussion-cap box that had lately been
+the pinchbug's prison, and the boys separated, each feeling wealthier
+than before.
+
+When Tom reached the little isolated frame schoolhouse, he strode in
+briskly, with the manner of one who had come with all honest speed.
+He hung his hat on a peg and flung himself into his seat with
+business-like alacrity. The master, throned on high in his great
+splint-bottom arm-chair, was dozing, lulled by the drowsy hum of study.
+The interruption roused him.
+
+"Thomas Sawyer!"
+
+Tom knew that when his name was pronounced in full, it meant trouble.
+
+"Sir!"
+
+"Come up here. Now, sir, why are you late again, as usual?"
+
+Tom was about to take refuge in a lie, when he saw two long tails of
+yellow hair hanging down a back that he recognized by the electric
+sympathy of love; and by that form was THE ONLY VACANT PLACE on the
+girls' side of the schoolhouse. He instantly said:
+
+"I STOPPED TO TALK WITH HUCKLEBERRY FINN!"
+
+The master's pulse stood still, and he stared helplessly. The buzz of
+study ceased. The pupils wondered if this foolhardy boy had lost his
+mind. The master said:
+
+"You--you did what?"
+
+"Stopped to talk with Huckleberry Finn."
+
+There was no mistaking the words.
+
+"Thomas Sawyer, this is the most astounding confession I have ever
+listened to. No mere ferule will answer for this offence. Take off your
+jacket."
+
+The master's arm performed until it was tired and the stock of
+switches notably diminished. Then the order followed:
+
+"Now, sir, go and sit with the girls! And let this be a warning to you."
+
+The titter that rippled around the room appeared to abash the boy, but
+in reality that result was caused rather more by his worshipful awe of
+his unknown idol and the dread pleasure that lay in his high good
+fortune. He sat down upon the end of the pine bench and the girl
+hitched herself away from him with a toss of her head. Nudges and winks
+and whispers traversed the room, but Tom sat still, with his arms upon
+the long, low desk before him, and seemed to study his book.
+
+By and by attention ceased from him, and the accustomed school murmur
+rose upon the dull air once more. Presently the boy began to steal
+furtive glances at the girl. She observed it, "made a mouth" at him and
+gave him the back of her head for the space of a minute. When she
+cautiously faced around again, a peach lay before her. She thrust it
+away. Tom gently put it back. She thrust it away again, but with less
+animosity. Tom patiently returned it to its place. Then she let it
+remain. Tom scrawled on his slate, "Please take it--I got more." The
+girl glanced at the words, but made no sign. Now the boy began to draw
+something on the slate, hiding his work with his left hand. For a time
+the girl refused to notice; but her human curiosity presently began to
+manifest itself by hardly perceptible signs. The boy worked on,
+apparently unconscious. The girl made a sort of noncommittal attempt to
+see, but the boy did not betray that he was aware of it. At last she
+gave in and hesitatingly whispered:
+
+"Let me see it."
+
+Tom partly uncovered a dismal caricature of a house with two gable
+ends to it and a corkscrew of smoke issuing from the chimney. Then the
+girl's interest began to fasten itself upon the work and she forgot
+everything else. When it was finished, she gazed a moment, then
+whispered:
+
+"It's nice--make a man."
+
+The artist erected a man in the front yard, that resembled a derrick.
+He could have stepped over the house; but the girl was not
+hypercritical; she was satisfied with the monster, and whispered:
+
+"It's a beautiful man--now make me coming along."
+
+Tom drew an hour-glass with a full moon and straw limbs to it and
+armed the spreading fingers with a portentous fan. The girl said:
+
+"It's ever so nice--I wish I could draw."
+
+"It's easy," whispered Tom, "I'll learn you."
+
+"Oh, will you? When?"
+
+"At noon. Do you go home to dinner?"
+
+"I'll stay if you will."
+
+"Good--that's a whack. What's your name?"
+
+"Becky Thatcher. What's yours? Oh, I know. It's Thomas Sawyer."
+
+"That's the name they lick me by. I'm Tom when I'm good. You call me
+Tom, will you?"
+
+"Yes."
+
+Now Tom began to scrawl something on the slate, hiding the words from
+the girl. But she was not backward this time. She begged to see. Tom
+said:
+
+"Oh, it ain't anything."
+
+"Yes it is."
+
+"No it ain't. You don't want to see."
+
+"Yes I do, indeed I do. Please let me."
+
+"You'll tell."
+
+"No I won't--deed and deed and double deed won't."
+
+"You won't tell anybody at all? Ever, as long as you live?"
+
+"No, I won't ever tell ANYbody. Now let me."
+
+"Oh, YOU don't want to see!"
+
+"Now that you treat me so, I WILL see." And she put her small hand
+upon his and a little scuffle ensued, Tom pretending to resist in
+earnest but letting his hand slip by degrees till these words were
+revealed: "I LOVE YOU."
+
+"Oh, you bad thing!" And she hit his hand a smart rap, but reddened
+and looked pleased, nevertheless.
+
+Just at this juncture the boy felt a slow, fateful grip closing on his
+ear, and a steady lifting impulse. In that wise he was borne across the
+house and deposited in his own seat, under a peppering fire of giggles
+from the whole school. Then the master stood over him during a few
+awful moments, and finally moved away to his throne without saying a
+word. But although Tom's ear tingled, his heart was jubilant.
+
+As the school quieted down Tom made an honest effort to study, but the
+turmoil within him was too great. In turn he took his place in the
+reading class and made a botch of it; then in the geography class and
+turned lakes into mountains, mountains into rivers, and rivers into
+continents, till chaos was come again; then in the spelling class, and
+got "turned down," by a succession of mere baby words, till he brought
+up at the foot and yielded up the pewter medal which he had worn with
+ostentation for months.
+
+
+
+CHAPTER VII
+
+THE harder Tom tried to fasten his mind on his book, the more his
+ideas wandered. So at last, with a sigh and a yawn, he gave it up. It
+seemed to him that the noon recess would never come. The air was
+utterly dead. There was not a breath stirring. It was the sleepiest of
+sleepy days. The drowsing murmur of the five and twenty studying
+scholars soothed the soul like the spell that is in the murmur of bees.
+Away off in the flaming sunshine, Cardiff Hill lifted its soft green
+sides through a shimmering veil of heat, tinted with the purple of
+distance; a few birds floated on lazy wing high in the air; no other
+living thing was visible but some cows, and they were asleep. Tom's
+heart ached to be free, or else to have something of interest to do to
+pass the dreary time. His hand wandered into his pocket and his face
+lit up with a glow of gratitude that was prayer, though he did not know
+it. Then furtively the percussion-cap box came out. He released the
+tick and put him on the long flat desk. The creature probably glowed
+with a gratitude that amounted to prayer, too, at this moment, but it
+was premature: for when he started thankfully to travel off, Tom turned
+him aside with a pin and made him take a new direction.
+
+Tom's bosom friend sat next him, suffering just as Tom had been, and
+now he was deeply and gratefully interested in this entertainment in an
+instant. This bosom friend was Joe Harper. The two boys were sworn
+friends all the week, and embattled enemies on Saturdays. Joe took a
+pin out of his lapel and began to assist in exercising the prisoner.
+The sport grew in interest momently. Soon Tom said that they were
+interfering with each other, and neither getting the fullest benefit of
+the tick. So he put Joe's slate on the desk and drew a line down the
+middle of it from top to bottom.
+
+"Now," said he, "as long as he is on your side you can stir him up and
+I'll let him alone; but if you let him get away and get on my side,
+you're to leave him alone as long as I can keep him from crossing over."
+
+"All right, go ahead; start him up."
+
+The tick escaped from Tom, presently, and crossed the equator. Joe
+harassed him awhile, and then he got away and crossed back again. This
+change of base occurred often. While one boy was worrying the tick with
+absorbing interest, the other would look on with interest as strong,
+the two heads bowed together over the slate, and the two souls dead to
+all things else. At last luck seemed to settle and abide with Joe. The
+tick tried this, that, and the other course, and got as excited and as
+anxious as the boys themselves, but time and again just as he would
+have victory in his very grasp, so to speak, and Tom's fingers would be
+twitching to begin, Joe's pin would deftly head him off, and keep
+possession. At last Tom could stand it no longer. The temptation was
+too strong. So he reached out and lent a hand with his pin. Joe was
+angry in a moment. Said he:
+
+"Tom, you let him alone."
+
+"I only just want to stir him up a little, Joe."
+
+"No, sir, it ain't fair; you just let him alone."
+
+"Blame it, I ain't going to stir him much."
+
+"Let him alone, I tell you."
+
+"I won't!"
+
+"You shall--he's on my side of the line."
+
+"Look here, Joe Harper, whose is that tick?"
+
+"I don't care whose tick he is--he's on my side of the line, and you
+sha'n't touch him."
+
+"Well, I'll just bet I will, though. He's my tick and I'll do what I
+blame please with him, or die!"
+
+A tremendous whack came down on Tom's shoulders, and its duplicate on
+Joe's; and for the space of two minutes the dust continued to fly from
+the two jackets and the whole school to enjoy it. The boys had been too
+absorbed to notice the hush that had stolen upon the school awhile
+before when the master came tiptoeing down the room and stood over
+them. He had contemplated a good part of the performance before he
+contributed his bit of variety to it.
+
+When school broke up at noon, Tom flew to Becky Thatcher, and
+whispered in her ear:
+
+"Put on your bonnet and let on you're going home; and when you get to
+the corner, give the rest of 'em the slip, and turn down through the
+lane and come back. I'll go the other way and come it over 'em the same
+way."
+
+So the one went off with one group of scholars, and the other with
+another. In a little while the two met at the bottom of the lane, and
+when they reached the school they had it all to themselves. Then they
+sat together, with a slate before them, and Tom gave Becky the pencil
+and held her hand in his, guiding it, and so created another surprising
+house. When the interest in art began to wane, the two fell to talking.
+Tom was swimming in bliss. He said:
+
+"Do you love rats?"
+
+"No! I hate them!"
+
+"Well, I do, too--LIVE ones. But I mean dead ones, to swing round your
+head with a string."
+
+"No, I don't care for rats much, anyway. What I like is chewing-gum."
+
+"Oh, I should say so! I wish I had some now."
+
+"Do you? I've got some. I'll let you chew it awhile, but you must give
+it back to me."
+
+That was agreeable, so they chewed it turn about, and dangled their
+legs against the bench in excess of contentment.
+
+"Was you ever at a circus?" said Tom.
+
+"Yes, and my pa's going to take me again some time, if I'm good."
+
+"I been to the circus three or four times--lots of times. Church ain't
+shucks to a circus. There's things going on at a circus all the time.
+I'm going to be a clown in a circus when I grow up."
+
+"Oh, are you! That will be nice. They're so lovely, all spotted up."
+
+"Yes, that's so. And they get slathers of money--most a dollar a day,
+Ben Rogers says. Say, Becky, was you ever engaged?"
+
+"What's that?"
+
+"Why, engaged to be married."
+
+"No."
+
+"Would you like to?"
+
+"I reckon so. I don't know. What is it like?"
+
+"Like? Why it ain't like anything. You only just tell a boy you won't
+ever have anybody but him, ever ever ever, and then you kiss and that's
+all. Anybody can do it."
+
+"Kiss? What do you kiss for?"
+
+"Why, that, you know, is to--well, they always do that."
+
+"Everybody?"
+
+"Why, yes, everybody that's in love with each other. Do you remember
+what I wrote on the slate?"
+
+"Ye--yes."
+
+"What was it?"
+
+"I sha'n't tell you."
+
+"Shall I tell YOU?"
+
+"Ye--yes--but some other time."
+
+"No, now."
+
+"No, not now--to-morrow."
+
+"Oh, no, NOW. Please, Becky--I'll whisper it, I'll whisper it ever so
+easy."
+
+Becky hesitating, Tom took silence for consent, and passed his arm
+about her waist and whispered the tale ever so softly, with his mouth
+close to her ear. And then he added:
+
+"Now you whisper it to me--just the same."
+
+She resisted, for a while, and then said:
+
+"You turn your face away so you can't see, and then I will. But you
+mustn't ever tell anybody--WILL you, Tom? Now you won't, WILL you?"
+
+"No, indeed, indeed I won't. Now, Becky."
+
+He turned his face away. She bent timidly around till her breath
+stirred his curls and whispered, "I--love--you!"
+
+Then she sprang away and ran around and around the desks and benches,
+with Tom after her, and took refuge in a corner at last, with her
+little white apron to her face. Tom clasped her about her neck and
+pleaded:
+
+"Now, Becky, it's all done--all over but the kiss. Don't you be afraid
+of that--it ain't anything at all. Please, Becky." And he tugged at her
+apron and the hands.
+
+By and by she gave up, and let her hands drop; her face, all glowing
+with the struggle, came up and submitted. Tom kissed the red lips and
+said:
+
+"Now it's all done, Becky. And always after this, you know, you ain't
+ever to love anybody but me, and you ain't ever to marry anybody but
+me, ever never and forever. Will you?"
+
+"No, I'll never love anybody but you, Tom, and I'll never marry
+anybody but you--and you ain't to ever marry anybody but me, either."
+
+"Certainly. Of course. That's PART of it. And always coming to school
+or when we're going home, you're to walk with me, when there ain't
+anybody looking--and you choose me and I choose you at parties, because
+that's the way you do when you're engaged."
+
+"It's so nice. I never heard of it before."
+
+"Oh, it's ever so gay! Why, me and Amy Lawrence--"
+
+The big eyes told Tom his blunder and he stopped, confused.
+
+"Oh, Tom! Then I ain't the first you've ever been engaged to!"
+
+The child began to cry. Tom said:
+
+"Oh, don't cry, Becky, I don't care for her any more."
+
+"Yes, you do, Tom--you know you do."
+
+Tom tried to put his arm about her neck, but she pushed him away and
+turned her face to the wall, and went on crying. Tom tried again, with
+soothing words in his mouth, and was repulsed again. Then his pride was
+up, and he strode away and went outside. He stood about, restless and
+uneasy, for a while, glancing at the door, every now and then, hoping
+she would repent and come to find him. But she did not. Then he began
+to feel badly and fear that he was in the wrong. It was a hard struggle
+with him to make new advances, now, but he nerved himself to it and
+entered. She was still standing back there in the corner, sobbing, with
+her face to the wall. Tom's heart smote him. He went to her and stood a
+moment, not knowing exactly how to proceed. Then he said hesitatingly:
+
+"Becky, I--I don't care for anybody but you."
+
+No reply--but sobs.
+
+"Becky"--pleadingly. "Becky, won't you say something?"
+
+More sobs.
+
+Tom got out his chiefest jewel, a brass knob from the top of an
+andiron, and passed it around her so that she could see it, and said:
+
+"Please, Becky, won't you take it?"
+
+She struck it to the floor. Then Tom marched out of the house and over
+the hills and far away, to return to school no more that day. Presently
+Becky began to suspect. She ran to the door; he was not in sight; she
+flew around to the play-yard; he was not there. Then she called:
+
+"Tom! Come back, Tom!"
+
+She listened intently, but there was no answer. She had no companions
+but silence and loneliness. So she sat down to cry again and upbraid
+herself; and by this time the scholars began to gather again, and she
+had to hide her griefs and still her broken heart and take up the cross
+of a long, dreary, aching afternoon, with none among the strangers
+about her to exchange sorrows with.
+
+
+
+CHAPTER VIII
+
+TOM dodged hither and thither through lanes until he was well out of
+the track of returning scholars, and then fell into a moody jog. He
+crossed a small "branch" two or three times, because of a prevailing
+juvenile superstition that to cross water baffled pursuit. Half an hour
+later he was disappearing behind the Douglas mansion on the summit of
+Cardiff Hill, and the schoolhouse was hardly distinguishable away off
+in the valley behind him. He entered a dense wood, picked his pathless
+way to the centre of it, and sat down on a mossy spot under a spreading
+oak. There was not even a zephyr stirring; the dead noonday heat had
+even stilled the songs of the birds; nature lay in a trance that was
+broken by no sound but the occasional far-off hammering of a
+woodpecker, and this seemed to render the pervading silence and sense
+of loneliness the more profound. The boy's soul was steeped in
+melancholy; his feelings were in happy accord with his surroundings. He
+sat long with his elbows on his knees and his chin in his hands,
+meditating. It seemed to him that life was but a trouble, at best, and
+he more than half envied Jimmy Hodges, so lately released; it must be
+very peaceful, he thought, to lie and slumber and dream forever and
+ever, with the wind whispering through the trees and caressing the
+grass and the flowers over the grave, and nothing to bother and grieve
+about, ever any more. If he only had a clean Sunday-school record he
+could be willing to go, and be done with it all. Now as to this girl.
+What had he done? Nothing. He had meant the best in the world, and been
+treated like a dog--like a very dog. She would be sorry some day--maybe
+when it was too late. Ah, if he could only die TEMPORARILY!
+
+But the elastic heart of youth cannot be compressed into one
+constrained shape long at a time. Tom presently began to drift
+insensibly back into the concerns of this life again. What if he turned
+his back, now, and disappeared mysteriously? What if he went away--ever
+so far away, into unknown countries beyond the seas--and never came
+back any more! How would she feel then! The idea of being a clown
+recurred to him now, only to fill him with disgust. For frivolity and
+jokes and spotted tights were an offense, when they intruded themselves
+upon a spirit that was exalted into the vague august realm of the
+romantic. No, he would be a soldier, and return after long years, all
+war-worn and illustrious. No--better still, he would join the Indians,
+and hunt buffaloes and go on the warpath in the mountain ranges and the
+trackless great plains of the Far West, and away in the future come
+back a great chief, bristling with feathers, hideous with paint, and
+prance into Sunday-school, some drowsy summer morning, with a
+bloodcurdling war-whoop, and sear the eyeballs of all his companions
+with unappeasable envy. But no, there was something gaudier even than
+this. He would be a pirate! That was it! NOW his future lay plain
+before him, and glowing with unimaginable splendor. How his name would
+fill the world, and make people shudder! How gloriously he would go
+plowing the dancing seas, in his long, low, black-hulled racer, the
+Spirit of the Storm, with his grisly flag flying at the fore! And at
+the zenith of his fame, how he would suddenly appear at the old village
+and stalk into church, brown and weather-beaten, in his black velvet
+doublet and trunks, his great jack-boots, his crimson sash, his belt
+bristling with horse-pistols, his crime-rusted cutlass at his side, his
+slouch hat with waving plumes, his black flag unfurled, with the skull
+and crossbones on it, and hear with swelling ecstasy the whisperings,
+"It's Tom Sawyer the Pirate!--the Black Avenger of the Spanish Main!"
+
+Yes, it was settled; his career was determined. He would run away from
+home and enter upon it. He would start the very next morning. Therefore
+he must now begin to get ready. He would collect his resources
+together. He went to a rotten log near at hand and began to dig under
+one end of it with his Barlow knife. He soon struck wood that sounded
+hollow. He put his hand there and uttered this incantation impressively:
+
+"What hasn't come here, come! What's here, stay here!"
+
+Then he scraped away the dirt, and exposed a pine shingle. He took it
+up and disclosed a shapely little treasure-house whose bottom and sides
+were of shingles. In it lay a marble. Tom's astonishment was boundless!
+He scratched his head with a perplexed air, and said:
+
+"Well, that beats anything!"
+
+Then he tossed the marble away pettishly, and stood cogitating. The
+truth was, that a superstition of his had failed, here, which he and
+all his comrades had always looked upon as infallible. If you buried a
+marble with certain necessary incantations, and left it alone a
+fortnight, and then opened the place with the incantation he had just
+used, you would find that all the marbles you had ever lost had
+gathered themselves together there, meantime, no matter how widely they
+had been separated. But now, this thing had actually and unquestionably
+failed. Tom's whole structure of faith was shaken to its foundations.
+He had many a time heard of this thing succeeding but never of its
+failing before. It did not occur to him that he had tried it several
+times before, himself, but could never find the hiding-places
+afterward. He puzzled over the matter some time, and finally decided
+that some witch had interfered and broken the charm. He thought he
+would satisfy himself on that point; so he searched around till he
+found a small sandy spot with a little funnel-shaped depression in it.
+He laid himself down and put his mouth close to this depression and
+called--
+
+"Doodle-bug, doodle-bug, tell me what I want to know! Doodle-bug,
+doodle-bug, tell me what I want to know!"
+
+The sand began to work, and presently a small black bug appeared for a
+second and then darted under again in a fright.
+
+"He dasn't tell! So it WAS a witch that done it. I just knowed it."
+
+He well knew the futility of trying to contend against witches, so he
+gave up discouraged. But it occurred to him that he might as well have
+the marble he had just thrown away, and therefore he went and made a
+patient search for it. But he could not find it. Now he went back to
+his treasure-house and carefully placed himself just as he had been
+standing when he tossed the marble away; then he took another marble
+from his pocket and tossed it in the same way, saying:
+
+"Brother, go find your brother!"
+
+He watched where it stopped, and went there and looked. But it must
+have fallen short or gone too far; so he tried twice more. The last
+repetition was successful. The two marbles lay within a foot of each
+other.
+
+Just here the blast of a toy tin trumpet came faintly down the green
+aisles of the forest. Tom flung off his jacket and trousers, turned a
+suspender into a belt, raked away some brush behind the rotten log,
+disclosing a rude bow and arrow, a lath sword and a tin trumpet, and in
+a moment had seized these things and bounded away, barelegged, with
+fluttering shirt. He presently halted under a great elm, blew an
+answering blast, and then began to tiptoe and look warily out, this way
+and that. He said cautiously--to an imaginary company:
+
+"Hold, my merry men! Keep hid till I blow."
+
+Now appeared Joe Harper, as airily clad and elaborately armed as Tom.
+Tom called:
+
+"Hold! Who comes here into Sherwood Forest without my pass?"
+
+"Guy of Guisborne wants no man's pass. Who art thou that--that--"
+
+"Dares to hold such language," said Tom, prompting--for they talked
+"by the book," from memory.
+
+"Who art thou that dares to hold such language?"
+
+"I, indeed! I am Robin Hood, as thy caitiff carcase soon shall know."
+
+"Then art thou indeed that famous outlaw? Right gladly will I dispute
+with thee the passes of the merry wood. Have at thee!"
+
+They took their lath swords, dumped their other traps on the ground,
+struck a fencing attitude, foot to foot, and began a grave, careful
+combat, "two up and two down." Presently Tom said:
+
+"Now, if you've got the hang, go it lively!"
+
+So they "went it lively," panting and perspiring with the work. By and
+by Tom shouted:
+
+"Fall! fall! Why don't you fall?"
+
+"I sha'n't! Why don't you fall yourself? You're getting the worst of
+it."
+
+"Why, that ain't anything. I can't fall; that ain't the way it is in
+the book. The book says, 'Then with one back-handed stroke he slew poor
+Guy of Guisborne.' You're to turn around and let me hit you in the
+back."
+
+There was no getting around the authorities, so Joe turned, received
+the whack and fell.
+
+"Now," said Joe, getting up, "you got to let me kill YOU. That's fair."
+
+"Why, I can't do that, it ain't in the book."
+
+"Well, it's blamed mean--that's all."
+
+"Well, say, Joe, you can be Friar Tuck or Much the miller's son, and
+lam me with a quarter-staff; or I'll be the Sheriff of Nottingham and
+you be Robin Hood a little while and kill me."
+
+This was satisfactory, and so these adventures were carried out. Then
+Tom became Robin Hood again, and was allowed by the treacherous nun to
+bleed his strength away through his neglected wound. And at last Joe,
+representing a whole tribe of weeping outlaws, dragged him sadly forth,
+gave his bow into his feeble hands, and Tom said, "Where this arrow
+falls, there bury poor Robin Hood under the greenwood tree." Then he
+shot the arrow and fell back and would have died, but he lit on a
+nettle and sprang up too gaily for a corpse.
+
+The boys dressed themselves, hid their accoutrements, and went off
+grieving that there were no outlaws any more, and wondering what modern
+civilization could claim to have done to compensate for their loss.
+They said they would rather be outlaws a year in Sherwood Forest than
+President of the United States forever.
+
+
+
+CHAPTER IX
+
+AT half-past nine, that night, Tom and Sid were sent to bed, as usual.
+They said their prayers, and Sid was soon asleep. Tom lay awake and
+waited, in restless impatience. When it seemed to him that it must be
+nearly daylight, he heard the clock strike ten! This was despair. He
+would have tossed and fidgeted, as his nerves demanded, but he was
+afraid he might wake Sid. So he lay still, and stared up into the dark.
+Everything was dismally still. By and by, out of the stillness, little,
+scarcely perceptible noises began to emphasize themselves. The ticking
+of the clock began to bring itself into notice. Old beams began to
+crack mysteriously. The stairs creaked faintly. Evidently spirits were
+abroad. A measured, muffled snore issued from Aunt Polly's chamber. And
+now the tiresome chirping of a cricket that no human ingenuity could
+locate, began. Next the ghastly ticking of a deathwatch in the wall at
+the bed's head made Tom shudder--it meant that somebody's days were
+numbered. Then the howl of a far-off dog rose on the night air, and was
+answered by a fainter howl from a remoter distance. Tom was in an
+agony. At last he was satisfied that time had ceased and eternity
+begun; he began to doze, in spite of himself; the clock chimed eleven,
+but he did not hear it. And then there came, mingling with his
+half-formed dreams, a most melancholy caterwauling. The raising of a
+neighboring window disturbed him. A cry of "Scat! you devil!" and the
+crash of an empty bottle against the back of his aunt's woodshed
+brought him wide awake, and a single minute later he was dressed and
+out of the window and creeping along the roof of the "ell" on all
+fours. He "meow'd" with caution once or twice, as he went; then jumped
+to the roof of the woodshed and thence to the ground. Huckleberry Finn
+was there, with his dead cat. The boys moved off and disappeared in the
+gloom. At the end of half an hour they were wading through the tall
+grass of the graveyard.
+
+It was a graveyard of the old-fashioned Western kind. It was on a
+hill, about a mile and a half from the village. It had a crazy board
+fence around it, which leaned inward in places, and outward the rest of
+the time, but stood upright nowhere. Grass and weeds grew rank over the
+whole cemetery. All the old graves were sunken in, there was not a
+tombstone on the place; round-topped, worm-eaten boards staggered over
+the graves, leaning for support and finding none. "Sacred to the memory
+of" So-and-So had been painted on them once, but it could no longer
+have been read, on the most of them, now, even if there had been light.
+
+A faint wind moaned through the trees, and Tom feared it might be the
+spirits of the dead, complaining at being disturbed. The boys talked
+little, and only under their breath, for the time and the place and the
+pervading solemnity and silence oppressed their spirits. They found the
+sharp new heap they were seeking, and ensconced themselves within the
+protection of three great elms that grew in a bunch within a few feet
+of the grave.
+
+Then they waited in silence for what seemed a long time. The hooting
+of a distant owl was all the sound that troubled the dead stillness.
+Tom's reflections grew oppressive. He must force some talk. So he said
+in a whisper:
+
+"Hucky, do you believe the dead people like it for us to be here?"
+
+Huckleberry whispered:
+
+"I wisht I knowed. It's awful solemn like, AIN'T it?"
+
+"I bet it is."
+
+There was a considerable pause, while the boys canvassed this matter
+inwardly. Then Tom whispered:
+
+"Say, Hucky--do you reckon Hoss Williams hears us talking?"
+
+"O' course he does. Least his sperrit does."
+
+Tom, after a pause:
+
+"I wish I'd said Mister Williams. But I never meant any harm.
+Everybody calls him Hoss."
+
+"A body can't be too partic'lar how they talk 'bout these-yer dead
+people, Tom."
+
+This was a damper, and conversation died again.
+
+Presently Tom seized his comrade's arm and said:
+
+"Sh!"
+
+"What is it, Tom?" And the two clung together with beating hearts.
+
+"Sh! There 'tis again! Didn't you hear it?"
+
+"I--"
+
+"There! Now you hear it."
+
+"Lord, Tom, they're coming! They're coming, sure. What'll we do?"
+
+"I dono. Think they'll see us?"
+
+"Oh, Tom, they can see in the dark, same as cats. I wisht I hadn't
+come."
+
+"Oh, don't be afeard. I don't believe they'll bother us. We ain't
+doing any harm. If we keep perfectly still, maybe they won't notice us
+at all."
+
+"I'll try to, Tom, but, Lord, I'm all of a shiver."
+
+"Listen!"
+
+The boys bent their heads together and scarcely breathed. A muffled
+sound of voices floated up from the far end of the graveyard.
+
+"Look! See there!" whispered Tom. "What is it?"
+
+"It's devil-fire. Oh, Tom, this is awful."
+
+Some vague figures approached through the gloom, swinging an
+old-fashioned tin lantern that freckled the ground with innumerable
+little spangles of light. Presently Huckleberry whispered with a
+shudder:
+
+"It's the devils sure enough. Three of 'em! Lordy, Tom, we're goners!
+Can you pray?"
+
+"I'll try, but don't you be afeard. They ain't going to hurt us. 'Now
+I lay me down to sleep, I--'"
+
+"Sh!"
+
+"What is it, Huck?"
+
+"They're HUMANS! One of 'em is, anyway. One of 'em's old Muff Potter's
+voice."
+
+"No--'tain't so, is it?"
+
+"I bet I know it. Don't you stir nor budge. He ain't sharp enough to
+notice us. Drunk, the same as usual, likely--blamed old rip!"
+
+"All right, I'll keep still. Now they're stuck. Can't find it. Here
+they come again. Now they're hot. Cold again. Hot again. Red hot!
+They're p'inted right, this time. Say, Huck, I know another o' them
+voices; it's Injun Joe."
+
+"That's so--that murderin' half-breed! I'd druther they was devils a
+dern sight. What kin they be up to?"
+
+The whisper died wholly out, now, for the three men had reached the
+grave and stood within a few feet of the boys' hiding-place.
+
+"Here it is," said the third voice; and the owner of it held the
+lantern up and revealed the face of young Doctor Robinson.
+
+Potter and Injun Joe were carrying a handbarrow with a rope and a
+couple of shovels on it. They cast down their load and began to open
+the grave. The doctor put the lantern at the head of the grave and came
+and sat down with his back against one of the elm trees. He was so
+close the boys could have touched him.
+
+"Hurry, men!" he said, in a low voice; "the moon might come out at any
+moment."
+
+They growled a response and went on digging. For some time there was
+no noise but the grating sound of the spades discharging their freight
+of mould and gravel. It was very monotonous. Finally a spade struck
+upon the coffin with a dull woody accent, and within another minute or
+two the men had hoisted it out on the ground. They pried off the lid
+with their shovels, got out the body and dumped it rudely on the
+ground. The moon drifted from behind the clouds and exposed the pallid
+face. The barrow was got ready and the corpse placed on it, covered
+with a blanket, and bound to its place with the rope. Potter took out a
+large spring-knife and cut off the dangling end of the rope and then
+said:
+
+"Now the cussed thing's ready, Sawbones, and you'll just out with
+another five, or here she stays."
+
+"That's the talk!" said Injun Joe.
+
+"Look here, what does this mean?" said the doctor. "You required your
+pay in advance, and I've paid you."
+
+"Yes, and you done more than that," said Injun Joe, approaching the
+doctor, who was now standing. "Five years ago you drove me away from
+your father's kitchen one night, when I come to ask for something to
+eat, and you said I warn't there for any good; and when I swore I'd get
+even with you if it took a hundred years, your father had me jailed for
+a vagrant. Did you think I'd forget? The Injun blood ain't in me for
+nothing. And now I've GOT you, and you got to SETTLE, you know!"
+
+He was threatening the doctor, with his fist in his face, by this
+time. The doctor struck out suddenly and stretched the ruffian on the
+ground. Potter dropped his knife, and exclaimed:
+
+"Here, now, don't you hit my pard!" and the next moment he had
+grappled with the doctor and the two were struggling with might and
+main, trampling the grass and tearing the ground with their heels.
+Injun Joe sprang to his feet, his eyes flaming with passion, snatched
+up Potter's knife, and went creeping, catlike and stooping, round and
+round about the combatants, seeking an opportunity. All at once the
+doctor flung himself free, seized the heavy headboard of Williams'
+grave and felled Potter to the earth with it--and in the same instant
+the half-breed saw his chance and drove the knife to the hilt in the
+young man's breast. He reeled and fell partly upon Potter, flooding him
+with his blood, and in the same moment the clouds blotted out the
+dreadful spectacle and the two frightened boys went speeding away in
+the dark.
+
+Presently, when the moon emerged again, Injun Joe was standing over
+the two forms, contemplating them. The doctor murmured inarticulately,
+gave a long gasp or two and was still. The half-breed muttered:
+
+"THAT score is settled--damn you."
+
+Then he robbed the body. After which he put the fatal knife in
+Potter's open right hand, and sat down on the dismantled coffin. Three
+--four--five minutes passed, and then Potter began to stir and moan. His
+hand closed upon the knife; he raised it, glanced at it, and let it
+fall, with a shudder. Then he sat up, pushing the body from him, and
+gazed at it, and then around him, confusedly. His eyes met Joe's.
+
+"Lord, how is this, Joe?" he said.
+
+"It's a dirty business," said Joe, without moving.
+
+"What did you do it for?"
+
+"I! I never done it!"
+
+"Look here! That kind of talk won't wash."
+
+Potter trembled and grew white.
+
+"I thought I'd got sober. I'd no business to drink to-night. But it's
+in my head yet--worse'n when we started here. I'm all in a muddle;
+can't recollect anything of it, hardly. Tell me, Joe--HONEST, now, old
+feller--did I do it? Joe, I never meant to--'pon my soul and honor, I
+never meant to, Joe. Tell me how it was, Joe. Oh, it's awful--and him
+so young and promising."
+
+"Why, you two was scuffling, and he fetched you one with the headboard
+and you fell flat; and then up you come, all reeling and staggering
+like, and snatched the knife and jammed it into him, just as he fetched
+you another awful clip--and here you've laid, as dead as a wedge til
+now."
+
+"Oh, I didn't know what I was a-doing. I wish I may die this minute if
+I did. It was all on account of the whiskey and the excitement, I
+reckon. I never used a weepon in my life before, Joe. I've fought, but
+never with weepons. They'll all say that. Joe, don't tell! Say you
+won't tell, Joe--that's a good feller. I always liked you, Joe, and
+stood up for you, too. Don't you remember? You WON'T tell, WILL you,
+Joe?" And the poor creature dropped on his knees before the stolid
+murderer, and clasped his appealing hands.
+
+"No, you've always been fair and square with me, Muff Potter, and I
+won't go back on you. There, now, that's as fair as a man can say."
+
+"Oh, Joe, you're an angel. I'll bless you for this the longest day I
+live." And Potter began to cry.
+
+"Come, now, that's enough of that. This ain't any time for blubbering.
+You be off yonder way and I'll go this. Move, now, and don't leave any
+tracks behind you."
+
+Potter started on a trot that quickly increased to a run. The
+half-breed stood looking after him. He muttered:
+
+"If he's as much stunned with the lick and fuddled with the rum as he
+had the look of being, he won't think of the knife till he's gone so
+far he'll be afraid to come back after it to such a place by himself
+--chicken-heart!"
+
+Two or three minutes later the murdered man, the blanketed corpse, the
+lidless coffin, and the open grave were under no inspection but the
+moon's. The stillness was complete again, too.
+
+
+
+CHAPTER X
+
+THE two boys flew on and on, toward the village, speechless with
+horror. They glanced backward over their shoulders from time to time,
+apprehensively, as if they feared they might be followed. Every stump
+that started up in their path seemed a man and an enemy, and made them
+catch their breath; and as they sped by some outlying cottages that lay
+near the village, the barking of the aroused watch-dogs seemed to give
+wings to their feet.
+
+"If we can only get to the old tannery before we break down!"
+whispered Tom, in short catches between breaths. "I can't stand it much
+longer."
+
+Huckleberry's hard pantings were his only reply, and the boys fixed
+their eyes on the goal of their hopes and bent to their work to win it.
+They gained steadily on it, and at last, breast to breast, they burst
+through the open door and fell grateful and exhausted in the sheltering
+shadows beyond. By and by their pulses slowed down, and Tom whispered:
+
+"Huckleberry, what do you reckon'll come of this?"
+
+"If Doctor Robinson dies, I reckon hanging'll come of it."
+
+"Do you though?"
+
+"Why, I KNOW it, Tom."
+
+Tom thought a while, then he said:
+
+"Who'll tell? We?"
+
+"What are you talking about? S'pose something happened and Injun Joe
+DIDN'T hang? Why, he'd kill us some time or other, just as dead sure as
+we're a laying here."
+
+"That's just what I was thinking to myself, Huck."
+
+"If anybody tells, let Muff Potter do it, if he's fool enough. He's
+generally drunk enough."
+
+Tom said nothing--went on thinking. Presently he whispered:
+
+"Huck, Muff Potter don't know it. How can he tell?"
+
+"What's the reason he don't know it?"
+
+"Because he'd just got that whack when Injun Joe done it. D'you reckon
+he could see anything? D'you reckon he knowed anything?"
+
+"By hokey, that's so, Tom!"
+
+"And besides, look-a-here--maybe that whack done for HIM!"
+
+"No, 'taint likely, Tom. He had liquor in him; I could see that; and
+besides, he always has. Well, when pap's full, you might take and belt
+him over the head with a church and you couldn't phase him. He says so,
+his own self. So it's the same with Muff Potter, of course. But if a
+man was dead sober, I reckon maybe that whack might fetch him; I dono."
+
+After another reflective silence, Tom said:
+
+"Hucky, you sure you can keep mum?"
+
+"Tom, we GOT to keep mum. You know that. That Injun devil wouldn't
+make any more of drownding us than a couple of cats, if we was to
+squeak 'bout this and they didn't hang him. Now, look-a-here, Tom, less
+take and swear to one another--that's what we got to do--swear to keep
+mum."
+
+"I'm agreed. It's the best thing. Would you just hold hands and swear
+that we--"
+
+"Oh no, that wouldn't do for this. That's good enough for little
+rubbishy common things--specially with gals, cuz THEY go back on you
+anyway, and blab if they get in a huff--but there orter be writing
+'bout a big thing like this. And blood."
+
+Tom's whole being applauded this idea. It was deep, and dark, and
+awful; the hour, the circumstances, the surroundings, were in keeping
+with it. He picked up a clean pine shingle that lay in the moonlight,
+took a little fragment of "red keel" out of his pocket, got the moon on
+his work, and painfully scrawled these lines, emphasizing each slow
+down-stroke by clamping his tongue between his teeth, and letting up
+the pressure on the up-strokes. [See next page.]
+
+   "Huck Finn and
+    Tom Sawyer swears
+    they will keep mum
+    about This and They
+    wish They may Drop
+    down dead in Their
+    Tracks if They ever
+    Tell and Rot."
+
+Huckleberry was filled with admiration of Tom's facility in writing,
+and the sublimity of his language. He at once took a pin from his lapel
+and was going to prick his flesh, but Tom said:
+
+"Hold on! Don't do that. A pin's brass. It might have verdigrease on
+it."
+
+"What's verdigrease?"
+
+"It's p'ison. That's what it is. You just swaller some of it once
+--you'll see."
+
+So Tom unwound the thread from one of his needles, and each boy
+pricked the ball of his thumb and squeezed out a drop of blood. In
+time, after many squeezes, Tom managed to sign his initials, using the
+ball of his little finger for a pen. Then he showed Huckleberry how to
+make an H and an F, and the oath was complete. They buried the shingle
+close to the wall, with some dismal ceremonies and incantations, and
+the fetters that bound their tongues were considered to be locked and
+the key thrown away.
+
+A figure crept stealthily through a break in the other end of the
+ruined building, now, but they did not notice it.
+
+"Tom," whispered Huckleberry, "does this keep us from EVER telling
+--ALWAYS?"
+
+"Of course it does. It don't make any difference WHAT happens, we got
+to keep mum. We'd drop down dead--don't YOU know that?"
+
+"Yes, I reckon that's so."
+
+They continued to whisper for some little time. Presently a dog set up
+a long, lugubrious howl just outside--within ten feet of them. The boys
+clasped each other suddenly, in an agony of fright.
+
+"Which of us does he mean?" gasped Huckleberry.
+
+"I dono--peep through the crack. Quick!"
+
+"No, YOU, Tom!"
+
+"I can't--I can't DO it, Huck!"
+
+"Please, Tom. There 'tis again!"
+
+"Oh, lordy, I'm thankful!" whispered Tom. "I know his voice. It's Bull
+Harbison." *
+
+[* If Mr. Harbison owned a slave named Bull, Tom would have spoken of
+him as "Harbison's Bull," but a son or a dog of that name was "Bull
+Harbison."]
+
+"Oh, that's good--I tell you, Tom, I was most scared to death; I'd a
+bet anything it was a STRAY dog."
+
+The dog howled again. The boys' hearts sank once more.
+
+"Oh, my! that ain't no Bull Harbison!" whispered Huckleberry. "DO, Tom!"
+
+Tom, quaking with fear, yielded, and put his eye to the crack. His
+whisper was hardly audible when he said:
+
+"Oh, Huck, IT S A STRAY DOG!"
+
+"Quick, Tom, quick! Who does he mean?"
+
+"Huck, he must mean us both--we're right together."
+
+"Oh, Tom, I reckon we're goners. I reckon there ain't no mistake 'bout
+where I'LL go to. I been so wicked."
+
+"Dad fetch it! This comes of playing hookey and doing everything a
+feller's told NOT to do. I might a been good, like Sid, if I'd a tried
+--but no, I wouldn't, of course. But if ever I get off this time, I lay
+I'll just WALLER in Sunday-schools!" And Tom began to snuffle a little.
+
+"YOU bad!" and Huckleberry began to snuffle too. "Consound it, Tom
+Sawyer, you're just old pie, 'longside o' what I am. Oh, LORDY, lordy,
+lordy, I wisht I only had half your chance."
+
+Tom choked off and whispered:
+
+"Look, Hucky, look! He's got his BACK to us!"
+
+Hucky looked, with joy in his heart.
+
+"Well, he has, by jingoes! Did he before?"
+
+"Yes, he did. But I, like a fool, never thought. Oh, this is bully,
+you know. NOW who can he mean?"
+
+The howling stopped. Tom pricked up his ears.
+
+"Sh! What's that?" he whispered.
+
+"Sounds like--like hogs grunting. No--it's somebody snoring, Tom."
+
+"That IS it! Where 'bouts is it, Huck?"
+
+"I bleeve it's down at 'tother end. Sounds so, anyway. Pap used to
+sleep there, sometimes, 'long with the hogs, but laws bless you, he
+just lifts things when HE snores. Besides, I reckon he ain't ever
+coming back to this town any more."
+
+The spirit of adventure rose in the boys' souls once more.
+
+"Hucky, do you das't to go if I lead?"
+
+"I don't like to, much. Tom, s'pose it's Injun Joe!"
+
+Tom quailed. But presently the temptation rose up strong again and the
+boys agreed to try, with the understanding that they would take to
+their heels if the snoring stopped. So they went tiptoeing stealthily
+down, the one behind the other. When they had got to within five steps
+of the snorer, Tom stepped on a stick, and it broke with a sharp snap.
+The man moaned, writhed a little, and his face came into the moonlight.
+It was Muff Potter. The boys' hearts had stood still, and their hopes
+too, when the man moved, but their fears passed away now. They tiptoed
+out, through the broken weather-boarding, and stopped at a little
+distance to exchange a parting word. That long, lugubrious howl rose on
+the night air again! They turned and saw the strange dog standing
+within a few feet of where Potter was lying, and FACING Potter, with
+his nose pointing heavenward.
+
+"Oh, geeminy, it's HIM!" exclaimed both boys, in a breath.
+
+"Say, Tom--they say a stray dog come howling around Johnny Miller's
+house, 'bout midnight, as much as two weeks ago; and a whippoorwill
+come in and lit on the banisters and sung, the very same evening; and
+there ain't anybody dead there yet."
+
+"Well, I know that. And suppose there ain't. Didn't Gracie Miller fall
+in the kitchen fire and burn herself terrible the very next Saturday?"
+
+"Yes, but she ain't DEAD. And what's more, she's getting better, too."
+
+"All right, you wait and see. She's a goner, just as dead sure as Muff
+Potter's a goner. That's what the niggers say, and they know all about
+these kind of things, Huck."
+
+Then they separated, cogitating. When Tom crept in at his bedroom
+window the night was almost spent. He undressed with excessive caution,
+and fell asleep congratulating himself that nobody knew of his
+escapade. He was not aware that the gently-snoring Sid was awake, and
+had been so for an hour.
+
+When Tom awoke, Sid was dressed and gone. There was a late look in the
+light, a late sense in the atmosphere. He was startled. Why had he not
+been called--persecuted till he was up, as usual? The thought filled
+him with bodings. Within five minutes he was dressed and down-stairs,
+feeling sore and drowsy. The family were still at table, but they had
+finished breakfast. There was no voice of rebuke; but there were
+averted eyes; there was a silence and an air of solemnity that struck a
+chill to the culprit's heart. He sat down and tried to seem gay, but it
+was up-hill work; it roused no smile, no response, and he lapsed into
+silence and let his heart sink down to the depths.
+
+After breakfast his aunt took him aside, and Tom almost brightened in
+the hope that he was going to be flogged; but it was not so. His aunt
+wept over him and asked him how he could go and break her old heart so;
+and finally told him to go on, and ruin himself and bring her gray
+hairs with sorrow to the grave, for it was no use for her to try any
+more. This was worse than a thousand whippings, and Tom's heart was
+sorer now than his body. He cried, he pleaded for forgiveness, promised
+to reform over and over again, and then received his dismissal, feeling
+that he had won but an imperfect forgiveness and established but a
+feeble confidence.
+
+He left the presence too miserable to even feel revengeful toward Sid;
+and so the latter's prompt retreat through the back gate was
+unnecessary. He moped to school gloomy and sad, and took his flogging,
+along with Joe Harper, for playing hookey the day before, with the air
+of one whose heart was busy with heavier woes and wholly dead to
+trifles. Then he betook himself to his seat, rested his elbows on his
+desk and his jaws in his hands, and stared at the wall with the stony
+stare of suffering that has reached the limit and can no further go.
+His elbow was pressing against some hard substance. After a long time
+he slowly and sadly changed his position, and took up this object with
+a sigh. It was in a paper. He unrolled it. A long, lingering, colossal
+sigh followed, and his heart broke. It was his brass andiron knob!
+
+This final feather broke the camel's back.
+
+
+
+CHAPTER XI
+
+CLOSE upon the hour of noon the whole village was suddenly electrified
+with the ghastly news. No need of the as yet undreamed-of telegraph;
+the tale flew from man to man, from group to group, from house to
+house, with little less than telegraphic speed. Of course the
+schoolmaster gave holiday for that afternoon; the town would have
+thought strangely of him if he had not.
+
+A gory knife had been found close to the murdered man, and it had been
+recognized by somebody as belonging to Muff Potter--so the story ran.
+And it was said that a belated citizen had come upon Potter washing
+himself in the "branch" about one or two o'clock in the morning, and
+that Potter had at once sneaked off--suspicious circumstances,
+especially the washing which was not a habit with Potter. It was also
+said that the town had been ransacked for this "murderer" (the public
+are not slow in the matter of sifting evidence and arriving at a
+verdict), but that he could not be found. Horsemen had departed down
+all the roads in every direction, and the Sheriff "was confident" that
+he would be captured before night.
+
+All the town was drifting toward the graveyard. Tom's heartbreak
+vanished and he joined the procession, not because he would not a
+thousand times rather go anywhere else, but because an awful,
+unaccountable fascination drew him on. Arrived at the dreadful place,
+he wormed his small body through the crowd and saw the dismal
+spectacle. It seemed to him an age since he was there before. Somebody
+pinched his arm. He turned, and his eyes met Huckleberry's. Then both
+looked elsewhere at once, and wondered if anybody had noticed anything
+in their mutual glance. But everybody was talking, and intent upon the
+grisly spectacle before them.
+
+"Poor fellow!" "Poor young fellow!" "This ought to be a lesson to
+grave robbers!" "Muff Potter'll hang for this if they catch him!" This
+was the drift of remark; and the minister said, "It was a judgment; His
+hand is here."
+
+Now Tom shivered from head to heel; for his eye fell upon the stolid
+face of Injun Joe. At this moment the crowd began to sway and struggle,
+and voices shouted, "It's him! it's him! he's coming himself!"
+
+"Who? Who?" from twenty voices.
+
+"Muff Potter!"
+
+"Hallo, he's stopped!--Look out, he's turning! Don't let him get away!"
+
+People in the branches of the trees over Tom's head said he wasn't
+trying to get away--he only looked doubtful and perplexed.
+
+"Infernal impudence!" said a bystander; "wanted to come and take a
+quiet look at his work, I reckon--didn't expect any company."
+
+The crowd fell apart, now, and the Sheriff came through,
+ostentatiously leading Potter by the arm. The poor fellow's face was
+haggard, and his eyes showed the fear that was upon him. When he stood
+before the murdered man, he shook as with a palsy, and he put his face
+in his hands and burst into tears.
+
+"I didn't do it, friends," he sobbed; "'pon my word and honor I never
+done it."
+
+"Who's accused you?" shouted a voice.
+
+This shot seemed to carry home. Potter lifted his face and looked
+around him with a pathetic hopelessness in his eyes. He saw Injun Joe,
+and exclaimed:
+
+"Oh, Injun Joe, you promised me you'd never--"
+
+"Is that your knife?" and it was thrust before him by the Sheriff.
+
+Potter would have fallen if they had not caught him and eased him to
+the ground. Then he said:
+
+"Something told me 't if I didn't come back and get--" He shuddered;
+then waved his nerveless hand with a vanquished gesture and said, "Tell
+'em, Joe, tell 'em--it ain't any use any more."
+
+Then Huckleberry and Tom stood dumb and staring, and heard the
+stony-hearted liar reel off his serene statement, they expecting every
+moment that the clear sky would deliver God's lightnings upon his head,
+and wondering to see how long the stroke was delayed. And when he had
+finished and still stood alive and whole, their wavering impulse to
+break their oath and save the poor betrayed prisoner's life faded and
+vanished away, for plainly this miscreant had sold himself to Satan and
+it would be fatal to meddle with the property of such a power as that.
+
+"Why didn't you leave? What did you want to come here for?" somebody
+said.
+
+"I couldn't help it--I couldn't help it," Potter moaned. "I wanted to
+run away, but I couldn't seem to come anywhere but here." And he fell
+to sobbing again.
+
+Injun Joe repeated his statement, just as calmly, a few minutes
+afterward on the inquest, under oath; and the boys, seeing that the
+lightnings were still withheld, were confirmed in their belief that Joe
+had sold himself to the devil. He was now become, to them, the most
+balefully interesting object they had ever looked upon, and they could
+not take their fascinated eyes from his face.
+
+They inwardly resolved to watch him nights, when opportunity should
+offer, in the hope of getting a glimpse of his dread master.
+
+Injun Joe helped to raise the body of the murdered man and put it in a
+wagon for removal; and it was whispered through the shuddering crowd
+that the wound bled a little! The boys thought that this happy
+circumstance would turn suspicion in the right direction; but they were
+disappointed, for more than one villager remarked:
+
+"It was within three feet of Muff Potter when it done it."
+
+Tom's fearful secret and gnawing conscience disturbed his sleep for as
+much as a week after this; and at breakfast one morning Sid said:
+
+"Tom, you pitch around and talk in your sleep so much that you keep me
+awake half the time."
+
+Tom blanched and dropped his eyes.
+
+"It's a bad sign," said Aunt Polly, gravely. "What you got on your
+mind, Tom?"
+
+"Nothing. Nothing 't I know of." But the boy's hand shook so that he
+spilled his coffee.
+
+"And you do talk such stuff," Sid said. "Last night you said, 'It's
+blood, it's blood, that's what it is!' You said that over and over. And
+you said, 'Don't torment me so--I'll tell!' Tell WHAT? What is it
+you'll tell?"
+
+Everything was swimming before Tom. There is no telling what might
+have happened, now, but luckily the concern passed out of Aunt Polly's
+face and she came to Tom's relief without knowing it. She said:
+
+"Sho! It's that dreadful murder. I dream about it most every night
+myself. Sometimes I dream it's me that done it."
+
+Mary said she had been affected much the same way. Sid seemed
+satisfied. Tom got out of the presence as quick as he plausibly could,
+and after that he complained of toothache for a week, and tied up his
+jaws every night. He never knew that Sid lay nightly watching, and
+frequently slipped the bandage free and then leaned on his elbow
+listening a good while at a time, and afterward slipped the bandage
+back to its place again. Tom's distress of mind wore off gradually and
+the toothache grew irksome and was discarded. If Sid really managed to
+make anything out of Tom's disjointed mutterings, he kept it to himself.
+
+It seemed to Tom that his schoolmates never would get done holding
+inquests on dead cats, and thus keeping his trouble present to his
+mind. Sid noticed that Tom never was coroner at one of these inquiries,
+though it had been his habit to take the lead in all new enterprises;
+he noticed, too, that Tom never acted as a witness--and that was
+strange; and Sid did not overlook the fact that Tom even showed a
+marked aversion to these inquests, and always avoided them when he
+could. Sid marvelled, but said nothing. However, even inquests went out
+of vogue at last, and ceased to torture Tom's conscience.
+
+Every day or two, during this time of sorrow, Tom watched his
+opportunity and went to the little grated jail-window and smuggled such
+small comforts through to the "murderer" as he could get hold of. The
+jail was a trifling little brick den that stood in a marsh at the edge
+of the village, and no guards were afforded for it; indeed, it was
+seldom occupied. These offerings greatly helped to ease Tom's
+conscience.
+
+The villagers had a strong desire to tar-and-feather Injun Joe and
+ride him on a rail, for body-snatching, but so formidable was his
+character that nobody could be found who was willing to take the lead
+in the matter, so it was dropped. He had been careful to begin both of
+his inquest-statements with the fight, without confessing the
+grave-robbery that preceded it; therefore it was deemed wisest not
+to try the case in the courts at present.
+
+
+
+CHAPTER XII
+
+ONE of the reasons why Tom's mind had drifted away from its secret
+troubles was, that it had found a new and weighty matter to interest
+itself about. Becky Thatcher had stopped coming to school. Tom had
+struggled with his pride a few days, and tried to "whistle her down the
+wind," but failed. He began to find himself hanging around her father's
+house, nights, and feeling very miserable. She was ill. What if she
+should die! There was distraction in the thought. He no longer took an
+interest in war, nor even in piracy. The charm of life was gone; there
+was nothing but dreariness left. He put his hoop away, and his bat;
+there was no joy in them any more. His aunt was concerned. She began to
+try all manner of remedies on him. She was one of those people who are
+infatuated with patent medicines and all new-fangled methods of
+producing health or mending it. She was an inveterate experimenter in
+these things. When something fresh in this line came out she was in a
+fever, right away, to try it; not on herself, for she was never ailing,
+but on anybody else that came handy. She was a subscriber for all the
+"Health" periodicals and phrenological frauds; and the solemn ignorance
+they were inflated with was breath to her nostrils. All the "rot" they
+contained about ventilation, and how to go to bed, and how to get up,
+and what to eat, and what to drink, and how much exercise to take, and
+what frame of mind to keep one's self in, and what sort of clothing to
+wear, was all gospel to her, and she never observed that her
+health-journals of the current month customarily upset everything they
+had recommended the month before. She was as simple-hearted and honest
+as the day was long, and so she was an easy victim. She gathered
+together her quack periodicals and her quack medicines, and thus armed
+with death, went about on her pale horse, metaphorically speaking, with
+"hell following after." But she never suspected that she was not an
+angel of healing and the balm of Gilead in disguise, to the suffering
+neighbors.
+
+The water treatment was new, now, and Tom's low condition was a
+windfall to her. She had him out at daylight every morning, stood him
+up in the woodshed and drowned him with a deluge of cold water; then
+she scrubbed him down with a towel like a file, and so brought him to;
+then she rolled him up in a wet sheet and put him away under blankets
+till she sweated his soul clean and "the yellow stains of it came
+through his pores"--as Tom said.
+
+Yet notwithstanding all this, the boy grew more and more melancholy
+and pale and dejected. She added hot baths, sitz baths, shower baths,
+and plunges. The boy remained as dismal as a hearse. She began to
+assist the water with a slim oatmeal diet and blister-plasters. She
+calculated his capacity as she would a jug's, and filled him up every
+day with quack cure-alls.
+
+Tom had become indifferent to persecution by this time. This phase
+filled the old lady's heart with consternation. This indifference must
+be broken up at any cost. Now she heard of Pain-killer for the first
+time. She ordered a lot at once. She tasted it and was filled with
+gratitude. It was simply fire in a liquid form. She dropped the water
+treatment and everything else, and pinned her faith to Pain-killer. She
+gave Tom a teaspoonful and watched with the deepest anxiety for the
+result. Her troubles were instantly at rest, her soul at peace again;
+for the "indifference" was broken up. The boy could not have shown a
+wilder, heartier interest, if she had built a fire under him.
+
+Tom felt that it was time to wake up; this sort of life might be
+romantic enough, in his blighted condition, but it was getting to have
+too little sentiment and too much distracting variety about it. So he
+thought over various plans for relief, and finally hit pon that of
+professing to be fond of Pain-killer. He asked for it so often that he
+became a nuisance, and his aunt ended by telling him to help himself
+and quit bothering her. If it had been Sid, she would have had no
+misgivings to alloy her delight; but since it was Tom, she watched the
+bottle clandestinely. She found that the medicine did really diminish,
+but it did not occur to her that the boy was mending the health of a
+crack in the sitting-room floor with it.
+
+One day Tom was in the act of dosing the crack when his aunt's yellow
+cat came along, purring, eying the teaspoon avariciously, and begging
+for a taste. Tom said:
+
+"Don't ask for it unless you want it, Peter."
+
+But Peter signified that he did want it.
+
+"You better make sure."
+
+Peter was sure.
+
+"Now you've asked for it, and I'll give it to you, because there ain't
+anything mean about me; but if you find you don't like it, you mustn't
+blame anybody but your own self."
+
+Peter was agreeable. So Tom pried his mouth open and poured down the
+Pain-killer. Peter sprang a couple of yards in the air, and then
+delivered a war-whoop and set off round and round the room, banging
+against furniture, upsetting flower-pots, and making general havoc.
+Next he rose on his hind feet and pranced around, in a frenzy of
+enjoyment, with his head over his shoulder and his voice proclaiming
+his unappeasable happiness. Then he went tearing around the house again
+spreading chaos and destruction in his path. Aunt Polly entered in time
+to see him throw a few double summersets, deliver a final mighty
+hurrah, and sail through the open window, carrying the rest of the
+flower-pots with him. The old lady stood petrified with astonishment,
+peering over her glasses; Tom lay on the floor expiring with laughter.
+
+"Tom, what on earth ails that cat?"
+
+"I don't know, aunt," gasped the boy.
+
+"Why, I never see anything like it. What did make him act so?"
+
+"Deed I don't know, Aunt Polly; cats always act so when they're having
+a good time."
+
+"They do, do they?" There was something in the tone that made Tom
+apprehensive.
+
+"Yes'm. That is, I believe they do."
+
+"You DO?"
+
+"Yes'm."
+
+The old lady was bending down, Tom watching, with interest emphasized
+by anxiety. Too late he divined her "drift." The handle of the telltale
+teaspoon was visible under the bed-valance. Aunt Polly took it, held it
+up. Tom winced, and dropped his eyes. Aunt Polly raised him by the
+usual handle--his ear--and cracked his head soundly with her thimble.
+
+"Now, sir, what did you want to treat that poor dumb beast so, for?"
+
+"I done it out of pity for him--because he hadn't any aunt."
+
+"Hadn't any aunt!--you numskull. What has that got to do with it?"
+
+"Heaps. Because if he'd had one she'd a burnt him out herself! She'd a
+roasted his bowels out of him 'thout any more feeling than if he was a
+human!"
+
+Aunt Polly felt a sudden pang of remorse. This was putting the thing
+in a new light; what was cruelty to a cat MIGHT be cruelty to a boy,
+too. She began to soften; she felt sorry. Her eyes watered a little,
+and she put her hand on Tom's head and said gently:
+
+"I was meaning for the best, Tom. And, Tom, it DID do you good."
+
+Tom looked up in her face with just a perceptible twinkle peeping
+through his gravity.
+
+"I know you was meaning for the best, aunty, and so was I with Peter.
+It done HIM good, too. I never see him get around so since--"
+
+"Oh, go 'long with you, Tom, before you aggravate me again. And you
+try and see if you can't be a good boy, for once, and you needn't take
+any more medicine."
+
+Tom reached school ahead of time. It was noticed that this strange
+thing had been occurring every day latterly. And now, as usual of late,
+he hung about the gate of the schoolyard instead of playing with his
+comrades. He was sick, he said, and he looked it. He tried to seem to
+be looking everywhere but whither he really was looking--down the road.
+Presently Jeff Thatcher hove in sight, and Tom's face lighted; he gazed
+a moment, and then turned sorrowfully away. When Jeff arrived, Tom
+accosted him; and "led up" warily to opportunities for remark about
+Becky, but the giddy lad never could see the bait. Tom watched and
+watched, hoping whenever a frisking frock came in sight, and hating the
+owner of it as soon as he saw she was not the right one. At last frocks
+ceased to appear, and he dropped hopelessly into the dumps; he entered
+the empty schoolhouse and sat down to suffer. Then one more frock
+passed in at the gate, and Tom's heart gave a great bound. The next
+instant he was out, and "going on" like an Indian; yelling, laughing,
+chasing boys, jumping over the fence at risk of life and limb, throwing
+handsprings, standing on his head--doing all the heroic things he could
+conceive of, and keeping a furtive eye out, all the while, to see if
+Becky Thatcher was noticing. But she seemed to be unconscious of it
+all; she never looked. Could it be possible that she was not aware that
+he was there? He carried his exploits to her immediate vicinity; came
+war-whooping around, snatched a boy's cap, hurled it to the roof of the
+schoolhouse, broke through a group of boys, tumbling them in every
+direction, and fell sprawling, himself, under Becky's nose, almost
+upsetting her--and she turned, with her nose in the air, and he heard
+her say: "Mf! some people think they're mighty smart--always showing
+off!"
+
+Tom's cheeks burned. He gathered himself up and sneaked off, crushed
+and crestfallen.
+
+
+
+CHAPTER XIII
+
+TOM'S mind was made up now. He was gloomy and desperate. He was a
+forsaken, friendless boy, he said; nobody loved him; when they found
+out what they had driven him to, perhaps they would be sorry; he had
+tried to do right and get along, but they would not let him; since
+nothing would do them but to be rid of him, let it be so; and let them
+blame HIM for the consequences--why shouldn't they? What right had the
+friendless to complain? Yes, they had forced him to it at last: he
+would lead a life of crime. There was no choice.
+
+By this time he was far down Meadow Lane, and the bell for school to
+"take up" tinkled faintly upon his ear. He sobbed, now, to think he
+should never, never hear that old familiar sound any more--it was very
+hard, but it was forced on him; since he was driven out into the cold
+world, he must submit--but he forgave them. Then the sobs came thick
+and fast.
+
+Just at this point he met his soul's sworn comrade, Joe Harper
+--hard-eyed, and with evidently a great and dismal purpose in his heart.
+Plainly here were "two souls with but a single thought." Tom, wiping
+his eyes with his sleeve, began to blubber out something about a
+resolution to escape from hard usage and lack of sympathy at home by
+roaming abroad into the great world never to return; and ended by
+hoping that Joe would not forget him.
+
+But it transpired that this was a request which Joe had just been
+going to make of Tom, and had come to hunt him up for that purpose. His
+mother had whipped him for drinking some cream which he had never
+tasted and knew nothing about; it was plain that she was tired of him
+and wished him to go; if she felt that way, there was nothing for him
+to do but succumb; he hoped she would be happy, and never regret having
+driven her poor boy out into the unfeeling world to suffer and die.
+
+As the two boys walked sorrowing along, they made a new compact to
+stand by each other and be brothers and never separate till death
+relieved them of their troubles. Then they began to lay their plans.
+Joe was for being a hermit, and living on crusts in a remote cave, and
+dying, some time, of cold and want and grief; but after listening to
+Tom, he conceded that there were some conspicuous advantages about a
+life of crime, and so he consented to be a pirate.
+
+Three miles below St. Petersburg, at a point where the Mississippi
+River was a trifle over a mile wide, there was a long, narrow, wooded
+island, with a shallow bar at the head of it, and this offered well as
+a rendezvous. It was not inhabited; it lay far over toward the further
+shore, abreast a dense and almost wholly unpeopled forest. So Jackson's
+Island was chosen. Who were to be the subjects of their piracies was a
+matter that did not occur to them. Then they hunted up Huckleberry
+Finn, and he joined them promptly, for all careers were one to him; he
+was indifferent. They presently separated to meet at a lonely spot on
+the river-bank two miles above the village at the favorite hour--which
+was midnight. There was a small log raft there which they meant to
+capture. Each would bring hooks and lines, and such provision as he
+could steal in the most dark and mysterious way--as became outlaws. And
+before the afternoon was done, they had all managed to enjoy the sweet
+glory of spreading the fact that pretty soon the town would "hear
+something." All who got this vague hint were cautioned to "be mum and
+wait."
+
+About midnight Tom arrived with a boiled ham and a few trifles,
+and stopped in a dense undergrowth on a small bluff overlooking the
+meeting-place. It was starlight, and very still. The mighty river lay
+like an ocean at rest. Tom listened a moment, but no sound disturbed the
+quiet. Then he gave a low, distinct whistle. It was answered from under
+the bluff. Tom whistled twice more; these signals were answered in the
+same way. Then a guarded voice said:
+
+"Who goes there?"
+
+"Tom Sawyer, the Black Avenger of the Spanish Main. Name your names."
+
+"Huck Finn the Red-Handed, and Joe Harper the Terror of the Seas." Tom
+had furnished these titles, from his favorite literature.
+
+"'Tis well. Give the countersign."
+
+Two hoarse whispers delivered the same awful word simultaneously to
+the brooding night:
+
+"BLOOD!"
+
+Then Tom tumbled his ham over the bluff and let himself down after it,
+tearing both skin and clothes to some extent in the effort. There was
+an easy, comfortable path along the shore under the bluff, but it
+lacked the advantages of difficulty and danger so valued by a pirate.
+
+The Terror of the Seas had brought a side of bacon, and had about worn
+himself out with getting it there. Finn the Red-Handed had stolen a
+skillet and a quantity of half-cured leaf tobacco, and had also brought
+a few corn-cobs to make pipes with. But none of the pirates smoked or
+"chewed" but himself. The Black Avenger of the Spanish Main said it
+would never do to start without some fire. That was a wise thought;
+matches were hardly known there in that day. They saw a fire
+smouldering upon a great raft a hundred yards above, and they went
+stealthily thither and helped themselves to a chunk. They made an
+imposing adventure of it, saying, "Hist!" every now and then, and
+suddenly halting with finger on lip; moving with hands on imaginary
+dagger-hilts; and giving orders in dismal whispers that if "the foe"
+stirred, to "let him have it to the hilt," because "dead men tell no
+tales." They knew well enough that the raftsmen were all down at the
+village laying in stores or having a spree, but still that was no
+excuse for their conducting this thing in an unpiratical way.
+
+They shoved off, presently, Tom in command, Huck at the after oar and
+Joe at the forward. Tom stood amidships, gloomy-browed, and with folded
+arms, and gave his orders in a low, stern whisper:
+
+"Luff, and bring her to the wind!"
+
+"Aye-aye, sir!"
+
+"Steady, steady-y-y-y!"
+
+"Steady it is, sir!"
+
+"Let her go off a point!"
+
+"Point it is, sir!"
+
+As the boys steadily and monotonously drove the raft toward mid-stream
+it was no doubt understood that these orders were given only for
+"style," and were not intended to mean anything in particular.
+
+"What sail's she carrying?"
+
+"Courses, tops'ls, and flying-jib, sir."
+
+"Send the r'yals up! Lay out aloft, there, half a dozen of ye
+--foretopmaststuns'l! Lively, now!"
+
+"Aye-aye, sir!"
+
+"Shake out that maintogalans'l! Sheets and braces! NOW my hearties!"
+
+"Aye-aye, sir!"
+
+"Hellum-a-lee--hard a port! Stand by to meet her when she comes! Port,
+port! NOW, men! With a will! Stead-y-y-y!"
+
+"Steady it is, sir!"
+
+The raft drew beyond the middle of the river; the boys pointed her
+head right, and then lay on their oars. The river was not high, so
+there was not more than a two or three mile current. Hardly a word was
+said during the next three-quarters of an hour. Now the raft was
+passing before the distant town. Two or three glimmering lights showed
+where it lay, peacefully sleeping, beyond the vague vast sweep of
+star-gemmed water, unconscious of the tremendous event that was happening.
+The Black Avenger stood still with folded arms, "looking his last" upon
+the scene of his former joys and his later sufferings, and wishing
+"she" could see him now, abroad on the wild sea, facing peril and death
+with dauntless heart, going to his doom with a grim smile on his lips.
+It was but a small strain on his imagination to remove Jackson's Island
+beyond eyeshot of the village, and so he "looked his last" with a
+broken and satisfied heart. The other pirates were looking their last,
+too; and they all looked so long that they came near letting the
+current drift them out of the range of the island. But they discovered
+the danger in time, and made shift to avert it. About two o'clock in
+the morning the raft grounded on the bar two hundred yards above the
+head of the island, and they waded back and forth until they had landed
+their freight. Part of the little raft's belongings consisted of an old
+sail, and this they spread over a nook in the bushes for a tent to
+shelter their provisions; but they themselves would sleep in the open
+air in good weather, as became outlaws.
+
+They built a fire against the side of a great log twenty or thirty
+steps within the sombre depths of the forest, and then cooked some
+bacon in the frying-pan for supper, and used up half of the corn "pone"
+stock they had brought. It seemed glorious sport to be feasting in that
+wild, free way in the virgin forest of an unexplored and uninhabited
+island, far from the haunts of men, and they said they never would
+return to civilization. The climbing fire lit up their faces and threw
+its ruddy glare upon the pillared tree-trunks of their forest temple,
+and upon the varnished foliage and festooning vines.
+
+When the last crisp slice of bacon was gone, and the last allowance of
+corn pone devoured, the boys stretched themselves out on the grass,
+filled with contentment. They could have found a cooler place, but they
+would not deny themselves such a romantic feature as the roasting
+camp-fire.
+
+"AIN'T it gay?" said Joe.
+
+"It's NUTS!" said Tom. "What would the boys say if they could see us?"
+
+"Say? Well, they'd just die to be here--hey, Hucky!"
+
+"I reckon so," said Huckleberry; "anyways, I'm suited. I don't want
+nothing better'n this. I don't ever get enough to eat, gen'ally--and
+here they can't come and pick at a feller and bullyrag him so."
+
+"It's just the life for me," said Tom. "You don't have to get up,
+mornings, and you don't have to go to school, and wash, and all that
+blame foolishness. You see a pirate don't have to do ANYTHING, Joe,
+when he's ashore, but a hermit HE has to be praying considerable, and
+then he don't have any fun, anyway, all by himself that way."
+
+"Oh yes, that's so," said Joe, "but I hadn't thought much about it,
+you know. I'd a good deal rather be a pirate, now that I've tried it."
+
+"You see," said Tom, "people don't go much on hermits, nowadays, like
+they used to in old times, but a pirate's always respected. And a
+hermit's got to sleep on the hardest place he can find, and put
+sackcloth and ashes on his head, and stand out in the rain, and--"
+
+"What does he put sackcloth and ashes on his head for?" inquired Huck.
+
+"I dono. But they've GOT to do it. Hermits always do. You'd have to do
+that if you was a hermit."
+
+"Dern'd if I would," said Huck.
+
+"Well, what would you do?"
+
+"I dono. But I wouldn't do that."
+
+"Why, Huck, you'd HAVE to. How'd you get around it?"
+
+"Why, I just wouldn't stand it. I'd run away."
+
+"Run away! Well, you WOULD be a nice old slouch of a hermit. You'd be
+a disgrace."
+
+The Red-Handed made no response, being better employed. He had
+finished gouging out a cob, and now he fitted a weed stem to it, loaded
+it with tobacco, and was pressing a coal to the charge and blowing a
+cloud of fragrant smoke--he was in the full bloom of luxurious
+contentment. The other pirates envied him this majestic vice, and
+secretly resolved to acquire it shortly. Presently Huck said:
+
+"What does pirates have to do?"
+
+Tom said:
+
+"Oh, they have just a bully time--take ships and burn them, and get
+the money and bury it in awful places in their island where there's
+ghosts and things to watch it, and kill everybody in the ships--make
+'em walk a plank."
+
+"And they carry the women to the island," said Joe; "they don't kill
+the women."
+
+"No," assented Tom, "they don't kill the women--they're too noble. And
+the women's always beautiful, too.
+
+"And don't they wear the bulliest clothes! Oh no! All gold and silver
+and di'monds," said Joe, with enthusiasm.
+
+"Who?" said Huck.
+
+"Why, the pirates."
+
+Huck scanned his own clothing forlornly.
+
+"I reckon I ain't dressed fitten for a pirate," said he, with a
+regretful pathos in his voice; "but I ain't got none but these."
+
+But the other boys told him the fine clothes would come fast enough,
+after they should have begun their adventures. They made him understand
+that his poor rags would do to begin with, though it was customary for
+wealthy pirates to start with a proper wardrobe.
+
+Gradually their talk died out and drowsiness began to steal upon the
+eyelids of the little waifs. The pipe dropped from the fingers of the
+Red-Handed, and he slept the sleep of the conscience-free and the
+weary. The Terror of the Seas and the Black Avenger of the Spanish Main
+had more difficulty in getting to sleep. They said their prayers
+inwardly, and lying down, since there was nobody there with authority
+to make them kneel and recite aloud; in truth, they had a mind not to
+say them at all, but they were afraid to proceed to such lengths as
+that, lest they might call down a sudden and special thunderbolt from
+heaven. Then at once they reached and hovered upon the imminent verge
+of sleep--but an intruder came, now, that would not "down." It was
+conscience. They began to feel a vague fear that they had been doing
+wrong to run away; and next they thought of the stolen meat, and then
+the real torture came. They tried to argue it away by reminding
+conscience that they had purloined sweetmeats and apples scores of
+times; but conscience was not to be appeased by such thin
+plausibilities; it seemed to them, in the end, that there was no
+getting around the stubborn fact that taking sweetmeats was only
+"hooking," while taking bacon and hams and such valuables was plain
+simple stealing--and there was a command against that in the Bible. So
+they inwardly resolved that so long as they remained in the business,
+their piracies should not again be sullied with the crime of stealing.
+Then conscience granted a truce, and these curiously inconsistent
+pirates fell peacefully to sleep.
+
+
+
+CHAPTER XIV
+
+WHEN Tom awoke in the morning, he wondered where he was. He sat up and
+rubbed his eyes and looked around. Then he comprehended. It was the
+cool gray dawn, and there was a delicious sense of repose and peace in
+the deep pervading calm and silence of the woods. Not a leaf stirred;
+not a sound obtruded upon great Nature's meditation. Beaded dewdrops
+stood upon the leaves and grasses. A white layer of ashes covered the
+fire, and a thin blue breath of smoke rose straight into the air. Joe
+and Huck still slept.
+
+Now, far away in the woods a bird called; another answered; presently
+the hammering of a woodpecker was heard. Gradually the cool dim gray of
+the morning whitened, and as gradually sounds multiplied and life
+manifested itself. The marvel of Nature shaking off sleep and going to
+work unfolded itself to the musing boy. A little green worm came
+crawling over a dewy leaf, lifting two-thirds of his body into the air
+from time to time and "sniffing around," then proceeding again--for he
+was measuring, Tom said; and when the worm approached him, of its own
+accord, he sat as still as a stone, with his hopes rising and falling,
+by turns, as the creature still came toward him or seemed inclined to
+go elsewhere; and when at last it considered a painful moment with its
+curved body in the air and then came decisively down upon Tom's leg and
+began a journey over him, his whole heart was glad--for that meant that
+he was going to have a new suit of clothes--without the shadow of a
+doubt a gaudy piratical uniform. Now a procession of ants appeared,
+from nowhere in particular, and went about their labors; one struggled
+manfully by with a dead spider five times as big as itself in its arms,
+and lugged it straight up a tree-trunk. A brown spotted lady-bug
+climbed the dizzy height of a grass blade, and Tom bent down close to
+it and said, "Lady-bug, lady-bug, fly away home, your house is on fire,
+your children's alone," and she took wing and went off to see about it
+--which did not surprise the boy, for he knew of old that this insect was
+credulous about conflagrations, and he had practised upon its
+simplicity more than once. A tumblebug came next, heaving sturdily at
+its ball, and Tom touched the creature, to see it shut its legs against
+its body and pretend to be dead. The birds were fairly rioting by this
+time. A catbird, the Northern mocker, lit in a tree over Tom's head,
+and trilled out her imitations of her neighbors in a rapture of
+enjoyment; then a shrill jay swept down, a flash of blue flame, and
+stopped on a twig almost within the boy's reach, cocked his head to one
+side and eyed the strangers with a consuming curiosity; a gray squirrel
+and a big fellow of the "fox" kind came skurrying along, sitting up at
+intervals to inspect and chatter at the boys, for the wild things had
+probably never seen a human being before and scarcely knew whether to
+be afraid or not. All Nature was wide awake and stirring, now; long
+lances of sunlight pierced down through the dense foliage far and near,
+and a few butterflies came fluttering upon the scene.
+
+Tom stirred up the other pirates and they all clattered away with a
+shout, and in a minute or two were stripped and chasing after and
+tumbling over each other in the shallow limpid water of the white
+sandbar. They felt no longing for the little village sleeping in the
+distance beyond the majestic waste of water. A vagrant current or a
+slight rise in the river had carried off their raft, but this only
+gratified them, since its going was something like burning the bridge
+between them and civilization.
+
+They came back to camp wonderfully refreshed, glad-hearted, and
+ravenous; and they soon had the camp-fire blazing up again. Huck found
+a spring of clear cold water close by, and the boys made cups of broad
+oak or hickory leaves, and felt that water, sweetened with such a
+wildwood charm as that, would be a good enough substitute for coffee.
+While Joe was slicing bacon for breakfast, Tom and Huck asked him to
+hold on a minute; they stepped to a promising nook in the river-bank
+and threw in their lines; almost immediately they had reward. Joe had
+not had time to get impatient before they were back again with some
+handsome bass, a couple of sun-perch and a small catfish--provisions
+enough for quite a family. They fried the fish with the bacon, and were
+astonished; for no fish had ever seemed so delicious before. They did
+not know that the quicker a fresh-water fish is on the fire after he is
+caught the better he is; and they reflected little upon what a sauce
+open-air sleeping, open-air exercise, bathing, and a large ingredient
+of hunger make, too.
+
+They lay around in the shade, after breakfast, while Huck had a smoke,
+and then went off through the woods on an exploring expedition. They
+tramped gayly along, over decaying logs, through tangled underbrush,
+among solemn monarchs of the forest, hung from their crowns to the
+ground with a drooping regalia of grape-vines. Now and then they came
+upon snug nooks carpeted with grass and jeweled with flowers.
+
+They found plenty of things to be delighted with, but nothing to be
+astonished at. They discovered that the island was about three miles
+long and a quarter of a mile wide, and that the shore it lay closest to
+was only separated from it by a narrow channel hardly two hundred yards
+wide. They took a swim about every hour, so it was close upon the
+middle of the afternoon when they got back to camp. They were too
+hungry to stop to fish, but they fared sumptuously upon cold ham, and
+then threw themselves down in the shade to talk. But the talk soon
+began to drag, and then died. The stillness, the solemnity that brooded
+in the woods, and the sense of loneliness, began to tell upon the
+spirits of the boys. They fell to thinking. A sort of undefined longing
+crept upon them. This took dim shape, presently--it was budding
+homesickness. Even Finn the Red-Handed was dreaming of his doorsteps
+and empty hogsheads. But they were all ashamed of their weakness, and
+none was brave enough to speak his thought.
+
+For some time, now, the boys had been dully conscious of a peculiar
+sound in the distance, just as one sometimes is of the ticking of a
+clock which he takes no distinct note of. But now this mysterious sound
+became more pronounced, and forced a recognition. The boys started,
+glanced at each other, and then each assumed a listening attitude.
+There was a long silence, profound and unbroken; then a deep, sullen
+boom came floating down out of the distance.
+
+"What is it!" exclaimed Joe, under his breath.
+
+"I wonder," said Tom in a whisper.
+
+"'Tain't thunder," said Huckleberry, in an awed tone, "becuz thunder--"
+
+"Hark!" said Tom. "Listen--don't talk."
+
+They waited a time that seemed an age, and then the same muffled boom
+troubled the solemn hush.
+
+"Let's go and see."
+
+They sprang to their feet and hurried to the shore toward the town.
+They parted the bushes on the bank and peered out over the water. The
+little steam ferryboat was about a mile below the village, drifting
+with the current. Her broad deck seemed crowded with people. There were
+a great many skiffs rowing about or floating with the stream in the
+neighborhood of the ferryboat, but the boys could not determine what
+the men in them were doing. Presently a great jet of white smoke burst
+from the ferryboat's side, and as it expanded and rose in a lazy cloud,
+that same dull throb of sound was borne to the listeners again.
+
+"I know now!" exclaimed Tom; "somebody's drownded!"
+
+"That's it!" said Huck; "they done that last summer, when Bill Turner
+got drownded; they shoot a cannon over the water, and that makes him
+come up to the top. Yes, and they take loaves of bread and put
+quicksilver in 'em and set 'em afloat, and wherever there's anybody
+that's drownded, they'll float right there and stop."
+
+"Yes, I've heard about that," said Joe. "I wonder what makes the bread
+do that."
+
+"Oh, it ain't the bread, so much," said Tom; "I reckon it's mostly
+what they SAY over it before they start it out."
+
+"But they don't say anything over it," said Huck. "I've seen 'em and
+they don't."
+
+"Well, that's funny," said Tom. "But maybe they say it to themselves.
+Of COURSE they do. Anybody might know that."
+
+The other boys agreed that there was reason in what Tom said, because
+an ignorant lump of bread, uninstructed by an incantation, could not be
+expected to act very intelligently when set upon an errand of such
+gravity.
+
+"By jings, I wish I was over there, now," said Joe.
+
+"I do too" said Huck "I'd give heaps to know who it is."
+
+The boys still listened and watched. Presently a revealing thought
+flashed through Tom's mind, and he exclaimed:
+
+"Boys, I know who's drownded--it's us!"
+
+They felt like heroes in an instant. Here was a gorgeous triumph; they
+were missed; they were mourned; hearts were breaking on their account;
+tears were being shed; accusing memories of unkindness to these poor
+lost lads were rising up, and unavailing regrets and remorse were being
+indulged; and best of all, the departed were the talk of the whole
+town, and the envy of all the boys, as far as this dazzling notoriety
+was concerned. This was fine. It was worth while to be a pirate, after
+all.
+
+As twilight drew on, the ferryboat went back to her accustomed
+business and the skiffs disappeared. The pirates returned to camp. They
+were jubilant with vanity over their new grandeur and the illustrious
+trouble they were making. They caught fish, cooked supper and ate it,
+and then fell to guessing at what the village was thinking and saying
+about them; and the pictures they drew of the public distress on their
+account were gratifying to look upon--from their point of view. But
+when the shadows of night closed them in, they gradually ceased to
+talk, and sat gazing into the fire, with their minds evidently
+wandering elsewhere. The excitement was gone, now, and Tom and Joe
+could not keep back thoughts of certain persons at home who were not
+enjoying this fine frolic as much as they were. Misgivings came; they
+grew troubled and unhappy; a sigh or two escaped, unawares. By and by
+Joe timidly ventured upon a roundabout "feeler" as to how the others
+might look upon a return to civilization--not right now, but--
+
+Tom withered him with derision! Huck, being uncommitted as yet, joined
+in with Tom, and the waverer quickly "explained," and was glad to get
+out of the scrape with as little taint of chicken-hearted homesickness
+clinging to his garments as he could. Mutiny was effectually laid to
+rest for the moment.
+
+As the night deepened, Huck began to nod, and presently to snore. Joe
+followed next. Tom lay upon his elbow motionless, for some time,
+watching the two intently. At last he got up cautiously, on his knees,
+and went searching among the grass and the flickering reflections flung
+by the camp-fire. He picked up and inspected several large
+semi-cylinders of the thin white bark of a sycamore, and finally chose
+two which seemed to suit him. Then he knelt by the fire and painfully
+wrote something upon each of these with his "red keel"; one he rolled up
+and put in his jacket pocket, and the other he put in Joe's hat and
+removed it to a little distance from the owner. And he also put into the
+hat certain schoolboy treasures of almost inestimable value--among them
+a lump of chalk, an India-rubber ball, three fishhooks, and one of that
+kind of marbles known as a "sure 'nough crystal." Then he tiptoed his
+way cautiously among the trees till he felt that he was out of hearing,
+and straightway broke into a keen run in the direction of the sandbar.
+
+
+
+CHAPTER XV
+
+A FEW minutes later Tom was in the shoal water of the bar, wading
+toward the Illinois shore. Before the depth reached his middle he was
+half-way over; the current would permit no more wading, now, so he
+struck out confidently to swim the remaining hundred yards. He swam
+quartering upstream, but still was swept downward rather faster than he
+had expected. However, he reached the shore finally, and drifted along
+till he found a low place and drew himself out. He put his hand on his
+jacket pocket, found his piece of bark safe, and then struck through
+the woods, following the shore, with streaming garments. Shortly before
+ten o'clock he came out into an open place opposite the village, and
+saw the ferryboat lying in the shadow of the trees and the high bank.
+Everything was quiet under the blinking stars. He crept down the bank,
+watching with all his eyes, slipped into the water, swam three or four
+strokes and climbed into the skiff that did "yawl" duty at the boat's
+stern. He laid himself down under the thwarts and waited, panting.
+
+Presently the cracked bell tapped and a voice gave the order to "cast
+off." A minute or two later the skiff's head was standing high up,
+against the boat's swell, and the voyage was begun. Tom felt happy in
+his success, for he knew it was the boat's last trip for the night. At
+the end of a long twelve or fifteen minutes the wheels stopped, and Tom
+slipped overboard and swam ashore in the dusk, landing fifty yards
+downstream, out of danger of possible stragglers.
+
+He flew along unfrequented alleys, and shortly found himself at his
+aunt's back fence. He climbed over, approached the "ell," and looked in
+at the sitting-room window, for a light was burning there. There sat
+Aunt Polly, Sid, Mary, and Joe Harper's mother, grouped together,
+talking. They were by the bed, and the bed was between them and the
+door. Tom went to the door and began to softly lift the latch; then he
+pressed gently and the door yielded a crack; he continued pushing
+cautiously, and quaking every time it creaked, till he judged he might
+squeeze through on his knees; so he put his head through and began,
+warily.
+
+"What makes the candle blow so?" said Aunt Polly. Tom hurried up.
+"Why, that door's open, I believe. Why, of course it is. No end of
+strange things now. Go 'long and shut it, Sid."
+
+Tom disappeared under the bed just in time. He lay and "breathed"
+himself for a time, and then crept to where he could almost touch his
+aunt's foot.
+
+"But as I was saying," said Aunt Polly, "he warn't BAD, so to say
+--only mischEEvous. Only just giddy, and harum-scarum, you know. He
+warn't any more responsible than a colt. HE never meant any harm, and
+he was the best-hearted boy that ever was"--and she began to cry.
+
+"It was just so with my Joe--always full of his devilment, and up to
+every kind of mischief, but he was just as unselfish and kind as he
+could be--and laws bless me, to think I went and whipped him for taking
+that cream, never once recollecting that I throwed it out myself
+because it was sour, and I never to see him again in this world, never,
+never, never, poor abused boy!" And Mrs. Harper sobbed as if her heart
+would break.
+
+"I hope Tom's better off where he is," said Sid, "but if he'd been
+better in some ways--"
+
+"SID!" Tom felt the glare of the old lady's eye, though he could not
+see it. "Not a word against my Tom, now that he's gone! God'll take
+care of HIM--never you trouble YOURself, sir! Oh, Mrs. Harper, I don't
+know how to give him up! I don't know how to give him up! He was such a
+comfort to me, although he tormented my old heart out of me, 'most."
+
+"The Lord giveth and the Lord hath taken away--Blessed be the name of
+the Lord! But it's so hard--Oh, it's so hard! Only last Saturday my
+Joe busted a firecracker right under my nose and I knocked him
+sprawling. Little did I know then, how soon--Oh, if it was to do over
+again I'd hug him and bless him for it."
+
+"Yes, yes, yes, I know just how you feel, Mrs. Harper, I know just
+exactly how you feel. No longer ago than yesterday noon, my Tom took
+and filled the cat full of Pain-killer, and I did think the cretur
+would tear the house down. And God forgive me, I cracked Tom's head
+with my thimble, poor boy, poor dead boy. But he's out of all his
+troubles now. And the last words I ever heard him say was to reproach--"
+
+But this memory was too much for the old lady, and she broke entirely
+down. Tom was snuffling, now, himself--and more in pity of himself than
+anybody else. He could hear Mary crying, and putting in a kindly word
+for him from time to time. He began to have a nobler opinion of himself
+than ever before. Still, he was sufficiently touched by his aunt's
+grief to long to rush out from under the bed and overwhelm her with
+joy--and the theatrical gorgeousness of the thing appealed strongly to
+his nature, too, but he resisted and lay still.
+
+He went on listening, and gathered by odds and ends that it was
+conjectured at first that the boys had got drowned while taking a swim;
+then the small raft had been missed; next, certain boys said the
+missing lads had promised that the village should "hear something"
+soon; the wise-heads had "put this and that together" and decided that
+the lads had gone off on that raft and would turn up at the next town
+below, presently; but toward noon the raft had been found, lodged
+against the Missouri shore some five or six miles below the village
+--and then hope perished; they must be drowned, else hunger would have
+driven them home by nightfall if not sooner. It was believed that the
+search for the bodies had been a fruitless effort merely because the
+drowning must have occurred in mid-channel, since the boys, being good
+swimmers, would otherwise have escaped to shore. This was Wednesday
+night. If the bodies continued missing until Sunday, all hope would be
+given over, and the funerals would be preached on that morning. Tom
+shuddered.
+
+Mrs. Harper gave a sobbing good-night and turned to go. Then with a
+mutual impulse the two bereaved women flung themselves into each
+other's arms and had a good, consoling cry, and then parted. Aunt Polly
+was tender far beyond her wont, in her good-night to Sid and Mary. Sid
+snuffled a bit and Mary went off crying with all her heart.
+
+Aunt Polly knelt down and prayed for Tom so touchingly, so
+appealingly, and with such measureless love in her words and her old
+trembling voice, that he was weltering in tears again, long before she
+was through.
+
+He had to keep still long after she went to bed, for she kept making
+broken-hearted ejaculations from time to time, tossing unrestfully, and
+turning over. But at last she was still, only moaning a little in her
+sleep. Now the boy stole out, rose gradually by the bedside, shaded the
+candle-light with his hand, and stood regarding her. His heart was full
+of pity for her. He took out his sycamore scroll and placed it by the
+candle. But something occurred to him, and he lingered considering. His
+face lighted with a happy solution of his thought; he put the bark
+hastily in his pocket. Then he bent over and kissed the faded lips, and
+straightway made his stealthy exit, latching the door behind him.
+
+He threaded his way back to the ferry landing, found nobody at large
+there, and walked boldly on board the boat, for he knew she was
+tenantless except that there was a watchman, who always turned in and
+slept like a graven image. He untied the skiff at the stern, slipped
+into it, and was soon rowing cautiously upstream. When he had pulled a
+mile above the village, he started quartering across and bent himself
+stoutly to his work. He hit the landing on the other side neatly, for
+this was a familiar bit of work to him. He was moved to capture the
+skiff, arguing that it might be considered a ship and therefore
+legitimate prey for a pirate, but he knew a thorough search would be
+made for it and that might end in revelations. So he stepped ashore and
+entered the woods.
+
+He sat down and took a long rest, torturing himself meanwhile to keep
+awake, and then started warily down the home-stretch. The night was far
+spent. It was broad daylight before he found himself fairly abreast the
+island bar. He rested again until the sun was well up and gilding the
+great river with its splendor, and then he plunged into the stream. A
+little later he paused, dripping, upon the threshold of the camp, and
+heard Joe say:
+
+"No, Tom's true-blue, Huck, and he'll come back. He won't desert. He
+knows that would be a disgrace to a pirate, and Tom's too proud for
+that sort of thing. He's up to something or other. Now I wonder what?"
+
+"Well, the things is ours, anyway, ain't they?"
+
+"Pretty near, but not yet, Huck. The writing says they are if he ain't
+back here to breakfast."
+
+"Which he is!" exclaimed Tom, with fine dramatic effect, stepping
+grandly into camp.
+
+A sumptuous breakfast of bacon and fish was shortly provided, and as
+the boys set to work upon it, Tom recounted (and adorned) his
+adventures. They were a vain and boastful company of heroes when the
+tale was done. Then Tom hid himself away in a shady nook to sleep till
+noon, and the other pirates got ready to fish and explore.
+
+
+
+CHAPTER XVI
+
+AFTER dinner all the gang turned out to hunt for turtle eggs on the
+bar. They went about poking sticks into the sand, and when they found a
+soft place they went down on their knees and dug with their hands.
+Sometimes they would take fifty or sixty eggs out of one hole. They
+were perfectly round white things a trifle smaller than an English
+walnut. They had a famous fried-egg feast that night, and another on
+Friday morning.
+
+After breakfast they went whooping and prancing out on the bar, and
+chased each other round and round, shedding clothes as they went, until
+they were naked, and then continued the frolic far away up the shoal
+water of the bar, against the stiff current, which latter tripped their
+legs from under them from time to time and greatly increased the fun.
+And now and then they stooped in a group and splashed water in each
+other's faces with their palms, gradually approaching each other, with
+averted faces to avoid the strangling sprays, and finally gripping and
+struggling till the best man ducked his neighbor, and then they all
+went under in a tangle of white legs and arms and came up blowing,
+sputtering, laughing, and gasping for breath at one and the same time.
+
+When they were well exhausted, they would run out and sprawl on the
+dry, hot sand, and lie there and cover themselves up with it, and by
+and by break for the water again and go through the original
+performance once more. Finally it occurred to them that their naked
+skin represented flesh-colored "tights" very fairly; so they drew a
+ring in the sand and had a circus--with three clowns in it, for none
+would yield this proudest post to his neighbor.
+
+Next they got their marbles and played "knucks" and "ring-taw" and
+"keeps" till that amusement grew stale. Then Joe and Huck had another
+swim, but Tom would not venture, because he found that in kicking off
+his trousers he had kicked his string of rattlesnake rattles off his
+ankle, and he wondered how he had escaped cramp so long without the
+protection of this mysterious charm. He did not venture again until he
+had found it, and by that time the other boys were tired and ready to
+rest. They gradually wandered apart, dropped into the "dumps," and fell
+to gazing longingly across the wide river to where the village lay
+drowsing in the sun. Tom found himself writing "BECKY" in the sand with
+his big toe; he scratched it out, and was angry with himself for his
+weakness. But he wrote it again, nevertheless; he could not help it. He
+erased it once more and then took himself out of temptation by driving
+the other boys together and joining them.
+
+But Joe's spirits had gone down almost beyond resurrection. He was so
+homesick that he could hardly endure the misery of it. The tears lay
+very near the surface. Huck was melancholy, too. Tom was downhearted,
+but tried hard not to show it. He had a secret which he was not ready
+to tell, yet, but if this mutinous depression was not broken up soon,
+he would have to bring it out. He said, with a great show of
+cheerfulness:
+
+"I bet there's been pirates on this island before, boys. We'll explore
+it again. They've hid treasures here somewhere. How'd you feel to light
+on a rotten chest full of gold and silver--hey?"
+
+But it roused only faint enthusiasm, which faded out, with no reply.
+Tom tried one or two other seductions; but they failed, too. It was
+discouraging work. Joe sat poking up the sand with a stick and looking
+very gloomy. Finally he said:
+
+"Oh, boys, let's give it up. I want to go home. It's so lonesome."
+
+"Oh no, Joe, you'll feel better by and by," said Tom. "Just think of
+the fishing that's here."
+
+"I don't care for fishing. I want to go home."
+
+"But, Joe, there ain't such another swimming-place anywhere."
+
+"Swimming's no good. I don't seem to care for it, somehow, when there
+ain't anybody to say I sha'n't go in. I mean to go home."
+
+"Oh, shucks! Baby! You want to see your mother, I reckon."
+
+"Yes, I DO want to see my mother--and you would, too, if you had one.
+I ain't any more baby than you are." And Joe snuffled a little.
+
+"Well, we'll let the cry-baby go home to his mother, won't we, Huck?
+Poor thing--does it want to see its mother? And so it shall. You like
+it here, don't you, Huck? We'll stay, won't we?"
+
+Huck said, "Y-e-s"--without any heart in it.
+
+"I'll never speak to you again as long as I live," said Joe, rising.
+"There now!" And he moved moodily away and began to dress himself.
+
+"Who cares!" said Tom. "Nobody wants you to. Go 'long home and get
+laughed at. Oh, you're a nice pirate. Huck and me ain't cry-babies.
+We'll stay, won't we, Huck? Let him go if he wants to. I reckon we can
+get along without him, per'aps."
+
+But Tom was uneasy, nevertheless, and was alarmed to see Joe go
+sullenly on with his dressing. And then it was discomforting to see
+Huck eying Joe's preparations so wistfully, and keeping up such an
+ominous silence. Presently, without a parting word, Joe began to wade
+off toward the Illinois shore. Tom's heart began to sink. He glanced at
+Huck. Huck could not bear the look, and dropped his eyes. Then he said:
+
+"I want to go, too, Tom. It was getting so lonesome anyway, and now
+it'll be worse. Let's us go, too, Tom."
+
+"I won't! You can all go, if you want to. I mean to stay."
+
+"Tom, I better go."
+
+"Well, go 'long--who's hendering you."
+
+Huck began to pick up his scattered clothes. He said:
+
+"Tom, I wisht you'd come, too. Now you think it over. We'll wait for
+you when we get to shore."
+
+"Well, you'll wait a blame long time, that's all."
+
+Huck started sorrowfully away, and Tom stood looking after him, with a
+strong desire tugging at his heart to yield his pride and go along too.
+He hoped the boys would stop, but they still waded slowly on. It
+suddenly dawned on Tom that it was become very lonely and still. He
+made one final struggle with his pride, and then darted after his
+comrades, yelling:
+
+"Wait! Wait! I want to tell you something!"
+
+They presently stopped and turned around. When he got to where they
+were, he began unfolding his secret, and they listened moodily till at
+last they saw the "point" he was driving at, and then they set up a
+war-whoop of applause and said it was "splendid!" and said if he had
+told them at first, they wouldn't have started away. He made a plausible
+excuse; but his real reason had been the fear that not even the secret
+would keep them with him any very great length of time, and so he had
+meant to hold it in reserve as a last seduction.
+
+The lads came gayly back and went at their sports again with a will,
+chattering all the time about Tom's stupendous plan and admiring the
+genius of it. After a dainty egg and fish dinner, Tom said he wanted to
+learn to smoke, now. Joe caught at the idea and said he would like to
+try, too. So Huck made pipes and filled them. These novices had never
+smoked anything before but cigars made of grape-vine, and they "bit"
+the tongue, and were not considered manly anyway.
+
+Now they stretched themselves out on their elbows and began to puff,
+charily, and with slender confidence. The smoke had an unpleasant
+taste, and they gagged a little, but Tom said:
+
+"Why, it's just as easy! If I'd a knowed this was all, I'd a learnt
+long ago."
+
+"So would I," said Joe. "It's just nothing."
+
+"Why, many a time I've looked at people smoking, and thought well I
+wish I could do that; but I never thought I could," said Tom.
+
+"That's just the way with me, hain't it, Huck? You've heard me talk
+just that way--haven't you, Huck? I'll leave it to Huck if I haven't."
+
+"Yes--heaps of times," said Huck.
+
+"Well, I have too," said Tom; "oh, hundreds of times. Once down by the
+slaughter-house. Don't you remember, Huck? Bob Tanner was there, and
+Johnny Miller, and Jeff Thatcher, when I said it. Don't you remember,
+Huck, 'bout me saying that?"
+
+"Yes, that's so," said Huck. "That was the day after I lost a white
+alley. No, 'twas the day before."
+
+"There--I told you so," said Tom. "Huck recollects it."
+
+"I bleeve I could smoke this pipe all day," said Joe. "I don't feel
+sick."
+
+"Neither do I," said Tom. "I could smoke it all day. But I bet you
+Jeff Thatcher couldn't."
+
+"Jeff Thatcher! Why, he'd keel over just with two draws. Just let him
+try it once. HE'D see!"
+
+"I bet he would. And Johnny Miller--I wish could see Johnny Miller
+tackle it once."
+
+"Oh, don't I!" said Joe. "Why, I bet you Johnny Miller couldn't any
+more do this than nothing. Just one little snifter would fetch HIM."
+
+"'Deed it would, Joe. Say--I wish the boys could see us now."
+
+"So do I."
+
+"Say--boys, don't say anything about it, and some time when they're
+around, I'll come up to you and say, 'Joe, got a pipe? I want a smoke.'
+And you'll say, kind of careless like, as if it warn't anything, you'll
+say, 'Yes, I got my OLD pipe, and another one, but my tobacker ain't
+very good.' And I'll say, 'Oh, that's all right, if it's STRONG
+enough.' And then you'll out with the pipes, and we'll light up just as
+ca'm, and then just see 'em look!"
+
+"By jings, that'll be gay, Tom! I wish it was NOW!"
+
+"So do I! And when we tell 'em we learned when we was off pirating,
+won't they wish they'd been along?"
+
+"Oh, I reckon not! I'll just BET they will!"
+
+So the talk ran on. But presently it began to flag a trifle, and grow
+disjointed. The silences widened; the expectoration marvellously
+increased. Every pore inside the boys' cheeks became a spouting
+fountain; they could scarcely bail out the cellars under their tongues
+fast enough to prevent an inundation; little overflowings down their
+throats occurred in spite of all they could do, and sudden retchings
+followed every time. Both boys were looking very pale and miserable,
+now. Joe's pipe dropped from his nerveless fingers. Tom's followed.
+Both fountains were going furiously and both pumps bailing with might
+and main. Joe said feebly:
+
+"I've lost my knife. I reckon I better go and find it."
+
+Tom said, with quivering lips and halting utterance:
+
+"I'll help you. You go over that way and I'll hunt around by the
+spring. No, you needn't come, Huck--we can find it."
+
+So Huck sat down again, and waited an hour. Then he found it lonesome,
+and went to find his comrades. They were wide apart in the woods, both
+very pale, both fast asleep. But something informed him that if they
+had had any trouble they had got rid of it.
+
+They were not talkative at supper that night. They had a humble look,
+and when Huck prepared his pipe after the meal and was going to prepare
+theirs, they said no, they were not feeling very well--something they
+ate at dinner had disagreed with them.
+
+About midnight Joe awoke, and called the boys. There was a brooding
+oppressiveness in the air that seemed to bode something. The boys
+huddled themselves together and sought the friendly companionship of
+the fire, though the dull dead heat of the breathless atmosphere was
+stifling. They sat still, intent and waiting. The solemn hush
+continued. Beyond the light of the fire everything was swallowed up in
+the blackness of darkness. Presently there came a quivering glow that
+vaguely revealed the foliage for a moment and then vanished. By and by
+another came, a little stronger. Then another. Then a faint moan came
+sighing through the branches of the forest and the boys felt a fleeting
+breath upon their cheeks, and shuddered with the fancy that the Spirit
+of the Night had gone by. There was a pause. Now a weird flash turned
+night into day and showed every little grass-blade, separate and
+distinct, that grew about their feet. And it showed three white,
+startled faces, too. A deep peal of thunder went rolling and tumbling
+down the heavens and lost itself in sullen rumblings in the distance. A
+sweep of chilly air passed by, rustling all the leaves and snowing the
+flaky ashes broadcast about the fire. Another fierce glare lit up the
+forest and an instant crash followed that seemed to rend the tree-tops
+right over the boys' heads. They clung together in terror, in the thick
+gloom that followed. A few big rain-drops fell pattering upon the
+leaves.
+
+"Quick! boys, go for the tent!" exclaimed Tom.
+
+They sprang away, stumbling over roots and among vines in the dark, no
+two plunging in the same direction. A furious blast roared through the
+trees, making everything sing as it went. One blinding flash after
+another came, and peal on peal of deafening thunder. And now a
+drenching rain poured down and the rising hurricane drove it in sheets
+along the ground. The boys cried out to each other, but the roaring
+wind and the booming thunder-blasts drowned their voices utterly.
+However, one by one they straggled in at last and took shelter under
+the tent, cold, scared, and streaming with water; but to have company
+in misery seemed something to be grateful for. They could not talk, the
+old sail flapped so furiously, even if the other noises would have
+allowed them. The tempest rose higher and higher, and presently the
+sail tore loose from its fastenings and went winging away on the blast.
+The boys seized each others' hands and fled, with many tumblings and
+bruises, to the shelter of a great oak that stood upon the river-bank.
+Now the battle was at its highest. Under the ceaseless conflagration of
+lightning that flamed in the skies, everything below stood out in
+clean-cut and shadowless distinctness: the bending trees, the billowy
+river, white with foam, the driving spray of spume-flakes, the dim
+outlines of the high bluffs on the other side, glimpsed through the
+drifting cloud-rack and the slanting veil of rain. Every little while
+some giant tree yielded the fight and fell crashing through the younger
+growth; and the unflagging thunder-peals came now in ear-splitting
+explosive bursts, keen and sharp, and unspeakably appalling. The storm
+culminated in one matchless effort that seemed likely to tear the island
+to pieces, burn it up, drown it to the tree-tops, blow it away, and
+deafen every creature in it, all at one and the same moment. It was a
+wild night for homeless young heads to be out in.
+
+But at last the battle was done, and the forces retired with weaker
+and weaker threatenings and grumblings, and peace resumed her sway. The
+boys went back to camp, a good deal awed; but they found there was
+still something to be thankful for, because the great sycamore, the
+shelter of their beds, was a ruin, now, blasted by the lightnings, and
+they were not under it when the catastrophe happened.
+
+Everything in camp was drenched, the camp-fire as well; for they were
+but heedless lads, like their generation, and had made no provision
+against rain. Here was matter for dismay, for they were soaked through
+and chilled. They were eloquent in their distress; but they presently
+discovered that the fire had eaten so far up under the great log it had
+been built against (where it curved upward and separated itself from
+the ground), that a handbreadth or so of it had escaped wetting; so
+they patiently wrought until, with shreds and bark gathered from the
+under sides of sheltered logs, they coaxed the fire to burn again. Then
+they piled on great dead boughs till they had a roaring furnace, and
+were glad-hearted once more. They dried their boiled ham and had a
+feast, and after that they sat by the fire and expanded and glorified
+their midnight adventure until morning, for there was not a dry spot to
+sleep on, anywhere around.
+
+As the sun began to steal in upon the boys, drowsiness came over them,
+and they went out on the sandbar and lay down to sleep. They got
+scorched out by and by, and drearily set about getting breakfast. After
+the meal they felt rusty, and stiff-jointed, and a little homesick once
+more. Tom saw the signs, and fell to cheering up the pirates as well as
+he could. But they cared nothing for marbles, or circus, or swimming,
+or anything. He reminded them of the imposing secret, and raised a ray
+of cheer. While it lasted, he got them interested in a new device. This
+was to knock off being pirates, for a while, and be Indians for a
+change. They were attracted by this idea; so it was not long before
+they were stripped, and striped from head to heel with black mud, like
+so many zebras--all of them chiefs, of course--and then they went
+tearing through the woods to attack an English settlement.
+
+By and by they separated into three hostile tribes, and darted upon
+each other from ambush with dreadful war-whoops, and killed and scalped
+each other by thousands. It was a gory day. Consequently it was an
+extremely satisfactory one.
+
+They assembled in camp toward supper-time, hungry and happy; but now a
+difficulty arose--hostile Indians could not break the bread of
+hospitality together without first making peace, and this was a simple
+impossibility without smoking a pipe of peace. There was no other
+process that ever they had heard of. Two of the savages almost wished
+they had remained pirates. However, there was no other way; so with
+such show of cheerfulness as they could muster they called for the pipe
+and took their whiff as it passed, in due form.
+
+And behold, they were glad they had gone into savagery, for they had
+gained something; they found that they could now smoke a little without
+having to go and hunt for a lost knife; they did not get sick enough to
+be seriously uncomfortable. They were not likely to fool away this high
+promise for lack of effort. No, they practised cautiously, after
+supper, with right fair success, and so they spent a jubilant evening.
+They were prouder and happier in their new acquirement than they would
+have been in the scalping and skinning of the Six Nations. We will
+leave them to smoke and chatter and brag, since we have no further use
+for them at present.
+
+
+
+CHAPTER XVII
+
+BUT there was no hilarity in the little town that same tranquil
+Saturday afternoon. The Harpers, and Aunt Polly's family, were being
+put into mourning, with great grief and many tears. An unusual quiet
+possessed the village, although it was ordinarily quiet enough, in all
+conscience. The villagers conducted their concerns with an absent air,
+and talked little; but they sighed often. The Saturday holiday seemed a
+burden to the children. They had no heart in their sports, and
+gradually gave them up.
+
+In the afternoon Becky Thatcher found herself moping about the
+deserted schoolhouse yard, and feeling very melancholy. But she found
+nothing there to comfort her. She soliloquized:
+
+"Oh, if I only had a brass andiron-knob again! But I haven't got
+anything now to remember him by." And she choked back a little sob.
+
+Presently she stopped, and said to herself:
+
+"It was right here. Oh, if it was to do over again, I wouldn't say
+that--I wouldn't say it for the whole world. But he's gone now; I'll
+never, never, never see him any more."
+
+This thought broke her down, and she wandered away, with tears rolling
+down her cheeks. Then quite a group of boys and girls--playmates of
+Tom's and Joe's--came by, and stood looking over the paling fence and
+talking in reverent tones of how Tom did so-and-so the last time they
+saw him, and how Joe said this and that small trifle (pregnant with
+awful prophecy, as they could easily see now!)--and each speaker
+pointed out the exact spot where the lost lads stood at the time, and
+then added something like "and I was a-standing just so--just as I am
+now, and as if you was him--I was as close as that--and he smiled, just
+this way--and then something seemed to go all over me, like--awful, you
+know--and I never thought what it meant, of course, but I can see now!"
+
+Then there was a dispute about who saw the dead boys last in life, and
+many claimed that dismal distinction, and offered evidences, more or
+less tampered with by the witness; and when it was ultimately decided
+who DID see the departed last, and exchanged the last words with them,
+the lucky parties took upon themselves a sort of sacred importance, and
+were gaped at and envied by all the rest. One poor chap, who had no
+other grandeur to offer, said with tolerably manifest pride in the
+remembrance:
+
+"Well, Tom Sawyer he licked me once."
+
+But that bid for glory was a failure. Most of the boys could say that,
+and so that cheapened the distinction too much. The group loitered
+away, still recalling memories of the lost heroes, in awed voices.
+
+When the Sunday-school hour was finished, the next morning, the bell
+began to toll, instead of ringing in the usual way. It was a very still
+Sabbath, and the mournful sound seemed in keeping with the musing hush
+that lay upon nature. The villagers began to gather, loitering a moment
+in the vestibule to converse in whispers about the sad event. But there
+was no whispering in the house; only the funereal rustling of dresses
+as the women gathered to their seats disturbed the silence there. None
+could remember when the little church had been so full before. There
+was finally a waiting pause, an expectant dumbness, and then Aunt Polly
+entered, followed by Sid and Mary, and they by the Harper family, all
+in deep black, and the whole congregation, the old minister as well,
+rose reverently and stood until the mourners were seated in the front
+pew. There was another communing silence, broken at intervals by
+muffled sobs, and then the minister spread his hands abroad and prayed.
+A moving hymn was sung, and the text followed: "I am the Resurrection
+and the Life."
+
+As the service proceeded, the clergyman drew such pictures of the
+graces, the winning ways, and the rare promise of the lost lads that
+every soul there, thinking he recognized these pictures, felt a pang in
+remembering that he had persistently blinded himself to them always
+before, and had as persistently seen only faults and flaws in the poor
+boys. The minister related many a touching incident in the lives of the
+departed, too, which illustrated their sweet, generous natures, and the
+people could easily see, now, how noble and beautiful those episodes
+were, and remembered with grief that at the time they occurred they had
+seemed rank rascalities, well deserving of the cowhide. The
+congregation became more and more moved, as the pathetic tale went on,
+till at last the whole company broke down and joined the weeping
+mourners in a chorus of anguished sobs, the preacher himself giving way
+to his feelings, and crying in the pulpit.
+
+There was a rustle in the gallery, which nobody noticed; a moment
+later the church door creaked; the minister raised his streaming eyes
+above his handkerchief, and stood transfixed! First one and then
+another pair of eyes followed the minister's, and then almost with one
+impulse the congregation rose and stared while the three dead boys came
+marching up the aisle, Tom in the lead, Joe next, and Huck, a ruin of
+drooping rags, sneaking sheepishly in the rear! They had been hid in
+the unused gallery listening to their own funeral sermon!
+
+Aunt Polly, Mary, and the Harpers threw themselves upon their restored
+ones, smothered them with kisses and poured out thanksgivings, while
+poor Huck stood abashed and uncomfortable, not knowing exactly what to
+do or where to hide from so many unwelcoming eyes. He wavered, and
+started to slink away, but Tom seized him and said:
+
+"Aunt Polly, it ain't fair. Somebody's got to be glad to see Huck."
+
+"And so they shall. I'm glad to see him, poor motherless thing!" And
+the loving attentions Aunt Polly lavished upon him were the one thing
+capable of making him more uncomfortable than he was before.
+
+Suddenly the minister shouted at the top of his voice: "Praise God
+from whom all blessings flow--SING!--and put your hearts in it!"
+
+And they did. Old Hundred swelled up with a triumphant burst, and
+while it shook the rafters Tom Sawyer the Pirate looked around upon the
+envying juveniles about him and confessed in his heart that this was
+the proudest moment of his life.
+
+As the "sold" congregation trooped out they said they would almost be
+willing to be made ridiculous again to hear Old Hundred sung like that
+once more.
+
+Tom got more cuffs and kisses that day--according to Aunt Polly's
+varying moods--than he had earned before in a year; and he hardly knew
+which expressed the most gratefulness to God and affection for himself.
+
+
+
+CHAPTER XVIII
+
+THAT was Tom's great secret--the scheme to return home with his
+brother pirates and attend their own funerals. They had paddled over to
+the Missouri shore on a log, at dusk on Saturday, landing five or six
+miles below the village; they had slept in the woods at the edge of the
+town till nearly daylight, and had then crept through back lanes and
+alleys and finished their sleep in the gallery of the church among a
+chaos of invalided benches.
+
+At breakfast, Monday morning, Aunt Polly and Mary were very loving to
+Tom, and very attentive to his wants. There was an unusual amount of
+talk. In the course of it Aunt Polly said:
+
+"Well, I don't say it wasn't a fine joke, Tom, to keep everybody
+suffering 'most a week so you boys had a good time, but it is a pity
+you could be so hard-hearted as to let me suffer so. If you could come
+over on a log to go to your funeral, you could have come over and give
+me a hint some way that you warn't dead, but only run off."
+
+"Yes, you could have done that, Tom," said Mary; "and I believe you
+would if you had thought of it."
+
+"Would you, Tom?" said Aunt Polly, her face lighting wistfully. "Say,
+now, would you, if you'd thought of it?"
+
+"I--well, I don't know. 'Twould 'a' spoiled everything."
+
+"Tom, I hoped you loved me that much," said Aunt Polly, with a grieved
+tone that discomforted the boy. "It would have been something if you'd
+cared enough to THINK of it, even if you didn't DO it."
+
+"Now, auntie, that ain't any harm," pleaded Mary; "it's only Tom's
+giddy way--he is always in such a rush that he never thinks of
+anything."
+
+"More's the pity. Sid would have thought. And Sid would have come and
+DONE it, too. Tom, you'll look back, some day, when it's too late, and
+wish you'd cared a little more for me when it would have cost you so
+little."
+
+"Now, auntie, you know I do care for you," said Tom.
+
+"I'd know it better if you acted more like it."
+
+"I wish now I'd thought," said Tom, with a repentant tone; "but I
+dreamt about you, anyway. That's something, ain't it?"
+
+"It ain't much--a cat does that much--but it's better than nothing.
+What did you dream?"
+
+"Why, Wednesday night I dreamt that you was sitting over there by the
+bed, and Sid was sitting by the woodbox, and Mary next to him."
+
+"Well, so we did. So we always do. I'm glad your dreams could take
+even that much trouble about us."
+
+"And I dreamt that Joe Harper's mother was here."
+
+"Why, she was here! Did you dream any more?"
+
+"Oh, lots. But it's so dim, now."
+
+"Well, try to recollect--can't you?"
+
+"Somehow it seems to me that the wind--the wind blowed the--the--"
+
+"Try harder, Tom! The wind did blow something. Come!"
+
+Tom pressed his fingers on his forehead an anxious minute, and then
+said:
+
+"I've got it now! I've got it now! It blowed the candle!"
+
+"Mercy on us! Go on, Tom--go on!"
+
+"And it seems to me that you said, 'Why, I believe that that door--'"
+
+"Go ON, Tom!"
+
+"Just let me study a moment--just a moment. Oh, yes--you said you
+believed the door was open."
+
+"As I'm sitting here, I did! Didn't I, Mary! Go on!"
+
+"And then--and then--well I won't be certain, but it seems like as if
+you made Sid go and--and--"
+
+"Well? Well? What did I make him do, Tom? What did I make him do?"
+
+"You made him--you--Oh, you made him shut it."
+
+"Well, for the land's sake! I never heard the beat of that in all my
+days! Don't tell ME there ain't anything in dreams, any more. Sereny
+Harper shall know of this before I'm an hour older. I'd like to see her
+get around THIS with her rubbage 'bout superstition. Go on, Tom!"
+
+"Oh, it's all getting just as bright as day, now. Next you said I
+warn't BAD, only mischeevous and harum-scarum, and not any more
+responsible than--than--I think it was a colt, or something."
+
+"And so it was! Well, goodness gracious! Go on, Tom!"
+
+"And then you began to cry."
+
+"So I did. So I did. Not the first time, neither. And then--"
+
+"Then Mrs. Harper she began to cry, and said Joe was just the same,
+and she wished she hadn't whipped him for taking cream when she'd
+throwed it out her own self--"
+
+"Tom! The sperrit was upon you! You was a prophesying--that's what you
+was doing! Land alive, go on, Tom!"
+
+"Then Sid he said--he said--"
+
+"I don't think I said anything," said Sid.
+
+"Yes you did, Sid," said Mary.
+
+"Shut your heads and let Tom go on! What did he say, Tom?"
+
+"He said--I THINK he said he hoped I was better off where I was gone
+to, but if I'd been better sometimes--"
+
+"THERE, d'you hear that! It was his very words!"
+
+"And you shut him up sharp."
+
+"I lay I did! There must 'a' been an angel there. There WAS an angel
+there, somewheres!"
+
+"And Mrs. Harper told about Joe scaring her with a firecracker, and
+you told about Peter and the Painkiller--"
+
+"Just as true as I live!"
+
+"And then there was a whole lot of talk 'bout dragging the river for
+us, and 'bout having the funeral Sunday, and then you and old Miss
+Harper hugged and cried, and she went."
+
+"It happened just so! It happened just so, as sure as I'm a-sitting in
+these very tracks. Tom, you couldn't told it more like if you'd 'a'
+seen it! And then what? Go on, Tom!"
+
+"Then I thought you prayed for me--and I could see you and hear every
+word you said. And you went to bed, and I was so sorry that I took and
+wrote on a piece of sycamore bark, 'We ain't dead--we are only off
+being pirates,' and put it on the table by the candle; and then you
+looked so good, laying there asleep, that I thought I went and leaned
+over and kissed you on the lips."
+
+"Did you, Tom, DID you! I just forgive you everything for that!" And
+she seized the boy in a crushing embrace that made him feel like the
+guiltiest of villains.
+
+"It was very kind, even though it was only a--dream," Sid soliloquized
+just audibly.
+
+"Shut up, Sid! A body does just the same in a dream as he'd do if he
+was awake. Here's a big Milum apple I've been saving for you, Tom, if
+you was ever found again--now go 'long to school. I'm thankful to the
+good God and Father of us all I've got you back, that's long-suffering
+and merciful to them that believe on Him and keep His word, though
+goodness knows I'm unworthy of it, but if only the worthy ones got His
+blessings and had His hand to help them over the rough places, there's
+few enough would smile here or ever enter into His rest when the long
+night comes. Go 'long Sid, Mary, Tom--take yourselves off--you've
+hendered me long enough."
+
+The children left for school, and the old lady to call on Mrs. Harper
+and vanquish her realism with Tom's marvellous dream. Sid had better
+judgment than to utter the thought that was in his mind as he left the
+house. It was this: "Pretty thin--as long a dream as that, without any
+mistakes in it!"
+
+What a hero Tom was become, now! He did not go skipping and prancing,
+but moved with a dignified swagger as became a pirate who felt that the
+public eye was on him. And indeed it was; he tried not to seem to see
+the looks or hear the remarks as he passed along, but they were food
+and drink to him. Smaller boys than himself flocked at his heels, as
+proud to be seen with him, and tolerated by him, as if he had been the
+drummer at the head of a procession or the elephant leading a menagerie
+into town. Boys of his own size pretended not to know he had been away
+at all; but they were consuming with envy, nevertheless. They would
+have given anything to have that swarthy suntanned skin of his, and his
+glittering notoriety; and Tom would not have parted with either for a
+circus.
+
+At school the children made so much of him and of Joe, and delivered
+such eloquent admiration from their eyes, that the two heroes were not
+long in becoming insufferably "stuck-up." They began to tell their
+adventures to hungry listeners--but they only began; it was not a thing
+likely to have an end, with imaginations like theirs to furnish
+material. And finally, when they got out their pipes and went serenely
+puffing around, the very summit of glory was reached.
+
+Tom decided that he could be independent of Becky Thatcher now. Glory
+was sufficient. He would live for glory. Now that he was distinguished,
+maybe she would be wanting to "make up." Well, let her--she should see
+that he could be as indifferent as some other people. Presently she
+arrived. Tom pretended not to see her. He moved away and joined a group
+of boys and girls and began to talk. Soon he observed that she was
+tripping gayly back and forth with flushed face and dancing eyes,
+pretending to be busy chasing schoolmates, and screaming with laughter
+when she made a capture; but he noticed that she always made her
+captures in his vicinity, and that she seemed to cast a conscious eye
+in his direction at such times, too. It gratified all the vicious
+vanity that was in him; and so, instead of winning him, it only "set
+him up" the more and made him the more diligent to avoid betraying that
+he knew she was about. Presently she gave over skylarking, and moved
+irresolutely about, sighing once or twice and glancing furtively and
+wistfully toward Tom. Then she observed that now Tom was talking more
+particularly to Amy Lawrence than to any one else. She felt a sharp
+pang and grew disturbed and uneasy at once. She tried to go away, but
+her feet were treacherous, and carried her to the group instead. She
+said to a girl almost at Tom's elbow--with sham vivacity:
+
+"Why, Mary Austin! you bad girl, why didn't you come to Sunday-school?"
+
+"I did come--didn't you see me?"
+
+"Why, no! Did you? Where did you sit?"
+
+"I was in Miss Peters' class, where I always go. I saw YOU."
+
+"Did you? Why, it's funny I didn't see you. I wanted to tell you about
+the picnic."
+
+"Oh, that's jolly. Who's going to give it?"
+
+"My ma's going to let me have one."
+
+"Oh, goody; I hope she'll let ME come."
+
+"Well, she will. The picnic's for me. She'll let anybody come that I
+want, and I want you."
+
+"That's ever so nice. When is it going to be?"
+
+"By and by. Maybe about vacation."
+
+"Oh, won't it be fun! You going to have all the girls and boys?"
+
+"Yes, every one that's friends to me--or wants to be"; and she glanced
+ever so furtively at Tom, but he talked right along to Amy Lawrence
+about the terrible storm on the island, and how the lightning tore the
+great sycamore tree "all to flinders" while he was "standing within
+three feet of it."
+
+"Oh, may I come?" said Grace Miller.
+
+"Yes."
+
+"And me?" said Sally Rogers.
+
+"Yes."
+
+"And me, too?" said Susy Harper. "And Joe?"
+
+"Yes."
+
+And so on, with clapping of joyful hands till all the group had begged
+for invitations but Tom and Amy. Then Tom turned coolly away, still
+talking, and took Amy with him. Becky's lips trembled and the tears
+came to her eyes; she hid these signs with a forced gayety and went on
+chattering, but the life had gone out of the picnic, now, and out of
+everything else; she got away as soon as she could and hid herself and
+had what her sex call "a good cry." Then she sat moody, with wounded
+pride, till the bell rang. She roused up, now, with a vindictive cast
+in her eye, and gave her plaited tails a shake and said she knew what
+SHE'D do.
+
+At recess Tom continued his flirtation with Amy with jubilant
+self-satisfaction. And he kept drifting about to find Becky and lacerate
+her with the performance. At last he spied her, but there was a sudden
+falling of his mercury. She was sitting cosily on a little bench behind
+the schoolhouse looking at a picture-book with Alfred Temple--and so
+absorbed were they, and their heads so close together over the book,
+that they did not seem to be conscious of anything in the world besides.
+Jealousy ran red-hot through Tom's veins. He began to hate himself for
+throwing away the chance Becky had offered for a reconciliation. He
+called himself a fool, and all the hard names he could think of. He
+wanted to cry with vexation. Amy chatted happily along, as they walked,
+for her heart was singing, but Tom's tongue had lost its function. He
+did not hear what Amy was saying, and whenever she paused expectantly he
+could only stammer an awkward assent, which was as often misplaced as
+otherwise. He kept drifting to the rear of the schoolhouse, again and
+again, to sear his eyeballs with the hateful spectacle there. He could
+not help it. And it maddened him to see, as he thought he saw, that
+Becky Thatcher never once suspected that he was even in the land of the
+living. But she did see, nevertheless; and she knew she was winning her
+fight, too, and was glad to see him suffer as she had suffered.
+
+Amy's happy prattle became intolerable. Tom hinted at things he had to
+attend to; things that must be done; and time was fleeting. But in
+vain--the girl chirped on. Tom thought, "Oh, hang her, ain't I ever
+going to get rid of her?" At last he must be attending to those
+things--and she said artlessly that she would be "around" when school
+let out. And he hastened away, hating her for it.
+
+"Any other boy!" Tom thought, grating his teeth. "Any boy in the whole
+town but that Saint Louis smarty that thinks he dresses so fine and is
+aristocracy! Oh, all right, I licked you the first day you ever saw
+this town, mister, and I'll lick you again! You just wait till I catch
+you out! I'll just take and--"
+
+And he went through the motions of thrashing an imaginary boy
+--pummelling the air, and kicking and gouging. "Oh, you do, do you? You
+holler 'nough, do you? Now, then, let that learn you!" And so the
+imaginary flogging was finished to his satisfaction.
+
+Tom fled home at noon. His conscience could not endure any more of
+Amy's grateful happiness, and his jealousy could bear no more of the
+other distress. Becky resumed her picture inspections with Alfred, but
+as the minutes dragged along and no Tom came to suffer, her triumph
+began to cloud and she lost interest; gravity and absent-mindedness
+followed, and then melancholy; two or three times she pricked up her
+ear at a footstep, but it was a false hope; no Tom came. At last she
+grew entirely miserable and wished she hadn't carried it so far. When
+poor Alfred, seeing that he was losing her, he did not know how, kept
+exclaiming: "Oh, here's a jolly one! look at this!" she lost patience
+at last, and said, "Oh, don't bother me! I don't care for them!" and
+burst into tears, and got up and walked away.
+
+Alfred dropped alongside and was going to try to comfort her, but she
+said:
+
+"Go away and leave me alone, can't you! I hate you!"
+
+So the boy halted, wondering what he could have done--for she had said
+she would look at pictures all through the nooning--and she walked on,
+crying. Then Alfred went musing into the deserted schoolhouse. He was
+humiliated and angry. He easily guessed his way to the truth--the girl
+had simply made a convenience of him to vent her spite upon Tom Sawyer.
+He was far from hating Tom the less when this thought occurred to him.
+He wished there was some way to get that boy into trouble without much
+risk to himself. Tom's spelling-book fell under his eye. Here was his
+opportunity. He gratefully opened to the lesson for the afternoon and
+poured ink upon the page.
+
+Becky, glancing in at a window behind him at the moment, saw the act,
+and moved on, without discovering herself. She started homeward, now,
+intending to find Tom and tell him; Tom would be thankful and their
+troubles would be healed. Before she was half way home, however, she
+had changed her mind. The thought of Tom's treatment of her when she
+was talking about her picnic came scorching back and filled her with
+shame. She resolved to let him get whipped on the damaged
+spelling-book's account, and to hate him forever, into the bargain.
+
+
+
+CHAPTER XIX
+
+TOM arrived at home in a dreary mood, and the first thing his aunt
+said to him showed him that he had brought his sorrows to an
+unpromising market:
+
+"Tom, I've a notion to skin you alive!"
+
+"Auntie, what have I done?"
+
+"Well, you've done enough. Here I go over to Sereny Harper, like an
+old softy, expecting I'm going to make her believe all that rubbage
+about that dream, when lo and behold you she'd found out from Joe that
+you was over here and heard all the talk we had that night. Tom, I
+don't know what is to become of a boy that will act like that. It makes
+me feel so bad to think you could let me go to Sereny Harper and make
+such a fool of myself and never say a word."
+
+This was a new aspect of the thing. His smartness of the morning had
+seemed to Tom a good joke before, and very ingenious. It merely looked
+mean and shabby now. He hung his head and could not think of anything
+to say for a moment. Then he said:
+
+"Auntie, I wish I hadn't done it--but I didn't think."
+
+"Oh, child, you never think. You never think of anything but your own
+selfishness. You could think to come all the way over here from
+Jackson's Island in the night to laugh at our troubles, and you could
+think to fool me with a lie about a dream; but you couldn't ever think
+to pity us and save us from sorrow."
+
+"Auntie, I know now it was mean, but I didn't mean to be mean. I
+didn't, honest. And besides, I didn't come over here to laugh at you
+that night."
+
+"What did you come for, then?"
+
+"It was to tell you not to be uneasy about us, because we hadn't got
+drownded."
+
+"Tom, Tom, I would be the thankfullest soul in this world if I could
+believe you ever had as good a thought as that, but you know you never
+did--and I know it, Tom."
+
+"Indeed and 'deed I did, auntie--I wish I may never stir if I didn't."
+
+"Oh, Tom, don't lie--don't do it. It only makes things a hundred times
+worse."
+
+"It ain't a lie, auntie; it's the truth. I wanted to keep you from
+grieving--that was all that made me come."
+
+"I'd give the whole world to believe that--it would cover up a power
+of sins, Tom. I'd 'most be glad you'd run off and acted so bad. But it
+ain't reasonable; because, why didn't you tell me, child?"
+
+"Why, you see, when you got to talking about the funeral, I just got
+all full of the idea of our coming and hiding in the church, and I
+couldn't somehow bear to spoil it. So I just put the bark back in my
+pocket and kept mum."
+
+"What bark?"
+
+"The bark I had wrote on to tell you we'd gone pirating. I wish, now,
+you'd waked up when I kissed you--I do, honest."
+
+The hard lines in his aunt's face relaxed and a sudden tenderness
+dawned in her eyes.
+
+"DID you kiss me, Tom?"
+
+"Why, yes, I did."
+
+"Are you sure you did, Tom?"
+
+"Why, yes, I did, auntie--certain sure."
+
+"What did you kiss me for, Tom?"
+
+"Because I loved you so, and you laid there moaning and I was so sorry."
+
+The words sounded like truth. The old lady could not hide a tremor in
+her voice when she said:
+
+"Kiss me again, Tom!--and be off with you to school, now, and don't
+bother me any more."
+
+The moment he was gone, she ran to a closet and got out the ruin of a
+jacket which Tom had gone pirating in. Then she stopped, with it in her
+hand, and said to herself:
+
+"No, I don't dare. Poor boy, I reckon he's lied about it--but it's a
+blessed, blessed lie, there's such a comfort come from it. I hope the
+Lord--I KNOW the Lord will forgive him, because it was such
+goodheartedness in him to tell it. But I don't want to find out it's a
+lie. I won't look."
+
+She put the jacket away, and stood by musing a minute. Twice she put
+out her hand to take the garment again, and twice she refrained. Once
+more she ventured, and this time she fortified herself with the
+thought: "It's a good lie--it's a good lie--I won't let it grieve me."
+So she sought the jacket pocket. A moment later she was reading Tom's
+piece of bark through flowing tears and saying: "I could forgive the
+boy, now, if he'd committed a million sins!"
+
+
+
+CHAPTER XX
+
+THERE was something about Aunt Polly's manner, when she kissed Tom,
+that swept away his low spirits and made him lighthearted and happy
+again. He started to school and had the luck of coming upon Becky
+Thatcher at the head of Meadow Lane. His mood always determined his
+manner. Without a moment's hesitation he ran to her and said:
+
+"I acted mighty mean to-day, Becky, and I'm so sorry. I won't ever,
+ever do that way again, as long as ever I live--please make up, won't
+you?"
+
+The girl stopped and looked him scornfully in the face:
+
+"I'll thank you to keep yourself TO yourself, Mr. Thomas Sawyer. I'll
+never speak to you again."
+
+She tossed her head and passed on. Tom was so stunned that he had not
+even presence of mind enough to say "Who cares, Miss Smarty?" until the
+right time to say it had gone by. So he said nothing. But he was in a
+fine rage, nevertheless. He moped into the schoolyard wishing she were
+a boy, and imagining how he would trounce her if she were. He presently
+encountered her and delivered a stinging remark as he passed. She
+hurled one in return, and the angry breach was complete. It seemed to
+Becky, in her hot resentment, that she could hardly wait for school to
+"take in," she was so impatient to see Tom flogged for the injured
+spelling-book. If she had had any lingering notion of exposing Alfred
+Temple, Tom's offensive fling had driven it entirely away.
+
+Poor girl, she did not know how fast she was nearing trouble herself.
+The master, Mr. Dobbins, had reached middle age with an unsatisfied
+ambition. The darling of his desires was, to be a doctor, but poverty
+had decreed that he should be nothing higher than a village
+schoolmaster. Every day he took a mysterious book out of his desk and
+absorbed himself in it at times when no classes were reciting. He kept
+that book under lock and key. There was not an urchin in school but was
+perishing to have a glimpse of it, but the chance never came. Every boy
+and girl had a theory about the nature of that book; but no two
+theories were alike, and there was no way of getting at the facts in
+the case. Now, as Becky was passing by the desk, which stood near the
+door, she noticed that the key was in the lock! It was a precious
+moment. She glanced around; found herself alone, and the next instant
+she had the book in her hands. The title-page--Professor Somebody's
+ANATOMY--carried no information to her mind; so she began to turn the
+leaves. She came at once upon a handsomely engraved and colored
+frontispiece--a human figure, stark naked. At that moment a shadow fell
+on the page and Tom Sawyer stepped in at the door and caught a glimpse
+of the picture. Becky snatched at the book to close it, and had the
+hard luck to tear the pictured page half down the middle. She thrust
+the volume into the desk, turned the key, and burst out crying with
+shame and vexation.
+
+"Tom Sawyer, you are just as mean as you can be, to sneak up on a
+person and look at what they're looking at."
+
+"How could I know you was looking at anything?"
+
+"You ought to be ashamed of yourself, Tom Sawyer; you know you're
+going to tell on me, and oh, what shall I do, what shall I do! I'll be
+whipped, and I never was whipped in school."
+
+Then she stamped her little foot and said:
+
+"BE so mean if you want to! I know something that's going to happen.
+You just wait and you'll see! Hateful, hateful, hateful!"--and she
+flung out of the house with a new explosion of crying.
+
+Tom stood still, rather flustered by this onslaught. Presently he said
+to himself:
+
+"What a curious kind of a fool a girl is! Never been licked in school!
+Shucks! What's a licking! That's just like a girl--they're so
+thin-skinned and chicken-hearted. Well, of course I ain't going to tell
+old Dobbins on this little fool, because there's other ways of getting
+even on her, that ain't so mean; but what of it? Old Dobbins will ask
+who it was tore his book. Nobody'll answer. Then he'll do just the way
+he always does--ask first one and then t'other, and when he comes to the
+right girl he'll know it, without any telling. Girls' faces always tell
+on them. They ain't got any backbone. She'll get licked. Well, it's a
+kind of a tight place for Becky Thatcher, because there ain't any way
+out of it." Tom conned the thing a moment longer, and then added: "All
+right, though; she'd like to see me in just such a fix--let her sweat it
+out!"
+
+Tom joined the mob of skylarking scholars outside. In a few moments
+the master arrived and school "took in." Tom did not feel a strong
+interest in his studies. Every time he stole a glance at the girls'
+side of the room Becky's face troubled him. Considering all things, he
+did not want to pity her, and yet it was all he could do to help it. He
+could get up no exultation that was really worthy the name. Presently
+the spelling-book discovery was made, and Tom's mind was entirely full
+of his own matters for a while after that. Becky roused up from her
+lethargy of distress and showed good interest in the proceedings. She
+did not expect that Tom could get out of his trouble by denying that he
+spilt the ink on the book himself; and she was right. The denial only
+seemed to make the thing worse for Tom. Becky supposed she would be
+glad of that, and she tried to believe she was glad of it, but she
+found she was not certain. When the worst came to the worst, she had an
+impulse to get up and tell on Alfred Temple, but she made an effort and
+forced herself to keep still--because, said she to herself, "he'll tell
+about me tearing the picture sure. I wouldn't say a word, not to save
+his life!"
+
+Tom took his whipping and went back to his seat not at all
+broken-hearted, for he thought it was possible that he had unknowingly
+upset the ink on the spelling-book himself, in some skylarking bout--he
+had denied it for form's sake and because it was custom, and had stuck
+to the denial from principle.
+
+A whole hour drifted by, the master sat nodding in his throne, the air
+was drowsy with the hum of study. By and by, Mr. Dobbins straightened
+himself up, yawned, then unlocked his desk, and reached for his book,
+but seemed undecided whether to take it out or leave it. Most of the
+pupils glanced up languidly, but there were two among them that watched
+his movements with intent eyes. Mr. Dobbins fingered his book absently
+for a while, then took it out and settled himself in his chair to read!
+Tom shot a glance at Becky. He had seen a hunted and helpless rabbit
+look as she did, with a gun levelled at its head. Instantly he forgot
+his quarrel with her. Quick--something must be done! done in a flash,
+too! But the very imminence of the emergency paralyzed his invention.
+Good!--he had an inspiration! He would run and snatch the book, spring
+through the door and fly. But his resolution shook for one little
+instant, and the chance was lost--the master opened the volume. If Tom
+only had the wasted opportunity back again! Too late. There was no help
+for Becky now, he said. The next moment the master faced the school.
+Every eye sank under his gaze. There was that in it which smote even
+the innocent with fear. There was silence while one might count ten
+--the master was gathering his wrath. Then he spoke: "Who tore this book?"
+
+There was not a sound. One could have heard a pin drop. The stillness
+continued; the master searched face after face for signs of guilt.
+
+"Benjamin Rogers, did you tear this book?"
+
+A denial. Another pause.
+
+"Joseph Harper, did you?"
+
+Another denial. Tom's uneasiness grew more and more intense under the
+slow torture of these proceedings. The master scanned the ranks of
+boys--considered a while, then turned to the girls:
+
+"Amy Lawrence?"
+
+A shake of the head.
+
+"Gracie Miller?"
+
+The same sign.
+
+"Susan Harper, did you do this?"
+
+Another negative. The next girl was Becky Thatcher. Tom was trembling
+from head to foot with excitement and a sense of the hopelessness of
+the situation.
+
+"Rebecca Thatcher" [Tom glanced at her face--it was white with terror]
+--"did you tear--no, look me in the face" [her hands rose in appeal]
+--"did you tear this book?"
+
+A thought shot like lightning through Tom's brain. He sprang to his
+feet and shouted--"I done it!"
+
+The school stared in perplexity at this incredible folly. Tom stood a
+moment, to gather his dismembered faculties; and when he stepped
+forward to go to his punishment the surprise, the gratitude, the
+adoration that shone upon him out of poor Becky's eyes seemed pay
+enough for a hundred floggings. Inspired by the splendor of his own
+act, he took without an outcry the most merciless flaying that even Mr.
+Dobbins had ever administered; and also received with indifference the
+added cruelty of a command to remain two hours after school should be
+dismissed--for he knew who would wait for him outside till his
+captivity was done, and not count the tedious time as loss, either.
+
+Tom went to bed that night planning vengeance against Alfred Temple;
+for with shame and repentance Becky had told him all, not forgetting
+her own treachery; but even the longing for vengeance had to give way,
+soon, to pleasanter musings, and he fell asleep at last with Becky's
+latest words lingering dreamily in his ear--
+
+"Tom, how COULD you be so noble!"
+
+
+
+CHAPTER XXI
+
+VACATION was approaching. The schoolmaster, always severe, grew
+severer and more exacting than ever, for he wanted the school to make a
+good showing on "Examination" day. His rod and his ferule were seldom
+idle now--at least among the smaller pupils. Only the biggest boys, and
+young ladies of eighteen and twenty, escaped lashing. Mr. Dobbins'
+lashings were very vigorous ones, too; for although he carried, under
+his wig, a perfectly bald and shiny head, he had only reached middle
+age, and there was no sign of feebleness in his muscle. As the great
+day approached, all the tyranny that was in him came to the surface; he
+seemed to take a vindictive pleasure in punishing the least
+shortcomings. The consequence was, that the smaller boys spent their
+days in terror and suffering and their nights in plotting revenge. They
+threw away no opportunity to do the master a mischief. But he kept
+ahead all the time. The retribution that followed every vengeful
+success was so sweeping and majestic that the boys always retired from
+the field badly worsted. At last they conspired together and hit upon a
+plan that promised a dazzling victory. They swore in the sign-painter's
+boy, told him the scheme, and asked his help. He had his own reasons
+for being delighted, for the master boarded in his father's family and
+had given the boy ample cause to hate him. The master's wife would go
+on a visit to the country in a few days, and there would be nothing to
+interfere with the plan; the master always prepared himself for great
+occasions by getting pretty well fuddled, and the sign-painter's boy
+said that when the dominie had reached the proper condition on
+Examination Evening he would "manage the thing" while he napped in his
+chair; then he would have him awakened at the right time and hurried
+away to school.
+
+In the fulness of time the interesting occasion arrived. At eight in
+the evening the schoolhouse was brilliantly lighted, and adorned with
+wreaths and festoons of foliage and flowers. The master sat throned in
+his great chair upon a raised platform, with his blackboard behind him.
+He was looking tolerably mellow. Three rows of benches on each side and
+six rows in front of him were occupied by the dignitaries of the town
+and by the parents of the pupils. To his left, back of the rows of
+citizens, was a spacious temporary platform upon which were seated the
+scholars who were to take part in the exercises of the evening; rows of
+small boys, washed and dressed to an intolerable state of discomfort;
+rows of gawky big boys; snowbanks of girls and young ladies clad in
+lawn and muslin and conspicuously conscious of their bare arms, their
+grandmothers' ancient trinkets, their bits of pink and blue ribbon and
+the flowers in their hair. All the rest of the house was filled with
+non-participating scholars.
+
+The exercises began. A very little boy stood up and sheepishly
+recited, "You'd scarce expect one of my age to speak in public on the
+stage," etc.--accompanying himself with the painfully exact and
+spasmodic gestures which a machine might have used--supposing the
+machine to be a trifle out of order. But he got through safely, though
+cruelly scared, and got a fine round of applause when he made his
+manufactured bow and retired.
+
+A little shamefaced girl lisped, "Mary had a little lamb," etc.,
+performed a compassion-inspiring curtsy, got her meed of applause, and
+sat down flushed and happy.
+
+Tom Sawyer stepped forward with conceited confidence and soared into
+the unquenchable and indestructible "Give me liberty or give me death"
+speech, with fine fury and frantic gesticulation, and broke down in the
+middle of it. A ghastly stage-fright seized him, his legs quaked under
+him and he was like to choke. True, he had the manifest sympathy of the
+house but he had the house's silence, too, which was even worse than
+its sympathy. The master frowned, and this completed the disaster. Tom
+struggled awhile and then retired, utterly defeated. There was a weak
+attempt at applause, but it died early.
+
+"The Boy Stood on the Burning Deck" followed; also "The Assyrian Came
+Down," and other declamatory gems. Then there were reading exercises,
+and a spelling fight. The meagre Latin class recited with honor. The
+prime feature of the evening was in order, now--original "compositions"
+by the young ladies. Each in her turn stepped forward to the edge of
+the platform, cleared her throat, held up her manuscript (tied with
+dainty ribbon), and proceeded to read, with labored attention to
+"expression" and punctuation. The themes were the same that had been
+illuminated upon similar occasions by their mothers before them, their
+grandmothers, and doubtless all their ancestors in the female line
+clear back to the Crusades. "Friendship" was one; "Memories of Other
+Days"; "Religion in History"; "Dream Land"; "The Advantages of
+Culture"; "Forms of Political Government Compared and Contrasted";
+"Melancholy"; "Filial Love"; "Heart Longings," etc., etc.
+
+A prevalent feature in these compositions was a nursed and petted
+melancholy; another was a wasteful and opulent gush of "fine language";
+another was a tendency to lug in by the ears particularly prized words
+and phrases until they were worn entirely out; and a peculiarity that
+conspicuously marked and marred them was the inveterate and intolerable
+sermon that wagged its crippled tail at the end of each and every one
+of them. No matter what the subject might be, a brain-racking effort
+was made to squirm it into some aspect or other that the moral and
+religious mind could contemplate with edification. The glaring
+insincerity of these sermons was not sufficient to compass the
+banishment of the fashion from the schools, and it is not sufficient
+to-day; it never will be sufficient while the world stands, perhaps.
+There is no school in all our land where the young ladies do not feel
+obliged to close their compositions with a sermon; and you will find
+that the sermon of the most frivolous and the least religious girl in
+the school is always the longest and the most relentlessly pious. But
+enough of this. Homely truth is unpalatable.
+
+Let us return to the "Examination." The first composition that was
+read was one entitled "Is this, then, Life?" Perhaps the reader can
+endure an extract from it:
+
+  "In the common walks of life, with what delightful
+   emotions does the youthful mind look forward to some
+   anticipated scene of festivity! Imagination is busy
+   sketching rose-tinted pictures of joy. In fancy, the
+   voluptuous votary of fashion sees herself amid the
+   festive throng, 'the observed of all observers.' Her
+   graceful form, arrayed in snowy robes, is whirling
+   through the mazes of the joyous dance; her eye is
+   brightest, her step is lightest in the gay assembly.
+
+  "In such delicious fancies time quickly glides by,
+   and the welcome hour arrives for her entrance into
+   the Elysian world, of which she has had such bright
+   dreams. How fairy-like does everything appear to
+   her enchanted vision! Each new scene is more charming
+   than the last. But after a while she finds that
+   beneath this goodly exterior, all is vanity, the
+   flattery which once charmed her soul, now grates
+   harshly upon her ear; the ball-room has lost its
+   charms; and with wasted health and imbittered heart,
+   she turns away with the conviction that earthly
+   pleasures cannot satisfy the longings of the soul!"
+
+And so forth and so on. There was a buzz of gratification from time to
+time during the reading, accompanied by whispered ejaculations of "How
+sweet!" "How eloquent!" "So true!" etc., and after the thing had closed
+with a peculiarly afflicting sermon the applause was enthusiastic.
+
+Then arose a slim, melancholy girl, whose face had the "interesting"
+paleness that comes of pills and indigestion, and read a "poem." Two
+stanzas of it will do:
+
+   "A MISSOURI MAIDEN'S FAREWELL TO ALABAMA
+
+   "Alabama, good-bye! I love thee well!
+      But yet for a while do I leave thee now!
+    Sad, yes, sad thoughts of thee my heart doth swell,
+      And burning recollections throng my brow!
+    For I have wandered through thy flowery woods;
+      Have roamed and read near Tallapoosa's stream;
+    Have listened to Tallassee's warring floods,
+      And wooed on Coosa's side Aurora's beam.
+
+   "Yet shame I not to bear an o'er-full heart,
+      Nor blush to turn behind my tearful eyes;
+    'Tis from no stranger land I now must part,
+      'Tis to no strangers left I yield these sighs.
+    Welcome and home were mine within this State,
+      Whose vales I leave--whose spires fade fast from me
+    And cold must be mine eyes, and heart, and tete,
+      When, dear Alabama! they turn cold on thee!"
+
+There were very few there who knew what "tete" meant, but the poem was
+very satisfactory, nevertheless.
+
+Next appeared a dark-complexioned, black-eyed, black-haired young
+lady, who paused an impressive moment, assumed a tragic expression, and
+began to read in a measured, solemn tone:
+
+  "A VISION
+
+   "Dark and tempestuous was night. Around the
+   throne on high not a single star quivered; but
+   the deep intonations of the heavy thunder
+   constantly vibrated upon the ear; whilst the
+   terrific lightning revelled in angry mood
+   through the cloudy chambers of heaven, seeming
+   to scorn the power exerted over its terror by
+   the illustrious Franklin! Even the boisterous
+   winds unanimously came forth from their mystic
+   homes, and blustered about as if to enhance by
+   their aid the wildness of the scene.
+
+   "At such a time, so dark, so dreary, for human
+   sympathy my very spirit sighed; but instead thereof,
+
+   "'My dearest friend, my counsellor, my comforter
+   and guide--My joy in grief, my second bliss
+   in joy,' came to my side. She moved like one of
+   those bright beings pictured in the sunny walks
+   of fancy's Eden by the romantic and young, a
+   queen of beauty unadorned save by her own
+   transcendent loveliness. So soft was her step, it
+   failed to make even a sound, and but for the
+   magical thrill imparted by her genial touch, as
+   other unobtrusive beauties, she would have glided
+   away un-perceived--unsought. A strange sadness
+   rested upon her features, like icy tears upon
+   the robe of December, as she pointed to the
+   contending elements without, and bade me contemplate
+   the two beings presented."
+
+This nightmare occupied some ten pages of manuscript and wound up with
+a sermon so destructive of all hope to non-Presbyterians that it took
+the first prize. This composition was considered to be the very finest
+effort of the evening. The mayor of the village, in delivering the
+prize to the author of it, made a warm speech in which he said that it
+was by far the most "eloquent" thing he had ever listened to, and that
+Daniel Webster himself might well be proud of it.
+
+It may be remarked, in passing, that the number of compositions in
+which the word "beauteous" was over-fondled, and human experience
+referred to as "life's page," was up to the usual average.
+
+Now the master, mellow almost to the verge of geniality, put his chair
+aside, turned his back to the audience, and began to draw a map of
+America on the blackboard, to exercise the geography class upon. But he
+made a sad business of it with his unsteady hand, and a smothered
+titter rippled over the house. He knew what the matter was, and set
+himself to right it. He sponged out lines and remade them; but he only
+distorted them more than ever, and the tittering was more pronounced.
+He threw his entire attention upon his work, now, as if determined not
+to be put down by the mirth. He felt that all eyes were fastened upon
+him; he imagined he was succeeding, and yet the tittering continued; it
+even manifestly increased. And well it might. There was a garret above,
+pierced with a scuttle over his head; and down through this scuttle
+came a cat, suspended around the haunches by a string; she had a rag
+tied about her head and jaws to keep her from mewing; as she slowly
+descended she curved upward and clawed at the string, she swung
+downward and clawed at the intangible air. The tittering rose higher
+and higher--the cat was within six inches of the absorbed teacher's
+head--down, down, a little lower, and she grabbed his wig with her
+desperate claws, clung to it, and was snatched up into the garret in an
+instant with her trophy still in her possession! And how the light did
+blaze abroad from the master's bald pate--for the sign-painter's boy
+had GILDED it!
+
+That broke up the meeting. The boys were avenged. Vacation had come.
+
+   NOTE:--The pretended "compositions" quoted in
+   this chapter are taken without alteration from a
+   volume entitled "Prose and Poetry, by a Western
+   Lady"--but they are exactly and precisely after
+   the schoolgirl pattern, and hence are much
+   happier than any mere imitations could be.
+
+
+
+CHAPTER XXII
+
+TOM joined the new order of Cadets of Temperance, being attracted by
+the showy character of their "regalia." He promised to abstain from
+smoking, chewing, and profanity as long as he remained a member. Now he
+found out a new thing--namely, that to promise not to do a thing is the
+surest way in the world to make a body want to go and do that very
+thing. Tom soon found himself tormented with a desire to drink and
+swear; the desire grew to be so intense that nothing but the hope of a
+chance to display himself in his red sash kept him from withdrawing
+from the order. Fourth of July was coming; but he soon gave that up
+--gave it up before he had worn his shackles over forty-eight hours--and
+fixed his hopes upon old Judge Frazer, justice of the peace, who was
+apparently on his deathbed and would have a big public funeral, since
+he was so high an official. During three days Tom was deeply concerned
+about the Judge's condition and hungry for news of it. Sometimes his
+hopes ran high--so high that he would venture to get out his regalia
+and practise before the looking-glass. But the Judge had a most
+discouraging way of fluctuating. At last he was pronounced upon the
+mend--and then convalescent. Tom was disgusted; and felt a sense of
+injury, too. He handed in his resignation at once--and that night the
+Judge suffered a relapse and died. Tom resolved that he would never
+trust a man like that again.
+
+The funeral was a fine thing. The Cadets paraded in a style calculated
+to kill the late member with envy. Tom was a free boy again, however
+--there was something in that. He could drink and swear, now--but found
+to his surprise that he did not want to. The simple fact that he could,
+took the desire away, and the charm of it.
+
+Tom presently wondered to find that his coveted vacation was beginning
+to hang a little heavily on his hands.
+
+He attempted a diary--but nothing happened during three days, and so
+he abandoned it.
+
+The first of all the negro minstrel shows came to town, and made a
+sensation. Tom and Joe Harper got up a band of performers and were
+happy for two days.
+
+Even the Glorious Fourth was in some sense a failure, for it rained
+hard, there was no procession in consequence, and the greatest man in
+the world (as Tom supposed), Mr. Benton, an actual United States
+Senator, proved an overwhelming disappointment--for he was not
+twenty-five feet high, nor even anywhere in the neighborhood of it.
+
+A circus came. The boys played circus for three days afterward in
+tents made of rag carpeting--admission, three pins for boys, two for
+girls--and then circusing was abandoned.
+
+A phrenologist and a mesmerizer came--and went again and left the
+village duller and drearier than ever.
+
+There were some boys-and-girls' parties, but they were so few and so
+delightful that they only made the aching voids between ache the harder.
+
+Becky Thatcher was gone to her Constantinople home to stay with her
+parents during vacation--so there was no bright side to life anywhere.
+
+The dreadful secret of the murder was a chronic misery. It was a very
+cancer for permanency and pain.
+
+Then came the measles.
+
+During two long weeks Tom lay a prisoner, dead to the world and its
+happenings. He was very ill, he was interested in nothing. When he got
+upon his feet at last and moved feebly down-town, a melancholy change
+had come over everything and every creature. There had been a
+"revival," and everybody had "got religion," not only the adults, but
+even the boys and girls. Tom went about, hoping against hope for the
+sight of one blessed sinful face, but disappointment crossed him
+everywhere. He found Joe Harper studying a Testament, and turned sadly
+away from the depressing spectacle. He sought Ben Rogers, and found him
+visiting the poor with a basket of tracts. He hunted up Jim Hollis, who
+called his attention to the precious blessing of his late measles as a
+warning. Every boy he encountered added another ton to his depression;
+and when, in desperation, he flew for refuge at last to the bosom of
+Huckleberry Finn and was received with a Scriptural quotation, his
+heart broke and he crept home and to bed realizing that he alone of all
+the town was lost, forever and forever.
+
+And that night there came on a terrific storm, with driving rain,
+awful claps of thunder and blinding sheets of lightning. He covered his
+head with the bedclothes and waited in a horror of suspense for his
+doom; for he had not the shadow of a doubt that all this hubbub was
+about him. He believed he had taxed the forbearance of the powers above
+to the extremity of endurance and that this was the result. It might
+have seemed to him a waste of pomp and ammunition to kill a bug with a
+battery of artillery, but there seemed nothing incongruous about the
+getting up such an expensive thunderstorm as this to knock the turf
+from under an insect like himself.
+
+By and by the tempest spent itself and died without accomplishing its
+object. The boy's first impulse was to be grateful, and reform. His
+second was to wait--for there might not be any more storms.
+
+The next day the doctors were back; Tom had relapsed. The three weeks
+he spent on his back this time seemed an entire age. When he got abroad
+at last he was hardly grateful that he had been spared, remembering how
+lonely was his estate, how companionless and forlorn he was. He drifted
+listlessly down the street and found Jim Hollis acting as judge in a
+juvenile court that was trying a cat for murder, in the presence of her
+victim, a bird. He found Joe Harper and Huck Finn up an alley eating a
+stolen melon. Poor lads! they--like Tom--had suffered a relapse.
+
+
+
+CHAPTER XXIII
+
+AT last the sleepy atmosphere was stirred--and vigorously: the murder
+trial came on in the court. It became the absorbing topic of village
+talk immediately. Tom could not get away from it. Every reference to
+the murder sent a shudder to his heart, for his troubled conscience and
+fears almost persuaded him that these remarks were put forth in his
+hearing as "feelers"; he did not see how he could be suspected of
+knowing anything about the murder, but still he could not be
+comfortable in the midst of this gossip. It kept him in a cold shiver
+all the time. He took Huck to a lonely place to have a talk with him.
+It would be some relief to unseal his tongue for a little while; to
+divide his burden of distress with another sufferer. Moreover, he
+wanted to assure himself that Huck had remained discreet.
+
+"Huck, have you ever told anybody about--that?"
+
+"'Bout what?"
+
+"You know what."
+
+"Oh--'course I haven't."
+
+"Never a word?"
+
+"Never a solitary word, so help me. What makes you ask?"
+
+"Well, I was afeard."
+
+"Why, Tom Sawyer, we wouldn't be alive two days if that got found out.
+YOU know that."
+
+Tom felt more comfortable. After a pause:
+
+"Huck, they couldn't anybody get you to tell, could they?"
+
+"Get me to tell? Why, if I wanted that half-breed devil to drownd me
+they could get me to tell. They ain't no different way."
+
+"Well, that's all right, then. I reckon we're safe as long as we keep
+mum. But let's swear again, anyway. It's more surer."
+
+"I'm agreed."
+
+So they swore again with dread solemnities.
+
+"What is the talk around, Huck? I've heard a power of it."
+
+"Talk? Well, it's just Muff Potter, Muff Potter, Muff Potter all the
+time. It keeps me in a sweat, constant, so's I want to hide som'ers."
+
+"That's just the same way they go on round me. I reckon he's a goner.
+Don't you feel sorry for him, sometimes?"
+
+"Most always--most always. He ain't no account; but then he hain't
+ever done anything to hurt anybody. Just fishes a little, to get money
+to get drunk on--and loafs around considerable; but lord, we all do
+that--leastways most of us--preachers and such like. But he's kind of
+good--he give me half a fish, once, when there warn't enough for two;
+and lots of times he's kind of stood by me when I was out of luck."
+
+"Well, he's mended kites for me, Huck, and knitted hooks on to my
+line. I wish we could get him out of there."
+
+"My! we couldn't get him out, Tom. And besides, 'twouldn't do any
+good; they'd ketch him again."
+
+"Yes--so they would. But I hate to hear 'em abuse him so like the
+dickens when he never done--that."
+
+"I do too, Tom. Lord, I hear 'em say he's the bloodiest looking
+villain in this country, and they wonder he wasn't ever hung before."
+
+"Yes, they talk like that, all the time. I've heard 'em say that if he
+was to get free they'd lynch him."
+
+"And they'd do it, too."
+
+The boys had a long talk, but it brought them little comfort. As the
+twilight drew on, they found themselves hanging about the neighborhood
+of the little isolated jail, perhaps with an undefined hope that
+something would happen that might clear away their difficulties. But
+nothing happened; there seemed to be no angels or fairies interested in
+this luckless captive.
+
+The boys did as they had often done before--went to the cell grating
+and gave Potter some tobacco and matches. He was on the ground floor
+and there were no guards.
+
+His gratitude for their gifts had always smote their consciences
+before--it cut deeper than ever, this time. They felt cowardly and
+treacherous to the last degree when Potter said:
+
+"You've been mighty good to me, boys--better'n anybody else in this
+town. And I don't forget it, I don't. Often I says to myself, says I,
+'I used to mend all the boys' kites and things, and show 'em where the
+good fishin' places was, and befriend 'em what I could, and now they've
+all forgot old Muff when he's in trouble; but Tom don't, and Huck
+don't--THEY don't forget him, says I, 'and I don't forget them.' Well,
+boys, I done an awful thing--drunk and crazy at the time--that's the
+only way I account for it--and now I got to swing for it, and it's
+right. Right, and BEST, too, I reckon--hope so, anyway. Well, we won't
+talk about that. I don't want to make YOU feel bad; you've befriended
+me. But what I want to say, is, don't YOU ever get drunk--then you won't
+ever get here. Stand a litter furder west--so--that's it; it's a prime
+comfort to see faces that's friendly when a body's in such a muck of
+trouble, and there don't none come here but yourn. Good friendly
+faces--good friendly faces. Git up on one another's backs and let me
+touch 'em. That's it. Shake hands--yourn'll come through the bars, but
+mine's too big. Little hands, and weak--but they've helped Muff Potter
+a power, and they'd help him more if they could."
+
+Tom went home miserable, and his dreams that night were full of
+horrors. The next day and the day after, he hung about the court-room,
+drawn by an almost irresistible impulse to go in, but forcing himself
+to stay out. Huck was having the same experience. They studiously
+avoided each other. Each wandered away, from time to time, but the same
+dismal fascination always brought them back presently. Tom kept his
+ears open when idlers sauntered out of the court-room, but invariably
+heard distressing news--the toils were closing more and more
+relentlessly around poor Potter. At the end of the second day the
+village talk was to the effect that Injun Joe's evidence stood firm and
+unshaken, and that there was not the slightest question as to what the
+jury's verdict would be.
+
+Tom was out late, that night, and came to bed through the window. He
+was in a tremendous state of excitement. It was hours before he got to
+sleep. All the village flocked to the court-house the next morning, for
+this was to be the great day. Both sexes were about equally represented
+in the packed audience. After a long wait the jury filed in and took
+their places; shortly afterward, Potter, pale and haggard, timid and
+hopeless, was brought in, with chains upon him, and seated where all
+the curious eyes could stare at him; no less conspicuous was Injun Joe,
+stolid as ever. There was another pause, and then the judge arrived and
+the sheriff proclaimed the opening of the court. The usual whisperings
+among the lawyers and gathering together of papers followed. These
+details and accompanying delays worked up an atmosphere of preparation
+that was as impressive as it was fascinating.
+
+Now a witness was called who testified that he found Muff Potter
+washing in the brook, at an early hour of the morning that the murder
+was discovered, and that he immediately sneaked away. After some
+further questioning, counsel for the prosecution said:
+
+"Take the witness."
+
+The prisoner raised his eyes for a moment, but dropped them again when
+his own counsel said:
+
+"I have no questions to ask him."
+
+The next witness proved the finding of the knife near the corpse.
+Counsel for the prosecution said:
+
+"Take the witness."
+
+"I have no questions to ask him," Potter's lawyer replied.
+
+A third witness swore he had often seen the knife in Potter's
+possession.
+
+"Take the witness."
+
+Counsel for Potter declined to question him. The faces of the audience
+began to betray annoyance. Did this attorney mean to throw away his
+client's life without an effort?
+
+Several witnesses deposed concerning Potter's guilty behavior when
+brought to the scene of the murder. They were allowed to leave the
+stand without being cross-questioned.
+
+Every detail of the damaging circumstances that occurred in the
+graveyard upon that morning which all present remembered so well was
+brought out by credible witnesses, but none of them were cross-examined
+by Potter's lawyer. The perplexity and dissatisfaction of the house
+expressed itself in murmurs and provoked a reproof from the bench.
+Counsel for the prosecution now said:
+
+"By the oaths of citizens whose simple word is above suspicion, we
+have fastened this awful crime, beyond all possibility of question,
+upon the unhappy prisoner at the bar. We rest our case here."
+
+A groan escaped from poor Potter, and he put his face in his hands and
+rocked his body softly to and fro, while a painful silence reigned in
+the court-room. Many men were moved, and many women's compassion
+testified itself in tears. Counsel for the defence rose and said:
+
+"Your honor, in our remarks at the opening of this trial, we
+foreshadowed our purpose to prove that our client did this fearful deed
+while under the influence of a blind and irresponsible delirium
+produced by drink. We have changed our mind. We shall not offer that
+plea." [Then to the clerk:] "Call Thomas Sawyer!"
+
+A puzzled amazement awoke in every face in the house, not even
+excepting Potter's. Every eye fastened itself with wondering interest
+upon Tom as he rose and took his place upon the stand. The boy looked
+wild enough, for he was badly scared. The oath was administered.
+
+"Thomas Sawyer, where were you on the seventeenth of June, about the
+hour of midnight?"
+
+Tom glanced at Injun Joe's iron face and his tongue failed him. The
+audience listened breathless, but the words refused to come. After a
+few moments, however, the boy got a little of his strength back, and
+managed to put enough of it into his voice to make part of the house
+hear:
+
+"In the graveyard!"
+
+"A little bit louder, please. Don't be afraid. You were--"
+
+"In the graveyard."
+
+A contemptuous smile flitted across Injun Joe's face.
+
+"Were you anywhere near Horse Williams' grave?"
+
+"Yes, sir."
+
+"Speak up--just a trifle louder. How near were you?"
+
+"Near as I am to you."
+
+"Were you hidden, or not?"
+
+"I was hid."
+
+"Where?"
+
+"Behind the elms that's on the edge of the grave."
+
+Injun Joe gave a barely perceptible start.
+
+"Any one with you?"
+
+"Yes, sir. I went there with--"
+
+"Wait--wait a moment. Never mind mentioning your companion's name. We
+will produce him at the proper time. Did you carry anything there with
+you."
+
+Tom hesitated and looked confused.
+
+"Speak out, my boy--don't be diffident. The truth is always
+respectable. What did you take there?"
+
+"Only a--a--dead cat."
+
+There was a ripple of mirth, which the court checked.
+
+"We will produce the skeleton of that cat. Now, my boy, tell us
+everything that occurred--tell it in your own way--don't skip anything,
+and don't be afraid."
+
+Tom began--hesitatingly at first, but as he warmed to his subject his
+words flowed more and more easily; in a little while every sound ceased
+but his own voice; every eye fixed itself upon him; with parted lips
+and bated breath the audience hung upon his words, taking no note of
+time, rapt in the ghastly fascinations of the tale. The strain upon
+pent emotion reached its climax when the boy said:
+
+"--and as the doctor fetched the board around and Muff Potter fell,
+Injun Joe jumped with the knife and--"
+
+Crash! Quick as lightning the half-breed sprang for a window, tore his
+way through all opposers, and was gone!
+
+
+
+CHAPTER XXIV
+
+TOM was a glittering hero once more--the pet of the old, the envy of
+the young. His name even went into immortal print, for the village
+paper magnified him. There were some that believed he would be
+President, yet, if he escaped hanging.
+
+As usual, the fickle, unreasoning world took Muff Potter to its bosom
+and fondled him as lavishly as it had abused him before. But that sort
+of conduct is to the world's credit; therefore it is not well to find
+fault with it.
+
+Tom's days were days of splendor and exultation to him, but his nights
+were seasons of horror. Injun Joe infested all his dreams, and always
+with doom in his eye. Hardly any temptation could persuade the boy to
+stir abroad after nightfall. Poor Huck was in the same state of
+wretchedness and terror, for Tom had told the whole story to the lawyer
+the night before the great day of the trial, and Huck was sore afraid
+that his share in the business might leak out, yet, notwithstanding
+Injun Joe's flight had saved him the suffering of testifying in court.
+The poor fellow had got the attorney to promise secrecy, but what of
+that? Since Tom's harassed conscience had managed to drive him to the
+lawyer's house by night and wring a dread tale from lips that had been
+sealed with the dismalest and most formidable of oaths, Huck's
+confidence in the human race was well-nigh obliterated.
+
+Daily Muff Potter's gratitude made Tom glad he had spoken; but nightly
+he wished he had sealed up his tongue.
+
+Half the time Tom was afraid Injun Joe would never be captured; the
+other half he was afraid he would be. He felt sure he never could draw
+a safe breath again until that man was dead and he had seen the corpse.
+
+Rewards had been offered, the country had been scoured, but no Injun
+Joe was found. One of those omniscient and awe-inspiring marvels, a
+detective, came up from St. Louis, moused around, shook his head,
+looked wise, and made that sort of astounding success which members of
+that craft usually achieve. That is to say, he "found a clew." But you
+can't hang a "clew" for murder, and so after that detective had got
+through and gone home, Tom felt just as insecure as he was before.
+
+The slow days drifted on, and each left behind it a slightly lightened
+weight of apprehension.
+
+
+
+CHAPTER XXV
+
+THERE comes a time in every rightly-constructed boy's life when he has
+a raging desire to go somewhere and dig for hidden treasure. This
+desire suddenly came upon Tom one day. He sallied out to find Joe
+Harper, but failed of success. Next he sought Ben Rogers; he had gone
+fishing. Presently he stumbled upon Huck Finn the Red-Handed. Huck
+would answer. Tom took him to a private place and opened the matter to
+him confidentially. Huck was willing. Huck was always willing to take a
+hand in any enterprise that offered entertainment and required no
+capital, for he had a troublesome superabundance of that sort of time
+which is not money. "Where'll we dig?" said Huck.
+
+"Oh, most anywhere."
+
+"Why, is it hid all around?"
+
+"No, indeed it ain't. It's hid in mighty particular places, Huck
+--sometimes on islands, sometimes in rotten chests under the end of a
+limb of an old dead tree, just where the shadow falls at midnight; but
+mostly under the floor in ha'nted houses."
+
+"Who hides it?"
+
+"Why, robbers, of course--who'd you reckon? Sunday-school
+sup'rintendents?"
+
+"I don't know. If 'twas mine I wouldn't hide it; I'd spend it and have
+a good time."
+
+"So would I. But robbers don't do that way. They always hide it and
+leave it there."
+
+"Don't they come after it any more?"
+
+"No, they think they will, but they generally forget the marks, or
+else they die. Anyway, it lays there a long time and gets rusty; and by
+and by somebody finds an old yellow paper that tells how to find the
+marks--a paper that's got to be ciphered over about a week because it's
+mostly signs and hy'roglyphics."
+
+"Hyro--which?"
+
+"Hy'roglyphics--pictures and things, you know, that don't seem to mean
+anything."
+
+"Have you got one of them papers, Tom?"
+
+"No."
+
+"Well then, how you going to find the marks?"
+
+"I don't want any marks. They always bury it under a ha'nted house or
+on an island, or under a dead tree that's got one limb sticking out.
+Well, we've tried Jackson's Island a little, and we can try it again
+some time; and there's the old ha'nted house up the Still-House branch,
+and there's lots of dead-limb trees--dead loads of 'em."
+
+"Is it under all of them?"
+
+"How you talk! No!"
+
+"Then how you going to know which one to go for?"
+
+"Go for all of 'em!"
+
+"Why, Tom, it'll take all summer."
+
+"Well, what of that? Suppose you find a brass pot with a hundred
+dollars in it, all rusty and gray, or rotten chest full of di'monds.
+How's that?"
+
+Huck's eyes glowed.
+
+"That's bully. Plenty bully enough for me. Just you gimme the hundred
+dollars and I don't want no di'monds."
+
+"All right. But I bet you I ain't going to throw off on di'monds. Some
+of 'em's worth twenty dollars apiece--there ain't any, hardly, but's
+worth six bits or a dollar."
+
+"No! Is that so?"
+
+"Cert'nly--anybody'll tell you so. Hain't you ever seen one, Huck?"
+
+"Not as I remember."
+
+"Oh, kings have slathers of them."
+
+"Well, I don' know no kings, Tom."
+
+"I reckon you don't. But if you was to go to Europe you'd see a raft
+of 'em hopping around."
+
+"Do they hop?"
+
+"Hop?--your granny! No!"
+
+"Well, what did you say they did, for?"
+
+"Shucks, I only meant you'd SEE 'em--not hopping, of course--what do
+they want to hop for?--but I mean you'd just see 'em--scattered around,
+you know, in a kind of a general way. Like that old humpbacked Richard."
+
+"Richard? What's his other name?"
+
+"He didn't have any other name. Kings don't have any but a given name."
+
+"No?"
+
+"But they don't."
+
+"Well, if they like it, Tom, all right; but I don't want to be a king
+and have only just a given name, like a nigger. But say--where you
+going to dig first?"
+
+"Well, I don't know. S'pose we tackle that old dead-limb tree on the
+hill t'other side of Still-House branch?"
+
+"I'm agreed."
+
+So they got a crippled pick and a shovel, and set out on their
+three-mile tramp. They arrived hot and panting, and threw themselves
+down in the shade of a neighboring elm to rest and have a smoke.
+
+"I like this," said Tom.
+
+"So do I."
+
+"Say, Huck, if we find a treasure here, what you going to do with your
+share?"
+
+"Well, I'll have pie and a glass of soda every day, and I'll go to
+every circus that comes along. I bet I'll have a gay time."
+
+"Well, ain't you going to save any of it?"
+
+"Save it? What for?"
+
+"Why, so as to have something to live on, by and by."
+
+"Oh, that ain't any use. Pap would come back to thish-yer town some
+day and get his claws on it if I didn't hurry up, and I tell you he'd
+clean it out pretty quick. What you going to do with yourn, Tom?"
+
+"I'm going to buy a new drum, and a sure-'nough sword, and a red
+necktie and a bull pup, and get married."
+
+"Married!"
+
+"That's it."
+
+"Tom, you--why, you ain't in your right mind."
+
+"Wait--you'll see."
+
+"Well, that's the foolishest thing you could do. Look at pap and my
+mother. Fight! Why, they used to fight all the time. I remember, mighty
+well."
+
+"That ain't anything. The girl I'm going to marry won't fight."
+
+"Tom, I reckon they're all alike. They'll all comb a body. Now you
+better think 'bout this awhile. I tell you you better. What's the name
+of the gal?"
+
+"It ain't a gal at all--it's a girl."
+
+"It's all the same, I reckon; some says gal, some says girl--both's
+right, like enough. Anyway, what's her name, Tom?"
+
+"I'll tell you some time--not now."
+
+"All right--that'll do. Only if you get married I'll be more lonesomer
+than ever."
+
+"No you won't. You'll come and live with me. Now stir out of this and
+we'll go to digging."
+
+They worked and sweated for half an hour. No result. They toiled
+another half-hour. Still no result. Huck said:
+
+"Do they always bury it as deep as this?"
+
+"Sometimes--not always. Not generally. I reckon we haven't got the
+right place."
+
+So they chose a new spot and began again. The labor dragged a little,
+but still they made progress. They pegged away in silence for some
+time. Finally Huck leaned on his shovel, swabbed the beaded drops from
+his brow with his sleeve, and said:
+
+"Where you going to dig next, after we get this one?"
+
+"I reckon maybe we'll tackle the old tree that's over yonder on
+Cardiff Hill back of the widow's."
+
+"I reckon that'll be a good one. But won't the widow take it away from
+us, Tom? It's on her land."
+
+"SHE take it away! Maybe she'd like to try it once. Whoever finds one
+of these hid treasures, it belongs to him. It don't make any difference
+whose land it's on."
+
+That was satisfactory. The work went on. By and by Huck said:
+
+"Blame it, we must be in the wrong place again. What do you think?"
+
+"It is mighty curious, Huck. I don't understand it. Sometimes witches
+interfere. I reckon maybe that's what's the trouble now."
+
+"Shucks! Witches ain't got no power in the daytime."
+
+"Well, that's so. I didn't think of that. Oh, I know what the matter
+is! What a blamed lot of fools we are! You got to find out where the
+shadow of the limb falls at midnight, and that's where you dig!"
+
+"Then consound it, we've fooled away all this work for nothing. Now
+hang it all, we got to come back in the night. It's an awful long way.
+Can you get out?"
+
+"I bet I will. We've got to do it to-night, too, because if somebody
+sees these holes they'll know in a minute what's here and they'll go
+for it."
+
+"Well, I'll come around and maow to-night."
+
+"All right. Let's hide the tools in the bushes."
+
+The boys were there that night, about the appointed time. They sat in
+the shadow waiting. It was a lonely place, and an hour made solemn by
+old traditions. Spirits whispered in the rustling leaves, ghosts lurked
+in the murky nooks, the deep baying of a hound floated up out of the
+distance, an owl answered with his sepulchral note. The boys were
+subdued by these solemnities, and talked little. By and by they judged
+that twelve had come; they marked where the shadow fell, and began to
+dig. Their hopes commenced to rise. Their interest grew stronger, and
+their industry kept pace with it. The hole deepened and still deepened,
+but every time their hearts jumped to hear the pick strike upon
+something, they only suffered a new disappointment. It was only a stone
+or a chunk. At last Tom said:
+
+"It ain't any use, Huck, we're wrong again."
+
+"Well, but we CAN'T be wrong. We spotted the shadder to a dot."
+
+"I know it, but then there's another thing."
+
+"What's that?".
+
+"Why, we only guessed at the time. Like enough it was too late or too
+early."
+
+Huck dropped his shovel.
+
+"That's it," said he. "That's the very trouble. We got to give this
+one up. We can't ever tell the right time, and besides this kind of
+thing's too awful, here this time of night with witches and ghosts
+a-fluttering around so. I feel as if something's behind me all the time;
+and I'm afeard to turn around, becuz maybe there's others in front
+a-waiting for a chance. I been creeping all over, ever since I got here."
+
+"Well, I've been pretty much so, too, Huck. They most always put in a
+dead man when they bury a treasure under a tree, to look out for it."
+
+"Lordy!"
+
+"Yes, they do. I've always heard that."
+
+"Tom, I don't like to fool around much where there's dead people. A
+body's bound to get into trouble with 'em, sure."
+
+"I don't like to stir 'em up, either. S'pose this one here was to
+stick his skull out and say something!"
+
+"Don't Tom! It's awful."
+
+"Well, it just is. Huck, I don't feel comfortable a bit."
+
+"Say, Tom, let's give this place up, and try somewheres else."
+
+"All right, I reckon we better."
+
+"What'll it be?"
+
+Tom considered awhile; and then said:
+
+"The ha'nted house. That's it!"
+
+"Blame it, I don't like ha'nted houses, Tom. Why, they're a dern sight
+worse'n dead people. Dead people might talk, maybe, but they don't come
+sliding around in a shroud, when you ain't noticing, and peep over your
+shoulder all of a sudden and grit their teeth, the way a ghost does. I
+couldn't stand such a thing as that, Tom--nobody could."
+
+"Yes, but, Huck, ghosts don't travel around only at night. They won't
+hender us from digging there in the daytime."
+
+"Well, that's so. But you know mighty well people don't go about that
+ha'nted house in the day nor the night."
+
+"Well, that's mostly because they don't like to go where a man's been
+murdered, anyway--but nothing's ever been seen around that house except
+in the night--just some blue lights slipping by the windows--no regular
+ghosts."
+
+"Well, where you see one of them blue lights flickering around, Tom,
+you can bet there's a ghost mighty close behind it. It stands to
+reason. Becuz you know that they don't anybody but ghosts use 'em."
+
+"Yes, that's so. But anyway they don't come around in the daytime, so
+what's the use of our being afeard?"
+
+"Well, all right. We'll tackle the ha'nted house if you say so--but I
+reckon it's taking chances."
+
+They had started down the hill by this time. There in the middle of
+the moonlit valley below them stood the "ha'nted" house, utterly
+isolated, its fences gone long ago, rank weeds smothering the very
+doorsteps, the chimney crumbled to ruin, the window-sashes vacant, a
+corner of the roof caved in. The boys gazed awhile, half expecting to
+see a blue light flit past a window; then talking in a low tone, as
+befitted the time and the circumstances, they struck far off to the
+right, to give the haunted house a wide berth, and took their way
+homeward through the woods that adorned the rearward side of Cardiff
+Hill.
+
+
+
+CHAPTER XXVI
+
+ABOUT noon the next day the boys arrived at the dead tree; they had
+come for their tools. Tom was impatient to go to the haunted house;
+Huck was measurably so, also--but suddenly said:
+
+"Lookyhere, Tom, do you know what day it is?"
+
+Tom mentally ran over the days of the week, and then quickly lifted
+his eyes with a startled look in them--
+
+"My! I never once thought of it, Huck!"
+
+"Well, I didn't neither, but all at once it popped onto me that it was
+Friday."
+
+"Blame it, a body can't be too careful, Huck. We might 'a' got into an
+awful scrape, tackling such a thing on a Friday."
+
+"MIGHT! Better say we WOULD! There's some lucky days, maybe, but
+Friday ain't."
+
+"Any fool knows that. I don't reckon YOU was the first that found it
+out, Huck."
+
+"Well, I never said I was, did I? And Friday ain't all, neither. I had
+a rotten bad dream last night--dreampt about rats."
+
+"No! Sure sign of trouble. Did they fight?"
+
+"No."
+
+"Well, that's good, Huck. When they don't fight it's only a sign that
+there's trouble around, you know. All we got to do is to look mighty
+sharp and keep out of it. We'll drop this thing for to-day, and play.
+Do you know Robin Hood, Huck?"
+
+"No. Who's Robin Hood?"
+
+"Why, he was one of the greatest men that was ever in England--and the
+best. He was a robber."
+
+"Cracky, I wisht I was. Who did he rob?"
+
+"Only sheriffs and bishops and rich people and kings, and such like.
+But he never bothered the poor. He loved 'em. He always divided up with
+'em perfectly square."
+
+"Well, he must 'a' been a brick."
+
+"I bet you he was, Huck. Oh, he was the noblest man that ever was.
+They ain't any such men now, I can tell you. He could lick any man in
+England, with one hand tied behind him; and he could take his yew bow
+and plug a ten-cent piece every time, a mile and a half."
+
+"What's a YEW bow?"
+
+"I don't know. It's some kind of a bow, of course. And if he hit that
+dime only on the edge he would set down and cry--and curse. But we'll
+play Robin Hood--it's nobby fun. I'll learn you."
+
+"I'm agreed."
+
+So they played Robin Hood all the afternoon, now and then casting a
+yearning eye down upon the haunted house and passing a remark about the
+morrow's prospects and possibilities there. As the sun began to sink
+into the west they took their way homeward athwart the long shadows of
+the trees and soon were buried from sight in the forests of Cardiff
+Hill.
+
+On Saturday, shortly after noon, the boys were at the dead tree again.
+They had a smoke and a chat in the shade, and then dug a little in
+their last hole, not with great hope, but merely because Tom said there
+were so many cases where people had given up a treasure after getting
+down within six inches of it, and then somebody else had come along and
+turned it up with a single thrust of a shovel. The thing failed this
+time, however, so the boys shouldered their tools and went away feeling
+that they had not trifled with fortune, but had fulfilled all the
+requirements that belong to the business of treasure-hunting.
+
+When they reached the haunted house there was something so weird and
+grisly about the dead silence that reigned there under the baking sun,
+and something so depressing about the loneliness and desolation of the
+place, that they were afraid, for a moment, to venture in. Then they
+crept to the door and took a trembling peep. They saw a weed-grown,
+floorless room, unplastered, an ancient fireplace, vacant windows, a
+ruinous staircase; and here, there, and everywhere hung ragged and
+abandoned cobwebs. They presently entered, softly, with quickened
+pulses, talking in whispers, ears alert to catch the slightest sound,
+and muscles tense and ready for instant retreat.
+
+In a little while familiarity modified their fears and they gave the
+place a critical and interested examination, rather admiring their own
+boldness, and wondering at it, too. Next they wanted to look up-stairs.
+This was something like cutting off retreat, but they got to daring
+each other, and of course there could be but one result--they threw
+their tools into a corner and made the ascent. Up there were the same
+signs of decay. In one corner they found a closet that promised
+mystery, but the promise was a fraud--there was nothing in it. Their
+courage was up now and well in hand. They were about to go down and
+begin work when--
+
+"Sh!" said Tom.
+
+"What is it?" whispered Huck, blanching with fright.
+
+"Sh!... There!... Hear it?"
+
+"Yes!... Oh, my! Let's run!"
+
+"Keep still! Don't you budge! They're coming right toward the door."
+
+The boys stretched themselves upon the floor with their eyes to
+knot-holes in the planking, and lay waiting, in a misery of fear.
+
+"They've stopped.... No--coming.... Here they are. Don't whisper
+another word, Huck. My goodness, I wish I was out of this!"
+
+Two men entered. Each boy said to himself: "There's the old deaf and
+dumb Spaniard that's been about town once or twice lately--never saw
+t'other man before."
+
+"T'other" was a ragged, unkempt creature, with nothing very pleasant
+in his face. The Spaniard was wrapped in a serape; he had bushy white
+whiskers; long white hair flowed from under his sombrero, and he wore
+green goggles. When they came in, "t'other" was talking in a low voice;
+they sat down on the ground, facing the door, with their backs to the
+wall, and the speaker continued his remarks. His manner became less
+guarded and his words more distinct as he proceeded:
+
+"No," said he, "I've thought it all over, and I don't like it. It's
+dangerous."
+
+"Dangerous!" grunted the "deaf and dumb" Spaniard--to the vast
+surprise of the boys. "Milksop!"
+
+This voice made the boys gasp and quake. It was Injun Joe's! There was
+silence for some time. Then Joe said:
+
+"What's any more dangerous than that job up yonder--but nothing's come
+of it."
+
+"That's different. Away up the river so, and not another house about.
+'Twon't ever be known that we tried, anyway, long as we didn't succeed."
+
+"Well, what's more dangerous than coming here in the daytime!--anybody
+would suspicion us that saw us."
+
+"I know that. But there warn't any other place as handy after that
+fool of a job. I want to quit this shanty. I wanted to yesterday, only
+it warn't any use trying to stir out of here, with those infernal boys
+playing over there on the hill right in full view."
+
+"Those infernal boys" quaked again under the inspiration of this
+remark, and thought how lucky it was that they had remembered it was
+Friday and concluded to wait a day. They wished in their hearts they
+had waited a year.
+
+The two men got out some food and made a luncheon. After a long and
+thoughtful silence, Injun Joe said:
+
+"Look here, lad--you go back up the river where you belong. Wait there
+till you hear from me. I'll take the chances on dropping into this town
+just once more, for a look. We'll do that 'dangerous' job after I've
+spied around a little and think things look well for it. Then for
+Texas! We'll leg it together!"
+
+This was satisfactory. Both men presently fell to yawning, and Injun
+Joe said:
+
+"I'm dead for sleep! It's your turn to watch."
+
+He curled down in the weeds and soon began to snore. His comrade
+stirred him once or twice and he became quiet. Presently the watcher
+began to nod; his head drooped lower and lower, both men began to snore
+now.
+
+The boys drew a long, grateful breath. Tom whispered:
+
+"Now's our chance--come!"
+
+Huck said:
+
+"I can't--I'd die if they was to wake."
+
+Tom urged--Huck held back. At last Tom rose slowly and softly, and
+started alone. But the first step he made wrung such a hideous creak
+from the crazy floor that he sank down almost dead with fright. He
+never made a second attempt. The boys lay there counting the dragging
+moments till it seemed to them that time must be done and eternity
+growing gray; and then they were grateful to note that at last the sun
+was setting.
+
+Now one snore ceased. Injun Joe sat up, stared around--smiled grimly
+upon his comrade, whose head was drooping upon his knees--stirred him
+up with his foot and said:
+
+"Here! YOU'RE a watchman, ain't you! All right, though--nothing's
+happened."
+
+"My! have I been asleep?"
+
+"Oh, partly, partly. Nearly time for us to be moving, pard. What'll we
+do with what little swag we've got left?"
+
+"I don't know--leave it here as we've always done, I reckon. No use to
+take it away till we start south. Six hundred and fifty in silver's
+something to carry."
+
+"Well--all right--it won't matter to come here once more."
+
+"No--but I'd say come in the night as we used to do--it's better."
+
+"Yes: but look here; it may be a good while before I get the right
+chance at that job; accidents might happen; 'tain't in such a very good
+place; we'll just regularly bury it--and bury it deep."
+
+"Good idea," said the comrade, who walked across the room, knelt down,
+raised one of the rearward hearth-stones and took out a bag that
+jingled pleasantly. He subtracted from it twenty or thirty dollars for
+himself and as much for Injun Joe, and passed the bag to the latter,
+who was on his knees in the corner, now, digging with his bowie-knife.
+
+The boys forgot all their fears, all their miseries in an instant.
+With gloating eyes they watched every movement. Luck!--the splendor of
+it was beyond all imagination! Six hundred dollars was money enough to
+make half a dozen boys rich! Here was treasure-hunting under the
+happiest auspices--there would not be any bothersome uncertainty as to
+where to dig. They nudged each other every moment--eloquent nudges and
+easily understood, for they simply meant--"Oh, but ain't you glad NOW
+we're here!"
+
+Joe's knife struck upon something.
+
+"Hello!" said he.
+
+"What is it?" said his comrade.
+
+"Half-rotten plank--no, it's a box, I believe. Here--bear a hand and
+we'll see what it's here for. Never mind, I've broke a hole."
+
+He reached his hand in and drew it out--
+
+"Man, it's money!"
+
+The two men examined the handful of coins. They were gold. The boys
+above were as excited as themselves, and as delighted.
+
+Joe's comrade said:
+
+"We'll make quick work of this. There's an old rusty pick over amongst
+the weeds in the corner the other side of the fireplace--I saw it a
+minute ago."
+
+He ran and brought the boys' pick and shovel. Injun Joe took the pick,
+looked it over critically, shook his head, muttered something to
+himself, and then began to use it. The box was soon unearthed. It was
+not very large; it was iron bound and had been very strong before the
+slow years had injured it. The men contemplated the treasure awhile in
+blissful silence.
+
+"Pard, there's thousands of dollars here," said Injun Joe.
+
+"'Twas always said that Murrel's gang used to be around here one
+summer," the stranger observed.
+
+"I know it," said Injun Joe; "and this looks like it, I should say."
+
+"Now you won't need to do that job."
+
+The half-breed frowned. Said he:
+
+"You don't know me. Least you don't know all about that thing. 'Tain't
+robbery altogether--it's REVENGE!" and a wicked light flamed in his
+eyes. "I'll need your help in it. When it's finished--then Texas. Go
+home to your Nance and your kids, and stand by till you hear from me."
+
+"Well--if you say so; what'll we do with this--bury it again?"
+
+"Yes. [Ravishing delight overhead.] NO! by the great Sachem, no!
+[Profound distress overhead.] I'd nearly forgot. That pick had fresh
+earth on it! [The boys were sick with terror in a moment.] What
+business has a pick and a shovel here? What business with fresh earth
+on them? Who brought them here--and where are they gone? Have you heard
+anybody?--seen anybody? What! bury it again and leave them to come and
+see the ground disturbed? Not exactly--not exactly. We'll take it to my
+den."
+
+"Why, of course! Might have thought of that before. You mean Number
+One?"
+
+"No--Number Two--under the cross. The other place is bad--too common."
+
+"All right. It's nearly dark enough to start."
+
+Injun Joe got up and went about from window to window cautiously
+peeping out. Presently he said:
+
+"Who could have brought those tools here? Do you reckon they can be
+up-stairs?"
+
+The boys' breath forsook them. Injun Joe put his hand on his knife,
+halted a moment, undecided, and then turned toward the stairway. The
+boys thought of the closet, but their strength was gone. The steps came
+creaking up the stairs--the intolerable distress of the situation woke
+the stricken resolution of the lads--they were about to spring for the
+closet, when there was a crash of rotten timbers and Injun Joe landed
+on the ground amid the debris of the ruined stairway. He gathered
+himself up cursing, and his comrade said:
+
+"Now what's the use of all that? If it's anybody, and they're up
+there, let them STAY there--who cares? If they want to jump down, now,
+and get into trouble, who objects? It will be dark in fifteen minutes
+--and then let them follow us if they want to. I'm willing. In my
+opinion, whoever hove those things in here caught a sight of us and
+took us for ghosts or devils or something. I'll bet they're running
+yet."
+
+Joe grumbled awhile; then he agreed with his friend that what daylight
+was left ought to be economized in getting things ready for leaving.
+Shortly afterward they slipped out of the house in the deepening
+twilight, and moved toward the river with their precious box.
+
+Tom and Huck rose up, weak but vastly relieved, and stared after them
+through the chinks between the logs of the house. Follow? Not they.
+They were content to reach ground again without broken necks, and take
+the townward track over the hill. They did not talk much. They were too
+much absorbed in hating themselves--hating the ill luck that made them
+take the spade and the pick there. But for that, Injun Joe never would
+have suspected. He would have hidden the silver with the gold to wait
+there till his "revenge" was satisfied, and then he would have had the
+misfortune to find that money turn up missing. Bitter, bitter luck that
+the tools were ever brought there!
+
+They resolved to keep a lookout for that Spaniard when he should come
+to town spying out for chances to do his revengeful job, and follow him
+to "Number Two," wherever that might be. Then a ghastly thought
+occurred to Tom.
+
+"Revenge? What if he means US, Huck!"
+
+"Oh, don't!" said Huck, nearly fainting.
+
+They talked it all over, and as they entered town they agreed to
+believe that he might possibly mean somebody else--at least that he
+might at least mean nobody but Tom, since only Tom had testified.
+
+Very, very small comfort it was to Tom to be alone in danger! Company
+would be a palpable improvement, he thought.
+
+
+
+CHAPTER XXVII
+
+THE adventure of the day mightily tormented Tom's dreams that night.
+Four times he had his hands on that rich treasure and four times it
+wasted to nothingness in his fingers as sleep forsook him and
+wakefulness brought back the hard reality of his misfortune. As he lay
+in the early morning recalling the incidents of his great adventure, he
+noticed that they seemed curiously subdued and far away--somewhat as if
+they had happened in another world, or in a time long gone by. Then it
+occurred to him that the great adventure itself must be a dream! There
+was one very strong argument in favor of this idea--namely, that the
+quantity of coin he had seen was too vast to be real. He had never seen
+as much as fifty dollars in one mass before, and he was like all boys
+of his age and station in life, in that he imagined that all references
+to "hundreds" and "thousands" were mere fanciful forms of speech, and
+that no such sums really existed in the world. He never had supposed
+for a moment that so large a sum as a hundred dollars was to be found
+in actual money in any one's possession. If his notions of hidden
+treasure had been analyzed, they would have been found to consist of a
+handful of real dimes and a bushel of vague, splendid, ungraspable
+dollars.
+
+But the incidents of his adventure grew sensibly sharper and clearer
+under the attrition of thinking them over, and so he presently found
+himself leaning to the impression that the thing might not have been a
+dream, after all. This uncertainty must be swept away. He would snatch
+a hurried breakfast and go and find Huck. Huck was sitting on the
+gunwale of a flatboat, listlessly dangling his feet in the water and
+looking very melancholy. Tom concluded to let Huck lead up to the
+subject. If he did not do it, then the adventure would be proved to
+have been only a dream.
+
+"Hello, Huck!"
+
+"Hello, yourself."
+
+Silence, for a minute.
+
+"Tom, if we'd 'a' left the blame tools at the dead tree, we'd 'a' got
+the money. Oh, ain't it awful!"
+
+"'Tain't a dream, then, 'tain't a dream! Somehow I most wish it was.
+Dog'd if I don't, Huck."
+
+"What ain't a dream?"
+
+"Oh, that thing yesterday. I been half thinking it was."
+
+"Dream! If them stairs hadn't broke down you'd 'a' seen how much dream
+it was! I've had dreams enough all night--with that patch-eyed Spanish
+devil going for me all through 'em--rot him!"
+
+"No, not rot him. FIND him! Track the money!"
+
+"Tom, we'll never find him. A feller don't have only one chance for
+such a pile--and that one's lost. I'd feel mighty shaky if I was to see
+him, anyway."
+
+"Well, so'd I; but I'd like to see him, anyway--and track him out--to
+his Number Two."
+
+"Number Two--yes, that's it. I been thinking 'bout that. But I can't
+make nothing out of it. What do you reckon it is?"
+
+"I dono. It's too deep. Say, Huck--maybe it's the number of a house!"
+
+"Goody!... No, Tom, that ain't it. If it is, it ain't in this
+one-horse town. They ain't no numbers here."
+
+"Well, that's so. Lemme think a minute. Here--it's the number of a
+room--in a tavern, you know!"
+
+"Oh, that's the trick! They ain't only two taverns. We can find out
+quick."
+
+"You stay here, Huck, till I come."
+
+Tom was off at once. He did not care to have Huck's company in public
+places. He was gone half an hour. He found that in the best tavern, No.
+2 had long been occupied by a young lawyer, and was still so occupied.
+In the less ostentatious house, No. 2 was a mystery. The
+tavern-keeper's young son said it was kept locked all the time, and he
+never saw anybody go into it or come out of it except at night; he did
+not know any particular reason for this state of things; had had some
+little curiosity, but it was rather feeble; had made the most of the
+mystery by entertaining himself with the idea that that room was
+"ha'nted"; had noticed that there was a light in there the night before.
+
+"That's what I've found out, Huck. I reckon that's the very No. 2
+we're after."
+
+"I reckon it is, Tom. Now what you going to do?"
+
+"Lemme think."
+
+Tom thought a long time. Then he said:
+
+"I'll tell you. The back door of that No. 2 is the door that comes out
+into that little close alley between the tavern and the old rattle trap
+of a brick store. Now you get hold of all the door-keys you can find,
+and I'll nip all of auntie's, and the first dark night we'll go there
+and try 'em. And mind you, keep a lookout for Injun Joe, because he
+said he was going to drop into town and spy around once more for a
+chance to get his revenge. If you see him, you just follow him; and if
+he don't go to that No. 2, that ain't the place."
+
+"Lordy, I don't want to foller him by myself!"
+
+"Why, it'll be night, sure. He mightn't ever see you--and if he did,
+maybe he'd never think anything."
+
+"Well, if it's pretty dark I reckon I'll track him. I dono--I dono.
+I'll try."
+
+"You bet I'll follow him, if it's dark, Huck. Why, he might 'a' found
+out he couldn't get his revenge, and be going right after that money."
+
+"It's so, Tom, it's so. I'll foller him; I will, by jingoes!"
+
+"Now you're TALKING! Don't you ever weaken, Huck, and I won't."
+
+
+
+CHAPTER XXVIII
+
+THAT night Tom and Huck were ready for their adventure. They hung
+about the neighborhood of the tavern until after nine, one watching the
+alley at a distance and the other the tavern door. Nobody entered the
+alley or left it; nobody resembling the Spaniard entered or left the
+tavern door. The night promised to be a fair one; so Tom went home with
+the understanding that if a considerable degree of darkness came on,
+Huck was to come and "maow," whereupon he would slip out and try the
+keys. But the night remained clear, and Huck closed his watch and
+retired to bed in an empty sugar hogshead about twelve.
+
+Tuesday the boys had the same ill luck. Also Wednesday. But Thursday
+night promised better. Tom slipped out in good season with his aunt's
+old tin lantern, and a large towel to blindfold it with. He hid the
+lantern in Huck's sugar hogshead and the watch began. An hour before
+midnight the tavern closed up and its lights (the only ones
+thereabouts) were put out. No Spaniard had been seen. Nobody had
+entered or left the alley. Everything was auspicious. The blackness of
+darkness reigned, the perfect stillness was interrupted only by
+occasional mutterings of distant thunder.
+
+Tom got his lantern, lit it in the hogshead, wrapped it closely in the
+towel, and the two adventurers crept in the gloom toward the tavern.
+Huck stood sentry and Tom felt his way into the alley. Then there was a
+season of waiting anxiety that weighed upon Huck's spirits like a
+mountain. He began to wish he could see a flash from the lantern--it
+would frighten him, but it would at least tell him that Tom was alive
+yet. It seemed hours since Tom had disappeared. Surely he must have
+fainted; maybe he was dead; maybe his heart had burst under terror and
+excitement. In his uneasiness Huck found himself drawing closer and
+closer to the alley; fearing all sorts of dreadful things, and
+momentarily expecting some catastrophe to happen that would take away
+his breath. There was not much to take away, for he seemed only able to
+inhale it by thimblefuls, and his heart would soon wear itself out, the
+way it was beating. Suddenly there was a flash of light and Tom came
+tearing by him: "Run!" said he; "run, for your life!"
+
+He needn't have repeated it; once was enough; Huck was making thirty
+or forty miles an hour before the repetition was uttered. The boys
+never stopped till they reached the shed of a deserted slaughter-house
+at the lower end of the village. Just as they got within its shelter
+the storm burst and the rain poured down. As soon as Tom got his breath
+he said:
+
+"Huck, it was awful! I tried two of the keys, just as soft as I could;
+but they seemed to make such a power of racket that I couldn't hardly
+get my breath I was so scared. They wouldn't turn in the lock, either.
+Well, without noticing what I was doing, I took hold of the knob, and
+open comes the door! It warn't locked! I hopped in, and shook off the
+towel, and, GREAT CAESAR'S GHOST!"
+
+"What!--what'd you see, Tom?"
+
+"Huck, I most stepped onto Injun Joe's hand!"
+
+"No!"
+
+"Yes! He was lying there, sound asleep on the floor, with his old
+patch on his eye and his arms spread out."
+
+"Lordy, what did you do? Did he wake up?"
+
+"No, never budged. Drunk, I reckon. I just grabbed that towel and
+started!"
+
+"I'd never 'a' thought of the towel, I bet!"
+
+"Well, I would. My aunt would make me mighty sick if I lost it."
+
+"Say, Tom, did you see that box?"
+
+"Huck, I didn't wait to look around. I didn't see the box, I didn't
+see the cross. I didn't see anything but a bottle and a tin cup on the
+floor by Injun Joe; yes, I saw two barrels and lots more bottles in the
+room. Don't you see, now, what's the matter with that ha'nted room?"
+
+"How?"
+
+"Why, it's ha'nted with whiskey! Maybe ALL the Temperance Taverns have
+got a ha'nted room, hey, Huck?"
+
+"Well, I reckon maybe that's so. Who'd 'a' thought such a thing? But
+say, Tom, now's a mighty good time to get that box, if Injun Joe's
+drunk."
+
+"It is, that! You try it!"
+
+Huck shuddered.
+
+"Well, no--I reckon not."
+
+"And I reckon not, Huck. Only one bottle alongside of Injun Joe ain't
+enough. If there'd been three, he'd be drunk enough and I'd do it."
+
+There was a long pause for reflection, and then Tom said:
+
+"Lookyhere, Huck, less not try that thing any more till we know Injun
+Joe's not in there. It's too scary. Now, if we watch every night, we'll
+be dead sure to see him go out, some time or other, and then we'll
+snatch that box quicker'n lightning."
+
+"Well, I'm agreed. I'll watch the whole night long, and I'll do it
+every night, too, if you'll do the other part of the job."
+
+"All right, I will. All you got to do is to trot up Hooper Street a
+block and maow--and if I'm asleep, you throw some gravel at the window
+and that'll fetch me."
+
+"Agreed, and good as wheat!"
+
+"Now, Huck, the storm's over, and I'll go home. It'll begin to be
+daylight in a couple of hours. You go back and watch that long, will
+you?"
+
+"I said I would, Tom, and I will. I'll ha'nt that tavern every night
+for a year! I'll sleep all day and I'll stand watch all night."
+
+"That's all right. Now, where you going to sleep?"
+
+"In Ben Rogers' hayloft. He lets me, and so does his pap's nigger man,
+Uncle Jake. I tote water for Uncle Jake whenever he wants me to, and
+any time I ask him he gives me a little something to eat if he can
+spare it. That's a mighty good nigger, Tom. He likes me, becuz I don't
+ever act as if I was above him. Sometime I've set right down and eat
+WITH him. But you needn't tell that. A body's got to do things when
+he's awful hungry he wouldn't want to do as a steady thing."
+
+"Well, if I don't want you in the daytime, I'll let you sleep. I won't
+come bothering around. Any time you see something's up, in the night,
+just skip right around and maow."
+
+
+
+CHAPTER XXIX
+
+THE first thing Tom heard on Friday morning was a glad piece of news
+--Judge Thatcher's family had come back to town the night before. Both
+Injun Joe and the treasure sunk into secondary importance for a moment,
+and Becky took the chief place in the boy's interest. He saw her and
+they had an exhausting good time playing "hi-spy" and "gully-keeper"
+with a crowd of their school-mates. The day was completed and crowned
+in a peculiarly satisfactory way: Becky teased her mother to appoint
+the next day for the long-promised and long-delayed picnic, and she
+consented. The child's delight was boundless; and Tom's not more
+moderate. The invitations were sent out before sunset, and straightway
+the young folks of the village were thrown into a fever of preparation
+and pleasurable anticipation. Tom's excitement enabled him to keep
+awake until a pretty late hour, and he had good hopes of hearing Huck's
+"maow," and of having his treasure to astonish Becky and the picnickers
+with, next day; but he was disappointed. No signal came that night.
+
+Morning came, eventually, and by ten or eleven o'clock a giddy and
+rollicking company were gathered at Judge Thatcher's, and everything
+was ready for a start. It was not the custom for elderly people to mar
+the picnics with their presence. The children were considered safe
+enough under the wings of a few young ladies of eighteen and a few
+young gentlemen of twenty-three or thereabouts. The old steam ferryboat
+was chartered for the occasion; presently the gay throng filed up the
+main street laden with provision-baskets. Sid was sick and had to miss
+the fun; Mary remained at home to entertain him. The last thing Mrs.
+Thatcher said to Becky, was:
+
+"You'll not get back till late. Perhaps you'd better stay all night
+with some of the girls that live near the ferry-landing, child."
+
+"Then I'll stay with Susy Harper, mamma."
+
+"Very well. And mind and behave yourself and don't be any trouble."
+
+Presently, as they tripped along, Tom said to Becky:
+
+"Say--I'll tell you what we'll do. 'Stead of going to Joe Harper's
+we'll climb right up the hill and stop at the Widow Douglas'. She'll
+have ice-cream! She has it most every day--dead loads of it. And she'll
+be awful glad to have us."
+
+"Oh, that will be fun!"
+
+Then Becky reflected a moment and said:
+
+"But what will mamma say?"
+
+"How'll she ever know?"
+
+The girl turned the idea over in her mind, and said reluctantly:
+
+"I reckon it's wrong--but--"
+
+"But shucks! Your mother won't know, and so what's the harm? All she
+wants is that you'll be safe; and I bet you she'd 'a' said go there if
+she'd 'a' thought of it. I know she would!"
+
+The Widow Douglas' splendid hospitality was a tempting bait. It and
+Tom's persuasions presently carried the day. So it was decided to say
+nothing anybody about the night's programme. Presently it occurred to
+Tom that maybe Huck might come this very night and give the signal. The
+thought took a deal of the spirit out of his anticipations. Still he
+could not bear to give up the fun at Widow Douglas'. And why should he
+give it up, he reasoned--the signal did not come the night before, so
+why should it be any more likely to come to-night? The sure fun of the
+evening outweighed the uncertain treasure; and, boy-like, he determined
+to yield to the stronger inclination and not allow himself to think of
+the box of money another time that day.
+
+Three miles below town the ferryboat stopped at the mouth of a woody
+hollow and tied up. The crowd swarmed ashore and soon the forest
+distances and craggy heights echoed far and near with shoutings and
+laughter. All the different ways of getting hot and tired were gone
+through with, and by-and-by the rovers straggled back to camp fortified
+with responsible appetites, and then the destruction of the good things
+began. After the feast there was a refreshing season of rest and chat
+in the shade of spreading oaks. By-and-by somebody shouted:
+
+"Who's ready for the cave?"
+
+Everybody was. Bundles of candles were procured, and straightway there
+was a general scamper up the hill. The mouth of the cave was up the
+hillside--an opening shaped like a letter A. Its massive oaken door
+stood unbarred. Within was a small chamber, chilly as an ice-house, and
+walled by Nature with solid limestone that was dewy with a cold sweat.
+It was romantic and mysterious to stand here in the deep gloom and look
+out upon the green valley shining in the sun. But the impressiveness of
+the situation quickly wore off, and the romping began again. The moment
+a candle was lighted there was a general rush upon the owner of it; a
+struggle and a gallant defence followed, but the candle was soon
+knocked down or blown out, and then there was a glad clamor of laughter
+and a new chase. But all things have an end. By-and-by the procession
+went filing down the steep descent of the main avenue, the flickering
+rank of lights dimly revealing the lofty walls of rock almost to their
+point of junction sixty feet overhead. This main avenue was not more
+than eight or ten feet wide. Every few steps other lofty and still
+narrower crevices branched from it on either hand--for McDougal's cave
+was but a vast labyrinth of crooked aisles that ran into each other and
+out again and led nowhere. It was said that one might wander days and
+nights together through its intricate tangle of rifts and chasms, and
+never find the end of the cave; and that he might go down, and down,
+and still down, into the earth, and it was just the same--labyrinth
+under labyrinth, and no end to any of them. No man "knew" the cave.
+That was an impossible thing. Most of the young men knew a portion of
+it, and it was not customary to venture much beyond this known portion.
+Tom Sawyer knew as much of the cave as any one.
+
+The procession moved along the main avenue some three-quarters of a
+mile, and then groups and couples began to slip aside into branch
+avenues, fly along the dismal corridors, and take each other by
+surprise at points where the corridors joined again. Parties were able
+to elude each other for the space of half an hour without going beyond
+the "known" ground.
+
+By-and-by, one group after another came straggling back to the mouth
+of the cave, panting, hilarious, smeared from head to foot with tallow
+drippings, daubed with clay, and entirely delighted with the success of
+the day. Then they were astonished to find that they had been taking no
+note of time and that night was about at hand. The clanging bell had
+been calling for half an hour. However, this sort of close to the day's
+adventures was romantic and therefore satisfactory. When the ferryboat
+with her wild freight pushed into the stream, nobody cared sixpence for
+the wasted time but the captain of the craft.
+
+Huck was already upon his watch when the ferryboat's lights went
+glinting past the wharf. He heard no noise on board, for the young
+people were as subdued and still as people usually are who are nearly
+tired to death. He wondered what boat it was, and why she did not stop
+at the wharf--and then he dropped her out of his mind and put his
+attention upon his business. The night was growing cloudy and dark. Ten
+o'clock came, and the noise of vehicles ceased, scattered lights began
+to wink out, all straggling foot-passengers disappeared, the village
+betook itself to its slumbers and left the small watcher alone with the
+silence and the ghosts. Eleven o'clock came, and the tavern lights were
+put out; darkness everywhere, now. Huck waited what seemed a weary long
+time, but nothing happened. His faith was weakening. Was there any use?
+Was there really any use? Why not give it up and turn in?
+
+A noise fell upon his ear. He was all attention in an instant. The
+alley door closed softly. He sprang to the corner of the brick store.
+The next moment two men brushed by him, and one seemed to have
+something under his arm. It must be that box! So they were going to
+remove the treasure. Why call Tom now? It would be absurd--the men
+would get away with the box and never be found again. No, he would
+stick to their wake and follow them; he would trust to the darkness for
+security from discovery. So communing with himself, Huck stepped out
+and glided along behind the men, cat-like, with bare feet, allowing
+them to keep just far enough ahead not to be invisible.
+
+They moved up the river street three blocks, then turned to the left
+up a cross-street. They went straight ahead, then, until they came to
+the path that led up Cardiff Hill; this they took. They passed by the
+old Welshman's house, half-way up the hill, without hesitating, and
+still climbed upward. Good, thought Huck, they will bury it in the old
+quarry. But they never stopped at the quarry. They passed on, up the
+summit. They plunged into the narrow path between the tall sumach
+bushes, and were at once hidden in the gloom. Huck closed up and
+shortened his distance, now, for they would never be able to see him.
+He trotted along awhile; then slackened his pace, fearing he was
+gaining too fast; moved on a piece, then stopped altogether; listened;
+no sound; none, save that he seemed to hear the beating of his own
+heart. The hooting of an owl came over the hill--ominous sound! But no
+footsteps. Heavens, was everything lost! He was about to spring with
+winged feet, when a man cleared his throat not four feet from him!
+Huck's heart shot into his throat, but he swallowed it again; and then
+he stood there shaking as if a dozen agues had taken charge of him at
+once, and so weak that he thought he must surely fall to the ground. He
+knew where he was. He knew he was within five steps of the stile
+leading into Widow Douglas' grounds. Very well, he thought, let them
+bury it there; it won't be hard to find.
+
+Now there was a voice--a very low voice--Injun Joe's:
+
+"Damn her, maybe she's got company--there's lights, late as it is."
+
+"I can't see any."
+
+This was that stranger's voice--the stranger of the haunted house. A
+deadly chill went to Huck's heart--this, then, was the "revenge" job!
+His thought was, to fly. Then he remembered that the Widow Douglas had
+been kind to him more than once, and maybe these men were going to
+murder her. He wished he dared venture to warn her; but he knew he
+didn't dare--they might come and catch him. He thought all this and
+more in the moment that elapsed between the stranger's remark and Injun
+Joe's next--which was--
+
+"Because the bush is in your way. Now--this way--now you see, don't
+you?"
+
+"Yes. Well, there IS company there, I reckon. Better give it up."
+
+"Give it up, and I just leaving this country forever! Give it up and
+maybe never have another chance. I tell you again, as I've told you
+before, I don't care for her swag--you may have it. But her husband was
+rough on me--many times he was rough on me--and mainly he was the
+justice of the peace that jugged me for a vagrant. And that ain't all.
+It ain't a millionth part of it! He had me HORSEWHIPPED!--horsewhipped
+in front of the jail, like a nigger!--with all the town looking on!
+HORSEWHIPPED!--do you understand? He took advantage of me and died. But
+I'll take it out of HER."
+
+"Oh, don't kill her! Don't do that!"
+
+"Kill? Who said anything about killing? I would kill HIM if he was
+here; but not her. When you want to get revenge on a woman you don't
+kill her--bosh! you go for her looks. You slit her nostrils--you notch
+her ears like a sow!"
+
+"By God, that's--"
+
+"Keep your opinion to yourself! It will be safest for you. I'll tie
+her to the bed. If she bleeds to death, is that my fault? I'll not cry,
+if she does. My friend, you'll help me in this thing--for MY sake
+--that's why you're here--I mightn't be able alone. If you flinch, I'll
+kill you. Do you understand that? And if I have to kill you, I'll kill
+her--and then I reckon nobody'll ever know much about who done this
+business."
+
+"Well, if it's got to be done, let's get at it. The quicker the
+better--I'm all in a shiver."
+
+"Do it NOW? And company there? Look here--I'll get suspicious of you,
+first thing you know. No--we'll wait till the lights are out--there's
+no hurry."
+
+Huck felt that a silence was going to ensue--a thing still more awful
+than any amount of murderous talk; so he held his breath and stepped
+gingerly back; planted his foot carefully and firmly, after balancing,
+one-legged, in a precarious way and almost toppling over, first on one
+side and then on the other. He took another step back, with the same
+elaboration and the same risks; then another and another, and--a twig
+snapped under his foot! His breath stopped and he listened. There was
+no sound--the stillness was perfect. His gratitude was measureless. Now
+he turned in his tracks, between the walls of sumach bushes--turned
+himself as carefully as if he were a ship--and then stepped quickly but
+cautiously along. When he emerged at the quarry he felt secure, and so
+he picked up his nimble heels and flew. Down, down he sped, till he
+reached the Welshman's. He banged at the door, and presently the heads
+of the old man and his two stalwart sons were thrust from windows.
+
+"What's the row there? Who's banging? What do you want?"
+
+"Let me in--quick! I'll tell everything."
+
+"Why, who are you?"
+
+"Huckleberry Finn--quick, let me in!"
+
+"Huckleberry Finn, indeed! It ain't a name to open many doors, I
+judge! But let him in, lads, and let's see what's the trouble."
+
+"Please don't ever tell I told you," were Huck's first words when he
+got in. "Please don't--I'd be killed, sure--but the widow's been good
+friends to me sometimes, and I want to tell--I WILL tell if you'll
+promise you won't ever say it was me."
+
+"By George, he HAS got something to tell, or he wouldn't act so!"
+exclaimed the old man; "out with it and nobody here'll ever tell, lad."
+
+Three minutes later the old man and his sons, well armed, were up the
+hill, and just entering the sumach path on tiptoe, their weapons in
+their hands. Huck accompanied them no further. He hid behind a great
+bowlder and fell to listening. There was a lagging, anxious silence,
+and then all of a sudden there was an explosion of firearms and a cry.
+
+Huck waited for no particulars. He sprang away and sped down the hill
+as fast as his legs could carry him.
+
+
+
+CHAPTER XXX
+
+AS the earliest suspicion of dawn appeared on Sunday morning, Huck
+came groping up the hill and rapped gently at the old Welshman's door.
+The inmates were asleep, but it was a sleep that was set on a
+hair-trigger, on account of the exciting episode of the night. A call
+came from a window:
+
+"Who's there!"
+
+Huck's scared voice answered in a low tone:
+
+"Please let me in! It's only Huck Finn!"
+
+"It's a name that can open this door night or day, lad!--and welcome!"
+
+These were strange words to the vagabond boy's ears, and the
+pleasantest he had ever heard. He could not recollect that the closing
+word had ever been applied in his case before. The door was quickly
+unlocked, and he entered. Huck was given a seat and the old man and his
+brace of tall sons speedily dressed themselves.
+
+"Now, my boy, I hope you're good and hungry, because breakfast will be
+ready as soon as the sun's up, and we'll have a piping hot one, too
+--make yourself easy about that! I and the boys hoped you'd turn up and
+stop here last night."
+
+"I was awful scared," said Huck, "and I run. I took out when the
+pistols went off, and I didn't stop for three mile. I've come now becuz
+I wanted to know about it, you know; and I come before daylight becuz I
+didn't want to run across them devils, even if they was dead."
+
+"Well, poor chap, you do look as if you'd had a hard night of it--but
+there's a bed here for you when you've had your breakfast. No, they
+ain't dead, lad--we are sorry enough for that. You see we knew right
+where to put our hands on them, by your description; so we crept along
+on tiptoe till we got within fifteen feet of them--dark as a cellar
+that sumach path was--and just then I found I was going to sneeze. It
+was the meanest kind of luck! I tried to keep it back, but no use
+--'twas bound to come, and it did come! I was in the lead with my pistol
+raised, and when the sneeze started those scoundrels a-rustling to get
+out of the path, I sung out, 'Fire boys!' and blazed away at the place
+where the rustling was. So did the boys. But they were off in a jiffy,
+those villains, and we after them, down through the woods. I judge we
+never touched them. They fired a shot apiece as they started, but their
+bullets whizzed by and didn't do us any harm. As soon as we lost the
+sound of their feet we quit chasing, and went down and stirred up the
+constables. They got a posse together, and went off to guard the river
+bank, and as soon as it is light the sheriff and a gang are going to
+beat up the woods. My boys will be with them presently. I wish we had
+some sort of description of those rascals--'twould help a good deal.
+But you couldn't see what they were like, in the dark, lad, I suppose?"
+
+"Oh yes; I saw them down-town and follered them."
+
+"Splendid! Describe them--describe them, my boy!"
+
+"One's the old deaf and dumb Spaniard that's ben around here once or
+twice, and t'other's a mean-looking, ragged--"
+
+"That's enough, lad, we know the men! Happened on them in the woods
+back of the widow's one day, and they slunk away. Off with you, boys,
+and tell the sheriff--get your breakfast to-morrow morning!"
+
+The Welshman's sons departed at once. As they were leaving the room
+Huck sprang up and exclaimed:
+
+"Oh, please don't tell ANYbody it was me that blowed on them! Oh,
+please!"
+
+"All right if you say it, Huck, but you ought to have the credit of
+what you did."
+
+"Oh no, no! Please don't tell!"
+
+When the young men were gone, the old Welshman said:
+
+"They won't tell--and I won't. But why don't you want it known?"
+
+Huck would not explain, further than to say that he already knew too
+much about one of those men and would not have the man know that he
+knew anything against him for the whole world--he would be killed for
+knowing it, sure.
+
+The old man promised secrecy once more, and said:
+
+"How did you come to follow these fellows, lad? Were they looking
+suspicious?"
+
+Huck was silent while he framed a duly cautious reply. Then he said:
+
+"Well, you see, I'm a kind of a hard lot,--least everybody says so,
+and I don't see nothing agin it--and sometimes I can't sleep much, on
+account of thinking about it and sort of trying to strike out a new way
+of doing. That was the way of it last night. I couldn't sleep, and so I
+come along up-street 'bout midnight, a-turning it all over, and when I
+got to that old shackly brick store by the Temperance Tavern, I backed
+up agin the wall to have another think. Well, just then along comes
+these two chaps slipping along close by me, with something under their
+arm, and I reckoned they'd stole it. One was a-smoking, and t'other one
+wanted a light; so they stopped right before me and the cigars lit up
+their faces and I see that the big one was the deaf and dumb Spaniard,
+by his white whiskers and the patch on his eye, and t'other one was a
+rusty, ragged-looking devil."
+
+"Could you see the rags by the light of the cigars?"
+
+This staggered Huck for a moment. Then he said:
+
+"Well, I don't know--but somehow it seems as if I did."
+
+"Then they went on, and you--"
+
+"Follered 'em--yes. That was it. I wanted to see what was up--they
+sneaked along so. I dogged 'em to the widder's stile, and stood in the
+dark and heard the ragged one beg for the widder, and the Spaniard
+swear he'd spile her looks just as I told you and your two--"
+
+"What! The DEAF AND DUMB man said all that!"
+
+Huck had made another terrible mistake! He was trying his best to keep
+the old man from getting the faintest hint of who the Spaniard might
+be, and yet his tongue seemed determined to get him into trouble in
+spite of all he could do. He made several efforts to creep out of his
+scrape, but the old man's eye was upon him and he made blunder after
+blunder. Presently the Welshman said:
+
+"My boy, don't be afraid of me. I wouldn't hurt a hair of your head
+for all the world. No--I'd protect you--I'd protect you. This Spaniard
+is not deaf and dumb; you've let that slip without intending it; you
+can't cover that up now. You know something about that Spaniard that
+you want to keep dark. Now trust me--tell me what it is, and trust me
+--I won't betray you."
+
+Huck looked into the old man's honest eyes a moment, then bent over
+and whispered in his ear:
+
+"'Tain't a Spaniard--it's Injun Joe!"
+
+The Welshman almost jumped out of his chair. In a moment he said:
+
+"It's all plain enough, now. When you talked about notching ears and
+slitting noses I judged that that was your own embellishment, because
+white men don't take that sort of revenge. But an Injun! That's a
+different matter altogether."
+
+During breakfast the talk went on, and in the course of it the old man
+said that the last thing which he and his sons had done, before going
+to bed, was to get a lantern and examine the stile and its vicinity for
+marks of blood. They found none, but captured a bulky bundle of--
+
+"Of WHAT?"
+
+If the words had been lightning they could not have leaped with a more
+stunning suddenness from Huck's blanched lips. His eyes were staring
+wide, now, and his breath suspended--waiting for the answer. The
+Welshman started--stared in return--three seconds--five seconds--ten
+--then replied:
+
+"Of burglar's tools. Why, what's the MATTER with you?"
+
+Huck sank back, panting gently, but deeply, unutterably grateful. The
+Welshman eyed him gravely, curiously--and presently said:
+
+"Yes, burglar's tools. That appears to relieve you a good deal. But
+what did give you that turn? What were YOU expecting we'd found?"
+
+Huck was in a close place--the inquiring eye was upon him--he would
+have given anything for material for a plausible answer--nothing
+suggested itself--the inquiring eye was boring deeper and deeper--a
+senseless reply offered--there was no time to weigh it, so at a venture
+he uttered it--feebly:
+
+"Sunday-school books, maybe."
+
+Poor Huck was too distressed to smile, but the old man laughed loud
+and joyously, shook up the details of his anatomy from head to foot,
+and ended by saying that such a laugh was money in a-man's pocket,
+because it cut down the doctor's bill like everything. Then he added:
+
+"Poor old chap, you're white and jaded--you ain't well a bit--no
+wonder you're a little flighty and off your balance. But you'll come
+out of it. Rest and sleep will fetch you out all right, I hope."
+
+Huck was irritated to think he had been such a goose and betrayed such
+a suspicious excitement, for he had dropped the idea that the parcel
+brought from the tavern was the treasure, as soon as he had heard the
+talk at the widow's stile. He had only thought it was not the treasure,
+however--he had not known that it wasn't--and so the suggestion of a
+captured bundle was too much for his self-possession. But on the whole
+he felt glad the little episode had happened, for now he knew beyond
+all question that that bundle was not THE bundle, and so his mind was
+at rest and exceedingly comfortable. In fact, everything seemed to be
+drifting just in the right direction, now; the treasure must be still
+in No. 2, the men would be captured and jailed that day, and he and Tom
+could seize the gold that night without any trouble or any fear of
+interruption.
+
+Just as breakfast was completed there was a knock at the door. Huck
+jumped for a hiding-place, for he had no mind to be connected even
+remotely with the late event. The Welshman admitted several ladies and
+gentlemen, among them the Widow Douglas, and noticed that groups of
+citizens were climbing up the hill--to stare at the stile. So the news
+had spread. The Welshman had to tell the story of the night to the
+visitors. The widow's gratitude for her preservation was outspoken.
+
+"Don't say a word about it, madam. There's another that you're more
+beholden to than you are to me and my boys, maybe, but he don't allow
+me to tell his name. We wouldn't have been there but for him."
+
+Of course this excited a curiosity so vast that it almost belittled
+the main matter--but the Welshman allowed it to eat into the vitals of
+his visitors, and through them be transmitted to the whole town, for he
+refused to part with his secret. When all else had been learned, the
+widow said:
+
+"I went to sleep reading in bed and slept straight through all that
+noise. Why didn't you come and wake me?"
+
+"We judged it warn't worth while. Those fellows warn't likely to come
+again--they hadn't any tools left to work with, and what was the use of
+waking you up and scaring you to death? My three negro men stood guard
+at your house all the rest of the night. They've just come back."
+
+More visitors came, and the story had to be told and retold for a
+couple of hours more.
+
+There was no Sabbath-school during day-school vacation, but everybody
+was early at church. The stirring event was well canvassed. News came
+that not a sign of the two villains had been yet discovered. When the
+sermon was finished, Judge Thatcher's wife dropped alongside of Mrs.
+Harper as she moved down the aisle with the crowd and said:
+
+"Is my Becky going to sleep all day? I just expected she would be
+tired to death."
+
+"Your Becky?"
+
+"Yes," with a startled look--"didn't she stay with you last night?"
+
+"Why, no."
+
+Mrs. Thatcher turned pale, and sank into a pew, just as Aunt Polly,
+talking briskly with a friend, passed by. Aunt Polly said:
+
+"Good-morning, Mrs. Thatcher. Good-morning, Mrs. Harper. I've got a
+boy that's turned up missing. I reckon my Tom stayed at your house last
+night--one of you. And now he's afraid to come to church. I've got to
+settle with him."
+
+Mrs. Thatcher shook her head feebly and turned paler than ever.
+
+"He didn't stay with us," said Mrs. Harper, beginning to look uneasy.
+A marked anxiety came into Aunt Polly's face.
+
+"Joe Harper, have you seen my Tom this morning?"
+
+"No'm."
+
+"When did you see him last?"
+
+Joe tried to remember, but was not sure he could say. The people had
+stopped moving out of church. Whispers passed along, and a boding
+uneasiness took possession of every countenance. Children were
+anxiously questioned, and young teachers. They all said they had not
+noticed whether Tom and Becky were on board the ferryboat on the
+homeward trip; it was dark; no one thought of inquiring if any one was
+missing. One young man finally blurted out his fear that they were
+still in the cave! Mrs. Thatcher swooned away. Aunt Polly fell to
+crying and wringing her hands.
+
+The alarm swept from lip to lip, from group to group, from street to
+street, and within five minutes the bells were wildly clanging and the
+whole town was up! The Cardiff Hill episode sank into instant
+insignificance, the burglars were forgotten, horses were saddled,
+skiffs were manned, the ferryboat ordered out, and before the horror
+was half an hour old, two hundred men were pouring down highroad and
+river toward the cave.
+
+All the long afternoon the village seemed empty and dead. Many women
+visited Aunt Polly and Mrs. Thatcher and tried to comfort them. They
+cried with them, too, and that was still better than words. All the
+tedious night the town waited for news; but when the morning dawned at
+last, all the word that came was, "Send more candles--and send food."
+Mrs. Thatcher was almost crazed; and Aunt Polly, also. Judge Thatcher
+sent messages of hope and encouragement from the cave, but they
+conveyed no real cheer.
+
+The old Welshman came home toward daylight, spattered with
+candle-grease, smeared with clay, and almost worn out. He found Huck
+still in the bed that had been provided for him, and delirious with
+fever. The physicians were all at the cave, so the Widow Douglas came
+and took charge of the patient. She said she would do her best by him,
+because, whether he was good, bad, or indifferent, he was the Lord's,
+and nothing that was the Lord's was a thing to be neglected. The
+Welshman said Huck had good spots in him, and the widow said:
+
+"You can depend on it. That's the Lord's mark. He don't leave it off.
+He never does. Puts it somewhere on every creature that comes from his
+hands."
+
+Early in the forenoon parties of jaded men began to straggle into the
+village, but the strongest of the citizens continued searching. All the
+news that could be gained was that remotenesses of the cavern were
+being ransacked that had never been visited before; that every corner
+and crevice was going to be thoroughly searched; that wherever one
+wandered through the maze of passages, lights were to be seen flitting
+hither and thither in the distance, and shoutings and pistol-shots sent
+their hollow reverberations to the ear down the sombre aisles. In one
+place, far from the section usually traversed by tourists, the names
+"BECKY & TOM" had been found traced upon the rocky wall with
+candle-smoke, and near at hand a grease-soiled bit of ribbon. Mrs.
+Thatcher recognized the ribbon and cried over it. She said it was the
+last relic she should ever have of her child; and that no other memorial
+of her could ever be so precious, because this one parted latest from
+the living body before the awful death came. Some said that now and
+then, in the cave, a far-away speck of light would glimmer, and then a
+glorious shout would burst forth and a score of men go trooping down the
+echoing aisle--and then a sickening disappointment always followed; the
+children were not there; it was only a searcher's light.
+
+Three dreadful days and nights dragged their tedious hours along, and
+the village sank into a hopeless stupor. No one had heart for anything.
+The accidental discovery, just made, that the proprietor of the
+Temperance Tavern kept liquor on his premises, scarcely fluttered the
+public pulse, tremendous as the fact was. In a lucid interval, Huck
+feebly led up to the subject of taverns, and finally asked--dimly
+dreading the worst--if anything had been discovered at the Temperance
+Tavern since he had been ill.
+
+"Yes," said the widow.
+
+Huck started up in bed, wild-eyed:
+
+"What? What was it?"
+
+"Liquor!--and the place has been shut up. Lie down, child--what a turn
+you did give me!"
+
+"Only tell me just one thing--only just one--please! Was it Tom Sawyer
+that found it?"
+
+The widow burst into tears. "Hush, hush, child, hush! I've told you
+before, you must NOT talk. You are very, very sick!"
+
+Then nothing but liquor had been found; there would have been a great
+powwow if it had been the gold. So the treasure was gone forever--gone
+forever! But what could she be crying about? Curious that she should
+cry.
+
+These thoughts worked their dim way through Huck's mind, and under the
+weariness they gave him he fell asleep. The widow said to herself:
+
+"There--he's asleep, poor wreck. Tom Sawyer find it! Pity but somebody
+could find Tom Sawyer! Ah, there ain't many left, now, that's got hope
+enough, or strength enough, either, to go on searching."
+
+
+
+CHAPTER XXXI
+
+NOW to return to Tom and Becky's share in the picnic. They tripped
+along the murky aisles with the rest of the company, visiting the
+familiar wonders of the cave--wonders dubbed with rather
+over-descriptive names, such as "The Drawing-Room," "The Cathedral,"
+"Aladdin's Palace," and so on. Presently the hide-and-seek frolicking
+began, and Tom and Becky engaged in it with zeal until the exertion
+began to grow a trifle wearisome; then they wandered down a sinuous
+avenue holding their candles aloft and reading the tangled web-work of
+names, dates, post-office addresses, and mottoes with which the rocky
+walls had been frescoed (in candle-smoke). Still drifting along and
+talking, they scarcely noticed that they were now in a part of the cave
+whose walls were not frescoed. They smoked their own names under an
+overhanging shelf and moved on. Presently they came to a place where a
+little stream of water, trickling over a ledge and carrying a limestone
+sediment with it, had, in the slow-dragging ages, formed a laced and
+ruffled Niagara in gleaming and imperishable stone. Tom squeezed his
+small body behind it in order to illuminate it for Becky's
+gratification. He found that it curtained a sort of steep natural
+stairway which was enclosed between narrow walls, and at once the
+ambition to be a discoverer seized him. Becky responded to his call,
+and they made a smoke-mark for future guidance, and started upon their
+quest. They wound this way and that, far down into the secret depths of
+the cave, made another mark, and branched off in search of novelties to
+tell the upper world about. In one place they found a spacious cavern,
+from whose ceiling depended a multitude of shining stalactites of the
+length and circumference of a man's leg; they walked all about it,
+wondering and admiring, and presently left it by one of the numerous
+passages that opened into it. This shortly brought them to a bewitching
+spring, whose basin was incrusted with a frostwork of glittering
+crystals; it was in the midst of a cavern whose walls were supported by
+many fantastic pillars which had been formed by the joining of great
+stalactites and stalagmites together, the result of the ceaseless
+water-drip of centuries. Under the roof vast knots of bats had packed
+themselves together, thousands in a bunch; the lights disturbed the
+creatures and they came flocking down by hundreds, squeaking and
+darting furiously at the candles. Tom knew their ways and the danger of
+this sort of conduct. He seized Becky's hand and hurried her into the
+first corridor that offered; and none too soon, for a bat struck
+Becky's light out with its wing while she was passing out of the
+cavern. The bats chased the children a good distance; but the fugitives
+plunged into every new passage that offered, and at last got rid of the
+perilous things. Tom found a subterranean lake, shortly, which
+stretched its dim length away until its shape was lost in the shadows.
+He wanted to explore its borders, but concluded that it would be best
+to sit down and rest awhile, first. Now, for the first time, the deep
+stillness of the place laid a clammy hand upon the spirits of the
+children. Becky said:
+
+"Why, I didn't notice, but it seems ever so long since I heard any of
+the others."
+
+"Come to think, Becky, we are away down below them--and I don't know
+how far away north, or south, or east, or whichever it is. We couldn't
+hear them here."
+
+Becky grew apprehensive.
+
+"I wonder how long we've been down here, Tom? We better start back."
+
+"Yes, I reckon we better. P'raps we better."
+
+"Can you find the way, Tom? It's all a mixed-up crookedness to me."
+
+"I reckon I could find it--but then the bats. If they put our candles
+out it will be an awful fix. Let's try some other way, so as not to go
+through there."
+
+"Well. But I hope we won't get lost. It would be so awful!" and the
+girl shuddered at the thought of the dreadful possibilities.
+
+They started through a corridor, and traversed it in silence a long
+way, glancing at each new opening, to see if there was anything
+familiar about the look of it; but they were all strange. Every time
+Tom made an examination, Becky would watch his face for an encouraging
+sign, and he would say cheerily:
+
+"Oh, it's all right. This ain't the one, but we'll come to it right
+away!"
+
+But he felt less and less hopeful with each failure, and presently
+began to turn off into diverging avenues at sheer random, in desperate
+hope of finding the one that was wanted. He still said it was "all
+right," but there was such a leaden dread at his heart that the words
+had lost their ring and sounded just as if he had said, "All is lost!"
+Becky clung to his side in an anguish of fear, and tried hard to keep
+back the tears, but they would come. At last she said:
+
+"Oh, Tom, never mind the bats, let's go back that way! We seem to get
+worse and worse off all the time."
+
+"Listen!" said he.
+
+Profound silence; silence so deep that even their breathings were
+conspicuous in the hush. Tom shouted. The call went echoing down the
+empty aisles and died out in the distance in a faint sound that
+resembled a ripple of mocking laughter.
+
+"Oh, don't do it again, Tom, it is too horrid," said Becky.
+
+"It is horrid, but I better, Becky; they might hear us, you know," and
+he shouted again.
+
+The "might" was even a chillier horror than the ghostly laughter, it
+so confessed a perishing hope. The children stood still and listened;
+but there was no result. Tom turned upon the back track at once, and
+hurried his steps. It was but a little while before a certain
+indecision in his manner revealed another fearful fact to Becky--he
+could not find his way back!
+
+"Oh, Tom, you didn't make any marks!"
+
+"Becky, I was such a fool! Such a fool! I never thought we might want
+to come back! No--I can't find the way. It's all mixed up."
+
+"Tom, Tom, we're lost! we're lost! We never can get out of this awful
+place! Oh, why DID we ever leave the others!"
+
+She sank to the ground and burst into such a frenzy of crying that Tom
+was appalled with the idea that she might die, or lose her reason. He
+sat down by her and put his arms around her; she buried her face in his
+bosom, she clung to him, she poured out her terrors, her unavailing
+regrets, and the far echoes turned them all to jeering laughter. Tom
+begged her to pluck up hope again, and she said she could not. He fell
+to blaming and abusing himself for getting her into this miserable
+situation; this had a better effect. She said she would try to hope
+again, she would get up and follow wherever he might lead if only he
+would not talk like that any more. For he was no more to blame than
+she, she said.
+
+So they moved on again--aimlessly--simply at random--all they could do
+was to move, keep moving. For a little while, hope made a show of
+reviving--not with any reason to back it, but only because it is its
+nature to revive when the spring has not been taken out of it by age
+and familiarity with failure.
+
+By-and-by Tom took Becky's candle and blew it out. This economy meant
+so much! Words were not needed. Becky understood, and her hope died
+again. She knew that Tom had a whole candle and three or four pieces in
+his pockets--yet he must economize.
+
+By-and-by, fatigue began to assert its claims; the children tried to
+pay attention, for it was dreadful to think of sitting down when time
+was grown to be so precious, moving, in some direction, in any
+direction, was at least progress and might bear fruit; but to sit down
+was to invite death and shorten its pursuit.
+
+At last Becky's frail limbs refused to carry her farther. She sat
+down. Tom rested with her, and they talked of home, and the friends
+there, and the comfortable beds and, above all, the light! Becky cried,
+and Tom tried to think of some way of comforting her, but all his
+encouragements were grown threadbare with use, and sounded like
+sarcasms. Fatigue bore so heavily upon Becky that she drowsed off to
+sleep. Tom was grateful. He sat looking into her drawn face and saw it
+grow smooth and natural under the influence of pleasant dreams; and
+by-and-by a smile dawned and rested there. The peaceful face reflected
+somewhat of peace and healing into his own spirit, and his thoughts
+wandered away to bygone times and dreamy memories. While he was deep in
+his musings, Becky woke up with a breezy little laugh--but it was
+stricken dead upon her lips, and a groan followed it.
+
+"Oh, how COULD I sleep! I wish I never, never had waked! No! No, I
+don't, Tom! Don't look so! I won't say it again."
+
+"I'm glad you've slept, Becky; you'll feel rested, now, and we'll find
+the way out."
+
+"We can try, Tom; but I've seen such a beautiful country in my dream.
+I reckon we are going there."
+
+"Maybe not, maybe not. Cheer up, Becky, and let's go on trying."
+
+They rose up and wandered along, hand in hand and hopeless. They tried
+to estimate how long they had been in the cave, but all they knew was
+that it seemed days and weeks, and yet it was plain that this could not
+be, for their candles were not gone yet. A long time after this--they
+could not tell how long--Tom said they must go softly and listen for
+dripping water--they must find a spring. They found one presently, and
+Tom said it was time to rest again. Both were cruelly tired, yet Becky
+said she thought she could go a little farther. She was surprised to
+hear Tom dissent. She could not understand it. They sat down, and Tom
+fastened his candle to the wall in front of them with some clay.
+Thought was soon busy; nothing was said for some time. Then Becky broke
+the silence:
+
+"Tom, I am so hungry!"
+
+Tom took something out of his pocket.
+
+"Do you remember this?" said he.
+
+Becky almost smiled.
+
+"It's our wedding-cake, Tom."
+
+"Yes--I wish it was as big as a barrel, for it's all we've got."
+
+"I saved it from the picnic for us to dream on, Tom, the way grown-up
+people do with wedding-cake--but it'll be our--"
+
+She dropped the sentence where it was. Tom divided the cake and Becky
+ate with good appetite, while Tom nibbled at his moiety. There was
+abundance of cold water to finish the feast with. By-and-by Becky
+suggested that they move on again. Tom was silent a moment. Then he
+said:
+
+"Becky, can you bear it if I tell you something?"
+
+Becky's face paled, but she thought she could.
+
+"Well, then, Becky, we must stay here, where there's water to drink.
+That little piece is our last candle!"
+
+Becky gave loose to tears and wailings. Tom did what he could to
+comfort her, but with little effect. At length Becky said:
+
+"Tom!"
+
+"Well, Becky?"
+
+"They'll miss us and hunt for us!"
+
+"Yes, they will! Certainly they will!"
+
+"Maybe they're hunting for us now, Tom."
+
+"Why, I reckon maybe they are. I hope they are."
+
+"When would they miss us, Tom?"
+
+"When they get back to the boat, I reckon."
+
+"Tom, it might be dark then--would they notice we hadn't come?"
+
+"I don't know. But anyway, your mother would miss you as soon as they
+got home."
+
+A frightened look in Becky's face brought Tom to his senses and he saw
+that he had made a blunder. Becky was not to have gone home that night!
+The children became silent and thoughtful. In a moment a new burst of
+grief from Becky showed Tom that the thing in his mind had struck hers
+also--that the Sabbath morning might be half spent before Mrs. Thatcher
+discovered that Becky was not at Mrs. Harper's.
+
+The children fastened their eyes upon their bit of candle and watched
+it melt slowly and pitilessly away; saw the half inch of wick stand
+alone at last; saw the feeble flame rise and fall, climb the thin
+column of smoke, linger at its top a moment, and then--the horror of
+utter darkness reigned!
+
+How long afterward it was that Becky came to a slow consciousness that
+she was crying in Tom's arms, neither could tell. All that they knew
+was, that after what seemed a mighty stretch of time, both awoke out of
+a dead stupor of sleep and resumed their miseries once more. Tom said
+it might be Sunday, now--maybe Monday. He tried to get Becky to talk,
+but her sorrows were too oppressive, all her hopes were gone. Tom said
+that they must have been missed long ago, and no doubt the search was
+going on. He would shout and maybe some one would come. He tried it;
+but in the darkness the distant echoes sounded so hideously that he
+tried it no more.
+
+The hours wasted away, and hunger came to torment the captives again.
+A portion of Tom's half of the cake was left; they divided and ate it.
+But they seemed hungrier than before. The poor morsel of food only
+whetted desire.
+
+By-and-by Tom said:
+
+"SH! Did you hear that?"
+
+Both held their breath and listened. There was a sound like the
+faintest, far-off shout. Instantly Tom answered it, and leading Becky
+by the hand, started groping down the corridor in its direction.
+Presently he listened again; again the sound was heard, and apparently
+a little nearer.
+
+"It's them!" said Tom; "they're coming! Come along, Becky--we're all
+right now!"
+
+The joy of the prisoners was almost overwhelming. Their speed was
+slow, however, because pitfalls were somewhat common, and had to be
+guarded against. They shortly came to one and had to stop. It might be
+three feet deep, it might be a hundred--there was no passing it at any
+rate. Tom got down on his breast and reached as far down as he could.
+No bottom. They must stay there and wait until the searchers came. They
+listened; evidently the distant shoutings were growing more distant! a
+moment or two more and they had gone altogether. The heart-sinking
+misery of it! Tom whooped until he was hoarse, but it was of no use. He
+talked hopefully to Becky; but an age of anxious waiting passed and no
+sounds came again.
+
+The children groped their way back to the spring. The weary time
+dragged on; they slept again, and awoke famished and woe-stricken. Tom
+believed it must be Tuesday by this time.
+
+Now an idea struck him. There were some side passages near at hand. It
+would be better to explore some of these than bear the weight of the
+heavy time in idleness. He took a kite-line from his pocket, tied it to
+a projection, and he and Becky started, Tom in the lead, unwinding the
+line as he groped along. At the end of twenty steps the corridor ended
+in a "jumping-off place." Tom got down on his knees and felt below, and
+then as far around the corner as he could reach with his hands
+conveniently; he made an effort to stretch yet a little farther to the
+right, and at that moment, not twenty yards away, a human hand, holding
+a candle, appeared from behind a rock! Tom lifted up a glorious shout,
+and instantly that hand was followed by the body it belonged to--Injun
+Joe's! Tom was paralyzed; he could not move. He was vastly gratified
+the next moment, to see the "Spaniard" take to his heels and get
+himself out of sight. Tom wondered that Joe had not recognized his
+voice and come over and killed him for testifying in court. But the
+echoes must have disguised the voice. Without doubt, that was it, he
+reasoned. Tom's fright weakened every muscle in his body. He said to
+himself that if he had strength enough to get back to the spring he
+would stay there, and nothing should tempt him to run the risk of
+meeting Injun Joe again. He was careful to keep from Becky what it was
+he had seen. He told her he had only shouted "for luck."
+
+But hunger and wretchedness rise superior to fears in the long run.
+Another tedious wait at the spring and another long sleep brought
+changes. The children awoke tortured with a raging hunger. Tom believed
+that it must be Wednesday or Thursday or even Friday or Saturday, now,
+and that the search had been given over. He proposed to explore another
+passage. He felt willing to risk Injun Joe and all other terrors. But
+Becky was very weak. She had sunk into a dreary apathy and would not be
+roused. She said she would wait, now, where she was, and die--it would
+not be long. She told Tom to go with the kite-line and explore if he
+chose; but she implored him to come back every little while and speak
+to her; and she made him promise that when the awful time came, he
+would stay by her and hold her hand until all was over.
+
+Tom kissed her, with a choking sensation in his throat, and made a
+show of being confident of finding the searchers or an escape from the
+cave; then he took the kite-line in his hand and went groping down one
+of the passages on his hands and knees, distressed with hunger and sick
+with bodings of coming doom.
+
+
+
+CHAPTER XXXII
+
+TUESDAY afternoon came, and waned to the twilight. The village of St.
+Petersburg still mourned. The lost children had not been found. Public
+prayers had been offered up for them, and many and many a private
+prayer that had the petitioner's whole heart in it; but still no good
+news came from the cave. The majority of the searchers had given up the
+quest and gone back to their daily avocations, saying that it was plain
+the children could never be found. Mrs. Thatcher was very ill, and a
+great part of the time delirious. People said it was heartbreaking to
+hear her call her child, and raise her head and listen a whole minute
+at a time, then lay it wearily down again with a moan. Aunt Polly had
+drooped into a settled melancholy, and her gray hair had grown almost
+white. The village went to its rest on Tuesday night, sad and forlorn.
+
+Away in the middle of the night a wild peal burst from the village
+bells, and in a moment the streets were swarming with frantic half-clad
+people, who shouted, "Turn out! turn out! they're found! they're
+found!" Tin pans and horns were added to the din, the population massed
+itself and moved toward the river, met the children coming in an open
+carriage drawn by shouting citizens, thronged around it, joined its
+homeward march, and swept magnificently up the main street roaring
+huzzah after huzzah!
+
+The village was illuminated; nobody went to bed again; it was the
+greatest night the little town had ever seen. During the first half-hour
+a procession of villagers filed through Judge Thatcher's house, seized
+the saved ones and kissed them, squeezed Mrs. Thatcher's hand, tried to
+speak but couldn't--and drifted out raining tears all over the place.
+
+Aunt Polly's happiness was complete, and Mrs. Thatcher's nearly so. It
+would be complete, however, as soon as the messenger dispatched with
+the great news to the cave should get the word to her husband. Tom lay
+upon a sofa with an eager auditory about him and told the history of
+the wonderful adventure, putting in many striking additions to adorn it
+withal; and closed with a description of how he left Becky and went on
+an exploring expedition; how he followed two avenues as far as his
+kite-line would reach; how he followed a third to the fullest stretch of
+the kite-line, and was about to turn back when he glimpsed a far-off
+speck that looked like daylight; dropped the line and groped toward it,
+pushed his head and shoulders through a small hole, and saw the broad
+Mississippi rolling by! And if it had only happened to be night he would
+not have seen that speck of daylight and would not have explored that
+passage any more! He told how he went back for Becky and broke the good
+news and she told him not to fret her with such stuff, for she was
+tired, and knew she was going to die, and wanted to. He described how he
+labored with her and convinced her; and how she almost died for joy when
+she had groped to where she actually saw the blue speck of daylight; how
+he pushed his way out at the hole and then helped her out; how they sat
+there and cried for gladness; how some men came along in a skiff and Tom
+hailed them and told them their situation and their famished condition;
+how the men didn't believe the wild tale at first, "because," said they,
+"you are five miles down the river below the valley the cave is in"
+--then took them aboard, rowed to a house, gave them supper, made them
+rest till two or three hours after dark and then brought them home.
+
+Before day-dawn, Judge Thatcher and the handful of searchers with him
+were tracked out, in the cave, by the twine clews they had strung
+behind them, and informed of the great news.
+
+Three days and nights of toil and hunger in the cave were not to be
+shaken off at once, as Tom and Becky soon discovered. They were
+bedridden all of Wednesday and Thursday, and seemed to grow more and
+more tired and worn, all the time. Tom got about, a little, on
+Thursday, was down-town Friday, and nearly as whole as ever Saturday;
+but Becky did not leave her room until Sunday, and then she looked as
+if she had passed through a wasting illness.
+
+Tom learned of Huck's sickness and went to see him on Friday, but
+could not be admitted to the bedroom; neither could he on Saturday or
+Sunday. He was admitted daily after that, but was warned to keep still
+about his adventure and introduce no exciting topic. The Widow Douglas
+stayed by to see that he obeyed. At home Tom learned of the Cardiff
+Hill event; also that the "ragged man's" body had eventually been found
+in the river near the ferry-landing; he had been drowned while trying
+to escape, perhaps.
+
+About a fortnight after Tom's rescue from the cave, he started off to
+visit Huck, who had grown plenty strong enough, now, to hear exciting
+talk, and Tom had some that would interest him, he thought. Judge
+Thatcher's house was on Tom's way, and he stopped to see Becky. The
+Judge and some friends set Tom to talking, and some one asked him
+ironically if he wouldn't like to go to the cave again. Tom said he
+thought he wouldn't mind it. The Judge said:
+
+"Well, there are others just like you, Tom, I've not the least doubt.
+But we have taken care of that. Nobody will get lost in that cave any
+more."
+
+"Why?"
+
+"Because I had its big door sheathed with boiler iron two weeks ago,
+and triple-locked--and I've got the keys."
+
+Tom turned as white as a sheet.
+
+"What's the matter, boy! Here, run, somebody! Fetch a glass of water!"
+
+The water was brought and thrown into Tom's face.
+
+"Ah, now you're all right. What was the matter with you, Tom?"
+
+"Oh, Judge, Injun Joe's in the cave!"
+
+
+
+CHAPTER XXXIII
+
+WITHIN a few minutes the news had spread, and a dozen skiff-loads of
+men were on their way to McDougal's cave, and the ferryboat, well
+filled with passengers, soon followed. Tom Sawyer was in the skiff that
+bore Judge Thatcher.
+
+When the cave door was unlocked, a sorrowful sight presented itself in
+the dim twilight of the place. Injun Joe lay stretched upon the ground,
+dead, with his face close to the crack of the door, as if his longing
+eyes had been fixed, to the latest moment, upon the light and the cheer
+of the free world outside. Tom was touched, for he knew by his own
+experience how this wretch had suffered. His pity was moved, but
+nevertheless he felt an abounding sense of relief and security, now,
+which revealed to him in a degree which he had not fully appreciated
+before how vast a weight of dread had been lying upon him since the day
+he lifted his voice against this bloody-minded outcast.
+
+Injun Joe's bowie-knife lay close by, its blade broken in two. The
+great foundation-beam of the door had been chipped and hacked through,
+with tedious labor; useless labor, too, it was, for the native rock
+formed a sill outside it, and upon that stubborn material the knife had
+wrought no effect; the only damage done was to the knife itself. But if
+there had been no stony obstruction there the labor would have been
+useless still, for if the beam had been wholly cut away Injun Joe could
+not have squeezed his body under the door, and he knew it. So he had
+only hacked that place in order to be doing something--in order to pass
+the weary time--in order to employ his tortured faculties. Ordinarily
+one could find half a dozen bits of candle stuck around in the crevices
+of this vestibule, left there by tourists; but there were none now. The
+prisoner had searched them out and eaten them. He had also contrived to
+catch a few bats, and these, also, he had eaten, leaving only their
+claws. The poor unfortunate had starved to death. In one place, near at
+hand, a stalagmite had been slowly growing up from the ground for ages,
+builded by the water-drip from a stalactite overhead. The captive had
+broken off the stalagmite, and upon the stump had placed a stone,
+wherein he had scooped a shallow hollow to catch the precious drop
+that fell once in every three minutes with the dreary regularity of a
+clock-tick--a dessertspoonful once in four and twenty hours. That drop
+was falling when the Pyramids were new; when Troy fell; when the
+foundations of Rome were laid; when Christ was crucified; when the
+Conqueror created the British empire; when Columbus sailed; when the
+massacre at Lexington was "news." It is falling now; it will still be
+falling when all these things shall have sunk down the afternoon of
+history, and the twilight of tradition, and been swallowed up in the
+thick night of oblivion. Has everything a purpose and a mission? Did
+this drop fall patiently during five thousand years to be ready for
+this flitting human insect's need? and has it another important object
+to accomplish ten thousand years to come? No matter. It is many and
+many a year since the hapless half-breed scooped out the stone to catch
+the priceless drops, but to this day the tourist stares longest at that
+pathetic stone and that slow-dropping water when he comes to see the
+wonders of McDougal's cave. Injun Joe's cup stands first in the list of
+the cavern's marvels; even "Aladdin's Palace" cannot rival it.
+
+Injun Joe was buried near the mouth of the cave; and people flocked
+there in boats and wagons from the towns and from all the farms and
+hamlets for seven miles around; they brought their children, and all
+sorts of provisions, and confessed that they had had almost as
+satisfactory a time at the funeral as they could have had at the
+hanging.
+
+This funeral stopped the further growth of one thing--the petition to
+the governor for Injun Joe's pardon. The petition had been largely
+signed; many tearful and eloquent meetings had been held, and a
+committee of sappy women been appointed to go in deep mourning and wail
+around the governor, and implore him to be a merciful ass and trample
+his duty under foot. Injun Joe was believed to have killed five
+citizens of the village, but what of that? If he had been Satan himself
+there would have been plenty of weaklings ready to scribble their names
+to a pardon-petition, and drip a tear on it from their permanently
+impaired and leaky water-works.
+
+The morning after the funeral Tom took Huck to a private place to have
+an important talk. Huck had learned all about Tom's adventure from the
+Welshman and the Widow Douglas, by this time, but Tom said he reckoned
+there was one thing they had not told him; that thing was what he
+wanted to talk about now. Huck's face saddened. He said:
+
+"I know what it is. You got into No. 2 and never found anything but
+whiskey. Nobody told me it was you; but I just knowed it must 'a' ben
+you, soon as I heard 'bout that whiskey business; and I knowed you
+hadn't got the money becuz you'd 'a' got at me some way or other and
+told me even if you was mum to everybody else. Tom, something's always
+told me we'd never get holt of that swag."
+
+"Why, Huck, I never told on that tavern-keeper. YOU know his tavern
+was all right the Saturday I went to the picnic. Don't you remember you
+was to watch there that night?"
+
+"Oh yes! Why, it seems 'bout a year ago. It was that very night that I
+follered Injun Joe to the widder's."
+
+"YOU followed him?"
+
+"Yes--but you keep mum. I reckon Injun Joe's left friends behind him,
+and I don't want 'em souring on me and doing me mean tricks. If it
+hadn't ben for me he'd be down in Texas now, all right."
+
+Then Huck told his entire adventure in confidence to Tom, who had only
+heard of the Welshman's part of it before.
+
+"Well," said Huck, presently, coming back to the main question,
+"whoever nipped the whiskey in No. 2, nipped the money, too, I reckon
+--anyways it's a goner for us, Tom."
+
+"Huck, that money wasn't ever in No. 2!"
+
+"What!" Huck searched his comrade's face keenly. "Tom, have you got on
+the track of that money again?"
+
+"Huck, it's in the cave!"
+
+Huck's eyes blazed.
+
+"Say it again, Tom."
+
+"The money's in the cave!"
+
+"Tom--honest injun, now--is it fun, or earnest?"
+
+"Earnest, Huck--just as earnest as ever I was in my life. Will you go
+in there with me and help get it out?"
+
+"I bet I will! I will if it's where we can blaze our way to it and not
+get lost."
+
+"Huck, we can do that without the least little bit of trouble in the
+world."
+
+"Good as wheat! What makes you think the money's--"
+
+"Huck, you just wait till we get in there. If we don't find it I'll
+agree to give you my drum and every thing I've got in the world. I
+will, by jings."
+
+"All right--it's a whiz. When do you say?"
+
+"Right now, if you say it. Are you strong enough?"
+
+"Is it far in the cave? I ben on my pins a little, three or four days,
+now, but I can't walk more'n a mile, Tom--least I don't think I could."
+
+"It's about five mile into there the way anybody but me would go,
+Huck, but there's a mighty short cut that they don't anybody but me
+know about. Huck, I'll take you right to it in a skiff. I'll float the
+skiff down there, and I'll pull it back again all by myself. You
+needn't ever turn your hand over."
+
+"Less start right off, Tom."
+
+"All right. We want some bread and meat, and our pipes, and a little
+bag or two, and two or three kite-strings, and some of these
+new-fangled things they call lucifer matches. I tell you, many's
+the time I wished I had some when I was in there before."
+
+A trifle after noon the boys borrowed a small skiff from a citizen who
+was absent, and got under way at once. When they were several miles
+below "Cave Hollow," Tom said:
+
+"Now you see this bluff here looks all alike all the way down from the
+cave hollow--no houses, no wood-yards, bushes all alike. But do you see
+that white place up yonder where there's been a landslide? Well, that's
+one of my marks. We'll get ashore, now."
+
+They landed.
+
+"Now, Huck, where we're a-standing you could touch that hole I got out
+of with a fishing-pole. See if you can find it."
+
+Huck searched all the place about, and found nothing. Tom proudly
+marched into a thick clump of sumach bushes and said:
+
+"Here you are! Look at it, Huck; it's the snuggest hole in this
+country. You just keep mum about it. All along I've been wanting to be
+a robber, but I knew I'd got to have a thing like this, and where to
+run across it was the bother. We've got it now, and we'll keep it
+quiet, only we'll let Joe Harper and Ben Rogers in--because of course
+there's got to be a Gang, or else there wouldn't be any style about it.
+Tom Sawyer's Gang--it sounds splendid, don't it, Huck?"
+
+"Well, it just does, Tom. And who'll we rob?"
+
+"Oh, most anybody. Waylay people--that's mostly the way."
+
+"And kill them?"
+
+"No, not always. Hive them in the cave till they raise a ransom."
+
+"What's a ransom?"
+
+"Money. You make them raise all they can, off'n their friends; and
+after you've kept them a year, if it ain't raised then you kill them.
+That's the general way. Only you don't kill the women. You shut up the
+women, but you don't kill them. They're always beautiful and rich, and
+awfully scared. You take their watches and things, but you always take
+your hat off and talk polite. They ain't anybody as polite as robbers
+--you'll see that in any book. Well, the women get to loving you, and
+after they've been in the cave a week or two weeks they stop crying and
+after that you couldn't get them to leave. If you drove them out they'd
+turn right around and come back. It's so in all the books."
+
+"Why, it's real bully, Tom. I believe it's better'n to be a pirate."
+
+"Yes, it's better in some ways, because it's close to home and
+circuses and all that."
+
+By this time everything was ready and the boys entered the hole, Tom
+in the lead. They toiled their way to the farther end of the tunnel,
+then made their spliced kite-strings fast and moved on. A few steps
+brought them to the spring, and Tom felt a shudder quiver all through
+him. He showed Huck the fragment of candle-wick perched on a lump of
+clay against the wall, and described how he and Becky had watched the
+flame struggle and expire.
+
+The boys began to quiet down to whispers, now, for the stillness and
+gloom of the place oppressed their spirits. They went on, and presently
+entered and followed Tom's other corridor until they reached the
+"jumping-off place." The candles revealed the fact that it was not
+really a precipice, but only a steep clay hill twenty or thirty feet
+high. Tom whispered:
+
+"Now I'll show you something, Huck."
+
+He held his candle aloft and said:
+
+"Look as far around the corner as you can. Do you see that? There--on
+the big rock over yonder--done with candle-smoke."
+
+"Tom, it's a CROSS!"
+
+"NOW where's your Number Two? 'UNDER THE CROSS,' hey? Right yonder's
+where I saw Injun Joe poke up his candle, Huck!"
+
+Huck stared at the mystic sign awhile, and then said with a shaky voice:
+
+"Tom, less git out of here!"
+
+"What! and leave the treasure?"
+
+"Yes--leave it. Injun Joe's ghost is round about there, certain."
+
+"No it ain't, Huck, no it ain't. It would ha'nt the place where he
+died--away out at the mouth of the cave--five mile from here."
+
+"No, Tom, it wouldn't. It would hang round the money. I know the ways
+of ghosts, and so do you."
+
+Tom began to fear that Huck was right. Misgivings gathered in his
+mind. But presently an idea occurred to him--
+
+"Lookyhere, Huck, what fools we're making of ourselves! Injun Joe's
+ghost ain't a going to come around where there's a cross!"
+
+The point was well taken. It had its effect.
+
+"Tom, I didn't think of that. But that's so. It's luck for us, that
+cross is. I reckon we'll climb down there and have a hunt for that box."
+
+Tom went first, cutting rude steps in the clay hill as he descended.
+Huck followed. Four avenues opened out of the small cavern which the
+great rock stood in. The boys examined three of them with no result.
+They found a small recess in the one nearest the base of the rock, with
+a pallet of blankets spread down in it; also an old suspender, some
+bacon rind, and the well-gnawed bones of two or three fowls. But there
+was no money-box. The lads searched and researched this place, but in
+vain. Tom said:
+
+"He said UNDER the cross. Well, this comes nearest to being under the
+cross. It can't be under the rock itself, because that sets solid on
+the ground."
+
+They searched everywhere once more, and then sat down discouraged.
+Huck could suggest nothing. By-and-by Tom said:
+
+"Lookyhere, Huck, there's footprints and some candle-grease on the
+clay about one side of this rock, but not on the other sides. Now,
+what's that for? I bet you the money IS under the rock. I'm going to
+dig in the clay."
+
+"That ain't no bad notion, Tom!" said Huck with animation.
+
+Tom's "real Barlow" was out at once, and he had not dug four inches
+before he struck wood.
+
+"Hey, Huck!--you hear that?"
+
+Huck began to dig and scratch now. Some boards were soon uncovered and
+removed. They had concealed a natural chasm which led under the rock.
+Tom got into this and held his candle as far under the rock as he
+could, but said he could not see to the end of the rift. He proposed to
+explore. He stooped and passed under; the narrow way descended
+gradually. He followed its winding course, first to the right, then to
+the left, Huck at his heels. Tom turned a short curve, by-and-by, and
+exclaimed:
+
+"My goodness, Huck, lookyhere!"
+
+It was the treasure-box, sure enough, occupying a snug little cavern,
+along with an empty powder-keg, a couple of guns in leather cases, two
+or three pairs of old moccasins, a leather belt, and some other rubbish
+well soaked with the water-drip.
+
+"Got it at last!" said Huck, ploughing among the tarnished coins with
+his hand. "My, but we're rich, Tom!"
+
+"Huck, I always reckoned we'd get it. It's just too good to believe,
+but we HAVE got it, sure! Say--let's not fool around here. Let's snake
+it out. Lemme see if I can lift the box."
+
+It weighed about fifty pounds. Tom could lift it, after an awkward
+fashion, but could not carry it conveniently.
+
+"I thought so," he said; "THEY carried it like it was heavy, that day
+at the ha'nted house. I noticed that. I reckon I was right to think of
+fetching the little bags along."
+
+The money was soon in the bags and the boys took it up to the cross
+rock.
+
+"Now less fetch the guns and things," said Huck.
+
+"No, Huck--leave them there. They're just the tricks to have when we
+go to robbing. We'll keep them there all the time, and we'll hold our
+orgies there, too. It's an awful snug place for orgies."
+
+"What orgies?"
+
+"I dono. But robbers always have orgies, and of course we've got to
+have them, too. Come along, Huck, we've been in here a long time. It's
+getting late, I reckon. I'm hungry, too. We'll eat and smoke when we
+get to the skiff."
+
+They presently emerged into the clump of sumach bushes, looked warily
+out, found the coast clear, and were soon lunching and smoking in the
+skiff. As the sun dipped toward the horizon they pushed out and got
+under way. Tom skimmed up the shore through the long twilight, chatting
+cheerily with Huck, and landed shortly after dark.
+
+"Now, Huck," said Tom, "we'll hide the money in the loft of the
+widow's woodshed, and I'll come up in the morning and we'll count it
+and divide, and then we'll hunt up a place out in the woods for it
+where it will be safe. Just you lay quiet here and watch the stuff till
+I run and hook Benny Taylor's little wagon; I won't be gone a minute."
+
+He disappeared, and presently returned with the wagon, put the two
+small sacks into it, threw some old rags on top of them, and started
+off, dragging his cargo behind him. When the boys reached the
+Welshman's house, they stopped to rest. Just as they were about to move
+on, the Welshman stepped out and said:
+
+"Hallo, who's that?"
+
+"Huck and Tom Sawyer."
+
+"Good! Come along with me, boys, you are keeping everybody waiting.
+Here--hurry up, trot ahead--I'll haul the wagon for you. Why, it's not
+as light as it might be. Got bricks in it?--or old metal?"
+
+"Old metal," said Tom.
+
+"I judged so; the boys in this town will take more trouble and fool
+away more time hunting up six bits' worth of old iron to sell to the
+foundry than they would to make twice the money at regular work. But
+that's human nature--hurry along, hurry along!"
+
+The boys wanted to know what the hurry was about.
+
+"Never mind; you'll see, when we get to the Widow Douglas'."
+
+Huck said with some apprehension--for he was long used to being
+falsely accused:
+
+"Mr. Jones, we haven't been doing nothing."
+
+The Welshman laughed.
+
+"Well, I don't know, Huck, my boy. I don't know about that. Ain't you
+and the widow good friends?"
+
+"Yes. Well, she's ben good friends to me, anyway."
+
+"All right, then. What do you want to be afraid for?"
+
+This question was not entirely answered in Huck's slow mind before he
+found himself pushed, along with Tom, into Mrs. Douglas' drawing-room.
+Mr. Jones left the wagon near the door and followed.
+
+The place was grandly lighted, and everybody that was of any
+consequence in the village was there. The Thatchers were there, the
+Harpers, the Rogerses, Aunt Polly, Sid, Mary, the minister, the editor,
+and a great many more, and all dressed in their best. The widow
+received the boys as heartily as any one could well receive two such
+looking beings. They were covered with clay and candle-grease. Aunt
+Polly blushed crimson with humiliation, and frowned and shook her head
+at Tom. Nobody suffered half as much as the two boys did, however. Mr.
+Jones said:
+
+"Tom wasn't at home, yet, so I gave him up; but I stumbled on him and
+Huck right at my door, and so I just brought them along in a hurry."
+
+"And you did just right," said the widow. "Come with me, boys."
+
+She took them to a bedchamber and said:
+
+"Now wash and dress yourselves. Here are two new suits of clothes
+--shirts, socks, everything complete. They're Huck's--no, no thanks,
+Huck--Mr. Jones bought one and I the other. But they'll fit both of you.
+Get into them. We'll wait--come down when you are slicked up enough."
+
+Then she left.
+
+
+
+CHAPTER XXXIV
+
+HUCK said: "Tom, we can slope, if we can find a rope. The window ain't
+high from the ground."
+
+"Shucks! what do you want to slope for?"
+
+"Well, I ain't used to that kind of a crowd. I can't stand it. I ain't
+going down there, Tom."
+
+"Oh, bother! It ain't anything. I don't mind it a bit. I'll take care
+of you."
+
+Sid appeared.
+
+"Tom," said he, "auntie has been waiting for you all the afternoon.
+Mary got your Sunday clothes ready, and everybody's been fretting about
+you. Say--ain't this grease and clay, on your clothes?"
+
+"Now, Mr. Siddy, you jist 'tend to your own business. What's all this
+blow-out about, anyway?"
+
+"It's one of the widow's parties that she's always having. This time
+it's for the Welshman and his sons, on account of that scrape they
+helped her out of the other night. And say--I can tell you something,
+if you want to know."
+
+"Well, what?"
+
+"Why, old Mr. Jones is going to try to spring something on the people
+here to-night, but I overheard him tell auntie to-day about it, as a
+secret, but I reckon it's not much of a secret now. Everybody knows
+--the widow, too, for all she tries to let on she don't. Mr. Jones was
+bound Huck should be here--couldn't get along with his grand secret
+without Huck, you know!"
+
+"Secret about what, Sid?"
+
+"About Huck tracking the robbers to the widow's. I reckon Mr. Jones
+was going to make a grand time over his surprise, but I bet you it will
+drop pretty flat."
+
+Sid chuckled in a very contented and satisfied way.
+
+"Sid, was it you that told?"
+
+"Oh, never mind who it was. SOMEBODY told--that's enough."
+
+"Sid, there's only one person in this town mean enough to do that, and
+that's you. If you had been in Huck's place you'd 'a' sneaked down the
+hill and never told anybody on the robbers. You can't do any but mean
+things, and you can't bear to see anybody praised for doing good ones.
+There--no thanks, as the widow says"--and Tom cuffed Sid's ears and
+helped him to the door with several kicks. "Now go and tell auntie if
+you dare--and to-morrow you'll catch it!"
+
+Some minutes later the widow's guests were at the supper-table, and a
+dozen children were propped up at little side-tables in the same room,
+after the fashion of that country and that day. At the proper time Mr.
+Jones made his little speech, in which he thanked the widow for the
+honor she was doing himself and his sons, but said that there was
+another person whose modesty--
+
+And so forth and so on. He sprung his secret about Huck's share in the
+adventure in the finest dramatic manner he was master of, but the
+surprise it occasioned was largely counterfeit and not as clamorous and
+effusive as it might have been under happier circumstances. However,
+the widow made a pretty fair show of astonishment, and heaped so many
+compliments and so much gratitude upon Huck that he almost forgot the
+nearly intolerable discomfort of his new clothes in the entirely
+intolerable discomfort of being set up as a target for everybody's gaze
+and everybody's laudations.
+
+The widow said she meant to give Huck a home under her roof and have
+him educated; and that when she could spare the money she would start
+him in business in a modest way. Tom's chance was come. He said:
+
+"Huck don't need it. Huck's rich."
+
+Nothing but a heavy strain upon the good manners of the company kept
+back the due and proper complimentary laugh at this pleasant joke. But
+the silence was a little awkward. Tom broke it:
+
+"Huck's got money. Maybe you don't believe it, but he's got lots of
+it. Oh, you needn't smile--I reckon I can show you. You just wait a
+minute."
+
+Tom ran out of doors. The company looked at each other with a
+perplexed interest--and inquiringly at Huck, who was tongue-tied.
+
+"Sid, what ails Tom?" said Aunt Polly. "He--well, there ain't ever any
+making of that boy out. I never--"
+
+Tom entered, struggling with the weight of his sacks, and Aunt Polly
+did not finish her sentence. Tom poured the mass of yellow coin upon
+the table and said:
+
+"There--what did I tell you? Half of it's Huck's and half of it's mine!"
+
+The spectacle took the general breath away. All gazed, nobody spoke
+for a moment. Then there was a unanimous call for an explanation. Tom
+said he could furnish it, and he did. The tale was long, but brimful of
+interest. There was scarcely an interruption from any one to break the
+charm of its flow. When he had finished, Mr. Jones said:
+
+"I thought I had fixed up a little surprise for this occasion, but it
+don't amount to anything now. This one makes it sing mighty small, I'm
+willing to allow."
+
+The money was counted. The sum amounted to a little over twelve
+thousand dollars. It was more than any one present had ever seen at one
+time before, though several persons were there who were worth
+considerably more than that in property.
+
+
+
+CHAPTER XXXV
+
+THE reader may rest satisfied that Tom's and Huck's windfall made a
+mighty stir in the poor little village of St. Petersburg. So vast a
+sum, all in actual cash, seemed next to incredible. It was talked
+about, gloated over, glorified, until the reason of many of the
+citizens tottered under the strain of the unhealthy excitement. Every
+"haunted" house in St. Petersburg and the neighboring villages was
+dissected, plank by plank, and its foundations dug up and ransacked for
+hidden treasure--and not by boys, but men--pretty grave, unromantic
+men, too, some of them. Wherever Tom and Huck appeared they were
+courted, admired, stared at. The boys were not able to remember that
+their remarks had possessed weight before; but now their sayings were
+treasured and repeated; everything they did seemed somehow to be
+regarded as remarkable; they had evidently lost the power of doing and
+saying commonplace things; moreover, their past history was raked up
+and discovered to bear marks of conspicuous originality. The village
+paper published biographical sketches of the boys.
+
+The Widow Douglas put Huck's money out at six per cent., and Judge
+Thatcher did the same with Tom's at Aunt Polly's request. Each lad had
+an income, now, that was simply prodigious--a dollar for every week-day
+in the year and half of the Sundays. It was just what the minister got
+--no, it was what he was promised--he generally couldn't collect it. A
+dollar and a quarter a week would board, lodge, and school a boy in
+those old simple days--and clothe him and wash him, too, for that
+matter.
+
+Judge Thatcher had conceived a great opinion of Tom. He said that no
+commonplace boy would ever have got his daughter out of the cave. When
+Becky told her father, in strict confidence, how Tom had taken her
+whipping at school, the Judge was visibly moved; and when she pleaded
+grace for the mighty lie which Tom had told in order to shift that
+whipping from her shoulders to his own, the Judge said with a fine
+outburst that it was a noble, a generous, a magnanimous lie--a lie that
+was worthy to hold up its head and march down through history breast to
+breast with George Washington's lauded Truth about the hatchet! Becky
+thought her father had never looked so tall and so superb as when he
+walked the floor and stamped his foot and said that. She went straight
+off and told Tom about it.
+
+Judge Thatcher hoped to see Tom a great lawyer or a great soldier some
+day. He said he meant to look to it that Tom should be admitted to the
+National Military Academy and afterward trained in the best law school
+in the country, in order that he might be ready for either career or
+both.
+
+Huck Finn's wealth and the fact that he was now under the Widow
+Douglas' protection introduced him into society--no, dragged him into
+it, hurled him into it--and his sufferings were almost more than he
+could bear. The widow's servants kept him clean and neat, combed and
+brushed, and they bedded him nightly in unsympathetic sheets that had
+not one little spot or stain which he could press to his heart and know
+for a friend. He had to eat with a knife and fork; he had to use
+napkin, cup, and plate; he had to learn his book, he had to go to
+church; he had to talk so properly that speech was become insipid in
+his mouth; whithersoever he turned, the bars and shackles of
+civilization shut him in and bound him hand and foot.
+
+He bravely bore his miseries three weeks, and then one day turned up
+missing. For forty-eight hours the widow hunted for him everywhere in
+great distress. The public were profoundly concerned; they searched
+high and low, they dragged the river for his body. Early the third
+morning Tom Sawyer wisely went poking among some old empty hogsheads
+down behind the abandoned slaughter-house, and in one of them he found
+the refugee. Huck had slept there; he had just breakfasted upon some
+stolen odds and ends of food, and was lying off, now, in comfort, with
+his pipe. He was unkempt, uncombed, and clad in the same old ruin of
+rags that had made him picturesque in the days when he was free and
+happy. Tom routed him out, told him the trouble he had been causing,
+and urged him to go home. Huck's face lost its tranquil content, and
+took a melancholy cast. He said:
+
+"Don't talk about it, Tom. I've tried it, and it don't work; it don't
+work, Tom. It ain't for me; I ain't used to it. The widder's good to
+me, and friendly; but I can't stand them ways. She makes me get up just
+at the same time every morning; she makes me wash, they comb me all to
+thunder; she won't let me sleep in the woodshed; I got to wear them
+blamed clothes that just smothers me, Tom; they don't seem to any air
+git through 'em, somehow; and they're so rotten nice that I can't set
+down, nor lay down, nor roll around anywher's; I hain't slid on a
+cellar-door for--well, it 'pears to be years; I got to go to church and
+sweat and sweat--I hate them ornery sermons! I can't ketch a fly in
+there, I can't chaw. I got to wear shoes all Sunday. The widder eats by
+a bell; she goes to bed by a bell; she gits up by a bell--everything's
+so awful reg'lar a body can't stand it."
+
+"Well, everybody does that way, Huck."
+
+"Tom, it don't make no difference. I ain't everybody, and I can't
+STAND it. It's awful to be tied up so. And grub comes too easy--I don't
+take no interest in vittles, that way. I got to ask to go a-fishing; I
+got to ask to go in a-swimming--dern'd if I hain't got to ask to do
+everything. Well, I'd got to talk so nice it wasn't no comfort--I'd got
+to go up in the attic and rip out awhile, every day, to git a taste in
+my mouth, or I'd a died, Tom. The widder wouldn't let me smoke; she
+wouldn't let me yell, she wouldn't let me gape, nor stretch, nor
+scratch, before folks--" [Then with a spasm of special irritation and
+injury]--"And dad fetch it, she prayed all the time! I never see such a
+woman! I HAD to shove, Tom--I just had to. And besides, that school's
+going to open, and I'd a had to go to it--well, I wouldn't stand THAT,
+Tom. Looky here, Tom, being rich ain't what it's cracked up to be. It's
+just worry and worry, and sweat and sweat, and a-wishing you was dead
+all the time. Now these clothes suits me, and this bar'l suits me, and
+I ain't ever going to shake 'em any more. Tom, I wouldn't ever got into
+all this trouble if it hadn't 'a' ben for that money; now you just take
+my sheer of it along with your'n, and gimme a ten-center sometimes--not
+many times, becuz I don't give a dern for a thing 'thout it's tollable
+hard to git--and you go and beg off for me with the widder."
+
+"Oh, Huck, you know I can't do that. 'Tain't fair; and besides if
+you'll try this thing just a while longer you'll come to like it."
+
+"Like it! Yes--the way I'd like a hot stove if I was to set on it long
+enough. No, Tom, I won't be rich, and I won't live in them cussed
+smothery houses. I like the woods, and the river, and hogsheads, and
+I'll stick to 'em, too. Blame it all! just as we'd got guns, and a
+cave, and all just fixed to rob, here this dern foolishness has got to
+come up and spile it all!"
+
+Tom saw his opportunity--
+
+"Lookyhere, Huck, being rich ain't going to keep me back from turning
+robber."
+
+"No! Oh, good-licks; are you in real dead-wood earnest, Tom?"
+
+"Just as dead earnest as I'm sitting here. But Huck, we can't let you
+into the gang if you ain't respectable, you know."
+
+Huck's joy was quenched.
+
+"Can't let me in, Tom? Didn't you let me go for a pirate?"
+
+"Yes, but that's different. A robber is more high-toned than what a
+pirate is--as a general thing. In most countries they're awful high up
+in the nobility--dukes and such."
+
+"Now, Tom, hain't you always ben friendly to me? You wouldn't shet me
+out, would you, Tom? You wouldn't do that, now, WOULD you, Tom?"
+
+"Huck, I wouldn't want to, and I DON'T want to--but what would people
+say? Why, they'd say, 'Mph! Tom Sawyer's Gang! pretty low characters in
+it!' They'd mean you, Huck. You wouldn't like that, and I wouldn't."
+
+Huck was silent for some time, engaged in a mental struggle. Finally
+he said:
+
+"Well, I'll go back to the widder for a month and tackle it and see if
+I can come to stand it, if you'll let me b'long to the gang, Tom."
+
+"All right, Huck, it's a whiz! Come along, old chap, and I'll ask the
+widow to let up on you a little, Huck."
+
+"Will you, Tom--now will you? That's good. If she'll let up on some of
+the roughest things, I'll smoke private and cuss private, and crowd
+through or bust. When you going to start the gang and turn robbers?"
+
+"Oh, right off. We'll get the boys together and have the initiation
+to-night, maybe."
+
+"Have the which?"
+
+"Have the initiation."
+
+"What's that?"
+
+"It's to swear to stand by one another, and never tell the gang's
+secrets, even if you're chopped all to flinders, and kill anybody and
+all his family that hurts one of the gang."
+
+"That's gay--that's mighty gay, Tom, I tell you."
+
+"Well, I bet it is. And all that swearing's got to be done at
+midnight, in the lonesomest, awfulest place you can find--a ha'nted
+house is the best, but they're all ripped up now."
+
+"Well, midnight's good, anyway, Tom."
+
+"Yes, so it is. And you've got to swear on a coffin, and sign it with
+blood."
+
+"Now, that's something LIKE! Why, it's a million times bullier than
+pirating. I'll stick to the widder till I rot, Tom; and if I git to be
+a reg'lar ripper of a robber, and everybody talking 'bout it, I reckon
+she'll be proud she snaked me in out of the wet."
+
+
+
+CONCLUSION
+
+SO endeth this chronicle. It being strictly a history of a BOY, it
+must stop here; the story could not go much further without becoming
+the history of a MAN. When one writes a novel about grown people, he
+knows exactly where to stop--that is, with a marriage; but when he
+writes of juveniles, he must stop where he best can.
+
+Most of the characters that perform in this book still live, and are
+prosperous and happy. Some day it may seem worth while to take up the
+story of the younger ones again and see what sort of men and women they
+turned out to be; therefore it will be wisest not to reveal any of that
+part of their lives at present.
+
+
+
+
+
+End of the Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
+by Mark Twain (Samuel Clemens)
+
+*** END OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
+
+***** This file should be named 74.txt or 74.zip *****
+This and all associated files of various formats will be found in:
+        http://www.gutenberg.net/7/74/
+
+Produced by David Widger. The previous edition was update by Jose
+Menendez.
+
+
+Updated editions will replace the previous one--the old editions
+will be renamed.
+
+Creating the works from public domain print editions means that no
+one owns a United States copyright in these works, so the Foundation
+(and you!) can copy and distribute it in the United States without
+permission and without paying copyright royalties.  Special rules,
+set forth in the General Terms of Use part of this license, apply to
+copying and distributing Project Gutenberg-tm electronic works to
+protect the PROJECT GUTENBERG-tm concept and trademark.  Project
+Gutenberg is a registered trademark, and may not be used if you
+charge for the eBooks, unless you receive specific permission.  If you
+do not charge anything for copies of this eBook, complying with the
+rules is very easy.  You may use this eBook for nearly any purpose
+such as creation of derivative works, reports, performances and
+research.  They may be modified and printed and given away--you may do
+practically ANYTHING with public domain eBooks.  Redistribution is
+subject to the trademark license, especially commercial
+redistribution.
+
+
+
+*** START: FULL LICENSE ***
+
+THE FULL PROJECT GUTENBERG LICENSE
+PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK
+
+To protect the Project Gutenberg-tm mission of promoting the free
+distribution of electronic works, by using or distributing this work
+(or any other work associated in any way with the phrase "Project
+Gutenberg"), you agree to comply with all the terms of the Full Project
+Gutenberg-tm License (available with this file or online at
+http://gutenberg.net/license).
+
+
+Section 1.  General Terms of Use and Redistributing Project Gutenberg-tm
+electronic works
+
+1.A.  By reading or using any part of this Project Gutenberg-tm
+electronic work, you indicate that you have read, understand, agree to
+and accept all the terms of this license and intellectual property
+(trademark/copyright) agreement.  If you do not agree to abide by all
+the terms of this agreement, you must cease using and return or destroy
+all copies of Project Gutenberg-tm electronic works in your possession.
+If you paid a fee for obtaining a copy of or access to a Project
+Gutenberg-tm electronic work and you do not agree to be bound by the
+terms of this agreement, you may obtain a refund from the person or
+entity to whom you paid the fee as set forth in paragraph 1.E.8.
+
+1.B.  "Project Gutenberg" is a registered trademark.  It may only be
+used on or associated in any way with an electronic work by people who
+agree to be bound by the terms of this agreement.  There are a few
+things that you can do with most Project Gutenberg-tm electronic works
+even without complying with the full terms of this agreement.  See
+paragraph 1.C below.  There are a lot of things you can do with Project
+Gutenberg-tm electronic works if you follow the terms of this agreement
+and help preserve free future access to Project Gutenberg-tm electronic
+works.  See paragraph 1.E below.
+
+1.C.  The Project Gutenberg Literary Archive Foundation ("the Foundation"
+or PGLAF), owns a compilation copyright in the collection of Project
+Gutenberg-tm electronic works.  Nearly all the individual works in the
+collection are in the public domain in the United States.  If an
+individual work is in the public domain in the United States and you are
+located in the United States, we do not claim a right to prevent you from
+copying, distributing, performing, displaying or creating derivative
+works based on the work as long as all references to Project Gutenberg
+are removed.  Of course, we hope that you will support the Project
+Gutenberg-tm mission of promoting free access to electronic works by
+freely sharing Project Gutenberg-tm works in compliance with the terms of
+this agreement for keeping the Project Gutenberg-tm name associated with
+the work.  You can easily comply with the terms of this agreement by
+keeping this work in the same format with its attached full Project
+Gutenberg-tm License when you share it without charge with others.
+
+1.D.  The copyright laws of the place where you are located also govern
+what you can do with this work.  Copyright laws in most countries are in
+a constant state of change.  If you are outside the United States, check
+the laws of your country in addition to the terms of this agreement
+before downloading, copying, displaying, performing, distributing or
+creating derivative works based on this work or any other Project
+Gutenberg-tm work.  The Foundation makes no representations concerning
+the copyright status of any work in any country outside the United
+States.
+
+1.E.  Unless you have removed all references to Project Gutenberg:
+
+1.E.1.  The following sentence, with active links to, or other immediate
+access to, the full Project Gutenberg-tm License must appear prominently
+whenever any copy of a Project Gutenberg-tm work (any work on which the
+phrase "Project Gutenberg" appears, or with which the phrase "Project
+Gutenberg" is associated) is accessed, displayed, performed, viewed,
+copied or distributed:
+
+This eBook is for the use of anyone anywhere at no cost and with
+almost no restrictions whatsoever.  You may copy it, give it away or
+re-use it under the terms of the Project Gutenberg License included
+with this eBook or online at www.gutenberg.net
+
+1.E.2.  If an individual Project Gutenberg-tm electronic work is derived
+from the public domain (does not contain a notice indicating that it is
+posted with permission of the copyright holder), the work can be copied
+and distributed to anyone in the United States without paying any fees
+or charges.  If you are redistributing or providing access to a work
+with the phrase "Project Gutenberg" associated with or appearing on the
+work, you must comply either with the requirements of paragraphs 1.E.1
+through 1.E.7 or obtain permission for the use of the work and the
+Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or
+1.E.9.
+
+1.E.3.  If an individual Project Gutenberg-tm electronic work is posted
+with the permission of the copyright holder, your use and distribution
+must comply with both paragraphs 1.E.1 through 1.E.7 and any additional
+terms imposed by the copyright holder.  Additional terms will be linked
+to the Project Gutenberg-tm License for all works posted with the
+permission of the copyright holder found at the beginning of this work.
+
+1.E.4.  Do not unlink or detach or remove the full Project Gutenberg-tm
+License terms from this work, or any files containing a part of this
+work or any other work associated with Project Gutenberg-tm.
+
+1.E.5.  Do not copy, display, perform, distribute or redistribute this
+electronic work, or any part of this electronic work, without
+prominently displaying the sentence set forth in paragraph 1.E.1 with
+active links or immediate access to the full terms of the Project
+Gutenberg-tm License.
+
+1.E.6.  You may convert to and distribute this work in any binary,
+compressed, marked up, nonproprietary or proprietary form, including any
+word processing or hypertext form.  However, if you provide access to or
+distribute copies of a Project Gutenberg-tm work in a format other than
+"Plain Vanilla ASCII" or other format used in the official version
+posted on the official Project Gutenberg-tm web site (www.gutenberg.net),
+you must, at no additional cost, fee or expense to the user, provide a
+copy, a means of exporting a copy, or a means of obtaining a copy upon
+request, of the work in its original "Plain Vanilla ASCII" or other
+form.  Any alternate format must include the full Project Gutenberg-tm
+License as specified in paragraph 1.E.1.
+
+1.E.7.  Do not charge a fee for access to, viewing, displaying,
+performing, copying or distributing any Project Gutenberg-tm works
+unless you comply with paragraph 1.E.8 or 1.E.9.
+
+1.E.8.  You may charge a reasonable fee for copies of or providing
+access to or distributing Project Gutenberg-tm electronic works provided
+that
+
+- You pay a royalty fee of 20% of the gross profits you derive from
+     the use of Project Gutenberg-tm works calculated using the method
+     you already use to calculate your applicable taxes.  The fee is
+     owed to the owner of the Project Gutenberg-tm trademark, but he
+     has agreed to donate royalties under this paragraph to the
+     Project Gutenberg Literary Archive Foundation.  Royalty payments
+     must be paid within 60 days following each date on which you
+     prepare (or are legally required to prepare) your periodic tax
+     returns.  Royalty payments should be clearly marked as such and
+     sent to the Project Gutenberg Literary Archive Foundation at the
+     address specified in Section 4, "Information about donations to
+     the Project Gutenberg Literary Archive Foundation."
+
+- You provide a full refund of any money paid by a user who notifies
+     you in writing (or by e-mail) within 30 days of receipt that s/he
+     does not agree to the terms of the full Project Gutenberg-tm
+     License.  You must require such a user to return or
+     destroy all copies of the works possessed in a physical medium
+     and discontinue all use of and all access to other copies of
+     Project Gutenberg-tm works.
+
+- You provide, in accordance with paragraph 1.F.3, a full refund of any
+     money paid for a work or a replacement copy, if a defect in the
+     electronic work is discovered and reported to you within 90 days
+     of receipt of the work.
+
+- You comply with all other terms of this agreement for free
+     distribution of Project Gutenberg-tm works.
+
+1.E.9.  If you wish to charge a fee or distribute a Project Gutenberg-tm
+electronic work or group of works on different terms than are set
+forth in this agreement, you must obtain permission in writing from
+both the Project Gutenberg Literary Archive Foundation and Michael
+Hart, the owner of the Project Gutenberg-tm trademark.  Contact the
+Foundation as set forth in Section 3 below.
+
+1.F.
+
+1.F.1.  Project Gutenberg volunteers and employees expend considerable
+effort to identify, do copyright research on, transcribe and proofread
+public domain works in creating the Project Gutenberg-tm
+collection.  Despite these efforts, Project Gutenberg-tm electronic
+works, and the medium on which they may be stored, may contain
+"Defects," such as, but not limited to, incomplete, inaccurate or
+corrupt data, transcription errors, a copyright or other intellectual
+property infringement, a defective or damaged disk or other medium, a
+computer virus, or computer codes that damage or cannot be read by
+your equipment.
+
+1.F.2.  LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the "Right
+of Replacement or Refund" described in paragraph 1.F.3, the Project
+Gutenberg Literary Archive Foundation, the owner of the Project
+Gutenberg-tm trademark, and any other party distributing a Project
+Gutenberg-tm electronic work under this agreement, disclaim all
+liability to you for damages, costs and expenses, including legal
+fees.  YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
+LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE
+PROVIDED IN PARAGRAPH F3.  YOU AGREE THAT THE FOUNDATION, THE
+TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE
+LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
+INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+1.F.3.  LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a
+defect in this electronic work within 90 days of receiving it, you can
+receive a refund of the money (if any) you paid for it by sending a
+written explanation to the person you received the work from.  If you
+received the work on a physical medium, you must return the medium with
+your written explanation.  The person or entity that provided you with
+the defective work may elect to provide a replacement copy in lieu of a
+refund.  If you received the work electronically, the person or entity
+providing it to you may choose to give you a second opportunity to
+receive the work electronically in lieu of a refund.  If the second copy
+is also defective, you may demand a refund in writing without further
+opportunities to fix the problem.
+
+1.F.4.  Except for the limited right of replacement or refund set forth
+in paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER
+WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE.
+
+1.F.5.  Some states do not allow disclaimers of certain implied
+warranties or the exclusion or limitation of certain types of damages.
+If any disclaimer or limitation set forth in this agreement violates the
+law of the state applicable to this agreement, the agreement shall be
+interpreted to make the maximum disclaimer or limitation permitted by
+the applicable state law.  The invalidity or unenforceability of any
+provision of this agreement shall not void the remaining provisions.
+
+1.F.6.  INDEMNITY - You agree to indemnify and hold the Foundation, the
+trademark owner, any agent or employee of the Foundation, anyone
+providing copies of Project Gutenberg-tm electronic works in accordance
+with this agreement, and any volunteers associated with the production,
+promotion and distribution of Project Gutenberg-tm electronic works,
+harmless from all liability, costs and expenses, including legal fees,
+that arise directly or indirectly from any of the following which you do
+or cause to occur: (a) distribution of this or any Project Gutenberg-tm
+work, (b) alteration, modification, or additions or deletions to any
+Project Gutenberg-tm work, and (c) any Defect you cause.
+
+
+Section  2.  Information about the Mission of Project Gutenberg-tm
+
+Project Gutenberg-tm is synonymous with the free distribution of
+electronic works in formats readable by the widest variety of computers
+including obsolete, old, middle-aged and new computers.  It exists
+because of the efforts of hundreds of volunteers and donations from
+people in all walks of life.
+
+Volunteers and financial support to provide volunteers with the
+assistance they need, is critical to reaching Project Gutenberg-tm's
+goals and ensuring that the Project Gutenberg-tm collection will
+remain freely available for generations to come.  In 2001, the Project
+Gutenberg Literary Archive Foundation was created to provide a secure
+and permanent future for Project Gutenberg-tm and future generations.
+To learn more about the Project Gutenberg Literary Archive Foundation
+and how your efforts and donations can help, see Sections 3 and 4
+and the Foundation web page at http://www.pglaf.org.
+
+
+Section 3.  Information about the Project Gutenberg Literary Archive
+Foundation
+
+The Project Gutenberg Literary Archive Foundation is a non profit
+501(c)(3) educational corporation organized under the laws of the
+state of Mississippi and granted tax exempt status by the Internal
+Revenue Service.  The Foundation's EIN or federal tax identification
+number is 64-6221541.  Its 501(c)(3) letter is posted at
+http://pglaf.org/fundraising.  Contributions to the Project Gutenberg
+Literary Archive Foundation are tax deductible to the full extent
+permitted by U.S. federal laws and your state's laws.
+
+The Foundation's principal office is located at 4557 Melan Dr. S.
+Fairbanks, AK, 99712., but its volunteers and employees are scattered
+throughout numerous locations.  Its business office is located at
+809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email
+business@pglaf.org.  Email contact links and up to date contact
+information can be found at the Foundation's web site and official
+page at http://pglaf.org
+
+For additional contact information:
+     Dr. Gregory B. Newby
+     Chief Executive and Director
+     gbnewby@pglaf.org
+
+
+Section 4.  Information about Donations to the Project Gutenberg
+Literary Archive Foundation
+
+Project Gutenberg-tm depends upon and cannot survive without wide
+spread public support and donations to carry out its mission of
+increasing the number of public domain and licensed works that can be
+freely distributed in machine readable form accessible by the widest
+array of equipment including outdated equipment.  Many small donations
+($1 to $5,000) are particularly important to maintaining tax exempt
+status with the IRS.
+
+The Foundation is committed to complying with the laws regulating
+charities and charitable donations in all 50 states of the United
+States.  Compliance requirements are not uniform and it takes a
+considerable effort, much paperwork and many fees to meet and keep up
+with these requirements.  We do not solicit donations in locations
+where we have not received written confirmation of compliance.  To
+SEND DONATIONS or determine the status of compliance for any
+particular state visit http://pglaf.org
+
+While we cannot and do not solicit contributions from states where we
+have not met the solicitation requirements, we know of no prohibition
+against accepting unsolicited donations from donors in such states who
+approach us with offers to donate.
+
+International donations are gratefully accepted, but we cannot make
+any statements concerning tax treatment of donations received from
+outside the United States.  U.S. laws alone swamp our small staff.
+
+Please check the Project Gutenberg Web pages for current donation
+methods and addresses.  Donations are accepted in a number of other
+ways including including checks, online payments and credit card
+donations.  To donate, please visit: http://pglaf.org/donate
+
+
+Section 5.  General Information About Project Gutenberg-tm electronic
+works.
+
+Professor Michael S. Hart is the originator of the Project Gutenberg-tm
+concept of a library of electronic works that could be freely shared
+with anyone.  For thirty years, he produced and distributed Project
+Gutenberg-tm eBooks with only a loose network of volunteer support.
+
+
+Project Gutenberg-tm eBooks are often created from several printed
+editions, all of which are confirmed as Public Domain in the U.S.
+unless a copyright notice is included.  Thus, we do not necessarily
+keep eBooks in compliance with any particular paper edition.
+
+
+Most people start at our Web site which has the main PG search facility:
+
+     http://www.gutenberg.net
+
+This Web site includes information about Project Gutenberg-tm,
+including how to make donations to the Project Gutenberg Literary
+Archive Foundation, how to help produce our new eBooks, and how to
+subscribe to our email newsletter to hear about new eBooks.
diff --git a/third_party/gofrontend/libgo/go/compress/testdata/e.txt b/third_party/gofrontend/libgo/go/compress/testdata/e.txt
new file mode 100644
index 0000000..5ca186f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/testdata/e.txt
@@ -0,0 +1 @@
+2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190115738341879307021540891499348841675092447614606680822648001684774118537423454424371075390777449920695517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416928368190255151086574637721112523897844250569536967707854499699679468644549059879316368892300987931277361782154249992295763514822082698951936680331825288693984964651058209392398294887933203625094431173012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509961818815930416903515988885193458072738667385894228792284998920868058257492796104841984443634632449684875602336248270419786232090021609902353043699418491463140934317381436405462531520961836908887070167683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354021234078498193343210681701210056278802351930332247450158539047304199577770935036604169973297250886876966403555707162268447162560798826517871341951246652010305921236677194325278675398558944896970964097545918569563802363701621120477427228364896134225164450781824423529486363721417402388934412479635743702637552944483379980161254922785092577825620926226483262779333865664816277251640191059004916449982893150566047258027786318641551956532442586982946959308019152987211725563475463964479101459040905862984967912874068705048958586717479854667757573205681288459205413340539220001137863009455606881667400169842055804033637953764520304024322566135278369511778838638744396625322498506549958862342818997077332761717839280349465014345588970719425863987727547109629537415211151368350627526023264847287039207643100595841166120545297030236472549296669381151373227536450988890313602057248176585118063036442812314965507047510254465011727211555194866850800368532281831521960037356252794495158284188294787610852639813955990067376482922443752871846245780361929819713991475644882626039033814418232625150974827987779964373089970388867782271383605772978824125611907176639465070633045279546618550966661856647097113444740160704626215680717481877844371436988218559670959102596862002353718588748569652200050311734392073211390803293634479727355955277349071783793421637012050054513263835440001863239914907054797780566978533580489669062951194324730995876552368128590413832411607226029983305353708761389396391779574540161372236187893652605381558415871869255386061647798340254351284396129460352913325942794904337299085731580290958631382683291477116396337092400316894586360606458459251269946557248391865642097526850823075442545993769170419777800853627309417101634349076964237222943523661255725088147792231519747780605696725380171807763603462459278778465850656050780844211529697521890874019660906651803516501792504619501366585436632712549639908549144200014574760819302212066024330096412704894390397177195180699086998606636583232278709376502260149291011517177635944602023249300280401867723910288097866605651183260043688508817157238669842242201024950551881694803221002515426494639812873677658927688163598312477886520141174110913601164995076629077943646005851941998560162647907615321038727557126992518275687989302761761146162549356495903798045838182323368612016243736569846703785853305275833337939907521660692380533698879565137285593883499894707416181550125397064648171946708348197214488898790676503795903669672494992545279033729636162658976039498576741397359441023744329709355477982629614591442936451428617158587339746791897571211956187385783644758448423555581050025611492391518893099463428413936080383091662818811503715284967059741625628236092168075150177725387402564253470879089137291722828611515915683725241630772254406337875931059826760944203261924285317018781772960235413060672136046000389661093647095141417185777014180606443636815464440053316087783143174440811949422975599314011888683314832802706553833004693290115744147563139997221703804617092894579096271662260740718749975359212756084414737823303270330168237193648002173285734935947564334129943024850235732214597843282641421684878721673367010615094243456984401873312810107945127223737886126058165668053714396127888732527373890392890506865324138062796025930387727697783792868409325365880733988457218746021005311483351323850047827169376218004904795597959290591655470505777514308175112698985188408718564026035305583737832422924185625644255022672155980274012617971928047139600689163828665277009752767069777036439260224372841840883251848770472638440379530166905465937461619323840363893131364327137688841026811219891275223056256756254701725086349765367288605966752740868627407912856576996313789753034660616669804218267724560530660773899624218340859882071864682623215080288286359746839654358856685503773131296587975810501214916207656769950659715344763470320853215603674828608378656803073062657633469774295634643716709397193060876963495328846833613038829431040800296873869117066666146800015121143442256023874474325250769387077775193299942137277211258843608715834835626961661980572526612206797540621062080649882918454395301529982092503005498257043390553570168653120526495614857249257386206917403695213533732531666345466588597286659451136441370331393672118569553952108458407244323835586063106806964924851232632699514603596037297253198368423363904632136710116192821711150282801604488058802382031981493096369596735832742024988245684941273860566491352526706046234450549227581151709314921879592718001940968866986837037302200475314338181092708030017205935530520700706072233999463990571311587099635777359027196285061146514837526209565346713290025994397663114545902685898979115837093419370441155121920117164880566945938131183843765620627846310490346293950029458341164824114969758326011800731699437393506966295712410273239138741754923071862454543222039552735295240245903805744502892246886285336542213815722131163288112052146489805180092024719391710555390113943316681515828843687606961102505171007392762385553386272553538830960671644662370922646809671254061869502143176211668140097595281493907222601112681153108387317617323235263605838173151034595736538223534992935822836851007810884634349983518404451704270189381994243410090575376257767571118090088164183319201962623416288166521374717325477727783488774366518828752156685719506371936565390389449366421764003121527870222366463635755503565576948886549500270853923617105502131147413744106134445544192101336172996285694899193369184729478580729156088510396781959429833186480756083679551496636448965592948187851784038773326247051945050419847742014183947731202815886845707290544057510601285258056594703046836344592652552137008068752009593453607316226118728173928074623094685367823106097921599360019946237993434210687813497346959246469752506246958616909178573976595199392993995567542714654910456860702099012606818704984178079173924071945996323060254707901774527513186809982284730860766536866855516467702911336827563107223346726113705490795365834538637196235856312618387156774118738527722922594743373785695538456246801013905727871016512966636764451872465653730402443684140814488732957847348490003019477888020460324660842875351848364959195082888323206522128104190448047247949291342284951970022601310430062410717971502793433263407995960531446053230488528972917659876016667811937932372453857209607582277178483361613582612896226118129455927462767137794487586753657544861407611931125958512655759734573015333642630767985443385761715333462325270572005303988289499034259566232975782488735029259166825894456894655992658454762694528780516501720674785417887982276806536650641910973434528878338621726156269582654478205672987756426325321594294418039943217000090542650763095588465895171709147607437136893319469090981904501290307099566226620303182649365733698419555776963787624918852865686607600566025605445711337286840205574416030837052312242587223438854123179481388550075689381124935386318635287083799845692619981794523364087429591180747453419551420351726184200845509170845682368200897739455842679214273477560879644279202708312150156406341341617166448069815483764491573900121217041547872591998943825364950514771379399147205219529079396137621107238494290616357604596231253506068537651423115349665683715116604220796394466621163255157729070978473156278277598788136491951257483328793771571459091064841642678309949723674420175862269402159407924480541255360431317992696739157542419296607312393763542139230617876753958711436104089409966089471418340698362993675362621545247298464213752891079884381306095552622720837518629837066787224430195793793786072107254277289071732854874374355781966511716618330881129120245204048682200072344035025448202834254187884653602591506445271657700044521097735585897622655484941621714989532383421600114062950718490427789258552743035221396835679018076406042138307308774460170842688272261177180842664333651780002171903449234264266292261456004337383868335555343453004264818473989215627086095650629340405264943244261445665921291225648893569655009154306426134252668472594914314239398845432486327461842846655985332312210466259890141712103446084271616619001257195870793217569698544013397622096749454185407118446433946990162698351607848924514058940946395267807354579700307051163682519487701189764002827648414160587206184185297189154019688253289309149665345753571427318482016384644832499037886069008072709327673127581966563941148961716832980455139729506687604740915420428429993541025829113502241690769431668574242522509026939034814856451303069925199590436384028429267412573422447765584177886171737265462085498294498946787350929581652632072258992368768457017823038096567883112289305809140572610865884845873101658151167533327674887014829167419701512559782572707406431808601428149024146780472327597684269633935773542930186739439716388611764209004068663398856841681003872389214483176070116684503887212364367043314091155733280182977988736590916659612402021778558854876176161989370794380056663364884365089144805571039765214696027662583599051987042300179465536788567430285974600143785483237068701190078499404930918919181649327259774030074879681484882342932023012128032327460392219687528340516906974194257614673978110715464186273369091584973185011183960482533518748438923177292613543024932562896371361977285456622924461644497284597867711574125670307871885109336344480149675240618536569532074170533486782754827815415561966911055101472799040386897220465550833170782394808785990501947563108984124144672821865459971596639015641941751820935932616316888380132758752601460507676098392625726411120135288591317848299475682472564885533357279772205543568126302535748216585414000805314820697137262149755576051890481622376790414926742600071045922695314835188137463887104273544767623577933993970632396604969145303273887874557905934937772320142954803345000695256980935282887783710670585567749481373858630385762823040694005665340584887527005308832459182183494318049834199639981458773435863115940570443683515285383609442955964360676090221741896883548131643997437764158365242234642619597390455450680695232850751868719449064767791886720306418630751053512149851051207313846648717547518382979990189317751550639981016466414592102406838294603208535554058147159273220677567669213664081505900806952540610628536408293276621931939933861623836069111767785448236129326858199965239275488427435414402884536455595124735546139403154952097397051896240157976832639450633230452192645049651735466775699295718989690470902730288544945416699791992948038254980285946029052763145580316514066229171223429375806143993484914362107993576737317948964252488813720435579287511385856973381976083524423240466778020948399639946684833774706725483618848273000648319163826022110555221246733323184463005504481849916996622087746140216157021029603318588727333298779352570182393861244026868339555870607758169954398469568540671174444932479519572159419645863736126915526457574786985964242176592896862383506370433939811671397544736228625506803682664135541448048997721373174119199970017293907303350869020922519124447393278376156321810842898207706974138707053266117683698647741787180202729412982310888796831880854367327806879771659111654224453806625861711729498038248879986504061563975629936962809358189761491017145343556659542757064194408833816841111166200759787244137082333917886114708228657531078536674695018462140736493917366254937783014074302668422150335117736471853872324040421037907750266020114814935482228916663640782450166815341213505278578539332606110249802273093636740213515386431693015267460536064351732154701091440650878823636764236831187390937464232609021646365627553976834019482932795750624399645272578624400375983422050808935129023122475970644105678361870877172333555465482598906861201410107222465904008553798235253885171623518256518482203125214950700378300411216212126052726059944320443056274522916128891766814160639131235975350390320077529587392412476451850809163911459296071156344204347133544720981178461451077872399140606290228276664309264900592249810291068759434533858330391178747575977065953570979640012224092199031158229259667913153991561438070129260780197022589662923368154312499412259460023399472228171056603931877226800493833148980338548909468685130789292064242819174795866199944411196208730498064385006852620258432842085582338566936649849720817046135376163584015342840674118587581546514598270228676671855309311923340191286170613364873183197560812569460089402953094429119590295968563923037689976327462283900735457144596414108229285922239332836210192822937243590283003884445701383771632056518351970100115722010956997890484964453434612129224964732356126321951155701565824427661599326463155806672053127596948538057364208384918887095176052287817339462747644656858900936266123311152910816041524100214195937349786431661556732702792109593543055579732660554677963552005378304619540636971842916168582734122217145885870814274090248185446421774876925093328785670674677381226752831653559245204578070541352576903253522738963847495646255940378924925007624386893776475310102323746733771474581625530698032499033676455430305274561512961214585944432150749051491453950981001388737926379964873728396416897555132275962011838248650746985492038097691932606437608743209385602815642849756549307909733854185583515789409814007691892389063090542534883896831762904120212949167195811935791203162514344096503132835216728021372415947344095498316138322505486708172221475138425166790445416617303200820330902895488808516797258495813407132180533988828139346049850532340472595097214331492586604248511405819579711564191458842833000525684776874305916390494306871343118796189637475503362820939949343690321031976898112055595369465424704173323895394046035325396758354395350516720261647961347790912327995264929045151148307923369382166010702872651938143844844532639517394110131152502750465749343063766541866128915264446926222884366299462732467958736383501937142786471398054038215513463223702071533134887083174146591492406359493020921122052610312390682941345696785958518393491382340884274312419099152870804332809132993078936867127413922890033069995875921815297612482409116951587789964090352577345938248232053055567238095022266790439614231852991989181065554412477204508510210071522352342792531266930108270633942321762570076323139159349709946933241013908779161651226804414809765618979735043151396066913258379033748620836695475083280318786707751177525663963479259219733577949555498655214193398170268639987388347010255262052312317215254062571636771270010760912281528326508984359568975961038372157726831170734552250194121701541318793651818502020877326906133592182000762327269503283827391243828198170871168108951187896746707073377869592565542713340052326706040004348843432902760360498027862160749469654989210474443927871934536701798673920803845633723311983855862638008516345597194441994344624761123844617615736242015935078520825600604101556889899501732554337298073561699861101908472096600708320280569917042590103876928658336557728758684250492690370934262028022399861803400211320742198642917383679176232826444645756330336556777374808644109969141827774253417010988435853189339175934511574023847292909015468559163792696196841000676598399744972047287881831200233383298030567865480871476464512824264478216644266616732096012564794514827125671326697067367144617795643752391742928503987022583734069852309190464967260243411270345611114149835783901793499713790913696706497637127248466613279908254305449295528594932793818341607827091326680865655921102733746700132583428715240835661522165574998431236278287106649401564670141943713823863454729606978693335973109537126499416282656463708490580151538205338326511289504938566468752921135932220265681856418260827538790002407915892646028490894922299966167437731347776134150965262448332709343898412056926145108857812249139616912534202918139898683901335795857624435194008943955180554746554000051766240202825944828833811886381749594284892013520090951007864941868256009273977667585642598378587497776669563350170748579027248701370264203283965756348010818356182372177082236423186591595883669487322411726504487268392328453010991677518376831599821263237123854357312681202445175401852132663740538802901249728180895021553100673598184430429105288459323064725590442355960551978839325930339572934663055160430923785677229293537208416693134575284011873746854691620648991164726909428982971065606801805807843600461866223562874591385185904416250663222249561448724413813849763797102676020845531824111963927941069619465426480006761727618115630063644321116224837379105623611358836334550102286170517890440570419577859833348463317921904494652923021469259756566389965893747728751393377105569802455757436190501772466214587592374418657530064998056688376964229825501195065837843125232135309371235243969149662310110328243570065781487677299160941153954063362752423712935549926713485031578238899567545287915578420483105749330060197958207739558522807307048950936235550769837881926357141779338750216344391014187576711938914416277109602859415809719913429313295145924373636456473035037374538503489286113141638094752301745088784885645741275003353303416138096560043105860548355773946625033230034341587814634602169235079216111013148948281895391028916816328709309713184139815427678818067628650978085718262117003140003377301581536334149093237034703637513354537634521050370995452942055232078817449370937677056009306353645510913481627378204985657055608784211964039972344556458607689515569686899384896439195225232309703301037277227710870564912966121061494072782442033414057441446459968236966118878411656290355117839944070961772567164919790168195234523807446299877664824873753313018142763910519234685081979001796519907050490865237442841652776611425351538665162781316090964802801234493372427866930894827913465443931965254154829494577875758599482099181824522449312077768250830768282335001597040419199560509705364696473142448453825888112602753909548852639708652339052941829691802357120545328231809270356491743371932080628731303589640570873779967845174740515317401384878082881006046388936711640477755985481263907504747295012609419990373721246201677030517790352952793168766305099837441859803498821239340919805055103821539827677291373138006715339240126954586376422065097810852907639079727841301764553247527073788764069366420012194745702358295481365781809867944020220280822637957006755393575808086318932075864444206644691649334467698180811716568665213389686173592450920801465312529777966137198695916451869432324246404401672381978020728394418264502183131483366019384891972317817154372192103946638473715630226701801343515930442853848941825678870721238520597263859224934763623122188113706307506918260109689069251417142514218153491532129077723748506635489170892850760234351768218355008829647410655814882049239533702270536705630750317499788187009989251020178015601042277836283644323729779929935160925884515772055232896978333126427671291093993103773425910592303277652667641874842441076564447767097790392324958416348527735171981064673837142742974468992320406932506062834468937543016787815320616009057693404906146176607094380110915443261929000745209895959201159412324102274845482605404361871836330268992858623582145643879695210235266673372434423091577183277565800211928270391042391966426911155333594569685782817020325495552528875464466074620294766116004435551604735044292127916358748473501590215522120388281168021413865865168464569964810015633741255098479730138656275460161279246359783661480163871602794405482710196290774543628092612567507181773641749763254436773503632580004042919906963117397787875081560227368824967077635559869284901628768699628053790181848148810833946900016380791075960745504688912686792812391148880036720729730801354431325347713094186717178607522981373539126772812593958220524289991371690685650421575056729991274177149279608831502358697816190894908487717722503860872618384947939757440664912760518878124233683125467278331513186758915668300679210215947336858591201395360301678110413444411030903388761520488296909104689167671555373346622545575975202624771242796225983278405833585897671474205724047439720232895903726148688388003174146490203843590358527993123871042845981608996101945691646983837718267264685264869172948414153004604004299585035164101899027529366867431834955447458124140190754681607770977920579383895378192128847409929537040546962226547278807248685508046571043123854873351653070570784584243335550958221912862797205455466267099131902370311779690892786623112661337671178512943059323281605826535623848164192144732543731002062738466812351691016359252588256806438946389880872735284406462208149513862275239938938734905082625472417781702582044129853760499827899020083498387362992498125742354568439023012261733665820546785671147973065077035475620567428300187473019197310881157516777005071432012726354601912460800451608108641835539669946936947322271670748972850464195392966434725254724357659192969949061670189061433616907056148280980363243454128229968275980226694045642181328624517549652147221620839824594576613342710564957193564431561774500828376935700995419541839029151033187933907614207467028867968594985439789457300768939890070073924697461812855764662265412913204052279071212820653775058280040897163467163709024906774736309136904002615646432159560910851092445162454420141442641660181385990017417408244245378610158433361777292580611159192008414091888191208858207627011483671760749046980914443057262211104583300789331698191603917150622792986282709446275915009683226345073725451366858172483498470080840163868209726371345205439802277866337293290829914010645589761697455978409211409167684020269370229231743334499986901841510888993165125090001163719114994852024821586396216294981753094623047604832399379391002142532996476235163569009445086058091202459904612118623318278614464727795523218635916551883057930657703331498510068357135624341881884405780028844018129031378653794869614630467726914552953690154167025838032477842272417994513653582260971652588356712133519546838335349801503269359798167463231847628306340588324731228951257944267639877946713121042763380872695738609314631539148548792514028885025189788076023838995615684850391995855029256054176767663145354058496296796781349420116003325874431438746248313850214980401681940795687219268462617287403480967931949965604299190281810597603263251746405016454606266765529010639868703668263299050577706266397868453584384057673298268163448646707439990917504018892319267557518354054956017732907127219134577524905771512773358423314008356080926962298894163047287780054743798498545562870729968407382937218623831766524716090967192007237658894226186550487552614557855898773008703234726418384831040394818743616224455286163287628541175946460497027724490799275146445792982549802258601001772437840167723166802004162547244179415547810554178036773553354467030326469619447560812831933095679685582771932031205941616693902049665352189672822671972640029493307384717544753761937017882976382487233361813499414541694736549254840633793674361541081593464960431603544354737728802361047743115330785159902977771499610274627769759612488879448609863349422852847651310277926279743981957617505591300993377368240510902583759345170015340522266144077237050890044496613295859536020556034009492820943862994618834790932894161098856594954213114335608810239423706087108026465913203560121875933791639666437282836752328391688865373751335794859860107569374889645657187292540448508624449947816273842517229343960137212406286783636675845331904743954740664015260871940915743955282773904303868772728262065663129387459875317749973799293043294371763801856280061141619563942414312254397099163565102848315765427037906837175764870230052388197498746636856292655058222887713221781440489538099681072143012394693530931524054081215705402274414521876541901428386744260011889041724570537470755550581632831687247110220353727166112304857340460879272501694701067831178927095527253222125224361673343366384756590949728221809418684074238351567868893421148203905824224324264643630201441787982022116248471657468291146315407563770222740135841109076078464780070182766336227978104546331131294044833570134869585165267459515187680033395522410548181767867772152798270250117195816577603549732923724732067853690257536233971216884390878879262188202305529937132397194333083536231248870386416194361506529551267334207198502259771408638122015980894363561808597010080081622557455039101321981979045520049618583777721048046635533806616517023595097133203631578945644487800945620369784973459902004606886572701865867757842758530645706617127194967371083950603267501532435909029491516973738110897934782297684100117657987098185725131372267749706609250481876835516003714638685918913011736805218743265426063700710595364425062760458252336880552521181566417553430681181548267844169315284408461087588214317641649835663127518728182948655658524206852221830755306118393326934164459415342651778653397980580828158806300749952897558204686612590853678738603318442905510689778698417735603118111677563872589911516803236547002987989628986181014596471307916144369564690909518788574398821730583884980809523077569358851616027719521488998358632323127308909861560777386006984035267826785387215920936255817889813416247486456433211043194821421299793188104636399541496539441501383868748384870224681829391860319598667962363489309283087840712400431022706137591368056518861313458307990705003607588327248867879324093380071864152853317943535073401891193638546730000660453783784472469288830546979000131248952100446949032058838294923613919284305249167833012980192255157050378521810552961623637523647962685751660066539364142273063001648652613891842243501797455993616794063303522111829071597538821839777552812981538570168702202620274678647916644030729018445497956399844836807851997088201407769199261674991148329821854382718946282165387064858588646221611410343570342878862979083418871606214430014533275029715104673156021000043869510583773779766003460887624861640938645252177935289947578496255243925598620521409052346250847830487046492688313289470553891357290706967599556298586669559721686506052072801342104355762779184021797626656484580261591407173477009039475168017709900129391137881248534255949312866653465033728846390649968460644741907524313323903404908195233044389559060547854954620263256676813262435925020249516275607080900436460421497025691488555265022810327762115842282433269528629137662675481993546118143913367579700141255870143319434764035725376914388899683088262844616425575034001428982557620386364384137906519612917777354183694676232982904981261717676191554292570438432239918482261744350470199171258214687683172646078959690569981353264435973965173473319484798758064137926885413552523275720457329477215706850016950046959758389373527538622664943456437071610511521617176237598050900553232154896062817794302268640579555845730600598376482703339859420098582351400179507104569019191359062304102336798080907240196312675268916362136351032648077232914950859151265812143823371072949148088472355286394195993455684156344577951727033374238129903260198160571971183950662758220321837136059718025940870615534713104482272716848395524105913605919812444978458110854511231668173534838253724825347636777581712867205865148285317273569069839935110763432091319780314031658897379628301178409806410175016511072932907832177487566289310650383806093372841399226733384778203302020700517188941706465146238366720632742644336612174011766914919235570905644803016342294301837655263108450172510307540942604409687066288066265900569082451407632599158164499361455172452057020443093722305550217222299706209749268609762787409626448772056043078634808885709143464793241536214303199965695610753570417207285334250171325558818113295504095217830139465216436594262960768570585698507157151317262928960072587601564840556088613165411835958628710665496282599535127193244635791046554389165150954187306071015034430609582302257455974944275067630926322529966338219395202927917973247094559691016402983683080426309910481567503623509654924302589575273521412445149542462972258510120707802110188106722347972579330653187713438466713807546383471635428854957610942841898601794658721444495198801550804042506452191484989920400007310672369944655246020908767882300064337725657385010969899058191290957079866699453765080407917852438222041070599278889267745752084287526377986730360561230710723922581504781379172731261234878334034473833573601973235946604273704635201327182592410906040097638585857716958419563109577748529579836844756803121874818202833941887076311731615289811756429711334181497218078040465077657204457082859417475114926179367379999220181789399433337731146911970737861041963986422166045588965683206701337505745038872111332436739840284188639147633491695114032583475841514170325690161784931455706904169858050217798497637014758914810543205854914100662201721719726878930012101267481270235940855162601689425111458499658315589660460091525797881670384625905383256920520425791378948827579603278877535466861441826827797651258953563761485994485049706638406266121957141911063246061774180577212381659872472432252969098533628440799030007594546281549235506086481557928961969617060715201589825299772803520002610888814176506636216905928021516429198484077446143617891415191517976537848282687018750030264867608433204658525470555882410254654806040437372771834769014720664234434374255514129178503032471263418076525187802925534774001104853996960549926508093910691337614841834884596365621526610332239417467064368340504749943339802285610313083038484571294767389856293937641914407036507544622061186499127249643799875806537850203753189972618014404667793050140301580709266213229273649718653952866567538572115133606114457222800851183757899219543063413692302293139751143702404830227357629039911794499248480915071002444078482866598579406525539141041497342780203520135419925977628178182825372022920108186449448349255421793982723279357095828748597126780783134286180750497175747373730296280477376908932558914598141724852658299510882230055223242218586191394795184220131553319634363922684259164168669438122537135960710031743651959027712571604588486044820674410935215327906816032054215967959066411120187618531256710150212239401285668608469435937408158536481912528004920724042172170913983123118054043277015835629513656274610248827706488865037765175678806872498861657094846665770674577000207144332525555736557083150320019082992096545498737419756608619533492312940263904930982014700371161829485939931199955070455381196711289367735249958182011774799788636393286405807810818657337668157893827656450642917396685579555053188715314552353070355994740186225988149854660737787698781542360397080977412361518245964026869979609564523828584235953564615185448165799966460648261396618720304839119560250381111550938420209894591555760083897989949964566262540514195610780090298667014635238532066032574466820259430618801773091109212741138269148784355679352572808875543164693077235363768226036080174040660997151176880434927489197133087822951123746632635635328517394189466510943745768270782209928468034684157443127739811044186762032954475468077511126663685479944460934809992951875666499902261686019672053749149951226823637895865245462813439289338365156536992413109638102559114643923805213907862893561660998836479175633176725856523591069520326895990054884753424160586689820067483163174286329119633399132709086065074595260357157323069712106423424081597068328707624437165532750228797802598690981111226558888151520837482450034463046505984569690276166958278982913613535306291331427881888249342136442417833519319786543940201465328083410341785272489879050919932369270996567133507711905899945951923990615156165480300145359212550696405345263823452155999210578191371030188979206408883974767667144727314254467923500524618849237455307575734902707342496298879996942094595961008702501329453325358045689285707241207965919809225550560061971283541270202072583994171175520920820151096509526685113897577150810849443508285458749912943857563115668324566827992991861539009255871716840495663991959154034218364537212023678608655364745175654879318925644085274489190918193411667583563439758886046349413111875241038425467937999203546910411935443113219136068129657568583611774564654674861061988591414805799318725367531243470335482637527081353105570818049642498584646147973467599315946514787025065271083508782350656532331797738656666181652390017664988485456054961300215776115255813396184027067814900350252876823607822107397102339146870159735868589015297010347780503292154014359595298683404657471756232196640515401477953167461726208727304820634652469109953327375561090578378455945469160223687689641425960164689647106348074109928546482353083540132332924864037318003195202317476206537726163717445360549726690601711176761047774971666890152163838974311714180622222345718567941507299526201086205084783127474791909996889937275229053674785020500038630036526218800670926674104806027341997756660029427941090400064654281074454007616429525362460261476180471744322889953285828397762184600967669267581270302806519535452053173536808954589902180783145775891280203970053633193821100095443241244197949192916205234421346395653840781209416214835001155883618421164283992454027590719621537570187067083731012246141362048926555668109467076386536083015847614512581588569610030337081197058344452874666198891534664244887911940711423940115986970795745946337170243268484864632018986352827092313047089215684758207753034387689978702323438584381125011714013265769320554911860153519551654627941175593967947958810333935413289702528893533748106257875620364294270257512121137330213811951395756419122685155962476203282038726342066227347868223036522019655729325905068134849292299647248229359787842720945578267329975853818536442370617353517653060396801087899490506654491544577952166038552398013798104340564182403396162494910454712104839439200945914647542424785991096900046541371091630096785951563947332190934511838669964622788855817353221326876634958059123761251203010983867841195725887799206041260049865895027247133146763722204388398558347770112599424691208308595666787531942465131444389971195968105937957532155524204659410081418351120174196853432672343271868099625045432475688702055341969199545300952644398446384346598830418262932239295612610045884644244285011551557765935780379565026806130721758672048541797157896401554276881090475899564605488362989140226580026134158039480357971019004151547655018391755772677897148793477372747525743898158705040701968215101218826088040084551332795162841280679678965570163917067779841529149397403158167896865448841319046368332179115059107813898261026271979696826411179918656038993895418928488851750122504754778999508544083983800725431468842988412616042682248823097788556495765424017114510393927980290997604904428832198976751320535115230545666467143795931915272680278210241540629795828828466355623580986725638200565215519951793551069127710538552661926903526081367717666435071213453983711357500975854405939558661737828297120544693182260401670308530911657973113259516101749193468250063285777004686987177255226525708428745733039859744230639751837209975339055095883623642814493247460522424051972825153787541962759327436278819283740253185668545040893929401040561666867664402868211607294830305236465560955351079987185041352121321534713770667681396211443891632403235741573773787908838267618458756361026435182951815392455211729022985278518025598478407179607904114472041476091765804302984501746867981277584971731733287305281134969591668387877072315968334322509070204019030503595891994666652037530271923764252552910347950343816357721698115464329245608951158732012675424975710520894362639501382962152214033621065422821876739580121286442788547491928976959315766891987305176388698461503354594898541849550251690616888419122873385522699976822609645007504500096116866129171093180282355042553653997166054753907348915189650027442328981181709248273610863801576007240601649547082331349361582435128299050405405333992577071321011503713898695076713447940748097845416328110406350804863393555238405735580863718763530261867971725608155328716436111474875107033512913923595452951407437943144900950809932872153235195999616750297532475931909938012968640379783553559071355708369947311923538531051736669154087312467233440702525006918026747725078958903448856673081487299464807786497709361969389290891718228134002845552513917355978456150353144603409441211512001738697261466786933733154341007587514908295822756919350542184106448264951943804240543255345965248373785310657979037977505031436474651422484768831323479762673689855474944277949916560108528257618964374464656819789319422077536824661110427671936481836360534108748971066866318805026555929568123959680449295166615409802610781691689418764353363449482900125929366840591370059526914934421861891742142561071896846626335874414976973921566392767687720145153302241853125308442727245771161505550519076276250016522166274796257424425420546785767478190959486500575711016264847833741198041625940813327229905891486422127968042984725356237202887830051788539737909455265135144073130049869453403245984236934627060242579432563660640597549471239092372458126154582526667304702319359866523378856244229188278436440434628094888288712101968642736370461639297485616780079779959696843367730352483047478240669928277140069031660709951473154191919911453182543906294573298686613524886500574780251977607442660798300291573030523199052185718628543687577860915726925232573171665625274275808460620177046433101212443409281314659760221360416223031167750085960128475289259463348312408766740128170543067985261868949895004918275008304998926472034986965363326210919830621495095877228260815566702155693484634079776879525038204442326697479264829899016938511552124688935873289878336267819361764023681714606495185508780596635354698788205094762016350757090024201498400967867845405354130050482404996646978558002628931826518708714613909521454987992300431779500489569529280112698632533646737179519363094399609176354568799002814515169743717518330632232942199132137614506411391269837128970829395360832883050256072727563548374205497856659895469089938558918441085605111510354367477810778500572718180809661542709143010161515013086522842238721618109043183163796046431523184434669799904865336375319295967726080853457652274714047941973192220960296582500937408249714373040087376988068797038047223488825819819025644086847749767508999164153502160223967816357097637814023962825054332801828798160046910336602415904504637333597488119998663995617171089911809851197616486499233594328274275983382931099806461605360243604040848379619072542165869409486682092396143083817303621520642297839982533698027039931804024928814430649614747600087654305571672697259114631990688823893005380061568007730984416061355843701277573463708822073792921409548717956947854414951731561828176343929570234710460088230637509877521391223419548471196982303169544468045517922669260631327498272520906329003279972932906827204647650366969765227673645419031639887433042226322021325368176044169612053532174352764937901877252263626883107879345194133825996368795020985033021472307603375442346871647223795507794130304865403488955400210765171630884759704098331306109510294140865574071074640401937347718815339902047036749084359309086354777210564861918603858715882024476138160390378532660185842568914109194464566162667753712365992832481865739251429498555141512136758288423285957759412684479036912662015308418041737698963759002546999454131659341985624780714434977201991702665380714107259910648709897259362243300706760476097690456341576573395549588448948093604077155688747288451838106069038026528318275560395905381507241627615047252487759578650784894547389096573312763852962664517004459626327934637721151028545472312880039058405918498833810711366073657536918428084655898982349219315205257478363855266205400703561310260405145079325925798227406012199249391735122145336707913500607486561657301854049217477162051678486507913573336334257685988361252720250944019430674728667983441293018131344299088234006652915385763779110955708000600143579956351811596764725075668367726052352939773016348235753572874236648294604770429166438403558846422370760111774821079625901180265548868995181239470625954254584491340203400196442965370643088660925268811549596291166168612036195319253262662271108142149856132646467211954801142455133946382385908540917878668826947602781853283155445565265933912487885639504644196022475186011405239187543742526581685003052301877096152411653980646785444273124462179491306502631062903402737260479940181929954454297256377507172705659271779285537195547433852182309492703218343678206382655341157162788603990157495208065443409462446634653253581574814022471260618973060860559065082163068709634119751925774318683671722139063093061019303182326666420628155129647685313861018672921889347039342072245556791239578260248978371473556820782675452142687314252252601795889759116238720807580527221031327444754083319215135934526961397220564699247718289310588394769170851420631557192703636345039529604362885088555160008371973526383838996789184600327073682083234847108471706160879195227388252347506380811606090840124222431476103563328940609282430125462013806032608121942876847907192546246309055749298781661271916548229644317263587524548607563020667656942355342774617635549231817456159185668061686428714964129290560130053913469569829490891003991259088290348791943368696942620662946948514931472688923571615032405542263391673583102728579723061998175868700492227418629077079508809336215346303842967525604369606110193842723883107587771653594778681499030978765900869583480043137176832954871752604714113064847270887246697164585218774442100900090916189819413456305028950484575822161887397443918833085509908566008543102796375247476265353031558684515120283396640547496946343986288291957510384781539068343717740714095628337554413567955424664601335663617305811711646062717854078898495334329100315985673932305693426085376230981047171826940937686754301837015557540822371538037838383342702379535934403549452173960327095407712107332936507766465603712364707109272580867897181182493799540477008369348889220963814281561595610931815183701135104790176383595168144627670903450457460997444500166918675661035889313483800512736411157304599205955471122443903196476642761038164285918037488354360663299436899730090925177601162043761411616688128178292382311221745850238080733727204908880095181889576314103157447684338100457385008523652069340710078955916549813037292944462306371284357984809871964143085146878525033128989319500645722582281175483887671061073178169281242483613796475692482076321356427357261609825142445262515952514875273805633150964052552659776922077806644338105562443538136258941809788015677378951310313157361136026047890761945591820289365770116416881703644242694283057457471567494391573593353763114830246668754727566653059819746822346578699972291792416156043557665183382167059157867799311835820189855730344883681934418305987021880502259192818047775223884407167894780414701414651073580452021499197980812095692195622632313741870979731320870864552236740416185590793816745658234353037283309503729022429802768451559528656923189798000383061378732434546500582722712325031420712488100290697226311129067629080951145758060270806092801504406139446350643069742785469477459876821004441453438033759717384777232052065301037861326418823586036569054773343070911759152582503029410738914441818378779490613137536794654893375260322906277631983337976816641721083140551864133302224787118511817036598365960493964571491686005656771360533192423185262166760222073368844844409234470948568027905894191829969467724456269443308241243846160408284006424867072583661011433404214473683453638496544701067827313169538435919120440283949541956874453676459875488726170687163109591315801609722382049772577307454562979127906177531663252857205858766376754282917933549923678212008601904369428956102301731743150352204665675088491593025926618816581008701658499456495586855628208747248318351516339189292646558880593601275151838235485893426165223086697314511412035659916934103076974774451947043836739600076578628245472064617380804602903639144493859012422380173377038154675297645596518492676039300171943042511794045679862114630138402371099347243455794730048929825402680821621522346560274258486595687074510352794291633405915025075992398611224340312056999780516223878772230396359709132856830486160362127579561601328561866388146004722200580017580282279272167842720649966956840905752590774886105493806116954293569077377792821084159737469613143291808510446953973485067590503662391722108732333169909603363771705474725026941732982890400239372879549386540463828596742216318201530139629734398479588628632934746650690284066719018081265539973675916799759010867483920062877888531102781695087545740384607594616919584610655963327283485609570305572502494416337066573150237126843581984154103154401008430380631442183776750349813408169325201240813452285974626715177152223063741359255747513535160669108359443999692315898156732033027129284241219651936303734407981204656795322986357374589031654007016472204989445629050395873788912680565516464274460174738175296313458739390484560414203426465560422112239134631023161290836446988901247285192778589195228773637440432659264672239982186452797664826673070168802722052338600372842903155828454593854349099449420750911108532138744823216151007808922516285123275724355101999038195993350032641446053470357293073912578481757987468353429629749652545426864234949270336399427519354240001973125098882419600095766257217621860474573769577649582201796258392376391717855799468922496750179251915218219624653575570564228220399546682648329822996167217080156801080799777126517156274295763666959661983507435667132218383358509536665806605597148376773866922551603463644386269977295750658468929599809168949981898588529537874489519527097766262684177088590284321676352132630838812766335363319004134332844347630067982023716933653652880580156390360562722752187272454764258840995216482554453662083811789117725225682611478014242896970967121967502094421226279437073328703410646312100557376727450271638975234111426287828736758358819056742163061523416789476056879277154789714326222041069587947186435439940738639948986836168919377836648327137363654676901173760246643082285362494712605173293777247276797635865806019396287718060679122426813922872134061694882029506831654589707623668302556167559477498715183426989208952182644710514911419441192277010977616645850068963849426165593473112961064282379048216056210094265076173838082479030510998790719611852832556787472942907151041468948104916751035295897242381802288151276582257190705537652455285511598636421244284176256230139538669970308943645907600684938040875210854159851278070333207779865635907968462191534944587677170063778573171211036517486371634098385626541555573292664616402279791195975248525300376741774056125700303625811704838385391207273191845064713669122576415213769896260940351804147432053600369234179035440735703058314741623452840188940808983125191307741823338981880316339159565954543405777784331681162551898060409183018907512170192983622897099598983405484962284289398469847938668614293324543983592637036699355184231661615244505980576745765335552338715678211466689996845227042954589710922163652573965950289645637766038988037941517917867910675199009966139206238732318786758420544279396366759104126821843375015743069045967947046685602358283919759975285865384338189120042853787549302768972168199113340697282255535300044743958830079799736518459131437946494086272149669719100359399974735262764126125995350902609540048669398955899487421379590802893196914845826873123710180229775301190684280440780938156598081694611679374425663244656799606363751546304833112722231812338371779800439731087402647536582575657351059978314264831879619843765495877803685261751835391844920488198629786329743136948511780579298636452193232481339393090754566368038513630619718033957979522539508697432546502659123585049283028832934489284591373621624852528877442891851104093746333590660233239711922814450735588373324057814862662207486215513375036775585494138678352928273109003823116855374520901095101174796663003330352534143230024288248051396631446632656081582045216883922312025671065388459503224002320453633895521539919011035217362720909565500846486605368975498478995875596103167696587161281951919668893326641203784750417081752273735270989343717167642329956935697166213782736138899530515711822960896394055380431939398453970864418654291655853168697537052760701061488025700785387150835779480952313152747735711713643356413242974208137266896149109564214803567792270566625834289773407718710649866150447478726164249976671481383053947984958938064202886667951943482750168192023591633247099185942520392818083953020434979919361853380201407072481627304313418985942503858404365993281651941497377286729589582881907490040331593436076189609669494800067194371424058105327517721952474344983414191979918179909864631583246021516575531754156198940698289315745851842783390581029411600498699307751428513021286202539508732388779357409781288187000829944831476678183644656510024467827445695591845768068704978044824105799710771577579093525803824227377612436908709875189149049904225568041463131309240101049368241449253427992201346380538342369643767428862595140146178201810734100565466708236854312816339049676558789901487477972479202502227218169405159042170892104287552188658308608452708423928652597536146290037780167001654671681605343292907573031466562485809639550080023347676187068086526878722783177420214068980703410506200235273632267291964034093571225623659496432076928058165514428643204955256838543079254299909353199329432966018220787933122323225928276556048763399988478426451731890365879756498207607478270258861409976050788036706732268192473513646356758611212953074644777149423343867876705824452296605797007134458987594126654609414211447540007211790607458330686866231309155780005966522736183536340439991445294960728379007338249976020630448806064574892740547730693971337007962746135534442514745423654662752252624869916077111131569725392943756732215758704952417232428206555322808868670153681482911738542735797154157943689491063759749151524510096986573825654899585216747260540468342338610760823605782941948009334370046866568258579827323875158302566720152604684361412652956519894291184887986819088277339147282063794512260294515707367105637720023427811802621502691790400488001808901847311751199425460594416773315777951735444490965752131026306836047140331442314298077895617051256930051804287472368435536402764392777908638966566390166776625678575354239947427919442544664643315554138265543388487778859972063679660692327601733858843763144148113561693030468420017434061395220072403658812798249143261731617813894970955038369479594617979829257740992171922783223006387384996138434398468502234780438733784470928703890536420557474836284616809363650973790900204118525835525201575239280826462555785658190226958376345342663420946214426672453987171047721482128157607275305173330963455909323664528978019175132987747952929099598069790148515839540444283988381797511245355548426126784217797728268989735007954505834273726937288386902125284843370917479603207479554080911491866208687184899550445210616155437083299502854903659617362726552868081324793106686855857401668022408227992433394360936223390321499357262507480617409173636062365464458476384647869520547719533384203403990244761056010612777546471464177412625548519830144627405538601855708359981544891286863480720710061787059669365218674805943569985859699554089329219507269337550235821561424994538234781138316591662683103065194730233419384164076823699357668723462219641322516076261161976034708844046473083172682611277723613381938490606534404043904909864126903479263503943531836741051762565704797064478004684323069430241749029731181951132935746854550484711078742905499870600373983113761544808189067620753424526993443755719446665453524088287267537759197074526286322840219629557247932987132852479994638938924943286917770190128914220188747760484939855471168524810559991574441551507431214406120333762869533792439547155394213121021954430556748370425907553004950664994802614794524739012802842646689229455664958621308118913500279654910344806150170407268010067948926855360944990373928383520627992820181576427054962997401900837493444950600754365525758905546552402103412862124809003162941975876195941956592556732874237856112669741771367104424821916671499611728903944393665340294226514575682907490402153401026923964977275904729573320027982816062130523130658731513076913832317193626664465502290735017347656293033318520949298475227462534564256702254695786484819977513326393221579478212493307051107367474918016345667888810782101151826314878755138027101379868751299375133303843885631415175908928986956197561123025310875057188962535763225834275763348421016668109884514141469311719314272028007223449941999003964948245457520704922091620614222912795322688239046498239081592961111003756999529251250673688233852648213896986384052437049402152187547825163347082430303521036927849762517317825860862215614519165573478940019558704784741658847364803865995119651409542615026615147651220820245816010801218275982577477652393859159165067449846149161165153821266726927461290533753163055654440793427876550267301214578324885948736899073512166118397877342715872870912311383472485146035661382188014840560716074652441118841800734067898587159273982452147328317214621907330492060817440914125388918087968538960627860118193099489240811702350413554126823863744341209267781729790694714759018264824761112414556423937732224538665992861551475342773370683344173073150805440138894084087253197595538897613986400165639906934600670780501058567196636796167140097031535132386972899001749862948883362389858632127176571330142071330179992326381982094042993377790345261665892577931395405145369730429462079488033141099249907113241694504241391265397274078984953073730364134893688060340009640631540701820289244667315059736321311926231179142794944897281477264038321021720718017561601025111179022163703476297572233435788863537030535008357679180120653016668316780269873860755423748298548246360981608957670421903145684942967286646362305101773132268579232832164818921732941553151386988781837232271364011755881332524294135348699384658137175857614330952147617551708342432434174779579226338663454959438736807839569911987059388085500837507984051126658973018149321061950769007587519836861526164087252594820126991923916722273718430385263107266000047367872474915828601694439920041571102706081507270147619679971490141639274282889578424398001497985658130305740620028554097382687819891158955487586486645709231721825870342960508203415938806006561845735081804032347750084214100574577342802985404049555529215986404933246481040773076611691605586804857302606467764258503301836174306413323887707999698641372275526317649662882467901094531117120243890323410259937511584651917675138077575448307953064925086002835629697045016137935696266759775923436166369375035368699454550392874449940328328128905560530091416446608691247256021455381248285307613556149618444364923014290938289373215312818797541139219415606631622784836152140668972661027123715779503062132916001988806369127647416567067485490795342762338253943990022498972883660263920518704790601584084302914787302246651371144395418253441269003331181914268070735159284180415100555199146564934872796969351992963117195821262627236458009708099166752820365818699111948365866102758375863322993225541477479210421324166848264953111826527351008031659958888814809945737293785681411438021523876706455063233067233939551964260397443829874822322662036352861302543796600943104500158604854027036789711934695579989189112302233381602302236277726084846296189550730850698061500281436425336666311433321645213882557346329366870956708432252564333895997812402164189946978348320376011613913855499933990786652305860332060641949298931012423081105800169745975038516887112037747631577311831360002742502722451570906304496369230938382329175076469684003556425503797106891999812319602533733677437970687713814747552190142928586781724044248049323750330957002929126630316970587409214456472022710796484778657310660832173093768033821742156446602190335203981531618935787083561603302255162155107179460621892674335641960083663483835896703409115513087820138723494714321400450513941428998350576038799343355677628023346565854351219361896876831439866735726040869511136649881229957801618882834124004126142251475184552502502640896823664946401177803776799157180146386554733265278569418005501363433953502870836220605121839418516239153709790768084909674194289061134979961034672077354959593868862427986411437928435620575955500144308051267664432183688321434583708549082240014585748228606859593502657405750939203135881722442164955416889785558265198046245527898343289578416968890756237467281044803018524217706136533236073856228166664597654076844715963930782091017090763377917711485205493367936868430832404126789220929930411890501756484917499452393770674524578019171841679541825554377930299249277892416277257788147974770446005423669346157135208417428211847353652367573702352791459837645712257646122605628127852169580892808988394594406165340521932514843306105322700231133680378433377389724881307874325614952744243584753011150345103737688223837573804282007358586938044331529253129961025096113761670187568525921208929131354473196308440066835155160913925692912175784379179004808848023029304392630921342768601226558630456913133560978156776098711809238440656353136182676923761613389237802972720736243967239854144480757286813436768000573823963610796223140429490728058551444771338682314499547929338131259971996894072233847404542592316639781608209399269744676323921370773991899853301483814622364299493902073285072098040905300059160091641710175605409814301906444379905831277826625762288108104414704097708248077905168225857235732665234414956169007985520848841886027352780861218049418060017941147110410688703738674378147161236141950474056521041002268987858525470689031657094677131822113205505046579701869337769278257145248837213394613987859786320048011792814546859096532616616068403160077901584946840224344163938313618742275417712170336151163782359059685168880561304838542087505126933144171705880517278127917564053282929427357971823360842784676292324980318169828654166132873909074116734612367109059236155113860447246378721244612580406931724769152219217409096880209008801535633471775664392125733993165330324425899852598966724744126503608416484160724482125980550754851232313331300621490042708542735985913041306918279258584509440150719217604794274047740253314305451367710311947544521321732225875550489799267468541529538871443696399406391099267018219539890685186755868574434469213792094590683677929528246795437302263472495359466300235998990248299853826140395410812427393530207575128774273992824866921285637240069184859771126480352376025469714309316636539718514623865421671429236191647402172547787238964043145364190541101514371773797752463632741619269990461595895793940622986041489302535678633503526382069821487003578061101552210224486633247184367035502326672749787730470216165019711937442505629639916559369593557640005236360445141148916155147776301876302136068825296274460238077523189646894043033182148655637014692476427395401909403584437251915352134557610698046469739424511797999048754951422010043090235713636892619493763602673645872492900162675597083797995647487354531686531900176427222751039446099641439322672532108666047912598938351926694497553568096931962642014042788365702610390456105151611792018698900673027082384103280213487456720062839744828713298223957579105420819286308176631987048287388639069922461848323992902685392499812367091421613488781501234093387999776097433615750910992585468475923085725368613605356762146929424264323906626708602846163376051573599050869800314239735368928435294958099434465414316189806451480849292695749412903363373410480943579407321266012450796613789442208485840536446021616517885568969302685188950832476793300404851688934411125834396590422211152736276278672366665845757559585409486248261694480201791748223085835007862255216359325125768382924978090431102048708975715033330963651576804501966025215527080352103848176167004443740572131294252820989545456276344353575741673638980108310579931697917916718271145837435222026387771805250290791645414791173616253155840768495583288190293564201219633684854080865928095131505012602919562576032932512847250469881908146475324342363863860247943921015193235101390117789997483527186469346024554247028375300033725403910085997650987642832802908445662021678362267272292737780213652404028817217012490974899454430826861772239385250883760749742195942655217301733355851389407457348144161511380845358039740277795072051893487170722955427683655826706766313911972211811528466502223383490906676554168336907959409404576472940901354356409277969379842065738891481990225399022315913388145851487225126560927576795873759207013915029216513720851137197522734365458411622066281660256333632074449918511469174455062297146086578736313585389023662557285424516018080487167823688885575325066254262367702604215835160174851981885460860036597606743233346410471991027562358645341748631726556391320606407754779439671383653877377610828300019937359760370467245737880967939894493795829602910746901609451288456550071458091887879542641820145369659962842686882363495879277007025298960996798975941955735253914237782443302746708282008722602053415292735847582937522487377937899136764642153727843553986244015856488692101644781661602962113570056638347990334049623875941092886778920270077504951511405782565295015024484968204744379710872943108541684540513016310902267112951959140520827546866418137305837933236150599142045255880213558474751516267815309465541240524091663857551298894834797423322854504140527354235070335984964593699534959698554244978249586929179182415068053002553370412778703476446244329205906832901886692400222391918714603175399666877477960121790688623311002908668305431787009355066944389131913333586368037447530664502418437136030852288582121720231274167009740351431532131803978033680228154223490183737494117973254478594157962104378787072154814091725163615415163381388912588517924237727229603497305533840942889918919161186249580560073570527227874940321250645426206304469470804277945973817146810395192821550688079136701210109944220737024613687196031491162370967939354636396448139025711768057799751751298979667073292674886430097398814873780767363792886767781170520534367705731566895899181530825761606591843760505051704242093231358724816618683821026679970982966436224723644898648976857100173643547336955619347638598187756855912376232580849341570570863450733443976604780386678461711520325115528237161469200634713570383377229877321365028868868859434051205798386937002783312365427450532283462669786446920780944052138528653384627970748017872477988461146015077617116261800781557915472305214759943058006652042710117125674185860274188801377931279938153727692612114066810156521441903567333926116697140453812010040811760123270513163743154487571768761575554916236601762880220601068655524141619314312671535587154866747899398685510873576261006923021359580838145290642217792987748784161516349497309700794368305080955621264592795333690631936594413261117944256602433064619312002953123619348034504503004315096798588111896950537335671086336886944665564112662287921812114121425167348136472449021275252555647623248505638391391630760976364990288930588053406631352470996993362568102360392264043588787550723319888417590521211390376609272658409023873553418516426444865247805763826160023858280693148922231457758783791564902227590699346481624734399733206013058796068136378152964615963260698744961105368384203105364183675373594176373955988088591188920114871545460924735613515979992999722298041707112256996310945945097765566409972722824015293663094891067963296735505830412258608050740410916678539569261234499102819759563955711753011823480304181029089719655278245770283085321733741593938595853203645590564229716679900322284081259569032886928291260139267587858284765599075828016611120063145411315144108875767081854894287737618991537664505164279985451077400771946398046265077776614053524831090497899859510873112620613018757108643735744708366215377470972660188656210681516328000908086198554303597948479869789466434027029290899143432223920333487108261968698934611177160561910681226015874410833093070377506876977485840324132474643763087889666151972556180371472590029550718424245405129246729039791532535999005557334600111693557020225722442772950263840538309433999383388018839553821540371447394465152512354603526742382254148328248990134023054550811390236768038649723899924257800315803725555410178461863478690646045865826036072306952576113184134225274786464852363324759102670562466350802553058142201552282050989197818420425028259521880098846231828512448393059455162005455907776121981297954040150653985341579053629101777939776957892084510979265382905626736402636703151957650493344879513766262192237185642999150828898080904189181015450813145034385734032579549707819385285699926238835221520814478940626889936085239827537174490903769904145555260249190126341431327373827075950390882531223536876389814182564965563294518709637484074360669912550026080424160562533591856230955376566866124027875883101021495284600804805028045254063691285010599912421270508133194975917146762267305044225075915290251742774636494555052325186322411388406191257012917881384181566918237215400893603475101448554254698937834239606460813666829750019379115061709452680984785152862123171377897417492087541064556959508967969794980679770961683057941674310519254486327358885118436597143583348756027405400165571178309126113117314169066606067613797690123141099672013123730329707678988740099317309687380126740538923612230370779727025191340850390101739924877352408881040807749924412635346413181858792480760553268122881584307471326768283097203149049868884456187976015468233715478415429742230166504759393312132256510189175368566338139736836336126010908419590215582111816677413843969205870515074254852744810154541079359513596653630049188769523677579147319184225806802539818418929888943038224766186405856591859943091324575886587044653095332668532261321209825839180538360814144791320319699276037194760191286674308615217243049852806380129834255379486287824758850820609389214668693729881191560115633701248675404205911464930888219050248857645752083363921499441937170268576222251074166230901665867067714568862793343153513505688216165112807318529333124070912343832502302341169501745502360505475824093175657701604884577017762183184615567978427541088499501610912720817913532406784267161792013428902861583277304794830971705537485109380418091491750245433432217445924133037928381694330975012918544596923388733288616144238100112755828623259628572648121538348900698511503485369544461542161283241700533583180520082915722904696365553178152398468725451306350506984981006205514844020769539324155096762680887603572463913955278222246439122592651921288446961107463586148252820017348957533954255019475442643148903233373926763409115527189768429887783617346613535388507656327107814312435018965109238453660236940276060642119384227665755210663671879603217527184404651560427289869560206997012906367847161654793068868305846508082886614111979138822898112498261434559408961813509226857611474609406147937240008842153535862052780125014270055274468359151840373309373580494342483940467505708347927948338133276237937844629209323999417593374917899786484958148818865149169302451512835579818112344900827168644548306546633975256079615935830821400021951611342337058359111545217293721664061708131602078213341260356852013161345136871600980378712556766143923146458085652084039744217352744813741215277475202259244561520365608268890193913957991844109971588312780020898275935898106482117936157951837937026741451400902833064466209280549839169261068975151083963132117128513257434964510681479694782619701483204392206140109523453209269311762298139422044308117317394338867965739135764377642819353621467837436136161591167926578700137748127848510041447845416464568496606699139509524527949914769441031612575776863713634644477006787131066832417871556281779122339077841275184193161188155887229676749605752053192594847679397486414128879475647133049543555044790277128690095643357913405127375570391806822344718167939329121448449553897728696601037841520390662890781218240141299368590465146519209198605347788576842696538459445700169758422531241268031418456268722581132040056433413524302102739213788415250475704533878002467378571470021087314693254557923134757243640544448132093266582986850659125571745568328831440322798049274104403921761438405750750288608423536966715191668510428001748971774811216784160854454400190449242294333666338347684438072624307319019363571067447363413698467328522605570126450123348367412135721830146848071241856625742852208909104583727386227300781566668914250733456373259567253354316171586533339843321723688126003809020585719930855573100508771533737446465211874481748868710652311198691114058503492239156755462142467550498676710264926176510110766876596258810039163948397811986615585196216487695936398904500383258041054420595482859955239065758108017936807080830518996468540836412752905182813744878769639548306385089756146421874889271294890398025623046812175145502330254086076115859321603465240763923593699949180470780496764486889980902123735780457040380820770357387588525976042434608851075199334470112741787878845674656640471901619633546770714090590826954225196409446319547658653032104723804625249971910690110456227579220926904132753699634145768795242244563973018311291451151322757841320376225862458224784696669785947914981610522628786944136373683125108310682898766123782697506343047263278453719024447970975017396831214493357290791648779915089163278018852504558488782722376705263811803792477835540018117452957747339714012352011459901984753358434861297092928529424139865507522507808919352104173963493428604871342370429572757862549365917805401652536330410692033704691093097588782938291296447890613200063096560747882082122140978472301680600835812336957051454650181292694364578357815608503303392466039553797630836137289498678842851139853615593352782103740733076818433040893624460576706096188294529171362940967592507631348636606011346115980434147450705511490716640635688739020690279453438236930531133440901381392849163507484449076828386687476663619303412376248380175840467851210698290605196112357188811150723607303158506622574566366740720668999061320627793994112805759798332878792144188725498543014546662945079670707688135022230580562225942983096887732856788971494623888272184647618153045844390967248232348259587963698908456664795754200195991919240707615823002328977439748112690476546256873684352229063217889227643289360535947903046811114130586348244566489159211382258867880972564351646404364328416076247766114349880319792230537889671148058968061594279189647401954989466232962162567264739015818692956765601444248501821713300527995551312539849919933907083138030214072556753022600033565715934283182650908979350869698950542635843046765145668997627989606295925119763672907762567862769469947280606094290314917493590511523235698715397127866718077578671910380368991445381484562682604003456798248689847811138328054940490519768008320299631757043011485087384048591850157264392187414592464617404735275250506783992273121600117160338604710710015235631159734711153198198710616109850375758965576728904060387168114313084172893710817412764581206119054145955378853200366615264923610030157044627231777788649806700723598889528747481372190175074700005571108178930354895017924552067329003818814068686247959272205591627902292600592107710510448103392878991286820705448979977319695574374529708195463942431669050083984398993036790655541596099324867822475424361758944371791403787168166189093900243862038610001362193667280872414291108080291896093127526202667881902085595708111853836166128848729527875143202956393295910508349687029060692838441522579419764824996318479414814660898281725690484184326061946254276693688953540732363428302189694947766126078346328490315128061501009539164530614554234923393806214007779256337619373052025699319099789404390847443596972052065999017828537676265683558625452697455260991024576619614037537859594506363227095122489241931813728141668427013096050734578659047904243852086508154491350136491698639048125666610843702294730266721499164849610746803261583352580352858275799038584091667618877199539888680431991650866887781701439663176815592262016991396613153738021294160006906947533431677802632207226265881842757216055461439677336258462997385077307751473833315101468395296411397329672457933540390136107395245686243008096720460995545708974893048753897955544443791303790422346037768729236001386569593952300768091377768847789746299699489949016141866131552200856673695770822720338936659590666350594330040363762591189195691561626122704788696510356062748423100605472091437069471661080277379848576543481249822444235828329813543645124092220896643987201997945619030397327254617823136363375927622656301565813545578319730419339269008282952718252138855126583037630477490625995514925943105307478901043009876580816508144862607975129633326675259272351611791836777128931053144471668835182920514343609292493191180249366051791485330421043899773019267686085347768149502299280938065840007311767895491286098112311307002535600347898600653805084532572431553654422067661352337408211307834360326940015926958459588297845649462271300855594293344520727007718206398887404742186697709349647758173683580193168322111365547392288184271373843690526638607662451284299368435082612881367358536293873792369928837047900484722240370919885912556341130849457067599032002751632513926694249485692320904596897775676762684224768120033279577059394613185252356456291805905295974791266162882381429824622654141067246487216174351317397697122228010100668178786776119825961537643641828573481088089988571570279722274734750248439022607880448075724807701621064670166965100202654371260046641935546165838945950143502160890185703558173661823437491622669077311800121188299737319891006060966841193266075165452741829459541189277264192546108246351931647783837078295218389645376236304858042774417907169146356546201215125418664885396161542055152375000426794253417764590821513675258479774465114750438460596325820468809667795709044645884673847481638045635188183210386594798204376334738389017759714236223057776395541011294523488098341476645559342209402059733452337956309441446698222457026367119493286653989491344225517746402732596722993581333110831711807234044326813737231209669052411856734897392234152750707954137453460386506786693396236535556479102508529284294227710593056660625152290924148057080971159783458351173168204129645967070633303569271821496292272073250126955216172649821895790908865085382490848904421755530946832055636316431893917626269931034289485184392539670922412565933079102365485294162132200251193795272480340133135247014182195618419055761030190199521647459734401211601239235679307823190770288415814605647291481745105388060109787505925537152356112290181284710137917215124667428500061818271276125025241876177485994084521492727902567005925854431027704636911098800554312457229683836980470864041706010966962231877065395275783874454229129966623016408054769705821417128636329650130416501278156397799631957412627634011130135082721772287129164002237230234809031485343677016544959380750634285293053131127965945266651960426350406454862543383772209428482543536823186182982713182489884498260285705690699045790998144649193654563259496570044689011049923939218088155626191834404362264965506449848521612498442375928443642612004256628602157801140467879662339228190804577624109076487087406157070486658398144845855803277997327929143195789110373530019873110486895656281917362036703039179710646309906285483702836118486672219457621775034511770110458001291255925462680537427727378863726783016568351092332280649908459179620305691566806180826586923920561895421631986004793961133953226395999749526798801074576466538377400437463695133685671362553184054638475191646737948743270916620098057717103475575333102702706317395612448413745782734376330101853438497450236265733191742446567787499665000938706441886733491099877926005340862442833450486907338279348425305698737469497333364267191968992849534561045719338665222471536681145666596959735075972188416698767321649331898967182978657974612216573922404856900225324160367805329990925438960169901664189038843548375648056012628830409421321300206164540821986138099462721214327234457806819925823202851398237118926541234460723597174777907172041523181575194793527456442984630888846385381068621715274531612303165705848974316209831401326306699896632888532682145204083110738032052784669279984003137878996525635126885368435559620598057278951754498694219326972133205286374577983487319388899574634252048213337552584571056619586932031563299451502519194559691231437579991138301656117185508816658756751184338145761060365142858427872190232598107834593970738225147111878311540875777560020664124562293239116606733386480367086953749244898068000217666674827426925968686433731916548717750106343608307376281613984107392410037196754833838054369880310983922140260514297591221159148505938770679068701351029862207502287721123345624421024715163941251258954337788492834236361124473822814504596821452253550035968325337489186278678359443979041598043992124889848660795045011701169092519383155609441705397900600291315024253848282782826223304151370929502192196508374714697845805550615914539506437316401173317807741497557116733034632008408954066541694665746735785483133770133628948904397670025863002540635264006601631712883920305576358989492412827022489373848906764385339931878608019223108328847459816417701264089078551777830131616162049792779670521847212730327970738223860581986744668610994383049960437407323195784473254857416239738852016202384784256163512597161783106850156299135559874758848151014815490937380933394074455700842090155903853444962128368313687375166780513082594599771257467939781491953642874321122421579851584491669362551569370916855252644720786527971466476760328471332985501945689772758983450586004316822658631176606237201721007922216410188299330808409384014213759697185976897042759041500946595252763487628135867117352364964121058854934496645898651826545634382851159137631569519895230262881794959971545221250667461174394884433312659432286710965281109501693028351496524082850120190831078678067061851145740970787563117610746428835593915985421673115153096948758378955979586132649569817205284291038172721213138681565524428109871168862743968021885581515367531218374119972919471325465199144188500672036481975944167950887487934416759598361960010994838744709079104099785974656112459851972157558134628546189728615020774374529539536929655449012953097288963767713353842429715394179547179095580120134210175150931491664699052366350233024087218654727629639065723341455005903913890253699317155917179823065162679744711857951506573868504088229934804445549850597823297898617029498418376255258757455303112991914341109413088238114443068843062655305601658801408561023324210300218460588586954418502977463085858496130037238190325162225570729975710727306066072916922978033647048840958711228045188511908718588299514331534128549297173849768523136276076868494780364948299904475715771141080958058141208956059471668626290036145602625334863284986816039463372436667112964460292915746181117789169695839947080954788863503281129626899231110099889317815313946681882028368363373822281414974006917942192888817139116283910295684918233358930813360131488748366464224381776081007739183393749346933644748150564933649323157235306109385796839902153381449126925350768211098738352197507736653475499431740580563099143218212547336281359488317681489194306530426029773885492974570569448783077945878865062970895499843760181694031056909587141386804846359853684034105948341788438963179956468815791937174656705047441528027712541569401365862097760735632832966564135817028088013546326104892768731829917950379944446328158595181380144716817284996793061814177131912099236282922612543236071226270324572637946863533391758737446552006008819975294017572421299723542069630427857950608911113416534893431149175314953530067419744979017235181671568754163484949491289001739377451431928382431183263265079530371177806185851153508809998200482761808307209649636476943066172549186143700971387567940218696710148540307471561091358933165600167252126542502898612259306484105898847129649230941215144563947889999327145875969555737090855150648002321476443037232466147111552578583071024936898814562568786834745518893385181791667579054210421036349316257870476543126790661216644142285017446278477132740595579600648343288827864837043456066966456899746910373987712891593313271266247505582258634928427718355831641593667712218537642376222104779338956378722902509543014182257180331300148113377736941508488867501893156994849838936052666818012783912005801431596441910546663236810148207799356523056490420711364192200177189107935243234322761787712568251126481332974354926568682748715986654943041648468220593921673359485057849622807932422649812705271398407720995707236227009245067665680069149966555737866411877079767754867028786431817941521796178310655030287157272282250812017060713380339641841211253856248920130010782462165136989511064611133562443838185366273563783436921279354709230119655914915800561707258518503167289370411936374780625824298250726464801821523430268081486978164824349353456855843696378384153838051184406043696871666416514036129729992912630842812149152469877429332305214999981829046119471676727503742221367186614654042534463141660649871499001000660041544868437352208483059495953182872280520828676300361091734508632133033647289584176588755345227938480297724485711815574893561311524926772006362198369980664159549388683836411891430443767715498026544959061738265591178545999378510861446014967645550103653971251138583505085112442517772923814396233043724036032603181442991365750246012787514117944901305803452199992701148071712847770301254994886841867572975189214295652512486943983729047410363121899124217339550688778643130750024823361832738729697376598820053895902935486054979802320400472236873557411858132734337978931582039412878989728973298812553514507641535360519462112217000676321611195841029252568536561813138784086477147099724553013170761712163186600291464501378587854802096244703771373587720086738054108140042311418525803293267396324596914044834665722042880679280616029884043400536534009706581694636096660911110968789751801325224478246957913251892122653056085866541115373584912790254654369020869419871125588453729063224423222287139122012248769976837147645598526739225904997885514250047585260297929306159913444898341973583316070107516452301310796620382579278533125161760789984630103493496981494261055367836366022561213767081421091373531780682420175737470287189310207606953355721704357535177461573524838432101571399813798596607129664438314791296359275429627129436142685922138993054980645399144588692472767598544271527788443836760149912897358259961869729756588978741082189422337344547375227693199222635973520722998387368484349176841191020246627479579564349615012657433845758638834735832242535328142047826934473129971189346354502994681747128179298167439644524956655532311649920677163664580318205849626132234652606175413532444702007661807418914040158148560001030119994109595492321434406067634769713089513389171050503856336503545166431774489640061738861761193622676890576955693918707703942304940038440622614449572516631017080642923345170422426679607075404028551182398361531383751432493056398381877995594942545196756559181968690885283434886050828529642437578712929439366177362830136595872723080969468398938676366226456791132977469812675226595621009318322081754694778878755356188335083870248295346078597023609865656376722755704495258739871812593441903785275571333409842450127258596692434317689018966145404453679047136294238156127656824247864736176671770647002431119711090007474065945650315375044177982192306323700872039212085499569681061379189029961178936752146022386905665481382858280449537530160921422195940638787074787991194920898374091788534417523064715030278397979864517336625329511775105559014160459873338186887977858817291976604516353353556047648420520888811722831990044504284486852338334530105533929637308039738230604714104525470094899407601215247602819963846343554852932377161410869591950786873276075400085220065031871239272857835807010762542769655355964789450166013816295177908531139811092831583216931563867459747449584385282701658246192092219529134323496779345585613140207765996142546463288677356891785576835169608392864188830094883324700447958316931533832382377876344426323456301679513671047510469669001217777128065522453689371871451567394733440447280450959433090683667110655953338602938000999949010642769859623260401863733572846679531229683156358145420890540651226419162015504500430562136991850941034609601030543816694795964585804425194905110733387679946734471718615647723811737035654917628707589456035519195603962301157866323750234725054461073979402475184415558178087962822231972692984516683306919505079993357259165675557294585962182052650473353712351623662770479333289322136141858785972771685682725303734836891911847197133753088446777943274857148827821608844765700041403499921376794209627560883081509438030705666022764678117533361028187800710219794428777313146387857817205661409023041499923248268982477222109852189758140879763486146763606368674611966620347304608917277240045953051376938375381543486981101990651706961774052218247422657652138152740612699012706880875386408669901461740890540981877671880076124151967064152117653084325544261017536348281196837493395825742541244634247233586360777980960199745187758845459645895956779558869098404768259253477849930457883128541747079059795909431627722327844578918694214929451540174214623240300841907975296782445969183509474202123617940309048634960534054931299919496087957952586977170236680033862505764938088740994009589948109397983231108838769236490221499111120870639202892490698435333152727991330986335454324971441378059132240814960156485679843966464780280409057580889190254236606774500413415794312112501275232250148067232979652230488493751166084976116412777395311302041566848265531411348993243747890268935173904043294851610659785832253168204202834993641595980197343889883020994152152288611175126686173051956249367180053845637855129171848417841594797435580617856680758491080185805695567990185198397660693358224779136504562705766735170961550493338390452612404395517449136885115987454340932040102218982707539212403241042424451570052968378815749468441508011138612561164102477190903050040240662278945607061512108266146098662040425010583978098192019726759010749924884966139441184159734610382401178556739080566483321039073867083298691078093495828888707110651559651222542929154212923108071159723275797510859911398076844732639426419452063138217862260999160086752446265457028969067192282283045169111363652774517975842147102219099906257373383472726498678244401048998507631630668050267115944636293525120269424810854530602810627264236538250773340575475701704367039596467715959261029438313074897245505729085688496091346323165819468660587092144653716755655531962091865952628448253731353698162517351930115341581171353292035873164168839107994000677266031617527582917398395852606454113318985505747847121053505795649095931672167565624818782002769963734155880000867852567422461511406015760115910256449002264980039498403358091309140197877843650167960167465370287466062584346329708303725980494653589318912163976013193079476972058034710553111117215859219066231028099212084069283091906017370764654655683413207556315315006453462321007133584907633048328153458698497332599801187479664273140279381289961720524540674695271948079930396730194274036466594154400092799908634806622334906695224044652158992864203435098858422692019340575496840904812955522654754650713532842543496616084954788090727649930252702815067862810825243222979985391759845188868387004477101866772159439708514664612871148749531862180941719676843144666435175837688436786081446319641912566574047718699160915550910878919431253671945651261878486910876729910565595155159739659034383628124629118117760949411880105946336671039049777312004243578115790429823045072038322781246413671297959415082918378213212876890545963586369344879749784841123274921331663162812456388238288715648447883142417650147980187858215768793063001153788998014623690135803753306246148576074932567807682651045738059018831237617271889933790487113395588485234240255002352200613574914318259142479829367775490496399350755839668967578364316618369307625603528602940662803255416535431518013714821941772672244005268401996533334184004345525296592918502940131600651124395297874364222806977720437363717873457948420238745151249157913139411148608416429347958793681868609689684640858334131017858142710955416293375915178392341303110543328703526599993904966822112768158316511246866451167351378214345336650598328347443536290312393672084593164394941881138607974670134709640378534907149089842317891739783650654751982883367395714360000003439863363212091718954899055748693397700245632475954504411422582410783866837655467400137324322809113692670682805397549111166171102397437749479335174036135005397581475520834285772800986189401984375446435081498218360112577632447389452051636938585136484259964518361856989088721789764694721246807900330925083496645841656554261294195108847197209106605105540933731954888406444080280579549008076040034154662137669606444293774985897353625591959618552448187940317374508256072895120945456562159540405425814886929842786582357673195799285293120866275922366115137445767916063621675267440451221051052090834707443986137829082352772895849625656881972792768694795806100573787084121444815034797422312103295359297822377134077549545477791813823542607184617108389097825964406170543546968567030745411634244134486308676327949177682923093183221341455482591367202823284396549001805653203960795517074496039006696990334199278212696767771835209083959545341866777944872740383733381985235884202840150981579594685874537989503257362809837592216229258598599123843993575573285028613155970362934249814178056461615863415338635077223269996508860870999964899373049307170967888740149746147542880387421250689212155876692242387434701120990859082164073576380817386959755176083877600277517253037133445654852635661720197563001580049790223419586738061442401502436288957503206533690825756785507020555105572381878574650371086308158185862815883054564662297694803970618265491385181326737485227188267917919091354407852685476254126683398240534022469989966652573155637645862251862823092085424412805997628505488913098331761884983352975136073772030571342739638126588567405013841074788943393996603591853934198416322617654857376671943132840050626295140357877264680649549355746326408186979718630218760025813995719923601345374229758918285167511358171472625828596940798518571870075823122317068134867930884899275181661399609753105295773584618525865211893339375771859916335112163441037910451845019023066893064178977808158101360449495409665363660370075881004450265734935127707426742578608784898185628869980851665713320835842613381142623855420315774246613108873106318111989880289722849790551075148403702290580483052731884959994156606537314021296702220821915862905952604040620011815269664910068587592655660567562963361434230232810747488395040380984981860056164646099819257616235478710913832967563761506732550860683433720438748186791668975746563456020002562889601191100980453350423842063824039434163502977688802779835087481178298349417211674919425601608685332435385951152061809031241698182079314615062073826097180458265687043623935757495737332781578904386011378078508110273049446611821957450170106059384336519458628360682108585130499820420578458577175933849015564447305834515291412561679970569657426139901681932056241927977282026714297258700193234337873153939403115411184101414292741703537542003698760608765500109345299007034032401334806388514095769557147190364152027721127070187421548123931953220997506553022646844227700020589045922742423904937051507367764629844971682121994198274794049092601715727439368569721862936007387077810797440975556627807371228030350048829843919546433753355787895064018998685060281902452191177018634505171087023903398550540704454189088472042376499749035038518949505897971286631644699407490959473411581934618336692169573605081585080837952036335619947691937965065016808710250735070825260046821242820434367245824478859256555487861614478717581068572356895150707602217433511627331709472765932413249132702425519391509083601346239612335001086614623850633127072987745618984384288764099836164964775714638573247333226653894523588365972955159905187411779288608760239306160016168434070611663449248395156319152882728822831375458678269830696691220130954815935450754923554167766876455212545681242936427474153815692219503331560151614492247512488957534835926226263545406704767033866410025277276800886383266629488582740369655329362236090572479794734434077704284318507901973469071141230364111729224929307731939309795452877412451183953480382210373644697046967493042810911797232448615413264031578430955396671061468083815548947146733652483679138566431084747848676243012018489329109615281108087617422779131629345494425395422727309645057976122885347393189600810965202090151104579377602529543130188938184010247010134929317443562883578609861545691161669857388024973756940558138630581099823372565164920155443216861690537054630176154809626620800633059320775897175589925862195462096455464624399535391743228225433267174308492508396461328929584567927365409119947616225155964704061297047759818551878441419948614013153859322060745185909608884280218943358691959604936409651570327527570641500776261323783648149005245481413195989296398441371781402764122087644989688629798910870164270169014007825748311598976330612951195680427485317886333041169767175063822135213839779138443325644288490872919067009802496281560626258636942322658490628628035057282983101266919109637258378149363774960594515216932644945188292639525772348420077356021656909077097264985642831778694777804964343991762549216500608626285329471055602670413384500507827390640287529864161287496473708235188892189612641279553536442286955430551308700009878557534223100547153412810957024870812654319123261956462149376527526356402127388765103883255007364899937167183280028398832319373301564123277185395654932422977953016534830128490677845037490891749347389015649588574802194996722621185874361039774946338633057887487405540005440439344888192044102134790034598411927024921557026873700970995205391930979319495883265922171508324621942300185974396706491149559411733728199869021311629886680267446443489233020607003821262841723679627307191405008084085703978151998148822390059948911946474438682533745889962375133378280532928272016815977970066488394482446332210928320504045983008943565954267256879714918703447338237767914829203283196838105907715727191903042365315650957464549643425328069510396558733549803850995143463506175361480050195045201350200180281506933241918267855737764414097080945745624854867704904368368717590918057269794010465019484853146726642978667687697789291431128505043098192949736165944259471754765135205245072597538577958372797702972231435199958499522344049394502115428867244188717409524554771867484911475031801773304689909317974472957035192387686405544278134169807249382219749124257510162187439772902147704638010731470653154201300583810458905006764557332998149945854655105526374914354195867992595981412218735238407957416123372264063860431988936249867649693592569592128495906254446474331759999685163660305216426770428154681777589339252115538590526823311608302751194384823861552852465010329467297198112105314125898165100120742688143577590825227466863206188376830450921784582526239594189673003640808624233657620979111641766331328852352062487922978959456450333733139422384778582717195412347860434376165241568717943562570215636666680088531006728947033079540804583324192188488870712275670333173939262509073556164513677064199539111948881240659821685787131385056850623094155206877987539740658484250135205615103489821873770245063583314243624807432542464195984647411575625441010389671576677263196442524931941806472423789334668561083789808830313571333157729435664956078125304917594015895146954965223118559669048559467607968190167266634650186182955669893965019614544401768162810604465068448139561667220729261210164692339016793399632833013163850830967942792934551268435760356901970523138364640961311774904600772840862214747547653221505518116489887879087780918009050706040061220010051271575991225725282523378026809030528461581739558198122397010092017202251606352922464781615533532275453264543087093320924631855976580561717446840450048285353396546862678852330044967795580761661801833668792312510460809773895565488962815089519622093675058841609752282328250433712970186608193748968699961301486924694482420723632912367052542145464162968910442981633373266871675946715392611950649224725627254543274193495995569590243279097174392258098103601486364409101491734183079646345064833303404765711827040276868271418084574998493392039317445402616663674646668754385093967129918067471909885312710726724428584870694307099756567949198418996425748884764622030325637751112534060087936904565779272035205921345924272965206683338510673615276261016026647772485083344719891986802656197236420847504962661607797092906844757798251795569758235084371746103310387911789239441630112634077535773520558040066982523191225570519133631407211349723226549151062961739050617857127509403623146700931176133132018631158730886798239298009805089491510788371194099750375473674305745187265414016446924576792185753680363289139664155342066705623272936001177781498886100830877849571709880858667023104043242526785955562077310543072298032125941107957349146684680220501816192150766649106862033378713826058987655210423668198670177861672671972374156917880001690656659046965316154923604061891820982414006103779407166342002735828911994182647812782659666207030384795881442790246669264032799404016800137293477301530941805070587421153284642203006550763966756168318897005152026656649929417382840327305940740147117478464839241225676523593418554066440983706083636457657081801664285044258224551650808864421212113914352453935225522162483791737330329812349528984098613273709957407786789349311975204237925022851375880436791854547836416773151821457226504640800104202100410766027807729152555503218182387221708112766208665317651926458452495269685376314437998340336947124447247796973890514941120010934140073794061859447165516612674930799374705772930521750426383798367668159183589049652163726492960837147204067428996276720315410211504333742057182854090136325721437592054640471894328548696883599785122262130812989581571391597464534806099601555877223193450760315411663112963843719400333736013305526352571490454327925190794007111504785378036370897340146753465517470747096935814912797188187854376797751675927822300312945518595042883902735494672667647506072643698761394806879080593531793001711000214417701504495496412454361656210150919997862972495905809191825255486358703529320142005857057855419217730505342687533799076038746689684283402648733290888881745453047194740939258407362058242849349024756883352446212456101562729065130618520732925434179252299417447855189995098959999877410951464170076989305620163502192692653166599093238118295411937545448509428621839424186218067457128099385258842631930670182098008050900019819621758458932516877698594110522845465835679362969619219080897536813210484518784516230623911878024604050824909336069998094776253792973597037759066145994638578378211017122446355845171941670344732162722443265914858595797823752976323442911242311368603724514438765801271594060878788638511089680883165505046309006148832545452819908256238805872042843941834687865142541377686054291079721004271658
diff --git a/third_party/gofrontend/libgo/go/compress/testdata/pi.txt b/third_party/gofrontend/libgo/go/compress/testdata/pi.txt
new file mode 100644
index 0000000..ca99bbc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/testdata/pi.txt
@@ -0,0 +1 @@
+3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678566722796619885782794848855834397518744545512965634434803966420557982936804352202770984294232533022576341807039476994159791594530069752148293366555661567873640053666564165473217043903521329543529169414599041608753201868379370234888689479151071637852902345292440773659495630510074210871426134974595615138498713757047101787957310422969066670214498637464595280824369445789772330048764765241339075920434019634039114732023380715095222010682563427471646024335440051521266932493419673977041595683753555166730273900749729736354964533288869844061196496162773449518273695588220757355176651589855190986665393549481068873206859907540792342402300925900701731960362254756478940647548346647760411463233905651343306844953979070903023460461470961696886885014083470405460742958699138296682468185710318879065287036650832431974404771855678934823089431068287027228097362480939962706074726455399253994428081137369433887294063079261595995462624629707062594845569034711972996409089418059534393251236235508134949004364278527138315912568989295196427287573946914272534366941532361004537304881985517065941217352462589548730167600298865925786628561249665523533829428785425340483083307016537228563559152534784459818313411290019992059813522051173365856407826484942764411376393866924803118364453698589175442647399882284621844900877769776312795722672655562596282542765318300134070922334365779160128093179401718598599933849235495640057099558561134980252499066984233017350358044081168552653117099570899427328709258487894436460050410892266917835258707859512983441729535195378855345737426085902908176515578039059464087350612322611200937310804854852635722825768203416050484662775045003126200800799804925485346941469775164932709504934639382432227188515974054702148289711177792376122578873477188196825462981268685817050740272550263329044976277894423621674119186269439650671515779586756482399391760426017633870454990176143641204692182370764887834196896861181558158736062938603810171215855272668300823834046564758804051380801633638874216371406435495561868964112282140753302655100424104896783528588290243670904887118190909494533144218287661810310073547705498159680772009474696134360928614849417850171807793068108546900094458995279424398139213505586422196483491512639012803832001097738680662877923971801461343244572640097374257007359210031541508936793008169980536520276007277496745840028362405346037263416554259027601834840306811381855105979705664007509426087885735796037324514146786703688098806097164258497595138069309449401515422221943291302173912538355915031003330325111749156969174502714943315155885403922164097229101129035521815762823283182342548326111912800928252561902052630163911477247331485739107775874425387611746578671169414776421441111263583553871361011023267987756410246824032264834641766369806637857681349204530224081972785647198396308781543221166912246415911776732253264335686146186545222681268872684459684424161078540167681420808850280054143613146230821025941737562389942075713627516745731891894562835257044133543758575342698699472547031656613991999682628247270641336222178923903176085428943733935618891651250424404008952719837873864805847268954624388234375178852014395600571048119498842390606136957342315590796703461491434478863604103182350736502778590897578272731305048893989009923913503373250855982655867089242612429473670193907727130706869170926462548423240748550366080136046689511840093668609546325002145852930950000907151058236267293264537382104938724996699339424685516483261134146110680267446637334375340764294026682973865220935701626384648528514903629320199199688285171839536691345222444708045923966028171565515656661113598231122506289058549145097157553900243931535190902107119457300243880176615035270862602537881797519478061013715004489917210022201335013106016391541589578037117792775225978742891917915522417189585361680594741234193398420218745649256443462392531953135103311476394911995072858430658361935369329699289837914941939406085724863968836903265564364216644257607914710869984315733749648835292769328220762947282381537409961545598798259891093717126218283025848112389011968221429457667580718653806506487026133892822994972574530332838963818439447707794022843598834100358385423897354243956475556840952248445541392394100016207693636846776413017819659379971557468541946334893748439129742391433659360410035234377706588867781139498616478747140793263858738624732889645643598774667638479466504074111825658378878454858148962961273998413442726086061872455452360643153710112746809778704464094758280348769758948328241239292960582948619196670918958089833201210318430340128495116203534280144127617285830243559830032042024512072872535581195840149180969253395075778400067465526031446167050827682772223534191102634163157147406123850425845988419907611287258059113935689601431668283176323567325417073420817332230462987992804908514094790368878687894930546955703072619009502076433493359106024545086453628935456862958531315337183868265617862273637169757741830239860065914816164049449650117321313895747062088474802365371031150898427992754426853277974311395143574172219759799359685252285745263796289612691572357986620573408375766873884266405990993505000813375432454635967504844235284874701443545419576258473564216198134073468541117668831186544893776979566517279662326714810338643913751865946730024434500544995399742372328712494834706044063471606325830649829795510109541836235030309453097335834462839476304775645015008507578949548931393944899216125525597701436858943585877526379625597081677643800125436502371412783467926101995585224717220177723700417808419423948725406801556035998390548985723546745642390585850216719031395262944554391316631345308939062046784387785054239390524731362012947691874975191011472315289326772533918146607300089027768963114810902209724520759167297007850580717186381054967973100167870850694207092232908070383263453452038027860990556900134137182368370991949516489600755049341267876436746384902063964019766685592335654639138363185745698147196210841080961884605456039038455343729141446513474940784884423772175154334260306698831768331001133108690421939031080143784334151370924353013677631084913516156422698475074303297167469640666531527035325467112667522460551199581831963763707617991919203579582007595605302346267757943936307463056901080114942714100939136913810725813781357894005599500183542511841721360557275221035268037357265279224173736057511278872181908449006178013889710770822931002797665935838758909395688148560263224393726562472776037890814458837855019702843779362407825052704875816470324581290878395232453237896029841669225489649715606981192186584926770403956481278102179913217416305810554598801300484562997651121241536374515005635070127815926714241342103301566165356024733807843028655257222753049998837015348793008062601809623815161366903341111386538510919367393835229345888322550887064507539473952043968079067086806445096986548801682874343786126453815834280753061845485903798217994599681154419742536344399602902510015888272164745006820704193761584547123183460072629339550548239557137256840232268213012476794522644820910235647752723082081063518899152692889108455571126603965034397896278250016110153235160519655904211844949907789992007329476905868577878720982901352956613978884860509786085957017731298155314951681467176959760994210036183559138777817698458758104466283998806006162298486169353373865787735983361613384133853684211978938900185295691967804554482858483701170967212535338758621582310133103877668272115726949518179589754693992642197915523385766231676275475703546994148929041301863861194391962838870543677743224276809132365449485366768000001065262485473055861598999140170769838548318875014293890899506854530765116803337322265175662207526951791442252808165171667766727930354851542040238174608923283917032754257508676551178593950027933895920576682789677644531840404185540104351348389531201326378369283580827193783126549617459970567450718332065034556644034490453627560011250184335607361222765949278393706478426456763388188075656121689605041611390390639601620221536849410926053876887148379895599991120991646464411918568277004574243434021672276445589330127781586869525069499364610175685060167145354315814801054588605645501332037586454858403240298717093480910556211671546848477803944756979804263180991756422809873998766973237695737015808068229045992123661689025962730430679316531149401764737693873514093361833216142802149763399189835484875625298752423873077559555955465196394401821840998412489826236737714672260616336432964063357281070788758164043814850188411431885988276944901193212968271588841338694346828590066640806314077757725705630729400492940302420498416565479736705485580445865720227637840466823379852827105784319753541795011347273625774080213476826045022851579795797647467022840999561601569108903845824502679265942055503958792298185264800706837650418365620945554346135134152570065974881916341359556719649654032187271602648593049039787489589066127250794828276938953521753621850796297785146188432719223223810158744450528665238022532843891375273845892384422535472653098171578447834215822327020690287232330053862163479885094695472004795231120150432932266282727632177908840087861480221475376578105819702226309717495072127248479478169572961423658595782090830733233560348465318730293026659645013718375428897557971449924654038681799213893469244741985097334626793321072686870768062639919361965044099542167627840914669856925715074315740793805323925239477557441591845821562518192155233709607483329234921034514626437449805596103307994145347784574699992128599999399612281615219314888769388022281083001986016549416542616968586788372609587745676182507275992950893180521872924610867639958916145855058397274209809097817293239301067663868240401113040247007350857828724627134946368531815469690466968693925472519413992914652423857762550047485295476814795467007050347999588867695016124972282040303995463278830695976249361510102436555352230690612949388599015734661023712235478911292547696176005047974928060721268039226911027772261025441492215765045081206771735712027180242968106203776578837166909109418074487814049075517820385653909910477594141321543284406250301802757169650820964273484146957263978842560084531214065935809041271135920041975985136254796160632288736181367373244506079244117639975974619383584574915988097667447093006546342423460634237474666080431701260052055928493695941434081468529815053947178900451835755154125223590590687264878635752541911288877371766374860276606349603536794702692322971868327717393236192007774522126247518698334951510198642698878471719396649769070825217423365662725928440620430214113719922785269984698847702323823840055655517889087661360130477098438611687052310553149162517283732728676007248172987637569816335415074608838663640693470437206688651275688266149730788657015685016918647488541679154596507234287730699853713904300266530783987763850323818215535597323530686043010675760838908627049841888595138091030423595782495143988590113185835840667472370297149785084145853085781339156270760356390763947311455495832266945702494139831634332378975955680856836297253867913275055542524491943589128405045226953812179131914513500993846311774017971512283785460116035955402864405902496466930707769055481028850208085800878115773817191741776017330738554758006056014337743299012728677253043182519757916792969965041460706645712588834697979642931622965520168797300035646304579308840327480771811555330909887025505207680463034608658165394876951960044084820659673794731680864156456505300498816164905788311543454850526600698230931577765003780704661264706021457505793270962047825615247145918965223608396645624105195510522357239739512881816405978591427914816542632892004281609136937773722299983327082082969955737727375667615527113922588055201898876201141680054687365580633471603734291703907986396522961312801782679717289822936070288069087768660593252746378405397691848082041021944719713869256084162451123980620113184541244782050110798760717155683154078865439041210873032402010685341947230476666721749869868547076781205124736792479193150856444775379853799732234456122785843296846647513336573692387201464723679427870042503255589926884349592876124007558756946413705625140011797133166207153715436006876477318675587148783989081074295309410605969443158477539700943988394914432353668539209946879645066533985738887866147629443414010498889931600512076781035886116602029611936396821349607501116498327856353161451684576956871090029997698412632665023477167286573785790857466460772283415403114415294188047825438761770790430001566986776795760909966936075594965152736349811896413043311662774712338817406037317439705406703109676765748695358789670031925866259410510533584384656023391796749267844763708474978333655579007384191473198862713525954625181604342253729962863267496824058060296421146386436864224724887283434170441573482481833301640566959668866769563491416328426414974533349999480002669987588815935073578151958899005395120853510357261373640343675347141048360175464883004078464167452167371904831096767113443494819262681110739948250607394950735031690197318521195526356325843390998224986240670310768318446607291248747540316179699411397387765899868554170318847788675929026070043212666179192235209382278788809886335991160819235355570464634911320859189796132791319756490976000139962344455350143464268604644958624769094347048293294140411146540923988344435159133201077394411184074107684981066347241048239358274019449356651610884631256785297769734684303061462418035852933159734583038455410337010916767763742762102137013548544509263071901147318485749233181672072137279355679528443925481560913728128406333039373562420016045664557414588166052166608738748047243391212955877763906969037078828527753894052460758496231574369171131761347838827194168606625721036851321566478001476752310393578606896111259960281839309548709059073861351914591819510297327875571049729011487171897180046961697770017913919613791417162707018958469214343696762927459109940060084983568425201915593703701011049747339493877885989417433031785348707603221982970579751191440510994235883034546353492349826883624043327267415540301619505680654180939409982020609994140216890900708213307230896621197755306659188141191577836272927461561857103721724710095214236964830864102592887457999322374955191221951903424452307535133806856807354464995127203174487195403976107308060269906258076020292731455252078079914184290638844373499681458273372072663917670201183004648190002413083508846584152148991276106513741539435657211390328574918769094413702090517031487773461652879848235338297260136110984514841823808120540996125274580881099486972216128524897425555516076371675054896173016809613803811914361143992106380050832140987604599309324851025168294467260666138151745712559754953580239983146982203613380828499356705575524712902745397762140493182014658008021566536067765508783804304134310591804606800834591136640834887408005741272586704792258319127415739080914383138456424150940849133918096840251163991936853225557338966953749026620923261318855891580832455571948453875628786128859004106006073746501402627824027346962528217174941582331749239683530136178653673760642166778137739951006589528877427662636841830680190804609849809469763667335662282915132352788806157768278159588669180238940333076441912403412022316368577860357276941541778826435238131905028087018575047046312933353757285386605888904583111450773942935201994321971171642235005644042979892081594307167019857469273848653833436145794634175922573898588001698014757420542995801242958105456510831046297282937584161162532562516572498078492099897990620035936509934721582965174135798491047111660791587436986541222348341887722929446335178653856731962559852026072947674072616767145573649812105677716893484917660771705277187601199908144113058645577910525684304811440261938402322470939249802933550731845890355397133088446174107959162511714864874468611247605428673436709046678468670274091881014249711149657817724279347070216688295610877794405048437528443375108828264771978540006509704033021862556147332117771174413350281608840351781452541964320309576018694649088681545285621346988355444560249556668436602922195124830910605377201980218310103270417838665447181260397190688462370857518080035327047185659499476124248110999288679158969049563947624608424065930948621507690314987020673533848349550836366017848771060809804269247132410009464014373603265645184566792456669551001502298330798496079949882497061723674493612262229617908143114146609412341593593095854079139087208322733549572080757165171876599449856937956238755516175754380917805280294642004472153962807463602113294255916002570735628126387331060058910652457080244749375431841494014821199962764531068006631183823761639663180931444671298615527598201451410275600689297502463040173514891945763607893528555053173314164570504996443890936308438744847839616840518452732884032345202470568516465716477139323775517294795126132398229602394548579754586517458787713318138752959809412174227300352296508089177705068259248822322154938048371454781647213976820963320508305647920482085920475499857320388876391601995240918938945576768749730856955958010659526503036266159750662225084067428898265907510637563569968211510949669744580547288693631020367823250182323708459790111548472087618212477813266330412076216587312970811230758159821248639807212407868878114501655825136178903070860870198975889807456643955157415363193191981070575336633738038272152798849350397480015890519420879711308051233933221903466249917169150948541401871060354603794643379005890957721180804465743962806186717861017156740967662080295766577051291209907944304632892947306159510430902221439371849560634056189342513057268291465783293340524635028929175470872564842600349629611654138230077313327298305001602567240141851520418907011542885799208121984493156999059182011819733500126187728036812481995877070207532406361259313438595542547781961142935163561223496661522614735399674051584998603552953329245752388810136202347624669055816438967863097627365504724348643071218494373485300606387644566272186661701238127715621379746149861328744117714552444708997144522885662942440230184791205478498574521634696448973892062401943518310088283480249249085403077863875165911302873958787098100772718271874529013972836614842142871705531796543076504534324600536361472618180969976933486264077435199928686323835088756683595097265574815431940195576850437248001020413749831872259677387154958399718444907279141965845930083942637020875635398216962055324803212267498911402678528599673405242031091797899905718821949391320753431707980023736590985375520238911643467185582906853711897952626234492483392496342449714656846591248918556629589329909035239233333647435203707701010843880032907598342170185542283861617210417603011645918780539367447472059985023582891833692922337323999480437108419659473162654825748099482509991833006976569367159689364493348864744213500840700660883597235039532340179582557036016936990988671132109798897070517280755855191269930673099250704070245568507786790694766126298082251633136399521170984528092630375922426742575599892892783704744452189363203489415521044597261883800300677617931381399162058062701651024458869247649246891924612125310275731390840470007143561362316992371694848132554200914530410371354532966206392105479824392125172540132314902740585892063217589494345489068463993137570910346332714153162232805522972979538018801628590735729554162788676498274186164218789885741071649069191851162815285486794173638906653885764229158342500673612453849160674137340173572779956341043326883569507814931378007362354180070619180267328551191942676091221035987469241172837493126163395001239599240508454375698507957046222664619000103500490183034153545842833764378111988556318777792537201166718539541835984438305203762819440761594106820716970302285152250573126093046898423433152732131361216582808075212631547730604423774753505952287174402666389148817173086436111389069420279088143119448799417154042103412190847094080254023932942945493878640230512927119097513536000921971105412096683111516328705423028470073120658032626417116165957613272351566662536672718998534199895236884830999302757419916463841427077988708874229277053891227172486322028898425125287217826030500994510824783572905691988555467886079462805371227042466543192145281760741482403827835829719301017888345674167811398954750448339314689630763396657226727043393216745421824557062524797219978668542798977992339579057581890622525473582205236424850783407110144980478726691990186438822932305382318559732869780922253529591017341407334884761005564018242392192695062083183814546983923664613639891012102177095976704908305081854704194664371312299692358895384930136356576186106062228705599423371631021278457446463989738188566746260879482018647487672727222062676465338099801966883680994159075776852639865146253336312450536402610569605513183813174261184420189088853196356986962795036738424313011331753305329802016688817481342988681585577810343231753064784983210629718425184385534427620128234570716988530518326179641178579608888150329602290705614476220915094739035946646916235396809201394578175891088931992112260073928149169481615273842736264298098234063200244024495894456129167049508235812487391799648641133480324757775219708932772262349486015046652681439877051615317026696929704928316285504212898146706195331970269507214378230476875280287354126166391708245925170010714180854800636923259462019002278087409859771921805158532147392653251559035410209284665925299914353791825314545290598415817637058927906909896911164381187809435371521332261443625314490127454772695739393481546916311624928873574718824071503995009446731954316193855485207665738825139639163576723151005556037263394867208207808653734942440115799667507360711159351331959197120948964717553024531364770942094635696982226673775209945168450643623824211853534887989395673187806606107885440005508276570305587448541805778891719207881423351138662929667179643468760077047999537883387870348718021842437342112273940255717690819603092018240188427057046092622564178375265263358324240661253311529423457965569502506810018310900411245379015332966156970522379210325706937051090830789479999004999395322153622748476603613677697978567386584670936679588583788795625946464891376652199588286933801836011932368578558558195556042156250883650203322024513762158204618106705195330653060606501054887167245377942831338871631395596905832083416898476065607118347136218123246227258841990286142087284956879639325464285343075301105285713829643709990356948885285190402956047346131138263878897551788560424998748316382804046848618938189590542039889872650697620201995548412650005394428203930127481638158530396439925470201672759328574366661644110962566337305409219519675148328734808957477775278344221091073111351828046036347198185655572957144747682552857863349342858423118749440003229690697758315903858039353521358860079600342097547392296733310649395601812237812854584317605561733861126734780745850676063048229409653041118306671081893031108871728167519579675347188537229309616143204006381322465841111157758358581135018569047815368938137718472814751998350504781297718599084707621974605887423256995828892535041937958260616211842368768511418316068315867994601652057740529423053601780313357263267054790338401257305912339601880137825421927094767337191987287385248057421248921183470876629667207272325650565129333126059505777727542471241648312832982072361750574673870128209575544305968395555686861188397135522084452852640081252027665557677495969626612604565245684086139238265768583384698499778726706555191854468698469478495734622606294219624557085371272776523098955450193037732166649182578154677292005212667143463209637891852323215018976126034373684067194193037746880999296877582441047878123266253181845960453853543839114496775312864260925211537673258866722604042523491087026958099647595805794663973419064010036361904042033113579336542426303561457009011244800890020801478056603710154122328891465722393145076071670643556827437743965789067972687438473076346451677562103098604092717090951280863090297385044527182892749689212106670081648583395537735919136950153162018908887484210798706899114804669270650940762046502772528650728905328548561433160812693005693785417861096969202538865034577183176686885923681488475276498468821949739729707737187188400414323127636504814531122850990020742409255859252926103021067368154347015252348786351643976235860419194129697690405264832347009911154242601273438022089331096686367898694977994001260164227609260823493041180643829138347354679725399262338791582998486459271734059225620749105308531537182911681637219395188700957788181586850464507699343940987433514431626330317247747486897918209239480833143970840673084079589358108966564775859905563769525232653614424780230826811831037735887089240613031336477371011628214614661679404090518615260360092521947218890918107335871964142144478654899528582343947050079830388538860831035719306002771194558021911942899922722353458707566246926177663178855144350218287026685610665003531050216318206017609217984684936863161293727951873078972637353717150256378733579771808184878458866504335824377004147710414934927438457587107159731559439426412570270965125108115548247939403597681188117282472158250109496096625393395380922195591918188552678062149923172763163218339896938075616855911752998450132067129392404144593862398809381240452191484831646210147389182510109096773869066404158973610476436500068077105656718486281496371118832192445663945814491486165500495676982690308911185687986929470513524816091743243015383684707292898982846022237301452655679898627767968091469798378268764311598832109043715611299766521539635464420869197567370005738764978437686287681792497469438427465256316323005551304174227341646455127812784577772457520386543754282825671412885834544435132562054464241011037955464190581168623059644769587054072141985212106734332410756767575818456990693046047522770167005684543969234041711089888993416350585157887353430815520811772071880379104046983069578685473937656433631979786803671873079693924236321448450354776315670255390065423117920153464977929066241508328858395290542637687668968805033317227800185885069736232403894700471897619347344308437443759925034178807972235859134245813144049847701732361694719765715353197754997162785663119046912609182591249890367654176979903623755286526375733763526969344354400473067198868901968147428767790866979688522501636949856730217523132529265375896415171479559538784278499866456302878831962099830494519874396369070682762657485810439112232618794059941554063270131989895703761105323606298674803779153767511583043208498720920280929752649812569163425000522908872646925284666104665392171482080130502298052637836426959733707053922789153510568883938113249757071331029504430346715989448786847116438328050692507766274500122003526203709466023414648998390252588830148678162196775194583167718762757200505439794412459900771152051546199305098386982542846407255540927403132571632640792934183342147090412542533523248021932277075355546795871638358750181593387174236061551171013123525633485820365146141870049205704372018261733194715700867578539336078622739558185797587258744102542077105475361294047460100094095444959662881486915903899071865980563617137692227290764197755177720104276496949611056220592502420217704269622154958726453989227697660310524980855759471631075870133208861463266412591148633881220284440694169488261529577625325019870359870674380469821942056381255833436421949232275937221289056420943082352544084110864545369404969271494003319782861318186188811118408257865928757426384450059944229568586460481033015388911499486935436030221810943466764000022362550573631294626296096198760564259963946138692330837196265954739234624134597795748524647837980795693198650815977675350553918991151335252298736112779182748542008689539658359421963331502869561192012298889887006079992795411188269023078913107603617634779489432032102773359416908650071932804017163840644987871753756781185321328408216571107549528294974936214608215583205687232185574065161096274874375098092230211609982633033915469494644491004515280925089745074896760324090768983652940657920198315265410658136823791984090645712468948470209357761193139980246813405200394781949866202624008902150166163813538381515037735022966074627952910384068685569070157516624192987244482719429331004854824454580718897633003232525821581280327467962002814762431828622171054352898348208273451680186131719593324711074662228508710666117703465352839577625997744672185715816126411143271794347885990892808486694914139097716736900277758502686646540565950394867841110790116104008572744562938425494167594605487117235946429105850909950214958793112196135908315882620682332156153086833730838173279328196983875087083483880463884784418840031847126974543709373298362402875197920802321878744882872843727378017827008058782410749357514889978911739746129320351081432703251409030487462262942344327571260086642508333187688650756429271605525289544921537651751492196367181049435317858383453865255656640657251363575064353236508936790431702597878177190314867963840828810209461490079715137717099061954969640070867667102330048672631475510537231757114322317411411680622864206388906210192355223546711662137499693269321737043105987225039456574924616978260970253359475020913836673772894438696400028110344026084712899000746807764844088711341352503367877316797709372778682166117865344231732264637847697875144332095340001650692130546476890985050203015044880834261845208730530973189492916425322933612431514306578264070283898409841602950309241897120971601649265613413433422298827909921786042679812457285345801338260995877178113102167340256562744007296834066198480676615805021691833723680399027931606420436812079900316264449146190219458229690992122788553948783538305646864881655562294315673128274390826450611628942803501661336697824051770155219626522725455850738640585299830379180350432876703809252167907571204061237596327685674845079151147313440001832570344920909712435809447900462494313455028900680648704293534037436032625820535790118395649089354345101342969617545249573960621490288728932792520696535386396443225388327522499605986974759882329916263545973324445163755334377492928990581175786355555626937426910947117002165411718219750519831787137106051063795558588905568852887989084750915764639074693619881507814685262133252473837651192990156109189777922008705793396463827490680698769168197492365624226087154176100430608904377976678519661891404144925270480881971498801542057787006521594009289777601330756847966992955433656139847738060394368895887646054983871478968482805384701730871117761159663505039979343869339119789887109156541709133082607647406305711411098839388095481437828474528838368079418884342666222070438722887413947801017721392281911992365405516395893474263953824829609036900288359327745855060801317988407162446563997948275783650195514221551339281978226984278638391679715091262410548725700924070045488485692950448110738087996547481568913935380943474556972128919827177020766613602489581468119133614121258783895577357194986317210844398901423948496659251731388171602663261931065366535041473070804414939169363262373767777095850313255990095762731957308648042467701212327020533742667053142448208168130306397378736642483672539837487690980602182785786216512738563513290148903509883270617258932575363993979055729175160097615459044771692265806315111028038436017374742152476085152099016158582312571590733421736576267142390478279587281505095633092802668458937649649770232973641319060982740633531089792464242134583740901169391964250459128813403498810635400887596820054408364386516617880557608956896727531538081942077332597917278437625661184319891025007491829086475149794003160703845549465385946027452447466812314687943441610993338908992638411847425257044572517459325738989565185716575961481266020310797628254165590506042479114016957900338356574869252800743025623419498286467914476322774005529460903940177536335655471931000175430047504719144899841040015867946179241610016454716551337074073950260442769538553834397550548871099785205401175169747581344926079433689543783221172450687344231989878844128542064742809735625807066983106979935260693392135685881391214807354728463227784908087002467776303605551232386656295178853719673034634701222939581606792509153217489030840886516061119011498443412350124646928028805996134283511884715449771278473361766285062169778717743824362565711779450064477718370221999106695021656757644044997940765037999954845002710665987813603802314126836905783190460792765297277694043613023051787080546511542469395265127101052927070306673024447125973939950514628404767431363739978259184541176413327906460636584152927019030276017339474866960348694976541752429306040727005059039503148522921392575594845078867977925253931765156416197168443524369794447355964260633391055126826061595726217036698506473281266724521989060549880280782881429796336696744124805982192146339565745722102298677599746738126069367069134081559412016115960190237753525556300606247983261249881288192937343476862689219239777833910733106588256813777172328315329082525092733047850724977139448333892552081175608452966590553940965568541706001179857293813998258319293679100391844099286575605993598910002969864460974714718470101531283762631146774209145574041815908800064943237855839308530828305476076799524357391631221886057549673832243195650655460852881201902363644712703748634421727257879503428486312944916318475347531435041392096108796057730987201352484075057637199253650470908582513936863463863368042891767107602111159828875539940120076013947033661793715396306139863655492213741597905119083588290097656647300733879314678913181465109316761575821351424860442292445304113160652700974330088499034675405518640677342603583409608605533747362760935658853109760994238347382222087292464497684560579562516765574088410321731345627735856052358236389532038534024842273371639123973215995440828421666636023296545694703577184873442034227706653837387506169212768015766181095420097708363604361110592409117889540338021426523948929686439808926114635414571535194342850721353453018315875628275733898268898523557799295727645229391567477566676051087887648453493636068278050564622813598885879259940946446041705204470046315137975431737187756039815962647501410906658866162180038266989961965580587208639721176995219466789857011798332440601811575658074284182910615193917630059194314434605154047710570054339000182453117733718955857603607182860506356479979004139761808955363669603162193113250223851791672055180659263518036251214575926238369348222665895576994660491938112486609099798128571823494006615552196112207203092277646200999315244273589488710576623894693889446495093960330454340842102462401048723328750081749179875543879387381439894238011762700837196053094383940063756116458560943129517597713935396074322792489221267045808183313764165818269562105872892447740035947009268662659651422050630078592002488291860839743732353849083964326147000532423540647042089499210250404726781059083644007466380020870126664209457181702946752278540074508552377720890581683918446592829417018288233014971554235235911774818628592967605048203864343108779562892925405638946621948268711042828163893975711757786915430165058602965217459581988878680408110328432739867198621306205559855266036405046282152306154594474489908839081999738747452969810776201487134000122535522246695409315213115337915798026979555710508507473874750758068765376445782524432638046143042889235934852961058269382103498000405248407084403561167817170512813378805705643450616119330424440798260377951198548694559152051960093041271007277849301555038895360338261929343797081874320949914159593396368110627557295278004254863060054523839151068998913578820019411786535682149118528207852130125518518493711503422159542244511900207393539627400208110465530207932867254740543652717595893500716336076321614725815407642053020045340183572338292661915308354095120226329165054426123619197051613839357326693760156914429944943744856809775696303129588719161129294681884936338647392747601226964158848900965717086160598147204467428664208765334799858222090619802173211614230419477754990738738567941189824660913091691772274207233367635032678340586301930193242996397204445179288122854478211953530898910125342975524727635730226281382091807439748671453590778633530160821559911314144205091447293535022230817193663509346865858656314855575862447818620108711889760652969899269328178705576435143382060141077329261063431525337182243385263520217735440715281898137698755157574546939727150488469793619500477720970561793913828989845327426227288647108883270173723258818244658436249580592560338105215606206155713299156084892064340303395262263451454283678698288074251422567451806184149564686111635404971897682154227722479474033571527436819409892050113653400123846714296551867344153741615042563256713430247655125219218035780169240326699541746087592409207004669340396510178134857835694440760470232540755557764728450751826890418293966113310160131119077398632462778219023650660374041606724962490137433217246454097412995570529142438208076098364823465973886691349919784013108015581343979194852830436739012482082444814128095443773898320059864909159505322857914576884962578665885999179867520554558099004556461178755249370124553217170194282884617402736649978475508294228020232901221630102309772151569446427909802190826689868834263071609207914085197695235553488657743425277531197247430873043619511396119080030255878387644206085044730631299277888942729189727169890575925244679660189707482960949190648764693702750773866432391919042254290235318923377293166736086996228032557185308919284403805071030064776847863243191000223929785255372375566213644740096760539439838235764606992465260089090624105904215453927904411529580345334500256244101006359530039598864466169595626351878060688513723462707997327233134693971456285542615467650632465676620279245208581347717608521691340946520307673391841147504140168924121319826881568664561485380287539331160232292555618941042995335640095786495340935115266454024418775949316930560448686420862757201172319526405023099774567647838488973464317215980626787671838005247696884084989185086149003432403476742686245952395890358582135006450998178244636087317754378859677672919526111213859194725451400301180503437875277664402762618941017576872680428176623860680477885242887430259145247073950546525135339459598789619778911041890292943818567205070964606263541732944649576612651953495701860015412623962286413897796733329070567376962156498184506842263690367849555970026079867996261019039331263768556968767029295371162528005543100786408728939225714512481135778627664902425161990277471090335933309304948380597856628844787441469841499067123764789582263294904679812089984857163571087831191848630254501620929805829208334813638405421720056121989353669371336733392464416125223196943471206417375491216357008573694397305979709719726666642267431117762176403068681310351899112271339724036887000996862922546465006385288620393800504778276912835603372548255793912985251506829969107754257647488325341412132800626717094009098223529657957997803018282428490221470748111124018607613415150387569830918652780658896682362523937845272634530420418802508442363190383318384550522367992357752929106925043261446950109861088899914658551881873582528164302520939285258077969737620845637482114433988162710031703151334402309526351929588680690821355853680161000213740851154484912685841268695899174149133820578492800698255195740201818105641297250836070356851055331787840829000041552511865779453963317538532092149720526607831260281961164858098684587525129997404092797683176639914655386108937587952214971731728131517932904431121815871023518740757222100123768721944747209349312324107065080618562372526732540733324875754482967573450019321902199119960797989373383673242576103938985349278777473980508080015544764061053522202325409443567718794565430406735896491017610775948364540823486130254718476485189575836674399791508512858020607820554462991723202028222914886959399729974297471155371858924238493855858595407438104882624648788053304271463011941589896328792678327322456103852197011130466587100500083285177311776489735230926661234588873102883515626446023671996644554727608310118788389151149340939344750073025855814756190881398752357812331342279866503522725367171230756861045004548970360079569827626392344107146584895780241408158405229536937499710665594894459246286619963556350652623405339439142111271810691052290024657423604130093691889255865784668461215679554256605416005071276641766056874274200329577160643448606201239821698271723197826816628249938714995449137302051843669076723577400053932662622760323659751718925901801104290384274185507894887438832703063283279963007200698012244365116394086922220745320244624121155804354542064215121585056896157356414313068883443185280853975927734433655384188340303517822946253702015782157373265523185763554098954033236382319219892171177449469403678296185920803403867575834111518824177439145077366384071880489358256868542011645031357633355509440319236720348651010561049872726472131986543435450409131859513145181276437310438972507004981987052176272494065214619959232142314439776546708351714749367986186552791715824080651063799500184295938799158350171580759883784962257398512129810326379376218322456594236685376799113140108043139732335449090824910499143325843298821033984698141715756010829706583065211347076803680695322971990599904451209087275776225351040902392888779424630483280319132710495478599180196967835321464441189260631526618167443193550817081875477050802654025294109218264858213857526688155584113198560022135158887210365696087515063187533002942118682221893775546027227291290504292259787710667873840000616772154638441292371193521828499824350920891801685572798156421858191197490985730570332667646460728757430565372602768982373259745084479649545648030771598153955827779139373601717422996027353102768719449444917939785144631597314435351850491413941557329382048542123508173912549749819308714396615132942045919380106231421774199184060180347949887691051557905554806953878540066453375981862846419905220452803306263695626490910827627115903856995051246529996062855443838330327638599800792922846659503551211245284087516229060262011857775313747949362055496401073001348853150735487353905602908933526400713274732621960311773433943673385759124508149335736911664541281788171454023054750667136518258284898099512139193995633241336556777098003081910272040997148687418134667006094051021462690280449159646545330107754695413088714165312544813061192407821188690056027781824235022696189344352547633573536485619363254417756613981703930632872166905722259745209192917262199844409646158269456380239502837121686446561785235565164127712826918688615572716201474934052276946595712198314943381622114006936307430444173284786101777743837977037231795255434107223445512555589998646183876764903972461167959018100035098928641204195163551108763204267612979826529425882951141275841262732790798807559751851576841264742209479721843309352972665210015662514552994745127631550917636730259462132930190402837954246323258550301096706922720227074863419005438302650681214142135057154175057508639907673946335146209082888934938376439399256900604067311422093312195936202982972351163259386772241477911629572780752395056251581603133359382311500518626890530658368129988108663263271980611271548858798093487912913707498230575929091862939195014721197586067270092547718025750337730799397134539532646195269996596385654917590458333585799102012713204583903200853878881633637685182083727885131175227769609787962142372162545214591281831798216044111311671406914827170981015457781939202311563871950805024679725792497605772625913328559726371211201905720771409148645074094926718035815157571514050397610963846755569298970383547314100223802583468767350129775413279532060971154506484212185936490997917766874774481882870632315515865032898164228288232746866106592732197907162384642153489852476216789050260998045266483929542357287343977680495774091449538391575565485459058976495198513801007958010783759945775299196700547602252552034453988712538780171960718164078124847847257912407824544361682345239570689514272269750431873633263011103053423335821609333191218806608268341428910415173247216053355849993224548730778822905252324234861531520976938461042582849714963475341837562003014915703279685301868631572488401526639835689563634657435321783493199825542117308467745297085839507616458229630324424328237737450517028560698067889521768198156710781633405266759539424926280756968326107495323390536223090807081455919837355377748742029039018142937311529334644468151212945097596534306284215319445727118614900017650558177095302468875263250119705209476159416768727784472000192789137251841622857783792284439084301181121496366424659033634194540657183544771912446621259392656620306888520055599121235363718226922531781458792593750441448933981608657900876165024635197045828895481793756681046474614105142498870252139936870509372305447734112641354892806841059107716677821238332810262185587751312721179344448201440425745083063944738363793906283008973306241380614589414227694747931665717623182472168350678076487573420491557628217583972975134478990696589532548940335615613167403276472469212505759116251529654568544633498114317670257295661844775487469378464233737238981920662048511894378868224807279352022501796545343757274163910791972952950812942922205347717304184477915673991738418311710362524395716152714669005814700002633010452643547865903290733205468338872078735444762647925297690170912007874183736735087713376977683496344252419949951388315074877537433849458259765560996555954318040920178497184685497370696212088524377013853757681416632722412634423982152941645378000492507262765150789085071265997036708726692764308377229685985169122305037462744310852934305273078865283977335246017463527703205938179125396915621063637625882937571373840754406468964783100704580613446731271591194608435935825987782835266531151065041623295329047772174083559349723758552138048305090009646676088301540612824308740645594431853413755220166305812111033453120745086824339432159043594430312431227471385842030390106070940315235556172767994160020393975099897629335325855575624808996691829864222677502360193257974726742578211119734709402357457222271212526852384295874273501563660093188045493338989741571490544182559738080871565281430102670460284316819230392535297795765862414392701549740879273131051636119137577008929564823323648298263024607975875767745377160102490804624301856524161756655600160859121534556267602192689982855377872583145144082654583484409478463178777374794653580169960779405568701192328608041130904629350871827125934668712766694873899824598527786499569165464029458935064964335809824765965165142090986755203808309203230487342703468288751604071546653834619611223013759451579252696743642531927390036038608236450762698827497618723575476762889950752114804852527950845033958570838130476937881321123674281319487950228066320170022460331989671970649163741175854851878484012054844672588851401562725019821719066960812627785485964818369621410721714214986361918774754509650308957099470934337856981674465828267911940611956037845397855839240761276344105766751024307559814552786167815949657062559755074306521085301597908073343736079432866757890533483669555486803913433720156498834220893399971641479746938696905480089193067138057171505857307148815649920714086758259602876056459782423770242469805328056632787041926768467116266879463486950464507420219373945259262668613552940624781361206202636498199999498405143868285258956342264328707663299304891723400725471764188685351372332667877921738347541480022803392997357936152412755829569276837231234798989446274330454566790062032420516396282588443085438307201495672106460533238537203143242112607424485845094580494081820927639140008540422023556260218564348994145439950410980591817948882628052066441086319001688568155169229486203010738897181007709290590480749092427141018933542818429995988169660993836961644381528877214085268088757488293258735809905670755817017949161906114001908553744882726200936685604475596557476485674008177381703307380305476973609786543859382187220583902344443508867499866506040645874346005331827436296177862518081893144363251205107094690813586440519229512932450078833398788429339342435126343365204385812912834345297308652909783300671261798130316794385535726296998740359570458452230856390098913179475948752126397078375944861139451960286751210561638976008880092746115860800207803341591451797073036835196977766076373785333012024120112046988609209339085365773222392412449051532780950955866459477634482269986074813297302630975028812103517723124465095349653693090018637764094094349837313251321862080214809922685502948454661814715557444709669530177690434272031892770604717784527939160472281534379803539679861424370956683221491465438014593829277393396032754048009552231816667380357183932757077142046723838624617803976292377131209580789363841447929802588065522129262093623930637313496640186619510811583471173312025805866727639992763579078063818813069156366274125431259589936119647626101405563503399523140323113819656236327198961837254845333702062563464223952766943568376761368711962921818754576081617053031590728828700712313666308722754918661395773730546065997437810987649802414011242142773668082751390959313404155826266789510846776118665957660165998178089414985754976284387856100263796543178313634025135814161151902096499133548733131115022700681930135929595971640197196053625033558479980963488718039111612813595968565478868325856437896173159762002419621552896297904819822199462269487137462444729093456470028537694958859591606789282491054412515996300781368367490209374915732896270028656829344431342347351239298259166739503425995868970697267332582735903121288746660451461487850346142827765991608090398652575717263081833494441820193533385071292345774375579344062178711330063106003324053991693682603746176638565758877580201229366353270267100681261825172914608202541892885935244491070138206211553827793565296914576502048643282865557934707209634807372692141186895467322767751335690190153723669036865389161291688887876407525493494249733427181178892759931596719354758988097924525262363659036320070854440784544797348291802082044926670634420437555325050527522833778887040804033531923407685630109347772125639088640413101073817853338316038135280828119040832564401842053746792992622037698718018061122624490909242641985820861751177113789051609140381575003366424156095216328197122335023167422600567941281406217219641842705784328959802882335059828208196666249035857789940333152274817776952843681630088531769694783690580671064828083598046698841098135158654906933319522394363287923990534810987830274500172065433699066117784554364687723631844464768069142828004551074686645392805399409108754939166095731619715033166968309929466349142798780842257220697148875580637480308862995118473187124777291910070227588893486939456289515802965372150409603107761289831263589964893410247036036645058687287589051406841238124247386385427908282733827973326885504935874303160274749063129572349742611221517417153133618622410913869500688835898962349276317316478340077460886655598733382113829928776911495492184192087771606068472874673681886167507221017261103830671787856694812948785048943063086169948798703160515884108282351274153538513365895332948629494495061868514779105804696039069372662670386512905201137810858616188886947957607413585534585151768051973334433495230120395770739623771316030242887200537320998253008977618973129817881944671731160647231476248457551928732782825127182446807824215216469567819294098238926284943760248852279003620219386696482215628093605373178040863727268426696421929946819214908701707533361094791381804063287387593848269535583077395761447997270003472880182785281389503217986345216111066608839314053226944905455527867894417579202440021450780192099804461382547805858048442416404775031536054906591430078158372430123137511562284015838644270890718284816757527123846782459534334449622010096071051370608461801187543120725491334994247617115633321408934609156561550600317384218701570226103101916603887064661438897736318780940711527528174689576401581047016965247557740891644568677717158500583269943401677202156767724068128366565264122982439465133197359199709403275938502669557470231813203243716420586141033606524536939160050644953060161267822648942437397166717661231048975031885732165554988342121802846912529086101485527815277625623750456375769497734336846015607727035509629049392487088406281067943622418704747008368842671022558302403599841645951122485272633632645114017395248086194635840783753556885622317115520947223065437092606797351000565549381224575483728545711797393615756167641692895805257297522338558611388322171107362265816218842443178857488798109026653793426664216990914056536432249301334867988154886628665052346997235574738424830590423677143278792316422403877764330192600192284778313837632536121025336935812624086866699738275977365682227907215832478888642369346396164363308730139814211430306008730666164803678984091335926293402304324974926887831643602681011309570716141912830686577323532639653677390317661361315965553584999398600565155921936759977717933019744688148371103206503693192894521402650915465184309936553493337183425298433679915939417466223900389527673813330617747629574943868716978453767219493506590875711917720875477107189937960894774512654757501871194870738736785890200617373321075693302216320628432065671192096950585761173961632326217708945426214609858410237813215817727602222738133495410481003073275107799948991977963883530734443457532975914263768405442264784216063122769646967156473999043715903323906560726644116438605404838847161912109008701019130726071044114143241976796828547885524779476481802959736049439700479596040292746299203572099761950140348315380947714601056333446998820822120587281510729182971211917876424880354672316916541852256729234429187128163232596965413548589577133208339911288775917226115273379010341362085614577992398778325083550730199818459025958355989260553299673770491722454935329683300002230181517226575787524058832249085821280089747909326100762578770428656006996176212176845478996440705066241710213327486796237430229155358200780141165348065647488230615003392068983794766255036549822805329662862117930628430170492402301985719978948836897183043805182174419147660429752437251683435411217038631379411422095295885798060152938752753799030938871683572095760715221900279379292786303637268765822681241993384808166021603722154710143007377537792699069587121289288019052031601285861825494413353820784883465311632650407642428390870121015194231961652268422003711230464300673442064747718021353070124098860353399152667923871101706221865883573781210935179775604425634694999787251125440854522274810914874307259869602040275941178942581281882159952359658979181144077653354321757595255536158128001163846720319346507296807990793963714961774312119402021297573125165253768017359101557338153772001952444543620071848475663415407442328621060997613243487548847434539665981338717466093020535070271952983943271425371155766600025784423031073429551533945060486222764966687624079324353192992639253731076892135352572321080889819339168668278948281170472624501948409700975760920983724090074717973340788141825195842598096241747610138252643955135259311885045636264188300338539652435997416931322894719878308427600401368074703904097238473945834896186539790594118599310356168436869219485382055780395773881360679549900085123259442529724486666766834641402189915944565309423440650667851948417766779470472041958822043295380326310537494883122180391279678446100139726753892195119117836587662528083690053249004597410947068772912328214304635337283519953648274325833119144459017809607782883583730111857543659958982724531925310588115026307542571493943024453931870179923608166611305426253995833897942971602070338767815033010280120095997252222280801423571094760351925544434929986767817891045559063015953809761875920358937341978962358931125983902598310267193304189215109689156225069659119828323455503059081730735195503721665870288053992138576037035377105178021280129566841984140362872725623214428754302210909472721073474134975514190737043318276626177275996888826027225247133683353452816692779591328861381766349857728936900965749562287103024362590772412219094300871755692625758065709912016659622436080242870024547362036394841255954881727272473653467783647201918303998717627037515724649922289467932322693619177641614618795613956699567783068290316589699430767333508234990790624100202506134057344300695745474682175690441651540636584680463692621274211075399042188716127617787014258864825775223889184599523376292377915585744549477361295525952226578636462118377598473700347971408206994145580719080213590732269233100831759510659019121294795408603640757358750205890208704579670007055262505811420663907459215273309406823649441590891009220296680523325266198911311842016291631076894084723564366808182168657219688268358402785500782804043453710183651096951782335743030504852653738073531074185917705610397395062640355442275156101107261779370634723804990666922161971194259120445084641746383589938239946517395509000859479990136026674261494290066467115067175422177038774507673563742154782905911012619157555870238957001405117822646989944917908301795475876760168094100135837613578591356924455647764464178667115391951357696104864922490083446715486383054477914330097680486878348184672733758436892724310447406807685278625585165092088263813233623148733336714764520450876627614950389949504809560460989604329123358348859990294526400284994280878624039811814884767301216754161106629995553668193123287425702063738352020086863691311733469731741219153633246745325630871347302792174956227014687325867891734558379964351358800959350877556356248810493852999007675135513527792412429277488565888566513247302514710210575352516511814850902750476845518252096331899068527614435138213662152368890578786699432288816028377482035506016029894009119713850179871683633744139275973644017007014763706655703504338121113576415018451821413619823495159601064752712575935185304332875537783057509567425442684712219618709178560783936144511383335649103256405733898667178123972237519316430617013859539474367843392670986712452211189690840236327411496601243483098929941738030588417166613073040067588380432111555379440605497721705942821514886165672771240903387727745629097110134885184374118695655449745736845218066982911045058004299887953899027804383596282409421860556287788428802127553884803728640019441614257499904272009595204654170598104989967504511936471172772220436102614079750809686975176600237187748348016120310234680567112644766123747627852190241202569943534716226660893675219833111813511146503854895025120655772636145473604426859498074396932331297127377157347099713952291182653485155587137336629120242714302503763269501350911612952993785864681307226486008270881333538193703682598867893321238327053297625857382790097826460545598555131836688844628265133798491667839409761353766251798258249663458771950124384040359140849209733754642474488176184070023569580177410177696925077814893386672557898564589851056891960924398841569280696983352240225634570497312245269354193837004843183357196516626721575524193401933099018319309196582920969656247667683659647019595754739345514337413708761517323677204227385674279170698204549953095918872434939524094441678998846319845504852393662972079777452814399418256789457795712552426826089940863317371538896262889629402112108884427376568624527612130371017300785135715404533041507959447776143597437803742436646973247138410492124314138903579092416036406314038149831481905251720937103964026808994832572297954564042701757722904173234796073618787889913318305843069394825961318713816423467218730845133877219086975104942843769325024981656673816260615941768252509993741672883951744066932549653403101452225316189009235376486378482881344209870048096227171226407489571939002918573307460104360729190945767994614929290427981687729426487729952858434647775386906950148984133924540394144680263625402118614317031251117577642829914644533408920976961699098372652361768745605894704968170136974909523072082682887890730190018253425805343421705928713931737993142410852647390948284596418093614138475831136130576108462366837237695913492615824516221552134879244145041756848064120636520170386330129532777699023118648020067556905682295016354931992305914246396217025329747573114094220180199368035026495636955866425906762685687372110339156793839895765565193177883000241613539562437777840801748819373095020699900890899328088397430367736595524891300156633294077907139615464534088791510300651321934486673248275907946807879819425019582622320395131252014109960531260696555404248670549986786923021746989009547850725672978794769888831093487464426400718183160331655511534276155622405474473378049246214952133258527698847336269182649174338987824789278468918828054669982303689939783413747587025805716349413568433929396068192061773331791738208562436433635359863494496890781064019674074436583667071586924521182997893804077137501290858646578905771426833582768978554717687184427726120509266486102051535642840632368481807287940717127966820060727559555904040233178749447346454760628189541512139162918444297651066947969354016866010055196077687335396511614930937570968554559381513789569039251014953265628147011998326992200066392875374713135236421589265126204072887716578358405219646054105435443642166562244565042999010256586927279142752931172082793937751326106052881235373451068372939893580871243869385934389175713376300720319760816604464683937725806909237297523486702916910426369262090199605204121024077648190316014085863558427609537086558164273995349346546314504040199528537252004957805254656251154109252437991326262713609099402902262062836752132305065183934057450112099341464918433323646569371725914489324159006242020612885732926133596808726500045628284557574596592120530341310111827501306961509835515632004310784601906565493806542525229161991819959602752327702249855738824899882707465936355768582560518068964285376850772012220347920993936179268206590142165615925306737944568949070853263568196831861772268249911472615732035807646298116244013316737892788689229032593349861797021994981925739617673075834417098559222170171825712777534491508205278430904619460835217402005838672849709411023266953921445461066215006410674740207009189911951376466904481267253691537162290791385403937560077835153374167747942100384002308951850994548779039346122220865060160500351776264831611153325587705073541279249909859373473787081194253055121436979749914951860535920403830235716352727630874693219622190064260886183676103346002255477477813641012691906569686495012688376296907233961276287223041141813610060264044030035996988919945827397624114613744804059697062576764723766065541618574690527229238228275186799156983390747671146103022776606020061246876477728819096791613354019881402757992174167678799231603963569492851513633647219540611171767387372555728522940054361785176502307544693869307873499110352182532929726044553210797887711449898870911511237250604238753734841257086064069052058452122754533848008205302450456517669518576913200042816758054924811780519832646032445792829730129105318385636821206215531288668564956512613892261367064093953334570526986959692350353094224543865278677673027540402702246384483553239914751363441044050092330361271496081355490531539021002299595756583705381261965683144286057956696622154721695620870013727768536960840704833325132793112232507148630206951245395003735723346807094656483089209801534878705633491092366057554050864111521441481434630437273271045027768661953107858323334857840297160925215326092558932655600672124359464255065996771770388445396181632879614460817789272171836908880126778207430106422524634807454300476492885553409062185153654355474125476152769772667769772777058315801412185688011705028365275543214803488004442979998062157904564161957212784508928489806426497427090579129069217807298769477975112447305991406050629946894280931034216416629935614828130998870745292716048433630818404126469637925843094185442216359084576146078558562473814931427078266215185541603870206876980461747400808324343665382354555109449498431093494759944672673665352517662706772194183191977196378015702169933675083760057163454643671776723387588643405644871566964321041282595645349841388412890420682047007615596916843038999348366793542549210328113363184722592305554383058206941675629992013373175489122037230349072681068534454035993561823576312837767640631013125335212141994611869350833176587852047112364331226765129964171325217513553261867681942338790365468908001827135283584888444111761234101179918709236507184857856221021104009776994453121795022479578069506532965940383987369907240797679040826794007618729547835963492793904576973661643405359792219285870574957481696694062334272619733518136626063735982575552496509807260123668283605928341855848026958413772558970883789942910549800331113884603401939166122186696058491571485733568286149500019097591125218800396419762163559375743718011480559442298730418196808085647265713547612831629200449880315402105530597076666362749328308916880932359290081787411985738317192616728834918402429721290434965526942726402559641463525914348400675867690350382320572934132981593533044446496829441367323442158380761694831219333119819061096142952201536170298575105594326461468505452684975764807808009221335811378197749271768545075538328768874474591593731162470601091244609829424841287520224462594477638749491997840446829257360968534549843266536862844489365704111817793806441616531223600214918768769467398407517176307516849856359201486892943105940202457969622924566644881967576294349535326382171613395757790766370764569570259738800438415805894336137106551859987600754924187211714889295221737721146081154344982665479872580056674724051122007383459271575727715218589946948117940644466399432370044291140747218180224825837736017346685300744985564715420036123593397312914458591522887408719508708632218837288262822884631843717261903305777147651564143822306791847386039147683108141358275755853643597721650028277803713422869688787349795096031108899196143386664068450697420787700280509367203387232629637856038653216432348815557557018469089074647879122436375556668678067610544955017260791142930831285761254481944449473244819093795369008206384631678225064809531810406570254327604385703505922818919878065865412184299217273720955103242251079718077833042609086794273428955735559252723805511440438001239041687716445180226491681641927401106451622431101700056691121733189423400547959684669804298017362570406733282129962153684881404102194463424646220745575643960452985313071409084608499653767803793201899140865814662175319337665970114330608625009829566917638846056762972931464911493704624469351984039534449135141193667933301936617663652555149174982307987072280860859626112660504289296966535652516688885572112276802772743708917389639772257564890533401038855931125679991516589025016486961427207005916056166159702451989051832969278935550303934681219761582183980483960562523091462638447386296039848924386187298507775928792722068554807210497817653286210187476766897248841139560349480376727036316921007350834073865261684507482496448597428134936480372426116704266870831925040997615319076855770327421785010006441984124207396400139603601583810565928413684574119102736420274163723488214524101347716529603128408658419787951116511529827814620379139855006399960326591248525308493690313130100799977191362230866011099929142871249388541612038020411340188887219693477904497527454288072803509305828754420755134816660927879353566521255620139988249628478726214432362853676502591450468377635282587652139156480972141929675549384375582600253168536356731379262475878049445944183429172756988376226261846365452743497662411138451305481449836311789784489732076719508784158618879692955819733250699951402601511675529750575437810242238957925786562128432731202200716730574069286869363930186765958251326499145950260917069347519408975357464016830811798846452473618956056479426358070562563281189269663026479535951097127659136233180866921535788607812759910537171402204506186075374866306350591483916467656723205714516886170790984695932236724946737583099607042589220481550799132752088583781117685214269334786921895240622657921043620348852926267984013953216458791151579050460579710838983371864038024417511347226472547010794793996953554669619726763255229914654933499663234185951450360980344092212206712567698723427940708857070474293173329188523896721971353924492426178641188637790962814486917869468177591717150669111480020759432012061969637795103227089029566085562225452602610460736131368869009281721068198618553780982018471154163630326265699283424155023600978046417108525537612728905335045506135684143775854429677977014660294387687225115363801191758154028120818255606485410787933598921064427244898618961629413418001295130683638609294100083136673372153008352696235737175330738653338204842190308186449184093723944033405244909554558016406460761581010301767488475017661908692946098769201691202181688291040870709560951470416921147027413390052253340834812870353031023919699978597413908593605433599697075604460134242453682496098772581311024732798562072126572499003468293886872304895562253204463602639854225258416464324271611419817802482595563544907219226583863662663750835944314877635156145710745528016159677048442714194435183275698407552677926411261765250615965235457187956673170913319358761628255920783080185206890151504713340386100310055914817852110384754542933389188444120517943969970194112695119526564919594189975418393234647424290702718875223534393673633663200307232747037407123982562024662651974090199762452056198557625760008708173083288344381831070054514493545885422678578551915372292379555494333410174420169600090696415612732297770221217951868376359082255128816470021992348864043959153018464004714321186360622527011541122283802778538911098490201342741014121559769965438877197485376431158229838533123071751132961904559007938064276695819014842627991221792947987348901868471676503827328552059082984529806259250352128451925927986593506132961946796252373972565584157853744567558998032405492186962888490332560851455344391660226257775512916200772796852629387937530454181080729285891989715381797343496187232927614747850192611450413274873242970583408471112333746274617274626582415324271059322506255302314738759251724787322881491455915605036334575424233779160374952502493022351481961381162563911415610326844958072508273431765944054098269765269344579863479709743124498271933113863873159636361218623497261409556079920628316999420072054811525353393946076850019909886553861433495781650089961649079678142901148387645682174914075623767618453775144031475411206760160726460556859257799322070337333398916369504346690694828436629980037414527627716547623825546170883189810868806847853705536480469350958818025360529740793538676511195079373282083146268960071075175520614433784114549950136432446328193346389050936545714506900864483440180428363390513578157273973334537284263372174065775771079830517555721036795976901889958494130195999573017901240193908681356585539661941371794487632079868800371607303220547423572266896801882123424391885984168972277652194032493227314793669234004848976059037958094696041754279613782553781223947646147832926976545162290281701100437846038756544151739433960048915318817576650500951697402415644771293656614253949368884230517400129920556854289853897942669956777027089146513736892206104415481662156804219838476730871787590279209175900695273456682026513373111518000181434120962601658629821076663523361774007837783423709152644063054071807843358061072961105550020415131696373046849213356837265400307509829089364612047891114753037049893952833457824082817386441322710002968311940203323456420826473276233830294639378998375836554559919340866235090967961134004867027123176526663710778725111860354037554487418693519733656621772359229396776463251562023487570113795712096237723431370212031004965152111976013176419408203437348512852602913334915125083119802850177855710725373149139215709105130965059885999931560863655477403551898166733535880048214665099741433761182777723351910741217572841592580872591315074606025634903777263373914461377038021318347447301113032670296917335047701632106616227830027269283365584011791419447808748253360714403296252285775009808599609040936312635621328162071453406104224112083010008587264252112262480142647519426184325853386753874054743491072710049754281159466017136122590440158991600229827801796035194080046513534752698777609527839984368086908989197839693532179980139135442552717910225397010810632143048511378291498511381969143043497500189980681644412123273328307192824362406733196554692677851193152775113446468905504248113361434984604849051258345683266441528489713972376040328212660253516693914082049947320486021627759791771234751097502403078935759937715095021751693555827072533911892334070223832077585802137174778378778391015234132098489423459613692340497998279304144463162707214796117456975719681239291913740982925805561955207434243295982898980529233366415419256367380689494201471241340525072204061794355252555225008748790086568314542835167750542294803274783044056438581591952666758282929705226127628711040134801787224801789684052407924360582742467443076721645270313451354167649668901274786801010295133862698649748212118629040337691568576240699296372493097201628707200189835423690364149270236961938547372480329855045112089192879829874467864129159417531675602533435310626745254507114181483239880607297140234725520713490798398982355268723950909365667878992383712578976248755990443228895388377317348941122757071410959790047919301046740750411435381782464630795989555638991884773781341347070246747362112048986226991888517456251732519341352038115863350123913054441910073628447567514161050410973505852762044489190978901984315485280533985777844313933883994310444465669244550885946314081751220331390681596592510546858013133838152176418210433429788826119630443111388796258746090226130900849975430395771243230616906262919403921439740270894777663702488155499322458825979020631257436910946393252806241642476868495455324938017639371615636847859823715902385421265840615367228607131702674740131145261063765383390315921943469817605358380310612887852051546933639241088467632009567089718367490578163085158138161966882222047570437590614338040725853862083565176998426774523195824182683698270160237414938363496629351576854061397342746470899685618170160551104880971554859118617189668025973541705423985135560018720335079060946421271143993196046527424050882225359773481519135438571253258540493946010865793798058620143366078825219717809025817370870916460452727977153509910340736425020386386718220522879694458387652947951048660717390229327455426785669776865939923416834122274663015062155320502655341460995249356050854921756549134830958906536175693817637473644183378974229700703545206663170929607591989627732423090252397443861014263098687733913882518684316501027964911497737582888913450341148865948670215492101084328080783428089417298008983297536940644969903125399863919581601468995220880662285408414864274786281975546629278814621607171381880180840572084715868906836919393381864278454537956719272397972364651667592011057995663962598535512763558768140213409829016296873429850792471846056874828331381259161962476156902875901072733103299140623864608333378638257926302391590003557609032477281338887339178096966601469615031754226751125993315529674213336300222964906480934582008181061802100227664580400278213336758573019011371754672763059044353131319036092489097246427928455549913490005180295707082919052556781889913899625138662319380053611346224294610248954072404857123256628888931722116432947816190554868054943441034090680716088028227959686950133643814268252170472870863010137301155236861416908375675747637239763185757038109443390564564468524183028148107998376918512127201935044041804604721626939445788377090105974693219720558114078775989772072009689382249303236830515862657281114637996983137517937623215111252349734305240622105244234353732905655163406669506165892878218707756794176080712973781335187117931650033155523822487730653444179453415395202424449703410120874072188109388268167512042299404948179449472732894770111574139441228455521828424922240658752689172272780607116754046973008037039618787796694882555614674384392570115829546661358678671897661297311267200072971553613027503556167817765442287442114729881614802705243806817653573275578602505847084013208837932816008769081300492491473682517035382219619039014999523495387105997351143478292339499187936608692301375596368532373806703591144243268561512109404259582639301678017128669239283231057658851714020211196957064799814031505633045141564414623163763809904402816256917576489142569714163598439317433270237812336938043012892626375382667795034169334323607500248175741808750388475094939454896209740485442635637164995949920980884294790363666297526003243856352945844728944547166209297495496616877414120882130477022816116456044007236351581149729739218966737382647204722642221242016560150284971306332795814302516013694825567014780935790889657134926158161346901806965089556310121218491805847922720691871696316330044858020102860657858591269974637661741463934159569539554203314628026518951167938074573315759846086173702687867602943677780500244673391332431669880354073232388281847501051641331189537036488422690270478052742490603492082954755054003457160184072574536938145531175354210726557835615499874447480427323457880061873149341566046352979779455075359304795687209316724536547208381685855606043801977030764246083489876101345709394877002946175792061952549255757109038525171488525265671045349813419803390641529876343695420256080277614421914318921393908834543131769685101840103844472348948869520981943531906506555354617335814045544837884752526253949665869992058417652780125341033896469818642430034146791380619028059607854888010789705516946215228773090104467462497979992627120951684779568482583341402266477210843362437593741610536734041954738964197895425335036301861400951534766961476255651873823292468547356935802896011536791787303553159378363082248615177770541577576561759358512016692943111138863582159667618830326104164651714846979385422621687161400122378213779774131268977266712992025922017408770076956283473932201088159356286281928563571893384958850603853158179760679479840878360975960149733420572704603521790605647603285569276273495182203236144112584182426247712012035776388895974318232827871314608053533574494297621796789034568169889553518504478325616380709476951699086247100019748809205009521943632378719764870339223811540363475488626845956159755193765410115014067001226927474393888589943859730245414801061235908036274585288493563251585384383242493252666087588908318700709100237377106576985056433928854337658342596750653715005333514489908293887737352051459333049626531415141386124437935885070944688045486975358170212908490787347806814366323322819415827345671356443171537967818058195852464840084032909981943781718177302317003989733050495387356116261023999433259780126893432605584710278764901070923443884634011735556865903585244919370181041626208504299258697435817098133894045934471937493877624232409852832762266604942385129709453245586252103600829286649724174919141988966129558076770979594795306013119159011773943104209049079424448868513086844493705909026006120649425744710353547657859242708130410618546219881830090634588187038755856274911587375421064667951346487586771543838018521348281915812462599335160198935595167968932852205824799421034512715877163345222995418839680448835529753361286837225935390079201666941339091168758803988828869216002373257361588207163516271332810518187602104852180675526648673908900907195138058626735124312215691637902277328705410842037841525683288718046987952513073266340278519059417338920358540395677035611329354482585628287610610698229721420961993509331312171187891078766872044548876089410174798647137882462153955933333275562009439580434537919782280590395959927436913793778664940964048777841748336432684026282932406260081908081804390914556351936856063045089142289645219987798849347477729132797266027658401667890136490508741142126861969862044126965282981087045479861559545338021201155646979976785738920186243599326777689454060508218838227909833627167124490026761178498264377033002081844590009717235204331994708242098771514449751017055643029542821819670009202515615844174205933658148134902693111517093872260026458630561325605792560927332265579346280805683443921373688405650434307396574061017779370141424615493070741360805442100295600095663588977899267630517718781943706761498217564186590116160865408635391513039201316805769034172596453692350806417446562351523929050409479953184074862151210561833854566176652606393713658802521666223576132201941701372664966073252010771947931265282763302413805164907174565964853748354669194523580315301969160480994606814904037819829732360930087135760798621425422096419004367905479049930078372421581954535418371129368658430553842717628035279128821129308351575656599944741788438381565148434229858704245592434693295232821803508333726283791830216591836181554217157448465778420134329982594566884558266171979012180849480332448787258183774805522268151011371745368417870280274452442905474518234674919564188551244421337783521423865979925988203287085109338386829906571994614906290257427686038850511032638544540419184958866538545040571323629681069146814847869659166861842756798460041868762298055562963045953227923051616721591968675849523635298935788507746081537321454642984792310511676357749494622952569497660359473962430995343310404994209677883827002714478494069037073249106444151696053256560586778757417472110827435774315194060757983563629143326397812218946287447798119807225646714664054850131009656786314880090303749338875364183165134982546694673316118123364854397649325026179549357204305402182974871251107404011611405899911093062492312813116340549262571356721818628932786138833718028535056503591952741400869510926167541476792668032109237467087213606278332922386413619594121339278036118276324106004740971111048140003623342714514483334641675466354699731494756643423659493496845884551524150756376605086632827424794136062876041290644913828519456402643153225858624043141838669590633245063000392213192647625962691510904457695301444054618037857503036686212462278639752746667870121003392984873375014475600322100622358029343774955032037012738468163061026570300872275462966796880890587127676361066225722352229739206443093524327228100859973095132528630601105497915644791845004618046762408928925680912930592960642357021061524646205023248966593987324933967376952023991760898474571843531936646529125848064480196520162838795189499336759241485626136995945307287254532463291529110128763770605570609531377527751867923292134955245133089867969165129073841302167573238637575820080363575728002754490327953079900799442541108725693188014667935595834676432868876966610097395749967836593397846346959948950610490383647409504695226063858046758073069912290474089879166872117147527644711604401952718169508289733537148530928937046384420893299771125856840846608339934045689026787516008775461267988015465856522061210953490796707365539702576199431376639960606061106406959330828171876426043573425361756943784848495250108266488395159700490598380812105221111091943323951136051446459834210799058082093716464523127704023160072138543723461267260997870385657091998507595634613248460188409850194287687902268734556500519121546544063829253851276317663922050938345204300773017029940362615434001322763910912988327863920412300445551684054889809080779174636092439334912641164240093880746356607262336695842764583698268734815881961058571835767462009650526065929263548291499045768307210893245857073701660717398194485028842603963660746031184786225831056580870870305567595861341700745402965687634774176431051751036732869245558582082372038601781739405175130437994868822320044378043103170921034261674998000073016094814586374488778522273076330495383944345382770608760763542098445008306247630253572781032783461766970544287155315340016497076657195985041748199087201490875686037783591994719343352772947285537925787684832301101859365800717291186967617655053775030293033830706448912811412025506150896411007623824574488655182581058140345320124754723269087547507078577659732542844459353044992070014538748948226556442223696365544194225441338212225477497535494624827680533336983284156138692363443358553868471111430498248398991803165458638289353799130535222833430137953372954016257623228081138499491876144141322933767106563492528814528239506209022357876684650116660097382753660405446941653422239052108314585847035529352219928272760574821266065291385530345549744551470344939486863429459658431024190785923680224560763936784166270518555178702904073557304620639692453307795782245949710420188043000183881429008173039450507342787013124466860092778581811040911511729374873627887874907465285565434748886831064110051023020875107768918781525622735251550379532444857787277617001964853703555167655209119339343762866284619844026295252183678522367475108809781507098978413086245881522660963551401874495836926917799047120726494905737264286005211403581231076006699518536124862746756375896225299116496066876508261734178484789337295056739007878617925351440621045366250640463728815698232317500596261080921955211150859302955654967538862612972339914628358476048627627027309739202001432248707582337354915246085608210328882974183906478869923273691360048837436615223517058437705545210815513361262142911815615301758882573594892507108879262128641392443309383797333867806131795237315266773820858024701433527009243803266951742119507670884326346442749127558907746863582162166042741315170212458586056233631493164646913946562497471741958354218607748711057338458433689939645913740603382159352243594751626239188685307822821763983237306180204246560477527943104796189724299533029792497481684052893791044947004590864991872727345413508101983881864673609392571930511968645601855782450218231065889437986522432050677379966196955472440585922417953006820451795370043472451762893566770508490213107736625751697335527462302943031203596260953423574397249659211010657817826108745318874803187430823573699195156340957162700992444929749105489851519658664740148225106335367949737142510229341882585117371994499115097583746130105505064197721531929354875371191630262030328588658528480193509225875775597425276584011721342323648084027143356367542046375182552524944329657043861387865901965738802868401894087672816714137033661732650120578653915780703088714261519075001492576112927675193096728453971160213606303090542243966320674323582797889332324405779199278484633339777737655901870574806828678347965624146102899508487399692970750432753029972872297327934442988646412725348160603779707298299173029296308695801996312413304939350493325412355071054461182591141116454534710329881047844067780138077131465400099386306481266614330858206811395838319169545558259426895769841428893743467084107946318932539106963955780706021245974898293564613560788983472419979478564362042094613412387613198865352358312996862268948608408456655606876954501274486631405054735351746873009806322780468912246821460806727627708402402266155485024008952891657117617439020337584877842911289623247059191874691042005848326140677333751027195653994697162517248312230633919328707983800748485726516123434933273356664473358556430235280883924348278760886164943289399166399210488307847777048045728491456303353265070029588906265915498509407972767567129795010098229476228961891591441520032283878773485130979081019129267227103778898053964156362364169154985768408398468861684375407065121039062506128107663799047908879674778069738473170475253442156390387201238806323688037017949308954900776331523063548374256816653361606641980030188287123767481898330246836371488309259283375902278942588060087286038859168849730693948020511221766359138251524278670094406942355120201568377778851824670025651708509249623747726813694284350062938814429987905301056217375459182679973217735029368928065210025396268807498092643458011655715886700443503976505323478287327368840863540002740676783821963522226539290939807367391364082898722017776747168118195856133721583119054682936083236976113450281757830202934845982925000895682630271263295866292147653142233351793093387951357095346377183684092444422096319331295620305575517340067973740614162107923633423805646850092037167152642556371853889571416419772387422610596667396997173168169415435095283193556417705668622215217991151355639707143312893657553844648326201206424338016955862698561022460646069330793847858814367407000599769703649019273328826135329363112403650698652160638987250267238087403396744397830258296894256896741864336134979475245526291426522842419243083388103580053787023999542172113686550275341362211693140694669513186928102574795985605145005021715913317751609957865551981886193211282110709442287240442481153406055895958355815232012184605820563592699303478851132068626627588771446035996656108430725696500563064489187599466596772847171539573612108180841547273142661748933134174632662354222072600146012701206934639520564445543291662986660783089068118790090815295063626782075614388815781351134695366303878412092346942868730839320432333872775496805210302821544324723388845215343727250128589747691460808314404125868181540049187772287869801853454537006526655649170915429522756709222217474112062720656622989806032891672068743654948246108697367225547404812889242471854323605753411672850757552057131156697954584887398742228135887985840783135060548290551482785294891121905383195624228719484759407859398047901094194070671764439032730712135887385049993638838205501683402777496070276844880281912220636888636811043569529300652195528261526991271637277388418993287130563464688227398288763198645709836308917786487086676185485680047672552675414742851028145807403152992197814557756843681110185317498167016426647884090262682824448258027532094549915104518517716546311804904567985713257528117913656278158111288816562285876030875974963849435275676612168959261485030785362045274507752950631012480341804584059432926079854435620093708091821523920371790678121992280496069738238743312626730306795943960954957189577217915597300588693646845576676092450906088202212235719254536715191834872587423919410890444115959932760044506556206461164655665487594247369252336955993030355095817626176231849561906494839673002037763874369343999829430209147073618947932692762445186560239559053705128978163455423320114975994896278424327483788032701418676952621180975006405149755889650293004867605208010491537885413909424531691719987628941277221129464568294860281493181560249677887949813777216229359437811004448060797672429276249510784153446429150842764520002042769470698041775832209097020291657347251582904630910359037842977572651720877244740952267166306005469716387943171196873484688738186656751279298575016363411314627530499019135646823804329970695770150789337728658035712790913767420805655493624646
diff --git a/third_party/gofrontend/libgo/go/compress/zlib/reader.go b/third_party/gofrontend/libgo/go/compress/zlib/reader.go
new file mode 100644
index 0000000..9e1aafd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/zlib/reader.go
@@ -0,0 +1,132 @@
+// 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 zlib implements reading and writing of zlib format compressed data,
+as specified in RFC 1950.
+
+The implementation provides filters that uncompress during reading
+and compress during writing.  For example, to write compressed data
+to a buffer:
+
+	var b bytes.Buffer
+	w := zlib.NewWriter(&b)
+	w.Write([]byte("hello, world\n"))
+	w.Close()
+
+and to read that data back:
+
+	r, err := zlib.NewReader(&b)
+	io.Copy(os.Stdout, r)
+	r.Close()
+*/
+package zlib
+
+import (
+	"bufio"
+	"compress/flate"
+	"errors"
+	"hash"
+	"hash/adler32"
+	"io"
+)
+
+const zlibDeflate = 8
+
+var (
+	// ErrChecksum is returned when reading ZLIB data that has an invalid checksum.
+	ErrChecksum = errors.New("zlib: invalid checksum")
+	// ErrDictionary is returned when reading ZLIB data that has an invalid dictionary.
+	ErrDictionary = errors.New("zlib: invalid dictionary")
+	// ErrHeader is returned when reading ZLIB data that has an invalid header.
+	ErrHeader = errors.New("zlib: invalid header")
+)
+
+type reader struct {
+	r            flate.Reader
+	decompressor io.ReadCloser
+	digest       hash.Hash32
+	err          error
+	scratch      [4]byte
+}
+
+// NewReader creates a new io.ReadCloser.
+// Reads from the returned io.ReadCloser read and decompress data from r.
+// The implementation buffers input and may read more data than necessary from r.
+// It is the caller's responsibility to call Close on the ReadCloser when done.
+func NewReader(r io.Reader) (io.ReadCloser, error) {
+	return NewReaderDict(r, nil)
+}
+
+// NewReaderDict is like NewReader but uses a preset dictionary.
+// NewReaderDict ignores the dictionary if the compressed data does not refer to it.
+func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
+	z := new(reader)
+	if fr, ok := r.(flate.Reader); ok {
+		z.r = fr
+	} else {
+		z.r = bufio.NewReader(r)
+	}
+	_, err := io.ReadFull(z.r, z.scratch[0:2])
+	if err != nil {
+		return nil, err
+	}
+	h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
+	if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
+		return nil, ErrHeader
+	}
+	if z.scratch[1]&0x20 != 0 {
+		_, err = io.ReadFull(z.r, z.scratch[0:4])
+		if err != nil {
+			return nil, err
+		}
+		checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
+		if checksum != adler32.Checksum(dict) {
+			return nil, ErrDictionary
+		}
+		z.decompressor = flate.NewReaderDict(z.r, dict)
+	} else {
+		z.decompressor = flate.NewReader(z.r)
+	}
+	z.digest = adler32.New()
+	return z, nil
+}
+
+func (z *reader) Read(p []byte) (n int, err error) {
+	if z.err != nil {
+		return 0, z.err
+	}
+	if len(p) == 0 {
+		return 0, nil
+	}
+
+	n, err = z.decompressor.Read(p)
+	z.digest.Write(p[0:n])
+	if n != 0 || err != io.EOF {
+		z.err = err
+		return
+	}
+
+	// Finished file; check checksum.
+	if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
+		z.err = err
+		return 0, err
+	}
+	// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
+	checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
+	if checksum != z.digest.Sum32() {
+		z.err = ErrChecksum
+		return 0, z.err
+	}
+	return
+}
+
+// Calling Close does not close the wrapped io.Reader originally passed to NewReader.
+func (z *reader) Close() error {
+	if z.err != nil {
+		return z.err
+	}
+	z.err = z.decompressor.Close()
+	return z.err
+}
diff --git a/third_party/gofrontend/libgo/go/compress/zlib/reader_test.go b/third_party/gofrontend/libgo/go/compress/zlib/reader_test.go
new file mode 100644
index 0000000..218ccba
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/zlib/reader_test.go
@@ -0,0 +1,127 @@
+// 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 zlib
+
+import (
+	"bytes"
+	"io"
+	"testing"
+)
+
+type zlibTest struct {
+	desc       string
+	raw        string
+	compressed []byte
+	dict       []byte
+	err        error
+}
+
+// Compare-to-golden test data was generated by the ZLIB example program at
+// http://www.zlib.net/zpipe.c
+
+var zlibTests = []zlibTest{
+	{
+		"empty",
+		"",
+		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
+		nil,
+		nil,
+	},
+	{
+		"goodbye",
+		"goodbye, world",
+		[]byte{
+			0x78, 0x9c, 0x4b, 0xcf, 0xcf, 0x4f, 0x49, 0xaa,
+			0x4c, 0xd5, 0x51, 0x28, 0xcf, 0x2f, 0xca, 0x49,
+			0x01, 0x00, 0x28, 0xa5, 0x05, 0x5e,
+		},
+		nil,
+		nil,
+	},
+	{
+		"bad header",
+		"",
+		[]byte{0x78, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
+		nil,
+		ErrHeader,
+	},
+	{
+		"bad checksum",
+		"",
+		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff},
+		nil,
+		ErrChecksum,
+	},
+	{
+		"not enough data",
+		"",
+		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00},
+		nil,
+		io.ErrUnexpectedEOF,
+	},
+	{
+		"excess data is silently ignored",
+		"",
+		[]byte{
+			0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01,
+			0x78, 0x9c, 0xff,
+		},
+		nil,
+		nil,
+	},
+	{
+		"dictionary",
+		"Hello, World!\n",
+		[]byte{
+			0x78, 0xbb, 0x1c, 0x32, 0x04, 0x27, 0xf3, 0x00,
+			0xb1, 0x75, 0x20, 0x1c, 0x45, 0x2e, 0x00, 0x24,
+			0x12, 0x04, 0x74,
+		},
+		[]byte{
+			0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a,
+		},
+		nil,
+	},
+	{
+		"wrong dictionary",
+		"",
+		[]byte{
+			0x78, 0xbb, 0x1c, 0x32, 0x04, 0x27, 0xf3, 0x00,
+			0xb1, 0x75, 0x20, 0x1c, 0x45, 0x2e, 0x00, 0x24,
+			0x12, 0x04, 0x74,
+		},
+		[]byte{
+			0x48, 0x65, 0x6c, 0x6c,
+		},
+		ErrDictionary,
+	},
+}
+
+func TestDecompressor(t *testing.T) {
+	b := new(bytes.Buffer)
+	for _, tt := range zlibTests {
+		in := bytes.NewReader(tt.compressed)
+		zlib, err := NewReaderDict(in, tt.dict)
+		if err != nil {
+			if err != tt.err {
+				t.Errorf("%s: NewReader: %s", tt.desc, err)
+			}
+			continue
+		}
+		defer zlib.Close()
+		b.Reset()
+		n, err := io.Copy(b, zlib)
+		if err != nil {
+			if err != tt.err {
+				t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err)
+			}
+			continue
+		}
+		s := b.String()
+		if s != tt.raw {
+			t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.desc, n, s, len(tt.raw), tt.raw)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/compress/zlib/writer.go b/third_party/gofrontend/libgo/go/compress/zlib/writer.go
new file mode 100644
index 0000000..3b4313a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/zlib/writer.go
@@ -0,0 +1,198 @@
+// 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 zlib
+
+import (
+	"compress/flate"
+	"fmt"
+	"hash"
+	"hash/adler32"
+	"io"
+)
+
+// These constants are copied from the flate package, so that code that imports
+// "compress/zlib" does not also have to import "compress/flate".
+const (
+	NoCompression      = flate.NoCompression
+	BestSpeed          = flate.BestSpeed
+	BestCompression    = flate.BestCompression
+	DefaultCompression = flate.DefaultCompression
+)
+
+// A Writer takes data written to it and writes the compressed
+// form of that data to an underlying writer (see NewWriter).
+type Writer struct {
+	w           io.Writer
+	level       int
+	dict        []byte
+	compressor  *flate.Writer
+	digest      hash.Hash32
+	err         error
+	scratch     [4]byte
+	wroteHeader bool
+}
+
+// NewWriter creates a new Writer.
+// Writes to the returned Writer are compressed and written to w.
+//
+// It is the caller's responsibility to call Close on the WriteCloser when done.
+// Writes may be buffered and not flushed until Close.
+func NewWriter(w io.Writer) *Writer {
+	z, _ := NewWriterLevelDict(w, DefaultCompression, nil)
+	return z
+}
+
+// NewWriterLevel is like NewWriter but specifies the compression level instead
+// of assuming DefaultCompression.
+//
+// The compression level can be DefaultCompression, NoCompression, or any
+// integer value between BestSpeed and BestCompression inclusive. The error
+// returned will be nil if the level is valid.
+func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
+	return NewWriterLevelDict(w, level, nil)
+}
+
+// NewWriterLevelDict is like NewWriterLevel but specifies a dictionary to
+// compress with.
+//
+// The dictionary may be nil. If not, its contents should not be modified until
+// the Writer is closed.
+func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error) {
+	if level < DefaultCompression || level > BestCompression {
+		return nil, fmt.Errorf("zlib: invalid compression level: %d", level)
+	}
+	return &Writer{
+		w:     w,
+		level: level,
+		dict:  dict,
+	}, nil
+}
+
+// Reset clears the state of the Writer z such that it is equivalent to its
+// initial state from NewWriterLevel or NewWriterLevelDict, but instead writing
+// to w.
+func (z *Writer) Reset(w io.Writer) {
+	z.w = w
+	// z.level and z.dict left unchanged.
+	if z.compressor != nil {
+		z.compressor.Reset(w)
+	}
+	if z.digest != nil {
+		z.digest.Reset()
+	}
+	z.err = nil
+	z.scratch = [4]byte{}
+	z.wroteHeader = false
+}
+
+// writeHeader writes the ZLIB header.
+func (z *Writer) writeHeader() (err error) {
+	z.wroteHeader = true
+	// ZLIB has a two-byte header (as documented in RFC 1950).
+	// The first four bits is the CINFO (compression info), which is 7 for the default deflate window size.
+	// The next four bits is the CM (compression method), which is 8 for deflate.
+	z.scratch[0] = 0x78
+	// The next two bits is the FLEVEL (compression level). The four values are:
+	// 0=fastest, 1=fast, 2=default, 3=best.
+	// The next bit, FDICT, is set if a dictionary is given.
+	// The final five FCHECK bits form a mod-31 checksum.
+	switch z.level {
+	case 0, 1:
+		z.scratch[1] = 0 << 6
+	case 2, 3, 4, 5:
+		z.scratch[1] = 1 << 6
+	case 6, -1:
+		z.scratch[1] = 2 << 6
+	case 7, 8, 9:
+		z.scratch[1] = 3 << 6
+	default:
+		panic("unreachable")
+	}
+	if z.dict != nil {
+		z.scratch[1] |= 1 << 5
+	}
+	z.scratch[1] += uint8(31 - (uint16(z.scratch[0])<<8+uint16(z.scratch[1]))%31)
+	if _, err = z.w.Write(z.scratch[0:2]); err != nil {
+		return err
+	}
+	if z.dict != nil {
+		// The next four bytes are the Adler-32 checksum of the dictionary.
+		checksum := adler32.Checksum(z.dict)
+		z.scratch[0] = uint8(checksum >> 24)
+		z.scratch[1] = uint8(checksum >> 16)
+		z.scratch[2] = uint8(checksum >> 8)
+		z.scratch[3] = uint8(checksum >> 0)
+		if _, err = z.w.Write(z.scratch[0:4]); err != nil {
+			return err
+		}
+	}
+	if z.compressor == nil {
+		// Initialize deflater unless the Writer is being reused
+		// after a Reset call.
+		z.compressor, err = flate.NewWriterDict(z.w, z.level, z.dict)
+		if err != nil {
+			return err
+		}
+		z.digest = adler32.New()
+	}
+	return nil
+}
+
+// Write writes a compressed form of p to the underlying io.Writer. The
+// compressed bytes are not necessarily flushed until the Writer is closed or
+// explicitly flushed.
+func (z *Writer) Write(p []byte) (n int, err error) {
+	if !z.wroteHeader {
+		z.err = z.writeHeader()
+	}
+	if z.err != nil {
+		return 0, z.err
+	}
+	if len(p) == 0 {
+		return 0, nil
+	}
+	n, err = z.compressor.Write(p)
+	if err != nil {
+		z.err = err
+		return
+	}
+	z.digest.Write(p)
+	return
+}
+
+// Flush flushes the Writer to its underlying io.Writer.
+func (z *Writer) Flush() error {
+	if !z.wroteHeader {
+		z.err = z.writeHeader()
+	}
+	if z.err != nil {
+		return z.err
+	}
+	z.err = z.compressor.Flush()
+	return z.err
+}
+
+// Close closes the Writer, flushing any unwritten data to the underlying
+// io.Writer, but does not close the underlying io.Writer.
+func (z *Writer) Close() error {
+	if !z.wroteHeader {
+		z.err = z.writeHeader()
+	}
+	if z.err != nil {
+		return z.err
+	}
+	z.err = z.compressor.Close()
+	if z.err != nil {
+		return z.err
+	}
+	checksum := z.digest.Sum32()
+	// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
+	z.scratch[0] = uint8(checksum >> 24)
+	z.scratch[1] = uint8(checksum >> 16)
+	z.scratch[2] = uint8(checksum >> 8)
+	z.scratch[3] = uint8(checksum >> 0)
+	_, z.err = z.w.Write(z.scratch[0:4])
+	return z.err
+}
diff --git a/third_party/gofrontend/libgo/go/compress/zlib/writer_test.go b/third_party/gofrontend/libgo/go/compress/zlib/writer_test.go
new file mode 100644
index 0000000..71ba81a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/compress/zlib/writer_test.go
@@ -0,0 +1,205 @@
+// 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 zlib
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"testing"
+)
+
+var filenames = []string{
+	"../testdata/e.txt",
+	"../testdata/pi.txt",
+}
+
+var data = []string{
+	"test a reasonable sized string that can be compressed",
+}
+
+// Tests that compressing and then decompressing the given file at the given compression level and dictionary
+// yields equivalent bytes to the original file.
+func testFileLevelDict(t *testing.T, fn string, level int, d string) {
+	// Read the file, as golden output.
+	golden, err := os.Open(fn)
+	if err != nil {
+		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
+		return
+	}
+	defer golden.Close()
+	b0, err0 := ioutil.ReadAll(golden)
+	if err0 != nil {
+		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
+		return
+	}
+	testLevelDict(t, fn, b0, level, d)
+}
+
+func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) {
+	// Make dictionary, if given.
+	var dict []byte
+	if d != "" {
+		dict = []byte(d)
+	}
+
+	// Push data through a pipe that compresses at the write end, and decompresses at the read end.
+	piper, pipew := io.Pipe()
+	defer piper.Close()
+	go func() {
+		defer pipew.Close()
+		zlibw, err := NewWriterLevelDict(pipew, level, dict)
+		if err != nil {
+			t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
+			return
+		}
+		defer zlibw.Close()
+		_, err = zlibw.Write(b0)
+		if err != nil {
+			t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
+			return
+		}
+	}()
+	zlibr, err := NewReaderDict(piper, dict)
+	if err != nil {
+		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
+		return
+	}
+	defer zlibr.Close()
+
+	// Compare the decompressed data.
+	b1, err1 := ioutil.ReadAll(zlibr)
+	if err1 != nil {
+		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
+		return
+	}
+	if len(b0) != len(b1) {
+		t.Errorf("%s (level=%d, dict=%q): length mismatch %d versus %d", fn, level, d, len(b0), len(b1))
+		return
+	}
+	for i := 0; i < len(b0); i++ {
+		if b0[i] != b1[i] {
+			t.Errorf("%s (level=%d, dict=%q): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, d, i, b0[i], b1[i])
+			return
+		}
+	}
+}
+
+func testFileLevelDictReset(t *testing.T, fn string, level int, dict []byte) {
+	var b0 []byte
+	var err error
+	if fn != "" {
+		b0, err = ioutil.ReadFile(fn)
+		if err != nil {
+			t.Errorf("%s (level=%d): %v", fn, level, err)
+			return
+		}
+	}
+
+	// Compress once.
+	buf := new(bytes.Buffer)
+	var zlibw *Writer
+	if dict == nil {
+		zlibw, err = NewWriterLevel(buf, level)
+	} else {
+		zlibw, err = NewWriterLevelDict(buf, level, dict)
+	}
+	if err == nil {
+		_, err = zlibw.Write(b0)
+	}
+	if err == nil {
+		err = zlibw.Close()
+	}
+	if err != nil {
+		t.Errorf("%s (level=%d): %v", fn, level, err)
+		return
+	}
+	out := buf.String()
+
+	// Reset and compress again.
+	buf2 := new(bytes.Buffer)
+	zlibw.Reset(buf2)
+	_, err = zlibw.Write(b0)
+	if err == nil {
+		err = zlibw.Close()
+	}
+	if err != nil {
+		t.Errorf("%s (level=%d): %v", fn, level, err)
+		return
+	}
+	out2 := buf2.String()
+
+	if out2 != out {
+		t.Errorf("%s (level=%d): different output after reset (got %d bytes, expected %d",
+			fn, level, len(out2), len(out))
+	}
+}
+
+func TestWriter(t *testing.T) {
+	for i, s := range data {
+		b := []byte(s)
+		tag := fmt.Sprintf("#%d", i)
+		testLevelDict(t, tag, b, DefaultCompression, "")
+		testLevelDict(t, tag, b, NoCompression, "")
+		for level := BestSpeed; level <= BestCompression; level++ {
+			testLevelDict(t, tag, b, level, "")
+		}
+	}
+}
+
+func TestWriterBig(t *testing.T) {
+	for _, fn := range filenames {
+		testFileLevelDict(t, fn, DefaultCompression, "")
+		testFileLevelDict(t, fn, NoCompression, "")
+		for level := BestSpeed; level <= BestCompression; level++ {
+			testFileLevelDict(t, fn, level, "")
+		}
+	}
+}
+
+func TestWriterDict(t *testing.T) {
+	const dictionary = "0123456789."
+	for _, fn := range filenames {
+		testFileLevelDict(t, fn, DefaultCompression, dictionary)
+		testFileLevelDict(t, fn, NoCompression, dictionary)
+		for level := BestSpeed; level <= BestCompression; level++ {
+			testFileLevelDict(t, fn, level, dictionary)
+		}
+	}
+}
+
+func TestWriterReset(t *testing.T) {
+	const dictionary = "0123456789."
+	for _, fn := range filenames {
+		testFileLevelDictReset(t, fn, NoCompression, nil)
+		testFileLevelDictReset(t, fn, DefaultCompression, nil)
+		testFileLevelDictReset(t, fn, NoCompression, []byte(dictionary))
+		testFileLevelDictReset(t, fn, DefaultCompression, []byte(dictionary))
+		if !testing.Short() {
+			for level := BestSpeed; level <= BestCompression; level++ {
+				testFileLevelDictReset(t, fn, level, nil)
+			}
+		}
+	}
+}
+
+func TestWriterDictIsUsed(t *testing.T) {
+	var input = []byte("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
+	var buf bytes.Buffer
+	compressor, err := NewWriterLevelDict(&buf, BestCompression, input)
+	if err != nil {
+		t.Errorf("error in NewWriterLevelDict: %s", err)
+		return
+	}
+	compressor.Write(input)
+	compressor.Close()
+	const expectedMaxSize = 25
+	output := buf.Bytes()
+	if len(output) > expectedMaxSize {
+		t.Errorf("result too large (got %d, want <= %d bytes). Is the dictionary being used?", len(output), expectedMaxSize)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/container/heap/heap.go b/third_party/gofrontend/libgo/go/container/heap/heap.go
new file mode 100644
index 0000000..c467a11
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/container/heap/heap.go
@@ -0,0 +1,117 @@
+// 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 heap provides heap operations for any type that implements
+// heap.Interface. A heap is a tree with the property that each node is the
+// minimum-valued node in its subtree.
+//
+// The minimum element in the tree is the root, at index 0.
+//
+// A heap is a common way to implement a priority queue. To build a priority
+// queue, implement the Heap interface with the (negative) priority as the
+// ordering for the Less method, so Push adds items while Pop removes the
+// highest-priority item from the queue. The Examples include such an
+// implementation; the file example_pq_test.go has the complete source.
+//
+package heap
+
+import "sort"
+
+// Any type that implements heap.Interface may be used as a
+// min-heap with the following invariants (established after
+// Init has been called or if the data is empty or sorted):
+//
+//	!h.Less(j, i) for 0 <= i < h.Len() and 2*i+1 <= j <= 2*i+2 and j < h.Len()
+//
+// Note that Push and Pop in this interface are for package heap's
+// implementation to call.  To add and remove things from the heap,
+// use heap.Push and heap.Pop.
+type Interface interface {
+	sort.Interface
+	Push(x interface{}) // add x as element Len()
+	Pop() interface{}   // remove and return element Len() - 1.
+}
+
+// A heap must be initialized before any of the heap operations
+// can be used. Init is idempotent with respect to the heap invariants
+// and may be called whenever the heap invariants may have been invalidated.
+// Its complexity is O(n) where n = h.Len().
+//
+func Init(h Interface) {
+	// heapify
+	n := h.Len()
+	for i := n/2 - 1; i >= 0; i-- {
+		down(h, i, n)
+	}
+}
+
+// Push pushes the element x onto the heap. The complexity is
+// O(log(n)) where n = h.Len().
+//
+func Push(h Interface, x interface{}) {
+	h.Push(x)
+	up(h, h.Len()-1)
+}
+
+// Pop removes the minimum element (according to Less) from the heap
+// and returns it. The complexity is O(log(n)) where n = h.Len().
+// It is equivalent to Remove(h, 0).
+//
+func Pop(h Interface) interface{} {
+	n := h.Len() - 1
+	h.Swap(0, n)
+	down(h, 0, n)
+	return h.Pop()
+}
+
+// Remove removes the element at index i from the heap.
+// The complexity is O(log(n)) where n = h.Len().
+//
+func Remove(h Interface, i int) interface{} {
+	n := h.Len() - 1
+	if n != i {
+		h.Swap(i, n)
+		down(h, i, n)
+		up(h, i)
+	}
+	return h.Pop()
+}
+
+// Fix re-establishes the heap ordering after the element at index i has changed its value.
+// Changing the value of the element at index i and then calling Fix is equivalent to,
+// but less expensive than, calling Remove(h, i) followed by a Push of the new value.
+// The complexity is O(log(n)) where n = h.Len().
+func Fix(h Interface, i int) {
+	down(h, i, h.Len())
+	up(h, i)
+}
+
+func up(h Interface, j int) {
+	for {
+		i := (j - 1) / 2 // parent
+		if i == j || !h.Less(j, i) {
+			break
+		}
+		h.Swap(i, j)
+		j = i
+	}
+}
+
+func down(h Interface, i, n int) {
+	for {
+		j1 := 2*i + 1
+		if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
+			break
+		}
+		j := j1 // left child
+		if j2 := j1 + 1; j2 < n && !h.Less(j1, j2) {
+			j = j2 // = 2*i + 2  // right child
+		}
+		if !h.Less(j, i) {
+			break
+		}
+		h.Swap(i, j)
+		i = j
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/container/heap/heap_test.go b/third_party/gofrontend/libgo/go/container/heap/heap_test.go
new file mode 100644
index 0000000..b3d054c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/container/heap/heap_test.go
@@ -0,0 +1,213 @@
+// 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 heap
+
+import (
+	"math/rand"
+	"testing"
+)
+
+type myHeap []int
+
+func (h *myHeap) Less(i, j int) bool {
+	return (*h)[i] < (*h)[j]
+}
+
+func (h *myHeap) Swap(i, j int) {
+	(*h)[i], (*h)[j] = (*h)[j], (*h)[i]
+}
+
+func (h *myHeap) Len() int {
+	return len(*h)
+}
+
+func (h *myHeap) Pop() (v interface{}) {
+	*h, v = (*h)[:h.Len()-1], (*h)[h.Len()-1]
+	return
+}
+
+func (h *myHeap) Push(v interface{}) {
+	*h = append(*h, v.(int))
+}
+
+func (h myHeap) verify(t *testing.T, i int) {
+	n := h.Len()
+	j1 := 2*i + 1
+	j2 := 2*i + 2
+	if j1 < n {
+		if h.Less(j1, i) {
+			t.Errorf("heap invariant invalidated [%d] = %d > [%d] = %d", i, h[i], j1, h[j1])
+			return
+		}
+		h.verify(t, j1)
+	}
+	if j2 < n {
+		if h.Less(j2, i) {
+			t.Errorf("heap invariant invalidated [%d] = %d > [%d] = %d", i, h[i], j1, h[j2])
+			return
+		}
+		h.verify(t, j2)
+	}
+}
+
+func TestInit0(t *testing.T) {
+	h := new(myHeap)
+	for i := 20; i > 0; i-- {
+		h.Push(0) // all elements are the same
+	}
+	Init(h)
+	h.verify(t, 0)
+
+	for i := 1; h.Len() > 0; i++ {
+		x := Pop(h).(int)
+		h.verify(t, 0)
+		if x != 0 {
+			t.Errorf("%d.th pop got %d; want %d", i, x, 0)
+		}
+	}
+}
+
+func TestInit1(t *testing.T) {
+	h := new(myHeap)
+	for i := 20; i > 0; i-- {
+		h.Push(i) // all elements are different
+	}
+	Init(h)
+	h.verify(t, 0)
+
+	for i := 1; h.Len() > 0; i++ {
+		x := Pop(h).(int)
+		h.verify(t, 0)
+		if x != i {
+			t.Errorf("%d.th pop got %d; want %d", i, x, i)
+		}
+	}
+}
+
+func Test(t *testing.T) {
+	h := new(myHeap)
+	h.verify(t, 0)
+
+	for i := 20; i > 10; i-- {
+		h.Push(i)
+	}
+	Init(h)
+	h.verify(t, 0)
+
+	for i := 10; i > 0; i-- {
+		Push(h, i)
+		h.verify(t, 0)
+	}
+
+	for i := 1; h.Len() > 0; i++ {
+		x := Pop(h).(int)
+		if i < 20 {
+			Push(h, 20+i)
+		}
+		h.verify(t, 0)
+		if x != i {
+			t.Errorf("%d.th pop got %d; want %d", i, x, i)
+		}
+	}
+}
+
+func TestRemove0(t *testing.T) {
+	h := new(myHeap)
+	for i := 0; i < 10; i++ {
+		h.Push(i)
+	}
+	h.verify(t, 0)
+
+	for h.Len() > 0 {
+		i := h.Len() - 1
+		x := Remove(h, i).(int)
+		if x != i {
+			t.Errorf("Remove(%d) got %d; want %d", i, x, i)
+		}
+		h.verify(t, 0)
+	}
+}
+
+func TestRemove1(t *testing.T) {
+	h := new(myHeap)
+	for i := 0; i < 10; i++ {
+		h.Push(i)
+	}
+	h.verify(t, 0)
+
+	for i := 0; h.Len() > 0; i++ {
+		x := Remove(h, 0).(int)
+		if x != i {
+			t.Errorf("Remove(0) got %d; want %d", x, i)
+		}
+		h.verify(t, 0)
+	}
+}
+
+func TestRemove2(t *testing.T) {
+	N := 10
+
+	h := new(myHeap)
+	for i := 0; i < N; i++ {
+		h.Push(i)
+	}
+	h.verify(t, 0)
+
+	m := make(map[int]bool)
+	for h.Len() > 0 {
+		m[Remove(h, (h.Len()-1)/2).(int)] = true
+		h.verify(t, 0)
+	}
+
+	if len(m) != N {
+		t.Errorf("len(m) = %d; want %d", len(m), N)
+	}
+	for i := 0; i < len(m); i++ {
+		if !m[i] {
+			t.Errorf("m[%d] doesn't exist", i)
+		}
+	}
+}
+
+func BenchmarkDup(b *testing.B) {
+	const n = 10000
+	h := make(myHeap, n)
+	for i := 0; i < b.N; i++ {
+		for j := 0; j < n; j++ {
+			Push(&h, 0) // all elements are the same
+		}
+		for h.Len() > 0 {
+			Pop(&h)
+		}
+	}
+}
+
+func TestFix(t *testing.T) {
+	h := new(myHeap)
+	h.verify(t, 0)
+
+	for i := 200; i > 0; i -= 10 {
+		Push(h, i)
+	}
+	h.verify(t, 0)
+
+	if (*h)[0] != 10 {
+		t.Fatalf("Expected head to be 10, was %d", (*h)[0])
+	}
+	(*h)[0] = 210
+	Fix(h, 0)
+	h.verify(t, 0)
+
+	for i := 100; i > 0; i-- {
+		elem := rand.Intn(h.Len())
+		if i&1 == 0 {
+			(*h)[elem] *= 2
+		} else {
+			(*h)[elem] /= 2
+		}
+		Fix(h, elem)
+		h.verify(t, 0)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/container/list/list.go b/third_party/gofrontend/libgo/go/container/list/list.go
new file mode 100644
index 0000000..0256768
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/container/list/list.go
@@ -0,0 +1,216 @@
+// 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 list implements a doubly linked list.
+//
+// To iterate over a list (where l is a *List):
+//	for e := l.Front(); e != nil; e = e.Next() {
+//		// do something with e.Value
+//	}
+//
+package list
+
+// Element is an element of a linked list.
+type Element struct {
+	// Next and previous pointers in the doubly-linked list of elements.
+	// To simplify the implementation, internally a list l is implemented
+	// as a ring, such that &l.root is both the next element of the last
+	// list element (l.Back()) and the previous element of the first list
+	// element (l.Front()).
+	next, prev *Element
+
+	// The list to which this element belongs.
+	list *List
+
+	// The value stored with this element.
+	Value interface{}
+}
+
+// Next returns the next list element or nil.
+func (e *Element) Next() *Element {
+	if p := e.next; e.list != nil && p != &e.list.root {
+		return p
+	}
+	return nil
+}
+
+// Prev returns the previous list element or nil.
+func (e *Element) Prev() *Element {
+	if p := e.prev; e.list != nil && p != &e.list.root {
+		return p
+	}
+	return nil
+}
+
+// List represents a doubly linked list.
+// The zero value for List is an empty list ready to use.
+type List struct {
+	root Element // sentinel list element, only &root, root.prev, and root.next are used
+	len  int     // current list length excluding (this) sentinel element
+}
+
+// Init initializes or clears list l.
+func (l *List) Init() *List {
+	l.root.next = &l.root
+	l.root.prev = &l.root
+	l.len = 0
+	return l
+}
+
+// New returns an initialized list.
+func New() *List { return new(List).Init() }
+
+// Len returns the number of elements of list l.
+// The complexity is O(1).
+func (l *List) Len() int { return l.len }
+
+// Front returns the first element of list l or nil.
+func (l *List) Front() *Element {
+	if l.len == 0 {
+		return nil
+	}
+	return l.root.next
+}
+
+// Back returns the last element of list l or nil.
+func (l *List) Back() *Element {
+	if l.len == 0 {
+		return nil
+	}
+	return l.root.prev
+}
+
+// lazyInit lazily initializes a zero List value.
+func (l *List) lazyInit() {
+	if l.root.next == nil {
+		l.Init()
+	}
+}
+
+// insert inserts e after at, increments l.len, and returns e.
+func (l *List) insert(e, at *Element) *Element {
+	n := at.next
+	at.next = e
+	e.prev = at
+	e.next = n
+	n.prev = e
+	e.list = l
+	l.len++
+	return e
+}
+
+// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
+func (l *List) insertValue(v interface{}, at *Element) *Element {
+	return l.insert(&Element{Value: v}, at)
+}
+
+// remove removes e from its list, decrements l.len, and returns e.
+func (l *List) remove(e *Element) *Element {
+	e.prev.next = e.next
+	e.next.prev = e.prev
+	e.next = nil // avoid memory leaks
+	e.prev = nil // avoid memory leaks
+	e.list = nil
+	l.len--
+	return e
+}
+
+// Remove removes e from l if e is an element of list l.
+// It returns the element value e.Value.
+func (l *List) Remove(e *Element) interface{} {
+	if e.list == l {
+		// if e.list == l, l must have been initialized when e was inserted
+		// in l or l == nil (e is a zero Element) and l.remove will crash
+		l.remove(e)
+	}
+	return e.Value
+}
+
+// PushFront inserts a new element e with value v at the front of list l and returns e.
+func (l *List) PushFront(v interface{}) *Element {
+	l.lazyInit()
+	return l.insertValue(v, &l.root)
+}
+
+// PushBack inserts a new element e with value v at the back of list l and returns e.
+func (l *List) PushBack(v interface{}) *Element {
+	l.lazyInit()
+	return l.insertValue(v, l.root.prev)
+}
+
+// InsertBefore inserts a new element e with value v immediately before mark and returns e.
+// If mark is not an element of l, the list is not modified.
+func (l *List) InsertBefore(v interface{}, mark *Element) *Element {
+	if mark.list != l {
+		return nil
+	}
+	// see comment in List.Remove about initialization of l
+	return l.insertValue(v, mark.prev)
+}
+
+// InsertAfter inserts a new element e with value v immediately after mark and returns e.
+// If mark is not an element of l, the list is not modified.
+func (l *List) InsertAfter(v interface{}, mark *Element) *Element {
+	if mark.list != l {
+		return nil
+	}
+	// see comment in List.Remove about initialization of l
+	return l.insertValue(v, mark)
+}
+
+// MoveToFront moves element e to the front of list l.
+// If e is not an element of l, the list is not modified.
+func (l *List) MoveToFront(e *Element) {
+	if e.list != l || l.root.next == e {
+		return
+	}
+	// see comment in List.Remove about initialization of l
+	l.insert(l.remove(e), &l.root)
+}
+
+// MoveToBack moves element e to the back of list l.
+// If e is not an element of l, the list is not modified.
+func (l *List) MoveToBack(e *Element) {
+	if e.list != l || l.root.prev == e {
+		return
+	}
+	// see comment in List.Remove about initialization of l
+	l.insert(l.remove(e), l.root.prev)
+}
+
+// MoveBefore moves element e to its new position before mark.
+// If e or mark is not an element of l, or e == mark, the list is not modified.
+func (l *List) MoveBefore(e, mark *Element) {
+	if e.list != l || e == mark || mark.list != l {
+		return
+	}
+	l.insert(l.remove(e), mark.prev)
+}
+
+// MoveAfter moves element e to its new position after mark.
+// If e or mark is not an element of l, or e == mark, the list is not modified.
+func (l *List) MoveAfter(e, mark *Element) {
+	if e.list != l || e == mark || mark.list != l {
+		return
+	}
+	l.insert(l.remove(e), mark)
+}
+
+// PushBackList inserts a copy of an other list at the back of list l.
+// The lists l and other may be the same.
+func (l *List) PushBackList(other *List) {
+	l.lazyInit()
+	for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
+		l.insertValue(e.Value, l.root.prev)
+	}
+}
+
+// PushFrontList inserts a copy of an other list at the front of list l.
+// The lists l and other may be the same.
+func (l *List) PushFrontList(other *List) {
+	l.lazyInit()
+	for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
+		l.insertValue(e.Value, &l.root)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/container/list/list_test.go b/third_party/gofrontend/libgo/go/container/list/list_test.go
new file mode 100644
index 0000000..4d8bfc2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/container/list/list_test.go
@@ -0,0 +1,343 @@
+// 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 list
+
+import "testing"
+
+func checkListLen(t *testing.T, l *List, len int) bool {
+	if n := l.Len(); n != len {
+		t.Errorf("l.Len() = %d, want %d", n, len)
+		return false
+	}
+	return true
+}
+
+func checkListPointers(t *testing.T, l *List, es []*Element) {
+	root := &l.root
+
+	if !checkListLen(t, l, len(es)) {
+		return
+	}
+
+	// zero length lists must be the zero value or properly initialized (sentinel circle)
+	if len(es) == 0 {
+		if l.root.next != nil && l.root.next != root || l.root.prev != nil && l.root.prev != root {
+			t.Errorf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p", l.root.next, l.root.prev, root)
+		}
+		return
+	}
+	// len(es) > 0
+
+	// check internal and external prev/next connections
+	for i, e := range es {
+		prev := root
+		Prev := (*Element)(nil)
+		if i > 0 {
+			prev = es[i-1]
+			Prev = prev
+		}
+		if p := e.prev; p != prev {
+			t.Errorf("elt[%d](%p).prev = %p, want %p", i, e, p, prev)
+		}
+		if p := e.Prev(); p != Prev {
+			t.Errorf("elt[%d](%p).Prev() = %p, want %p", i, e, p, Prev)
+		}
+
+		next := root
+		Next := (*Element)(nil)
+		if i < len(es)-1 {
+			next = es[i+1]
+			Next = next
+		}
+		if n := e.next; n != next {
+			t.Errorf("elt[%d](%p).next = %p, want %p", i, e, n, next)
+		}
+		if n := e.Next(); n != Next {
+			t.Errorf("elt[%d](%p).Next() = %p, want %p", i, e, n, Next)
+		}
+	}
+}
+
+func TestList(t *testing.T) {
+	l := New()
+	checkListPointers(t, l, []*Element{})
+
+	// Single element list
+	e := l.PushFront("a")
+	checkListPointers(t, l, []*Element{e})
+	l.MoveToFront(e)
+	checkListPointers(t, l, []*Element{e})
+	l.MoveToBack(e)
+	checkListPointers(t, l, []*Element{e})
+	l.Remove(e)
+	checkListPointers(t, l, []*Element{})
+
+	// Bigger list
+	e2 := l.PushFront(2)
+	e1 := l.PushFront(1)
+	e3 := l.PushBack(3)
+	e4 := l.PushBack("banana")
+	checkListPointers(t, l, []*Element{e1, e2, e3, e4})
+
+	l.Remove(e2)
+	checkListPointers(t, l, []*Element{e1, e3, e4})
+
+	l.MoveToFront(e3) // move from middle
+	checkListPointers(t, l, []*Element{e3, e1, e4})
+
+	l.MoveToFront(e1)
+	l.MoveToBack(e3) // move from middle
+	checkListPointers(t, l, []*Element{e1, e4, e3})
+
+	l.MoveToFront(e3) // move from back
+	checkListPointers(t, l, []*Element{e3, e1, e4})
+	l.MoveToFront(e3) // should be no-op
+	checkListPointers(t, l, []*Element{e3, e1, e4})
+
+	l.MoveToBack(e3) // move from front
+	checkListPointers(t, l, []*Element{e1, e4, e3})
+	l.MoveToBack(e3) // should be no-op
+	checkListPointers(t, l, []*Element{e1, e4, e3})
+
+	e2 = l.InsertBefore(2, e1) // insert before front
+	checkListPointers(t, l, []*Element{e2, e1, e4, e3})
+	l.Remove(e2)
+	e2 = l.InsertBefore(2, e4) // insert before middle
+	checkListPointers(t, l, []*Element{e1, e2, e4, e3})
+	l.Remove(e2)
+	e2 = l.InsertBefore(2, e3) // insert before back
+	checkListPointers(t, l, []*Element{e1, e4, e2, e3})
+	l.Remove(e2)
+
+	e2 = l.InsertAfter(2, e1) // insert after front
+	checkListPointers(t, l, []*Element{e1, e2, e4, e3})
+	l.Remove(e2)
+	e2 = l.InsertAfter(2, e4) // insert after middle
+	checkListPointers(t, l, []*Element{e1, e4, e2, e3})
+	l.Remove(e2)
+	e2 = l.InsertAfter(2, e3) // insert after back
+	checkListPointers(t, l, []*Element{e1, e4, e3, e2})
+	l.Remove(e2)
+
+	// Check standard iteration.
+	sum := 0
+	for e := l.Front(); e != nil; e = e.Next() {
+		if i, ok := e.Value.(int); ok {
+			sum += i
+		}
+	}
+	if sum != 4 {
+		t.Errorf("sum over l = %d, want 4", sum)
+	}
+
+	// Clear all elements by iterating
+	var next *Element
+	for e := l.Front(); e != nil; e = next {
+		next = e.Next()
+		l.Remove(e)
+	}
+	checkListPointers(t, l, []*Element{})
+}
+
+func checkList(t *testing.T, l *List, es []interface{}) {
+	if !checkListLen(t, l, len(es)) {
+		return
+	}
+
+	i := 0
+	for e := l.Front(); e != nil; e = e.Next() {
+		le := e.Value.(int)
+		if le != es[i] {
+			t.Errorf("elt[%d].Value = %v, want %v", i, le, es[i])
+		}
+		i++
+	}
+}
+
+func TestExtending(t *testing.T) {
+	l1 := New()
+	l2 := New()
+
+	l1.PushBack(1)
+	l1.PushBack(2)
+	l1.PushBack(3)
+
+	l2.PushBack(4)
+	l2.PushBack(5)
+
+	l3 := New()
+	l3.PushBackList(l1)
+	checkList(t, l3, []interface{}{1, 2, 3})
+	l3.PushBackList(l2)
+	checkList(t, l3, []interface{}{1, 2, 3, 4, 5})
+
+	l3 = New()
+	l3.PushFrontList(l2)
+	checkList(t, l3, []interface{}{4, 5})
+	l3.PushFrontList(l1)
+	checkList(t, l3, []interface{}{1, 2, 3, 4, 5})
+
+	checkList(t, l1, []interface{}{1, 2, 3})
+	checkList(t, l2, []interface{}{4, 5})
+
+	l3 = New()
+	l3.PushBackList(l1)
+	checkList(t, l3, []interface{}{1, 2, 3})
+	l3.PushBackList(l3)
+	checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3})
+
+	l3 = New()
+	l3.PushFrontList(l1)
+	checkList(t, l3, []interface{}{1, 2, 3})
+	l3.PushFrontList(l3)
+	checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3})
+
+	l3 = New()
+	l1.PushBackList(l3)
+	checkList(t, l1, []interface{}{1, 2, 3})
+	l1.PushFrontList(l3)
+	checkList(t, l1, []interface{}{1, 2, 3})
+}
+
+func TestRemove(t *testing.T) {
+	l := New()
+	e1 := l.PushBack(1)
+	e2 := l.PushBack(2)
+	checkListPointers(t, l, []*Element{e1, e2})
+	e := l.Front()
+	l.Remove(e)
+	checkListPointers(t, l, []*Element{e2})
+	l.Remove(e)
+	checkListPointers(t, l, []*Element{e2})
+}
+
+func TestIssue4103(t *testing.T) {
+	l1 := New()
+	l1.PushBack(1)
+	l1.PushBack(2)
+
+	l2 := New()
+	l2.PushBack(3)
+	l2.PushBack(4)
+
+	e := l1.Front()
+	l2.Remove(e) // l2 should not change because e is not an element of l2
+	if n := l2.Len(); n != 2 {
+		t.Errorf("l2.Len() = %d, want 2", n)
+	}
+
+	l1.InsertBefore(8, e)
+	if n := l1.Len(); n != 3 {
+		t.Errorf("l1.Len() = %d, want 3", n)
+	}
+}
+
+func TestIssue6349(t *testing.T) {
+	l := New()
+	l.PushBack(1)
+	l.PushBack(2)
+
+	e := l.Front()
+	l.Remove(e)
+	if e.Value != 1 {
+		t.Errorf("e.value = %d, want 1", e.Value)
+	}
+	if e.Next() != nil {
+		t.Errorf("e.Next() != nil")
+	}
+	if e.Prev() != nil {
+		t.Errorf("e.Prev() != nil")
+	}
+}
+
+func TestMove(t *testing.T) {
+	l := New()
+	e1 := l.PushBack(1)
+	e2 := l.PushBack(2)
+	e3 := l.PushBack(3)
+	e4 := l.PushBack(4)
+
+	l.MoveAfter(e3, e3)
+	checkListPointers(t, l, []*Element{e1, e2, e3, e4})
+	l.MoveBefore(e2, e2)
+	checkListPointers(t, l, []*Element{e1, e2, e3, e4})
+
+	l.MoveAfter(e3, e2)
+	checkListPointers(t, l, []*Element{e1, e2, e3, e4})
+	l.MoveBefore(e2, e3)
+	checkListPointers(t, l, []*Element{e1, e2, e3, e4})
+
+	l.MoveBefore(e2, e4)
+	checkListPointers(t, l, []*Element{e1, e3, e2, e4})
+	e1, e2, e3, e4 = e1, e3, e2, e4
+
+	l.MoveBefore(e4, e1)
+	checkListPointers(t, l, []*Element{e4, e1, e2, e3})
+	e1, e2, e3, e4 = e4, e1, e2, e3
+
+	l.MoveAfter(e4, e1)
+	checkListPointers(t, l, []*Element{e1, e4, e2, e3})
+	e1, e2, e3, e4 = e1, e4, e2, e3
+
+	l.MoveAfter(e2, e3)
+	checkListPointers(t, l, []*Element{e1, e3, e2, e4})
+	e1, e2, e3, e4 = e1, e3, e2, e4
+}
+
+// Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized List
+func TestZeroList(t *testing.T) {
+	var l1 = new(List)
+	l1.PushFront(1)
+	checkList(t, l1, []interface{}{1})
+
+	var l2 = new(List)
+	l2.PushBack(1)
+	checkList(t, l2, []interface{}{1})
+
+	var l3 = new(List)
+	l3.PushFrontList(l1)
+	checkList(t, l3, []interface{}{1})
+
+	var l4 = new(List)
+	l4.PushBackList(l2)
+	checkList(t, l4, []interface{}{1})
+}
+
+// Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l.
+func TestInsertBeforeUnknownMark(t *testing.T) {
+	var l List
+	l.PushBack(1)
+	l.PushBack(2)
+	l.PushBack(3)
+	l.InsertBefore(1, new(Element))
+	checkList(t, &l, []interface{}{1, 2, 3})
+}
+
+// Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l.
+func TestInsertAfterUnknownMark(t *testing.T) {
+	var l List
+	l.PushBack(1)
+	l.PushBack(2)
+	l.PushBack(3)
+	l.InsertAfter(1, new(Element))
+	checkList(t, &l, []interface{}{1, 2, 3})
+}
+
+// Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l.
+func TestMoveUnkownMark(t *testing.T) {
+	var l1 List
+	e1 := l1.PushBack(1)
+
+	var l2 List
+	e2 := l2.PushBack(2)
+
+	l1.MoveAfter(e1, e2)
+	checkList(t, &l1, []interface{}{1})
+	checkList(t, &l2, []interface{}{2})
+
+	l1.MoveBefore(e1, e2)
+	checkList(t, &l1, []interface{}{1})
+	checkList(t, &l2, []interface{}{2})
+}
diff --git a/third_party/gofrontend/libgo/go/container/ring/ring.go b/third_party/gofrontend/libgo/go/container/ring/ring.go
new file mode 100644
index 0000000..6d3b3e5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/container/ring/ring.go
@@ -0,0 +1,141 @@
+// 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 ring implements operations on circular lists.
+package ring
+
+// A Ring is an element of a circular list, or ring.
+// Rings do not have a beginning or end; a pointer to any ring element
+// serves as reference to the entire ring. Empty rings are represented
+// as nil Ring pointers. The zero value for a Ring is a one-element
+// ring with a nil Value.
+//
+type Ring struct {
+	next, prev *Ring
+	Value      interface{} // for use by client; untouched by this library
+}
+
+func (r *Ring) init() *Ring {
+	r.next = r
+	r.prev = r
+	return r
+}
+
+// Next returns the next ring element. r must not be empty.
+func (r *Ring) Next() *Ring {
+	if r.next == nil {
+		return r.init()
+	}
+	return r.next
+}
+
+// Prev returns the previous ring element. r must not be empty.
+func (r *Ring) Prev() *Ring {
+	if r.next == nil {
+		return r.init()
+	}
+	return r.prev
+}
+
+// Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0)
+// in the ring and returns that ring element. r must not be empty.
+//
+func (r *Ring) Move(n int) *Ring {
+	if r.next == nil {
+		return r.init()
+	}
+	switch {
+	case n < 0:
+		for ; n < 0; n++ {
+			r = r.prev
+		}
+	case n > 0:
+		for ; n > 0; n-- {
+			r = r.next
+		}
+	}
+	return r
+}
+
+// New creates a ring of n elements.
+func New(n int) *Ring {
+	if n <= 0 {
+		return nil
+	}
+	r := new(Ring)
+	p := r
+	for i := 1; i < n; i++ {
+		p.next = &Ring{prev: p}
+		p = p.next
+	}
+	p.next = r
+	r.prev = p
+	return r
+}
+
+// Link connects ring r with ring s such that r.Next()
+// becomes s and returns the original value for r.Next().
+// r must not be empty.
+//
+// If r and s point to the same ring, linking
+// them removes the elements between r and s from the ring.
+// The removed elements form a subring and the result is a
+// reference to that subring (if no elements were removed,
+// the result is still the original value for r.Next(),
+// and not nil).
+//
+// If r and s point to different rings, linking
+// them creates a single ring with the elements of s inserted
+// after r. The result points to the element following the
+// last element of s after insertion.
+//
+func (r *Ring) Link(s *Ring) *Ring {
+	n := r.Next()
+	if s != nil {
+		p := s.Prev()
+		// Note: Cannot use multiple assignment because
+		// evaluation order of LHS is not specified.
+		r.next = s
+		s.prev = r
+		n.prev = p
+		p.next = n
+	}
+	return n
+}
+
+// Unlink removes n % r.Len() elements from the ring r, starting
+// at r.Next(). If n % r.Len() == 0, r remains unchanged.
+// The result is the removed subring. r must not be empty.
+//
+func (r *Ring) Unlink(n int) *Ring {
+	if n <= 0 {
+		return nil
+	}
+	return r.Link(r.Move(n + 1))
+}
+
+// Len computes the number of elements in ring r.
+// It executes in time proportional to the number of elements.
+//
+func (r *Ring) Len() int {
+	n := 0
+	if r != nil {
+		n = 1
+		for p := r.Next(); p != r; p = p.next {
+			n++
+		}
+	}
+	return n
+}
+
+// Do calls function f on each element of the ring, in forward order.
+// The behavior of Do is undefined if f changes *r.
+func (r *Ring) Do(f func(interface{})) {
+	if r != nil {
+		f(r.Value)
+		for p := r.Next(); p != r; p = p.next {
+			f(p.Value)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/container/ring/ring_test.go b/third_party/gofrontend/libgo/go/container/ring/ring_test.go
new file mode 100644
index 0000000..552f0e2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/container/ring/ring_test.go
@@ -0,0 +1,228 @@
+// 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 ring
+
+import (
+	"fmt"
+	"testing"
+)
+
+// For debugging - keep around.
+func dump(r *Ring) {
+	if r == nil {
+		fmt.Println("empty")
+		return
+	}
+	i, n := 0, r.Len()
+	for p := r; i < n; p = p.next {
+		fmt.Printf("%4d: %p = {<- %p | %p ->}\n", i, p, p.prev, p.next)
+		i++
+	}
+	fmt.Println()
+}
+
+func verify(t *testing.T, r *Ring, N int, sum int) {
+	// Len
+	n := r.Len()
+	if n != N {
+		t.Errorf("r.Len() == %d; expected %d", n, N)
+	}
+
+	// iteration
+	n = 0
+	s := 0
+	r.Do(func(p interface{}) {
+		n++
+		if p != nil {
+			s += p.(int)
+		}
+	})
+	if n != N {
+		t.Errorf("number of forward iterations == %d; expected %d", n, N)
+	}
+	if sum >= 0 && s != sum {
+		t.Errorf("forward ring sum = %d; expected %d", s, sum)
+	}
+
+	if r == nil {
+		return
+	}
+
+	// connections
+	if r.next != nil {
+		var p *Ring // previous element
+		for q := r; p == nil || q != r; q = q.next {
+			if p != nil && p != q.prev {
+				t.Errorf("prev = %p, expected q.prev = %p\n", p, q.prev)
+			}
+			p = q
+		}
+		if p != r.prev {
+			t.Errorf("prev = %p, expected r.prev = %p\n", p, r.prev)
+		}
+	}
+
+	// Next, Prev
+	if r.Next() != r.next {
+		t.Errorf("r.Next() != r.next")
+	}
+	if r.Prev() != r.prev {
+		t.Errorf("r.Prev() != r.prev")
+	}
+
+	// Move
+	if r.Move(0) != r {
+		t.Errorf("r.Move(0) != r")
+	}
+	if r.Move(N) != r {
+		t.Errorf("r.Move(%d) != r", N)
+	}
+	if r.Move(-N) != r {
+		t.Errorf("r.Move(%d) != r", -N)
+	}
+	for i := 0; i < 10; i++ {
+		ni := N + i
+		mi := ni % N
+		if r.Move(ni) != r.Move(mi) {
+			t.Errorf("r.Move(%d) != r.Move(%d)", ni, mi)
+		}
+		if r.Move(-ni) != r.Move(-mi) {
+			t.Errorf("r.Move(%d) != r.Move(%d)", -ni, -mi)
+		}
+	}
+}
+
+func TestCornerCases(t *testing.T) {
+	var (
+		r0 *Ring
+		r1 Ring
+	)
+	// Basics
+	verify(t, r0, 0, 0)
+	verify(t, &r1, 1, 0)
+	// Insert
+	r1.Link(r0)
+	verify(t, r0, 0, 0)
+	verify(t, &r1, 1, 0)
+	// Insert
+	r1.Link(r0)
+	verify(t, r0, 0, 0)
+	verify(t, &r1, 1, 0)
+	// Unlink
+	r1.Unlink(0)
+	verify(t, &r1, 1, 0)
+}
+
+func makeN(n int) *Ring {
+	r := New(n)
+	for i := 1; i <= n; i++ {
+		r.Value = i
+		r = r.Next()
+	}
+	return r
+}
+
+func sumN(n int) int { return (n*n + n) / 2 }
+
+func TestNew(t *testing.T) {
+	for i := 0; i < 10; i++ {
+		r := New(i)
+		verify(t, r, i, -1)
+	}
+	for i := 0; i < 10; i++ {
+		r := makeN(i)
+		verify(t, r, i, sumN(i))
+	}
+}
+
+func TestLink1(t *testing.T) {
+	r1a := makeN(1)
+	var r1b Ring
+	r2a := r1a.Link(&r1b)
+	verify(t, r2a, 2, 1)
+	if r2a != r1a {
+		t.Errorf("a) 2-element link failed")
+	}
+
+	r2b := r2a.Link(r2a.Next())
+	verify(t, r2b, 2, 1)
+	if r2b != r2a.Next() {
+		t.Errorf("b) 2-element link failed")
+	}
+
+	r1c := r2b.Link(r2b)
+	verify(t, r1c, 1, 1)
+	verify(t, r2b, 1, 0)
+}
+
+func TestLink2(t *testing.T) {
+	var r0 *Ring
+	r1a := &Ring{Value: 42}
+	r1b := &Ring{Value: 77}
+	r10 := makeN(10)
+
+	r1a.Link(r0)
+	verify(t, r1a, 1, 42)
+
+	r1a.Link(r1b)
+	verify(t, r1a, 2, 42+77)
+
+	r10.Link(r0)
+	verify(t, r10, 10, sumN(10))
+
+	r10.Link(r1a)
+	verify(t, r10, 12, sumN(10)+42+77)
+}
+
+func TestLink3(t *testing.T) {
+	var r Ring
+	n := 1
+	for i := 1; i < 100; i++ {
+		n += i
+		verify(t, r.Link(New(i)), n, -1)
+	}
+}
+
+func TestUnlink(t *testing.T) {
+	r10 := makeN(10)
+	s10 := r10.Move(6)
+
+	sum10 := sumN(10)
+
+	verify(t, r10, 10, sum10)
+	verify(t, s10, 10, sum10)
+
+	r0 := r10.Unlink(0)
+	verify(t, r0, 0, 0)
+
+	r1 := r10.Unlink(1)
+	verify(t, r1, 1, 2)
+	verify(t, r10, 9, sum10-2)
+
+	r9 := r10.Unlink(9)
+	verify(t, r9, 9, sum10-2)
+	verify(t, r10, 9, sum10-2)
+}
+
+func TestLinkUnlink(t *testing.T) {
+	for i := 1; i < 4; i++ {
+		ri := New(i)
+		for j := 0; j < i; j++ {
+			rj := ri.Unlink(j)
+			verify(t, rj, j, -1)
+			verify(t, ri, i-j, -1)
+			ri.Link(rj)
+			verify(t, ri, i, -1)
+		}
+	}
+}
+
+// Test that calling Move() on an empty Ring initializes it.
+func TestMoveEmptyRing(t *testing.T) {
+	var r Ring
+
+	r.Move(1)
+	verify(t, &r, 1, 0)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/aes/aes_test.go b/third_party/gofrontend/libgo/go/crypto/aes/aes_test.go
new file mode 100644
index 0000000..3631809
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/aes/aes_test.go
@@ -0,0 +1,421 @@
+// 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 aes
+
+import (
+	"testing"
+)
+
+// See const.go for overview of math here.
+
+// Test that powx is initialized correctly.
+// (Can adapt this code to generate it too.)
+func TestPowx(t *testing.T) {
+	p := 1
+	for i := 0; i < len(powx); i++ {
+		if powx[i] != byte(p) {
+			t.Errorf("powx[%d] = %#x, want %#x", i, powx[i], p)
+		}
+		p <<= 1
+		if p&0x100 != 0 {
+			p ^= poly
+		}
+	}
+}
+
+// Multiply b and c as GF(2) polynomials modulo poly
+func mul(b, c uint32) uint32 {
+	i := b
+	j := c
+	s := uint32(0)
+	for k := uint32(1); k < 0x100 && j != 0; k <<= 1 {
+		// Invariant: k == 1<<n, i == b * xⁿ
+
+		if j&k != 0 {
+			// s += i in GF(2); xor in binary
+			s ^= i
+			j ^= k // turn off bit to end loop early
+		}
+
+		// i *= x in GF(2) modulo the polynomial
+		i <<= 1
+		if i&0x100 != 0 {
+			i ^= poly
+		}
+	}
+	return s
+}
+
+// Test all mul inputs against bit-by-bit n² algorithm.
+func TestMul(t *testing.T) {
+	for i := uint32(0); i < 256; i++ {
+		for j := uint32(0); j < 256; j++ {
+			// Multiply i, j bit by bit.
+			s := uint8(0)
+			for k := uint(0); k < 8; k++ {
+				for l := uint(0); l < 8; l++ {
+					if i&(1<<k) != 0 && j&(1<<l) != 0 {
+						s ^= powx[k+l]
+					}
+				}
+			}
+			if x := mul(i, j); x != uint32(s) {
+				t.Fatalf("mul(%#x, %#x) = %#x, want %#x", i, j, x, s)
+			}
+		}
+	}
+}
+
+// Check that S-boxes are inverses of each other.
+// They have more structure that we could test,
+// but if this sanity check passes, we'll assume
+// the cut and paste from the FIPS PDF worked.
+func TestSboxes(t *testing.T) {
+	for i := 0; i < 256; i++ {
+		if j := sbox0[sbox1[i]]; j != byte(i) {
+			t.Errorf("sbox0[sbox1[%#x]] = %#x", i, j)
+		}
+		if j := sbox1[sbox0[i]]; j != byte(i) {
+			t.Errorf("sbox1[sbox0[%#x]] = %#x", i, j)
+		}
+	}
+}
+
+// Test that encryption tables are correct.
+// (Can adapt this code to generate them too.)
+func TestTe(t *testing.T) {
+	for i := 0; i < 256; i++ {
+		s := uint32(sbox0[i])
+		s2 := mul(s, 2)
+		s3 := mul(s, 3)
+		w := s2<<24 | s<<16 | s<<8 | s3
+		te := [][256]uint32{te0, te1, te2, te3}
+		for j := 0; j < 4; j++ {
+			if x := te[j][i]; x != w {
+				t.Fatalf("te[%d][%d] = %#x, want %#x", j, i, x, w)
+			}
+			w = w<<24 | w>>8
+		}
+	}
+}
+
+// Test that decryption tables are correct.
+// (Can adapt this code to generate them too.)
+func TestTd(t *testing.T) {
+	for i := 0; i < 256; i++ {
+		s := uint32(sbox1[i])
+		s9 := mul(s, 0x9)
+		sb := mul(s, 0xb)
+		sd := mul(s, 0xd)
+		se := mul(s, 0xe)
+		w := se<<24 | s9<<16 | sd<<8 | sb
+		td := [][256]uint32{td0, td1, td2, td3}
+		for j := 0; j < 4; j++ {
+			if x := td[j][i]; x != w {
+				t.Fatalf("td[%d][%d] = %#x, want %#x", j, i, x, w)
+			}
+			w = w<<24 | w>>8
+		}
+	}
+}
+
+// Test vectors are from FIPS 197:
+//	http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+
+// Appendix A of FIPS 197: Key expansion examples
+type KeyTest struct {
+	key []byte
+	enc []uint32
+	dec []uint32 // decryption expansion; not in FIPS 197, computed from C implementation.
+}
+
+var keyTests = []KeyTest{
+	{
+		// A.1.  Expansion of a 128-bit Cipher Key
+		[]byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c},
+		[]uint32{
+			0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c,
+			0xa0fafe17, 0x88542cb1, 0x23a33939, 0x2a6c7605,
+			0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f,
+			0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b,
+			0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00,
+			0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc,
+			0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd,
+			0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f,
+			0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f,
+			0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e,
+			0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6,
+		},
+		[]uint32{
+			0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6,
+			0xc7b5a63, 0x1319eafe, 0xb0398890, 0x664cfbb4,
+			0xdf7d925a, 0x1f62b09d, 0xa320626e, 0xd6757324,
+			0x12c07647, 0xc01f22c7, 0xbc42d2f3, 0x7555114a,
+			0x6efcd876, 0xd2df5480, 0x7c5df034, 0xc917c3b9,
+			0x6ea30afc, 0xbc238cf6, 0xae82a4b4, 0xb54a338d,
+			0x90884413, 0xd280860a, 0x12a12842, 0x1bc89739,
+			0x7c1f13f7, 0x4208c219, 0xc021ae48, 0x969bf7b,
+			0xcc7505eb, 0x3e17d1ee, 0x82296c51, 0xc9481133,
+			0x2b3708a7, 0xf262d405, 0xbc3ebdbf, 0x4b617d62,
+			0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x9cf4f3c,
+		},
+	},
+	{
+		// A.2.  Expansion of a 192-bit Cipher Key
+		[]byte{
+			0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+			0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
+		},
+		[]uint32{
+			0x8e73b0f7, 0xda0e6452, 0xc810f32b, 0x809079e5,
+			0x62f8ead2, 0x522c6b7b, 0xfe0c91f7, 0x2402f5a5,
+			0xec12068e, 0x6c827f6b, 0x0e7a95b9, 0x5c56fec2,
+			0x4db7b4bd, 0x69b54118, 0x85a74796, 0xe92538fd,
+			0xe75fad44, 0xbb095386, 0x485af057, 0x21efb14f,
+			0xa448f6d9, 0x4d6dce24, 0xaa326360, 0x113b30e6,
+			0xa25e7ed5, 0x83b1cf9a, 0x27f93943, 0x6a94f767,
+			0xc0a69407, 0xd19da4e1, 0xec1786eb, 0x6fa64971,
+			0x485f7032, 0x22cb8755, 0xe26d1352, 0x33f0b7b3,
+			0x40beeb28, 0x2f18a259, 0x6747d26b, 0x458c553e,
+			0xa7e1466c, 0x9411f1df, 0x821f750a, 0xad07d753,
+			0xca400538, 0x8fcc5006, 0x282d166a, 0xbc3ce7b5,
+			0xe98ba06f, 0x448c773c, 0x8ecc7204, 0x01002202,
+		},
+		nil,
+	},
+	{
+		// A.3.  Expansion of a 256-bit Cipher Key
+		[]byte{
+			0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+			0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4,
+		},
+		[]uint32{
+			0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781,
+			0x1f352c07, 0x3b6108d7, 0x2d9810a3, 0x0914dff4,
+			0x9ba35411, 0x8e6925af, 0xa51a8b5f, 0x2067fcde,
+			0xa8b09c1a, 0x93d194cd, 0xbe49846e, 0xb75d5b9a,
+			0xd59aecb8, 0x5bf3c917, 0xfee94248, 0xde8ebe96,
+			0xb5a9328a, 0x2678a647, 0x98312229, 0x2f6c79b3,
+			0x812c81ad, 0xdadf48ba, 0x24360af2, 0xfab8b464,
+			0x98c5bfc9, 0xbebd198e, 0x268c3ba7, 0x09e04214,
+			0x68007bac, 0xb2df3316, 0x96e939e4, 0x6c518d80,
+			0xc814e204, 0x76a9fb8a, 0x5025c02d, 0x59c58239,
+			0xde136967, 0x6ccc5a71, 0xfa256395, 0x9674ee15,
+			0x5886ca5d, 0x2e2f31d7, 0x7e0af1fa, 0x27cf73c3,
+			0x749c47ab, 0x18501dda, 0xe2757e4f, 0x7401905a,
+			0xcafaaae3, 0xe4d59b34, 0x9adf6ace, 0xbd10190d,
+			0xfe4890d1, 0xe6188d0b, 0x046df344, 0x706c631e,
+		},
+		nil,
+	},
+}
+
+// Test key expansion against FIPS 197 examples.
+func TestExpandKey(t *testing.T) {
+L:
+	for i, tt := range keyTests {
+		enc := make([]uint32, len(tt.enc))
+		var dec []uint32
+		if tt.dec != nil {
+			dec = make([]uint32, len(tt.dec))
+		}
+		// This test could only test Go version of expandKey because asm
+		// version might use different memory layout for expanded keys
+		// This is OK because we don't expose expanded keys to the outside
+		expandKeyGo(tt.key, enc, dec)
+		for j, v := range enc {
+			if v != tt.enc[j] {
+				t.Errorf("key %d: enc[%d] = %#x, want %#x", i, j, v, tt.enc[j])
+				continue L
+			}
+		}
+		if dec != nil {
+			for j, v := range dec {
+				if v != tt.dec[j] {
+					t.Errorf("key %d: dec[%d] = %#x, want %#x", i, j, v, tt.dec[j])
+					continue L
+				}
+			}
+		}
+	}
+}
+
+// Appendix B, C of FIPS 197: Cipher examples, Example vectors.
+type CryptTest struct {
+	key []byte
+	in  []byte
+	out []byte
+}
+
+var encryptTests = []CryptTest{
+	{
+		// Appendix B.
+		[]byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c},
+		[]byte{0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34},
+		[]byte{0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32},
+	},
+	{
+		// Appendix C.1.  AES-128
+		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
+		[]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
+		[]byte{0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a},
+	},
+	{
+		// Appendix C.2.  AES-192
+		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+		},
+		[]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
+		[]byte{0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91},
+	},
+	{
+		// Appendix C.3.  AES-256
+		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+		},
+		[]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
+		[]byte{0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89},
+	},
+}
+
+// Test encryptBlock against FIPS 197 examples.
+func TestEncryptBlock(t *testing.T) {
+	for i, tt := range encryptTests {
+		n := len(tt.key) + 28
+		enc := make([]uint32, n)
+		dec := make([]uint32, n)
+		expandKey(tt.key, enc, dec)
+		out := make([]byte, len(tt.in))
+		encryptBlock(enc, out, tt.in)
+		for j, v := range out {
+			if v != tt.out[j] {
+				t.Errorf("encryptBlock %d: out[%d] = %#x, want %#x", i, j, v, tt.out[j])
+				break
+			}
+		}
+	}
+}
+
+// Test decryptBlock against FIPS 197 examples.
+func TestDecryptBlock(t *testing.T) {
+	for i, tt := range encryptTests {
+		n := len(tt.key) + 28
+		enc := make([]uint32, n)
+		dec := make([]uint32, n)
+		expandKey(tt.key, enc, dec)
+		plain := make([]byte, len(tt.in))
+		decryptBlock(dec, plain, tt.out)
+		for j, v := range plain {
+			if v != tt.in[j] {
+				t.Errorf("decryptBlock %d: plain[%d] = %#x, want %#x", i, j, v, tt.in[j])
+				break
+			}
+		}
+	}
+}
+
+// Test Cipher Encrypt method against FIPS 197 examples.
+func TestCipherEncrypt(t *testing.T) {
+	for i, tt := range encryptTests {
+		c, err := NewCipher(tt.key)
+		if err != nil {
+			t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
+			continue
+		}
+		out := make([]byte, len(tt.in))
+		c.Encrypt(out, tt.in)
+		for j, v := range out {
+			if v != tt.out[j] {
+				t.Errorf("Cipher.Encrypt %d: out[%d] = %#x, want %#x", i, j, v, tt.out[j])
+				break
+			}
+		}
+	}
+}
+
+// Test Cipher Decrypt against FIPS 197 examples.
+func TestCipherDecrypt(t *testing.T) {
+	for i, tt := range encryptTests {
+		c, err := NewCipher(tt.key)
+		if err != nil {
+			t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
+			continue
+		}
+		plain := make([]byte, len(tt.in))
+		c.Decrypt(plain, tt.out)
+		for j, v := range plain {
+			if v != tt.in[j] {
+				t.Errorf("decryptBlock %d: plain[%d] = %#x, want %#x", i, j, v, tt.in[j])
+				break
+			}
+		}
+	}
+}
+
+// Test short input/output.
+// Assembly used to not notice.
+// See issue 7928.
+func TestShortBlocks(t *testing.T) {
+	bytes := func(n int) []byte { return make([]byte, n) }
+
+	c, _ := NewCipher(bytes(16))
+
+	mustPanic(t, "crypto/aes: input not full block", func() { c.Encrypt(bytes(1), bytes(1)) })
+	mustPanic(t, "crypto/aes: input not full block", func() { c.Decrypt(bytes(1), bytes(1)) })
+	mustPanic(t, "crypto/aes: input not full block", func() { c.Encrypt(bytes(100), bytes(1)) })
+	mustPanic(t, "crypto/aes: input not full block", func() { c.Decrypt(bytes(100), bytes(1)) })
+	mustPanic(t, "crypto/aes: output not full block", func() { c.Encrypt(bytes(1), bytes(100)) })
+	mustPanic(t, "crypto/aes: output not full block", func() { c.Decrypt(bytes(1), bytes(100)) })
+}
+
+func mustPanic(t *testing.T, msg string, f func()) {
+	defer func() {
+		err := recover()
+		if err == nil {
+			t.Errorf("function did not panic, wanted %q", msg)
+		} else if err != msg {
+			t.Errorf("got panic %v, wanted %q", err, msg)
+		}
+	}()
+	f()
+}
+
+func BenchmarkEncrypt(b *testing.B) {
+	tt := encryptTests[0]
+	c, err := NewCipher(tt.key)
+	if err != nil {
+		b.Fatal("NewCipher:", err)
+	}
+	out := make([]byte, len(tt.in))
+	b.SetBytes(int64(len(out)))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		c.Encrypt(out, tt.in)
+	}
+}
+
+func BenchmarkDecrypt(b *testing.B) {
+	tt := encryptTests[0]
+	c, err := NewCipher(tt.key)
+	if err != nil {
+		b.Fatal("NewCipher:", err)
+	}
+	out := make([]byte, len(tt.out))
+	b.SetBytes(int64(len(out)))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		c.Decrypt(out, tt.out)
+	}
+}
+
+func BenchmarkExpand(b *testing.B) {
+	tt := encryptTests[0]
+	n := len(tt.key) + 28
+	c := &aesCipher{make([]uint32, n), make([]uint32, n)}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		expandKey(tt.key, c.enc, c.dec)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/aes/block.go b/third_party/gofrontend/libgo/go/crypto/aes/block.go
new file mode 100644
index 0000000..57a7e9e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/aes/block.go
@@ -0,0 +1,176 @@
+// 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.
+
+// This Go implementation is derived in part from the reference
+// ANSI C implementation, which carries the following notice:
+//
+//	rijndael-alg-fst.c
+//
+//	@version 3.0 (December 2000)
+//
+//	Optimised ANSI C code for the Rijndael cipher (now AES)
+//
+//	@author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+//	@author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+//	@author Paulo Barreto <paulo.barreto@terra.com.br>
+//
+//	This code is hereby placed in the public domain.
+//
+//	THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+//	OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//	ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+//	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+//	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+//	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+//	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+//	WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+//	OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+//	EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// See FIPS 197 for specification, and see Daemen and Rijmen's Rijndael submission
+// for implementation details.
+//	http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+//	http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf
+
+package aes
+
+// Encrypt one block from src into dst, using the expanded key xk.
+func encryptBlockGo(xk []uint32, dst, src []byte) {
+	var s0, s1, s2, s3, t0, t1, t2, t3 uint32
+
+	s0 = uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	s1 = uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+	s2 = uint32(src[8])<<24 | uint32(src[9])<<16 | uint32(src[10])<<8 | uint32(src[11])
+	s3 = uint32(src[12])<<24 | uint32(src[13])<<16 | uint32(src[14])<<8 | uint32(src[15])
+
+	// First round just XORs input with key.
+	s0 ^= xk[0]
+	s1 ^= xk[1]
+	s2 ^= xk[2]
+	s3 ^= xk[3]
+
+	// Middle rounds shuffle using tables.
+	// Number of rounds is set by length of expanded key.
+	nr := len(xk)/4 - 2 // - 2: one above, one more below
+	k := 4
+	for r := 0; r < nr; r++ {
+		t0 = xk[k+0] ^ te0[uint8(s0>>24)] ^ te1[uint8(s1>>16)] ^ te2[uint8(s2>>8)] ^ te3[uint8(s3)]
+		t1 = xk[k+1] ^ te0[uint8(s1>>24)] ^ te1[uint8(s2>>16)] ^ te2[uint8(s3>>8)] ^ te3[uint8(s0)]
+		t2 = xk[k+2] ^ te0[uint8(s2>>24)] ^ te1[uint8(s3>>16)] ^ te2[uint8(s0>>8)] ^ te3[uint8(s1)]
+		t3 = xk[k+3] ^ te0[uint8(s3>>24)] ^ te1[uint8(s0>>16)] ^ te2[uint8(s1>>8)] ^ te3[uint8(s2)]
+		k += 4
+		s0, s1, s2, s3 = t0, t1, t2, t3
+	}
+
+	// Last round uses s-box directly and XORs to produce output.
+	s0 = uint32(sbox0[t0>>24])<<24 | uint32(sbox0[t1>>16&0xff])<<16 | uint32(sbox0[t2>>8&0xff])<<8 | uint32(sbox0[t3&0xff])
+	s1 = uint32(sbox0[t1>>24])<<24 | uint32(sbox0[t2>>16&0xff])<<16 | uint32(sbox0[t3>>8&0xff])<<8 | uint32(sbox0[t0&0xff])
+	s2 = uint32(sbox0[t2>>24])<<24 | uint32(sbox0[t3>>16&0xff])<<16 | uint32(sbox0[t0>>8&0xff])<<8 | uint32(sbox0[t1&0xff])
+	s3 = uint32(sbox0[t3>>24])<<24 | uint32(sbox0[t0>>16&0xff])<<16 | uint32(sbox0[t1>>8&0xff])<<8 | uint32(sbox0[t2&0xff])
+
+	s0 ^= xk[k+0]
+	s1 ^= xk[k+1]
+	s2 ^= xk[k+2]
+	s3 ^= xk[k+3]
+
+	dst[0], dst[1], dst[2], dst[3] = byte(s0>>24), byte(s0>>16), byte(s0>>8), byte(s0)
+	dst[4], dst[5], dst[6], dst[7] = byte(s1>>24), byte(s1>>16), byte(s1>>8), byte(s1)
+	dst[8], dst[9], dst[10], dst[11] = byte(s2>>24), byte(s2>>16), byte(s2>>8), byte(s2)
+	dst[12], dst[13], dst[14], dst[15] = byte(s3>>24), byte(s3>>16), byte(s3>>8), byte(s3)
+}
+
+// Decrypt one block from src into dst, using the expanded key xk.
+func decryptBlockGo(xk []uint32, dst, src []byte) {
+	var s0, s1, s2, s3, t0, t1, t2, t3 uint32
+
+	s0 = uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	s1 = uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+	s2 = uint32(src[8])<<24 | uint32(src[9])<<16 | uint32(src[10])<<8 | uint32(src[11])
+	s3 = uint32(src[12])<<24 | uint32(src[13])<<16 | uint32(src[14])<<8 | uint32(src[15])
+
+	// First round just XORs input with key.
+	s0 ^= xk[0]
+	s1 ^= xk[1]
+	s2 ^= xk[2]
+	s3 ^= xk[3]
+
+	// Middle rounds shuffle using tables.
+	// Number of rounds is set by length of expanded key.
+	nr := len(xk)/4 - 2 // - 2: one above, one more below
+	k := 4
+	for r := 0; r < nr; r++ {
+		t0 = xk[k+0] ^ td0[uint8(s0>>24)] ^ td1[uint8(s3>>16)] ^ td2[uint8(s2>>8)] ^ td3[uint8(s1)]
+		t1 = xk[k+1] ^ td0[uint8(s1>>24)] ^ td1[uint8(s0>>16)] ^ td2[uint8(s3>>8)] ^ td3[uint8(s2)]
+		t2 = xk[k+2] ^ td0[uint8(s2>>24)] ^ td1[uint8(s1>>16)] ^ td2[uint8(s0>>8)] ^ td3[uint8(s3)]
+		t3 = xk[k+3] ^ td0[uint8(s3>>24)] ^ td1[uint8(s2>>16)] ^ td2[uint8(s1>>8)] ^ td3[uint8(s0)]
+		k += 4
+		s0, s1, s2, s3 = t0, t1, t2, t3
+	}
+
+	// Last round uses s-box directly and XORs to produce output.
+	s0 = uint32(sbox1[t0>>24])<<24 | uint32(sbox1[t3>>16&0xff])<<16 | uint32(sbox1[t2>>8&0xff])<<8 | uint32(sbox1[t1&0xff])
+	s1 = uint32(sbox1[t1>>24])<<24 | uint32(sbox1[t0>>16&0xff])<<16 | uint32(sbox1[t3>>8&0xff])<<8 | uint32(sbox1[t2&0xff])
+	s2 = uint32(sbox1[t2>>24])<<24 | uint32(sbox1[t1>>16&0xff])<<16 | uint32(sbox1[t0>>8&0xff])<<8 | uint32(sbox1[t3&0xff])
+	s3 = uint32(sbox1[t3>>24])<<24 | uint32(sbox1[t2>>16&0xff])<<16 | uint32(sbox1[t1>>8&0xff])<<8 | uint32(sbox1[t0&0xff])
+
+	s0 ^= xk[k+0]
+	s1 ^= xk[k+1]
+	s2 ^= xk[k+2]
+	s3 ^= xk[k+3]
+
+	dst[0], dst[1], dst[2], dst[3] = byte(s0>>24), byte(s0>>16), byte(s0>>8), byte(s0)
+	dst[4], dst[5], dst[6], dst[7] = byte(s1>>24), byte(s1>>16), byte(s1>>8), byte(s1)
+	dst[8], dst[9], dst[10], dst[11] = byte(s2>>24), byte(s2>>16), byte(s2>>8), byte(s2)
+	dst[12], dst[13], dst[14], dst[15] = byte(s3>>24), byte(s3>>16), byte(s3>>8), byte(s3)
+}
+
+// Apply sbox0 to each byte in w.
+func subw(w uint32) uint32 {
+	return uint32(sbox0[w>>24])<<24 |
+		uint32(sbox0[w>>16&0xff])<<16 |
+		uint32(sbox0[w>>8&0xff])<<8 |
+		uint32(sbox0[w&0xff])
+}
+
+// Rotate
+func rotw(w uint32) uint32 { return w<<8 | w>>24 }
+
+// Key expansion algorithm.  See FIPS-197, Figure 11.
+// Their rcon[i] is our powx[i-1] << 24.
+func expandKeyGo(key []byte, enc, dec []uint32) {
+	// Encryption key setup.
+	var i int
+	nk := len(key) / 4
+	for i = 0; i < nk; i++ {
+		enc[i] = uint32(key[4*i])<<24 | uint32(key[4*i+1])<<16 | uint32(key[4*i+2])<<8 | uint32(key[4*i+3])
+	}
+	for ; i < len(enc); i++ {
+		t := enc[i-1]
+		if i%nk == 0 {
+			t = subw(rotw(t)) ^ (uint32(powx[i/nk-1]) << 24)
+		} else if nk > 6 && i%nk == 4 {
+			t = subw(t)
+		}
+		enc[i] = enc[i-nk] ^ t
+	}
+
+	// Derive decryption key from encryption key.
+	// Reverse the 4-word round key sets from enc to produce dec.
+	// All sets but the first and last get the MixColumn transform applied.
+	if dec == nil {
+		return
+	}
+	n := len(enc)
+	for i := 0; i < n; i += 4 {
+		ei := n - i - 4
+		for j := 0; j < 4; j++ {
+			x := enc[ei+j]
+			if i > 0 && i+4 < n {
+				x = td0[sbox0[x>>24]] ^ td1[sbox0[x>>16&0xff]] ^ td2[sbox0[x>>8&0xff]] ^ td3[sbox0[x&0xff]]
+			}
+			dec[i+j] = x
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/aes/cipher.go b/third_party/gofrontend/libgo/go/crypto/aes/cipher.go
new file mode 100644
index 0000000..2c6bb0a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/aes/cipher.go
@@ -0,0 +1,66 @@
+// 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 aes
+
+import (
+	"crypto/cipher"
+	"strconv"
+)
+
+// The AES block size in bytes.
+const BlockSize = 16
+
+// A cipher is an instance of AES encryption using a particular key.
+type aesCipher struct {
+	enc []uint32
+	dec []uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+	return "crypto/aes: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a new cipher.Block.
+// The key argument should be the AES key,
+// either 16, 24, or 32 bytes to select
+// AES-128, AES-192, or AES-256.
+func NewCipher(key []byte) (cipher.Block, error) {
+	k := len(key)
+	switch k {
+	default:
+		return nil, KeySizeError(k)
+	case 16, 24, 32:
+		break
+	}
+
+	n := k + 28
+	c := &aesCipher{make([]uint32, n), make([]uint32, n)}
+	expandKey(key, c.enc, c.dec)
+	return c, nil
+}
+
+func (c *aesCipher) BlockSize() int { return BlockSize }
+
+func (c *aesCipher) Encrypt(dst, src []byte) {
+	if len(src) < BlockSize {
+		panic("crypto/aes: input not full block")
+	}
+	if len(dst) < BlockSize {
+		panic("crypto/aes: output not full block")
+	}
+	encryptBlock(c.enc, dst, src)
+}
+
+func (c *aesCipher) Decrypt(dst, src []byte) {
+	if len(src) < BlockSize {
+		panic("crypto/aes: input not full block")
+	}
+	if len(dst) < BlockSize {
+		panic("crypto/aes: output not full block")
+	}
+	decryptBlock(c.dec, dst, src)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/aes/cipher_asm.go b/third_party/gofrontend/libgo/go/crypto/aes/cipher_asm.go
new file mode 100644
index 0000000..964eaaa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/aes/cipher_asm.go
@@ -0,0 +1,48 @@
+// 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.
+
+// +build amd64
+
+package aes
+
+// defined in asm_$GOARCH.s
+func hasAsm() bool
+func encryptBlockAsm(nr int, xk *uint32, dst, src *byte)
+func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
+func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32)
+
+var useAsm = hasAsm()
+
+func encryptBlock(xk []uint32, dst, src []byte) {
+	if useAsm {
+		encryptBlockAsm(len(xk)/4-1, &xk[0], &dst[0], &src[0])
+	} else {
+		encryptBlockGo(xk, dst, src)
+	}
+}
+
+func decryptBlock(xk []uint32, dst, src []byte) {
+	if useAsm {
+		decryptBlockAsm(len(xk)/4-1, &xk[0], &dst[0], &src[0])
+	} else {
+		decryptBlockGo(xk, dst, src)
+	}
+}
+
+func expandKey(key []byte, enc, dec []uint32) {
+	if useAsm {
+		rounds := 10
+		switch len(key) {
+		case 128 / 8:
+			rounds = 10
+		case 192 / 8:
+			rounds = 12
+		case 256 / 8:
+			rounds = 14
+		}
+		expandKeyAsm(rounds, &key[0], &enc[0], &dec[0])
+	} else {
+		expandKeyGo(key, enc, dec)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/aes/cipher_generic.go b/third_party/gofrontend/libgo/go/crypto/aes/cipher_generic.go
new file mode 100644
index 0000000..1714e0f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/aes/cipher_generic.go
@@ -0,0 +1,19 @@
+// 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.
+
+// +build !amd64
+
+package aes
+
+func encryptBlock(xk []uint32, dst, src []byte) {
+	encryptBlockGo(xk, dst, src)
+}
+
+func decryptBlock(xk []uint32, dst, src []byte) {
+	decryptBlockGo(xk, dst, src)
+}
+
+func expandKey(key []byte, enc, dec []uint32) {
+	expandKeyGo(key, enc, dec)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/aes/const.go b/third_party/gofrontend/libgo/go/crypto/aes/const.go
new file mode 100644
index 0000000..aee73a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/aes/const.go
@@ -0,0 +1,358 @@
+// 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 aes implements AES encryption (formerly Rijndael), as defined in
+// U.S. Federal Information Processing Standards Publication 197.
+package aes
+
+// This file contains AES constants - 8720 bytes of initialized data.
+
+// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+
+// AES is based on the mathematical behavior of binary polynomials
+// (polynomials over GF(2)) modulo the irreducible polynomial x⁸ + x⁴ + x³ + x + 1.
+// Addition of these binary polynomials corresponds to binary xor.
+// Reducing mod poly corresponds to binary xor with poly every
+// time a 0x100 bit appears.
+const poly = 1<<8 | 1<<4 | 1<<3 | 1<<1 | 1<<0 // x⁸ + x⁴ + x³ + x + 1
+
+// Powers of x mod poly in GF(2).
+var powx = [16]byte{
+	0x01,
+	0x02,
+	0x04,
+	0x08,
+	0x10,
+	0x20,
+	0x40,
+	0x80,
+	0x1b,
+	0x36,
+	0x6c,
+	0xd8,
+	0xab,
+	0x4d,
+	0x9a,
+	0x2f,
+}
+
+// FIPS-197 Figure 7. S-box substitution values in hexadecimal format.
+var sbox0 = [256]byte{
+	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
+}
+
+// FIPS-197 Figure 14.  Inverse S-box substitution values in hexadecimal format.
+var sbox1 = [256]byte{
+	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+	0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+	0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+	0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+	0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+	0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+	0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+	0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+	0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+	0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
+}
+
+// Lookup tables for encryption.
+// These can be recomputed by adapting the tests in aes_test.go.
+
+var te0 = [256]uint32{
+	0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554,
+	0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a,
+	0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b,
+	0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b,
+	0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f,
+	0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,
+	0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5,
+	0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
+	0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,
+	0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497,
+	0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed,
+	0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,
+	0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594,
+	0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3,
+	0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504,
+	0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
+	0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739,
+	0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
+	0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883,
+	0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76,
+	0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4,
+	0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b,
+	0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0,
+	0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
+	0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651,
+	0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85,
+	0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,
+	0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9,
+	0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7,
+	0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,
+	0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8,
+	0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a,
+}
+var te1 = [256]uint32{
+	0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5,
+	0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676,
+	0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0,
+	0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0,
+	0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc,
+	0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515,
+	0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a,
+	0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575,
+	0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0,
+	0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484,
+	0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b,
+	0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf,
+	0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585,
+	0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8,
+	0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5,
+	0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2,
+	0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717,
+	0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373,
+	0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888,
+	0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb,
+	0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c,
+	0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979,
+	0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9,
+	0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808,
+	0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6,
+	0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a,
+	0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e,
+	0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e,
+	0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494,
+	0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf,
+	0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868,
+	0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616,
+}
+var te2 = [256]uint32{
+	0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5,
+	0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76,
+	0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0,
+	0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0,
+	0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc,
+	0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15,
+	0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a,
+	0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75,
+	0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0,
+	0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384,
+	0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b,
+	0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf,
+	0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185,
+	0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8,
+	0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5,
+	0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2,
+	0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17,
+	0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673,
+	0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88,
+	0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb,
+	0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c,
+	0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279,
+	0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9,
+	0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008,
+	0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6,
+	0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a,
+	0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e,
+	0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e,
+	0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394,
+	0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df,
+	0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068,
+	0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16,
+}
+var te3 = [256]uint32{
+	0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491,
+	0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec,
+	0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb,
+	0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b,
+	0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83,
+	0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a,
+	0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f,
+	0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea,
+	0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b,
+	0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713,
+	0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6,
+	0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85,
+	0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411,
+	0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b,
+	0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1,
+	0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf,
+	0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e,
+	0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6,
+	0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b,
+	0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad,
+	0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8,
+	0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2,
+	0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049,
+	0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810,
+	0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197,
+	0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f,
+	0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c,
+	0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927,
+	0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733,
+	0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5,
+	0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0,
+	0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c,
+}
+
+// Lookup tables for decryption.
+// These can be recomputed by adapting the tests in aes_test.go.
+
+var td0 = [256]uint32{
+	0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393,
+	0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f,
+	0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6,
+	0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844,
+	0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4,
+	0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94,
+	0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a,
+	0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
+	0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a,
+	0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051,
+	0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff,
+	0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb,
+	0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e,
+	0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a,
+	0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16,
+	0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
+	0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34,
+	0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120,
+	0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0,
+	0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef,
+	0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4,
+	0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5,
+	0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b,
+	0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
+	0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0,
+	0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f,
+	0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f,
+	0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713,
+	0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c,
+	0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86,
+	0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541,
+	0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742,
+}
+var td1 = [256]uint32{
+	0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303,
+	0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3,
+	0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9,
+	0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8,
+	0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a,
+	0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b,
+	0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab,
+	0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682,
+	0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe,
+	0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10,
+	0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015,
+	0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee,
+	0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72,
+	0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e,
+	0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a,
+	0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9,
+	0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e,
+	0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611,
+	0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3,
+	0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390,
+	0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf,
+	0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af,
+	0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb,
+	0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8,
+	0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266,
+	0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6,
+	0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551,
+	0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647,
+	0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1,
+	0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db,
+	0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95,
+	0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857,
+}
+var td2 = [256]uint32{
+	0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3,
+	0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562,
+	0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3,
+	0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9,
+	0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce,
+	0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908,
+	0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655,
+	0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16,
+	0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6,
+	0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e,
+	0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050,
+	0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8,
+	0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a,
+	0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436,
+	0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12,
+	0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e,
+	0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb,
+	0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6,
+	0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1,
+	0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233,
+	0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad,
+	0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3,
+	0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b,
+	0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15,
+	0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2,
+	0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791,
+	0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665,
+	0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6,
+	0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47,
+	0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844,
+	0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d,
+	0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8,
+}
+var td3 = [256]uint32{
+	0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b,
+	0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5,
+	0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b,
+	0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e,
+	0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d,
+	0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9,
+	0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66,
+	0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced,
+	0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4,
+	0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd,
+	0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60,
+	0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79,
+	0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c,
+	0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24,
+	0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c,
+	0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814,
+	0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b,
+	0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084,
+	0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077,
+	0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22,
+	0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f,
+	0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582,
+	0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb,
+	0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef,
+	0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035,
+	0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17,
+	0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46,
+	0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d,
+	0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a,
+	0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678,
+	0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff,
+	0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0,
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/benchmark_test.go b/third_party/gofrontend/libgo/go/crypto/cipher/benchmark_test.go
new file mode 100644
index 0000000..027b248
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/benchmark_test.go
@@ -0,0 +1,139 @@
+// Copyright 2013 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 cipher_test
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"testing"
+)
+
+func BenchmarkAESGCMSeal1K(b *testing.B) {
+	buf := make([]byte, 1024)
+	b.SetBytes(int64(len(buf)))
+
+	var key [16]byte
+	var nonce [12]byte
+	aes, _ := aes.NewCipher(key[:])
+	aesgcm, _ := cipher.NewGCM(aes)
+	var out []byte
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		out = aesgcm.Seal(out[:0], nonce[:], buf, nonce[:])
+	}
+}
+
+func BenchmarkAESGCMOpen1K(b *testing.B) {
+	buf := make([]byte, 1024)
+	b.SetBytes(int64(len(buf)))
+
+	var key [16]byte
+	var nonce [12]byte
+	aes, _ := aes.NewCipher(key[:])
+	aesgcm, _ := cipher.NewGCM(aes)
+	var out []byte
+	out = aesgcm.Seal(out[:0], nonce[:], buf, nonce[:])
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, err := aesgcm.Open(buf[:0], nonce[:], out, nonce[:])
+		if err != nil {
+			b.Errorf("Open: %v", err)
+		}
+	}
+}
+
+// If we test exactly 1K blocks, we would generate exact multiples of
+// the cipher's block size, and the cipher stream fragments would
+// always be wordsize aligned, whereas non-aligned is a more typical
+// use-case.
+const almost1K = 1024 - 5
+
+func BenchmarkAESCFBEncrypt1K(b *testing.B) {
+	buf := make([]byte, almost1K)
+	b.SetBytes(int64(len(buf)))
+
+	var key [16]byte
+	var iv [16]byte
+	aes, _ := aes.NewCipher(key[:])
+	ctr := cipher.NewCFBEncrypter(aes, iv[:])
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		ctr.XORKeyStream(buf, buf)
+	}
+}
+
+func BenchmarkAESCFBDecrypt1K(b *testing.B) {
+	buf := make([]byte, almost1K)
+	b.SetBytes(int64(len(buf)))
+
+	var key [16]byte
+	var iv [16]byte
+	aes, _ := aes.NewCipher(key[:])
+	ctr := cipher.NewCFBDecrypter(aes, iv[:])
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		ctr.XORKeyStream(buf, buf)
+	}
+}
+
+func BenchmarkAESOFB1K(b *testing.B) {
+	buf := make([]byte, almost1K)
+	b.SetBytes(int64(len(buf)))
+
+	var key [16]byte
+	var iv [16]byte
+	aes, _ := aes.NewCipher(key[:])
+	ctr := cipher.NewOFB(aes, iv[:])
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		ctr.XORKeyStream(buf, buf)
+	}
+}
+
+func BenchmarkAESCTR1K(b *testing.B) {
+	buf := make([]byte, almost1K)
+	b.SetBytes(int64(len(buf)))
+
+	var key [16]byte
+	var iv [16]byte
+	aes, _ := aes.NewCipher(key[:])
+	ctr := cipher.NewCTR(aes, iv[:])
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		ctr.XORKeyStream(buf, buf)
+	}
+}
+
+func BenchmarkAESCBCEncrypt1K(b *testing.B) {
+	buf := make([]byte, 1024)
+	b.SetBytes(int64(len(buf)))
+
+	var key [16]byte
+	var iv [16]byte
+	aes, _ := aes.NewCipher(key[:])
+	cbc := cipher.NewCBCEncrypter(aes, iv[:])
+	for i := 0; i < b.N; i++ {
+		cbc.CryptBlocks(buf, buf)
+	}
+}
+
+func BenchmarkAESCBCDecrypt1K(b *testing.B) {
+	buf := make([]byte, 1024)
+	b.SetBytes(int64(len(buf)))
+
+	var key [16]byte
+	var iv [16]byte
+	aes, _ := aes.NewCipher(key[:])
+	cbc := cipher.NewCBCDecrypter(aes, iv[:])
+	for i := 0; i < b.N; i++ {
+		cbc.CryptBlocks(buf, buf)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/cbc.go b/third_party/gofrontend/libgo/go/crypto/cipher/cbc.go
new file mode 100644
index 0000000..241e122
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/cbc.go
@@ -0,0 +1,133 @@
+// 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.
+
+// Cipher block chaining (CBC) mode.
+
+// CBC provides confidentiality by xoring (chaining) each plaintext block
+// with the previous ciphertext block before applying the block cipher.
+
+// See NIST SP 800-38A, pp 10-11
+
+package cipher
+
+type cbc struct {
+	b         Block
+	blockSize int
+	iv        []byte
+	tmp       []byte
+}
+
+func newCBC(b Block, iv []byte) *cbc {
+	return &cbc{
+		b:         b,
+		blockSize: b.BlockSize(),
+		iv:        dup(iv),
+		tmp:       make([]byte, b.BlockSize()),
+	}
+}
+
+type cbcEncrypter cbc
+
+// NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining
+// mode, using the given Block. The length of iv must be the same as the
+// Block's block size.
+func NewCBCEncrypter(b Block, iv []byte) BlockMode {
+	if len(iv) != b.BlockSize() {
+		panic("cipher.NewCBCEncrypter: IV length must equal block size")
+	}
+	return (*cbcEncrypter)(newCBC(b, iv))
+}
+
+func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
+
+func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
+	if len(src)%x.blockSize != 0 {
+		panic("crypto/cipher: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+
+	iv := x.iv
+
+	for len(src) > 0 {
+		// Write the xor to dst, then encrypt in place.
+		xorBytes(dst[:x.blockSize], src[:x.blockSize], iv)
+		x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize])
+
+		// Move to the next block with this block as the next iv.
+		iv = dst[:x.blockSize]
+		src = src[x.blockSize:]
+		dst = dst[x.blockSize:]
+	}
+
+	// Save the iv for the next CryptBlocks call.
+	copy(x.iv, iv)
+}
+
+func (x *cbcEncrypter) SetIV(iv []byte) {
+	if len(iv) != len(x.iv) {
+		panic("cipher: incorrect length IV")
+	}
+	copy(x.iv, iv)
+}
+
+type cbcDecrypter cbc
+
+// NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining
+// mode, using the given Block. The length of iv must be the same as the
+// Block's block size and must match the iv used to encrypt the data.
+func NewCBCDecrypter(b Block, iv []byte) BlockMode {
+	if len(iv) != b.BlockSize() {
+		panic("cipher.NewCBCDecrypter: IV length must equal block size")
+	}
+	return (*cbcDecrypter)(newCBC(b, iv))
+}
+
+func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
+
+func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
+	if len(src)%x.blockSize != 0 {
+		panic("crypto/cipher: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	if len(src) == 0 {
+		return
+	}
+
+	// For each block, we need to xor the decrypted data with the previous block's ciphertext (the iv).
+	// To avoid making a copy each time, we loop over the blocks BACKWARDS.
+	end := len(src)
+	start := end - x.blockSize
+	prev := start - x.blockSize
+
+	// Copy the last block of ciphertext in preparation as the new iv.
+	copy(x.tmp, src[start:end])
+
+	// Loop over all but the first block.
+	for start > 0 {
+		x.b.Decrypt(dst[start:end], src[start:end])
+		xorBytes(dst[start:end], dst[start:end], src[prev:start])
+
+		end = start
+		start = prev
+		prev -= x.blockSize
+	}
+
+	// The first block is special because it uses the saved iv.
+	x.b.Decrypt(dst[start:end], src[start:end])
+	xorBytes(dst[start:end], dst[start:end], x.iv)
+
+	// Set the new iv to the first block we copied earlier.
+	x.iv, x.tmp = x.tmp, x.iv
+}
+
+func (x *cbcDecrypter) SetIV(iv []byte) {
+	if len(iv) != len(x.iv) {
+		panic("cipher: incorrect length IV")
+	}
+	copy(x.iv, iv)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/cbc_aes_test.go b/third_party/gofrontend/libgo/go/crypto/cipher/cbc_aes_test.go
new file mode 100644
index 0000000..bf9e7ad
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/cbc_aes_test.go
@@ -0,0 +1,104 @@
+// 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.
+
+// CBC AES test vectors.
+
+// See U.S. National Institute of Standards and Technology (NIST)
+// Special Publication 800-38A, ``Recommendation for Block Cipher
+// Modes of Operation,'' 2001 Edition, pp. 24-29.
+
+package cipher_test
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"testing"
+)
+
+var cbcAESTests = []struct {
+	name string
+	key  []byte
+	iv   []byte
+	in   []byte
+	out  []byte
+}{
+	// NIST SP 800-38A pp 27-29
+	{
+		"CBC-AES128",
+		commonKey128,
+		commonIV,
+		commonInput,
+		[]byte{
+			0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
+			0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
+			0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
+			0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7,
+		},
+	},
+	{
+		"CBC-AES192",
+		commonKey192,
+		commonIV,
+		commonInput,
+		[]byte{
+			0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
+			0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
+			0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0, 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
+			0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81, 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd,
+		},
+	},
+	{
+		"CBC-AES256",
+		commonKey256,
+		commonIV,
+		commonInput,
+		[]byte{
+			0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+			0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+			0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+			0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b,
+		},
+	},
+}
+
+func TestCBCEncrypterAES(t *testing.T) {
+	for _, test := range cbcAESTests {
+		c, err := aes.NewCipher(test.key)
+		if err != nil {
+			t.Errorf("%s: NewCipher(%d bytes) = %s", test.name, len(test.key), err)
+			continue
+		}
+
+		encrypter := cipher.NewCBCEncrypter(c, test.iv)
+
+		data := make([]byte, len(test.in))
+		copy(data, test.in)
+
+		encrypter.CryptBlocks(data, data)
+		if !bytes.Equal(test.out, data) {
+			t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test.name, data, test.out)
+		}
+	}
+}
+
+func TestCBCDecrypterAES(t *testing.T) {
+	for _, test := range cbcAESTests {
+		c, err := aes.NewCipher(test.key)
+		if err != nil {
+			t.Errorf("%s: NewCipher(%d bytes) = %s", test.name, len(test.key), err)
+			continue
+		}
+
+		decrypter := cipher.NewCBCDecrypter(c, test.iv)
+
+		data := make([]byte, len(test.out))
+		copy(data, test.out)
+
+		decrypter.CryptBlocks(data, data)
+		if !bytes.Equal(test.in, data) {
+			t.Errorf("%s: CBCDecrypter\nhave %x\nwant %x", test.name, data, test.in)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/cfb.go b/third_party/gofrontend/libgo/go/crypto/cipher/cfb.go
new file mode 100644
index 0000000..9b4eebf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/cfb.go
@@ -0,0 +1,72 @@
+// Copyright 2010 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.
+
+// CFB (Cipher Feedback) Mode.
+
+package cipher
+
+type cfb struct {
+	b       Block
+	next    []byte
+	out     []byte
+	outUsed int
+
+	decrypt bool
+}
+
+func (x *cfb) XORKeyStream(dst, src []byte) {
+	for len(src) > 0 {
+		if x.outUsed == len(x.out) {
+			x.b.Encrypt(x.out, x.next)
+			x.outUsed = 0
+		}
+
+		if x.decrypt {
+			// We can precompute a larger segment of the
+			// keystream on decryption. This will allow
+			// larger batches for xor, and we should be
+			// able to match CTR/OFB performance.
+			copy(x.next[x.outUsed:], src)
+		}
+		n := xorBytes(dst, src, x.out[x.outUsed:])
+		if !x.decrypt {
+			copy(x.next[x.outUsed:], dst)
+		}
+		dst = dst[n:]
+		src = src[n:]
+		x.outUsed += n
+	}
+}
+
+// NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode,
+// using the given Block. The iv must be the same length as the Block's block
+// size.
+func NewCFBEncrypter(block Block, iv []byte) Stream {
+	return newCFB(block, iv, false)
+}
+
+// NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode,
+// using the given Block. The iv must be the same length as the Block's block
+// size.
+func NewCFBDecrypter(block Block, iv []byte) Stream {
+	return newCFB(block, iv, true)
+}
+
+func newCFB(block Block, iv []byte, decrypt bool) Stream {
+	blockSize := block.BlockSize()
+	if len(iv) != blockSize {
+		// stack trace will indicate whether it was de or encryption
+		panic("cipher.newCFB: IV length must equal block size")
+	}
+	x := &cfb{
+		b:       block,
+		out:     make([]byte, blockSize),
+		next:    make([]byte, blockSize),
+		outUsed: blockSize,
+		decrypt: decrypt,
+	}
+	copy(x.next, iv)
+
+	return x
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/cfb_test.go b/third_party/gofrontend/libgo/go/crypto/cipher/cfb_test.go
new file mode 100644
index 0000000..ec708ab
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/cfb_test.go
@@ -0,0 +1,38 @@
+// Copyright 2010 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 cipher_test
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/rand"
+	"testing"
+)
+
+func TestCFB(t *testing.T) {
+	block, err := aes.NewCipher(commonKey128)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	plaintext := []byte("this is the plaintext. this is the plaintext.")
+	iv := make([]byte, block.BlockSize())
+	rand.Reader.Read(iv)
+	cfb := cipher.NewCFBEncrypter(block, iv)
+	ciphertext := make([]byte, len(plaintext))
+	copy(ciphertext, plaintext)
+	cfb.XORKeyStream(ciphertext, ciphertext)
+
+	cfbdec := cipher.NewCFBDecrypter(block, iv)
+	plaintextCopy := make([]byte, len(plaintext))
+	copy(plaintextCopy, ciphertext)
+	cfbdec.XORKeyStream(plaintextCopy, plaintextCopy)
+
+	if !bytes.Equal(plaintextCopy, plaintext) {
+		t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/cipher.go b/third_party/gofrontend/libgo/go/crypto/cipher/cipher.go
new file mode 100644
index 0000000..67afdb1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/cipher.go
@@ -0,0 +1,53 @@
+// Copyright 2010 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 cipher implements standard block cipher modes that can be wrapped
+// around low-level block cipher implementations.
+// See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
+// and NIST Special Publication 800-38A.
+package cipher
+
+// A Block represents an implementation of block cipher
+// using a given key.  It provides the capability to encrypt
+// or decrypt individual blocks.  The mode implementations
+// extend that capability to streams of blocks.
+type Block interface {
+	// BlockSize returns the cipher's block size.
+	BlockSize() int
+
+	// Encrypt encrypts the first block in src into dst.
+	// Dst and src may point at the same memory.
+	Encrypt(dst, src []byte)
+
+	// Decrypt decrypts the first block in src into dst.
+	// Dst and src may point at the same memory.
+	Decrypt(dst, src []byte)
+}
+
+// A Stream represents a stream cipher.
+type Stream interface {
+	// XORKeyStream XORs each byte in the given slice with a byte from the
+	// cipher's key stream. Dst and src may point to the same memory.
+	XORKeyStream(dst, src []byte)
+}
+
+// A BlockMode represents a block cipher running in a block-based mode (CBC,
+// ECB etc).
+type BlockMode interface {
+	// BlockSize returns the mode's block size.
+	BlockSize() int
+
+	// CryptBlocks encrypts or decrypts a number of blocks. The length of
+	// src must be a multiple of the block size. Dst and src may point to
+	// the same memory.
+	CryptBlocks(dst, src []byte)
+}
+
+// Utility routines
+
+func dup(p []byte) []byte {
+	q := make([]byte, len(p))
+	copy(q, p)
+	return q
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/cipher_test.go b/third_party/gofrontend/libgo/go/crypto/cipher/cipher_test.go
new file mode 100644
index 0000000..8da5bce
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/cipher_test.go
@@ -0,0 +1,36 @@
+// Copyright 2013 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 cipher_test
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"testing"
+)
+
+func TestCryptBlocks(t *testing.T) {
+	buf := make([]byte, 16)
+	block, _ := aes.NewCipher(buf)
+
+	mode := cipher.NewCBCDecrypter(block, buf)
+	mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) })
+	mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) })
+
+	mode = cipher.NewCBCEncrypter(block, buf)
+	mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) })
+	mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) })
+}
+
+func mustPanic(t *testing.T, msg string, f func()) {
+	defer func() {
+		err := recover()
+		if err == nil {
+			t.Errorf("function did not panic, wanted %q", msg)
+		} else if err != msg {
+			t.Errorf("got panic %v, wanted %q", err, msg)
+		}
+	}()
+	f()
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/common_test.go b/third_party/gofrontend/libgo/go/crypto/cipher/common_test.go
new file mode 100644
index 0000000..c75c919
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/common_test.go
@@ -0,0 +1,28 @@
+// 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 cipher_test
+
+// Common values for tests.
+
+var commonInput = []byte{
+	0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+	0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+	0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+	0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
+}
+
+var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
+
+var commonKey192 = []byte{
+	0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+	0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
+}
+
+var commonKey256 = []byte{
+	0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+	0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4,
+}
+
+var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/ctr.go b/third_party/gofrontend/libgo/go/crypto/cipher/ctr.go
new file mode 100644
index 0000000..70ac40f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/ctr.go
@@ -0,0 +1,76 @@
+// 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.
+
+// Counter (CTR) mode.
+
+// CTR converts a block cipher into a stream cipher by
+// repeatedly encrypting an incrementing counter and
+// xoring the resulting stream of data with the input.
+
+// See NIST SP 800-38A, pp 13-15
+
+package cipher
+
+type ctr struct {
+	b       Block
+	ctr     []byte
+	out     []byte
+	outUsed int
+}
+
+const streamBufferSize = 512
+
+// NewCTR returns a Stream which encrypts/decrypts using the given Block in
+// counter mode. The length of iv must be the same as the Block's block size.
+func NewCTR(block Block, iv []byte) Stream {
+	if len(iv) != block.BlockSize() {
+		panic("cipher.NewCTR: IV length must equal block size")
+	}
+	bufSize := streamBufferSize
+	if bufSize < block.BlockSize() {
+		bufSize = block.BlockSize()
+	}
+	return &ctr{
+		b:       block,
+		ctr:     dup(iv),
+		out:     make([]byte, 0, bufSize),
+		outUsed: 0,
+	}
+}
+
+func (x *ctr) refill() {
+	remain := len(x.out) - x.outUsed
+	if remain > x.outUsed {
+		return
+	}
+	copy(x.out, x.out[x.outUsed:])
+	x.out = x.out[:cap(x.out)]
+	bs := x.b.BlockSize()
+	for remain < len(x.out)-bs {
+		x.b.Encrypt(x.out[remain:], x.ctr)
+		remain += bs
+
+		// Increment counter
+		for i := len(x.ctr) - 1; i >= 0; i-- {
+			x.ctr[i]++
+			if x.ctr[i] != 0 {
+				break
+			}
+		}
+	}
+	x.out = x.out[:remain]
+	x.outUsed = 0
+}
+
+func (x *ctr) XORKeyStream(dst, src []byte) {
+	for len(src) > 0 {
+		if x.outUsed >= len(x.out)-x.b.BlockSize() {
+			x.refill()
+		}
+		n := xorBytes(dst, src, x.out[x.outUsed:])
+		dst = dst[n:]
+		src = src[n:]
+		x.outUsed += n
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/ctr_aes_test.go b/third_party/gofrontend/libgo/go/crypto/cipher/ctr_aes_test.go
new file mode 100644
index 0000000..d019ae0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/ctr_aes_test.go
@@ -0,0 +1,102 @@
+// 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.
+
+// CTR AES test vectors.
+
+// See U.S. National Institute of Standards and Technology (NIST)
+// Special Publication 800-38A, ``Recommendation for Block Cipher
+// Modes of Operation,'' 2001 Edition, pp. 55-58.
+
+package cipher_test
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"testing"
+)
+
+var commonCounter = []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}
+
+var ctrAESTests = []struct {
+	name string
+	key  []byte
+	iv   []byte
+	in   []byte
+	out  []byte
+}{
+	// NIST SP 800-38A pp 55-58
+	{
+		"CTR-AES128",
+		commonKey128,
+		commonCounter,
+		commonInput,
+		[]byte{
+			0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce,
+			0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff,
+			0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab,
+			0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee,
+		},
+	},
+	{
+		"CTR-AES192",
+		commonKey192,
+		commonCounter,
+		commonInput,
+		[]byte{
+			0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b,
+			0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6, 0xfa, 0xef, 0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94,
+			0x1e, 0x36, 0xb2, 0x6b, 0xd1, 0xeb, 0xc6, 0x70, 0xd1, 0xbd, 0x1d, 0x66, 0x56, 0x20, 0xab, 0xf7,
+			0x4f, 0x78, 0xa7, 0xf6, 0xd2, 0x98, 0x09, 0x58, 0x5a, 0x97, 0xda, 0xec, 0x58, 0xc6, 0xb0, 0x50,
+		},
+	},
+	{
+		"CTR-AES256",
+		commonKey256,
+		commonCounter,
+		commonInput,
+		[]byte{
+			0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28,
+			0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5,
+			0x2b, 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c, 0xe8, 0x70, 0x17, 0xba, 0x2d, 0x84, 0x98, 0x8d,
+			0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad, 0xa6, 0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6,
+		},
+	},
+}
+
+func TestCTR_AES(t *testing.T) {
+	for _, tt := range ctrAESTests {
+		test := tt.name
+
+		c, err := aes.NewCipher(tt.key)
+		if err != nil {
+			t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
+			continue
+		}
+
+		for j := 0; j <= 5; j += 5 {
+			in := tt.in[0 : len(tt.in)-j]
+			ctr := cipher.NewCTR(c, tt.iv)
+			encrypted := make([]byte, len(in))
+			ctr.XORKeyStream(encrypted, in)
+			if out := tt.out[0:len(in)]; !bytes.Equal(out, encrypted) {
+				t.Errorf("%s/%d: CTR\ninpt %x\nhave %x\nwant %x", test, len(in), in, encrypted, out)
+			}
+		}
+
+		for j := 0; j <= 7; j += 7 {
+			in := tt.out[0 : len(tt.out)-j]
+			ctr := cipher.NewCTR(c, tt.iv)
+			plain := make([]byte, len(in))
+			ctr.XORKeyStream(plain, in)
+			if out := tt.in[0:len(in)]; !bytes.Equal(out, plain) {
+				t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), plain, out)
+			}
+		}
+
+		if t.Failed() {
+			break
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/example_test.go b/third_party/gofrontend/libgo/go/crypto/cipher/example_test.go
new file mode 100644
index 0000000..373f679
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/example_test.go
@@ -0,0 +1,283 @@
+// 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 cipher_test
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/rand"
+	"encoding/hex"
+	"fmt"
+	"io"
+	"os"
+)
+
+func ExampleNewCBCDecrypter() {
+	key := []byte("example key 1234")
+	ciphertext, _ := hex.DecodeString("f363f3ccdcb12bb883abf484ba77d9cd7d32b5baecb3d4b1b3e0e4beffdb3ded")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	if len(ciphertext) < aes.BlockSize {
+		panic("ciphertext too short")
+	}
+	iv := ciphertext[:aes.BlockSize]
+	ciphertext = ciphertext[aes.BlockSize:]
+
+	// CBC mode always works in whole blocks.
+	if len(ciphertext)%aes.BlockSize != 0 {
+		panic("ciphertext is not a multiple of the block size")
+	}
+
+	mode := cipher.NewCBCDecrypter(block, iv)
+
+	// CryptBlocks can work in-place if the two arguments are the same.
+	mode.CryptBlocks(ciphertext, ciphertext)
+
+	// If the original plaintext lengths are not a multiple of the block
+	// size, padding would have to be added when encrypting, which would be
+	// removed at this point. For an example, see
+	// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. However, it's
+	// critical to note that ciphertexts must be authenticated (i.e. by
+	// using crypto/hmac) before being decrypted in order to avoid creating
+	// a padding oracle.
+
+	fmt.Printf("%s\n", ciphertext)
+	// Output: exampleplaintext
+}
+
+func ExampleNewCBCEncrypter() {
+	key := []byte("example key 1234")
+	plaintext := []byte("exampleplaintext")
+
+	// CBC mode works on blocks so plaintexts may need to be padded to the
+	// next whole block. For an example of such padding, see
+	// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
+	// assume that the plaintext is already of the correct length.
+	if len(plaintext)%aes.BlockSize != 0 {
+		panic("plaintext is not a multiple of the block size")
+	}
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+	iv := ciphertext[:aes.BlockSize]
+	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+		panic(err)
+	}
+
+	mode := cipher.NewCBCEncrypter(block, iv)
+	mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
+
+	// It's important to remember that ciphertexts must be authenticated
+	// (i.e. by using crypto/hmac) as well as being encrypted in order to
+	// be secure.
+
+	fmt.Printf("%x\n", ciphertext)
+}
+
+func ExampleNewCFBDecrypter() {
+	key := []byte("example key 1234")
+	ciphertext, _ := hex.DecodeString("22277966616d9bc47177bd02603d08c9a67d5380d0fe8cf3b44438dff7b9")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	if len(ciphertext) < aes.BlockSize {
+		panic("ciphertext too short")
+	}
+	iv := ciphertext[:aes.BlockSize]
+	ciphertext = ciphertext[aes.BlockSize:]
+
+	stream := cipher.NewCFBDecrypter(block, iv)
+
+	// XORKeyStream can work in-place if the two arguments are the same.
+	stream.XORKeyStream(ciphertext, ciphertext)
+	fmt.Printf("%s", ciphertext)
+	// Output: some plaintext
+}
+
+func ExampleNewCFBEncrypter() {
+	key := []byte("example key 1234")
+	plaintext := []byte("some plaintext")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+	iv := ciphertext[:aes.BlockSize]
+	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+		panic(err)
+	}
+
+	stream := cipher.NewCFBEncrypter(block, iv)
+	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+	// It's important to remember that ciphertexts must be authenticated
+	// (i.e. by using crypto/hmac) as well as being encrypted in order to
+	// be secure.
+}
+
+func ExampleNewCTR() {
+	key := []byte("example key 1234")
+	plaintext := []byte("some plaintext")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+	iv := ciphertext[:aes.BlockSize]
+	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+		panic(err)
+	}
+
+	stream := cipher.NewCTR(block, iv)
+	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+	// It's important to remember that ciphertexts must be authenticated
+	// (i.e. by using crypto/hmac) as well as being encrypted in order to
+	// be secure.
+
+	// CTR mode is the same for both encryption and decryption, so we can
+	// also decrypt that ciphertext with NewCTR.
+
+	plaintext2 := make([]byte, len(plaintext))
+	stream = cipher.NewCTR(block, iv)
+	stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
+
+	fmt.Printf("%s\n", plaintext2)
+	// Output: some plaintext
+}
+
+func ExampleNewOFB() {
+	key := []byte("example key 1234")
+	plaintext := []byte("some plaintext")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+	iv := ciphertext[:aes.BlockSize]
+	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+		panic(err)
+	}
+
+	stream := cipher.NewOFB(block, iv)
+	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+	// It's important to remember that ciphertexts must be authenticated
+	// (i.e. by using crypto/hmac) as well as being encrypted in order to
+	// be secure.
+
+	// OFB mode is the same for both encryption and decryption, so we can
+	// also decrypt that ciphertext with NewOFB.
+
+	plaintext2 := make([]byte, len(plaintext))
+	stream = cipher.NewOFB(block, iv)
+	stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
+
+	fmt.Printf("%s\n", plaintext2)
+	// Output: some plaintext
+}
+
+func ExampleStreamReader() {
+	key := []byte("example key 1234")
+
+	inFile, err := os.Open("encrypted-file")
+	if err != nil {
+		panic(err)
+	}
+	defer inFile.Close()
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// If the key is unique for each ciphertext, then it's ok to use a zero
+	// IV.
+	var iv [aes.BlockSize]byte
+	stream := cipher.NewOFB(block, iv[:])
+
+	outFile, err := os.OpenFile("decrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+	if err != nil {
+		panic(err)
+	}
+	defer outFile.Close()
+
+	reader := &cipher.StreamReader{S: stream, R: inFile}
+	// Copy the input file to the output file, decrypting as we go.
+	if _, err := io.Copy(outFile, reader); err != nil {
+		panic(err)
+	}
+
+	// Note that this example is simplistic in that it omits any
+	// authentication of the encrypted data. It you were actually to use
+	// StreamReader in this manner, an attacker could flip arbitrary bits in
+	// the output.
+}
+
+func ExampleStreamWriter() {
+	key := []byte("example key 1234")
+
+	inFile, err := os.Open("plaintext-file")
+	if err != nil {
+		panic(err)
+	}
+	defer inFile.Close()
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// If the key is unique for each ciphertext, then it's ok to use a zero
+	// IV.
+	var iv [aes.BlockSize]byte
+	stream := cipher.NewOFB(block, iv[:])
+
+	outFile, err := os.OpenFile("encrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+	if err != nil {
+		panic(err)
+	}
+	defer outFile.Close()
+
+	writer := &cipher.StreamWriter{S: stream, W: outFile}
+	// Copy the input file to the output file, encrypting as we go.
+	if _, err := io.Copy(writer, inFile); err != nil {
+		panic(err)
+	}
+
+	// Note that this example is simplistic in that it omits any
+	// authentication of the encrypted data. It you were actually to use
+	// StreamReader in this manner, an attacker could flip arbitrary bits in
+	// the decrypted result.
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/gcm.go b/third_party/gofrontend/libgo/go/crypto/cipher/gcm.go
new file mode 100644
index 0000000..bdafd85
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/gcm.go
@@ -0,0 +1,343 @@
+// Copyright 2013 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 cipher
+
+import (
+	"crypto/subtle"
+	"errors"
+)
+
+// AEAD is a cipher mode providing authenticated encryption with associated
+// data.
+type AEAD interface {
+	// NonceSize returns the size of the nonce that must be passed to Seal
+	// and Open.
+	NonceSize() int
+
+	// Overhead returns the maximum difference between the lengths of a
+	// plaintext and ciphertext.
+	Overhead() int
+
+	// Seal encrypts and authenticates plaintext, authenticates the
+	// additional data and appends the result to dst, returning the updated
+	// slice. The nonce must be NonceSize() bytes long and unique for all
+	// time, for a given key.
+	//
+	// The plaintext and dst may alias exactly or not at all.
+	Seal(dst, nonce, plaintext, data []byte) []byte
+
+	// Open decrypts and authenticates ciphertext, authenticates the
+	// additional data and, if successful, appends the resulting plaintext
+	// to dst, returning the updated slice. The nonce must be NonceSize()
+	// bytes long and both it and the additional data must match the
+	// value passed to Seal.
+	//
+	// The ciphertext and dst may alias exactly or not at all.
+	Open(dst, nonce, ciphertext, data []byte) ([]byte, error)
+}
+
+// gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM
+// standard and make getUint64 suitable for marshaling these values, the bits
+// are stored backwards. For example:
+//   the coefficient of x⁰ can be obtained by v.low >> 63.
+//   the coefficient of x⁶³ can be obtained by v.low & 1.
+//   the coefficient of x⁶⁴ can be obtained by v.high >> 63.
+//   the coefficient of x¹²⁷ can be obtained by v.high & 1.
+type gcmFieldElement struct {
+	low, high uint64
+}
+
+// gcm represents a Galois Counter Mode with a specific key. See
+// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
+type gcm struct {
+	cipher Block
+	// productTable contains the first sixteen powers of the key, H.
+	// However, they are in bit reversed order. See NewGCM.
+	productTable [16]gcmFieldElement
+}
+
+// NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode.
+func NewGCM(cipher Block) (AEAD, error) {
+	if cipher.BlockSize() != gcmBlockSize {
+		return nil, errors.New("cipher: NewGCM requires 128-bit block cipher")
+	}
+
+	var key [gcmBlockSize]byte
+	cipher.Encrypt(key[:], key[:])
+
+	g := &gcm{cipher: cipher}
+
+	// We precompute 16 multiples of |key|. However, when we do lookups
+	// into this table we'll be using bits from a field element and
+	// therefore the bits will be in the reverse order. So normally one
+	// would expect, say, 4*key to be in index 4 of the table but due to
+	// this bit ordering it will actually be in index 0010 (base 2) = 2.
+	x := gcmFieldElement{
+		getUint64(key[:8]),
+		getUint64(key[8:]),
+	}
+	g.productTable[reverseBits(1)] = x
+
+	for i := 2; i < 16; i += 2 {
+		g.productTable[reverseBits(i)] = gcmDouble(&g.productTable[reverseBits(i/2)])
+		g.productTable[reverseBits(i+1)] = gcmAdd(&g.productTable[reverseBits(i)], &x)
+	}
+
+	return g, nil
+}
+
+const (
+	gcmBlockSize = 16
+	gcmTagSize   = 16
+	gcmNonceSize = 12
+)
+
+func (*gcm) NonceSize() int {
+	return gcmNonceSize
+}
+
+func (*gcm) Overhead() int {
+	return gcmTagSize
+}
+
+func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte {
+	if len(nonce) != gcmNonceSize {
+		panic("cipher: incorrect nonce length given to GCM")
+	}
+
+	ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize)
+
+	// See GCM spec, section 7.1.
+	var counter, tagMask [gcmBlockSize]byte
+	copy(counter[:], nonce)
+	counter[gcmBlockSize-1] = 1
+
+	g.cipher.Encrypt(tagMask[:], counter[:])
+	gcmInc32(&counter)
+
+	g.counterCrypt(out, plaintext, &counter)
+	g.auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask)
+
+	return ret
+}
+
+var errOpen = errors.New("cipher: message authentication failed")
+
+func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
+	if len(nonce) != gcmNonceSize {
+		panic("cipher: incorrect nonce length given to GCM")
+	}
+
+	if len(ciphertext) < gcmTagSize {
+		return nil, errOpen
+	}
+	tag := ciphertext[len(ciphertext)-gcmTagSize:]
+	ciphertext = ciphertext[:len(ciphertext)-gcmTagSize]
+
+	// See GCM spec, section 7.1.
+	var counter, tagMask [gcmBlockSize]byte
+	copy(counter[:], nonce)
+	counter[gcmBlockSize-1] = 1
+
+	g.cipher.Encrypt(tagMask[:], counter[:])
+	gcmInc32(&counter)
+
+	var expectedTag [gcmTagSize]byte
+	g.auth(expectedTag[:], ciphertext, data, &tagMask)
+
+	if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 {
+		return nil, errOpen
+	}
+
+	ret, out := sliceForAppend(dst, len(ciphertext))
+	g.counterCrypt(out, ciphertext, &counter)
+
+	return ret, nil
+}
+
+// reverseBits reverses the order of the bits of 4-bit number in i.
+func reverseBits(i int) int {
+	i = ((i << 2) & 0xc) | ((i >> 2) & 0x3)
+	i = ((i << 1) & 0xa) | ((i >> 1) & 0x5)
+	return i
+}
+
+// gcmAdd adds two elements of GF(2¹²⁸) and returns the sum.
+func gcmAdd(x, y *gcmFieldElement) gcmFieldElement {
+	// Addition in a characteristic 2 field is just XOR.
+	return gcmFieldElement{x.low ^ y.low, x.high ^ y.high}
+}
+
+// gcmDouble returns the result of doubling an element of GF(2¹²⁸).
+func gcmDouble(x *gcmFieldElement) (double gcmFieldElement) {
+	msbSet := x.high&1 == 1
+
+	// Because of the bit-ordering, doubling is actually a right shift.
+	double.high = x.high >> 1
+	double.high |= x.low << 63
+	double.low = x.low >> 1
+
+	// If the most-significant bit was set before shifting then it,
+	// conceptually, becomes a term of x^128. This is greater than the
+	// irreducible polynomial so the result has to be reduced. The
+	// irreducible polynomial is 1+x+x^2+x^7+x^128. We can subtract that to
+	// eliminate the term at x^128 which also means subtracting the other
+	// four terms. In characteristic 2 fields, subtraction == addition ==
+	// XOR.
+	if msbSet {
+		double.low ^= 0xe100000000000000
+	}
+
+	return
+}
+
+var gcmReductionTable = []uint16{
+	0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
+	0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
+}
+
+// mul sets y to y*H, where H is the GCM key, fixed during NewGCM.
+func (g *gcm) mul(y *gcmFieldElement) {
+	var z gcmFieldElement
+
+	for i := 0; i < 2; i++ {
+		word := y.high
+		if i == 1 {
+			word = y.low
+		}
+
+		// Multiplication works by multiplying z by 16 and adding in
+		// one of the precomputed multiples of H.
+		for j := 0; j < 64; j += 4 {
+			msw := z.high & 0xf
+			z.high >>= 4
+			z.high |= z.low << 60
+			z.low >>= 4
+			z.low ^= uint64(gcmReductionTable[msw]) << 48
+
+			// the values in |table| are ordered for
+			// little-endian bit positions. See the comment
+			// in NewGCM.
+			t := &g.productTable[word&0xf]
+
+			z.low ^= t.low
+			z.high ^= t.high
+			word >>= 4
+		}
+	}
+
+	*y = z
+}
+
+// updateBlocks extends y with more polynomial terms from blocks, based on
+// Horner's rule. There must be a multiple of gcmBlockSize bytes in blocks.
+func (g *gcm) updateBlocks(y *gcmFieldElement, blocks []byte) {
+	for len(blocks) > 0 {
+		y.low ^= getUint64(blocks)
+		y.high ^= getUint64(blocks[8:])
+		g.mul(y)
+		blocks = blocks[gcmBlockSize:]
+	}
+}
+
+// update extends y with more polynomial terms from data. If data is not a
+// multiple of gcmBlockSize bytes long then the remainder is zero padded.
+func (g *gcm) update(y *gcmFieldElement, data []byte) {
+	fullBlocks := (len(data) >> 4) << 4
+	g.updateBlocks(y, data[:fullBlocks])
+
+	if len(data) != fullBlocks {
+		var partialBlock [gcmBlockSize]byte
+		copy(partialBlock[:], data[fullBlocks:])
+		g.updateBlocks(y, partialBlock[:])
+	}
+}
+
+// gcmInc32 treats the final four bytes of counterBlock as a big-endian value
+// and increments it.
+func gcmInc32(counterBlock *[16]byte) {
+	for i := gcmBlockSize - 1; i >= gcmBlockSize-4; i-- {
+		counterBlock[i]++
+		if counterBlock[i] != 0 {
+			break
+		}
+	}
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+	if total := len(in) + n; cap(in) >= total {
+		head = in[:total]
+	} else {
+		head = make([]byte, total)
+		copy(head, in)
+	}
+	tail = head[len(in):]
+	return
+}
+
+// counterCrypt crypts in to out using g.cipher in counter mode.
+func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) {
+	var mask [gcmBlockSize]byte
+
+	for len(in) >= gcmBlockSize {
+		g.cipher.Encrypt(mask[:], counter[:])
+		gcmInc32(counter)
+
+		xorWords(out, in, mask[:])
+		out = out[gcmBlockSize:]
+		in = in[gcmBlockSize:]
+	}
+
+	if len(in) > 0 {
+		g.cipher.Encrypt(mask[:], counter[:])
+		gcmInc32(counter)
+		xorBytes(out, in, mask[:])
+	}
+}
+
+// auth calculates GHASH(ciphertext, additionalData), masks the result with
+// tagMask and writes the result to out.
+func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) {
+	var y gcmFieldElement
+	g.update(&y, additionalData)
+	g.update(&y, ciphertext)
+
+	y.low ^= uint64(len(additionalData)) * 8
+	y.high ^= uint64(len(ciphertext)) * 8
+
+	g.mul(&y)
+
+	putUint64(out, y.low)
+	putUint64(out[8:], y.high)
+
+	xorWords(out, out, tagMask[:])
+}
+
+func getUint64(data []byte) uint64 {
+	r := uint64(data[0])<<56 |
+		uint64(data[1])<<48 |
+		uint64(data[2])<<40 |
+		uint64(data[3])<<32 |
+		uint64(data[4])<<24 |
+		uint64(data[5])<<16 |
+		uint64(data[6])<<8 |
+		uint64(data[7])
+	return r
+}
+
+func putUint64(out []byte, v uint64) {
+	out[0] = byte(v >> 56)
+	out[1] = byte(v >> 48)
+	out[2] = byte(v >> 40)
+	out[3] = byte(v >> 32)
+	out[4] = byte(v >> 24)
+	out[5] = byte(v >> 16)
+	out[6] = byte(v >> 8)
+	out[7] = byte(v)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/gcm_test.go b/third_party/gofrontend/libgo/go/crypto/cipher/gcm_test.go
new file mode 100644
index 0000000..0c502ce
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/gcm_test.go
@@ -0,0 +1,159 @@
+// Copyright 2013 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 cipher_test
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"encoding/hex"
+	"testing"
+)
+
+// AES-GCM test vectors taken from gcmEncryptExtIV128.rsp from
+// http://csrc.nist.gov/groups/STM/cavp/index.html.
+var aesGCMTests = []struct {
+	key, nonce, plaintext, ad, result string
+}{
+	{
+		"11754cd72aec309bf52f7687212e8957",
+		"3c819d9a9bed087615030b65",
+		"",
+		"",
+		"250327c674aaf477aef2675748cf6971",
+	},
+	{
+		"ca47248ac0b6f8372a97ac43508308ed",
+		"ffd2b598feabc9019262d2be",
+		"",
+		"",
+		"60d20404af527d248d893ae495707d1a",
+	},
+	{
+		"77be63708971c4e240d1cb79e8d77feb",
+		"e0e00f19fed7ba0136a797f3",
+		"",
+		"7a43ec1d9c0a5a78a0b16533a6213cab",
+		"209fcc8d3675ed938e9c7166709dd946",
+	},
+	{
+		"7680c5d3ca6154758e510f4d25b98820",
+		"f8f105f9c3df4965780321f8",
+		"",
+		"c94c410194c765e3dcc7964379758ed3",
+		"94dca8edfcf90bb74b153c8d48a17930",
+	},
+	{
+		"7fddb57453c241d03efbed3ac44e371c",
+		"ee283a3fc75575e33efd4887",
+		"d5de42b461646c255c87bd2962d3b9a2",
+		"",
+		"2ccda4a5415cb91e135c2a0f78c9b2fdb36d1df9b9d5e596f83e8b7f52971cb3",
+	},
+	{
+		"ab72c77b97cb5fe9a382d9fe81ffdbed",
+		"54cc7dc2c37ec006bcc6d1da",
+		"007c5e5b3e59df24a7c355584fc1518d",
+		"",
+		"0e1bde206a07a9c2c1b65300f8c649972b4401346697138c7a4891ee59867d0c",
+	},
+	{
+		"fe47fcce5fc32665d2ae399e4eec72ba",
+		"5adb9609dbaeb58cbd6e7275",
+		"7c0e88c88899a779228465074797cd4c2e1498d259b54390b85e3eef1c02df60e743f1b840382c4bccaf3bafb4ca8429bea063",
+		"88319d6e1d3ffa5f987199166c8a9b56c2aeba5a",
+		"98f4826f05a265e6dd2be82db241c0fbbbf9ffb1c173aa83964b7cf5393043736365253ddbc5db8778371495da76d269e5db3e291ef1982e4defedaa2249f898556b47",
+	},
+	{
+		"ec0c2ba17aa95cd6afffe949da9cc3a8",
+		"296bce5b50b7d66096d627ef",
+		"b85b3753535b825cbe5f632c0b843c741351f18aa484281aebec2f45bb9eea2d79d987b764b9611f6c0f8641843d5d58f3a242",
+		"f8d00f05d22bf68599bcdeb131292ad6e2df5d14",
+		"a7443d31c26bdf2a1c945e29ee4bd344a99cfaf3aa71f8b3f191f83c2adfc7a07162995506fde6309ffc19e716eddf1a828c5a890147971946b627c40016da1ecf3e77",
+	},
+	{
+		"2c1f21cf0f6fb3661943155c3e3d8492",
+		"23cb5ff362e22426984d1907",
+		"42f758836986954db44bf37c6ef5e4ac0adaf38f27252a1b82d02ea949c8a1a2dbc0d68b5615ba7c1220ff6510e259f06655d8",
+		"5d3624879d35e46849953e45a32a624d6a6c536ed9857c613b572b0333e701557a713e3f010ecdf9a6bd6c9e3e44b065208645aff4aabee611b391528514170084ccf587177f4488f33cfb5e979e42b6e1cfc0a60238982a7aec",
+		"81824f0e0d523db30d3da369fdc0d60894c7a0a20646dd015073ad2732bd989b14a222b6ad57af43e1895df9dca2a5344a62cc57a3ee28136e94c74838997ae9823f3a",
+	},
+	{
+		"d9f7d2411091f947b4d6f1e2d1f0fb2e",
+		"e1934f5db57cc983e6b180e7",
+		"73ed042327f70fe9c572a61545eda8b2a0c6e1d6c291ef19248e973aee6c312012f490c2c6f6166f4a59431e182663fcaea05a",
+		"0a8a18a7150e940c3d87b38e73baee9a5c049ee21795663e264b694a949822b639092d0e67015e86363583fcf0ca645af9f43375f05fdb4ce84f411dcbca73c2220dea03a20115d2e51398344b16bee1ed7c499b353d6c597af8",
+		"aaadbd5c92e9151ce3db7210b8714126b73e43436d242677afa50384f2149b831f1d573c7891c2a91fbc48db29967ec9542b2321b51ca862cb637cdd03b99a0f93b134",
+	},
+	{
+		"fe9bb47deb3a61e423c2231841cfd1fb",
+		"4d328eb776f500a2f7fb47aa",
+		"f1cc3818e421876bb6b8bbd6c9",
+		"",
+		"b88c5c1977b35b517b0aeae96743fd4727fe5cdb4b5b42818dea7ef8c9",
+	},
+	{
+		"6703df3701a7f54911ca72e24dca046a",
+		"12823ab601c350ea4bc2488c",
+		"793cd125b0b84a043e3ac67717",
+		"",
+		"b2051c80014f42f08735a7b0cd38e6bcd29962e5f2c13626b85a877101",
+	},
+}
+
+func TestAESGCM(t *testing.T) {
+	for i, test := range aesGCMTests {
+		key, _ := hex.DecodeString(test.key)
+		aes, err := aes.NewCipher(key)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		nonce, _ := hex.DecodeString(test.nonce)
+		plaintext, _ := hex.DecodeString(test.plaintext)
+		ad, _ := hex.DecodeString(test.ad)
+		aesgcm, err := cipher.NewGCM(aes)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		ct := aesgcm.Seal(nil, nonce, plaintext, ad)
+		if ctHex := hex.EncodeToString(ct); ctHex != test.result {
+			t.Errorf("#%d: got %s, want %s", i, ctHex, test.result)
+			continue
+		}
+
+		plaintext2, err := aesgcm.Open(nil, nonce, ct, ad)
+		if err != nil {
+			t.Errorf("#%d: Open failed", i)
+			continue
+		}
+
+		if !bytes.Equal(plaintext, plaintext2) {
+			t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
+			continue
+		}
+
+		if len(ad) > 0 {
+			ad[0] ^= 0x80
+			if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil {
+				t.Errorf("#%d: Open was successful after altering additional data", i)
+			}
+			ad[0] ^= 0x80
+		}
+
+		nonce[0] ^= 0x80
+		if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil {
+			t.Errorf("#%d: Open was successful after altering nonce", i)
+		}
+		nonce[0] ^= 0x80
+
+		ct[0] ^= 0x80
+		if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil {
+			t.Errorf("#%d: Open was successful after altering ciphertext", i)
+		}
+		ct[0] ^= 0x80
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/io.go b/third_party/gofrontend/libgo/go/crypto/cipher/io.go
new file mode 100644
index 0000000..3938c0a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/io.go
@@ -0,0 +1,55 @@
+// Copyright 2010 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 cipher
+
+import "io"
+
+// The Stream* objects are so simple that all their members are public. Users
+// can create them themselves.
+
+// StreamReader wraps a Stream into an io.Reader. It calls XORKeyStream
+// to process each slice of data which passes through.
+type StreamReader struct {
+	S Stream
+	R io.Reader
+}
+
+func (r StreamReader) Read(dst []byte) (n int, err error) {
+	n, err = r.R.Read(dst)
+	r.S.XORKeyStream(dst[:n], dst[:n])
+	return
+}
+
+// StreamWriter wraps a Stream into an io.Writer. It calls XORKeyStream
+// to process each slice of data which passes through. If any Write call
+// returns short then the StreamWriter is out of sync and must be discarded.
+// A StreamWriter has no internal buffering; Close does not need
+// to be called to flush write data.
+type StreamWriter struct {
+	S   Stream
+	W   io.Writer
+	Err error // unused
+}
+
+func (w StreamWriter) Write(src []byte) (n int, err error) {
+	c := make([]byte, len(src))
+	w.S.XORKeyStream(c, src)
+	n, err = w.W.Write(c)
+	if n != len(src) {
+		if err == nil { // should never happen
+			err = io.ErrShortWrite
+		}
+	}
+	return
+}
+
+// Close closes the underlying Writer and returns its Close return value, if the Writer
+// is also an io.Closer. Otherwise it returns nil.
+func (w StreamWriter) Close() error {
+	if c, ok := w.W.(io.Closer); ok {
+		return c.Close()
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/ofb.go b/third_party/gofrontend/libgo/go/crypto/cipher/ofb.go
new file mode 100644
index 0000000..e86ebcb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/ofb.go
@@ -0,0 +1,66 @@
+// 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.
+
+// OFB (Output Feedback) Mode.
+
+package cipher
+
+type ofb struct {
+	b       Block
+	cipher  []byte
+	out     []byte
+	outUsed int
+}
+
+// NewOFB returns a Stream that encrypts or decrypts using the block cipher b
+// in output feedback mode. The initialization vector iv's length must be equal
+// to b's block size.
+func NewOFB(b Block, iv []byte) Stream {
+	blockSize := b.BlockSize()
+	if len(iv) != blockSize {
+		return nil
+	}
+	bufSize := streamBufferSize
+	if bufSize < blockSize {
+		bufSize = blockSize
+	}
+	x := &ofb{
+		b:       b,
+		cipher:  make([]byte, blockSize),
+		out:     make([]byte, 0, bufSize),
+		outUsed: 0,
+	}
+
+	copy(x.cipher, iv)
+	return x
+}
+
+func (x *ofb) refill() {
+	bs := x.b.BlockSize()
+	remain := len(x.out) - x.outUsed
+	if remain > x.outUsed {
+		return
+	}
+	copy(x.out, x.out[x.outUsed:])
+	x.out = x.out[:cap(x.out)]
+	for remain < len(x.out)-bs {
+		x.b.Encrypt(x.cipher, x.cipher)
+		copy(x.out[remain:], x.cipher)
+		remain += bs
+	}
+	x.out = x.out[:remain]
+	x.outUsed = 0
+}
+
+func (x *ofb) XORKeyStream(dst, src []byte) {
+	for len(src) > 0 {
+		if x.outUsed >= len(x.out)-x.b.BlockSize() {
+			x.refill()
+		}
+		n := xorBytes(dst, src, x.out[x.outUsed:])
+		dst = dst[n:]
+		src = src[n:]
+		x.outUsed += n
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/ofb_test.go b/third_party/gofrontend/libgo/go/crypto/cipher/ofb_test.go
new file mode 100644
index 0000000..8d3c5d3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/ofb_test.go
@@ -0,0 +1,102 @@
+// 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.
+
+// OFB AES test vectors.
+
+// See U.S. National Institute of Standards and Technology (NIST)
+// Special Publication 800-38A, ``Recommendation for Block Cipher
+// Modes of Operation,'' 2001 Edition, pp. 52-55.
+
+package cipher_test
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"testing"
+)
+
+type ofbTest struct {
+	name string
+	key  []byte
+	iv   []byte
+	in   []byte
+	out  []byte
+}
+
+var ofbTests = []ofbTest{
+	// NIST SP 800-38A pp 52-55
+	{
+		"OFB-AES128",
+		commonKey128,
+		commonIV,
+		commonInput,
+		[]byte{
+			0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
+			0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
+			0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
+			0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e,
+		},
+	},
+	{
+		"OFB-AES192",
+		commonKey192,
+		commonIV,
+		commonInput,
+		[]byte{
+			0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
+			0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
+			0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
+			0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a,
+		},
+	},
+	{
+		"OFB-AES256",
+		commonKey256,
+		commonIV,
+		commonInput,
+		[]byte{
+			0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
+			0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
+			0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
+			0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84,
+		},
+	},
+}
+
+func TestOFB(t *testing.T) {
+	for _, tt := range ofbTests {
+		test := tt.name
+
+		c, err := aes.NewCipher(tt.key)
+		if err != nil {
+			t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
+			continue
+		}
+
+		for j := 0; j <= 5; j += 5 {
+			plaintext := tt.in[0 : len(tt.in)-j]
+			ofb := cipher.NewOFB(c, tt.iv)
+			ciphertext := make([]byte, len(plaintext))
+			ofb.XORKeyStream(ciphertext, plaintext)
+			if !bytes.Equal(ciphertext, tt.out[:len(plaintext)]) {
+				t.Errorf("%s/%d: encrypting\ninput % x\nhave % x\nwant % x", test, len(plaintext), plaintext, ciphertext, tt.out)
+			}
+		}
+
+		for j := 0; j <= 5; j += 5 {
+			ciphertext := tt.out[0 : len(tt.in)-j]
+			ofb := cipher.NewOFB(c, tt.iv)
+			plaintext := make([]byte, len(ciphertext))
+			ofb.XORKeyStream(plaintext, ciphertext)
+			if !bytes.Equal(plaintext, tt.in[:len(ciphertext)]) {
+				t.Errorf("%s/%d: decrypting\nhave % x\nwant % x", test, len(ciphertext), plaintext, tt.in)
+			}
+		}
+
+		if t.Failed() {
+			break
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/xor.go b/third_party/gofrontend/libgo/go/crypto/cipher/xor.go
new file mode 100644
index 0000000..f88dc89
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/xor.go
@@ -0,0 +1,84 @@
+// Copyright 2013 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 cipher
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+const wordSize = int(unsafe.Sizeof(uintptr(0)))
+const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64"
+
+// fastXORBytes xors in bulk. It only works on architectures that
+// support unaligned read/writes.
+func fastXORBytes(dst, a, b []byte) int {
+	n := len(a)
+	if len(b) < n {
+		n = len(b)
+	}
+
+	w := n / wordSize
+	if w > 0 {
+		dw := *(*[]uintptr)(unsafe.Pointer(&dst))
+		aw := *(*[]uintptr)(unsafe.Pointer(&a))
+		bw := *(*[]uintptr)(unsafe.Pointer(&b))
+		for i := 0; i < w; i++ {
+			dw[i] = aw[i] ^ bw[i]
+		}
+	}
+
+	for i := (n - n%wordSize); i < n; i++ {
+		dst[i] = a[i] ^ b[i]
+	}
+
+	return n
+}
+
+func safeXORBytes(dst, a, b []byte) int {
+	n := len(a)
+	if len(b) < n {
+		n = len(b)
+	}
+	for i := 0; i < n; i++ {
+		dst[i] = a[i] ^ b[i]
+	}
+	return n
+}
+
+// xorBytes xors the bytes in a and b. The destination is assumed to have enough
+// space. Returns the number of bytes xor'd.
+func xorBytes(dst, a, b []byte) int {
+	if supportsUnaligned {
+		return fastXORBytes(dst, a, b)
+	} else {
+		// TODO(hanwen): if (dst, a, b) have common alignment
+		// we could still try fastXORBytes. It is not clear
+		// how often this happens, and it's only worth it if
+		// the block encryption itself is hardware
+		// accelerated.
+		return safeXORBytes(dst, a, b)
+	}
+}
+
+// fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.)
+// The arguments are assumed to be of equal length.
+func fastXORWords(dst, a, b []byte) {
+	dw := *(*[]uintptr)(unsafe.Pointer(&dst))
+	aw := *(*[]uintptr)(unsafe.Pointer(&a))
+	bw := *(*[]uintptr)(unsafe.Pointer(&b))
+	n := len(b) / wordSize
+	for i := 0; i < n; i++ {
+		dw[i] = aw[i] ^ bw[i]
+	}
+}
+
+func xorWords(dst, a, b []byte) {
+	if supportsUnaligned {
+		fastXORWords(dst, a, b)
+	} else {
+		safeXORBytes(dst, a, b)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/cipher/xor_test.go b/third_party/gofrontend/libgo/go/crypto/cipher/xor_test.go
new file mode 100644
index 0000000..cc1c9d7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/cipher/xor_test.go
@@ -0,0 +1,28 @@
+// Copyright 2013 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 cipher
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestXOR(t *testing.T) {
+	for alignP := 0; alignP < 2; alignP++ {
+		for alignQ := 0; alignQ < 2; alignQ++ {
+			for alignD := 0; alignD < 2; alignD++ {
+				p := make([]byte, 1024)[alignP:]
+				q := make([]byte, 1024)[alignQ:]
+				d1 := make([]byte, 1024+alignD)[alignD:]
+				d2 := make([]byte, 1024+alignD)[alignD:]
+				xorBytes(d1, p, q)
+				safeXORBytes(d2, p, q)
+				if bytes.Compare(d1, d2) != 0 {
+					t.Error("not equal")
+				}
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/crypto.go b/third_party/gofrontend/libgo/go/crypto/crypto.go
new file mode 100644
index 0000000..4b03628
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/crypto.go
@@ -0,0 +1,85 @@
+// 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.
+
+// Package crypto collects common cryptographic constants.
+package crypto
+
+import (
+	"hash"
+	"strconv"
+)
+
+// Hash identifies a cryptographic hash function that is implemented in another
+// package.
+type Hash uint
+
+const (
+	MD4       Hash = 1 + iota // import code.google.com/p/go.crypto/md4
+	MD5                       // import crypto/md5
+	SHA1                      // import crypto/sha1
+	SHA224                    // import crypto/sha256
+	SHA256                    // import crypto/sha256
+	SHA384                    // import crypto/sha512
+	SHA512                    // import crypto/sha512
+	MD5SHA1                   // no implementation; MD5+SHA1 used for TLS RSA
+	RIPEMD160                 // import code.google.com/p/go.crypto/ripemd160
+	maxHash
+)
+
+var digestSizes = []uint8{
+	MD4:       16,
+	MD5:       16,
+	SHA1:      20,
+	SHA224:    28,
+	SHA256:    32,
+	SHA384:    48,
+	SHA512:    64,
+	MD5SHA1:   36,
+	RIPEMD160: 20,
+}
+
+// Size returns the length, in bytes, of a digest resulting from the given hash
+// function. It doesn't require that the hash function in question be linked
+// into the program.
+func (h Hash) Size() int {
+	if h > 0 && h < maxHash {
+		return int(digestSizes[h])
+	}
+	panic("crypto: Size of unknown hash function")
+}
+
+var hashes = make([]func() hash.Hash, maxHash)
+
+// New returns a new hash.Hash calculating the given hash function. New panics
+// if the hash function is not linked into the binary.
+func (h Hash) New() hash.Hash {
+	if h > 0 && h < maxHash {
+		f := hashes[h]
+		if f != nil {
+			return f()
+		}
+	}
+	panic("crypto: requested hash function #" + strconv.Itoa(int(h)) + " is unavailable")
+}
+
+// Available reports whether the given hash function is linked into the binary.
+func (h Hash) Available() bool {
+	return h < maxHash && hashes[h] != nil
+}
+
+// RegisterHash registers a function that returns a new instance of the given
+// hash function. This is intended to be called from the init function in
+// packages that implement hash functions.
+func RegisterHash(h Hash, f func() hash.Hash) {
+	if h >= maxHash {
+		panic("crypto: RegisterHash of unknown hash function")
+	}
+	hashes[h] = f
+}
+
+// PublicKey represents a public key using an unspecified algorithm.
+type PublicKey interface{}
+
+// PrivateKey represents a private key using an unspecified algorithm.
+type PrivateKey interface{}
diff --git a/third_party/gofrontend/libgo/go/crypto/des/block.go b/third_party/gofrontend/libgo/go/crypto/des/block.go
new file mode 100644
index 0000000..26355a2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/des/block.go
@@ -0,0 +1,223 @@
+// 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.
+
+package des
+
+import (
+	"encoding/binary"
+)
+
+func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) {
+	b := binary.BigEndian.Uint64(src)
+	b = permuteInitialBlock(b)
+	left, right := uint32(b>>32), uint32(b)
+
+	var subkey uint64
+	for i := 0; i < 16; i++ {
+		if decrypt {
+			subkey = subkeys[15-i]
+		} else {
+			subkey = subkeys[i]
+		}
+
+		left, right = right, left^feistel(right, subkey)
+	}
+	// switch left & right and perform final permutation
+	preOutput := (uint64(right) << 32) | uint64(left)
+	binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
+}
+
+// Encrypt one block from src into dst, using the subkeys.
+func encryptBlock(subkeys []uint64, dst, src []byte) {
+	cryptBlock(subkeys, dst, src, false)
+}
+
+// Decrypt one block from src into dst, using the subkeys.
+func decryptBlock(subkeys []uint64, dst, src []byte) {
+	cryptBlock(subkeys, dst, src, true)
+}
+
+// DES Feistel function
+func feistel(right uint32, key uint64) (result uint32) {
+	sBoxLocations := key ^ expandBlock(right)
+	var sBoxResult uint32
+	for i := uint8(0); i < 8; i++ {
+		sBoxLocation := uint8(sBoxLocations>>42) & 0x3f
+		sBoxLocations <<= 6
+		// row determined by 1st and 6th bit
+		// column is middle four bits
+		row := (sBoxLocation & 0x1) | ((sBoxLocation & 0x20) >> 4)
+		column := (sBoxLocation >> 1) & 0xf
+		sBoxResult ^= feistelBox[i][16*row+column]
+	}
+	return sBoxResult
+}
+
+// feistelBox[s][16*i+j] contains the output of permutationFunction
+// for sBoxes[s][i][j] << 4*(7-s)
+var feistelBox [8][64]uint32
+
+// general purpose function to perform DES block permutations
+func permuteBlock(src uint64, permutation []uint8) (block uint64) {
+	for position, n := range permutation {
+		bit := (src >> n) & 1
+		block |= bit << uint((len(permutation)-1)-position)
+	}
+	return
+}
+
+func init() {
+	for s := range sBoxes {
+		for i := 0; i < 4; i++ {
+			for j := 0; j < 16; j++ {
+				f := uint64(sBoxes[s][i][j]) << (4 * (7 - uint(s)))
+				f = permuteBlock(uint64(f), permutationFunction[:])
+				feistelBox[s][16*i+j] = uint32(f)
+			}
+		}
+	}
+}
+
+// expandBlock expands an input block of 32 bits,
+// producing an output block of 48 bits.
+func expandBlock(src uint32) (block uint64) {
+	// rotate the 5 highest bits to the right.
+	src = (src << 5) | (src >> 27)
+	for i := 0; i < 8; i++ {
+		block <<= 6
+		// take the 6 bits on the right
+		block |= uint64(src) & (1<<6 - 1)
+		// advance by 4 bits.
+		src = (src << 4) | (src >> 28)
+	}
+	return
+}
+
+// permuteInitialBlock is equivalent to the permutation defined
+// by initialPermutation.
+func permuteInitialBlock(block uint64) uint64 {
+	// block = b7 b6 b5 b4 b3 b2 b1 b0 (8 bytes)
+	b1 := block >> 48
+	b2 := block << 48
+	block ^= b1 ^ b2 ^ b1<<48 ^ b2>>48
+
+	// block = b1 b0 b5 b4 b3 b2 b7 b6
+	b1 = block >> 32 & 0xff00ff
+	b2 = (block & 0xff00ff00)
+	block ^= b1<<32 ^ b2 ^ b1<<8 ^ b2<<24 // exchange b0 b4 with b3 b7
+
+	// block is now b1 b3 b5 b7 b0 b2 b4 b7, the permutation:
+	//                  ...  8
+	//                  ... 24
+	//                  ... 40
+	//                  ... 56
+	//  7  6  5  4  3  2  1  0
+	// 23 22 21 20 19 18 17 16
+	//                  ... 32
+	//                  ... 48
+
+	// exchange 4,5,6,7 with 32,33,34,35 etc.
+	b1 = block & 0x0f0f00000f0f0000
+	b2 = block & 0x0000f0f00000f0f0
+	block ^= b1 ^ b2 ^ b1>>12 ^ b2<<12
+
+	// block is the permutation:
+	//
+	//   [+8]         [+40]
+	//
+	//  7  6  5  4
+	// 23 22 21 20
+	//  3  2  1  0
+	// 19 18 17 16    [+32]
+
+	// exchange 0,1,4,5 with 18,19,22,23
+	b1 = block & 0x3300330033003300
+	b2 = block & 0x00cc00cc00cc00cc
+	block ^= b1 ^ b2 ^ b1>>6 ^ b2<<6
+
+	// block is the permutation:
+	// 15 14
+	// 13 12
+	// 11 10
+	//  9  8
+	//  7  6
+	//  5  4
+	//  3  2
+	//  1  0 [+16] [+32] [+64]
+
+	// exchange 0,2,4,6 with 9,11,13,15:
+	b1 = block & 0xaaaaaaaa55555555
+	block ^= b1 ^ b1>>33 ^ b1<<33
+
+	// block is the permutation:
+	// 6 14 22 30 38 46 54 62
+	// 4 12 20 28 36 44 52 60
+	// 2 10 18 26 34 42 50 58
+	// 0  8 16 24 32 40 48 56
+	// 7 15 23 31 39 47 55 63
+	// 5 13 21 29 37 45 53 61
+	// 3 11 19 27 35 43 51 59
+	// 1  9 17 25 33 41 49 57
+	return block
+}
+
+// permuteInitialBlock is equivalent to the permutation defined
+// by finalPermutation.
+func permuteFinalBlock(block uint64) uint64 {
+	// Perform the same bit exchanges as permuteInitialBlock
+	// but in reverse order.
+	b1 := block & 0xaaaaaaaa55555555
+	block ^= b1 ^ b1>>33 ^ b1<<33
+
+	b1 = block & 0x3300330033003300
+	b2 := block & 0x00cc00cc00cc00cc
+	block ^= b1 ^ b2 ^ b1>>6 ^ b2<<6
+
+	b1 = block & 0x0f0f00000f0f0000
+	b2 = block & 0x0000f0f00000f0f0
+	block ^= b1 ^ b2 ^ b1>>12 ^ b2<<12
+
+	b1 = block >> 32 & 0xff00ff
+	b2 = (block & 0xff00ff00)
+	block ^= b1<<32 ^ b2 ^ b1<<8 ^ b2<<24
+
+	b1 = block >> 48
+	b2 = block << 48
+	block ^= b1 ^ b2 ^ b1<<48 ^ b2>>48
+	return block
+}
+
+// creates 16 28-bit blocks rotated according
+// to the rotation schedule
+func ksRotate(in uint32) (out []uint32) {
+	out = make([]uint32, 16)
+	last := in
+	for i := 0; i < 16; i++ {
+		// 28-bit circular left shift
+		left := (last << (4 + ksRotations[i])) >> 4
+		right := (last << 4) >> (32 - ksRotations[i])
+		out[i] = left | right
+		last = out[i]
+	}
+	return
+}
+
+// creates 16 56-bit subkeys from the original key
+func (c *desCipher) generateSubkeys(keyBytes []byte) {
+	// apply PC1 permutation to key
+	key := binary.BigEndian.Uint64(keyBytes)
+	permutedKey := permuteBlock(key, permutedChoice1[:])
+
+	// rotate halves of permuted key according to the rotation schedule
+	leftRotations := ksRotate(uint32(permutedKey >> 28))
+	rightRotations := ksRotate(uint32(permutedKey<<4) >> 4)
+
+	// generate subkeys
+	for i := 0; i < 16; i++ {
+		// combine halves to form 56-bit input to PC2
+		pc2Input := uint64(leftRotations[i])<<28 | uint64(rightRotations[i])
+		// apply PC2 permutation to 7 byte input
+		c.subkeys[i] = permuteBlock(pc2Input, permutedChoice2[:])
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/des/cipher.go b/third_party/gofrontend/libgo/go/crypto/des/cipher.go
new file mode 100644
index 0000000..2f929ca
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/des/cipher.go
@@ -0,0 +1,73 @@
+// 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.
+
+package des
+
+import (
+	"crypto/cipher"
+	"strconv"
+)
+
+// The DES block size in bytes.
+const BlockSize = 8
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+	return "crypto/des: invalid key size " + strconv.Itoa(int(k))
+}
+
+// desCipher is an instance of DES encryption.
+type desCipher struct {
+	subkeys [16]uint64
+}
+
+// NewCipher creates and returns a new cipher.Block.
+func NewCipher(key []byte) (cipher.Block, error) {
+	if len(key) != 8 {
+		return nil, KeySizeError(len(key))
+	}
+
+	c := new(desCipher)
+	c.generateSubkeys(key)
+	return c, nil
+}
+
+func (c *desCipher) BlockSize() int { return BlockSize }
+
+func (c *desCipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
+
+func (c *desCipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
+
+// A tripleDESCipher is an instance of TripleDES encryption.
+type tripleDESCipher struct {
+	cipher1, cipher2, cipher3 desCipher
+}
+
+// NewTripleDESCipher creates and returns a new cipher.Block.
+func NewTripleDESCipher(key []byte) (cipher.Block, error) {
+	if len(key) != 24 {
+		return nil, KeySizeError(len(key))
+	}
+
+	c := new(tripleDESCipher)
+	c.cipher1.generateSubkeys(key[:8])
+	c.cipher2.generateSubkeys(key[8:16])
+	c.cipher3.generateSubkeys(key[16:])
+	return c, nil
+}
+
+func (c *tripleDESCipher) BlockSize() int { return BlockSize }
+
+func (c *tripleDESCipher) Encrypt(dst, src []byte) {
+	c.cipher1.Encrypt(dst, src)
+	c.cipher2.Decrypt(dst, dst)
+	c.cipher3.Encrypt(dst, dst)
+}
+
+func (c *tripleDESCipher) Decrypt(dst, src []byte) {
+	c.cipher3.Decrypt(dst, src)
+	c.cipher2.Encrypt(dst, dst)
+	c.cipher1.Decrypt(dst, dst)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/des/const.go b/third_party/gofrontend/libgo/go/crypto/des/const.go
new file mode 100644
index 0000000..2bd485e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/des/const.go
@@ -0,0 +1,139 @@
+// Copyright 2010 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 des implements the Data Encryption Standard (DES) and the
+// Triple Data Encryption Algorithm (TDEA) as defined
+// in U.S. Federal Information Processing Standards Publication 46-3.
+package des
+
+// Used to perform an initial permutation of a 64-bit input block.
+var initialPermutation = [64]byte{
+	6, 14, 22, 30, 38, 46, 54, 62,
+	4, 12, 20, 28, 36, 44, 52, 60,
+	2, 10, 18, 26, 34, 42, 50, 58,
+	0, 8, 16, 24, 32, 40, 48, 56,
+	7, 15, 23, 31, 39, 47, 55, 63,
+	5, 13, 21, 29, 37, 45, 53, 61,
+	3, 11, 19, 27, 35, 43, 51, 59,
+	1, 9, 17, 25, 33, 41, 49, 57,
+}
+
+// Used to perform a final permutation of a 4-bit preoutput block. This is the
+// inverse of initialPermutation
+var finalPermutation = [64]byte{
+	24, 56, 16, 48, 8, 40, 0, 32,
+	25, 57, 17, 49, 9, 41, 1, 33,
+	26, 58, 18, 50, 10, 42, 2, 34,
+	27, 59, 19, 51, 11, 43, 3, 35,
+	28, 60, 20, 52, 12, 44, 4, 36,
+	29, 61, 21, 53, 13, 45, 5, 37,
+	30, 62, 22, 54, 14, 46, 6, 38,
+	31, 63, 23, 55, 15, 47, 7, 39,
+}
+
+// Used to expand an input block of 32 bits, producing an output block of 48
+// bits.
+var expansionFunction = [48]byte{
+	0, 31, 30, 29, 28, 27, 28, 27,
+	26, 25, 24, 23, 24, 23, 22, 21,
+	20, 19, 20, 19, 18, 17, 16, 15,
+	16, 15, 14, 13, 12, 11, 12, 11,
+	10, 9, 8, 7, 8, 7, 6, 5,
+	4, 3, 4, 3, 2, 1, 0, 31,
+}
+
+// Yields a 32-bit output from a 32-bit input
+var permutationFunction = [32]byte{
+	16, 25, 12, 11, 3, 20, 4, 15,
+	31, 17, 9, 6, 27, 14, 1, 22,
+	30, 24, 8, 18, 0, 5, 29, 23,
+	13, 19, 2, 26, 10, 21, 28, 7,
+}
+
+// Used in the key schedule to select 56 bits
+// from a 64-bit input.
+var permutedChoice1 = [56]byte{
+	7, 15, 23, 31, 39, 47, 55, 63,
+	6, 14, 22, 30, 38, 46, 54, 62,
+	5, 13, 21, 29, 37, 45, 53, 61,
+	4, 12, 20, 28, 1, 9, 17, 25,
+	33, 41, 49, 57, 2, 10, 18, 26,
+	34, 42, 50, 58, 3, 11, 19, 27,
+	35, 43, 51, 59, 36, 44, 52, 60,
+}
+
+// Used in the key schedule to produce each subkey by selecting 48 bits from
+// the 56-bit input
+var permutedChoice2 = [48]byte{
+	42, 39, 45, 32, 55, 51, 53, 28,
+	41, 50, 35, 46, 33, 37, 44, 52,
+	30, 48, 40, 49, 29, 36, 43, 54,
+	15, 4, 25, 19, 9, 1, 26, 16,
+	5, 11, 23, 8, 12, 7, 17, 0,
+	22, 3, 10, 14, 6, 20, 27, 24,
+}
+
+// 8 S-boxes composed of 4 rows and 16 columns
+// Used in the DES cipher function
+var sBoxes = [8][4][16]uint8{
+	// S-box 1
+	{
+		{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
+		{0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
+		{4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
+		{15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13},
+	},
+	// S-box 2
+	{
+		{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
+		{3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
+		{0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
+		{13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9},
+	},
+	// S-box 3
+	{
+		{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
+		{13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
+		{13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
+		{1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12},
+	},
+	// S-box 4
+	{
+		{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
+		{13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
+		{10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
+		{3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14},
+	},
+	// S-box 5
+	{
+		{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
+		{14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
+		{4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
+		{11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3},
+	},
+	// S-box 6
+	{
+		{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
+		{10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
+		{9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
+		{4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13},
+	},
+	// S-box 7
+	{
+		{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
+		{13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
+		{1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
+		{6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12},
+	},
+	// S-box 8
+	{
+		{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
+		{1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
+		{7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
+		{2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11},
+	},
+}
+
+// Size of left rotation per round in each half of the key schedule
+var ksRotations = [16]uint8{1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}
diff --git a/third_party/gofrontend/libgo/go/crypto/des/des_test.go b/third_party/gofrontend/libgo/go/crypto/des/des_test.go
new file mode 100644
index 0000000..2bd525a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/des/des_test.go
@@ -0,0 +1,1566 @@
+// 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.
+
+package des
+
+import (
+	"bytes"
+	"testing"
+)
+
+type CryptTest struct {
+	key []byte
+	in  []byte
+	out []byte
+}
+
+// some custom tests for DES
+var encryptDESTests = []CryptTest{
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x8c, 0xa6, 0x4d, 0xe9, 0xc1, 0xb1, 0x23, 0xa7}},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0x35, 0x55, 0x50, 0xb2, 0x15, 0x0e, 0x24, 0x51}},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0x61, 0x7b, 0x3a, 0x0c, 0xe8, 0xf0, 0x71, 0x00}},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		[]byte{0x92, 0x31, 0xf2, 0x36, 0xff, 0x9a, 0xa9, 0x5c}},
+	{
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xca, 0xaa, 0xaf, 0x4d, 0xea, 0xf1, 0xdb, 0xae}},
+	{
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0x73, 0x59, 0xb2, 0x16, 0x3e, 0x4e, 0xdc, 0x58}},
+	{
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0x6d, 0xce, 0x0d, 0xc9, 0x00, 0x65, 0x56, 0xa3}},
+	{
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		[]byte{0x9e, 0x84, 0xc5, 0xf3, 0x17, 0x0f, 0x8e, 0xff}},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xd5, 0xd4, 0x4f, 0xf7, 0x20, 0x68, 0x3d, 0x0d}},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0x59, 0x73, 0x23, 0x56, 0xf3, 0x6f, 0xde, 0x06}},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0x56, 0xcc, 0x09, 0xe7, 0xcf, 0xdc, 0x4c, 0xef}},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		[]byte{0x12, 0xc6, 0x26, 0xaf, 0x05, 0x8b, 0x43, 0x3b}},
+	{
+		[]byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xa6, 0x8c, 0xdc, 0xa9, 0x0c, 0x90, 0x21, 0xf9}},
+	{
+		[]byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0x2a, 0x2b, 0xb0, 0x08, 0xdf, 0x97, 0xc2, 0xf2}},
+	{
+		[]byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0xed, 0x39, 0xd9, 0x50, 0xfa, 0x74, 0xbc, 0xc4}},
+	{
+		[]byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		[]byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		[]byte{0xa9, 0x33, 0xf6, 0x18, 0x30, 0x23, 0xb3, 0x10}},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+		[]byte{0x17, 0x66, 0x8d, 0xfc, 0x72, 0x92, 0x53, 0x2d}},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		[]byte{0xb4, 0xfd, 0x23, 0x16, 0x47, 0xa5, 0xbe, 0xc0}},
+	{
+		[]byte{0x0e, 0x32, 0x92, 0x32, 0xea, 0x6d, 0x0d, 0x73},
+		[]byte{0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+	{
+		[]byte{0x73, 0x65, 0x63, 0x52, 0x33, 0x74, 0x24, 0x3b}, // "secR3t$;"
+		[]byte{0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x31, 0x32}, // "a test12"
+		[]byte{0x37, 0x0d, 0xee, 0x2c, 0x1f, 0xb4, 0xf7, 0xa5}},
+	{
+		[]byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+		[]byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+		[]byte{0x2a, 0x8d, 0x69, 0xde, 0x9d, 0x5f, 0xdf, 0xf9}},
+	{
+		[]byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+		[]byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678"
+		[]byte{0x21, 0xc6, 0x0d, 0xa5, 0x34, 0x24, 0x8b, 0xce}},
+	{
+		[]byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678"
+		[]byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+		[]byte{0x94, 0xd4, 0x43, 0x6b, 0xc3, 0xb5, 0xb6, 0x93}},
+	{
+		[]byte{0x1f, 0x79, 0x90, 0x5f, 0x88, 0x01, 0xc8, 0x88}, // random
+		[]byte{0xc7, 0x46, 0x18, 0x73, 0xaf, 0x48, 0x5f, 0xb3}, // random
+		[]byte{0xb0, 0x93, 0x50, 0x88, 0xf9, 0x92, 0x44, 0x6a}},
+	{
+		[]byte{0xe6, 0xf4, 0xf2, 0xdb, 0x31, 0x42, 0x53, 0x01}, // random
+		[]byte{0xff, 0x3d, 0x25, 0x50, 0x12, 0xe3, 0x4a, 0xc5}, // random
+		[]byte{0x86, 0x08, 0xd3, 0xd1, 0x6c, 0x2f, 0xd2, 0x55}},
+	{
+		[]byte{0x69, 0xc1, 0x9d, 0xc1, 0x15, 0xc5, 0xfb, 0x2b}, // random
+		[]byte{0x1a, 0x22, 0x5c, 0xaf, 0x1f, 0x1d, 0xa3, 0xf9}, // random
+		[]byte{0x64, 0xba, 0x31, 0x67, 0x56, 0x91, 0x1e, 0xa7}},
+	{
+		[]byte{0x6e, 0x5e, 0xe2, 0x47, 0xc4, 0xbf, 0xf6, 0x51}, // random
+		[]byte{0x11, 0xc9, 0x57, 0xff, 0x66, 0x89, 0x0e, 0xf0}, // random
+		[]byte{0x94, 0xc5, 0x35, 0xb2, 0xc5, 0x8b, 0x39, 0x72}},
+}
+
+var weakKeyTests = []CryptTest{
+	{
+		[]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		[]byte{0x55, 0x74, 0xc0, 0xbd, 0x7c, 0xdf, 0xf7, 0x39}, // random
+		nil},
+	{
+		[]byte{0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe},
+		[]byte{0xe8, 0xe1, 0xa7, 0xc1, 0xde, 0x11, 0x89, 0xaa}, // random
+		nil},
+	{
+		[]byte{0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1},
+		[]byte{0x50, 0x6a, 0x4b, 0x94, 0x3b, 0xed, 0x7d, 0xdc}, // random
+		nil},
+	{
+		[]byte{0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e},
+		[]byte{0x88, 0x81, 0x56, 0x38, 0xec, 0x3b, 0x1c, 0x97}, // random
+		nil},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x17, 0xa0, 0x83, 0x62, 0x32, 0xfe, 0x9a, 0x0b}, // random
+		nil},
+	{
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0xca, 0x8f, 0xca, 0x1f, 0x50, 0xc5, 0x7b, 0x49}, // random
+		nil},
+	{
+		[]byte{0xe1, 0xe1, 0xe1, 0xe1, 0xf0, 0xf0, 0xf0, 0xf0},
+		[]byte{0xb1, 0xea, 0xad, 0x7d, 0xe7, 0xc3, 0x7a, 0x43}, // random
+		nil},
+	{
+		[]byte{0x1e, 0x1e, 0x1e, 0x1e, 0x0f, 0x0f, 0x0f, 0x0f},
+		[]byte{0xae, 0x74, 0x7d, 0x6f, 0xef, 0x16, 0xbb, 0x81}, // random
+		nil},
+}
+
+var semiWeakKeyTests = []CryptTest{
+	// key and out contain the semi-weak key pair
+	{
+		[]byte{0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e},
+		[]byte{0x12, 0xfa, 0x31, 0x16, 0xf9, 0xc5, 0x0a, 0xe4}, // random
+		[]byte{0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01}},
+	{
+		[]byte{0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1},
+		[]byte{0xb0, 0x4c, 0x7a, 0xee, 0xd2, 0xe5, 0x4d, 0xb7}, // random
+		[]byte{0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01}},
+	{
+		[]byte{0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe},
+		[]byte{0xa4, 0x81, 0xcd, 0xb1, 0x64, 0x6f, 0xd3, 0xbc}, // random
+		[]byte{0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01}},
+	{
+		[]byte{0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1},
+		[]byte{0xee, 0x27, 0xdd, 0x88, 0x4c, 0x22, 0xcd, 0xce}, // random
+		[]byte{0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e}},
+	{
+		[]byte{0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe},
+		[]byte{0x19, 0x3d, 0xcf, 0x97, 0x70, 0xfb, 0xab, 0xe1}, // random
+		[]byte{0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e}},
+	{
+		[]byte{0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe},
+		[]byte{0x7c, 0x82, 0x69, 0xe4, 0x1e, 0x86, 0x99, 0xd7}, // random
+		[]byte{0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1}},
+}
+
+// some custom tests for TripleDES
+var encryptTripleDESTests = []CryptTest{
+	{
+		[]byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x92, 0x95, 0xb5, 0x9b, 0xb3, 0x84, 0x73, 0x6e}},
+	{
+		[]byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0xc1, 0x97, 0xf5, 0x58, 0x74, 0x8a, 0x20, 0xe7}},
+	{
+		[]byte{
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x3e, 0x68, 0x0a, 0xa7, 0x8b, 0x75, 0xdf, 0x18}},
+	{
+		[]byte{
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		[]byte{0x6d, 0x6a, 0x4a, 0x64, 0x4c, 0x7b, 0x8c, 0x91}},
+	{
+		[]byte{ // "abcdefgh12345678ABCDEFGH"
+			0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+			0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+			0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+		[]byte{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}, // "00000000"
+		[]byte{0xe4, 0x61, 0xb7, 0x59, 0x68, 0x8b, 0xff, 0x66}},
+	{
+		[]byte{ // "abcdefgh12345678ABCDEFGH"
+			0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+			0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+			0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+		[]byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678"
+		[]byte{0xdb, 0xd0, 0x92, 0xde, 0xf8, 0x34, 0xff, 0x58}},
+	{
+		[]byte{ // "abcdefgh12345678ABCDEFGH"
+			0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+			0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+			0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+		[]byte{0xf0, 0xc5, 0x82, 0x22, 0xd3, 0xe6, 0x12, 0xd2}, // random
+		[]byte{0xba, 0xe4, 0x41, 0xb1, 0x3c, 0x37, 0x4d, 0xf4}},
+	{
+		[]byte{ // random
+			0xd3, 0x7d, 0x45, 0xee, 0x22, 0xe9, 0xcf, 0x52,
+			0xf4, 0x65, 0xa2, 0x4f, 0x70, 0xd1, 0x81, 0x8a,
+			0x3d, 0xbe, 0x2f, 0x39, 0xc7, 0x71, 0xd2, 0xe9},
+		[]byte{0x49, 0x53, 0xc3, 0xe9, 0x78, 0xdf, 0x9f, 0xaf}, // random
+		[]byte{0x53, 0x40, 0x51, 0x24, 0xd8, 0x3c, 0xf9, 0x88}},
+	{
+		[]byte{ // random
+			0xcb, 0x10, 0x7d, 0xda, 0x7e, 0x96, 0x57, 0x0a,
+			0xe8, 0xeb, 0xe8, 0x07, 0x8e, 0x87, 0xd3, 0x57,
+			0xb2, 0x61, 0x12, 0xb8, 0x2a, 0x90, 0xb7, 0x2f},
+		[]byte{0xa3, 0xc2, 0x60, 0xb1, 0x0b, 0xb7, 0x28, 0x6e}, // random
+		[]byte{0x56, 0x73, 0x7d, 0xfb, 0xb5, 0xa1, 0xc3, 0xde}},
+}
+
+// NIST Special Publication 800-20, Appendix A
+// Key for use with Table A.1 tests
+var tableA1Key = []byte{
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+}
+
+// Table A.1 Resulting Ciphertext from the Variable Plaintext Known Answer Test
+var tableA1Tests = []CryptTest{
+	{nil, // 0
+		[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x95, 0xf8, 0xa5, 0xe5, 0xdd, 0x31, 0xd9, 0x00}},
+	{nil, // 1
+		[]byte{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xdd, 0x7f, 0x12, 0x1c, 0xa5, 0x01, 0x56, 0x19}},
+	{nil, // 2
+		[]byte{0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x2e, 0x86, 0x53, 0x10, 0x4f, 0x38, 0x34, 0xea}},
+	{nil, // 3
+		[]byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x4b, 0xd3, 0x88, 0xff, 0x6c, 0xd8, 0x1d, 0x4f}},
+	{nil, // 4
+		[]byte{0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x20, 0xb9, 0xe7, 0x67, 0xb2, 0xfb, 0x14, 0x56}},
+	{nil, // 5
+		[]byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x55, 0x57, 0x93, 0x80, 0xd7, 0x71, 0x38, 0xef}},
+	{nil, // 6
+		[]byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x6c, 0xc5, 0xde, 0xfa, 0xaf, 0x04, 0x51, 0x2f}},
+	{nil, // 7
+		[]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x0d, 0x9f, 0x27, 0x9b, 0xa5, 0xd8, 0x72, 0x60}},
+	{nil, // 8
+		[]byte{0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xd9, 0x03, 0x1b, 0x02, 0x71, 0xbd, 0x5a, 0x0a}},
+	{nil, // 9
+		[]byte{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x42, 0x42, 0x50, 0xb3, 0x7c, 0x3d, 0xd9, 0x51}},
+	{nil, // 10
+		[]byte{0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xb8, 0x06, 0x1b, 0x7e, 0xcd, 0x9a, 0x21, 0xe5}},
+	{nil, // 11
+		[]byte{0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xf1, 0x5d, 0x0f, 0x28, 0x6b, 0x65, 0xbd, 0x28}},
+	{nil, // 12
+		[]byte{0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xad, 0xd0, 0xcc, 0x8d, 0x6e, 0x5d, 0xeb, 0xa1}},
+	{nil, // 13
+		[]byte{0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xe6, 0xd5, 0xf8, 0x27, 0x52, 0xad, 0x63, 0xd1}},
+	{nil, // 14
+		[]byte{0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xec, 0xbf, 0xe3, 0xbd, 0x3f, 0x59, 0x1a, 0x5e}},
+	{nil, // 15
+		[]byte{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xf3, 0x56, 0x83, 0x43, 0x79, 0xd1, 0x65, 0xcd}},
+	{nil, // 16
+		[]byte{0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x2b, 0x9f, 0x98, 0x2f, 0x20, 0x03, 0x7f, 0xa9}},
+	{nil, // 17
+		[]byte{0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x88, 0x9d, 0xe0, 0x68, 0xa1, 0x6f, 0x0b, 0xe6}},
+	{nil, // 18
+		[]byte{0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xe1, 0x9e, 0x27, 0x5d, 0x84, 0x6a, 0x12, 0x98}},
+	{nil, // 19
+		[]byte{0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x32, 0x9a, 0x8e, 0xd5, 0x23, 0xd7, 0x1a, 0xec}},
+	{nil, // 20
+		[]byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xe7, 0xfc, 0xe2, 0x25, 0x57, 0xd2, 0x3c, 0x97}},
+	{nil, // 21
+		[]byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x12, 0xa9, 0xf5, 0x81, 0x7f, 0xf2, 0xd6, 0x5d}},
+	{nil, // 22
+		[]byte{0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xa4, 0x84, 0xc3, 0xad, 0x38, 0xdc, 0x9c, 0x19}},
+	{nil, // 23
+		[]byte{0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xfb, 0xe0, 0x0a, 0x8a, 0x1e, 0xf8, 0xad, 0x72}},
+	{nil, // 24
+		[]byte{0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x75, 0x0d, 0x07, 0x94, 0x07, 0x52, 0x13, 0x63}},
+	{nil, // 25
+		[]byte{0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x64, 0xfe, 0xed, 0x9c, 0x72, 0x4c, 0x2f, 0xaf}},
+	{nil, // 26
+		[]byte{0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xf0, 0x2b, 0x26, 0x3b, 0x32, 0x8e, 0x2b, 0x60}},
+	{nil, // 27
+		[]byte{0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x9d, 0x64, 0x55, 0x5a, 0x9a, 0x10, 0xb8, 0x52}},
+	{nil, // 28
+		[]byte{0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xd1, 0x06, 0xff, 0x0b, 0xed, 0x52, 0x55, 0xd7}},
+	{nil, // 29
+		[]byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xe1, 0x65, 0x2c, 0x6b, 0x13, 0x8c, 0x64, 0xa5}},
+	{nil, // 30
+		[]byte{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xe4, 0x28, 0x58, 0x11, 0x86, 0xec, 0x8f, 0x46}},
+	{nil, // 31
+		[]byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xae, 0xb5, 0xf5, 0xed, 0xe2, 0x2d, 0x1a, 0x36}},
+	{nil, // 32
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00},
+		[]byte{0xe9, 0x43, 0xd7, 0x56, 0x8a, 0xec, 0x0c, 0x5c}},
+	{nil, // 33
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00},
+		[]byte{0xdf, 0x98, 0xc8, 0x27, 0x6f, 0x54, 0xb0, 0x4b}},
+	{nil, // 34
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00},
+		[]byte{0xb1, 0x60, 0xe4, 0x68, 0x0f, 0x6c, 0x69, 0x6f}},
+	{nil, // 35
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},
+		[]byte{0xfa, 0x07, 0x52, 0xb0, 0x7d, 0x9c, 0x4a, 0xb8}},
+	{nil, // 36
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00},
+		[]byte{0xca, 0x3a, 0x2b, 0x03, 0x6d, 0xbc, 0x85, 0x02}},
+	{nil, // 37
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00},
+		[]byte{0x5e, 0x09, 0x05, 0x51, 0x7b, 0xb5, 0x9b, 0xcf}},
+	{nil, // 38
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00},
+		[]byte{0x81, 0x4e, 0xeb, 0x3b, 0x91, 0xd9, 0x07, 0x26}},
+	{nil, // 39
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
+		[]byte{0x4d, 0x49, 0xdb, 0x15, 0x32, 0x91, 0x9c, 0x9f}},
+	{nil, // 40
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00},
+		[]byte{0x25, 0xeb, 0x5f, 0xc3, 0xf8, 0xcf, 0x06, 0x21}},
+	{nil, // 41
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00},
+		[]byte{0xab, 0x6a, 0x20, 0xc0, 0x62, 0x0d, 0x1c, 0x6f}},
+	{nil, // 42
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00},
+		[]byte{0x79, 0xe9, 0x0d, 0xbc, 0x98, 0xf9, 0x2c, 0xca}},
+	{nil, // 43
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00},
+		[]byte{0x86, 0x6e, 0xce, 0xdd, 0x80, 0x72, 0xbb, 0x0e}},
+	{nil, // 44
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00},
+		[]byte{0x8b, 0x54, 0x53, 0x6f, 0x2f, 0x3e, 0x64, 0xa8}},
+	{nil, // 45
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00},
+		[]byte{0xea, 0x51, 0xd3, 0x97, 0x55, 0x95, 0xb8, 0x6b}},
+	{nil, // 46
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00},
+		[]byte{0xca, 0xff, 0xc6, 0xac, 0x45, 0x42, 0xde, 0x31}},
+	{nil, // 47
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00},
+		[]byte{0x8d, 0xd4, 0x5a, 0x2d, 0xdf, 0x90, 0x79, 0x6c}},
+	{nil, // 48
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00},
+		[]byte{0x10, 0x29, 0xd5, 0x5e, 0x88, 0x0e, 0xc2, 0xd0}},
+	{nil, // 49
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00},
+		[]byte{0x5d, 0x86, 0xcb, 0x23, 0x63, 0x9d, 0xbe, 0xa9}},
+	{nil, // 50
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00},
+		[]byte{0x1d, 0x1c, 0xa8, 0x53, 0xae, 0x7c, 0x0c, 0x5f}},
+	{nil, // 51
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00},
+		[]byte{0xce, 0x33, 0x23, 0x29, 0x24, 0x8f, 0x32, 0x28}},
+	{nil, // 52
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00},
+		[]byte{0x84, 0x05, 0xd1, 0xab, 0xe2, 0x4f, 0xb9, 0x42}},
+	{nil, // 53
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00},
+		[]byte{0xe6, 0x43, 0xd7, 0x80, 0x90, 0xca, 0x42, 0x07}},
+	{nil, // 54
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00},
+		[]byte{0x48, 0x22, 0x1b, 0x99, 0x37, 0x74, 0x8a, 0x23}},
+	{nil, // 55
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
+		[]byte{0xdd, 0x7c, 0x0b, 0xbd, 0x61, 0xfa, 0xfd, 0x54}},
+	{nil, // 56
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80},
+		[]byte{0x2f, 0xbc, 0x29, 0x1a, 0x57, 0x0d, 0xb5, 0xc4}},
+	{nil, // 57
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40},
+		[]byte{0xe0, 0x7c, 0x30, 0xd7, 0xe4, 0xe2, 0x6e, 0x12}},
+	{nil, // 58
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20},
+		[]byte{0x09, 0x53, 0xe2, 0x25, 0x8e, 0x8e, 0x90, 0xa1}},
+	{nil, // 59
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+		[]byte{0x5b, 0x71, 0x1b, 0xc4, 0xce, 0xeb, 0xf2, 0xee}},
+	{nil, // 60
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08},
+		[]byte{0xcc, 0x08, 0x3f, 0x1e, 0x6d, 0x9e, 0x85, 0xf6}},
+	{nil, // 61
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04},
+		[]byte{0xd2, 0xfd, 0x88, 0x67, 0xd5, 0x0d, 0x2d, 0xfe}},
+	{nil, // 62
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+		[]byte{0x06, 0xe7, 0xea, 0x22, 0xce, 0x92, 0x70, 0x8f}},
+	{nil, // 63
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+		[]byte{0x16, 0x6b, 0x40, 0xb4, 0x4a, 0xba, 0x4b, 0xd6}},
+}
+
+// Plaintext for use with Table A.2 tests
+var tableA2Plaintext = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+// Table A.2 Resulting Ciphertext from the Variable Key Known Answer Test
+var tableA2Tests = []CryptTest{
+	{ // 0
+		[]byte{
+			0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x95, 0xa8, 0xd7, 0x28, 0x13, 0xda, 0xa9, 0x4d}},
+	{ // 1
+		[]byte{
+			0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x0e, 0xec, 0x14, 0x87, 0xdd, 0x8c, 0x26, 0xd5}},
+	{ // 2
+		[]byte{
+			0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x7a, 0xd1, 0x6f, 0xfb, 0x79, 0xc4, 0x59, 0x26}},
+	{ // 3
+		[]byte{
+			0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xd3, 0x74, 0x62, 0x94, 0xca, 0x6a, 0x6c, 0xf3}},
+	{ // 4
+		[]byte{
+			0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x80, 0x9f, 0x5f, 0x87, 0x3c, 0x1f, 0xd7, 0x61}},
+	{ // 5
+		[]byte{
+			0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xc0, 0x2f, 0xaf, 0xfe, 0xc9, 0x89, 0xd1, 0xfc}},
+	{ // 6
+		[]byte{
+			0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x46, 0x15, 0xaa, 0x1d, 0x33, 0xe7, 0x2f, 0x10}},
+	{ // 7
+		[]byte{
+			0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x20, 0x55, 0x12, 0x33, 0x50, 0xc0, 0x08, 0x58}},
+	{ // 8
+		[]byte{
+			0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xdf, 0x3b, 0x99, 0xd6, 0x57, 0x73, 0x97, 0xc8}},
+	{ // 9
+		[]byte{
+			0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x31, 0xfe, 0x17, 0x36, 0x9b, 0x52, 0x88, 0xc9}},
+	{ // 10
+		[]byte{
+			0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xdf, 0xdd, 0x3c, 0xc6, 0x4d, 0xae, 0x16, 0x42}},
+	{ // 11
+		[]byte{
+			0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x17, 0x8c, 0x83, 0xce, 0x2b, 0x39, 0x9d, 0x94}},
+	{ // 12
+		[]byte{
+			0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x50, 0xf6, 0x36, 0x32, 0x4a, 0x9b, 0x7f, 0x80}},
+	{ // 13
+		[]byte{
+			0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xa8, 0x46, 0x8e, 0xe3, 0xbc, 0x18, 0xf0, 0x6d}},
+	{ // 14
+		[]byte{
+			0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xa2, 0xdc, 0x9e, 0x92, 0xfd, 0x3c, 0xde, 0x92}},
+	{ // 15
+		[]byte{
+			0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xca, 0xc0, 0x9f, 0x79, 0x7d, 0x03, 0x12, 0x87}},
+	{ // 16
+		[]byte{
+			0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x90, 0xba, 0x68, 0x0b, 0x22, 0xae, 0xb5, 0x25}},
+	{ // 17
+		[]byte{
+			0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xce, 0x7a, 0x24, 0xf3, 0x50, 0xe2, 0x80, 0xb6}},
+	{ // 18
+		[]byte{
+			0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x88, 0x2b, 0xff, 0x0a, 0xa0, 0x1a, 0x0b, 0x87}},
+	{ // 19
+		[]byte{
+			0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xc2}},
+	{ // 20
+		[]byte{
+			0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xc7, 0x15, 0x16, 0xc2, 0x9c, 0x75, 0xd1, 0x70}},
+	{ // 21
+		[]byte{
+			0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x51, 0x99, 0xc2, 0x9a, 0x52, 0xc9, 0xf0, 0x59}},
+	{ // 22
+		[]byte{
+			0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xc2, 0x2f, 0x0a, 0x29, 0x4a, 0x71, 0xf2, 0x9f}},
+	{ // 23
+		[]byte{
+			0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xee, 0x37, 0x14, 0x83, 0x71, 0x4c, 0x02, 0xea}},
+	{ // 24
+		[]byte{
+			0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xa8, 0x1f, 0xbd, 0x44, 0x8f, 0x9e, 0x52, 0x2f}},
+	{ // 25
+		[]byte{
+			0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x4f, 0x64, 0x4c, 0x92, 0xe1, 0x92, 0xdf, 0xed}},
+	{ // 26
+		[]byte{
+			0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x1a, 0xfa, 0x9a, 0x66, 0xa6, 0xdf, 0x92, 0xae}},
+	{ // 27
+		[]byte{
+			0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xb3, 0xc1, 0xcc, 0x71, 0x5c, 0xb8, 0x79, 0xd8}},
+	{ // 28
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x19, 0xd0, 0x32, 0xe6, 0x4a, 0xb0, 0xbd, 0x8b}},
+	{ // 29
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x3c, 0xfa, 0xa7, 0xa7, 0xdc, 0x87, 0x20, 0xdc}},
+	{ // 30
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0xb7, 0x26, 0x5f, 0x7f, 0x44, 0x7a, 0xc6, 0xf3}},
+	{ // 31
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x9d, 0xb7, 0x3b, 0x3c, 0x0d, 0x16, 0x3f, 0x54}},
+	{ // 32
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x81, 0x81, 0xb6, 0x5b, 0xab, 0xf4, 0xa9, 0x75}},
+	{ // 33
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x93, 0xc9, 0xb6, 0x40, 0x42, 0xea, 0xa2, 0x40}},
+	{ // 34
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01},
+		nil,
+		[]byte{0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92}},
+	{ // 35
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01},
+		nil,
+		[]byte{0x86, 0x38, 0x80, 0x9e, 0x87, 0x87, 0x87, 0xa0}},
+	{ // 36
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01},
+		nil,
+		[]byte{0x41, 0xb9, 0xa7, 0x9a, 0xf7, 0x9a, 0xc2, 0x08}},
+	{ // 37
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01},
+		nil,
+		[]byte{0x7a, 0x9b, 0xe4, 0x2f, 0x20, 0x09, 0xa8, 0x92}},
+	{ // 38
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01},
+		nil,
+		[]byte{0x29, 0x03, 0x8d, 0x56, 0xba, 0x6d, 0x27, 0x45}},
+	{ // 39
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01},
+		nil,
+		[]byte{0x54, 0x95, 0xc6, 0xab, 0xf1, 0xe5, 0xdf, 0x51}},
+	{ // 40
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01},
+		nil,
+		[]byte{0xae, 0x13, 0xdb, 0xd5, 0x61, 0x48, 0x89, 0x33}},
+	{ // 41
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01},
+		nil,
+		[]byte{0x02, 0x4d, 0x1f, 0xfa, 0x89, 0x04, 0xe3, 0x89}},
+	{ // 42
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01},
+		nil,
+		[]byte{0xd1, 0x39, 0x97, 0x12, 0xf9, 0x9b, 0xf0, 0x2e}},
+	{ // 43
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01},
+		nil,
+		[]byte{0x14, 0xc1, 0xd7, 0xc1, 0xcf, 0xfe, 0xc7, 0x9e}},
+	{ // 44
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01},
+		nil,
+		[]byte{0x1d, 0xe5, 0x27, 0x9d, 0xae, 0x3b, 0xed, 0x6f}},
+	{ // 45
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01},
+		nil,
+		[]byte{0xe9, 0x41, 0xa3, 0x3f, 0x85, 0x50, 0x13, 0x03}},
+	{ // 46
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01},
+		nil,
+		[]byte{0xda, 0x99, 0xdb, 0xbc, 0x9a, 0x03, 0xf3, 0x79}},
+	{ // 47
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01},
+		nil,
+		[]byte{0xb7, 0xfc, 0x92, 0xf9, 0x1d, 0x8e, 0x92, 0xe9}},
+	{ // 48
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01},
+		nil,
+		[]byte{0xae, 0x8e, 0x5c, 0xaa, 0x3c, 0xa0, 0x4e, 0x85}},
+	{ // 49
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80},
+		nil,
+		[]byte{0x9c, 0xc6, 0x2d, 0xf4, 0x3b, 0x6e, 0xed, 0x74}},
+	{ // 50
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40},
+		nil,
+		[]byte{0xd8, 0x63, 0xdb, 0xb5, 0xc5, 0x9a, 0x91, 0xa0}},
+	{ // 50
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20},
+		nil,
+		[]byte{0xa1, 0xab, 0x21, 0x90, 0x54, 0x5b, 0x91, 0xd7}},
+	{ // 52
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10},
+		nil,
+		[]byte{0x08, 0x75, 0x04, 0x1e, 0x64, 0xc5, 0x70, 0xf7}},
+	{ // 53
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08},
+		nil,
+		[]byte{0x5a, 0x59, 0x45, 0x28, 0xbe, 0xbe, 0xf1, 0xcc}},
+	{ // 54
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04},
+		nil,
+		[]byte{0xfc, 0xdb, 0x32, 0x91, 0xde, 0x21, 0xf0, 0xc0}},
+	{ // 55
+		[]byte{
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02},
+		nil,
+		[]byte{0x86, 0x9e, 0xfd, 0x7f, 0x9f, 0x26, 0x5a, 0x09}},
+}
+
+// Plaintext for use with Table A.3 tests
+var tableA3Plaintext = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+// Table A.3 Values To Be Used for the Permutation Operation Known Answer Test
+var tableA3Tests = []CryptTest{
+	{ // 0
+		[]byte{
+			0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
+			0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
+			0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
+		},
+		nil,
+		[]byte{0x88, 0xd5, 0x5e, 0x54, 0xf5, 0x4c, 0x97, 0xb4}},
+	{ // 1
+		[]byte{
+			0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+			0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+			0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+		},
+		nil,
+		[]byte{0x0c, 0x0c, 0xc0, 0x0c, 0x83, 0xea, 0x48, 0xfd}},
+	{ // 2
+		[]byte{
+			0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20,
+			0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20,
+			0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20,
+		},
+		nil,
+		[]byte{0x83, 0xbc, 0x8e, 0xf3, 0xa6, 0x57, 0x01, 0x83}},
+	{ // 3
+		[]byte{
+			0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+			0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+			0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+		},
+		nil,
+		[]byte{0xdf, 0x72, 0x5d, 0xca, 0xd9, 0x4e, 0xa2, 0xe9}},
+	{ // 4
+		[]byte{
+			0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01,
+			0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01,
+			0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0xe6, 0x52, 0xb5, 0x3b, 0x55, 0x0b, 0xe8, 0xb0}},
+	{ // 5
+		[]byte{
+			0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01,
+			0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01,
+			0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0xaf, 0x52, 0x71, 0x20, 0xc4, 0x85, 0xcb, 0xb0}},
+	{ // 6
+		[]byte{
+			0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01,
+			0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01,
+			0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0x0f, 0x04, 0xce, 0x39, 0x3d, 0xb9, 0x26, 0xd5}},
+	{ // 7
+		[]byte{
+			0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01,
+			0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01,
+			0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0xc9, 0xf0, 0x0f, 0xfc, 0x74, 0x07, 0x90, 0x67}},
+	{ // 8
+		[]byte{
+			0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01,
+			0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01,
+			0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0x7c, 0xfd, 0x82, 0xa5, 0x93, 0x25, 0x2b, 0x4e}},
+	{ // 9
+		[]byte{
+			0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01,
+			0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01,
+			0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0xcb, 0x49, 0xa2, 0xf9, 0xe9, 0x13, 0x63, 0xe3}},
+	{ // 10
+		[]byte{
+			0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40,
+			0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40,
+			0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40,
+		},
+		nil,
+		[]byte{0x00, 0xb5, 0x88, 0xbe, 0x70, 0xd2, 0x3f, 0x56}},
+	{ // 11
+		[]byte{
+			0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40,
+			0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40,
+			0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40,
+		},
+		nil,
+		[]byte{0x40, 0x6a, 0x9a, 0x6a, 0xb4, 0x33, 0x99, 0xae}},
+	{ // 12
+		[]byte{
+			0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01,
+			0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01,
+			0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0x6c, 0xb7, 0x73, 0x61, 0x1d, 0xca, 0x9a, 0xda}},
+	{ // 13
+		[]byte{
+			0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01,
+			0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01,
+			0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0x67, 0xfd, 0x21, 0xc1, 0x7d, 0xbb, 0x5d, 0x70}},
+	{ // 14
+		[]byte{
+			0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+			0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+			0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0x95, 0x92, 0xcb, 0x41, 0x10, 0x43, 0x07, 0x87}},
+	{ // 15
+		[]byte{
+			0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20,
+			0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20,
+			0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20,
+		},
+		nil,
+		[]byte{0xa6, 0xb7, 0xff, 0x68, 0xa3, 0x18, 0xdd, 0xd3}},
+	{ // 16
+		[]byte{
+			0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01,
+			0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01,
+			0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0x4d, 0x10, 0x21, 0x96, 0xc9, 0x14, 0xca, 0x16}},
+	{ // 17
+		[]byte{
+			0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01,
+			0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01,
+			0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01,
+		},
+		nil,
+		[]byte{0x2d, 0xfa, 0x9f, 0x45, 0x73, 0x59, 0x49, 0x65}},
+	{ // 18
+		[]byte{
+			0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01,
+			0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01,
+			0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0xb4, 0x66, 0x04, 0x81, 0x6c, 0x0e, 0x07, 0x74}},
+	{ // 19
+		[]byte{
+			0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01,
+			0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01,
+			0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01,
+		},
+		nil,
+		[]byte{0x6e, 0x7e, 0x62, 0x21, 0xa4, 0xf3, 0x4e, 0x87}},
+	{ // 20
+		[]byte{
+			0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01,
+			0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01,
+			0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0xaa, 0x85, 0xe7, 0x46, 0x43, 0x23, 0x31, 0x99}},
+	{ // 21
+		[]byte{
+			0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01,
+			0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01,
+			0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01,
+		},
+		nil,
+		[]byte{0x2e, 0x5a, 0x19, 0xdb, 0x4d, 0x19, 0x62, 0xd6}},
+	{ // 22
+		[]byte{
+			0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01,
+			0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01,
+			0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01,
+		},
+		nil,
+		[]byte{0x23, 0xa8, 0x66, 0xa8, 0x09, 0xd3, 0x08, 0x94}},
+	{ // 23
+		[]byte{
+			0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01,
+			0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01,
+			0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0xd8, 0x12, 0xd9, 0x61, 0xf0, 0x17, 0xd3, 0x20}},
+	{ // 24
+		[]byte{
+			0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b,
+			0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b,
+			0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b,
+		},
+		nil,
+		[]byte{0x05, 0x56, 0x05, 0x81, 0x6e, 0x58, 0x60, 0x8f}},
+	{ // 25
+		[]byte{
+			0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01,
+			0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01,
+			0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0xab, 0xd8, 0x8e, 0x8b, 0x1b, 0x77, 0x16, 0xf1}},
+	{ // 26
+		[]byte{
+			0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02,
+			0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02,
+			0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02,
+		},
+		nil,
+		[]byte{0x53, 0x7a, 0xc9, 0x5b, 0xe6, 0x9d, 0xa1, 0xe1}},
+	{ // 27
+		[]byte{
+			0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08,
+			0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08,
+			0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08,
+		},
+		nil,
+		[]byte{0xae, 0xd0, 0xf6, 0xae, 0x3c, 0x25, 0xcd, 0xd8}},
+	{ // 28
+		[]byte{
+			0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04,
+			0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04,
+			0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04,
+		},
+		nil,
+		[]byte{0xb3, 0xe3, 0x5a, 0x5e, 0xe5, 0x3e, 0x7b, 0x8d}},
+	{ // 29
+		[]byte{
+			0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04,
+			0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04,
+			0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04,
+		},
+		nil,
+		[]byte{0x61, 0xc7, 0x9c, 0x71, 0x92, 0x1a, 0x2e, 0xf8}},
+	{ // 30
+		[]byte{
+			0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01,
+			0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01,
+			0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01,
+		},
+		nil,
+		[]byte{0xe2, 0xf5, 0x72, 0x8f, 0x09, 0x95, 0x01, 0x3c}},
+	{ // 31
+		[]byte{
+			0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01,
+			0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01,
+			0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01,
+		},
+		nil,
+		[]byte{0x1a, 0xea, 0xc3, 0x9a, 0x61, 0xf0, 0xa4, 0x64}},
+}
+
+// Table A.4 Values To Be Used for the Substitution Table Known Answer Test
+var tableA4Tests = []CryptTest{
+	{ // 0
+		[]byte{
+			0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57,
+			0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57,
+			0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57},
+		[]byte{0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42},
+		[]byte{0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b}},
+	{ // 1
+		[]byte{
+			0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e,
+			0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e,
+			0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e},
+		[]byte{0x5c, 0xd5, 0x4c, 0xa8, 0x3d, 0xef, 0x57, 0xda},
+		[]byte{0x7a, 0x38, 0x9d, 0x10, 0x35, 0x4b, 0xd2, 0x71}},
+	{ // 2
+		[]byte{
+			0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86,
+			0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86,
+			0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86},
+		[]byte{0x02, 0x48, 0xd4, 0x38, 0x06, 0xf6, 0x71, 0x72},
+		[]byte{0x86, 0x8e, 0xbb, 0x51, 0xca, 0xb4, 0x59, 0x9a}},
+	{ // 3
+		[]byte{
+			0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e,
+			0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e,
+			0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e},
+		[]byte{0x51, 0x45, 0x4b, 0x58, 0x2d, 0xdf, 0x44, 0x0a},
+		[]byte{0x71, 0x78, 0x87, 0x6e, 0x01, 0xf1, 0x9b, 0x2a}},
+	{ // 4
+		[]byte{
+			0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6,
+			0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6,
+			0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6},
+		[]byte{0x42, 0xfd, 0x44, 0x30, 0x59, 0x57, 0x7f, 0xa2},
+		[]byte{0xaf, 0x37, 0xfb, 0x42, 0x1f, 0x8c, 0x40, 0x95}},
+	{ // 5
+		[]byte{
+			0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce,
+			0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce,
+			0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce},
+		[]byte{0x05, 0x9b, 0x5e, 0x08, 0x51, 0xcf, 0x14, 0x3a},
+		[]byte{0x86, 0xa5, 0x60, 0xf1, 0x0e, 0xc6, 0xd8, 0x5b}},
+	{ // 6
+		[]byte{
+			0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6,
+			0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6,
+			0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6},
+		[]byte{0x07, 0x56, 0xd8, 0xe0, 0x77, 0x47, 0x61, 0xd2},
+		[]byte{0x0c, 0xd3, 0xda, 0x02, 0x00, 0x21, 0xdc, 0x09}},
+	{ // 7
+		[]byte{
+			0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe,
+			0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe,
+			0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe},
+		[]byte{0x76, 0x25, 0x14, 0xb8, 0x29, 0xbf, 0x48, 0x6a},
+		[]byte{0xea, 0x67, 0x6b, 0x2c, 0xb7, 0xdb, 0x2b, 0x7a}},
+	{ // 8
+		[]byte{
+			0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16,
+			0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16,
+			0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16},
+		[]byte{0x3b, 0xdd, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
+		[]byte{0xdf, 0xd6, 0x4a, 0x81, 0x5c, 0xaf, 0x1a, 0x0f}},
+	{ // 9
+		[]byte{
+			0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+			0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+			0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f},
+		[]byte{0x26, 0x95, 0x5f, 0x68, 0x35, 0xaf, 0x60, 0x9a},
+		[]byte{0x5c, 0x51, 0x3c, 0x9c, 0x48, 0x86, 0xc0, 0x88}},
+	{ // 10
+		[]byte{
+			0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46,
+			0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46,
+			0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46},
+		[]byte{0x16, 0x4d, 0x5e, 0x40, 0x4f, 0x27, 0x52, 0x32},
+		[]byte{0x0a, 0x2a, 0xee, 0xae, 0x3f, 0xf4, 0xab, 0x77}},
+	{ // 11
+		[]byte{
+			0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e,
+			0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e,
+			0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e},
+		[]byte{0x6b, 0x05, 0x6e, 0x18, 0x75, 0x9f, 0x5c, 0xca},
+		[]byte{0xef, 0x1b, 0xf0, 0x3e, 0x5d, 0xfa, 0x57, 0x5a}},
+	{ // 12
+		[]byte{
+			0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+			0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+			0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76},
+		[]byte{0x00, 0x4b, 0xd6, 0xef, 0x09, 0x17, 0x60, 0x62},
+		[]byte{0x88, 0xbf, 0x0d, 0xb6, 0xd7, 0x0d, 0xee, 0x56}},
+	{ // 13
+		[]byte{
+			0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07,
+			0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07,
+			0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07},
+		[]byte{0x48, 0x0d, 0x39, 0x00, 0x6e, 0xe7, 0x62, 0xf2},
+		[]byte{0xa1, 0xf9, 0x91, 0x55, 0x41, 0x02, 0x0b, 0x56}},
+	{ // 14
+		[]byte{
+			0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f,
+			0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f,
+			0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f},
+		[]byte{0x43, 0x75, 0x40, 0xc8, 0x69, 0x8f, 0x3c, 0xfa},
+		[]byte{0x6f, 0xbf, 0x1c, 0xaf, 0xcf, 0xfd, 0x05, 0x56}},
+	{ // 15
+		[]byte{
+			0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7,
+			0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7,
+			0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7},
+		[]byte{0x07, 0x2d, 0x43, 0xa0, 0x77, 0x07, 0x52, 0x92},
+		[]byte{0x2f, 0x22, 0xe4, 0x9b, 0xab, 0x7c, 0xa1, 0xac}},
+	{ // 16
+		[]byte{
+			0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf,
+			0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf,
+			0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf},
+		[]byte{0x02, 0xfe, 0x55, 0x77, 0x81, 0x17, 0xf1, 0x2a},
+		[]byte{0x5a, 0x6b, 0x61, 0x2c, 0xc2, 0x6c, 0xce, 0x4a}},
+	{ // 17
+		[]byte{
+			0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6,
+			0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6,
+			0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6},
+		[]byte{0x1d, 0x9d, 0x5c, 0x50, 0x18, 0xf7, 0x28, 0xc2},
+		[]byte{0x5f, 0x4c, 0x03, 0x8e, 0xd1, 0x2b, 0x2e, 0x41}},
+	{ // 18
+		[]byte{
+			0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef,
+			0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef,
+			0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef},
+		[]byte{0x30, 0x55, 0x32, 0x28, 0x6d, 0x6f, 0x29, 0x5a},
+		[]byte{0x63, 0xfa, 0xc0, 0xd0, 0x34, 0xd9, 0xf7, 0x93}},
+}
+
+func newCipher(key []byte) *desCipher {
+	c, err := NewCipher(key)
+	if err != nil {
+		panic("NewCipher failed: " + err.Error())
+	}
+	return c.(*desCipher)
+}
+
+// Use the known weak keys to test DES implementation
+func TestWeakKeys(t *testing.T) {
+	for i, tt := range weakKeyTests {
+		var encrypt = func(in []byte) (out []byte) {
+			c := newCipher(tt.key)
+			out = make([]byte, len(in))
+			encryptBlock(c.subkeys[:], out, in)
+			return
+		}
+
+		// Encrypting twice with a DES weak
+		// key should reproduce the original input
+		result := encrypt(tt.in)
+		result = encrypt(result)
+
+		if !bytes.Equal(result, tt.in) {
+			t.Errorf("#%d: result: %x want: %x", i, result, tt.in)
+		}
+	}
+}
+
+// Use the known semi-weak key pairs to test DES implementation
+func TestSemiWeakKeyPairs(t *testing.T) {
+	for i, tt := range semiWeakKeyTests {
+		var encrypt = func(key, in []byte) (out []byte) {
+			c := newCipher(key)
+			out = make([]byte, len(in))
+			encryptBlock(c.subkeys[:], out, in)
+			return
+		}
+
+		// Encrypting with one member of the semi-weak pair
+		// and then encrypting the result with the other member
+		// should reproduce the original input.
+		result := encrypt(tt.key, tt.in)
+		result = encrypt(tt.out, result)
+
+		if !bytes.Equal(result, tt.in) {
+			t.Errorf("#%d: result: %x want: %x", i, result, tt.in)
+		}
+	}
+}
+
+func TestDESEncryptBlock(t *testing.T) {
+	for i, tt := range encryptDESTests {
+		c := newCipher(tt.key)
+		out := make([]byte, len(tt.in))
+		encryptBlock(c.subkeys[:], out, tt.in)
+
+		if !bytes.Equal(out, tt.out) {
+			t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+		}
+	}
+}
+
+func TestDESDecryptBlock(t *testing.T) {
+	for i, tt := range encryptDESTests {
+		c := newCipher(tt.key)
+		plain := make([]byte, len(tt.in))
+		decryptBlock(c.subkeys[:], plain, tt.out)
+
+		if !bytes.Equal(plain, tt.in) {
+			t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+		}
+	}
+}
+
+func TestEncryptTripleDES(t *testing.T) {
+	for i, tt := range encryptTripleDESTests {
+		c, _ := NewTripleDESCipher(tt.key)
+		out := make([]byte, len(tt.in))
+		c.Encrypt(out, tt.in)
+
+		if !bytes.Equal(out, tt.out) {
+			t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+		}
+	}
+}
+
+func TestDecryptTripleDES(t *testing.T) {
+	for i, tt := range encryptTripleDESTests {
+		c, _ := NewTripleDESCipher(tt.key)
+
+		plain := make([]byte, len(tt.in))
+		c.Decrypt(plain, tt.out)
+
+		if !bytes.Equal(plain, tt.in) {
+			t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+		}
+	}
+}
+
+// Defined in Pub 800-20
+func TestVariablePlaintextKnownAnswer(t *testing.T) {
+	for i, tt := range tableA1Tests {
+		c, _ := NewTripleDESCipher(tableA1Key)
+
+		out := make([]byte, len(tt.in))
+		c.Encrypt(out, tt.in)
+
+		if !bytes.Equal(out, tt.out) {
+			t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+		}
+	}
+}
+
+// Defined in Pub 800-20
+func TestVariableCiphertextKnownAnswer(t *testing.T) {
+	for i, tt := range tableA1Tests {
+		c, _ := NewTripleDESCipher(tableA1Key)
+
+		plain := make([]byte, len(tt.out))
+		c.Decrypt(plain, tt.out)
+
+		if !bytes.Equal(plain, tt.in) {
+			t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+		}
+	}
+}
+
+// Defined in Pub 800-20
+// Encrypting the Table A.1 ciphertext with the
+// 0x01... key produces the original plaintext
+func TestInversePermutationKnownAnswer(t *testing.T) {
+	for i, tt := range tableA1Tests {
+		c, _ := NewTripleDESCipher(tableA1Key)
+
+		plain := make([]byte, len(tt.in))
+		c.Encrypt(plain, tt.out)
+
+		if !bytes.Equal(plain, tt.in) {
+			t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+		}
+	}
+}
+
+// Defined in Pub 800-20
+// Decrypting the Table A.1 plaintext with the
+// 0x01... key produces the corresponding ciphertext
+func TestInitialPermutationKnownAnswer(t *testing.T) {
+	for i, tt := range tableA1Tests {
+		c, _ := NewTripleDESCipher(tableA1Key)
+
+		out := make([]byte, len(tt.in))
+		c.Decrypt(out, tt.in)
+
+		if !bytes.Equal(out, tt.out) {
+			t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+		}
+	}
+}
+
+// Defined in Pub 800-20
+func TestVariableKeyKnownAnswerEncrypt(t *testing.T) {
+	for i, tt := range tableA2Tests {
+		c, _ := NewTripleDESCipher(tt.key)
+
+		out := make([]byte, len(tableA2Plaintext))
+		c.Encrypt(out, tableA2Plaintext)
+
+		if !bytes.Equal(out, tt.out) {
+			t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+		}
+	}
+}
+
+// Defined in Pub 800-20
+func TestVariableKeyKnownAnswerDecrypt(t *testing.T) {
+	for i, tt := range tableA2Tests {
+		c, _ := NewTripleDESCipher(tt.key)
+
+		out := make([]byte, len(tt.out))
+		c.Decrypt(out, tt.out)
+
+		if !bytes.Equal(out, tableA2Plaintext) {
+			t.Errorf("#%d: result: %x want: %x", i, out, tableA2Plaintext)
+		}
+	}
+}
+
+// Defined in Pub 800-20
+func TestPermutationOperationKnownAnswerEncrypt(t *testing.T) {
+	for i, tt := range tableA3Tests {
+		c, _ := NewTripleDESCipher(tt.key)
+
+		out := make([]byte, len(tableA3Plaintext))
+		c.Encrypt(out, tableA3Plaintext)
+
+		if !bytes.Equal(out, tt.out) {
+			t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+		}
+	}
+}
+
+// Defined in Pub 800-20
+func TestPermutationOperationKnownAnswerDecrypt(t *testing.T) {
+	for i, tt := range tableA3Tests {
+		c, _ := NewTripleDESCipher(tt.key)
+
+		out := make([]byte, len(tt.out))
+		c.Decrypt(out, tt.out)
+
+		if !bytes.Equal(out, tableA3Plaintext) {
+			t.Errorf("#%d: result: %x want: %x", i, out, tableA3Plaintext)
+		}
+	}
+}
+
+// Defined in Pub 800-20
+func TestSubstitutionTableKnownAnswerEncrypt(t *testing.T) {
+	for i, tt := range tableA4Tests {
+		c, _ := NewTripleDESCipher(tt.key)
+
+		out := make([]byte, len(tt.in))
+		c.Encrypt(out, tt.in)
+
+		if !bytes.Equal(out, tt.out) {
+			t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+		}
+	}
+}
+
+// Defined in Pub 800-20
+func TestSubstitutionTableKnownAnswerDecrypt(t *testing.T) {
+	for i, tt := range tableA4Tests {
+		c, _ := NewTripleDESCipher(tt.key)
+
+		out := make([]byte, len(tt.out))
+		c.Decrypt(out, tt.out)
+
+		if !bytes.Equal(out, tt.in) {
+			t.Errorf("#%d: result: %x want: %x", i, out, tt.in)
+		}
+	}
+}
+
+func TestInitialPermute(t *testing.T) {
+	for i := uint(0); i < 64; i++ {
+		bit := uint64(1) << i
+		got := permuteInitialBlock(bit)
+		want := uint64(1) << finalPermutation[63-i]
+		if got != want {
+			t.Errorf("permute(%x) = %x, want %x", bit, got, want)
+		}
+	}
+}
+
+func TestFinalPermute(t *testing.T) {
+	for i := uint(0); i < 64; i++ {
+		bit := uint64(1) << i
+		got := permuteFinalBlock(bit)
+		want := uint64(1) << initialPermutation[63-i]
+		if got != want {
+			t.Errorf("permute(%x) = %x, want %x", bit, got, want)
+		}
+	}
+}
+
+func TestExpandBlock(t *testing.T) {
+	for i := uint(0); i < 32; i++ {
+		bit := uint32(1) << i
+		got := expandBlock(bit)
+		want := permuteBlock(uint64(bit), expansionFunction[:])
+		if got != want {
+			t.Errorf("expand(%x) = %x, want %x", bit, got, want)
+		}
+	}
+}
+
+func BenchmarkEncrypt(b *testing.B) {
+	tt := encryptDESTests[0]
+	c, err := NewCipher(tt.key)
+	if err != nil {
+		b.Fatal("NewCipher:", err)
+	}
+	out := make([]byte, len(tt.in))
+	b.SetBytes(int64(len(out)))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		c.Encrypt(out, tt.in)
+	}
+}
+
+func BenchmarkDecrypt(b *testing.B) {
+	tt := encryptDESTests[0]
+	c, err := NewCipher(tt.key)
+	if err != nil {
+		b.Fatal("NewCipher:", err)
+	}
+	out := make([]byte, len(tt.out))
+	b.SetBytes(int64(len(out)))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		c.Decrypt(out, tt.out)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/dsa/dsa.go b/third_party/gofrontend/libgo/go/crypto/dsa/dsa.go
new file mode 100644
index 0000000..b7565a6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/dsa/dsa.go
@@ -0,0 +1,278 @@
+// 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.
+
+// Package dsa implements the Digital Signature Algorithm, as defined in FIPS 186-3.
+package dsa
+
+import (
+	"errors"
+	"io"
+	"math/big"
+)
+
+// Parameters represents the domain parameters for a key. These parameters can
+// be shared across many keys. The bit length of Q must be a multiple of 8.
+type Parameters struct {
+	P, Q, G *big.Int
+}
+
+// PublicKey represents a DSA public key.
+type PublicKey struct {
+	Parameters
+	Y *big.Int
+}
+
+// PrivateKey represents a DSA private key.
+type PrivateKey struct {
+	PublicKey
+	X *big.Int
+}
+
+// ErrInvalidPublicKey results when a public key is not usable by this code.
+// FIPS is quite strict about the format of DSA keys, but other code may be
+// less so. Thus, when using keys which may have been generated by other code,
+// this error must be handled.
+var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key")
+
+// ParameterSizes is a enumeration of the acceptable bit lengths of the primes
+// in a set of DSA parameters. See FIPS 186-3, section 4.2.
+type ParameterSizes int
+
+const (
+	L1024N160 ParameterSizes = iota
+	L2048N224
+	L2048N256
+	L3072N256
+)
+
+// numMRTests is the number of Miller-Rabin primality tests that we perform. We
+// pick the largest recommended number from table C.1 of FIPS 186-3.
+const numMRTests = 64
+
+// GenerateParameters puts a random, valid set of DSA parameters into params.
+// This function takes many seconds, even on fast machines.
+func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) (err error) {
+	// This function doesn't follow FIPS 186-3 exactly in that it doesn't
+	// use a verification seed to generate the primes. The verification
+	// seed doesn't appear to be exported or used by other code and
+	// omitting it makes the code cleaner.
+
+	var L, N int
+	switch sizes {
+	case L1024N160:
+		L = 1024
+		N = 160
+	case L2048N224:
+		L = 2048
+		N = 224
+	case L2048N256:
+		L = 2048
+		N = 256
+	case L3072N256:
+		L = 3072
+		N = 256
+	default:
+		return errors.New("crypto/dsa: invalid ParameterSizes")
+	}
+
+	qBytes := make([]byte, N/8)
+	pBytes := make([]byte, L/8)
+
+	q := new(big.Int)
+	p := new(big.Int)
+	rem := new(big.Int)
+	one := new(big.Int)
+	one.SetInt64(1)
+
+GeneratePrimes:
+	for {
+		_, err = io.ReadFull(rand, qBytes)
+		if err != nil {
+			return
+		}
+
+		qBytes[len(qBytes)-1] |= 1
+		qBytes[0] |= 0x80
+		q.SetBytes(qBytes)
+
+		if !q.ProbablyPrime(numMRTests) {
+			continue
+		}
+
+		for i := 0; i < 4*L; i++ {
+			_, err = io.ReadFull(rand, pBytes)
+			if err != nil {
+				return
+			}
+
+			pBytes[len(pBytes)-1] |= 1
+			pBytes[0] |= 0x80
+
+			p.SetBytes(pBytes)
+			rem.Mod(p, q)
+			rem.Sub(rem, one)
+			p.Sub(p, rem)
+			if p.BitLen() < L {
+				continue
+			}
+
+			if !p.ProbablyPrime(numMRTests) {
+				continue
+			}
+
+			params.P = p
+			params.Q = q
+			break GeneratePrimes
+		}
+	}
+
+	h := new(big.Int)
+	h.SetInt64(2)
+	g := new(big.Int)
+
+	pm1 := new(big.Int).Sub(p, one)
+	e := new(big.Int).Div(pm1, q)
+
+	for {
+		g.Exp(h, e, p)
+		if g.Cmp(one) == 0 {
+			h.Add(h, one)
+			continue
+		}
+
+		params.G = g
+		return
+	}
+}
+
+// GenerateKey generates a public&private key pair. The Parameters of the
+// PrivateKey must already be valid (see GenerateParameters).
+func GenerateKey(priv *PrivateKey, rand io.Reader) error {
+	if priv.P == nil || priv.Q == nil || priv.G == nil {
+		return errors.New("crypto/dsa: parameters not set up before generating key")
+	}
+
+	x := new(big.Int)
+	xBytes := make([]byte, priv.Q.BitLen()/8)
+
+	for {
+		_, err := io.ReadFull(rand, xBytes)
+		if err != nil {
+			return err
+		}
+		x.SetBytes(xBytes)
+		if x.Sign() != 0 && x.Cmp(priv.Q) < 0 {
+			break
+		}
+	}
+
+	priv.X = x
+	priv.Y = new(big.Int)
+	priv.Y.Exp(priv.G, x, priv.P)
+	return nil
+}
+
+// fermatInverse calculates the inverse of k in GF(P) using Fermat's method.
+// This has better constant-time properties than Euclid's method (implemented
+// in math/big.Int.ModInverse) although math/big itself isn't strictly
+// constant-time so it's not perfect.
+func fermatInverse(k, P *big.Int) *big.Int {
+	two := big.NewInt(2)
+	pMinus2 := new(big.Int).Sub(P, two)
+	return new(big.Int).Exp(k, pMinus2, P)
+}
+
+// Sign signs an arbitrary length hash (which should be the result of hashing a
+// larger message) using the private key, priv. It returns the signature as a
+// pair of integers. The security of the private key depends on the entropy of
+// rand.
+//
+// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
+// to the byte-length of the subgroup. This function does not perform that
+// truncation itself.
+func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
+	// FIPS 186-3, section 4.6
+
+	n := priv.Q.BitLen()
+	if n&7 != 0 {
+		err = ErrInvalidPublicKey
+		return
+	}
+	n >>= 3
+
+	for {
+		k := new(big.Int)
+		buf := make([]byte, n)
+		for {
+			_, err = io.ReadFull(rand, buf)
+			if err != nil {
+				return
+			}
+			k.SetBytes(buf)
+			if k.Sign() > 0 && k.Cmp(priv.Q) < 0 {
+				break
+			}
+		}
+
+		kInv := fermatInverse(k, priv.Q)
+
+		r = new(big.Int).Exp(priv.G, k, priv.P)
+		r.Mod(r, priv.Q)
+
+		if r.Sign() == 0 {
+			continue
+		}
+
+		z := k.SetBytes(hash)
+
+		s = new(big.Int).Mul(priv.X, r)
+		s.Add(s, z)
+		s.Mod(s, priv.Q)
+		s.Mul(s, kInv)
+		s.Mod(s, priv.Q)
+
+		if s.Sign() != 0 {
+			break
+		}
+	}
+
+	return
+}
+
+// Verify verifies the signature in r, s of hash using the public key, pub. It
+// reports whether the signature is valid.
+//
+// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
+// to the byte-length of the subgroup. This function does not perform that
+// truncation itself.
+func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
+	// FIPS 186-3, section 4.7
+
+	if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 {
+		return false
+	}
+	if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 {
+		return false
+	}
+
+	w := new(big.Int).ModInverse(s, pub.Q)
+
+	n := pub.Q.BitLen()
+	if n&7 != 0 {
+		return false
+	}
+	z := new(big.Int).SetBytes(hash)
+
+	u1 := new(big.Int).Mul(z, w)
+	u1.Mod(u1, pub.Q)
+	u2 := w.Mul(r, w)
+	u2.Mod(u2, pub.Q)
+	v := u1.Exp(pub.G, u1, pub.P)
+	u2.Exp(pub.Y, u2, pub.P)
+	v.Mul(v, u2)
+	v.Mod(v, pub.P)
+	v.Mod(v, pub.Q)
+
+	return v.Cmp(r) == 0
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/dsa/dsa_test.go b/third_party/gofrontend/libgo/go/crypto/dsa/dsa_test.go
new file mode 100644
index 0000000..568416d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/dsa/dsa_test.go
@@ -0,0 +1,85 @@
+// 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.
+
+package dsa
+
+import (
+	"crypto/rand"
+	"math/big"
+	"testing"
+)
+
+func testSignAndVerify(t *testing.T, i int, priv *PrivateKey) {
+	hashed := []byte("testing")
+	r, s, err := Sign(rand.Reader, priv, hashed)
+	if err != nil {
+		t.Errorf("%d: error signing: %s", i, err)
+		return
+	}
+
+	if !Verify(&priv.PublicKey, hashed, r, s) {
+		t.Errorf("%d: Verify failed", i)
+	}
+}
+
+func testParameterGeneration(t *testing.T, sizes ParameterSizes, L, N int) {
+	var priv PrivateKey
+	params := &priv.Parameters
+
+	err := GenerateParameters(params, rand.Reader, sizes)
+	if err != nil {
+		t.Errorf("%d: %s", int(sizes), err)
+		return
+	}
+
+	if params.P.BitLen() != L {
+		t.Errorf("%d: params.BitLen got:%d want:%d", int(sizes), params.P.BitLen(), L)
+	}
+
+	if params.Q.BitLen() != N {
+		t.Errorf("%d: q.BitLen got:%d want:%d", int(sizes), params.Q.BitLen(), L)
+	}
+
+	one := new(big.Int)
+	one.SetInt64(1)
+	pm1 := new(big.Int).Sub(params.P, one)
+	quo, rem := new(big.Int).DivMod(pm1, params.Q, new(big.Int))
+	if rem.Sign() != 0 {
+		t.Errorf("%d: p-1 mod q != 0", int(sizes))
+	}
+	x := new(big.Int).Exp(params.G, quo, params.P)
+	if x.Cmp(one) == 0 {
+		t.Errorf("%d: invalid generator", int(sizes))
+	}
+
+	err = GenerateKey(&priv, rand.Reader)
+	if err != nil {
+		t.Errorf("error generating key: %s", err)
+		return
+	}
+
+	testSignAndVerify(t, int(sizes), &priv)
+}
+
+func TestParameterGeneration(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping parameter generation test in short mode")
+	}
+
+	testParameterGeneration(t, L1024N160, 1024, 160)
+	testParameterGeneration(t, L2048N224, 2048, 224)
+	testParameterGeneration(t, L2048N256, 2048, 256)
+	testParameterGeneration(t, L3072N256, 3072, 256)
+}
+
+func TestSignAndVerify(t *testing.T) {
+	var priv PrivateKey
+	priv.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16)
+	priv.Q, _ = new(big.Int).SetString("E1D3391245933D68A0714ED34BBCB7A1F422B9C1", 16)
+	priv.G, _ = new(big.Int).SetString("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA", 16)
+	priv.Y, _ = new(big.Int).SetString("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2", 16)
+	priv.X, _ = new(big.Int).SetString("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A", 16)
+
+	testSignAndVerify(t, 0, &priv)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/ecdsa/ecdsa.go b/third_party/gofrontend/libgo/go/crypto/ecdsa/ecdsa.go
new file mode 100644
index 0000000..1bec743
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/ecdsa/ecdsa.go
@@ -0,0 +1,165 @@
+// 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.
+
+// Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as
+// defined in FIPS 186-3.
+package ecdsa
+
+// References:
+//   [NSA]: Suite B implementer's guide to FIPS 186-3,
+//     http://www.nsa.gov/ia/_files/ecdsa.pdf
+//   [SECG]: SECG, SEC1
+//     http://www.secg.org/download/aid-780/sec1-v2.pdf
+
+import (
+	"crypto/elliptic"
+	"io"
+	"math/big"
+)
+
+// PublicKey represents an ECDSA public key.
+type PublicKey struct {
+	elliptic.Curve
+	X, Y *big.Int
+}
+
+// PrivateKey represents a ECDSA private key.
+type PrivateKey struct {
+	PublicKey
+	D *big.Int
+}
+
+var one = new(big.Int).SetInt64(1)
+
+// randFieldElement returns a random element of the field underlying the given
+// curve using the procedure given in [NSA] A.2.1.
+func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
+	params := c.Params()
+	b := make([]byte, params.BitSize/8+8)
+	_, err = io.ReadFull(rand, b)
+	if err != nil {
+		return
+	}
+
+	k = new(big.Int).SetBytes(b)
+	n := new(big.Int).Sub(params.N, one)
+	k.Mod(k, n)
+	k.Add(k, one)
+	return
+}
+
+// GenerateKey generates a public and private key pair.
+func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error) {
+	k, err := randFieldElement(c, rand)
+	if err != nil {
+		return
+	}
+
+	priv = new(PrivateKey)
+	priv.PublicKey.Curve = c
+	priv.D = k
+	priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
+	return
+}
+
+// hashToInt converts a hash value to an integer. There is some disagreement
+// about how this is done. [NSA] suggests that this is done in the obvious
+// manner, but [SECG] truncates the hash to the bit-length of the curve order
+// first. We follow [SECG] because that's what OpenSSL does. Additionally,
+// OpenSSL right shifts excess bits from the number if the hash is too large
+// and we mirror that too.
+func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
+	orderBits := c.Params().N.BitLen()
+	orderBytes := (orderBits + 7) / 8
+	if len(hash) > orderBytes {
+		hash = hash[:orderBytes]
+	}
+
+	ret := new(big.Int).SetBytes(hash)
+	excess := len(hash)*8 - orderBits
+	if excess > 0 {
+		ret.Rsh(ret, uint(excess))
+	}
+	return ret
+}
+
+// fermatInverse calculates the inverse of k in GF(P) using Fermat's method.
+// This has better constant-time properties than Euclid's method (implemented
+// in math/big.Int.ModInverse) although math/big itself isn't strictly
+// constant-time so it's not perfect.
+func fermatInverse(k, N *big.Int) *big.Int {
+	two := big.NewInt(2)
+	nMinus2 := new(big.Int).Sub(N, two)
+	return new(big.Int).Exp(k, nMinus2, N)
+}
+
+// Sign signs an arbitrary length hash (which should be the result of hashing a
+// larger message) using the private key, priv. It returns the signature as a
+// pair of integers. The security of the private key depends on the entropy of
+// rand.
+func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
+	// See [NSA] 3.4.1
+	c := priv.PublicKey.Curve
+	N := c.Params().N
+
+	var k, kInv *big.Int
+	for {
+		for {
+			k, err = randFieldElement(c, rand)
+			if err != nil {
+				r = nil
+				return
+			}
+
+			kInv = fermatInverse(k, N)
+			r, _ = priv.Curve.ScalarBaseMult(k.Bytes())
+			r.Mod(r, N)
+			if r.Sign() != 0 {
+				break
+			}
+		}
+
+		e := hashToInt(hash, c)
+		s = new(big.Int).Mul(priv.D, r)
+		s.Add(s, e)
+		s.Mul(s, kInv)
+		s.Mod(s, N)
+		if s.Sign() != 0 {
+			break
+		}
+	}
+
+	return
+}
+
+// Verify verifies the signature in r, s of hash using the public key, pub. Its
+// return value records whether the signature is valid.
+func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
+	// See [NSA] 3.4.2
+	c := pub.Curve
+	N := c.Params().N
+
+	if r.Sign() == 0 || s.Sign() == 0 {
+		return false
+	}
+	if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 {
+		return false
+	}
+	e := hashToInt(hash, c)
+	w := new(big.Int).ModInverse(s, N)
+
+	u1 := e.Mul(e, w)
+	u1.Mod(u1, N)
+	u2 := w.Mul(r, w)
+	u2.Mod(u2, N)
+
+	x1, y1 := c.ScalarBaseMult(u1.Bytes())
+	x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes())
+	x, y := c.Add(x1, y1, x2, y2)
+	if x.Sign() == 0 && y.Sign() == 0 {
+		return false
+	}
+	x.Mod(x, N)
+	return x.Cmp(r) == 0
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/ecdsa/ecdsa_test.go b/third_party/gofrontend/libgo/go/crypto/ecdsa/ecdsa_test.go
new file mode 100644
index 0000000..0c06431
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/ecdsa/ecdsa_test.go
@@ -0,0 +1,191 @@
+// 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.
+
+package ecdsa
+
+import (
+	"bufio"
+	"compress/bzip2"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/sha512"
+	"encoding/hex"
+	"hash"
+	"io"
+	"math/big"
+	"os"
+	"strings"
+	"testing"
+)
+
+func testKeyGeneration(t *testing.T, c elliptic.Curve, tag string) {
+	priv, err := GenerateKey(c, rand.Reader)
+	if err != nil {
+		t.Errorf("%s: error: %s", tag, err)
+		return
+	}
+	if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) {
+		t.Errorf("%s: public key invalid: %s", tag, err)
+	}
+}
+
+func TestKeyGeneration(t *testing.T) {
+	testKeyGeneration(t, elliptic.P224(), "p224")
+	if testing.Short() {
+		return
+	}
+	testKeyGeneration(t, elliptic.P256(), "p256")
+	testKeyGeneration(t, elliptic.P384(), "p384")
+	testKeyGeneration(t, elliptic.P521(), "p521")
+}
+
+func testSignAndVerify(t *testing.T, c elliptic.Curve, tag string) {
+	priv, _ := GenerateKey(c, rand.Reader)
+
+	hashed := []byte("testing")
+	r, s, err := Sign(rand.Reader, priv, hashed)
+	if err != nil {
+		t.Errorf("%s: error signing: %s", tag, err)
+		return
+	}
+
+	if !Verify(&priv.PublicKey, hashed, r, s) {
+		t.Errorf("%s: Verify failed", tag)
+	}
+
+	hashed[0] ^= 0xff
+	if Verify(&priv.PublicKey, hashed, r, s) {
+		t.Errorf("%s: Verify always works!", tag)
+	}
+}
+
+func TestSignAndVerify(t *testing.T) {
+	testSignAndVerify(t, elliptic.P224(), "p224")
+	if testing.Short() {
+		return
+	}
+	testSignAndVerify(t, elliptic.P256(), "p256")
+	testSignAndVerify(t, elliptic.P384(), "p384")
+	testSignAndVerify(t, elliptic.P521(), "p521")
+}
+
+func fromHex(s string) *big.Int {
+	r, ok := new(big.Int).SetString(s, 16)
+	if !ok {
+		panic("bad hex")
+	}
+	return r
+}
+
+func TestVectors(t *testing.T) {
+	// This test runs the full set of NIST test vectors from
+	// http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip
+	//
+	// The SigVer.rsp file has been edited to remove test vectors for
+	// unsupported algorithms and has been compressed.
+
+	if testing.Short() {
+		return
+	}
+
+	f, err := os.Open("testdata/SigVer.rsp.bz2")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	buf := bufio.NewReader(bzip2.NewReader(f))
+
+	lineNo := 1
+	var h hash.Hash
+	var msg []byte
+	var hashed []byte
+	var r, s *big.Int
+	pub := new(PublicKey)
+
+	for {
+		line, err := buf.ReadString('\n')
+		if len(line) == 0 {
+			if err == io.EOF {
+				break
+			}
+			t.Fatalf("error reading from input: %s", err)
+		}
+		lineNo++
+		// Need to remove \r\n from the end of the line.
+		if !strings.HasSuffix(line, "\r\n") {
+			t.Fatalf("bad line ending (expected \\r\\n) on line %d", lineNo)
+		}
+		line = line[:len(line)-2]
+
+		if len(line) == 0 || line[0] == '#' {
+			continue
+		}
+
+		if line[0] == '[' {
+			line = line[1 : len(line)-1]
+			parts := strings.SplitN(line, ",", 2)
+
+			switch parts[0] {
+			case "P-224":
+				pub.Curve = elliptic.P224()
+			case "P-256":
+				pub.Curve = elliptic.P256()
+			case "P-384":
+				pub.Curve = elliptic.P384()
+			case "P-521":
+				pub.Curve = elliptic.P521()
+			default:
+				pub.Curve = nil
+			}
+
+			switch parts[1] {
+			case "SHA-1":
+				h = sha1.New()
+			case "SHA-224":
+				h = sha256.New224()
+			case "SHA-256":
+				h = sha256.New()
+			case "SHA-384":
+				h = sha512.New384()
+			case "SHA-512":
+				h = sha512.New()
+			default:
+				h = nil
+			}
+
+			continue
+		}
+
+		if h == nil || pub.Curve == nil {
+			continue
+		}
+
+		switch {
+		case strings.HasPrefix(line, "Msg = "):
+			if msg, err = hex.DecodeString(line[6:]); err != nil {
+				t.Fatalf("failed to decode message on line %d: %s", lineNo, err)
+			}
+		case strings.HasPrefix(line, "Qx = "):
+			pub.X = fromHex(line[5:])
+		case strings.HasPrefix(line, "Qy = "):
+			pub.Y = fromHex(line[5:])
+		case strings.HasPrefix(line, "R = "):
+			r = fromHex(line[4:])
+		case strings.HasPrefix(line, "S = "):
+			s = fromHex(line[4:])
+		case strings.HasPrefix(line, "Result = "):
+			expected := line[9] == 'P'
+			h.Reset()
+			h.Write(msg)
+			hashed := h.Sum(hashed[:0])
+			if Verify(pub, hashed, r, s) != expected {
+				t.Fatalf("incorrect result on line %d", lineNo)
+			}
+		default:
+			t.Fatalf("unknown variable on line %d: %s", lineNo, line)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/elliptic/elliptic.go b/third_party/gofrontend/libgo/go/crypto/elliptic/elliptic.go
new file mode 100644
index 0000000..ba673f8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/elliptic/elliptic.go
@@ -0,0 +1,373 @@
+// Copyright 2010 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 elliptic implements several standard elliptic curves over prime
+// fields.
+package elliptic
+
+// This package operates, internally, on Jacobian coordinates. For a given
+// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
+// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
+// calculation can be performed within the transform (as in ScalarMult and
+// ScalarBaseMult). But even for Add and Double, it's faster to apply and
+// reverse the transform than to operate in affine coordinates.
+
+import (
+	"io"
+	"math/big"
+	"sync"
+)
+
+// A Curve represents a short-form Weierstrass curve with a=-3.
+// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
+type Curve interface {
+	// Params returns the parameters for the curve.
+	Params() *CurveParams
+	// IsOnCurve returns true if the given (x,y) lies on the curve.
+	IsOnCurve(x, y *big.Int) bool
+	// Add returns the sum of (x1,y1) and (x2,y2)
+	Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int)
+	// Double returns 2*(x,y)
+	Double(x1, y1 *big.Int) (x, y *big.Int)
+	// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
+	ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int)
+	// ScalarBaseMult returns k*G, where G is the base point of the group
+	// and k is an integer in big-endian form.
+	ScalarBaseMult(k []byte) (x, y *big.Int)
+}
+
+// CurveParams contains the parameters of an elliptic curve and also provides
+// a generic, non-constant time implementation of Curve.
+type CurveParams struct {
+	P       *big.Int // the order of the underlying field
+	N       *big.Int // the order of the base point
+	B       *big.Int // the constant of the curve equation
+	Gx, Gy  *big.Int // (x,y) of the base point
+	BitSize int      // the size of the underlying field
+}
+
+func (curve *CurveParams) Params() *CurveParams {
+	return curve
+}
+
+func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
+	// y² = x³ - 3x + b
+	y2 := new(big.Int).Mul(y, y)
+	y2.Mod(y2, curve.P)
+
+	x3 := new(big.Int).Mul(x, x)
+	x3.Mul(x3, x)
+
+	threeX := new(big.Int).Lsh(x, 1)
+	threeX.Add(threeX, x)
+
+	x3.Sub(x3, threeX)
+	x3.Add(x3, curve.B)
+	x3.Mod(x3, curve.P)
+
+	return x3.Cmp(y2) == 0
+}
+
+// zForAffine returns a Jacobian Z value for the affine point (x, y). If x and
+// y are zero, it assumes that they represent the point at infinity because (0,
+// 0) is not on the any of the curves handled here.
+func zForAffine(x, y *big.Int) *big.Int {
+	z := new(big.Int)
+	if x.Sign() != 0 || y.Sign() != 0 {
+		z.SetInt64(1)
+	}
+	return z
+}
+
+// affineFromJacobian reverses the Jacobian transform. See the comment at the
+// top of the file. If the point is ∞ it returns 0, 0.
+func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
+	if z.Sign() == 0 {
+		return new(big.Int), new(big.Int)
+	}
+
+	zinv := new(big.Int).ModInverse(z, curve.P)
+	zinvsq := new(big.Int).Mul(zinv, zinv)
+
+	xOut = new(big.Int).Mul(x, zinvsq)
+	xOut.Mod(xOut, curve.P)
+	zinvsq.Mul(zinvsq, zinv)
+	yOut = new(big.Int).Mul(y, zinvsq)
+	yOut.Mod(yOut, curve.P)
+	return
+}
+
+func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+	z1 := zForAffine(x1, y1)
+	z2 := zForAffine(x2, y2)
+	return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2))
+}
+
+// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
+// (x2, y2, z2) and returns their sum, also in Jacobian form.
+func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
+	// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
+	x3, y3, z3 := new(big.Int), new(big.Int), new(big.Int)
+	if z1.Sign() == 0 {
+		x3.Set(x2)
+		y3.Set(y2)
+		z3.Set(z2)
+		return x3, y3, z3
+	}
+	if z2.Sign() == 0 {
+		x3.Set(x1)
+		y3.Set(y1)
+		z3.Set(z1)
+		return x3, y3, z3
+	}
+
+	z1z1 := new(big.Int).Mul(z1, z1)
+	z1z1.Mod(z1z1, curve.P)
+	z2z2 := new(big.Int).Mul(z2, z2)
+	z2z2.Mod(z2z2, curve.P)
+
+	u1 := new(big.Int).Mul(x1, z2z2)
+	u1.Mod(u1, curve.P)
+	u2 := new(big.Int).Mul(x2, z1z1)
+	u2.Mod(u2, curve.P)
+	h := new(big.Int).Sub(u2, u1)
+	xEqual := h.Sign() == 0
+	if h.Sign() == -1 {
+		h.Add(h, curve.P)
+	}
+	i := new(big.Int).Lsh(h, 1)
+	i.Mul(i, i)
+	j := new(big.Int).Mul(h, i)
+
+	s1 := new(big.Int).Mul(y1, z2)
+	s1.Mul(s1, z2z2)
+	s1.Mod(s1, curve.P)
+	s2 := new(big.Int).Mul(y2, z1)
+	s2.Mul(s2, z1z1)
+	s2.Mod(s2, curve.P)
+	r := new(big.Int).Sub(s2, s1)
+	if r.Sign() == -1 {
+		r.Add(r, curve.P)
+	}
+	yEqual := r.Sign() == 0
+	if xEqual && yEqual {
+		return curve.doubleJacobian(x1, y1, z1)
+	}
+	r.Lsh(r, 1)
+	v := new(big.Int).Mul(u1, i)
+
+	x3.Set(r)
+	x3.Mul(x3, x3)
+	x3.Sub(x3, j)
+	x3.Sub(x3, v)
+	x3.Sub(x3, v)
+	x3.Mod(x3, curve.P)
+
+	y3.Set(r)
+	v.Sub(v, x3)
+	y3.Mul(y3, v)
+	s1.Mul(s1, j)
+	s1.Lsh(s1, 1)
+	y3.Sub(y3, s1)
+	y3.Mod(y3, curve.P)
+
+	z3.Add(z1, z2)
+	z3.Mul(z3, z3)
+	z3.Sub(z3, z1z1)
+	z3.Sub(z3, z2z2)
+	z3.Mul(z3, h)
+	z3.Mod(z3, curve.P)
+
+	return x3, y3, z3
+}
+
+func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+	z1 := zForAffine(x1, y1)
+	return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1))
+}
+
+// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
+// returns its double, also in Jacobian form.
+func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
+	// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
+	delta := new(big.Int).Mul(z, z)
+	delta.Mod(delta, curve.P)
+	gamma := new(big.Int).Mul(y, y)
+	gamma.Mod(gamma, curve.P)
+	alpha := new(big.Int).Sub(x, delta)
+	if alpha.Sign() == -1 {
+		alpha.Add(alpha, curve.P)
+	}
+	alpha2 := new(big.Int).Add(x, delta)
+	alpha.Mul(alpha, alpha2)
+	alpha2.Set(alpha)
+	alpha.Lsh(alpha, 1)
+	alpha.Add(alpha, alpha2)
+
+	beta := alpha2.Mul(x, gamma)
+
+	x3 := new(big.Int).Mul(alpha, alpha)
+	beta8 := new(big.Int).Lsh(beta, 3)
+	x3.Sub(x3, beta8)
+	for x3.Sign() == -1 {
+		x3.Add(x3, curve.P)
+	}
+	x3.Mod(x3, curve.P)
+
+	z3 := new(big.Int).Add(y, z)
+	z3.Mul(z3, z3)
+	z3.Sub(z3, gamma)
+	if z3.Sign() == -1 {
+		z3.Add(z3, curve.P)
+	}
+	z3.Sub(z3, delta)
+	if z3.Sign() == -1 {
+		z3.Add(z3, curve.P)
+	}
+	z3.Mod(z3, curve.P)
+
+	beta.Lsh(beta, 2)
+	beta.Sub(beta, x3)
+	if beta.Sign() == -1 {
+		beta.Add(beta, curve.P)
+	}
+	y3 := alpha.Mul(alpha, beta)
+
+	gamma.Mul(gamma, gamma)
+	gamma.Lsh(gamma, 3)
+	gamma.Mod(gamma, curve.P)
+
+	y3.Sub(y3, gamma)
+	if y3.Sign() == -1 {
+		y3.Add(y3, curve.P)
+	}
+	y3.Mod(y3, curve.P)
+
+	return x3, y3, z3
+}
+
+func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
+	Bz := new(big.Int).SetInt64(1)
+	x, y, z := new(big.Int), new(big.Int), new(big.Int)
+
+	for _, byte := range k {
+		for bitNum := 0; bitNum < 8; bitNum++ {
+			x, y, z = curve.doubleJacobian(x, y, z)
+			if byte&0x80 == 0x80 {
+				x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z)
+			}
+			byte <<= 1
+		}
+	}
+
+	return curve.affineFromJacobian(x, y, z)
+}
+
+func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
+	return curve.ScalarMult(curve.Gx, curve.Gy, k)
+}
+
+var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
+
+// GenerateKey returns a public/private key pair. The private key is
+// generated using the given reader, which must return random data.
+func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) {
+	bitSize := curve.Params().BitSize
+	byteLen := (bitSize + 7) >> 3
+	priv = make([]byte, byteLen)
+
+	for x == nil {
+		_, err = io.ReadFull(rand, priv)
+		if err != nil {
+			return
+		}
+		// We have to mask off any excess bits in the case that the size of the
+		// underlying field is not a whole number of bytes.
+		priv[0] &= mask[bitSize%8]
+		// This is because, in tests, rand will return all zeros and we don't
+		// want to get the point at infinity and loop forever.
+		priv[1] ^= 0x42
+		x, y = curve.ScalarBaseMult(priv)
+	}
+	return
+}
+
+// Marshal converts a point into the form specified in section 4.3.6 of ANSI X9.62.
+func Marshal(curve Curve, x, y *big.Int) []byte {
+	byteLen := (curve.Params().BitSize + 7) >> 3
+
+	ret := make([]byte, 1+2*byteLen)
+	ret[0] = 4 // uncompressed point
+
+	xBytes := x.Bytes()
+	copy(ret[1+byteLen-len(xBytes):], xBytes)
+	yBytes := y.Bytes()
+	copy(ret[1+2*byteLen-len(yBytes):], yBytes)
+	return ret
+}
+
+// Unmarshal converts a point, serialized by Marshal, into an x, y pair. On error, x = nil.
+func Unmarshal(curve Curve, data []byte) (x, y *big.Int) {
+	byteLen := (curve.Params().BitSize + 7) >> 3
+	if len(data) != 1+2*byteLen {
+		return
+	}
+	if data[0] != 4 { // uncompressed form
+		return
+	}
+	x = new(big.Int).SetBytes(data[1 : 1+byteLen])
+	y = new(big.Int).SetBytes(data[1+byteLen:])
+	return
+}
+
+var initonce sync.Once
+var p384 *CurveParams
+var p521 *CurveParams
+
+func initAll() {
+	initP224()
+	initP256()
+	initP384()
+	initP521()
+}
+
+func initP384() {
+	// See FIPS 186-3, section D.2.4
+	p384 = new(CurveParams)
+	p384.P, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10)
+	p384.N, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643", 10)
+	p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16)
+	p384.Gx, _ = new(big.Int).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16)
+	p384.Gy, _ = new(big.Int).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16)
+	p384.BitSize = 384
+}
+
+func initP521() {
+	// See FIPS 186-3, section D.2.5
+	p521 = new(CurveParams)
+	p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10)
+	p521.N, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10)
+	p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16)
+	p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16)
+	p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16)
+	p521.BitSize = 521
+}
+
+// P256 returns a Curve which implements P-256 (see FIPS 186-3, section D.2.3)
+func P256() Curve {
+	initonce.Do(initAll)
+	return p256
+}
+
+// P384 returns a Curve which implements P-384 (see FIPS 186-3, section D.2.4)
+func P384() Curve {
+	initonce.Do(initAll)
+	return p384
+}
+
+// P521 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
+func P521() Curve {
+	initonce.Do(initAll)
+	return p521
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/elliptic/elliptic_test.go b/third_party/gofrontend/libgo/go/crypto/elliptic/elliptic_test.go
new file mode 100644
index 0000000..4dc27c9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/elliptic/elliptic_test.go
@@ -0,0 +1,458 @@
+// Copyright 2010 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 elliptic
+
+import (
+	"crypto/rand"
+	"encoding/hex"
+	"fmt"
+	"math/big"
+	"testing"
+)
+
+func TestOnCurve(t *testing.T) {
+	p224 := P224()
+	if !p224.IsOnCurve(p224.Params().Gx, p224.Params().Gy) {
+		t.Errorf("FAIL")
+	}
+}
+
+type baseMultTest struct {
+	k    string
+	x, y string
+}
+
+var p224BaseMultTests = []baseMultTest{
+	{
+		"1",
+		"b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
+		"bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
+	},
+	{
+		"2",
+		"706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
+		"1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb",
+	},
+	{
+		"3",
+		"df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
+		"a3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925",
+	},
+	{
+		"4",
+		"ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
+		"482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9",
+	},
+	{
+		"5",
+		"31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa",
+		"27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b",
+	},
+	{
+		"6",
+		"1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408",
+		"89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e",
+	},
+	{
+		"7",
+		"db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28",
+		"f3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963",
+	},
+	{
+		"8",
+		"858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550",
+		"46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a",
+	},
+	{
+		"9",
+		"2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d",
+		"371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463",
+	},
+	{
+		"10",
+		"aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd",
+		"39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f",
+	},
+	{
+		"11",
+		"ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c",
+		"20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da",
+	},
+	{
+		"12",
+		"6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a",
+		"207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13",
+	},
+	{
+		"13",
+		"34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca",
+		"252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767",
+	},
+	{
+		"14",
+		"a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa",
+		"d5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf",
+	},
+	{
+		"15",
+		"baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9",
+		"979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989",
+	},
+	{
+		"16",
+		"b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d",
+		"3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482",
+	},
+	{
+		"17",
+		"b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc",
+		"ff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26",
+	},
+	{
+		"18",
+		"c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc",
+		"ea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002",
+	},
+	{
+		"19",
+		"a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c",
+		"dcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd",
+	},
+	{
+		"20",
+		"fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455",
+		"d5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530",
+	},
+	{
+		"112233445566778899",
+		"61f077c6f62ed802dad7c2f38f5c67f2cc453601e61bd076bb46179e",
+		"2272f9e9f5933e70388ee652513443b5e289dd135dcc0d0299b225e4",
+	},
+	{
+		"112233445566778899112233445566778899",
+		"29895f0af496bfc62b6ef8d8a65c88c613949b03668aab4f0429e35",
+		"3ea6e53f9a841f2019ec24bde1a75677aa9b5902e61081c01064de93",
+	},
+	{
+		"6950511619965839450988900688150712778015737983940691968051900319680",
+		"ab689930bcae4a4aa5f5cb085e823e8ae30fd365eb1da4aba9cf0379",
+		"3345a121bbd233548af0d210654eb40bab788a03666419be6fbd34e7",
+	},
+	{
+		"13479972933410060327035789020509431695094902435494295338570602119423",
+		"bdb6a8817c1f89da1c2f3dd8e97feb4494f2ed302a4ce2bc7f5f4025",
+		"4c7020d57c00411889462d77a5438bb4e97d177700bf7243a07f1680",
+	},
+	{
+		"13479971751745682581351455311314208093898607229429740618390390702079",
+		"d58b61aa41c32dd5eba462647dba75c5d67c83606c0af2bd928446a9",
+		"d24ba6a837be0460dd107ae77725696d211446c5609b4595976b16bd",
+	},
+	{
+		"13479972931865328106486971546324465392952975980343228160962702868479",
+		"dc9fa77978a005510980e929a1485f63716df695d7a0c18bb518df03",
+		"ede2b016f2ddffc2a8c015b134928275ce09e5661b7ab14ce0d1d403",
+	},
+	{
+		"11795773708834916026404142434151065506931607341523388140225443265536",
+		"499d8b2829cfb879c901f7d85d357045edab55028824d0f05ba279ba",
+		"bf929537b06e4015919639d94f57838fa33fc3d952598dcdbb44d638",
+	},
+	{
+		"784254593043826236572847595991346435467177662189391577090",
+		"8246c999137186632c5f9eddf3b1b0e1764c5e8bd0e0d8a554b9cb77",
+		"e80ed8660bc1cb17ac7d845be40a7a022d3306f116ae9f81fea65947",
+	},
+	{
+		"13479767645505654746623887797783387853576174193480695826442858012671",
+		"6670c20afcceaea672c97f75e2e9dd5c8460e54bb38538ebb4bd30eb",
+		"f280d8008d07a4caf54271f993527d46ff3ff46fd1190a3f1faa4f74",
+	},
+	{
+		"205688069665150753842126177372015544874550518966168735589597183",
+		"eca934247425cfd949b795cb5ce1eff401550386e28d1a4c5a8eb",
+		"d4c01040dba19628931bc8855370317c722cbd9ca6156985f1c2e9ce",
+	},
+	{
+		"13479966930919337728895168462090683249159702977113823384618282123295",
+		"ef353bf5c73cd551b96d596fbc9a67f16d61dd9fe56af19de1fba9cd",
+		"21771b9cdce3e8430c09b3838be70b48c21e15bc09ee1f2d7945b91f",
+	},
+	{
+		"50210731791415612487756441341851895584393717453129007497216",
+		"4036052a3091eb481046ad3289c95d3ac905ca0023de2c03ecd451cf",
+		"d768165a38a2b96f812586a9d59d4136035d9c853a5bf2e1c86a4993",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368041",
+		"fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455",
+		"f2a28eefd8b345832116f1e574f2c6b2c895aa8c24941f40d8b80ad1",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368042",
+		"a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c",
+		"230e093c24f638f533dac6e2b6d01da3b5e7f45429315ca93fb8e634",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368043",
+		"c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc",
+		"156729f1a003647030666054e208180f8f7b0df2249e44fba5931fff",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368044",
+		"b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc",
+		"eb610599f95942df1082e4f9426d086fb9c6231ae8b24933aab5db",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368045",
+		"b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d",
+		"cc662b9bcba6f94ee4ff1c9c10bd6ddd0d138df2d099a282152a4b7f",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368046",
+		"baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9",
+		"6865a0b8a607f0b04b13d1cb0aa992a5a97f5ee8ca1849efb9ed8678",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368047",
+		"a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa",
+		"2a7eb328dbe663b5a468b5bc97a040a3745396ba636b964370dc3352",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368048",
+		"34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca",
+		"dad7e608e380480434ea641cc82c82cbc92801469c8db0204f13489a",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368049",
+		"6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a",
+		"df82220fc7a4021549165325725f94c3410ddb56c54e161fc9ef62ee",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368050",
+		"ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c",
+		"df4aefffbf6d1699c930481cd102127c9a3d992048ab05929b6e5927",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368051",
+		"aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd",
+		"c644cf154cc81f5ade49345e541b4d4b5c1adb3eb5c01c14ee949aa2",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368052",
+		"2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d",
+		"c8e8cd1b0be40b0877cfca1958603122f1e6914f84b7e8e968ae8b9e",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368053",
+		"858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550",
+		"fb9232c15a3bc7673a3a03b0253824c53d0fd1411b1cabe2e187fb87",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368054",
+		"db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28",
+		"f0c5cff7ab680d09ee11dae84e9c1072ac48ea2e744b1b7f72fd469e",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368055",
+		"1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408",
+		"76050f3348af2664aac3a8b05281304ebc7a7914c6ad50a4b4eac383",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368056",
+		"31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa",
+		"d817400e8ba9ca13a45f360e3d121eaaeb39af82d6001c8186f5f866",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368057",
+		"ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
+		"fb7da7f5f13a43b81774373c879cd32d6934c05fa758eeb14fcfab38",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368058",
+		"df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
+		"5c080fc3522f41bbb3f55a97cfecf21f882ce8cbb1e50ca6e67e56dc",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368059",
+		"706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
+		"e3d4895843da188fd58fb0567976d7b50359d6b78530c8f62d1b1746",
+	},
+	{
+		"26959946667150639794667015087019625940457807714424391721682722368060",
+		"b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
+		"42c89c774a08dc04b3dd201932bc8a5ea5f8b89bbb2a7e667aff81cd",
+	},
+}
+
+func TestBaseMult(t *testing.T) {
+	p224 := P224()
+	for i, e := range p224BaseMultTests {
+		k, ok := new(big.Int).SetString(e.k, 10)
+		if !ok {
+			t.Errorf("%d: bad value for k: %s", i, e.k)
+		}
+		x, y := p224.ScalarBaseMult(k.Bytes())
+		if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
+			t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y)
+		}
+		if testing.Short() && i > 5 {
+			break
+		}
+	}
+}
+
+func TestGenericBaseMult(t *testing.T) {
+	// We use the P224 CurveParams directly in order to test the generic implementation.
+	p224 := P224().Params()
+	for i, e := range p224BaseMultTests {
+		k, ok := new(big.Int).SetString(e.k, 10)
+		if !ok {
+			t.Errorf("%d: bad value for k: %s", i, e.k)
+		}
+		x, y := p224.ScalarBaseMult(k.Bytes())
+		if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
+			t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y)
+		}
+		if testing.Short() && i > 5 {
+			break
+		}
+	}
+}
+
+func TestP256BaseMult(t *testing.T) {
+	p256 := P256()
+	p256Generic := p256.Params()
+
+	scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1)
+	for _, e := range p224BaseMultTests {
+		k, _ := new(big.Int).SetString(e.k, 10)
+		scalars = append(scalars, k)
+	}
+	k := new(big.Int).SetInt64(1)
+	k.Lsh(k, 500)
+	scalars = append(scalars, k)
+
+	for i, k := range scalars {
+		x, y := p256.ScalarBaseMult(k.Bytes())
+		x2, y2 := p256Generic.ScalarBaseMult(k.Bytes())
+		if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 {
+			t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, x, y, x2, y2)
+		}
+
+		if testing.Short() && i > 5 {
+			break
+		}
+	}
+}
+
+func TestP256Mult(t *testing.T) {
+	p256 := P256()
+	p256Generic := p256.Params()
+
+	for i, e := range p224BaseMultTests {
+		x, _ := new(big.Int).SetString(e.x, 16)
+		y, _ := new(big.Int).SetString(e.y, 16)
+		k, _ := new(big.Int).SetString(e.k, 10)
+
+		xx, yy := p256.ScalarMult(x, y, k.Bytes())
+		xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes())
+		if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 {
+			t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2)
+		}
+		if testing.Short() && i > 5 {
+			break
+		}
+	}
+}
+
+func TestInfinity(t *testing.T) {
+	tests := []struct {
+		name  string
+		curve Curve
+	}{
+		{"p224", P224()},
+		{"p256", P256()},
+	}
+
+	for _, test := range tests {
+		curve := test.curve
+		x, y := curve.ScalarBaseMult(nil)
+		if x.Sign() != 0 || y.Sign() != 0 {
+			t.Errorf("%s: x^0 != ∞", test.name)
+		}
+		x.SetInt64(0)
+		y.SetInt64(0)
+
+		x2, y2 := curve.Double(x, y)
+		if x2.Sign() != 0 || y2.Sign() != 0 {
+			t.Errorf("%s: 2∞ != ∞", test.name)
+		}
+
+		baseX := curve.Params().Gx
+		baseY := curve.Params().Gy
+
+		x3, y3 := curve.Add(baseX, baseY, x, y)
+		if x3.Cmp(baseX) != 0 || y3.Cmp(baseY) != 0 {
+			t.Errorf("%s: x+∞ != x", test.name)
+		}
+
+		x4, y4 := curve.Add(x, y, baseX, baseY)
+		if x4.Cmp(baseX) != 0 || y4.Cmp(baseY) != 0 {
+			t.Errorf("%s: ∞+x != x", test.name)
+		}
+	}
+}
+
+func BenchmarkBaseMult(b *testing.B) {
+	b.ResetTimer()
+	p224 := P224()
+	e := p224BaseMultTests[25]
+	k, _ := new(big.Int).SetString(e.k, 10)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		p224.ScalarBaseMult(k.Bytes())
+	}
+}
+
+func BenchmarkBaseMultP256(b *testing.B) {
+	b.ResetTimer()
+	p256 := P256()
+	e := p224BaseMultTests[25]
+	k, _ := new(big.Int).SetString(e.k, 10)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		p256.ScalarBaseMult(k.Bytes())
+	}
+}
+
+func TestMarshal(t *testing.T) {
+	p224 := P224()
+	_, x, y, err := GenerateKey(p224, rand.Reader)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	serialized := Marshal(p224, x, y)
+	xx, yy := Unmarshal(p224, serialized)
+	if xx == nil {
+		t.Error("failed to unmarshal")
+		return
+	}
+	if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 {
+		t.Error("unmarshal returned different values")
+		return
+	}
+}
+
+func TestP224Overflow(t *testing.T) {
+	// This tests for a specific bug in the P224 implementation.
+	p224 := P224()
+	pointData, _ := hex.DecodeString("049B535B45FB0A2072398A6831834624C7E32CCFD5A4B933BCEAF77F1DD945E08BBE5178F5EDF5E733388F196D2A631D2E075BB16CBFEEA15B")
+	x, y := Unmarshal(p224, pointData)
+	if !p224.IsOnCurve(x, y) {
+		t.Error("P224 failed to validate a correct point")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/elliptic/p224.go b/third_party/gofrontend/libgo/go/crypto/elliptic/p224.go
new file mode 100644
index 0000000..1f7ff3f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/elliptic/p224.go
@@ -0,0 +1,765 @@
+// 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 elliptic
+
+// This is a constant-time, 32-bit implementation of P224. See FIPS 186-3,
+// section D.2.2.
+//
+// See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
+
+import (
+	"math/big"
+)
+
+var p224 p224Curve
+
+type p224Curve struct {
+	*CurveParams
+	gx, gy, b p224FieldElement
+}
+
+func initP224() {
+	// See FIPS 186-3, section D.2.2
+	p224.CurveParams = new(CurveParams)
+	p224.P, _ = new(big.Int).SetString("26959946667150639794667015087019630673557916260026308143510066298881", 10)
+	p224.N, _ = new(big.Int).SetString("26959946667150639794667015087019625940457807714424391721682722368061", 10)
+	p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16)
+	p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16)
+	p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16)
+	p224.BitSize = 224
+
+	p224FromBig(&p224.gx, p224.Gx)
+	p224FromBig(&p224.gy, p224.Gy)
+	p224FromBig(&p224.b, p224.B)
+}
+
+// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2)
+func P224() Curve {
+	initonce.Do(initAll)
+	return p224
+}
+
+func (curve p224Curve) Params() *CurveParams {
+	return curve.CurveParams
+}
+
+func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool {
+	var x, y p224FieldElement
+	p224FromBig(&x, bigX)
+	p224FromBig(&y, bigY)
+
+	// y² = x³ - 3x + b
+	var tmp p224LargeFieldElement
+	var x3 p224FieldElement
+	p224Square(&x3, &x, &tmp)
+	p224Mul(&x3, &x3, &x, &tmp)
+
+	for i := 0; i < 8; i++ {
+		x[i] *= 3
+	}
+	p224Sub(&x3, &x3, &x)
+	p224Reduce(&x3)
+	p224Add(&x3, &x3, &curve.b)
+	p224Contract(&x3, &x3)
+
+	p224Square(&y, &y, &tmp)
+	p224Contract(&y, &y)
+
+	for i := 0; i < 8; i++ {
+		if y[i] != x3[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (p224Curve) Add(bigX1, bigY1, bigX2, bigY2 *big.Int) (x, y *big.Int) {
+	var x1, y1, z1, x2, y2, z2, x3, y3, z3 p224FieldElement
+
+	p224FromBig(&x1, bigX1)
+	p224FromBig(&y1, bigY1)
+	if bigX1.Sign() != 0 || bigY1.Sign() != 0 {
+		z1[0] = 1
+	}
+	p224FromBig(&x2, bigX2)
+	p224FromBig(&y2, bigY2)
+	if bigX2.Sign() != 0 || bigY2.Sign() != 0 {
+		z2[0] = 1
+	}
+
+	p224AddJacobian(&x3, &y3, &z3, &x1, &y1, &z1, &x2, &y2, &z2)
+	return p224ToAffine(&x3, &y3, &z3)
+}
+
+func (p224Curve) Double(bigX1, bigY1 *big.Int) (x, y *big.Int) {
+	var x1, y1, z1, x2, y2, z2 p224FieldElement
+
+	p224FromBig(&x1, bigX1)
+	p224FromBig(&y1, bigY1)
+	z1[0] = 1
+
+	p224DoubleJacobian(&x2, &y2, &z2, &x1, &y1, &z1)
+	return p224ToAffine(&x2, &y2, &z2)
+}
+
+func (p224Curve) ScalarMult(bigX1, bigY1 *big.Int, scalar []byte) (x, y *big.Int) {
+	var x1, y1, z1, x2, y2, z2 p224FieldElement
+
+	p224FromBig(&x1, bigX1)
+	p224FromBig(&y1, bigY1)
+	z1[0] = 1
+
+	p224ScalarMult(&x2, &y2, &z2, &x1, &y1, &z1, scalar)
+	return p224ToAffine(&x2, &y2, &z2)
+}
+
+func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
+	var z1, x2, y2, z2 p224FieldElement
+
+	z1[0] = 1
+	p224ScalarMult(&x2, &y2, &z2, &curve.gx, &curve.gy, &z1, scalar)
+	return p224ToAffine(&x2, &y2, &z2)
+}
+
+// Field element functions.
+//
+// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1.
+//
+// Field elements are represented by a FieldElement, which is a typedef to an
+// array of 8 uint32's. The value of a FieldElement, a, is:
+//   a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7]
+//
+// Using 28-bit limbs means that there's only 4 bits of headroom, which is less
+// than we would really like. But it has the useful feature that we hit 2**224
+// exactly, making the reflections during a reduce much nicer.
+type p224FieldElement [8]uint32
+
+// p224P is the order of the field, represented as a p224FieldElement.
+var p224P = [8]uint32{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
+
+// p224IsZero returns 1 if a == 0 mod p and 0 otherwise.
+//
+// a[i] < 2**29
+func p224IsZero(a *p224FieldElement) uint32 {
+	// Since a p224FieldElement contains 224 bits there are two possible
+	// representations of 0: 0 and p.
+	var minimal p224FieldElement
+	p224Contract(&minimal, a)
+
+	var isZero, isP uint32
+	for i, v := range minimal {
+		isZero |= v
+		isP |= v - p224P[i]
+	}
+
+	// If either isZero or isP is 0, then we should return 1.
+	isZero |= isZero >> 16
+	isZero |= isZero >> 8
+	isZero |= isZero >> 4
+	isZero |= isZero >> 2
+	isZero |= isZero >> 1
+
+	isP |= isP >> 16
+	isP |= isP >> 8
+	isP |= isP >> 4
+	isP |= isP >> 2
+	isP |= isP >> 1
+
+	// For isZero and isP, the LSB is 0 iff all the bits are zero.
+	result := isZero & isP
+	result = (^result) & 1
+
+	return result
+}
+
+// p224Add computes *out = a+b
+//
+// a[i] + b[i] < 2**32
+func p224Add(out, a, b *p224FieldElement) {
+	for i := 0; i < 8; i++ {
+		out[i] = a[i] + b[i]
+	}
+}
+
+const two31p3 = 1<<31 + 1<<3
+const two31m3 = 1<<31 - 1<<3
+const two31m15m3 = 1<<31 - 1<<15 - 1<<3
+
+// p224ZeroModP31 is 0 mod p where bit 31 is set in all limbs so that we can
+// subtract smaller amounts without underflow. See the section "Subtraction" in
+// [1] for reasoning.
+var p224ZeroModP31 = []uint32{two31p3, two31m3, two31m3, two31m15m3, two31m3, two31m3, two31m3, two31m3}
+
+// p224Sub computes *out = a-b
+//
+// a[i], b[i] < 2**30
+// out[i] < 2**32
+func p224Sub(out, a, b *p224FieldElement) {
+	for i := 0; i < 8; i++ {
+		out[i] = a[i] + p224ZeroModP31[i] - b[i]
+	}
+}
+
+// LargeFieldElement also represents an element of the field. The limbs are
+// still spaced 28-bits apart and in little-endian order. So the limbs are at
+// 0, 28, 56, ..., 392 bits, each 64-bits wide.
+type p224LargeFieldElement [15]uint64
+
+const two63p35 = 1<<63 + 1<<35
+const two63m35 = 1<<63 - 1<<35
+const two63m35m19 = 1<<63 - 1<<35 - 1<<19
+
+// p224ZeroModP63 is 0 mod p where bit 63 is set in all limbs. See the section
+// "Subtraction" in [1] for why.
+var p224ZeroModP63 = [8]uint64{two63p35, two63m35, two63m35, two63m35, two63m35m19, two63m35, two63m35, two63m35}
+
+const bottom12Bits = 0xfff
+const bottom28Bits = 0xfffffff
+
+// p224Mul computes *out = a*b
+//
+// a[i] < 2**29, b[i] < 2**30 (or vice versa)
+// out[i] < 2**29
+func p224Mul(out, a, b *p224FieldElement, tmp *p224LargeFieldElement) {
+	for i := 0; i < 15; i++ {
+		tmp[i] = 0
+	}
+
+	for i := 0; i < 8; i++ {
+		for j := 0; j < 8; j++ {
+			tmp[i+j] += uint64(a[i]) * uint64(b[j])
+		}
+	}
+
+	p224ReduceLarge(out, tmp)
+}
+
+// Square computes *out = a*a
+//
+// a[i] < 2**29
+// out[i] < 2**29
+func p224Square(out, a *p224FieldElement, tmp *p224LargeFieldElement) {
+	for i := 0; i < 15; i++ {
+		tmp[i] = 0
+	}
+
+	for i := 0; i < 8; i++ {
+		for j := 0; j <= i; j++ {
+			r := uint64(a[i]) * uint64(a[j])
+			if i == j {
+				tmp[i+j] += r
+			} else {
+				tmp[i+j] += r << 1
+			}
+		}
+	}
+
+	p224ReduceLarge(out, tmp)
+}
+
+// ReduceLarge converts a p224LargeFieldElement to a p224FieldElement.
+//
+// in[i] < 2**62
+func p224ReduceLarge(out *p224FieldElement, in *p224LargeFieldElement) {
+	for i := 0; i < 8; i++ {
+		in[i] += p224ZeroModP63[i]
+	}
+
+	// Eliminate the coefficients at 2**224 and greater.
+	for i := 14; i >= 8; i-- {
+		in[i-8] -= in[i]
+		in[i-5] += (in[i] & 0xffff) << 12
+		in[i-4] += in[i] >> 16
+	}
+	in[8] = 0
+	// in[0..8] < 2**64
+
+	// As the values become small enough, we start to store them in |out|
+	// and use 32-bit operations.
+	for i := 1; i < 8; i++ {
+		in[i+1] += in[i] >> 28
+		out[i] = uint32(in[i] & bottom28Bits)
+	}
+	in[0] -= in[8]
+	out[3] += uint32(in[8]&0xffff) << 12
+	out[4] += uint32(in[8] >> 16)
+	// in[0] < 2**64
+	// out[3] < 2**29
+	// out[4] < 2**29
+	// out[1,2,5..7] < 2**28
+
+	out[0] = uint32(in[0] & bottom28Bits)
+	out[1] += uint32((in[0] >> 28) & bottom28Bits)
+	out[2] += uint32(in[0] >> 56)
+	// out[0] < 2**28
+	// out[1..4] < 2**29
+	// out[5..7] < 2**28
+}
+
+// Reduce reduces the coefficients of a to smaller bounds.
+//
+// On entry: a[i] < 2**31 + 2**30
+// On exit: a[i] < 2**29
+func p224Reduce(a *p224FieldElement) {
+	for i := 0; i < 7; i++ {
+		a[i+1] += a[i] >> 28
+		a[i] &= bottom28Bits
+	}
+	top := a[7] >> 28
+	a[7] &= bottom28Bits
+
+	// top < 2**4
+	mask := top
+	mask |= mask >> 2
+	mask |= mask >> 1
+	mask <<= 31
+	mask = uint32(int32(mask) >> 31)
+	// Mask is all ones if top != 0, all zero otherwise
+
+	a[0] -= top
+	a[3] += top << 12
+
+	// We may have just made a[0] negative but, if we did, then we must
+	// have added something to a[3], this it's > 2**12. Therefore we can
+	// carry down to a[0].
+	a[3] -= 1 & mask
+	a[2] += mask & (1<<28 - 1)
+	a[1] += mask & (1<<28 - 1)
+	a[0] += mask & (1 << 28)
+}
+
+// p224Invert calculates *out = in**-1 by computing in**(2**224 - 2**96 - 1),
+// i.e. Fermat's little theorem.
+func p224Invert(out, in *p224FieldElement) {
+	var f1, f2, f3, f4 p224FieldElement
+	var c p224LargeFieldElement
+
+	p224Square(&f1, in, &c)    // 2
+	p224Mul(&f1, &f1, in, &c)  // 2**2 - 1
+	p224Square(&f1, &f1, &c)   // 2**3 - 2
+	p224Mul(&f1, &f1, in, &c)  // 2**3 - 1
+	p224Square(&f2, &f1, &c)   // 2**4 - 2
+	p224Square(&f2, &f2, &c)   // 2**5 - 4
+	p224Square(&f2, &f2, &c)   // 2**6 - 8
+	p224Mul(&f1, &f1, &f2, &c) // 2**6 - 1
+	p224Square(&f2, &f1, &c)   // 2**7 - 2
+	for i := 0; i < 5; i++ {   // 2**12 - 2**6
+		p224Square(&f2, &f2, &c)
+	}
+	p224Mul(&f2, &f2, &f1, &c) // 2**12 - 1
+	p224Square(&f3, &f2, &c)   // 2**13 - 2
+	for i := 0; i < 11; i++ {  // 2**24 - 2**12
+		p224Square(&f3, &f3, &c)
+	}
+	p224Mul(&f2, &f3, &f2, &c) // 2**24 - 1
+	p224Square(&f3, &f2, &c)   // 2**25 - 2
+	for i := 0; i < 23; i++ {  // 2**48 - 2**24
+		p224Square(&f3, &f3, &c)
+	}
+	p224Mul(&f3, &f3, &f2, &c) // 2**48 - 1
+	p224Square(&f4, &f3, &c)   // 2**49 - 2
+	for i := 0; i < 47; i++ {  // 2**96 - 2**48
+		p224Square(&f4, &f4, &c)
+	}
+	p224Mul(&f3, &f3, &f4, &c) // 2**96 - 1
+	p224Square(&f4, &f3, &c)   // 2**97 - 2
+	for i := 0; i < 23; i++ {  // 2**120 - 2**24
+		p224Square(&f4, &f4, &c)
+	}
+	p224Mul(&f2, &f4, &f2, &c) // 2**120 - 1
+	for i := 0; i < 6; i++ {   // 2**126 - 2**6
+		p224Square(&f2, &f2, &c)
+	}
+	p224Mul(&f1, &f1, &f2, &c) // 2**126 - 1
+	p224Square(&f1, &f1, &c)   // 2**127 - 2
+	p224Mul(&f1, &f1, in, &c)  // 2**127 - 1
+	for i := 0; i < 97; i++ {  // 2**224 - 2**97
+		p224Square(&f1, &f1, &c)
+	}
+	p224Mul(out, &f1, &f3, &c) // 2**224 - 2**96 - 1
+}
+
+// p224Contract converts a FieldElement to its unique, minimal form.
+//
+// On entry, in[i] < 2**29
+// On exit, in[i] < 2**28
+func p224Contract(out, in *p224FieldElement) {
+	copy(out[:], in[:])
+
+	for i := 0; i < 7; i++ {
+		out[i+1] += out[i] >> 28
+		out[i] &= bottom28Bits
+	}
+	top := out[7] >> 28
+	out[7] &= bottom28Bits
+
+	out[0] -= top
+	out[3] += top << 12
+
+	// We may just have made out[i] negative. So we carry down. If we made
+	// out[0] negative then we know that out[3] is sufficiently positive
+	// because we just added to it.
+	for i := 0; i < 3; i++ {
+		mask := uint32(int32(out[i]) >> 31)
+		out[i] += (1 << 28) & mask
+		out[i+1] -= 1 & mask
+	}
+
+	// We might have pushed out[3] over 2**28 so we perform another, partial,
+	// carry chain.
+	for i := 3; i < 7; i++ {
+		out[i+1] += out[i] >> 28
+		out[i] &= bottom28Bits
+	}
+	top = out[7] >> 28
+	out[7] &= bottom28Bits
+
+	// Eliminate top while maintaining the same value mod p.
+	out[0] -= top
+	out[3] += top << 12
+
+	// There are two cases to consider for out[3]:
+	//   1) The first time that we eliminated top, we didn't push out[3] over
+	//      2**28. In this case, the partial carry chain didn't change any values
+	//      and top is zero.
+	//   2) We did push out[3] over 2**28 the first time that we eliminated top.
+	//      The first value of top was in [0..16), therefore, prior to eliminating
+	//      the first top, 0xfff1000 <= out[3] <= 0xfffffff. Therefore, after
+	//      overflowing and being reduced by the second carry chain, out[3] <=
+	//      0xf000. Thus it cannot have overflowed when we eliminated top for the
+	//      second time.
+
+	// Again, we may just have made out[0] negative, so do the same carry down.
+	// As before, if we made out[0] negative then we know that out[3] is
+	// sufficiently positive.
+	for i := 0; i < 3; i++ {
+		mask := uint32(int32(out[i]) >> 31)
+		out[i] += (1 << 28) & mask
+		out[i+1] -= 1 & mask
+	}
+
+	// Now we see if the value is >= p and, if so, subtract p.
+
+	// First we build a mask from the top four limbs, which must all be
+	// equal to bottom28Bits if the whole value is >= p. If top4AllOnes
+	// ends up with any zero bits in the bottom 28 bits, then this wasn't
+	// true.
+	top4AllOnes := uint32(0xffffffff)
+	for i := 4; i < 8; i++ {
+		top4AllOnes &= out[i]
+	}
+	top4AllOnes |= 0xf0000000
+	// Now we replicate any zero bits to all the bits in top4AllOnes.
+	top4AllOnes &= top4AllOnes >> 16
+	top4AllOnes &= top4AllOnes >> 8
+	top4AllOnes &= top4AllOnes >> 4
+	top4AllOnes &= top4AllOnes >> 2
+	top4AllOnes &= top4AllOnes >> 1
+	top4AllOnes = uint32(int32(top4AllOnes<<31) >> 31)
+
+	// Now we test whether the bottom three limbs are non-zero.
+	bottom3NonZero := out[0] | out[1] | out[2]
+	bottom3NonZero |= bottom3NonZero >> 16
+	bottom3NonZero |= bottom3NonZero >> 8
+	bottom3NonZero |= bottom3NonZero >> 4
+	bottom3NonZero |= bottom3NonZero >> 2
+	bottom3NonZero |= bottom3NonZero >> 1
+	bottom3NonZero = uint32(int32(bottom3NonZero<<31) >> 31)
+
+	// Everything depends on the value of out[3].
+	//    If it's > 0xffff000 and top4AllOnes != 0 then the whole value is >= p
+	//    If it's = 0xffff000 and top4AllOnes != 0 and bottom3NonZero != 0,
+	//      then the whole value is >= p
+	//    If it's < 0xffff000, then the whole value is < p
+	n := out[3] - 0xffff000
+	out3Equal := n
+	out3Equal |= out3Equal >> 16
+	out3Equal |= out3Equal >> 8
+	out3Equal |= out3Equal >> 4
+	out3Equal |= out3Equal >> 2
+	out3Equal |= out3Equal >> 1
+	out3Equal = ^uint32(int32(out3Equal<<31) >> 31)
+
+	// If out[3] > 0xffff000 then n's MSB will be zero.
+	out3GT := ^uint32(int32(n) >> 31)
+
+	mask := top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT)
+	out[0] -= 1 & mask
+	out[3] -= 0xffff000 & mask
+	out[4] -= 0xfffffff & mask
+	out[5] -= 0xfffffff & mask
+	out[6] -= 0xfffffff & mask
+	out[7] -= 0xfffffff & mask
+}
+
+// Group element functions.
+//
+// These functions deal with group elements. The group is an elliptic curve
+// group with a = -3 defined in FIPS 186-3, section D.2.2.
+
+// p224AddJacobian computes *out = a+b where a != b.
+func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
+	// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-p224Add-2007-bl
+	var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement
+	var c p224LargeFieldElement
+
+	z1IsZero := p224IsZero(z1)
+	z2IsZero := p224IsZero(z2)
+
+	// Z1Z1 = Z1²
+	p224Square(&z1z1, z1, &c)
+	// Z2Z2 = Z2²
+	p224Square(&z2z2, z2, &c)
+	// U1 = X1*Z2Z2
+	p224Mul(&u1, x1, &z2z2, &c)
+	// U2 = X2*Z1Z1
+	p224Mul(&u2, x2, &z1z1, &c)
+	// S1 = Y1*Z2*Z2Z2
+	p224Mul(&s1, z2, &z2z2, &c)
+	p224Mul(&s1, y1, &s1, &c)
+	// S2 = Y2*Z1*Z1Z1
+	p224Mul(&s2, z1, &z1z1, &c)
+	p224Mul(&s2, y2, &s2, &c)
+	// H = U2-U1
+	p224Sub(&h, &u2, &u1)
+	p224Reduce(&h)
+	xEqual := p224IsZero(&h)
+	// I = (2*H)²
+	for j := 0; j < 8; j++ {
+		i[j] = h[j] << 1
+	}
+	p224Reduce(&i)
+	p224Square(&i, &i, &c)
+	// J = H*I
+	p224Mul(&j, &h, &i, &c)
+	// r = 2*(S2-S1)
+	p224Sub(&r, &s2, &s1)
+	p224Reduce(&r)
+	yEqual := p224IsZero(&r)
+	if xEqual == 1 && yEqual == 1 && z1IsZero == 0 && z2IsZero == 0 {
+		p224DoubleJacobian(x3, y3, z3, x1, y1, z1)
+		return
+	}
+	for i := 0; i < 8; i++ {
+		r[i] <<= 1
+	}
+	p224Reduce(&r)
+	// V = U1*I
+	p224Mul(&v, &u1, &i, &c)
+	// Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H
+	p224Add(&z1z1, &z1z1, &z2z2)
+	p224Add(&z2z2, z1, z2)
+	p224Reduce(&z2z2)
+	p224Square(&z2z2, &z2z2, &c)
+	p224Sub(z3, &z2z2, &z1z1)
+	p224Reduce(z3)
+	p224Mul(z3, z3, &h, &c)
+	// X3 = r²-J-2*V
+	for i := 0; i < 8; i++ {
+		z1z1[i] = v[i] << 1
+	}
+	p224Add(&z1z1, &j, &z1z1)
+	p224Reduce(&z1z1)
+	p224Square(x3, &r, &c)
+	p224Sub(x3, x3, &z1z1)
+	p224Reduce(x3)
+	// Y3 = r*(V-X3)-2*S1*J
+	for i := 0; i < 8; i++ {
+		s1[i] <<= 1
+	}
+	p224Mul(&s1, &s1, &j, &c)
+	p224Sub(&z1z1, &v, x3)
+	p224Reduce(&z1z1)
+	p224Mul(&z1z1, &z1z1, &r, &c)
+	p224Sub(y3, &z1z1, &s1)
+	p224Reduce(y3)
+
+	p224CopyConditional(x3, x2, z1IsZero)
+	p224CopyConditional(x3, x1, z2IsZero)
+	p224CopyConditional(y3, y2, z1IsZero)
+	p224CopyConditional(y3, y1, z2IsZero)
+	p224CopyConditional(z3, z2, z1IsZero)
+	p224CopyConditional(z3, z1, z2IsZero)
+}
+
+// p224DoubleJacobian computes *out = a+a.
+func p224DoubleJacobian(x3, y3, z3, x1, y1, z1 *p224FieldElement) {
+	var delta, gamma, beta, alpha, t p224FieldElement
+	var c p224LargeFieldElement
+
+	p224Square(&delta, z1, &c)
+	p224Square(&gamma, y1, &c)
+	p224Mul(&beta, x1, &gamma, &c)
+
+	// alpha = 3*(X1-delta)*(X1+delta)
+	p224Add(&t, x1, &delta)
+	for i := 0; i < 8; i++ {
+		t[i] += t[i] << 1
+	}
+	p224Reduce(&t)
+	p224Sub(&alpha, x1, &delta)
+	p224Reduce(&alpha)
+	p224Mul(&alpha, &alpha, &t, &c)
+
+	// Z3 = (Y1+Z1)²-gamma-delta
+	p224Add(z3, y1, z1)
+	p224Reduce(z3)
+	p224Square(z3, z3, &c)
+	p224Sub(z3, z3, &gamma)
+	p224Reduce(z3)
+	p224Sub(z3, z3, &delta)
+	p224Reduce(z3)
+
+	// X3 = alpha²-8*beta
+	for i := 0; i < 8; i++ {
+		delta[i] = beta[i] << 3
+	}
+	p224Reduce(&delta)
+	p224Square(x3, &alpha, &c)
+	p224Sub(x3, x3, &delta)
+	p224Reduce(x3)
+
+	// Y3 = alpha*(4*beta-X3)-8*gamma²
+	for i := 0; i < 8; i++ {
+		beta[i] <<= 2
+	}
+	p224Sub(&beta, &beta, x3)
+	p224Reduce(&beta)
+	p224Square(&gamma, &gamma, &c)
+	for i := 0; i < 8; i++ {
+		gamma[i] <<= 3
+	}
+	p224Reduce(&gamma)
+	p224Mul(y3, &alpha, &beta, &c)
+	p224Sub(y3, y3, &gamma)
+	p224Reduce(y3)
+}
+
+// p224CopyConditional sets *out = *in iff the least-significant-bit of control
+// is true, and it runs in constant time.
+func p224CopyConditional(out, in *p224FieldElement, control uint32) {
+	control <<= 31
+	control = uint32(int32(control) >> 31)
+
+	for i := 0; i < 8; i++ {
+		out[i] ^= (out[i] ^ in[i]) & control
+	}
+}
+
+func p224ScalarMult(outX, outY, outZ, inX, inY, inZ *p224FieldElement, scalar []byte) {
+	var xx, yy, zz p224FieldElement
+	for i := 0; i < 8; i++ {
+		outX[i] = 0
+		outY[i] = 0
+		outZ[i] = 0
+	}
+
+	for _, byte := range scalar {
+		for bitNum := uint(0); bitNum < 8; bitNum++ {
+			p224DoubleJacobian(outX, outY, outZ, outX, outY, outZ)
+			bit := uint32((byte >> (7 - bitNum)) & 1)
+			p224AddJacobian(&xx, &yy, &zz, inX, inY, inZ, outX, outY, outZ)
+			p224CopyConditional(outX, &xx, bit)
+			p224CopyConditional(outY, &yy, bit)
+			p224CopyConditional(outZ, &zz, bit)
+		}
+	}
+}
+
+// p224ToAffine converts from Jacobian to affine form.
+func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) {
+	var zinv, zinvsq, outx, outy p224FieldElement
+	var tmp p224LargeFieldElement
+
+	if isPointAtInfinity := p224IsZero(z); isPointAtInfinity == 1 {
+		return new(big.Int), new(big.Int)
+	}
+
+	p224Invert(&zinv, z)
+	p224Square(&zinvsq, &zinv, &tmp)
+	p224Mul(x, x, &zinvsq, &tmp)
+	p224Mul(&zinvsq, &zinvsq, &zinv, &tmp)
+	p224Mul(y, y, &zinvsq, &tmp)
+
+	p224Contract(&outx, x)
+	p224Contract(&outy, y)
+	return p224ToBig(&outx), p224ToBig(&outy)
+}
+
+// get28BitsFromEnd returns the least-significant 28 bits from buf>>shift,
+// where buf is interpreted as a big-endian number.
+func get28BitsFromEnd(buf []byte, shift uint) (uint32, []byte) {
+	var ret uint32
+
+	for i := uint(0); i < 4; i++ {
+		var b byte
+		if l := len(buf); l > 0 {
+			b = buf[l-1]
+			// We don't remove the byte if we're about to return and we're not
+			// reading all of it.
+			if i != 3 || shift == 4 {
+				buf = buf[:l-1]
+			}
+		}
+		ret |= uint32(b) << (8 * i) >> shift
+	}
+	ret &= bottom28Bits
+	return ret, buf
+}
+
+// p224FromBig sets *out = *in.
+func p224FromBig(out *p224FieldElement, in *big.Int) {
+	bytes := in.Bytes()
+	out[0], bytes = get28BitsFromEnd(bytes, 0)
+	out[1], bytes = get28BitsFromEnd(bytes, 4)
+	out[2], bytes = get28BitsFromEnd(bytes, 0)
+	out[3], bytes = get28BitsFromEnd(bytes, 4)
+	out[4], bytes = get28BitsFromEnd(bytes, 0)
+	out[5], bytes = get28BitsFromEnd(bytes, 4)
+	out[6], bytes = get28BitsFromEnd(bytes, 0)
+	out[7], bytes = get28BitsFromEnd(bytes, 4)
+}
+
+// p224ToBig returns in as a big.Int.
+func p224ToBig(in *p224FieldElement) *big.Int {
+	var buf [28]byte
+	buf[27] = byte(in[0])
+	buf[26] = byte(in[0] >> 8)
+	buf[25] = byte(in[0] >> 16)
+	buf[24] = byte(((in[0] >> 24) & 0x0f) | (in[1]<<4)&0xf0)
+
+	buf[23] = byte(in[1] >> 4)
+	buf[22] = byte(in[1] >> 12)
+	buf[21] = byte(in[1] >> 20)
+
+	buf[20] = byte(in[2])
+	buf[19] = byte(in[2] >> 8)
+	buf[18] = byte(in[2] >> 16)
+	buf[17] = byte(((in[2] >> 24) & 0x0f) | (in[3]<<4)&0xf0)
+
+	buf[16] = byte(in[3] >> 4)
+	buf[15] = byte(in[3] >> 12)
+	buf[14] = byte(in[3] >> 20)
+
+	buf[13] = byte(in[4])
+	buf[12] = byte(in[4] >> 8)
+	buf[11] = byte(in[4] >> 16)
+	buf[10] = byte(((in[4] >> 24) & 0x0f) | (in[5]<<4)&0xf0)
+
+	buf[9] = byte(in[5] >> 4)
+	buf[8] = byte(in[5] >> 12)
+	buf[7] = byte(in[5] >> 20)
+
+	buf[6] = byte(in[6])
+	buf[5] = byte(in[6] >> 8)
+	buf[4] = byte(in[6] >> 16)
+	buf[3] = byte(((in[6] >> 24) & 0x0f) | (in[7]<<4)&0xf0)
+
+	buf[2] = byte(in[7] >> 4)
+	buf[1] = byte(in[7] >> 12)
+	buf[0] = byte(in[7] >> 20)
+
+	return new(big.Int).SetBytes(buf[:])
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/elliptic/p224_test.go b/third_party/gofrontend/libgo/go/crypto/elliptic/p224_test.go
new file mode 100644
index 0000000..4b26d16
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/elliptic/p224_test.go
@@ -0,0 +1,47 @@
+// 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 elliptic
+
+import (
+	"math/big"
+	"testing"
+)
+
+var toFromBigTests = []string{
+	"0",
+	"1",
+	"23",
+	"b70e0cb46bb4bf7f321390b94a03c1d356c01122343280d6105c1d21",
+	"706a46d476dcb76798e6046d89474788d164c18032d268fd10704fa6",
+}
+
+func p224AlternativeToBig(in *p224FieldElement) *big.Int {
+	ret := new(big.Int)
+	tmp := new(big.Int)
+
+	for i := uint(0); i < 8; i++ {
+		tmp.SetInt64(int64(in[i]))
+		tmp.Lsh(tmp, 28*i)
+		ret.Add(ret, tmp)
+	}
+	ret.Mod(ret, p224.P)
+	return ret
+}
+
+func TestToFromBig(t *testing.T) {
+	for i, test := range toFromBigTests {
+		n, _ := new(big.Int).SetString(test, 16)
+		var x p224FieldElement
+		p224FromBig(&x, n)
+		m := p224ToBig(&x)
+		if n.Cmp(m) != 0 {
+			t.Errorf("#%d: %x != %x", i, n, m)
+		}
+		q := p224AlternativeToBig(&x)
+		if n.Cmp(q) != 0 {
+			t.Errorf("#%d: %x != %x (alternative)", i, n, m)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/elliptic/p256.go b/third_party/gofrontend/libgo/go/crypto/elliptic/p256.go
new file mode 100644
index 0000000..82be51e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/elliptic/p256.go
@@ -0,0 +1,1186 @@
+// Copyright 2013 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 elliptic
+
+// This file contains a constant-time, 32-bit implementation of P256.
+
+import (
+	"math/big"
+)
+
+type p256Curve struct {
+	*CurveParams
+}
+
+var (
+	p256 p256Curve
+	// RInverse contains 1/R mod p - the inverse of the Montgomery constant
+	// (2**257).
+	p256RInverse *big.Int
+)
+
+func initP256() {
+	// See FIPS 186-3, section D.2.3
+	p256.CurveParams = new(CurveParams)
+	p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
+	p256.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
+	p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
+	p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
+	p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
+	p256.BitSize = 256
+
+	p256RInverse, _ = new(big.Int).SetString("7fffffff00000001fffffffe8000000100000000ffffffff0000000180000000", 16)
+}
+
+func (curve p256Curve) Params() *CurveParams {
+	return curve.CurveParams
+}
+
+// p256GetScalar endian-swaps the big-endian scalar value from in and writes it
+// to out. If the scalar is equal or greater than the order of the group, it's
+// reduced modulo that order.
+func p256GetScalar(out *[32]byte, in []byte) {
+	n := new(big.Int).SetBytes(in)
+	var scalarBytes []byte
+
+	if n.Cmp(p256.N) >= 0 {
+		n.Mod(n, p256.N)
+		scalarBytes = n.Bytes()
+	} else {
+		scalarBytes = in
+	}
+
+	for i, v := range scalarBytes {
+		out[len(scalarBytes)-(1+i)] = v
+	}
+}
+
+func (p256Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
+	var scalarReversed [32]byte
+	p256GetScalar(&scalarReversed, scalar)
+
+	var x1, y1, z1 [p256Limbs]uint32
+	p256ScalarBaseMult(&x1, &y1, &z1, &scalarReversed)
+	return p256ToAffine(&x1, &y1, &z1)
+}
+
+func (p256Curve) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y *big.Int) {
+	var scalarReversed [32]byte
+	p256GetScalar(&scalarReversed, scalar)
+
+	var px, py, x1, y1, z1 [p256Limbs]uint32
+	p256FromBig(&px, bigX)
+	p256FromBig(&py, bigY)
+	p256ScalarMult(&x1, &y1, &z1, &px, &py, &scalarReversed)
+	return p256ToAffine(&x1, &y1, &z1)
+}
+
+// Field elements are represented as nine, unsigned 32-bit words.
+//
+// The value of an field element is:
+//   x[0] + (x[1] * 2**29) + (x[2] * 2**57) + ... + (x[8] * 2**228)
+//
+// That is, each limb is alternately 29 or 28-bits wide in little-endian
+// order.
+//
+// This means that a field element hits 2**257, rather than 2**256 as we would
+// like. A 28, 29, ... pattern would cause us to hit 2**256, but that causes
+// problems when multiplying as terms end up one bit short of a limb which
+// would require much bit-shifting to correct.
+//
+// Finally, the values stored in a field element are in Montgomery form. So the
+// value |y| is stored as (y*R) mod p, where p is the P-256 prime and R is
+// 2**257.
+
+const (
+	p256Limbs    = 9
+	bottom29Bits = 0x1fffffff
+)
+
+var (
+	// p256One is the number 1 as a field element.
+	p256One  = [p256Limbs]uint32{2, 0, 0, 0xffff800, 0x1fffffff, 0xfffffff, 0x1fbfffff, 0x1ffffff, 0}
+	p256Zero = [p256Limbs]uint32{0, 0, 0, 0, 0, 0, 0, 0, 0}
+	// p256P is the prime modulus as a field element.
+	p256P = [p256Limbs]uint32{0x1fffffff, 0xfffffff, 0x1fffffff, 0x3ff, 0, 0, 0x200000, 0xf000000, 0xfffffff}
+	// p2562P is the twice prime modulus as a field element.
+	p2562P = [p256Limbs]uint32{0x1ffffffe, 0xfffffff, 0x1fffffff, 0x7ff, 0, 0, 0x400000, 0xe000000, 0x1fffffff}
+)
+
+// p256Precomputed contains precomputed values to aid the calculation of scalar
+// multiples of the base point, G. It's actually two, equal length, tables
+// concatenated.
+//
+// The first table contains (x,y) field element pairs for 16 multiples of the
+// base point, G.
+//
+//   Index  |  Index (binary) | Value
+//       0  |           0000  | 0G (all zeros, omitted)
+//       1  |           0001  | G
+//       2  |           0010  | 2**64G
+//       3  |           0011  | 2**64G + G
+//       4  |           0100  | 2**128G
+//       5  |           0101  | 2**128G + G
+//       6  |           0110  | 2**128G + 2**64G
+//       7  |           0111  | 2**128G + 2**64G + G
+//       8  |           1000  | 2**192G
+//       9  |           1001  | 2**192G + G
+//      10  |           1010  | 2**192G + 2**64G
+//      11  |           1011  | 2**192G + 2**64G + G
+//      12  |           1100  | 2**192G + 2**128G
+//      13  |           1101  | 2**192G + 2**128G + G
+//      14  |           1110  | 2**192G + 2**128G + 2**64G
+//      15  |           1111  | 2**192G + 2**128G + 2**64G + G
+//
+// The second table follows the same style, but the terms are 2**32G,
+// 2**96G, 2**160G, 2**224G.
+//
+// This is ~2KB of data.
+var p256Precomputed = [p256Limbs * 2 * 15 * 2]uint32{
+	0x11522878, 0xe730d41, 0xdb60179, 0x4afe2ff, 0x12883add, 0xcaddd88, 0x119e7edc, 0xd4a6eab, 0x3120bee,
+	0x1d2aac15, 0xf25357c, 0x19e45cdd, 0x5c721d0, 0x1992c5a5, 0xa237487, 0x154ba21, 0x14b10bb, 0xae3fe3,
+	0xd41a576, 0x922fc51, 0x234994f, 0x60b60d3, 0x164586ae, 0xce95f18, 0x1fe49073, 0x3fa36cc, 0x5ebcd2c,
+	0xb402f2f, 0x15c70bf, 0x1561925c, 0x5a26704, 0xda91e90, 0xcdc1c7f, 0x1ea12446, 0xe1ade1e, 0xec91f22,
+	0x26f7778, 0x566847e, 0xa0bec9e, 0x234f453, 0x1a31f21a, 0xd85e75c, 0x56c7109, 0xa267a00, 0xb57c050,
+	0x98fb57, 0xaa837cc, 0x60c0792, 0xcfa5e19, 0x61bab9e, 0x589e39b, 0xa324c5, 0x7d6dee7, 0x2976e4b,
+	0x1fc4124a, 0xa8c244b, 0x1ce86762, 0xcd61c7e, 0x1831c8e0, 0x75774e1, 0x1d96a5a9, 0x843a649, 0xc3ab0fa,
+	0x6e2e7d5, 0x7673a2a, 0x178b65e8, 0x4003e9b, 0x1a1f11c2, 0x7816ea, 0xf643e11, 0x58c43df, 0xf423fc2,
+	0x19633ffa, 0x891f2b2, 0x123c231c, 0x46add8c, 0x54700dd, 0x59e2b17, 0x172db40f, 0x83e277d, 0xb0dd609,
+	0xfd1da12, 0x35c6e52, 0x19ede20c, 0xd19e0c0, 0x97d0f40, 0xb015b19, 0x449e3f5, 0xe10c9e, 0x33ab581,
+	0x56a67ab, 0x577734d, 0x1dddc062, 0xc57b10d, 0x149b39d, 0x26a9e7b, 0xc35df9f, 0x48764cd, 0x76dbcca,
+	0xca4b366, 0xe9303ab, 0x1a7480e7, 0x57e9e81, 0x1e13eb50, 0xf466cf3, 0x6f16b20, 0x4ba3173, 0xc168c33,
+	0x15cb5439, 0x6a38e11, 0x73658bd, 0xb29564f, 0x3f6dc5b, 0x53b97e, 0x1322c4c0, 0x65dd7ff, 0x3a1e4f6,
+	0x14e614aa, 0x9246317, 0x1bc83aca, 0xad97eed, 0xd38ce4a, 0xf82b006, 0x341f077, 0xa6add89, 0x4894acd,
+	0x9f162d5, 0xf8410ef, 0x1b266a56, 0xd7f223, 0x3e0cb92, 0xe39b672, 0x6a2901a, 0x69a8556, 0x7e7c0,
+	0x9b7d8d3, 0x309a80, 0x1ad05f7f, 0xc2fb5dd, 0xcbfd41d, 0x9ceb638, 0x1051825c, 0xda0cf5b, 0x812e881,
+	0x6f35669, 0x6a56f2c, 0x1df8d184, 0x345820, 0x1477d477, 0x1645db1, 0xbe80c51, 0xc22be3e, 0xe35e65a,
+	0x1aeb7aa0, 0xc375315, 0xf67bc99, 0x7fdd7b9, 0x191fc1be, 0x61235d, 0x2c184e9, 0x1c5a839, 0x47a1e26,
+	0xb7cb456, 0x93e225d, 0x14f3c6ed, 0xccc1ac9, 0x17fe37f3, 0x4988989, 0x1a90c502, 0x2f32042, 0xa17769b,
+	0xafd8c7c, 0x8191c6e, 0x1dcdb237, 0x16200c0, 0x107b32a1, 0x66c08db, 0x10d06a02, 0x3fc93, 0x5620023,
+	0x16722b27, 0x68b5c59, 0x270fcfc, 0xfad0ecc, 0xe5de1c2, 0xeab466b, 0x2fc513c, 0x407f75c, 0xbaab133,
+	0x9705fe9, 0xb88b8e7, 0x734c993, 0x1e1ff8f, 0x19156970, 0xabd0f00, 0x10469ea7, 0x3293ac0, 0xcdc98aa,
+	0x1d843fd, 0xe14bfe8, 0x15be825f, 0x8b5212, 0xeb3fb67, 0x81cbd29, 0xbc62f16, 0x2b6fcc7, 0xf5a4e29,
+	0x13560b66, 0xc0b6ac2, 0x51ae690, 0xd41e271, 0xf3e9bd4, 0x1d70aab, 0x1029f72, 0x73e1c35, 0xee70fbc,
+	0xad81baf, 0x9ecc49a, 0x86c741e, 0xfe6be30, 0x176752e7, 0x23d416, 0x1f83de85, 0x27de188, 0x66f70b8,
+	0x181cd51f, 0x96b6e4c, 0x188f2335, 0xa5df759, 0x17a77eb6, 0xfeb0e73, 0x154ae914, 0x2f3ec51, 0x3826b59,
+	0xb91f17d, 0x1c72949, 0x1362bf0a, 0xe23fddf, 0xa5614b0, 0xf7d8f, 0x79061, 0x823d9d2, 0x8213f39,
+	0x1128ae0b, 0xd095d05, 0xb85c0c2, 0x1ecb2ef, 0x24ddc84, 0xe35e901, 0x18411a4a, 0xf5ddc3d, 0x3786689,
+	0x52260e8, 0x5ae3564, 0x542b10d, 0x8d93a45, 0x19952aa4, 0x996cc41, 0x1051a729, 0x4be3499, 0x52b23aa,
+	0x109f307e, 0x6f5b6bb, 0x1f84e1e7, 0x77a0cfa, 0x10c4df3f, 0x25a02ea, 0xb048035, 0xe31de66, 0xc6ecaa3,
+	0x28ea335, 0x2886024, 0x1372f020, 0xf55d35, 0x15e4684c, 0xf2a9e17, 0x1a4a7529, 0xcb7beb1, 0xb2a78a1,
+	0x1ab21f1f, 0x6361ccf, 0x6c9179d, 0xb135627, 0x1267b974, 0x4408bad, 0x1cbff658, 0xe3d6511, 0xc7d76f,
+	0x1cc7a69, 0xe7ee31b, 0x54fab4f, 0x2b914f, 0x1ad27a30, 0xcd3579e, 0xc50124c, 0x50daa90, 0xb13f72,
+	0xb06aa75, 0x70f5cc6, 0x1649e5aa, 0x84a5312, 0x329043c, 0x41c4011, 0x13d32411, 0xb04a838, 0xd760d2d,
+	0x1713b532, 0xbaa0c03, 0x84022ab, 0x6bcf5c1, 0x2f45379, 0x18ae070, 0x18c9e11e, 0x20bca9a, 0x66f496b,
+	0x3eef294, 0x67500d2, 0xd7f613c, 0x2dbbeb, 0xb741038, 0xe04133f, 0x1582968d, 0xbe985f7, 0x1acbc1a,
+	0x1a6a939f, 0x33e50f6, 0xd665ed4, 0xb4b7bd6, 0x1e5a3799, 0x6b33847, 0x17fa56ff, 0x65ef930, 0x21dc4a,
+	0x2b37659, 0x450fe17, 0xb357b65, 0xdf5efac, 0x15397bef, 0x9d35a7f, 0x112ac15f, 0x624e62e, 0xa90ae2f,
+	0x107eecd2, 0x1f69bbe, 0x77d6bce, 0x5741394, 0x13c684fc, 0x950c910, 0x725522b, 0xdc78583, 0x40eeabb,
+	0x1fde328a, 0xbd61d96, 0xd28c387, 0x9e77d89, 0x12550c40, 0x759cb7d, 0x367ef34, 0xae2a960, 0x91b8bdc,
+	0x93462a9, 0xf469ef, 0xb2e9aef, 0xd2ca771, 0x54e1f42, 0x7aaa49, 0x6316abb, 0x2413c8e, 0x5425bf9,
+	0x1bed3e3a, 0xf272274, 0x1f5e7326, 0x6416517, 0xea27072, 0x9cedea7, 0x6e7633, 0x7c91952, 0xd806dce,
+	0x8e2a7e1, 0xe421e1a, 0x418c9e1, 0x1dbc890, 0x1b395c36, 0xa1dc175, 0x1dc4ef73, 0x8956f34, 0xe4b5cf2,
+	0x1b0d3a18, 0x3194a36, 0x6c2641f, 0xe44124c, 0xa2f4eaa, 0xa8c25ba, 0xf927ed7, 0x627b614, 0x7371cca,
+	0xba16694, 0x417bc03, 0x7c0a7e3, 0x9c35c19, 0x1168a205, 0x8b6b00d, 0x10e3edc9, 0x9c19bf2, 0x5882229,
+	0x1b2b4162, 0xa5cef1a, 0x1543622b, 0x9bd433e, 0x364e04d, 0x7480792, 0x5c9b5b3, 0xe85ff25, 0x408ef57,
+	0x1814cfa4, 0x121b41b, 0xd248a0f, 0x3b05222, 0x39bb16a, 0xc75966d, 0xa038113, 0xa4a1769, 0x11fbc6c,
+	0x917e50e, 0xeec3da8, 0x169d6eac, 0x10c1699, 0xa416153, 0xf724912, 0x15cd60b7, 0x4acbad9, 0x5efc5fa,
+	0xf150ed7, 0x122b51, 0x1104b40a, 0xcb7f442, 0xfbb28ff, 0x6ac53ca, 0x196142cc, 0x7bf0fa9, 0x957651,
+	0x4e0f215, 0xed439f8, 0x3f46bd5, 0x5ace82f, 0x110916b6, 0x6db078, 0xffd7d57, 0xf2ecaac, 0xca86dec,
+	0x15d6b2da, 0x965ecc9, 0x1c92b4c2, 0x1f3811, 0x1cb080f5, 0x2d8b804, 0x19d1c12d, 0xf20bd46, 0x1951fa7,
+	0xa3656c3, 0x523a425, 0xfcd0692, 0xd44ddc8, 0x131f0f5b, 0xaf80e4a, 0xcd9fc74, 0x99bb618, 0x2db944c,
+	0xa673090, 0x1c210e1, 0x178c8d23, 0x1474383, 0x10b8743d, 0x985a55b, 0x2e74779, 0x576138, 0x9587927,
+	0x133130fa, 0xbe05516, 0x9f4d619, 0xbb62570, 0x99ec591, 0xd9468fe, 0x1d07782d, 0xfc72e0b, 0x701b298,
+	0x1863863b, 0x85954b8, 0x121a0c36, 0x9e7fedf, 0xf64b429, 0x9b9d71e, 0x14e2f5d8, 0xf858d3a, 0x942eea8,
+	0xda5b765, 0x6edafff, 0xa9d18cc, 0xc65e4ba, 0x1c747e86, 0xe4ea915, 0x1981d7a1, 0x8395659, 0x52ed4e2,
+	0x87d43b7, 0x37ab11b, 0x19d292ce, 0xf8d4692, 0x18c3053f, 0x8863e13, 0x4c146c0, 0x6bdf55a, 0x4e4457d,
+	0x16152289, 0xac78ec2, 0x1a59c5a2, 0x2028b97, 0x71c2d01, 0x295851f, 0x404747b, 0x878558d, 0x7d29aa4,
+	0x13d8341f, 0x8daefd7, 0x139c972d, 0x6b7ea75, 0xd4a9dde, 0xff163d8, 0x81d55d7, 0xa5bef68, 0xb7b30d8,
+	0xbe73d6f, 0xaa88141, 0xd976c81, 0x7e7a9cc, 0x18beb771, 0xd773cbd, 0x13f51951, 0x9d0c177, 0x1c49a78,
+}
+
+// Field element operations:
+
+// nonZeroToAllOnes returns:
+//   0xffffffff for 0 < x <= 2**31
+//   0 for x == 0 or x > 2**31.
+func nonZeroToAllOnes(x uint32) uint32 {
+	return ((x - 1) >> 31) - 1
+}
+
+// p256ReduceCarry adds a multiple of p in order to cancel |carry|,
+// which is a term at 2**257.
+//
+// On entry: carry < 2**3, inout[0,2,...] < 2**29, inout[1,3,...] < 2**28.
+// On exit: inout[0,2,..] < 2**30, inout[1,3,...] < 2**29.
+func p256ReduceCarry(inout *[p256Limbs]uint32, carry uint32) {
+	carry_mask := nonZeroToAllOnes(carry)
+
+	inout[0] += carry << 1
+	inout[3] += 0x10000000 & carry_mask
+	// carry < 2**3 thus (carry << 11) < 2**14 and we added 2**28 in the
+	// previous line therefore this doesn't underflow.
+	inout[3] -= carry << 11
+	inout[4] += (0x20000000 - 1) & carry_mask
+	inout[5] += (0x10000000 - 1) & carry_mask
+	inout[6] += (0x20000000 - 1) & carry_mask
+	inout[6] -= carry << 22
+	// This may underflow if carry is non-zero but, if so, we'll fix it in the
+	// next line.
+	inout[7] -= 1 & carry_mask
+	inout[7] += carry << 25
+}
+
+// p256Sum sets out = in+in2.
+//
+// On entry, in[i]+in2[i] must not overflow a 32-bit word.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29
+func p256Sum(out, in, in2 *[p256Limbs]uint32) {
+	carry := uint32(0)
+	for i := 0; ; i++ {
+		out[i] = in[i] + in2[i]
+		out[i] += carry
+		carry = out[i] >> 29
+		out[i] &= bottom29Bits
+
+		i++
+		if i == p256Limbs {
+			break
+		}
+
+		out[i] = in[i] + in2[i]
+		out[i] += carry
+		carry = out[i] >> 28
+		out[i] &= bottom28Bits
+	}
+
+	p256ReduceCarry(out, carry)
+}
+
+const (
+	two30m2    = 1<<30 - 1<<2
+	two30p13m2 = 1<<30 + 1<<13 - 1<<2
+	two31m2    = 1<<31 - 1<<2
+	two31p24m2 = 1<<31 + 1<<24 - 1<<2
+	two30m27m2 = 1<<30 - 1<<27 - 1<<2
+)
+
+// p256Zero31 is 0 mod p.
+var p256Zero31 = [p256Limbs]uint32{two31m3, two30m2, two31m2, two30p13m2, two31m2, two30m2, two31p24m2, two30m27m2, two31m2}
+
+// p256Diff sets out = in-in2.
+//
+// On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29 and
+//           in2[0,2,...] < 2**30, in2[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Diff(out, in, in2 *[p256Limbs]uint32) {
+	var carry uint32
+
+	for i := 0; ; i++ {
+		out[i] = in[i] - in2[i]
+		out[i] += p256Zero31[i]
+		out[i] += carry
+		carry = out[i] >> 29
+		out[i] &= bottom29Bits
+
+		i++
+		if i == p256Limbs {
+			break
+		}
+
+		out[i] = in[i] - in2[i]
+		out[i] += p256Zero31[i]
+		out[i] += carry
+		carry = out[i] >> 28
+		out[i] &= bottom28Bits
+	}
+
+	p256ReduceCarry(out, carry)
+}
+
+// p256ReduceDegree sets out = tmp/R mod p where tmp contains 64-bit words with
+// the same 29,28,... bit positions as an field element.
+//
+// The values in field elements are in Montgomery form: x*R mod p where R =
+// 2**257. Since we just multiplied two Montgomery values together, the result
+// is x*y*R*R mod p. We wish to divide by R in order for the result also to be
+// in Montgomery form.
+//
+// On entry: tmp[i] < 2**64
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29
+func p256ReduceDegree(out *[p256Limbs]uint32, tmp [17]uint64) {
+	// The following table may be helpful when reading this code:
+	//
+	// Limb number:   0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10...
+	// Width (bits):  29| 28| 29| 28| 29| 28| 29| 28| 29| 28| 29
+	// Start bit:     0 | 29| 57| 86|114|143|171|200|228|257|285
+	//   (odd phase): 0 | 28| 57| 85|114|142|171|199|228|256|285
+	var tmp2 [18]uint32
+	var carry, x, xMask uint32
+
+	// tmp contains 64-bit words with the same 29,28,29-bit positions as an
+	// field element. So the top of an element of tmp might overlap with
+	// another element two positions down. The following loop eliminates
+	// this overlap.
+	tmp2[0] = uint32(tmp[0]) & bottom29Bits
+
+	tmp2[1] = uint32(tmp[0]) >> 29
+	tmp2[1] |= (uint32(tmp[0]>>32) << 3) & bottom28Bits
+	tmp2[1] += uint32(tmp[1]) & bottom28Bits
+	carry = tmp2[1] >> 28
+	tmp2[1] &= bottom28Bits
+
+	for i := 2; i < 17; i++ {
+		tmp2[i] = (uint32(tmp[i-2] >> 32)) >> 25
+		tmp2[i] += (uint32(tmp[i-1])) >> 28
+		tmp2[i] += (uint32(tmp[i-1]>>32) << 4) & bottom29Bits
+		tmp2[i] += uint32(tmp[i]) & bottom29Bits
+		tmp2[i] += carry
+		carry = tmp2[i] >> 29
+		tmp2[i] &= bottom29Bits
+
+		i++
+		if i == 17 {
+			break
+		}
+		tmp2[i] = uint32(tmp[i-2]>>32) >> 25
+		tmp2[i] += uint32(tmp[i-1]) >> 29
+		tmp2[i] += ((uint32(tmp[i-1] >> 32)) << 3) & bottom28Bits
+		tmp2[i] += uint32(tmp[i]) & bottom28Bits
+		tmp2[i] += carry
+		carry = tmp2[i] >> 28
+		tmp2[i] &= bottom28Bits
+	}
+
+	tmp2[17] = uint32(tmp[15]>>32) >> 25
+	tmp2[17] += uint32(tmp[16]) >> 29
+	tmp2[17] += uint32(tmp[16]>>32) << 3
+	tmp2[17] += carry
+
+	// Montgomery elimination of terms:
+	//
+	// Since R is 2**257, we can divide by R with a bitwise shift if we can
+	// ensure that the right-most 257 bits are all zero. We can make that true
+	// by adding multiplies of p without affecting the value.
+	//
+	// So we eliminate limbs from right to left. Since the bottom 29 bits of p
+	// are all ones, then by adding tmp2[0]*p to tmp2 we'll make tmp2[0] == 0.
+	// We can do that for 8 further limbs and then right shift to eliminate the
+	// extra factor of R.
+	for i := 0; ; i += 2 {
+		tmp2[i+1] += tmp2[i] >> 29
+		x = tmp2[i] & bottom29Bits
+		xMask = nonZeroToAllOnes(x)
+		tmp2[i] = 0
+
+		// The bounds calculations for this loop are tricky. Each iteration of
+		// the loop eliminates two words by adding values to words to their
+		// right.
+		//
+		// The following table contains the amounts added to each word (as an
+		// offset from the value of i at the top of the loop). The amounts are
+		// accounted for from the first and second half of the loop separately
+		// and are written as, for example, 28 to mean a value <2**28.
+		//
+		// Word:                   3   4   5   6   7   8   9   10
+		// Added in top half:     28  11      29  21  29  28
+		//                                        28  29
+		//                                            29
+		// Added in bottom half:      29  10      28  21  28   28
+		//                                            29
+		//
+		// The value that is currently offset 7 will be offset 5 for the next
+		// iteration and then offset 3 for the iteration after that. Therefore
+		// the total value added will be the values added at 7, 5 and 3.
+		//
+		// The following table accumulates these values. The sums at the bottom
+		// are written as, for example, 29+28, to mean a value < 2**29+2**28.
+		//
+		// Word:                   3   4   5   6   7   8   9  10  11  12  13
+		//                        28  11  10  29  21  29  28  28  28  28  28
+		//                            29  28  11  28  29  28  29  28  29  28
+		//                                    29  28  21  21  29  21  29  21
+		//                                        10  29  28  21  28  21  28
+		//                                        28  29  28  29  28  29  28
+		//                                            11  10  29  10  29  10
+		//                                            29  28  11  28  11
+		//                                                    29      29
+		//                        --------------------------------------------
+		//                                                30+ 31+ 30+ 31+ 30+
+		//                                                28+ 29+ 28+ 29+ 21+
+		//                                                21+ 28+ 21+ 28+ 10
+		//                                                10  21+ 10  21+
+		//                                                    11      11
+		//
+		// So the greatest amount is added to tmp2[10] and tmp2[12]. If
+		// tmp2[10/12] has an initial value of <2**29, then the maximum value
+		// will be < 2**31 + 2**30 + 2**28 + 2**21 + 2**11, which is < 2**32,
+		// as required.
+		tmp2[i+3] += (x << 10) & bottom28Bits
+		tmp2[i+4] += (x >> 18)
+
+		tmp2[i+6] += (x << 21) & bottom29Bits
+		tmp2[i+7] += x >> 8
+
+		// At position 200, which is the starting bit position for word 7, we
+		// have a factor of 0xf000000 = 2**28 - 2**24.
+		tmp2[i+7] += 0x10000000 & xMask
+		tmp2[i+8] += (x - 1) & xMask
+		tmp2[i+7] -= (x << 24) & bottom28Bits
+		tmp2[i+8] -= x >> 4
+
+		tmp2[i+8] += 0x20000000 & xMask
+		tmp2[i+8] -= x
+		tmp2[i+8] += (x << 28) & bottom29Bits
+		tmp2[i+9] += ((x >> 1) - 1) & xMask
+
+		if i+1 == p256Limbs {
+			break
+		}
+		tmp2[i+2] += tmp2[i+1] >> 28
+		x = tmp2[i+1] & bottom28Bits
+		xMask = nonZeroToAllOnes(x)
+		tmp2[i+1] = 0
+
+		tmp2[i+4] += (x << 11) & bottom29Bits
+		tmp2[i+5] += (x >> 18)
+
+		tmp2[i+7] += (x << 21) & bottom28Bits
+		tmp2[i+8] += x >> 7
+
+		// At position 199, which is the starting bit of the 8th word when
+		// dealing with a context starting on an odd word, we have a factor of
+		// 0x1e000000 = 2**29 - 2**25. Since we have not updated i, the 8th
+		// word from i+1 is i+8.
+		tmp2[i+8] += 0x20000000 & xMask
+		tmp2[i+9] += (x - 1) & xMask
+		tmp2[i+8] -= (x << 25) & bottom29Bits
+		tmp2[i+9] -= x >> 4
+
+		tmp2[i+9] += 0x10000000 & xMask
+		tmp2[i+9] -= x
+		tmp2[i+10] += (x - 1) & xMask
+	}
+
+	// We merge the right shift with a carry chain. The words above 2**257 have
+	// widths of 28,29,... which we need to correct when copying them down.
+	carry = 0
+	for i := 0; i < 8; i++ {
+		// The maximum value of tmp2[i + 9] occurs on the first iteration and
+		// is < 2**30+2**29+2**28. Adding 2**29 (from tmp2[i + 10]) is
+		// therefore safe.
+		out[i] = tmp2[i+9]
+		out[i] += carry
+		out[i] += (tmp2[i+10] << 28) & bottom29Bits
+		carry = out[i] >> 29
+		out[i] &= bottom29Bits
+
+		i++
+		out[i] = tmp2[i+9] >> 1
+		out[i] += carry
+		carry = out[i] >> 28
+		out[i] &= bottom28Bits
+	}
+
+	out[8] = tmp2[17]
+	out[8] += carry
+	carry = out[8] >> 29
+	out[8] &= bottom29Bits
+
+	p256ReduceCarry(out, carry)
+}
+
+// p256Square sets out=in*in.
+//
+// On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Square(out, in *[p256Limbs]uint32) {
+	var tmp [17]uint64
+
+	tmp[0] = uint64(in[0]) * uint64(in[0])
+	tmp[1] = uint64(in[0]) * (uint64(in[1]) << 1)
+	tmp[2] = uint64(in[0])*(uint64(in[2])<<1) +
+		uint64(in[1])*(uint64(in[1])<<1)
+	tmp[3] = uint64(in[0])*(uint64(in[3])<<1) +
+		uint64(in[1])*(uint64(in[2])<<1)
+	tmp[4] = uint64(in[0])*(uint64(in[4])<<1) +
+		uint64(in[1])*(uint64(in[3])<<2) +
+		uint64(in[2])*uint64(in[2])
+	tmp[5] = uint64(in[0])*(uint64(in[5])<<1) +
+		uint64(in[1])*(uint64(in[4])<<1) +
+		uint64(in[2])*(uint64(in[3])<<1)
+	tmp[6] = uint64(in[0])*(uint64(in[6])<<1) +
+		uint64(in[1])*(uint64(in[5])<<2) +
+		uint64(in[2])*(uint64(in[4])<<1) +
+		uint64(in[3])*(uint64(in[3])<<1)
+	tmp[7] = uint64(in[0])*(uint64(in[7])<<1) +
+		uint64(in[1])*(uint64(in[6])<<1) +
+		uint64(in[2])*(uint64(in[5])<<1) +
+		uint64(in[3])*(uint64(in[4])<<1)
+	// tmp[8] has the greatest value of 2**61 + 2**60 + 2**61 + 2**60 + 2**60,
+	// which is < 2**64 as required.
+	tmp[8] = uint64(in[0])*(uint64(in[8])<<1) +
+		uint64(in[1])*(uint64(in[7])<<2) +
+		uint64(in[2])*(uint64(in[6])<<1) +
+		uint64(in[3])*(uint64(in[5])<<2) +
+		uint64(in[4])*uint64(in[4])
+	tmp[9] = uint64(in[1])*(uint64(in[8])<<1) +
+		uint64(in[2])*(uint64(in[7])<<1) +
+		uint64(in[3])*(uint64(in[6])<<1) +
+		uint64(in[4])*(uint64(in[5])<<1)
+	tmp[10] = uint64(in[2])*(uint64(in[8])<<1) +
+		uint64(in[3])*(uint64(in[7])<<2) +
+		uint64(in[4])*(uint64(in[6])<<1) +
+		uint64(in[5])*(uint64(in[5])<<1)
+	tmp[11] = uint64(in[3])*(uint64(in[8])<<1) +
+		uint64(in[4])*(uint64(in[7])<<1) +
+		uint64(in[5])*(uint64(in[6])<<1)
+	tmp[12] = uint64(in[4])*(uint64(in[8])<<1) +
+		uint64(in[5])*(uint64(in[7])<<2) +
+		uint64(in[6])*uint64(in[6])
+	tmp[13] = uint64(in[5])*(uint64(in[8])<<1) +
+		uint64(in[6])*(uint64(in[7])<<1)
+	tmp[14] = uint64(in[6])*(uint64(in[8])<<1) +
+		uint64(in[7])*(uint64(in[7])<<1)
+	tmp[15] = uint64(in[7]) * (uint64(in[8]) << 1)
+	tmp[16] = uint64(in[8]) * uint64(in[8])
+
+	p256ReduceDegree(out, tmp)
+}
+
+// p256Mul sets out=in*in2.
+//
+// On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29 and
+//           in2[0,2,...] < 2**30, in2[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Mul(out, in, in2 *[p256Limbs]uint32) {
+	var tmp [17]uint64
+
+	tmp[0] = uint64(in[0]) * uint64(in2[0])
+	tmp[1] = uint64(in[0])*(uint64(in2[1])<<0) +
+		uint64(in[1])*(uint64(in2[0])<<0)
+	tmp[2] = uint64(in[0])*(uint64(in2[2])<<0) +
+		uint64(in[1])*(uint64(in2[1])<<1) +
+		uint64(in[2])*(uint64(in2[0])<<0)
+	tmp[3] = uint64(in[0])*(uint64(in2[3])<<0) +
+		uint64(in[1])*(uint64(in2[2])<<0) +
+		uint64(in[2])*(uint64(in2[1])<<0) +
+		uint64(in[3])*(uint64(in2[0])<<0)
+	tmp[4] = uint64(in[0])*(uint64(in2[4])<<0) +
+		uint64(in[1])*(uint64(in2[3])<<1) +
+		uint64(in[2])*(uint64(in2[2])<<0) +
+		uint64(in[3])*(uint64(in2[1])<<1) +
+		uint64(in[4])*(uint64(in2[0])<<0)
+	tmp[5] = uint64(in[0])*(uint64(in2[5])<<0) +
+		uint64(in[1])*(uint64(in2[4])<<0) +
+		uint64(in[2])*(uint64(in2[3])<<0) +
+		uint64(in[3])*(uint64(in2[2])<<0) +
+		uint64(in[4])*(uint64(in2[1])<<0) +
+		uint64(in[5])*(uint64(in2[0])<<0)
+	tmp[6] = uint64(in[0])*(uint64(in2[6])<<0) +
+		uint64(in[1])*(uint64(in2[5])<<1) +
+		uint64(in[2])*(uint64(in2[4])<<0) +
+		uint64(in[3])*(uint64(in2[3])<<1) +
+		uint64(in[4])*(uint64(in2[2])<<0) +
+		uint64(in[5])*(uint64(in2[1])<<1) +
+		uint64(in[6])*(uint64(in2[0])<<0)
+	tmp[7] = uint64(in[0])*(uint64(in2[7])<<0) +
+		uint64(in[1])*(uint64(in2[6])<<0) +
+		uint64(in[2])*(uint64(in2[5])<<0) +
+		uint64(in[3])*(uint64(in2[4])<<0) +
+		uint64(in[4])*(uint64(in2[3])<<0) +
+		uint64(in[5])*(uint64(in2[2])<<0) +
+		uint64(in[6])*(uint64(in2[1])<<0) +
+		uint64(in[7])*(uint64(in2[0])<<0)
+	// tmp[8] has the greatest value but doesn't overflow. See logic in
+	// p256Square.
+	tmp[8] = uint64(in[0])*(uint64(in2[8])<<0) +
+		uint64(in[1])*(uint64(in2[7])<<1) +
+		uint64(in[2])*(uint64(in2[6])<<0) +
+		uint64(in[3])*(uint64(in2[5])<<1) +
+		uint64(in[4])*(uint64(in2[4])<<0) +
+		uint64(in[5])*(uint64(in2[3])<<1) +
+		uint64(in[6])*(uint64(in2[2])<<0) +
+		uint64(in[7])*(uint64(in2[1])<<1) +
+		uint64(in[8])*(uint64(in2[0])<<0)
+	tmp[9] = uint64(in[1])*(uint64(in2[8])<<0) +
+		uint64(in[2])*(uint64(in2[7])<<0) +
+		uint64(in[3])*(uint64(in2[6])<<0) +
+		uint64(in[4])*(uint64(in2[5])<<0) +
+		uint64(in[5])*(uint64(in2[4])<<0) +
+		uint64(in[6])*(uint64(in2[3])<<0) +
+		uint64(in[7])*(uint64(in2[2])<<0) +
+		uint64(in[8])*(uint64(in2[1])<<0)
+	tmp[10] = uint64(in[2])*(uint64(in2[8])<<0) +
+		uint64(in[3])*(uint64(in2[7])<<1) +
+		uint64(in[4])*(uint64(in2[6])<<0) +
+		uint64(in[5])*(uint64(in2[5])<<1) +
+		uint64(in[6])*(uint64(in2[4])<<0) +
+		uint64(in[7])*(uint64(in2[3])<<1) +
+		uint64(in[8])*(uint64(in2[2])<<0)
+	tmp[11] = uint64(in[3])*(uint64(in2[8])<<0) +
+		uint64(in[4])*(uint64(in2[7])<<0) +
+		uint64(in[5])*(uint64(in2[6])<<0) +
+		uint64(in[6])*(uint64(in2[5])<<0) +
+		uint64(in[7])*(uint64(in2[4])<<0) +
+		uint64(in[8])*(uint64(in2[3])<<0)
+	tmp[12] = uint64(in[4])*(uint64(in2[8])<<0) +
+		uint64(in[5])*(uint64(in2[7])<<1) +
+		uint64(in[6])*(uint64(in2[6])<<0) +
+		uint64(in[7])*(uint64(in2[5])<<1) +
+		uint64(in[8])*(uint64(in2[4])<<0)
+	tmp[13] = uint64(in[5])*(uint64(in2[8])<<0) +
+		uint64(in[6])*(uint64(in2[7])<<0) +
+		uint64(in[7])*(uint64(in2[6])<<0) +
+		uint64(in[8])*(uint64(in2[5])<<0)
+	tmp[14] = uint64(in[6])*(uint64(in2[8])<<0) +
+		uint64(in[7])*(uint64(in2[7])<<1) +
+		uint64(in[8])*(uint64(in2[6])<<0)
+	tmp[15] = uint64(in[7])*(uint64(in2[8])<<0) +
+		uint64(in[8])*(uint64(in2[7])<<0)
+	tmp[16] = uint64(in[8]) * (uint64(in2[8]) << 0)
+
+	p256ReduceDegree(out, tmp)
+}
+
+func p256Assign(out, in *[p256Limbs]uint32) {
+	*out = *in
+}
+
+// p256Invert calculates |out| = |in|^{-1}
+//
+// Based on Fermat's Little Theorem:
+//   a^p = a (mod p)
+//   a^{p-1} = 1 (mod p)
+//   a^{p-2} = a^{-1} (mod p)
+func p256Invert(out, in *[p256Limbs]uint32) {
+	var ftmp, ftmp2 [p256Limbs]uint32
+
+	// each e_I will hold |in|^{2^I - 1}
+	var e2, e4, e8, e16, e32, e64 [p256Limbs]uint32
+
+	p256Square(&ftmp, in)     // 2^1
+	p256Mul(&ftmp, in, &ftmp) // 2^2 - 2^0
+	p256Assign(&e2, &ftmp)
+	p256Square(&ftmp, &ftmp)   // 2^3 - 2^1
+	p256Square(&ftmp, &ftmp)   // 2^4 - 2^2
+	p256Mul(&ftmp, &ftmp, &e2) // 2^4 - 2^0
+	p256Assign(&e4, &ftmp)
+	p256Square(&ftmp, &ftmp)   // 2^5 - 2^1
+	p256Square(&ftmp, &ftmp)   // 2^6 - 2^2
+	p256Square(&ftmp, &ftmp)   // 2^7 - 2^3
+	p256Square(&ftmp, &ftmp)   // 2^8 - 2^4
+	p256Mul(&ftmp, &ftmp, &e4) // 2^8 - 2^0
+	p256Assign(&e8, &ftmp)
+	for i := 0; i < 8; i++ {
+		p256Square(&ftmp, &ftmp)
+	} // 2^16 - 2^8
+	p256Mul(&ftmp, &ftmp, &e8) // 2^16 - 2^0
+	p256Assign(&e16, &ftmp)
+	for i := 0; i < 16; i++ {
+		p256Square(&ftmp, &ftmp)
+	} // 2^32 - 2^16
+	p256Mul(&ftmp, &ftmp, &e16) // 2^32 - 2^0
+	p256Assign(&e32, &ftmp)
+	for i := 0; i < 32; i++ {
+		p256Square(&ftmp, &ftmp)
+	} // 2^64 - 2^32
+	p256Assign(&e64, &ftmp)
+	p256Mul(&ftmp, &ftmp, in) // 2^64 - 2^32 + 2^0
+	for i := 0; i < 192; i++ {
+		p256Square(&ftmp, &ftmp)
+	} // 2^256 - 2^224 + 2^192
+
+	p256Mul(&ftmp2, &e64, &e32) // 2^64 - 2^0
+	for i := 0; i < 16; i++ {
+		p256Square(&ftmp2, &ftmp2)
+	} // 2^80 - 2^16
+	p256Mul(&ftmp2, &ftmp2, &e16) // 2^80 - 2^0
+	for i := 0; i < 8; i++ {
+		p256Square(&ftmp2, &ftmp2)
+	} // 2^88 - 2^8
+	p256Mul(&ftmp2, &ftmp2, &e8) // 2^88 - 2^0
+	for i := 0; i < 4; i++ {
+		p256Square(&ftmp2, &ftmp2)
+	} // 2^92 - 2^4
+	p256Mul(&ftmp2, &ftmp2, &e4) // 2^92 - 2^0
+	p256Square(&ftmp2, &ftmp2)   // 2^93 - 2^1
+	p256Square(&ftmp2, &ftmp2)   // 2^94 - 2^2
+	p256Mul(&ftmp2, &ftmp2, &e2) // 2^94 - 2^0
+	p256Square(&ftmp2, &ftmp2)   // 2^95 - 2^1
+	p256Square(&ftmp2, &ftmp2)   // 2^96 - 2^2
+	p256Mul(&ftmp2, &ftmp2, in)  // 2^96 - 3
+
+	p256Mul(out, &ftmp2, &ftmp) // 2^256 - 2^224 + 2^192 + 2^96 - 3
+}
+
+// p256Scalar3 sets out=3*out.
+//
+// On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Scalar3(out *[p256Limbs]uint32) {
+	var carry uint32
+
+	for i := 0; ; i++ {
+		out[i] *= 3
+		out[i] += carry
+		carry = out[i] >> 29
+		out[i] &= bottom29Bits
+
+		i++
+		if i == p256Limbs {
+			break
+		}
+
+		out[i] *= 3
+		out[i] += carry
+		carry = out[i] >> 28
+		out[i] &= bottom28Bits
+	}
+
+	p256ReduceCarry(out, carry)
+}
+
+// p256Scalar4 sets out=4*out.
+//
+// On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Scalar4(out *[p256Limbs]uint32) {
+	var carry, nextCarry uint32
+
+	for i := 0; ; i++ {
+		nextCarry = out[i] >> 27
+		out[i] <<= 2
+		out[i] &= bottom29Bits
+		out[i] += carry
+		carry = nextCarry + (out[i] >> 29)
+		out[i] &= bottom29Bits
+
+		i++
+		if i == p256Limbs {
+			break
+		}
+		nextCarry = out[i] >> 26
+		out[i] <<= 2
+		out[i] &= bottom28Bits
+		out[i] += carry
+		carry = nextCarry + (out[i] >> 28)
+		out[i] &= bottom28Bits
+	}
+
+	p256ReduceCarry(out, carry)
+}
+
+// p256Scalar8 sets out=8*out.
+//
+// On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Scalar8(out *[p256Limbs]uint32) {
+	var carry, nextCarry uint32
+
+	for i := 0; ; i++ {
+		nextCarry = out[i] >> 26
+		out[i] <<= 3
+		out[i] &= bottom29Bits
+		out[i] += carry
+		carry = nextCarry + (out[i] >> 29)
+		out[i] &= bottom29Bits
+
+		i++
+		if i == p256Limbs {
+			break
+		}
+		nextCarry = out[i] >> 25
+		out[i] <<= 3
+		out[i] &= bottom28Bits
+		out[i] += carry
+		carry = nextCarry + (out[i] >> 28)
+		out[i] &= bottom28Bits
+	}
+
+	p256ReduceCarry(out, carry)
+}
+
+// Group operations:
+//
+// Elements of the elliptic curve group are represented in Jacobian
+// coordinates: (x, y, z). An affine point (x', y') is x'=x/z**2, y'=y/z**3 in
+// Jacobian form.
+
+// p256PointDouble sets {xOut,yOut,zOut} = 2*{x,y,z}.
+//
+// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
+func p256PointDouble(xOut, yOut, zOut, x, y, z *[p256Limbs]uint32) {
+	var delta, gamma, alpha, beta, tmp, tmp2 [p256Limbs]uint32
+
+	p256Square(&delta, z)
+	p256Square(&gamma, y)
+	p256Mul(&beta, x, &gamma)
+
+	p256Sum(&tmp, x, &delta)
+	p256Diff(&tmp2, x, &delta)
+	p256Mul(&alpha, &tmp, &tmp2)
+	p256Scalar3(&alpha)
+
+	p256Sum(&tmp, y, z)
+	p256Square(&tmp, &tmp)
+	p256Diff(&tmp, &tmp, &gamma)
+	p256Diff(zOut, &tmp, &delta)
+
+	p256Scalar4(&beta)
+	p256Square(xOut, &alpha)
+	p256Diff(xOut, xOut, &beta)
+	p256Diff(xOut, xOut, &beta)
+
+	p256Diff(&tmp, &beta, xOut)
+	p256Mul(&tmp, &alpha, &tmp)
+	p256Square(&tmp2, &gamma)
+	p256Scalar8(&tmp2)
+	p256Diff(yOut, &tmp, &tmp2)
+}
+
+// p256PointAddMixed sets {xOut,yOut,zOut} = {x1,y1,z1} + {x2,y2,1}.
+// (i.e. the second point is affine.)
+//
+// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
+//
+// Note that this function does not handle P+P, infinity+P nor P+infinity
+// correctly.
+func p256PointAddMixed(xOut, yOut, zOut, x1, y1, z1, x2, y2 *[p256Limbs]uint32) {
+	var z1z1, z1z1z1, s2, u2, h, i, j, r, rr, v, tmp [p256Limbs]uint32
+
+	p256Square(&z1z1, z1)
+	p256Sum(&tmp, z1, z1)
+
+	p256Mul(&u2, x2, &z1z1)
+	p256Mul(&z1z1z1, z1, &z1z1)
+	p256Mul(&s2, y2, &z1z1z1)
+	p256Diff(&h, &u2, x1)
+	p256Sum(&i, &h, &h)
+	p256Square(&i, &i)
+	p256Mul(&j, &h, &i)
+	p256Diff(&r, &s2, y1)
+	p256Sum(&r, &r, &r)
+	p256Mul(&v, x1, &i)
+
+	p256Mul(zOut, &tmp, &h)
+	p256Square(&rr, &r)
+	p256Diff(xOut, &rr, &j)
+	p256Diff(xOut, xOut, &v)
+	p256Diff(xOut, xOut, &v)
+
+	p256Diff(&tmp, &v, xOut)
+	p256Mul(yOut, &tmp, &r)
+	p256Mul(&tmp, y1, &j)
+	p256Diff(yOut, yOut, &tmp)
+	p256Diff(yOut, yOut, &tmp)
+}
+
+// p256PointAdd sets {xOut,yOut,zOut} = {x1,y1,z1} + {x2,y2,z2}.
+//
+// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
+//
+// Note that this function does not handle P+P, infinity+P nor P+infinity
+// correctly.
+func p256PointAdd(xOut, yOut, zOut, x1, y1, z1, x2, y2, z2 *[p256Limbs]uint32) {
+	var z1z1, z1z1z1, z2z2, z2z2z2, s1, s2, u1, u2, h, i, j, r, rr, v, tmp [p256Limbs]uint32
+
+	p256Square(&z1z1, z1)
+	p256Square(&z2z2, z2)
+	p256Mul(&u1, x1, &z2z2)
+
+	p256Sum(&tmp, z1, z2)
+	p256Square(&tmp, &tmp)
+	p256Diff(&tmp, &tmp, &z1z1)
+	p256Diff(&tmp, &tmp, &z2z2)
+
+	p256Mul(&z2z2z2, z2, &z2z2)
+	p256Mul(&s1, y1, &z2z2z2)
+
+	p256Mul(&u2, x2, &z1z1)
+	p256Mul(&z1z1z1, z1, &z1z1)
+	p256Mul(&s2, y2, &z1z1z1)
+	p256Diff(&h, &u2, &u1)
+	p256Sum(&i, &h, &h)
+	p256Square(&i, &i)
+	p256Mul(&j, &h, &i)
+	p256Diff(&r, &s2, &s1)
+	p256Sum(&r, &r, &r)
+	p256Mul(&v, &u1, &i)
+
+	p256Mul(zOut, &tmp, &h)
+	p256Square(&rr, &r)
+	p256Diff(xOut, &rr, &j)
+	p256Diff(xOut, xOut, &v)
+	p256Diff(xOut, xOut, &v)
+
+	p256Diff(&tmp, &v, xOut)
+	p256Mul(yOut, &tmp, &r)
+	p256Mul(&tmp, &s1, &j)
+	p256Diff(yOut, yOut, &tmp)
+	p256Diff(yOut, yOut, &tmp)
+}
+
+// p256CopyConditional sets out=in if mask = 0xffffffff in constant time.
+//
+// On entry: mask is either 0 or 0xffffffff.
+func p256CopyConditional(out, in *[p256Limbs]uint32, mask uint32) {
+	for i := 0; i < p256Limbs; i++ {
+		tmp := mask & (in[i] ^ out[i])
+		out[i] ^= tmp
+	}
+}
+
+// p256SelectAffinePoint sets {out_x,out_y} to the index'th entry of table.
+// On entry: index < 16, table[0] must be zero.
+func p256SelectAffinePoint(xOut, yOut *[p256Limbs]uint32, table []uint32, index uint32) {
+	for i := range xOut {
+		xOut[i] = 0
+	}
+	for i := range yOut {
+		yOut[i] = 0
+	}
+
+	for i := uint32(1); i < 16; i++ {
+		mask := i ^ index
+		mask |= mask >> 2
+		mask |= mask >> 1
+		mask &= 1
+		mask--
+		for j := range xOut {
+			xOut[j] |= table[0] & mask
+			table = table[1:]
+		}
+		for j := range yOut {
+			yOut[j] |= table[0] & mask
+			table = table[1:]
+		}
+	}
+}
+
+// p256SelectJacobianPoint sets {out_x,out_y,out_z} to the index'th entry of
+// table.
+// On entry: index < 16, table[0] must be zero.
+func p256SelectJacobianPoint(xOut, yOut, zOut *[p256Limbs]uint32, table *[16][3][p256Limbs]uint32, index uint32) {
+	for i := range xOut {
+		xOut[i] = 0
+	}
+	for i := range yOut {
+		yOut[i] = 0
+	}
+	for i := range zOut {
+		zOut[i] = 0
+	}
+
+	// The implicit value at index 0 is all zero. We don't need to perform that
+	// iteration of the loop because we already set out_* to zero.
+	for i := uint32(1); i < 16; i++ {
+		mask := i ^ index
+		mask |= mask >> 2
+		mask |= mask >> 1
+		mask &= 1
+		mask--
+		for j := range xOut {
+			xOut[j] |= table[i][0][j] & mask
+		}
+		for j := range yOut {
+			yOut[j] |= table[i][1][j] & mask
+		}
+		for j := range zOut {
+			zOut[j] |= table[i][2][j] & mask
+		}
+	}
+}
+
+// p256GetBit returns the bit'th bit of scalar.
+func p256GetBit(scalar *[32]uint8, bit uint) uint32 {
+	return uint32(((scalar[bit>>3]) >> (bit & 7)) & 1)
+}
+
+// p256ScalarBaseMult sets {xOut,yOut,zOut} = scalar*G where scalar is a
+// little-endian number. Note that the value of scalar must be less than the
+// order of the group.
+func p256ScalarBaseMult(xOut, yOut, zOut *[p256Limbs]uint32, scalar *[32]uint8) {
+	nIsInfinityMask := ^uint32(0)
+	var pIsNoninfiniteMask, mask, tableOffset uint32
+	var px, py, tx, ty, tz [p256Limbs]uint32
+
+	for i := range xOut {
+		xOut[i] = 0
+	}
+	for i := range yOut {
+		yOut[i] = 0
+	}
+	for i := range zOut {
+		zOut[i] = 0
+	}
+
+	// The loop adds bits at positions 0, 64, 128 and 192, followed by
+	// positions 32,96,160 and 224 and does this 32 times.
+	for i := uint(0); i < 32; i++ {
+		if i != 0 {
+			p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut)
+		}
+		tableOffset = 0
+		for j := uint(0); j <= 32; j += 32 {
+			bit0 := p256GetBit(scalar, 31-i+j)
+			bit1 := p256GetBit(scalar, 95-i+j)
+			bit2 := p256GetBit(scalar, 159-i+j)
+			bit3 := p256GetBit(scalar, 223-i+j)
+			index := bit0 | (bit1 << 1) | (bit2 << 2) | (bit3 << 3)
+
+			p256SelectAffinePoint(&px, &py, p256Precomputed[tableOffset:], index)
+			tableOffset += 30 * p256Limbs
+
+			// Since scalar is less than the order of the group, we know that
+			// {xOut,yOut,zOut} != {px,py,1}, unless both are zero, which we handle
+			// below.
+			p256PointAddMixed(&tx, &ty, &tz, xOut, yOut, zOut, &px, &py)
+			// The result of pointAddMixed is incorrect if {xOut,yOut,zOut} is zero
+			// (a.k.a.  the point at infinity). We handle that situation by
+			// copying the point from the table.
+			p256CopyConditional(xOut, &px, nIsInfinityMask)
+			p256CopyConditional(yOut, &py, nIsInfinityMask)
+			p256CopyConditional(zOut, &p256One, nIsInfinityMask)
+
+			// Equally, the result is also wrong if the point from the table is
+			// zero, which happens when the index is zero. We handle that by
+			// only copying from {tx,ty,tz} to {xOut,yOut,zOut} if index != 0.
+			pIsNoninfiniteMask = nonZeroToAllOnes(index)
+			mask = pIsNoninfiniteMask & ^nIsInfinityMask
+			p256CopyConditional(xOut, &tx, mask)
+			p256CopyConditional(yOut, &ty, mask)
+			p256CopyConditional(zOut, &tz, mask)
+			// If p was not zero, then n is now non-zero.
+			nIsInfinityMask &= ^pIsNoninfiniteMask
+		}
+	}
+}
+
+// p256PointToAffine converts a Jacobian point to an affine point. If the input
+// is the point at infinity then it returns (0, 0) in constant time.
+func p256PointToAffine(xOut, yOut, x, y, z *[p256Limbs]uint32) {
+	var zInv, zInvSq [p256Limbs]uint32
+
+	p256Invert(&zInv, z)
+	p256Square(&zInvSq, &zInv)
+	p256Mul(xOut, x, &zInvSq)
+	p256Mul(&zInv, &zInv, &zInvSq)
+	p256Mul(yOut, y, &zInv)
+}
+
+// p256ToAffine returns a pair of *big.Int containing the affine representation
+// of {x,y,z}.
+func p256ToAffine(x, y, z *[p256Limbs]uint32) (xOut, yOut *big.Int) {
+	var xx, yy [p256Limbs]uint32
+	p256PointToAffine(&xx, &yy, x, y, z)
+	return p256ToBig(&xx), p256ToBig(&yy)
+}
+
+// p256ScalarMult sets {xOut,yOut,zOut} = scalar*{x,y}.
+func p256ScalarMult(xOut, yOut, zOut, x, y *[p256Limbs]uint32, scalar *[32]uint8) {
+	var px, py, pz, tx, ty, tz [p256Limbs]uint32
+	var precomp [16][3][p256Limbs]uint32
+	var nIsInfinityMask, index, pIsNoninfiniteMask, mask uint32
+
+	// We precompute 0,1,2,... times {x,y}.
+	precomp[1][0] = *x
+	precomp[1][1] = *y
+	precomp[1][2] = p256One
+
+	for i := 2; i < 16; i += 2 {
+		p256PointDouble(&precomp[i][0], &precomp[i][1], &precomp[i][2], &precomp[i/2][0], &precomp[i/2][1], &precomp[i/2][2])
+		p256PointAddMixed(&precomp[i+1][0], &precomp[i+1][1], &precomp[i+1][2], &precomp[i][0], &precomp[i][1], &precomp[i][2], x, y)
+	}
+
+	for i := range xOut {
+		xOut[i] = 0
+	}
+	for i := range yOut {
+		yOut[i] = 0
+	}
+	for i := range zOut {
+		zOut[i] = 0
+	}
+	nIsInfinityMask = ^uint32(0)
+
+	// We add in a window of four bits each iteration and do this 64 times.
+	for i := 0; i < 64; i++ {
+		if i != 0 {
+			p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut)
+			p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut)
+			p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut)
+			p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut)
+		}
+
+		index = uint32(scalar[31-i/2])
+		if (i & 1) == 1 {
+			index &= 15
+		} else {
+			index >>= 4
+		}
+
+		// See the comments in scalarBaseMult about handling infinities.
+		p256SelectJacobianPoint(&px, &py, &pz, &precomp, index)
+		p256PointAdd(&tx, &ty, &tz, xOut, yOut, zOut, &px, &py, &pz)
+		p256CopyConditional(xOut, &px, nIsInfinityMask)
+		p256CopyConditional(yOut, &py, nIsInfinityMask)
+		p256CopyConditional(zOut, &pz, nIsInfinityMask)
+
+		pIsNoninfiniteMask = nonZeroToAllOnes(index)
+		mask = pIsNoninfiniteMask & ^nIsInfinityMask
+		p256CopyConditional(xOut, &tx, mask)
+		p256CopyConditional(yOut, &ty, mask)
+		p256CopyConditional(zOut, &tz, mask)
+		nIsInfinityMask &= ^pIsNoninfiniteMask
+	}
+}
+
+// p256FromBig sets out = R*in.
+func p256FromBig(out *[p256Limbs]uint32, in *big.Int) {
+	tmp := new(big.Int).Lsh(in, 257)
+	tmp.Mod(tmp, p256.P)
+
+	for i := 0; i < p256Limbs; i++ {
+		if bits := tmp.Bits(); len(bits) > 0 {
+			out[i] = uint32(bits[0]) & bottom29Bits
+		} else {
+			out[i] = 0
+		}
+		tmp.Rsh(tmp, 29)
+
+		i++
+		if i == p256Limbs {
+			break
+		}
+
+		if bits := tmp.Bits(); len(bits) > 0 {
+			out[i] = uint32(bits[0]) & bottom28Bits
+		} else {
+			out[i] = 0
+		}
+		tmp.Rsh(tmp, 28)
+	}
+}
+
+// p256ToBig returns a *big.Int containing the value of in.
+func p256ToBig(in *[p256Limbs]uint32) *big.Int {
+	result, tmp := new(big.Int), new(big.Int)
+
+	result.SetInt64(int64(in[p256Limbs-1]))
+	for i := p256Limbs - 2; i >= 0; i-- {
+		if (i & 1) == 0 {
+			result.Lsh(result, 29)
+		} else {
+			result.Lsh(result, 28)
+		}
+		tmp.SetInt64(int64(in[i]))
+		result.Add(result, tmp)
+	}
+
+	result.Mul(result, p256RInverse)
+	result.Mod(result, p256.P)
+	return result
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/hmac/hmac.go b/third_party/gofrontend/libgo/go/crypto/hmac/hmac.go
new file mode 100644
index 0000000..b6f4919
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/hmac/hmac.go
@@ -0,0 +1,102 @@
+// 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 hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
+defined in U.S. Federal Information Processing Standards Publication 198.
+An HMAC is a cryptographic hash that uses a key to sign a message.
+The receiver verifies the hash by recomputing it using the same key.
+
+Receivers should be careful to use Equal to compare MACs in order to avoid
+timing side-channels:
+
+	// CheckMAC returns true if messageMAC is a valid HMAC tag for message.
+	func CheckMAC(message, messageMAC, key []byte) bool {
+		mac := hmac.New(sha256.New, key)
+		mac.Write(message)
+		expectedMAC := mac.Sum(nil)
+		return hmac.Equal(messageMAC, expectedMAC)
+	}
+*/
+package hmac
+
+import (
+	"crypto/subtle"
+	"hash"
+)
+
+// FIPS 198:
+// http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
+
+// key is zero padded to the block size of the hash function
+// ipad = 0x36 byte repeated for key length
+// opad = 0x5c byte repeated for key length
+// hmac = H([key ^ opad] H([key ^ ipad] text))
+
+type hmac struct {
+	size         int
+	blocksize    int
+	key, tmp     []byte
+	outer, inner hash.Hash
+}
+
+func (h *hmac) tmpPad(xor byte) {
+	for i, k := range h.key {
+		h.tmp[i] = xor ^ k
+	}
+	for i := len(h.key); i < h.blocksize; i++ {
+		h.tmp[i] = xor
+	}
+}
+
+func (h *hmac) Sum(in []byte) []byte {
+	origLen := len(in)
+	in = h.inner.Sum(in)
+	h.tmpPad(0x5c)
+	copy(h.tmp[h.blocksize:], in[origLen:])
+	h.outer.Reset()
+	h.outer.Write(h.tmp)
+	return h.outer.Sum(in[:origLen])
+}
+
+func (h *hmac) Write(p []byte) (n int, err error) {
+	return h.inner.Write(p)
+}
+
+func (h *hmac) Size() int { return h.size }
+
+func (h *hmac) BlockSize() int { return h.blocksize }
+
+func (h *hmac) Reset() {
+	h.inner.Reset()
+	h.tmpPad(0x36)
+	h.inner.Write(h.tmp[:h.blocksize])
+}
+
+// New returns a new HMAC hash using the given hash.Hash type and key.
+func New(h func() hash.Hash, key []byte) hash.Hash {
+	hm := new(hmac)
+	hm.outer = h()
+	hm.inner = h()
+	hm.size = hm.inner.Size()
+	hm.blocksize = hm.inner.BlockSize()
+	hm.tmp = make([]byte, hm.blocksize+hm.size)
+	if len(key) > hm.blocksize {
+		// If key is too big, hash it.
+		hm.outer.Write(key)
+		key = hm.outer.Sum(nil)
+	}
+	hm.key = make([]byte, len(key))
+	copy(hm.key, key)
+	hm.Reset()
+	return hm
+}
+
+// Equal compares two MACs for equality without leaking timing information.
+func Equal(mac1, mac2 []byte) bool {
+	// We don't have to be constant time if the lengths of the MACs are
+	// different as that suggests that a completely different hash function
+	// was used.
+	return len(mac1) == len(mac2) && subtle.ConstantTimeCompare(mac1, mac2) == 1
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/hmac/hmac_test.go b/third_party/gofrontend/libgo/go/crypto/hmac/hmac_test.go
new file mode 100644
index 0000000..e80b7e0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/hmac/hmac_test.go
@@ -0,0 +1,570 @@
+// 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 hmac
+
+import (
+	"crypto/md5"
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/sha512"
+	"fmt"
+	"hash"
+	"testing"
+)
+
+type hmacTest struct {
+	hash      func() hash.Hash
+	key       []byte
+	in        []byte
+	out       string
+	size      int
+	blocksize int
+}
+
+var hmacTests = []hmacTest{
+	// Tests from US FIPS 198
+	// http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
+	{
+		sha1.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		},
+		[]byte("Sample #1"),
+		"4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0a",
+		sha1.Size,
+		sha1.BlockSize,
+	},
+	{
+		sha1.New,
+		[]byte{
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43,
+		},
+		[]byte("Sample #2"),
+		"0922d3405faa3d194f82a45830737d5cc6c75d24",
+		sha1.Size,
+		sha1.BlockSize,
+	},
+	{
+		sha1.New,
+		[]byte{
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			0xb0, 0xb1, 0xb2, 0xb3,
+		},
+		[]byte("Sample #3"),
+		"bcf41eab8bb2d802f3d05caf7cb092ecf8d1a3aa",
+		sha1.Size,
+		sha1.BlockSize,
+	},
+
+	// Test from Plan 9.
+	{
+		md5.New,
+		[]byte("Jefe"),
+		[]byte("what do ya want for nothing?"),
+		"750c783e6ab0b503eaa86e310a5db738",
+		md5.Size,
+		md5.BlockSize,
+	},
+
+	// Tests from RFC 4231
+	{
+		sha256.New,
+		[]byte{
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			0x0b, 0x0b, 0x0b, 0x0b,
+		},
+		[]byte("Hi There"),
+		"b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
+		sha256.Size,
+		sha256.BlockSize,
+	},
+	{
+		sha256.New,
+		[]byte("Jefe"),
+		[]byte("what do ya want for nothing?"),
+		"5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
+		sha256.Size,
+		sha256.BlockSize,
+	},
+	{
+		sha256.New,
+		[]byte{
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa,
+		},
+		[]byte{
+			0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+			0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+			0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+			0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+			0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+			0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+			0xdd, 0xdd,
+		},
+		"773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
+		sha256.Size,
+		sha256.BlockSize,
+	},
+	{
+		sha256.New,
+		[]byte{
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+			0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+			0x19,
+		},
+		[]byte{
+			0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+			0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+			0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+			0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+			0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+			0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+			0xcd, 0xcd,
+		},
+		"82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
+		sha256.Size,
+		sha256.BlockSize,
+	},
+	{
+		sha256.New,
+		[]byte{
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa,
+		},
+		[]byte("Test Using Larger Than Block-Size Key - Hash Key First"),
+		"60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
+		sha256.Size,
+		sha256.BlockSize,
+	},
+	{
+		sha256.New,
+		[]byte{
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa,
+		},
+		[]byte("This is a test using a larger than block-size key " +
+			"and a larger than block-size data. The key needs to " +
+			"be hashed before being used by the HMAC algorithm."),
+		"9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
+		sha256.Size,
+		sha256.BlockSize,
+	},
+
+	// Tests from http://csrc.nist.gov/groups/ST/toolkit/examples.html
+	// (truncated tag tests are left out)
+	{
+		sha1.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"5fd596ee78d5553c8ff4e72d266dfd192366da29",
+		sha1.Size,
+		sha1.BlockSize,
+	},
+	{
+		sha1.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13,
+		},
+		[]byte("Sample message for keylen<blocklen"),
+		"4c99ff0cb1b31bd33f8431dbaf4d17fcd356a807",
+		sha1.Size,
+		sha1.BlockSize,
+	},
+	{
+		sha1.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"2d51b2f7750e410584662e38f133435f4c4fd42a",
+		sha1.Size,
+		sha1.BlockSize,
+	},
+	{
+		sha256.New224,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"c7405e3ae058e8cd30b08b4140248581ed174cb34e1224bcc1efc81b",
+		sha256.Size224,
+		sha256.BlockSize,
+	},
+	{
+		sha256.New224,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b,
+		},
+		[]byte("Sample message for keylen<blocklen"),
+		"e3d249a8cfb67ef8b7a169e9a0a599714a2cecba65999a51beb8fbbe",
+		sha256.Size224,
+		sha256.BlockSize,
+	},
+	{
+		sha256.New224,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"91c52509e5af8531601ae6230099d90bef88aaefb961f4080abc014d",
+		sha256.Size224,
+		sha256.BlockSize,
+	},
+	{
+		sha256.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"8bb9a1db9806f20df7f77b82138c7914d174d59e13dc4d0169c9057b133e1d62",
+		sha256.Size,
+		sha256.BlockSize,
+	},
+	{
+		sha256.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+		},
+		[]byte("Sample message for keylen<blocklen"),
+		"a28cf43130ee696a98f14a37678b56bcfcbdd9e5cf69717fecf5480f0ebdf790",
+		sha256.Size,
+		sha256.BlockSize,
+	},
+	{
+		sha256.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"bdccb6c72ddeadb500ae768386cb38cc41c63dbb0878ddb9c7a38a431b78378d",
+		sha256.Size,
+		sha256.BlockSize,
+	},
+	{
+		sha512.New384,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"63c5daa5e651847ca897c95814ab830bededc7d25e83eef9195cd45857a37f448947858f5af50cc2b1b730ddf29671a9",
+		sha512.Size384,
+		sha512.BlockSize,
+	},
+	{
+		sha512.New384,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+		},
+		[]byte("Sample message for keylen<blocklen"),
+		"6eb242bdbb582ca17bebfa481b1e23211464d2b7f8c20b9ff2201637b93646af5ae9ac316e98db45d9cae773675eeed0",
+		sha512.Size384,
+		sha512.BlockSize,
+	},
+	{
+		sha512.New384,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"5b664436df69b0ca22551231a3f0a3d5b4f97991713cfa84bff4d0792eff96c27dccbbb6f79b65d548b40e8564cef594",
+		sha512.Size384,
+		sha512.BlockSize,
+	},
+	{
+		sha512.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"fc25e240658ca785b7a811a8d3f7b4ca" +
+			"48cfa26a8a366bf2cd1f836b05fcb024bd36853081811d6c" +
+			"ea4216ebad79da1cfcb95ea4586b8a0ce356596a55fb1347",
+		sha512.Size,
+		sha512.BlockSize,
+	},
+	{
+		sha512.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		},
+		[]byte("Sample message for keylen<blocklen"),
+		"fd44c18bda0bb0a6ce0e82b031bf2818" +
+			"f6539bd56ec00bdc10a8a2d730b3634de2545d639b0f2cf7" +
+			"10d0692c72a1896f1f211c2b922d1a96c392e07e7ea9fedc",
+		sha512.Size,
+		sha512.BlockSize,
+	},
+	{
+		sha512.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"d93ec8d2de1ad2a9957cb9b83f14e76a" +
+			"d6b5e0cce285079a127d3b14bccb7aa7286d4ac0d4ce6421" +
+			"5f2bc9e6870b33d97438be4aaa20cda5c5a912b48b8e27f3",
+		sha512.Size,
+		sha512.BlockSize,
+	},
+}
+
+func TestHMAC(t *testing.T) {
+	for i, tt := range hmacTests {
+		h := New(tt.hash, tt.key)
+		if s := h.Size(); s != tt.size {
+			t.Errorf("Size: got %v, want %v", s, tt.size)
+		}
+		if b := h.BlockSize(); b != tt.blocksize {
+			t.Errorf("BlockSize: got %v, want %v", b, tt.blocksize)
+		}
+		for j := 0; j < 2; j++ {
+			n, err := h.Write(tt.in)
+			if n != len(tt.in) || err != nil {
+				t.Errorf("test %d.%d: Write(%d) = %d, %v", i, j, len(tt.in), n, err)
+				continue
+			}
+
+			// Repetitive Sum() calls should return the same value
+			for k := 0; k < 2; k++ {
+				sum := fmt.Sprintf("%x", h.Sum(nil))
+				if sum != tt.out {
+					t.Errorf("test %d.%d.%d: have %s want %s\n", i, j, k, sum, tt.out)
+				}
+			}
+
+			// Second iteration: make sure reset works.
+			h.Reset()
+		}
+	}
+}
+
+func TestEqual(t *testing.T) {
+	a := []byte("test")
+	b := []byte("test1")
+	c := []byte("test2")
+
+	if !Equal(b, b) {
+		t.Error("Equal failed with equal arguments")
+	}
+	if Equal(a, b) {
+		t.Error("Equal accepted a prefix of the second argument")
+	}
+	if Equal(b, a) {
+		t.Error("Equal accepted a prefix of the first argument")
+	}
+	if Equal(b, c) {
+		t.Error("Equal accepted unequal slices")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/md5/gen.go b/third_party/gofrontend/libgo/go/crypto/md5/gen.go
new file mode 100644
index 0000000..75295e4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/md5/gen.go
@@ -0,0 +1,316 @@
+// 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.
+
+// +build ignore
+
+// This program generates md5block.go
+// Invoke as
+//
+//	go run gen.go [-full] |gofmt >md5block.go
+//
+// The -full flag causes the generated code to do a full
+// (16x) unrolling instead of a 4x unrolling.
+
+package main
+
+import (
+	"flag"
+	"log"
+	"os"
+	"strings"
+	"text/template"
+)
+
+func main() {
+	flag.Parse()
+
+	t := template.Must(template.New("main").Funcs(funcs).Parse(program))
+	if err := t.Execute(os.Stdout, data); err != nil {
+		log.Fatal(err)
+	}
+}
+
+type Data struct {
+	a, b, c, d string
+	Shift1     []int
+	Shift2     []int
+	Shift3     []int
+	Shift4     []int
+	Table1     []uint32
+	Table2     []uint32
+	Table3     []uint32
+	Table4     []uint32
+	Full       bool
+}
+
+var funcs = template.FuncMap{
+	"dup":     dup,
+	"relabel": relabel,
+	"rotate":  rotate,
+}
+
+func dup(count int, x []int) []int {
+	var out []int
+	for i := 0; i < count; i++ {
+		out = append(out, x...)
+	}
+	return out
+}
+
+func relabel(s string) string {
+	return strings.NewReplacer("a", data.a, "b", data.b, "c", data.c, "d", data.d).Replace(s)
+}
+
+func rotate() string {
+	data.a, data.b, data.c, data.d = data.d, data.a, data.b, data.c
+	return "" // no output
+}
+
+func init() {
+	flag.BoolVar(&data.Full, "full", false, "complete unrolling")
+}
+
+var data = Data{
+	a:      "a",
+	b:      "b",
+	c:      "c",
+	d:      "d",
+	Shift1: []int{7, 12, 17, 22},
+	Shift2: []int{5, 9, 14, 20},
+	Shift3: []int{4, 11, 16, 23},
+	Shift4: []int{6, 10, 15, 21},
+
+	// table[i] = int((1<<32) * abs(sin(i+1 radians))).
+	Table1: []uint32{
+		// round 1
+		0xd76aa478,
+		0xe8c7b756,
+		0x242070db,
+		0xc1bdceee,
+		0xf57c0faf,
+		0x4787c62a,
+		0xa8304613,
+		0xfd469501,
+		0x698098d8,
+		0x8b44f7af,
+		0xffff5bb1,
+		0x895cd7be,
+		0x6b901122,
+		0xfd987193,
+		0xa679438e,
+		0x49b40821,
+	},
+	Table2: []uint32{
+		// round 2
+		0xf61e2562,
+		0xc040b340,
+		0x265e5a51,
+		0xe9b6c7aa,
+		0xd62f105d,
+		0x2441453,
+		0xd8a1e681,
+		0xe7d3fbc8,
+		0x21e1cde6,
+		0xc33707d6,
+		0xf4d50d87,
+		0x455a14ed,
+		0xa9e3e905,
+		0xfcefa3f8,
+		0x676f02d9,
+		0x8d2a4c8a,
+	},
+	Table3: []uint32{
+		// round3
+		0xfffa3942,
+		0x8771f681,
+		0x6d9d6122,
+		0xfde5380c,
+		0xa4beea44,
+		0x4bdecfa9,
+		0xf6bb4b60,
+		0xbebfbc70,
+		0x289b7ec6,
+		0xeaa127fa,
+		0xd4ef3085,
+		0x4881d05,
+		0xd9d4d039,
+		0xe6db99e5,
+		0x1fa27cf8,
+		0xc4ac5665,
+	},
+	Table4: []uint32{
+		// round 4
+		0xf4292244,
+		0x432aff97,
+		0xab9423a7,
+		0xfc93a039,
+		0x655b59c3,
+		0x8f0ccc92,
+		0xffeff47d,
+		0x85845dd1,
+		0x6fa87e4f,
+		0xfe2ce6e0,
+		0xa3014314,
+		0x4e0811a1,
+		0xf7537e82,
+		0xbd3af235,
+		0x2ad7d2bb,
+		0xeb86d391,
+	},
+}
+
+var program = `// Copyright 2013 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.
+
+// DO NOT EDIT.
+// Generate with: go run gen.go{{if .Full}} -full{{end}} | gofmt >md5block.go
+
+package md5
+
+import (
+	"unsafe"
+	"runtime"
+)
+
+{{if not .Full}}
+	var t1 = [...]uint32{
+	{{range .Table1}}{{printf "\t%#x,\n" .}}{{end}}
+	}
+	
+	var t2 = [...]uint32{
+	{{range .Table2}}{{printf "\t%#x,\n" .}}{{end}}
+	}
+	
+	var t3 = [...]uint32{
+	{{range .Table3}}{{printf "\t%#x,\n" .}}{{end}}
+	}
+	
+	var t4 = [...]uint32{
+	{{range .Table4}}{{printf "\t%#x,\n" .}}{{end}}
+	}
+{{end}}
+
+const x86 = runtime.GOARCH == "amd64" || runtime.GOARCH == "386"
+
+var littleEndian bool
+
+func init() {
+	x := uint32(0x04030201)
+	y := [4]byte{0x1, 0x2, 0x3, 0x4}
+	littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y
+}
+
+func blockGeneric(dig *digest, p []byte) {
+	a := dig.s[0]
+	b := dig.s[1]
+	c := dig.s[2]
+	d := dig.s[3]
+	var X *[16]uint32
+	var xbuf [16]uint32
+	for len(p) >= chunk {
+		aa, bb, cc, dd := a, b, c, d
+
+		// This is a constant condition - it is not evaluated on each iteration.
+		if x86 {
+			// MD5 was designed so that x86 processors can just iterate
+			// over the block data directly as uint32s, and we generate
+			// less code and run 1.3x faster if we take advantage of that.
+			// My apologies.
+			X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+		} else if littleEndian && uintptr(unsafe.Pointer(&p[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+			X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+		} else {
+			X = &xbuf
+			j := 0
+			for i := 0; i < 16; i++ {
+				X[i&15] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+				j += 4
+			}
+		}
+
+		{{if .Full}}
+			// Round 1.
+			{{range $i, $s := dup 4 .Shift1}}
+				{{index $.Table1 $i | printf "a += (((c^d)&b)^d) + X[%d] + %d" $i | relabel}}
+				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+				{{rotate}}
+			{{end}}
+	
+			// Round 2.
+			{{range $i, $s := dup 4 .Shift2}}
+				{{index $.Table2 $i | printf "a += (((b^c)&d)^c) + X[(1+5*%d)&15] + %d" $i | relabel}}
+				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+				{{rotate}}
+			{{end}}
+	
+			// Round 3.
+			{{range $i, $s := dup 4 .Shift3}}
+				{{index $.Table3 $i | printf "a += (b^c^d) + X[(5+3*%d)&15] + %d" $i | relabel}}
+				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+				{{rotate}}
+			{{end}}
+	
+			// Round 4.
+			{{range $i, $s := dup 4 .Shift4}}
+				{{index $.Table4 $i | printf "a += (c^(b|^d)) + X[(7*%d)&15] + %d" $i | relabel}}
+				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+				{{rotate}}
+			{{end}}
+		{{else}}
+			// Round 1.
+			for i := uint(0); i < 16; {
+				{{range $s := .Shift1}}
+					{{printf "a += (((c^d)&b)^d) + X[i&15] + t1[i&15]" | relabel}}
+					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+					i++
+					{{rotate}}
+				{{end}}
+			}
+	
+			// Round 2.
+			for i := uint(0); i < 16; {
+				{{range $s := .Shift2}}
+					{{printf "a += (((b^c)&d)^c) + X[(1+5*i)&15] + t2[i&15]" | relabel}}
+					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+					i++
+					{{rotate}}
+				{{end}}
+			}
+	
+			// Round 3.
+			for i := uint(0); i < 16; {
+				{{range $s := .Shift3}}
+					{{printf "a += (b^c^d) + X[(5+3*i)&15] + t3[i&15]" | relabel}}
+					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+					i++
+					{{rotate}}
+				{{end}}
+			}
+	
+			// Round 4.
+			for i := uint(0); i < 16; {
+				{{range $s := .Shift4}}
+					{{printf "a += (c^(b|^d)) + X[(7*i)&15] + t4[i&15]" | relabel}}
+					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+					i++
+					{{rotate}}
+				{{end}}
+			}
+		{{end}}
+
+		a += aa
+		b += bb
+		c += cc
+		d += dd
+
+		p = p[chunk:]
+	}
+
+	dig.s[0] = a
+	dig.s[1] = b
+	dig.s[2] = c
+	dig.s[3] = d
+}
+`
diff --git a/third_party/gofrontend/libgo/go/crypto/md5/md5.go b/third_party/gofrontend/libgo/go/crypto/md5/md5.go
new file mode 100644
index 0000000..1a1f35f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/md5/md5.go
@@ -0,0 +1,134 @@
+// 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 md5 implements the MD5 hash algorithm as defined in RFC 1321.
+package md5
+
+import (
+	"crypto"
+	"hash"
+)
+
+func init() {
+	crypto.RegisterHash(crypto.MD5, New)
+}
+
+// The size of an MD5 checksum in bytes.
+const Size = 16
+
+// The blocksize of MD5 in bytes.
+const BlockSize = 64
+
+const (
+	chunk = 64
+	init0 = 0x67452301
+	init1 = 0xEFCDAB89
+	init2 = 0x98BADCFE
+	init3 = 0x10325476
+)
+
+// digest represents the partial evaluation of a checksum.
+type digest struct {
+	s   [4]uint32
+	x   [chunk]byte
+	nx  int
+	len uint64
+}
+
+func (d *digest) Reset() {
+	d.s[0] = init0
+	d.s[1] = init1
+	d.s[2] = init2
+	d.s[3] = init3
+	d.nx = 0
+	d.len = 0
+}
+
+// New returns a new hash.Hash computing the MD5 checksum.
+func New() hash.Hash {
+	d := new(digest)
+	d.Reset()
+	return d
+}
+
+func (d *digest) Size() int { return Size }
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
+	nn = len(p)
+	d.len += uint64(nn)
+	if d.nx > 0 {
+		n := len(p)
+		if n > chunk-d.nx {
+			n = chunk - d.nx
+		}
+		for i := 0; i < n; i++ {
+			d.x[d.nx+i] = p[i]
+		}
+		d.nx += n
+		if d.nx == chunk {
+			block(d, d.x[0:chunk])
+			d.nx = 0
+		}
+		p = p[n:]
+	}
+	if len(p) >= chunk {
+		n := len(p) &^ (chunk - 1)
+		block(d, p[:n])
+		p = p[n:]
+	}
+	if len(p) > 0 {
+		d.nx = copy(d.x[:], p)
+	}
+	return
+}
+
+func (d0 *digest) Sum(in []byte) []byte {
+	// Make a copy of d0 so that caller can keep writing and summing.
+	d := *d0
+	hash := d.checkSum()
+	return append(in, hash[:]...)
+}
+
+func (d *digest) checkSum() [Size]byte {
+	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
+	len := d.len
+	var tmp [64]byte
+	tmp[0] = 0x80
+	if len%64 < 56 {
+		d.Write(tmp[0 : 56-len%64])
+	} else {
+		d.Write(tmp[0 : 64+56-len%64])
+	}
+
+	// Length in bits.
+	len <<= 3
+	for i := uint(0); i < 8; i++ {
+		tmp[i] = byte(len >> (8 * i))
+	}
+	d.Write(tmp[0:8])
+
+	if d.nx != 0 {
+		panic("d.nx != 0")
+	}
+
+	var digest [Size]byte
+	for i, s := range d.s {
+		digest[i*4] = byte(s)
+		digest[i*4+1] = byte(s >> 8)
+		digest[i*4+2] = byte(s >> 16)
+		digest[i*4+3] = byte(s >> 24)
+	}
+
+	return digest
+}
+
+// Sum returns the MD5 checksum of the data.
+func Sum(data []byte) [Size]byte {
+	var d digest
+	d.Reset()
+	d.Write(data)
+	return d.checkSum()
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/md5/md5_test.go b/third_party/gofrontend/libgo/go/crypto/md5/md5_test.go
new file mode 100644
index 0000000..e7faf49
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/md5/md5_test.go
@@ -0,0 +1,163 @@
+// 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 md5
+
+import (
+	"crypto/rand"
+	"fmt"
+	"io"
+	"testing"
+	"unsafe"
+)
+
+type md5Test struct {
+	out string
+	in  string
+}
+
+var golden = []md5Test{
+	{"d41d8cd98f00b204e9800998ecf8427e", ""},
+	{"0cc175b9c0f1b6a831c399e269772661", "a"},
+	{"187ef4436122d1cc2f40dc2b92f0eba0", "ab"},
+	{"900150983cd24fb0d6963f7d28e17f72", "abc"},
+	{"e2fc714c4727ee9395f324cd2e7f331f", "abcd"},
+	{"ab56b4d92b40713acc5af89985d4b786", "abcde"},
+	{"e80b5017098950fc58aad83c8c14978e", "abcdef"},
+	{"7ac66c0f148de9519b8bd264312c4d64", "abcdefg"},
+	{"e8dc4081b13434b45189a720b77b6818", "abcdefgh"},
+	{"8aa99b1f439ff71293e95357bac6fd94", "abcdefghi"},
+	{"a925576942e94b2ef57a066101b48876", "abcdefghij"},
+	{"d747fc1719c7eacb84058196cfe56d57", "Discard medicine more than two years old."},
+	{"bff2dcb37ef3a44ba43ab144768ca837", "He who has a shady past knows that nice guys finish last."},
+	{"0441015ecb54a7342d017ed1bcfdbea5", "I wouldn't marry him with a ten foot pole."},
+	{"9e3cac8e9e9757a60c3ea391130d3689", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+	{"a0f04459b031f916a59a35cc482dc039", "The days of the digital watch are numbered.  -Tom Stoppard"},
+	{"e7a48e0fe884faf31475d2a04b1362cc", "Nepal premier won't resign."},
+	{"637d2fe925c07c113800509964fb0e06", "For every action there is an equal and opposite government program."},
+	{"834a8d18d5c6562119cf4c7f5086cb71", "His money is twice tainted: 'taint yours and 'taint mine."},
+	{"de3a4d2fd6c73ec2db2abad23b444281", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+	{"acf203f997e2cf74ea3aff86985aefaf", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+	{"e1c1384cb4d2221dfdd7c795a4222c9a", "size:  a.out:  bad magic"},
+	{"c90f3ddecc54f34228c063d7525bf644", "The major problem is with sendmail.  -Mark Horton"},
+	{"cdf7ab6c1fd49bd9933c43f3ea5af185", "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
+	{"83bc85234942fc883c063cbd7f0ad5d0", "If the enemy is within range, then so are you."},
+	{"277cbe255686b48dd7e8f389394d9299", "It's well we cannot hear the screams/That we create in others' dreams."},
+	{"fd3fb0a7ffb8af16603f3d3af98f8e1f", "You remind me of a TV show, but that's all right: I watch it anyway."},
+	{"469b13a78ebf297ecda64d4723655154", "C is as portable as Stonehedge!!"},
+	{"63eb3a2f466410104731c4b037600110", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+	{"72c2ed7592debca1c90fc0100f931a2f", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
+	{"132f7619d33b523b1d9e5bd8e0928355", "How can you write a big system without C++?  -Paul Glick"},
+}
+
+func TestGolden(t *testing.T) {
+	for i := 0; i < len(golden); i++ {
+		g := golden[i]
+		s := fmt.Sprintf("%x", Sum([]byte(g.in)))
+		if s != g.out {
+			t.Fatalf("Sum function: md5(%s) = %s want %s", g.in, s, g.out)
+		}
+		c := New()
+		buf := make([]byte, len(g.in)+4)
+		for j := 0; j < 3+4; j++ {
+			if j < 2 {
+				io.WriteString(c, g.in)
+			} else if j == 2 {
+				io.WriteString(c, g.in[0:len(g.in)/2])
+				c.Sum(nil)
+				io.WriteString(c, g.in[len(g.in)/2:])
+			} else if j > 2 {
+				// test unaligned write
+				buf = buf[1:]
+				copy(buf, g.in)
+				c.Write(buf[:len(g.in)])
+			}
+			s := fmt.Sprintf("%x", c.Sum(nil))
+			if s != g.out {
+				t.Fatalf("md5[%d](%s) = %s want %s", j, g.in, s, g.out)
+			}
+			c.Reset()
+		}
+	}
+}
+
+func TestLarge(t *testing.T) {
+	const N = 10000
+	ok := "2bb571599a4180e1d542f76904adc3df" // md5sum of "0123456789" * 1000
+	block := make([]byte, 10004)
+	c := New()
+	for offset := 0; offset < 4; offset++ {
+		for i := 0; i < N; i++ {
+			block[offset+i] = '0' + byte(i%10)
+		}
+		for blockSize := 10; blockSize <= N; blockSize *= 10 {
+			blocks := N / blockSize
+			b := block[offset : offset+blockSize]
+			c.Reset()
+			for i := 0; i < blocks; i++ {
+				c.Write(b)
+			}
+			s := fmt.Sprintf("%x", c.Sum(nil))
+			if s != ok {
+				t.Fatalf("md5 TestLarge offset=%d, blockSize=%d = %s want %s", offset, blockSize, s, ok)
+			}
+		}
+	}
+}
+
+// Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match.
+func TestBlockGeneric(t *testing.T) {
+	gen, asm := New().(*digest), New().(*digest)
+	buf := make([]byte, BlockSize*20) // arbitrary factor
+	rand.Read(buf)
+	blockGeneric(gen, buf)
+	block(asm, buf)
+	if *gen != *asm {
+		t.Error("block and blockGeneric resulted in different states")
+	}
+}
+
+var bench = New()
+var buf = make([]byte, 8192+1)
+var sum = make([]byte, bench.Size())
+
+func benchmarkSize(b *testing.B, size int, unaligned bool) {
+	b.SetBytes(int64(size))
+	buf := buf
+	if unaligned {
+		if uintptr(unsafe.Pointer(&buf[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+			buf = buf[1:]
+		}
+	}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bench.Reset()
+		bench.Write(buf[:size])
+		bench.Sum(sum[:0])
+	}
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+	benchmarkSize(b, 8, false)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+	benchmarkSize(b, 1024, false)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+	benchmarkSize(b, 8192, false)
+}
+
+func BenchmarkHash8BytesUnaligned(b *testing.B) {
+	benchmarkSize(b, 8, true)
+}
+
+func BenchmarkHash1KUnaligned(b *testing.B) {
+	benchmarkSize(b, 1024, true)
+}
+
+func BenchmarkHash8KUnaligned(b *testing.B) {
+	benchmarkSize(b, 8192, true)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/md5/md5block.go b/third_party/gofrontend/libgo/go/crypto/md5/md5block.go
new file mode 100644
index 0000000..e2a1767
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/md5/md5block.go
@@ -0,0 +1,265 @@
+// Copyright 2013 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.
+
+// DO NOT EDIT.
+// Generate with: go run gen.go -full | gofmt >md5block.go
+
+package md5
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+const x86 = runtime.GOARCH == "amd64" || runtime.GOARCH == "386"
+
+var littleEndian bool
+
+func init() {
+	x := uint32(0x04030201)
+	y := [4]byte{0x1, 0x2, 0x3, 0x4}
+	littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y
+}
+
+func blockGeneric(dig *digest, p []byte) {
+	a := dig.s[0]
+	b := dig.s[1]
+	c := dig.s[2]
+	d := dig.s[3]
+	var X *[16]uint32
+	var xbuf [16]uint32
+	for len(p) >= chunk {
+		aa, bb, cc, dd := a, b, c, d
+
+		// This is a constant condition - it is not evaluated on each iteration.
+		if x86 {
+			// MD5 was designed so that x86 processors can just iterate
+			// over the block data directly as uint32s, and we generate
+			// less code and run 1.3x faster if we take advantage of that.
+			// My apologies.
+			X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+		} else if littleEndian && uintptr(unsafe.Pointer(&p[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+			X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+		} else {
+			X = &xbuf
+			j := 0
+			for i := 0; i < 16; i++ {
+				X[i&15] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+				j += 4
+			}
+		}
+
+		// Round 1.
+
+		a += (((c ^ d) & b) ^ d) + X[0] + 3614090360
+		a = a<<7 | a>>(32-7) + b
+
+		d += (((b ^ c) & a) ^ c) + X[1] + 3905402710
+		d = d<<12 | d>>(32-12) + a
+
+		c += (((a ^ b) & d) ^ b) + X[2] + 606105819
+		c = c<<17 | c>>(32-17) + d
+
+		b += (((d ^ a) & c) ^ a) + X[3] + 3250441966
+		b = b<<22 | b>>(32-22) + c
+
+		a += (((c ^ d) & b) ^ d) + X[4] + 4118548399
+		a = a<<7 | a>>(32-7) + b
+
+		d += (((b ^ c) & a) ^ c) + X[5] + 1200080426
+		d = d<<12 | d>>(32-12) + a
+
+		c += (((a ^ b) & d) ^ b) + X[6] + 2821735955
+		c = c<<17 | c>>(32-17) + d
+
+		b += (((d ^ a) & c) ^ a) + X[7] + 4249261313
+		b = b<<22 | b>>(32-22) + c
+
+		a += (((c ^ d) & b) ^ d) + X[8] + 1770035416
+		a = a<<7 | a>>(32-7) + b
+
+		d += (((b ^ c) & a) ^ c) + X[9] + 2336552879
+		d = d<<12 | d>>(32-12) + a
+
+		c += (((a ^ b) & d) ^ b) + X[10] + 4294925233
+		c = c<<17 | c>>(32-17) + d
+
+		b += (((d ^ a) & c) ^ a) + X[11] + 2304563134
+		b = b<<22 | b>>(32-22) + c
+
+		a += (((c ^ d) & b) ^ d) + X[12] + 1804603682
+		a = a<<7 | a>>(32-7) + b
+
+		d += (((b ^ c) & a) ^ c) + X[13] + 4254626195
+		d = d<<12 | d>>(32-12) + a
+
+		c += (((a ^ b) & d) ^ b) + X[14] + 2792965006
+		c = c<<17 | c>>(32-17) + d
+
+		b += (((d ^ a) & c) ^ a) + X[15] + 1236535329
+		b = b<<22 | b>>(32-22) + c
+
+		// Round 2.
+
+		a += (((b ^ c) & d) ^ c) + X[(1+5*0)&15] + 4129170786
+		a = a<<5 | a>>(32-5) + b
+
+		d += (((a ^ b) & c) ^ b) + X[(1+5*1)&15] + 3225465664
+		d = d<<9 | d>>(32-9) + a
+
+		c += (((d ^ a) & b) ^ a) + X[(1+5*2)&15] + 643717713
+		c = c<<14 | c>>(32-14) + d
+
+		b += (((c ^ d) & a) ^ d) + X[(1+5*3)&15] + 3921069994
+		b = b<<20 | b>>(32-20) + c
+
+		a += (((b ^ c) & d) ^ c) + X[(1+5*4)&15] + 3593408605
+		a = a<<5 | a>>(32-5) + b
+
+		d += (((a ^ b) & c) ^ b) + X[(1+5*5)&15] + 38016083
+		d = d<<9 | d>>(32-9) + a
+
+		c += (((d ^ a) & b) ^ a) + X[(1+5*6)&15] + 3634488961
+		c = c<<14 | c>>(32-14) + d
+
+		b += (((c ^ d) & a) ^ d) + X[(1+5*7)&15] + 3889429448
+		b = b<<20 | b>>(32-20) + c
+
+		a += (((b ^ c) & d) ^ c) + X[(1+5*8)&15] + 568446438
+		a = a<<5 | a>>(32-5) + b
+
+		d += (((a ^ b) & c) ^ b) + X[(1+5*9)&15] + 3275163606
+		d = d<<9 | d>>(32-9) + a
+
+		c += (((d ^ a) & b) ^ a) + X[(1+5*10)&15] + 4107603335
+		c = c<<14 | c>>(32-14) + d
+
+		b += (((c ^ d) & a) ^ d) + X[(1+5*11)&15] + 1163531501
+		b = b<<20 | b>>(32-20) + c
+
+		a += (((b ^ c) & d) ^ c) + X[(1+5*12)&15] + 2850285829
+		a = a<<5 | a>>(32-5) + b
+
+		d += (((a ^ b) & c) ^ b) + X[(1+5*13)&15] + 4243563512
+		d = d<<9 | d>>(32-9) + a
+
+		c += (((d ^ a) & b) ^ a) + X[(1+5*14)&15] + 1735328473
+		c = c<<14 | c>>(32-14) + d
+
+		b += (((c ^ d) & a) ^ d) + X[(1+5*15)&15] + 2368359562
+		b = b<<20 | b>>(32-20) + c
+
+		// Round 3.
+
+		a += (b ^ c ^ d) + X[(5+3*0)&15] + 4294588738
+		a = a<<4 | a>>(32-4) + b
+
+		d += (a ^ b ^ c) + X[(5+3*1)&15] + 2272392833
+		d = d<<11 | d>>(32-11) + a
+
+		c += (d ^ a ^ b) + X[(5+3*2)&15] + 1839030562
+		c = c<<16 | c>>(32-16) + d
+
+		b += (c ^ d ^ a) + X[(5+3*3)&15] + 4259657740
+		b = b<<23 | b>>(32-23) + c
+
+		a += (b ^ c ^ d) + X[(5+3*4)&15] + 2763975236
+		a = a<<4 | a>>(32-4) + b
+
+		d += (a ^ b ^ c) + X[(5+3*5)&15] + 1272893353
+		d = d<<11 | d>>(32-11) + a
+
+		c += (d ^ a ^ b) + X[(5+3*6)&15] + 4139469664
+		c = c<<16 | c>>(32-16) + d
+
+		b += (c ^ d ^ a) + X[(5+3*7)&15] + 3200236656
+		b = b<<23 | b>>(32-23) + c
+
+		a += (b ^ c ^ d) + X[(5+3*8)&15] + 681279174
+		a = a<<4 | a>>(32-4) + b
+
+		d += (a ^ b ^ c) + X[(5+3*9)&15] + 3936430074
+		d = d<<11 | d>>(32-11) + a
+
+		c += (d ^ a ^ b) + X[(5+3*10)&15] + 3572445317
+		c = c<<16 | c>>(32-16) + d
+
+		b += (c ^ d ^ a) + X[(5+3*11)&15] + 76029189
+		b = b<<23 | b>>(32-23) + c
+
+		a += (b ^ c ^ d) + X[(5+3*12)&15] + 3654602809
+		a = a<<4 | a>>(32-4) + b
+
+		d += (a ^ b ^ c) + X[(5+3*13)&15] + 3873151461
+		d = d<<11 | d>>(32-11) + a
+
+		c += (d ^ a ^ b) + X[(5+3*14)&15] + 530742520
+		c = c<<16 | c>>(32-16) + d
+
+		b += (c ^ d ^ a) + X[(5+3*15)&15] + 3299628645
+		b = b<<23 | b>>(32-23) + c
+
+		// Round 4.
+
+		a += (c ^ (b | ^d)) + X[(7*0)&15] + 4096336452
+		a = a<<6 | a>>(32-6) + b
+
+		d += (b ^ (a | ^c)) + X[(7*1)&15] + 1126891415
+		d = d<<10 | d>>(32-10) + a
+
+		c += (a ^ (d | ^b)) + X[(7*2)&15] + 2878612391
+		c = c<<15 | c>>(32-15) + d
+
+		b += (d ^ (c | ^a)) + X[(7*3)&15] + 4237533241
+		b = b<<21 | b>>(32-21) + c
+
+		a += (c ^ (b | ^d)) + X[(7*4)&15] + 1700485571
+		a = a<<6 | a>>(32-6) + b
+
+		d += (b ^ (a | ^c)) + X[(7*5)&15] + 2399980690
+		d = d<<10 | d>>(32-10) + a
+
+		c += (a ^ (d | ^b)) + X[(7*6)&15] + 4293915773
+		c = c<<15 | c>>(32-15) + d
+
+		b += (d ^ (c | ^a)) + X[(7*7)&15] + 2240044497
+		b = b<<21 | b>>(32-21) + c
+
+		a += (c ^ (b | ^d)) + X[(7*8)&15] + 1873313359
+		a = a<<6 | a>>(32-6) + b
+
+		d += (b ^ (a | ^c)) + X[(7*9)&15] + 4264355552
+		d = d<<10 | d>>(32-10) + a
+
+		c += (a ^ (d | ^b)) + X[(7*10)&15] + 2734768916
+		c = c<<15 | c>>(32-15) + d
+
+		b += (d ^ (c | ^a)) + X[(7*11)&15] + 1309151649
+		b = b<<21 | b>>(32-21) + c
+
+		a += (c ^ (b | ^d)) + X[(7*12)&15] + 4149444226
+		a = a<<6 | a>>(32-6) + b
+
+		d += (b ^ (a | ^c)) + X[(7*13)&15] + 3174756917
+		d = d<<10 | d>>(32-10) + a
+
+		c += (a ^ (d | ^b)) + X[(7*14)&15] + 718787259
+		c = c<<15 | c>>(32-15) + d
+
+		b += (d ^ (c | ^a)) + X[(7*15)&15] + 3951481745
+		b = b<<21 | b>>(32-21) + c
+
+		a += aa
+		b += bb
+		c += cc
+		d += dd
+
+		p = p[chunk:]
+	}
+
+	dig.s[0] = a
+	dig.s[1] = b
+	dig.s[2] = c
+	dig.s[3] = d
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/md5/md5block_decl.go b/third_party/gofrontend/libgo/go/crypto/md5/md5block_decl.go
new file mode 100644
index 0000000..d7956a6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/md5/md5block_decl.go
@@ -0,0 +1,11 @@
+// Copyright 2013 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.
+
+// +build amd64 amd64p32 386 arm
+
+package md5
+
+//go:noescape
+
+func block(dig *digest, p []byte)
diff --git a/third_party/gofrontend/libgo/go/crypto/md5/md5block_generic.go b/third_party/gofrontend/libgo/go/crypto/md5/md5block_generic.go
new file mode 100644
index 0000000..263463e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/md5/md5block_generic.go
@@ -0,0 +1,9 @@
+// Copyright 2014 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.
+
+// +build !amd64,!amd64p32,!386,!arm
+
+package md5
+
+var block = blockGeneric
diff --git a/third_party/gofrontend/libgo/go/crypto/rand/rand.go b/third_party/gofrontend/libgo/go/crypto/rand/rand.go
new file mode 100644
index 0000000..4da3adb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rand/rand.go
@@ -0,0 +1,21 @@
+// Copyright 2010 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 rand implements a cryptographically secure
+// pseudorandom number generator.
+package rand
+
+import "io"
+
+// Reader is a global, shared instance of a cryptographically
+// strong pseudo-random generator.
+// On Unix-like systems, Reader reads from /dev/urandom.
+// On Windows systems, Reader uses the CryptGenRandom API.
+var Reader io.Reader
+
+// Read is a helper function that calls Reader.Read using io.ReadFull.
+// On return, n == len(b) if and only if err == nil.
+func Read(b []byte) (n int, err error) {
+	return io.ReadFull(Reader, b)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rand/rand_test.go b/third_party/gofrontend/libgo/go/crypto/rand/rand_test.go
new file mode 100644
index 0000000..e46e61d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rand/rand_test.go
@@ -0,0 +1,43 @@
+// Copyright 2010 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 rand
+
+import (
+	"bytes"
+	"compress/flate"
+	"io"
+	"testing"
+)
+
+func TestRead(t *testing.T) {
+	var n int = 4e6
+	if testing.Short() {
+		n = 1e5
+	}
+	b := make([]byte, n)
+	n, err := io.ReadFull(Reader, b)
+	if n != len(b) || err != nil {
+		t.Fatalf("ReadFull(buf) = %d, %s", n, err)
+	}
+
+	var z bytes.Buffer
+	f, _ := flate.NewWriter(&z, 5)
+	f.Write(b)
+	f.Close()
+	if z.Len() < len(b)*99/100 {
+		t.Fatalf("Compressed %d -> %d", len(b), z.Len())
+	}
+}
+
+func TestReadEmpty(t *testing.T) {
+	n, err := Reader.Read(make([]byte, 0))
+	if n != 0 || err != nil {
+		t.Fatalf("Read(make([]byte, 0)) = %d, %v", n, err)
+	}
+	n, err = Reader.Read(nil)
+	if n != 0 || err != nil {
+		t.Fatalf("Read(nil) = %d, %v", n, err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rand/rand_unix.go b/third_party/gofrontend/libgo/go/crypto/rand/rand_unix.go
new file mode 100644
index 0000000..1e741fd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rand/rand_unix.go
@@ -0,0 +1,138 @@
+// Copyright 2010 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris
+
+// Unix cryptographically secure pseudorandom number
+// generator.
+
+package rand
+
+import (
+	"bufio"
+	"crypto/aes"
+	"crypto/cipher"
+	"io"
+	"os"
+	"runtime"
+	"sync"
+	"time"
+)
+
+// Easy implementation: read from /dev/urandom.
+// This is sufficient on Linux, OS X, and FreeBSD.
+
+func init() {
+	if runtime.GOOS == "plan9" {
+		Reader = newReader(nil)
+	} else {
+		Reader = &devReader{name: "/dev/urandom"}
+	}
+}
+
+// A devReader satisfies reads by reading the file named name.
+type devReader struct {
+	name string
+	f    io.Reader
+	mu   sync.Mutex
+}
+
+func (r *devReader) Read(b []byte) (n int, err error) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.f == nil {
+		f, err := os.Open(r.name)
+		if f == nil {
+			return 0, err
+		}
+		if runtime.GOOS == "plan9" {
+			r.f = f
+		} else {
+			r.f = bufio.NewReader(f)
+		}
+	}
+	return r.f.Read(b)
+}
+
+// Alternate pseudo-random implementation for use on
+// systems without a reliable /dev/urandom.
+
+// newReader returns a new pseudorandom generator that
+// seeds itself by reading from entropy.  If entropy == nil,
+// the generator seeds itself by reading from the system's
+// random number generator, typically /dev/random.
+// The Read method on the returned reader always returns
+// the full amount asked for, or else it returns an error.
+//
+// The generator uses the X9.31 algorithm with AES-128,
+// reseeding after every 1 MB of generated data.
+func newReader(entropy io.Reader) io.Reader {
+	if entropy == nil {
+		entropy = &devReader{name: "/dev/random"}
+	}
+	return &reader{entropy: entropy}
+}
+
+type reader struct {
+	mu                   sync.Mutex
+	budget               int // number of bytes that can be generated
+	cipher               cipher.Block
+	entropy              io.Reader
+	time, seed, dst, key [aes.BlockSize]byte
+}
+
+func (r *reader) Read(b []byte) (n int, err error) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	n = len(b)
+
+	for len(b) > 0 {
+		if r.budget == 0 {
+			_, err := io.ReadFull(r.entropy, r.seed[0:])
+			if err != nil {
+				return n - len(b), err
+			}
+			_, err = io.ReadFull(r.entropy, r.key[0:])
+			if err != nil {
+				return n - len(b), err
+			}
+			r.cipher, err = aes.NewCipher(r.key[0:])
+			if err != nil {
+				return n - len(b), err
+			}
+			r.budget = 1 << 20 // reseed after generating 1MB
+		}
+		r.budget -= aes.BlockSize
+
+		// ANSI X9.31 (== X9.17) algorithm, but using AES in place of 3DES.
+		//
+		// single block:
+		// t = encrypt(time)
+		// dst = encrypt(t^seed)
+		// seed = encrypt(t^dst)
+		ns := time.Now().UnixNano()
+		r.time[0] = byte(ns >> 56)
+		r.time[1] = byte(ns >> 48)
+		r.time[2] = byte(ns >> 40)
+		r.time[3] = byte(ns >> 32)
+		r.time[4] = byte(ns >> 24)
+		r.time[5] = byte(ns >> 16)
+		r.time[6] = byte(ns >> 8)
+		r.time[7] = byte(ns)
+		r.cipher.Encrypt(r.time[0:], r.time[0:])
+		for i := 0; i < aes.BlockSize; i++ {
+			r.dst[i] = r.time[i] ^ r.seed[i]
+		}
+		r.cipher.Encrypt(r.dst[0:], r.dst[0:])
+		for i := 0; i < aes.BlockSize; i++ {
+			r.seed[i] = r.time[i] ^ r.dst[i]
+		}
+		r.cipher.Encrypt(r.seed[0:], r.seed[0:])
+
+		m := copy(b, r.dst[0:])
+		b = b[m:]
+	}
+
+	return n, nil
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rand/rand_windows.go b/third_party/gofrontend/libgo/go/crypto/rand/rand_windows.go
new file mode 100644
index 0000000..82b39b6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rand/rand_windows.go
@@ -0,0 +1,47 @@
+// Copyright 2010 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.
+
+// Windows cryptographically secure pseudorandom number
+// generator.
+
+package rand
+
+import (
+	"os"
+	"sync"
+	"syscall"
+)
+
+// Implemented by using Windows CryptoAPI 2.0.
+
+func init() { Reader = &rngReader{} }
+
+// A rngReader satisfies reads by reading from the Windows CryptGenRandom API.
+type rngReader struct {
+	prov syscall.Handle
+	mu   sync.Mutex
+}
+
+func (r *rngReader) Read(b []byte) (n int, err error) {
+	r.mu.Lock()
+	if r.prov == 0 {
+		const provType = syscall.PROV_RSA_FULL
+		const flags = syscall.CRYPT_VERIFYCONTEXT | syscall.CRYPT_SILENT
+		err := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
+		if err != nil {
+			r.mu.Unlock()
+			return 0, os.NewSyscallError("CryptAcquireContext", err)
+		}
+	}
+	r.mu.Unlock()
+
+	if len(b) == 0 {
+		return 0, nil
+	}
+	err = syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
+	if err != nil {
+		return 0, os.NewSyscallError("CryptGenRandom", err)
+	}
+	return len(b), nil
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rand/util.go b/third_party/gofrontend/libgo/go/crypto/rand/util.go
new file mode 100644
index 0000000..5f74407
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rand/util.go
@@ -0,0 +1,136 @@
+// 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.
+
+package rand
+
+import (
+	"errors"
+	"io"
+	"math/big"
+)
+
+// smallPrimes is a list of small, prime numbers that allows us to rapidly
+// exclude some fraction of composite candidates when searching for a random
+// prime. This list is truncated at the point where smallPrimesProduct exceeds
+// a uint64. It does not include two because we ensure that the candidates are
+// odd by construction.
+var smallPrimes = []uint8{
+	3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
+}
+
+// smallPrimesProduct is the product of the values in smallPrimes and allows us
+// to reduce a candidate prime by this number and then determine whether it's
+// coprime to all the elements of smallPrimes without further big.Int
+// operations.
+var smallPrimesProduct = new(big.Int).SetUint64(16294579238595022365)
+
+// Prime returns a number, p, of the given size, such that p is prime
+// with high probability.
+// Prime will return error for any error returned by rand.Read or if bits < 2.
+func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
+	if bits < 2 {
+		err = errors.New("crypto/rand: prime size must be at least 2-bit")
+		return
+	}
+
+	b := uint(bits % 8)
+	if b == 0 {
+		b = 8
+	}
+
+	bytes := make([]byte, (bits+7)/8)
+	p = new(big.Int)
+
+	bigMod := new(big.Int)
+
+	for {
+		_, err = io.ReadFull(rand, bytes)
+		if err != nil {
+			return nil, err
+		}
+
+		// Clear bits in the first byte to make sure the candidate has a size <= bits.
+		bytes[0] &= uint8(int(1<<b) - 1)
+		// Don't let the value be too small, i.e, set the most significant two bits.
+		// Setting the top two bits, rather than just the top bit,
+		// means that when two of these values are multiplied together,
+		// the result isn't ever one bit short.
+		if b >= 2 {
+			bytes[0] |= 3 << (b - 2)
+		} else {
+			// Here b==1, because b cannot be zero.
+			bytes[0] |= 1
+			if len(bytes) > 1 {
+				bytes[1] |= 0x80
+			}
+		}
+		// Make the value odd since an even number this large certainly isn't prime.
+		bytes[len(bytes)-1] |= 1
+
+		p.SetBytes(bytes)
+
+		// Calculate the value mod the product of smallPrimes.  If it's
+		// a multiple of any of these primes we add two until it isn't.
+		// The probability of overflowing is minimal and can be ignored
+		// because we still perform Miller-Rabin tests on the result.
+		bigMod.Mod(p, smallPrimesProduct)
+		mod := bigMod.Uint64()
+
+	NextDelta:
+		for delta := uint64(0); delta < 1<<20; delta += 2 {
+			m := mod + delta
+			for _, prime := range smallPrimes {
+				if m%uint64(prime) == 0 && (bits > 6 || m != uint64(prime)) {
+					continue NextDelta
+				}
+			}
+
+			if delta > 0 {
+				bigMod.SetUint64(delta)
+				p.Add(p, bigMod)
+			}
+			break
+		}
+
+		// There is a tiny possibility that, by adding delta, we caused
+		// the number to be one bit too long. Thus we check BitLen
+		// here.
+		if p.ProbablyPrime(20) && p.BitLen() == bits {
+			return
+		}
+	}
+}
+
+// Int returns a uniform random value in [0, max). It panics if max <= 0.
+func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) {
+	if max.Sign() <= 0 {
+		panic("crypto/rand: argument to Int is <= 0")
+	}
+	k := (max.BitLen() + 7) / 8
+
+	// b is the number of bits in the most significant byte of max.
+	b := uint(max.BitLen() % 8)
+	if b == 0 {
+		b = 8
+	}
+
+	bytes := make([]byte, k)
+	n = new(big.Int)
+
+	for {
+		_, err = io.ReadFull(rand, bytes)
+		if err != nil {
+			return nil, err
+		}
+
+		// Clear bits in the first byte to increase the probability
+		// that the candidate is < max.
+		bytes[0] &= uint8(int(1<<b) - 1)
+
+		n.SetBytes(bytes)
+		if n.Cmp(max) < 0 {
+			return
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rand/util_test.go b/third_party/gofrontend/libgo/go/crypto/rand/util_test.go
new file mode 100644
index 0000000..1e2a4dd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rand/util_test.go
@@ -0,0 +1,65 @@
+// Copyright 2013 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 rand_test
+
+import (
+	"crypto/rand"
+	"math/big"
+	"testing"
+)
+
+// http://golang.org/issue/6849.
+func TestPrimeSmall(t *testing.T) {
+	for n := 2; n < 10; n++ {
+		p, err := rand.Prime(rand.Reader, n)
+		if err != nil {
+			t.Fatalf("Can't generate %d-bit prime: %v", n, err)
+		}
+		if p.BitLen() != n {
+			t.Fatalf("%v is not %d-bit", p, n)
+		}
+		if !p.ProbablyPrime(32) {
+			t.Fatalf("%v is not prime", p)
+		}
+	}
+}
+
+// Test that passing bits < 2 causes Prime to return nil, error
+func TestPrimeBitsLt2(t *testing.T) {
+	if p, err := rand.Prime(rand.Reader, 1); p != nil || err == nil {
+		t.Errorf("Prime should return nil, error when called with bits < 2")
+	}
+}
+
+func TestInt(t *testing.T) {
+	// start at 128 so the case of (max.BitLen() % 8) == 0 is covered
+	for n := 128; n < 140; n++ {
+		b := new(big.Int).SetInt64(int64(n))
+		if i, err := rand.Int(rand.Reader, b); err != nil {
+			t.Fatalf("Can't generate random value: %v, %v", i, err)
+		}
+	}
+}
+
+func testIntPanics(t *testing.T, b *big.Int) {
+	defer func() {
+		if err := recover(); err == nil {
+			t.Errorf("Int should panic when called with max <= 0: %v", b)
+		}
+	}()
+	rand.Int(rand.Reader, b)
+}
+
+// Test that passing a new big.Int as max causes Int to panic
+func TestIntEmptyMaxPanics(t *testing.T) {
+	b := new(big.Int)
+	testIntPanics(t, b)
+}
+
+// Test that passing a negative value as max causes Int to panic
+func TestIntNegativeMaxPanics(t *testing.T) {
+	b := new(big.Int).SetInt64(int64(-1))
+	testIntPanics(t, b)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rc4/rc4.go b/third_party/gofrontend/libgo/go/crypto/rc4/rc4.go
new file mode 100644
index 0000000..9acb681
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rc4/rc4.go
@@ -0,0 +1,69 @@
+// 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 rc4 implements RC4 encryption, as defined in Bruce Schneier's
+// Applied Cryptography.
+package rc4
+
+// BUG(agl): RC4 is in common use but has design weaknesses that make
+// it a poor choice for new protocols.
+
+import "strconv"
+
+// A Cipher is an instance of RC4 using a particular key.
+type Cipher struct {
+	s    [256]uint32
+	i, j uint8
+}
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+	return "crypto/rc4: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a new Cipher.  The key argument should be the
+// RC4 key, at least 1 byte and at most 256 bytes.
+func NewCipher(key []byte) (*Cipher, error) {
+	k := len(key)
+	if k < 1 || k > 256 {
+		return nil, KeySizeError(k)
+	}
+	var c Cipher
+	for i := 0; i < 256; i++ {
+		c.s[i] = uint32(i)
+	}
+	var j uint8 = 0
+	for i := 0; i < 256; i++ {
+		j += uint8(c.s[i]) + key[i%k]
+		c.s[i], c.s[j] = c.s[j], c.s[i]
+	}
+	return &c, nil
+}
+
+// Reset zeros the key data so that it will no longer appear in the
+// process's memory.
+func (c *Cipher) Reset() {
+	for i := range c.s {
+		c.s[i] = 0
+	}
+	c.i, c.j = 0, 0
+}
+
+// xorKeyStreamGeneric sets dst to the result of XORing src with the
+// key stream.  Dst and src may be the same slice but otherwise should
+// not overlap.
+//
+// This is the pure Go version. rc4_{amd64,386,arm}* contain assembly
+// implementations. This is here for tests and to prevent bitrot.
+func (c *Cipher) xorKeyStreamGeneric(dst, src []byte) {
+	i, j := c.i, c.j
+	for k, v := range src {
+		i += 1
+		j += uint8(c.s[i])
+		c.s[i], c.s[j] = c.s[j], c.s[i]
+		dst[k] = v ^ uint8(c.s[uint8(c.s[i]+c.s[j])])
+	}
+	c.i, c.j = i, j
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rc4/rc4_asm.go b/third_party/gofrontend/libgo/go/crypto/rc4/rc4_asm.go
new file mode 100644
index 0000000..fc71b9a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rc4/rc4_asm.go
@@ -0,0 +1,18 @@
+// Copyright 2013 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.
+
+// +build amd64 amd64p32 arm 386
+
+package rc4
+
+func xorKeyStream(dst, src *byte, n int, state *[256]uint32, i, j *uint8)
+
+// XORKeyStream sets dst to the result of XORing src with the key stream.
+// Dst and src may be the same slice but otherwise should not overlap.
+func (c *Cipher) XORKeyStream(dst, src []byte) {
+	if len(src) == 0 {
+		return
+	}
+	xorKeyStream(&dst[0], &src[0], len(src), &c.s, &c.i, &c.j)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rc4/rc4_ref.go b/third_party/gofrontend/libgo/go/crypto/rc4/rc4_ref.go
new file mode 100644
index 0000000..1ecce1a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rc4/rc4_ref.go
@@ -0,0 +1,13 @@
+// Copyright 2013 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.
+
+// +build !amd64,!amd64p32,!arm,!386
+
+package rc4
+
+// XORKeyStream sets dst to the result of XORing src with the key stream.
+// Dst and src may be the same slice but otherwise should not overlap.
+func (c *Cipher) XORKeyStream(dst, src []byte) {
+	c.xorKeyStreamGeneric(dst, src)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rc4/rc4_test.go b/third_party/gofrontend/libgo/go/crypto/rc4/rc4_test.go
new file mode 100644
index 0000000..af79882
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rc4/rc4_test.go
@@ -0,0 +1,173 @@
+// 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 rc4
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+)
+
+type rc4Test struct {
+	key, keystream []byte
+}
+
+var golden = []rc4Test{
+	// Test vectors from the original cypherpunk posting of ARC4:
+	//   http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0?pli=1
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		[]byte{0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79},
+	},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a},
+	},
+	{
+		[]byte{0xef, 0x01, 0x23, 0x45},
+		[]byte{0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, 0xbd, 0x61},
+	},
+
+	// Test vectors from the Wikipedia page: http://en.wikipedia.org/wiki/RC4
+	{
+		[]byte{0x4b, 0x65, 0x79},
+		[]byte{0xeb, 0x9f, 0x77, 0x81, 0xb7, 0x34, 0xca, 0x72, 0xa7, 0x19},
+	},
+	{
+		[]byte{0x57, 0x69, 0x6b, 0x69},
+		[]byte{0x60, 0x44, 0xdb, 0x6d, 0x41, 0xb7},
+	},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{
+			0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a,
+			0x8a, 0x06, 0x1e, 0x67, 0x57, 0x6e, 0x92, 0x6d,
+			0xc7, 0x1a, 0x7f, 0xa3, 0xf0, 0xcc, 0xeb, 0x97,
+			0x45, 0x2b, 0x4d, 0x32, 0x27, 0x96, 0x5f, 0x9e,
+			0xa8, 0xcc, 0x75, 0x07, 0x6d, 0x9f, 0xb9, 0xc5,
+			0x41, 0x7a, 0xa5, 0xcb, 0x30, 0xfc, 0x22, 0x19,
+			0x8b, 0x34, 0x98, 0x2d, 0xbb, 0x62, 0x9e, 0xc0,
+			0x4b, 0x4f, 0x8b, 0x05, 0xa0, 0x71, 0x08, 0x50,
+			0x92, 0xa0, 0xc3, 0x58, 0x4a, 0x48, 0xe4, 0xa3,
+			0x0a, 0x39, 0x7b, 0x8a, 0xcd, 0x1d, 0x00, 0x9e,
+			0xc8, 0x7d, 0x68, 0x11, 0xf2, 0x2c, 0xf4, 0x9c,
+			0xa3, 0xe5, 0x93, 0x54, 0xb9, 0x45, 0x15, 0x35,
+			0xa2, 0x18, 0x7a, 0x86, 0x42, 0x6c, 0xca, 0x7d,
+			0x5e, 0x82, 0x3e, 0xba, 0x00, 0x44, 0x12, 0x67,
+			0x12, 0x57, 0xb8, 0xd8, 0x60, 0xae, 0x4c, 0xbd,
+			0x4c, 0x49, 0x06, 0xbb, 0xc5, 0x35, 0xef, 0xe1,
+			0x58, 0x7f, 0x08, 0xdb, 0x33, 0x95, 0x5c, 0xdb,
+			0xcb, 0xad, 0x9b, 0x10, 0xf5, 0x3f, 0xc4, 0xe5,
+			0x2c, 0x59, 0x15, 0x65, 0x51, 0x84, 0x87, 0xfe,
+			0x08, 0x4d, 0x0e, 0x3f, 0x03, 0xde, 0xbc, 0xc9,
+			0xda, 0x1c, 0xe9, 0x0d, 0x08, 0x5c, 0x2d, 0x8a,
+			0x19, 0xd8, 0x37, 0x30, 0x86, 0x16, 0x36, 0x92,
+			0x14, 0x2b, 0xd8, 0xfc, 0x5d, 0x7a, 0x73, 0x49,
+			0x6a, 0x8e, 0x59, 0xee, 0x7e, 0xcf, 0x6b, 0x94,
+			0x06, 0x63, 0xf4, 0xa6, 0xbe, 0xe6, 0x5b, 0xd2,
+			0xc8, 0x5c, 0x46, 0x98, 0x6c, 0x1b, 0xef, 0x34,
+			0x90, 0xd3, 0x7b, 0x38, 0xda, 0x85, 0xd3, 0x2e,
+			0x97, 0x39, 0xcb, 0x23, 0x4a, 0x2b, 0xe7, 0x40,
+		},
+	},
+}
+
+func testEncrypt(t *testing.T, desc string, c *Cipher, src, expect []byte) {
+	dst := make([]byte, len(src))
+	c.XORKeyStream(dst, src)
+	for i, v := range dst {
+		if v != expect[i] {
+			t.Fatalf("%s: mismatch at byte %d:\nhave %x\nwant %x", desc, i, dst, expect)
+		}
+	}
+}
+
+func TestGolden(t *testing.T) {
+	for gi, g := range golden {
+		data := make([]byte, len(g.keystream))
+		for i := range data {
+			data[i] = byte(i)
+		}
+
+		expect := make([]byte, len(g.keystream))
+		for i := range expect {
+			expect[i] = byte(i) ^ g.keystream[i]
+		}
+
+		for size := 1; size <= len(g.keystream); size++ {
+			c, err := NewCipher(g.key)
+			if err != nil {
+				t.Fatalf("#%d: NewCipher: %v", gi, err)
+			}
+
+			off := 0
+			for off < len(g.keystream) {
+				n := len(g.keystream) - off
+				if n > size {
+					n = size
+				}
+				desc := fmt.Sprintf("#%d@[%d:%d]", gi, off, off+n)
+				testEncrypt(t, desc, c, data[off:off+n], expect[off:off+n])
+				off += n
+			}
+		}
+	}
+}
+
+func TestBlock(t *testing.T) {
+	testBlock(t, (*Cipher).XORKeyStream)
+}
+
+// Test the pure Go version.
+// Because we have assembly for amd64, 386, and arm, this prevents
+// bitrot of the reference implementations.
+func TestBlockGeneric(t *testing.T) {
+	testBlock(t, (*Cipher).xorKeyStreamGeneric)
+}
+
+func testBlock(t *testing.T, xor func(c *Cipher, dst, src []byte)) {
+	c1a, _ := NewCipher(golden[0].key)
+	c1b, _ := NewCipher(golden[1].key)
+	data1 := make([]byte, 1<<20)
+	for i := range data1 {
+		xor(c1a, data1[i:i+1], data1[i:i+1])
+		xor(c1b, data1[i:i+1], data1[i:i+1])
+	}
+
+	c2a, _ := NewCipher(golden[0].key)
+	c2b, _ := NewCipher(golden[1].key)
+	data2 := make([]byte, 1<<20)
+	xor(c2a, data2, data2)
+	xor(c2b, data2, data2)
+
+	if !bytes.Equal(data1, data2) {
+		t.Fatalf("bad block")
+	}
+}
+
+func benchmark(b *testing.B, size int64) {
+	buf := make([]byte, size)
+	c, err := NewCipher(golden[0].key)
+	if err != nil {
+		panic(err)
+	}
+	b.SetBytes(size)
+
+	for i := 0; i < b.N; i++ {
+		c.XORKeyStream(buf, buf)
+	}
+}
+
+func BenchmarkRC4_128(b *testing.B) {
+	benchmark(b, 128)
+}
+
+func BenchmarkRC4_1K(b *testing.B) {
+	benchmark(b, 1024)
+}
+
+func BenchmarkRC4_8K(b *testing.B) {
+	benchmark(b, 8096)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rsa/pkcs1v15.go b/third_party/gofrontend/libgo/go/crypto/rsa/pkcs1v15.go
new file mode 100644
index 0000000..59e8bb5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rsa/pkcs1v15.go
@@ -0,0 +1,292 @@
+// 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 rsa
+
+import (
+	"crypto"
+	"crypto/subtle"
+	"errors"
+	"io"
+	"math/big"
+)
+
+// This file implements encryption and decryption using PKCS#1 v1.5 padding.
+
+// EncryptPKCS1v15 encrypts the given message with RSA and the padding scheme from PKCS#1 v1.5.
+// The message must be no longer than the length of the public modulus minus 11 bytes.
+// WARNING: use of this function to encrypt plaintexts other than session keys
+// is dangerous. Use RSA OAEP in new protocols.
+func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) {
+	if err := checkPub(pub); err != nil {
+		return nil, err
+	}
+	k := (pub.N.BitLen() + 7) / 8
+	if len(msg) > k-11 {
+		err = ErrMessageTooLong
+		return
+	}
+
+	// EM = 0x00 || 0x02 || PS || 0x00 || M
+	em := make([]byte, k)
+	em[1] = 2
+	ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
+	err = nonZeroRandomBytes(ps, rand)
+	if err != nil {
+		return
+	}
+	em[len(em)-len(msg)-1] = 0
+	copy(mm, msg)
+
+	m := new(big.Int).SetBytes(em)
+	c := encrypt(new(big.Int), pub, m)
+
+	copyWithLeftPad(em, c.Bytes())
+	out = em
+	return
+}
+
+// DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
+// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
+func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) {
+	if err := checkPub(&priv.PublicKey); err != nil {
+		return nil, err
+	}
+	valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext)
+	if err != nil {
+		return
+	}
+	if valid == 0 {
+		return nil, ErrDecryption
+	}
+	out = out[index:]
+	return
+}
+
+// DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5.
+// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
+// It returns an error if the ciphertext is the wrong length or if the
+// ciphertext is greater than the public modulus. Otherwise, no error is
+// returned. If the padding is valid, the resulting plaintext message is copied
+// into key. Otherwise, key is unchanged. These alternatives occur in constant
+// time. It is intended that the user of this function generate a random
+// session key beforehand and continue the protocol with the resulting value.
+// This will remove any possibility that an attacker can learn any information
+// about the plaintext.
+// See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA
+// Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
+// (Crypto '98).
+func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
+	if err := checkPub(&priv.PublicKey); err != nil {
+		return err
+	}
+	k := (priv.N.BitLen() + 7) / 8
+	if k-(len(key)+3+8) < 0 {
+		return ErrDecryption
+	}
+
+	valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext)
+	if err != nil {
+		return
+	}
+
+	if len(em) != k {
+		// This should be impossible because decryptPKCS1v15 always
+		// returns the full slice.
+		return ErrDecryption
+	}
+
+	valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key)))
+	subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):])
+	return
+}
+
+// decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if
+// rand is not nil. It returns one or zero in valid that indicates whether the
+// plaintext was correctly structured. In either case, the plaintext is
+// returned in em so that it may be read independently of whether it was valid
+// in order to maintain constant memory access patterns. If the plaintext was
+// valid then index contains the index of the original message in em.
+func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) {
+	k := (priv.N.BitLen() + 7) / 8
+	if k < 11 {
+		err = ErrDecryption
+		return
+	}
+
+	c := new(big.Int).SetBytes(ciphertext)
+	m, err := decrypt(rand, priv, c)
+	if err != nil {
+		return
+	}
+
+	em = leftPad(m.Bytes(), k)
+	firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
+	secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
+
+	// The remainder of the plaintext must be a string of non-zero random
+	// octets, followed by a 0, followed by the message.
+	//   lookingForIndex: 1 iff we are still looking for the zero.
+	//   index: the offset of the first zero byte.
+	lookingForIndex := 1
+
+	for i := 2; i < len(em); i++ {
+		equals0 := subtle.ConstantTimeByteEq(em[i], 0)
+		index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
+		lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
+	}
+
+	// The PS padding must be at least 8 bytes long, and it starts two
+	// bytes into em.
+	validPS := subtle.ConstantTimeLessOrEq(2+8, index)
+
+	valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS
+	index = subtle.ConstantTimeSelect(valid, index+1, 0)
+	return valid, em, index, nil
+}
+
+// nonZeroRandomBytes fills the given slice with non-zero random octets.
+func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
+	_, err = io.ReadFull(rand, s)
+	if err != nil {
+		return
+	}
+
+	for i := 0; i < len(s); i++ {
+		for s[i] == 0 {
+			_, err = io.ReadFull(rand, s[i:i+1])
+			if err != nil {
+				return
+			}
+			// In tests, the PRNG may return all zeros so we do
+			// this to break the loop.
+			s[i] ^= 0x42
+		}
+	}
+
+	return
+}
+
+// These are ASN1 DER structures:
+//   DigestInfo ::= SEQUENCE {
+//     digestAlgorithm AlgorithmIdentifier,
+//     digest OCTET STRING
+//   }
+// For performance, we don't use the generic ASN1 encoder. Rather, we
+// precompute a prefix of the digest value that makes a valid ASN1 DER string
+// with the correct contents.
+var hashPrefixes = map[crypto.Hash][]byte{
+	crypto.MD5:       {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
+	crypto.SHA1:      {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
+	crypto.SHA224:    {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
+	crypto.SHA256:    {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
+	crypto.SHA384:    {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
+	crypto.SHA512:    {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
+	crypto.MD5SHA1:   {}, // A special TLS case which doesn't use an ASN1 prefix.
+	crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
+}
+
+// SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5.
+// Note that hashed must be the result of hashing the input message using the
+// given hash function. If hash is zero, hashed is signed directly. This isn't
+// advisable except for interoperability.
+func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error) {
+	hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
+	if err != nil {
+		return
+	}
+
+	tLen := len(prefix) + hashLen
+	k := (priv.N.BitLen() + 7) / 8
+	if k < tLen+11 {
+		return nil, ErrMessageTooLong
+	}
+
+	// EM = 0x00 || 0x01 || PS || 0x00 || T
+	em := make([]byte, k)
+	em[1] = 1
+	for i := 2; i < k-tLen-1; i++ {
+		em[i] = 0xff
+	}
+	copy(em[k-tLen:k-hashLen], prefix)
+	copy(em[k-hashLen:k], hashed)
+
+	m := new(big.Int).SetBytes(em)
+	c, err := decrypt(rand, priv, m)
+	if err != nil {
+		return
+	}
+
+	copyWithLeftPad(em, c.Bytes())
+	s = em
+	return
+}
+
+// VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
+// hashed is the result of hashing the input message using the given hash
+// function and sig is the signature. A valid signature is indicated by
+// returning a nil error. If hash is zero then hashed is used directly. This
+// isn't advisable except for interoperability.
+func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error) {
+	hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
+	if err != nil {
+		return
+	}
+
+	tLen := len(prefix) + hashLen
+	k := (pub.N.BitLen() + 7) / 8
+	if k < tLen+11 {
+		err = ErrVerification
+		return
+	}
+
+	c := new(big.Int).SetBytes(sig)
+	m := encrypt(new(big.Int), pub, c)
+	em := leftPad(m.Bytes(), k)
+	// EM = 0x00 || 0x01 || PS || 0x00 || T
+
+	ok := subtle.ConstantTimeByteEq(em[0], 0)
+	ok &= subtle.ConstantTimeByteEq(em[1], 1)
+	ok &= subtle.ConstantTimeCompare(em[k-hashLen:k], hashed)
+	ok &= subtle.ConstantTimeCompare(em[k-tLen:k-hashLen], prefix)
+	ok &= subtle.ConstantTimeByteEq(em[k-tLen-1], 0)
+
+	for i := 2; i < k-tLen-1; i++ {
+		ok &= subtle.ConstantTimeByteEq(em[i], 0xff)
+	}
+
+	if ok != 1 {
+		return ErrVerification
+	}
+
+	return nil
+}
+
+func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
+	// Special case: crypto.Hash(0) is used to indicate that the data is
+	// signed directly.
+	if hash == 0 {
+		return inLen, nil, nil
+	}
+
+	hashLen = hash.Size()
+	if inLen != hashLen {
+		return 0, nil, errors.New("crypto/rsa: input must be hashed message")
+	}
+	prefix, ok := hashPrefixes[hash]
+	if !ok {
+		return 0, nil, errors.New("crypto/rsa: unsupported hash function")
+	}
+	return
+}
+
+// copyWithLeftPad copies src to the end of dest, padding with zero bytes as
+// needed.
+func copyWithLeftPad(dest, src []byte) {
+	numPaddingBytes := len(dest) - len(src)
+	for i := 0; i < numPaddingBytes; i++ {
+		dest[i] = 0
+	}
+	copy(dest[numPaddingBytes:], src)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rsa/pkcs1v15_test.go b/third_party/gofrontend/libgo/go/crypto/rsa/pkcs1v15_test.go
new file mode 100644
index 0000000..2dc5dbc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rsa/pkcs1v15_test.go
@@ -0,0 +1,271 @@
+// 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 rsa
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/rand"
+	"crypto/sha1"
+	"encoding/base64"
+	"encoding/hex"
+	"io"
+	"math/big"
+	"testing"
+	"testing/quick"
+)
+
+func decodeBase64(in string) []byte {
+	out := make([]byte, base64.StdEncoding.DecodedLen(len(in)))
+	n, err := base64.StdEncoding.Decode(out, []byte(in))
+	if err != nil {
+		return nil
+	}
+	return out[0:n]
+}
+
+type DecryptPKCS1v15Test struct {
+	in, out string
+}
+
+// These test vectors were generated with `openssl rsautl -pkcs -encrypt`
+var decryptPKCS1v15Tests = []DecryptPKCS1v15Test{
+	{
+		"gIcUIoVkD6ATMBk/u/nlCZCCWRKdkfjCgFdo35VpRXLduiKXhNz1XupLLzTXAybEq15juc+EgY5o0DHv/nt3yg==",
+		"x",
+	},
+	{
+		"Y7TOCSqofGhkRb+jaVRLzK8xw2cSo1IVES19utzv6hwvx+M8kFsoWQm5DzBeJCZTCVDPkTpavUuEbgp8hnUGDw==",
+		"testing.",
+	},
+	{
+		"arReP9DJtEVyV2Dg3dDp4c/PSk1O6lxkoJ8HcFupoRorBZG+7+1fDAwT1olNddFnQMjmkb8vxwmNMoTAT/BFjQ==",
+		"testing.\n",
+	},
+	{
+		"WtaBXIoGC54+vH0NH0CHHE+dRDOsMc/6BrfFu2lEqcKL9+uDuWaf+Xj9mrbQCjjZcpQuX733zyok/jsnqe/Ftw==",
+		"01234567890123456789012345678901234567890123456789012",
+	},
+}
+
+func TestDecryptPKCS1v15(t *testing.T) {
+	for i, test := range decryptPKCS1v15Tests {
+		out, err := DecryptPKCS1v15(nil, rsaPrivateKey, decodeBase64(test.in))
+		if err != nil {
+			t.Errorf("#%d error decrypting", i)
+		}
+		want := []byte(test.out)
+		if !bytes.Equal(out, want) {
+			t.Errorf("#%d got:%#v want:%#v", i, out, want)
+		}
+	}
+}
+
+func TestEncryptPKCS1v15(t *testing.T) {
+	random := rand.Reader
+	k := (rsaPrivateKey.N.BitLen() + 7) / 8
+
+	tryEncryptDecrypt := func(in []byte, blind bool) bool {
+		if len(in) > k-11 {
+			in = in[0 : k-11]
+		}
+
+		ciphertext, err := EncryptPKCS1v15(random, &rsaPrivateKey.PublicKey, in)
+		if err != nil {
+			t.Errorf("error encrypting: %s", err)
+			return false
+		}
+
+		var rand io.Reader
+		if !blind {
+			rand = nil
+		} else {
+			rand = random
+		}
+		plaintext, err := DecryptPKCS1v15(rand, rsaPrivateKey, ciphertext)
+		if err != nil {
+			t.Errorf("error decrypting: %s", err)
+			return false
+		}
+
+		if !bytes.Equal(plaintext, in) {
+			t.Errorf("output mismatch: %#v %#v", plaintext, in)
+			return false
+		}
+		return true
+	}
+
+	config := new(quick.Config)
+	if testing.Short() {
+		config.MaxCount = 10
+	}
+	quick.Check(tryEncryptDecrypt, config)
+}
+
+// These test vectors were generated with `openssl rsautl -pkcs -encrypt`
+var decryptPKCS1v15SessionKeyTests = []DecryptPKCS1v15Test{
+	{
+		"e6ukkae6Gykq0fKzYwULpZehX+UPXYzMoB5mHQUDEiclRbOTqas4Y0E6nwns1BBpdvEJcilhl5zsox/6DtGsYg==",
+		"1234",
+	},
+	{
+		"Dtis4uk/q/LQGGqGk97P59K03hkCIVFMEFZRgVWOAAhxgYpCRG0MX2adptt92l67IqMki6iVQyyt0TtX3IdtEw==",
+		"FAIL",
+	},
+	{
+		"LIyFyCYCptPxrvTxpol8F3M7ZivlMsf53zs0vHRAv+rDIh2YsHS69ePMoPMe3TkOMZ3NupiL3takPxIs1sK+dw==",
+		"abcd",
+	},
+	{
+		"bafnobel46bKy76JzqU/RIVOH0uAYvzUtauKmIidKgM0sMlvobYVAVQPeUQ/oTGjbIZ1v/6Gyi5AO4DtHruGdw==",
+		"FAIL",
+	},
+}
+
+func TestEncryptPKCS1v15SessionKey(t *testing.T) {
+	for i, test := range decryptPKCS1v15SessionKeyTests {
+		key := []byte("FAIL")
+		err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, decodeBase64(test.in), key)
+		if err != nil {
+			t.Errorf("#%d error decrypting", i)
+		}
+		want := []byte(test.out)
+		if !bytes.Equal(key, want) {
+			t.Errorf("#%d got:%#v want:%#v", i, key, want)
+		}
+	}
+}
+
+func TestNonZeroRandomBytes(t *testing.T) {
+	random := rand.Reader
+
+	b := make([]byte, 512)
+	err := nonZeroRandomBytes(b, random)
+	if err != nil {
+		t.Errorf("returned error: %s", err)
+	}
+	for _, b := range b {
+		if b == 0 {
+			t.Errorf("Zero octet found")
+			return
+		}
+	}
+}
+
+type signPKCS1v15Test struct {
+	in, out string
+}
+
+// These vectors have been tested with
+//   `openssl rsautl -verify -inkey pk -in signature | hexdump -C`
+var signPKCS1v15Tests = []signPKCS1v15Test{
+	{"Test.\n", "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e336ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"},
+}
+
+func TestSignPKCS1v15(t *testing.T) {
+	for i, test := range signPKCS1v15Tests {
+		h := sha1.New()
+		h.Write([]byte(test.in))
+		digest := h.Sum(nil)
+
+		s, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.SHA1, digest)
+		if err != nil {
+			t.Errorf("#%d %s", i, err)
+		}
+
+		expected, _ := hex.DecodeString(test.out)
+		if !bytes.Equal(s, expected) {
+			t.Errorf("#%d got: %x want: %x", i, s, expected)
+		}
+	}
+}
+
+func TestVerifyPKCS1v15(t *testing.T) {
+	for i, test := range signPKCS1v15Tests {
+		h := sha1.New()
+		h.Write([]byte(test.in))
+		digest := h.Sum(nil)
+
+		sig, _ := hex.DecodeString(test.out)
+
+		err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA1, digest, sig)
+		if err != nil {
+			t.Errorf("#%d %s", i, err)
+		}
+	}
+}
+
+func TestOverlongMessagePKCS1v15(t *testing.T) {
+	ciphertext := decodeBase64("fjOVdirUzFoLlukv80dBllMLjXythIf22feqPrNo0YoIjzyzyoMFiLjAc/Y4krkeZ11XFThIrEvw\nkRiZcCq5ng==")
+	_, err := DecryptPKCS1v15(nil, rsaPrivateKey, ciphertext)
+	if err == nil {
+		t.Error("RSA decrypted a message that was too long.")
+	}
+}
+
+func TestUnpaddedSignature(t *testing.T) {
+	msg := []byte("Thu Dec 19 18:06:16 EST 2013\n")
+	// This base64 value was generated with:
+	// % echo Thu Dec 19 18:06:16 EST 2013 > /tmp/msg
+	// % openssl rsautl -sign -inkey key -out /tmp/sig -in /tmp/msg
+	//
+	// Where "key" contains the RSA private key given at the bottom of this
+	// file.
+	expectedSig := decodeBase64("pX4DR8azytjdQ1rtUiC040FjkepuQut5q2ZFX1pTjBrOVKNjgsCDyiJDGZTCNoh9qpXYbhl7iEym30BWWwuiZg==")
+
+	sig, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.Hash(0), msg)
+	if err != nil {
+		t.Fatalf("SignPKCS1v15 failed: %s", err)
+	}
+	if !bytes.Equal(sig, expectedSig) {
+		t.Fatalf("signature is not expected value: got %x, want %x", sig, expectedSig)
+	}
+	if err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.Hash(0), msg, sig); err != nil {
+		t.Fatalf("signature failed to verify: %s", err)
+	}
+}
+
+func TestShortSessionKey(t *testing.T) {
+	// This tests that attempting to decrypt a session key where the
+	// ciphertext is too small doesn't run outside the array bounds.
+	ciphertext, err := EncryptPKCS1v15(rand.Reader, &rsaPrivateKey.PublicKey, []byte{1})
+	if err != nil {
+		t.Fatalf("Failed to encrypt short message: %s", err)
+	}
+
+	var key [32]byte
+	if err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, ciphertext, key[:]); err != nil {
+		t.Fatalf("Failed to decrypt short message: %s", err)
+	}
+
+	for _, v := range key {
+		if v != 0 {
+			t.Fatal("key was modified when ciphertext was invalid")
+		}
+	}
+}
+
+// In order to generate new test vectors you'll need the PEM form of this key:
+// -----BEGIN RSA PRIVATE KEY-----
+// MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
+// fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
+// /ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
+// RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
+// EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
+// IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
+// tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
+// -----END RSA PRIVATE KEY-----
+
+var rsaPrivateKey = &PrivateKey{
+	PublicKey: PublicKey{
+		N: fromBase10("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
+		E: 65537,
+	},
+	D: fromBase10("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
+	Primes: []*big.Int{
+		fromBase10("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
+		fromBase10("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+	},
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rsa/pss.go b/third_party/gofrontend/libgo/go/crypto/rsa/pss.go
new file mode 100644
index 0000000..18eafbc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rsa/pss.go
@@ -0,0 +1,282 @@
+// Copyright 2013 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 rsa
+
+// This file implements the PSS signature scheme [1].
+//
+// [1] http://www.rsa.com/rsalabs/pkcs/files/h11300-wp-pkcs-1v2-2-rsa-cryptography-standard.pdf
+
+import (
+	"bytes"
+	"crypto"
+	"errors"
+	"hash"
+	"io"
+	"math/big"
+)
+
+func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) {
+	// See [1], section 9.1.1
+	hLen := hash.Size()
+	sLen := len(salt)
+	emLen := (emBits + 7) / 8
+
+	// 1.  If the length of M is greater than the input limitation for the
+	//     hash function (2^61 - 1 octets for SHA-1), output "message too
+	//     long" and stop.
+	//
+	// 2.  Let mHash = Hash(M), an octet string of length hLen.
+
+	if len(mHash) != hLen {
+		return nil, errors.New("crypto/rsa: input must be hashed message")
+	}
+
+	// 3.  If emLen < hLen + sLen + 2, output "encoding error" and stop.
+
+	if emLen < hLen+sLen+2 {
+		return nil, errors.New("crypto/rsa: encoding error")
+	}
+
+	em := make([]byte, emLen)
+	db := em[:emLen-sLen-hLen-2+1+sLen]
+	h := em[emLen-sLen-hLen-2+1+sLen : emLen-1]
+
+	// 4.  Generate a random octet string salt of length sLen; if sLen = 0,
+	//     then salt is the empty string.
+	//
+	// 5.  Let
+	//       M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt;
+	//
+	//     M' is an octet string of length 8 + hLen + sLen with eight
+	//     initial zero octets.
+	//
+	// 6.  Let H = Hash(M'), an octet string of length hLen.
+
+	var prefix [8]byte
+
+	hash.Write(prefix[:])
+	hash.Write(mHash)
+	hash.Write(salt)
+
+	h = hash.Sum(h[:0])
+	hash.Reset()
+
+	// 7.  Generate an octet string PS consisting of emLen - sLen - hLen - 2
+	//     zero octets.  The length of PS may be 0.
+	//
+	// 8.  Let DB = PS || 0x01 || salt; DB is an octet string of length
+	//     emLen - hLen - 1.
+
+	db[emLen-sLen-hLen-2] = 0x01
+	copy(db[emLen-sLen-hLen-1:], salt)
+
+	// 9.  Let dbMask = MGF(H, emLen - hLen - 1).
+	//
+	// 10. Let maskedDB = DB \xor dbMask.
+
+	mgf1XOR(db, hash, h)
+
+	// 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in
+	//     maskedDB to zero.
+
+	db[0] &= (0xFF >> uint(8*emLen-emBits))
+
+	// 12. Let EM = maskedDB || H || 0xbc.
+	em[emLen-1] = 0xBC
+
+	// 13. Output EM.
+	return em, nil
+}
+
+func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
+	// 1.  If the length of M is greater than the input limitation for the
+	//     hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
+	//     and stop.
+	//
+	// 2.  Let mHash = Hash(M), an octet string of length hLen.
+	hLen := hash.Size()
+	if hLen != len(mHash) {
+		return ErrVerification
+	}
+
+	// 3.  If emLen < hLen + sLen + 2, output "inconsistent" and stop.
+	emLen := (emBits + 7) / 8
+	if emLen < hLen+sLen+2 {
+		return ErrVerification
+	}
+
+	// 4.  If the rightmost octet of EM does not have hexadecimal value
+	//     0xbc, output "inconsistent" and stop.
+	if em[len(em)-1] != 0xBC {
+		return ErrVerification
+	}
+
+	// 5.  Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
+	//     let H be the next hLen octets.
+	db := em[:emLen-hLen-1]
+	h := em[emLen-hLen-1 : len(em)-1]
+
+	// 6.  If the leftmost 8 * emLen - emBits bits of the leftmost octet in
+	//     maskedDB are not all equal to zero, output "inconsistent" and
+	//     stop.
+	if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 {
+		return ErrVerification
+	}
+
+	// 7.  Let dbMask = MGF(H, emLen - hLen - 1).
+	//
+	// 8.  Let DB = maskedDB \xor dbMask.
+	mgf1XOR(db, hash, h)
+
+	// 9.  Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
+	//     to zero.
+	db[0] &= (0xFF >> uint(8*emLen-emBits))
+
+	if sLen == PSSSaltLengthAuto {
+	FindSaltLength:
+		for sLen = emLen - (hLen + 2); sLen >= 0; sLen-- {
+			switch db[emLen-hLen-sLen-2] {
+			case 1:
+				break FindSaltLength
+			case 0:
+				continue
+			default:
+				return ErrVerification
+			}
+		}
+		if sLen < 0 {
+			return ErrVerification
+		}
+	} else {
+		// 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
+		//     or if the octet at position emLen - hLen - sLen - 1 (the leftmost
+		//     position is "position 1") does not have hexadecimal value 0x01,
+		//     output "inconsistent" and stop.
+		for _, e := range db[:emLen-hLen-sLen-2] {
+			if e != 0x00 {
+				return ErrVerification
+			}
+		}
+		if db[emLen-hLen-sLen-2] != 0x01 {
+			return ErrVerification
+		}
+	}
+
+	// 11.  Let salt be the last sLen octets of DB.
+	salt := db[len(db)-sLen:]
+
+	// 12.  Let
+	//          M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ;
+	//     M' is an octet string of length 8 + hLen + sLen with eight
+	//     initial zero octets.
+	//
+	// 13. Let H' = Hash(M'), an octet string of length hLen.
+	var prefix [8]byte
+	hash.Write(prefix[:])
+	hash.Write(mHash)
+	hash.Write(salt)
+
+	h0 := hash.Sum(nil)
+
+	// 14. If H = H', output "consistent." Otherwise, output "inconsistent."
+	if !bytes.Equal(h0, h) {
+		return ErrVerification
+	}
+	return nil
+}
+
+// signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt.
+// Note that hashed must be the result of hashing the input message using the
+// given hash function. salt is a random sequence of bytes whose length will be
+// later used to verify the signature.
+func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) {
+	nBits := priv.N.BitLen()
+	em, err := emsaPSSEncode(hashed, nBits-1, salt, hash.New())
+	if err != nil {
+		return
+	}
+	m := new(big.Int).SetBytes(em)
+	c, err := decrypt(rand, priv, m)
+	if err != nil {
+		return
+	}
+	s = make([]byte, (nBits+7)/8)
+	copyWithLeftPad(s, c.Bytes())
+	return
+}
+
+const (
+	// PSSSaltLengthAuto causes the salt in a PSS signature to be as large
+	// as possible when signing, and to be auto-detected when verifying.
+	PSSSaltLengthAuto = 0
+	// PSSSaltLengthEqualsHash causes the salt length to equal the length
+	// of the hash used in the signature.
+	PSSSaltLengthEqualsHash = -1
+)
+
+// PSSOptions contains options for creating and verifying PSS signatures.
+type PSSOptions struct {
+	// SaltLength controls the length of the salt used in the PSS
+	// signature. It can either be a number of bytes, or one of the special
+	// PSSSaltLength constants.
+	SaltLength int
+}
+
+func (opts *PSSOptions) saltLength() int {
+	if opts == nil {
+		return PSSSaltLengthAuto
+	}
+	return opts.SaltLength
+}
+
+// SignPSS calculates the signature of hashed using RSASSA-PSS [1].
+// Note that hashed must be the result of hashing the input message using the
+// given hash function. The opts argument may be nil, in which case sensible
+// defaults are used.
+func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) (s []byte, err error) {
+	saltLength := opts.saltLength()
+	switch saltLength {
+	case PSSSaltLengthAuto:
+		saltLength = (priv.N.BitLen()+7)/8 - 2 - hash.Size()
+	case PSSSaltLengthEqualsHash:
+		saltLength = hash.Size()
+	}
+
+	salt := make([]byte, saltLength)
+	if _, err = io.ReadFull(rand, salt); err != nil {
+		return
+	}
+	return signPSSWithSalt(rand, priv, hash, hashed, salt)
+}
+
+// VerifyPSS verifies a PSS signature.
+// hashed is the result of hashing the input message using the given hash
+// function and sig is the signature. A valid signature is indicated by
+// returning a nil error. The opts argument may be nil, in which case sensible
+// defaults are used.
+func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error {
+	return verifyPSS(pub, hash, hashed, sig, opts.saltLength())
+}
+
+// verifyPSS verifies a PSS signature with the given salt length.
+func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error {
+	nBits := pub.N.BitLen()
+	if len(sig) != (nBits+7)/8 {
+		return ErrVerification
+	}
+	s := new(big.Int).SetBytes(sig)
+	m := encrypt(new(big.Int), pub, s)
+	emBits := nBits - 1
+	emLen := (emBits + 7) / 8
+	if emLen < len(m.Bytes()) {
+		return ErrVerification
+	}
+	em := make([]byte, emLen)
+	copyWithLeftPad(em, m.Bytes())
+	if saltLen == PSSSaltLengthEqualsHash {
+		saltLen = hash.Size()
+	}
+	return emsaPSSVerify(hashed, em, emBits, saltLen, hash.New())
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rsa/pss_test.go b/third_party/gofrontend/libgo/go/crypto/rsa/pss_test.go
new file mode 100644
index 0000000..32e6fc3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rsa/pss_test.go
@@ -0,0 +1,249 @@
+// Copyright 2013 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 rsa
+
+import (
+	"bufio"
+	"bytes"
+	"compress/bzip2"
+	"crypto"
+	_ "crypto/md5"
+	"crypto/rand"
+	"crypto/sha1"
+	_ "crypto/sha256"
+	"encoding/hex"
+	"math/big"
+	"os"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func TestEMSAPSS(t *testing.T) {
+	// Test vector in file pss-int.txt from: ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+	msg := []byte{
+		0x85, 0x9e, 0xef, 0x2f, 0xd7, 0x8a, 0xca, 0x00, 0x30, 0x8b,
+		0xdc, 0x47, 0x11, 0x93, 0xbf, 0x55, 0xbf, 0x9d, 0x78, 0xdb,
+		0x8f, 0x8a, 0x67, 0x2b, 0x48, 0x46, 0x34, 0xf3, 0xc9, 0xc2,
+		0x6e, 0x64, 0x78, 0xae, 0x10, 0x26, 0x0f, 0xe0, 0xdd, 0x8c,
+		0x08, 0x2e, 0x53, 0xa5, 0x29, 0x3a, 0xf2, 0x17, 0x3c, 0xd5,
+		0x0c, 0x6d, 0x5d, 0x35, 0x4f, 0xeb, 0xf7, 0x8b, 0x26, 0x02,
+		0x1c, 0x25, 0xc0, 0x27, 0x12, 0xe7, 0x8c, 0xd4, 0x69, 0x4c,
+		0x9f, 0x46, 0x97, 0x77, 0xe4, 0x51, 0xe7, 0xf8, 0xe9, 0xe0,
+		0x4c, 0xd3, 0x73, 0x9c, 0x6b, 0xbf, 0xed, 0xae, 0x48, 0x7f,
+		0xb5, 0x56, 0x44, 0xe9, 0xca, 0x74, 0xff, 0x77, 0xa5, 0x3c,
+		0xb7, 0x29, 0x80, 0x2f, 0x6e, 0xd4, 0xa5, 0xff, 0xa8, 0xba,
+		0x15, 0x98, 0x90, 0xfc,
+	}
+	salt := []byte{
+		0xe3, 0xb5, 0xd5, 0xd0, 0x02, 0xc1, 0xbc, 0xe5, 0x0c, 0x2b,
+		0x65, 0xef, 0x88, 0xa1, 0x88, 0xd8, 0x3b, 0xce, 0x7e, 0x61,
+	}
+	expected := []byte{
+		0x66, 0xe4, 0x67, 0x2e, 0x83, 0x6a, 0xd1, 0x21, 0xba, 0x24,
+		0x4b, 0xed, 0x65, 0x76, 0xb8, 0x67, 0xd9, 0xa4, 0x47, 0xc2,
+		0x8a, 0x6e, 0x66, 0xa5, 0xb8, 0x7d, 0xee, 0x7f, 0xbc, 0x7e,
+		0x65, 0xaf, 0x50, 0x57, 0xf8, 0x6f, 0xae, 0x89, 0x84, 0xd9,
+		0xba, 0x7f, 0x96, 0x9a, 0xd6, 0xfe, 0x02, 0xa4, 0xd7, 0x5f,
+		0x74, 0x45, 0xfe, 0xfd, 0xd8, 0x5b, 0x6d, 0x3a, 0x47, 0x7c,
+		0x28, 0xd2, 0x4b, 0xa1, 0xe3, 0x75, 0x6f, 0x79, 0x2d, 0xd1,
+		0xdc, 0xe8, 0xca, 0x94, 0x44, 0x0e, 0xcb, 0x52, 0x79, 0xec,
+		0xd3, 0x18, 0x3a, 0x31, 0x1f, 0xc8, 0x96, 0xda, 0x1c, 0xb3,
+		0x93, 0x11, 0xaf, 0x37, 0xea, 0x4a, 0x75, 0xe2, 0x4b, 0xdb,
+		0xfd, 0x5c, 0x1d, 0xa0, 0xde, 0x7c, 0xec, 0xdf, 0x1a, 0x89,
+		0x6f, 0x9d, 0x8b, 0xc8, 0x16, 0xd9, 0x7c, 0xd7, 0xa2, 0xc4,
+		0x3b, 0xad, 0x54, 0x6f, 0xbe, 0x8c, 0xfe, 0xbc,
+	}
+
+	hash := sha1.New()
+	hash.Write(msg)
+	hashed := hash.Sum(nil)
+
+	encoded, err := emsaPSSEncode(hashed, 1023, salt, sha1.New())
+	if err != nil {
+		t.Errorf("Error from emsaPSSEncode: %s\n", err)
+	}
+	if !bytes.Equal(encoded, expected) {
+		t.Errorf("Bad encoding. got %x, want %x", encoded, expected)
+	}
+
+	if err = emsaPSSVerify(hashed, encoded, 1023, len(salt), sha1.New()); err != nil {
+		t.Errorf("Bad verification: %s", err)
+	}
+}
+
+// TestPSSGolden tests all the test vectors in pss-vect.txt from
+// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+func TestPSSGolden(t *testing.T) {
+	inFile, err := os.Open("testdata/pss-vect.txt.bz2")
+	if err != nil {
+		t.Fatalf("Failed to open input file: %s", err)
+	}
+	defer inFile.Close()
+
+	// The pss-vect.txt file contains RSA keys and then a series of
+	// signatures. A goroutine is used to preprocess the input by merging
+	// lines, removing spaces in hex values and identifying the start of
+	// new keys and signature blocks.
+	const newKeyMarker = "START NEW KEY"
+	const newSignatureMarker = "START NEW SIGNATURE"
+
+	values := make(chan string)
+
+	go func() {
+		defer close(values)
+		scanner := bufio.NewScanner(bzip2.NewReader(inFile))
+		var partialValue string
+		lastWasValue := true
+
+		for scanner.Scan() {
+			line := scanner.Text()
+			switch {
+			case len(line) == 0:
+				if len(partialValue) > 0 {
+					values <- strings.Replace(partialValue, " ", "", -1)
+					partialValue = ""
+					lastWasValue = true
+				}
+				continue
+			case strings.HasPrefix(line, "# ======") && lastWasValue:
+				values <- newKeyMarker
+				lastWasValue = false
+			case strings.HasPrefix(line, "# ------") && lastWasValue:
+				values <- newSignatureMarker
+				lastWasValue = false
+			case strings.HasPrefix(line, "#"):
+				continue
+			default:
+				partialValue += line
+			}
+		}
+		if err := scanner.Err(); err != nil {
+			panic(err)
+		}
+	}()
+
+	var key *PublicKey
+	var hashed []byte
+	hash := crypto.SHA1
+	h := hash.New()
+	opts := &PSSOptions{
+		SaltLength: PSSSaltLengthEqualsHash,
+	}
+
+	for marker := range values {
+		switch marker {
+		case newKeyMarker:
+			key = new(PublicKey)
+			nHex, ok := <-values
+			if !ok {
+				continue
+			}
+			key.N = bigFromHex(nHex)
+			key.E = intFromHex(<-values)
+			// We don't care for d, p, q, dP, dQ or qInv.
+			for i := 0; i < 6; i++ {
+				<-values
+			}
+		case newSignatureMarker:
+			msg := fromHex(<-values)
+			<-values // skip salt
+			sig := fromHex(<-values)
+
+			h.Reset()
+			h.Write(msg)
+			hashed = h.Sum(hashed[:0])
+
+			if err := VerifyPSS(key, hash, hashed, sig, opts); err != nil {
+				t.Error(err)
+			}
+		default:
+			t.Fatalf("unknown marker: " + marker)
+		}
+	}
+}
+
+// TestPSSOpenSSL ensures that we can verify a PSS signature from OpenSSL with
+// the default options. OpenSSL sets the salt length to be maximal.
+func TestPSSOpenSSL(t *testing.T) {
+	hash := crypto.SHA256
+	h := hash.New()
+	h.Write([]byte("testing"))
+	hashed := h.Sum(nil)
+
+	// Generated with `echo -n testing | openssl dgst -sign key.pem -sigopt rsa_padding_mode:pss -sha256 > sig`
+	sig := []byte{
+		0x95, 0x59, 0x6f, 0xd3, 0x10, 0xa2, 0xe7, 0xa2, 0x92, 0x9d,
+		0x4a, 0x07, 0x2e, 0x2b, 0x27, 0xcc, 0x06, 0xc2, 0x87, 0x2c,
+		0x52, 0xf0, 0x4a, 0xcc, 0x05, 0x94, 0xf2, 0xc3, 0x2e, 0x20,
+		0xd7, 0x3e, 0x66, 0x62, 0xb5, 0x95, 0x2b, 0xa3, 0x93, 0x9a,
+		0x66, 0x64, 0x25, 0xe0, 0x74, 0x66, 0x8c, 0x3e, 0x92, 0xeb,
+		0xc6, 0xe6, 0xc0, 0x44, 0xf3, 0xb4, 0xb4, 0x2e, 0x8c, 0x66,
+		0x0a, 0x37, 0x9c, 0x69,
+	}
+
+	if err := VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, nil); err != nil {
+		t.Error(err)
+	}
+}
+
+func TestPSSSigning(t *testing.T) {
+	var saltLengthCombinations = []struct {
+		signSaltLength, verifySaltLength int
+		good                             bool
+	}{
+		{PSSSaltLengthAuto, PSSSaltLengthAuto, true},
+		{PSSSaltLengthEqualsHash, PSSSaltLengthAuto, true},
+		{PSSSaltLengthEqualsHash, PSSSaltLengthEqualsHash, true},
+		{PSSSaltLengthEqualsHash, 8, false},
+		{PSSSaltLengthAuto, PSSSaltLengthEqualsHash, false},
+		{8, 8, true},
+	}
+
+	hash := crypto.MD5
+	h := hash.New()
+	h.Write([]byte("testing"))
+	hashed := h.Sum(nil)
+	var opts PSSOptions
+
+	for i, test := range saltLengthCombinations {
+		opts.SaltLength = test.signSaltLength
+		sig, err := SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, &opts)
+		if err != nil {
+			t.Errorf("#%d: error while signing: %s", i, err)
+			continue
+		}
+
+		opts.SaltLength = test.verifySaltLength
+		err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts)
+		if (err == nil) != test.good {
+			t.Errorf("#%d: bad result, wanted: %t, got: %s", i, test.good, err)
+		}
+	}
+}
+
+func bigFromHex(hex string) *big.Int {
+	n, ok := new(big.Int).SetString(hex, 16)
+	if !ok {
+		panic("bad hex: " + hex)
+	}
+	return n
+}
+
+func intFromHex(hex string) int {
+	i, err := strconv.ParseInt(hex, 16, 32)
+	if err != nil {
+		panic(err)
+	}
+	return int(i)
+}
+
+func fromHex(hexStr string) []byte {
+	s, err := hex.DecodeString(hexStr)
+	if err != nil {
+		panic(err)
+	}
+	return s
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rsa/rsa.go b/third_party/gofrontend/libgo/go/crypto/rsa/rsa.go
new file mode 100644
index 0000000..bce6ba4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rsa/rsa.go
@@ -0,0 +1,538 @@
+// 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 rsa implements RSA encryption as specified in PKCS#1.
+package rsa
+
+import (
+	"crypto/rand"
+	"crypto/subtle"
+	"errors"
+	"hash"
+	"io"
+	"math/big"
+)
+
+var bigZero = big.NewInt(0)
+var bigOne = big.NewInt(1)
+
+// A PublicKey represents the public part of an RSA key.
+type PublicKey struct {
+	N *big.Int // modulus
+	E int      // public exponent
+}
+
+var (
+	errPublicModulus       = errors.New("crypto/rsa: missing public modulus")
+	errPublicExponentSmall = errors.New("crypto/rsa: public exponent too small")
+	errPublicExponentLarge = errors.New("crypto/rsa: public exponent too large")
+)
+
+// checkPub sanity checks the public key before we use it.
+// We require pub.E to fit into a 32-bit integer so that we
+// do not have different behavior depending on whether
+// int is 32 or 64 bits. See also
+// http://www.imperialviolet.org/2012/03/16/rsae.html.
+func checkPub(pub *PublicKey) error {
+	if pub.N == nil {
+		return errPublicModulus
+	}
+	if pub.E < 2 {
+		return errPublicExponentSmall
+	}
+	if pub.E > 1<<31-1 {
+		return errPublicExponentLarge
+	}
+	return nil
+}
+
+// A PrivateKey represents an RSA key
+type PrivateKey struct {
+	PublicKey            // public part.
+	D         *big.Int   // private exponent
+	Primes    []*big.Int // prime factors of N, has >= 2 elements.
+
+	// Precomputed contains precomputed values that speed up private
+	// operations, if available.
+	Precomputed PrecomputedValues
+}
+
+type PrecomputedValues struct {
+	Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
+	Qinv   *big.Int // Q^-1 mod P
+
+	// CRTValues is used for the 3rd and subsequent primes. Due to a
+	// historical accident, the CRT for the first two primes is handled
+	// differently in PKCS#1 and interoperability is sufficiently
+	// important that we mirror this.
+	CRTValues []CRTValue
+}
+
+// CRTValue contains the precomputed chinese remainder theorem values.
+type CRTValue struct {
+	Exp   *big.Int // D mod (prime-1).
+	Coeff *big.Int // R·Coeff ≡ 1 mod Prime.
+	R     *big.Int // product of primes prior to this (inc p and q).
+}
+
+// Validate performs basic sanity checks on the key.
+// It returns nil if the key is valid, or else an error describing a problem.
+func (priv *PrivateKey) Validate() error {
+	if err := checkPub(&priv.PublicKey); err != nil {
+		return err
+	}
+
+	// Check that the prime factors are actually prime. Note that this is
+	// just a sanity check. Since the random witnesses chosen by
+	// ProbablyPrime are deterministic, given the candidate number, it's
+	// easy for an attack to generate composites that pass this test.
+	for _, prime := range priv.Primes {
+		if !prime.ProbablyPrime(20) {
+			return errors.New("crypto/rsa: prime factor is composite")
+		}
+	}
+
+	// Check that Πprimes == n.
+	modulus := new(big.Int).Set(bigOne)
+	for _, prime := range priv.Primes {
+		modulus.Mul(modulus, prime)
+	}
+	if modulus.Cmp(priv.N) != 0 {
+		return errors.New("crypto/rsa: invalid modulus")
+	}
+
+	// Check that de ≡ 1 mod p-1, for each prime.
+	// This implies that e is coprime to each p-1 as e has a multiplicative
+	// inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) =
+	// exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1
+	// mod p. Thus a^de ≡ a mod n for all a coprime to n, as required.
+	congruence := new(big.Int)
+	de := new(big.Int).SetInt64(int64(priv.E))
+	de.Mul(de, priv.D)
+	for _, prime := range priv.Primes {
+		pminus1 := new(big.Int).Sub(prime, bigOne)
+		congruence.Mod(de, pminus1)
+		if congruence.Cmp(bigOne) != 0 {
+			return errors.New("crypto/rsa: invalid exponents")
+		}
+	}
+	return nil
+}
+
+// GenerateKey generates an RSA keypair of the given bit size using the
+// random source random (for example, crypto/rand.Reader).
+func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error) {
+	return GenerateMultiPrimeKey(random, 2, bits)
+}
+
+// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit
+// size and the given random source, as suggested in [1]. Although the public
+// keys are compatible (actually, indistinguishable) from the 2-prime case,
+// the private keys are not. Thus it may not be possible to export multi-prime
+// private keys in certain formats or to subsequently import them into other
+// code.
+//
+// Table 1 in [2] suggests maximum numbers of primes for a given size.
+//
+// [1] US patent 4405829 (1972, expired)
+// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
+func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *PrivateKey, err error) {
+	priv = new(PrivateKey)
+	priv.E = 65537
+
+	if nprimes < 2 {
+		return nil, errors.New("crypto/rsa: GenerateMultiPrimeKey: nprimes must be >= 2")
+	}
+
+	primes := make([]*big.Int, nprimes)
+
+NextSetOfPrimes:
+	for {
+		todo := bits
+		// crypto/rand should set the top two bits in each prime.
+		// Thus each prime has the form
+		//   p_i = 2^bitlen(p_i) × 0.11... (in base 2).
+		// And the product is:
+		//   P = 2^todo × α
+		// where α is the product of nprimes numbers of the form 0.11...
+		//
+		// If α < 1/2 (which can happen for nprimes > 2), we need to
+		// shift todo to compensate for lost bits: the mean value of 0.11...
+		// is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2
+		// will give good results.
+		if nprimes >= 7 {
+			todo += (nprimes - 2) / 5
+		}
+		for i := 0; i < nprimes; i++ {
+			primes[i], err = rand.Prime(random, todo/(nprimes-i))
+			if err != nil {
+				return nil, err
+			}
+			todo -= primes[i].BitLen()
+		}
+
+		// Make sure that primes is pairwise unequal.
+		for i, prime := range primes {
+			for j := 0; j < i; j++ {
+				if prime.Cmp(primes[j]) == 0 {
+					continue NextSetOfPrimes
+				}
+			}
+		}
+
+		n := new(big.Int).Set(bigOne)
+		totient := new(big.Int).Set(bigOne)
+		pminus1 := new(big.Int)
+		for _, prime := range primes {
+			n.Mul(n, prime)
+			pminus1.Sub(prime, bigOne)
+			totient.Mul(totient, pminus1)
+		}
+		if n.BitLen() != bits {
+			// This should never happen for nprimes == 2 because
+			// crypto/rand should set the top two bits in each prime.
+			// For nprimes > 2 we hope it does not happen often.
+			continue NextSetOfPrimes
+		}
+
+		g := new(big.Int)
+		priv.D = new(big.Int)
+		y := new(big.Int)
+		e := big.NewInt(int64(priv.E))
+		g.GCD(priv.D, y, e, totient)
+
+		if g.Cmp(bigOne) == 0 {
+			if priv.D.Sign() < 0 {
+				priv.D.Add(priv.D, totient)
+			}
+			priv.Primes = primes
+			priv.N = n
+
+			break
+		}
+	}
+
+	priv.Precompute()
+	return
+}
+
+// incCounter increments a four byte, big-endian counter.
+func incCounter(c *[4]byte) {
+	if c[3]++; c[3] != 0 {
+		return
+	}
+	if c[2]++; c[2] != 0 {
+		return
+	}
+	if c[1]++; c[1] != 0 {
+		return
+	}
+	c[0]++
+}
+
+// mgf1XOR XORs the bytes in out with a mask generated using the MGF1 function
+// specified in PKCS#1 v2.1.
+func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
+	var counter [4]byte
+	var digest []byte
+
+	done := 0
+	for done < len(out) {
+		hash.Write(seed)
+		hash.Write(counter[0:4])
+		digest = hash.Sum(digest[:0])
+		hash.Reset()
+
+		for i := 0; i < len(digest) && done < len(out); i++ {
+			out[done] ^= digest[i]
+			done++
+		}
+		incCounter(&counter)
+	}
+}
+
+// ErrMessageTooLong is returned when attempting to encrypt a message which is
+// too large for the size of the public key.
+var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size")
+
+func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
+	e := big.NewInt(int64(pub.E))
+	c.Exp(m, e, pub.N)
+	return c
+}
+
+// EncryptOAEP encrypts the given message with RSA-OAEP.
+// The message must be no longer than the length of the public modulus less
+// twice the hash length plus 2.
+func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error) {
+	if err := checkPub(pub); err != nil {
+		return nil, err
+	}
+	hash.Reset()
+	k := (pub.N.BitLen() + 7) / 8
+	if len(msg) > k-2*hash.Size()-2 {
+		err = ErrMessageTooLong
+		return
+	}
+
+	hash.Write(label)
+	lHash := hash.Sum(nil)
+	hash.Reset()
+
+	em := make([]byte, k)
+	seed := em[1 : 1+hash.Size()]
+	db := em[1+hash.Size():]
+
+	copy(db[0:hash.Size()], lHash)
+	db[len(db)-len(msg)-1] = 1
+	copy(db[len(db)-len(msg):], msg)
+
+	_, err = io.ReadFull(random, seed)
+	if err != nil {
+		return
+	}
+
+	mgf1XOR(db, hash, seed)
+	mgf1XOR(seed, hash, db)
+
+	m := new(big.Int)
+	m.SetBytes(em)
+	c := encrypt(new(big.Int), pub, m)
+	out = c.Bytes()
+
+	if len(out) < k {
+		// If the output is too small, we need to left-pad with zeros.
+		t := make([]byte, k)
+		copy(t[k-len(out):], out)
+		out = t
+	}
+
+	return
+}
+
+// ErrDecryption represents a failure to decrypt a message.
+// It is deliberately vague to avoid adaptive attacks.
+var ErrDecryption = errors.New("crypto/rsa: decryption error")
+
+// ErrVerification represents a failure to verify a signature.
+// It is deliberately vague to avoid adaptive attacks.
+var ErrVerification = errors.New("crypto/rsa: verification error")
+
+// modInverse returns ia, the inverse of a in the multiplicative group of prime
+// order n. It requires that a be a member of the group (i.e. less than n).
+func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
+	g := new(big.Int)
+	x := new(big.Int)
+	y := new(big.Int)
+	g.GCD(x, y, a, n)
+	if g.Cmp(bigOne) != 0 {
+		// In this case, a and n aren't coprime and we cannot calculate
+		// the inverse. This happens because the values of n are nearly
+		// prime (being the product of two primes) rather than truly
+		// prime.
+		return
+	}
+
+	if x.Cmp(bigOne) < 0 {
+		// 0 is not the multiplicative inverse of any element so, if x
+		// < 1, then x is negative.
+		x.Add(x, n)
+	}
+
+	return x, true
+}
+
+// Precompute performs some calculations that speed up private key operations
+// in the future.
+func (priv *PrivateKey) Precompute() {
+	if priv.Precomputed.Dp != nil {
+		return
+	}
+
+	priv.Precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne)
+	priv.Precomputed.Dp.Mod(priv.D, priv.Precomputed.Dp)
+
+	priv.Precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne)
+	priv.Precomputed.Dq.Mod(priv.D, priv.Precomputed.Dq)
+
+	priv.Precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0])
+
+	r := new(big.Int).Mul(priv.Primes[0], priv.Primes[1])
+	priv.Precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2)
+	for i := 2; i < len(priv.Primes); i++ {
+		prime := priv.Primes[i]
+		values := &priv.Precomputed.CRTValues[i-2]
+
+		values.Exp = new(big.Int).Sub(prime, bigOne)
+		values.Exp.Mod(priv.D, values.Exp)
+
+		values.R = new(big.Int).Set(r)
+		values.Coeff = new(big.Int).ModInverse(r, prime)
+
+		r.Mul(r, prime)
+	}
+}
+
+// decrypt performs an RSA decryption, resulting in a plaintext integer. If a
+// random source is given, RSA blinding is used.
+func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
+	// TODO(agl): can we get away with reusing blinds?
+	if c.Cmp(priv.N) > 0 {
+		err = ErrDecryption
+		return
+	}
+
+	var ir *big.Int
+	if random != nil {
+		// Blinding enabled. Blinding involves multiplying c by r^e.
+		// Then the decryption operation performs (m^e * r^e)^d mod n
+		// which equals mr mod n. The factor of r can then be removed
+		// by multiplying by the multiplicative inverse of r.
+
+		var r *big.Int
+
+		for {
+			r, err = rand.Int(random, priv.N)
+			if err != nil {
+				return
+			}
+			if r.Cmp(bigZero) == 0 {
+				r = bigOne
+			}
+			var ok bool
+			ir, ok = modInverse(r, priv.N)
+			if ok {
+				break
+			}
+		}
+		bigE := big.NewInt(int64(priv.E))
+		rpowe := new(big.Int).Exp(r, bigE, priv.N)
+		cCopy := new(big.Int).Set(c)
+		cCopy.Mul(cCopy, rpowe)
+		cCopy.Mod(cCopy, priv.N)
+		c = cCopy
+	}
+
+	if priv.Precomputed.Dp == nil {
+		m = new(big.Int).Exp(c, priv.D, priv.N)
+	} else {
+		// We have the precalculated values needed for the CRT.
+		m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
+		m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
+		m.Sub(m, m2)
+		if m.Sign() < 0 {
+			m.Add(m, priv.Primes[0])
+		}
+		m.Mul(m, priv.Precomputed.Qinv)
+		m.Mod(m, priv.Primes[0])
+		m.Mul(m, priv.Primes[1])
+		m.Add(m, m2)
+
+		for i, values := range priv.Precomputed.CRTValues {
+			prime := priv.Primes[2+i]
+			m2.Exp(c, values.Exp, prime)
+			m2.Sub(m2, m)
+			m2.Mul(m2, values.Coeff)
+			m2.Mod(m2, prime)
+			if m2.Sign() < 0 {
+				m2.Add(m2, prime)
+			}
+			m2.Mul(m2, values.R)
+			m.Add(m, m2)
+		}
+	}
+
+	if ir != nil {
+		// Unblind.
+		m.Mul(m, ir)
+		m.Mod(m, priv.N)
+	}
+
+	return
+}
+
+// DecryptOAEP decrypts ciphertext using RSA-OAEP.
+// If random != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
+func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
+	if err := checkPub(&priv.PublicKey); err != nil {
+		return nil, err
+	}
+	k := (priv.N.BitLen() + 7) / 8
+	if len(ciphertext) > k ||
+		k < hash.Size()*2+2 {
+		err = ErrDecryption
+		return
+	}
+
+	c := new(big.Int).SetBytes(ciphertext)
+
+	m, err := decrypt(random, priv, c)
+	if err != nil {
+		return
+	}
+
+	hash.Write(label)
+	lHash := hash.Sum(nil)
+	hash.Reset()
+
+	// Converting the plaintext number to bytes will strip any
+	// leading zeros so we may have to left pad. We do this unconditionally
+	// to avoid leaking timing information. (Although we still probably
+	// leak the number of leading zeros. It's not clear that we can do
+	// anything about this.)
+	em := leftPad(m.Bytes(), k)
+
+	firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
+
+	seed := em[1 : hash.Size()+1]
+	db := em[hash.Size()+1:]
+
+	mgf1XOR(seed, hash, db)
+	mgf1XOR(db, hash, seed)
+
+	lHash2 := db[0:hash.Size()]
+
+	// We have to validate the plaintext in constant time in order to avoid
+	// attacks like: J. Manger. A Chosen Ciphertext Attack on RSA Optimal
+	// Asymmetric Encryption Padding (OAEP) as Standardized in PKCS #1
+	// v2.0. In J. Kilian, editor, Advances in Cryptology.
+	lHash2Good := subtle.ConstantTimeCompare(lHash, lHash2)
+
+	// The remainder of the plaintext must be zero or more 0x00, followed
+	// by 0x01, followed by the message.
+	//   lookingForIndex: 1 iff we are still looking for the 0x01
+	//   index: the offset of the first 0x01 byte
+	//   invalid: 1 iff we saw a non-zero byte before the 0x01.
+	var lookingForIndex, index, invalid int
+	lookingForIndex = 1
+	rest := db[hash.Size():]
+
+	for i := 0; i < len(rest); i++ {
+		equals0 := subtle.ConstantTimeByteEq(rest[i], 0)
+		equals1 := subtle.ConstantTimeByteEq(rest[i], 1)
+		index = subtle.ConstantTimeSelect(lookingForIndex&equals1, i, index)
+		lookingForIndex = subtle.ConstantTimeSelect(equals1, 0, lookingForIndex)
+		invalid = subtle.ConstantTimeSelect(lookingForIndex&^equals0, 1, invalid)
+	}
+
+	if firstByteIsZero&lHash2Good&^invalid&^lookingForIndex != 1 {
+		err = ErrDecryption
+		return
+	}
+
+	msg = rest[index+1:]
+	return
+}
+
+// leftPad returns a new slice of length size. The contents of input are right
+// aligned in the new slice.
+func leftPad(input []byte, size int) (out []byte) {
+	n := len(input)
+	if n > size {
+		n = size
+	}
+	out = make([]byte, size)
+	copy(out[len(out)-n:], input)
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rsa/rsa_test.go b/third_party/gofrontend/libgo/go/crypto/rsa/rsa_test.go
new file mode 100644
index 0000000..4ee1c3a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rsa/rsa_test.go
@@ -0,0 +1,392 @@
+// 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 rsa
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/sha1"
+	"math/big"
+	"testing"
+)
+
+func TestKeyGeneration(t *testing.T) {
+	size := 1024
+	if testing.Short() {
+		size = 128
+	}
+	priv, err := GenerateKey(rand.Reader, size)
+	if err != nil {
+		t.Errorf("failed to generate key")
+	}
+	if bits := priv.N.BitLen(); bits != size {
+		t.Errorf("key too short (%d vs %d)", bits, size)
+	}
+	testKeyBasics(t, priv)
+}
+
+func Test3PrimeKeyGeneration(t *testing.T) {
+	size := 768
+	if testing.Short() {
+		size = 256
+	}
+
+	priv, err := GenerateMultiPrimeKey(rand.Reader, 3, size)
+	if err != nil {
+		t.Errorf("failed to generate key")
+	}
+	testKeyBasics(t, priv)
+}
+
+func Test4PrimeKeyGeneration(t *testing.T) {
+	size := 768
+	if testing.Short() {
+		size = 256
+	}
+
+	priv, err := GenerateMultiPrimeKey(rand.Reader, 4, size)
+	if err != nil {
+		t.Errorf("failed to generate key")
+	}
+	testKeyBasics(t, priv)
+}
+
+func TestNPrimeKeyGeneration(t *testing.T) {
+	primeSize := 64
+	maxN := 24
+	if testing.Short() {
+		primeSize = 16
+		maxN = 16
+	}
+	// Test that generation of N-prime keys works for N > 4.
+	for n := 5; n < maxN; n++ {
+		priv, err := GenerateMultiPrimeKey(rand.Reader, n, 64+n*primeSize)
+		if err == nil {
+			testKeyBasics(t, priv)
+		} else {
+			t.Errorf("failed to generate %d-prime key", n)
+		}
+	}
+}
+
+func TestGnuTLSKey(t *testing.T) {
+	// This is a key generated by `certtool --generate-privkey --bits 128`.
+	// It's such that de ≢ 1 mod φ(n), but is congruent mod the order of
+	// the group.
+	priv := &PrivateKey{
+		PublicKey: PublicKey{
+			N: fromBase10("290684273230919398108010081414538931343"),
+			E: 65537,
+		},
+		D: fromBase10("31877380284581499213530787347443987241"),
+		Primes: []*big.Int{
+			fromBase10("16775196964030542637"),
+			fromBase10("17328218193455850539"),
+		},
+	}
+	testKeyBasics(t, priv)
+}
+
+func testKeyBasics(t *testing.T, priv *PrivateKey) {
+	if err := priv.Validate(); err != nil {
+		t.Errorf("Validate() failed: %s", err)
+	}
+	if priv.D.Cmp(priv.N) > 0 {
+		t.Errorf("private exponent too large")
+	}
+
+	pub := &priv.PublicKey
+	m := big.NewInt(42)
+	c := encrypt(new(big.Int), pub, m)
+
+	m2, err := decrypt(nil, priv, c)
+	if err != nil {
+		t.Errorf("error while decrypting: %s", err)
+		return
+	}
+	if m.Cmp(m2) != 0 {
+		t.Errorf("got:%v, want:%v (%+v)", m2, m, priv)
+	}
+
+	m3, err := decrypt(rand.Reader, priv, c)
+	if err != nil {
+		t.Errorf("error while decrypting (blind): %s", err)
+	}
+	if m.Cmp(m3) != 0 {
+		t.Errorf("(blind) got:%v, want:%v (%#v)", m3, m, priv)
+	}
+}
+
+func fromBase10(base10 string) *big.Int {
+	i, ok := new(big.Int).SetString(base10, 10)
+	if !ok {
+		panic("bad number: " + base10)
+	}
+	return i
+}
+
+func BenchmarkRSA2048Decrypt(b *testing.B) {
+	b.StopTimer()
+	priv := &PrivateKey{
+		PublicKey: PublicKey{
+			N: fromBase10("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557"),
+			E: 3,
+		},
+		D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"),
+		Primes: []*big.Int{
+			fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
+			fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
+		},
+	}
+	priv.Precompute()
+
+	c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
+
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		decrypt(nil, priv, c)
+	}
+}
+
+func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
+	b.StopTimer()
+	priv := &PrivateKey{
+		PublicKey: PublicKey{
+			N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
+			E: 3,
+		},
+		D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
+		Primes: []*big.Int{
+			fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
+			fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
+			fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+		},
+	}
+	priv.Precompute()
+
+	c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
+
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		decrypt(nil, priv, c)
+	}
+}
+
+type testEncryptOAEPMessage struct {
+	in   []byte
+	seed []byte
+	out  []byte
+}
+
+type testEncryptOAEPStruct struct {
+	modulus string
+	e       int
+	d       string
+	msgs    []testEncryptOAEPMessage
+}
+
+func TestEncryptOAEP(t *testing.T) {
+	sha1 := sha1.New()
+	n := new(big.Int)
+	for i, test := range testEncryptOAEPData {
+		n.SetString(test.modulus, 16)
+		public := PublicKey{n, test.e}
+
+		for j, message := range test.msgs {
+			randomSource := bytes.NewReader(message.seed)
+			out, err := EncryptOAEP(sha1, randomSource, &public, message.in, nil)
+			if err != nil {
+				t.Errorf("#%d,%d error: %s", i, j, err)
+			}
+			if !bytes.Equal(out, message.out) {
+				t.Errorf("#%d,%d bad result: %x (want %x)", i, j, out, message.out)
+			}
+		}
+	}
+}
+
+func TestDecryptOAEP(t *testing.T) {
+	random := rand.Reader
+
+	sha1 := sha1.New()
+	n := new(big.Int)
+	d := new(big.Int)
+	for i, test := range testEncryptOAEPData {
+		n.SetString(test.modulus, 16)
+		d.SetString(test.d, 16)
+		private := new(PrivateKey)
+		private.PublicKey = PublicKey{n, test.e}
+		private.D = d
+
+		for j, message := range test.msgs {
+			out, err := DecryptOAEP(sha1, nil, private, message.out, nil)
+			if err != nil {
+				t.Errorf("#%d,%d error: %s", i, j, err)
+			} else if !bytes.Equal(out, message.in) {
+				t.Errorf("#%d,%d bad result: %#v (want %#v)", i, j, out, message.in)
+			}
+
+			// Decrypt with blinding.
+			out, err = DecryptOAEP(sha1, random, private, message.out, nil)
+			if err != nil {
+				t.Errorf("#%d,%d (blind) error: %s", i, j, err)
+			} else if !bytes.Equal(out, message.in) {
+				t.Errorf("#%d,%d (blind) bad result: %#v (want %#v)", i, j, out, message.in)
+			}
+		}
+		if testing.Short() {
+			break
+		}
+	}
+}
+
+// testEncryptOAEPData contains a subset of the vectors from RSA's "Test vectors for RSA-OAEP".
+var testEncryptOAEPData = []testEncryptOAEPStruct{
+	// Key 1
+	{"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb",
+		65537,
+		"53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1",
+		[]testEncryptOAEPMessage{
+			// Example 1.1
+			{
+				[]byte{0x66, 0x28, 0x19, 0x4e, 0x12, 0x07, 0x3d, 0xb0,
+					0x3b, 0xa9, 0x4c, 0xda, 0x9e, 0xf9, 0x53, 0x23, 0x97,
+					0xd5, 0x0d, 0xba, 0x79, 0xb9, 0x87, 0x00, 0x4a, 0xfe,
+					0xfe, 0x34,
+				},
+				[]byte{0x18, 0xb7, 0x76, 0xea, 0x21, 0x06, 0x9d, 0x69,
+					0x77, 0x6a, 0x33, 0xe9, 0x6b, 0xad, 0x48, 0xe1, 0xdd,
+					0xa0, 0xa5, 0xef,
+				},
+				[]byte{0x35, 0x4f, 0xe6, 0x7b, 0x4a, 0x12, 0x6d, 0x5d,
+					0x35, 0xfe, 0x36, 0xc7, 0x77, 0x79, 0x1a, 0x3f, 0x7b,
+					0xa1, 0x3d, 0xef, 0x48, 0x4e, 0x2d, 0x39, 0x08, 0xaf,
+					0xf7, 0x22, 0xfa, 0xd4, 0x68, 0xfb, 0x21, 0x69, 0x6d,
+					0xe9, 0x5d, 0x0b, 0xe9, 0x11, 0xc2, 0xd3, 0x17, 0x4f,
+					0x8a, 0xfc, 0xc2, 0x01, 0x03, 0x5f, 0x7b, 0x6d, 0x8e,
+					0x69, 0x40, 0x2d, 0xe5, 0x45, 0x16, 0x18, 0xc2, 0x1a,
+					0x53, 0x5f, 0xa9, 0xd7, 0xbf, 0xc5, 0xb8, 0xdd, 0x9f,
+					0xc2, 0x43, 0xf8, 0xcf, 0x92, 0x7d, 0xb3, 0x13, 0x22,
+					0xd6, 0xe8, 0x81, 0xea, 0xa9, 0x1a, 0x99, 0x61, 0x70,
+					0xe6, 0x57, 0xa0, 0x5a, 0x26, 0x64, 0x26, 0xd9, 0x8c,
+					0x88, 0x00, 0x3f, 0x84, 0x77, 0xc1, 0x22, 0x70, 0x94,
+					0xa0, 0xd9, 0xfa, 0x1e, 0x8c, 0x40, 0x24, 0x30, 0x9c,
+					0xe1, 0xec, 0xcc, 0xb5, 0x21, 0x00, 0x35, 0xd4, 0x7a,
+					0xc7, 0x2e, 0x8a,
+				},
+			},
+			// Example 1.2
+			{
+				[]byte{0x75, 0x0c, 0x40, 0x47, 0xf5, 0x47, 0xe8, 0xe4,
+					0x14, 0x11, 0x85, 0x65, 0x23, 0x29, 0x8a, 0xc9, 0xba,
+					0xe2, 0x45, 0xef, 0xaf, 0x13, 0x97, 0xfb, 0xe5, 0x6f,
+					0x9d, 0xd5,
+				},
+				[]byte{0x0c, 0xc7, 0x42, 0xce, 0x4a, 0x9b, 0x7f, 0x32,
+					0xf9, 0x51, 0xbc, 0xb2, 0x51, 0xef, 0xd9, 0x25, 0xfe,
+					0x4f, 0xe3, 0x5f,
+				},
+				[]byte{0x64, 0x0d, 0xb1, 0xac, 0xc5, 0x8e, 0x05, 0x68,
+					0xfe, 0x54, 0x07, 0xe5, 0xf9, 0xb7, 0x01, 0xdf, 0xf8,
+					0xc3, 0xc9, 0x1e, 0x71, 0x6c, 0x53, 0x6f, 0xc7, 0xfc,
+					0xec, 0x6c, 0xb5, 0xb7, 0x1c, 0x11, 0x65, 0x98, 0x8d,
+					0x4a, 0x27, 0x9e, 0x15, 0x77, 0xd7, 0x30, 0xfc, 0x7a,
+					0x29, 0x93, 0x2e, 0x3f, 0x00, 0xc8, 0x15, 0x15, 0x23,
+					0x6d, 0x8d, 0x8e, 0x31, 0x01, 0x7a, 0x7a, 0x09, 0xdf,
+					0x43, 0x52, 0xd9, 0x04, 0xcd, 0xeb, 0x79, 0xaa, 0x58,
+					0x3a, 0xdc, 0xc3, 0x1e, 0xa6, 0x98, 0xa4, 0xc0, 0x52,
+					0x83, 0xda, 0xba, 0x90, 0x89, 0xbe, 0x54, 0x91, 0xf6,
+					0x7c, 0x1a, 0x4e, 0xe4, 0x8d, 0xc7, 0x4b, 0xbb, 0xe6,
+					0x64, 0x3a, 0xef, 0x84, 0x66, 0x79, 0xb4, 0xcb, 0x39,
+					0x5a, 0x35, 0x2d, 0x5e, 0xd1, 0x15, 0x91, 0x2d, 0xf6,
+					0x96, 0xff, 0xe0, 0x70, 0x29, 0x32, 0x94, 0x6d, 0x71,
+					0x49, 0x2b, 0x44,
+				},
+			},
+			// Example 1.3
+			{
+				[]byte{0xd9, 0x4a, 0xe0, 0x83, 0x2e, 0x64, 0x45, 0xce,
+					0x42, 0x33, 0x1c, 0xb0, 0x6d, 0x53, 0x1a, 0x82, 0xb1,
+					0xdb, 0x4b, 0xaa, 0xd3, 0x0f, 0x74, 0x6d, 0xc9, 0x16,
+					0xdf, 0x24, 0xd4, 0xe3, 0xc2, 0x45, 0x1f, 0xff, 0x59,
+					0xa6, 0x42, 0x3e, 0xb0, 0xe1, 0xd0, 0x2d, 0x4f, 0xe6,
+					0x46, 0xcf, 0x69, 0x9d, 0xfd, 0x81, 0x8c, 0x6e, 0x97,
+					0xb0, 0x51,
+				},
+				[]byte{0x25, 0x14, 0xdf, 0x46, 0x95, 0x75, 0x5a, 0x67,
+					0xb2, 0x88, 0xea, 0xf4, 0x90, 0x5c, 0x36, 0xee, 0xc6,
+					0x6f, 0xd2, 0xfd,
+				},
+				[]byte{0x42, 0x37, 0x36, 0xed, 0x03, 0x5f, 0x60, 0x26,
+					0xaf, 0x27, 0x6c, 0x35, 0xc0, 0xb3, 0x74, 0x1b, 0x36,
+					0x5e, 0x5f, 0x76, 0xca, 0x09, 0x1b, 0x4e, 0x8c, 0x29,
+					0xe2, 0xf0, 0xbe, 0xfe, 0xe6, 0x03, 0x59, 0x5a, 0xa8,
+					0x32, 0x2d, 0x60, 0x2d, 0x2e, 0x62, 0x5e, 0x95, 0xeb,
+					0x81, 0xb2, 0xf1, 0xc9, 0x72, 0x4e, 0x82, 0x2e, 0xca,
+					0x76, 0xdb, 0x86, 0x18, 0xcf, 0x09, 0xc5, 0x34, 0x35,
+					0x03, 0xa4, 0x36, 0x08, 0x35, 0xb5, 0x90, 0x3b, 0xc6,
+					0x37, 0xe3, 0x87, 0x9f, 0xb0, 0x5e, 0x0e, 0xf3, 0x26,
+					0x85, 0xd5, 0xae, 0xc5, 0x06, 0x7c, 0xd7, 0xcc, 0x96,
+					0xfe, 0x4b, 0x26, 0x70, 0xb6, 0xea, 0xc3, 0x06, 0x6b,
+					0x1f, 0xcf, 0x56, 0x86, 0xb6, 0x85, 0x89, 0xaa, 0xfb,
+					0x7d, 0x62, 0x9b, 0x02, 0xd8, 0xf8, 0x62, 0x5c, 0xa3,
+					0x83, 0x36, 0x24, 0xd4, 0x80, 0x0f, 0xb0, 0x81, 0xb1,
+					0xcf, 0x94, 0xeb,
+				},
+			},
+		},
+	},
+	// Key 10
+	{"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb",
+		65537,
+		"056b04216fe5f354ac77250a4b6b0c8525a85c59b0bd80c56450a22d5f438e596a333aa875e291dd43f48cb88b9d5fc0d499f9fcd1c397f9afc070cd9e398c8d19e61db7c7410a6b2675dfbf5d345b804d201add502d5ce2dfcb091ce9997bbebe57306f383e4d588103f036f7e85d1934d152a323e4a8db451d6f4a5b1b0f102cc150e02feee2b88dea4ad4c1baccb24d84072d14e1d24a6771f7408ee30564fb86d4393a34bcf0b788501d193303f13a2284b001f0f649eaf79328d4ac5c430ab4414920a9460ed1b7bc40ec653e876d09abc509ae45b525190116a0c26101848298509c1c3bf3a483e7274054e15e97075036e989f60932807b5257751e79",
+		[]testEncryptOAEPMessage{
+			// Example 10.1
+			{
+				[]byte{0x8b, 0xba, 0x6b, 0xf8, 0x2a, 0x6c, 0x0f, 0x86,
+					0xd5, 0xf1, 0x75, 0x6e, 0x97, 0x95, 0x68, 0x70, 0xb0,
+					0x89, 0x53, 0xb0, 0x6b, 0x4e, 0xb2, 0x05, 0xbc, 0x16,
+					0x94, 0xee,
+				},
+				[]byte{0x47, 0xe1, 0xab, 0x71, 0x19, 0xfe, 0xe5, 0x6c,
+					0x95, 0xee, 0x5e, 0xaa, 0xd8, 0x6f, 0x40, 0xd0, 0xaa,
+					0x63, 0xbd, 0x33,
+				},
+				[]byte{0x53, 0xea, 0x5d, 0xc0, 0x8c, 0xd2, 0x60, 0xfb,
+					0x3b, 0x85, 0x85, 0x67, 0x28, 0x7f, 0xa9, 0x15, 0x52,
+					0xc3, 0x0b, 0x2f, 0xeb, 0xfb, 0xa2, 0x13, 0xf0, 0xae,
+					0x87, 0x70, 0x2d, 0x06, 0x8d, 0x19, 0xba, 0xb0, 0x7f,
+					0xe5, 0x74, 0x52, 0x3d, 0xfb, 0x42, 0x13, 0x9d, 0x68,
+					0xc3, 0xc5, 0xaf, 0xee, 0xe0, 0xbf, 0xe4, 0xcb, 0x79,
+					0x69, 0xcb, 0xf3, 0x82, 0xb8, 0x04, 0xd6, 0xe6, 0x13,
+					0x96, 0x14, 0x4e, 0x2d, 0x0e, 0x60, 0x74, 0x1f, 0x89,
+					0x93, 0xc3, 0x01, 0x4b, 0x58, 0xb9, 0xb1, 0x95, 0x7a,
+					0x8b, 0xab, 0xcd, 0x23, 0xaf, 0x85, 0x4f, 0x4c, 0x35,
+					0x6f, 0xb1, 0x66, 0x2a, 0xa7, 0x2b, 0xfc, 0xc7, 0xe5,
+					0x86, 0x55, 0x9d, 0xc4, 0x28, 0x0d, 0x16, 0x0c, 0x12,
+					0x67, 0x85, 0xa7, 0x23, 0xeb, 0xee, 0xbe, 0xff, 0x71,
+					0xf1, 0x15, 0x94, 0x44, 0x0a, 0xae, 0xf8, 0x7d, 0x10,
+					0x79, 0x3a, 0x87, 0x74, 0xa2, 0x39, 0xd4, 0xa0, 0x4c,
+					0x87, 0xfe, 0x14, 0x67, 0xb9, 0xda, 0xf8, 0x52, 0x08,
+					0xec, 0x6c, 0x72, 0x55, 0x79, 0x4a, 0x96, 0xcc, 0x29,
+					0x14, 0x2f, 0x9a, 0x8b, 0xd4, 0x18, 0xe3, 0xc1, 0xfd,
+					0x67, 0x34, 0x4b, 0x0c, 0xd0, 0x82, 0x9d, 0xf3, 0xb2,
+					0xbe, 0xc6, 0x02, 0x53, 0x19, 0x62, 0x93, 0xc6, 0xb3,
+					0x4d, 0x3f, 0x75, 0xd3, 0x2f, 0x21, 0x3d, 0xd4, 0x5c,
+					0x62, 0x73, 0xd5, 0x05, 0xad, 0xf4, 0xcc, 0xed, 0x10,
+					0x57, 0xcb, 0x75, 0x8f, 0xc2, 0x6a, 0xee, 0xfa, 0x44,
+					0x12, 0x55, 0xed, 0x4e, 0x64, 0xc1, 0x99, 0xee, 0x07,
+					0x5e, 0x7f, 0x16, 0x64, 0x61, 0x82, 0xfd, 0xb4, 0x64,
+					0x73, 0x9b, 0x68, 0xab, 0x5d, 0xaf, 0xf0, 0xe6, 0x3e,
+					0x95, 0x52, 0x01, 0x68, 0x24, 0xf0, 0x54, 0xbf, 0x4d,
+					0x3c, 0x8c, 0x90, 0xa9, 0x7b, 0xb6, 0xb6, 0x55, 0x32,
+					0x84, 0xeb, 0x42, 0x9f, 0xcc,
+				},
+			},
+		},
+	},
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/rsa/testdata/pss-vect.txt.bz2 b/third_party/gofrontend/libgo/go/crypto/rsa/testdata/pss-vect.txt.bz2
new file mode 100644
index 0000000..ad3da1a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/rsa/testdata/pss-vect.txt.bz2
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/crypto/sha1/sha1.go b/third_party/gofrontend/libgo/go/crypto/sha1/sha1.go
new file mode 100644
index 0000000..9f1a96e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha1/sha1.go
@@ -0,0 +1,130 @@
+// 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 sha1 implements the SHA1 hash algorithm as defined in RFC 3174.
+package sha1
+
+import (
+	"crypto"
+	"hash"
+)
+
+func init() {
+	crypto.RegisterHash(crypto.SHA1, New)
+}
+
+// The size of a SHA1 checksum in bytes.
+const Size = 20
+
+// The blocksize of SHA1 in bytes.
+const BlockSize = 64
+
+const (
+	chunk = 64
+	init0 = 0x67452301
+	init1 = 0xEFCDAB89
+	init2 = 0x98BADCFE
+	init3 = 0x10325476
+	init4 = 0xC3D2E1F0
+)
+
+// digest represents the partial evaluation of a checksum.
+type digest struct {
+	h   [5]uint32
+	x   [chunk]byte
+	nx  int
+	len uint64
+}
+
+func (d *digest) Reset() {
+	d.h[0] = init0
+	d.h[1] = init1
+	d.h[2] = init2
+	d.h[3] = init3
+	d.h[4] = init4
+	d.nx = 0
+	d.len = 0
+}
+
+// New returns a new hash.Hash computing the SHA1 checksum.
+func New() hash.Hash {
+	d := new(digest)
+	d.Reset()
+	return d
+}
+
+func (d *digest) Size() int { return Size }
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
+	nn = len(p)
+	d.len += uint64(nn)
+	if d.nx > 0 {
+		n := copy(d.x[d.nx:], p)
+		d.nx += n
+		if d.nx == chunk {
+			block(d, d.x[:])
+			d.nx = 0
+		}
+		p = p[n:]
+	}
+	if len(p) >= chunk {
+		n := len(p) &^ (chunk - 1)
+		block(d, p[:n])
+		p = p[n:]
+	}
+	if len(p) > 0 {
+		d.nx = copy(d.x[:], p)
+	}
+	return
+}
+
+func (d0 *digest) Sum(in []byte) []byte {
+	// Make a copy of d0 so that caller can keep writing and summing.
+	d := *d0
+	hash := d.checkSum()
+	return append(in, hash[:]...)
+}
+
+func (d *digest) checkSum() [Size]byte {
+	len := d.len
+	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
+	var tmp [64]byte
+	tmp[0] = 0x80
+	if len%64 < 56 {
+		d.Write(tmp[0 : 56-len%64])
+	} else {
+		d.Write(tmp[0 : 64+56-len%64])
+	}
+
+	// Length in bits.
+	len <<= 3
+	for i := uint(0); i < 8; i++ {
+		tmp[i] = byte(len >> (56 - 8*i))
+	}
+	d.Write(tmp[0:8])
+
+	if d.nx != 0 {
+		panic("d.nx != 0")
+	}
+
+	var digest [Size]byte
+	for i, s := range d.h {
+		digest[i*4] = byte(s >> 24)
+		digest[i*4+1] = byte(s >> 16)
+		digest[i*4+2] = byte(s >> 8)
+		digest[i*4+3] = byte(s)
+	}
+
+	return digest
+}
+
+// Sum returns the SHA1 checksum of the data.
+func Sum(data []byte) [Size]byte {
+	var d digest
+	d.Reset()
+	d.Write(data)
+	return d.checkSum()
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/sha1/sha1_test.go b/third_party/gofrontend/libgo/go/crypto/sha1/sha1_test.go
new file mode 100644
index 0000000..4a62951
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha1/sha1_test.go
@@ -0,0 +1,129 @@
+// 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.
+
+// SHA1 hash algorithm.  See RFC 3174.
+
+package sha1
+
+import (
+	"crypto/rand"
+	"fmt"
+	"io"
+	"testing"
+)
+
+type sha1Test struct {
+	out string
+	in  string
+}
+
+var golden = []sha1Test{
+	{"da39a3ee5e6b4b0d3255bfef95601890afd80709", ""},
+	{"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", "a"},
+	{"da23614e02469a0d7c7bd1bdab5c9c474b1904dc", "ab"},
+	{"a9993e364706816aba3e25717850c26c9cd0d89d", "abc"},
+	{"81fe8bfe87576c3ecb22426f8e57847382917acf", "abcd"},
+	{"03de6c570bfe24bfc328ccd7ca46b76eadaf4334", "abcde"},
+	{"1f8ac10f23c5b5bc1167bda84b833e5c057a77d2", "abcdef"},
+	{"2fb5e13419fc89246865e7a324f476ec624e8740", "abcdefg"},
+	{"425af12a0743502b322e93a015bcf868e324d56a", "abcdefgh"},
+	{"c63b19f1e4c8b5f76b25c49b8b87f57d8e4872a1", "abcdefghi"},
+	{"d68c19a0a345b7eab78d5e11e991c026ec60db63", "abcdefghij"},
+	{"ebf81ddcbe5bf13aaabdc4d65354fdf2044f38a7", "Discard medicine more than two years old."},
+	{"e5dea09392dd886ca63531aaa00571dc07554bb6", "He who has a shady past knows that nice guys finish last."},
+	{"45988f7234467b94e3e9494434c96ee3609d8f8f", "I wouldn't marry him with a ten foot pole."},
+	{"55dee037eb7460d5a692d1ce11330b260e40c988", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+	{"b7bc5fb91080c7de6b582ea281f8a396d7c0aee8", "The days of the digital watch are numbered.  -Tom Stoppard"},
+	{"c3aed9358f7c77f523afe86135f06b95b3999797", "Nepal premier won't resign."},
+	{"6e29d302bf6e3a5e4305ff318d983197d6906bb9", "For every action there is an equal and opposite government program."},
+	{"597f6a540010f94c15d71806a99a2c8710e747bd", "His money is twice tainted: 'taint yours and 'taint mine."},
+	{"6859733b2590a8a091cecf50086febc5ceef1e80", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+	{"514b2630ec089b8aee18795fc0cf1f4860cdacad", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+	{"c5ca0d4a7b6676fc7aa72caa41cc3d5df567ed69", "size:  a.out:  bad magic"},
+	{"74c51fa9a04eadc8c1bbeaa7fc442f834b90a00a", "The major problem is with sendmail.  -Mark Horton"},
+	{"0b4c4ce5f52c3ad2821852a8dc00217fa18b8b66", "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
+	{"3ae7937dd790315beb0f48330e8642237c61550a", "If the enemy is within range, then so are you."},
+	{"410a2b296df92b9a47412b13281df8f830a9f44b", "It's well we cannot hear the screams/That we create in others' dreams."},
+	{"841e7c85ca1adcddbdd0187f1289acb5c642f7f5", "You remind me of a TV show, but that's all right: I watch it anyway."},
+	{"163173b825d03b952601376b25212df66763e1db", "C is as portable as Stonehedge!!"},
+	{"32b0377f2687eb88e22106f133c586ab314d5279", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+	{"0885aaf99b569542fd165fa44e322718f4a984e0", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
+	{"6627d6904d71420b0bf3886ab629623538689f45", "How can you write a big system without C++?  -Paul Glick"},
+}
+
+func TestGolden(t *testing.T) {
+	for i := 0; i < len(golden); i++ {
+		g := golden[i]
+		s := fmt.Sprintf("%x", Sum([]byte(g.in)))
+		if s != g.out {
+			t.Fatalf("Sum function: sha1(%s) = %s want %s", g.in, s, g.out)
+		}
+		c := New()
+		for j := 0; j < 3; j++ {
+			if j < 2 {
+				io.WriteString(c, g.in)
+			} else {
+				io.WriteString(c, g.in[0:len(g.in)/2])
+				c.Sum(nil)
+				io.WriteString(c, g.in[len(g.in)/2:])
+			}
+			s := fmt.Sprintf("%x", c.Sum(nil))
+			if s != g.out {
+				t.Fatalf("sha1[%d](%s) = %s want %s", j, g.in, s, g.out)
+			}
+			c.Reset()
+		}
+	}
+}
+
+func TestSize(t *testing.T) {
+	c := New()
+	if got := c.Size(); got != Size {
+		t.Errorf("Size = %d; want %d", got, Size)
+	}
+}
+
+func TestBlockSize(t *testing.T) {
+	c := New()
+	if got := c.BlockSize(); got != BlockSize {
+		t.Errorf("BlockSize = %d; want %d", got, BlockSize)
+	}
+}
+
+// Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match.
+func TestBlockGeneric(t *testing.T) {
+	gen, asm := New().(*digest), New().(*digest)
+	buf := make([]byte, BlockSize*20) // arbitrary factor
+	rand.Read(buf)
+	blockGeneric(gen, buf)
+	block(asm, buf)
+	if *gen != *asm {
+		t.Error("block and blockGeneric resulted in different states")
+	}
+}
+
+var bench = New()
+var buf = make([]byte, 8192)
+
+func benchmarkSize(b *testing.B, size int) {
+	b.SetBytes(int64(size))
+	sum := make([]byte, bench.Size())
+	for i := 0; i < b.N; i++ {
+		bench.Reset()
+		bench.Write(buf[:size])
+		bench.Sum(sum[:0])
+	}
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+	benchmarkSize(b, 8)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+	benchmarkSize(b, 1024)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+	benchmarkSize(b, 8192)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/sha1/sha1block.go b/third_party/gofrontend/libgo/go/crypto/sha1/sha1block.go
new file mode 100644
index 0000000..fde3c98
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha1/sha1block.go
@@ -0,0 +1,90 @@
+// 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 sha1
+
+const (
+	_K0 = 0x5A827999
+	_K1 = 0x6ED9EBA1
+	_K2 = 0x8F1BBCDC
+	_K3 = 0xCA62C1D6
+)
+
+// blockGeneric is a portable, pure Go version of the SHA1 block step.
+// It's used by sha1block_generic.go and tests.
+func blockGeneric(dig *digest, p []byte) {
+	var w [16]uint32
+
+	h0, h1, h2, h3, h4 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4]
+	for len(p) >= chunk {
+		// Can interlace the computation of w with the
+		// rounds below if needed for speed.
+		for i := 0; i < 16; i++ {
+			j := i * 4
+			w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
+		}
+
+		a, b, c, d, e := h0, h1, h2, h3, h4
+
+		// Each of the four 20-iteration rounds
+		// differs only in the computation of f and
+		// the choice of K (_K0, _K1, etc).
+		i := 0
+		for ; i < 16; i++ {
+			f := b&c | (^b)&d
+			a5 := a<<5 | a>>(32-5)
+			b30 := b<<30 | b>>(32-30)
+			t := a5 + f + e + w[i&0xf] + _K0
+			a, b, c, d, e = t, a, b30, c, d
+		}
+		for ; i < 20; i++ {
+			tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+			w[i&0xf] = tmp<<1 | tmp>>(32-1)
+
+			f := b&c | (^b)&d
+			a5 := a<<5 | a>>(32-5)
+			b30 := b<<30 | b>>(32-30)
+			t := a5 + f + e + w[i&0xf] + _K0
+			a, b, c, d, e = t, a, b30, c, d
+		}
+		for ; i < 40; i++ {
+			tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+			w[i&0xf] = tmp<<1 | tmp>>(32-1)
+			f := b ^ c ^ d
+			a5 := a<<5 | a>>(32-5)
+			b30 := b<<30 | b>>(32-30)
+			t := a5 + f + e + w[i&0xf] + _K1
+			a, b, c, d, e = t, a, b30, c, d
+		}
+		for ; i < 60; i++ {
+			tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+			w[i&0xf] = tmp<<1 | tmp>>(32-1)
+			f := ((b | c) & d) | (b & c)
+
+			a5 := a<<5 | a>>(32-5)
+			b30 := b<<30 | b>>(32-30)
+			t := a5 + f + e + w[i&0xf] + _K2
+			a, b, c, d, e = t, a, b30, c, d
+		}
+		for ; i < 80; i++ {
+			tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+			w[i&0xf] = tmp<<1 | tmp>>(32-1)
+			f := b ^ c ^ d
+			a5 := a<<5 | a>>(32-5)
+			b30 := b<<30 | b>>(32-30)
+			t := a5 + f + e + w[i&0xf] + _K3
+			a, b, c, d, e = t, a, b30, c, d
+		}
+
+		h0 += a
+		h1 += b
+		h2 += c
+		h3 += d
+		h4 += e
+
+		p = p[chunk:]
+	}
+
+	dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4] = h0, h1, h2, h3, h4
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/sha1/sha1block_decl.go b/third_party/gofrontend/libgo/go/crypto/sha1/sha1block_decl.go
new file mode 100644
index 0000000..24e521a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha1/sha1block_decl.go
@@ -0,0 +1,11 @@
+// Copyright 2013 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.
+
+// +build amd64 amd64p32 arm 386
+
+package sha1
+
+//go:noescape
+
+func block(dig *digest, p []byte)
diff --git a/third_party/gofrontend/libgo/go/crypto/sha1/sha1block_generic.go b/third_party/gofrontend/libgo/go/crypto/sha1/sha1block_generic.go
new file mode 100644
index 0000000..696e26b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha1/sha1block_generic.go
@@ -0,0 +1,9 @@
+// Copyright 2014 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.
+
+// +build !amd64,!amd64p32,!386,!arm
+
+package sha1
+
+var block = blockGeneric
diff --git a/third_party/gofrontend/libgo/go/crypto/sha256/sha256.go b/third_party/gofrontend/libgo/go/crypto/sha256/sha256.go
new file mode 100644
index 0000000..d84cebf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha256/sha256.go
@@ -0,0 +1,193 @@
+// 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 sha256 implements the SHA224 and SHA256 hash algorithms as defined
+// in FIPS 180-4.
+package sha256
+
+import (
+	"crypto"
+	"hash"
+)
+
+func init() {
+	crypto.RegisterHash(crypto.SHA224, New224)
+	crypto.RegisterHash(crypto.SHA256, New)
+}
+
+// The size of a SHA256 checksum in bytes.
+const Size = 32
+
+// The size of a SHA224 checksum in bytes.
+const Size224 = 28
+
+// The blocksize of SHA256 and SHA224 in bytes.
+const BlockSize = 64
+
+const (
+	chunk     = 64
+	init0     = 0x6A09E667
+	init1     = 0xBB67AE85
+	init2     = 0x3C6EF372
+	init3     = 0xA54FF53A
+	init4     = 0x510E527F
+	init5     = 0x9B05688C
+	init6     = 0x1F83D9AB
+	init7     = 0x5BE0CD19
+	init0_224 = 0xC1059ED8
+	init1_224 = 0x367CD507
+	init2_224 = 0x3070DD17
+	init3_224 = 0xF70E5939
+	init4_224 = 0xFFC00B31
+	init5_224 = 0x68581511
+	init6_224 = 0x64F98FA7
+	init7_224 = 0xBEFA4FA4
+)
+
+// digest represents the partial evaluation of a checksum.
+type digest struct {
+	h     [8]uint32
+	x     [chunk]byte
+	nx    int
+	len   uint64
+	is224 bool // mark if this digest is SHA-224
+}
+
+func (d *digest) Reset() {
+	if !d.is224 {
+		d.h[0] = init0
+		d.h[1] = init1
+		d.h[2] = init2
+		d.h[3] = init3
+		d.h[4] = init4
+		d.h[5] = init5
+		d.h[6] = init6
+		d.h[7] = init7
+	} else {
+		d.h[0] = init0_224
+		d.h[1] = init1_224
+		d.h[2] = init2_224
+		d.h[3] = init3_224
+		d.h[4] = init4_224
+		d.h[5] = init5_224
+		d.h[6] = init6_224
+		d.h[7] = init7_224
+	}
+	d.nx = 0
+	d.len = 0
+}
+
+// New returns a new hash.Hash computing the SHA256 checksum.
+func New() hash.Hash {
+	d := new(digest)
+	d.Reset()
+	return d
+}
+
+// New224 returns a new hash.Hash computing the SHA224 checksum.
+func New224() hash.Hash {
+	d := new(digest)
+	d.is224 = true
+	d.Reset()
+	return d
+}
+
+func (d *digest) Size() int {
+	if !d.is224 {
+		return Size
+	}
+	return Size224
+}
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
+	nn = len(p)
+	d.len += uint64(nn)
+	if d.nx > 0 {
+		n := copy(d.x[d.nx:], p)
+		d.nx += n
+		if d.nx == chunk {
+			block(d, d.x[:])
+			d.nx = 0
+		}
+		p = p[n:]
+	}
+	if len(p) >= chunk {
+		n := len(p) &^ (chunk - 1)
+		block(d, p[:n])
+		p = p[n:]
+	}
+	if len(p) > 0 {
+		d.nx = copy(d.x[:], p)
+	}
+	return
+}
+
+func (d0 *digest) Sum(in []byte) []byte {
+	// Make a copy of d0 so that caller can keep writing and summing.
+	d := *d0
+	hash := d.checkSum()
+	if d.is224 {
+		return append(in, hash[:Size224]...)
+	}
+	return append(in, hash[:]...)
+}
+
+func (d *digest) checkSum() [Size]byte {
+	len := d.len
+	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
+	var tmp [64]byte
+	tmp[0] = 0x80
+	if len%64 < 56 {
+		d.Write(tmp[0 : 56-len%64])
+	} else {
+		d.Write(tmp[0 : 64+56-len%64])
+	}
+
+	// Length in bits.
+	len <<= 3
+	for i := uint(0); i < 8; i++ {
+		tmp[i] = byte(len >> (56 - 8*i))
+	}
+	d.Write(tmp[0:8])
+
+	if d.nx != 0 {
+		panic("d.nx != 0")
+	}
+
+	h := d.h[:]
+	if d.is224 {
+		h = d.h[:7]
+	}
+
+	var digest [Size]byte
+	for i, s := range h {
+		digest[i*4] = byte(s >> 24)
+		digest[i*4+1] = byte(s >> 16)
+		digest[i*4+2] = byte(s >> 8)
+		digest[i*4+3] = byte(s)
+	}
+
+	return digest
+}
+
+// Sum256 returns the SHA256 checksum of the data.
+func Sum256(data []byte) [Size]byte {
+	var d digest
+	d.Reset()
+	d.Write(data)
+	return d.checkSum()
+}
+
+// Sum224 returns the SHA224 checksum of the data.
+func Sum224(data []byte) (sum224 [Size224]byte) {
+	var d digest
+	d.is224 = true
+	d.Reset()
+	d.Write(data)
+	sum := d.checkSum()
+	copy(sum224[:], sum[:Size224])
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/sha256/sha256_test.go b/third_party/gofrontend/libgo/go/crypto/sha256/sha256_test.go
new file mode 100644
index 0000000..1d883d3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha256/sha256_test.go
@@ -0,0 +1,176 @@
+// 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.
+
+// SHA256 hash algorithm.  See FIPS 180-2.
+
+package sha256
+
+import (
+	"fmt"
+	"io"
+	"testing"
+)
+
+type sha256Test struct {
+	out string
+	in  string
+}
+
+var golden = []sha256Test{
+	{"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
+	{"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", "a"},
+	{"fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603", "ab"},
+	{"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "abc"},
+	{"88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589", "abcd"},
+	{"36bbe50ed96841d10443bcb670d6554f0a34b761be67ec9c4a8ad2c0c44ca42c", "abcde"},
+	{"bef57ec7f53a6d40beb640a780a639c83bc29ac8a9816f1fc6c5c6dcd93c4721", "abcdef"},
+	{"7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a", "abcdefg"},
+	{"9c56cc51b374c3ba189210d5b6d4bf57790d351c96c47c02190ecf1e430635ab", "abcdefgh"},
+	{"19cc02f26df43cc571bc9ed7b0c4d29224a3ec229529221725ef76d021c8326f", "abcdefghi"},
+	{"72399361da6a7754fec986dca5b7cbaf1c810a28ded4abaf56b2106d06cb78b0", "abcdefghij"},
+	{"a144061c271f152da4d151034508fed1c138b8c976339de229c3bb6d4bbb4fce", "Discard medicine more than two years old."},
+	{"6dae5caa713a10ad04b46028bf6dad68837c581616a1589a265a11288d4bb5c4", "He who has a shady past knows that nice guys finish last."},
+	{"ae7a702a9509039ddbf29f0765e70d0001177914b86459284dab8b348c2dce3f", "I wouldn't marry him with a ten foot pole."},
+	{"6748450b01c568586715291dfa3ee018da07d36bb7ea6f180c1af6270215c64f", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+	{"14b82014ad2b11f661b5ae6a99b75105c2ffac278cd071cd6c05832793635774", "The days of the digital watch are numbered.  -Tom Stoppard"},
+	{"7102cfd76e2e324889eece5d6c41921b1e142a4ac5a2692be78803097f6a48d8", "Nepal premier won't resign."},
+	{"23b1018cd81db1d67983c5f7417c44da9deb582459e378d7a068552ea649dc9f", "For every action there is an equal and opposite government program."},
+	{"8001f190dfb527261c4cfcab70c98e8097a7a1922129bc4096950e57c7999a5a", "His money is twice tainted: 'taint yours and 'taint mine."},
+	{"8c87deb65505c3993eb24b7a150c4155e82eee6960cf0c3a8114ff736d69cad5", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+	{"bfb0a67a19cdec3646498b2e0f751bddc41bba4b7f30081b0b932aad214d16d7", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+	{"7f9a0b9bf56332e19f5a0ec1ad9c1425a153da1c624868fda44561d6b74daf36", "size:  a.out:  bad magic"},
+	{"b13f81b8aad9e3666879af19886140904f7f429ef083286195982a7588858cfc", "The major problem is with sendmail.  -Mark Horton"},
+	{"b26c38d61519e894480c70c8374ea35aa0ad05b2ae3d6674eec5f52a69305ed4", "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
+	{"049d5e26d4f10222cd841a119e38bd8d2e0d1129728688449575d4ff42b842c1", "If the enemy is within range, then so are you."},
+	{"0e116838e3cc1c1a14cd045397e29b4d087aa11b0853fc69ec82e90330d60949", "It's well we cannot hear the screams/That we create in others' dreams."},
+	{"4f7d8eb5bcf11de2a56b971021a444aa4eafd6ecd0f307b5109e4e776cd0fe46", "You remind me of a TV show, but that's all right: I watch it anyway."},
+	{"61c0cc4c4bd8406d5120b3fb4ebc31ce87667c162f29468b3c779675a85aebce", "C is as portable as Stonehedge!!"},
+	{"1fb2eb3688093c4a3f80cd87a5547e2ce940a4f923243a79a2a1e242220693ac", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+	{"395585ce30617b62c80b93e8208ce866d4edc811a177fdb4b82d3911d8696423", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
+	{"4f9b189a13d030838269dce846b16a1ce9ce81fe63e65de2f636863336a98fe6", "How can you write a big system without C++?  -Paul Glick"},
+}
+
+var golden224 = []sha256Test{
+	{"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", ""},
+	{"abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5", "a"},
+	{"db3cda86d4429a1d39c148989566b38f7bda0156296bd364ba2f878b", "ab"},
+	{"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", "abc"},
+	{"a76654d8e3550e9a2d67a0eeb6c67b220e5885eddd3fde135806e601", "abcd"},
+	{"bdd03d560993e675516ba5a50638b6531ac2ac3d5847c61916cfced6", "abcde"},
+	{"7043631cb415556a275a4ebecb802c74ee9f6153908e1792a90b6a98", "abcdef"},
+	{"d1884e711701ad81abe0c77a3b0ea12e19ba9af64077286c72fc602d", "abcdefg"},
+	{"17eb7d40f0356f8598e89eafad5f6c759b1f822975d9c9b737c8a517", "abcdefgh"},
+	{"aeb35915346c584db820d2de7af3929ffafef9222a9bcb26516c7334", "abcdefghi"},
+	{"d35e1e5af29ddb0d7e154357df4ad9842afee527c689ee547f753188", "abcdefghij"},
+	{"19297f1cef7ddc8a7e947f5c5a341e10f7245045e425db67043988d7", "Discard medicine more than two years old."},
+	{"0f10c2eb436251f777fbbd125e260d36aecf180411726c7c885f599a", "He who has a shady past knows that nice guys finish last."},
+	{"4d1842104919f314cad8a3cd20b3cba7e8ed3e7abed62b57441358f6", "I wouldn't marry him with a ten foot pole."},
+	{"a8ba85c6fe0c48fbffc72bbb2f03fcdbc87ae2dc7a56804d1590fb3b", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+	{"5543fbab26e67e8885b1a852d567d1cb8b9bfe42e0899584c50449a9", "The days of the digital watch are numbered.  -Tom Stoppard"},
+	{"65ca107390f5da9efa05d28e57b221657edc7e43a9a18fb15b053ddb", "Nepal premier won't resign."},
+	{"84953962be366305a9cc9b5cd16ed019edc37ac96c0deb3e12cca116", "For every action there is an equal and opposite government program."},
+	{"35a189ce987151dfd00b3577583cc6a74b9869eecf894459cb52038d", "His money is twice tainted: 'taint yours and 'taint mine."},
+	{"2fc333713983edfd4ef2c0da6fb6d6415afb94987c91e4069eb063e6", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+	{"cbe32d38d577a1b355960a4bc3c659c2dc4670859a19777a875842c4", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+	{"a2dc118ce959e027576413a7b440c875cdc8d40df9141d6ef78a57e1", "size:  a.out:  bad magic"},
+	{"d10787e24052bcff26dc484787a54ed819e4e4511c54890ee977bf81", "The major problem is with sendmail.  -Mark Horton"},
+	{"62efcf16ab8a893acdf2f348aaf06b63039ff1bf55508c830532c9fb", "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
+	{"3e9b7e4613c59f58665104c5fa86c272db5d3a2ff30df5bb194a5c99", "If the enemy is within range, then so are you."},
+	{"5999c208b8bdf6d471bb7c359ac5b829e73a8211dff686143a4e7f18", "It's well we cannot hear the screams/That we create in others' dreams."},
+	{"3b2d67ff54eabc4ef737b14edf87c64280ef582bcdf2a6d56908b405", "You remind me of a TV show, but that's all right: I watch it anyway."},
+	{"d0733595d20e4d3d6b5c565a445814d1bbb2fd08b9a3b8ffb97930c6", "C is as portable as Stonehedge!!"},
+	{"43fb8aeed8a833175c9295c1165415f98c866ef08a4922959d673507", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+	{"ec18e66e93afc4fb1604bc2baedbfd20b44c43d76e65c0996d7851c6", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
+	{"86ed2eaa9c75ba98396e5c9fb2f679ecf0ea2ed1e0ee9ceecb4a9332", "How can you write a big system without C++?  -Paul Glick"},
+}
+
+func TestGolden(t *testing.T) {
+	for i := 0; i < len(golden); i++ {
+		g := golden[i]
+		s := fmt.Sprintf("%x", Sum256([]byte(g.in)))
+		if s != g.out {
+			t.Fatalf("Sum256 function: sha256(%s) = %s want %s", g.in, s, g.out)
+		}
+		c := New()
+		for j := 0; j < 3; j++ {
+			if j < 2 {
+				io.WriteString(c, g.in)
+			} else {
+				io.WriteString(c, g.in[0:len(g.in)/2])
+				c.Sum(nil)
+				io.WriteString(c, g.in[len(g.in)/2:])
+			}
+			s := fmt.Sprintf("%x", c.Sum(nil))
+			if s != g.out {
+				t.Fatalf("sha256[%d](%s) = %s want %s", j, g.in, s, g.out)
+			}
+			c.Reset()
+		}
+	}
+	for i := 0; i < len(golden224); i++ {
+		g := golden224[i]
+		s := fmt.Sprintf("%x", Sum224([]byte(g.in)))
+		if s != g.out {
+			t.Fatalf("Sum224 function: sha224(%s) = %s want %s", g.in, s, g.out)
+		}
+		c := New224()
+		for j := 0; j < 3; j++ {
+			if j < 2 {
+				io.WriteString(c, g.in)
+			} else {
+				io.WriteString(c, g.in[0:len(g.in)/2])
+				c.Sum(nil)
+				io.WriteString(c, g.in[len(g.in)/2:])
+			}
+			s := fmt.Sprintf("%x", c.Sum(nil))
+			if s != g.out {
+				t.Fatalf("sha224[%d](%s) = %s want %s", j, g.in, s, g.out)
+			}
+			c.Reset()
+		}
+	}
+}
+
+func TestSize(t *testing.T) {
+	c := New()
+	if got := c.Size(); got != Size {
+		t.Errorf("Size = %d; want %d", got, Size)
+	}
+	c = New224()
+	if got := c.Size(); got != Size224 {
+		t.Errorf("New224.Size = %d; want %d", got, Size224)
+	}
+}
+
+func TestBlockSize(t *testing.T) {
+	c := New()
+	if got := c.BlockSize(); got != BlockSize {
+		t.Errorf("BlockSize = %d want %d", got, BlockSize)
+	}
+}
+
+var bench = New()
+var buf = make([]byte, 8192)
+
+func benchmarkSize(b *testing.B, size int) {
+	b.SetBytes(int64(size))
+	sum := make([]byte, bench.Size())
+	for i := 0; i < b.N; i++ {
+		bench.Reset()
+		bench.Write(buf[:size])
+		bench.Sum(sum[:0])
+	}
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+	benchmarkSize(b, 8)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+	benchmarkSize(b, 1024)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+	benchmarkSize(b, 8192)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/sha256/sha256block.go b/third_party/gofrontend/libgo/go/crypto/sha256/sha256block.go
new file mode 100644
index 0000000..ca5efd1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha256/sha256block.go
@@ -0,0 +1,128 @@
+// 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.
+
+// +build !386,!amd64
+
+// SHA256 block step.
+// In its own file so that a faster assembly or C version
+// can be substituted easily.
+
+package sha256
+
+var _K = []uint32{
+	0x428a2f98,
+	0x71374491,
+	0xb5c0fbcf,
+	0xe9b5dba5,
+	0x3956c25b,
+	0x59f111f1,
+	0x923f82a4,
+	0xab1c5ed5,
+	0xd807aa98,
+	0x12835b01,
+	0x243185be,
+	0x550c7dc3,
+	0x72be5d74,
+	0x80deb1fe,
+	0x9bdc06a7,
+	0xc19bf174,
+	0xe49b69c1,
+	0xefbe4786,
+	0x0fc19dc6,
+	0x240ca1cc,
+	0x2de92c6f,
+	0x4a7484aa,
+	0x5cb0a9dc,
+	0x76f988da,
+	0x983e5152,
+	0xa831c66d,
+	0xb00327c8,
+	0xbf597fc7,
+	0xc6e00bf3,
+	0xd5a79147,
+	0x06ca6351,
+	0x14292967,
+	0x27b70a85,
+	0x2e1b2138,
+	0x4d2c6dfc,
+	0x53380d13,
+	0x650a7354,
+	0x766a0abb,
+	0x81c2c92e,
+	0x92722c85,
+	0xa2bfe8a1,
+	0xa81a664b,
+	0xc24b8b70,
+	0xc76c51a3,
+	0xd192e819,
+	0xd6990624,
+	0xf40e3585,
+	0x106aa070,
+	0x19a4c116,
+	0x1e376c08,
+	0x2748774c,
+	0x34b0bcb5,
+	0x391c0cb3,
+	0x4ed8aa4a,
+	0x5b9cca4f,
+	0x682e6ff3,
+	0x748f82ee,
+	0x78a5636f,
+	0x84c87814,
+	0x8cc70208,
+	0x90befffa,
+	0xa4506ceb,
+	0xbef9a3f7,
+	0xc67178f2,
+}
+
+func block(dig *digest, p []byte) {
+	var w [64]uint32
+	h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
+	for len(p) >= chunk {
+		// Can interlace the computation of w with the
+		// rounds below if needed for speed.
+		for i := 0; i < 16; i++ {
+			j := i * 4
+			w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
+		}
+		for i := 16; i < 64; i++ {
+			v1 := w[i-2]
+			t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10)
+			v2 := w[i-15]
+			t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3)
+			w[i] = t1 + w[i-7] + t2 + w[i-16]
+		}
+
+		a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7
+
+		for i := 0; i < 64; i++ {
+			t1 := h + ((e>>6 | e<<(32-6)) ^ (e>>11 | e<<(32-11)) ^ (e>>25 | e<<(32-25))) + ((e & f) ^ (^e & g)) + _K[i] + w[i]
+
+			t2 := ((a>>2 | a<<(32-2)) ^ (a>>13 | a<<(32-13)) ^ (a>>22 | a<<(32-22))) + ((a & b) ^ (a & c) ^ (b & c))
+
+			h = g
+			g = f
+			f = e
+			e = d + t1
+			d = c
+			c = b
+			b = a
+			a = t1 + t2
+		}
+
+		h0 += a
+		h1 += b
+		h2 += c
+		h3 += d
+		h4 += e
+		h5 += f
+		h6 += g
+		h7 += h
+
+		p = p[chunk:]
+	}
+
+	dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/sha256/sha256block_decl.go b/third_party/gofrontend/libgo/go/crypto/sha256/sha256block_decl.go
new file mode 100644
index 0000000..a50c978
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha256/sha256block_decl.go
@@ -0,0 +1,11 @@
+// Copyright 2013 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.
+
+// +build 386 amd64
+
+package sha256
+
+//go:noescape
+
+func block(dig *digest, p []byte)
diff --git a/third_party/gofrontend/libgo/go/crypto/sha512/sha512.go b/third_party/gofrontend/libgo/go/crypto/sha512/sha512.go
new file mode 100644
index 0000000..bca7a91
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha512/sha512.go
@@ -0,0 +1,198 @@
+// 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 sha512 implements the SHA384 and SHA512 hash algorithms as defined
+// in FIPS 180-2.
+package sha512
+
+import (
+	"crypto"
+	"hash"
+)
+
+func init() {
+	crypto.RegisterHash(crypto.SHA384, New384)
+	crypto.RegisterHash(crypto.SHA512, New)
+}
+
+// The size of a SHA512 checksum in bytes.
+const Size = 64
+
+// The size of a SHA384 checksum in bytes.
+const Size384 = 48
+
+// The blocksize of SHA512 and SHA384 in bytes.
+const BlockSize = 128
+
+const (
+	chunk     = 128
+	init0     = 0x6a09e667f3bcc908
+	init1     = 0xbb67ae8584caa73b
+	init2     = 0x3c6ef372fe94f82b
+	init3     = 0xa54ff53a5f1d36f1
+	init4     = 0x510e527fade682d1
+	init5     = 0x9b05688c2b3e6c1f
+	init6     = 0x1f83d9abfb41bd6b
+	init7     = 0x5be0cd19137e2179
+	init0_384 = 0xcbbb9d5dc1059ed8
+	init1_384 = 0x629a292a367cd507
+	init2_384 = 0x9159015a3070dd17
+	init3_384 = 0x152fecd8f70e5939
+	init4_384 = 0x67332667ffc00b31
+	init5_384 = 0x8eb44a8768581511
+	init6_384 = 0xdb0c2e0d64f98fa7
+	init7_384 = 0x47b5481dbefa4fa4
+)
+
+// digest represents the partial evaluation of a checksum.
+type digest struct {
+	h     [8]uint64
+	x     [chunk]byte
+	nx    int
+	len   uint64
+	is384 bool // mark if this digest is SHA-384
+}
+
+func (d *digest) Reset() {
+	if !d.is384 {
+		d.h[0] = init0
+		d.h[1] = init1
+		d.h[2] = init2
+		d.h[3] = init3
+		d.h[4] = init4
+		d.h[5] = init5
+		d.h[6] = init6
+		d.h[7] = init7
+	} else {
+		d.h[0] = init0_384
+		d.h[1] = init1_384
+		d.h[2] = init2_384
+		d.h[3] = init3_384
+		d.h[4] = init4_384
+		d.h[5] = init5_384
+		d.h[6] = init6_384
+		d.h[7] = init7_384
+	}
+	d.nx = 0
+	d.len = 0
+}
+
+// New returns a new hash.Hash computing the SHA512 checksum.
+func New() hash.Hash {
+	d := new(digest)
+	d.Reset()
+	return d
+}
+
+// New384 returns a new hash.Hash computing the SHA384 checksum.
+func New384() hash.Hash {
+	d := new(digest)
+	d.is384 = true
+	d.Reset()
+	return d
+}
+
+func (d *digest) Size() int {
+	if !d.is384 {
+		return Size
+	}
+	return Size384
+}
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
+	nn = len(p)
+	d.len += uint64(nn)
+	if d.nx > 0 {
+		n := copy(d.x[d.nx:], p)
+		d.nx += n
+		if d.nx == chunk {
+			block(d, d.x[:])
+			d.nx = 0
+		}
+		p = p[n:]
+	}
+	if len(p) >= chunk {
+		n := len(p) &^ (chunk - 1)
+		block(d, p[:n])
+		p = p[n:]
+	}
+	if len(p) > 0 {
+		d.nx = copy(d.x[:], p)
+	}
+	return
+}
+
+func (d0 *digest) Sum(in []byte) []byte {
+	// Make a copy of d0 so that caller can keep writing and summing.
+	d := new(digest)
+	*d = *d0
+	hash := d.checkSum()
+	if d.is384 {
+		return append(in, hash[:Size384]...)
+	}
+	return append(in, hash[:]...)
+}
+
+func (d *digest) checkSum() [Size]byte {
+	// Padding.  Add a 1 bit and 0 bits until 112 bytes mod 128.
+	len := d.len
+	var tmp [128]byte
+	tmp[0] = 0x80
+	if len%128 < 112 {
+		d.Write(tmp[0 : 112-len%128])
+	} else {
+		d.Write(tmp[0 : 128+112-len%128])
+	}
+
+	// Length in bits.
+	len <<= 3
+	for i := uint(0); i < 16; i++ {
+		tmp[i] = byte(len >> (120 - 8*i))
+	}
+	d.Write(tmp[0:16])
+
+	if d.nx != 0 {
+		panic("d.nx != 0")
+	}
+
+	h := d.h[:]
+	if d.is384 {
+		h = d.h[:6]
+	}
+
+	var digest [Size]byte
+	for i, s := range h {
+		digest[i*8] = byte(s >> 56)
+		digest[i*8+1] = byte(s >> 48)
+		digest[i*8+2] = byte(s >> 40)
+		digest[i*8+3] = byte(s >> 32)
+		digest[i*8+4] = byte(s >> 24)
+		digest[i*8+5] = byte(s >> 16)
+		digest[i*8+6] = byte(s >> 8)
+		digest[i*8+7] = byte(s)
+	}
+
+	return digest
+}
+
+// Sum512 returns the SHA512 checksum of the data.
+func Sum512(data []byte) [Size]byte {
+	var d digest
+	d.Reset()
+	d.Write(data)
+	return d.checkSum()
+}
+
+// Sum384 returns the SHA384 checksum of the data.
+func Sum384(data []byte) (sum384 [Size384]byte) {
+	var d digest
+	d.is384 = true
+	d.Reset()
+	d.Write(data)
+	sum := d.checkSum()
+	copy(sum384[:], sum[:Size384])
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/sha512/sha512_test.go b/third_party/gofrontend/libgo/go/crypto/sha512/sha512_test.go
new file mode 100644
index 0000000..541860f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha512/sha512_test.go
@@ -0,0 +1,176 @@
+// 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.
+
+// SHA512 hash algorithm.  See FIPS 180-2.
+
+package sha512
+
+import (
+	"fmt"
+	"io"
+	"testing"
+)
+
+type sha512Test struct {
+	out string
+	in  string
+}
+
+var golden = []sha512Test{
+	{"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", ""},
+	{"1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75", "a"},
+	{"2d408a0717ec188158278a796c689044361dc6fdde28d6f04973b80896e1823975cdbf12eb63f9e0591328ee235d80e9b5bf1aa6a44f4617ff3caf6400eb172d", "ab"},
+	{"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", "abc"},
+	{"d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f", "abcd"},
+	{"878ae65a92e86cac011a570d4c30a7eaec442b85ce8eca0c2952b5e3cc0628c2e79d889ad4d5c7c626986d452dd86374b6ffaa7cd8b67665bef2289a5c70b0a1", "abcde"},
+	{"e32ef19623e8ed9d267f657a81944b3d07adbb768518068e88435745564e8d4150a0a703be2a7d88b61e3d390c2bb97e2d4c311fdc69d6b1267f05f59aa920e7", "abcdef"},
+	{"d716a4188569b68ab1b6dfac178e570114cdf0ea3a1cc0e31486c3e41241bc6a76424e8c37ab26f096fc85ef9886c8cb634187f4fddff645fb099f1ff54c6b8c", "abcdefg"},
+	{"a3a8c81bc97c2560010d7389bc88aac974a104e0e2381220c6e084c4dccd1d2d17d4f86db31c2a851dc80e6681d74733c55dcd03dd96f6062cdda12a291ae6ce", "abcdefgh"},
+	{"f22d51d25292ca1d0f68f69aedc7897019308cc9db46efb75a03dd494fc7f126c010e8ade6a00a0c1a5f1b75d81e0ed5a93ce98dc9b833db7839247b1d9c24fe", "abcdefghi"},
+	{"ef6b97321f34b1fea2169a7db9e1960b471aa13302a988087357c520be957ca119c3ba68e6b4982c019ec89de3865ccf6a3cda1fe11e59f98d99f1502c8b9745", "abcdefghij"},
+	{"2210d99af9c8bdecda1b4beff822136753d8342505ddce37f1314e2cdbb488c6016bdaa9bd2ffa513dd5de2e4b50f031393d8ab61f773b0e0130d7381e0f8a1d", "Discard medicine more than two years old."},
+	{"a687a8985b4d8d0a24f115fe272255c6afaf3909225838546159c1ed685c211a203796ae8ecc4c81a5b6315919b3a64f10713da07e341fcdbb08541bf03066ce", "He who has a shady past knows that nice guys finish last."},
+	{"8ddb0392e818b7d585ab22769a50df660d9f6d559cca3afc5691b8ca91b8451374e42bcdabd64589ed7c91d85f626596228a5c8572677eb98bc6b624befb7af8", "I wouldn't marry him with a ten foot pole."},
+	{"26ed8f6ca7f8d44b6a8a54ae39640fa8ad5c673f70ee9ce074ba4ef0d483eea00bab2f61d8695d6b34df9c6c48ae36246362200ed820448bdc03a720366a87c6", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+	{"e5a14bf044be69615aade89afcf1ab0389d5fc302a884d403579d1386a2400c089b0dbb387ed0f463f9ee342f8244d5a38cfbc0e819da9529fbff78368c9a982", "The days of the digital watch are numbered.  -Tom Stoppard"},
+	{"420a1faa48919e14651bed45725abe0f7a58e0f099424c4e5a49194946e38b46c1f8034b18ef169b2e31050d1648e0b982386595f7df47da4b6fd18e55333015", "Nepal premier won't resign."},
+	{"d926a863beadb20134db07683535c72007b0e695045876254f341ddcccde132a908c5af57baa6a6a9c63e6649bba0c213dc05fadcf9abccea09f23dcfb637fbe", "For every action there is an equal and opposite government program."},
+	{"9a98dd9bb67d0da7bf83da5313dff4fd60a4bac0094f1b05633690ffa7f6d61de9a1d4f8617937d560833a9aaa9ccafe3fd24db418d0e728833545cadd3ad92d", "His money is twice tainted: 'taint yours and 'taint mine."},
+	{"d7fde2d2351efade52f4211d3746a0780a26eec3df9b2ed575368a8a1c09ec452402293a8ea4eceb5a4f60064ea29b13cdd86918cd7a4faf366160b009804107", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+	{"b0f35ffa2697359c33a56f5c0cf715c7aeed96da9905ca2698acadb08fbc9e669bf566b6bd5d61a3e86dc22999bcc9f2224e33d1d4f32a228cf9d0349e2db518", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+	{"3d2e5f91778c9e66f7e061293aaa8a8fc742dd3b2e4f483772464b1144189b49273e610e5cccd7a81a19ca1fa70f16b10f1a100a4d8c1372336be8484c64b311", "size:  a.out:  bad magic"},
+	{"b2f68ff58ac015efb1c94c908b0d8c2bf06f491e4de8e6302c49016f7f8a33eac3e959856c7fddbc464de618701338a4b46f76dbfaf9a1e5262b5f40639771c7", "The major problem is with sendmail.  -Mark Horton"},
+	{"d8c92db5fdf52cf8215e4df3b4909d29203ff4d00e9ad0b64a6a4e04dec5e74f62e7c35c7fb881bd5de95442123df8f57a489b0ae616bd326f84d10021121c57", "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
+	{"19a9f8dc0a233e464e8566ad3ca9b91e459a7b8c4780985b015776e1bf239a19bc233d0556343e2b0a9bc220900b4ebf4f8bdf89ff8efeaf79602d6849e6f72e", "If the enemy is within range, then so are you."},
+	{"00b4c41f307bde87301cdc5b5ab1ae9a592e8ecbb2021dd7bc4b34e2ace60741cc362560bec566ba35178595a91932b8d5357e2c9cec92d393b0fa7831852476", "It's well we cannot hear the screams/That we create in others' dreams."},
+	{"91eccc3d5375fd026e4d6787874b1dce201cecd8a27dbded5065728cb2d09c58a3d467bb1faf353bf7ba567e005245d5321b55bc344f7c07b91cb6f26c959be7", "You remind me of a TV show, but that's all right: I watch it anyway."},
+	{"fabbbe22180f1f137cfdc9556d2570e775d1ae02a597ded43a72a40f9b485d500043b7be128fb9fcd982b83159a0d99aa855a9e7cc4240c00dc01a9bdf8218d7", "C is as portable as Stonehedge!!"},
+	{"2ecdec235c1fa4fc2a154d8fba1dddb8a72a1ad73838b51d792331d143f8b96a9f6fcb0f34d7caa351fe6d88771c4f105040e0392f06e0621689d33b2f3ba92e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+	{"7ad681f6f96f82f7abfa7ecc0334e8fa16d3dc1cdc45b60b7af43fe4075d2357c0c1d60e98350f1afb1f2fe7a4d7cd2ad55b88e458e06b73c40b437331f5dab4", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
+	{"833f9248ab4a3b9e5131f745fda1ffd2dd435b30e965957e78291c7ab73605fd1912b0794e5c233ab0a12d205a39778d19b83515d6a47003f19cdee51d98c7e0", "How can you write a big system without C++?  -Paul Glick"},
+}
+
+var golden384 = []sha512Test{
+	{"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", ""},
+	{"54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31", "a"},
+	{"c7be03ba5bcaa384727076db0018e99248e1a6e8bd1b9ef58a9ec9dd4eeebb3f48b836201221175befa74ddc3d35afdd", "ab"},
+	{"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7", "abc"},
+	{"1165b3406ff0b52a3d24721f785462ca2276c9f454a116c2b2ba20171a7905ea5a026682eb659c4d5f115c363aa3c79b", "abcd"},
+	{"4c525cbeac729eaf4b4665815bc5db0c84fe6300068a727cf74e2813521565abc0ec57a37ee4d8be89d097c0d2ad52f0", "abcde"},
+	{"c6a4c65b227e7387b9c3e839d44869c4cfca3ef583dea64117859b808c1e3d8ae689e1e314eeef52a6ffe22681aa11f5", "abcdef"},
+	{"9f11fc131123f844c1226f429b6a0a6af0525d9f40f056c7fc16cdf1b06bda08e302554417a59fa7dcf6247421959d22", "abcdefg"},
+	{"9000cd7cada59d1d2eb82912f7f24e5e69cc5517f68283b005fa27c285b61e05edf1ad1a8a9bded6fd29eb87d75ad806", "abcdefgh"},
+	{"ef54915b60cf062b8dd0c29ae3cad69abe6310de63ac081f46ef019c5c90897caefd79b796cfa81139788a260ded52df", "abcdefghi"},
+	{"a12070030a02d86b0ddacd0d3a5b598344513d0a051e7355053e556a0055489c1555399b03342845c4adde2dc44ff66c", "abcdefghij"},
+	{"86f58ec2d74d1b7f8eb0c2ff0967316699639e8d4eb129de54bdf34c96cdbabe200d052149f2dd787f43571ba74670d4", "Discard medicine more than two years old."},
+	{"ae4a2b639ca9bfa04b1855d5a05fe7f230994f790891c6979103e2605f660c4c1262a48142dcbeb57a1914ba5f7c3fa7", "He who has a shady past knows that nice guys finish last."},
+	{"40ae213df6436eca952aa6841886fcdb82908ef1576a99c8f49bb9dd5023169f7c53035abdda0b54c302f4974e2105e7", "I wouldn't marry him with a ten foot pole."},
+	{"e7cf8b873c9bc950f06259aa54309f349cefa72c00d597aebf903e6519a50011dfe355afff064a10701c705693848df9", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+	{"c3d4f0f4047181c7d39d34703365f7bf70207183caf2c2f6145f04da895ef69124d9cdeb635da636c3a474e61024e29b", "The days of the digital watch are numbered.  -Tom Stoppard"},
+	{"a097aab567e167d5cf93676ed73252a69f9687cb3179bb2d27c9878119e94bf7b7c4b58dc90582edfaf66e11388ed714", "Nepal premier won't resign."},
+	{"5026ca45c41fc64712eb65065da92f6467541c78f8966d3fe2c8e3fb769a3ec14215f819654b47bd64f7f0eac17184f3", "For every action there is an equal and opposite government program."},
+	{"ac1cc0f5ac8d5f5514a7b738ac322b7fb52a161b449c3672e9b6a6ad1a5e4b26b001cf3bad24c56598676ca17d4b445a", "His money is twice tainted: 'taint yours and 'taint mine."},
+	{"722d10c5de371ec0c8c4b5247ac8a5f1d240d68c73f8da13d8b25f0166d6f309bf9561979a111a0049405771d201941a", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+	{"dc2d3ea18bfa10549c63bf2b75b39b5167a80c12aff0e05443168ea87ff149fb0eda5e0bd234eb5d48c7d02ffc5807f1", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+	{"1d67c969e2a945ae5346d2139760261504d4ba164c522443afe19ef3e29b152a4c52445489cfc9d7215e5a450e8e1e4e", "size:  a.out:  bad magic"},
+	{"5ff8e075e465646e7b73ef36d812c6e9f7d60fa6ea0e533e5569b4f73cde53cdd2cc787f33540af57cca3fe467d32fe0", "The major problem is with sendmail.  -Mark Horton"},
+	{"5bd0a997a67c9ae1979a894eb0cde403dde003c9b6f2c03cf21925c42ff4e1176e6df1ca005381612ef18457b9b7ec3b", "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
+	{"1eee6da33e7e54fc5be52ae23b94b16ba4d2a947ae4505c6a3edfc7401151ea5205ac01b669b56f27d8ef7f175ed7762", "If the enemy is within range, then so are you."},
+	{"76b06e9dea66bfbb1a96029426dc0dfd7830bd297eb447ff5358d94a87cd00c88b59df2493fef56ecbb5231073892ea9", "It's well we cannot hear the screams/That we create in others' dreams."},
+	{"12acaf21452cff586143e3f5db0bfdf7802c057e1adf2a619031c4e1b0ccc4208cf6cef8fe722bbaa2fb46a30d9135d8", "You remind me of a TV show, but that's all right: I watch it anyway."},
+	{"0fc23d7f4183efd186f0bc4fc5db867e026e2146b06cb3d52f4bdbd57d1740122caa853b41868b197b2ac759db39df88", "C is as portable as Stonehedge!!"},
+	{"bc805578a7f85d34a86a32976e1c34fe65cf815186fbef76f46ef99cda10723f971f3f1464d488243f5e29db7488598d", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+	{"b23918399a12ebf4431559eec3813eaf7412e875fd7464f16d581e473330842d2e96c6be49a7ce3f9bb0b8bc0fcbe0fe", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
+	{"1764b700eb1ead52a2fc33cc28975c2180f1b8faa5038d94cffa8d78154aab16e91dd787e7b0303948ebed62561542c8", "How can you write a big system without C++?  -Paul Glick"},
+}
+
+func TestGolden(t *testing.T) {
+	for i := 0; i < len(golden); i++ {
+		g := golden[i]
+		s := fmt.Sprintf("%x", Sum512([]byte(g.in)))
+		if s != g.out {
+			t.Fatalf("Sum512 function: sha512(%s) = %s want %s", g.in, s, g.out)
+		}
+		c := New()
+		for j := 0; j < 3; j++ {
+			if j < 2 {
+				io.WriteString(c, g.in)
+			} else {
+				io.WriteString(c, g.in[0:len(g.in)/2])
+				c.Sum(nil)
+				io.WriteString(c, g.in[len(g.in)/2:])
+			}
+			s := fmt.Sprintf("%x", c.Sum(nil))
+			if s != g.out {
+				t.Fatalf("sha512[%d](%s) = %s want %s", j, g.in, s, g.out)
+			}
+			c.Reset()
+		}
+	}
+	for i := 0; i < len(golden384); i++ {
+		g := golden384[i]
+		s := fmt.Sprintf("%x", Sum384([]byte(g.in)))
+		if s != g.out {
+			t.Fatalf("Sum384 function: sha384(%s) = %s want %s", g.in, s, g.out)
+		}
+		c := New384()
+		for j := 0; j < 3; j++ {
+			if j < 2 {
+				io.WriteString(c, g.in)
+			} else {
+				io.WriteString(c, g.in[0:len(g.in)/2])
+				c.Sum(nil)
+				io.WriteString(c, g.in[len(g.in)/2:])
+			}
+			s := fmt.Sprintf("%x", c.Sum(nil))
+			if s != g.out {
+				t.Fatalf("sha384[%d](%s) = %s want %s", j, g.in, s, g.out)
+			}
+			c.Reset()
+		}
+	}
+}
+
+func TestSize(t *testing.T) {
+	c := New()
+	if got := c.Size(); got != Size {
+		t.Errorf("Size = %d; want %d", got, Size)
+	}
+	c = New384()
+	if got := c.Size(); got != Size384 {
+		t.Errorf("New384.Size = %d; want %d", got, Size384)
+	}
+}
+
+func TestBlockSize(t *testing.T) {
+	c := New()
+	if got := c.BlockSize(); got != BlockSize {
+		t.Errorf("BlockSize = %d; want %d", got, BlockSize)
+	}
+}
+
+var bench = New()
+var buf = make([]byte, 8192)
+
+func benchmarkSize(b *testing.B, size int) {
+	b.SetBytes(int64(size))
+	sum := make([]byte, bench.Size())
+	for i := 0; i < b.N; i++ {
+		bench.Reset()
+		bench.Write(buf[:size])
+		bench.Sum(sum[:0])
+	}
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+	benchmarkSize(b, 8)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+	benchmarkSize(b, 1024)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+	benchmarkSize(b, 8192)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/sha512/sha512block.go b/third_party/gofrontend/libgo/go/crypto/sha512/sha512block.go
new file mode 100644
index 0000000..648ae8f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha512/sha512block.go
@@ -0,0 +1,144 @@
+// 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.
+
+// +build !amd64
+
+// SHA512 block step.
+// In its own file so that a faster assembly or C version
+// can be substituted easily.
+
+package sha512
+
+var _K = []uint64{
+	0x428a2f98d728ae22,
+	0x7137449123ef65cd,
+	0xb5c0fbcfec4d3b2f,
+	0xe9b5dba58189dbbc,
+	0x3956c25bf348b538,
+	0x59f111f1b605d019,
+	0x923f82a4af194f9b,
+	0xab1c5ed5da6d8118,
+	0xd807aa98a3030242,
+	0x12835b0145706fbe,
+	0x243185be4ee4b28c,
+	0x550c7dc3d5ffb4e2,
+	0x72be5d74f27b896f,
+	0x80deb1fe3b1696b1,
+	0x9bdc06a725c71235,
+	0xc19bf174cf692694,
+	0xe49b69c19ef14ad2,
+	0xefbe4786384f25e3,
+	0x0fc19dc68b8cd5b5,
+	0x240ca1cc77ac9c65,
+	0x2de92c6f592b0275,
+	0x4a7484aa6ea6e483,
+	0x5cb0a9dcbd41fbd4,
+	0x76f988da831153b5,
+	0x983e5152ee66dfab,
+	0xa831c66d2db43210,
+	0xb00327c898fb213f,
+	0xbf597fc7beef0ee4,
+	0xc6e00bf33da88fc2,
+	0xd5a79147930aa725,
+	0x06ca6351e003826f,
+	0x142929670a0e6e70,
+	0x27b70a8546d22ffc,
+	0x2e1b21385c26c926,
+	0x4d2c6dfc5ac42aed,
+	0x53380d139d95b3df,
+	0x650a73548baf63de,
+	0x766a0abb3c77b2a8,
+	0x81c2c92e47edaee6,
+	0x92722c851482353b,
+	0xa2bfe8a14cf10364,
+	0xa81a664bbc423001,
+	0xc24b8b70d0f89791,
+	0xc76c51a30654be30,
+	0xd192e819d6ef5218,
+	0xd69906245565a910,
+	0xf40e35855771202a,
+	0x106aa07032bbd1b8,
+	0x19a4c116b8d2d0c8,
+	0x1e376c085141ab53,
+	0x2748774cdf8eeb99,
+	0x34b0bcb5e19b48a8,
+	0x391c0cb3c5c95a63,
+	0x4ed8aa4ae3418acb,
+	0x5b9cca4f7763e373,
+	0x682e6ff3d6b2b8a3,
+	0x748f82ee5defb2fc,
+	0x78a5636f43172f60,
+	0x84c87814a1f0ab72,
+	0x8cc702081a6439ec,
+	0x90befffa23631e28,
+	0xa4506cebde82bde9,
+	0xbef9a3f7b2c67915,
+	0xc67178f2e372532b,
+	0xca273eceea26619c,
+	0xd186b8c721c0c207,
+	0xeada7dd6cde0eb1e,
+	0xf57d4f7fee6ed178,
+	0x06f067aa72176fba,
+	0x0a637dc5a2c898a6,
+	0x113f9804bef90dae,
+	0x1b710b35131c471b,
+	0x28db77f523047d84,
+	0x32caab7b40c72493,
+	0x3c9ebe0a15c9bebc,
+	0x431d67c49c100d4c,
+	0x4cc5d4becb3e42b6,
+	0x597f299cfc657e2a,
+	0x5fcb6fab3ad6faec,
+	0x6c44198c4a475817,
+}
+
+func block(dig *digest, p []byte) {
+	var w [80]uint64
+	h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
+	for len(p) >= chunk {
+		for i := 0; i < 16; i++ {
+			j := i * 8
+			w[i] = uint64(p[j])<<56 | uint64(p[j+1])<<48 | uint64(p[j+2])<<40 | uint64(p[j+3])<<32 |
+				uint64(p[j+4])<<24 | uint64(p[j+5])<<16 | uint64(p[j+6])<<8 | uint64(p[j+7])
+		}
+		for i := 16; i < 80; i++ {
+			v1 := w[i-2]
+			t1 := (v1>>19 | v1<<(64-19)) ^ (v1>>61 | v1<<(64-61)) ^ (v1 >> 6)
+			v2 := w[i-15]
+			t2 := (v2>>1 | v2<<(64-1)) ^ (v2>>8 | v2<<(64-8)) ^ (v2 >> 7)
+
+			w[i] = t1 + w[i-7] + t2 + w[i-16]
+		}
+
+		a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7
+
+		for i := 0; i < 80; i++ {
+			t1 := h + ((e>>14 | e<<(64-14)) ^ (e>>18 | e<<(64-18)) ^ (e>>41 | e<<(64-41))) + ((e & f) ^ (^e & g)) + _K[i] + w[i]
+
+			t2 := ((a>>28 | a<<(64-28)) ^ (a>>34 | a<<(64-34)) ^ (a>>39 | a<<(64-39))) + ((a & b) ^ (a & c) ^ (b & c))
+
+			h = g
+			g = f
+			f = e
+			e = d + t1
+			d = c
+			c = b
+			b = a
+			a = t1 + t2
+		}
+
+		h0 += a
+		h1 += b
+		h2 += c
+		h3 += d
+		h4 += e
+		h5 += f
+		h6 += g
+		h7 += h
+
+		p = p[chunk:]
+	}
+
+	dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/sha512/sha512block_decl.go b/third_party/gofrontend/libgo/go/crypto/sha512/sha512block_decl.go
new file mode 100644
index 0000000..bef99de
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/sha512/sha512block_decl.go
@@ -0,0 +1,11 @@
+// Copyright 2013 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.
+
+// +build amd64
+
+package sha512
+
+//go:noescape
+
+func block(dig *digest, p []byte)
diff --git a/third_party/gofrontend/libgo/go/crypto/subtle/constant_time.go b/third_party/gofrontend/libgo/go/crypto/subtle/constant_time.go
new file mode 100644
index 0000000..9c4b14a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/subtle/constant_time.go
@@ -0,0 +1,74 @@
+// 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 subtle implements functions that are often useful in cryptographic
+// code but require careful thought to use correctly.
+package subtle
+
+// ConstantTimeCompare returns 1 iff the two equal length slices, x
+// and y, have equal contents. The time taken is a function of the length of
+// the slices and is independent of the contents.
+func ConstantTimeCompare(x, y []byte) int {
+	if len(x) != len(y) {
+		panic("subtle: slices have different lengths")
+	}
+
+	var v byte
+
+	for i := 0; i < len(x); i++ {
+		v |= x[i] ^ y[i]
+	}
+
+	return ConstantTimeByteEq(v, 0)
+}
+
+// ConstantTimeSelect returns x if v is 1 and y if v is 0.
+// Its behavior is undefined if v takes any other value.
+func ConstantTimeSelect(v, x, y int) int { return ^(v-1)&x | (v-1)&y }
+
+// ConstantTimeByteEq returns 1 if x == y and 0 otherwise.
+func ConstantTimeByteEq(x, y uint8) int {
+	z := ^(x ^ y)
+	z &= z >> 4
+	z &= z >> 2
+	z &= z >> 1
+
+	return int(z)
+}
+
+// ConstantTimeEq returns 1 if x == y and 0 otherwise.
+func ConstantTimeEq(x, y int32) int {
+	z := ^(x ^ y)
+	z &= z >> 16
+	z &= z >> 8
+	z &= z >> 4
+	z &= z >> 2
+	z &= z >> 1
+
+	return int(z & 1)
+}
+
+// ConstantTimeCopy copies the contents of y into x (a slice of equal length)
+// if v == 1. If v == 0, x is left unchanged. Its behavior is undefined if v
+// takes any other value.
+func ConstantTimeCopy(v int, x, y []byte) {
+	if len(x) != len(y) {
+		panic("subtle: slices have different lengths")
+	}
+
+	xmask := byte(v - 1)
+	ymask := byte(^(v - 1))
+	for i := 0; i < len(x); i++ {
+		x[i] = x[i]&xmask | y[i]&ymask
+	}
+	return
+}
+
+// ConstantTimeLessOrEq returns 1 if x <= y and 0 otherwise.
+// Its behavior is undefined if x or y are negative or > 2**31 - 1.
+func ConstantTimeLessOrEq(x, y int) int {
+	x32 := int32(x)
+	y32 := int32(y)
+	return int(((x32 - y32 - 1) >> 31) & 1)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/subtle/constant_time_test.go b/third_party/gofrontend/libgo/go/crypto/subtle/constant_time_test.go
new file mode 100644
index 0000000..d8e321e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/subtle/constant_time_test.go
@@ -0,0 +1,125 @@
+// 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 subtle
+
+import (
+	"testing"
+	"testing/quick"
+)
+
+type TestConstantTimeCompareStruct struct {
+	a, b []byte
+	out  int
+}
+
+var testConstantTimeCompareData = []TestConstantTimeCompareStruct{
+	{[]byte{}, []byte{}, 1},
+	{[]byte{0x11}, []byte{0x11}, 1},
+	{[]byte{0x12}, []byte{0x11}, 0},
+}
+
+func TestConstantTimeCompare(t *testing.T) {
+	for i, test := range testConstantTimeCompareData {
+		if r := ConstantTimeCompare(test.a, test.b); r != test.out {
+			t.Errorf("#%d bad result (got %x, want %x)", i, r, test.out)
+		}
+	}
+}
+
+type TestConstantTimeByteEqStruct struct {
+	a, b uint8
+	out  int
+}
+
+var testConstandTimeByteEqData = []TestConstantTimeByteEqStruct{
+	{0, 0, 1},
+	{0, 1, 0},
+	{1, 0, 0},
+	{0xff, 0xff, 1},
+	{0xff, 0xfe, 0},
+}
+
+func byteEq(a, b uint8) int {
+	if a == b {
+		return 1
+	}
+	return 0
+}
+
+func TestConstantTimeByteEq(t *testing.T) {
+	for i, test := range testConstandTimeByteEqData {
+		if r := ConstantTimeByteEq(test.a, test.b); r != test.out {
+			t.Errorf("#%d bad result (got %x, want %x)", i, r, test.out)
+		}
+	}
+	err := quick.CheckEqual(ConstantTimeByteEq, byteEq, nil)
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func eq(a, b int32) int {
+	if a == b {
+		return 1
+	}
+	return 0
+}
+
+func TestConstantTimeEq(t *testing.T) {
+	err := quick.CheckEqual(ConstantTimeEq, eq, nil)
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func makeCopy(v int, x, y []byte) []byte {
+	if len(x) > len(y) {
+		x = x[0:len(y)]
+	} else {
+		y = y[0:len(x)]
+	}
+	if v == 1 {
+		copy(x, y)
+	}
+	return x
+}
+
+func constantTimeCopyWrapper(v int, x, y []byte) []byte {
+	if len(x) > len(y) {
+		x = x[0:len(y)]
+	} else {
+		y = y[0:len(x)]
+	}
+	v &= 1
+	ConstantTimeCopy(v, x, y)
+	return x
+}
+
+func TestConstantTimeCopy(t *testing.T) {
+	err := quick.CheckEqual(constantTimeCopyWrapper, makeCopy, nil)
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+var lessOrEqTests = []struct {
+	x, y, result int
+}{
+	{0, 0, 1},
+	{1, 0, 0},
+	{0, 1, 1},
+	{10, 20, 1},
+	{20, 10, 0},
+	{10, 10, 1},
+}
+
+func TestConstantTimeLessOrEq(t *testing.T) {
+	for i, test := range lessOrEqTests {
+		result := ConstantTimeLessOrEq(test.x, test.y)
+		if result != test.result {
+			t.Errorf("#%d: %d <= %d gave %d, expected %d", i, test.x, test.y, result, test.result)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/alert.go b/third_party/gofrontend/libgo/go/crypto/tls/alert.go
new file mode 100644
index 0000000..0856311
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/alert.go
@@ -0,0 +1,77 @@
+// 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 tls
+
+import "strconv"
+
+type alert uint8
+
+const (
+	// alert level
+	alertLevelWarning = 1
+	alertLevelError   = 2
+)
+
+const (
+	alertCloseNotify            alert = 0
+	alertUnexpectedMessage      alert = 10
+	alertBadRecordMAC           alert = 20
+	alertDecryptionFailed       alert = 21
+	alertRecordOverflow         alert = 22
+	alertDecompressionFailure   alert = 30
+	alertHandshakeFailure       alert = 40
+	alertBadCertificate         alert = 42
+	alertUnsupportedCertificate alert = 43
+	alertCertificateRevoked     alert = 44
+	alertCertificateExpired     alert = 45
+	alertCertificateUnknown     alert = 46
+	alertIllegalParameter       alert = 47
+	alertUnknownCA              alert = 48
+	alertAccessDenied           alert = 49
+	alertDecodeError            alert = 50
+	alertDecryptError           alert = 51
+	alertProtocolVersion        alert = 70
+	alertInsufficientSecurity   alert = 71
+	alertInternalError          alert = 80
+	alertUserCanceled           alert = 90
+	alertNoRenegotiation        alert = 100
+)
+
+var alertText = map[alert]string{
+	alertCloseNotify:            "close notify",
+	alertUnexpectedMessage:      "unexpected message",
+	alertBadRecordMAC:           "bad record MAC",
+	alertDecryptionFailed:       "decryption failed",
+	alertRecordOverflow:         "record overflow",
+	alertDecompressionFailure:   "decompression failure",
+	alertHandshakeFailure:       "handshake failure",
+	alertBadCertificate:         "bad certificate",
+	alertUnsupportedCertificate: "unsupported certificate",
+	alertCertificateRevoked:     "revoked certificate",
+	alertCertificateExpired:     "expired certificate",
+	alertCertificateUnknown:     "unknown certificate",
+	alertIllegalParameter:       "illegal parameter",
+	alertUnknownCA:              "unknown certificate authority",
+	alertAccessDenied:           "access denied",
+	alertDecodeError:            "error decoding message",
+	alertDecryptError:           "error decrypting message",
+	alertProtocolVersion:        "protocol version not supported",
+	alertInsufficientSecurity:   "insufficient security level",
+	alertInternalError:          "internal error",
+	alertUserCanceled:           "user canceled",
+	alertNoRenegotiation:        "no renegotiation",
+}
+
+func (e alert) String() string {
+	s, ok := alertText[e]
+	if ok {
+		return s
+	}
+	return "alert(" + strconv.Itoa(int(e)) + ")"
+}
+
+func (e alert) Error() string {
+	return e.String()
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/cipher_suites.go b/third_party/gofrontend/libgo/go/crypto/tls/cipher_suites.go
new file mode 100644
index 0000000..39a5145
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/cipher_suites.go
@@ -0,0 +1,270 @@
+// Copyright 2010 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 tls
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/des"
+	"crypto/hmac"
+	"crypto/rc4"
+	"crypto/sha1"
+	"crypto/x509"
+	"hash"
+)
+
+// a keyAgreement implements the client and server side of a TLS key agreement
+// protocol by generating and processing key exchange messages.
+type keyAgreement interface {
+	// On the server side, the first two methods are called in order.
+
+	// In the case that the key agreement protocol doesn't use a
+	// ServerKeyExchange message, generateServerKeyExchange can return nil,
+	// nil.
+	generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
+	processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
+
+	// On the client side, the next two methods are called in order.
+
+	// This method may not be called if the server doesn't send a
+	// ServerKeyExchange message.
+	processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
+	generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
+}
+
+const (
+	// suiteECDH indicates that the cipher suite involves elliptic curve
+	// Diffie-Hellman. This means that it should only be selected when the
+	// client indicates that it supports ECC with a curve and point format
+	// that we're happy with.
+	suiteECDHE = 1 << iota
+	// suiteECDSA indicates that the cipher suite involves an ECDSA
+	// signature and therefore may only be selected when the server's
+	// certificate is ECDSA. If this is not set then the cipher suite is
+	// RSA based.
+	suiteECDSA
+	// suiteTLS12 indicates that the cipher suite should only be advertised
+	// and accepted when using TLS 1.2.
+	suiteTLS12
+)
+
+// A cipherSuite is a specific combination of key agreement, cipher and MAC
+// function. All cipher suites currently assume RSA key agreement.
+type cipherSuite struct {
+	id uint16
+	// the lengths, in bytes, of the key material needed for each component.
+	keyLen int
+	macLen int
+	ivLen  int
+	ka     func(version uint16) keyAgreement
+	// flags is a bitmask of the suite* values, above.
+	flags  int
+	cipher func(key, iv []byte, isRead bool) interface{}
+	mac    func(version uint16, macKey []byte) macFunction
+	aead   func(key, fixedNonce []byte) cipher.AEAD
+}
+
+var cipherSuites = []*cipherSuite{
+	// Ciphersuite order is chosen so that ECDHE comes before plain RSA
+	// and RC4 comes before AES (because of the Lucky13 attack).
+	{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE, cipherRC4, macSHA1, nil},
+	{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherRC4, macSHA1, nil},
+	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+	{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, 0, cipherRC4, macSHA1, nil},
+	{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
+	{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
+	{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
+}
+
+func cipherRC4(key, iv []byte, isRead bool) interface{} {
+	cipher, _ := rc4.NewCipher(key)
+	return cipher
+}
+
+func cipher3DES(key, iv []byte, isRead bool) interface{} {
+	block, _ := des.NewTripleDESCipher(key)
+	if isRead {
+		return cipher.NewCBCDecrypter(block, iv)
+	}
+	return cipher.NewCBCEncrypter(block, iv)
+}
+
+func cipherAES(key, iv []byte, isRead bool) interface{} {
+	block, _ := aes.NewCipher(key)
+	if isRead {
+		return cipher.NewCBCDecrypter(block, iv)
+	}
+	return cipher.NewCBCEncrypter(block, iv)
+}
+
+// macSHA1 returns a macFunction for the given protocol version.
+func macSHA1(version uint16, key []byte) macFunction {
+	if version == VersionSSL30 {
+		mac := ssl30MAC{
+			h:   sha1.New(),
+			key: make([]byte, len(key)),
+		}
+		copy(mac.key, key)
+		return mac
+	}
+	return tls10MAC{hmac.New(sha1.New, key)}
+}
+
+type macFunction interface {
+	Size() int
+	MAC(digestBuf, seq, header, data []byte) []byte
+}
+
+// fixedNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to
+// each call.
+type fixedNonceAEAD struct {
+	// sealNonce and openNonce are buffers where the larger nonce will be
+	// constructed. Since a seal and open operation may be running
+	// concurrently, there is a separate buffer for each.
+	sealNonce, openNonce []byte
+	aead                 cipher.AEAD
+}
+
+func (f *fixedNonceAEAD) NonceSize() int { return 8 }
+func (f *fixedNonceAEAD) Overhead() int  { return f.aead.Overhead() }
+
+func (f *fixedNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
+	copy(f.sealNonce[len(f.sealNonce)-8:], nonce)
+	return f.aead.Seal(out, f.sealNonce, plaintext, additionalData)
+}
+
+func (f *fixedNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) {
+	copy(f.openNonce[len(f.openNonce)-8:], nonce)
+	return f.aead.Open(out, f.openNonce, plaintext, additionalData)
+}
+
+func aeadAESGCM(key, fixedNonce []byte) cipher.AEAD {
+	aes, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+	aead, err := cipher.NewGCM(aes)
+	if err != nil {
+		panic(err)
+	}
+
+	nonce1, nonce2 := make([]byte, 12), make([]byte, 12)
+	copy(nonce1, fixedNonce)
+	copy(nonce2, fixedNonce)
+
+	return &fixedNonceAEAD{nonce1, nonce2, aead}
+}
+
+// ssl30MAC implements the SSLv3 MAC function, as defined in
+// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 5.2.3.1
+type ssl30MAC struct {
+	h   hash.Hash
+	key []byte
+}
+
+func (s ssl30MAC) Size() int {
+	return s.h.Size()
+}
+
+var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}
+
+var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
+
+func (s ssl30MAC) MAC(digestBuf, seq, header, data []byte) []byte {
+	padLength := 48
+	if s.h.Size() == 20 {
+		padLength = 40
+	}
+
+	s.h.Reset()
+	s.h.Write(s.key)
+	s.h.Write(ssl30Pad1[:padLength])
+	s.h.Write(seq)
+	s.h.Write(header[:1])
+	s.h.Write(header[3:5])
+	s.h.Write(data)
+	digestBuf = s.h.Sum(digestBuf[:0])
+
+	s.h.Reset()
+	s.h.Write(s.key)
+	s.h.Write(ssl30Pad2[:padLength])
+	s.h.Write(digestBuf)
+	return s.h.Sum(digestBuf[:0])
+}
+
+// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3.
+type tls10MAC struct {
+	h hash.Hash
+}
+
+func (s tls10MAC) Size() int {
+	return s.h.Size()
+}
+
+func (s tls10MAC) MAC(digestBuf, seq, header, data []byte) []byte {
+	s.h.Reset()
+	s.h.Write(seq)
+	s.h.Write(header)
+	s.h.Write(data)
+	return s.h.Sum(digestBuf[:0])
+}
+
+func rsaKA(version uint16) keyAgreement {
+	return rsaKeyAgreement{}
+}
+
+func ecdheECDSAKA(version uint16) keyAgreement {
+	return &ecdheKeyAgreement{
+		sigType: signatureECDSA,
+		version: version,
+	}
+}
+
+func ecdheRSAKA(version uint16) keyAgreement {
+	return &ecdheKeyAgreement{
+		sigType: signatureRSA,
+		version: version,
+	}
+}
+
+// mutualCipherSuite returns a cipherSuite given a list of supported
+// ciphersuites and the id requested by the peer.
+func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
+	for _, id := range have {
+		if id == want {
+			for _, suite := range cipherSuites {
+				if suite.id == want {
+					return suite
+				}
+			}
+			return nil
+		}
+	}
+	return nil
+}
+
+// A list of the possible cipher suite ids. Taken from
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
+const (
+	TLS_RSA_WITH_RC4_128_SHA                uint16 = 0x0005
+	TLS_RSA_WITH_3DES_EDE_CBC_SHA           uint16 = 0x000a
+	TLS_RSA_WITH_AES_128_CBC_SHA            uint16 = 0x002f
+	TLS_RSA_WITH_AES_256_CBC_SHA            uint16 = 0x0035
+	TLS_ECDHE_ECDSA_WITH_RC4_128_SHA        uint16 = 0xc007
+	TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA    uint16 = 0xc009
+	TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA    uint16 = 0xc00a
+	TLS_ECDHE_RSA_WITH_RC4_128_SHA          uint16 = 0xc011
+	TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA     uint16 = 0xc012
+	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA      uint16 = 0xc013
+	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA      uint16 = 0xc014
+	TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256   uint16 = 0xc02f
+	TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
+)
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/common.go b/third_party/gofrontend/libgo/go/crypto/tls/common.go
new file mode 100644
index 0000000..fca98bd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/common.go
@@ -0,0 +1,568 @@
+// 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 tls
+
+import (
+	"container/list"
+	"crypto"
+	"crypto/rand"
+	"crypto/x509"
+	"fmt"
+	"io"
+	"math/big"
+	"strings"
+	"sync"
+	"time"
+)
+
+const (
+	VersionSSL30 = 0x0300
+	VersionTLS10 = 0x0301
+	VersionTLS11 = 0x0302
+	VersionTLS12 = 0x0303
+)
+
+const (
+	maxPlaintext    = 16384        // maximum plaintext payload length
+	maxCiphertext   = 16384 + 2048 // maximum ciphertext payload length
+	recordHeaderLen = 5            // record header length
+	maxHandshake    = 65536        // maximum handshake we support (protocol max is 16 MB)
+
+	minVersion = VersionSSL30
+	maxVersion = VersionTLS12
+)
+
+// TLS record types.
+type recordType uint8
+
+const (
+	recordTypeChangeCipherSpec recordType = 20
+	recordTypeAlert            recordType = 21
+	recordTypeHandshake        recordType = 22
+	recordTypeApplicationData  recordType = 23
+)
+
+// TLS handshake message types.
+const (
+	typeClientHello        uint8 = 1
+	typeServerHello        uint8 = 2
+	typeNewSessionTicket   uint8 = 4
+	typeCertificate        uint8 = 11
+	typeServerKeyExchange  uint8 = 12
+	typeCertificateRequest uint8 = 13
+	typeServerHelloDone    uint8 = 14
+	typeCertificateVerify  uint8 = 15
+	typeClientKeyExchange  uint8 = 16
+	typeFinished           uint8 = 20
+	typeCertificateStatus  uint8 = 22
+	typeNextProtocol       uint8 = 67 // Not IANA assigned
+)
+
+// TLS compression types.
+const (
+	compressionNone uint8 = 0
+)
+
+// TLS extension numbers
+const (
+	extensionServerName          uint16 = 0
+	extensionStatusRequest       uint16 = 5
+	extensionSupportedCurves     uint16 = 10
+	extensionSupportedPoints     uint16 = 11
+	extensionSignatureAlgorithms uint16 = 13
+	extensionSessionTicket       uint16 = 35
+	extensionNextProtoNeg        uint16 = 13172 // not IANA assigned
+	extensionRenegotiationInfo   uint16 = 0xff01
+)
+
+// TLS signaling cipher suite values
+const (
+	scsvRenegotiation uint16 = 0x00ff
+)
+
+// CurveID is the type of a TLS identifier for an elliptic curve. See
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
+type CurveID uint16
+
+const (
+	CurveP256 CurveID = 23
+	CurveP384 CurveID = 24
+	CurveP521 CurveID = 25
+)
+
+// TLS Elliptic Curve Point Formats
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
+const (
+	pointFormatUncompressed uint8 = 0
+)
+
+// TLS CertificateStatusType (RFC 3546)
+const (
+	statusTypeOCSP uint8 = 1
+)
+
+// Certificate types (for certificateRequestMsg)
+const (
+	certTypeRSASign    = 1 // A certificate containing an RSA key
+	certTypeDSSSign    = 2 // A certificate containing a DSA key
+	certTypeRSAFixedDH = 3 // A certificate containing a static DH key
+	certTypeDSSFixedDH = 4 // A certificate containing a static DH key
+
+	// See RFC4492 sections 3 and 5.5.
+	certTypeECDSASign      = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA.
+	certTypeRSAFixedECDH   = 65 // A certificate containing an ECDH-capable public key, signed with RSA.
+	certTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA.
+
+	// Rest of these are reserved by the TLS spec
+)
+
+// Hash functions for TLS 1.2 (See RFC 5246, section A.4.1)
+const (
+	hashSHA1   uint8 = 2
+	hashSHA256 uint8 = 4
+)
+
+// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
+const (
+	signatureRSA   uint8 = 1
+	signatureECDSA uint8 = 3
+)
+
+// signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See
+// RFC 5246, section A.4.1.
+type signatureAndHash struct {
+	hash, signature uint8
+}
+
+// supportedSKXSignatureAlgorithms contains the signature and hash algorithms
+// that the code advertises as supported in a TLS 1.2 ClientHello.
+var supportedSKXSignatureAlgorithms = []signatureAndHash{
+	{hashSHA256, signatureRSA},
+	{hashSHA256, signatureECDSA},
+	{hashSHA1, signatureRSA},
+	{hashSHA1, signatureECDSA},
+}
+
+// supportedClientCertSignatureAlgorithms contains the signature and hash
+// algorithms that the code advertises as supported in a TLS 1.2
+// CertificateRequest.
+var supportedClientCertSignatureAlgorithms = []signatureAndHash{
+	{hashSHA256, signatureRSA},
+	{hashSHA256, signatureECDSA},
+}
+
+// ConnectionState records basic TLS details about the connection.
+type ConnectionState struct {
+	Version                    uint16                // TLS version used by the connection (e.g. VersionTLS12)
+	HandshakeComplete          bool                  // TLS handshake is complete
+	DidResume                  bool                  // connection resumes a previous TLS connection
+	CipherSuite                uint16                // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...)
+	NegotiatedProtocol         string                // negotiated next protocol (from Config.NextProtos)
+	NegotiatedProtocolIsMutual bool                  // negotiated protocol was advertised by server
+	ServerName                 string                // server name requested by client, if any (server side only)
+	PeerCertificates           []*x509.Certificate   // certificate chain presented by remote peer
+	VerifiedChains             [][]*x509.Certificate // verified chains built from PeerCertificates
+}
+
+// ClientAuthType declares the policy the server will follow for
+// TLS Client Authentication.
+type ClientAuthType int
+
+const (
+	NoClientCert ClientAuthType = iota
+	RequestClientCert
+	RequireAnyClientCert
+	VerifyClientCertIfGiven
+	RequireAndVerifyClientCert
+)
+
+// ClientSessionState contains the state needed by clients to resume TLS
+// sessions.
+type ClientSessionState struct {
+	sessionTicket      []uint8             // Encrypted ticket used for session resumption with server
+	vers               uint16              // SSL/TLS version negotiated for the session
+	cipherSuite        uint16              // Ciphersuite negotiated for the session
+	masterSecret       []byte              // MasterSecret generated by client on a full handshake
+	serverCertificates []*x509.Certificate // Certificate chain presented by the server
+}
+
+// ClientSessionCache is a cache of ClientSessionState objects that can be used
+// by a client to resume a TLS session with a given server. ClientSessionCache
+// implementations should expect to be called concurrently from different
+// goroutines.
+type ClientSessionCache interface {
+	// Get searches for a ClientSessionState associated with the given key.
+	// On return, ok is true if one was found.
+	Get(sessionKey string) (session *ClientSessionState, ok bool)
+
+	// Put adds the ClientSessionState to the cache with the given key.
+	Put(sessionKey string, cs *ClientSessionState)
+}
+
+// A Config structure is used to configure a TLS client or server.
+// After one has been passed to a TLS function it must not be
+// modified. A Config may be reused; the tls package will also not
+// modify it.
+type Config struct {
+	// Rand provides the source of entropy for nonces and RSA blinding.
+	// If Rand is nil, TLS uses the cryptographic random reader in package
+	// crypto/rand.
+	// The Reader must be safe for use by multiple goroutines.
+	Rand io.Reader
+
+	// Time returns the current time as the number of seconds since the epoch.
+	// If Time is nil, TLS uses time.Now.
+	Time func() time.Time
+
+	// Certificates contains one or more certificate chains
+	// to present to the other side of the connection.
+	// Server configurations must include at least one certificate.
+	Certificates []Certificate
+
+	// NameToCertificate maps from a certificate name to an element of
+	// Certificates. Note that a certificate name can be of the form
+	// '*.example.com' and so doesn't have to be a domain name as such.
+	// See Config.BuildNameToCertificate
+	// The nil value causes the first element of Certificates to be used
+	// for all connections.
+	NameToCertificate map[string]*Certificate
+
+	// RootCAs defines the set of root certificate authorities
+	// that clients use when verifying server certificates.
+	// If RootCAs is nil, TLS uses the host's root CA set.
+	RootCAs *x509.CertPool
+
+	// NextProtos is a list of supported, application level protocols.
+	NextProtos []string
+
+	// ServerName is used to verify the hostname on the returned
+	// certificates unless InsecureSkipVerify is given. It is also included
+	// in the client's handshake to support virtual hosting.
+	ServerName string
+
+	// ClientAuth determines the server's policy for
+	// TLS Client Authentication. The default is NoClientCert.
+	ClientAuth ClientAuthType
+
+	// ClientCAs defines the set of root certificate authorities
+	// that servers use if required to verify a client certificate
+	// by the policy in ClientAuth.
+	ClientCAs *x509.CertPool
+
+	// InsecureSkipVerify controls whether a client verifies the
+	// server's certificate chain and host name.
+	// If InsecureSkipVerify is true, TLS accepts any certificate
+	// presented by the server and any host name in that certificate.
+	// In this mode, TLS is susceptible to man-in-the-middle attacks.
+	// This should be used only for testing.
+	InsecureSkipVerify bool
+
+	// CipherSuites is a list of supported cipher suites. If CipherSuites
+	// is nil, TLS uses a list of suites supported by the implementation.
+	CipherSuites []uint16
+
+	// PreferServerCipherSuites controls whether the server selects the
+	// client's most preferred ciphersuite, or the server's most preferred
+	// ciphersuite. If true then the server's preference, as expressed in
+	// the order of elements in CipherSuites, is used.
+	PreferServerCipherSuites bool
+
+	// SessionTicketsDisabled may be set to true to disable session ticket
+	// (resumption) support.
+	SessionTicketsDisabled bool
+
+	// SessionTicketKey is used by TLS servers to provide session
+	// resumption. See RFC 5077. If zero, it will be filled with
+	// random data before the first server handshake.
+	//
+	// If multiple servers are terminating connections for the same host
+	// they should all have the same SessionTicketKey. If the
+	// SessionTicketKey leaks, previously recorded and future TLS
+	// connections using that key are compromised.
+	SessionTicketKey [32]byte
+
+	// SessionCache is a cache of ClientSessionState entries for TLS session
+	// resumption.
+	ClientSessionCache ClientSessionCache
+
+	// MinVersion contains the minimum SSL/TLS version that is acceptable.
+	// If zero, then SSLv3 is taken as the minimum.
+	MinVersion uint16
+
+	// MaxVersion contains the maximum SSL/TLS version that is acceptable.
+	// If zero, then the maximum version supported by this package is used,
+	// which is currently TLS 1.2.
+	MaxVersion uint16
+
+	// CurvePreferences contains the elliptic curves that will be used in
+	// an ECDHE handshake, in preference order. If empty, the default will
+	// be used.
+	CurvePreferences []CurveID
+
+	serverInitOnce sync.Once // guards calling (*Config).serverInit
+}
+
+func (c *Config) serverInit() {
+	if c.SessionTicketsDisabled {
+		return
+	}
+
+	// If the key has already been set then we have nothing to do.
+	for _, b := range c.SessionTicketKey {
+		if b != 0 {
+			return
+		}
+	}
+
+	if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil {
+		c.SessionTicketsDisabled = true
+	}
+}
+
+func (c *Config) rand() io.Reader {
+	r := c.Rand
+	if r == nil {
+		return rand.Reader
+	}
+	return r
+}
+
+func (c *Config) time() time.Time {
+	t := c.Time
+	if t == nil {
+		t = time.Now
+	}
+	return t()
+}
+
+func (c *Config) cipherSuites() []uint16 {
+	s := c.CipherSuites
+	if s == nil {
+		s = defaultCipherSuites()
+	}
+	return s
+}
+
+func (c *Config) minVersion() uint16 {
+	if c == nil || c.MinVersion == 0 {
+		return minVersion
+	}
+	return c.MinVersion
+}
+
+func (c *Config) maxVersion() uint16 {
+	if c == nil || c.MaxVersion == 0 {
+		return maxVersion
+	}
+	return c.MaxVersion
+}
+
+var defaultCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521}
+
+func (c *Config) curvePreferences() []CurveID {
+	if c == nil || len(c.CurvePreferences) == 0 {
+		return defaultCurvePreferences
+	}
+	return c.CurvePreferences
+}
+
+// mutualVersion returns the protocol version to use given the advertised
+// version of the peer.
+func (c *Config) mutualVersion(vers uint16) (uint16, bool) {
+	minVersion := c.minVersion()
+	maxVersion := c.maxVersion()
+
+	if vers < minVersion {
+		return 0, false
+	}
+	if vers > maxVersion {
+		vers = maxVersion
+	}
+	return vers, true
+}
+
+// getCertificateForName returns the best certificate for the given name,
+// defaulting to the first element of c.Certificates if there are no good
+// options.
+func (c *Config) getCertificateForName(name string) *Certificate {
+	if len(c.Certificates) == 1 || c.NameToCertificate == nil {
+		// There's only one choice, so no point doing any work.
+		return &c.Certificates[0]
+	}
+
+	name = strings.ToLower(name)
+	for len(name) > 0 && name[len(name)-1] == '.' {
+		name = name[:len(name)-1]
+	}
+
+	if cert, ok := c.NameToCertificate[name]; ok {
+		return cert
+	}
+
+	// try replacing labels in the name with wildcards until we get a
+	// match.
+	labels := strings.Split(name, ".")
+	for i := range labels {
+		labels[i] = "*"
+		candidate := strings.Join(labels, ".")
+		if cert, ok := c.NameToCertificate[candidate]; ok {
+			return cert
+		}
+	}
+
+	// If nothing matches, return the first certificate.
+	return &c.Certificates[0]
+}
+
+// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate
+// from the CommonName and SubjectAlternateName fields of each of the leaf
+// certificates.
+func (c *Config) BuildNameToCertificate() {
+	c.NameToCertificate = make(map[string]*Certificate)
+	for i := range c.Certificates {
+		cert := &c.Certificates[i]
+		x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
+		if err != nil {
+			continue
+		}
+		if len(x509Cert.Subject.CommonName) > 0 {
+			c.NameToCertificate[x509Cert.Subject.CommonName] = cert
+		}
+		for _, san := range x509Cert.DNSNames {
+			c.NameToCertificate[san] = cert
+		}
+	}
+}
+
+// A Certificate is a chain of one or more certificates, leaf first.
+type Certificate struct {
+	Certificate [][]byte
+	PrivateKey  crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey
+	// OCSPStaple contains an optional OCSP response which will be served
+	// to clients that request it.
+	OCSPStaple []byte
+	// Leaf is the parsed form of the leaf certificate, which may be
+	// initialized using x509.ParseCertificate to reduce per-handshake
+	// processing for TLS clients doing client authentication. If nil, the
+	// leaf certificate will be parsed as needed.
+	Leaf *x509.Certificate
+}
+
+// A TLS record.
+type record struct {
+	contentType  recordType
+	major, minor uint8
+	payload      []byte
+}
+
+type handshakeMessage interface {
+	marshal() []byte
+	unmarshal([]byte) bool
+}
+
+// lruSessionCache is a ClientSessionCache implementation that uses an LRU
+// caching strategy.
+type lruSessionCache struct {
+	sync.Mutex
+
+	m        map[string]*list.Element
+	q        *list.List
+	capacity int
+}
+
+type lruSessionCacheEntry struct {
+	sessionKey string
+	state      *ClientSessionState
+}
+
+// NewLRUClientSessionCache returns a ClientSessionCache with the given
+// capacity that uses an LRU strategy. If capacity is < 1, a default capacity
+// is used instead.
+func NewLRUClientSessionCache(capacity int) ClientSessionCache {
+	const defaultSessionCacheCapacity = 64
+
+	if capacity < 1 {
+		capacity = defaultSessionCacheCapacity
+	}
+	return &lruSessionCache{
+		m:        make(map[string]*list.Element),
+		q:        list.New(),
+		capacity: capacity,
+	}
+}
+
+// Put adds the provided (sessionKey, cs) pair to the cache.
+func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) {
+	c.Lock()
+	defer c.Unlock()
+
+	if elem, ok := c.m[sessionKey]; ok {
+		entry := elem.Value.(*lruSessionCacheEntry)
+		entry.state = cs
+		c.q.MoveToFront(elem)
+		return
+	}
+
+	if c.q.Len() < c.capacity {
+		entry := &lruSessionCacheEntry{sessionKey, cs}
+		c.m[sessionKey] = c.q.PushFront(entry)
+		return
+	}
+
+	elem := c.q.Back()
+	entry := elem.Value.(*lruSessionCacheEntry)
+	delete(c.m, entry.sessionKey)
+	entry.sessionKey = sessionKey
+	entry.state = cs
+	c.q.MoveToFront(elem)
+	c.m[sessionKey] = elem
+}
+
+// Get returns the ClientSessionState value associated with a given key. It
+// returns (nil, false) if no value is found.
+func (c *lruSessionCache) Get(sessionKey string) (*ClientSessionState, bool) {
+	c.Lock()
+	defer c.Unlock()
+
+	if elem, ok := c.m[sessionKey]; ok {
+		c.q.MoveToFront(elem)
+		return elem.Value.(*lruSessionCacheEntry).state, true
+	}
+	return nil, false
+}
+
+// TODO(jsing): Make these available to both crypto/x509 and crypto/tls.
+type dsaSignature struct {
+	R, S *big.Int
+}
+
+type ecdsaSignature dsaSignature
+
+var emptyConfig Config
+
+func defaultConfig() *Config {
+	return &emptyConfig
+}
+
+var (
+	once                   sync.Once
+	varDefaultCipherSuites []uint16
+)
+
+func defaultCipherSuites() []uint16 {
+	once.Do(initDefaultCipherSuites)
+	return varDefaultCipherSuites
+}
+
+func initDefaultCipherSuites() {
+	varDefaultCipherSuites = make([]uint16, len(cipherSuites))
+	for i, suite := range cipherSuites {
+		varDefaultCipherSuites[i] = suite.id
+	}
+}
+
+func unexpectedMessageError(wanted, got interface{}) error {
+	return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/conn.go b/third_party/gofrontend/libgo/go/crypto/tls/conn.go
new file mode 100644
index 0000000..8f7d2c1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/conn.go
@@ -0,0 +1,1024 @@
+// Copyright 2010 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.
+
+// TLS low level connection and record layer
+
+package tls
+
+import (
+	"bytes"
+	"crypto/cipher"
+	"crypto/subtle"
+	"crypto/x509"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"sync"
+	"time"
+)
+
+// A Conn represents a secured connection.
+// It implements the net.Conn interface.
+type Conn struct {
+	// constant
+	conn     net.Conn
+	isClient bool
+
+	// constant after handshake; protected by handshakeMutex
+	handshakeMutex    sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex
+	handshakeErr      error      // error resulting from handshake
+	vers              uint16     // TLS version
+	haveVers          bool       // version has been negotiated
+	config            *Config    // configuration passed to constructor
+	handshakeComplete bool
+	didResume         bool // whether this connection was a session resumption
+	cipherSuite       uint16
+	ocspResponse      []byte // stapled OCSP response
+	peerCertificates  []*x509.Certificate
+	// verifiedChains contains the certificate chains that we built, as
+	// opposed to the ones presented by the server.
+	verifiedChains [][]*x509.Certificate
+	// serverName contains the server name indicated by the client, if any.
+	serverName string
+
+	clientProtocol         string
+	clientProtocolFallback bool
+
+	// input/output
+	in, out  halfConn     // in.Mutex < out.Mutex
+	rawInput *block       // raw input, right off the wire
+	input    *block       // application data waiting to be read
+	hand     bytes.Buffer // handshake data waiting to be read
+
+	tmp [16]byte
+}
+
+// Access to net.Conn methods.
+// Cannot just embed net.Conn because that would
+// export the struct field too.
+
+// LocalAddr returns the local network address.
+func (c *Conn) LocalAddr() net.Addr {
+	return c.conn.LocalAddr()
+}
+
+// RemoteAddr returns the remote network address.
+func (c *Conn) RemoteAddr() net.Addr {
+	return c.conn.RemoteAddr()
+}
+
+// SetDeadline sets the read and write deadlines associated with the connection.
+// A zero value for t means Read and Write will not time out.
+// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
+func (c *Conn) SetDeadline(t time.Time) error {
+	return c.conn.SetDeadline(t)
+}
+
+// SetReadDeadline sets the read deadline on the underlying connection.
+// A zero value for t means Read will not time out.
+func (c *Conn) SetReadDeadline(t time.Time) error {
+	return c.conn.SetReadDeadline(t)
+}
+
+// SetWriteDeadline sets the write deadline on the underlying connection.
+// A zero value for t means Write will not time out.
+// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
+func (c *Conn) SetWriteDeadline(t time.Time) error {
+	return c.conn.SetWriteDeadline(t)
+}
+
+// A halfConn represents one direction of the record layer
+// connection, either sending or receiving.
+type halfConn struct {
+	sync.Mutex
+
+	err     error       // first permanent error
+	version uint16      // protocol version
+	cipher  interface{} // cipher algorithm
+	mac     macFunction
+	seq     [8]byte // 64-bit sequence number
+	bfree   *block  // list of free blocks
+
+	nextCipher interface{} // next encryption state
+	nextMac    macFunction // next MAC algorithm
+
+	// used to save allocating a new buffer for each MAC.
+	inDigestBuf, outDigestBuf []byte
+}
+
+func (hc *halfConn) setErrorLocked(err error) error {
+	hc.err = err
+	return err
+}
+
+func (hc *halfConn) error() error {
+	hc.Lock()
+	err := hc.err
+	hc.Unlock()
+	return err
+}
+
+// prepareCipherSpec sets the encryption and MAC states
+// that a subsequent changeCipherSpec will use.
+func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) {
+	hc.version = version
+	hc.nextCipher = cipher
+	hc.nextMac = mac
+}
+
+// changeCipherSpec changes the encryption and MAC states
+// to the ones previously passed to prepareCipherSpec.
+func (hc *halfConn) changeCipherSpec() error {
+	if hc.nextCipher == nil {
+		return alertInternalError
+	}
+	hc.cipher = hc.nextCipher
+	hc.mac = hc.nextMac
+	hc.nextCipher = nil
+	hc.nextMac = nil
+	for i := range hc.seq {
+		hc.seq[i] = 0
+	}
+	return nil
+}
+
+// incSeq increments the sequence number.
+func (hc *halfConn) incSeq() {
+	for i := 7; i >= 0; i-- {
+		hc.seq[i]++
+		if hc.seq[i] != 0 {
+			return
+		}
+	}
+
+	// Not allowed to let sequence number wrap.
+	// Instead, must renegotiate before it does.
+	// Not likely enough to bother.
+	panic("TLS: sequence number wraparound")
+}
+
+// resetSeq resets the sequence number to zero.
+func (hc *halfConn) resetSeq() {
+	for i := range hc.seq {
+		hc.seq[i] = 0
+	}
+}
+
+// removePadding returns an unpadded slice, in constant time, which is a prefix
+// of the input. It also returns a byte which is equal to 255 if the padding
+// was valid and 0 otherwise. See RFC 2246, section 6.2.3.2
+func removePadding(payload []byte) ([]byte, byte) {
+	if len(payload) < 1 {
+		return payload, 0
+	}
+
+	paddingLen := payload[len(payload)-1]
+	t := uint(len(payload)-1) - uint(paddingLen)
+	// if len(payload) >= (paddingLen - 1) then the MSB of t is zero
+	good := byte(int32(^t) >> 31)
+
+	toCheck := 255 // the maximum possible padding length
+	// The length of the padded data is public, so we can use an if here
+	if toCheck+1 > len(payload) {
+		toCheck = len(payload) - 1
+	}
+
+	for i := 0; i < toCheck; i++ {
+		t := uint(paddingLen) - uint(i)
+		// if i <= paddingLen then the MSB of t is zero
+		mask := byte(int32(^t) >> 31)
+		b := payload[len(payload)-1-i]
+		good &^= mask&paddingLen ^ mask&b
+	}
+
+	// We AND together the bits of good and replicate the result across
+	// all the bits.
+	good &= good << 4
+	good &= good << 2
+	good &= good << 1
+	good = uint8(int8(good) >> 7)
+
+	toRemove := good&paddingLen + 1
+	return payload[:len(payload)-int(toRemove)], good
+}
+
+// removePaddingSSL30 is a replacement for removePadding in the case that the
+// protocol version is SSLv3. In this version, the contents of the padding
+// are random and cannot be checked.
+func removePaddingSSL30(payload []byte) ([]byte, byte) {
+	if len(payload) < 1 {
+		return payload, 0
+	}
+
+	paddingLen := int(payload[len(payload)-1]) + 1
+	if paddingLen > len(payload) {
+		return payload, 0
+	}
+
+	return payload[:len(payload)-paddingLen], 255
+}
+
+func roundUp(a, b int) int {
+	return a + (b-a%b)%b
+}
+
+// cbcMode is an interface for block ciphers using cipher block chaining.
+type cbcMode interface {
+	cipher.BlockMode
+	SetIV([]byte)
+}
+
+// decrypt checks and strips the mac and decrypts the data in b. Returns a
+// success boolean, the number of bytes to skip from the start of the record in
+// order to get the application payload, and an optional alert value.
+func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert) {
+	// pull out payload
+	payload := b.data[recordHeaderLen:]
+
+	macSize := 0
+	if hc.mac != nil {
+		macSize = hc.mac.Size()
+	}
+
+	paddingGood := byte(255)
+	explicitIVLen := 0
+
+	// decrypt
+	if hc.cipher != nil {
+		switch c := hc.cipher.(type) {
+		case cipher.Stream:
+			c.XORKeyStream(payload, payload)
+		case cipher.AEAD:
+			explicitIVLen = 8
+			if len(payload) < explicitIVLen {
+				return false, 0, alertBadRecordMAC
+			}
+			nonce := payload[:8]
+			payload = payload[8:]
+
+			var additionalData [13]byte
+			copy(additionalData[:], hc.seq[:])
+			copy(additionalData[8:], b.data[:3])
+			n := len(payload) - c.Overhead()
+			additionalData[11] = byte(n >> 8)
+			additionalData[12] = byte(n)
+			var err error
+			payload, err = c.Open(payload[:0], nonce, payload, additionalData[:])
+			if err != nil {
+				return false, 0, alertBadRecordMAC
+			}
+			b.resize(recordHeaderLen + explicitIVLen + len(payload))
+		case cbcMode:
+			blockSize := c.BlockSize()
+			if hc.version >= VersionTLS11 {
+				explicitIVLen = blockSize
+			}
+
+			if len(payload)%blockSize != 0 || len(payload) < roundUp(explicitIVLen+macSize+1, blockSize) {
+				return false, 0, alertBadRecordMAC
+			}
+
+			if explicitIVLen > 0 {
+				c.SetIV(payload[:explicitIVLen])
+				payload = payload[explicitIVLen:]
+			}
+			c.CryptBlocks(payload, payload)
+			if hc.version == VersionSSL30 {
+				payload, paddingGood = removePaddingSSL30(payload)
+			} else {
+				payload, paddingGood = removePadding(payload)
+			}
+			b.resize(recordHeaderLen + explicitIVLen + len(payload))
+
+			// note that we still have a timing side-channel in the
+			// MAC check, below. An attacker can align the record
+			// so that a correct padding will cause one less hash
+			// block to be calculated. Then they can iteratively
+			// decrypt a record by breaking each byte. See
+			// "Password Interception in a SSL/TLS Channel", Brice
+			// Canvel et al.
+			//
+			// However, our behavior matches OpenSSL, so we leak
+			// only as much as they do.
+		default:
+			panic("unknown cipher type")
+		}
+	}
+
+	// check, strip mac
+	if hc.mac != nil {
+		if len(payload) < macSize {
+			return false, 0, alertBadRecordMAC
+		}
+
+		// strip mac off payload, b.data
+		n := len(payload) - macSize
+		b.data[3] = byte(n >> 8)
+		b.data[4] = byte(n)
+		b.resize(recordHeaderLen + explicitIVLen + n)
+		remoteMAC := payload[n:]
+		localMAC := hc.mac.MAC(hc.inDigestBuf, hc.seq[0:], b.data[:recordHeaderLen], payload[:n])
+
+		if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
+			return false, 0, alertBadRecordMAC
+		}
+		hc.inDigestBuf = localMAC
+	}
+	hc.incSeq()
+
+	return true, recordHeaderLen + explicitIVLen, 0
+}
+
+// padToBlockSize calculates the needed padding block, if any, for a payload.
+// On exit, prefix aliases payload and extends to the end of the last full
+// block of payload. finalBlock is a fresh slice which contains the contents of
+// any suffix of payload as well as the needed padding to make finalBlock a
+// full block.
+func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) {
+	overrun := len(payload) % blockSize
+	paddingLen := blockSize - overrun
+	prefix = payload[:len(payload)-overrun]
+	finalBlock = make([]byte, blockSize)
+	copy(finalBlock, payload[len(payload)-overrun:])
+	for i := overrun; i < blockSize; i++ {
+		finalBlock[i] = byte(paddingLen - 1)
+	}
+	return
+}
+
+// encrypt encrypts and macs the data in b.
+func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
+	// mac
+	if hc.mac != nil {
+		mac := hc.mac.MAC(hc.outDigestBuf, hc.seq[0:], b.data[:recordHeaderLen], b.data[recordHeaderLen+explicitIVLen:])
+
+		n := len(b.data)
+		b.resize(n + len(mac))
+		copy(b.data[n:], mac)
+		hc.outDigestBuf = mac
+	}
+
+	payload := b.data[recordHeaderLen:]
+
+	// encrypt
+	if hc.cipher != nil {
+		switch c := hc.cipher.(type) {
+		case cipher.Stream:
+			c.XORKeyStream(payload, payload)
+		case cipher.AEAD:
+			payloadLen := len(b.data) - recordHeaderLen - explicitIVLen
+			b.resize(len(b.data) + c.Overhead())
+			nonce := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
+			payload := b.data[recordHeaderLen+explicitIVLen:]
+			payload = payload[:payloadLen]
+
+			var additionalData [13]byte
+			copy(additionalData[:], hc.seq[:])
+			copy(additionalData[8:], b.data[:3])
+			additionalData[11] = byte(payloadLen >> 8)
+			additionalData[12] = byte(payloadLen)
+
+			c.Seal(payload[:0], nonce, payload, additionalData[:])
+		case cbcMode:
+			blockSize := c.BlockSize()
+			if explicitIVLen > 0 {
+				c.SetIV(payload[:explicitIVLen])
+				payload = payload[explicitIVLen:]
+			}
+			prefix, finalBlock := padToBlockSize(payload, blockSize)
+			b.resize(recordHeaderLen + explicitIVLen + len(prefix) + len(finalBlock))
+			c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen:], prefix)
+			c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen+len(prefix):], finalBlock)
+		default:
+			panic("unknown cipher type")
+		}
+	}
+
+	// update length to include MAC and any block padding needed.
+	n := len(b.data) - recordHeaderLen
+	b.data[3] = byte(n >> 8)
+	b.data[4] = byte(n)
+	hc.incSeq()
+
+	return true, 0
+}
+
+// A block is a simple data buffer.
+type block struct {
+	data []byte
+	off  int // index for Read
+	link *block
+}
+
+// resize resizes block to be n bytes, growing if necessary.
+func (b *block) resize(n int) {
+	if n > cap(b.data) {
+		b.reserve(n)
+	}
+	b.data = b.data[0:n]
+}
+
+// reserve makes sure that block contains a capacity of at least n bytes.
+func (b *block) reserve(n int) {
+	if cap(b.data) >= n {
+		return
+	}
+	m := cap(b.data)
+	if m == 0 {
+		m = 1024
+	}
+	for m < n {
+		m *= 2
+	}
+	data := make([]byte, len(b.data), m)
+	copy(data, b.data)
+	b.data = data
+}
+
+// readFromUntil reads from r into b until b contains at least n bytes
+// or else returns an error.
+func (b *block) readFromUntil(r io.Reader, n int) error {
+	// quick case
+	if len(b.data) >= n {
+		return nil
+	}
+
+	// read until have enough.
+	b.reserve(n)
+	for {
+		m, err := r.Read(b.data[len(b.data):cap(b.data)])
+		b.data = b.data[0 : len(b.data)+m]
+		if len(b.data) >= n {
+			// TODO(bradfitz,agl): slightly suspicious
+			// that we're throwing away r.Read's err here.
+			break
+		}
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (b *block) Read(p []byte) (n int, err error) {
+	n = copy(p, b.data[b.off:])
+	b.off += n
+	return
+}
+
+// newBlock allocates a new block, from hc's free list if possible.
+func (hc *halfConn) newBlock() *block {
+	b := hc.bfree
+	if b == nil {
+		return new(block)
+	}
+	hc.bfree = b.link
+	b.link = nil
+	b.resize(0)
+	return b
+}
+
+// freeBlock returns a block to hc's free list.
+// The protocol is such that each side only has a block or two on
+// its free list at a time, so there's no need to worry about
+// trimming the list, etc.
+func (hc *halfConn) freeBlock(b *block) {
+	b.link = hc.bfree
+	hc.bfree = b
+}
+
+// splitBlock splits a block after the first n bytes,
+// returning a block with those n bytes and a
+// block with the remainder.  the latter may be nil.
+func (hc *halfConn) splitBlock(b *block, n int) (*block, *block) {
+	if len(b.data) <= n {
+		return b, nil
+	}
+	bb := hc.newBlock()
+	bb.resize(len(b.data) - n)
+	copy(bb.data, b.data[n:])
+	b.data = b.data[0:n]
+	return b, bb
+}
+
+// readRecord reads the next TLS record from the connection
+// and updates the record layer state.
+// c.in.Mutex <= L; c.input == nil.
+func (c *Conn) readRecord(want recordType) error {
+	// Caller must be in sync with connection:
+	// handshake data if handshake not yet completed,
+	// else application data.  (We don't support renegotiation.)
+	switch want {
+	default:
+		c.sendAlert(alertInternalError)
+		return c.in.setErrorLocked(errors.New("tls: unknown record type requested"))
+	case recordTypeHandshake, recordTypeChangeCipherSpec:
+		if c.handshakeComplete {
+			c.sendAlert(alertInternalError)
+			return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested after handshake complete"))
+		}
+	case recordTypeApplicationData:
+		if !c.handshakeComplete {
+			c.sendAlert(alertInternalError)
+			return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete"))
+		}
+	}
+
+Again:
+	if c.rawInput == nil {
+		c.rawInput = c.in.newBlock()
+	}
+	b := c.rawInput
+
+	// Read header, payload.
+	if err := b.readFromUntil(c.conn, recordHeaderLen); err != nil {
+		// RFC suggests that EOF without an alertCloseNotify is
+		// an error, but popular web sites seem to do this,
+		// so we can't make it an error.
+		// if err == io.EOF {
+		// 	err = io.ErrUnexpectedEOF
+		// }
+		if e, ok := err.(net.Error); !ok || !e.Temporary() {
+			c.in.setErrorLocked(err)
+		}
+		return err
+	}
+	typ := recordType(b.data[0])
+
+	// No valid TLS record has a type of 0x80, however SSLv2 handshakes
+	// start with a uint16 length where the MSB is set and the first record
+	// is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
+	// an SSLv2 client.
+	if want == recordTypeHandshake && typ == 0x80 {
+		c.sendAlert(alertProtocolVersion)
+		return c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
+	}
+
+	vers := uint16(b.data[1])<<8 | uint16(b.data[2])
+	n := int(b.data[3])<<8 | int(b.data[4])
+	if c.haveVers && vers != c.vers {
+		c.sendAlert(alertProtocolVersion)
+		return c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers))
+	}
+	if n > maxCiphertext {
+		c.sendAlert(alertRecordOverflow)
+		return c.in.setErrorLocked(fmt.Errorf("tls: oversized record received with length %d", n))
+	}
+	if !c.haveVers {
+		// First message, be extra suspicious:
+		// this might not be a TLS client.
+		// Bail out before reading a full 'body', if possible.
+		// The current max version is 3.1.
+		// If the version is >= 16.0, it's probably not real.
+		// Similarly, a clientHello message encodes in
+		// well under a kilobyte.  If the length is >= 12 kB,
+		// it's probably not real.
+		if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 || n >= 0x3000 {
+			c.sendAlert(alertUnexpectedMessage)
+			return c.in.setErrorLocked(fmt.Errorf("tls: first record does not look like a TLS handshake"))
+		}
+	}
+	if err := b.readFromUntil(c.conn, recordHeaderLen+n); err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		if e, ok := err.(net.Error); !ok || !e.Temporary() {
+			c.in.setErrorLocked(err)
+		}
+		return err
+	}
+
+	// Process message.
+	b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
+	ok, off, err := c.in.decrypt(b)
+	if !ok {
+		c.in.setErrorLocked(c.sendAlert(err))
+	}
+	b.off = off
+	data := b.data[b.off:]
+	if len(data) > maxPlaintext {
+		err := c.sendAlert(alertRecordOverflow)
+		c.in.freeBlock(b)
+		return c.in.setErrorLocked(err)
+	}
+
+	switch typ {
+	default:
+		c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+
+	case recordTypeAlert:
+		if len(data) != 2 {
+			c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+			break
+		}
+		if alert(data[1]) == alertCloseNotify {
+			c.in.setErrorLocked(io.EOF)
+			break
+		}
+		switch data[0] {
+		case alertLevelWarning:
+			// drop on the floor
+			c.in.freeBlock(b)
+			goto Again
+		case alertLevelError:
+			c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])})
+		default:
+			c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+		}
+
+	case recordTypeChangeCipherSpec:
+		if typ != want || len(data) != 1 || data[0] != 1 {
+			c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+			break
+		}
+		err := c.in.changeCipherSpec()
+		if err != nil {
+			c.in.setErrorLocked(c.sendAlert(err.(alert)))
+		}
+
+	case recordTypeApplicationData:
+		if typ != want {
+			c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+			break
+		}
+		c.input = b
+		b = nil
+
+	case recordTypeHandshake:
+		// TODO(rsc): Should at least pick off connection close.
+		if typ != want {
+			return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation))
+		}
+		c.hand.Write(data)
+	}
+
+	if b != nil {
+		c.in.freeBlock(b)
+	}
+	return c.in.err
+}
+
+// sendAlert sends a TLS alert message.
+// c.out.Mutex <= L.
+func (c *Conn) sendAlertLocked(err alert) error {
+	switch err {
+	case alertNoRenegotiation, alertCloseNotify:
+		c.tmp[0] = alertLevelWarning
+	default:
+		c.tmp[0] = alertLevelError
+	}
+	c.tmp[1] = byte(err)
+	c.writeRecord(recordTypeAlert, c.tmp[0:2])
+	// closeNotify is a special case in that it isn't an error:
+	if err != alertCloseNotify {
+		return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
+	}
+	return nil
+}
+
+// sendAlert sends a TLS alert message.
+// L < c.out.Mutex.
+func (c *Conn) sendAlert(err alert) error {
+	c.out.Lock()
+	defer c.out.Unlock()
+	return c.sendAlertLocked(err)
+}
+
+// writeRecord writes a TLS record with the given type and payload
+// to the connection and updates the record layer state.
+// c.out.Mutex <= L.
+func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
+	b := c.out.newBlock()
+	for len(data) > 0 {
+		m := len(data)
+		if m > maxPlaintext {
+			m = maxPlaintext
+		}
+		explicitIVLen := 0
+		explicitIVIsSeq := false
+
+		var cbc cbcMode
+		if c.out.version >= VersionTLS11 {
+			var ok bool
+			if cbc, ok = c.out.cipher.(cbcMode); ok {
+				explicitIVLen = cbc.BlockSize()
+			}
+		}
+		if explicitIVLen == 0 {
+			if _, ok := c.out.cipher.(cipher.AEAD); ok {
+				explicitIVLen = 8
+				// The AES-GCM construction in TLS has an
+				// explicit nonce so that the nonce can be
+				// random. However, the nonce is only 8 bytes
+				// which is too small for a secure, random
+				// nonce. Therefore we use the sequence number
+				// as the nonce.
+				explicitIVIsSeq = true
+			}
+		}
+		b.resize(recordHeaderLen + explicitIVLen + m)
+		b.data[0] = byte(typ)
+		vers := c.vers
+		if vers == 0 {
+			// Some TLS servers fail if the record version is
+			// greater than TLS 1.0 for the initial ClientHello.
+			vers = VersionTLS10
+		}
+		b.data[1] = byte(vers >> 8)
+		b.data[2] = byte(vers)
+		b.data[3] = byte(m >> 8)
+		b.data[4] = byte(m)
+		if explicitIVLen > 0 {
+			explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
+			if explicitIVIsSeq {
+				copy(explicitIV, c.out.seq[:])
+			} else {
+				if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil {
+					break
+				}
+			}
+		}
+		copy(b.data[recordHeaderLen+explicitIVLen:], data)
+		c.out.encrypt(b, explicitIVLen)
+		_, err = c.conn.Write(b.data)
+		if err != nil {
+			break
+		}
+		n += m
+		data = data[m:]
+	}
+	c.out.freeBlock(b)
+
+	if typ == recordTypeChangeCipherSpec {
+		err = c.out.changeCipherSpec()
+		if err != nil {
+			// Cannot call sendAlert directly,
+			// because we already hold c.out.Mutex.
+			c.tmp[0] = alertLevelError
+			c.tmp[1] = byte(err.(alert))
+			c.writeRecord(recordTypeAlert, c.tmp[0:2])
+			return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
+		}
+	}
+	return
+}
+
+// readHandshake reads the next handshake message from
+// the record layer.
+// c.in.Mutex < L; c.out.Mutex < L.
+func (c *Conn) readHandshake() (interface{}, error) {
+	for c.hand.Len() < 4 {
+		if err := c.in.err; err != nil {
+			return nil, err
+		}
+		if err := c.readRecord(recordTypeHandshake); err != nil {
+			return nil, err
+		}
+	}
+
+	data := c.hand.Bytes()
+	n := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+	if n > maxHandshake {
+		return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError))
+	}
+	for c.hand.Len() < 4+n {
+		if err := c.in.err; err != nil {
+			return nil, err
+		}
+		if err := c.readRecord(recordTypeHandshake); err != nil {
+			return nil, err
+		}
+	}
+	data = c.hand.Next(4 + n)
+	var m handshakeMessage
+	switch data[0] {
+	case typeClientHello:
+		m = new(clientHelloMsg)
+	case typeServerHello:
+		m = new(serverHelloMsg)
+	case typeNewSessionTicket:
+		m = new(newSessionTicketMsg)
+	case typeCertificate:
+		m = new(certificateMsg)
+	case typeCertificateRequest:
+		m = &certificateRequestMsg{
+			hasSignatureAndHash: c.vers >= VersionTLS12,
+		}
+	case typeCertificateStatus:
+		m = new(certificateStatusMsg)
+	case typeServerKeyExchange:
+		m = new(serverKeyExchangeMsg)
+	case typeServerHelloDone:
+		m = new(serverHelloDoneMsg)
+	case typeClientKeyExchange:
+		m = new(clientKeyExchangeMsg)
+	case typeCertificateVerify:
+		m = &certificateVerifyMsg{
+			hasSignatureAndHash: c.vers >= VersionTLS12,
+		}
+	case typeNextProtocol:
+		m = new(nextProtoMsg)
+	case typeFinished:
+		m = new(finishedMsg)
+	default:
+		return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+	}
+
+	// The handshake message unmarshallers
+	// expect to be able to keep references to data,
+	// so pass in a fresh copy that won't be overwritten.
+	data = append([]byte(nil), data...)
+
+	if !m.unmarshal(data) {
+		return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+	}
+	return m, nil
+}
+
+// Write writes data to the connection.
+func (c *Conn) Write(b []byte) (int, error) {
+	if err := c.Handshake(); err != nil {
+		return 0, err
+	}
+
+	c.out.Lock()
+	defer c.out.Unlock()
+
+	if err := c.out.err; err != nil {
+		return 0, err
+	}
+
+	if !c.handshakeComplete {
+		return 0, alertInternalError
+	}
+
+	// SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
+	// attack when using block mode ciphers due to predictable IVs.
+	// This can be prevented by splitting each Application Data
+	// record into two records, effectively randomizing the IV.
+	//
+	// http://www.openssl.org/~bodo/tls-cbc.txt
+	// https://bugzilla.mozilla.org/show_bug.cgi?id=665814
+	// http://www.imperialviolet.org/2012/01/15/beastfollowup.html
+
+	var m int
+	if len(b) > 1 && c.vers <= VersionTLS10 {
+		if _, ok := c.out.cipher.(cipher.BlockMode); ok {
+			n, err := c.writeRecord(recordTypeApplicationData, b[:1])
+			if err != nil {
+				return n, c.out.setErrorLocked(err)
+			}
+			m, b = 1, b[1:]
+		}
+	}
+
+	n, err := c.writeRecord(recordTypeApplicationData, b)
+	return n + m, c.out.setErrorLocked(err)
+}
+
+// Read can be made to time out and return a net.Error with Timeout() == true
+// after a fixed time limit; see SetDeadline and SetReadDeadline.
+func (c *Conn) Read(b []byte) (n int, err error) {
+	if err = c.Handshake(); err != nil {
+		return
+	}
+	if len(b) == 0 {
+		// Put this after Handshake, in case people were calling
+		// Read(nil) for the side effect of the Handshake.
+		return
+	}
+
+	c.in.Lock()
+	defer c.in.Unlock()
+
+	// Some OpenSSL servers send empty records in order to randomize the
+	// CBC IV. So this loop ignores a limited number of empty records.
+	const maxConsecutiveEmptyRecords = 100
+	for emptyRecordCount := 0; emptyRecordCount <= maxConsecutiveEmptyRecords; emptyRecordCount++ {
+		for c.input == nil && c.in.err == nil {
+			if err := c.readRecord(recordTypeApplicationData); err != nil {
+				// Soft error, like EAGAIN
+				return 0, err
+			}
+		}
+		if err := c.in.err; err != nil {
+			return 0, err
+		}
+
+		n, err = c.input.Read(b)
+		if c.input.off >= len(c.input.data) {
+			c.in.freeBlock(c.input)
+			c.input = nil
+		}
+
+		// If a close-notify alert is waiting, read it so that
+		// we can return (n, EOF) instead of (n, nil), to signal
+		// to the HTTP response reading goroutine that the
+		// connection is now closed. This eliminates a race
+		// where the HTTP response reading goroutine would
+		// otherwise not observe the EOF until its next read,
+		// by which time a client goroutine might have already
+		// tried to reuse the HTTP connection for a new
+		// request.
+		// See https://codereview.appspot.com/76400046
+		// and http://golang.org/issue/3514
+		if ri := c.rawInput; ri != nil &&
+			n != 0 && err == nil &&
+			c.input == nil && len(ri.data) > 0 && recordType(ri.data[0]) == recordTypeAlert {
+			if recErr := c.readRecord(recordTypeApplicationData); recErr != nil {
+				err = recErr // will be io.EOF on closeNotify
+			}
+		}
+
+		if n != 0 || err != nil {
+			return n, err
+		}
+	}
+
+	return 0, io.ErrNoProgress
+}
+
+// Close closes the connection.
+func (c *Conn) Close() error {
+	var alertErr error
+
+	c.handshakeMutex.Lock()
+	defer c.handshakeMutex.Unlock()
+	if c.handshakeComplete {
+		alertErr = c.sendAlert(alertCloseNotify)
+	}
+
+	if err := c.conn.Close(); err != nil {
+		return err
+	}
+	return alertErr
+}
+
+// Handshake runs the client or server handshake
+// protocol if it has not yet been run.
+// Most uses of this package need not call Handshake
+// explicitly: the first Read or Write will call it automatically.
+func (c *Conn) Handshake() error {
+	c.handshakeMutex.Lock()
+	defer c.handshakeMutex.Unlock()
+	if err := c.handshakeErr; err != nil {
+		return err
+	}
+	if c.handshakeComplete {
+		return nil
+	}
+
+	if c.isClient {
+		c.handshakeErr = c.clientHandshake()
+	} else {
+		c.handshakeErr = c.serverHandshake()
+	}
+	return c.handshakeErr
+}
+
+// ConnectionState returns basic TLS details about the connection.
+func (c *Conn) ConnectionState() ConnectionState {
+	c.handshakeMutex.Lock()
+	defer c.handshakeMutex.Unlock()
+
+	var state ConnectionState
+	state.HandshakeComplete = c.handshakeComplete
+	if c.handshakeComplete {
+		state.Version = c.vers
+		state.NegotiatedProtocol = c.clientProtocol
+		state.DidResume = c.didResume
+		state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
+		state.CipherSuite = c.cipherSuite
+		state.PeerCertificates = c.peerCertificates
+		state.VerifiedChains = c.verifiedChains
+		state.ServerName = c.serverName
+	}
+
+	return state
+}
+
+// OCSPResponse returns the stapled OCSP response from the TLS server, if
+// any. (Only valid for client connections.)
+func (c *Conn) OCSPResponse() []byte {
+	c.handshakeMutex.Lock()
+	defer c.handshakeMutex.Unlock()
+
+	return c.ocspResponse
+}
+
+// VerifyHostname checks that the peer certificate chain is valid for
+// connecting to host.  If so, it returns nil; if not, it returns an error
+// describing the problem.
+func (c *Conn) VerifyHostname(host string) error {
+	c.handshakeMutex.Lock()
+	defer c.handshakeMutex.Unlock()
+	if !c.isClient {
+		return errors.New("tls: VerifyHostname called on TLS server connection")
+	}
+	if !c.handshakeComplete {
+		return errors.New("tls: handshake has not yet been performed")
+	}
+	return c.peerCertificates[0].VerifyHostname(host)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/conn_test.go b/third_party/gofrontend/libgo/go/crypto/tls/conn_test.go
new file mode 100644
index 0000000..5c55514
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/conn_test.go
@@ -0,0 +1,106 @@
+// Copyright 2010 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 tls
+
+import (
+	"testing"
+)
+
+func TestRoundUp(t *testing.T) {
+	if roundUp(0, 16) != 0 ||
+		roundUp(1, 16) != 16 ||
+		roundUp(15, 16) != 16 ||
+		roundUp(16, 16) != 16 ||
+		roundUp(17, 16) != 32 {
+		t.Error("roundUp broken")
+	}
+}
+
+var paddingTests = []struct {
+	in          []byte
+	good        bool
+	expectedLen int
+}{
+	{[]byte{1, 2, 3, 4, 0}, true, 4},
+	{[]byte{1, 2, 3, 4, 0, 1}, false, 0},
+	{[]byte{1, 2, 3, 4, 99, 99}, false, 0},
+	{[]byte{1, 2, 3, 4, 1, 1}, true, 4},
+	{[]byte{1, 2, 3, 2, 2, 2}, true, 3},
+	{[]byte{1, 2, 3, 3, 3, 3}, true, 2},
+	{[]byte{1, 2, 3, 4, 3, 3}, false, 0},
+	{[]byte{1, 4, 4, 4, 4, 4}, true, 1},
+	{[]byte{5, 5, 5, 5, 5, 5}, true, 0},
+	{[]byte{6, 6, 6, 6, 6, 6}, false, 0},
+}
+
+func TestRemovePadding(t *testing.T) {
+	for i, test := range paddingTests {
+		payload, good := removePadding(test.in)
+		expectedGood := byte(255)
+		if !test.good {
+			expectedGood = 0
+		}
+		if good != expectedGood {
+			t.Errorf("#%d: wrong validity, want:%d got:%d", i, expectedGood, good)
+		}
+		if good == 255 && len(payload) != test.expectedLen {
+			t.Errorf("#%d: got %d, want %d", i, len(payload), test.expectedLen)
+		}
+	}
+}
+
+var certExampleCom = `308201403081eda003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313138353835325a170d3132303933303138353835325a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31a301830160603551d11040f300d820b6578616d706c652e636f6d300b06092a864886f70d0101050341001a0b419d2c74474c6450654e5f10b32bf426ffdf55cad1c52602e7a9151513a3424c70f5960dcd682db0c33769cc1daa3fcdd3db10809d2392ed4a1bf50ced18`
+
+var certWildcardExampleCom = `308201423081efa003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303034365a170d3132303933303139303034365a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31c301a30180603551d110411300f820d2a2e6578616d706c652e636f6d300b06092a864886f70d0101050341001676f0c9e7c33c1b656ed5a6476c4e2ee9ec8e62df7407accb1875272b2edd0a22096cb2c22598d11604104d604f810eb4b5987ca6bb319c7e6ce48725c54059`
+
+var certFooExampleCom = `308201443081f1a003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303131345a170d3132303933303139303131345a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31e301c301a0603551d1104133011820f666f6f2e6578616d706c652e636f6d300b06092a864886f70d010105034100646a2a51f2aa2477add854b462cf5207ba16d3213ffb5d3d0eed473fbf09935019192d1d5b8ca6a2407b424cf04d97c4cd9197c83ecf81f0eab9464a1109d09f`
+
+var certDoubleWildcardExampleCom = `308201443081f1a003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303134315a170d3132303933303139303134315a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31e301c301a0603551d1104133011820f2a2e2a2e6578616d706c652e636f6d300b06092a864886f70d0101050341001c3de267975f56ef57771c6218ef95ecc65102e57bd1defe6f7efea90d9b26cf40de5bd7ad75e46201c7f2a92aaa3e907451e9409f65e28ddb6db80d726290f6`
+
+func TestCertificateSelection(t *testing.T) {
+	config := Config{
+		Certificates: []Certificate{
+			{
+				Certificate: [][]byte{fromHex(certExampleCom)},
+			},
+			{
+				Certificate: [][]byte{fromHex(certWildcardExampleCom)},
+			},
+			{
+				Certificate: [][]byte{fromHex(certFooExampleCom)},
+			},
+			{
+				Certificate: [][]byte{fromHex(certDoubleWildcardExampleCom)},
+			},
+		},
+	}
+
+	config.BuildNameToCertificate()
+
+	pointerToIndex := func(c *Certificate) int {
+		for i := range config.Certificates {
+			if c == &config.Certificates[i] {
+				return i
+			}
+		}
+		return -1
+	}
+
+	if n := pointerToIndex(config.getCertificateForName("example.com")); n != 0 {
+		t.Errorf("example.com returned certificate %d, not 0", n)
+	}
+	if n := pointerToIndex(config.getCertificateForName("bar.example.com")); n != 1 {
+		t.Errorf("bar.example.com returned certificate %d, not 1", n)
+	}
+	if n := pointerToIndex(config.getCertificateForName("foo.example.com")); n != 2 {
+		t.Errorf("foo.example.com returned certificate %d, not 2", n)
+	}
+	if n := pointerToIndex(config.getCertificateForName("foo.bar.example.com")); n != 3 {
+		t.Errorf("foo.bar.example.com returned certificate %d, not 3", n)
+	}
+	if n := pointerToIndex(config.getCertificateForName("foo.bar.baz.example.com")); n != 0 {
+		t.Errorf("foo.bar.baz.example.com returned certificate %d, not 0", n)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/generate_cert.go b/third_party/gofrontend/libgo/go/crypto/tls/generate_cert.go
new file mode 100644
index 0000000..5c6d839
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/generate_cert.go
@@ -0,0 +1,115 @@
+// 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.
+
+// +build ignore
+
+// Generate a self-signed X.509 certificate for a TLS server. Outputs to
+// 'cert.pem' and 'key.pem' and will overwrite existing files.
+
+package main
+
+import (
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"flag"
+	"fmt"
+	"log"
+	"math/big"
+	"net"
+	"os"
+	"strings"
+	"time"
+)
+
+var (
+	host      = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
+	validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
+	validFor  = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
+	isCA      = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
+	rsaBits   = flag.Int("rsa-bits", 2048, "Size of RSA key to generate")
+)
+
+func main() {
+	flag.Parse()
+
+	if len(*host) == 0 {
+		log.Fatalf("Missing required --host parameter")
+	}
+
+	priv, err := rsa.GenerateKey(rand.Reader, *rsaBits)
+	if err != nil {
+		log.Fatalf("failed to generate private key: %s", err)
+	}
+
+	var notBefore time.Time
+	if len(*validFrom) == 0 {
+		notBefore = time.Now()
+	} else {
+		notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err)
+			os.Exit(1)
+		}
+	}
+
+	notAfter := notBefore.Add(*validFor)
+
+	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+	if err != nil {
+		log.Fatalf("failed to generate serial number: %s", err)
+	}
+
+	template := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Acme Co"},
+		},
+		NotBefore: notBefore,
+		NotAfter:  notAfter,
+
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+		BasicConstraintsValid: true,
+	}
+
+	hosts := strings.Split(*host, ",")
+	for _, h := range hosts {
+		if ip := net.ParseIP(h); ip != nil {
+			template.IPAddresses = append(template.IPAddresses, ip)
+		} else {
+			template.DNSNames = append(template.DNSNames, h)
+		}
+	}
+
+	if *isCA {
+		template.IsCA = true
+		template.KeyUsage |= x509.KeyUsageCertSign
+	}
+
+	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
+	if err != nil {
+		log.Fatalf("Failed to create certificate: %s", err)
+	}
+
+	certOut, err := os.Create("cert.pem")
+	if err != nil {
+		log.Fatalf("failed to open cert.pem for writing: %s", err)
+	}
+	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
+	certOut.Close()
+	log.Print("written cert.pem\n")
+
+	keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+	if err != nil {
+		log.Print("failed to open key.pem for writing:", err)
+		return
+	}
+	pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
+	keyOut.Close()
+	log.Print("written key.pem\n")
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/handshake_client.go b/third_party/gofrontend/libgo/go/crypto/tls/handshake_client.go
new file mode 100644
index 0000000..a320fde
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/handshake_client.go
@@ -0,0 +1,601 @@
+// 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 tls
+
+import (
+	"bytes"
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"crypto/subtle"
+	"crypto/x509"
+	"encoding/asn1"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"strconv"
+)
+
+type clientHandshakeState struct {
+	c            *Conn
+	serverHello  *serverHelloMsg
+	hello        *clientHelloMsg
+	suite        *cipherSuite
+	finishedHash finishedHash
+	masterSecret []byte
+	session      *ClientSessionState
+}
+
+func (c *Conn) clientHandshake() error {
+	if c.config == nil {
+		c.config = defaultConfig()
+	}
+
+	if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify {
+		return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
+	}
+
+	hello := &clientHelloMsg{
+		vers:                c.config.maxVersion(),
+		compressionMethods:  []uint8{compressionNone},
+		random:              make([]byte, 32),
+		ocspStapling:        true,
+		serverName:          c.config.ServerName,
+		supportedCurves:     c.config.curvePreferences(),
+		supportedPoints:     []uint8{pointFormatUncompressed},
+		nextProtoNeg:        len(c.config.NextProtos) > 0,
+		secureRenegotiation: true,
+	}
+
+	possibleCipherSuites := c.config.cipherSuites()
+	hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
+
+NextCipherSuite:
+	for _, suiteId := range possibleCipherSuites {
+		for _, suite := range cipherSuites {
+			if suite.id != suiteId {
+				continue
+			}
+			// Don't advertise TLS 1.2-only cipher suites unless
+			// we're attempting TLS 1.2.
+			if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
+				continue
+			}
+			hello.cipherSuites = append(hello.cipherSuites, suiteId)
+			continue NextCipherSuite
+		}
+	}
+
+	_, err := io.ReadFull(c.config.rand(), hello.random)
+	if err != nil {
+		c.sendAlert(alertInternalError)
+		return errors.New("tls: short read from Rand: " + err.Error())
+	}
+
+	if hello.vers >= VersionTLS12 {
+		hello.signatureAndHashes = supportedSKXSignatureAlgorithms
+	}
+
+	var session *ClientSessionState
+	var cacheKey string
+	sessionCache := c.config.ClientSessionCache
+	if c.config.SessionTicketsDisabled {
+		sessionCache = nil
+	}
+
+	if sessionCache != nil {
+		hello.ticketSupported = true
+
+		// Try to resume a previously negotiated TLS session, if
+		// available.
+		cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
+		candidateSession, ok := sessionCache.Get(cacheKey)
+		if ok {
+			// Check that the ciphersuite/version used for the
+			// previous session are still valid.
+			cipherSuiteOk := false
+			for _, id := range hello.cipherSuites {
+				if id == candidateSession.cipherSuite {
+					cipherSuiteOk = true
+					break
+				}
+			}
+
+			versOk := candidateSession.vers >= c.config.minVersion() &&
+				candidateSession.vers <= c.config.maxVersion()
+			if versOk && cipherSuiteOk {
+				session = candidateSession
+			}
+		}
+	}
+
+	if session != nil {
+		hello.sessionTicket = session.sessionTicket
+		// A random session ID is used to detect when the
+		// server accepted the ticket and is resuming a session
+		// (see RFC 5077).
+		hello.sessionId = make([]byte, 16)
+		if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
+			c.sendAlert(alertInternalError)
+			return errors.New("tls: short read from Rand: " + err.Error())
+		}
+	}
+
+	c.writeRecord(recordTypeHandshake, hello.marshal())
+
+	msg, err := c.readHandshake()
+	if err != nil {
+		return err
+	}
+	serverHello, ok := msg.(*serverHelloMsg)
+	if !ok {
+		c.sendAlert(alertUnexpectedMessage)
+		return unexpectedMessageError(serverHello, msg)
+	}
+
+	vers, ok := c.config.mutualVersion(serverHello.vers)
+	if !ok || vers < VersionTLS10 {
+		// TLS 1.0 is the minimum version supported as a client.
+		c.sendAlert(alertProtocolVersion)
+		return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers)
+	}
+	c.vers = vers
+	c.haveVers = true
+
+	suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
+	if suite == nil {
+		c.sendAlert(alertHandshakeFailure)
+		return fmt.Errorf("tls: server selected an unsupported cipher suite")
+	}
+
+	hs := &clientHandshakeState{
+		c:            c,
+		serverHello:  serverHello,
+		hello:        hello,
+		suite:        suite,
+		finishedHash: newFinishedHash(c.vers),
+		session:      session,
+	}
+
+	hs.finishedHash.Write(hs.hello.marshal())
+	hs.finishedHash.Write(hs.serverHello.marshal())
+
+	isResume, err := hs.processServerHello()
+	if err != nil {
+		return err
+	}
+
+	if isResume {
+		if err := hs.establishKeys(); err != nil {
+			return err
+		}
+		if err := hs.readSessionTicket(); err != nil {
+			return err
+		}
+		if err := hs.readFinished(); err != nil {
+			return err
+		}
+		if err := hs.sendFinished(); err != nil {
+			return err
+		}
+	} else {
+		if err := hs.doFullHandshake(); err != nil {
+			return err
+		}
+		if err := hs.establishKeys(); err != nil {
+			return err
+		}
+		if err := hs.sendFinished(); err != nil {
+			return err
+		}
+		if err := hs.readSessionTicket(); err != nil {
+			return err
+		}
+		if err := hs.readFinished(); err != nil {
+			return err
+		}
+	}
+
+	if sessionCache != nil && hs.session != nil && session != hs.session {
+		sessionCache.Put(cacheKey, hs.session)
+	}
+
+	c.didResume = isResume
+	c.handshakeComplete = true
+	c.cipherSuite = suite.id
+	return nil
+}
+
+func (hs *clientHandshakeState) doFullHandshake() error {
+	c := hs.c
+
+	msg, err := c.readHandshake()
+	if err != nil {
+		return err
+	}
+	certMsg, ok := msg.(*certificateMsg)
+	if !ok || len(certMsg.certificates) == 0 {
+		c.sendAlert(alertUnexpectedMessage)
+		return unexpectedMessageError(certMsg, msg)
+	}
+	hs.finishedHash.Write(certMsg.marshal())
+
+	certs := make([]*x509.Certificate, len(certMsg.certificates))
+	for i, asn1Data := range certMsg.certificates {
+		cert, err := x509.ParseCertificate(asn1Data)
+		if err != nil {
+			c.sendAlert(alertBadCertificate)
+			return errors.New("tls: failed to parse certificate from server: " + err.Error())
+		}
+		certs[i] = cert
+	}
+
+	if !c.config.InsecureSkipVerify {
+		opts := x509.VerifyOptions{
+			Roots:         c.config.RootCAs,
+			CurrentTime:   c.config.time(),
+			DNSName:       c.config.ServerName,
+			Intermediates: x509.NewCertPool(),
+		}
+
+		for i, cert := range certs {
+			if i == 0 {
+				continue
+			}
+			opts.Intermediates.AddCert(cert)
+		}
+		c.verifiedChains, err = certs[0].Verify(opts)
+		if err != nil {
+			c.sendAlert(alertBadCertificate)
+			return err
+		}
+	}
+
+	switch certs[0].PublicKey.(type) {
+	case *rsa.PublicKey, *ecdsa.PublicKey:
+		break
+	default:
+		c.sendAlert(alertUnsupportedCertificate)
+		return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
+	}
+
+	c.peerCertificates = certs
+
+	if hs.serverHello.ocspStapling {
+		msg, err = c.readHandshake()
+		if err != nil {
+			return err
+		}
+		cs, ok := msg.(*certificateStatusMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(cs, msg)
+		}
+		hs.finishedHash.Write(cs.marshal())
+
+		if cs.statusType == statusTypeOCSP {
+			c.ocspResponse = cs.response
+		}
+	}
+
+	msg, err = c.readHandshake()
+	if err != nil {
+		return err
+	}
+
+	keyAgreement := hs.suite.ka(c.vers)
+
+	skx, ok := msg.(*serverKeyExchangeMsg)
+	if ok {
+		hs.finishedHash.Write(skx.marshal())
+		err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, certs[0], skx)
+		if err != nil {
+			c.sendAlert(alertUnexpectedMessage)
+			return err
+		}
+
+		msg, err = c.readHandshake()
+		if err != nil {
+			return err
+		}
+	}
+
+	var chainToSend *Certificate
+	var certRequested bool
+	certReq, ok := msg.(*certificateRequestMsg)
+	if ok {
+		certRequested = true
+
+		// RFC 4346 on the certificateAuthorities field:
+		// A list of the distinguished names of acceptable certificate
+		// authorities. These distinguished names may specify a desired
+		// distinguished name for a root CA or for a subordinate CA;
+		// thus, this message can be used to describe both known roots
+		// and a desired authorization space. If the
+		// certificate_authorities list is empty then the client MAY
+		// send any certificate of the appropriate
+		// ClientCertificateType, unless there is some external
+		// arrangement to the contrary.
+
+		hs.finishedHash.Write(certReq.marshal())
+
+		var rsaAvail, ecdsaAvail bool
+		for _, certType := range certReq.certificateTypes {
+			switch certType {
+			case certTypeRSASign:
+				rsaAvail = true
+			case certTypeECDSASign:
+				ecdsaAvail = true
+			}
+		}
+
+		// We need to search our list of client certs for one
+		// where SignatureAlgorithm is RSA and the Issuer is in
+		// certReq.certificateAuthorities
+	findCert:
+		for i, chain := range c.config.Certificates {
+			if !rsaAvail && !ecdsaAvail {
+				continue
+			}
+
+			for j, cert := range chain.Certificate {
+				x509Cert := chain.Leaf
+				// parse the certificate if this isn't the leaf
+				// node, or if chain.Leaf was nil
+				if j != 0 || x509Cert == nil {
+					if x509Cert, err = x509.ParseCertificate(cert); err != nil {
+						c.sendAlert(alertInternalError)
+						return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
+					}
+				}
+
+				switch {
+				case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
+				case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
+				default:
+					continue findCert
+				}
+
+				if len(certReq.certificateAuthorities) == 0 {
+					// they gave us an empty list, so just take the
+					// first RSA cert from c.config.Certificates
+					chainToSend = &chain
+					break findCert
+				}
+
+				for _, ca := range certReq.certificateAuthorities {
+					if bytes.Equal(x509Cert.RawIssuer, ca) {
+						chainToSend = &chain
+						break findCert
+					}
+				}
+			}
+		}
+
+		msg, err = c.readHandshake()
+		if err != nil {
+			return err
+		}
+	}
+
+	shd, ok := msg.(*serverHelloDoneMsg)
+	if !ok {
+		c.sendAlert(alertUnexpectedMessage)
+		return unexpectedMessageError(shd, msg)
+	}
+	hs.finishedHash.Write(shd.marshal())
+
+	// If the server requested a certificate then we have to send a
+	// Certificate message, even if it's empty because we don't have a
+	// certificate to send.
+	if certRequested {
+		certMsg = new(certificateMsg)
+		if chainToSend != nil {
+			certMsg.certificates = chainToSend.Certificate
+		}
+		hs.finishedHash.Write(certMsg.marshal())
+		c.writeRecord(recordTypeHandshake, certMsg.marshal())
+	}
+
+	preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, certs[0])
+	if err != nil {
+		c.sendAlert(alertInternalError)
+		return err
+	}
+	if ckx != nil {
+		hs.finishedHash.Write(ckx.marshal())
+		c.writeRecord(recordTypeHandshake, ckx.marshal())
+	}
+
+	if chainToSend != nil {
+		var signed []byte
+		certVerify := &certificateVerifyMsg{
+			hasSignatureAndHash: c.vers >= VersionTLS12,
+		}
+
+		switch key := c.config.Certificates[0].PrivateKey.(type) {
+		case *ecdsa.PrivateKey:
+			digest, _, hashId := hs.finishedHash.hashForClientCertificate(signatureECDSA)
+			r, s, err := ecdsa.Sign(c.config.rand(), key, digest)
+			if err == nil {
+				signed, err = asn1.Marshal(ecdsaSignature{r, s})
+			}
+			certVerify.signatureAndHash.signature = signatureECDSA
+			certVerify.signatureAndHash.hash = hashId
+		case *rsa.PrivateKey:
+			digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureRSA)
+			signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
+			certVerify.signatureAndHash.signature = signatureRSA
+			certVerify.signatureAndHash.hash = hashId
+		default:
+			err = errors.New("unknown private key type")
+		}
+		if err != nil {
+			c.sendAlert(alertInternalError)
+			return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
+		}
+		certVerify.signature = signed
+
+		hs.finishedHash.Write(certVerify.marshal())
+		c.writeRecord(recordTypeHandshake, certVerify.marshal())
+	}
+
+	hs.masterSecret = masterFromPreMasterSecret(c.vers, preMasterSecret, hs.hello.random, hs.serverHello.random)
+	return nil
+}
+
+func (hs *clientHandshakeState) establishKeys() error {
+	c := hs.c
+
+	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+		keysFromMasterSecret(c.vers, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
+	var clientCipher, serverCipher interface{}
+	var clientHash, serverHash macFunction
+	if hs.suite.cipher != nil {
+		clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
+		clientHash = hs.suite.mac(c.vers, clientMAC)
+		serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
+		serverHash = hs.suite.mac(c.vers, serverMAC)
+	} else {
+		clientCipher = hs.suite.aead(clientKey, clientIV)
+		serverCipher = hs.suite.aead(serverKey, serverIV)
+	}
+
+	c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
+	c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
+	return nil
+}
+
+func (hs *clientHandshakeState) serverResumedSession() bool {
+	// If the server responded with the same sessionId then it means the
+	// sessionTicket is being used to resume a TLS session.
+	return hs.session != nil && hs.hello.sessionId != nil &&
+		bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
+}
+
+func (hs *clientHandshakeState) processServerHello() (bool, error) {
+	c := hs.c
+
+	if hs.serverHello.compressionMethod != compressionNone {
+		c.sendAlert(alertUnexpectedMessage)
+		return false, errors.New("tls: server selected unsupported compression format")
+	}
+
+	if !hs.hello.nextProtoNeg && hs.serverHello.nextProtoNeg {
+		c.sendAlert(alertHandshakeFailure)
+		return false, errors.New("server advertised unrequested NPN extension")
+	}
+
+	if hs.serverResumedSession() {
+		// Restore masterSecret and peerCerts from previous state
+		hs.masterSecret = hs.session.masterSecret
+		c.peerCertificates = hs.session.serverCertificates
+		return true, nil
+	}
+	return false, nil
+}
+
+func (hs *clientHandshakeState) readFinished() error {
+	c := hs.c
+
+	c.readRecord(recordTypeChangeCipherSpec)
+	if err := c.in.error(); err != nil {
+		return err
+	}
+
+	msg, err := c.readHandshake()
+	if err != nil {
+		return err
+	}
+	serverFinished, ok := msg.(*finishedMsg)
+	if !ok {
+		c.sendAlert(alertUnexpectedMessage)
+		return unexpectedMessageError(serverFinished, msg)
+	}
+
+	verify := hs.finishedHash.serverSum(hs.masterSecret)
+	if len(verify) != len(serverFinished.verifyData) ||
+		subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("tls: server's Finished message was incorrect")
+	}
+	hs.finishedHash.Write(serverFinished.marshal())
+	return nil
+}
+
+func (hs *clientHandshakeState) readSessionTicket() error {
+	if !hs.serverHello.ticketSupported {
+		return nil
+	}
+
+	c := hs.c
+	msg, err := c.readHandshake()
+	if err != nil {
+		return err
+	}
+	sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
+	if !ok {
+		c.sendAlert(alertUnexpectedMessage)
+		return unexpectedMessageError(sessionTicketMsg, msg)
+	}
+	hs.finishedHash.Write(sessionTicketMsg.marshal())
+
+	hs.session = &ClientSessionState{
+		sessionTicket:      sessionTicketMsg.ticket,
+		vers:               c.vers,
+		cipherSuite:        hs.suite.id,
+		masterSecret:       hs.masterSecret,
+		serverCertificates: c.peerCertificates,
+	}
+
+	return nil
+}
+
+func (hs *clientHandshakeState) sendFinished() error {
+	c := hs.c
+
+	c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
+	if hs.serverHello.nextProtoNeg {
+		nextProto := new(nextProtoMsg)
+		proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos)
+		nextProto.proto = proto
+		c.clientProtocol = proto
+		c.clientProtocolFallback = fallback
+
+		hs.finishedHash.Write(nextProto.marshal())
+		c.writeRecord(recordTypeHandshake, nextProto.marshal())
+	}
+
+	finished := new(finishedMsg)
+	finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
+	hs.finishedHash.Write(finished.marshal())
+	c.writeRecord(recordTypeHandshake, finished.marshal())
+	return nil
+}
+
+// clientSessionCacheKey returns a key used to cache sessionTickets that could
+// be used to resume previously negotiated TLS sessions with a server.
+func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
+	if len(config.ServerName) > 0 {
+		return config.ServerName
+	}
+	return serverAddr.String()
+}
+
+// mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
+// set of client and server supported protocols. The set of client supported
+// protocols must not be empty. It returns the resulting protocol and flag
+// indicating if the fallback case was reached.
+func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
+	for _, s := range serverProtos {
+		for _, c := range clientProtos {
+			if s == c {
+				return s, false
+			}
+		}
+	}
+
+	return clientProtos[0], true
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/handshake_client_test.go b/third_party/gofrontend/libgo/go/crypto/tls/handshake_client_test.go
new file mode 100644
index 0000000..0d73c8e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/handshake_client_test.go
@@ -0,0 +1,439 @@
+// Copyright 2010 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 tls
+
+import (
+	"bytes"
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/pem"
+	"fmt"
+	"io"
+	"net"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strconv"
+	"testing"
+	"time"
+)
+
+// Note: see comment in handshake_test.go for details of how the reference
+// tests work.
+
+// blockingSource is an io.Reader that blocks a Read call until it's closed.
+type blockingSource chan bool
+
+func (b blockingSource) Read([]byte) (n int, err error) {
+	<-b
+	return 0, io.EOF
+}
+
+// clientTest represents a test of the TLS client handshake against a reference
+// implementation.
+type clientTest struct {
+	// name is a freeform string identifying the test and the file in which
+	// the expected results will be stored.
+	name string
+	// command, if not empty, contains a series of arguments for the
+	// command to run for the reference server.
+	command []string
+	// config, if not nil, contains a custom Config to use for this test.
+	config *Config
+	// cert, if not empty, contains a DER-encoded certificate for the
+	// reference server.
+	cert []byte
+	// key, if not nil, contains either a *rsa.PrivateKey or
+	// *ecdsa.PrivateKey which is the private key for the reference server.
+	key interface{}
+}
+
+var defaultServerCommand = []string{"openssl", "s_server"}
+
+// connFromCommand starts the reference server process, connects to it and
+// returns a recordingConn for the connection. The stdin return value is a
+// blockingSource for the stdin of the child process. It must be closed before
+// Waiting for child.
+func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, stdin blockingSource, err error) {
+	cert := testRSACertificate
+	if len(test.cert) > 0 {
+		cert = test.cert
+	}
+	certPath := tempFile(string(cert))
+	defer os.Remove(certPath)
+
+	var key interface{} = testRSAPrivateKey
+	if test.key != nil {
+		key = test.key
+	}
+	var pemType string
+	var derBytes []byte
+	switch key := key.(type) {
+	case *rsa.PrivateKey:
+		pemType = "RSA"
+		derBytes = x509.MarshalPKCS1PrivateKey(key)
+	case *ecdsa.PrivateKey:
+		pemType = "EC"
+		var err error
+		derBytes, err = x509.MarshalECPrivateKey(key)
+		if err != nil {
+			panic(err)
+		}
+	default:
+		panic("unknown key type")
+	}
+
+	var pemOut bytes.Buffer
+	pem.Encode(&pemOut, &pem.Block{Type: pemType + " PRIVATE KEY", Bytes: derBytes})
+
+	keyPath := tempFile(string(pemOut.Bytes()))
+	defer os.Remove(keyPath)
+
+	var command []string
+	if len(test.command) > 0 {
+		command = append(command, test.command...)
+	} else {
+		command = append(command, defaultServerCommand...)
+	}
+	command = append(command, "-cert", certPath, "-certform", "DER", "-key", keyPath)
+	// serverPort contains the port that OpenSSL will listen on. OpenSSL
+	// can't take "0" as an argument here so we have to pick a number and
+	// hope that it's not in use on the machine. Since this only occurs
+	// when -update is given and thus when there's a human watching the
+	// test, this isn't too bad.
+	const serverPort = 24323
+	command = append(command, "-accept", strconv.Itoa(serverPort))
+
+	cmd := exec.Command(command[0], command[1:]...)
+	stdin = blockingSource(make(chan bool))
+	cmd.Stdin = stdin
+	var out bytes.Buffer
+	cmd.Stdout = &out
+	cmd.Stderr = &out
+	if err := cmd.Start(); err != nil {
+		return nil, nil, nil, err
+	}
+
+	// OpenSSL does print an "ACCEPT" banner, but it does so *before*
+	// opening the listening socket, so we can't use that to wait until it
+	// has started listening. Thus we are forced to poll until we get a
+	// connection.
+	var tcpConn net.Conn
+	for i := uint(0); i < 5; i++ {
+		var err error
+		tcpConn, err = net.DialTCP("tcp", nil, &net.TCPAddr{
+			IP:   net.IPv4(127, 0, 0, 1),
+			Port: serverPort,
+		})
+		if err == nil {
+			break
+		}
+		time.Sleep((1 << i) * 5 * time.Millisecond)
+	}
+	if tcpConn == nil {
+		close(stdin)
+		out.WriteTo(os.Stdout)
+		cmd.Process.Kill()
+		return nil, nil, nil, cmd.Wait()
+	}
+
+	record := &recordingConn{
+		Conn: tcpConn,
+	}
+
+	return record, cmd, stdin, nil
+}
+
+func (test *clientTest) dataPath() string {
+	return filepath.Join("testdata", "Client-"+test.name)
+}
+
+func (test *clientTest) loadData() (flows [][]byte, err error) {
+	in, err := os.Open(test.dataPath())
+	if err != nil {
+		return nil, err
+	}
+	defer in.Close()
+	return parseTestData(in)
+}
+
+func (test *clientTest) run(t *testing.T, write bool) {
+	var clientConn, serverConn net.Conn
+	var recordingConn *recordingConn
+	var childProcess *exec.Cmd
+	var stdin blockingSource
+
+	if write {
+		var err error
+		recordingConn, childProcess, stdin, err = test.connFromCommand()
+		if err != nil {
+			t.Fatalf("Failed to start subcommand: %s", err)
+		}
+		clientConn = recordingConn
+	} else {
+		clientConn, serverConn = net.Pipe()
+	}
+
+	config := test.config
+	if config == nil {
+		config = testConfig
+	}
+	client := Client(clientConn, config)
+
+	doneChan := make(chan bool)
+	go func() {
+		if _, err := client.Write([]byte("hello\n")); err != nil {
+			t.Logf("Client.Write failed: %s", err)
+		}
+		client.Close()
+		clientConn.Close()
+		doneChan <- true
+	}()
+
+	if !write {
+		flows, err := test.loadData()
+		if err != nil {
+			t.Fatalf("%s: failed to load data from %s", test.name, test.dataPath())
+		}
+		for i, b := range flows {
+			if i%2 == 1 {
+				serverConn.Write(b)
+				continue
+			}
+			bb := make([]byte, len(b))
+			_, err := io.ReadFull(serverConn, bb)
+			if err != nil {
+				t.Fatalf("%s #%d: %s", test.name, i, err)
+			}
+			if !bytes.Equal(b, bb) {
+				t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i, bb, b)
+			}
+		}
+		serverConn.Close()
+	}
+
+	<-doneChan
+
+	if write {
+		path := test.dataPath()
+		out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+		if err != nil {
+			t.Fatalf("Failed to create output file: %s", err)
+		}
+		defer out.Close()
+		recordingConn.Close()
+		close(stdin)
+		childProcess.Process.Kill()
+		childProcess.Wait()
+		if len(recordingConn.flows) < 3 {
+			childProcess.Stdout.(*bytes.Buffer).WriteTo(os.Stdout)
+			t.Fatalf("Client connection didn't work")
+		}
+		recordingConn.WriteTo(out)
+		fmt.Printf("Wrote %s\n", path)
+	}
+}
+
+func runClientTestForVersion(t *testing.T, template *clientTest, prefix, option string) {
+	test := *template
+	test.name = prefix + test.name
+	if len(test.command) == 0 {
+		test.command = defaultClientCommand
+	}
+	test.command = append([]string(nil), test.command...)
+	test.command = append(test.command, option)
+	test.run(t, *update)
+}
+
+func runClientTestTLS10(t *testing.T, template *clientTest) {
+	runClientTestForVersion(t, template, "TLSv10-", "-tls1")
+}
+
+func runClientTestTLS11(t *testing.T, template *clientTest) {
+	runClientTestForVersion(t, template, "TLSv11-", "-tls1_1")
+}
+
+func runClientTestTLS12(t *testing.T, template *clientTest) {
+	runClientTestForVersion(t, template, "TLSv12-", "-tls1_2")
+}
+
+func TestHandshakeClientRSARC4(t *testing.T) {
+	test := &clientTest{
+		name:    "RSA-RC4",
+		command: []string{"openssl", "s_server", "-cipher", "RC4-SHA"},
+	}
+	runClientTestTLS10(t, test)
+	runClientTestTLS11(t, test)
+	runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientECDHERSAAES(t *testing.T) {
+	test := &clientTest{
+		name:    "ECDHE-RSA-AES",
+		command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES128-SHA"},
+	}
+	runClientTestTLS10(t, test)
+	runClientTestTLS11(t, test)
+	runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientECDHEECDSAAES(t *testing.T) {
+	test := &clientTest{
+		name:    "ECDHE-ECDSA-AES",
+		command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA"},
+		cert:    testECDSACertificate,
+		key:     testECDSAPrivateKey,
+	}
+	runClientTestTLS10(t, test)
+	runClientTestTLS11(t, test)
+	runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientECDHEECDSAAESGCM(t *testing.T) {
+	test := &clientTest{
+		name:    "ECDHE-ECDSA-AES-GCM",
+		command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-GCM-SHA256"},
+		cert:    testECDSACertificate,
+		key:     testECDSAPrivateKey,
+	}
+	runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientCertRSA(t *testing.T) {
+	config := *testConfig
+	cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM))
+	config.Certificates = []Certificate{cert}
+
+	test := &clientTest{
+		name:    "ClientCert-RSA-RSA",
+		command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
+		config:  &config,
+	}
+
+	runClientTestTLS10(t, test)
+	runClientTestTLS12(t, test)
+
+	test = &clientTest{
+		name:    "ClientCert-RSA-ECDSA",
+		command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"},
+		config:  &config,
+		cert:    testECDSACertificate,
+		key:     testECDSAPrivateKey,
+	}
+
+	runClientTestTLS10(t, test)
+	runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientCertECDSA(t *testing.T) {
+	config := *testConfig
+	cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM))
+	config.Certificates = []Certificate{cert}
+
+	test := &clientTest{
+		name:    "ClientCert-ECDSA-RSA",
+		command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
+		config:  &config,
+	}
+
+	runClientTestTLS10(t, test)
+	runClientTestTLS12(t, test)
+
+	test = &clientTest{
+		name:    "ClientCert-ECDSA-ECDSA",
+		command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"},
+		config:  &config,
+		cert:    testECDSACertificate,
+		key:     testECDSAPrivateKey,
+	}
+
+	runClientTestTLS10(t, test)
+	runClientTestTLS12(t, test)
+}
+
+func TestClientResumption(t *testing.T) {
+	serverConfig := &Config{
+		CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+		Certificates: testConfig.Certificates,
+	}
+	clientConfig := &Config{
+		CipherSuites:       []uint16{TLS_RSA_WITH_RC4_128_SHA},
+		InsecureSkipVerify: true,
+		ClientSessionCache: NewLRUClientSessionCache(32),
+	}
+
+	testResumeState := func(test string, didResume bool) {
+		hs, err := testHandshake(clientConfig, serverConfig)
+		if err != nil {
+			t.Fatalf("%s: handshake failed: %s", test, err)
+		}
+		if hs.DidResume != didResume {
+			t.Fatalf("%s resumed: %v, expected: %v", test, hs.DidResume, didResume)
+		}
+	}
+
+	testResumeState("Handshake", false)
+	testResumeState("Resume", true)
+
+	if _, err := io.ReadFull(serverConfig.rand(), serverConfig.SessionTicketKey[:]); err != nil {
+		t.Fatalf("Failed to invalidate SessionTicketKey")
+	}
+	testResumeState("InvalidSessionTicketKey", false)
+	testResumeState("ResumeAfterInvalidSessionTicketKey", true)
+
+	clientConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}
+	testResumeState("DifferentCipherSuite", false)
+	testResumeState("DifferentCipherSuiteRecovers", true)
+
+	clientConfig.ClientSessionCache = nil
+	testResumeState("WithoutSessionCache", false)
+}
+
+func TestLRUClientSessionCache(t *testing.T) {
+	// Initialize cache of capacity 4.
+	cache := NewLRUClientSessionCache(4)
+	cs := make([]ClientSessionState, 6)
+	keys := []string{"0", "1", "2", "3", "4", "5", "6"}
+
+	// Add 4 entries to the cache and look them up.
+	for i := 0; i < 4; i++ {
+		cache.Put(keys[i], &cs[i])
+	}
+	for i := 0; i < 4; i++ {
+		if s, ok := cache.Get(keys[i]); !ok || s != &cs[i] {
+			t.Fatalf("session cache failed lookup for added key: %s", keys[i])
+		}
+	}
+
+	// Add 2 more entries to the cache. First 2 should be evicted.
+	for i := 4; i < 6; i++ {
+		cache.Put(keys[i], &cs[i])
+	}
+	for i := 0; i < 2; i++ {
+		if s, ok := cache.Get(keys[i]); ok || s != nil {
+			t.Fatalf("session cache should have evicted key: %s", keys[i])
+		}
+	}
+
+	// Touch entry 2. LRU should evict 3 next.
+	cache.Get(keys[2])
+	cache.Put(keys[0], &cs[0])
+	if s, ok := cache.Get(keys[3]); ok || s != nil {
+		t.Fatalf("session cache should have evicted key 3")
+	}
+
+	// Update entry 0 in place.
+	cache.Put(keys[0], &cs[3])
+	if s, ok := cache.Get(keys[0]); !ok || s != &cs[3] {
+		t.Fatalf("session cache failed update for key 0")
+	}
+
+	// Adding a nil entry is valid.
+	cache.Put(keys[0], nil)
+	if s, ok := cache.Get(keys[0]); !ok || s != nil {
+		t.Fatalf("failed to add nil entry to cache")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/handshake_messages.go b/third_party/gofrontend/libgo/go/crypto/tls/handshake_messages.go
new file mode 100644
index 0000000..7bcaa5e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/handshake_messages.go
@@ -0,0 +1,1344 @@
+// 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 tls
+
+import "bytes"
+
+type clientHelloMsg struct {
+	raw                 []byte
+	vers                uint16
+	random              []byte
+	sessionId           []byte
+	cipherSuites        []uint16
+	compressionMethods  []uint8
+	nextProtoNeg        bool
+	serverName          string
+	ocspStapling        bool
+	supportedCurves     []CurveID
+	supportedPoints     []uint8
+	ticketSupported     bool
+	sessionTicket       []uint8
+	signatureAndHashes  []signatureAndHash
+	secureRenegotiation bool
+}
+
+func (m *clientHelloMsg) equal(i interface{}) bool {
+	m1, ok := i.(*clientHelloMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		m.vers == m1.vers &&
+		bytes.Equal(m.random, m1.random) &&
+		bytes.Equal(m.sessionId, m1.sessionId) &&
+		eqUint16s(m.cipherSuites, m1.cipherSuites) &&
+		bytes.Equal(m.compressionMethods, m1.compressionMethods) &&
+		m.nextProtoNeg == m1.nextProtoNeg &&
+		m.serverName == m1.serverName &&
+		m.ocspStapling == m1.ocspStapling &&
+		eqCurveIDs(m.supportedCurves, m1.supportedCurves) &&
+		bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
+		m.ticketSupported == m1.ticketSupported &&
+		bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
+		eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) &&
+		m.secureRenegotiation == m1.secureRenegotiation
+}
+
+func (m *clientHelloMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	length := 2 + 32 + 1 + len(m.sessionId) + 2 + len(m.cipherSuites)*2 + 1 + len(m.compressionMethods)
+	numExtensions := 0
+	extensionsLength := 0
+	if m.nextProtoNeg {
+		numExtensions++
+	}
+	if m.ocspStapling {
+		extensionsLength += 1 + 2 + 2
+		numExtensions++
+	}
+	if len(m.serverName) > 0 {
+		extensionsLength += 5 + len(m.serverName)
+		numExtensions++
+	}
+	if len(m.supportedCurves) > 0 {
+		extensionsLength += 2 + 2*len(m.supportedCurves)
+		numExtensions++
+	}
+	if len(m.supportedPoints) > 0 {
+		extensionsLength += 1 + len(m.supportedPoints)
+		numExtensions++
+	}
+	if m.ticketSupported {
+		extensionsLength += len(m.sessionTicket)
+		numExtensions++
+	}
+	if len(m.signatureAndHashes) > 0 {
+		extensionsLength += 2 + 2*len(m.signatureAndHashes)
+		numExtensions++
+	}
+	if m.secureRenegotiation {
+		extensionsLength += 1
+		numExtensions++
+	}
+	if numExtensions > 0 {
+		extensionsLength += 4 * numExtensions
+		length += 2 + extensionsLength
+	}
+
+	x := make([]byte, 4+length)
+	x[0] = typeClientHello
+	x[1] = uint8(length >> 16)
+	x[2] = uint8(length >> 8)
+	x[3] = uint8(length)
+	x[4] = uint8(m.vers >> 8)
+	x[5] = uint8(m.vers)
+	copy(x[6:38], m.random)
+	x[38] = uint8(len(m.sessionId))
+	copy(x[39:39+len(m.sessionId)], m.sessionId)
+	y := x[39+len(m.sessionId):]
+	y[0] = uint8(len(m.cipherSuites) >> 7)
+	y[1] = uint8(len(m.cipherSuites) << 1)
+	for i, suite := range m.cipherSuites {
+		y[2+i*2] = uint8(suite >> 8)
+		y[3+i*2] = uint8(suite)
+	}
+	z := y[2+len(m.cipherSuites)*2:]
+	z[0] = uint8(len(m.compressionMethods))
+	copy(z[1:], m.compressionMethods)
+
+	z = z[1+len(m.compressionMethods):]
+	if numExtensions > 0 {
+		z[0] = byte(extensionsLength >> 8)
+		z[1] = byte(extensionsLength)
+		z = z[2:]
+	}
+	if m.nextProtoNeg {
+		z[0] = byte(extensionNextProtoNeg >> 8)
+		z[1] = byte(extensionNextProtoNeg & 0xff)
+		// The length is always 0
+		z = z[4:]
+	}
+	if len(m.serverName) > 0 {
+		z[0] = byte(extensionServerName >> 8)
+		z[1] = byte(extensionServerName & 0xff)
+		l := len(m.serverName) + 5
+		z[2] = byte(l >> 8)
+		z[3] = byte(l)
+		z = z[4:]
+
+		// RFC 3546, section 3.1
+		//
+		// struct {
+		//     NameType name_type;
+		//     select (name_type) {
+		//         case host_name: HostName;
+		//     } name;
+		// } ServerName;
+		//
+		// enum {
+		//     host_name(0), (255)
+		// } NameType;
+		//
+		// opaque HostName<1..2^16-1>;
+		//
+		// struct {
+		//     ServerName server_name_list<1..2^16-1>
+		// } ServerNameList;
+
+		z[0] = byte((len(m.serverName) + 3) >> 8)
+		z[1] = byte(len(m.serverName) + 3)
+		z[3] = byte(len(m.serverName) >> 8)
+		z[4] = byte(len(m.serverName))
+		copy(z[5:], []byte(m.serverName))
+		z = z[l:]
+	}
+	if m.ocspStapling {
+		// RFC 4366, section 3.6
+		z[0] = byte(extensionStatusRequest >> 8)
+		z[1] = byte(extensionStatusRequest)
+		z[2] = 0
+		z[3] = 5
+		z[4] = 1 // OCSP type
+		// Two zero valued uint16s for the two lengths.
+		z = z[9:]
+	}
+	if len(m.supportedCurves) > 0 {
+		// http://tools.ietf.org/html/rfc4492#section-5.5.1
+		z[0] = byte(extensionSupportedCurves >> 8)
+		z[1] = byte(extensionSupportedCurves)
+		l := 2 + 2*len(m.supportedCurves)
+		z[2] = byte(l >> 8)
+		z[3] = byte(l)
+		l -= 2
+		z[4] = byte(l >> 8)
+		z[5] = byte(l)
+		z = z[6:]
+		for _, curve := range m.supportedCurves {
+			z[0] = byte(curve >> 8)
+			z[1] = byte(curve)
+			z = z[2:]
+		}
+	}
+	if len(m.supportedPoints) > 0 {
+		// http://tools.ietf.org/html/rfc4492#section-5.5.2
+		z[0] = byte(extensionSupportedPoints >> 8)
+		z[1] = byte(extensionSupportedPoints)
+		l := 1 + len(m.supportedPoints)
+		z[2] = byte(l >> 8)
+		z[3] = byte(l)
+		l--
+		z[4] = byte(l)
+		z = z[5:]
+		for _, pointFormat := range m.supportedPoints {
+			z[0] = byte(pointFormat)
+			z = z[1:]
+		}
+	}
+	if m.ticketSupported {
+		// http://tools.ietf.org/html/rfc5077#section-3.2
+		z[0] = byte(extensionSessionTicket >> 8)
+		z[1] = byte(extensionSessionTicket)
+		l := len(m.sessionTicket)
+		z[2] = byte(l >> 8)
+		z[3] = byte(l)
+		z = z[4:]
+		copy(z, m.sessionTicket)
+		z = z[len(m.sessionTicket):]
+	}
+	if len(m.signatureAndHashes) > 0 {
+		// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+		z[0] = byte(extensionSignatureAlgorithms >> 8)
+		z[1] = byte(extensionSignatureAlgorithms)
+		l := 2 + 2*len(m.signatureAndHashes)
+		z[2] = byte(l >> 8)
+		z[3] = byte(l)
+		z = z[4:]
+
+		l -= 2
+		z[0] = byte(l >> 8)
+		z[1] = byte(l)
+		z = z[2:]
+		for _, sigAndHash := range m.signatureAndHashes {
+			z[0] = sigAndHash.hash
+			z[1] = sigAndHash.signature
+			z = z[2:]
+		}
+	}
+	if m.secureRenegotiation {
+		z[0] = byte(extensionRenegotiationInfo >> 8)
+		z[1] = byte(extensionRenegotiationInfo & 0xff)
+		z[2] = 0
+		z[3] = 1
+		z = z[5:]
+	}
+
+	m.raw = x
+
+	return x
+}
+
+func (m *clientHelloMsg) unmarshal(data []byte) bool {
+	if len(data) < 42 {
+		return false
+	}
+	m.raw = data
+	m.vers = uint16(data[4])<<8 | uint16(data[5])
+	m.random = data[6:38]
+	sessionIdLen := int(data[38])
+	if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
+		return false
+	}
+	m.sessionId = data[39 : 39+sessionIdLen]
+	data = data[39+sessionIdLen:]
+	if len(data) < 2 {
+		return false
+	}
+	// cipherSuiteLen is the number of bytes of cipher suite numbers. Since
+	// they are uint16s, the number must be even.
+	cipherSuiteLen := int(data[0])<<8 | int(data[1])
+	if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
+		return false
+	}
+	numCipherSuites := cipherSuiteLen / 2
+	m.cipherSuites = make([]uint16, numCipherSuites)
+	for i := 0; i < numCipherSuites; i++ {
+		m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
+		if m.cipherSuites[i] == scsvRenegotiation {
+			m.secureRenegotiation = true
+		}
+	}
+	data = data[2+cipherSuiteLen:]
+	if len(data) < 1 {
+		return false
+	}
+	compressionMethodsLen := int(data[0])
+	if len(data) < 1+compressionMethodsLen {
+		return false
+	}
+	m.compressionMethods = data[1 : 1+compressionMethodsLen]
+
+	data = data[1+compressionMethodsLen:]
+
+	m.nextProtoNeg = false
+	m.serverName = ""
+	m.ocspStapling = false
+	m.ticketSupported = false
+	m.sessionTicket = nil
+	m.signatureAndHashes = nil
+
+	if len(data) == 0 {
+		// ClientHello is optionally followed by extension data
+		return true
+	}
+	if len(data) < 2 {
+		return false
+	}
+
+	extensionsLength := int(data[0])<<8 | int(data[1])
+	data = data[2:]
+	if extensionsLength != len(data) {
+		return false
+	}
+
+	for len(data) != 0 {
+		if len(data) < 4 {
+			return false
+		}
+		extension := uint16(data[0])<<8 | uint16(data[1])
+		length := int(data[2])<<8 | int(data[3])
+		data = data[4:]
+		if len(data) < length {
+			return false
+		}
+
+		switch extension {
+		case extensionServerName:
+			if length < 2 {
+				return false
+			}
+			numNames := int(data[0])<<8 | int(data[1])
+			d := data[2:]
+			for i := 0; i < numNames; i++ {
+				if len(d) < 3 {
+					return false
+				}
+				nameType := d[0]
+				nameLen := int(d[1])<<8 | int(d[2])
+				d = d[3:]
+				if len(d) < nameLen {
+					return false
+				}
+				if nameType == 0 {
+					m.serverName = string(d[0:nameLen])
+					break
+				}
+				d = d[nameLen:]
+			}
+		case extensionNextProtoNeg:
+			if length > 0 {
+				return false
+			}
+			m.nextProtoNeg = true
+		case extensionStatusRequest:
+			m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
+		case extensionSupportedCurves:
+			// http://tools.ietf.org/html/rfc4492#section-5.5.1
+			if length < 2 {
+				return false
+			}
+			l := int(data[0])<<8 | int(data[1])
+			if l%2 == 1 || length != l+2 {
+				return false
+			}
+			numCurves := l / 2
+			m.supportedCurves = make([]CurveID, numCurves)
+			d := data[2:]
+			for i := 0; i < numCurves; i++ {
+				m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1])
+				d = d[2:]
+			}
+		case extensionSupportedPoints:
+			// http://tools.ietf.org/html/rfc4492#section-5.5.2
+			if length < 1 {
+				return false
+			}
+			l := int(data[0])
+			if length != l+1 {
+				return false
+			}
+			m.supportedPoints = make([]uint8, l)
+			copy(m.supportedPoints, data[1:])
+		case extensionSessionTicket:
+			// http://tools.ietf.org/html/rfc5077#section-3.2
+			m.ticketSupported = true
+			m.sessionTicket = data[:length]
+		case extensionSignatureAlgorithms:
+			// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+			if length < 2 || length&1 != 0 {
+				return false
+			}
+			l := int(data[0])<<8 | int(data[1])
+			if l != length-2 {
+				return false
+			}
+			n := l / 2
+			d := data[2:]
+			m.signatureAndHashes = make([]signatureAndHash, n)
+			for i := range m.signatureAndHashes {
+				m.signatureAndHashes[i].hash = d[0]
+				m.signatureAndHashes[i].signature = d[1]
+				d = d[2:]
+			}
+		case extensionRenegotiationInfo + 1:
+			if length != 1 || data[0] != 0 {
+				return false
+			}
+			m.secureRenegotiation = true
+		}
+		data = data[length:]
+	}
+
+	return true
+}
+
+type serverHelloMsg struct {
+	raw                 []byte
+	vers                uint16
+	random              []byte
+	sessionId           []byte
+	cipherSuite         uint16
+	compressionMethod   uint8
+	nextProtoNeg        bool
+	nextProtos          []string
+	ocspStapling        bool
+	ticketSupported     bool
+	secureRenegotiation bool
+}
+
+func (m *serverHelloMsg) equal(i interface{}) bool {
+	m1, ok := i.(*serverHelloMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		m.vers == m1.vers &&
+		bytes.Equal(m.random, m1.random) &&
+		bytes.Equal(m.sessionId, m1.sessionId) &&
+		m.cipherSuite == m1.cipherSuite &&
+		m.compressionMethod == m1.compressionMethod &&
+		m.nextProtoNeg == m1.nextProtoNeg &&
+		eqStrings(m.nextProtos, m1.nextProtos) &&
+		m.ocspStapling == m1.ocspStapling &&
+		m.ticketSupported == m1.ticketSupported &&
+		m.secureRenegotiation == m1.secureRenegotiation
+}
+
+func (m *serverHelloMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	length := 38 + len(m.sessionId)
+	numExtensions := 0
+	extensionsLength := 0
+
+	nextProtoLen := 0
+	if m.nextProtoNeg {
+		numExtensions++
+		for _, v := range m.nextProtos {
+			nextProtoLen += len(v)
+		}
+		nextProtoLen += len(m.nextProtos)
+		extensionsLength += nextProtoLen
+	}
+	if m.ocspStapling {
+		numExtensions++
+	}
+	if m.ticketSupported {
+		numExtensions++
+	}
+	if m.secureRenegotiation {
+		extensionsLength += 1
+		numExtensions++
+	}
+	if numExtensions > 0 {
+		extensionsLength += 4 * numExtensions
+		length += 2 + extensionsLength
+	}
+
+	x := make([]byte, 4+length)
+	x[0] = typeServerHello
+	x[1] = uint8(length >> 16)
+	x[2] = uint8(length >> 8)
+	x[3] = uint8(length)
+	x[4] = uint8(m.vers >> 8)
+	x[5] = uint8(m.vers)
+	copy(x[6:38], m.random)
+	x[38] = uint8(len(m.sessionId))
+	copy(x[39:39+len(m.sessionId)], m.sessionId)
+	z := x[39+len(m.sessionId):]
+	z[0] = uint8(m.cipherSuite >> 8)
+	z[1] = uint8(m.cipherSuite)
+	z[2] = uint8(m.compressionMethod)
+
+	z = z[3:]
+	if numExtensions > 0 {
+		z[0] = byte(extensionsLength >> 8)
+		z[1] = byte(extensionsLength)
+		z = z[2:]
+	}
+	if m.nextProtoNeg {
+		z[0] = byte(extensionNextProtoNeg >> 8)
+		z[1] = byte(extensionNextProtoNeg & 0xff)
+		z[2] = byte(nextProtoLen >> 8)
+		z[3] = byte(nextProtoLen)
+		z = z[4:]
+
+		for _, v := range m.nextProtos {
+			l := len(v)
+			if l > 255 {
+				l = 255
+			}
+			z[0] = byte(l)
+			copy(z[1:], []byte(v[0:l]))
+			z = z[1+l:]
+		}
+	}
+	if m.ocspStapling {
+		z[0] = byte(extensionStatusRequest >> 8)
+		z[1] = byte(extensionStatusRequest)
+		z = z[4:]
+	}
+	if m.ticketSupported {
+		z[0] = byte(extensionSessionTicket >> 8)
+		z[1] = byte(extensionSessionTicket)
+		z = z[4:]
+	}
+	if m.secureRenegotiation {
+		z[0] = byte(extensionRenegotiationInfo >> 8)
+		z[1] = byte(extensionRenegotiationInfo & 0xff)
+		z[2] = 0
+		z[3] = 1
+		z = z[5:]
+	}
+
+	m.raw = x
+
+	return x
+}
+
+func (m *serverHelloMsg) unmarshal(data []byte) bool {
+	if len(data) < 42 {
+		return false
+	}
+	m.raw = data
+	m.vers = uint16(data[4])<<8 | uint16(data[5])
+	m.random = data[6:38]
+	sessionIdLen := int(data[38])
+	if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
+		return false
+	}
+	m.sessionId = data[39 : 39+sessionIdLen]
+	data = data[39+sessionIdLen:]
+	if len(data) < 3 {
+		return false
+	}
+	m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
+	m.compressionMethod = data[2]
+	data = data[3:]
+
+	m.nextProtoNeg = false
+	m.nextProtos = nil
+	m.ocspStapling = false
+	m.ticketSupported = false
+
+	if len(data) == 0 {
+		// ServerHello is optionally followed by extension data
+		return true
+	}
+	if len(data) < 2 {
+		return false
+	}
+
+	extensionsLength := int(data[0])<<8 | int(data[1])
+	data = data[2:]
+	if len(data) != extensionsLength {
+		return false
+	}
+
+	for len(data) != 0 {
+		if len(data) < 4 {
+			return false
+		}
+		extension := uint16(data[0])<<8 | uint16(data[1])
+		length := int(data[2])<<8 | int(data[3])
+		data = data[4:]
+		if len(data) < length {
+			return false
+		}
+
+		switch extension {
+		case extensionNextProtoNeg:
+			m.nextProtoNeg = true
+			d := data[:length]
+			for len(d) > 0 {
+				l := int(d[0])
+				d = d[1:]
+				if l == 0 || l > len(d) {
+					return false
+				}
+				m.nextProtos = append(m.nextProtos, string(d[:l]))
+				d = d[l:]
+			}
+		case extensionStatusRequest:
+			if length > 0 {
+				return false
+			}
+			m.ocspStapling = true
+		case extensionSessionTicket:
+			if length > 0 {
+				return false
+			}
+			m.ticketSupported = true
+		case extensionRenegotiationInfo:
+			if length != 1 || data[0] != 0 {
+				return false
+			}
+			m.secureRenegotiation = true
+		}
+		data = data[length:]
+	}
+
+	return true
+}
+
+type certificateMsg struct {
+	raw          []byte
+	certificates [][]byte
+}
+
+func (m *certificateMsg) equal(i interface{}) bool {
+	m1, ok := i.(*certificateMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		eqByteSlices(m.certificates, m1.certificates)
+}
+
+func (m *certificateMsg) marshal() (x []byte) {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	var i int
+	for _, slice := range m.certificates {
+		i += len(slice)
+	}
+
+	length := 3 + 3*len(m.certificates) + i
+	x = make([]byte, 4+length)
+	x[0] = typeCertificate
+	x[1] = uint8(length >> 16)
+	x[2] = uint8(length >> 8)
+	x[3] = uint8(length)
+
+	certificateOctets := length - 3
+	x[4] = uint8(certificateOctets >> 16)
+	x[5] = uint8(certificateOctets >> 8)
+	x[6] = uint8(certificateOctets)
+
+	y := x[7:]
+	for _, slice := range m.certificates {
+		y[0] = uint8(len(slice) >> 16)
+		y[1] = uint8(len(slice) >> 8)
+		y[2] = uint8(len(slice))
+		copy(y[3:], slice)
+		y = y[3+len(slice):]
+	}
+
+	m.raw = x
+	return
+}
+
+func (m *certificateMsg) unmarshal(data []byte) bool {
+	if len(data) < 7 {
+		return false
+	}
+
+	m.raw = data
+	certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6])
+	if uint32(len(data)) != certsLen+7 {
+		return false
+	}
+
+	numCerts := 0
+	d := data[7:]
+	for certsLen > 0 {
+		if len(d) < 4 {
+			return false
+		}
+		certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
+		if uint32(len(d)) < 3+certLen {
+			return false
+		}
+		d = d[3+certLen:]
+		certsLen -= 3 + certLen
+		numCerts++
+	}
+
+	m.certificates = make([][]byte, numCerts)
+	d = data[7:]
+	for i := 0; i < numCerts; i++ {
+		certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
+		m.certificates[i] = d[3 : 3+certLen]
+		d = d[3+certLen:]
+	}
+
+	return true
+}
+
+type serverKeyExchangeMsg struct {
+	raw []byte
+	key []byte
+}
+
+func (m *serverKeyExchangeMsg) equal(i interface{}) bool {
+	m1, ok := i.(*serverKeyExchangeMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.key, m1.key)
+}
+
+func (m *serverKeyExchangeMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+	length := len(m.key)
+	x := make([]byte, length+4)
+	x[0] = typeServerKeyExchange
+	x[1] = uint8(length >> 16)
+	x[2] = uint8(length >> 8)
+	x[3] = uint8(length)
+	copy(x[4:], m.key)
+
+	m.raw = x
+	return x
+}
+
+func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
+	m.raw = data
+	if len(data) < 4 {
+		return false
+	}
+	m.key = data[4:]
+	return true
+}
+
+type certificateStatusMsg struct {
+	raw        []byte
+	statusType uint8
+	response   []byte
+}
+
+func (m *certificateStatusMsg) equal(i interface{}) bool {
+	m1, ok := i.(*certificateStatusMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		m.statusType == m1.statusType &&
+		bytes.Equal(m.response, m1.response)
+}
+
+func (m *certificateStatusMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	var x []byte
+	if m.statusType == statusTypeOCSP {
+		x = make([]byte, 4+4+len(m.response))
+		x[0] = typeCertificateStatus
+		l := len(m.response) + 4
+		x[1] = byte(l >> 16)
+		x[2] = byte(l >> 8)
+		x[3] = byte(l)
+		x[4] = statusTypeOCSP
+
+		l -= 4
+		x[5] = byte(l >> 16)
+		x[6] = byte(l >> 8)
+		x[7] = byte(l)
+		copy(x[8:], m.response)
+	} else {
+		x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
+	}
+
+	m.raw = x
+	return x
+}
+
+func (m *certificateStatusMsg) unmarshal(data []byte) bool {
+	m.raw = data
+	if len(data) < 5 {
+		return false
+	}
+	m.statusType = data[4]
+
+	m.response = nil
+	if m.statusType == statusTypeOCSP {
+		if len(data) < 8 {
+			return false
+		}
+		respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
+		if uint32(len(data)) != 4+4+respLen {
+			return false
+		}
+		m.response = data[8:]
+	}
+	return true
+}
+
+type serverHelloDoneMsg struct{}
+
+func (m *serverHelloDoneMsg) equal(i interface{}) bool {
+	_, ok := i.(*serverHelloDoneMsg)
+	return ok
+}
+
+func (m *serverHelloDoneMsg) marshal() []byte {
+	x := make([]byte, 4)
+	x[0] = typeServerHelloDone
+	return x
+}
+
+func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
+	return len(data) == 4
+}
+
+type clientKeyExchangeMsg struct {
+	raw        []byte
+	ciphertext []byte
+}
+
+func (m *clientKeyExchangeMsg) equal(i interface{}) bool {
+	m1, ok := i.(*clientKeyExchangeMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.ciphertext, m1.ciphertext)
+}
+
+func (m *clientKeyExchangeMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+	length := len(m.ciphertext)
+	x := make([]byte, length+4)
+	x[0] = typeClientKeyExchange
+	x[1] = uint8(length >> 16)
+	x[2] = uint8(length >> 8)
+	x[3] = uint8(length)
+	copy(x[4:], m.ciphertext)
+
+	m.raw = x
+	return x
+}
+
+func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
+	m.raw = data
+	if len(data) < 4 {
+		return false
+	}
+	l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+	if l != len(data)-4 {
+		return false
+	}
+	m.ciphertext = data[4:]
+	return true
+}
+
+type finishedMsg struct {
+	raw        []byte
+	verifyData []byte
+}
+
+func (m *finishedMsg) equal(i interface{}) bool {
+	m1, ok := i.(*finishedMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.verifyData, m1.verifyData)
+}
+
+func (m *finishedMsg) marshal() (x []byte) {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	x = make([]byte, 4+len(m.verifyData))
+	x[0] = typeFinished
+	x[3] = byte(len(m.verifyData))
+	copy(x[4:], m.verifyData)
+	m.raw = x
+	return
+}
+
+func (m *finishedMsg) unmarshal(data []byte) bool {
+	m.raw = data
+	if len(data) < 4 {
+		return false
+	}
+	m.verifyData = data[4:]
+	return true
+}
+
+type nextProtoMsg struct {
+	raw   []byte
+	proto string
+}
+
+func (m *nextProtoMsg) equal(i interface{}) bool {
+	m1, ok := i.(*nextProtoMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		m.proto == m1.proto
+}
+
+func (m *nextProtoMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+	l := len(m.proto)
+	if l > 255 {
+		l = 255
+	}
+
+	padding := 32 - (l+2)%32
+	length := l + padding + 2
+	x := make([]byte, length+4)
+	x[0] = typeNextProtocol
+	x[1] = uint8(length >> 16)
+	x[2] = uint8(length >> 8)
+	x[3] = uint8(length)
+
+	y := x[4:]
+	y[0] = byte(l)
+	copy(y[1:], []byte(m.proto[0:l]))
+	y = y[1+l:]
+	y[0] = byte(padding)
+
+	m.raw = x
+
+	return x
+}
+
+func (m *nextProtoMsg) unmarshal(data []byte) bool {
+	m.raw = data
+
+	if len(data) < 5 {
+		return false
+	}
+	data = data[4:]
+	protoLen := int(data[0])
+	data = data[1:]
+	if len(data) < protoLen {
+		return false
+	}
+	m.proto = string(data[0:protoLen])
+	data = data[protoLen:]
+
+	if len(data) < 1 {
+		return false
+	}
+	paddingLen := int(data[0])
+	data = data[1:]
+	if len(data) != paddingLen {
+		return false
+	}
+
+	return true
+}
+
+type certificateRequestMsg struct {
+	raw []byte
+	// hasSignatureAndHash indicates whether this message includes a list
+	// of signature and hash functions. This change was introduced with TLS
+	// 1.2.
+	hasSignatureAndHash bool
+
+	certificateTypes       []byte
+	signatureAndHashes     []signatureAndHash
+	certificateAuthorities [][]byte
+}
+
+func (m *certificateRequestMsg) equal(i interface{}) bool {
+	m1, ok := i.(*certificateRequestMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.certificateTypes, m1.certificateTypes) &&
+		eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities) &&
+		eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes)
+}
+
+func (m *certificateRequestMsg) marshal() (x []byte) {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	// See http://tools.ietf.org/html/rfc4346#section-7.4.4
+	length := 1 + len(m.certificateTypes) + 2
+	casLength := 0
+	for _, ca := range m.certificateAuthorities {
+		casLength += 2 + len(ca)
+	}
+	length += casLength
+
+	if m.hasSignatureAndHash {
+		length += 2 + 2*len(m.signatureAndHashes)
+	}
+
+	x = make([]byte, 4+length)
+	x[0] = typeCertificateRequest
+	x[1] = uint8(length >> 16)
+	x[2] = uint8(length >> 8)
+	x[3] = uint8(length)
+
+	x[4] = uint8(len(m.certificateTypes))
+
+	copy(x[5:], m.certificateTypes)
+	y := x[5+len(m.certificateTypes):]
+
+	if m.hasSignatureAndHash {
+		n := len(m.signatureAndHashes) * 2
+		y[0] = uint8(n >> 8)
+		y[1] = uint8(n)
+		y = y[2:]
+		for _, sigAndHash := range m.signatureAndHashes {
+			y[0] = sigAndHash.hash
+			y[1] = sigAndHash.signature
+			y = y[2:]
+		}
+	}
+
+	y[0] = uint8(casLength >> 8)
+	y[1] = uint8(casLength)
+	y = y[2:]
+	for _, ca := range m.certificateAuthorities {
+		y[0] = uint8(len(ca) >> 8)
+		y[1] = uint8(len(ca))
+		y = y[2:]
+		copy(y, ca)
+		y = y[len(ca):]
+	}
+
+	m.raw = x
+	return
+}
+
+func (m *certificateRequestMsg) unmarshal(data []byte) bool {
+	m.raw = data
+
+	if len(data) < 5 {
+		return false
+	}
+
+	length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+	if uint32(len(data))-4 != length {
+		return false
+	}
+
+	numCertTypes := int(data[4])
+	data = data[5:]
+	if numCertTypes == 0 || len(data) <= numCertTypes {
+		return false
+	}
+
+	m.certificateTypes = make([]byte, numCertTypes)
+	if copy(m.certificateTypes, data) != numCertTypes {
+		return false
+	}
+
+	data = data[numCertTypes:]
+
+	if m.hasSignatureAndHash {
+		if len(data) < 2 {
+			return false
+		}
+		sigAndHashLen := uint16(data[0])<<8 | uint16(data[1])
+		data = data[2:]
+		if sigAndHashLen&1 != 0 {
+			return false
+		}
+		if len(data) < int(sigAndHashLen) {
+			return false
+		}
+		numSigAndHash := sigAndHashLen / 2
+		m.signatureAndHashes = make([]signatureAndHash, numSigAndHash)
+		for i := range m.signatureAndHashes {
+			m.signatureAndHashes[i].hash = data[0]
+			m.signatureAndHashes[i].signature = data[1]
+			data = data[2:]
+		}
+	}
+
+	if len(data) < 2 {
+		return false
+	}
+	casLength := uint16(data[0])<<8 | uint16(data[1])
+	data = data[2:]
+	if len(data) < int(casLength) {
+		return false
+	}
+	cas := make([]byte, casLength)
+	copy(cas, data)
+	data = data[casLength:]
+
+	m.certificateAuthorities = nil
+	for len(cas) > 0 {
+		if len(cas) < 2 {
+			return false
+		}
+		caLen := uint16(cas[0])<<8 | uint16(cas[1])
+		cas = cas[2:]
+
+		if len(cas) < int(caLen) {
+			return false
+		}
+
+		m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
+		cas = cas[caLen:]
+	}
+	if len(data) > 0 {
+		return false
+	}
+
+	return true
+}
+
+type certificateVerifyMsg struct {
+	raw                 []byte
+	hasSignatureAndHash bool
+	signatureAndHash    signatureAndHash
+	signature           []byte
+}
+
+func (m *certificateVerifyMsg) equal(i interface{}) bool {
+	m1, ok := i.(*certificateVerifyMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		m.hasSignatureAndHash == m1.hasSignatureAndHash &&
+		m.signatureAndHash.hash == m1.signatureAndHash.hash &&
+		m.signatureAndHash.signature == m1.signatureAndHash.signature &&
+		bytes.Equal(m.signature, m1.signature)
+}
+
+func (m *certificateVerifyMsg) marshal() (x []byte) {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	// See http://tools.ietf.org/html/rfc4346#section-7.4.8
+	siglength := len(m.signature)
+	length := 2 + siglength
+	if m.hasSignatureAndHash {
+		length += 2
+	}
+	x = make([]byte, 4+length)
+	x[0] = typeCertificateVerify
+	x[1] = uint8(length >> 16)
+	x[2] = uint8(length >> 8)
+	x[3] = uint8(length)
+	y := x[4:]
+	if m.hasSignatureAndHash {
+		y[0] = m.signatureAndHash.hash
+		y[1] = m.signatureAndHash.signature
+		y = y[2:]
+	}
+	y[0] = uint8(siglength >> 8)
+	y[1] = uint8(siglength)
+	copy(y[2:], m.signature)
+
+	m.raw = x
+
+	return
+}
+
+func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
+	m.raw = data
+
+	if len(data) < 6 {
+		return false
+	}
+
+	length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+	if uint32(len(data))-4 != length {
+		return false
+	}
+
+	data = data[4:]
+	if m.hasSignatureAndHash {
+		m.signatureAndHash.hash = data[0]
+		m.signatureAndHash.signature = data[1]
+		data = data[2:]
+	}
+
+	if len(data) < 2 {
+		return false
+	}
+	siglength := int(data[0])<<8 + int(data[1])
+	data = data[2:]
+	if len(data) != siglength {
+		return false
+	}
+
+	m.signature = data
+
+	return true
+}
+
+type newSessionTicketMsg struct {
+	raw    []byte
+	ticket []byte
+}
+
+func (m *newSessionTicketMsg) equal(i interface{}) bool {
+	m1, ok := i.(*newSessionTicketMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.ticket, m1.ticket)
+}
+
+func (m *newSessionTicketMsg) marshal() (x []byte) {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	// See http://tools.ietf.org/html/rfc5077#section-3.3
+	ticketLen := len(m.ticket)
+	length := 2 + 4 + ticketLen
+	x = make([]byte, 4+length)
+	x[0] = typeNewSessionTicket
+	x[1] = uint8(length >> 16)
+	x[2] = uint8(length >> 8)
+	x[3] = uint8(length)
+	x[8] = uint8(ticketLen >> 8)
+	x[9] = uint8(ticketLen)
+	copy(x[10:], m.ticket)
+
+	m.raw = x
+
+	return
+}
+
+func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
+	m.raw = data
+
+	if len(data) < 10 {
+		return false
+	}
+
+	length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+	if uint32(len(data))-4 != length {
+		return false
+	}
+
+	ticketLen := int(data[8])<<8 + int(data[9])
+	if len(data)-10 != ticketLen {
+		return false
+	}
+
+	m.ticket = data[10:]
+
+	return true
+}
+
+func eqUint16s(x, y []uint16) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, v := range x {
+		if y[i] != v {
+			return false
+		}
+	}
+	return true
+}
+
+func eqCurveIDs(x, y []CurveID) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, v := range x {
+		if y[i] != v {
+			return false
+		}
+	}
+	return true
+}
+
+func eqStrings(x, y []string) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, v := range x {
+		if y[i] != v {
+			return false
+		}
+	}
+	return true
+}
+
+func eqByteSlices(x, y [][]byte) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, v := range x {
+		if !bytes.Equal(v, y[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+func eqSignatureAndHashes(x, y []signatureAndHash) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, v := range x {
+		v2 := y[i]
+		if v.hash != v2.hash || v.signature != v2.signature {
+			return false
+		}
+	}
+	return true
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/handshake_messages_test.go b/third_party/gofrontend/libgo/go/crypto/tls/handshake_messages_test.go
new file mode 100644
index 0000000..f46aabd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/handshake_messages_test.go
@@ -0,0 +1,246 @@
+// 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 tls
+
+import (
+	"math/rand"
+	"reflect"
+	"testing"
+	"testing/quick"
+)
+
+var tests = []interface{}{
+	&clientHelloMsg{},
+	&serverHelloMsg{},
+	&finishedMsg{},
+
+	&certificateMsg{},
+	&certificateRequestMsg{},
+	&certificateVerifyMsg{},
+	&certificateStatusMsg{},
+	&clientKeyExchangeMsg{},
+	&nextProtoMsg{},
+	&newSessionTicketMsg{},
+	&sessionState{},
+}
+
+type testMessage interface {
+	marshal() []byte
+	unmarshal([]byte) bool
+	equal(interface{}) bool
+}
+
+func TestMarshalUnmarshal(t *testing.T) {
+	rand := rand.New(rand.NewSource(0))
+
+	for i, iface := range tests {
+		ty := reflect.ValueOf(iface).Type()
+
+		n := 100
+		if testing.Short() {
+			n = 5
+		}
+		for j := 0; j < n; j++ {
+			v, ok := quick.Value(ty, rand)
+			if !ok {
+				t.Errorf("#%d: failed to create value", i)
+				break
+			}
+
+			m1 := v.Interface().(testMessage)
+			marshaled := m1.marshal()
+			m2 := iface.(testMessage)
+			if !m2.unmarshal(marshaled) {
+				t.Errorf("#%d failed to unmarshal %#v %x", i, m1, marshaled)
+				break
+			}
+			m2.marshal() // to fill any marshal cache in the message
+
+			if !m1.equal(m2) {
+				t.Errorf("#%d got:%#v want:%#v %x", i, m2, m1, marshaled)
+				break
+			}
+
+			if i >= 3 {
+				// The first three message types (ClientHello,
+				// ServerHello and Finished) are allowed to
+				// have parsable prefixes because the extension
+				// data is optional and the length of the
+				// Finished varies across versions.
+				for j := 0; j < len(marshaled); j++ {
+					if m2.unmarshal(marshaled[0:j]) {
+						t.Errorf("#%d unmarshaled a prefix of length %d of %#v", i, j, m1)
+						break
+					}
+				}
+			}
+		}
+	}
+}
+
+func TestFuzz(t *testing.T) {
+	rand := rand.New(rand.NewSource(0))
+	for _, iface := range tests {
+		m := iface.(testMessage)
+
+		for j := 0; j < 1000; j++ {
+			len := rand.Intn(100)
+			bytes := randomBytes(len, rand)
+			// This just looks for crashes due to bounds errors etc.
+			m.unmarshal(bytes)
+		}
+	}
+}
+
+func randomBytes(n int, rand *rand.Rand) []byte {
+	r := make([]byte, n)
+	for i := 0; i < n; i++ {
+		r[i] = byte(rand.Int31())
+	}
+	return r
+}
+
+func randomString(n int, rand *rand.Rand) string {
+	b := randomBytes(n, rand)
+	return string(b)
+}
+
+func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &clientHelloMsg{}
+	m.vers = uint16(rand.Intn(65536))
+	m.random = randomBytes(32, rand)
+	m.sessionId = randomBytes(rand.Intn(32), rand)
+	m.cipherSuites = make([]uint16, rand.Intn(63)+1)
+	for i := 0; i < len(m.cipherSuites); i++ {
+		m.cipherSuites[i] = uint16(rand.Int31())
+	}
+	m.compressionMethods = randomBytes(rand.Intn(63)+1, rand)
+	if rand.Intn(10) > 5 {
+		m.nextProtoNeg = true
+	}
+	if rand.Intn(10) > 5 {
+		m.serverName = randomString(rand.Intn(255), rand)
+	}
+	m.ocspStapling = rand.Intn(10) > 5
+	m.supportedPoints = randomBytes(rand.Intn(5)+1, rand)
+	m.supportedCurves = make([]CurveID, rand.Intn(5)+1)
+	for i := range m.supportedCurves {
+		m.supportedCurves[i] = CurveID(rand.Intn(30000))
+	}
+	if rand.Intn(10) > 5 {
+		m.ticketSupported = true
+		if rand.Intn(10) > 5 {
+			m.sessionTicket = randomBytes(rand.Intn(300), rand)
+		}
+	}
+	if rand.Intn(10) > 5 {
+		m.signatureAndHashes = supportedSKXSignatureAlgorithms
+	}
+
+	return reflect.ValueOf(m)
+}
+
+func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &serverHelloMsg{}
+	m.vers = uint16(rand.Intn(65536))
+	m.random = randomBytes(32, rand)
+	m.sessionId = randomBytes(rand.Intn(32), rand)
+	m.cipherSuite = uint16(rand.Int31())
+	m.compressionMethod = uint8(rand.Intn(256))
+
+	if rand.Intn(10) > 5 {
+		m.nextProtoNeg = true
+
+		n := rand.Intn(10)
+		m.nextProtos = make([]string, n)
+		for i := 0; i < n; i++ {
+			m.nextProtos[i] = randomString(20, rand)
+		}
+	}
+
+	if rand.Intn(10) > 5 {
+		m.ocspStapling = true
+	}
+	if rand.Intn(10) > 5 {
+		m.ticketSupported = true
+	}
+
+	return reflect.ValueOf(m)
+}
+
+func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &certificateMsg{}
+	numCerts := rand.Intn(20)
+	m.certificates = make([][]byte, numCerts)
+	for i := 0; i < numCerts; i++ {
+		m.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
+	}
+	return reflect.ValueOf(m)
+}
+
+func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &certificateRequestMsg{}
+	m.certificateTypes = randomBytes(rand.Intn(5)+1, rand)
+	numCAs := rand.Intn(100)
+	m.certificateAuthorities = make([][]byte, numCAs)
+	for i := 0; i < numCAs; i++ {
+		m.certificateAuthorities[i] = randomBytes(rand.Intn(15)+1, rand)
+	}
+	return reflect.ValueOf(m)
+}
+
+func (*certificateVerifyMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &certificateVerifyMsg{}
+	m.signature = randomBytes(rand.Intn(15)+1, rand)
+	return reflect.ValueOf(m)
+}
+
+func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &certificateStatusMsg{}
+	if rand.Intn(10) > 5 {
+		m.statusType = statusTypeOCSP
+		m.response = randomBytes(rand.Intn(10)+1, rand)
+	} else {
+		m.statusType = 42
+	}
+	return reflect.ValueOf(m)
+}
+
+func (*clientKeyExchangeMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &clientKeyExchangeMsg{}
+	m.ciphertext = randomBytes(rand.Intn(1000)+1, rand)
+	return reflect.ValueOf(m)
+}
+
+func (*finishedMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &finishedMsg{}
+	m.verifyData = randomBytes(12, rand)
+	return reflect.ValueOf(m)
+}
+
+func (*nextProtoMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &nextProtoMsg{}
+	m.proto = randomString(rand.Intn(255), rand)
+	return reflect.ValueOf(m)
+}
+
+func (*newSessionTicketMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &newSessionTicketMsg{}
+	m.ticket = randomBytes(rand.Intn(4), rand)
+	return reflect.ValueOf(m)
+}
+
+func (*sessionState) Generate(rand *rand.Rand, size int) reflect.Value {
+	s := &sessionState{}
+	s.vers = uint16(rand.Intn(10000))
+	s.cipherSuite = uint16(rand.Intn(10000))
+	s.masterSecret = randomBytes(rand.Intn(100), rand)
+	numCerts := rand.Intn(20)
+	s.certificates = make([][]byte, numCerts)
+	for i := 0; i < numCerts; i++ {
+		s.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
+	}
+	return reflect.ValueOf(s)
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/handshake_server.go b/third_party/gofrontend/libgo/go/crypto/tls/handshake_server.go
new file mode 100644
index 0000000..dff6fd9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/handshake_server.go
@@ -0,0 +1,654 @@
+// 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 tls
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"crypto/subtle"
+	"crypto/x509"
+	"encoding/asn1"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// serverHandshakeState contains details of a server handshake in progress.
+// It's discarded once the handshake has completed.
+type serverHandshakeState struct {
+	c               *Conn
+	clientHello     *clientHelloMsg
+	hello           *serverHelloMsg
+	suite           *cipherSuite
+	ellipticOk      bool
+	ecdsaOk         bool
+	sessionState    *sessionState
+	finishedHash    finishedHash
+	masterSecret    []byte
+	certsFromClient [][]byte
+	cert            *Certificate
+}
+
+// serverHandshake performs a TLS handshake as a server.
+func (c *Conn) serverHandshake() error {
+	config := c.config
+
+	// If this is the first server handshake, we generate a random key to
+	// encrypt the tickets with.
+	config.serverInitOnce.Do(config.serverInit)
+
+	hs := serverHandshakeState{
+		c: c,
+	}
+	isResume, err := hs.readClientHello()
+	if err != nil {
+		return err
+	}
+
+	// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
+	if isResume {
+		// The client has included a session ticket and so we do an abbreviated handshake.
+		if err := hs.doResumeHandshake(); err != nil {
+			return err
+		}
+		if err := hs.establishKeys(); err != nil {
+			return err
+		}
+		if err := hs.sendFinished(); err != nil {
+			return err
+		}
+		if err := hs.readFinished(); err != nil {
+			return err
+		}
+		c.didResume = true
+	} else {
+		// The client didn't include a session ticket, or it wasn't
+		// valid so we do a full handshake.
+		if err := hs.doFullHandshake(); err != nil {
+			return err
+		}
+		if err := hs.establishKeys(); err != nil {
+			return err
+		}
+		if err := hs.readFinished(); err != nil {
+			return err
+		}
+		if err := hs.sendSessionTicket(); err != nil {
+			return err
+		}
+		if err := hs.sendFinished(); err != nil {
+			return err
+		}
+	}
+	c.handshakeComplete = true
+
+	return nil
+}
+
+// readClientHello reads a ClientHello message from the client and decides
+// whether we will perform session resumption.
+func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
+	config := hs.c.config
+	c := hs.c
+
+	msg, err := c.readHandshake()
+	if err != nil {
+		return false, err
+	}
+	var ok bool
+	hs.clientHello, ok = msg.(*clientHelloMsg)
+	if !ok {
+		c.sendAlert(alertUnexpectedMessage)
+		return false, unexpectedMessageError(hs.clientHello, msg)
+	}
+	c.vers, ok = config.mutualVersion(hs.clientHello.vers)
+	if !ok {
+		c.sendAlert(alertProtocolVersion)
+		return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers)
+	}
+	c.haveVers = true
+
+	hs.finishedHash = newFinishedHash(c.vers)
+	hs.finishedHash.Write(hs.clientHello.marshal())
+
+	hs.hello = new(serverHelloMsg)
+
+	supportedCurve := false
+	preferredCurves := config.curvePreferences()
+Curves:
+	for _, curve := range hs.clientHello.supportedCurves {
+		for _, supported := range preferredCurves {
+			if supported == curve {
+				supportedCurve = true
+				break Curves
+			}
+		}
+	}
+
+	supportedPointFormat := false
+	for _, pointFormat := range hs.clientHello.supportedPoints {
+		if pointFormat == pointFormatUncompressed {
+			supportedPointFormat = true
+			break
+		}
+	}
+	hs.ellipticOk = supportedCurve && supportedPointFormat
+
+	foundCompression := false
+	// We only support null compression, so check that the client offered it.
+	for _, compression := range hs.clientHello.compressionMethods {
+		if compression == compressionNone {
+			foundCompression = true
+			break
+		}
+	}
+
+	if !foundCompression {
+		c.sendAlert(alertHandshakeFailure)
+		return false, errors.New("tls: client does not support uncompressed connections")
+	}
+
+	hs.hello.vers = c.vers
+	hs.hello.random = make([]byte, 32)
+	_, err = io.ReadFull(config.rand(), hs.hello.random)
+	if err != nil {
+		c.sendAlert(alertInternalError)
+		return false, err
+	}
+	hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation
+	hs.hello.compressionMethod = compressionNone
+	if len(hs.clientHello.serverName) > 0 {
+		c.serverName = hs.clientHello.serverName
+	}
+	// Although sending an empty NPN extension is reasonable, Firefox has
+	// had a bug around this. Best to send nothing at all if
+	// config.NextProtos is empty. See
+	// https://code.google.com/p/go/issues/detail?id=5445.
+	if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
+		hs.hello.nextProtoNeg = true
+		hs.hello.nextProtos = config.NextProtos
+	}
+
+	if len(config.Certificates) == 0 {
+		c.sendAlert(alertInternalError)
+		return false, errors.New("tls: no certificates configured")
+	}
+	hs.cert = &config.Certificates[0]
+	if len(hs.clientHello.serverName) > 0 {
+		hs.cert = config.getCertificateForName(hs.clientHello.serverName)
+	}
+
+	_, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
+
+	if hs.checkForResumption() {
+		return true, nil
+	}
+
+	var preferenceList, supportedList []uint16
+	if c.config.PreferServerCipherSuites {
+		preferenceList = c.config.cipherSuites()
+		supportedList = hs.clientHello.cipherSuites
+	} else {
+		preferenceList = hs.clientHello.cipherSuites
+		supportedList = c.config.cipherSuites()
+	}
+
+	for _, id := range preferenceList {
+		if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, hs.ellipticOk, hs.ecdsaOk); hs.suite != nil {
+			break
+		}
+	}
+
+	if hs.suite == nil {
+		c.sendAlert(alertHandshakeFailure)
+		return false, errors.New("tls: no cipher suite supported by both client and server")
+	}
+
+	return false, nil
+}
+
+// checkForResumption returns true if we should perform resumption on this connection.
+func (hs *serverHandshakeState) checkForResumption() bool {
+	c := hs.c
+
+	if c.config.SessionTicketsDisabled {
+		return false
+	}
+
+	var ok bool
+	if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
+		return false
+	}
+
+	if hs.sessionState.vers > hs.clientHello.vers {
+		return false
+	}
+	if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
+		return false
+	}
+
+	cipherSuiteOk := false
+	// Check that the client is still offering the ciphersuite in the session.
+	for _, id := range hs.clientHello.cipherSuites {
+		if id == hs.sessionState.cipherSuite {
+			cipherSuiteOk = true
+			break
+		}
+	}
+	if !cipherSuiteOk {
+		return false
+	}
+
+	// Check that we also support the ciphersuite from the session.
+	hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers, hs.ellipticOk, hs.ecdsaOk)
+	if hs.suite == nil {
+		return false
+	}
+
+	sessionHasClientCerts := len(hs.sessionState.certificates) != 0
+	needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
+	if needClientCerts && !sessionHasClientCerts {
+		return false
+	}
+	if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
+		return false
+	}
+
+	return true
+}
+
+func (hs *serverHandshakeState) doResumeHandshake() error {
+	c := hs.c
+
+	hs.hello.cipherSuite = hs.suite.id
+	// We echo the client's session ID in the ServerHello to let it know
+	// that we're doing a resumption.
+	hs.hello.sessionId = hs.clientHello.sessionId
+	hs.finishedHash.Write(hs.hello.marshal())
+	c.writeRecord(recordTypeHandshake, hs.hello.marshal())
+
+	if len(hs.sessionState.certificates) > 0 {
+		if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
+			return err
+		}
+	}
+
+	hs.masterSecret = hs.sessionState.masterSecret
+
+	return nil
+}
+
+func (hs *serverHandshakeState) doFullHandshake() error {
+	config := hs.c.config
+	c := hs.c
+
+	if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
+		hs.hello.ocspStapling = true
+	}
+
+	hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled
+	hs.hello.cipherSuite = hs.suite.id
+	hs.finishedHash.Write(hs.hello.marshal())
+	c.writeRecord(recordTypeHandshake, hs.hello.marshal())
+
+	certMsg := new(certificateMsg)
+	certMsg.certificates = hs.cert.Certificate
+	hs.finishedHash.Write(certMsg.marshal())
+	c.writeRecord(recordTypeHandshake, certMsg.marshal())
+
+	if hs.hello.ocspStapling {
+		certStatus := new(certificateStatusMsg)
+		certStatus.statusType = statusTypeOCSP
+		certStatus.response = hs.cert.OCSPStaple
+		hs.finishedHash.Write(certStatus.marshal())
+		c.writeRecord(recordTypeHandshake, certStatus.marshal())
+	}
+
+	keyAgreement := hs.suite.ka(c.vers)
+	skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello)
+	if err != nil {
+		c.sendAlert(alertHandshakeFailure)
+		return err
+	}
+	if skx != nil {
+		hs.finishedHash.Write(skx.marshal())
+		c.writeRecord(recordTypeHandshake, skx.marshal())
+	}
+
+	if config.ClientAuth >= RequestClientCert {
+		// Request a client certificate
+		certReq := new(certificateRequestMsg)
+		certReq.certificateTypes = []byte{
+			byte(certTypeRSASign),
+			byte(certTypeECDSASign),
+		}
+		if c.vers >= VersionTLS12 {
+			certReq.hasSignatureAndHash = true
+			certReq.signatureAndHashes = supportedClientCertSignatureAlgorithms
+		}
+
+		// An empty list of certificateAuthorities signals to
+		// the client that it may send any certificate in response
+		// to our request. When we know the CAs we trust, then
+		// we can send them down, so that the client can choose
+		// an appropriate certificate to give to us.
+		if config.ClientCAs != nil {
+			certReq.certificateAuthorities = config.ClientCAs.Subjects()
+		}
+		hs.finishedHash.Write(certReq.marshal())
+		c.writeRecord(recordTypeHandshake, certReq.marshal())
+	}
+
+	helloDone := new(serverHelloDoneMsg)
+	hs.finishedHash.Write(helloDone.marshal())
+	c.writeRecord(recordTypeHandshake, helloDone.marshal())
+
+	var pub crypto.PublicKey // public key for client auth, if any
+
+	msg, err := c.readHandshake()
+	if err != nil {
+		return err
+	}
+
+	var ok bool
+	// If we requested a client certificate, then the client must send a
+	// certificate message, even if it's empty.
+	if config.ClientAuth >= RequestClientCert {
+		if certMsg, ok = msg.(*certificateMsg); !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(certMsg, msg)
+		}
+		hs.finishedHash.Write(certMsg.marshal())
+
+		if len(certMsg.certificates) == 0 {
+			// The client didn't actually send a certificate
+			switch config.ClientAuth {
+			case RequireAnyClientCert, RequireAndVerifyClientCert:
+				c.sendAlert(alertBadCertificate)
+				return errors.New("tls: client didn't provide a certificate")
+			}
+		}
+
+		pub, err = hs.processCertsFromClient(certMsg.certificates)
+		if err != nil {
+			return err
+		}
+
+		msg, err = c.readHandshake()
+		if err != nil {
+			return err
+		}
+	}
+
+	// Get client key exchange
+	ckx, ok := msg.(*clientKeyExchangeMsg)
+	if !ok {
+		c.sendAlert(alertUnexpectedMessage)
+		return unexpectedMessageError(ckx, msg)
+	}
+	hs.finishedHash.Write(ckx.marshal())
+
+	// If we received a client cert in response to our certificate request message,
+	// the client will send us a certificateVerifyMsg immediately after the
+	// clientKeyExchangeMsg.  This message is a digest of all preceding
+	// handshake-layer messages that is signed using the private key corresponding
+	// to the client's certificate. This allows us to verify that the client is in
+	// possession of the private key of the certificate.
+	if len(c.peerCertificates) > 0 {
+		msg, err = c.readHandshake()
+		if err != nil {
+			return err
+		}
+		certVerify, ok := msg.(*certificateVerifyMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(certVerify, msg)
+		}
+
+		switch key := pub.(type) {
+		case *ecdsa.PublicKey:
+			ecdsaSig := new(ecdsaSignature)
+			if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
+				break
+			}
+			if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+				err = errors.New("ECDSA signature contained zero or negative values")
+				break
+			}
+			digest, _, _ := hs.finishedHash.hashForClientCertificate(signatureECDSA)
+			if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
+				err = errors.New("ECDSA verification failure")
+				break
+			}
+		case *rsa.PublicKey:
+			digest, hashFunc, _ := hs.finishedHash.hashForClientCertificate(signatureRSA)
+			err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
+		}
+		if err != nil {
+			c.sendAlert(alertBadCertificate)
+			return errors.New("could not validate signature of connection nonces: " + err.Error())
+		}
+
+		hs.finishedHash.Write(certVerify.marshal())
+	}
+
+	preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
+	if err != nil {
+		c.sendAlert(alertHandshakeFailure)
+		return err
+	}
+	hs.masterSecret = masterFromPreMasterSecret(c.vers, preMasterSecret, hs.clientHello.random, hs.hello.random)
+
+	return nil
+}
+
+func (hs *serverHandshakeState) establishKeys() error {
+	c := hs.c
+
+	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+		keysFromMasterSecret(c.vers, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
+
+	var clientCipher, serverCipher interface{}
+	var clientHash, serverHash macFunction
+
+	if hs.suite.aead == nil {
+		clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
+		clientHash = hs.suite.mac(c.vers, clientMAC)
+		serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
+		serverHash = hs.suite.mac(c.vers, serverMAC)
+	} else {
+		clientCipher = hs.suite.aead(clientKey, clientIV)
+		serverCipher = hs.suite.aead(serverKey, serverIV)
+	}
+
+	c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
+	c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
+
+	return nil
+}
+
+func (hs *serverHandshakeState) readFinished() error {
+	c := hs.c
+
+	c.readRecord(recordTypeChangeCipherSpec)
+	if err := c.in.error(); err != nil {
+		return err
+	}
+
+	if hs.hello.nextProtoNeg {
+		msg, err := c.readHandshake()
+		if err != nil {
+			return err
+		}
+		nextProto, ok := msg.(*nextProtoMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(nextProto, msg)
+		}
+		hs.finishedHash.Write(nextProto.marshal())
+		c.clientProtocol = nextProto.proto
+	}
+
+	msg, err := c.readHandshake()
+	if err != nil {
+		return err
+	}
+	clientFinished, ok := msg.(*finishedMsg)
+	if !ok {
+		c.sendAlert(alertUnexpectedMessage)
+		return unexpectedMessageError(clientFinished, msg)
+	}
+
+	verify := hs.finishedHash.clientSum(hs.masterSecret)
+	if len(verify) != len(clientFinished.verifyData) ||
+		subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("tls: client's Finished message is incorrect")
+	}
+
+	hs.finishedHash.Write(clientFinished.marshal())
+	return nil
+}
+
+func (hs *serverHandshakeState) sendSessionTicket() error {
+	if !hs.hello.ticketSupported {
+		return nil
+	}
+
+	c := hs.c
+	m := new(newSessionTicketMsg)
+
+	var err error
+	state := sessionState{
+		vers:         c.vers,
+		cipherSuite:  hs.suite.id,
+		masterSecret: hs.masterSecret,
+		certificates: hs.certsFromClient,
+	}
+	m.ticket, err = c.encryptTicket(&state)
+	if err != nil {
+		return err
+	}
+
+	hs.finishedHash.Write(m.marshal())
+	c.writeRecord(recordTypeHandshake, m.marshal())
+
+	return nil
+}
+
+func (hs *serverHandshakeState) sendFinished() error {
+	c := hs.c
+
+	c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
+
+	finished := new(finishedMsg)
+	finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
+	hs.finishedHash.Write(finished.marshal())
+	c.writeRecord(recordTypeHandshake, finished.marshal())
+
+	c.cipherSuite = hs.suite.id
+
+	return nil
+}
+
+// processCertsFromClient takes a chain of client certificates either from a
+// Certificates message or from a sessionState and verifies them. It returns
+// the public key of the leaf certificate.
+func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
+	c := hs.c
+
+	hs.certsFromClient = certificates
+	certs := make([]*x509.Certificate, len(certificates))
+	var err error
+	for i, asn1Data := range certificates {
+		if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
+			c.sendAlert(alertBadCertificate)
+			return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
+		}
+	}
+
+	if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
+		opts := x509.VerifyOptions{
+			Roots:         c.config.ClientCAs,
+			CurrentTime:   c.config.time(),
+			Intermediates: x509.NewCertPool(),
+			KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
+		}
+
+		for _, cert := range certs[1:] {
+			opts.Intermediates.AddCert(cert)
+		}
+
+		chains, err := certs[0].Verify(opts)
+		if err != nil {
+			c.sendAlert(alertBadCertificate)
+			return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
+		}
+
+		ok := false
+		for _, ku := range certs[0].ExtKeyUsage {
+			if ku == x509.ExtKeyUsageClientAuth {
+				ok = true
+				break
+			}
+		}
+		if !ok {
+			c.sendAlert(alertHandshakeFailure)
+			return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
+		}
+
+		c.verifiedChains = chains
+	}
+
+	if len(certs) > 0 {
+		var pub crypto.PublicKey
+		switch key := certs[0].PublicKey.(type) {
+		case *ecdsa.PublicKey, *rsa.PublicKey:
+			pub = key
+		default:
+			c.sendAlert(alertUnsupportedCertificate)
+			return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
+		}
+		c.peerCertificates = certs
+		return pub, nil
+	}
+
+	return nil, nil
+}
+
+// tryCipherSuite returns a cipherSuite with the given id if that cipher suite
+// is acceptable to use.
+func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16, ellipticOk, ecdsaOk bool) *cipherSuite {
+	for _, supported := range supportedCipherSuites {
+		if id == supported {
+			var candidate *cipherSuite
+
+			for _, s := range cipherSuites {
+				if s.id == id {
+					candidate = s
+					break
+				}
+			}
+			if candidate == nil {
+				continue
+			}
+			// Don't select a ciphersuite which we can't
+			// support for this client.
+			if (candidate.flags&suiteECDHE != 0) && !ellipticOk {
+				continue
+			}
+			if (candidate.flags&suiteECDSA != 0) != ecdsaOk {
+				continue
+			}
+			if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
+				continue
+			}
+			return candidate
+		}
+	}
+
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/handshake_server_test.go b/third_party/gofrontend/libgo/go/crypto/tls/handshake_server_test.go
new file mode 100644
index 0000000..3444d5c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/handshake_server_test.go
@@ -0,0 +1,726 @@
+// 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 tls
+
+import (
+	"bytes"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/hex"
+	"encoding/pem"
+	"errors"
+	"fmt"
+	"io"
+	"math/big"
+	"net"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"testing"
+	"time"
+)
+
+// zeroSource is an io.Reader that returns an unlimited number of zero bytes.
+type zeroSource struct{}
+
+func (zeroSource) Read(b []byte) (n int, err error) {
+	for i := range b {
+		b[i] = 0
+	}
+
+	return len(b), nil
+}
+
+var testConfig *Config
+
+func init() {
+	testConfig = &Config{
+		Time:               func() time.Time { return time.Unix(0, 0) },
+		Rand:               zeroSource{},
+		Certificates:       make([]Certificate, 2),
+		InsecureSkipVerify: true,
+		MinVersion:         VersionSSL30,
+		MaxVersion:         VersionTLS12,
+	}
+	testConfig.Certificates[0].Certificate = [][]byte{testRSACertificate}
+	testConfig.Certificates[0].PrivateKey = testRSAPrivateKey
+	testConfig.Certificates[1].Certificate = [][]byte{testSNICertificate}
+	testConfig.Certificates[1].PrivateKey = testRSAPrivateKey
+	testConfig.BuildNameToCertificate()
+}
+
+func testClientHelloFailure(t *testing.T, m handshakeMessage, expectedSubStr string) {
+	// Create in-memory network connection,
+	// send message to server.  Should return
+	// expected error.
+	c, s := net.Pipe()
+	go func() {
+		cli := Client(c, testConfig)
+		if ch, ok := m.(*clientHelloMsg); ok {
+			cli.vers = ch.vers
+		}
+		cli.writeRecord(recordTypeHandshake, m.marshal())
+		c.Close()
+	}()
+	err := Server(s, testConfig).Handshake()
+	s.Close()
+	if err == nil || !strings.Contains(err.Error(), expectedSubStr) {
+		t.Errorf("Got error: %s; expected to match substring '%s'", err, expectedSubStr)
+	}
+}
+
+func TestSimpleError(t *testing.T) {
+	testClientHelloFailure(t, &serverHelloDoneMsg{}, "unexpected handshake message")
+}
+
+var badProtocolVersions = []uint16{0x0000, 0x0005, 0x0100, 0x0105, 0x0200, 0x0205}
+
+func TestRejectBadProtocolVersion(t *testing.T) {
+	for _, v := range badProtocolVersions {
+		testClientHelloFailure(t, &clientHelloMsg{vers: v}, "unsupported, maximum protocol version")
+	}
+}
+
+func TestNoSuiteOverlap(t *testing.T) {
+	clientHello := &clientHelloMsg{
+		vers:               0x0301,
+		cipherSuites:       []uint16{0xff00},
+		compressionMethods: []uint8{0},
+	}
+	testClientHelloFailure(t, clientHello, "no cipher suite supported by both client and server")
+}
+
+func TestNoCompressionOverlap(t *testing.T) {
+	clientHello := &clientHelloMsg{
+		vers:               0x0301,
+		cipherSuites:       []uint16{TLS_RSA_WITH_RC4_128_SHA},
+		compressionMethods: []uint8{0xff},
+	}
+	testClientHelloFailure(t, clientHello, "client does not support uncompressed connections")
+}
+
+func TestTLS12OnlyCipherSuites(t *testing.T) {
+	// Test that a Server doesn't select a TLS 1.2-only cipher suite when
+	// the client negotiates TLS 1.1.
+	var zeros [32]byte
+
+	clientHello := &clientHelloMsg{
+		vers:   VersionTLS11,
+		random: zeros[:],
+		cipherSuites: []uint16{
+			// The Server, by default, will use the client's
+			// preference order. So the GCM cipher suite
+			// will be selected unless it's excluded because
+			// of the version in this ClientHello.
+			TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+			TLS_RSA_WITH_RC4_128_SHA,
+		},
+		compressionMethods: []uint8{compressionNone},
+		supportedCurves:    []CurveID{CurveP256, CurveP384, CurveP521},
+		supportedPoints:    []uint8{pointFormatUncompressed},
+	}
+
+	c, s := net.Pipe()
+	var reply interface{}
+	var clientErr error
+	go func() {
+		cli := Client(c, testConfig)
+		cli.vers = clientHello.vers
+		cli.writeRecord(recordTypeHandshake, clientHello.marshal())
+		reply, clientErr = cli.readHandshake()
+		c.Close()
+	}()
+	config := *testConfig
+	config.CipherSuites = clientHello.cipherSuites
+	Server(s, &config).Handshake()
+	s.Close()
+	if clientErr != nil {
+		t.Fatal(clientErr)
+	}
+	serverHello, ok := reply.(*serverHelloMsg)
+	if !ok {
+		t.Fatalf("didn't get ServerHello message in reply. Got %v\n", reply)
+	}
+	if s := serverHello.cipherSuite; s != TLS_RSA_WITH_RC4_128_SHA {
+		t.Fatalf("bad cipher suite from server: %x", s)
+	}
+}
+
+func TestAlertForwarding(t *testing.T) {
+	c, s := net.Pipe()
+	go func() {
+		Client(c, testConfig).sendAlert(alertUnknownCA)
+		c.Close()
+	}()
+
+	err := Server(s, testConfig).Handshake()
+	s.Close()
+	if e, ok := err.(*net.OpError); !ok || e.Err != error(alertUnknownCA) {
+		t.Errorf("Got error: %s; expected: %s", err, error(alertUnknownCA))
+	}
+}
+
+func TestClose(t *testing.T) {
+	c, s := net.Pipe()
+	go c.Close()
+
+	err := Server(s, testConfig).Handshake()
+	s.Close()
+	if err != io.EOF {
+		t.Errorf("Got error: %s; expected: %s", err, io.EOF)
+	}
+}
+
+func testHandshake(clientConfig, serverConfig *Config) (state ConnectionState, err error) {
+	c, s := net.Pipe()
+	done := make(chan bool)
+	go func() {
+		cli := Client(c, clientConfig)
+		cli.Handshake()
+		c.Close()
+		done <- true
+	}()
+	server := Server(s, serverConfig)
+	err = server.Handshake()
+	if err == nil {
+		state = server.ConnectionState()
+	}
+	s.Close()
+	<-done
+	return
+}
+
+func TestVersion(t *testing.T) {
+	serverConfig := &Config{
+		Certificates: testConfig.Certificates,
+		MaxVersion:   VersionTLS11,
+	}
+	clientConfig := &Config{
+		InsecureSkipVerify: true,
+	}
+	state, err := testHandshake(clientConfig, serverConfig)
+	if err != nil {
+		t.Fatalf("handshake failed: %s", err)
+	}
+	if state.Version != VersionTLS11 {
+		t.Fatalf("Incorrect version %x, should be %x", state.Version, VersionTLS11)
+	}
+}
+
+func TestCipherSuitePreference(t *testing.T) {
+	serverConfig := &Config{
+		CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+		Certificates: testConfig.Certificates,
+		MaxVersion:   VersionTLS11,
+	}
+	clientConfig := &Config{
+		CipherSuites:       []uint16{TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_RC4_128_SHA},
+		InsecureSkipVerify: true,
+	}
+	state, err := testHandshake(clientConfig, serverConfig)
+	if err != nil {
+		t.Fatalf("handshake failed: %s", err)
+	}
+	if state.CipherSuite != TLS_RSA_WITH_AES_128_CBC_SHA {
+		// By default the server should use the client's preference.
+		t.Fatalf("Client's preference was not used, got %x", state.CipherSuite)
+	}
+
+	serverConfig.PreferServerCipherSuites = true
+	state, err = testHandshake(clientConfig, serverConfig)
+	if err != nil {
+		t.Fatalf("handshake failed: %s", err)
+	}
+	if state.CipherSuite != TLS_RSA_WITH_RC4_128_SHA {
+		t.Fatalf("Server's preference was not used, got %x", state.CipherSuite)
+	}
+}
+
+// Note: see comment in handshake_test.go for details of how the reference
+// tests work.
+
+// serverTest represents a test of the TLS server handshake against a reference
+// implementation.
+type serverTest struct {
+	// name is a freeform string identifying the test and the file in which
+	// the expected results will be stored.
+	name string
+	// command, if not empty, contains a series of arguments for the
+	// command to run for the reference server.
+	command []string
+	// expectedPeerCerts contains a list of PEM blocks of expected
+	// certificates from the client.
+	expectedPeerCerts []string
+	// config, if not nil, contains a custom Config to use for this test.
+	config *Config
+}
+
+var defaultClientCommand = []string{"openssl", "s_client", "-no_ticket"}
+
+// connFromCommand starts opens a listening socket and starts the reference
+// client to connect to it. It returns a recordingConn that wraps the resulting
+// connection.
+func (test *serverTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, err error) {
+	l, err := net.ListenTCP("tcp", &net.TCPAddr{
+		IP:   net.IPv4(127, 0, 0, 1),
+		Port: 0,
+	})
+	if err != nil {
+		return nil, nil, err
+	}
+	defer l.Close()
+
+	port := l.Addr().(*net.TCPAddr).Port
+
+	var command []string
+	command = append(command, test.command...)
+	if len(command) == 0 {
+		command = defaultClientCommand
+	}
+	command = append(command, "-connect")
+	command = append(command, fmt.Sprintf("127.0.0.1:%d", port))
+	cmd := exec.Command(command[0], command[1:]...)
+	cmd.Stdin = nil
+	var output bytes.Buffer
+	cmd.Stdout = &output
+	cmd.Stderr = &output
+	if err := cmd.Start(); err != nil {
+		return nil, nil, err
+	}
+
+	connChan := make(chan interface{})
+	go func() {
+		tcpConn, err := l.Accept()
+		if err != nil {
+			connChan <- err
+		}
+		connChan <- tcpConn
+	}()
+
+	var tcpConn net.Conn
+	select {
+	case connOrError := <-connChan:
+		if err, ok := connOrError.(error); ok {
+			return nil, nil, err
+		}
+		tcpConn = connOrError.(net.Conn)
+	case <-time.After(2 * time.Second):
+		output.WriteTo(os.Stdout)
+		return nil, nil, errors.New("timed out waiting for connection from child process")
+	}
+
+	record := &recordingConn{
+		Conn: tcpConn,
+	}
+
+	return record, cmd, nil
+}
+
+func (test *serverTest) dataPath() string {
+	return filepath.Join("testdata", "Server-"+test.name)
+}
+
+func (test *serverTest) loadData() (flows [][]byte, err error) {
+	in, err := os.Open(test.dataPath())
+	if err != nil {
+		return nil, err
+	}
+	defer in.Close()
+	return parseTestData(in)
+}
+
+func (test *serverTest) run(t *testing.T, write bool) {
+	var clientConn, serverConn net.Conn
+	var recordingConn *recordingConn
+	var childProcess *exec.Cmd
+
+	if write {
+		var err error
+		recordingConn, childProcess, err = test.connFromCommand()
+		if err != nil {
+			t.Fatalf("Failed to start subcommand: %s", err)
+		}
+		serverConn = recordingConn
+	} else {
+		clientConn, serverConn = net.Pipe()
+	}
+	config := test.config
+	if config == nil {
+		config = testConfig
+	}
+	server := Server(serverConn, config)
+	peerCertsChan := make(chan []*x509.Certificate, 1)
+	go func() {
+		if _, err := server.Write([]byte("hello, world\n")); err != nil {
+			t.Logf("Error from Server.Write: %s", err)
+		}
+		server.Close()
+		serverConn.Close()
+		peerCertsChan <- server.ConnectionState().PeerCertificates
+	}()
+
+	if !write {
+		flows, err := test.loadData()
+		if err != nil {
+			t.Fatalf("%s: failed to load data from %s", test.name, test.dataPath())
+		}
+		for i, b := range flows {
+			if i%2 == 0 {
+				clientConn.Write(b)
+				continue
+			}
+			bb := make([]byte, len(b))
+			n, err := io.ReadFull(clientConn, bb)
+			if err != nil {
+				t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", test.name, i+1, err, n, len(bb), bb[:n], b)
+			}
+			if !bytes.Equal(b, bb) {
+				t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i+1, bb, b)
+			}
+		}
+		clientConn.Close()
+	}
+
+	peerCerts := <-peerCertsChan
+	if len(peerCerts) == len(test.expectedPeerCerts) {
+		for i, peerCert := range peerCerts {
+			block, _ := pem.Decode([]byte(test.expectedPeerCerts[i]))
+			if !bytes.Equal(block.Bytes, peerCert.Raw) {
+				t.Fatalf("%s: mismatch on peer cert %d", test.name, i+1)
+			}
+		}
+	} else {
+		t.Fatalf("%s: mismatch on peer list length: %d (wanted) != %d (got)", test.name, len(test.expectedPeerCerts), len(peerCerts))
+	}
+
+	if write {
+		path := test.dataPath()
+		out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+		if err != nil {
+			t.Fatalf("Failed to create output file: %s", err)
+		}
+		defer out.Close()
+		recordingConn.Close()
+		if len(recordingConn.flows) < 3 {
+			childProcess.Stdout.(*bytes.Buffer).WriteTo(os.Stdout)
+			t.Fatalf("Handshake failed")
+		}
+		recordingConn.WriteTo(out)
+		fmt.Printf("Wrote %s\n", path)
+		childProcess.Wait()
+	}
+}
+
+func runServerTestForVersion(t *testing.T, template *serverTest, prefix, option string) {
+	test := *template
+	test.name = prefix + test.name
+	if len(test.command) == 0 {
+		test.command = defaultClientCommand
+	}
+	test.command = append([]string(nil), test.command...)
+	test.command = append(test.command, option)
+	test.run(t, *update)
+}
+
+func runServerTestSSLv3(t *testing.T, template *serverTest) {
+	runServerTestForVersion(t, template, "SSLv3-", "-ssl3")
+}
+
+func runServerTestTLS10(t *testing.T, template *serverTest) {
+	runServerTestForVersion(t, template, "TLSv10-", "-tls1")
+}
+
+func runServerTestTLS11(t *testing.T, template *serverTest) {
+	runServerTestForVersion(t, template, "TLSv11-", "-tls1_1")
+}
+
+func runServerTestTLS12(t *testing.T, template *serverTest) {
+	runServerTestForVersion(t, template, "TLSv12-", "-tls1_2")
+}
+
+func TestHandshakeServerRSARC4(t *testing.T) {
+	test := &serverTest{
+		name:    "RSA-RC4",
+		command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA"},
+	}
+	runServerTestSSLv3(t, test)
+	runServerTestTLS10(t, test)
+	runServerTestTLS11(t, test)
+	runServerTestTLS12(t, test)
+}
+
+func TestHandshakeServerRSA3DES(t *testing.T) {
+	test := &serverTest{
+		name:    "RSA-3DES",
+		command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "DES-CBC3-SHA"},
+	}
+	runServerTestSSLv3(t, test)
+	runServerTestTLS10(t, test)
+	runServerTestTLS12(t, test)
+}
+
+func TestHandshakeServerRSAAES(t *testing.T) {
+	test := &serverTest{
+		name:    "RSA-AES",
+		command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA"},
+	}
+	runServerTestSSLv3(t, test)
+	runServerTestTLS10(t, test)
+	runServerTestTLS12(t, test)
+}
+
+func TestHandshakeServerAESGCM(t *testing.T) {
+	test := &serverTest{
+		name:    "RSA-AES-GCM",
+		command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-AES128-GCM-SHA256"},
+	}
+	runServerTestTLS12(t, test)
+}
+
+func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
+	config := *testConfig
+	config.Certificates = make([]Certificate, 1)
+	config.Certificates[0].Certificate = [][]byte{testECDSACertificate}
+	config.Certificates[0].PrivateKey = testECDSAPrivateKey
+	config.BuildNameToCertificate()
+
+	test := &serverTest{
+		name:    "ECDHE-ECDSA-AES",
+		command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-ECDSA-AES256-SHA"},
+		config:  &config,
+	}
+	runServerTestTLS10(t, test)
+	runServerTestTLS12(t, test)
+}
+
+// TestHandshakeServerSNI involves a client sending an SNI extension of
+// "snitest.com", which happens to match the CN of testSNICertificate. The test
+// verifies that the server correctly selects that certificate.
+func TestHandshakeServerSNI(t *testing.T) {
+	test := &serverTest{
+		name:    "SNI",
+		command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"},
+	}
+	runServerTestTLS12(t, test)
+}
+
+// TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with
+// an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate.
+func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
+	config := *testConfig
+	config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}
+	config.PreferServerCipherSuites = true
+
+	test := &serverTest{
+		name:   "CipherSuiteCertPreferenceRSA",
+		config: &config,
+	}
+	runServerTestTLS12(t, test)
+
+	config = *testConfig
+	config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}
+	config.Certificates = []Certificate{
+		Certificate{
+			Certificate: [][]byte{testECDSACertificate},
+			PrivateKey:  testECDSAPrivateKey,
+		},
+	}
+	config.BuildNameToCertificate()
+	config.PreferServerCipherSuites = true
+
+	test = &serverTest{
+		name:   "CipherSuiteCertPreferenceECDSA",
+		config: &config,
+	}
+	runServerTestTLS12(t, test)
+}
+
+func TestResumption(t *testing.T) {
+	sessionFilePath := tempFile("")
+	defer os.Remove(sessionFilePath)
+
+	test := &serverTest{
+		name:    "IssueTicket",
+		command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath},
+	}
+	runServerTestTLS12(t, test)
+
+	test = &serverTest{
+		name:    "Resume",
+		command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath},
+	}
+	runServerTestTLS12(t, test)
+}
+
+func TestResumptionDisabled(t *testing.T) {
+	sessionFilePath := tempFile("")
+	defer os.Remove(sessionFilePath)
+
+	config := *testConfig
+
+	test := &serverTest{
+		name:    "IssueTicketPreDisable",
+		command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath},
+		config:  &config,
+	}
+	runServerTestTLS12(t, test)
+
+	config.SessionTicketsDisabled = true
+
+	test = &serverTest{
+		name:    "ResumeDisabled",
+		command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath},
+		config:  &config,
+	}
+	runServerTestTLS12(t, test)
+
+	// One needs to manually confirm that the handshake in the golden data
+	// file for ResumeDisabled does not include a resumption handshake.
+}
+
+// cert.pem and key.pem were generated with generate_cert.go
+// Thus, they have no ExtKeyUsage fields and trigger an error
+// when verification is turned on.
+
+const clientCertificatePEM = `
+-----BEGIN CERTIFICATE-----
+MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
+bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4
+MDAxMlowJjEQMA4GA1UEChMHQWNtZSBDbzESMBAGA1UEAxMJMTI3LjAuMC4xMIGc
+MAsGCSqGSIb3DQEBAQOBjAAwgYgCgYBO0Hsx44Jk2VnAwoekXh6LczPHY1PfZpIG
+hPZk1Y/kNqcdK+izIDZFI7Xjla7t4PUgnI2V339aEu+H5Fto5OkOdOwEin/ekyfE
+ARl6vfLcPRSr0FTKIQzQTW6HLlzF0rtNS0/Otiz3fojsfNcCkXSmHgwa2uNKWi7e
+E5xMQIhZkwIDAQABozIwMDAOBgNVHQ8BAf8EBAMCAKAwDQYDVR0OBAYEBAECAwQw
+DwYDVR0jBAgwBoAEAQIDBDALBgkqhkiG9w0BAQUDgYEANh+zegx1yW43RmEr1b3A
+p0vMRpqBWHyFeSnIyMZn3TJWRSt1tukkqVCavh9a+hoV2cxVlXIWg7nCto/9iIw4
+hB2rXZIxE0/9gzvGnfERYraL7KtnvshksBFQRlgXa5kc0x38BvEO5ZaoDPl4ILdE
+GFGNEH5PlGffo05wc46QkYU=
+-----END CERTIFICATE-----`
+
+const clientKeyPEM = `
+-----BEGIN RSA PRIVATE KEY-----
+MIICWgIBAAKBgE7QezHjgmTZWcDCh6ReHotzM8djU99mkgaE9mTVj+Q2px0r6LMg
+NkUjteOVru3g9SCcjZXff1oS74fkW2jk6Q507ASKf96TJ8QBGXq98tw9FKvQVMoh
+DNBNbocuXMXSu01LT862LPd+iOx81wKRdKYeDBra40paLt4TnExAiFmTAgMBAAEC
+gYBxvXd8yNteFTns8A/2yomEMC4yeosJJSpp1CsN3BJ7g8/qTnrVPxBy+RU+qr63
+t2WquaOu/cr5P8iEsa6lk20tf8pjKLNXeX0b1RTzK8rJLbS7nGzP3tvOhL096VtQ
+dAo4ROEaro0TzYpHmpciSvxVIeEIAAdFDObDJPKqcJAxyQJBAJizfYgK8Gzx9fsx
+hxp+VteCbVPg2euASH5Yv3K5LukRdKoSzHE2grUVQgN/LafC0eZibRanxHegYSr7
+7qaswKUCQQCEIWor/X4XTMdVj3Oj+vpiw75y/S9gh682+myZL+d/02IEkwnB098P
+RkKVpenBHyrGg0oeN5La7URILWKj7CPXAkBKo6F+d+phNjwIFoN1Xb/RA32w/D1I
+saG9sF+UEhRt9AxUfW/U/tIQ9V0ZHHcSg1XaCM5Nvp934brdKdvTOKnJAkBD5h/3
+Rybatlvg/fzBEaJFyq09zhngkxlZOUtBVTqzl17RVvY2orgH02U4HbCHy4phxOn7
+qTdQRYlHRftgnWK1AkANibn9PRYJ7mJyJ9Dyj2QeNcSkSTzrt0tPvUMf4+meJymN
+1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvA
+-----END RSA PRIVATE KEY-----`
+
+const clientECDSACertificatePEM = `
+-----BEGIN CERTIFICATE-----
+MIIB/DCCAV4CCQCaMIRsJjXZFzAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQwHhcNMTIxMTE0MTMyNTUzWhcNMjIxMTEyMTMyNTUzWjBBMQswCQYDVQQG
+EwJBVTEMMAoGA1UECBMDTlNXMRAwDgYDVQQHEwdQeXJtb250MRIwEAYDVQQDEwlK
+b2VsIFNpbmcwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACVjJF1FMBexFe01MNv
+ja5oHt1vzobhfm6ySD6B5U7ixohLZNz1MLvT/2XMW/TdtWo+PtAd3kfDdq0Z9kUs
+jLzYHQFMH3CQRnZIi4+DzEpcj0B22uCJ7B0rxE4wdihBsmKo+1vx+U56jb0JuK7q
+ixgnTy5w/hOWusPTQBbNZU6sER7m8TAJBgcqhkjOPQQBA4GMADCBiAJCAOAUxGBg
+C3JosDJdYUoCdFzCgbkWqD8pyDbHgf9stlvZcPE4O1BIKJTLCRpS8V3ujfK58PDa
+2RU6+b0DeoeiIzXsAkIBo9SKeDUcSpoj0gq+KxAxnZxfvuiRs9oa9V2jI/Umi0Vw
+jWVim34BmT0Y9hCaOGGbLlfk+syxis7iI6CH8OFnUes=
+-----END CERTIFICATE-----`
+
+const clientECDSAKeyPEM = `
+-----BEGIN EC PARAMETERS-----
+BgUrgQQAIw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBkJN9X4IqZIguiEVKMqeBUP5xtRsEv4HJEtOpOGLELwO53SD78Ew8
+k+wLWoqizS3NpQyMtrU8JFdWfj+C57UNkOugBwYFK4EEACOhgYkDgYYABACVjJF1
+FMBexFe01MNvja5oHt1vzobhfm6ySD6B5U7ixohLZNz1MLvT/2XMW/TdtWo+PtAd
+3kfDdq0Z9kUsjLzYHQFMH3CQRnZIi4+DzEpcj0B22uCJ7B0rxE4wdihBsmKo+1vx
++U56jb0JuK7qixgnTy5w/hOWusPTQBbNZU6sER7m8Q==
+-----END EC PRIVATE KEY-----`
+
+func TestClientAuth(t *testing.T) {
+	var certPath, keyPath, ecdsaCertPath, ecdsaKeyPath string
+
+	if *update {
+		certPath = tempFile(clientCertificatePEM)
+		defer os.Remove(certPath)
+		keyPath = tempFile(clientKeyPEM)
+		defer os.Remove(keyPath)
+		ecdsaCertPath = tempFile(clientECDSACertificatePEM)
+		defer os.Remove(ecdsaCertPath)
+		ecdsaKeyPath = tempFile(clientECDSAKeyPEM)
+		defer os.Remove(ecdsaKeyPath)
+	}
+
+	config := *testConfig
+	config.ClientAuth = RequestClientCert
+
+	test := &serverTest{
+		name:    "ClientAuthRequestedNotGiven",
+		command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA"},
+		config:  &config,
+	}
+	runServerTestTLS12(t, test)
+
+	test = &serverTest{
+		name:              "ClientAuthRequestedAndGiven",
+		command:           []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", certPath, "-key", keyPath},
+		config:            &config,
+		expectedPeerCerts: []string{clientCertificatePEM},
+	}
+	runServerTestTLS12(t, test)
+
+	test = &serverTest{
+		name:              "ClientAuthRequestedAndECDSAGiven",
+		command:           []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", ecdsaCertPath, "-key", ecdsaKeyPath},
+		config:            &config,
+		expectedPeerCerts: []string{clientECDSACertificatePEM},
+	}
+	runServerTestTLS12(t, test)
+}
+
+func bigFromString(s string) *big.Int {
+	ret := new(big.Int)
+	ret.SetString(s, 10)
+	return ret
+}
+
+func fromHex(s string) []byte {
+	b, _ := hex.DecodeString(s)
+	return b
+}
+
+var testRSACertificate = fromHex("308202b030820219a00302010202090085b0bba48a7fb8ca300d06092a864886f70d01010505003045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3130303432343039303933385a170d3131303432343039303933385a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819f300d06092a864886f70d010101050003818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a381a73081a4301d0603551d0e04160414b1ade2855acfcb28db69ce2369ded3268e18883930750603551d23046e306c8014b1ade2855acfcb28db69ce2369ded3268e188839a149a4473045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746482090085b0bba48a7fb8ca300c0603551d13040530030101ff300d06092a864886f70d010105050003818100086c4524c76bb159ab0c52ccf2b014d7879d7a6475b55a9566e4c52b8eae12661feb4f38b36e60d392fdf74108b52513b1187a24fb301dbaed98b917ece7d73159db95d31d78ea50565cd5825a2d5a5f33c4b6d8c97590968c0f5298b5cd981f89205ff2a01ca31b9694dda9fd57e970e8266d71999b266e3850296c90a7bdd9")
+
+var testECDSACertificate = fromHex("3082020030820162020900b8bf2d47a0d2ebf4300906072a8648ce3d04013045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3132313132323135303633325a170d3232313132303135303633325a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819b301006072a8648ce3d020106052b81040023038186000400c4a1edbe98f90b4873367ec316561122f23d53c33b4d213dcd6b75e6f6b0dc9adf26c1bcb287f072327cb3642f1c90bcea6823107efee325c0483a69e0286dd33700ef0462dd0da09c706283d881d36431aa9e9731bd96b068c09b23de76643f1a5c7fe9120e5858b65f70dd9bd8ead5d7f5d5ccb9b69f30665b669a20e227e5bffe3b300906072a8648ce3d040103818c0030818802420188a24febe245c5487d1bacf5ed989dae4770c05e1bb62fbdf1b64db76140d311a2ceee0b7e927eff769dc33b7ea53fcefa10e259ec472d7cacda4e970e15a06fd00242014dfcbe67139c2d050ebd3fa38c25c13313830d9406bbd4377af6ec7ac9862eddd711697f857c56defb31782be4c7780daecbbe9e4e3624317b6a0f399512078f2a")
+
+var testSNICertificate = fromHex("308201f23082015da003020102020100300b06092a864886f70d01010530283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d301e170d3132303431313137343033355a170d3133303431313137343533355a30283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d30819d300b06092a864886f70d01010103818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a3323030300e0603551d0f0101ff0404030200a0300d0603551d0e0406040401020304300f0603551d2304083006800401020304300b06092a864886f70d0101050381810089c6455f1c1f5ef8eb1ab174ee2439059f5c4259bb1a8d86cdb1d056f56a717da40e95ab90f59e8deaf627c157995094db0802266eb34fc6842dea8a4b68d9c1389103ab84fb9e1f85d9b5d23ff2312c8670fbb540148245a4ebafe264d90c8a4cf4f85b0fac12ac2fc4a3154bad52462868af96c62c6525d652b6e31845bdcc")
+
+var testRSAPrivateKey = &rsa.PrivateKey{
+	PublicKey: rsa.PublicKey{
+		N: bigFromString("131650079503776001033793877885499001334664249354723305978524647182322416328664556247316495448366990052837680518067798333412266673813370895702118944398081598789828837447552603077848001020611640547221687072142537202428102790818451901395596882588063427854225330436740647715202971973145151161964464812406232198521"),
+		E: 65537,
+	},
+	D: bigFromString("29354450337804273969007277378287027274721892607543397931919078829901848876371746653677097639302788129485893852488285045793268732234230875671682624082413996177431586734171663258657462237320300610850244186316880055243099640544518318093544057213190320837094958164973959123058337475052510833916491060913053867729"),
+	Primes: []*big.Int{
+		bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
+		bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
+	},
+}
+
+var testECDSAPrivateKey = &ecdsa.PrivateKey{
+	PublicKey: ecdsa.PublicKey{
+		Curve: elliptic.P521(),
+		X:     bigFromString("2636411247892461147287360222306590634450676461695221912739908880441342231985950069527906976759812296359387337367668045707086543273113073382714101597903639351"),
+		Y:     bigFromString("3204695818431246682253994090650952614555094516658732116404513121125038617915183037601737180082382202488628239201196033284060130040574800684774115478859677243"),
+	},
+	D: bigFromString("5477294338614160138026852784385529180817726002953041720191098180813046231640184669647735805135001309477695746518160084669446643325196003346204701381388769751"),
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/handshake_test.go b/third_party/gofrontend/libgo/go/crypto/tls/handshake_test.go
new file mode 100644
index 0000000..f95f274
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/handshake_test.go
@@ -0,0 +1,167 @@
+// Copyright 2013 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 tls
+
+import (
+	"bufio"
+	"encoding/hex"
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"strconv"
+	"strings"
+	"sync"
+)
+
+// TLS reference tests run a connection against a reference implementation
+// (OpenSSL) of TLS and record the bytes of the resulting connection. The Go
+// code, during a test, is configured with deterministic randomness and so the
+// reference test can be reproduced exactly in the future.
+//
+// In order to save everyone who wishes to run the tests from needing the
+// reference implementation installed, the reference connections are saved in
+// files in the testdata directory. Thus running the tests involves nothing
+// external, but creating and updating them requires the reference
+// implementation.
+//
+// Tests can be updated by running them with the -update flag. This will cause
+// the test files. Generally one should combine the -update flag with -test.run
+// to updated a specific test. Since the reference implementation will always
+// generate fresh random numbers, large parts of the reference connection will
+// always change.
+
+var update = flag.Bool("update", false, "update golden files on disk")
+
+// recordingConn is a net.Conn that records the traffic that passes through it.
+// WriteTo can be used to produce output that can be later be loaded with
+// ParseTestData.
+type recordingConn struct {
+	net.Conn
+	sync.Mutex
+	flows   [][]byte
+	reading bool
+}
+
+func (r *recordingConn) Read(b []byte) (n int, err error) {
+	if n, err = r.Conn.Read(b); n == 0 {
+		return
+	}
+	b = b[:n]
+
+	r.Lock()
+	defer r.Unlock()
+
+	if l := len(r.flows); l == 0 || !r.reading {
+		buf := make([]byte, len(b))
+		copy(buf, b)
+		r.flows = append(r.flows, buf)
+	} else {
+		r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+	}
+	r.reading = true
+	return
+}
+
+func (r *recordingConn) Write(b []byte) (n int, err error) {
+	if n, err = r.Conn.Write(b); n == 0 {
+		return
+	}
+	b = b[:n]
+
+	r.Lock()
+	defer r.Unlock()
+
+	if l := len(r.flows); l == 0 || r.reading {
+		buf := make([]byte, len(b))
+		copy(buf, b)
+		r.flows = append(r.flows, buf)
+	} else {
+		r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+	}
+	r.reading = false
+	return
+}
+
+// WriteTo writes Go source code to w that contains the recorded traffic.
+func (r *recordingConn) WriteTo(w io.Writer) {
+	// TLS always starts with a client to server flow.
+	clientToServer := true
+
+	for i, flow := range r.flows {
+		source, dest := "client", "server"
+		if !clientToServer {
+			source, dest = dest, source
+		}
+		fmt.Fprintf(w, ">>> Flow %d (%s to %s)\n", i+1, source, dest)
+		dumper := hex.Dumper(w)
+		dumper.Write(flow)
+		dumper.Close()
+		clientToServer = !clientToServer
+	}
+}
+
+func parseTestData(r io.Reader) (flows [][]byte, err error) {
+	var currentFlow []byte
+
+	scanner := bufio.NewScanner(r)
+	for scanner.Scan() {
+		line := scanner.Text()
+		// If the line starts with ">>> " then it marks the beginning
+		// of a new flow.
+		if strings.HasPrefix(line, ">>> ") {
+			if len(currentFlow) > 0 || len(flows) > 0 {
+				flows = append(flows, currentFlow)
+				currentFlow = nil
+			}
+			continue
+		}
+
+		// Otherwise the line is a line of hex dump that looks like:
+		// 00000170  fc f5 06 bf (...)  |.....X{&?......!|
+		// (Some bytes have been omitted from the middle section.)
+
+		if i := strings.IndexByte(line, ' '); i >= 0 {
+			line = line[i:]
+		} else {
+			return nil, errors.New("invalid test data")
+		}
+
+		if i := strings.IndexByte(line, '|'); i >= 0 {
+			line = line[:i]
+		} else {
+			return nil, errors.New("invalid test data")
+		}
+
+		hexBytes := strings.Fields(line)
+		for _, hexByte := range hexBytes {
+			val, err := strconv.ParseUint(hexByte, 16, 8)
+			if err != nil {
+				return nil, errors.New("invalid hex byte in test data: " + err.Error())
+			}
+			currentFlow = append(currentFlow, byte(val))
+		}
+	}
+
+	if len(currentFlow) > 0 {
+		flows = append(flows, currentFlow)
+	}
+
+	return flows, nil
+}
+
+// tempFile creates a temp file containing contents and returns its path.
+func tempFile(contents string) string {
+	file, err := ioutil.TempFile("", "go-tls-test")
+	if err != nil {
+		panic("failed to create temp file: " + err.Error())
+	}
+	path := file.Name()
+	file.WriteString(contents)
+	file.Close()
+	return path
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/key_agreement.go b/third_party/gofrontend/libgo/go/crypto/tls/key_agreement.go
new file mode 100644
index 0000000..f38b701
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/key_agreement.go
@@ -0,0 +1,407 @@
+// Copyright 2010 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 tls
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/md5"
+	"crypto/rsa"
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/x509"
+	"encoding/asn1"
+	"errors"
+	"io"
+	"math/big"
+)
+
+var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
+var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
+
+// rsaKeyAgreement implements the standard TLS key agreement where the client
+// encrypts the pre-master secret to the server's public key.
+type rsaKeyAgreement struct{}
+
+func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+	return nil, nil
+}
+
+func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+	preMasterSecret := make([]byte, 48)
+	_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
+	if err != nil {
+		return nil, err
+	}
+
+	if len(ckx.ciphertext) < 2 {
+		return nil, errClientKeyExchange
+	}
+
+	ciphertext := ckx.ciphertext
+	if version != VersionSSL30 {
+		ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
+		if ciphertextLen != len(ckx.ciphertext)-2 {
+			return nil, errClientKeyExchange
+		}
+		ciphertext = ckx.ciphertext[2:]
+	}
+
+	err = rsa.DecryptPKCS1v15SessionKey(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
+	if err != nil {
+		return nil, err
+	}
+	// We don't check the version number in the premaster secret.  For one,
+	// by checking it, we would leak information about the validity of the
+	// encrypted pre-master secret. Secondly, it provides only a small
+	// benefit against a downgrade attack and some implementations send the
+	// wrong version anyway. See the discussion at the end of section
+	// 7.4.7.1 of RFC 4346.
+	return preMasterSecret, nil
+}
+
+func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+	return errors.New("tls: unexpected ServerKeyExchange")
+}
+
+func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+	preMasterSecret := make([]byte, 48)
+	preMasterSecret[0] = byte(clientHello.vers >> 8)
+	preMasterSecret[1] = byte(clientHello.vers)
+	_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
+	if err != nil {
+		return nil, nil, err
+	}
+
+	encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
+	if err != nil {
+		return nil, nil, err
+	}
+	ckx := new(clientKeyExchangeMsg)
+	ckx.ciphertext = make([]byte, len(encrypted)+2)
+	ckx.ciphertext[0] = byte(len(encrypted) >> 8)
+	ckx.ciphertext[1] = byte(len(encrypted))
+	copy(ckx.ciphertext[2:], encrypted)
+	return preMasterSecret, ckx, nil
+}
+
+// sha1Hash calculates a SHA1 hash over the given byte slices.
+func sha1Hash(slices [][]byte) []byte {
+	hsha1 := sha1.New()
+	for _, slice := range slices {
+		hsha1.Write(slice)
+	}
+	return hsha1.Sum(nil)
+}
+
+// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
+// concatenation of an MD5 and SHA1 hash.
+func md5SHA1Hash(slices [][]byte) []byte {
+	md5sha1 := make([]byte, md5.Size+sha1.Size)
+	hmd5 := md5.New()
+	for _, slice := range slices {
+		hmd5.Write(slice)
+	}
+	copy(md5sha1, hmd5.Sum(nil))
+	copy(md5sha1[md5.Size:], sha1Hash(slices))
+	return md5sha1
+}
+
+// sha256Hash implements TLS 1.2's hash function.
+func sha256Hash(slices [][]byte) []byte {
+	h := sha256.New()
+	for _, slice := range slices {
+		h.Write(slice)
+	}
+	return h.Sum(nil)
+}
+
+// hashForServerKeyExchange hashes the given slices and returns their digest
+// and the identifier of the hash function used. The hashFunc argument is only
+// used for >= TLS 1.2 and precisely identifies the hash function to use.
+func hashForServerKeyExchange(sigType, hashFunc uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
+	if version >= VersionTLS12 {
+		switch hashFunc {
+		case hashSHA256:
+			return sha256Hash(slices), crypto.SHA256, nil
+		case hashSHA1:
+			return sha1Hash(slices), crypto.SHA1, nil
+		default:
+			return nil, crypto.Hash(0), errors.New("tls: unknown hash function used by peer")
+		}
+	}
+	if sigType == signatureECDSA {
+		return sha1Hash(slices), crypto.SHA1, nil
+	}
+	return md5SHA1Hash(slices), crypto.MD5SHA1, nil
+}
+
+// pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
+// ServerKeyExchange given the signature type being used and the client's
+// advertised list of supported signature and hash combinations.
+func pickTLS12HashForSignature(sigType uint8, clientSignatureAndHashes []signatureAndHash) (uint8, error) {
+	if len(clientSignatureAndHashes) == 0 {
+		// If the client didn't specify any signature_algorithms
+		// extension then we can assume that it supports SHA1. See
+		// http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+		return hashSHA1, nil
+	}
+
+	for _, sigAndHash := range clientSignatureAndHashes {
+		if sigAndHash.signature != sigType {
+			continue
+		}
+		switch sigAndHash.hash {
+		case hashSHA1, hashSHA256:
+			return sigAndHash.hash, nil
+		}
+	}
+
+	return 0, errors.New("tls: client doesn't support any common hash functions")
+}
+
+func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
+	switch id {
+	case CurveP256:
+		return elliptic.P256(), true
+	case CurveP384:
+		return elliptic.P384(), true
+	case CurveP521:
+		return elliptic.P521(), true
+	default:
+		return nil, false
+	}
+
+}
+
+// ecdheRSAKeyAgreement implements a TLS key agreement where the server
+// generates a ephemeral EC public/private key pair and signs it. The
+// pre-master secret is then calculated using ECDH. The signature may
+// either be ECDSA or RSA.
+type ecdheKeyAgreement struct {
+	version    uint16
+	sigType    uint8
+	privateKey []byte
+	curve      elliptic.Curve
+	x, y       *big.Int
+}
+
+func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+	var curveid CurveID
+	preferredCurves := config.curvePreferences()
+
+NextCandidate:
+	for _, candidate := range preferredCurves {
+		for _, c := range clientHello.supportedCurves {
+			if candidate == c {
+				curveid = c
+				break NextCandidate
+			}
+		}
+	}
+
+	if curveid == 0 {
+		return nil, errors.New("tls: no supported elliptic curves offered")
+	}
+
+	var ok bool
+	if ka.curve, ok = curveForCurveID(curveid); !ok {
+		return nil, errors.New("tls: preferredCurves includes unsupported curve")
+	}
+
+	var x, y *big.Int
+	var err error
+	ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
+	if err != nil {
+		return nil, err
+	}
+	ecdhePublic := elliptic.Marshal(ka.curve, x, y)
+
+	// http://tools.ietf.org/html/rfc4492#section-5.4
+	serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
+	serverECDHParams[0] = 3 // named curve
+	serverECDHParams[1] = byte(curveid >> 8)
+	serverECDHParams[2] = byte(curveid)
+	serverECDHParams[3] = byte(len(ecdhePublic))
+	copy(serverECDHParams[4:], ecdhePublic)
+
+	var tls12HashId uint8
+	if ka.version >= VersionTLS12 {
+		if tls12HashId, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
+			return nil, err
+		}
+	}
+
+	digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, hello.random, serverECDHParams)
+	if err != nil {
+		return nil, err
+	}
+	var sig []byte
+	switch ka.sigType {
+	case signatureECDSA:
+		privKey, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
+		if !ok {
+			return nil, errors.New("ECDHE ECDSA requires an ECDSA server private key")
+		}
+		r, s, err := ecdsa.Sign(config.rand(), privKey, digest)
+		if err != nil {
+			return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
+		}
+		sig, err = asn1.Marshal(ecdsaSignature{r, s})
+	case signatureRSA:
+		privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
+		if !ok {
+			return nil, errors.New("ECDHE RSA requires a RSA server private key")
+		}
+		sig, err = rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
+		if err != nil {
+			return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
+		}
+	default:
+		return nil, errors.New("unknown ECDHE signature algorithm")
+	}
+
+	skx := new(serverKeyExchangeMsg)
+	sigAndHashLen := 0
+	if ka.version >= VersionTLS12 {
+		sigAndHashLen = 2
+	}
+	skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig))
+	copy(skx.key, serverECDHParams)
+	k := skx.key[len(serverECDHParams):]
+	if ka.version >= VersionTLS12 {
+		k[0] = tls12HashId
+		k[1] = ka.sigType
+		k = k[2:]
+	}
+	k[0] = byte(len(sig) >> 8)
+	k[1] = byte(len(sig))
+	copy(k[2:], sig)
+
+	return skx, nil
+}
+
+func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+	if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
+		return nil, errClientKeyExchange
+	}
+	x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
+	if x == nil {
+		return nil, errClientKeyExchange
+	}
+	x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
+	preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
+	xBytes := x.Bytes()
+	copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
+
+	return preMasterSecret, nil
+}
+
+func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+	if len(skx.key) < 4 {
+		return errServerKeyExchange
+	}
+	if skx.key[0] != 3 { // named curve
+		return errors.New("tls: server selected unsupported curve")
+	}
+	curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
+
+	var ok bool
+	if ka.curve, ok = curveForCurveID(curveid); !ok {
+		return errors.New("tls: server selected unsupported curve")
+	}
+
+	publicLen := int(skx.key[3])
+	if publicLen+4 > len(skx.key) {
+		return errServerKeyExchange
+	}
+	ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
+	if ka.x == nil {
+		return errServerKeyExchange
+	}
+	serverECDHParams := skx.key[:4+publicLen]
+
+	sig := skx.key[4+publicLen:]
+	if len(sig) < 2 {
+		return errServerKeyExchange
+	}
+
+	var tls12HashId uint8
+	if ka.version >= VersionTLS12 {
+		// handle SignatureAndHashAlgorithm
+		var sigAndHash []uint8
+		sigAndHash, sig = sig[:2], sig[2:]
+		if sigAndHash[1] != ka.sigType {
+			return errServerKeyExchange
+		}
+		tls12HashId = sigAndHash[0]
+		if len(sig) < 2 {
+			return errServerKeyExchange
+		}
+	}
+	sigLen := int(sig[0])<<8 | int(sig[1])
+	if sigLen+2 != len(sig) {
+		return errServerKeyExchange
+	}
+	sig = sig[2:]
+
+	digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, serverHello.random, serverECDHParams)
+	if err != nil {
+		return err
+	}
+	switch ka.sigType {
+	case signatureECDSA:
+		pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
+		if !ok {
+			return errors.New("ECDHE ECDSA requires a ECDSA server public key")
+		}
+		ecdsaSig := new(ecdsaSignature)
+		if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
+			return err
+		}
+		if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+			return errors.New("ECDSA signature contained zero or negative values")
+		}
+		if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
+			return errors.New("ECDSA verification failure")
+		}
+	case signatureRSA:
+		pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
+		if !ok {
+			return errors.New("ECDHE RSA requires a RSA server public key")
+		}
+		if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
+			return err
+		}
+	default:
+		return errors.New("unknown ECDHE signature algorithm")
+	}
+
+	return nil
+}
+
+func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+	if ka.curve == nil {
+		return nil, nil, errors.New("missing ServerKeyExchange message")
+	}
+	priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
+	if err != nil {
+		return nil, nil, err
+	}
+	x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
+	preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
+	xBytes := x.Bytes()
+	copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
+
+	serialized := elliptic.Marshal(ka.curve, mx, my)
+
+	ckx := new(clientKeyExchangeMsg)
+	ckx.ciphertext = make([]byte, 1+len(serialized))
+	ckx.ciphertext[0] = byte(len(serialized))
+	copy(ckx.ciphertext[1:], serialized)
+
+	return preMasterSecret, ckx, nil
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/prf.go b/third_party/gofrontend/libgo/go/crypto/tls/prf.go
new file mode 100644
index 0000000..fb8b3ab
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/prf.go
@@ -0,0 +1,291 @@
+// 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 tls
+
+import (
+	"crypto"
+	"crypto/hmac"
+	"crypto/md5"
+	"crypto/sha1"
+	"crypto/sha256"
+	"hash"
+)
+
+// Split a premaster secret in two as specified in RFC 4346, section 5.
+func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
+	s1 = secret[0 : (len(secret)+1)/2]
+	s2 = secret[len(secret)/2:]
+	return
+}
+
+// pHash implements the P_hash function, as defined in RFC 4346, section 5.
+func pHash(result, secret, seed []byte, hash func() hash.Hash) {
+	h := hmac.New(hash, secret)
+	h.Write(seed)
+	a := h.Sum(nil)
+
+	j := 0
+	for j < len(result) {
+		h.Reset()
+		h.Write(a)
+		h.Write(seed)
+		b := h.Sum(nil)
+		todo := len(b)
+		if j+todo > len(result) {
+			todo = len(result) - j
+		}
+		copy(result[j:j+todo], b)
+		j += todo
+
+		h.Reset()
+		h.Write(a)
+		a = h.Sum(nil)
+	}
+}
+
+// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
+func prf10(result, secret, label, seed []byte) {
+	hashSHA1 := sha1.New
+	hashMD5 := md5.New
+
+	labelAndSeed := make([]byte, len(label)+len(seed))
+	copy(labelAndSeed, label)
+	copy(labelAndSeed[len(label):], seed)
+
+	s1, s2 := splitPreMasterSecret(secret)
+	pHash(result, s1, labelAndSeed, hashMD5)
+	result2 := make([]byte, len(result))
+	pHash(result2, s2, labelAndSeed, hashSHA1)
+
+	for i, b := range result2 {
+		result[i] ^= b
+	}
+}
+
+// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
+func prf12(result, secret, label, seed []byte) {
+	labelAndSeed := make([]byte, len(label)+len(seed))
+	copy(labelAndSeed, label)
+	copy(labelAndSeed[len(label):], seed)
+
+	pHash(result, secret, labelAndSeed, sha256.New)
+}
+
+// prf30 implements the SSL 3.0 pseudo-random function, as defined in
+// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
+func prf30(result, secret, label, seed []byte) {
+	hashSHA1 := sha1.New()
+	hashMD5 := md5.New()
+
+	done := 0
+	i := 0
+	// RFC5246 section 6.3 says that the largest PRF output needed is 128
+	// bytes. Since no more ciphersuites will be added to SSLv3, this will
+	// remain true. Each iteration gives us 16 bytes so 10 iterations will
+	// be sufficient.
+	var b [11]byte
+	for done < len(result) {
+		for j := 0; j <= i; j++ {
+			b[j] = 'A' + byte(i)
+		}
+
+		hashSHA1.Reset()
+		hashSHA1.Write(b[:i+1])
+		hashSHA1.Write(secret)
+		hashSHA1.Write(seed)
+		digest := hashSHA1.Sum(nil)
+
+		hashMD5.Reset()
+		hashMD5.Write(secret)
+		hashMD5.Write(digest)
+
+		done += copy(result[done:], hashMD5.Sum(nil))
+		i++
+	}
+}
+
+const (
+	tlsRandomLength      = 32 // Length of a random nonce in TLS 1.1.
+	masterSecretLength   = 48 // Length of a master secret in TLS 1.1.
+	finishedVerifyLength = 12 // Length of verify_data in a Finished message.
+)
+
+var masterSecretLabel = []byte("master secret")
+var keyExpansionLabel = []byte("key expansion")
+var clientFinishedLabel = []byte("client finished")
+var serverFinishedLabel = []byte("server finished")
+
+func prfForVersion(version uint16) func(result, secret, label, seed []byte) {
+	switch version {
+	case VersionSSL30:
+		return prf30
+	case VersionTLS10, VersionTLS11:
+		return prf10
+	case VersionTLS12:
+		return prf12
+	default:
+		panic("unknown version")
+	}
+}
+
+// masterFromPreMasterSecret generates the master secret from the pre-master
+// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
+func masterFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte) []byte {
+	var seed [tlsRandomLength * 2]byte
+	copy(seed[0:len(clientRandom)], clientRandom)
+	copy(seed[len(clientRandom):], serverRandom)
+	masterSecret := make([]byte, masterSecretLength)
+	prfForVersion(version)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+	return masterSecret
+}
+
+// keysFromMasterSecret generates the connection keys from the master
+// secret, given the lengths of the MAC key, cipher key and IV, as defined in
+// RFC 2246, section 6.3.
+func keysFromMasterSecret(version uint16, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+	var seed [tlsRandomLength * 2]byte
+	copy(seed[0:len(clientRandom)], serverRandom)
+	copy(seed[len(serverRandom):], clientRandom)
+
+	n := 2*macLen + 2*keyLen + 2*ivLen
+	keyMaterial := make([]byte, n)
+	prfForVersion(version)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
+	clientMAC = keyMaterial[:macLen]
+	keyMaterial = keyMaterial[macLen:]
+	serverMAC = keyMaterial[:macLen]
+	keyMaterial = keyMaterial[macLen:]
+	clientKey = keyMaterial[:keyLen]
+	keyMaterial = keyMaterial[keyLen:]
+	serverKey = keyMaterial[:keyLen]
+	keyMaterial = keyMaterial[keyLen:]
+	clientIV = keyMaterial[:ivLen]
+	keyMaterial = keyMaterial[ivLen:]
+	serverIV = keyMaterial[:ivLen]
+	return
+}
+
+func newFinishedHash(version uint16) finishedHash {
+	if version >= VersionTLS12 {
+		return finishedHash{sha256.New(), sha256.New(), nil, nil, version}
+	}
+	return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), version}
+}
+
+// A finishedHash calculates the hash of a set of handshake messages suitable
+// for including in a Finished message.
+type finishedHash struct {
+	client hash.Hash
+	server hash.Hash
+
+	// Prior to TLS 1.2, an additional MD5 hash is required.
+	clientMD5 hash.Hash
+	serverMD5 hash.Hash
+
+	version uint16
+}
+
+func (h finishedHash) Write(msg []byte) (n int, err error) {
+	h.client.Write(msg)
+	h.server.Write(msg)
+
+	if h.version < VersionTLS12 {
+		h.clientMD5.Write(msg)
+		h.serverMD5.Write(msg)
+	}
+	return len(msg), nil
+}
+
+// finishedSum30 calculates the contents of the verify_data member of a SSLv3
+// Finished message given the MD5 and SHA1 hashes of a set of handshake
+// messages.
+func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []byte {
+	md5.Write(magic[:])
+	md5.Write(masterSecret)
+	md5.Write(ssl30Pad1[:])
+	md5Digest := md5.Sum(nil)
+
+	md5.Reset()
+	md5.Write(masterSecret)
+	md5.Write(ssl30Pad2[:])
+	md5.Write(md5Digest)
+	md5Digest = md5.Sum(nil)
+
+	sha1.Write(magic[:])
+	sha1.Write(masterSecret)
+	sha1.Write(ssl30Pad1[:40])
+	sha1Digest := sha1.Sum(nil)
+
+	sha1.Reset()
+	sha1.Write(masterSecret)
+	sha1.Write(ssl30Pad2[:40])
+	sha1.Write(sha1Digest)
+	sha1Digest = sha1.Sum(nil)
+
+	ret := make([]byte, len(md5Digest)+len(sha1Digest))
+	copy(ret, md5Digest)
+	copy(ret[len(md5Digest):], sha1Digest)
+	return ret
+}
+
+var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
+var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
+
+// clientSum returns the contents of the verify_data member of a client's
+// Finished message.
+func (h finishedHash) clientSum(masterSecret []byte) []byte {
+	if h.version == VersionSSL30 {
+		return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic)
+	}
+
+	out := make([]byte, finishedVerifyLength)
+	if h.version >= VersionTLS12 {
+		seed := h.client.Sum(nil)
+		prf12(out, masterSecret, clientFinishedLabel, seed)
+	} else {
+		seed := make([]byte, 0, md5.Size+sha1.Size)
+		seed = h.clientMD5.Sum(seed)
+		seed = h.client.Sum(seed)
+		prf10(out, masterSecret, clientFinishedLabel, seed)
+	}
+	return out
+}
+
+// serverSum returns the contents of the verify_data member of a server's
+// Finished message.
+func (h finishedHash) serverSum(masterSecret []byte) []byte {
+	if h.version == VersionSSL30 {
+		return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic)
+	}
+
+	out := make([]byte, finishedVerifyLength)
+	if h.version >= VersionTLS12 {
+		seed := h.server.Sum(nil)
+		prf12(out, masterSecret, serverFinishedLabel, seed)
+	} else {
+		seed := make([]byte, 0, md5.Size+sha1.Size)
+		seed = h.serverMD5.Sum(seed)
+		seed = h.server.Sum(seed)
+		prf10(out, masterSecret, serverFinishedLabel, seed)
+	}
+	return out
+}
+
+// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
+// id suitable for signing by a TLS client certificate.
+func (h finishedHash) hashForClientCertificate(sigType uint8) ([]byte, crypto.Hash, uint8) {
+	if h.version >= VersionTLS12 {
+		digest := h.server.Sum(nil)
+		return digest, crypto.SHA256, hashSHA256
+	}
+	if sigType == signatureECDSA {
+		digest := h.server.Sum(nil)
+		return digest, crypto.SHA1, hashSHA1
+	}
+
+	digest := make([]byte, 0, 36)
+	digest = h.serverMD5.Sum(digest)
+	digest = h.server.Sum(digest)
+	return digest, crypto.MD5SHA1, 0 /* not specified in TLS 1.2. */
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/prf_test.go b/third_party/gofrontend/libgo/go/crypto/tls/prf_test.go
new file mode 100644
index 0000000..a9b6c9e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/prf_test.go
@@ -0,0 +1,126 @@
+// 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 tls
+
+import (
+	"encoding/hex"
+	"testing"
+)
+
+type testSplitPreMasterSecretTest struct {
+	in, out1, out2 string
+}
+
+var testSplitPreMasterSecretTests = []testSplitPreMasterSecretTest{
+	{"", "", ""},
+	{"00", "00", "00"},
+	{"0011", "00", "11"},
+	{"001122", "0011", "1122"},
+	{"00112233", "0011", "2233"},
+}
+
+func TestSplitPreMasterSecret(t *testing.T) {
+	for i, test := range testSplitPreMasterSecretTests {
+		in, _ := hex.DecodeString(test.in)
+		out1, out2 := splitPreMasterSecret(in)
+		s1 := hex.EncodeToString(out1)
+		s2 := hex.EncodeToString(out2)
+		if s1 != test.out1 || s2 != test.out2 {
+			t.Errorf("#%d: got: (%s, %s) want: (%s, %s)", i, s1, s2, test.out1, test.out2)
+		}
+	}
+}
+
+type testKeysFromTest struct {
+	version                    uint16
+	preMasterSecret            string
+	clientRandom, serverRandom string
+	masterSecret               string
+	clientMAC, serverMAC       string
+	clientKey, serverKey       string
+	macLen, keyLen             int
+}
+
+func TestKeysFromPreMasterSecret(t *testing.T) {
+	for i, test := range testKeysFromTests {
+		in, _ := hex.DecodeString(test.preMasterSecret)
+		clientRandom, _ := hex.DecodeString(test.clientRandom)
+		serverRandom, _ := hex.DecodeString(test.serverRandom)
+
+		masterSecret := masterFromPreMasterSecret(test.version, in, clientRandom, serverRandom)
+		if s := hex.EncodeToString(masterSecret); s != test.masterSecret {
+			t.Errorf("#%d: bad master secret %s, want %s", i, s, test.masterSecret)
+			continue
+		}
+
+		clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromMasterSecret(test.version, masterSecret, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
+		clientMACString := hex.EncodeToString(clientMAC)
+		serverMACString := hex.EncodeToString(serverMAC)
+		clientKeyString := hex.EncodeToString(clientKey)
+		serverKeyString := hex.EncodeToString(serverKey)
+		if clientMACString != test.clientMAC ||
+			serverMACString != test.serverMAC ||
+			clientKeyString != test.clientKey ||
+			serverKeyString != test.serverKey {
+			t.Errorf("#%d: got: (%s, %s, %s, %s) want: (%s, %s, %s, %s)", i, clientMACString, serverMACString, clientKeyString, serverKeyString, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey)
+		}
+	}
+}
+
+// These test vectors were generated from GnuTLS using `gnutls-cli --insecure -d 9 `
+var testKeysFromTests = []testKeysFromTest{
+	{
+		VersionTLS10,
+		"0302cac83ad4b1db3b9ab49ad05957de2a504a634a386fc600889321e1a971f57479466830ac3e6f468e87f5385fa0c5",
+		"4ae66303755184a3917fcb44880605fcc53baa01912b22ed94473fc69cebd558",
+		"4ae663020ec16e6bb5130be918cfcafd4d765979a3136a5d50c593446e4e44db",
+		"3d851bab6e5556e959a16bc36d66cfae32f672bfa9ecdef6096cbb1b23472df1da63dbbd9827606413221d149ed08ceb",
+		"805aaa19b3d2c0a0759a4b6c9959890e08480119",
+		"2d22f9fe519c075c16448305ceee209fc24ad109",
+		"d50b5771244f850cd8117a9ccafe2cf1",
+		"e076e33206b30507a85c32855acd0919",
+		20,
+		16,
+	},
+	{
+		VersionTLS10,
+		"03023f7527316bc12cbcd69e4b9e8275d62c028f27e65c745cfcddc7ce01bd3570a111378b63848127f1c36e5f9e4890",
+		"4ae66364b5ea56b20ce4e25555aed2d7e67f42788dd03f3fee4adae0459ab106",
+		"4ae66363ab815cbf6a248b87d6b556184e945e9b97fbdf247858b0bdafacfa1c",
+		"7d64be7c80c59b740200b4b9c26d0baaa1c5ae56705acbcf2307fe62beb4728c19392c83f20483801cce022c77645460",
+		"97742ed60a0554ca13f04f97ee193177b971e3b0",
+		"37068751700400e03a8477a5c7eec0813ab9e0dc",
+		"207cddbc600d2a200abac6502053ee5c",
+		"df3f94f6e1eacc753b815fe16055cd43",
+		20,
+		16,
+	},
+	{
+		VersionTLS10,
+		"832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1",
+		"4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e",
+		"4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e",
+		"1aff2e7a2c4279d0126f57a65a77a8d9d0087cf2733366699bec27eb53d5740705a8574bb1acc2abbe90e44f0dd28d6c",
+		"3c7647c93c1379a31a609542aa44e7f117a70085",
+		"0d73102994be74a575a3ead8532590ca32a526d4",
+		"ac7581b0b6c10d85bbd905ffbf36c65e",
+		"ff07edde49682b45466bd2e39464b306",
+		20,
+		16,
+	},
+	{
+		VersionSSL30,
+		"832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1",
+		"4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e",
+		"4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e",
+		"a614863e56299dcffeea2938f22c2ba023768dbe4b3f6877bc9c346c6ae529b51d9cb87ff9695ea4d01f2205584405b2",
+		"2c450d5b6f6e2013ac6bea6a0b32200d4e1ffb94",
+		"7a7a7438769536f2fb1ae49a61f0703b79b2dc53",
+		"f8f6b26c10f12855c9aafb1e0e839ccf",
+		"2b9d4b4a60cb7f396780ebff50650419",
+		20,
+		16,
+	},
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
new file mode 100644
index 0000000..00722cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
@@ -0,0 +1,129 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 59 02 00 00  55 03 01 53 04 f1 03 46  |....Y...U..S...F|
+00000010  0f 84 c4 cb 55 ef 85 f6  4f d7 0e e1 4b 10 d4 bb  |....U...O...K...|
+00000020  35 87 2d f3 d7 18 ec 4e  95 4b f4 20 28 82 94 d9  |5.-....N.K. (...|
+00000030  df c4 fc ee 21 23 c1 e2  76 3e 7b 09 af 2c 39 23  |....!#..v>{..,9#|
+00000040  f8 46 6c 31 88 42 f0 79  de 37 2b 00 c0 09 00 00  |.Fl1.B.y.7+.....|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  01 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
+00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
+00000080  30 09 06 07 2a 86 48 ce  3d 04 01 30 45 31 0b 30  |0...*.H.=..0E1.0|
+00000090  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+000000a0  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+000000b0  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+000000c0  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+000000d0  74 64 30 1e 17 0d 31 32  31 31 32 32 31 35 30 36  |td0...1211221506|
+000000e0  33 32 5a 17 0d 32 32 31  31 32 30 31 35 30 36 33  |32Z..22112015063|
+000000f0  32 5a 30 45 31 0b 30 09  06 03 55 04 06 13 02 41  |2Z0E1.0...U....A|
+00000100  55 31 13 30 11 06 03 55  04 08 13 0a 53 6f 6d 65  |U1.0...U....Some|
+00000110  2d 53 74 61 74 65 31 21  30 1f 06 03 55 04 0a 13  |-State1!0...U...|
+00000120  18 49 6e 74 65 72 6e 65  74 20 57 69 64 67 69 74  |.Internet Widgit|
+00000130  73 20 50 74 79 20 4c 74  64 30 81 9b 30 10 06 07  |s Pty Ltd0..0...|
+00000140  2a 86 48 ce 3d 02 01 06  05 2b 81 04 00 23 03 81  |*.H.=....+...#..|
+00000150  86 00 04 00 c4 a1 ed be  98 f9 0b 48 73 36 7e c3  |...........Hs6~.|
+00000160  16 56 11 22 f2 3d 53 c3  3b 4d 21 3d cd 6b 75 e6  |.V.".=S.;M!=.ku.|
+00000170  f6 b0 dc 9a df 26 c1 bc  b2 87 f0 72 32 7c b3 64  |.....&.....r2|.d|
+00000180  2f 1c 90 bc ea 68 23 10  7e fe e3 25 c0 48 3a 69  |/....h#.~..%.H:i|
+00000190  e0 28 6d d3 37 00 ef 04  62 dd 0d a0 9c 70 62 83  |.(m.7...b....pb.|
+000001a0  d8 81 d3 64 31 aa 9e 97  31 bd 96 b0 68 c0 9b 23  |...d1...1...h..#|
+000001b0  de 76 64 3f 1a 5c 7f e9  12 0e 58 58 b6 5f 70 dd  |.vd?.\....XX._p.|
+000001c0  9b d8 ea d5 d7 f5 d5 cc  b9 b6 9f 30 66 5b 66 9a  |...........0f[f.|
+000001d0  20 e2 27 e5 bf fe 3b 30  09 06 07 2a 86 48 ce 3d  | .'...;0...*.H.=|
+000001e0  04 01 03 81 8c 00 30 81  88 02 42 01 88 a2 4f eb  |......0...B...O.|
+000001f0  e2 45 c5 48 7d 1b ac f5  ed 98 9d ae 47 70 c0 5e  |.E.H}.......Gp.^|
+00000200  1b b6 2f bd f1 b6 4d b7  61 40 d3 11 a2 ce ee 0b  |../...M.a@......|
+00000210  7e 92 7e ff 76 9d c3 3b  7e a5 3f ce fa 10 e2 59  |~.~.v..;~.?....Y|
+00000220  ec 47 2d 7c ac da 4e 97  0e 15 a0 6f d0 02 42 01  |.G-|..N....o..B.|
+00000230  4d fc be 67 13 9c 2d 05  0e bd 3f a3 8c 25 c1 33  |M..g..-...?..%.3|
+00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
+00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
+00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
+00000270  2a 16 03 01 00 d5 0c 00  00 d1 03 00 17 41 04 4f  |*............A.O|
+00000280  47 16 72 98 9e 9f 2e 8e  78 e9 0f fe 95 83 7b aa  |G.r.....x.....{.|
+00000290  e5 3d c0 7d cf 83 bd 22  0b fd 48 f1 a7 49 a5 7d  |.=.}..."..H..I.}|
+000002a0  8e 0c 83 7f e1 2d 71 03  cc 90 09 ab f7 35 81 48  |.....-q......5.H|
+000002b0  a4 1e 7d 87 21 23 12 58  2c 47 f3 af c7 6c 71 00  |..}.!#.X,G...lq.|
+000002c0  8a 30 81 87 02 42 00 b4  03 38 60 43 d9 32 ef 64  |.0...B...8`C.2.d|
+000002d0  5a 9c 91 95 0d 10 21 53  c7 78 f8 bf 50 ed 13 5d  |Z.....!S.x..P..]|
+000002e0  c3 e7 71 d6 11 04 f1 e4  9d ce 17 99 8d 1a 87 1f  |..q.............|
+000002f0  cb dd f8 1b ae cd bc 4a  77 ab 7c 50 bf 73 c3 ea  |.......Jw.|P.s..|
+00000300  d6 df 88 56 f6 b1 03 83  02 41 66 3d fb 4e 7e af  |...V.....Af=.N~.|
+00000310  4e c1 60 fe 09 fa 7e 74  99 66 7f de b4 b2 74 89  |N.`...~t.f....t.|
+00000320  1c a4 cf 74 1a 55 a5 be  74 f9 36 21 3d ae c8 c3  |...t.U..t.6!=...|
+00000330  24 8e ad db a3 26 67 8f  98 27 e3 93 ee d9 5c fb  |$....&g..'....\.|
+00000340  85 82 e2 13 c3 50 ab e9  f6 39 2b 16 03 01 00 0e  |.....P...9+.....|
+00000350  0d 00 00 06 03 01 02 40  00 00 0e 00 00 00        |.......@......|
+>>> Flow 3 (client to server)
+00000000  16 03 01 02 0a 0b 00 02  06 00 02 03 00 02 00 30  |...............0|
+00000010  82 01 fc 30 82 01 5e 02  09 00 9a 30 84 6c 26 35  |...0..^....0.l&5|
+00000020  d9 17 30 09 06 07 2a 86  48 ce 3d 04 01 30 45 31  |..0...*.H.=..0E1|
+00000030  0b 30 09 06 03 55 04 06  13 02 41 55 31 13 30 11  |.0...U....AU1.0.|
+00000040  06 03 55 04 08 13 0a 53  6f 6d 65 2d 53 74 61 74  |..U....Some-Stat|
+00000050  65 31 21 30 1f 06 03 55  04 0a 13 18 49 6e 74 65  |e1!0...U....Inte|
+00000060  72 6e 65 74 20 57 69 64  67 69 74 73 20 50 74 79  |rnet Widgits Pty|
+00000070  20 4c 74 64 30 1e 17 0d  31 32 31 31 31 34 31 33  | Ltd0...12111413|
+00000080  32 35 35 33 5a 17 0d 32  32 31 31 31 32 31 33 32  |2553Z..221112132|
+00000090  35 35 33 5a 30 41 31 0b  30 09 06 03 55 04 06 13  |553Z0A1.0...U...|
+000000a0  02 41 55 31 0c 30 0a 06  03 55 04 08 13 03 4e 53  |.AU1.0...U....NS|
+000000b0  57 31 10 30 0e 06 03 55  04 07 13 07 50 79 72 6d  |W1.0...U....Pyrm|
+000000c0  6f 6e 74 31 12 30 10 06  03 55 04 03 13 09 4a 6f  |ont1.0...U....Jo|
+000000d0  65 6c 20 53 69 6e 67 30  81 9b 30 10 06 07 2a 86  |el Sing0..0...*.|
+000000e0  48 ce 3d 02 01 06 05 2b  81 04 00 23 03 81 86 00  |H.=....+...#....|
+000000f0  04 00 95 8c 91 75 14 c0  5e c4 57 b4 d4 c3 6f 8d  |.....u..^.W...o.|
+00000100  ae 68 1e dd 6f ce 86 e1  7e 6e b2 48 3e 81 e5 4e  |.h..o...~n.H>..N|
+00000110  e2 c6 88 4b 64 dc f5 30  bb d3 ff 65 cc 5b f4 dd  |...Kd..0...e.[..|
+00000120  b5 6a 3e 3e d0 1d de 47  c3 76 ad 19 f6 45 2c 8c  |.j>>...G.v...E,.|
+00000130  bc d8 1d 01 4c 1f 70 90  46 76 48 8b 8f 83 cc 4a  |....L.p.FvH....J|
+00000140  5c 8f 40 76 da e0 89 ec  1d 2b c4 4e 30 76 28 41  |\.@v.....+.N0v(A|
+00000150  b2 62 a8 fb 5b f1 f9 4e  7a 8d bd 09 b8 ae ea 8b  |.b..[..Nz.......|
+00000160  18 27 4f 2e 70 fe 13 96  ba c3 d3 40 16 cd 65 4e  |.'O.p......@..eN|
+00000170  ac 11 1e e6 f1 30 09 06  07 2a 86 48 ce 3d 04 01  |.....0...*.H.=..|
+00000180  03 81 8c 00 30 81 88 02  42 00 e0 14 c4 60 60 0b  |....0...B....``.|
+00000190  72 68 b0 32 5d 61 4a 02  74 5c c2 81 b9 16 a8 3f  |rh.2]aJ.t\.....?|
+000001a0  29 c8 36 c7 81 ff 6c b6  5b d9 70 f1 38 3b 50 48  |).6...l.[.p.8;PH|
+000001b0  28 94 cb 09 1a 52 f1 5d  ee 8d f2 b9 f0 f0 da d9  |(....R.]........|
+000001c0  15 3a f9 bd 03 7a 87 a2  23 35 ec 02 42 01 a3 d4  |.:...z..#5..B...|
+000001d0  8a 78 35 1c 4a 9a 23 d2  0a be 2b 10 31 9d 9c 5f  |.x5.J.#...+.1.._|
+000001e0  be e8 91 b3 da 1a f5 5d  a3 23 f5 26 8b 45 70 8d  |.......].#.&.Ep.|
+000001f0  65 62 9b 7e 01 99 3d 18  f6 10 9a 38 61 9b 2e 57  |eb.~..=....8a..W|
+00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
+00000210  03 01 00 46 10 00 00 42  41 04 1e 18 37 ef 0d 19  |...F...BA...7...|
+00000220  51 88 35 75 71 b5 e5 54  5b 12 2e 8f 09 67 fd a7  |Q.5uq..T[....g..|
+00000230  24 20 3e b2 56 1c ce 97  28 5e f8 2b 2d 4f 9e f1  |$ >.V...(^.+-O..|
+00000240  07 9f 6c 4b 5b 83 56 e2  32 42 e9 58 b6 d7 49 a6  |..lK[.V.2B.X..I.|
+00000250  b5 68 1a 41 03 56 6b dc  5a 89 16 03 01 00 90 0f  |.h.A.Vk.Z.......|
+00000260  00 00 8c 00 8a 30 81 87  02 42 00 c6 85 8e 06 b7  |.....0...B......|
+00000270  04 04 e9 cd 9e 3e cb 66  23 95 b4 42 9c 64 81 39  |.....>.f#..B.d.9|
+00000280  05 3f b5 21 f8 28 af 60  6b 4d 3d ba a1 4b 5e 77  |.?.!.(.`kM=..K^w|
+00000290  ef e7 59 28 fe 1d c1 27  a2 ff a8 de 33 48 b3 c1  |..Y(...'....3H..|
+000002a0  85 6a 42 9b f9 7e 7e 31  c2 e5 bd 66 02 41 4b 49  |.jB..~~1...f.AKI|
+000002b0  c6 cd 02 e3 83 f7 03 50  18 6d b4 c9 51 02 c0 ab  |.......P.m..Q...|
+000002c0  87 bc e0 3e 4b 89 53 3a  e2 65 89 97 02 c1 87 f1  |...>K.S:.e......|
+000002d0  67 d0 f2 06 28 4e 51 4e  fd f0 01 be 41 3c 52 42  |g...(NQN....A<RB|
+000002e0  10 44 73 88 3e 44 24 bb  2e 77 01 77 6f a8 ac 14  |.Ds.>D$..w.wo...|
+000002f0  03 01 00 01 01 16 03 01  00 30 a3 da 45 22 96 83  |.........0..E"..|
+00000300  59 90 e9 6b ec 3b 77 50  05 89 e6 0c 61 d1 1d 2b  |Y..k.;wP....a..+|
+00000310  da d4 49 bf b9 c6 dd ad  c3 9c 82 bd 53 62 e8 57  |..I.........Sb.W|
+00000320  a4 6a e7 9f b1 d5 39 77  88 6d                    |.j....9w.m|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 30 a4 45 dd 99 df  |..........0.E...|
+00000010  66 ae f5 c7 bd 1a eb 6a  ff ac a6 38 14 81 b5 07  |f......j...8....|
+00000020  86 24 80 f1 09 59 ad 33  3d 43 ed 9e 43 b1 1e 9f  |.$...Y.3=C..C...|
+00000030  bd 8c b3 e0 41 83 a1 34  91 c5 a1                 |....A..4...|
+>>> Flow 5 (client to server)
+00000000  17 03 01 00 20 ae e3 ae  7f 2d e3 a2 f7 1b 4e 69  |.... ....-....Ni|
+00000010  cb 18 c6 68 42 f8 de 61  92 4c fa d6 19 7c 8c 09  |...hB..a.L...|..|
+00000020  82 e2 f2 32 19 17 03 01  00 20 2a 77 65 1f c1 fd  |...2..... *we...|
+00000030  5e 37 b7 15 f6 1f 4c 7f  5f 89 52 b4 32 27 4d 17  |^7....L._.R.2'M.|
+00000040  33 c6 e8 50 ac 70 c8 b9  2d 0a 15 03 01 00 20 e0  |3..P.p..-..... .|
+00000050  cb ce 07 80 55 a0 46 ca  a7 25 4c 5f 9d 7c 73 37  |....U.F..%L_.|s7|
+00000060  de 72 6d 36 a8 e4 be fd  2a e7 f8 8d 14 80 b7     |.rm6....*......|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
new file mode 100644
index 0000000..c0be824
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
@@ -0,0 +1,125 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 51 02 00 00  4d 03 01 53 04 f1 02 ed  |....Q...M..S....|
+00000010  86 9c 56 84 5a d3 7d d7  f3 4e 6f 2c 69 0d f0 59  |..V.Z.}..No,i..Y|
+00000020  a5 d1 de 2d 03 2f dd 63  c3 ab fa 20 30 d6 5a 24  |...-./.c... 0.Z$|
+00000030  5c 31 67 36 8d 4c 43 e1  64 c4 8a 2c a5 fd 39 92  |\1g6.LC.d..,..9.|
+00000040  c5 6f 58 47 a3 fe 63 14  98 92 11 90 00 05 00 00  |.oXG..c.........|
+00000050  05 ff 01 00 01 00 16 03  01 02 be 0b 00 02 ba 00  |................|
+00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 01 00 0e 0d 00  |n8P)l...........|
+00000320  00 06 03 01 02 40 00 00  0e 00 00 00              |.....@......|
+>>> Flow 3 (client to server)
+00000000  16 03 01 02 0a 0b 00 02  06 00 02 03 00 02 00 30  |...............0|
+00000010  82 01 fc 30 82 01 5e 02  09 00 9a 30 84 6c 26 35  |...0..^....0.l&5|
+00000020  d9 17 30 09 06 07 2a 86  48 ce 3d 04 01 30 45 31  |..0...*.H.=..0E1|
+00000030  0b 30 09 06 03 55 04 06  13 02 41 55 31 13 30 11  |.0...U....AU1.0.|
+00000040  06 03 55 04 08 13 0a 53  6f 6d 65 2d 53 74 61 74  |..U....Some-Stat|
+00000050  65 31 21 30 1f 06 03 55  04 0a 13 18 49 6e 74 65  |e1!0...U....Inte|
+00000060  72 6e 65 74 20 57 69 64  67 69 74 73 20 50 74 79  |rnet Widgits Pty|
+00000070  20 4c 74 64 30 1e 17 0d  31 32 31 31 31 34 31 33  | Ltd0...12111413|
+00000080  32 35 35 33 5a 17 0d 32  32 31 31 31 32 31 33 32  |2553Z..221112132|
+00000090  35 35 33 5a 30 41 31 0b  30 09 06 03 55 04 06 13  |553Z0A1.0...U...|
+000000a0  02 41 55 31 0c 30 0a 06  03 55 04 08 13 03 4e 53  |.AU1.0...U....NS|
+000000b0  57 31 10 30 0e 06 03 55  04 07 13 07 50 79 72 6d  |W1.0...U....Pyrm|
+000000c0  6f 6e 74 31 12 30 10 06  03 55 04 03 13 09 4a 6f  |ont1.0...U....Jo|
+000000d0  65 6c 20 53 69 6e 67 30  81 9b 30 10 06 07 2a 86  |el Sing0..0...*.|
+000000e0  48 ce 3d 02 01 06 05 2b  81 04 00 23 03 81 86 00  |H.=....+...#....|
+000000f0  04 00 95 8c 91 75 14 c0  5e c4 57 b4 d4 c3 6f 8d  |.....u..^.W...o.|
+00000100  ae 68 1e dd 6f ce 86 e1  7e 6e b2 48 3e 81 e5 4e  |.h..o...~n.H>..N|
+00000110  e2 c6 88 4b 64 dc f5 30  bb d3 ff 65 cc 5b f4 dd  |...Kd..0...e.[..|
+00000120  b5 6a 3e 3e d0 1d de 47  c3 76 ad 19 f6 45 2c 8c  |.j>>...G.v...E,.|
+00000130  bc d8 1d 01 4c 1f 70 90  46 76 48 8b 8f 83 cc 4a  |....L.p.FvH....J|
+00000140  5c 8f 40 76 da e0 89 ec  1d 2b c4 4e 30 76 28 41  |\.@v.....+.N0v(A|
+00000150  b2 62 a8 fb 5b f1 f9 4e  7a 8d bd 09 b8 ae ea 8b  |.b..[..Nz.......|
+00000160  18 27 4f 2e 70 fe 13 96  ba c3 d3 40 16 cd 65 4e  |.'O.p......@..eN|
+00000170  ac 11 1e e6 f1 30 09 06  07 2a 86 48 ce 3d 04 01  |.....0...*.H.=..|
+00000180  03 81 8c 00 30 81 88 02  42 00 e0 14 c4 60 60 0b  |....0...B....``.|
+00000190  72 68 b0 32 5d 61 4a 02  74 5c c2 81 b9 16 a8 3f  |rh.2]aJ.t\.....?|
+000001a0  29 c8 36 c7 81 ff 6c b6  5b d9 70 f1 38 3b 50 48  |).6...l.[.p.8;PH|
+000001b0  28 94 cb 09 1a 52 f1 5d  ee 8d f2 b9 f0 f0 da d9  |(....R.]........|
+000001c0  15 3a f9 bd 03 7a 87 a2  23 35 ec 02 42 01 a3 d4  |.:...z..#5..B...|
+000001d0  8a 78 35 1c 4a 9a 23 d2  0a be 2b 10 31 9d 9c 5f  |.x5.J.#...+.1.._|
+000001e0  be e8 91 b3 da 1a f5 5d  a3 23 f5 26 8b 45 70 8d  |.......].#.&.Ep.|
+000001f0  65 62 9b 7e 01 99 3d 18  f6 10 9a 38 61 9b 2e 57  |eb.~..=....8a..W|
+00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
+00000210  03 01 00 86 10 00 00 82  00 80 6d 51 f3 7f f9 3e  |..........mQ...>|
+00000220  fb 75 82 41 36 83 e8 6a  ee 2a 2e 25 90 67 4c 8e  |.u.A6..j.*.%.gL.|
+00000230  62 2f 30 81 17 e0 85 09  0c 2b b7 23 d7 b0 e2 1d  |b/0......+.#....|
+00000240  f7 3b d7 f5 a1 27 b6 ee  24 b6 1b cc 5b ea 66 0d  |.;...'..$...[.f.|
+00000250  6a f4 e5 85 f9 da 43 b4  0e 86 85 e1 f5 aa be c8  |j.....C.........|
+00000260  ce 39 4c 9c 86 00 08 c2  4b e2 c6 ec 2f f7 ce e6  |.9L.....K.../...|
+00000270  bd 77 82 6f 23 b6 e0 bd  a2 92 b7 3a ac e8 56 f1  |.w.o#......:..V.|
+00000280  af 54 5e 46 87 e9 3b 33  e7 b8 28 b7 d6 c8 90 35  |.T^F..;3..(....5|
+00000290  d4 1c 43 d1 30 6f 55 4e  0a 70 16 03 01 00 90 0f  |..C.0oUN.p......|
+000002a0  00 00 8c 00 8a 30 81 87  02 42 00 c6 85 8e 06 b7  |.....0...B......|
+000002b0  04 04 e9 cd 9e 3e cb 66  23 95 b4 42 9c 64 81 39  |.....>.f#..B.d.9|
+000002c0  05 3f b5 21 f8 28 af 60  6b 4d 3d ba a1 4b 5e 77  |.?.!.(.`kM=..K^w|
+000002d0  ef e7 59 28 fe 1d c1 27  a2 ff a8 de 33 48 b3 c1  |..Y(...'....3H..|
+000002e0  85 6a 42 9b f9 7e 7e 31  c2 e5 bd 66 02 41 4b 49  |.jB..~~1...f.AKI|
+000002f0  c6 cd 02 e3 83 f7 03 50  18 6d b4 c9 51 02 c0 ab  |.......P.m..Q...|
+00000300  87 bc e0 3e 4b 89 53 3a  e2 65 89 97 02 c1 87 f1  |...>K.S:.e......|
+00000310  67 d0 f2 06 28 4e 51 4e  fd f0 01 47 e7 c9 d9 23  |g...(NQN...G...#|
+00000320  21 6b 87 d2 55 e3 c9 f7  eb 86 d5 1e 50 df d5 14  |!k..U.......P...|
+00000330  03 01 00 01 01 16 03 01  00 24 95 62 42 be 90 39  |.........$.bB..9|
+00000340  68 ae f5 77 47 21 14 b9  ac ee 81 2d e3 9e c7 34  |h..wG!.....-...4|
+00000350  3a 00 5c c9 12 1d c0 5a  7c e7 ef e0 cd fd        |:.\....Z|.....|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 24 ea 98 c0 fb 86  |..........$.....|
+00000010  87 7a 2e e1 c7 68 61 3e  5b cc da 1f d6 7b ab 5a  |.z...ha>[....{.Z|
+00000020  a0 ae a2 cf d0 54 44 19  12 db 75 2b 8c 73 8c     |.....TD...u+.s.|
+>>> Flow 5 (client to server)
+00000000  17 03 01 00 1a f3 28 77  31 33 4c b3 7c 4b 75 61  |......(w13L.|Kua|
+00000010  38 69 6b ae c9 36 ab 2e  56 16 29 6a 9a 00 2f 15  |8ik..6..V.)j../.|
+00000020  03 01 00 16 6b ed 68 18  ed ff 44 39 9b 4a e4 a2  |....k.h...D9.J..|
+00000030  cd 79 ef 2a 3e 5a 4d b1  5d 56                    |.y.*>ZM.]V|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
new file mode 100644
index 0000000..3e6dbc2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
@@ -0,0 +1,128 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 59 02 00 00  55 03 01 53 04 f1 02 4f  |....Y...U..S...O|
+00000010  73 06 2d 72 41 36 a1 b2  d3 50 97 55 8c c5 f1 43  |s.-rA6...P.U...C|
+00000020  37 1f 1a 2a fe 51 70 0b  2f 25 9e 20 50 61 86 80  |7..*.Qp./%. Pa..|
+00000030  9a 9c 6d 6f c9 ea 5c ce  0c b7 7c ce e3 be d0 e5  |..mo..\...|.....|
+00000040  be d0 c4 80 78 c3 c7 17  0c 2d 8e c8 c0 09 00 00  |....x....-......|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  01 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
+00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
+00000080  30 09 06 07 2a 86 48 ce  3d 04 01 30 45 31 0b 30  |0...*.H.=..0E1.0|
+00000090  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+000000a0  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+000000b0  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+000000c0  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+000000d0  74 64 30 1e 17 0d 31 32  31 31 32 32 31 35 30 36  |td0...1211221506|
+000000e0  33 32 5a 17 0d 32 32 31  31 32 30 31 35 30 36 33  |32Z..22112015063|
+000000f0  32 5a 30 45 31 0b 30 09  06 03 55 04 06 13 02 41  |2Z0E1.0...U....A|
+00000100  55 31 13 30 11 06 03 55  04 08 13 0a 53 6f 6d 65  |U1.0...U....Some|
+00000110  2d 53 74 61 74 65 31 21  30 1f 06 03 55 04 0a 13  |-State1!0...U...|
+00000120  18 49 6e 74 65 72 6e 65  74 20 57 69 64 67 69 74  |.Internet Widgit|
+00000130  73 20 50 74 79 20 4c 74  64 30 81 9b 30 10 06 07  |s Pty Ltd0..0...|
+00000140  2a 86 48 ce 3d 02 01 06  05 2b 81 04 00 23 03 81  |*.H.=....+...#..|
+00000150  86 00 04 00 c4 a1 ed be  98 f9 0b 48 73 36 7e c3  |...........Hs6~.|
+00000160  16 56 11 22 f2 3d 53 c3  3b 4d 21 3d cd 6b 75 e6  |.V.".=S.;M!=.ku.|
+00000170  f6 b0 dc 9a df 26 c1 bc  b2 87 f0 72 32 7c b3 64  |.....&.....r2|.d|
+00000180  2f 1c 90 bc ea 68 23 10  7e fe e3 25 c0 48 3a 69  |/....h#.~..%.H:i|
+00000190  e0 28 6d d3 37 00 ef 04  62 dd 0d a0 9c 70 62 83  |.(m.7...b....pb.|
+000001a0  d8 81 d3 64 31 aa 9e 97  31 bd 96 b0 68 c0 9b 23  |...d1...1...h..#|
+000001b0  de 76 64 3f 1a 5c 7f e9  12 0e 58 58 b6 5f 70 dd  |.vd?.\....XX._p.|
+000001c0  9b d8 ea d5 d7 f5 d5 cc  b9 b6 9f 30 66 5b 66 9a  |...........0f[f.|
+000001d0  20 e2 27 e5 bf fe 3b 30  09 06 07 2a 86 48 ce 3d  | .'...;0...*.H.=|
+000001e0  04 01 03 81 8c 00 30 81  88 02 42 01 88 a2 4f eb  |......0...B...O.|
+000001f0  e2 45 c5 48 7d 1b ac f5  ed 98 9d ae 47 70 c0 5e  |.E.H}.......Gp.^|
+00000200  1b b6 2f bd f1 b6 4d b7  61 40 d3 11 a2 ce ee 0b  |../...M.a@......|
+00000210  7e 92 7e ff 76 9d c3 3b  7e a5 3f ce fa 10 e2 59  |~.~.v..;~.?....Y|
+00000220  ec 47 2d 7c ac da 4e 97  0e 15 a0 6f d0 02 42 01  |.G-|..N....o..B.|
+00000230  4d fc be 67 13 9c 2d 05  0e bd 3f a3 8c 25 c1 33  |M..g..-...?..%.3|
+00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
+00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
+00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
+00000270  2a 16 03 01 00 d6 0c 00  00 d2 03 00 17 41 04 b1  |*............A..|
+00000280  0f 0f 4a 18 ed 25 32 b3  a3 19 ed 4b 61 b6 eb e4  |..J..%2....Ka...|
+00000290  d3 f7 77 13 ac 9f 60 c7  8d 6d cb f1 ee 99 1a 71  |..w...`..m.....q|
+000002a0  68 aa d3 a7 70 7f 38 d0  f6 23 ab 9a f6 dd 19 4f  |h...p.8..#.....O|
+000002b0  ce 10 ef d5 cf 64 85 2f  75 f6 20 06 4b f0 b9 00  |.....d./u. .K...|
+000002c0  8b 30 81 88 02 42 01 00  b9 6b 80 91 59 0a 48 3f  |.0...B...k..Y.H?|
+000002d0  72 16 96 8f 21 2c 28 e4  6d 03 74 66 35 16 7d ec  |r...!,(.m.tf5.}.|
+000002e0  c7 08 9b 52 b5 05 d9 38  d8 b7 51 42 a7 4a 9f 9b  |...R...8..QB.J..|
+000002f0  1a 37 14 de c5 f5 16 96  83 81 58 d3 a6 1e ce 8a  |.7........X.....|
+00000300  bc 19 47 30 fe c5 85 55  02 42 01 4f 61 59 68 85  |..G0...U.B.OaYh.|
+00000310  c7 64 23 22 f6 83 53 cc  58 38 25 b5 ce 74 c1 68  |.d#"..S.X8%..t.h|
+00000320  9f 32 72 33 ea c9 62 e0  26 63 92 e3 5f 34 10 0b  |.2r3..b.&c.._4..|
+00000330  3c d5 83 fe 9f 67 69 ef  33 6b 19 c1 ec d6 6c 35  |<....gi.3k....l5|
+00000340  89 33 17 d3 9d 93 e2 e5  6e 89 9a a1 16 03 01 00  |.3......n.......|
+00000350  0e 0d 00 00 06 03 01 02  40 00 00 0e 00 00 00     |........@......|
+>>> Flow 3 (client to server)
+00000000  16 03 01 01 fb 0b 00 01  f7 00 01 f4 00 01 f1 30  |...............0|
+00000010  82 01 ed 30 82 01 58 a0  03 02 01 02 02 01 00 30  |...0..X........0|
+00000020  0b 06 09 2a 86 48 86 f7  0d 01 01 05 30 26 31 10  |...*.H......0&1.|
+00000030  30 0e 06 03 55 04 0a 13  07 41 63 6d 65 20 43 6f  |0...U....Acme Co|
+00000040  31 12 30 10 06 03 55 04  03 13 09 31 32 37 2e 30  |1.0...U....127.0|
+00000050  2e 30 2e 31 30 1e 17 0d  31 31 31 32 30 38 30 37  |.0.10...11120807|
+00000060  35 35 31 32 5a 17 0d 31  32 31 32 30 37 30 38 30  |5512Z..121207080|
+00000070  30 31 32 5a 30 26 31 10  30 0e 06 03 55 04 0a 13  |012Z0&1.0...U...|
+00000080  07 41 63 6d 65 20 43 6f  31 12 30 10 06 03 55 04  |.Acme Co1.0...U.|
+00000090  03 13 09 31 32 37 2e 30  2e 30 2e 31 30 81 9c 30  |...127.0.0.10..0|
+000000a0  0b 06 09 2a 86 48 86 f7  0d 01 01 01 03 81 8c 00  |...*.H..........|
+000000b0  30 81 88 02 81 80 4e d0  7b 31 e3 82 64 d9 59 c0  |0.....N.{1..d.Y.|
+000000c0  c2 87 a4 5e 1e 8b 73 33  c7 63 53 df 66 92 06 84  |...^..s3.cS.f...|
+000000d0  f6 64 d5 8f e4 36 a7 1d  2b e8 b3 20 36 45 23 b5  |.d...6..+.. 6E#.|
+000000e0  e3 95 ae ed e0 f5 20 9c  8d 95 df 7f 5a 12 ef 87  |...... .....Z...|
+000000f0  e4 5b 68 e4 e9 0e 74 ec  04 8a 7f de 93 27 c4 01  |.[h...t......'..|
+00000100  19 7a bd f2 dc 3d 14 ab  d0 54 ca 21 0c d0 4d 6e  |.z...=...T.!..Mn|
+00000110  87 2e 5c c5 d2 bb 4d 4b  4f ce b6 2c f7 7e 88 ec  |..\...MKO..,.~..|
+00000120  7c d7 02 91 74 a6 1e 0c  1a da e3 4a 5a 2e de 13  ||...t......JZ...|
+00000130  9c 4c 40 88 59 93 02 03  01 00 01 a3 32 30 30 30  |.L@.Y.......2000|
+00000140  0e 06 03 55 1d 0f 01 01  ff 04 04 03 02 00 a0 30  |...U...........0|
+00000150  0d 06 03 55 1d 0e 04 06  04 04 01 02 03 04 30 0f  |...U..........0.|
+00000160  06 03 55 1d 23 04 08 30  06 80 04 01 02 03 04 30  |..U.#..0.......0|
+00000170  0b 06 09 2a 86 48 86 f7  0d 01 01 05 03 81 81 00  |...*.H..........|
+00000180  36 1f b3 7a 0c 75 c9 6e  37 46 61 2b d5 bd c0 a7  |6..z.u.n7Fa+....|
+00000190  4b cc 46 9a 81 58 7c 85  79 29 c8 c8 c6 67 dd 32  |K.F..X|.y)...g.2|
+000001a0  56 45 2b 75 b6 e9 24 a9  50 9a be 1f 5a fa 1a 15  |VE+u..$.P...Z...|
+000001b0  d9 cc 55 95 72 16 83 b9  c2 b6 8f fd 88 8c 38 84  |..U.r.........8.|
+000001c0  1d ab 5d 92 31 13 4f fd  83 3b c6 9d f1 11 62 b6  |..].1.O..;....b.|
+000001d0  8b ec ab 67 be c8 64 b0  11 50 46 58 17 6b 99 1c  |...g..d..PFX.k..|
+000001e0  d3 1d fc 06 f1 0e e5 96  a8 0c f9 78 20 b7 44 18  |...........x .D.|
+000001f0  51 8d 10 7e 4f 94 67 df  a3 4e 70 73 8e 90 91 85  |Q..~O.g..Nps....|
+00000200  16 03 01 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
+00000210  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
+00000220  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
+00000230  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
+00000240  a6 b5 68 1a 41 03 56 6b  dc 5a 89 16 03 01 00 86  |..h.A.Vk.Z......|
+00000250  0f 00 00 82 00 80 20 2c  5a 08 3a 00 33 50 19 b2  |...... ,Z.:.3P..|
+00000260  0f ba 6c 76 7f 5c 92 e2  78 55 3e 32 32 bb 33 bc  |..lv.\..xU>22.3.|
+00000270  ab a9 34 e0 83 cf 82 cd  9e 6b 3f 9d e6 49 61 29  |..4......k?..Ia)|
+00000280  8b b4 ed e8 12 cd a9 52  86 11 48 64 08 61 72 8d  |.......R..Hd.ar.|
+00000290  d6 6a ac 42 cc e4 07 5f  08 56 9f 2f c5 35 d3 9b  |.j.B..._.V./.5..|
+000002a0  e9 0d 91 82 c0 e9 bb 9f  a9 8f df 96 85 08 9a 69  |...............i|
+000002b0  a4 93 b3 72 37 ba f9 b1  a4 0b b0 9f 43 6a 15 ec  |...r7.......Cj..|
+000002c0  79 b8 fd 9c 1f 5f 0d 2c  56 33 c7 15 d5 4a b7 82  |y...._.,V3...J..|
+000002d0  ea 44 80 20 c5 80 14 03  01 00 01 01 16 03 01 00  |.D. ............|
+000002e0  30 c9 c0 7c d7 57 d3 00  ab 87 eb 78 56 6b a1 69  |0..|.W.....xVk.i|
+000002f0  1d fa ec ae 38 f3 ef 5d  49 19 0d 4b f0 73 63 af  |....8..]I..K.sc.|
+00000300  89 b6 cb 76 cf fb b9 c1  99 98 06 0a 54 67 a0 6e  |...v........Tg.n|
+00000310  e7                                                |.|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 30 20 db fd ed ed  |..........0 ....|
+00000010  7c d5 bf 8f 06 3b 86 1b  c1 60 7d a4 74 e9 a6 c9  ||....;...`}.t...|
+00000020  f5 7c c7 f4 65 91 06 d5  53 88 d7 57 a4 22 b6 1f  |.|..e...S..W."..|
+00000030  f1 02 e9 79 36 e6 a1 22  51 3a 4c                 |...y6.."Q:L|
+>>> Flow 5 (client to server)
+00000000  17 03 01 00 20 00 66 51  6a 14 ca ea e2 21 48 74  |.... .fQj....!Ht|
+00000010  c4 c1 6e b9 8b 23 af 7c  33 c9 00 f8 0b ec ab 35  |..n..#.|3......5|
+00000020  e7 42 0a d1 ae 17 03 01  00 20 00 1c 6d 60 75 5d  |.B....... ..m`u]|
+00000030  b3 fb 40 2e e0 b7 0d 48  f4 87 ac d4 bf ea 01 0d  |..@....H........|
+00000040  fe 10 0d 05 04 43 6b 19  ed f2 15 03 01 00 20 f8  |.....Ck....... .|
+00000050  03 ac 62 4b 1f db 2e d2  4e 00 c3 a4 57 3c 0a 62  |..bK....N...W<.b|
+00000060  05 a0 ef bd 2b 9b 9a 63  27 72 d7 d8 f1 8d 84     |....+..c'r.....|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
new file mode 100644
index 0000000..94e6860
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
@@ -0,0 +1,124 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 51 02 00 00  4d 03 01 53 04 f1 02 73  |....Q...M..S...s|
+00000010  ee 5f 70 a4 aa 0d be d7  46 a3 25 3f e3 5d ef 7b  |._p.....F.%?.].{|
+00000020  73 49 7c b6 82 4d 99 2f  31 fc 8b 20 2d a3 33 7c  |sI|..M./1.. -.3||
+00000030  a5 c3 85 86 ba 61 4d 05  b0 5e d3 5e 88 6e c3 4b  |.....aM..^.^.n.K|
+00000040  95 d3 e9 67 f1 96 24 58  7a 6f e6 c5 00 05 00 00  |...g..$Xzo......|
+00000050  05 ff 01 00 01 00 16 03  01 02 be 0b 00 02 ba 00  |................|
+00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 01 00 0e 0d 00  |n8P)l...........|
+00000320  00 06 03 01 02 40 00 00  0e 00 00 00              |.....@......|
+>>> Flow 3 (client to server)
+00000000  16 03 01 01 fb 0b 00 01  f7 00 01 f4 00 01 f1 30  |...............0|
+00000010  82 01 ed 30 82 01 58 a0  03 02 01 02 02 01 00 30  |...0..X........0|
+00000020  0b 06 09 2a 86 48 86 f7  0d 01 01 05 30 26 31 10  |...*.H......0&1.|
+00000030  30 0e 06 03 55 04 0a 13  07 41 63 6d 65 20 43 6f  |0...U....Acme Co|
+00000040  31 12 30 10 06 03 55 04  03 13 09 31 32 37 2e 30  |1.0...U....127.0|
+00000050  2e 30 2e 31 30 1e 17 0d  31 31 31 32 30 38 30 37  |.0.10...11120807|
+00000060  35 35 31 32 5a 17 0d 31  32 31 32 30 37 30 38 30  |5512Z..121207080|
+00000070  30 31 32 5a 30 26 31 10  30 0e 06 03 55 04 0a 13  |012Z0&1.0...U...|
+00000080  07 41 63 6d 65 20 43 6f  31 12 30 10 06 03 55 04  |.Acme Co1.0...U.|
+00000090  03 13 09 31 32 37 2e 30  2e 30 2e 31 30 81 9c 30  |...127.0.0.10..0|
+000000a0  0b 06 09 2a 86 48 86 f7  0d 01 01 01 03 81 8c 00  |...*.H..........|
+000000b0  30 81 88 02 81 80 4e d0  7b 31 e3 82 64 d9 59 c0  |0.....N.{1..d.Y.|
+000000c0  c2 87 a4 5e 1e 8b 73 33  c7 63 53 df 66 92 06 84  |...^..s3.cS.f...|
+000000d0  f6 64 d5 8f e4 36 a7 1d  2b e8 b3 20 36 45 23 b5  |.d...6..+.. 6E#.|
+000000e0  e3 95 ae ed e0 f5 20 9c  8d 95 df 7f 5a 12 ef 87  |...... .....Z...|
+000000f0  e4 5b 68 e4 e9 0e 74 ec  04 8a 7f de 93 27 c4 01  |.[h...t......'..|
+00000100  19 7a bd f2 dc 3d 14 ab  d0 54 ca 21 0c d0 4d 6e  |.z...=...T.!..Mn|
+00000110  87 2e 5c c5 d2 bb 4d 4b  4f ce b6 2c f7 7e 88 ec  |..\...MKO..,.~..|
+00000120  7c d7 02 91 74 a6 1e 0c  1a da e3 4a 5a 2e de 13  ||...t......JZ...|
+00000130  9c 4c 40 88 59 93 02 03  01 00 01 a3 32 30 30 30  |.L@.Y.......2000|
+00000140  0e 06 03 55 1d 0f 01 01  ff 04 04 03 02 00 a0 30  |...U...........0|
+00000150  0d 06 03 55 1d 0e 04 06  04 04 01 02 03 04 30 0f  |...U..........0.|
+00000160  06 03 55 1d 23 04 08 30  06 80 04 01 02 03 04 30  |..U.#..0.......0|
+00000170  0b 06 09 2a 86 48 86 f7  0d 01 01 05 03 81 81 00  |...*.H..........|
+00000180  36 1f b3 7a 0c 75 c9 6e  37 46 61 2b d5 bd c0 a7  |6..z.u.n7Fa+....|
+00000190  4b cc 46 9a 81 58 7c 85  79 29 c8 c8 c6 67 dd 32  |K.F..X|.y)...g.2|
+000001a0  56 45 2b 75 b6 e9 24 a9  50 9a be 1f 5a fa 1a 15  |VE+u..$.P...Z...|
+000001b0  d9 cc 55 95 72 16 83 b9  c2 b6 8f fd 88 8c 38 84  |..U.r.........8.|
+000001c0  1d ab 5d 92 31 13 4f fd  83 3b c6 9d f1 11 62 b6  |..].1.O..;....b.|
+000001d0  8b ec ab 67 be c8 64 b0  11 50 46 58 17 6b 99 1c  |...g..d..PFX.k..|
+000001e0  d3 1d fc 06 f1 0e e5 96  a8 0c f9 78 20 b7 44 18  |...........x .D.|
+000001f0  51 8d 10 7e 4f 94 67 df  a3 4e 70 73 8e 90 91 85  |Q..~O.g..Nps....|
+00000200  16 03 01 00 86 10 00 00  82 00 80 6d 51 f3 7f f9  |...........mQ...|
+00000210  3e fb 75 82 41 36 83 e8  6a ee 2a 2e 25 90 67 4c  |>.u.A6..j.*.%.gL|
+00000220  8e 62 2f 30 81 17 e0 85  09 0c 2b b7 23 d7 b0 e2  |.b/0......+.#...|
+00000230  1d f7 3b d7 f5 a1 27 b6  ee 24 b6 1b cc 5b ea 66  |..;...'..$...[.f|
+00000240  0d 6a f4 e5 85 f9 da 43  b4 0e 86 85 e1 f5 aa be  |.j.....C........|
+00000250  c8 ce 39 4c 9c 86 00 08  c2 4b e2 c6 ec 2f f7 ce  |..9L.....K.../..|
+00000260  e6 bd 77 82 6f 23 b6 e0  bd a2 92 b7 3a ac e8 56  |..w.o#......:..V|
+00000270  f1 af 54 5e 46 87 e9 3b  33 e7 b8 28 b7 d6 c8 90  |..T^F..;3..(....|
+00000280  35 d4 1c 43 d1 30 6f 55  4e 0a 70 16 03 01 00 86  |5..C.0oUN.p.....|
+00000290  0f 00 00 82 00 80 0f 4c  d2 b2 f0 94 6d 61 d1 2c  |.......L....ma.,|
+000002a0  db 6f 79 03 bd 40 b2 d2  1d 61 ef 83 1b 4a 0c 7b  |.oy..@...a...J.{|
+000002b0  c5 73 1e 1a 81 e7 67 0a  d6 aa 2d 04 04 cc 0e 4b  |.s....g...-....K|
+000002c0  2e da 96 7f 15 6c 05 ee  c4 53 7e 33 89 28 7d db  |.....l...S~3.(}.|
+000002d0  a1 77 43 ba a3 51 a9 1c  b9 f5 ec 9a 8d eb 2c 46  |.wC..Q........,F|
+000002e0  5c 33 59 6b 16 af de f4  9b 80 76 a3 22 30 5d bb  |\3Yk......v."0].|
+000002f0  02 b9 77 96 8a db 36 9f  54 95 00 d8 58 e1 aa 04  |..w...6.T...X...|
+00000300  98 c9 0c 32 ae 62 81 12  0c f6 1b 76 c6 58 a7 8c  |...2.b.....v.X..|
+00000310  0e d8 b7 8e ed 0f 14 03  01 00 01 01 16 03 01 00  |................|
+00000320  24 1d c0 20 02 2d da 69  54 29 8c ff af 5c 56 a8  |$.. .-.iT)...\V.|
+00000330  eb d0 09 95 29 8f 52 8c  e2 7b 9f 36 3e 47 a0 33  |....).R..{.6>G.3|
+00000340  2e 63 a2 24 93                                    |.c.$.|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 24 99 e8 fb 65 f4  |..........$...e.|
+00000010  95 ae 8b 71 cc 5d a4 95  a7 27 98 fd 16 3f 7a 1a  |...q.]...'...?z.|
+00000020  b6 bd bf 0a 58 72 77 97  1f 8e b1 dd 4b 12 12     |....Xrw.....K..|
+>>> Flow 5 (client to server)
+00000000  17 03 01 00 1a 42 70 c0  89 78 12 5c 91 7e 88 2d  |.....Bp..x.\.~.-|
+00000010  2f 8f be f2 f2 12 9d 81  ae 78 08 38 5e 6d 1b 15  |/........x.8^m..|
+00000020  03 01 00 16 1a 64 b1 6f  8a ff d3 63 6a c7 b8 95  |.....d.o...cj...|
+00000030  3d b0 87 bc 62 e9 88 5b  26 bd                    |=...b..[&.|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
new file mode 100644
index 0000000..30c4c6b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
@@ -0,0 +1,87 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 59 02 00 00  55 03 01 53 04 f1 02 b2  |....Y...U..S....|
+00000010  e0 f6 f6 b5 c9 5b 28 d0  5d 58 1b 6f 4e 2b 9d 05  |.....[(.]X.oN+..|
+00000020  2a b9 b4 da 45 cf f3 10  b2 23 44 20 f8 4d 59 05  |*...E....#D .MY.|
+00000030  ad 27 f2 a0 ee 7f ec cc  20 dc e7 a2 1b 07 b3 a5  |.'...... .......|
+00000040  37 7e 61 3d d6 5c 03 cf  cc f5 9b ca c0 09 00 00  |7~a=.\..........|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  01 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
+00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
+00000080  30 09 06 07 2a 86 48 ce  3d 04 01 30 45 31 0b 30  |0...*.H.=..0E1.0|
+00000090  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+000000a0  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+000000b0  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+000000c0  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+000000d0  74 64 30 1e 17 0d 31 32  31 31 32 32 31 35 30 36  |td0...1211221506|
+000000e0  33 32 5a 17 0d 32 32 31  31 32 30 31 35 30 36 33  |32Z..22112015063|
+000000f0  32 5a 30 45 31 0b 30 09  06 03 55 04 06 13 02 41  |2Z0E1.0...U....A|
+00000100  55 31 13 30 11 06 03 55  04 08 13 0a 53 6f 6d 65  |U1.0...U....Some|
+00000110  2d 53 74 61 74 65 31 21  30 1f 06 03 55 04 0a 13  |-State1!0...U...|
+00000120  18 49 6e 74 65 72 6e 65  74 20 57 69 64 67 69 74  |.Internet Widgit|
+00000130  73 20 50 74 79 20 4c 74  64 30 81 9b 30 10 06 07  |s Pty Ltd0..0...|
+00000140  2a 86 48 ce 3d 02 01 06  05 2b 81 04 00 23 03 81  |*.H.=....+...#..|
+00000150  86 00 04 00 c4 a1 ed be  98 f9 0b 48 73 36 7e c3  |...........Hs6~.|
+00000160  16 56 11 22 f2 3d 53 c3  3b 4d 21 3d cd 6b 75 e6  |.V.".=S.;M!=.ku.|
+00000170  f6 b0 dc 9a df 26 c1 bc  b2 87 f0 72 32 7c b3 64  |.....&.....r2|.d|
+00000180  2f 1c 90 bc ea 68 23 10  7e fe e3 25 c0 48 3a 69  |/....h#.~..%.H:i|
+00000190  e0 28 6d d3 37 00 ef 04  62 dd 0d a0 9c 70 62 83  |.(m.7...b....pb.|
+000001a0  d8 81 d3 64 31 aa 9e 97  31 bd 96 b0 68 c0 9b 23  |...d1...1...h..#|
+000001b0  de 76 64 3f 1a 5c 7f e9  12 0e 58 58 b6 5f 70 dd  |.vd?.\....XX._p.|
+000001c0  9b d8 ea d5 d7 f5 d5 cc  b9 b6 9f 30 66 5b 66 9a  |...........0f[f.|
+000001d0  20 e2 27 e5 bf fe 3b 30  09 06 07 2a 86 48 ce 3d  | .'...;0...*.H.=|
+000001e0  04 01 03 81 8c 00 30 81  88 02 42 01 88 a2 4f eb  |......0...B...O.|
+000001f0  e2 45 c5 48 7d 1b ac f5  ed 98 9d ae 47 70 c0 5e  |.E.H}.......Gp.^|
+00000200  1b b6 2f bd f1 b6 4d b7  61 40 d3 11 a2 ce ee 0b  |../...M.a@......|
+00000210  7e 92 7e ff 76 9d c3 3b  7e a5 3f ce fa 10 e2 59  |~.~.v..;~.?....Y|
+00000220  ec 47 2d 7c ac da 4e 97  0e 15 a0 6f d0 02 42 01  |.G-|..N....o..B.|
+00000230  4d fc be 67 13 9c 2d 05  0e bd 3f a3 8c 25 c1 33  |M..g..-...?..%.3|
+00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
+00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
+00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
+00000270  2a 16 03 01 00 d5 0c 00  00 d1 03 00 17 41 04 da  |*............A..|
+00000280  5a fd 09 e5 d6 c0 70 41  5e 3a 87 eb df 0c ad 90  |Z.....pA^:......|
+00000290  22 8a 2f 90 81 0c 24 00  68 92 f3 d5 95 2f 93 43  |"./...$.h..../.C|
+000002a0  e9 58 2d 18 28 62 ee 33  5b 21 2e 49 87 21 4d 32  |.X-.(b.3[!.I.!M2|
+000002b0  32 19 b3 ba fe 2d 9a 85  12 0e a1 77 08 06 75 00  |2....-.....w..u.|
+000002c0  8a 30 81 87 02 42 01 91  14 fc 68 74 95 10 4b d4  |.0...B....ht..K.|
+000002d0  67 60 12 46 bb b0 f6 98  77 a3 41 b8 01 5c 49 54  |g`.F....w.A..\IT|
+000002e0  9e 3e 81 e7 97 a3 b9 73  6e 15 74 67 be e5 d9 eb  |.>.....sn.tg....|
+000002f0  8b 87 c5 22 ab ab 58 28  4f d1 b6 80 94 1b f5 f7  |..."..X(O.......|
+00000300  12 43 ef 0a c7 3e 1a 76  02 41 7a 00 49 cb 9f 3b  |.C...>.v.Az.I..;|
+00000310  91 6e 38 58 0a d3 d0 d1  ee 67 f0 b6 5d cd fa 23  |.n8X.....g..]..#|
+00000320  b6 98 43 af 9c 71 90 1e  1d 50 a2 6e 61 5b f2 92  |..C..q...P.na[..|
+00000330  b4 69 73 f2 3b 54 bf 1c  9d 05 19 97 e4 4e 41 9e  |.is.;T.......NA.|
+00000340  f2 9a 76 77 9a 86 43 1f  1f 30 a2 16 03 01 00 04  |..vw..C..0......|
+00000350  0e 00 00 00                                       |....|
+>>> Flow 3 (client to server)
+00000000  16 03 01 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
+00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
+00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
+00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
+00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 01 00 01  |..h.A.Vk.Z......|
+00000050  01 16 03 01 00 30 88 60  65 b2 d7 51 1f ad 96 56  |.....0.`e..Q...V|
+00000060  4e 0a 20 eb b5 b0 1a dd  4c f6 1a cf d4 5c 47 c4  |N. .....L....\G.|
+00000070  9c 7c a0 36 dd d1 1b 96  91 99 c0 a7 2d 9a 7c 42  |.|.6........-.|B|
+00000080  51 d1 de 87 2b a4                                 |Q...+.|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 30 86 6c b5 94 69  |..........0.l..i|
+00000010  2e e0 55 a2 4d a8 63 f2  5b 1f ae 34 21 c8 21 6a  |..U.M.c.[..4!.!j|
+00000020  00 b6 56 ed 4e 2a b0 ff  01 2f da ce a1 c0 41 03  |..V.N*.../....A.|
+00000030  a9 1b 6e 2e e1 88 50 ba  62 14 88                 |..n...P.b..|
+>>> Flow 5 (client to server)
+00000000  17 03 01 00 20 a6 63 0a  2f a5 dc e1 fb cb 7b 1f  |.... .c./.....{.|
+00000010  f2 da 74 c3 ff e9 f5 8b  9c 5f 0c d3 f7 1f 44 e6  |..t......_....D.|
+00000020  90 13 5c 48 50 17 03 01  00 20 c7 75 b5 ff bc 09  |..\HP.... .u....|
+00000030  34 f2 45 db 0d 22 08 8e  f1 35 cd b6 0f b0 eb 2a  |4.E.."...5.....*|
+00000040  b7 1a d0 8e 14 a4 54 84  f9 dc 15 03 01 00 20 e0  |......T....... .|
+00000050  36 3d aa b3 a9 b4 20 23  ca 9e 8c 5d fc a8 c8 b7  |6=.... #...]....|
+00000060  f5 c2 b6 d0 5a e2 ce a5  7b 68 a0 48 86 95 6a     |....Z...{h.H..j|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
new file mode 100644
index 0000000..868f0ce
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
@@ -0,0 +1,97 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 59 02 00 00  55 03 01 53 04 f1 02 21  |....Y...U..S...!|
+00000010  67 b5 2b 34 fb 62 d7 36  4f cf 68 2e 29 39 d0 28  |g.+4.b.6O.h.)9.(|
+00000020  3a 02 32 82 8f 95 de 62  d6 03 77 20 e6 98 56 cd  |:.2....b..w ..V.|
+00000030  96 24 d1 b9 4d eb 51 19  bb b7 71 f4 9c 29 32 d4  |.$..M.Q...q..)2.|
+00000040  e5 c6 0a 54 e0 4a 20 29  3e bd 06 0d c0 13 00 00  |...T.J )>.......|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  01 02 be 0b 00 02 ba 00  02 b7 00 02 b4 30 82 02  |.............0..|
+00000070  b0 30 82 02 19 a0 03 02  01 02 02 09 00 85 b0 bb  |.0..............|
+00000080  a4 8a 7f b8 ca 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
+00000090  01 05 05 00 30 45 31 0b  30 09 06 03 55 04 06 13  |....0E1.0...U...|
+000000a0  02 41 55 31 13 30 11 06  03 55 04 08 13 0a 53 6f  |.AU1.0...U....So|
+000000b0  6d 65 2d 53 74 61 74 65  31 21 30 1f 06 03 55 04  |me-State1!0...U.|
+000000c0  0a 13 18 49 6e 74 65 72  6e 65 74 20 57 69 64 67  |...Internet Widg|
+000000d0  69 74 73 20 50 74 79 20  4c 74 64 30 1e 17 0d 31  |its Pty Ltd0...1|
+000000e0  30 30 34 32 34 30 39 30  39 33 38 5a 17 0d 31 31  |00424090938Z..11|
+000000f0  30 34 32 34 30 39 30 39  33 38 5a 30 45 31 0b 30  |0424090938Z0E1.0|
+00000100  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+00000110  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+00000120  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+00000130  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+00000140  74 64 30 81 9f 30 0d 06  09 2a 86 48 86 f7 0d 01  |td0..0...*.H....|
+00000150  01 01 05 00 03 81 8d 00  30 81 89 02 81 81 00 bb  |........0.......|
+00000160  79 d6 f5 17 b5 e5 bf 46  10 d0 dc 69 be e6 2b 07  |y......F...i..+.|
+00000170  43 5a d0 03 2d 8a 7a 43  85 b7 14 52 e7 a5 65 4c  |CZ..-.zC...R..eL|
+00000180  2c 78 b8 23 8c b5 b4 82  e5 de 1f 95 3b 7e 62 a5  |,x.#........;~b.|
+00000190  2c a5 33 d6 fe 12 5c 7a  56 fc f5 06 bf fa 58 7b  |,.3...\zV.....X{|
+000001a0  26 3f b5 cd 04 d3 d0 c9  21 96 4a c7 f4 54 9f 5a  |&?......!.J..T.Z|
+000001b0  bf ef 42 71 00 fe 18 99  07 7f 7e 88 7d 7d f1 04  |..Bq......~.}}..|
+000001c0  39 c4 a2 2e db 51 c9 7c  e3 c0 4c 3b 32 66 01 cf  |9....Q.|..L;2f..|
+000001d0  af b1 1d b8 71 9a 1d db  db 89 6b ae da 2d 79 02  |....q.....k..-y.|
+000001e0  03 01 00 01 a3 81 a7 30  81 a4 30 1d 06 03 55 1d  |.......0..0...U.|
+000001f0  0e 04 16 04 14 b1 ad e2  85 5a cf cb 28 db 69 ce  |.........Z..(.i.|
+00000200  23 69 de d3 26 8e 18 88  39 30 75 06 03 55 1d 23  |#i..&...90u..U.#|
+00000210  04 6e 30 6c 80 14 b1 ad  e2 85 5a cf cb 28 db 69  |.n0l......Z..(.i|
+00000220  ce 23 69 de d3 26 8e 18  88 39 a1 49 a4 47 30 45  |.#i..&...9.I.G0E|
+00000230  31 0b 30 09 06 03 55 04  06 13 02 41 55 31 13 30  |1.0...U....AU1.0|
+00000240  11 06 03 55 04 08 13 0a  53 6f 6d 65 2d 53 74 61  |...U....Some-Sta|
+00000250  74 65 31 21 30 1f 06 03  55 04 0a 13 18 49 6e 74  |te1!0...U....Int|
+00000260  65 72 6e 65 74 20 57 69  64 67 69 74 73 20 50 74  |ernet Widgits Pt|
+00000270  79 20 4c 74 64 82 09 00  85 b0 bb a4 8a 7f b8 ca  |y Ltd...........|
+00000280  30 0c 06 03 55 1d 13 04  05 30 03 01 01 ff 30 0d  |0...U....0....0.|
+00000290  06 09 2a 86 48 86 f7 0d  01 01 05 05 00 03 81 81  |..*.H...........|
+000002a0  00 08 6c 45 24 c7 6b b1  59 ab 0c 52 cc f2 b0 14  |..lE$.k.Y..R....|
+000002b0  d7 87 9d 7a 64 75 b5 5a  95 66 e4 c5 2b 8e ae 12  |...zdu.Z.f..+...|
+000002c0  66 1f eb 4f 38 b3 6e 60  d3 92 fd f7 41 08 b5 25  |f..O8.n`....A..%|
+000002d0  13 b1 18 7a 24 fb 30 1d  ba ed 98 b9 17 ec e7 d7  |...z$.0.........|
+000002e0  31 59 db 95 d3 1d 78 ea  50 56 5c d5 82 5a 2d 5a  |1Y....x.PV\..Z-Z|
+000002f0  5f 33 c4 b6 d8 c9 75 90  96 8c 0f 52 98 b5 cd 98  |_3....u....R....|
+00000300  1f 89 20 5f f2 a0 1c a3  1b 96 94 dd a9 fd 57 e9  |.. _..........W.|
+00000310  70 e8 26 6d 71 99 9b 26  6e 38 50 29 6c 90 a7 bd  |p.&mq..&n8P)l...|
+00000320  d9 16 03 01 00 cb 0c 00  00 c7 03 00 17 41 04 05  |.............A..|
+00000330  45 33 f8 4b e9 96 0e 4a  fd ec 54 76 21 9b 24 8a  |E3.K...J..Tv!.$.|
+00000340  75 0b 80 84 c7 30 2b 22  f0 85 57 a4 a9 79 d6 f6  |u....0+"..W..y..|
+00000350  6d 80 b0 71 d9 66 c9 6c  dd 76 fc 32 d0 c6 bc 52  |m..q.f.l.v.2...R|
+00000360  2f f1 c9 62 17 53 76 ec  be a6 1c 93 f2 b4 5d 00  |/..b.Sv.......].|
+00000370  80 72 d9 20 52 70 7c 03  b1 33 fa 51 23 cd 05 97  |.r. Rp|..3.Q#...|
+00000380  6f d6 89 2f 8d 2e 3a 17  32 eb f2 ff 6b 39 70 5e  |o../..:.2...k9p^|
+00000390  21 41 8d 69 02 c8 9a 17  19 e4 48 9b 51 c3 7f 9b  |!A.i......H.Q...|
+000003a0  8d 4a 83 97 07 0e 30 f1  8b 6b e9 92 12 01 d6 96  |.J....0..k......|
+000003b0  f2 1a a2 10 7f 59 87 16  1a fb 55 67 68 fc 78 c6  |.....Y....Ugh.x.|
+000003c0  57 ac 05 dd f3 6f 77 84  eb ae b0 33 2d 19 2c ba  |W....ow....3-.,.|
+000003d0  b8 ae 9f 95 69 85 95 45  5e 37 f4 17 17 9b 03 c1  |....i..E^7......|
+000003e0  50 b1 36 42 bd 60 5c 8b  d8 b6 f3 c8 34 c8 9d 9d  |P.6B.`\.....4...|
+000003f0  75 16 03 01 00 04 0e 00  00 00                    |u.........|
+>>> Flow 3 (client to server)
+00000000  16 03 01 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
+00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
+00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
+00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
+00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 01 00 01  |..h.A.Vk.Z......|
+00000050  01 16 03 01 00 30 ca d1  1b 08 27 9b 44 e7 e9 b4  |.....0....'.D...|
+00000060  90 16 4d 30 4e 65 5c 0d  47 ba 46 86 cf c9 80 e7  |..M0Ne\.G.F.....|
+00000070  64 31 f5 a1 9e dc 39 15  d3 be 16 4f c7 90 b6 62  |d1....9....O...b|
+00000080  5d 6d 7f 41 4e 3e                                 |]m.AN>|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 30 98 81 24 8e cd  |..........0..$..|
+00000010  b6 48 2f 80 de 8e 24 3c  cd 02 67 80 34 97 d7 92  |.H/...$<..g.4...|
+00000020  78 c2 44 3d 5d 05 eb 88  76 79 46 7a c3 fa ca 73  |x.D=]...vyFz...s|
+00000030  45 82 ad c1 81 00 ca 40  c1 2f 13                 |E......@./.|
+>>> Flow 5 (client to server)
+00000000  17 03 01 00 20 ee 19 59  67 67 a9 8b db 99 87 50  |.... ..Ygg.....P|
+00000010  01 e2 02 c1 d5 6d 36 79  af aa ec 1b 80 0e b6 5e  |.....m6y.......^|
+00000020  5f fa 03 01 cc 17 03 01  00 20 ec e2 04 b7 3b a5  |_........ ....;.|
+00000030  f2 e0 13 1f 17 48 e7 6e  d3 eb f0 fa 36 ef 6e 2e  |.....H.n....6.n.|
+00000040  fb ea c8 39 c4 5f 4b 28  d4 50 15 03 01 00 20 c7  |...9._K(.P.... .|
+00000050  45 ff fb c7 07 0c d8 0e  35 a3 c5 31 47 b7 03 0e  |E.......5..1G...|
+00000060  14 c8 29 fd 53 70 5f 15  ac d2 1c 4c 69 fb d6     |..).Sp_....Li..|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4
new file mode 100644
index 0000000..395d53b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4
@@ -0,0 +1,83 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 51 02 00 00  4d 03 01 53 04 f1 02 76  |....Q...M..S...v|
+00000010  e8 45 7f 57 f3 42 4b 33  0b 06 fa a6 fa c4 3d 84  |.E.W.BK3......=.|
+00000020  5a 45 dc 93 41 a5 8d 79  6e 8f 11 20 e7 c6 29 2b  |ZE..A..yn.. ..)+|
+00000030  ff 4a 6e 63 67 a6 10 cb  49 19 46 1e 5e 0a d5 70  |.Jncg...I.F.^..p|
+00000040  96 88 9a 32 48 ef c3 4a  45 4c 6d e0 00 05 00 00  |...2H..JELm.....|
+00000050  05 ff 01 00 01 00 16 03  01 02 be 0b 00 02 ba 00  |................|
+00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 01 00 04 0e 00  |n8P)l...........|
+00000320  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 01 00 86 10 00 00  82 00 80 6d 51 f3 7f f9  |...........mQ...|
+00000010  3e fb 75 82 41 36 83 e8  6a ee 2a 2e 25 90 67 4c  |>.u.A6..j.*.%.gL|
+00000020  8e 62 2f 30 81 17 e0 85  09 0c 2b b7 23 d7 b0 e2  |.b/0......+.#...|
+00000030  1d f7 3b d7 f5 a1 27 b6  ee 24 b6 1b cc 5b ea 66  |..;...'..$...[.f|
+00000040  0d 6a f4 e5 85 f9 da 43  b4 0e 86 85 e1 f5 aa be  |.j.....C........|
+00000050  c8 ce 39 4c 9c 86 00 08  c2 4b e2 c6 ec 2f f7 ce  |..9L.....K.../..|
+00000060  e6 bd 77 82 6f 23 b6 e0  bd a2 92 b7 3a ac e8 56  |..w.o#......:..V|
+00000070  f1 af 54 5e 46 87 e9 3b  33 e7 b8 28 b7 d6 c8 90  |..T^F..;3..(....|
+00000080  35 d4 1c 43 d1 30 6f 55  4e 0a 70 14 03 01 00 01  |5..C.0oUN.p.....|
+00000090  01 16 03 01 00 24 cd c0  68 dc 2e 69 cc c7 5b c5  |.....$..h..i..[.|
+000000a0  3f bd 40 cf a0 0f 41 34  ce 16 37 10 26 c8 3f d1  |?.@...A4..7.&.?.|
+000000b0  46 3b ad 7b b0 31 f3 c5  36 e7                    |F;.{.1..6.|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 24 ea 77 6f 3c 42  |..........$.wo<B|
+00000010  12 16 51 de e8 b6 f9 85  06 d9 6d 05 75 50 2b 27  |..Q.......m.uP+'|
+00000020  93 b7 6b 65 e9 14 99 48  53 3e be e4 be 03 5d     |..ke...HS>....]|
+>>> Flow 5 (client to server)
+00000000  17 03 01 00 1a 9e ae ca  55 df c4 d9 47 04 55 dd  |........U...G.U.|
+00000010  3b 33 e1 a6 16 6f a1 94  b1 9b 4d 0d cb 6c 3b 15  |;3...o....M..l;.|
+00000020  03 01 00 16 92 5d 76 07  e9 b7 31 29 09 c5 b1 09  |.....]v...1)....|
+00000030  2d 64 3d 85 8d f1 d1 40  54 b8                    |-d=....@T.|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
new file mode 100644
index 0000000..9f941f8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
@@ -0,0 +1,89 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 02 00 59 02 00 00  55 03 02 53 04 f1 02 1c  |....Y...U..S....|
+00000010  d1 1c 6a 5f 7a 5c 26 69  92 cd ee c3 57 ed 96 90  |..j_z\&i....W...|
+00000020  e3 c5 f1 ee 8b ee 99 5f  46 2c e6 20 c8 50 6a a4  |......._F,. .Pj.|
+00000030  4b 93 e6 da ba 6d d4 87  f6 75 a8 9d 44 db b5 43  |K....m...u..D..C|
+00000040  df 12 57 de a4 f1 bc fb  b8 7a 3f 6a c0 09 00 00  |..W......z?j....|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  02 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
+00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
+00000080  30 09 06 07 2a 86 48 ce  3d 04 01 30 45 31 0b 30  |0...*.H.=..0E1.0|
+00000090  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+000000a0  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+000000b0  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+000000c0  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+000000d0  74 64 30 1e 17 0d 31 32  31 31 32 32 31 35 30 36  |td0...1211221506|
+000000e0  33 32 5a 17 0d 32 32 31  31 32 30 31 35 30 36 33  |32Z..22112015063|
+000000f0  32 5a 30 45 31 0b 30 09  06 03 55 04 06 13 02 41  |2Z0E1.0...U....A|
+00000100  55 31 13 30 11 06 03 55  04 08 13 0a 53 6f 6d 65  |U1.0...U....Some|
+00000110  2d 53 74 61 74 65 31 21  30 1f 06 03 55 04 0a 13  |-State1!0...U...|
+00000120  18 49 6e 74 65 72 6e 65  74 20 57 69 64 67 69 74  |.Internet Widgit|
+00000130  73 20 50 74 79 20 4c 74  64 30 81 9b 30 10 06 07  |s Pty Ltd0..0...|
+00000140  2a 86 48 ce 3d 02 01 06  05 2b 81 04 00 23 03 81  |*.H.=....+...#..|
+00000150  86 00 04 00 c4 a1 ed be  98 f9 0b 48 73 36 7e c3  |...........Hs6~.|
+00000160  16 56 11 22 f2 3d 53 c3  3b 4d 21 3d cd 6b 75 e6  |.V.".=S.;M!=.ku.|
+00000170  f6 b0 dc 9a df 26 c1 bc  b2 87 f0 72 32 7c b3 64  |.....&.....r2|.d|
+00000180  2f 1c 90 bc ea 68 23 10  7e fe e3 25 c0 48 3a 69  |/....h#.~..%.H:i|
+00000190  e0 28 6d d3 37 00 ef 04  62 dd 0d a0 9c 70 62 83  |.(m.7...b....pb.|
+000001a0  d8 81 d3 64 31 aa 9e 97  31 bd 96 b0 68 c0 9b 23  |...d1...1...h..#|
+000001b0  de 76 64 3f 1a 5c 7f e9  12 0e 58 58 b6 5f 70 dd  |.vd?.\....XX._p.|
+000001c0  9b d8 ea d5 d7 f5 d5 cc  b9 b6 9f 30 66 5b 66 9a  |...........0f[f.|
+000001d0  20 e2 27 e5 bf fe 3b 30  09 06 07 2a 86 48 ce 3d  | .'...;0...*.H.=|
+000001e0  04 01 03 81 8c 00 30 81  88 02 42 01 88 a2 4f eb  |......0...B...O.|
+000001f0  e2 45 c5 48 7d 1b ac f5  ed 98 9d ae 47 70 c0 5e  |.E.H}.......Gp.^|
+00000200  1b b6 2f bd f1 b6 4d b7  61 40 d3 11 a2 ce ee 0b  |../...M.a@......|
+00000210  7e 92 7e ff 76 9d c3 3b  7e a5 3f ce fa 10 e2 59  |~.~.v..;~.?....Y|
+00000220  ec 47 2d 7c ac da 4e 97  0e 15 a0 6f d0 02 42 01  |.G-|..N....o..B.|
+00000230  4d fc be 67 13 9c 2d 05  0e bd 3f a3 8c 25 c1 33  |M..g..-...?..%.3|
+00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
+00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
+00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
+00000270  2a 16 03 02 00 d4 0c 00  00 d0 03 00 17 41 04 7b  |*............A.{|
+00000280  c4 00 37 35 51 de c3 f2  a4 95 2c 19 21 3e a6 94  |..75Q.....,.!>..|
+00000290  7b fd 04 d7 b7 1c 56 e6  af 3c ee 36 cb 55 e6 f0  |{.....V..<.6.U..|
+000002a0  e6 24 34 6b 8a 02 66 71  f9 e2 f5 a6 c9 d7 6c dc  |.$4k..fq......l.|
+000002b0  65 59 ff 1c c9 ec a9 8b  07 d6 52 2c 01 3c c3 00  |eY........R,.<..|
+000002c0  89 30 81 86 02 41 74 89  1a 31 72 e6 8b c0 4a ce  |.0...At..1r...J.|
+000002d0  8f 5a 49 a7 52 2d 6d b9  8b 50 17 62 2a 99 d6 3b  |.ZI.R-m..P.b*..;|
+000002e0  02 85 41 4d 34 53 b5 09  bd e3 ac 16 c1 9b e9 83  |..AM4S..........|
+000002f0  cc 83 e3 9c 23 34 67 71  72 d4 05 a2 34 f7 08 29  |....#4gqr...4..)|
+00000300  62 43 2e cc bc 08 01 02  41 59 de 5a d0 dd d7 6b  |bC......AY.Z...k|
+00000310  db 9c 35 29 79 f8 96 91  56 74 1f 18 7b ee 25 83  |..5)y...Vt..{.%.|
+00000320  f2 37 0e 77 ab 38 fb 5e  04 0b 09 d9 b4 1f 3f be  |.7.w.8.^......?.|
+00000330  2e e3 60 e3 96 f3 29 c1  6d 8f 56 1b fd 62 14 48  |..`...).m.V..b.H|
+00000340  e3 d9 2a ea 2f be 93 d0  8b 31 16 03 02 00 04 0e  |..*./....1......|
+00000350  00 00 00                                          |...|
+>>> Flow 3 (client to server)
+00000000  16 03 02 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
+00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
+00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
+00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
+00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 02 00 01  |..h.A.Vk.Z......|
+00000050  01 16 03 02 00 40 00 00  00 00 00 00 00 00 00 00  |.....@..........|
+00000060  00 00 00 00 00 00 b6 98  a2 a9 48 34 12 6b 0a 94  |..........H4.k..|
+00000070  89 fc 38 04 63 5a 6f 63  36 3e d9 35 12 64 8c 28  |..8.cZoc6>.5.d.(|
+00000080  99 a6 cf 2e 57 e3 14 6d  0a 8a ab f0 a6 58 37 7c  |....W..m.....X7||
+00000090  96 04 d3 71 bc d4                                 |...q..|
+>>> Flow 4 (server to client)
+00000000  14 03 02 00 01 01 16 03  02 00 40 c5 01 c9 0a b0  |..........@.....|
+00000010  d8 ca 5e c1 19 dc 37 6c  2e a0 b3 11 a8 87 65 5a  |..^...7l......eZ|
+00000020  09 41 b9 fe 53 c4 c9 76  97 6d 7f ac c0 be d2 07  |.A..S..v.m......|
+00000030  84 e5 5b 78 37 34 ee da  3b cb 3e 82 52 79 91 44  |..[x74..;.>.Ry.D|
+00000040  b4 e4 1c ec 3a c0 c0 9d  cd ff 13                 |....:......|
+>>> Flow 5 (client to server)
+00000000  17 03 02 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+00000010  00 00 00 00 00 46 60 13  39 2b 2f 72 95 ed 0e aa  |.....F`.9+/r....|
+00000020  69 6e b4 64 3e 83 43 d0  f9 7f 37 7c 1d b9 ce 11  |in.d>.C...7|....|
+00000030  d9 41 66 60 6d 15 03 02  00 30 00 00 00 00 00 00  |.Af`m....0......|
+00000040  00 00 00 00 00 00 00 00  00 00 b1 26 d0 5d 08 98  |...........&.]..|
+00000050  eb 28 42 74 31 58 42 95  c5 ad 1a 92 0a f5 5f ed  |.(Bt1XB......._.|
+00000060  45 98 e0 90 e5 a3 b6 8b  8d 18                    |E.........|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
new file mode 100644
index 0000000..fc72339
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
@@ -0,0 +1,99 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 02 00 59 02 00 00  55 03 02 53 04 f1 02 fe  |....Y...U..S....|
+00000010  17 8b 79 ad 93 2e d3 89  66 9b 5d 9b b4 03 3e ba  |..y.....f.]...>.|
+00000020  65 2a f1 55 f9 3c 33 de  2c a7 47 20 fa 4f 82 11  |e*.U.<3.,.G .O..|
+00000030  96 81 d0 70 2e 65 b3 68  2e 3a 6d d7 6c 74 22 33  |...p.e.h.:m.lt"3|
+00000040  d4 ae 6c aa c8 f0 c7 20  8b 10 21 e7 c0 13 00 00  |..l.... ..!.....|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  02 02 be 0b 00 02 ba 00  02 b7 00 02 b4 30 82 02  |.............0..|
+00000070  b0 30 82 02 19 a0 03 02  01 02 02 09 00 85 b0 bb  |.0..............|
+00000080  a4 8a 7f b8 ca 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
+00000090  01 05 05 00 30 45 31 0b  30 09 06 03 55 04 06 13  |....0E1.0...U...|
+000000a0  02 41 55 31 13 30 11 06  03 55 04 08 13 0a 53 6f  |.AU1.0...U....So|
+000000b0  6d 65 2d 53 74 61 74 65  31 21 30 1f 06 03 55 04  |me-State1!0...U.|
+000000c0  0a 13 18 49 6e 74 65 72  6e 65 74 20 57 69 64 67  |...Internet Widg|
+000000d0  69 74 73 20 50 74 79 20  4c 74 64 30 1e 17 0d 31  |its Pty Ltd0...1|
+000000e0  30 30 34 32 34 30 39 30  39 33 38 5a 17 0d 31 31  |00424090938Z..11|
+000000f0  30 34 32 34 30 39 30 39  33 38 5a 30 45 31 0b 30  |0424090938Z0E1.0|
+00000100  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+00000110  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+00000120  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+00000130  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+00000140  74 64 30 81 9f 30 0d 06  09 2a 86 48 86 f7 0d 01  |td0..0...*.H....|
+00000150  01 01 05 00 03 81 8d 00  30 81 89 02 81 81 00 bb  |........0.......|
+00000160  79 d6 f5 17 b5 e5 bf 46  10 d0 dc 69 be e6 2b 07  |y......F...i..+.|
+00000170  43 5a d0 03 2d 8a 7a 43  85 b7 14 52 e7 a5 65 4c  |CZ..-.zC...R..eL|
+00000180  2c 78 b8 23 8c b5 b4 82  e5 de 1f 95 3b 7e 62 a5  |,x.#........;~b.|
+00000190  2c a5 33 d6 fe 12 5c 7a  56 fc f5 06 bf fa 58 7b  |,.3...\zV.....X{|
+000001a0  26 3f b5 cd 04 d3 d0 c9  21 96 4a c7 f4 54 9f 5a  |&?......!.J..T.Z|
+000001b0  bf ef 42 71 00 fe 18 99  07 7f 7e 88 7d 7d f1 04  |..Bq......~.}}..|
+000001c0  39 c4 a2 2e db 51 c9 7c  e3 c0 4c 3b 32 66 01 cf  |9....Q.|..L;2f..|
+000001d0  af b1 1d b8 71 9a 1d db  db 89 6b ae da 2d 79 02  |....q.....k..-y.|
+000001e0  03 01 00 01 a3 81 a7 30  81 a4 30 1d 06 03 55 1d  |.......0..0...U.|
+000001f0  0e 04 16 04 14 b1 ad e2  85 5a cf cb 28 db 69 ce  |.........Z..(.i.|
+00000200  23 69 de d3 26 8e 18 88  39 30 75 06 03 55 1d 23  |#i..&...90u..U.#|
+00000210  04 6e 30 6c 80 14 b1 ad  e2 85 5a cf cb 28 db 69  |.n0l......Z..(.i|
+00000220  ce 23 69 de d3 26 8e 18  88 39 a1 49 a4 47 30 45  |.#i..&...9.I.G0E|
+00000230  31 0b 30 09 06 03 55 04  06 13 02 41 55 31 13 30  |1.0...U....AU1.0|
+00000240  11 06 03 55 04 08 13 0a  53 6f 6d 65 2d 53 74 61  |...U....Some-Sta|
+00000250  74 65 31 21 30 1f 06 03  55 04 0a 13 18 49 6e 74  |te1!0...U....Int|
+00000260  65 72 6e 65 74 20 57 69  64 67 69 74 73 20 50 74  |ernet Widgits Pt|
+00000270  79 20 4c 74 64 82 09 00  85 b0 bb a4 8a 7f b8 ca  |y Ltd...........|
+00000280  30 0c 06 03 55 1d 13 04  05 30 03 01 01 ff 30 0d  |0...U....0....0.|
+00000290  06 09 2a 86 48 86 f7 0d  01 01 05 05 00 03 81 81  |..*.H...........|
+000002a0  00 08 6c 45 24 c7 6b b1  59 ab 0c 52 cc f2 b0 14  |..lE$.k.Y..R....|
+000002b0  d7 87 9d 7a 64 75 b5 5a  95 66 e4 c5 2b 8e ae 12  |...zdu.Z.f..+...|
+000002c0  66 1f eb 4f 38 b3 6e 60  d3 92 fd f7 41 08 b5 25  |f..O8.n`....A..%|
+000002d0  13 b1 18 7a 24 fb 30 1d  ba ed 98 b9 17 ec e7 d7  |...z$.0.........|
+000002e0  31 59 db 95 d3 1d 78 ea  50 56 5c d5 82 5a 2d 5a  |1Y....x.PV\..Z-Z|
+000002f0  5f 33 c4 b6 d8 c9 75 90  96 8c 0f 52 98 b5 cd 98  |_3....u....R....|
+00000300  1f 89 20 5f f2 a0 1c a3  1b 96 94 dd a9 fd 57 e9  |.. _..........W.|
+00000310  70 e8 26 6d 71 99 9b 26  6e 38 50 29 6c 90 a7 bd  |p.&mq..&n8P)l...|
+00000320  d9 16 03 02 00 cb 0c 00  00 c7 03 00 17 41 04 26  |.............A.&|
+00000330  56 18 02 e5 66 d4 aa 24  7e ae 39 e5 ca 78 6c c1  |V...f..$~.9..xl.|
+00000340  90 02 c3 c4 ad 79 2c 47  a8 bf 54 e2 8a 22 b6 ef  |.....y,G..T.."..|
+00000350  99 d4 7a 7f 8f 78 6a 78  4e 14 2a 16 0d bb 54 38  |..z..xjxN.*...T8|
+00000360  59 1f 7a 53 1b c7 73 10  89 4b de c3 66 39 7a 00  |Y.zS..s..K..f9z.|
+00000370  80 3a 88 38 c8 15 07 ab  2f 0f 0d cb 19 07 84 ac  |.:.8..../.......|
+00000380  24 fd 8b d2 9d 05 45 c6  11 c3 d6 84 58 95 5a 08  |$.....E.....X.Z.|
+00000390  b9 a4 2c c0 41 4e 34 e0  b2 24 98 94 b7 67 27 50  |..,.AN4..$...g'P|
+000003a0  ba 82 35 28 a9 bf 16 ee  e3 7b 49 9c 4c 81 80 69  |..5(.....{I.L..i|
+000003b0  d7 aa ed 46 ea 9a 68 c4  97 b7 11 d4 35 91 74 5e  |...F..h.....5.t^|
+000003c0  54 10 34 83 cd c4 06 18  49 7d 7a 28 c9 53 06 73  |T.4.....I}z(.S.s|
+000003d0  00 7b 04 b6 d8 36 a7 4b  67 7f 81 30 94 de 40 4d  |.{...6.Kg..0..@M|
+000003e0  18 f8 c4 b7 02 00 44 8e  bc 72 06 24 53 15 74 72  |......D..r.$S.tr|
+000003f0  8d 16 03 02 00 04 0e 00  00 00                    |..........|
+>>> Flow 3 (client to server)
+00000000  16 03 02 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
+00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
+00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
+00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
+00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 02 00 01  |..h.A.Vk.Z......|
+00000050  01 16 03 02 00 40 00 00  00 00 00 00 00 00 00 00  |.....@..........|
+00000060  00 00 00 00 00 00 8a 87  81 38 35 c0 4c bb f8 12  |.........85.L...|
+00000070  fa 75 04 cd 1e 3a 61 96  93 c8 fb 07 d1 6d b4 55  |.u...:a......m.U|
+00000080  0f b5 0f 07 35 0a 96 ce  5c 6f 24 62 d3 68 e4 b0  |....5...\o$b.h..|
+00000090  5d be 81 37 c2 9c                                 |]..7..|
+>>> Flow 4 (server to client)
+00000000  14 03 02 00 01 01 16 03  02 00 40 66 36 8d f8 8c  |..........@f6...|
+00000010  7f db 38 e8 39 df f8 2f  cb 88 9c 14 d9 89 10 b4  |..8.9../........|
+00000020  be 59 88 d7 f3 73 62 af  a3 42 66 6e 74 38 64 9f  |.Y...sb..Bfnt8d.|
+00000030  16 79 09 d7 14 7e 91 8a  70 73 63 28 30 58 fe cc  |.y...~..psc(0X..|
+00000040  42 45 d6 37 fb 9e 8c c1  01 af 34                 |BE.7......4|
+>>> Flow 5 (client to server)
+00000000  17 03 02 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+00000010  00 00 00 00 00 31 0b e3  9d 2a 05 83 19 7d 10 36  |.....1...*...}.6|
+00000020  23 dc da fe 00 ab d3 aa  8f ce 28 5f 08 fd b7 59  |#.........(_...Y|
+00000030  1e 00 2e 25 5a 15 03 02  00 30 00 00 00 00 00 00  |...%Z....0......|
+00000040  00 00 00 00 00 00 00 00  00 00 10 91 fd fa 59 07  |..............Y.|
+00000050  df 2c 92 25 15 7b 7c 83  44 89 0d 4f 65 43 99 2e  |.,.%.{|.D..OeC..|
+00000060  41 5d 51 c9 09 89 ed 02  08 bc                    |A]Q.......|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4
new file mode 100644
index 0000000..f7be3f7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4
@@ -0,0 +1,83 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 02 00 51 02 00 00  4d 03 02 53 04 f1 02 d4  |....Q...M..S....|
+00000010  69 65 aa 96 3d 42 96 eb  9e 7d 8a 18 af 4c 7c 5d  |ie..=B...}...L|]|
+00000020  fb 97 5f da 94 62 13 69  1f 66 06 20 aa 52 e3 08  |.._..b.i.f. .R..|
+00000030  35 0a 87 d5 ef 93 49 ab  1a 74 dd 90 bd 69 70 d1  |5.....I..t...ip.|
+00000040  e9 f1 44 17 3a dc 33 98  f5 e5 ab 93 00 05 00 00  |..D.:.3.........|
+00000050  05 ff 01 00 01 00 16 03  02 02 be 0b 00 02 ba 00  |................|
+00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 02 00 04 0e 00  |n8P)l...........|
+00000320  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 02 00 86 10 00 00  82 00 80 6d 51 f3 7f f9  |...........mQ...|
+00000010  3e fb 75 82 41 36 83 e8  6a ee 2a 2e 25 90 67 4c  |>.u.A6..j.*.%.gL|
+00000020  8e 62 2f 30 81 17 e0 85  09 0c 2b b7 23 d7 b0 e2  |.b/0......+.#...|
+00000030  1d f7 3b d7 f5 a1 27 b6  ee 24 b6 1b cc 5b ea 66  |..;...'..$...[.f|
+00000040  0d 6a f4 e5 85 f9 da 43  b4 0e 86 85 e1 f5 aa be  |.j.....C........|
+00000050  c8 ce 39 4c 9c 86 00 08  c2 4b e2 c6 ec 2f f7 ce  |..9L.....K.../..|
+00000060  e6 bd 77 82 6f 23 b6 e0  bd a2 92 b7 3a ac e8 56  |..w.o#......:..V|
+00000070  f1 af 54 5e 46 87 e9 3b  33 e7 b8 28 b7 d6 c8 90  |..T^F..;3..(....|
+00000080  35 d4 1c 43 d1 30 6f 55  4e 0a 70 14 03 02 00 01  |5..C.0oUN.p.....|
+00000090  01 16 03 02 00 24 07 9f  dc df 2d c3 a6 88 06 28  |.....$....-....(|
+000000a0  21 e0 e0 d3 31 99 fc 89  b8 82 6e 95 f4 4b 9e e2  |!...1.....n..K..|
+000000b0  d9 36 5c 14 ce d7 db e2  78 4e                    |.6\.....xN|
+>>> Flow 4 (server to client)
+00000000  14 03 02 00 01 01 16 03  02 00 24 81 72 75 80 d4  |..........$.ru..|
+00000010  1b 1a 32 00 89 bf 9e 79  30 b9 6b 67 e0 8e c7 eb  |..2....y0.kg....|
+00000020  73 f2 e4 93 51 65 9b 5f  91 b1 b4 b1 f7 44 76     |s...Qe._.....Dv|
+>>> Flow 5 (client to server)
+00000000  17 03 02 00 1a b2 91 39  63 c0 38 3c 4d 25 fd 14  |.......9c.8<M%..|
+00000010  b9 b6 e1 23 21 b4 8d 17  9e 1f d8 33 92 69 c2 15  |...#!......3.i..|
+00000020  03 02 00 16 4b 10 25 4d  9d 09 c2 11 96 be f7 5b  |....K.%M.......[|
+00000030  c2 9b 99 fd 1f 8e af 0f  2c 51                    |........,Q|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
new file mode 100644
index 0000000..2073270
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
@@ -0,0 +1,134 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 59 02 00 00  55 03 03 53 04 f1 03 6f  |....Y...U..S...o|
+00000010  c6 4b 55 27 fe e8 fe 4d  7c 0e d4 20 98 b8 7c 81  |.KU'...M|.. ..|.|
+00000020  3d 31 f8 35 66 2f 0a 0b  f1 2c e3 20 86 4d 12 32  |=1.5f/...,. .M.2|
+00000030  73 e3 ba be 25 50 a4 a2  a1 7b f1 9a 76 7a 75 fb  |s...%P...{..vzu.|
+00000040  e2 64 a2 12 ec f3 e7 9d  9a 24 6e 94 c0 09 00 00  |.d.......$n.....|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
+00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
+00000080  30 09 06 07 2a 86 48 ce  3d 04 01 30 45 31 0b 30  |0...*.H.=..0E1.0|
+00000090  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+000000a0  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+000000b0  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+000000c0  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+000000d0  74 64 30 1e 17 0d 31 32  31 31 32 32 31 35 30 36  |td0...1211221506|
+000000e0  33 32 5a 17 0d 32 32 31  31 32 30 31 35 30 36 33  |32Z..22112015063|
+000000f0  32 5a 30 45 31 0b 30 09  06 03 55 04 06 13 02 41  |2Z0E1.0...U....A|
+00000100  55 31 13 30 11 06 03 55  04 08 13 0a 53 6f 6d 65  |U1.0...U....Some|
+00000110  2d 53 74 61 74 65 31 21  30 1f 06 03 55 04 0a 13  |-State1!0...U...|
+00000120  18 49 6e 74 65 72 6e 65  74 20 57 69 64 67 69 74  |.Internet Widgit|
+00000130  73 20 50 74 79 20 4c 74  64 30 81 9b 30 10 06 07  |s Pty Ltd0..0...|
+00000140  2a 86 48 ce 3d 02 01 06  05 2b 81 04 00 23 03 81  |*.H.=....+...#..|
+00000150  86 00 04 00 c4 a1 ed be  98 f9 0b 48 73 36 7e c3  |...........Hs6~.|
+00000160  16 56 11 22 f2 3d 53 c3  3b 4d 21 3d cd 6b 75 e6  |.V.".=S.;M!=.ku.|
+00000170  f6 b0 dc 9a df 26 c1 bc  b2 87 f0 72 32 7c b3 64  |.....&.....r2|.d|
+00000180  2f 1c 90 bc ea 68 23 10  7e fe e3 25 c0 48 3a 69  |/....h#.~..%.H:i|
+00000190  e0 28 6d d3 37 00 ef 04  62 dd 0d a0 9c 70 62 83  |.(m.7...b....pb.|
+000001a0  d8 81 d3 64 31 aa 9e 97  31 bd 96 b0 68 c0 9b 23  |...d1...1...h..#|
+000001b0  de 76 64 3f 1a 5c 7f e9  12 0e 58 58 b6 5f 70 dd  |.vd?.\....XX._p.|
+000001c0  9b d8 ea d5 d7 f5 d5 cc  b9 b6 9f 30 66 5b 66 9a  |...........0f[f.|
+000001d0  20 e2 27 e5 bf fe 3b 30  09 06 07 2a 86 48 ce 3d  | .'...;0...*.H.=|
+000001e0  04 01 03 81 8c 00 30 81  88 02 42 01 88 a2 4f eb  |......0...B...O.|
+000001f0  e2 45 c5 48 7d 1b ac f5  ed 98 9d ae 47 70 c0 5e  |.E.H}.......Gp.^|
+00000200  1b b6 2f bd f1 b6 4d b7  61 40 d3 11 a2 ce ee 0b  |../...M.a@......|
+00000210  7e 92 7e ff 76 9d c3 3b  7e a5 3f ce fa 10 e2 59  |~.~.v..;~.?....Y|
+00000220  ec 47 2d 7c ac da 4e 97  0e 15 a0 6f d0 02 42 01  |.G-|..N....o..B.|
+00000230  4d fc be 67 13 9c 2d 05  0e bd 3f a3 8c 25 c1 33  |M..g..-...?..%.3|
+00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
+00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
+00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
+00000270  2a 16 03 03 00 d7 0c 00  00 d3 03 00 17 41 04 a3  |*............A..|
+00000280  03 8c de d2 b0 68 c8 25  0e 85 ea d7 ae 13 0d 79  |.....h.%.......y|
+00000290  ec 59 0d b5 4d 51 96 d9  7f 64 36 fb 4c d5 6a 26  |.Y..MQ...d6.L.j&|
+000002a0  ae 0e 48 61 df 5c 2b d4  ff 09 41 15 c4 14 8e 1b  |..Ha.\+...A.....|
+000002b0  84 a8 c8 cd ef 10 97 95  66 67 85 dd fd dc 2a 04  |........fg....*.|
+000002c0  03 00 8a 30 81 87 02 41  11 75 5d bc bd 08 28 d4  |...0...A.u]...(.|
+000002d0  5b 1b 45 7f 9c d3 8d 0b  91 fa f6 82 ba 59 bd 3e  |[.E..........Y.>|
+000002e0  96 01 c6 1d 38 db fe 08  e7 56 89 fc 10 b0 37 6a  |....8....V....7j|
+000002f0  3d d6 c9 50 16 53 f7 c2  a2 60 67 82 1f 74 b8 d5  |=..P.S...`g..t..|
+00000300  bc 02 ec 96 db 82 18 8c  87 02 42 01 0d df f7 b7  |..........B.....|
+00000310  05 3c 8c 56 f0 1d 33 18  cf c5 4c 80 7e 0b d9 f9  |.<.V..3...L.~...|
+00000320  f0 51 69 fe 5d b8 0b 64  c0 c7 0d f4 75 65 ae 07  |.Qi.]..d....ue..|
+00000330  9d cf f4 4b ad 52 f6 b8  10 26 18 bd d6 e2 0d a8  |...K.R...&......|
+00000340  80 10 50 34 15 cd 72 0b  7d a9 94 de 4c 16 03 03  |..P4..r.}...L...|
+00000350  00 30 0d 00 00 28 03 01  02 40 00 20 06 01 06 02  |.0...(...@. ....|
+00000360  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
+00000370  03 02 03 03 02 01 02 02  02 03 01 01 00 00 0e 00  |................|
+00000380  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 03 02 0a 0b 00 02  06 00 02 03 00 02 00 30  |...............0|
+00000010  82 01 fc 30 82 01 5e 02  09 00 9a 30 84 6c 26 35  |...0..^....0.l&5|
+00000020  d9 17 30 09 06 07 2a 86  48 ce 3d 04 01 30 45 31  |..0...*.H.=..0E1|
+00000030  0b 30 09 06 03 55 04 06  13 02 41 55 31 13 30 11  |.0...U....AU1.0.|
+00000040  06 03 55 04 08 13 0a 53  6f 6d 65 2d 53 74 61 74  |..U....Some-Stat|
+00000050  65 31 21 30 1f 06 03 55  04 0a 13 18 49 6e 74 65  |e1!0...U....Inte|
+00000060  72 6e 65 74 20 57 69 64  67 69 74 73 20 50 74 79  |rnet Widgits Pty|
+00000070  20 4c 74 64 30 1e 17 0d  31 32 31 31 31 34 31 33  | Ltd0...12111413|
+00000080  32 35 35 33 5a 17 0d 32  32 31 31 31 32 31 33 32  |2553Z..221112132|
+00000090  35 35 33 5a 30 41 31 0b  30 09 06 03 55 04 06 13  |553Z0A1.0...U...|
+000000a0  02 41 55 31 0c 30 0a 06  03 55 04 08 13 03 4e 53  |.AU1.0...U....NS|
+000000b0  57 31 10 30 0e 06 03 55  04 07 13 07 50 79 72 6d  |W1.0...U....Pyrm|
+000000c0  6f 6e 74 31 12 30 10 06  03 55 04 03 13 09 4a 6f  |ont1.0...U....Jo|
+000000d0  65 6c 20 53 69 6e 67 30  81 9b 30 10 06 07 2a 86  |el Sing0..0...*.|
+000000e0  48 ce 3d 02 01 06 05 2b  81 04 00 23 03 81 86 00  |H.=....+...#....|
+000000f0  04 00 95 8c 91 75 14 c0  5e c4 57 b4 d4 c3 6f 8d  |.....u..^.W...o.|
+00000100  ae 68 1e dd 6f ce 86 e1  7e 6e b2 48 3e 81 e5 4e  |.h..o...~n.H>..N|
+00000110  e2 c6 88 4b 64 dc f5 30  bb d3 ff 65 cc 5b f4 dd  |...Kd..0...e.[..|
+00000120  b5 6a 3e 3e d0 1d de 47  c3 76 ad 19 f6 45 2c 8c  |.j>>...G.v...E,.|
+00000130  bc d8 1d 01 4c 1f 70 90  46 76 48 8b 8f 83 cc 4a  |....L.p.FvH....J|
+00000140  5c 8f 40 76 da e0 89 ec  1d 2b c4 4e 30 76 28 41  |\.@v.....+.N0v(A|
+00000150  b2 62 a8 fb 5b f1 f9 4e  7a 8d bd 09 b8 ae ea 8b  |.b..[..Nz.......|
+00000160  18 27 4f 2e 70 fe 13 96  ba c3 d3 40 16 cd 65 4e  |.'O.p......@..eN|
+00000170  ac 11 1e e6 f1 30 09 06  07 2a 86 48 ce 3d 04 01  |.....0...*.H.=..|
+00000180  03 81 8c 00 30 81 88 02  42 00 e0 14 c4 60 60 0b  |....0...B....``.|
+00000190  72 68 b0 32 5d 61 4a 02  74 5c c2 81 b9 16 a8 3f  |rh.2]aJ.t\.....?|
+000001a0  29 c8 36 c7 81 ff 6c b6  5b d9 70 f1 38 3b 50 48  |).6...l.[.p.8;PH|
+000001b0  28 94 cb 09 1a 52 f1 5d  ee 8d f2 b9 f0 f0 da d9  |(....R.]........|
+000001c0  15 3a f9 bd 03 7a 87 a2  23 35 ec 02 42 01 a3 d4  |.:...z..#5..B...|
+000001d0  8a 78 35 1c 4a 9a 23 d2  0a be 2b 10 31 9d 9c 5f  |.x5.J.#...+.1.._|
+000001e0  be e8 91 b3 da 1a f5 5d  a3 23 f5 26 8b 45 70 8d  |.......].#.&.Ep.|
+000001f0  65 62 9b 7e 01 99 3d 18  f6 10 9a 38 61 9b 2e 57  |eb.~..=....8a..W|
+00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
+00000210  03 03 00 46 10 00 00 42  41 04 1e 18 37 ef 0d 19  |...F...BA...7...|
+00000220  51 88 35 75 71 b5 e5 54  5b 12 2e 8f 09 67 fd a7  |Q.5uq..T[....g..|
+00000230  24 20 3e b2 56 1c ce 97  28 5e f8 2b 2d 4f 9e f1  |$ >.V...(^.+-O..|
+00000240  07 9f 6c 4b 5b 83 56 e2  32 42 e9 58 b6 d7 49 a6  |..lK[.V.2B.X..I.|
+00000250  b5 68 1a 41 03 56 6b dc  5a 89 16 03 03 00 92 0f  |.h.A.Vk.Z.......|
+00000260  00 00 8e 04 03 00 8a 30  81 87 02 42 00 c6 85 8e  |.......0...B....|
+00000270  06 b7 04 04 e9 cd 9e 3e  cb 66 23 95 b4 42 9c 64  |.......>.f#..B.d|
+00000280  81 39 05 3f b5 21 f8 28  af 60 6b 4d 3d ba a1 4b  |.9.?.!.(.`kM=..K|
+00000290  5e 77 ef e7 59 28 fe 1d  c1 27 a2 ff a8 de 33 48  |^w..Y(...'....3H|
+000002a0  b3 c1 85 6a 42 9b f9 7e  7e 31 c2 e5 bd 66 02 41  |...jB..~~1...f.A|
+000002b0  4b 49 c6 cd 02 e3 83 f7  03 50 18 6d b4 c9 51 02  |KI.......P.m..Q.|
+000002c0  c0 ab 87 bc e0 3e 4b 89  53 3a e2 65 89 97 02 c1  |.....>K.S:.e....|
+000002d0  88 0d 64 db 8e 4f 73 4e  ea 29 0b ed a0 f5 ce 3d  |..d..OsN.).....=|
+000002e0  5f cc 20 ef 0a 22 02 82  f2 14 2a b7 42 68 bd c7  |_. .."....*.Bh..|
+000002f0  4d 14 03 03 00 01 01 16  03 03 00 40 00 00 00 00  |M..........@....|
+00000300  00 00 00 00 00 00 00 00  00 00 00 00 f0 cc 4f c7  |..............O.|
+00000310  b6 0f c9 38 4d 4b 97 2c  4f be 53 08 4c d6 5b 4e  |...8MK.,O.S.L.[N|
+00000320  24 70 30 81 82 3a 7f 62  95 03 4d fc 54 78 ec 13  |$p0..:.b..M.Tx..|
+00000330  b2 a1 00 85 2b 04 e4 1d  7b 6e 87 60              |....+...{n.`|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 40 d5 2a 76 79 1c  |..........@.*vy.|
+00000010  e7 d5 b1 5c 65 6b d1 45  73 53 4c 05 3a 6c 5d 81  |...\ek.EsSL.:l].|
+00000020  dd 2f f0 74 62 e4 8e f8  ed 21 99 c7 4f d6 28 40  |./.tb....!..O.(@|
+00000030  63 d9 6d e5 b0 04 73 27  7a 1d 08 19 31 10 da ef  |c.m...s'z...1...|
+00000040  79 26 33 fb 45 23 be a4  7c 03 66                 |y&3.E#..|.f|
+>>> Flow 5 (client to server)
+00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+00000010  00 00 00 00 00 e2 53 bd  c0 ef 9e e6 44 94 ea 5d  |......S.....D..]|
+00000020  f5 c5 a9 4b ed eb 1c 49  9f 79 44 f9 cd d7 de 02  |...K...I.yD.....|
+00000030  51 10 ae 87 7d 15 03 03  00 30 00 00 00 00 00 00  |Q...}....0......|
+00000040  00 00 00 00 00 00 00 00  00 00 d3 95 13 7f 5f 58  |.............._X|
+00000050  ab d6 17 ea 01 2c 2a ea  5d 7c 44 61 4a 27 97 52  |.....,*.]|DaJ'.R|
+00000060  cc 9b 86 f6 37 42 2b 94  01 49                    |....7B+..I|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
new file mode 100644
index 0000000..c3b753a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
@@ -0,0 +1,127 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 51 02 00 00  4d 03 03 53 04 f1 03 b0  |....Q...M..S....|
+00000010  43 00 97 24 a7 a8 ea b2  24 fe 96 24 a1 49 64 fd  |C..$....$..$.Id.|
+00000020  1c a3 30 35 2d 85 a7 40  42 86 6b 20 af 27 7f ac  |..05-..@B.k .'..|
+00000030  8b 16 89 6c 78 b7 f5 29  02 58 a6 8b 61 43 c2 b0  |...lx..).X..aC..|
+00000040  e0 a8 96 c8 fa 2b 26 ad  9a 5f 2d d6 00 05 00 00  |.....+&.._-.....|
+00000050  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 30 0d 00  |n8P)l........0..|
+00000320  00 28 03 01 02 40 00 20  06 01 06 02 06 03 05 01  |.(...@. ........|
+00000330  05 02 05 03 04 01 04 02  04 03 03 01 03 02 03 03  |................|
+00000340  02 01 02 02 02 03 01 01  00 00 0e 00 00 00        |..............|
+>>> Flow 3 (client to server)
+00000000  16 03 03 02 0a 0b 00 02  06 00 02 03 00 02 00 30  |...............0|
+00000010  82 01 fc 30 82 01 5e 02  09 00 9a 30 84 6c 26 35  |...0..^....0.l&5|
+00000020  d9 17 30 09 06 07 2a 86  48 ce 3d 04 01 30 45 31  |..0...*.H.=..0E1|
+00000030  0b 30 09 06 03 55 04 06  13 02 41 55 31 13 30 11  |.0...U....AU1.0.|
+00000040  06 03 55 04 08 13 0a 53  6f 6d 65 2d 53 74 61 74  |..U....Some-Stat|
+00000050  65 31 21 30 1f 06 03 55  04 0a 13 18 49 6e 74 65  |e1!0...U....Inte|
+00000060  72 6e 65 74 20 57 69 64  67 69 74 73 20 50 74 79  |rnet Widgits Pty|
+00000070  20 4c 74 64 30 1e 17 0d  31 32 31 31 31 34 31 33  | Ltd0...12111413|
+00000080  32 35 35 33 5a 17 0d 32  32 31 31 31 32 31 33 32  |2553Z..221112132|
+00000090  35 35 33 5a 30 41 31 0b  30 09 06 03 55 04 06 13  |553Z0A1.0...U...|
+000000a0  02 41 55 31 0c 30 0a 06  03 55 04 08 13 03 4e 53  |.AU1.0...U....NS|
+000000b0  57 31 10 30 0e 06 03 55  04 07 13 07 50 79 72 6d  |W1.0...U....Pyrm|
+000000c0  6f 6e 74 31 12 30 10 06  03 55 04 03 13 09 4a 6f  |ont1.0...U....Jo|
+000000d0  65 6c 20 53 69 6e 67 30  81 9b 30 10 06 07 2a 86  |el Sing0..0...*.|
+000000e0  48 ce 3d 02 01 06 05 2b  81 04 00 23 03 81 86 00  |H.=....+...#....|
+000000f0  04 00 95 8c 91 75 14 c0  5e c4 57 b4 d4 c3 6f 8d  |.....u..^.W...o.|
+00000100  ae 68 1e dd 6f ce 86 e1  7e 6e b2 48 3e 81 e5 4e  |.h..o...~n.H>..N|
+00000110  e2 c6 88 4b 64 dc f5 30  bb d3 ff 65 cc 5b f4 dd  |...Kd..0...e.[..|
+00000120  b5 6a 3e 3e d0 1d de 47  c3 76 ad 19 f6 45 2c 8c  |.j>>...G.v...E,.|
+00000130  bc d8 1d 01 4c 1f 70 90  46 76 48 8b 8f 83 cc 4a  |....L.p.FvH....J|
+00000140  5c 8f 40 76 da e0 89 ec  1d 2b c4 4e 30 76 28 41  |\.@v.....+.N0v(A|
+00000150  b2 62 a8 fb 5b f1 f9 4e  7a 8d bd 09 b8 ae ea 8b  |.b..[..Nz.......|
+00000160  18 27 4f 2e 70 fe 13 96  ba c3 d3 40 16 cd 65 4e  |.'O.p......@..eN|
+00000170  ac 11 1e e6 f1 30 09 06  07 2a 86 48 ce 3d 04 01  |.....0...*.H.=..|
+00000180  03 81 8c 00 30 81 88 02  42 00 e0 14 c4 60 60 0b  |....0...B....``.|
+00000190  72 68 b0 32 5d 61 4a 02  74 5c c2 81 b9 16 a8 3f  |rh.2]aJ.t\.....?|
+000001a0  29 c8 36 c7 81 ff 6c b6  5b d9 70 f1 38 3b 50 48  |).6...l.[.p.8;PH|
+000001b0  28 94 cb 09 1a 52 f1 5d  ee 8d f2 b9 f0 f0 da d9  |(....R.]........|
+000001c0  15 3a f9 bd 03 7a 87 a2  23 35 ec 02 42 01 a3 d4  |.:...z..#5..B...|
+000001d0  8a 78 35 1c 4a 9a 23 d2  0a be 2b 10 31 9d 9c 5f  |.x5.J.#...+.1.._|
+000001e0  be e8 91 b3 da 1a f5 5d  a3 23 f5 26 8b 45 70 8d  |.......].#.&.Ep.|
+000001f0  65 62 9b 7e 01 99 3d 18  f6 10 9a 38 61 9b 2e 57  |eb.~..=....8a..W|
+00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
+00000210  03 03 00 86 10 00 00 82  00 80 6d 51 f3 7f f9 3e  |..........mQ...>|
+00000220  fb 75 82 41 36 83 e8 6a  ee 2a 2e 25 90 67 4c 8e  |.u.A6..j.*.%.gL.|
+00000230  62 2f 30 81 17 e0 85 09  0c 2b b7 23 d7 b0 e2 1d  |b/0......+.#....|
+00000240  f7 3b d7 f5 a1 27 b6 ee  24 b6 1b cc 5b ea 66 0d  |.;...'..$...[.f.|
+00000250  6a f4 e5 85 f9 da 43 b4  0e 86 85 e1 f5 aa be c8  |j.....C.........|
+00000260  ce 39 4c 9c 86 00 08 c2  4b e2 c6 ec 2f f7 ce e6  |.9L.....K.../...|
+00000270  bd 77 82 6f 23 b6 e0 bd  a2 92 b7 3a ac e8 56 f1  |.w.o#......:..V.|
+00000280  af 54 5e 46 87 e9 3b 33  e7 b8 28 b7 d6 c8 90 35  |.T^F..;3..(....5|
+00000290  d4 1c 43 d1 30 6f 55 4e  0a 70 16 03 03 00 92 0f  |..C.0oUN.p......|
+000002a0  00 00 8e 04 03 00 8a 30  81 87 02 42 00 c6 85 8e  |.......0...B....|
+000002b0  06 b7 04 04 e9 cd 9e 3e  cb 66 23 95 b4 42 9c 64  |.......>.f#..B.d|
+000002c0  81 39 05 3f b5 21 f8 28  af 60 6b 4d 3d ba a1 4b  |.9.?.!.(.`kM=..K|
+000002d0  5e 77 ef e7 59 28 fe 1d  c1 27 a2 ff a8 de 33 48  |^w..Y(...'....3H|
+000002e0  b3 c1 85 6a 42 9b f9 7e  7e 31 c2 e5 bd 66 02 41  |...jB..~~1...f.A|
+000002f0  4b 49 c6 cd 02 e3 83 f7  03 50 18 6d b4 c9 51 02  |KI.......P.m..Q.|
+00000300  c0 ab 87 bc e0 3e 4b 89  53 3a e2 65 89 97 02 c1  |.....>K.S:.e....|
+00000310  88 5a 97 82 3e 55 6b 7c  d8 db b8 cc 1b 30 84 0a  |.Z..>Uk|.....0..|
+00000320  7a 97 71 e4 10 bb a4 39  8c 2a cf f5 88 c7 d1 95  |z.q....9.*......|
+00000330  73 14 03 03 00 01 01 16  03 03 00 24 9f 1e f0 72  |s..........$...r|
+00000340  92 ea dc f7 56 96 37 e4  69 db db 66 1d f6 94 c4  |....V.7.i..f....|
+00000350  18 31 4f d0 5d c5 f4 53  21 aa 98 b1 dc 08 94 94  |.1O.]..S!.......|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 24 ee 68 c1 87 9f  |..........$.h...|
+00000010  d7 90 94 f1 3b 6d 26 0b  3d 89 7a 45 3b 52 5d 3c  |....;m&.=.zE;R]<|
+00000020  dd 7c c1 4e 57 3e a9 ee  91 be cf 2b a3 98 9d     |.|.NW>.....+...|
+>>> Flow 5 (client to server)
+00000000  17 03 03 00 1a 88 33 3e  2b 22 6b 92 d0 bb 8a 1e  |......3>+"k.....|
+00000010  9b f4 9e aa 91 8b 2b 95  ea 53 c8 03 0a 93 58 15  |......+..S....X.|
+00000020  03 03 00 16 c4 67 79 ba  ec cf 90 b1 f9 ac ec 64  |.....gy........d|
+00000030  72 01 08 8f 3a 98 aa 66  25 00                    |r...:..f%.|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
new file mode 100644
index 0000000..0037af6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
@@ -0,0 +1,133 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 59 02 00 00  55 03 03 53 04 f1 02 fd  |....Y...U..S....|
+00000010  41 bd ef ee f3 da fc 1a  31 8c 77 f2 e9 66 54 a0  |A.......1.w..fT.|
+00000020  f4 15 b1 1c 84 0d 6d 74  87 ac 7d 20 78 17 8b 08  |......mt..} x...|
+00000030  10 20 c9 44 e4 8a 43 af  4a c7 b8 3d 99 f2 f7 af  |. .D..C.J..=....|
+00000040  bb a3 21 2f 40 cc ed b6  da a8 a1 d5 c0 09 00 00  |..!/@...........|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
+00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
+00000080  30 09 06 07 2a 86 48 ce  3d 04 01 30 45 31 0b 30  |0...*.H.=..0E1.0|
+00000090  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+000000a0  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+000000b0  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+000000c0  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+000000d0  74 64 30 1e 17 0d 31 32  31 31 32 32 31 35 30 36  |td0...1211221506|
+000000e0  33 32 5a 17 0d 32 32 31  31 32 30 31 35 30 36 33  |32Z..22112015063|
+000000f0  32 5a 30 45 31 0b 30 09  06 03 55 04 06 13 02 41  |2Z0E1.0...U....A|
+00000100  55 31 13 30 11 06 03 55  04 08 13 0a 53 6f 6d 65  |U1.0...U....Some|
+00000110  2d 53 74 61 74 65 31 21  30 1f 06 03 55 04 0a 13  |-State1!0...U...|
+00000120  18 49 6e 74 65 72 6e 65  74 20 57 69 64 67 69 74  |.Internet Widgit|
+00000130  73 20 50 74 79 20 4c 74  64 30 81 9b 30 10 06 07  |s Pty Ltd0..0...|
+00000140  2a 86 48 ce 3d 02 01 06  05 2b 81 04 00 23 03 81  |*.H.=....+...#..|
+00000150  86 00 04 00 c4 a1 ed be  98 f9 0b 48 73 36 7e c3  |...........Hs6~.|
+00000160  16 56 11 22 f2 3d 53 c3  3b 4d 21 3d cd 6b 75 e6  |.V.".=S.;M!=.ku.|
+00000170  f6 b0 dc 9a df 26 c1 bc  b2 87 f0 72 32 7c b3 64  |.....&.....r2|.d|
+00000180  2f 1c 90 bc ea 68 23 10  7e fe e3 25 c0 48 3a 69  |/....h#.~..%.H:i|
+00000190  e0 28 6d d3 37 00 ef 04  62 dd 0d a0 9c 70 62 83  |.(m.7...b....pb.|
+000001a0  d8 81 d3 64 31 aa 9e 97  31 bd 96 b0 68 c0 9b 23  |...d1...1...h..#|
+000001b0  de 76 64 3f 1a 5c 7f e9  12 0e 58 58 b6 5f 70 dd  |.vd?.\....XX._p.|
+000001c0  9b d8 ea d5 d7 f5 d5 cc  b9 b6 9f 30 66 5b 66 9a  |...........0f[f.|
+000001d0  20 e2 27 e5 bf fe 3b 30  09 06 07 2a 86 48 ce 3d  | .'...;0...*.H.=|
+000001e0  04 01 03 81 8c 00 30 81  88 02 42 01 88 a2 4f eb  |......0...B...O.|
+000001f0  e2 45 c5 48 7d 1b ac f5  ed 98 9d ae 47 70 c0 5e  |.E.H}.......Gp.^|
+00000200  1b b6 2f bd f1 b6 4d b7  61 40 d3 11 a2 ce ee 0b  |../...M.a@......|
+00000210  7e 92 7e ff 76 9d c3 3b  7e a5 3f ce fa 10 e2 59  |~.~.v..;~.?....Y|
+00000220  ec 47 2d 7c ac da 4e 97  0e 15 a0 6f d0 02 42 01  |.G-|..N....o..B.|
+00000230  4d fc be 67 13 9c 2d 05  0e bd 3f a3 8c 25 c1 33  |M..g..-...?..%.3|
+00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
+00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
+00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
+00000270  2a 16 03 03 00 d8 0c 00  00 d4 03 00 17 41 04 a9  |*............A..|
+00000280  19 8b d9 9b 5c 7c 6a 7d  85 d2 70 4e 89 7e 0b 5b  |....\|j}..pN.~.[|
+00000290  dd 5e a1 63 8d 15 bc 0b  0c 47 3d 4d e8 a7 56 88  |.^.c.....G=M..V.|
+000002a0  2e f6 7f e2 4d fc ed cc  03 ed a1 2d ac ae 81 a5  |....M......-....|
+000002b0  e2 6d 7f 9f a3 93 e9 10  c1 0e 48 1b f3 f4 38 04  |.m........H...8.|
+000002c0  03 00 8b 30 81 88 02 42  00 87 fe 7e 63 82 14 57  |...0...B...~c..W|
+000002d0  dc 7d e2 0f cc 97 2d ba  3c a7 56 4a 17 a8 09 6a  |.}....-.<.VJ...j|
+000002e0  28 2e f2 66 1a 3f 2d 48  2b 6f 79 a1 60 cd 5e 10  |(..f.?-H+oy.`.^.|
+000002f0  0b 0a 28 f2 5f e4 3f 4f  f9 c9 91 34 d9 dc bc fc  |..(._.?O...4....|
+00000300  98 ea 77 0b 99 f8 a2 11  c4 bd 02 42 01 a0 b0 dc  |..w........B....|
+00000310  db 5b c2 09 99 bd ee a0  b9 aa 31 b9 10 84 22 be  |.[........1...".|
+00000320  5a 63 12 5a 43 00 8e c1  33 cc 91 bb c2 70 7a 63  |Zc.ZC...3....pzc|
+00000330  19 82 c0 74 48 a1 c7 3d  1f f1 6f 4a 6f 6a 8c 3f  |...tH..=..oJoj.?|
+00000340  28 31 a8 0c 65 19 26 62  4b 7a 7c 4b ea 1a 16 03  |(1..e.&bKz|K....|
+00000350  03 00 30 0d 00 00 28 03  01 02 40 00 20 06 01 06  |..0...(...@. ...|
+00000360  02 06 03 05 01 05 02 05  03 04 01 04 02 04 03 03  |................|
+00000370  01 03 02 03 03 02 01 02  02 02 03 01 01 00 00 0e  |................|
+00000380  00 00 00                                          |...|
+>>> Flow 3 (client to server)
+00000000  16 03 03 01 fb 0b 00 01  f7 00 01 f4 00 01 f1 30  |...............0|
+00000010  82 01 ed 30 82 01 58 a0  03 02 01 02 02 01 00 30  |...0..X........0|
+00000020  0b 06 09 2a 86 48 86 f7  0d 01 01 05 30 26 31 10  |...*.H......0&1.|
+00000030  30 0e 06 03 55 04 0a 13  07 41 63 6d 65 20 43 6f  |0...U....Acme Co|
+00000040  31 12 30 10 06 03 55 04  03 13 09 31 32 37 2e 30  |1.0...U....127.0|
+00000050  2e 30 2e 31 30 1e 17 0d  31 31 31 32 30 38 30 37  |.0.10...11120807|
+00000060  35 35 31 32 5a 17 0d 31  32 31 32 30 37 30 38 30  |5512Z..121207080|
+00000070  30 31 32 5a 30 26 31 10  30 0e 06 03 55 04 0a 13  |012Z0&1.0...U...|
+00000080  07 41 63 6d 65 20 43 6f  31 12 30 10 06 03 55 04  |.Acme Co1.0...U.|
+00000090  03 13 09 31 32 37 2e 30  2e 30 2e 31 30 81 9c 30  |...127.0.0.10..0|
+000000a0  0b 06 09 2a 86 48 86 f7  0d 01 01 01 03 81 8c 00  |...*.H..........|
+000000b0  30 81 88 02 81 80 4e d0  7b 31 e3 82 64 d9 59 c0  |0.....N.{1..d.Y.|
+000000c0  c2 87 a4 5e 1e 8b 73 33  c7 63 53 df 66 92 06 84  |...^..s3.cS.f...|
+000000d0  f6 64 d5 8f e4 36 a7 1d  2b e8 b3 20 36 45 23 b5  |.d...6..+.. 6E#.|
+000000e0  e3 95 ae ed e0 f5 20 9c  8d 95 df 7f 5a 12 ef 87  |...... .....Z...|
+000000f0  e4 5b 68 e4 e9 0e 74 ec  04 8a 7f de 93 27 c4 01  |.[h...t......'..|
+00000100  19 7a bd f2 dc 3d 14 ab  d0 54 ca 21 0c d0 4d 6e  |.z...=...T.!..Mn|
+00000110  87 2e 5c c5 d2 bb 4d 4b  4f ce b6 2c f7 7e 88 ec  |..\...MKO..,.~..|
+00000120  7c d7 02 91 74 a6 1e 0c  1a da e3 4a 5a 2e de 13  ||...t......JZ...|
+00000130  9c 4c 40 88 59 93 02 03  01 00 01 a3 32 30 30 30  |.L@.Y.......2000|
+00000140  0e 06 03 55 1d 0f 01 01  ff 04 04 03 02 00 a0 30  |...U...........0|
+00000150  0d 06 03 55 1d 0e 04 06  04 04 01 02 03 04 30 0f  |...U..........0.|
+00000160  06 03 55 1d 23 04 08 30  06 80 04 01 02 03 04 30  |..U.#..0.......0|
+00000170  0b 06 09 2a 86 48 86 f7  0d 01 01 05 03 81 81 00  |...*.H..........|
+00000180  36 1f b3 7a 0c 75 c9 6e  37 46 61 2b d5 bd c0 a7  |6..z.u.n7Fa+....|
+00000190  4b cc 46 9a 81 58 7c 85  79 29 c8 c8 c6 67 dd 32  |K.F..X|.y)...g.2|
+000001a0  56 45 2b 75 b6 e9 24 a9  50 9a be 1f 5a fa 1a 15  |VE+u..$.P...Z...|
+000001b0  d9 cc 55 95 72 16 83 b9  c2 b6 8f fd 88 8c 38 84  |..U.r.........8.|
+000001c0  1d ab 5d 92 31 13 4f fd  83 3b c6 9d f1 11 62 b6  |..].1.O..;....b.|
+000001d0  8b ec ab 67 be c8 64 b0  11 50 46 58 17 6b 99 1c  |...g..d..PFX.k..|
+000001e0  d3 1d fc 06 f1 0e e5 96  a8 0c f9 78 20 b7 44 18  |...........x .D.|
+000001f0  51 8d 10 7e 4f 94 67 df  a3 4e 70 73 8e 90 91 85  |Q..~O.g..Nps....|
+00000200  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
+00000210  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
+00000220  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
+00000230  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
+00000240  a6 b5 68 1a 41 03 56 6b  dc 5a 89 16 03 03 00 88  |..h.A.Vk.Z......|
+00000250  0f 00 00 84 04 01 00 80  38 f2 16 e5 b5 86 16 62  |........8......b|
+00000260  86 e1 7d 01 f1 a8 e1 f7  e7 85 b1 a0 17 ee 84 25  |..}............%|
+00000270  cb 3c 46 61 1a 78 7b 1e  ee 32 bc d9 6c fa 6b 76  |.<Fa.x{..2..l.kv|
+00000280  67 a7 9e c8 7a 4c e8 79  0d 22 27 ad e7 98 6a 98  |g...zL.y."'...j.|
+00000290  89 88 8b a9 69 5b 6f c6  00 48 9a 21 77 a9 7c 15  |....i[o..H.!w.|.|
+000002a0  ba 47 16 74 8d 6c 67 dc  6d f1 98 b6 61 e8 bc 08  |.G.t.lg.m...a...|
+000002b0  18 53 a6 93 bf fc 27 5e  b7 4d d2 eb 68 e9 23 ee  |.S....'^.M..h.#.|
+000002c0  d2 70 d2 55 2c c7 99 7d  c0 66 b5 1c ea 38 71 5c  |.p.U,..}.f...8q\|
+000002d0  a6 57 1f 52 e4 8e e8 51  14 03 03 00 01 01 16 03  |.W.R...Q........|
+000002e0  03 00 40 00 00 00 00 00  00 00 00 00 00 00 00 00  |..@.............|
+000002f0  00 00 00 5e e7 6e 1c a2  02 24 34 f0 a6 b6 27 ea  |...^.n...$4...'.|
+00000300  69 d5 0e 2e a8 ad 5c ad  6c 06 78 68 39 92 27 f1  |i.....\.l.xh9.'.|
+00000310  e8 35 49 67 4d fb 5d 8a  31 2e 4e 3f 19 ed ea 30  |.5IgM.].1.N?...0|
+00000320  20 60 e1                                          | `.|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 40 ee a8 82 bc 3f  |..........@....?|
+00000010  bf ab a6 e4 30 e0 3d f1  2f 19 a2 ac 7a 81 57 f1  |....0.=./...z.W.|
+00000020  ee 67 3f 55 2b 30 fa 72  b5 10 03 ec 8d 0a 8f bb  |.g?U+0.r........|
+00000030  24 f5 45 f5 4e 53 4b 93  a5 0d 42 6c 46 69 98 fb  |$.E.NSK...BlFi..|
+00000040  63 c5 9f 95 65 d1 b6 f0  a4 15 bd                 |c...e......|
+>>> Flow 5 (client to server)
+00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+00000010  00 00 00 00 00 cb 4e bc  d1 a9 58 ef c8 39 a9 36  |......N...X..9.6|
+00000020  f4 35 05 96 8e a4 50 bc  f4 15 06 f9 fd 41 6d 1e  |.5....P......Am.|
+00000030  5e 7c 82 63 94 15 03 03  00 30 00 00 00 00 00 00  |^|.c.....0......|
+00000040  00 00 00 00 00 00 00 00  00 00 bd 77 87 a5 5a d4  |...........w..Z.|
+00000050  b8 59 e6 6b 0f dd ea f9  ed 18 b2 9f a9 61 b4 3a  |.Y.k.........a.:|
+00000060  47 15 15 3b 83 ef e1 6d  db a8                    |G..;...m..|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
new file mode 100644
index 0000000..df3eaa4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
@@ -0,0 +1,126 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 51 02 00 00  4d 03 03 53 04 f1 02 1d  |....Q...M..S....|
+00000010  0e dc 86 e5 a9 07 71 46  15 34 af 47 15 3f 03 9c  |......qF.4.G.?..|
+00000020  fc d6 fd 44 7c f4 f1 c7  8d 6f f8 20 28 ea 3c dc  |...D|....o. (.<.|
+00000030  b2 4c b7 ba 20 88 c4 db  a5 73 ea 93 ab 3a 85 a6  |.L.. ....s...:..|
+00000040  8f 59 49 d9 a9 31 14 d5  a6 2b 4f d1 00 05 00 00  |.YI..1...+O.....|
+00000050  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 30 0d 00  |n8P)l........0..|
+00000320  00 28 03 01 02 40 00 20  06 01 06 02 06 03 05 01  |.(...@. ........|
+00000330  05 02 05 03 04 01 04 02  04 03 03 01 03 02 03 03  |................|
+00000340  02 01 02 02 02 03 01 01  00 00 0e 00 00 00        |..............|
+>>> Flow 3 (client to server)
+00000000  16 03 03 01 fb 0b 00 01  f7 00 01 f4 00 01 f1 30  |...............0|
+00000010  82 01 ed 30 82 01 58 a0  03 02 01 02 02 01 00 30  |...0..X........0|
+00000020  0b 06 09 2a 86 48 86 f7  0d 01 01 05 30 26 31 10  |...*.H......0&1.|
+00000030  30 0e 06 03 55 04 0a 13  07 41 63 6d 65 20 43 6f  |0...U....Acme Co|
+00000040  31 12 30 10 06 03 55 04  03 13 09 31 32 37 2e 30  |1.0...U....127.0|
+00000050  2e 30 2e 31 30 1e 17 0d  31 31 31 32 30 38 30 37  |.0.10...11120807|
+00000060  35 35 31 32 5a 17 0d 31  32 31 32 30 37 30 38 30  |5512Z..121207080|
+00000070  30 31 32 5a 30 26 31 10  30 0e 06 03 55 04 0a 13  |012Z0&1.0...U...|
+00000080  07 41 63 6d 65 20 43 6f  31 12 30 10 06 03 55 04  |.Acme Co1.0...U.|
+00000090  03 13 09 31 32 37 2e 30  2e 30 2e 31 30 81 9c 30  |...127.0.0.10..0|
+000000a0  0b 06 09 2a 86 48 86 f7  0d 01 01 01 03 81 8c 00  |...*.H..........|
+000000b0  30 81 88 02 81 80 4e d0  7b 31 e3 82 64 d9 59 c0  |0.....N.{1..d.Y.|
+000000c0  c2 87 a4 5e 1e 8b 73 33  c7 63 53 df 66 92 06 84  |...^..s3.cS.f...|
+000000d0  f6 64 d5 8f e4 36 a7 1d  2b e8 b3 20 36 45 23 b5  |.d...6..+.. 6E#.|
+000000e0  e3 95 ae ed e0 f5 20 9c  8d 95 df 7f 5a 12 ef 87  |...... .....Z...|
+000000f0  e4 5b 68 e4 e9 0e 74 ec  04 8a 7f de 93 27 c4 01  |.[h...t......'..|
+00000100  19 7a bd f2 dc 3d 14 ab  d0 54 ca 21 0c d0 4d 6e  |.z...=...T.!..Mn|
+00000110  87 2e 5c c5 d2 bb 4d 4b  4f ce b6 2c f7 7e 88 ec  |..\...MKO..,.~..|
+00000120  7c d7 02 91 74 a6 1e 0c  1a da e3 4a 5a 2e de 13  ||...t......JZ...|
+00000130  9c 4c 40 88 59 93 02 03  01 00 01 a3 32 30 30 30  |.L@.Y.......2000|
+00000140  0e 06 03 55 1d 0f 01 01  ff 04 04 03 02 00 a0 30  |...U...........0|
+00000150  0d 06 03 55 1d 0e 04 06  04 04 01 02 03 04 30 0f  |...U..........0.|
+00000160  06 03 55 1d 23 04 08 30  06 80 04 01 02 03 04 30  |..U.#..0.......0|
+00000170  0b 06 09 2a 86 48 86 f7  0d 01 01 05 03 81 81 00  |...*.H..........|
+00000180  36 1f b3 7a 0c 75 c9 6e  37 46 61 2b d5 bd c0 a7  |6..z.u.n7Fa+....|
+00000190  4b cc 46 9a 81 58 7c 85  79 29 c8 c8 c6 67 dd 32  |K.F..X|.y)...g.2|
+000001a0  56 45 2b 75 b6 e9 24 a9  50 9a be 1f 5a fa 1a 15  |VE+u..$.P...Z...|
+000001b0  d9 cc 55 95 72 16 83 b9  c2 b6 8f fd 88 8c 38 84  |..U.r.........8.|
+000001c0  1d ab 5d 92 31 13 4f fd  83 3b c6 9d f1 11 62 b6  |..].1.O..;....b.|
+000001d0  8b ec ab 67 be c8 64 b0  11 50 46 58 17 6b 99 1c  |...g..d..PFX.k..|
+000001e0  d3 1d fc 06 f1 0e e5 96  a8 0c f9 78 20 b7 44 18  |...........x .D.|
+000001f0  51 8d 10 7e 4f 94 67 df  a3 4e 70 73 8e 90 91 85  |Q..~O.g..Nps....|
+00000200  16 03 03 00 86 10 00 00  82 00 80 6d 51 f3 7f f9  |...........mQ...|
+00000210  3e fb 75 82 41 36 83 e8  6a ee 2a 2e 25 90 67 4c  |>.u.A6..j.*.%.gL|
+00000220  8e 62 2f 30 81 17 e0 85  09 0c 2b b7 23 d7 b0 e2  |.b/0......+.#...|
+00000230  1d f7 3b d7 f5 a1 27 b6  ee 24 b6 1b cc 5b ea 66  |..;...'..$...[.f|
+00000240  0d 6a f4 e5 85 f9 da 43  b4 0e 86 85 e1 f5 aa be  |.j.....C........|
+00000250  c8 ce 39 4c 9c 86 00 08  c2 4b e2 c6 ec 2f f7 ce  |..9L.....K.../..|
+00000260  e6 bd 77 82 6f 23 b6 e0  bd a2 92 b7 3a ac e8 56  |..w.o#......:..V|
+00000270  f1 af 54 5e 46 87 e9 3b  33 e7 b8 28 b7 d6 c8 90  |..T^F..;3..(....|
+00000280  35 d4 1c 43 d1 30 6f 55  4e 0a 70 16 03 03 00 88  |5..C.0oUN.p.....|
+00000290  0f 00 00 84 04 01 00 80  2a 1f ae 48 9f 86 16 dc  |........*..H....|
+000002a0  c2 55 1f 5f 95 81 ed 56  00 5d 35 46 e5 b6 57 d5  |.U._...V.]5F..W.|
+000002b0  a6 3e 32 38 8b e2 c6 1c  b9 b1 38 b2 da 66 45 ed  |.>28......8..fE.|
+000002c0  58 6a 7f 43 41 93 a5 09  da b9 04 ce 3f 13 8a 19  |Xj.CA.......?...|
+000002d0  13 e9 2c 1f c5 e7 35 b4  2d ea 7c 81 90 33 c0 66  |..,...5.-.|..3.f|
+000002e0  dc 41 8b 23 08 8f 69 d4  d6 a2 5f c1 bd 26 e6 2e  |.A.#..i..._..&..|
+000002f0  7f c8 7c a8 2d d4 08 95  ce 6e 58 54 04 a2 a6 63  |..|.-....nXT...c|
+00000300  54 72 67 f2 7f 61 0a 6b  58 46 d4 88 95 38 37 f2  |Trg..a.kXF...87.|
+00000310  93 95 48 56 14 a7 b9 7c  14 03 03 00 01 01 16 03  |..HV...|........|
+00000320  03 00 24 64 bb 41 3a cb  a2 2f 95 53 5c 2f f7 83  |..$d.A:../.S\/..|
+00000330  a2 35 18 f6 d0 8d 6f e2  54 ed 2f 07 10 f4 36 e2  |.5....o.T./...6.|
+00000340  3d e5 30 1d e3 63 01                              |=.0..c.|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 24 0a 22 b6 bc da  |..........$."...|
+00000010  34 38 53 8e 80 e2 25 7b  31 2f 70 8e 3a db e8 a3  |48S...%{1/p.:...|
+00000020  70 0e 88 22 b4 a8 be d4  a3 e3 cc 13 94 ef 47     |p.."..........G|
+>>> Flow 5 (client to server)
+00000000  17 03 03 00 1a b4 9c b1  57 ea 01 03 fe 01 e7 1e  |........W.......|
+00000010  c4 a7 0f 25 14 99 00 4f  88 51 c1 98 6e 99 01 15  |...%...O.Q..n...|
+00000020  03 03 00 16 2e c4 11 8b  1a fc 37 81 18 33 e4 9f  |..........7..3..|
+00000030  48 a3 29 e3 ad 9b 9b ec  9f 99                    |H.).......|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
new file mode 100644
index 0000000..7644590
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
@@ -0,0 +1,89 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 59 02 00 00  55 03 03 53 04 f1 02 a0  |....Y...U..S....|
+00000010  5f bd a4 8d 98 93 b8 da  08 86 9f b2 be 9a a4 91  |_...............|
+00000020  2b 3c 1f 18 f0 75 7c a9  a8 a0 f7 20 4a 89 9a d2  |+<...u|.... J...|
+00000030  34 3b d9 b1 c2 fd 61 bd  97 19 22 ce b9 d1 5b a7  |4;....a..."...[.|
+00000040  83 80 9c 19 d0 f5 a0 aa  4c ac 06 20 c0 09 00 00  |........L.. ....|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
+00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
+00000080  30 09 06 07 2a 86 48 ce  3d 04 01 30 45 31 0b 30  |0...*.H.=..0E1.0|
+00000090  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+000000a0  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+000000b0  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+000000c0  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+000000d0  74 64 30 1e 17 0d 31 32  31 31 32 32 31 35 30 36  |td0...1211221506|
+000000e0  33 32 5a 17 0d 32 32 31  31 32 30 31 35 30 36 33  |32Z..22112015063|
+000000f0  32 5a 30 45 31 0b 30 09  06 03 55 04 06 13 02 41  |2Z0E1.0...U....A|
+00000100  55 31 13 30 11 06 03 55  04 08 13 0a 53 6f 6d 65  |U1.0...U....Some|
+00000110  2d 53 74 61 74 65 31 21  30 1f 06 03 55 04 0a 13  |-State1!0...U...|
+00000120  18 49 6e 74 65 72 6e 65  74 20 57 69 64 67 69 74  |.Internet Widgit|
+00000130  73 20 50 74 79 20 4c 74  64 30 81 9b 30 10 06 07  |s Pty Ltd0..0...|
+00000140  2a 86 48 ce 3d 02 01 06  05 2b 81 04 00 23 03 81  |*.H.=....+...#..|
+00000150  86 00 04 00 c4 a1 ed be  98 f9 0b 48 73 36 7e c3  |...........Hs6~.|
+00000160  16 56 11 22 f2 3d 53 c3  3b 4d 21 3d cd 6b 75 e6  |.V.".=S.;M!=.ku.|
+00000170  f6 b0 dc 9a df 26 c1 bc  b2 87 f0 72 32 7c b3 64  |.....&.....r2|.d|
+00000180  2f 1c 90 bc ea 68 23 10  7e fe e3 25 c0 48 3a 69  |/....h#.~..%.H:i|
+00000190  e0 28 6d d3 37 00 ef 04  62 dd 0d a0 9c 70 62 83  |.(m.7...b....pb.|
+000001a0  d8 81 d3 64 31 aa 9e 97  31 bd 96 b0 68 c0 9b 23  |...d1...1...h..#|
+000001b0  de 76 64 3f 1a 5c 7f e9  12 0e 58 58 b6 5f 70 dd  |.vd?.\....XX._p.|
+000001c0  9b d8 ea d5 d7 f5 d5 cc  b9 b6 9f 30 66 5b 66 9a  |...........0f[f.|
+000001d0  20 e2 27 e5 bf fe 3b 30  09 06 07 2a 86 48 ce 3d  | .'...;0...*.H.=|
+000001e0  04 01 03 81 8c 00 30 81  88 02 42 01 88 a2 4f eb  |......0...B...O.|
+000001f0  e2 45 c5 48 7d 1b ac f5  ed 98 9d ae 47 70 c0 5e  |.E.H}.......Gp.^|
+00000200  1b b6 2f bd f1 b6 4d b7  61 40 d3 11 a2 ce ee 0b  |../...M.a@......|
+00000210  7e 92 7e ff 76 9d c3 3b  7e a5 3f ce fa 10 e2 59  |~.~.v..;~.?....Y|
+00000220  ec 47 2d 7c ac da 4e 97  0e 15 a0 6f d0 02 42 01  |.G-|..N....o..B.|
+00000230  4d fc be 67 13 9c 2d 05  0e bd 3f a3 8c 25 c1 33  |M..g..-...?..%.3|
+00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
+00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
+00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
+00000270  2a 16 03 03 00 d7 0c 00  00 d3 03 00 17 41 04 3c  |*............A.<|
+00000280  8f 35 1e 47 5d 7b ad 13  0c e9 5c c0 97 c7 83 06  |.5.G]{....\.....|
+00000290  49 0f 6c cf e5 4d 3b ed  f7 1b c6 96 8d ba 54 35  |I.l..M;.......T5|
+000002a0  7f df 35 e3 6e 28 e9 71  f2 24 b5 ab 17 2b 4b 2b  |..5.n(.q.$...+K+|
+000002b0  0c 8f 9f 48 89 73 8f 09  69 84 af 7f ec 43 7a 04  |...H.s..i....Cz.|
+000002c0  03 00 8a 30 81 87 02 41  79 84 43 0c 78 fa 7e e2  |...0...Ay.C.x.~.|
+000002d0  c5 51 c1 60 88 c4 4a 59  7d 02 fa dc 19 68 33 ed  |.Q.`..JY}....h3.|
+000002e0  19 ef a1 df ef 6b 21 a6  98 aa ba a9 13 70 91 0f  |.....k!......p..|
+000002f0  cc 6c 5c 1e 99 53 1b 42  51 6c 06 a7 3c c4 04 22  |.l\..S.BQl..<.."|
+00000300  5d 0d c1 30 ab e3 ec b4  54 02 42 01 15 15 1a 6e  |]..0....T.B....n|
+00000310  6f f1 c6 b1 10 84 2c c8  04 de 2b 52 d5 b4 f7 c9  |o.....,...+R....|
+00000320  4f 6d 0e 0e 26 45 1d 7a  28 59 2b 8b f6 92 3a 23  |Om..&E.z(Y+...:#|
+00000330  7a 39 9c d5 4e cc 5d c5  45 92 9c d0 5f 33 12 e3  |z9..N.].E..._3..|
+00000340  2b 29 39 52 bb 16 aa e1  72 9e b5 fe 99 16 03 03  |+)9R....r.......|
+00000350  00 04 0e 00 00 00                                 |......|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
+00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
+00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
+00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
+00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
+00000050  01 16 03 03 00 40 00 00  00 00 00 00 00 00 00 00  |.....@..........|
+00000060  00 00 00 00 00 00 20 a3  f8 5a e2 ea f3 09 19 3e  |...... ..Z.....>|
+00000070  4a 54 69 70 06 5b 17 35  0f ed e7 30 3b 6f eb a1  |JTip.[.5...0;o..|
+00000080  cb 9c 35 81 10 2e 34 f7  12 a5 e4 63 20 b2 65 31  |..5...4....c .e1|
+00000090  19 da 30 43 39 59                                 |..0C9Y|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 40 8d 4d 31 07 df  |..........@.M1..|
+00000010  ab 41 f5 19 9c 1a 57 fc  33 ab 5f e6 bd 45 b9 fa  |.A....W.3._..E..|
+00000020  7f db c0 df 72 f2 3b ef  aa d4 5e 34 e6 3d 44 7c  |....r.;...^4.=D||
+00000030  12 05 c7 57 da 54 b1 e3  66 f0 0a ab cd 15 a5 bf  |...W.T..f.......|
+00000040  c5 c2 07 a9 d9 a7 2e 5e  29 da da                 |.......^)..|
+>>> Flow 5 (client to server)
+00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+00000010  00 00 00 00 00 dc 03 7b  29 2c 49 64 58 2d dc f7  |.......{),IdX-..|
+00000020  26 a1 3b ec 2d e8 30 c4  6c a3 ff e2 bc b5 a4 a6  |&.;.-.0.l.......|
+00000030  93 ce 14 bd da 15 03 03  00 30 00 00 00 00 00 00  |.........0......|
+00000040  00 00 00 00 00 00 00 00  00 00 a6 77 10 30 15 eb  |...........w.0..|
+00000050  ed cf 73 5b 74 5d 09 52  4a 5b e2 f0 e4 67 f8 7a  |..s[t].RJ[...g.z|
+00000060  5e 5e fc ba 7f 80 0a d2  f4 fb                    |^^........|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
new file mode 100644
index 0000000..fb5af17
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
@@ -0,0 +1,84 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 59 02 00 00  55 03 03 53 04 f1 02 48  |....Y...U..S...H|
+00000010  03 36 01 05 56 6f f0 54  d2 c3 d3 41 c2 e2 69 7b  |.6..Vo.T...A..i{|
+00000020  50 f8 03 ef 3f 5d 7c e6  9c cb fe 20 82 a0 81 fd  |P...?]|.... ....|
+00000030  72 4b b8 e6 29 76 3b 0f  1d 0a b7 82 9d 0b cf a0  |rK..)v;.........|
+00000040  65 b1 56 53 c9 d5 58 7b  f0 b6 2d cf c0 2b 00 00  |e.VS..X{..-..+..|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
+00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
+00000080  30 09 06 07 2a 86 48 ce  3d 04 01 30 45 31 0b 30  |0...*.H.=..0E1.0|
+00000090  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+000000a0  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+000000b0  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+000000c0  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+000000d0  74 64 30 1e 17 0d 31 32  31 31 32 32 31 35 30 36  |td0...1211221506|
+000000e0  33 32 5a 17 0d 32 32 31  31 32 30 31 35 30 36 33  |32Z..22112015063|
+000000f0  32 5a 30 45 31 0b 30 09  06 03 55 04 06 13 02 41  |2Z0E1.0...U....A|
+00000100  55 31 13 30 11 06 03 55  04 08 13 0a 53 6f 6d 65  |U1.0...U....Some|
+00000110  2d 53 74 61 74 65 31 21  30 1f 06 03 55 04 0a 13  |-State1!0...U...|
+00000120  18 49 6e 74 65 72 6e 65  74 20 57 69 64 67 69 74  |.Internet Widgit|
+00000130  73 20 50 74 79 20 4c 74  64 30 81 9b 30 10 06 07  |s Pty Ltd0..0...|
+00000140  2a 86 48 ce 3d 02 01 06  05 2b 81 04 00 23 03 81  |*.H.=....+...#..|
+00000150  86 00 04 00 c4 a1 ed be  98 f9 0b 48 73 36 7e c3  |...........Hs6~.|
+00000160  16 56 11 22 f2 3d 53 c3  3b 4d 21 3d cd 6b 75 e6  |.V.".=S.;M!=.ku.|
+00000170  f6 b0 dc 9a df 26 c1 bc  b2 87 f0 72 32 7c b3 64  |.....&.....r2|.d|
+00000180  2f 1c 90 bc ea 68 23 10  7e fe e3 25 c0 48 3a 69  |/....h#.~..%.H:i|
+00000190  e0 28 6d d3 37 00 ef 04  62 dd 0d a0 9c 70 62 83  |.(m.7...b....pb.|
+000001a0  d8 81 d3 64 31 aa 9e 97  31 bd 96 b0 68 c0 9b 23  |...d1...1...h..#|
+000001b0  de 76 64 3f 1a 5c 7f e9  12 0e 58 58 b6 5f 70 dd  |.vd?.\....XX._p.|
+000001c0  9b d8 ea d5 d7 f5 d5 cc  b9 b6 9f 30 66 5b 66 9a  |...........0f[f.|
+000001d0  20 e2 27 e5 bf fe 3b 30  09 06 07 2a 86 48 ce 3d  | .'...;0...*.H.=|
+000001e0  04 01 03 81 8c 00 30 81  88 02 42 01 88 a2 4f eb  |......0...B...O.|
+000001f0  e2 45 c5 48 7d 1b ac f5  ed 98 9d ae 47 70 c0 5e  |.E.H}.......Gp.^|
+00000200  1b b6 2f bd f1 b6 4d b7  61 40 d3 11 a2 ce ee 0b  |../...M.a@......|
+00000210  7e 92 7e ff 76 9d c3 3b  7e a5 3f ce fa 10 e2 59  |~.~.v..;~.?....Y|
+00000220  ec 47 2d 7c ac da 4e 97  0e 15 a0 6f d0 02 42 01  |.G-|..N....o..B.|
+00000230  4d fc be 67 13 9c 2d 05  0e bd 3f a3 8c 25 c1 33  |M..g..-...?..%.3|
+00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
+00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
+00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
+00000270  2a 16 03 03 00 d7 0c 00  00 d3 03 00 17 41 04 86  |*............A..|
+00000280  36 b4 78 76 87 70 ed ae  0d 34 70 3d 16 e5 a4 db  |6.xv.p...4p=....|
+00000290  ae 28 58 4c 01 5a 56 73  a7 0d 34 59 a7 04 75 69  |.(XL.ZVs..4Y..ui|
+000002a0  f2 55 24 40 b0 33 c6 93  ff ae e0 14 f5 4b ce a8  |.U$@.3.......K..|
+000002b0  e2 e6 9a 67 1d 66 fb 8f  fd 56 59 e7 73 f2 2c 04  |...g.f...VY.s.,.|
+000002c0  03 00 8a 30 81 87 02 41  73 ab a8 3c 64 17 69 9f  |...0...As..<d.i.|
+000002d0  4d b2 9b 55 12 60 33 94  cf f3 83 40 2b 7b 1b af  |M..U.`3....@+{..|
+000002e0  5c f4 cd 02 66 fb 83 04  35 fd ab 74 98 1a 7d f6  |\...f...5..t..}.|
+000002f0  9e 50 98 c3 98 e8 56 9c  f2 2a b0 30 9d 05 14 58  |.P....V..*.0...X|
+00000300  68 6a 88 04 49 07 78 bf  3a 02 42 01 be b2 05 9e  |hj..I.x.:.B.....|
+00000310  67 da 1e e9 5a 36 98 52  21 9f 43 75 43 ba bb 9a  |g...Z6.R!.CuC...|
+00000320  e6 e2 65 f4 e0 44 45 08  5a 1e 54 06 dd 5f 60 2e  |..e..DE.Z.T.._`.|
+00000330  7d e7 55 08 d3 7b 4e 0a  c7 da d4 27 34 d4 bd b0  |}.U..{N....'4...|
+00000340  12 2f 41 7a ed 71 32 ef  ee 12 74 66 00 16 03 03  |./Az.q2...tf....|
+00000350  00 04 0e 00 00 00                                 |......|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
+00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
+00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
+00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
+00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
+00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 87 7a  |.....(.........z|
+00000060  82 d7 46 25 1d a6 bb c2  a8 a8 4e a5 d1 f8 02 db  |..F%......N.....|
+00000070  33 33 ca 78 b6 d3 bd 77  8a 33 23 a7 95 fb        |33.x...w.3#...|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 28 ce a1 9d 01 c0  |..........(.....|
+00000010  31 e5 d5 57 16 e1 a6 b3  8b 25 58 0f fa 2a de 3e  |1..W.....%X..*.>|
+00000020  0c d9 06 11 a6 b0 d7 b0  33 ad 31 73 5b 26 b4 d2  |........3.1s[&..|
+00000030  12 56 c8                                          |.V.|
+>>> Flow 5 (client to server)
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 d5 04 4c  |...............L|
+00000010  7b 35 b4 d7 90 ae fe 00  d2 f2 4b 76 f1 36 5e 24  |{5........Kv.6^$|
+00000020  4a aa 94 15 03 03 00 1a  00 00 00 00 00 00 00 02  |J...............|
+00000030  d3 1c 41 37 ab f6 17 79  f0 01 a4 19 a5 75 7a 8e  |..A7...y.....uz.|
+00000040  a3 b2                                             |..|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
new file mode 100644
index 0000000..5336bbb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
@@ -0,0 +1,99 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 59 02 00 00  55 03 03 53 04 f1 02 41  |....Y...U..S...A|
+00000010  95 cc 56 30 65 46 24 75  d5 9e 3c a7 5b 6c 99 fe  |..V0eF$u..<.[l..|
+00000020  86 35 23 42 3a 8f 4d 4c  b9 98 7d 20 a7 46 43 72  |.5#B:.ML..} .FCr|
+00000030  66 bb b6 ad ff ad cf 63  37 fe 6b b4 78 94 08 49  |f......c7.k.x..I|
+00000040  54 06 ed f4 85 73 38 4a  c6 fe b6 98 c0 13 00 00  |T....s8J........|
+00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
+00000060  03 02 be 0b 00 02 ba 00  02 b7 00 02 b4 30 82 02  |.............0..|
+00000070  b0 30 82 02 19 a0 03 02  01 02 02 09 00 85 b0 bb  |.0..............|
+00000080  a4 8a 7f b8 ca 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
+00000090  01 05 05 00 30 45 31 0b  30 09 06 03 55 04 06 13  |....0E1.0...U...|
+000000a0  02 41 55 31 13 30 11 06  03 55 04 08 13 0a 53 6f  |.AU1.0...U....So|
+000000b0  6d 65 2d 53 74 61 74 65  31 21 30 1f 06 03 55 04  |me-State1!0...U.|
+000000c0  0a 13 18 49 6e 74 65 72  6e 65 74 20 57 69 64 67  |...Internet Widg|
+000000d0  69 74 73 20 50 74 79 20  4c 74 64 30 1e 17 0d 31  |its Pty Ltd0...1|
+000000e0  30 30 34 32 34 30 39 30  39 33 38 5a 17 0d 31 31  |00424090938Z..11|
+000000f0  30 34 32 34 30 39 30 39  33 38 5a 30 45 31 0b 30  |0424090938Z0E1.0|
+00000100  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
+00000110  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
+00000120  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
+00000130  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
+00000140  74 64 30 81 9f 30 0d 06  09 2a 86 48 86 f7 0d 01  |td0..0...*.H....|
+00000150  01 01 05 00 03 81 8d 00  30 81 89 02 81 81 00 bb  |........0.......|
+00000160  79 d6 f5 17 b5 e5 bf 46  10 d0 dc 69 be e6 2b 07  |y......F...i..+.|
+00000170  43 5a d0 03 2d 8a 7a 43  85 b7 14 52 e7 a5 65 4c  |CZ..-.zC...R..eL|
+00000180  2c 78 b8 23 8c b5 b4 82  e5 de 1f 95 3b 7e 62 a5  |,x.#........;~b.|
+00000190  2c a5 33 d6 fe 12 5c 7a  56 fc f5 06 bf fa 58 7b  |,.3...\zV.....X{|
+000001a0  26 3f b5 cd 04 d3 d0 c9  21 96 4a c7 f4 54 9f 5a  |&?......!.J..T.Z|
+000001b0  bf ef 42 71 00 fe 18 99  07 7f 7e 88 7d 7d f1 04  |..Bq......~.}}..|
+000001c0  39 c4 a2 2e db 51 c9 7c  e3 c0 4c 3b 32 66 01 cf  |9....Q.|..L;2f..|
+000001d0  af b1 1d b8 71 9a 1d db  db 89 6b ae da 2d 79 02  |....q.....k..-y.|
+000001e0  03 01 00 01 a3 81 a7 30  81 a4 30 1d 06 03 55 1d  |.......0..0...U.|
+000001f0  0e 04 16 04 14 b1 ad e2  85 5a cf cb 28 db 69 ce  |.........Z..(.i.|
+00000200  23 69 de d3 26 8e 18 88  39 30 75 06 03 55 1d 23  |#i..&...90u..U.#|
+00000210  04 6e 30 6c 80 14 b1 ad  e2 85 5a cf cb 28 db 69  |.n0l......Z..(.i|
+00000220  ce 23 69 de d3 26 8e 18  88 39 a1 49 a4 47 30 45  |.#i..&...9.I.G0E|
+00000230  31 0b 30 09 06 03 55 04  06 13 02 41 55 31 13 30  |1.0...U....AU1.0|
+00000240  11 06 03 55 04 08 13 0a  53 6f 6d 65 2d 53 74 61  |...U....Some-Sta|
+00000250  74 65 31 21 30 1f 06 03  55 04 0a 13 18 49 6e 74  |te1!0...U....Int|
+00000260  65 72 6e 65 74 20 57 69  64 67 69 74 73 20 50 74  |ernet Widgits Pt|
+00000270  79 20 4c 74 64 82 09 00  85 b0 bb a4 8a 7f b8 ca  |y Ltd...........|
+00000280  30 0c 06 03 55 1d 13 04  05 30 03 01 01 ff 30 0d  |0...U....0....0.|
+00000290  06 09 2a 86 48 86 f7 0d  01 01 05 05 00 03 81 81  |..*.H...........|
+000002a0  00 08 6c 45 24 c7 6b b1  59 ab 0c 52 cc f2 b0 14  |..lE$.k.Y..R....|
+000002b0  d7 87 9d 7a 64 75 b5 5a  95 66 e4 c5 2b 8e ae 12  |...zdu.Z.f..+...|
+000002c0  66 1f eb 4f 38 b3 6e 60  d3 92 fd f7 41 08 b5 25  |f..O8.n`....A..%|
+000002d0  13 b1 18 7a 24 fb 30 1d  ba ed 98 b9 17 ec e7 d7  |...z$.0.........|
+000002e0  31 59 db 95 d3 1d 78 ea  50 56 5c d5 82 5a 2d 5a  |1Y....x.PV\..Z-Z|
+000002f0  5f 33 c4 b6 d8 c9 75 90  96 8c 0f 52 98 b5 cd 98  |_3....u....R....|
+00000300  1f 89 20 5f f2 a0 1c a3  1b 96 94 dd a9 fd 57 e9  |.. _..........W.|
+00000310  70 e8 26 6d 71 99 9b 26  6e 38 50 29 6c 90 a7 bd  |p.&mq..&n8P)l...|
+00000320  d9 16 03 03 00 cd 0c 00  00 c9 03 00 17 41 04 48  |.............A.H|
+00000330  68 d8 8a 10 b4 bf eb 8d  d1 98 b0 a6 f4 47 5d 91  |h............G].|
+00000340  61 da 50 d9 85 7b 5d 90  02 2c 38 c9 af 81 d3 55  |a.P..{]..,8....U|
+00000350  07 62 b1 62 58 7f 39 94  d7 91 96 a8 1f 47 60 a5  |.b.bX.9......G`.|
+00000360  c0 04 f2 fb cb 15 75 a6  16 3f 94 53 7c ff dd 04  |......u..?.S|...|
+00000370  01 00 80 b9 82 fa 0b f8  8c 94 2c 6e 05 81 7d 80  |..........,n..}.|
+00000380  5d 9a 77 78 af c8 33 5d  89 7e 2e 3c e5 72 66 a8  |].wx..3].~.<.rf.|
+00000390  f1 5c 02 04 02 70 76 7b  45 ff 0d 29 a0 cb 0d db  |.\...pv{E..)....|
+000003a0  7a 4c c4 13 19 cd 47 b2  f1 c9 43 4f 95 d2 f1 c6  |zL....G...CO....|
+000003b0  bc ae 31 4a 9d de 80 b2  a4 b7 b6 dd 8c 03 3e 2a  |..1J..........>*|
+000003c0  46 5e d1 e7 5b c5 9e 06  58 f3 55 b2 77 09 f3 98  |F^..[...X.U.w...|
+000003d0  d5 7f 5a 74 64 7e 48 22  8f 7d a8 68 b6 1d 90 df  |..Ztd~H".}.h....|
+000003e0  2c 91 d7 c5 07 3d d1 6f  e9 c1 91 03 3c 23 5a 56  |,....=.o....<#ZV|
+000003f0  3b b2 c2 16 03 03 00 04  0e 00 00 00              |;...........|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
+00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
+00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
+00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
+00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
+00000050  01 16 03 03 00 40 00 00  00 00 00 00 00 00 00 00  |.....@..........|
+00000060  00 00 00 00 00 00 59 e6  92 05 27 ec 09 2c b0 a5  |......Y...'..,..|
+00000070  2a fb 7e f1 03 53 16 63  68 a1 86 13 bb da 98 27  |*.~..S.ch......'|
+00000080  6d 42 08 35 6a ec 58 61  2a 4d 44 ec ae c5 b9 d2  |mB.5j.Xa*MD.....|
+00000090  76 57 1f 75 9f 8d                                 |vW.u..|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 40 6e 03 d0 e6 98  |..........@n....|
+00000010  1f f5 39 7b 06 9f 95 f0  7a 88 35 7c 55 db c3 2f  |..9{....z.5|U../|
+00000020  00 ef 5b d3 62 87 a2 94  da 2f f6 4a 89 c9 a8 3d  |..[.b..../.J...=|
+00000030  3a 92 db 77 35 92 01 4b  f5 c5 6b 95 09 9f cd 79  |:..w5..K..k....y|
+00000040  3c af 37 5b 27 bf 93 3e  04 55 71                 |<.7['..>.Uq|
+>>> Flow 5 (client to server)
+00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+00000010  00 00 00 00 00 bc c9 d0  8e 80 14 de 32 18 49 e8  |............2.I.|
+00000020  20 dc 5e 6c e4 6d 14 00  df 51 71 fb 86 95 16 4c  | .^l.m...Qq....L|
+00000030  04 8e 71 e1 48 15 03 03  00 30 00 00 00 00 00 00  |..q.H....0......|
+00000040  00 00 00 00 00 00 00 00  00 00 b7 6d 30 72 61 53  |...........m0raS|
+00000050  d8 0a d4 1d ae e5 d4 22  46 c9 d5 4e 4a 86 f5 ac  |......."F..NJ...|
+00000060  72 98 c6 db 38 29 97 2c  84 0b                    |r...8).,..|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4
new file mode 100644
index 0000000..0377f05
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4
@@ -0,0 +1,83 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 75 01 00 00  71 03 03 00 00 00 00 00  |....u...q.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1a c0 2f  |.............../|
+00000030  c0 2b c0 11 c0 07 c0 13  c0 09 c0 14 c0 0a 00 05  |.+..............|
+00000040  00 2f 00 35 c0 12 00 0a  01 00 00 2e 00 05 00 05  |./.5............|
+00000050  01 00 00 00 00 00 0a 00  08 00 06 00 17 00 18 00  |................|
+00000060  19 00 0b 00 02 01 00 00  0d 00 0a 00 08 04 01 04  |................|
+00000070  03 02 01 02 03 ff 01 00  01 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 51 02 00 00  4d 03 03 53 04 f1 02 9d  |....Q...M..S....|
+00000010  2e 4e d9 17 4a 35 fa 9d  94 f6 45 0a f6 6b 5d 1c  |.N..J5....E..k].|
+00000020  1e 15 19 8d 6d 94 cc 90  d9 39 94 20 8b 4b de 76  |....m....9. .K.v|
+00000030  d5 64 5d b7 19 df e7 eb  7e a0 22 c4 09 38 a0 12  |.d].....~."..8..|
+00000040  d5 59 10 c8 31 06 dc fc  e4 9d d1 80 00 05 00 00  |.Y..1...........|
+00000050  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 04 0e 00  |n8P)l...........|
+00000320  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 86 10 00 00  82 00 80 6d 51 f3 7f f9  |...........mQ...|
+00000010  3e fb 75 82 41 36 83 e8  6a ee 2a 2e 25 90 67 4c  |>.u.A6..j.*.%.gL|
+00000020  8e 62 2f 30 81 17 e0 85  09 0c 2b b7 23 d7 b0 e2  |.b/0......+.#...|
+00000030  1d f7 3b d7 f5 a1 27 b6  ee 24 b6 1b cc 5b ea 66  |..;...'..$...[.f|
+00000040  0d 6a f4 e5 85 f9 da 43  b4 0e 86 85 e1 f5 aa be  |.j.....C........|
+00000050  c8 ce 39 4c 9c 86 00 08  c2 4b e2 c6 ec 2f f7 ce  |..9L.....K.../..|
+00000060  e6 bd 77 82 6f 23 b6 e0  bd a2 92 b7 3a ac e8 56  |..w.o#......:..V|
+00000070  f1 af 54 5e 46 87 e9 3b  33 e7 b8 28 b7 d6 c8 90  |..T^F..;3..(....|
+00000080  35 d4 1c 43 d1 30 6f 55  4e 0a 70 14 03 03 00 01  |5..C.0oUN.p.....|
+00000090  01 16 03 03 00 24 37 14  b2 97 7b b5 f0 9a 38 05  |.....$7...{...8.|
+000000a0  22 35 69 9c 95 2f 86 4b  37 98 22 db 4e 9a 46 9c  |"5i../.K7.".N.F.|
+000000b0  b9 81 74 72 58 18 53 0c  5c 3c                    |..trX.S.\<|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 24 3c b3 e7 77 5a  |..........$<..wZ|
+00000010  7c 36 5a 74 74 26 8d 5b  5a 09 96 60 e8 24 45 2f  ||6Ztt&.[Z..`.$E/|
+00000020  c2 39 14 5e db 58 12 49  ad a8 b6 ea ef 58 16     |.9.^.X.I.....X.|
+>>> Flow 5 (client to server)
+00000000  17 03 03 00 1a 6d 29 d7  ba 2f 85 02 b6 f0 82 64  |.....m)../.....d|
+00000010  6c 55 ae ab f6 fd 14 ff  b8 38 f0 f8 a6 ea cc 15  |lU.......8......|
+00000020  03 03 00 16 10 c5 d9 41  7b e2 89 67 dc 29 8e f8  |.......A{..g.)..|
+00000030  b5 ab 32 91 44 2c 27 84  49 f7                    |..2.D,'.I.|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES
new file mode 100644
index 0000000..a6c7a41
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES
@@ -0,0 +1,83 @@
+>>> Flow 1 (client to server)
+00000000  16 03 00 00 2f 01 00 00  2b 03 00 52 cc 57 59 d8  |..../...+..R.WY.|
+00000010  86 d6 07 ae e0 8d 63 b7  1e cb aa c6 67 32 c8 dd  |......c.....g2..|
+00000020  68 03 d8 3d 37 18 72 c3  c0 f1 9d 00 00 04 00 0a  |h..=7.r.........|
+00000030  00 ff 01 00                                       |....|
+>>> Flow 2 (server to client)
+00000000  16 03 00 00 31 02 00 00  2d 03 00 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 0a 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  00 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 00 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 00 00 84 10 00 00  80 75 e0 c9 76 d6 e9 34  |.........u..v..4|
+00000010  1d e3 31 9e db 3b 03 41  93 e8 db 73 7c e9 3f 6a  |..1..;.A...s|.?j|
+00000020  d8 2a 7b 25 83 4f 45 de  3f 78 3f b6 53 a7 b4 6c  |.*{%.OE.?x?.S..l|
+00000030  e3 87 c4 c3 70 55 71 79  55 dc 74 98 84 21 19 13  |....pUqyU.t..!..|
+00000040  be d5 8e 0a ff 2f 9f 7a  6b d4 6c ef 78 d1 cb 65  |...../.zk.l.x..e|
+00000050  32 4c 0c c5 29 b9 60 94  c6 79 56 a2 aa 2d d9 ad  |2L..).`..yV..-..|
+00000060  51 2c 54 1b 28 23 33 54  cd 48 cb 80 13 45 3d 4a  |Q,T.(#3T.H...E=J|
+00000070  8e 2f f2 da bd 68 3e 1b  eb 73 f9 2d 35 6b b1 40  |./...h>..s.-5k.@|
+00000080  2e 6d 9d 1c e9 c1 02 80  37 14 03 00 00 01 01 16  |.m......7.......|
+00000090  03 00 00 40 f7 c3 dd a4  64 3d 81 24 de a2 81 7d  |...@....d=.$...}|
+000000a0  e4 df 78 46 e7 ba 93 6c  36 43 05 96 fc 75 ef ec  |..xF...l6C...u..|
+000000b0  a5 46 6d 47 a5 be 74 ad  15 93 d9 87 4f 1d e2 b3  |.FmG..t.....O...|
+000000c0  03 ff 2e 89 6e 50 f4 d6  a6 e2 b3 54 cb 74 07 f7  |....nP.....T.t..|
+000000d0  ca 1b 8c 0a                                       |....|
+>>> Flow 4 (server to client)
+00000000  14 03 00 00 01 01 16 03  00 00 40 6d 3d d8 d5 cf  |..........@m=...|
+00000010  05 7d 98 8c 28 28 e2 43  ab ad 4a fa ae bf ec c3  |.}..((.C..J.....|
+00000020  9c 0a 13 4d 28 a4 45 c4  b9 f2 bc c5 12 a2 68 91  |...M(.E.......h.|
+00000030  77 fa 72 f8 9e 4e b7 1f  b4 02 02 e3 5d 57 b0 8b  |w.r..N......]W..|
+00000040  d8 90 0c 9d e6 df 5b 90  92 a1 0d 17 03 00 00 18  |......[.........|
+00000050  91 48 8a e1 d6 bf 79 1c  d5 0a 70 d5 94 20 25 78  |.H....y...p.. %x|
+00000060  d8 84 c8 6e 54 f0 99 01  17 03 00 00 28 74 19 90  |...nT.......(t..|
+00000070  41 44 53 27 bb fb 1f fd  71 34 20 61 a0 eb a4 7c  |ADS'....q4 a...||
+00000080  fe 36 f8 4b d7 b0 27 d3  b9 36 e1 67 af 2d 0e 23  |.6.K..'..6.g.-.#|
+00000090  2b 76 a7 2f c3 15 03 00  00 18 db fc e9 fd 87 5f  |+v./..........._|
+000000a0  92 a8 3d 4b 35 f5 c6 48  2c b4 42 50 c3 81 28 f0  |..=K5..H,.BP..(.|
+000000b0  2b 41                                             |+A|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES
new file mode 100644
index 0000000..4885b26
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES
@@ -0,0 +1,84 @@
+>>> Flow 1 (client to server)
+00000000  16 03 00 00 2f 01 00 00  2b 03 00 52 cc 57 59 30  |..../...+..R.WY0|
+00000010  e1 ee 8c 60 5b 40 dd 95  bd b4 84 87 2f 01 15 e7  |...`[@....../...|
+00000020  50 88 4c 82 6b 6d 93 8a  57 d0 27 00 00 04 00 2f  |P.L.km..W.'..../|
+00000030  00 ff 01 00                                       |....|
+>>> Flow 2 (server to client)
+00000000  16 03 00 00 31 02 00 00  2d 03 00 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 2f 00 00  |............./..|
+00000030  05 ff 01 00 01 00 16 03  00 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 00 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 00 00 84 10 00 00  80 74 50 05 6f f5 83 c9  |.........tP.o...|
+00000010  f5 0c 5a 65 c7 4e c6 f3  87 96 d7 5d 3e 88 27 32  |..Ze.N.....]>.'2|
+00000020  89 12 ba ec db ef c0 85  70 84 ed b6 83 03 8f 44  |........p......D|
+00000030  f5 6f fa fa d0 1f 95 30  d1 ae a7 71 cf ee e9 b1  |.o.....0...q....|
+00000040  80 7b 34 a9 ea 1b 5e e5  71 40 3f e8 7d 30 d1 8b  |.{4...^.q@?.}0..|
+00000050  11 f1 68 1f c8 25 f0 77  c5 af b3 92 6e d9 81 cc  |..h..%.w....n...|
+00000060  f8 fd 82 95 cc 1f 4a b1  05 15 7a b3 a1 22 33 09  |......J...z.."3.|
+00000070  e7 a5 c2 89 7f 03 e0 91  b6 61 a3 a0 4e 17 0d 7a  |.........a..N..z|
+00000080  13 01 c4 b6 50 c7 d9 81  15 14 03 00 00 01 01 16  |....P...........|
+00000090  03 00 00 40 56 da 56 ab  e6 26 98 58 53 1f 36 b5  |...@V.V..&.XS.6.|
+000000a0  03 14 bd 42 29 ee 9c 7c  e4 48 26 82 68 ae fd fe  |...B)..|.H&.h...|
+000000b0  5e a4 43 22 75 95 7b c8  77 88 fd d6 d4 9b c9 b5  |^.C"u.{.w.......|
+000000c0  ee 3e a6 e8 c5 04 90 63  3f ac be 56 67 da 30 d4  |.>.....c?..Vg.0.|
+000000d0  64 fb a8 a0                                       |d...|
+>>> Flow 4 (server to client)
+00000000  14 03 00 00 01 01 16 03  00 00 40 96 af fb 79 96  |..........@...y.|
+00000010  92 97 2d d0 67 46 1e 08  b5 35 65 ef dc bc 8e 57  |..-.gF...5e....W|
+00000020  53 b7 36 58 74 d7 88 b1  55 fc eb fa 2e f3 17 b7  |S.6Xt...U.......|
+00000030  62 58 a0 9d 99 e1 85 d4  33 e0 b4 1f 1d 94 f2 88  |bX......3.......|
+00000040  d5 9a 34 5b 74 cd d2 ff  87 bd 52 17 03 00 00 20  |..4[t.....R.... |
+00000050  c6 61 c2 28 ac d2 0c 08  7f f1 c2 62 af 37 7e 78  |.a.(.......b.7~x|
+00000060  e8 e2 a1 54 f2 3a 80 97  f8 47 64 f2 cd 94 dd 0b  |...T.:...Gd.....|
+00000070  17 03 00 00 30 b8 40 8f  a3 18 ff 03 84 d4 1c 28  |....0.@........(|
+00000080  82 ce d8 9a 81 3a dd 23  7c 65 d8 ca f7 f1 46 1b  |.....:.#|e....F.|
+00000090  70 f0 d7 d9 54 a7 71 e6  4d d4 25 61 5a e4 30 d3  |p...T.q.M.%aZ.0.|
+000000a0  4a 42 ae 26 a5 15 03 00  00 20 c4 e8 ed 40 57 00  |JB.&..... ...@W.|
+000000b0  dc a5 0e 82 90 47 92 08  dd 7e 50 6b 30 66 5e 90  |.....G...~Pk0f^.|
+000000c0  73 7c 81 93 8d 24 b1 06  e7 39                    |s|...$...9|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4 b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4
new file mode 100644
index 0000000..1314b65
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4
@@ -0,0 +1,79 @@
+>>> Flow 1 (client to server)
+00000000  16 03 00 00 2f 01 00 00  2b 03 00 52 cc 57 59 79  |..../...+..R.WYy|
+00000010  b9 3b ef df 53 fb 09 f6  01 e5 18 0a fc 3d 65 bb  |.;..S........=e.|
+00000020  cf 9c 4c 77 b1 e8 6b 4f  5f c7 94 00 00 04 00 05  |..Lw..kO_.......|
+00000030  00 ff 01 00                                       |....|
+>>> Flow 2 (server to client)
+00000000  16 03 00 00 31 02 00 00  2d 03 00 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 05 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  00 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 00 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 00 00 84 10 00 00  80 4d 66 7a f3 f8 ab 86  |.........Mfz....|
+00000010  43 4c 5f 7c 52 ca e7 3f  ba 62 b3 82 88 16 7d ca  |CL_|R..?.b....}.|
+00000020  3a 66 15 c0 36 55 2c ab  bf 30 6b cd 9c d8 b9 48  |:f..6U,..0k....H|
+00000030  03 c9 d0 98 ab 0b a6 5b  39 c8 fe 82 8e bb f0 16  |.......[9.......|
+00000040  6f 96 62 81 f2 dc 52 02  c9 de e4 47 73 21 6e 1e  |o.b...R....Gs!n.|
+00000050  3a 11 89 7a e2 6b 9e 04  64 72 15 ba 2d 10 a2 69  |:..z.k..dr..-..i|
+00000060  07 e6 ba 17 cf 54 d6 4e  5f 99 e8 59 8b 54 ce 8e  |.....T.N_..Y.T..|
+00000070  6b 58 ba 83 68 46 4a 5f  43 3e 9b e1 32 a2 19 42  |kX..hFJ_C>..2..B|
+00000080  46 0f e4 47 1a 3b 16 5f  e1 14 03 00 00 01 01 16  |F..G.;._........|
+00000090  03 00 00 3c 78 7e ee da  0d 38 0b 1a d6 d4 8e d5  |...<x~...8......|
+000000a0  6a c5 3a 0f 85 e7 37 a6  3c 8d 1e 4b da 02 94 bf  |j.:...7.<..K....|
+000000b0  ae 2c 50 3b 4e 1c 0c 3c  4f cc d5 1c da 33 13 43  |.,P;N..<O....3.C|
+000000c0  37 64 44 ac 26 43 28 0b  d0 c2 04 09 b5 0f 23 1d  |7dD.&C(.......#.|
+>>> Flow 4 (server to client)
+00000000  14 03 00 00 01 01 16 03  00 00 3c 23 29 64 62 23  |..........<#)db#|
+00000010  19 20 f8 2e 15 07 ee c8  f4 ab f0 3e 66 c3 ed 7b  |. .........>f..{|
+00000020  7c a7 c2 7e c3 25 3c 8f  f3 04 dc 37 e8 fc 0a 1d  ||..~.%<....7....|
+00000030  fa 7a 09 d4 21 11 e3 24  21 4b 37 d1 85 cc 40 bf  |.z..!..$!K7...@.|
+00000040  bd bd f8 59 6b cd 73 17  03 00 00 21 47 1d ac 54  |...Yk.s....!G..T|
+00000050  bd 58 a6 c0 04 e2 0c 6b  66 64 5a 85 09 0e 47 fc  |.X.....kfdZ...G.|
+00000060  0b 57 ee f1 24 b6 89 57  46 be 6b 0d f2 15 03 00  |.W..$..WF.k.....|
+00000070  00 16 b4 f7 34 99 19 43  b6 b3 5a 8b c3 d2 67 2f  |....4..C..Z...g/|
+00000080  3b 19 1c 31 d4 f9 bd 96                           |;..1....|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
new file mode 100644
index 0000000..9b8cb4d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
@@ -0,0 +1,84 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 76 01 00 00  72 03 01 53 04 f0 f9 4b  |....v...r..S...K|
+00000010  30 a8 68 d0 79 13 14 69  ee 3b 5d 05 cb 71 63 43  |0.h.y..i.;]..qcC|
+00000020  4a 55 6b 05 25 53 19 ba  e0 2f b1 00 00 04 c0 0a  |JUk.%S.../......|
+00000030  00 ff 01 00 00 45 00 0b  00 04 03 00 01 02 00 0a  |.....E..........|
+00000040  00 34 00 32 00 0e 00 0d  00 19 00 0b 00 0c 00 18  |.4.2............|
+00000050  00 09 00 0a 00 16 00 17  00 08 00 06 00 07 00 14  |................|
+00000060  00 15 00 04 00 05 00 12  00 13 00 01 00 02 00 03  |................|
+00000070  00 0f 00 10 00 11 00 0f  00 01 01                 |...........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 31 02 00 00  2d 03 01 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 c0 0a 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  01 02 0e 0b 00 02 0a 00  |................|
+00000040  02 07 00 02 04 30 82 02  00 30 82 01 62 02 09 00  |.....0...0..b...|
+00000050  b8 bf 2d 47 a0 d2 eb f4  30 09 06 07 2a 86 48 ce  |..-G....0...*.H.|
+00000060  3d 04 01 30 45 31 0b 30  09 06 03 55 04 06 13 02  |=..0E1.0...U....|
+00000070  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+00000080  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000090  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+000000a0  74 73 20 50 74 79 20 4c  74 64 30 1e 17 0d 31 32  |ts Pty Ltd0...12|
+000000b0  31 31 32 32 31 35 30 36  33 32 5a 17 0d 32 32 31  |1122150632Z..221|
+000000c0  31 32 30 31 35 30 36 33  32 5a 30 45 31 0b 30 09  |120150632Z0E1.0.|
+000000d0  06 03 55 04 06 13 02 41  55 31 13 30 11 06 03 55  |..U....AU1.0...U|
+000000e0  04 08 13 0a 53 6f 6d 65  2d 53 74 61 74 65 31 21  |....Some-State1!|
+000000f0  30 1f 06 03 55 04 0a 13  18 49 6e 74 65 72 6e 65  |0...U....Interne|
+00000100  74 20 57 69 64 67 69 74  73 20 50 74 79 20 4c 74  |t Widgits Pty Lt|
+00000110  64 30 81 9b 30 10 06 07  2a 86 48 ce 3d 02 01 06  |d0..0...*.H.=...|
+00000120  05 2b 81 04 00 23 03 81  86 00 04 00 c4 a1 ed be  |.+...#..........|
+00000130  98 f9 0b 48 73 36 7e c3  16 56 11 22 f2 3d 53 c3  |...Hs6~..V.".=S.|
+00000140  3b 4d 21 3d cd 6b 75 e6  f6 b0 dc 9a df 26 c1 bc  |;M!=.ku......&..|
+00000150  b2 87 f0 72 32 7c b3 64  2f 1c 90 bc ea 68 23 10  |...r2|.d/....h#.|
+00000160  7e fe e3 25 c0 48 3a 69  e0 28 6d d3 37 00 ef 04  |~..%.H:i.(m.7...|
+00000170  62 dd 0d a0 9c 70 62 83  d8 81 d3 64 31 aa 9e 97  |b....pb....d1...|
+00000180  31 bd 96 b0 68 c0 9b 23  de 76 64 3f 1a 5c 7f e9  |1...h..#.vd?.\..|
+00000190  12 0e 58 58 b6 5f 70 dd  9b d8 ea d5 d7 f5 d5 cc  |..XX._p.........|
+000001a0  b9 b6 9f 30 66 5b 66 9a  20 e2 27 e5 bf fe 3b 30  |...0f[f. .'...;0|
+000001b0  09 06 07 2a 86 48 ce 3d  04 01 03 81 8c 00 30 81  |...*.H.=......0.|
+000001c0  88 02 42 01 88 a2 4f eb  e2 45 c5 48 7d 1b ac f5  |..B...O..E.H}...|
+000001d0  ed 98 9d ae 47 70 c0 5e  1b b6 2f bd f1 b6 4d b7  |....Gp.^../...M.|
+000001e0  61 40 d3 11 a2 ce ee 0b  7e 92 7e ff 76 9d c3 3b  |a@......~.~.v..;|
+000001f0  7e a5 3f ce fa 10 e2 59  ec 47 2d 7c ac da 4e 97  |~.?....Y.G-|..N.|
+00000200  0e 15 a0 6f d0 02 42 01  4d fc be 67 13 9c 2d 05  |...o..B.M..g..-.|
+00000210  0e bd 3f a3 8c 25 c1 33  13 83 0d 94 06 bb d4 37  |..?..%.3.......7|
+00000220  7a f6 ec 7a c9 86 2e dd  d7 11 69 7f 85 7c 56 de  |z..z......i..|V.|
+00000230  fb 31 78 2b e4 c7 78 0d  ae cb be 9e 4e 36 24 31  |.1x+..x.....N6$1|
+00000240  7b 6a 0f 39 95 12 07 8f  2a 16 03 01 00 d6 0c 00  |{j.9....*.......|
+00000250  00 d2 03 00 17 41 04 1e  18 37 ef 0d 19 51 88 35  |.....A...7...Q.5|
+00000260  75 71 b5 e5 54 5b 12 2e  8f 09 67 fd a7 24 20 3e  |uq..T[....g..$ >|
+00000270  b2 56 1c ce 97 28 5e f8  2b 2d 4f 9e f1 07 9f 6c  |.V...(^.+-O....l|
+00000280  4b 5b 83 56 e2 32 42 e9  58 b6 d7 49 a6 b5 68 1a  |K[.V.2B.X..I..h.|
+00000290  41 03 56 6b dc 5a 89 00  8b 30 81 88 02 42 00 c6  |A.Vk.Z...0...B..|
+000002a0  85 8e 06 b7 04 04 e9 cd  9e 3e cb 66 23 95 b4 42  |.........>.f#..B|
+000002b0  9c 64 81 39 05 3f b5 21  f8 28 af 60 6b 4d 3d ba  |.d.9.?.!.(.`kM=.|
+000002c0  a1 4b 5e 77 ef e7 59 28  fe 1d c1 27 a2 ff a8 de  |.K^w..Y(...'....|
+000002d0  33 48 b3 c1 85 6a 42 9b  f9 7e 7e 31 c2 e5 bd 66  |3H...jB..~~1...f|
+000002e0  02 42 00 ad 7d 06 35 ab  ec 8d ac d4 ba 1b 49 5e  |.B..}.5.......I^|
+000002f0  05 5f f0 97 93 82 b8 2b  8d 91 98 63 8e b4 14 62  |._.....+...c...b|
+00000300  db 1e c9 2b 30 f8 41 9b  a6 e6 bc de 0e 68 30 21  |...+0.A......h0!|
+00000310  d8 ef 2f 05 42 da f2 e0  2c 06 33 1d 0d 9a 1a 75  |../.B...,.3....u|
+00000320  59 a7 3a bc 16 03 01 00  04 0e 00 00 00           |Y.:..........|
+>>> Flow 3 (client to server)
+00000000  16 03 01 00 46 10 00 00  42 41 04 08 28 cf bd 3c  |....F...BA..(..<|
+00000010  3c cc 98 9e 73 3f 92 a7  cb 22 83 3b c7 61 46 0e  |<...s?...".;.aF.|
+00000020  4d 7c 30 b5 06 85 2f 01  be b5 40 e2 64 1e 45 c1  |M|0.../...@.d.E.|
+00000030  9d 73 95 d5 65 92 0b 9b  e7 6f c6 91 ab b6 fa be  |.s..e....o......|
+00000040  61 83 a7 f2 eb f5 65 31  fe 24 7b 14 03 01 00 01  |a.....e1.${.....|
+00000050  01 16 03 01 00 30 15 d1  c4 ca 0b 01 84 13 5a ba  |.....0........Z.|
+00000060  89 04 87 73 7c bb d8 89  7e 10 27 ba 6f 5d dc d3  |...s|...~.'.o]..|
+00000070  b5 ef 32 86 58 cc fb eb  5c 32 9e 95 ef 01 1c ac  |..2.X...\2......|
+00000080  dc 8e df 7f fe 0a                                 |......|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 30 e8 48 86 81 3c  |..........0.H..<|
+00000010  f5 25 5c 94 a9 06 c4 5c  71 62 b1 43 76 ec 2c 44  |.%\....\qb.Cv.,D|
+00000020  95 b5 8c 95 d2 ff 82 92  b6 fc 52 75 03 c6 a1 f0  |..........Ru....|
+00000030  99 6d b1 ed ec 68 6c d7  9f 18 50 17 03 01 00 20  |.m...hl...P.... |
+00000040  32 d9 26 8a 81 b8 9d a5  7b fd d5 4e 7a db 2e 29  |2.&.....{..Nz..)|
+00000050  58 9a 4f 6a 27 18 bc dc  c2 49 b8 65 cb 8e 16 5a  |X.Oj'....I.e...Z|
+00000060  17 03 01 00 30 c4 56 0a  ad 9a 82 cb 3e 32 f1 7c  |....0.V.....>2.||
+00000070  95 6e dd cd e9 4d f0 e5  2d c9 a3 f7 de bb d7 fd  |.n...M..-.......|
+00000080  84 bb df 34 8c 64 1f 03  58 64 19 4a 5b 7a a8 81  |...4.d..Xd.J[z..|
+00000090  52 bb 51 0a 43 15 03 01  00 20 89 18 7a 40 ec 49  |R.Q.C.... ..z@.I|
+000000a0  52 d5 d3 20 ac 07 eb e9  4a 78 23 cf e7 21 32 74  |R.. ....Jx#..!2t|
+000000b0  ec 40 8d a8 f4 33 1c ae  93 cf                    |.@...3....|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES
new file mode 100644
index 0000000..c0e6241
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES
@@ -0,0 +1,79 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 36 01 00 00  32 03 01 52 cc 57 59 13  |....6...2..R.WY.|
+00000010  8b e6 5b a3 1d cb 94 ef  48 e4 59 7e 20 6d 07 67  |..[.....H.Y~ m.g|
+00000020  1e 28 6d 31 a2 e7 96 b3  7d 32 cc 00 00 04 00 0a  |.(m1....}2......|
+00000030  00 ff 01 00 00 05 00 0f  00 01 01                 |...........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 31 02 00 00  2d 03 01 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 0a 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  01 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 01 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 01 00 86 10 00 00  82 00 80 2e af d2 61 f6  |..............a.|
+00000010  e2 b8 24 da 28 17 55 99  fd 11 bd 7a ab 98 dd f2  |..$.(.U....z....|
+00000020  f6 5f e0 11 6b 12 61 6f  86 48 b2 6e db f0 dd d5  |._..k.ao.H.n....|
+00000030  07 88 e5 95 f4 2d 6b 0c  d0 09 1a 5e 5f 50 1f dc  |.....-k....^_P..|
+00000040  f2 e7 02 7d 5e a0 70 29  80 ef 87 aa cc 95 3f 2e  |...}^.p)......?.|
+00000050  24 d1 40 b6 62 53 1d 25  31 87 1e 2f 77 d3 e1 1c  |$.@.bS.%1../w...|
+00000060  c4 99 89 bc 99 09 e9 ad  1f ce 09 e6 36 1c 3e 97  |............6.>.|
+00000070  be 62 69 a0 4e 14 20 9c  82 2a 3e fc 7e 9b c4 7a  |.bi.N. ..*>.~..z|
+00000080  5a f7 ad 1a 03 17 2a f8  7a 5f 44 14 03 01 00 01  |Z.....*.z_D.....|
+00000090  01 16 03 01 00 28 49 6b  da 73 07 ad 85 9a 0e fb  |.....(Ik.s......|
+000000a0  dd e0 69 ef c9 22 2d 86  91 51 26 63 d0 24 7d 16  |..i.."-..Q&c.$}.|
+000000b0  3c db 9b 00 c9 7e 64 e2  69 02 85 7d f7 47        |<....~d.i..}.G|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 28 dc 60 83 43 6c  |..........(.`.Cl|
+00000010  37 79 ab 6e 92 1f 66 d0  b1 12 ce c1 64 9d 2b 68  |7y.n..f.....d.+h|
+00000020  c7 1a e5 1f 8c 80 08 d2  86 3e a1 2c e3 7e f4 64  |.........>.,.~.d|
+00000030  e7 96 b2 17 03 01 00 18  8d b5 7c 03 78 cf dc 09  |..........|.x...|
+00000040  95 06 4b a6 82 f9 30 d2  6b 26 cb 0a 9a 9d 47 9f  |..K...0.k&....G.|
+00000050  17 03 01 00 28 30 a9 55  dd b9 4d 6a 76 00 39 96  |....(0.U..Mjv.9.|
+00000060  a3 94 6a df e5 af 1e a2  eb bb e4 ac 95 2c f7 93  |..j..........,..|
+00000070  ef d1 b5 13 d8 e2 06 1a  ad 5c 00 dd 0c 15 03 01  |.........\......|
+00000080  00 18 a5 62 e4 8b 51 1d  28 46 bc 8a c8 50 a3 32  |...b..Q.(F...P.2|
+00000090  6b 7b f1 b6 19 43 63 1f  7d 38                    |k{...Cc.}8|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES
new file mode 100644
index 0000000..1670997
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES
@@ -0,0 +1,82 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 36 01 00 00  32 03 01 52 cc 57 59 5d  |....6...2..R.WY]|
+00000010  0d 77 24 3e b3 32 3d ba  0f b0 aa 1d e3 13 06 f6  |.w$>.2=.........|
+00000020  0f be 3c 92 ba 93 bd a6  6d 69 53 00 00 04 00 2f  |..<.....miS..../|
+00000030  00 ff 01 00 00 05 00 0f  00 01 01                 |...........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 31 02 00 00  2d 03 01 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 2f 00 00  |............./..|
+00000030  05 ff 01 00 01 00 16 03  01 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 01 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 01 00 86 10 00 00  82 00 80 20 e6 80 f7 48  |........... ...H|
+00000010  7e 7d 08 08 54 e1 b4 e3  98 27 5f 90 9d 3b e3 c2  |~}..T....'_..;..|
+00000020  c8 8b dc 9e ff 75 fa fc  60 e1 9e 67 7c c4 08 27  |.....u..`..g|..'|
+00000030  cc 6f 15 6c bc 7c 96 de  83 8f 98 6d 4a c7 b7 20  |.o.l.|.....mJ.. |
+00000040  8c 19 47 5a ff 76 92 0a  df df 66 d2 b6 9d 2d 06  |..GZ.v....f...-.|
+00000050  fb ac 07 cf 38 08 f1 fd  0d fe 07 d7 69 3e 8a 79  |....8.......i>.y|
+00000060  dc 2d ab bb f7 18 3c 51  14 6e c6 70 95 a2 59 b1  |.-....<Q.n.p..Y.|
+00000070  39 04 9f ae f3 5f fb a7  2b d3 5a c0 96 d9 4d 2a  |9...._..+.Z...M*|
+00000080  2a 6c 6d 39 ee fc ce 76  1a 92 1b 14 03 01 00 01  |*lm9...v........|
+00000090  01 16 03 01 00 30 10 20  90 7b 0e e6 c2 05 81 c3  |.....0. .{......|
+000000a0  bc da 84 67 dd 5f 97 e2  74 c4 35 4e bf d2 1b 90  |...g._..t.5N....|
+000000b0  2f e0 af dd 6b f5 52 db  36 cd 3e e1 e6 bd 99 30  |/...k.R.6.>....0|
+000000c0  ed c6 bc c2 38 b6                                 |....8.|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 30 5d 0c a2 18 13  |..........0]....|
+00000010  40 a1 84 ce c5 d8 4e fc  a4 8a 14 b5 94 18 b1 86  |@.....N.........|
+00000020  da 6a 7d 26 08 d6 a0 f8  78 5b 42 7e f8 83 54 56  |.j}&....x[B~..TV|
+00000030  36 a4 91 37 67 5a d7 68  37 c4 4f 17 03 01 00 20  |6..7gZ.h7.O.... |
+00000040  fd aa 5e cf 4b 12 c5 be  a4 a2 65 5d 6e 65 46 5f  |..^.K.....e]neF_|
+00000050  d2 fe 46 e7 77 2d 9c 1e  0b 39 40 48 c2 2f be 21  |..F.w-...9@H./.!|
+00000060  17 03 01 00 30 03 af 9e  6b d6 76 ed 9e 1d 8b 8b  |....0...k.v.....|
+00000070  2e 2a 5d da c4 73 95 ac  0e 6f 69 cb 63 df 50 27  |.*]..s...oi.c.P'|
+00000080  30 de 2e 55 86 85 ad 3e  33 22 49 72 f2 e2 9f 8f  |0..U...>3"Ir....|
+00000090  ba cf 4e 30 34 15 03 01  00 20 4c 4c 97 61 70 ea  |..N04.... LL.ap.|
+000000a0  ae fc a2 e9 c6 c2 b6 2e  4d 85 f6 ae 2b 56 46 82  |........M...+VF.|
+000000b0  9d d8 a5 82 17 fa 3e 62  67 7e                    |......>bg~|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4 b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4
new file mode 100644
index 0000000..d653561
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4
@@ -0,0 +1,76 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 36 01 00 00  32 03 01 52 cc 57 59 cf  |....6...2..R.WY.|
+00000010  00 a1 49 a4 37 69 74 d8  a7 93 ea 8d e7 50 b7 b3  |..I.7it......P..|
+00000020  8c ec e5 56 fb dc 5f 1a  2e ab 18 00 00 04 00 05  |...V.._.........|
+00000030  00 ff 01 00 00 05 00 0f  00 01 01                 |...........|
+>>> Flow 2 (server to client)
+00000000  16 03 01 00 31 02 00 00  2d 03 01 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 05 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  01 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 01 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 01 00 86 10 00 00  82 00 80 b1 96 7b 6f f5  |.............{o.|
+00000010  a0 cb 0d 60 9b 64 d3 f5  17 76 47 7b bc a5 0e 96  |...`.d...vG{....|
+00000020  53 af 68 0c 96 22 f7 28  0c 24 37 9c 51 69 ed b2  |S.h..".(.$7.Qi..|
+00000030  47 14 ba 33 c5 79 6b 96  f2 ab 3c 02 5c 37 a4 97  |G..3.yk...<.\7..|
+00000040  23 fc 7f d3 95 2d 85 99  1a 10 1b 38 e5 f1 83 55  |#....-.....8...U|
+00000050  4a ab 60 f8 89 0a 6a c4  eb 45 f5 b0 f4 f8 09 31  |J.`...j..E.....1|
+00000060  6e f0 25 30 fd 5e 68 61  bc cb 0d 9e 05 73 0a f4  |n.%0.^ha.....s..|
+00000070  a5 2e d9 d5 4e 08 f6 3b  8d 2d 21 f5 79 b6 97 55  |....N..;.-!.y..U|
+00000080  b9 99 03 49 ea 96 36 49  21 56 bf 14 03 01 00 01  |...I..6I!V......|
+00000090  01 16 03 01 00 24 f0 4f  30 06 c3 25 01 93 34 ab  |.....$.O0..%..4.|
+000000a0  93 8f 59 26 83 6e 8a fd  5a a6 cf af ad b1 a2 83  |..Y&.n..Z.......|
+000000b0  28 ff c2 66 5f ac e5 a5  a5 03                    |(..f_.....|
+>>> Flow 4 (server to client)
+00000000  14 03 01 00 01 01 16 03  01 00 24 9d b4 ea d8 be  |..........$.....|
+00000010  b5 9f 00 fd b5 99 04 12  6b 7a 3f b8 52 d7 52 a9  |........kz?.R.R.|
+00000020  e9 bd 5b 63 ad b0 53 ac  46 80 be 48 6e dd ee 17  |..[c..S.F..Hn...|
+00000030  03 01 00 21 07 ac c4 fb  21 e4 b8 6b 64 3b b5 27  |...!....!..kd;.'|
+00000040  29 67 a1 10 2e d2 71 d5  59 5e fc 1d 84 31 15 6e  |)g....q.Y^...1.n|
+00000050  4d 4b dc a9 3a 15 03 01  00 16 25 22 a5 78 23 5a  |MK..:.....%".x#Z|
+00000060  69 6f 99 a1 b3 1c 8d bf  f3 bd 1b c8 1c 57 15 75  |io...........W.u|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4 b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4
new file mode 100644
index 0000000..9237db0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4
@@ -0,0 +1,76 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 36 01 00 00  32 03 02 52 cc 57 59 bd  |....6...2..R.WY.|
+00000010  cd 9d 1e 17 38 43 a5 e3  e7 30 e4 2b 2a ef f7 5b  |....8C...0.+*..[|
+00000020  81 91 0c 0b 52 f8 2d 2c  61 d3 13 00 00 04 00 05  |....R.-,a.......|
+00000030  00 ff 01 00 00 05 00 0f  00 01 01                 |...........|
+>>> Flow 2 (server to client)
+00000000  16 03 02 00 31 02 00 00  2d 03 02 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 05 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  02 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 02 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 02 00 86 10 00 00  82 00 80 71 2b 19 25 86  |...........q+.%.|
+00000010  a0 ff ba d5 1c a6 0c 8b  6b 0a b8 e9 42 93 2f 55  |........k...B./U|
+00000020  a8 ee 62 fa ed bc 6d e2  9d e3 76 a6 73 d7 99 58  |..b...m...v.s..X|
+00000030  cc 0b 14 42 96 7c b6 c7  8f 21 16 cf 71 9b 2b b9  |...B.|...!..q.+.|
+00000040  e0 34 57 76 22 d5 87 8a  ce 1f ea 26 6e 1e e6 ca  |.4Wv"......&n...|
+00000050  55 3b 20 cd cf 42 26 b1  51 3e 8c 1d a2 ae c4 63  |U; ..B&.Q>.....c|
+00000060  f5 ce 27 3c 1e c3 e0 e3  b1 16 c1 8a 62 bd 21 7f  |..'<........b.!.|
+00000070  38 b5 b7 3a 3c bb 03 37  e1 a5 ff f1 29 e2 21 0a  |8..:<..7....).!.|
+00000080  8c 20 02 e0 c0 82 97 9d  18 6d f8 14 03 02 00 01  |. .......m......|
+00000090  01 16 03 02 00 24 bc 19  16 6e fd 0b db 9e d5 1d  |.....$...n......|
+000000a0  65 b6 57 1c 58 b5 6a ac  f7 4f f0 cd a1 a9 0c c0  |e.W.X.j..O......|
+000000b0  df e6 eb d5 00 f7 fd 43  bb 27                    |.......C.'|
+>>> Flow 4 (server to client)
+00000000  14 03 02 00 01 01 16 03  02 00 24 cf 4f e4 27 b0  |..........$.O.'.|
+00000010  3d 17 34 b1 3c 37 6e c5  2b 3d 4a c3 46 50 44 b4  |=.4.<7n.+=J.FPD.|
+00000020  de 77 18 10 4f 60 b3 4e  dc 06 fd 25 ec 05 15 17  |.w..O`.N...%....|
+00000030  03 02 00 21 a5 c9 32 f2  21 fb 94 7e 0d 15 65 fd  |...!..2.!..~..e.|
+00000040  3e fe e4 c1 a5 e9 88 72  b2 f1 26 39 a6 48 59 97  |>......r..&9.HY.|
+00000050  65 e3 f0 cb 46 15 03 02  00 16 4b 02 ec cd ca 30  |e...F.....K....0|
+00000060  42 cf 3d a0 4a fa 8e 79  bb ed b0 59 40 9b 2c 1a  |B.=.J..y...Y@.,.|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
new file mode 100644
index 0000000..0ab8b8d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
@@ -0,0 +1,91 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 ca 01 00 00  c6 03 03 53 04 f1 3f 5f  |...........S..?_|
+00000010  f4 ef 1f b3 41 0b 54 e4  4d 56 0a 31 22 b8 5c 73  |....A.T.MV.1".\s|
+00000020  a3 cb b5 b2 9d 43 f1 83  bc d3 bd 00 00 32 c0 30  |.....C.......2.0|
+00000030  c0 2c c0 28 c0 24 c0 14  c0 0a c0 22 c0 21 00 a3  |.,.(.$.....".!..|
+00000040  00 9f 00 6b 00 6a 00 39  00 38 00 88 00 87 c0 32  |...k.j.9.8.....2|
+00000050  c0 2e c0 2a c0 26 c0 0f  c0 05 00 9d 00 3d 00 35  |...*.&.......=.5|
+00000060  01 00 00 6b 00 0b 00 04  03 00 01 02 00 0a 00 34  |...k...........4|
+00000070  00 32 00 0e 00 0d 00 19  00 0b 00 0c 00 18 00 09  |.2..............|
+00000080  00 0a 00 16 00 17 00 08  00 06 00 07 00 14 00 15  |................|
+00000090  00 04 00 05 00 12 00 13  00 01 00 02 00 03 00 0f  |................|
+000000a0  00 10 00 11 00 0d 00 22  00 20 06 01 06 02 06 03  |.......". ......|
+000000b0  05 01 05 02 05 03 04 01  04 02 04 03 03 01 03 02  |................|
+000000c0  03 03 02 01 02 02 02 03  01 01 00 0f 00 01 01     |...............|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 2a 02 00 00  26 03 03 00 00 00 00 00  |....*...&.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 c0 0a 00 16  |................|
+00000030  03 03 02 0e 0b 00 02 0a  00 02 07 00 02 04 30 82  |..............0.|
+00000040  02 00 30 82 01 62 02 09  00 b8 bf 2d 47 a0 d2 eb  |..0..b.....-G...|
+00000050  f4 30 09 06 07 2a 86 48  ce 3d 04 01 30 45 31 0b  |.0...*.H.=..0E1.|
+00000060  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000070  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000080  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+00000090  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000a0  4c 74 64 30 1e 17 0d 31  32 31 31 32 32 31 35 30  |Ltd0...121122150|
+000000b0  36 33 32 5a 17 0d 32 32  31 31 32 30 31 35 30 36  |632Z..2211201506|
+000000c0  33 32 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |32Z0E1.0...U....|
+000000d0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000e0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+000000f0  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000100  74 73 20 50 74 79 20 4c  74 64 30 81 9b 30 10 06  |ts Pty Ltd0..0..|
+00000110  07 2a 86 48 ce 3d 02 01  06 05 2b 81 04 00 23 03  |.*.H.=....+...#.|
+00000120  81 86 00 04 00 c4 a1 ed  be 98 f9 0b 48 73 36 7e  |............Hs6~|
+00000130  c3 16 56 11 22 f2 3d 53  c3 3b 4d 21 3d cd 6b 75  |..V.".=S.;M!=.ku|
+00000140  e6 f6 b0 dc 9a df 26 c1  bc b2 87 f0 72 32 7c b3  |......&.....r2|.|
+00000150  64 2f 1c 90 bc ea 68 23  10 7e fe e3 25 c0 48 3a  |d/....h#.~..%.H:|
+00000160  69 e0 28 6d d3 37 00 ef  04 62 dd 0d a0 9c 70 62  |i.(m.7...b....pb|
+00000170  83 d8 81 d3 64 31 aa 9e  97 31 bd 96 b0 68 c0 9b  |....d1...1...h..|
+00000180  23 de 76 64 3f 1a 5c 7f  e9 12 0e 58 58 b6 5f 70  |#.vd?.\....XX._p|
+00000190  dd 9b d8 ea d5 d7 f5 d5  cc b9 b6 9f 30 66 5b 66  |............0f[f|
+000001a0  9a 20 e2 27 e5 bf fe 3b  30 09 06 07 2a 86 48 ce  |. .'...;0...*.H.|
+000001b0  3d 04 01 03 81 8c 00 30  81 88 02 42 01 88 a2 4f  |=......0...B...O|
+000001c0  eb e2 45 c5 48 7d 1b ac  f5 ed 98 9d ae 47 70 c0  |..E.H}.......Gp.|
+000001d0  5e 1b b6 2f bd f1 b6 4d  b7 61 40 d3 11 a2 ce ee  |^../...M.a@.....|
+000001e0  0b 7e 92 7e ff 76 9d c3  3b 7e a5 3f ce fa 10 e2  |.~.~.v..;~.?....|
+000001f0  59 ec 47 2d 7c ac da 4e  97 0e 15 a0 6f d0 02 42  |Y.G-|..N....o..B|
+00000200  01 4d fc be 67 13 9c 2d  05 0e bd 3f a3 8c 25 c1  |.M..g..-...?..%.|
+00000210  33 13 83 0d 94 06 bb d4  37 7a f6 ec 7a c9 86 2e  |3.......7z..z...|
+00000220  dd d7 11 69 7f 85 7c 56  de fb 31 78 2b e4 c7 78  |...i..|V..1x+..x|
+00000230  0d ae cb be 9e 4e 36 24  31 7b 6a 0f 39 95 12 07  |.....N6$1{j.9...|
+00000240  8f 2a 16 03 03 00 d8 0c  00 00 d4 03 00 17 41 04  |.*............A.|
+00000250  1e 18 37 ef 0d 19 51 88  35 75 71 b5 e5 54 5b 12  |..7...Q.5uq..T[.|
+00000260  2e 8f 09 67 fd a7 24 20  3e b2 56 1c ce 97 28 5e  |...g..$ >.V...(^|
+00000270  f8 2b 2d 4f 9e f1 07 9f  6c 4b 5b 83 56 e2 32 42  |.+-O....lK[.V.2B|
+00000280  e9 58 b6 d7 49 a6 b5 68  1a 41 03 56 6b dc 5a 89  |.X..I..h.A.Vk.Z.|
+00000290  04 03 00 8b 30 81 88 02  42 00 c6 85 8e 06 b7 04  |....0...B.......|
+000002a0  04 e9 cd 9e 3e cb 66 23  95 b4 42 9c 64 81 39 05  |....>.f#..B.d.9.|
+000002b0  3f b5 21 f8 28 af 60 6b  4d 3d ba a1 4b 5e 77 ef  |?.!.(.`kM=..K^w.|
+000002c0  e7 59 28 fe 1d c1 27 a2  ff a8 de 33 48 b3 c1 85  |.Y(...'....3H...|
+000002d0  6a 42 9b f9 7e 7e 31 c2  e5 bd 66 02 42 00 ad 7d  |jB..~~1...f.B..}|
+000002e0  06 35 ab ec 8d ac d4 ba  1b 49 5e 05 5f f0 97 93  |.5.......I^._...|
+000002f0  82 b8 2b 8d 91 98 63 8e  b4 14 62 db 1e c9 2b 64  |..+...c...b...+d|
+00000300  e9 e6 bf 15 5b 67 c2 40  90 c6 1f b7 92 db 4b f6  |....[g.@......K.|
+00000310  f4 db ae 82 f1 4f 02 75  52 40 38 10 ff 35 f0 16  |.....O.uR@8..5..|
+00000320  03 03 00 04 0e 00 00 00                           |........|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 46 10 00 00  42 41 04 d8 94 c4 05 26  |....F...BA.....&|
+00000010  76 29 2d 0e ec 47 b6 50  d5 a3 da 2a ba 02 11 37  |v)-..G.P...*...7|
+00000020  3d ef e6 2a db d0 47 47  a7 9a 5f 43 2d 98 78 26  |=..*..GG.._C-.x&|
+00000030  81 e2 f1 ba fe f7 66 c6  61 cb c1 b7 60 62 34 a5  |......f.a...`b4.|
+00000040  78 67 50 3d 9a 0e 4a 8c  8f d7 10 14 03 03 00 01  |xgP=..J.........|
+00000050  01 16 03 03 00 40 5e 46  b0 5d 30 f6 da 8f 9e 67  |.....@^F.]0....g|
+00000060  f5 3e bd fe c9 b8 53 b2  10 d5 7c 0e 34 e3 93 6d  |.>....S...|.4..m|
+00000070  0e 8e 8a 2b df fb 9a 0f  a5 23 55 e7 0a 4b e2 d3  |...+.....#U..K..|
+00000080  db 15 e8 52 74 26 78 b3  b0 56 65 63 ac ae 1e c0  |...Rt&x..Vec....|
+00000090  0b f4 92 56 a9 04                                 |...V..|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |..........@.....|
+00000010  00 00 00 00 00 00 00 00  00 00 00 16 a9 63 0a 99  |.............c..|
+00000020  21 8a fc 5c b3 ee 05 71  4e 75 c0 d9 40 54 0d 3e  |!..\...qNu..@T.>|
+00000030  4e 5d 44 b7 4b 5d a9 e7  5a 30 ed b6 d5 08 50 b1  |N]D.K]..Z0....P.|
+00000040  e8 8c 54 eb 1b 39 7a f9  3b ac 2e 17 03 03 00 40  |..T..9z.;......@|
+00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000060  96 03 20 2b 20 c4 c1 9a  76 7b f3 96 bd 33 ed e6  |.. + ...v{...3..|
+00000070  38 48 ea 53 d5 e0 62 b5  7e 1a 36 a8 dd 9f 2d 4b  |8H.S..b.~.6...-K|
+00000080  06 0d ae f6 bc 99 14 b3  93 14 27 63 e2 a0 c8 76  |..........'c...v|
+00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+000000a0  00 00 00 00 00 48 af e1  e4 11 e1 b7 03 19 b0 e3  |.....H..........|
+000000b0  e6 a9 66 d8 ac af aa 03  f6 0d 51 df 9a 27 78 3a  |..f.......Q..'x:|
+000000c0  56 5a 03 1a 4c                                    |VZ..L|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
new file mode 100644
index 0000000..88abb15
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
@@ -0,0 +1,101 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 ca 01 00 00  c6 03 03 53 04 f1 3f cc  |...........S..?.|
+00000010  41 74 00 07 cb ae 3b 30  79 48 51 60 41 a3 8c ab  |At....;0yHQ`A...|
+00000020  dc 76 f9 74 52 1e c5 fb  a9 69 c2 00 00 32 c0 30  |.v.tR....i...2.0|
+00000030  c0 2c c0 28 c0 24 c0 14  c0 0a c0 22 c0 21 00 a3  |.,.(.$.....".!..|
+00000040  00 9f 00 6b 00 6a 00 39  00 38 00 88 00 87 c0 32  |...k.j.9.8.....2|
+00000050  c0 2e c0 2a c0 26 c0 0f  c0 05 00 9d 00 3d 00 35  |...*.&.......=.5|
+00000060  01 00 00 6b 00 0b 00 04  03 00 01 02 00 0a 00 34  |...k...........4|
+00000070  00 32 00 0e 00 0d 00 19  00 0b 00 0c 00 18 00 09  |.2..............|
+00000080  00 0a 00 16 00 17 00 08  00 06 00 07 00 14 00 15  |................|
+00000090  00 04 00 05 00 12 00 13  00 01 00 02 00 03 00 0f  |................|
+000000a0  00 10 00 11 00 0d 00 22  00 20 06 01 06 02 06 03  |.......". ......|
+000000b0  05 01 05 02 05 03 04 01  04 02 04 03 03 01 03 02  |................|
+000000c0  03 03 02 01 02 02 02 03  01 01 00 0f 00 01 01     |...............|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 2a 02 00 00  26 03 03 00 00 00 00 00  |....*...&.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 c0 14 00 16  |................|
+00000030  03 03 02 be 0b 00 02 ba  00 02 b7 00 02 b4 30 82  |..............0.|
+00000040  02 b0 30 82 02 19 a0 03  02 01 02 02 09 00 85 b0  |..0.............|
+00000050  bb a4 8a 7f b8 ca 30 0d  06 09 2a 86 48 86 f7 0d  |......0...*.H...|
+00000060  01 01 05 05 00 30 45 31  0b 30 09 06 03 55 04 06  |.....0E1.0...U..|
+00000070  13 02 41 55 31 13 30 11  06 03 55 04 08 13 0a 53  |..AU1.0...U....S|
+00000080  6f 6d 65 2d 53 74 61 74  65 31 21 30 1f 06 03 55  |ome-State1!0...U|
+00000090  04 0a 13 18 49 6e 74 65  72 6e 65 74 20 57 69 64  |....Internet Wid|
+000000a0  67 69 74 73 20 50 74 79  20 4c 74 64 30 1e 17 0d  |gits Pty Ltd0...|
+000000b0  31 30 30 34 32 34 30 39  30 39 33 38 5a 17 0d 31  |100424090938Z..1|
+000000c0  31 30 34 32 34 30 39 30  39 33 38 5a 30 45 31 0b  |10424090938Z0E1.|
+000000d0  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+000000e0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+000000f0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+00000100  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+00000110  4c 74 64 30 81 9f 30 0d  06 09 2a 86 48 86 f7 0d  |Ltd0..0...*.H...|
+00000120  01 01 01 05 00 03 81 8d  00 30 81 89 02 81 81 00  |.........0......|
+00000130  bb 79 d6 f5 17 b5 e5 bf  46 10 d0 dc 69 be e6 2b  |.y......F...i..+|
+00000140  07 43 5a d0 03 2d 8a 7a  43 85 b7 14 52 e7 a5 65  |.CZ..-.zC...R..e|
+00000150  4c 2c 78 b8 23 8c b5 b4  82 e5 de 1f 95 3b 7e 62  |L,x.#........;~b|
+00000160  a5 2c a5 33 d6 fe 12 5c  7a 56 fc f5 06 bf fa 58  |.,.3...\zV.....X|
+00000170  7b 26 3f b5 cd 04 d3 d0  c9 21 96 4a c7 f4 54 9f  |{&?......!.J..T.|
+00000180  5a bf ef 42 71 00 fe 18  99 07 7f 7e 88 7d 7d f1  |Z..Bq......~.}}.|
+00000190  04 39 c4 a2 2e db 51 c9  7c e3 c0 4c 3b 32 66 01  |.9....Q.|..L;2f.|
+000001a0  cf af b1 1d b8 71 9a 1d  db db 89 6b ae da 2d 79  |.....q.....k..-y|
+000001b0  02 03 01 00 01 a3 81 a7  30 81 a4 30 1d 06 03 55  |........0..0...U|
+000001c0  1d 0e 04 16 04 14 b1 ad  e2 85 5a cf cb 28 db 69  |..........Z..(.i|
+000001d0  ce 23 69 de d3 26 8e 18  88 39 30 75 06 03 55 1d  |.#i..&...90u..U.|
+000001e0  23 04 6e 30 6c 80 14 b1  ad e2 85 5a cf cb 28 db  |#.n0l......Z..(.|
+000001f0  69 ce 23 69 de d3 26 8e  18 88 39 a1 49 a4 47 30  |i.#i..&...9.I.G0|
+00000200  45 31 0b 30 09 06 03 55  04 06 13 02 41 55 31 13  |E1.0...U....AU1.|
+00000210  30 11 06 03 55 04 08 13  0a 53 6f 6d 65 2d 53 74  |0...U....Some-St|
+00000220  61 74 65 31 21 30 1f 06  03 55 04 0a 13 18 49 6e  |ate1!0...U....In|
+00000230  74 65 72 6e 65 74 20 57  69 64 67 69 74 73 20 50  |ternet Widgits P|
+00000240  74 79 20 4c 74 64 82 09  00 85 b0 bb a4 8a 7f b8  |ty Ltd..........|
+00000250  ca 30 0c 06 03 55 1d 13  04 05 30 03 01 01 ff 30  |.0...U....0....0|
+00000260  0d 06 09 2a 86 48 86 f7  0d 01 01 05 05 00 03 81  |...*.H..........|
+00000270  81 00 08 6c 45 24 c7 6b  b1 59 ab 0c 52 cc f2 b0  |...lE$.k.Y..R...|
+00000280  14 d7 87 9d 7a 64 75 b5  5a 95 66 e4 c5 2b 8e ae  |....zdu.Z.f..+..|
+00000290  12 66 1f eb 4f 38 b3 6e  60 d3 92 fd f7 41 08 b5  |.f..O8.n`....A..|
+000002a0  25 13 b1 18 7a 24 fb 30  1d ba ed 98 b9 17 ec e7  |%...z$.0........|
+000002b0  d7 31 59 db 95 d3 1d 78  ea 50 56 5c d5 82 5a 2d  |.1Y....x.PV\..Z-|
+000002c0  5a 5f 33 c4 b6 d8 c9 75  90 96 8c 0f 52 98 b5 cd  |Z_3....u....R...|
+000002d0  98 1f 89 20 5f f2 a0 1c  a3 1b 96 94 dd a9 fd 57  |... _..........W|
+000002e0  e9 70 e8 26 6d 71 99 9b  26 6e 38 50 29 6c 90 a7  |.p.&mq..&n8P)l..|
+000002f0  bd d9 16 03 03 00 cd 0c  00 00 c9 03 00 17 41 04  |..............A.|
+00000300  1e 18 37 ef 0d 19 51 88  35 75 71 b5 e5 54 5b 12  |..7...Q.5uq..T[.|
+00000310  2e 8f 09 67 fd a7 24 20  3e b2 56 1c ce 97 28 5e  |...g..$ >.V...(^|
+00000320  f8 2b 2d 4f 9e f1 07 9f  6c 4b 5b 83 56 e2 32 42  |.+-O....lK[.V.2B|
+00000330  e9 58 b6 d7 49 a6 b5 68  1a 41 03 56 6b dc 5a 89  |.X..I..h.A.Vk.Z.|
+00000340  04 01 00 80 9d 84 09 35  73 fb f6 ea 94 7b 49 fb  |.......5s....{I.|
+00000350  c2 70 b1 11 64 5b 93 9f  d9 8c f5 56 98 f6 d3 66  |.p..d[.....V...f|
+00000360  a6 1d 18 56 88 87 71 3f  b0 38 9d 44 1f ad 2c 0d  |...V..q?.8.D..,.|
+00000370  3a a7 e8 d4 3e 33 3c 41  20 f3 3f 5c e5 fb e3 23  |:...>3<A .?\...#|
+00000380  12 48 ff d2 c4 30 7c 8a  51 3f 9f 19 6e 34 d7 60  |.H...0|.Q?..n4.`|
+00000390  7d 12 8a aa 90 0f 50 d9  0b 9a b2 d7 66 b1 c6 84  |}.....P.....f...|
+000003a0  af 5c e2 5e 16 3e 36 61  73 84 64 89 b3 c1 6d 50  |.\.^.>6as.d...mP|
+000003b0  33 55 c7 e1 c5 a5 4c 32  5c 95 dc 07 43 60 49 11  |3U....L2\...C`I.|
+000003c0  e9 98 cc ba 16 03 03 00  04 0e 00 00 00           |.............|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 46 10 00 00  42 41 04 28 02 84 d5 b4  |....F...BA.(....|
+00000010  58 07 47 d5 a0 d6 0b 1d  37 91 e6 34 a4 ad 0b ad  |X.G.....7..4....|
+00000020  22 01 82 77 a7 32 86 78  83 3a da 75 2f e5 68 7a  |"..w.2.x.:.u/.hz|
+00000030  de e4 05 e0 02 47 40 4e  38 d2 2c c3 7b da 53 73  |.....G@N8.,.{.Ss|
+00000040  19 cb 8b 73 34 72 4d 33  71 39 c8 14 03 03 00 01  |...s4rM3q9......|
+00000050  01 16 03 03 00 40 10 63  43 76 83 bd 36 e4 1e 4d  |.....@.cCv..6..M|
+00000060  7e 13 b0 ac aa c8 ec 90  31 df 84 46 49 68 39 5a  |~.......1..FIh9Z|
+00000070  05 8b 73 32 86 15 3a 18  57 d8 e2 2c 2d 05 89 93  |..s2..:.W..,-...|
+00000080  37 b8 dd 73 33 92 ff a7  b2 53 27 94 b7 25 56 64  |7..s3....S'..%Vd|
+00000090  a1 d3 2c f7 6b 71                                 |..,.kq|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |..........@.....|
+00000010  00 00 00 00 00 00 00 00  00 00 00 21 5c 31 b1 4b  |...........!\1.K|
+00000020  96 96 30 8f 79 35 3a 3a  2d 26 67 d0 70 48 be 30  |..0.y5::-&g.pH.0|
+00000030  f8 3e e8 c1 cb 1d d5 89  f6 9c 72 bb 1c f9 4d 90  |.>........r...M.|
+00000040  9c d7 c6 fa 40 76 a5 61  46 61 24 17 03 03 00 40  |....@v.aFa$....@|
+00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000060  94 8a 14 04 06 b9 30 a0  67 fd b2 4c 84 f4 10 93  |......0.g..L....|
+00000070  7d d4 2b 23 f0 e9 62 93  c2 20 a2 f2 7c 07 21 4b  |}.+#..b.. ..|.!K|
+00000080  94 ba 7b 7d cb 77 da 85  93 bd 53 ee ca db 9b 3e  |..{}.w....S....>|
+00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+000000a0  00 00 00 00 00 17 3f 53  8d b3 35 b4 84 ed bb 12  |......?S..5.....|
+000000b0  cf 73 25 25 7c c3 d3 bb  1f 5a 6b 73 9a 8a b1 a2  |.s%%|....Zks....|
+000000c0  ba 99 f8 0e 43                                    |....C|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
new file mode 100644
index 0000000..547f798
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
@@ -0,0 +1,122 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 5c 01 00 00  58 03 03 52 cc 57 59 65  |....\...X..R.WYe|
+00000010  ae b3 ec a4 7a 05 f7 ec  39 22 7d 8c 91 96 6b e0  |....z...9"}...k.|
+00000020  69 81 ff 88 28 17 60 ac  94 19 ff 00 00 04 00 05  |i...(.`.........|
+00000030  00 ff 01 00 00 2b 00 0d  00 22 00 20 06 01 06 02  |.....+...". ....|
+00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
+00000050  03 02 03 03 02 01 02 02  02 03 01 01 00 0f 00 01  |................|
+00000060  01                                                |.|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 05 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 0f 0d 00  |n8P)l...........|
+00000300  00 0b 02 01 40 00 04 04  01 04 03 00 00 16 03 03  |....@...........|
+00000310  00 04 0e 00 00 00                                 |......|
+>>> Flow 3 (client to server)
+00000000  16 03 03 02 0a 0b 00 02  06 00 02 03 00 02 00 30  |...............0|
+00000010  82 01 fc 30 82 01 5e 02  09 00 9a 30 84 6c 26 35  |...0..^....0.l&5|
+00000020  d9 17 30 09 06 07 2a 86  48 ce 3d 04 01 30 45 31  |..0...*.H.=..0E1|
+00000030  0b 30 09 06 03 55 04 06  13 02 41 55 31 13 30 11  |.0...U....AU1.0.|
+00000040  06 03 55 04 08 13 0a 53  6f 6d 65 2d 53 74 61 74  |..U....Some-Stat|
+00000050  65 31 21 30 1f 06 03 55  04 0a 13 18 49 6e 74 65  |e1!0...U....Inte|
+00000060  72 6e 65 74 20 57 69 64  67 69 74 73 20 50 74 79  |rnet Widgits Pty|
+00000070  20 4c 74 64 30 1e 17 0d  31 32 31 31 31 34 31 33  | Ltd0...12111413|
+00000080  32 35 35 33 5a 17 0d 32  32 31 31 31 32 31 33 32  |2553Z..221112132|
+00000090  35 35 33 5a 30 41 31 0b  30 09 06 03 55 04 06 13  |553Z0A1.0...U...|
+000000a0  02 41 55 31 0c 30 0a 06  03 55 04 08 13 03 4e 53  |.AU1.0...U....NS|
+000000b0  57 31 10 30 0e 06 03 55  04 07 13 07 50 79 72 6d  |W1.0...U....Pyrm|
+000000c0  6f 6e 74 31 12 30 10 06  03 55 04 03 13 09 4a 6f  |ont1.0...U....Jo|
+000000d0  65 6c 20 53 69 6e 67 30  81 9b 30 10 06 07 2a 86  |el Sing0..0...*.|
+000000e0  48 ce 3d 02 01 06 05 2b  81 04 00 23 03 81 86 00  |H.=....+...#....|
+000000f0  04 00 95 8c 91 75 14 c0  5e c4 57 b4 d4 c3 6f 8d  |.....u..^.W...o.|
+00000100  ae 68 1e dd 6f ce 86 e1  7e 6e b2 48 3e 81 e5 4e  |.h..o...~n.H>..N|
+00000110  e2 c6 88 4b 64 dc f5 30  bb d3 ff 65 cc 5b f4 dd  |...Kd..0...e.[..|
+00000120  b5 6a 3e 3e d0 1d de 47  c3 76 ad 19 f6 45 2c 8c  |.j>>...G.v...E,.|
+00000130  bc d8 1d 01 4c 1f 70 90  46 76 48 8b 8f 83 cc 4a  |....L.p.FvH....J|
+00000140  5c 8f 40 76 da e0 89 ec  1d 2b c4 4e 30 76 28 41  |\.@v.....+.N0v(A|
+00000150  b2 62 a8 fb 5b f1 f9 4e  7a 8d bd 09 b8 ae ea 8b  |.b..[..Nz.......|
+00000160  18 27 4f 2e 70 fe 13 96  ba c3 d3 40 16 cd 65 4e  |.'O.p......@..eN|
+00000170  ac 11 1e e6 f1 30 09 06  07 2a 86 48 ce 3d 04 01  |.....0...*.H.=..|
+00000180  03 81 8c 00 30 81 88 02  42 00 e0 14 c4 60 60 0b  |....0...B....``.|
+00000190  72 68 b0 32 5d 61 4a 02  74 5c c2 81 b9 16 a8 3f  |rh.2]aJ.t\.....?|
+000001a0  29 c8 36 c7 81 ff 6c b6  5b d9 70 f1 38 3b 50 48  |).6...l.[.p.8;PH|
+000001b0  28 94 cb 09 1a 52 f1 5d  ee 8d f2 b9 f0 f0 da d9  |(....R.]........|
+000001c0  15 3a f9 bd 03 7a 87 a2  23 35 ec 02 42 01 a3 d4  |.:...z..#5..B...|
+000001d0  8a 78 35 1c 4a 9a 23 d2  0a be 2b 10 31 9d 9c 5f  |.x5.J.#...+.1.._|
+000001e0  be e8 91 b3 da 1a f5 5d  a3 23 f5 26 8b 45 70 8d  |.......].#.&.Ep.|
+000001f0  65 62 9b 7e 01 99 3d 18  f6 10 9a 38 61 9b 2e 57  |eb.~..=....8a..W|
+00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
+00000210  03 03 00 86 10 00 00 82  00 80 47 5a 2f b8 78 46  |..........GZ/.xF|
+00000220  9f 3c fc ab 8b 35 c9 77  da c3 96 78 31 7c 2b 4f  |.<...5.w...x1|+O|
+00000230  56 be 0f 33 bd 17 bc 1c  86 5a ae b3 0f 8b 18 2f  |V..3.....Z...../|
+00000240  48 0d e0 0a 20 d3 53 96  88 d2 8a 7d b6 58 13 44  |H... .S....}.X.D|
+00000250  a5 e8 19 6d 02 df a6 1b  79 c5 54 c2 ef 4d 41 4f  |...m....y.T..MAO|
+00000260  04 1c eb 37 55 b7 2b f4  7c 6d 37 9c f1 89 a0 2c  |...7U.+.|m7....,|
+00000270  0f ba 10 09 e4 a1 ee 0a  7e 9a fd 2c 32 63 1c 55  |........~..,2c.U|
+00000280  85 38 de d0 7b 5f 46 03  1f cc 4d 69 51 97 d8 d7  |.8..{_F...MiQ...|
+00000290  88 6f ba 43 04 b0 42 09  61 5e 16 03 03 00 92 0f  |.o.C..B.a^......|
+000002a0  00 00 8e 04 03 00 8a 30  81 87 02 41 14 3d 4c 71  |.......0...A.=Lq|
+000002b0  c2 32 4a 20 ee b7 69 17  55 e8 99 55 11 76 51 7a  |.2J ..i.U..U.vQz|
+000002c0  74 55 e7 e8 c3 3b b3 70  db 1c 8e f6 8a d4 99 40  |tU...;.p.......@|
+000002d0  6e da 04 fd 7a 47 41 d6  ae c0 63 ad fd 91 a8 58  |n...zGA...c....X|
+000002e0  24 b9 ac 2f 7a 4c bf 5b  24 12 cb 3a f3 02 42 00  |$../zL.[$..:..B.|
+000002f0  90 f9 48 97 0e d4 33 99  09 9f 1d a8 97 16 60 82  |..H...3.......`.|
+00000300  85 cc 5a 5d 79 f7 2f 03  2a c0 b8 12 61 ac 9f 88  |..Z]y./.*...a...|
+00000310  1d 0d 9e 0a ee 28 a8 5a  e2 42 b7 94 e2 e6 0e 13  |.....(.Z.B......|
+00000320  c8 64 dc 4e d3 6b 10 d6  83 41 9c dc d4 53 c3 08  |.d.N.k...A...S..|
+00000330  19 14 03 03 00 01 01 16  03 03 00 24 ef bd e3 23  |...........$...#|
+00000340  10 23 ae 6e b5 12 eb 9c  21 78 db 36 fd bf 7f ee  |.#.n....!x.6....|
+00000350  6f c8 00 2d b6 35 cc 2f  38 73 ae a4 34 cf 0d df  |o..-.5./8s..4...|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 24 a7 50 0f 50 b4  |..........$.P.P.|
+00000010  1c c3 4d f3 7a 64 df 65  ac 35 22 13 46 cc ec 36  |..M.zd.e.5".F..6|
+00000020  e6 d2 f3 67 94 6a 18 85  9f 4a 3c 44 a3 58 b0 17  |...g.j...J<D.X..|
+00000030  03 03 00 21 51 0a 41 8c  fd 50 e3 54 8b 6a 1f 83  |...!Q.A..P.T.j..|
+00000040  a5 37 98 e1 5b 1e ec 03  1d c7 0e 28 6d 79 3f 34  |.7..[......(my?4|
+00000050  de 1c 38 6d 7e 15 03 03  00 16 06 fc b1 7d ad 70  |..8m~........}.p|
+00000060  1a de d4 b7 b5 e7 a2 6d  1b 9a b0 31 0c cc 7b 70  |.......m...1..{p|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
new file mode 100644
index 0000000..04a5b11
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
@@ -0,0 +1,121 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 5c 01 00 00  58 03 03 52 cc 57 59 6b  |....\...X..R.WYk|
+00000010  11 07 04 39 77 20 c2 b4  3f cb 0a c9 53 fe 5b 3e  |...9w ..?...S.[>|
+00000020  5f 58 2c 7e 30 69 e1 8e  6c 9d c8 00 00 04 00 05  |_X,~0i..l.......|
+00000030  00 ff 01 00 00 2b 00 0d  00 22 00 20 06 01 06 02  |.....+...". ....|
+00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
+00000050  03 02 03 03 02 01 02 02  02 03 01 01 00 0f 00 01  |................|
+00000060  01                                                |.|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 05 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 0f 0d 00  |n8P)l...........|
+00000300  00 0b 02 01 40 00 04 04  01 04 03 00 00 16 03 03  |....@...........|
+00000310  00 04 0e 00 00 00                                 |......|
+>>> Flow 3 (client to server)
+00000000  16 03 03 01 fb 0b 00 01  f7 00 01 f4 00 01 f1 30  |...............0|
+00000010  82 01 ed 30 82 01 58 a0  03 02 01 02 02 01 00 30  |...0..X........0|
+00000020  0b 06 09 2a 86 48 86 f7  0d 01 01 05 30 26 31 10  |...*.H......0&1.|
+00000030  30 0e 06 03 55 04 0a 13  07 41 63 6d 65 20 43 6f  |0...U....Acme Co|
+00000040  31 12 30 10 06 03 55 04  03 13 09 31 32 37 2e 30  |1.0...U....127.0|
+00000050  2e 30 2e 31 30 1e 17 0d  31 31 31 32 30 38 30 37  |.0.10...11120807|
+00000060  35 35 31 32 5a 17 0d 31  32 31 32 30 37 30 38 30  |5512Z..121207080|
+00000070  30 31 32 5a 30 26 31 10  30 0e 06 03 55 04 0a 13  |012Z0&1.0...U...|
+00000080  07 41 63 6d 65 20 43 6f  31 12 30 10 06 03 55 04  |.Acme Co1.0...U.|
+00000090  03 13 09 31 32 37 2e 30  2e 30 2e 31 30 81 9c 30  |...127.0.0.10..0|
+000000a0  0b 06 09 2a 86 48 86 f7  0d 01 01 01 03 81 8c 00  |...*.H..........|
+000000b0  30 81 88 02 81 80 4e d0  7b 31 e3 82 64 d9 59 c0  |0.....N.{1..d.Y.|
+000000c0  c2 87 a4 5e 1e 8b 73 33  c7 63 53 df 66 92 06 84  |...^..s3.cS.f...|
+000000d0  f6 64 d5 8f e4 36 a7 1d  2b e8 b3 20 36 45 23 b5  |.d...6..+.. 6E#.|
+000000e0  e3 95 ae ed e0 f5 20 9c  8d 95 df 7f 5a 12 ef 87  |...... .....Z...|
+000000f0  e4 5b 68 e4 e9 0e 74 ec  04 8a 7f de 93 27 c4 01  |.[h...t......'..|
+00000100  19 7a bd f2 dc 3d 14 ab  d0 54 ca 21 0c d0 4d 6e  |.z...=...T.!..Mn|
+00000110  87 2e 5c c5 d2 bb 4d 4b  4f ce b6 2c f7 7e 88 ec  |..\...MKO..,.~..|
+00000120  7c d7 02 91 74 a6 1e 0c  1a da e3 4a 5a 2e de 13  ||...t......JZ...|
+00000130  9c 4c 40 88 59 93 02 03  01 00 01 a3 32 30 30 30  |.L@.Y.......2000|
+00000140  0e 06 03 55 1d 0f 01 01  ff 04 04 03 02 00 a0 30  |...U...........0|
+00000150  0d 06 03 55 1d 0e 04 06  04 04 01 02 03 04 30 0f  |...U..........0.|
+00000160  06 03 55 1d 23 04 08 30  06 80 04 01 02 03 04 30  |..U.#..0.......0|
+00000170  0b 06 09 2a 86 48 86 f7  0d 01 01 05 03 81 81 00  |...*.H..........|
+00000180  36 1f b3 7a 0c 75 c9 6e  37 46 61 2b d5 bd c0 a7  |6..z.u.n7Fa+....|
+00000190  4b cc 46 9a 81 58 7c 85  79 29 c8 c8 c6 67 dd 32  |K.F..X|.y)...g.2|
+000001a0  56 45 2b 75 b6 e9 24 a9  50 9a be 1f 5a fa 1a 15  |VE+u..$.P...Z...|
+000001b0  d9 cc 55 95 72 16 83 b9  c2 b6 8f fd 88 8c 38 84  |..U.r.........8.|
+000001c0  1d ab 5d 92 31 13 4f fd  83 3b c6 9d f1 11 62 b6  |..].1.O..;....b.|
+000001d0  8b ec ab 67 be c8 64 b0  11 50 46 58 17 6b 99 1c  |...g..d..PFX.k..|
+000001e0  d3 1d fc 06 f1 0e e5 96  a8 0c f9 78 20 b7 44 18  |...........x .D.|
+000001f0  51 8d 10 7e 4f 94 67 df  a3 4e 70 73 8e 90 91 85  |Q..~O.g..Nps....|
+00000200  16 03 03 00 86 10 00 00  82 00 80 44 89 7d aa 26  |...........D.}.&|
+00000210  30 ce 6b db 25 70 b0 1e  16 fa 5b 3a dd 4a 4b bd  |0.k.%p....[:.JK.|
+00000220  ec ee 50 9d 21 ba 52 b5  51 4f a8 65 d8 2e 41 e2  |..P.!.R.QO.e..A.|
+00000230  e1 dc f3 1a df 58 4f 87  7a d3 e1 e1 1c 13 b2 0b  |.....XO.z.......|
+00000240  b7 43 b7 92 f2 df 19 bb  79 71 e0 71 44 ab 19 2f  |.C......yq.qD../|
+00000250  37 11 ac 62 50 b6 f1 53  fe aa b4 bc 29 8e 0b 4c  |7..bP..S....)..L|
+00000260  0b 12 8d d5 84 a9 fa a9  ea 16 aa c3 0d da 32 c8  |..............2.|
+00000270  e0 4c 9f 99 f8 69 cd a8  c3 b1 76 42 67 f3 ff 15  |.L...i....vBg...|
+00000280  52 95 43 66 da 49 43 25  9d e5 eb 16 03 03 00 88  |R.Cf.IC%........|
+00000290  0f 00 00 84 04 01 00 80  01 d5 0e 1c 75 97 89 52  |............u..R|
+000002a0  1a f0 cc ef 93 6e 71 b2  b1 38 8c 50 11 f7 a3 02  |.....nq..8.P....|
+000002b0  71 c4 d5 6f 8d 01 83 06  2e ea 5a 10 8a 0d d0 fc  |q..o......Z.....|
+000002c0  b6 a2 63 af 4f 99 b5 eb  ab fd 01 c2 fb 26 fc fd  |..c.O........&..|
+000002d0  ad 2c b3 63 b3 87 a6 f5  14 ea 7d e7 fe a8 e7 7e  |.,.c......}....~|
+000002e0  20 ab b9 f6 c3 58 bd c0  f3 96 eb 83 dc 42 6c 0d  | ....X.......Bl.|
+000002f0  5e e8 09 55 c7 b8 24 05  dd e1 7c af 9f 2c 22 6c  |^..U..$...|..,"l|
+00000300  fa b8 94 13 3b f1 09 e1  38 59 fc a1 8c cb aa ca  |....;...8Y......|
+00000310  f8 e0 2a 9c 36 f9 c3 2b  14 03 03 00 01 01 16 03  |..*.6..+........|
+00000320  03 00 24 d0 12 7c cc d2  3e 37 1f f4 7d b4 c0 fc  |..$..|..>7..}...|
+00000330  19 f6 c8 ea 62 12 e0 0d  af 62 d4 69 f7 96 5a c0  |....b....b.i..Z.|
+00000340  97 d3 bb b0 a3 f7 3f                              |......?|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 24 cd 20 85 1e 74  |..........$. ..t|
+00000010  18 b2 71 48 d5 10 61 c6  b0 18 26 83 c2 7f f1 b1  |..qH..a...&.....|
+00000020  2f b5 35 d0 47 a8 99 9a  9a a5 62 64 fb f9 29 17  |/.5.G.....bd..).|
+00000030  03 03 00 21 22 7b ed 61  e3 9b 6d 98 b9 23 98 e3  |...!"{.a..m..#..|
+00000040  55 11 b8 0f 7e 2b e1 c1  d4 f1 83 79 c3 f8 03 f0  |U...~+.....y....|
+00000050  02 5c 61 24 d7 15 03 03  00 16 14 2b a3 5a 56 f0  |.\a$.......+.ZV.|
+00000060  92 da d0 e6 32 91 d8 30  7a b4 d0 a2 93 f5 01 ea  |....2..0z.......|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
new file mode 100644
index 0000000..562fe1a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
@@ -0,0 +1,81 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 5c 01 00 00  58 03 03 52 cc 57 59 1b  |....\...X..R.WY.|
+00000010  08 fe f7 8a bf 07 84 2b  60 a6 13 2d 15 13 f8 b6  |.......+`..-....|
+00000020  d4 b6 3b f2 7a 98 ff 32  a0 68 7c 00 00 04 00 05  |..;.z..2.h|.....|
+00000030  00 ff 01 00 00 2b 00 0d  00 22 00 20 06 01 06 02  |.....+...". ....|
+00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
+00000050  03 02 03 03 02 01 02 02  02 03 01 01 00 0f 00 01  |................|
+00000060  01                                                |.|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 05 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 0f 0d 00  |n8P)l...........|
+00000300  00 0b 02 01 40 00 04 04  01 04 03 00 00 16 03 03  |....@...........|
+00000310  00 04 0e 00 00 00                                 |......|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 07 0b 00 00  03 00 00 00 16 03 03 00  |................|
+00000010  86 10 00 00 82 00 80 6b  51 48 d3 18 7d 30 e0 0c  |.......kQH..}0..|
+00000020  20 8d f3 e4 39 47 30 0e  a5 85 79 f9 8b 11 50 9e  | ...9G0...y...P.|
+00000030  81 71 5c 26 c6 bb cb aa  d5 00 d1 89 79 b1 77 2d  |.q\&........y.w-|
+00000040  eb 9b 86 7c 52 c6 f7 b7  10 b0 b6 94 22 51 b8 12  |...|R......."Q..|
+00000050  3c 09 35 8e 1b cc f4 3b  b7 b8 78 ab 89 59 41 49  |<.5....;..x..YAI|
+00000060  21 31 eb f0 f8 94 63 3d  e6 96 8f b6 63 95 05 dd  |!1....c=....c...|
+00000070  46 b3 00 8a d6 83 75 99  1b 5a 48 0a 23 b5 10 c1  |F.....u..ZH.#...|
+00000080  95 b5 bc 15 72 b5 f5 a0  62 e2 1d c0 ff d2 87 a5  |....r...b.......|
+00000090  97 5c 33 49 a7 26 35 14  03 03 00 01 01 16 03 03  |.\3I.&5.........|
+000000a0  00 24 61 38 1f 9d fb d9  65 2e 02 07 fb be f9 85  |.$a8....e.......|
+000000b0  8d 15 34 c0 d1 0e 4e 10  3c 25 60 2f ac 04 21 66  |..4...N.<%`/..!f|
+000000c0  04 9d 9a 60 31 72                                 |...`1r|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 24 fe 0e 3e 84 af  |..........$..>..|
+00000010  e5 6b 10 ed 41 9c 2b e0  ba e0 2b 53 61 36 1b 40  |.k..A.+...+Sa6.@|
+00000020  35 de 3a c7 c3 5c df 74  67 f7 05 74 84 f5 e1 17  |5.:..\.tg..t....|
+00000030  03 03 00 21 d3 8d 81 85  b7 1f 30 bd 89 33 f9 81  |...!......0..3..|
+00000040  89 f7 af d1 be b0 c1 46  e3 df 32 f6 dc 2f 4d 82  |.......F..2../M.|
+00000050  0a 84 9f 5b 03 15 03 03  00 16 13 af 37 91 82 67  |...[........7..g|
+00000060  b0 7c 5e 0e ec 8e cc 31  a0 ea a5 72 a4 2b 0b 73  |.|^....1...r.+.s|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
new file mode 100644
index 0000000..aacbb86
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
@@ -0,0 +1,89 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 9c 01 00 00  98 03 03 53 04 f0 f9 09  |...........S....|
+00000010  13 56 01 37 84 b1 32 59  4c 73 b1 8e bb 02 1a 32  |.V.7..2YLs.....2|
+00000020  db ab 8c e6 ed ad 7f 52  9a 59 39 00 00 04 c0 0a  |.......R.Y9.....|
+00000030  00 ff 01 00 00 6b 00 0b  00 04 03 00 01 02 00 0a  |.....k..........|
+00000040  00 34 00 32 00 0e 00 0d  00 19 00 0b 00 0c 00 18  |.4.2............|
+00000050  00 09 00 0a 00 16 00 17  00 08 00 06 00 07 00 14  |................|
+00000060  00 15 00 04 00 05 00 12  00 13 00 01 00 02 00 03  |................|
+00000070  00 0f 00 10 00 11 00 0d  00 22 00 20 06 01 06 02  |.........". ....|
+00000080  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
+00000090  03 02 03 03 02 01 02 02  02 03 01 01 00 0f 00 01  |................|
+000000a0  01                                                |.|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 c0 0a 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  03 02 0e 0b 00 02 0a 00  |................|
+00000040  02 07 00 02 04 30 82 02  00 30 82 01 62 02 09 00  |.....0...0..b...|
+00000050  b8 bf 2d 47 a0 d2 eb f4  30 09 06 07 2a 86 48 ce  |..-G....0...*.H.|
+00000060  3d 04 01 30 45 31 0b 30  09 06 03 55 04 06 13 02  |=..0E1.0...U....|
+00000070  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+00000080  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000090  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+000000a0  74 73 20 50 74 79 20 4c  74 64 30 1e 17 0d 31 32  |ts Pty Ltd0...12|
+000000b0  31 31 32 32 31 35 30 36  33 32 5a 17 0d 32 32 31  |1122150632Z..221|
+000000c0  31 32 30 31 35 30 36 33  32 5a 30 45 31 0b 30 09  |120150632Z0E1.0.|
+000000d0  06 03 55 04 06 13 02 41  55 31 13 30 11 06 03 55  |..U....AU1.0...U|
+000000e0  04 08 13 0a 53 6f 6d 65  2d 53 74 61 74 65 31 21  |....Some-State1!|
+000000f0  30 1f 06 03 55 04 0a 13  18 49 6e 74 65 72 6e 65  |0...U....Interne|
+00000100  74 20 57 69 64 67 69 74  73 20 50 74 79 20 4c 74  |t Widgits Pty Lt|
+00000110  64 30 81 9b 30 10 06 07  2a 86 48 ce 3d 02 01 06  |d0..0...*.H.=...|
+00000120  05 2b 81 04 00 23 03 81  86 00 04 00 c4 a1 ed be  |.+...#..........|
+00000130  98 f9 0b 48 73 36 7e c3  16 56 11 22 f2 3d 53 c3  |...Hs6~..V.".=S.|
+00000140  3b 4d 21 3d cd 6b 75 e6  f6 b0 dc 9a df 26 c1 bc  |;M!=.ku......&..|
+00000150  b2 87 f0 72 32 7c b3 64  2f 1c 90 bc ea 68 23 10  |...r2|.d/....h#.|
+00000160  7e fe e3 25 c0 48 3a 69  e0 28 6d d3 37 00 ef 04  |~..%.H:i.(m.7...|
+00000170  62 dd 0d a0 9c 70 62 83  d8 81 d3 64 31 aa 9e 97  |b....pb....d1...|
+00000180  31 bd 96 b0 68 c0 9b 23  de 76 64 3f 1a 5c 7f e9  |1...h..#.vd?.\..|
+00000190  12 0e 58 58 b6 5f 70 dd  9b d8 ea d5 d7 f5 d5 cc  |..XX._p.........|
+000001a0  b9 b6 9f 30 66 5b 66 9a  20 e2 27 e5 bf fe 3b 30  |...0f[f. .'...;0|
+000001b0  09 06 07 2a 86 48 ce 3d  04 01 03 81 8c 00 30 81  |...*.H.=......0.|
+000001c0  88 02 42 01 88 a2 4f eb  e2 45 c5 48 7d 1b ac f5  |..B...O..E.H}...|
+000001d0  ed 98 9d ae 47 70 c0 5e  1b b6 2f bd f1 b6 4d b7  |....Gp.^../...M.|
+000001e0  61 40 d3 11 a2 ce ee 0b  7e 92 7e ff 76 9d c3 3b  |a@......~.~.v..;|
+000001f0  7e a5 3f ce fa 10 e2 59  ec 47 2d 7c ac da 4e 97  |~.?....Y.G-|..N.|
+00000200  0e 15 a0 6f d0 02 42 01  4d fc be 67 13 9c 2d 05  |...o..B.M..g..-.|
+00000210  0e bd 3f a3 8c 25 c1 33  13 83 0d 94 06 bb d4 37  |..?..%.3.......7|
+00000220  7a f6 ec 7a c9 86 2e dd  d7 11 69 7f 85 7c 56 de  |z..z......i..|V.|
+00000230  fb 31 78 2b e4 c7 78 0d  ae cb be 9e 4e 36 24 31  |.1x+..x.....N6$1|
+00000240  7b 6a 0f 39 95 12 07 8f  2a 16 03 03 00 d8 0c 00  |{j.9....*.......|
+00000250  00 d4 03 00 17 41 04 1e  18 37 ef 0d 19 51 88 35  |.....A...7...Q.5|
+00000260  75 71 b5 e5 54 5b 12 2e  8f 09 67 fd a7 24 20 3e  |uq..T[....g..$ >|
+00000270  b2 56 1c ce 97 28 5e f8  2b 2d 4f 9e f1 07 9f 6c  |.V...(^.+-O....l|
+00000280  4b 5b 83 56 e2 32 42 e9  58 b6 d7 49 a6 b5 68 1a  |K[.V.2B.X..I..h.|
+00000290  41 03 56 6b dc 5a 89 04  03 00 8b 30 81 88 02 42  |A.Vk.Z.....0...B|
+000002a0  00 c6 85 8e 06 b7 04 04  e9 cd 9e 3e cb 66 23 95  |...........>.f#.|
+000002b0  b4 42 9c 64 81 39 05 3f  b5 21 f8 28 af 60 6b 4d  |.B.d.9.?.!.(.`kM|
+000002c0  3d ba a1 4b 5e 77 ef e7  59 28 fe 1d c1 27 a2 ff  |=..K^w..Y(...'..|
+000002d0  a8 de 33 48 b3 c1 85 6a  42 9b f9 7e 7e 31 c2 e5  |..3H...jB..~~1..|
+000002e0  bd 66 02 42 00 ad 7d 06  35 ab ec 8d ac d4 ba 1b  |.f.B..}.5.......|
+000002f0  49 5e 05 5f f0 97 93 82  b8 2b 8d 91 98 63 8e b4  |I^._.....+...c..|
+00000300  14 62 db 1e c9 2c 13 ae  b7 d3 17 38 23 2f f6 7f  |.b...,.....8#/..|
+00000310  0c 4d d3 33 d2 79 d1 77  ee cb b1 c2 fc 34 b8 69  |.M.3.y.w.....4.i|
+00000320  f9 10 8b 61 89 85 16 03  03 00 04 0e 00 00 00     |...a...........|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 46 10 00 00  42 41 04 dd 22 68 a1 4e  |....F...BA.."h.N|
+00000010  04 1b 47 f9 c5 7d 04 1d  d8 fe 84 fa be 31 2e a7  |..G..}.......1..|
+00000020  f8 e5 b8 14 92 44 99 11  0e 34 97 fc e5 b1 91 cf  |.....D...4......|
+00000030  a4 d1 3f b4 71 94 c6 06  16 f0 98 c0 3e 05 f9 2f  |..?.q.......>../|
+00000040  0a 97 78 3d ef dc fa a2  d7 ee 7d 14 03 03 00 01  |..x=......}.....|
+00000050  01 16 03 03 00 40 90 bf  7f e9 c9 6e d1 80 f5 12  |.....@.....n....|
+00000060  6d c5 b7 c5 15 4b 18 a5  d3 18 1e f8 8c 4d 7e 6d  |m....K.......M~m|
+00000070  03 60 29 7c 45 7c b2 ca  8c 07 71 70 aa 23 fa 6e  |.`)|E|....qp.#.n|
+00000080  d9 0b 0a 32 4c 9e e5 00  f9 19 9b b6 8d dc d3 67  |...2L..........g|
+00000090  3d 0f bb b8 4b 9e                                 |=...K.|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |..........@.....|
+00000010  00 00 00 00 00 00 00 00  00 00 00 a1 6e e5 d1 ca  |............n...|
+00000020  03 f4 77 dc ec ee 5d f0  22 5e 7f 55 1a 8d ad 45  |..w...]."^.U...E|
+00000030  09 f1 3b b2 61 36 dc 3d  2a 1e 1f e5 a7 84 76 a9  |..;.a6.=*.....v.|
+00000040  41 5b 86 03 ac 22 18 20  9b a9 29 17 03 03 00 40  |A[...". ..)....@|
+00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000060  f5 cb 28 1e b5 bc 82 7f  82 38 54 14 e8 b9 6d 3b  |..(......8T...m;|
+00000070  bc 99 d6 0e f9 00 96 99  a8 92 2e 86 9d 62 4e 90  |.............bN.|
+00000080  27 52 58 45 20 93 90 a1  f3 a8 89 2b e7 21 24 16  |'RXE ......+.!$.|
+00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+000000a0  00 00 00 00 00 a8 2a ab  8f b0 ce 49 8b fd a5 c9  |......*....I....|
+000000b0  11 b2 04 83 18 f3 1d 6c  82 34 1d df dd 2f 45 3b  |.......l.4.../E;|
+000000c0  27 8a 0f 16 69                                    |'...i|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket
new file mode 100644
index 0000000..e3e62f2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket
@@ -0,0 +1,87 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 60 01 00 00  5c 03 03 52 cc 57 59 7e  |....`...\..R.WY~|
+00000010  43 5c 3b fd 50 ab 61 3f  64 a4 f9 bd ba 8c 28 e1  |C\;.P.a?d.....(.|
+00000020  f9 a1 45 7e 48 9e 62 af  25 de 0e 00 00 04 00 05  |..E~H.b.%.......|
+00000030  00 ff 01 00 00 2f 00 23  00 00 00 0d 00 22 00 20  |...../.#.....". |
+00000040  06 01 06 02 06 03 05 01  05 02 05 03 04 01 04 02  |................|
+00000050  04 03 03 01 03 02 03 03  02 01 02 02 02 03 01 01  |................|
+00000060  00 0f 00 01 01                                    |.....|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 35 02 00 00  31 03 03 00 00 00 00 00  |....5...1.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 05 00 00  |................|
+00000030  09 00 23 00 00 ff 01 00  01 00 16 03 03 02 be 0b  |..#.............|
+00000040  00 02 ba 00 02 b7 00 02  b4 30 82 02 b0 30 82 02  |.........0...0..|
+00000050  19 a0 03 02 01 02 02 09  00 85 b0 bb a4 8a 7f b8  |................|
+00000060  ca 30 0d 06 09 2a 86 48  86 f7 0d 01 01 05 05 00  |.0...*.H........|
+00000070  30 45 31 0b 30 09 06 03  55 04 06 13 02 41 55 31  |0E1.0...U....AU1|
+00000080  13 30 11 06 03 55 04 08  13 0a 53 6f 6d 65 2d 53  |.0...U....Some-S|
+00000090  74 61 74 65 31 21 30 1f  06 03 55 04 0a 13 18 49  |tate1!0...U....I|
+000000a0  6e 74 65 72 6e 65 74 20  57 69 64 67 69 74 73 20  |nternet Widgits |
+000000b0  50 74 79 20 4c 74 64 30  1e 17 0d 31 30 30 34 32  |Pty Ltd0...10042|
+000000c0  34 30 39 30 39 33 38 5a  17 0d 31 31 30 34 32 34  |4090938Z..110424|
+000000d0  30 39 30 39 33 38 5a 30  45 31 0b 30 09 06 03 55  |090938Z0E1.0...U|
+000000e0  04 06 13 02 41 55 31 13  30 11 06 03 55 04 08 13  |....AU1.0...U...|
+000000f0  0a 53 6f 6d 65 2d 53 74  61 74 65 31 21 30 1f 06  |.Some-State1!0..|
+00000100  03 55 04 0a 13 18 49 6e  74 65 72 6e 65 74 20 57  |.U....Internet W|
+00000110  69 64 67 69 74 73 20 50  74 79 20 4c 74 64 30 81  |idgits Pty Ltd0.|
+00000120  9f 30 0d 06 09 2a 86 48  86 f7 0d 01 01 01 05 00  |.0...*.H........|
+00000130  03 81 8d 00 30 81 89 02  81 81 00 bb 79 d6 f5 17  |....0.......y...|
+00000140  b5 e5 bf 46 10 d0 dc 69  be e6 2b 07 43 5a d0 03  |...F...i..+.CZ..|
+00000150  2d 8a 7a 43 85 b7 14 52  e7 a5 65 4c 2c 78 b8 23  |-.zC...R..eL,x.#|
+00000160  8c b5 b4 82 e5 de 1f 95  3b 7e 62 a5 2c a5 33 d6  |........;~b.,.3.|
+00000170  fe 12 5c 7a 56 fc f5 06  bf fa 58 7b 26 3f b5 cd  |..\zV.....X{&?..|
+00000180  04 d3 d0 c9 21 96 4a c7  f4 54 9f 5a bf ef 42 71  |....!.J..T.Z..Bq|
+00000190  00 fe 18 99 07 7f 7e 88  7d 7d f1 04 39 c4 a2 2e  |......~.}}..9...|
+000001a0  db 51 c9 7c e3 c0 4c 3b  32 66 01 cf af b1 1d b8  |.Q.|..L;2f......|
+000001b0  71 9a 1d db db 89 6b ae  da 2d 79 02 03 01 00 01  |q.....k..-y.....|
+000001c0  a3 81 a7 30 81 a4 30 1d  06 03 55 1d 0e 04 16 04  |...0..0...U.....|
+000001d0  14 b1 ad e2 85 5a cf cb  28 db 69 ce 23 69 de d3  |.....Z..(.i.#i..|
+000001e0  26 8e 18 88 39 30 75 06  03 55 1d 23 04 6e 30 6c  |&...90u..U.#.n0l|
+000001f0  80 14 b1 ad e2 85 5a cf  cb 28 db 69 ce 23 69 de  |......Z..(.i.#i.|
+00000200  d3 26 8e 18 88 39 a1 49  a4 47 30 45 31 0b 30 09  |.&...9.I.G0E1.0.|
+00000210  06 03 55 04 06 13 02 41  55 31 13 30 11 06 03 55  |..U....AU1.0...U|
+00000220  04 08 13 0a 53 6f 6d 65  2d 53 74 61 74 65 31 21  |....Some-State1!|
+00000230  30 1f 06 03 55 04 0a 13  18 49 6e 74 65 72 6e 65  |0...U....Interne|
+00000240  74 20 57 69 64 67 69 74  73 20 50 74 79 20 4c 74  |t Widgits Pty Lt|
+00000250  64 82 09 00 85 b0 bb a4  8a 7f b8 ca 30 0c 06 03  |d...........0...|
+00000260  55 1d 13 04 05 30 03 01  01 ff 30 0d 06 09 2a 86  |U....0....0...*.|
+00000270  48 86 f7 0d 01 01 05 05  00 03 81 81 00 08 6c 45  |H.............lE|
+00000280  24 c7 6b b1 59 ab 0c 52  cc f2 b0 14 d7 87 9d 7a  |$.k.Y..R.......z|
+00000290  64 75 b5 5a 95 66 e4 c5  2b 8e ae 12 66 1f eb 4f  |du.Z.f..+...f..O|
+000002a0  38 b3 6e 60 d3 92 fd f7  41 08 b5 25 13 b1 18 7a  |8.n`....A..%...z|
+000002b0  24 fb 30 1d ba ed 98 b9  17 ec e7 d7 31 59 db 95  |$.0.........1Y..|
+000002c0  d3 1d 78 ea 50 56 5c d5  82 5a 2d 5a 5f 33 c4 b6  |..x.PV\..Z-Z_3..|
+000002d0  d8 c9 75 90 96 8c 0f 52  98 b5 cd 98 1f 89 20 5f  |..u....R...... _|
+000002e0  f2 a0 1c a3 1b 96 94 dd  a9 fd 57 e9 70 e8 26 6d  |..........W.p.&m|
+000002f0  71 99 9b 26 6e 38 50 29  6c 90 a7 bd d9 16 03 03  |q..&n8P)l.......|
+00000300  00 04 0e 00 00 00                                 |......|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 86 10 00 00  82 00 80 6e 2e 79 82 3a  |...........n.y.:|
+00000010  c4 68 72 f5 a2 42 3d 71  f9 ec 22 8c 0b fa f0 82  |.hr..B=q..".....|
+00000020  82 c0 cb fc 52 0a 51 03  04 8c eb 4a 4e 4f b6 49  |....R.Q....JNO.I|
+00000030  ef 94 65 21 3c f7 9d 46  85 6e 35 d5 17 6b ff a3  |..e!<..F.n5..k..|
+00000040  5e 4d c1 36 1a 2f 68 f5  06 d4 2d 73 4f 1c 3b 7b  |^M.6./h...-sO.;{|
+00000050  c1 fa 4e 7e 7c f9 6c 13  a6 f4 3a 43 e9 aa be 22  |..N~|.l...:C..."|
+00000060  85 6f 2f 7c 5b b0 08 e2  86 b2 ae cb a9 12 d8 32  |.o/|[..........2|
+00000070  80 1d e4 2e 5d c3 66 d1  19 e5 89 33 2a 88 24 40  |....].f....3*.$@|
+00000080  2a 6d 6b b5 f1 92 4b 66  06 b8 49 14 03 03 00 01  |*mk...Kf..I.....|
+00000090  01 16 03 03 00 24 16 49  e2 a0 67 31 cf 0d 72 cb  |.....$.I..g1..r.|
+000000a0  ac 16 2c 80 37 71 69 f7  5f c4 d3 00 19 b7 4b fb  |..,.7qi._.....K.|
+000000b0  e5 e9 74 8e 30 b3 1c c5  ae e6                    |..t.0.....|
+>>> Flow 4 (server to client)
+00000000  16 03 03 00 72 04 00 00  6e 00 00 00 00 00 68 00  |....r...n.....h.|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 65  |...............e|
+00000020  ea 4b d1 ef ba 06 38 1e  e1 88 82 3a cd 03 ac 3b  |.K....8....:...;|
+00000030  39 0a e0 19 fd af 6c 57  30 df 31 6e f7 92 38 4b  |9.....lW0.1n..8K|
+00000040  5d 77 90 39 ff 32 51 f5  ed 12 d7 b0 7c 4d 6c c5  |]w.9.2Q.....|Ml.|
+00000050  76 e4 72 48 3e 59 23 fe  0d 15 df f4 ba ea b9 67  |v.rH>Y#........g|
+00000060  16 23 8f 7d 15 b6 11 f1  ab d7 d4 cd a3 21 82 92  |.#.}.........!..|
+00000070  2a 12 cf 95 f3 60 b2 14  03 03 00 01 01 16 03 03  |*....`..........|
+00000080  00 24 89 ad 87 04 4f 08  dc 2a 71 37 fb f1 95 d1  |.$....O..*q7....|
+00000090  2e 3c c2 6e 0f 38 5d e4  0e c3 f7 27 d0 46 a3 c1  |.<.n.8]....'.F..|
+000000a0  a8 3b 06 ed 96 ec 17 03  03 00 21 30 d4 9f 0b 49  |.;........!0...I|
+000000b0  9f a2 a8 a1 2c 0a 79 93  56 2d 8a ee 85 ed 62 42  |....,.y.V-....bB|
+000000c0  8c 18 fe 7a 09 3a 24 c4  5e ed 7d 2a 15 03 03 00  |...z.:$.^.}*....|
+000000d0  16 a0 24 0a 8b 90 4c fc  99 ba 67 bb 04 1e 59 69  |..$...L...g...Yi|
+000000e0  c2 98 49 b5 00 0b e0                              |..I....|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
new file mode 100644
index 0000000..30f0026
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
@@ -0,0 +1,87 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 60 01 00 00  5c 03 03 54 23 54 02 17  |....`...\..T#T..|
+00000010  f3 53 13 3d 48 88 c3 19  b9 d1 3d 33 7f f5 99 56  |.S.=H.....=3...V|
+00000020  04 71 1b d9 d5 64 8a 0d  4a 54 00 00 00 04 00 05  |.q...d..JT......|
+00000030  00 ff 01 00 00 2f 00 23  00 00 00 0d 00 22 00 20  |...../.#.....". |
+00000040  06 01 06 02 06 03 05 01  05 02 05 03 04 01 04 02  |................|
+00000050  04 03 03 01 03 02 03 03  02 01 02 02 02 03 01 01  |................|
+00000060  00 0f 00 01 01                                    |.....|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 35 02 00 00  31 03 03 00 00 00 00 00  |....5...1.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 05 00 00  |................|
+00000030  09 00 23 00 00 ff 01 00  01 00 16 03 03 02 be 0b  |..#.............|
+00000040  00 02 ba 00 02 b7 00 02  b4 30 82 02 b0 30 82 02  |.........0...0..|
+00000050  19 a0 03 02 01 02 02 09  00 85 b0 bb a4 8a 7f b8  |................|
+00000060  ca 30 0d 06 09 2a 86 48  86 f7 0d 01 01 05 05 00  |.0...*.H........|
+00000070  30 45 31 0b 30 09 06 03  55 04 06 13 02 41 55 31  |0E1.0...U....AU1|
+00000080  13 30 11 06 03 55 04 08  13 0a 53 6f 6d 65 2d 53  |.0...U....Some-S|
+00000090  74 61 74 65 31 21 30 1f  06 03 55 04 0a 13 18 49  |tate1!0...U....I|
+000000a0  6e 74 65 72 6e 65 74 20  57 69 64 67 69 74 73 20  |nternet Widgits |
+000000b0  50 74 79 20 4c 74 64 30  1e 17 0d 31 30 30 34 32  |Pty Ltd0...10042|
+000000c0  34 30 39 30 39 33 38 5a  17 0d 31 31 30 34 32 34  |4090938Z..110424|
+000000d0  30 39 30 39 33 38 5a 30  45 31 0b 30 09 06 03 55  |090938Z0E1.0...U|
+000000e0  04 06 13 02 41 55 31 13  30 11 06 03 55 04 08 13  |....AU1.0...U...|
+000000f0  0a 53 6f 6d 65 2d 53 74  61 74 65 31 21 30 1f 06  |.Some-State1!0..|
+00000100  03 55 04 0a 13 18 49 6e  74 65 72 6e 65 74 20 57  |.U....Internet W|
+00000110  69 64 67 69 74 73 20 50  74 79 20 4c 74 64 30 81  |idgits Pty Ltd0.|
+00000120  9f 30 0d 06 09 2a 86 48  86 f7 0d 01 01 01 05 00  |.0...*.H........|
+00000130  03 81 8d 00 30 81 89 02  81 81 00 bb 79 d6 f5 17  |....0.......y...|
+00000140  b5 e5 bf 46 10 d0 dc 69  be e6 2b 07 43 5a d0 03  |...F...i..+.CZ..|
+00000150  2d 8a 7a 43 85 b7 14 52  e7 a5 65 4c 2c 78 b8 23  |-.zC...R..eL,x.#|
+00000160  8c b5 b4 82 e5 de 1f 95  3b 7e 62 a5 2c a5 33 d6  |........;~b.,.3.|
+00000170  fe 12 5c 7a 56 fc f5 06  bf fa 58 7b 26 3f b5 cd  |..\zV.....X{&?..|
+00000180  04 d3 d0 c9 21 96 4a c7  f4 54 9f 5a bf ef 42 71  |....!.J..T.Z..Bq|
+00000190  00 fe 18 99 07 7f 7e 88  7d 7d f1 04 39 c4 a2 2e  |......~.}}..9...|
+000001a0  db 51 c9 7c e3 c0 4c 3b  32 66 01 cf af b1 1d b8  |.Q.|..L;2f......|
+000001b0  71 9a 1d db db 89 6b ae  da 2d 79 02 03 01 00 01  |q.....k..-y.....|
+000001c0  a3 81 a7 30 81 a4 30 1d  06 03 55 1d 0e 04 16 04  |...0..0...U.....|
+000001d0  14 b1 ad e2 85 5a cf cb  28 db 69 ce 23 69 de d3  |.....Z..(.i.#i..|
+000001e0  26 8e 18 88 39 30 75 06  03 55 1d 23 04 6e 30 6c  |&...90u..U.#.n0l|
+000001f0  80 14 b1 ad e2 85 5a cf  cb 28 db 69 ce 23 69 de  |......Z..(.i.#i.|
+00000200  d3 26 8e 18 88 39 a1 49  a4 47 30 45 31 0b 30 09  |.&...9.I.G0E1.0.|
+00000210  06 03 55 04 06 13 02 41  55 31 13 30 11 06 03 55  |..U....AU1.0...U|
+00000220  04 08 13 0a 53 6f 6d 65  2d 53 74 61 74 65 31 21  |....Some-State1!|
+00000230  30 1f 06 03 55 04 0a 13  18 49 6e 74 65 72 6e 65  |0...U....Interne|
+00000240  74 20 57 69 64 67 69 74  73 20 50 74 79 20 4c 74  |t Widgits Pty Lt|
+00000250  64 82 09 00 85 b0 bb a4  8a 7f b8 ca 30 0c 06 03  |d...........0...|
+00000260  55 1d 13 04 05 30 03 01  01 ff 30 0d 06 09 2a 86  |U....0....0...*.|
+00000270  48 86 f7 0d 01 01 05 05  00 03 81 81 00 08 6c 45  |H.............lE|
+00000280  24 c7 6b b1 59 ab 0c 52  cc f2 b0 14 d7 87 9d 7a  |$.k.Y..R.......z|
+00000290  64 75 b5 5a 95 66 e4 c5  2b 8e ae 12 66 1f eb 4f  |du.Z.f..+...f..O|
+000002a0  38 b3 6e 60 d3 92 fd f7  41 08 b5 25 13 b1 18 7a  |8.n`....A..%...z|
+000002b0  24 fb 30 1d ba ed 98 b9  17 ec e7 d7 31 59 db 95  |$.0.........1Y..|
+000002c0  d3 1d 78 ea 50 56 5c d5  82 5a 2d 5a 5f 33 c4 b6  |..x.PV\..Z-Z_3..|
+000002d0  d8 c9 75 90 96 8c 0f 52  98 b5 cd 98 1f 89 20 5f  |..u....R...... _|
+000002e0  f2 a0 1c a3 1b 96 94 dd  a9 fd 57 e9 70 e8 26 6d  |..........W.p.&m|
+000002f0  71 99 9b 26 6e 38 50 29  6c 90 a7 bd d9 16 03 03  |q..&n8P)l.......|
+00000300  00 04 0e 00 00 00                                 |......|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 86 10 00 00  82 00 80 27 e9 a4 f7 e7  |...........'....|
+00000010  df 25 de 84 8c 1f d6 e6  c3 11 28 55 9a c1 91 37  |.%........(U...7|
+00000020  84 f5 ba f8 80 0d ca 50  cb 1e 72 f7 97 6f c2 b2  |.......P..r..o..|
+00000030  04 4d 13 7c e0 6e a0 1f  91 e1 38 1b a2 c0 55 16  |.M.|.n....8...U.|
+00000040  7f 29 fc ed 1c 1a cf 72  14 c3 00 c1 dd 36 36 af  |.).....r.....66.|
+00000050  a6 e4 a8 be ba ec 13 d0  1e d0 1d fd e1 5b 27 fd  |.............['.|
+00000060  9a da 2e 12 c8 b0 b9 c2  b9 76 ec 7f 3c 98 b6 63  |.........v..<..c|
+00000070  bc da f0 07 7a 3d e7 61  f4 2f 12 80 3b f9 3b cc  |....z=.a./..;.;.|
+00000080  05 c8 2f 7e 28 b2 73 bf  97 61 29 14 03 03 00 01  |../~(.s..a).....|
+00000090  01 16 03 03 00 24 17 59  a9 45 53 46 33 96 50 dd  |.....$.Y.ESF3.P.|
+000000a0  3e 23 aa 91 38 f8 56 4a  2f 1a f2 b1 44 9b ce 17  |>#..8.VJ/...D...|
+000000b0  6b 8a 89 76 bc 67 b8 8b  ba 90                    |k..v.g....|
+>>> Flow 4 (server to client)
+00000000  16 03 03 00 72 04 00 00  6e 00 00 00 00 00 68 00  |....r...n.....h.|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 65  |...............e|
+00000020  ea 4b d1 ef ba 2d db 0c  ba 9a d4 20 76 57 c8 ec  |.K...-..... vW..|
+00000030  dc 2d 77 fb fb 3b 93 5f  53 e0 14 4f 90 fb d6 55  |.-w..;._S..O...U|
+00000040  57 8c 8d 0d 25 ea 5d 0d  f2 91 e5 12 22 12 ec 7b  |W...%.]....."..{|
+00000050  5f b6 6e fd 07 59 23 24  fc b1 97 ca ea 56 a5 c2  |_.n..Y#$.....V..|
+00000060  a0 e4 9e 99 64 f2 64 d0  75 7a 46 63 e3 dc 21 ed  |....d.d.uzFc..!.|
+00000070  78 56 e9 e1 ab 66 80 14  03 03 00 01 01 16 03 03  |xV...f..........|
+00000080  00 24 fc 14 68 07 17 1f  df b7 84 cb fd c1 e0 e4  |.$..h...........|
+00000090  f2 1a ea 34 b5 00 7f 70  be c8 1c 0a d6 55 e3 57  |...4...p.....U.W|
+000000a0  50 4e 6d 7d 8a 5d 17 03  03 00 21 24 27 50 40 c1  |PNm}.]....!$'P@.|
+000000b0  c5 bd c7 9f 95 d9 ba 2e  7b 0e db ea a7 31 81 05  |........{....1..|
+000000c0  75 43 b1 63 cf b8 55 92  ef 76 98 a9 15 03 03 00  |uC.c..U..v......|
+000000d0  16 d7 ea 3c 79 e7 a6 2f  61 39 ec 4e 95 86 48 5e  |...<y../a9.N..H^|
+000000e0  75 a0 9e 41 42 89 67                              |u..AB.g|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-3DES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-3DES
new file mode 100644
index 0000000..5995b33
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-3DES
@@ -0,0 +1,83 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 5c 01 00 00  58 03 03 52 cc 57 59 68  |....\...X..R.WYh|
+00000010  11 72 a6 ec 6b 0a 47 1d  10 06 ec 75 af 07 38 a0  |.r..k.G....u..8.|
+00000020  30 9e 91 12 e1 9b 19 46  0d d4 45 00 00 04 00 0a  |0......F..E.....|
+00000030  00 ff 01 00 00 2b 00 0d  00 22 00 20 06 01 06 02  |.....+...". ....|
+00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
+00000050  03 02 03 03 02 01 02 02  02 03 01 01 00 0f 00 01  |................|
+00000060  01                                                |.|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 0a 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 86 10 00 00  82 00 80 7a c0 73 ec cb  |...........z.s..|
+00000010  cf c2 a8 86 c0 7e 03 63  57 a1 ce 42 37 6d 78 54  |.....~.cW..B7mxT|
+00000020  29 f5 3e cc 57 c7 0d d9  69 e1 52 5c 3b 6b c4 c7  |).>.W...i.R\;k..|
+00000030  20 6d 59 ee c0 07 81 74  74 9f 62 41 64 f0 4d c8  | mY....tt.bAd.M.|
+00000040  9b aa 1a b9 da 56 07 f5  6c 1c 59 8c d3 f9 08 d9  |.....V..l.Y.....|
+00000050  08 f4 16 93 5d 9a e5 6f  fb 9f ba 3d 3c d6 81 ad  |....]..o...=<...|
+00000060  02 12 a7 28 b6 81 6a 77  c3 e9 d7 c7 54 d6 77 83  |...(..jw....T.w.|
+00000070  77 de 71 fb b3 f3 2d c4  a5 b1 e5 de aa 0e 21 bd  |w.q...-.......!.|
+00000080  91 a2 dc 7f f7 6f 90 82  54 b1 e7 14 03 03 00 01  |.....o..T.......|
+00000090  01 16 03 03 00 30 8f ee  bf fb c8 5c 54 f5 29 23  |.....0.....\T.)#|
+000000a0  d4 55 f6 98 a1 6e d5 43  e7 81 b2 36 f2 98 d8 1b  |.U...n.C...6....|
+000000b0  0d 76 cb 14 ba 32 d7 36  30 e6 ab 42 80 95 f6 8a  |.v...2.60..B....|
+000000c0  60 64 a0 6b 90 81                                 |`d.k..|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 30 00 00 00 00 00  |..........0.....|
+00000010  00 00 00 2c 21 52 34 63  ac e3 a3 66 45 00 41 0c  |...,!R4c...fE.A.|
+00000020  93 5d 6a 74 5a 25 dc 69  1d 76 73 0c f4 42 6a 18  |.]jtZ%.i.vs..Bj.|
+00000030  5b 62 23 e7 fe 41 cf d4  9b 86 35 17 03 03 00 30  |[b#..A....5....0|
+00000040  00 00 00 00 00 00 00 00  7d 5d ce 43 85 5c 6b 89  |........}].C.\k.|
+00000050  c9 a5 0e 22 69 8e b9 4a  77 4c c0 4e cc 79 d9 7e  |..."i..JwL.N.y.~|
+00000060  a3 c8 d3 db 5c 53 f8 92  4d c4 5a 88 72 58 05 11  |....\S..M.Z.rX..|
+00000070  15 03 03 00 20 00 00 00  00 00 00 00 00 1d 63 8b  |.... .........c.|
+00000080  a7 74 fb 76 1d 47 31 93  1f ec 8c e2 18 8e 21 dd  |.t.v.G1.......!.|
+00000090  87 97 9f 1c ca                                    |.....|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES
new file mode 100644
index 0000000..a152a96
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES
@@ -0,0 +1,87 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 5c 01 00 00  58 03 03 52 cc 57 59 d0  |....\...X..R.WY.|
+00000010  38 05 36 7e e3 1e 93 2a  5a bf dc c2 f8 0a 03 6f  |8.6~...*Z......o|
+00000020  1a fc 21 74 e5 8b 2a c3  9e 2c 26 00 00 04 00 2f  |..!t..*..,&..../|
+00000030  00 ff 01 00 00 2b 00 0d  00 22 00 20 06 01 06 02  |.....+...". ....|
+00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
+00000050  03 02 03 03 02 01 02 02  02 03 01 01 00 0f 00 01  |................|
+00000060  01                                                |.|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 2f 00 00  |............./..|
+00000030  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 86 10 00 00  82 00 80 4b b4 28 bc 78  |...........K.(.x|
+00000010  41 34 f3 49 e8 74 07 74  42 ae 2e 55 9e 9a ce e5  |A4.I.t.tB..U....|
+00000020  4a 1b e7 55 c7 64 c4 9c  b3 dd 20 d6 f8 8e 67 b3  |J..U.d.... ...g.|
+00000030  7a 5c 3b 34 e4 1a f6 bd  65 fc 21 cd 9a de 64 77  |z\;4....e.!...dw|
+00000040  09 a5 92 e5 a4 f5 18 7b  23 5b 8b c1 95 23 97 6f  |.......{#[...#.o|
+00000050  76 55 04 34 22 7d 43 71  db cd eb f8 36 36 44 4b  |vU.4"}Cq....66DK|
+00000060  ae e3 cc ec 64 88 7b e1  ea d6 ab 49 35 94 a5 04  |....d.{....I5...|
+00000070  1e 83 c5 cf 21 bb ca 33  5f d4 bf 1d d3 4d 07 59  |....!..3_....M.Y|
+00000080  b4 39 b2 4b 7b 05 43 70  0d ba 7a 14 03 03 00 01  |.9.K{.Cp..z.....|
+00000090  01 16 03 03 00 40 74 4b  7d b2 53 49 ea 86 90 c3  |.....@tK}.SI....|
+000000a0  64 6b 64 31 1a 2a 3f 1a  37 1e 56 b8 dd 12 6d 56  |dkd1.*?.7.V...mV|
+000000b0  2a 61 92 5b 39 e7 e1 be  71 70 4b 9b b3 f0 71 e7  |*a.[9...qpK...q.|
+000000c0  47 2e 2e 17 c3 0a 66 9f  69 74 30 2d f0 a0 7f 84  |G.....f.it0-....|
+000000d0  25 db c1 81 ee cf                                 |%.....|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |..........@.....|
+00000010  00 00 00 00 00 00 00 00  00 00 00 f3 4d 5a fc 21  |............MZ.!|
+00000020  30 b5 a1 86 9d e2 ea 38  ac 54 57 fa 5a 54 97 b8  |0......8.TW.ZT..|
+00000030  bb 4d 64 09 ef ce a1 75  0c 50 8d ff 5c c2 e9 47  |.Md....u.P..\..G|
+00000040  95 93 53 c0 bd dc c5 9c  e0 59 17 17 03 03 00 40  |..S......Y.....@|
+00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000060  69 c5 48 6e 45 cf 98 1b  2c 23 40 d1 ab a3 c2 e2  |i.HnE...,#@.....|
+00000070  10 7b b1 c8 21 3c f0 eb  96 bd 4f 78 b2 4a 7b 18  |.{..!<....Ox.J{.|
+00000080  4c b1 a6 67 bf 06 40 01  d0 8d 91 be 17 d8 0c 71  |L..g..@........q|
+00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+000000a0  00 00 00 00 00 20 84 80  3d 70 fe ae ee d7 2f e9  |..... ..=p..../.|
+000000b0  bf 65 30 bf 0b dd 98 ea  bb ba 12 14 98 53 7f d5  |.e0..........S..|
+000000c0  56 ce 06 3c d0                                    |V..<.|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
new file mode 100644
index 0000000..0ddfe02
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
@@ -0,0 +1,93 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 9c 01 00 00  98 03 03 53 04 f1 30 73  |...........S..0s|
+00000010  a1 ea 8c d2 90 1c c6 d6  0d 3c af 58 21 65 90 25  |.........<.X!e.%|
+00000020  5e fa f4 27 22 65 c9 68  90 b9 04 00 00 04 c0 2f  |^..'"e.h......./|
+00000030  00 ff 01 00 00 6b 00 0b  00 04 03 00 01 02 00 0a  |.....k..........|
+00000040  00 34 00 32 00 0e 00 0d  00 19 00 0b 00 0c 00 18  |.4.2............|
+00000050  00 09 00 0a 00 16 00 17  00 08 00 06 00 07 00 14  |................|
+00000060  00 15 00 04 00 05 00 12  00 13 00 01 00 02 00 03  |................|
+00000070  00 0f 00 10 00 11 00 0d  00 22 00 20 06 01 06 02  |.........". ....|
+00000080  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
+00000090  03 02 03 03 02 01 02 02  02 03 01 01 00 0f 00 01  |................|
+000000a0  01                                                |.|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 c0 2f 00 00  |............./..|
+00000030  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 cd 0c 00  |n8P)l...........|
+00000300  00 c9 03 00 17 41 04 1e  18 37 ef 0d 19 51 88 35  |.....A...7...Q.5|
+00000310  75 71 b5 e5 54 5b 12 2e  8f 09 67 fd a7 24 20 3e  |uq..T[....g..$ >|
+00000320  b2 56 1c ce 97 28 5e f8  2b 2d 4f 9e f1 07 9f 6c  |.V...(^.+-O....l|
+00000330  4b 5b 83 56 e2 32 42 e9  58 b6 d7 49 a6 b5 68 1a  |K[.V.2B.X..I..h.|
+00000340  41 03 56 6b dc 5a 89 04  01 00 80 a2 54 61 84 29  |A.Vk.Z......Ta.)|
+00000350  3e 97 4b 97 9a 9f 5c c0  49 6d 86 d2 79 8e 95 a1  |>.K...\.Im..y...|
+00000360  0a 5a 36 73 34 bb 05 73  35 47 e1 2b 5d f3 ef 36  |.Z6s4..s5G.+]..6|
+00000370  a8 32 e2 7e ef aa 3f 1f  b3 64 60 d4 06 2e 98 e3  |.2.~..?..d`.....|
+00000380  11 e2 60 3c d6 20 17 63  b2 6f a0 cd 21 01 2b 4e  |..`<. .c.o..!.+N|
+00000390  b2 a8 55 04 39 37 5c 6c  71 66 4d a3 eb 1b 83 67  |..U.97\lqfM....g|
+000003a0  6b 15 a0 56 9a f1 a2 79  92 29 ce 58 3c 10 4d 65  |k..V...y.).X<.Me|
+000003b0  1f 22 e3 ea d8 74 aa 01  7e ca f3 89 23 41 4d bd  |."...t..~...#AM.|
+000003c0  df 77 4e 59 54 97 74 ad  07 ea c0 16 03 03 00 04  |.wNYT.t.........|
+000003d0  0e 00 00 00                                       |....|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 46 10 00 00  42 41 04 45 65 ce f7 b9  |....F...BA.Ee...|
+00000010  52 e3 fb 13 db 91 f2 65  43 84 57 f5 1a 19 a0 e6  |R......eC.W.....|
+00000020  89 2d bb 2c 83 6b 62 f6  6f 1f 26 ae 59 67 bd dc  |.-.,.kb.o.&.Yg..|
+00000030  c4 9e 0b dc 7d 6e f8 6b  95 8c 61 47 3d cd d1 df  |....}n.k..aG=...|
+00000040  82 45 30 81 c3 a3 49 5d  85 59 70 14 03 03 00 01  |.E0...I].Yp.....|
+00000050  01 16 03 03 00 28 3f aa  85 33 f9 c6 95 a0 56 ff  |.....(?..3....V.|
+00000060  1c f1 5a ba 6e 41 50 0c  ab 92 e1 e2 8e 89 1c f1  |..Z.nAP.........|
+00000070  fa 54 1b f1 f5 00 01 12  6d c4 96 78 b6 87        |.T......m..x..|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 28 00 00 00 00 00  |..........(.....|
+00000010  00 00 00 94 5c be 46 05  d6 d0 b0 3a 56 dc 2c 10  |....\.F....:V.,.|
+00000020  0f 6f 5d 33 33 7f a5 4e  74 84 bf 63 87 c4 f4 49  |.o]33..Nt..c...I|
+00000030  bc 6b ab 17 03 03 00 25  00 00 00 00 00 00 00 01  |.k.....%........|
+00000040  7e 4f f9 ae ae fe 6b a0  4a f8 0f 0b b4 b6 65 b6  |~O....k.J.....e.|
+00000050  be 24 5f 94 6d d1 db 54  11 07 b9 ce 01 15 03 03  |.$_.m..T........|
+00000060  00 1a 00 00 00 00 00 00  00 02 a8 1c d6 62 ac fd  |.............b..|
+00000070  77 ba 23 92 5d 34 f1 17  c7 e1 1c 99              |w.#.]4......|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4 b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4
new file mode 100644
index 0000000..b703a8f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4
@@ -0,0 +1,79 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 5c 01 00 00  58 03 03 52 cc 57 59 c9  |....\...X..R.WY.|
+00000010  c3 13 fc 18 8a ee c2 0e  88 ff fb 4a 16 f2 eb eb  |...........J....|
+00000020  d4 f8 b3 5b cd bb 25 0e  0b cb 48 00 00 04 00 05  |...[..%...H.....|
+00000030  00 ff 01 00 00 2b 00 0d  00 22 00 20 06 01 06 02  |.....+...". ....|
+00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
+00000050  03 02 03 03 02 01 02 02  02 03 01 01 00 0f 00 01  |................|
+00000060  01                                                |.|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 05 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 86 10 00 00  82 00 80 35 b3 60 ba 14  |...........5.`..|
+00000010  5f 19 24 a0 24 de 4e 85  a9 64 78 3a 51 24 64 70  |_.$.$.N..dx:Q$dp|
+00000020  88 55 6d c3 11 b8 d3 9f  bc 7a 33 f8 3c 48 93 2f  |.Um......z3.<H./|
+00000030  66 69 11 33 39 37 7a 36  a3 1c ef b0 81 71 7d 25  |fi.397z6.....q}%|
+00000040  35 da 2c 42 e2 ab d3 b7  07 8b 4a 0d 6d 77 bd ae  |5.,B......J.mw..|
+00000050  02 51 7c a5 0d a6 03 4c  3c d0 ce 89 2c 83 6c de  |.Q|....L<...,.l.|
+00000060  40 15 cc 72 c7 95 c8 6d  ee 05 86 da 3e c6 7c d4  |@..r...m....>.|.|
+00000070  44 82 f4 24 03 22 40 00  64 27 53 15 41 8c 01 e9  |D..$."@.d'S.A...|
+00000080  39 32 fa 8e 2d f9 b4 89  34 15 d6 14 03 03 00 01  |92..-...4.......|
+00000090  01 16 03 03 00 24 f5 61  8b 24 bf b4 82 3a cf 49  |.....$.a.$...:.I|
+000000a0  99 a0 b1 1b a7 a7 a3 92  7c 84 85 e0 64 a3 3d bd  |........|...d.=.|
+000000b0  38 98 7d 97 a8 b9 2a 35  a9 09                    |8.}...*5..|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 24 c9 0b 84 e6 39  |..........$....9|
+00000010  f2 e0 f3 ac 9f 0f 17 92  5f 6d de 94 18 c4 60 d9  |........_m....`.|
+00000020  66 c3 0d 1a ae c2 8f 46  8f 7f f0 58 0e 4a 9b 17  |f......F...X.J..|
+00000030  03 03 00 21 8b 73 a1 6a  7e d9 7e 4f 1d cc b2 7d  |...!.s.j~.~O...}|
+00000040  3c 83 3f 52 f8 08 77 01  4c 65 11 6d 50 25 9a cc  |<.?R..w.Le.mP%..|
+00000050  e3 54 27 72 59 15 03 03  00 16 3d c8 ab 14 51 fa  |.T'rY.....=...Q.|
+00000060  97 f1 ef 5f b4 4f 44 58  d4 93 3b ae e5 61 1f a3  |..._.ODX..;..a..|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-Resume b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-Resume
new file mode 100644
index 0000000..c495d4a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-Resume
@@ -0,0 +1,36 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 e8 01 00 00  e4 03 03 52 cc 57 59 c3  |...........R.WY.|
+00000010  8b df 97 05 d8 5f 16 22  b4 b1 e7 cb 7d 2f 9b 58  |....._."....}/.X|
+00000020  a3 f4 d7 2c a4 c1 9d 49  ed 4b ba 20 90 da 90 3e  |...,...I.K. ...>|
+00000030  36 19 7a db 56 43 26 f7  dc 42 57 33 22 ed 9d a4  |6.z.VC&..BW3"...|
+00000040  9d 53 da f8 9d 4e 60 66  71 a0 2e 2e 00 04 00 05  |.S...N`fq.......|
+00000050  00 ff 01 00 00 97 00 23  00 68 00 00 00 00 00 00  |.......#.h......|
+00000060  00 00 00 00 00 00 00 00  00 00 65 ea 4b d1 ef ba  |..........e.K...|
+00000070  06 38 1e e1 88 82 3a cd  03 ac 3b 39 0a e0 19 fd  |.8....:...;9....|
+00000080  af 6c 57 30 df 31 6e f7  92 38 4b 5d 77 90 39 ff  |.lW0.1n..8K]w.9.|
+00000090  32 51 f5 ed 12 d7 b0 7c  4d 6c c5 76 e4 72 48 3e  |2Q.....|Ml.v.rH>|
+000000a0  59 23 fe 0d 15 df f4 ba  ea b9 67 16 23 8f 7d 15  |Y#........g.#.}.|
+000000b0  b6 11 f1 ab d7 d4 cd a3  21 82 92 2a 12 cf 95 f3  |........!..*....|
+000000c0  60 b2 00 0d 00 22 00 20  06 01 06 02 06 03 05 01  |`....". ........|
+000000d0  05 02 05 03 04 01 04 02  04 03 03 01 03 02 03 03  |................|
+000000e0  02 01 02 02 02 03 01 01  00 0f 00 01 01           |.............|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 51 02 00 00  4d 03 03 00 00 00 00 00  |....Q...M.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 20 90 da 90 3e  |........... ...>|
+00000030  36 19 7a db 56 43 26 f7  dc 42 57 33 22 ed 9d a4  |6.z.VC&..BW3"...|
+00000040  9d 53 da f8 9d 4e 60 66  71 a0 2e 2e 00 05 00 00  |.S...N`fq.......|
+00000050  05 ff 01 00 01 00 14 03  03 00 01 01 16 03 03 00  |................|
+00000060  24 11 12 ff 28 10 14 4c  e5 0e ad a7 fa f3 92 fb  |$...(..L........|
+00000070  13 7d ae f2 b2 4a 6b a1  9e 67 cf a8 f7 8c 6f a0  |.}...Jk..g....o.|
+00000080  6c 30 0e 18 55                                    |l0..U|
+>>> Flow 3 (client to server)
+00000000  14 03 03 00 01 01 16 03  03 00 24 0d 46 41 8b 24  |..........$.FA.$|
+00000010  36 01 a9 fd 8b ec fc e6  b1 83 96 df 0d 3e 53 54  |6............>ST|
+00000020  58 b8 43 f2 a6 25 5e 1a  ae 19 9e d2 28 44 92     |X.C..%^.....(D.|
+>>> Flow 4 (server to client)
+00000000  17 03 03 00 21 c4 fb f6  53 bb 3e 04 cc 0b a0 03  |....!...S.>.....|
+00000010  fa 49 96 da b5 8d b2 f2  e5 d8 f3 5c 27 57 4f 9c  |.I.........\'WO.|
+00000020  30 00 34 fc 52 92 15 03  03 00 16 a3 02 7a 50 d2  |0.4.R........zP.|
+00000030  c6 b3 fc 69 8f e4 94 ae  ab 22 ad 05 1d 15 69 b9  |...i....."....i.|
+00000040  a5                                                |.|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
new file mode 100644
index 0000000..db833f6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
@@ -0,0 +1,87 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 e8 01 00 00  e4 03 03 54 23 54 02 a5  |...........T#T..|
+00000010  10 11 0f 6d e5 2d 2f e8  bb 52 b1 38 3f 65 01 43  |...m.-/..R.8?e.C|
+00000020  36 cc 48 f6 09 22 a1 85  20 28 3c 20 35 8b fe 7a  |6.H..".. (< 5..z|
+00000030  41 3b 59 3a 5d b9 b3 21  f0 62 e9 0d 7b af f5 5d  |A;Y:]..!.b..{..]|
+00000040  fa 65 1a 40 c8 ca cd 74  8c ef d2 fb 00 04 00 05  |.e.@...t........|
+00000050  00 ff 01 00 00 97 00 23  00 68 00 00 00 00 00 00  |.......#.h......|
+00000060  00 00 00 00 00 00 00 00  00 00 65 ea 4b d1 ef ba  |..........e.K...|
+00000070  2d db 0c ba 9a d4 20 76  57 c8 ec dc 2d 77 fb fb  |-..... vW...-w..|
+00000080  3b 93 5f 53 e0 14 4f 90  fb d6 55 57 8c 8d 0d 25  |;._S..O...UW...%|
+00000090  ea 5d 0d f2 91 e5 12 22  12 ec 7b 5f b6 6e fd 07  |.]....."..{_.n..|
+000000a0  59 23 24 fc b1 97 ca ea  56 a5 c2 a0 e4 9e 99 64  |Y#$.....V......d|
+000000b0  f2 64 d0 75 7a 46 63 e3  dc 21 ed 78 56 e9 e1 ab  |.d.uzFc..!.xV...|
+000000c0  66 80 00 0d 00 22 00 20  06 01 06 02 06 03 05 01  |f....". ........|
+000000d0  05 02 05 03 04 01 04 02  04 03 03 01 03 02 03 03  |................|
+000000e0  02 01 02 02 02 03 01 01  00 0f 00 01 01           |.............|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 05 00 00  |................|
+00000030  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
+00000040  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
+00000050  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
+00000060  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
+00000070  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
+00000080  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
+00000090  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
+000000a0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
+000000b0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
+000000c0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
+000000d0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
+000000e0  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
+000000f0  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
+00000100  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
+00000110  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
+00000120  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
+00000130  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
+00000140  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
+00000150  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
+00000160  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
+00000170  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
+00000180  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
+00000190  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
+000001a0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
+000001b0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
+000001c0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
+000001d0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
+000001e0  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
+000001f0  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
+00000200  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
+00000210  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
+00000220  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
+00000230  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
+00000240  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
+00000250  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
+00000260  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
+00000270  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
+00000280  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
+00000290  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
+000002a0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
+000002b0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
+000002c0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
+000002d0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
+000002e0  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
+000002f0  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 04 0e 00  |n8P)l...........|
+00000300  00 00                                             |..|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 86 10 00 00  82 00 80 ae 02 dd 1f 1a  |................|
+00000010  86 83 f5 2f 82 46 4b 29  58 aa a1 b3 56 8b 4e 40  |.../.FK)X...V.N@|
+00000020  ef 23 65 67 ad 48 e5 e1  fd ae dd bf 68 fd bd a6  |.#eg.H......h...|
+00000030  13 a0 7e 05 ab f7 20 e1  6a 4e d1 37 93 08 1d c9  |..~... .jN.7....|
+00000040  37 e0 b5 34 28 bf 20 45  45 da 0f 7e 51 a7 c6 ae  |7..4(. EE..~Q...|
+00000050  61 6c 07 1b 73 ef da 6e  25 c4 ed be e3 3f da ae  |al..s..n%....?..|
+00000060  cd 3c 17 9c 2e ee fb 47  9d b3 a1 b2 c3 5d e0 83  |.<.....G.....]..|
+00000070  74 20 37 2d 72 d6 d0 4d  58 0e 26 1c 50 22 95 08  |t 7-r..MX.&.P"..|
+00000080  7d e0 5f 86 99 9e 2c 2e  a7 a0 7f 14 03 03 00 01  |}._...,.........|
+00000090  01 16 03 03 00 24 a2 ab  41 25 a5 cf 04 18 1d 98  |.....$..A%......|
+000000a0  88 6c 59 21 86 33 54 f4  35 b4 21 6e a5 29 d5 6e  |.lY!.3T.5.!n.).n|
+000000b0  3d 08 72 b0 af 46 b5 8f  6b 86                    |=.r..F..k.|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 24 59 20 4d c2 17  |..........$Y M..|
+00000010  8b 3c 9b 33 d9 f9 ef fb  80 18 1f 67 a7 58 12 89  |.<.3.......g.X..|
+00000020  4e 73 0f 2d 7b e6 c4 a6  79 73 01 da 22 e8 54 17  |Ns.-{...ys..".T.|
+00000030  03 03 00 21 36 ca 64 0f  4a 12 a5 50 3d 97 bb 39  |...!6.d.J..P=..9|
+00000040  02 fc ed d1 82 6a 9a 2e  21 79 f6 e1 b3 cc 32 db  |.....j..!y....2.|
+00000050  0f 5d b3 fb a5 15 03 03  00 16 51 f4 be 57 7a df  |.]........Q..Wz.|
+00000060  f1 f2 bd b5 51 5e 45 80  be 0b 9a 0c d1 19 3c 79  |....Q^E.......<y|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI
new file mode 100644
index 0000000..61b17a1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI
@@ -0,0 +1,76 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 70 01 00 00  6c 03 03 52 cc 57 59 2d  |....p...l..R.WY-|
+00000010  77 aa 75 35 fa ff 2a a2  bf 91 5e e3 7f 38 7d 7a  |w.u5..*...^..8}z|
+00000020  e3 93 d3 e8 8b 09 bb 06  c8 6d 91 00 00 04 00 2f  |.........m...../|
+00000030  00 ff 01 00 00 3f 00 00  00 10 00 0e 00 00 0b 73  |.....?.........s|
+00000040  6e 69 74 65 73 74 2e 63  6f 6d 00 0d 00 22 00 20  |nitest.com...". |
+00000050  06 01 06 02 06 03 05 01  05 02 05 03 04 01 04 02  |................|
+00000060  04 03 03 01 03 02 03 03  02 01 02 02 02 03 01 01  |................|
+00000070  00 0f 00 01 01                                    |.....|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 2f 00 00  |............./..|
+00000030  05 ff 01 00 01 00 16 03  03 02 00 0b 00 01 fc 00  |................|
+00000040  01 f9 00 01 f6 30 82 01  f2 30 82 01 5d a0 03 02  |.....0...0..]...|
+00000050  01 02 02 01 00 30 0b 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
+00000060  01 05 30 28 31 10 30 0e  06 03 55 04 0a 13 07 41  |..0(1.0...U....A|
+00000070  63 6d 65 20 43 6f 31 14  30 12 06 03 55 04 03 13  |cme Co1.0...U...|
+00000080  0b 73 6e 69 74 65 73 74  2e 63 6f 6d 30 1e 17 0d  |.snitest.com0...|
+00000090  31 32 30 34 31 31 31 37  34 30 33 35 5a 17 0d 31  |120411174035Z..1|
+000000a0  33 30 34 31 31 31 37 34  35 33 35 5a 30 28 31 10  |30411174535Z0(1.|
+000000b0  30 0e 06 03 55 04 0a 13  07 41 63 6d 65 20 43 6f  |0...U....Acme Co|
+000000c0  31 14 30 12 06 03 55 04  03 13 0b 73 6e 69 74 65  |1.0...U....snite|
+000000d0  73 74 2e 63 6f 6d 30 81  9d 30 0b 06 09 2a 86 48  |st.com0..0...*.H|
+000000e0  86 f7 0d 01 01 01 03 81  8d 00 30 81 89 02 81 81  |..........0.....|
+000000f0  00 bb 79 d6 f5 17 b5 e5  bf 46 10 d0 dc 69 be e6  |..y......F...i..|
+00000100  2b 07 43 5a d0 03 2d 8a  7a 43 85 b7 14 52 e7 a5  |+.CZ..-.zC...R..|
+00000110  65 4c 2c 78 b8 23 8c b5  b4 82 e5 de 1f 95 3b 7e  |eL,x.#........;~|
+00000120  62 a5 2c a5 33 d6 fe 12  5c 7a 56 fc f5 06 bf fa  |b.,.3...\zV.....|
+00000130  58 7b 26 3f b5 cd 04 d3  d0 c9 21 96 4a c7 f4 54  |X{&?......!.J..T|
+00000140  9f 5a bf ef 42 71 00 fe  18 99 07 7f 7e 88 7d 7d  |.Z..Bq......~.}}|
+00000150  f1 04 39 c4 a2 2e db 51  c9 7c e3 c0 4c 3b 32 66  |..9....Q.|..L;2f|
+00000160  01 cf af b1 1d b8 71 9a  1d db db 89 6b ae da 2d  |......q.....k..-|
+00000170  79 02 03 01 00 01 a3 32  30 30 30 0e 06 03 55 1d  |y......2000...U.|
+00000180  0f 01 01 ff 04 04 03 02  00 a0 30 0d 06 03 55 1d  |..........0...U.|
+00000190  0e 04 06 04 04 01 02 03  04 30 0f 06 03 55 1d 23  |.........0...U.#|
+000001a0  04 08 30 06 80 04 01 02  03 04 30 0b 06 09 2a 86  |..0.......0...*.|
+000001b0  48 86 f7 0d 01 01 05 03  81 81 00 89 c6 45 5f 1c  |H............E_.|
+000001c0  1f 5e f8 eb 1a b1 74 ee  24 39 05 9f 5c 42 59 bb  |.^....t.$9..\BY.|
+000001d0  1a 8d 86 cd b1 d0 56 f5  6a 71 7d a4 0e 95 ab 90  |......V.jq}.....|
+000001e0  f5 9e 8d ea f6 27 c1 57  99 50 94 db 08 02 26 6e  |.....'.W.P....&n|
+000001f0  b3 4f c6 84 2d ea 8a 4b  68 d9 c1 38 91 03 ab 84  |.O..-..Kh..8....|
+00000200  fb 9e 1f 85 d9 b5 d2 3f  f2 31 2c 86 70 fb b5 40  |.......?.1,.p..@|
+00000210  14 82 45 a4 eb af e2 64  d9 0c 8a 4c f4 f8 5b 0f  |..E....d...L..[.|
+00000220  ac 12 ac 2f c4 a3 15 4b  ad 52 46 28 68 af 96 c6  |.../...K.RF(h...|
+00000230  2c 65 25 d6 52 b6 e3 18  45 bd cc 16 03 03 00 04  |,e%.R...E.......|
+00000240  0e 00 00 00                                       |....|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 86 10 00 00  82 00 80 0d f2 bf 75 a9  |..............u.|
+00000010  aa db f3 25 55 d4 20 59  63 54 d1 70 82 f9 61 c5  |...%U. YcT.p..a.|
+00000020  b7 ae 3f 75 71 75 9d c5  01 a1 ed b1 07 66 9f 3f  |..?uqu.......f.?|
+00000030  cf c6 e6 ad 44 03 fd 18  6f 53 24 ce 76 01 bd fe  |....D...oS$.v...|
+00000040  e2 51 f7 df 8a 23 3a 21  c4 00 15 ff d0 e0 ff c8  |.Q...#:!........|
+00000050  8b 89 33 c6 8e e0 ce 97  ef b4 c6 f9 b0 ea 38 89  |..3...........8.|
+00000060  79 98 34 9e f7 bc c6 fd  d2 5d 56 84 5c d2 9a ce  |y.4......]V.\...|
+00000070  ae de 09 bc 24 25 fc 09  0c bc 0e 91 0d 6b 36 ae  |....$%.......k6.|
+00000080  ce 6b cd 14 ec b6 3c fa  d6 df fc 14 03 03 00 01  |.k....<.........|
+00000090  01 16 03 03 00 40 ad 21  13 2b 33 7a 4a 0d fb 0f  |.....@.!.+3zJ...|
+000000a0  eb d2 b6 85 29 1f 59 79  ba 86 53 5c 68 b4 c7 e3  |....).Yy..S\h...|
+000000b0  8a 6c 5c 18 04 4d e4 76  19 30 ba 92 b4 79 8c 64  |.l\..M.v.0...y.d|
+000000c0  00 a0 2e 13 96 45 9f e7  a9 e4 23 9e 9f 89 23 26  |.....E....#...#&|
+000000d0  36 20 82 fc 75 fe                                 |6 ..u.|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |..........@.....|
+00000010  00 00 00 00 00 00 00 00  00 00 00 b7 87 61 10 03  |.............a..|
+00000020  b8 a4 42 d4 8b 49 bc 40  80 70 92 c8 25 b0 c6 7f  |..B..I.@.p..%...|
+00000030  b3 87 76 50 5a 59 b3 3c  d8 3e 23 24 aa 1a f3 36  |..vPZY.<.>#$...6|
+00000040  c9 2c 87 c1 22 d2 94 f8  2c fd ef 17 03 03 00 40  |.,.."...,......@|
+00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000060  e5 7f bd 3e ff 9f d4 1b  91 02 f8 69 6f 70 9d 51  |...>.......iop.Q|
+00000070  a5 ec ef 5b 10 3f 4e 3f  44 e5 9a 39 68 7c 3a b9  |...[.?N?D..9h|:.|
+00000080  69 38 31 ec 9c 45 bf 19  d1 5c 5e 2e 06 00 ca 19  |i81..E...\^.....|
+00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
+000000a0  00 00 00 00 00 63 5e 79  2c f2 05 dc 2b d7 5b ac  |.....c^y,...+.[.|
+000000b0  9d fc 75 94 03 16 ca 1f  b2 75 58 2d f1 2f f1 1e  |..u......uX-./..|
+000000c0  d2 f6 84 8f 2e                                    |.....|
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/ticket.go b/third_party/gofrontend/libgo/go/crypto/tls/ticket.go
new file mode 100644
index 0000000..0923027
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/ticket.go
@@ -0,0 +1,183 @@
+// 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 tls
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/hmac"
+	"crypto/sha256"
+	"crypto/subtle"
+	"errors"
+	"io"
+)
+
+// sessionState contains the information that is serialized into a session
+// ticket in order to later resume a connection.
+type sessionState struct {
+	vers         uint16
+	cipherSuite  uint16
+	masterSecret []byte
+	certificates [][]byte
+}
+
+func (s *sessionState) equal(i interface{}) bool {
+	s1, ok := i.(*sessionState)
+	if !ok {
+		return false
+	}
+
+	if s.vers != s1.vers ||
+		s.cipherSuite != s1.cipherSuite ||
+		!bytes.Equal(s.masterSecret, s1.masterSecret) {
+		return false
+	}
+
+	if len(s.certificates) != len(s1.certificates) {
+		return false
+	}
+
+	for i := range s.certificates {
+		if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
+			return false
+		}
+	}
+
+	return true
+}
+
+func (s *sessionState) marshal() []byte {
+	length := 2 + 2 + 2 + len(s.masterSecret) + 2
+	for _, cert := range s.certificates {
+		length += 4 + len(cert)
+	}
+
+	ret := make([]byte, length)
+	x := ret
+	x[0] = byte(s.vers >> 8)
+	x[1] = byte(s.vers)
+	x[2] = byte(s.cipherSuite >> 8)
+	x[3] = byte(s.cipherSuite)
+	x[4] = byte(len(s.masterSecret) >> 8)
+	x[5] = byte(len(s.masterSecret))
+	x = x[6:]
+	copy(x, s.masterSecret)
+	x = x[len(s.masterSecret):]
+
+	x[0] = byte(len(s.certificates) >> 8)
+	x[1] = byte(len(s.certificates))
+	x = x[2:]
+
+	for _, cert := range s.certificates {
+		x[0] = byte(len(cert) >> 24)
+		x[1] = byte(len(cert) >> 16)
+		x[2] = byte(len(cert) >> 8)
+		x[3] = byte(len(cert))
+		copy(x[4:], cert)
+		x = x[4+len(cert):]
+	}
+
+	return ret
+}
+
+func (s *sessionState) unmarshal(data []byte) bool {
+	if len(data) < 8 {
+		return false
+	}
+
+	s.vers = uint16(data[0])<<8 | uint16(data[1])
+	s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
+	masterSecretLen := int(data[4])<<8 | int(data[5])
+	data = data[6:]
+	if len(data) < masterSecretLen {
+		return false
+	}
+
+	s.masterSecret = data[:masterSecretLen]
+	data = data[masterSecretLen:]
+
+	if len(data) < 2 {
+		return false
+	}
+
+	numCerts := int(data[0])<<8 | int(data[1])
+	data = data[2:]
+
+	s.certificates = make([][]byte, numCerts)
+	for i := range s.certificates {
+		if len(data) < 4 {
+			return false
+		}
+		certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+		data = data[4:]
+		if certLen < 0 {
+			return false
+		}
+		if len(data) < certLen {
+			return false
+		}
+		s.certificates[i] = data[:certLen]
+		data = data[certLen:]
+	}
+
+	if len(data) > 0 {
+		return false
+	}
+
+	return true
+}
+
+func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) {
+	serialized := state.marshal()
+	encrypted := make([]byte, aes.BlockSize+len(serialized)+sha256.Size)
+	iv := encrypted[:aes.BlockSize]
+	macBytes := encrypted[len(encrypted)-sha256.Size:]
+
+	if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
+		return nil, err
+	}
+	block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
+	if err != nil {
+		return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
+	}
+	cipher.NewCTR(block, iv).XORKeyStream(encrypted[aes.BlockSize:], serialized)
+
+	mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
+	mac.Write(encrypted[:len(encrypted)-sha256.Size])
+	mac.Sum(macBytes[:0])
+
+	return encrypted, nil
+}
+
+func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
+	if c.config.SessionTicketsDisabled ||
+		len(encrypted) < aes.BlockSize+sha256.Size {
+		return nil, false
+	}
+
+	iv := encrypted[:aes.BlockSize]
+	macBytes := encrypted[len(encrypted)-sha256.Size:]
+
+	mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
+	mac.Write(encrypted[:len(encrypted)-sha256.Size])
+	expected := mac.Sum(nil)
+
+	if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
+		return nil, false
+	}
+
+	block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
+	if err != nil {
+		return nil, false
+	}
+	ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size]
+	plaintext := ciphertext
+	cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
+
+	state := new(sessionState)
+	ok := state.unmarshal(plaintext)
+	return state, ok
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/tls.go b/third_party/gofrontend/libgo/go/crypto/tls/tls.go
new file mode 100644
index 0000000..d50e120
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/tls.go
@@ -0,0 +1,275 @@
+// 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 tls partially implements TLS 1.2, as specified in RFC 5246.
+package tls
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/pem"
+	"errors"
+	"io/ioutil"
+	"net"
+	"strings"
+	"time"
+)
+
+// Server returns a new TLS server side connection
+// using conn as the underlying transport.
+// The configuration config must be non-nil and must have
+// at least one certificate.
+func Server(conn net.Conn, config *Config) *Conn {
+	return &Conn{conn: conn, config: config}
+}
+
+// Client returns a new TLS client side connection
+// using conn as the underlying transport.
+// The config cannot be nil: users must set either ServerName or
+// InsecureSkipVerify in the config.
+func Client(conn net.Conn, config *Config) *Conn {
+	return &Conn{conn: conn, config: config, isClient: true}
+}
+
+// A listener implements a network listener (net.Listener) for TLS connections.
+type listener struct {
+	net.Listener
+	config *Config
+}
+
+// Accept waits for and returns the next incoming TLS connection.
+// The returned connection c is a *tls.Conn.
+func (l *listener) Accept() (c net.Conn, err error) {
+	c, err = l.Listener.Accept()
+	if err != nil {
+		return
+	}
+	c = Server(c, l.config)
+	return
+}
+
+// NewListener creates a Listener which accepts connections from an inner
+// Listener and wraps each connection with Server.
+// The configuration config must be non-nil and must have
+// at least one certificate.
+func NewListener(inner net.Listener, config *Config) net.Listener {
+	l := new(listener)
+	l.Listener = inner
+	l.config = config
+	return l
+}
+
+// Listen creates a TLS listener accepting connections on the
+// given network address using net.Listen.
+// The configuration config must be non-nil and must have
+// at least one certificate.
+func Listen(network, laddr string, config *Config) (net.Listener, error) {
+	if config == nil || len(config.Certificates) == 0 {
+		return nil, errors.New("tls.Listen: no certificates in configuration")
+	}
+	l, err := net.Listen(network, laddr)
+	if err != nil {
+		return nil, err
+	}
+	return NewListener(l, config), nil
+}
+
+type timeoutError struct{}
+
+func (timeoutError) Error() string   { return "tls: DialWithDialer timed out" }
+func (timeoutError) Timeout() bool   { return true }
+func (timeoutError) Temporary() bool { return true }
+
+// DialWithDialer connects to the given network address using dialer.Dial and
+// then initiates a TLS handshake, returning the resulting TLS connection. Any
+// timeout or deadline given in the dialer apply to connection and TLS
+// handshake as a whole.
+//
+// DialWithDialer interprets a nil configuration as equivalent to the zero
+// configuration; see the documentation of Config for the defaults.
+func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) {
+	// We want the Timeout and Deadline values from dialer to cover the
+	// whole process: TCP connection and TLS handshake. This means that we
+	// also need to start our own timers now.
+	timeout := dialer.Timeout
+
+	if !dialer.Deadline.IsZero() {
+		deadlineTimeout := dialer.Deadline.Sub(time.Now())
+		if timeout == 0 || deadlineTimeout < timeout {
+			timeout = deadlineTimeout
+		}
+	}
+
+	var errChannel chan error
+
+	if timeout != 0 {
+		errChannel = make(chan error, 2)
+		time.AfterFunc(timeout, func() {
+			errChannel <- timeoutError{}
+		})
+	}
+
+	rawConn, err := dialer.Dial(network, addr)
+	if err != nil {
+		return nil, err
+	}
+
+	colonPos := strings.LastIndex(addr, ":")
+	if colonPos == -1 {
+		colonPos = len(addr)
+	}
+	hostname := addr[:colonPos]
+
+	if config == nil {
+		config = defaultConfig()
+	}
+	// If no ServerName is set, infer the ServerName
+	// from the hostname we're connecting to.
+	if config.ServerName == "" {
+		// Make a copy to avoid polluting argument or default.
+		c := *config
+		c.ServerName = hostname
+		config = &c
+	}
+
+	conn := Client(rawConn, config)
+
+	if timeout == 0 {
+		err = conn.Handshake()
+	} else {
+		go func() {
+			errChannel <- conn.Handshake()
+		}()
+
+		err = <-errChannel
+	}
+
+	if err != nil {
+		rawConn.Close()
+		return nil, err
+	}
+
+	return conn, nil
+}
+
+// Dial connects to the given network address using net.Dial
+// and then initiates a TLS handshake, returning the resulting
+// TLS connection.
+// Dial interprets a nil configuration as equivalent to
+// the zero configuration; see the documentation of Config
+// for the defaults.
+func Dial(network, addr string, config *Config) (*Conn, error) {
+	return DialWithDialer(new(net.Dialer), network, addr, config)
+}
+
+// LoadX509KeyPair reads and parses a public/private key pair from a pair of
+// files. The files must contain PEM encoded data.
+func LoadX509KeyPair(certFile, keyFile string) (cert Certificate, err error) {
+	certPEMBlock, err := ioutil.ReadFile(certFile)
+	if err != nil {
+		return
+	}
+	keyPEMBlock, err := ioutil.ReadFile(keyFile)
+	if err != nil {
+		return
+	}
+	return X509KeyPair(certPEMBlock, keyPEMBlock)
+}
+
+// X509KeyPair parses a public/private key pair from a pair of
+// PEM encoded data.
+func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error) {
+	var certDERBlock *pem.Block
+	for {
+		certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
+		if certDERBlock == nil {
+			break
+		}
+		if certDERBlock.Type == "CERTIFICATE" {
+			cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
+		}
+	}
+
+	if len(cert.Certificate) == 0 {
+		err = errors.New("crypto/tls: failed to parse certificate PEM data")
+		return
+	}
+
+	var keyDERBlock *pem.Block
+	for {
+		keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
+		if keyDERBlock == nil {
+			err = errors.New("crypto/tls: failed to parse key PEM data")
+			return
+		}
+		if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
+			break
+		}
+	}
+
+	cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
+	if err != nil {
+		return
+	}
+
+	// We don't need to parse the public key for TLS, but we so do anyway
+	// to check that it looks sane and matches the private key.
+	x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
+	if err != nil {
+		return
+	}
+
+	switch pub := x509Cert.PublicKey.(type) {
+	case *rsa.PublicKey:
+		priv, ok := cert.PrivateKey.(*rsa.PrivateKey)
+		if !ok {
+			err = errors.New("crypto/tls: private key type does not match public key type")
+			return
+		}
+		if pub.N.Cmp(priv.N) != 0 {
+			err = errors.New("crypto/tls: private key does not match public key")
+			return
+		}
+	case *ecdsa.PublicKey:
+		priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
+		if !ok {
+			err = errors.New("crypto/tls: private key type does not match public key type")
+			return
+
+		}
+		if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
+			err = errors.New("crypto/tls: private key does not match public key")
+			return
+		}
+	default:
+		err = errors.New("crypto/tls: unknown public key algorithm")
+		return
+	}
+
+	return
+}
+
+// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
+// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
+// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
+func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
+	if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
+		return key, nil
+	}
+	if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
+		switch key := key.(type) {
+		case *rsa.PrivateKey, *ecdsa.PrivateKey:
+			return key, nil
+		default:
+			return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping")
+		}
+	}
+	if key, err := x509.ParseECPrivateKey(der); err == nil {
+		return key, nil
+	}
+
+	return nil, errors.New("crypto/tls: failed to parse private key")
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/tls/tls_test.go b/third_party/gofrontend/libgo/go/crypto/tls/tls_test.go
new file mode 100644
index 0000000..f8c94ff
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/tls/tls_test.go
@@ -0,0 +1,237 @@
+// 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 tls
+
+import (
+	"fmt"
+	"io"
+	"net"
+	"strings"
+	"testing"
+	"time"
+)
+
+var rsaCertPEM = `-----BEGIN CERTIFICATE-----
+MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ
+hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa
+rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv
+zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW
+r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V
+-----END CERTIFICATE-----
+`
+
+var rsaKeyPEM = `-----BEGIN RSA PRIVATE KEY-----
+MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
+k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
+6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
+MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
+SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
+xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
+D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
+-----END RSA PRIVATE KEY-----
+`
+
+// keyPEM is the same as rsaKeyPEM, but declares itself as just
+// "PRIVATE KEY", not "RSA PRIVATE KEY".  http://golang.org/issue/4477
+var keyPEM = `-----BEGIN PRIVATE KEY-----
+MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
+k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
+6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
+MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
+SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
+xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
+D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
+-----END PRIVATE KEY-----
+`
+
+var ecdsaCertPEM = `-----BEGIN CERTIFICATE-----
+MIIB/jCCAWICCQDscdUxw16XFDAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQwHhcNMTIxMTE0MTI0MDQ4WhcNMTUxMTE0MTI0MDQ4WjBFMQswCQYDVQQG
+EwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lk
+Z2l0cyBQdHkgTHRkMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBY9+my9OoeSUR
+lDQdV/x8LsOuLilthhiS1Tz4aGDHIPwC1mlvnf7fg5lecYpMCrLLhauAc1UJXcgl
+01xoLuzgtAEAgv2P/jgytzRSpUYvgLBt1UA0leLYBy6mQQbrNEuqT3INapKIcUv8
+XxYP0xMEUksLPq6Ca+CRSqTtrd/23uTnapkwCQYHKoZIzj0EAQOBigAwgYYCQXJo
+A7Sl2nLVf+4Iu/tAX/IF4MavARKC4PPHK3zfuGfPR3oCCcsAoz3kAzOeijvd0iXb
+H5jBImIxPL4WxQNiBTexAkF8D1EtpYuWdlVQ80/h/f4pBcGiXPqX5h2PQSQY7hP1
++jwM1FGS4fREIOvlBYr/SzzQRtwrvrzGYxDEDbsC0ZGRnA==
+-----END CERTIFICATE-----
+`
+
+var ecdsaKeyPEM = `-----BEGIN EC PARAMETERS-----
+BgUrgQQAIw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBrsoKp0oqcv6/JovJJDoDVSGWdirrkgCWxrprGlzB9o0X8fV675X0
+NwuBenXFfeZvVcwluO7/Q9wkYoPd/t3jGImgBwYFK4EEACOhgYkDgYYABAFj36bL
+06h5JRGUNB1X/Hwuw64uKW2GGJLVPPhoYMcg/ALWaW+d/t+DmV5xikwKssuFq4Bz
+VQldyCXTXGgu7OC0AQCC/Y/+ODK3NFKlRi+AsG3VQDSV4tgHLqZBBus0S6pPcg1q
+kohxS/xfFg/TEwRSSws+roJr4JFKpO2t3/be5OdqmQ==
+-----END EC PRIVATE KEY-----
+`
+
+var keyPairTests = []struct {
+	algo string
+	cert string
+	key  string
+}{
+	{"ECDSA", ecdsaCertPEM, ecdsaKeyPEM},
+	{"RSA", rsaCertPEM, rsaKeyPEM},
+	{"RSA-untyped", rsaCertPEM, keyPEM}, // golang.org/issue/4477
+}
+
+func TestX509KeyPair(t *testing.T) {
+	var pem []byte
+	for _, test := range keyPairTests {
+		pem = []byte(test.cert + test.key)
+		if _, err := X509KeyPair(pem, pem); err != nil {
+			t.Errorf("Failed to load %s cert followed by %s key: %s", test.algo, test.algo, err)
+		}
+		pem = []byte(test.key + test.cert)
+		if _, err := X509KeyPair(pem, pem); err != nil {
+			t.Errorf("Failed to load %s key followed by %s cert: %s", test.algo, test.algo, err)
+		}
+	}
+}
+
+func TestX509MixedKeyPair(t *testing.T) {
+	if _, err := X509KeyPair([]byte(rsaCertPEM), []byte(ecdsaKeyPEM)); err == nil {
+		t.Error("Load of RSA certificate succeeded with ECDSA private key")
+	}
+	if _, err := X509KeyPair([]byte(ecdsaCertPEM), []byte(rsaKeyPEM)); err == nil {
+		t.Error("Load of ECDSA certificate succeeded with RSA private key")
+	}
+}
+
+func newLocalListener(t *testing.T) net.Listener {
+	ln, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		ln, err = net.Listen("tcp6", "[::1]:0")
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+	return ln
+}
+
+func TestDialTimeout(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	listener := newLocalListener(t)
+
+	addr := listener.Addr().String()
+	defer listener.Close()
+
+	complete := make(chan bool)
+	defer close(complete)
+
+	go func() {
+		conn, err := listener.Accept()
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		<-complete
+		conn.Close()
+	}()
+
+	dialer := &net.Dialer{
+		Timeout: 10 * time.Millisecond,
+	}
+
+	var err error
+	if _, err = DialWithDialer(dialer, "tcp", addr, nil); err == nil {
+		t.Fatal("DialWithTimeout completed successfully")
+	}
+
+	if !strings.Contains(err.Error(), "timed out") {
+		t.Errorf("resulting error not a timeout: %s", err)
+	}
+}
+
+// tests that Conn.Read returns (non-zero, io.EOF) instead of
+// (non-zero, nil) when a Close (alertCloseNotify) is sitting right
+// behind the application data in the buffer.
+func TestConnReadNonzeroAndEOF(t *testing.T) {
+	// This test is racy: it assumes that after a write to a
+	// localhost TCP connection, the peer TCP connection can
+	// immediately read it.  Because it's racy, we skip this test
+	// in short mode, and then retry it several times with an
+	// increasing sleep in between our final write (via srv.Close
+	// below) and the following read.
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	var err error
+	for delay := time.Millisecond; delay <= 64*time.Millisecond; delay *= 2 {
+		if err = testConnReadNonzeroAndEOF(t, delay); err == nil {
+			return
+		}
+	}
+	t.Error(err)
+}
+
+func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	srvCh := make(chan *Conn, 1)
+	var serr error
+	go func() {
+		sconn, err := ln.Accept()
+		if err != nil {
+			serr = err
+			srvCh <- nil
+			return
+		}
+		serverConfig := *testConfig
+		srv := Server(sconn, &serverConfig)
+		if err := srv.Handshake(); err != nil {
+			serr = fmt.Errorf("handshake: %v", err)
+			srvCh <- nil
+			return
+		}
+		srvCh <- srv
+	}()
+
+	clientConfig := *testConfig
+	conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer conn.Close()
+
+	srv := <-srvCh
+	if srv == nil {
+		return serr
+	}
+
+	buf := make([]byte, 6)
+
+	srv.Write([]byte("foobar"))
+	n, err := conn.Read(buf)
+	if n != 6 || err != nil || string(buf) != "foobar" {
+		return fmt.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf)
+	}
+
+	srv.Write([]byte("abcdef"))
+	srv.Close()
+	time.Sleep(delay)
+	n, err = conn.Read(buf)
+	if n != 6 || string(buf) != "abcdef" {
+		return fmt.Errorf("Read = %d, buf= %q; want 6, abcdef", n, buf)
+	}
+	if err != io.EOF {
+		return fmt.Errorf("Second Read error = %v; want io.EOF", err)
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/cert_pool.go b/third_party/gofrontend/libgo/go/crypto/x509/cert_pool.go
new file mode 100644
index 0000000..babe94d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/cert_pool.go
@@ -0,0 +1,116 @@
+// 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.
+
+package x509
+
+import (
+	"encoding/pem"
+)
+
+// CertPool is a set of certificates.
+type CertPool struct {
+	bySubjectKeyId map[string][]int
+	byName         map[string][]int
+	certs          []*Certificate
+}
+
+// NewCertPool returns a new, empty CertPool.
+func NewCertPool() *CertPool {
+	return &CertPool{
+		make(map[string][]int),
+		make(map[string][]int),
+		nil,
+	}
+}
+
+// findVerifiedParents attempts to find certificates in s which have signed the
+// given certificate. If any candidates were rejected then errCert will be set
+// to one of them, arbitrarily, and err will contain the reason that it was
+// rejected.
+func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
+	if s == nil {
+		return
+	}
+	var candidates []int
+
+	if len(cert.AuthorityKeyId) > 0 {
+		candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
+	}
+	if len(candidates) == 0 {
+		candidates = s.byName[string(cert.RawIssuer)]
+	}
+
+	for _, c := range candidates {
+		if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
+			parents = append(parents, c)
+		} else {
+			errCert = s.certs[c]
+		}
+	}
+
+	return
+}
+
+// AddCert adds a certificate to a pool.
+func (s *CertPool) AddCert(cert *Certificate) {
+	if cert == nil {
+		panic("adding nil Certificate to CertPool")
+	}
+
+	// Check that the certificate isn't being added twice.
+	for _, c := range s.certs {
+		if c.Equal(cert) {
+			return
+		}
+	}
+
+	n := len(s.certs)
+	s.certs = append(s.certs, cert)
+
+	if len(cert.SubjectKeyId) > 0 {
+		keyId := string(cert.SubjectKeyId)
+		s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
+	}
+	name := string(cert.RawSubject)
+	s.byName[name] = append(s.byName[name], n)
+}
+
+// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
+// It appends any certificates found to s and returns true if any certificates
+// were successfully parsed.
+//
+// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
+// of root CAs in a format suitable for this function.
+func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
+	for len(pemCerts) > 0 {
+		var block *pem.Block
+		block, pemCerts = pem.Decode(pemCerts)
+		if block == nil {
+			break
+		}
+		if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
+			continue
+		}
+
+		cert, err := ParseCertificate(block.Bytes)
+		if err != nil {
+			continue
+		}
+
+		s.AddCert(cert)
+		ok = true
+	}
+
+	return
+}
+
+// Subjects returns a list of the DER-encoded subjects of
+// all of the certificates in the pool.
+func (s *CertPool) Subjects() (res [][]byte) {
+	res = make([][]byte, len(s.certs))
+	for i, c := range s.certs {
+		res[i] = c.RawSubject
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/pem_decrypt.go b/third_party/gofrontend/libgo/go/crypto/x509/pem_decrypt.go
new file mode 100644
index 0000000..194c81b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/pem_decrypt.go
@@ -0,0 +1,233 @@
+// 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 x509
+
+// RFC 1423 describes the encryption of PEM blocks. The algorithm used to
+// generate a key from the password was derived by looking at the OpenSSL
+// implementation.
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/des"
+	"crypto/md5"
+	"encoding/hex"
+	"encoding/pem"
+	"errors"
+	"io"
+	"strings"
+)
+
+type PEMCipher int
+
+// Possible values for the EncryptPEMBlock encryption algorithm.
+const (
+	_ PEMCipher = iota
+	PEMCipherDES
+	PEMCipher3DES
+	PEMCipherAES128
+	PEMCipherAES192
+	PEMCipherAES256
+)
+
+// rfc1423Algo holds a method for enciphering a PEM block.
+type rfc1423Algo struct {
+	cipher     PEMCipher
+	name       string
+	cipherFunc func(key []byte) (cipher.Block, error)
+	keySize    int
+	blockSize  int
+}
+
+// rfc1423Algos holds a slice of the possible ways to encrypt a PEM
+// block.  The ivSize numbers were taken from the OpenSSL source.
+var rfc1423Algos = []rfc1423Algo{{
+	cipher:     PEMCipherDES,
+	name:       "DES-CBC",
+	cipherFunc: des.NewCipher,
+	keySize:    8,
+	blockSize:  des.BlockSize,
+}, {
+	cipher:     PEMCipher3DES,
+	name:       "DES-EDE3-CBC",
+	cipherFunc: des.NewTripleDESCipher,
+	keySize:    24,
+	blockSize:  des.BlockSize,
+}, {
+	cipher:     PEMCipherAES128,
+	name:       "AES-128-CBC",
+	cipherFunc: aes.NewCipher,
+	keySize:    16,
+	blockSize:  aes.BlockSize,
+}, {
+	cipher:     PEMCipherAES192,
+	name:       "AES-192-CBC",
+	cipherFunc: aes.NewCipher,
+	keySize:    24,
+	blockSize:  aes.BlockSize,
+}, {
+	cipher:     PEMCipherAES256,
+	name:       "AES-256-CBC",
+	cipherFunc: aes.NewCipher,
+	keySize:    32,
+	blockSize:  aes.BlockSize,
+},
+}
+
+// deriveKey uses a key derivation function to stretch the password into a key
+// with the number of bits our cipher requires. This algorithm was derived from
+// the OpenSSL source.
+func (c rfc1423Algo) deriveKey(password, salt []byte) []byte {
+	hash := md5.New()
+	out := make([]byte, c.keySize)
+	var digest []byte
+
+	for i := 0; i < len(out); i += len(digest) {
+		hash.Reset()
+		hash.Write(digest)
+		hash.Write(password)
+		hash.Write(salt)
+		digest = hash.Sum(digest[:0])
+		copy(out[i:], digest)
+	}
+	return out
+}
+
+// IsEncryptedPEMBlock returns if the PEM block is password encrypted.
+func IsEncryptedPEMBlock(b *pem.Block) bool {
+	_, ok := b.Headers["DEK-Info"]
+	return ok
+}
+
+// IncorrectPasswordError is returned when an incorrect password is detected.
+var IncorrectPasswordError = errors.New("x509: decryption password incorrect")
+
+// DecryptPEMBlock takes a password encrypted PEM block and the password used to
+// encrypt it and returns a slice of decrypted DER encoded bytes. It inspects
+// the DEK-Info header to determine the algorithm used for decryption. If no
+// DEK-Info header is present, an error is returned. If an incorrect password
+// is detected an IncorrectPasswordError is returned.
+func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) {
+	dek, ok := b.Headers["DEK-Info"]
+	if !ok {
+		return nil, errors.New("x509: no DEK-Info header in block")
+	}
+
+	idx := strings.Index(dek, ",")
+	if idx == -1 {
+		return nil, errors.New("x509: malformed DEK-Info header")
+	}
+
+	mode, hexIV := dek[:idx], dek[idx+1:]
+	ciph := cipherByName(mode)
+	if ciph == nil {
+		return nil, errors.New("x509: unknown encryption mode")
+	}
+	iv, err := hex.DecodeString(hexIV)
+	if err != nil {
+		return nil, err
+	}
+	if len(iv) != ciph.blockSize {
+		return nil, errors.New("x509: incorrect IV size")
+	}
+
+	// Based on the OpenSSL implementation. The salt is the first 8 bytes
+	// of the initialization vector.
+	key := ciph.deriveKey(password, iv[:8])
+	block, err := ciph.cipherFunc(key)
+	if err != nil {
+		return nil, err
+	}
+
+	data := make([]byte, len(b.Bytes))
+	dec := cipher.NewCBCDecrypter(block, iv)
+	dec.CryptBlocks(data, b.Bytes)
+
+	// Blocks are padded using a scheme where the last n bytes of padding are all
+	// equal to n. It can pad from 1 to blocksize bytes inclusive. See RFC 1423.
+	// For example:
+	//	[x y z 2 2]
+	//	[x y 7 7 7 7 7 7 7]
+	// If we detect a bad padding, we assume it is an invalid password.
+	dlen := len(data)
+	if dlen == 0 || dlen%ciph.blockSize != 0 {
+		return nil, errors.New("x509: invalid padding")
+	}
+	last := int(data[dlen-1])
+	if dlen < last {
+		return nil, IncorrectPasswordError
+	}
+	if last == 0 || last > ciph.blockSize {
+		return nil, IncorrectPasswordError
+	}
+	for _, val := range data[dlen-last:] {
+		if int(val) != last {
+			return nil, IncorrectPasswordError
+		}
+	}
+	return data[:dlen-last], nil
+}
+
+// EncryptPEMBlock returns a PEM block of the specified type holding the
+// given DER-encoded data encrypted with the specified algorithm and
+// password.
+func EncryptPEMBlock(rand io.Reader, blockType string, data, password []byte, alg PEMCipher) (*pem.Block, error) {
+	ciph := cipherByKey(alg)
+	if ciph == nil {
+		return nil, errors.New("x509: unknown encryption mode")
+	}
+	iv := make([]byte, ciph.blockSize)
+	if _, err := io.ReadFull(rand, iv); err != nil {
+		return nil, errors.New("x509: cannot generate IV: " + err.Error())
+	}
+	// The salt is the first 8 bytes of the initialization vector,
+	// matching the key derivation in DecryptPEMBlock.
+	key := ciph.deriveKey(password, iv[:8])
+	block, err := ciph.cipherFunc(key)
+	if err != nil {
+		return nil, err
+	}
+	enc := cipher.NewCBCEncrypter(block, iv)
+	pad := ciph.blockSize - len(data)%ciph.blockSize
+	encrypted := make([]byte, len(data), len(data)+pad)
+	// We could save this copy by encrypting all the whole blocks in
+	// the data separately, but it doesn't seem worth the additional
+	// code.
+	copy(encrypted, data)
+	// See RFC 1423, section 1.1
+	for i := 0; i < pad; i++ {
+		encrypted = append(encrypted, byte(pad))
+	}
+	enc.CryptBlocks(encrypted, encrypted)
+
+	return &pem.Block{
+		Type: blockType,
+		Headers: map[string]string{
+			"Proc-Type": "4,ENCRYPTED",
+			"DEK-Info":  ciph.name + "," + hex.EncodeToString(iv),
+		},
+		Bytes: encrypted,
+	}, nil
+}
+
+func cipherByName(name string) *rfc1423Algo {
+	for i := range rfc1423Algos {
+		alg := &rfc1423Algos[i]
+		if alg.name == name {
+			return alg
+		}
+	}
+	return nil
+}
+
+func cipherByKey(key PEMCipher) *rfc1423Algo {
+	for i := range rfc1423Algos {
+		alg := &rfc1423Algos[i]
+		if alg.cipher == key {
+			return alg
+		}
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/pem_decrypt_test.go b/third_party/gofrontend/libgo/go/crypto/x509/pem_decrypt_test.go
new file mode 100644
index 0000000..59ba6f9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/pem_decrypt_test.go
@@ -0,0 +1,223 @@
+// 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 x509
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/base64"
+	"encoding/pem"
+	"testing"
+)
+
+func TestDecrypt(t *testing.T) {
+	for i, data := range testData {
+		t.Logf("test %d. %s", i, data.kind)
+		block, rest := pem.Decode(data.pemData)
+		if len(rest) > 0 {
+			t.Error("extra data")
+		}
+		der, err := DecryptPEMBlock(block, data.password)
+		if err != nil {
+			t.Error("decrypt failed: ", err)
+			continue
+		}
+		if _, err := ParsePKCS1PrivateKey(der); err != nil {
+			t.Error("invalid private key: ", err)
+		}
+		plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
+		if err != nil {
+			t.Fatal("cannot decode test DER data: ", err)
+		}
+		if !bytes.Equal(der, plainDER) {
+			t.Error("data mismatch")
+		}
+	}
+}
+
+func TestEncrypt(t *testing.T) {
+	for i, data := range testData {
+		t.Logf("test %d. %s", i, data.kind)
+		plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
+		if err != nil {
+			t.Fatal("cannot decode test DER data: ", err)
+		}
+		password := []byte("kremvax1")
+		block, err := EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", plainDER, password, data.kind)
+		if err != nil {
+			t.Error("encrypt: ", err)
+			continue
+		}
+		if !IsEncryptedPEMBlock(block) {
+			t.Error("PEM block does not appear to be encrypted")
+		}
+		if block.Type != "RSA PRIVATE KEY" {
+			t.Errorf("unexpected block type; got %q want %q", block.Type, "RSA PRIVATE KEY")
+		}
+		if block.Headers["Proc-Type"] != "4,ENCRYPTED" {
+			t.Errorf("block does not have correct Proc-Type header")
+		}
+		der, err := DecryptPEMBlock(block, password)
+		if err != nil {
+			t.Error("decrypt: ", err)
+			continue
+		}
+		if !bytes.Equal(der, plainDER) {
+			t.Errorf("data mismatch")
+		}
+	}
+}
+
+var testData = []struct {
+	kind     PEMCipher
+	password []byte
+	pemData  []byte
+	plainDER string
+}{
+	{
+		kind:     PEMCipherDES,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CBC,34F09A4FC8DE22B5
+
+WXxy8kbZdiZvANtKvhmPBLV7eVFj2A5z6oAxvI9KGyhG0ZK0skfnt00C24vfU7m5
+ICXeoqP67lzJ18xCzQfHjDaBNs53DSDT+Iz4e8QUep1xQ30+8QKX2NA2coee3nwc
+6oM1cuvhNUDemBH2i3dKgMVkfaga0zQiiOq6HJyGSncCMSruQ7F9iWEfRbFcxFCx
+qtHb1kirfGKEtgWTF+ynyco6+2gMXNu70L7nJcnxnV/RLFkHt7AUU1yrclxz7eZz
+XOH9VfTjb52q/I8Suozq9coVQwg4tXfIoYUdT//O+mB7zJb9HI9Ps77b9TxDE6Gm
+4C9brwZ3zg2vqXcwwV6QRZMtyll9rOpxkbw6NPlpfBqkc3xS51bbxivbO/Nve4KD
+r12ymjFNF4stXCfJnNqKoZ50BHmEEUDu5Wb0fpVn82XrGw7CYc4iug==
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MIIBPAIBAAJBAPASZe+tCPU6p80AjHhDkVsLYa51D35e/YGa8QcZyooeZM8EHozo
+KD0fNiKI+53bHdy07N+81VQ8/ejPcRoXPlsCAwEAAQJBAMTxIuSq27VpR+zZ7WJf
+c6fvv1OBvpMZ0/d1pxL/KnOAgq2rD5hDtk9b0LGhTPgQAmrrMTKuSeGoIuYE+gKQ
+QvkCIQD+GC1m+/do+QRurr0uo46Kx1LzLeSCrjBk34wiOp2+dwIhAPHfTLRXS2fv
+7rljm0bYa4+eDZpz+E8RcXEgzhhvcQQ9AiAI5eHZJGOyml3MXnQjiPi55WcDOw0w
+glcRgT6QCEtz2wIhANSyqaFtosIkHKqrDUGfz/bb5tqMYTAnBruVPaf/WEOBAiEA
+9xORWeRG1tRpso4+dYy4KdDkuLPIO01KY6neYGm3BCM=`,
+	},
+	{
+		kind:     PEMCipher3DES,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C1F4A6A03682C2C7
+
+0JqVdBEH6iqM7drTkj+e2W/bE3LqakaiWhb9WUVonFkhyu8ca/QzebY3b5gCvAZQ
+YwBvDcT/GHospKqPx+cxDHJNsUASDZws6bz8ZXWJGwZGExKzr0+Qx5fgXn44Ms3x
+8g1ENFuTXtxo+KoNK0zuAMAqp66Llcds3Fjl4XR18QaD0CrVNAfOdgATWZm5GJxk
+Fgx5f84nT+/ovvreG+xeOzWgvtKo0UUZVrhGOgfKLpa57adumcJ6SkUuBtEFpZFB
+ldw5w7WC7d13x2LsRkwo8ZrDKgIV+Y9GNvhuCCkTzNP0V3gNeJpd201HZHR+9n3w
+3z0VjR/MGqsfcy1ziEWMNOO53At3zlG6zP05aHMnMcZoVXadEK6L1gz++inSSDCq
+gI0UJP4e3JVB7AkgYymYAwiYALAkoEIuanxoc50njJk=
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MIIBOwIBAAJBANOCXKdoNS/iP/MAbl9cf1/SF3P+Ns7ZeNL27CfmDh0O6Zduaax5
+NBiumd2PmjkaCu7lQ5JOibHfWn+xJsc3kw0CAwEAAQJANX/W8d1Q/sCqzkuAn4xl
+B5a7qfJWaLHndu1QRLNTRJPn0Ee7OKJ4H0QKOhQM6vpjRrz+P2u9thn6wUxoPsef
+QQIhAP/jCkfejFcy4v15beqKzwz08/tslVjF+Yq41eJGejmxAiEA05pMoqfkyjcx
+fyvGhpoOyoCp71vSGUfR2I9CR65oKh0CIC1Msjs66LlfJtQctRq6bCEtFCxEcsP+
+eEjYo/Sk6WphAiEAxpgWPMJeU/shFT28gS+tmhjPZLpEoT1qkVlC14u0b3ECIQDX
+tZZZxCtPAm7shftEib0VU77Lk8MsXJcx2C4voRsjEw==`,
+	},
+	{
+		kind:     PEMCipherAES128,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,D4492E793FC835CC038A728ED174F78A
+
+EyfQSzXSjv6BaNH+NHdXRlkHdimpF9izWlugVJAPApgXrq5YldPe2aGIOFXyJ+QE
+ZIG20DYqaPzJRjTEbPNZ6Es0S2JJ5yCpKxwJuDkgJZKtF39Q2i36JeGbSZQIuWJE
+GZbBpf1jDH/pr0iGonuAdl2PCCZUiy+8eLsD2tyviHUkFLOB+ykYoJ5t8ngZ/B6D
+33U43LLb7+9zD4y3Q9OVHqBFGyHcxCY9+9Qh4ZnFp7DTf6RY5TNEvE3s4g6aDpBs
+3NbvRVvYTgs8K9EPk4K+5R+P2kD8J8KvEIGxVa1vz8QoCJ/jr7Ka2rvNgPCex5/E
+080LzLHPCrXKdlr/f50yhNWq08ZxMWQFkui+FDHPDUaEELKAXV8/5PDxw80Rtybo
+AVYoCVIbZXZCuCO81op8UcOgEpTtyU5Lgh3Mw5scQL0=
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MIIBOgIBAAJBAMBlj5FxYtqbcy8wY89d/S7n0+r5MzD9F63BA/Lpl78vQKtdJ5dT
+cDGh/rBt1ufRrNp0WihcmZi7Mpl/3jHjiWECAwEAAQJABNOHYnKhtDIqFYj1OAJ3
+k3GlU0OlERmIOoeY/cL2V4lgwllPBEs7r134AY4wMmZSBUj8UR/O4SNO668ElKPE
+cQIhAOuqY7/115x5KCdGDMWi+jNaMxIvI4ETGwV40ykGzqlzAiEA0P9oEC3m9tHB
+kbpjSTxaNkrXxDgdEOZz8X0uOUUwHNsCIAwzcSCiGLyYJTULUmP1ESERfW1mlV78
+XzzESaJpIM/zAiBQkSTcl9VhcJreQqvjn5BnPZLP4ZHS4gPwJAGdsj5J4QIhAOVR
+B3WlRNTXR2WsJ5JdByezg9xzdXzULqmga0OE339a`,
+	},
+	{
+		kind:     PEMCipherAES192,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,E2C9FB02BCA23ADE1829F8D8BC5F5369
+
+cqVslvHqDDM6qwU6YjezCRifXmKsrgEev7ng6Qs7UmDJOpHDgJQZI9fwMFUhIyn5
+FbCu1SHkLMW52Ld3CuEqMnzWMlhPrW8tFvUOrMWPYSisv7nNq88HobZEJcUNL2MM
+Y15XmHW6IJwPqhKyLHpWXyOCVEh4ODND2nV15PCoi18oTa475baxSk7+1qH7GuIs
+Rb7tshNTMqHbCpyo9Rn3UxeFIf9efdl8YLiMoIqc7J8E5e9VlbeQSdLMQOgDAQJG
+ReUtTw8exmKsY4gsSjhkg5uiw7/ZB1Ihto0qnfQJgjGc680qGkT1d6JfvOfeYAk6
+xn5RqS/h8rYAYm64KnepfC9vIujo4NqpaREDmaLdX5MJPQ+SlytITQvgUsUq3q/t
+Ss85xjQEZH3hzwjQqdJvmA4hYP6SUjxYpBM+02xZ1Xw=
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MIIBOwIBAAJBAMGcRrZiNNmtF20zyS6MQ7pdGx17aFDl+lTl+qnLuJRUCMUG05xs
+OmxmL/O1Qlf+bnqR8Bgg65SfKg21SYuLhiMCAwEAAQJBAL94uuHyO4wux2VC+qpj
+IzPykjdU7XRcDHbbvksf4xokSeUFjjD3PB0Qa83M94y89ZfdILIqS9x5EgSB4/lX
+qNkCIQD6cCIqLfzq/lYbZbQgAAjpBXeQVYsbvVtJrPrXJAlVVQIhAMXpDKMeFPMn
+J0g2rbx1gngx0qOa5r5iMU5w/noN4W2XAiBjf+WzCG5yFvazD+dOx3TC0A8+4x3P
+uZ3pWbaXf5PNuQIgAcdXarvhelH2w2piY1g3BPeFqhzBSCK/yLGxR82KIh8CIQDD
++qGKsd09NhQ/G27y/DARzOYtml1NvdmCQAgsDIIOLA==`,
+	},
+	{
+		kind:     PEMCipherAES256,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,8E7ED5CD731902CE938957A886A5FFBD
+
+4Mxr+KIzRVwoOP0wwq6caSkvW0iS+GE2h2Ov/u+n9ZTMwL83PRnmjfjzBgfRZLVf
+JFPXxUK26kMNpIdssNnqGOds+DhB+oSrsNKoxgxSl5OBoYv9eJTVYm7qOyAFIsjr
+DRKAcjYCmzfesr7PVTowwy0RtHmYwyXMGDlAzzZrEvaiySFFmMyKKvtoavwaFoc7
+Pz3RZScwIuubzTGJ1x8EzdffYOsdCa9Mtgpp3L136+23dOd6L/qK2EG2fzrJSHs/
+2XugkleBFSMKzEp9mxXKRfa++uidQvMZTFLDK9w5YjrRvMBo/l2BoZIsq0jAIE1N
+sv5Z/KwlX+3MDEpPQpUwGPlGGdLnjI3UZ+cjgqBcoMiNc6HfgbBgYJSU6aDSHuCk
+clCwByxWkBNgJ2GrkwNrF26v+bGJJJNR4SKouY1jQf0=
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MIIBOgIBAAJBAKy3GFkstoCHIEeUU/qO8207m8WSrjksR+p9B4tf1w5k+2O1V/GY
+AQ5WFCApItcOkQe/I0yZZJk/PmCqMzSxrc8CAwEAAQJAOCAz0F7AW9oNelVQSP8F
+Sfzx7O1yom+qWyAQQJF/gFR11gpf9xpVnnyu1WxIRnDUh1LZwUsjwlDYb7MB74id
+oQIhANPcOiLwOPT4sIUpRM5HG6BF1BI7L77VpyGVk8xNP7X/AiEA0LMHZtk4I+lJ
+nClgYp4Yh2JZ1Znbu7IoQMCEJCjwKDECIGd8Dzm5tViTkUW6Hs3Tlf73nNs65duF
+aRnSglss8I3pAiEAonEnKruawgD8RavDFR+fUgmQiPz4FnGGeVgfwpGG1JECIBYq
+PXHYtPqxQIbD2pScR5qum7iGUh11lEUPkmt+2uqS`,
+	},
+	{
+		// generated with:
+		// openssl genrsa -aes128 -passout pass:asdf -out server.orig.key 128
+		kind:     PEMCipherAES128,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7
+
+6ei/MlytjE0FFgZOGQ+jrwomKfpl8kdefeE0NSt/DMRrw8OacHAzBNi3pPEa0eX3
+eND9l7C9meCirWovjj9QWVHrXyugFuDIqgdhQ8iHTgCfF3lrmcttVrbIfMDw+smD
+hTP8O1mS/MHl92NE0nhv0w==
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MGMCAQACEQC6ssxmYuauuHGOCDAI54RdAgMBAAECEQCWIn6Yv2O+kBcDF7STctKB
+AgkA8SEfu/2i3g0CCQDGNlXbBHX7kQIIK3Ww5o0cYbECCQDCimPb0dYGsQIIeQ7A
+jryIst8=`,
+	},
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/pkcs1.go b/third_party/gofrontend/libgo/go/crypto/x509/pkcs1.go
new file mode 100644
index 0000000..acebe35
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/pkcs1.go
@@ -0,0 +1,122 @@
+// 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.
+
+package x509
+
+import (
+	"crypto/rsa"
+	"encoding/asn1"
+	"errors"
+	"math/big"
+)
+
+// pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key.
+type pkcs1PrivateKey struct {
+	Version int
+	N       *big.Int
+	E       int
+	D       *big.Int
+	P       *big.Int
+	Q       *big.Int
+	// We ignore these values, if present, because rsa will calculate them.
+	Dp   *big.Int `asn1:"optional"`
+	Dq   *big.Int `asn1:"optional"`
+	Qinv *big.Int `asn1:"optional"`
+
+	AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"`
+}
+
+type pkcs1AdditionalRSAPrime struct {
+	Prime *big.Int
+
+	// We ignore these values because rsa will calculate them.
+	Exp   *big.Int
+	Coeff *big.Int
+}
+
+// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
+func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error) {
+	var priv pkcs1PrivateKey
+	rest, err := asn1.Unmarshal(der, &priv)
+	if len(rest) > 0 {
+		err = asn1.SyntaxError{Msg: "trailing data"}
+		return
+	}
+	if err != nil {
+		return
+	}
+
+	if priv.Version > 1 {
+		return nil, errors.New("x509: unsupported private key version")
+	}
+
+	if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
+		return nil, errors.New("x509: private key contains zero or negative value")
+	}
+
+	key = new(rsa.PrivateKey)
+	key.PublicKey = rsa.PublicKey{
+		E: priv.E,
+		N: priv.N,
+	}
+
+	key.D = priv.D
+	key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
+	key.Primes[0] = priv.P
+	key.Primes[1] = priv.Q
+	for i, a := range priv.AdditionalPrimes {
+		if a.Prime.Sign() <= 0 {
+			return nil, errors.New("x509: private key contains zero or negative prime")
+		}
+		key.Primes[i+2] = a.Prime
+		// We ignore the other two values because rsa will calculate
+		// them as needed.
+	}
+
+	err = key.Validate()
+	if err != nil {
+		return nil, err
+	}
+	key.Precompute()
+
+	return
+}
+
+// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
+func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
+	key.Precompute()
+
+	version := 0
+	if len(key.Primes) > 2 {
+		version = 1
+	}
+
+	priv := pkcs1PrivateKey{
+		Version: version,
+		N:       key.N,
+		E:       key.PublicKey.E,
+		D:       key.D,
+		P:       key.Primes[0],
+		Q:       key.Primes[1],
+		Dp:      key.Precomputed.Dp,
+		Dq:      key.Precomputed.Dq,
+		Qinv:    key.Precomputed.Qinv,
+	}
+
+	priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues))
+	for i, values := range key.Precomputed.CRTValues {
+		priv.AdditionalPrimes[i].Prime = key.Primes[2+i]
+		priv.AdditionalPrimes[i].Exp = values.Exp
+		priv.AdditionalPrimes[i].Coeff = values.Coeff
+	}
+
+	b, _ := asn1.Marshal(priv)
+	return b
+}
+
+// rsaPublicKey reflects the ASN.1 structure of a PKCS#1 public key.
+type rsaPublicKey struct {
+	N *big.Int
+	E int
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/pkcs8.go b/third_party/gofrontend/libgo/go/crypto/x509/pkcs8.go
new file mode 100644
index 0000000..ba19989
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/pkcs8.go
@@ -0,0 +1,54 @@
+// 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.
+
+package x509
+
+import (
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"errors"
+	"fmt"
+)
+
+// pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See
+// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn
+// and RFC5208.
+type pkcs8 struct {
+	Version    int
+	Algo       pkix.AlgorithmIdentifier
+	PrivateKey []byte
+	// optional attributes omitted.
+}
+
+// ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key. See
+// http://www.rsa.com/rsalabs/node.asp?id=2130 and RFC5208.
+func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
+	var privKey pkcs8
+	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
+		return nil, err
+	}
+	switch {
+	case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA):
+		key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
+		if err != nil {
+			return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
+		}
+		return key, nil
+
+	case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA):
+		bytes := privKey.Algo.Parameters.FullBytes
+		namedCurveOID := new(asn1.ObjectIdentifier)
+		if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
+			namedCurveOID = nil
+		}
+		key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
+		if err != nil {
+			return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
+		}
+		return key, nil
+
+	default:
+		return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/pkcs8_test.go b/third_party/gofrontend/libgo/go/crypto/x509/pkcs8_test.go
new file mode 100644
index 0000000..4114efd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/pkcs8_test.go
@@ -0,0 +1,28 @@
+// 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.
+
+package x509
+
+import (
+	"encoding/hex"
+	"testing"
+)
+
+var pkcs8RSAPrivateKeyHex = `30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031`
+
+// Generated using:
+//   openssl ecparam -genkey -name secp521r1 | openssl pkcs8 -topk8 -nocrypt
+var pkcs8ECPrivateKeyHex = `3081ed020100301006072a8648ce3d020106052b810400230481d53081d20201010441850d81618c5da1aec74c2eed608ba816038506975e6427237c2def150c96a3b13efbfa1f89f1be15cdf4d0ac26422e680e65a0ddd4ad3541ad76165fbf54d6e34ba18189038186000400da97bcedba1eb6d30aeb93c9f9a1454598fa47278df27d6f60ea73eb672d8dc528a9b67885b5b5dcef93c9824f7449ab512ee6a27e76142f56b94b474cfd697e810046c8ca70419365245c1d7d44d0db82c334073835d002232714548abbae6e5700f5ef315ee08b929d8581383dcf2d1c98c2f8a9fccbf79c9579f7b2fd8a90115ac2`
+
+func TestPKCS8(t *testing.T) {
+	derBytes, _ := hex.DecodeString(pkcs8RSAPrivateKeyHex)
+	if _, err := ParsePKCS8PrivateKey(derBytes); err != nil {
+		t.Errorf("failed to decode PKCS8 with RSA private key: %s", err)
+	}
+
+	derBytes, _ = hex.DecodeString(pkcs8ECPrivateKeyHex)
+	if _, err := ParsePKCS8PrivateKey(derBytes); err != nil {
+		t.Errorf("failed to decode PKCS8 with EC private key: %s", err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/pkix/pkix.go b/third_party/gofrontend/libgo/go/crypto/x509/pkix/pkix.go
new file mode 100644
index 0000000..58c1e54
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/pkix/pkix.go
@@ -0,0 +1,178 @@
+// 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.
+
+// Package pkix contains shared, low level structures used for ASN.1 parsing
+// and serialization of X.509 certificates, CRL and OCSP.
+package pkix
+
+import (
+	"encoding/asn1"
+	"math/big"
+	"time"
+)
+
+// AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
+// 5280, section 4.1.1.2.
+type AlgorithmIdentifier struct {
+	Algorithm  asn1.ObjectIdentifier
+	Parameters asn1.RawValue `asn1:"optional"`
+}
+
+type RDNSequence []RelativeDistinguishedNameSET
+
+type RelativeDistinguishedNameSET []AttributeTypeAndValue
+
+// AttributeTypeAndValue mirrors the ASN.1 structure of the same name in
+// http://tools.ietf.org/html/rfc5280#section-4.1.2.4
+type AttributeTypeAndValue struct {
+	Type  asn1.ObjectIdentifier
+	Value interface{}
+}
+
+// AttributeTypeAndValueSET represents a set of ASN.1 sequences of
+// AttributeTypeAndValue sequences from RFC 2986 (PKCS #10).
+type AttributeTypeAndValueSET struct {
+	Type  asn1.ObjectIdentifier
+	Value [][]AttributeTypeAndValue `asn1:"set"`
+}
+
+// Extension represents the ASN.1 structure of the same name. See RFC
+// 5280, section 4.2.
+type Extension struct {
+	Id       asn1.ObjectIdentifier
+	Critical bool `asn1:"optional"`
+	Value    []byte
+}
+
+// Name represents an X.509 distinguished name. This only includes the common
+// elements of a DN.  Additional elements in the name are ignored.
+type Name struct {
+	Country, Organization, OrganizationalUnit []string
+	Locality, Province                        []string
+	StreetAddress, PostalCode                 []string
+	SerialNumber, CommonName                  string
+
+	Names []AttributeTypeAndValue
+}
+
+func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
+	for _, rdn := range *rdns {
+		if len(rdn) == 0 {
+			continue
+		}
+		atv := rdn[0]
+		n.Names = append(n.Names, atv)
+		value, ok := atv.Value.(string)
+		if !ok {
+			continue
+		}
+
+		t := atv.Type
+		if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 {
+			switch t[3] {
+			case 3:
+				n.CommonName = value
+			case 5:
+				n.SerialNumber = value
+			case 6:
+				n.Country = append(n.Country, value)
+			case 7:
+				n.Locality = append(n.Locality, value)
+			case 8:
+				n.Province = append(n.Province, value)
+			case 9:
+				n.StreetAddress = append(n.StreetAddress, value)
+			case 10:
+				n.Organization = append(n.Organization, value)
+			case 11:
+				n.OrganizationalUnit = append(n.OrganizationalUnit, value)
+			case 17:
+				n.PostalCode = append(n.PostalCode, value)
+			}
+		}
+	}
+}
+
+var (
+	oidCountry            = []int{2, 5, 4, 6}
+	oidOrganization       = []int{2, 5, 4, 10}
+	oidOrganizationalUnit = []int{2, 5, 4, 11}
+	oidCommonName         = []int{2, 5, 4, 3}
+	oidSerialNumber       = []int{2, 5, 4, 5}
+	oidLocality           = []int{2, 5, 4, 7}
+	oidProvince           = []int{2, 5, 4, 8}
+	oidStreetAddress      = []int{2, 5, 4, 9}
+	oidPostalCode         = []int{2, 5, 4, 17}
+)
+
+// appendRDNs appends a relativeDistinguishedNameSET to the given RDNSequence
+// and returns the new value. The relativeDistinguishedNameSET contains an
+// attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and
+// search for AttributeTypeAndValue.
+func appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence {
+	if len(values) == 0 {
+		return in
+	}
+
+	s := make([]AttributeTypeAndValue, len(values))
+	for i, value := range values {
+		s[i].Type = oid
+		s[i].Value = value
+	}
+
+	return append(in, s)
+}
+
+func (n Name) ToRDNSequence() (ret RDNSequence) {
+	ret = appendRDNs(ret, n.Country, oidCountry)
+	ret = appendRDNs(ret, n.Organization, oidOrganization)
+	ret = appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
+	ret = appendRDNs(ret, n.Locality, oidLocality)
+	ret = appendRDNs(ret, n.Province, oidProvince)
+	ret = appendRDNs(ret, n.StreetAddress, oidStreetAddress)
+	ret = appendRDNs(ret, n.PostalCode, oidPostalCode)
+	if len(n.CommonName) > 0 {
+		ret = appendRDNs(ret, []string{n.CommonName}, oidCommonName)
+	}
+	if len(n.SerialNumber) > 0 {
+		ret = appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber)
+	}
+
+	return ret
+}
+
+// CertificateList represents the ASN.1 structure of the same name. See RFC
+// 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the
+// signature.
+type CertificateList struct {
+	TBSCertList        TBSCertificateList
+	SignatureAlgorithm AlgorithmIdentifier
+	SignatureValue     asn1.BitString
+}
+
+// HasExpired reports whether now is past the expiry time of certList.
+func (certList *CertificateList) HasExpired(now time.Time) bool {
+	return now.After(certList.TBSCertList.NextUpdate)
+}
+
+// TBSCertificateList represents the ASN.1 structure of the same name. See RFC
+// 5280, section 5.1.
+type TBSCertificateList struct {
+	Raw                 asn1.RawContent
+	Version             int `asn1:"optional,default:2"`
+	Signature           AlgorithmIdentifier
+	Issuer              RDNSequence
+	ThisUpdate          time.Time
+	NextUpdate          time.Time
+	RevokedCertificates []RevokedCertificate `asn1:"optional"`
+	Extensions          []Extension          `asn1:"tag:0,optional,explicit"`
+}
+
+// RevokedCertificate represents the ASN.1 structure of the same name. See RFC
+// 5280, section 5.1.
+type RevokedCertificate struct {
+	SerialNumber   *big.Int
+	RevocationTime time.Time
+	Extensions     []Extension `asn1:"optional"`
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/root.go b/third_party/gofrontend/libgo/go/crypto/x509/root.go
new file mode 100644
index 0000000..8aae14e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/root.go
@@ -0,0 +1,17 @@
+// 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 x509
+
+import "sync"
+
+var (
+	once        sync.Once
+	systemRoots *CertPool
+)
+
+func systemRootsPool() *CertPool {
+	once.Do(initSystemRoots)
+	return systemRoots
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/root_cgo_darwin.go b/third_party/gofrontend/libgo/go/crypto/x509/root_cgo_darwin.go
new file mode 100644
index 0000000..bdcc2c1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/root_cgo_darwin.go
@@ -0,0 +1,79 @@
+// 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.
+
+// +build cgo
+
+package x509
+
+/*
+#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060
+#cgo LDFLAGS: -framework CoreFoundation -framework Security
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+
+// FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
+//
+// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
+// certificates of the system. On failure, the function returns -1.
+//
+// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
+// we've consumed its content.
+int FetchPEMRoots(CFDataRef *pemRoots) {
+	if (pemRoots == NULL) {
+		return -1;
+	}
+
+	CFArrayRef certs = NULL;
+	OSStatus err = SecTrustCopyAnchorCertificates(&certs);
+	if (err != noErr) {
+		return -1;
+	}
+
+	CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
+	int i, ncerts = CFArrayGetCount(certs);
+	for (i = 0; i < ncerts; i++) {
+		CFDataRef data = NULL;
+		SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
+		if (cert == NULL) {
+			continue;
+		}
+
+		// Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
+		// Once we support weak imports via cgo we should prefer that, and fall back to this
+		// for older systems.
+		err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
+		if (err != noErr) {
+			continue;
+		}
+
+		if (data != NULL) {
+			CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
+			CFRelease(data);
+		}
+	}
+
+	CFRelease(certs);
+
+	*pemRoots = combinedData;
+	return 0;
+}
+*/
+import "C"
+import "unsafe"
+
+func initSystemRoots() {
+	roots := NewCertPool()
+
+	var data C.CFDataRef = nil
+	err := C.FetchPEMRoots(&data)
+	if err == -1 {
+		return
+	}
+
+	defer C.CFRelease(C.CFTypeRef(data))
+	buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
+	roots.AppendCertsFromPEM(buf)
+	systemRoots = roots
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/root_darwin.go b/third_party/gofrontend/libgo/go/crypto/x509/root_darwin.go
new file mode 100644
index 0000000..2a61d36
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/root_darwin.go
@@ -0,0 +1,23 @@
+// Copyright 2013 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 x509
+
+import "os/exec"
+
+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
+	return nil, nil
+}
+
+func execSecurityRoots() (*CertPool, error) {
+	cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain")
+	data, err := cmd.Output()
+	if err != nil {
+		return nil, err
+	}
+
+	roots := NewCertPool()
+	roots.AppendCertsFromPEM(data)
+	return roots, nil
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/root_nocgo_darwin.go b/third_party/gofrontend/libgo/go/crypto/x509/root_nocgo_darwin.go
new file mode 100644
index 0000000..d00e257
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/root_nocgo_darwin.go
@@ -0,0 +1,11 @@
+// Copyright 2013 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.
+
+// +build !cgo
+
+package x509
+
+func initSystemRoots() {
+	systemRoots, _ = execSecurityRoots()
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/root_plan9.go b/third_party/gofrontend/libgo/go/crypto/x509/root_plan9.go
new file mode 100644
index 0000000..9965caa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/root_plan9.go
@@ -0,0 +1,33 @@
+// 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.
+
+// +build plan9
+
+package x509
+
+import "io/ioutil"
+
+// Possible certificate files; stop after finding one.
+var certFiles = []string{
+	"/sys/lib/tls/ca.pem",
+}
+
+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
+	return nil, nil
+}
+
+func initSystemRoots() {
+	roots := NewCertPool()
+	for _, file := range certFiles {
+		data, err := ioutil.ReadFile(file)
+		if err == nil {
+			roots.AppendCertsFromPEM(data)
+			systemRoots = roots
+			return
+		}
+	}
+
+	// All of the files failed to load. systemRoots will be nil which will
+	// trigger a specific error at verification time.
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/root_unix.go b/third_party/gofrontend/libgo/go/crypto/x509/root_unix.go
new file mode 100644
index 0000000..11ad3c4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/root_unix.go
@@ -0,0 +1,37 @@
+// 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.
+
+// +build dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package x509
+
+import "io/ioutil"
+
+// Possible certificate files; stop after finding one.
+var certFiles = []string{
+	"/etc/ssl/certs/ca-certificates.crt",     // Debian/Ubuntu/Gentoo etc.
+	"/etc/pki/tls/certs/ca-bundle.crt",       // Fedora/RHEL
+	"/etc/ssl/ca-bundle.pem",                 // OpenSUSE
+	"/etc/ssl/cert.pem",                      // OpenBSD
+	"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
+}
+
+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
+	return nil, nil
+}
+
+func initSystemRoots() {
+	roots := NewCertPool()
+	for _, file := range certFiles {
+		data, err := ioutil.ReadFile(file)
+		if err == nil {
+			roots.AppendCertsFromPEM(data)
+			systemRoots = roots
+			return
+		}
+	}
+
+	// All of the files failed to load. systemRoots will be nil which will
+	// trigger a specific error at verification time.
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/root_windows.go b/third_party/gofrontend/libgo/go/crypto/x509/root_windows.go
new file mode 100644
index 0000000..81018b7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/root_windows.go
@@ -0,0 +1,229 @@
+// 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 x509
+
+import (
+	"errors"
+	"syscall"
+	"unsafe"
+)
+
+// Creates a new *syscall.CertContext representing the leaf certificate in an in-memory
+// certificate store containing itself and all of the intermediate certificates specified
+// in the opts.Intermediates CertPool.
+//
+// A pointer to the in-memory store is available in the returned CertContext's Store field.
+// The store is automatically freed when the CertContext is freed using
+// syscall.CertFreeCertificateContext.
+func createStoreContext(leaf *Certificate, opts *VerifyOptions) (*syscall.CertContext, error) {
+	var storeCtx *syscall.CertContext
+
+	leafCtx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &leaf.Raw[0], uint32(len(leaf.Raw)))
+	if err != nil {
+		return nil, err
+	}
+	defer syscall.CertFreeCertificateContext(leafCtx)
+
+	handle, err := syscall.CertOpenStore(syscall.CERT_STORE_PROV_MEMORY, 0, 0, syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, 0)
+	if err != nil {
+		return nil, err
+	}
+	defer syscall.CertCloseStore(handle, 0)
+
+	err = syscall.CertAddCertificateContextToStore(handle, leafCtx, syscall.CERT_STORE_ADD_ALWAYS, &storeCtx)
+	if err != nil {
+		return nil, err
+	}
+
+	if opts.Intermediates != nil {
+		for _, intermediate := range opts.Intermediates.certs {
+			ctx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &intermediate.Raw[0], uint32(len(intermediate.Raw)))
+			if err != nil {
+				return nil, err
+			}
+
+			err = syscall.CertAddCertificateContextToStore(handle, ctx, syscall.CERT_STORE_ADD_ALWAYS, nil)
+			syscall.CertFreeCertificateContext(ctx)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	return storeCtx, nil
+}
+
+// extractSimpleChain extracts the final certificate chain from a CertSimpleChain.
+func extractSimpleChain(simpleChain **syscall.CertSimpleChain, count int) (chain []*Certificate, err error) {
+	if simpleChain == nil || count == 0 {
+		return nil, errors.New("x509: invalid simple chain")
+	}
+
+	simpleChains := (*[1 << 20]*syscall.CertSimpleChain)(unsafe.Pointer(simpleChain))[:]
+	lastChain := simpleChains[count-1]
+	elements := (*[1 << 20]*syscall.CertChainElement)(unsafe.Pointer(lastChain.Elements))[:]
+	for i := 0; i < int(lastChain.NumElements); i++ {
+		// Copy the buf, since ParseCertificate does not create its own copy.
+		cert := elements[i].CertContext
+		encodedCert := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]
+		buf := make([]byte, cert.Length)
+		copy(buf, encodedCert[:])
+		parsedCert, err := ParseCertificate(buf)
+		if err != nil {
+			return nil, err
+		}
+		chain = append(chain, parsedCert)
+	}
+
+	return chain, nil
+}
+
+// checkChainTrustStatus checks the trust status of the certificate chain, translating
+// any errors it finds into Go errors in the process.
+func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) error {
+	if chainCtx.TrustStatus.ErrorStatus != syscall.CERT_TRUST_NO_ERROR {
+		status := chainCtx.TrustStatus.ErrorStatus
+		switch status {
+		case syscall.CERT_TRUST_IS_NOT_TIME_VALID:
+			return CertificateInvalidError{c, Expired}
+		default:
+			return UnknownAuthorityError{c, nil, nil}
+		}
+	}
+	return nil
+}
+
+// checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for
+// use as a certificate chain for a SSL/TLS server.
+func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error {
+	servernamep, err := syscall.UTF16PtrFromString(opts.DNSName)
+	if err != nil {
+		return err
+	}
+	sslPara := &syscall.SSLExtraCertChainPolicyPara{
+		AuthType:   syscall.AUTHTYPE_SERVER,
+		ServerName: servernamep,
+	}
+	sslPara.Size = uint32(unsafe.Sizeof(*sslPara))
+
+	para := &syscall.CertChainPolicyPara{
+		ExtraPolicyPara: uintptr(unsafe.Pointer(sslPara)),
+	}
+	para.Size = uint32(unsafe.Sizeof(*para))
+
+	status := syscall.CertChainPolicyStatus{}
+	err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status)
+	if err != nil {
+		return err
+	}
+
+	// TODO(mkrautz): use the lChainIndex and lElementIndex fields
+	// of the CertChainPolicyStatus to provide proper context, instead
+	// using c.
+	if status.Error != 0 {
+		switch status.Error {
+		case syscall.CERT_E_EXPIRED:
+			return CertificateInvalidError{c, Expired}
+		case syscall.CERT_E_CN_NO_MATCH:
+			return HostnameError{c, opts.DNSName}
+		case syscall.CERT_E_UNTRUSTEDROOT:
+			return UnknownAuthorityError{c, nil, nil}
+		default:
+			return UnknownAuthorityError{c, nil, nil}
+		}
+	}
+
+	return nil
+}
+
+// systemVerify is like Verify, except that it uses CryptoAPI calls
+// to build certificate chains and verify them.
+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
+	hasDNSName := opts != nil && len(opts.DNSName) > 0
+
+	storeCtx, err := createStoreContext(c, opts)
+	if err != nil {
+		return nil, err
+	}
+	defer syscall.CertFreeCertificateContext(storeCtx)
+
+	para := new(syscall.CertChainPara)
+	para.Size = uint32(unsafe.Sizeof(*para))
+
+	// If there's a DNSName set in opts, assume we're verifying
+	// a certificate from a TLS server.
+	if hasDNSName {
+		oids := []*byte{
+			&syscall.OID_PKIX_KP_SERVER_AUTH[0],
+			// Both IE and Chrome allow certificates with
+			// Server Gated Crypto as well. Some certificates
+			// in the wild require them.
+			&syscall.OID_SERVER_GATED_CRYPTO[0],
+			&syscall.OID_SGC_NETSCAPE[0],
+		}
+		para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_OR
+		para.RequestedUsage.Usage.Length = uint32(len(oids))
+		para.RequestedUsage.Usage.UsageIdentifiers = &oids[0]
+	} else {
+		para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_AND
+		para.RequestedUsage.Usage.Length = 0
+		para.RequestedUsage.Usage.UsageIdentifiers = nil
+	}
+
+	var verifyTime *syscall.Filetime
+	if opts != nil && !opts.CurrentTime.IsZero() {
+		ft := syscall.NsecToFiletime(opts.CurrentTime.UnixNano())
+		verifyTime = &ft
+	}
+
+	// CertGetCertificateChain will traverse Windows's root stores
+	// in an attempt to build a verified certificate chain.  Once
+	// it has found a verified chain, it stops. MSDN docs on
+	// CERT_CHAIN_CONTEXT:
+	//
+	//   When a CERT_CHAIN_CONTEXT is built, the first simple chain
+	//   begins with an end certificate and ends with a self-signed
+	//   certificate. If that self-signed certificate is not a root
+	//   or otherwise trusted certificate, an attempt is made to
+	//   build a new chain. CTLs are used to create the new chain
+	//   beginning with the self-signed certificate from the original
+	//   chain as the end certificate of the new chain. This process
+	//   continues building additional simple chains until the first
+	//   self-signed certificate is a trusted certificate or until
+	//   an additional simple chain cannot be built.
+	//
+	// The result is that we'll only get a single trusted chain to
+	// return to our caller.
+	var chainCtx *syscall.CertChainContext
+	err = syscall.CertGetCertificateChain(syscall.Handle(0), storeCtx, verifyTime, storeCtx.Store, para, 0, 0, &chainCtx)
+	if err != nil {
+		return nil, err
+	}
+	defer syscall.CertFreeCertificateChain(chainCtx)
+
+	err = checkChainTrustStatus(c, chainCtx)
+	if err != nil {
+		return nil, err
+	}
+
+	if hasDNSName {
+		err = checkChainSSLServerPolicy(c, chainCtx, opts)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	chain, err := extractSimpleChain(chainCtx.Chains, int(chainCtx.ChainCount))
+	if err != nil {
+		return nil, err
+	}
+
+	chains = append(chains, chain)
+
+	return chains, nil
+}
+
+func initSystemRoots() {
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/sec1.go b/third_party/gofrontend/libgo/go/crypto/x509/sec1.go
new file mode 100644
index 0000000..7de6675
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/sec1.go
@@ -0,0 +1,83 @@
+// 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 x509
+
+import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"encoding/asn1"
+	"errors"
+	"fmt"
+	"math/big"
+)
+
+const ecPrivKeyVersion = 1
+
+// ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure.
+// References:
+//   RFC5915
+//   SEC1 - http://www.secg.org/download/aid-780/sec1-v2.pdf
+// Per RFC5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in
+// most cases it is not.
+type ecPrivateKey struct {
+	Version       int
+	PrivateKey    []byte
+	NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
+	PublicKey     asn1.BitString        `asn1:"optional,explicit,tag:1"`
+}
+
+// ParseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
+func ParseECPrivateKey(der []byte) (key *ecdsa.PrivateKey, err error) {
+	return parseECPrivateKey(nil, der)
+}
+
+// MarshalECPrivateKey marshals an EC private key into ASN.1, DER format.
+func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
+	oid, ok := oidFromNamedCurve(key.Curve)
+	if !ok {
+		return nil, errors.New("x509: unknown elliptic curve")
+	}
+	return asn1.Marshal(ecPrivateKey{
+		Version:       1,
+		PrivateKey:    key.D.Bytes(),
+		NamedCurveOID: oid,
+		PublicKey:     asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
+	})
+}
+
+// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
+// The OID for the named curve may be provided from another source (such as
+// the PKCS8 container) - if it is provided then use this instead of the OID
+// that may exist in the EC private key structure.
+func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) {
+	var privKey ecPrivateKey
+	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
+		return nil, errors.New("x509: failed to parse EC private key: " + err.Error())
+	}
+	if privKey.Version != ecPrivKeyVersion {
+		return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version)
+	}
+
+	var curve elliptic.Curve
+	if namedCurveOID != nil {
+		curve = namedCurveFromOID(*namedCurveOID)
+	} else {
+		curve = namedCurveFromOID(privKey.NamedCurveOID)
+	}
+	if curve == nil {
+		return nil, errors.New("x509: unknown elliptic curve")
+	}
+
+	k := new(big.Int).SetBytes(privKey.PrivateKey)
+	if k.Cmp(curve.Params().N) >= 0 {
+		return nil, errors.New("x509: invalid elliptic curve private key value")
+	}
+	priv := new(ecdsa.PrivateKey)
+	priv.Curve = curve
+	priv.D = k
+	priv.X, priv.Y = curve.ScalarBaseMult(privKey.PrivateKey)
+
+	return priv, nil
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/sec1_test.go b/third_party/gofrontend/libgo/go/crypto/x509/sec1_test.go
new file mode 100644
index 0000000..95f18e7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/sec1_test.go
@@ -0,0 +1,30 @@
+// 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 x509
+
+import (
+	"bytes"
+	"encoding/hex"
+	"testing"
+)
+
+// Generated using:
+//   openssl ecparam -genkey -name secp384r1 -outform PEM
+var ecPrivateKeyHex = `3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50`
+
+func TestParseECPrivateKey(t *testing.T) {
+	derBytes, _ := hex.DecodeString(ecPrivateKeyHex)
+	key, err := ParseECPrivateKey(derBytes)
+	if err != nil {
+		t.Errorf("failed to decode EC private key: %s", err)
+	}
+	serialized, err := MarshalECPrivateKey(key)
+	if err != nil {
+		t.Fatalf("failed to encode EC private key: %s", err)
+	}
+	if !bytes.Equal(serialized, derBytes) {
+		t.Fatalf("serialized key differs: got %x, want %x", serialized, derBytes)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/verify.go b/third_party/gofrontend/libgo/go/crypto/x509/verify.go
new file mode 100644
index 0000000..5fd8e37
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/verify.go
@@ -0,0 +1,474 @@
+// 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.
+
+package x509
+
+import (
+	"fmt"
+	"net"
+	"runtime"
+	"strings"
+	"time"
+	"unicode/utf8"
+)
+
+type InvalidReason int
+
+const (
+	// NotAuthorizedToSign results when a certificate is signed by another
+	// which isn't marked as a CA certificate.
+	NotAuthorizedToSign InvalidReason = iota
+	// Expired results when a certificate has expired, based on the time
+	// given in the VerifyOptions.
+	Expired
+	// CANotAuthorizedForThisName results when an intermediate or root
+	// certificate has a name constraint which doesn't include the name
+	// being checked.
+	CANotAuthorizedForThisName
+	// TooManyIntermediates results when a path length constraint is
+	// violated.
+	TooManyIntermediates
+	// IncompatibleUsage results when the certificate's key usage indicates
+	// that it may only be used for a different purpose.
+	IncompatibleUsage
+)
+
+// CertificateInvalidError results when an odd error occurs. Users of this
+// library probably want to handle all these errors uniformly.
+type CertificateInvalidError struct {
+	Cert   *Certificate
+	Reason InvalidReason
+}
+
+func (e CertificateInvalidError) Error() string {
+	switch e.Reason {
+	case NotAuthorizedToSign:
+		return "x509: certificate is not authorized to sign other certificates"
+	case Expired:
+		return "x509: certificate has expired or is not yet valid"
+	case CANotAuthorizedForThisName:
+		return "x509: a root or intermediate certificate is not authorized to sign in this domain"
+	case TooManyIntermediates:
+		return "x509: too many intermediates for path length constraint"
+	case IncompatibleUsage:
+		return "x509: certificate specifies an incompatible key usage"
+	}
+	return "x509: unknown error"
+}
+
+// HostnameError results when the set of authorized names doesn't match the
+// requested name.
+type HostnameError struct {
+	Certificate *Certificate
+	Host        string
+}
+
+func (h HostnameError) Error() string {
+	c := h.Certificate
+
+	var valid string
+	if ip := net.ParseIP(h.Host); ip != nil {
+		// Trying to validate an IP
+		if len(c.IPAddresses) == 0 {
+			return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
+		}
+		for _, san := range c.IPAddresses {
+			if len(valid) > 0 {
+				valid += ", "
+			}
+			valid += san.String()
+		}
+	} else {
+		if len(c.DNSNames) > 0 {
+			valid = strings.Join(c.DNSNames, ", ")
+		} else {
+			valid = c.Subject.CommonName
+		}
+	}
+	return "x509: certificate is valid for " + valid + ", not " + h.Host
+}
+
+// UnknownAuthorityError results when the certificate issuer is unknown
+type UnknownAuthorityError struct {
+	cert *Certificate
+	// hintErr contains an error that may be helpful in determining why an
+	// authority wasn't found.
+	hintErr error
+	// hintCert contains a possible authority certificate that was rejected
+	// because of the error in hintErr.
+	hintCert *Certificate
+}
+
+func (e UnknownAuthorityError) Error() string {
+	s := "x509: certificate signed by unknown authority"
+	if e.hintErr != nil {
+		certName := e.hintCert.Subject.CommonName
+		if len(certName) == 0 {
+			if len(e.hintCert.Subject.Organization) > 0 {
+				certName = e.hintCert.Subject.Organization[0]
+			}
+			certName = "serial:" + e.hintCert.SerialNumber.String()
+		}
+		s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
+	}
+	return s
+}
+
+// SystemRootsError results when we fail to load the system root certificates.
+type SystemRootsError struct {
+}
+
+func (e SystemRootsError) Error() string {
+	return "x509: failed to load system roots and no roots provided"
+}
+
+// VerifyOptions contains parameters for Certificate.Verify. It's a structure
+// because other PKIX verification APIs have ended up needing many options.
+type VerifyOptions struct {
+	DNSName       string
+	Intermediates *CertPool
+	Roots         *CertPool // if nil, the system roots are used
+	CurrentTime   time.Time // if zero, the current time is used
+	// KeyUsage specifies which Extended Key Usage values are acceptable.
+	// An empty list means ExtKeyUsageServerAuth. Key usage is considered a
+	// constraint down the chain which mirrors Windows CryptoAPI behaviour,
+	// but not the spec. To accept any key usage, include ExtKeyUsageAny.
+	KeyUsages []ExtKeyUsage
+}
+
+const (
+	leafCertificate = iota
+	intermediateCertificate
+	rootCertificate
+)
+
+// isValid performs validity checks on the c.
+func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
+	now := opts.CurrentTime
+	if now.IsZero() {
+		now = time.Now()
+	}
+	if now.Before(c.NotBefore) || now.After(c.NotAfter) {
+		return CertificateInvalidError{c, Expired}
+	}
+
+	if len(c.PermittedDNSDomains) > 0 {
+		ok := false
+		for _, domain := range c.PermittedDNSDomains {
+			if opts.DNSName == domain ||
+				(strings.HasSuffix(opts.DNSName, domain) &&
+					len(opts.DNSName) >= 1+len(domain) &&
+					opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') {
+				ok = true
+				break
+			}
+		}
+
+		if !ok {
+			return CertificateInvalidError{c, CANotAuthorizedForThisName}
+		}
+	}
+
+	// KeyUsage status flags are ignored. From Engineering Security, Peter
+	// Gutmann: A European government CA marked its signing certificates as
+	// being valid for encryption only, but no-one noticed. Another
+	// European CA marked its signature keys as not being valid for
+	// signatures. A different CA marked its own trusted root certificate
+	// as being invalid for certificate signing.  Another national CA
+	// distributed a certificate to be used to encrypt data for the
+	// country’s tax authority that was marked as only being usable for
+	// digital signatures but not for encryption. Yet another CA reversed
+	// the order of the bit flags in the keyUsage due to confusion over
+	// encoding endianness, essentially setting a random keyUsage in
+	// certificates that it issued. Another CA created a self-invalidating
+	// certificate by adding a certificate policy statement stipulating
+	// that the certificate had to be used strictly as specified in the
+	// keyUsage, and a keyUsage containing a flag indicating that the RSA
+	// encryption key could only be used for Diffie-Hellman key agreement.
+
+	if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
+		return CertificateInvalidError{c, NotAuthorizedToSign}
+	}
+
+	if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
+		numIntermediates := len(currentChain) - 1
+		if numIntermediates > c.MaxPathLen {
+			return CertificateInvalidError{c, TooManyIntermediates}
+		}
+	}
+
+	return nil
+}
+
+// Verify attempts to verify c by building one or more chains from c to a
+// certificate in opts.Roots, using certificates in opts.Intermediates if
+// needed. If successful, it returns one or more chains where the first
+// element of the chain is c and the last element is from opts.Roots.
+//
+// WARNING: this doesn't do any revocation checking.
+func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
+	// Use Windows's own verification and chain building.
+	if opts.Roots == nil && runtime.GOOS == "windows" {
+		return c.systemVerify(&opts)
+	}
+
+	if opts.Roots == nil {
+		opts.Roots = systemRootsPool()
+		if opts.Roots == nil {
+			return nil, SystemRootsError{}
+		}
+	}
+
+	err = c.isValid(leafCertificate, nil, &opts)
+	if err != nil {
+		return
+	}
+
+	if len(opts.DNSName) > 0 {
+		err = c.VerifyHostname(opts.DNSName)
+		if err != nil {
+			return
+		}
+	}
+
+	candidateChains, err := c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
+	if err != nil {
+		return
+	}
+
+	keyUsages := opts.KeyUsages
+	if len(keyUsages) == 0 {
+		keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
+	}
+
+	// If any key usage is acceptable then we're done.
+	for _, usage := range keyUsages {
+		if usage == ExtKeyUsageAny {
+			chains = candidateChains
+			return
+		}
+	}
+
+	for _, candidate := range candidateChains {
+		if checkChainForKeyUsage(candidate, keyUsages) {
+			chains = append(chains, candidate)
+		}
+	}
+
+	if len(chains) == 0 {
+		err = CertificateInvalidError{c, IncompatibleUsage}
+	}
+
+	return
+}
+
+func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
+	n := make([]*Certificate, len(chain)+1)
+	copy(n, chain)
+	n[len(chain)] = cert
+	return n
+}
+
+func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) {
+	possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c)
+	for _, rootNum := range possibleRoots {
+		root := opts.Roots.certs[rootNum]
+		err = root.isValid(rootCertificate, currentChain, opts)
+		if err != nil {
+			continue
+		}
+		chains = append(chains, appendToFreshChain(currentChain, root))
+	}
+
+	possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c)
+nextIntermediate:
+	for _, intermediateNum := range possibleIntermediates {
+		intermediate := opts.Intermediates.certs[intermediateNum]
+		for _, cert := range currentChain {
+			if cert == intermediate {
+				continue nextIntermediate
+			}
+		}
+		err = intermediate.isValid(intermediateCertificate, currentChain, opts)
+		if err != nil {
+			continue
+		}
+		var childChains [][]*Certificate
+		childChains, ok := cache[intermediateNum]
+		if !ok {
+			childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts)
+			cache[intermediateNum] = childChains
+		}
+		chains = append(chains, childChains...)
+	}
+
+	if len(chains) > 0 {
+		err = nil
+	}
+
+	if len(chains) == 0 && err == nil {
+		hintErr := rootErr
+		hintCert := failedRoot
+		if hintErr == nil {
+			hintErr = intermediateErr
+			hintCert = failedIntermediate
+		}
+		err = UnknownAuthorityError{c, hintErr, hintCert}
+	}
+
+	return
+}
+
+func matchHostnames(pattern, host string) bool {
+	if len(pattern) == 0 || len(host) == 0 {
+		return false
+	}
+
+	patternParts := strings.Split(pattern, ".")
+	hostParts := strings.Split(host, ".")
+
+	if len(patternParts) != len(hostParts) {
+		return false
+	}
+
+	for i, patternPart := range patternParts {
+		if patternPart == "*" {
+			continue
+		}
+		if patternPart != hostParts[i] {
+			return false
+		}
+	}
+
+	return true
+}
+
+// toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
+// an explicitly ASCII function to avoid any sharp corners resulting from
+// performing Unicode operations on DNS labels.
+func toLowerCaseASCII(in string) string {
+	// If the string is already lower-case then there's nothing to do.
+	isAlreadyLowerCase := true
+	for _, c := range in {
+		if c == utf8.RuneError {
+			// If we get a UTF-8 error then there might be
+			// upper-case ASCII bytes in the invalid sequence.
+			isAlreadyLowerCase = false
+			break
+		}
+		if 'A' <= c && c <= 'Z' {
+			isAlreadyLowerCase = false
+			break
+		}
+	}
+
+	if isAlreadyLowerCase {
+		return in
+	}
+
+	out := []byte(in)
+	for i, c := range out {
+		if 'A' <= c && c <= 'Z' {
+			out[i] += 'a' - 'A'
+		}
+	}
+	return string(out)
+}
+
+// VerifyHostname returns nil if c is a valid certificate for the named host.
+// Otherwise it returns an error describing the mismatch.
+func (c *Certificate) VerifyHostname(h string) error {
+	// IP addresses may be written in [ ].
+	candidateIP := h
+	if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
+		candidateIP = h[1 : len(h)-1]
+	}
+	if ip := net.ParseIP(candidateIP); ip != nil {
+		// We only match IP addresses against IP SANs.
+		// https://tools.ietf.org/html/rfc6125#appendix-B.2
+		for _, candidate := range c.IPAddresses {
+			if ip.Equal(candidate) {
+				return nil
+			}
+		}
+		return HostnameError{c, candidateIP}
+	}
+
+	lowered := toLowerCaseASCII(h)
+
+	if len(c.DNSNames) > 0 {
+		for _, match := range c.DNSNames {
+			if matchHostnames(toLowerCaseASCII(match), lowered) {
+				return nil
+			}
+		}
+		// If Subject Alt Name is given, we ignore the common name.
+	} else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) {
+		return nil
+	}
+
+	return HostnameError{c, h}
+}
+
+func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
+	usages := make([]ExtKeyUsage, len(keyUsages))
+	copy(usages, keyUsages)
+
+	if len(chain) == 0 {
+		return false
+	}
+
+	usagesRemaining := len(usages)
+
+	// We walk down the list and cross out any usages that aren't supported
+	// by each certificate. If we cross out all the usages, then the chain
+	// is unacceptable.
+
+NextCert:
+	for i := len(chain) - 1; i >= 0; i-- {
+		cert := chain[i]
+		if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
+			// The certificate doesn't have any extended key usage specified.
+			continue
+		}
+
+		for _, usage := range cert.ExtKeyUsage {
+			if usage == ExtKeyUsageAny {
+				// The certificate is explicitly good for any usage.
+				continue NextCert
+			}
+		}
+
+		const invalidUsage ExtKeyUsage = -1
+
+	NextRequestedUsage:
+		for i, requestedUsage := range usages {
+			if requestedUsage == invalidUsage {
+				continue
+			}
+
+			for _, usage := range cert.ExtKeyUsage {
+				if requestedUsage == usage {
+					continue NextRequestedUsage
+				} else if requestedUsage == ExtKeyUsageServerAuth &&
+					(usage == ExtKeyUsageNetscapeServerGatedCrypto ||
+						usage == ExtKeyUsageMicrosoftServerGatedCrypto) {
+					// In order to support COMODO
+					// certificate chains, we have to
+					// accept Netscape or Microsoft SGC
+					// usages as equal to ServerAuth.
+					continue NextRequestedUsage
+				}
+			}
+
+			usages[i] = invalidUsage
+			usagesRemaining--
+			if usagesRemaining == 0 {
+				return false
+			}
+		}
+	}
+
+	return true
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/verify_test.go b/third_party/gofrontend/libgo/go/crypto/x509/verify_test.go
new file mode 100644
index 0000000..96b9d9b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/verify_test.go
@@ -0,0 +1,1123 @@
+// 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.
+
+package x509
+
+import (
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"errors"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+type verifyTest struct {
+	leaf                 string
+	intermediates        []string
+	roots                []string
+	currentTime          int64
+	dnsName              string
+	systemSkip           bool
+	keyUsages            []ExtKeyUsage
+	testSystemRootsError bool
+
+	errorCallback  func(*testing.T, int, error) bool
+	expectedChains [][]string
+}
+
+var verifyTests = []verifyTest{
+	{
+		leaf:                 googleLeaf,
+		intermediates:        []string{giag2Intermediate},
+		currentTime:          1395785200,
+		dnsName:              "www.google.com",
+		testSystemRootsError: true,
+
+		// Without any roots specified we should get a system roots
+		// error.
+		errorCallback: expectSystemRootsError,
+	},
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{giag2Intermediate},
+		roots:         []string{geoTrustRoot},
+		currentTime:   1395785200,
+		dnsName:       "www.google.com",
+
+		expectedChains: [][]string{
+			{"Google", "Google Internet Authority", "GeoTrust"},
+		},
+	},
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{giag2Intermediate},
+		roots:         []string{geoTrustRoot},
+		currentTime:   1395785200,
+		dnsName:       "WwW.GooGLE.coM",
+
+		expectedChains: [][]string{
+			{"Google", "Google Internet Authority", "GeoTrust"},
+		},
+	},
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{giag2Intermediate},
+		roots:         []string{geoTrustRoot},
+		currentTime:   1395785200,
+		dnsName:       "www.example.com",
+
+		errorCallback: expectHostnameError,
+	},
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{giag2Intermediate},
+		roots:         []string{geoTrustRoot},
+		currentTime:   1,
+		dnsName:       "www.example.com",
+
+		errorCallback: expectExpired,
+	},
+	{
+		leaf:        googleLeaf,
+		roots:       []string{geoTrustRoot},
+		currentTime: 1395785200,
+		dnsName:     "www.google.com",
+
+		// Skip when using systemVerify, since Windows
+		// *will* find the missing intermediate cert.
+		systemSkip:    true,
+		errorCallback: expectAuthorityUnknown,
+	},
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{geoTrustRoot, giag2Intermediate},
+		roots:         []string{geoTrustRoot},
+		currentTime:   1395785200,
+		dnsName:       "www.google.com",
+
+		expectedChains: [][]string{
+			{"Google", "Google Internet Authority", "GeoTrust"},
+			// TODO(agl): this is ok, but it would be nice if the
+			//            chain building didn't visit the same SPKI
+			//            twice.
+			{"Google", "Google Internet Authority", "GeoTrust", "GeoTrust"},
+		},
+		// CAPI doesn't build the chain with the duplicated GeoTrust
+		// entry so the results don't match. Thus we skip this test
+		// until that's fixed.
+		systemSkip: true,
+	},
+	{
+		leaf:          dnssecExpLeaf,
+		intermediates: []string{startComIntermediate},
+		roots:         []string{startComRoot},
+		currentTime:   1302726541,
+
+		expectedChains: [][]string{
+			{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
+		},
+	},
+	{
+		leaf:          dnssecExpLeaf,
+		intermediates: []string{startComIntermediate, startComRoot},
+		roots:         []string{startComRoot},
+		currentTime:   1302726541,
+
+		// Skip when using systemVerify, since Windows
+		// can only return a single chain to us (for now).
+		systemSkip: true,
+		expectedChains: [][]string{
+			{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
+			{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority", "StartCom Certification Authority"},
+		},
+	},
+	{
+		leaf:          googleLeafWithInvalidHash,
+		intermediates: []string{giag2Intermediate},
+		roots:         []string{geoTrustRoot},
+		currentTime:   1395785200,
+		dnsName:       "www.google.com",
+
+		// The specific error message may not occur when using system
+		// verification.
+		systemSkip:    true,
+		errorCallback: expectHashError,
+	},
+	{
+		// The default configuration should reject an S/MIME chain.
+		leaf:        smimeLeaf,
+		roots:       []string{smimeIntermediate},
+		currentTime: 1339436154,
+
+		// Key usage not implemented for Windows yet.
+		systemSkip:    true,
+		errorCallback: expectUsageError,
+	},
+	{
+		leaf:        smimeLeaf,
+		roots:       []string{smimeIntermediate},
+		currentTime: 1339436154,
+		keyUsages:   []ExtKeyUsage{ExtKeyUsageServerAuth},
+
+		// Key usage not implemented for Windows yet.
+		systemSkip:    true,
+		errorCallback: expectUsageError,
+	},
+	{
+		leaf:        smimeLeaf,
+		roots:       []string{smimeIntermediate},
+		currentTime: 1339436154,
+		keyUsages:   []ExtKeyUsage{ExtKeyUsageEmailProtection},
+
+		// Key usage not implemented for Windows yet.
+		systemSkip: true,
+		expectedChains: [][]string{
+			{"Ryan Hurst", "GlobalSign PersonalSign 2 CA - G2"},
+		},
+	},
+	{
+		leaf:          megaLeaf,
+		intermediates: []string{comodoIntermediate1},
+		roots:         []string{comodoRoot},
+		currentTime:   1360431182,
+
+		// CryptoAPI can find alternative validation paths so we don't
+		// perform this test with system validation.
+		systemSkip: true,
+		expectedChains: [][]string{
+			{"mega.co.nz", "EssentialSSL CA", "COMODO Certification Authority"},
+		},
+	},
+	{
+		// Check that a name constrained intermediate works even when
+		// it lists multiple constraints.
+		leaf:          nameConstraintsLeaf,
+		intermediates: []string{nameConstraintsIntermediate1, nameConstraintsIntermediate2},
+		roots:         []string{globalSignRoot},
+		currentTime:   1382387896,
+		dnsName:       "secure.iddl.vt.edu",
+
+		expectedChains: [][]string{
+			{
+				"Technology-enhanced Learning and Online Strategies",
+				"Virginia Tech Global Qualified Server CA",
+				"Trusted Root CA G2",
+				"GlobalSign Root CA",
+			},
+		},
+	},
+	{
+		// Check that SHA-384 intermediates (which are popping up)
+		// work.
+		leaf:          moipLeafCert,
+		intermediates: []string{comodoIntermediateSHA384, comodoRSAAuthority},
+		roots:         []string{addTrustRoot},
+		currentTime:   1397502195,
+		dnsName:       "api.moip.com.br",
+
+		expectedChains: [][]string{
+			{
+				"api.moip.com.br",
+				"COMODO RSA Extended Validation Secure Server CA",
+				"COMODO RSA Certification Authority",
+				"AddTrust External CA Root",
+			},
+		},
+	},
+}
+
+func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
+	if _, ok := err.(HostnameError); !ok {
+		t.Errorf("#%d: error was not a HostnameError: %s", i, err)
+		return false
+	}
+	return true
+}
+
+func expectExpired(t *testing.T, i int, err error) (ok bool) {
+	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired {
+		t.Errorf("#%d: error was not Expired: %s", i, err)
+		return false
+	}
+	return true
+}
+
+func expectUsageError(t *testing.T, i int, err error) (ok bool) {
+	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != IncompatibleUsage {
+		t.Errorf("#%d: error was not IncompatibleUsage: %s", i, err)
+		return false
+	}
+	return true
+}
+
+func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) {
+	if _, ok := err.(UnknownAuthorityError); !ok {
+		t.Errorf("#%d: error was not UnknownAuthorityError: %s", i, err)
+		return false
+	}
+	return true
+}
+
+func expectSystemRootsError(t *testing.T, i int, err error) bool {
+	if _, ok := err.(SystemRootsError); !ok {
+		t.Errorf("#%d: error was not SystemRootsError: %s", i, err)
+		return false
+	}
+	return true
+}
+
+func expectHashError(t *testing.T, i int, err error) bool {
+	if err == nil {
+		t.Errorf("#%d: no error resulted from invalid hash", i)
+		return false
+	}
+	if expected := "algorithm unimplemented"; !strings.Contains(err.Error(), expected) {
+		t.Errorf("#%d: error resulting from invalid hash didn't contain '%s', rather it was: %s", i, expected, err)
+		return false
+	}
+	return true
+}
+
+func certificateFromPEM(pemBytes string) (*Certificate, error) {
+	block, _ := pem.Decode([]byte(pemBytes))
+	if block == nil {
+		return nil, errors.New("failed to decode PEM")
+	}
+	return ParseCertificate(block.Bytes)
+}
+
+func testVerify(t *testing.T, useSystemRoots bool) {
+	for i, test := range verifyTests {
+		if useSystemRoots && test.systemSkip {
+			continue
+		}
+		if runtime.GOOS == "windows" && test.testSystemRootsError {
+			continue
+		}
+
+		opts := VerifyOptions{
+			Intermediates: NewCertPool(),
+			DNSName:       test.dnsName,
+			CurrentTime:   time.Unix(test.currentTime, 0),
+			KeyUsages:     test.keyUsages,
+		}
+
+		if !useSystemRoots {
+			opts.Roots = NewCertPool()
+			for j, root := range test.roots {
+				ok := opts.Roots.AppendCertsFromPEM([]byte(root))
+				if !ok {
+					t.Errorf("#%d: failed to parse root #%d", i, j)
+					return
+				}
+			}
+		}
+
+		for j, intermediate := range test.intermediates {
+			ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate))
+			if !ok {
+				t.Errorf("#%d: failed to parse intermediate #%d", i, j)
+				return
+			}
+		}
+
+		leaf, err := certificateFromPEM(test.leaf)
+		if err != nil {
+			t.Errorf("#%d: failed to parse leaf: %s", i, err)
+			return
+		}
+
+		var oldSystemRoots *CertPool
+		if test.testSystemRootsError {
+			oldSystemRoots = systemRootsPool()
+			systemRoots = nil
+			opts.Roots = nil
+		}
+
+		chains, err := leaf.Verify(opts)
+
+		if test.testSystemRootsError {
+			systemRoots = oldSystemRoots
+		}
+
+		if test.errorCallback == nil && err != nil {
+			t.Errorf("#%d: unexpected error: %s", i, err)
+		}
+		if test.errorCallback != nil {
+			if !test.errorCallback(t, i, err) {
+				return
+			}
+		}
+
+		if len(chains) != len(test.expectedChains) {
+			t.Errorf("#%d: wanted %d chains, got %d", i, len(test.expectedChains), len(chains))
+		}
+
+		// We check that each returned chain matches a chain from
+		// expectedChains but an entry in expectedChains can't match
+		// two chains.
+		seenChains := make([]bool, len(chains))
+	NextOutputChain:
+		for _, chain := range chains {
+		TryNextExpected:
+			for j, expectedChain := range test.expectedChains {
+				if seenChains[j] {
+					continue
+				}
+				if len(chain) != len(expectedChain) {
+					continue
+				}
+				for k, cert := range chain {
+					if strings.Index(nameToKey(&cert.Subject), expectedChain[k]) == -1 {
+						continue TryNextExpected
+					}
+				}
+				// we matched
+				seenChains[j] = true
+				continue NextOutputChain
+			}
+			t.Errorf("#%d: No expected chain matched %s", i, chainToDebugString(chain))
+		}
+	}
+}
+
+func TestGoVerify(t *testing.T) {
+	testVerify(t, false)
+}
+
+func TestSystemVerify(t *testing.T) {
+	if runtime.GOOS != "windows" {
+		t.Skipf("skipping verify test using system APIs on %q", runtime.GOOS)
+	}
+
+	testVerify(t, true)
+}
+
+func chainToDebugString(chain []*Certificate) string {
+	var chainStr string
+	for _, cert := range chain {
+		if len(chainStr) > 0 {
+			chainStr += " -> "
+		}
+		chainStr += nameToKey(&cert.Subject)
+	}
+	return chainStr
+}
+
+func nameToKey(name *pkix.Name) string {
+	return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
+}
+
+const geoTrustRoot = `-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
+R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
+9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
+fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
+iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
+1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
+MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
+ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
+uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
+Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
+tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
+PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
+hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
+5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
+-----END CERTIFICATE-----
+`
+
+const giag2Intermediate = `-----BEGIN CERTIFICATE-----
+MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG
+EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy
+bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP
+VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv
+h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE
+ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ
+EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC
+DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7
+qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD
+VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g
+K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI
+KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n
+ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB
+BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY
+/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/
+zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza
+HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto
+WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6
+yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx
+-----END CERTIFICATE-----
+`
+
+const googleLeaf = `-----BEGIN CERTIFICATE-----
+MIIEdjCCA16gAwIBAgIIcR5k4dkoe04wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
+BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
+cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMzEyMDkzODMwWhcNMTQwNjEwMDAwMDAw
+WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
+TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3
+Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4zYCe
+m0oUBhwE0EwBr65eBOcgcQO2PaSIAB2dEP/c1EMX2tOy0ov8rk83ePhJ+MWdT1z6
+jge9X4zQQI8ZyA9qIiwrKBZOi8DNUvrqNZC7fJAVRrb9aX/99uYOJCypIbpmWG1q
+fhbHjJewhwf8xYPj71eU4rLG80a+DapWmphtfq3h52lDQIBzLVf1yYbyrTaELaz4
+NXF7HXb5YkId/gxIsSzM0aFUVu2o8sJcLYAsJqwfFKBKOMxUcn545nlspf0mTcWZ
+0APlbwsKznNs4/xCDwIxxWjjqgHrYAFl6y07i1gzbAOqdNEyR24p+3JWI8WZBlBI
+dk2KGj0W1fIfsvyxAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
+KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE
+XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0
+MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G
+A1UdDgQWBBTXD5Bx6iqT+dmEhbFL4OUoHyZn8zAMBgNVHRMBAf8EAjAAMB8GA1Ud
+IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYKKwYBBAHW
+eQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB
+RzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCR3RJtHzgDh33b/MI1ugiki+nl8Ikj
+5larbJRE/rcA5oite+QJyAr6SU1gJJ/rRrK3ItVEHr9L621BCM7GSdoNMjB9MMcf
+tJAW0kYGJ+wqKm53wG/JaOADTnnq2Mt/j6F2uvjgN/ouns1nRHufIvd370N0LeH+
+orKqTuAPzXK7imQk6+OycYABbqCtC/9qmwRd8wwn7sF97DtYfK8WuNHtFalCAwyi
+8LxJJYJCLWoMhZ+V8GZm+FOex5qkQAjnZrtNlbQJ8ro4r+rpKXtmMFFhfa+7L+PA
+Kom08eUK8skxAzfDDijZPh10VtJ66uBoiDPdT+uCBehcBIcmSTrKjFGX
+-----END CERTIFICATE-----
+`
+
+// googleLeafWithInvalidHash is the same as googleLeaf, but the signature
+// algorithm in the certificate contains a nonsense OID.
+const googleLeafWithInvalidHash = `-----BEGIN CERTIFICATE-----
+MIIEdjCCA16gAwIBAgIIcR5k4dkoe04wDQYJKoZIhvcNAWAFBQAwSTELMAkGA1UE
+BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
+cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMzEyMDkzODMwWhcNMTQwNjEwMDAwMDAw
+WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
+TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3
+Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4zYCe
+m0oUBhwE0EwBr65eBOcgcQO2PaSIAB2dEP/c1EMX2tOy0ov8rk83ePhJ+MWdT1z6
+jge9X4zQQI8ZyA9qIiwrKBZOi8DNUvrqNZC7fJAVRrb9aX/99uYOJCypIbpmWG1q
+fhbHjJewhwf8xYPj71eU4rLG80a+DapWmphtfq3h52lDQIBzLVf1yYbyrTaELaz4
+NXF7HXb5YkId/gxIsSzM0aFUVu2o8sJcLYAsJqwfFKBKOMxUcn545nlspf0mTcWZ
+0APlbwsKznNs4/xCDwIxxWjjqgHrYAFl6y07i1gzbAOqdNEyR24p+3JWI8WZBlBI
+dk2KGj0W1fIfsvyxAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
+KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE
+XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0
+MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G
+A1UdDgQWBBTXD5Bx6iqT+dmEhbFL4OUoHyZn8zAMBgNVHRMBAf8EAjAAMB8GA1Ud
+IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYKKwYBBAHW
+eQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB
+RzIuY3JsMA0GCSqGSIb3DQFgBQUAA4IBAQCR3RJtHzgDh33b/MI1ugiki+nl8Ikj
+5larbJRE/rcA5oite+QJyAr6SU1gJJ/rRrK3ItVEHr9L621BCM7GSdoNMjB9MMcf
+tJAW0kYGJ+wqKm53wG/JaOADTnnq2Mt/j6F2uvjgN/ouns1nRHufIvd370N0LeH+
+orKqTuAPzXK7imQk6+OycYABbqCtC/9qmwRd8wwn7sF97DtYfK8WuNHtFalCAwyi
+8LxJJYJCLWoMhZ+V8GZm+FOex5qkQAjnZrtNlbQJ8ro4r+rpKXtmMFFhfa+7L+PA
+Kom08eUK8skxAzfDDijZPh10VtJ66uBoiDPdT+uCBehcBIcmSTrKjFGX
+-----END CERTIFICATE-----
+`
+
+const dnssecExpLeaf = `-----BEGIN CERTIFICATE-----
+MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
+TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
+YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
+MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTAwNzA0MTQ1MjQ1
+WhcNMTEwNzA1MTA1NzA0WjCBwTEgMB4GA1UEDRMXMjIxMTM3LWxpOWE5dHhJRzZM
+NnNyVFMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVQZXJzb25hIE5vdCBWYWxpZGF0
+ZWQxKTAnBgNVBAsTIFN0YXJ0Q29tIEZyZWUgQ2VydGlmaWNhdGUgTWVtYmVyMRsw
+GQYDVQQDExJ3d3cuZG5zc2VjLWV4cC5vcmcxKDAmBgkqhkiG9w0BCQEWGWhvc3Rt
+YXN0ZXJAZG5zc2VjLWV4cC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDEdF/22vaxrPbqpgVYMWi+alfpzBctpbfLBdPGuqOazJdCT0NbWcK8/+B4
+X6OlSOURNIlwLzhkmwVsWdVv6dVSaN7d4yI/fJkvgfDB9+au+iBJb6Pcz8ULBfe6
+D8HVvqKdORp6INzHz71z0sghxrQ0EAEkoWAZLh+kcn2ZHdcmZaBNUfjmGbyU6PRt
+RjdqoP+owIaC1aktBN7zl4uO7cRjlYFdusINrh2kPP02KAx2W84xjxX1uyj6oS6e
+7eBfvcwe8czW/N1rbE0CoR7h9+HnIrjnVG9RhBiZEiw3mUmF++Up26+4KTdRKbu3
++BL4yMpfd66z0+zzqu+HkvyLpFn5AgMBAAGjggL/MIIC+zAJBgNVHRMEAjAAMAsG
+A1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUy04I5guM
+drzfh2JQaXhgV86+4jUwHwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xkLu8OLEUw
+LQYDVR0RBCYwJIISd3d3LmRuc3NlYy1leHAub3Jngg5kbnNzZWMtZXhwLm9yZzCC
+AUIGA1UdIASCATkwggE1MIIBMQYLKwYBBAGBtTcBAgIwggEgMC4GCCsGAQUFBwIB
+FiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMDQGCCsGAQUFBwIB
+FihodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9pbnRlcm1lZGlhdGUucGRmMIG3Bggr
+BgEFBQcCAjCBqjAUFg1TdGFydENvbSBMdGQuMAMCAQEagZFMaW1pdGVkIExpYWJp
+bGl0eSwgc2VlIHNlY3Rpb24gKkxlZ2FsIExpbWl0YXRpb25zKiBvZiB0aGUgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUG9saWN5IGF2YWlsYWJsZSBh
+dCBodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMGEGA1UdHwRaMFgw
+KqAooCaGJGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDAqoCig
+JoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1jcmwuY3JsMIGOBggrBgEF
+BQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFydHNzbC5jb20v
+c3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKGNmh0dHA6Ly93d3cuc3Rh
+cnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVyLmNhLmNydDAjBgNVHRIE
+HDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQEFBQADggEB
+ACXj6SB59KRJPenn6gUdGEqcta97U769SATyiQ87i9er64qLwvIGLMa3o2Rcgl2Y
+kghUeyLdN/EXyFBYA8L8uvZREPoc7EZukpT/ZDLXy9i2S0jkOxvF2fD/XLbcjGjM
+iEYG1/6ASw0ri9C0k4oDDoJLCoeH9++yqF7SFCCMcDkJqiAGXNb4euDpa8vCCtEQ
+CSS+ObZbfkreRt3cNCf5LfCXe9OsTnCfc8Cuq81c0oLaG+SmaLUQNBuToq8e9/Zm
++b+/a3RVjxmkV5OCcGVBxsXNDn54Q6wsdw0TBMcjwoEndzpLS7yWgFbbkq5ZiGpw
+Qibb2+CfKuQ+WFV1GkVQmVA=
+-----END CERTIFICATE-----`
+
+const startComIntermediate = `-----BEGIN CERTIFICATE-----
+MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB
+jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT
+IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0
+YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE
+gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA
+pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv
+kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/
+ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5
+xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID
+AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov
+L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0
+YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3
+dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0
+c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu
+BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0
+BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl
+LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp
+tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen
+xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw
+xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X
+t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI
+RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi
+YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L
+WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN
+SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD
+wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L
+p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un
+0q6Dp6jOW6c=
+-----END CERTIFICATE-----`
+
+const startComRoot = `-----BEGIN CERTIFICATE-----
+MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
+ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
+LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
+BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
+Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
+dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
+cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
+YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
+dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
+bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
+YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
+TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
+9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
+jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
+FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
+ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
+ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
+EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
+L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
+yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
+O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
+um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
+NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
+-----END CERTIFICATE-----`
+
+const startComRootSHA256 = `-----BEGIN CERTIFICATE-----
+MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC
+ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w
+ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk
+aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0
+YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg
+c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93
+d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG
+CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF
+wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS
+Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst
+0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc
+pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl
+CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF
+P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK
+1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm
+KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
+JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ
+8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm
+fyWl8kgAwKQB2j8=
+-----END CERTIFICATE-----`
+
+const smimeLeaf = `-----BEGIN CERTIFICATE-----
+MIIFBjCCA+6gAwIBAgISESFvrjT8XcJTEe6rBlPptILlMA0GCSqGSIb3DQEBBQUA
+MFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSowKAYD
+VQQDEyFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiAyIENBIC0gRzIwHhcNMTIwMTIz
+MTYzNjU5WhcNMTUwMTIzMTYzNjU5WjCBlDELMAkGA1UEBhMCVVMxFjAUBgNVBAgT
+DU5ldyBIYW1zcGhpcmUxEzARBgNVBAcTClBvcnRzbW91dGgxGTAXBgNVBAoTEEds
+b2JhbFNpZ24sIEluYy4xEzARBgNVBAMTClJ5YW4gSHVyc3QxKDAmBgkqhkiG9w0B
+CQEWGXJ5YW4uaHVyc3RAZ2xvYmFsc2lnbi5jb20wggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQC4ASSTvavmsFQAob60ukSSwOAL9nT/s99ltNUCAf5fPH5j
+NceMKxaQse2miOmRRIXaykcq1p/TbI70Ztce38r2mbOwqDHHPVi13GxJEyUXWgaR
+BteDMu5OGyWNG1kchVsGWpbstT0Z4v0md5m1BYFnxB20ebJyOR2lXDxsFK28nnKV
++5eMj76U8BpPQ4SCH7yTMG6y0XXsB3cCrBKr2o3TOYgEKv+oNnbaoMt3UxMt9nSf
+9jyIshjqfnT5Aew3CUNMatO55g5FXXdIukAweg1YSb1ls05qW3sW00T3d7dQs9/7
+NuxCg/A2elmVJSoy8+MLR8JSFEf/aMgjO/TyLg/jAgMBAAGjggGPMIIBizAOBgNV
+HQ8BAf8EBAMCBaAwTQYDVR0gBEYwRDBCBgorBgEEAaAyASgKMDQwMgYIKwYBBQUH
+AgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMCQGA1Ud
+EQQdMBuBGXJ5YW4uaHVyc3RAZ2xvYmFsc2lnbi5jb20wCQYDVR0TBAIwADAdBgNV
+HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwQwYDVR0fBDwwOjA4oDagNIYyaHR0
+cDovL2NybC5nbG9iYWxzaWduLmNvbS9ncy9nc3BlcnNvbmFsc2lnbjJnMi5jcmww
+VQYIKwYBBQUHAQEESTBHMEUGCCsGAQUFBzAChjlodHRwOi8vc2VjdXJlLmdsb2Jh
+bHNpZ24uY29tL2NhY2VydC9nc3BlcnNvbmFsc2lnbjJnMi5jcnQwHQYDVR0OBBYE
+FFWiECe0/L72eVYqcWYnLV6SSjzhMB8GA1UdIwQYMBaAFD8V0m18L+cxnkMKBqiU
+bCw7xe5lMA0GCSqGSIb3DQEBBQUAA4IBAQAhQi6hLPeudmf3IBF4IDzCvRI0FaYd
+BKfprSk/H0PDea4vpsLbWpA0t0SaijiJYtxKjlM4bPd+2chb7ejatDdyrZIzmDVy
+q4c30/xMninGKokpYA11/Ve+i2dvjulu65qasrtQRGybAuuZ67lrp/K3OMFgjV5N
+C3AHYLzvNU4Dwc4QQ1BaMOg6KzYSrKbABRZajfrpC9uiePsv7mDIXLx/toBPxWNl
+a5vJm5DrZdn7uHdvBCE6kMykbOLN5pmEK0UIlwKh6Qi5XD0pzlVkEZliFkBMJgub
+d/eF7xeg7TKPWC5xyOFp9SdMolJM7LTC3wnSO3frBAev+q/nGs9Xxyvs
+-----END CERTIFICATE-----`
+
+const smimeIntermediate = `-----BEGIN CERTIFICATE-----
+MIIEFjCCAv6gAwIBAgILBAAAAAABL07hL1IwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0MTMxMDAw
+MDBaFw0xOTA0MTMxMDAwMDBaMFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMSowKAYDVQQDEyFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiAy
+IENBIC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBa0H5Nez4
+En3dIlFpX7e5E0YndxQ74xOBbz7kdBd+DLX0LOQMjVPU3DAgKL9ujhH+ZhHkURbH
+3X/94TQSUL/z2JjsaQvS0NqyZXHhM5eeuquzOJRzEQ8+odETzHg2G0Erv7yjSeww
+gkwDWDJnYUDlOjYTDUEG6+i+8Mn425reo4I0E277wD542kmVWeW7+oHv5dZo9e1Q
+yWwiKTEP6BEQVVSBgThXMG4traSSDRUt3T1eQTZx5EObpiBEBO4OTqiBTJfg4vEI
+YgkXzKLpnfszTB6YMDpR9/QS6p3ANB3kfAb+t6udSO3WCst0DGrwHDLBFGDR4UeY
+T5KGGnI7cWL7AgMBAAGjgeUwgeIwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI
+MAYBAf8CAQAwHQYDVR0OBBYEFD8V0m18L+cxnkMKBqiUbCw7xe5lMEcGA1UdIARA
+MD4wPAYEVR0gADA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWdu
+LmNvbS9yZXBvc2l0b3J5LzAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmds
+b2JhbHNpZ24ubmV0L3Jvb3QuY3JsMB8GA1UdIwQYMBaAFGB7ZhpFDZfKiVAvfQTN
+NKj//P1LMA0GCSqGSIb3DQEBBQUAA4IBAQBDc3nMpMxJMQMcYUCB3+C73UpvwDE8
+eCOr7t2F/uaQKKcyqqstqLZc6vPwI/rcE9oDHugY5QEjQzIBIEaTnN6P0vege2IX
+eCOr7t2F/uaQKKcyqqstqLZc6vPwI/rcE9oDHugY5QEjQzIBIEaTnN6P0vege2IX
+YEvTWbWwGdPytDFPYIl3/6OqNSXSnZ7DxPcdLJq2uyiga8PB/TTIIHYkdM2+1DE0
+7y3rH/7TjwDVD7SLu5/SdOfKskuMPTjOEvz3K161mymW06klVhubCIWOro/Gx1Q2
+2FQOZ7/2k4uYoOdBTSlb8kTAuzZNgIE0rB2BIYCTz/P6zZIKW0ogbRSH
+-----END CERTIFICATE-----`
+
+var megaLeaf = `-----BEGIN CERTIFICATE-----
+MIIFOjCCBCKgAwIBAgIQWYE8Dup170kZ+k11Lg51OjANBgkqhkiG9w0BAQUFADBy
+MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
+VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEYMBYGA1UE
+AxMPRXNzZW50aWFsU1NMIENBMB4XDTEyMTIxNDAwMDAwMFoXDTE0MTIxNDIzNTk1
+OVowfzEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMS4wLAYDVQQL
+EyVIb3N0ZWQgYnkgSW5zdHJhIENvcnBvcmF0aW9uIFB0eS4gTFREMRUwEwYDVQQL
+EwxFc3NlbnRpYWxTU0wxEzARBgNVBAMTCm1lZ2EuY28ubnowggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDcxMCClae8BQIaJHBUIVttlLvhbK4XhXPk3RQ3
+G5XA6tLZMBQ33l3F9knYJ0YErXtr8IdfYoulRQFmKFMJl9GtWyg4cGQi2Rcr5VN5
+S5dA1vu4oyJBxE9fPELcK6Yz1vqaf+n6za+mYTiQYKggVdS8/s8hmNuXP9Zk1pIn
++q0pGsf8NAcSHMJgLqPQrTDw+zae4V03DvcYfNKjuno88d2226ld7MAmQZ7uRNsI
+/CnkdelVs+akZsXf0szefSqMJlf08SY32t2jj4Ra7RApVYxOftD9nij/aLfuqOU6
+ow6IgIcIG2ZvXLZwK87c5fxL7UAsTTV+M1sVv8jA33V2oKLhAgMBAAGjggG9MIIB
+uTAfBgNVHSMEGDAWgBTay+qtWwhdzP/8JlTOSeVVxjj0+DAdBgNVHQ4EFgQUmP9l
+6zhyrZ06Qj4zogt+6LKFk4AwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAw
+NAYDVR0lBC0wKwYIKwYBBQUHAwEGCCsGAQUFBwMCBgorBgEEAYI3CgMDBglghkgB
+hvhCBAEwTwYDVR0gBEgwRjA6BgsrBgEEAbIxAQICBzArMCkGCCsGAQUFBwIBFh1o
+dHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzAIBgZngQwBAgEwOwYDVR0fBDQw
+MjAwoC6gLIYqaHR0cDovL2NybC5jb21vZG9jYS5jb20vRXNzZW50aWFsU1NMQ0Eu
+Y3JsMG4GCCsGAQUFBwEBBGIwYDA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21v
+ZG9jYS5jb20vRXNzZW50aWFsU1NMQ0FfMi5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6
+Ly9vY3NwLmNvbW9kb2NhLmNvbTAlBgNVHREEHjAcggptZWdhLmNvLm56gg53d3cu
+bWVnYS5jby5uejANBgkqhkiG9w0BAQUFAAOCAQEAcYhrsPSvDuwihMOh0ZmRpbOE
+Gw6LqKgLNTmaYUPQhzi2cyIjhUhNvugXQQlP5f0lp5j8cixmArafg1dTn4kQGgD3
+ivtuhBTgKO1VYB/VRoAt6Lmswg3YqyiS7JiLDZxjoV7KoS5xdiaINfHDUaBBY4ZH
+j2BUlPniNBjCqXe/HndUTVUewlxbVps9FyCmH+C4o9DWzdGBzDpCkcmo5nM+cp7q
+ZhTIFTvZfo3zGuBoyu8BzuopCJcFRm3cRiXkpI7iOMUIixO1szkJS6WpL1sKdT73
+UXp08U0LBqoqG130FbzEJBBV3ixbvY6BWMHoCWuaoF12KJnC5kHt2RoWAAgMXA==
+-----END CERTIFICATE-----`
+
+var comodoIntermediate1 = `-----BEGIN CERTIFICATE-----
+MIIFAzCCA+ugAwIBAgIQGLLLuqME8aAPwfLzJkYqSjANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0xOTEyMzEyMzU5NTlaMHIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVh
+dGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9E
+TyBDQSBMaW1pdGVkMRgwFgYDVQQDEw9Fc3NlbnRpYWxTU0wgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt8AiwcsargxIxF3CJhakgEtSYau2A1NHf
+5I5ZLdOWIY120j8YC0YZYwvHIPPlC92AGvFaoL0dds23Izp0XmEbdaqb1IX04XiR
+0y3hr/yYLgbSeT1awB8hLRyuIVPGOqchfr7tZ291HRqfalsGs2rjsQuqag7nbWzD
+ypWMN84hHzWQfdvaGlyoiBSyD8gSIF/F03/o4Tjg27z5H6Gq1huQByH6RSRQXScq
+oChBRVt9vKCiL6qbfltTxfEFFld+Edc7tNkBdtzffRDPUanlOPJ7FAB1WfnwWdsX
+Pvev5gItpHnBXaIcw5rIp6gLSApqLn8tl2X2xQScRMiZln5+pN0vAgMBAAGjggGD
+MIIBfzAfBgNVHSMEGDAWgBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAdBgNVHQ4EFgQU
+2svqrVsIXcz//CZUzknlVcY49PgwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI
+MAYBAf8CAQAwIAYDVR0lBBkwFwYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMD4GA1Ud
+IAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21v
+ZG8uY29tL0NQUzBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9kb2Nh
+LmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBsBggrBgEFBQcB
+AQRgMF4wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NvbW9k
+b1VUTlNHQ0NBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2Eu
+Y29tMA0GCSqGSIb3DQEBBQUAA4IBAQAtlzR6QDLqcJcvgTtLeRJ3rvuq1xqo2l/z
+odueTZbLN3qo6u6bldudu+Ennv1F7Q5Slqz0J790qpL0pcRDAB8OtXj5isWMcL2a
+ejGjKdBZa0wztSz4iw+SY1dWrCRnilsvKcKxudokxeRiDn55w/65g+onO7wdQ7Vu
+F6r7yJiIatnyfKH2cboZT7g440LX8NqxwCPf3dfxp+0Jj1agq8MLy6SSgIGSH6lv
++Wwz3D5XxqfyH8wqfOQsTEZf6/Nh9yvENZ+NWPU6g0QO2JOsTGvMd/QDzczc4BxL
+XSXaPV7Od4rhPsbXlM1wSTz/Dr0ISKvlUhQVnQ6cGodWaK2cCQBk
+-----END CERTIFICATE-----`
+
+var comodoRoot = `-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----`
+
+var nameConstraintsLeaf = `-----BEGIN CERTIFICATE-----
+MIIHMTCCBRmgAwIBAgIIIZaV/3ezOJkwDQYJKoZIhvcNAQEFBQAwgcsxCzAJBgNV
+BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEj
+MCEGA1UECxMaR2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1Zp
+cmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0
+eTExMC8GA1UEAxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZl
+ciBDQTAeFw0xMzA5MTkxNDM2NTVaFw0xNTA5MTkxNDM2NTVaMIHNMQswCQYDVQQG
+EwJVUzERMA8GA1UECAwIVmlyZ2luaWExEzARBgNVBAcMCkJsYWNrc2J1cmcxPDA6
+BgNVBAoMM1ZpcmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUg
+VW5pdmVyc2l0eTE7MDkGA1UECwwyVGVjaG5vbG9neS1lbmhhbmNlZCBMZWFybmlu
+ZyBhbmQgT25saW5lIFN0cmF0ZWdpZXMxGzAZBgNVBAMMEnNlY3VyZS5pZGRsLnZ0
+LmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkOyPpsOK/6IuPG
+WnIBlVwlHzeYf+cUlggqkLq0b0+vZbiTXgio9/VCuNQ8opSoss7J7o3ygV9to+9Y
+YwJKVC5WDT/y5JWpQey0CWILymViJnpNSwnxBc8A+Q8w5NUGDd/UhtPx/U8/hqbd
+WPDYj2hbOqyq8UlRhfS5pwtnv6BbCTaY11I6FhCLK7zttISyTuWCf9p9o/ggiipP
+ii/5oh4dkl+r5SfuSp5GPNHlYO8lWqys5NAPoDD4fc/kuflcK7Exx7XJ+Oqu0W0/
+psjEY/tES1ZgDWU/ParcxxFpFmKHbD5DXsfPOObzkVWXIY6tGMutSlE1Froy/Nn0
+OZsAOrcCAwEAAaOCAhMwggIPMIG4BggrBgEFBQcBAQSBqzCBqDBYBggrBgEFBQcw
+AoZMaHR0cDovL3d3dy5wa2kudnQuZWR1L2dsb2JhbHF1YWxpZmllZHNlcnZlci9j
+YWNlcnQvZ2xvYmFscXVhbGlmaWVkc2VydmVyLmNydDBMBggrBgEFBQcwAYZAaHR0
+cDovL3Z0Y2EtcC5lcHJvdi5zZXRpLnZ0LmVkdTo4MDgwL2VqYmNhL3B1YmxpY3dl
+Yi9zdGF0dXMvb2NzcDAdBgNVHQ4EFgQUp7xbO6iHkvtZbPE4jmndmnAbSEcwDAYD
+VR0TAQH/BAIwADAfBgNVHSMEGDAWgBS8YmAn1eM1SBfpS6tFatDIqHdxjDBqBgNV
+HSAEYzBhMA4GDCsGAQQBtGgFAgICATAOBgwrBgEEAbRoBQICAQEwPwYMKwYBBAG0
+aAUCAgMBMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9i
+YWwvY3BzLzBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vd3d3LnBraS52dC5lZHUv
+Z2xvYmFscXVhbGlmaWVkc2VydmVyL2NybC9jYWNybC5jcmwwDgYDVR0PAQH/BAQD
+AgTwMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHREEFjAUghJz
+ZWN1cmUuaWRkbC52dC5lZHUwDQYJKoZIhvcNAQEFBQADggIBAEgoYo4aUtatY3gI
+OyyKp7QlIOaLbTJZywESHqy+L5EGDdJW2DJV+mcE0LDGvqa2/1Lo+AR1ntsZwfOi
+Y718JwgVVaX/RCd5+QKP25c5/x72xI8hb/L1bgS0ED9b0YAhd7Qm1K1ot82+6mqX
+DW6WiGeDr8Z07MQ3143qQe2rBlq+QI69DYzm2GOqAIAnUIWv7tCyLUm31b4DwmrJ
+TeudVreTKUbBNB1TWRFHEPkWhjjXKZnNGRO11wHXcyBu6YekIvVZ+vmx8ePee4jJ
+3GFOi7lMuWOeq57jTVL7KOKaKLVXBb6gqo5aq+Wwt8RUD5MakrCAEeQZj7DKaFmZ
+oQCO0Pxrsl3InCGvxnGzT+bFVO9nJ/BAMj7hknFdm9Jr6Bg5q33Z+gnf909AD9QF
+ESqUSykaHu2LVdJx2MaCH1CyKnRgMw5tEwE15EXpUjCm24m8FMOYC+rNtf18pgrz
+5D8Jhh+oxK9PjcBYqXNtnioIxiMCYcV0q5d4w4BYFEh71tk7/bYB0R55CsBUVPmp
+timWNOdRd57Tfpk3USaVsumWZAf9MP3wPiC7gb4d5tYEEAG5BuDT8ruFw838wU8G
+1VvAVutSiYBg7k3NYO7AUqZ+Ax4klQX3aM9lgonmJ78Qt94UPtbptrfZ4/lSqEf8
+GBUwDrQNTb+gsXsDkjd5lcYxNx6l
+-----END CERTIFICATE-----`
+
+var nameConstraintsIntermediate1 = `-----BEGIN CERTIFICATE-----
+MIINLjCCDBagAwIBAgIRIqpyf/YoGgvHc8HiDAxAI8owDQYJKoZIhvcNAQEFBQAw
+XDELMAkGA1UEBhMCQkUxFTATBgNVBAsTDFRydXN0ZWQgUm9vdDEZMBcGA1UEChMQ
+R2xvYmFsU2lnbiBudi1zYTEbMBkGA1UEAxMSVHJ1c3RlZCBSb290IENBIEcyMB4X
+DTEyMTIxMzAwMDAwMFoXDTE3MTIxMzAwMDAwMFowgcsxCzAJBgNVBAYTAlVTMREw
+DwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEjMCEGA1UECxMa
+R2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1ZpcmdpbmlhIFBv
+bHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0eTExMC8GA1UE
+AxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALgIZhEaptBWADBqdJ45ueFGzMXa
+GHnzNxoxR1fQIaaRQNdCg4cw3A4dWKMeEgYLtsp65ai3Xfw62Qaus0+KJ3RhgV+r
+ihqK81NUzkls78fJlADVDI4fCTlothsrE1CTOMiy97jKHai5mVTiWxmcxpmjv7fm
+5Nhc+uHgh2hIz6npryq495mD51ZrUTIaqAQN6Pw/VHfAmR524vgriTOjtp1t4lA9
+pXGWjF/vkhAKFFheOQSQ00rngo2wHgCqMla64UTN0oz70AsCYNZ3jDLx0kOP0YmM
+R3Ih91VA63kLqPXA0R6yxmmhhxLZ5bcyAy1SLjr1N302MIxLM/pSy6aquEnbELhz
+qyp9yGgRyGJay96QH7c4RJY6gtcoPDbldDcHI9nXngdAL4DrZkJ9OkDkJLyqG66W
+ZTF5q4EIs6yMdrywz0x7QP+OXPJrjYpbeFs6tGZCFnWPFfmHCRJF8/unofYrheq+
+9J7Jx3U55S/k57NXbAM1RAJOuMTlfn9Etf9Dpoac9poI4Liav6rBoUQk3N3JWqnV
+HNx/NdCyJ1/6UbKMJUZsStAVglsi6lVPo289HHOE4f7iwl3SyekizVOp01wUin3y
+cnbZB/rXmZbwapSxTTSBf0EIOr9i4EGfnnhCAVA9U5uLrI5OEB69IY8PNX0071s3
+Z2a2fio5c8m3JkdrAgMBAAGjggh5MIIIdTAOBgNVHQ8BAf8EBAMCAQYwTAYDVR0g
+BEUwQzBBBgkrBgEEAaAyATwwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv
+YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wEgYDVR0TAQH/BAgwBgEB/wIBADCCBtAG
+A1UdHgSCBscwggbDoIIGvzASghAzZGJsYWNrc2J1cmcub3JnMBiCFmFjY2VsZXJh
+dGV2aXJnaW5pYS5jb20wGIIWYWNjZWxlcmF0ZXZpcmdpbmlhLm9yZzALgglhY3Zj
+cC5vcmcwCYIHYmV2Lm5ldDAJggdiZXYub3JnMAuCCWNsaWdzLm9yZzAMggpjbWl3
+ZWIub3JnMBeCFWVhc3Rlcm5icm9va3Ryb3V0Lm5ldDAXghVlYXN0ZXJuYnJvb2t0
+cm91dC5vcmcwEYIPZWNvcnJpZG9ycy5pbmZvMBOCEWVkZ2FycmVzZWFyY2gub3Jn
+MBKCEGdldC1lZHVjYXRlZC5jb20wE4IRZ2V0LWVkdWNhdGVkLmluZm8wEYIPZ2V0
+ZWR1Y2F0ZWQubmV0MBKCEGdldC1lZHVjYXRlZC5uZXQwEYIPZ2V0ZWR1Y2F0ZWQu
+b3JnMBKCEGdldC1lZHVjYXRlZC5vcmcwD4INaG9raWVjbHViLmNvbTAQgg5ob2tp
+ZXBob3RvLmNvbTAPgg1ob2tpZXNob3AuY29tMBGCD2hva2llc3BvcnRzLmNvbTAS
+ghBob2tpZXRpY2tldHMuY29tMBKCEGhvdGVscm9hbm9rZS5jb20wE4IRaHVtYW53
+aWxkbGlmZS5vcmcwF4IVaW5uYXR2aXJnaW5pYXRlY2guY29tMA+CDWlzY2hwMjAx
+MS5vcmcwD4INbGFuZHJlaGFiLm9yZzAggh5uYXRpb25hbHRpcmVyZXNlYXJjaGNl
+bnRlci5jb20wFYITbmV0d29ya3ZpcmdpbmlhLm5ldDAMggpwZHJjdnQuY29tMBiC
+FnBldGVkeWVyaXZlcmNvdXJzZS5jb20wDYILcmFkaW9pcS5vcmcwFYITcml2ZXJj
+b3Vyc2Vnb2xmLmNvbTALgglzZGltaS5vcmcwEIIOc292YW1vdGlvbi5jb20wHoIc
+c3VzdGFpbmFibGUtYmlvbWF0ZXJpYWxzLmNvbTAeghxzdXN0YWluYWJsZS1iaW9t
+YXRlcmlhbHMub3JnMBWCE3RoaXNpc3RoZWZ1dHVyZS5jb20wGIIWdGhpcy1pcy10
+aGUtZnV0dXJlLmNvbTAVghN0aGlzaXN0aGVmdXR1cmUubmV0MBiCFnRoaXMtaXMt
+dGhlLWZ1dHVyZS5uZXQwCoIIdmFkcy5vcmcwDIIKdmFsZWFmLm9yZzANggt2YXRl
+Y2guaW5mbzANggt2YXRlY2gubW9iaTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5n
+LmNvbTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5nLm5ldDAcghp2YXRlY2hsaWZl
+bG9uZ2xlYXJuaW5nLm9yZzAKggh2Y29tLmVkdTASghB2aXJnaW5pYXZpZXcubmV0
+MDSCMnZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVuaXZlcnNp
+dHkuY29tMDWCM3ZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVu
+aXZlcnNpdHkuaW5mbzA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0dXRlYW5k
+c3RhdGV1bml2ZXJzaXR5Lm5ldDA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0
+dXRlYW5kc3RhdGV1bml2ZXJzaXR5Lm9yZzAZghd2aXJnaW5pYXB1YmxpY3JhZGlv
+Lm9yZzASghB2aXJnaW5pYXRlY2guZWR1MBOCEXZpcmdpbmlhdGVjaC5tb2JpMByC
+GnZpcmdpbmlhdGVjaGZvdW5kYXRpb24ub3JnMAiCBnZ0LmVkdTALggl2dGFyYy5v
+cmcwDIIKdnQtYXJjLm9yZzALggl2dGNyYy5jb20wCoIIdnRpcC5vcmcwDIIKdnRs
+ZWFuLm9yZzAWghR2dGtub3dsZWRnZXdvcmtzLmNvbTAYghZ2dGxpZmVsb25nbGVh
+cm5pbmcuY29tMBiCFnZ0bGlmZWxvbmdsZWFybmluZy5uZXQwGIIWdnRsaWZlbG9u
+Z2xlYXJuaW5nLm9yZzATghF2dHNwb3J0c21lZGlhLmNvbTALggl2dHdlaS5jb20w
+D4INd2l3YXR3ZXJjLmNvbTAKggh3dnRmLm9yZzAIgQZ2dC5lZHUwd6R1MHMxCzAJ
+BgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVy
+ZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFuZCBT
+dGF0ZSBVbml2ZXJzaXR5MCcGA1UdJQQgMB4GCCsGAQUFBwMCBggrBgEFBQcDAQYI
+KwYBBQUHAwkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2NybC5nbG9iYWxzaWdu
+LmNvbS9ncy90cnVzdHJvb3RnMi5jcmwwgYQGCCsGAQUFBwEBBHgwdjAzBggrBgEF
+BQcwAYYnaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3RydXN0cm9vdGcyMD8G
+CCsGAQUFBzAChjNodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC90
+cnVzdHJvb3RnMi5jcnQwHQYDVR0OBBYEFLxiYCfV4zVIF+lLq0Vq0Miod3GMMB8G
+A1UdIwQYMBaAFBT25YsxtkWASkxt/MKHico2w5BiMA0GCSqGSIb3DQEBBQUAA4IB
+AQAyJm/lOB2Er4tHXhc/+fSufSzgjohJgYfMkvG4LknkvnZ1BjliefR8tTXX49d2
+SCDFWfGjqyJZwavavkl/4p3oXPG/nAMDMvxh4YAT+CfEK9HH+6ICV087kD4BLegi
++aFJMj8MMdReWCzn5sLnSR1rdse2mo2arX3Uod14SW+PGrbUmTuWNyvRbz3fVmxp
+UdbGmj3laknO9YPsBGgHfv73pVVsTJkW4ZfY/7KdD/yaVv6ophpOB3coXfjl2+kd
+Z4ypn2zK+cx9IL/LSewqd/7W9cD55PCUy4X9OTbEmAccwiz3LB66mQoUGfdHdkoB
+jUY+v9vLQXmaVwI0AYL7g9LN
+-----END CERTIFICATE-----`
+
+var nameConstraintsIntermediate2 = `-----BEGIN CERTIFICATE-----
+MIIEXTCCA0WgAwIBAgILBAAAAAABNuk6OrMwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMjA0MjUxMTAw
+MDBaFw0yNzA0MjUxMTAwMDBaMFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVz
+dGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRy
+dXN0ZWQgUm9vdCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKyuvqrtcMr7g7EuNbu4sKwxM127UsCmx1RxbxxgcArGS7rjiefpBH/w4LYrymjf
+vcw1ueyMNoqLo9nJMz/ORXupb35NNfE667prQYHa+tTjl1IiKpB7QUwt3wXPuTMF
+Ja1tXtjKzkqJyuJlNuPKT76HcjgNqgV1s9qG44MD5I2JvI12du8zI1bgdQ+l/KsX
+kTfbGjUvhOLOlVNWVQDpL+YMIrGqgBYxy5TUNgrAcRtwpNdS2KkF5otSmMweVb5k
+hoUVv3u8UxQH/WWbNhHq1RrIlg/0rBUfi/ziShYFSB7U+aLx5DxPphTFBiDquQGp
+tB+FC4JvnukDStFihZCZ1R8CAwEAAaOCASMwggEfMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MEcGA1UdIARAMD4wPAYEVR0gADA0MDIGCCsGAQUFBwIB
+FiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAdBgNVHQ4E
+FgQUFPblizG2RYBKTG38woeJyjbDkGIwMwYDVR0fBCwwKjAooCagJIYiaHR0cDov
+L2NybC5nbG9iYWxzaWduLm5ldC9yb290LmNybDA+BggrBgEFBQcBAQQyMDAwLgYI
+KwYBBQUHMAGGImh0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9yb290cjEwHwYD
+VR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZIhvcNAQEFBQADggEB
+AL7IG0l+k4LkcpI+a/kvZsSRwSM4uA6zGX34e78A2oytr8RG8bJwVb8+AHMUD+Xe
+2kYdh/Uj/waQXfqR0OgxQXL9Ct4ZM+JlR1avsNKXWL5AwYXAXCOB3J5PW2XOck7H
+Zw0vRbGQhjWjQx+B4KOUFg1b3ov/z6Xkr3yaCfRQhXh7KC0Bc0RXPPG5Nv5lCW+z
+tbbg0zMm3kyfQITRusMSg6IBsDJqOnjaiaKQRcXiD0Sk43ZXb2bUKMxC7+Td3QL4
+RyHcWJbQ7YylLTS/x+jxWIcOQ0oO5/54t5PTQ14neYhOz9x4gUk2AYAW6d1vePwb
+hcC8roQwkHT7HvfYBoc74FM=
+-----END CERTIFICATE-----`
+
+var globalSignRoot = `-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----`
+
+var moipLeafCert = `-----BEGIN CERTIFICATE-----
+MIIGQDCCBSigAwIBAgIRAPe/cwh7CUWizo8mYSDavLIwDQYJKoZIhvcNAQELBQAw
+gZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
+BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYD
+VQQDEy9DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl
+ciBDQTAeFw0xMzA4MTUwMDAwMDBaFw0xNDA4MTUyMzU5NTlaMIIBQjEXMBUGA1UE
+BRMOMDg3MTg0MzEwMDAxMDgxEzARBgsrBgEEAYI3PAIBAxMCQlIxGjAYBgsrBgEE
+AYI3PAIBAhMJU2FvIFBhdWxvMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlv
+bjELMAkGA1UEBhMCQlIxETAPBgNVBBETCDAxNDUyMDAwMRIwEAYDVQQIEwlTYW8g
+UGF1bG8xEjAQBgNVBAcTCVNhbyBQYXVsbzEtMCsGA1UECRMkQXZlbmlkYSBCcmln
+YWRlaXJvIEZhcmlhIExpbWEgLCAyOTI3MR0wGwYDVQQKExRNb2lwIFBhZ2FtZW50
+b3MgUy5BLjENMAsGA1UECxMETU9JUDEYMBYGA1UECxMPU1NMIEJsaW5kYWRvIEVW
+MRgwFgYDVQQDEw9hcGkubW9pcC5jb20uYnIwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDN0b9x6TrXXA9hPCF8/NjqGJ++2D4LO4ZiMFTjs0VwpXy2Y1Oe
+s74/HuiLGnAHxTmAtV7IpZMibiOcTxcnDYp9oEWkf+gR+hZvwFZwyOBC7wyb3SR3
+UvV0N1ZbEVRYpN9kuX/3vjDghjDmzzBwu8a/T+y5JTym5uiJlngVAWyh/RjtIvYi
++NVkQMbyVlPGkoCe6c30pH8DKYuUCZU6DHjUsPTX3jAskqbhDSAnclX9iX0p2bmw
+KVBc+5Vh/2geyzDuquF0w+mNIYdU5h7uXvlmJnf3d2Cext5dxdL8/jezD3U0dAqI
+pYSKERbyxSkJWxdvRlhdpM9YXMJcpc88xNp1AgMBAAGjggHcMIIB2DAfBgNVHSME
+GDAWgBQ52v/KKBSKqHQTCLnkDqnS+n6daTAdBgNVHQ4EFgQU/lXuOa7DMExzZjRj
+LQWcMWGZY7swDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQUB
+MCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMFYG
+A1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JT
+QUV4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCBhwYIKwYBBQUH
+AQEEezB5MFEGCCsGAQUFBzAChkVodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01P
+RE9SU0FFeHRlbmRlZFZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5jcnQwJAYIKwYB
+BQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAvBgNVHREEKDAmgg9hcGku
+bW9pcC5jb20uYnKCE3d3dy5hcGkubW9pcC5jb20uYnIwDQYJKoZIhvcNAQELBQAD
+ggEBAFoTmPlaDcf+nudhjXHwud8g7/LRyA8ucb+3/vfmgbn7FUc1eprF5sJS1mA+
+pbiTyXw4IxcJq2KUj0Nw3IPOe9k84mzh+XMmdCKH+QK3NWkE9Udz+VpBOBc0dlqC
+1RH5umStYDmuZg/8/r652eeQ5kUDcJyADfpKWBgDPYaGtwzKVT4h3Aok9SLXRHx6
+z/gOaMjEDMarMCMw4VUIG1pvNraZrG5oTaALPaIXXpd8VqbQYPudYJ6fR5eY3FeW
+H/ofbYFdRcuD26MfBFWE9VGGral9Fgo8sEHffho+UWhgApuQV4/l5fMzxB5YBXyQ
+jhuy8PqqZS9OuLilTeLu4a8z2JI=
+-----END CERTIFICATE-----`
+
+var comodoIntermediateSHA384 = `-----BEGIN CERTIFICATE-----
+MIIGDjCCA/agAwIBAgIQBqdDgNTr/tQ1taP34Wq92DANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTIwMjEy
+MDAwMDAwWhcNMjcwMjExMjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBSU0EgRXh0ZW5kZWQg
+VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAlVbeVLTf1QJJe9FbXKKyHo+cK2JMK40SKPMalaPGEP0p3uGf
+CzhAk9HvbpUQ/OGQF3cs7nU+e2PsYZJuTzurgElr3wDqAwB/L3XVKC/sVmePgIOj
+vdwDmZOLlJFWW6G4ajo/Br0OksxgnP214J9mMF/b5pTwlWqvyIqvgNnmiDkBfBzA
+xSr3e5Wg8narbZtyOTDr0VdVAZ1YEZ18bYSPSeidCfw8/QpKdhQhXBZzQCMZdMO6
+WAqmli7eNuWf0MLw4eDBYuPCGEUZUaoXHugjddTI0JYT/8ck0YwLJ66eetw6YWNg
+iJctXQUL5Tvrrs46R3N2qPos3cCHF+msMJn4HwIDAQABo4IBaTCCAWUwHwYDVR0j
+BBgwFoAUu69+Aj36pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFDna/8ooFIqodBMI
+ueQOqdL6fp1pMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMD4G
+A1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5j
+b21vZG8uY29tL0NQUzBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9k
+b2NhLmNvbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggr
+BgEFBQcBAQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29t
+L0NPTU9ET1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
+cC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAERCnUFRK0iIXZebeV4R
+AUpSGXtBLMeJPNBy3IX6WK/VJeQT+FhlZ58N/1eLqYVeyqZLsKeyLeCMIs37/3mk
+jCuN/gI9JN6pXV/kD0fQ22YlPodHDK4ixVAihNftSlka9pOlk7DgG4HyVsTIEFPk
+1Hax0VtpS3ey4E/EhOfUoFDuPPpE/NBXueEoU/1Tzdy5H3pAvTA/2GzS8+cHnx8i
+teoiccsq8FZ8/qyo0QYPFBRSTP5kKwxpKrgNUG4+BAe/eiCL+O5lCeHHSQgyPQ0o
+fkkdt0rvAucNgBfIXOBhYsvss2B5JdoaZXOcOBCgJjqwyBZ9kzEi7nQLiMBciUEA
+KKlHMd99SUWa9eanRRrSjhMQ34Ovmw2tfn6dNVA0BM7pINae253UqNpktNEvWS5e
+ojZh1CSggjMziqHRbO9haKPl0latxf1eYusVqHQSTC8xjOnB3xBLAer2VBvNfzu9
+XJ/B288ByvK6YBIhMe2pZLiySVgXbVrXzYxtvp5/4gJYp9vDLVj2dAZqmvZh+fYA
+tmnYOosxWd2R5nwnI4fdAw+PKowegwFOAWEMUnNt/AiiuSpm5HZNMaBWm9lTjaK2
+jwLI5jqmBNFI+8NKAnb9L9K8E7bobTQk+p0pisehKxTxlgBzuRPpwLk6R1YCcYAn
+pLwltum95OmYdBbxN4SBB7SC
+-----END CERTIFICATE-----`
+
+const comodoRSAAuthority = `-----BEGIN CERTIFICATE-----
+MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv
+MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
+ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
+eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow
+gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
+BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD
+VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw
+AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6
+2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr
+ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt
+4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq
+m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/
+vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT
+8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE
+IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO
+KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO
+GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/
+s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g
+JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD
+AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9
+MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy
+bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6
+Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ
+zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj
+Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY
+Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5
+B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx
+PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR
+pu/xO28QOG8=
+-----END CERTIFICATE-----`
+
+const addTrustRoot = `-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
+IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
+MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
+bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
+H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
+uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
+mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
+a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
+E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
+WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
+VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
+Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
+cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
+IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
+AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
+YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
+Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
+c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
+mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----`
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/x509.go b/third_party/gofrontend/libgo/go/crypto/x509/x509.go
new file mode 100644
index 0000000..c347fb3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/x509.go
@@ -0,0 +1,1903 @@
+// 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 x509 parses X.509-encoded keys and certificates.
+package x509
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rsa"
+	"crypto/sha1"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"encoding/pem"
+	"errors"
+	"io"
+	"math/big"
+	"net"
+	"strconv"
+	"time"
+)
+
+// pkixPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo
+// in RFC 3280.
+type pkixPublicKey struct {
+	Algo      pkix.AlgorithmIdentifier
+	BitString asn1.BitString
+}
+
+// ParsePKIXPublicKey parses a DER encoded public key. These values are
+// typically found in PEM blocks with "BEGIN PUBLIC KEY".
+func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) {
+	var pki publicKeyInfo
+	if _, err = asn1.Unmarshal(derBytes, &pki); err != nil {
+		return
+	}
+	algo := getPublicKeyAlgorithmFromOID(pki.Algorithm.Algorithm)
+	if algo == UnknownPublicKeyAlgorithm {
+		return nil, errors.New("x509: unknown public key algorithm")
+	}
+	return parsePublicKey(algo, &pki)
+}
+
+func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) {
+	switch pub := pub.(type) {
+	case *rsa.PublicKey:
+		publicKeyBytes, err = asn1.Marshal(rsaPublicKey{
+			N: pub.N,
+			E: pub.E,
+		})
+		publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
+		// This is a NULL parameters value which is technically
+		// superfluous, but most other code includes it and, by
+		// doing this, we match their public key hashes.
+		publicKeyAlgorithm.Parameters = asn1.RawValue{
+			Tag: 5,
+		}
+	case *ecdsa.PublicKey:
+		publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
+		oid, ok := oidFromNamedCurve(pub.Curve)
+		if !ok {
+			return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported elliptic curve")
+		}
+		publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
+		var paramBytes []byte
+		paramBytes, err = asn1.Marshal(oid)
+		if err != nil {
+			return
+		}
+		publicKeyAlgorithm.Parameters.FullBytes = paramBytes
+	default:
+		return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: only RSA and ECDSA public keys supported")
+	}
+
+	return publicKeyBytes, publicKeyAlgorithm, nil
+}
+
+// MarshalPKIXPublicKey serialises a public key to DER-encoded PKIX format.
+func MarshalPKIXPublicKey(pub interface{}) ([]byte, error) {
+	var publicKeyBytes []byte
+	var publicKeyAlgorithm pkix.AlgorithmIdentifier
+	var err error
+
+	if publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub); err != nil {
+		return nil, err
+	}
+
+	pkix := pkixPublicKey{
+		Algo: publicKeyAlgorithm,
+		BitString: asn1.BitString{
+			Bytes:     publicKeyBytes,
+			BitLength: 8 * len(publicKeyBytes),
+		},
+	}
+
+	ret, _ := asn1.Marshal(pkix)
+	return ret, nil
+}
+
+// These structures reflect the ASN.1 structure of X.509 certificates.:
+
+type certificate struct {
+	Raw                asn1.RawContent
+	TBSCertificate     tbsCertificate
+	SignatureAlgorithm pkix.AlgorithmIdentifier
+	SignatureValue     asn1.BitString
+}
+
+type tbsCertificate struct {
+	Raw                asn1.RawContent
+	Version            int `asn1:"optional,explicit,default:1,tag:0"`
+	SerialNumber       *big.Int
+	SignatureAlgorithm pkix.AlgorithmIdentifier
+	Issuer             asn1.RawValue
+	Validity           validity
+	Subject            asn1.RawValue
+	PublicKey          publicKeyInfo
+	UniqueId           asn1.BitString   `asn1:"optional,tag:1"`
+	SubjectUniqueId    asn1.BitString   `asn1:"optional,tag:2"`
+	Extensions         []pkix.Extension `asn1:"optional,explicit,tag:3"`
+}
+
+type dsaAlgorithmParameters struct {
+	P, Q, G *big.Int
+}
+
+type dsaSignature struct {
+	R, S *big.Int
+}
+
+type ecdsaSignature dsaSignature
+
+type validity struct {
+	NotBefore, NotAfter time.Time
+}
+
+type publicKeyInfo struct {
+	Raw       asn1.RawContent
+	Algorithm pkix.AlgorithmIdentifier
+	PublicKey asn1.BitString
+}
+
+// RFC 5280,  4.2.1.1
+type authKeyId struct {
+	Id []byte `asn1:"optional,tag:0"`
+}
+
+type SignatureAlgorithm int
+
+const (
+	UnknownSignatureAlgorithm SignatureAlgorithm = iota
+	MD2WithRSA
+	MD5WithRSA
+	SHA1WithRSA
+	SHA256WithRSA
+	SHA384WithRSA
+	SHA512WithRSA
+	DSAWithSHA1
+	DSAWithSHA256
+	ECDSAWithSHA1
+	ECDSAWithSHA256
+	ECDSAWithSHA384
+	ECDSAWithSHA512
+)
+
+type PublicKeyAlgorithm int
+
+const (
+	UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota
+	RSA
+	DSA
+	ECDSA
+)
+
+// OIDs for signature algorithms
+//
+// pkcs-1 OBJECT IDENTIFIER ::= {
+//    iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
+//
+//
+// RFC 3279 2.2.1 RSA Signature Algorithms
+//
+// md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
+//
+// md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
+//
+// sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
+//
+// dsaWithSha1 OBJECT IDENTIFIER ::= {
+//    iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 }
+//
+// RFC 3279 2.2.3 ECDSA Signature Algorithm
+//
+// ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
+// 	  iso(1) member-body(2) us(840) ansi-x962(10045)
+//    signatures(4) ecdsa-with-SHA1(1)}
+//
+//
+// RFC 4055 5 PKCS #1 Version 1.5
+//
+// sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
+//
+// sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
+//
+// sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
+//
+//
+// RFC 5758 3.1 DSA Signature Algorithms
+//
+// dsaWithSha256 OBJECT IDENTIFIER ::= {
+//    joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101)
+//    csor(3) algorithms(4) id-dsa-with-sha2(3) 2}
+//
+// RFC 5758 3.2 ECDSA Signature Algorithm
+//
+// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+//    us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
+//
+// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+//    us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
+//
+// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+//    us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
+
+var (
+	oidSignatureMD2WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
+	oidSignatureMD5WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
+	oidSignatureSHA1WithRSA     = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
+	oidSignatureSHA256WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
+	oidSignatureSHA384WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
+	oidSignatureSHA512WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
+	oidSignatureDSAWithSHA1     = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
+	oidSignatureDSAWithSHA256   = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
+	oidSignatureECDSAWithSHA1   = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
+	oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
+	oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
+	oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
+)
+
+var signatureAlgorithmDetails = []struct {
+	algo       SignatureAlgorithm
+	oid        asn1.ObjectIdentifier
+	pubKeyAlgo PublicKeyAlgorithm
+	hash       crypto.Hash
+}{
+	{MD2WithRSA, oidSignatureMD2WithRSA, RSA, crypto.Hash(0) /* no value for MD2 */},
+	{MD5WithRSA, oidSignatureMD5WithRSA, RSA, crypto.MD5},
+	{SHA1WithRSA, oidSignatureSHA1WithRSA, RSA, crypto.SHA1},
+	{SHA256WithRSA, oidSignatureSHA256WithRSA, RSA, crypto.SHA256},
+	{SHA384WithRSA, oidSignatureSHA384WithRSA, RSA, crypto.SHA384},
+	{SHA512WithRSA, oidSignatureSHA512WithRSA, RSA, crypto.SHA512},
+	{DSAWithSHA1, oidSignatureDSAWithSHA1, DSA, crypto.SHA1},
+	{DSAWithSHA256, oidSignatureDSAWithSHA256, DSA, crypto.SHA256},
+	{ECDSAWithSHA1, oidSignatureECDSAWithSHA1, ECDSA, crypto.SHA1},
+	{ECDSAWithSHA256, oidSignatureECDSAWithSHA256, ECDSA, crypto.SHA256},
+	{ECDSAWithSHA384, oidSignatureECDSAWithSHA384, ECDSA, crypto.SHA384},
+	{ECDSAWithSHA512, oidSignatureECDSAWithSHA512, ECDSA, crypto.SHA512},
+}
+
+func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm {
+	for _, details := range signatureAlgorithmDetails {
+		if oid.Equal(details.oid) {
+			return details.algo
+		}
+	}
+	return UnknownSignatureAlgorithm
+}
+
+// RFC 3279, 2.3 Public Key Algorithms
+//
+// pkcs-1 OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
+//    rsadsi(113549) pkcs(1) 1 }
+//
+// rsaEncryption OBJECT IDENTIFIER ::== { pkcs1-1 1 }
+//
+// id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
+//    x9-57(10040) x9cm(4) 1 }
+//
+// RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters
+//
+// id-ecPublicKey OBJECT IDENTIFIER ::= {
+//       iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
+var (
+	oidPublicKeyRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
+	oidPublicKeyDSA   = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
+	oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
+)
+
+func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm {
+	switch {
+	case oid.Equal(oidPublicKeyRSA):
+		return RSA
+	case oid.Equal(oidPublicKeyDSA):
+		return DSA
+	case oid.Equal(oidPublicKeyECDSA):
+		return ECDSA
+	}
+	return UnknownPublicKeyAlgorithm
+}
+
+// RFC 5480, 2.1.1.1. Named Curve
+//
+// secp224r1 OBJECT IDENTIFIER ::= {
+//   iso(1) identified-organization(3) certicom(132) curve(0) 33 }
+//
+// secp256r1 OBJECT IDENTIFIER ::= {
+//   iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
+//   prime(1) 7 }
+//
+// secp384r1 OBJECT IDENTIFIER ::= {
+//   iso(1) identified-organization(3) certicom(132) curve(0) 34 }
+//
+// secp521r1 OBJECT IDENTIFIER ::= {
+//   iso(1) identified-organization(3) certicom(132) curve(0) 35 }
+//
+// NB: secp256r1 is equivalent to prime256v1
+var (
+	oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
+	oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
+	oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
+	oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
+)
+
+func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
+	switch {
+	case oid.Equal(oidNamedCurveP224):
+		return elliptic.P224()
+	case oid.Equal(oidNamedCurveP256):
+		return elliptic.P256()
+	case oid.Equal(oidNamedCurveP384):
+		return elliptic.P384()
+	case oid.Equal(oidNamedCurveP521):
+		return elliptic.P521()
+	}
+	return nil
+}
+
+func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
+	switch curve {
+	case elliptic.P224():
+		return oidNamedCurveP224, true
+	case elliptic.P256():
+		return oidNamedCurveP256, true
+	case elliptic.P384():
+		return oidNamedCurveP384, true
+	case elliptic.P521():
+		return oidNamedCurveP521, true
+	}
+
+	return nil, false
+}
+
+// KeyUsage represents the set of actions that are valid for a given key. It's
+// a bitmap of the KeyUsage* constants.
+type KeyUsage int
+
+const (
+	KeyUsageDigitalSignature KeyUsage = 1 << iota
+	KeyUsageContentCommitment
+	KeyUsageKeyEncipherment
+	KeyUsageDataEncipherment
+	KeyUsageKeyAgreement
+	KeyUsageCertSign
+	KeyUsageCRLSign
+	KeyUsageEncipherOnly
+	KeyUsageDecipherOnly
+)
+
+// RFC 5280, 4.2.1.12  Extended Key Usage
+//
+// anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }
+//
+// id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
+//
+// id-kp-serverAuth             OBJECT IDENTIFIER ::= { id-kp 1 }
+// id-kp-clientAuth             OBJECT IDENTIFIER ::= { id-kp 2 }
+// id-kp-codeSigning            OBJECT IDENTIFIER ::= { id-kp 3 }
+// id-kp-emailProtection        OBJECT IDENTIFIER ::= { id-kp 4 }
+// id-kp-timeStamping           OBJECT IDENTIFIER ::= { id-kp 8 }
+// id-kp-OCSPSigning            OBJECT IDENTIFIER ::= { id-kp 9 }
+var (
+	oidExtKeyUsageAny                        = asn1.ObjectIdentifier{2, 5, 29, 37, 0}
+	oidExtKeyUsageServerAuth                 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}
+	oidExtKeyUsageClientAuth                 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
+	oidExtKeyUsageCodeSigning                = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
+	oidExtKeyUsageEmailProtection            = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
+	oidExtKeyUsageIPSECEndSystem             = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5}
+	oidExtKeyUsageIPSECTunnel                = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6}
+	oidExtKeyUsageIPSECUser                  = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7}
+	oidExtKeyUsageTimeStamping               = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
+	oidExtKeyUsageOCSPSigning                = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
+	oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3}
+	oidExtKeyUsageNetscapeServerGatedCrypto  = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1}
+)
+
+// ExtKeyUsage represents an extended set of actions that are valid for a given key.
+// Each of the ExtKeyUsage* constants define a unique action.
+type ExtKeyUsage int
+
+const (
+	ExtKeyUsageAny ExtKeyUsage = iota
+	ExtKeyUsageServerAuth
+	ExtKeyUsageClientAuth
+	ExtKeyUsageCodeSigning
+	ExtKeyUsageEmailProtection
+	ExtKeyUsageIPSECEndSystem
+	ExtKeyUsageIPSECTunnel
+	ExtKeyUsageIPSECUser
+	ExtKeyUsageTimeStamping
+	ExtKeyUsageOCSPSigning
+	ExtKeyUsageMicrosoftServerGatedCrypto
+	ExtKeyUsageNetscapeServerGatedCrypto
+)
+
+// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID.
+var extKeyUsageOIDs = []struct {
+	extKeyUsage ExtKeyUsage
+	oid         asn1.ObjectIdentifier
+}{
+	{ExtKeyUsageAny, oidExtKeyUsageAny},
+	{ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth},
+	{ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth},
+	{ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning},
+	{ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection},
+	{ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem},
+	{ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel},
+	{ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser},
+	{ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping},
+	{ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning},
+	{ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto},
+	{ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto},
+}
+
+func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) {
+	for _, pair := range extKeyUsageOIDs {
+		if oid.Equal(pair.oid) {
+			return pair.extKeyUsage, true
+		}
+	}
+	return
+}
+
+func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) {
+	for _, pair := range extKeyUsageOIDs {
+		if eku == pair.extKeyUsage {
+			return pair.oid, true
+		}
+	}
+	return
+}
+
+// A Certificate represents an X.509 certificate.
+type Certificate struct {
+	Raw                     []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
+	RawTBSCertificate       []byte // Certificate part of raw ASN.1 DER content.
+	RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
+	RawSubject              []byte // DER encoded Subject
+	RawIssuer               []byte // DER encoded Issuer
+
+	Signature          []byte
+	SignatureAlgorithm SignatureAlgorithm
+
+	PublicKeyAlgorithm PublicKeyAlgorithm
+	PublicKey          interface{}
+
+	Version             int
+	SerialNumber        *big.Int
+	Issuer              pkix.Name
+	Subject             pkix.Name
+	NotBefore, NotAfter time.Time // Validity bounds.
+	KeyUsage            KeyUsage
+
+	// Extensions contains raw X.509 extensions. When parsing certificates,
+	// this can be used to extract non-critical extensions that are not
+	// parsed by this package. When marshaling certificates, the Extensions
+	// field is ignored, see ExtraExtensions.
+	Extensions []pkix.Extension
+
+	// ExtraExtensions contains extensions to be copied, raw, into any
+	// marshaled certificates. Values override any extensions that would
+	// otherwise be produced based on the other fields. The ExtraExtensions
+	// field is not populated when parsing certificates, see Extensions.
+	ExtraExtensions []pkix.Extension
+
+	ExtKeyUsage        []ExtKeyUsage           // Sequence of extended key usages.
+	UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package.
+
+	BasicConstraintsValid bool // if true then the next two fields are valid.
+	IsCA                  bool
+	MaxPathLen            int
+
+	SubjectKeyId   []byte
+	AuthorityKeyId []byte
+
+	// RFC 5280, 4.2.2.1 (Authority Information Access)
+	OCSPServer            []string
+	IssuingCertificateURL []string
+
+	// Subject Alternate Name values
+	DNSNames       []string
+	EmailAddresses []string
+	IPAddresses    []net.IP
+
+	// Name constraints
+	PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
+	PermittedDNSDomains         []string
+
+	// CRL Distribution Points
+	CRLDistributionPoints []string
+
+	PolicyIdentifiers []asn1.ObjectIdentifier
+}
+
+// ErrUnsupportedAlgorithm results from attempting to perform an operation that
+// involves algorithms that are not currently implemented.
+var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented")
+
+// ConstraintViolationError results when a requested usage is not permitted by
+// a certificate. For example: checking a signature when the public key isn't a
+// certificate signing key.
+type ConstraintViolationError struct{}
+
+func (ConstraintViolationError) Error() string {
+	return "x509: invalid signature: parent certificate cannot sign this kind of certificate"
+}
+
+func (c *Certificate) Equal(other *Certificate) bool {
+	return bytes.Equal(c.Raw, other.Raw)
+}
+
+// Entrust have a broken root certificate (CN=Entrust.net Certification
+// Authority (2048)) which isn't marked as a CA certificate and is thus invalid
+// according to PKIX.
+// We recognise this certificate by its SubjectPublicKeyInfo and exempt it
+// from the Basic Constraints requirement.
+// See http://www.entrust.net/knowledge-base/technote.cfm?tn=7869
+//
+// TODO(agl): remove this hack once their reissued root is sufficiently
+// widespread.
+var entrustBrokenSPKI = []byte{
+	0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09,
+	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+	0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00,
+	0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
+	0x00, 0x97, 0xa3, 0x2d, 0x3c, 0x9e, 0xde, 0x05,
+	0xda, 0x13, 0xc2, 0x11, 0x8d, 0x9d, 0x8e, 0xe3,
+	0x7f, 0xc7, 0x4b, 0x7e, 0x5a, 0x9f, 0xb3, 0xff,
+	0x62, 0xab, 0x73, 0xc8, 0x28, 0x6b, 0xba, 0x10,
+	0x64, 0x82, 0x87, 0x13, 0xcd, 0x57, 0x18, 0xff,
+	0x28, 0xce, 0xc0, 0xe6, 0x0e, 0x06, 0x91, 0x50,
+	0x29, 0x83, 0xd1, 0xf2, 0xc3, 0x2a, 0xdb, 0xd8,
+	0xdb, 0x4e, 0x04, 0xcc, 0x00, 0xeb, 0x8b, 0xb6,
+	0x96, 0xdc, 0xbc, 0xaa, 0xfa, 0x52, 0x77, 0x04,
+	0xc1, 0xdb, 0x19, 0xe4, 0xae, 0x9c, 0xfd, 0x3c,
+	0x8b, 0x03, 0xef, 0x4d, 0xbc, 0x1a, 0x03, 0x65,
+	0xf9, 0xc1, 0xb1, 0x3f, 0x72, 0x86, 0xf2, 0x38,
+	0xaa, 0x19, 0xae, 0x10, 0x88, 0x78, 0x28, 0xda,
+	0x75, 0xc3, 0x3d, 0x02, 0x82, 0x02, 0x9c, 0xb9,
+	0xc1, 0x65, 0x77, 0x76, 0x24, 0x4c, 0x98, 0xf7,
+	0x6d, 0x31, 0x38, 0xfb, 0xdb, 0xfe, 0xdb, 0x37,
+	0x02, 0x76, 0xa1, 0x18, 0x97, 0xa6, 0xcc, 0xde,
+	0x20, 0x09, 0x49, 0x36, 0x24, 0x69, 0x42, 0xf6,
+	0xe4, 0x37, 0x62, 0xf1, 0x59, 0x6d, 0xa9, 0x3c,
+	0xed, 0x34, 0x9c, 0xa3, 0x8e, 0xdb, 0xdc, 0x3a,
+	0xd7, 0xf7, 0x0a, 0x6f, 0xef, 0x2e, 0xd8, 0xd5,
+	0x93, 0x5a, 0x7a, 0xed, 0x08, 0x49, 0x68, 0xe2,
+	0x41, 0xe3, 0x5a, 0x90, 0xc1, 0x86, 0x55, 0xfc,
+	0x51, 0x43, 0x9d, 0xe0, 0xb2, 0xc4, 0x67, 0xb4,
+	0xcb, 0x32, 0x31, 0x25, 0xf0, 0x54, 0x9f, 0x4b,
+	0xd1, 0x6f, 0xdb, 0xd4, 0xdd, 0xfc, 0xaf, 0x5e,
+	0x6c, 0x78, 0x90, 0x95, 0xde, 0xca, 0x3a, 0x48,
+	0xb9, 0x79, 0x3c, 0x9b, 0x19, 0xd6, 0x75, 0x05,
+	0xa0, 0xf9, 0x88, 0xd7, 0xc1, 0xe8, 0xa5, 0x09,
+	0xe4, 0x1a, 0x15, 0xdc, 0x87, 0x23, 0xaa, 0xb2,
+	0x75, 0x8c, 0x63, 0x25, 0x87, 0xd8, 0xf8, 0x3d,
+	0xa6, 0xc2, 0xcc, 0x66, 0xff, 0xa5, 0x66, 0x68,
+	0x55, 0x02, 0x03, 0x01, 0x00, 0x01,
+}
+
+// CheckSignatureFrom verifies that the signature on c is a valid signature
+// from parent.
+func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) {
+	// RFC 5280, 4.2.1.9:
+	// "If the basic constraints extension is not present in a version 3
+	// certificate, or the extension is present but the cA boolean is not
+	// asserted, then the certified public key MUST NOT be used to verify
+	// certificate signatures."
+	// (except for Entrust, see comment above entrustBrokenSPKI)
+	if (parent.Version == 3 && !parent.BasicConstraintsValid ||
+		parent.BasicConstraintsValid && !parent.IsCA) &&
+		!bytes.Equal(c.RawSubjectPublicKeyInfo, entrustBrokenSPKI) {
+		return ConstraintViolationError{}
+	}
+
+	if parent.KeyUsage != 0 && parent.KeyUsage&KeyUsageCertSign == 0 {
+		return ConstraintViolationError{}
+	}
+
+	if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm {
+		return ErrUnsupportedAlgorithm
+	}
+
+	// TODO(agl): don't ignore the path length constraint.
+
+	return parent.CheckSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature)
+}
+
+// CheckSignature verifies that signature is a valid signature over signed from
+// c's public key.
+func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) (err error) {
+	var hashType crypto.Hash
+
+	switch algo {
+	case SHA1WithRSA, DSAWithSHA1, ECDSAWithSHA1:
+		hashType = crypto.SHA1
+	case SHA256WithRSA, DSAWithSHA256, ECDSAWithSHA256:
+		hashType = crypto.SHA256
+	case SHA384WithRSA, ECDSAWithSHA384:
+		hashType = crypto.SHA384
+	case SHA512WithRSA, ECDSAWithSHA512:
+		hashType = crypto.SHA512
+	default:
+		return ErrUnsupportedAlgorithm
+	}
+
+	if !hashType.Available() {
+		return ErrUnsupportedAlgorithm
+	}
+	h := hashType.New()
+
+	h.Write(signed)
+	digest := h.Sum(nil)
+
+	switch pub := c.PublicKey.(type) {
+	case *rsa.PublicKey:
+		return rsa.VerifyPKCS1v15(pub, hashType, digest, signature)
+	case *dsa.PublicKey:
+		dsaSig := new(dsaSignature)
+		if _, err := asn1.Unmarshal(signature, dsaSig); err != nil {
+			return err
+		}
+		if dsaSig.R.Sign() <= 0 || dsaSig.S.Sign() <= 0 {
+			return errors.New("x509: DSA signature contained zero or negative values")
+		}
+		if !dsa.Verify(pub, digest, dsaSig.R, dsaSig.S) {
+			return errors.New("x509: DSA verification failure")
+		}
+		return
+	case *ecdsa.PublicKey:
+		ecdsaSig := new(ecdsaSignature)
+		if _, err := asn1.Unmarshal(signature, ecdsaSig); err != nil {
+			return err
+		}
+		if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+			return errors.New("x509: ECDSA signature contained zero or negative values")
+		}
+		if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) {
+			return errors.New("x509: ECDSA verification failure")
+		}
+		return
+	}
+	return ErrUnsupportedAlgorithm
+}
+
+// CheckCRLSignature checks that the signature in crl is from c.
+func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) (err error) {
+	algo := getSignatureAlgorithmFromOID(crl.SignatureAlgorithm.Algorithm)
+	return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign())
+}
+
+type UnhandledCriticalExtension struct{}
+
+func (h UnhandledCriticalExtension) Error() string {
+	return "x509: unhandled critical extension"
+}
+
+type basicConstraints struct {
+	IsCA       bool `asn1:"optional"`
+	MaxPathLen int  `asn1:"optional,default:-1"`
+}
+
+// RFC 5280 4.2.1.4
+type policyInformation struct {
+	Policy asn1.ObjectIdentifier
+	// policyQualifiers omitted
+}
+
+// RFC 5280, 4.2.1.10
+type nameConstraints struct {
+	Permitted []generalSubtree `asn1:"optional,tag:0"`
+	Excluded  []generalSubtree `asn1:"optional,tag:1"`
+}
+
+type generalSubtree struct {
+	Name string `asn1:"tag:2,optional,ia5"`
+}
+
+// RFC 5280, 4.2.2.1
+type authorityInfoAccess struct {
+	Method   asn1.ObjectIdentifier
+	Location asn1.RawValue
+}
+
+// RFC 5280, 4.2.1.14
+type distributionPoint struct {
+	DistributionPoint distributionPointName `asn1:"optional,tag:0"`
+	Reason            asn1.BitString        `asn1:"optional,tag:1"`
+	CRLIssuer         asn1.RawValue         `asn1:"optional,tag:2"`
+}
+
+type distributionPointName struct {
+	FullName     asn1.RawValue    `asn1:"optional,tag:0"`
+	RelativeName pkix.RDNSequence `asn1:"optional,tag:1"`
+}
+
+func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
+	asn1Data := keyData.PublicKey.RightAlign()
+	switch algo {
+	case RSA:
+		p := new(rsaPublicKey)
+		_, err := asn1.Unmarshal(asn1Data, p)
+		if err != nil {
+			return nil, err
+		}
+
+		if p.N.Sign() <= 0 {
+			return nil, errors.New("x509: RSA modulus is not a positive number")
+		}
+		if p.E <= 0 {
+			return nil, errors.New("x509: RSA public exponent is not a positive number")
+		}
+
+		pub := &rsa.PublicKey{
+			E: p.E,
+			N: p.N,
+		}
+		return pub, nil
+	case DSA:
+		var p *big.Int
+		_, err := asn1.Unmarshal(asn1Data, &p)
+		if err != nil {
+			return nil, err
+		}
+		paramsData := keyData.Algorithm.Parameters.FullBytes
+		params := new(dsaAlgorithmParameters)
+		_, err = asn1.Unmarshal(paramsData, params)
+		if err != nil {
+			return nil, err
+		}
+		if p.Sign() <= 0 || params.P.Sign() <= 0 || params.Q.Sign() <= 0 || params.G.Sign() <= 0 {
+			return nil, errors.New("x509: zero or negative DSA parameter")
+		}
+		pub := &dsa.PublicKey{
+			Parameters: dsa.Parameters{
+				P: params.P,
+				Q: params.Q,
+				G: params.G,
+			},
+			Y: p,
+		}
+		return pub, nil
+	case ECDSA:
+		paramsData := keyData.Algorithm.Parameters.FullBytes
+		namedCurveOID := new(asn1.ObjectIdentifier)
+		_, err := asn1.Unmarshal(paramsData, namedCurveOID)
+		if err != nil {
+			return nil, err
+		}
+		namedCurve := namedCurveFromOID(*namedCurveOID)
+		if namedCurve == nil {
+			return nil, errors.New("x509: unsupported elliptic curve")
+		}
+		x, y := elliptic.Unmarshal(namedCurve, asn1Data)
+		if x == nil {
+			return nil, errors.New("x509: failed to unmarshal elliptic curve point")
+		}
+		pub := &ecdsa.PublicKey{
+			Curve: namedCurve,
+			X:     x,
+			Y:     y,
+		}
+		return pub, nil
+	default:
+		return nil, nil
+	}
+}
+
+func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddresses []net.IP, err error) {
+	// RFC 5280, 4.2.1.6
+
+	// SubjectAltName ::= GeneralNames
+	//
+	// GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+	//
+	// GeneralName ::= CHOICE {
+	//      otherName                       [0]     OtherName,
+	//      rfc822Name                      [1]     IA5String,
+	//      dNSName                         [2]     IA5String,
+	//      x400Address                     [3]     ORAddress,
+	//      directoryName                   [4]     Name,
+	//      ediPartyName                    [5]     EDIPartyName,
+	//      uniformResourceIdentifier       [6]     IA5String,
+	//      iPAddress                       [7]     OCTET STRING,
+	//      registeredID                    [8]     OBJECT IDENTIFIER }
+	var seq asn1.RawValue
+	if _, err = asn1.Unmarshal(value, &seq); err != nil {
+		return
+	}
+	if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 {
+		err = asn1.StructuralError{Msg: "bad SAN sequence"}
+		return
+	}
+
+	rest := seq.Bytes
+	for len(rest) > 0 {
+		var v asn1.RawValue
+		rest, err = asn1.Unmarshal(rest, &v)
+		if err != nil {
+			return
+		}
+		switch v.Tag {
+		case 1:
+			emailAddresses = append(emailAddresses, string(v.Bytes))
+		case 2:
+			dnsNames = append(dnsNames, string(v.Bytes))
+		case 7:
+			switch len(v.Bytes) {
+			case net.IPv4len, net.IPv6len:
+				ipAddresses = append(ipAddresses, v.Bytes)
+			default:
+				err = errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes)))
+				return
+			}
+		}
+	}
+
+	return
+}
+
+func parseCertificate(in *certificate) (*Certificate, error) {
+	out := new(Certificate)
+	out.Raw = in.Raw
+	out.RawTBSCertificate = in.TBSCertificate.Raw
+	out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw
+	out.RawSubject = in.TBSCertificate.Subject.FullBytes
+	out.RawIssuer = in.TBSCertificate.Issuer.FullBytes
+
+	out.Signature = in.SignatureValue.RightAlign()
+	out.SignatureAlgorithm =
+		getSignatureAlgorithmFromOID(in.TBSCertificate.SignatureAlgorithm.Algorithm)
+
+	out.PublicKeyAlgorithm =
+		getPublicKeyAlgorithmFromOID(in.TBSCertificate.PublicKey.Algorithm.Algorithm)
+	var err error
+	out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCertificate.PublicKey)
+	if err != nil {
+		return nil, err
+	}
+
+	if in.TBSCertificate.SerialNumber.Sign() < 0 {
+		return nil, errors.New("x509: negative serial number")
+	}
+
+	out.Version = in.TBSCertificate.Version + 1
+	out.SerialNumber = in.TBSCertificate.SerialNumber
+
+	var issuer, subject pkix.RDNSequence
+	if _, err := asn1.Unmarshal(in.TBSCertificate.Subject.FullBytes, &subject); err != nil {
+		return nil, err
+	}
+	if _, err := asn1.Unmarshal(in.TBSCertificate.Issuer.FullBytes, &issuer); err != nil {
+		return nil, err
+	}
+
+	out.Issuer.FillFromRDNSequence(&issuer)
+	out.Subject.FillFromRDNSequence(&subject)
+
+	out.NotBefore = in.TBSCertificate.Validity.NotBefore
+	out.NotAfter = in.TBSCertificate.Validity.NotAfter
+
+	for _, e := range in.TBSCertificate.Extensions {
+		out.Extensions = append(out.Extensions, e)
+
+		if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 {
+			switch e.Id[3] {
+			case 15:
+				// RFC 5280, 4.2.1.3
+				var usageBits asn1.BitString
+				_, err := asn1.Unmarshal(e.Value, &usageBits)
+
+				if err == nil {
+					var usage int
+					for i := 0; i < 9; i++ {
+						if usageBits.At(i) != 0 {
+							usage |= 1 << uint(i)
+						}
+					}
+					out.KeyUsage = KeyUsage(usage)
+					continue
+				}
+			case 19:
+				// RFC 5280, 4.2.1.9
+				var constraints basicConstraints
+				_, err := asn1.Unmarshal(e.Value, &constraints)
+
+				if err == nil {
+					out.BasicConstraintsValid = true
+					out.IsCA = constraints.IsCA
+					out.MaxPathLen = constraints.MaxPathLen
+					continue
+				}
+			case 17:
+				out.DNSNames, out.EmailAddresses, out.IPAddresses, err = parseSANExtension(e.Value)
+				if err != nil {
+					return nil, err
+				}
+
+				if len(out.DNSNames) > 0 || len(out.EmailAddresses) > 0 || len(out.IPAddresses) > 0 {
+					continue
+				}
+				// If we didn't parse any of the names then we
+				// fall through to the critical check below.
+
+			case 30:
+				// RFC 5280, 4.2.1.10
+
+				// NameConstraints ::= SEQUENCE {
+				//      permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
+				//      excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
+				//
+				// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+				//
+				// GeneralSubtree ::= SEQUENCE {
+				//      base                    GeneralName,
+				//      minimum         [0]     BaseDistance DEFAULT 0,
+				//      maximum         [1]     BaseDistance OPTIONAL }
+				//
+				// BaseDistance ::= INTEGER (0..MAX)
+
+				var constraints nameConstraints
+				_, err := asn1.Unmarshal(e.Value, &constraints)
+				if err != nil {
+					return nil, err
+				}
+
+				if len(constraints.Excluded) > 0 && e.Critical {
+					return out, UnhandledCriticalExtension{}
+				}
+
+				for _, subtree := range constraints.Permitted {
+					if len(subtree.Name) == 0 {
+						if e.Critical {
+							return out, UnhandledCriticalExtension{}
+						}
+						continue
+					}
+					out.PermittedDNSDomains = append(out.PermittedDNSDomains, subtree.Name)
+				}
+				continue
+
+			case 31:
+				// RFC 5280, 4.2.1.14
+
+				// CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+				//
+				// DistributionPoint ::= SEQUENCE {
+				//     distributionPoint       [0]     DistributionPointName OPTIONAL,
+				//     reasons                 [1]     ReasonFlags OPTIONAL,
+				//     cRLIssuer               [2]     GeneralNames OPTIONAL }
+				//
+				// DistributionPointName ::= CHOICE {
+				//     fullName                [0]     GeneralNames,
+				//     nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
+
+				var cdp []distributionPoint
+				_, err := asn1.Unmarshal(e.Value, &cdp)
+				if err != nil {
+					return nil, err
+				}
+
+				for _, dp := range cdp {
+					var n asn1.RawValue
+					_, err = asn1.Unmarshal(dp.DistributionPoint.FullName.Bytes, &n)
+					if err != nil {
+						return nil, err
+					}
+
+					if n.Tag == 6 {
+						out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(n.Bytes))
+					}
+				}
+				continue
+
+			case 35:
+				// RFC 5280, 4.2.1.1
+				var a authKeyId
+				_, err = asn1.Unmarshal(e.Value, &a)
+				if err != nil {
+					return nil, err
+				}
+				out.AuthorityKeyId = a.Id
+				continue
+
+			case 37:
+				// RFC 5280, 4.2.1.12.  Extended Key Usage
+
+				// id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 }
+				//
+				// ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+				//
+				// KeyPurposeId ::= OBJECT IDENTIFIER
+
+				var keyUsage []asn1.ObjectIdentifier
+				_, err = asn1.Unmarshal(e.Value, &keyUsage)
+				if err != nil {
+					return nil, err
+				}
+
+				for _, u := range keyUsage {
+					if extKeyUsage, ok := extKeyUsageFromOID(u); ok {
+						out.ExtKeyUsage = append(out.ExtKeyUsage, extKeyUsage)
+					} else {
+						out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u)
+					}
+				}
+
+				continue
+
+			case 14:
+				// RFC 5280, 4.2.1.2
+				var keyid []byte
+				_, err = asn1.Unmarshal(e.Value, &keyid)
+				if err != nil {
+					return nil, err
+				}
+				out.SubjectKeyId = keyid
+				continue
+
+			case 32:
+				// RFC 5280 4.2.1.4: Certificate Policies
+				var policies []policyInformation
+				if _, err = asn1.Unmarshal(e.Value, &policies); err != nil {
+					return nil, err
+				}
+				out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies))
+				for i, policy := range policies {
+					out.PolicyIdentifiers[i] = policy.Policy
+				}
+			}
+		} else if e.Id.Equal(oidExtensionAuthorityInfoAccess) {
+			// RFC 5280 4.2.2.1: Authority Information Access
+			var aia []authorityInfoAccess
+			if _, err = asn1.Unmarshal(e.Value, &aia); err != nil {
+				return nil, err
+			}
+
+			for _, v := range aia {
+				// GeneralName: uniformResourceIdentifier [6] IA5String
+				if v.Location.Tag != 6 {
+					continue
+				}
+				if v.Method.Equal(oidAuthorityInfoAccessOcsp) {
+					out.OCSPServer = append(out.OCSPServer, string(v.Location.Bytes))
+				} else if v.Method.Equal(oidAuthorityInfoAccessIssuers) {
+					out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(v.Location.Bytes))
+				}
+			}
+		}
+
+		if e.Critical {
+			return out, UnhandledCriticalExtension{}
+		}
+	}
+
+	return out, nil
+}
+
+// ParseCertificate parses a single certificate from the given ASN.1 DER data.
+func ParseCertificate(asn1Data []byte) (*Certificate, error) {
+	var cert certificate
+	rest, err := asn1.Unmarshal(asn1Data, &cert)
+	if err != nil {
+		return nil, err
+	}
+	if len(rest) > 0 {
+		return nil, asn1.SyntaxError{Msg: "trailing data"}
+	}
+
+	return parseCertificate(&cert)
+}
+
+// ParseCertificates parses one or more certificates from the given ASN.1 DER
+// data. The certificates must be concatenated with no intermediate padding.
+func ParseCertificates(asn1Data []byte) ([]*Certificate, error) {
+	var v []*certificate
+
+	for len(asn1Data) > 0 {
+		cert := new(certificate)
+		var err error
+		asn1Data, err = asn1.Unmarshal(asn1Data, cert)
+		if err != nil {
+			return nil, err
+		}
+		v = append(v, cert)
+	}
+
+	ret := make([]*Certificate, len(v))
+	for i, ci := range v {
+		cert, err := parseCertificate(ci)
+		if err != nil {
+			return nil, err
+		}
+		ret[i] = cert
+	}
+
+	return ret, nil
+}
+
+func reverseBitsInAByte(in byte) byte {
+	b1 := in>>4 | in<<4
+	b2 := b1>>2&0x33 | b1<<2&0xcc
+	b3 := b2>>1&0x55 | b2<<1&0xaa
+	return b3
+}
+
+var (
+	oidExtensionSubjectKeyId          = []int{2, 5, 29, 14}
+	oidExtensionKeyUsage              = []int{2, 5, 29, 15}
+	oidExtensionExtendedKeyUsage      = []int{2, 5, 29, 37}
+	oidExtensionAuthorityKeyId        = []int{2, 5, 29, 35}
+	oidExtensionBasicConstraints      = []int{2, 5, 29, 19}
+	oidExtensionSubjectAltName        = []int{2, 5, 29, 17}
+	oidExtensionCertificatePolicies   = []int{2, 5, 29, 32}
+	oidExtensionNameConstraints       = []int{2, 5, 29, 30}
+	oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31}
+	oidExtensionAuthorityInfoAccess   = []int{1, 3, 6, 1, 5, 5, 7, 1, 1}
+)
+
+var (
+	oidAuthorityInfoAccessOcsp    = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1}
+	oidAuthorityInfoAccessIssuers = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 2}
+)
+
+// oidNotInExtensions returns whether an extension with the given oid exists in
+// extensions.
+func oidInExtensions(oid asn1.ObjectIdentifier, extensions []pkix.Extension) bool {
+	for _, e := range extensions {
+		if e.Id.Equal(oid) {
+			return true
+		}
+	}
+	return false
+}
+
+// marshalSANs marshals a list of addresses into a the contents of an X.509
+// SubjectAlternativeName extension.
+func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP) (derBytes []byte, err error) {
+	var rawValues []asn1.RawValue
+	for _, name := range dnsNames {
+		rawValues = append(rawValues, asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)})
+	}
+	for _, email := range emailAddresses {
+		rawValues = append(rawValues, asn1.RawValue{Tag: 1, Class: 2, Bytes: []byte(email)})
+	}
+	for _, rawIP := range ipAddresses {
+		// If possible, we always want to encode IPv4 addresses in 4 bytes.
+		ip := rawIP.To4()
+		if ip == nil {
+			ip = rawIP
+		}
+		rawValues = append(rawValues, asn1.RawValue{Tag: 7, Class: 2, Bytes: ip})
+	}
+	return asn1.Marshal(rawValues)
+}
+
+func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
+	ret = make([]pkix.Extension, 10 /* maximum number of elements. */)
+	n := 0
+
+	if template.KeyUsage != 0 &&
+		!oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) {
+		ret[n].Id = oidExtensionKeyUsage
+		ret[n].Critical = true
+
+		var a [2]byte
+		a[0] = reverseBitsInAByte(byte(template.KeyUsage))
+		a[1] = reverseBitsInAByte(byte(template.KeyUsage >> 8))
+
+		l := 1
+		if a[1] != 0 {
+			l = 2
+		}
+
+		ret[n].Value, err = asn1.Marshal(asn1.BitString{Bytes: a[0:l], BitLength: l * 8})
+		if err != nil {
+			return
+		}
+		n++
+	}
+
+	if (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) &&
+		!oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) {
+		ret[n].Id = oidExtensionExtendedKeyUsage
+
+		var oids []asn1.ObjectIdentifier
+		for _, u := range template.ExtKeyUsage {
+			if oid, ok := oidFromExtKeyUsage(u); ok {
+				oids = append(oids, oid)
+			} else {
+				panic("internal error")
+			}
+		}
+
+		oids = append(oids, template.UnknownExtKeyUsage...)
+
+		ret[n].Value, err = asn1.Marshal(oids)
+		if err != nil {
+			return
+		}
+		n++
+	}
+
+	if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) {
+		ret[n].Id = oidExtensionBasicConstraints
+		ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, template.MaxPathLen})
+		ret[n].Critical = true
+		if err != nil {
+			return
+		}
+		n++
+	}
+
+	if len(template.SubjectKeyId) > 0 && !oidInExtensions(oidExtensionSubjectKeyId, template.ExtraExtensions) {
+		ret[n].Id = oidExtensionSubjectKeyId
+		ret[n].Value, err = asn1.Marshal(template.SubjectKeyId)
+		if err != nil {
+			return
+		}
+		n++
+	}
+
+	if len(template.AuthorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) {
+		ret[n].Id = oidExtensionAuthorityKeyId
+		ret[n].Value, err = asn1.Marshal(authKeyId{template.AuthorityKeyId})
+		if err != nil {
+			return
+		}
+		n++
+	}
+
+	if (len(template.OCSPServer) > 0 || len(template.IssuingCertificateURL) > 0) &&
+		!oidInExtensions(oidExtensionAuthorityInfoAccess, template.ExtraExtensions) {
+		ret[n].Id = oidExtensionAuthorityInfoAccess
+		var aiaValues []authorityInfoAccess
+		for _, name := range template.OCSPServer {
+			aiaValues = append(aiaValues, authorityInfoAccess{
+				Method:   oidAuthorityInfoAccessOcsp,
+				Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},
+			})
+		}
+		for _, name := range template.IssuingCertificateURL {
+			aiaValues = append(aiaValues, authorityInfoAccess{
+				Method:   oidAuthorityInfoAccessIssuers,
+				Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},
+			})
+		}
+		ret[n].Value, err = asn1.Marshal(aiaValues)
+		if err != nil {
+			return
+		}
+		n++
+	}
+
+	if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0) &&
+		!oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) {
+		ret[n].Id = oidExtensionSubjectAltName
+		ret[n].Value, err = marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses)
+		if err != nil {
+			return
+		}
+		n++
+	}
+
+	if len(template.PolicyIdentifiers) > 0 &&
+		!oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) {
+		ret[n].Id = oidExtensionCertificatePolicies
+		policies := make([]policyInformation, len(template.PolicyIdentifiers))
+		for i, policy := range template.PolicyIdentifiers {
+			policies[i].Policy = policy
+		}
+		ret[n].Value, err = asn1.Marshal(policies)
+		if err != nil {
+			return
+		}
+		n++
+	}
+
+	if len(template.PermittedDNSDomains) > 0 &&
+		!oidInExtensions(oidExtensionNameConstraints, template.ExtraExtensions) {
+		ret[n].Id = oidExtensionNameConstraints
+		ret[n].Critical = template.PermittedDNSDomainsCritical
+
+		var out nameConstraints
+		out.Permitted = make([]generalSubtree, len(template.PermittedDNSDomains))
+		for i, permitted := range template.PermittedDNSDomains {
+			out.Permitted[i] = generalSubtree{Name: permitted}
+		}
+		ret[n].Value, err = asn1.Marshal(out)
+		if err != nil {
+			return
+		}
+		n++
+	}
+
+	if len(template.CRLDistributionPoints) > 0 &&
+		!oidInExtensions(oidExtensionCRLDistributionPoints, template.ExtraExtensions) {
+		ret[n].Id = oidExtensionCRLDistributionPoints
+
+		var crlDp []distributionPoint
+		for _, name := range template.CRLDistributionPoints {
+			rawFullName, _ := asn1.Marshal(asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)})
+
+			dp := distributionPoint{
+				DistributionPoint: distributionPointName{
+					FullName: asn1.RawValue{Tag: 0, Class: 2, Bytes: rawFullName},
+				},
+			}
+			crlDp = append(crlDp, dp)
+		}
+
+		ret[n].Value, err = asn1.Marshal(crlDp)
+		if err != nil {
+			return
+		}
+		n++
+	}
+
+	// Adding another extension here? Remember to update the maximum number
+	// of elements in the make() at the top of the function.
+
+	return append(ret[:n], template.ExtraExtensions...), nil
+}
+
+func subjectBytes(cert *Certificate) ([]byte, error) {
+	if len(cert.RawSubject) > 0 {
+		return cert.RawSubject, nil
+	}
+
+	return asn1.Marshal(cert.Subject.ToRDNSequence())
+}
+
+// signingParamsForPrivateKey returns the parameters to use for signing with
+// priv. If requestedSigAlgo is not zero then it overrides the default
+// signature algorithm.
+func signingParamsForPrivateKey(priv interface{}, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
+	var pubType PublicKeyAlgorithm
+
+	switch priv := priv.(type) {
+	case *rsa.PrivateKey:
+		pubType = RSA
+		sigAlgo.Algorithm = oidSignatureSHA256WithRSA
+		hashFunc = crypto.SHA256
+
+	case *ecdsa.PrivateKey:
+		pubType = ECDSA
+
+		switch priv.Curve {
+		case elliptic.P224(), elliptic.P256():
+			hashFunc = crypto.SHA256
+			sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
+		case elliptic.P384():
+			hashFunc = crypto.SHA384
+			sigAlgo.Algorithm = oidSignatureECDSAWithSHA384
+		case elliptic.P521():
+			hashFunc = crypto.SHA512
+			sigAlgo.Algorithm = oidSignatureECDSAWithSHA512
+		default:
+			err = errors.New("x509: unknown elliptic curve")
+		}
+
+	default:
+		err = errors.New("x509: only RSA and ECDSA private keys supported")
+	}
+
+	if err != nil {
+		return
+	}
+
+	if requestedSigAlgo == 0 {
+		return
+	}
+
+	found := false
+	for _, details := range signatureAlgorithmDetails {
+		if details.algo == requestedSigAlgo {
+			if details.pubKeyAlgo != pubType {
+				err = errors.New("x509: requested SignatureAlgorithm does not match private key type")
+				return
+			}
+			sigAlgo.Algorithm, hashFunc = details.oid, details.hash
+			if hashFunc == 0 {
+				err = errors.New("x509: cannot sign with hash function requested")
+				return
+			}
+			found = true
+			break
+		}
+	}
+
+	if !found {
+		err = errors.New("x509: unknown SignatureAlgorithm")
+	}
+
+	return
+}
+
+// CreateCertificate creates a new certificate based on a template. The
+// following members of template are used: SerialNumber, Subject, NotBefore,
+// NotAfter, KeyUsage, ExtKeyUsage, UnknownExtKeyUsage, BasicConstraintsValid,
+// IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
+// PermittedDNSDomains, SignatureAlgorithm.
+//
+// The certificate is signed by parent. If parent is equal to template then the
+// certificate is self-signed. The parameter pub is the public key of the
+// signee and priv is the private key of the signer.
+//
+// The returned slice is the certificate in DER encoding.
+//
+// The only supported key types are RSA and ECDSA (*rsa.PublicKey or
+// *ecdsa.PublicKey for pub, *rsa.PrivateKey or *ecdsa.PrivateKey for priv).
+func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interface{}, priv interface{}) (cert []byte, err error) {
+	hashFunc, signatureAlgorithm, err := signingParamsForPrivateKey(priv, template.SignatureAlgorithm)
+	if err != nil {
+		return nil, err
+	}
+
+	publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(pub)
+	if err != nil {
+		return nil, err
+	}
+
+	if err != nil {
+		return
+	}
+
+	if len(parent.SubjectKeyId) > 0 {
+		template.AuthorityKeyId = parent.SubjectKeyId
+	}
+
+	extensions, err := buildExtensions(template)
+	if err != nil {
+		return
+	}
+
+	asn1Issuer, err := subjectBytes(parent)
+	if err != nil {
+		return
+	}
+
+	asn1Subject, err := subjectBytes(template)
+	if err != nil {
+		return
+	}
+
+	encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
+	c := tbsCertificate{
+		Version:            2,
+		SerialNumber:       template.SerialNumber,
+		SignatureAlgorithm: signatureAlgorithm,
+		Issuer:             asn1.RawValue{FullBytes: asn1Issuer},
+		Validity:           validity{template.NotBefore.UTC(), template.NotAfter.UTC()},
+		Subject:            asn1.RawValue{FullBytes: asn1Subject},
+		PublicKey:          publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
+		Extensions:         extensions,
+	}
+
+	tbsCertContents, err := asn1.Marshal(c)
+	if err != nil {
+		return
+	}
+
+	c.Raw = tbsCertContents
+
+	h := hashFunc.New()
+	h.Write(tbsCertContents)
+	digest := h.Sum(nil)
+
+	var signature []byte
+
+	switch priv := priv.(type) {
+	case *rsa.PrivateKey:
+		signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest)
+	case *ecdsa.PrivateKey:
+		var r, s *big.Int
+		if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil {
+			signature, err = asn1.Marshal(ecdsaSignature{r, s})
+		}
+	default:
+		panic("internal error")
+	}
+
+	if err != nil {
+		return
+	}
+
+	cert, err = asn1.Marshal(certificate{
+		nil,
+		c,
+		signatureAlgorithm,
+		asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
+	})
+	return
+}
+
+// pemCRLPrefix is the magic string that indicates that we have a PEM encoded
+// CRL.
+var pemCRLPrefix = []byte("-----BEGIN X509 CRL")
+
+// pemType is the type of a PEM encoded CRL.
+var pemType = "X509 CRL"
+
+// ParseCRL parses a CRL from the given bytes. It's often the case that PEM
+// encoded CRLs will appear where they should be DER encoded, so this function
+// will transparently handle PEM encoding as long as there isn't any leading
+// garbage.
+func ParseCRL(crlBytes []byte) (certList *pkix.CertificateList, err error) {
+	if bytes.HasPrefix(crlBytes, pemCRLPrefix) {
+		block, _ := pem.Decode(crlBytes)
+		if block != nil && block.Type == pemType {
+			crlBytes = block.Bytes
+		}
+	}
+	return ParseDERCRL(crlBytes)
+}
+
+// ParseDERCRL parses a DER encoded CRL from the given bytes.
+func ParseDERCRL(derBytes []byte) (certList *pkix.CertificateList, err error) {
+	certList = new(pkix.CertificateList)
+	_, err = asn1.Unmarshal(derBytes, certList)
+	if err != nil {
+		certList = nil
+	}
+	return
+}
+
+// CreateCRL returns a DER encoded CRL, signed by this Certificate, that
+// contains the given list of revoked certificates.
+//
+// The only supported key type is RSA (*rsa.PrivateKey for priv).
+func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) {
+	rsaPriv, ok := priv.(*rsa.PrivateKey)
+	if !ok {
+		return nil, errors.New("x509: non-RSA private keys not supported")
+	}
+	tbsCertList := pkix.TBSCertificateList{
+		Version: 2,
+		Signature: pkix.AlgorithmIdentifier{
+			Algorithm: oidSignatureSHA1WithRSA,
+		},
+		Issuer:              c.Subject.ToRDNSequence(),
+		ThisUpdate:          now.UTC(),
+		NextUpdate:          expiry.UTC(),
+		RevokedCertificates: revokedCerts,
+	}
+
+	tbsCertListContents, err := asn1.Marshal(tbsCertList)
+	if err != nil {
+		return
+	}
+
+	h := sha1.New()
+	h.Write(tbsCertListContents)
+	digest := h.Sum(nil)
+
+	signature, err := rsa.SignPKCS1v15(rand, rsaPriv, crypto.SHA1, digest)
+	if err != nil {
+		return
+	}
+
+	return asn1.Marshal(pkix.CertificateList{
+		TBSCertList: tbsCertList,
+		SignatureAlgorithm: pkix.AlgorithmIdentifier{
+			Algorithm: oidSignatureSHA1WithRSA,
+		},
+		SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
+	})
+}
+
+// CertificateRequest represents a PKCS #10, certificate signature request.
+type CertificateRequest struct {
+	Raw                      []byte // Complete ASN.1 DER content (CSR, signature algorithm and signature).
+	RawTBSCertificateRequest []byte // Certificate request info part of raw ASN.1 DER content.
+	RawSubjectPublicKeyInfo  []byte // DER encoded SubjectPublicKeyInfo.
+	RawSubject               []byte // DER encoded Subject.
+
+	Version            int
+	Signature          []byte
+	SignatureAlgorithm SignatureAlgorithm
+
+	PublicKeyAlgorithm PublicKeyAlgorithm
+	PublicKey          interface{}
+
+	Subject pkix.Name
+
+	// Attributes is a collection of attributes providing
+	// additional information about the subject of the certificate.
+	// See RFC 2986 section 4.1.
+	Attributes []pkix.AttributeTypeAndValueSET
+
+	// Extensions contains raw X.509 extensions. When parsing CSRs, this
+	// can be used to extract extensions that are not parsed by this
+	// package.
+	Extensions []pkix.Extension
+
+	// ExtraExtensions contains extensions to be copied, raw, into any
+	// marshaled CSR. Values override any extensions that would otherwise
+	// be produced based on the other fields but are overridden by any
+	// extensions specified in Attributes.
+	//
+	// The ExtraExtensions field is not populated when parsing CSRs, see
+	// Extensions.
+	ExtraExtensions []pkix.Extension
+
+	// Subject Alternate Name values.
+	DNSNames       []string
+	EmailAddresses []string
+	IPAddresses    []net.IP
+}
+
+// These structures reflect the ASN.1 structure of X.509 certificate
+// signature requests (see RFC 2986):
+
+type tbsCertificateRequest struct {
+	Raw        asn1.RawContent
+	Version    int
+	Subject    asn1.RawValue
+	PublicKey  publicKeyInfo
+	Attributes []pkix.AttributeTypeAndValueSET `asn1:"tag:0"`
+}
+
+type certificateRequest struct {
+	Raw                asn1.RawContent
+	TBSCSR             tbsCertificateRequest
+	SignatureAlgorithm pkix.AlgorithmIdentifier
+	SignatureValue     asn1.BitString
+}
+
+// oidExtensionRequest is a PKCS#9 OBJECT IDENTIFIER that indicates requested
+// extensions in a CSR.
+var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14}
+
+// CreateCertificateRequest creates a new certificate based on a template. The
+// following members of template are used: Subject, Attributes,
+// SignatureAlgorithm, Extension, DNSNames, EmailAddresses, and IPAddresses.
+// The private key is the private key of the signer.
+//
+// The returned slice is the certificate request in DER encoding.
+//
+// The only supported key types are RSA (*rsa.PrivateKey) and ECDSA
+// (*ecdsa.PrivateKey).
+func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv interface{}) (csr []byte, err error) {
+	hashFunc, sigAlgo, err := signingParamsForPrivateKey(priv, template.SignatureAlgorithm)
+	if err != nil {
+		return nil, err
+	}
+
+	var publicKeyBytes []byte
+	var publicKeyAlgorithm pkix.AlgorithmIdentifier
+
+	switch priv := priv.(type) {
+	case *rsa.PrivateKey:
+		publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(&priv.PublicKey)
+	case *ecdsa.PrivateKey:
+		publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(&priv.PublicKey)
+	default:
+		panic("internal error")
+	}
+
+	if err != nil {
+		return nil, err
+	}
+
+	var extensions []pkix.Extension
+
+	if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0) &&
+		!oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) {
+		sanBytes, err := marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses)
+		if err != nil {
+			return nil, err
+		}
+
+		extensions = append(extensions, pkix.Extension{
+			Id:    oidExtensionSubjectAltName,
+			Value: sanBytes,
+		})
+	}
+
+	extensions = append(extensions, template.ExtraExtensions...)
+
+	var attributes []pkix.AttributeTypeAndValueSET
+	attributes = append(attributes, template.Attributes...)
+
+	if len(extensions) > 0 {
+		// specifiedExtensions contains all the extensions that we
+		// found specified via template.Attributes.
+		specifiedExtensions := make(map[string]bool)
+
+		for _, atvSet := range template.Attributes {
+			if !atvSet.Type.Equal(oidExtensionRequest) {
+				continue
+			}
+
+			for _, atvs := range atvSet.Value {
+				for _, atv := range atvs {
+					specifiedExtensions[atv.Type.String()] = true
+				}
+			}
+		}
+
+		atvs := make([]pkix.AttributeTypeAndValue, 0, len(extensions))
+		for _, e := range extensions {
+			if specifiedExtensions[e.Id.String()] {
+				// Attributes already contained a value for
+				// this extension and it takes priority.
+				continue
+			}
+
+			atvs = append(atvs, pkix.AttributeTypeAndValue{
+				// There is no place for the critical flag in a CSR.
+				Type:  e.Id,
+				Value: e.Value,
+			})
+		}
+
+		// Append the extensions to an existing attribute if possible.
+		appended := false
+		for _, atvSet := range attributes {
+			if !atvSet.Type.Equal(oidExtensionRequest) || len(atvSet.Value) == 0 {
+				continue
+			}
+
+			atvSet.Value[0] = append(atvSet.Value[0], atvs...)
+			appended = true
+			break
+		}
+
+		// Otherwise, add a new attribute for the extensions.
+		if !appended {
+			attributes = append(attributes, pkix.AttributeTypeAndValueSET{
+				Type: oidExtensionRequest,
+				Value: [][]pkix.AttributeTypeAndValue{
+					atvs,
+				},
+			})
+		}
+	}
+
+	asn1Subject := template.RawSubject
+	if len(asn1Subject) == 0 {
+		asn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence())
+		if err != nil {
+			return
+		}
+	}
+
+	tbsCSR := tbsCertificateRequest{
+		Version: 0, // PKCS #10, RFC 2986
+		Subject: asn1.RawValue{FullBytes: asn1Subject},
+		PublicKey: publicKeyInfo{
+			Algorithm: publicKeyAlgorithm,
+			PublicKey: asn1.BitString{
+				Bytes:     publicKeyBytes,
+				BitLength: len(publicKeyBytes) * 8,
+			},
+		},
+		Attributes: attributes,
+	}
+
+	tbsCSRContents, err := asn1.Marshal(tbsCSR)
+	if err != nil {
+		return
+	}
+	tbsCSR.Raw = tbsCSRContents
+
+	h := hashFunc.New()
+	h.Write(tbsCSRContents)
+	digest := h.Sum(nil)
+
+	var signature []byte
+	switch priv := priv.(type) {
+	case *rsa.PrivateKey:
+		signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest)
+	case *ecdsa.PrivateKey:
+		var r, s *big.Int
+		if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil {
+			signature, err = asn1.Marshal(ecdsaSignature{r, s})
+		}
+	default:
+		panic("internal error")
+	}
+
+	if err != nil {
+		return
+	}
+
+	return asn1.Marshal(certificateRequest{
+		TBSCSR:             tbsCSR,
+		SignatureAlgorithm: sigAlgo,
+		SignatureValue: asn1.BitString{
+			Bytes:     signature,
+			BitLength: len(signature) * 8,
+		},
+	})
+}
+
+// ParseCertificateRequest parses a single certificate request from the
+// given ASN.1 DER data.
+func ParseCertificateRequest(asn1Data []byte) (*CertificateRequest, error) {
+	var csr certificateRequest
+
+	rest, err := asn1.Unmarshal(asn1Data, &csr)
+	if err != nil {
+		return nil, err
+	} else if len(rest) != 0 {
+		return nil, asn1.SyntaxError{Msg: "trailing data"}
+	}
+
+	return parseCertificateRequest(&csr)
+}
+
+func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error) {
+	out := &CertificateRequest{
+		Raw: in.Raw,
+		RawTBSCertificateRequest: in.TBSCSR.Raw,
+		RawSubjectPublicKeyInfo:  in.TBSCSR.PublicKey.Raw,
+		RawSubject:               in.TBSCSR.Subject.FullBytes,
+
+		Signature:          in.SignatureValue.RightAlign(),
+		SignatureAlgorithm: getSignatureAlgorithmFromOID(in.SignatureAlgorithm.Algorithm),
+
+		PublicKeyAlgorithm: getPublicKeyAlgorithmFromOID(in.TBSCSR.PublicKey.Algorithm.Algorithm),
+
+		Version:    in.TBSCSR.Version,
+		Attributes: in.TBSCSR.Attributes,
+	}
+
+	var err error
+	out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCSR.PublicKey)
+	if err != nil {
+		return nil, err
+	}
+
+	var subject pkix.RDNSequence
+	if _, err := asn1.Unmarshal(in.TBSCSR.Subject.FullBytes, &subject); err != nil {
+		return nil, err
+	}
+
+	out.Subject.FillFromRDNSequence(&subject)
+
+	var extensions []pkix.AttributeTypeAndValue
+
+	for _, atvSet := range in.TBSCSR.Attributes {
+		if !atvSet.Type.Equal(oidExtensionRequest) {
+			continue
+		}
+
+		for _, atvs := range atvSet.Value {
+			extensions = append(extensions, atvs...)
+		}
+	}
+
+	out.Extensions = make([]pkix.Extension, 0, len(extensions))
+
+	for _, e := range extensions {
+		value, ok := e.Value.([]byte)
+		if !ok {
+			return nil, errors.New("x509: extension attribute contained non-OCTET STRING data")
+		}
+
+		out.Extensions = append(out.Extensions, pkix.Extension{
+			Id:    e.Type,
+			Value: value,
+		})
+
+		if len(e.Type) == 4 && e.Type[0] == 2 && e.Type[1] == 5 && e.Type[2] == 29 {
+			switch e.Type[3] {
+			case 17:
+				out.DNSNames, out.EmailAddresses, out.IPAddresses, err = parseSANExtension(value)
+				if err != nil {
+					return nil, err
+				}
+			}
+		}
+	}
+
+	return out, nil
+}
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/x509_test.go b/third_party/gofrontend/libgo/go/crypto/x509/x509_test.go
new file mode 100644
index 0000000..41d186b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/x509_test.go
@@ -0,0 +1,953 @@
+// 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 x509
+
+import (
+	"bytes"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/rsa"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"encoding/base64"
+	"encoding/hex"
+	"encoding/pem"
+	"math/big"
+	"net"
+	"os/exec"
+	"reflect"
+	"runtime"
+	"testing"
+	"time"
+)
+
+func TestParsePKCS1PrivateKey(t *testing.T) {
+	block, _ := pem.Decode([]byte(pemPrivateKey))
+	priv, err := ParsePKCS1PrivateKey(block.Bytes)
+	if err != nil {
+		t.Errorf("Failed to parse private key: %s", err)
+		return
+	}
+	if priv.PublicKey.N.Cmp(rsaPrivateKey.PublicKey.N) != 0 ||
+		priv.PublicKey.E != rsaPrivateKey.PublicKey.E ||
+		priv.D.Cmp(rsaPrivateKey.D) != 0 ||
+		priv.Primes[0].Cmp(rsaPrivateKey.Primes[0]) != 0 ||
+		priv.Primes[1].Cmp(rsaPrivateKey.Primes[1]) != 0 {
+		t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey)
+	}
+}
+
+func TestParsePKIXPublicKey(t *testing.T) {
+	block, _ := pem.Decode([]byte(pemPublicKey))
+	pub, err := ParsePKIXPublicKey(block.Bytes)
+	if err != nil {
+		t.Errorf("Failed to parse RSA public key: %s", err)
+		return
+	}
+	rsaPub, ok := pub.(*rsa.PublicKey)
+	if !ok {
+		t.Errorf("Value returned from ParsePKIXPublicKey was not an RSA public key")
+		return
+	}
+
+	pubBytes2, err := MarshalPKIXPublicKey(rsaPub)
+	if err != nil {
+		t.Errorf("Failed to marshal RSA public key for the second time: %s", err)
+		return
+	}
+	if !bytes.Equal(pubBytes2, block.Bytes) {
+		t.Errorf("Reserialization of public key didn't match. got %x, want %x", pubBytes2, block.Bytes)
+	}
+}
+
+var pemPublicKey = `-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3VoPN9PKUjKFLMwOge6+
+wnDi8sbETGIx2FKXGgqtAKpzmem53kRGEQg8WeqRmp12wgp74TGpkEXsGae7RS1k
+enJCnma4fii+noGH7R0qKgHvPrI2Bwa9hzsH8tHxpyM3qrXslOmD45EH9SxIDUBJ
+FehNdaPbLP1gFyahKMsdfxFJLUvbUycuZSJ2ZnIgeVxwm4qbSvZInL9Iu4FzuPtg
+fINKcbbovy1qq4KvPIrXzhbY3PWDc6btxCf3SE0JdE1MCPThntB62/bLMSQ7xdDR
+FF53oIpvxe/SCOymfWq/LW849Ytv3Xwod0+wzAP8STXG4HSELS4UedPYeHJJJYcZ
++QIDAQAB
+-----END PUBLIC KEY-----
+`
+
+var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
+MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
+fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
+/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
+RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
+EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
+IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
+tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
+-----END RSA PRIVATE KEY-----
+`
+
+func bigFromString(s string) *big.Int {
+	ret := new(big.Int)
+	ret.SetString(s, 10)
+	return ret
+}
+
+func fromBase10(base10 string) *big.Int {
+	i := new(big.Int)
+	i.SetString(base10, 10)
+	return i
+}
+
+func bigFromHexString(s string) *big.Int {
+	ret := new(big.Int)
+	ret.SetString(s, 16)
+	return ret
+}
+
+var rsaPrivateKey = &rsa.PrivateKey{
+	PublicKey: rsa.PublicKey{
+		N: bigFromString("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
+		E: 65537,
+	},
+	D: bigFromString("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
+	Primes: []*big.Int{
+		bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
+		bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+	},
+}
+
+func TestMarshalRSAPrivateKey(t *testing.T) {
+	priv := &rsa.PrivateKey{
+		PublicKey: rsa.PublicKey{
+			N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
+			E: 3,
+		},
+		D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
+		Primes: []*big.Int{
+			fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
+			fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
+			fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+		},
+	}
+
+	derBytes := MarshalPKCS1PrivateKey(priv)
+
+	priv2, err := ParsePKCS1PrivateKey(derBytes)
+	if err != nil {
+		t.Errorf("error parsing serialized key: %s", err)
+		return
+	}
+	if priv.PublicKey.N.Cmp(priv2.PublicKey.N) != 0 ||
+		priv.PublicKey.E != priv2.PublicKey.E ||
+		priv.D.Cmp(priv2.D) != 0 ||
+		len(priv2.Primes) != 3 ||
+		priv.Primes[0].Cmp(priv2.Primes[0]) != 0 ||
+		priv.Primes[1].Cmp(priv2.Primes[1]) != 0 ||
+		priv.Primes[2].Cmp(priv2.Primes[2]) != 0 {
+		t.Errorf("got:%+v want:%+v", priv, priv2)
+	}
+}
+
+type matchHostnamesTest struct {
+	pattern, host string
+	ok            bool
+}
+
+var matchHostnamesTests = []matchHostnamesTest{
+	{"a.b.c", "a.b.c", true},
+	{"a.b.c", "b.b.c", false},
+	{"", "b.b.c", false},
+	{"a.b.c", "", false},
+	{"example.com", "example.com", true},
+	{"example.com", "www.example.com", false},
+	{"*.example.com", "www.example.com", true},
+	{"*.example.com", "xyz.www.example.com", false},
+	{"*.*.example.com", "xyz.www.example.com", true},
+	{"*.www.*.com", "xyz.www.example.com", true},
+}
+
+func TestMatchHostnames(t *testing.T) {
+	for i, test := range matchHostnamesTests {
+		r := matchHostnames(test.pattern, test.host)
+		if r != test.ok {
+			t.Errorf("#%d mismatch got: %t want: %t", i, r, test.ok)
+		}
+	}
+}
+
+func TestMatchIP(t *testing.T) {
+	// Check that pattern matching is working.
+	c := &Certificate{
+		DNSNames: []string{"*.foo.bar.baz"},
+		Subject: pkix.Name{
+			CommonName: "*.foo.bar.baz",
+		},
+	}
+	err := c.VerifyHostname("quux.foo.bar.baz")
+	if err != nil {
+		t.Fatalf("VerifyHostname(quux.foo.bar.baz): %v", err)
+	}
+
+	// But check that if we change it to be matching against an IP address,
+	// it is rejected.
+	c = &Certificate{
+		DNSNames: []string{"*.2.3.4"},
+		Subject: pkix.Name{
+			CommonName: "*.2.3.4",
+		},
+	}
+	err = c.VerifyHostname("1.2.3.4")
+	if err == nil {
+		t.Fatalf("VerifyHostname(1.2.3.4) should have failed, did not")
+	}
+
+	c = &Certificate{
+		IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")},
+	}
+	err = c.VerifyHostname("127.0.0.1")
+	if err != nil {
+		t.Fatalf("VerifyHostname(127.0.0.1): %v", err)
+	}
+	err = c.VerifyHostname("::1")
+	if err != nil {
+		t.Fatalf("VerifyHostname(::1): %v", err)
+	}
+	err = c.VerifyHostname("[::1]")
+	if err != nil {
+		t.Fatalf("VerifyHostname([::1]): %v", err)
+	}
+}
+
+func TestCertificateParse(t *testing.T) {
+	s, _ := hex.DecodeString(certBytes)
+	certs, err := ParseCertificates(s)
+	if err != nil {
+		t.Error(err)
+	}
+	if len(certs) != 2 {
+		t.Errorf("Wrong number of certs: got %d want 2", len(certs))
+		return
+	}
+
+	err = certs[0].CheckSignatureFrom(certs[1])
+	if err != nil {
+		t.Error(err)
+	}
+
+	if err := certs[0].VerifyHostname("mail.google.com"); err != nil {
+		t.Error(err)
+	}
+
+	const expectedExtensions = 4
+	if n := len(certs[0].Extensions); n != expectedExtensions {
+		t.Errorf("want %d extensions, got %d", expectedExtensions, n)
+	}
+}
+
+var certBytes = "308203223082028ba00302010202106edf0d9499fd4533dd1297fc42a93be1300d06092a864886" +
+	"f70d0101050500304c310b3009060355040613025a4131253023060355040a131c546861777465" +
+	"20436f6e73756c74696e67202850747929204c74642e311630140603550403130d546861777465" +
+	"20534743204341301e170d3039303332353136343932395a170d3130303332353136343932395a" +
+	"3069310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630" +
+	"140603550407130d4d6f756e7461696e205669657731133011060355040a130a476f6f676c6520" +
+	"496e63311830160603550403130f6d61696c2e676f6f676c652e636f6d30819f300d06092a8648" +
+	"86f70d010101050003818d0030818902818100c5d6f892fccaf5614b064149e80a2c9581a218ef" +
+	"41ec35bd7a58125ae76f9ea54ddc893abbeb029f6b73616bf0ffd868791fba7af9c4aebf3706ba" +
+	"3eeaeed27435b4ddcfb157c05f351d66aa87fee0de072d66d773affbd36ab78bef090e0cc861a9" +
+	"03ac90dd98b51c9c41566c017f0beec3bff391051ffba0f5cc6850ad2a590203010001a381e730" +
+	"81e430280603551d250421301f06082b0601050507030106082b06010505070302060960864801" +
+	"86f842040130360603551d1f042f302d302ba029a0278625687474703a2f2f63726c2e74686177" +
+	"74652e636f6d2f54686177746553474343412e63726c307206082b060105050701010466306430" +
+	"2206082b060105050730018616687474703a2f2f6f6373702e7468617774652e636f6d303e0608" +
+	"2b060105050730028632687474703a2f2f7777772e7468617774652e636f6d2f7265706f736974" +
+	"6f72792f5468617774655f5347435f43412e637274300c0603551d130101ff04023000300d0609" +
+	"2a864886f70d01010505000381810062f1f3050ebc105e497c7aedf87e24d2f4a986bb3b837bd1" +
+	"9b91ebcad98b065992f6bd2b49b7d6d3cb2e427a99d606c7b1d46352527fac39e6a8b6726de5bf" +
+	"70212a52cba07634a5e332011bd1868e78eb5e3c93cf03072276786f207494feaa0ed9d53b2110" +
+	"a76571f90209cdae884385c882587030ee15f33d761e2e45a6bc308203233082028ca003020102" +
+	"020430000002300d06092a864886f70d0101050500305f310b3009060355040613025553311730" +
+	"15060355040a130e566572695369676e2c20496e632e31373035060355040b132e436c61737320" +
+	"33205075626c6963205072696d6172792043657274696669636174696f6e20417574686f726974" +
+	"79301e170d3034303531333030303030305a170d3134303531323233353935395a304c310b3009" +
+	"060355040613025a4131253023060355040a131c54686177746520436f6e73756c74696e672028" +
+	"50747929204c74642e311630140603550403130d5468617774652053474320434130819f300d06" +
+	"092a864886f70d010101050003818d0030818902818100d4d367d08d157faecd31fe7d1d91a13f" +
+	"0b713cacccc864fb63fc324b0794bd6f80ba2fe10493c033fc093323e90b742b71c403c6d2cde2" +
+	"2ff50963cdff48a500bfe0e7f388b72d32de9836e60aad007bc4644a3b847503f270927d0e62f5" +
+	"21ab693684317590f8bfc76c881b06957cc9e5a8de75a12c7a68dfd5ca1c875860190203010001" +
+	"a381fe3081fb30120603551d130101ff040830060101ff020100300b0603551d0f040403020106" +
+	"301106096086480186f842010104040302010630280603551d110421301fa41d301b3119301706" +
+	"035504031310507269766174654c6162656c332d313530310603551d1f042a30283026a024a022" +
+	"8620687474703a2f2f63726c2e766572697369676e2e636f6d2f706361332e63726c303206082b" +
+	"0601050507010104263024302206082b060105050730018616687474703a2f2f6f6373702e7468" +
+	"617774652e636f6d30340603551d25042d302b06082b0601050507030106082b06010505070302" +
+	"06096086480186f8420401060a6086480186f845010801300d06092a864886f70d010105050003" +
+	"81810055ac63eadea1ddd2905f9f0bce76be13518f93d9052bc81b774bad6950a1eededcfddb07" +
+	"e9e83994dcab72792f06bfab8170c4a8edea5334edef1e53d906c7562bd15cf4d18a8eb42bb137" +
+	"9048084225c53e8acb7feb6f04d16dc574a2f7a27c7b603c77cd0ece48027f012fb69b37e02a2a" +
+	"36dcd585d6ace53f546f961e05af"
+
+func TestCreateSelfSignedCertificate(t *testing.T) {
+	random := rand.Reader
+
+	block, _ := pem.Decode([]byte(pemPrivateKey))
+	rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes)
+	if err != nil {
+		t.Fatalf("Failed to parse private key: %s", err)
+	}
+
+	ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		t.Fatalf("Failed to generate ECDSA key: %s", err)
+	}
+
+	tests := []struct {
+		name      string
+		pub, priv interface{}
+		checkSig  bool
+		sigAlgo   SignatureAlgorithm
+	}{
+		{"RSA/RSA", &rsaPriv.PublicKey, rsaPriv, true, SHA1WithRSA},
+		{"RSA/ECDSA", &rsaPriv.PublicKey, ecdsaPriv, false, ECDSAWithSHA384},
+		{"ECDSA/RSA", &ecdsaPriv.PublicKey, rsaPriv, false, SHA256WithRSA},
+		{"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA1},
+	}
+
+	testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
+	testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}}
+	extraExtensionData := []byte("extra extension")
+
+	for _, test := range tests {
+		commonName := "test.example.com"
+		template := Certificate{
+			SerialNumber: big.NewInt(1),
+			Subject: pkix.Name{
+				CommonName:   commonName,
+				Organization: []string{"Σ Acme Co"},
+			},
+			NotBefore: time.Unix(1000, 0),
+			NotAfter:  time.Unix(100000, 0),
+
+			SignatureAlgorithm: test.sigAlgo,
+
+			SubjectKeyId: []byte{1, 2, 3, 4},
+			KeyUsage:     KeyUsageCertSign,
+
+			ExtKeyUsage:        testExtKeyUsage,
+			UnknownExtKeyUsage: testUnknownExtKeyUsage,
+
+			BasicConstraintsValid: true,
+			IsCA: true,
+
+			OCSPServer:            []string{"http://ocsp.example.com"},
+			IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"},
+
+			DNSNames:       []string{"test.example.com"},
+			EmailAddresses: []string{"gopher@golang.org"},
+			IPAddresses:    []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
+
+			PolicyIdentifiers:   []asn1.ObjectIdentifier{[]int{1, 2, 3}},
+			PermittedDNSDomains: []string{".example.com", "example.com"},
+
+			CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
+
+			ExtraExtensions: []pkix.Extension{
+				{
+					Id:    []int{1, 2, 3, 4},
+					Value: extraExtensionData,
+				},
+				// This extension should override the SubjectKeyId, above.
+				{
+					Id:       oidExtensionSubjectKeyId,
+					Critical: false,
+					Value:    []byte{0x04, 0x04, 4, 3, 2, 1},
+				},
+			},
+		}
+
+		derBytes, err := CreateCertificate(random, &template, &template, test.pub, test.priv)
+		if err != nil {
+			t.Errorf("%s: failed to create certificate: %s", test.name, err)
+			continue
+		}
+
+		cert, err := ParseCertificate(derBytes)
+		if err != nil {
+			t.Errorf("%s: failed to parse certificate: %s", test.name, err)
+			continue
+		}
+
+		if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
+			t.Errorf("%s: failed to parse policy identifiers: got:%#v want:%#v", test.name, cert.PolicyIdentifiers, template.PolicyIdentifiers)
+		}
+
+		if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
+			t.Errorf("%s: failed to parse name constraints: %#v", test.name, cert.PermittedDNSDomains)
+		}
+
+		if cert.Subject.CommonName != commonName {
+			t.Errorf("%s: subject wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Subject.CommonName, commonName)
+		}
+
+		if cert.Issuer.CommonName != commonName {
+			t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName)
+		}
+
+		if cert.SignatureAlgorithm != test.sigAlgo {
+			t.Errorf("%s: SignatureAlgorithm wasn't copied from template. Got %v, want %v", test.name, cert.SignatureAlgorithm, test.sigAlgo)
+		}
+
+		if !reflect.DeepEqual(cert.ExtKeyUsage, testExtKeyUsage) {
+			t.Errorf("%s: extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.ExtKeyUsage, testExtKeyUsage)
+		}
+
+		if !reflect.DeepEqual(cert.UnknownExtKeyUsage, testUnknownExtKeyUsage) {
+			t.Errorf("%s: unknown extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.UnknownExtKeyUsage, testUnknownExtKeyUsage)
+		}
+
+		if !reflect.DeepEqual(cert.OCSPServer, template.OCSPServer) {
+			t.Errorf("%s: OCSP servers differ from template. Got %v, want %v", test.name, cert.OCSPServer, template.OCSPServer)
+		}
+
+		if !reflect.DeepEqual(cert.IssuingCertificateURL, template.IssuingCertificateURL) {
+			t.Errorf("%s: Issuing certificate URLs differ from template. Got %v, want %v", test.name, cert.IssuingCertificateURL, template.IssuingCertificateURL)
+		}
+
+		if !reflect.DeepEqual(cert.DNSNames, template.DNSNames) {
+			t.Errorf("%s: SAN DNS names differ from template. Got %v, want %v", test.name, cert.DNSNames, template.DNSNames)
+		}
+
+		if !reflect.DeepEqual(cert.EmailAddresses, template.EmailAddresses) {
+			t.Errorf("%s: SAN emails differ from template. Got %v, want %v", test.name, cert.EmailAddresses, template.EmailAddresses)
+		}
+
+		if !reflect.DeepEqual(cert.IPAddresses, template.IPAddresses) {
+			t.Errorf("%s: SAN IPs differ from template. Got %v, want %v", test.name, cert.IPAddresses, template.IPAddresses)
+		}
+
+		if !reflect.DeepEqual(cert.CRLDistributionPoints, template.CRLDistributionPoints) {
+			t.Errorf("%s: CRL distribution points differ from template. Got %v, want %v", test.name, cert.CRLDistributionPoints, template.CRLDistributionPoints)
+		}
+
+		if !bytes.Equal(cert.SubjectKeyId, []byte{4, 3, 2, 1}) {
+			t.Errorf("%s: ExtraExtensions didn't override SubjectKeyId", test.name)
+		}
+
+		if bytes.Index(derBytes, extraExtensionData) == -1 {
+			t.Errorf("%s: didn't find extra extension in DER output", test.name)
+		}
+
+		if test.checkSig {
+			err = cert.CheckSignatureFrom(cert)
+			if err != nil {
+				t.Errorf("%s: signature verification failed: %s", test.name, err)
+			}
+		}
+	}
+}
+
+// Self-signed certificate using ECDSA with SHA1 & secp256r1
+var ecdsaSHA1CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICDjCCAbUCCQDF6SfN0nsnrjAJBgcqhkjOPQQBMIGPMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMG
+A1UECgwMR29vZ2xlLCBJbmMuMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIwMjAyMDUw
+WhcNMjIwNTE4MjAyMDUwWjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTATBgNVBAoMDEdvb2dsZSwg
+SW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAhBgkqhkiG9w0BCQEWFGdv
+bGFuZy1kZXZAZ21haWwuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/Wgn
+WQDo5+bz71T0327ERgd5SDDXFbXLpzIZDXTkjpe8QTEbsF+ezsQfrekrpDPC4Cd3
+P9LY0tG+aI8IyVKdUjAJBgcqhkjOPQQBA0gAMEUCIGlsqMcRqWVIWTD6wXwe6Jk2
+DKxL46r/FLgJYnzBEH99AiEA3fBouObsvV1R3oVkb4BQYnD4/4LeId6lAT43YvyV
+a/A=
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA256 & secp256r1
+var ecdsaSHA256p256CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICDzCCAbYCCQDlsuMWvgQzhTAKBggqhkjOPQQDAjCBjzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
+BgNVBAoMDEdvb2dsZSwgSW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAh
+BgkqhkiG9w0BCQEWFGdvbGFuZy1kZXZAZ21haWwuY29tMB4XDTEyMDUyMTAwMTkx
+NloXDTIyMDUxOTAwMTkxNlowgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYDVQQKDAxHb29nbGUs
+IEluYy4xFzAVBgNVBAMMDnd3dy5nb29nbGUuY29tMSMwIQYJKoZIhvcNAQkBFhRn
+b2xhbmctZGV2QGdtYWlsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPMt
+2ErhxAty5EJRu9yM+MTy+hUXm3pdW1ensAv382KoGExSXAFWP7pjJnNtHO+XSwVm
+YNtqjcAGFKpweoN//kQwCgYIKoZIzj0EAwIDRwAwRAIgIYSaUA/IB81gjbIw/hUV
+70twxJr5EcgOo0hLp3Jm+EYCIFDO3NNcgmURbJ1kfoS3N/0O+irUtoPw38YoNkqJ
+h5wi
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA256 & secp384r1
+var ecdsaSHA256p384CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICSjCCAdECCQDje/no7mXkVzAKBggqhkjOPQQDAjCBjjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
+BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMDYxMDM0
+WhcNMjIwNTE5MDYxMDM0WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
+SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
+YW5nLWRldkBnbWFpbC5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARRuzRNIKRK
+jIktEmXanNmrTR/q/FaHXLhWRZ6nHWe26Fw7Rsrbk+VjGy4vfWtNn7xSFKrOu5ze
+qxKnmE0h5E480MNgrUiRkaGO2GMJJVmxx20aqkXOk59U8yGA4CghE6MwCgYIKoZI
+zj0EAwIDZwAwZAIwBZEN8gvmRmfeP/9C1PRLzODIY4JqWub2PLRT4mv9GU+yw3Gr
+PU9A3CHMdEcdw/MEAjBBO1lId8KOCh9UZunsSMfqXiVurpzmhWd6VYZ/32G+M+Mh
+3yILeYQzllt/g0rKVRk=
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA384 & secp521r1
+var ecdsaSHA384p521CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICljCCAfcCCQDhp1AFD/ahKjAKBggqhkjOPQQDAzCBjjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
+BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMTUwNDI5
+WhcNMjIwNTE5MTUwNDI5WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
+SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
+YW5nLWRldkBnbWFpbC5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACqx9Rv
+IssRs1LWYcNN+WffwlHw4Tv3y8/LIAA9MF1ZScIonU9nRMxt4a2uGJVCPDw6JHpz
+PaYc0E9puLoE9AfKpwFr59Jkot7dBg55SKPEFkddoip/rvmN7NPAWjMBirOwjOkm
+8FPthvPhGPqsu9AvgVuHu3PosWiHGNrhh379pva8MzAKBggqhkjOPQQDAwOBjAAw
+gYgCQgEHNmswkUdPpHqrVxp9PvLVl+xxPuHBkT+75z9JizyxtqykHQo9Uh6SWCYH
+BF9KLolo01wMt8DjoYP5Fb3j5MH7xwJCAbWZzTOp4l4DPkIvAh4LeC4VWbwPPyqh
+kBg71w/iEcSY3wUKgHGcJJrObZw7wys91I5kENljqw/Samdr3ka+jBJa
+-----END CERTIFICATE-----
+`
+
+var ecdsaTests = []struct {
+	sigAlgo SignatureAlgorithm
+	pemCert string
+}{
+	{ECDSAWithSHA1, ecdsaSHA1CertPem},
+	{ECDSAWithSHA256, ecdsaSHA256p256CertPem},
+	{ECDSAWithSHA256, ecdsaSHA256p384CertPem},
+	{ECDSAWithSHA384, ecdsaSHA384p521CertPem},
+}
+
+func TestECDSA(t *testing.T) {
+	for i, test := range ecdsaTests {
+		pemBlock, _ := pem.Decode([]byte(test.pemCert))
+		cert, err := ParseCertificate(pemBlock.Bytes)
+		if err != nil {
+			t.Errorf("%d: failed to parse certificate: %s", i, err)
+			continue
+		}
+		if sa := cert.SignatureAlgorithm; sa != test.sigAlgo {
+			t.Errorf("%d: signature algorithm is %v, want %v", i, sa, test.sigAlgo)
+		}
+		if parsedKey, ok := cert.PublicKey.(*ecdsa.PublicKey); !ok {
+			t.Errorf("%d: wanted an ECDSA public key but found: %#v", i, parsedKey)
+		}
+		if pka := cert.PublicKeyAlgorithm; pka != ECDSA {
+			t.Errorf("%d: public key algorithm is %v, want ECDSA", i, pka)
+		}
+		if err = cert.CheckSignatureFrom(cert); err != nil {
+			t.Errorf("%d: certificate verification failed: %s", i, err)
+		}
+	}
+}
+
+// Self-signed certificate using DSA with SHA1
+var dsaCertPem = `-----BEGIN CERTIFICATE-----
+MIIEDTCCA82gAwIBAgIJALHPghaoxeDhMAkGByqGSM44BAMweTELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAk5DMQ8wDQYDVQQHEwZOZXd0b24xFDASBgNVBAoTC0dvb2ds
+ZSwgSW5jMRIwEAYDVQQDEwlKb24gQWxsaWUxIjAgBgkqhkiG9w0BCQEWE2pvbmFs
+bGllQGdvb2dsZS5jb20wHhcNMTEwNTE0MDMwMTQ1WhcNMTEwNjEzMDMwMTQ1WjB5
+MQswCQYDVQQGEwJVUzELMAkGA1UECBMCTkMxDzANBgNVBAcTBk5ld3RvbjEUMBIG
+A1UEChMLR29vZ2xlLCBJbmMxEjAQBgNVBAMTCUpvbiBBbGxpZTEiMCAGCSqGSIb3
+DQEJARYTam9uYWxsaWVAZ29vZ2xlLmNvbTCCAbcwggEsBgcqhkjOOAQBMIIBHwKB
+gQC8hLUnQ7FpFYu4WXTj6DKvXvz8QrJkNJCVMTpKAT7uBpobk32S5RrPKXocd4gN
+8lyGB9ggS03EVlEwXvSmO0DH2MQtke2jl9j1HLydClMf4sbx5V6TV9IFw505U1iW
+jL7awRMgxge+FsudtJK254FjMFo03ZnOQ8ZJJ9E6AEDrlwIVAJpnBn9moyP11Ox5
+Asc/5dnjb6dPAoGBAJFHd4KVv1iTVCvEG6gGiYop5DJh28hUQcN9kul+2A0yPUSC
+X93oN00P8Vh3eYgSaCWZsha7zDG53MrVJ0Zf6v/X/CoZNhLldeNOepivTRAzn+Rz
+kKUYy5l1sxYLHQKF0UGNCXfFKZT0PCmgU+PWhYNBBMn6/cIh44vp85ideo5CA4GE
+AAKBgFmifCafzeRaohYKXJgMGSEaggCVCRq5xdyDCat+wbOkjC4mfG01/um3G8u5
+LxasjlWRKTR/tcAL7t0QuokVyQaYdVypZXNaMtx1db7YBuHjj3aP+8JOQRI9xz8c
+bp5NDJ5pISiFOv4p3GZfqZPcqckDt78AtkQrmnal2txhhjF6o4HeMIHbMB0GA1Ud
+DgQWBBQVyyr7hO11ZFFpWX50298Sa3V+rzCBqwYDVR0jBIGjMIGggBQVyyr7hO11
+ZFFpWX50298Sa3V+r6F9pHsweTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk5DMQ8w
+DQYDVQQHEwZOZXd0b24xFDASBgNVBAoTC0dvb2dsZSwgSW5jMRIwEAYDVQQDEwlK
+b24gQWxsaWUxIjAgBgkqhkiG9w0BCQEWE2pvbmFsbGllQGdvb2dsZS5jb22CCQCx
+z4IWqMXg4TAMBgNVHRMEBTADAQH/MAkGByqGSM44BAMDLwAwLAIUPtn/5j8Q1jJI
+7ggOIsgrhgUdjGQCFCsmDq1H11q9+9Wp9IMeGrTSKHIM
+-----END CERTIFICATE-----
+`
+
+func TestParseCertificateWithDsaPublicKey(t *testing.T) {
+	expectedKey := &dsa.PublicKey{
+		Parameters: dsa.Parameters{
+			P: bigFromHexString("00BC84B52743B169158BB85974E3E832AF5EFCFC42B264349095313A4A013EEE069A1B937D92E51ACF297A1C77880DF25C8607D8204B4DC45651305EF4A63B40C7D8C42D91EDA397D8F51CBC9D0A531FE2C6F1E55E9357D205C39D395358968CBEDAC11320C607BE16CB9DB492B6E78163305A34DD99CE43C64927D13A0040EB97"),
+			Q: bigFromHexString("009A67067F66A323F5D4EC7902C73FE5D9E36FA74F"),
+			G: bigFromHexString("009147778295BF5893542BC41BA806898A29E43261DBC85441C37D92E97ED80D323D44825FDDE8374D0FF15877798812682599B216BBCC31B9DCCAD527465FEAFFD7FC2A193612E575E34E7A98AF4D10339FE47390A518CB9975B3160B1D0285D1418D0977C52994F43C29A053E3D685834104C9FAFDC221E38BE9F3989D7A8E42"),
+		},
+		Y: bigFromHexString("59A27C269FCDE45AA2160A5C980C19211A820095091AB9C5DC8309AB7EC1B3A48C2E267C6D35FEE9B71BCBB92F16AC8E559129347FB5C00BEEDD10BA8915C90698755CA965735A32DC7575BED806E1E38F768FFBC24E41123DC73F1C6E9E4D0C9E692128853AFE29DC665FA993DCA9C903B7BF00B6442B9A76A5DADC6186317A"),
+	}
+	pemBlock, _ := pem.Decode([]byte(dsaCertPem))
+	cert, err := ParseCertificate(pemBlock.Bytes)
+	if err != nil {
+		t.Fatalf("Failed to parse certificate: %s", err)
+	}
+	if cert.PublicKeyAlgorithm != DSA {
+		t.Errorf("Parsed key algorithm was not DSA")
+	}
+	parsedKey, ok := cert.PublicKey.(*dsa.PublicKey)
+	if !ok {
+		t.Fatalf("Parsed key was not a DSA key: %s", err)
+	}
+	if expectedKey.Y.Cmp(parsedKey.Y) != 0 ||
+		expectedKey.P.Cmp(parsedKey.P) != 0 ||
+		expectedKey.Q.Cmp(parsedKey.Q) != 0 ||
+		expectedKey.G.Cmp(parsedKey.G) != 0 {
+		t.Fatal("Parsed key differs from expected key")
+	}
+}
+
+func TestParseCertificateWithDSASignatureAlgorithm(t *testing.T) {
+	pemBlock, _ := pem.Decode([]byte(dsaCertPem))
+	cert, err := ParseCertificate(pemBlock.Bytes)
+	if err != nil {
+		t.Fatalf("Failed to parse certificate: %s", err)
+	}
+	if cert.SignatureAlgorithm != DSAWithSHA1 {
+		t.Errorf("Parsed signature algorithm was not DSAWithSHA1")
+	}
+}
+
+func TestVerifyCertificateWithDSASignature(t *testing.T) {
+	pemBlock, _ := pem.Decode([]byte(dsaCertPem))
+	cert, err := ParseCertificate(pemBlock.Bytes)
+	if err != nil {
+		t.Fatalf("Failed to parse certificate: %s", err)
+	}
+	// test cert is self-signed
+	if err = cert.CheckSignatureFrom(cert); err != nil {
+		t.Fatalf("DSA Certificate verification failed: %s", err)
+	}
+}
+
+const pemCertificate = `-----BEGIN CERTIFICATE-----
+MIIB5DCCAZCgAwIBAgIBATALBgkqhkiG9w0BAQUwLTEQMA4GA1UEChMHQWNtZSBDbzEZMBcGA1UE
+AxMQdGVzdC5leGFtcGxlLmNvbTAeFw03MDAxMDEwMDE2NDBaFw03MDAxMDIwMzQ2NDBaMC0xEDAO
+BgNVBAoTB0FjbWUgQ28xGTAXBgNVBAMTEHRlc3QuZXhhbXBsZS5jb20wWjALBgkqhkiG9w0BAQED
+SwAwSAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0fd7Ai2KW5ToIwzFo
+fvJcS/STa6HA5gQenRUCAwEAAaOBnjCBmzAOBgNVHQ8BAf8EBAMCAAQwDwYDVR0TAQH/BAUwAwEB
+/zANBgNVHQ4EBgQEAQIDBDAPBgNVHSMECDAGgAQBAgMEMBsGA1UdEQQUMBKCEHRlc3QuZXhhbXBs
+ZS5jb20wDwYDVR0gBAgwBjAEBgIqAzAqBgNVHR4EIzAhoB8wDoIMLmV4YW1wbGUuY29tMA2CC2V4
+YW1wbGUuY29tMAsGCSqGSIb3DQEBBQNBAHKZKoS1wEQOGhgklx4+/yFYQlnqwKXvar/ZecQvJwui
+0seMQnwBhwdBkHfVIU2Fu5VUMRyxlf0ZNaDXcpU581k=
+-----END CERTIFICATE-----`
+
+func TestCRLCreation(t *testing.T) {
+	block, _ := pem.Decode([]byte(pemPrivateKey))
+	priv, _ := ParsePKCS1PrivateKey(block.Bytes)
+	block, _ = pem.Decode([]byte(pemCertificate))
+	cert, _ := ParseCertificate(block.Bytes)
+
+	now := time.Unix(1000, 0)
+	expiry := time.Unix(10000, 0)
+
+	revokedCerts := []pkix.RevokedCertificate{
+		{
+			SerialNumber:   big.NewInt(1),
+			RevocationTime: now,
+		},
+		{
+			SerialNumber:   big.NewInt(42),
+			RevocationTime: now,
+		},
+	}
+
+	crlBytes, err := cert.CreateCRL(rand.Reader, priv, revokedCerts, now, expiry)
+	if err != nil {
+		t.Errorf("error creating CRL: %s", err)
+	}
+
+	_, err = ParseDERCRL(crlBytes)
+	if err != nil {
+		t.Errorf("error reparsing CRL: %s", err)
+	}
+}
+
+func fromBase64(in string) []byte {
+	out := make([]byte, base64.StdEncoding.DecodedLen(len(in)))
+	n, err := base64.StdEncoding.Decode(out, []byte(in))
+	if err != nil {
+		panic("failed to base64 decode")
+	}
+	return out[:n]
+}
+
+func TestParseDERCRL(t *testing.T) {
+	derBytes := fromBase64(derCRLBase64)
+	certList, err := ParseDERCRL(derBytes)
+	if err != nil {
+		t.Errorf("error parsing: %s", err)
+		return
+	}
+	numCerts := len(certList.TBSCertList.RevokedCertificates)
+	expected := 88
+	if numCerts != expected {
+		t.Errorf("bad number of revoked certificates. got: %d want: %d", numCerts, expected)
+	}
+
+	if certList.HasExpired(time.Unix(1302517272, 0)) {
+		t.Errorf("CRL has expired (but shouldn't have)")
+	}
+
+	// Can't check the signature here without a package cycle.
+}
+
+func TestParsePEMCRL(t *testing.T) {
+	pemBytes := fromBase64(pemCRLBase64)
+	certList, err := ParseCRL(pemBytes)
+	if err != nil {
+		t.Errorf("error parsing: %s", err)
+		return
+	}
+	numCerts := len(certList.TBSCertList.RevokedCertificates)
+	expected := 2
+	if numCerts != expected {
+		t.Errorf("bad number of revoked certificates. got: %d want: %d", numCerts, expected)
+	}
+
+	if certList.HasExpired(time.Unix(1302517272, 0)) {
+		t.Errorf("CRL has expired (but shouldn't have)")
+	}
+
+	// Can't check the signature here without a package cycle.
+}
+
+func TestImports(t *testing.T) {
+	t.Skip("gccgo does not have a go command")
+	if runtime.GOOS == "nacl" {
+		t.Skip("skipping on nacl")
+	}
+
+	if err := exec.Command("go", "run", "x509_test_import.go").Run(); err != nil {
+		t.Errorf("failed to run x509_test_import.go: %s", err)
+	}
+}
+
+const derCRLBase64 = "MIINqzCCDJMCAQEwDQYJKoZIhvcNAQEFBQAwVjEZMBcGA1UEAxMQUEtJIEZJTk1FQ0NBTklDQTEVMBMGA1UEChMMRklOTUVDQ0FOSUNBMRUwEwYDVQQLEwxGSU5NRUNDQU5JQ0ExCzAJBgNVBAYTAklUFw0xMTA1MDQxNjU3NDJaFw0xMTA1MDQyMDU3NDJaMIIMBzAhAg4Ze1od49Lt1qIXBydAzhcNMDkwNzE2MDg0MzIyWjAAMCECDl0HSL9bcZ1Ci/UHJ0DPFw0wOTA3MTYwODQzMTNaMAAwIQIOESB9tVAmX3cY7QcnQNAXDTA5MDcxNjA4NDUyMlowADAhAg4S1tGAQ3mHt8uVBydA1RcNMDkwODA0MTUyNTIyWjAAMCECDlQ249Y7vtC25ScHJ0DWFw0wOTA4MDQxNTI1MzdaMAAwIQIOISMop3NkA4PfYwcnQNkXDTA5MDgwNDExMDAzNFowADAhAg56/BMoS29KEShTBydA2hcNMDkwODA0MTEwMTAzWjAAMCECDnBp/22HPH5CSWoHJ0DbFw0wOTA4MDQxMDU0NDlaMAAwIQIOV9IP+8CD8bK+XAcnQNwXDTA5MDgwNDEwNTcxN1owADAhAg4v5aRz0IxWqYiXBydA3RcNMDkwODA0MTA1NzQ1WjAAMCECDlOU34VzvZAybQwHJ0DeFw0wOTA4MDQxMDU4MjFaMAAwIAINO4CD9lluIxcwBydBAxcNMDkwNzIyMTUzMTU5WjAAMCECDgOllfO8Y1QA7/wHJ0ExFw0wOTA3MjQxMTQxNDNaMAAwIQIOJBX7jbiCdRdyjgcnQUQXDTA5MDkxNjA5MzAwOFowADAhAg5iYSAgmDrlH/RZBydBRRcNMDkwOTE2MDkzMDE3WjAAMCECDmu6k6srP3jcMaQHJ0FRFw0wOTA4MDQxMDU2NDBaMAAwIQIOX8aHlO0V+WVH4QcnQVMXDTA5MDgwNDEwNTcyOVowADAhAg5flK2rg3NnsRgDBydBzhcNMTEwMjAxMTUzMzQ2WjAAMCECDg35yJDL1jOPTgoHJ0HPFw0xMTAyMDExNTM0MjZaMAAwIQIOMyFJ6+e9iiGVBQcnQdAXDTA5MDkxODEzMjAwNVowADAhAg5Emb/Oykucmn8fBydB1xcNMDkwOTIxMTAxMDQ3WjAAMCECDjQKCncV+MnUavMHJ0HaFw0wOTA5MjIwODE1MjZaMAAwIQIOaxiFUt3dpd+tPwcnQfQXDTEwMDYxODA4NDI1MVowADAhAg5G7P8nO0tkrMt7BydB9RcNMTAwNjE4MDg0MjMwWjAAMCECDmTCC3SXhmDRst4HJ0H2Fw0wOTA5MjgxMjA3MjBaMAAwIQIOHoGhUr/pRwzTKgcnQfcXDTA5MDkyODEyMDcyNFowADAhAg50wrcrCiw8mQmPBydCBBcNMTAwMjE2MTMwMTA2WjAAMCECDifWmkvwyhEqwEcHJ0IFFw0xMDAyMTYxMzAxMjBaMAAwIQIOfgPmlW9fg+osNgcnQhwXDTEwMDQxMzA5NTIwMFowADAhAg4YHAGuA6LgCk7tBydCHRcNMTAwNDEzMDk1MTM4WjAAMCECDi1zH1bxkNJhokAHJ0IsFw0xMDA0MTMwOTU5MzBaMAAwIQIOMipNccsb/wo2fwcnQi0XDTEwMDQxMzA5NTkwMFowADAhAg46lCmvPl4GpP6ABydCShcNMTAwMTE5MDk1MjE3WjAAMCECDjaTcaj+wBpcGAsHJ0JLFw0xMDAxMTkwOTUyMzRaMAAwIQIOOMC13EOrBuxIOQcnQloXDTEwMDIwMTA5NDcwNVowADAhAg5KmZl+krz4RsmrBydCWxcNMTAwMjAxMDk0NjQwWjAAMCECDmLG3zQJ/fzdSsUHJ0JiFw0xMDAzMDEwOTUxNDBaMAAwIQIOP39ksgHdojf4owcnQmMXDTEwMDMwMTA5NTExN1owADAhAg4LDQzvWNRlD6v9BydCZBcNMTAwMzAxMDk0NjIyWjAAMCECDkmNfeclaFhIaaUHJ0JlFw0xMDAzMDEwOTQ2MDVaMAAwIQIOT/qWWfpH/m8NTwcnQpQXDTEwMDUxMTA5MTgyMVowADAhAg5m/ksYxvCEgJSvBydClRcNMTAwNTExMDkxODAxWjAAMCECDgvf3Ohq6JOPU9AHJ0KWFw0xMDA1MTEwOTIxMjNaMAAwIQIOKSPas10z4jNVIQcnQpcXDTEwMDUxMTA5MjEwMlowADAhAg4mCWmhoZ3lyKCDBydCohcNMTEwNDI4MTEwMjI1WjAAMCECDkeiyRsBMK0Gvr4HJ0KjFw0xMTA0MjgxMTAyMDdaMAAwIQIOa09b/nH2+55SSwcnQq4XDTExMDQwMTA4Mjk0NlowADAhAg5O7M7iq7gGplr1BydCrxcNMTEwNDAxMDgzMDE3WjAAMCECDjlT6mJxUjTvyogHJ0K1Fw0xMTAxMjcxNTQ4NTJaMAAwIQIODS/l4UUFLe21NAcnQrYXDTExMDEyNzE1NDgyOFowADAhAg5lPRA0XdOUF6lSBydDHhcNMTEwMTI4MTQzNTA1WjAAMCECDixKX4fFGGpENwgHJ0MfFw0xMTAxMjgxNDM1MzBaMAAwIQIORNBkqsPnpKTtbAcnQ08XDTEwMDkwOTA4NDg0MlowADAhAg5QL+EMM3lohedEBydDUBcNMTAwOTA5MDg0ODE5WjAAMCECDlhDnHK+HiTRAXcHJ0NUFw0xMDEwMTkxNjIxNDBaMAAwIQIOdBFqAzq/INz53gcnQ1UXDTEwMTAxOTE2MjA0NFowADAhAg4OjR7s8MgKles1BydDWhcNMTEwMTI3MTY1MzM2WjAAMCECDmfR/elHee+d0SoHJ0NbFw0xMTAxMjcxNjUzNTZaMAAwIQIOBTKv2ui+KFMI+wcnQ5YXDTEwMDkxNTEwMjE1N1owADAhAg49F3c/GSah+oRUBydDmxcNMTEwMTI3MTczMjMzWjAAMCECDggv4I61WwpKFMMHJ0OcFw0xMTAxMjcxNzMyNTVaMAAwIQIOXx/Y8sEvwS10LAcnQ6UXDTExMDEyODExMjkzN1owADAhAg5LSLbnVrSKaw/9BydDphcNMTEwMTI4MTEyOTIwWjAAMCECDmFFoCuhKUeACQQHJ0PfFw0xMTAxMTExMDE3MzdaMAAwIQIOQTDdFh2fSPF6AAcnQ+AXDTExMDExMTEwMTcxMFowADAhAg5B8AOXX61FpvbbBydD5RcNMTAxMDA2MTAxNDM2WjAAMCECDh41P2Gmi7PkwI4HJ0PmFw0xMDEwMDYxMDE2MjVaMAAwIQIOWUHGLQCd+Ale9gcnQ/0XDTExMDUwMjA3NTYxMFowADAhAg5Z2c9AYkikmgWOBydD/hcNMTEwNTAyMDc1NjM0WjAAMCECDmf/UD+/h8nf+74HJ0QVFw0xMTA0MTUwNzI4MzNaMAAwIQIOICvj4epy3MrqfwcnRBYXDTExMDQxNTA3Mjg1NlowADAhAg4bouRMfOYqgv4xBydEHxcNMTEwMzA4MTYyNDI1WjAAMCECDhebWHGoKiTp7pEHJ0QgFw0xMTAzMDgxNjI0NDhaMAAwIQIOX+qnxxAqJ8LtawcnRDcXDTExMDEzMTE1MTIyOFowADAhAg4j0fICqZ+wkOdqBydEOBcNMTEwMTMxMTUxMTQxWjAAMCECDhmXjsV4SUpWtAMHJ0RLFw0xMTAxMjgxMTI0MTJaMAAwIQIODno/w+zG43kkTwcnREwXDTExMDEyODExMjM1MlowADAhAg4b1gc88767Fr+LBydETxcNMTEwMTI4MTEwMjA4WjAAMCECDn+M3Pa1w2nyFeUHJ0RQFw0xMTAxMjgxMDU4NDVaMAAwIQIOaduoyIH61tqybAcnRJUXDTEwMTIxNTA5NDMyMlowADAhAg4nLqQPkyi3ESAKBydElhcNMTAxMjE1MDk0MzM2WjAAMCECDi504NIMH8578gQHJ0SbFw0xMTAyMTQxNDA1NDFaMAAwIQIOGuaM8PDaC5u1egcnRJwXDTExMDIxNDE0MDYwNFowADAhAg4ehYq/BXGnB5PWBydEnxcNMTEwMjA0MDgwOTUxWjAAMCECDkSD4eS4FxW5H20HJ0SgFw0xMTAyMDQwODA5MjVaMAAwIQIOOCcb6ilYObt1egcnRKEXDTExMDEyNjEwNDEyOVowADAhAg58tISWCCwFnKGnBydEohcNMTEwMjA0MDgxMzQyWjAAMCECDn5rjtabY/L/WL0HJ0TJFw0xMTAyMDQxMTAzNDFaMAAwDQYJKoZIhvcNAQEFBQADggEBAGnF2Gs0+LNiYCW1Ipm83OXQYP/bd5tFFRzyz3iepFqNfYs4D68/QihjFoRHQoXEB0OEe1tvaVnnPGnEOpi6krwekquMxo4H88B5SlyiFIqemCOIss0SxlCFs69LmfRYvPPvPEhoXtQ3ZThe0UvKG83GOklhvGl6OaiRf4Mt+m8zOT4Wox/j6aOBK6cw6qKCdmD+Yj1rrNqFGg1CnSWMoD6S6mwNgkzwdBUJZ22BwrzAAo4RHa2Uy3ef1FjwD0XtU5N3uDSxGGBEDvOe5z82rps3E22FpAA8eYl8kaXtmWqyvYU0epp4brGuTxCuBMCAsxt/OjIjeNNQbBGkwxgfYA0="
+
+const pemCRLBase64 = "LS0tLS1CRUdJTiBYNTA5IENSTC0tLS0tDQpNSUlCOWpDQ0FWOENBUUV3RFFZSktvWklodmNOQVFFRkJRQXdiREVhTUJnR0ExVUVDaE1SVWxOQklGTmxZM1Z5DQphWFI1SUVsdVl5NHhIakFjQmdOVkJBTVRGVkpUUVNCUWRXSnNhV01nVW05dmRDQkRRU0IyTVRFdU1Dd0dDU3FHDQpTSWIzRFFFSkFSWWZjbk5oYTJWdmJuSnZiM1J6YVdkdVFISnpZWE5sWTNWeWFYUjVMbU52YlJjTk1URXdNakl6DQpNVGt5T0RNd1doY05NVEV3T0RJeU1Ua3lPRE13V2pDQmpEQktBaEVBckRxb2g5RkhKSFhUN09QZ3V1bjQrQmNODQpNRGt4TVRBeU1UUXlOekE1V2pBbU1Bb0dBMVVkRlFRRENnRUpNQmdHQTFVZEdBUVJHQTh5TURBNU1URXdNakUwDQpNalExTlZvd1BnSVJBTEd6blowOTVQQjVhQU9MUGc1N2ZNTVhEVEF5TVRBeU16RTBOVEF4TkZvd0dqQVlCZ05WDQpIUmdFRVJnUE1qQXdNakV3TWpNeE5EVXdNVFJhb0RBd0xqQWZCZ05WSFNNRUdEQVdnQlQxVERGNlVRTS9MTmVMDQpsNWx2cUhHUXEzZzltekFMQmdOVkhSUUVCQUlDQUlRd0RRWUpLb1pJaHZjTkFRRUZCUUFEZ1lFQUZVNUFzNk16DQpxNVBSc2lmYW9iUVBHaDFhSkx5QytNczVBZ2MwYld5QTNHQWR4dXI1U3BQWmVSV0NCamlQL01FSEJXSkNsQkhQDQpHUmNxNXlJZDNFakRrYUV5eFJhK2k2N0x6dmhJNmMyOUVlNks5cFNZd2ppLzdSVWhtbW5Qclh0VHhsTDBsckxyDQptUVFKNnhoRFJhNUczUUE0Q21VZHNITnZicnpnbUNZcHZWRT0NCi0tLS0tRU5EIFg1MDkgQ1JMLS0tLS0NCg0K"
+
+func TestCreateCertificateRequest(t *testing.T) {
+	random := rand.Reader
+
+	block, _ := pem.Decode([]byte(pemPrivateKey))
+	rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes)
+	if err != nil {
+		t.Fatalf("Failed to parse private key: %s", err)
+	}
+
+	ecdsa256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		t.Fatalf("Failed to generate ECDSA key: %s", err)
+	}
+
+	ecdsa384Priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
+	if err != nil {
+		t.Fatalf("Failed to generate ECDSA key: %s", err)
+	}
+
+	ecdsa521Priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
+	if err != nil {
+		t.Fatalf("Failed to generate ECDSA key: %s", err)
+	}
+
+	tests := []struct {
+		name    string
+		priv    interface{}
+		sigAlgo SignatureAlgorithm
+	}{
+		{"RSA", rsaPriv, SHA1WithRSA},
+		{"ECDSA-256", ecdsa256Priv, ECDSAWithSHA1},
+		{"ECDSA-384", ecdsa384Priv, ECDSAWithSHA1},
+		{"ECDSA-521", ecdsa521Priv, ECDSAWithSHA1},
+	}
+
+	for _, test := range tests {
+		template := CertificateRequest{
+			Subject: pkix.Name{
+				CommonName:   "test.example.com",
+				Organization: []string{"Σ Acme Co"},
+			},
+			SignatureAlgorithm: test.sigAlgo,
+			DNSNames:           []string{"test.example.com"},
+			EmailAddresses:     []string{"gopher@golang.org"},
+			IPAddresses:        []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
+		}
+
+		derBytes, err := CreateCertificateRequest(random, &template, test.priv)
+		if err != nil {
+			t.Errorf("%s: failed to create certificate request: %s", test.name, err)
+			continue
+		}
+
+		out, err := ParseCertificateRequest(derBytes)
+		if err != nil {
+			t.Errorf("%s: failed to create certificate request: %s", test.name, err)
+			continue
+		}
+
+		if out.Subject.CommonName != template.Subject.CommonName {
+			t.Errorf("%s: output subject common name and template subject common name don't match", test.name)
+		} else if len(out.Subject.Organization) != len(template.Subject.Organization) {
+			t.Errorf("%s: output subject organisation and template subject organisation don't match", test.name)
+		} else if len(out.DNSNames) != len(template.DNSNames) {
+			t.Errorf("%s: output DNS names and template DNS names don't match", test.name)
+		} else if len(out.EmailAddresses) != len(template.EmailAddresses) {
+			t.Errorf("%s: output email addresses and template email addresses don't match", test.name)
+		} else if len(out.IPAddresses) != len(template.IPAddresses) {
+			t.Errorf("%s: output IP addresses and template IP addresses names don't match", test.name)
+		}
+	}
+}
+
+func marshalAndParseCSR(t *testing.T, template *CertificateRequest) *CertificateRequest {
+	block, _ := pem.Decode([]byte(pemPrivateKey))
+	rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	derBytes, err := CreateCertificateRequest(rand.Reader, template, rsaPriv)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	csr, err := ParseCertificateRequest(derBytes)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	return csr
+}
+
+func TestCertificateRequestOverrides(t *testing.T) {
+	sanContents, err := marshalSANs([]string{"foo.example.com"}, nil, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	template := CertificateRequest{
+		Subject: pkix.Name{
+			CommonName:   "test.example.com",
+			Organization: []string{"Σ Acme Co"},
+		},
+		DNSNames: []string{"test.example.com"},
+
+		// An explicit extension should override the DNSNames from the
+		// template.
+		ExtraExtensions: []pkix.Extension{
+			pkix.Extension{
+				Id:    oidExtensionSubjectAltName,
+				Value: sanContents,
+			},
+		},
+	}
+
+	csr := marshalAndParseCSR(t, &template)
+
+	if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "foo.example.com" {
+		t.Errorf("Extension did not override template. Got %v\n", csr.DNSNames)
+	}
+
+	// If there is already an attribute with X.509 extensions then the
+	// extra extensions should be added to it rather than creating a CSR
+	// with two extension attributes.
+
+	template.Attributes = []pkix.AttributeTypeAndValueSET{
+		pkix.AttributeTypeAndValueSET{
+			Type: oidExtensionRequest,
+			Value: [][]pkix.AttributeTypeAndValue{
+				[]pkix.AttributeTypeAndValue{
+					pkix.AttributeTypeAndValue{
+						Type:  oidExtensionAuthorityInfoAccess,
+						Value: []byte("foo"),
+					},
+				},
+			},
+		},
+	}
+
+	csr = marshalAndParseCSR(t, &template)
+	if l := len(csr.Attributes); l != 1 {
+		t.Errorf("incorrect number of attributes: %d\n", l)
+	}
+
+	if !csr.Attributes[0].Type.Equal(oidExtensionRequest) ||
+		len(csr.Attributes[0].Value) != 1 ||
+		len(csr.Attributes[0].Value[0]) != 2 {
+		t.Errorf("bad attributes: %#v\n", csr.Attributes)
+	}
+
+	sanContents2, err := marshalSANs([]string{"foo2.example.com"}, nil, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Extensions in Attributes should override those in ExtraExtensions.
+	template.Attributes[0].Value[0] = append(template.Attributes[0].Value[0], pkix.AttributeTypeAndValue{
+		Type:  oidExtensionSubjectAltName,
+		Value: sanContents2,
+	})
+
+	csr = marshalAndParseCSR(t, &template)
+
+	if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "foo2.example.com" {
+		t.Errorf("Attributes did not override ExtraExtensions. Got %v\n", csr.DNSNames)
+	}
+}
+
+func TestParseCertificateRequest(t *testing.T) {
+	csrBytes := fromBase64(csrBase64)
+	csr, err := ParseCertificateRequest(csrBytes)
+	if err != nil {
+		t.Fatalf("failed to parse CSR: %s", err)
+	}
+
+	if len(csr.EmailAddresses) != 1 || csr.EmailAddresses[0] != "gopher@golang.org" {
+		t.Errorf("incorrect email addresses found: %v", csr.EmailAddresses)
+	}
+
+	if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "test.example.com" {
+		t.Errorf("incorrect DNS names found: %v", csr.DNSNames)
+	}
+
+	if len(csr.Subject.Country) != 1 || csr.Subject.Country[0] != "AU" {
+		t.Errorf("incorrect Subject name: %v", csr.Subject)
+	}
+
+	found := false
+	for _, e := range csr.Extensions {
+		if e.Id.Equal(oidExtensionBasicConstraints) {
+			found = true
+			break
+		}
+	}
+	if !found {
+		t.Errorf("basic constraints extension not found in CSR")
+	}
+}
+
+// This CSR was generated with OpenSSL:
+//  openssl req -out CSR.csr -new -newkey rsa:2048 -nodes -keyout privateKey.key -config openssl.cnf
+//
+// The openssl.cnf needs to include this section:
+//   [ v3_req ]
+//   basicConstraints = CA:FALSE
+//   keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+//   subjectAltName = email:gopher@golang.org,DNS:test.example.com
+const csrBase64 = "MIIC4zCCAcsCAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOY+MVedRg2JEnyeLcSzcsMv2VcsTfkB5+Etd6hihAh6MrGezNyASMMKuQN6YhCX1icQDiQtGsDLTtheNnSXK06tAhHjAP/hGlszRJp+5+rP2M58fDBAkUBEhskbCUWwpY14jFtVuGNJ8vF8h8IeczdolvQhX9lVai9G0EUXJMliMKdjA899H0mRs9PzHyidyrXFNiZlQXfD8Kg7gETn2Ny965iyI6ujAIYSCvam6TnxRHYH2MBKyVGvsYGbPYUQJCsgdgyajEg6ekihvQY3SzO1HSAlZAd7d1QYO4VeWJ2mY6Wu3Jpmh+AmG19S9CcHqGjd0bhuAX9cpPOKgnEmqn0CAwEAAaBZMFcGCSqGSIb3DQEJDjFKMEgwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwLgYDVR0RBCcwJYERZ29waGVyQGdvbGFuZy5vcmeCEHRlc3QuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADggEBAC9+QpKfdabxwCWwf4IEe1cKjdXLS1ScSuw27a3kZzQiPV78WJMa6dB8dqhdH5BRwGZ/qsgLrO6ZHlNeIv2Ib41Ccq71ecHW/nXc94A1BzJ/bVdI9LZcmTUvR1/m1jCpN7UqQ0ml1u9VihK7Pe762hEYxuWDQzYEU0l15S/bXmqeq3eF1A59XT/2jwe5+NV0Wwf4UQlkTXsAQMsJ+KzrQafd8Qv2A49o048uRvmjeJDrXLawGVianZ7D5A6Fpd1rZh6XcjqBpmgLw41DRQWENOdzhy+HyphKRv1MlY8OLkNqpGMhu8DdgJVGoT16DGiickoEa7Z3UCPVNgdTkT9jq7U="
diff --git a/third_party/gofrontend/libgo/go/crypto/x509/x509_test_import.go b/third_party/gofrontend/libgo/go/crypto/x509/x509_test_import.go
new file mode 100644
index 0000000..3fda7da
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/crypto/x509/x509_test_import.go
@@ -0,0 +1,53 @@
+// Copyright 2013 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.
+
+// +build ignore
+
+// This file is run by the x509 tests to ensure that a program with minimal
+// imports can sign certificates without errors resulting from missing hash
+// functions.
+package main
+
+import (
+	"crypto/rand"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"math/big"
+	"time"
+)
+
+func main() {
+	block, _ := pem.Decode([]byte(pemPrivateKey))
+	rsaPriv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
+	if err != nil {
+		panic("Failed to parse private key: " + err.Error())
+	}
+
+	template := x509.Certificate{
+		SerialNumber: big.NewInt(1),
+		Subject: pkix.Name{
+			CommonName:   "test",
+			Organization: []string{"Σ Acme Co"},
+		},
+		NotBefore: time.Unix(1000, 0),
+		NotAfter:  time.Unix(100000, 0),
+		KeyUsage:  x509.KeyUsageCertSign,
+	}
+
+	if _, err = x509.CreateCertificate(rand.Reader, &template, &template, &rsaPriv.PublicKey, rsaPriv); err != nil {
+		panic("failed to create certificate with basic imports: " + err.Error())
+	}
+}
+
+var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
+MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
+fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
+/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
+RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
+EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
+IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
+tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
+-----END RSA PRIVATE KEY-----
+`
diff --git a/third_party/gofrontend/libgo/go/database/sql/convert.go b/third_party/gofrontend/libgo/go/database/sql/convert.go
new file mode 100644
index 0000000..c0b38a2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/database/sql/convert.go
@@ -0,0 +1,299 @@
+// 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.
+
+// Type conversions for Scan.
+
+package sql
+
+import (
+	"database/sql/driver"
+	"errors"
+	"fmt"
+	"reflect"
+	"strconv"
+)
+
+var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
+
+// driverArgs converts arguments from callers of Stmt.Exec and
+// Stmt.Query into driver Values.
+//
+// The statement ds may be nil, if no statement is available.
+func driverArgs(ds *driverStmt, args []interface{}) ([]driver.Value, error) {
+	dargs := make([]driver.Value, len(args))
+	var si driver.Stmt
+	if ds != nil {
+		si = ds.si
+	}
+	cc, ok := si.(driver.ColumnConverter)
+
+	// Normal path, for a driver.Stmt that is not a ColumnConverter.
+	if !ok {
+		for n, arg := range args {
+			var err error
+			dargs[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
+			if err != nil {
+				return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
+			}
+		}
+		return dargs, nil
+	}
+
+	// Let the Stmt convert its own arguments.
+	for n, arg := range args {
+		// First, see if the value itself knows how to convert
+		// itself to a driver type.  For example, a NullString
+		// struct changing into a string or nil.
+		if svi, ok := arg.(driver.Valuer); ok {
+			sv, err := svi.Value()
+			if err != nil {
+				return nil, fmt.Errorf("sql: argument index %d from Value: %v", n, err)
+			}
+			if !driver.IsValue(sv) {
+				return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from Value", n, sv)
+			}
+			arg = sv
+		}
+
+		// Second, ask the column to sanity check itself. For
+		// example, drivers might use this to make sure that
+		// an int64 values being inserted into a 16-bit
+		// integer field is in range (before getting
+		// truncated), or that a nil can't go into a NOT NULL
+		// column before going across the network to get the
+		// same error.
+		var err error
+		ds.Lock()
+		dargs[n], err = cc.ColumnConverter(n).ConvertValue(arg)
+		ds.Unlock()
+		if err != nil {
+			return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n, err)
+		}
+		if !driver.IsValue(dargs[n]) {
+			return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T",
+				arg, dargs[n])
+		}
+	}
+
+	return dargs, nil
+}
+
+// convertAssign copies to dest the value in src, converting it if possible.
+// An error is returned if the copy would result in loss of information.
+// dest should be a pointer type.
+func convertAssign(dest, src interface{}) error {
+	// Common cases, without reflect.
+	switch s := src.(type) {
+	case string:
+		switch d := dest.(type) {
+		case *string:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = s
+			return nil
+		case *[]byte:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = []byte(s)
+			return nil
+		}
+	case []byte:
+		switch d := dest.(type) {
+		case *string:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = string(s)
+			return nil
+		case *interface{}:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = cloneBytes(s)
+			return nil
+		case *[]byte:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = cloneBytes(s)
+			return nil
+		case *RawBytes:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = s
+			return nil
+		}
+	case nil:
+		switch d := dest.(type) {
+		case *interface{}:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = nil
+			return nil
+		case *[]byte:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = nil
+			return nil
+		case *RawBytes:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = nil
+			return nil
+		}
+	}
+
+	var sv reflect.Value
+
+	switch d := dest.(type) {
+	case *string:
+		sv = reflect.ValueOf(src)
+		switch sv.Kind() {
+		case reflect.Bool,
+			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+			reflect.Float32, reflect.Float64:
+			*d = asString(src)
+			return nil
+		}
+	case *[]byte:
+		sv = reflect.ValueOf(src)
+		if b, ok := asBytes(nil, sv); ok {
+			*d = b
+			return nil
+		}
+	case *RawBytes:
+		sv = reflect.ValueOf(src)
+		if b, ok := asBytes([]byte(*d)[:0], sv); ok {
+			*d = RawBytes(b)
+			return nil
+		}
+	case *bool:
+		bv, err := driver.Bool.ConvertValue(src)
+		if err == nil {
+			*d = bv.(bool)
+		}
+		return err
+	case *interface{}:
+		*d = src
+		return nil
+	}
+
+	if scanner, ok := dest.(Scanner); ok {
+		return scanner.Scan(src)
+	}
+
+	dpv := reflect.ValueOf(dest)
+	if dpv.Kind() != reflect.Ptr {
+		return errors.New("destination not a pointer")
+	}
+	if dpv.IsNil() {
+		return errNilPtr
+	}
+
+	if !sv.IsValid() {
+		sv = reflect.ValueOf(src)
+	}
+
+	dv := reflect.Indirect(dpv)
+	if dv.Kind() == sv.Kind() {
+		dv.Set(sv)
+		return nil
+	}
+
+	switch dv.Kind() {
+	case reflect.Ptr:
+		if src == nil {
+			dv.Set(reflect.Zero(dv.Type()))
+			return nil
+		} else {
+			dv.Set(reflect.New(dv.Type().Elem()))
+			return convertAssign(dv.Interface(), src)
+		}
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		s := asString(src)
+		i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
+		if err != nil {
+			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+		}
+		dv.SetInt(i64)
+		return nil
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		s := asString(src)
+		u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
+		if err != nil {
+			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+		}
+		dv.SetUint(u64)
+		return nil
+	case reflect.Float32, reflect.Float64:
+		s := asString(src)
+		f64, err := strconv.ParseFloat(s, dv.Type().Bits())
+		if err != nil {
+			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+		}
+		dv.SetFloat(f64)
+		return nil
+	}
+
+	return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
+}
+
+func cloneBytes(b []byte) []byte {
+	if b == nil {
+		return nil
+	} else {
+		c := make([]byte, len(b))
+		copy(c, b)
+		return c
+	}
+}
+
+func asString(src interface{}) string {
+	switch v := src.(type) {
+	case string:
+		return v
+	case []byte:
+		return string(v)
+	}
+	rv := reflect.ValueOf(src)
+	switch rv.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return strconv.FormatInt(rv.Int(), 10)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		return strconv.FormatUint(rv.Uint(), 10)
+	case reflect.Float64:
+		return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
+	case reflect.Float32:
+		return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
+	case reflect.Bool:
+		return strconv.FormatBool(rv.Bool())
+	}
+	return fmt.Sprintf("%v", src)
+}
+
+func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
+	switch rv.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return strconv.AppendInt(buf, rv.Int(), 10), true
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		return strconv.AppendUint(buf, rv.Uint(), 10), true
+	case reflect.Float32:
+		return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true
+	case reflect.Float64:
+		return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true
+	case reflect.Bool:
+		return strconv.AppendBool(buf, rv.Bool()), true
+	case reflect.String:
+		s := rv.String()
+		return append(buf, s...), true
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/database/sql/convert_test.go b/third_party/gofrontend/libgo/go/database/sql/convert_test.go
new file mode 100644
index 0000000..6e24830
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/database/sql/convert_test.go
@@ -0,0 +1,337 @@
+// 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.
+
+package sql
+
+import (
+	"database/sql/driver"
+	"fmt"
+	"reflect"
+	"runtime"
+	"testing"
+	"time"
+)
+
+var someTime = time.Unix(123, 0)
+var answer int64 = 42
+
+type conversionTest struct {
+	s, d interface{} // source and destination
+
+	// following are used if they're non-zero
+	wantint   int64
+	wantuint  uint64
+	wantstr   string
+	wantbytes []byte
+	wantraw   RawBytes
+	wantf32   float32
+	wantf64   float64
+	wanttime  time.Time
+	wantbool  bool // used if d is of type *bool
+	wanterr   string
+	wantiface interface{}
+	wantptr   *int64 // if non-nil, *d's pointed value must be equal to *wantptr
+	wantnil   bool   // if true, *d must be *int64(nil)
+}
+
+// Target variables for scanning into.
+var (
+	scanstr    string
+	scanbytes  []byte
+	scanraw    RawBytes
+	scanint    int
+	scanint8   int8
+	scanint16  int16
+	scanint32  int32
+	scanuint8  uint8
+	scanuint16 uint16
+	scanbool   bool
+	scanf32    float32
+	scanf64    float64
+	scantime   time.Time
+	scanptr    *int64
+	scaniface  interface{}
+)
+
+var conversionTests = []conversionTest{
+	// Exact conversions (destination pointer type matches source type)
+	{s: "foo", d: &scanstr, wantstr: "foo"},
+	{s: 123, d: &scanint, wantint: 123},
+	{s: someTime, d: &scantime, wanttime: someTime},
+
+	// To strings
+	{s: "string", d: &scanstr, wantstr: "string"},
+	{s: []byte("byteslice"), d: &scanstr, wantstr: "byteslice"},
+	{s: 123, d: &scanstr, wantstr: "123"},
+	{s: int8(123), d: &scanstr, wantstr: "123"},
+	{s: int64(123), d: &scanstr, wantstr: "123"},
+	{s: uint8(123), d: &scanstr, wantstr: "123"},
+	{s: uint16(123), d: &scanstr, wantstr: "123"},
+	{s: uint32(123), d: &scanstr, wantstr: "123"},
+	{s: uint64(123), d: &scanstr, wantstr: "123"},
+	{s: 1.5, d: &scanstr, wantstr: "1.5"},
+
+	// To []byte
+	{s: nil, d: &scanbytes, wantbytes: nil},
+	{s: "string", d: &scanbytes, wantbytes: []byte("string")},
+	{s: []byte("byteslice"), d: &scanbytes, wantbytes: []byte("byteslice")},
+	{s: 123, d: &scanbytes, wantbytes: []byte("123")},
+	{s: int8(123), d: &scanbytes, wantbytes: []byte("123")},
+	{s: int64(123), d: &scanbytes, wantbytes: []byte("123")},
+	{s: uint8(123), d: &scanbytes, wantbytes: []byte("123")},
+	{s: uint16(123), d: &scanbytes, wantbytes: []byte("123")},
+	{s: uint32(123), d: &scanbytes, wantbytes: []byte("123")},
+	{s: uint64(123), d: &scanbytes, wantbytes: []byte("123")},
+	{s: 1.5, d: &scanbytes, wantbytes: []byte("1.5")},
+
+	// To RawBytes
+	{s: nil, d: &scanraw, wantraw: nil},
+	{s: []byte("byteslice"), d: &scanraw, wantraw: RawBytes("byteslice")},
+	{s: 123, d: &scanraw, wantraw: RawBytes("123")},
+	{s: int8(123), d: &scanraw, wantraw: RawBytes("123")},
+	{s: int64(123), d: &scanraw, wantraw: RawBytes("123")},
+	{s: uint8(123), d: &scanraw, wantraw: RawBytes("123")},
+	{s: uint16(123), d: &scanraw, wantraw: RawBytes("123")},
+	{s: uint32(123), d: &scanraw, wantraw: RawBytes("123")},
+	{s: uint64(123), d: &scanraw, wantraw: RawBytes("123")},
+	{s: 1.5, d: &scanraw, wantraw: RawBytes("1.5")},
+
+	// Strings to integers
+	{s: "255", d: &scanuint8, wantuint: 255},
+	{s: "256", d: &scanuint8, wanterr: `converting string "256" to a uint8: strconv.ParseUint: parsing "256": value out of range`},
+	{s: "256", d: &scanuint16, wantuint: 256},
+	{s: "-1", d: &scanint, wantint: -1},
+	{s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: strconv.ParseInt: parsing "foo": invalid syntax`},
+
+	// True bools
+	{s: true, d: &scanbool, wantbool: true},
+	{s: "True", d: &scanbool, wantbool: true},
+	{s: "TRUE", d: &scanbool, wantbool: true},
+	{s: "1", d: &scanbool, wantbool: true},
+	{s: 1, d: &scanbool, wantbool: true},
+	{s: int64(1), d: &scanbool, wantbool: true},
+	{s: uint16(1), d: &scanbool, wantbool: true},
+
+	// False bools
+	{s: false, d: &scanbool, wantbool: false},
+	{s: "false", d: &scanbool, wantbool: false},
+	{s: "FALSE", d: &scanbool, wantbool: false},
+	{s: "0", d: &scanbool, wantbool: false},
+	{s: 0, d: &scanbool, wantbool: false},
+	{s: int64(0), d: &scanbool, wantbool: false},
+	{s: uint16(0), d: &scanbool, wantbool: false},
+
+	// Not bools
+	{s: "yup", d: &scanbool, wanterr: `sql/driver: couldn't convert "yup" into type bool`},
+	{s: 2, d: &scanbool, wanterr: `sql/driver: couldn't convert 2 into type bool`},
+
+	// Floats
+	{s: float64(1.5), d: &scanf64, wantf64: float64(1.5)},
+	{s: int64(1), d: &scanf64, wantf64: float64(1)},
+	{s: float64(1.5), d: &scanf32, wantf32: float32(1.5)},
+	{s: "1.5", d: &scanf32, wantf32: float32(1.5)},
+	{s: "1.5", d: &scanf64, wantf64: float64(1.5)},
+
+	// Pointers
+	{s: interface{}(nil), d: &scanptr, wantnil: true},
+	{s: int64(42), d: &scanptr, wantptr: &answer},
+
+	// To interface{}
+	{s: float64(1.5), d: &scaniface, wantiface: float64(1.5)},
+	{s: int64(1), d: &scaniface, wantiface: int64(1)},
+	{s: "str", d: &scaniface, wantiface: "str"},
+	{s: []byte("byteslice"), d: &scaniface, wantiface: []byte("byteslice")},
+	{s: true, d: &scaniface, wantiface: true},
+	{s: nil, d: &scaniface},
+	{s: []byte(nil), d: &scaniface, wantiface: []byte(nil)},
+}
+
+func intPtrValue(intptr interface{}) interface{} {
+	return reflect.Indirect(reflect.Indirect(reflect.ValueOf(intptr))).Int()
+}
+
+func intValue(intptr interface{}) int64 {
+	return reflect.Indirect(reflect.ValueOf(intptr)).Int()
+}
+
+func uintValue(intptr interface{}) uint64 {
+	return reflect.Indirect(reflect.ValueOf(intptr)).Uint()
+}
+
+func float64Value(ptr interface{}) float64 {
+	return *(ptr.(*float64))
+}
+
+func float32Value(ptr interface{}) float32 {
+	return *(ptr.(*float32))
+}
+
+func timeValue(ptr interface{}) time.Time {
+	return *(ptr.(*time.Time))
+}
+
+func TestConversions(t *testing.T) {
+	for n, ct := range conversionTests {
+		err := convertAssign(ct.d, ct.s)
+		errstr := ""
+		if err != nil {
+			errstr = err.Error()
+		}
+		errf := func(format string, args ...interface{}) {
+			base := fmt.Sprintf("convertAssign #%d: for %v (%T) -> %T, ", n, ct.s, ct.s, ct.d)
+			t.Errorf(base+format, args...)
+		}
+		if errstr != ct.wanterr {
+			errf("got error %q, want error %q", errstr, ct.wanterr)
+		}
+		if ct.wantstr != "" && ct.wantstr != scanstr {
+			errf("want string %q, got %q", ct.wantstr, scanstr)
+		}
+		if ct.wantint != 0 && ct.wantint != intValue(ct.d) {
+			errf("want int %d, got %d", ct.wantint, intValue(ct.d))
+		}
+		if ct.wantuint != 0 && ct.wantuint != uintValue(ct.d) {
+			errf("want uint %d, got %d", ct.wantuint, uintValue(ct.d))
+		}
+		if ct.wantf32 != 0 && ct.wantf32 != float32Value(ct.d) {
+			errf("want float32 %v, got %v", ct.wantf32, float32Value(ct.d))
+		}
+		if ct.wantf64 != 0 && ct.wantf64 != float64Value(ct.d) {
+			errf("want float32 %v, got %v", ct.wantf64, float64Value(ct.d))
+		}
+		if bp, boolTest := ct.d.(*bool); boolTest && *bp != ct.wantbool && ct.wanterr == "" {
+			errf("want bool %v, got %v", ct.wantbool, *bp)
+		}
+		if !ct.wanttime.IsZero() && !ct.wanttime.Equal(timeValue(ct.d)) {
+			errf("want time %v, got %v", ct.wanttime, timeValue(ct.d))
+		}
+		if ct.wantnil && *ct.d.(**int64) != nil {
+			errf("want nil, got %v", intPtrValue(ct.d))
+		}
+		if ct.wantptr != nil {
+			if *ct.d.(**int64) == nil {
+				errf("want pointer to %v, got nil", *ct.wantptr)
+			} else if *ct.wantptr != intPtrValue(ct.d) {
+				errf("want pointer to %v, got %v", *ct.wantptr, intPtrValue(ct.d))
+			}
+		}
+		if ifptr, ok := ct.d.(*interface{}); ok {
+			if !reflect.DeepEqual(ct.wantiface, scaniface) {
+				errf("want interface %#v, got %#v", ct.wantiface, scaniface)
+				continue
+			}
+			if srcBytes, ok := ct.s.([]byte); ok {
+				dstBytes := (*ifptr).([]byte)
+				if len(srcBytes) > 0 && &dstBytes[0] == &srcBytes[0] {
+					errf("copy into interface{} didn't copy []byte data")
+				}
+			}
+		}
+	}
+}
+
+func TestNullString(t *testing.T) {
+	var ns NullString
+	convertAssign(&ns, []byte("foo"))
+	if !ns.Valid {
+		t.Errorf("expecting not null")
+	}
+	if ns.String != "foo" {
+		t.Errorf("expecting foo; got %q", ns.String)
+	}
+	convertAssign(&ns, nil)
+	if ns.Valid {
+		t.Errorf("expecting null on nil")
+	}
+	if ns.String != "" {
+		t.Errorf("expecting blank on nil; got %q", ns.String)
+	}
+}
+
+type valueConverterTest struct {
+	c       driver.ValueConverter
+	in, out interface{}
+	err     string
+}
+
+var valueConverterTests = []valueConverterTest{
+	{driver.DefaultParameterConverter, NullString{"hi", true}, "hi", ""},
+	{driver.DefaultParameterConverter, NullString{"", false}, nil, ""},
+}
+
+func TestValueConverters(t *testing.T) {
+	for i, tt := range valueConverterTests {
+		out, err := tt.c.ConvertValue(tt.in)
+		goterr := ""
+		if err != nil {
+			goterr = err.Error()
+		}
+		if goterr != tt.err {
+			t.Errorf("test %d: %T(%T(%v)) error = %q; want error = %q",
+				i, tt.c, tt.in, tt.in, goterr, tt.err)
+		}
+		if tt.err != "" {
+			continue
+		}
+		if !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("test %d: %T(%T(%v)) = %v (%T); want %v (%T)",
+				i, tt.c, tt.in, tt.in, out, out, tt.out, tt.out)
+		}
+	}
+}
+
+// Tests that assigning to RawBytes doesn't allocate (and also works).
+func TestRawBytesAllocs(t *testing.T) {
+	buf := make(RawBytes, 10)
+	test := func(name string, in interface{}, want string) {
+		if err := convertAssign(&buf, in); err != nil {
+			t.Fatalf("%s: convertAssign = %v", name, err)
+		}
+		match := len(buf) == len(want)
+		if match {
+			for i, b := range buf {
+				if want[i] != b {
+					match = false
+					break
+				}
+			}
+		}
+		if !match {
+			t.Fatalf("%s: got %q (len %d); want %q (len %d)", name, buf, len(buf), want, len(want))
+		}
+	}
+	n := testing.AllocsPerRun(100, func() {
+		test("uint64", uint64(12345678), "12345678")
+		test("uint32", uint32(1234), "1234")
+		test("uint16", uint16(12), "12")
+		test("uint8", uint8(1), "1")
+		test("uint", uint(123), "123")
+		test("int", int(123), "123")
+		test("int8", int8(1), "1")
+		test("int16", int16(12), "12")
+		test("int32", int32(1234), "1234")
+		test("int64", int64(12345678), "12345678")
+		test("float32", float32(1.5), "1.5")
+		test("float64", float64(64), "64")
+		test("bool", false, "false")
+	})
+
+	// The numbers below are only valid for 64-bit interface word sizes,
+	// and gc. With 32-bit words there are more convT2E allocs, and
+	// with gccgo, only pointers currently go in interface data.
+	// So only care on amd64 gc for now.
+	measureAllocs := runtime.GOARCH == "amd64" && runtime.Compiler == "gc"
+
+	if n > 0.5 && measureAllocs {
+		t.Fatalf("allocs = %v; want 0", n)
+	}
+
+	// This one involves a convT2E allocation, string -> interface{}
+	n = testing.AllocsPerRun(100, func() {
+		test("string", "foo", "foo")
+	})
+	if n > 1.5 && measureAllocs {
+		t.Fatalf("allocs = %v; want max 1", n)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/database/sql/driver/driver.go b/third_party/gofrontend/libgo/go/database/sql/driver/driver.go
new file mode 100644
index 0000000..eca25f2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/database/sql/driver/driver.go
@@ -0,0 +1,211 @@
+// 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.
+
+// Package driver defines interfaces to be implemented by database
+// drivers as used by package sql.
+//
+// Most code should use package sql.
+package driver
+
+import "errors"
+
+// Value is a value that drivers must be able to handle.
+// It is either nil or an instance of one of these types:
+//
+//   int64
+//   float64
+//   bool
+//   []byte
+//   string   [*] everywhere except from Rows.Next.
+//   time.Time
+type Value interface{}
+
+// Driver is the interface that must be implemented by a database
+// driver.
+type Driver interface {
+	// Open returns a new connection to the database.
+	// The name is a string in a driver-specific format.
+	//
+	// Open may return a cached connection (one previously
+	// closed), but doing so is unnecessary; the sql package
+	// maintains a pool of idle connections for efficient re-use.
+	//
+	// The returned connection is only used by one goroutine at a
+	// time.
+	Open(name string) (Conn, error)
+}
+
+// ErrSkip may be returned by some optional interfaces' methods to
+// indicate at runtime that the fast path is unavailable and the sql
+// package should continue as if the optional interface was not
+// implemented. ErrSkip is only supported where explicitly
+// documented.
+var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented")
+
+// ErrBadConn should be returned by a driver to signal to the sql
+// package that a driver.Conn is in a bad state (such as the server
+// having earlier closed the connection) and the sql package should
+// retry on a new connection.
+//
+// To prevent duplicate operations, ErrBadConn should NOT be returned
+// if there's a possibility that the database server might have
+// performed the operation. Even if the server sends back an error,
+// you shouldn't return ErrBadConn.
+var ErrBadConn = errors.New("driver: bad connection")
+
+// Execer is an optional interface that may be implemented by a Conn.
+//
+// If a Conn does not implement Execer, the sql package's DB.Exec will
+// first prepare a query, execute the statement, and then close the
+// statement.
+//
+// Exec may return ErrSkip.
+type Execer interface {
+	Exec(query string, args []Value) (Result, error)
+}
+
+// Queryer is an optional interface that may be implemented by a Conn.
+//
+// If a Conn does not implement Queryer, the sql package's DB.Query will
+// first prepare a query, execute the statement, and then close the
+// statement.
+//
+// Query may return ErrSkip.
+type Queryer interface {
+	Query(query string, args []Value) (Rows, error)
+}
+
+// Conn is a connection to a database. It is not used concurrently
+// by multiple goroutines.
+//
+// Conn is assumed to be stateful.
+type Conn interface {
+	// Prepare returns a prepared statement, bound to this connection.
+	Prepare(query string) (Stmt, error)
+
+	// Close invalidates and potentially stops any current
+	// prepared statements and transactions, marking this
+	// connection as no longer in use.
+	//
+	// Because the sql package maintains a free pool of
+	// connections and only calls Close when there's a surplus of
+	// idle connections, it shouldn't be necessary for drivers to
+	// do their own connection caching.
+	Close() error
+
+	// Begin starts and returns a new transaction.
+	Begin() (Tx, error)
+}
+
+// Result is the result of a query execution.
+type Result interface {
+	// LastInsertId returns the database's auto-generated ID
+	// after, for example, an INSERT into a table with primary
+	// key.
+	LastInsertId() (int64, error)
+
+	// RowsAffected returns the number of rows affected by the
+	// query.
+	RowsAffected() (int64, error)
+}
+
+// Stmt is a prepared statement. It is bound to a Conn and not
+// used by multiple goroutines concurrently.
+type Stmt interface {
+	// Close closes the statement.
+	//
+	// As of Go 1.1, a Stmt will not be closed if it's in use
+	// by any queries.
+	Close() error
+
+	// NumInput returns the number of placeholder parameters.
+	//
+	// If NumInput returns >= 0, the sql package will sanity check
+	// argument counts from callers and return errors to the caller
+	// before the statement's Exec or Query methods are called.
+	//
+	// NumInput may also return -1, if the driver doesn't know
+	// its number of placeholders. In that case, the sql package
+	// will not sanity check Exec or Query argument counts.
+	NumInput() int
+
+	// Exec executes a query that doesn't return rows, such
+	// as an INSERT or UPDATE.
+	Exec(args []Value) (Result, error)
+
+	// Query executes a query that may return rows, such as a
+	// SELECT.
+	Query(args []Value) (Rows, error)
+}
+
+// ColumnConverter may be optionally implemented by Stmt if the
+// statement is aware of its own columns' types and can convert from
+// any type to a driver Value.
+type ColumnConverter interface {
+	// ColumnConverter returns a ValueConverter for the provided
+	// column index.  If the type of a specific column isn't known
+	// or shouldn't be handled specially, DefaultValueConverter
+	// can be returned.
+	ColumnConverter(idx int) ValueConverter
+}
+
+// Rows is an iterator over an executed query's results.
+type Rows interface {
+	// Columns returns the names of the columns. The number of
+	// columns of the result is inferred from the length of the
+	// slice.  If a particular column name isn't known, an empty
+	// string should be returned for that entry.
+	Columns() []string
+
+	// Close closes the rows iterator.
+	Close() error
+
+	// Next is called to populate the next row of data into
+	// the provided slice. The provided slice will be the same
+	// size as the Columns() are wide.
+	//
+	// The dest slice may be populated only with
+	// a driver Value type, but excluding string.
+	// All string values must be converted to []byte.
+	//
+	// Next should return io.EOF when there are no more rows.
+	Next(dest []Value) error
+}
+
+// Tx is a transaction.
+type Tx interface {
+	Commit() error
+	Rollback() error
+}
+
+// RowsAffected implements Result for an INSERT or UPDATE operation
+// which mutates a number of rows.
+type RowsAffected int64
+
+var _ Result = RowsAffected(0)
+
+func (RowsAffected) LastInsertId() (int64, error) {
+	return 0, errors.New("no LastInsertId available")
+}
+
+func (v RowsAffected) RowsAffected() (int64, error) {
+	return int64(v), nil
+}
+
+// ResultNoRows is a pre-defined Result for drivers to return when a DDL
+// command (such as a CREATE TABLE) succeeds. It returns an error for both
+// LastInsertId and RowsAffected.
+var ResultNoRows noRows
+
+type noRows struct{}
+
+var _ Result = noRows{}
+
+func (noRows) LastInsertId() (int64, error) {
+	return 0, errors.New("no LastInsertId available after DDL statement")
+}
+
+func (noRows) RowsAffected() (int64, error) {
+	return 0, errors.New("no RowsAffected available after DDL statement")
+}
diff --git a/third_party/gofrontend/libgo/go/database/sql/driver/types.go b/third_party/gofrontend/libgo/go/database/sql/driver/types.go
new file mode 100644
index 0000000..3305354
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/database/sql/driver/types.go
@@ -0,0 +1,252 @@
+// 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.
+
+package driver
+
+import (
+	"fmt"
+	"reflect"
+	"strconv"
+	"time"
+)
+
+// ValueConverter is the interface providing the ConvertValue method.
+//
+// Various implementations of ValueConverter are provided by the
+// driver package to provide consistent implementations of conversions
+// between drivers.  The ValueConverters have several uses:
+//
+//  * converting from the Value types as provided by the sql package
+//    into a database table's specific column type and making sure it
+//    fits, such as making sure a particular int64 fits in a
+//    table's uint16 column.
+//
+//  * converting a value as given from the database into one of the
+//    driver Value types.
+//
+//  * by the sql package, for converting from a driver's Value type
+//    to a user's type in a scan.
+type ValueConverter interface {
+	// ConvertValue converts a value to a driver Value.
+	ConvertValue(v interface{}) (Value, error)
+}
+
+// Valuer is the interface providing the Value method.
+//
+// Types implementing Valuer interface are able to convert
+// themselves to a driver Value.
+type Valuer interface {
+	// Value returns a driver Value.
+	Value() (Value, error)
+}
+
+// Bool is a ValueConverter that converts input values to bools.
+//
+// The conversion rules are:
+//  - booleans are returned unchanged
+//  - for integer types,
+//       1 is true
+//       0 is false,
+//       other integers are an error
+//  - for strings and []byte, same rules as strconv.ParseBool
+//  - all other types are an error
+var Bool boolType
+
+type boolType struct{}
+
+var _ ValueConverter = boolType{}
+
+func (boolType) String() string { return "Bool" }
+
+func (boolType) ConvertValue(src interface{}) (Value, error) {
+	switch s := src.(type) {
+	case bool:
+		return s, nil
+	case string:
+		b, err := strconv.ParseBool(s)
+		if err != nil {
+			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
+		}
+		return b, nil
+	case []byte:
+		b, err := strconv.ParseBool(string(s))
+		if err != nil {
+			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
+		}
+		return b, nil
+	}
+
+	sv := reflect.ValueOf(src)
+	switch sv.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		iv := sv.Int()
+		if iv == 1 || iv == 0 {
+			return iv == 1, nil
+		}
+		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", iv)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		uv := sv.Uint()
+		if uv == 1 || uv == 0 {
+			return uv == 1, nil
+		}
+		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", uv)
+	}
+
+	return nil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", src, src)
+}
+
+// Int32 is a ValueConverter that converts input values to int64,
+// respecting the limits of an int32 value.
+var Int32 int32Type
+
+type int32Type struct{}
+
+var _ ValueConverter = int32Type{}
+
+func (int32Type) ConvertValue(v interface{}) (Value, error) {
+	rv := reflect.ValueOf(v)
+	switch rv.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		i64 := rv.Int()
+		if i64 > (1<<31)-1 || i64 < -(1<<31) {
+			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
+		}
+		return i64, nil
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		u64 := rv.Uint()
+		if u64 > (1<<31)-1 {
+			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
+		}
+		return int64(u64), nil
+	case reflect.String:
+		i, err := strconv.Atoi(rv.String())
+		if err != nil {
+			return nil, fmt.Errorf("sql/driver: value %q can't be converted to int32", v)
+		}
+		return int64(i), nil
+	}
+	return nil, fmt.Errorf("sql/driver: unsupported value %v (type %T) converting to int32", v, v)
+}
+
+// String is a ValueConverter that converts its input to a string.
+// If the value is already a string or []byte, it's unchanged.
+// If the value is of another type, conversion to string is done
+// with fmt.Sprintf("%v", v).
+var String stringType
+
+type stringType struct{}
+
+func (stringType) ConvertValue(v interface{}) (Value, error) {
+	switch v.(type) {
+	case string, []byte:
+		return v, nil
+	}
+	return fmt.Sprintf("%v", v), nil
+}
+
+// Null is a type that implements ValueConverter by allowing nil
+// values but otherwise delegating to another ValueConverter.
+type Null struct {
+	Converter ValueConverter
+}
+
+func (n Null) ConvertValue(v interface{}) (Value, error) {
+	if v == nil {
+		return nil, nil
+	}
+	return n.Converter.ConvertValue(v)
+}
+
+// NotNull is a type that implements ValueConverter by disallowing nil
+// values but otherwise delegating to another ValueConverter.
+type NotNull struct {
+	Converter ValueConverter
+}
+
+func (n NotNull) ConvertValue(v interface{}) (Value, error) {
+	if v == nil {
+		return nil, fmt.Errorf("nil value not allowed")
+	}
+	return n.Converter.ConvertValue(v)
+}
+
+// IsValue reports whether v is a valid Value parameter type.
+// Unlike IsScanValue, IsValue permits the string type.
+func IsValue(v interface{}) bool {
+	if IsScanValue(v) {
+		return true
+	}
+	if _, ok := v.(string); ok {
+		return true
+	}
+	return false
+}
+
+// IsScanValue reports whether v is a valid Value scan type.
+// Unlike IsValue, IsScanValue does not permit the string type.
+func IsScanValue(v interface{}) bool {
+	if v == nil {
+		return true
+	}
+	switch v.(type) {
+	case int64, float64, []byte, bool, time.Time:
+		return true
+	}
+	return false
+}
+
+// DefaultParameterConverter is the default implementation of
+// ValueConverter that's used when a Stmt doesn't implement
+// ColumnConverter.
+//
+// DefaultParameterConverter returns the given value directly if
+// IsValue(value).  Otherwise integer type are converted to
+// int64, floats to float64, and strings to []byte.  Other types are
+// an error.
+var DefaultParameterConverter defaultConverter
+
+type defaultConverter struct{}
+
+var _ ValueConverter = defaultConverter{}
+
+func (defaultConverter) ConvertValue(v interface{}) (Value, error) {
+	if IsValue(v) {
+		return v, nil
+	}
+
+	if svi, ok := v.(Valuer); ok {
+		sv, err := svi.Value()
+		if err != nil {
+			return nil, err
+		}
+		if !IsValue(sv) {
+			return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
+		}
+		return sv, nil
+	}
+
+	rv := reflect.ValueOf(v)
+	switch rv.Kind() {
+	case reflect.Ptr:
+		// indirect pointers
+		if rv.IsNil() {
+			return nil, nil
+		} else {
+			return defaultConverter{}.ConvertValue(rv.Elem().Interface())
+		}
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return rv.Int(), nil
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
+		return int64(rv.Uint()), nil
+	case reflect.Uint64:
+		u64 := rv.Uint()
+		if u64 >= 1<<63 {
+			return nil, fmt.Errorf("uint64 values with high bit set are not supported")
+		}
+		return int64(u64), nil
+	case reflect.Float32, reflect.Float64:
+		return rv.Float(), nil
+	}
+	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
+}
diff --git a/third_party/gofrontend/libgo/go/database/sql/driver/types_test.go b/third_party/gofrontend/libgo/go/database/sql/driver/types_test.go
new file mode 100644
index 0000000..1ce0ff0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/database/sql/driver/types_test.go
@@ -0,0 +1,65 @@
+// 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.
+
+package driver
+
+import (
+	"reflect"
+	"testing"
+	"time"
+)
+
+type valueConverterTest struct {
+	c   ValueConverter
+	in  interface{}
+	out interface{}
+	err string
+}
+
+var now = time.Now()
+var answer int64 = 42
+
+var valueConverterTests = []valueConverterTest{
+	{Bool, "true", true, ""},
+	{Bool, "True", true, ""},
+	{Bool, []byte("t"), true, ""},
+	{Bool, true, true, ""},
+	{Bool, "1", true, ""},
+	{Bool, 1, true, ""},
+	{Bool, int64(1), true, ""},
+	{Bool, uint16(1), true, ""},
+	{Bool, "false", false, ""},
+	{Bool, false, false, ""},
+	{Bool, "0", false, ""},
+	{Bool, 0, false, ""},
+	{Bool, int64(0), false, ""},
+	{Bool, uint16(0), false, ""},
+	{c: Bool, in: "foo", err: "sql/driver: couldn't convert \"foo\" into type bool"},
+	{c: Bool, in: 2, err: "sql/driver: couldn't convert 2 into type bool"},
+	{DefaultParameterConverter, now, now, ""},
+	{DefaultParameterConverter, (*int64)(nil), nil, ""},
+	{DefaultParameterConverter, &answer, answer, ""},
+	{DefaultParameterConverter, &now, now, ""},
+}
+
+func TestValueConverters(t *testing.T) {
+	for i, tt := range valueConverterTests {
+		out, err := tt.c.ConvertValue(tt.in)
+		goterr := ""
+		if err != nil {
+			goterr = err.Error()
+		}
+		if goterr != tt.err {
+			t.Errorf("test %d: %T(%T(%v)) error = %q; want error = %q",
+				i, tt.c, tt.in, tt.in, goterr, tt.err)
+		}
+		if tt.err != "" {
+			continue
+		}
+		if !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("test %d: %T(%T(%v)) = %v (%T); want %v (%T)",
+				i, tt.c, tt.in, tt.in, out, out, tt.out, tt.out)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/database/sql/fakedb_test.go b/third_party/gofrontend/libgo/go/database/sql/fakedb_test.go
new file mode 100644
index 0000000..c7db0dd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/database/sql/fakedb_test.go
@@ -0,0 +1,805 @@
+// 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.
+
+package sql
+
+import (
+	"database/sql/driver"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"strconv"
+	"strings"
+	"sync"
+	"testing"
+	"time"
+)
+
+var _ = log.Printf
+
+// fakeDriver is a fake database that implements Go's driver.Driver
+// interface, just for testing.
+//
+// It speaks a query language that's semantically similar to but
+// syntactically different and simpler than SQL.  The syntax is as
+// follows:
+//
+//   WIPE
+//   CREATE|<tablename>|<col>=<type>,<col>=<type>,...
+//     where types are: "string", [u]int{8,16,32,64}, "bool"
+//   INSERT|<tablename>|col=val,col2=val2,col3=?
+//   SELECT|<tablename>|projectcol1,projectcol2|filtercol=?,filtercol2=?
+//
+// When opening a fakeDriver's database, it starts empty with no
+// tables.  All tables and data are stored in memory only.
+type fakeDriver struct {
+	mu         sync.Mutex // guards 3 following fields
+	openCount  int        // conn opens
+	closeCount int        // conn closes
+	waitCh     chan struct{}
+	waitingCh  chan struct{}
+	dbs        map[string]*fakeDB
+}
+
+type fakeDB struct {
+	name string
+
+	mu      sync.Mutex
+	free    []*fakeConn
+	tables  map[string]*table
+	badConn bool
+}
+
+type table struct {
+	mu      sync.Mutex
+	colname []string
+	coltype []string
+	rows    []*row
+}
+
+func (t *table) columnIndex(name string) int {
+	for n, nname := range t.colname {
+		if name == nname {
+			return n
+		}
+	}
+	return -1
+}
+
+type row struct {
+	cols []interface{} // must be same size as its table colname + coltype
+}
+
+func (r *row) clone() *row {
+	nrow := &row{cols: make([]interface{}, len(r.cols))}
+	copy(nrow.cols, r.cols)
+	return nrow
+}
+
+type fakeConn struct {
+	db *fakeDB // where to return ourselves to
+
+	currTx *fakeTx
+
+	// Stats for tests:
+	mu          sync.Mutex
+	stmtsMade   int
+	stmtsClosed int
+	numPrepare  int
+	bad         bool
+}
+
+func (c *fakeConn) incrStat(v *int) {
+	c.mu.Lock()
+	*v++
+	c.mu.Unlock()
+}
+
+type fakeTx struct {
+	c *fakeConn
+}
+
+type fakeStmt struct {
+	c *fakeConn
+	q string // just for debugging
+
+	cmd   string
+	table string
+
+	closed bool
+
+	colName      []string      // used by CREATE, INSERT, SELECT (selected columns)
+	colType      []string      // used by CREATE
+	colValue     []interface{} // used by INSERT (mix of strings and "?" for bound params)
+	placeholders int           // used by INSERT/SELECT: number of ? params
+
+	whereCol []string // used by SELECT (all placeholders)
+
+	placeholderConverter []driver.ValueConverter // used by INSERT
+}
+
+var fdriver driver.Driver = &fakeDriver{}
+
+func init() {
+	Register("test", fdriver)
+}
+
+// Supports dsn forms:
+//    <dbname>
+//    <dbname>;<opts>  (only currently supported option is `badConn`,
+//                      which causes driver.ErrBadConn to be returned on
+//                      every other conn.Begin())
+func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
+	parts := strings.Split(dsn, ";")
+	if len(parts) < 1 {
+		return nil, errors.New("fakedb: no database name")
+	}
+	name := parts[0]
+
+	db := d.getDB(name)
+
+	d.mu.Lock()
+	d.openCount++
+	d.mu.Unlock()
+	conn := &fakeConn{db: db}
+
+	if len(parts) >= 2 && parts[1] == "badConn" {
+		conn.bad = true
+	}
+	if d.waitCh != nil {
+		d.waitingCh <- struct{}{}
+		<-d.waitCh
+		d.waitCh = nil
+		d.waitingCh = nil
+	}
+	return conn, nil
+}
+
+func (d *fakeDriver) getDB(name string) *fakeDB {
+	d.mu.Lock()
+	defer d.mu.Unlock()
+	if d.dbs == nil {
+		d.dbs = make(map[string]*fakeDB)
+	}
+	db, ok := d.dbs[name]
+	if !ok {
+		db = &fakeDB{name: name}
+		d.dbs[name] = db
+	}
+	return db
+}
+
+func (db *fakeDB) wipe() {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	db.tables = nil
+}
+
+func (db *fakeDB) createTable(name string, columnNames, columnTypes []string) error {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	if db.tables == nil {
+		db.tables = make(map[string]*table)
+	}
+	if _, exist := db.tables[name]; exist {
+		return fmt.Errorf("table %q already exists", name)
+	}
+	if len(columnNames) != len(columnTypes) {
+		return fmt.Errorf("create table of %q len(names) != len(types): %d vs %d",
+			name, len(columnNames), len(columnTypes))
+	}
+	db.tables[name] = &table{colname: columnNames, coltype: columnTypes}
+	return nil
+}
+
+// must be called with db.mu lock held
+func (db *fakeDB) table(table string) (*table, bool) {
+	if db.tables == nil {
+		return nil, false
+	}
+	t, ok := db.tables[table]
+	return t, ok
+}
+
+func (db *fakeDB) columnType(table, column string) (typ string, ok bool) {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	t, ok := db.table(table)
+	if !ok {
+		return
+	}
+	for n, cname := range t.colname {
+		if cname == column {
+			return t.coltype[n], true
+		}
+	}
+	return "", false
+}
+
+func (c *fakeConn) isBad() bool {
+	// if not simulating bad conn, do nothing
+	if !c.bad {
+		return false
+	}
+	// alternate between bad conn and not bad conn
+	c.db.badConn = !c.db.badConn
+	return c.db.badConn
+}
+
+func (c *fakeConn) Begin() (driver.Tx, error) {
+	if c.isBad() {
+		return nil, driver.ErrBadConn
+	}
+	if c.currTx != nil {
+		return nil, errors.New("already in a transaction")
+	}
+	c.currTx = &fakeTx{c: c}
+	return c.currTx, nil
+}
+
+var hookPostCloseConn struct {
+	sync.Mutex
+	fn func(*fakeConn, error)
+}
+
+func setHookpostCloseConn(fn func(*fakeConn, error)) {
+	hookPostCloseConn.Lock()
+	defer hookPostCloseConn.Unlock()
+	hookPostCloseConn.fn = fn
+}
+
+var testStrictClose *testing.T
+
+// setStrictFakeConnClose sets the t to Errorf on when fakeConn.Close
+// fails to close. If nil, the check is disabled.
+func setStrictFakeConnClose(t *testing.T) {
+	testStrictClose = t
+}
+
+func (c *fakeConn) Close() (err error) {
+	drv := fdriver.(*fakeDriver)
+	defer func() {
+		if err != nil && testStrictClose != nil {
+			testStrictClose.Errorf("failed to close a test fakeConn: %v", err)
+		}
+		hookPostCloseConn.Lock()
+		fn := hookPostCloseConn.fn
+		hookPostCloseConn.Unlock()
+		if fn != nil {
+			fn(c, err)
+		}
+		if err == nil {
+			drv.mu.Lock()
+			drv.closeCount++
+			drv.mu.Unlock()
+		}
+	}()
+	if c.currTx != nil {
+		return errors.New("can't close fakeConn; in a Transaction")
+	}
+	if c.db == nil {
+		return errors.New("can't close fakeConn; already closed")
+	}
+	if c.stmtsMade > c.stmtsClosed {
+		return errors.New("can't close; dangling statement(s)")
+	}
+	c.db = nil
+	return nil
+}
+
+func checkSubsetTypes(args []driver.Value) error {
+	for n, arg := range args {
+		switch arg.(type) {
+		case int64, float64, bool, nil, []byte, string, time.Time:
+		default:
+			return fmt.Errorf("fakedb_test: invalid argument #%d: %v, type %T", n+1, arg, arg)
+		}
+	}
+	return nil
+}
+
+func (c *fakeConn) Exec(query string, args []driver.Value) (driver.Result, error) {
+	// This is an optional interface, but it's implemented here
+	// just to check that all the args are of the proper types.
+	// ErrSkip is returned so the caller acts as if we didn't
+	// implement this at all.
+	err := checkSubsetTypes(args)
+	if err != nil {
+		return nil, err
+	}
+	return nil, driver.ErrSkip
+}
+
+func (c *fakeConn) Query(query string, args []driver.Value) (driver.Rows, error) {
+	// This is an optional interface, but it's implemented here
+	// just to check that all the args are of the proper types.
+	// ErrSkip is returned so the caller acts as if we didn't
+	// implement this at all.
+	err := checkSubsetTypes(args)
+	if err != nil {
+		return nil, err
+	}
+	return nil, driver.ErrSkip
+}
+
+func errf(msg string, args ...interface{}) error {
+	return errors.New("fakedb: " + fmt.Sprintf(msg, args...))
+}
+
+// parts are table|selectCol1,selectCol2|whereCol=?,whereCol2=?
+// (note that where columns must always contain ? marks,
+//  just a limitation for fakedb)
+func (c *fakeConn) prepareSelect(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
+	if len(parts) != 3 {
+		stmt.Close()
+		return nil, errf("invalid SELECT syntax with %d parts; want 3", len(parts))
+	}
+	stmt.table = parts[0]
+	stmt.colName = strings.Split(parts[1], ",")
+	for n, colspec := range strings.Split(parts[2], ",") {
+		if colspec == "" {
+			continue
+		}
+		nameVal := strings.Split(colspec, "=")
+		if len(nameVal) != 2 {
+			stmt.Close()
+			return nil, errf("SELECT on table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
+		}
+		column, value := nameVal[0], nameVal[1]
+		_, ok := c.db.columnType(stmt.table, column)
+		if !ok {
+			stmt.Close()
+			return nil, errf("SELECT on table %q references non-existent column %q", stmt.table, column)
+		}
+		if value != "?" {
+			stmt.Close()
+			return nil, errf("SELECT on table %q has pre-bound value for where column %q; need a question mark",
+				stmt.table, column)
+		}
+		stmt.whereCol = append(stmt.whereCol, column)
+		stmt.placeholders++
+	}
+	return stmt, nil
+}
+
+// parts are table|col=type,col2=type2
+func (c *fakeConn) prepareCreate(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
+	if len(parts) != 2 {
+		stmt.Close()
+		return nil, errf("invalid CREATE syntax with %d parts; want 2", len(parts))
+	}
+	stmt.table = parts[0]
+	for n, colspec := range strings.Split(parts[1], ",") {
+		nameType := strings.Split(colspec, "=")
+		if len(nameType) != 2 {
+			stmt.Close()
+			return nil, errf("CREATE table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
+		}
+		stmt.colName = append(stmt.colName, nameType[0])
+		stmt.colType = append(stmt.colType, nameType[1])
+	}
+	return stmt, nil
+}
+
+// parts are table|col=?,col2=val
+func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
+	if len(parts) != 2 {
+		stmt.Close()
+		return nil, errf("invalid INSERT syntax with %d parts; want 2", len(parts))
+	}
+	stmt.table = parts[0]
+	for n, colspec := range strings.Split(parts[1], ",") {
+		nameVal := strings.Split(colspec, "=")
+		if len(nameVal) != 2 {
+			stmt.Close()
+			return nil, errf("INSERT table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
+		}
+		column, value := nameVal[0], nameVal[1]
+		ctype, ok := c.db.columnType(stmt.table, column)
+		if !ok {
+			stmt.Close()
+			return nil, errf("INSERT table %q references non-existent column %q", stmt.table, column)
+		}
+		stmt.colName = append(stmt.colName, column)
+
+		if value != "?" {
+			var subsetVal interface{}
+			// Convert to driver subset type
+			switch ctype {
+			case "string":
+				subsetVal = []byte(value)
+			case "blob":
+				subsetVal = []byte(value)
+			case "int32":
+				i, err := strconv.Atoi(value)
+				if err != nil {
+					stmt.Close()
+					return nil, errf("invalid conversion to int32 from %q", value)
+				}
+				subsetVal = int64(i) // int64 is a subset type, but not int32
+			default:
+				stmt.Close()
+				return nil, errf("unsupported conversion for pre-bound parameter %q to type %q", value, ctype)
+			}
+			stmt.colValue = append(stmt.colValue, subsetVal)
+		} else {
+			stmt.placeholders++
+			stmt.placeholderConverter = append(stmt.placeholderConverter, converterForType(ctype))
+			stmt.colValue = append(stmt.colValue, "?")
+		}
+	}
+	return stmt, nil
+}
+
+// hook to simulate broken connections
+var hookPrepareBadConn func() bool
+
+func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
+	c.numPrepare++
+	if c.db == nil {
+		panic("nil c.db; conn = " + fmt.Sprintf("%#v", c))
+	}
+
+	if hookPrepareBadConn != nil && hookPrepareBadConn() {
+		return nil, driver.ErrBadConn
+	}
+
+	parts := strings.Split(query, "|")
+	if len(parts) < 1 {
+		return nil, errf("empty query")
+	}
+	cmd := parts[0]
+	parts = parts[1:]
+	stmt := &fakeStmt{q: query, c: c, cmd: cmd}
+	c.incrStat(&c.stmtsMade)
+	switch cmd {
+	case "WIPE":
+		// Nothing
+	case "SELECT":
+		return c.prepareSelect(stmt, parts)
+	case "CREATE":
+		return c.prepareCreate(stmt, parts)
+	case "INSERT":
+		return c.prepareInsert(stmt, parts)
+	case "NOSERT":
+		// Do all the prep-work like for an INSERT but don't actually insert the row.
+		// Used for some of the concurrent tests.
+		return c.prepareInsert(stmt, parts)
+	default:
+		stmt.Close()
+		return nil, errf("unsupported command type %q", cmd)
+	}
+	return stmt, nil
+}
+
+func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
+	if len(s.placeholderConverter) == 0 {
+		return driver.DefaultParameterConverter
+	}
+	return s.placeholderConverter[idx]
+}
+
+func (s *fakeStmt) Close() error {
+	if s.c == nil {
+		panic("nil conn in fakeStmt.Close")
+	}
+	if s.c.db == nil {
+		panic("in fakeStmt.Close, conn's db is nil (already closed)")
+	}
+	if !s.closed {
+		s.c.incrStat(&s.c.stmtsClosed)
+		s.closed = true
+	}
+	return nil
+}
+
+var errClosed = errors.New("fakedb: statement has been closed")
+
+// hook to simulate broken connections
+var hookExecBadConn func() bool
+
+func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
+	if s.closed {
+		return nil, errClosed
+	}
+
+	if hookExecBadConn != nil && hookExecBadConn() {
+		return nil, driver.ErrBadConn
+	}
+
+	err := checkSubsetTypes(args)
+	if err != nil {
+		return nil, err
+	}
+
+	db := s.c.db
+	switch s.cmd {
+	case "WIPE":
+		db.wipe()
+		return driver.ResultNoRows, nil
+	case "CREATE":
+		if err := db.createTable(s.table, s.colName, s.colType); err != nil {
+			return nil, err
+		}
+		return driver.ResultNoRows, nil
+	case "INSERT":
+		return s.execInsert(args, true)
+	case "NOSERT":
+		// Do all the prep-work like for an INSERT but don't actually insert the row.
+		// Used for some of the concurrent tests.
+		return s.execInsert(args, false)
+	}
+	fmt.Printf("EXEC statement, cmd=%q: %#v\n", s.cmd, s)
+	return nil, fmt.Errorf("unimplemented statement Exec command type of %q", s.cmd)
+}
+
+// When doInsert is true, add the row to the table.
+// When doInsert is false do prep-work and error checking, but don't
+// actually add the row to the table.
+func (s *fakeStmt) execInsert(args []driver.Value, doInsert bool) (driver.Result, error) {
+	db := s.c.db
+	if len(args) != s.placeholders {
+		panic("error in pkg db; should only get here if size is correct")
+	}
+	db.mu.Lock()
+	t, ok := db.table(s.table)
+	db.mu.Unlock()
+	if !ok {
+		return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
+	}
+
+	t.mu.Lock()
+	defer t.mu.Unlock()
+
+	var cols []interface{}
+	if doInsert {
+		cols = make([]interface{}, len(t.colname))
+	}
+	argPos := 0
+	for n, colname := range s.colName {
+		colidx := t.columnIndex(colname)
+		if colidx == -1 {
+			return nil, fmt.Errorf("fakedb: column %q doesn't exist or dropped since prepared statement was created", colname)
+		}
+		var val interface{}
+		if strvalue, ok := s.colValue[n].(string); ok && strvalue == "?" {
+			val = args[argPos]
+			argPos++
+		} else {
+			val = s.colValue[n]
+		}
+		if doInsert {
+			cols[colidx] = val
+		}
+	}
+
+	if doInsert {
+		t.rows = append(t.rows, &row{cols: cols})
+	}
+	return driver.RowsAffected(1), nil
+}
+
+// hook to simulate broken connections
+var hookQueryBadConn func() bool
+
+func (s *fakeStmt) Query(args []driver.Value) (driver.Rows, error) {
+	if s.closed {
+		return nil, errClosed
+	}
+
+	if hookQueryBadConn != nil && hookQueryBadConn() {
+		return nil, driver.ErrBadConn
+	}
+
+	err := checkSubsetTypes(args)
+	if err != nil {
+		return nil, err
+	}
+
+	db := s.c.db
+	if len(args) != s.placeholders {
+		panic("error in pkg db; should only get here if size is correct")
+	}
+
+	db.mu.Lock()
+	t, ok := db.table(s.table)
+	db.mu.Unlock()
+	if !ok {
+		return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
+	}
+
+	if s.table == "magicquery" {
+		if len(s.whereCol) == 2 && s.whereCol[0] == "op" && s.whereCol[1] == "millis" {
+			if args[0] == "sleep" {
+				time.Sleep(time.Duration(args[1].(int64)) * time.Millisecond)
+			}
+		}
+	}
+
+	t.mu.Lock()
+	defer t.mu.Unlock()
+
+	colIdx := make(map[string]int) // select column name -> column index in table
+	for _, name := range s.colName {
+		idx := t.columnIndex(name)
+		if idx == -1 {
+			return nil, fmt.Errorf("fakedb: unknown column name %q", name)
+		}
+		colIdx[name] = idx
+	}
+
+	mrows := []*row{}
+rows:
+	for _, trow := range t.rows {
+		// Process the where clause, skipping non-match rows. This is lazy
+		// and just uses fmt.Sprintf("%v") to test equality.  Good enough
+		// for test code.
+		for widx, wcol := range s.whereCol {
+			idx := t.columnIndex(wcol)
+			if idx == -1 {
+				return nil, fmt.Errorf("db: invalid where clause column %q", wcol)
+			}
+			tcol := trow.cols[idx]
+			if bs, ok := tcol.([]byte); ok {
+				// lazy hack to avoid sprintf %v on a []byte
+				tcol = string(bs)
+			}
+			if fmt.Sprintf("%v", tcol) != fmt.Sprintf("%v", args[widx]) {
+				continue rows
+			}
+		}
+		mrow := &row{cols: make([]interface{}, len(s.colName))}
+		for seli, name := range s.colName {
+			mrow.cols[seli] = trow.cols[colIdx[name]]
+		}
+		mrows = append(mrows, mrow)
+	}
+
+	cursor := &rowsCursor{
+		pos:    -1,
+		rows:   mrows,
+		cols:   s.colName,
+		errPos: -1,
+	}
+	return cursor, nil
+}
+
+func (s *fakeStmt) NumInput() int {
+	return s.placeholders
+}
+
+func (tx *fakeTx) Commit() error {
+	tx.c.currTx = nil
+	return nil
+}
+
+func (tx *fakeTx) Rollback() error {
+	tx.c.currTx = nil
+	return nil
+}
+
+type rowsCursor struct {
+	cols   []string
+	pos    int
+	rows   []*row
+	closed bool
+
+	// errPos and err are for making Next return early with error.
+	errPos int
+	err    error
+
+	// a clone of slices to give out to clients, indexed by the
+	// the original slice's first byte address.  we clone them
+	// just so we're able to corrupt them on close.
+	bytesClone map[*byte][]byte
+}
+
+func (rc *rowsCursor) Close() error {
+	if !rc.closed {
+		for _, bs := range rc.bytesClone {
+			bs[0] = 255 // first byte corrupted
+		}
+	}
+	rc.closed = true
+	return nil
+}
+
+func (rc *rowsCursor) Columns() []string {
+	return rc.cols
+}
+
+var rowsCursorNextHook func(dest []driver.Value) error
+
+func (rc *rowsCursor) Next(dest []driver.Value) error {
+	if rowsCursorNextHook != nil {
+		return rowsCursorNextHook(dest)
+	}
+
+	if rc.closed {
+		return errors.New("fakedb: cursor is closed")
+	}
+	rc.pos++
+	if rc.pos == rc.errPos {
+		return rc.err
+	}
+	if rc.pos >= len(rc.rows) {
+		return io.EOF // per interface spec
+	}
+	for i, v := range rc.rows[rc.pos].cols {
+		// TODO(bradfitz): convert to subset types? naah, I
+		// think the subset types should only be input to
+		// driver, but the sql package should be able to handle
+		// a wider range of types coming out of drivers. all
+		// for ease of drivers, and to prevent drivers from
+		// messing up conversions or doing them differently.
+		dest[i] = v
+
+		if bs, ok := v.([]byte); ok {
+			if rc.bytesClone == nil {
+				rc.bytesClone = make(map[*byte][]byte)
+			}
+			clone, ok := rc.bytesClone[&bs[0]]
+			if !ok {
+				clone = make([]byte, len(bs))
+				copy(clone, bs)
+				rc.bytesClone[&bs[0]] = clone
+			}
+			dest[i] = clone
+		}
+	}
+	return nil
+}
+
+// fakeDriverString is like driver.String, but indirects pointers like
+// DefaultValueConverter.
+//
+// This could be surprising behavior to retroactively apply to
+// driver.String now that Go1 is out, but this is convenient for
+// our TestPointerParamsAndScans.
+//
+type fakeDriverString struct{}
+
+func (fakeDriverString) ConvertValue(v interface{}) (driver.Value, error) {
+	switch c := v.(type) {
+	case string, []byte:
+		return v, nil
+	case *string:
+		if c == nil {
+			return nil, nil
+		}
+		return *c, nil
+	}
+	return fmt.Sprintf("%v", v), nil
+}
+
+func converterForType(typ string) driver.ValueConverter {
+	switch typ {
+	case "bool":
+		return driver.Bool
+	case "nullbool":
+		return driver.Null{Converter: driver.Bool}
+	case "int32":
+		return driver.Int32
+	case "string":
+		return driver.NotNull{Converter: fakeDriverString{}}
+	case "nullstring":
+		return driver.Null{Converter: fakeDriverString{}}
+	case "int64":
+		// TODO(coopernurse): add type-specific converter
+		return driver.NotNull{Converter: driver.DefaultParameterConverter}
+	case "nullint64":
+		// TODO(coopernurse): add type-specific converter
+		return driver.Null{Converter: driver.DefaultParameterConverter}
+	case "float64":
+		// TODO(coopernurse): add type-specific converter
+		return driver.NotNull{Converter: driver.DefaultParameterConverter}
+	case "nullfloat64":
+		// TODO(coopernurse): add type-specific converter
+		return driver.Null{Converter: driver.DefaultParameterConverter}
+	case "datetime":
+		return driver.DefaultParameterConverter
+	}
+	panic("invalid fakedb column type of " + typ)
+}
diff --git a/third_party/gofrontend/libgo/go/database/sql/sql.go b/third_party/gofrontend/libgo/go/database/sql/sql.go
new file mode 100644
index 0000000..765b80c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/database/sql/sql.go
@@ -0,0 +1,1720 @@
+// 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.
+
+// Package sql provides a generic interface around SQL (or SQL-like)
+// databases.
+//
+// The sql package must be used in conjunction with a database driver.
+// See http://golang.org/s/sqldrivers for a list of drivers.
+//
+// For more usage examples, see the wiki page at
+// http://golang.org/s/sqlwiki.
+package sql
+
+import (
+	"container/list"
+	"database/sql/driver"
+	"errors"
+	"fmt"
+	"io"
+	"runtime"
+	"sync"
+)
+
+var drivers = make(map[string]driver.Driver)
+
+// Register makes a database driver available by the provided name.
+// If Register is called twice with the same name or if driver is nil,
+// it panics.
+func Register(name string, driver driver.Driver) {
+	if driver == nil {
+		panic("sql: Register driver is nil")
+	}
+	if _, dup := drivers[name]; dup {
+		panic("sql: Register called twice for driver " + name)
+	}
+	drivers[name] = driver
+}
+
+// RawBytes is a byte slice that holds a reference to memory owned by
+// the database itself. After a Scan into a RawBytes, the slice is only
+// valid until the next call to Next, Scan, or Close.
+type RawBytes []byte
+
+// NullString represents a string that may be null.
+// NullString implements the Scanner interface so
+// it can be used as a scan destination:
+//
+//  var s NullString
+//  err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&s)
+//  ...
+//  if s.Valid {
+//     // use s.String
+//  } else {
+//     // NULL value
+//  }
+//
+type NullString struct {
+	String string
+	Valid  bool // Valid is true if String is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (ns *NullString) Scan(value interface{}) error {
+	if value == nil {
+		ns.String, ns.Valid = "", false
+		return nil
+	}
+	ns.Valid = true
+	return convertAssign(&ns.String, value)
+}
+
+// Value implements the driver Valuer interface.
+func (ns NullString) Value() (driver.Value, error) {
+	if !ns.Valid {
+		return nil, nil
+	}
+	return ns.String, nil
+}
+
+// NullInt64 represents an int64 that may be null.
+// NullInt64 implements the Scanner interface so
+// it can be used as a scan destination, similar to NullString.
+type NullInt64 struct {
+	Int64 int64
+	Valid bool // Valid is true if Int64 is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (n *NullInt64) Scan(value interface{}) error {
+	if value == nil {
+		n.Int64, n.Valid = 0, false
+		return nil
+	}
+	n.Valid = true
+	return convertAssign(&n.Int64, value)
+}
+
+// Value implements the driver Valuer interface.
+func (n NullInt64) Value() (driver.Value, error) {
+	if !n.Valid {
+		return nil, nil
+	}
+	return n.Int64, nil
+}
+
+// NullFloat64 represents a float64 that may be null.
+// NullFloat64 implements the Scanner interface so
+// it can be used as a scan destination, similar to NullString.
+type NullFloat64 struct {
+	Float64 float64
+	Valid   bool // Valid is true if Float64 is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (n *NullFloat64) Scan(value interface{}) error {
+	if value == nil {
+		n.Float64, n.Valid = 0, false
+		return nil
+	}
+	n.Valid = true
+	return convertAssign(&n.Float64, value)
+}
+
+// Value implements the driver Valuer interface.
+func (n NullFloat64) Value() (driver.Value, error) {
+	if !n.Valid {
+		return nil, nil
+	}
+	return n.Float64, nil
+}
+
+// NullBool represents a bool that may be null.
+// NullBool implements the Scanner interface so
+// it can be used as a scan destination, similar to NullString.
+type NullBool struct {
+	Bool  bool
+	Valid bool // Valid is true if Bool is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (n *NullBool) Scan(value interface{}) error {
+	if value == nil {
+		n.Bool, n.Valid = false, false
+		return nil
+	}
+	n.Valid = true
+	return convertAssign(&n.Bool, value)
+}
+
+// Value implements the driver Valuer interface.
+func (n NullBool) Value() (driver.Value, error) {
+	if !n.Valid {
+		return nil, nil
+	}
+	return n.Bool, nil
+}
+
+// Scanner is an interface used by Scan.
+type Scanner interface {
+	// Scan assigns a value from a database driver.
+	//
+	// The src value will be of one of the following restricted
+	// set of types:
+	//
+	//    int64
+	//    float64
+	//    bool
+	//    []byte
+	//    string
+	//    time.Time
+	//    nil - for NULL values
+	//
+	// An error should be returned if the value can not be stored
+	// without loss of information.
+	Scan(src interface{}) error
+}
+
+// ErrNoRows is returned by Scan when QueryRow doesn't return a
+// row. In such a case, QueryRow returns a placeholder *Row value that
+// defers this error until a Scan.
+var ErrNoRows = errors.New("sql: no rows in result set")
+
+// DB is a database handle representing a pool of zero or more
+// underlying connections. It's safe for concurrent use by multiple
+// goroutines.
+//
+// The sql package creates and frees connections automatically; it
+// also maintains a free pool of idle connections. If the database has
+// a concept of per-connection state, such state can only be reliably
+// observed within a transaction. Once DB.Begin is called, the
+// returned Tx is bound to a single connection. Once Commit or
+// Rollback is called on the transaction, that transaction's
+// connection is returned to DB's idle connection pool. The pool size
+// can be controlled with SetMaxIdleConns.
+type DB struct {
+	driver driver.Driver
+	dsn    string
+
+	mu           sync.Mutex // protects following fields
+	freeConn     *list.List // of *driverConn
+	connRequests *list.List // of connRequest
+	numOpen      int
+	pendingOpens int
+	// Used to signal the need for new connections
+	// a goroutine running connectionOpener() reads on this chan and
+	// maybeOpenNewConnections sends on the chan (one send per needed connection)
+	// It is closed during db.Close(). The close tells the connectionOpener
+	// goroutine to exit.
+	openerCh chan struct{}
+	closed   bool
+	dep      map[finalCloser]depSet
+	lastPut  map[*driverConn]string // stacktrace of last conn's put; debug only
+	maxIdle  int                    // zero means defaultMaxIdleConns; negative means 0
+	maxOpen  int                    // <= 0 means unlimited
+}
+
+// driverConn wraps a driver.Conn with a mutex, to
+// be held during all calls into the Conn. (including any calls onto
+// interfaces returned via that Conn, such as calls on Tx, Stmt,
+// Result, Rows)
+type driverConn struct {
+	db *DB
+
+	sync.Mutex  // guards following
+	ci          driver.Conn
+	closed      bool
+	finalClosed bool // ci.Close has been called
+	openStmt    map[driver.Stmt]bool
+
+	// guarded by db.mu
+	inUse      bool
+	onPut      []func() // code (with db.mu held) run when conn is next returned
+	dbmuClosed bool     // same as closed, but guarded by db.mu, for connIfFree
+	// This is the Element returned by db.freeConn.PushFront(conn).
+	// It's used by connIfFree to remove the conn from the freeConn list.
+	listElem *list.Element
+}
+
+func (dc *driverConn) releaseConn(err error) {
+	dc.db.putConn(dc, err)
+}
+
+func (dc *driverConn) removeOpenStmt(si driver.Stmt) {
+	dc.Lock()
+	defer dc.Unlock()
+	delete(dc.openStmt, si)
+}
+
+func (dc *driverConn) prepareLocked(query string) (driver.Stmt, error) {
+	si, err := dc.ci.Prepare(query)
+	if err == nil {
+		// Track each driverConn's open statements, so we can close them
+		// before closing the conn.
+		//
+		// TODO(bradfitz): let drivers opt out of caring about
+		// stmt closes if the conn is about to close anyway? For now
+		// do the safe thing, in case stmts need to be closed.
+		//
+		// TODO(bradfitz): after Go 1.2, closing driver.Stmts
+		// should be moved to driverStmt, using unique
+		// *driverStmts everywhere (including from
+		// *Stmt.connStmt, instead of returning a
+		// driver.Stmt), using driverStmt as a pointer
+		// everywhere, and making it a finalCloser.
+		if dc.openStmt == nil {
+			dc.openStmt = make(map[driver.Stmt]bool)
+		}
+		dc.openStmt[si] = true
+	}
+	return si, err
+}
+
+// the dc.db's Mutex is held.
+func (dc *driverConn) closeDBLocked() func() error {
+	dc.Lock()
+	defer dc.Unlock()
+	if dc.closed {
+		return func() error { return errors.New("sql: duplicate driverConn close") }
+	}
+	dc.closed = true
+	return dc.db.removeDepLocked(dc, dc)
+}
+
+func (dc *driverConn) Close() error {
+	dc.Lock()
+	if dc.closed {
+		dc.Unlock()
+		return errors.New("sql: duplicate driverConn close")
+	}
+	dc.closed = true
+	dc.Unlock() // not defer; removeDep finalClose calls may need to lock
+
+	// And now updates that require holding dc.mu.Lock.
+	dc.db.mu.Lock()
+	dc.dbmuClosed = true
+	fn := dc.db.removeDepLocked(dc, dc)
+	dc.db.mu.Unlock()
+	return fn()
+}
+
+func (dc *driverConn) finalClose() error {
+	dc.Lock()
+
+	for si := range dc.openStmt {
+		si.Close()
+	}
+	dc.openStmt = nil
+
+	err := dc.ci.Close()
+	dc.ci = nil
+	dc.finalClosed = true
+	dc.Unlock()
+
+	dc.db.mu.Lock()
+	dc.db.numOpen--
+	dc.db.maybeOpenNewConnections()
+	dc.db.mu.Unlock()
+
+	return err
+}
+
+// driverStmt associates a driver.Stmt with the
+// *driverConn from which it came, so the driverConn's lock can be
+// held during calls.
+type driverStmt struct {
+	sync.Locker // the *driverConn
+	si          driver.Stmt
+}
+
+func (ds *driverStmt) Close() error {
+	ds.Lock()
+	defer ds.Unlock()
+	return ds.si.Close()
+}
+
+// depSet is a finalCloser's outstanding dependencies
+type depSet map[interface{}]bool // set of true bools
+
+// The finalCloser interface is used by (*DB).addDep and related
+// dependency reference counting.
+type finalCloser interface {
+	// finalClose is called when the reference count of an object
+	// goes to zero. (*DB).mu is not held while calling it.
+	finalClose() error
+}
+
+// addDep notes that x now depends on dep, and x's finalClose won't be
+// called until all of x's dependencies are removed with removeDep.
+func (db *DB) addDep(x finalCloser, dep interface{}) {
+	//println(fmt.Sprintf("addDep(%T %p, %T %p)", x, x, dep, dep))
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	db.addDepLocked(x, dep)
+}
+
+func (db *DB) addDepLocked(x finalCloser, dep interface{}) {
+	if db.dep == nil {
+		db.dep = make(map[finalCloser]depSet)
+	}
+	xdep := db.dep[x]
+	if xdep == nil {
+		xdep = make(depSet)
+		db.dep[x] = xdep
+	}
+	xdep[dep] = true
+}
+
+// removeDep notes that x no longer depends on dep.
+// If x still has dependencies, nil is returned.
+// If x no longer has any dependencies, its finalClose method will be
+// called and its error value will be returned.
+func (db *DB) removeDep(x finalCloser, dep interface{}) error {
+	db.mu.Lock()
+	fn := db.removeDepLocked(x, dep)
+	db.mu.Unlock()
+	return fn()
+}
+
+func (db *DB) removeDepLocked(x finalCloser, dep interface{}) func() error {
+	//println(fmt.Sprintf("removeDep(%T %p, %T %p)", x, x, dep, dep))
+
+	xdep, ok := db.dep[x]
+	if !ok {
+		panic(fmt.Sprintf("unpaired removeDep: no deps for %T", x))
+	}
+
+	l0 := len(xdep)
+	delete(xdep, dep)
+
+	switch len(xdep) {
+	case l0:
+		// Nothing removed. Shouldn't happen.
+		panic(fmt.Sprintf("unpaired removeDep: no %T dep on %T", dep, x))
+	case 0:
+		// No more dependencies.
+		delete(db.dep, x)
+		return x.finalClose
+	default:
+		// Dependencies remain.
+		return func() error { return nil }
+	}
+}
+
+// This is the size of the connectionOpener request chan (dn.openerCh).
+// This value should be larger than the maximum typical value
+// used for db.maxOpen. If maxOpen is significantly larger than
+// connectionRequestQueueSize then it is possible for ALL calls into the *DB
+// to block until the connectionOpener can satisfy the backlog of requests.
+var connectionRequestQueueSize = 1000000
+
+// Open opens a database specified by its database driver name and a
+// driver-specific data source name, usually consisting of at least a
+// database name and connection information.
+//
+// Most users will open a database via a driver-specific connection
+// helper function that returns a *DB. No database drivers are included
+// in the Go standard library. See http://golang.org/s/sqldrivers for
+// a list of third-party drivers.
+//
+// Open may just validate its arguments without creating a connection
+// to the database. To verify that the data source name is valid, call
+// Ping.
+//
+// The returned DB is safe for concurrent use by multiple goroutines
+// and maintains its own pool of idle connections. Thus, the Open
+// function should be called just once. It is rarely necessary to
+// close a DB.
+func Open(driverName, dataSourceName string) (*DB, error) {
+	driveri, ok := drivers[driverName]
+	if !ok {
+		return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
+	}
+	db := &DB{
+		driver:   driveri,
+		dsn:      dataSourceName,
+		openerCh: make(chan struct{}, connectionRequestQueueSize),
+		lastPut:  make(map[*driverConn]string),
+	}
+	db.freeConn = list.New()
+	db.connRequests = list.New()
+	go db.connectionOpener()
+	return db, nil
+}
+
+// Ping verifies a connection to the database is still alive,
+// establishing a connection if necessary.
+func (db *DB) Ping() error {
+	// TODO(bradfitz): give drivers an optional hook to implement
+	// this in a more efficient or more reliable way, if they
+	// have one.
+	dc, err := db.conn()
+	if err != nil {
+		return err
+	}
+	db.putConn(dc, nil)
+	return nil
+}
+
+// Close closes the database, releasing any open resources.
+//
+// It is rare to Close a DB, as the DB handle is meant to be
+// long-lived and shared between many goroutines.
+func (db *DB) Close() error {
+	db.mu.Lock()
+	if db.closed { // Make DB.Close idempotent
+		db.mu.Unlock()
+		return nil
+	}
+	close(db.openerCh)
+	var err error
+	fns := make([]func() error, 0, db.freeConn.Len())
+	for db.freeConn.Front() != nil {
+		dc := db.freeConn.Front().Value.(*driverConn)
+		dc.listElem = nil
+		fns = append(fns, dc.closeDBLocked())
+		db.freeConn.Remove(db.freeConn.Front())
+	}
+	db.closed = true
+	for db.connRequests.Front() != nil {
+		req := db.connRequests.Front().Value.(connRequest)
+		db.connRequests.Remove(db.connRequests.Front())
+		close(req)
+	}
+	db.mu.Unlock()
+	for _, fn := range fns {
+		err1 := fn()
+		if err1 != nil {
+			err = err1
+		}
+	}
+	return err
+}
+
+const defaultMaxIdleConns = 2
+
+func (db *DB) maxIdleConnsLocked() int {
+	n := db.maxIdle
+	switch {
+	case n == 0:
+		// TODO(bradfitz): ask driver, if supported, for its default preference
+		return defaultMaxIdleConns
+	case n < 0:
+		return 0
+	default:
+		return n
+	}
+}
+
+// SetMaxIdleConns sets the maximum number of connections in the idle
+// connection pool.
+//
+// If MaxOpenConns is greater than 0 but less than the new MaxIdleConns
+// then the new MaxIdleConns will be reduced to match the MaxOpenConns limit
+//
+// If n <= 0, no idle connections are retained.
+func (db *DB) SetMaxIdleConns(n int) {
+	db.mu.Lock()
+	if n > 0 {
+		db.maxIdle = n
+	} else {
+		// No idle connections.
+		db.maxIdle = -1
+	}
+	// Make sure maxIdle doesn't exceed maxOpen
+	if db.maxOpen > 0 && db.maxIdleConnsLocked() > db.maxOpen {
+		db.maxIdle = db.maxOpen
+	}
+	var closing []*driverConn
+	for db.freeConn.Len() > db.maxIdleConnsLocked() {
+		dc := db.freeConn.Back().Value.(*driverConn)
+		dc.listElem = nil
+		db.freeConn.Remove(db.freeConn.Back())
+		closing = append(closing, dc)
+	}
+	db.mu.Unlock()
+	for _, c := range closing {
+		c.Close()
+	}
+}
+
+// SetMaxOpenConns sets the maximum number of open connections to the database.
+//
+// If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than
+// MaxIdleConns, then MaxIdleConns will be reduced to match the new
+// MaxOpenConns limit
+//
+// If n <= 0, then there is no limit on the number of open connections.
+// The default is 0 (unlimited).
+func (db *DB) SetMaxOpenConns(n int) {
+	db.mu.Lock()
+	db.maxOpen = n
+	if n < 0 {
+		db.maxOpen = 0
+	}
+	syncMaxIdle := db.maxOpen > 0 && db.maxIdleConnsLocked() > db.maxOpen
+	db.mu.Unlock()
+	if syncMaxIdle {
+		db.SetMaxIdleConns(n)
+	}
+}
+
+// Assumes db.mu is locked.
+// If there are connRequests and the connection limit hasn't been reached,
+// then tell the connectionOpener to open new connections.
+func (db *DB) maybeOpenNewConnections() {
+	numRequests := db.connRequests.Len() - db.pendingOpens
+	if db.maxOpen > 0 {
+		numCanOpen := db.maxOpen - (db.numOpen + db.pendingOpens)
+		if numRequests > numCanOpen {
+			numRequests = numCanOpen
+		}
+	}
+	for numRequests > 0 {
+		db.pendingOpens++
+		numRequests--
+		db.openerCh <- struct{}{}
+	}
+}
+
+// Runs in a separate goroutine, opens new connections when requested.
+func (db *DB) connectionOpener() {
+	for _ = range db.openerCh {
+		db.openNewConnection()
+	}
+}
+
+// Open one new connection
+func (db *DB) openNewConnection() {
+	ci, err := db.driver.Open(db.dsn)
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	if db.closed {
+		if err == nil {
+			ci.Close()
+		}
+		return
+	}
+	db.pendingOpens--
+	if err != nil {
+		db.putConnDBLocked(nil, err)
+		return
+	}
+	dc := &driverConn{
+		db: db,
+		ci: ci,
+	}
+	if db.putConnDBLocked(dc, err) {
+		db.addDepLocked(dc, dc)
+		db.numOpen++
+	} else {
+		ci.Close()
+	}
+}
+
+// connRequest represents one request for a new connection
+// When there are no idle connections available, DB.conn will create
+// a new connRequest and put it on the db.connRequests list.
+type connRequest chan<- interface{} // takes either a *driverConn or an error
+
+var errDBClosed = errors.New("sql: database is closed")
+
+// conn returns a newly-opened or cached *driverConn
+func (db *DB) conn() (*driverConn, error) {
+	db.mu.Lock()
+	if db.closed {
+		db.mu.Unlock()
+		return nil, errDBClosed
+	}
+
+	// If db.maxOpen > 0 and the number of open connections is over the limit
+	// and there are no free connection, make a request and wait.
+	if db.maxOpen > 0 && db.numOpen >= db.maxOpen && db.freeConn.Len() == 0 {
+		// Make the connRequest channel. It's buffered so that the
+		// connectionOpener doesn't block while waiting for the req to be read.
+		ch := make(chan interface{}, 1)
+		req := connRequest(ch)
+		db.connRequests.PushBack(req)
+		db.maybeOpenNewConnections()
+		db.mu.Unlock()
+		ret, ok := <-ch
+		if !ok {
+			return nil, errDBClosed
+		}
+		switch ret.(type) {
+		case *driverConn:
+			return ret.(*driverConn), nil
+		case error:
+			return nil, ret.(error)
+		default:
+			panic("sql: Unexpected type passed through connRequest.ch")
+		}
+	}
+
+	if f := db.freeConn.Front(); f != nil {
+		conn := f.Value.(*driverConn)
+		conn.listElem = nil
+		db.freeConn.Remove(f)
+		conn.inUse = true
+		db.mu.Unlock()
+		return conn, nil
+	}
+
+	db.numOpen++ // optimistically
+	db.mu.Unlock()
+	ci, err := db.driver.Open(db.dsn)
+	if err != nil {
+		db.mu.Lock()
+		db.numOpen-- // correct for earlier optimism
+		db.mu.Unlock()
+		return nil, err
+	}
+	db.mu.Lock()
+	dc := &driverConn{
+		db: db,
+		ci: ci,
+	}
+	db.addDepLocked(dc, dc)
+	dc.inUse = true
+	db.mu.Unlock()
+	return dc, nil
+}
+
+var (
+	errConnClosed = errors.New("database/sql: internal sentinel error: conn is closed")
+	errConnBusy   = errors.New("database/sql: internal sentinel error: conn is busy")
+)
+
+// connIfFree returns (wanted, nil) if wanted is still a valid conn and
+// isn't in use.
+//
+// The error is errConnClosed if the connection if the requested connection
+// is invalid because it's been closed.
+//
+// The error is errConnBusy if the connection is in use.
+func (db *DB) connIfFree(wanted *driverConn) (*driverConn, error) {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	if wanted.dbmuClosed {
+		return nil, errConnClosed
+	}
+	if wanted.inUse {
+		return nil, errConnBusy
+	}
+	if wanted.listElem != nil {
+		db.freeConn.Remove(wanted.listElem)
+		wanted.listElem = nil
+		wanted.inUse = true
+		return wanted, nil
+	}
+	// TODO(bradfitz): shouldn't get here. After Go 1.1, change this to:
+	// panic("connIfFree call requested a non-closed, non-busy, non-free conn")
+	// Which passes all the tests, but I'm too paranoid to include this
+	// late in Go 1.1.
+	// Instead, treat it like a busy connection:
+	return nil, errConnBusy
+}
+
+// putConnHook is a hook for testing.
+var putConnHook func(*DB, *driverConn)
+
+// noteUnusedDriverStatement notes that si is no longer used and should
+// be closed whenever possible (when c is next not in use), unless c is
+// already closed.
+func (db *DB) noteUnusedDriverStatement(c *driverConn, si driver.Stmt) {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	if c.inUse {
+		c.onPut = append(c.onPut, func() {
+			si.Close()
+		})
+	} else {
+		c.Lock()
+		defer c.Unlock()
+		if !c.finalClosed {
+			si.Close()
+		}
+	}
+}
+
+// debugGetPut determines whether getConn & putConn calls' stack traces
+// are returned for more verbose crashes.
+const debugGetPut = false
+
+// putConn adds a connection to the db's free pool.
+// err is optionally the last error that occurred on this connection.
+func (db *DB) putConn(dc *driverConn, err error) {
+	db.mu.Lock()
+	if !dc.inUse {
+		if debugGetPut {
+			fmt.Printf("putConn(%v) DUPLICATE was: %s\n\nPREVIOUS was: %s", dc, stack(), db.lastPut[dc])
+		}
+		panic("sql: connection returned that was never out")
+	}
+	if debugGetPut {
+		db.lastPut[dc] = stack()
+	}
+	dc.inUse = false
+
+	for _, fn := range dc.onPut {
+		fn()
+	}
+	dc.onPut = nil
+
+	if err == driver.ErrBadConn {
+		// Don't reuse bad connections.
+		// Since the conn is considered bad and is being discarded, treat it
+		// as closed. Don't decrement the open count here, finalClose will
+		// take care of that.
+		db.maybeOpenNewConnections()
+		db.mu.Unlock()
+		dc.Close()
+		return
+	}
+	if putConnHook != nil {
+		putConnHook(db, dc)
+	}
+	added := db.putConnDBLocked(dc, nil)
+	db.mu.Unlock()
+
+	if !added {
+		dc.Close()
+	}
+}
+
+// Satisfy a connRequest or put the driverConn in the idle pool and return true
+// or return false.
+// putConnDBLocked will satisfy a connRequest if there is one, or it will
+// return the *driverConn to the freeConn list if err == nil and the idle
+// connection limit will not be exceeded.
+// If err != nil, the value of dc is ignored.
+// If err == nil, then dc must not equal nil.
+// If a connRequest was fulfilled or the *driverConn was placed in the
+// freeConn list, then true is returned, otherwise false is returned.
+func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
+	if db.connRequests.Len() > 0 {
+		req := db.connRequests.Front().Value.(connRequest)
+		db.connRequests.Remove(db.connRequests.Front())
+		if err != nil {
+			req <- err
+		} else {
+			dc.inUse = true
+			req <- dc
+		}
+		return true
+	} else if err == nil && !db.closed && db.maxIdleConnsLocked() > db.freeConn.Len() {
+		dc.listElem = db.freeConn.PushFront(dc)
+		return true
+	}
+	return false
+}
+
+// maxBadConnRetries is the number of maximum retries if the driver returns
+// driver.ErrBadConn to signal a broken connection.
+const maxBadConnRetries = 10
+
+// Prepare creates a prepared statement for later queries or executions.
+// Multiple queries or executions may be run concurrently from the
+// returned statement.
+func (db *DB) Prepare(query string) (*Stmt, error) {
+	var stmt *Stmt
+	var err error
+	for i := 0; i < maxBadConnRetries; i++ {
+		stmt, err = db.prepare(query)
+		if err != driver.ErrBadConn {
+			break
+		}
+	}
+	return stmt, err
+}
+
+func (db *DB) prepare(query string) (*Stmt, error) {
+	// TODO: check if db.driver supports an optional
+	// driver.Preparer interface and call that instead, if so,
+	// otherwise we make a prepared statement that's bound
+	// to a connection, and to execute this prepared statement
+	// we either need to use this connection (if it's free), else
+	// get a new connection + re-prepare + execute on that one.
+	dc, err := db.conn()
+	if err != nil {
+		return nil, err
+	}
+	dc.Lock()
+	si, err := dc.prepareLocked(query)
+	dc.Unlock()
+	if err != nil {
+		db.putConn(dc, err)
+		return nil, err
+	}
+	stmt := &Stmt{
+		db:    db,
+		query: query,
+		css:   []connStmt{{dc, si}},
+	}
+	db.addDep(stmt, stmt)
+	db.putConn(dc, nil)
+	return stmt, nil
+}
+
+// Exec executes a query without returning any rows.
+// The args are for any placeholder parameters in the query.
+func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
+	var res Result
+	var err error
+	for i := 0; i < maxBadConnRetries; i++ {
+		res, err = db.exec(query, args)
+		if err != driver.ErrBadConn {
+			break
+		}
+	}
+	return res, err
+}
+
+func (db *DB) exec(query string, args []interface{}) (res Result, err error) {
+	dc, err := db.conn()
+	if err != nil {
+		return nil, err
+	}
+	defer func() {
+		db.putConn(dc, err)
+	}()
+
+	if execer, ok := dc.ci.(driver.Execer); ok {
+		dargs, err := driverArgs(nil, args)
+		if err != nil {
+			return nil, err
+		}
+		dc.Lock()
+		resi, err := execer.Exec(query, dargs)
+		dc.Unlock()
+		if err != driver.ErrSkip {
+			if err != nil {
+				return nil, err
+			}
+			return driverResult{dc, resi}, nil
+		}
+	}
+
+	dc.Lock()
+	si, err := dc.ci.Prepare(query)
+	dc.Unlock()
+	if err != nil {
+		return nil, err
+	}
+	defer withLock(dc, func() { si.Close() })
+	return resultFromStatement(driverStmt{dc, si}, args...)
+}
+
+// Query executes a query that returns rows, typically a SELECT.
+// The args are for any placeholder parameters in the query.
+func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
+	var rows *Rows
+	var err error
+	for i := 0; i < maxBadConnRetries; i++ {
+		rows, err = db.query(query, args)
+		if err != driver.ErrBadConn {
+			break
+		}
+	}
+	return rows, err
+}
+
+func (db *DB) query(query string, args []interface{}) (*Rows, error) {
+	ci, err := db.conn()
+	if err != nil {
+		return nil, err
+	}
+
+	return db.queryConn(ci, ci.releaseConn, query, args)
+}
+
+// queryConn executes a query on the given connection.
+// The connection gets released by the releaseConn function.
+func (db *DB) queryConn(dc *driverConn, releaseConn func(error), query string, args []interface{}) (*Rows, error) {
+	if queryer, ok := dc.ci.(driver.Queryer); ok {
+		dargs, err := driverArgs(nil, args)
+		if err != nil {
+			releaseConn(err)
+			return nil, err
+		}
+		dc.Lock()
+		rowsi, err := queryer.Query(query, dargs)
+		dc.Unlock()
+		if err != driver.ErrSkip {
+			if err != nil {
+				releaseConn(err)
+				return nil, err
+			}
+			// Note: ownership of dc passes to the *Rows, to be freed
+			// with releaseConn.
+			rows := &Rows{
+				dc:          dc,
+				releaseConn: releaseConn,
+				rowsi:       rowsi,
+			}
+			return rows, nil
+		}
+	}
+
+	dc.Lock()
+	si, err := dc.ci.Prepare(query)
+	dc.Unlock()
+	if err != nil {
+		releaseConn(err)
+		return nil, err
+	}
+
+	ds := driverStmt{dc, si}
+	rowsi, err := rowsiFromStatement(ds, args...)
+	if err != nil {
+		dc.Lock()
+		si.Close()
+		dc.Unlock()
+		releaseConn(err)
+		return nil, err
+	}
+
+	// Note: ownership of ci passes to the *Rows, to be freed
+	// with releaseConn.
+	rows := &Rows{
+		dc:          dc,
+		releaseConn: releaseConn,
+		rowsi:       rowsi,
+		closeStmt:   si,
+	}
+	return rows, nil
+}
+
+// QueryRow executes a query that is expected to return at most one row.
+// QueryRow always return a non-nil value. Errors are deferred until
+// Row's Scan method is called.
+func (db *DB) QueryRow(query string, args ...interface{}) *Row {
+	rows, err := db.Query(query, args...)
+	return &Row{rows: rows, err: err}
+}
+
+// Begin starts a transaction. The isolation level is dependent on
+// the driver.
+func (db *DB) Begin() (*Tx, error) {
+	var tx *Tx
+	var err error
+	for i := 0; i < maxBadConnRetries; i++ {
+		tx, err = db.begin()
+		if err != driver.ErrBadConn {
+			break
+		}
+	}
+	return tx, err
+}
+
+func (db *DB) begin() (tx *Tx, err error) {
+	dc, err := db.conn()
+	if err != nil {
+		return nil, err
+	}
+	dc.Lock()
+	txi, err := dc.ci.Begin()
+	dc.Unlock()
+	if err != nil {
+		db.putConn(dc, err)
+		return nil, err
+	}
+	return &Tx{
+		db:  db,
+		dc:  dc,
+		txi: txi,
+	}, nil
+}
+
+// Driver returns the database's underlying driver.
+func (db *DB) Driver() driver.Driver {
+	return db.driver
+}
+
+// Tx is an in-progress database transaction.
+//
+// A transaction must end with a call to Commit or Rollback.
+//
+// After a call to Commit or Rollback, all operations on the
+// transaction fail with ErrTxDone.
+type Tx struct {
+	db *DB
+
+	// dc is owned exclusively until Commit or Rollback, at which point
+	// it's returned with putConn.
+	dc  *driverConn
+	txi driver.Tx
+
+	// done transitions from false to true exactly once, on Commit
+	// or Rollback. once done, all operations fail with
+	// ErrTxDone.
+	done bool
+}
+
+var ErrTxDone = errors.New("sql: Transaction has already been committed or rolled back")
+
+func (tx *Tx) close() {
+	if tx.done {
+		panic("double close") // internal error
+	}
+	tx.done = true
+	tx.db.putConn(tx.dc, nil)
+	tx.dc = nil
+	tx.txi = nil
+}
+
+func (tx *Tx) grabConn() (*driverConn, error) {
+	if tx.done {
+		return nil, ErrTxDone
+	}
+	return tx.dc, nil
+}
+
+// Commit commits the transaction.
+func (tx *Tx) Commit() error {
+	if tx.done {
+		return ErrTxDone
+	}
+	defer tx.close()
+	tx.dc.Lock()
+	defer tx.dc.Unlock()
+	return tx.txi.Commit()
+}
+
+// Rollback aborts the transaction.
+func (tx *Tx) Rollback() error {
+	if tx.done {
+		return ErrTxDone
+	}
+	defer tx.close()
+	tx.dc.Lock()
+	defer tx.dc.Unlock()
+	return tx.txi.Rollback()
+}
+
+// Prepare creates a prepared statement for use within a transaction.
+//
+// The returned statement operates within the transaction and can no longer
+// be used once the transaction has been committed or rolled back.
+//
+// To use an existing prepared statement on this transaction, see Tx.Stmt.
+func (tx *Tx) Prepare(query string) (*Stmt, error) {
+	// TODO(bradfitz): We could be more efficient here and either
+	// provide a method to take an existing Stmt (created on
+	// perhaps a different Conn), and re-create it on this Conn if
+	// necessary. Or, better: keep a map in DB of query string to
+	// Stmts, and have Stmt.Execute do the right thing and
+	// re-prepare if the Conn in use doesn't have that prepared
+	// statement.  But we'll want to avoid caching the statement
+	// in the case where we only call conn.Prepare implicitly
+	// (such as in db.Exec or tx.Exec), but the caller package
+	// can't be holding a reference to the returned statement.
+	// Perhaps just looking at the reference count (by noting
+	// Stmt.Close) would be enough. We might also want a finalizer
+	// on Stmt to drop the reference count.
+	dc, err := tx.grabConn()
+	if err != nil {
+		return nil, err
+	}
+
+	dc.Lock()
+	si, err := dc.ci.Prepare(query)
+	dc.Unlock()
+	if err != nil {
+		return nil, err
+	}
+
+	stmt := &Stmt{
+		db: tx.db,
+		tx: tx,
+		txsi: &driverStmt{
+			Locker: dc,
+			si:     si,
+		},
+		query: query,
+	}
+	return stmt, nil
+}
+
+// Stmt returns a transaction-specific prepared statement from
+// an existing statement.
+//
+// Example:
+//  updateMoney, err := db.Prepare("UPDATE balance SET money=money+? WHERE id=?")
+//  ...
+//  tx, err := db.Begin()
+//  ...
+//  res, err := tx.Stmt(updateMoney).Exec(123.45, 98293203)
+func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
+	// TODO(bradfitz): optimize this. Currently this re-prepares
+	// each time.  This is fine for now to illustrate the API but
+	// we should really cache already-prepared statements
+	// per-Conn. See also the big comment in Tx.Prepare.
+
+	if tx.db != stmt.db {
+		return &Stmt{stickyErr: errors.New("sql: Tx.Stmt: statement from different database used")}
+	}
+	dc, err := tx.grabConn()
+	if err != nil {
+		return &Stmt{stickyErr: err}
+	}
+	dc.Lock()
+	si, err := dc.ci.Prepare(stmt.query)
+	dc.Unlock()
+	return &Stmt{
+		db: tx.db,
+		tx: tx,
+		txsi: &driverStmt{
+			Locker: dc,
+			si:     si,
+		},
+		query:     stmt.query,
+		stickyErr: err,
+	}
+}
+
+// Exec executes a query that doesn't return rows.
+// For example: an INSERT and UPDATE.
+func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
+	dc, err := tx.grabConn()
+	if err != nil {
+		return nil, err
+	}
+
+	if execer, ok := dc.ci.(driver.Execer); ok {
+		dargs, err := driverArgs(nil, args)
+		if err != nil {
+			return nil, err
+		}
+		dc.Lock()
+		resi, err := execer.Exec(query, dargs)
+		dc.Unlock()
+		if err == nil {
+			return driverResult{dc, resi}, nil
+		}
+		if err != driver.ErrSkip {
+			return nil, err
+		}
+	}
+
+	dc.Lock()
+	si, err := dc.ci.Prepare(query)
+	dc.Unlock()
+	if err != nil {
+		return nil, err
+	}
+	defer withLock(dc, func() { si.Close() })
+
+	return resultFromStatement(driverStmt{dc, si}, args...)
+}
+
+// Query executes a query that returns rows, typically a SELECT.
+func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
+	dc, err := tx.grabConn()
+	if err != nil {
+		return nil, err
+	}
+	releaseConn := func(error) {}
+	return tx.db.queryConn(dc, releaseConn, query, args)
+}
+
+// QueryRow executes a query that is expected to return at most one row.
+// QueryRow always return a non-nil value. Errors are deferred until
+// Row's Scan method is called.
+func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
+	rows, err := tx.Query(query, args...)
+	return &Row{rows: rows, err: err}
+}
+
+// connStmt is a prepared statement on a particular connection.
+type connStmt struct {
+	dc *driverConn
+	si driver.Stmt
+}
+
+// Stmt is a prepared statement. Stmt is safe for concurrent use by multiple goroutines.
+type Stmt struct {
+	// Immutable:
+	db        *DB    // where we came from
+	query     string // that created the Stmt
+	stickyErr error  // if non-nil, this error is returned for all operations
+
+	closemu sync.RWMutex // held exclusively during close, for read otherwise.
+
+	// If in a transaction, else both nil:
+	tx   *Tx
+	txsi *driverStmt
+
+	mu     sync.Mutex // protects the rest of the fields
+	closed bool
+
+	// css is a list of underlying driver statement interfaces
+	// that are valid on particular connections.  This is only
+	// used if tx == nil and one is found that has idle
+	// connections.  If tx != nil, txsi is always used.
+	css []connStmt
+}
+
+// Exec executes a prepared statement with the given arguments and
+// returns a Result summarizing the effect of the statement.
+func (s *Stmt) Exec(args ...interface{}) (Result, error) {
+	s.closemu.RLock()
+	defer s.closemu.RUnlock()
+
+	var res Result
+	for i := 0; i < maxBadConnRetries; i++ {
+		dc, releaseConn, si, err := s.connStmt()
+		if err != nil {
+			if err == driver.ErrBadConn {
+				continue
+			}
+			return nil, err
+		}
+
+		res, err = resultFromStatement(driverStmt{dc, si}, args...)
+		releaseConn(err)
+		if err != driver.ErrBadConn {
+			return res, err
+		}
+	}
+	return nil, driver.ErrBadConn
+}
+
+func resultFromStatement(ds driverStmt, args ...interface{}) (Result, error) {
+	ds.Lock()
+	want := ds.si.NumInput()
+	ds.Unlock()
+
+	// -1 means the driver doesn't know how to count the number of
+	// placeholders, so we won't sanity check input here and instead let the
+	// driver deal with errors.
+	if want != -1 && len(args) != want {
+		return nil, fmt.Errorf("sql: expected %d arguments, got %d", want, len(args))
+	}
+
+	dargs, err := driverArgs(&ds, args)
+	if err != nil {
+		return nil, err
+	}
+
+	ds.Lock()
+	resi, err := ds.si.Exec(dargs)
+	ds.Unlock()
+	if err != nil {
+		return nil, err
+	}
+	return driverResult{ds.Locker, resi}, nil
+}
+
+// connStmt returns a free driver connection on which to execute the
+// statement, a function to call to release the connection, and a
+// statement bound to that connection.
+func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.Stmt, err error) {
+	if err = s.stickyErr; err != nil {
+		return
+	}
+	s.mu.Lock()
+	if s.closed {
+		s.mu.Unlock()
+		err = errors.New("sql: statement is closed")
+		return
+	}
+
+	// In a transaction, we always use the connection that the
+	// transaction was created on.
+	if s.tx != nil {
+		s.mu.Unlock()
+		ci, err = s.tx.grabConn() // blocks, waiting for the connection.
+		if err != nil {
+			return
+		}
+		releaseConn = func(error) {}
+		return ci, releaseConn, s.txsi.si, nil
+	}
+
+	var cs connStmt
+	match := false
+	for i := 0; i < len(s.css); i++ {
+		v := s.css[i]
+		_, err := s.db.connIfFree(v.dc)
+		if err == nil {
+			match = true
+			cs = v
+			break
+		}
+		if err == errConnClosed {
+			// Lazily remove dead conn from our freelist.
+			s.css[i] = s.css[len(s.css)-1]
+			s.css = s.css[:len(s.css)-1]
+			i--
+		}
+
+	}
+	s.mu.Unlock()
+
+	// Make a new conn if all are busy.
+	// TODO(bradfitz): or wait for one? make configurable later?
+	if !match {
+		dc, err := s.db.conn()
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		dc.Lock()
+		si, err := dc.prepareLocked(s.query)
+		dc.Unlock()
+		if err != nil {
+			s.db.putConn(dc, err)
+			return nil, nil, nil, err
+		}
+		s.mu.Lock()
+		cs = connStmt{dc, si}
+		s.css = append(s.css, cs)
+		s.mu.Unlock()
+	}
+
+	conn := cs.dc
+	return conn, conn.releaseConn, cs.si, nil
+}
+
+// Query executes a prepared query statement with the given arguments
+// and returns the query results as a *Rows.
+func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
+	s.closemu.RLock()
+	defer s.closemu.RUnlock()
+
+	var rowsi driver.Rows
+	for i := 0; i < maxBadConnRetries; i++ {
+		dc, releaseConn, si, err := s.connStmt()
+		if err != nil {
+			if err == driver.ErrBadConn {
+				continue
+			}
+			return nil, err
+		}
+
+		rowsi, err = rowsiFromStatement(driverStmt{dc, si}, args...)
+		if err == nil {
+			// Note: ownership of ci passes to the *Rows, to be freed
+			// with releaseConn.
+			rows := &Rows{
+				dc:    dc,
+				rowsi: rowsi,
+				// releaseConn set below
+			}
+			s.db.addDep(s, rows)
+			rows.releaseConn = func(err error) {
+				releaseConn(err)
+				s.db.removeDep(s, rows)
+			}
+			return rows, nil
+		}
+
+		releaseConn(err)
+		if err != driver.ErrBadConn {
+			return nil, err
+		}
+	}
+	return nil, driver.ErrBadConn
+}
+
+func rowsiFromStatement(ds driverStmt, args ...interface{}) (driver.Rows, error) {
+	ds.Lock()
+	want := ds.si.NumInput()
+	ds.Unlock()
+
+	// -1 means the driver doesn't know how to count the number of
+	// placeholders, so we won't sanity check input here and instead let the
+	// driver deal with errors.
+	if want != -1 && len(args) != want {
+		return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", want, len(args))
+	}
+
+	dargs, err := driverArgs(&ds, args)
+	if err != nil {
+		return nil, err
+	}
+
+	ds.Lock()
+	rowsi, err := ds.si.Query(dargs)
+	ds.Unlock()
+	if err != nil {
+		return nil, err
+	}
+	return rowsi, nil
+}
+
+// QueryRow executes a prepared query statement with the given arguments.
+// If an error occurs during the execution of the statement, that error will
+// be returned by a call to Scan on the returned *Row, which is always non-nil.
+// If the query selects no rows, the *Row's Scan will return ErrNoRows.
+// Otherwise, the *Row's Scan scans the first selected row and discards
+// the rest.
+//
+// Example usage:
+//
+//  var name string
+//  err := nameByUseridStmt.QueryRow(id).Scan(&name)
+func (s *Stmt) QueryRow(args ...interface{}) *Row {
+	rows, err := s.Query(args...)
+	if err != nil {
+		return &Row{err: err}
+	}
+	return &Row{rows: rows}
+}
+
+// Close closes the statement.
+func (s *Stmt) Close() error {
+	s.closemu.Lock()
+	defer s.closemu.Unlock()
+
+	if s.stickyErr != nil {
+		return s.stickyErr
+	}
+	s.mu.Lock()
+	if s.closed {
+		s.mu.Unlock()
+		return nil
+	}
+	s.closed = true
+
+	if s.tx != nil {
+		s.txsi.Close()
+		s.mu.Unlock()
+		return nil
+	}
+	s.mu.Unlock()
+
+	return s.db.removeDep(s, s)
+}
+
+func (s *Stmt) finalClose() error {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+	if s.css != nil {
+		for _, v := range s.css {
+			s.db.noteUnusedDriverStatement(v.dc, v.si)
+			v.dc.removeOpenStmt(v.si)
+		}
+		s.css = nil
+	}
+	return nil
+}
+
+// Rows is the result of a query. Its cursor starts before the first row
+// of the result set. Use Next to advance through the rows:
+//
+//     rows, err := db.Query("SELECT ...")
+//     ...
+//     defer rows.Close()
+//     for rows.Next() {
+//         var id int
+//         var name string
+//         err = rows.Scan(&id, &name)
+//         ...
+//     }
+//     err = rows.Err() // get any error encountered during iteration
+//     ...
+type Rows struct {
+	dc          *driverConn // owned; must call releaseConn when closed to release
+	releaseConn func(error)
+	rowsi       driver.Rows
+
+	closed    bool
+	lastcols  []driver.Value
+	lasterr   error       // non-nil only if closed is true
+	closeStmt driver.Stmt // if non-nil, statement to Close on close
+}
+
+// Next prepares the next result row for reading with the Scan method.  It
+// returns true on success, or false if there is no next result row or an error
+// happened while preparing it.  Err should be consulted to distinguish between
+// the two cases.
+//
+// Every call to Scan, even the first one, must be preceded by a call to Next.
+func (rs *Rows) Next() bool {
+	if rs.closed {
+		return false
+	}
+	if rs.lastcols == nil {
+		rs.lastcols = make([]driver.Value, len(rs.rowsi.Columns()))
+	}
+	rs.lasterr = rs.rowsi.Next(rs.lastcols)
+	if rs.lasterr != nil {
+		rs.Close()
+		return false
+	}
+	return true
+}
+
+// Err returns the error, if any, that was encountered during iteration.
+// Err may be called after an explicit or implicit Close.
+func (rs *Rows) Err() error {
+	if rs.lasterr == io.EOF {
+		return nil
+	}
+	return rs.lasterr
+}
+
+// Columns returns the column names.
+// Columns returns an error if the rows are closed, or if the rows
+// are from QueryRow and there was a deferred error.
+func (rs *Rows) Columns() ([]string, error) {
+	if rs.closed {
+		return nil, errors.New("sql: Rows are closed")
+	}
+	if rs.rowsi == nil {
+		return nil, errors.New("sql: no Rows available")
+	}
+	return rs.rowsi.Columns(), nil
+}
+
+// Scan copies the columns in the current row into the values pointed
+// at by dest.
+//
+// If an argument has type *[]byte, Scan saves in that argument a copy
+// of the corresponding data. The copy is owned by the caller and can
+// be modified and held indefinitely. The copy can be avoided by using
+// an argument of type *RawBytes instead; see the documentation for
+// RawBytes for restrictions on its use.
+//
+// If an argument has type *interface{}, Scan copies the value
+// provided by the underlying driver without conversion. If the value
+// is of type []byte, a copy is made and the caller owns the result.
+func (rs *Rows) Scan(dest ...interface{}) error {
+	if rs.closed {
+		return errors.New("sql: Rows are closed")
+	}
+	if rs.lastcols == nil {
+		return errors.New("sql: Scan called without calling Next")
+	}
+	if len(dest) != len(rs.lastcols) {
+		return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
+	}
+	for i, sv := range rs.lastcols {
+		err := convertAssign(dest[i], sv)
+		if err != nil {
+			return fmt.Errorf("sql: Scan error on column index %d: %v", i, err)
+		}
+	}
+	return nil
+}
+
+var rowsCloseHook func(*Rows, *error)
+
+// Close closes the Rows, preventing further enumeration. If Next returns
+// false, the Rows are closed automatically and it will suffice to check the
+// result of Err. Close is idempotent and does not affect the result of Err.
+func (rs *Rows) Close() error {
+	if rs.closed {
+		return nil
+	}
+	rs.closed = true
+	err := rs.rowsi.Close()
+	if fn := rowsCloseHook; fn != nil {
+		fn(rs, &err)
+	}
+	if rs.closeStmt != nil {
+		rs.closeStmt.Close()
+	}
+	rs.releaseConn(err)
+	return err
+}
+
+// Row is the result of calling QueryRow to select a single row.
+type Row struct {
+	// One of these two will be non-nil:
+	err  error // deferred error for easy chaining
+	rows *Rows
+}
+
+// Scan copies the columns from the matched row into the values
+// pointed at by dest.  If more than one row matches the query,
+// Scan uses the first row and discards the rest.  If no row matches
+// the query, Scan returns ErrNoRows.
+func (r *Row) Scan(dest ...interface{}) error {
+	if r.err != nil {
+		return r.err
+	}
+
+	// TODO(bradfitz): for now we need to defensively clone all
+	// []byte that the driver returned (not permitting
+	// *RawBytes in Rows.Scan), since we're about to close
+	// the Rows in our defer, when we return from this function.
+	// the contract with the driver.Next(...) interface is that it
+	// can return slices into read-only temporary memory that's
+	// only valid until the next Scan/Close.  But the TODO is that
+	// for a lot of drivers, this copy will be unnecessary.  We
+	// should provide an optional interface for drivers to
+	// implement to say, "don't worry, the []bytes that I return
+	// from Next will not be modified again." (for instance, if
+	// they were obtained from the network anyway) But for now we
+	// don't care.
+	defer r.rows.Close()
+	for _, dp := range dest {
+		if _, ok := dp.(*RawBytes); ok {
+			return errors.New("sql: RawBytes isn't allowed on Row.Scan")
+		}
+	}
+
+	if !r.rows.Next() {
+		if err := r.rows.Err(); err != nil {
+			return err
+		}
+		return ErrNoRows
+	}
+	err := r.rows.Scan(dest...)
+	if err != nil {
+		return err
+	}
+	// Make sure the query can be processed to completion with no errors.
+	if err := r.rows.Close(); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// A Result summarizes an executed SQL command.
+type Result interface {
+	// LastInsertId returns the integer generated by the database
+	// in response to a command. Typically this will be from an
+	// "auto increment" column when inserting a new row. Not all
+	// databases support this feature, and the syntax of such
+	// statements varies.
+	LastInsertId() (int64, error)
+
+	// RowsAffected returns the number of rows affected by an
+	// update, insert, or delete. Not every database or database
+	// driver may support this.
+	RowsAffected() (int64, error)
+}
+
+type driverResult struct {
+	sync.Locker // the *driverConn
+	resi        driver.Result
+}
+
+func (dr driverResult) LastInsertId() (int64, error) {
+	dr.Lock()
+	defer dr.Unlock()
+	return dr.resi.LastInsertId()
+}
+
+func (dr driverResult) RowsAffected() (int64, error) {
+	dr.Lock()
+	defer dr.Unlock()
+	return dr.resi.RowsAffected()
+}
+
+func stack() string {
+	var buf [2 << 10]byte
+	return string(buf[:runtime.Stack(buf[:], false)])
+}
+
+// withLock runs while holding lk.
+func withLock(lk sync.Locker, fn func()) {
+	lk.Lock()
+	fn()
+	lk.Unlock()
+}
diff --git a/third_party/gofrontend/libgo/go/database/sql/sql_test.go b/third_party/gofrontend/libgo/go/database/sql/sql_test.go
new file mode 100644
index 0000000..7971f14
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/database/sql/sql_test.go
@@ -0,0 +1,1949 @@
+// 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.
+
+package sql
+
+import (
+	"database/sql/driver"
+	"errors"
+	"fmt"
+	"math/rand"
+	"reflect"
+	"runtime"
+	"strings"
+	"sync"
+	"testing"
+	"time"
+)
+
+func init() {
+	type dbConn struct {
+		db *DB
+		c  *driverConn
+	}
+	freedFrom := make(map[dbConn]string)
+	putConnHook = func(db *DB, c *driverConn) {
+		if c.listElem != nil {
+			// print before panic, as panic may get lost due to conflicting panic
+			// (all goroutines asleep) elsewhere, since we might not unlock
+			// the mutex in freeConn here.
+			println("double free of conn. conflicts are:\nA) " + freedFrom[dbConn{db, c}] + "\n\nand\nB) " + stack())
+			panic("double free of conn.")
+		}
+		freedFrom[dbConn{db, c}] = stack()
+	}
+}
+
+const fakeDBName = "foo"
+
+var chrisBirthday = time.Unix(123456789, 0)
+
+func newTestDB(t testing.TB, name string) *DB {
+	db, err := Open("test", fakeDBName)
+	if err != nil {
+		t.Fatalf("Open: %v", err)
+	}
+	if _, err := db.Exec("WIPE"); err != nil {
+		t.Fatalf("exec wipe: %v", err)
+	}
+	if name == "people" {
+		exec(t, db, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime")
+		exec(t, db, "INSERT|people|name=Alice,age=?,photo=APHOTO", 1)
+		exec(t, db, "INSERT|people|name=Bob,age=?,photo=BPHOTO", 2)
+		exec(t, db, "INSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
+	}
+	if name == "magicquery" {
+		// Magic table name and column, known by fakedb_test.go.
+		exec(t, db, "CREATE|magicquery|op=string,millis=int32")
+		exec(t, db, "INSERT|magicquery|op=sleep,millis=10")
+	}
+	return db
+}
+
+func exec(t testing.TB, db *DB, query string, args ...interface{}) {
+	_, err := db.Exec(query, args...)
+	if err != nil {
+		t.Fatalf("Exec of %q: %v", query, err)
+	}
+}
+
+func closeDB(t testing.TB, db *DB) {
+	if e := recover(); e != nil {
+		fmt.Printf("Panic: %v\n", e)
+		panic(e)
+	}
+	defer setHookpostCloseConn(nil)
+	setHookpostCloseConn(func(_ *fakeConn, err error) {
+		if err != nil {
+			t.Errorf("Error closing fakeConn: %v", err)
+		}
+	})
+	for node, i := db.freeConn.Front(), 0; node != nil; node, i = node.Next(), i+1 {
+		dc := node.Value.(*driverConn)
+		if n := len(dc.openStmt); n > 0 {
+			// Just a sanity check. This is legal in
+			// general, but if we make the tests clean up
+			// their statements first, then we can safely
+			// verify this is always zero here, and any
+			// other value is a leak.
+			t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, db.freeConn.Len(), n)
+		}
+	}
+	err := db.Close()
+	if err != nil {
+		t.Fatalf("error closing DB: %v", err)
+	}
+	db.mu.Lock()
+	count := db.numOpen
+	db.mu.Unlock()
+	if count != 0 {
+		t.Fatalf("%d connections still open after closing DB", db.numOpen)
+	}
+}
+
+// numPrepares assumes that db has exactly 1 idle conn and returns
+// its count of calls to Prepare
+func numPrepares(t *testing.T, db *DB) int {
+	if n := db.freeConn.Len(); n != 1 {
+		t.Fatalf("free conns = %d; want 1", n)
+	}
+	return (db.freeConn.Front().Value.(*driverConn)).ci.(*fakeConn).numPrepare
+}
+
+func (db *DB) numDeps() int {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	return len(db.dep)
+}
+
+// Dependencies are closed via a goroutine, so this polls waiting for
+// numDeps to fall to want, waiting up to d.
+func (db *DB) numDepsPollUntil(want int, d time.Duration) int {
+	deadline := time.Now().Add(d)
+	for {
+		n := db.numDeps()
+		if n <= want || time.Now().After(deadline) {
+			return n
+		}
+		time.Sleep(50 * time.Millisecond)
+	}
+}
+
+func (db *DB) numFreeConns() int {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	return db.freeConn.Len()
+}
+
+func (db *DB) dumpDeps(t *testing.T) {
+	for fc := range db.dep {
+		db.dumpDep(t, 0, fc, map[finalCloser]bool{})
+	}
+}
+
+func (db *DB) dumpDep(t *testing.T, depth int, dep finalCloser, seen map[finalCloser]bool) {
+	seen[dep] = true
+	indent := strings.Repeat("  ", depth)
+	ds := db.dep[dep]
+	for k := range ds {
+		t.Logf("%s%T (%p) waiting for -> %T (%p)", indent, dep, dep, k, k)
+		if fc, ok := k.(finalCloser); ok {
+			if !seen[fc] {
+				db.dumpDep(t, depth+1, fc, seen)
+			}
+		}
+	}
+}
+
+func TestQuery(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	prepares0 := numPrepares(t, db)
+	rows, err := db.Query("SELECT|people|age,name|")
+	if err != nil {
+		t.Fatalf("Query: %v", err)
+	}
+	type row struct {
+		age  int
+		name string
+	}
+	got := []row{}
+	for rows.Next() {
+		var r row
+		err = rows.Scan(&r.age, &r.name)
+		if err != nil {
+			t.Fatalf("Scan: %v", err)
+		}
+		got = append(got, r)
+	}
+	err = rows.Err()
+	if err != nil {
+		t.Fatalf("Err: %v", err)
+	}
+	want := []row{
+		{age: 1, name: "Alice"},
+		{age: 2, name: "Bob"},
+		{age: 3, name: "Chris"},
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
+	}
+
+	// And verify that the final rows.Next() call, which hit EOF,
+	// also closed the rows connection.
+	if n := db.numFreeConns(); n != 1 {
+		t.Fatalf("free conns after query hitting EOF = %d; want 1", n)
+	}
+	if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
+		t.Errorf("executed %d Prepare statements; want 1", prepares)
+	}
+}
+
+func TestByteOwnership(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	rows, err := db.Query("SELECT|people|name,photo|")
+	if err != nil {
+		t.Fatalf("Query: %v", err)
+	}
+	type row struct {
+		name  []byte
+		photo RawBytes
+	}
+	got := []row{}
+	for rows.Next() {
+		var r row
+		err = rows.Scan(&r.name, &r.photo)
+		if err != nil {
+			t.Fatalf("Scan: %v", err)
+		}
+		got = append(got, r)
+	}
+	corruptMemory := []byte("\xffPHOTO")
+	want := []row{
+		{name: []byte("Alice"), photo: corruptMemory},
+		{name: []byte("Bob"), photo: corruptMemory},
+		{name: []byte("Chris"), photo: corruptMemory},
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
+	}
+
+	var photo RawBytes
+	err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo)
+	if err == nil {
+		t.Error("want error scanning into RawBytes from QueryRow")
+	}
+}
+
+func TestRowsColumns(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	rows, err := db.Query("SELECT|people|age,name|")
+	if err != nil {
+		t.Fatalf("Query: %v", err)
+	}
+	cols, err := rows.Columns()
+	if err != nil {
+		t.Fatalf("Columns: %v", err)
+	}
+	want := []string{"age", "name"}
+	if !reflect.DeepEqual(cols, want) {
+		t.Errorf("got %#v; want %#v", cols, want)
+	}
+	if err := rows.Close(); err != nil {
+		t.Errorf("error closing rows: %s", err)
+	}
+}
+
+func TestQueryRow(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	var name string
+	var age int
+	var birthday time.Time
+
+	err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age)
+	if err == nil || !strings.Contains(err.Error(), "expected 2 destination arguments") {
+		t.Errorf("expected error from wrong number of arguments; actually got: %v", err)
+	}
+
+	err = db.QueryRow("SELECT|people|bdate|age=?", 3).Scan(&birthday)
+	if err != nil || !birthday.Equal(chrisBirthday) {
+		t.Errorf("chris birthday = %v, err = %v; want %v", birthday, err, chrisBirthday)
+	}
+
+	err = db.QueryRow("SELECT|people|age,name|age=?", 2).Scan(&age, &name)
+	if err != nil {
+		t.Fatalf("age QueryRow+Scan: %v", err)
+	}
+	if name != "Bob" {
+		t.Errorf("expected name Bob, got %q", name)
+	}
+	if age != 2 {
+		t.Errorf("expected age 2, got %d", age)
+	}
+
+	err = db.QueryRow("SELECT|people|age,name|name=?", "Alice").Scan(&age, &name)
+	if err != nil {
+		t.Fatalf("name QueryRow+Scan: %v", err)
+	}
+	if name != "Alice" {
+		t.Errorf("expected name Alice, got %q", name)
+	}
+	if age != 1 {
+		t.Errorf("expected age 1, got %d", age)
+	}
+
+	var photo []byte
+	err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo)
+	if err != nil {
+		t.Fatalf("photo QueryRow+Scan: %v", err)
+	}
+	want := []byte("APHOTO")
+	if !reflect.DeepEqual(photo, want) {
+		t.Errorf("photo = %q; want %q", photo, want)
+	}
+}
+
+func TestStatementErrorAfterClose(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	stmt, err := db.Prepare("SELECT|people|age|name=?")
+	if err != nil {
+		t.Fatalf("Prepare: %v", err)
+	}
+	err = stmt.Close()
+	if err != nil {
+		t.Fatalf("Close: %v", err)
+	}
+	var name string
+	err = stmt.QueryRow("foo").Scan(&name)
+	if err == nil {
+		t.Errorf("expected error from QueryRow.Scan after Stmt.Close")
+	}
+}
+
+func TestStatementQueryRow(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	stmt, err := db.Prepare("SELECT|people|age|name=?")
+	if err != nil {
+		t.Fatalf("Prepare: %v", err)
+	}
+	defer stmt.Close()
+	var age int
+	for n, tt := range []struct {
+		name string
+		want int
+	}{
+		{"Alice", 1},
+		{"Bob", 2},
+		{"Chris", 3},
+	} {
+		if err := stmt.QueryRow(tt.name).Scan(&age); err != nil {
+			t.Errorf("%d: on %q, QueryRow/Scan: %v", n, tt.name, err)
+		} else if age != tt.want {
+			t.Errorf("%d: age=%d, want %d", n, age, tt.want)
+		}
+	}
+}
+
+// golang.org/issue/3734
+func TestStatementQueryRowConcurrent(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	stmt, err := db.Prepare("SELECT|people|age|name=?")
+	if err != nil {
+		t.Fatalf("Prepare: %v", err)
+	}
+	defer stmt.Close()
+
+	const n = 10
+	ch := make(chan error, n)
+	for i := 0; i < n; i++ {
+		go func() {
+			var age int
+			err := stmt.QueryRow("Alice").Scan(&age)
+			if err == nil && age != 1 {
+				err = fmt.Errorf("unexpected age %d", age)
+			}
+			ch <- err
+		}()
+	}
+	for i := 0; i < n; i++ {
+		if err := <-ch; err != nil {
+			t.Error(err)
+		}
+	}
+}
+
+// just a test of fakedb itself
+func TestBogusPreboundParameters(t *testing.T) {
+	db := newTestDB(t, "foo")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	_, err := db.Prepare("INSERT|t1|name=?,age=bogusconversion")
+	if err == nil {
+		t.Fatalf("expected error")
+	}
+	if err.Error() != `fakedb: invalid conversion to int32 from "bogusconversion"` {
+		t.Errorf("unexpected error: %v", err)
+	}
+}
+
+func TestExec(t *testing.T) {
+	db := newTestDB(t, "foo")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+	if err != nil {
+		t.Errorf("Stmt, err = %v, %v", stmt, err)
+	}
+	defer stmt.Close()
+
+	type execTest struct {
+		args    []interface{}
+		wantErr string
+	}
+	execTests := []execTest{
+		// Okay:
+		{[]interface{}{"Brad", 31}, ""},
+		{[]interface{}{"Brad", int64(31)}, ""},
+		{[]interface{}{"Bob", "32"}, ""},
+		{[]interface{}{7, 9}, ""},
+
+		// Invalid conversions:
+		{[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument #1's type: sql/driver: value 4294967295 overflows int32"},
+		{[]interface{}{"Brad", "strconv fail"}, "sql: converting argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
+
+		// Wrong number of args:
+		{[]interface{}{}, "sql: expected 2 arguments, got 0"},
+		{[]interface{}{1, 2, 3}, "sql: expected 2 arguments, got 3"},
+	}
+	for n, et := range execTests {
+		_, err := stmt.Exec(et.args...)
+		errStr := ""
+		if err != nil {
+			errStr = err.Error()
+		}
+		if errStr != et.wantErr {
+			t.Errorf("stmt.Execute #%d: for %v, got error %q, want error %q",
+				n, et.args, errStr, et.wantErr)
+		}
+	}
+}
+
+func TestTxStmt(t *testing.T) {
+	db := newTestDB(t, "")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+	if err != nil {
+		t.Fatalf("Stmt, err = %v, %v", stmt, err)
+	}
+	defer stmt.Close()
+	tx, err := db.Begin()
+	if err != nil {
+		t.Fatalf("Begin = %v", err)
+	}
+	txs := tx.Stmt(stmt)
+	defer txs.Close()
+	_, err = txs.Exec("Bobby", 7)
+	if err != nil {
+		t.Fatalf("Exec = %v", err)
+	}
+	err = tx.Commit()
+	if err != nil {
+		t.Fatalf("Commit = %v", err)
+	}
+}
+
+// Issue: http://golang.org/issue/2784
+// This test didn't fail before because we got lucky with the fakedb driver.
+// It was failing, and now not, in github.com/bradfitz/go-sql-test
+func TestTxQuery(t *testing.T) {
+	db := newTestDB(t, "")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	exec(t, db, "INSERT|t1|name=Alice")
+
+	tx, err := db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer tx.Rollback()
+
+	r, err := tx.Query("SELECT|t1|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer r.Close()
+
+	if !r.Next() {
+		if r.Err() != nil {
+			t.Fatal(r.Err())
+		}
+		t.Fatal("expected one row")
+	}
+
+	var x string
+	err = r.Scan(&x)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestTxQueryInvalid(t *testing.T) {
+	db := newTestDB(t, "")
+	defer closeDB(t, db)
+
+	tx, err := db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer tx.Rollback()
+
+	_, err = tx.Query("SELECT|t1|name|")
+	if err == nil {
+		t.Fatal("Error expected")
+	}
+}
+
+// Tests fix for issue 4433, that retries in Begin happen when
+// conn.Begin() returns ErrBadConn
+func TestTxErrBadConn(t *testing.T) {
+	db, err := Open("test", fakeDBName+";badConn")
+	if err != nil {
+		t.Fatalf("Open: %v", err)
+	}
+	if _, err := db.Exec("WIPE"); err != nil {
+		t.Fatalf("exec wipe: %v", err)
+	}
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+	if err != nil {
+		t.Fatalf("Stmt, err = %v, %v", stmt, err)
+	}
+	defer stmt.Close()
+	tx, err := db.Begin()
+	if err != nil {
+		t.Fatalf("Begin = %v", err)
+	}
+	txs := tx.Stmt(stmt)
+	defer txs.Close()
+	_, err = txs.Exec("Bobby", 7)
+	if err != nil {
+		t.Fatalf("Exec = %v", err)
+	}
+	err = tx.Commit()
+	if err != nil {
+		t.Fatalf("Commit = %v", err)
+	}
+}
+
+// Tests fix for issue 2542, that we release a lock when querying on
+// a closed connection.
+func TestIssue2542Deadlock(t *testing.T) {
+	db := newTestDB(t, "people")
+	closeDB(t, db)
+	for i := 0; i < 2; i++ {
+		_, err := db.Query("SELECT|people|age,name|")
+		if err == nil {
+			t.Fatalf("expected error")
+		}
+	}
+}
+
+// From golang.org/issue/3865
+func TestCloseStmtBeforeRows(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	s, err := db.Prepare("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	r, err := s.Query()
+	if err != nil {
+		s.Close()
+		t.Fatal(err)
+	}
+
+	err = s.Close()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	r.Close()
+}
+
+// Tests fix for issue 2788, that we bind nil to a []byte if the
+// value in the column is sql null
+func TestNullByteSlice(t *testing.T) {
+	db := newTestDB(t, "")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t|id=int32,name=nullstring")
+	exec(t, db, "INSERT|t|id=10,name=?", nil)
+
+	var name []byte
+
+	err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if name != nil {
+		t.Fatalf("name []byte should be nil for null column value, got: %#v", name)
+	}
+
+	exec(t, db, "INSERT|t|id=11,name=?", "bob")
+	err = db.QueryRow("SELECT|t|name|id=?", 11).Scan(&name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(name) != "bob" {
+		t.Fatalf("name []byte should be bob, got: %q", string(name))
+	}
+}
+
+func TestPointerParamsAndScans(t *testing.T) {
+	db := newTestDB(t, "")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t|id=int32,name=nullstring")
+
+	bob := "bob"
+	var name *string
+
+	name = &bob
+	exec(t, db, "INSERT|t|id=10,name=?", name)
+	name = nil
+	exec(t, db, "INSERT|t|id=20,name=?", name)
+
+	err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name)
+	if err != nil {
+		t.Fatalf("querying id 10: %v", err)
+	}
+	if name == nil {
+		t.Errorf("id 10's name = nil; want bob")
+	} else if *name != "bob" {
+		t.Errorf("id 10's name = %q; want bob", *name)
+	}
+
+	err = db.QueryRow("SELECT|t|name|id=?", 20).Scan(&name)
+	if err != nil {
+		t.Fatalf("querying id 20: %v", err)
+	}
+	if name != nil {
+		t.Errorf("id 20 = %q; want nil", *name)
+	}
+}
+
+func TestQueryRowClosingStmt(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	var name string
+	var age int
+	err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age, &name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if db.freeConn.Len() != 1 {
+		t.Fatalf("expected 1 free conn")
+	}
+	fakeConn := (db.freeConn.Front().Value.(*driverConn)).ci.(*fakeConn)
+	if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed {
+		t.Errorf("statement close mismatch: made %d, closed %d", made, closed)
+	}
+}
+
+// Test issue 6651
+func TestIssue6651(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	var v string
+
+	want := "error in rows.Next"
+	rowsCursorNextHook = func(dest []driver.Value) error {
+		return fmt.Errorf(want)
+	}
+	defer func() { rowsCursorNextHook = nil }()
+	err := db.QueryRow("SELECT|people|name|").Scan(&v)
+	if err == nil || err.Error() != want {
+		t.Errorf("error = %q; want %q", err, want)
+	}
+	rowsCursorNextHook = nil
+
+	want = "error in rows.Close"
+	rowsCloseHook = func(rows *Rows, err *error) {
+		*err = fmt.Errorf(want)
+	}
+	defer func() { rowsCloseHook = nil }()
+	err = db.QueryRow("SELECT|people|name|").Scan(&v)
+	if err == nil || err.Error() != want {
+		t.Errorf("error = %q; want %q", err, want)
+	}
+}
+
+type nullTestRow struct {
+	nullParam    interface{}
+	notNullParam interface{}
+	scanNullVal  interface{}
+}
+
+type nullTestSpec struct {
+	nullType    string
+	notNullType string
+	rows        [6]nullTestRow
+}
+
+func TestNullStringParam(t *testing.T) {
+	spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{
+		{NullString{"aqua", true}, "", NullString{"aqua", true}},
+		{NullString{"brown", false}, "", NullString{"", false}},
+		{"chartreuse", "", NullString{"chartreuse", true}},
+		{NullString{"darkred", true}, "", NullString{"darkred", true}},
+		{NullString{"eel", false}, "", NullString{"", false}},
+		{"foo", NullString{"black", false}, nil},
+	}}
+	nullTestRun(t, spec)
+}
+
+func TestNullInt64Param(t *testing.T) {
+	spec := nullTestSpec{"nullint64", "int64", [6]nullTestRow{
+		{NullInt64{31, true}, 1, NullInt64{31, true}},
+		{NullInt64{-22, false}, 1, NullInt64{0, false}},
+		{22, 1, NullInt64{22, true}},
+		{NullInt64{33, true}, 1, NullInt64{33, true}},
+		{NullInt64{222, false}, 1, NullInt64{0, false}},
+		{0, NullInt64{31, false}, nil},
+	}}
+	nullTestRun(t, spec)
+}
+
+func TestNullFloat64Param(t *testing.T) {
+	spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{
+		{NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}},
+		{NullFloat64{13.1, false}, 1, NullFloat64{0, false}},
+		{-22.9, 1, NullFloat64{-22.9, true}},
+		{NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}},
+		{NullFloat64{222, false}, 1, NullFloat64{0, false}},
+		{10, NullFloat64{31.2, false}, nil},
+	}}
+	nullTestRun(t, spec)
+}
+
+func TestNullBoolParam(t *testing.T) {
+	spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{
+		{NullBool{false, true}, true, NullBool{false, true}},
+		{NullBool{true, false}, false, NullBool{false, false}},
+		{true, true, NullBool{true, true}},
+		{NullBool{true, true}, false, NullBool{true, true}},
+		{NullBool{true, false}, true, NullBool{false, false}},
+		{true, NullBool{true, false}, nil},
+	}}
+	nullTestRun(t, spec)
+}
+
+func nullTestRun(t *testing.T, spec nullTestSpec) {
+	db := newTestDB(t, "")
+	defer closeDB(t, db)
+	exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType))
+
+	// Inserts with db.Exec:
+	exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam)
+	exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam)
+
+	// Inserts with a prepared statement:
+	stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?")
+	if err != nil {
+		t.Fatalf("prepare: %v", err)
+	}
+	defer stmt.Close()
+	if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil {
+		t.Errorf("exec insert chris: %v", err)
+	}
+	if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil {
+		t.Errorf("exec insert dave: %v", err)
+	}
+	if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil {
+		t.Errorf("exec insert eleanor: %v", err)
+	}
+
+	// Can't put null val into non-null col
+	if _, err := stmt.Exec(6, "bob", spec.rows[5].nullParam, spec.rows[5].notNullParam); err == nil {
+		t.Errorf("expected error inserting nil val with prepared statement Exec")
+	}
+
+	_, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil)
+	if err == nil {
+		// TODO: this test fails, but it's just because
+		// fakeConn implements the optional Execer interface,
+		// so arguably this is the correct behavior.  But
+		// maybe I should flesh out the fakeConn.Exec
+		// implementation so this properly fails.
+		// t.Errorf("expected error inserting nil name with Exec")
+	}
+
+	paramtype := reflect.TypeOf(spec.rows[0].nullParam)
+	bindVal := reflect.New(paramtype).Interface()
+
+	for i := 0; i < 5; i++ {
+		id := i + 1
+		if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil {
+			t.Errorf("id=%d Scan: %v", id, err)
+		}
+		bindValDeref := reflect.ValueOf(bindVal).Elem().Interface()
+		if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) {
+			t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal)
+		}
+	}
+}
+
+// golang.org/issue/4859
+func TestQueryRowNilScanDest(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	var name *string // nil pointer
+	err := db.QueryRow("SELECT|people|name|").Scan(name)
+	want := "sql: Scan error on column index 0: destination pointer is nil"
+	if err == nil || err.Error() != want {
+		t.Errorf("error = %q; want %q", err.Error(), want)
+	}
+}
+
+func TestIssue4902(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	driver := db.driver.(*fakeDriver)
+	opens0 := driver.openCount
+
+	var stmt *Stmt
+	var err error
+	for i := 0; i < 10; i++ {
+		stmt, err = db.Prepare("SELECT|people|name|")
+		if err != nil {
+			t.Fatal(err)
+		}
+		err = stmt.Close()
+		if err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	opens := driver.openCount - opens0
+	if opens > 1 {
+		t.Errorf("opens = %d; want <= 1", opens)
+		t.Logf("db = %#v", db)
+		t.Logf("driver = %#v", driver)
+		t.Logf("stmt = %#v", stmt)
+	}
+}
+
+// Issue 3857
+// This used to deadlock.
+func TestSimultaneousQueries(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	tx, err := db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer tx.Rollback()
+
+	r1, err := tx.Query("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer r1.Close()
+
+	r2, err := tx.Query("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer r2.Close()
+}
+
+func TestMaxIdleConns(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	tx, err := db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+	tx.Commit()
+	if got := db.freeConn.Len(); got != 1 {
+		t.Errorf("freeConns = %d; want 1", got)
+	}
+
+	db.SetMaxIdleConns(0)
+
+	if got := db.freeConn.Len(); got != 0 {
+		t.Errorf("freeConns after set to zero = %d; want 0", got)
+	}
+
+	tx, err = db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+	tx.Commit()
+	if got := db.freeConn.Len(); got != 0 {
+		t.Errorf("freeConns = %d; want 0", got)
+	}
+}
+
+func TestMaxOpenConns(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	defer setHookpostCloseConn(nil)
+	setHookpostCloseConn(func(_ *fakeConn, err error) {
+		if err != nil {
+			t.Errorf("Error closing fakeConn: %v", err)
+		}
+	})
+
+	db := newTestDB(t, "magicquery")
+	defer closeDB(t, db)
+
+	driver := db.driver.(*fakeDriver)
+
+	// Force the number of open connections to 0 so we can get an accurate
+	// count for the test
+	db.SetMaxIdleConns(0)
+
+	if g, w := db.numFreeConns(), 0; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	if n := db.numDepsPollUntil(0, time.Second); n > 0 {
+		t.Errorf("number of dependencies = %d; expected 0", n)
+		db.dumpDeps(t)
+	}
+
+	driver.mu.Lock()
+	opens0 := driver.openCount
+	closes0 := driver.closeCount
+	driver.mu.Unlock()
+
+	db.SetMaxIdleConns(10)
+	db.SetMaxOpenConns(10)
+
+	stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Start 50 parallel slow queries.
+	const (
+		nquery      = 50
+		sleepMillis = 25
+		nbatch      = 2
+	)
+	var wg sync.WaitGroup
+	for batch := 0; batch < nbatch; batch++ {
+		for i := 0; i < nquery; i++ {
+			wg.Add(1)
+			go func() {
+				defer wg.Done()
+				var op string
+				if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows {
+					t.Error(err)
+				}
+			}()
+		}
+		// Sleep for twice the expected length of time for the
+		// batch of 50 queries above to finish before starting
+		// the next round.
+		time.Sleep(2 * sleepMillis * time.Millisecond)
+	}
+	wg.Wait()
+
+	if g, w := db.numFreeConns(), 10; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	if n := db.numDepsPollUntil(20, time.Second); n > 20 {
+		t.Errorf("number of dependencies = %d; expected <= 20", n)
+		db.dumpDeps(t)
+	}
+
+	driver.mu.Lock()
+	opens := driver.openCount - opens0
+	closes := driver.closeCount - closes0
+	driver.mu.Unlock()
+
+	if opens > 10 {
+		t.Logf("open calls = %d", opens)
+		t.Logf("close calls = %d", closes)
+		t.Errorf("db connections opened = %d; want <= 10", opens)
+		db.dumpDeps(t)
+	}
+
+	if err := stmt.Close(); err != nil {
+		t.Fatal(err)
+	}
+
+	if g, w := db.numFreeConns(), 10; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	if n := db.numDepsPollUntil(10, time.Second); n > 10 {
+		t.Errorf("number of dependencies = %d; expected <= 10", n)
+		db.dumpDeps(t)
+	}
+
+	db.SetMaxOpenConns(5)
+
+	if g, w := db.numFreeConns(), 5; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	if n := db.numDepsPollUntil(5, time.Second); n > 5 {
+		t.Errorf("number of dependencies = %d; expected 0", n)
+		db.dumpDeps(t)
+	}
+
+	db.SetMaxOpenConns(0)
+
+	if g, w := db.numFreeConns(), 5; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	if n := db.numDepsPollUntil(5, time.Second); n > 5 {
+		t.Errorf("number of dependencies = %d; expected 0", n)
+		db.dumpDeps(t)
+	}
+
+	db.SetMaxIdleConns(0)
+
+	if g, w := db.numFreeConns(), 0; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	if n := db.numDepsPollUntil(0, time.Second); n > 0 {
+		t.Errorf("number of dependencies = %d; expected 0", n)
+		db.dumpDeps(t)
+	}
+}
+
+func TestSingleOpenConn(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	db.SetMaxOpenConns(1)
+
+	rows, err := db.Query("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err = rows.Close(); err != nil {
+		t.Fatal(err)
+	}
+	// shouldn't deadlock
+	rows, err = db.Query("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err = rows.Close(); err != nil {
+		t.Fatal(err)
+	}
+}
+
+// golang.org/issue/5323
+func TestStmtCloseDeps(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	defer setHookpostCloseConn(nil)
+	setHookpostCloseConn(func(_ *fakeConn, err error) {
+		if err != nil {
+			t.Errorf("Error closing fakeConn: %v", err)
+		}
+	})
+
+	db := newTestDB(t, "magicquery")
+	defer closeDB(t, db)
+
+	driver := db.driver.(*fakeDriver)
+
+	driver.mu.Lock()
+	opens0 := driver.openCount
+	closes0 := driver.closeCount
+	driver.mu.Unlock()
+	openDelta0 := opens0 - closes0
+
+	stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Start 50 parallel slow queries.
+	const (
+		nquery      = 50
+		sleepMillis = 25
+		nbatch      = 2
+	)
+	var wg sync.WaitGroup
+	for batch := 0; batch < nbatch; batch++ {
+		for i := 0; i < nquery; i++ {
+			wg.Add(1)
+			go func() {
+				defer wg.Done()
+				var op string
+				if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows {
+					t.Error(err)
+				}
+			}()
+		}
+		// Sleep for twice the expected length of time for the
+		// batch of 50 queries above to finish before starting
+		// the next round.
+		time.Sleep(2 * sleepMillis * time.Millisecond)
+	}
+	wg.Wait()
+
+	if g, w := db.numFreeConns(), 2; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	if n := db.numDepsPollUntil(4, time.Second); n > 4 {
+		t.Errorf("number of dependencies = %d; expected <= 4", n)
+		db.dumpDeps(t)
+	}
+
+	driver.mu.Lock()
+	opens := driver.openCount - opens0
+	closes := driver.closeCount - closes0
+	openDelta := (driver.openCount - driver.closeCount) - openDelta0
+	driver.mu.Unlock()
+
+	if openDelta > 2 {
+		t.Logf("open calls = %d", opens)
+		t.Logf("close calls = %d", closes)
+		t.Logf("open delta = %d", openDelta)
+		t.Errorf("db connections opened = %d; want <= 2", openDelta)
+		db.dumpDeps(t)
+	}
+
+	if len(stmt.css) > nquery {
+		t.Errorf("len(stmt.css) = %d; want <= %d", len(stmt.css), nquery)
+	}
+
+	if err := stmt.Close(); err != nil {
+		t.Fatal(err)
+	}
+
+	if g, w := db.numFreeConns(), 2; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	if n := db.numDepsPollUntil(2, time.Second); n > 2 {
+		t.Errorf("number of dependencies = %d; expected <= 2", n)
+		db.dumpDeps(t)
+	}
+
+	db.SetMaxIdleConns(0)
+
+	if g, w := db.numFreeConns(), 0; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	if n := db.numDepsPollUntil(0, time.Second); n > 0 {
+		t.Errorf("number of dependencies = %d; expected 0", n)
+		db.dumpDeps(t)
+	}
+}
+
+// golang.org/issue/5046
+func TestCloseConnBeforeStmts(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	defer setHookpostCloseConn(nil)
+	setHookpostCloseConn(func(_ *fakeConn, err error) {
+		if err != nil {
+			t.Errorf("Error closing fakeConn: %v; from %s", err, stack())
+			db.dumpDeps(t)
+			t.Errorf("DB = %#v", db)
+		}
+	})
+
+	stmt, err := db.Prepare("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if db.freeConn.Len() != 1 {
+		t.Fatalf("expected 1 freeConn; got %d", db.freeConn.Len())
+	}
+	dc := db.freeConn.Front().Value.(*driverConn)
+	if dc.closed {
+		t.Errorf("conn shouldn't be closed")
+	}
+
+	if n := len(dc.openStmt); n != 1 {
+		t.Errorf("driverConn num openStmt = %d; want 1", n)
+	}
+	err = db.Close()
+	if err != nil {
+		t.Errorf("db Close = %v", err)
+	}
+	if !dc.closed {
+		t.Errorf("after db.Close, driverConn should be closed")
+	}
+	if n := len(dc.openStmt); n != 0 {
+		t.Errorf("driverConn num openStmt = %d; want 0", n)
+	}
+
+	err = stmt.Close()
+	if err != nil {
+		t.Errorf("Stmt close = %v", err)
+	}
+
+	if !dc.closed {
+		t.Errorf("conn should be closed")
+	}
+	if dc.ci != nil {
+		t.Errorf("after Stmt Close, driverConn's Conn interface should be nil")
+	}
+}
+
+// golang.org/issue/5283: don't release the Rows' connection in Close
+// before calling Stmt.Close.
+func TestRowsCloseOrder(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	db.SetMaxIdleConns(0)
+	setStrictFakeConnClose(t)
+	defer setStrictFakeConnClose(nil)
+
+	rows, err := db.Query("SELECT|people|age,name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+	err = rows.Close()
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestRowsImplicitClose(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	rows, err := db.Query("SELECT|people|age,name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	want, fail := 2, errors.New("fail")
+	r := rows.rowsi.(*rowsCursor)
+	r.errPos, r.err = want, fail
+
+	got := 0
+	for rows.Next() {
+		got++
+	}
+	if got != want {
+		t.Errorf("got %d rows, want %d", got, want)
+	}
+	if err := rows.Err(); err != fail {
+		t.Errorf("got error %v, want %v", err, fail)
+	}
+	if !r.closed {
+		t.Errorf("r.closed is false, want true")
+	}
+}
+
+func TestStmtCloseOrder(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	db.SetMaxIdleConns(0)
+	setStrictFakeConnClose(t)
+	defer setStrictFakeConnClose(nil)
+
+	_, err := db.Query("SELECT|non_existent|name|")
+	if err == nil {
+		t.Fatal("Quering non-existent table should fail")
+	}
+}
+
+// golang.org/issue/5781
+func TestErrBadConnReconnect(t *testing.T) {
+	db := newTestDB(t, "foo")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+
+	simulateBadConn := func(name string, hook *func() bool, op func() error) {
+		broken, retried := false, false
+		numOpen := db.numOpen
+
+		// simulate a broken connection on the first try
+		*hook = func() bool {
+			if !broken {
+				broken = true
+				return true
+			}
+			retried = true
+			return false
+		}
+
+		if err := op(); err != nil {
+			t.Errorf(name+": %v", err)
+			return
+		}
+
+		if !broken || !retried {
+			t.Error(name + ": Failed to simulate broken connection")
+		}
+		*hook = nil
+
+		if numOpen != db.numOpen {
+			t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen)
+			numOpen = db.numOpen
+		}
+	}
+
+	// db.Exec
+	dbExec := func() error {
+		_, err := db.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true)
+		return err
+	}
+	simulateBadConn("db.Exec prepare", &hookPrepareBadConn, dbExec)
+	simulateBadConn("db.Exec exec", &hookExecBadConn, dbExec)
+
+	// db.Query
+	dbQuery := func() error {
+		rows, err := db.Query("SELECT|t1|age,name|")
+		if err == nil {
+			err = rows.Close()
+		}
+		return err
+	}
+	simulateBadConn("db.Query prepare", &hookPrepareBadConn, dbQuery)
+	simulateBadConn("db.Query query", &hookQueryBadConn, dbQuery)
+
+	// db.Prepare
+	simulateBadConn("db.Prepare", &hookPrepareBadConn, func() error {
+		stmt, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?")
+		if err != nil {
+			return err
+		}
+		stmt.Close()
+		return nil
+	})
+
+	// stmt.Exec
+	stmt1, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?")
+	if err != nil {
+		t.Fatalf("prepare: %v", err)
+	}
+	defer stmt1.Close()
+	// make sure we must prepare the stmt first
+	for _, cs := range stmt1.css {
+		cs.dc.inUse = true
+	}
+
+	stmtExec := func() error {
+		_, err := stmt1.Exec("Gopher", 3, false)
+		return err
+	}
+	simulateBadConn("stmt.Exec prepare", &hookPrepareBadConn, stmtExec)
+	simulateBadConn("stmt.Exec exec", &hookExecBadConn, stmtExec)
+
+	// stmt.Query
+	stmt2, err := db.Prepare("SELECT|t1|age,name|")
+	if err != nil {
+		t.Fatalf("prepare: %v", err)
+	}
+	defer stmt2.Close()
+	// make sure we must prepare the stmt first
+	for _, cs := range stmt2.css {
+		cs.dc.inUse = true
+	}
+
+	stmtQuery := func() error {
+		rows, err := stmt2.Query()
+		if err == nil {
+			err = rows.Close()
+		}
+		return err
+	}
+	simulateBadConn("stmt.Query prepare", &hookPrepareBadConn, stmtQuery)
+	simulateBadConn("stmt.Query exec", &hookQueryBadConn, stmtQuery)
+}
+
+type concurrentTest interface {
+	init(t testing.TB, db *DB)
+	finish(t testing.TB)
+	test(t testing.TB) error
+}
+
+type concurrentDBQueryTest struct {
+	db *DB
+}
+
+func (c *concurrentDBQueryTest) init(t testing.TB, db *DB) {
+	c.db = db
+}
+
+func (c *concurrentDBQueryTest) finish(t testing.TB) {
+	c.db = nil
+}
+
+func (c *concurrentDBQueryTest) test(t testing.TB) error {
+	rows, err := c.db.Query("SELECT|people|name|")
+	if err != nil {
+		t.Error(err)
+		return err
+	}
+	var name string
+	for rows.Next() {
+		rows.Scan(&name)
+	}
+	rows.Close()
+	return nil
+}
+
+type concurrentDBExecTest struct {
+	db *DB
+}
+
+func (c *concurrentDBExecTest) init(t testing.TB, db *DB) {
+	c.db = db
+}
+
+func (c *concurrentDBExecTest) finish(t testing.TB) {
+	c.db = nil
+}
+
+func (c *concurrentDBExecTest) test(t testing.TB) error {
+	_, err := c.db.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
+	if err != nil {
+		t.Error(err)
+		return err
+	}
+	return nil
+}
+
+type concurrentStmtQueryTest struct {
+	db   *DB
+	stmt *Stmt
+}
+
+func (c *concurrentStmtQueryTest) init(t testing.TB, db *DB) {
+	c.db = db
+	var err error
+	c.stmt, err = db.Prepare("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func (c *concurrentStmtQueryTest) finish(t testing.TB) {
+	if c.stmt != nil {
+		c.stmt.Close()
+		c.stmt = nil
+	}
+	c.db = nil
+}
+
+func (c *concurrentStmtQueryTest) test(t testing.TB) error {
+	rows, err := c.stmt.Query()
+	if err != nil {
+		t.Errorf("error on query:  %v", err)
+		return err
+	}
+
+	var name string
+	for rows.Next() {
+		rows.Scan(&name)
+	}
+	rows.Close()
+	return nil
+}
+
+type concurrentStmtExecTest struct {
+	db   *DB
+	stmt *Stmt
+}
+
+func (c *concurrentStmtExecTest) init(t testing.TB, db *DB) {
+	c.db = db
+	var err error
+	c.stmt, err = db.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func (c *concurrentStmtExecTest) finish(t testing.TB) {
+	if c.stmt != nil {
+		c.stmt.Close()
+		c.stmt = nil
+	}
+	c.db = nil
+}
+
+func (c *concurrentStmtExecTest) test(t testing.TB) error {
+	_, err := c.stmt.Exec(3, chrisBirthday)
+	if err != nil {
+		t.Errorf("error on exec:  %v", err)
+		return err
+	}
+	return nil
+}
+
+type concurrentTxQueryTest struct {
+	db *DB
+	tx *Tx
+}
+
+func (c *concurrentTxQueryTest) init(t testing.TB, db *DB) {
+	c.db = db
+	var err error
+	c.tx, err = c.db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func (c *concurrentTxQueryTest) finish(t testing.TB) {
+	if c.tx != nil {
+		c.tx.Rollback()
+		c.tx = nil
+	}
+	c.db = nil
+}
+
+func (c *concurrentTxQueryTest) test(t testing.TB) error {
+	rows, err := c.db.Query("SELECT|people|name|")
+	if err != nil {
+		t.Error(err)
+		return err
+	}
+	var name string
+	for rows.Next() {
+		rows.Scan(&name)
+	}
+	rows.Close()
+	return nil
+}
+
+type concurrentTxExecTest struct {
+	db *DB
+	tx *Tx
+}
+
+func (c *concurrentTxExecTest) init(t testing.TB, db *DB) {
+	c.db = db
+	var err error
+	c.tx, err = c.db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func (c *concurrentTxExecTest) finish(t testing.TB) {
+	if c.tx != nil {
+		c.tx.Rollback()
+		c.tx = nil
+	}
+	c.db = nil
+}
+
+func (c *concurrentTxExecTest) test(t testing.TB) error {
+	_, err := c.tx.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
+	if err != nil {
+		t.Error(err)
+		return err
+	}
+	return nil
+}
+
+type concurrentTxStmtQueryTest struct {
+	db   *DB
+	tx   *Tx
+	stmt *Stmt
+}
+
+func (c *concurrentTxStmtQueryTest) init(t testing.TB, db *DB) {
+	c.db = db
+	var err error
+	c.tx, err = c.db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+	c.stmt, err = c.tx.Prepare("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func (c *concurrentTxStmtQueryTest) finish(t testing.TB) {
+	if c.stmt != nil {
+		c.stmt.Close()
+		c.stmt = nil
+	}
+	if c.tx != nil {
+		c.tx.Rollback()
+		c.tx = nil
+	}
+	c.db = nil
+}
+
+func (c *concurrentTxStmtQueryTest) test(t testing.TB) error {
+	rows, err := c.stmt.Query()
+	if err != nil {
+		t.Errorf("error on query:  %v", err)
+		return err
+	}
+
+	var name string
+	for rows.Next() {
+		rows.Scan(&name)
+	}
+	rows.Close()
+	return nil
+}
+
+type concurrentTxStmtExecTest struct {
+	db   *DB
+	tx   *Tx
+	stmt *Stmt
+}
+
+func (c *concurrentTxStmtExecTest) init(t testing.TB, db *DB) {
+	c.db = db
+	var err error
+	c.tx, err = c.db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+	c.stmt, err = c.tx.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func (c *concurrentTxStmtExecTest) finish(t testing.TB) {
+	if c.stmt != nil {
+		c.stmt.Close()
+		c.stmt = nil
+	}
+	if c.tx != nil {
+		c.tx.Rollback()
+		c.tx = nil
+	}
+	c.db = nil
+}
+
+func (c *concurrentTxStmtExecTest) test(t testing.TB) error {
+	_, err := c.stmt.Exec(3, chrisBirthday)
+	if err != nil {
+		t.Errorf("error on exec:  %v", err)
+		return err
+	}
+	return nil
+}
+
+type concurrentRandomTest struct {
+	tests []concurrentTest
+}
+
+func (c *concurrentRandomTest) init(t testing.TB, db *DB) {
+	c.tests = []concurrentTest{
+		new(concurrentDBQueryTest),
+		new(concurrentDBExecTest),
+		new(concurrentStmtQueryTest),
+		new(concurrentStmtExecTest),
+		new(concurrentTxQueryTest),
+		new(concurrentTxExecTest),
+		new(concurrentTxStmtQueryTest),
+		new(concurrentTxStmtExecTest),
+	}
+	for _, ct := range c.tests {
+		ct.init(t, db)
+	}
+}
+
+func (c *concurrentRandomTest) finish(t testing.TB) {
+	for _, ct := range c.tests {
+		ct.finish(t)
+	}
+}
+
+func (c *concurrentRandomTest) test(t testing.TB) error {
+	ct := c.tests[rand.Intn(len(c.tests))]
+	return ct.test(t)
+}
+
+func doConcurrentTest(t testing.TB, ct concurrentTest) {
+	maxProcs, numReqs := 1, 500
+	if testing.Short() {
+		maxProcs, numReqs = 4, 50
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
+
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	ct.init(t, db)
+	defer ct.finish(t)
+
+	var wg sync.WaitGroup
+	wg.Add(numReqs)
+
+	reqs := make(chan bool)
+	defer close(reqs)
+
+	for i := 0; i < maxProcs*2; i++ {
+		go func() {
+			for _ = range reqs {
+				err := ct.test(t)
+				if err != nil {
+					wg.Done()
+					continue
+				}
+				wg.Done()
+			}
+		}()
+	}
+
+	for i := 0; i < numReqs; i++ {
+		reqs <- true
+	}
+
+	wg.Wait()
+}
+
+func manyConcurrentQueries(t testing.TB) {
+	maxProcs, numReqs := 16, 500
+	if testing.Short() {
+		maxProcs, numReqs = 4, 50
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
+
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	stmt, err := db.Prepare("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer stmt.Close()
+
+	var wg sync.WaitGroup
+	wg.Add(numReqs)
+
+	reqs := make(chan bool)
+	defer close(reqs)
+
+	for i := 0; i < maxProcs*2; i++ {
+		go func() {
+			for _ = range reqs {
+				rows, err := stmt.Query()
+				if err != nil {
+					t.Errorf("error on query:  %v", err)
+					wg.Done()
+					continue
+				}
+
+				var name string
+				for rows.Next() {
+					rows.Scan(&name)
+				}
+				rows.Close()
+
+				wg.Done()
+			}
+		}()
+	}
+
+	for i := 0; i < numReqs; i++ {
+		reqs <- true
+	}
+
+	wg.Wait()
+}
+
+func TestIssue6081(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	drv := db.driver.(*fakeDriver)
+	drv.mu.Lock()
+	opens0 := drv.openCount
+	closes0 := drv.closeCount
+	drv.mu.Unlock()
+
+	stmt, err := db.Prepare("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+	rowsCloseHook = func(rows *Rows, err *error) {
+		*err = driver.ErrBadConn
+	}
+	defer func() { rowsCloseHook = nil }()
+	for i := 0; i < 10; i++ {
+		rows, err := stmt.Query()
+		if err != nil {
+			t.Fatal(err)
+		}
+		rows.Close()
+	}
+	if n := len(stmt.css); n > 1 {
+		t.Errorf("len(css slice) = %d; want <= 1", n)
+	}
+	stmt.Close()
+	if n := len(stmt.css); n != 0 {
+		t.Errorf("len(css slice) after Close = %d; want 0", n)
+	}
+
+	drv.mu.Lock()
+	opens := drv.openCount - opens0
+	closes := drv.closeCount - closes0
+	drv.mu.Unlock()
+	if opens < 9 {
+		t.Errorf("opens = %d; want >= 9", opens)
+	}
+	if closes < 9 {
+		t.Errorf("closes = %d; want >= 9", closes)
+	}
+}
+
+func TestConcurrency(t *testing.T) {
+	doConcurrentTest(t, new(concurrentDBQueryTest))
+	doConcurrentTest(t, new(concurrentDBExecTest))
+	doConcurrentTest(t, new(concurrentStmtQueryTest))
+	doConcurrentTest(t, new(concurrentStmtExecTest))
+	doConcurrentTest(t, new(concurrentTxQueryTest))
+	doConcurrentTest(t, new(concurrentTxExecTest))
+	doConcurrentTest(t, new(concurrentTxStmtQueryTest))
+	doConcurrentTest(t, new(concurrentTxStmtExecTest))
+	doConcurrentTest(t, new(concurrentRandomTest))
+}
+
+func TestConnectionLeak(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	// Start by opening defaultMaxIdleConns
+	rows := make([]*Rows, defaultMaxIdleConns)
+	// We need to SetMaxOpenConns > MaxIdleConns, so the DB can open
+	// a new connection and we can fill the idle queue with the released
+	// connections.
+	db.SetMaxOpenConns(len(rows) + 1)
+	for ii := range rows {
+		r, err := db.Query("SELECT|people|name|")
+		if err != nil {
+			t.Fatal(err)
+		}
+		r.Next()
+		if err := r.Err(); err != nil {
+			t.Fatal(err)
+		}
+		rows[ii] = r
+	}
+	// Now we have defaultMaxIdleConns busy connections. Open
+	// a new one, but wait until the busy connections are released
+	// before returning control to DB.
+	drv := db.driver.(*fakeDriver)
+	drv.waitCh = make(chan struct{}, 1)
+	drv.waitingCh = make(chan struct{}, 1)
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		r, err := db.Query("SELECT|people|name|")
+		if err != nil {
+			t.Fatal(err)
+		}
+		r.Close()
+		wg.Done()
+	}()
+	// Wait until the goroutine we've just created has started waiting.
+	<-drv.waitingCh
+	// Now close the busy connections. This provides a connection for
+	// the blocked goroutine and then fills up the idle queue.
+	for _, v := range rows {
+		v.Close()
+	}
+	// At this point we give the new connection to DB. This connection is
+	// now useless, since the idle queue is full and there are no pending
+	// requests. DB should deal with this situation without leaking the
+	// connection.
+	drv.waitCh <- struct{}{}
+	wg.Wait()
+}
+
+func BenchmarkConcurrentDBExec(b *testing.B) {
+	b.ReportAllocs()
+	ct := new(concurrentDBExecTest)
+	for i := 0; i < b.N; i++ {
+		doConcurrentTest(b, ct)
+	}
+}
+
+func BenchmarkConcurrentStmtQuery(b *testing.B) {
+	b.ReportAllocs()
+	ct := new(concurrentStmtQueryTest)
+	for i := 0; i < b.N; i++ {
+		doConcurrentTest(b, ct)
+	}
+}
+
+func BenchmarkConcurrentStmtExec(b *testing.B) {
+	b.ReportAllocs()
+	ct := new(concurrentStmtExecTest)
+	for i := 0; i < b.N; i++ {
+		doConcurrentTest(b, ct)
+	}
+}
+
+func BenchmarkConcurrentTxQuery(b *testing.B) {
+	b.ReportAllocs()
+	ct := new(concurrentTxQueryTest)
+	for i := 0; i < b.N; i++ {
+		doConcurrentTest(b, ct)
+	}
+}
+
+func BenchmarkConcurrentTxExec(b *testing.B) {
+	b.ReportAllocs()
+	ct := new(concurrentTxExecTest)
+	for i := 0; i < b.N; i++ {
+		doConcurrentTest(b, ct)
+	}
+}
+
+func BenchmarkConcurrentTxStmtQuery(b *testing.B) {
+	b.ReportAllocs()
+	ct := new(concurrentTxStmtQueryTest)
+	for i := 0; i < b.N; i++ {
+		doConcurrentTest(b, ct)
+	}
+}
+
+func BenchmarkConcurrentTxStmtExec(b *testing.B) {
+	b.ReportAllocs()
+	ct := new(concurrentTxStmtExecTest)
+	for i := 0; i < b.N; i++ {
+		doConcurrentTest(b, ct)
+	}
+}
+
+func BenchmarkConcurrentRandom(b *testing.B) {
+	b.ReportAllocs()
+	ct := new(concurrentRandomTest)
+	for i := 0; i < b.N; i++ {
+		doConcurrentTest(b, ct)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/buf.go b/third_party/gofrontend/libgo/go/debug/dwarf/buf.go
new file mode 100644
index 0000000..53c46eb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/buf.go
@@ -0,0 +1,181 @@
+// 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.
+
+// Buffered reading and decoding of DWARF data streams.
+
+package dwarf
+
+import (
+	"encoding/binary"
+	"strconv"
+)
+
+// Data buffer being decoded.
+type buf struct {
+	dwarf  *Data
+	order  binary.ByteOrder
+	format dataFormat
+	name   string
+	off    Offset
+	data   []byte
+	err    error
+}
+
+// Data format, other than byte order.  This affects the handling of
+// certain field formats.
+type dataFormat interface {
+	// DWARF version number.  Zero means unknown.
+	version() int
+
+	// 64-bit DWARF format?
+	dwarf64() (dwarf64 bool, isKnown bool)
+
+	// Size of an address, in bytes.  Zero means unknown.
+	addrsize() int
+}
+
+// Some parts of DWARF have no data format, e.g., abbrevs.
+type unknownFormat struct{}
+
+func (u unknownFormat) version() int {
+	return 0
+}
+
+func (u unknownFormat) dwarf64() (bool, bool) {
+	return false, false
+}
+
+func (u unknownFormat) addrsize() int {
+	return 0
+}
+
+func makeBuf(d *Data, format dataFormat, name string, off Offset, data []byte) buf {
+	return buf{d, d.order, format, name, off, data, nil}
+}
+
+func (b *buf) uint8() uint8 {
+	if len(b.data) < 1 {
+		b.error("underflow")
+		return 0
+	}
+	val := b.data[0]
+	b.data = b.data[1:]
+	b.off++
+	return val
+}
+
+func (b *buf) bytes(n int) []byte {
+	if len(b.data) < n {
+		b.error("underflow")
+		return nil
+	}
+	data := b.data[0:n]
+	b.data = b.data[n:]
+	b.off += Offset(n)
+	return data
+}
+
+func (b *buf) skip(n int) { b.bytes(n) }
+
+func (b *buf) string() string {
+	for i := 0; i < len(b.data); i++ {
+		if b.data[i] == 0 {
+			s := string(b.data[0:i])
+			b.data = b.data[i+1:]
+			b.off += Offset(i + 1)
+			return s
+		}
+	}
+	b.error("underflow")
+	return ""
+}
+
+func (b *buf) uint16() uint16 {
+	a := b.bytes(2)
+	if a == nil {
+		return 0
+	}
+	return b.order.Uint16(a)
+}
+
+func (b *buf) uint32() uint32 {
+	a := b.bytes(4)
+	if a == nil {
+		return 0
+	}
+	return b.order.Uint32(a)
+}
+
+func (b *buf) uint64() uint64 {
+	a := b.bytes(8)
+	if a == nil {
+		return 0
+	}
+	return b.order.Uint64(a)
+}
+
+// Read a varint, which is 7 bits per byte, little endian.
+// the 0x80 bit means read another byte.
+func (b *buf) varint() (c uint64, bits uint) {
+	for i := 0; i < len(b.data); i++ {
+		byte := b.data[i]
+		c |= uint64(byte&0x7F) << bits
+		bits += 7
+		if byte&0x80 == 0 {
+			b.off += Offset(i + 1)
+			b.data = b.data[i+1:]
+			return c, bits
+		}
+	}
+	return 0, 0
+}
+
+// Unsigned int is just a varint.
+func (b *buf) uint() uint64 {
+	x, _ := b.varint()
+	return x
+}
+
+// Signed int is a sign-extended varint.
+func (b *buf) int() int64 {
+	ux, bits := b.varint()
+	x := int64(ux)
+	if x&(1<<(bits-1)) != 0 {
+		x |= -1 << bits
+	}
+	return x
+}
+
+// Address-sized uint.
+func (b *buf) addr() uint64 {
+	switch b.format.addrsize() {
+	case 1:
+		return uint64(b.uint8())
+	case 2:
+		return uint64(b.uint16())
+	case 4:
+		return uint64(b.uint32())
+	case 8:
+		return uint64(b.uint64())
+	}
+	b.error("unknown address size")
+	return 0
+}
+
+func (b *buf) error(s string) {
+	if b.err == nil {
+		b.data = nil
+		b.err = DecodeError{b.name, b.off, s}
+	}
+}
+
+type DecodeError struct {
+	Name   string
+	Offset Offset
+	Err    string
+}
+
+func (e DecodeError) Error() string {
+	return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err
+}
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/const.go b/third_party/gofrontend/libgo/go/debug/dwarf/const.go
new file mode 100644
index 0000000..6cc6bc9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/const.go
@@ -0,0 +1,481 @@
+// 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.
+
+// Constants
+
+package dwarf
+
+import "strconv"
+
+// An Attr identifies the attribute type in a DWARF Entry's Field.
+type Attr uint32
+
+const (
+	AttrSibling        Attr = 0x01
+	AttrLocation       Attr = 0x02
+	AttrName           Attr = 0x03
+	AttrOrdering       Attr = 0x09
+	AttrByteSize       Attr = 0x0B
+	AttrBitOffset      Attr = 0x0C
+	AttrBitSize        Attr = 0x0D
+	AttrStmtList       Attr = 0x10
+	AttrLowpc          Attr = 0x11
+	AttrHighpc         Attr = 0x12
+	AttrLanguage       Attr = 0x13
+	AttrDiscr          Attr = 0x15
+	AttrDiscrValue     Attr = 0x16
+	AttrVisibility     Attr = 0x17
+	AttrImport         Attr = 0x18
+	AttrStringLength   Attr = 0x19
+	AttrCommonRef      Attr = 0x1A
+	AttrCompDir        Attr = 0x1B
+	AttrConstValue     Attr = 0x1C
+	AttrContainingType Attr = 0x1D
+	AttrDefaultValue   Attr = 0x1E
+	AttrInline         Attr = 0x20
+	AttrIsOptional     Attr = 0x21
+	AttrLowerBound     Attr = 0x22
+	AttrProducer       Attr = 0x25
+	AttrPrototyped     Attr = 0x27
+	AttrReturnAddr     Attr = 0x2A
+	AttrStartScope     Attr = 0x2C
+	AttrStrideSize     Attr = 0x2E
+	AttrUpperBound     Attr = 0x2F
+	AttrAbstractOrigin Attr = 0x31
+	AttrAccessibility  Attr = 0x32
+	AttrAddrClass      Attr = 0x33
+	AttrArtificial     Attr = 0x34
+	AttrBaseTypes      Attr = 0x35
+	AttrCalling        Attr = 0x36
+	AttrCount          Attr = 0x37
+	AttrDataMemberLoc  Attr = 0x38
+	AttrDeclColumn     Attr = 0x39
+	AttrDeclFile       Attr = 0x3A
+	AttrDeclLine       Attr = 0x3B
+	AttrDeclaration    Attr = 0x3C
+	AttrDiscrList      Attr = 0x3D
+	AttrEncoding       Attr = 0x3E
+	AttrExternal       Attr = 0x3F
+	AttrFrameBase      Attr = 0x40
+	AttrFriend         Attr = 0x41
+	AttrIdentifierCase Attr = 0x42
+	AttrMacroInfo      Attr = 0x43
+	AttrNamelistItem   Attr = 0x44
+	AttrPriority       Attr = 0x45
+	AttrSegment        Attr = 0x46
+	AttrSpecification  Attr = 0x47
+	AttrStaticLink     Attr = 0x48
+	AttrType           Attr = 0x49
+	AttrUseLocation    Attr = 0x4A
+	AttrVarParam       Attr = 0x4B
+	AttrVirtuality     Attr = 0x4C
+	AttrVtableElemLoc  Attr = 0x4D
+	AttrAllocated      Attr = 0x4E
+	AttrAssociated     Attr = 0x4F
+	AttrDataLocation   Attr = 0x50
+	AttrStride         Attr = 0x51
+	AttrEntrypc        Attr = 0x52
+	AttrUseUTF8        Attr = 0x53
+	AttrExtension      Attr = 0x54
+	AttrRanges         Attr = 0x55
+	AttrTrampoline     Attr = 0x56
+	AttrCallColumn     Attr = 0x57
+	AttrCallFile       Attr = 0x58
+	AttrCallLine       Attr = 0x59
+	AttrDescription    Attr = 0x5A
+)
+
+var attrNames = [...]string{
+	AttrSibling:        "Sibling",
+	AttrLocation:       "Location",
+	AttrName:           "Name",
+	AttrOrdering:       "Ordering",
+	AttrByteSize:       "ByteSize",
+	AttrBitOffset:      "BitOffset",
+	AttrBitSize:        "BitSize",
+	AttrStmtList:       "StmtList",
+	AttrLowpc:          "Lowpc",
+	AttrHighpc:         "Highpc",
+	AttrLanguage:       "Language",
+	AttrDiscr:          "Discr",
+	AttrDiscrValue:     "DiscrValue",
+	AttrVisibility:     "Visibility",
+	AttrImport:         "Import",
+	AttrStringLength:   "StringLength",
+	AttrCommonRef:      "CommonRef",
+	AttrCompDir:        "CompDir",
+	AttrConstValue:     "ConstValue",
+	AttrContainingType: "ContainingType",
+	AttrDefaultValue:   "DefaultValue",
+	AttrInline:         "Inline",
+	AttrIsOptional:     "IsOptional",
+	AttrLowerBound:     "LowerBound",
+	AttrProducer:       "Producer",
+	AttrPrototyped:     "Prototyped",
+	AttrReturnAddr:     "ReturnAddr",
+	AttrStartScope:     "StartScope",
+	AttrStrideSize:     "StrideSize",
+	AttrUpperBound:     "UpperBound",
+	AttrAbstractOrigin: "AbstractOrigin",
+	AttrAccessibility:  "Accessibility",
+	AttrAddrClass:      "AddrClass",
+	AttrArtificial:     "Artificial",
+	AttrBaseTypes:      "BaseTypes",
+	AttrCalling:        "Calling",
+	AttrCount:          "Count",
+	AttrDataMemberLoc:  "DataMemberLoc",
+	AttrDeclColumn:     "DeclColumn",
+	AttrDeclFile:       "DeclFile",
+	AttrDeclLine:       "DeclLine",
+	AttrDeclaration:    "Declaration",
+	AttrDiscrList:      "DiscrList",
+	AttrEncoding:       "Encoding",
+	AttrExternal:       "External",
+	AttrFrameBase:      "FrameBase",
+	AttrFriend:         "Friend",
+	AttrIdentifierCase: "IdentifierCase",
+	AttrMacroInfo:      "MacroInfo",
+	AttrNamelistItem:   "NamelistItem",
+	AttrPriority:       "Priority",
+	AttrSegment:        "Segment",
+	AttrSpecification:  "Specification",
+	AttrStaticLink:     "StaticLink",
+	AttrType:           "Type",
+	AttrUseLocation:    "UseLocation",
+	AttrVarParam:       "VarParam",
+	AttrVirtuality:     "Virtuality",
+	AttrVtableElemLoc:  "VtableElemLoc",
+	AttrAllocated:      "Allocated",
+	AttrAssociated:     "Associated",
+	AttrDataLocation:   "DataLocation",
+	AttrStride:         "Stride",
+	AttrEntrypc:        "Entrypc",
+	AttrUseUTF8:        "UseUTF8",
+	AttrExtension:      "Extension",
+	AttrRanges:         "Ranges",
+	AttrTrampoline:     "Trampoline",
+	AttrCallColumn:     "CallColumn",
+	AttrCallFile:       "CallFile",
+	AttrCallLine:       "CallLine",
+	AttrDescription:    "Description",
+}
+
+func (a Attr) String() string {
+	if int(a) < len(attrNames) {
+		s := attrNames[a]
+		if s != "" {
+			return s
+		}
+	}
+	return strconv.Itoa(int(a))
+}
+
+func (a Attr) GoString() string {
+	if int(a) < len(attrNames) {
+		s := attrNames[a]
+		if s != "" {
+			return "dwarf.Attr" + s
+		}
+	}
+	return "dwarf.Attr(" + strconv.FormatInt(int64(a), 10) + ")"
+}
+
+// A format is a DWARF data encoding format.
+type format uint32
+
+const (
+	// value formats
+	formAddr        format = 0x01
+	formDwarfBlock2 format = 0x03
+	formDwarfBlock4 format = 0x04
+	formData2       format = 0x05
+	formData4       format = 0x06
+	formData8       format = 0x07
+	formString      format = 0x08
+	formDwarfBlock  format = 0x09
+	formDwarfBlock1 format = 0x0A
+	formData1       format = 0x0B
+	formFlag        format = 0x0C
+	formSdata       format = 0x0D
+	formStrp        format = 0x0E
+	formUdata       format = 0x0F
+	formRefAddr     format = 0x10
+	formRef1        format = 0x11
+	formRef2        format = 0x12
+	formRef4        format = 0x13
+	formRef8        format = 0x14
+	formRefUdata    format = 0x15
+	formIndirect    format = 0x16
+	// The following are new in DWARF 4.
+	formSecOffset   format = 0x17
+	formExprloc     format = 0x18
+	formFlagPresent format = 0x19
+	formRefSig8     format = 0x20
+	// Extensions for multi-file compression (.dwz)
+	// http://www.dwarfstd.org/ShowIssue.php?issue=120604.1
+	formGnuRefAlt  format = 0x1f20
+	formGnuStrpAlt format = 0x1f21
+)
+
+// A Tag is the classification (the type) of an Entry.
+type Tag uint32
+
+const (
+	TagArrayType              Tag = 0x01
+	TagClassType              Tag = 0x02
+	TagEntryPoint             Tag = 0x03
+	TagEnumerationType        Tag = 0x04
+	TagFormalParameter        Tag = 0x05
+	TagImportedDeclaration    Tag = 0x08
+	TagLabel                  Tag = 0x0A
+	TagLexDwarfBlock          Tag = 0x0B
+	TagMember                 Tag = 0x0D
+	TagPointerType            Tag = 0x0F
+	TagReferenceType          Tag = 0x10
+	TagCompileUnit            Tag = 0x11
+	TagStringType             Tag = 0x12
+	TagStructType             Tag = 0x13
+	TagSubroutineType         Tag = 0x15
+	TagTypedef                Tag = 0x16
+	TagUnionType              Tag = 0x17
+	TagUnspecifiedParameters  Tag = 0x18
+	TagVariant                Tag = 0x19
+	TagCommonDwarfBlock       Tag = 0x1A
+	TagCommonInclusion        Tag = 0x1B
+	TagInheritance            Tag = 0x1C
+	TagInlinedSubroutine      Tag = 0x1D
+	TagModule                 Tag = 0x1E
+	TagPtrToMemberType        Tag = 0x1F
+	TagSetType                Tag = 0x20
+	TagSubrangeType           Tag = 0x21
+	TagWithStmt               Tag = 0x22
+	TagAccessDeclaration      Tag = 0x23
+	TagBaseType               Tag = 0x24
+	TagCatchDwarfBlock        Tag = 0x25
+	TagConstType              Tag = 0x26
+	TagConstant               Tag = 0x27
+	TagEnumerator             Tag = 0x28
+	TagFileType               Tag = 0x29
+	TagFriend                 Tag = 0x2A
+	TagNamelist               Tag = 0x2B
+	TagNamelistItem           Tag = 0x2C
+	TagPackedType             Tag = 0x2D
+	TagSubprogram             Tag = 0x2E
+	TagTemplateTypeParameter  Tag = 0x2F
+	TagTemplateValueParameter Tag = 0x30
+	TagThrownType             Tag = 0x31
+	TagTryDwarfBlock          Tag = 0x32
+	TagVariantPart            Tag = 0x33
+	TagVariable               Tag = 0x34
+	TagVolatileType           Tag = 0x35
+	// The following are new in DWARF 3.
+	TagDwarfProcedure  Tag = 0x36
+	TagRestrictType    Tag = 0x37
+	TagInterfaceType   Tag = 0x38
+	TagNamespace       Tag = 0x39
+	TagImportedModule  Tag = 0x3A
+	TagUnspecifiedType Tag = 0x3B
+	TagPartialUnit     Tag = 0x3C
+	TagImportedUnit    Tag = 0x3D
+	TagMutableType     Tag = 0x3E // Later removed from DWARF.
+	TagCondition       Tag = 0x3F
+	TagSharedType      Tag = 0x40
+	// The following are new in DWARF 4.
+	TagTypeUnit            Tag = 0x41
+	TagRvalueReferenceType Tag = 0x42
+	TagTemplateAlias       Tag = 0x43
+)
+
+var tagNames = [...]string{
+	TagArrayType:              "ArrayType",
+	TagClassType:              "ClassType",
+	TagEntryPoint:             "EntryPoint",
+	TagEnumerationType:        "EnumerationType",
+	TagFormalParameter:        "FormalParameter",
+	TagImportedDeclaration:    "ImportedDeclaration",
+	TagLabel:                  "Label",
+	TagLexDwarfBlock:          "LexDwarfBlock",
+	TagMember:                 "Member",
+	TagPointerType:            "PointerType",
+	TagReferenceType:          "ReferenceType",
+	TagCompileUnit:            "CompileUnit",
+	TagStringType:             "StringType",
+	TagStructType:             "StructType",
+	TagSubroutineType:         "SubroutineType",
+	TagTypedef:                "Typedef",
+	TagUnionType:              "UnionType",
+	TagUnspecifiedParameters:  "UnspecifiedParameters",
+	TagVariant:                "Variant",
+	TagCommonDwarfBlock:       "CommonDwarfBlock",
+	TagCommonInclusion:        "CommonInclusion",
+	TagInheritance:            "Inheritance",
+	TagInlinedSubroutine:      "InlinedSubroutine",
+	TagModule:                 "Module",
+	TagPtrToMemberType:        "PtrToMemberType",
+	TagSetType:                "SetType",
+	TagSubrangeType:           "SubrangeType",
+	TagWithStmt:               "WithStmt",
+	TagAccessDeclaration:      "AccessDeclaration",
+	TagBaseType:               "BaseType",
+	TagCatchDwarfBlock:        "CatchDwarfBlock",
+	TagConstType:              "ConstType",
+	TagConstant:               "Constant",
+	TagEnumerator:             "Enumerator",
+	TagFileType:               "FileType",
+	TagFriend:                 "Friend",
+	TagNamelist:               "Namelist",
+	TagNamelistItem:           "NamelistItem",
+	TagPackedType:             "PackedType",
+	TagSubprogram:             "Subprogram",
+	TagTemplateTypeParameter:  "TemplateTypeParameter",
+	TagTemplateValueParameter: "TemplateValueParameter",
+	TagThrownType:             "ThrownType",
+	TagTryDwarfBlock:          "TryDwarfBlock",
+	TagVariantPart:            "VariantPart",
+	TagVariable:               "Variable",
+	TagVolatileType:           "VolatileType",
+	TagDwarfProcedure:         "DwarfProcedure",
+	TagRestrictType:           "RestrictType",
+	TagInterfaceType:          "InterfaceType",
+	TagNamespace:              "Namespace",
+	TagImportedModule:         "ImportedModule",
+	TagUnspecifiedType:        "UnspecifiedType",
+	TagPartialUnit:            "PartialUnit",
+	TagImportedUnit:           "ImportedUnit",
+	TagMutableType:            "MutableType",
+	TagCondition:              "Condition",
+	TagSharedType:             "SharedType",
+	TagTypeUnit:               "TypeUnit",
+	TagRvalueReferenceType:    "RvalueReferenceType",
+	TagTemplateAlias:          "TemplateAlias",
+}
+
+func (t Tag) String() string {
+	if int(t) < len(tagNames) {
+		s := tagNames[t]
+		if s != "" {
+			return s
+		}
+	}
+	return strconv.Itoa(int(t))
+}
+
+func (t Tag) GoString() string {
+	if int(t) < len(tagNames) {
+		s := tagNames[t]
+		if s != "" {
+			return "dwarf.Tag" + s
+		}
+	}
+	return "dwarf.Tag(" + strconv.FormatInt(int64(t), 10) + ")"
+}
+
+// Location expression operators.
+// The debug info encodes value locations like 8(R3)
+// as a sequence of these op codes.
+// This package does not implement full expressions;
+// the opPlusUconst operator is expected by the type parser.
+const (
+	opAddr       = 0x03 /* 1 op, const addr */
+	opDeref      = 0x06
+	opConst1u    = 0x08 /* 1 op, 1 byte const */
+	opConst1s    = 0x09 /*	" signed */
+	opConst2u    = 0x0A /* 1 op, 2 byte const  */
+	opConst2s    = 0x0B /*	" signed */
+	opConst4u    = 0x0C /* 1 op, 4 byte const */
+	opConst4s    = 0x0D /*	" signed */
+	opConst8u    = 0x0E /* 1 op, 8 byte const */
+	opConst8s    = 0x0F /*	" signed */
+	opConstu     = 0x10 /* 1 op, LEB128 const */
+	opConsts     = 0x11 /*	" signed */
+	opDup        = 0x12
+	opDrop       = 0x13
+	opOver       = 0x14
+	opPick       = 0x15 /* 1 op, 1 byte stack index */
+	opSwap       = 0x16
+	opRot        = 0x17
+	opXderef     = 0x18
+	opAbs        = 0x19
+	opAnd        = 0x1A
+	opDiv        = 0x1B
+	opMinus      = 0x1C
+	opMod        = 0x1D
+	opMul        = 0x1E
+	opNeg        = 0x1F
+	opNot        = 0x20
+	opOr         = 0x21
+	opPlus       = 0x22
+	opPlusUconst = 0x23 /* 1 op, ULEB128 addend */
+	opShl        = 0x24
+	opShr        = 0x25
+	opShra       = 0x26
+	opXor        = 0x27
+	opSkip       = 0x2F /* 1 op, signed 2-byte constant */
+	opBra        = 0x28 /* 1 op, signed 2-byte constant */
+	opEq         = 0x29
+	opGe         = 0x2A
+	opGt         = 0x2B
+	opLe         = 0x2C
+	opLt         = 0x2D
+	opNe         = 0x2E
+	opLit0       = 0x30
+	/* OpLitN = OpLit0 + N for N = 0..31 */
+	opReg0 = 0x50
+	/* OpRegN = OpReg0 + N for N = 0..31 */
+	opBreg0 = 0x70 /* 1 op, signed LEB128 constant */
+	/* OpBregN = OpBreg0 + N for N = 0..31 */
+	opRegx       = 0x90 /* 1 op, ULEB128 register */
+	opFbreg      = 0x91 /* 1 op, SLEB128 offset */
+	opBregx      = 0x92 /* 2 op, ULEB128 reg; SLEB128 off */
+	opPiece      = 0x93 /* 1 op, ULEB128 size of piece */
+	opDerefSize  = 0x94 /* 1-byte size of data retrieved */
+	opXderefSize = 0x95 /* 1-byte size of data retrieved */
+	opNop        = 0x96
+	/* next four new in Dwarf v3 */
+	opPushObjAddr = 0x97
+	opCall2       = 0x98 /* 2-byte offset of DIE */
+	opCall4       = 0x99 /* 4-byte offset of DIE */
+	opCallRef     = 0x9A /* 4- or 8- byte offset of DIE */
+	/* 0xE0-0xFF reserved for user-specific */
+)
+
+// Basic type encodings -- the value for AttrEncoding in a TagBaseType Entry.
+const (
+	encAddress        = 0x01
+	encBoolean        = 0x02
+	encComplexFloat   = 0x03
+	encFloat          = 0x04
+	encSigned         = 0x05
+	encSignedChar     = 0x06
+	encUnsigned       = 0x07
+	encUnsignedChar   = 0x08
+	encImaginaryFloat = 0x09
+)
+
+// Line number opcodes.
+const (
+	LineExtendedOp     = 0
+	LineCopy           = 1
+	LineAdvancePC      = 2
+	LineAdvanceLine    = 3
+	LineSetFile        = 4
+	LineSetColumn      = 5
+	LineNegateStmt     = 6
+	LineSetBasicBlock  = 7
+	LineConstAddPC     = 8
+	LineFixedAdvancePC = 9
+	// next 3 are DWARF 3
+	LineSetPrologueEnd   = 10
+	LineSetEpilogueBegin = 11
+	LineSetISA           = 12
+)
+
+// Line number extended opcodes.
+const (
+	LineExtEndSequence = 1
+	LineExtSetAddress  = 2
+	LineExtDefineFile  = 3
+	// next 1 is DWARF 4
+	LineExtSetDiscriminator = 4
+)
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/entry.go b/third_party/gofrontend/libgo/go/debug/dwarf/entry.go
new file mode 100644
index 0000000..b6ba8c0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/entry.go
@@ -0,0 +1,410 @@
+// 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.
+
+// DWARF debug information entry parser.
+// An entry is a sequence of data items of a given format.
+// The first word in the entry is an index into what DWARF
+// calls the ``abbreviation table.''  An abbreviation is really
+// just a type descriptor: it's an array of attribute tag/value format pairs.
+
+package dwarf
+
+import (
+	"errors"
+	"strconv"
+)
+
+// a single entry's description: a sequence of attributes
+type abbrev struct {
+	tag      Tag
+	children bool
+	field    []afield
+}
+
+type afield struct {
+	attr Attr
+	fmt  format
+}
+
+// a map from entry format ids to their descriptions
+type abbrevTable map[uint32]abbrev
+
+// ParseAbbrev returns the abbreviation table that starts at byte off
+// in the .debug_abbrev section.
+func (d *Data) parseAbbrev(off uint32) (abbrevTable, error) {
+	if m, ok := d.abbrevCache[off]; ok {
+		return m, nil
+	}
+
+	data := d.abbrev
+	if off > uint32(len(data)) {
+		data = nil
+	} else {
+		data = data[off:]
+	}
+	b := makeBuf(d, unknownFormat{}, "abbrev", 0, data)
+
+	// Error handling is simplified by the buf getters
+	// returning an endless stream of 0s after an error.
+	m := make(abbrevTable)
+	for {
+		// Table ends with id == 0.
+		id := uint32(b.uint())
+		if id == 0 {
+			break
+		}
+
+		// Walk over attributes, counting.
+		n := 0
+		b1 := b // Read from copy of b.
+		b1.uint()
+		b1.uint8()
+		for {
+			tag := b1.uint()
+			fmt := b1.uint()
+			if tag == 0 && fmt == 0 {
+				break
+			}
+			n++
+		}
+		if b1.err != nil {
+			return nil, b1.err
+		}
+
+		// Walk over attributes again, this time writing them down.
+		var a abbrev
+		a.tag = Tag(b.uint())
+		a.children = b.uint8() != 0
+		a.field = make([]afield, n)
+		for i := range a.field {
+			a.field[i].attr = Attr(b.uint())
+			a.field[i].fmt = format(b.uint())
+		}
+		b.uint()
+		b.uint()
+
+		m[id] = a
+	}
+	if b.err != nil {
+		return nil, b.err
+	}
+	d.abbrevCache[off] = m
+	return m, nil
+}
+
+// An entry is a sequence of attribute/value pairs.
+type Entry struct {
+	Offset   Offset // offset of Entry in DWARF info
+	Tag      Tag    // tag (kind of Entry)
+	Children bool   // whether Entry is followed by children
+	Field    []Field
+}
+
+// A Field is a single attribute/value pair in an Entry.
+type Field struct {
+	Attr Attr
+	Val  interface{}
+}
+
+// Val returns the value associated with attribute Attr in Entry,
+// or nil if there is no such attribute.
+//
+// A common idiom is to merge the check for nil return with
+// the check that the value has the expected dynamic type, as in:
+//	v, ok := e.Val(AttrSibling).(int64);
+//
+func (e *Entry) Val(a Attr) interface{} {
+	for _, f := range e.Field {
+		if f.Attr == a {
+			return f.Val
+		}
+	}
+	return nil
+}
+
+// An Offset represents the location of an Entry within the DWARF info.
+// (See Reader.Seek.)
+type Offset uint32
+
+// Entry reads a single entry from buf, decoding
+// according to the given abbreviation table.
+func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
+	off := b.off
+	id := uint32(b.uint())
+	if id == 0 {
+		return &Entry{}
+	}
+	a, ok := atab[id]
+	if !ok {
+		b.error("unknown abbreviation table index")
+		return nil
+	}
+	e := &Entry{
+		Offset:   off,
+		Tag:      a.tag,
+		Children: a.children,
+		Field:    make([]Field, len(a.field)),
+	}
+	for i := range e.Field {
+		e.Field[i].Attr = a.field[i].attr
+		fmt := a.field[i].fmt
+		if fmt == formIndirect {
+			fmt = format(b.uint())
+		}
+		var val interface{}
+		switch fmt {
+		default:
+			b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
+
+		// address
+		case formAddr:
+			val = b.addr()
+
+		// block
+		case formDwarfBlock1:
+			val = b.bytes(int(b.uint8()))
+		case formDwarfBlock2:
+			val = b.bytes(int(b.uint16()))
+		case formDwarfBlock4:
+			val = b.bytes(int(b.uint32()))
+		case formDwarfBlock:
+			val = b.bytes(int(b.uint()))
+
+		// constant
+		case formData1:
+			val = int64(b.uint8())
+		case formData2:
+			val = int64(b.uint16())
+		case formData4:
+			val = int64(b.uint32())
+		case formData8:
+			val = int64(b.uint64())
+		case formSdata:
+			val = int64(b.int())
+		case formUdata:
+			val = int64(b.uint())
+
+		// flag
+		case formFlag:
+			val = b.uint8() == 1
+		// New in DWARF 4.
+		case formFlagPresent:
+			// The attribute is implicitly indicated as present, and no value is
+			// encoded in the debugging information entry itself.
+			val = true
+
+		// reference to other entry
+		case formRefAddr:
+			vers := b.format.version()
+			if vers == 0 {
+				b.error("unknown version for DW_FORM_ref_addr")
+			} else if vers == 2 {
+				val = Offset(b.addr())
+			} else {
+				is64, known := b.format.dwarf64()
+				if !known {
+					b.error("unknown size for DW_FORM_ref_addr")
+				} else if is64 {
+					val = Offset(b.uint64())
+				} else {
+					val = Offset(b.uint32())
+				}
+			}
+		case formRef1:
+			val = Offset(b.uint8()) + ubase
+		case formRef2:
+			val = Offset(b.uint16()) + ubase
+		case formRef4:
+			val = Offset(b.uint32()) + ubase
+		case formRef8:
+			val = Offset(b.uint64()) + ubase
+		case formRefUdata:
+			val = Offset(b.uint()) + ubase
+
+		// string
+		case formString:
+			val = b.string()
+		case formStrp:
+			off := b.uint32() // offset into .debug_str
+			if b.err != nil {
+				return nil
+			}
+			b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str)
+			b1.skip(int(off))
+			val = b1.string()
+			if b1.err != nil {
+				b.err = b1.err
+				return nil
+			}
+
+		// lineptr, loclistptr, macptr, rangelistptr
+		// New in DWARF 4, but clang can generate them with -gdwarf-2.
+		// Section reference, replacing use of formData4 and formData8.
+		case formSecOffset, formGnuRefAlt, formGnuStrpAlt:
+			is64, known := b.format.dwarf64()
+			if !known {
+				b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16))
+			} else if is64 {
+				val = int64(b.uint64())
+			} else {
+				val = int64(b.uint32())
+			}
+
+		// exprloc
+		// New in DWARF 4.
+		case formExprloc:
+			val = b.bytes(int(b.uint()))
+
+		// reference
+		// New in DWARF 4.
+		case formRefSig8:
+			// 64-bit type signature.
+			val = b.uint64()
+		}
+		e.Field[i].Val = val
+	}
+	if b.err != nil {
+		return nil
+	}
+	return e
+}
+
+// A Reader allows reading Entry structures from a DWARF ``info'' section.
+// The Entry structures are arranged in a tree.  The Reader's Next function
+// return successive entries from a pre-order traversal of the tree.
+// If an entry has children, its Children field will be true, and the children
+// follow, terminated by an Entry with Tag 0.
+type Reader struct {
+	b            buf
+	d            *Data
+	err          error
+	unit         int
+	lastChildren bool   // .Children of last entry returned by Next
+	lastSibling  Offset // .Val(AttrSibling) of last entry returned by Next
+}
+
+// Reader returns a new Reader for Data.
+// The reader is positioned at byte offset 0 in the DWARF ``info'' section.
+func (d *Data) Reader() *Reader {
+	r := &Reader{d: d}
+	r.Seek(0)
+	return r
+}
+
+// unitReader returns a new reader starting at a specific unit.
+func (d *Data) unitReader(i int) *Reader {
+	r := &Reader{d: d}
+	r.unit = i
+	u := &d.unit[i]
+	r.b = makeBuf(d, u, "info", u.off, u.data)
+	return r
+}
+
+// Seek positions the Reader at offset off in the encoded entry stream.
+// Offset 0 can be used to denote the first entry.
+func (r *Reader) Seek(off Offset) {
+	d := r.d
+	r.err = nil
+	r.lastChildren = false
+	if off == 0 {
+		if len(d.unit) == 0 {
+			return
+		}
+		u := &d.unit[0]
+		r.unit = 0
+		r.b = makeBuf(r.d, u, "info", u.off, u.data)
+		return
+	}
+
+	// TODO(rsc): binary search (maybe a new package)
+	var i int
+	var u *unit
+	for i = range d.unit {
+		u = &d.unit[i]
+		if u.off <= off && off < u.off+Offset(len(u.data)) {
+			r.unit = i
+			r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
+			return
+		}
+	}
+	r.err = errors.New("offset out of range")
+}
+
+// maybeNextUnit advances to the next unit if this one is finished.
+func (r *Reader) maybeNextUnit() {
+	for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
+		r.unit++
+		u := &r.d.unit[r.unit]
+		r.b = makeBuf(r.d, u, "info", u.off, u.data)
+	}
+}
+
+// Next reads the next entry from the encoded entry stream.
+// It returns nil, nil when it reaches the end of the section.
+// It returns an error if the current offset is invalid or the data at the
+// offset cannot be decoded as a valid Entry.
+func (r *Reader) Next() (*Entry, error) {
+	if r.err != nil {
+		return nil, r.err
+	}
+	r.maybeNextUnit()
+	if len(r.b.data) == 0 {
+		return nil, nil
+	}
+	u := &r.d.unit[r.unit]
+	e := r.b.entry(u.atable, u.base)
+	if r.b.err != nil {
+		r.err = r.b.err
+		return nil, r.err
+	}
+	if e != nil {
+		r.lastChildren = e.Children
+		if r.lastChildren {
+			r.lastSibling, _ = e.Val(AttrSibling).(Offset)
+		}
+	} else {
+		r.lastChildren = false
+	}
+	return e, nil
+}
+
+// SkipChildren skips over the child entries associated with
+// the last Entry returned by Next.  If that Entry did not have
+// children or Next has not been called, SkipChildren is a no-op.
+func (r *Reader) SkipChildren() {
+	if r.err != nil || !r.lastChildren {
+		return
+	}
+
+	// If the last entry had a sibling attribute,
+	// that attribute gives the offset of the next
+	// sibling, so we can avoid decoding the
+	// child subtrees.
+	if r.lastSibling >= r.b.off {
+		r.Seek(r.lastSibling)
+		return
+	}
+
+	for {
+		e, err := r.Next()
+		if err != nil || e == nil || e.Tag == 0 {
+			break
+		}
+		if e.Children {
+			r.SkipChildren()
+		}
+	}
+}
+
+// clone returns a copy of the reader.  This is used by the typeReader
+// interface.
+func (r *Reader) clone() typeReader {
+	return r.d.Reader()
+}
+
+// offset returns the current buffer offset.  This is used by the
+// typeReader interface.
+func (r *Reader) offset() Offset {
+	return r.b.off
+}
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/line.go b/third_party/gofrontend/libgo/go/debug/dwarf/line.go
new file mode 100644
index 0000000..c463c3b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/line.go
@@ -0,0 +1,481 @@
+// 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.
+
+// DWARF line number information.
+
+package dwarf
+
+import (
+	"errors"
+	"path/filepath"
+	"sort"
+	"strconv"
+)
+
+// A Line holds all the available information about the source code
+// corresponding to a specific program counter address.
+type Line struct {
+	Filename      string // source file name
+	OpIndex       int    // index of operation in VLIW instruction
+	Line          int    // line number
+	Column        int    // column number
+	ISA           int    // instruction set code
+	Discriminator int    // block discriminator
+	Stmt          bool   // instruction starts statement
+	Block         bool   // instruction starts basic block
+	EndPrologue   bool   // instruction ends function prologue
+	BeginEpilogue bool   // instruction begins function epilogue
+}
+
+// LineForPc returns the line number information for a program counter
+// address, if any.  When this returns multiple Line structures in a
+// context where only one can be used, the last one is the best.
+func (d *Data) LineForPC(pc uint64) ([]*Line, error) {
+	for i := range d.unit {
+		u := &d.unit[i]
+		if u.pc == nil {
+			if err := d.readUnitLine(i, u); err != nil {
+				return nil, err
+			}
+		}
+		for _, ar := range u.pc {
+			if pc >= ar.low && pc < ar.high {
+				return d.findLine(u, pc)
+			}
+		}
+	}
+	return nil, nil
+}
+
+// readUnitLine reads in the line number information for a compilation
+// unit.
+func (d *Data) readUnitLine(i int, u *unit) error {
+	r := d.unitReader(i)
+	setLineOff := false
+	for {
+		e, err := r.Next()
+		if err != nil {
+			return err
+		}
+		if e == nil {
+			break
+		}
+		if r.unit != i {
+			break
+		}
+		switch e.Tag {
+		case TagCompileUnit, TagSubprogram, TagEntryPoint, TagInlinedSubroutine:
+			low, lowok := e.Val(AttrLowpc).(uint64)
+			var high uint64
+			var highok bool
+			switch v := e.Val(AttrHighpc).(type) {
+			case uint64:
+				high = v
+				highok = true
+			case int64:
+				high = low + uint64(v)
+				highok = true
+			}
+			if lowok && highok {
+				u.pc = append(u.pc, addrRange{low, high})
+			} else if off, ok := e.Val(AttrRanges).(Offset); ok {
+				if err := d.readAddressRanges(off, low, u); err != nil {
+					return err
+				}
+			}
+			val := e.Val(AttrStmtList)
+			if val != nil {
+				if off, ok := val.(int64); ok {
+					u.lineoff = Offset(off)
+					setLineOff = true
+				} else if off, ok := val.(Offset); ok {
+					u.lineoff = off
+					setLineOff = true
+				} else {
+					return errors.New("unrecognized format for DW_ATTR_stmt_list")
+				}
+			}
+			if dir, ok := e.Val(AttrCompDir).(string); ok {
+				u.dir = dir
+			}
+		}
+	}
+	if !setLineOff {
+		u.lineoff = Offset(0)
+		u.lineoff--
+	}
+	return nil
+}
+
+// readAddressRanges adds address ranges to a unit.
+func (d *Data) readAddressRanges(off Offset, base uint64, u *unit) error {
+	b := makeBuf(d, u, "ranges", off, d.ranges[off:])
+	var highest uint64
+	switch u.addrsize() {
+	case 1:
+		highest = 0xff
+	case 2:
+		highest = 0xffff
+	case 4:
+		highest = 0xffffffff
+	case 8:
+		highest = 0xffffffffffffffff
+	default:
+		return errors.New("unknown address size")
+	}
+	for {
+		if b.err != nil {
+			return b.err
+		}
+		low := b.addr()
+		high := b.addr()
+		if low == 0 && high == 0 {
+			return b.err
+		} else if low == highest {
+			base = high
+		} else {
+			u.pc = append(u.pc, addrRange{low + base, high + base})
+		}
+	}
+}
+
+// findLine finds the line information for a PC value, given the unit
+// containing the information.
+func (d *Data) findLine(u *unit, pc uint64) ([]*Line, error) {
+	if u.lines == nil {
+		if err := d.parseLine(u); err != nil {
+			return nil, err
+		}
+	}
+
+	for _, ln := range u.lines {
+		if pc < ln.addrs[0].pc || pc > ln.addrs[len(ln.addrs)-1].pc {
+			continue
+		}
+		i := sort.Search(len(ln.addrs),
+			func(i int) bool { return ln.addrs[i].pc > pc })
+		i--
+		p := new(Line)
+		*p = ln.line
+		p.Line = ln.addrs[i].line
+		ret := []*Line{p}
+		for i++; i < len(ln.addrs) && ln.addrs[i].pc == pc; i++ {
+			p = new(Line)
+			*p = ln.line
+			p.Line = ln.addrs[i].line
+			ret = append(ret, p)
+		}
+		return ret, nil
+	}
+
+	return nil, nil
+}
+
+// FileLine returns the file name and line number for a program
+// counter address, or "", 0 if unknown.
+func (d *Data) FileLine(pc uint64) (string, int, error) {
+	r, err := d.LineForPC(pc)
+	if err != nil {
+		return "", 0, err
+	}
+	if r == nil {
+		return "", 0, nil
+	}
+	ln := r[len(r)-1]
+	return ln.Filename, ln.Line, nil
+}
+
+// A mapLineInfo holds the PC values and line numbers associated with
+// a single Line structure.  This representation is chosen to reduce
+// memory usage based on typical debug info.
+type mapLineInfo struct {
+	line  Line      // line.Line will be zero
+	addrs lineAddrs // sorted by PC
+}
+
+// A list of lines.  This will be sorted by PC.
+type lineAddrs []oneLineInfo
+
+func (p lineAddrs) Len() int           { return len(p) }
+func (p lineAddrs) Less(i, j int) bool { return p[i].pc < p[j].pc }
+func (p lineAddrs) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// A oneLineInfo is a single PC and line number.
+type oneLineInfo struct {
+	pc   uint64
+	line int
+}
+
+// A lineHdr holds the relevant information from a line number
+// program header.
+type lineHdr struct {
+	version       uint16   // version of line number encoding
+	minInsnLen    uint8    // minimum instruction length
+	maxOpsPerInsn uint8    // maximum number of ops per instruction
+	defStmt       bool     // initial value of stmt register
+	lineBase      int8     // line adjustment base
+	lineRange     uint8    // line adjustment step
+	opBase        uint8    // base of special opcode values
+	opLen         []uint8  // lengths of standard opcodes
+	dirs          []string // directories
+	files         []string // file names
+}
+
+// parseLine parses the line number information for a compilation unit
+func (d *Data) parseLine(u *unit) error {
+	if u.lineoff+1 == 0 {
+		return errors.New("unknown line offset")
+	}
+	b := makeBuf(d, u, "line", u.lineoff, d.line[u.lineoff:])
+	len := uint64(b.uint32())
+	dwarf64 := false
+	if len == 0xffffffff {
+		len = b.uint64()
+		dwarf64 = true
+	}
+	end := b.off + Offset(len)
+	hdr := d.parseLineHdr(u, &b, dwarf64)
+	if b.err == nil {
+		d.parseLineProgram(u, &b, hdr, end)
+	}
+	return b.err
+}
+
+// parseLineHdr parses a line number program header.
+func (d *Data) parseLineHdr(u *unit, b *buf, dwarf64 bool) (hdr lineHdr) {
+	hdr.version = b.uint16()
+	if hdr.version < 2 || hdr.version > 4 {
+		b.error("unsupported DWARF version " + strconv.Itoa(int(hdr.version)))
+		return
+	}
+
+	var hlen Offset
+	if dwarf64 {
+		hlen = Offset(b.uint64())
+	} else {
+		hlen = Offset(b.uint32())
+	}
+	end := b.off + hlen
+
+	hdr.minInsnLen = b.uint8()
+	if hdr.version < 4 {
+		hdr.maxOpsPerInsn = 1
+	} else {
+		hdr.maxOpsPerInsn = b.uint8()
+	}
+
+	if b.uint8() == 0 {
+		hdr.defStmt = false
+	} else {
+		hdr.defStmt = true
+	}
+	hdr.lineBase = int8(b.uint8())
+	hdr.lineRange = b.uint8()
+	hdr.opBase = b.uint8()
+	hdr.opLen = b.bytes(int(hdr.opBase - 1))
+
+	for d := b.string(); len(d) > 0; d = b.string() {
+		hdr.dirs = append(hdr.dirs, d)
+	}
+
+	for f := b.string(); len(f) > 0; f = b.string() {
+		d := b.uint()
+		if !filepath.IsAbs(f) {
+			if d > 0 {
+				if d > uint64(len(hdr.dirs)) {
+					b.error("DWARF directory index out of range")
+					return
+				}
+				f = filepath.Join(hdr.dirs[d-1], f)
+			} else if u.dir != "" {
+				f = filepath.Join(u.dir, f)
+			}
+		}
+		b.uint() // file's last mtime
+		b.uint() // file length
+		hdr.files = append(hdr.files, f)
+	}
+
+	if end > b.off {
+		b.bytes(int(end - b.off))
+	}
+
+	return
+}
+
+// parseLineProgram parses a line program, adding information to
+// d.lineInfo as it goes.
+func (d *Data) parseLineProgram(u *unit, b *buf, hdr lineHdr, end Offset) {
+	address := uint64(0)
+	line := 1
+	resetLineInfo := Line{
+		Filename:      "",
+		OpIndex:       0,
+		Line:          0,
+		Column:        0,
+		ISA:           0,
+		Discriminator: 0,
+		Stmt:          hdr.defStmt,
+		Block:         false,
+		EndPrologue:   false,
+		BeginEpilogue: false,
+	}
+	if len(hdr.files) > 0 {
+		resetLineInfo.Filename = hdr.files[0]
+	}
+	lineInfo := resetLineInfo
+
+	var lines []mapLineInfo
+
+	minInsnLen := uint64(hdr.minInsnLen)
+	maxOpsPerInsn := uint64(hdr.maxOpsPerInsn)
+	lineBase := int(hdr.lineBase)
+	lineRange := hdr.lineRange
+	newLineInfo := true
+	for b.off < end && b.err == nil {
+		op := b.uint8()
+		if op >= hdr.opBase {
+			// This is a special opcode.
+			op -= hdr.opBase
+			advance := uint64(op / hdr.lineRange)
+			opIndex := uint64(lineInfo.OpIndex)
+			address += minInsnLen * ((opIndex + advance) / maxOpsPerInsn)
+			newOpIndex := int((opIndex + advance) % maxOpsPerInsn)
+			line += lineBase + int(op%lineRange)
+			if newOpIndex != lineInfo.OpIndex {
+				lineInfo.OpIndex = newOpIndex
+				newLineInfo = true
+			}
+			lines, lineInfo, newLineInfo = d.addLine(lines, lineInfo, address, line, newLineInfo)
+		} else if op == LineExtendedOp {
+			c := b.uint()
+			op = b.uint8()
+			switch op {
+			case LineExtEndSequence:
+				u.lines = append(u.lines, lines...)
+				lineInfo = resetLineInfo
+				lines = nil
+				newLineInfo = true
+			case LineExtSetAddress:
+				address = b.addr()
+			case LineExtDefineFile:
+				f := b.string()
+				d := b.uint()
+				b.uint() // mtime
+				b.uint() // length
+				if d > 0 && !filepath.IsAbs(f) {
+					if d >= uint64(len(hdr.dirs)) {
+						b.error("DWARF directory index out of range")
+						return
+					}
+					f = filepath.Join(hdr.dirs[d-1], f)
+				}
+				hdr.files = append(hdr.files, f)
+			case LineExtSetDiscriminator:
+				lineInfo.Discriminator = int(b.uint())
+				newLineInfo = true
+			default:
+				if c > 0 {
+					b.bytes(int(c) - 1)
+				}
+			}
+		} else {
+			switch op {
+			case LineCopy:
+				lines, lineInfo, newLineInfo = d.addLine(lines, lineInfo, address, line, newLineInfo)
+			case LineAdvancePC:
+				advance := b.uint()
+				opIndex := uint64(lineInfo.OpIndex)
+				address += minInsnLen * ((opIndex + advance) / maxOpsPerInsn)
+				newOpIndex := int((opIndex + advance) % maxOpsPerInsn)
+				if newOpIndex != lineInfo.OpIndex {
+					lineInfo.OpIndex = newOpIndex
+					newLineInfo = true
+				}
+			case LineAdvanceLine:
+				line += int(b.int())
+			case LineSetFile:
+				i := b.uint()
+				if i > uint64(len(hdr.files)) {
+					b.error("DWARF file number out of range")
+					return
+				}
+				lineInfo.Filename = hdr.files[i-1]
+				newLineInfo = true
+			case LineSetColumn:
+				lineInfo.Column = int(b.uint())
+				newLineInfo = true
+			case LineNegateStmt:
+				lineInfo.Stmt = !lineInfo.Stmt
+				newLineInfo = true
+			case LineSetBasicBlock:
+				lineInfo.Block = true
+				newLineInfo = true
+			case LineConstAddPC:
+				op = 255 - hdr.opBase
+				advance := uint64(op / hdr.lineRange)
+				opIndex := uint64(lineInfo.OpIndex)
+				address += minInsnLen * ((opIndex + advance) / maxOpsPerInsn)
+				newOpIndex := int((opIndex + advance) % maxOpsPerInsn)
+				if newOpIndex != lineInfo.OpIndex {
+					lineInfo.OpIndex = newOpIndex
+					newLineInfo = true
+				}
+			case LineFixedAdvancePC:
+				address += uint64(b.uint16())
+				if lineInfo.OpIndex != 0 {
+					lineInfo.OpIndex = 0
+					newLineInfo = true
+				}
+			case LineSetPrologueEnd:
+				lineInfo.EndPrologue = true
+				newLineInfo = true
+			case LineSetEpilogueBegin:
+				lineInfo.BeginEpilogue = true
+				newLineInfo = true
+			case LineSetISA:
+				lineInfo.ISA = int(b.uint())
+				newLineInfo = true
+			default:
+				if int(op) >= len(hdr.opLen) {
+					b.error("DWARF line opcode has unknown length")
+					return
+				}
+				for i := hdr.opLen[op-1]; i > 0; i-- {
+					b.int()
+				}
+			}
+		}
+	}
+}
+
+// addLine adds the current address and line to lines using lineInfo.
+// If newLineInfo is true this is a new lineInfo.  This returns the
+// updated lines, lineInfo, and newLineInfo.
+func (d *Data) addLine(lines []mapLineInfo, lineInfo Line, address uint64, line int, newLineInfo bool) ([]mapLineInfo, Line, bool) {
+	if newLineInfo {
+		if len(lines) > 0 {
+			sort.Sort(lines[len(lines)-1].addrs)
+			p := &lines[len(lines)-1]
+			if len(p.addrs) > 0 && address > p.addrs[len(p.addrs)-1].pc {
+				p.addrs = append(p.addrs, oneLineInfo{address, p.addrs[len(p.addrs)-1].line})
+			}
+		}
+		lines = append(lines, mapLineInfo{line: lineInfo})
+	}
+	p := &lines[len(lines)-1]
+	p.addrs = append(p.addrs, oneLineInfo{address, line})
+
+	if lineInfo.Block || lineInfo.EndPrologue || lineInfo.BeginEpilogue || lineInfo.Discriminator != 0 {
+		lineInfo.Block = false
+		lineInfo.EndPrologue = false
+		lineInfo.BeginEpilogue = false
+		lineInfo.Discriminator = 0
+		newLineInfo = true
+	} else {
+		newLineInfo = false
+	}
+
+	return lines, lineInfo, newLineInfo
+}
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/line_test.go b/third_party/gofrontend/libgo/go/debug/dwarf/line_test.go
new file mode 100644
index 0000000..2476a6f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/line_test.go
@@ -0,0 +1,53 @@
+// 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 dwarf_test
+
+import (
+	. "debug/dwarf"
+	"path/filepath"
+	"testing"
+)
+
+type lineTest struct {
+	pc   uint64
+	file string
+	line int
+}
+
+var elfLineTests = [...]lineTest{
+	{0x4004c4, "typedef.c", 83},
+	{0x4004c8, "typedef.c", 84},
+	{0x4004ca, "typedef.c", 84},
+	{0x4003e0, "", 0},
+}
+
+var machoLineTests = [...]lineTest{
+	{0x0, "typedef.c", 83},
+}
+
+func TestLineElf(t *testing.T) {
+	testLine(t, elfData(t, "testdata/typedef.elf"), elfLineTests[:], "elf")
+}
+
+func TestLineMachO(t *testing.T) {
+	testLine(t, machoData(t, "testdata/typedef.macho"), machoLineTests[:], "macho")
+}
+
+func testLine(t *testing.T, d *Data, tests []lineTest, kind string) {
+	for _, v := range tests {
+		file, line, err := d.FileLine(v.pc)
+		if err != nil {
+			t.Errorf("%s: %v", kind, err)
+			continue
+		}
+		if file != "" {
+			file = filepath.Base(file)
+		}
+		if file != v.file || line != v.line {
+			t.Errorf("%s: for %d have %q:%d want %q:%d",
+				kind, v.pc, file, line, v.file, v.line)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/open.go b/third_party/gofrontend/libgo/go/debug/dwarf/open.go
new file mode 100644
index 0000000..c1b3f37
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/open.go
@@ -0,0 +1,87 @@
+// 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 dwarf provides access to DWARF debugging information loaded from
+// executable files, as defined in the DWARF 2.0 Standard at
+// http://dwarfstd.org/doc/dwarf-2.0.0.pdf
+package dwarf
+
+import "encoding/binary"
+
+// Data represents the DWARF debugging information
+// loaded from an executable file (for example, an ELF or Mach-O executable).
+type Data struct {
+	// raw data
+	abbrev   []byte
+	aranges  []byte
+	frame    []byte
+	info     []byte
+	line     []byte
+	pubnames []byte
+	ranges   []byte
+	str      []byte
+
+	// parsed data
+	abbrevCache map[uint32]abbrevTable
+	order       binary.ByteOrder
+	typeCache   map[Offset]Type
+	typeSigs    map[uint64]*typeUnit
+	unit        []unit
+}
+
+// New returns a new Data object initialized from the given parameters.
+// Rather than calling this function directly, clients should typically use
+// the DWARF method of the File type of the appropriate package debug/elf,
+// debug/macho, or debug/pe.
+//
+// The []byte arguments are the data from the corresponding debug section
+// in the object file; for example, for an ELF object, abbrev is the contents of
+// the ".debug_abbrev" section.
+func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Data, error) {
+	d := &Data{
+		abbrev:      abbrev,
+		aranges:     aranges,
+		frame:       frame,
+		info:        info,
+		line:        line,
+		pubnames:    pubnames,
+		ranges:      ranges,
+		str:         str,
+		abbrevCache: make(map[uint32]abbrevTable),
+		typeCache:   make(map[Offset]Type),
+		typeSigs:    make(map[uint64]*typeUnit),
+	}
+
+	// Sniff .debug_info to figure out byte order.
+	// bytes 4:6 are the version, a tiny 16-bit number (1, 2, 3).
+	if len(d.info) < 6 {
+		return nil, DecodeError{"info", Offset(len(d.info)), "too short"}
+	}
+	x, y := d.info[4], d.info[5]
+	switch {
+	case x == 0 && y == 0:
+		return nil, DecodeError{"info", 4, "unsupported version 0"}
+	case x == 0:
+		d.order = binary.BigEndian
+	case y == 0:
+		d.order = binary.LittleEndian
+	default:
+		return nil, DecodeError{"info", 4, "cannot determine byte order"}
+	}
+
+	u, err := d.parseUnits()
+	if err != nil {
+		return nil, err
+	}
+	d.unit = u
+	return d, nil
+}
+
+// AddTypes will add one .debug_types section to the DWARF data.  A
+// typical object with DWARF version 4 debug info will have multiple
+// .debug_types sections.  The name is used for error reporting only,
+// and serves to distinguish one .debug_types section from another.
+func (d *Data) AddTypes(name string, types []byte) error {
+	return d.parseTypes(name, types)
+}
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.c b/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.c
new file mode 100644
index 0000000..f05f015
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.c
@@ -0,0 +1,85 @@
+// 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.
+
+/*
+Linux ELF:
+gcc -gdwarf-2 -m64 -c typedef.c && gcc -gdwarf-2 -m64 -o typedef.elf typedef.o
+
+OS X Mach-O:
+gcc -gdwarf-2 -m64 -c typedef.c -o typedef.macho
+*/
+#include <complex.h>
+
+typedef volatile int* t_ptr_volatile_int;
+typedef const char *t_ptr_const_char;
+typedef long t_long;
+typedef unsigned short t_ushort;
+typedef int t_func_int_of_float_double(float, double);
+typedef int (*t_ptr_func_int_of_float_double)(float, double);
+typedef int (*t_ptr_func_int_of_float_complex)(float complex);
+typedef int (*t_ptr_func_int_of_double_complex)(double complex);
+typedef int (*t_ptr_func_int_of_long_double_complex)(long double complex);
+typedef int *t_func_ptr_int_of_char_schar_uchar(char, signed char, unsigned char);
+typedef void t_func_void_of_char(char);
+typedef void t_func_void_of_void(void);
+typedef void t_func_void_of_ptr_char_dots(char*, ...);
+typedef struct my_struct {
+	volatile int vi;
+	char x : 1;
+	int y : 4;
+	int z[0];
+	long long array[40];
+	int zz[0];
+} t_my_struct;
+typedef struct my_struct1 {
+	int zz [1];
+} t_my_struct1;
+typedef union my_union {
+	volatile int vi;
+	char x : 1;
+	int y : 4;
+	long long array[40];
+} t_my_union;
+typedef enum my_enum {
+	e1 = 1,
+	e2 = 2,
+	e3 = -5,
+	e4 = 1000000000000000LL,
+} t_my_enum;
+
+typedef struct list t_my_list;
+struct list {
+	short val;
+	t_my_list *next;
+};
+
+typedef struct tree {
+	struct tree *left, *right;
+	unsigned long long val;
+} t_my_tree;
+
+t_ptr_volatile_int *a2;
+t_ptr_const_char **a3a;
+t_long *a4;
+t_ushort *a5;
+t_func_int_of_float_double *a6;
+t_ptr_func_int_of_float_double *a7;
+t_func_ptr_int_of_char_schar_uchar *a8;
+t_func_void_of_char *a9;
+t_func_void_of_void *a10;
+t_func_void_of_ptr_char_dots *a11;
+t_my_struct *a12;
+t_my_struct1 *a12a;
+t_my_union *a12b;
+t_my_enum *a13;
+t_my_list *a14;
+t_my_tree *a15;
+t_ptr_func_int_of_float_complex *a16;
+t_ptr_func_int_of_double_complex *a17;
+t_ptr_func_int_of_long_double_complex *a18;
+
+int main()
+{
+	return 0;
+}
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.elf b/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.elf
new file mode 100755
index 0000000..b2062d2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.elf
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.elf4 b/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.elf4
new file mode 100644
index 0000000..3d5a5a1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.elf4
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.macho b/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.macho
new file mode 100644
index 0000000..f75afcc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/testdata/typedef.macho
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/type.go b/third_party/gofrontend/libgo/go/debug/dwarf/type.go
new file mode 100644
index 0000000..68866d0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/type.go
@@ -0,0 +1,659 @@
+// 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.
+
+// DWARF type information structures.
+// The format is heavily biased toward C, but for simplicity
+// the String methods use a pseudo-Go syntax.
+
+package dwarf
+
+import "strconv"
+
+// A Type conventionally represents a pointer to any of the
+// specific Type structures (CharType, StructType, etc.).
+type Type interface {
+	Common() *CommonType
+	String() string
+	Size() int64
+}
+
+// A CommonType holds fields common to multiple types.
+// If a field is not known or not applicable for a given type,
+// the zero value is used.
+type CommonType struct {
+	ByteSize int64  // size of value of this type, in bytes
+	Name     string // name that can be used to refer to type
+}
+
+func (c *CommonType) Common() *CommonType { return c }
+
+func (c *CommonType) Size() int64 { return c.ByteSize }
+
+// Basic types
+
+// A BasicType holds fields common to all basic types.
+type BasicType struct {
+	CommonType
+	BitSize   int64
+	BitOffset int64
+}
+
+func (b *BasicType) Basic() *BasicType { return b }
+
+func (t *BasicType) String() string {
+	if t.Name != "" {
+		return t.Name
+	}
+	return "?"
+}
+
+// A CharType represents a signed character type.
+type CharType struct {
+	BasicType
+}
+
+// A UcharType represents an unsigned character type.
+type UcharType struct {
+	BasicType
+}
+
+// An IntType represents a signed integer type.
+type IntType struct {
+	BasicType
+}
+
+// A UintType represents an unsigned integer type.
+type UintType struct {
+	BasicType
+}
+
+// A FloatType represents a floating point type.
+type FloatType struct {
+	BasicType
+}
+
+// A ComplexType represents a complex floating point type.
+type ComplexType struct {
+	BasicType
+}
+
+// A BoolType represents a boolean type.
+type BoolType struct {
+	BasicType
+}
+
+// An AddrType represents a machine address type.
+type AddrType struct {
+	BasicType
+}
+
+// qualifiers
+
+// A QualType represents a type that has the C/C++ "const", "restrict", or "volatile" qualifier.
+type QualType struct {
+	CommonType
+	Qual string
+	Type Type
+}
+
+func (t *QualType) String() string { return t.Qual + " " + t.Type.String() }
+
+func (t *QualType) Size() int64 { return t.Type.Size() }
+
+// An ArrayType represents a fixed size array type.
+type ArrayType struct {
+	CommonType
+	Type          Type
+	StrideBitSize int64 // if > 0, number of bits to hold each element
+	Count         int64 // if == -1, an incomplete array, like char x[].
+}
+
+func (t *ArrayType) String() string {
+	return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String()
+}
+
+func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() }
+
+// A VoidType represents the C void type.
+type VoidType struct {
+	CommonType
+}
+
+func (t *VoidType) String() string { return "void" }
+
+// A PtrType represents a pointer type.
+type PtrType struct {
+	CommonType
+	Type Type
+}
+
+func (t *PtrType) String() string { return "*" + t.Type.String() }
+
+// A StructType represents a struct, union, or C++ class type.
+type StructType struct {
+	CommonType
+	StructName string
+	Kind       string // "struct", "union", or "class".
+	Field      []*StructField
+	Incomplete bool // if true, struct, union, class is declared but not defined
+}
+
+// A StructField represents a field in a struct, union, or C++ class type.
+type StructField struct {
+	Name       string
+	Type       Type
+	ByteOffset int64
+	ByteSize   int64
+	BitOffset  int64 // within the ByteSize bytes at ByteOffset
+	BitSize    int64 // zero if not a bit field
+}
+
+func (t *StructType) String() string {
+	if t.StructName != "" {
+		return t.Kind + " " + t.StructName
+	}
+	return t.Defn()
+}
+
+func (t *StructType) Defn() string {
+	s := t.Kind
+	if t.StructName != "" {
+		s += " " + t.StructName
+	}
+	if t.Incomplete {
+		s += " /*incomplete*/"
+		return s
+	}
+	s += " {"
+	for i, f := range t.Field {
+		if i > 0 {
+			s += "; "
+		}
+		s += f.Name + " " + f.Type.String()
+		s += "@" + strconv.FormatInt(f.ByteOffset, 10)
+		if f.BitSize > 0 {
+			s += " : " + strconv.FormatInt(f.BitSize, 10)
+			s += "@" + strconv.FormatInt(f.BitOffset, 10)
+		}
+	}
+	s += "}"
+	return s
+}
+
+// An EnumType represents an enumerated type.
+// The only indication of its native integer type is its ByteSize
+// (inside CommonType).
+type EnumType struct {
+	CommonType
+	EnumName string
+	Val      []*EnumValue
+}
+
+// An EnumValue represents a single enumeration value.
+type EnumValue struct {
+	Name string
+	Val  int64
+}
+
+func (t *EnumType) String() string {
+	s := "enum"
+	if t.EnumName != "" {
+		s += " " + t.EnumName
+	}
+	s += " {"
+	for i, v := range t.Val {
+		if i > 0 {
+			s += "; "
+		}
+		s += v.Name + "=" + strconv.FormatInt(v.Val, 10)
+	}
+	s += "}"
+	return s
+}
+
+// A FuncType represents a function type.
+type FuncType struct {
+	CommonType
+	ReturnType Type
+	ParamType  []Type
+}
+
+func (t *FuncType) String() string {
+	s := "func("
+	for i, t := range t.ParamType {
+		if i > 0 {
+			s += ", "
+		}
+		s += t.String()
+	}
+	s += ")"
+	if t.ReturnType != nil {
+		s += " " + t.ReturnType.String()
+	}
+	return s
+}
+
+// A DotDotDotType represents the variadic ... function parameter.
+type DotDotDotType struct {
+	CommonType
+}
+
+func (t *DotDotDotType) String() string { return "..." }
+
+// A TypedefType represents a named type.
+type TypedefType struct {
+	CommonType
+	Type Type
+}
+
+func (t *TypedefType) String() string { return t.Name }
+
+func (t *TypedefType) Size() int64 { return t.Type.Size() }
+
+// typeReader is used to read from either the info section or the
+// types section.
+type typeReader interface {
+	Seek(Offset)
+	Next() (*Entry, error)
+	clone() typeReader
+	offset() Offset
+}
+
+// Type reads the type at off in the DWARF ``info'' section.
+func (d *Data) Type(off Offset) (Type, error) {
+	return d.readType("info", d.Reader(), off, d.typeCache)
+}
+
+// readType reads a type from r at off of name using and updating a
+// type cache.
+func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type) (Type, error) {
+	if t, ok := typeCache[off]; ok {
+		return t, nil
+	}
+	r.Seek(off)
+	e, err := r.Next()
+	if err != nil {
+		return nil, err
+	}
+	if e == nil || e.Offset != off {
+		return nil, DecodeError{name, off, "no type at offset"}
+	}
+
+	// Parse type from Entry.
+	// Must always set typeCache[off] before calling
+	// d.Type recursively, to handle circular types correctly.
+	var typ Type
+
+	nextDepth := 0
+
+	// Get next child; set err if error happens.
+	next := func() *Entry {
+		if !e.Children {
+			return nil
+		}
+		// Only return direct children.
+		// Skip over composite entries that happen to be nested
+		// inside this one. Most DWARF generators wouldn't generate
+		// such a thing, but clang does.
+		// See golang.org/issue/6472.
+		for {
+			kid, err1 := r.Next()
+			if err1 != nil {
+				err = err1
+				return nil
+			}
+			if kid == nil {
+				err = DecodeError{name, r.offset(), "unexpected end of DWARF entries"}
+				return nil
+			}
+			if kid.Tag == 0 {
+				if nextDepth > 0 {
+					nextDepth--
+					continue
+				}
+				return nil
+			}
+			if kid.Children {
+				nextDepth++
+			}
+			if nextDepth > 0 {
+				continue
+			}
+			return kid
+		}
+	}
+
+	// Get Type referred to by Entry's AttrType field.
+	// Set err if error happens.  Not having a type is an error.
+	typeOf := func(e *Entry) Type {
+		tval := e.Val(AttrType)
+		var t Type
+		switch toff := tval.(type) {
+		case Offset:
+			if t, err = d.readType(name, r.clone(), toff, typeCache); err != nil {
+				return nil
+			}
+		case uint64:
+			if t, err = d.sigToType(toff); err != nil {
+				return nil
+			}
+		default:
+			// It appears that no Type means "void".
+			return new(VoidType)
+		}
+		return t
+	}
+
+	switch e.Tag {
+	case TagArrayType:
+		// Multi-dimensional array.  (DWARF v2 §5.4)
+		// Attributes:
+		//	AttrType:subtype [required]
+		//	AttrStrideSize: size in bits of each element of the array
+		//	AttrByteSize: size of entire array
+		// Children:
+		//	TagSubrangeType or TagEnumerationType giving one dimension.
+		//	dimensions are in left to right order.
+		t := new(ArrayType)
+		typ = t
+		typeCache[off] = t
+		if t.Type = typeOf(e); err != nil {
+			goto Error
+		}
+		t.StrideBitSize, _ = e.Val(AttrStrideSize).(int64)
+
+		// Accumulate dimensions,
+		ndim := 0
+		for kid := next(); kid != nil; kid = next() {
+			// TODO(rsc): Can also be TagEnumerationType
+			// but haven't seen that in the wild yet.
+			switch kid.Tag {
+			case TagSubrangeType:
+				max, ok := kid.Val(AttrUpperBound).(int64)
+				if !ok {
+					max = -2 // Count == -1, as in x[].
+				}
+				if ndim == 0 {
+					t.Count = max + 1
+				} else {
+					// Multidimensional array.
+					// Create new array type underneath this one.
+					t.Type = &ArrayType{Type: t.Type, Count: max + 1}
+				}
+				ndim++
+			case TagEnumerationType:
+				err = DecodeError{name, kid.Offset, "cannot handle enumeration type as array bound"}
+				goto Error
+			}
+		}
+		if ndim == 0 {
+			// LLVM generates this for x[].
+			t.Count = -1
+		}
+
+	case TagBaseType:
+		// Basic type.  (DWARF v2 §5.1)
+		// Attributes:
+		//	AttrName: name of base type in programming language of the compilation unit [required]
+		//	AttrEncoding: encoding value for type (encFloat etc) [required]
+		//	AttrByteSize: size of type in bytes [required]
+		//	AttrBitOffset: for sub-byte types, size in bits
+		//	AttrBitSize: for sub-byte types, bit offset of high order bit in the AttrByteSize bytes
+		name, _ := e.Val(AttrName).(string)
+		enc, ok := e.Val(AttrEncoding).(int64)
+		if !ok {
+			err = DecodeError{name, e.Offset, "missing encoding attribute for " + name}
+			goto Error
+		}
+		switch enc {
+		default:
+			err = DecodeError{name, e.Offset, "unrecognized encoding attribute value"}
+			goto Error
+
+		case encAddress:
+			typ = new(AddrType)
+		case encBoolean:
+			typ = new(BoolType)
+		case encComplexFloat:
+			typ = new(ComplexType)
+		case encFloat:
+			typ = new(FloatType)
+		case encSigned:
+			typ = new(IntType)
+		case encUnsigned:
+			typ = new(UintType)
+		case encSignedChar:
+			typ = new(CharType)
+		case encUnsignedChar:
+			typ = new(UcharType)
+		}
+		typeCache[off] = typ
+		t := typ.(interface {
+			Basic() *BasicType
+		}).Basic()
+		t.Name = name
+		t.BitSize, _ = e.Val(AttrBitSize).(int64)
+		t.BitOffset, _ = e.Val(AttrBitOffset).(int64)
+
+	case TagClassType, TagStructType, TagUnionType:
+		// Structure, union, or class type.  (DWARF v2 §5.5)
+		// Attributes:
+		//	AttrName: name of struct, union, or class
+		//	AttrByteSize: byte size [required]
+		//	AttrDeclaration: if true, struct/union/class is incomplete
+		// Children:
+		//	TagMember to describe one member.
+		//		AttrName: name of member [required]
+		//		AttrType: type of member [required]
+		//		AttrByteSize: size in bytes
+		//		AttrBitOffset: bit offset within bytes for bit fields
+		//		AttrBitSize: bit size for bit fields
+		//		AttrDataMemberLoc: location within struct [required for struct, class]
+		// There is much more to handle C++, all ignored for now.
+		t := new(StructType)
+		typ = t
+		typeCache[off] = t
+		switch e.Tag {
+		case TagClassType:
+			t.Kind = "class"
+		case TagStructType:
+			t.Kind = "struct"
+		case TagUnionType:
+			t.Kind = "union"
+		}
+		t.StructName, _ = e.Val(AttrName).(string)
+		t.Incomplete = e.Val(AttrDeclaration) != nil
+		t.Field = make([]*StructField, 0, 8)
+		var lastFieldType Type
+		var lastFieldBitOffset int64
+		for kid := next(); kid != nil; kid = next() {
+			if kid.Tag == TagMember {
+				f := new(StructField)
+				if f.Type = typeOf(kid); err != nil {
+					goto Error
+				}
+				switch loc := kid.Val(AttrDataMemberLoc).(type) {
+				case []byte:
+					// TODO: Should have original compilation
+					// unit here, not unknownFormat.
+					b := makeBuf(d, unknownFormat{}, "location", 0, loc)
+					if b.uint8() != opPlusUconst {
+						err = DecodeError{name, kid.Offset, "unexpected opcode"}
+						goto Error
+					}
+					f.ByteOffset = int64(b.uint())
+					if b.err != nil {
+						err = b.err
+						goto Error
+					}
+				case int64:
+					f.ByteOffset = loc
+				}
+
+				haveBitOffset := false
+				f.Name, _ = kid.Val(AttrName).(string)
+				f.ByteSize, _ = kid.Val(AttrByteSize).(int64)
+				f.BitOffset, haveBitOffset = kid.Val(AttrBitOffset).(int64)
+				f.BitSize, _ = kid.Val(AttrBitSize).(int64)
+				t.Field = append(t.Field, f)
+
+				bito := f.BitOffset
+				if !haveBitOffset {
+					bito = f.ByteOffset * 8
+				}
+				if bito == lastFieldBitOffset && t.Kind != "union" {
+					// Last field was zero width.  Fix array length.
+					// (DWARF writes out 0-length arrays as if they were 1-length arrays.)
+					zeroArray(lastFieldType)
+				}
+				lastFieldType = f.Type
+				lastFieldBitOffset = bito
+			}
+		}
+		if t.Kind != "union" {
+			b, ok := e.Val(AttrByteSize).(int64)
+			if ok && b*8 == lastFieldBitOffset {
+				// Final field must be zero width.  Fix array length.
+				zeroArray(lastFieldType)
+			}
+		}
+
+	case TagConstType, TagVolatileType, TagRestrictType:
+		// Type modifier (DWARF v2 §5.2)
+		// Attributes:
+		//	AttrType: subtype
+		t := new(QualType)
+		typ = t
+		typeCache[off] = t
+		if t.Type = typeOf(e); err != nil {
+			goto Error
+		}
+		switch e.Tag {
+		case TagConstType:
+			t.Qual = "const"
+		case TagRestrictType:
+			t.Qual = "restrict"
+		case TagVolatileType:
+			t.Qual = "volatile"
+		}
+
+	case TagEnumerationType:
+		// Enumeration type (DWARF v2 §5.6)
+		// Attributes:
+		//	AttrName: enum name if any
+		//	AttrByteSize: bytes required to represent largest value
+		// Children:
+		//	TagEnumerator:
+		//		AttrName: name of constant
+		//		AttrConstValue: value of constant
+		t := new(EnumType)
+		typ = t
+		typeCache[off] = t
+		t.EnumName, _ = e.Val(AttrName).(string)
+		t.Val = make([]*EnumValue, 0, 8)
+		for kid := next(); kid != nil; kid = next() {
+			if kid.Tag == TagEnumerator {
+				f := new(EnumValue)
+				f.Name, _ = kid.Val(AttrName).(string)
+				f.Val, _ = kid.Val(AttrConstValue).(int64)
+				n := len(t.Val)
+				if n >= cap(t.Val) {
+					val := make([]*EnumValue, n, n*2)
+					copy(val, t.Val)
+					t.Val = val
+				}
+				t.Val = t.Val[0 : n+1]
+				t.Val[n] = f
+			}
+		}
+
+	case TagPointerType:
+		// Type modifier (DWARF v2 §5.2)
+		// Attributes:
+		//	AttrType: subtype [not required!  void* has no AttrType]
+		//	AttrAddrClass: address class [ignored]
+		t := new(PtrType)
+		typ = t
+		typeCache[off] = t
+		if e.Val(AttrType) == nil {
+			t.Type = &VoidType{}
+			break
+		}
+		t.Type = typeOf(e)
+
+	case TagSubroutineType:
+		// Subroutine type.  (DWARF v2 §5.7)
+		// Attributes:
+		//	AttrType: type of return value if any
+		//	AttrName: possible name of type [ignored]
+		//	AttrPrototyped: whether used ANSI C prototype [ignored]
+		// Children:
+		//	TagFormalParameter: typed parameter
+		//		AttrType: type of parameter
+		//	TagUnspecifiedParameter: final ...
+		t := new(FuncType)
+		typ = t
+		typeCache[off] = t
+		if t.ReturnType = typeOf(e); err != nil {
+			goto Error
+		}
+		t.ParamType = make([]Type, 0, 8)
+		for kid := next(); kid != nil; kid = next() {
+			var tkid Type
+			switch kid.Tag {
+			default:
+				continue
+			case TagFormalParameter:
+				if tkid = typeOf(kid); err != nil {
+					goto Error
+				}
+			case TagUnspecifiedParameters:
+				tkid = &DotDotDotType{}
+			}
+			t.ParamType = append(t.ParamType, tkid)
+		}
+
+	case TagTypedef:
+		// Typedef (DWARF v2 §5.3)
+		// Attributes:
+		//	AttrName: name [required]
+		//	AttrType: type definition [required]
+		t := new(TypedefType)
+		typ = t
+		typeCache[off] = t
+		t.Name, _ = e.Val(AttrName).(string)
+		t.Type = typeOf(e)
+	}
+
+	if err != nil {
+		goto Error
+	}
+
+	{
+		b, ok := e.Val(AttrByteSize).(int64)
+		if !ok {
+			b = -1
+		}
+		typ.Common().ByteSize = b
+	}
+	return typ, nil
+
+Error:
+	// If the parse fails, take the type out of the cache
+	// so that the next call with this offset doesn't hit
+	// the cache and return success.
+	delete(typeCache, off)
+	return nil, err
+}
+
+func zeroArray(t Type) {
+	for {
+		at, ok := t.(*ArrayType)
+		if !ok {
+			break
+		}
+		at.Count = 0
+		t = at.Type
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/type_test.go b/third_party/gofrontend/libgo/go/debug/dwarf/type_test.go
new file mode 100644
index 0000000..2cb85e7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/type_test.go
@@ -0,0 +1,122 @@
+// 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 dwarf_test
+
+import (
+	. "debug/dwarf"
+	"debug/elf"
+	"debug/macho"
+	"testing"
+)
+
+var typedefTests = map[string]string{
+	"t_ptr_volatile_int":                    "*volatile int",
+	"t_ptr_const_char":                      "*const char",
+	"t_long":                                "long int",
+	"t_ushort":                              "short unsigned int",
+	"t_func_int_of_float_double":            "func(float, double) int",
+	"t_ptr_func_int_of_float_double":        "*func(float, double) int",
+	"t_ptr_func_int_of_float_complex":       "*func(complex float) int",
+	"t_ptr_func_int_of_double_complex":      "*func(complex double) int",
+	"t_ptr_func_int_of_long_double_complex": "*func(complex long double) int",
+	"t_func_ptr_int_of_char_schar_uchar":    "func(char, signed char, unsigned char) *int",
+	"t_func_void_of_char":                   "func(char) void",
+	"t_func_void_of_void":                   "func() void",
+	"t_func_void_of_ptr_char_dots":          "func(*char, ...) void",
+	"t_my_struct":                           "struct my_struct {vi volatile int@0; x char@4 : 1@7; y int@4 : 4@27; z [0]int@8; array [40]long long int@8; zz [0]int@328}",
+	"t_my_struct1":                          "struct my_struct1 {zz [1]int@0}",
+	"t_my_union":                            "union my_union {vi volatile int@0; x char@0 : 1@7; y int@0 : 4@28; array [40]long long int@0}",
+	"t_my_enum":                             "enum my_enum {e1=1; e2=2; e3=-5; e4=1000000000000000}",
+	"t_my_list":                             "struct list {val short int@0; next *t_my_list@8}",
+	"t_my_tree":                             "struct tree {left *struct tree@0; right *struct tree@8; val long long unsigned int@16}",
+}
+
+// As Apple converts gcc to a clang-based front end
+// they keep breaking the DWARF output.  This map lists the
+// conversion from real answer to Apple answer.
+var machoBug = map[string]string{
+	"func(*char, ...) void":                                 "func(*char) void",
+	"enum my_enum {e1=1; e2=2; e3=-5; e4=1000000000000000}": "enum my_enum {e1=1; e2=2; e3=-5; e4=-1530494976}",
+}
+
+func elfData(t *testing.T, name string) *Data {
+	f, err := elf.Open(name)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	d, err := f.DWARF()
+	if err != nil {
+		t.Fatal(err)
+	}
+	return d
+}
+
+func machoData(t *testing.T, name string) *Data {
+	f, err := macho.Open(name)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	d, err := f.DWARF()
+	if err != nil {
+		t.Fatal(err)
+	}
+	return d
+}
+
+func TestTypedefsELF(t *testing.T) { testTypedefs(t, elfData(t, "testdata/typedef.elf"), "elf") }
+
+func TestTypedefsMachO(t *testing.T) {
+	testTypedefs(t, machoData(t, "testdata/typedef.macho"), "macho")
+}
+
+func TestTypedefsELFDwarf4(t *testing.T) { testTypedefs(t, elfData(t, "testdata/typedef.elf4"), "elf") }
+
+func testTypedefs(t *testing.T, d *Data, kind string) {
+	r := d.Reader()
+	seen := make(map[string]bool)
+	for {
+		e, err := r.Next()
+		if err != nil {
+			t.Fatal("r.Next:", err)
+		}
+		if e == nil {
+			break
+		}
+		if e.Tag == TagTypedef {
+			typ, err := d.Type(e.Offset)
+			if err != nil {
+				t.Fatal("d.Type:", err)
+			}
+			t1 := typ.(*TypedefType)
+			var typstr string
+			if ts, ok := t1.Type.(*StructType); ok {
+				typstr = ts.Defn()
+			} else {
+				typstr = t1.Type.String()
+			}
+
+			if want, ok := typedefTests[t1.Name]; ok {
+				if seen[t1.Name] {
+					t.Errorf("multiple definitions for %s", t1.Name)
+				}
+				seen[t1.Name] = true
+				if typstr != want && (kind != "macho" || typstr != machoBug[want]) {
+					t.Errorf("%s:\n\thave %s\n\twant %s", t1.Name, typstr, want)
+				}
+			}
+		}
+		if e.Tag != TagCompileUnit {
+			r.SkipChildren()
+		}
+	}
+
+	for k := range typedefTests {
+		if !seen[k] {
+			t.Errorf("missing %s", k)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/typeunit.go b/third_party/gofrontend/libgo/go/debug/dwarf/typeunit.go
new file mode 100644
index 0000000..3fd1c99
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/typeunit.go
@@ -0,0 +1,166 @@
+// 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 dwarf
+
+import (
+	"fmt"
+	"strconv"
+)
+
+// Parse the type units stored in a DWARF4 .debug_types section.  Each
+// type unit defines a single primary type and an 8-byte signature.
+// Other sections may then use formRefSig8 to refer to the type.
+
+// The typeUnit format is a single type with a signature.  It holds
+// the same data as a compilation unit.
+type typeUnit struct {
+	unit
+	toff  Offset // Offset to signature type within data.
+	name  string // Name of .debug_type section.
+	cache Type   // Cache the type, nil to start.
+}
+
+// Parse a .debug_types section.
+func (d *Data) parseTypes(name string, types []byte) error {
+	b := makeBuf(d, unknownFormat{}, name, 0, types)
+	for len(b.data) > 0 {
+		base := b.off
+		dwarf64 := false
+		n := b.uint32()
+		if n == 0xffffffff {
+			n64 := b.uint64()
+			if n64 != uint64(uint32(n64)) {
+				b.error("type unit length overflow")
+				return b.err
+			}
+			n = uint32(n64)
+			dwarf64 = true
+		}
+		hdroff := b.off
+		vers := b.uint16()
+		if vers != 4 {
+			b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
+			return b.err
+		}
+		var ao uint32
+		if !dwarf64 {
+			ao = b.uint32()
+		} else {
+			ao64 := b.uint64()
+			if ao64 != uint64(uint32(ao64)) {
+				b.error("type unit abbrev offset overflow")
+				return b.err
+			}
+			ao = uint32(ao64)
+		}
+		atable, err := d.parseAbbrev(ao)
+		if err != nil {
+			return err
+		}
+		asize := b.uint8()
+		sig := b.uint64()
+
+		var toff uint32
+		if !dwarf64 {
+			toff = b.uint32()
+		} else {
+			to64 := b.uint64()
+			if to64 != uint64(uint32(to64)) {
+				b.error("type unit type offset overflow")
+				return b.err
+			}
+			toff = uint32(to64)
+		}
+
+		boff := b.off
+		d.typeSigs[sig] = &typeUnit{
+			unit: unit{
+				base:   base,
+				off:    boff,
+				data:   b.bytes(int(Offset(n) - (b.off - hdroff))),
+				atable: atable,
+				asize:  int(asize),
+				vers:   int(vers),
+				is64:   dwarf64,
+			},
+			toff: Offset(toff),
+			name: name,
+		}
+		if b.err != nil {
+			return b.err
+		}
+	}
+	return nil
+}
+
+// Return the type for a type signature.
+func (d *Data) sigToType(sig uint64) (Type, error) {
+	tu := d.typeSigs[sig]
+	if tu == nil {
+		return nil, fmt.Errorf("no type unit with signature %v", sig)
+	}
+	if tu.cache != nil {
+		return tu.cache, nil
+	}
+
+	b := makeBuf(d, tu, tu.name, tu.off, tu.data)
+	r := &typeUnitReader{d: d, tu: tu, b: b}
+	t, err := d.readType(tu.name, r, Offset(tu.toff), make(map[Offset]Type))
+	if err != nil {
+		return nil, err
+	}
+
+	tu.cache = t
+	return t, nil
+}
+
+// typeUnitReader is a typeReader for a tagTypeUnit.
+type typeUnitReader struct {
+	d   *Data
+	tu  *typeUnit
+	b   buf
+	err error
+}
+
+// Seek to a new position in the type unit.
+func (tur *typeUnitReader) Seek(off Offset) {
+	tur.err = nil
+	doff := off - tur.tu.off
+	if doff < 0 || doff >= Offset(len(tur.tu.data)) {
+		tur.err = fmt.Errorf("%s: offset %d out of range; max %d", tur.tu.name, doff, len(tur.tu.data))
+		return
+	}
+	tur.b = makeBuf(tur.d, tur.tu, tur.tu.name, off, tur.tu.data[doff:])
+}
+
+// Next reads the next Entry from the type unit.
+func (tur *typeUnitReader) Next() (*Entry, error) {
+	if tur.err != nil {
+		return nil, tur.err
+	}
+	if len(tur.tu.data) == 0 {
+		return nil, nil
+	}
+	e := tur.b.entry(tur.tu.atable, tur.tu.base)
+	if tur.b.err != nil {
+		tur.err = tur.b.err
+		return nil, tur.err
+	}
+	return e, nil
+}
+
+// clone returns a new reader for the type unit.
+func (tur *typeUnitReader) clone() typeReader {
+	return &typeUnitReader{
+		d:  tur.d,
+		tu: tur.tu,
+		b:  makeBuf(tur.d, tur.tu, tur.tu.name, tur.tu.off, tur.tu.data),
+	}
+}
+
+// offset returns the current offset.
+func (tur *typeUnitReader) offset() Offset {
+	return tur.b.off
+}
diff --git a/third_party/gofrontend/libgo/go/debug/dwarf/unit.go b/third_party/gofrontend/libgo/go/debug/dwarf/unit.go
new file mode 100644
index 0000000..be60935
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/dwarf/unit.go
@@ -0,0 +1,100 @@
+// 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 dwarf
+
+import "strconv"
+
+// DWARF debug info is split into a sequence of compilation units.
+// Each unit has its own abbreviation table and address size.
+
+type unit struct {
+	base    Offset // byte offset of header within the aggregate info
+	off     Offset // byte offset of data within the aggregate info
+	lineoff Offset // byte offset of data within the line info
+	data    []byte
+	atable  abbrevTable
+	asize   int
+	vers    int
+	is64    bool // True for 64-bit DWARF format
+	dir     string
+	pc      []addrRange   // PC ranges in this compilation unit
+	lines   []mapLineInfo // PC -> line mapping
+}
+
+// Implement the dataFormat interface.
+
+func (u *unit) version() int {
+	return u.vers
+}
+
+func (u *unit) dwarf64() (bool, bool) {
+	return u.is64, true
+}
+
+func (u *unit) addrsize() int {
+	return u.asize
+}
+
+// A range is an address range.
+type addrRange struct {
+	low  uint64
+	high uint64
+}
+
+func (d *Data) parseUnits() ([]unit, error) {
+	// Count units.
+	nunit := 0
+	b := makeBuf(d, unknownFormat{}, "info", 0, d.info)
+	for len(b.data) > 0 {
+		len := b.uint32()
+		if len == 0xffffffff {
+			len64 := b.uint64()
+			if len64 != uint64(uint32(len64)) {
+				b.error("unit length overflow")
+				break
+			}
+			len = uint32(len64)
+		}
+		b.skip(int(len))
+		nunit++
+	}
+	if b.err != nil {
+		return nil, b.err
+	}
+
+	// Again, this time writing them down.
+	b = makeBuf(d, unknownFormat{}, "info", 0, d.info)
+	units := make([]unit, nunit)
+	for i := range units {
+		u := &units[i]
+		u.base = b.off
+		n := b.uint32()
+		if n == 0xffffffff {
+			u.is64 = true
+			n = uint32(b.uint64())
+		}
+		vers := b.uint16()
+		if vers != 2 && vers != 3 && vers != 4 {
+			b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
+			break
+		}
+		u.vers = int(vers)
+		atable, err := d.parseAbbrev(b.uint32())
+		if err != nil {
+			if b.err == nil {
+				b.err = err
+			}
+			break
+		}
+		u.atable = atable
+		u.asize = int(b.uint8())
+		u.off = b.off
+		u.data = b.bytes(int(n - (2 + 4 + 1)))
+	}
+	if b.err != nil {
+		return nil, b.err
+	}
+	return units, nil
+}
diff --git a/third_party/gofrontend/libgo/go/debug/elf/elf.go b/third_party/gofrontend/libgo/go/debug/elf/elf.go
new file mode 100644
index 0000000..a7986a5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/elf.go
@@ -0,0 +1,1765 @@
+/*
+ * ELF constants and data structures
+ *
+ * Derived from:
+ * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $
+ * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $
+ * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $
+ * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $
+ * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $
+ * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $
+ * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $
+ * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $
+ *
+ * Copyright (c) 1996-1998 John D. Polstra.  All rights reserved.
+ * Copyright (c) 2001 David E. O'Brien
+ * Portions Copyright 2009 The Go Authors.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+package elf
+
+import "strconv"
+
+/*
+ * Constants
+ */
+
+// Indexes into the Header.Ident array.
+const (
+	EI_CLASS      = 4  /* Class of machine. */
+	EI_DATA       = 5  /* Data format. */
+	EI_VERSION    = 6  /* ELF format version. */
+	EI_OSABI      = 7  /* Operating system / ABI identification */
+	EI_ABIVERSION = 8  /* ABI version */
+	EI_PAD        = 9  /* Start of padding (per SVR4 ABI). */
+	EI_NIDENT     = 16 /* Size of e_ident array. */
+)
+
+// Initial magic number for ELF files.
+const ELFMAG = "\177ELF"
+
+// Version is found in Header.Ident[EI_VERSION] and Header.Version.
+type Version byte
+
+const (
+	EV_NONE    Version = 0
+	EV_CURRENT Version = 1
+)
+
+var versionStrings = []intName{
+	{0, "EV_NONE"},
+	{1, "EV_CURRENT"},
+}
+
+func (i Version) String() string   { return stringName(uint32(i), versionStrings, false) }
+func (i Version) GoString() string { return stringName(uint32(i), versionStrings, true) }
+
+// Class is found in Header.Ident[EI_CLASS] and Header.Class.
+type Class byte
+
+const (
+	ELFCLASSNONE Class = 0 /* Unknown class. */
+	ELFCLASS32   Class = 1 /* 32-bit architecture. */
+	ELFCLASS64   Class = 2 /* 64-bit architecture. */
+)
+
+var classStrings = []intName{
+	{0, "ELFCLASSNONE"},
+	{1, "ELFCLASS32"},
+	{2, "ELFCLASS64"},
+}
+
+func (i Class) String() string   { return stringName(uint32(i), classStrings, false) }
+func (i Class) GoString() string { return stringName(uint32(i), classStrings, true) }
+
+// Data is found in Header.Ident[EI_DATA] and Header.Data.
+type Data byte
+
+const (
+	ELFDATANONE Data = 0 /* Unknown data format. */
+	ELFDATA2LSB Data = 1 /* 2's complement little-endian. */
+	ELFDATA2MSB Data = 2 /* 2's complement big-endian. */
+)
+
+var dataStrings = []intName{
+	{0, "ELFDATANONE"},
+	{1, "ELFDATA2LSB"},
+	{2, "ELFDATA2MSB"},
+}
+
+func (i Data) String() string   { return stringName(uint32(i), dataStrings, false) }
+func (i Data) GoString() string { return stringName(uint32(i), dataStrings, true) }
+
+// OSABI is found in Header.Ident[EI_OSABI] and Header.OSABI.
+type OSABI byte
+
+const (
+	ELFOSABI_NONE       OSABI = 0   /* UNIX System V ABI */
+	ELFOSABI_HPUX       OSABI = 1   /* HP-UX operating system */
+	ELFOSABI_NETBSD     OSABI = 2   /* NetBSD */
+	ELFOSABI_LINUX      OSABI = 3   /* GNU/Linux */
+	ELFOSABI_HURD       OSABI = 4   /* GNU/Hurd */
+	ELFOSABI_86OPEN     OSABI = 5   /* 86Open common IA32 ABI */
+	ELFOSABI_SOLARIS    OSABI = 6   /* Solaris */
+	ELFOSABI_AIX        OSABI = 7   /* AIX */
+	ELFOSABI_IRIX       OSABI = 8   /* IRIX */
+	ELFOSABI_FREEBSD    OSABI = 9   /* FreeBSD */
+	ELFOSABI_TRU64      OSABI = 10  /* TRU64 UNIX */
+	ELFOSABI_MODESTO    OSABI = 11  /* Novell Modesto */
+	ELFOSABI_OPENBSD    OSABI = 12  /* OpenBSD */
+	ELFOSABI_OPENVMS    OSABI = 13  /* Open VMS */
+	ELFOSABI_NSK        OSABI = 14  /* HP Non-Stop Kernel */
+	ELFOSABI_ARM        OSABI = 97  /* ARM */
+	ELFOSABI_STANDALONE OSABI = 255 /* Standalone (embedded) application */
+)
+
+var osabiStrings = []intName{
+	{0, "ELFOSABI_NONE"},
+	{1, "ELFOSABI_HPUX"},
+	{2, "ELFOSABI_NETBSD"},
+	{3, "ELFOSABI_LINUX"},
+	{4, "ELFOSABI_HURD"},
+	{5, "ELFOSABI_86OPEN"},
+	{6, "ELFOSABI_SOLARIS"},
+	{7, "ELFOSABI_AIX"},
+	{8, "ELFOSABI_IRIX"},
+	{9, "ELFOSABI_FREEBSD"},
+	{10, "ELFOSABI_TRU64"},
+	{11, "ELFOSABI_MODESTO"},
+	{12, "ELFOSABI_OPENBSD"},
+	{13, "ELFOSABI_OPENVMS"},
+	{14, "ELFOSABI_NSK"},
+	{97, "ELFOSABI_ARM"},
+	{255, "ELFOSABI_STANDALONE"},
+}
+
+func (i OSABI) String() string   { return stringName(uint32(i), osabiStrings, false) }
+func (i OSABI) GoString() string { return stringName(uint32(i), osabiStrings, true) }
+
+// Type is found in Header.Type.
+type Type uint16
+
+const (
+	ET_NONE   Type = 0      /* Unknown type. */
+	ET_REL    Type = 1      /* Relocatable. */
+	ET_EXEC   Type = 2      /* Executable. */
+	ET_DYN    Type = 3      /* Shared object. */
+	ET_CORE   Type = 4      /* Core file. */
+	ET_LOOS   Type = 0xfe00 /* First operating system specific. */
+	ET_HIOS   Type = 0xfeff /* Last operating system-specific. */
+	ET_LOPROC Type = 0xff00 /* First processor-specific. */
+	ET_HIPROC Type = 0xffff /* Last processor-specific. */
+)
+
+var typeStrings = []intName{
+	{0, "ET_NONE"},
+	{1, "ET_REL"},
+	{2, "ET_EXEC"},
+	{3, "ET_DYN"},
+	{4, "ET_CORE"},
+	{0xfe00, "ET_LOOS"},
+	{0xfeff, "ET_HIOS"},
+	{0xff00, "ET_LOPROC"},
+	{0xffff, "ET_HIPROC"},
+}
+
+func (i Type) String() string   { return stringName(uint32(i), typeStrings, false) }
+func (i Type) GoString() string { return stringName(uint32(i), typeStrings, true) }
+
+// Machine is found in Header.Machine.
+type Machine uint16
+
+const (
+	EM_NONE        Machine = 0  /* Unknown machine. */
+	EM_M32         Machine = 1  /* AT&T WE32100. */
+	EM_SPARC       Machine = 2  /* Sun SPARC. */
+	EM_386         Machine = 3  /* Intel i386. */
+	EM_68K         Machine = 4  /* Motorola 68000. */
+	EM_88K         Machine = 5  /* Motorola 88000. */
+	EM_860         Machine = 7  /* Intel i860. */
+	EM_MIPS        Machine = 8  /* MIPS R3000 Big-Endian only. */
+	EM_S370        Machine = 9  /* IBM System/370. */
+	EM_MIPS_RS3_LE Machine = 10 /* MIPS R3000 Little-Endian. */
+	EM_PARISC      Machine = 15 /* HP PA-RISC. */
+	EM_VPP500      Machine = 17 /* Fujitsu VPP500. */
+	EM_SPARC32PLUS Machine = 18 /* SPARC v8plus. */
+	EM_960         Machine = 19 /* Intel 80960. */
+	EM_PPC         Machine = 20 /* PowerPC 32-bit. */
+	EM_PPC64       Machine = 21 /* PowerPC 64-bit. */
+	EM_S390        Machine = 22 /* IBM System/390. */
+	EM_V800        Machine = 36 /* NEC V800. */
+	EM_FR20        Machine = 37 /* Fujitsu FR20. */
+	EM_RH32        Machine = 38 /* TRW RH-32. */
+	EM_RCE         Machine = 39 /* Motorola RCE. */
+	EM_ARM         Machine = 40 /* ARM. */
+	EM_SH          Machine = 42 /* Hitachi SH. */
+	EM_SPARCV9     Machine = 43 /* SPARC v9 64-bit. */
+	EM_TRICORE     Machine = 44 /* Siemens TriCore embedded processor. */
+	EM_ARC         Machine = 45 /* Argonaut RISC Core. */
+	EM_H8_300      Machine = 46 /* Hitachi H8/300. */
+	EM_H8_300H     Machine = 47 /* Hitachi H8/300H. */
+	EM_H8S         Machine = 48 /* Hitachi H8S. */
+	EM_H8_500      Machine = 49 /* Hitachi H8/500. */
+	EM_IA_64       Machine = 50 /* Intel IA-64 Processor. */
+	EM_MIPS_X      Machine = 51 /* Stanford MIPS-X. */
+	EM_COLDFIRE    Machine = 52 /* Motorola ColdFire. */
+	EM_68HC12      Machine = 53 /* Motorola M68HC12. */
+	EM_MMA         Machine = 54 /* Fujitsu MMA. */
+	EM_PCP         Machine = 55 /* Siemens PCP. */
+	EM_NCPU        Machine = 56 /* Sony nCPU. */
+	EM_NDR1        Machine = 57 /* Denso NDR1 microprocessor. */
+	EM_STARCORE    Machine = 58 /* Motorola Star*Core processor. */
+	EM_ME16        Machine = 59 /* Toyota ME16 processor. */
+	EM_ST100       Machine = 60 /* STMicroelectronics ST100 processor. */
+	EM_TINYJ       Machine = 61 /* Advanced Logic Corp. TinyJ processor. */
+	EM_X86_64      Machine = 62 /* Advanced Micro Devices x86-64 */
+
+	/* Non-standard or deprecated. */
+	EM_486         Machine = 6      /* Intel i486. */
+	EM_MIPS_RS4_BE Machine = 10     /* MIPS R4000 Big-Endian */
+	EM_ALPHA_STD   Machine = 41     /* Digital Alpha (standard value). */
+	EM_ALPHA       Machine = 0x9026 /* Alpha (written in the absence of an ABI) */
+)
+
+var machineStrings = []intName{
+	{0, "EM_NONE"},
+	{1, "EM_M32"},
+	{2, "EM_SPARC"},
+	{3, "EM_386"},
+	{4, "EM_68K"},
+	{5, "EM_88K"},
+	{7, "EM_860"},
+	{8, "EM_MIPS"},
+	{9, "EM_S370"},
+	{10, "EM_MIPS_RS3_LE"},
+	{15, "EM_PARISC"},
+	{17, "EM_VPP500"},
+	{18, "EM_SPARC32PLUS"},
+	{19, "EM_960"},
+	{20, "EM_PPC"},
+	{21, "EM_PPC64"},
+	{22, "EM_S390"},
+	{36, "EM_V800"},
+	{37, "EM_FR20"},
+	{38, "EM_RH32"},
+	{39, "EM_RCE"},
+	{40, "EM_ARM"},
+	{42, "EM_SH"},
+	{43, "EM_SPARCV9"},
+	{44, "EM_TRICORE"},
+	{45, "EM_ARC"},
+	{46, "EM_H8_300"},
+	{47, "EM_H8_300H"},
+	{48, "EM_H8S"},
+	{49, "EM_H8_500"},
+	{50, "EM_IA_64"},
+	{51, "EM_MIPS_X"},
+	{52, "EM_COLDFIRE"},
+	{53, "EM_68HC12"},
+	{54, "EM_MMA"},
+	{55, "EM_PCP"},
+	{56, "EM_NCPU"},
+	{57, "EM_NDR1"},
+	{58, "EM_STARCORE"},
+	{59, "EM_ME16"},
+	{60, "EM_ST100"},
+	{61, "EM_TINYJ"},
+	{62, "EM_X86_64"},
+
+	/* Non-standard or deprecated. */
+	{6, "EM_486"},
+	{10, "EM_MIPS_RS4_BE"},
+	{41, "EM_ALPHA_STD"},
+	{0x9026, "EM_ALPHA"},
+}
+
+func (i Machine) String() string   { return stringName(uint32(i), machineStrings, false) }
+func (i Machine) GoString() string { return stringName(uint32(i), machineStrings, true) }
+
+// Special section indices.
+type SectionIndex int
+
+const (
+	SHN_UNDEF     SectionIndex = 0      /* Undefined, missing, irrelevant. */
+	SHN_LORESERVE SectionIndex = 0xff00 /* First of reserved range. */
+	SHN_LOPROC    SectionIndex = 0xff00 /* First processor-specific. */
+	SHN_HIPROC    SectionIndex = 0xff1f /* Last processor-specific. */
+	SHN_LOOS      SectionIndex = 0xff20 /* First operating system-specific. */
+	SHN_HIOS      SectionIndex = 0xff3f /* Last operating system-specific. */
+	SHN_ABS       SectionIndex = 0xfff1 /* Absolute values. */
+	SHN_COMMON    SectionIndex = 0xfff2 /* Common data. */
+	SHN_XINDEX    SectionIndex = 0xffff /* Escape -- index stored elsewhere. */
+	SHN_HIRESERVE SectionIndex = 0xffff /* Last of reserved range. */
+)
+
+var shnStrings = []intName{
+	{0, "SHN_UNDEF"},
+	{0xff00, "SHN_LOPROC"},
+	{0xff20, "SHN_LOOS"},
+	{0xfff1, "SHN_ABS"},
+	{0xfff2, "SHN_COMMON"},
+	{0xffff, "SHN_XINDEX"},
+}
+
+func (i SectionIndex) String() string   { return stringName(uint32(i), shnStrings, false) }
+func (i SectionIndex) GoString() string { return stringName(uint32(i), shnStrings, true) }
+
+// Section type.
+type SectionType uint32
+
+const (
+	SHT_NULL           SectionType = 0          /* inactive */
+	SHT_PROGBITS       SectionType = 1          /* program defined information */
+	SHT_SYMTAB         SectionType = 2          /* symbol table section */
+	SHT_STRTAB         SectionType = 3          /* string table section */
+	SHT_RELA           SectionType = 4          /* relocation section with addends */
+	SHT_HASH           SectionType = 5          /* symbol hash table section */
+	SHT_DYNAMIC        SectionType = 6          /* dynamic section */
+	SHT_NOTE           SectionType = 7          /* note section */
+	SHT_NOBITS         SectionType = 8          /* no space section */
+	SHT_REL            SectionType = 9          /* relocation section - no addends */
+	SHT_SHLIB          SectionType = 10         /* reserved - purpose unknown */
+	SHT_DYNSYM         SectionType = 11         /* dynamic symbol table section */
+	SHT_INIT_ARRAY     SectionType = 14         /* Initialization function pointers. */
+	SHT_FINI_ARRAY     SectionType = 15         /* Termination function pointers. */
+	SHT_PREINIT_ARRAY  SectionType = 16         /* Pre-initialization function ptrs. */
+	SHT_GROUP          SectionType = 17         /* Section group. */
+	SHT_SYMTAB_SHNDX   SectionType = 18         /* Section indexes (see SHN_XINDEX). */
+	SHT_LOOS           SectionType = 0x60000000 /* First of OS specific semantics */
+	SHT_GNU_ATTRIBUTES SectionType = 0x6ffffff5 /* GNU object attributes */
+	SHT_GNU_HASH       SectionType = 0x6ffffff6 /* GNU hash table */
+	SHT_GNU_LIBLIST    SectionType = 0x6ffffff7 /* GNU prelink library list */
+	SHT_GNU_VERDEF     SectionType = 0x6ffffffd /* GNU version definition section */
+	SHT_GNU_VERNEED    SectionType = 0x6ffffffe /* GNU version needs section */
+	SHT_GNU_VERSYM     SectionType = 0x6fffffff /* GNU version symbol table */
+	SHT_HIOS           SectionType = 0x6fffffff /* Last of OS specific semantics */
+	SHT_LOPROC         SectionType = 0x70000000 /* reserved range for processor */
+	SHT_HIPROC         SectionType = 0x7fffffff /* specific section header types */
+	SHT_LOUSER         SectionType = 0x80000000 /* reserved range for application */
+	SHT_HIUSER         SectionType = 0xffffffff /* specific indexes */
+)
+
+var shtStrings = []intName{
+	{0, "SHT_NULL"},
+	{1, "SHT_PROGBITS"},
+	{2, "SHT_SYMTAB"},
+	{3, "SHT_STRTAB"},
+	{4, "SHT_RELA"},
+	{5, "SHT_HASH"},
+	{6, "SHT_DYNAMIC"},
+	{7, "SHT_NOTE"},
+	{8, "SHT_NOBITS"},
+	{9, "SHT_REL"},
+	{10, "SHT_SHLIB"},
+	{11, "SHT_DYNSYM"},
+	{14, "SHT_INIT_ARRAY"},
+	{15, "SHT_FINI_ARRAY"},
+	{16, "SHT_PREINIT_ARRAY"},
+	{17, "SHT_GROUP"},
+	{18, "SHT_SYMTAB_SHNDX"},
+	{0x60000000, "SHT_LOOS"},
+	{0x6ffffff5, "SHT_GNU_ATTRIBUTES"},
+	{0x6ffffff6, "SHT_GNU_HASH"},
+	{0x6ffffff7, "SHT_GNU_LIBLIST"},
+	{0x6ffffffd, "SHT_GNU_VERDEF"},
+	{0x6ffffffe, "SHT_GNU_VERNEED"},
+	{0x6fffffff, "SHT_GNU_VERSYM"},
+	{0x70000000, "SHT_LOPROC"},
+	{0x7fffffff, "SHT_HIPROC"},
+	{0x80000000, "SHT_LOUSER"},
+	{0xffffffff, "SHT_HIUSER"},
+}
+
+func (i SectionType) String() string   { return stringName(uint32(i), shtStrings, false) }
+func (i SectionType) GoString() string { return stringName(uint32(i), shtStrings, true) }
+
+// Section flags.
+type SectionFlag uint32
+
+const (
+	SHF_WRITE            SectionFlag = 0x1        /* Section contains writable data. */
+	SHF_ALLOC            SectionFlag = 0x2        /* Section occupies memory. */
+	SHF_EXECINSTR        SectionFlag = 0x4        /* Section contains instructions. */
+	SHF_MERGE            SectionFlag = 0x10       /* Section may be merged. */
+	SHF_STRINGS          SectionFlag = 0x20       /* Section contains strings. */
+	SHF_INFO_LINK        SectionFlag = 0x40       /* sh_info holds section index. */
+	SHF_LINK_ORDER       SectionFlag = 0x80       /* Special ordering requirements. */
+	SHF_OS_NONCONFORMING SectionFlag = 0x100      /* OS-specific processing required. */
+	SHF_GROUP            SectionFlag = 0x200      /* Member of section group. */
+	SHF_TLS              SectionFlag = 0x400      /* Section contains TLS data. */
+	SHF_MASKOS           SectionFlag = 0x0ff00000 /* OS-specific semantics. */
+	SHF_MASKPROC         SectionFlag = 0xf0000000 /* Processor-specific semantics. */
+)
+
+var shfStrings = []intName{
+	{0x1, "SHF_WRITE"},
+	{0x2, "SHF_ALLOC"},
+	{0x4, "SHF_EXECINSTR"},
+	{0x10, "SHF_MERGE"},
+	{0x20, "SHF_STRINGS"},
+	{0x40, "SHF_INFO_LINK"},
+	{0x80, "SHF_LINK_ORDER"},
+	{0x100, "SHF_OS_NONCONFORMING"},
+	{0x200, "SHF_GROUP"},
+	{0x400, "SHF_TLS"},
+}
+
+func (i SectionFlag) String() string   { return flagName(uint32(i), shfStrings, false) }
+func (i SectionFlag) GoString() string { return flagName(uint32(i), shfStrings, true) }
+
+// Prog.Type
+type ProgType int
+
+const (
+	PT_NULL    ProgType = 0          /* Unused entry. */
+	PT_LOAD    ProgType = 1          /* Loadable segment. */
+	PT_DYNAMIC ProgType = 2          /* Dynamic linking information segment. */
+	PT_INTERP  ProgType = 3          /* Pathname of interpreter. */
+	PT_NOTE    ProgType = 4          /* Auxiliary information. */
+	PT_SHLIB   ProgType = 5          /* Reserved (not used). */
+	PT_PHDR    ProgType = 6          /* Location of program header itself. */
+	PT_TLS     ProgType = 7          /* Thread local storage segment */
+	PT_LOOS    ProgType = 0x60000000 /* First OS-specific. */
+	PT_HIOS    ProgType = 0x6fffffff /* Last OS-specific. */
+	PT_LOPROC  ProgType = 0x70000000 /* First processor-specific type. */
+	PT_HIPROC  ProgType = 0x7fffffff /* Last processor-specific type. */
+)
+
+var ptStrings = []intName{
+	{0, "PT_NULL"},
+	{1, "PT_LOAD"},
+	{2, "PT_DYNAMIC"},
+	{3, "PT_INTERP"},
+	{4, "PT_NOTE"},
+	{5, "PT_SHLIB"},
+	{6, "PT_PHDR"},
+	{7, "PT_TLS"},
+	{0x60000000, "PT_LOOS"},
+	{0x6fffffff, "PT_HIOS"},
+	{0x70000000, "PT_LOPROC"},
+	{0x7fffffff, "PT_HIPROC"},
+}
+
+func (i ProgType) String() string   { return stringName(uint32(i), ptStrings, false) }
+func (i ProgType) GoString() string { return stringName(uint32(i), ptStrings, true) }
+
+// Prog.Flag
+type ProgFlag uint32
+
+const (
+	PF_X        ProgFlag = 0x1        /* Executable. */
+	PF_W        ProgFlag = 0x2        /* Writable. */
+	PF_R        ProgFlag = 0x4        /* Readable. */
+	PF_MASKOS   ProgFlag = 0x0ff00000 /* Operating system-specific. */
+	PF_MASKPROC ProgFlag = 0xf0000000 /* Processor-specific. */
+)
+
+var pfStrings = []intName{
+	{0x1, "PF_X"},
+	{0x2, "PF_W"},
+	{0x4, "PF_R"},
+}
+
+func (i ProgFlag) String() string   { return flagName(uint32(i), pfStrings, false) }
+func (i ProgFlag) GoString() string { return flagName(uint32(i), pfStrings, true) }
+
+// Dyn.Tag
+type DynTag int
+
+const (
+	DT_NULL         DynTag = 0  /* Terminating entry. */
+	DT_NEEDED       DynTag = 1  /* String table offset of a needed shared library. */
+	DT_PLTRELSZ     DynTag = 2  /* Total size in bytes of PLT relocations. */
+	DT_PLTGOT       DynTag = 3  /* Processor-dependent address. */
+	DT_HASH         DynTag = 4  /* Address of symbol hash table. */
+	DT_STRTAB       DynTag = 5  /* Address of string table. */
+	DT_SYMTAB       DynTag = 6  /* Address of symbol table. */
+	DT_RELA         DynTag = 7  /* Address of ElfNN_Rela relocations. */
+	DT_RELASZ       DynTag = 8  /* Total size of ElfNN_Rela relocations. */
+	DT_RELAENT      DynTag = 9  /* Size of each ElfNN_Rela relocation entry. */
+	DT_STRSZ        DynTag = 10 /* Size of string table. */
+	DT_SYMENT       DynTag = 11 /* Size of each symbol table entry. */
+	DT_INIT         DynTag = 12 /* Address of initialization function. */
+	DT_FINI         DynTag = 13 /* Address of finalization function. */
+	DT_SONAME       DynTag = 14 /* String table offset of shared object name. */
+	DT_RPATH        DynTag = 15 /* String table offset of library path. [sup] */
+	DT_SYMBOLIC     DynTag = 16 /* Indicates "symbolic" linking. [sup] */
+	DT_REL          DynTag = 17 /* Address of ElfNN_Rel relocations. */
+	DT_RELSZ        DynTag = 18 /* Total size of ElfNN_Rel relocations. */
+	DT_RELENT       DynTag = 19 /* Size of each ElfNN_Rel relocation. */
+	DT_PLTREL       DynTag = 20 /* Type of relocation used for PLT. */
+	DT_DEBUG        DynTag = 21 /* Reserved (not used). */
+	DT_TEXTREL      DynTag = 22 /* Indicates there may be relocations in non-writable segments. [sup] */
+	DT_JMPREL       DynTag = 23 /* Address of PLT relocations. */
+	DT_BIND_NOW     DynTag = 24 /* [sup] */
+	DT_INIT_ARRAY   DynTag = 25 /* Address of the array of pointers to initialization functions */
+	DT_FINI_ARRAY   DynTag = 26 /* Address of the array of pointers to termination functions */
+	DT_INIT_ARRAYSZ DynTag = 27 /* Size in bytes of the array of initialization functions. */
+	DT_FINI_ARRAYSZ DynTag = 28 /* Size in bytes of the array of termination functions. */
+	DT_RUNPATH      DynTag = 29 /* String table offset of a null-terminated library search path string. */
+	DT_FLAGS        DynTag = 30 /* Object specific flag values. */
+	DT_ENCODING     DynTag = 32 /* Values greater than or equal to DT_ENCODING
+	   and less than DT_LOOS follow the rules for
+	   the interpretation of the d_un union
+	   as follows: even == 'd_ptr', even == 'd_val'
+	   or none */
+	DT_PREINIT_ARRAY   DynTag = 32         /* Address of the array of pointers to pre-initialization functions. */
+	DT_PREINIT_ARRAYSZ DynTag = 33         /* Size in bytes of the array of pre-initialization functions. */
+	DT_LOOS            DynTag = 0x6000000d /* First OS-specific */
+	DT_HIOS            DynTag = 0x6ffff000 /* Last OS-specific */
+	DT_VERSYM          DynTag = 0x6ffffff0
+	DT_VERNEED         DynTag = 0x6ffffffe
+	DT_VERNEEDNUM      DynTag = 0x6fffffff
+	DT_LOPROC          DynTag = 0x70000000 /* First processor-specific type. */
+	DT_HIPROC          DynTag = 0x7fffffff /* Last processor-specific type. */
+)
+
+var dtStrings = []intName{
+	{0, "DT_NULL"},
+	{1, "DT_NEEDED"},
+	{2, "DT_PLTRELSZ"},
+	{3, "DT_PLTGOT"},
+	{4, "DT_HASH"},
+	{5, "DT_STRTAB"},
+	{6, "DT_SYMTAB"},
+	{7, "DT_RELA"},
+	{8, "DT_RELASZ"},
+	{9, "DT_RELAENT"},
+	{10, "DT_STRSZ"},
+	{11, "DT_SYMENT"},
+	{12, "DT_INIT"},
+	{13, "DT_FINI"},
+	{14, "DT_SONAME"},
+	{15, "DT_RPATH"},
+	{16, "DT_SYMBOLIC"},
+	{17, "DT_REL"},
+	{18, "DT_RELSZ"},
+	{19, "DT_RELENT"},
+	{20, "DT_PLTREL"},
+	{21, "DT_DEBUG"},
+	{22, "DT_TEXTREL"},
+	{23, "DT_JMPREL"},
+	{24, "DT_BIND_NOW"},
+	{25, "DT_INIT_ARRAY"},
+	{26, "DT_FINI_ARRAY"},
+	{27, "DT_INIT_ARRAYSZ"},
+	{28, "DT_FINI_ARRAYSZ"},
+	{29, "DT_RUNPATH"},
+	{30, "DT_FLAGS"},
+	{32, "DT_ENCODING"},
+	{32, "DT_PREINIT_ARRAY"},
+	{33, "DT_PREINIT_ARRAYSZ"},
+	{0x6000000d, "DT_LOOS"},
+	{0x6ffff000, "DT_HIOS"},
+	{0x6ffffff0, "DT_VERSYM"},
+	{0x6ffffffe, "DT_VERNEED"},
+	{0x6fffffff, "DT_VERNEEDNUM"},
+	{0x70000000, "DT_LOPROC"},
+	{0x7fffffff, "DT_HIPROC"},
+}
+
+func (i DynTag) String() string   { return stringName(uint32(i), dtStrings, false) }
+func (i DynTag) GoString() string { return stringName(uint32(i), dtStrings, true) }
+
+// DT_FLAGS values.
+type DynFlag int
+
+const (
+	DF_ORIGIN DynFlag = 0x0001 /* Indicates that the object being loaded may
+	   make reference to the
+	   $ORIGIN substitution string */
+	DF_SYMBOLIC DynFlag = 0x0002 /* Indicates "symbolic" linking. */
+	DF_TEXTREL  DynFlag = 0x0004 /* Indicates there may be relocations in non-writable segments. */
+	DF_BIND_NOW DynFlag = 0x0008 /* Indicates that the dynamic linker should
+	   process all relocations for the object
+	   containing this entry before transferring
+	   control to the program. */
+	DF_STATIC_TLS DynFlag = 0x0010 /* Indicates that the shared object or
+	   executable contains code using a static
+	   thread-local storage scheme. */
+)
+
+var dflagStrings = []intName{
+	{0x0001, "DF_ORIGIN"},
+	{0x0002, "DF_SYMBOLIC"},
+	{0x0004, "DF_TEXTREL"},
+	{0x0008, "DF_BIND_NOW"},
+	{0x0010, "DF_STATIC_TLS"},
+}
+
+func (i DynFlag) String() string   { return flagName(uint32(i), dflagStrings, false) }
+func (i DynFlag) GoString() string { return flagName(uint32(i), dflagStrings, true) }
+
+// NType values; used in core files.
+type NType int
+
+const (
+	NT_PRSTATUS NType = 1 /* Process status. */
+	NT_FPREGSET NType = 2 /* Floating point registers. */
+	NT_PRPSINFO NType = 3 /* Process state info. */
+)
+
+var ntypeStrings = []intName{
+	{1, "NT_PRSTATUS"},
+	{2, "NT_FPREGSET"},
+	{3, "NT_PRPSINFO"},
+}
+
+func (i NType) String() string   { return stringName(uint32(i), ntypeStrings, false) }
+func (i NType) GoString() string { return stringName(uint32(i), ntypeStrings, true) }
+
+/* Symbol Binding - ELFNN_ST_BIND - st_info */
+type SymBind int
+
+const (
+	STB_LOCAL  SymBind = 0  /* Local symbol */
+	STB_GLOBAL SymBind = 1  /* Global symbol */
+	STB_WEAK   SymBind = 2  /* like global - lower precedence */
+	STB_LOOS   SymBind = 10 /* Reserved range for operating system */
+	STB_HIOS   SymBind = 12 /*   specific semantics. */
+	STB_LOPROC SymBind = 13 /* reserved range for processor */
+	STB_HIPROC SymBind = 15 /*   specific semantics. */
+)
+
+var stbStrings = []intName{
+	{0, "STB_LOCAL"},
+	{1, "STB_GLOBAL"},
+	{2, "STB_WEAK"},
+	{10, "STB_LOOS"},
+	{12, "STB_HIOS"},
+	{13, "STB_LOPROC"},
+	{15, "STB_HIPROC"},
+}
+
+func (i SymBind) String() string   { return stringName(uint32(i), stbStrings, false) }
+func (i SymBind) GoString() string { return stringName(uint32(i), stbStrings, true) }
+
+/* Symbol type - ELFNN_ST_TYPE - st_info */
+type SymType int
+
+const (
+	STT_NOTYPE  SymType = 0  /* Unspecified type. */
+	STT_OBJECT  SymType = 1  /* Data object. */
+	STT_FUNC    SymType = 2  /* Function. */
+	STT_SECTION SymType = 3  /* Section. */
+	STT_FILE    SymType = 4  /* Source file. */
+	STT_COMMON  SymType = 5  /* Uninitialized common block. */
+	STT_TLS     SymType = 6  /* TLS object. */
+	STT_LOOS    SymType = 10 /* Reserved range for operating system */
+	STT_HIOS    SymType = 12 /*   specific semantics. */
+	STT_LOPROC  SymType = 13 /* reserved range for processor */
+	STT_HIPROC  SymType = 15 /*   specific semantics. */
+)
+
+var sttStrings = []intName{
+	{0, "STT_NOTYPE"},
+	{1, "STT_OBJECT"},
+	{2, "STT_FUNC"},
+	{3, "STT_SECTION"},
+	{4, "STT_FILE"},
+	{5, "STT_COMMON"},
+	{6, "STT_TLS"},
+	{10, "STT_LOOS"},
+	{12, "STT_HIOS"},
+	{13, "STT_LOPROC"},
+	{15, "STT_HIPROC"},
+}
+
+func (i SymType) String() string   { return stringName(uint32(i), sttStrings, false) }
+func (i SymType) GoString() string { return stringName(uint32(i), sttStrings, true) }
+
+/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */
+type SymVis int
+
+const (
+	STV_DEFAULT   SymVis = 0x0 /* Default visibility (see binding). */
+	STV_INTERNAL  SymVis = 0x1 /* Special meaning in relocatable objects. */
+	STV_HIDDEN    SymVis = 0x2 /* Not visible. */
+	STV_PROTECTED SymVis = 0x3 /* Visible but not preemptible. */
+)
+
+var stvStrings = []intName{
+	{0x0, "STV_DEFAULT"},
+	{0x1, "STV_INTERNAL"},
+	{0x2, "STV_HIDDEN"},
+	{0x3, "STV_PROTECTED"},
+}
+
+func (i SymVis) String() string   { return stringName(uint32(i), stvStrings, false) }
+func (i SymVis) GoString() string { return stringName(uint32(i), stvStrings, true) }
+
+/*
+ * Relocation types.
+ */
+
+// Relocation types for x86-64.
+type R_X86_64 int
+
+const (
+	R_X86_64_NONE     R_X86_64 = 0  /* No relocation. */
+	R_X86_64_64       R_X86_64 = 1  /* Add 64 bit symbol value. */
+	R_X86_64_PC32     R_X86_64 = 2  /* PC-relative 32 bit signed sym value. */
+	R_X86_64_GOT32    R_X86_64 = 3  /* PC-relative 32 bit GOT offset. */
+	R_X86_64_PLT32    R_X86_64 = 4  /* PC-relative 32 bit PLT offset. */
+	R_X86_64_COPY     R_X86_64 = 5  /* Copy data from shared object. */
+	R_X86_64_GLOB_DAT R_X86_64 = 6  /* Set GOT entry to data address. */
+	R_X86_64_JMP_SLOT R_X86_64 = 7  /* Set GOT entry to code address. */
+	R_X86_64_RELATIVE R_X86_64 = 8  /* Add load address of shared object. */
+	R_X86_64_GOTPCREL R_X86_64 = 9  /* Add 32 bit signed pcrel offset to GOT. */
+	R_X86_64_32       R_X86_64 = 10 /* Add 32 bit zero extended symbol value */
+	R_X86_64_32S      R_X86_64 = 11 /* Add 32 bit sign extended symbol value */
+	R_X86_64_16       R_X86_64 = 12 /* Add 16 bit zero extended symbol value */
+	R_X86_64_PC16     R_X86_64 = 13 /* Add 16 bit signed extended pc relative symbol value */
+	R_X86_64_8        R_X86_64 = 14 /* Add 8 bit zero extended symbol value */
+	R_X86_64_PC8      R_X86_64 = 15 /* Add 8 bit signed extended pc relative symbol value */
+	R_X86_64_DTPMOD64 R_X86_64 = 16 /* ID of module containing symbol */
+	R_X86_64_DTPOFF64 R_X86_64 = 17 /* Offset in TLS block */
+	R_X86_64_TPOFF64  R_X86_64 = 18 /* Offset in static TLS block */
+	R_X86_64_TLSGD    R_X86_64 = 19 /* PC relative offset to GD GOT entry */
+	R_X86_64_TLSLD    R_X86_64 = 20 /* PC relative offset to LD GOT entry */
+	R_X86_64_DTPOFF32 R_X86_64 = 21 /* Offset in TLS block */
+	R_X86_64_GOTTPOFF R_X86_64 = 22 /* PC relative offset to IE GOT entry */
+	R_X86_64_TPOFF32  R_X86_64 = 23 /* Offset in static TLS block */
+)
+
+var rx86_64Strings = []intName{
+	{0, "R_X86_64_NONE"},
+	{1, "R_X86_64_64"},
+	{2, "R_X86_64_PC32"},
+	{3, "R_X86_64_GOT32"},
+	{4, "R_X86_64_PLT32"},
+	{5, "R_X86_64_COPY"},
+	{6, "R_X86_64_GLOB_DAT"},
+	{7, "R_X86_64_JMP_SLOT"},
+	{8, "R_X86_64_RELATIVE"},
+	{9, "R_X86_64_GOTPCREL"},
+	{10, "R_X86_64_32"},
+	{11, "R_X86_64_32S"},
+	{12, "R_X86_64_16"},
+	{13, "R_X86_64_PC16"},
+	{14, "R_X86_64_8"},
+	{15, "R_X86_64_PC8"},
+	{16, "R_X86_64_DTPMOD64"},
+	{17, "R_X86_64_DTPOFF64"},
+	{18, "R_X86_64_TPOFF64"},
+	{19, "R_X86_64_TLSGD"},
+	{20, "R_X86_64_TLSLD"},
+	{21, "R_X86_64_DTPOFF32"},
+	{22, "R_X86_64_GOTTPOFF"},
+	{23, "R_X86_64_TPOFF32"},
+}
+
+func (i R_X86_64) String() string   { return stringName(uint32(i), rx86_64Strings, false) }
+func (i R_X86_64) GoString() string { return stringName(uint32(i), rx86_64Strings, true) }
+
+// Relocation types for Alpha.
+type R_ALPHA int
+
+const (
+	R_ALPHA_NONE           R_ALPHA = 0  /* No reloc */
+	R_ALPHA_REFLONG        R_ALPHA = 1  /* Direct 32 bit */
+	R_ALPHA_REFQUAD        R_ALPHA = 2  /* Direct 64 bit */
+	R_ALPHA_GPREL32        R_ALPHA = 3  /* GP relative 32 bit */
+	R_ALPHA_LITERAL        R_ALPHA = 4  /* GP relative 16 bit w/optimization */
+	R_ALPHA_LITUSE         R_ALPHA = 5  /* Optimization hint for LITERAL */
+	R_ALPHA_GPDISP         R_ALPHA = 6  /* Add displacement to GP */
+	R_ALPHA_BRADDR         R_ALPHA = 7  /* PC+4 relative 23 bit shifted */
+	R_ALPHA_HINT           R_ALPHA = 8  /* PC+4 relative 16 bit shifted */
+	R_ALPHA_SREL16         R_ALPHA = 9  /* PC relative 16 bit */
+	R_ALPHA_SREL32         R_ALPHA = 10 /* PC relative 32 bit */
+	R_ALPHA_SREL64         R_ALPHA = 11 /* PC relative 64 bit */
+	R_ALPHA_OP_PUSH        R_ALPHA = 12 /* OP stack push */
+	R_ALPHA_OP_STORE       R_ALPHA = 13 /* OP stack pop and store */
+	R_ALPHA_OP_PSUB        R_ALPHA = 14 /* OP stack subtract */
+	R_ALPHA_OP_PRSHIFT     R_ALPHA = 15 /* OP stack right shift */
+	R_ALPHA_GPVALUE        R_ALPHA = 16
+	R_ALPHA_GPRELHIGH      R_ALPHA = 17
+	R_ALPHA_GPRELLOW       R_ALPHA = 18
+	R_ALPHA_IMMED_GP_16    R_ALPHA = 19
+	R_ALPHA_IMMED_GP_HI32  R_ALPHA = 20
+	R_ALPHA_IMMED_SCN_HI32 R_ALPHA = 21
+	R_ALPHA_IMMED_BR_HI32  R_ALPHA = 22
+	R_ALPHA_IMMED_LO32     R_ALPHA = 23
+	R_ALPHA_COPY           R_ALPHA = 24 /* Copy symbol at runtime */
+	R_ALPHA_GLOB_DAT       R_ALPHA = 25 /* Create GOT entry */
+	R_ALPHA_JMP_SLOT       R_ALPHA = 26 /* Create PLT entry */
+	R_ALPHA_RELATIVE       R_ALPHA = 27 /* Adjust by program base */
+)
+
+var ralphaStrings = []intName{
+	{0, "R_ALPHA_NONE"},
+	{1, "R_ALPHA_REFLONG"},
+	{2, "R_ALPHA_REFQUAD"},
+	{3, "R_ALPHA_GPREL32"},
+	{4, "R_ALPHA_LITERAL"},
+	{5, "R_ALPHA_LITUSE"},
+	{6, "R_ALPHA_GPDISP"},
+	{7, "R_ALPHA_BRADDR"},
+	{8, "R_ALPHA_HINT"},
+	{9, "R_ALPHA_SREL16"},
+	{10, "R_ALPHA_SREL32"},
+	{11, "R_ALPHA_SREL64"},
+	{12, "R_ALPHA_OP_PUSH"},
+	{13, "R_ALPHA_OP_STORE"},
+	{14, "R_ALPHA_OP_PSUB"},
+	{15, "R_ALPHA_OP_PRSHIFT"},
+	{16, "R_ALPHA_GPVALUE"},
+	{17, "R_ALPHA_GPRELHIGH"},
+	{18, "R_ALPHA_GPRELLOW"},
+	{19, "R_ALPHA_IMMED_GP_16"},
+	{20, "R_ALPHA_IMMED_GP_HI32"},
+	{21, "R_ALPHA_IMMED_SCN_HI32"},
+	{22, "R_ALPHA_IMMED_BR_HI32"},
+	{23, "R_ALPHA_IMMED_LO32"},
+	{24, "R_ALPHA_COPY"},
+	{25, "R_ALPHA_GLOB_DAT"},
+	{26, "R_ALPHA_JMP_SLOT"},
+	{27, "R_ALPHA_RELATIVE"},
+}
+
+func (i R_ALPHA) String() string   { return stringName(uint32(i), ralphaStrings, false) }
+func (i R_ALPHA) GoString() string { return stringName(uint32(i), ralphaStrings, true) }
+
+// Relocation types for ARM.
+type R_ARM int
+
+const (
+	R_ARM_NONE          R_ARM = 0 /* No relocation. */
+	R_ARM_PC24          R_ARM = 1
+	R_ARM_ABS32         R_ARM = 2
+	R_ARM_REL32         R_ARM = 3
+	R_ARM_PC13          R_ARM = 4
+	R_ARM_ABS16         R_ARM = 5
+	R_ARM_ABS12         R_ARM = 6
+	R_ARM_THM_ABS5      R_ARM = 7
+	R_ARM_ABS8          R_ARM = 8
+	R_ARM_SBREL32       R_ARM = 9
+	R_ARM_THM_PC22      R_ARM = 10
+	R_ARM_THM_PC8       R_ARM = 11
+	R_ARM_AMP_VCALL9    R_ARM = 12
+	R_ARM_SWI24         R_ARM = 13
+	R_ARM_THM_SWI8      R_ARM = 14
+	R_ARM_XPC25         R_ARM = 15
+	R_ARM_THM_XPC22     R_ARM = 16
+	R_ARM_COPY          R_ARM = 20 /* Copy data from shared object. */
+	R_ARM_GLOB_DAT      R_ARM = 21 /* Set GOT entry to data address. */
+	R_ARM_JUMP_SLOT     R_ARM = 22 /* Set GOT entry to code address. */
+	R_ARM_RELATIVE      R_ARM = 23 /* Add load address of shared object. */
+	R_ARM_GOTOFF        R_ARM = 24 /* Add GOT-relative symbol address. */
+	R_ARM_GOTPC         R_ARM = 25 /* Add PC-relative GOT table address. */
+	R_ARM_GOT32         R_ARM = 26 /* Add PC-relative GOT offset. */
+	R_ARM_PLT32         R_ARM = 27 /* Add PC-relative PLT offset. */
+	R_ARM_GNU_VTENTRY   R_ARM = 100
+	R_ARM_GNU_VTINHERIT R_ARM = 101
+	R_ARM_RSBREL32      R_ARM = 250
+	R_ARM_THM_RPC22     R_ARM = 251
+	R_ARM_RREL32        R_ARM = 252
+	R_ARM_RABS32        R_ARM = 253
+	R_ARM_RPC24         R_ARM = 254
+	R_ARM_RBASE         R_ARM = 255
+)
+
+var rarmStrings = []intName{
+	{0, "R_ARM_NONE"},
+	{1, "R_ARM_PC24"},
+	{2, "R_ARM_ABS32"},
+	{3, "R_ARM_REL32"},
+	{4, "R_ARM_PC13"},
+	{5, "R_ARM_ABS16"},
+	{6, "R_ARM_ABS12"},
+	{7, "R_ARM_THM_ABS5"},
+	{8, "R_ARM_ABS8"},
+	{9, "R_ARM_SBREL32"},
+	{10, "R_ARM_THM_PC22"},
+	{11, "R_ARM_THM_PC8"},
+	{12, "R_ARM_AMP_VCALL9"},
+	{13, "R_ARM_SWI24"},
+	{14, "R_ARM_THM_SWI8"},
+	{15, "R_ARM_XPC25"},
+	{16, "R_ARM_THM_XPC22"},
+	{20, "R_ARM_COPY"},
+	{21, "R_ARM_GLOB_DAT"},
+	{22, "R_ARM_JUMP_SLOT"},
+	{23, "R_ARM_RELATIVE"},
+	{24, "R_ARM_GOTOFF"},
+	{25, "R_ARM_GOTPC"},
+	{26, "R_ARM_GOT32"},
+	{27, "R_ARM_PLT32"},
+	{100, "R_ARM_GNU_VTENTRY"},
+	{101, "R_ARM_GNU_VTINHERIT"},
+	{250, "R_ARM_RSBREL32"},
+	{251, "R_ARM_THM_RPC22"},
+	{252, "R_ARM_RREL32"},
+	{253, "R_ARM_RABS32"},
+	{254, "R_ARM_RPC24"},
+	{255, "R_ARM_RBASE"},
+}
+
+func (i R_ARM) String() string   { return stringName(uint32(i), rarmStrings, false) }
+func (i R_ARM) GoString() string { return stringName(uint32(i), rarmStrings, true) }
+
+// Relocation types for 386.
+type R_386 int
+
+const (
+	R_386_NONE         R_386 = 0  /* No relocation. */
+	R_386_32           R_386 = 1  /* Add symbol value. */
+	R_386_PC32         R_386 = 2  /* Add PC-relative symbol value. */
+	R_386_GOT32        R_386 = 3  /* Add PC-relative GOT offset. */
+	R_386_PLT32        R_386 = 4  /* Add PC-relative PLT offset. */
+	R_386_COPY         R_386 = 5  /* Copy data from shared object. */
+	R_386_GLOB_DAT     R_386 = 6  /* Set GOT entry to data address. */
+	R_386_JMP_SLOT     R_386 = 7  /* Set GOT entry to code address. */
+	R_386_RELATIVE     R_386 = 8  /* Add load address of shared object. */
+	R_386_GOTOFF       R_386 = 9  /* Add GOT-relative symbol address. */
+	R_386_GOTPC        R_386 = 10 /* Add PC-relative GOT table address. */
+	R_386_TLS_TPOFF    R_386 = 14 /* Negative offset in static TLS block */
+	R_386_TLS_IE       R_386 = 15 /* Absolute address of GOT for -ve static TLS */
+	R_386_TLS_GOTIE    R_386 = 16 /* GOT entry for negative static TLS block */
+	R_386_TLS_LE       R_386 = 17 /* Negative offset relative to static TLS */
+	R_386_TLS_GD       R_386 = 18 /* 32 bit offset to GOT (index,off) pair */
+	R_386_TLS_LDM      R_386 = 19 /* 32 bit offset to GOT (index,zero) pair */
+	R_386_TLS_GD_32    R_386 = 24 /* 32 bit offset to GOT (index,off) pair */
+	R_386_TLS_GD_PUSH  R_386 = 25 /* pushl instruction for Sun ABI GD sequence */
+	R_386_TLS_GD_CALL  R_386 = 26 /* call instruction for Sun ABI GD sequence */
+	R_386_TLS_GD_POP   R_386 = 27 /* popl instruction for Sun ABI GD sequence */
+	R_386_TLS_LDM_32   R_386 = 28 /* 32 bit offset to GOT (index,zero) pair */
+	R_386_TLS_LDM_PUSH R_386 = 29 /* pushl instruction for Sun ABI LD sequence */
+	R_386_TLS_LDM_CALL R_386 = 30 /* call instruction for Sun ABI LD sequence */
+	R_386_TLS_LDM_POP  R_386 = 31 /* popl instruction for Sun ABI LD sequence */
+	R_386_TLS_LDO_32   R_386 = 32 /* 32 bit offset from start of TLS block */
+	R_386_TLS_IE_32    R_386 = 33 /* 32 bit offset to GOT static TLS offset entry */
+	R_386_TLS_LE_32    R_386 = 34 /* 32 bit offset within static TLS block */
+	R_386_TLS_DTPMOD32 R_386 = 35 /* GOT entry containing TLS index */
+	R_386_TLS_DTPOFF32 R_386 = 36 /* GOT entry containing TLS offset */
+	R_386_TLS_TPOFF32  R_386 = 37 /* GOT entry of -ve static TLS offset */
+)
+
+var r386Strings = []intName{
+	{0, "R_386_NONE"},
+	{1, "R_386_32"},
+	{2, "R_386_PC32"},
+	{3, "R_386_GOT32"},
+	{4, "R_386_PLT32"},
+	{5, "R_386_COPY"},
+	{6, "R_386_GLOB_DAT"},
+	{7, "R_386_JMP_SLOT"},
+	{8, "R_386_RELATIVE"},
+	{9, "R_386_GOTOFF"},
+	{10, "R_386_GOTPC"},
+	{14, "R_386_TLS_TPOFF"},
+	{15, "R_386_TLS_IE"},
+	{16, "R_386_TLS_GOTIE"},
+	{17, "R_386_TLS_LE"},
+	{18, "R_386_TLS_GD"},
+	{19, "R_386_TLS_LDM"},
+	{24, "R_386_TLS_GD_32"},
+	{25, "R_386_TLS_GD_PUSH"},
+	{26, "R_386_TLS_GD_CALL"},
+	{27, "R_386_TLS_GD_POP"},
+	{28, "R_386_TLS_LDM_32"},
+	{29, "R_386_TLS_LDM_PUSH"},
+	{30, "R_386_TLS_LDM_CALL"},
+	{31, "R_386_TLS_LDM_POP"},
+	{32, "R_386_TLS_LDO_32"},
+	{33, "R_386_TLS_IE_32"},
+	{34, "R_386_TLS_LE_32"},
+	{35, "R_386_TLS_DTPMOD32"},
+	{36, "R_386_TLS_DTPOFF32"},
+	{37, "R_386_TLS_TPOFF32"},
+}
+
+func (i R_386) String() string   { return stringName(uint32(i), r386Strings, false) }
+func (i R_386) GoString() string { return stringName(uint32(i), r386Strings, true) }
+
+// Relocation types for PowerPC.
+type R_PPC int
+
+const (
+	R_PPC_NONE            R_PPC = 0 /* No relocation. */
+	R_PPC_ADDR32          R_PPC = 1
+	R_PPC_ADDR24          R_PPC = 2
+	R_PPC_ADDR16          R_PPC = 3
+	R_PPC_ADDR16_LO       R_PPC = 4
+	R_PPC_ADDR16_HI       R_PPC = 5
+	R_PPC_ADDR16_HA       R_PPC = 6
+	R_PPC_ADDR14          R_PPC = 7
+	R_PPC_ADDR14_BRTAKEN  R_PPC = 8
+	R_PPC_ADDR14_BRNTAKEN R_PPC = 9
+	R_PPC_REL24           R_PPC = 10
+	R_PPC_REL14           R_PPC = 11
+	R_PPC_REL14_BRTAKEN   R_PPC = 12
+	R_PPC_REL14_BRNTAKEN  R_PPC = 13
+	R_PPC_GOT16           R_PPC = 14
+	R_PPC_GOT16_LO        R_PPC = 15
+	R_PPC_GOT16_HI        R_PPC = 16
+	R_PPC_GOT16_HA        R_PPC = 17
+	R_PPC_PLTREL24        R_PPC = 18
+	R_PPC_COPY            R_PPC = 19
+	R_PPC_GLOB_DAT        R_PPC = 20
+	R_PPC_JMP_SLOT        R_PPC = 21
+	R_PPC_RELATIVE        R_PPC = 22
+	R_PPC_LOCAL24PC       R_PPC = 23
+	R_PPC_UADDR32         R_PPC = 24
+	R_PPC_UADDR16         R_PPC = 25
+	R_PPC_REL32           R_PPC = 26
+	R_PPC_PLT32           R_PPC = 27
+	R_PPC_PLTREL32        R_PPC = 28
+	R_PPC_PLT16_LO        R_PPC = 29
+	R_PPC_PLT16_HI        R_PPC = 30
+	R_PPC_PLT16_HA        R_PPC = 31
+	R_PPC_SDAREL16        R_PPC = 32
+	R_PPC_SECTOFF         R_PPC = 33
+	R_PPC_SECTOFF_LO      R_PPC = 34
+	R_PPC_SECTOFF_HI      R_PPC = 35
+	R_PPC_SECTOFF_HA      R_PPC = 36
+	R_PPC_TLS             R_PPC = 67
+	R_PPC_DTPMOD32        R_PPC = 68
+	R_PPC_TPREL16         R_PPC = 69
+	R_PPC_TPREL16_LO      R_PPC = 70
+	R_PPC_TPREL16_HI      R_PPC = 71
+	R_PPC_TPREL16_HA      R_PPC = 72
+	R_PPC_TPREL32         R_PPC = 73
+	R_PPC_DTPREL16        R_PPC = 74
+	R_PPC_DTPREL16_LO     R_PPC = 75
+	R_PPC_DTPREL16_HI     R_PPC = 76
+	R_PPC_DTPREL16_HA     R_PPC = 77
+	R_PPC_DTPREL32        R_PPC = 78
+	R_PPC_GOT_TLSGD16     R_PPC = 79
+	R_PPC_GOT_TLSGD16_LO  R_PPC = 80
+	R_PPC_GOT_TLSGD16_HI  R_PPC = 81
+	R_PPC_GOT_TLSGD16_HA  R_PPC = 82
+	R_PPC_GOT_TLSLD16     R_PPC = 83
+	R_PPC_GOT_TLSLD16_LO  R_PPC = 84
+	R_PPC_GOT_TLSLD16_HI  R_PPC = 85
+	R_PPC_GOT_TLSLD16_HA  R_PPC = 86
+	R_PPC_GOT_TPREL16     R_PPC = 87
+	R_PPC_GOT_TPREL16_LO  R_PPC = 88
+	R_PPC_GOT_TPREL16_HI  R_PPC = 89
+	R_PPC_GOT_TPREL16_HA  R_PPC = 90
+	R_PPC_EMB_NADDR32     R_PPC = 101
+	R_PPC_EMB_NADDR16     R_PPC = 102
+	R_PPC_EMB_NADDR16_LO  R_PPC = 103
+	R_PPC_EMB_NADDR16_HI  R_PPC = 104
+	R_PPC_EMB_NADDR16_HA  R_PPC = 105
+	R_PPC_EMB_SDAI16      R_PPC = 106
+	R_PPC_EMB_SDA2I16     R_PPC = 107
+	R_PPC_EMB_SDA2REL     R_PPC = 108
+	R_PPC_EMB_SDA21       R_PPC = 109
+	R_PPC_EMB_MRKREF      R_PPC = 110
+	R_PPC_EMB_RELSEC16    R_PPC = 111
+	R_PPC_EMB_RELST_LO    R_PPC = 112
+	R_PPC_EMB_RELST_HI    R_PPC = 113
+	R_PPC_EMB_RELST_HA    R_PPC = 114
+	R_PPC_EMB_BIT_FLD     R_PPC = 115
+	R_PPC_EMB_RELSDA      R_PPC = 116
+)
+
+var rppcStrings = []intName{
+	{0, "R_PPC_NONE"},
+	{1, "R_PPC_ADDR32"},
+	{2, "R_PPC_ADDR24"},
+	{3, "R_PPC_ADDR16"},
+	{4, "R_PPC_ADDR16_LO"},
+	{5, "R_PPC_ADDR16_HI"},
+	{6, "R_PPC_ADDR16_HA"},
+	{7, "R_PPC_ADDR14"},
+	{8, "R_PPC_ADDR14_BRTAKEN"},
+	{9, "R_PPC_ADDR14_BRNTAKEN"},
+	{10, "R_PPC_REL24"},
+	{11, "R_PPC_REL14"},
+	{12, "R_PPC_REL14_BRTAKEN"},
+	{13, "R_PPC_REL14_BRNTAKEN"},
+	{14, "R_PPC_GOT16"},
+	{15, "R_PPC_GOT16_LO"},
+	{16, "R_PPC_GOT16_HI"},
+	{17, "R_PPC_GOT16_HA"},
+	{18, "R_PPC_PLTREL24"},
+	{19, "R_PPC_COPY"},
+	{20, "R_PPC_GLOB_DAT"},
+	{21, "R_PPC_JMP_SLOT"},
+	{22, "R_PPC_RELATIVE"},
+	{23, "R_PPC_LOCAL24PC"},
+	{24, "R_PPC_UADDR32"},
+	{25, "R_PPC_UADDR16"},
+	{26, "R_PPC_REL32"},
+	{27, "R_PPC_PLT32"},
+	{28, "R_PPC_PLTREL32"},
+	{29, "R_PPC_PLT16_LO"},
+	{30, "R_PPC_PLT16_HI"},
+	{31, "R_PPC_PLT16_HA"},
+	{32, "R_PPC_SDAREL16"},
+	{33, "R_PPC_SECTOFF"},
+	{34, "R_PPC_SECTOFF_LO"},
+	{35, "R_PPC_SECTOFF_HI"},
+	{36, "R_PPC_SECTOFF_HA"},
+
+	{67, "R_PPC_TLS"},
+	{68, "R_PPC_DTPMOD32"},
+	{69, "R_PPC_TPREL16"},
+	{70, "R_PPC_TPREL16_LO"},
+	{71, "R_PPC_TPREL16_HI"},
+	{72, "R_PPC_TPREL16_HA"},
+	{73, "R_PPC_TPREL32"},
+	{74, "R_PPC_DTPREL16"},
+	{75, "R_PPC_DTPREL16_LO"},
+	{76, "R_PPC_DTPREL16_HI"},
+	{77, "R_PPC_DTPREL16_HA"},
+	{78, "R_PPC_DTPREL32"},
+	{79, "R_PPC_GOT_TLSGD16"},
+	{80, "R_PPC_GOT_TLSGD16_LO"},
+	{81, "R_PPC_GOT_TLSGD16_HI"},
+	{82, "R_PPC_GOT_TLSGD16_HA"},
+	{83, "R_PPC_GOT_TLSLD16"},
+	{84, "R_PPC_GOT_TLSLD16_LO"},
+	{85, "R_PPC_GOT_TLSLD16_HI"},
+	{86, "R_PPC_GOT_TLSLD16_HA"},
+	{87, "R_PPC_GOT_TPREL16"},
+	{88, "R_PPC_GOT_TPREL16_LO"},
+	{89, "R_PPC_GOT_TPREL16_HI"},
+	{90, "R_PPC_GOT_TPREL16_HA"},
+
+	{101, "R_PPC_EMB_NADDR32"},
+	{102, "R_PPC_EMB_NADDR16"},
+	{103, "R_PPC_EMB_NADDR16_LO"},
+	{104, "R_PPC_EMB_NADDR16_HI"},
+	{105, "R_PPC_EMB_NADDR16_HA"},
+	{106, "R_PPC_EMB_SDAI16"},
+	{107, "R_PPC_EMB_SDA2I16"},
+	{108, "R_PPC_EMB_SDA2REL"},
+	{109, "R_PPC_EMB_SDA21"},
+	{110, "R_PPC_EMB_MRKREF"},
+	{111, "R_PPC_EMB_RELSEC16"},
+	{112, "R_PPC_EMB_RELST_LO"},
+	{113, "R_PPC_EMB_RELST_HI"},
+	{114, "R_PPC_EMB_RELST_HA"},
+	{115, "R_PPC_EMB_BIT_FLD"},
+	{116, "R_PPC_EMB_RELSDA"},
+}
+
+func (i R_PPC) String() string   { return stringName(uint32(i), rppcStrings, false) }
+func (i R_PPC) GoString() string { return stringName(uint32(i), rppcStrings, true) }
+
+// Relocation types for PowerPC 64.
+type R_PPC64 int
+
+const (
+	R_PPC64_NONE               R_PPC64 = 0
+	R_PPC64_ADDR32             R_PPC64 = 1
+	R_PPC64_ADDR24             R_PPC64 = 2
+	R_PPC64_ADDR16             R_PPC64 = 3
+	R_PPC64_ADDR16_LO          R_PPC64 = 4
+	R_PPC64_ADDR16_HI          R_PPC64 = 5
+	R_PPC64_ADDR16_HA          R_PPC64 = 6
+	R_PPC64_ADDR14             R_PPC64 = 7
+	R_PPC64_ADDR14_BRTAKEN     R_PPC64 = 8
+	R_PPC64_ADDR14_BRNTAKEN    R_PPC64 = 9
+	R_PPC64_REL24              R_PPC64 = 10
+	R_PPC64_REL14              R_PPC64 = 11
+	R_PPC64_REL14_BRTAKEN      R_PPC64 = 12
+	R_PPC64_REL14_BRNTAKEN     R_PPC64 = 13
+	R_PPC64_GOT16              R_PPC64 = 14
+	R_PPC64_GOT16_LO           R_PPC64 = 15
+	R_PPC64_GOT16_HI           R_PPC64 = 16
+	R_PPC64_GOT16_HA           R_PPC64 = 17
+	R_PPC64_JMP_SLOT           R_PPC64 = 21
+	R_PPC64_REL32              R_PPC64 = 26
+	R_PPC64_ADDR64             R_PPC64 = 38
+	R_PPC64_ADDR16_HIGHER      R_PPC64 = 39
+	R_PPC64_ADDR16_HIGHERA     R_PPC64 = 40
+	R_PPC64_ADDR16_HIGHEST     R_PPC64 = 41
+	R_PPC64_ADDR16_HIGHESTA    R_PPC64 = 42
+	R_PPC64_REL64              R_PPC64 = 44
+	R_PPC64_TOC16              R_PPC64 = 47
+	R_PPC64_TOC16_LO           R_PPC64 = 48
+	R_PPC64_TOC16_HI           R_PPC64 = 49
+	R_PPC64_TOC16_HA           R_PPC64 = 50
+	R_PPC64_TOC                R_PPC64 = 51
+	R_PPC64_ADDR16_DS          R_PPC64 = 56
+	R_PPC64_ADDR16_LO_DS       R_PPC64 = 57
+	R_PPC64_GOT16_DS           R_PPC64 = 58
+	R_PPC64_GOT16_LO_DS        R_PPC64 = 59
+	R_PPC64_TOC16_DS           R_PPC64 = 63
+	R_PPC64_TOC16_LO_DS        R_PPC64 = 64
+	R_PPC64_TLS                R_PPC64 = 67
+	R_PPC64_DTPMOD64           R_PPC64 = 68
+	R_PPC64_TPREL16            R_PPC64 = 69
+	R_PPC64_TPREL16_LO         R_PPC64 = 70
+	R_PPC64_TPREL16_HI         R_PPC64 = 71
+	R_PPC64_TPREL16_HA         R_PPC64 = 72
+	R_PPC64_TPREL64            R_PPC64 = 73
+	R_PPC64_DTPREL16           R_PPC64 = 74
+	R_PPC64_DTPREL16_LO        R_PPC64 = 75
+	R_PPC64_DTPREL16_HI        R_PPC64 = 76
+	R_PPC64_DTPREL16_HA        R_PPC64 = 77
+	R_PPC64_DTPREL64           R_PPC64 = 78
+	R_PPC64_GOT_TLSGD16        R_PPC64 = 79
+	R_PPC64_GOT_TLSGD16_LO     R_PPC64 = 80
+	R_PPC64_GOT_TLSGD16_HI     R_PPC64 = 81
+	R_PPC64_GOT_TLSGD16_HA     R_PPC64 = 82
+	R_PPC64_GOT_TLSLD16        R_PPC64 = 83
+	R_PPC64_GOT_TLSLD16_LO     R_PPC64 = 84
+	R_PPC64_GOT_TLSLD16_HI     R_PPC64 = 85
+	R_PPC64_GOT_TLSLD16_HA     R_PPC64 = 86
+	R_PPC64_GOT_TPREL16_DS     R_PPC64 = 87
+	R_PPC64_GOT_TPREL16_LO_DS  R_PPC64 = 88
+	R_PPC64_GOT_TPREL16_HI     R_PPC64 = 89
+	R_PPC64_GOT_TPREL16_HA     R_PPC64 = 90
+	R_PPC64_GOT_DTPREL16_DS    R_PPC64 = 91
+	R_PPC64_GOT_DTPREL16_LO_DS R_PPC64 = 92
+	R_PPC64_GOT_DTPREL16_HI    R_PPC64 = 93
+	R_PPC64_GOT_DTPREL16_HA    R_PPC64 = 94
+	R_PPC64_TPREL16_DS         R_PPC64 = 95
+	R_PPC64_TPREL16_LO_DS      R_PPC64 = 96
+	R_PPC64_TPREL16_HIGHER     R_PPC64 = 97
+	R_PPC64_TPREL16_HIGHERA    R_PPC64 = 98
+	R_PPC64_TPREL16_HIGHEST    R_PPC64 = 99
+	R_PPC64_TPREL16_HIGHESTA   R_PPC64 = 100
+	R_PPC64_DTPREL16_DS        R_PPC64 = 101
+	R_PPC64_DTPREL16_LO_DS     R_PPC64 = 102
+	R_PPC64_DTPREL16_HIGHER    R_PPC64 = 103
+	R_PPC64_DTPREL16_HIGHERA   R_PPC64 = 104
+	R_PPC64_DTPREL16_HIGHEST   R_PPC64 = 105
+	R_PPC64_DTPREL16_HIGHESTA  R_PPC64 = 106
+	R_PPC64_TLSGD              R_PPC64 = 107
+	R_PPC64_TLSLD              R_PPC64 = 108
+	R_PPC64_REL16              R_PPC64 = 249
+	R_PPC64_REL16_LO           R_PPC64 = 250
+	R_PPC64_REL16_HI           R_PPC64 = 251
+	R_PPC64_REL16_HA           R_PPC64 = 252
+)
+
+var rppc64Strings = []intName{
+	{0, "R_PPC64_NONE"},
+	{1, "R_PPC64_ADDR32"},
+	{2, "R_PPC64_ADDR24"},
+	{3, "R_PPC64_ADDR16"},
+	{4, "R_PPC64_ADDR16_LO"},
+	{5, "R_PPC64_ADDR16_HI"},
+	{6, "R_PPC64_ADDR16_HA"},
+	{7, "R_PPC64_ADDR14"},
+	{8, "R_PPC64_ADDR14_BRTAKEN"},
+	{9, "R_PPC64_ADDR14_BRNTAKEN"},
+	{10, "R_PPC64_REL24"},
+	{11, "R_PPC64_REL14"},
+	{12, "R_PPC64_REL14_BRTAKEN"},
+	{13, "R_PPC64_REL14_BRNTAKEN"},
+	{14, "R_PPC64_GOT16"},
+	{15, "R_PPC64_GOT16_LO"},
+	{16, "R_PPC64_GOT16_HI"},
+	{17, "R_PPC64_GOT16_HA"},
+	{21, "R_PPC64_JMP_SLOT"},
+	{26, "R_PPC64_REL32"},
+	{38, "R_PPC64_ADDR64"},
+	{39, "R_PPC64_ADDR16_HIGHER"},
+	{40, "R_PPC64_ADDR16_HIGHERA"},
+	{41, "R_PPC64_ADDR16_HIGHEST"},
+	{42, "R_PPC64_ADDR16_HIGHESTA"},
+	{44, "R_PPC64_REL64"},
+	{47, "R_PPC64_TOC16"},
+	{48, "R_PPC64_TOC16_LO"},
+	{49, "R_PPC64_TOC16_HI"},
+	{50, "R_PPC64_TOC16_HA"},
+	{51, "R_PPC64_TOC"},
+	{56, "R_PPC64_ADDR16_DS"},
+	{57, "R_PPC64_ADDR16_LO_DS"},
+	{58, "R_PPC64_GOT16_DS"},
+	{59, "R_PPC64_GOT16_LO_DS"},
+	{63, "R_PPC64_TOC16_DS"},
+	{64, "R_PPC64_TOC16_LO_DS"},
+	{67, "R_PPC64_TLS"},
+	{68, "R_PPC64_DTPMOD64"},
+	{69, "R_PPC64_TPREL16"},
+	{70, "R_PPC64_TPREL16_LO"},
+	{71, "R_PPC64_TPREL16_HI"},
+	{72, "R_PPC64_TPREL16_HA"},
+	{73, "R_PPC64_TPREL64"},
+	{74, "R_PPC64_DTPREL16"},
+	{75, "R_PPC64_DTPREL16_LO"},
+	{76, "R_PPC64_DTPREL16_HI"},
+	{77, "R_PPC64_DTPREL16_HA"},
+	{78, "R_PPC64_DTPREL64"},
+	{79, "R_PPC64_GOT_TLSGD16"},
+	{80, "R_PPC64_GOT_TLSGD16_LO"},
+	{81, "R_PPC64_GOT_TLSGD16_HI"},
+	{82, "R_PPC64_GOT_TLSGD16_HA"},
+	{83, "R_PPC64_GOT_TLSLD16"},
+	{84, "R_PPC64_GOT_TLSLD16_LO"},
+	{85, "R_PPC64_GOT_TLSLD16_HI"},
+	{86, "R_PPC64_GOT_TLSLD16_HA"},
+	{87, "R_PPC64_GOT_TPREL16_DS"},
+	{88, "R_PPC64_GOT_TPREL16_LO_DS"},
+	{89, "R_PPC64_GOT_TPREL16_HI"},
+	{90, "R_PPC64_GOT_TPREL16_HA"},
+	{91, "R_PPC64_GOT_DTPREL16_DS"},
+	{92, "R_PPC64_GOT_DTPREL16_LO_DS"},
+	{93, "R_PPC64_GOT_DTPREL16_HI"},
+	{94, "R_PPC64_GOT_DTPREL16_HA"},
+	{95, "R_PPC64_TPREL16_DS"},
+	{96, "R_PPC64_TPREL16_LO_DS"},
+	{97, "R_PPC64_TPREL16_HIGHER"},
+	{98, "R_PPC64_TPREL16_HIGHERA"},
+	{99, "R_PPC64_TPREL16_HIGHEST"},
+	{100, "R_PPC64_TPREL16_HIGHESTA"},
+	{101, "R_PPC64_DTPREL16_DS"},
+	{102, "R_PPC64_DTPREL16_LO_DS"},
+	{103, "R_PPC64_DTPREL16_HIGHER"},
+	{104, "R_PPC64_DTPREL16_HIGHERA"},
+	{105, "R_PPC64_DTPREL16_HIGHEST"},
+	{106, "R_PPC64_DTPREL16_HIGHESTA"},
+	{107, "R_PPC64_TLSGD"},
+	{108, "R_PPC64_TLSLD"},
+	{249, "R_PPC64_REL16"},
+	{250, "R_PPC64_REL16_LO"},
+	{251, "R_PPC64_REL16_HI"},
+	{252, "R_PPC64_REL16_HA"},
+}
+
+func (i R_PPC64) String() string   { return stringName(uint32(i), rppc64Strings, false) }
+func (i R_PPC64) GoString() string { return stringName(uint32(i), rppc64Strings, true) }
+
+// Relocation types for s390
+type R_390 int
+
+const (
+	R_390_NONE     R_390 = 0
+	R_390_8        R_390 = 1
+	R_390_12       R_390 = 2
+	R_390_16       R_390 = 3
+	R_390_32       R_390 = 4
+	R_390_PC32     R_390 = 5
+	R_390_GOT12    R_390 = 6
+	R_390_GOT32    R_390 = 7
+	R_390_PLT32    R_390 = 8
+	R_390_COPY     R_390 = 9
+	R_390_GLOB_DAT R_390 = 10
+	R_390_JMP_SLOT R_390 = 11
+	R_390_RELATIVE R_390 = 12
+	R_390_GOTOFF   R_390 = 13
+	R_390_GOTPC    R_390 = 14
+	R_390_GOT16    R_390 = 15
+	R_390_PC16     R_390 = 16
+	R_390_PC16DBL  R_390 = 17
+	R_390_PLT16DBL R_390 = 18
+	R_390_PC32DBL  R_390 = 19
+	R_390_PLT32DBL R_390 = 20
+	R_390_GOTPCDBL R_390 = 21
+	R_390_64       R_390 = 22
+	R_390_PC64     R_390 = 23
+	R_390_GOT64    R_390 = 24
+	R_390_PLT64    R_390 = 25
+	R_390_GOTENT   R_390 = 26
+)
+
+var r390Strings = []intName{
+	{0, "R_390_NONE"},
+	{1, "R_390_8"},
+	{2, "R_390_12"},
+	{3, "R_390_16"},
+	{4, "R_390_32"},
+	{5, "R_390_PC32"},
+	{6, "R_390_GOT12"},
+	{7, "R_390_GOT32"},
+	{8, "R_390_PLT32"},
+	{9, "R_390_COPY"},
+	{10, "R_390_GLOB_DAT"},
+	{11, "R_390_JMP_SLOT"},
+	{12, "R_390_RELATIVE"},
+	{13, "R_390_GOTOFF"},
+	{14, "R_390_GOTPC"},
+	{15, "R_390_GOT16"},
+	{16, "R_390_PC16"},
+	{17, "R_390_PC16DBL"},
+	{18, "R_390_PLT16DBL"},
+	{19, "R_390_PC32DBL"},
+	{20, "R_390_PLT32DBL"},
+	{21, "R_390_GOTPCDBL"},
+	{22, "R_390_64"},
+	{23, "R_390_PC64"},
+	{24, "R_390_GOT64"},
+	{25, "R_390_PLT64"},
+	{26, "R_390_GOTENT"},
+}
+
+func (i R_390) String() string   { return stringName(uint32(i), r390Strings, false) }
+func (i R_390) GoString() string { return stringName(uint32(i), r390Strings, true) }
+
+// Relocation types for SPARC.
+type R_SPARC int
+
+const (
+	R_SPARC_NONE     R_SPARC = 0
+	R_SPARC_8        R_SPARC = 1
+	R_SPARC_16       R_SPARC = 2
+	R_SPARC_32       R_SPARC = 3
+	R_SPARC_DISP8    R_SPARC = 4
+	R_SPARC_DISP16   R_SPARC = 5
+	R_SPARC_DISP32   R_SPARC = 6
+	R_SPARC_WDISP30  R_SPARC = 7
+	R_SPARC_WDISP22  R_SPARC = 8
+	R_SPARC_HI22     R_SPARC = 9
+	R_SPARC_22       R_SPARC = 10
+	R_SPARC_13       R_SPARC = 11
+	R_SPARC_LO10     R_SPARC = 12
+	R_SPARC_GOT10    R_SPARC = 13
+	R_SPARC_GOT13    R_SPARC = 14
+	R_SPARC_GOT22    R_SPARC = 15
+	R_SPARC_PC10     R_SPARC = 16
+	R_SPARC_PC22     R_SPARC = 17
+	R_SPARC_WPLT30   R_SPARC = 18
+	R_SPARC_COPY     R_SPARC = 19
+	R_SPARC_GLOB_DAT R_SPARC = 20
+	R_SPARC_JMP_SLOT R_SPARC = 21
+	R_SPARC_RELATIVE R_SPARC = 22
+	R_SPARC_UA32     R_SPARC = 23
+	R_SPARC_PLT32    R_SPARC = 24
+	R_SPARC_HIPLT22  R_SPARC = 25
+	R_SPARC_LOPLT10  R_SPARC = 26
+	R_SPARC_PCPLT32  R_SPARC = 27
+	R_SPARC_PCPLT22  R_SPARC = 28
+	R_SPARC_PCPLT10  R_SPARC = 29
+	R_SPARC_10       R_SPARC = 30
+	R_SPARC_11       R_SPARC = 31
+	R_SPARC_64       R_SPARC = 32
+	R_SPARC_OLO10    R_SPARC = 33
+	R_SPARC_HH22     R_SPARC = 34
+	R_SPARC_HM10     R_SPARC = 35
+	R_SPARC_LM22     R_SPARC = 36
+	R_SPARC_PC_HH22  R_SPARC = 37
+	R_SPARC_PC_HM10  R_SPARC = 38
+	R_SPARC_PC_LM22  R_SPARC = 39
+	R_SPARC_WDISP16  R_SPARC = 40
+	R_SPARC_WDISP19  R_SPARC = 41
+	R_SPARC_GLOB_JMP R_SPARC = 42
+	R_SPARC_7        R_SPARC = 43
+	R_SPARC_5        R_SPARC = 44
+	R_SPARC_6        R_SPARC = 45
+	R_SPARC_DISP64   R_SPARC = 46
+	R_SPARC_PLT64    R_SPARC = 47
+	R_SPARC_HIX22    R_SPARC = 48
+	R_SPARC_LOX10    R_SPARC = 49
+	R_SPARC_H44      R_SPARC = 50
+	R_SPARC_M44      R_SPARC = 51
+	R_SPARC_L44      R_SPARC = 52
+	R_SPARC_REGISTER R_SPARC = 53
+	R_SPARC_UA64     R_SPARC = 54
+	R_SPARC_UA16     R_SPARC = 55
+)
+
+var rsparcStrings = []intName{
+	{0, "R_SPARC_NONE"},
+	{1, "R_SPARC_8"},
+	{2, "R_SPARC_16"},
+	{3, "R_SPARC_32"},
+	{4, "R_SPARC_DISP8"},
+	{5, "R_SPARC_DISP16"},
+	{6, "R_SPARC_DISP32"},
+	{7, "R_SPARC_WDISP30"},
+	{8, "R_SPARC_WDISP22"},
+	{9, "R_SPARC_HI22"},
+	{10, "R_SPARC_22"},
+	{11, "R_SPARC_13"},
+	{12, "R_SPARC_LO10"},
+	{13, "R_SPARC_GOT10"},
+	{14, "R_SPARC_GOT13"},
+	{15, "R_SPARC_GOT22"},
+	{16, "R_SPARC_PC10"},
+	{17, "R_SPARC_PC22"},
+	{18, "R_SPARC_WPLT30"},
+	{19, "R_SPARC_COPY"},
+	{20, "R_SPARC_GLOB_DAT"},
+	{21, "R_SPARC_JMP_SLOT"},
+	{22, "R_SPARC_RELATIVE"},
+	{23, "R_SPARC_UA32"},
+	{24, "R_SPARC_PLT32"},
+	{25, "R_SPARC_HIPLT22"},
+	{26, "R_SPARC_LOPLT10"},
+	{27, "R_SPARC_PCPLT32"},
+	{28, "R_SPARC_PCPLT22"},
+	{29, "R_SPARC_PCPLT10"},
+	{30, "R_SPARC_10"},
+	{31, "R_SPARC_11"},
+	{32, "R_SPARC_64"},
+	{33, "R_SPARC_OLO10"},
+	{34, "R_SPARC_HH22"},
+	{35, "R_SPARC_HM10"},
+	{36, "R_SPARC_LM22"},
+	{37, "R_SPARC_PC_HH22"},
+	{38, "R_SPARC_PC_HM10"},
+	{39, "R_SPARC_PC_LM22"},
+	{40, "R_SPARC_WDISP16"},
+	{41, "R_SPARC_WDISP19"},
+	{42, "R_SPARC_GLOB_JMP"},
+	{43, "R_SPARC_7"},
+	{44, "R_SPARC_5"},
+	{45, "R_SPARC_6"},
+	{46, "R_SPARC_DISP64"},
+	{47, "R_SPARC_PLT64"},
+	{48, "R_SPARC_HIX22"},
+	{49, "R_SPARC_LOX10"},
+	{50, "R_SPARC_H44"},
+	{51, "R_SPARC_M44"},
+	{52, "R_SPARC_L44"},
+	{53, "R_SPARC_REGISTER"},
+	{54, "R_SPARC_UA64"},
+	{55, "R_SPARC_UA16"},
+}
+
+func (i R_SPARC) String() string   { return stringName(uint32(i), rsparcStrings, false) }
+func (i R_SPARC) GoString() string { return stringName(uint32(i), rsparcStrings, true) }
+
+// Magic number for the elf trampoline, chosen wisely to be an immediate value.
+const ARM_MAGIC_TRAMP_NUMBER = 0x5c000003
+
+// ELF32 File header.
+type Header32 struct {
+	Ident     [EI_NIDENT]byte /* File identification. */
+	Type      uint16          /* File type. */
+	Machine   uint16          /* Machine architecture. */
+	Version   uint32          /* ELF format version. */
+	Entry     uint32          /* Entry point. */
+	Phoff     uint32          /* Program header file offset. */
+	Shoff     uint32          /* Section header file offset. */
+	Flags     uint32          /* Architecture-specific flags. */
+	Ehsize    uint16          /* Size of ELF header in bytes. */
+	Phentsize uint16          /* Size of program header entry. */
+	Phnum     uint16          /* Number of program header entries. */
+	Shentsize uint16          /* Size of section header entry. */
+	Shnum     uint16          /* Number of section header entries. */
+	Shstrndx  uint16          /* Section name strings section. */
+}
+
+// ELF32 Section header.
+type Section32 struct {
+	Name      uint32 /* Section name (index into the section header string table). */
+	Type      uint32 /* Section type. */
+	Flags     uint32 /* Section flags. */
+	Addr      uint32 /* Address in memory image. */
+	Off       uint32 /* Offset in file. */
+	Size      uint32 /* Size in bytes. */
+	Link      uint32 /* Index of a related section. */
+	Info      uint32 /* Depends on section type. */
+	Addralign uint32 /* Alignment in bytes. */
+	Entsize   uint32 /* Size of each entry in section. */
+}
+
+// ELF32 Program header.
+type Prog32 struct {
+	Type   uint32 /* Entry type. */
+	Off    uint32 /* File offset of contents. */
+	Vaddr  uint32 /* Virtual address in memory image. */
+	Paddr  uint32 /* Physical address (not used). */
+	Filesz uint32 /* Size of contents in file. */
+	Memsz  uint32 /* Size of contents in memory. */
+	Flags  uint32 /* Access permission flags. */
+	Align  uint32 /* Alignment in memory and file. */
+}
+
+// ELF32 Dynamic structure.  The ".dynamic" section contains an array of them.
+type Dyn32 struct {
+	Tag int32  /* Entry type. */
+	Val uint32 /* Integer/Address value. */
+}
+
+/*
+ * Relocation entries.
+ */
+
+// ELF32 Relocations that don't need an addend field.
+type Rel32 struct {
+	Off  uint32 /* Location to be relocated. */
+	Info uint32 /* Relocation type and symbol index. */
+}
+
+// ELF32 Relocations that need an addend field.
+type Rela32 struct {
+	Off    uint32 /* Location to be relocated. */
+	Info   uint32 /* Relocation type and symbol index. */
+	Addend int32  /* Addend. */
+}
+
+func R_SYM32(info uint32) uint32      { return uint32(info >> 8) }
+func R_TYPE32(info uint32) uint32     { return uint32(info & 0xff) }
+func R_INFO32(sym, typ uint32) uint32 { return sym<<8 | typ }
+
+// ELF32 Symbol.
+type Sym32 struct {
+	Name  uint32
+	Value uint32
+	Size  uint32
+	Info  uint8
+	Other uint8
+	Shndx uint16
+}
+
+const Sym32Size = 16
+
+func ST_BIND(info uint8) SymBind { return SymBind(info >> 4) }
+func ST_TYPE(info uint8) SymType { return SymType(info & 0xF) }
+func ST_INFO(bind SymBind, typ SymType) uint8 {
+	return uint8(bind)<<4 | uint8(typ)&0xf
+}
+func ST_VISIBILITY(other uint8) SymVis { return SymVis(other & 3) }
+
+/*
+ * ELF64
+ */
+
+// ELF64 file header.
+type Header64 struct {
+	Ident     [EI_NIDENT]byte /* File identification. */
+	Type      uint16          /* File type. */
+	Machine   uint16          /* Machine architecture. */
+	Version   uint32          /* ELF format version. */
+	Entry     uint64          /* Entry point. */
+	Phoff     uint64          /* Program header file offset. */
+	Shoff     uint64          /* Section header file offset. */
+	Flags     uint32          /* Architecture-specific flags. */
+	Ehsize    uint16          /* Size of ELF header in bytes. */
+	Phentsize uint16          /* Size of program header entry. */
+	Phnum     uint16          /* Number of program header entries. */
+	Shentsize uint16          /* Size of section header entry. */
+	Shnum     uint16          /* Number of section header entries. */
+	Shstrndx  uint16          /* Section name strings section. */
+}
+
+// ELF64 Section header.
+type Section64 struct {
+	Name      uint32 /* Section name (index into the section header string table). */
+	Type      uint32 /* Section type. */
+	Flags     uint64 /* Section flags. */
+	Addr      uint64 /* Address in memory image. */
+	Off       uint64 /* Offset in file. */
+	Size      uint64 /* Size in bytes. */
+	Link      uint32 /* Index of a related section. */
+	Info      uint32 /* Depends on section type. */
+	Addralign uint64 /* Alignment in bytes. */
+	Entsize   uint64 /* Size of each entry in section. */
+}
+
+// ELF64 Program header.
+type Prog64 struct {
+	Type   uint32 /* Entry type. */
+	Flags  uint32 /* Access permission flags. */
+	Off    uint64 /* File offset of contents. */
+	Vaddr  uint64 /* Virtual address in memory image. */
+	Paddr  uint64 /* Physical address (not used). */
+	Filesz uint64 /* Size of contents in file. */
+	Memsz  uint64 /* Size of contents in memory. */
+	Align  uint64 /* Alignment in memory and file. */
+}
+
+// ELF64 Dynamic structure.  The ".dynamic" section contains an array of them.
+type Dyn64 struct {
+	Tag int64  /* Entry type. */
+	Val uint64 /* Integer/address value */
+}
+
+/*
+ * Relocation entries.
+ */
+
+/* ELF64 relocations that don't need an addend field. */
+type Rel64 struct {
+	Off  uint64 /* Location to be relocated. */
+	Info uint64 /* Relocation type and symbol index. */
+}
+
+/* ELF64 relocations that need an addend field. */
+type Rela64 struct {
+	Off    uint64 /* Location to be relocated. */
+	Info   uint64 /* Relocation type and symbol index. */
+	Addend int64  /* Addend. */
+}
+
+func R_SYM64(info uint64) uint32    { return uint32(info >> 32) }
+func R_TYPE64(info uint64) uint32   { return uint32(info) }
+func R_INFO(sym, typ uint32) uint64 { return uint64(sym)<<32 | uint64(typ) }
+
+// ELF64 symbol table entries.
+type Sym64 struct {
+	Name  uint32 /* String table index of name. */
+	Info  uint8  /* Type and binding information. */
+	Other uint8  /* Reserved (not used). */
+	Shndx uint16 /* Section index of symbol. */
+	Value uint64 /* Symbol value. */
+	Size  uint64 /* Size of associated object. */
+}
+
+const Sym64Size = 24
+
+type intName struct {
+	i uint32
+	s string
+}
+
+func stringName(i uint32, names []intName, goSyntax bool) string {
+	for _, n := range names {
+		if n.i == i {
+			if goSyntax {
+				return "elf." + n.s
+			}
+			return n.s
+		}
+	}
+
+	// second pass - look for smaller to add with.
+	// assume sorted already
+	for j := len(names) - 1; j >= 0; j-- {
+		n := names[j]
+		if n.i < i {
+			s := n.s
+			if goSyntax {
+				s = "elf." + s
+			}
+			return s + "+" + strconv.FormatUint(uint64(i-n.i), 10)
+		}
+	}
+
+	return strconv.FormatUint(uint64(i), 10)
+}
+
+func flagName(i uint32, names []intName, goSyntax bool) string {
+	s := ""
+	for _, n := range names {
+		if n.i&i == n.i {
+			if len(s) > 0 {
+				s += "+"
+			}
+			if goSyntax {
+				s += "elf."
+			}
+			s += n.s
+			i -= n.i
+		}
+	}
+	if len(s) == 0 {
+		return "0x" + strconv.FormatUint(uint64(i), 16)
+	}
+	if i != 0 {
+		s += "+0x" + strconv.FormatUint(uint64(i), 16)
+	}
+	return s
+}
diff --git a/third_party/gofrontend/libgo/go/debug/elf/elf_test.go b/third_party/gofrontend/libgo/go/debug/elf/elf_test.go
new file mode 100644
index 0000000..e3c51bb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/elf_test.go
@@ -0,0 +1,49 @@
+// 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 elf
+
+import (
+	"fmt"
+	"testing"
+)
+
+type nameTest struct {
+	val interface{}
+	str string
+}
+
+var nameTests = []nameTest{
+	{ELFOSABI_LINUX, "ELFOSABI_LINUX"},
+	{ET_EXEC, "ET_EXEC"},
+	{EM_860, "EM_860"},
+	{SHN_LOPROC, "SHN_LOPROC"},
+	{SHT_PROGBITS, "SHT_PROGBITS"},
+	{SHF_MERGE + SHF_TLS, "SHF_MERGE+SHF_TLS"},
+	{PT_LOAD, "PT_LOAD"},
+	{PF_W + PF_R + 0x50, "PF_W+PF_R+0x50"},
+	{DT_SYMBOLIC, "DT_SYMBOLIC"},
+	{DF_BIND_NOW, "DF_BIND_NOW"},
+	{NT_FPREGSET, "NT_FPREGSET"},
+	{STB_GLOBAL, "STB_GLOBAL"},
+	{STT_COMMON, "STT_COMMON"},
+	{STV_HIDDEN, "STV_HIDDEN"},
+	{R_X86_64_PC32, "R_X86_64_PC32"},
+	{R_ALPHA_OP_PUSH, "R_ALPHA_OP_PUSH"},
+	{R_ARM_THM_ABS5, "R_ARM_THM_ABS5"},
+	{R_386_GOT32, "R_386_GOT32"},
+	{R_PPC_GOT16_HI, "R_PPC_GOT16_HI"},
+	{R_SPARC_GOT22, "R_SPARC_GOT22"},
+	{ET_LOOS + 5, "ET_LOOS+5"},
+	{ProgFlag(0x50), "0x50"},
+}
+
+func TestNames(t *testing.T) {
+	for i, tt := range nameTests {
+		s := fmt.Sprint(tt.val)
+		if s != tt.str {
+			t.Errorf("#%d: Sprint(%d) = %q, want %q", i, tt.val, s, tt.str)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/elf/file.go b/third_party/gofrontend/libgo/go/debug/elf/file.go
new file mode 100644
index 0000000..0c8dff5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/file.go
@@ -0,0 +1,973 @@
+// 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 elf implements access to ELF object files.
+package elf
+
+import (
+	"bytes"
+	"debug/dwarf"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"os"
+)
+
+// TODO: error reporting detail
+
+/*
+ * Internal ELF representation
+ */
+
+// A FileHeader represents an ELF file header.
+type FileHeader struct {
+	Class      Class
+	Data       Data
+	Version    Version
+	OSABI      OSABI
+	ABIVersion uint8
+	ByteOrder  binary.ByteOrder
+	Type       Type
+	Machine    Machine
+	Entry      uint64
+}
+
+// A File represents an open ELF file.
+type File struct {
+	FileHeader
+	Sections  []*Section
+	Progs     []*Prog
+	closer    io.Closer
+	gnuNeed   []verneed
+	gnuVersym []byte
+}
+
+// A SectionHeader represents a single ELF section header.
+type SectionHeader struct {
+	Name      string
+	Type      SectionType
+	Flags     SectionFlag
+	Addr      uint64
+	Offset    uint64
+	Size      uint64
+	Link      uint32
+	Info      uint32
+	Addralign uint64
+	Entsize   uint64
+}
+
+// A Section represents a single section in an ELF file.
+type Section struct {
+	SectionHeader
+
+	// Embed ReaderAt for ReadAt method.
+	// Do not embed SectionReader directly
+	// to avoid having Read and Seek.
+	// If a client wants Read and Seek it must use
+	// Open() to avoid fighting over the seek offset
+	// with other clients.
+	io.ReaderAt
+	sr *io.SectionReader
+}
+
+// Data reads and returns the contents of the ELF section.
+func (s *Section) Data() ([]byte, error) {
+	dat := make([]byte, s.sr.Size())
+	n, err := s.sr.ReadAt(dat, 0)
+	if n == len(dat) {
+		err = nil
+	}
+	return dat[0:n], err
+}
+
+// stringTable reads and returns the string table given by the
+// specified link value.
+func (f *File) stringTable(link uint32) ([]byte, error) {
+	if link <= 0 || link >= uint32(len(f.Sections)) {
+		return nil, errors.New("section has invalid string table link")
+	}
+	return f.Sections[link].Data()
+}
+
+// Open returns a new ReadSeeker reading the ELF section.
+func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
+
+// A ProgHeader represents a single ELF program header.
+type ProgHeader struct {
+	Type   ProgType
+	Flags  ProgFlag
+	Off    uint64
+	Vaddr  uint64
+	Paddr  uint64
+	Filesz uint64
+	Memsz  uint64
+	Align  uint64
+}
+
+// A Prog represents a single ELF program header in an ELF binary.
+type Prog struct {
+	ProgHeader
+
+	// Embed ReaderAt for ReadAt method.
+	// Do not embed SectionReader directly
+	// to avoid having Read and Seek.
+	// If a client wants Read and Seek it must use
+	// Open() to avoid fighting over the seek offset
+	// with other clients.
+	io.ReaderAt
+	sr *io.SectionReader
+}
+
+// Open returns a new ReadSeeker reading the ELF program body.
+func (p *Prog) Open() io.ReadSeeker { return io.NewSectionReader(p.sr, 0, 1<<63-1) }
+
+// A Symbol represents an entry in an ELF symbol table section.
+type Symbol struct {
+	Name        string
+	Info, Other byte
+	Section     SectionIndex
+	Value, Size uint64
+}
+
+/*
+ * ELF reader
+ */
+
+type FormatError struct {
+	off int64
+	msg string
+	val interface{}
+}
+
+func (e *FormatError) Error() string {
+	msg := e.msg
+	if e.val != nil {
+		msg += fmt.Sprintf(" '%v' ", e.val)
+	}
+	msg += fmt.Sprintf("in record at byte %#x", e.off)
+	return msg
+}
+
+// Open opens the named file using os.Open and prepares it for use as an ELF binary.
+func Open(name string) (*File, error) {
+	f, err := os.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	ff, err := NewFile(f)
+	if err != nil {
+		f.Close()
+		return nil, err
+	}
+	ff.closer = f
+	return ff, nil
+}
+
+// Close closes the File.
+// If the File was created using NewFile directly instead of Open,
+// Close has no effect.
+func (f *File) Close() error {
+	var err error
+	if f.closer != nil {
+		err = f.closer.Close()
+		f.closer = nil
+	}
+	return err
+}
+
+// SectionByType returns the first section in f with the
+// given type, or nil if there is no such section.
+func (f *File) SectionByType(typ SectionType) *Section {
+	for _, s := range f.Sections {
+		if s.Type == typ {
+			return s
+		}
+	}
+	return nil
+}
+
+// NewFile creates a new File for accessing an ELF binary in an underlying reader.
+// The ELF binary is expected to start at position 0 in the ReaderAt.
+func NewFile(r io.ReaderAt) (*File, error) {
+	sr := io.NewSectionReader(r, 0, 1<<63-1)
+	// Read and decode ELF identifier
+	var ident [16]uint8
+	if _, err := r.ReadAt(ident[0:], 0); err != nil {
+		return nil, err
+	}
+	if ident[0] != '\x7f' || ident[1] != 'E' || ident[2] != 'L' || ident[3] != 'F' {
+		return nil, &FormatError{0, "bad magic number", ident[0:4]}
+	}
+
+	f := new(File)
+	f.Class = Class(ident[EI_CLASS])
+	switch f.Class {
+	case ELFCLASS32:
+	case ELFCLASS64:
+		// ok
+	default:
+		return nil, &FormatError{0, "unknown ELF class", f.Class}
+	}
+
+	f.Data = Data(ident[EI_DATA])
+	switch f.Data {
+	case ELFDATA2LSB:
+		f.ByteOrder = binary.LittleEndian
+	case ELFDATA2MSB:
+		f.ByteOrder = binary.BigEndian
+	default:
+		return nil, &FormatError{0, "unknown ELF data encoding", f.Data}
+	}
+
+	f.Version = Version(ident[EI_VERSION])
+	if f.Version != EV_CURRENT {
+		return nil, &FormatError{0, "unknown ELF version", f.Version}
+	}
+
+	f.OSABI = OSABI(ident[EI_OSABI])
+	f.ABIVersion = ident[EI_ABIVERSION]
+
+	// Read ELF file header
+	var phoff int64
+	var phentsize, phnum int
+	var shoff int64
+	var shentsize, shnum, shstrndx int
+	shstrndx = -1
+	switch f.Class {
+	case ELFCLASS32:
+		hdr := new(Header32)
+		sr.Seek(0, os.SEEK_SET)
+		if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
+			return nil, err
+		}
+		f.Type = Type(hdr.Type)
+		f.Machine = Machine(hdr.Machine)
+		f.Entry = uint64(hdr.Entry)
+		if v := Version(hdr.Version); v != f.Version {
+			return nil, &FormatError{0, "mismatched ELF version", v}
+		}
+		phoff = int64(hdr.Phoff)
+		phentsize = int(hdr.Phentsize)
+		phnum = int(hdr.Phnum)
+		shoff = int64(hdr.Shoff)
+		shentsize = int(hdr.Shentsize)
+		shnum = int(hdr.Shnum)
+		shstrndx = int(hdr.Shstrndx)
+	case ELFCLASS64:
+		hdr := new(Header64)
+		sr.Seek(0, os.SEEK_SET)
+		if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
+			return nil, err
+		}
+		f.Type = Type(hdr.Type)
+		f.Machine = Machine(hdr.Machine)
+		f.Entry = uint64(hdr.Entry)
+		if v := Version(hdr.Version); v != f.Version {
+			return nil, &FormatError{0, "mismatched ELF version", v}
+		}
+		phoff = int64(hdr.Phoff)
+		phentsize = int(hdr.Phentsize)
+		phnum = int(hdr.Phnum)
+		shoff = int64(hdr.Shoff)
+		shentsize = int(hdr.Shentsize)
+		shnum = int(hdr.Shnum)
+		shstrndx = int(hdr.Shstrndx)
+	}
+
+	if shnum > 0 && shoff > 0 && (shstrndx < 0 || shstrndx >= shnum) {
+		return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx}
+	}
+
+	// Read program headers
+	f.Progs = make([]*Prog, phnum)
+	for i := 0; i < phnum; i++ {
+		off := phoff + int64(i)*int64(phentsize)
+		sr.Seek(off, os.SEEK_SET)
+		p := new(Prog)
+		switch f.Class {
+		case ELFCLASS32:
+			ph := new(Prog32)
+			if err := binary.Read(sr, f.ByteOrder, ph); err != nil {
+				return nil, err
+			}
+			p.ProgHeader = ProgHeader{
+				Type:   ProgType(ph.Type),
+				Flags:  ProgFlag(ph.Flags),
+				Off:    uint64(ph.Off),
+				Vaddr:  uint64(ph.Vaddr),
+				Paddr:  uint64(ph.Paddr),
+				Filesz: uint64(ph.Filesz),
+				Memsz:  uint64(ph.Memsz),
+				Align:  uint64(ph.Align),
+			}
+		case ELFCLASS64:
+			ph := new(Prog64)
+			if err := binary.Read(sr, f.ByteOrder, ph); err != nil {
+				return nil, err
+			}
+			p.ProgHeader = ProgHeader{
+				Type:   ProgType(ph.Type),
+				Flags:  ProgFlag(ph.Flags),
+				Off:    uint64(ph.Off),
+				Vaddr:  uint64(ph.Vaddr),
+				Paddr:  uint64(ph.Paddr),
+				Filesz: uint64(ph.Filesz),
+				Memsz:  uint64(ph.Memsz),
+				Align:  uint64(ph.Align),
+			}
+		}
+		p.sr = io.NewSectionReader(r, int64(p.Off), int64(p.Filesz))
+		p.ReaderAt = p.sr
+		f.Progs[i] = p
+	}
+
+	// Read section headers
+	f.Sections = make([]*Section, shnum)
+	names := make([]uint32, shnum)
+	for i := 0; i < shnum; i++ {
+		off := shoff + int64(i)*int64(shentsize)
+		sr.Seek(off, os.SEEK_SET)
+		s := new(Section)
+		switch f.Class {
+		case ELFCLASS32:
+			sh := new(Section32)
+			if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
+				return nil, err
+			}
+			names[i] = sh.Name
+			s.SectionHeader = SectionHeader{
+				Type:      SectionType(sh.Type),
+				Flags:     SectionFlag(sh.Flags),
+				Addr:      uint64(sh.Addr),
+				Offset:    uint64(sh.Off),
+				Size:      uint64(sh.Size),
+				Link:      uint32(sh.Link),
+				Info:      uint32(sh.Info),
+				Addralign: uint64(sh.Addralign),
+				Entsize:   uint64(sh.Entsize),
+			}
+		case ELFCLASS64:
+			sh := new(Section64)
+			if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
+				return nil, err
+			}
+			names[i] = sh.Name
+			s.SectionHeader = SectionHeader{
+				Type:      SectionType(sh.Type),
+				Flags:     SectionFlag(sh.Flags),
+				Offset:    uint64(sh.Off),
+				Size:      uint64(sh.Size),
+				Addr:      uint64(sh.Addr),
+				Link:      uint32(sh.Link),
+				Info:      uint32(sh.Info),
+				Addralign: uint64(sh.Addralign),
+				Entsize:   uint64(sh.Entsize),
+			}
+		}
+		s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Size))
+		s.ReaderAt = s.sr
+		f.Sections[i] = s
+	}
+
+	if len(f.Sections) == 0 {
+		return f, nil
+	}
+
+	// Load section header string table.
+	shstrtab, err := f.Sections[shstrndx].Data()
+	if err != nil {
+		return nil, err
+	}
+	for i, s := range f.Sections {
+		var ok bool
+		s.Name, ok = getString(shstrtab, int(names[i]))
+		if !ok {
+			return nil, &FormatError{shoff + int64(i*shentsize), "bad section name index", names[i]}
+		}
+	}
+
+	return f, nil
+}
+
+// getSymbols returns a slice of Symbols from parsing the symbol table
+// with the given type, along with the associated string table.
+func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) {
+	switch f.Class {
+	case ELFCLASS64:
+		return f.getSymbols64(typ)
+
+	case ELFCLASS32:
+		return f.getSymbols32(typ)
+	}
+
+	return nil, nil, errors.New("not implemented")
+}
+
+func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
+	symtabSection := f.SectionByType(typ)
+	if symtabSection == nil {
+		return nil, nil, errors.New("no symbol section")
+	}
+
+	data, err := symtabSection.Data()
+	if err != nil {
+		return nil, nil, errors.New("cannot load symbol section")
+	}
+	symtab := bytes.NewReader(data)
+	if symtab.Len()%Sym32Size != 0 {
+		return nil, nil, errors.New("length of symbol section is not a multiple of SymSize")
+	}
+
+	strdata, err := f.stringTable(symtabSection.Link)
+	if err != nil {
+		return nil, nil, errors.New("cannot load string table section")
+	}
+
+	// The first entry is all zeros.
+	var skip [Sym32Size]byte
+	symtab.Read(skip[:])
+
+	symbols := make([]Symbol, symtab.Len()/Sym32Size)
+
+	i := 0
+	var sym Sym32
+	for symtab.Len() > 0 {
+		binary.Read(symtab, f.ByteOrder, &sym)
+		str, _ := getString(strdata, int(sym.Name))
+		symbols[i].Name = str
+		symbols[i].Info = sym.Info
+		symbols[i].Other = sym.Other
+		symbols[i].Section = SectionIndex(sym.Shndx)
+		symbols[i].Value = uint64(sym.Value)
+		symbols[i].Size = uint64(sym.Size)
+		i++
+	}
+
+	return symbols, strdata, nil
+}
+
+func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
+	symtabSection := f.SectionByType(typ)
+	if symtabSection == nil {
+		return nil, nil, errors.New("no symbol section")
+	}
+
+	data, err := symtabSection.Data()
+	if err != nil {
+		return nil, nil, errors.New("cannot load symbol section")
+	}
+	symtab := bytes.NewReader(data)
+	if symtab.Len()%Sym64Size != 0 {
+		return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size")
+	}
+
+	strdata, err := f.stringTable(symtabSection.Link)
+	if err != nil {
+		return nil, nil, errors.New("cannot load string table section")
+	}
+
+	// The first entry is all zeros.
+	var skip [Sym64Size]byte
+	symtab.Read(skip[:])
+
+	symbols := make([]Symbol, symtab.Len()/Sym64Size)
+
+	i := 0
+	var sym Sym64
+	for symtab.Len() > 0 {
+		binary.Read(symtab, f.ByteOrder, &sym)
+		str, _ := getString(strdata, int(sym.Name))
+		symbols[i].Name = str
+		symbols[i].Info = sym.Info
+		symbols[i].Other = sym.Other
+		symbols[i].Section = SectionIndex(sym.Shndx)
+		symbols[i].Value = sym.Value
+		symbols[i].Size = sym.Size
+		i++
+	}
+
+	return symbols, strdata, nil
+}
+
+// getString extracts a string from an ELF string table.
+func getString(section []byte, start int) (string, bool) {
+	if start < 0 || start >= len(section) {
+		return "", false
+	}
+
+	for end := start; end < len(section); end++ {
+		if section[end] == 0 {
+			return string(section[start:end]), true
+		}
+	}
+	return "", false
+}
+
+// Section returns a section with the given name, or nil if no such
+// section exists.
+func (f *File) Section(name string) *Section {
+	for _, s := range f.Sections {
+		if s.Name == name {
+			return s
+		}
+	}
+	return nil
+}
+
+// applyRelocations applies relocations to dst. rels is a relocations section
+// in RELA format.
+func (f *File) applyRelocations(dst []byte, rels []byte) error {
+	if f.Class == ELFCLASS64 && f.Machine == EM_X86_64 {
+		return f.applyRelocationsAMD64(dst, rels)
+	}
+	if f.Class == ELFCLASS32 && f.Machine == EM_386 {
+		return f.applyRelocations386(dst, rels)
+	}
+	if f.Class == ELFCLASS64 && f.Machine == EM_PPC64 {
+		return f.applyRelocationsPPC64(dst, rels)
+	}
+	if f.Class == ELFCLASS64 && f.Machine == EM_S390 {
+		return f.applyRelocationsS390x(dst, rels)
+	}
+
+	return errors.New("not implemented")
+}
+
+func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
+	// 24 is the size of Rela64.
+	if len(rels)%24 != 0 {
+		return errors.New("length of relocation section is not a multiple of 24")
+	}
+
+	symbols, _, err := f.getSymbols(SHT_SYMTAB)
+	if err != nil {
+		return err
+	}
+
+	b := bytes.NewReader(rels)
+	var rela Rela64
+
+	for b.Len() > 0 {
+		binary.Read(b, f.ByteOrder, &rela)
+		symNo := rela.Info >> 32
+		t := R_X86_64(rela.Info & 0xffff)
+
+		if symNo == 0 || symNo > uint64(len(symbols)) {
+			continue
+		}
+		sym := &symbols[symNo-1]
+		if SymType(sym.Info&0xf) != STT_SECTION {
+			// We don't handle non-section relocations for now.
+			continue
+		}
+
+		switch t {
+		case R_X86_64_64:
+			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
+				continue
+			}
+			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
+		case R_X86_64_32:
+			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
+				continue
+			}
+			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
+		}
+	}
+
+	return nil
+}
+
+func (f *File) applyRelocations386(dst []byte, rels []byte) error {
+	// 8 is the size of Rel32.
+	if len(rels)%8 != 0 {
+		return errors.New("length of relocation section is not a multiple of 8")
+	}
+
+	symbols, _, err := f.getSymbols(SHT_SYMTAB)
+	if err != nil {
+		return err
+	}
+
+	b := bytes.NewReader(rels)
+	var rel Rel32
+
+	for b.Len() > 0 {
+		binary.Read(b, f.ByteOrder, &rel)
+		symNo := rel.Info >> 8
+		t := R_386(rel.Info & 0xff)
+
+		if symNo == 0 || symNo > uint32(len(symbols)) {
+			continue
+		}
+		sym := &symbols[symNo-1]
+
+		if t == R_386_32 {
+			if rel.Off+4 >= uint32(len(dst)) {
+				continue
+			}
+			val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
+			val += uint32(sym.Value)
+			f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
+		}
+	}
+
+	return nil
+}
+
+func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
+	// 24 is the size of Rela64.
+	if len(rels)%24 != 0 {
+		return errors.New("length of relocation section is not a multiple of 24")
+	}
+
+	symbols, _, err := f.getSymbols(SHT_SYMTAB)
+	if err != nil {
+		return err
+	}
+
+	b := bytes.NewReader(rels)
+	var rela Rela64
+
+	for b.Len() > 0 {
+		binary.Read(b, f.ByteOrder, &rela)
+		symNo := rela.Info >> 32
+		t := R_PPC64(rela.Info & 0xffff)
+
+		if symNo == 0 || symNo > uint64(len(symbols)) {
+			continue
+		}
+		sym := &symbols[symNo-1]
+		if SymType(sym.Info&0xf) != STT_SECTION {
+			// We don't handle non-section relocations for now.
+			continue
+		}
+
+		switch t {
+		case R_PPC64_ADDR64:
+			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
+				continue
+			}
+			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
+		case R_PPC64_ADDR32:
+			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
+				continue
+			}
+			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
+		}
+	}
+
+	return nil
+}
+
+func (f *File) applyRelocationsS390x(dst []byte, rels []byte) error {
+	// 24 is the size of Rela64.
+	if len(rels)%24 != 0 {
+		return errors.New("length of relocation section is not a multiple of 24")
+	}
+
+	symbols, _, err := f.getSymbols(SHT_SYMTAB)
+	if err != nil {
+		return err
+	}
+
+	b := bytes.NewBuffer(rels)
+	var rela Rela64
+
+	for b.Len() > 0 {
+		binary.Read(b, f.ByteOrder, &rela)
+		symNo := rela.Info >> 32
+		t := R_390(rela.Info & 0xffff)
+
+		if symNo == 0 || symNo > uint64(len(symbols)) {
+			continue
+		}
+		sym := &symbols[symNo-1]
+
+		switch t {
+		case R_390_64:
+			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
+				continue
+			}
+			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)+uint64(sym.Value))
+		case R_390_32:
+			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
+				continue
+			}
+			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)+uint32(sym.Value))
+		}
+	}
+
+	return nil
+}
+
+func (f *File) DWARF() (*dwarf.Data, error) {
+	// There are many other DWARF sections, but these
+	// are the required ones, and the debug/dwarf package
+	// does not use the others, so don't bother loading them.
+	var names = [...]string{"abbrev", "info", "line", "ranges", "str"}
+	var dat [len(names)][]byte
+	for i, name := range names {
+		name = ".debug_" + name
+		s := f.Section(name)
+		if s == nil {
+			continue
+		}
+		b, err := s.Data()
+		if err != nil && uint64(len(b)) < s.Size {
+			return nil, err
+		}
+		dat[i] = b
+	}
+
+	// If there's a relocation table for .debug_info, we have to process it
+	// now otherwise the data in .debug_info is invalid for x86-64 objects.
+	rela := f.Section(".rela.debug_info")
+	if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_PPC64 || f.Machine == EM_S390) {
+		data, err := rela.Data()
+		if err != nil {
+			return nil, err
+		}
+		err = f.applyRelocations(dat[1], data)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	// When using clang we need to process relocations even for 386.
+	rel := f.Section(".rel.debug_info")
+	if rel != nil && rel.Type == SHT_REL && f.Machine == EM_386 {
+		data, err := rel.Data()
+		if err != nil {
+			return nil, err
+		}
+		err = f.applyRelocations(dat[1], data)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	abbrev, info, line, ranges, str := dat[0], dat[1], dat[2], dat[3], dat[4]
+	d, err := dwarf.New(abbrev, nil, nil, info, line, nil, ranges, str)
+	if err != nil {
+		return nil, err
+	}
+
+	// Look for DWARF4 .debug_types sections.
+	for i, s := range f.Sections {
+		if s.Name == ".debug_types" {
+			b, err := s.Data()
+			if err != nil && uint64(len(b)) < s.Size {
+				return nil, err
+			}
+
+			for _, r := range f.Sections {
+				if r.Type != SHT_RELA && r.Type != SHT_REL {
+					continue
+				}
+				if int(r.Info) != i {
+					continue
+				}
+				rd, err := r.Data()
+				if err != nil {
+					return nil, err
+				}
+				err = f.applyRelocations(b, rd)
+				if err != nil {
+					return nil, err
+				}
+			}
+
+			err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	return d, nil
+}
+
+// Symbols returns the symbol table for f.
+//
+// For compatibility with Go 1.0, Symbols omits the null symbol at index 0.
+// After retrieving the symbols as symtab, an externally supplied index x
+// corresponds to symtab[x-1], not symtab[x].
+func (f *File) Symbols() ([]Symbol, error) {
+	sym, _, err := f.getSymbols(SHT_SYMTAB)
+	return sym, err
+}
+
+type ImportedSymbol struct {
+	Name    string
+	Version string
+	Library string
+}
+
+// ImportedSymbols returns the names of all symbols
+// referred to by the binary f that are expected to be
+// satisfied by other libraries at dynamic load time.
+// It does not return weak symbols.
+func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
+	sym, str, err := f.getSymbols(SHT_DYNSYM)
+	if err != nil {
+		return nil, err
+	}
+	f.gnuVersionInit(str)
+	var all []ImportedSymbol
+	for i, s := range sym {
+		if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
+			all = append(all, ImportedSymbol{Name: s.Name})
+			f.gnuVersion(i, &all[len(all)-1])
+		}
+	}
+	return all, nil
+}
+
+type verneed struct {
+	File string
+	Name string
+}
+
+// gnuVersionInit parses the GNU version tables
+// for use by calls to gnuVersion.
+func (f *File) gnuVersionInit(str []byte) {
+	// Accumulate verneed information.
+	vn := f.SectionByType(SHT_GNU_VERNEED)
+	if vn == nil {
+		return
+	}
+	d, _ := vn.Data()
+
+	var need []verneed
+	i := 0
+	for {
+		if i+16 > len(d) {
+			break
+		}
+		vers := f.ByteOrder.Uint16(d[i : i+2])
+		if vers != 1 {
+			break
+		}
+		cnt := f.ByteOrder.Uint16(d[i+2 : i+4])
+		fileoff := f.ByteOrder.Uint32(d[i+4 : i+8])
+		aux := f.ByteOrder.Uint32(d[i+8 : i+12])
+		next := f.ByteOrder.Uint32(d[i+12 : i+16])
+		file, _ := getString(str, int(fileoff))
+
+		var name string
+		j := i + int(aux)
+		for c := 0; c < int(cnt); c++ {
+			if j+16 > len(d) {
+				break
+			}
+			// hash := f.ByteOrder.Uint32(d[j:j+4])
+			// flags := f.ByteOrder.Uint16(d[j+4:j+6])
+			other := f.ByteOrder.Uint16(d[j+6 : j+8])
+			nameoff := f.ByteOrder.Uint32(d[j+8 : j+12])
+			next := f.ByteOrder.Uint32(d[j+12 : j+16])
+			name, _ = getString(str, int(nameoff))
+			ndx := int(other)
+			if ndx >= len(need) {
+				a := make([]verneed, 2*(ndx+1))
+				copy(a, need)
+				need = a
+			}
+
+			need[ndx] = verneed{file, name}
+			if next == 0 {
+				break
+			}
+			j += int(next)
+		}
+
+		if next == 0 {
+			break
+		}
+		i += int(next)
+	}
+
+	// Versym parallels symbol table, indexing into verneed.
+	vs := f.SectionByType(SHT_GNU_VERSYM)
+	if vs == nil {
+		return
+	}
+	d, _ = vs.Data()
+
+	f.gnuNeed = need
+	f.gnuVersym = d
+}
+
+// gnuVersion adds Library and Version information to sym,
+// which came from offset i of the symbol table.
+func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
+	// Each entry is two bytes.
+	i = (i + 1) * 2
+	if i >= len(f.gnuVersym) {
+		return
+	}
+	j := int(f.ByteOrder.Uint16(f.gnuVersym[i:]))
+	if j < 2 || j >= len(f.gnuNeed) {
+		return
+	}
+	n := &f.gnuNeed[j]
+	sym.Library = n.File
+	sym.Version = n.Name
+}
+
+// ImportedLibraries returns the names of all libraries
+// referred to by the binary f that are expected to be
+// linked with the binary at dynamic link time.
+func (f *File) ImportedLibraries() ([]string, error) {
+	return f.DynString(DT_NEEDED)
+}
+
+// DynString returns the strings listed for the given tag in the file's dynamic
+// section.
+//
+// The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or
+// DT_RUNPATH.
+func (f *File) DynString(tag DynTag) ([]string, error) {
+	switch tag {
+	case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH:
+	default:
+		return nil, fmt.Errorf("non-string-valued tag %v", tag)
+	}
+	ds := f.SectionByType(SHT_DYNAMIC)
+	if ds == nil {
+		// not dynamic, so no libraries
+		return nil, nil
+	}
+	d, err := ds.Data()
+	if err != nil {
+		return nil, err
+	}
+	str, err := f.stringTable(ds.Link)
+	if err != nil {
+		return nil, err
+	}
+	var all []string
+	for len(d) > 0 {
+		var t DynTag
+		var v uint64
+		switch f.Class {
+		case ELFCLASS32:
+			t = DynTag(f.ByteOrder.Uint32(d[0:4]))
+			v = uint64(f.ByteOrder.Uint32(d[4:8]))
+			d = d[8:]
+		case ELFCLASS64:
+			t = DynTag(f.ByteOrder.Uint64(d[0:8]))
+			v = f.ByteOrder.Uint64(d[8:16])
+			d = d[16:]
+		}
+		if t == tag {
+			s, ok := getString(str, int(v))
+			if ok {
+				all = append(all, s)
+			}
+		}
+	}
+	return all, nil
+}
diff --git a/third_party/gofrontend/libgo/go/debug/elf/file_test.go b/third_party/gofrontend/libgo/go/debug/elf/file_test.go
new file mode 100644
index 0000000..db83bad
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/file_test.go
@@ -0,0 +1,345 @@
+// 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 elf
+
+import (
+	"bytes"
+	"compress/gzip"
+	"debug/dwarf"
+	"encoding/binary"
+	"io"
+	"net"
+	"os"
+	"path"
+	"reflect"
+	"runtime"
+	"testing"
+)
+
+type fileTest struct {
+	file     string
+	hdr      FileHeader
+	sections []SectionHeader
+	progs    []ProgHeader
+	needed   []string
+}
+
+var fileTests = []fileTest{
+	{
+		"testdata/gcc-386-freebsd-exec",
+		FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc},
+		[]SectionHeader{
+			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0},
+			{".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4},
+			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10},
+			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0},
+			{".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8},
+			{".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0},
+			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4},
+			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0},
+			{".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0},
+			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0},
+			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0},
+			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0},
+			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8},
+			{".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0},
+			{".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0},
+			{".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0},
+			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4},
+			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0},
+			{".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0},
+			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0},
+			{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0},
+			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0},
+			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0},
+			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0},
+			{".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0},
+			{".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0},
+			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0},
+			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10},
+			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0},
+		},
+		[]ProgHeader{
+			{PT_PHDR, PF_R + PF_X, 0x34, 0x8048034, 0x8048034, 0xa0, 0xa0, 0x4},
+			{PT_INTERP, PF_R, 0xd4, 0x80480d4, 0x80480d4, 0x15, 0x15, 0x1},
+			{PT_LOAD, PF_R + PF_X, 0x0, 0x8048000, 0x8048000, 0x5fb, 0x5fb, 0x1000},
+			{PT_LOAD, PF_R + PF_W, 0x5fc, 0x80495fc, 0x80495fc, 0xd8, 0xf8, 0x1000},
+			{PT_DYNAMIC, PF_R + PF_W, 0x60c, 0x804960c, 0x804960c, 0x98, 0x98, 0x4},
+		},
+		[]string{"libc.so.6"},
+	},
+	{
+		"testdata/gcc-amd64-linux-exec",
+		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0},
+		[]SectionHeader{
+			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0},
+			{".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0},
+			{".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4},
+			{".gnu.hash", SHT_LOOS + 268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0},
+			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18},
+			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0},
+			{".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2},
+			{".gnu.version_r", SHT_LOOS + 268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0},
+			{".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18},
+			{".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18},
+			{".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0},
+			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10},
+			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0},
+			{".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0},
+			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0},
+			{".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0},
+			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0},
+			{".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0},
+			{".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0},
+			{".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0},
+			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10},
+			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8},
+			{".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8},
+			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0},
+			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0},
+			{".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0},
+			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0},
+			{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0},
+			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0},
+			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0},
+			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0},
+			{".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1},
+			{".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0},
+			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0},
+			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18},
+			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0},
+		},
+		[]ProgHeader{
+			{PT_PHDR, PF_R + PF_X, 0x40, 0x400040, 0x400040, 0x1c0, 0x1c0, 0x8},
+			{PT_INTERP, PF_R, 0x200, 0x400200, 0x400200, 0x1c, 0x1c, 1},
+			{PT_LOAD, PF_R + PF_X, 0x0, 0x400000, 0x400000, 0x684, 0x684, 0x200000},
+			{PT_LOAD, PF_R + PF_W, 0x688, 0x600688, 0x600688, 0x210, 0x218, 0x200000},
+			{PT_DYNAMIC, PF_R + PF_W, 0x6b0, 0x6006b0, 0x6006b0, 0x1a0, 0x1a0, 0x8},
+			{PT_NOTE, PF_R, 0x21c, 0x40021c, 0x40021c, 0x20, 0x20, 0x4},
+			{PT_LOOS + 0x474E550, PF_R, 0x5b8, 0x4005b8, 0x4005b8, 0x24, 0x24, 0x4},
+			{PT_LOOS + 0x474E551, PF_R + PF_W, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8},
+		},
+		[]string{"libc.so.6"},
+	},
+	{
+		"testdata/hello-world-core.gz",
+		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_CORE, EM_X86_64, 0x0},
+		[]SectionHeader{},
+		[]ProgHeader{
+			{Type: PT_NOTE, Flags: 0x0, Off: 0x3f8, Vaddr: 0x0, Paddr: 0x0, Filesz: 0x8ac, Memsz: 0x0, Align: 0x0},
+			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x1000, Vaddr: 0x400000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_R, Off: 0x1000, Vaddr: 0x401000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x2000, Vaddr: 0x402000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3000, Vaddr: 0x7f54078b8000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1b5000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: 0x0, Off: 0x3000, Vaddr: 0x7f5407a6d000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1ff000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_R, Off: 0x3000, Vaddr: 0x7f5407c6c000, Paddr: 0x0, Filesz: 0x4000, Memsz: 0x4000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x7000, Vaddr: 0x7f5407c70000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x9000, Vaddr: 0x7f5407c72000, Paddr: 0x0, Filesz: 0x5000, Memsz: 0x5000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0xe000, Vaddr: 0x7f5407c77000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x22000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0xe000, Vaddr: 0x7f5407e81000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x11000, Vaddr: 0x7f5407e96000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_R, Off: 0x14000, Vaddr: 0x7f5407e99000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x15000, Vaddr: 0x7f5407e9a000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x17000, Vaddr: 0x7fff79972000, Paddr: 0x0, Filesz: 0x23000, Memsz: 0x23000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3a000, Vaddr: 0x7fff799f8000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3b000, Vaddr: 0xffffffffff600000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
+		},
+		nil,
+	},
+}
+
+func TestOpen(t *testing.T) {
+	for i := range fileTests {
+		tt := &fileTests[i]
+
+		var f *File
+		var err error
+		if path.Ext(tt.file) == ".gz" {
+			var r io.ReaderAt
+			if r, err = decompress(tt.file); err == nil {
+				f, err = NewFile(r)
+			}
+		} else {
+			f, err = Open(tt.file)
+		}
+		defer f.Close()
+		if err != nil {
+			t.Errorf("cannot open file %s: %v", tt.file, err)
+			continue
+		}
+		if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
+			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
+			continue
+		}
+		for i, s := range f.Sections {
+			if i >= len(tt.sections) {
+				break
+			}
+			sh := &tt.sections[i]
+			if !reflect.DeepEqual(&s.SectionHeader, sh) {
+				t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &s.SectionHeader, sh)
+			}
+		}
+		for i, p := range f.Progs {
+			if i >= len(tt.progs) {
+				break
+			}
+			ph := &tt.progs[i]
+			if !reflect.DeepEqual(&p.ProgHeader, ph) {
+				t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &p.ProgHeader, ph)
+			}
+		}
+		tn := len(tt.sections)
+		fn := len(f.Sections)
+		if tn != fn {
+			t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
+		}
+		tn = len(tt.progs)
+		fn = len(f.Progs)
+		if tn != fn {
+			t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn)
+		}
+		tl := tt.needed
+		fl, err := f.ImportedLibraries()
+		if err != nil {
+			t.Error(err)
+		}
+		if !reflect.DeepEqual(tl, fl) {
+			t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl)
+		}
+	}
+}
+
+// elf.NewFile requires io.ReaderAt, which compress/gzip cannot
+// provide. Decompress the file to a bytes.Reader.
+func decompress(gz string) (io.ReaderAt, error) {
+	in, err := os.Open(gz)
+	if err != nil {
+		return nil, err
+	}
+	defer in.Close()
+	r, err := gzip.NewReader(in)
+	if err != nil {
+		return nil, err
+	}
+	var out bytes.Buffer
+	_, err = io.Copy(&out, r)
+	return bytes.NewReader(out.Bytes()), err
+}
+
+type relocationTestEntry struct {
+	entryNumber int
+	entry       *dwarf.Entry
+}
+
+type relocationTest struct {
+	file    string
+	entries []relocationTestEntry
+}
+
+var relocationTests = []relocationTest{
+	{
+		"testdata/go-relocation-test-gcc441-x86-64.obj",
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x6)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
+		},
+	},
+	{
+		"testdata/go-relocation-test-gcc441-x86.obj",
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "t.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x5)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
+		},
+	},
+	{
+		"testdata/go-relocation-test-gcc424-x86-64.obj",
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x6)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
+		},
+	},
+	{
+		"testdata/go-relocation-test-gcc482-ppc64le.obj",
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector"}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(1)}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c"}, dwarf.Field{Attr: dwarf.AttrCompDir, Val: "/tmp"}, dwarf.Field{Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, dwarf.Field{Attr: dwarf.AttrHighpc, Val: uint64(0x24)}, dwarf.Field{Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
+		},
+	},
+	{
+		"testdata/go-relocation-test-clang-x86.obj",
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)"}, {Attr: dwarf.AttrLanguage, Val: int64(12)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c"}, {Attr: dwarf.AttrStmtList, Val: int64(0)}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}}}},
+		},
+	},
+	{
+		"testdata/gcc-amd64-openbsd-debug-with-rela.obj",
+		[]relocationTestEntry{
+			{203, &dwarf.Entry{Offset: 0xc62, Tag: dwarf.TagMember, Children: false, Field: []dwarf.Field{{Attr: dwarf.AttrName, Val: "it_interval"}, {Attr: dwarf.AttrDeclFile, Val: int64(7)}, {Attr: dwarf.AttrDeclLine, Val: int64(236)}, {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f)}, {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}}}}},
+			{204, &dwarf.Entry{Offset: 0xc70, Tag: dwarf.TagMember, Children: false, Field: []dwarf.Field{{Attr: dwarf.AttrName, Val: "it_value"}, {Attr: dwarf.AttrDeclFile, Val: int64(7)}, {Attr: dwarf.AttrDeclLine, Val: int64(237)}, {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f)}, {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}}}}},
+		},
+	},
+}
+
+func TestDWARFRelocations(t *testing.T) {
+	for i, test := range relocationTests {
+		f, err := Open(test.file)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		dwarf, err := f.DWARF()
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		for _, testEntry := range test.entries {
+			reader := dwarf.Reader()
+			for j := 0; j < testEntry.entryNumber; j++ {
+				entry, err := reader.Next()
+				if entry == nil || err != nil {
+					t.Errorf("Failed to skip to entry %d: %v", testEntry.entryNumber, err)
+					continue
+				}
+			}
+			entry, err := reader.Next()
+			if err != nil {
+				t.Error(err)
+				continue
+			}
+			if !reflect.DeepEqual(testEntry.entry, entry) {
+				t.Errorf("#%d/%d: mismatch: got:%#v want:%#v", i, testEntry.entryNumber, entry, testEntry.entry)
+				continue
+			}
+		}
+	}
+}
+
+func TestNoSectionOverlaps(t *testing.T) {
+	// Ensure 6l outputs sections without overlaps.
+	if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" {
+		return // not ELF
+	}
+	_ = net.ResolveIPAddr // force dynamic linkage
+	f, err := Open(os.Args[0])
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	for i, si := range f.Sections {
+		sih := si.SectionHeader
+		if sih.Type == SHT_NOBITS {
+			continue
+		}
+		for j, sj := range f.Sections {
+			sjh := sj.SectionHeader
+			if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 {
+				continue
+			}
+			if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.Size {
+				t.Errorf("ld produced ELF with section %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
+					sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.Size, sjh.Offset+sjh.Size)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/elf/testdata/gcc-386-freebsd-exec b/third_party/gofrontend/libgo/go/debug/elf/testdata/gcc-386-freebsd-exec
new file mode 100755
index 0000000..7af9c58
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/testdata/gcc-386-freebsd-exec
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/elf/testdata/gcc-amd64-linux-exec b/third_party/gofrontend/libgo/go/debug/elf/testdata/gcc-amd64-linux-exec
new file mode 100755
index 0000000..c6cb1de
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/testdata/gcc-amd64-linux-exec
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj b/third_party/gofrontend/libgo/go/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj
new file mode 100644
index 0000000..f62b1ea
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-clang-x86.obj b/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-clang-x86.obj
new file mode 100644
index 0000000..e909cf4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-clang-x86.obj
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj b/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj
new file mode 100644
index 0000000..a7c6d6e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj b/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj
new file mode 100644
index 0000000..2d37ab6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc441-x86.obj b/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc441-x86.obj
new file mode 100644
index 0000000..0d59fe3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc441-x86.obj
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj b/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj
new file mode 100644
index 0000000..dad7445
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/elf/testdata/hello-world-core.gz b/third_party/gofrontend/libgo/go/debug/elf/testdata/hello-world-core.gz
new file mode 100644
index 0000000..806af6e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/testdata/hello-world-core.gz
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/elf/testdata/hello.c b/third_party/gofrontend/libgo/go/debug/elf/testdata/hello.c
new file mode 100644
index 0000000..34d9ee7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/elf/testdata/hello.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+main(int argc, char *argv[])
+{
+	printf("hello, world\n");
+}
diff --git a/third_party/gofrontend/libgo/go/debug/gosym/pclinetest.h b/third_party/gofrontend/libgo/go/debug/gosym/pclinetest.h
new file mode 100644
index 0000000..a6c40e7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/gosym/pclinetest.h
@@ -0,0 +1,7 @@
+// Empty include file to generate z symbols
+
+
+
+
+
+// EOF
diff --git a/third_party/gofrontend/libgo/go/debug/gosym/pclinetest.s b/third_party/gofrontend/libgo/go/debug/gosym/pclinetest.s
new file mode 100644
index 0000000..519656b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/gosym/pclinetest.s
@@ -0,0 +1,89 @@
+TEXT linefrompc(SB),7,$0	// Each byte stores its line delta
+BYTE $2;
+BYTE $1;
+BYTE $1; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1;
+BYTE $1;
+BYTE $1; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+BYTE $1; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+#include "pclinetest.h"
+BYTE $2;
+#include "pclinetest.h"
+BYTE $2;
+
+TEXT pcfromline(SB),7,$0	// Each record stores its line delta, then n, then n more bytes
+BYTE $31; BYTE $0;
+BYTE $1; BYTE $1; BYTE $0;
+BYTE $1; BYTE $0;
+
+BYTE $2; BYTE $4; BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+
+
+#include "pclinetest.h"
+BYTE $4; BYTE $0;
+
+
+BYTE $3; BYTE $3; BYTE $0; BYTE $0; BYTE $0;
+#include "pclinetest.h"
+
+
+BYTE $4; BYTE $3; BYTE $0; BYTE $0; BYTE $0;
+
+TEXT main(SB),7,$0
+	// Prevent GC of our test symbols
+	CALL linefrompc(SB)
+	CALL pcfromline(SB)
+
+// Keep the linker happy
+TEXT runtime·morestack(SB),7,$0
+	RET
+
+TEXT runtime·morestack00(SB),7,$0
+	RET
+
+TEXT runtime·morestack10(SB),7,$0
+	RET
+
+TEXT runtime·morestack01(SB),7,$0
+	RET
+
+TEXT runtime·morestack11(SB),7,$0
+	RET
+
+TEXT runtime·morestack8(SB),7,$0
+	RET
+
+TEXT runtime·morestack16(SB),7,$0
+	RET
+
+TEXT runtime·morestack24(SB),7,$0
+	RET
+
+TEXT runtime·morestack32(SB),7,$0
+	RET
+
+TEXT runtime·morestack40(SB),7,$0
+	RET
+
+TEXT runtime·morestack48(SB),7,$0
+	RET
+
+TEXT runtime·morestack8(SB),7,$0
+	RET
+
diff --git a/third_party/gofrontend/libgo/go/debug/gosym/pclntab.go b/third_party/gofrontend/libgo/go/debug/gosym/pclntab.go
new file mode 100644
index 0000000..6620aef
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/gosym/pclntab.go
@@ -0,0 +1,453 @@
+// 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.
+
+/*
+ * Line tables
+ */
+
+package gosym
+
+import (
+	"encoding/binary"
+	"sync"
+)
+
+// A LineTable is a data structure mapping program counters to line numbers.
+//
+// In Go 1.1 and earlier, each function (represented by a Func) had its own LineTable,
+// and the line number corresponded to a numbering of all source lines in the
+// program, across all files. That absolute line number would then have to be
+// converted separately to a file name and line number within the file.
+//
+// In Go 1.2, the format of the data changed so that there is a single LineTable
+// for the entire program, shared by all Funcs, and there are no absolute line
+// numbers, just line numbers within specific files.
+//
+// For the most part, LineTable's methods should be treated as an internal
+// detail of the package; callers should use the methods on Table instead.
+type LineTable struct {
+	Data []byte
+	PC   uint64
+	Line int
+
+	// Go 1.2 state
+	mu       sync.Mutex
+	go12     int // is this in Go 1.2 format? -1 no, 0 unknown, 1 yes
+	binary   binary.ByteOrder
+	quantum  uint32
+	ptrsize  uint32
+	functab  []byte
+	nfunctab uint32
+	filetab  []byte
+	nfiletab uint32
+	fileMap  map[string]uint32
+}
+
+// NOTE(rsc): This is wrong for GOARCH=arm, which uses a quantum of 4,
+// but we have no idea whether we're using arm or not. This only
+// matters in the old (pre-Go 1.2) symbol table format, so it's not worth
+// fixing.
+const oldQuantum = 1
+
+func (t *LineTable) parse(targetPC uint64, targetLine int) (b []byte, pc uint64, line int) {
+	// The PC/line table can be thought of as a sequence of
+	//  <pc update>* <line update>
+	// batches.  Each update batch results in a (pc, line) pair,
+	// where line applies to every PC from pc up to but not
+	// including the pc of the next pair.
+	//
+	// Here we process each update individually, which simplifies
+	// the code, but makes the corner cases more confusing.
+	b, pc, line = t.Data, t.PC, t.Line
+	for pc <= targetPC && line != targetLine && len(b) > 0 {
+		code := b[0]
+		b = b[1:]
+		switch {
+		case code == 0:
+			if len(b) < 4 {
+				b = b[0:0]
+				break
+			}
+			val := binary.BigEndian.Uint32(b)
+			b = b[4:]
+			line += int(val)
+		case code <= 64:
+			line += int(code)
+		case code <= 128:
+			line -= int(code - 64)
+		default:
+			pc += oldQuantum * uint64(code-128)
+			continue
+		}
+		pc += oldQuantum
+	}
+	return b, pc, line
+}
+
+func (t *LineTable) slice(pc uint64) *LineTable {
+	data, pc, line := t.parse(pc, -1)
+	return &LineTable{Data: data, PC: pc, Line: line}
+}
+
+// PCToLine returns the line number for the given program counter.
+// Callers should use Table's PCToLine method instead.
+func (t *LineTable) PCToLine(pc uint64) int {
+	if t.isGo12() {
+		return t.go12PCToLine(pc)
+	}
+	_, _, line := t.parse(pc, -1)
+	return line
+}
+
+// LineToPC returns the program counter for the given line number,
+// considering only program counters before maxpc.
+// Callers should use Table's LineToPC method instead.
+func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 {
+	if t.isGo12() {
+		return 0
+	}
+	_, pc, line1 := t.parse(maxpc, line)
+	if line1 != line {
+		return 0
+	}
+	// Subtract quantum from PC to account for post-line increment
+	return pc - oldQuantum
+}
+
+// NewLineTable returns a new PC/line table
+// corresponding to the encoded data.
+// Text must be the start address of the
+// corresponding text segment.
+func NewLineTable(data []byte, text uint64) *LineTable {
+	return &LineTable{Data: data, PC: text, Line: 0}
+}
+
+// Go 1.2 symbol table format.
+// See golang.org/s/go12symtab.
+//
+// A general note about the methods here: rather than try to avoid
+// index out of bounds errors, we trust Go to detect them, and then
+// we recover from the panics and treat them as indicative of a malformed
+// or incomplete table.
+//
+// The methods called by symtab.go, which begin with "go12" prefixes,
+// are expected to have that recovery logic.
+
+// isGo12 reports whether this is a Go 1.2 (or later) symbol table.
+func (t *LineTable) isGo12() bool {
+	t.go12Init()
+	return t.go12 == 1
+}
+
+const go12magic = 0xfffffffb
+
+// uintptr returns the pointer-sized value encoded at b.
+// The pointer size is dictated by the table being read.
+func (t *LineTable) uintptr(b []byte) uint64 {
+	if t.ptrsize == 4 {
+		return uint64(t.binary.Uint32(b))
+	}
+	return t.binary.Uint64(b)
+}
+
+// go12init initializes the Go 1.2 metadata if t is a Go 1.2 symbol table.
+func (t *LineTable) go12Init() {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	if t.go12 != 0 {
+		return
+	}
+
+	defer func() {
+		// If we panic parsing, assume it's not a Go 1.2 symbol table.
+		recover()
+	}()
+
+	// Check header: 4-byte magic, two zeros, pc quantum, pointer size.
+	t.go12 = -1 // not Go 1.2 until proven otherwise
+	if len(t.Data) < 16 || t.Data[4] != 0 || t.Data[5] != 0 ||
+		(t.Data[6] != 1 && t.Data[6] != 4) || // pc quantum
+		(t.Data[7] != 4 && t.Data[7] != 8) { // pointer size
+		return
+	}
+
+	switch uint32(go12magic) {
+	case binary.LittleEndian.Uint32(t.Data):
+		t.binary = binary.LittleEndian
+	case binary.BigEndian.Uint32(t.Data):
+		t.binary = binary.BigEndian
+	default:
+		return
+	}
+
+	t.quantum = uint32(t.Data[6])
+	t.ptrsize = uint32(t.Data[7])
+
+	t.nfunctab = uint32(t.uintptr(t.Data[8:]))
+	t.functab = t.Data[8+t.ptrsize:]
+	functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize
+	fileoff := t.binary.Uint32(t.functab[functabsize:])
+	t.functab = t.functab[:functabsize]
+	t.filetab = t.Data[fileoff:]
+	t.nfiletab = t.binary.Uint32(t.filetab)
+	t.filetab = t.filetab[:t.nfiletab*4]
+
+	t.go12 = 1 // so far so good
+}
+
+// go12Funcs returns a slice of Funcs derived from the Go 1.2 pcln table.
+func (t *LineTable) go12Funcs() []Func {
+	// Assume it is malformed and return nil on error.
+	defer func() {
+		recover()
+	}()
+
+	n := len(t.functab) / int(t.ptrsize) / 2
+	funcs := make([]Func, n)
+	for i := range funcs {
+		f := &funcs[i]
+		f.Entry = uint64(t.uintptr(t.functab[2*i*int(t.ptrsize):]))
+		f.End = uint64(t.uintptr(t.functab[(2*i+2)*int(t.ptrsize):]))
+		info := t.Data[t.uintptr(t.functab[(2*i+1)*int(t.ptrsize):]):]
+		f.LineTable = t
+		f.FrameSize = int(t.binary.Uint32(info[t.ptrsize+2*4:]))
+		f.Sym = &Sym{
+			Value:  f.Entry,
+			Type:   'T',
+			Name:   t.string(t.binary.Uint32(info[t.ptrsize:])),
+			GoType: 0,
+			Func:   f,
+		}
+	}
+	return funcs
+}
+
+// findFunc returns the func corresponding to the given program counter.
+func (t *LineTable) findFunc(pc uint64) []byte {
+	if pc < t.uintptr(t.functab) || pc >= t.uintptr(t.functab[len(t.functab)-int(t.ptrsize):]) {
+		return nil
+	}
+
+	// The function table is a list of 2*nfunctab+1 uintptrs,
+	// alternating program counters and offsets to func structures.
+	f := t.functab
+	nf := t.nfunctab
+	for nf > 0 {
+		m := nf / 2
+		fm := f[2*t.ptrsize*m:]
+		if t.uintptr(fm) <= pc && pc < t.uintptr(fm[2*t.ptrsize:]) {
+			return t.Data[t.uintptr(fm[t.ptrsize:]):]
+		} else if pc < t.uintptr(fm) {
+			nf = m
+		} else {
+			f = f[(m+1)*2*t.ptrsize:]
+			nf -= m + 1
+		}
+	}
+	return nil
+}
+
+// readvarint reads, removes, and returns a varint from *pp.
+func (t *LineTable) readvarint(pp *[]byte) uint32 {
+	var v, shift uint32
+	p := *pp
+	for shift = 0; ; shift += 7 {
+		b := p[0]
+		p = p[1:]
+		v |= (uint32(b) & 0x7F) << shift
+		if b&0x80 == 0 {
+			break
+		}
+	}
+	*pp = p
+	return v
+}
+
+// string returns a Go string found at off.
+func (t *LineTable) string(off uint32) string {
+	for i := off; ; i++ {
+		if t.Data[i] == 0 {
+			return string(t.Data[off:i])
+		}
+	}
+}
+
+// step advances to the next pc, value pair in the encoded table.
+func (t *LineTable) step(p *[]byte, pc *uint64, val *int32, first bool) bool {
+	uvdelta := t.readvarint(p)
+	if uvdelta == 0 && !first {
+		return false
+	}
+	if uvdelta&1 != 0 {
+		uvdelta = ^(uvdelta >> 1)
+	} else {
+		uvdelta >>= 1
+	}
+	vdelta := int32(uvdelta)
+	pcdelta := t.readvarint(p) * t.quantum
+	*pc += uint64(pcdelta)
+	*val += vdelta
+	return true
+}
+
+// pcvalue reports the value associated with the target pc.
+// off is the offset to the beginning of the pc-value table,
+// and entry is the start PC for the corresponding function.
+func (t *LineTable) pcvalue(off uint32, entry, targetpc uint64) int32 {
+	if off == 0 {
+		return -1
+	}
+	p := t.Data[off:]
+
+	val := int32(-1)
+	pc := entry
+	for t.step(&p, &pc, &val, pc == entry) {
+		if targetpc < pc {
+			return val
+		}
+	}
+	return -1
+}
+
+// findFileLine scans one function in the binary looking for a
+// program counter in the given file on the given line.
+// It does so by running the pc-value tables mapping program counter
+// to file number. Since most functions come from a single file, these
+// are usually short and quick to scan. If a file match is found, then the
+// code goes to the expense of looking for a simultaneous line number match.
+func (t *LineTable) findFileLine(entry uint64, filetab, linetab uint32, filenum, line int32) uint64 {
+	if filetab == 0 || linetab == 0 {
+		return 0
+	}
+
+	fp := t.Data[filetab:]
+	fl := t.Data[linetab:]
+	fileVal := int32(-1)
+	filePC := entry
+	lineVal := int32(-1)
+	linePC := entry
+	fileStartPC := filePC
+	for t.step(&fp, &filePC, &fileVal, filePC == entry) {
+		if fileVal == filenum && fileStartPC < filePC {
+			// fileVal is in effect starting at fileStartPC up to
+			// but not including filePC, and it's the file we want.
+			// Run the PC table looking for a matching line number
+			// or until we reach filePC.
+			lineStartPC := linePC
+			for linePC < filePC && t.step(&fl, &linePC, &lineVal, linePC == entry) {
+				// lineVal is in effect until linePC, and lineStartPC < filePC.
+				if lineVal == line {
+					if fileStartPC <= lineStartPC {
+						return lineStartPC
+					}
+					if fileStartPC < linePC {
+						return fileStartPC
+					}
+				}
+				lineStartPC = linePC
+			}
+		}
+		fileStartPC = filePC
+	}
+	return 0
+}
+
+// go12PCToLine maps program counter to line number for the Go 1.2 pcln table.
+func (t *LineTable) go12PCToLine(pc uint64) (line int) {
+	defer func() {
+		if recover() != nil {
+			line = -1
+		}
+	}()
+
+	f := t.findFunc(pc)
+	if f == nil {
+		return -1
+	}
+	entry := t.uintptr(f)
+	linetab := t.binary.Uint32(f[t.ptrsize+5*4:])
+	return int(t.pcvalue(linetab, entry, pc))
+}
+
+// go12PCToFile maps program counter to file name for the Go 1.2 pcln table.
+func (t *LineTable) go12PCToFile(pc uint64) (file string) {
+	defer func() {
+		if recover() != nil {
+			file = ""
+		}
+	}()
+
+	f := t.findFunc(pc)
+	if f == nil {
+		return ""
+	}
+	entry := t.uintptr(f)
+	filetab := t.binary.Uint32(f[t.ptrsize+4*4:])
+	fno := t.pcvalue(filetab, entry, pc)
+	if fno <= 0 {
+		return ""
+	}
+	return t.string(t.binary.Uint32(t.filetab[4*fno:]))
+}
+
+// go12LineToPC maps a (file, line) pair to a program counter for the Go 1.2 pcln table.
+func (t *LineTable) go12LineToPC(file string, line int) (pc uint64) {
+	defer func() {
+		if recover() != nil {
+			pc = 0
+		}
+	}()
+
+	t.initFileMap()
+	filenum := t.fileMap[file]
+	if filenum == 0 {
+		return 0
+	}
+
+	// Scan all functions.
+	// If this turns out to be a bottleneck, we could build a map[int32][]int32
+	// mapping file number to a list of functions with code from that file.
+	for i := uint32(0); i < t.nfunctab; i++ {
+		f := t.Data[t.uintptr(t.functab[2*t.ptrsize*i+t.ptrsize:]):]
+		entry := t.uintptr(f)
+		filetab := t.binary.Uint32(f[t.ptrsize+4*4:])
+		linetab := t.binary.Uint32(f[t.ptrsize+5*4:])
+		pc := t.findFileLine(entry, filetab, linetab, int32(filenum), int32(line))
+		if pc != 0 {
+			return pc
+		}
+	}
+	return 0
+}
+
+// initFileMap initializes the map from file name to file number.
+func (t *LineTable) initFileMap() {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+
+	if t.fileMap != nil {
+		return
+	}
+	m := make(map[string]uint32)
+
+	for i := uint32(1); i < t.nfiletab; i++ {
+		s := t.string(t.binary.Uint32(t.filetab[4*i:]))
+		m[s] = i
+	}
+	t.fileMap = m
+}
+
+// go12MapFiles adds to m a key for every file in the Go 1.2 LineTable.
+// Every key maps to obj. That's not a very interesting map, but it provides
+// a way for callers to obtain the list of files in the program.
+func (t *LineTable) go12MapFiles(m map[string]*Obj, obj *Obj) {
+	defer func() {
+		recover()
+	}()
+
+	t.initFileMap()
+	for file := range t.fileMap {
+		m[file] = obj
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/gosym/pclntab_test.go b/third_party/gofrontend/libgo/go/debug/gosym/pclntab_test.go
new file mode 100644
index 0000000..35502e8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/gosym/pclntab_test.go
@@ -0,0 +1,274 @@
+// 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 gosym
+
+import (
+	"debug/elf"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+var (
+	pclineTempDir    string
+	pclinetestBinary string
+)
+
+func dotest(self bool) bool {
+	// For now, only works on amd64 platforms.
+	if runtime.GOARCH != "amd64" {
+		return false
+	}
+	// Self test reads test binary; only works on Linux.
+	if self && runtime.GOOS != "linux" {
+		return false
+	}
+	// Command below expects "sh", so Unix.
+	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+		return false
+	}
+	if pclinetestBinary != "" {
+		return true
+	}
+	var err error
+	pclineTempDir, err = ioutil.TempDir("", "pclinetest")
+	if err != nil {
+		panic(err)
+	}
+	if strings.Contains(pclineTempDir, " ") {
+		panic("unexpected space in tempdir")
+	}
+	// This command builds pclinetest from pclinetest.asm;
+	// the resulting binary looks like it was built from pclinetest.s,
+	// but we have renamed it to keep it away from the go tool.
+	pclinetestBinary = filepath.Join(pclineTempDir, "pclinetest")
+	command := fmt.Sprintf("go tool 6a -o %s.6 pclinetest.asm && go tool 6l -H linux -E main -o %s %s.6",
+		pclinetestBinary, pclinetestBinary, pclinetestBinary)
+	cmd := exec.Command("sh", "-c", command)
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	if err := cmd.Run(); err != nil {
+		panic(err)
+	}
+	return true
+}
+
+func endtest() {
+	if pclineTempDir != "" {
+		os.RemoveAll(pclineTempDir)
+		pclineTempDir = ""
+		pclinetestBinary = ""
+	}
+}
+
+func getTable(t *testing.T) *Table {
+	f, tab := crack(os.Args[0], t)
+	f.Close()
+	return tab
+}
+
+func crack(file string, t *testing.T) (*elf.File, *Table) {
+	// Open self
+	f, err := elf.Open(file)
+	if err != nil {
+		t.Fatal(err)
+	}
+	return parse(file, f, t)
+}
+
+func parse(file string, f *elf.File, t *testing.T) (*elf.File, *Table) {
+	symdat, err := f.Section(".gosymtab").Data()
+	if err != nil {
+		f.Close()
+		t.Fatalf("reading %s gosymtab: %v", file, err)
+	}
+	pclndat, err := f.Section(".gopclntab").Data()
+	if err != nil {
+		f.Close()
+		t.Fatalf("reading %s gopclntab: %v", file, err)
+	}
+
+	pcln := NewLineTable(pclndat, f.Section(".text").Addr)
+	tab, err := NewTable(symdat, pcln)
+	if err != nil {
+		f.Close()
+		t.Fatalf("parsing %s gosymtab: %v", file, err)
+	}
+
+	return f, tab
+}
+
+var goarch = os.Getenv("O")
+
+func TestLineFromAline(t *testing.T) {
+	if !dotest(true) {
+		return
+	}
+	defer endtest()
+
+	tab := getTable(t)
+	if tab.go12line != nil {
+		// aline's don't exist in the Go 1.2 table.
+		t.Skip("not relevant to Go 1.2 symbol table")
+	}
+
+	// Find the sym package
+	pkg := tab.LookupFunc("debug/gosym.TestLineFromAline").Obj
+	if pkg == nil {
+		t.Fatalf("nil pkg")
+	}
+
+	// Walk every absolute line and ensure that we hit every
+	// source line monotonically
+	lastline := make(map[string]int)
+	final := -1
+	for i := 0; i < 10000; i++ {
+		path, line := pkg.lineFromAline(i)
+		// Check for end of object
+		if path == "" {
+			if final == -1 {
+				final = i - 1
+			}
+			continue
+		} else if final != -1 {
+			t.Fatalf("reached end of package at absolute line %d, but absolute line %d mapped to %s:%d", final, i, path, line)
+		}
+		// It's okay to see files multiple times (e.g., sys.a)
+		if line == 1 {
+			lastline[path] = 1
+			continue
+		}
+		// Check that the is the next line in path
+		ll, ok := lastline[path]
+		if !ok {
+			t.Errorf("file %s starts on line %d", path, line)
+		} else if line != ll+1 {
+			t.Fatalf("expected next line of file %s to be %d, got %d", path, ll+1, line)
+		}
+		lastline[path] = line
+	}
+	if final == -1 {
+		t.Errorf("never reached end of object")
+	}
+}
+
+func TestLineAline(t *testing.T) {
+	if !dotest(true) {
+		return
+	}
+	defer endtest()
+
+	tab := getTable(t)
+	if tab.go12line != nil {
+		// aline's don't exist in the Go 1.2 table.
+		t.Skip("not relevant to Go 1.2 symbol table")
+	}
+
+	for _, o := range tab.Files {
+		// A source file can appear multiple times in a
+		// object.  alineFromLine will always return alines in
+		// the first file, so track which lines we've seen.
+		found := make(map[string]int)
+		for i := 0; i < 1000; i++ {
+			path, line := o.lineFromAline(i)
+			if path == "" {
+				break
+			}
+
+			// cgo files are full of 'Z' symbols, which we don't handle
+			if len(path) > 4 && path[len(path)-4:] == ".cgo" {
+				continue
+			}
+
+			if minline, ok := found[path]; path != "" && ok {
+				if minline >= line {
+					// We've already covered this file
+					continue
+				}
+			}
+			found[path] = line
+
+			a, err := o.alineFromLine(path, line)
+			if err != nil {
+				t.Errorf("absolute line %d in object %s maps to %s:%d, but mapping that back gives error %s", i, o.Paths[0].Name, path, line, err)
+			} else if a != i {
+				t.Errorf("absolute line %d in object %s maps to %s:%d, which maps back to absolute line %d\n", i, o.Paths[0].Name, path, line, a)
+			}
+		}
+	}
+}
+
+func TestPCLine(t *testing.T) {
+	if !dotest(false) {
+		return
+	}
+	defer endtest()
+
+	f, tab := crack(pclinetestBinary, t)
+	text := f.Section(".text")
+	textdat, err := text.Data()
+	if err != nil {
+		t.Fatalf("reading .text: %v", err)
+	}
+
+	// Test PCToLine
+	sym := tab.LookupFunc("linefrompc")
+	wantLine := 0
+	for pc := sym.Entry; pc < sym.End; pc++ {
+		off := pc - text.Addr // TODO(rsc): should not need off; bug in 8g
+		if textdat[off] == 255 {
+			break
+		}
+		wantLine += int(textdat[off])
+		t.Logf("off is %d %#x (max %d)", off, textdat[off], sym.End-pc)
+		file, line, fn := tab.PCToLine(pc)
+		if fn == nil {
+			t.Errorf("failed to get line of PC %#x", pc)
+		} else if !strings.HasSuffix(file, "pclinetest.asm") || line != wantLine || fn != sym {
+			t.Errorf("PCToLine(%#x) = %s:%d (%s), want %s:%d (%s)", pc, file, line, fn.Name, "pclinetest.asm", wantLine, sym.Name)
+		}
+	}
+
+	// Test LineToPC
+	sym = tab.LookupFunc("pcfromline")
+	lookupline := -1
+	wantLine = 0
+	off := uint64(0) // TODO(rsc): should not need off; bug in 8g
+	for pc := sym.Value; pc < sym.End; pc += 2 + uint64(textdat[off]) {
+		file, line, fn := tab.PCToLine(pc)
+		off = pc - text.Addr
+		if textdat[off] == 255 {
+			break
+		}
+		wantLine += int(textdat[off])
+		if line != wantLine {
+			t.Errorf("expected line %d at PC %#x in pcfromline, got %d", wantLine, pc, line)
+			off = pc + 1 - text.Addr
+			continue
+		}
+		if lookupline == -1 {
+			lookupline = line
+		}
+		for ; lookupline <= line; lookupline++ {
+			pc2, fn2, err := tab.LineToPC(file, lookupline)
+			if lookupline != line {
+				// Should be nothing on this line
+				if err == nil {
+					t.Errorf("expected no PC at line %d, got %#x (%s)", lookupline, pc2, fn2.Name)
+				}
+			} else if err != nil {
+				t.Errorf("failed to get PC of line %d: %s", lookupline, err)
+			} else if pc != pc2 {
+				t.Errorf("expected PC %#x (%s) at line %d, got PC %#x (%s)", pc, fn.Name, line, pc2, fn2.Name)
+			}
+		}
+		off = pc + 1 - text.Addr
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/gosym/symtab.go b/third_party/gofrontend/libgo/go/debug/gosym/symtab.go
new file mode 100644
index 0000000..3864e3c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/gosym/symtab.go
@@ -0,0 +1,710 @@
+// 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 gosym implements access to the Go symbol
+// and line number tables embedded in Go binaries generated
+// by the gc compilers.
+package gosym
+
+// The table format is a variant of the format used in Plan 9's a.out
+// format, documented at http://plan9.bell-labs.com/magic/man2html/6/a.out.
+// The best reference for the differences between the Plan 9 format
+// and the Go format is the runtime source, specifically ../../runtime/symtab.c.
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+/*
+ * Symbols
+ */
+
+// A Sym represents a single symbol table entry.
+type Sym struct {
+	Value  uint64
+	Type   byte
+	Name   string
+	GoType uint64
+	// If this symbol if a function symbol, the corresponding Func
+	Func *Func
+}
+
+// Static reports whether this symbol is static (not visible outside its file).
+func (s *Sym) Static() bool { return s.Type >= 'a' }
+
+// PackageName returns the package part of the symbol name,
+// or the empty string if there is none.
+func (s *Sym) PackageName() string {
+	if i := strings.Index(s.Name, "."); i != -1 {
+		return s.Name[0:i]
+	}
+	return ""
+}
+
+// ReceiverName returns the receiver type name of this symbol,
+// or the empty string if there is none.
+func (s *Sym) ReceiverName() string {
+	l := strings.Index(s.Name, ".")
+	r := strings.LastIndex(s.Name, ".")
+	if l == -1 || r == -1 || l == r {
+		return ""
+	}
+	return s.Name[l+1 : r]
+}
+
+// BaseName returns the symbol name without the package or receiver name.
+func (s *Sym) BaseName() string {
+	if i := strings.LastIndex(s.Name, "."); i != -1 {
+		return s.Name[i+1:]
+	}
+	return s.Name
+}
+
+// A Func collects information about a single function.
+type Func struct {
+	Entry uint64
+	*Sym
+	End       uint64
+	Params    []*Sym
+	Locals    []*Sym
+	FrameSize int
+	LineTable *LineTable
+	Obj       *Obj
+}
+
+// An Obj represents a collection of functions in a symbol table.
+//
+// The exact method of division of a binary into separate Objs is an internal detail
+// of the symbol table format.
+//
+// In early versions of Go each source file became a different Obj.
+//
+// In Go 1 and Go 1.1, each package produced one Obj for all Go sources
+// and one Obj per C source file.
+//
+// In Go 1.2, there is a single Obj for the entire program.
+type Obj struct {
+	// Funcs is a list of functions in the Obj.
+	Funcs []Func
+
+	// In Go 1.1 and earlier, Paths is a list of symbols corresponding
+	// to the source file names that produced the Obj.
+	// In Go 1.2, Paths is nil.
+	// Use the keys of Table.Files to obtain a list of source files.
+	Paths []Sym // meta
+}
+
+/*
+ * Symbol tables
+ */
+
+// Table represents a Go symbol table.  It stores all of the
+// symbols decoded from the program and provides methods to translate
+// between symbols, names, and addresses.
+type Table struct {
+	Syms  []Sym
+	Funcs []Func
+	Files map[string]*Obj // nil for Go 1.2 and later binaries
+	Objs  []Obj           // nil for Go 1.2 and later binaries
+
+	go12line *LineTable // Go 1.2 line number table
+}
+
+type sym struct {
+	value  uint64
+	gotype uint64
+	typ    byte
+	name   []byte
+}
+
+var (
+	littleEndianSymtab    = []byte{0xFD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00}
+	bigEndianSymtab       = []byte{0xFF, 0xFF, 0xFF, 0xFD, 0x00, 0x00, 0x00}
+	oldLittleEndianSymtab = []byte{0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00}
+)
+
+func walksymtab(data []byte, fn func(sym) error) error {
+	if len(data) == 0 { // missing symtab is okay
+		return nil
+	}
+	var order binary.ByteOrder = binary.BigEndian
+	newTable := false
+	switch {
+	case bytes.HasPrefix(data, oldLittleEndianSymtab):
+		// Same as Go 1.0, but little endian.
+		// Format was used during interim development between Go 1.0 and Go 1.1.
+		// Should not be widespread, but easy to support.
+		data = data[6:]
+		order = binary.LittleEndian
+	case bytes.HasPrefix(data, bigEndianSymtab):
+		newTable = true
+	case bytes.HasPrefix(data, littleEndianSymtab):
+		newTable = true
+		order = binary.LittleEndian
+	}
+	var ptrsz int
+	if newTable {
+		if len(data) < 8 {
+			return &DecodingError{len(data), "unexpected EOF", nil}
+		}
+		ptrsz = int(data[7])
+		if ptrsz != 4 && ptrsz != 8 {
+			return &DecodingError{7, "invalid pointer size", ptrsz}
+		}
+		data = data[8:]
+	}
+	var s sym
+	p := data
+	for len(p) >= 4 {
+		var typ byte
+		if newTable {
+			// Symbol type, value, Go type.
+			typ = p[0] & 0x3F
+			wideValue := p[0]&0x40 != 0
+			goType := p[0]&0x80 != 0
+			if typ < 26 {
+				typ += 'A'
+			} else {
+				typ += 'a' - 26
+			}
+			s.typ = typ
+			p = p[1:]
+			if wideValue {
+				if len(p) < ptrsz {
+					return &DecodingError{len(data), "unexpected EOF", nil}
+				}
+				// fixed-width value
+				if ptrsz == 8 {
+					s.value = order.Uint64(p[0:8])
+					p = p[8:]
+				} else {
+					s.value = uint64(order.Uint32(p[0:4]))
+					p = p[4:]
+				}
+			} else {
+				// varint value
+				s.value = 0
+				shift := uint(0)
+				for len(p) > 0 && p[0]&0x80 != 0 {
+					s.value |= uint64(p[0]&0x7F) << shift
+					shift += 7
+					p = p[1:]
+				}
+				if len(p) == 0 {
+					return &DecodingError{len(data), "unexpected EOF", nil}
+				}
+				s.value |= uint64(p[0]) << shift
+				p = p[1:]
+			}
+			if goType {
+				if len(p) < ptrsz {
+					return &DecodingError{len(data), "unexpected EOF", nil}
+				}
+				// fixed-width go type
+				if ptrsz == 8 {
+					s.gotype = order.Uint64(p[0:8])
+					p = p[8:]
+				} else {
+					s.gotype = uint64(order.Uint32(p[0:4]))
+					p = p[4:]
+				}
+			}
+		} else {
+			// Value, symbol type.
+			s.value = uint64(order.Uint32(p[0:4]))
+			if len(p) < 5 {
+				return &DecodingError{len(data), "unexpected EOF", nil}
+			}
+			typ = p[4]
+			if typ&0x80 == 0 {
+				return &DecodingError{len(data) - len(p) + 4, "bad symbol type", typ}
+			}
+			typ &^= 0x80
+			s.typ = typ
+			p = p[5:]
+		}
+
+		// Name.
+		var i int
+		var nnul int
+		for i = 0; i < len(p); i++ {
+			if p[i] == 0 {
+				nnul = 1
+				break
+			}
+		}
+		switch typ {
+		case 'z', 'Z':
+			p = p[i+nnul:]
+			for i = 0; i+2 <= len(p); i += 2 {
+				if p[i] == 0 && p[i+1] == 0 {
+					nnul = 2
+					break
+				}
+			}
+		}
+		if len(p) < i+nnul {
+			return &DecodingError{len(data), "unexpected EOF", nil}
+		}
+		s.name = p[0:i]
+		i += nnul
+		p = p[i:]
+
+		if !newTable {
+			if len(p) < 4 {
+				return &DecodingError{len(data), "unexpected EOF", nil}
+			}
+			// Go type.
+			s.gotype = uint64(order.Uint32(p[:4]))
+			p = p[4:]
+		}
+		fn(s)
+	}
+	return nil
+}
+
+// NewTable decodes the Go symbol table in data,
+// returning an in-memory representation.
+func NewTable(symtab []byte, pcln *LineTable) (*Table, error) {
+	var n int
+	err := walksymtab(symtab, func(s sym) error {
+		n++
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	var t Table
+	if pcln.isGo12() {
+		t.go12line = pcln
+	}
+	fname := make(map[uint16]string)
+	t.Syms = make([]Sym, 0, n)
+	nf := 0
+	nz := 0
+	lasttyp := uint8(0)
+	err = walksymtab(symtab, func(s sym) error {
+		n := len(t.Syms)
+		t.Syms = t.Syms[0 : n+1]
+		ts := &t.Syms[n]
+		ts.Type = s.typ
+		ts.Value = uint64(s.value)
+		ts.GoType = uint64(s.gotype)
+		switch s.typ {
+		default:
+			// rewrite name to use . instead of · (c2 b7)
+			w := 0
+			b := s.name
+			for i := 0; i < len(b); i++ {
+				if b[i] == 0xc2 && i+1 < len(b) && b[i+1] == 0xb7 {
+					i++
+					b[i] = '.'
+				}
+				b[w] = b[i]
+				w++
+			}
+			ts.Name = string(s.name[0:w])
+		case 'z', 'Z':
+			if lasttyp != 'z' && lasttyp != 'Z' {
+				nz++
+			}
+			for i := 0; i < len(s.name); i += 2 {
+				eltIdx := binary.BigEndian.Uint16(s.name[i : i+2])
+				elt, ok := fname[eltIdx]
+				if !ok {
+					return &DecodingError{-1, "bad filename code", eltIdx}
+				}
+				if n := len(ts.Name); n > 0 && ts.Name[n-1] != '/' {
+					ts.Name += "/"
+				}
+				ts.Name += elt
+			}
+		}
+		switch s.typ {
+		case 'T', 't', 'L', 'l':
+			nf++
+		case 'f':
+			fname[uint16(s.value)] = ts.Name
+		}
+		lasttyp = s.typ
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	t.Funcs = make([]Func, 0, nf)
+	t.Files = make(map[string]*Obj)
+
+	var obj *Obj
+	if t.go12line != nil {
+		// Put all functions into one Obj.
+		t.Objs = make([]Obj, 1)
+		obj = &t.Objs[0]
+		t.go12line.go12MapFiles(t.Files, obj)
+	} else {
+		t.Objs = make([]Obj, 0, nz)
+	}
+
+	// Count text symbols and attach frame sizes, parameters, and
+	// locals to them.  Also, find object file boundaries.
+	lastf := 0
+	for i := 0; i < len(t.Syms); i++ {
+		sym := &t.Syms[i]
+		switch sym.Type {
+		case 'Z', 'z': // path symbol
+			if t.go12line != nil {
+				// Go 1.2 binaries have the file information elsewhere. Ignore.
+				break
+			}
+			// Finish the current object
+			if obj != nil {
+				obj.Funcs = t.Funcs[lastf:]
+			}
+			lastf = len(t.Funcs)
+
+			// Start new object
+			n := len(t.Objs)
+			t.Objs = t.Objs[0 : n+1]
+			obj = &t.Objs[n]
+
+			// Count & copy path symbols
+			var end int
+			for end = i + 1; end < len(t.Syms); end++ {
+				if c := t.Syms[end].Type; c != 'Z' && c != 'z' {
+					break
+				}
+			}
+			obj.Paths = t.Syms[i:end]
+			i = end - 1 // loop will i++
+
+			// Record file names
+			depth := 0
+			for j := range obj.Paths {
+				s := &obj.Paths[j]
+				if s.Name == "" {
+					depth--
+				} else {
+					if depth == 0 {
+						t.Files[s.Name] = obj
+					}
+					depth++
+				}
+			}
+
+		case 'T', 't', 'L', 'l': // text symbol
+			if n := len(t.Funcs); n > 0 {
+				t.Funcs[n-1].End = sym.Value
+			}
+			if sym.Name == "etext" {
+				continue
+			}
+
+			// Count parameter and local (auto) syms
+			var np, na int
+			var end int
+		countloop:
+			for end = i + 1; end < len(t.Syms); end++ {
+				switch t.Syms[end].Type {
+				case 'T', 't', 'L', 'l', 'Z', 'z':
+					break countloop
+				case 'p':
+					np++
+				case 'a':
+					na++
+				}
+			}
+
+			// Fill in the function symbol
+			n := len(t.Funcs)
+			t.Funcs = t.Funcs[0 : n+1]
+			fn := &t.Funcs[n]
+			sym.Func = fn
+			fn.Params = make([]*Sym, 0, np)
+			fn.Locals = make([]*Sym, 0, na)
+			fn.Sym = sym
+			fn.Entry = sym.Value
+			fn.Obj = obj
+			if t.go12line != nil {
+				// All functions share the same line table.
+				// It knows how to narrow down to a specific
+				// function quickly.
+				fn.LineTable = t.go12line
+			} else if pcln != nil {
+				fn.LineTable = pcln.slice(fn.Entry)
+				pcln = fn.LineTable
+			}
+			for j := i; j < end; j++ {
+				s := &t.Syms[j]
+				switch s.Type {
+				case 'm':
+					fn.FrameSize = int(s.Value)
+				case 'p':
+					n := len(fn.Params)
+					fn.Params = fn.Params[0 : n+1]
+					fn.Params[n] = s
+				case 'a':
+					n := len(fn.Locals)
+					fn.Locals = fn.Locals[0 : n+1]
+					fn.Locals[n] = s
+				}
+			}
+			i = end - 1 // loop will i++
+		}
+	}
+
+	if t.go12line != nil && nf == 0 {
+		t.Funcs = t.go12line.go12Funcs()
+	}
+	if obj != nil {
+		obj.Funcs = t.Funcs[lastf:]
+	}
+	return &t, nil
+}
+
+// PCToFunc returns the function containing the program counter pc,
+// or nil if there is no such function.
+func (t *Table) PCToFunc(pc uint64) *Func {
+	funcs := t.Funcs
+	for len(funcs) > 0 {
+		m := len(funcs) / 2
+		fn := &funcs[m]
+		switch {
+		case pc < fn.Entry:
+			funcs = funcs[0:m]
+		case fn.Entry <= pc && pc < fn.End:
+			return fn
+		default:
+			funcs = funcs[m+1:]
+		}
+	}
+	return nil
+}
+
+// PCToLine looks up line number information for a program counter.
+// If there is no information, it returns fn == nil.
+func (t *Table) PCToLine(pc uint64) (file string, line int, fn *Func) {
+	if fn = t.PCToFunc(pc); fn == nil {
+		return
+	}
+	if t.go12line != nil {
+		file = t.go12line.go12PCToFile(pc)
+		line = t.go12line.go12PCToLine(pc)
+	} else {
+		file, line = fn.Obj.lineFromAline(fn.LineTable.PCToLine(pc))
+	}
+	return
+}
+
+// LineToPC looks up the first program counter on the given line in
+// the named file.  It returns UnknownPathError or UnknownLineError if
+// there is an error looking up this line.
+func (t *Table) LineToPC(file string, line int) (pc uint64, fn *Func, err error) {
+	obj, ok := t.Files[file]
+	if !ok {
+		return 0, nil, UnknownFileError(file)
+	}
+
+	if t.go12line != nil {
+		pc := t.go12line.go12LineToPC(file, line)
+		if pc == 0 {
+			return 0, nil, &UnknownLineError{file, line}
+		}
+		return pc, t.PCToFunc(pc), nil
+	}
+
+	abs, err := obj.alineFromLine(file, line)
+	if err != nil {
+		return
+	}
+	for i := range obj.Funcs {
+		f := &obj.Funcs[i]
+		pc := f.LineTable.LineToPC(abs, f.End)
+		if pc != 0 {
+			return pc, f, nil
+		}
+	}
+	return 0, nil, &UnknownLineError{file, line}
+}
+
+// LookupSym returns the text, data, or bss symbol with the given name,
+// or nil if no such symbol is found.
+func (t *Table) LookupSym(name string) *Sym {
+	// TODO(austin) Maybe make a map
+	for i := range t.Syms {
+		s := &t.Syms[i]
+		switch s.Type {
+		case 'T', 't', 'L', 'l', 'D', 'd', 'B', 'b':
+			if s.Name == name {
+				return s
+			}
+		}
+	}
+	return nil
+}
+
+// LookupFunc returns the text, data, or bss symbol with the given name,
+// or nil if no such symbol is found.
+func (t *Table) LookupFunc(name string) *Func {
+	for i := range t.Funcs {
+		f := &t.Funcs[i]
+		if f.Sym.Name == name {
+			return f
+		}
+	}
+	return nil
+}
+
+// SymByAddr returns the text, data, or bss symbol starting at the given address.
+func (t *Table) SymByAddr(addr uint64) *Sym {
+	for i := range t.Syms {
+		s := &t.Syms[i]
+		switch s.Type {
+		case 'T', 't', 'L', 'l', 'D', 'd', 'B', 'b':
+			if s.Value == addr {
+				return s
+			}
+		}
+	}
+	return nil
+}
+
+/*
+ * Object files
+ */
+
+// This is legacy code for Go 1.1 and earlier, which used the
+// Plan 9 format for pc-line tables. This code was never quite
+// correct. It's probably very close, and it's usually correct, but
+// we never quite found all the corner cases.
+//
+// Go 1.2 and later use a simpler format, documented at golang.org/s/go12symtab.
+
+func (o *Obj) lineFromAline(aline int) (string, int) {
+	type stackEnt struct {
+		path   string
+		start  int
+		offset int
+		prev   *stackEnt
+	}
+
+	noPath := &stackEnt{"", 0, 0, nil}
+	tos := noPath
+
+pathloop:
+	for _, s := range o.Paths {
+		val := int(s.Value)
+		switch {
+		case val > aline:
+			break pathloop
+
+		case val == 1:
+			// Start a new stack
+			tos = &stackEnt{s.Name, val, 0, noPath}
+
+		case s.Name == "":
+			// Pop
+			if tos == noPath {
+				return "<malformed symbol table>", 0
+			}
+			tos.prev.offset += val - tos.start
+			tos = tos.prev
+
+		default:
+			// Push
+			tos = &stackEnt{s.Name, val, 0, tos}
+		}
+	}
+
+	if tos == noPath {
+		return "", 0
+	}
+	return tos.path, aline - tos.start - tos.offset + 1
+}
+
+func (o *Obj) alineFromLine(path string, line int) (int, error) {
+	if line < 1 {
+		return 0, &UnknownLineError{path, line}
+	}
+
+	for i, s := range o.Paths {
+		// Find this path
+		if s.Name != path {
+			continue
+		}
+
+		// Find this line at this stack level
+		depth := 0
+		var incstart int
+		line += int(s.Value)
+	pathloop:
+		for _, s := range o.Paths[i:] {
+			val := int(s.Value)
+			switch {
+			case depth == 1 && val >= line:
+				return line - 1, nil
+
+			case s.Name == "":
+				depth--
+				if depth == 0 {
+					break pathloop
+				} else if depth == 1 {
+					line += val - incstart
+				}
+
+			default:
+				if depth == 1 {
+					incstart = val
+				}
+				depth++
+			}
+		}
+		return 0, &UnknownLineError{path, line}
+	}
+	return 0, UnknownFileError(path)
+}
+
+/*
+ * Errors
+ */
+
+// UnknownFileError represents a failure to find the specific file in
+// the symbol table.
+type UnknownFileError string
+
+func (e UnknownFileError) Error() string { return "unknown file: " + string(e) }
+
+// UnknownLineError represents a failure to map a line to a program
+// counter, either because the line is beyond the bounds of the file
+// or because there is no code on the given line.
+type UnknownLineError struct {
+	File string
+	Line int
+}
+
+func (e *UnknownLineError) Error() string {
+	return "no code at " + e.File + ":" + strconv.Itoa(e.Line)
+}
+
+// DecodingError represents an error during the decoding of
+// the symbol table.
+type DecodingError struct {
+	off int
+	msg string
+	val interface{}
+}
+
+func (e *DecodingError) Error() string {
+	msg := e.msg
+	if e.val != nil {
+		msg += fmt.Sprintf(" '%v'", e.val)
+	}
+	msg += fmt.Sprintf(" at byte %#x", e.off)
+	return msg
+}
diff --git a/third_party/gofrontend/libgo/go/debug/macho/fat.go b/third_party/gofrontend/libgo/go/debug/macho/fat.go
new file mode 100644
index 0000000..93b8315
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/macho/fat.go
@@ -0,0 +1,146 @@
+// Copyright 2014 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 macho
+
+import (
+	"encoding/binary"
+	"fmt"
+	"io"
+	"os"
+)
+
+// A FatFile is a Mach-O universal binary that contains at least one architecture.
+type FatFile struct {
+	Magic  uint32
+	Arches []FatArch
+	closer io.Closer
+}
+
+// A FatArchHeader represents a fat header for a specific image architecture.
+type FatArchHeader struct {
+	Cpu    Cpu
+	SubCpu uint32
+	Offset uint32
+	Size   uint32
+	Align  uint32
+}
+
+const fatArchHeaderSize = 5 * 4
+
+// A FatArch is a Mach-O File inside a FatFile.
+type FatArch struct {
+	FatArchHeader
+	*File
+}
+
+// ErrNotFat is returned from NewFatFile or OpenFat when the file is not a
+// universal binary but may be a thin binary, based on its magic number.
+var ErrNotFat = &FormatError{0, "not a fat Mach-O file", nil}
+
+// NewFatFile creates a new FatFile for accessing all the Mach-O images in a
+// universal binary. The Mach-O binary is expected to start at position 0 in
+// the ReaderAt.
+func NewFatFile(r io.ReaderAt) (*FatFile, error) {
+	var ff FatFile
+	sr := io.NewSectionReader(r, 0, 1<<63-1)
+
+	// Read the fat_header struct, which is always in big endian.
+	// Start with the magic number.
+	err := binary.Read(sr, binary.BigEndian, &ff.Magic)
+	if err != nil {
+		return nil, &FormatError{0, "error reading magic number", nil}
+	} else if ff.Magic != MagicFat {
+		// See if this is a Mach-O file via its magic number. The magic
+		// must be converted to little endian first though.
+		var buf [4]byte
+		binary.BigEndian.PutUint32(buf[:], ff.Magic)
+		leMagic := binary.LittleEndian.Uint32(buf[:])
+		if leMagic == Magic32 || leMagic == Magic64 {
+			return nil, ErrNotFat
+		} else {
+			return nil, &FormatError{0, "invalid magic number", nil}
+		}
+	}
+	offset := int64(4)
+
+	// Read the number of FatArchHeaders that come after the fat_header.
+	var narch uint32
+	err = binary.Read(sr, binary.BigEndian, &narch)
+	if err != nil {
+		return nil, &FormatError{offset, "invalid fat_header", nil}
+	}
+	offset += 4
+
+	if narch < 1 {
+		return nil, &FormatError{offset, "file contains no images", nil}
+	}
+
+	// Combine the Cpu and SubCpu (both uint32) into a uint64 to make sure
+	// there are not duplicate architectures.
+	seenArches := make(map[uint64]bool, narch)
+	// Make sure that all images are for the same MH_ type.
+	var machoType Type
+
+	// Following the fat_header comes narch fat_arch structs that index
+	// Mach-O images further in the file.
+	ff.Arches = make([]FatArch, narch)
+	for i := uint32(0); i < narch; i++ {
+		fa := &ff.Arches[i]
+		err = binary.Read(sr, binary.BigEndian, &fa.FatArchHeader)
+		if err != nil {
+			return nil, &FormatError{offset, "invalid fat_arch header", nil}
+		}
+		offset += fatArchHeaderSize
+
+		fr := io.NewSectionReader(r, int64(fa.Offset), int64(fa.Size))
+		fa.File, err = NewFile(fr)
+		if err != nil {
+			return nil, err
+		}
+
+		// Make sure the architecture for this image is not duplicate.
+		seenArch := (uint64(fa.Cpu) << 32) | uint64(fa.SubCpu)
+		if o, k := seenArches[seenArch]; o || k {
+			return nil, &FormatError{offset, fmt.Sprintf("duplicate architecture cpu=%v, subcpu=%#x", fa.Cpu, fa.SubCpu), nil}
+		}
+		seenArches[seenArch] = true
+
+		// Make sure the Mach-O type matches that of the first image.
+		if i == 0 {
+			machoType = fa.Type
+		} else {
+			if fa.Type != machoType {
+				return nil, &FormatError{offset, fmt.Sprintf("Mach-O type for architecture #%d (type=%#x) does not match first (type=%#x)", i, fa.Type, machoType), nil}
+			}
+		}
+	}
+
+	return &ff, nil
+}
+
+// OpenFat opens the named file using os.Open and prepares it for use as a Mach-O
+// universal binary.
+func OpenFat(name string) (ff *FatFile, err error) {
+	f, err := os.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	ff, err = NewFatFile(f)
+	if err != nil {
+		f.Close()
+		return nil, err
+	}
+	ff.closer = f
+	return
+}
+
+func (ff *FatFile) Close() error {
+	var err error
+	if ff.closer != nil {
+		err = ff.closer.Close()
+		ff.closer = nil
+	}
+	return err
+}
diff --git a/third_party/gofrontend/libgo/go/debug/macho/file.go b/third_party/gofrontend/libgo/go/debug/macho/file.go
new file mode 100644
index 0000000..da13c51
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/macho/file.go
@@ -0,0 +1,524 @@
+// 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 macho implements access to Mach-O object files.
+package macho
+
+// High level access to low level data structures.
+
+import (
+	"bytes"
+	"debug/dwarf"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"os"
+)
+
+// A File represents an open Mach-O file.
+type File struct {
+	FileHeader
+	ByteOrder binary.ByteOrder
+	Loads     []Load
+	Sections  []*Section
+
+	Symtab   *Symtab
+	Dysymtab *Dysymtab
+
+	closer io.Closer
+}
+
+// A Load represents any Mach-O load command.
+type Load interface {
+	Raw() []byte
+}
+
+// A LoadBytes is the uninterpreted bytes of a Mach-O load command.
+type LoadBytes []byte
+
+func (b LoadBytes) Raw() []byte { return b }
+
+// A SegmentHeader is the header for a Mach-O 32-bit or 64-bit load segment command.
+type SegmentHeader struct {
+	Cmd     LoadCmd
+	Len     uint32
+	Name    string
+	Addr    uint64
+	Memsz   uint64
+	Offset  uint64
+	Filesz  uint64
+	Maxprot uint32
+	Prot    uint32
+	Nsect   uint32
+	Flag    uint32
+}
+
+// A Segment represents a Mach-O 32-bit or 64-bit load segment command.
+type Segment struct {
+	LoadBytes
+	SegmentHeader
+
+	// Embed ReaderAt for ReadAt method.
+	// Do not embed SectionReader directly
+	// to avoid having Read and Seek.
+	// If a client wants Read and Seek it must use
+	// Open() to avoid fighting over the seek offset
+	// with other clients.
+	io.ReaderAt
+	sr *io.SectionReader
+}
+
+// Data reads and returns the contents of the segment.
+func (s *Segment) Data() ([]byte, error) {
+	dat := make([]byte, s.sr.Size())
+	n, err := s.sr.ReadAt(dat, 0)
+	if n == len(dat) {
+		err = nil
+	}
+	return dat[0:n], err
+}
+
+// Open returns a new ReadSeeker reading the segment.
+func (s *Segment) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
+
+type SectionHeader struct {
+	Name   string
+	Seg    string
+	Addr   uint64
+	Size   uint64
+	Offset uint32
+	Align  uint32
+	Reloff uint32
+	Nreloc uint32
+	Flags  uint32
+}
+
+type Section struct {
+	SectionHeader
+
+	// Embed ReaderAt for ReadAt method.
+	// Do not embed SectionReader directly
+	// to avoid having Read and Seek.
+	// If a client wants Read and Seek it must use
+	// Open() to avoid fighting over the seek offset
+	// with other clients.
+	io.ReaderAt
+	sr *io.SectionReader
+}
+
+// Data reads and returns the contents of the Mach-O section.
+func (s *Section) Data() ([]byte, error) {
+	dat := make([]byte, s.sr.Size())
+	n, err := s.sr.ReadAt(dat, 0)
+	if n == len(dat) {
+		err = nil
+	}
+	return dat[0:n], err
+}
+
+// Open returns a new ReadSeeker reading the Mach-O section.
+func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
+
+// A Dylib represents a Mach-O load dynamic library command.
+type Dylib struct {
+	LoadBytes
+	Name           string
+	Time           uint32
+	CurrentVersion uint32
+	CompatVersion  uint32
+}
+
+// A Symtab represents a Mach-O symbol table command.
+type Symtab struct {
+	LoadBytes
+	SymtabCmd
+	Syms []Symbol
+}
+
+// A Dysymtab represents a Mach-O dynamic symbol table command.
+type Dysymtab struct {
+	LoadBytes
+	DysymtabCmd
+	IndirectSyms []uint32 // indices into Symtab.Syms
+}
+
+/*
+ * Mach-O reader
+ */
+
+// FormatError is returned by some operations if the data does
+// not have the correct format for an object file.
+type FormatError struct {
+	off int64
+	msg string
+	val interface{}
+}
+
+func (e *FormatError) Error() string {
+	msg := e.msg
+	if e.val != nil {
+		msg += fmt.Sprintf(" '%v'", e.val)
+	}
+	msg += fmt.Sprintf(" in record at byte %#x", e.off)
+	return msg
+}
+
+// Open opens the named file using os.Open and prepares it for use as a Mach-O binary.
+func Open(name string) (*File, error) {
+	f, err := os.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	ff, err := NewFile(f)
+	if err != nil {
+		f.Close()
+		return nil, err
+	}
+	ff.closer = f
+	return ff, nil
+}
+
+// Close closes the File.
+// If the File was created using NewFile directly instead of Open,
+// Close has no effect.
+func (f *File) Close() error {
+	var err error
+	if f.closer != nil {
+		err = f.closer.Close()
+		f.closer = nil
+	}
+	return err
+}
+
+// NewFile creates a new File for accessing a Mach-O binary in an underlying reader.
+// The Mach-O binary is expected to start at position 0 in the ReaderAt.
+func NewFile(r io.ReaderAt) (*File, error) {
+	f := new(File)
+	sr := io.NewSectionReader(r, 0, 1<<63-1)
+
+	// Read and decode Mach magic to determine byte order, size.
+	// Magic32 and Magic64 differ only in the bottom bit.
+	var ident [4]byte
+	if _, err := r.ReadAt(ident[0:], 0); err != nil {
+		return nil, err
+	}
+	be := binary.BigEndian.Uint32(ident[0:])
+	le := binary.LittleEndian.Uint32(ident[0:])
+	switch Magic32 &^ 1 {
+	case be &^ 1:
+		f.ByteOrder = binary.BigEndian
+		f.Magic = be
+	case le &^ 1:
+		f.ByteOrder = binary.LittleEndian
+		f.Magic = le
+	default:
+		return nil, &FormatError{0, "invalid magic number", nil}
+	}
+
+	// Read entire file header.
+	if err := binary.Read(sr, f.ByteOrder, &f.FileHeader); err != nil {
+		return nil, err
+	}
+
+	// Then load commands.
+	offset := int64(fileHeaderSize32)
+	if f.Magic == Magic64 {
+		offset = fileHeaderSize64
+	}
+	dat := make([]byte, f.Cmdsz)
+	if _, err := r.ReadAt(dat, offset); err != nil {
+		return nil, err
+	}
+	f.Loads = make([]Load, f.Ncmd)
+	bo := f.ByteOrder
+	for i := range f.Loads {
+		// Each load command begins with uint32 command and length.
+		if len(dat) < 8 {
+			return nil, &FormatError{offset, "command block too small", nil}
+		}
+		cmd, siz := LoadCmd(bo.Uint32(dat[0:4])), bo.Uint32(dat[4:8])
+		if siz < 8 || siz > uint32(len(dat)) {
+			return nil, &FormatError{offset, "invalid command block size", nil}
+		}
+		var cmddat []byte
+		cmddat, dat = dat[0:siz], dat[siz:]
+		offset += int64(siz)
+		var s *Segment
+		switch cmd {
+		default:
+			f.Loads[i] = LoadBytes(cmddat)
+
+		case LoadCmdDylib:
+			var hdr DylibCmd
+			b := bytes.NewReader(cmddat)
+			if err := binary.Read(b, bo, &hdr); err != nil {
+				return nil, err
+			}
+			l := new(Dylib)
+			if hdr.Name >= uint32(len(cmddat)) {
+				return nil, &FormatError{offset, "invalid name in dynamic library command", hdr.Name}
+			}
+			l.Name = cstring(cmddat[hdr.Name:])
+			l.Time = hdr.Time
+			l.CurrentVersion = hdr.CurrentVersion
+			l.CompatVersion = hdr.CompatVersion
+			l.LoadBytes = LoadBytes(cmddat)
+			f.Loads[i] = l
+
+		case LoadCmdSymtab:
+			var hdr SymtabCmd
+			b := bytes.NewReader(cmddat)
+			if err := binary.Read(b, bo, &hdr); err != nil {
+				return nil, err
+			}
+			strtab := make([]byte, hdr.Strsize)
+			if _, err := r.ReadAt(strtab, int64(hdr.Stroff)); err != nil {
+				return nil, err
+			}
+			var symsz int
+			if f.Magic == Magic64 {
+				symsz = 16
+			} else {
+				symsz = 12
+			}
+			symdat := make([]byte, int(hdr.Nsyms)*symsz)
+			if _, err := r.ReadAt(symdat, int64(hdr.Symoff)); err != nil {
+				return nil, err
+			}
+			st, err := f.parseSymtab(symdat, strtab, cmddat, &hdr, offset)
+			if err != nil {
+				return nil, err
+			}
+			f.Loads[i] = st
+			f.Symtab = st
+
+		case LoadCmdDysymtab:
+			var hdr DysymtabCmd
+			b := bytes.NewReader(cmddat)
+			if err := binary.Read(b, bo, &hdr); err != nil {
+				return nil, err
+			}
+			dat := make([]byte, hdr.Nindirectsyms*4)
+			if _, err := r.ReadAt(dat, int64(hdr.Indirectsymoff)); err != nil {
+				return nil, err
+			}
+			x := make([]uint32, hdr.Nindirectsyms)
+			if err := binary.Read(bytes.NewReader(dat), bo, x); err != nil {
+				return nil, err
+			}
+			st := new(Dysymtab)
+			st.LoadBytes = LoadBytes(cmddat)
+			st.DysymtabCmd = hdr
+			st.IndirectSyms = x
+			f.Loads[i] = st
+			f.Dysymtab = st
+
+		case LoadCmdSegment:
+			var seg32 Segment32
+			b := bytes.NewReader(cmddat)
+			if err := binary.Read(b, bo, &seg32); err != nil {
+				return nil, err
+			}
+			s = new(Segment)
+			s.LoadBytes = cmddat
+			s.Cmd = cmd
+			s.Len = siz
+			s.Name = cstring(seg32.Name[0:])
+			s.Addr = uint64(seg32.Addr)
+			s.Memsz = uint64(seg32.Memsz)
+			s.Offset = uint64(seg32.Offset)
+			s.Filesz = uint64(seg32.Filesz)
+			s.Maxprot = seg32.Maxprot
+			s.Prot = seg32.Prot
+			s.Nsect = seg32.Nsect
+			s.Flag = seg32.Flag
+			f.Loads[i] = s
+			for i := 0; i < int(s.Nsect); i++ {
+				var sh32 Section32
+				if err := binary.Read(b, bo, &sh32); err != nil {
+					return nil, err
+				}
+				sh := new(Section)
+				sh.Name = cstring(sh32.Name[0:])
+				sh.Seg = cstring(sh32.Seg[0:])
+				sh.Addr = uint64(sh32.Addr)
+				sh.Size = uint64(sh32.Size)
+				sh.Offset = sh32.Offset
+				sh.Align = sh32.Align
+				sh.Reloff = sh32.Reloff
+				sh.Nreloc = sh32.Nreloc
+				sh.Flags = sh32.Flags
+				f.pushSection(sh, r)
+			}
+
+		case LoadCmdSegment64:
+			var seg64 Segment64
+			b := bytes.NewReader(cmddat)
+			if err := binary.Read(b, bo, &seg64); err != nil {
+				return nil, err
+			}
+			s = new(Segment)
+			s.LoadBytes = cmddat
+			s.Cmd = cmd
+			s.Len = siz
+			s.Name = cstring(seg64.Name[0:])
+			s.Addr = seg64.Addr
+			s.Memsz = seg64.Memsz
+			s.Offset = seg64.Offset
+			s.Filesz = seg64.Filesz
+			s.Maxprot = seg64.Maxprot
+			s.Prot = seg64.Prot
+			s.Nsect = seg64.Nsect
+			s.Flag = seg64.Flag
+			f.Loads[i] = s
+			for i := 0; i < int(s.Nsect); i++ {
+				var sh64 Section64
+				if err := binary.Read(b, bo, &sh64); err != nil {
+					return nil, err
+				}
+				sh := new(Section)
+				sh.Name = cstring(sh64.Name[0:])
+				sh.Seg = cstring(sh64.Seg[0:])
+				sh.Addr = sh64.Addr
+				sh.Size = sh64.Size
+				sh.Offset = sh64.Offset
+				sh.Align = sh64.Align
+				sh.Reloff = sh64.Reloff
+				sh.Nreloc = sh64.Nreloc
+				sh.Flags = sh64.Flags
+				f.pushSection(sh, r)
+			}
+		}
+		if s != nil {
+			s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Filesz))
+			s.ReaderAt = s.sr
+		}
+	}
+	return f, nil
+}
+
+func (f *File) parseSymtab(symdat, strtab, cmddat []byte, hdr *SymtabCmd, offset int64) (*Symtab, error) {
+	bo := f.ByteOrder
+	symtab := make([]Symbol, hdr.Nsyms)
+	b := bytes.NewReader(symdat)
+	for i := range symtab {
+		var n Nlist64
+		if f.Magic == Magic64 {
+			if err := binary.Read(b, bo, &n); err != nil {
+				return nil, err
+			}
+		} else {
+			var n32 Nlist32
+			if err := binary.Read(b, bo, &n32); err != nil {
+				return nil, err
+			}
+			n.Name = n32.Name
+			n.Type = n32.Type
+			n.Sect = n32.Sect
+			n.Desc = n32.Desc
+			n.Value = uint64(n32.Value)
+		}
+		sym := &symtab[i]
+		if n.Name >= uint32(len(strtab)) {
+			return nil, &FormatError{offset, "invalid name in symbol table", n.Name}
+		}
+		sym.Name = cstring(strtab[n.Name:])
+		sym.Type = n.Type
+		sym.Sect = n.Sect
+		sym.Desc = n.Desc
+		sym.Value = n.Value
+	}
+	st := new(Symtab)
+	st.LoadBytes = LoadBytes(cmddat)
+	st.Syms = symtab
+	return st, nil
+}
+
+func (f *File) pushSection(sh *Section, r io.ReaderAt) {
+	f.Sections = append(f.Sections, sh)
+	sh.sr = io.NewSectionReader(r, int64(sh.Offset), int64(sh.Size))
+	sh.ReaderAt = sh.sr
+}
+
+func cstring(b []byte) string {
+	var i int
+	for i = 0; i < len(b) && b[i] != 0; i++ {
+	}
+	return string(b[0:i])
+}
+
+// Segment returns the first Segment with the given name, or nil if no such segment exists.
+func (f *File) Segment(name string) *Segment {
+	for _, l := range f.Loads {
+		if s, ok := l.(*Segment); ok && s.Name == name {
+			return s
+		}
+	}
+	return nil
+}
+
+// Section returns the first section with the given name, or nil if no such
+// section exists.
+func (f *File) Section(name string) *Section {
+	for _, s := range f.Sections {
+		if s.Name == name {
+			return s
+		}
+	}
+	return nil
+}
+
+// DWARF returns the DWARF debug information for the Mach-O file.
+func (f *File) DWARF() (*dwarf.Data, error) {
+	// There are many other DWARF sections, but these
+	// are the required ones, and the debug/dwarf package
+	// does not use the others, so don't bother loading them.
+	var names = [...]string{"abbrev", "info", "line", "str"}
+	var dat [len(names)][]byte
+	for i, name := range names {
+		name = "__debug_" + name
+		s := f.Section(name)
+		if s == nil {
+			continue
+		}
+		b, err := s.Data()
+		if err != nil && uint64(len(b)) < s.Size {
+			return nil, err
+		}
+		dat[i] = b
+	}
+
+	abbrev, info, line, str := dat[0], dat[1], dat[2], dat[3]
+	return dwarf.New(abbrev, nil, nil, info, line, nil, nil, str)
+}
+
+// ImportedSymbols returns the names of all symbols
+// referred to by the binary f that are expected to be
+// satisfied by other libraries at dynamic load time.
+func (f *File) ImportedSymbols() ([]string, error) {
+	if f.Dysymtab == nil || f.Symtab == nil {
+		return nil, &FormatError{0, "missing symbol table", nil}
+	}
+
+	st := f.Symtab
+	dt := f.Dysymtab
+	var all []string
+	for _, s := range st.Syms[dt.Iundefsym : dt.Iundefsym+dt.Nundefsym] {
+		all = append(all, s.Name)
+	}
+	return all, nil
+}
+
+// ImportedLibraries returns the paths of all libraries
+// referred to by the binary f that are expected to be
+// linked with the binary at dynamic link time.
+func (f *File) ImportedLibraries() ([]string, error) {
+	var all []string
+	for _, l := range f.Loads {
+		if lib, ok := l.(*Dylib); ok {
+			all = append(all, lib.Name)
+		}
+	}
+	return all, nil
+}
diff --git a/third_party/gofrontend/libgo/go/debug/macho/file_test.go b/third_party/gofrontend/libgo/go/debug/macho/file_test.go
new file mode 100644
index 0000000..4797780
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/macho/file_test.go
@@ -0,0 +1,210 @@
+// 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 macho
+
+import (
+	"reflect"
+	"testing"
+)
+
+type fileTest struct {
+	file     string
+	hdr      FileHeader
+	segments []*SegmentHeader
+	sections []*SectionHeader
+}
+
+var fileTests = []fileTest{
+	{
+		"testdata/gcc-386-darwin-exec",
+		FileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0xc, 0x3c0, 0x85},
+		[]*SegmentHeader{
+			{LoadCmdSegment, 0x38, "__PAGEZERO", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+			{LoadCmdSegment, 0xc0, "__TEXT", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0},
+			{LoadCmdSegment, 0xc0, "__DATA", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0},
+			{LoadCmdSegment, 0x7c, "__IMPORT", 0x3000, 0x1000, 0x2000, 0x1000, 0x7, 0x7, 0x1, 0x0},
+			{LoadCmdSegment, 0x38, "__LINKEDIT", 0x4000, 0x1000, 0x3000, 0x12c, 0x7, 0x1, 0x0, 0x0},
+			nil,
+			nil,
+			nil,
+			nil,
+			nil,
+			nil,
+			nil,
+		},
+		[]*SectionHeader{
+			{"__text", "__TEXT", 0x1f68, 0x88, 0xf68, 0x2, 0x0, 0x0, 0x80000400},
+			{"__cstring", "__TEXT", 0x1ff0, 0xd, 0xff0, 0x0, 0x0, 0x0, 0x2},
+			{"__data", "__DATA", 0x2000, 0x14, 0x1000, 0x2, 0x0, 0x0, 0x0},
+			{"__dyld", "__DATA", 0x2014, 0x1c, 0x1014, 0x2, 0x0, 0x0, 0x0},
+			{"__jump_table", "__IMPORT", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008},
+		},
+	},
+	{
+		"testdata/gcc-amd64-darwin-exec",
+		FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0xb, 0x568, 0x85},
+		[]*SegmentHeader{
+			{LoadCmdSegment64, 0x48, "__PAGEZERO", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+			{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0},
+			{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0},
+			{LoadCmdSegment64, 0x48, "__LINKEDIT", 0x100002000, 0x1000, 0x2000, 0x140, 0x7, 0x1, 0x0, 0x0},
+			nil,
+			nil,
+			nil,
+			nil,
+			nil,
+			nil,
+			nil,
+		},
+		[]*SectionHeader{
+			{"__text", "__TEXT", 0x100000f14, 0x6d, 0xf14, 0x2, 0x0, 0x0, 0x80000400},
+			{"__symbol_stub1", "__TEXT", 0x100000f81, 0xc, 0xf81, 0x0, 0x0, 0x0, 0x80000408},
+			{"__stub_helper", "__TEXT", 0x100000f90, 0x18, 0xf90, 0x2, 0x0, 0x0, 0x0},
+			{"__cstring", "__TEXT", 0x100000fa8, 0xd, 0xfa8, 0x0, 0x0, 0x0, 0x2},
+			{"__eh_frame", "__TEXT", 0x100000fb8, 0x48, 0xfb8, 0x3, 0x0, 0x0, 0x6000000b},
+			{"__data", "__DATA", 0x100001000, 0x1c, 0x1000, 0x3, 0x0, 0x0, 0x0},
+			{"__dyld", "__DATA", 0x100001020, 0x38, 0x1020, 0x3, 0x0, 0x0, 0x0},
+			{"__la_symbol_ptr", "__DATA", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7},
+		},
+	},
+	{
+		"testdata/gcc-amd64-darwin-exec-debug",
+		FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0xa, 0x4, 0x5a0, 0},
+		[]*SegmentHeader{
+			nil,
+			{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0},
+			{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0},
+			{LoadCmdSegment64, 0x278, "__DWARF", 0x100002000, 0x1000, 0x1000, 0x1bc, 0x7, 0x3, 0x7, 0x0},
+		},
+		[]*SectionHeader{
+			{"__text", "__TEXT", 0x100000f14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x80000400},
+			{"__symbol_stub1", "__TEXT", 0x100000f81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000408},
+			{"__stub_helper", "__TEXT", 0x100000f90, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0},
+			{"__cstring", "__TEXT", 0x100000fa8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
+			{"__eh_frame", "__TEXT", 0x100000fb8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x6000000b},
+			{"__data", "__DATA", 0x100001000, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
+			{"__dyld", "__DATA", 0x100001020, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
+			{"__la_symbol_ptr", "__DATA", 0x100001058, 0x0, 0x0, 0x2, 0x0, 0x0, 0x7},
+			{"__debug_abbrev", "__DWARF", 0x100002000, 0x36, 0x1000, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_aranges", "__DWARF", 0x100002036, 0x30, 0x1036, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_frame", "__DWARF", 0x100002066, 0x40, 0x1066, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_info", "__DWARF", 0x1000020a6, 0x54, 0x10a6, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_line", "__DWARF", 0x1000020fa, 0x47, 0x10fa, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_pubnames", "__DWARF", 0x100002141, 0x1b, 0x1141, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0},
+		},
+	},
+}
+
+func TestOpen(t *testing.T) {
+	for i := range fileTests {
+		tt := &fileTests[i]
+
+		f, err := Open(tt.file)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
+			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
+			continue
+		}
+		for i, l := range f.Loads {
+			if i >= len(tt.segments) {
+				break
+			}
+			sh := tt.segments[i]
+			s, ok := l.(*Segment)
+			if sh == nil {
+				if ok {
+					t.Errorf("open %s, section %d: skipping %#v\n", tt.file, i, &s.SegmentHeader)
+				}
+				continue
+			}
+			if !ok {
+				t.Errorf("open %s, section %d: not *Segment\n", tt.file, i)
+				continue
+			}
+			have := &s.SegmentHeader
+			want := sh
+			if !reflect.DeepEqual(have, want) {
+				t.Errorf("open %s, segment %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
+			}
+		}
+		tn := len(tt.segments)
+		fn := len(f.Loads)
+		if tn != fn {
+			t.Errorf("open %s: len(Loads) = %d, want %d", tt.file, fn, tn)
+		}
+
+		for i, sh := range f.Sections {
+			if i >= len(tt.sections) {
+				break
+			}
+			have := &sh.SectionHeader
+			want := tt.sections[i]
+			if !reflect.DeepEqual(have, want) {
+				t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
+			}
+		}
+		tn = len(tt.sections)
+		fn = len(f.Sections)
+		if tn != fn {
+			t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
+		}
+
+	}
+}
+
+func TestOpenFailure(t *testing.T) {
+	filename := "file.go"    // not a Mach-O file
+	_, err := Open(filename) // don't crash
+	if err == nil {
+		t.Errorf("open %s: succeeded unexpectedly", filename)
+	}
+}
+
+func TestOpenFat(t *testing.T) {
+	ff, err := OpenFat("testdata/fat-gcc-386-amd64-darwin-exec")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if ff.Magic != MagicFat {
+		t.Errorf("OpenFat: got magic number %#x, want %#x", ff.Magic, MagicFat)
+	}
+	if len(ff.Arches) != 2 {
+		t.Errorf("OpenFat: got %d architectures, want 2", len(ff.Arches))
+	}
+
+	for i := range ff.Arches {
+		arch := &ff.Arches[i]
+		ftArch := &fileTests[i]
+
+		if arch.Cpu != ftArch.hdr.Cpu || arch.SubCpu != ftArch.hdr.SubCpu {
+			t.Errorf("OpenFat: architecture #%d got cpu=%#x subtype=%#x, expected cpu=%#x, subtype=%#x", i, arch.Cpu, arch.SubCpu, ftArch.hdr.Cpu, ftArch.hdr.SubCpu)
+		}
+
+		if !reflect.DeepEqual(arch.FileHeader, ftArch.hdr) {
+			t.Errorf("OpenFat header:\n\tgot %#v\n\twant %#v\n", arch.FileHeader, ftArch.hdr)
+		}
+	}
+}
+
+func TestOpenFatFailure(t *testing.T) {
+	filename := "file.go" // not a Mach-O file
+	if _, err := OpenFat(filename); err == nil {
+		t.Errorf("OpenFat %s: succeeded unexpectedly", filename)
+	}
+
+	filename = "testdata/gcc-386-darwin-exec" // not a fat Mach-O
+	ff, err := OpenFat(filename)
+	if err != ErrNotFat {
+		t.Errorf("OpenFat %s: got %v, want ErrNotFat", filename, err)
+	}
+	if ff != nil {
+		t.Errorf("OpenFat %s: got %v, want nil", filename, ff)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/macho/macho.go b/third_party/gofrontend/libgo/go/debug/macho/macho.go
new file mode 100644
index 0000000..d9678c8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/macho/macho.go
@@ -0,0 +1,316 @@
+// 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.
+
+// Mach-O header data structures
+// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
+
+package macho
+
+import "strconv"
+
+// A FileHeader represents a Mach-O file header.
+type FileHeader struct {
+	Magic  uint32
+	Cpu    Cpu
+	SubCpu uint32
+	Type   Type
+	Ncmd   uint32
+	Cmdsz  uint32
+	Flags  uint32
+}
+
+const (
+	fileHeaderSize32 = 7 * 4
+	fileHeaderSize64 = 8 * 4
+)
+
+const (
+	Magic32  uint32 = 0xfeedface
+	Magic64  uint32 = 0xfeedfacf
+	MagicFat uint32 = 0xcafebabe
+)
+
+// A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library.
+type Type uint32
+
+const (
+	TypeObj    Type = 1
+	TypeExec   Type = 2
+	TypeDylib  Type = 6
+	TypeBundle Type = 8
+)
+
+// A Cpu is a Mach-O cpu type.
+type Cpu uint32
+
+const cpuArch64 = 0x01000000
+
+const (
+	Cpu386   Cpu = 7
+	CpuAmd64 Cpu = Cpu386 | cpuArch64
+	CpuArm   Cpu = 12
+	CpuPpc   Cpu = 18
+	CpuPpc64 Cpu = CpuPpc | cpuArch64
+)
+
+var cpuStrings = []intName{
+	{uint32(Cpu386), "Cpu386"},
+	{uint32(CpuAmd64), "CpuAmd64"},
+	{uint32(CpuArm), "CpuArm"},
+	{uint32(CpuPpc), "CpuPpc"},
+	{uint32(CpuPpc64), "CpuPpc64"},
+}
+
+func (i Cpu) String() string   { return stringName(uint32(i), cpuStrings, false) }
+func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) }
+
+// A LoadCmd is a Mach-O load command.
+type LoadCmd uint32
+
+const (
+	LoadCmdSegment    LoadCmd = 1
+	LoadCmdSymtab     LoadCmd = 2
+	LoadCmdThread     LoadCmd = 4
+	LoadCmdUnixThread LoadCmd = 5 // thread+stack
+	LoadCmdDysymtab   LoadCmd = 11
+	LoadCmdDylib      LoadCmd = 12
+	LoadCmdDylinker   LoadCmd = 15
+	LoadCmdSegment64  LoadCmd = 25
+)
+
+var cmdStrings = []intName{
+	{uint32(LoadCmdSegment), "LoadCmdSegment"},
+	{uint32(LoadCmdThread), "LoadCmdThread"},
+	{uint32(LoadCmdUnixThread), "LoadCmdUnixThread"},
+	{uint32(LoadCmdDylib), "LoadCmdDylib"},
+	{uint32(LoadCmdSegment64), "LoadCmdSegment64"},
+}
+
+func (i LoadCmd) String() string   { return stringName(uint32(i), cmdStrings, false) }
+func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) }
+
+// A Segment64 is a 64-bit Mach-O segment load command.
+type Segment64 struct {
+	Cmd     LoadCmd
+	Len     uint32
+	Name    [16]byte
+	Addr    uint64
+	Memsz   uint64
+	Offset  uint64
+	Filesz  uint64
+	Maxprot uint32
+	Prot    uint32
+	Nsect   uint32
+	Flag    uint32
+}
+
+// A Segment32 is a 32-bit Mach-O segment load command.
+type Segment32 struct {
+	Cmd     LoadCmd
+	Len     uint32
+	Name    [16]byte
+	Addr    uint32
+	Memsz   uint32
+	Offset  uint32
+	Filesz  uint32
+	Maxprot uint32
+	Prot    uint32
+	Nsect   uint32
+	Flag    uint32
+}
+
+// A DylibCmd is a Mach-O load dynamic library command.
+type DylibCmd struct {
+	Cmd            LoadCmd
+	Len            uint32
+	Name           uint32
+	Time           uint32
+	CurrentVersion uint32
+	CompatVersion  uint32
+}
+
+// A Section32 is a 32-bit Mach-O section header.
+type Section32 struct {
+	Name     [16]byte
+	Seg      [16]byte
+	Addr     uint32
+	Size     uint32
+	Offset   uint32
+	Align    uint32
+	Reloff   uint32
+	Nreloc   uint32
+	Flags    uint32
+	Reserve1 uint32
+	Reserve2 uint32
+}
+
+// A Section32 is a 64-bit Mach-O section header.
+type Section64 struct {
+	Name     [16]byte
+	Seg      [16]byte
+	Addr     uint64
+	Size     uint64
+	Offset   uint32
+	Align    uint32
+	Reloff   uint32
+	Nreloc   uint32
+	Flags    uint32
+	Reserve1 uint32
+	Reserve2 uint32
+	Reserve3 uint32
+}
+
+// A SymtabCmd is a Mach-O symbol table command.
+type SymtabCmd struct {
+	Cmd     LoadCmd
+	Len     uint32
+	Symoff  uint32
+	Nsyms   uint32
+	Stroff  uint32
+	Strsize uint32
+}
+
+// A DysymtabCmd is a Mach-O dynamic symbol table command.
+type DysymtabCmd struct {
+	Cmd            LoadCmd
+	Len            uint32
+	Ilocalsym      uint32
+	Nlocalsym      uint32
+	Iextdefsym     uint32
+	Nextdefsym     uint32
+	Iundefsym      uint32
+	Nundefsym      uint32
+	Tocoffset      uint32
+	Ntoc           uint32
+	Modtaboff      uint32
+	Nmodtab        uint32
+	Extrefsymoff   uint32
+	Nextrefsyms    uint32
+	Indirectsymoff uint32
+	Nindirectsyms  uint32
+	Extreloff      uint32
+	Nextrel        uint32
+	Locreloff      uint32
+	Nlocrel        uint32
+}
+
+// An Nlist32 is a Mach-O 32-bit symbol table entry.
+type Nlist32 struct {
+	Name  uint32
+	Type  uint8
+	Sect  uint8
+	Desc  uint16
+	Value uint32
+}
+
+// An Nlist64 is a Mach-O 64-bit symbol table entry.
+type Nlist64 struct {
+	Name  uint32
+	Type  uint8
+	Sect  uint8
+	Desc  uint16
+	Value uint64
+}
+
+// A Symbol is a Mach-O 32-bit or 64-bit symbol table entry.
+type Symbol struct {
+	Name  string
+	Type  uint8
+	Sect  uint8
+	Desc  uint16
+	Value uint64
+}
+
+// A Thread is a Mach-O thread state command.
+type Thread struct {
+	Cmd  LoadCmd
+	Len  uint32
+	Type uint32
+	Data []uint32
+}
+
+// Regs386 is the Mach-O 386 register structure.
+type Regs386 struct {
+	AX    uint32
+	BX    uint32
+	CX    uint32
+	DX    uint32
+	DI    uint32
+	SI    uint32
+	BP    uint32
+	SP    uint32
+	SS    uint32
+	FLAGS uint32
+	IP    uint32
+	CS    uint32
+	DS    uint32
+	ES    uint32
+	FS    uint32
+	GS    uint32
+}
+
+// RegsAMD64 is the Mach-O AMD64 register structure.
+type RegsAMD64 struct {
+	AX    uint64
+	BX    uint64
+	CX    uint64
+	DX    uint64
+	DI    uint64
+	SI    uint64
+	BP    uint64
+	SP    uint64
+	R8    uint64
+	R9    uint64
+	R10   uint64
+	R11   uint64
+	R12   uint64
+	R13   uint64
+	R14   uint64
+	R15   uint64
+	IP    uint64
+	FLAGS uint64
+	CS    uint64
+	FS    uint64
+	GS    uint64
+}
+
+type intName struct {
+	i uint32
+	s string
+}
+
+func stringName(i uint32, names []intName, goSyntax bool) string {
+	for _, n := range names {
+		if n.i == i {
+			if goSyntax {
+				return "macho." + n.s
+			}
+			return n.s
+		}
+	}
+	return strconv.FormatUint(uint64(i), 10)
+}
+
+func flagName(i uint32, names []intName, goSyntax bool) string {
+	s := ""
+	for _, n := range names {
+		if n.i&i == n.i {
+			if len(s) > 0 {
+				s += "+"
+			}
+			if goSyntax {
+				s += "macho."
+			}
+			s += n.s
+			i -= n.i
+		}
+	}
+	if len(s) == 0 {
+		return "0x" + strconv.FormatUint(uint64(i), 16)
+	}
+	if i != 0 {
+		s += "+0x" + strconv.FormatUint(uint64(i), 16)
+	}
+	return s
+}
diff --git a/third_party/gofrontend/libgo/go/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec b/third_party/gofrontend/libgo/go/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec
new file mode 100644
index 0000000..7efd193
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/macho/testdata/gcc-386-darwin-exec b/third_party/gofrontend/libgo/go/debug/macho/testdata/gcc-386-darwin-exec
new file mode 100755
index 0000000..03ba1ba
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/macho/testdata/gcc-386-darwin-exec
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/macho/testdata/gcc-amd64-darwin-exec b/third_party/gofrontend/libgo/go/debug/macho/testdata/gcc-amd64-darwin-exec
new file mode 100755
index 0000000..5155a5a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/macho/testdata/gcc-amd64-darwin-exec
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/macho/testdata/gcc-amd64-darwin-exec-debug b/third_party/gofrontend/libgo/go/debug/macho/testdata/gcc-amd64-darwin-exec-debug
new file mode 100644
index 0000000..a47d3ae
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/macho/testdata/gcc-amd64-darwin-exec-debug
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/macho/testdata/hello.c b/third_party/gofrontend/libgo/go/debug/macho/testdata/hello.c
new file mode 100644
index 0000000..a689d36
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/macho/testdata/hello.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int
+main(void)
+{
+	printf("hello, world\n");
+	return 0;
+}
diff --git a/third_party/gofrontend/libgo/go/debug/pe/file.go b/third_party/gofrontend/libgo/go/debug/pe/file.go
new file mode 100644
index 0000000..ce6f140
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/pe/file.go
@@ -0,0 +1,390 @@
+// 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 pe implements access to PE (Microsoft Windows Portable Executable) files.
+package pe
+
+import (
+	"debug/dwarf"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"os"
+	"strconv"
+	"unsafe"
+)
+
+// A File represents an open PE file.
+type File struct {
+	FileHeader
+	OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64
+	Sections       []*Section
+	Symbols        []*Symbol
+
+	closer io.Closer
+}
+
+type SectionHeader struct {
+	Name                 string
+	VirtualSize          uint32
+	VirtualAddress       uint32
+	Size                 uint32
+	Offset               uint32
+	PointerToRelocations uint32
+	PointerToLineNumbers uint32
+	NumberOfRelocations  uint16
+	NumberOfLineNumbers  uint16
+	Characteristics      uint32
+}
+
+type Section struct {
+	SectionHeader
+
+	// Embed ReaderAt for ReadAt method.
+	// Do not embed SectionReader directly
+	// to avoid having Read and Seek.
+	// If a client wants Read and Seek it must use
+	// Open() to avoid fighting over the seek offset
+	// with other clients.
+	io.ReaderAt
+	sr *io.SectionReader
+}
+
+type Symbol struct {
+	Name          string
+	Value         uint32
+	SectionNumber int16
+	Type          uint16
+	StorageClass  uint8
+}
+
+type ImportDirectory struct {
+	OriginalFirstThunk uint32
+	TimeDateStamp      uint32
+	ForwarderChain     uint32
+	Name               uint32
+	FirstThunk         uint32
+
+	dll string
+}
+
+// Data reads and returns the contents of the PE section.
+func (s *Section) Data() ([]byte, error) {
+	dat := make([]byte, s.sr.Size())
+	n, err := s.sr.ReadAt(dat, 0)
+	if n == len(dat) {
+		err = nil
+	}
+	return dat[0:n], err
+}
+
+// Open returns a new ReadSeeker reading the PE section.
+func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
+
+type FormatError struct {
+	off int64
+	msg string
+	val interface{}
+}
+
+func (e *FormatError) Error() string {
+	msg := e.msg
+	if e.val != nil {
+		msg += fmt.Sprintf(" '%v'", e.val)
+	}
+	msg += fmt.Sprintf(" in record at byte %#x", e.off)
+	return msg
+}
+
+// Open opens the named file using os.Open and prepares it for use as a PE binary.
+func Open(name string) (*File, error) {
+	f, err := os.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	ff, err := NewFile(f)
+	if err != nil {
+		f.Close()
+		return nil, err
+	}
+	ff.closer = f
+	return ff, nil
+}
+
+// Close closes the File.
+// If the File was created using NewFile directly instead of Open,
+// Close has no effect.
+func (f *File) Close() error {
+	var err error
+	if f.closer != nil {
+		err = f.closer.Close()
+		f.closer = nil
+	}
+	return err
+}
+
+// NewFile creates a new File for accessing a PE binary in an underlying reader.
+func NewFile(r io.ReaderAt) (*File, error) {
+	f := new(File)
+	sr := io.NewSectionReader(r, 0, 1<<63-1)
+
+	var dosheader [96]byte
+	if _, err := r.ReadAt(dosheader[0:], 0); err != nil {
+		return nil, err
+	}
+	var base int64
+	if dosheader[0] == 'M' && dosheader[1] == 'Z' {
+		signoff := int64(binary.LittleEndian.Uint32(dosheader[0x3c:]))
+		var sign [4]byte
+		r.ReadAt(sign[:], signoff)
+		if !(sign[0] == 'P' && sign[1] == 'E' && sign[2] == 0 && sign[3] == 0) {
+			return nil, errors.New("Invalid PE File Format.")
+		}
+		base = signoff + 4
+	} else {
+		base = int64(0)
+	}
+	sr.Seek(base, os.SEEK_SET)
+	if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil {
+		return nil, err
+	}
+	if f.FileHeader.Machine != IMAGE_FILE_MACHINE_UNKNOWN && f.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64 && f.FileHeader.Machine != IMAGE_FILE_MACHINE_I386 {
+		return nil, errors.New("Invalid PE File Format.")
+	}
+
+	var ss []byte
+	if f.FileHeader.NumberOfSymbols > 0 {
+		// Get COFF string table, which is located at the end of the COFF symbol table.
+		sr.Seek(int64(f.FileHeader.PointerToSymbolTable+COFFSymbolSize*f.FileHeader.NumberOfSymbols), os.SEEK_SET)
+		var l uint32
+		if err := binary.Read(sr, binary.LittleEndian, &l); err != nil {
+			return nil, err
+		}
+		ss = make([]byte, l)
+		if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+COFFSymbolSize*f.FileHeader.NumberOfSymbols)); err != nil {
+			return nil, err
+		}
+
+		// Process COFF symbol table.
+		sr.Seek(int64(f.FileHeader.PointerToSymbolTable), os.SEEK_SET)
+		aux := uint8(0)
+		for i := 0; i < int(f.FileHeader.NumberOfSymbols); i++ {
+			cs := new(COFFSymbol)
+			if err := binary.Read(sr, binary.LittleEndian, cs); err != nil {
+				return nil, err
+			}
+			if aux > 0 {
+				aux--
+				continue
+			}
+			var name string
+			if cs.Name[0] == 0 && cs.Name[1] == 0 && cs.Name[2] == 0 && cs.Name[3] == 0 {
+				si := int(binary.LittleEndian.Uint32(cs.Name[4:]))
+				name, _ = getString(ss, si)
+			} else {
+				name = cstring(cs.Name[:])
+			}
+			aux = cs.NumberOfAuxSymbols
+			s := &Symbol{
+				Name:          name,
+				Value:         cs.Value,
+				SectionNumber: cs.SectionNumber,
+				Type:          cs.Type,
+				StorageClass:  cs.StorageClass,
+			}
+			f.Symbols = append(f.Symbols, s)
+		}
+	}
+
+	// Read optional header.
+	sr.Seek(base, os.SEEK_SET)
+	if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil {
+		return nil, err
+	}
+	var oh32 OptionalHeader32
+	var oh64 OptionalHeader64
+	switch uintptr(f.FileHeader.SizeOfOptionalHeader) {
+	case unsafe.Sizeof(oh32):
+		if err := binary.Read(sr, binary.LittleEndian, &oh32); err != nil {
+			return nil, err
+		}
+		if oh32.Magic != 0x10b { // PE32
+			return nil, fmt.Errorf("pe32 optional header has unexpected Magic of 0x%x", oh32.Magic)
+		}
+		f.OptionalHeader = &oh32
+	case unsafe.Sizeof(oh64):
+		if err := binary.Read(sr, binary.LittleEndian, &oh64); err != nil {
+			return nil, err
+		}
+		if oh64.Magic != 0x20b { // PE32+
+			return nil, fmt.Errorf("pe32+ optional header has unexpected Magic of 0x%x", oh64.Magic)
+		}
+		f.OptionalHeader = &oh64
+	}
+
+	// Process sections.
+	f.Sections = make([]*Section, f.FileHeader.NumberOfSections)
+	for i := 0; i < int(f.FileHeader.NumberOfSections); i++ {
+		sh := new(SectionHeader32)
+		if err := binary.Read(sr, binary.LittleEndian, sh); err != nil {
+			return nil, err
+		}
+		var name string
+		if sh.Name[0] == '\x2F' {
+			si, _ := strconv.Atoi(cstring(sh.Name[1:]))
+			name, _ = getString(ss, si)
+		} else {
+			name = cstring(sh.Name[0:])
+		}
+		s := new(Section)
+		s.SectionHeader = SectionHeader{
+			Name:                 name,
+			VirtualSize:          sh.VirtualSize,
+			VirtualAddress:       sh.VirtualAddress,
+			Size:                 sh.SizeOfRawData,
+			Offset:               sh.PointerToRawData,
+			PointerToRelocations: sh.PointerToRelocations,
+			PointerToLineNumbers: sh.PointerToLineNumbers,
+			NumberOfRelocations:  sh.NumberOfRelocations,
+			NumberOfLineNumbers:  sh.NumberOfLineNumbers,
+			Characteristics:      sh.Characteristics,
+		}
+		s.sr = io.NewSectionReader(r, int64(s.SectionHeader.Offset), int64(s.SectionHeader.Size))
+		s.ReaderAt = s.sr
+		f.Sections[i] = s
+	}
+	return f, nil
+}
+
+func cstring(b []byte) string {
+	var i int
+	for i = 0; i < len(b) && b[i] != 0; i++ {
+	}
+	return string(b[0:i])
+}
+
+// getString extracts a string from symbol string table.
+func getString(section []byte, start int) (string, bool) {
+	if start < 0 || start >= len(section) {
+		return "", false
+	}
+
+	for end := start; end < len(section); end++ {
+		if section[end] == 0 {
+			return string(section[start:end]), true
+		}
+	}
+	return "", false
+}
+
+// Section returns the first section with the given name, or nil if no such
+// section exists.
+func (f *File) Section(name string) *Section {
+	for _, s := range f.Sections {
+		if s.Name == name {
+			return s
+		}
+	}
+	return nil
+}
+
+func (f *File) DWARF() (*dwarf.Data, error) {
+	// There are many other DWARF sections, but these
+	// are the required ones, and the debug/dwarf package
+	// does not use the others, so don't bother loading them.
+	var names = [...]string{"abbrev", "info", "str"}
+	var dat [len(names)][]byte
+	for i, name := range names {
+		name = ".debug_" + name
+		s := f.Section(name)
+		if s == nil {
+			continue
+		}
+		b, err := s.Data()
+		if err != nil && uint32(len(b)) < s.Size {
+			return nil, err
+		}
+		dat[i] = b
+	}
+
+	abbrev, info, str := dat[0], dat[1], dat[2]
+	return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str)
+}
+
+// ImportedSymbols returns the names of all symbols
+// referred to by the binary f that are expected to be
+// satisfied by other libraries at dynamic load time.
+// It does not return weak symbols.
+func (f *File) ImportedSymbols() ([]string, error) {
+	pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64
+	ds := f.Section(".idata")
+	if ds == nil {
+		// not dynamic, so no libraries
+		return nil, nil
+	}
+	d, err := ds.Data()
+	if err != nil {
+		return nil, err
+	}
+	var ida []ImportDirectory
+	for len(d) > 0 {
+		var dt ImportDirectory
+		dt.OriginalFirstThunk = binary.LittleEndian.Uint32(d[0:4])
+		dt.Name = binary.LittleEndian.Uint32(d[12:16])
+		dt.FirstThunk = binary.LittleEndian.Uint32(d[16:20])
+		d = d[20:]
+		if dt.OriginalFirstThunk == 0 {
+			break
+		}
+		ida = append(ida, dt)
+	}
+	names, _ := ds.Data()
+	var all []string
+	for _, dt := range ida {
+		dt.dll, _ = getString(names, int(dt.Name-ds.VirtualAddress))
+		d, _ = ds.Data()
+		// seek to OriginalFirstThunk
+		d = d[dt.OriginalFirstThunk-ds.VirtualAddress:]
+		for len(d) > 0 {
+			if pe64 { // 64bit
+				va := binary.LittleEndian.Uint64(d[0:8])
+				d = d[8:]
+				if va == 0 {
+					break
+				}
+				if va&0x8000000000000000 > 0 { // is Ordinal
+					// TODO add dynimport ordinal support.
+				} else {
+					fn, _ := getString(names, int(uint32(va)-ds.VirtualAddress+2))
+					all = append(all, fn+":"+dt.dll)
+				}
+			} else { // 32bit
+				va := binary.LittleEndian.Uint32(d[0:4])
+				d = d[4:]
+				if va == 0 {
+					break
+				}
+				if va&0x80000000 > 0 { // is Ordinal
+					// TODO add dynimport ordinal support.
+					//ord := va&0x0000FFFF
+				} else {
+					fn, _ := getString(names, int(va-ds.VirtualAddress+2))
+					all = append(all, fn+":"+dt.dll)
+				}
+			}
+		}
+	}
+
+	return all, nil
+}
+
+// ImportedLibraries returns the names of all libraries
+// referred to by the binary f that are expected to be
+// linked with the binary at dynamic link time.
+func (f *File) ImportedLibraries() ([]string, error) {
+	// TODO
+	// cgo -dynimport don't use this for windows PE, so just return.
+	return nil, nil
+}
diff --git a/third_party/gofrontend/libgo/go/debug/pe/file_test.go b/third_party/gofrontend/libgo/go/debug/pe/file_test.go
new file mode 100644
index 0000000..ddbb271
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/pe/file_test.go
@@ -0,0 +1,236 @@
+// 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 pe
+
+import (
+	"reflect"
+	"testing"
+)
+
+type fileTest struct {
+	file     string
+	hdr      FileHeader
+	opthdr   interface{}
+	sections []*SectionHeader
+	symbols  []*Symbol
+}
+
+var fileTests = []fileTest{
+	{
+		"testdata/gcc-386-mingw-obj",
+		FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
+		nil,
+		[]*SectionHeader{
+			{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
+			{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
+			{".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
+			{".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
+			{".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
+			{".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
+			{".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
+			{".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
+			{".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
+			{".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
+			{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
+			{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
+		},
+		[]*Symbol{
+			{".file", 0x0, -2, 0x0, 0x67},
+			{"_main", 0x0, 1, 0x20, 0x2},
+			{".text", 0x0, 1, 0x0, 0x3},
+			{".data", 0x0, 2, 0x0, 0x3},
+			{".bss", 0x0, 3, 0x0, 0x3},
+			{".debug_abbrev", 0x0, 4, 0x0, 0x3},
+			{".debug_info", 0x0, 5, 0x0, 0x3},
+			{".debug_line", 0x0, 6, 0x0, 0x3},
+			{".rdata", 0x0, 7, 0x0, 0x3},
+			{".debug_frame", 0x0, 8, 0x0, 0x3},
+			{".debug_loc", 0x0, 9, 0x0, 0x3},
+			{".debug_pubnames", 0x0, 10, 0x0, 0x3},
+			{".debug_pubtypes", 0x0, 11, 0x0, 0x3},
+			{".debug_aranges", 0x0, 12, 0x0, 0x3},
+			{"___main", 0x0, 0, 0x20, 0x2},
+			{"_puts", 0x0, 0, 0x20, 0x2},
+		},
+	},
+	{
+		"testdata/gcc-386-mingw-exec",
+		FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
+		&OptionalHeader32{
+			0x10b, 0x2, 0x38, 0xe00, 0x1a00, 0x200, 0x1160, 0x1000, 0x2000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x10000, 0x400, 0x14abb, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
+			[16]DataDirectory{
+				{0x0, 0x0},
+				{0x5000, 0x3c8},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x7000, 0x18},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+			},
+		},
+		[]*SectionHeader{
+			{".text", 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
+			{".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+			{".rdata", 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
+			{".bss", 0xdc, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0400080},
+			{".idata", 0x3c8, 0x5000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+			{".CRT", 0x18, 0x6000, 0x200, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+			{".tls", 0x20, 0x7000, 0x200, 0x1c00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+			{".debug_aranges", 0x20, 0x8000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+			{".debug_pubnames", 0x51, 0x9000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+			{".debug_pubtypes", 0x91, 0xa000, 0x200, 0x2200, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+			{".debug_info", 0xe22, 0xb000, 0x1000, 0x2400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+			{".debug_abbrev", 0x157, 0xc000, 0x200, 0x3400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+			{".debug_line", 0x144, 0xd000, 0x200, 0x3600, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+			{".debug_frame", 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000},
+			{".debug_loc", 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+		},
+		[]*Symbol{},
+	},
+	{
+		"testdata/gcc-amd64-mingw-obj",
+		FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4},
+		nil,
+		[]*SectionHeader{
+			{".text", 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020},
+			{".data", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
+			{".bss", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080},
+			{".rdata", 0x0, 0x0, 0x10, 0x134, 0x0, 0x0, 0x0, 0x0, 0x40500040},
+			{".xdata", 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040},
+			{".pdata", 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040},
+		},
+		[]*Symbol{
+			{".file", 0x0, -2, 0x0, 0x67},
+			{"main", 0x0, 1, 0x20, 0x2},
+			{".text", 0x0, 1, 0x0, 0x3},
+			{".data", 0x0, 2, 0x0, 0x3},
+			{".bss", 0x0, 3, 0x0, 0x3},
+			{".rdata", 0x0, 4, 0x0, 0x3},
+			{".xdata", 0x0, 5, 0x0, 0x3},
+			{".pdata", 0x0, 6, 0x0, 0x3},
+			{"__main", 0x0, 0, 0x20, 0x2},
+			{"puts", 0x0, 0, 0x20, 0x2},
+		},
+	},
+	{
+		"testdata/gcc-amd64-mingw-exec",
+		FileHeader{0x8664, 0x9, 0x53472993, 0x0, 0x0, 0xf0, 0x22f},
+		&OptionalHeader64{
+			0x20b, 0x2, 0x16, 0x6a00, 0x2400, 0x1600, 0x14e0, 0x1000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x0, 0x0, 0x5, 0x2, 0x0, 0x11000, 0x400, 0x1841e, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
+			[16]DataDirectory{
+				{0x0, 0x0},
+				{0xe000, 0x990},
+				{0x0, 0x0},
+				{0xa000, 0x498},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x10000, 0x28},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0xe254, 0x218},
+				{0x0, 0x0},
+				{0x0, 0x0},
+				{0x0, 0x0},
+			},
+		},
+		[]*SectionHeader{
+			{".text", 0x6860, 0x1000, 0x6a00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500020},
+			{".data", 0xe0, 0x8000, 0x200, 0x6e00, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
+			{".rdata", 0x6b0, 0x9000, 0x800, 0x7000, 0x0, 0x0, 0x0, 0x0, 0x40600040},
+			{".pdata", 0x498, 0xa000, 0x600, 0x7800, 0x0, 0x0, 0x0, 0x0, 0x40300040},
+			{".xdata", 0x488, 0xb000, 0x600, 0x7e00, 0x0, 0x0, 0x0, 0x0, 0x40300040},
+			{".bss", 0x1410, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0600080},
+			{".idata", 0x990, 0xe000, 0xa00, 0x8400, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+			{".CRT", 0x68, 0xf000, 0x200, 0x8e00, 0x0, 0x0, 0x0, 0x0, 0xc0400040},
+			{".tls", 0x48, 0x10000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0600040},
+		},
+		[]*Symbol{},
+	},
+}
+
+func isOptHdrEq(a, b interface{}) bool {
+	switch va := a.(type) {
+	case *OptionalHeader32:
+		vb, ok := b.(*OptionalHeader32)
+		if !ok {
+			return false
+		}
+		return *vb == *va
+	case *OptionalHeader64:
+		vb, ok := b.(*OptionalHeader64)
+		if !ok {
+			return false
+		}
+		return *vb == *va
+	case nil:
+		return b == nil
+	}
+	return false
+}
+
+func TestOpen(t *testing.T) {
+	for i := range fileTests {
+		tt := &fileTests[i]
+
+		f, err := Open(tt.file)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
+			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
+			continue
+		}
+		if !isOptHdrEq(tt.opthdr, f.OptionalHeader) {
+			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.OptionalHeader, tt.opthdr)
+			continue
+		}
+
+		for i, sh := range f.Sections {
+			if i >= len(tt.sections) {
+				break
+			}
+			have := &sh.SectionHeader
+			want := tt.sections[i]
+			if !reflect.DeepEqual(have, want) {
+				t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
+			}
+		}
+		tn := len(tt.sections)
+		fn := len(f.Sections)
+		if tn != fn {
+			t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
+		}
+		for i, have := range f.Symbols {
+			if i >= len(tt.symbols) {
+				break
+			}
+			want := tt.symbols[i]
+			if !reflect.DeepEqual(have, want) {
+				t.Errorf("open %s, symbol %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
+			}
+		}
+	}
+}
+
+func TestOpenFailure(t *testing.T) {
+	filename := "file.go"    // not a PE file
+	_, err := Open(filename) // don't crash
+	if err == nil {
+		t.Errorf("open %s: succeeded unexpectedly", filename)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/pe/pe.go b/third_party/gofrontend/libgo/go/debug/pe/pe.go
new file mode 100644
index 0000000..8e90b1b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/pe/pe.go
@@ -0,0 +1,134 @@
+// 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 pe
+
+type FileHeader struct {
+	Machine              uint16
+	NumberOfSections     uint16
+	TimeDateStamp        uint32
+	PointerToSymbolTable uint32
+	NumberOfSymbols      uint32
+	SizeOfOptionalHeader uint16
+	Characteristics      uint16
+}
+
+type DataDirectory struct {
+	VirtualAddress uint32
+	Size           uint32
+}
+
+type OptionalHeader32 struct {
+	Magic                       uint16
+	MajorLinkerVersion          uint8
+	MinorLinkerVersion          uint8
+	SizeOfCode                  uint32
+	SizeOfInitializedData       uint32
+	SizeOfUninitializedData     uint32
+	AddressOfEntryPoint         uint32
+	BaseOfCode                  uint32
+	BaseOfData                  uint32
+	ImageBase                   uint32
+	SectionAlignment            uint32
+	FileAlignment               uint32
+	MajorOperatingSystemVersion uint16
+	MinorOperatingSystemVersion uint16
+	MajorImageVersion           uint16
+	MinorImageVersion           uint16
+	MajorSubsystemVersion       uint16
+	MinorSubsystemVersion       uint16
+	Win32VersionValue           uint32
+	SizeOfImage                 uint32
+	SizeOfHeaders               uint32
+	CheckSum                    uint32
+	Subsystem                   uint16
+	DllCharacteristics          uint16
+	SizeOfStackReserve          uint32
+	SizeOfStackCommit           uint32
+	SizeOfHeapReserve           uint32
+	SizeOfHeapCommit            uint32
+	LoaderFlags                 uint32
+	NumberOfRvaAndSizes         uint32
+	DataDirectory               [16]DataDirectory
+}
+
+type OptionalHeader64 struct {
+	Magic                       uint16
+	MajorLinkerVersion          uint8
+	MinorLinkerVersion          uint8
+	SizeOfCode                  uint32
+	SizeOfInitializedData       uint32
+	SizeOfUninitializedData     uint32
+	AddressOfEntryPoint         uint32
+	BaseOfCode                  uint32
+	ImageBase                   uint64
+	SectionAlignment            uint32
+	FileAlignment               uint32
+	MajorOperatingSystemVersion uint16
+	MinorOperatingSystemVersion uint16
+	MajorImageVersion           uint16
+	MinorImageVersion           uint16
+	MajorSubsystemVersion       uint16
+	MinorSubsystemVersion       uint16
+	Win32VersionValue           uint32
+	SizeOfImage                 uint32
+	SizeOfHeaders               uint32
+	CheckSum                    uint32
+	Subsystem                   uint16
+	DllCharacteristics          uint16
+	SizeOfStackReserve          uint64
+	SizeOfStackCommit           uint64
+	SizeOfHeapReserve           uint64
+	SizeOfHeapCommit            uint64
+	LoaderFlags                 uint32
+	NumberOfRvaAndSizes         uint32
+	DataDirectory               [16]DataDirectory
+}
+
+type SectionHeader32 struct {
+	Name                 [8]uint8
+	VirtualSize          uint32
+	VirtualAddress       uint32
+	SizeOfRawData        uint32
+	PointerToRawData     uint32
+	PointerToRelocations uint32
+	PointerToLineNumbers uint32
+	NumberOfRelocations  uint16
+	NumberOfLineNumbers  uint16
+	Characteristics      uint32
+}
+
+const COFFSymbolSize = 18
+
+type COFFSymbol struct {
+	Name               [8]uint8
+	Value              uint32
+	SectionNumber      int16
+	Type               uint16
+	StorageClass       uint8
+	NumberOfAuxSymbols uint8
+}
+
+const (
+	IMAGE_FILE_MACHINE_UNKNOWN   = 0x0
+	IMAGE_FILE_MACHINE_AM33      = 0x1d3
+	IMAGE_FILE_MACHINE_AMD64     = 0x8664
+	IMAGE_FILE_MACHINE_ARM       = 0x1c0
+	IMAGE_FILE_MACHINE_EBC       = 0xebc
+	IMAGE_FILE_MACHINE_I386      = 0x14c
+	IMAGE_FILE_MACHINE_IA64      = 0x200
+	IMAGE_FILE_MACHINE_M32R      = 0x9041
+	IMAGE_FILE_MACHINE_MIPS16    = 0x266
+	IMAGE_FILE_MACHINE_MIPSFPU   = 0x366
+	IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466
+	IMAGE_FILE_MACHINE_POWERPC   = 0x1f0
+	IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1
+	IMAGE_FILE_MACHINE_R4000     = 0x166
+	IMAGE_FILE_MACHINE_SH3       = 0x1a2
+	IMAGE_FILE_MACHINE_SH3DSP    = 0x1a3
+	IMAGE_FILE_MACHINE_SH4       = 0x1a6
+	IMAGE_FILE_MACHINE_SH5       = 0x1a8
+	IMAGE_FILE_MACHINE_THUMB     = 0x1c2
+	IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169
+)
diff --git a/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-386-mingw-exec b/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-386-mingw-exec
new file mode 100644
index 0000000..4b808d0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-386-mingw-exec
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-386-mingw-obj b/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-386-mingw-obj
new file mode 100644
index 0000000..0c84d89
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-386-mingw-obj
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-amd64-mingw-exec b/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-amd64-mingw-exec
new file mode 100644
index 0000000..78d4e5f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-amd64-mingw-exec
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-amd64-mingw-obj b/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-amd64-mingw-obj
new file mode 100644
index 0000000..48ae792
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/pe/testdata/gcc-amd64-mingw-obj
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/pe/testdata/hello.c b/third_party/gofrontend/libgo/go/debug/pe/testdata/hello.c
new file mode 100644
index 0000000..a689d36
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/pe/testdata/hello.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int
+main(void)
+{
+	printf("hello, world\n");
+	return 0;
+}
diff --git a/third_party/gofrontend/libgo/go/debug/plan9obj/file.go b/third_party/gofrontend/libgo/go/debug/plan9obj/file.go
new file mode 100644
index 0000000..60a5857
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/plan9obj/file.go
@@ -0,0 +1,325 @@
+// Copyright 2014 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 plan9obj implements access to Plan 9 a.out object files.
+package plan9obj
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"os"
+)
+
+// A FileHeader represents a Plan 9 a.out file header.
+type FileHeader struct {
+	Magic   uint32
+	Bss     uint32
+	Entry   uint64
+	PtrSize int
+}
+
+// A File represents an open Plan 9 a.out file.
+type File struct {
+	FileHeader
+	Sections []*Section
+	closer   io.Closer
+}
+
+// A SectionHeader represents a single Plan 9 a.out section header.
+// This structure doesn't exist on-disk, but eases navigation
+// through the object file.
+type SectionHeader struct {
+	Name   string
+	Size   uint32
+	Offset uint32
+}
+
+// A Section represents a single section in a Plan 9 a.out file.
+type Section struct {
+	SectionHeader
+
+	// Embed ReaderAt for ReadAt method.
+	// Do not embed SectionReader directly
+	// to avoid having Read and Seek.
+	// If a client wants Read and Seek it must use
+	// Open() to avoid fighting over the seek offset
+	// with other clients.
+	io.ReaderAt
+	sr *io.SectionReader
+}
+
+// Data reads and returns the contents of the Plan 9 a.out section.
+func (s *Section) Data() ([]byte, error) {
+	dat := make([]byte, s.sr.Size())
+	n, err := s.sr.ReadAt(dat, 0)
+	if n == len(dat) {
+		err = nil
+	}
+	return dat[0:n], err
+}
+
+// Open returns a new ReadSeeker reading the Plan 9 a.out section.
+func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
+
+// A Symbol represents an entry in a Plan 9 a.out symbol table section.
+type Sym struct {
+	Value uint64
+	Type  rune
+	Name  string
+}
+
+/*
+ * Plan 9 a.out reader
+ */
+
+// formatError is returned by some operations if the data does
+// not have the correct format for an object file.
+type formatError struct {
+	off int
+	msg string
+	val interface{}
+}
+
+func (e *formatError) Error() string {
+	msg := e.msg
+	if e.val != nil {
+		msg += fmt.Sprintf(" '%v'", e.val)
+	}
+	msg += fmt.Sprintf(" in record at byte %#x", e.off)
+	return msg
+}
+
+// Open opens the named file using os.Open and prepares it for use as a Plan 9 a.out binary.
+func Open(name string) (*File, error) {
+	f, err := os.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	ff, err := NewFile(f)
+	if err != nil {
+		f.Close()
+		return nil, err
+	}
+	ff.closer = f
+	return ff, nil
+}
+
+// Close closes the File.
+// If the File was created using NewFile directly instead of Open,
+// Close has no effect.
+func (f *File) Close() error {
+	var err error
+	if f.closer != nil {
+		err = f.closer.Close()
+		f.closer = nil
+	}
+	return err
+}
+
+func parseMagic(magic []byte) (uint32, error) {
+	m := binary.BigEndian.Uint32(magic)
+	switch m {
+	case Magic386, MagicAMD64, MagicARM:
+		return m, nil
+	}
+	return 0, &formatError{0, "bad magic number", magic}
+}
+
+// NewFile creates a new File for accessing a Plan 9 binary in an underlying reader.
+// The Plan 9 binary is expected to start at position 0 in the ReaderAt.
+func NewFile(r io.ReaderAt) (*File, error) {
+	sr := io.NewSectionReader(r, 0, 1<<63-1)
+	// Read and decode Plan 9 magic
+	var magic [4]byte
+	if _, err := r.ReadAt(magic[:], 0); err != nil {
+		return nil, err
+	}
+	_, err := parseMagic(magic[:])
+	if err != nil {
+		return nil, err
+	}
+
+	ph := new(prog)
+	if err := binary.Read(sr, binary.BigEndian, ph); err != nil {
+		return nil, err
+	}
+
+	f := &File{FileHeader: FileHeader{
+		Magic:   ph.Magic,
+		Bss:     ph.Bss,
+		Entry:   uint64(ph.Entry),
+		PtrSize: 4,
+	}}
+
+	hdrSize := 4 * 8
+
+	if ph.Magic&Magic64 != 0 {
+		if err := binary.Read(sr, binary.BigEndian, &f.Entry); err != nil {
+			return nil, err
+		}
+		f.PtrSize = 8
+		hdrSize += 8
+	}
+
+	var sects = []struct {
+		name string
+		size uint32
+	}{
+		{"text", ph.Text},
+		{"data", ph.Data},
+		{"syms", ph.Syms},
+		{"spsz", ph.Spsz},
+		{"pcsz", ph.Pcsz},
+	}
+
+	f.Sections = make([]*Section, 5)
+
+	off := uint32(hdrSize)
+
+	for i, sect := range sects {
+		s := new(Section)
+		s.SectionHeader = SectionHeader{
+			Name:   sect.name,
+			Size:   sect.size,
+			Offset: off,
+		}
+		off += sect.size
+		s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Size))
+		s.ReaderAt = s.sr
+		f.Sections[i] = s
+	}
+
+	return f, nil
+}
+
+func walksymtab(data []byte, ptrsz int, fn func(sym) error) error {
+	var order binary.ByteOrder = binary.BigEndian
+	var s sym
+	p := data
+	for len(p) >= 4 {
+		// Symbol type, value.
+		if len(p) < ptrsz {
+			return &formatError{len(data), "unexpected EOF", nil}
+		}
+		// fixed-width value
+		if ptrsz == 8 {
+			s.value = order.Uint64(p[0:8])
+			p = p[8:]
+		} else {
+			s.value = uint64(order.Uint32(p[0:4]))
+			p = p[4:]
+		}
+
+		var typ byte
+		typ = p[0] & 0x7F
+		s.typ = typ
+		p = p[1:]
+
+		// Name.
+		var i int
+		var nnul int
+		for i = 0; i < len(p); i++ {
+			if p[i] == 0 {
+				nnul = 1
+				break
+			}
+		}
+		switch typ {
+		case 'z', 'Z':
+			p = p[i+nnul:]
+			for i = 0; i+2 <= len(p); i += 2 {
+				if p[i] == 0 && p[i+1] == 0 {
+					nnul = 2
+					break
+				}
+			}
+		}
+		if len(p) < i+nnul {
+			return &formatError{len(data), "unexpected EOF", nil}
+		}
+		s.name = p[0:i]
+		i += nnul
+		p = p[i:]
+
+		fn(s)
+	}
+	return nil
+}
+
+// NewTable decodes the Go symbol table in data,
+// returning an in-memory representation.
+func newTable(symtab []byte, ptrsz int) ([]Sym, error) {
+	var n int
+	err := walksymtab(symtab, ptrsz, func(s sym) error {
+		n++
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	fname := make(map[uint16]string)
+	syms := make([]Sym, 0, n)
+	err = walksymtab(symtab, ptrsz, func(s sym) error {
+		n := len(syms)
+		syms = syms[0 : n+1]
+		ts := &syms[n]
+		ts.Type = rune(s.typ)
+		ts.Value = s.value
+		switch s.typ {
+		default:
+			ts.Name = string(s.name[:])
+		case 'z', 'Z':
+			for i := 0; i < len(s.name); i += 2 {
+				eltIdx := binary.BigEndian.Uint16(s.name[i : i+2])
+				elt, ok := fname[eltIdx]
+				if !ok {
+					return &formatError{-1, "bad filename code", eltIdx}
+				}
+				if n := len(ts.Name); n > 0 && ts.Name[n-1] != '/' {
+					ts.Name += "/"
+				}
+				ts.Name += elt
+			}
+		}
+		switch s.typ {
+		case 'f':
+			fname[uint16(s.value)] = ts.Name
+		}
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return syms, nil
+}
+
+// Symbols returns the symbol table for f.
+func (f *File) Symbols() ([]Sym, error) {
+	symtabSection := f.Section("syms")
+	if symtabSection == nil {
+		return nil, errors.New("no symbol section")
+	}
+
+	symtab, err := symtabSection.Data()
+	if err != nil {
+		return nil, errors.New("cannot load symbol section")
+	}
+
+	return newTable(symtab, f.PtrSize)
+}
+
+// Section returns a section with the given name, or nil if no such
+// section exists.
+func (f *File) Section(name string) *Section {
+	for _, s := range f.Sections {
+		if s.Name == name {
+			return s
+		}
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/debug/plan9obj/file_test.go b/third_party/gofrontend/libgo/go/debug/plan9obj/file_test.go
new file mode 100644
index 0000000..96186d8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/plan9obj/file_test.go
@@ -0,0 +1,81 @@
+// Copyright 2014 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 plan9obj
+
+import (
+	"reflect"
+	"testing"
+)
+
+type fileTest struct {
+	file     string
+	hdr      FileHeader
+	sections []*SectionHeader
+}
+
+var fileTests = []fileTest{
+	{
+		"testdata/386-plan9-exec",
+		FileHeader{Magic386, 0x324, 0x14, 4},
+		[]*SectionHeader{
+			{"text", 0x4c5f, 0x20},
+			{"data", 0x94c, 0x4c7f},
+			{"syms", 0x2c2b, 0x55cb},
+			{"spsz", 0x0, 0x81f6},
+			{"pcsz", 0xf7a, 0x81f6},
+		},
+	},
+	{
+		"testdata/amd64-plan9-exec",
+		FileHeader{MagicAMD64, 0x618, 0x13, 8},
+		[]*SectionHeader{
+			{"text", 0x4213, 0x28},
+			{"data", 0xa80, 0x423b},
+			{"syms", 0x2c8c, 0x4cbb},
+			{"spsz", 0x0, 0x7947},
+			{"pcsz", 0xca0, 0x7947},
+		},
+	},
+}
+
+func TestOpen(t *testing.T) {
+	for i := range fileTests {
+		tt := &fileTests[i]
+
+		f, err := Open(tt.file)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
+			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
+			continue
+		}
+
+		for i, sh := range f.Sections {
+			if i >= len(tt.sections) {
+				break
+			}
+			have := &sh.SectionHeader
+			want := tt.sections[i]
+			if !reflect.DeepEqual(have, want) {
+				t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
+			}
+		}
+		tn := len(tt.sections)
+		fn := len(f.Sections)
+		if tn != fn {
+			t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
+		}
+	}
+}
+
+func TestOpenFailure(t *testing.T) {
+	filename := "file.go"    // not a Plan 9 a.out file
+	_, err := Open(filename) // don't crash
+	if err == nil {
+		t.Errorf("open %s: succeeded unexpectedly", filename)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/debug/plan9obj/plan9obj.go b/third_party/gofrontend/libgo/go/debug/plan9obj/plan9obj.go
new file mode 100644
index 0000000..af98585
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/plan9obj/plan9obj.go
@@ -0,0 +1,36 @@
+// Copyright 2014 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.
+
+/*
+ * Plan 9 a.out constants and data structures
+ */
+
+package plan9obj
+
+// Plan 9 Program header.
+type prog struct {
+	Magic uint32 /* magic number */
+	Text  uint32 /* size of text segment */
+	Data  uint32 /* size of initialized data */
+	Bss   uint32 /* size of uninitialized data */
+	Syms  uint32 /* size of symbol table */
+	Entry uint32 /* entry point */
+	Spsz  uint32 /* size of pc/sp offset table */
+	Pcsz  uint32 /* size of pc/line number table */
+}
+
+// Plan 9 symbol table entries.
+type sym struct {
+	value uint64
+	typ   byte
+	name  []byte
+}
+
+const (
+	Magic64 = 0x8000 // 64-bit expanded header
+
+	Magic386   = (4*11+0)*11 + 7
+	MagicAMD64 = (4*26+0)*26 + 7 + Magic64
+	MagicARM   = (4*20+0)*20 + 7
+)
diff --git a/third_party/gofrontend/libgo/go/debug/plan9obj/testdata/386-plan9-exec b/third_party/gofrontend/libgo/go/debug/plan9obj/testdata/386-plan9-exec
new file mode 100644
index 0000000..748e83f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/plan9obj/testdata/386-plan9-exec
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/plan9obj/testdata/amd64-plan9-exec b/third_party/gofrontend/libgo/go/debug/plan9obj/testdata/amd64-plan9-exec
new file mode 100644
index 0000000..3e257dd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/plan9obj/testdata/amd64-plan9-exec
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/debug/plan9obj/testdata/hello.c b/third_party/gofrontend/libgo/go/debug/plan9obj/testdata/hello.c
new file mode 100644
index 0000000..c0d633e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/debug/plan9obj/testdata/hello.c
@@ -0,0 +1,8 @@
+#include <u.h>
+#include <libc.h>
+
+void
+main(void)
+{
+	print("hello, world\n");
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/ascii85/ascii85.go b/third_party/gofrontend/libgo/go/encoding/ascii85/ascii85.go
new file mode 100644
index 0000000..60da304
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/ascii85/ascii85.go
@@ -0,0 +1,311 @@
+// 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 ascii85 implements the ascii85 data encoding
+// as used in the btoa tool and Adobe's PostScript and PDF document formats.
+package ascii85
+
+import (
+	"io"
+	"strconv"
+)
+
+/*
+ * Encoder
+ */
+
+// Encode encodes src into at most MaxEncodedLen(len(src))
+// bytes of dst, returning the actual number of bytes written.
+//
+// The encoding handles 4-byte chunks, using a special encoding
+// for the last fragment, so Encode is not appropriate for use on
+// individual blocks of a large data stream.  Use NewEncoder() instead.
+//
+// Often, ascii85-encoded data is wrapped in <~ and ~> symbols.
+// Encode does not add these.
+func Encode(dst, src []byte) int {
+	if len(src) == 0 {
+		return 0
+	}
+
+	n := 0
+	for len(src) > 0 {
+		dst[0] = 0
+		dst[1] = 0
+		dst[2] = 0
+		dst[3] = 0
+		dst[4] = 0
+
+		// Unpack 4 bytes into uint32 to repack into base 85 5-byte.
+		var v uint32
+		switch len(src) {
+		default:
+			v |= uint32(src[3])
+			fallthrough
+		case 3:
+			v |= uint32(src[2]) << 8
+			fallthrough
+		case 2:
+			v |= uint32(src[1]) << 16
+			fallthrough
+		case 1:
+			v |= uint32(src[0]) << 24
+		}
+
+		// Special case: zero (!!!!!) shortens to z.
+		if v == 0 && len(src) >= 4 {
+			dst[0] = 'z'
+			dst = dst[1:]
+			src = src[4:]
+			n++
+			continue
+		}
+
+		// Otherwise, 5 base 85 digits starting at !.
+		for i := 4; i >= 0; i-- {
+			dst[i] = '!' + byte(v%85)
+			v /= 85
+		}
+
+		// If src was short, discard the low destination bytes.
+		m := 5
+		if len(src) < 4 {
+			m -= 4 - len(src)
+			src = nil
+		} else {
+			src = src[4:]
+		}
+		dst = dst[m:]
+		n += m
+	}
+	return n
+}
+
+// MaxEncodedLen returns the maximum length of an encoding of n source bytes.
+func MaxEncodedLen(n int) int { return (n + 3) / 4 * 5 }
+
+// NewEncoder returns a new ascii85 stream encoder.  Data written to
+// the returned writer will be encoded and then written to w.
+// Ascii85 encodings operate in 32-bit blocks; when finished
+// writing, the caller must Close the returned encoder to flush any
+// trailing partial block.
+func NewEncoder(w io.Writer) io.WriteCloser { return &encoder{w: w} }
+
+type encoder struct {
+	err  error
+	w    io.Writer
+	buf  [4]byte    // buffered data waiting to be encoded
+	nbuf int        // number of bytes in buf
+	out  [1024]byte // output buffer
+}
+
+func (e *encoder) Write(p []byte) (n int, err error) {
+	if e.err != nil {
+		return 0, e.err
+	}
+
+	// Leading fringe.
+	if e.nbuf > 0 {
+		var i int
+		for i = 0; i < len(p) && e.nbuf < 4; i++ {
+			e.buf[e.nbuf] = p[i]
+			e.nbuf++
+		}
+		n += i
+		p = p[i:]
+		if e.nbuf < 4 {
+			return
+		}
+		nout := Encode(e.out[0:], e.buf[0:])
+		if _, e.err = e.w.Write(e.out[0:nout]); e.err != nil {
+			return n, e.err
+		}
+		e.nbuf = 0
+	}
+
+	// Large interior chunks.
+	for len(p) >= 4 {
+		nn := len(e.out) / 5 * 4
+		if nn > len(p) {
+			nn = len(p)
+		}
+		nn -= nn % 4
+		if nn > 0 {
+			nout := Encode(e.out[0:], p[0:nn])
+			if _, e.err = e.w.Write(e.out[0:nout]); e.err != nil {
+				return n, e.err
+			}
+		}
+		n += nn
+		p = p[nn:]
+	}
+
+	// Trailing fringe.
+	for i := 0; i < len(p); i++ {
+		e.buf[i] = p[i]
+	}
+	e.nbuf = len(p)
+	n += len(p)
+	return
+}
+
+// Close flushes any pending output from the encoder.
+// It is an error to call Write after calling Close.
+func (e *encoder) Close() error {
+	// If there's anything left in the buffer, flush it out
+	if e.err == nil && e.nbuf > 0 {
+		nout := Encode(e.out[0:], e.buf[0:e.nbuf])
+		e.nbuf = 0
+		_, e.err = e.w.Write(e.out[0:nout])
+	}
+	return e.err
+}
+
+/*
+ * Decoder
+ */
+
+type CorruptInputError int64
+
+func (e CorruptInputError) Error() string {
+	return "illegal ascii85 data at input byte " + strconv.FormatInt(int64(e), 10)
+}
+
+// Decode decodes src into dst, returning both the number
+// of bytes written to dst and the number consumed from src.
+// If src contains invalid ascii85 data, Decode will return the
+// number of bytes successfully written and a CorruptInputError.
+// Decode ignores space and control characters in src.
+// Often, ascii85-encoded data is wrapped in <~ and ~> symbols.
+// Decode expects these to have been stripped by the caller.
+//
+// If flush is true, Decode assumes that src represents the
+// end of the input stream and processes it completely rather
+// than wait for the completion of another 32-bit block.
+//
+// NewDecoder wraps an io.Reader interface around Decode.
+//
+func Decode(dst, src []byte, flush bool) (ndst, nsrc int, err error) {
+	var v uint32
+	var nb int
+	for i, b := range src {
+		if len(dst)-ndst < 4 {
+			return
+		}
+		switch {
+		case b <= ' ':
+			continue
+		case b == 'z' && nb == 0:
+			nb = 5
+			v = 0
+		case '!' <= b && b <= 'u':
+			v = v*85 + uint32(b-'!')
+			nb++
+		default:
+			return 0, 0, CorruptInputError(i)
+		}
+		if nb == 5 {
+			nsrc = i + 1
+			dst[ndst] = byte(v >> 24)
+			dst[ndst+1] = byte(v >> 16)
+			dst[ndst+2] = byte(v >> 8)
+			dst[ndst+3] = byte(v)
+			ndst += 4
+			nb = 0
+			v = 0
+		}
+	}
+	if flush {
+		nsrc = len(src)
+		if nb > 0 {
+			// The number of output bytes in the last fragment
+			// is the number of leftover input bytes - 1:
+			// the extra byte provides enough bits to cover
+			// the inefficiency of the encoding for the block.
+			if nb == 1 {
+				return 0, 0, CorruptInputError(len(src))
+			}
+			for i := nb; i < 5; i++ {
+				// The short encoding truncated the output value.
+				// We have to assume the worst case values (digit 84)
+				// in order to ensure that the top bits are correct.
+				v = v*85 + 84
+			}
+			for i := 0; i < nb-1; i++ {
+				dst[ndst] = byte(v >> 24)
+				v <<= 8
+				ndst++
+			}
+		}
+	}
+	return
+}
+
+// NewDecoder constructs a new ascii85 stream decoder.
+func NewDecoder(r io.Reader) io.Reader { return &decoder{r: r} }
+
+type decoder struct {
+	err     error
+	readErr error
+	r       io.Reader
+	end     bool       // saw end of message
+	buf     [1024]byte // leftover input
+	nbuf    int
+	out     []byte // leftover decoded output
+	outbuf  [1024]byte
+}
+
+func (d *decoder) Read(p []byte) (n int, err error) {
+	if len(p) == 0 {
+		return 0, nil
+	}
+	if d.err != nil {
+		return 0, d.err
+	}
+
+	for {
+		// Copy leftover output from last decode.
+		if len(d.out) > 0 {
+			n = copy(p, d.out)
+			d.out = d.out[n:]
+			return
+		}
+
+		// Decode leftover input from last read.
+		var nn, nsrc, ndst int
+		if d.nbuf > 0 {
+			ndst, nsrc, d.err = Decode(d.outbuf[0:], d.buf[0:d.nbuf], d.readErr != nil)
+			if ndst > 0 {
+				d.out = d.outbuf[0:ndst]
+				d.nbuf = copy(d.buf[0:], d.buf[nsrc:d.nbuf])
+				continue // copy out and return
+			}
+			if ndst == 0 && d.err == nil {
+				// Special case: input buffer is mostly filled with non-data bytes.
+				// Filter out such bytes to make room for more input.
+				off := 0
+				for i := 0; i < d.nbuf; i++ {
+					if d.buf[i] > ' ' {
+						d.buf[off] = d.buf[i]
+						off++
+					}
+				}
+				d.nbuf = off
+			}
+		}
+
+		// Out of input, out of decoded output.  Check errors.
+		if d.err != nil {
+			return 0, d.err
+		}
+		if d.readErr != nil {
+			d.err = d.readErr
+			return 0, d.err
+		}
+
+		// Read more data.
+		nn, d.readErr = d.r.Read(d.buf[d.nbuf:])
+		d.nbuf += nn
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/ascii85/ascii85_test.go b/third_party/gofrontend/libgo/go/encoding/ascii85/ascii85_test.go
new file mode 100644
index 0000000..aad199b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/ascii85/ascii85_test.go
@@ -0,0 +1,210 @@
+// 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 ascii85
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+type testpair struct {
+	decoded, encoded string
+}
+
+var pairs = []testpair{
+	// Encode returns 0 when len(src) is 0
+	{
+		"",
+		"",
+	},
+	// Wikipedia example
+	{
+		"Man is distinguished, not only by his reason, but by this singular passion from " +
+			"other animals, which is a lust of the mind, that by a perseverance of delight in " +
+			"the continued and indefatigable generation of knowledge, exceeds the short " +
+			"vehemence of any carnal pleasure.",
+		"9jqo^BlbD-BleB1DJ+*+F(f,q/0JhKF<GL>Cj@.4Gp$d7F!,L7@<6@)/0JDEF<G%<+EV:2F!,\n" +
+			"O<DJ+*.@<*K0@<6L(Df-\\0Ec5e;DffZ(EZee.Bl.9pF\"AGXBPCsi+DGm>@3BB/F*&OCAfu2/AKY\n" +
+			"i(DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIa\n" +
+			"l(DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G\n" +
+			">uD.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c\n",
+	},
+	// Special case when shortening !!!!! to z.
+	{
+		"\000\000\000\000",
+		"z",
+	},
+}
+
+var bigtest = pairs[len(pairs)-1]
+
+func testEqual(t *testing.T, msg string, args ...interface{}) bool {
+	if args[len(args)-2] != args[len(args)-1] {
+		t.Errorf(msg, args...)
+		return false
+	}
+	return true
+}
+
+func strip85(s string) string {
+	t := make([]byte, len(s))
+	w := 0
+	for r := 0; r < len(s); r++ {
+		c := s[r]
+		if c > ' ' {
+			t[w] = c
+			w++
+		}
+	}
+	return string(t[0:w])
+}
+
+func TestEncode(t *testing.T) {
+	for _, p := range pairs {
+		buf := make([]byte, MaxEncodedLen(len(p.decoded)))
+		n := Encode(buf, []byte(p.decoded))
+		buf = buf[0:n]
+		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, strip85(string(buf)), strip85(p.encoded))
+	}
+}
+
+func TestEncoder(t *testing.T) {
+	for _, p := range pairs {
+		bb := &bytes.Buffer{}
+		encoder := NewEncoder(bb)
+		encoder.Write([]byte(p.decoded))
+		encoder.Close()
+		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, strip85(bb.String()), strip85(p.encoded))
+	}
+}
+
+func TestEncoderBuffering(t *testing.T) {
+	input := []byte(bigtest.decoded)
+	for bs := 1; bs <= 12; bs++ {
+		bb := &bytes.Buffer{}
+		encoder := NewEncoder(bb)
+		for pos := 0; pos < len(input); pos += bs {
+			end := pos + bs
+			if end > len(input) {
+				end = len(input)
+			}
+			n, err := encoder.Write(input[pos:end])
+			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
+			testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
+		}
+		err := encoder.Close()
+		testEqual(t, "Close gave error %v, want %v", err, error(nil))
+		testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, strip85(bb.String()), strip85(bigtest.encoded))
+	}
+}
+
+func TestDecode(t *testing.T) {
+	for _, p := range pairs {
+		dbuf := make([]byte, 4*len(p.encoded))
+		ndst, nsrc, err := Decode(dbuf, []byte(p.encoded), true)
+		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
+		testEqual(t, "Decode(%q) = nsrc %v, want %v", p.encoded, nsrc, len(p.encoded))
+		testEqual(t, "Decode(%q) = ndst %v, want %v", p.encoded, ndst, len(p.decoded))
+		testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:ndst]), p.decoded)
+	}
+}
+
+func TestDecoder(t *testing.T) {
+	for _, p := range pairs {
+		decoder := NewDecoder(strings.NewReader(p.encoded))
+		dbuf, err := ioutil.ReadAll(decoder)
+		if err != nil {
+			t.Fatal("Read failed", err)
+		}
+		testEqual(t, "Read from %q = length %v, want %v", p.encoded, len(dbuf), len(p.decoded))
+		testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf), p.decoded)
+		if err != nil {
+			testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
+		}
+	}
+}
+
+func TestDecoderBuffering(t *testing.T) {
+	for bs := 1; bs <= 12; bs++ {
+		decoder := NewDecoder(strings.NewReader(bigtest.encoded))
+		buf := make([]byte, len(bigtest.decoded)+12)
+		var total int
+		for total = 0; total < len(bigtest.decoded); {
+			n, err := decoder.Read(buf[total : total+bs])
+			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, error(nil))
+			total += n
+		}
+		testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
+	}
+}
+
+func TestDecodeCorrupt(t *testing.T) {
+	type corrupt struct {
+		e string
+		p int
+	}
+	examples := []corrupt{
+		{"v", 0},
+		{"!z!!!!!!!!!", 1},
+	}
+
+	for _, e := range examples {
+		dbuf := make([]byte, 4*len(e.e))
+		_, _, err := Decode(dbuf, []byte(e.e), true)
+		switch err := err.(type) {
+		case CorruptInputError:
+			testEqual(t, "Corruption in %q at offset %v, want %v", e.e, int(err), e.p)
+		default:
+			t.Error("Decoder failed to detect corruption in", e)
+		}
+	}
+}
+
+func TestBig(t *testing.T) {
+	n := 3*1000 + 1
+	raw := make([]byte, n)
+	const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	for i := 0; i < n; i++ {
+		raw[i] = alpha[i%len(alpha)]
+	}
+	encoded := new(bytes.Buffer)
+	w := NewEncoder(encoded)
+	nn, err := w.Write(raw)
+	if nn != n || err != nil {
+		t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n)
+	}
+	err = w.Close()
+	if err != nil {
+		t.Fatalf("Encoder.Close() = %v want nil", err)
+	}
+	decoded, err := ioutil.ReadAll(NewDecoder(encoded))
+	if err != nil {
+		t.Fatalf("io.ReadAll(NewDecoder(...)): %v", err)
+	}
+
+	if !bytes.Equal(raw, decoded) {
+		var i int
+		for i = 0; i < len(decoded) && i < len(raw); i++ {
+			if decoded[i] != raw[i] {
+				break
+			}
+		}
+		t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i)
+	}
+}
+
+func TestDecoderInternalWhitespace(t *testing.T) {
+	s := strings.Repeat(" ", 2048) + "z"
+	decoded, err := ioutil.ReadAll(NewDecoder(strings.NewReader(s)))
+	if err != nil {
+		t.Errorf("Decode gave error %v", err)
+	}
+	if want := []byte("\000\000\000\000"); !bytes.Equal(want, decoded) {
+		t.Errorf("Decode failed: got %v, want %v", decoded, want)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/asn1/asn1.go b/third_party/gofrontend/libgo/go/encoding/asn1/asn1.go
new file mode 100644
index 0000000..ec7f91c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/asn1/asn1.go
@@ -0,0 +1,908 @@
+// 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 asn1 implements parsing of DER-encoded ASN.1 data structures,
+// as defined in ITU-T Rec X.690.
+//
+// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,''
+// http://luca.ntop.org/Teaching/Appunti/asn1.html.
+package asn1
+
+// ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc
+// are different encoding formats for those objects. Here, we'll be dealing
+// with DER, the Distinguished Encoding Rules. DER is used in X.509 because
+// it's fast to parse and, unlike BER, has a unique encoding for every object.
+// When calculating hashes over objects, it's important that the resulting
+// bytes be the same at both ends and DER removes this margin of error.
+//
+// ASN.1 is very complex and this package doesn't attempt to implement
+// everything by any means.
+
+import (
+	"fmt"
+	"math/big"
+	"reflect"
+	"strconv"
+	"time"
+)
+
+// A StructuralError suggests that the ASN.1 data is valid, but the Go type
+// which is receiving it doesn't match.
+type StructuralError struct {
+	Msg string
+}
+
+func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg }
+
+// A SyntaxError suggests that the ASN.1 data is invalid.
+type SyntaxError struct {
+	Msg string
+}
+
+func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg }
+
+// We start by dealing with each of the primitive types in turn.
+
+// BOOLEAN
+
+func parseBool(bytes []byte) (ret bool, err error) {
+	if len(bytes) != 1 {
+		err = SyntaxError{"invalid boolean"}
+		return
+	}
+
+	// DER demands that "If the encoding represents the boolean value TRUE,
+	// its single contents octet shall have all eight bits set to one."
+	// Thus only 0 and 255 are valid encoded values.
+	switch bytes[0] {
+	case 0:
+		ret = false
+	case 0xff:
+		ret = true
+	default:
+		err = SyntaxError{"invalid boolean"}
+	}
+
+	return
+}
+
+// INTEGER
+
+// parseInt64 treats the given bytes as a big-endian, signed integer and
+// returns the result.
+func parseInt64(bytes []byte) (ret int64, err error) {
+	if len(bytes) > 8 {
+		// We'll overflow an int64 in this case.
+		err = StructuralError{"integer too large"}
+		return
+	}
+	for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
+		ret <<= 8
+		ret |= int64(bytes[bytesRead])
+	}
+
+	// Shift up and down in order to sign extend the result.
+	ret <<= 64 - uint8(len(bytes))*8
+	ret >>= 64 - uint8(len(bytes))*8
+	return
+}
+
+// parseInt treats the given bytes as a big-endian, signed integer and returns
+// the result.
+func parseInt32(bytes []byte) (int32, error) {
+	ret64, err := parseInt64(bytes)
+	if err != nil {
+		return 0, err
+	}
+	if ret64 != int64(int32(ret64)) {
+		return 0, StructuralError{"integer too large"}
+	}
+	return int32(ret64), nil
+}
+
+var bigOne = big.NewInt(1)
+
+// parseBigInt treats the given bytes as a big-endian, signed integer and returns
+// the result.
+func parseBigInt(bytes []byte) *big.Int {
+	ret := new(big.Int)
+	if len(bytes) > 0 && bytes[0]&0x80 == 0x80 {
+		// This is a negative number.
+		notBytes := make([]byte, len(bytes))
+		for i := range notBytes {
+			notBytes[i] = ^bytes[i]
+		}
+		ret.SetBytes(notBytes)
+		ret.Add(ret, bigOne)
+		ret.Neg(ret)
+		return ret
+	}
+	ret.SetBytes(bytes)
+	return ret
+}
+
+// BIT STRING
+
+// BitString is the structure to use when you want an ASN.1 BIT STRING type. A
+// bit string is padded up to the nearest byte in memory and the number of
+// valid bits is recorded. Padding bits will be zero.
+type BitString struct {
+	Bytes     []byte // bits packed into bytes.
+	BitLength int    // length in bits.
+}
+
+// At returns the bit at the given index. If the index is out of range it
+// returns false.
+func (b BitString) At(i int) int {
+	if i < 0 || i >= b.BitLength {
+		return 0
+	}
+	x := i / 8
+	y := 7 - uint(i%8)
+	return int(b.Bytes[x]>>y) & 1
+}
+
+// RightAlign returns a slice where the padding bits are at the beginning. The
+// slice may share memory with the BitString.
+func (b BitString) RightAlign() []byte {
+	shift := uint(8 - (b.BitLength % 8))
+	if shift == 8 || len(b.Bytes) == 0 {
+		return b.Bytes
+	}
+
+	a := make([]byte, len(b.Bytes))
+	a[0] = b.Bytes[0] >> shift
+	for i := 1; i < len(b.Bytes); i++ {
+		a[i] = b.Bytes[i-1] << (8 - shift)
+		a[i] |= b.Bytes[i] >> shift
+	}
+
+	return a
+}
+
+// parseBitString parses an ASN.1 bit string from the given byte slice and returns it.
+func parseBitString(bytes []byte) (ret BitString, err error) {
+	if len(bytes) == 0 {
+		err = SyntaxError{"zero length BIT STRING"}
+		return
+	}
+	paddingBits := int(bytes[0])
+	if paddingBits > 7 ||
+		len(bytes) == 1 && paddingBits > 0 ||
+		bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {
+		err = SyntaxError{"invalid padding bits in BIT STRING"}
+		return
+	}
+	ret.BitLength = (len(bytes)-1)*8 - paddingBits
+	ret.Bytes = bytes[1:]
+	return
+}
+
+// OBJECT IDENTIFIER
+
+// An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER.
+type ObjectIdentifier []int
+
+// Equal reports whether oi and other represent the same identifier.
+func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool {
+	if len(oi) != len(other) {
+		return false
+	}
+	for i := 0; i < len(oi); i++ {
+		if oi[i] != other[i] {
+			return false
+		}
+	}
+
+	return true
+}
+
+func (oi ObjectIdentifier) String() string {
+	var s string
+
+	for i, v := range oi {
+		if i > 0 {
+			s += "."
+		}
+		s += strconv.Itoa(v)
+	}
+
+	return s
+}
+
+// parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and
+// returns it. An object identifier is a sequence of variable length integers
+// that are assigned in a hierarchy.
+func parseObjectIdentifier(bytes []byte) (s []int, err error) {
+	if len(bytes) == 0 {
+		err = SyntaxError{"zero length OBJECT IDENTIFIER"}
+		return
+	}
+
+	// In the worst case, we get two elements from the first byte (which is
+	// encoded differently) and then every varint is a single byte long.
+	s = make([]int, len(bytes)+1)
+
+	// The first varint is 40*value1 + value2:
+	// According to this packing, value1 can take the values 0, 1 and 2 only.
+	// When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,
+	// then there are no restrictions on value2.
+	v, offset, err := parseBase128Int(bytes, 0)
+	if err != nil {
+		return
+	}
+	if v < 80 {
+		s[0] = v / 40
+		s[1] = v % 40
+	} else {
+		s[0] = 2
+		s[1] = v - 80
+	}
+
+	i := 2
+	for ; offset < len(bytes); i++ {
+		v, offset, err = parseBase128Int(bytes, offset)
+		if err != nil {
+			return
+		}
+		s[i] = v
+	}
+	s = s[0:i]
+	return
+}
+
+// ENUMERATED
+
+// An Enumerated is represented as a plain int.
+type Enumerated int
+
+// FLAG
+
+// A Flag accepts any data and is set to true if present.
+type Flag bool
+
+// parseBase128Int parses a base-128 encoded int from the given offset in the
+// given byte slice. It returns the value and the new offset.
+func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) {
+	offset = initOffset
+	for shifted := 0; offset < len(bytes); shifted++ {
+		if shifted > 4 {
+			err = StructuralError{"base 128 integer too large"}
+			return
+		}
+		ret <<= 7
+		b := bytes[offset]
+		ret |= int(b & 0x7f)
+		offset++
+		if b&0x80 == 0 {
+			return
+		}
+	}
+	err = SyntaxError{"truncated base 128 integer"}
+	return
+}
+
+// UTCTime
+
+func parseUTCTime(bytes []byte) (ret time.Time, err error) {
+	s := string(bytes)
+	ret, err = time.Parse("0601021504Z0700", s)
+	if err != nil {
+		ret, err = time.Parse("060102150405Z0700", s)
+	}
+	if err == nil && ret.Year() >= 2050 {
+		// UTCTime only encodes times prior to 2050. See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
+		ret = ret.AddDate(-100, 0, 0)
+	}
+
+	return
+}
+
+// parseGeneralizedTime parses the GeneralizedTime from the given byte slice
+// and returns the resulting time.
+func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) {
+	return time.Parse("20060102150405Z0700", string(bytes))
+}
+
+// PrintableString
+
+// parsePrintableString parses a ASN.1 PrintableString from the given byte
+// array and returns it.
+func parsePrintableString(bytes []byte) (ret string, err error) {
+	for _, b := range bytes {
+		if !isPrintable(b) {
+			err = SyntaxError{"PrintableString contains invalid character"}
+			return
+		}
+	}
+	ret = string(bytes)
+	return
+}
+
+// isPrintable returns true iff the given b is in the ASN.1 PrintableString set.
+func isPrintable(b byte) bool {
+	return 'a' <= b && b <= 'z' ||
+		'A' <= b && b <= 'Z' ||
+		'0' <= b && b <= '9' ||
+		'\'' <= b && b <= ')' ||
+		'+' <= b && b <= '/' ||
+		b == ' ' ||
+		b == ':' ||
+		b == '=' ||
+		b == '?' ||
+		// This is technically not allowed in a PrintableString.
+		// However, x509 certificates with wildcard strings don't
+		// always use the correct string type so we permit it.
+		b == '*'
+}
+
+// IA5String
+
+// parseIA5String parses a ASN.1 IA5String (ASCII string) from the given
+// byte slice and returns it.
+func parseIA5String(bytes []byte) (ret string, err error) {
+	for _, b := range bytes {
+		if b >= 0x80 {
+			err = SyntaxError{"IA5String contains invalid character"}
+			return
+		}
+	}
+	ret = string(bytes)
+	return
+}
+
+// T61String
+
+// parseT61String parses a ASN.1 T61String (8-bit clean string) from the given
+// byte slice and returns it.
+func parseT61String(bytes []byte) (ret string, err error) {
+	return string(bytes), nil
+}
+
+// UTF8String
+
+// parseUTF8String parses a ASN.1 UTF8String (raw UTF-8) from the given byte
+// array and returns it.
+func parseUTF8String(bytes []byte) (ret string, err error) {
+	return string(bytes), nil
+}
+
+// A RawValue represents an undecoded ASN.1 object.
+type RawValue struct {
+	Class, Tag int
+	IsCompound bool
+	Bytes      []byte
+	FullBytes  []byte // includes the tag and length
+}
+
+// RawContent is used to signal that the undecoded, DER data needs to be
+// preserved for a struct. To use it, the first field of the struct must have
+// this type. It's an error for any of the other fields to have this type.
+type RawContent []byte
+
+// Tagging
+
+// parseTagAndLength parses an ASN.1 tag and length pair from the given offset
+// into a byte slice. It returns the parsed data and the new offset. SET and
+// SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we
+// don't distinguish between ordered and unordered objects in this code.
+func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) {
+	offset = initOffset
+	b := bytes[offset]
+	offset++
+	ret.class = int(b >> 6)
+	ret.isCompound = b&0x20 == 0x20
+	ret.tag = int(b & 0x1f)
+
+	// If the bottom five bits are set, then the tag number is actually base 128
+	// encoded afterwards
+	if ret.tag == 0x1f {
+		ret.tag, offset, err = parseBase128Int(bytes, offset)
+		if err != nil {
+			return
+		}
+	}
+	if offset >= len(bytes) {
+		err = SyntaxError{"truncated tag or length"}
+		return
+	}
+	b = bytes[offset]
+	offset++
+	if b&0x80 == 0 {
+		// The length is encoded in the bottom 7 bits.
+		ret.length = int(b & 0x7f)
+	} else {
+		// Bottom 7 bits give the number of length bytes to follow.
+		numBytes := int(b & 0x7f)
+		if numBytes == 0 {
+			err = SyntaxError{"indefinite length found (not DER)"}
+			return
+		}
+		ret.length = 0
+		for i := 0; i < numBytes; i++ {
+			if offset >= len(bytes) {
+				err = SyntaxError{"truncated tag or length"}
+				return
+			}
+			b = bytes[offset]
+			offset++
+			if ret.length >= 1<<23 {
+				// We can't shift ret.length up without
+				// overflowing.
+				err = StructuralError{"length too large"}
+				return
+			}
+			ret.length <<= 8
+			ret.length |= int(b)
+			if ret.length == 0 {
+				// DER requires that lengths be minimal.
+				err = StructuralError{"superfluous leading zeros in length"}
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse
+// a number of ASN.1 values from the given byte slice and returns them as a
+// slice of Go values of the given type.
+func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err error) {
+	expectedTag, compoundType, ok := getUniversalType(elemType)
+	if !ok {
+		err = StructuralError{"unknown Go type for slice"}
+		return
+	}
+
+	// First we iterate over the input and count the number of elements,
+	// checking that the types are correct in each case.
+	numElements := 0
+	for offset := 0; offset < len(bytes); {
+		var t tagAndLength
+		t, offset, err = parseTagAndLength(bytes, offset)
+		if err != nil {
+			return
+		}
+		switch t.tag {
+		case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
+			// We pretend that various other string types are
+			// PRINTABLE STRINGs so that a sequence of them can be
+			// parsed into a []string.
+			t.tag = tagPrintableString
+		case tagGeneralizedTime, tagUTCTime:
+			// Likewise, both time types are treated the same.
+			t.tag = tagUTCTime
+		}
+
+		if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag {
+			err = StructuralError{"sequence tag mismatch"}
+			return
+		}
+		if invalidLength(offset, t.length, len(bytes)) {
+			err = SyntaxError{"truncated sequence"}
+			return
+		}
+		offset += t.length
+		numElements++
+	}
+	ret = reflect.MakeSlice(sliceType, numElements, numElements)
+	params := fieldParameters{}
+	offset := 0
+	for i := 0; i < numElements; i++ {
+		offset, err = parseField(ret.Index(i), bytes, offset, params)
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+var (
+	bitStringType        = reflect.TypeOf(BitString{})
+	objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
+	enumeratedType       = reflect.TypeOf(Enumerated(0))
+	flagType             = reflect.TypeOf(Flag(false))
+	timeType             = reflect.TypeOf(time.Time{})
+	rawValueType         = reflect.TypeOf(RawValue{})
+	rawContentsType      = reflect.TypeOf(RawContent(nil))
+	bigIntType           = reflect.TypeOf(new(big.Int))
+)
+
+// invalidLength returns true iff offset + length > sliceLength, or if the
+// addition would overflow.
+func invalidLength(offset, length, sliceLength int) bool {
+	return offset+length < offset || offset+length > sliceLength
+}
+
+// parseField is the main parsing function. Given a byte slice and an offset
+// into the array, it will try to parse a suitable ASN.1 value out and store it
+// in the given Value.
+func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err error) {
+	offset = initOffset
+	fieldType := v.Type()
+
+	// If we have run out of data, it may be that there are optional elements at the end.
+	if offset == len(bytes) {
+		if !setDefaultValue(v, params) {
+			err = SyntaxError{"sequence truncated"}
+		}
+		return
+	}
+
+	// Deal with raw values.
+	if fieldType == rawValueType {
+		var t tagAndLength
+		t, offset, err = parseTagAndLength(bytes, offset)
+		if err != nil {
+			return
+		}
+		if invalidLength(offset, t.length, len(bytes)) {
+			err = SyntaxError{"data truncated"}
+			return
+		}
+		result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]}
+		offset += t.length
+		v.Set(reflect.ValueOf(result))
+		return
+	}
+
+	// Deal with the ANY type.
+	if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 {
+		var t tagAndLength
+		t, offset, err = parseTagAndLength(bytes, offset)
+		if err != nil {
+			return
+		}
+		if invalidLength(offset, t.length, len(bytes)) {
+			err = SyntaxError{"data truncated"}
+			return
+		}
+		var result interface{}
+		if !t.isCompound && t.class == classUniversal {
+			innerBytes := bytes[offset : offset+t.length]
+			switch t.tag {
+			case tagPrintableString:
+				result, err = parsePrintableString(innerBytes)
+			case tagIA5String:
+				result, err = parseIA5String(innerBytes)
+			case tagT61String:
+				result, err = parseT61String(innerBytes)
+			case tagUTF8String:
+				result, err = parseUTF8String(innerBytes)
+			case tagInteger:
+				result, err = parseInt64(innerBytes)
+			case tagBitString:
+				result, err = parseBitString(innerBytes)
+			case tagOID:
+				result, err = parseObjectIdentifier(innerBytes)
+			case tagUTCTime:
+				result, err = parseUTCTime(innerBytes)
+			case tagOctetString:
+				result = innerBytes
+			default:
+				// If we don't know how to handle the type, we just leave Value as nil.
+			}
+		}
+		offset += t.length
+		if err != nil {
+			return
+		}
+		if result != nil {
+			v.Set(reflect.ValueOf(result))
+		}
+		return
+	}
+	universalTag, compoundType, ok1 := getUniversalType(fieldType)
+	if !ok1 {
+		err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)}
+		return
+	}
+
+	t, offset, err := parseTagAndLength(bytes, offset)
+	if err != nil {
+		return
+	}
+	if params.explicit {
+		expectedClass := classContextSpecific
+		if params.application {
+			expectedClass = classApplication
+		}
+		if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) {
+			if t.length > 0 {
+				t, offset, err = parseTagAndLength(bytes, offset)
+				if err != nil {
+					return
+				}
+			} else {
+				if fieldType != flagType {
+					err = StructuralError{"zero length explicit tag was not an asn1.Flag"}
+					return
+				}
+				v.SetBool(true)
+				return
+			}
+		} else {
+			// The tags didn't match, it might be an optional element.
+			ok := setDefaultValue(v, params)
+			if ok {
+				offset = initOffset
+			} else {
+				err = StructuralError{"explicitly tagged member didn't match"}
+			}
+			return
+		}
+	}
+
+	// Special case for strings: all the ASN.1 string types map to the Go
+	// type string. getUniversalType returns the tag for PrintableString
+	// when it sees a string, so if we see a different string type on the
+	// wire, we change the universal type to match.
+	if universalTag == tagPrintableString {
+		switch t.tag {
+		case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
+			universalTag = t.tag
+		}
+	}
+
+	// Special case for time: UTCTime and GeneralizedTime both map to the
+	// Go type time.Time.
+	if universalTag == tagUTCTime && t.tag == tagGeneralizedTime {
+		universalTag = tagGeneralizedTime
+	}
+
+	if params.set {
+		universalTag = tagSet
+	}
+
+	expectedClass := classUniversal
+	expectedTag := universalTag
+
+	if !params.explicit && params.tag != nil {
+		expectedClass = classContextSpecific
+		expectedTag = *params.tag
+	}
+
+	if !params.explicit && params.application && params.tag != nil {
+		expectedClass = classApplication
+		expectedTag = *params.tag
+	}
+
+	// We have unwrapped any explicit tagging at this point.
+	if t.class != expectedClass || t.tag != expectedTag || t.isCompound != compoundType {
+		// Tags don't match. Again, it could be an optional element.
+		ok := setDefaultValue(v, params)
+		if ok {
+			offset = initOffset
+		} else {
+			err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)}
+		}
+		return
+	}
+	if invalidLength(offset, t.length, len(bytes)) {
+		err = SyntaxError{"data truncated"}
+		return
+	}
+	innerBytes := bytes[offset : offset+t.length]
+	offset += t.length
+
+	// We deal with the structures defined in this package first.
+	switch fieldType {
+	case objectIdentifierType:
+		newSlice, err1 := parseObjectIdentifier(innerBytes)
+		v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice)))
+		if err1 == nil {
+			reflect.Copy(v, reflect.ValueOf(newSlice))
+		}
+		err = err1
+		return
+	case bitStringType:
+		bs, err1 := parseBitString(innerBytes)
+		if err1 == nil {
+			v.Set(reflect.ValueOf(bs))
+		}
+		err = err1
+		return
+	case timeType:
+		var time time.Time
+		var err1 error
+		if universalTag == tagUTCTime {
+			time, err1 = parseUTCTime(innerBytes)
+		} else {
+			time, err1 = parseGeneralizedTime(innerBytes)
+		}
+		if err1 == nil {
+			v.Set(reflect.ValueOf(time))
+		}
+		err = err1
+		return
+	case enumeratedType:
+		parsedInt, err1 := parseInt32(innerBytes)
+		if err1 == nil {
+			v.SetInt(int64(parsedInt))
+		}
+		err = err1
+		return
+	case flagType:
+		v.SetBool(true)
+		return
+	case bigIntType:
+		parsedInt := parseBigInt(innerBytes)
+		v.Set(reflect.ValueOf(parsedInt))
+		return
+	}
+	switch val := v; val.Kind() {
+	case reflect.Bool:
+		parsedBool, err1 := parseBool(innerBytes)
+		if err1 == nil {
+			val.SetBool(parsedBool)
+		}
+		err = err1
+		return
+	case reflect.Int, reflect.Int32, reflect.Int64:
+		if val.Type().Size() == 4 {
+			parsedInt, err1 := parseInt32(innerBytes)
+			if err1 == nil {
+				val.SetInt(int64(parsedInt))
+			}
+			err = err1
+		} else {
+			parsedInt, err1 := parseInt64(innerBytes)
+			if err1 == nil {
+				val.SetInt(parsedInt)
+			}
+			err = err1
+		}
+		return
+	// TODO(dfc) Add support for the remaining integer types
+	case reflect.Struct:
+		structType := fieldType
+
+		if structType.NumField() > 0 &&
+			structType.Field(0).Type == rawContentsType {
+			bytes := bytes[initOffset:offset]
+			val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
+		}
+
+		innerOffset := 0
+		for i := 0; i < structType.NumField(); i++ {
+			field := structType.Field(i)
+			if i == 0 && field.Type == rawContentsType {
+				continue
+			}
+			innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1")))
+			if err != nil {
+				return
+			}
+		}
+		// We allow extra bytes at the end of the SEQUENCE because
+		// adding elements to the end has been used in X.509 as the
+		// version numbers have increased.
+		return
+	case reflect.Slice:
+		sliceType := fieldType
+		if sliceType.Elem().Kind() == reflect.Uint8 {
+			val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
+			reflect.Copy(val, reflect.ValueOf(innerBytes))
+			return
+		}
+		newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
+		if err1 == nil {
+			val.Set(newSlice)
+		}
+		err = err1
+		return
+	case reflect.String:
+		var v string
+		switch universalTag {
+		case tagPrintableString:
+			v, err = parsePrintableString(innerBytes)
+		case tagIA5String:
+			v, err = parseIA5String(innerBytes)
+		case tagT61String:
+			v, err = parseT61String(innerBytes)
+		case tagUTF8String:
+			v, err = parseUTF8String(innerBytes)
+		case tagGeneralString:
+			// GeneralString is specified in ISO-2022/ECMA-35,
+			// A brief review suggests that it includes structures
+			// that allow the encoding to change midstring and
+			// such. We give up and pass it as an 8-bit string.
+			v, err = parseT61String(innerBytes)
+		default:
+			err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
+		}
+		if err == nil {
+			val.SetString(v)
+		}
+		return
+	}
+	err = StructuralError{"unsupported: " + v.Type().String()}
+	return
+}
+
+// setDefaultValue is used to install a default value, from a tag string, into
+// a Value. It is successful is the field was optional, even if a default value
+// wasn't provided or it failed to install it into the Value.
+func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
+	if !params.optional {
+		return
+	}
+	ok = true
+	if params.defaultValue == nil {
+		return
+	}
+	switch val := v; val.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		val.SetInt(*params.defaultValue)
+	}
+	return
+}
+
+// Unmarshal parses the DER-encoded ASN.1 data structure b
+// and uses the reflect package to fill in an arbitrary value pointed at by val.
+// Because Unmarshal uses the reflect package, the structs
+// being written to must use upper case field names.
+//
+// An ASN.1 INTEGER can be written to an int, int32, int64,
+// or *big.Int (from the math/big package).
+// If the encoded value does not fit in the Go type,
+// Unmarshal returns a parse error.
+//
+// An ASN.1 BIT STRING can be written to a BitString.
+//
+// An ASN.1 OCTET STRING can be written to a []byte.
+//
+// An ASN.1 OBJECT IDENTIFIER can be written to an
+// ObjectIdentifier.
+//
+// An ASN.1 ENUMERATED can be written to an Enumerated.
+//
+// An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a time.Time.
+//
+// An ASN.1 PrintableString or IA5String can be written to a string.
+//
+// Any of the above ASN.1 values can be written to an interface{}.
+// The value stored in the interface has the corresponding Go type.
+// For integers, that type is int64.
+//
+// An ASN.1 SEQUENCE OF x or SET OF x can be written
+// to a slice if an x can be written to the slice's element type.
+//
+// An ASN.1 SEQUENCE or SET can be written to a struct
+// if each of the elements in the sequence can be
+// written to the corresponding element in the struct.
+//
+// The following tags on struct fields have special meaning to Unmarshal:
+//
+//	application	specifies that a APPLICATION tag is used
+//	default:x	sets the default value for optional integer fields
+//	explicit	specifies that an additional, explicit tag wraps the implicit one
+//	optional	marks the field as ASN.1 OPTIONAL
+//	set		causes a SET, rather than a SEQUENCE type to be expected
+//	tag:x		specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC
+//
+// If the type of the first field of a structure is RawContent then the raw
+// ASN1 contents of the struct will be stored in it.
+//
+// If the type name of a slice element ends with "SET" then it's treated as if
+// the "set" tag was set on it. This can be used with nested slices where a
+// struct tag cannot be given.
+//
+// Other ASN.1 types are not supported; if it encounters them,
+// Unmarshal returns a parse error.
+func Unmarshal(b []byte, val interface{}) (rest []byte, err error) {
+	return UnmarshalWithParams(b, val, "")
+}
+
+// UnmarshalWithParams allows field parameters to be specified for the
+// top-level element. The form of the params is the same as the field tags.
+func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err error) {
+	v := reflect.ValueOf(val).Elem()
+	offset, err := parseField(v, b, 0, parseFieldParameters(params))
+	if err != nil {
+		return nil, err
+	}
+	return b[offset:], nil
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/asn1/asn1_test.go b/third_party/gofrontend/libgo/go/encoding/asn1/asn1_test.go
new file mode 100644
index 0000000..b553f78
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/asn1/asn1_test.go
@@ -0,0 +1,814 @@
+// 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 asn1
+
+import (
+	"bytes"
+	"fmt"
+	"math/big"
+	"reflect"
+	"testing"
+	"time"
+)
+
+type boolTest struct {
+	in  []byte
+	ok  bool
+	out bool
+}
+
+var boolTestData = []boolTest{
+	{[]byte{0x00}, true, false},
+	{[]byte{0xff}, true, true},
+	{[]byte{0x00, 0x00}, false, false},
+	{[]byte{0xff, 0xff}, false, false},
+	{[]byte{0x01}, false, false},
+}
+
+func TestParseBool(t *testing.T) {
+	for i, test := range boolTestData {
+		ret, err := parseBool(test.in)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if test.ok && ret != test.out {
+			t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
+		}
+	}
+}
+
+type int64Test struct {
+	in  []byte
+	ok  bool
+	out int64
+}
+
+var int64TestData = []int64Test{
+	{[]byte{0x00}, true, 0},
+	{[]byte{0x7f}, true, 127},
+	{[]byte{0x00, 0x80}, true, 128},
+	{[]byte{0x01, 0x00}, true, 256},
+	{[]byte{0x80}, true, -128},
+	{[]byte{0xff, 0x7f}, true, -129},
+	{[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, true, -1},
+	{[]byte{0xff}, true, -1},
+	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, true, -9223372036854775808},
+	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, false, 0},
+}
+
+func TestParseInt64(t *testing.T) {
+	for i, test := range int64TestData {
+		ret, err := parseInt64(test.in)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if test.ok && ret != test.out {
+			t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
+		}
+	}
+}
+
+type int32Test struct {
+	in  []byte
+	ok  bool
+	out int32
+}
+
+var int32TestData = []int32Test{
+	{[]byte{0x00}, true, 0},
+	{[]byte{0x7f}, true, 127},
+	{[]byte{0x00, 0x80}, true, 128},
+	{[]byte{0x01, 0x00}, true, 256},
+	{[]byte{0x80}, true, -128},
+	{[]byte{0xff, 0x7f}, true, -129},
+	{[]byte{0xff, 0xff, 0xff, 0xff}, true, -1},
+	{[]byte{0xff}, true, -1},
+	{[]byte{0x80, 0x00, 0x00, 0x00}, true, -2147483648},
+	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00}, false, 0},
+}
+
+func TestParseInt32(t *testing.T) {
+	for i, test := range int32TestData {
+		ret, err := parseInt32(test.in)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if test.ok && int32(ret) != test.out {
+			t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
+		}
+	}
+}
+
+var bigIntTests = []struct {
+	in     []byte
+	base10 string
+}{
+	{[]byte{0xff}, "-1"},
+	{[]byte{0x00}, "0"},
+	{[]byte{0x01}, "1"},
+	{[]byte{0x00, 0xff}, "255"},
+	{[]byte{0xff, 0x00}, "-256"},
+	{[]byte{0x01, 0x00}, "256"},
+}
+
+func TestParseBigInt(t *testing.T) {
+	for i, test := range bigIntTests {
+		ret := parseBigInt(test.in)
+		if ret.String() != test.base10 {
+			t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10)
+		}
+		fw := newForkableWriter()
+		marshalBigInt(fw, ret)
+		result := fw.Bytes()
+		if !bytes.Equal(result, test.in) {
+			t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in)
+		}
+	}
+}
+
+type bitStringTest struct {
+	in        []byte
+	ok        bool
+	out       []byte
+	bitLength int
+}
+
+var bitStringTestData = []bitStringTest{
+	{[]byte{}, false, []byte{}, 0},
+	{[]byte{0x00}, true, []byte{}, 0},
+	{[]byte{0x07, 0x00}, true, []byte{0x00}, 1},
+	{[]byte{0x07, 0x01}, false, []byte{}, 0},
+	{[]byte{0x07, 0x40}, false, []byte{}, 0},
+	{[]byte{0x08, 0x00}, false, []byte{}, 0},
+}
+
+func TestBitString(t *testing.T) {
+	for i, test := range bitStringTestData {
+		ret, err := parseBitString(test.in)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if err == nil {
+			if test.bitLength != ret.BitLength || !bytes.Equal(ret.Bytes, test.out) {
+				t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength)
+			}
+		}
+	}
+}
+
+func TestBitStringAt(t *testing.T) {
+	bs := BitString{[]byte{0x82, 0x40}, 16}
+	if bs.At(0) != 1 {
+		t.Error("#1: Failed")
+	}
+	if bs.At(1) != 0 {
+		t.Error("#2: Failed")
+	}
+	if bs.At(6) != 1 {
+		t.Error("#3: Failed")
+	}
+	if bs.At(9) != 1 {
+		t.Error("#4: Failed")
+	}
+	if bs.At(-1) != 0 {
+		t.Error("#5: Failed")
+	}
+	if bs.At(17) != 0 {
+		t.Error("#6: Failed")
+	}
+}
+
+type bitStringRightAlignTest struct {
+	in    []byte
+	inlen int
+	out   []byte
+}
+
+var bitStringRightAlignTests = []bitStringRightAlignTest{
+	{[]byte{0x80}, 1, []byte{0x01}},
+	{[]byte{0x80, 0x80}, 9, []byte{0x01, 0x01}},
+	{[]byte{}, 0, []byte{}},
+	{[]byte{0xce}, 8, []byte{0xce}},
+	{[]byte{0xce, 0x47}, 16, []byte{0xce, 0x47}},
+	{[]byte{0x34, 0x50}, 12, []byte{0x03, 0x45}},
+}
+
+func TestBitStringRightAlign(t *testing.T) {
+	for i, test := range bitStringRightAlignTests {
+		bs := BitString{test.in, test.inlen}
+		out := bs.RightAlign()
+		if !bytes.Equal(out, test.out) {
+			t.Errorf("#%d got: %x want: %x", i, out, test.out)
+		}
+	}
+}
+
+type objectIdentifierTest struct {
+	in  []byte
+	ok  bool
+	out []int
+}
+
+var objectIdentifierTestData = []objectIdentifierTest{
+	{[]byte{}, false, []int{}},
+	{[]byte{85}, true, []int{2, 5}},
+	{[]byte{85, 0x02}, true, []int{2, 5, 2}},
+	{[]byte{85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}},
+	{[]byte{0x81, 0x34, 0x03}, true, []int{2, 100, 3}},
+	{[]byte{85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
+}
+
+func TestObjectIdentifier(t *testing.T) {
+	for i, test := range objectIdentifierTestData {
+		ret, err := parseObjectIdentifier(test.in)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if err == nil {
+			if !reflect.DeepEqual(test.out, ret) {
+				t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
+			}
+		}
+	}
+
+	if s := ObjectIdentifier([]int{1, 2, 3, 4}).String(); s != "1.2.3.4" {
+		t.Errorf("bad ObjectIdentifier.String(). Got %s, want 1.2.3.4", s)
+	}
+}
+
+type timeTest struct {
+	in  string
+	ok  bool
+	out time.Time
+}
+
+var utcTestData = []timeTest{
+	{"910506164540-0700", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", -7*60*60))},
+	{"910506164540+0730", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", 7*60*60+30*60))},
+	{"910506234540Z", true, time.Date(1991, 05, 06, 23, 45, 40, 0, time.UTC)},
+	{"9105062345Z", true, time.Date(1991, 05, 06, 23, 45, 0, 0, time.UTC)},
+	{"5105062345Z", true, time.Date(1951, 05, 06, 23, 45, 0, 0, time.UTC)},
+	{"a10506234540Z", false, time.Time{}},
+	{"91a506234540Z", false, time.Time{}},
+	{"9105a6234540Z", false, time.Time{}},
+	{"910506a34540Z", false, time.Time{}},
+	{"910506334a40Z", false, time.Time{}},
+	{"91050633444aZ", false, time.Time{}},
+	{"910506334461Z", false, time.Time{}},
+	{"910506334400Za", false, time.Time{}},
+}
+
+func TestUTCTime(t *testing.T) {
+	for i, test := range utcTestData {
+		ret, err := parseUTCTime([]byte(test.in))
+		if err != nil {
+			if test.ok {
+				t.Errorf("#%d: parseUTCTime(%q) = error %v", i, test.in, err)
+			}
+			continue
+		}
+		if !test.ok {
+			t.Errorf("#%d: parseUTCTime(%q) succeeded, should have failed", i, test.in)
+			continue
+		}
+		const format = "Jan _2 15:04:05 -0700 2006" // ignore zone name, just offset
+		have := ret.Format(format)
+		want := test.out.Format(format)
+		if have != want {
+			t.Errorf("#%d: parseUTCTime(%q) = %s, want %s", i, test.in, have, want)
+		}
+	}
+}
+
+var generalizedTimeTestData = []timeTest{
+	{"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)},
+	{"20100102030405", false, time.Time{}},
+	{"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))},
+	{"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))},
+}
+
+func TestGeneralizedTime(t *testing.T) {
+	for i, test := range generalizedTimeTestData {
+		ret, err := parseGeneralizedTime([]byte(test.in))
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if err == nil {
+			if !reflect.DeepEqual(test.out, ret) {
+				t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
+			}
+		}
+	}
+}
+
+type tagAndLengthTest struct {
+	in  []byte
+	ok  bool
+	out tagAndLength
+}
+
+var tagAndLengthData = []tagAndLengthTest{
+	{[]byte{0x80, 0x01}, true, tagAndLength{2, 0, 1, false}},
+	{[]byte{0xa0, 0x01}, true, tagAndLength{2, 0, 1, true}},
+	{[]byte{0x02, 0x00}, true, tagAndLength{0, 2, 0, false}},
+	{[]byte{0xfe, 0x00}, true, tagAndLength{3, 30, 0, true}},
+	{[]byte{0x1f, 0x01, 0x00}, true, tagAndLength{0, 1, 0, false}},
+	{[]byte{0x1f, 0x81, 0x00, 0x00}, true, tagAndLength{0, 128, 0, false}},
+	{[]byte{0x1f, 0x81, 0x80, 0x01, 0x00}, true, tagAndLength{0, 0x4001, 0, false}},
+	{[]byte{0x00, 0x81, 0x01}, true, tagAndLength{0, 0, 1, false}},
+	{[]byte{0x00, 0x82, 0x01, 0x00}, true, tagAndLength{0, 0, 256, false}},
+	{[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}},
+	{[]byte{0x1f, 0x85}, false, tagAndLength{}},
+	{[]byte{0x30, 0x80}, false, tagAndLength{}},
+	// Superfluous zeros in the length should be an error.
+	{[]byte{0xa0, 0x82, 0x00, 0x01}, false, tagAndLength{}},
+	// Lengths up to the maximum size of an int should work.
+	{[]byte{0xa0, 0x84, 0x7f, 0xff, 0xff, 0xff}, true, tagAndLength{2, 0, 0x7fffffff, true}},
+	// Lengths that would overflow an int should be rejected.
+	{[]byte{0xa0, 0x84, 0x80, 0x00, 0x00, 0x00}, false, tagAndLength{}},
+}
+
+func TestParseTagAndLength(t *testing.T) {
+	for i, test := range tagAndLengthData {
+		tagAndLength, _, err := parseTagAndLength(test.in, 0)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did pass? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if err == nil && !reflect.DeepEqual(test.out, tagAndLength) {
+			t.Errorf("#%d: Bad result: %v (expected %v)", i, tagAndLength, test.out)
+		}
+	}
+}
+
+type parseFieldParametersTest struct {
+	in  string
+	out fieldParameters
+}
+
+func newInt(n int) *int { return &n }
+
+func newInt64(n int64) *int64 { return &n }
+
+func newString(s string) *string { return &s }
+
+func newBool(b bool) *bool { return &b }
+
+var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{
+	{"", fieldParameters{}},
+	{"ia5", fieldParameters{stringType: tagIA5String}},
+	{"printable", fieldParameters{stringType: tagPrintableString}},
+	{"optional", fieldParameters{optional: true}},
+	{"explicit", fieldParameters{explicit: true, tag: new(int)}},
+	{"application", fieldParameters{application: true, tag: new(int)}},
+	{"optional,explicit", fieldParameters{optional: true, explicit: true, tag: new(int)}},
+	{"default:42", fieldParameters{defaultValue: newInt64(42)}},
+	{"tag:17", fieldParameters{tag: newInt(17)}},
+	{"optional,explicit,default:42,tag:17", fieldParameters{optional: true, explicit: true, defaultValue: newInt64(42), tag: newInt(17)}},
+	{"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{true, true, false, newInt64(42), newInt(17), 0, false, false}},
+	{"set", fieldParameters{set: true}},
+}
+
+func TestParseFieldParameters(t *testing.T) {
+	for i, test := range parseFieldParametersTestData {
+		f := parseFieldParameters(test.in)
+		if !reflect.DeepEqual(f, test.out) {
+			t.Errorf("#%d: Bad result: %v (expected %v)", i, f, test.out)
+		}
+	}
+}
+
+type TestObjectIdentifierStruct struct {
+	OID ObjectIdentifier
+}
+
+type TestContextSpecificTags struct {
+	A int `asn1:"tag:1"`
+}
+
+type TestContextSpecificTags2 struct {
+	A int `asn1:"explicit,tag:1"`
+	B int
+}
+
+type TestElementsAfterString struct {
+	S    string
+	A, B int
+}
+
+type TestBigInt struct {
+	X *big.Int
+}
+
+type TestSet struct {
+	Ints []int `asn1:"set"`
+}
+
+var unmarshalTestData = []struct {
+	in  []byte
+	out interface{}
+}{
+	{[]byte{0x02, 0x01, 0x42}, newInt(0x42)},
+	{[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}},
+	{[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}},
+	{[]byte{0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &[]int{1, 2, 3}},
+	{[]byte{0x02, 0x01, 0x10}, newInt(16)},
+	{[]byte{0x13, 0x04, 't', 'e', 's', 't'}, newString("test")},
+	{[]byte{0x16, 0x04, 't', 'e', 's', 't'}, newString("test")},
+	{[]byte{0x16, 0x04, 't', 'e', 's', 't'}, &RawValue{0, 22, false, []byte("test"), []byte("\x16\x04test")}},
+	{[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}},
+	{[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}},
+	{[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}},
+	{[]byte{0x01, 0x01, 0x00}, newBool(false)},
+	{[]byte{0x01, 0x01, 0xff}, newBool(true)},
+	{[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}},
+	{[]byte{0x30, 0x05, 0x02, 0x03, 0x12, 0x34, 0x56}, &TestBigInt{big.NewInt(0x123456)}},
+	{[]byte{0x30, 0x0b, 0x31, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &TestSet{Ints: []int{1, 2, 3}}},
+}
+
+func TestUnmarshal(t *testing.T) {
+	for i, test := range unmarshalTestData {
+		pv := reflect.New(reflect.TypeOf(test.out).Elem())
+		val := pv.Interface()
+		_, err := Unmarshal(test.in, val)
+		if err != nil {
+			t.Errorf("Unmarshal failed at index %d %v", i, err)
+		}
+		if !reflect.DeepEqual(val, test.out) {
+			t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out)
+		}
+	}
+}
+
+type Certificate struct {
+	TBSCertificate     TBSCertificate
+	SignatureAlgorithm AlgorithmIdentifier
+	SignatureValue     BitString
+}
+
+type TBSCertificate struct {
+	Version            int `asn1:"optional,explicit,default:0,tag:0"`
+	SerialNumber       RawValue
+	SignatureAlgorithm AlgorithmIdentifier
+	Issuer             RDNSequence
+	Validity           Validity
+	Subject            RDNSequence
+	PublicKey          PublicKeyInfo
+}
+
+type AlgorithmIdentifier struct {
+	Algorithm ObjectIdentifier
+}
+
+type RDNSequence []RelativeDistinguishedNameSET
+
+type RelativeDistinguishedNameSET []AttributeTypeAndValue
+
+type AttributeTypeAndValue struct {
+	Type  ObjectIdentifier
+	Value interface{}
+}
+
+type Validity struct {
+	NotBefore, NotAfter time.Time
+}
+
+type PublicKeyInfo struct {
+	Algorithm AlgorithmIdentifier
+	PublicKey BitString
+}
+
+func TestCertificate(t *testing.T) {
+	// This is a minimal, self-signed certificate that should parse correctly.
+	var cert Certificate
+	if _, err := Unmarshal(derEncodedSelfSignedCertBytes, &cert); err != nil {
+		t.Errorf("Unmarshal failed: %v", err)
+	}
+	if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) {
+		t.Errorf("Bad result:\ngot: %+v\nwant: %+v", cert, derEncodedSelfSignedCert)
+	}
+}
+
+func TestCertificateWithNUL(t *testing.T) {
+	// This is the paypal NUL-hack certificate. It should fail to parse because
+	// NUL isn't a permitted character in a PrintableString.
+
+	var cert Certificate
+	if _, err := Unmarshal(derEncodedPaypalNULCertBytes, &cert); err == nil {
+		t.Error("Unmarshal succeeded, should not have")
+	}
+}
+
+type rawStructTest struct {
+	Raw RawContent
+	A   int
+}
+
+func TestRawStructs(t *testing.T) {
+	var s rawStructTest
+	input := []byte{0x30, 0x03, 0x02, 0x01, 0x50}
+
+	rest, err := Unmarshal(input, &s)
+	if len(rest) != 0 {
+		t.Errorf("incomplete parse: %x", rest)
+		return
+	}
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	if s.A != 0x50 {
+		t.Errorf("bad value for A: got %d want %d", s.A, 0x50)
+	}
+	if !bytes.Equal([]byte(s.Raw), input) {
+		t.Errorf("bad value for Raw: got %x want %x", s.Raw, input)
+	}
+}
+
+type oiEqualTest struct {
+	first  ObjectIdentifier
+	second ObjectIdentifier
+	same   bool
+}
+
+var oiEqualTests = []oiEqualTest{
+	{
+		ObjectIdentifier{1, 2, 3},
+		ObjectIdentifier{1, 2, 3},
+		true,
+	},
+	{
+		ObjectIdentifier{1},
+		ObjectIdentifier{1, 2, 3},
+		false,
+	},
+	{
+		ObjectIdentifier{1, 2, 3},
+		ObjectIdentifier{10, 11, 12},
+		false,
+	},
+}
+
+func TestObjectIdentifierEqual(t *testing.T) {
+	for _, o := range oiEqualTests {
+		if s := o.first.Equal(o.second); s != o.same {
+			t.Errorf("ObjectIdentifier.Equal: got: %t want: %t", s, o.same)
+		}
+	}
+}
+
+var derEncodedSelfSignedCert = Certificate{
+	TBSCertificate: TBSCertificate{
+		Version:            0,
+		SerialNumber:       RawValue{Class: 0, Tag: 2, IsCompound: false, Bytes: []uint8{0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}, FullBytes: []byte{2, 9, 0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}},
+		SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
+		Issuer: RDNSequence{
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}},
+		},
+		Validity: Validity{
+			NotBefore: time.Date(2009, 10, 8, 00, 25, 53, 0, time.UTC),
+			NotAfter:  time.Date(2010, 10, 8, 00, 25, 53, 0, time.UTC),
+		},
+		Subject: RDNSequence{
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}},
+		},
+		PublicKey: PublicKeyInfo{
+			Algorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}},
+			PublicKey: BitString{
+				Bytes: []uint8{
+					0x30, 0x48, 0x2, 0x41, 0x0, 0xcd, 0xb7,
+					0x63, 0x9c, 0x32, 0x78, 0xf0, 0x6, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42,
+					0x90, 0x2b, 0x59, 0x2d, 0x8c, 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4,
+					0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2,
+					0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, 0x96, 0x57, 0x72, 0x2a, 0x4f,
+					0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, 0xdc, 0x8f, 0xde, 0xec,
+					0x35, 0x7d, 0x2, 0x3, 0x1, 0x0, 0x1,
+				},
+				BitLength: 592,
+			},
+		},
+	},
+	SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
+	SignatureValue: BitString{
+		Bytes: []uint8{
+			0xa6, 0x7b, 0x6, 0xec, 0x5e, 0xce,
+			0x92, 0x77, 0x2c, 0xa4, 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c,
+			0x7b, 0x45, 0x11, 0xcd, 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x4, 0x2, 0xdf, 0x2b,
+			0x99, 0x8b, 0xb9, 0xa4, 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8,
+			0xd9, 0x1e, 0xde, 0x14, 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa,
+			0xfa, 0x88, 0x21, 0x49, 0x4, 0x35,
+		},
+		BitLength: 512,
+	},
+}
+
+var derEncodedSelfSignedCertBytes = []byte{
+	0x30, 0x82, 0x02, 0x18, 0x30,
+	0x82, 0x01, 0xc2, 0x02, 0x09, 0x00, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c,
+	0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+	0x05, 0x05, 0x00, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+	0x04, 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+	0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+	0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43,
+	0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+	0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+	0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31,
+	0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c,
+	0x73, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
+	0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+	0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78,
+	0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
+	0x30, 0x39, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, 0x33, 0x5a,
+	0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35,
+	0x33, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+	0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
+	0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+	0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, 0x69,
+	0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18,
+	0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+	0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x1a,
+	0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, 0x73,
+	0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
+	0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+	0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, 0x61,
+	0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06,
+	0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+	0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xcd, 0xb7, 0x63, 0x9c, 0x32, 0x78,
+	0xf0, 0x06, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, 0x90, 0x2b, 0x59, 0x2d, 0x8c,
+	0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea,
+	0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88,
+	0x96, 0x57, 0x72, 0x2a, 0x4f, 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45,
+	0xdc, 0x8f, 0xde, 0xec, 0x35, 0x7d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d,
+	0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+	0x03, 0x41, 0x00, 0xa6, 0x7b, 0x06, 0xec, 0x5e, 0xce, 0x92, 0x77, 0x2c, 0xa4,
+	0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, 0x7b, 0x45, 0x11, 0xcd,
+	0x40, 0xa7, 0xf6, 0x59, 0x98, 0x04, 0x02, 0xdf, 0x2b, 0x99, 0x8b, 0xb9, 0xa4,
+	0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, 0xd9, 0x1e, 0xde, 0x14,
+	0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, 0xfa, 0x88, 0x21, 0x49,
+	0x04, 0x35,
+}
+
+var derEncodedPaypalNULCertBytes = []byte{
+	0x30, 0x82, 0x06, 0x44, 0x30,
+	0x82, 0x05, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x00, 0xf0, 0x9b,
+	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+	0x05, 0x00, 0x30, 0x82, 0x01, 0x12, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+	0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
+	0x04, 0x08, 0x13, 0x09, 0x42, 0x61, 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61,
+	0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x42, 0x61,
+	0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03,
+	0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x50, 0x53, 0x20, 0x43, 0x65, 0x72, 0x74,
+	0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74,
+	0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x73, 0x2e, 0x6c, 0x2e, 0x31, 0x2e,
+	0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x25, 0x67, 0x65, 0x6e, 0x65,
+	0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d,
+	0x20, 0x43, 0x2e, 0x49, 0x2e, 0x46, 0x2e, 0x20, 0x20, 0x42, 0x2d, 0x42, 0x36,
+	0x32, 0x32, 0x31, 0x30, 0x36, 0x39, 0x35, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03,
+	0x55, 0x04, 0x0b, 0x13, 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c,
+	0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
+	0x69, 0x74, 0x79, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+	0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
+	0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
+	0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,
+	0x01, 0x16, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70,
+	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39,
+	0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, 0x17, 0x0d,
+	0x31, 0x31, 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a,
+	0x30, 0x81, 0x94, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+	0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+	0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16,
+	0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x53, 0x61, 0x6e, 0x20,
+	0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x31, 0x11, 0x30, 0x0f,
+	0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
+	0x74, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
+	0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x31, 0x2f,
+	0x30, 0x2d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x26, 0x77, 0x77, 0x77, 0x2e,
+	0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x73, 0x73,
+	0x6c, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
+	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x63, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+	0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
+	0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x69,
+	0xfa, 0x6f, 0x3a, 0x00, 0xb4, 0x21, 0x1b, 0xc8, 0xb1, 0x02, 0xd7, 0x3f, 0x19,
+	0xb2, 0xc4, 0x6d, 0xb4, 0x54, 0xf8, 0x8b, 0x8a, 0xcc, 0xdb, 0x72, 0xc2, 0x9e,
+	0x3c, 0x60, 0xb9, 0xc6, 0x91, 0x3d, 0x82, 0xb7, 0x7d, 0x99, 0xff, 0xd1, 0x29,
+	0x84, 0xc1, 0x73, 0x53, 0x9c, 0x82, 0xdd, 0xfc, 0x24, 0x8c, 0x77, 0xd5, 0x41,
+	0xf3, 0xe8, 0x1e, 0x42, 0xa1, 0xad, 0x2d, 0x9e, 0xff, 0x5b, 0x10, 0x26, 0xce,
+	0x9d, 0x57, 0x17, 0x73, 0x16, 0x23, 0x38, 0xc8, 0xd6, 0xf1, 0xba, 0xa3, 0x96,
+	0x5b, 0x16, 0x67, 0x4a, 0x4f, 0x73, 0x97, 0x3a, 0x4d, 0x14, 0xa4, 0xf4, 0xe2,
+	0x3f, 0x8b, 0x05, 0x83, 0x42, 0xd1, 0xd0, 0xdc, 0x2f, 0x7a, 0xe5, 0xb6, 0x10,
+	0xb2, 0x11, 0xc0, 0xdc, 0x21, 0x2a, 0x90, 0xff, 0xae, 0x97, 0x71, 0x5a, 0x49,
+	0x81, 0xac, 0x40, 0xf3, 0x3b, 0xb8, 0x59, 0xb2, 0x4f, 0x02, 0x03, 0x01, 0x00,
+	0x01, 0xa3, 0x82, 0x03, 0x21, 0x30, 0x82, 0x03, 0x1d, 0x30, 0x09, 0x06, 0x03,
+	0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86,
+	0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40,
+	0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03, 0xf8,
+	0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08,
+	0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1d, 0x06, 0x03, 0x55,
+	0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x61, 0x8f, 0x61, 0x34, 0x43, 0x55, 0x14,
+	0x7f, 0x27, 0x09, 0xce, 0x4c, 0x8b, 0xea, 0x9b, 0x7b, 0x19, 0x25, 0xbc, 0x6e,
+	0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+	0x0e, 0x07, 0x60, 0xd4, 0x39, 0xc9, 0x1b, 0x5b, 0x5d, 0x90, 0x7b, 0x23, 0xc8,
+	0xd2, 0x34, 0x9d, 0x4a, 0x9a, 0x46, 0x39, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d,
+	0x11, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x1d, 0x12, 0x04,
+	0x15, 0x30, 0x13, 0x81, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40,
+	0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x72, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x65, 0x16, 0x63,
+	0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+	0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e,
+	0x4f, 0x54, 0x20, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x44, 0x2e,
+	0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x53, 0x65, 0x72, 0x76,
+	0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+	0x65, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68,
+	0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
+	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x2f, 0x06, 0x09, 0x60,
+	0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x02, 0x04, 0x22, 0x16, 0x20, 0x68,
+	0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
+	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
+	0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+	0x86, 0xf8, 0x42, 0x01, 0x04, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70,
+	0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61,
+	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30,
+	0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c,
+	0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x46, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x03, 0x04, 0x39, 0x16, 0x37,
+	0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
+	0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
+	0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74,
+	0x6d, 0x6c, 0x3f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8,
+	0x42, 0x01, 0x07, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
+	0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63,
+	0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f,
+	0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
+	0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x30, 0x41, 0x06, 0x09, 0x60, 0x86,
+	0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x34, 0x16, 0x32, 0x68, 0x74,
+	0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73,
+	0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32,
+	0x30, 0x30, 0x32, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x4c, 0x41,
+	0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x30, 0x81, 0x83, 0x06,
+	0x03, 0x55, 0x1d, 0x1f, 0x04, 0x7c, 0x30, 0x7a, 0x30, 0x39, 0xa0, 0x37, 0xa0,
+	0x35, 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
+	0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70,
+	0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
+	0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63,
+	0x72, 0x6c, 0x30, 0x3d, 0xa0, 0x3b, 0xa0, 0x39, 0x86, 0x37, 0x68, 0x74, 0x74,
+	0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x69,
+	0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
+	0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30,
+	0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c,
+	0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04,
+	0x26, 0x30, 0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+	0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63,
+	0x73, 0x70, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+	0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x68, 0xee, 0x79, 0x97, 0x97, 0xdd, 0x3b,
+	0xef, 0x16, 0x6a, 0x06, 0xf2, 0x14, 0x9a, 0x6e, 0xcd, 0x9e, 0x12, 0xf7, 0xaa,
+	0x83, 0x10, 0xbd, 0xd1, 0x7c, 0x98, 0xfa, 0xc7, 0xae, 0xd4, 0x0e, 0x2c, 0x9e,
+	0x38, 0x05, 0x9d, 0x52, 0x60, 0xa9, 0x99, 0x0a, 0x81, 0xb4, 0x98, 0x90, 0x1d,
+	0xae, 0xbb, 0x4a, 0xd7, 0xb9, 0xdc, 0x88, 0x9e, 0x37, 0x78, 0x41, 0x5b, 0xf7,
+	0x82, 0xa5, 0xf2, 0xba, 0x41, 0x25, 0x5a, 0x90, 0x1a, 0x1e, 0x45, 0x38, 0xa1,
+	0x52, 0x58, 0x75, 0x94, 0x26, 0x44, 0xfb, 0x20, 0x07, 0xba, 0x44, 0xcc, 0xe5,
+	0x4a, 0x2d, 0x72, 0x3f, 0x98, 0x47, 0xf6, 0x26, 0xdc, 0x05, 0x46, 0x05, 0x07,
+	0x63, 0x21, 0xab, 0x46, 0x9b, 0x9c, 0x78, 0xd5, 0x54, 0x5b, 0x3d, 0x0c, 0x1e,
+	0xc8, 0x64, 0x8c, 0xb5, 0x50, 0x23, 0x82, 0x6f, 0xdb, 0xb8, 0x22, 0x1c, 0x43,
+	0x96, 0x07, 0xa8, 0xbb,
+}
+
+var stringSliceTestData = [][]string{
+	{"foo", "bar"},
+	{"foo", "\\bar"},
+	{"foo", "\"bar\""},
+	{"foo", "åäö"},
+}
+
+func TestStringSlice(t *testing.T) {
+	for _, test := range stringSliceTestData {
+		bs, err := Marshal(test)
+		if err != nil {
+			t.Error(err)
+		}
+
+		var res []string
+		_, err = Unmarshal(bs, &res)
+		if err != nil {
+			t.Error(err)
+		}
+
+		if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", test) {
+			t.Errorf("incorrect marshal/unmarshal; %v != %v", res, test)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/asn1/common.go b/third_party/gofrontend/libgo/go/encoding/asn1/common.go
new file mode 100644
index 0000000..33a117e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/asn1/common.go
@@ -0,0 +1,163 @@
+// 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 asn1
+
+import (
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+// ASN.1 objects have metadata preceding them:
+//   the tag: the type of the object
+//   a flag denoting if this object is compound or not
+//   the class type: the namespace of the tag
+//   the length of the object, in bytes
+
+// Here are some standard tags and classes
+
+const (
+	tagBoolean         = 1
+	tagInteger         = 2
+	tagBitString       = 3
+	tagOctetString     = 4
+	tagOID             = 6
+	tagEnum            = 10
+	tagUTF8String      = 12
+	tagSequence        = 16
+	tagSet             = 17
+	tagPrintableString = 19
+	tagT61String       = 20
+	tagIA5String       = 22
+	tagUTCTime         = 23
+	tagGeneralizedTime = 24
+	tagGeneralString   = 27
+)
+
+const (
+	classUniversal       = 0
+	classApplication     = 1
+	classContextSpecific = 2
+	classPrivate         = 3
+)
+
+type tagAndLength struct {
+	class, tag, length int
+	isCompound         bool
+}
+
+// ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead
+// of" and "in addition to". When not specified, every primitive type has a
+// default tag in the UNIVERSAL class.
+//
+// For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1
+// doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT
+// CONTEXT-SPECIFIC 42], that means that the tag is replaced by another.
+//
+// On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an
+// /additional/ tag would wrap the default tag. This explicit tag will have the
+// compound flag set.
+//
+// (This is used in order to remove ambiguity with optional elements.)
+//
+// You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we
+// don't support that here. We support a single layer of EXPLICIT or IMPLICIT
+// tagging with tag strings on the fields of a structure.
+
+// fieldParameters is the parsed representation of tag string from a structure field.
+type fieldParameters struct {
+	optional     bool   // true iff the field is OPTIONAL
+	explicit     bool   // true iff an EXPLICIT tag is in use.
+	application  bool   // true iff an APPLICATION tag is in use.
+	defaultValue *int64 // a default value for INTEGER typed fields (maybe nil).
+	tag          *int   // the EXPLICIT or IMPLICIT tag (maybe nil).
+	stringType   int    // the string tag to use when marshaling.
+	set          bool   // true iff this should be encoded as a SET
+	omitEmpty    bool   // true iff this should be omitted if empty when marshaling.
+
+	// Invariants:
+	//   if explicit is set, tag is non-nil.
+}
+
+// Given a tag string with the format specified in the package comment,
+// parseFieldParameters will parse it into a fieldParameters structure,
+// ignoring unknown parts of the string.
+func parseFieldParameters(str string) (ret fieldParameters) {
+	for _, part := range strings.Split(str, ",") {
+		switch {
+		case part == "optional":
+			ret.optional = true
+		case part == "explicit":
+			ret.explicit = true
+			if ret.tag == nil {
+				ret.tag = new(int)
+			}
+		case part == "ia5":
+			ret.stringType = tagIA5String
+		case part == "printable":
+			ret.stringType = tagPrintableString
+		case part == "utf8":
+			ret.stringType = tagUTF8String
+		case strings.HasPrefix(part, "default:"):
+			i, err := strconv.ParseInt(part[8:], 10, 64)
+			if err == nil {
+				ret.defaultValue = new(int64)
+				*ret.defaultValue = i
+			}
+		case strings.HasPrefix(part, "tag:"):
+			i, err := strconv.Atoi(part[4:])
+			if err == nil {
+				ret.tag = new(int)
+				*ret.tag = i
+			}
+		case part == "set":
+			ret.set = true
+		case part == "application":
+			ret.application = true
+			if ret.tag == nil {
+				ret.tag = new(int)
+			}
+		case part == "omitempty":
+			ret.omitEmpty = true
+		}
+	}
+	return
+}
+
+// Given a reflected Go type, getUniversalType returns the default tag number
+// and expected compound flag.
+func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
+	switch t {
+	case objectIdentifierType:
+		return tagOID, false, true
+	case bitStringType:
+		return tagBitString, false, true
+	case timeType:
+		return tagUTCTime, false, true
+	case enumeratedType:
+		return tagEnum, false, true
+	case bigIntType:
+		return tagInteger, false, true
+	}
+	switch t.Kind() {
+	case reflect.Bool:
+		return tagBoolean, false, true
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return tagInteger, false, true
+	case reflect.Struct:
+		return tagSequence, true, true
+	case reflect.Slice:
+		if t.Elem().Kind() == reflect.Uint8 {
+			return tagOctetString, false, true
+		}
+		if strings.HasSuffix(t.Name(), "SET") {
+			return tagSet, true, true
+		}
+		return tagSequence, true, true
+	case reflect.String:
+		return tagPrintableString, false, true
+	}
+	return 0, false, false
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/asn1/marshal.go b/third_party/gofrontend/libgo/go/encoding/asn1/marshal.go
new file mode 100644
index 0000000..e26fe59
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/asn1/marshal.go
@@ -0,0 +1,632 @@
+// 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 asn1
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"math/big"
+	"reflect"
+	"time"
+	"unicode/utf8"
+)
+
+// A forkableWriter is an in-memory buffer that can be
+// 'forked' to create new forkableWriters that bracket the
+// original.  After
+//    pre, post := w.fork();
+// the overall sequence of bytes represented is logically w+pre+post.
+type forkableWriter struct {
+	*bytes.Buffer
+	pre, post *forkableWriter
+}
+
+func newForkableWriter() *forkableWriter {
+	return &forkableWriter{new(bytes.Buffer), nil, nil}
+}
+
+func (f *forkableWriter) fork() (pre, post *forkableWriter) {
+	if f.pre != nil || f.post != nil {
+		panic("have already forked")
+	}
+	f.pre = newForkableWriter()
+	f.post = newForkableWriter()
+	return f.pre, f.post
+}
+
+func (f *forkableWriter) Len() (l int) {
+	l += f.Buffer.Len()
+	if f.pre != nil {
+		l += f.pre.Len()
+	}
+	if f.post != nil {
+		l += f.post.Len()
+	}
+	return
+}
+
+func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) {
+	n, err = out.Write(f.Bytes())
+	if err != nil {
+		return
+	}
+
+	var nn int
+
+	if f.pre != nil {
+		nn, err = f.pre.writeTo(out)
+		n += nn
+		if err != nil {
+			return
+		}
+	}
+
+	if f.post != nil {
+		nn, err = f.post.writeTo(out)
+		n += nn
+	}
+	return
+}
+
+func marshalBase128Int(out *forkableWriter, n int64) (err error) {
+	if n == 0 {
+		err = out.WriteByte(0)
+		return
+	}
+
+	l := 0
+	for i := n; i > 0; i >>= 7 {
+		l++
+	}
+
+	for i := l - 1; i >= 0; i-- {
+		o := byte(n >> uint(i*7))
+		o &= 0x7f
+		if i != 0 {
+			o |= 0x80
+		}
+		err = out.WriteByte(o)
+		if err != nil {
+			return
+		}
+	}
+
+	return nil
+}
+
+func marshalInt64(out *forkableWriter, i int64) (err error) {
+	n := int64Length(i)
+
+	for ; n > 0; n-- {
+		err = out.WriteByte(byte(i >> uint((n-1)*8)))
+		if err != nil {
+			return
+		}
+	}
+
+	return nil
+}
+
+func int64Length(i int64) (numBytes int) {
+	numBytes = 1
+
+	for i > 127 {
+		numBytes++
+		i >>= 8
+	}
+
+	for i < -128 {
+		numBytes++
+		i >>= 8
+	}
+
+	return
+}
+
+func marshalBigInt(out *forkableWriter, n *big.Int) (err error) {
+	if n.Sign() < 0 {
+		// A negative number has to be converted to two's-complement
+		// form. So we'll subtract 1 and invert. If the
+		// most-significant-bit isn't set then we'll need to pad the
+		// beginning with 0xff in order to keep the number negative.
+		nMinus1 := new(big.Int).Neg(n)
+		nMinus1.Sub(nMinus1, bigOne)
+		bytes := nMinus1.Bytes()
+		for i := range bytes {
+			bytes[i] ^= 0xff
+		}
+		if len(bytes) == 0 || bytes[0]&0x80 == 0 {
+			err = out.WriteByte(0xff)
+			if err != nil {
+				return
+			}
+		}
+		_, err = out.Write(bytes)
+	} else if n.Sign() == 0 {
+		// Zero is written as a single 0 zero rather than no bytes.
+		err = out.WriteByte(0x00)
+	} else {
+		bytes := n.Bytes()
+		if len(bytes) > 0 && bytes[0]&0x80 != 0 {
+			// We'll have to pad this with 0x00 in order to stop it
+			// looking like a negative number.
+			err = out.WriteByte(0)
+			if err != nil {
+				return
+			}
+		}
+		_, err = out.Write(bytes)
+	}
+	return
+}
+
+func marshalLength(out *forkableWriter, i int) (err error) {
+	n := lengthLength(i)
+
+	for ; n > 0; n-- {
+		err = out.WriteByte(byte(i >> uint((n-1)*8)))
+		if err != nil {
+			return
+		}
+	}
+
+	return nil
+}
+
+func lengthLength(i int) (numBytes int) {
+	numBytes = 1
+	for i > 255 {
+		numBytes++
+		i >>= 8
+	}
+	return
+}
+
+func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) {
+	b := uint8(t.class) << 6
+	if t.isCompound {
+		b |= 0x20
+	}
+	if t.tag >= 31 {
+		b |= 0x1f
+		err = out.WriteByte(b)
+		if err != nil {
+			return
+		}
+		err = marshalBase128Int(out, int64(t.tag))
+		if err != nil {
+			return
+		}
+	} else {
+		b |= uint8(t.tag)
+		err = out.WriteByte(b)
+		if err != nil {
+			return
+		}
+	}
+
+	if t.length >= 128 {
+		l := lengthLength(t.length)
+		err = out.WriteByte(0x80 | byte(l))
+		if err != nil {
+			return
+		}
+		err = marshalLength(out, t.length)
+		if err != nil {
+			return
+		}
+	} else {
+		err = out.WriteByte(byte(t.length))
+		if err != nil {
+			return
+		}
+	}
+
+	return nil
+}
+
+func marshalBitString(out *forkableWriter, b BitString) (err error) {
+	paddingBits := byte((8 - b.BitLength%8) % 8)
+	err = out.WriteByte(paddingBits)
+	if err != nil {
+		return
+	}
+	_, err = out.Write(b.Bytes)
+	return
+}
+
+func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) {
+	if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
+		return StructuralError{"invalid object identifier"}
+	}
+
+	err = marshalBase128Int(out, int64(oid[0]*40+oid[1]))
+	if err != nil {
+		return
+	}
+	for i := 2; i < len(oid); i++ {
+		err = marshalBase128Int(out, int64(oid[i]))
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+func marshalPrintableString(out *forkableWriter, s string) (err error) {
+	b := []byte(s)
+	for _, c := range b {
+		if !isPrintable(c) {
+			return StructuralError{"PrintableString contains invalid character"}
+		}
+	}
+
+	_, err = out.Write(b)
+	return
+}
+
+func marshalIA5String(out *forkableWriter, s string) (err error) {
+	b := []byte(s)
+	for _, c := range b {
+		if c > 127 {
+			return StructuralError{"IA5String contains invalid character"}
+		}
+	}
+
+	_, err = out.Write(b)
+	return
+}
+
+func marshalUTF8String(out *forkableWriter, s string) (err error) {
+	_, err = out.Write([]byte(s))
+	return
+}
+
+func marshalTwoDigits(out *forkableWriter, v int) (err error) {
+	err = out.WriteByte(byte('0' + (v/10)%10))
+	if err != nil {
+		return
+	}
+	return out.WriteByte(byte('0' + v%10))
+}
+
+func marshalFourDigits(out *forkableWriter, v int) (err error) {
+	var bytes [4]byte
+	for i := range bytes {
+		bytes[3-i] = '0' + byte(v%10)
+		v /= 10
+	}
+	_, err = out.Write(bytes[:])
+	return
+}
+
+func outsideUTCRange(t time.Time) bool {
+	year := t.Year()
+	return year < 1950 || year >= 2050
+}
+
+func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
+	year := t.Year()
+
+	switch {
+	case 1950 <= year && year < 2000:
+		err = marshalTwoDigits(out, int(year-1900))
+	case 2000 <= year && year < 2050:
+		err = marshalTwoDigits(out, int(year-2000))
+	default:
+		return StructuralError{"cannot represent time as UTCTime"}
+	}
+	if err != nil {
+		return
+	}
+
+	return marshalTimeCommon(out, t)
+}
+
+func marshalGeneralizedTime(out *forkableWriter, t time.Time) (err error) {
+	year := t.Year()
+	if year < 0 || year > 9999 {
+		return StructuralError{"cannot represent time as GeneralizedTime"}
+	}
+	if err = marshalFourDigits(out, year); err != nil {
+		return
+	}
+
+	return marshalTimeCommon(out, t)
+}
+
+func marshalTimeCommon(out *forkableWriter, t time.Time) (err error) {
+	_, month, day := t.Date()
+
+	err = marshalTwoDigits(out, int(month))
+	if err != nil {
+		return
+	}
+
+	err = marshalTwoDigits(out, day)
+	if err != nil {
+		return
+	}
+
+	hour, min, sec := t.Clock()
+
+	err = marshalTwoDigits(out, hour)
+	if err != nil {
+		return
+	}
+
+	err = marshalTwoDigits(out, min)
+	if err != nil {
+		return
+	}
+
+	err = marshalTwoDigits(out, sec)
+	if err != nil {
+		return
+	}
+
+	_, offset := t.Zone()
+
+	switch {
+	case offset/60 == 0:
+		err = out.WriteByte('Z')
+		return
+	case offset > 0:
+		err = out.WriteByte('+')
+	case offset < 0:
+		err = out.WriteByte('-')
+	}
+
+	if err != nil {
+		return
+	}
+
+	offsetMinutes := offset / 60
+	if offsetMinutes < 0 {
+		offsetMinutes = -offsetMinutes
+	}
+
+	err = marshalTwoDigits(out, offsetMinutes/60)
+	if err != nil {
+		return
+	}
+
+	err = marshalTwoDigits(out, offsetMinutes%60)
+	return
+}
+
+func stripTagAndLength(in []byte) []byte {
+	_, offset, err := parseTagAndLength(in, 0)
+	if err != nil {
+		return in
+	}
+	return in[offset:]
+}
+
+func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) {
+	switch value.Type() {
+	case timeType:
+		t := value.Interface().(time.Time)
+		if outsideUTCRange(t) {
+			return marshalGeneralizedTime(out, t)
+		} else {
+			return marshalUTCTime(out, t)
+		}
+	case bitStringType:
+		return marshalBitString(out, value.Interface().(BitString))
+	case objectIdentifierType:
+		return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
+	case bigIntType:
+		return marshalBigInt(out, value.Interface().(*big.Int))
+	}
+
+	switch v := value; v.Kind() {
+	case reflect.Bool:
+		if v.Bool() {
+			return out.WriteByte(255)
+		} else {
+			return out.WriteByte(0)
+		}
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return marshalInt64(out, int64(v.Int()))
+	case reflect.Struct:
+		t := v.Type()
+
+		startingField := 0
+
+		// If the first element of the structure is a non-empty
+		// RawContents, then we don't bother serializing the rest.
+		if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
+			s := v.Field(0)
+			if s.Len() > 0 {
+				bytes := make([]byte, s.Len())
+				for i := 0; i < s.Len(); i++ {
+					bytes[i] = uint8(s.Index(i).Uint())
+				}
+				/* The RawContents will contain the tag and
+				 * length fields but we'll also be writing
+				 * those ourselves, so we strip them out of
+				 * bytes */
+				_, err = out.Write(stripTagAndLength(bytes))
+				return
+			} else {
+				startingField = 1
+			}
+		}
+
+		for i := startingField; i < t.NumField(); i++ {
+			var pre *forkableWriter
+			pre, out = out.fork()
+			err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1")))
+			if err != nil {
+				return
+			}
+		}
+		return
+	case reflect.Slice:
+		sliceType := v.Type()
+		if sliceType.Elem().Kind() == reflect.Uint8 {
+			bytes := make([]byte, v.Len())
+			for i := 0; i < v.Len(); i++ {
+				bytes[i] = uint8(v.Index(i).Uint())
+			}
+			_, err = out.Write(bytes)
+			return
+		}
+
+		var fp fieldParameters
+		for i := 0; i < v.Len(); i++ {
+			var pre *forkableWriter
+			pre, out = out.fork()
+			err = marshalField(pre, v.Index(i), fp)
+			if err != nil {
+				return
+			}
+		}
+		return
+	case reflect.String:
+		switch params.stringType {
+		case tagIA5String:
+			return marshalIA5String(out, v.String())
+		case tagPrintableString:
+			return marshalPrintableString(out, v.String())
+		default:
+			return marshalUTF8String(out, v.String())
+		}
+	}
+
+	return StructuralError{"unknown Go type"}
+}
+
+func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) {
+	// If the field is an interface{} then recurse into it.
+	if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
+		return marshalField(out, v.Elem(), params)
+	}
+
+	if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty {
+		return
+	}
+
+	if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
+		return
+	}
+
+	if v.Type() == rawValueType {
+		rv := v.Interface().(RawValue)
+		if len(rv.FullBytes) != 0 {
+			_, err = out.Write(rv.FullBytes)
+		} else {
+			err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
+			if err != nil {
+				return
+			}
+			_, err = out.Write(rv.Bytes)
+		}
+		return
+	}
+
+	tag, isCompound, ok := getUniversalType(v.Type())
+	if !ok {
+		err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
+		return
+	}
+	class := classUniversal
+
+	if params.stringType != 0 && tag != tagPrintableString {
+		return StructuralError{"explicit string type given to non-string member"}
+	}
+
+	switch tag {
+	case tagPrintableString:
+		if params.stringType == 0 {
+			// This is a string without an explicit string type. We'll use
+			// a PrintableString if the character set in the string is
+			// sufficiently limited, otherwise we'll use a UTF8String.
+			for _, r := range v.String() {
+				if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
+					if !utf8.ValidString(v.String()) {
+						return errors.New("asn1: string not valid UTF-8")
+					}
+					tag = tagUTF8String
+					break
+				}
+			}
+		} else {
+			tag = params.stringType
+		}
+	case tagUTCTime:
+		if outsideUTCRange(v.Interface().(time.Time)) {
+			tag = tagGeneralizedTime
+		}
+	}
+
+	if params.set {
+		if tag != tagSequence {
+			return StructuralError{"non sequence tagged as set"}
+		}
+		tag = tagSet
+	}
+
+	tags, body := out.fork()
+
+	err = marshalBody(body, v, params)
+	if err != nil {
+		return
+	}
+
+	bodyLen := body.Len()
+
+	var explicitTag *forkableWriter
+	if params.explicit {
+		explicitTag, tags = tags.fork()
+	}
+
+	if !params.explicit && params.tag != nil {
+		// implicit tag.
+		tag = *params.tag
+		class = classContextSpecific
+	}
+
+	err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
+	if err != nil {
+		return
+	}
+
+	if params.explicit {
+		err = marshalTagAndLength(explicitTag, tagAndLength{
+			class:      classContextSpecific,
+			tag:        *params.tag,
+			length:     bodyLen + tags.Len(),
+			isCompound: true,
+		})
+	}
+
+	return nil
+}
+
+// Marshal returns the ASN.1 encoding of val.
+//
+// In addition to the struct tags recognised by Unmarshal, the following can be
+// used:
+//
+//	ia5:		causes strings to be marshaled as ASN.1, IA5 strings
+//	omitempty:	causes empty slices to be skipped
+//	printable:	causes strings to be marshaled as ASN.1, PrintableString strings.
+//	utf8:		causes strings to be marshaled as ASN.1, UTF8 strings
+func Marshal(val interface{}) ([]byte, error) {
+	var out bytes.Buffer
+	v := reflect.ValueOf(val)
+	f := newForkableWriter()
+	err := marshalField(f, v, fieldParameters{})
+	if err != nil {
+		return nil, err
+	}
+	_, err = f.writeTo(&out)
+	return out.Bytes(), nil
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/asn1/marshal_test.go b/third_party/gofrontend/libgo/go/encoding/asn1/marshal_test.go
new file mode 100644
index 0000000..a15acbe
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/asn1/marshal_test.go
@@ -0,0 +1,157 @@
+// 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 asn1
+
+import (
+	"bytes"
+	"encoding/hex"
+	"math/big"
+	"testing"
+	"time"
+)
+
+type intStruct struct {
+	A int
+}
+
+type twoIntStruct struct {
+	A int
+	B int
+}
+
+type bigIntStruct struct {
+	A *big.Int
+}
+
+type nestedStruct struct {
+	A intStruct
+}
+
+type rawContentsStruct struct {
+	Raw RawContent
+	A   int
+}
+
+type implicitTagTest struct {
+	A int `asn1:"implicit,tag:5"`
+}
+
+type explicitTagTest struct {
+	A int `asn1:"explicit,tag:5"`
+}
+
+type ia5StringTest struct {
+	A string `asn1:"ia5"`
+}
+
+type printableStringTest struct {
+	A string `asn1:"printable"`
+}
+
+type optionalRawValueTest struct {
+	A RawValue `asn1:"optional"`
+}
+
+type omitEmptyTest struct {
+	A []string `asn1:"omitempty"`
+}
+
+type testSET []int
+
+var PST = time.FixedZone("PST", -8*60*60)
+
+type marshalTest struct {
+	in  interface{}
+	out string // hex encoded
+}
+
+func farFuture() time.Time {
+	t, err := time.Parse(time.RFC3339, "2100-04-05T12:01:01Z")
+	if err != nil {
+		panic(err)
+	}
+	return t
+}
+
+var marshalTests = []marshalTest{
+	{10, "02010a"},
+	{127, "02017f"},
+	{128, "02020080"},
+	{-128, "020180"},
+	{-129, "0202ff7f"},
+	{intStruct{64}, "3003020140"},
+	{bigIntStruct{big.NewInt(0x123456)}, "30050203123456"},
+	{twoIntStruct{64, 65}, "3006020140020141"},
+	{nestedStruct{intStruct{127}}, "3005300302017f"},
+	{[]byte{1, 2, 3}, "0403010203"},
+	{implicitTagTest{64}, "3003850140"},
+	{explicitTagTest{64}, "3005a503020140"},
+	{time.Unix(0, 0).UTC(), "170d3730303130313030303030305a"},
+	{time.Unix(1258325776, 0).UTC(), "170d3039313131353232353631365a"},
+	{time.Unix(1258325776, 0).In(PST), "17113039313131353134353631362d30383030"},
+	{farFuture(), "180f32313030303430353132303130315a"},
+	{BitString{[]byte{0x80}, 1}, "03020780"},
+	{BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"},
+	{ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"},
+	{ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"},
+	{ObjectIdentifier([]int{2, 100, 3}), "0603813403"},
+	{"test", "130474657374"},
+	{
+		"" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 127 times 'x'
+		"137f" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"78787878787878787878787878787878787878787878787878787878787878",
+	},
+	{
+		"" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 128 times 'x'
+		"138180" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"7878787878787878787878787878787878787878787878787878787878787878",
+	},
+	{ia5StringTest{"test"}, "3006160474657374"},
+	{optionalRawValueTest{}, "3000"},
+	{printableStringTest{"test"}, "3006130474657374"},
+	{printableStringTest{"test*"}, "30071305746573742a"},
+	{rawContentsStruct{nil, 64}, "3003020140"},
+	{rawContentsStruct{[]byte{0x30, 3, 1, 2, 3}, 64}, "3003010203"},
+	{RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"},
+	{testSET([]int{10}), "310302010a"},
+	{omitEmptyTest{[]string{}}, "3000"},
+	{omitEmptyTest{[]string{"1"}}, "30053003130131"},
+	{"Σ", "0c02cea3"},
+}
+
+func TestMarshal(t *testing.T) {
+	for i, test := range marshalTests {
+		data, err := Marshal(test.in)
+		if err != nil {
+			t.Errorf("#%d failed: %s", i, err)
+		}
+		out, _ := hex.DecodeString(test.out)
+		if !bytes.Equal(out, data) {
+			t.Errorf("#%d got: %x want %x\n\t%q\n\t%q", i, data, out, data, out)
+
+		}
+	}
+}
+
+func TestInvalidUTF8(t *testing.T) {
+	_, err := Marshal(string([]byte{0xff, 0xff}))
+	if err == nil {
+		t.Errorf("invalid UTF8 string was accepted")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/base32/base32.go b/third_party/gofrontend/libgo/go/encoding/base32/base32.go
new file mode 100644
index 0000000..d770de3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/base32/base32.go
@@ -0,0 +1,428 @@
+// 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.
+
+// Package base32 implements base32 encoding as specified by RFC 4648.
+package base32
+
+import (
+	"bytes"
+	"io"
+	"strconv"
+	"strings"
+)
+
+/*
+ * Encodings
+ */
+
+// An Encoding is a radix 32 encoding/decoding scheme, defined by a
+// 32-character alphabet.  The most common is the "base32" encoding
+// introduced for SASL GSSAPI and standardized in RFC 4648.
+// The alternate "base32hex" encoding is used in DNSSEC.
+type Encoding struct {
+	encode    string
+	decodeMap [256]byte
+}
+
+const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
+const encodeHex = "0123456789ABCDEFGHIJKLMNOPQRSTUV"
+
+// NewEncoding returns a new Encoding defined by the given alphabet,
+// which must be a 32-byte string.
+func NewEncoding(encoder string) *Encoding {
+	e := new(Encoding)
+	e.encode = encoder
+	for i := 0; i < len(e.decodeMap); i++ {
+		e.decodeMap[i] = 0xFF
+	}
+	for i := 0; i < len(encoder); i++ {
+		e.decodeMap[encoder[i]] = byte(i)
+	}
+	return e
+}
+
+// StdEncoding is the standard base32 encoding, as defined in
+// RFC 4648.
+var StdEncoding = NewEncoding(encodeStd)
+
+// HexEncoding is the ``Extended Hex Alphabet'' defined in RFC 4648.
+// It is typically used in DNS.
+var HexEncoding = NewEncoding(encodeHex)
+
+var removeNewlinesMapper = func(r rune) rune {
+	if r == '\r' || r == '\n' {
+		return -1
+	}
+	return r
+}
+
+/*
+ * Encoder
+ */
+
+// Encode encodes src using the encoding enc, writing
+// EncodedLen(len(src)) bytes to dst.
+//
+// The encoding pads the output to a multiple of 8 bytes,
+// so Encode is not appropriate for use on individual blocks
+// of a large data stream.  Use NewEncoder() instead.
+func (enc *Encoding) Encode(dst, src []byte) {
+	if len(src) == 0 {
+		return
+	}
+
+	for len(src) > 0 {
+		dst[0] = 0
+		dst[1] = 0
+		dst[2] = 0
+		dst[3] = 0
+		dst[4] = 0
+		dst[5] = 0
+		dst[6] = 0
+		dst[7] = 0
+
+		// Unpack 8x 5-bit source blocks into a 5 byte
+		// destination quantum
+		switch len(src) {
+		default:
+			dst[7] |= src[4] & 0x1F
+			dst[6] |= src[4] >> 5
+			fallthrough
+		case 4:
+			dst[6] |= (src[3] << 3) & 0x1F
+			dst[5] |= (src[3] >> 2) & 0x1F
+			dst[4] |= src[3] >> 7
+			fallthrough
+		case 3:
+			dst[4] |= (src[2] << 1) & 0x1F
+			dst[3] |= (src[2] >> 4) & 0x1F
+			fallthrough
+		case 2:
+			dst[3] |= (src[1] << 4) & 0x1F
+			dst[2] |= (src[1] >> 1) & 0x1F
+			dst[1] |= (src[1] >> 6) & 0x1F
+			fallthrough
+		case 1:
+			dst[1] |= (src[0] << 2) & 0x1F
+			dst[0] |= src[0] >> 3
+		}
+
+		// Encode 5-bit blocks using the base32 alphabet
+		for j := 0; j < 8; j++ {
+			dst[j] = enc.encode[dst[j]]
+		}
+
+		// Pad the final quantum
+		if len(src) < 5 {
+			dst[7] = '='
+			if len(src) < 4 {
+				dst[6] = '='
+				dst[5] = '='
+				if len(src) < 3 {
+					dst[4] = '='
+					if len(src) < 2 {
+						dst[3] = '='
+						dst[2] = '='
+					}
+				}
+			}
+			break
+		}
+		src = src[5:]
+		dst = dst[8:]
+	}
+}
+
+// EncodeToString returns the base32 encoding of src.
+func (enc *Encoding) EncodeToString(src []byte) string {
+	buf := make([]byte, enc.EncodedLen(len(src)))
+	enc.Encode(buf, src)
+	return string(buf)
+}
+
+type encoder struct {
+	err  error
+	enc  *Encoding
+	w    io.Writer
+	buf  [5]byte    // buffered data waiting to be encoded
+	nbuf int        // number of bytes in buf
+	out  [1024]byte // output buffer
+}
+
+func (e *encoder) Write(p []byte) (n int, err error) {
+	if e.err != nil {
+		return 0, e.err
+	}
+
+	// Leading fringe.
+	if e.nbuf > 0 {
+		var i int
+		for i = 0; i < len(p) && e.nbuf < 5; i++ {
+			e.buf[e.nbuf] = p[i]
+			e.nbuf++
+		}
+		n += i
+		p = p[i:]
+		if e.nbuf < 5 {
+			return
+		}
+		e.enc.Encode(e.out[0:], e.buf[0:])
+		if _, e.err = e.w.Write(e.out[0:8]); e.err != nil {
+			return n, e.err
+		}
+		e.nbuf = 0
+	}
+
+	// Large interior chunks.
+	for len(p) >= 5 {
+		nn := len(e.out) / 8 * 5
+		if nn > len(p) {
+			nn = len(p)
+			nn -= nn % 5
+		}
+		e.enc.Encode(e.out[0:], p[0:nn])
+		if _, e.err = e.w.Write(e.out[0 : nn/5*8]); e.err != nil {
+			return n, e.err
+		}
+		n += nn
+		p = p[nn:]
+	}
+
+	// Trailing fringe.
+	for i := 0; i < len(p); i++ {
+		e.buf[i] = p[i]
+	}
+	e.nbuf = len(p)
+	n += len(p)
+	return
+}
+
+// Close flushes any pending output from the encoder.
+// It is an error to call Write after calling Close.
+func (e *encoder) Close() error {
+	// If there's anything left in the buffer, flush it out
+	if e.err == nil && e.nbuf > 0 {
+		e.enc.Encode(e.out[0:], e.buf[0:e.nbuf])
+		e.nbuf = 0
+		_, e.err = e.w.Write(e.out[0:8])
+	}
+	return e.err
+}
+
+// NewEncoder returns a new base32 stream encoder.  Data written to
+// the returned writer will be encoded using enc and then written to w.
+// Base32 encodings operate in 5-byte blocks; when finished
+// writing, the caller must Close the returned encoder to flush any
+// partially written blocks.
+func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
+	return &encoder{enc: enc, w: w}
+}
+
+// EncodedLen returns the length in bytes of the base32 encoding
+// of an input buffer of length n.
+func (enc *Encoding) EncodedLen(n int) int { return (n + 4) / 5 * 8 }
+
+/*
+ * Decoder
+ */
+
+type CorruptInputError int64
+
+func (e CorruptInputError) Error() string {
+	return "illegal base32 data at input byte " + strconv.FormatInt(int64(e), 10)
+}
+
+// decode is like Decode but returns an additional 'end' value, which
+// indicates if end-of-message padding was encountered and thus any
+// additional data is an error. This method assumes that src has been
+// stripped of all supported whitespace ('\r' and '\n').
+func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
+	olen := len(src)
+	for len(src) > 0 && !end {
+		// Decode quantum using the base32 alphabet
+		var dbuf [8]byte
+		dlen := 8
+
+		for j := 0; j < 8; {
+			if len(src) == 0 {
+				return n, false, CorruptInputError(olen - len(src) - j)
+			}
+			in := src[0]
+			src = src[1:]
+			if in == '=' && j >= 2 && len(src) < 8 {
+				// We've reached the end and there's padding
+				if len(src)+j < 8-1 {
+					// not enough padding
+					return n, false, CorruptInputError(olen)
+				}
+				for k := 0; k < 8-1-j; k++ {
+					if len(src) > k && src[k] != '=' {
+						// incorrect padding
+						return n, false, CorruptInputError(olen - len(src) + k - 1)
+					}
+				}
+				dlen, end = j, true
+				// 7, 5 and 2 are not valid padding lengths, and so 1, 3 and 6 are not
+				// valid dlen values. See RFC 4648 Section 6 "Base 32 Encoding" listing
+				// the five valid padding lengths, and Section 9 "Illustrations and
+				// Examples" for an illustration for how the 1st, 3rd and 6th base32
+				// src bytes do not yield enough information to decode a dst byte.
+				if dlen == 1 || dlen == 3 || dlen == 6 {
+					return n, false, CorruptInputError(olen - len(src) - 1)
+				}
+				break
+			}
+			dbuf[j] = enc.decodeMap[in]
+			if dbuf[j] == 0xFF {
+				return n, false, CorruptInputError(olen - len(src) - 1)
+			}
+			j++
+		}
+
+		// Pack 8x 5-bit source blocks into 5 byte destination
+		// quantum
+		switch dlen {
+		case 8:
+			dst[4] = dbuf[6]<<5 | dbuf[7]
+			fallthrough
+		case 7:
+			dst[3] = dbuf[4]<<7 | dbuf[5]<<2 | dbuf[6]>>3
+			fallthrough
+		case 5:
+			dst[2] = dbuf[3]<<4 | dbuf[4]>>1
+			fallthrough
+		case 4:
+			dst[1] = dbuf[1]<<6 | dbuf[2]<<1 | dbuf[3]>>4
+			fallthrough
+		case 2:
+			dst[0] = dbuf[0]<<3 | dbuf[1]>>2
+		}
+		dst = dst[5:]
+		switch dlen {
+		case 2:
+			n += 1
+		case 4:
+			n += 2
+		case 5:
+			n += 3
+		case 7:
+			n += 4
+		case 8:
+			n += 5
+		}
+	}
+	return n, end, nil
+}
+
+// Decode decodes src using the encoding enc.  It writes at most
+// DecodedLen(len(src)) bytes to dst and returns the number of bytes
+// written.  If src contains invalid base32 data, it will return the
+// number of bytes successfully written and CorruptInputError.
+// New line characters (\r and \n) are ignored.
+func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
+	src = bytes.Map(removeNewlinesMapper, src)
+	n, _, err = enc.decode(dst, src)
+	return
+}
+
+// DecodeString returns the bytes represented by the base32 string s.
+func (enc *Encoding) DecodeString(s string) ([]byte, error) {
+	s = strings.Map(removeNewlinesMapper, s)
+	dbuf := make([]byte, enc.DecodedLen(len(s)))
+	n, err := enc.Decode(dbuf, []byte(s))
+	return dbuf[:n], err
+}
+
+type decoder struct {
+	err    error
+	enc    *Encoding
+	r      io.Reader
+	end    bool       // saw end of message
+	buf    [1024]byte // leftover input
+	nbuf   int
+	out    []byte // leftover decoded output
+	outbuf [1024 / 8 * 5]byte
+}
+
+func (d *decoder) Read(p []byte) (n int, err error) {
+	if d.err != nil {
+		return 0, d.err
+	}
+
+	// Use leftover decoded output from last read.
+	if len(d.out) > 0 {
+		n = copy(p, d.out)
+		d.out = d.out[n:]
+		return n, nil
+	}
+
+	// Read a chunk.
+	nn := len(p) / 5 * 8
+	if nn < 8 {
+		nn = 8
+	}
+	if nn > len(d.buf) {
+		nn = len(d.buf)
+	}
+	nn, d.err = io.ReadAtLeast(d.r, d.buf[d.nbuf:nn], 8-d.nbuf)
+	d.nbuf += nn
+	if d.nbuf < 8 {
+		return 0, d.err
+	}
+
+	// Decode chunk into p, or d.out and then p if p is too small.
+	nr := d.nbuf / 8 * 8
+	nw := d.nbuf / 8 * 5
+	if nw > len(p) {
+		nw, d.end, d.err = d.enc.decode(d.outbuf[0:], d.buf[0:nr])
+		d.out = d.outbuf[0:nw]
+		n = copy(p, d.out)
+		d.out = d.out[n:]
+	} else {
+		n, d.end, d.err = d.enc.decode(p, d.buf[0:nr])
+	}
+	d.nbuf -= nr
+	for i := 0; i < d.nbuf; i++ {
+		d.buf[i] = d.buf[i+nr]
+	}
+
+	if d.err == nil {
+		d.err = err
+	}
+	return n, d.err
+}
+
+type newlineFilteringReader struct {
+	wrapped io.Reader
+}
+
+func (r *newlineFilteringReader) Read(p []byte) (int, error) {
+	n, err := r.wrapped.Read(p)
+	for n > 0 {
+		offset := 0
+		for i, b := range p[0:n] {
+			if b != '\r' && b != '\n' {
+				if i != offset {
+					p[offset] = b
+				}
+				offset++
+			}
+		}
+		if offset > 0 {
+			return offset, err
+		}
+		// Previous buffer entirely whitespace, read again
+		n, err = r.wrapped.Read(p)
+	}
+	return n, err
+}
+
+// NewDecoder constructs a new base32 stream decoder.
+func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
+	return &decoder{enc: enc, r: &newlineFilteringReader{r}}
+}
+
+// DecodedLen returns the maximum length in bytes of the decoded data
+// corresponding to n bytes of base32-encoded data.
+func (enc *Encoding) DecodedLen(n int) int { return n / 8 * 5 }
diff --git a/third_party/gofrontend/libgo/go/encoding/base32/base32_test.go b/third_party/gofrontend/libgo/go/encoding/base32/base32_test.go
new file mode 100644
index 0000000..f56b996
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/base32/base32_test.go
@@ -0,0 +1,286 @@
+// 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 base32
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+type testpair struct {
+	decoded, encoded string
+}
+
+var pairs = []testpair{
+	// RFC 4648 examples
+	{"", ""},
+	{"f", "MY======"},
+	{"fo", "MZXQ===="},
+	{"foo", "MZXW6==="},
+	{"foob", "MZXW6YQ="},
+	{"fooba", "MZXW6YTB"},
+	{"foobar", "MZXW6YTBOI======"},
+
+	// Wikipedia examples, converted to base32
+	{"sure.", "ON2XEZJO"},
+	{"sure", "ON2XEZI="},
+	{"sur", "ON2XE==="},
+	{"su", "ON2Q===="},
+	{"leasure.", "NRSWC43VOJSS4==="},
+	{"easure.", "MVQXG5LSMUXA===="},
+	{"asure.", "MFZXK4TFFY======"},
+	{"sure.", "ON2XEZJO"},
+}
+
+var bigtest = testpair{
+	"Twas brillig, and the slithy toves",
+	"KR3WC4ZAMJZGS3DMNFTSYIDBNZSCA5DIMUQHG3DJORUHSIDUN53GK4Y=",
+}
+
+func testEqual(t *testing.T, msg string, args ...interface{}) bool {
+	if args[len(args)-2] != args[len(args)-1] {
+		t.Errorf(msg, args...)
+		return false
+	}
+	return true
+}
+
+func TestEncode(t *testing.T) {
+	for _, p := range pairs {
+		got := StdEncoding.EncodeToString([]byte(p.decoded))
+		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded)
+	}
+}
+
+func TestEncoder(t *testing.T) {
+	for _, p := range pairs {
+		bb := &bytes.Buffer{}
+		encoder := NewEncoder(StdEncoding, bb)
+		encoder.Write([]byte(p.decoded))
+		encoder.Close()
+		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded)
+	}
+}
+
+func TestEncoderBuffering(t *testing.T) {
+	input := []byte(bigtest.decoded)
+	for bs := 1; bs <= 12; bs++ {
+		bb := &bytes.Buffer{}
+		encoder := NewEncoder(StdEncoding, bb)
+		for pos := 0; pos < len(input); pos += bs {
+			end := pos + bs
+			if end > len(input) {
+				end = len(input)
+			}
+			n, err := encoder.Write(input[pos:end])
+			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
+			testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
+		}
+		err := encoder.Close()
+		testEqual(t, "Close gave error %v, want %v", err, error(nil))
+		testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded)
+	}
+}
+
+func TestDecode(t *testing.T) {
+	for _, p := range pairs {
+		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
+		count, end, err := StdEncoding.decode(dbuf, []byte(p.encoded))
+		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
+		testEqual(t, "Decode(%q) = length %v, want %v", p.encoded, count, len(p.decoded))
+		if len(p.encoded) > 0 {
+			testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '='))
+		}
+		testEqual(t, "Decode(%q) = %q, want %q", p.encoded,
+			string(dbuf[0:count]),
+			p.decoded)
+
+		dbuf, err = StdEncoding.DecodeString(p.encoded)
+		testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, error(nil))
+		testEqual(t, "DecodeString(%q) = %q, want %q", p.encoded, string(dbuf), p.decoded)
+	}
+}
+
+func TestDecoder(t *testing.T) {
+	for _, p := range pairs {
+		decoder := NewDecoder(StdEncoding, strings.NewReader(p.encoded))
+		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
+		count, err := decoder.Read(dbuf)
+		if err != nil && err != io.EOF {
+			t.Fatal("Read failed", err)
+		}
+		testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded))
+		testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
+		if err != io.EOF {
+			count, err = decoder.Read(dbuf)
+		}
+		testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
+	}
+}
+
+func TestDecoderBuffering(t *testing.T) {
+	for bs := 1; bs <= 12; bs++ {
+		decoder := NewDecoder(StdEncoding, strings.NewReader(bigtest.encoded))
+		buf := make([]byte, len(bigtest.decoded)+12)
+		var total int
+		for total = 0; total < len(bigtest.decoded); {
+			n, err := decoder.Read(buf[total : total+bs])
+			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, error(nil))
+			total += n
+		}
+		testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
+	}
+}
+
+func TestDecodeCorrupt(t *testing.T) {
+	testCases := []struct {
+		input  string
+		offset int // -1 means no corruption.
+	}{
+		{"", -1},
+		{"!!!!", 0},
+		{"x===", 0},
+		{"AA=A====", 2},
+		{"AAA=AAAA", 3},
+		{"MMMMMMMMM", 8},
+		{"MMMMMM", 0},
+		{"A=", 1},
+		{"AA=", 3},
+		{"AA==", 4},
+		{"AA===", 5},
+		{"AAAA=", 5},
+		{"AAAA==", 6},
+		{"AAAAA=", 6},
+		{"AAAAA==", 7},
+		{"A=======", 1},
+		{"AA======", -1},
+		{"AAA=====", 3},
+		{"AAAA====", -1},
+		{"AAAAA===", -1},
+		{"AAAAAA==", 6},
+		{"AAAAAAA=", -1},
+		{"AAAAAAAA", -1},
+	}
+	for _, tc := range testCases {
+		dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input)))
+		_, err := StdEncoding.Decode(dbuf, []byte(tc.input))
+		if tc.offset == -1 {
+			if err != nil {
+				t.Error("Decoder wrongly detected coruption in", tc.input)
+			}
+			continue
+		}
+		switch err := err.(type) {
+		case CorruptInputError:
+			testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset)
+		default:
+			t.Error("Decoder failed to detect corruption in", tc)
+		}
+	}
+}
+
+func TestBig(t *testing.T) {
+	n := 3*1000 + 1
+	raw := make([]byte, n)
+	const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	for i := 0; i < n; i++ {
+		raw[i] = alpha[i%len(alpha)]
+	}
+	encoded := new(bytes.Buffer)
+	w := NewEncoder(StdEncoding, encoded)
+	nn, err := w.Write(raw)
+	if nn != n || err != nil {
+		t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n)
+	}
+	err = w.Close()
+	if err != nil {
+		t.Fatalf("Encoder.Close() = %v want nil", err)
+	}
+	decoded, err := ioutil.ReadAll(NewDecoder(StdEncoding, encoded))
+	if err != nil {
+		t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err)
+	}
+
+	if !bytes.Equal(raw, decoded) {
+		var i int
+		for i = 0; i < len(decoded) && i < len(raw); i++ {
+			if decoded[i] != raw[i] {
+				break
+			}
+		}
+		t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i)
+	}
+}
+
+func testStringEncoding(t *testing.T, expected string, examples []string) {
+	for _, e := range examples {
+		buf, err := StdEncoding.DecodeString(e)
+		if err != nil {
+			t.Errorf("Decode(%q) failed: %v", e, err)
+			continue
+		}
+		if s := string(buf); s != expected {
+			t.Errorf("Decode(%q) = %q, want %q", e, s, expected)
+		}
+	}
+}
+
+func TestNewLineCharacters(t *testing.T) {
+	// Each of these should decode to the string "sure", without errors.
+	examples := []string{
+		"ON2XEZI=",
+		"ON2XEZI=\r",
+		"ON2XEZI=\n",
+		"ON2XEZI=\r\n",
+		"ON2XEZ\r\nI=",
+		"ON2X\rEZ\nI=",
+		"ON2X\nEZ\rI=",
+		"ON2XEZ\nI=",
+		"ON2XEZI\n=",
+	}
+	testStringEncoding(t, "sure", examples)
+
+	// Each of these should decode to the string "foobar", without errors.
+	examples = []string{
+		"MZXW6YTBOI======",
+		"MZXW6YTBOI=\r\n=====",
+	}
+	testStringEncoding(t, "foobar", examples)
+}
+
+func TestDecoderIssue4779(t *testing.T) {
+	encoded := `JRXXEZLNEBUXA43VNUQGI33MN5ZCA43JOQQGC3LFOQWCAY3PNZZWKY3UMV2HK4
+RAMFSGS4DJONUWG2LOM4QGK3DJOQWCA43FMQQGI3YKMVUXK43NN5SCA5DFNVYG64RANFXGG2LENFSH
+K3TUEB2XIIDMMFRG64TFEBSXIIDEN5WG64TFEBWWCZ3OMEQGC3DJOF2WCLRAKV2CAZLONFWQUYLEEB
+WWS3TJNUQHMZLONFQW2LBAOF2WS4ZANZXXG5DSOVSCAZLYMVZGG2LUMF2GS33OEB2WY3DBNVRW6IDM
+MFRG64TJOMQG42LTNEQHK5AKMFWGS4LVNFYCAZLYEBSWCIDDN5WW233EN4QGG33OONSXC5LBOQXCAR
+DVNFZSAYLVORSSA2LSOVZGKIDEN5WG64RANFXAU4TFOBZGK2DFNZSGK4TJOQQGS3RAOZXWY5LQORQX
+IZJAOZSWY2LUEBSXG43FEBRWS3DMOVWSAZDPNRXXEZJAMV2SAZTVM5UWC5BANZ2WY3DBBJYGC4TJMF
+2HK4ROEBCXQY3FOB2GK5LSEBZWS3TUEBXWGY3BMVRWC5BAMN2XA2LEMF2GC5BANZXW4IDQOJXWSZDF
+NZ2CYIDTOVXHIIDJNYFGG5LMOBQSA4LVNEQG6ZTGNFRWSYJAMRSXGZLSOVXHIIDNN5WGY2LUEBQW42
+LNEBUWIIDFON2CA3DBMJXXE5LNFY==
+====`
+	encodedShort := strings.Replace(encoded, "\n", "", -1)
+
+	dec := NewDecoder(StdEncoding, strings.NewReader(encoded))
+	res1, err := ioutil.ReadAll(dec)
+	if err != nil {
+		t.Errorf("ReadAll failed: %v", err)
+	}
+
+	dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort))
+	var res2 []byte
+	res2, err = ioutil.ReadAll(dec)
+	if err != nil {
+		t.Errorf("ReadAll failed: %v", err)
+	}
+
+	if !bytes.Equal(res1, res2) {
+		t.Error("Decoded results not equal")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/base64/base64.go b/third_party/gofrontend/libgo/go/encoding/base64/base64.go
new file mode 100644
index 0000000..e38c26d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/base64/base64.go
@@ -0,0 +1,393 @@
+// 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 base64 implements base64 encoding as specified by RFC 4648.
+package base64
+
+import (
+	"bytes"
+	"io"
+	"strconv"
+	"strings"
+)
+
+/*
+ * Encodings
+ */
+
+// An Encoding is a radix 64 encoding/decoding scheme, defined by a
+// 64-character alphabet.  The most common encoding is the "base64"
+// encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM
+// (RFC 1421).  RFC 4648 also defines an alternate encoding, which is
+// the standard encoding with - and _ substituted for + and /.
+type Encoding struct {
+	encode    string
+	decodeMap [256]byte
+}
+
+const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
+
+// NewEncoding returns a new Encoding defined by the given alphabet,
+// which must be a 64-byte string.
+func NewEncoding(encoder string) *Encoding {
+	e := new(Encoding)
+	e.encode = encoder
+	for i := 0; i < len(e.decodeMap); i++ {
+		e.decodeMap[i] = 0xFF
+	}
+	for i := 0; i < len(encoder); i++ {
+		e.decodeMap[encoder[i]] = byte(i)
+	}
+	return e
+}
+
+// StdEncoding is the standard base64 encoding, as defined in
+// RFC 4648.
+var StdEncoding = NewEncoding(encodeStd)
+
+// URLEncoding is the alternate base64 encoding defined in RFC 4648.
+// It is typically used in URLs and file names.
+var URLEncoding = NewEncoding(encodeURL)
+
+var removeNewlinesMapper = func(r rune) rune {
+	if r == '\r' || r == '\n' {
+		return -1
+	}
+	return r
+}
+
+/*
+ * Encoder
+ */
+
+// Encode encodes src using the encoding enc, writing
+// EncodedLen(len(src)) bytes to dst.
+//
+// The encoding pads the output to a multiple of 4 bytes,
+// so Encode is not appropriate for use on individual blocks
+// of a large data stream.  Use NewEncoder() instead.
+func (enc *Encoding) Encode(dst, src []byte) {
+	if len(src) == 0 {
+		return
+	}
+
+	for len(src) > 0 {
+		dst[0] = 0
+		dst[1] = 0
+		dst[2] = 0
+		dst[3] = 0
+
+		// Unpack 4x 6-bit source blocks into a 4 byte
+		// destination quantum
+		switch len(src) {
+		default:
+			dst[3] |= src[2] & 0x3F
+			dst[2] |= src[2] >> 6
+			fallthrough
+		case 2:
+			dst[2] |= (src[1] << 2) & 0x3F
+			dst[1] |= src[1] >> 4
+			fallthrough
+		case 1:
+			dst[1] |= (src[0] << 4) & 0x3F
+			dst[0] |= src[0] >> 2
+		}
+
+		// Encode 6-bit blocks using the base64 alphabet
+		for j := 0; j < 4; j++ {
+			dst[j] = enc.encode[dst[j]]
+		}
+
+		// Pad the final quantum
+		if len(src) < 3 {
+			dst[3] = '='
+			if len(src) < 2 {
+				dst[2] = '='
+			}
+			break
+		}
+
+		src = src[3:]
+		dst = dst[4:]
+	}
+}
+
+// EncodeToString returns the base64 encoding of src.
+func (enc *Encoding) EncodeToString(src []byte) string {
+	buf := make([]byte, enc.EncodedLen(len(src)))
+	enc.Encode(buf, src)
+	return string(buf)
+}
+
+type encoder struct {
+	err  error
+	enc  *Encoding
+	w    io.Writer
+	buf  [3]byte    // buffered data waiting to be encoded
+	nbuf int        // number of bytes in buf
+	out  [1024]byte // output buffer
+}
+
+func (e *encoder) Write(p []byte) (n int, err error) {
+	if e.err != nil {
+		return 0, e.err
+	}
+
+	// Leading fringe.
+	if e.nbuf > 0 {
+		var i int
+		for i = 0; i < len(p) && e.nbuf < 3; i++ {
+			e.buf[e.nbuf] = p[i]
+			e.nbuf++
+		}
+		n += i
+		p = p[i:]
+		if e.nbuf < 3 {
+			return
+		}
+		e.enc.Encode(e.out[0:], e.buf[0:])
+		if _, e.err = e.w.Write(e.out[0:4]); e.err != nil {
+			return n, e.err
+		}
+		e.nbuf = 0
+	}
+
+	// Large interior chunks.
+	for len(p) >= 3 {
+		nn := len(e.out) / 4 * 3
+		if nn > len(p) {
+			nn = len(p)
+			nn -= nn % 3
+		}
+		e.enc.Encode(e.out[0:], p[0:nn])
+		if _, e.err = e.w.Write(e.out[0 : nn/3*4]); e.err != nil {
+			return n, e.err
+		}
+		n += nn
+		p = p[nn:]
+	}
+
+	// Trailing fringe.
+	for i := 0; i < len(p); i++ {
+		e.buf[i] = p[i]
+	}
+	e.nbuf = len(p)
+	n += len(p)
+	return
+}
+
+// Close flushes any pending output from the encoder.
+// It is an error to call Write after calling Close.
+func (e *encoder) Close() error {
+	// If there's anything left in the buffer, flush it out
+	if e.err == nil && e.nbuf > 0 {
+		e.enc.Encode(e.out[0:], e.buf[0:e.nbuf])
+		e.nbuf = 0
+		_, e.err = e.w.Write(e.out[0:4])
+	}
+	return e.err
+}
+
+// NewEncoder returns a new base64 stream encoder.  Data written to
+// the returned writer will be encoded using enc and then written to w.
+// Base64 encodings operate in 4-byte blocks; when finished
+// writing, the caller must Close the returned encoder to flush any
+// partially written blocks.
+func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
+	return &encoder{enc: enc, w: w}
+}
+
+// EncodedLen returns the length in bytes of the base64 encoding
+// of an input buffer of length n.
+func (enc *Encoding) EncodedLen(n int) int { return (n + 2) / 3 * 4 }
+
+/*
+ * Decoder
+ */
+
+type CorruptInputError int64
+
+func (e CorruptInputError) Error() string {
+	return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
+}
+
+// decode is like Decode but returns an additional 'end' value, which
+// indicates if end-of-message padding was encountered and thus any
+// additional data is an error. This method assumes that src has been
+// stripped of all supported whitespace ('\r' and '\n').
+func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
+	olen := len(src)
+	for len(src) > 0 && !end {
+		// Decode quantum using the base64 alphabet
+		var dbuf [4]byte
+		dlen := 4
+
+		for j := range dbuf {
+			if len(src) == 0 {
+				return n, false, CorruptInputError(olen - len(src) - j)
+			}
+			in := src[0]
+			src = src[1:]
+			if in == '=' {
+				// We've reached the end and there's padding
+				switch j {
+				case 0, 1:
+					// incorrect padding
+					return n, false, CorruptInputError(olen - len(src) - 1)
+				case 2:
+					// "==" is expected, the first "=" is already consumed.
+					if len(src) == 0 {
+						// not enough padding
+						return n, false, CorruptInputError(olen)
+					}
+					if src[0] != '=' {
+						// incorrect padding
+						return n, false, CorruptInputError(olen - len(src) - 1)
+					}
+					src = src[1:]
+				}
+				if len(src) > 0 {
+					// trailing garbage
+					err = CorruptInputError(olen - len(src))
+				}
+				dlen, end = j, true
+				break
+			}
+			dbuf[j] = enc.decodeMap[in]
+			if dbuf[j] == 0xFF {
+				return n, false, CorruptInputError(olen - len(src) - 1)
+			}
+		}
+
+		// Pack 4x 6-bit source blocks into 3 byte destination
+		// quantum
+		switch dlen {
+		case 4:
+			dst[2] = dbuf[2]<<6 | dbuf[3]
+			fallthrough
+		case 3:
+			dst[1] = dbuf[1]<<4 | dbuf[2]>>2
+			fallthrough
+		case 2:
+			dst[0] = dbuf[0]<<2 | dbuf[1]>>4
+		}
+		dst = dst[3:]
+		n += dlen - 1
+	}
+
+	return n, end, err
+}
+
+// Decode decodes src using the encoding enc.  It writes at most
+// DecodedLen(len(src)) bytes to dst and returns the number of bytes
+// written.  If src contains invalid base64 data, it will return the
+// number of bytes successfully written and CorruptInputError.
+// New line characters (\r and \n) are ignored.
+func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
+	src = bytes.Map(removeNewlinesMapper, src)
+	n, _, err = enc.decode(dst, src)
+	return
+}
+
+// DecodeString returns the bytes represented by the base64 string s.
+func (enc *Encoding) DecodeString(s string) ([]byte, error) {
+	s = strings.Map(removeNewlinesMapper, s)
+	dbuf := make([]byte, enc.DecodedLen(len(s)))
+	n, err := enc.Decode(dbuf, []byte(s))
+	return dbuf[:n], err
+}
+
+type decoder struct {
+	err    error
+	enc    *Encoding
+	r      io.Reader
+	end    bool       // saw end of message
+	buf    [1024]byte // leftover input
+	nbuf   int
+	out    []byte // leftover decoded output
+	outbuf [1024 / 4 * 3]byte
+}
+
+func (d *decoder) Read(p []byte) (n int, err error) {
+	if d.err != nil {
+		return 0, d.err
+	}
+
+	// Use leftover decoded output from last read.
+	if len(d.out) > 0 {
+		n = copy(p, d.out)
+		d.out = d.out[n:]
+		return n, nil
+	}
+
+	// Read a chunk.
+	nn := len(p) / 3 * 4
+	if nn < 4 {
+		nn = 4
+	}
+	if nn > len(d.buf) {
+		nn = len(d.buf)
+	}
+	nn, d.err = io.ReadAtLeast(d.r, d.buf[d.nbuf:nn], 4-d.nbuf)
+	d.nbuf += nn
+	if d.err != nil || d.nbuf < 4 {
+		return 0, d.err
+	}
+
+	// Decode chunk into p, or d.out and then p if p is too small.
+	nr := d.nbuf / 4 * 4
+	nw := d.nbuf / 4 * 3
+	if nw > len(p) {
+		nw, d.end, d.err = d.enc.decode(d.outbuf[0:], d.buf[0:nr])
+		d.out = d.outbuf[0:nw]
+		n = copy(p, d.out)
+		d.out = d.out[n:]
+	} else {
+		n, d.end, d.err = d.enc.decode(p, d.buf[0:nr])
+	}
+	d.nbuf -= nr
+	for i := 0; i < d.nbuf; i++ {
+		d.buf[i] = d.buf[i+nr]
+	}
+
+	if d.err == nil {
+		d.err = err
+	}
+	return n, d.err
+}
+
+type newlineFilteringReader struct {
+	wrapped io.Reader
+}
+
+func (r *newlineFilteringReader) Read(p []byte) (int, error) {
+	n, err := r.wrapped.Read(p)
+	for n > 0 {
+		offset := 0
+		for i, b := range p[0:n] {
+			if b != '\r' && b != '\n' {
+				if i != offset {
+					p[offset] = b
+				}
+				offset++
+			}
+		}
+		if offset > 0 {
+			return offset, err
+		}
+		// Previous buffer entirely whitespace, read again
+		n, err = r.wrapped.Read(p)
+	}
+	return n, err
+}
+
+// NewDecoder constructs a new base64 stream decoder.
+func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
+	return &decoder{enc: enc, r: &newlineFilteringReader{r}}
+}
+
+// DecodedLen returns the maximum length in bytes of the decoded data
+// corresponding to n bytes of base64-encoded data.
+func (enc *Encoding) DecodedLen(n int) int { return n / 4 * 3 }
diff --git a/third_party/gofrontend/libgo/go/encoding/base64/base64_test.go b/third_party/gofrontend/libgo/go/encoding/base64/base64_test.go
new file mode 100644
index 0000000..a075194
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/base64/base64_test.go
@@ -0,0 +1,344 @@
+// 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 base64
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"io/ioutil"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+)
+
+type testpair struct {
+	decoded, encoded string
+}
+
+var pairs = []testpair{
+	// RFC 3548 examples
+	{"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l+"},
+	{"\x14\xfb\x9c\x03\xd9", "FPucA9k="},
+	{"\x14\xfb\x9c\x03", "FPucAw=="},
+
+	// RFC 4648 examples
+	{"", ""},
+	{"f", "Zg=="},
+	{"fo", "Zm8="},
+	{"foo", "Zm9v"},
+	{"foob", "Zm9vYg=="},
+	{"fooba", "Zm9vYmE="},
+	{"foobar", "Zm9vYmFy"},
+
+	// Wikipedia examples
+	{"sure.", "c3VyZS4="},
+	{"sure", "c3VyZQ=="},
+	{"sur", "c3Vy"},
+	{"su", "c3U="},
+	{"leasure.", "bGVhc3VyZS4="},
+	{"easure.", "ZWFzdXJlLg=="},
+	{"asure.", "YXN1cmUu"},
+	{"sure.", "c3VyZS4="},
+}
+
+var bigtest = testpair{
+	"Twas brillig, and the slithy toves",
+	"VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==",
+}
+
+func testEqual(t *testing.T, msg string, args ...interface{}) bool {
+	if args[len(args)-2] != args[len(args)-1] {
+		t.Errorf(msg, args...)
+		return false
+	}
+	return true
+}
+
+func TestEncode(t *testing.T) {
+	for _, p := range pairs {
+		got := StdEncoding.EncodeToString([]byte(p.decoded))
+		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded)
+	}
+}
+
+func TestEncoder(t *testing.T) {
+	for _, p := range pairs {
+		bb := &bytes.Buffer{}
+		encoder := NewEncoder(StdEncoding, bb)
+		encoder.Write([]byte(p.decoded))
+		encoder.Close()
+		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded)
+	}
+}
+
+func TestEncoderBuffering(t *testing.T) {
+	input := []byte(bigtest.decoded)
+	for bs := 1; bs <= 12; bs++ {
+		bb := &bytes.Buffer{}
+		encoder := NewEncoder(StdEncoding, bb)
+		for pos := 0; pos < len(input); pos += bs {
+			end := pos + bs
+			if end > len(input) {
+				end = len(input)
+			}
+			n, err := encoder.Write(input[pos:end])
+			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
+			testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
+		}
+		err := encoder.Close()
+		testEqual(t, "Close gave error %v, want %v", err, error(nil))
+		testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded)
+	}
+}
+
+func TestDecode(t *testing.T) {
+	for _, p := range pairs {
+		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
+		count, end, err := StdEncoding.decode(dbuf, []byte(p.encoded))
+		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
+		testEqual(t, "Decode(%q) = length %v, want %v", p.encoded, count, len(p.decoded))
+		if len(p.encoded) > 0 {
+			testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '='))
+		}
+		testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
+
+		dbuf, err = StdEncoding.DecodeString(p.encoded)
+		testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, error(nil))
+		testEqual(t, "DecodeString(%q) = %q, want %q", string(dbuf), p.decoded)
+	}
+}
+
+func TestDecoder(t *testing.T) {
+	for _, p := range pairs {
+		decoder := NewDecoder(StdEncoding, strings.NewReader(p.encoded))
+		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
+		count, err := decoder.Read(dbuf)
+		if err != nil && err != io.EOF {
+			t.Fatal("Read failed", err)
+		}
+		testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded))
+		testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
+		if err != io.EOF {
+			count, err = decoder.Read(dbuf)
+		}
+		testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
+	}
+}
+
+func TestDecoderBuffering(t *testing.T) {
+	for bs := 1; bs <= 12; bs++ {
+		decoder := NewDecoder(StdEncoding, strings.NewReader(bigtest.encoded))
+		buf := make([]byte, len(bigtest.decoded)+12)
+		var total int
+		for total = 0; total < len(bigtest.decoded); {
+			n, err := decoder.Read(buf[total : total+bs])
+			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, error(nil))
+			total += n
+		}
+		testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
+	}
+}
+
+func TestDecodeCorrupt(t *testing.T) {
+	testCases := []struct {
+		input  string
+		offset int // -1 means no corruption.
+	}{
+		{"", -1},
+		{"!!!!", 0},
+		{"====", 0},
+		{"x===", 1},
+		{"=AAA", 0},
+		{"A=AA", 1},
+		{"AA=A", 2},
+		{"AA==A", 4},
+		{"AAA=AAAA", 4},
+		{"AAAAA", 4},
+		{"AAAAAA", 4},
+		{"A=", 1},
+		{"A==", 1},
+		{"AA=", 3},
+		{"AA==", -1},
+		{"AAA=", -1},
+		{"AAAA", -1},
+		{"AAAAAA=", 7},
+		{"YWJjZA=====", 8},
+	}
+	for _, tc := range testCases {
+		dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input)))
+		_, err := StdEncoding.Decode(dbuf, []byte(tc.input))
+		if tc.offset == -1 {
+			if err != nil {
+				t.Error("Decoder wrongly detected coruption in", tc.input)
+			}
+			continue
+		}
+		switch err := err.(type) {
+		case CorruptInputError:
+			testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset)
+		default:
+			t.Error("Decoder failed to detect corruption in", tc)
+		}
+	}
+}
+
+func TestBig(t *testing.T) {
+	n := 3*1000 + 1
+	raw := make([]byte, n)
+	const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	for i := 0; i < n; i++ {
+		raw[i] = alpha[i%len(alpha)]
+	}
+	encoded := new(bytes.Buffer)
+	w := NewEncoder(StdEncoding, encoded)
+	nn, err := w.Write(raw)
+	if nn != n || err != nil {
+		t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n)
+	}
+	err = w.Close()
+	if err != nil {
+		t.Fatalf("Encoder.Close() = %v want nil", err)
+	}
+	decoded, err := ioutil.ReadAll(NewDecoder(StdEncoding, encoded))
+	if err != nil {
+		t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err)
+	}
+
+	if !bytes.Equal(raw, decoded) {
+		var i int
+		for i = 0; i < len(decoded) && i < len(raw); i++ {
+			if decoded[i] != raw[i] {
+				break
+			}
+		}
+		t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i)
+	}
+}
+
+func TestNewLineCharacters(t *testing.T) {
+	// Each of these should decode to the string "sure", without errors.
+	const expected = "sure"
+	examples := []string{
+		"c3VyZQ==",
+		"c3VyZQ==\r",
+		"c3VyZQ==\n",
+		"c3VyZQ==\r\n",
+		"c3VyZ\r\nQ==",
+		"c3V\ryZ\nQ==",
+		"c3V\nyZ\rQ==",
+		"c3VyZ\nQ==",
+		"c3VyZQ\n==",
+		"c3VyZQ=\n=",
+		"c3VyZQ=\r\n\r\n=",
+	}
+	for _, e := range examples {
+		buf, err := StdEncoding.DecodeString(e)
+		if err != nil {
+			t.Errorf("Decode(%q) failed: %v", e, err)
+			continue
+		}
+		if s := string(buf); s != expected {
+			t.Errorf("Decode(%q) = %q, want %q", e, s, expected)
+		}
+	}
+}
+
+type nextRead struct {
+	n   int   // bytes to return
+	err error // error to return
+}
+
+// faultInjectReader returns data from source, rate-limited
+// and with the errors as written to nextc.
+type faultInjectReader struct {
+	source string
+	nextc  <-chan nextRead
+}
+
+func (r *faultInjectReader) Read(p []byte) (int, error) {
+	nr := <-r.nextc
+	if len(p) > nr.n {
+		p = p[:nr.n]
+	}
+	n := copy(p, r.source)
+	r.source = r.source[n:]
+	return n, nr.err
+}
+
+// tests that we don't ignore errors from our underlying reader
+func TestDecoderIssue3577(t *testing.T) {
+	next := make(chan nextRead, 10)
+	wantErr := errors.New("my error")
+	next <- nextRead{5, nil}
+	next <- nextRead{10, wantErr}
+	next <- nextRead{0, wantErr}
+	d := NewDecoder(StdEncoding, &faultInjectReader{
+		source: "VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==", // twas brillig...
+		nextc:  next,
+	})
+	errc := make(chan error)
+	go func() {
+		_, err := ioutil.ReadAll(d)
+		errc <- err
+	}()
+	select {
+	case err := <-errc:
+		if err != wantErr {
+			t.Errorf("got error %v; want %v", err, wantErr)
+		}
+	case <-time.After(5 * time.Second):
+		t.Errorf("timeout; Decoder blocked without returning an error")
+	}
+}
+
+func TestDecoderIssue4779(t *testing.T) {
+	encoded := `CP/EAT8AAAEF
+AQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAAB
+BAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHx
+Y3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm
+9jdHV2d3h5ent8fX5/cRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS
+0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0
+pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//aAAwDAQACEQMRAD8A9VSSSSUpJJJJSkkkJ+Tj
+1kiy1jCJJDnAcCTykpKkuQ6p/jN6FgmxlNduXawwAzaGH+V6jn/R/wCt71zdn+N/qL3kVYFNYB4N
+ji6PDVjWpKp9TSXnvTf8bFNjg3qOEa2n6VlLpj/rT/pf567DpX1i6L1hs9Py67X8mqdtg/rUWbbf
++gkp0kkkklKSSSSUpJJJJT//0PVUkkklKVLq3WMDpGI7KzrNjADtYNXvI/Mqr/Pd/q9W3vaxjnvM
+NaCXE9gNSvGPrf8AWS3qmba5jjsJhoB0DAf0NDf6sevf+/lf8Hj0JJATfWT6/dV6oXU1uOLQeKKn
+EQP+Hubtfe/+R7Mf/g7f5xcocp++Z11JMCJPgFBxOg7/AOuqDx8I/ikpkXkmSdU8mJIJA/O8EMAy
+j+mSARB/17pKVXYWHXjsj7yIex0PadzXMO1zT5KHoNA3HT8ietoGhgjsfA+CSnvvqh/jJtqsrwOv
+2b6NGNzXfTYexzJ+nU7/ALkf4P8Awv6P9KvTQQ4AgyDqCF85Pho3CTB7eHwXoH+LT65uZbX9X+o2
+bqbPb06551Y4
+`
+	encodedShort := strings.Replace(encoded, "\n", "", -1)
+
+	dec := NewDecoder(StdEncoding, strings.NewReader(encoded))
+	res1, err := ioutil.ReadAll(dec)
+	if err != nil {
+		t.Errorf("ReadAll failed: %v", err)
+	}
+
+	dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort))
+	var res2 []byte
+	res2, err = ioutil.ReadAll(dec)
+	if err != nil {
+		t.Errorf("ReadAll failed: %v", err)
+	}
+
+	if !bytes.Equal(res1, res2) {
+		t.Error("Decoded results not equal")
+	}
+}
+
+func TestDecoderIssue7733(t *testing.T) {
+	s, err := StdEncoding.DecodeString("YWJjZA=====")
+	want := CorruptInputError(8)
+	if !reflect.DeepEqual(want, err) {
+		t.Errorf("Error = %v; want CorruptInputError(8)", err)
+	}
+	if string(s) != "abcd" {
+		t.Errorf("DecodeString = %q; want abcd", s)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/binary/binary.go b/third_party/gofrontend/libgo/go/encoding/binary/binary.go
new file mode 100644
index 0000000..a569487
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/binary/binary.go
@@ -0,0 +1,639 @@
+// 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 binary implements simple translation between numbers and byte
+// sequences and encoding and decoding of varints.
+//
+// Numbers are translated by reading and writing fixed-size values.
+// A fixed-size value is either a fixed-size arithmetic
+// type (int8, uint8, int16, float32, complex64, ...)
+// or an array or struct containing only fixed-size values.
+//
+// Varints are a method of encoding integers using one or more bytes;
+// numbers with smaller absolute value take a smaller number of bytes.
+// For a specification, see http://code.google.com/apis/protocolbuffers/docs/encoding.html.
+//
+// This package favors simplicity over efficiency. Clients that require
+// high-performance serialization, especially for large data structures,
+// should look at more advanced solutions such as the encoding/gob
+// package or protocol buffers.
+package binary
+
+import (
+	"errors"
+	"io"
+	"math"
+	"reflect"
+)
+
+// A ByteOrder specifies how to convert byte sequences into
+// 16-, 32-, or 64-bit unsigned integers.
+type ByteOrder interface {
+	Uint16([]byte) uint16
+	Uint32([]byte) uint32
+	Uint64([]byte) uint64
+	PutUint16([]byte, uint16)
+	PutUint32([]byte, uint32)
+	PutUint64([]byte, uint64)
+	String() string
+}
+
+// LittleEndian is the little-endian implementation of ByteOrder.
+var LittleEndian littleEndian
+
+// BigEndian is the big-endian implementation of ByteOrder.
+var BigEndian bigEndian
+
+type littleEndian struct{}
+
+func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 }
+
+func (littleEndian) PutUint16(b []byte, v uint16) {
+	b[0] = byte(v)
+	b[1] = byte(v >> 8)
+}
+
+func (littleEndian) Uint32(b []byte) uint32 {
+	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+func (littleEndian) PutUint32(b []byte, v uint32) {
+	b[0] = byte(v)
+	b[1] = byte(v >> 8)
+	b[2] = byte(v >> 16)
+	b[3] = byte(v >> 24)
+}
+
+func (littleEndian) Uint64(b []byte) uint64 {
+	return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+		uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+}
+
+func (littleEndian) PutUint64(b []byte, v uint64) {
+	b[0] = byte(v)
+	b[1] = byte(v >> 8)
+	b[2] = byte(v >> 16)
+	b[3] = byte(v >> 24)
+	b[4] = byte(v >> 32)
+	b[5] = byte(v >> 40)
+	b[6] = byte(v >> 48)
+	b[7] = byte(v >> 56)
+}
+
+func (littleEndian) String() string { return "LittleEndian" }
+
+func (littleEndian) GoString() string { return "binary.LittleEndian" }
+
+type bigEndian struct{}
+
+func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 }
+
+func (bigEndian) PutUint16(b []byte, v uint16) {
+	b[0] = byte(v >> 8)
+	b[1] = byte(v)
+}
+
+func (bigEndian) Uint32(b []byte) uint32 {
+	return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
+}
+
+func (bigEndian) PutUint32(b []byte, v uint32) {
+	b[0] = byte(v >> 24)
+	b[1] = byte(v >> 16)
+	b[2] = byte(v >> 8)
+	b[3] = byte(v)
+}
+
+func (bigEndian) Uint64(b []byte) uint64 {
+	return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+		uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+}
+
+func (bigEndian) PutUint64(b []byte, v uint64) {
+	b[0] = byte(v >> 56)
+	b[1] = byte(v >> 48)
+	b[2] = byte(v >> 40)
+	b[3] = byte(v >> 32)
+	b[4] = byte(v >> 24)
+	b[5] = byte(v >> 16)
+	b[6] = byte(v >> 8)
+	b[7] = byte(v)
+}
+
+func (bigEndian) String() string { return "BigEndian" }
+
+func (bigEndian) GoString() string { return "binary.BigEndian" }
+
+// Read reads structured binary data from r into data.
+// Data must be a pointer to a fixed-size value or a slice
+// of fixed-size values.
+// Bytes read from r are decoded using the specified byte order
+// and written to successive fields of the data.
+// When reading into structs, the field data for fields with
+// blank (_) field names is skipped; i.e., blank field names
+// may be used for padding.
+// When reading into a struct, all non-blank fields must be exported.
+func Read(r io.Reader, order ByteOrder, data interface{}) error {
+	// Fast path for basic types and slices.
+	if n := intDataSize(data); n != 0 {
+		var b [8]byte
+		var bs []byte
+		if n > len(b) {
+			bs = make([]byte, n)
+		} else {
+			bs = b[:n]
+		}
+		if _, err := io.ReadFull(r, bs); err != nil {
+			return err
+		}
+		switch data := data.(type) {
+		case *int8:
+			*data = int8(b[0])
+		case *uint8:
+			*data = b[0]
+		case *int16:
+			*data = int16(order.Uint16(bs))
+		case *uint16:
+			*data = order.Uint16(bs)
+		case *int32:
+			*data = int32(order.Uint32(bs))
+		case *uint32:
+			*data = order.Uint32(bs)
+		case *int64:
+			*data = int64(order.Uint64(bs))
+		case *uint64:
+			*data = order.Uint64(bs)
+		case []int8:
+			for i, x := range bs { // Easier to loop over the input for 8-bit values.
+				data[i] = int8(x)
+			}
+		case []uint8:
+			copy(data, bs)
+		case []int16:
+			for i := range data {
+				data[i] = int16(order.Uint16(bs[2*i:]))
+			}
+		case []uint16:
+			for i := range data {
+				data[i] = order.Uint16(bs[2*i:])
+			}
+		case []int32:
+			for i := range data {
+				data[i] = int32(order.Uint32(bs[4*i:]))
+			}
+		case []uint32:
+			for i := range data {
+				data[i] = order.Uint32(bs[4*i:])
+			}
+		case []int64:
+			for i := range data {
+				data[i] = int64(order.Uint64(bs[8*i:]))
+			}
+		case []uint64:
+			for i := range data {
+				data[i] = order.Uint64(bs[8*i:])
+			}
+		}
+		return nil
+	}
+
+	// Fallback to reflect-based decoding.
+	var v reflect.Value
+	switch d := reflect.ValueOf(data); d.Kind() {
+	case reflect.Ptr:
+		v = d.Elem()
+	case reflect.Slice:
+		v = d
+	default:
+		return errors.New("binary.Read: invalid type " + d.Type().String())
+	}
+	size, err := dataSize(v)
+	if err != nil {
+		return errors.New("binary.Read: " + err.Error())
+	}
+	d := &decoder{order: order, buf: make([]byte, size)}
+	if _, err := io.ReadFull(r, d.buf); err != nil {
+		return err
+	}
+	d.value(v)
+	return nil
+}
+
+// Write writes the binary representation of data into w.
+// Data must be a fixed-size value or a slice of fixed-size
+// values, or a pointer to such data.
+// Bytes written to w are encoded using the specified byte order
+// and read from successive fields of the data.
+// When writing structs, zero values are written for fields
+// with blank (_) field names.
+func Write(w io.Writer, order ByteOrder, data interface{}) error {
+	// Fast path for basic types and slices.
+	if n := intDataSize(data); n != 0 {
+		var b [8]byte
+		var bs []byte
+		if n > len(b) {
+			bs = make([]byte, n)
+		} else {
+			bs = b[:n]
+		}
+		switch v := data.(type) {
+		case *int8:
+			bs = b[:1]
+			b[0] = byte(*v)
+		case int8:
+			bs = b[:1]
+			b[0] = byte(v)
+		case []int8:
+			for i, x := range v {
+				bs[i] = byte(x)
+			}
+		case *uint8:
+			bs = b[:1]
+			b[0] = *v
+		case uint8:
+			bs = b[:1]
+			b[0] = byte(v)
+		case []uint8:
+			bs = v
+		case *int16:
+			bs = b[:2]
+			order.PutUint16(bs, uint16(*v))
+		case int16:
+			bs = b[:2]
+			order.PutUint16(bs, uint16(v))
+		case []int16:
+			for i, x := range v {
+				order.PutUint16(bs[2*i:], uint16(x))
+			}
+		case *uint16:
+			bs = b[:2]
+			order.PutUint16(bs, *v)
+		case uint16:
+			bs = b[:2]
+			order.PutUint16(bs, v)
+		case []uint16:
+			for i, x := range v {
+				order.PutUint16(bs[2*i:], x)
+			}
+		case *int32:
+			bs = b[:4]
+			order.PutUint32(bs, uint32(*v))
+		case int32:
+			bs = b[:4]
+			order.PutUint32(bs, uint32(v))
+		case []int32:
+			for i, x := range v {
+				order.PutUint32(bs[4*i:], uint32(x))
+			}
+		case *uint32:
+			bs = b[:4]
+			order.PutUint32(bs, *v)
+		case uint32:
+			bs = b[:4]
+			order.PutUint32(bs, v)
+		case []uint32:
+			for i, x := range v {
+				order.PutUint32(bs[4*i:], x)
+			}
+		case *int64:
+			bs = b[:8]
+			order.PutUint64(bs, uint64(*v))
+		case int64:
+			bs = b[:8]
+			order.PutUint64(bs, uint64(v))
+		case []int64:
+			for i, x := range v {
+				order.PutUint64(bs[8*i:], uint64(x))
+			}
+		case *uint64:
+			bs = b[:8]
+			order.PutUint64(bs, *v)
+		case uint64:
+			bs = b[:8]
+			order.PutUint64(bs, v)
+		case []uint64:
+			for i, x := range v {
+				order.PutUint64(bs[8*i:], x)
+			}
+		}
+		_, err := w.Write(bs)
+		return err
+	}
+
+	// Fallback to reflect-based encoding.
+	v := reflect.Indirect(reflect.ValueOf(data))
+	size, err := dataSize(v)
+	if err != nil {
+		return errors.New("binary.Write: " + err.Error())
+	}
+	buf := make([]byte, size)
+	e := &encoder{order: order, buf: buf}
+	e.value(v)
+	_, err = w.Write(buf)
+	return err
+}
+
+// Size returns how many bytes Write would generate to encode the value v, which
+// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
+func Size(v interface{}) int {
+	n, err := dataSize(reflect.Indirect(reflect.ValueOf(v)))
+	if err != nil {
+		return -1
+	}
+	return n
+}
+
+// dataSize returns the number of bytes the actual data represented by v occupies in memory.
+// For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
+// it returns the length of the slice times the element size and does not count the memory
+// occupied by the header.
+func dataSize(v reflect.Value) (int, error) {
+	if v.Kind() == reflect.Slice {
+		elem, err := sizeof(v.Type().Elem())
+		if err != nil {
+			return 0, err
+		}
+		return v.Len() * elem, nil
+	}
+	return sizeof(v.Type())
+}
+
+func sizeof(t reflect.Type) (int, error) {
+	switch t.Kind() {
+	case reflect.Array:
+		n, err := sizeof(t.Elem())
+		if err != nil {
+			return 0, err
+		}
+		return t.Len() * n, nil
+
+	case reflect.Struct:
+		sum := 0
+		for i, n := 0, t.NumField(); i < n; i++ {
+			s, err := sizeof(t.Field(i).Type)
+			if err != nil {
+				return 0, err
+			}
+			sum += s
+		}
+		return sum, nil
+
+	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+		reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+		reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
+		return int(t.Size()), nil
+	}
+	return 0, errors.New("invalid type " + t.String())
+}
+
+type coder struct {
+	order ByteOrder
+	buf   []byte
+}
+
+type decoder coder
+type encoder coder
+
+func (d *decoder) uint8() uint8 {
+	x := d.buf[0]
+	d.buf = d.buf[1:]
+	return x
+}
+
+func (e *encoder) uint8(x uint8) {
+	e.buf[0] = x
+	e.buf = e.buf[1:]
+}
+
+func (d *decoder) uint16() uint16 {
+	x := d.order.Uint16(d.buf[0:2])
+	d.buf = d.buf[2:]
+	return x
+}
+
+func (e *encoder) uint16(x uint16) {
+	e.order.PutUint16(e.buf[0:2], x)
+	e.buf = e.buf[2:]
+}
+
+func (d *decoder) uint32() uint32 {
+	x := d.order.Uint32(d.buf[0:4])
+	d.buf = d.buf[4:]
+	return x
+}
+
+func (e *encoder) uint32(x uint32) {
+	e.order.PutUint32(e.buf[0:4], x)
+	e.buf = e.buf[4:]
+}
+
+func (d *decoder) uint64() uint64 {
+	x := d.order.Uint64(d.buf[0:8])
+	d.buf = d.buf[8:]
+	return x
+}
+
+func (e *encoder) uint64(x uint64) {
+	e.order.PutUint64(e.buf[0:8], x)
+	e.buf = e.buf[8:]
+}
+
+func (d *decoder) int8() int8 { return int8(d.uint8()) }
+
+func (e *encoder) int8(x int8) { e.uint8(uint8(x)) }
+
+func (d *decoder) int16() int16 { return int16(d.uint16()) }
+
+func (e *encoder) int16(x int16) { e.uint16(uint16(x)) }
+
+func (d *decoder) int32() int32 { return int32(d.uint32()) }
+
+func (e *encoder) int32(x int32) { e.uint32(uint32(x)) }
+
+func (d *decoder) int64() int64 { return int64(d.uint64()) }
+
+func (e *encoder) int64(x int64) { e.uint64(uint64(x)) }
+
+func (d *decoder) value(v reflect.Value) {
+	switch v.Kind() {
+	case reflect.Array:
+		l := v.Len()
+		for i := 0; i < l; i++ {
+			d.value(v.Index(i))
+		}
+
+	case reflect.Struct:
+		t := v.Type()
+		l := v.NumField()
+		for i := 0; i < l; i++ {
+			// Note: Calling v.CanSet() below is an optimization.
+			// It would be sufficient to check the field name,
+			// but creating the StructField info for each field is
+			// costly (run "go test -bench=ReadStruct" and compare
+			// results when making changes to this code).
+			if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
+				d.value(v)
+			} else {
+				d.skip(v)
+			}
+		}
+
+	case reflect.Slice:
+		l := v.Len()
+		for i := 0; i < l; i++ {
+			d.value(v.Index(i))
+		}
+
+	case reflect.Int8:
+		v.SetInt(int64(d.int8()))
+	case reflect.Int16:
+		v.SetInt(int64(d.int16()))
+	case reflect.Int32:
+		v.SetInt(int64(d.int32()))
+	case reflect.Int64:
+		v.SetInt(d.int64())
+
+	case reflect.Uint8:
+		v.SetUint(uint64(d.uint8()))
+	case reflect.Uint16:
+		v.SetUint(uint64(d.uint16()))
+	case reflect.Uint32:
+		v.SetUint(uint64(d.uint32()))
+	case reflect.Uint64:
+		v.SetUint(d.uint64())
+
+	case reflect.Float32:
+		v.SetFloat(float64(math.Float32frombits(d.uint32())))
+	case reflect.Float64:
+		v.SetFloat(math.Float64frombits(d.uint64()))
+
+	case reflect.Complex64:
+		v.SetComplex(complex(
+			float64(math.Float32frombits(d.uint32())),
+			float64(math.Float32frombits(d.uint32())),
+		))
+	case reflect.Complex128:
+		v.SetComplex(complex(
+			math.Float64frombits(d.uint64()),
+			math.Float64frombits(d.uint64()),
+		))
+	}
+}
+
+func (e *encoder) value(v reflect.Value) {
+	switch v.Kind() {
+	case reflect.Array:
+		l := v.Len()
+		for i := 0; i < l; i++ {
+			e.value(v.Index(i))
+		}
+
+	case reflect.Struct:
+		t := v.Type()
+		l := v.NumField()
+		for i := 0; i < l; i++ {
+			// see comment for corresponding code in decoder.value()
+			if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
+				e.value(v)
+			} else {
+				e.skip(v)
+			}
+		}
+
+	case reflect.Slice:
+		l := v.Len()
+		for i := 0; i < l; i++ {
+			e.value(v.Index(i))
+		}
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		switch v.Type().Kind() {
+		case reflect.Int8:
+			e.int8(int8(v.Int()))
+		case reflect.Int16:
+			e.int16(int16(v.Int()))
+		case reflect.Int32:
+			e.int32(int32(v.Int()))
+		case reflect.Int64:
+			e.int64(v.Int())
+		}
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		switch v.Type().Kind() {
+		case reflect.Uint8:
+			e.uint8(uint8(v.Uint()))
+		case reflect.Uint16:
+			e.uint16(uint16(v.Uint()))
+		case reflect.Uint32:
+			e.uint32(uint32(v.Uint()))
+		case reflect.Uint64:
+			e.uint64(v.Uint())
+		}
+
+	case reflect.Float32, reflect.Float64:
+		switch v.Type().Kind() {
+		case reflect.Float32:
+			e.uint32(math.Float32bits(float32(v.Float())))
+		case reflect.Float64:
+			e.uint64(math.Float64bits(v.Float()))
+		}
+
+	case reflect.Complex64, reflect.Complex128:
+		switch v.Type().Kind() {
+		case reflect.Complex64:
+			x := v.Complex()
+			e.uint32(math.Float32bits(float32(real(x))))
+			e.uint32(math.Float32bits(float32(imag(x))))
+		case reflect.Complex128:
+			x := v.Complex()
+			e.uint64(math.Float64bits(real(x)))
+			e.uint64(math.Float64bits(imag(x)))
+		}
+	}
+}
+
+func (d *decoder) skip(v reflect.Value) {
+	n, _ := dataSize(v)
+	d.buf = d.buf[n:]
+}
+
+func (e *encoder) skip(v reflect.Value) {
+	n, _ := dataSize(v)
+	for i := range e.buf[0:n] {
+		e.buf[i] = 0
+	}
+	e.buf = e.buf[n:]
+}
+
+// intDataSize returns the size of the data required to represent the data when encoded.
+// It returns zero if the type cannot be implemented by the fast path in Read or Write.
+func intDataSize(data interface{}) int {
+	switch data := data.(type) {
+	case int8, *int8, *uint8:
+		return 1
+	case []int8:
+		return len(data)
+	case []uint8:
+		return len(data)
+	case int16, *int16, *uint16:
+		return 2
+	case []int16:
+		return 2 * len(data)
+	case []uint16:
+		return 2 * len(data)
+	case int32, *int32, *uint32:
+		return 4
+	case []int32:
+		return 4 * len(data)
+	case []uint32:
+		return 4 * len(data)
+	case int64, *int64, *uint64:
+		return 8
+	case []int64:
+		return 8 * len(data)
+	case []uint64:
+		return 8 * len(data)
+	}
+	return 0
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/binary/binary_test.go b/third_party/gofrontend/libgo/go/encoding/binary/binary_test.go
new file mode 100644
index 0000000..c80c903
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/binary/binary_test.go
@@ -0,0 +1,397 @@
+// 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 binary
+
+import (
+	"bytes"
+	"io"
+	"math"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+type Struct struct {
+	Int8       int8
+	Int16      int16
+	Int32      int32
+	Int64      int64
+	Uint8      uint8
+	Uint16     uint16
+	Uint32     uint32
+	Uint64     uint64
+	Float32    float32
+	Float64    float64
+	Complex64  complex64
+	Complex128 complex128
+	Array      [4]uint8
+}
+
+type T struct {
+	Int     int
+	Uint    uint
+	Uintptr uintptr
+	Array   [4]int
+}
+
+var s = Struct{
+	0x01,
+	0x0203,
+	0x04050607,
+	0x08090a0b0c0d0e0f,
+	0x10,
+	0x1112,
+	0x13141516,
+	0x1718191a1b1c1d1e,
+
+	math.Float32frombits(0x1f202122),
+	math.Float64frombits(0x232425262728292a),
+	complex(
+		math.Float32frombits(0x2b2c2d2e),
+		math.Float32frombits(0x2f303132),
+	),
+	complex(
+		math.Float64frombits(0x333435363738393a),
+		math.Float64frombits(0x3b3c3d3e3f404142),
+	),
+
+	[4]uint8{0x43, 0x44, 0x45, 0x46},
+}
+
+var big = []byte{
+	1,
+	2, 3,
+	4, 5, 6, 7,
+	8, 9, 10, 11, 12, 13, 14, 15,
+	16,
+	17, 18,
+	19, 20, 21, 22,
+	23, 24, 25, 26, 27, 28, 29, 30,
+
+	31, 32, 33, 34,
+	35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50,
+	51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+
+	67, 68, 69, 70,
+}
+
+var little = []byte{
+	1,
+	3, 2,
+	7, 6, 5, 4,
+	15, 14, 13, 12, 11, 10, 9, 8,
+	16,
+	18, 17,
+	22, 21, 20, 19,
+	30, 29, 28, 27, 26, 25, 24, 23,
+
+	34, 33, 32, 31,
+	42, 41, 40, 39, 38, 37, 36, 35,
+	46, 45, 44, 43, 50, 49, 48, 47,
+	58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59,
+
+	67, 68, 69, 70,
+}
+
+var src = []byte{1, 2, 3, 4, 5, 6, 7, 8}
+var res = []int32{0x01020304, 0x05060708}
+
+func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want interface{}) {
+	if err != nil {
+		t.Errorf("%v %v: %v", dir, order, err)
+		return
+	}
+	if !reflect.DeepEqual(have, want) {
+		t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want)
+	}
+}
+
+func testRead(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
+	var s2 Struct
+	err := Read(bytes.NewReader(b), order, &s2)
+	checkResult(t, "Read", order, err, s2, s1)
+}
+
+func testWrite(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
+	buf := new(bytes.Buffer)
+	err := Write(buf, order, s1)
+	checkResult(t, "Write", order, err, buf.Bytes(), b)
+}
+
+func TestLittleEndianRead(t *testing.T)     { testRead(t, LittleEndian, little, s) }
+func TestLittleEndianWrite(t *testing.T)    { testWrite(t, LittleEndian, little, s) }
+func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
+
+func TestBigEndianRead(t *testing.T)     { testRead(t, BigEndian, big, s) }
+func TestBigEndianWrite(t *testing.T)    { testWrite(t, BigEndian, big, s) }
+func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) }
+
+func TestReadSlice(t *testing.T) {
+	slice := make([]int32, 2)
+	err := Read(bytes.NewReader(src), BigEndian, slice)
+	checkResult(t, "ReadSlice", BigEndian, err, slice, res)
+}
+
+func TestWriteSlice(t *testing.T) {
+	buf := new(bytes.Buffer)
+	err := Write(buf, BigEndian, res)
+	checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src)
+}
+
+// Addresses of arrays are easier to manipulate with reflection than are slices.
+var intArrays = []interface{}{
+	&[100]int8{},
+	&[100]int16{},
+	&[100]int32{},
+	&[100]int64{},
+	&[100]uint8{},
+	&[100]uint16{},
+	&[100]uint32{},
+	&[100]uint64{},
+}
+
+func TestSliceRoundTrip(t *testing.T) {
+	buf := new(bytes.Buffer)
+	for _, array := range intArrays {
+		src := reflect.ValueOf(array).Elem()
+		unsigned := false
+		switch src.Index(0).Kind() {
+		case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+			unsigned = true
+		}
+		for i := 0; i < src.Len(); i++ {
+			if unsigned {
+				src.Index(i).SetUint(uint64(i * 0x07654321))
+			} else {
+				src.Index(i).SetInt(int64(i * 0x07654321))
+			}
+		}
+		buf.Reset()
+		srcSlice := src.Slice(0, src.Len())
+		err := Write(buf, BigEndian, srcSlice.Interface())
+		if err != nil {
+			t.Fatal(err)
+		}
+		dst := reflect.New(src.Type()).Elem()
+		dstSlice := dst.Slice(0, dst.Len())
+		err = Read(buf, BigEndian, dstSlice.Interface())
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !reflect.DeepEqual(src.Interface(), dst.Interface()) {
+			t.Fatal(src)
+		}
+	}
+}
+
+func TestWriteT(t *testing.T) {
+	buf := new(bytes.Buffer)
+	ts := T{}
+	if err := Write(buf, BigEndian, ts); err == nil {
+		t.Errorf("WriteT: have err == nil, want non-nil")
+	}
+
+	tv := reflect.Indirect(reflect.ValueOf(ts))
+	for i, n := 0, tv.NumField(); i < n; i++ {
+		typ := tv.Field(i).Type().String()
+		if typ == "[4]int" {
+			typ = "int" // the problem is int, not the [4]
+		}
+		if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil {
+			t.Errorf("WriteT.%v: have err == nil, want non-nil", tv.Field(i).Type())
+		} else if !strings.Contains(err.Error(), typ) {
+			t.Errorf("WriteT: have err == %q, want it to mention %s", err, typ)
+		}
+	}
+}
+
+type BlankFields struct {
+	A uint32
+	_ int32
+	B float64
+	_ [4]int16
+	C byte
+	_ [7]byte
+	_ struct {
+		f [8]float32
+	}
+}
+
+type BlankFieldsProbe struct {
+	A  uint32
+	P0 int32
+	B  float64
+	P1 [4]int16
+	C  byte
+	P2 [7]byte
+	P3 struct {
+		F [8]float32
+	}
+}
+
+func TestBlankFields(t *testing.T) {
+	buf := new(bytes.Buffer)
+	b1 := BlankFields{A: 1234567890, B: 2.718281828, C: 42}
+	if err := Write(buf, LittleEndian, &b1); err != nil {
+		t.Error(err)
+	}
+
+	// zero values must have been written for blank fields
+	var p BlankFieldsProbe
+	if err := Read(buf, LittleEndian, &p); err != nil {
+		t.Error(err)
+	}
+
+	// quick test: only check first value of slices
+	if p.P0 != 0 || p.P1[0] != 0 || p.P2[0] != 0 || p.P3.F[0] != 0 {
+		t.Errorf("non-zero values for originally blank fields: %#v", p)
+	}
+
+	// write p and see if we can probe only some fields
+	if err := Write(buf, LittleEndian, &p); err != nil {
+		t.Error(err)
+	}
+
+	// read should ignore blank fields in b2
+	var b2 BlankFields
+	if err := Read(buf, LittleEndian, &b2); err != nil {
+		t.Error(err)
+	}
+	if b1.A != b2.A || b1.B != b2.B || b1.C != b2.C {
+		t.Errorf("%#v != %#v", b1, b2)
+	}
+}
+
+// An attempt to read into a struct with an unexported field will
+// panic.  This is probably not the best choice, but at this point
+// anything else would be an API change.
+
+type Unexported struct {
+	a int32
+}
+
+func TestUnexportedRead(t *testing.T) {
+	var buf bytes.Buffer
+	u1 := Unexported{a: 1}
+	if err := Write(&buf, LittleEndian, &u1); err != nil {
+		t.Fatal(err)
+	}
+
+	defer func() {
+		if recover() == nil {
+			t.Fatal("did not panic")
+		}
+	}()
+	var u2 Unexported
+	Read(&buf, LittleEndian, &u2)
+}
+
+type byteSliceReader struct {
+	remain []byte
+}
+
+func (br *byteSliceReader) Read(p []byte) (int, error) {
+	n := copy(p, br.remain)
+	br.remain = br.remain[n:]
+	return n, nil
+}
+
+func BenchmarkReadSlice1000Int32s(b *testing.B) {
+	bsr := &byteSliceReader{}
+	slice := make([]int32, 1000)
+	buf := make([]byte, len(slice)*4)
+	b.SetBytes(int64(len(buf)))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bsr.remain = buf
+		Read(bsr, BigEndian, slice)
+	}
+}
+
+func BenchmarkReadStruct(b *testing.B) {
+	bsr := &byteSliceReader{}
+	var buf bytes.Buffer
+	Write(&buf, BigEndian, &s)
+	n, _ := dataSize(reflect.ValueOf(s))
+	b.SetBytes(int64(n))
+	t := s
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bsr.remain = buf.Bytes()
+		Read(bsr, BigEndian, &t)
+	}
+	b.StopTimer()
+	if !reflect.DeepEqual(s, t) {
+		b.Fatal("no match")
+	}
+}
+
+func BenchmarkReadInts(b *testing.B) {
+	var ls Struct
+	bsr := &byteSliceReader{}
+	var r io.Reader = bsr
+	b.SetBytes(2 * (1 + 2 + 4 + 8))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bsr.remain = big
+		Read(r, BigEndian, &ls.Int8)
+		Read(r, BigEndian, &ls.Int16)
+		Read(r, BigEndian, &ls.Int32)
+		Read(r, BigEndian, &ls.Int64)
+		Read(r, BigEndian, &ls.Uint8)
+		Read(r, BigEndian, &ls.Uint16)
+		Read(r, BigEndian, &ls.Uint32)
+		Read(r, BigEndian, &ls.Uint64)
+	}
+
+	want := s
+	want.Float32 = 0
+	want.Float64 = 0
+	want.Complex64 = 0
+	want.Complex128 = 0
+	for i := range want.Array {
+		want.Array[i] = 0
+	}
+	b.StopTimer()
+	if !reflect.DeepEqual(ls, want) {
+		panic("no match")
+	}
+}
+
+func BenchmarkWriteInts(b *testing.B) {
+	buf := new(bytes.Buffer)
+	var w io.Writer = buf
+	b.SetBytes(2 * (1 + 2 + 4 + 8))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		buf.Reset()
+		Write(w, BigEndian, s.Int8)
+		Write(w, BigEndian, s.Int16)
+		Write(w, BigEndian, s.Int32)
+		Write(w, BigEndian, s.Int64)
+		Write(w, BigEndian, s.Uint8)
+		Write(w, BigEndian, s.Uint16)
+		Write(w, BigEndian, s.Uint32)
+		Write(w, BigEndian, s.Uint64)
+	}
+	b.StopTimer()
+	if !bytes.Equal(buf.Bytes(), big[:30]) {
+		b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30])
+	}
+}
+
+func BenchmarkWriteSlice1000Int32s(b *testing.B) {
+	slice := make([]int32, 1000)
+	buf := new(bytes.Buffer)
+	var w io.Writer = buf
+	b.SetBytes(4 * 1000)
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		buf.Reset()
+		Write(w, BigEndian, slice)
+	}
+	b.StopTimer()
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/binary/varint.go b/third_party/gofrontend/libgo/go/encoding/binary/varint.go
new file mode 100644
index 0000000..3a2dfa3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/binary/varint.go
@@ -0,0 +1,133 @@
+// 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.
+
+package binary
+
+// This file implements "varint" encoding of 64-bit integers.
+// The encoding is:
+// - unsigned integers are serialized 7 bits at a time, starting with the
+//   least significant bits
+// - the most significant bit (msb) in each output byte indicates if there
+//   is a continuation byte (msb = 1)
+// - signed integers are mapped to unsigned integers using "zig-zag"
+//   encoding: Positive values x are written as 2*x + 0, negative values
+//   are written as 2*(^x) + 1; that is, negative numbers are complemented
+//   and whether to complement is encoded in bit 0.
+//
+// Design note:
+// At most 10 bytes are needed for 64-bit values. The encoding could
+// be more dense: a full 64-bit value needs an extra byte just to hold bit 63.
+// Instead, the msb of the previous byte could be used to hold bit 63 since we
+// know there can't be more than 64 bits. This is a trivial improvement and
+// would reduce the maximum encoding length to 9 bytes. However, it breaks the
+// invariant that the msb is always the "continuation bit" and thus makes the
+// format incompatible with a varint encoding for larger numbers (say 128-bit).
+
+import (
+	"errors"
+	"io"
+)
+
+// MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.
+const (
+	MaxVarintLen16 = 3
+	MaxVarintLen32 = 5
+	MaxVarintLen64 = 10
+)
+
+// PutUvarint encodes a uint64 into buf and returns the number of bytes written.
+// If the buffer is too small, PutUvarint will panic.
+func PutUvarint(buf []byte, x uint64) int {
+	i := 0
+	for x >= 0x80 {
+		buf[i] = byte(x) | 0x80
+		x >>= 7
+		i++
+	}
+	buf[i] = byte(x)
+	return i + 1
+}
+
+// Uvarint decodes a uint64 from buf and returns that value and the
+// number of bytes read (> 0). If an error occurred, the value is 0
+// and the number of bytes n is <= 0 meaning:
+//
+//	n == 0: buf too small
+//	n  < 0: value larger than 64 bits (overflow)
+//              and -n is the number of bytes read
+//
+func Uvarint(buf []byte) (uint64, int) {
+	var x uint64
+	var s uint
+	for i, b := range buf {
+		if b < 0x80 {
+			if i > 9 || i == 9 && b > 1 {
+				return 0, -(i + 1) // overflow
+			}
+			return x | uint64(b)<<s, i + 1
+		}
+		x |= uint64(b&0x7f) << s
+		s += 7
+	}
+	return 0, 0
+}
+
+// PutVarint encodes an int64 into buf and returns the number of bytes written.
+// If the buffer is too small, PutVarint will panic.
+func PutVarint(buf []byte, x int64) int {
+	ux := uint64(x) << 1
+	if x < 0 {
+		ux = ^ux
+	}
+	return PutUvarint(buf, ux)
+}
+
+// Varint decodes an int64 from buf and returns that value and the
+// number of bytes read (> 0). If an error occurred, the value is 0
+// and the number of bytes n is <= 0 with the following meaning:
+//
+//	n == 0: buf too small
+//	n  < 0: value larger than 64 bits (overflow)
+//              and -n is the number of bytes read
+//
+func Varint(buf []byte) (int64, int) {
+	ux, n := Uvarint(buf) // ok to continue in presence of error
+	x := int64(ux >> 1)
+	if ux&1 != 0 {
+		x = ^x
+	}
+	return x, n
+}
+
+var overflow = errors.New("binary: varint overflows a 64-bit integer")
+
+// ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.
+func ReadUvarint(r io.ByteReader) (uint64, error) {
+	var x uint64
+	var s uint
+	for i := 0; ; i++ {
+		b, err := r.ReadByte()
+		if err != nil {
+			return x, err
+		}
+		if b < 0x80 {
+			if i > 9 || i == 9 && b > 1 {
+				return x, overflow
+			}
+			return x | uint64(b)<<s, nil
+		}
+		x |= uint64(b&0x7f) << s
+		s += 7
+	}
+}
+
+// ReadVarint reads an encoded signed integer from r and returns it as an int64.
+func ReadVarint(r io.ByteReader) (int64, error) {
+	ux, err := ReadUvarint(r) // ok to continue in presence of error
+	x := int64(ux >> 1)
+	if ux&1 != 0 {
+		x = ^x
+	}
+	return x, err
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/binary/varint_test.go b/third_party/gofrontend/libgo/go/encoding/binary/varint_test.go
new file mode 100644
index 0000000..ca411ec
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/binary/varint_test.go
@@ -0,0 +1,168 @@
+// 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.
+
+package binary
+
+import (
+	"bytes"
+	"io"
+	"testing"
+)
+
+func testConstant(t *testing.T, w uint, max int) {
+	buf := make([]byte, MaxVarintLen64)
+	n := PutUvarint(buf, 1<<w-1)
+	if n != max {
+		t.Errorf("MaxVarintLen%d = %d; want %d", w, max, n)
+	}
+}
+
+func TestConstants(t *testing.T) {
+	testConstant(t, 16, MaxVarintLen16)
+	testConstant(t, 32, MaxVarintLen32)
+	testConstant(t, 64, MaxVarintLen64)
+}
+
+func testVarint(t *testing.T, x int64) {
+	buf := make([]byte, MaxVarintLen64)
+	n := PutVarint(buf, x)
+	y, m := Varint(buf[0:n])
+	if x != y {
+		t.Errorf("Varint(%d): got %d", x, y)
+	}
+	if n != m {
+		t.Errorf("Varint(%d): got n = %d; want %d", x, m, n)
+	}
+
+	y, err := ReadVarint(bytes.NewReader(buf))
+	if err != nil {
+		t.Errorf("ReadVarint(%d): %s", x, err)
+	}
+	if x != y {
+		t.Errorf("ReadVarint(%d): got %d", x, y)
+	}
+}
+
+func testUvarint(t *testing.T, x uint64) {
+	buf := make([]byte, MaxVarintLen64)
+	n := PutUvarint(buf, x)
+	y, m := Uvarint(buf[0:n])
+	if x != y {
+		t.Errorf("Uvarint(%d): got %d", x, y)
+	}
+	if n != m {
+		t.Errorf("Uvarint(%d): got n = %d; want %d", x, m, n)
+	}
+
+	y, err := ReadUvarint(bytes.NewReader(buf))
+	if err != nil {
+		t.Errorf("ReadUvarint(%d): %s", x, err)
+	}
+	if x != y {
+		t.Errorf("ReadUvarint(%d): got %d", x, y)
+	}
+}
+
+var tests = []int64{
+	-1 << 63,
+	-1<<63 + 1,
+	-1,
+	0,
+	1,
+	2,
+	10,
+	20,
+	63,
+	64,
+	65,
+	127,
+	128,
+	129,
+	255,
+	256,
+	257,
+	1<<63 - 1,
+}
+
+func TestVarint(t *testing.T) {
+	for _, x := range tests {
+		testVarint(t, x)
+		testVarint(t, -x)
+	}
+	for x := int64(0x7); x != 0; x <<= 1 {
+		testVarint(t, x)
+		testVarint(t, -x)
+	}
+}
+
+func TestUvarint(t *testing.T) {
+	for _, x := range tests {
+		testUvarint(t, uint64(x))
+	}
+	for x := uint64(0x7); x != 0; x <<= 1 {
+		testUvarint(t, x)
+	}
+}
+
+func TestBufferTooSmall(t *testing.T) {
+	buf := []byte{0x80, 0x80, 0x80, 0x80}
+	for i := 0; i <= len(buf); i++ {
+		buf := buf[0:i]
+		x, n := Uvarint(buf)
+		if x != 0 || n != 0 {
+			t.Errorf("Uvarint(%v): got x = %d, n = %d", buf, x, n)
+		}
+
+		x, err := ReadUvarint(bytes.NewReader(buf))
+		if x != 0 || err != io.EOF {
+			t.Errorf("ReadUvarint(%v): got x = %d, err = %s", buf, x, err)
+		}
+	}
+}
+
+func testOverflow(t *testing.T, buf []byte, n0 int, err0 error) {
+	x, n := Uvarint(buf)
+	if x != 0 || n != n0 {
+		t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, %d", buf, x, n, n0)
+	}
+
+	x, err := ReadUvarint(bytes.NewReader(buf))
+	if x != 0 || err != err0 {
+		t.Errorf("ReadUvarint(%v): got x = %d, err = %s; want 0, %s", buf, x, err, err0)
+	}
+}
+
+func TestOverflow(t *testing.T) {
+	testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, -10, overflow)
+	testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, -13, overflow)
+}
+
+func TestNonCanonicalZero(t *testing.T) {
+	buf := []byte{0x80, 0x80, 0x80, 0}
+	x, n := Uvarint(buf)
+	if x != 0 || n != 4 {
+		t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, 4", buf, x, n)
+
+	}
+}
+
+func BenchmarkPutUvarint32(b *testing.B) {
+	buf := make([]byte, MaxVarintLen32)
+	b.SetBytes(4)
+	for i := 0; i < b.N; i++ {
+		for j := uint(0); j < MaxVarintLen32; j++ {
+			PutUvarint(buf, 1<<(j*7))
+		}
+	}
+}
+
+func BenchmarkPutUvarint64(b *testing.B) {
+	buf := make([]byte, MaxVarintLen64)
+	b.SetBytes(8)
+	for i := 0; i < b.N; i++ {
+		for j := uint(0); j < MaxVarintLen64; j++ {
+			PutUvarint(buf, 1<<(j*7))
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/csv/reader.go b/third_party/gofrontend/libgo/go/encoding/csv/reader.go
new file mode 100644
index 0000000..d943295
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/csv/reader.go
@@ -0,0 +1,337 @@
+// 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.
+
+// Package csv reads and writes comma-separated values (CSV) files.
+//
+// A csv file contains zero or more records of one or more fields per record.
+// Each record is separated by the newline character. The final record may
+// optionally be followed by a newline character.
+//
+//	field1,field2,field3
+//
+// White space is considered part of a field.
+//
+// Carriage returns before newline characters are silently removed.
+//
+// Blank lines are ignored.  A line with only whitespace characters (excluding
+// the ending newline character) is not considered a blank line.
+//
+// Fields which start and stop with the quote character " are called
+// quoted-fields.  The beginning and ending quote are not part of the
+// field.
+//
+// The source:
+//
+//	normal string,"quoted-field"
+//
+// results in the fields
+//
+//	{`normal string`, `quoted-field`}
+//
+// Within a quoted-field a quote character followed by a second quote
+// character is considered a single quote.
+//
+//	"the ""word"" is true","a ""quoted-field"""
+//
+// results in
+//
+//	{`the "word" is true`, `a "quoted-field"`}
+//
+// Newlines and commas may be included in a quoted-field
+//
+//	"Multi-line
+//	field","comma is ,"
+//
+// results in
+//
+//	{`Multi-line
+//	field`, `comma is ,`}
+package csv
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"unicode"
+)
+
+// A ParseError is returned for parsing errors.
+// The first line is 1.  The first column is 0.
+type ParseError struct {
+	Line   int   // Line where the error occurred
+	Column int   // Column (rune index) where the error occurred
+	Err    error // The actual error
+}
+
+func (e *ParseError) Error() string {
+	return fmt.Sprintf("line %d, column %d: %s", e.Line, e.Column, e.Err)
+}
+
+// These are the errors that can be returned in ParseError.Error
+var (
+	ErrTrailingComma = errors.New("extra delimiter at end of line") // no longer used
+	ErrBareQuote     = errors.New("bare \" in non-quoted-field")
+	ErrQuote         = errors.New("extraneous \" in field")
+	ErrFieldCount    = errors.New("wrong number of fields in line")
+)
+
+// A Reader reads records from a CSV-encoded file.
+//
+// As returned by NewReader, a Reader expects input conforming to RFC 4180.
+// The exported fields can be changed to customize the details before the
+// first call to Read or ReadAll.
+//
+// Comma is the field delimiter.  It defaults to ','.
+//
+// Comment, if not 0, is the comment character. Lines beginning with the
+// Comment character are ignored.
+//
+// If FieldsPerRecord is positive, Read requires each record to
+// have the given number of fields.  If FieldsPerRecord is 0, Read sets it to
+// the number of fields in the first record, so that future records must
+// have the same field count.  If FieldsPerRecord is negative, no check is
+// made and records may have a variable number of fields.
+//
+// If LazyQuotes is true, a quote may appear in an unquoted field and a
+// non-doubled quote may appear in a quoted field.
+//
+// If TrimLeadingSpace is true, leading white space in a field is ignored.
+type Reader struct {
+	Comma            rune // field delimiter (set to ',' by NewReader)
+	Comment          rune // comment character for start of line
+	FieldsPerRecord  int  // number of expected fields per record
+	LazyQuotes       bool // allow lazy quotes
+	TrailingComma    bool // ignored; here for backwards compatibility
+	TrimLeadingSpace bool // trim leading space
+	line             int
+	column           int
+	r                *bufio.Reader
+	field            bytes.Buffer
+}
+
+// NewReader returns a new Reader that reads from r.
+func NewReader(r io.Reader) *Reader {
+	return &Reader{
+		Comma: ',',
+		r:     bufio.NewReader(r),
+	}
+}
+
+// error creates a new ParseError based on err.
+func (r *Reader) error(err error) error {
+	return &ParseError{
+		Line:   r.line,
+		Column: r.column,
+		Err:    err,
+	}
+}
+
+// Read reads one record from r.  The record is a slice of strings with each
+// string representing one field.
+func (r *Reader) Read() (record []string, err error) {
+	for {
+		record, err = r.parseRecord()
+		if record != nil {
+			break
+		}
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	if r.FieldsPerRecord > 0 {
+		if len(record) != r.FieldsPerRecord {
+			r.column = 0 // report at start of record
+			return record, r.error(ErrFieldCount)
+		}
+	} else if r.FieldsPerRecord == 0 {
+		r.FieldsPerRecord = len(record)
+	}
+	return record, nil
+}
+
+// ReadAll reads all the remaining records from r.
+// Each record is a slice of fields.
+// A successful call returns err == nil, not err == EOF. Because ReadAll is
+// defined to read until EOF, it does not treat end of file as an error to be
+// reported.
+func (r *Reader) ReadAll() (records [][]string, err error) {
+	for {
+		record, err := r.Read()
+		if err == io.EOF {
+			return records, nil
+		}
+		if err != nil {
+			return nil, err
+		}
+		records = append(records, record)
+	}
+}
+
+// readRune reads one rune from r, folding \r\n to \n and keeping track
+// of how far into the line we have read.  r.column will point to the start
+// of this rune, not the end of this rune.
+func (r *Reader) readRune() (rune, error) {
+	r1, _, err := r.r.ReadRune()
+
+	// Handle \r\n here.  We make the simplifying assumption that
+	// anytime \r is followed by \n that it can be folded to \n.
+	// We will not detect files which contain both \r\n and bare \n.
+	if r1 == '\r' {
+		r1, _, err = r.r.ReadRune()
+		if err == nil {
+			if r1 != '\n' {
+				r.r.UnreadRune()
+				r1 = '\r'
+			}
+		}
+	}
+	r.column++
+	return r1, err
+}
+
+// skip reads runes up to and including the rune delim or until error.
+func (r *Reader) skip(delim rune) error {
+	for {
+		r1, err := r.readRune()
+		if err != nil {
+			return err
+		}
+		if r1 == delim {
+			return nil
+		}
+	}
+}
+
+// parseRecord reads and parses a single csv record from r.
+func (r *Reader) parseRecord() (fields []string, err error) {
+	// Each record starts on a new line.  We increment our line
+	// number (lines start at 1, not 0) and set column to -1
+	// so as we increment in readRune it points to the character we read.
+	r.line++
+	r.column = -1
+
+	// Peek at the first rune.  If it is an error we are done.
+	// If we are support comments and it is the comment character
+	// then skip to the end of line.
+
+	r1, _, err := r.r.ReadRune()
+	if err != nil {
+		return nil, err
+	}
+
+	if r.Comment != 0 && r1 == r.Comment {
+		return nil, r.skip('\n')
+	}
+	r.r.UnreadRune()
+
+	// At this point we have at least one field.
+	for {
+		haveField, delim, err := r.parseField()
+		if haveField {
+			fields = append(fields, r.field.String())
+		}
+		if delim == '\n' || err == io.EOF {
+			return fields, err
+		} else if err != nil {
+			return nil, err
+		}
+	}
+}
+
+// parseField parses the next field in the record.  The read field is
+// located in r.field.  Delim is the first character not part of the field
+// (r.Comma or '\n').
+func (r *Reader) parseField() (haveField bool, delim rune, err error) {
+	r.field.Reset()
+
+	r1, err := r.readRune()
+	for err == nil && r.TrimLeadingSpace && r1 != '\n' && unicode.IsSpace(r1) {
+		r1, err = r.readRune()
+	}
+
+	if err == io.EOF && r.column != 0 {
+		return true, 0, err
+	}
+	if err != nil {
+		return false, 0, err
+	}
+
+	switch r1 {
+	case r.Comma:
+		// will check below
+
+	case '\n':
+		// We are a trailing empty field or a blank line
+		if r.column == 0 {
+			return false, r1, nil
+		}
+		return true, r1, nil
+
+	case '"':
+		// quoted field
+	Quoted:
+		for {
+			r1, err = r.readRune()
+			if err != nil {
+				if err == io.EOF {
+					if r.LazyQuotes {
+						return true, 0, err
+					}
+					return false, 0, r.error(ErrQuote)
+				}
+				return false, 0, err
+			}
+			switch r1 {
+			case '"':
+				r1, err = r.readRune()
+				if err != nil || r1 == r.Comma {
+					break Quoted
+				}
+				if r1 == '\n' {
+					return true, r1, nil
+				}
+				if r1 != '"' {
+					if !r.LazyQuotes {
+						r.column--
+						return false, 0, r.error(ErrQuote)
+					}
+					// accept the bare quote
+					r.field.WriteRune('"')
+				}
+			case '\n':
+				r.line++
+				r.column = -1
+			}
+			r.field.WriteRune(r1)
+		}
+
+	default:
+		// unquoted field
+		for {
+			r.field.WriteRune(r1)
+			r1, err = r.readRune()
+			if err != nil || r1 == r.Comma {
+				break
+			}
+			if r1 == '\n' {
+				return true, r1, nil
+			}
+			if !r.LazyQuotes && r1 == '"' {
+				return false, 0, r.error(ErrBareQuote)
+			}
+		}
+	}
+
+	if err != nil {
+		if err == io.EOF {
+			return true, 0, err
+		}
+		return false, 0, err
+	}
+
+	return true, r1, nil
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/csv/reader_test.go b/third_party/gofrontend/libgo/go/encoding/csv/reader_test.go
new file mode 100644
index 0000000..123df06
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/csv/reader_test.go
@@ -0,0 +1,284 @@
+// 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.
+
+package csv
+
+import (
+	"reflect"
+	"strings"
+	"testing"
+)
+
+var readTests = []struct {
+	Name               string
+	Input              string
+	Output             [][]string
+	UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1
+
+	// These fields are copied into the Reader
+	Comma            rune
+	Comment          rune
+	FieldsPerRecord  int
+	LazyQuotes       bool
+	TrailingComma    bool
+	TrimLeadingSpace bool
+
+	Error  string
+	Line   int // Expected error line if != 0
+	Column int // Expected error column if line != 0
+}{
+	{
+		Name:   "Simple",
+		Input:  "a,b,c\n",
+		Output: [][]string{{"a", "b", "c"}},
+	},
+	{
+		Name:   "CRLF",
+		Input:  "a,b\r\nc,d\r\n",
+		Output: [][]string{{"a", "b"}, {"c", "d"}},
+	},
+	{
+		Name:   "BareCR",
+		Input:  "a,b\rc,d\r\n",
+		Output: [][]string{{"a", "b\rc", "d"}},
+	},
+	{
+		Name:               "RFC4180test",
+		UseFieldsPerRecord: true,
+		Input: `#field1,field2,field3
+"aaa","bb
+b","ccc"
+"a,a","b""bb","ccc"
+zzz,yyy,xxx
+`,
+		Output: [][]string{
+			{"#field1", "field2", "field3"},
+			{"aaa", "bb\nb", "ccc"},
+			{"a,a", `b"bb`, "ccc"},
+			{"zzz", "yyy", "xxx"},
+		},
+	},
+	{
+		Name:   "NoEOLTest",
+		Input:  "a,b,c",
+		Output: [][]string{{"a", "b", "c"}},
+	},
+	{
+		Name:   "Semicolon",
+		Comma:  ';',
+		Input:  "a;b;c\n",
+		Output: [][]string{{"a", "b", "c"}},
+	},
+	{
+		Name: "MultiLine",
+		Input: `"two
+line","one line","three
+line
+field"`,
+		Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}},
+	},
+	{
+		Name:  "BlankLine",
+		Input: "a,b,c\n\nd,e,f\n\n",
+		Output: [][]string{
+			{"a", "b", "c"},
+			{"d", "e", "f"},
+		},
+	},
+	{
+		Name:             "TrimSpace",
+		Input:            " a,  b,   c\n",
+		TrimLeadingSpace: true,
+		Output:           [][]string{{"a", "b", "c"}},
+	},
+	{
+		Name:   "LeadingSpace",
+		Input:  " a,  b,   c\n",
+		Output: [][]string{{" a", "  b", "   c"}},
+	},
+	{
+		Name:    "Comment",
+		Comment: '#',
+		Input:   "#1,2,3\na,b,c\n#comment",
+		Output:  [][]string{{"a", "b", "c"}},
+	},
+	{
+		Name:   "NoComment",
+		Input:  "#1,2,3\na,b,c",
+		Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}},
+	},
+	{
+		Name:       "LazyQuotes",
+		LazyQuotes: true,
+		Input:      `a "word","1"2",a","b`,
+		Output:     [][]string{{`a "word"`, `1"2`, `a"`, `b`}},
+	},
+	{
+		Name:       "BareQuotes",
+		LazyQuotes: true,
+		Input:      `a "word","1"2",a"`,
+		Output:     [][]string{{`a "word"`, `1"2`, `a"`}},
+	},
+	{
+		Name:       "BareDoubleQuotes",
+		LazyQuotes: true,
+		Input:      `a""b,c`,
+		Output:     [][]string{{`a""b`, `c`}},
+	},
+	{
+		Name:  "BadDoubleQuotes",
+		Input: `a""b,c`,
+		Error: `bare " in non-quoted-field`, Line: 1, Column: 1,
+	},
+	{
+		Name:             "TrimQuote",
+		Input:            ` "a"," b",c`,
+		TrimLeadingSpace: true,
+		Output:           [][]string{{"a", " b", "c"}},
+	},
+	{
+		Name:  "BadBareQuote",
+		Input: `a "word","b"`,
+		Error: `bare " in non-quoted-field`, Line: 1, Column: 2,
+	},
+	{
+		Name:  "BadTrailingQuote",
+		Input: `"a word",b"`,
+		Error: `bare " in non-quoted-field`, Line: 1, Column: 10,
+	},
+	{
+		Name:  "ExtraneousQuote",
+		Input: `"a "word","b"`,
+		Error: `extraneous " in field`, Line: 1, Column: 3,
+	},
+	{
+		Name:               "BadFieldCount",
+		UseFieldsPerRecord: true,
+		Input:              "a,b,c\nd,e",
+		Error:              "wrong number of fields", Line: 2,
+	},
+	{
+		Name:               "BadFieldCount1",
+		UseFieldsPerRecord: true,
+		FieldsPerRecord:    2,
+		Input:              `a,b,c`,
+		Error:              "wrong number of fields", Line: 1,
+	},
+	{
+		Name:   "FieldCount",
+		Input:  "a,b,c\nd,e",
+		Output: [][]string{{"a", "b", "c"}, {"d", "e"}},
+	},
+	{
+		Name:   "TrailingCommaEOF",
+		Input:  "a,b,c,",
+		Output: [][]string{{"a", "b", "c", ""}},
+	},
+	{
+		Name:   "TrailingCommaEOL",
+		Input:  "a,b,c,\n",
+		Output: [][]string{{"a", "b", "c", ""}},
+	},
+	{
+		Name:             "TrailingCommaSpaceEOF",
+		TrimLeadingSpace: true,
+		Input:            "a,b,c, ",
+		Output:           [][]string{{"a", "b", "c", ""}},
+	},
+	{
+		Name:             "TrailingCommaSpaceEOL",
+		TrimLeadingSpace: true,
+		Input:            "a,b,c, \n",
+		Output:           [][]string{{"a", "b", "c", ""}},
+	},
+	{
+		Name:             "TrailingCommaLine3",
+		TrimLeadingSpace: true,
+		Input:            "a,b,c\nd,e,f\ng,hi,",
+		Output:           [][]string{{"a", "b", "c"}, {"d", "e", "f"}, {"g", "hi", ""}},
+	},
+	{
+		Name:   "NotTrailingComma3",
+		Input:  "a,b,c, \n",
+		Output: [][]string{{"a", "b", "c", " "}},
+	},
+	{
+		Name:          "CommaFieldTest",
+		TrailingComma: true,
+		Input: `x,y,z,w
+x,y,z,
+x,y,,
+x,,,
+,,,
+"x","y","z","w"
+"x","y","z",""
+"x","y","",""
+"x","","",""
+"","","",""
+`,
+		Output: [][]string{
+			{"x", "y", "z", "w"},
+			{"x", "y", "z", ""},
+			{"x", "y", "", ""},
+			{"x", "", "", ""},
+			{"", "", "", ""},
+			{"x", "y", "z", "w"},
+			{"x", "y", "z", ""},
+			{"x", "y", "", ""},
+			{"x", "", "", ""},
+			{"", "", "", ""},
+		},
+	},
+	{
+		Name:             "TrailingCommaIneffective1",
+		TrailingComma:    true,
+		TrimLeadingSpace: true,
+		Input:            "a,b,\nc,d,e",
+		Output: [][]string{
+			{"a", "b", ""},
+			{"c", "d", "e"},
+		},
+	},
+	{
+		Name:             "TrailingCommaIneffective2",
+		TrailingComma:    false,
+		TrimLeadingSpace: true,
+		Input:            "a,b,\nc,d,e",
+		Output: [][]string{
+			{"a", "b", ""},
+			{"c", "d", "e"},
+		},
+	},
+}
+
+func TestRead(t *testing.T) {
+	for _, tt := range readTests {
+		r := NewReader(strings.NewReader(tt.Input))
+		r.Comment = tt.Comment
+		if tt.UseFieldsPerRecord {
+			r.FieldsPerRecord = tt.FieldsPerRecord
+		} else {
+			r.FieldsPerRecord = -1
+		}
+		r.LazyQuotes = tt.LazyQuotes
+		r.TrailingComma = tt.TrailingComma
+		r.TrimLeadingSpace = tt.TrimLeadingSpace
+		if tt.Comma != 0 {
+			r.Comma = tt.Comma
+		}
+		out, err := r.ReadAll()
+		perr, _ := err.(*ParseError)
+		if tt.Error != "" {
+			if err == nil || !strings.Contains(err.Error(), tt.Error) {
+				t.Errorf("%s: error %v, want error %q", tt.Name, err, tt.Error)
+			} else if tt.Line != 0 && (tt.Line != perr.Line || tt.Column != perr.Column) {
+				t.Errorf("%s: error at %d:%d expected %d:%d", tt.Name, perr.Line, perr.Column, tt.Line, tt.Column)
+			}
+		} else if err != nil {
+			t.Errorf("%s: unexpected error %v", tt.Name, err)
+		} else if !reflect.DeepEqual(out, tt.Output) {
+			t.Errorf("%s: out=%q want %q", tt.Name, out, tt.Output)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/csv/writer.go b/third_party/gofrontend/libgo/go/encoding/csv/writer.go
new file mode 100644
index 0000000..1faecb6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/csv/writer.go
@@ -0,0 +1,127 @@
+// 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.
+
+package csv
+
+import (
+	"bufio"
+	"io"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// A Writer writes records to a CSV encoded file.
+//
+// As returned by NewWriter, a Writer writes records terminated by a
+// newline and uses ',' as the field delimiter.  The exported fields can be
+// changed to customize the details before the first call to Write or WriteAll.
+//
+// Comma is the field delimiter.
+//
+// If UseCRLF is true, the Writer ends each record with \r\n instead of \n.
+type Writer struct {
+	Comma   rune // Field delimiter (set to ',' by NewWriter)
+	UseCRLF bool // True to use \r\n as the line terminator
+	w       *bufio.Writer
+}
+
+// NewWriter returns a new Writer that writes to w.
+func NewWriter(w io.Writer) *Writer {
+	return &Writer{
+		Comma: ',',
+		w:     bufio.NewWriter(w),
+	}
+}
+
+// Writer writes a single CSV record to w along with any necessary quoting.
+// A record is a slice of strings with each string being one field.
+func (w *Writer) Write(record []string) (err error) {
+	for n, field := range record {
+		if n > 0 {
+			if _, err = w.w.WriteRune(w.Comma); err != nil {
+				return
+			}
+		}
+
+		// If we don't have to have a quoted field then just
+		// write out the field and continue to the next field.
+		if !w.fieldNeedsQuotes(field) {
+			if _, err = w.w.WriteString(field); err != nil {
+				return
+			}
+			continue
+		}
+		if err = w.w.WriteByte('"'); err != nil {
+			return
+		}
+
+		for _, r1 := range field {
+			switch r1 {
+			case '"':
+				_, err = w.w.WriteString(`""`)
+			case '\r':
+				if !w.UseCRLF {
+					err = w.w.WriteByte('\r')
+				}
+			case '\n':
+				if w.UseCRLF {
+					_, err = w.w.WriteString("\r\n")
+				} else {
+					err = w.w.WriteByte('\n')
+				}
+			default:
+				_, err = w.w.WriteRune(r1)
+			}
+			if err != nil {
+				return
+			}
+		}
+
+		if err = w.w.WriteByte('"'); err != nil {
+			return
+		}
+	}
+	if w.UseCRLF {
+		_, err = w.w.WriteString("\r\n")
+	} else {
+		err = w.w.WriteByte('\n')
+	}
+	return
+}
+
+// Flush writes any buffered data to the underlying io.Writer.
+// To check if an error occurred during the Flush, call Error.
+func (w *Writer) Flush() {
+	w.w.Flush()
+}
+
+// Error reports any error that has occurred during a previous Write or Flush.
+func (w *Writer) Error() error {
+	_, err := w.w.Write(nil)
+	return err
+}
+
+// WriteAll writes multiple CSV records to w using Write and then calls Flush.
+func (w *Writer) WriteAll(records [][]string) (err error) {
+	for _, record := range records {
+		err = w.Write(record)
+		if err != nil {
+			return err
+		}
+	}
+	return w.w.Flush()
+}
+
+// fieldNeedsQuotes returns true if our field must be enclosed in quotes.
+// Empty fields, files with a Comma, fields with a quote or newline, and
+// fields which start with a space must be enclosed in quotes.
+func (w *Writer) fieldNeedsQuotes(field string) bool {
+	if len(field) == 0 || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
+		return true
+	}
+
+	r1, _ := utf8.DecodeRuneInString(field)
+	return unicode.IsSpace(r1)
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/csv/writer_test.go b/third_party/gofrontend/libgo/go/encoding/csv/writer_test.go
new file mode 100644
index 0000000..22b740c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/csv/writer_test.go
@@ -0,0 +1,74 @@
+// 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.
+
+package csv
+
+import (
+	"bytes"
+	"errors"
+	"testing"
+)
+
+var writeTests = []struct {
+	Input   [][]string
+	Output  string
+	UseCRLF bool
+}{
+	{Input: [][]string{{"abc"}}, Output: "abc\n"},
+	{Input: [][]string{{"abc"}}, Output: "abc\r\n", UseCRLF: true},
+	{Input: [][]string{{`"abc"`}}, Output: `"""abc"""` + "\n"},
+	{Input: [][]string{{`a"b`}}, Output: `"a""b"` + "\n"},
+	{Input: [][]string{{`"a"b"`}}, Output: `"""a""b"""` + "\n"},
+	{Input: [][]string{{" abc"}}, Output: `" abc"` + "\n"},
+	{Input: [][]string{{"abc,def"}}, Output: `"abc,def"` + "\n"},
+	{Input: [][]string{{"abc", "def"}}, Output: "abc,def\n"},
+	{Input: [][]string{{"abc"}, {"def"}}, Output: "abc\ndef\n"},
+	{Input: [][]string{{"abc\ndef"}}, Output: "\"abc\ndef\"\n"},
+	{Input: [][]string{{"abc\ndef"}}, Output: "\"abc\r\ndef\"\r\n", UseCRLF: true},
+	{Input: [][]string{{"abc\rdef"}}, Output: "\"abcdef\"\r\n", UseCRLF: true},
+	{Input: [][]string{{"abc\rdef"}}, Output: "\"abc\rdef\"\n", UseCRLF: false},
+}
+
+func TestWrite(t *testing.T) {
+	for n, tt := range writeTests {
+		b := &bytes.Buffer{}
+		f := NewWriter(b)
+		f.UseCRLF = tt.UseCRLF
+		err := f.WriteAll(tt.Input)
+		if err != nil {
+			t.Errorf("Unexpected error: %s\n", err)
+		}
+		out := b.String()
+		if out != tt.Output {
+			t.Errorf("#%d: out=%q want %q", n, out, tt.Output)
+		}
+	}
+}
+
+type errorWriter struct{}
+
+func (e errorWriter) Write(b []byte) (int, error) {
+	return 0, errors.New("Test")
+}
+
+func TestError(t *testing.T) {
+	b := &bytes.Buffer{}
+	f := NewWriter(b)
+	f.Write([]string{"abc"})
+	f.Flush()
+	err := f.Error()
+
+	if err != nil {
+		t.Errorf("Unexpected error: %s\n", err)
+	}
+
+	f = NewWriter(errorWriter{})
+	f.Write([]string{"abc"})
+	f.Flush()
+	err = f.Error()
+
+	if err == nil {
+		t.Error("Error should not be nil")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/encoding.go b/third_party/gofrontend/libgo/go/encoding/encoding.go
new file mode 100644
index 0000000..6d21807
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/encoding.go
@@ -0,0 +1,48 @@
+// Copyright 2013 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 encoding defines interfaces shared by other packages that
+// convert data to and from byte-level and textual representations.
+// Packages that check for these interfaces include encoding/gob,
+// encoding/json, and encoding/xml. As a result, implementing an
+// interface once can make a type useful in multiple encodings.
+// Standard types that implement these interfaces include time.Time and net.IP.
+// The interfaces come in pairs that produce and consume encoded data.
+package encoding
+
+// BinaryMarshaler is the interface implemented by an object that can
+// marshal itself into a binary form.
+//
+// MarshalBinary encodes the receiver into a binary form and returns the result.
+type BinaryMarshaler interface {
+	MarshalBinary() (data []byte, err error)
+}
+
+// BinaryUnmarshaler is the interface implemented by an object that can
+// unmarshal a binary representation of itself.
+//
+// UnmarshalBinary must be able to decode the form generated by MarshalBinary.
+// UnmarshalBinary must copy the data if it wishes to retain the data
+// after returning.
+type BinaryUnmarshaler interface {
+	UnmarshalBinary(data []byte) error
+}
+
+// TextMarshaler is the interface implemented by an object that can
+// marshal itself into a textual form.
+//
+// MarshalText encodes the receiver into UTF-8-encoded text and returns the result.
+type TextMarshaler interface {
+	MarshalText() (text []byte, err error)
+}
+
+// TextUnmarshaler is the interface implemented by an object that can
+// unmarshal a textual representation of itself.
+//
+// UnmarshalText must be able to decode the form generated by MarshalText.
+// UnmarshalText must copy the text if it wishes to retain the text
+// after returning.
+type TextUnmarshaler interface {
+	UnmarshalText(text []byte) error
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/codec_test.go b/third_party/gofrontend/libgo/go/encoding/gob/codec_test.go
new file mode 100644
index 0000000..fa57f37
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/codec_test.go
@@ -0,0 +1,1506 @@
+// 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 gob
+
+import (
+	"bytes"
+	"errors"
+	"flag"
+	"math"
+	"math/rand"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+	"unsafe"
+)
+
+var doFuzzTests = flag.Bool("gob.fuzz", false, "run the fuzz tests, which are large and very slow")
+
+// Guarantee encoding format by comparing some encodings to hand-written values
+type EncodeT struct {
+	x uint64
+	b []byte
+}
+
+var encodeT = []EncodeT{
+	{0x00, []byte{0x00}},
+	{0x0F, []byte{0x0F}},
+	{0xFF, []byte{0xFF, 0xFF}},
+	{0xFFFF, []byte{0xFE, 0xFF, 0xFF}},
+	{0xFFFFFF, []byte{0xFD, 0xFF, 0xFF, 0xFF}},
+	{0xFFFFFFFF, []byte{0xFC, 0xFF, 0xFF, 0xFF, 0xFF}},
+	{0xFFFFFFFFFF, []byte{0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
+	{0xFFFFFFFFFFFF, []byte{0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
+	{0xFFFFFFFFFFFFFF, []byte{0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
+	{0xFFFFFFFFFFFFFFFF, []byte{0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
+	{0x1111, []byte{0xFE, 0x11, 0x11}},
+	{0x1111111111111111, []byte{0xF8, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
+	{0x8888888888888888, []byte{0xF8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}},
+	{1 << 63, []byte{0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+}
+
+// testError is meant to be used as a deferred function to turn a panic(gobError) into a
+// plain test.Error call.
+func testError(t *testing.T) {
+	if e := recover(); e != nil {
+		t.Error(e.(gobError).err) // Will re-panic if not one of our errors, such as a runtime error.
+	}
+	return
+}
+
+// Test basic encode/decode routines for unsigned integers
+func TestUintCodec(t *testing.T) {
+	defer testError(t)
+	b := new(bytes.Buffer)
+	encState := newEncoderState(b)
+	for _, tt := range encodeT {
+		b.Reset()
+		encState.encodeUint(tt.x)
+		if !bytes.Equal(tt.b, b.Bytes()) {
+			t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes())
+		}
+	}
+	decState := newDecodeState(b)
+	for u := uint64(0); ; u = (u + 1) * 7 {
+		b.Reset()
+		encState.encodeUint(u)
+		v := decState.decodeUint()
+		if u != v {
+			t.Errorf("Encode/Decode: sent %#x received %#x", u, v)
+		}
+		if u&(1<<63) != 0 {
+			break
+		}
+	}
+}
+
+func verifyInt(i int64, t *testing.T) {
+	defer testError(t)
+	var b = new(bytes.Buffer)
+	encState := newEncoderState(b)
+	encState.encodeInt(i)
+	decState := newDecodeState(b)
+	decState.buf = make([]byte, 8)
+	j := decState.decodeInt()
+	if i != j {
+		t.Errorf("Encode/Decode: sent %#x received %#x", uint64(i), uint64(j))
+	}
+}
+
+// Test basic encode/decode routines for signed integers
+func TestIntCodec(t *testing.T) {
+	for u := uint64(0); ; u = (u + 1) * 7 {
+		// Do positive and negative values
+		i := int64(u)
+		verifyInt(i, t)
+		verifyInt(-i, t)
+		verifyInt(^i, t)
+		if u&(1<<63) != 0 {
+			break
+		}
+	}
+	verifyInt(-1<<63, t) // a tricky case
+}
+
+// The result of encoding a true boolean with field number 7
+var boolResult = []byte{0x07, 0x01}
+
+// The result of encoding a number 17 with field number 7
+var signedResult = []byte{0x07, 2 * 17}
+var unsignedResult = []byte{0x07, 17}
+var floatResult = []byte{0x07, 0xFE, 0x31, 0x40}
+
+// The result of encoding a number 17+19i with field number 7
+var complexResult = []byte{0x07, 0xFE, 0x31, 0x40, 0xFE, 0x33, 0x40}
+
+// The result of encoding "hello" with field number 7
+var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'}
+
+func newDecodeState(buf *bytes.Buffer) *decoderState {
+	d := new(decoderState)
+	d.b = buf
+	d.buf = make([]byte, uint64Size)
+	return d
+}
+
+func newEncoderState(b *bytes.Buffer) *encoderState {
+	b.Reset()
+	state := &encoderState{enc: nil, b: b}
+	state.fieldnum = -1
+	return state
+}
+
+// Test instruction execution for encoding.
+// Do not run the machine yet; instead do individual instructions crafted by hand.
+func TestScalarEncInstructions(t *testing.T) {
+	var b = new(bytes.Buffer)
+
+	// bool
+	{
+		data := struct{ a bool }{true}
+		instr := &encInstr{encBool, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(boolResult, b.Bytes()) {
+			t.Errorf("bool enc instructions: expected % x got % x", boolResult, b.Bytes())
+		}
+	}
+
+	// int
+	{
+		b.Reset()
+		data := struct{ a int }{17}
+		instr := &encInstr{encInt, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(signedResult, b.Bytes()) {
+			t.Errorf("int enc instructions: expected % x got % x", signedResult, b.Bytes())
+		}
+	}
+
+	// uint
+	{
+		b.Reset()
+		data := struct{ a uint }{17}
+		instr := &encInstr{encUint, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(unsignedResult, b.Bytes()) {
+			t.Errorf("uint enc instructions: expected % x got % x", unsignedResult, b.Bytes())
+		}
+	}
+
+	// int8
+	{
+		b.Reset()
+		data := struct{ a int8 }{17}
+		instr := &encInstr{encInt8, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(signedResult, b.Bytes()) {
+			t.Errorf("int8 enc instructions: expected % x got % x", signedResult, b.Bytes())
+		}
+	}
+
+	// uint8
+	{
+		b.Reset()
+		data := struct{ a uint8 }{17}
+		instr := &encInstr{encUint8, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(unsignedResult, b.Bytes()) {
+			t.Errorf("uint8 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
+		}
+	}
+
+	// int16
+	{
+		b.Reset()
+		data := struct{ a int16 }{17}
+		instr := &encInstr{encInt16, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(signedResult, b.Bytes()) {
+			t.Errorf("int16 enc instructions: expected % x got % x", signedResult, b.Bytes())
+		}
+	}
+
+	// uint16
+	{
+		b.Reset()
+		data := struct{ a uint16 }{17}
+		instr := &encInstr{encUint16, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(unsignedResult, b.Bytes()) {
+			t.Errorf("uint16 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
+		}
+	}
+
+	// int32
+	{
+		b.Reset()
+		data := struct{ a int32 }{17}
+		instr := &encInstr{encInt32, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(signedResult, b.Bytes()) {
+			t.Errorf("int32 enc instructions: expected % x got % x", signedResult, b.Bytes())
+		}
+	}
+
+	// uint32
+	{
+		b.Reset()
+		data := struct{ a uint32 }{17}
+		instr := &encInstr{encUint32, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(unsignedResult, b.Bytes()) {
+			t.Errorf("uint32 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
+		}
+	}
+
+	// int64
+	{
+		b.Reset()
+		data := struct{ a int64 }{17}
+		instr := &encInstr{encInt64, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(signedResult, b.Bytes()) {
+			t.Errorf("int64 enc instructions: expected % x got % x", signedResult, b.Bytes())
+		}
+	}
+
+	// uint64
+	{
+		b.Reset()
+		data := struct{ a uint64 }{17}
+		instr := &encInstr{encUint64, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(unsignedResult, b.Bytes()) {
+			t.Errorf("uint64 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
+		}
+	}
+
+	// float32
+	{
+		b.Reset()
+		data := struct{ a float32 }{17}
+		instr := &encInstr{encFloat32, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(floatResult, b.Bytes()) {
+			t.Errorf("float32 enc instructions: expected % x got % x", floatResult, b.Bytes())
+		}
+	}
+
+	// float64
+	{
+		b.Reset()
+		data := struct{ a float64 }{17}
+		instr := &encInstr{encFloat64, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(floatResult, b.Bytes()) {
+			t.Errorf("float64 enc instructions: expected % x got % x", floatResult, b.Bytes())
+		}
+	}
+
+	// bytes == []uint8
+	{
+		b.Reset()
+		data := struct{ a []byte }{[]byte("hello")}
+		instr := &encInstr{encUint8Array, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(bytesResult, b.Bytes()) {
+			t.Errorf("bytes enc instructions: expected % x got % x", bytesResult, b.Bytes())
+		}
+	}
+
+	// string
+	{
+		b.Reset()
+		data := struct{ a string }{"hello"}
+		instr := &encInstr{encString, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(bytesResult, b.Bytes()) {
+			t.Errorf("string enc instructions: expected % x got % x", bytesResult, b.Bytes())
+		}
+	}
+}
+
+func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, p unsafe.Pointer) {
+	defer testError(t)
+	v := int(state.decodeUint())
+	if v+state.fieldnum != 6 {
+		t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum)
+	}
+	instr.op(instr, state, decIndirect(p, instr.indir))
+	state.fieldnum = 6
+}
+
+func newDecodeStateFromData(data []byte) *decoderState {
+	b := bytes.NewBuffer(data)
+	state := newDecodeState(b)
+	state.fieldnum = -1
+	return state
+}
+
+// Test instruction execution for decoding.
+// Do not run the machine yet; instead do individual instructions crafted by hand.
+func TestScalarDecInstructions(t *testing.T) {
+	ovfl := errors.New("overflow")
+
+	// bool
+	{
+		var data struct {
+			a bool
+		}
+		instr := &decInstr{decBool, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(boolResult)
+		execDec("bool", instr, state, t, unsafe.Pointer(&data))
+		if data.a != true {
+			t.Errorf("bool a = %v not true", data.a)
+		}
+	}
+	// int
+	{
+		var data struct {
+			a int
+		}
+		instr := &decInstr{decOpTable[reflect.Int], 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(signedResult)
+		execDec("int", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("int a = %v not 17", data.a)
+		}
+	}
+
+	// uint
+	{
+		var data struct {
+			a uint
+		}
+		instr := &decInstr{decOpTable[reflect.Uint], 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uint", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uint a = %v not 17", data.a)
+		}
+	}
+
+	// int8
+	{
+		var data struct {
+			a int8
+		}
+		instr := &decInstr{decInt8, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(signedResult)
+		execDec("int8", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("int8 a = %v not 17", data.a)
+		}
+	}
+
+	// uint8
+	{
+		var data struct {
+			a uint8
+		}
+		instr := &decInstr{decUint8, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uint8", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uint8 a = %v not 17", data.a)
+		}
+	}
+
+	// int16
+	{
+		var data struct {
+			a int16
+		}
+		instr := &decInstr{decInt16, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(signedResult)
+		execDec("int16", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("int16 a = %v not 17", data.a)
+		}
+	}
+
+	// uint16
+	{
+		var data struct {
+			a uint16
+		}
+		instr := &decInstr{decUint16, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uint16", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uint16 a = %v not 17", data.a)
+		}
+	}
+
+	// int32
+	{
+		var data struct {
+			a int32
+		}
+		instr := &decInstr{decInt32, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(signedResult)
+		execDec("int32", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("int32 a = %v not 17", data.a)
+		}
+	}
+
+	// uint32
+	{
+		var data struct {
+			a uint32
+		}
+		instr := &decInstr{decUint32, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uint32", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uint32 a = %v not 17", data.a)
+		}
+	}
+
+	// uintptr
+	{
+		var data struct {
+			a uintptr
+		}
+		instr := &decInstr{decOpTable[reflect.Uintptr], 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uintptr", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uintptr a = %v not 17", data.a)
+		}
+	}
+
+	// int64
+	{
+		var data struct {
+			a int64
+		}
+		instr := &decInstr{decInt64, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(signedResult)
+		execDec("int64", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("int64 a = %v not 17", data.a)
+		}
+	}
+
+	// uint64
+	{
+		var data struct {
+			a uint64
+		}
+		instr := &decInstr{decUint64, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uint64", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uint64 a = %v not 17", data.a)
+		}
+	}
+
+	// float32
+	{
+		var data struct {
+			a float32
+		}
+		instr := &decInstr{decFloat32, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(floatResult)
+		execDec("float32", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("float32 a = %v not 17", data.a)
+		}
+	}
+
+	// float64
+	{
+		var data struct {
+			a float64
+		}
+		instr := &decInstr{decFloat64, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(floatResult)
+		execDec("float64", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("float64 a = %v not 17", data.a)
+		}
+	}
+
+	// complex64
+	{
+		var data struct {
+			a complex64
+		}
+		instr := &decInstr{decOpTable[reflect.Complex64], 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(complexResult)
+		execDec("complex", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17+19i {
+			t.Errorf("complex a = %v not 17+19i", data.a)
+		}
+	}
+
+	// complex128
+	{
+		var data struct {
+			a complex128
+		}
+		instr := &decInstr{decOpTable[reflect.Complex128], 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(complexResult)
+		execDec("complex", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17+19i {
+			t.Errorf("complex a = %v not 17+19i", data.a)
+		}
+	}
+
+	// bytes == []uint8
+	{
+		var data struct {
+			a []byte
+		}
+		instr := &decInstr{decUint8Slice, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(bytesResult)
+		execDec("bytes", instr, state, t, unsafe.Pointer(&data))
+		if string(data.a) != "hello" {
+			t.Errorf(`bytes a = %q not "hello"`, string(data.a))
+		}
+	}
+
+	// string
+	{
+		var data struct {
+			a string
+		}
+		instr := &decInstr{decString, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(bytesResult)
+		execDec("bytes", instr, state, t, unsafe.Pointer(&data))
+		if data.a != "hello" {
+			t.Errorf(`bytes a = %q not "hello"`, data.a)
+		}
+	}
+}
+
+func TestEndToEnd(t *testing.T) {
+	type T2 struct {
+		T string
+	}
+	s1 := "string1"
+	s2 := "string2"
+	type T1 struct {
+		A, B, C  int
+		M        map[string]*float64
+		EmptyMap map[string]int // to check that we receive a non-nil map.
+		N        *[3]float64
+		Strs     *[2]string
+		Int64s   *[]int64
+		RI       complex64
+		S        string
+		Y        []byte
+		T        *T2
+	}
+	pi := 3.14159
+	e := 2.71828
+	t1 := &T1{
+		A:        17,
+		B:        18,
+		C:        -5,
+		M:        map[string]*float64{"pi": &pi, "e": &e},
+		EmptyMap: make(map[string]int),
+		N:        &[3]float64{1.5, 2.5, 3.5},
+		Strs:     &[2]string{s1, s2},
+		Int64s:   &[]int64{77, 89, 123412342134},
+		RI:       17 - 23i,
+		S:        "Now is the time",
+		Y:        []byte("hello, sailor"),
+		T:        &T2{"this is T2"},
+	}
+	b := new(bytes.Buffer)
+	err := NewEncoder(b).Encode(t1)
+	if err != nil {
+		t.Error("encode:", err)
+	}
+	var _t1 T1
+	err = NewDecoder(b).Decode(&_t1)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if !reflect.DeepEqual(t1, &_t1) {
+		t.Errorf("encode expected %v got %v", *t1, _t1)
+	}
+	// Be absolutely sure the received map is non-nil.
+	if t1.EmptyMap == nil {
+		t.Errorf("nil map sent")
+	}
+	if _t1.EmptyMap == nil {
+		t.Errorf("nil map received")
+	}
+}
+
+func TestOverflow(t *testing.T) {
+	type inputT struct {
+		Maxi int64
+		Mini int64
+		Maxu uint64
+		Maxf float64
+		Minf float64
+		Maxc complex128
+		Minc complex128
+	}
+	var it inputT
+	var err error
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	dec := NewDecoder(b)
+
+	// int8
+	b.Reset()
+	it = inputT{
+		Maxi: math.MaxInt8 + 1,
+	}
+	type outi8 struct {
+		Maxi int8
+		Mini int8
+	}
+	var o1 outi8
+	enc.Encode(it)
+	err = dec.Decode(&o1)
+	if err == nil || err.Error() != `value for "Maxi" out of range` {
+		t.Error("wrong overflow error for int8:", err)
+	}
+	it = inputT{
+		Mini: math.MinInt8 - 1,
+	}
+	b.Reset()
+	enc.Encode(it)
+	err = dec.Decode(&o1)
+	if err == nil || err.Error() != `value for "Mini" out of range` {
+		t.Error("wrong underflow error for int8:", err)
+	}
+
+	// int16
+	b.Reset()
+	it = inputT{
+		Maxi: math.MaxInt16 + 1,
+	}
+	type outi16 struct {
+		Maxi int16
+		Mini int16
+	}
+	var o2 outi16
+	enc.Encode(it)
+	err = dec.Decode(&o2)
+	if err == nil || err.Error() != `value for "Maxi" out of range` {
+		t.Error("wrong overflow error for int16:", err)
+	}
+	it = inputT{
+		Mini: math.MinInt16 - 1,
+	}
+	b.Reset()
+	enc.Encode(it)
+	err = dec.Decode(&o2)
+	if err == nil || err.Error() != `value for "Mini" out of range` {
+		t.Error("wrong underflow error for int16:", err)
+	}
+
+	// int32
+	b.Reset()
+	it = inputT{
+		Maxi: math.MaxInt32 + 1,
+	}
+	type outi32 struct {
+		Maxi int32
+		Mini int32
+	}
+	var o3 outi32
+	enc.Encode(it)
+	err = dec.Decode(&o3)
+	if err == nil || err.Error() != `value for "Maxi" out of range` {
+		t.Error("wrong overflow error for int32:", err)
+	}
+	it = inputT{
+		Mini: math.MinInt32 - 1,
+	}
+	b.Reset()
+	enc.Encode(it)
+	err = dec.Decode(&o3)
+	if err == nil || err.Error() != `value for "Mini" out of range` {
+		t.Error("wrong underflow error for int32:", err)
+	}
+
+	// uint8
+	b.Reset()
+	it = inputT{
+		Maxu: math.MaxUint8 + 1,
+	}
+	type outu8 struct {
+		Maxu uint8
+	}
+	var o4 outu8
+	enc.Encode(it)
+	err = dec.Decode(&o4)
+	if err == nil || err.Error() != `value for "Maxu" out of range` {
+		t.Error("wrong overflow error for uint8:", err)
+	}
+
+	// uint16
+	b.Reset()
+	it = inputT{
+		Maxu: math.MaxUint16 + 1,
+	}
+	type outu16 struct {
+		Maxu uint16
+	}
+	var o5 outu16
+	enc.Encode(it)
+	err = dec.Decode(&o5)
+	if err == nil || err.Error() != `value for "Maxu" out of range` {
+		t.Error("wrong overflow error for uint16:", err)
+	}
+
+	// uint32
+	b.Reset()
+	it = inputT{
+		Maxu: math.MaxUint32 + 1,
+	}
+	type outu32 struct {
+		Maxu uint32
+	}
+	var o6 outu32
+	enc.Encode(it)
+	err = dec.Decode(&o6)
+	if err == nil || err.Error() != `value for "Maxu" out of range` {
+		t.Error("wrong overflow error for uint32:", err)
+	}
+
+	// float32
+	b.Reset()
+	it = inputT{
+		Maxf: math.MaxFloat32 * 2,
+	}
+	type outf32 struct {
+		Maxf float32
+		Minf float32
+	}
+	var o7 outf32
+	enc.Encode(it)
+	err = dec.Decode(&o7)
+	if err == nil || err.Error() != `value for "Maxf" out of range` {
+		t.Error("wrong overflow error for float32:", err)
+	}
+
+	// complex64
+	b.Reset()
+	it = inputT{
+		Maxc: complex(math.MaxFloat32*2, math.MaxFloat32*2),
+	}
+	type outc64 struct {
+		Maxc complex64
+		Minc complex64
+	}
+	var o8 outc64
+	enc.Encode(it)
+	err = dec.Decode(&o8)
+	if err == nil || err.Error() != `value for "Maxc" out of range` {
+		t.Error("wrong overflow error for complex64:", err)
+	}
+}
+
+func TestNesting(t *testing.T) {
+	type RT struct {
+		A    string
+		Next *RT
+	}
+	rt := new(RT)
+	rt.A = "level1"
+	rt.Next = new(RT)
+	rt.Next.A = "level2"
+	b := new(bytes.Buffer)
+	NewEncoder(b).Encode(rt)
+	var drt RT
+	dec := NewDecoder(b)
+	err := dec.Decode(&drt)
+	if err != nil {
+		t.Fatal("decoder error:", err)
+	}
+	if drt.A != rt.A {
+		t.Errorf("nesting: encode expected %v got %v", *rt, drt)
+	}
+	if drt.Next == nil {
+		t.Errorf("nesting: recursion failed")
+	}
+	if drt.Next.A != rt.Next.A {
+		t.Errorf("nesting: encode expected %v got %v", *rt.Next, *drt.Next)
+	}
+}
+
+// These three structures have the same data with different indirections
+type T0 struct {
+	A int
+	B int
+	C int
+	D int
+}
+type T1 struct {
+	A int
+	B *int
+	C **int
+	D ***int
+}
+type T2 struct {
+	A ***int
+	B **int
+	C *int
+	D int
+}
+
+func TestAutoIndirection(t *testing.T) {
+	// First transfer t1 into t0
+	var t1 T1
+	t1.A = 17
+	t1.B = new(int)
+	*t1.B = 177
+	t1.C = new(*int)
+	*t1.C = new(int)
+	**t1.C = 1777
+	t1.D = new(**int)
+	*t1.D = new(*int)
+	**t1.D = new(int)
+	***t1.D = 17777
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	enc.Encode(t1)
+	dec := NewDecoder(b)
+	var t0 T0
+	dec.Decode(&t0)
+	if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
+		t.Errorf("t1->t0: expected {17 177 1777 17777}; got %v", t0)
+	}
+
+	// Now transfer t2 into t0
+	var t2 T2
+	t2.D = 17777
+	t2.C = new(int)
+	*t2.C = 1777
+	t2.B = new(*int)
+	*t2.B = new(int)
+	**t2.B = 177
+	t2.A = new(**int)
+	*t2.A = new(*int)
+	**t2.A = new(int)
+	***t2.A = 17
+	b.Reset()
+	enc.Encode(t2)
+	t0 = T0{}
+	dec.Decode(&t0)
+	if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
+		t.Errorf("t2->t0 expected {17 177 1777 17777}; got %v", t0)
+	}
+
+	// Now transfer t0 into t1
+	t0 = T0{17, 177, 1777, 17777}
+	b.Reset()
+	enc.Encode(t0)
+	t1 = T1{}
+	dec.Decode(&t1)
+	if t1.A != 17 || *t1.B != 177 || **t1.C != 1777 || ***t1.D != 17777 {
+		t.Errorf("t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}", t1.A, *t1.B, **t1.C, ***t1.D)
+	}
+
+	// Now transfer t0 into t2
+	b.Reset()
+	enc.Encode(t0)
+	t2 = T2{}
+	dec.Decode(&t2)
+	if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 {
+		t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D)
+	}
+
+	// Now do t2 again but without pre-allocated pointers.
+	b.Reset()
+	enc.Encode(t0)
+	***t2.A = 0
+	**t2.B = 0
+	*t2.C = 0
+	t2.D = 0
+	dec.Decode(&t2)
+	if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 {
+		t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D)
+	}
+}
+
+type RT0 struct {
+	A int
+	B string
+	C float64
+}
+type RT1 struct {
+	C      float64
+	B      string
+	A      int
+	NotSet string
+}
+
+func TestReorderedFields(t *testing.T) {
+	var rt0 RT0
+	rt0.A = 17
+	rt0.B = "hello"
+	rt0.C = 3.14159
+	b := new(bytes.Buffer)
+	NewEncoder(b).Encode(rt0)
+	dec := NewDecoder(b)
+	var rt1 RT1
+	// Wire type is RT0, local type is RT1.
+	err := dec.Decode(&rt1)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if rt0.A != rt1.A || rt0.B != rt1.B || rt0.C != rt1.C {
+		t.Errorf("rt1->rt0: expected %v; got %v", rt0, rt1)
+	}
+}
+
+// Like an RT0 but with fields we'll ignore on the decode side.
+type IT0 struct {
+	A        int64
+	B        string
+	Ignore_d []int
+	Ignore_e [3]float64
+	Ignore_f bool
+	Ignore_g string
+	Ignore_h []byte
+	Ignore_i *RT1
+	Ignore_m map[string]int
+	C        float64
+}
+
+func TestIgnoredFields(t *testing.T) {
+	var it0 IT0
+	it0.A = 17
+	it0.B = "hello"
+	it0.C = 3.14159
+	it0.Ignore_d = []int{1, 2, 3}
+	it0.Ignore_e[0] = 1.0
+	it0.Ignore_e[1] = 2.0
+	it0.Ignore_e[2] = 3.0
+	it0.Ignore_f = true
+	it0.Ignore_g = "pay no attention"
+	it0.Ignore_h = []byte("to the curtain")
+	it0.Ignore_i = &RT1{3.1, "hi", 7, "hello"}
+	it0.Ignore_m = map[string]int{"one": 1, "two": 2}
+
+	b := new(bytes.Buffer)
+	NewEncoder(b).Encode(it0)
+	dec := NewDecoder(b)
+	var rt1 RT1
+	// Wire type is IT0, local type is RT1.
+	err := dec.Decode(&rt1)
+	if err != nil {
+		t.Error("error: ", err)
+	}
+	if int(it0.A) != rt1.A || it0.B != rt1.B || it0.C != rt1.C {
+		t.Errorf("rt0->rt1: expected %v; got %v", it0, rt1)
+	}
+}
+
+func TestBadRecursiveType(t *testing.T) {
+	type Rec ***Rec
+	var rec Rec
+	b := new(bytes.Buffer)
+	err := NewEncoder(b).Encode(&rec)
+	if err == nil {
+		t.Error("expected error; got none")
+	} else if strings.Index(err.Error(), "recursive") < 0 {
+		t.Error("expected recursive type error; got", err)
+	}
+	// Can't test decode easily because we can't encode one, so we can't pass one to a Decoder.
+}
+
+type Indirect struct {
+	A ***[3]int
+	S ***[]int
+	M ****map[string]int
+}
+
+type Direct struct {
+	A [3]int
+	S []int
+	M map[string]int
+}
+
+func TestIndirectSliceMapArray(t *testing.T) {
+	// Marshal indirect, unmarshal to direct.
+	i := new(Indirect)
+	i.A = new(**[3]int)
+	*i.A = new(*[3]int)
+	**i.A = new([3]int)
+	***i.A = [3]int{1, 2, 3}
+	i.S = new(**[]int)
+	*i.S = new(*[]int)
+	**i.S = new([]int)
+	***i.S = []int{4, 5, 6}
+	i.M = new(***map[string]int)
+	*i.M = new(**map[string]int)
+	**i.M = new(*map[string]int)
+	***i.M = new(map[string]int)
+	****i.M = map[string]int{"one": 1, "two": 2, "three": 3}
+	b := new(bytes.Buffer)
+	NewEncoder(b).Encode(i)
+	dec := NewDecoder(b)
+	var d Direct
+	err := dec.Decode(&d)
+	if err != nil {
+		t.Error("error: ", err)
+	}
+	if len(d.A) != 3 || d.A[0] != 1 || d.A[1] != 2 || d.A[2] != 3 {
+		t.Errorf("indirect to direct: d.A is %v not %v", d.A, ***i.A)
+	}
+	if len(d.S) != 3 || d.S[0] != 4 || d.S[1] != 5 || d.S[2] != 6 {
+		t.Errorf("indirect to direct: d.S is %v not %v", d.S, ***i.S)
+	}
+	if len(d.M) != 3 || d.M["one"] != 1 || d.M["two"] != 2 || d.M["three"] != 3 {
+		t.Errorf("indirect to direct: d.M is %v not %v", d.M, ***i.M)
+	}
+	// Marshal direct, unmarshal to indirect.
+	d.A = [3]int{11, 22, 33}
+	d.S = []int{44, 55, 66}
+	d.M = map[string]int{"four": 4, "five": 5, "six": 6}
+	i = new(Indirect)
+	b.Reset()
+	NewEncoder(b).Encode(d)
+	dec = NewDecoder(b)
+	err = dec.Decode(&i)
+	if err != nil {
+		t.Fatal("error: ", err)
+	}
+	if len(***i.A) != 3 || (***i.A)[0] != 11 || (***i.A)[1] != 22 || (***i.A)[2] != 33 {
+		t.Errorf("direct to indirect: ***i.A is %v not %v", ***i.A, d.A)
+	}
+	if len(***i.S) != 3 || (***i.S)[0] != 44 || (***i.S)[1] != 55 || (***i.S)[2] != 66 {
+		t.Errorf("direct to indirect: ***i.S is %v not %v", ***i.S, ***i.S)
+	}
+	if len(****i.M) != 3 || (****i.M)["four"] != 4 || (****i.M)["five"] != 5 || (****i.M)["six"] != 6 {
+		t.Errorf("direct to indirect: ****i.M is %v not %v", ****i.M, d.M)
+	}
+}
+
+// An interface with several implementations
+type Squarer interface {
+	Square() int
+}
+
+type Int int
+
+func (i Int) Square() int {
+	return int(i * i)
+}
+
+type Float float64
+
+func (f Float) Square() int {
+	return int(f * f)
+}
+
+type Vector []int
+
+func (v Vector) Square() int {
+	sum := 0
+	for _, x := range v {
+		sum += x * x
+	}
+	return sum
+}
+
+type Point struct {
+	X, Y int
+}
+
+func (p Point) Square() int {
+	return p.X*p.X + p.Y*p.Y
+}
+
+// A struct with interfaces in it.
+type InterfaceItem struct {
+	I             int
+	Sq1, Sq2, Sq3 Squarer
+	F             float64
+	Sq            []Squarer
+}
+
+// The same struct without interfaces
+type NoInterfaceItem struct {
+	I int
+	F float64
+}
+
+func TestInterface(t *testing.T) {
+	iVal := Int(3)
+	fVal := Float(5)
+	// Sending a Vector will require that the receiver define a type in the middle of
+	// receiving the value for item2.
+	vVal := Vector{1, 2, 3}
+	b := new(bytes.Buffer)
+	item1 := &InterfaceItem{1, iVal, fVal, vVal, 11.5, []Squarer{iVal, fVal, nil, vVal}}
+	// Register the types.
+	Register(Int(0))
+	Register(Float(0))
+	Register(Vector{})
+	err := NewEncoder(b).Encode(item1)
+	if err != nil {
+		t.Error("expected no encode error; got", err)
+	}
+
+	item2 := InterfaceItem{}
+	err = NewDecoder(b).Decode(&item2)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if item2.I != item1.I {
+		t.Error("normal int did not decode correctly")
+	}
+	if item2.Sq1 == nil || item2.Sq1.Square() != iVal.Square() {
+		t.Error("Int did not decode correctly")
+	}
+	if item2.Sq2 == nil || item2.Sq2.Square() != fVal.Square() {
+		t.Error("Float did not decode correctly")
+	}
+	if item2.Sq3 == nil || item2.Sq3.Square() != vVal.Square() {
+		t.Error("Vector did not decode correctly")
+	}
+	if item2.F != item1.F {
+		t.Error("normal float did not decode correctly")
+	}
+	// Now check that we received a slice of Squarers correctly, including a nil element
+	if len(item1.Sq) != len(item2.Sq) {
+		t.Fatalf("[]Squarer length wrong: got %d; expected %d", len(item2.Sq), len(item1.Sq))
+	}
+	for i, v1 := range item1.Sq {
+		v2 := item2.Sq[i]
+		if v1 == nil || v2 == nil {
+			if v1 != nil || v2 != nil {
+				t.Errorf("item %d inconsistent nils", i)
+			}
+		} else if v1.Square() != v2.Square() {
+			t.Errorf("item %d inconsistent values: %v %v", i, v1, v2)
+		}
+	}
+}
+
+// A struct with all basic types, stored in interfaces.
+type BasicInterfaceItem struct {
+	Int, Int8, Int16, Int32, Int64      interface{}
+	Uint, Uint8, Uint16, Uint32, Uint64 interface{}
+	Float32, Float64                    interface{}
+	Complex64, Complex128               interface{}
+	Bool                                interface{}
+	String                              interface{}
+	Bytes                               interface{}
+}
+
+func TestInterfaceBasic(t *testing.T) {
+	b := new(bytes.Buffer)
+	item1 := &BasicInterfaceItem{
+		int(1), int8(1), int16(1), int32(1), int64(1),
+		uint(1), uint8(1), uint16(1), uint32(1), uint64(1),
+		float32(1), 1.0,
+		complex64(1i), complex128(1i),
+		true,
+		"hello",
+		[]byte("sailor"),
+	}
+	err := NewEncoder(b).Encode(item1)
+	if err != nil {
+		t.Error("expected no encode error; got", err)
+	}
+
+	item2 := &BasicInterfaceItem{}
+	err = NewDecoder(b).Decode(&item2)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if !reflect.DeepEqual(item1, item2) {
+		t.Errorf("encode expected %v got %v", item1, item2)
+	}
+	// Hand check a couple for correct types.
+	if v, ok := item2.Bool.(bool); !ok || !v {
+		t.Error("boolean should be true")
+	}
+	if v, ok := item2.String.(string); !ok || v != item1.String.(string) {
+		t.Errorf("string should be %v is %v", item1.String, v)
+	}
+}
+
+type String string
+
+type PtrInterfaceItem struct {
+	Str1 interface{} // basic
+	Str2 interface{} // derived
+}
+
+// We'll send pointers; should receive values.
+// Also check that we can register T but send *T.
+func TestInterfacePointer(t *testing.T) {
+	b := new(bytes.Buffer)
+	str1 := "howdy"
+	str2 := String("kiddo")
+	item1 := &PtrInterfaceItem{
+		&str1,
+		&str2,
+	}
+	// Register the type.
+	Register(str2)
+	err := NewEncoder(b).Encode(item1)
+	if err != nil {
+		t.Error("expected no encode error; got", err)
+	}
+
+	item2 := &PtrInterfaceItem{}
+	err = NewDecoder(b).Decode(&item2)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	// Hand test for correct types and values.
+	if v, ok := item2.Str1.(string); !ok || v != str1 {
+		t.Errorf("basic string failed: %q should be %q", v, str1)
+	}
+	if v, ok := item2.Str2.(String); !ok || v != str2 {
+		t.Errorf("derived type String failed: %q should be %q", v, str2)
+	}
+}
+
+func TestIgnoreInterface(t *testing.T) {
+	iVal := Int(3)
+	fVal := Float(5)
+	// Sending a Point will require that the receiver define a type in the middle of
+	// receiving the value for item2.
+	pVal := Point{2, 3}
+	b := new(bytes.Buffer)
+	item1 := &InterfaceItem{1, iVal, fVal, pVal, 11.5, nil}
+	// Register the types.
+	Register(Int(0))
+	Register(Float(0))
+	Register(Point{})
+	err := NewEncoder(b).Encode(item1)
+	if err != nil {
+		t.Error("expected no encode error; got", err)
+	}
+
+	item2 := NoInterfaceItem{}
+	err = NewDecoder(b).Decode(&item2)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if item2.I != item1.I {
+		t.Error("normal int did not decode correctly")
+	}
+	if item2.F != item2.F {
+		t.Error("normal float did not decode correctly")
+	}
+}
+
+type U struct {
+	A int
+	B string
+	c float64
+	D uint
+}
+
+func TestUnexportedFields(t *testing.T) {
+	var u0 U
+	u0.A = 17
+	u0.B = "hello"
+	u0.c = 3.14159
+	u0.D = 23
+	b := new(bytes.Buffer)
+	NewEncoder(b).Encode(u0)
+	dec := NewDecoder(b)
+	var u1 U
+	u1.c = 1234.
+	err := dec.Decode(&u1)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if u0.A != u0.A || u0.B != u1.B || u0.D != u1.D {
+		t.Errorf("u1->u0: expected %v; got %v", u0, u1)
+	}
+	if u1.c != 1234. {
+		t.Error("u1.c modified")
+	}
+}
+
+var singletons = []interface{}{
+	true,
+	7,
+	3.2,
+	"hello",
+	[3]int{11, 22, 33},
+	[]float32{0.5, 0.25, 0.125},
+	map[string]int{"one": 1, "two": 2},
+}
+
+func TestDebugSingleton(t *testing.T) {
+	if debugFunc == nil {
+		return
+	}
+	b := new(bytes.Buffer)
+	// Accumulate a number of values and print them out all at once.
+	for _, x := range singletons {
+		err := NewEncoder(b).Encode(x)
+		if err != nil {
+			t.Fatal("encode:", err)
+		}
+	}
+	debugFunc(b)
+}
+
+// A type that won't be defined in the gob until we send it in an interface value.
+type OnTheFly struct {
+	A int
+}
+
+type DT struct {
+	//	X OnTheFly
+	A     int
+	B     string
+	C     float64
+	I     interface{}
+	J     interface{}
+	I_nil interface{}
+	M     map[string]int
+	T     [3]int
+	S     []string
+}
+
+func newDT() DT {
+	var dt DT
+	dt.A = 17
+	dt.B = "hello"
+	dt.C = 3.14159
+	dt.I = 271828
+	dt.J = OnTheFly{3}
+	dt.I_nil = nil
+	dt.M = map[string]int{"one": 1, "two": 2}
+	dt.T = [3]int{11, 22, 33}
+	dt.S = []string{"hi", "joe"}
+	return dt
+}
+
+func TestDebugStruct(t *testing.T) {
+	if debugFunc == nil {
+		return
+	}
+	Register(OnTheFly{})
+	dt := newDT()
+	b := new(bytes.Buffer)
+	err := NewEncoder(b).Encode(dt)
+	if err != nil {
+		t.Fatal("encode:", err)
+	}
+	debugBuffer := bytes.NewBuffer(b.Bytes())
+	dt2 := &DT{}
+	err = NewDecoder(b).Decode(&dt2)
+	if err != nil {
+		t.Error("decode:", err)
+	}
+	debugFunc(debugBuffer)
+}
+
+func encFuzzDec(rng *rand.Rand, in interface{}) error {
+	buf := new(bytes.Buffer)
+	enc := NewEncoder(buf)
+	if err := enc.Encode(&in); err != nil {
+		return err
+	}
+
+	b := buf.Bytes()
+	for i, bi := range b {
+		if rng.Intn(10) < 3 {
+			b[i] = bi + uint8(rng.Intn(256))
+		}
+	}
+
+	dec := NewDecoder(buf)
+	var e interface{}
+	if err := dec.Decode(&e); err != nil {
+		return err
+	}
+	return nil
+}
+
+// This does some "fuzz testing" by attempting to decode a sequence of random bytes.
+func TestFuzz(t *testing.T) {
+	if !*doFuzzTests {
+		t.Logf("disabled; run with -gob.fuzz to enable")
+		return
+	}
+
+	// all possible inputs
+	input := []interface{}{
+		new(int),
+		new(float32),
+		new(float64),
+		new(complex128),
+		&ByteStruct{255},
+		&ArrayStruct{},
+		&StringStruct{"hello"},
+		&GobTest1{0, &StringStruct{"hello"}},
+	}
+	testFuzz(t, time.Now().UnixNano(), 100, input...)
+}
+
+func TestFuzzRegressions(t *testing.T) {
+	if !*doFuzzTests {
+		t.Logf("disabled; run with -gob.fuzz to enable")
+		return
+	}
+
+	// An instance triggering a type name of length ~102 GB.
+	testFuzz(t, 1328492090837718000, 100, new(float32))
+	// An instance triggering a type name of 1.6 GB.
+	// Note: can take several minutes to run.
+	testFuzz(t, 1330522872628565000, 100, new(int))
+}
+
+func testFuzz(t *testing.T, seed int64, n int, input ...interface{}) {
+	for _, e := range input {
+		t.Logf("seed=%d n=%d e=%T", seed, n, e)
+		rng := rand.New(rand.NewSource(seed))
+		for i := 0; i < n; i++ {
+			encFuzzDec(rng, e)
+		}
+	}
+}
+
+// TestFuzzOneByte tries to decode corrupted input sequences
+// and checks that no panic occurs.
+func TestFuzzOneByte(t *testing.T) {
+	buf := new(bytes.Buffer)
+	Register(OnTheFly{})
+	dt := newDT()
+	if err := NewEncoder(buf).Encode(dt); err != nil {
+		t.Fatal(err)
+	}
+	s := buf.String()
+
+	indices := make([]int, 0, len(s))
+	for i := 0; i < len(s); i++ {
+		switch i {
+		case 14, 167, 231, 265: // a slice length, corruptions are not handled yet.
+			continue
+		}
+		indices = append(indices, i)
+	}
+	if testing.Short() {
+		indices = []int{1, 111, 178} // known fixed panics
+	}
+	for _, i := range indices {
+		for j := 0; j < 256; j += 3 {
+			b := []byte(s)
+			b[i] ^= byte(j)
+			var e DT
+			func() {
+				defer func() {
+					if p := recover(); p != nil {
+						t.Errorf("crash for b[%d] ^= 0x%x", i, j)
+						panic(p)
+					}
+				}()
+				err := NewDecoder(bytes.NewReader(b)).Decode(&e)
+				_ = err
+			}()
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/debug.go b/third_party/gofrontend/libgo/go/encoding/gob/debug.go
new file mode 100644
index 0000000..6117eb0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/debug.go
@@ -0,0 +1,705 @@
+// 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.
+
+// Delete the next line to include in the gob package.
+// +build ignore
+
+package gob
+
+// This file is not normally included in the gob package.  Used only for debugging the package itself.
+// Except for reading uints, it is an implementation of a reader that is independent of
+// the one implemented by Decoder.
+// To enable the Debug function, delete the +build ignore line above and do
+//	go install
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"sync"
+)
+
+var dumpBytes = false // If true, print the remaining bytes in the input buffer at each item.
+
+// Init installs the debugging facility. If this file is not compiled in the
+// package, the tests in codec_test.go are no-ops.
+func init() {
+	debugFunc = Debug
+}
+
+var (
+	blanks = bytes.Repeat([]byte{' '}, 3*10)
+	empty  = []byte(": <empty>\n")
+	tabs   = strings.Repeat("\t", 100)
+)
+
+// tab indents itself when printed.
+type tab int
+
+func (t tab) String() string {
+	n := int(t)
+	if n > len(tabs) {
+		n = len(tabs)
+	}
+	return tabs[0:n]
+}
+
+func (t tab) print() {
+	fmt.Fprint(os.Stderr, t)
+}
+
+// A peekReader wraps an io.Reader, allowing one to peek ahead to see
+// what's coming without stealing the data from the client of the Reader.
+type peekReader struct {
+	r    io.Reader
+	data []byte // read-ahead data
+}
+
+// newPeekReader returns a peekReader that wraps r.
+func newPeekReader(r io.Reader) *peekReader {
+	return &peekReader{r: r}
+}
+
+// Read is the usual method. It will first take data that has been read ahead.
+func (p *peekReader) Read(b []byte) (n int, err error) {
+	if len(p.data) == 0 {
+		return p.r.Read(b)
+	}
+	// Satisfy what's possible from the read-ahead data.
+	n = copy(b, p.data)
+	// Move data down to beginning of slice, to avoid endless growth
+	copy(p.data, p.data[n:])
+	p.data = p.data[:len(p.data)-n]
+	return
+}
+
+// peek returns as many bytes as possible from the unread
+// portion of the stream, up to the length of b.
+func (p *peekReader) peek(b []byte) (n int, err error) {
+	if len(p.data) > 0 {
+		n = copy(b, p.data)
+		if n == len(b) {
+			return
+		}
+		b = b[n:]
+	}
+	if len(b) == 0 {
+		return
+	}
+	m, e := io.ReadFull(p.r, b)
+	if m > 0 {
+		p.data = append(p.data, b[:m]...)
+	}
+	n += m
+	if e == io.ErrUnexpectedEOF {
+		// That means m > 0 but we reached EOF. If we got data
+		// we won't complain about not being able to peek enough.
+		if n > 0 {
+			e = nil
+		} else {
+			e = io.EOF
+		}
+	}
+	return n, e
+}
+
+type debugger struct {
+	mutex          sync.Mutex
+	remain         int  // the number of bytes known to remain in the input
+	remainingKnown bool // the value of 'remain' is valid
+	r              *peekReader
+	wireType       map[typeId]*wireType
+	tmp            []byte // scratch space for decoding uints.
+}
+
+// dump prints the next nBytes of the input.
+// It arranges to print the output aligned from call to
+// call, to make it easy to see what has been consumed.
+func (deb *debugger) dump(format string, args ...interface{}) {
+	if !dumpBytes {
+		return
+	}
+	fmt.Fprintf(os.Stderr, format+" ", args...)
+	if !deb.remainingKnown {
+		return
+	}
+	if deb.remain < 0 {
+		fmt.Fprintf(os.Stderr, "remaining byte count is negative! %d\n", deb.remain)
+		return
+	}
+	data := make([]byte, deb.remain)
+	n, _ := deb.r.peek(data)
+	if n == 0 {
+		os.Stderr.Write(empty)
+		return
+	}
+	b := new(bytes.Buffer)
+	fmt.Fprintf(b, "[%d]{\n", deb.remain)
+	// Blanks until first byte
+	lineLength := 0
+	if n := len(data); n%10 != 0 {
+		lineLength = 10 - n%10
+		fmt.Fprintf(b, "\t%s", blanks[:lineLength*3])
+	}
+	// 10 bytes per line
+	for len(data) > 0 {
+		if lineLength == 0 {
+			fmt.Fprint(b, "\t")
+		}
+		m := 10 - lineLength
+		lineLength = 0
+		if m > len(data) {
+			m = len(data)
+		}
+		fmt.Fprintf(b, "% x\n", data[:m])
+		data = data[m:]
+	}
+	fmt.Fprint(b, "}\n")
+	os.Stderr.Write(b.Bytes())
+}
+
+// Debug prints a human-readable representation of the gob data read from r.
+// It is a no-op unless debugging was enabled when the package was built.
+func Debug(r io.Reader) {
+	err := debug(r)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "gob debug: %s\n", err)
+	}
+}
+
+// debug implements Debug, but catches panics and returns
+// them as errors to be printed by Debug.
+func debug(r io.Reader) (err error) {
+	defer catchError(&err)
+	fmt.Fprintln(os.Stderr, "Start of debugging")
+	deb := &debugger{
+		r:        newPeekReader(r),
+		wireType: make(map[typeId]*wireType),
+		tmp:      make([]byte, 16),
+	}
+	if b, ok := r.(*bytes.Buffer); ok {
+		deb.remain = b.Len()
+		deb.remainingKnown = true
+	}
+	deb.gobStream()
+	return
+}
+
+// note that we've consumed some bytes
+func (deb *debugger) consumed(n int) {
+	if deb.remainingKnown {
+		deb.remain -= n
+	}
+}
+
+// int64 decodes and returns the next integer, which must be present.
+// Don't call this if you could be at EOF.
+func (deb *debugger) int64() int64 {
+	return toInt(deb.uint64())
+}
+
+// uint64 returns and decodes the next unsigned integer, which must be present.
+// Don't call this if you could be at EOF.
+// TODO: handle errors better.
+func (deb *debugger) uint64() uint64 {
+	n, w, err := decodeUintReader(deb.r, deb.tmp)
+	if err != nil {
+		errorf("debug: read error: %s", err)
+	}
+	deb.consumed(w)
+	return n
+}
+
+// GobStream:
+//	DelimitedMessage* (until EOF)
+func (deb *debugger) gobStream() {
+	// Make sure we're single-threaded through here.
+	deb.mutex.Lock()
+	defer deb.mutex.Unlock()
+
+	for deb.delimitedMessage(0) {
+	}
+}
+
+// DelimitedMessage:
+//	uint(lengthOfMessage) Message
+func (deb *debugger) delimitedMessage(indent tab) bool {
+	for {
+		n := deb.loadBlock(true)
+		if n < 0 {
+			return false
+		}
+		deb.dump("Delimited message of length %d", n)
+		deb.message(indent)
+	}
+	return true
+}
+
+// loadBlock preps us to read a message
+// of the length specified next in the input. It returns
+// the length of the block. The argument tells whether
+// an EOF is acceptable now.  If it is and one is found,
+// the return value is negative.
+func (deb *debugger) loadBlock(eofOK bool) int {
+	n64, w, err := decodeUintReader(deb.r, deb.tmp) // deb.uint64 will error at EOF
+	if err != nil {
+		if eofOK && err == io.EOF {
+			return -1
+		}
+		errorf("debug: unexpected error: %s", err)
+	}
+	deb.consumed(w)
+	n := int(n64)
+	if n < 0 {
+		errorf("huge value for message length: %d", n64)
+	}
+	return int(n)
+}
+
+// Message:
+//	TypeSequence TypedValue
+// TypeSequence
+//	(TypeDefinition DelimitedTypeDefinition*)?
+// DelimitedTypeDefinition:
+//	uint(lengthOfTypeDefinition) TypeDefinition
+// TypedValue:
+//	int(typeId) Value
+func (deb *debugger) message(indent tab) bool {
+	for {
+		// Convert the uint64 to a signed integer typeId
+		uid := deb.int64()
+		id := typeId(uid)
+		deb.dump("type id=%d", id)
+		if id < 0 {
+			deb.typeDefinition(indent, -id)
+			n := deb.loadBlock(false)
+			deb.dump("Message of length %d", n)
+			continue
+		} else {
+			deb.value(indent, id)
+			break
+		}
+	}
+	return true
+}
+
+// Helper methods to make it easy to scan a type descriptor.
+
+// common returns the CommonType at the input point.
+func (deb *debugger) common() CommonType {
+	fieldNum := -1
+	name := ""
+	id := typeId(0)
+	for {
+		delta := deb.delta(-1)
+		if delta == 0 {
+			break
+		}
+		fieldNum += delta
+		switch fieldNum {
+		case 0:
+			name = deb.string()
+		case 1:
+			// Id typeId
+			id = deb.typeId()
+		default:
+			errorf("corrupted CommonType")
+		}
+	}
+	return CommonType{name, id}
+}
+
+// uint returns the unsigned int at the input point, as a uint (not uint64).
+func (deb *debugger) uint() uint {
+	return uint(deb.uint64())
+}
+
+// int returns the signed int at the input point, as an int (not int64).
+func (deb *debugger) int() int {
+	return int(deb.int64())
+}
+
+// typeId returns the type id at the input point.
+func (deb *debugger) typeId() typeId {
+	return typeId(deb.int64())
+}
+
+// string returns the string at the input point.
+func (deb *debugger) string() string {
+	x := int(deb.uint64())
+	b := make([]byte, x)
+	nb, _ := deb.r.Read(b)
+	if nb != x {
+		errorf("corrupted type")
+	}
+	deb.consumed(nb)
+	return string(b)
+}
+
+// delta returns the field delta at the input point.  The expect argument,
+// if non-negative, identifies what the value should be.
+func (deb *debugger) delta(expect int) int {
+	delta := int(deb.uint64())
+	if delta < 0 || (expect >= 0 && delta != expect) {
+		errorf("decode: corrupted type: delta %d expected %d", delta, expect)
+	}
+	return delta
+}
+
+// TypeDefinition:
+//	[int(-typeId) (already read)] encodingOfWireType
+func (deb *debugger) typeDefinition(indent tab, id typeId) {
+	deb.dump("type definition for id %d", id)
+	// Encoding is of a wireType. Decode the structure as usual
+	fieldNum := -1
+	wire := new(wireType)
+	// A wireType defines a single field.
+	delta := deb.delta(-1)
+	fieldNum += delta
+	switch fieldNum {
+	case 0: // array type, one field of {{Common}, elem, length}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		// Field number 1 is type Id of elem
+		deb.delta(1)
+		id := deb.typeId()
+		// Field number 3 is length
+		deb.delta(1)
+		length := deb.int()
+		wire.ArrayT = &arrayType{com, id, length}
+
+	case 1: // slice type, one field of {{Common}, elem}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		// Field number 1 is type Id of elem
+		deb.delta(1)
+		id := deb.typeId()
+		wire.SliceT = &sliceType{com, id}
+
+	case 2: // struct type, one field of {{Common}, []fieldType}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		// Field number 1 is slice of FieldType
+		deb.delta(1)
+		numField := int(deb.uint())
+		field := make([]*fieldType, numField)
+		for i := 0; i < numField; i++ {
+			field[i] = new(fieldType)
+			deb.delta(1) // field 0 of fieldType: name
+			field[i].Name = deb.string()
+			deb.delta(1) // field 1 of fieldType: id
+			field[i].Id = deb.typeId()
+			deb.delta(0) // end of fieldType
+		}
+		wire.StructT = &structType{com, field}
+
+	case 3: // map type, one field of {{Common}, key, elem}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		// Field number 1 is type Id of key
+		deb.delta(1)
+		keyId := deb.typeId()
+		// Field number 2 is type Id of elem
+		deb.delta(1)
+		elemId := deb.typeId()
+		wire.MapT = &mapType{com, keyId, elemId}
+	case 4: // GobEncoder type, one field of {{Common}}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		wire.GobEncoderT = &gobEncoderType{com}
+	case 5: // BinaryMarshaler type, one field of {{Common}}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		wire.BinaryMarshalerT = &gobEncoderType{com}
+	case 6: // TextMarshaler type, one field of {{Common}}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		wire.TextMarshalerT = &gobEncoderType{com}
+	default:
+		errorf("bad field in type %d", fieldNum)
+	}
+	deb.printWireType(indent, wire)
+	deb.delta(0) // end inner type (arrayType, etc.)
+	deb.delta(0) // end wireType
+	// Remember we've seen this type.
+	deb.wireType[id] = wire
+}
+
+// Value:
+//	SingletonValue | StructValue
+func (deb *debugger) value(indent tab, id typeId) {
+	wire, ok := deb.wireType[id]
+	if ok && wire.StructT != nil {
+		deb.structValue(indent, id)
+	} else {
+		deb.singletonValue(indent, id)
+	}
+}
+
+// SingletonValue:
+//	uint(0) FieldValue
+func (deb *debugger) singletonValue(indent tab, id typeId) {
+	deb.dump("Singleton value")
+	// is it a builtin type?
+	wire := deb.wireType[id]
+	_, ok := builtinIdToType[id]
+	if !ok && wire == nil {
+		errorf("type id %d not defined", id)
+	}
+	m := deb.uint64()
+	if m != 0 {
+		errorf("expected zero; got %d", m)
+	}
+	deb.fieldValue(indent, id)
+}
+
+// InterfaceValue:
+//	NilInterfaceValue | NonNilInterfaceValue
+func (deb *debugger) interfaceValue(indent tab) {
+	deb.dump("Start of interface value")
+	if nameLen := deb.uint64(); nameLen == 0 {
+		deb.nilInterfaceValue(indent)
+	} else {
+		deb.nonNilInterfaceValue(indent, int(nameLen))
+	}
+}
+
+// NilInterfaceValue:
+//	uint(0) [already read]
+func (deb *debugger) nilInterfaceValue(indent tab) int {
+	fmt.Fprintf(os.Stderr, "%snil interface\n", indent)
+	return 0
+}
+
+// NonNilInterfaceValue:
+//	ConcreteTypeName TypeSequence InterfaceContents
+// ConcreteTypeName:
+//	uint(lengthOfName) [already read=n] name
+// InterfaceContents:
+//	int(concreteTypeId) DelimitedValue
+// DelimitedValue:
+//	uint(length) Value
+func (deb *debugger) nonNilInterfaceValue(indent tab, nameLen int) {
+	// ConcreteTypeName
+	b := make([]byte, nameLen)
+	deb.r.Read(b) // TODO: CHECK THESE READS!!
+	deb.consumed(nameLen)
+	name := string(b)
+
+	for {
+		id := deb.typeId()
+		if id < 0 {
+			deb.typeDefinition(indent, -id)
+			n := deb.loadBlock(false)
+			deb.dump("Nested message of length %d", n)
+		} else {
+			// DelimitedValue
+			x := deb.uint64() // in case we want to ignore the value; we don't.
+			fmt.Fprintf(os.Stderr, "%sinterface value, type %q id=%d; valueLength %d\n", indent, name, id, x)
+			deb.value(indent, id)
+			break
+		}
+	}
+}
+
+// printCommonType prints a common type; used by printWireType.
+func (deb *debugger) printCommonType(indent tab, kind string, common *CommonType) {
+	indent.print()
+	fmt.Fprintf(os.Stderr, "%s %q id=%d\n", kind, common.Name, common.Id)
+}
+
+// printWireType prints the contents of a wireType.
+func (deb *debugger) printWireType(indent tab, wire *wireType) {
+	fmt.Fprintf(os.Stderr, "%stype definition {\n", indent)
+	indent++
+	switch {
+	case wire.ArrayT != nil:
+		deb.printCommonType(indent, "array", &wire.ArrayT.CommonType)
+		fmt.Fprintf(os.Stderr, "%slen %d\n", indent+1, wire.ArrayT.Len)
+		fmt.Fprintf(os.Stderr, "%selemid %d\n", indent+1, wire.ArrayT.Elem)
+	case wire.MapT != nil:
+		deb.printCommonType(indent, "map", &wire.MapT.CommonType)
+		fmt.Fprintf(os.Stderr, "%skey id=%d\n", indent+1, wire.MapT.Key)
+		fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.MapT.Elem)
+	case wire.SliceT != nil:
+		deb.printCommonType(indent, "slice", &wire.SliceT.CommonType)
+		fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.SliceT.Elem)
+	case wire.StructT != nil:
+		deb.printCommonType(indent, "struct", &wire.StructT.CommonType)
+		for i, field := range wire.StructT.Field {
+			fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\tid=%d\n", indent+1, i, field.Name, field.Id)
+		}
+	case wire.GobEncoderT != nil:
+		deb.printCommonType(indent, "GobEncoder", &wire.GobEncoderT.CommonType)
+	}
+	indent--
+	fmt.Fprintf(os.Stderr, "%s}\n", indent)
+}
+
+// fieldValue prints a value of any type, such as a struct field.
+// FieldValue:
+//	builtinValue | ArrayValue | MapValue | SliceValue | StructValue | InterfaceValue
+func (deb *debugger) fieldValue(indent tab, id typeId) {
+	_, ok := builtinIdToType[id]
+	if ok {
+		if id == tInterface {
+			deb.interfaceValue(indent)
+		} else {
+			deb.printBuiltin(indent, id)
+		}
+		return
+	}
+	wire, ok := deb.wireType[id]
+	if !ok {
+		errorf("type id %d not defined", id)
+	}
+	switch {
+	case wire.ArrayT != nil:
+		deb.arrayValue(indent, wire)
+	case wire.MapT != nil:
+		deb.mapValue(indent, wire)
+	case wire.SliceT != nil:
+		deb.sliceValue(indent, wire)
+	case wire.StructT != nil:
+		deb.structValue(indent, id)
+	case wire.GobEncoderT != nil:
+		deb.gobEncoderValue(indent, id)
+	default:
+		panic("bad wire type for field")
+	}
+}
+
+// printBuiltin prints a value not of a fundamental type, that is,
+// one whose type is known to gobs at bootstrap time.
+func (deb *debugger) printBuiltin(indent tab, id typeId) {
+	switch id {
+	case tBool:
+		x := deb.int64()
+		if x == 0 {
+			fmt.Fprintf(os.Stderr, "%sfalse\n", indent)
+		} else {
+			fmt.Fprintf(os.Stderr, "%strue\n", indent)
+		}
+	case tInt:
+		x := deb.int64()
+		fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
+	case tUint:
+		x := deb.int64()
+		fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
+	case tFloat:
+		x := deb.uint64()
+		fmt.Fprintf(os.Stderr, "%s%g\n", indent, floatFromBits(x))
+	case tComplex:
+		r := deb.uint64()
+		i := deb.uint64()
+		fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, floatFromBits(r), floatFromBits(i))
+	case tBytes:
+		x := int(deb.uint64())
+		b := make([]byte, x)
+		deb.r.Read(b)
+		deb.consumed(x)
+		fmt.Fprintf(os.Stderr, "%s{% x}=%q\n", indent, b, b)
+	case tString:
+		x := int(deb.uint64())
+		b := make([]byte, x)
+		deb.r.Read(b)
+		deb.consumed(x)
+		fmt.Fprintf(os.Stderr, "%s%q\n", indent, b)
+	default:
+		panic("unknown builtin")
+	}
+}
+
+// ArrayValue:
+//	uint(n) FieldValue*n
+func (deb *debugger) arrayValue(indent tab, wire *wireType) {
+	elemId := wire.ArrayT.Elem
+	u := deb.uint64()
+	length := int(u)
+	for i := 0; i < length; i++ {
+		deb.fieldValue(indent, elemId)
+	}
+	if length != wire.ArrayT.Len {
+		fmt.Fprintf(os.Stderr, "%s(wrong length for array: %d should be %d)\n", indent, length, wire.ArrayT.Len)
+	}
+}
+
+// MapValue:
+//	uint(n) (FieldValue FieldValue)*n  [n (key, value) pairs]
+func (deb *debugger) mapValue(indent tab, wire *wireType) {
+	keyId := wire.MapT.Key
+	elemId := wire.MapT.Elem
+	u := deb.uint64()
+	length := int(u)
+	for i := 0; i < length; i++ {
+		deb.fieldValue(indent+1, keyId)
+		deb.fieldValue(indent+1, elemId)
+	}
+}
+
+// SliceValue:
+//	uint(n) (n FieldValue)
+func (deb *debugger) sliceValue(indent tab, wire *wireType) {
+	elemId := wire.SliceT.Elem
+	u := deb.uint64()
+	length := int(u)
+	deb.dump("Start of slice of length %d", length)
+
+	for i := 0; i < length; i++ {
+		deb.fieldValue(indent, elemId)
+	}
+}
+
+// StructValue:
+//	(uint(fieldDelta) FieldValue)*
+func (deb *debugger) structValue(indent tab, id typeId) {
+	deb.dump("Start of struct value of %q id=%d\n<<\n", id.name(), id)
+	fmt.Fprintf(os.Stderr, "%s%s struct {\n", indent, id.name())
+	wire, ok := deb.wireType[id]
+	if !ok {
+		errorf("type id %d not defined", id)
+	}
+	strct := wire.StructT
+	fieldNum := -1
+	indent++
+	for {
+		delta := deb.uint64()
+		if delta == 0 { // struct terminator is zero delta fieldnum
+			break
+		}
+		fieldNum += int(delta)
+		if fieldNum < 0 || fieldNum >= len(strct.Field) {
+			deb.dump("field number out of range: prevField=%d delta=%d", fieldNum-int(delta), delta)
+			break
+		}
+		fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\n", indent, fieldNum, wire.StructT.Field[fieldNum].Name)
+		deb.fieldValue(indent+1, strct.Field[fieldNum].Id)
+	}
+	indent--
+	fmt.Fprintf(os.Stderr, "%s} // end %s struct\n", indent, id.name())
+	deb.dump(">> End of struct value of type %d %q", id, id.name())
+}
+
+// GobEncoderValue:
+//	uint(n) byte*n
+func (deb *debugger) gobEncoderValue(indent tab, id typeId) {
+	len := deb.uint64()
+	deb.dump("GobEncoder value of %q id=%d, length %d\n", id.name(), id, len)
+	fmt.Fprintf(os.Stderr, "%s%s (implements GobEncoder)\n", indent, id.name())
+	data := make([]byte, len)
+	_, err := deb.r.Read(data)
+	if err != nil {
+		errorf("gobEncoder data read: %s", err)
+	}
+	fmt.Fprintf(os.Stderr, "%s[% .2x]\n", indent+1, data)
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/decode.go b/third_party/gofrontend/libgo/go/encoding/gob/decode.go
new file mode 100644
index 0000000..d851314
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/decode.go
@@ -0,0 +1,1317 @@
+// 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 gob
+
+// TODO(rsc): When garbage collector changes, revisit
+// the allocations in this file that use unsafe.Pointer.
+
+import (
+	"bytes"
+	"encoding"
+	"errors"
+	"io"
+	"math"
+	"reflect"
+	"unsafe"
+)
+
+var (
+	errBadUint = errors.New("gob: encoded unsigned integer out of range")
+	errBadType = errors.New("gob: unknown type id or corrupted data")
+	errRange   = errors.New("gob: bad data: field numbers out of bounds")
+)
+
+// decoderState is the execution state of an instance of the decoder. A new state
+// is created for nested objects.
+type decoderState struct {
+	dec *Decoder
+	// The buffer is stored with an extra indirection because it may be replaced
+	// if we load a type during decode (when reading an interface value).
+	b        *bytes.Buffer
+	fieldnum int // the last field number read.
+	buf      []byte
+	next     *decoderState // for free list
+}
+
+// We pass the bytes.Buffer separately for easier testing of the infrastructure
+// without requiring a full Decoder.
+func (dec *Decoder) newDecoderState(buf *bytes.Buffer) *decoderState {
+	d := dec.freeList
+	if d == nil {
+		d = new(decoderState)
+		d.dec = dec
+		d.buf = make([]byte, uint64Size)
+	} else {
+		dec.freeList = d.next
+	}
+	d.b = buf
+	return d
+}
+
+func (dec *Decoder) freeDecoderState(d *decoderState) {
+	d.next = dec.freeList
+	dec.freeList = d
+}
+
+func overflow(name string) error {
+	return errors.New(`value for "` + name + `" out of range`)
+}
+
+// decodeUintReader reads an encoded unsigned integer from an io.Reader.
+// Used only by the Decoder to read the message length.
+func decodeUintReader(r io.Reader, buf []byte) (x uint64, width int, err error) {
+	width = 1
+	n, err := io.ReadFull(r, buf[0:width])
+	if n == 0 {
+		return
+	}
+	b := buf[0]
+	if b <= 0x7f {
+		return uint64(b), width, nil
+	}
+	n = -int(int8(b))
+	if n > uint64Size {
+		err = errBadUint
+		return
+	}
+	width, err = io.ReadFull(r, buf[0:n])
+	if err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		return
+	}
+	// Could check that the high byte is zero but it's not worth it.
+	for _, b := range buf[0:width] {
+		x = x<<8 | uint64(b)
+	}
+	width++ // +1 for length byte
+	return
+}
+
+// decodeUint reads an encoded unsigned integer from state.r.
+// Does not check for overflow.
+func (state *decoderState) decodeUint() (x uint64) {
+	b, err := state.b.ReadByte()
+	if err != nil {
+		error_(err)
+	}
+	if b <= 0x7f {
+		return uint64(b)
+	}
+	n := -int(int8(b))
+	if n > uint64Size {
+		error_(errBadUint)
+	}
+	width, err := state.b.Read(state.buf[0:n])
+	if err != nil {
+		error_(err)
+	}
+	// Don't need to check error; it's safe to loop regardless.
+	// Could check that the high byte is zero but it's not worth it.
+	for _, b := range state.buf[0:width] {
+		x = x<<8 | uint64(b)
+	}
+	return x
+}
+
+// decodeInt reads an encoded signed integer from state.r.
+// Does not check for overflow.
+func (state *decoderState) decodeInt() int64 {
+	x := state.decodeUint()
+	if x&1 != 0 {
+		return ^int64(x >> 1)
+	}
+	return int64(x >> 1)
+}
+
+// decOp is the signature of a decoding operator for a given type.
+type decOp func(i *decInstr, state *decoderState, p unsafe.Pointer)
+
+// The 'instructions' of the decoding machine
+type decInstr struct {
+	op     decOp
+	field  int     // field number of the wire type
+	indir  int     // how many pointer indirections to reach the value in the struct
+	offset uintptr // offset in the structure of the field to encode
+	ovfl   error   // error message for overflow/underflow (for arrays, of the elements)
+}
+
+// Since the encoder writes no zeros, if we arrive at a decoder we have
+// a value to extract and store.  The field number has already been read
+// (it's how we knew to call this decoder).
+// Each decoder is responsible for handling any indirections associated
+// with the data structure.  If any pointer so reached is nil, allocation must
+// be done.
+
+// Walk the pointer hierarchy, allocating if we find a nil.  Stop one before the end.
+func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
+	for ; indir > 1; indir-- {
+		if *(*unsafe.Pointer)(p) == nil {
+			// Allocation required
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(unsafe.Pointer))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	return p
+}
+
+// ignoreUint discards a uint value with no destination.
+func ignoreUint(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	state.decodeUint()
+}
+
+// ignoreTwoUints discards a uint value with no destination. It's used to skip
+// complex values.
+func ignoreTwoUints(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	state.decodeUint()
+	state.decodeUint()
+}
+
+// decBool decodes a uint and stores it as a boolean through p.
+func decBool(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	*(*bool)(p) = state.decodeUint() != 0
+}
+
+// decInt8 decodes an integer and stores it as an int8 through p.
+func decInt8(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeInt()
+	if v < math.MinInt8 || math.MaxInt8 < v {
+		error_(i.ovfl)
+	} else {
+		*(*int8)(p) = int8(v)
+	}
+}
+
+// decUint8 decodes an unsigned integer and stores it as a uint8 through p.
+func decUint8(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeUint()
+	if math.MaxUint8 < v {
+		error_(i.ovfl)
+	} else {
+		*(*uint8)(p) = uint8(v)
+	}
+}
+
+// decInt16 decodes an integer and stores it as an int16 through p.
+func decInt16(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeInt()
+	if v < math.MinInt16 || math.MaxInt16 < v {
+		error_(i.ovfl)
+	} else {
+		*(*int16)(p) = int16(v)
+	}
+}
+
+// decUint16 decodes an unsigned integer and stores it as a uint16 through p.
+func decUint16(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeUint()
+	if math.MaxUint16 < v {
+		error_(i.ovfl)
+	} else {
+		*(*uint16)(p) = uint16(v)
+	}
+}
+
+// decInt32 decodes an integer and stores it as an int32 through p.
+func decInt32(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeInt()
+	if v < math.MinInt32 || math.MaxInt32 < v {
+		error_(i.ovfl)
+	} else {
+		*(*int32)(p) = int32(v)
+	}
+}
+
+// decUint32 decodes an unsigned integer and stores it as a uint32 through p.
+func decUint32(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeUint()
+	if math.MaxUint32 < v {
+		error_(i.ovfl)
+	} else {
+		*(*uint32)(p) = uint32(v)
+	}
+}
+
+// decInt64 decodes an integer and stores it as an int64 through p.
+func decInt64(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	*(*int64)(p) = int64(state.decodeInt())
+}
+
+// decUint64 decodes an unsigned integer and stores it as a uint64 through p.
+func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	*(*uint64)(p) = uint64(state.decodeUint())
+}
+
+// Floating-point numbers are transmitted as uint64s holding the bits
+// of the underlying representation.  They are sent byte-reversed, with
+// the exponent end coming out first, so integer floating point numbers
+// (for example) transmit more compactly.  This routine does the
+// unswizzling.
+func floatFromBits(u uint64) float64 {
+	var v uint64
+	for i := 0; i < 8; i++ {
+		v <<= 8
+		v |= u & 0xFF
+		u >>= 8
+	}
+	return math.Float64frombits(v)
+}
+
+// storeFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
+// number, and stores it through p. It's a helper function for float32 and complex64.
+func storeFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	v := floatFromBits(state.decodeUint())
+	av := v
+	if av < 0 {
+		av = -av
+	}
+	// +Inf is OK in both 32- and 64-bit floats.  Underflow is always OK.
+	if math.MaxFloat32 < av && av <= math.MaxFloat64 {
+		error_(i.ovfl)
+	} else {
+		*(*float32)(p) = float32(v)
+	}
+}
+
+// decFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
+// number, and stores it through p.
+func decFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	storeFloat32(i, state, p)
+}
+
+// decFloat64 decodes an unsigned integer, treats it as a 64-bit floating-point
+// number, and stores it through p.
+func decFloat64(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	*(*float64)(p) = floatFromBits(uint64(state.decodeUint()))
+}
+
+// decComplex64 decodes a pair of unsigned integers, treats them as a
+// pair of floating point numbers, and stores them as a complex64 through p.
+// The real part comes first.
+func decComplex64(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex64))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	storeFloat32(i, state, p)
+	storeFloat32(i, state, unsafe.Pointer(uintptr(p)+unsafe.Sizeof(float32(0))))
+}
+
+// decComplex128 decodes a pair of unsigned integers, treats them as a
+// pair of floating point numbers, and stores them as a complex128 through p.
+// The real part comes first.
+func decComplex128(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex128))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	real := floatFromBits(uint64(state.decodeUint()))
+	imag := floatFromBits(uint64(state.decodeUint()))
+	*(*complex128)(p) = complex(real, imag)
+}
+
+// decUint8Slice decodes a byte slice and stores through p a slice header
+// describing the data.
+// uint8 slices are encoded as an unsigned count followed by the raw bytes.
+func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	n := state.decodeUint()
+	if n > uint64(state.b.Len()) {
+		errorf("length of []byte exceeds input size (%d bytes)", n)
+	}
+	slice := (*[]uint8)(p)
+	if uint64(cap(*slice)) < n {
+		*slice = make([]uint8, n)
+	} else {
+		*slice = (*slice)[0:n]
+	}
+	if _, err := state.b.Read(*slice); err != nil {
+		errorf("error decoding []byte: %s", err)
+	}
+}
+
+// decString decodes byte array and stores through p a string header
+// describing the data.
+// Strings are encoded as an unsigned count followed by the raw bytes.
+func decString(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(string))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	n := state.decodeUint()
+	if n > uint64(state.b.Len()) {
+		errorf("string length exceeds input size (%d bytes)", n)
+	}
+	b := make([]byte, n)
+	state.b.Read(b)
+	// It would be a shame to do the obvious thing here,
+	//	*(*string)(p) = string(b)
+	// because we've already allocated the storage and this would
+	// allocate again and copy.  So we do this ugly hack, which is even
+	// even more unsafe than it looks as it depends the memory
+	// representation of a string matching the beginning of the memory
+	// representation of a byte slice (a byte slice is longer).
+	*(*string)(p) = *(*string)(unsafe.Pointer(&b))
+}
+
+// ignoreUint8Array skips over the data for a byte slice value with no destination.
+func ignoreUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	b := make([]byte, state.decodeUint())
+	state.b.Read(b)
+}
+
+// Execution engine
+
+// The encoder engine is an array of instructions indexed by field number of the incoming
+// decoder.  It is executed with random access according to field number.
+type decEngine struct {
+	instr    []decInstr
+	numInstr int // the number of active instructions
+}
+
+// allocate makes sure storage is available for an object of underlying type rtyp
+// that is indir levels of indirection through p.
+func allocate(rtyp reflect.Type, p unsafe.Pointer, indir int) unsafe.Pointer {
+	if indir == 0 {
+		return p
+	}
+	up := p
+	if indir > 1 {
+		up = decIndirect(up, indir)
+	}
+	if *(*unsafe.Pointer)(up) == nil {
+		// Allocate object.
+		*(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer())
+	}
+	return *(*unsafe.Pointer)(up)
+}
+
+// decodeSingle decodes a top-level value that is not a struct and stores it through p.
+// Such values are preceded by a zero, making them have the memory layout of a
+// struct field (although with an illegal field number).
+func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep unsafe.Pointer) {
+	state := dec.newDecoderState(&dec.buf)
+	state.fieldnum = singletonField
+	delta := int(state.decodeUint())
+	if delta != 0 {
+		errorf("decode: corrupted data: non-zero delta for singleton")
+	}
+	instr := &engine.instr[singletonField]
+	if instr.indir != ut.indir {
+		errorf("internal error: inconsistent indirection instr %d ut %d", instr.indir, ut.indir)
+	}
+	ptr := basep // offset will be zero
+	if instr.indir > 1 {
+		ptr = decIndirect(ptr, instr.indir)
+	}
+	instr.op(instr, state, ptr)
+	dec.freeDecoderState(state)
+}
+
+// decodeStruct decodes a top-level struct and stores it through p.
+// Indir is for the value, not the type.  At the time of the call it may
+// differ from ut.indir, which was computed when the engine was built.
+// This state cannot arise for decodeSingle, which is called directly
+// from the user's value, not from the innards of an engine.
+func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.Pointer, indir int) {
+	p = allocate(ut.base, p, indir)
+	state := dec.newDecoderState(&dec.buf)
+	state.fieldnum = -1
+	basep := p
+	for state.b.Len() > 0 {
+		delta := int(state.decodeUint())
+		if delta < 0 {
+			errorf("decode: corrupted data: negative delta")
+		}
+		if delta == 0 { // struct terminator is zero delta fieldnum
+			break
+		}
+		fieldnum := state.fieldnum + delta
+		if fieldnum >= len(engine.instr) {
+			error_(errRange)
+			break
+		}
+		instr := &engine.instr[fieldnum]
+		p := unsafe.Pointer(uintptr(basep) + instr.offset)
+		if instr.indir > 1 {
+			p = decIndirect(p, instr.indir)
+		}
+		instr.op(instr, state, p)
+		state.fieldnum = fieldnum
+	}
+	dec.freeDecoderState(state)
+}
+
+// ignoreStruct discards the data for a struct with no destination.
+func (dec *Decoder) ignoreStruct(engine *decEngine) {
+	state := dec.newDecoderState(&dec.buf)
+	state.fieldnum = -1
+	for state.b.Len() > 0 {
+		delta := int(state.decodeUint())
+		if delta < 0 {
+			errorf("ignore decode: corrupted data: negative delta")
+		}
+		if delta == 0 { // struct terminator is zero delta fieldnum
+			break
+		}
+		fieldnum := state.fieldnum + delta
+		if fieldnum >= len(engine.instr) {
+			error_(errRange)
+		}
+		instr := &engine.instr[fieldnum]
+		instr.op(instr, state, unsafe.Pointer(nil))
+		state.fieldnum = fieldnum
+	}
+	dec.freeDecoderState(state)
+}
+
+// ignoreSingle discards the data for a top-level non-struct value with no
+// destination. It's used when calling Decode with a nil value.
+func (dec *Decoder) ignoreSingle(engine *decEngine) {
+	state := dec.newDecoderState(&dec.buf)
+	state.fieldnum = singletonField
+	delta := int(state.decodeUint())
+	if delta != 0 {
+		errorf("decode: corrupted data: non-zero delta for singleton")
+	}
+	instr := &engine.instr[singletonField]
+	instr.op(instr, state, unsafe.Pointer(nil))
+	dec.freeDecoderState(state)
+}
+
+// decodeArrayHelper does the work for decoding arrays and slices.
+func (dec *Decoder) decodeArrayHelper(state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
+	instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
+	for i := 0; i < length; i++ {
+		if state.b.Len() == 0 {
+			errorf("decoding array or slice: length exceeds input size (%d elements)", length)
+		}
+		up := p
+		if elemIndir > 1 {
+			up = decIndirect(up, elemIndir)
+		}
+		elemOp(instr, state, up)
+		p = unsafe.Pointer(uintptr(p) + elemWid)
+	}
+}
+
+// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element.
+// The length is an unsigned integer preceding the elements.  Even though the length is redundant
+// (it's part of the type), it's a useful check and is included in the encoding.
+func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) {
+	if indir > 0 {
+		p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
+	}
+	if n := state.decodeUint(); n != uint64(length) {
+		errorf("length mismatch in decodeArray")
+	}
+	dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl)
+}
+
+// decodeIntoValue is a helper for map decoding.  Since maps are decoded using reflection,
+// unlike the other items we can't use a pointer directly.
+func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl error) reflect.Value {
+	instr := &decInstr{op, 0, indir, 0, ovfl}
+	up := unsafeAddr(v)
+	if indir > 1 {
+		up = decIndirect(up, indir)
+	}
+	op(instr, state, up)
+	return v
+}
+
+// decodeMap decodes a map and stores its header through p.
+// Maps are encoded as a length followed by key:value pairs.
+// Because the internals of maps are not visible to us, we must
+// use reflection rather than pointer magic.
+func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p unsafe.Pointer, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
+	if indir > 0 {
+		p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
+	}
+	up := unsafe.Pointer(p)
+	if *(*unsafe.Pointer)(up) == nil { // maps are represented as a pointer in the runtime
+		// Allocate map.
+		*(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.MakeMap(mtyp).Pointer())
+	}
+	// Maps cannot be accessed by moving addresses around the way
+	// that slices etc. can.  We must recover a full reflection value for
+	// the iteration.
+	v := reflect.NewAt(mtyp, unsafe.Pointer(p)).Elem()
+	n := int(state.decodeUint())
+	for i := 0; i < n; i++ {
+		key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl)
+		elem := decodeIntoValue(state, elemOp, elemIndir, allocValue(mtyp.Elem()), ovfl)
+		v.SetMapIndex(key, elem)
+	}
+}
+
+// ignoreArrayHelper does the work for discarding arrays and slices.
+func (dec *Decoder) ignoreArrayHelper(state *decoderState, elemOp decOp, length int) {
+	instr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")}
+	for i := 0; i < length; i++ {
+		elemOp(instr, state, nil)
+	}
+}
+
+// ignoreArray discards the data for an array value with no destination.
+func (dec *Decoder) ignoreArray(state *decoderState, elemOp decOp, length int) {
+	if n := state.decodeUint(); n != uint64(length) {
+		errorf("length mismatch in ignoreArray")
+	}
+	dec.ignoreArrayHelper(state, elemOp, length)
+}
+
+// ignoreMap discards the data for a map value with no destination.
+func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) {
+	n := int(state.decodeUint())
+	keyInstr := &decInstr{keyOp, 0, 0, 0, errors.New("no error")}
+	elemInstr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")}
+	for i := 0; i < n; i++ {
+		keyOp(keyInstr, state, nil)
+		elemOp(elemInstr, state, nil)
+	}
+}
+
+// decodeSlice decodes a slice and stores the slice header through p.
+// Slices are encoded as an unsigned length followed by the elements.
+func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) {
+	nr := state.decodeUint()
+	n := int(nr)
+	if indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			// Allocate the slice header.
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new([]unsafe.Pointer))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	// Allocate storage for the slice elements, that is, the underlying array,
+	// if the existing slice does not have the capacity.
+	// Always write a header at p.
+	hdrp := (*reflect.SliceHeader)(p)
+	if hdrp.Cap < n {
+		hdrp.Data = reflect.MakeSlice(atyp, n, n).Pointer()
+		hdrp.Cap = n
+	}
+	hdrp.Len = n
+	dec.decodeArrayHelper(state, unsafe.Pointer(hdrp.Data), elemOp, elemWid, n, elemIndir, ovfl)
+}
+
+// ignoreSlice skips over the data for a slice value with no destination.
+func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) {
+	dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint()))
+}
+
+// setInterfaceValue sets an interface value to a concrete value,
+// but first it checks that the assignment will succeed.
+func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
+	if !value.Type().AssignableTo(ivalue.Type()) {
+		errorf("%s is not assignable to type %s", value.Type(), ivalue.Type())
+	}
+	ivalue.Set(value)
+}
+
+// decodeInterface decodes an interface value and stores it through p.
+// Interfaces are encoded as the name of a concrete type followed by a value.
+// If the name is empty, the value is nil and no value is sent.
+func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p unsafe.Pointer, indir int) {
+	// Create a writable interface reflect.Value.  We need one even for the nil case.
+	ivalue := allocValue(ityp)
+	// Read the name of the concrete type.
+	nr := state.decodeUint()
+	if nr < 0 || nr > 1<<31 { // zero is permissible for anonymous types
+		errorf("invalid type name length %d", nr)
+	}
+	if nr > uint64(state.b.Len()) {
+		errorf("invalid type name length %d: exceeds input size", nr)
+	}
+	b := make([]byte, nr)
+	state.b.Read(b)
+	name := string(b)
+	if name == "" {
+		// Copy the representation of the nil interface value to the target.
+		// This is horribly unsafe and special.
+		if indir > 0 {
+			p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect
+		}
+		*(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
+		return
+	}
+	if len(name) > 1024 {
+		errorf("name too long (%d bytes): %.20q...", len(name), name)
+	}
+	// The concrete type must be registered.
+	registerLock.RLock()
+	typ, ok := nameToConcreteType[name]
+	registerLock.RUnlock()
+	if !ok {
+		errorf("name not registered for interface: %q", name)
+	}
+	// Read the type id of the concrete value.
+	concreteId := dec.decodeTypeSequence(true)
+	if concreteId < 0 {
+		error_(dec.err)
+	}
+	// Byte count of value is next; we don't care what it is (it's there
+	// in case we want to ignore the value by skipping it completely).
+	state.decodeUint()
+	// Read the concrete value.
+	value := allocValue(typ)
+	dec.decodeValue(concreteId, value)
+	if dec.err != nil {
+		error_(dec.err)
+	}
+	// Allocate the destination interface value.
+	if indir > 0 {
+		p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect
+	}
+	// Assign the concrete value to the interface.
+	// Tread carefully; it might not satisfy the interface.
+	setInterfaceValue(ivalue, value)
+	// Copy the representation of the interface value to the target.
+	// This is horribly unsafe and special.
+	*(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
+}
+
+// ignoreInterface discards the data for an interface value with no destination.
+func (dec *Decoder) ignoreInterface(state *decoderState) {
+	// Read the name of the concrete type.
+	b := make([]byte, state.decodeUint())
+	_, err := state.b.Read(b)
+	if err != nil {
+		error_(err)
+	}
+	id := dec.decodeTypeSequence(true)
+	if id < 0 {
+		error_(dec.err)
+	}
+	// At this point, the decoder buffer contains a delimited value. Just toss it.
+	state.b.Next(int(state.decodeUint()))
+}
+
+// decodeGobDecoder decodes something implementing the GobDecoder interface.
+// The data is encoded as a byte slice.
+func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, v reflect.Value) {
+	// Read the bytes for the value.
+	b := make([]byte, state.decodeUint())
+	_, err := state.b.Read(b)
+	if err != nil {
+		error_(err)
+	}
+	// We know it's one of these.
+	switch ut.externalDec {
+	case xGob:
+		err = v.Interface().(GobDecoder).GobDecode(b)
+	case xBinary:
+		err = v.Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(b)
+	case xText:
+		err = v.Interface().(encoding.TextUnmarshaler).UnmarshalText(b)
+	}
+	if err != nil {
+		error_(err)
+	}
+}
+
+// ignoreGobDecoder discards the data for a GobDecoder value with no destination.
+func (dec *Decoder) ignoreGobDecoder(state *decoderState) {
+	// Read the bytes for the value.
+	b := make([]byte, state.decodeUint())
+	_, err := state.b.Read(b)
+	if err != nil {
+		error_(err)
+	}
+}
+
+// Index by Go types.
+var decOpTable = [...]decOp{
+	reflect.Bool:       decBool,
+	reflect.Int8:       decInt8,
+	reflect.Int16:      decInt16,
+	reflect.Int32:      decInt32,
+	reflect.Int64:      decInt64,
+	reflect.Uint8:      decUint8,
+	reflect.Uint16:     decUint16,
+	reflect.Uint32:     decUint32,
+	reflect.Uint64:     decUint64,
+	reflect.Float32:    decFloat32,
+	reflect.Float64:    decFloat64,
+	reflect.Complex64:  decComplex64,
+	reflect.Complex128: decComplex128,
+	reflect.String:     decString,
+}
+
+// Indexed by gob types.  tComplex will be added during type.init().
+var decIgnoreOpMap = map[typeId]decOp{
+	tBool:    ignoreUint,
+	tInt:     ignoreUint,
+	tUint:    ignoreUint,
+	tFloat:   ignoreUint,
+	tBytes:   ignoreUint8Array,
+	tString:  ignoreUint8Array,
+	tComplex: ignoreTwoUints,
+}
+
+// decOpFor returns the decoding op for the base type under rt and
+// the indirection count to reach it.
+func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) (*decOp, int) {
+	ut := userType(rt)
+	// If the type implements GobEncoder, we handle it without further processing.
+	if ut.externalDec != 0 {
+		return dec.gobDecodeOpFor(ut)
+	}
+
+	// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
+	// Return the pointer to the op we're already building.
+	if opPtr := inProgress[rt]; opPtr != nil {
+		return opPtr, ut.indir
+	}
+	typ := ut.base
+	indir := ut.indir
+	var op decOp
+	k := typ.Kind()
+	if int(k) < len(decOpTable) {
+		op = decOpTable[k]
+	}
+	if op == nil {
+		inProgress[rt] = &op
+		// Special cases
+		switch t := typ; t.Kind() {
+		case reflect.Array:
+			name = "element of " + name
+			elemId := dec.wireType[wireId].ArrayT.Elem
+			elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
+			ovfl := overflow(name)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.decodeArray(t, state, p, *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
+			}
+
+		case reflect.Map:
+			keyId := dec.wireType[wireId].MapT.Key
+			elemId := dec.wireType[wireId].MapT.Elem
+			keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), "key of "+name, inProgress)
+			elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress)
+			ovfl := overflow(name)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.decodeMap(t, state, p, *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
+			}
+
+		case reflect.Slice:
+			name = "element of " + name
+			if t.Elem().Kind() == reflect.Uint8 {
+				op = decUint8Slice
+				break
+			}
+			var elemId typeId
+			if tt, ok := builtinIdToType[wireId]; ok {
+				elemId = tt.(*sliceType).Elem
+			} else {
+				elemId = dec.wireType[wireId].SliceT.Elem
+			}
+			elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
+			ovfl := overflow(name)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.decodeSlice(t, state, p, *elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl)
+			}
+
+		case reflect.Struct:
+			// Generate a closure that calls out to the engine for the nested type.
+			enginePtr, err := dec.getDecEnginePtr(wireId, userType(typ))
+			if err != nil {
+				error_(err)
+			}
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				// indirect through enginePtr to delay evaluation for recursive structs.
+				dec.decodeStruct(*enginePtr, userType(typ), p, i.indir)
+			}
+		case reflect.Interface:
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.decodeInterface(t, state, p, i.indir)
+			}
+		}
+	}
+	if op == nil {
+		errorf("decode can't handle type %s", rt)
+	}
+	return &op, indir
+}
+
+// decIgnoreOpFor returns the decoding op for a field that has no destination.
+func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
+	op, ok := decIgnoreOpMap[wireId]
+	if !ok {
+		if wireId == tInterface {
+			// Special case because it's a method: the ignored item might
+			// define types and we need to record their state in the decoder.
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.ignoreInterface(state)
+			}
+			return op
+		}
+		// Special cases
+		wire := dec.wireType[wireId]
+		switch {
+		case wire == nil:
+			errorf("bad data: undefined type %s", wireId.string())
+		case wire.ArrayT != nil:
+			elemId := wire.ArrayT.Elem
+			elemOp := dec.decIgnoreOpFor(elemId)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len)
+			}
+
+		case wire.MapT != nil:
+			keyId := dec.wireType[wireId].MapT.Key
+			elemId := dec.wireType[wireId].MapT.Elem
+			keyOp := dec.decIgnoreOpFor(keyId)
+			elemOp := dec.decIgnoreOpFor(elemId)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.ignoreMap(state, keyOp, elemOp)
+			}
+
+		case wire.SliceT != nil:
+			elemId := wire.SliceT.Elem
+			elemOp := dec.decIgnoreOpFor(elemId)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.ignoreSlice(state, elemOp)
+			}
+
+		case wire.StructT != nil:
+			// Generate a closure that calls out to the engine for the nested type.
+			enginePtr, err := dec.getIgnoreEnginePtr(wireId)
+			if err != nil {
+				error_(err)
+			}
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				// indirect through enginePtr to delay evaluation for recursive structs
+				state.dec.ignoreStruct(*enginePtr)
+			}
+
+		case wire.GobEncoderT != nil, wire.BinaryMarshalerT != nil, wire.TextMarshalerT != nil:
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.ignoreGobDecoder(state)
+			}
+		}
+	}
+	if op == nil {
+		errorf("bad data: ignore can't handle type %s", wireId.string())
+	}
+	return op
+}
+
+// gobDecodeOpFor returns the op for a type that is known to implement
+// GobDecoder.
+func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
+	rcvrType := ut.user
+	if ut.decIndir == -1 {
+		rcvrType = reflect.PtrTo(rcvrType)
+	} else if ut.decIndir > 0 {
+		for i := int8(0); i < ut.decIndir; i++ {
+			rcvrType = rcvrType.Elem()
+		}
+	}
+	var op decOp
+	op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+		// Caller has gotten us to within one indirection of our value.
+		if i.indir > 0 {
+			if *(*unsafe.Pointer)(p) == nil {
+				*(*unsafe.Pointer)(p) = unsafe.Pointer(reflect.New(ut.base).Pointer())
+			}
+		}
+		// Now p is a pointer to the base type.  Do we need to climb out to
+		// get to the receiver type?
+		var v reflect.Value
+		if ut.decIndir == -1 {
+			v = reflect.NewAt(rcvrType, unsafe.Pointer(&p)).Elem()
+		} else {
+			v = reflect.NewAt(rcvrType, p).Elem()
+		}
+		state.dec.decodeGobDecoder(ut, state, v)
+	}
+	return &op, int(ut.indir)
+
+}
+
+// compatibleType asks: Are these two gob Types compatible?
+// Answers the question for basic types, arrays, maps and slices, plus
+// GobEncoder/Decoder pairs.
+// Structs are considered ok; fields will be checked later.
+func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId, inProgress map[reflect.Type]typeId) bool {
+	if rhs, ok := inProgress[fr]; ok {
+		return rhs == fw
+	}
+	inProgress[fr] = fw
+	ut := userType(fr)
+	wire, ok := dec.wireType[fw]
+	// If wire was encoded with an encoding method, fr must have that method.
+	// And if not, it must not.
+	// At most one of the booleans in ut is set.
+	// We could possibly relax this constraint in the future in order to
+	// choose the decoding method using the data in the wireType.
+	// The parentheses look odd but are correct.
+	if (ut.externalDec == xGob) != (ok && wire.GobEncoderT != nil) ||
+		(ut.externalDec == xBinary) != (ok && wire.BinaryMarshalerT != nil) ||
+		(ut.externalDec == xText) != (ok && wire.TextMarshalerT != nil) {
+		return false
+	}
+	if ut.externalDec != 0 { // This test trumps all others.
+		return true
+	}
+	switch t := ut.base; t.Kind() {
+	default:
+		// chan, etc: cannot handle.
+		return false
+	case reflect.Bool:
+		return fw == tBool
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return fw == tInt
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return fw == tUint
+	case reflect.Float32, reflect.Float64:
+		return fw == tFloat
+	case reflect.Complex64, reflect.Complex128:
+		return fw == tComplex
+	case reflect.String:
+		return fw == tString
+	case reflect.Interface:
+		return fw == tInterface
+	case reflect.Array:
+		if !ok || wire.ArrayT == nil {
+			return false
+		}
+		array := wire.ArrayT
+		return t.Len() == array.Len && dec.compatibleType(t.Elem(), array.Elem, inProgress)
+	case reflect.Map:
+		if !ok || wire.MapT == nil {
+			return false
+		}
+		MapType := wire.MapT
+		return dec.compatibleType(t.Key(), MapType.Key, inProgress) && dec.compatibleType(t.Elem(), MapType.Elem, inProgress)
+	case reflect.Slice:
+		// Is it an array of bytes?
+		if t.Elem().Kind() == reflect.Uint8 {
+			return fw == tBytes
+		}
+		// Extract and compare element types.
+		var sw *sliceType
+		if tt, ok := builtinIdToType[fw]; ok {
+			sw, _ = tt.(*sliceType)
+		} else if wire != nil {
+			sw = wire.SliceT
+		}
+		elem := userType(t.Elem()).base
+		return sw != nil && dec.compatibleType(elem, sw.Elem, inProgress)
+	case reflect.Struct:
+		return true
+	}
+}
+
+// typeString returns a human-readable description of the type identified by remoteId.
+func (dec *Decoder) typeString(remoteId typeId) string {
+	if t := idToType[remoteId]; t != nil {
+		// globally known type.
+		return t.string()
+	}
+	return dec.wireType[remoteId].string()
+}
+
+// compileSingle compiles the decoder engine for a non-struct top-level value, including
+// GobDecoders.
+func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) {
+	rt := ut.user
+	engine = new(decEngine)
+	engine.instr = make([]decInstr, 1) // one item
+	name := rt.String()                // best we can do
+	if !dec.compatibleType(rt, remoteId, make(map[reflect.Type]typeId)) {
+		remoteType := dec.typeString(remoteId)
+		// Common confusing case: local interface type, remote concrete type.
+		if ut.base.Kind() == reflect.Interface && remoteId != tInterface {
+			return nil, errors.New("gob: local interface type " + name + " can only be decoded from remote interface type; received concrete type " + remoteType)
+		}
+		return nil, errors.New("gob: decoding into local type " + name + ", received remote type " + remoteType)
+	}
+	op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp))
+	ovfl := errors.New(`value for "` + name + `" out of range`)
+	engine.instr[singletonField] = decInstr{*op, singletonField, indir, 0, ovfl}
+	engine.numInstr = 1
+	return
+}
+
+// compileIgnoreSingle compiles the decoder engine for a non-struct top-level value that will be discarded.
+func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err error) {
+	engine = new(decEngine)
+	engine.instr = make([]decInstr, 1) // one item
+	op := dec.decIgnoreOpFor(remoteId)
+	ovfl := overflow(dec.typeString(remoteId))
+	engine.instr[0] = decInstr{op, 0, 0, 0, ovfl}
+	engine.numInstr = 1
+	return
+}
+
+// compileDec compiles the decoder engine for a value.  If the value is not a struct,
+// it calls out to compileSingle.
+func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) {
+	rt := ut.base
+	srt := rt
+	if srt.Kind() != reflect.Struct || ut.externalDec != 0 {
+		return dec.compileSingle(remoteId, ut)
+	}
+	var wireStruct *structType
+	// Builtin types can come from global pool; the rest must be defined by the decoder.
+	// Also we know we're decoding a struct now, so the client must have sent one.
+	if t, ok := builtinIdToType[remoteId]; ok {
+		wireStruct, _ = t.(*structType)
+	} else {
+		wire := dec.wireType[remoteId]
+		if wire == nil {
+			error_(errBadType)
+		}
+		wireStruct = wire.StructT
+	}
+	if wireStruct == nil {
+		errorf("type mismatch in decoder: want struct type %s; got non-struct", rt)
+	}
+	engine = new(decEngine)
+	engine.instr = make([]decInstr, len(wireStruct.Field))
+	seen := make(map[reflect.Type]*decOp)
+	// Loop over the fields of the wire type.
+	for fieldnum := 0; fieldnum < len(wireStruct.Field); fieldnum++ {
+		wireField := wireStruct.Field[fieldnum]
+		if wireField.Name == "" {
+			errorf("empty name for remote field of type %s", wireStruct.Name)
+		}
+		ovfl := overflow(wireField.Name)
+		// Find the field of the local type with the same name.
+		localField, present := srt.FieldByName(wireField.Name)
+		// TODO(r): anonymous names
+		if !present || !isExported(wireField.Name) {
+			op := dec.decIgnoreOpFor(wireField.Id)
+			engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl}
+			continue
+		}
+		if !dec.compatibleType(localField.Type, wireField.Id, make(map[reflect.Type]typeId)) {
+			errorf("wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name)
+		}
+		op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen)
+		engine.instr[fieldnum] = decInstr{*op, fieldnum, indir, uintptr(localField.Offset), ovfl}
+		engine.numInstr++
+	}
+	return
+}
+
+// getDecEnginePtr returns the engine for the specified type.
+func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePtr **decEngine, err error) {
+	rt := ut.user
+	decoderMap, ok := dec.decoderCache[rt]
+	if !ok {
+		decoderMap = make(map[typeId]**decEngine)
+		dec.decoderCache[rt] = decoderMap
+	}
+	if enginePtr, ok = decoderMap[remoteId]; !ok {
+		// To handle recursive types, mark this engine as underway before compiling.
+		enginePtr = new(*decEngine)
+		decoderMap[remoteId] = enginePtr
+		*enginePtr, err = dec.compileDec(remoteId, ut)
+		if err != nil {
+			delete(decoderMap, remoteId)
+		}
+	}
+	return
+}
+
+// emptyStruct is the type we compile into when ignoring a struct value.
+type emptyStruct struct{}
+
+var emptyStructType = reflect.TypeOf(emptyStruct{})
+
+// getDecEnginePtr returns the engine for the specified type when the value is to be discarded.
+func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, err error) {
+	var ok bool
+	if enginePtr, ok = dec.ignorerCache[wireId]; !ok {
+		// To handle recursive types, mark this engine as underway before compiling.
+		enginePtr = new(*decEngine)
+		dec.ignorerCache[wireId] = enginePtr
+		wire := dec.wireType[wireId]
+		if wire != nil && wire.StructT != nil {
+			*enginePtr, err = dec.compileDec(wireId, userType(emptyStructType))
+		} else {
+			*enginePtr, err = dec.compileIgnoreSingle(wireId)
+		}
+		if err != nil {
+			delete(dec.ignorerCache, wireId)
+		}
+	}
+	return
+}
+
+// decodeValue decodes the data stream representing a value and stores it in val.
+func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
+	defer catchError(&dec.err)
+	// If the value is nil, it means we should just ignore this item.
+	if !val.IsValid() {
+		dec.decodeIgnoredValue(wireId)
+		return
+	}
+	// Dereference down to the underlying type.
+	ut := userType(val.Type())
+	base := ut.base
+	var enginePtr **decEngine
+	enginePtr, dec.err = dec.getDecEnginePtr(wireId, ut)
+	if dec.err != nil {
+		return
+	}
+	engine := *enginePtr
+	if st := base; st.Kind() == reflect.Struct && ut.externalDec == 0 {
+		if engine.numInstr == 0 && st.NumField() > 0 &&
+			dec.wireType[wireId] != nil && len(dec.wireType[wireId].StructT.Field) > 0 {
+			name := base.Name()
+			errorf("type mismatch: no fields matched compiling decoder for %s", name)
+		}
+		dec.decodeStruct(engine, ut, unsafeAddr(val), ut.indir)
+	} else {
+		dec.decodeSingle(engine, ut, unsafeAddr(val))
+	}
+}
+
+// decodeIgnoredValue decodes the data stream representing a value of the specified type and discards it.
+func (dec *Decoder) decodeIgnoredValue(wireId typeId) {
+	var enginePtr **decEngine
+	enginePtr, dec.err = dec.getIgnoreEnginePtr(wireId)
+	if dec.err != nil {
+		return
+	}
+	wire := dec.wireType[wireId]
+	if wire != nil && wire.StructT != nil {
+		dec.ignoreStruct(*enginePtr)
+	} else {
+		dec.ignoreSingle(*enginePtr)
+	}
+}
+
+func init() {
+	var iop, uop decOp
+	switch reflect.TypeOf(int(0)).Bits() {
+	case 32:
+		iop = decInt32
+		uop = decUint32
+	case 64:
+		iop = decInt64
+		uop = decUint64
+	default:
+		panic("gob: unknown size of int/uint")
+	}
+	decOpTable[reflect.Int] = iop
+	decOpTable[reflect.Uint] = uop
+
+	// Finally uintptr
+	switch reflect.TypeOf(uintptr(0)).Bits() {
+	case 32:
+		uop = decUint32
+	case 64:
+		uop = decUint64
+	default:
+		panic("gob: unknown size of uintptr")
+	}
+	decOpTable[reflect.Uintptr] = uop
+}
+
+// Gob assumes it can call UnsafeAddr on any Value
+// in order to get a pointer it can copy data from.
+// Values that have just been created and do not point
+// into existing structs or slices cannot be addressed,
+// so simulate it by returning a pointer to a copy.
+// Each call allocates once.
+func unsafeAddr(v reflect.Value) unsafe.Pointer {
+	if v.CanAddr() {
+		return unsafe.Pointer(v.UnsafeAddr())
+	}
+	x := reflect.New(v.Type()).Elem()
+	x.Set(v)
+	return unsafe.Pointer(x.UnsafeAddr())
+}
+
+// Gob depends on being able to take the address
+// of zeroed Values it creates, so use this wrapper instead
+// of the standard reflect.Zero.
+// Each call allocates once.
+func allocValue(t reflect.Type) reflect.Value {
+	return reflect.New(t).Elem()
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/decoder.go b/third_party/gofrontend/libgo/go/encoding/gob/decoder.go
new file mode 100644
index 0000000..3a769ec
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/decoder.go
@@ -0,0 +1,237 @@
+// 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 gob
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"io"
+	"reflect"
+	"sync"
+)
+
+// A Decoder manages the receipt of type and data information read from the
+// remote side of a connection.
+type Decoder struct {
+	mutex        sync.Mutex                              // each item must be received atomically
+	r            io.Reader                               // source of the data
+	buf          bytes.Buffer                            // buffer for more efficient i/o from r
+	wireType     map[typeId]*wireType                    // map from remote ID to local description
+	decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines
+	ignorerCache map[typeId]**decEngine                  // ditto for ignored objects
+	freeList     *decoderState                           // list of free decoderStates; avoids reallocation
+	countBuf     []byte                                  // used for decoding integers while parsing messages
+	tmp          []byte                                  // temporary storage for i/o; saves reallocating
+	err          error
+}
+
+// NewDecoder returns a new decoder that reads from the io.Reader.
+// If r does not also implement io.ByteReader, it will be wrapped in a
+// bufio.Reader.
+func NewDecoder(r io.Reader) *Decoder {
+	dec := new(Decoder)
+	// We use the ability to read bytes as a plausible surrogate for buffering.
+	if _, ok := r.(io.ByteReader); !ok {
+		r = bufio.NewReader(r)
+	}
+	dec.r = r
+	dec.wireType = make(map[typeId]*wireType)
+	dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
+	dec.ignorerCache = make(map[typeId]**decEngine)
+	dec.countBuf = make([]byte, 9) // counts may be uint64s (unlikely!), require 9 bytes
+
+	return dec
+}
+
+// recvType loads the definition of a type.
+func (dec *Decoder) recvType(id typeId) {
+	// Have we already seen this type?  That's an error
+	if id < firstUserId || dec.wireType[id] != nil {
+		dec.err = errors.New("gob: duplicate type received")
+		return
+	}
+
+	// Type:
+	wire := new(wireType)
+	dec.decodeValue(tWireType, reflect.ValueOf(wire))
+	if dec.err != nil {
+		return
+	}
+	// Remember we've seen this type.
+	dec.wireType[id] = wire
+}
+
+var errBadCount = errors.New("invalid message length")
+
+// recvMessage reads the next count-delimited item from the input. It is the converse
+// of Encoder.writeMessage. It returns false on EOF or other error reading the message.
+func (dec *Decoder) recvMessage() bool {
+	// Read a count.
+	nbytes, _, err := decodeUintReader(dec.r, dec.countBuf)
+	if err != nil {
+		dec.err = err
+		return false
+	}
+	// Upper limit of 1GB, allowing room to grow a little without overflow.
+	// TODO: We might want more control over this limit.
+	if nbytes >= 1<<30 {
+		dec.err = errBadCount
+		return false
+	}
+	dec.readMessage(int(nbytes))
+	return dec.err == nil
+}
+
+// readMessage reads the next nbytes bytes from the input.
+func (dec *Decoder) readMessage(nbytes int) {
+	// Allocate the dec.tmp buffer, up to 10KB.
+	const maxBuf = 10 * 1024
+	nTmp := nbytes
+	if nTmp > maxBuf {
+		nTmp = maxBuf
+	}
+	if cap(dec.tmp) < nTmp {
+		nAlloc := nTmp + 100 // A little extra for growth.
+		if nAlloc > maxBuf {
+			nAlloc = maxBuf
+		}
+		dec.tmp = make([]byte, nAlloc)
+	}
+	dec.tmp = dec.tmp[:nTmp]
+
+	// Read the data
+	dec.buf.Grow(nbytes)
+	for nbytes > 0 {
+		if nbytes < nTmp {
+			dec.tmp = dec.tmp[:nbytes]
+		}
+		var nRead int
+		nRead, dec.err = io.ReadFull(dec.r, dec.tmp)
+		if dec.err != nil {
+			if dec.err == io.EOF {
+				dec.err = io.ErrUnexpectedEOF
+			}
+			return
+		}
+		dec.buf.Write(dec.tmp)
+		nbytes -= nRead
+	}
+}
+
+// toInt turns an encoded uint64 into an int, according to the marshaling rules.
+func toInt(x uint64) int64 {
+	i := int64(x >> 1)
+	if x&1 != 0 {
+		i = ^i
+	}
+	return i
+}
+
+func (dec *Decoder) nextInt() int64 {
+	n, _, err := decodeUintReader(&dec.buf, dec.countBuf)
+	if err != nil {
+		dec.err = err
+	}
+	return toInt(n)
+}
+
+func (dec *Decoder) nextUint() uint64 {
+	n, _, err := decodeUintReader(&dec.buf, dec.countBuf)
+	if err != nil {
+		dec.err = err
+	}
+	return n
+}
+
+// decodeTypeSequence parses:
+// TypeSequence
+//	(TypeDefinition DelimitedTypeDefinition*)?
+// and returns the type id of the next value.  It returns -1 at
+// EOF.  Upon return, the remainder of dec.buf is the value to be
+// decoded.  If this is an interface value, it can be ignored by
+// resetting that buffer.
+func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
+	for dec.err == nil {
+		if dec.buf.Len() == 0 {
+			if !dec.recvMessage() {
+				break
+			}
+		}
+		// Receive a type id.
+		id := typeId(dec.nextInt())
+		if id >= 0 {
+			// Value follows.
+			return id
+		}
+		// Type definition for (-id) follows.
+		dec.recvType(-id)
+		// When decoding an interface, after a type there may be a
+		// DelimitedValue still in the buffer.  Skip its count.
+		// (Alternatively, the buffer is empty and the byte count
+		// will be absorbed by recvMessage.)
+		if dec.buf.Len() > 0 {
+			if !isInterface {
+				dec.err = errors.New("extra data in buffer")
+				break
+			}
+			dec.nextUint()
+		}
+	}
+	return -1
+}
+
+// Decode reads the next value from the input stream and stores
+// it in the data represented by the empty interface value.
+// If e is nil, the value will be discarded. Otherwise,
+// the value underlying e must be a pointer to the
+// correct type for the next data item received.
+// If the input is at EOF, Decode returns io.EOF and
+// does not modify e.
+func (dec *Decoder) Decode(e interface{}) error {
+	if e == nil {
+		return dec.DecodeValue(reflect.Value{})
+	}
+	value := reflect.ValueOf(e)
+	// If e represents a value as opposed to a pointer, the answer won't
+	// get back to the caller.  Make sure it's a pointer.
+	if value.Type().Kind() != reflect.Ptr {
+		dec.err = errors.New("gob: attempt to decode into a non-pointer")
+		return dec.err
+	}
+	return dec.DecodeValue(value)
+}
+
+// DecodeValue reads the next value from the input stream.
+// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value.
+// Otherwise, it stores the value into v.  In that case, v must represent
+// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet())
+// If the input is at EOF, DecodeValue returns io.EOF and
+// does not modify e.
+func (dec *Decoder) DecodeValue(v reflect.Value) error {
+	if v.IsValid() {
+		if v.Kind() == reflect.Ptr && !v.IsNil() {
+			// That's okay, we'll store through the pointer.
+		} else if !v.CanSet() {
+			return errors.New("gob: DecodeValue of unassignable value")
+		}
+	}
+	// Make sure we're single-threaded through here.
+	dec.mutex.Lock()
+	defer dec.mutex.Unlock()
+
+	dec.buf.Reset() // In case data lingers from previous invocation.
+	dec.err = nil
+	id := dec.decodeTypeSequence(false)
+	if dec.err == nil {
+		dec.decodeValue(id, v)
+	}
+	return dec.err
+}
+
+// If debug.go is compiled into the program , debugFunc prints a human-readable
+// representation of the gob data read from r by calling that file's Debug function.
+// Otherwise it is nil.
+var debugFunc func(io.Reader)
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/doc.go b/third_party/gofrontend/libgo/go/encoding/gob/doc.go
new file mode 100644
index 0000000..d0acaba
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/doc.go
@@ -0,0 +1,386 @@
+// 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 gob manages streams of gobs - binary values exchanged between an
+Encoder (transmitter) and a Decoder (receiver).  A typical use is transporting
+arguments and results of remote procedure calls (RPCs) such as those provided by
+package "rpc".
+
+The implementation compiles a custom codec for each data type in the stream and
+is most efficient when a single Encoder is used to transmit a stream of values,
+amortizing the cost of compilation.
+
+Basics
+
+A stream of gobs is self-describing.  Each data item in the stream is preceded by
+a specification of its type, expressed in terms of a small set of predefined
+types.  Pointers are not transmitted, but the things they point to are
+transmitted; that is, the values are flattened.  Recursive types work fine, but
+recursive values (data with cycles) are problematic.  This may change.
+
+To use gobs, create an Encoder and present it with a series of data items as
+values or addresses that can be dereferenced to values.  The Encoder makes sure
+all type information is sent before it is needed.  At the receive side, a
+Decoder retrieves values from the encoded stream and unpacks them into local
+variables.
+
+Types and Values
+
+The source and destination values/types need not correspond exactly.  For structs,
+fields (identified by name) that are in the source but absent from the receiving
+variable will be ignored.  Fields that are in the receiving variable but missing
+from the transmitted type or value will be ignored in the destination.  If a field
+with the same name is present in both, their types must be compatible. Both the
+receiver and transmitter will do all necessary indirection and dereferencing to
+convert between gobs and actual Go values.  For instance, a gob type that is
+schematically,
+
+	struct { A, B int }
+
+can be sent from or received into any of these Go types:
+
+	struct { A, B int }	// the same
+	*struct { A, B int }	// extra indirection of the struct
+	struct { *A, **B int }	// extra indirection of the fields
+	struct { A, B int64 }	// different concrete value type; see below
+
+It may also be received into any of these:
+
+	struct { A, B int }	// the same
+	struct { B, A int }	// ordering doesn't matter; matching is by name
+	struct { A, B, C int }	// extra field (C) ignored
+	struct { B int }	// missing field (A) ignored; data will be dropped
+	struct { B, C int }	// missing field (A) ignored; extra field (C) ignored.
+
+Attempting to receive into these types will draw a decode error:
+
+	struct { A int; B uint }	// change of signedness for B
+	struct { A int; B float }	// change of type for B
+	struct { }			// no field names in common
+	struct { C, D int }		// no field names in common
+
+Integers are transmitted two ways: arbitrary precision signed integers or
+arbitrary precision unsigned integers.  There is no int8, int16 etc.
+discrimination in the gob format; there are only signed and unsigned integers.  As
+described below, the transmitter sends the value in a variable-length encoding;
+the receiver accepts the value and stores it in the destination variable.
+Floating-point numbers are always sent using IEEE-754 64-bit precision (see
+below).
+
+Signed integers may be received into any signed integer variable: int, int16, etc.;
+unsigned integers may be received into any unsigned integer variable; and floating
+point values may be received into any floating point variable.  However,
+the destination variable must be able to represent the value or the decode
+operation will fail.
+
+Structs, arrays and slices are also supported. Structs encode and decode only
+exported fields. Strings and arrays of bytes are supported with a special,
+efficient representation (see below). When a slice is decoded, if the existing
+slice has capacity the slice will be extended in place; if not, a new array is
+allocated. Regardless, the length of the resulting slice reports the number of
+elements decoded.
+
+Functions and channels will not be sent in a gob. Attempting to encode such a value
+at top the level will fail. A struct field of chan or func type is treated exactly
+like an unexported field and is ignored.
+
+Gob can encode a value of any type implementing the GobEncoder or
+encoding.BinaryMarshaler interfaces by calling the corresponding method,
+in that order of preference.
+
+Gob can decode a value of any type implementing the GobDecoder or
+encoding.BinaryUnmarshaler interfaces by calling the corresponding method,
+again in that order of preference.
+
+Encoding Details
+
+This section documents the encoding, details that are not important for most
+users. Details are presented bottom-up.
+
+An unsigned integer is sent one of two ways.  If it is less than 128, it is sent
+as a byte with that value.  Otherwise it is sent as a minimal-length big-endian
+(high byte first) byte stream holding the value, preceded by one byte holding the
+byte count, negated.  Thus 0 is transmitted as (00), 7 is transmitted as (07) and
+256 is transmitted as (FE 01 00).
+
+A boolean is encoded within an unsigned integer: 0 for false, 1 for true.
+
+A signed integer, i, is encoded within an unsigned integer, u.  Within u, bits 1
+upward contain the value; bit 0 says whether they should be complemented upon
+receipt.  The encode algorithm looks like this:
+
+	uint u;
+	if i < 0 {
+		u = (^i << 1) | 1	// complement i, bit 0 is 1
+	} else {
+		u = (i << 1)	// do not complement i, bit 0 is 0
+	}
+	encodeUnsigned(u)
+
+The low bit is therefore analogous to a sign bit, but making it the complement bit
+instead guarantees that the largest negative integer is not a special case.  For
+example, -129=^128=(^256>>1) encodes as (FE 01 01).
+
+Floating-point numbers are always sent as a representation of a float64 value.
+That value is converted to a uint64 using math.Float64bits.  The uint64 is then
+byte-reversed and sent as a regular unsigned integer.  The byte-reversal means the
+exponent and high-precision part of the mantissa go first.  Since the low bits are
+often zero, this can save encoding bytes.  For instance, 17.0 is encoded in only
+three bytes (FE 31 40).
+
+Strings and slices of bytes are sent as an unsigned count followed by that many
+uninterpreted bytes of the value.
+
+All other slices and arrays are sent as an unsigned count followed by that many
+elements using the standard gob encoding for their type, recursively.
+
+Maps are sent as an unsigned count followed by that many key, element
+pairs. Empty but non-nil maps are sent, so if the sender has allocated
+a map, the receiver will allocate a map even if no elements are
+transmitted.
+
+Structs are sent as a sequence of (field number, field value) pairs.  The field
+value is sent using the standard gob encoding for its type, recursively.  If a
+field has the zero value for its type, it is omitted from the transmission.  The
+field number is defined by the type of the encoded struct: the first field of the
+encoded type is field 0, the second is field 1, etc.  When encoding a value, the
+field numbers are delta encoded for efficiency and the fields are always sent in
+order of increasing field number; the deltas are therefore unsigned.  The
+initialization for the delta encoding sets the field number to -1, so an unsigned
+integer field 0 with value 7 is transmitted as unsigned delta = 1, unsigned value
+= 7 or (01 07).  Finally, after all the fields have been sent a terminating mark
+denotes the end of the struct.  That mark is a delta=0 value, which has
+representation (00).
+
+Interface types are not checked for compatibility; all interface types are
+treated, for transmission, as members of a single "interface" type, analogous to
+int or []byte - in effect they're all treated as interface{}.  Interface values
+are transmitted as a string identifying the concrete type being sent (a name
+that must be pre-defined by calling Register), followed by a byte count of the
+length of the following data (so the value can be skipped if it cannot be
+stored), followed by the usual encoding of concrete (dynamic) value stored in
+the interface value.  (A nil interface value is identified by the empty string
+and transmits no value.) Upon receipt, the decoder verifies that the unpacked
+concrete item satisfies the interface of the receiving variable.
+
+The representation of types is described below.  When a type is defined on a given
+connection between an Encoder and Decoder, it is assigned a signed integer type
+id.  When Encoder.Encode(v) is called, it makes sure there is an id assigned for
+the type of v and all its elements and then it sends the pair (typeid, encoded-v)
+where typeid is the type id of the encoded type of v and encoded-v is the gob
+encoding of the value v.
+
+To define a type, the encoder chooses an unused, positive type id and sends the
+pair (-type id, encoded-type) where encoded-type is the gob encoding of a wireType
+description, constructed from these types:
+
+	type wireType struct {
+		ArrayT  *ArrayType
+		SliceT  *SliceType
+		StructT *StructType
+		MapT    *MapType
+	}
+	type arrayType struct {
+		CommonType
+		Elem typeId
+		Len  int
+	}
+	type CommonType struct {
+		Name string // the name of the struct type
+		Id  int    // the id of the type, repeated so it's inside the type
+	}
+	type sliceType struct {
+		CommonType
+		Elem typeId
+	}
+	type structType struct {
+		CommonType
+		Field []*fieldType // the fields of the struct.
+	}
+	type fieldType struct {
+		Name string // the name of the field.
+		Id   int    // the type id of the field, which must be already defined
+	}
+	type mapType struct {
+		CommonType
+		Key  typeId
+		Elem typeId
+	}
+
+If there are nested type ids, the types for all inner type ids must be defined
+before the top-level type id is used to describe an encoded-v.
+
+For simplicity in setup, the connection is defined to understand these types a
+priori, as well as the basic gob types int, uint, etc.  Their ids are:
+
+	bool        1
+	int         2
+	uint        3
+	float       4
+	[]byte      5
+	string      6
+	complex     7
+	interface   8
+	// gap for reserved ids.
+	WireType    16
+	ArrayType   17
+	CommonType  18
+	SliceType   19
+	StructType  20
+	FieldType   21
+	// 22 is slice of fieldType.
+	MapType     23
+
+Finally, each message created by a call to Encode is preceded by an encoded
+unsigned integer count of the number of bytes remaining in the message.  After
+the initial type name, interface values are wrapped the same way; in effect, the
+interface value acts like a recursive invocation of Encode.
+
+In summary, a gob stream looks like
+
+	(byteCount (-type id, encoding of a wireType)* (type id, encoding of a value))*
+
+where * signifies zero or more repetitions and the type id of a value must
+be predefined or be defined before the value in the stream.
+
+See "Gobs of data" for a design discussion of the gob wire format:
+http://golang.org/doc/articles/gobs_of_data.html
+*/
+package gob
+
+/*
+Grammar:
+
+Tokens starting with a lower case letter are terminals; int(n)
+and uint(n) represent the signed/unsigned encodings of the value n.
+
+GobStream:
+	DelimitedMessage*
+DelimitedMessage:
+	uint(lengthOfMessage) Message
+Message:
+	TypeSequence TypedValue
+TypeSequence
+	(TypeDefinition DelimitedTypeDefinition*)?
+DelimitedTypeDefinition:
+	uint(lengthOfTypeDefinition) TypeDefinition
+TypedValue:
+	int(typeId) Value
+TypeDefinition:
+	int(-typeId) encodingOfWireType
+Value:
+	SingletonValue | StructValue
+SingletonValue:
+	uint(0) FieldValue
+FieldValue:
+	builtinValue | ArrayValue | MapValue | SliceValue | StructValue | InterfaceValue
+InterfaceValue:
+	NilInterfaceValue | NonNilInterfaceValue
+NilInterfaceValue:
+	uint(0)
+NonNilInterfaceValue:
+	ConcreteTypeName TypeSequence InterfaceContents
+ConcreteTypeName:
+	uint(lengthOfName) [already read=n] name
+InterfaceContents:
+	int(concreteTypeId) DelimitedValue
+DelimitedValue:
+	uint(length) Value
+ArrayValue:
+	uint(n) FieldValue*n [n elements]
+MapValue:
+	uint(n) (FieldValue FieldValue)*n  [n (key, value) pairs]
+SliceValue:
+	uint(n) FieldValue*n [n elements]
+StructValue:
+	(uint(fieldDelta) FieldValue)*
+*/
+
+/*
+For implementers and the curious, here is an encoded example.  Given
+	type Point struct {X, Y int}
+and the value
+	p := Point{22, 33}
+the bytes transmitted that encode p will be:
+	1f ff 81 03 01 01 05 50 6f 69 6e 74 01 ff 82 00
+	01 02 01 01 58 01 04 00 01 01 59 01 04 00 00 00
+	07 ff 82 01 2c 01 42 00
+They are determined as follows.
+
+Since this is the first transmission of type Point, the type descriptor
+for Point itself must be sent before the value.  This is the first type
+we've sent on this Encoder, so it has type id 65 (0 through 64 are
+reserved).
+
+	1f	// This item (a type descriptor) is 31 bytes long.
+	ff 81	// The negative of the id for the type we're defining, -65.
+		// This is one byte (indicated by FF = -1) followed by
+		// ^-65<<1 | 1.  The low 1 bit signals to complement the
+		// rest upon receipt.
+
+	// Now we send a type descriptor, which is itself a struct (wireType).
+	// The type of wireType itself is known (it's built in, as is the type of
+	// all its components), so we just need to send a *value* of type wireType
+	// that represents type "Point".
+	// Here starts the encoding of that value.
+	// Set the field number implicitly to -1; this is done at the beginning
+	// of every struct, including nested structs.
+	03	// Add 3 to field number; now 2 (wireType.structType; this is a struct).
+		// structType starts with an embedded CommonType, which appears
+		// as a regular structure here too.
+	01	// add 1 to field number (now 0); start of embedded CommonType.
+	01	// add 1 to field number (now 0, the name of the type)
+	05	// string is (unsigned) 5 bytes long
+	50 6f 69 6e 74	// wireType.structType.CommonType.name = "Point"
+	01	// add 1 to field number (now 1, the id of the type)
+	ff 82	// wireType.structType.CommonType._id = 65
+	00	// end of embedded wiretype.structType.CommonType struct
+	01	// add 1 to field number (now 1, the field array in wireType.structType)
+	02	// There are two fields in the type (len(structType.field))
+	01	// Start of first field structure; add 1 to get field number 0: field[0].name
+	01	// 1 byte
+	58	// structType.field[0].name = "X"
+	01	// Add 1 to get field number 1: field[0].id
+	04	// structType.field[0].typeId is 2 (signed int).
+	00	// End of structType.field[0]; start structType.field[1]; set field number to -1.
+	01	// Add 1 to get field number 0: field[1].name
+	01	// 1 byte
+	59	// structType.field[1].name = "Y"
+	01	// Add 1 to get field number 1: field[1].id
+	04	// struct.Type.field[1].typeId is 2 (signed int).
+	00	// End of structType.field[1]; end of structType.field.
+	00	// end of wireType.structType structure
+	00	// end of wireType structure
+
+Now we can send the Point value.  Again the field number resets to -1:
+
+	07	// this value is 7 bytes long
+	ff 82	// the type number, 65 (1 byte (-FF) followed by 65<<1)
+	01	// add one to field number, yielding field 0
+	2c	// encoding of signed "22" (0x22 = 44 = 22<<1); Point.x = 22
+	01	// add one to field number, yielding field 1
+	42	// encoding of signed "33" (0x42 = 66 = 33<<1); Point.y = 33
+	00	// end of structure
+
+The type encoding is long and fairly intricate but we send it only once.
+If p is transmitted a second time, the type is already known so the
+output will be just:
+
+	07 ff 82 01 2c 01 42 00
+
+A single non-struct value at top level is transmitted like a field with
+delta tag 0.  For instance, a signed integer with value 3 presented as
+the argument to Encode will emit:
+
+	03 04 00 06
+
+Which represents:
+
+	03	// this value is 3 bytes long
+	04	// the type number, 2, represents an integer
+	00	// tag delta 0
+	06	// value 3
+
+*/
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/dump.go b/third_party/gofrontend/libgo/go/encoding/gob/dump.go
new file mode 100644
index 0000000..17238c9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/dump.go
@@ -0,0 +1,29 @@
+// 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.
+
+// +build ignore
+
+package main
+
+// Need to compile package gob with debug.go to build this program.
+// See comments in debug.go for how to do this.
+
+import (
+	"encoding/gob"
+	"fmt"
+	"os"
+)
+
+func main() {
+	var err error
+	file := os.Stdin
+	if len(os.Args) > 1 {
+		file, err = os.Open(os.Args[1])
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "dump: %s\n", err)
+			os.Exit(1)
+		}
+	}
+	gob.Debug(file)
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/encode.go b/third_party/gofrontend/libgo/go/encoding/gob/encode.go
new file mode 100644
index 0000000..7831c02
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/encode.go
@@ -0,0 +1,760 @@
+// 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 gob
+
+import (
+	"bytes"
+	"encoding"
+	"math"
+	"reflect"
+	"unsafe"
+)
+
+const uint64Size = int(unsafe.Sizeof(uint64(0)))
+
+// encoderState is the global execution state of an instance of the encoder.
+// Field numbers are delta encoded and always increase. The field
+// number is initialized to -1 so 0 comes out as delta(1). A delta of
+// 0 terminates the structure.
+type encoderState struct {
+	enc      *Encoder
+	b        *bytes.Buffer
+	sendZero bool                 // encoding an array element or map key/value pair; send zero values
+	fieldnum int                  // the last field number written.
+	buf      [1 + uint64Size]byte // buffer used by the encoder; here to avoid allocation.
+	next     *encoderState        // for free list
+}
+
+func (enc *Encoder) newEncoderState(b *bytes.Buffer) *encoderState {
+	e := enc.freeList
+	if e == nil {
+		e = new(encoderState)
+		e.enc = enc
+	} else {
+		enc.freeList = e.next
+	}
+	e.sendZero = false
+	e.fieldnum = 0
+	e.b = b
+	return e
+}
+
+func (enc *Encoder) freeEncoderState(e *encoderState) {
+	e.next = enc.freeList
+	enc.freeList = e
+}
+
+// Unsigned integers have a two-state encoding.  If the number is less
+// than 128 (0 through 0x7F), its value is written directly.
+// Otherwise the value is written in big-endian byte order preceded
+// by the byte length, negated.
+
+// encodeUint writes an encoded unsigned integer to state.b.
+func (state *encoderState) encodeUint(x uint64) {
+	if x <= 0x7F {
+		err := state.b.WriteByte(uint8(x))
+		if err != nil {
+			error_(err)
+		}
+		return
+	}
+	i := uint64Size
+	for x > 0 {
+		state.buf[i] = uint8(x)
+		x >>= 8
+		i--
+	}
+	state.buf[i] = uint8(i - uint64Size) // = loop count, negated
+	_, err := state.b.Write(state.buf[i : uint64Size+1])
+	if err != nil {
+		error_(err)
+	}
+}
+
+// encodeInt writes an encoded signed integer to state.w.
+// The low bit of the encoding says whether to bit complement the (other bits of the)
+// uint to recover the int.
+func (state *encoderState) encodeInt(i int64) {
+	var x uint64
+	if i < 0 {
+		x = uint64(^i<<1) | 1
+	} else {
+		x = uint64(i << 1)
+	}
+	state.encodeUint(uint64(x))
+}
+
+// encOp is the signature of an encoding operator for a given type.
+type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer)
+
+// The 'instructions' of the encoding machine
+type encInstr struct {
+	op     encOp
+	field  int     // field number
+	indir  int     // how many pointer indirections to reach the value in the struct
+	offset uintptr // offset in the structure of the field to encode
+}
+
+// update emits a field number and updates the state to record its value for delta encoding.
+// If the instruction pointer is nil, it does nothing
+func (state *encoderState) update(instr *encInstr) {
+	if instr != nil {
+		state.encodeUint(uint64(instr.field - state.fieldnum))
+		state.fieldnum = instr.field
+	}
+}
+
+// Each encoder for a composite is responsible for handling any
+// indirections associated with the elements of the data structure.
+// If any pointer so reached is nil, no bytes are written.  If the
+// data item is zero, no bytes are written.  Single values - ints,
+// strings etc. - are indirected before calling their encoders.
+// Otherwise, the output (for a scalar) is the field number, as an
+// encoded integer, followed by the field data in its appropriate
+// format.
+
+// encIndirect dereferences p indir times and returns the result.
+func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
+	for ; indir > 0; indir-- {
+		p = *(*unsafe.Pointer)(p)
+		if p == nil {
+			return unsafe.Pointer(nil)
+		}
+	}
+	return p
+}
+
+// encBool encodes the bool with address p as an unsigned 0 or 1.
+func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	b := *(*bool)(p)
+	if b || state.sendZero {
+		state.update(i)
+		if b {
+			state.encodeUint(1)
+		} else {
+			state.encodeUint(0)
+		}
+	}
+}
+
+// encInt encodes the int with address p.
+func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := int64(*(*int)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeInt(v)
+	}
+}
+
+// encUint encodes the uint with address p.
+func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := uint64(*(*uint)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encInt8 encodes the int8 with address p.
+func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := int64(*(*int8)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeInt(v)
+	}
+}
+
+// encUint8 encodes the uint8 with address p.
+func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := uint64(*(*uint8)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encInt16 encodes the int16 with address p.
+func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := int64(*(*int16)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeInt(v)
+	}
+}
+
+// encUint16 encodes the uint16 with address p.
+func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := uint64(*(*uint16)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encInt32 encodes the int32 with address p.
+func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := int64(*(*int32)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeInt(v)
+	}
+}
+
+// encUint encodes the uint32 with address p.
+func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := uint64(*(*uint32)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encInt64 encodes the int64 with address p.
+func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := *(*int64)(p)
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeInt(v)
+	}
+}
+
+// encInt64 encodes the uint64 with address p.
+func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := *(*uint64)(p)
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encUintptr encodes the uintptr with address p.
+func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := uint64(*(*uintptr)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// floatBits returns a uint64 holding the bits of a floating-point number.
+// Floating-point numbers are transmitted as uint64s holding the bits
+// of the underlying representation.  They are sent byte-reversed, with
+// the exponent end coming out first, so integer floating point numbers
+// (for example) transmit more compactly.  This routine does the
+// swizzling.
+func floatBits(f float64) uint64 {
+	u := math.Float64bits(f)
+	var v uint64
+	for i := 0; i < 8; i++ {
+		v <<= 8
+		v |= u & 0xFF
+		u >>= 8
+	}
+	return v
+}
+
+// encFloat32 encodes the float32 with address p.
+func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	f := *(*float32)(p)
+	if f != 0 || state.sendZero {
+		v := floatBits(float64(f))
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encFloat64 encodes the float64 with address p.
+func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	f := *(*float64)(p)
+	if f != 0 || state.sendZero {
+		state.update(i)
+		v := floatBits(f)
+		state.encodeUint(v)
+	}
+}
+
+// encComplex64 encodes the complex64 with address p.
+// Complex numbers are just a pair of floating-point numbers, real part first.
+func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	c := *(*complex64)(p)
+	if c != 0+0i || state.sendZero {
+		rpart := floatBits(float64(real(c)))
+		ipart := floatBits(float64(imag(c)))
+		state.update(i)
+		state.encodeUint(rpart)
+		state.encodeUint(ipart)
+	}
+}
+
+// encComplex128 encodes the complex128 with address p.
+func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	c := *(*complex128)(p)
+	if c != 0+0i || state.sendZero {
+		rpart := floatBits(real(c))
+		ipart := floatBits(imag(c))
+		state.update(i)
+		state.encodeUint(rpart)
+		state.encodeUint(ipart)
+	}
+}
+
+// encUint8Array encodes the byte slice whose header has address p.
+// Byte arrays are encoded as an unsigned count followed by the raw bytes.
+func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	b := *(*[]byte)(p)
+	if len(b) > 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(uint64(len(b)))
+		state.b.Write(b)
+	}
+}
+
+// encString encodes the string whose header has address p.
+// Strings are encoded as an unsigned count followed by the raw bytes.
+func encString(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	s := *(*string)(p)
+	if len(s) > 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(uint64(len(s)))
+		state.b.WriteString(s)
+	}
+}
+
+// encStructTerminator encodes the end of an encoded struct
+// as delta field number of 0.
+func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	state.encodeUint(0)
+}
+
+// Execution engine
+
+// encEngine an array of instructions indexed by field number of the encoding
+// data, typically a struct.  It is executed top to bottom, walking the struct.
+type encEngine struct {
+	instr []encInstr
+}
+
+const singletonField = 0
+
+// encodeSingle encodes a single top-level non-struct value.
+func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) {
+	state := enc.newEncoderState(b)
+	state.fieldnum = singletonField
+	// There is no surrounding struct to frame the transmission, so we must
+	// generate data even if the item is zero.  To do this, set sendZero.
+	state.sendZero = true
+	instr := &engine.instr[singletonField]
+	p := basep // offset will be zero
+	if instr.indir > 0 {
+		if p = encIndirect(p, instr.indir); p == nil {
+			return
+		}
+	}
+	instr.op(instr, state, p)
+	enc.freeEncoderState(state)
+}
+
+// encodeStruct encodes a single struct value.
+func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) {
+	state := enc.newEncoderState(b)
+	state.fieldnum = -1
+	for i := 0; i < len(engine.instr); i++ {
+		instr := &engine.instr[i]
+		p := unsafe.Pointer(uintptr(basep) + instr.offset)
+		if instr.indir > 0 {
+			if p = encIndirect(p, instr.indir); p == nil {
+				continue
+			}
+		}
+		instr.op(instr, state, p)
+	}
+	enc.freeEncoderState(state)
+}
+
+// encodeArray encodes the array whose 0th element is at p.
+func (enc *Encoder) encodeArray(b *bytes.Buffer, p unsafe.Pointer, op encOp, elemWid uintptr, elemIndir int, length int) {
+	state := enc.newEncoderState(b)
+	state.fieldnum = -1
+	state.sendZero = true
+	state.encodeUint(uint64(length))
+	for i := 0; i < length; i++ {
+		elemp := p
+		if elemIndir > 0 {
+			up := encIndirect(elemp, elemIndir)
+			if up == nil {
+				errorf("encodeArray: nil element")
+			}
+			elemp = up
+		}
+		op(nil, state, elemp)
+		p = unsafe.Pointer(uintptr(p) + elemWid)
+	}
+	enc.freeEncoderState(state)
+}
+
+// encodeReflectValue is a helper for maps. It encodes the value v.
+func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir int) {
+	for i := 0; i < indir && v.IsValid(); i++ {
+		v = reflect.Indirect(v)
+	}
+	if !v.IsValid() {
+		errorf("encodeReflectValue: nil element")
+	}
+	op(nil, state, unsafeAddr(v))
+}
+
+// encodeMap encodes a map as unsigned count followed by key:value pairs.
+// Because map internals are not exposed, we must use reflection rather than
+// addresses.
+func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp encOp, keyIndir, elemIndir int) {
+	state := enc.newEncoderState(b)
+	state.fieldnum = -1
+	state.sendZero = true
+	keys := mv.MapKeys()
+	state.encodeUint(uint64(len(keys)))
+	for _, key := range keys {
+		encodeReflectValue(state, key, keyOp, keyIndir)
+		encodeReflectValue(state, mv.MapIndex(key), elemOp, elemIndir)
+	}
+	enc.freeEncoderState(state)
+}
+
+// encodeInterface encodes the interface value iv.
+// To send an interface, we send a string identifying the concrete type, followed
+// by the type identifier (which might require defining that type right now), followed
+// by the concrete value.  A nil value gets sent as the empty string for the name,
+// followed by no value.
+func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
+	// Gobs can encode nil interface values but not typed interface
+	// values holding nil pointers, since nil pointers point to no value.
+	elem := iv.Elem()
+	if elem.Kind() == reflect.Ptr && elem.IsNil() {
+		errorf("gob: cannot encode nil pointer of type %s inside interface", iv.Elem().Type())
+	}
+	state := enc.newEncoderState(b)
+	state.fieldnum = -1
+	state.sendZero = true
+	if iv.IsNil() {
+		state.encodeUint(0)
+		return
+	}
+
+	ut := userType(iv.Elem().Type())
+	registerLock.RLock()
+	name, ok := concreteTypeToName[ut.base]
+	registerLock.RUnlock()
+	if !ok {
+		errorf("type not registered for interface: %s", ut.base)
+	}
+	// Send the name.
+	state.encodeUint(uint64(len(name)))
+	_, err := state.b.WriteString(name)
+	if err != nil {
+		error_(err)
+	}
+	// Define the type id if necessary.
+	enc.sendTypeDescriptor(enc.writer(), state, ut)
+	// Send the type id.
+	enc.sendTypeId(state, ut)
+	// Encode the value into a new buffer.  Any nested type definitions
+	// should be written to b, before the encoded value.
+	enc.pushWriter(b)
+	data := new(bytes.Buffer)
+	data.Write(spaceForLength)
+	enc.encode(data, elem, ut)
+	if enc.err != nil {
+		error_(enc.err)
+	}
+	enc.popWriter()
+	enc.writeMessage(b, data)
+	if enc.err != nil {
+		error_(err)
+	}
+	enc.freeEncoderState(state)
+}
+
+// isZero reports whether the value is the zero of its type.
+func isZero(val reflect.Value) bool {
+	switch val.Kind() {
+	case reflect.Array:
+		for i := 0; i < val.Len(); i++ {
+			if !isZero(val.Index(i)) {
+				return false
+			}
+		}
+		return true
+	case reflect.Map, reflect.Slice, reflect.String:
+		return val.Len() == 0
+	case reflect.Bool:
+		return !val.Bool()
+	case reflect.Complex64, reflect.Complex128:
+		return val.Complex() == 0
+	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr:
+		return val.IsNil()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return val.Int() == 0
+	case reflect.Float32, reflect.Float64:
+		return val.Float() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return val.Uint() == 0
+	case reflect.Struct:
+		for i := 0; i < val.NumField(); i++ {
+			if !isZero(val.Field(i)) {
+				return false
+			}
+		}
+		return true
+	}
+	panic("unknown type in isZero " + val.Type().String())
+}
+
+// encGobEncoder encodes a value that implements the GobEncoder interface.
+// The data is sent as a byte array.
+func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, ut *userTypeInfo, v reflect.Value) {
+	// TODO: should we catch panics from the called method?
+
+	var data []byte
+	var err error
+	// We know it's one of these.
+	switch ut.externalEnc {
+	case xGob:
+		data, err = v.Interface().(GobEncoder).GobEncode()
+	case xBinary:
+		data, err = v.Interface().(encoding.BinaryMarshaler).MarshalBinary()
+	case xText:
+		data, err = v.Interface().(encoding.TextMarshaler).MarshalText()
+	}
+	if err != nil {
+		error_(err)
+	}
+	state := enc.newEncoderState(b)
+	state.fieldnum = -1
+	state.encodeUint(uint64(len(data)))
+	state.b.Write(data)
+	enc.freeEncoderState(state)
+}
+
+var encOpTable = [...]encOp{
+	reflect.Bool:       encBool,
+	reflect.Int:        encInt,
+	reflect.Int8:       encInt8,
+	reflect.Int16:      encInt16,
+	reflect.Int32:      encInt32,
+	reflect.Int64:      encInt64,
+	reflect.Uint:       encUint,
+	reflect.Uint8:      encUint8,
+	reflect.Uint16:     encUint16,
+	reflect.Uint32:     encUint32,
+	reflect.Uint64:     encUint64,
+	reflect.Uintptr:    encUintptr,
+	reflect.Float32:    encFloat32,
+	reflect.Float64:    encFloat64,
+	reflect.Complex64:  encComplex64,
+	reflect.Complex128: encComplex128,
+	reflect.String:     encString,
+}
+
+// encOpFor returns (a pointer to) the encoding op for the base type under rt and
+// the indirection count to reach it.
+func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) {
+	ut := userType(rt)
+	// If the type implements GobEncoder, we handle it without further processing.
+	if ut.externalEnc != 0 {
+		return enc.gobEncodeOpFor(ut)
+	}
+	// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
+	// Return the pointer to the op we're already building.
+	if opPtr := inProgress[rt]; opPtr != nil {
+		return opPtr, ut.indir
+	}
+	typ := ut.base
+	indir := ut.indir
+	k := typ.Kind()
+	var op encOp
+	if int(k) < len(encOpTable) {
+		op = encOpTable[k]
+	}
+	if op == nil {
+		inProgress[rt] = &op
+		// Special cases
+		switch t := typ; t.Kind() {
+		case reflect.Slice:
+			if t.Elem().Kind() == reflect.Uint8 {
+				op = encUint8Array
+				break
+			}
+			// Slices have a header; we decode it to find the underlying array.
+			elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress)
+			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+				slice := (*reflect.SliceHeader)(p)
+				if !state.sendZero && slice.Len == 0 {
+					return
+				}
+				state.update(i)
+				state.enc.encodeArray(state.b, unsafe.Pointer(slice.Data), *elemOp, t.Elem().Size(), elemIndir, int(slice.Len))
+			}
+		case reflect.Array:
+			// True arrays have size in the type.
+			elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress)
+			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+				state.update(i)
+				state.enc.encodeArray(state.b, p, *elemOp, t.Elem().Size(), elemIndir, t.Len())
+			}
+		case reflect.Map:
+			keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress)
+			elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress)
+			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+				// Maps cannot be accessed by moving addresses around the way
+				// that slices etc. can.  We must recover a full reflection value for
+				// the iteration.
+				v := reflect.NewAt(t, unsafe.Pointer(p)).Elem()
+				mv := reflect.Indirect(v)
+				// We send zero-length (but non-nil) maps because the
+				// receiver might want to use the map.  (Maps don't use append.)
+				if !state.sendZero && mv.IsNil() {
+					return
+				}
+				state.update(i)
+				state.enc.encodeMap(state.b, mv, *keyOp, *elemOp, keyIndir, elemIndir)
+			}
+		case reflect.Struct:
+			// Generate a closure that calls out to the engine for the nested type.
+			enc.getEncEngine(userType(typ))
+			info := mustGetTypeInfo(typ)
+			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+				state.update(i)
+				// indirect through info to delay evaluation for recursive structs
+				state.enc.encodeStruct(state.b, info.encoder, p)
+			}
+		case reflect.Interface:
+			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+				// Interfaces transmit the name and contents of the concrete
+				// value they contain.
+				v := reflect.NewAt(t, unsafe.Pointer(p)).Elem()
+				iv := reflect.Indirect(v)
+				if !state.sendZero && (!iv.IsValid() || iv.IsNil()) {
+					return
+				}
+				state.update(i)
+				state.enc.encodeInterface(state.b, iv)
+			}
+		}
+	}
+	if op == nil {
+		errorf("can't happen: encode type %s", rt)
+	}
+	return &op, indir
+}
+
+// gobEncodeOpFor returns the op for a type that is known to implement
+// GobEncoder.
+func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
+	rt := ut.user
+	if ut.encIndir == -1 {
+		rt = reflect.PtrTo(rt)
+	} else if ut.encIndir > 0 {
+		for i := int8(0); i < ut.encIndir; i++ {
+			rt = rt.Elem()
+		}
+	}
+	var op encOp
+	op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+		var v reflect.Value
+		if ut.encIndir == -1 {
+			// Need to climb up one level to turn value into pointer.
+			v = reflect.NewAt(rt, unsafe.Pointer(&p)).Elem()
+		} else {
+			v = reflect.NewAt(rt, p).Elem()
+		}
+		if !state.sendZero && isZero(v) {
+			return
+		}
+		state.update(i)
+		state.enc.encodeGobEncoder(state.b, ut, v)
+	}
+	return &op, int(ut.encIndir) // encIndir: op will get called with p == address of receiver.
+}
+
+// compileEnc returns the engine to compile the type.
+func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
+	srt := ut.base
+	engine := new(encEngine)
+	seen := make(map[reflect.Type]*encOp)
+	rt := ut.base
+	if ut.externalEnc != 0 {
+		rt = ut.user
+	}
+	if ut.externalEnc == 0 && srt.Kind() == reflect.Struct {
+		for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); fieldNum++ {
+			f := srt.Field(fieldNum)
+			if !isSent(&f) {
+				continue
+			}
+			op, indir := enc.encOpFor(f.Type, seen)
+			engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, indir, uintptr(f.Offset)})
+			wireFieldNum++
+		}
+		if srt.NumField() > 0 && len(engine.instr) == 0 {
+			errorf("type %s has no exported fields", rt)
+		}
+		engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, 0, 0})
+	} else {
+		engine.instr = make([]encInstr, 1)
+		op, indir := enc.encOpFor(rt, seen)
+		engine.instr[0] = encInstr{*op, singletonField, indir, 0} // offset is zero
+	}
+	return engine
+}
+
+// getEncEngine returns the engine to compile the type.
+// typeLock must be held (or we're in initialization and guaranteed single-threaded).
+func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine {
+	info, err1 := getTypeInfo(ut)
+	if err1 != nil {
+		error_(err1)
+	}
+	if info.encoder == nil {
+		// Assign the encEngine now, so recursive types work correctly. But...
+		info.encoder = new(encEngine)
+		// ... if we fail to complete building the engine, don't cache the half-built machine.
+		// Doing this here means we won't cache a type that is itself OK but
+		// that contains a nested type that won't compile. The result is consistent
+		// error behavior when Encode is called multiple times on the top-level type.
+		ok := false
+		defer func() {
+			if !ok {
+				info.encoder = nil
+			}
+		}()
+		info.encoder = enc.compileEnc(ut)
+		ok = true
+	}
+	return info.encoder
+}
+
+// lockAndGetEncEngine is a function that locks and compiles.
+// This lets us hold the lock only while compiling, not when encoding.
+func (enc *Encoder) lockAndGetEncEngine(ut *userTypeInfo) *encEngine {
+	typeLock.Lock()
+	defer typeLock.Unlock()
+	return enc.getEncEngine(ut)
+}
+
+func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInfo) {
+	defer catchError(&enc.err)
+	engine := enc.lockAndGetEncEngine(ut)
+	indir := ut.indir
+	if ut.externalEnc != 0 {
+		indir = int(ut.encIndir)
+	}
+	for i := 0; i < indir; i++ {
+		value = reflect.Indirect(value)
+	}
+	if ut.externalEnc == 0 && value.Type().Kind() == reflect.Struct {
+		enc.encodeStruct(b, engine, unsafeAddr(value))
+	} else {
+		enc.encodeSingle(b, engine, unsafeAddr(value))
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/encoder.go b/third_party/gofrontend/libgo/go/encoding/gob/encoder.go
new file mode 100644
index 0000000..a3301c3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/encoder.go
@@ -0,0 +1,253 @@
+// 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 gob
+
+import (
+	"bytes"
+	"io"
+	"reflect"
+	"sync"
+)
+
+// An Encoder manages the transmission of type and data information to the
+// other side of a connection.
+type Encoder struct {
+	mutex      sync.Mutex              // each item must be sent atomically
+	w          []io.Writer             // where to send the data
+	sent       map[reflect.Type]typeId // which types we've already sent
+	countState *encoderState           // stage for writing counts
+	freeList   *encoderState           // list of free encoderStates; avoids reallocation
+	byteBuf    bytes.Buffer            // buffer for top-level encoderState
+	err        error
+}
+
+// Before we encode a message, we reserve space at the head of the
+// buffer in which to encode its length. This means we can use the
+// buffer to assemble the message without another allocation.
+const maxLength = 9 // Maximum size of an encoded length.
+var spaceForLength = make([]byte, maxLength)
+
+// NewEncoder returns a new encoder that will transmit on the io.Writer.
+func NewEncoder(w io.Writer) *Encoder {
+	enc := new(Encoder)
+	enc.w = []io.Writer{w}
+	enc.sent = make(map[reflect.Type]typeId)
+	enc.countState = enc.newEncoderState(new(bytes.Buffer))
+	return enc
+}
+
+// writer() returns the innermost writer the encoder is using
+func (enc *Encoder) writer() io.Writer {
+	return enc.w[len(enc.w)-1]
+}
+
+// pushWriter adds a writer to the encoder.
+func (enc *Encoder) pushWriter(w io.Writer) {
+	enc.w = append(enc.w, w)
+}
+
+// popWriter pops the innermost writer.
+func (enc *Encoder) popWriter() {
+	enc.w = enc.w[0 : len(enc.w)-1]
+}
+
+func (enc *Encoder) setError(err error) {
+	if enc.err == nil { // remember the first.
+		enc.err = err
+	}
+}
+
+// writeMessage sends the data item preceded by a unsigned count of its length.
+func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) {
+	// Space has been reserved for the length at the head of the message.
+	// This is a little dirty: we grab the slice from the bytes.Buffer and massage
+	// it by hand.
+	message := b.Bytes()
+	messageLen := len(message) - maxLength
+	// Encode the length.
+	enc.countState.b.Reset()
+	enc.countState.encodeUint(uint64(messageLen))
+	// Copy the length to be a prefix of the message.
+	offset := maxLength - enc.countState.b.Len()
+	copy(message[offset:], enc.countState.b.Bytes())
+	// Write the data.
+	_, err := w.Write(message[offset:])
+	// Drain the buffer and restore the space at the front for the count of the next message.
+	b.Reset()
+	b.Write(spaceForLength)
+	if err != nil {
+		enc.setError(err)
+	}
+}
+
+// sendActualType sends the requested type, without further investigation, unless
+// it's been sent before.
+func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTypeInfo, actual reflect.Type) (sent bool) {
+	if _, alreadySent := enc.sent[actual]; alreadySent {
+		return false
+	}
+	typeLock.Lock()
+	info, err := getTypeInfo(ut)
+	typeLock.Unlock()
+	if err != nil {
+		enc.setError(err)
+		return
+	}
+	// Send the pair (-id, type)
+	// Id:
+	state.encodeInt(-int64(info.id))
+	// Type:
+	enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo)
+	enc.writeMessage(w, state.b)
+	if enc.err != nil {
+		return
+	}
+
+	// Remember we've sent this type, both what the user gave us and the base type.
+	enc.sent[ut.base] = info.id
+	if ut.user != ut.base {
+		enc.sent[ut.user] = info.id
+	}
+	// Now send the inner types
+	switch st := actual; st.Kind() {
+	case reflect.Struct:
+		for i := 0; i < st.NumField(); i++ {
+			if isExported(st.Field(i).Name) {
+				enc.sendType(w, state, st.Field(i).Type)
+			}
+		}
+	case reflect.Array, reflect.Slice:
+		enc.sendType(w, state, st.Elem())
+	case reflect.Map:
+		enc.sendType(w, state, st.Key())
+		enc.sendType(w, state, st.Elem())
+	}
+	return true
+}
+
+// sendType sends the type info to the other side, if necessary.
+func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) {
+	ut := userType(origt)
+	if ut.externalEnc != 0 {
+		// The rules are different: regardless of the underlying type's representation,
+		// we need to tell the other side that the base type is a GobEncoder.
+		return enc.sendActualType(w, state, ut, ut.base)
+	}
+
+	// It's a concrete value, so drill down to the base type.
+	switch rt := ut.base; rt.Kind() {
+	default:
+		// Basic types and interfaces do not need to be described.
+		return
+	case reflect.Slice:
+		// If it's []uint8, don't send; it's considered basic.
+		if rt.Elem().Kind() == reflect.Uint8 {
+			return
+		}
+		// Otherwise we do send.
+		break
+	case reflect.Array:
+		// arrays must be sent so we know their lengths and element types.
+		break
+	case reflect.Map:
+		// maps must be sent so we know their lengths and key/value types.
+		break
+	case reflect.Struct:
+		// structs must be sent so we know their fields.
+		break
+	case reflect.Chan, reflect.Func:
+		// If we get here, it's a field of a struct; ignore it.
+		return
+	}
+
+	return enc.sendActualType(w, state, ut, ut.base)
+}
+
+// Encode transmits the data item represented by the empty interface value,
+// guaranteeing that all necessary type information has been transmitted first.
+func (enc *Encoder) Encode(e interface{}) error {
+	return enc.EncodeValue(reflect.ValueOf(e))
+}
+
+// sendTypeDescriptor makes sure the remote side knows about this type.
+// It will send a descriptor if this is the first time the type has been
+// sent.
+func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *userTypeInfo) {
+	// Make sure the type is known to the other side.
+	// First, have we already sent this type?
+	rt := ut.base
+	if ut.externalEnc != 0 {
+		rt = ut.user
+	}
+	if _, alreadySent := enc.sent[rt]; !alreadySent {
+		// No, so send it.
+		sent := enc.sendType(w, state, rt)
+		if enc.err != nil {
+			return
+		}
+		// If the type info has still not been transmitted, it means we have
+		// a singleton basic type (int, []byte etc.) at top level.  We don't
+		// need to send the type info but we do need to update enc.sent.
+		if !sent {
+			typeLock.Lock()
+			info, err := getTypeInfo(ut)
+			typeLock.Unlock()
+			if err != nil {
+				enc.setError(err)
+				return
+			}
+			enc.sent[rt] = info.id
+		}
+	}
+}
+
+// sendTypeId sends the id, which must have already been defined.
+func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) {
+	// Identify the type of this top-level value.
+	state.encodeInt(int64(enc.sent[ut.base]))
+}
+
+// EncodeValue transmits the data item represented by the reflection value,
+// guaranteeing that all necessary type information has been transmitted first.
+func (enc *Encoder) EncodeValue(value reflect.Value) error {
+	// Gobs contain values. They cannot represent nil pointers, which
+	// have no value to encode.
+	if value.Kind() == reflect.Ptr && value.IsNil() {
+		panic("gob: cannot encode nil pointer of type " + value.Type().String())
+	}
+
+	// Make sure we're single-threaded through here, so multiple
+	// goroutines can share an encoder.
+	enc.mutex.Lock()
+	defer enc.mutex.Unlock()
+
+	// Remove any nested writers remaining due to previous errors.
+	enc.w = enc.w[0:1]
+
+	ut, err := validUserType(value.Type())
+	if err != nil {
+		return err
+	}
+
+	enc.err = nil
+	enc.byteBuf.Reset()
+	enc.byteBuf.Write(spaceForLength)
+	state := enc.newEncoderState(&enc.byteBuf)
+
+	enc.sendTypeDescriptor(enc.writer(), state, ut)
+	enc.sendTypeId(state, ut)
+	if enc.err != nil {
+		return enc.err
+	}
+
+	// Encode the object.
+	enc.encode(state.b, value, ut)
+	if enc.err == nil {
+		enc.writeMessage(enc.writer(), state.b)
+	}
+
+	enc.freeEncoderState(state)
+	return enc.err
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/encoder_test.go b/third_party/gofrontend/libgo/go/encoding/gob/encoder_test.go
new file mode 100644
index 0000000..6445ce1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/encoder_test.go
@@ -0,0 +1,862 @@
+// 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 gob
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+type ET2 struct {
+	X string
+}
+
+type ET1 struct {
+	A    int
+	Et2  *ET2
+	Next *ET1
+}
+
+// Like ET1 but with a different name for a field
+type ET3 struct {
+	A             int
+	Et2           *ET2
+	DifferentNext *ET1
+}
+
+// Like ET1 but with a different type for a field
+type ET4 struct {
+	A    int
+	Et2  float64
+	Next int
+}
+
+func TestEncoderDecoder(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	et1 := new(ET1)
+	et1.A = 7
+	et1.Et2 = new(ET2)
+	err := enc.Encode(et1)
+	if err != nil {
+		t.Error("encoder fail:", err)
+	}
+	dec := NewDecoder(b)
+	newEt1 := new(ET1)
+	err = dec.Decode(newEt1)
+	if err != nil {
+		t.Fatal("error decoding ET1:", err)
+	}
+
+	if !reflect.DeepEqual(et1, newEt1) {
+		t.Fatalf("invalid data for et1: expected %+v; got %+v", *et1, *newEt1)
+	}
+	if b.Len() != 0 {
+		t.Error("not at eof;", b.Len(), "bytes left")
+	}
+
+	enc.Encode(et1)
+	newEt1 = new(ET1)
+	err = dec.Decode(newEt1)
+	if err != nil {
+		t.Fatal("round 2: error decoding ET1:", err)
+	}
+	if !reflect.DeepEqual(et1, newEt1) {
+		t.Fatalf("round 2: invalid data for et1: expected %+v; got %+v", *et1, *newEt1)
+	}
+	if b.Len() != 0 {
+		t.Error("round 2: not at eof;", b.Len(), "bytes left")
+	}
+
+	// Now test with a running encoder/decoder pair that we recognize a type mismatch.
+	err = enc.Encode(et1)
+	if err != nil {
+		t.Error("round 3: encoder fail:", err)
+	}
+	newEt2 := new(ET2)
+	err = dec.Decode(newEt2)
+	if err == nil {
+		t.Fatal("round 3: expected `bad type' error decoding ET2")
+	}
+}
+
+// Run one value through the encoder/decoder, but use the wrong type.
+// Input is always an ET1; we compare it to whatever is under 'e'.
+func badTypeCheck(e interface{}, shouldFail bool, msg string, t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	et1 := new(ET1)
+	et1.A = 7
+	et1.Et2 = new(ET2)
+	err := enc.Encode(et1)
+	if err != nil {
+		t.Error("encoder fail:", err)
+	}
+	dec := NewDecoder(b)
+	err = dec.Decode(e)
+	if shouldFail && err == nil {
+		t.Error("expected error for", msg)
+	}
+	if !shouldFail && err != nil {
+		t.Error("unexpected error for", msg, err)
+	}
+}
+
+// Test that we recognize a bad type the first time.
+func TestWrongTypeDecoder(t *testing.T) {
+	badTypeCheck(new(ET2), true, "no fields in common", t)
+	badTypeCheck(new(ET3), false, "different name of field", t)
+	badTypeCheck(new(ET4), true, "different type of field", t)
+}
+
+func corruptDataCheck(s string, err error, t *testing.T) {
+	b := bytes.NewBufferString(s)
+	dec := NewDecoder(b)
+	err1 := dec.Decode(new(ET2))
+	if err1 != err {
+		t.Errorf("from %q expected error %s; got %s", s, err, err1)
+	}
+}
+
+// Check that we survive bad data.
+func TestBadData(t *testing.T) {
+	corruptDataCheck("", io.EOF, t)
+	corruptDataCheck("\x7Fhi", io.ErrUnexpectedEOF, t)
+	corruptDataCheck("\x03now is the time for all good men", errBadType, t)
+	// issue 6323.
+	corruptDataCheck("\x04\x24foo", errRange, t)
+}
+
+// Types not supported at top level by the Encoder.
+var unsupportedValues = []interface{}{
+	make(chan int),
+	func(a int) bool { return true },
+}
+
+func TestUnsupported(t *testing.T) {
+	var b bytes.Buffer
+	enc := NewEncoder(&b)
+	for _, v := range unsupportedValues {
+		err := enc.Encode(v)
+		if err == nil {
+			t.Errorf("expected error for %T; got none", v)
+		}
+	}
+}
+
+func encAndDec(in, out interface{}) error {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(in)
+	if err != nil {
+		return err
+	}
+	dec := NewDecoder(b)
+	err = dec.Decode(out)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func TestTypeToPtrType(t *testing.T) {
+	// Encode a T, decode a *T
+	type Type0 struct {
+		A int
+	}
+	t0 := Type0{7}
+	t0p := new(Type0)
+	if err := encAndDec(t0, t0p); err != nil {
+		t.Error(err)
+	}
+}
+
+func TestPtrTypeToType(t *testing.T) {
+	// Encode a *T, decode a T
+	type Type1 struct {
+		A uint
+	}
+	t1p := &Type1{17}
+	var t1 Type1
+	if err := encAndDec(t1, t1p); err != nil {
+		t.Error(err)
+	}
+}
+
+func TestTypeToPtrPtrPtrPtrType(t *testing.T) {
+	type Type2 struct {
+		A ****float64
+	}
+	t2 := Type2{}
+	t2.A = new(***float64)
+	*t2.A = new(**float64)
+	**t2.A = new(*float64)
+	***t2.A = new(float64)
+	****t2.A = 27.4
+	t2pppp := new(***Type2)
+	if err := encAndDec(t2, t2pppp); err != nil {
+		t.Fatal(err)
+	}
+	if ****(****t2pppp).A != ****t2.A {
+		t.Errorf("wrong value after decode: %g not %g", ****(****t2pppp).A, ****t2.A)
+	}
+}
+
+func TestSlice(t *testing.T) {
+	type Type3 struct {
+		A []string
+	}
+	t3p := &Type3{[]string{"hello", "world"}}
+	var t3 Type3
+	if err := encAndDec(t3, t3p); err != nil {
+		t.Error(err)
+	}
+}
+
+func TestValueError(t *testing.T) {
+	// Encode a *T, decode a T
+	type Type4 struct {
+		A int
+	}
+	t4p := &Type4{3}
+	var t4 Type4 // note: not a pointer.
+	if err := encAndDec(t4p, t4); err == nil || strings.Index(err.Error(), "pointer") < 0 {
+		t.Error("expected error about pointer; got", err)
+	}
+}
+
+func TestArray(t *testing.T) {
+	type Type5 struct {
+		A [3]string
+		B [3]byte
+	}
+	type Type6 struct {
+		A [2]string // can't hold t5.a
+	}
+	t5 := Type5{[3]string{"hello", ",", "world"}, [3]byte{1, 2, 3}}
+	var t5p Type5
+	if err := encAndDec(t5, &t5p); err != nil {
+		t.Error(err)
+	}
+	var t6 Type6
+	if err := encAndDec(t5, &t6); err == nil {
+		t.Error("should fail with mismatched array sizes")
+	}
+}
+
+func TestRecursiveMapType(t *testing.T) {
+	type recursiveMap map[string]recursiveMap
+	r1 := recursiveMap{"A": recursiveMap{"B": nil, "C": nil}, "D": nil}
+	r2 := make(recursiveMap)
+	if err := encAndDec(r1, &r2); err != nil {
+		t.Error(err)
+	}
+}
+
+func TestRecursiveSliceType(t *testing.T) {
+	type recursiveSlice []recursiveSlice
+	r1 := recursiveSlice{0: recursiveSlice{0: nil}, 1: nil}
+	r2 := make(recursiveSlice, 0)
+	if err := encAndDec(r1, &r2); err != nil {
+		t.Error(err)
+	}
+}
+
+// Regression test for bug: must send zero values inside arrays
+func TestDefaultsInArray(t *testing.T) {
+	type Type7 struct {
+		B []bool
+		I []int
+		S []string
+		F []float64
+	}
+	t7 := Type7{
+		[]bool{false, false, true},
+		[]int{0, 0, 1},
+		[]string{"hi", "", "there"},
+		[]float64{0, 0, 1},
+	}
+	var t7p Type7
+	if err := encAndDec(t7, &t7p); err != nil {
+		t.Error(err)
+	}
+}
+
+var testInt int
+var testFloat32 float32
+var testString string
+var testSlice []string
+var testMap map[string]int
+var testArray [7]int
+
+type SingleTest struct {
+	in  interface{}
+	out interface{}
+	err string
+}
+
+var singleTests = []SingleTest{
+	{17, &testInt, ""},
+	{float32(17.5), &testFloat32, ""},
+	{"bike shed", &testString, ""},
+	{[]string{"bike", "shed", "paint", "color"}, &testSlice, ""},
+	{map[string]int{"seven": 7, "twelve": 12}, &testMap, ""},
+	{[7]int{4, 55, 0, 0, 0, 0, 0}, &testArray, ""}, // case that once triggered a bug
+	{[7]int{4, 55, 1, 44, 22, 66, 1234}, &testArray, ""},
+
+	// Decode errors
+	{172, &testFloat32, "type"},
+}
+
+func TestSingletons(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	dec := NewDecoder(b)
+	for _, test := range singleTests {
+		b.Reset()
+		err := enc.Encode(test.in)
+		if err != nil {
+			t.Errorf("error encoding %v: %s", test.in, err)
+			continue
+		}
+		err = dec.Decode(test.out)
+		switch {
+		case err != nil && test.err == "":
+			t.Errorf("error decoding %v: %s", test.in, err)
+			continue
+		case err == nil && test.err != "":
+			t.Errorf("expected error decoding %v: %s", test.in, test.err)
+			continue
+		case err != nil && test.err != "":
+			if strings.Index(err.Error(), test.err) < 0 {
+				t.Errorf("wrong error decoding %v: wanted %s, got %v", test.in, test.err, err)
+			}
+			continue
+		}
+		// Get rid of the pointer in the rhs
+		val := reflect.ValueOf(test.out).Elem().Interface()
+		if !reflect.DeepEqual(test.in, val) {
+			t.Errorf("decoding singleton: expected %v got %v", test.in, val)
+		}
+	}
+}
+
+func TestStructNonStruct(t *testing.T) {
+	type Struct struct {
+		A string
+	}
+	type NonStruct string
+	s := Struct{"hello"}
+	var sp Struct
+	if err := encAndDec(s, &sp); err != nil {
+		t.Error(err)
+	}
+	var ns NonStruct
+	if err := encAndDec(s, &ns); err == nil {
+		t.Error("should get error for struct/non-struct")
+	} else if strings.Index(err.Error(), "type") < 0 {
+		t.Error("for struct/non-struct expected type error; got", err)
+	}
+	// Now try the other way
+	var nsp NonStruct
+	if err := encAndDec(ns, &nsp); err != nil {
+		t.Error(err)
+	}
+	if err := encAndDec(ns, &s); err == nil {
+		t.Error("should get error for non-struct/struct")
+	} else if strings.Index(err.Error(), "type") < 0 {
+		t.Error("for non-struct/struct expected type error; got", err)
+	}
+}
+
+type interfaceIndirectTestI interface {
+	F() bool
+}
+
+type interfaceIndirectTestT struct{}
+
+func (this *interfaceIndirectTestT) F() bool {
+	return true
+}
+
+// A version of a bug reported on golang-nuts.  Also tests top-level
+// slice of interfaces.  The issue was registering *T caused T to be
+// stored as the concrete type.
+func TestInterfaceIndirect(t *testing.T) {
+	Register(&interfaceIndirectTestT{})
+	b := new(bytes.Buffer)
+	w := []interfaceIndirectTestI{&interfaceIndirectTestT{}}
+	err := NewEncoder(b).Encode(w)
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+
+	var r []interfaceIndirectTestI
+	err = NewDecoder(b).Decode(&r)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+}
+
+// Now follow various tests that decode into things that can't represent the
+// encoded value, all of which should be legal.
+
+// Also, when the ignored object contains an interface value, it may define
+// types. Make sure that skipping the value still defines the types by using
+// the encoder/decoder pair to send a value afterwards.  If an interface
+// is sent, its type in the test is always NewType0, so this checks that the
+// encoder and decoder don't skew with respect to type definitions.
+
+type Struct0 struct {
+	I interface{}
+}
+
+type NewType0 struct {
+	S string
+}
+
+type ignoreTest struct {
+	in, out interface{}
+}
+
+var ignoreTests = []ignoreTest{
+	// Decode normal struct into an empty struct
+	{&struct{ A int }{23}, &struct{}{}},
+	// Decode normal struct into a nil.
+	{&struct{ A int }{23}, nil},
+	// Decode singleton string into a nil.
+	{"hello, world", nil},
+	// Decode singleton slice into a nil.
+	{[]int{1, 2, 3, 4}, nil},
+	// Decode struct containing an interface into a nil.
+	{&Struct0{&NewType0{"value0"}}, nil},
+	// Decode singleton slice of interfaces into a nil.
+	{[]interface{}{"hi", &NewType0{"value1"}, 23}, nil},
+}
+
+func TestDecodeIntoNothing(t *testing.T) {
+	Register(new(NewType0))
+	for i, test := range ignoreTests {
+		b := new(bytes.Buffer)
+		enc := NewEncoder(b)
+		err := enc.Encode(test.in)
+		if err != nil {
+			t.Errorf("%d: encode error %s:", i, err)
+			continue
+		}
+		dec := NewDecoder(b)
+		err = dec.Decode(test.out)
+		if err != nil {
+			t.Errorf("%d: decode error: %s", i, err)
+			continue
+		}
+		// Now see if the encoder and decoder are in a consistent state.
+		str := fmt.Sprintf("Value %d", i)
+		err = enc.Encode(&NewType0{str})
+		if err != nil {
+			t.Fatalf("%d: NewType0 encode error: %s", i, err)
+		}
+		ns := new(NewType0)
+		err = dec.Decode(ns)
+		if err != nil {
+			t.Fatalf("%d: NewType0 decode error: %s", i, err)
+		}
+		if ns.S != str {
+			t.Fatalf("%d: expected %q got %q", i, str, ns.S)
+		}
+	}
+}
+
+// Another bug from golang-nuts, involving nested interfaces.
+type Bug0Outer struct {
+	Bug0Field interface{}
+}
+
+type Bug0Inner struct {
+	A int
+}
+
+func TestNestedInterfaces(t *testing.T) {
+	var buf bytes.Buffer
+	e := NewEncoder(&buf)
+	d := NewDecoder(&buf)
+	Register(new(Bug0Outer))
+	Register(new(Bug0Inner))
+	f := &Bug0Outer{&Bug0Outer{&Bug0Inner{7}}}
+	var v interface{} = f
+	err := e.Encode(&v)
+	if err != nil {
+		t.Fatal("Encode:", err)
+	}
+	err = d.Decode(&v)
+	if err != nil {
+		t.Fatal("Decode:", err)
+	}
+	// Make sure it decoded correctly.
+	outer1, ok := v.(*Bug0Outer)
+	if !ok {
+		t.Fatalf("v not Bug0Outer: %T", v)
+	}
+	outer2, ok := outer1.Bug0Field.(*Bug0Outer)
+	if !ok {
+		t.Fatalf("v.Bug0Field not Bug0Outer: %T", outer1.Bug0Field)
+	}
+	inner, ok := outer2.Bug0Field.(*Bug0Inner)
+	if !ok {
+		t.Fatalf("v.Bug0Field.Bug0Field not Bug0Inner: %T", outer2.Bug0Field)
+	}
+	if inner.A != 7 {
+		t.Fatalf("final value %d; expected %d", inner.A, 7)
+	}
+}
+
+// The bugs keep coming. We forgot to send map subtypes before the map.
+
+type Bug1Elem struct {
+	Name string
+	Id   int
+}
+
+type Bug1StructMap map[string]Bug1Elem
+
+func bug1EncDec(in Bug1StructMap, out *Bug1StructMap) error {
+	return nil
+}
+
+func TestMapBug1(t *testing.T) {
+	in := make(Bug1StructMap)
+	in["val1"] = Bug1Elem{"elem1", 1}
+	in["val2"] = Bug1Elem{"elem2", 2}
+
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(in)
+	if err != nil {
+		t.Fatal("encode:", err)
+	}
+	dec := NewDecoder(b)
+	out := make(Bug1StructMap)
+	err = dec.Decode(&out)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if !reflect.DeepEqual(in, out) {
+		t.Errorf("mismatch: %v %v", in, out)
+	}
+}
+
+func TestGobMapInterfaceEncode(t *testing.T) {
+	m := map[string]interface{}{
+		"up": uintptr(0),
+		"i0": []int{-1},
+		"i1": []int8{-1},
+		"i2": []int16{-1},
+		"i3": []int32{-1},
+		"i4": []int64{-1},
+		"u0": []uint{1},
+		"u1": []uint8{1},
+		"u2": []uint16{1},
+		"u3": []uint32{1},
+		"u4": []uint64{1},
+		"f0": []float32{1},
+		"f1": []float64{1},
+		"c0": []complex64{complex(2, -2)},
+		"c1": []complex128{complex(2, float64(-2))},
+		"us": []uintptr{0},
+		"bo": []bool{false},
+		"st": []string{"s"},
+	}
+	enc := NewEncoder(new(bytes.Buffer))
+	err := enc.Encode(m)
+	if err != nil {
+		t.Errorf("encode map: %s", err)
+	}
+}
+
+func TestSliceReusesMemory(t *testing.T) {
+	buf := new(bytes.Buffer)
+	// Bytes
+	{
+		x := []byte("abcd")
+		enc := NewEncoder(buf)
+		err := enc.Encode(x)
+		if err != nil {
+			t.Errorf("bytes: encode: %s", err)
+		}
+		// Decode into y, which is big enough.
+		y := []byte("ABCDE")
+		addr := &y[0]
+		dec := NewDecoder(buf)
+		err = dec.Decode(&y)
+		if err != nil {
+			t.Fatal("bytes: decode:", err)
+		}
+		if !bytes.Equal(x, y) {
+			t.Errorf("bytes: expected %q got %q\n", x, y)
+		}
+		if addr != &y[0] {
+			t.Errorf("bytes: unnecessary reallocation")
+		}
+	}
+	// general slice
+	{
+		x := []rune("abcd")
+		enc := NewEncoder(buf)
+		err := enc.Encode(x)
+		if err != nil {
+			t.Errorf("ints: encode: %s", err)
+		}
+		// Decode into y, which is big enough.
+		y := []rune("ABCDE")
+		addr := &y[0]
+		dec := NewDecoder(buf)
+		err = dec.Decode(&y)
+		if err != nil {
+			t.Fatal("ints: decode:", err)
+		}
+		if !reflect.DeepEqual(x, y) {
+			t.Errorf("ints: expected %q got %q\n", x, y)
+		}
+		if addr != &y[0] {
+			t.Errorf("ints: unnecessary reallocation")
+		}
+	}
+}
+
+// Used to crash: negative count in recvMessage.
+func TestBadCount(t *testing.T) {
+	b := []byte{0xfb, 0xa5, 0x82, 0x2f, 0xca, 0x1}
+	if err := NewDecoder(bytes.NewReader(b)).Decode(nil); err == nil {
+		t.Error("expected error from bad count")
+	} else if err.Error() != errBadCount.Error() {
+		t.Error("expected bad count error; got", err)
+	}
+}
+
+// Verify that sequential Decoders built on a single input will
+// succeed if the input implements ReadByte and there is no
+// type information in the stream.
+func TestSequentialDecoder(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	const count = 10
+	for i := 0; i < count; i++ {
+		s := fmt.Sprintf("%d", i)
+		if err := enc.Encode(s); err != nil {
+			t.Error("encoder fail:", err)
+		}
+	}
+	for i := 0; i < count; i++ {
+		dec := NewDecoder(b)
+		var s string
+		if err := dec.Decode(&s); err != nil {
+			t.Fatal("decoder fail:", err)
+		}
+		if s != fmt.Sprintf("%d", i) {
+			t.Fatalf("decode expected %d got %s", i, s)
+		}
+	}
+}
+
+// Should be able to have unrepresentable fields (chan, func, *chan etc.); we just ignore them.
+type Bug2 struct {
+	A   int
+	C   chan int
+	CP  *chan int
+	F   func()
+	FPP **func()
+}
+
+func TestChanFuncIgnored(t *testing.T) {
+	c := make(chan int)
+	f := func() {}
+	fp := &f
+	b0 := Bug2{23, c, &c, f, &fp}
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	if err := enc.Encode(b0); err != nil {
+		t.Fatal("error encoding:", err)
+	}
+	var b1 Bug2
+	err := NewDecoder(&buf).Decode(&b1)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if b1.A != b0.A {
+		t.Fatalf("got %d want %d", b1.A, b0.A)
+	}
+	if b1.C != nil || b1.CP != nil || b1.F != nil || b1.FPP != nil {
+		t.Fatal("unexpected value for chan or func")
+	}
+}
+
+func TestSliceIncompatibility(t *testing.T) {
+	var in = []byte{1, 2, 3}
+	var out []int
+	if err := encAndDec(in, &out); err == nil {
+		t.Error("expected compatibility error")
+	}
+}
+
+// Mutually recursive slices of structs caused problems.
+type Bug3 struct {
+	Num      int
+	Children []*Bug3
+}
+
+func TestGobPtrSlices(t *testing.T) {
+	in := []*Bug3{
+		{1, nil},
+		{2, nil},
+	}
+	b := new(bytes.Buffer)
+	err := NewEncoder(b).Encode(&in)
+	if err != nil {
+		t.Fatal("encode:", err)
+	}
+
+	var out []*Bug3
+	err = NewDecoder(b).Decode(&out)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if !reflect.DeepEqual(in, out) {
+		t.Fatalf("got %v; wanted %v", out, in)
+	}
+}
+
+// getDecEnginePtr cached engine for ut.base instead of ut.user so we passed
+// a *map and then tried to reuse its engine to decode the inner map.
+func TestPtrToMapOfMap(t *testing.T) {
+	Register(make(map[string]interface{}))
+	subdata := make(map[string]interface{})
+	subdata["bar"] = "baz"
+	data := make(map[string]interface{})
+	data["foo"] = subdata
+
+	b := new(bytes.Buffer)
+	err := NewEncoder(b).Encode(data)
+	if err != nil {
+		t.Fatal("encode:", err)
+	}
+	var newData map[string]interface{}
+	err = NewDecoder(b).Decode(&newData)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if !reflect.DeepEqual(data, newData) {
+		t.Fatalf("expected %v got %v", data, newData)
+	}
+}
+
+// A top-level nil pointer generates a panic with a helpful string-valued message.
+func TestTopLevelNilPointer(t *testing.T) {
+	errMsg := topLevelNilPanic(t)
+	if errMsg == "" {
+		t.Fatal("top-level nil pointer did not panic")
+	}
+	if !strings.Contains(errMsg, "nil pointer") {
+		t.Fatal("expected nil pointer error, got:", errMsg)
+	}
+}
+
+func topLevelNilPanic(t *testing.T) (panicErr string) {
+	defer func() {
+		e := recover()
+		if err, ok := e.(string); ok {
+			panicErr = err
+		}
+	}()
+	var ip *int
+	buf := new(bytes.Buffer)
+	if err := NewEncoder(buf).Encode(ip); err != nil {
+		t.Fatal("error in encode:", err)
+	}
+	return
+}
+
+func TestNilPointerInsideInterface(t *testing.T) {
+	var ip *int
+	si := struct {
+		I interface{}
+	}{
+		I: ip,
+	}
+	buf := new(bytes.Buffer)
+	err := NewEncoder(buf).Encode(si)
+	if err == nil {
+		t.Fatal("expected error, got none")
+	}
+	errMsg := err.Error()
+	if !strings.Contains(errMsg, "nil pointer") || !strings.Contains(errMsg, "interface") {
+		t.Fatal("expected error about nil pointer and interface, got:", errMsg)
+	}
+}
+
+type Bug4Public struct {
+	Name   string
+	Secret Bug4Secret
+}
+
+type Bug4Secret struct {
+	a int // error: no exported fields.
+}
+
+// Test that a failed compilation doesn't leave around an executable encoder.
+// Issue 3273.
+func TestMutipleEncodingsOfBadType(t *testing.T) {
+	x := Bug4Public{
+		Name:   "name",
+		Secret: Bug4Secret{1},
+	}
+	buf := new(bytes.Buffer)
+	enc := NewEncoder(buf)
+	err := enc.Encode(x)
+	if err == nil {
+		t.Fatal("first encoding: expected error")
+	}
+	buf.Reset()
+	enc = NewEncoder(buf)
+	err = enc.Encode(x)
+	if err == nil {
+		t.Fatal("second encoding: expected error")
+	}
+	if !strings.Contains(err.Error(), "no exported fields") {
+		t.Errorf("expected error about no exported fields; got %v", err)
+	}
+}
+
+// There was an error check comparing the length of the input with the
+// length of the slice being decoded. It was wrong because the next
+// thing in the input might be a type definition, which would lead to
+// an incorrect length check.  This test reproduces the corner case.
+
+type Z struct {
+}
+
+func Test29ElementSlice(t *testing.T) {
+	Register(Z{})
+	src := make([]interface{}, 100) // Size needs to be bigger than size of type definition.
+	for i := range src {
+		src[i] = Z{}
+	}
+	buf := new(bytes.Buffer)
+	err := NewEncoder(buf).Encode(src)
+	if err != nil {
+		t.Fatalf("encode: %v", err)
+		return
+	}
+
+	var dst []interface{}
+	err = NewDecoder(buf).Decode(&dst)
+	if err != nil {
+		t.Errorf("decode: %v", err)
+		return
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/error.go b/third_party/gofrontend/libgo/go/encoding/gob/error.go
new file mode 100644
index 0000000..92cc0c6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/error.go
@@ -0,0 +1,43 @@
+// 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 gob
+
+import "fmt"
+
+// Errors in decoding and encoding are handled using panic and recover.
+// Panics caused by user error (that is, everything except run-time panics
+// such as "index out of bounds" errors) do not leave the file that caused
+// them, but are instead turned into plain error returns.  Encoding and
+// decoding functions and methods that do not return an error either use
+// panic to report an error or are guaranteed error-free.
+
+// A gobError is used to distinguish errors (panics) generated in this package.
+type gobError struct {
+	err error
+}
+
+// errorf is like error_ but takes Printf-style arguments to construct an error.
+// It always prefixes the message with "gob: ".
+func errorf(format string, args ...interface{}) {
+	error_(fmt.Errorf("gob: "+format, args...))
+}
+
+// error wraps the argument error and uses it as the argument to panic.
+func error_(err error) {
+	panic(gobError{err})
+}
+
+// catchError is meant to be used as a deferred function to turn a panic(gobError) into a
+// plain error.  It overwrites the error return of the function that deferred its call.
+func catchError(err *error) {
+	if e := recover(); e != nil {
+		ge, ok := e.(gobError)
+		if !ok {
+			panic(e)
+		}
+		*err = ge.err
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/gobencdec_test.go b/third_party/gofrontend/libgo/go/encoding/gob/gobencdec_test.go
new file mode 100644
index 0000000..157b772
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/gobencdec_test.go
@@ -0,0 +1,797 @@
+// 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.
+
+// This file contains tests of the GobEncoder/GobDecoder support.
+
+package gob
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"strings"
+	"testing"
+	"time"
+)
+
+// Types that implement the GobEncoder/Decoder interfaces.
+
+type ByteStruct struct {
+	a byte // not an exported field
+}
+
+type StringStruct struct {
+	s string // not an exported field
+}
+
+type ArrayStruct struct {
+	a [8192]byte // not an exported field
+}
+
+type Gobber int
+
+type ValueGobber string // encodes with a value, decodes with a pointer.
+
+type BinaryGobber int
+
+type BinaryValueGobber string
+
+type TextGobber int
+
+type TextValueGobber string
+
+// The relevant methods
+
+func (g *ByteStruct) GobEncode() ([]byte, error) {
+	b := make([]byte, 3)
+	b[0] = g.a
+	b[1] = g.a + 1
+	b[2] = g.a + 2
+	return b, nil
+}
+
+func (g *ByteStruct) GobDecode(data []byte) error {
+	if g == nil {
+		return errors.New("NIL RECEIVER")
+	}
+	// Expect N sequential-valued bytes.
+	if len(data) == 0 {
+		return io.EOF
+	}
+	g.a = data[0]
+	for i, c := range data {
+		if c != g.a+byte(i) {
+			return errors.New("invalid data sequence")
+		}
+	}
+	return nil
+}
+
+func (g *StringStruct) GobEncode() ([]byte, error) {
+	return []byte(g.s), nil
+}
+
+func (g *StringStruct) GobDecode(data []byte) error {
+	// Expect N sequential-valued bytes.
+	if len(data) == 0 {
+		return io.EOF
+	}
+	a := data[0]
+	for i, c := range data {
+		if c != a+byte(i) {
+			return errors.New("invalid data sequence")
+		}
+	}
+	g.s = string(data)
+	return nil
+}
+
+func (a *ArrayStruct) GobEncode() ([]byte, error) {
+	return a.a[:], nil
+}
+
+func (a *ArrayStruct) GobDecode(data []byte) error {
+	if len(data) != len(a.a) {
+		return errors.New("wrong length in array decode")
+	}
+	copy(a.a[:], data)
+	return nil
+}
+
+func (g *Gobber) GobEncode() ([]byte, error) {
+	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
+}
+
+func (g *Gobber) GobDecode(data []byte) error {
+	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
+	return err
+}
+
+func (g *BinaryGobber) MarshalBinary() ([]byte, error) {
+	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
+}
+
+func (g *BinaryGobber) UnmarshalBinary(data []byte) error {
+	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
+	return err
+}
+
+func (g *TextGobber) MarshalText() ([]byte, error) {
+	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
+}
+
+func (g *TextGobber) UnmarshalText(data []byte) error {
+	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
+	return err
+}
+
+func (v ValueGobber) GobEncode() ([]byte, error) {
+	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
+}
+
+func (v *ValueGobber) GobDecode(data []byte) error {
+	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
+	return err
+}
+
+func (v BinaryValueGobber) MarshalBinary() ([]byte, error) {
+	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
+}
+
+func (v *BinaryValueGobber) UnmarshalBinary(data []byte) error {
+	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
+	return err
+}
+
+func (v TextValueGobber) MarshalText() ([]byte, error) {
+	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
+}
+
+func (v *TextValueGobber) UnmarshalText(data []byte) error {
+	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
+	return err
+}
+
+// Structs that include GobEncodable fields.
+
+type GobTest0 struct {
+	X int // guarantee we have  something in common with GobTest*
+	G *ByteStruct
+}
+
+type GobTest1 struct {
+	X int // guarantee we have  something in common with GobTest*
+	G *StringStruct
+}
+
+type GobTest2 struct {
+	X int    // guarantee we have  something in common with GobTest*
+	G string // not a GobEncoder - should give us errors
+}
+
+type GobTest3 struct {
+	X int // guarantee we have  something in common with GobTest*
+	G *Gobber
+	B *BinaryGobber
+	T *TextGobber
+}
+
+type GobTest4 struct {
+	X  int // guarantee we have  something in common with GobTest*
+	V  ValueGobber
+	BV BinaryValueGobber
+	TV TextValueGobber
+}
+
+type GobTest5 struct {
+	X  int // guarantee we have  something in common with GobTest*
+	V  *ValueGobber
+	BV *BinaryValueGobber
+	TV *TextValueGobber
+}
+
+type GobTest6 struct {
+	X  int // guarantee we have  something in common with GobTest*
+	V  ValueGobber
+	W  *ValueGobber
+	BV BinaryValueGobber
+	BW *BinaryValueGobber
+	TV TextValueGobber
+	TW *TextValueGobber
+}
+
+type GobTest7 struct {
+	X  int // guarantee we have  something in common with GobTest*
+	V  *ValueGobber
+	W  ValueGobber
+	BV *BinaryValueGobber
+	BW BinaryValueGobber
+	TV *TextValueGobber
+	TW TextValueGobber
+}
+
+type GobTestIgnoreEncoder struct {
+	X int // guarantee we have  something in common with GobTest*
+}
+
+type GobTestValueEncDec struct {
+	X int          // guarantee we have  something in common with GobTest*
+	G StringStruct // not a pointer.
+}
+
+type GobTestIndirectEncDec struct {
+	X int             // guarantee we have  something in common with GobTest*
+	G ***StringStruct // indirections to the receiver.
+}
+
+type GobTestArrayEncDec struct {
+	X int         // guarantee we have  something in common with GobTest*
+	A ArrayStruct // not a pointer.
+}
+
+type GobTestIndirectArrayEncDec struct {
+	X int            // guarantee we have  something in common with GobTest*
+	A ***ArrayStruct // indirections to a large receiver.
+}
+
+func TestGobEncoderField(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest0)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.G.a != 'A' {
+		t.Errorf("expected 'A' got %c", x.G.a)
+	}
+	// Now a field that's not a structure.
+	b.Reset()
+	gobber := Gobber(23)
+	bgobber := BinaryGobber(24)
+	tgobber := TextGobber(25)
+	err = enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	y := new(GobTest3)
+	err = dec.Decode(y)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if *y.G != 23 || *y.B != 24 || *y.T != 25 {
+		t.Errorf("expected '23 got %d", *y.G)
+	}
+}
+
+// Even though the field is a value, we can still take its address
+// and should be able to call the methods.
+func TestGobEncoderValueField(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTestValueEncDec{17, StringStruct{"HIJKL"}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestValueEncDec)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.G.s != "HIJKL" {
+		t.Errorf("expected `HIJKL` got %s", x.G.s)
+	}
+}
+
+// GobEncode/Decode should work even if the value is
+// more indirect than the receiver.
+func TestGobEncoderIndirectField(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	s := &StringStruct{"HIJKL"}
+	sp := &s
+	err := enc.Encode(GobTestIndirectEncDec{17, &sp})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestIndirectEncDec)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if (***x.G).s != "HIJKL" {
+		t.Errorf("expected `HIJKL` got %s", (***x.G).s)
+	}
+}
+
+// Test with a large field with methods.
+func TestGobEncoderArrayField(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	var a GobTestArrayEncDec
+	a.X = 17
+	for i := range a.A.a {
+		a.A.a[i] = byte(i)
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestArrayEncDec)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	for i, v := range x.A.a {
+		if v != byte(i) {
+			t.Errorf("expected %x got %x", byte(i), v)
+			break
+		}
+	}
+}
+
+// Test an indirection to a large field with methods.
+func TestGobEncoderIndirectArrayField(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	var a GobTestIndirectArrayEncDec
+	a.X = 17
+	var array ArrayStruct
+	ap := &array
+	app := &ap
+	a.A = &app
+	for i := range array.a {
+		array.a[i] = byte(i)
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestIndirectArrayEncDec)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	for i, v := range (***x.A).a {
+		if v != byte(i) {
+			t.Errorf("expected %x got %x", byte(i), v)
+			break
+		}
+	}
+}
+
+// As long as the fields have the same name and implement the
+// interface, we can cross-connect them.  Not sure it's useful
+// and may even be bad but it works and it's hard to prevent
+// without exposing the contents of the object, which would
+// defeat the purpose.
+func TestGobEncoderFieldsOfDifferentType(t *testing.T) {
+	// first, string in field to byte in field
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest0)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.G.a != 'A' {
+		t.Errorf("expected 'A' got %c", x.G.a)
+	}
+	// now the other direction, byte in field to string in field
+	b.Reset()
+	err = enc.Encode(GobTest0{17, &ByteStruct{'X'}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	y := new(GobTest1)
+	err = dec.Decode(y)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if y.G.s != "XYZ" {
+		t.Fatalf("expected `XYZ` got %q", y.G.s)
+	}
+}
+
+// Test that we can encode a value and decode into a pointer.
+func TestGobEncoderValueEncoder(t *testing.T) {
+	// first, string in field to byte in field
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest4{17, ValueGobber("hello"), BinaryValueGobber("Καλημέρα"), TextValueGobber("こんにちは")})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest5)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if *x.V != "hello" || *x.BV != "Καλημέρα" || *x.TV != "こんにちは" {
+		t.Errorf("expected `hello` got %s", *x.V)
+	}
+}
+
+// Test that we can use a value then a pointer type of a GobEncoder
+// in the same encoded value.  Bug 4647.
+func TestGobEncoderValueThenPointer(t *testing.T) {
+	v := ValueGobber("forty-two")
+	w := ValueGobber("six-by-nine")
+	bv := BinaryValueGobber("1nanocentury")
+	bw := BinaryValueGobber("πseconds")
+	tv := TextValueGobber("gravitationalacceleration")
+	tw := TextValueGobber("π²ft/s²")
+
+	// this was a bug: encoding a GobEncoder by value before a GobEncoder
+	// pointer would cause duplicate type definitions to be sent.
+
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	if err := enc.Encode(GobTest6{42, v, &w, bv, &bw, tv, &tw}); err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest6)
+	if err := dec.Decode(x); err != nil {
+		t.Fatal("decode error:", err)
+	}
+
+	if got, want := x.V, v; got != want {
+		t.Errorf("v = %q, want %q", got, want)
+	}
+	if got, want := x.W, w; got == nil {
+		t.Errorf("w = nil, want %q", want)
+	} else if *got != want {
+		t.Errorf("w = %q, want %q", *got, want)
+	}
+
+	if got, want := x.BV, bv; got != want {
+		t.Errorf("bv = %q, want %q", got, want)
+	}
+	if got, want := x.BW, bw; got == nil {
+		t.Errorf("bw = nil, want %q", want)
+	} else if *got != want {
+		t.Errorf("bw = %q, want %q", *got, want)
+	}
+
+	if got, want := x.TV, tv; got != want {
+		t.Errorf("tv = %q, want %q", got, want)
+	}
+	if got, want := x.TW, tw; got == nil {
+		t.Errorf("tw = nil, want %q", want)
+	} else if *got != want {
+		t.Errorf("tw = %q, want %q", *got, want)
+	}
+}
+
+// Test that we can use a pointer then a value type of a GobEncoder
+// in the same encoded value.
+func TestGobEncoderPointerThenValue(t *testing.T) {
+	v := ValueGobber("forty-two")
+	w := ValueGobber("six-by-nine")
+	bv := BinaryValueGobber("1nanocentury")
+	bw := BinaryValueGobber("πseconds")
+	tv := TextValueGobber("gravitationalacceleration")
+	tw := TextValueGobber("π²ft/s²")
+
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	if err := enc.Encode(GobTest7{42, &v, w, &bv, bw, &tv, tw}); err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest7)
+	if err := dec.Decode(x); err != nil {
+		t.Fatal("decode error:", err)
+	}
+
+	if got, want := x.V, v; got == nil {
+		t.Errorf("v = nil, want %q", want)
+	} else if *got != want {
+		t.Errorf("v = %q, want %q", *got, want)
+	}
+	if got, want := x.W, w; got != want {
+		t.Errorf("w = %q, want %q", got, want)
+	}
+
+	if got, want := x.BV, bv; got == nil {
+		t.Errorf("bv = nil, want %q", want)
+	} else if *got != want {
+		t.Errorf("bv = %q, want %q", *got, want)
+	}
+	if got, want := x.BW, bw; got != want {
+		t.Errorf("bw = %q, want %q", got, want)
+	}
+
+	if got, want := x.TV, tv; got == nil {
+		t.Errorf("tv = nil, want %q", want)
+	} else if *got != want {
+		t.Errorf("tv = %q, want %q", *got, want)
+	}
+	if got, want := x.TW, tw; got != want {
+		t.Errorf("tw = %q, want %q", got, want)
+	}
+}
+
+func TestGobEncoderFieldTypeError(t *testing.T) {
+	// GobEncoder to non-decoder: error
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := &GobTest2{}
+	err = dec.Decode(x)
+	if err == nil {
+		t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)")
+	}
+	if strings.Index(err.Error(), "type") < 0 {
+		t.Fatal("expected type error; got", err)
+	}
+	// Non-encoder to GobDecoder: error
+	b.Reset()
+	err = enc.Encode(GobTest2{17, "ABC"})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	y := &GobTest1{}
+	err = dec.Decode(y)
+	if err == nil {
+		t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)")
+	}
+	if strings.Index(err.Error(), "type") < 0 {
+		t.Fatal("expected type error; got", err)
+	}
+}
+
+// Even though ByteStruct is a struct, it's treated as a singleton at the top level.
+func TestGobEncoderStructSingleton(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(&ByteStruct{'A'})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(ByteStruct)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.a != 'A' {
+		t.Errorf("expected 'A' got %c", x.a)
+	}
+}
+
+func TestGobEncoderNonStructSingleton(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(Gobber(1234))
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	var x Gobber
+	err = dec.Decode(&x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x != 1234 {
+		t.Errorf("expected 1234 got %d", x)
+	}
+}
+
+func TestGobEncoderIgnoreStructField(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestIgnoreEncoder)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.X != 17 {
+		t.Errorf("expected 17 got %c", x.X)
+	}
+}
+
+func TestGobEncoderIgnoreNonStructField(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	gobber := Gobber(23)
+	bgobber := BinaryGobber(24)
+	tgobber := TextGobber(25)
+	err := enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestIgnoreEncoder)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.X != 17 {
+		t.Errorf("expected 17 got %c", x.X)
+	}
+}
+
+func TestGobEncoderIgnoreNilEncoder(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest0{X: 18}) // G is nil
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest0)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.X != 18 {
+		t.Errorf("expected x.X = 18, got %v", x.X)
+	}
+	if x.G != nil {
+		t.Errorf("expected x.G = nil, got %v", x.G)
+	}
+}
+
+type gobDecoderBug0 struct {
+	foo, bar string
+}
+
+func (br *gobDecoderBug0) String() string {
+	return br.foo + "-" + br.bar
+}
+
+func (br *gobDecoderBug0) GobEncode() ([]byte, error) {
+	return []byte(br.String()), nil
+}
+
+func (br *gobDecoderBug0) GobDecode(b []byte) error {
+	br.foo = "foo"
+	br.bar = "bar"
+	return nil
+}
+
+// This was a bug: the receiver has a different indirection level
+// than the variable.
+func TestGobEncoderExtraIndirect(t *testing.T) {
+	gdb := &gobDecoderBug0{"foo", "bar"}
+	buf := new(bytes.Buffer)
+	e := NewEncoder(buf)
+	if err := e.Encode(gdb); err != nil {
+		t.Fatalf("encode: %v", err)
+	}
+	d := NewDecoder(buf)
+	var got *gobDecoderBug0
+	if err := d.Decode(&got); err != nil {
+		t.Fatalf("decode: %v", err)
+	}
+	if got.foo != gdb.foo || got.bar != gdb.bar {
+		t.Errorf("got = %q, want %q", got, gdb)
+	}
+}
+
+// Another bug: this caused a crash with the new Go1 Time type.
+// We throw in a gob-encoding array, to test another case of isZero,
+// and a struct containing an nil interface, to test a third.
+type isZeroBug struct {
+	T time.Time
+	S string
+	I int
+	A isZeroBugArray
+	F isZeroBugInterface
+}
+
+type isZeroBugArray [2]uint8
+
+// Receiver is value, not pointer, to test isZero of array.
+func (a isZeroBugArray) GobEncode() (b []byte, e error) {
+	b = append(b, a[:]...)
+	return b, nil
+}
+
+func (a *isZeroBugArray) GobDecode(data []byte) error {
+	if len(data) != len(a) {
+		return io.EOF
+	}
+	a[0] = data[0]
+	a[1] = data[1]
+	return nil
+}
+
+type isZeroBugInterface struct {
+	I interface{}
+}
+
+func (i isZeroBugInterface) GobEncode() (b []byte, e error) {
+	return []byte{}, nil
+}
+
+func (i *isZeroBugInterface) GobDecode(data []byte) error {
+	return nil
+}
+
+func TestGobEncodeIsZero(t *testing.T) {
+	x := isZeroBug{time.Now(), "hello", -55, isZeroBugArray{1, 2}, isZeroBugInterface{}}
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(x)
+	if err != nil {
+		t.Fatal("encode:", err)
+	}
+	var y isZeroBug
+	dec := NewDecoder(b)
+	err = dec.Decode(&y)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if x != y {
+		t.Fatalf("%v != %v", x, y)
+	}
+}
+
+func TestGobEncodePtrError(t *testing.T) {
+	var err error
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err = enc.Encode(&err)
+	if err != nil {
+		t.Fatal("encode:", err)
+	}
+	dec := NewDecoder(b)
+	err2 := fmt.Errorf("foo")
+	err = dec.Decode(&err2)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if err2 != nil {
+		t.Fatalf("expected nil, got %v", err2)
+	}
+}
+
+func TestNetIP(t *testing.T) {
+	// Encoding of net.IP{1,2,3,4} in Go 1.1.
+	enc := []byte{0x07, 0x0a, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04}
+
+	var ip net.IP
+	err := NewDecoder(bytes.NewReader(enc)).Decode(&ip)
+	if err != nil {
+		t.Fatalf("decode: %v", err)
+	}
+	if ip.String() != "1.2.3.4" {
+		t.Errorf("decoded to %v, want 1.2.3.4", ip.String())
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/timing_test.go b/third_party/gofrontend/libgo/go/encoding/gob/timing_test.go
new file mode 100644
index 0000000..9fbb0ac
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/timing_test.go
@@ -0,0 +1,109 @@
+// 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.
+
+package gob
+
+import (
+	"bytes"
+	"io"
+	"os"
+	"runtime"
+	"testing"
+)
+
+type Bench struct {
+	A int
+	B float64
+	C string
+	D []byte
+}
+
+func benchmarkEndToEnd(r io.Reader, w io.Writer, b *testing.B) {
+	b.StopTimer()
+	enc := NewEncoder(w)
+	dec := NewDecoder(r)
+	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if enc.Encode(bench) != nil {
+			panic("encode error")
+		}
+		if dec.Decode(bench) != nil {
+			panic("decode error")
+		}
+	}
+}
+
+func BenchmarkEndToEndPipe(b *testing.B) {
+	r, w, err := os.Pipe()
+	if err != nil {
+		b.Fatal("can't get pipe:", err)
+	}
+	benchmarkEndToEnd(r, w, b)
+}
+
+func BenchmarkEndToEndByteBuffer(b *testing.B) {
+	var buf bytes.Buffer
+	benchmarkEndToEnd(&buf, &buf, b)
+}
+
+func TestCountEncodeMallocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Skip("skipping; GOMAXPROCS>1")
+	}
+
+	const N = 1000
+
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
+
+	allocs := testing.AllocsPerRun(N, func() {
+		err := enc.Encode(bench)
+		if err != nil {
+			t.Fatal("encode:", err)
+		}
+	})
+	if allocs != 0 {
+		t.Fatalf("mallocs per encode of type Bench: %v; wanted 0\n", allocs)
+	}
+}
+
+func TestCountDecodeMallocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Skip("skipping; GOMAXPROCS>1")
+	}
+
+	const N = 1000
+
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
+
+	// Fill the buffer with enough to decode
+	testing.AllocsPerRun(N, func() {
+		err := enc.Encode(bench)
+		if err != nil {
+			t.Fatal("encode:", err)
+		}
+	})
+
+	dec := NewDecoder(&buf)
+	allocs := testing.AllocsPerRun(N, func() {
+		*bench = Bench{}
+		err := dec.Decode(&bench)
+		if err != nil {
+			t.Fatal("decode:", err)
+		}
+	})
+	if allocs != 3 {
+		t.Fatalf("mallocs per decode of type Bench: %v; wanted 3\n", allocs)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/type.go b/third_party/gofrontend/libgo/go/encoding/gob/type.go
new file mode 100644
index 0000000..cad1452
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/type.go
@@ -0,0 +1,893 @@
+// 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 gob
+
+import (
+	"encoding"
+	"errors"
+	"fmt"
+	"os"
+	"reflect"
+	"sync"
+	"unicode"
+	"unicode/utf8"
+)
+
+// userTypeInfo stores the information associated with a type the user has handed
+// to the package.  It's computed once and stored in a map keyed by reflection
+// type.
+type userTypeInfo struct {
+	user        reflect.Type // the type the user handed us
+	base        reflect.Type // the base type after all indirections
+	indir       int          // number of indirections to reach the base type
+	externalEnc int          // xGob, xBinary, or xText
+	externalDec int          // xGob, xBinary or xText
+	encIndir    int8         // number of indirections to reach the receiver type; may be negative
+	decIndir    int8         // number of indirections to reach the receiver type; may be negative
+}
+
+// externalEncoding bits
+const (
+	xGob    = 1 + iota // GobEncoder or GobDecoder
+	xBinary            // encoding.BinaryMarshaler or encoding.BinaryUnmarshaler
+	xText              // encoding.TextMarshaler or encoding.TextUnmarshaler
+)
+
+var (
+	// Protected by an RWMutex because we read it a lot and write
+	// it only when we see a new type, typically when compiling.
+	userTypeLock  sync.RWMutex
+	userTypeCache = make(map[reflect.Type]*userTypeInfo)
+)
+
+// validType returns, and saves, the information associated with user-provided type rt.
+// If the user type is not valid, err will be non-nil.  To be used when the error handler
+// is not set up.
+func validUserType(rt reflect.Type) (ut *userTypeInfo, err error) {
+	userTypeLock.RLock()
+	ut = userTypeCache[rt]
+	userTypeLock.RUnlock()
+	if ut != nil {
+		return
+	}
+	// Now set the value under the write lock.
+	userTypeLock.Lock()
+	defer userTypeLock.Unlock()
+	if ut = userTypeCache[rt]; ut != nil {
+		// Lost the race; not a problem.
+		return
+	}
+	ut = new(userTypeInfo)
+	ut.base = rt
+	ut.user = rt
+	// A type that is just a cycle of pointers (such as type T *T) cannot
+	// be represented in gobs, which need some concrete data.  We use a
+	// cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6,
+	// pp 539-540.  As we step through indirections, run another type at
+	// half speed. If they meet up, there's a cycle.
+	slowpoke := ut.base // walks half as fast as ut.base
+	for {
+		pt := ut.base
+		if pt.Kind() != reflect.Ptr {
+			break
+		}
+		ut.base = pt.Elem()
+		if ut.base == slowpoke { // ut.base lapped slowpoke
+			// recursive pointer type.
+			return nil, errors.New("can't represent recursive pointer type " + ut.base.String())
+		}
+		if ut.indir%2 == 0 {
+			slowpoke = slowpoke.Elem()
+		}
+		ut.indir++
+	}
+
+	if ok, indir := implementsInterface(ut.user, gobEncoderInterfaceType); ok {
+		ut.externalEnc, ut.encIndir = xGob, indir
+	} else if ok, indir := implementsInterface(ut.user, binaryMarshalerInterfaceType); ok {
+		ut.externalEnc, ut.encIndir = xBinary, indir
+	}
+
+	// NOTE(rsc): Would like to allow MarshalText here, but results in incompatibility
+	// with older encodings for net.IP. See golang.org/issue/6760.
+	// } else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok {
+	// 	ut.externalEnc, ut.encIndir = xText, indir
+	// }
+
+	if ok, indir := implementsInterface(ut.user, gobDecoderInterfaceType); ok {
+		ut.externalDec, ut.decIndir = xGob, indir
+	} else if ok, indir := implementsInterface(ut.user, binaryUnmarshalerInterfaceType); ok {
+		ut.externalDec, ut.decIndir = xBinary, indir
+	}
+
+	// See note above.
+	// } else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok {
+	// 	ut.externalDec, ut.decIndir = xText, indir
+	// }
+
+	userTypeCache[rt] = ut
+	return
+}
+
+var (
+	gobEncoderInterfaceType        = reflect.TypeOf((*GobEncoder)(nil)).Elem()
+	gobDecoderInterfaceType        = reflect.TypeOf((*GobDecoder)(nil)).Elem()
+	binaryMarshalerInterfaceType   = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem()
+	binaryUnmarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
+	textMarshalerInterfaceType     = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+	textUnmarshalerInterfaceType   = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+)
+
+// implementsInterface reports whether the type implements the
+// gobEncoder/gobDecoder interface.
+// It also returns the number of indirections required to get to the
+// implementation.
+func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) {
+	if typ == nil {
+		return
+	}
+	rt := typ
+	// The type might be a pointer and we need to keep
+	// dereferencing to the base type until we find an implementation.
+	for {
+		if rt.Implements(gobEncDecType) {
+			return true, indir
+		}
+		if p := rt; p.Kind() == reflect.Ptr {
+			indir++
+			if indir > 100 { // insane number of indirections
+				return false, 0
+			}
+			rt = p.Elem()
+			continue
+		}
+		break
+	}
+	// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
+	if typ.Kind() != reflect.Ptr {
+		// Not a pointer, but does the pointer work?
+		if reflect.PtrTo(typ).Implements(gobEncDecType) {
+			return true, -1
+		}
+	}
+	return false, 0
+}
+
+// userType returns, and saves, the information associated with user-provided type rt.
+// If the user type is not valid, it calls error.
+func userType(rt reflect.Type) *userTypeInfo {
+	ut, err := validUserType(rt)
+	if err != nil {
+		error_(err)
+	}
+	return ut
+}
+
+// A typeId represents a gob Type as an integer that can be passed on the wire.
+// Internally, typeIds are used as keys to a map to recover the underlying type info.
+type typeId int32
+
+var nextId typeId       // incremented for each new type we build
+var typeLock sync.Mutex // set while building a type
+const firstUserId = 64  // lowest id number granted to user
+
+type gobType interface {
+	id() typeId
+	setId(id typeId)
+	name() string
+	string() string // not public; only for debugging
+	safeString(seen map[typeId]bool) string
+}
+
+var types = make(map[reflect.Type]gobType)
+var idToType = make(map[typeId]gobType)
+var builtinIdToType map[typeId]gobType // set in init() after builtins are established
+
+func setTypeId(typ gobType) {
+	// When building recursive types, someone may get there before us.
+	if typ.id() != 0 {
+		return
+	}
+	nextId++
+	typ.setId(nextId)
+	idToType[nextId] = typ
+}
+
+func (t typeId) gobType() gobType {
+	if t == 0 {
+		return nil
+	}
+	return idToType[t]
+}
+
+// string returns the string representation of the type associated with the typeId.
+func (t typeId) string() string {
+	if t.gobType() == nil {
+		return "<nil>"
+	}
+	return t.gobType().string()
+}
+
+// Name returns the name of the type associated with the typeId.
+func (t typeId) name() string {
+	if t.gobType() == nil {
+		return "<nil>"
+	}
+	return t.gobType().name()
+}
+
+// CommonType holds elements of all types.
+// It is a historical artifact, kept for binary compatibility and exported
+// only for the benefit of the package's encoding of type descriptors. It is
+// not intended for direct use by clients.
+type CommonType struct {
+	Name string
+	Id   typeId
+}
+
+func (t *CommonType) id() typeId { return t.Id }
+
+func (t *CommonType) setId(id typeId) { t.Id = id }
+
+func (t *CommonType) string() string { return t.Name }
+
+func (t *CommonType) safeString(seen map[typeId]bool) string {
+	return t.Name
+}
+
+func (t *CommonType) name() string { return t.Name }
+
+// Create and check predefined types
+// The string for tBytes is "bytes" not "[]byte" to signify its specialness.
+
+var (
+	// Primordial types, needed during initialization.
+	// Always passed as pointers so the interface{} type
+	// goes through without losing its interfaceness.
+	tBool      = bootstrapType("bool", (*bool)(nil), 1)
+	tInt       = bootstrapType("int", (*int)(nil), 2)
+	tUint      = bootstrapType("uint", (*uint)(nil), 3)
+	tFloat     = bootstrapType("float", (*float64)(nil), 4)
+	tBytes     = bootstrapType("bytes", (*[]byte)(nil), 5)
+	tString    = bootstrapType("string", (*string)(nil), 6)
+	tComplex   = bootstrapType("complex", (*complex128)(nil), 7)
+	tInterface = bootstrapType("interface", (*interface{})(nil), 8)
+	// Reserve some Ids for compatible expansion
+	tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9)
+	tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10)
+	tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11)
+	tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12)
+	tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13)
+	tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14)
+	tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15)
+)
+
+// Predefined because it's needed by the Decoder
+var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id
+var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType)
+
+func init() {
+	// Some magic numbers to make sure there are no surprises.
+	checkId(16, tWireType)
+	checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id)
+	checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id)
+	checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id)
+	checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id)
+	checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id)
+	checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id)
+
+	builtinIdToType = make(map[typeId]gobType)
+	for k, v := range idToType {
+		builtinIdToType[k] = v
+	}
+
+	// Move the id space upwards to allow for growth in the predefined world
+	// without breaking existing files.
+	if nextId > firstUserId {
+		panic(fmt.Sprintln("nextId too large:", nextId))
+	}
+	nextId = firstUserId
+	registerBasics()
+	wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil)))
+}
+
+// Array type
+type arrayType struct {
+	CommonType
+	Elem typeId
+	Len  int
+}
+
+func newArrayType(name string) *arrayType {
+	a := &arrayType{CommonType{Name: name}, 0, 0}
+	return a
+}
+
+func (a *arrayType) init(elem gobType, len int) {
+	// Set our type id before evaluating the element's, in case it's our own.
+	setTypeId(a)
+	a.Elem = elem.id()
+	a.Len = len
+}
+
+func (a *arrayType) safeString(seen map[typeId]bool) string {
+	if seen[a.Id] {
+		return a.Name
+	}
+	seen[a.Id] = true
+	return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen))
+}
+
+func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) }
+
+// GobEncoder type (something that implements the GobEncoder interface)
+type gobEncoderType struct {
+	CommonType
+}
+
+func newGobEncoderType(name string) *gobEncoderType {
+	g := &gobEncoderType{CommonType{Name: name}}
+	setTypeId(g)
+	return g
+}
+
+func (g *gobEncoderType) safeString(seen map[typeId]bool) string {
+	return g.Name
+}
+
+func (g *gobEncoderType) string() string { return g.Name }
+
+// Map type
+type mapType struct {
+	CommonType
+	Key  typeId
+	Elem typeId
+}
+
+func newMapType(name string) *mapType {
+	m := &mapType{CommonType{Name: name}, 0, 0}
+	return m
+}
+
+func (m *mapType) init(key, elem gobType) {
+	// Set our type id before evaluating the element's, in case it's our own.
+	setTypeId(m)
+	m.Key = key.id()
+	m.Elem = elem.id()
+}
+
+func (m *mapType) safeString(seen map[typeId]bool) string {
+	if seen[m.Id] {
+		return m.Name
+	}
+	seen[m.Id] = true
+	key := m.Key.gobType().safeString(seen)
+	elem := m.Elem.gobType().safeString(seen)
+	return fmt.Sprintf("map[%s]%s", key, elem)
+}
+
+func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) }
+
+// Slice type
+type sliceType struct {
+	CommonType
+	Elem typeId
+}
+
+func newSliceType(name string) *sliceType {
+	s := &sliceType{CommonType{Name: name}, 0}
+	return s
+}
+
+func (s *sliceType) init(elem gobType) {
+	// Set our type id before evaluating the element's, in case it's our own.
+	setTypeId(s)
+	// See the comments about ids in newTypeObject. Only slices and
+	// structs have mutual recursion.
+	if elem.id() == 0 {
+		setTypeId(elem)
+	}
+	s.Elem = elem.id()
+}
+
+func (s *sliceType) safeString(seen map[typeId]bool) string {
+	if seen[s.Id] {
+		return s.Name
+	}
+	seen[s.Id] = true
+	return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen))
+}
+
+func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) }
+
+// Struct type
+type fieldType struct {
+	Name string
+	Id   typeId
+}
+
+type structType struct {
+	CommonType
+	Field []*fieldType
+}
+
+func (s *structType) safeString(seen map[typeId]bool) string {
+	if s == nil {
+		return "<nil>"
+	}
+	if _, ok := seen[s.Id]; ok {
+		return s.Name
+	}
+	seen[s.Id] = true
+	str := s.Name + " = struct { "
+	for _, f := range s.Field {
+		str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen))
+	}
+	str += "}"
+	return str
+}
+
+func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) }
+
+func newStructType(name string) *structType {
+	s := &structType{CommonType{Name: name}, nil}
+	// For historical reasons we set the id here rather than init.
+	// See the comment in newTypeObject for details.
+	setTypeId(s)
+	return s
+}
+
+// newTypeObject allocates a gobType for the reflection type rt.
+// Unless ut represents a GobEncoder, rt should be the base type
+// of ut.
+// This is only called from the encoding side. The decoding side
+// works through typeIds and userTypeInfos alone.
+func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
+	// Does this type implement GobEncoder?
+	if ut.externalEnc != 0 {
+		return newGobEncoderType(name), nil
+	}
+	var err error
+	var type0, type1 gobType
+	defer func() {
+		if err != nil {
+			delete(types, rt)
+		}
+	}()
+	// Install the top-level type before the subtypes (e.g. struct before
+	// fields) so recursive types can be constructed safely.
+	switch t := rt; t.Kind() {
+	// All basic types are easy: they are predefined.
+	case reflect.Bool:
+		return tBool.gobType(), nil
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return tInt.gobType(), nil
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return tUint.gobType(), nil
+
+	case reflect.Float32, reflect.Float64:
+		return tFloat.gobType(), nil
+
+	case reflect.Complex64, reflect.Complex128:
+		return tComplex.gobType(), nil
+
+	case reflect.String:
+		return tString.gobType(), nil
+
+	case reflect.Interface:
+		return tInterface.gobType(), nil
+
+	case reflect.Array:
+		at := newArrayType(name)
+		types[rt] = at
+		type0, err = getBaseType("", t.Elem())
+		if err != nil {
+			return nil, err
+		}
+		// Historical aside:
+		// For arrays, maps, and slices, we set the type id after the elements
+		// are constructed. This is to retain the order of type id allocation after
+		// a fix made to handle recursive types, which changed the order in
+		// which types are built.  Delaying the setting in this way preserves
+		// type ids while allowing recursive types to be described. Structs,
+		// done below, were already handling recursion correctly so they
+		// assign the top-level id before those of the field.
+		at.init(type0, t.Len())
+		return at, nil
+
+	case reflect.Map:
+		mt := newMapType(name)
+		types[rt] = mt
+		type0, err = getBaseType("", t.Key())
+		if err != nil {
+			return nil, err
+		}
+		type1, err = getBaseType("", t.Elem())
+		if err != nil {
+			return nil, err
+		}
+		mt.init(type0, type1)
+		return mt, nil
+
+	case reflect.Slice:
+		// []byte == []uint8 is a special case
+		if t.Elem().Kind() == reflect.Uint8 {
+			return tBytes.gobType(), nil
+		}
+		st := newSliceType(name)
+		types[rt] = st
+		type0, err = getBaseType(t.Elem().Name(), t.Elem())
+		if err != nil {
+			return nil, err
+		}
+		st.init(type0)
+		return st, nil
+
+	case reflect.Struct:
+		st := newStructType(name)
+		types[rt] = st
+		idToType[st.id()] = st
+		for i := 0; i < t.NumField(); i++ {
+			f := t.Field(i)
+			if !isSent(&f) {
+				continue
+			}
+			typ := userType(f.Type).base
+			tname := typ.Name()
+			if tname == "" {
+				t := userType(f.Type).base
+				tname = t.String()
+			}
+			gt, err := getBaseType(tname, f.Type)
+			if err != nil {
+				return nil, err
+			}
+			// Some mutually recursive types can cause us to be here while
+			// still defining the element. Fix the element type id here.
+			// We could do this more neatly by setting the id at the start of
+			// building every type, but that would break binary compatibility.
+			if gt.id() == 0 {
+				setTypeId(gt)
+			}
+			st.Field = append(st.Field, &fieldType{f.Name, gt.id()})
+		}
+		return st, nil
+
+	default:
+		return nil, errors.New("gob NewTypeObject can't handle type: " + rt.String())
+	}
+}
+
+// isExported reports whether this is an exported - upper case - name.
+func isExported(name string) bool {
+	rune, _ := utf8.DecodeRuneInString(name)
+	return unicode.IsUpper(rune)
+}
+
+// isSent reports whether this struct field is to be transmitted.
+// It will be transmitted only if it is exported and not a chan or func field
+// or pointer to chan or func.
+func isSent(field *reflect.StructField) bool {
+	if !isExported(field.Name) {
+		return false
+	}
+	// If the field is a chan or func or pointer thereto, don't send it.
+	// That is, treat it like an unexported field.
+	typ := field.Type
+	for typ.Kind() == reflect.Ptr {
+		typ = typ.Elem()
+	}
+	if typ.Kind() == reflect.Chan || typ.Kind() == reflect.Func {
+		return false
+	}
+	return true
+}
+
+// getBaseType returns the Gob type describing the given reflect.Type's base type.
+// typeLock must be held.
+func getBaseType(name string, rt reflect.Type) (gobType, error) {
+	ut := userType(rt)
+	return getType(name, ut, ut.base)
+}
+
+// getType returns the Gob type describing the given reflect.Type.
+// Should be called only when handling GobEncoders/Decoders,
+// which may be pointers.  All other types are handled through the
+// base type, never a pointer.
+// typeLock must be held.
+func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
+	typ, present := types[rt]
+	if present {
+		return typ, nil
+	}
+	typ, err := newTypeObject(name, ut, rt)
+	if err == nil {
+		types[rt] = typ
+	}
+	return typ, err
+}
+
+func checkId(want, got typeId) {
+	if want != got {
+		fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want))
+		panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string())
+	}
+}
+
+// used for building the basic types; called only from init().  the incoming
+// interface always refers to a pointer.
+func bootstrapType(name string, e interface{}, expect typeId) typeId {
+	rt := reflect.TypeOf(e).Elem()
+	_, present := types[rt]
+	if present {
+		panic("bootstrap type already present: " + name + ", " + rt.String())
+	}
+	typ := &CommonType{Name: name}
+	types[rt] = typ
+	setTypeId(typ)
+	checkId(expect, nextId)
+	userType(rt) // might as well cache it now
+	return nextId
+}
+
+// Representation of the information we send and receive about this type.
+// Each value we send is preceded by its type definition: an encoded int.
+// However, the very first time we send the value, we first send the pair
+// (-id, wireType).
+// For bootstrapping purposes, we assume that the recipient knows how
+// to decode a wireType; it is exactly the wireType struct here, interpreted
+// using the gob rules for sending a structure, except that we assume the
+// ids for wireType and structType etc. are known.  The relevant pieces
+// are built in encode.go's init() function.
+// To maintain binary compatibility, if you extend this type, always put
+// the new fields last.
+type wireType struct {
+	ArrayT           *arrayType
+	SliceT           *sliceType
+	StructT          *structType
+	MapT             *mapType
+	GobEncoderT      *gobEncoderType
+	BinaryMarshalerT *gobEncoderType
+	TextMarshalerT   *gobEncoderType
+}
+
+func (w *wireType) string() string {
+	const unknown = "unknown type"
+	if w == nil {
+		return unknown
+	}
+	switch {
+	case w.ArrayT != nil:
+		return w.ArrayT.Name
+	case w.SliceT != nil:
+		return w.SliceT.Name
+	case w.StructT != nil:
+		return w.StructT.Name
+	case w.MapT != nil:
+		return w.MapT.Name
+	case w.GobEncoderT != nil:
+		return w.GobEncoderT.Name
+	case w.BinaryMarshalerT != nil:
+		return w.BinaryMarshalerT.Name
+	case w.TextMarshalerT != nil:
+		return w.TextMarshalerT.Name
+	}
+	return unknown
+}
+
+type typeInfo struct {
+	id      typeId
+	encoder *encEngine
+	wire    *wireType
+}
+
+var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock
+
+// typeLock must be held.
+func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) {
+	rt := ut.base
+	if ut.externalEnc != 0 {
+		// We want the user type, not the base type.
+		rt = ut.user
+	}
+	info, ok := typeInfoMap[rt]
+	if ok {
+		return info, nil
+	}
+	info = new(typeInfo)
+	gt, err := getBaseType(rt.Name(), rt)
+	if err != nil {
+		return nil, err
+	}
+	info.id = gt.id()
+
+	if ut.externalEnc != 0 {
+		userType, err := getType(rt.Name(), ut, rt)
+		if err != nil {
+			return nil, err
+		}
+		gt := userType.id().gobType().(*gobEncoderType)
+		switch ut.externalEnc {
+		case xGob:
+			info.wire = &wireType{GobEncoderT: gt}
+		case xBinary:
+			info.wire = &wireType{BinaryMarshalerT: gt}
+		case xText:
+			info.wire = &wireType{TextMarshalerT: gt}
+		}
+		typeInfoMap[ut.user] = info
+		return info, nil
+	}
+
+	t := info.id.gobType()
+	switch typ := rt; typ.Kind() {
+	case reflect.Array:
+		info.wire = &wireType{ArrayT: t.(*arrayType)}
+	case reflect.Map:
+		info.wire = &wireType{MapT: t.(*mapType)}
+	case reflect.Slice:
+		// []byte == []uint8 is a special case handled separately
+		if typ.Elem().Kind() != reflect.Uint8 {
+			info.wire = &wireType{SliceT: t.(*sliceType)}
+		}
+	case reflect.Struct:
+		info.wire = &wireType{StructT: t.(*structType)}
+	}
+	typeInfoMap[rt] = info
+	return info, nil
+}
+
+// Called only when a panic is acceptable and unexpected.
+func mustGetTypeInfo(rt reflect.Type) *typeInfo {
+	t, err := getTypeInfo(userType(rt))
+	if err != nil {
+		panic("getTypeInfo: " + err.Error())
+	}
+	return t
+}
+
+// GobEncoder is the interface describing data that provides its own
+// representation for encoding values for transmission to a GobDecoder.
+// A type that implements GobEncoder and GobDecoder has complete
+// control over the representation of its data and may therefore
+// contain things such as private fields, channels, and functions,
+// which are not usually transmissible in gob streams.
+//
+// Note: Since gobs can be stored permanently, It is good design
+// to guarantee the encoding used by a GobEncoder is stable as the
+// software evolves.  For instance, it might make sense for GobEncode
+// to include a version number in the encoding.
+type GobEncoder interface {
+	// GobEncode returns a byte slice representing the encoding of the
+	// receiver for transmission to a GobDecoder, usually of the same
+	// concrete type.
+	GobEncode() ([]byte, error)
+}
+
+// GobDecoder is the interface describing data that provides its own
+// routine for decoding transmitted values sent by a GobEncoder.
+type GobDecoder interface {
+	// GobDecode overwrites the receiver, which must be a pointer,
+	// with the value represented by the byte slice, which was written
+	// by GobEncode, usually for the same concrete type.
+	GobDecode([]byte) error
+}
+
+var (
+	registerLock       sync.RWMutex
+	nameToConcreteType = make(map[string]reflect.Type)
+	concreteTypeToName = make(map[reflect.Type]string)
+)
+
+// RegisterName is like Register but uses the provided name rather than the
+// type's default.
+func RegisterName(name string, value interface{}) {
+	if name == "" {
+		// reserved for nil
+		panic("attempt to register empty name")
+	}
+	registerLock.Lock()
+	defer registerLock.Unlock()
+	ut := userType(reflect.TypeOf(value))
+	// Check for incompatible duplicates. The name must refer to the
+	// same user type, and vice versa.
+	if t, ok := nameToConcreteType[name]; ok && t != ut.user {
+		panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", name, t, ut.user))
+	}
+	if n, ok := concreteTypeToName[ut.base]; ok && n != name {
+		panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", ut.user, n, name))
+	}
+	// Store the name and type provided by the user....
+	nameToConcreteType[name] = reflect.TypeOf(value)
+	// but the flattened type in the type table, since that's what decode needs.
+	concreteTypeToName[ut.base] = name
+}
+
+// Register records a type, identified by a value for that type, under its
+// internal type name.  That name will identify the concrete type of a value
+// sent or received as an interface variable.  Only types that will be
+// transferred as implementations of interface values need to be registered.
+// Expecting to be used only during initialization, it panics if the mapping
+// between types and names is not a bijection.
+func Register(value interface{}) {
+	// Default to printed representation for unnamed types
+	rt := reflect.TypeOf(value)
+	name := rt.String()
+
+	// But for named types (or pointers to them), qualify with import path (but see inner comment).
+	// Dereference one pointer looking for a named type.
+	star := ""
+	if rt.Name() == "" {
+		if pt := rt; pt.Kind() == reflect.Ptr {
+			star = "*"
+			// NOTE: The following line should be rt = pt.Elem() to implement
+			// what the comment above claims, but fixing it would break compatibility
+			// with existing gobs.
+			//
+			// Given package p imported as "full/p" with these definitions:
+			//     package p
+			//     type T1 struct { ... }
+			// this table shows the intended and actual strings used by gob to
+			// name the types:
+			//
+			// Type      Correct string     Actual string
+			//
+			// T1        full/p.T1          full/p.T1
+			// *T1       *full/p.T1         *p.T1
+			//
+			// The missing full path cannot be fixed without breaking existing gob decoders.
+			rt = pt
+		}
+	}
+	if rt.Name() != "" {
+		if rt.PkgPath() == "" {
+			name = star + rt.Name()
+		} else {
+			name = star + rt.PkgPath() + "." + rt.Name()
+		}
+	}
+
+	RegisterName(name, value)
+}
+
+func registerBasics() {
+	Register(int(0))
+	Register(int8(0))
+	Register(int16(0))
+	Register(int32(0))
+	Register(int64(0))
+	Register(uint(0))
+	Register(uint8(0))
+	Register(uint16(0))
+	Register(uint32(0))
+	Register(uint64(0))
+	Register(float32(0))
+	Register(float64(0))
+	Register(complex64(0i))
+	Register(complex128(0i))
+	Register(uintptr(0))
+	Register(false)
+	Register("")
+	Register([]byte(nil))
+	Register([]int(nil))
+	Register([]int8(nil))
+	Register([]int16(nil))
+	Register([]int32(nil))
+	Register([]int64(nil))
+	Register([]uint(nil))
+	Register([]uint8(nil))
+	Register([]uint16(nil))
+	Register([]uint32(nil))
+	Register([]uint64(nil))
+	Register([]float32(nil))
+	Register([]float64(nil))
+	Register([]complex64(nil))
+	Register([]complex128(nil))
+	Register([]uintptr(nil))
+	Register([]bool(nil))
+	Register([]string(nil))
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/gob/type_test.go b/third_party/gofrontend/libgo/go/encoding/gob/type_test.go
new file mode 100644
index 0000000..e230d22
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/gob/type_test.go
@@ -0,0 +1,222 @@
+// 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 gob
+
+import (
+	"bytes"
+	"reflect"
+	"testing"
+)
+
+type typeT struct {
+	id  typeId
+	str string
+}
+
+var basicTypes = []typeT{
+	{tBool, "bool"},
+	{tInt, "int"},
+	{tUint, "uint"},
+	{tFloat, "float"},
+	{tBytes, "bytes"},
+	{tString, "string"},
+}
+
+func getTypeUnlocked(name string, rt reflect.Type) gobType {
+	typeLock.Lock()
+	defer typeLock.Unlock()
+	t, err := getBaseType(name, rt)
+	if err != nil {
+		panic("getTypeUnlocked: " + err.Error())
+	}
+	return t
+}
+
+// Sanity checks
+func TestBasic(t *testing.T) {
+	for _, tt := range basicTypes {
+		if tt.id.string() != tt.str {
+			t.Errorf("checkType: expected %q got %s", tt.str, tt.id.string())
+		}
+		if tt.id == 0 {
+			t.Errorf("id for %q is zero", tt.str)
+		}
+	}
+}
+
+// Reregister some basic types to check registration is idempotent.
+func TestReregistration(t *testing.T) {
+	newtyp := getTypeUnlocked("int", reflect.TypeOf(int(0)))
+	if newtyp != tInt.gobType() {
+		t.Errorf("reregistration of %s got new type", newtyp.string())
+	}
+	newtyp = getTypeUnlocked("uint", reflect.TypeOf(uint(0)))
+	if newtyp != tUint.gobType() {
+		t.Errorf("reregistration of %s got new type", newtyp.string())
+	}
+	newtyp = getTypeUnlocked("string", reflect.TypeOf("hello"))
+	if newtyp != tString.gobType() {
+		t.Errorf("reregistration of %s got new type", newtyp.string())
+	}
+}
+
+func TestArrayType(t *testing.T) {
+	var a3 [3]int
+	a3int := getTypeUnlocked("foo", reflect.TypeOf(a3))
+	newa3int := getTypeUnlocked("bar", reflect.TypeOf(a3))
+	if a3int != newa3int {
+		t.Errorf("second registration of [3]int creates new type")
+	}
+	var a4 [4]int
+	a4int := getTypeUnlocked("goo", reflect.TypeOf(a4))
+	if a3int == a4int {
+		t.Errorf("registration of [3]int creates same type as [4]int")
+	}
+	var b3 [3]bool
+	a3bool := getTypeUnlocked("", reflect.TypeOf(b3))
+	if a3int == a3bool {
+		t.Errorf("registration of [3]bool creates same type as [3]int")
+	}
+	str := a3bool.string()
+	expected := "[3]bool"
+	if str != expected {
+		t.Errorf("array printed as %q; expected %q", str, expected)
+	}
+}
+
+func TestSliceType(t *testing.T) {
+	var s []int
+	sint := getTypeUnlocked("slice", reflect.TypeOf(s))
+	var news []int
+	newsint := getTypeUnlocked("slice1", reflect.TypeOf(news))
+	if sint != newsint {
+		t.Errorf("second registration of []int creates new type")
+	}
+	var b []bool
+	sbool := getTypeUnlocked("", reflect.TypeOf(b))
+	if sbool == sint {
+		t.Errorf("registration of []bool creates same type as []int")
+	}
+	str := sbool.string()
+	expected := "[]bool"
+	if str != expected {
+		t.Errorf("slice printed as %q; expected %q", str, expected)
+	}
+}
+
+func TestMapType(t *testing.T) {
+	var m map[string]int
+	mapStringInt := getTypeUnlocked("map", reflect.TypeOf(m))
+	var newm map[string]int
+	newMapStringInt := getTypeUnlocked("map1", reflect.TypeOf(newm))
+	if mapStringInt != newMapStringInt {
+		t.Errorf("second registration of map[string]int creates new type")
+	}
+	var b map[string]bool
+	mapStringBool := getTypeUnlocked("", reflect.TypeOf(b))
+	if mapStringBool == mapStringInt {
+		t.Errorf("registration of map[string]bool creates same type as map[string]int")
+	}
+	str := mapStringBool.string()
+	expected := "map[string]bool"
+	if str != expected {
+		t.Errorf("map printed as %q; expected %q", str, expected)
+	}
+}
+
+type Bar struct {
+	X string
+}
+
+// This structure has pointers and refers to itself, making it a good test case.
+type Foo struct {
+	A int
+	B int32 // will become int
+	C string
+	D []byte
+	E *float64    // will become float64
+	F ****float64 // will become float64
+	G *Bar
+	H *Bar // should not interpolate the definition of Bar again
+	I *Foo // will not explode
+}
+
+func TestStructType(t *testing.T) {
+	sstruct := getTypeUnlocked("Foo", reflect.TypeOf(Foo{}))
+	str := sstruct.string()
+	// If we can print it correctly, we built it correctly.
+	expected := "Foo = struct { A int; B int; C string; D bytes; E float; F float; G Bar = struct { X string; }; H Bar; I Foo; }"
+	if str != expected {
+		t.Errorf("struct printed as %q; expected %q", str, expected)
+	}
+}
+
+// Should be OK to register the same type multiple times, as long as they're
+// at the same level of indirection.
+func TestRegistration(t *testing.T) {
+	type T struct{ a int }
+	Register(new(T))
+	Register(new(T))
+}
+
+type N1 struct{}
+type N2 struct{}
+
+// See comment in type.go/Register.
+func TestRegistrationNaming(t *testing.T) {
+	testCases := []struct {
+		t    interface{}
+		name string
+	}{
+		{&N1{}, "*gob.N1"},
+		{N2{}, "encoding/gob.N2"},
+	}
+
+	for _, tc := range testCases {
+		Register(tc.t)
+
+		tct := reflect.TypeOf(tc.t)
+		registerLock.RLock()
+		ct := nameToConcreteType[tc.name]
+		registerLock.RUnlock()
+		if ct != tct {
+			t.Errorf("nameToConcreteType[%q] = %v, want %v", tc.name, ct, tct)
+		}
+		// concreteTypeToName is keyed off the base type.
+		if tct.Kind() == reflect.Ptr {
+			tct = tct.Elem()
+		}
+		if n := concreteTypeToName[tct]; n != tc.name {
+			t.Errorf("concreteTypeToName[%v] got %v, want %v", tct, n, tc.name)
+		}
+	}
+}
+
+func TestStressParallel(t *testing.T) {
+	type T2 struct{ A int }
+	c := make(chan bool)
+	const N = 10
+	for i := 0; i < N; i++ {
+		go func() {
+			p := new(T2)
+			Register(p)
+			b := new(bytes.Buffer)
+			enc := NewEncoder(b)
+			err := enc.Encode(p)
+			if err != nil {
+				t.Error("encoder fail:", err)
+			}
+			dec := NewDecoder(b)
+			err = dec.Decode(p)
+			if err != nil {
+				t.Error("decoder fail:", err)
+			}
+			c <- true
+		}()
+	}
+	for i := 0; i < N; i++ {
+		<-c
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/hex/hex.go b/third_party/gofrontend/libgo/go/encoding/hex/hex.go
new file mode 100644
index 0000000..d1fc702
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/hex/hex.go
@@ -0,0 +1,216 @@
+// 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 hex implements hexadecimal encoding and decoding.
+package hex
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+)
+
+const hextable = "0123456789abcdef"
+
+// EncodedLen returns the length of an encoding of n source bytes.
+func EncodedLen(n int) int { return n * 2 }
+
+// Encode encodes src into EncodedLen(len(src))
+// bytes of dst.  As a convenience, it returns the number
+// of bytes written to dst, but this value is always EncodedLen(len(src)).
+// Encode implements hexadecimal encoding.
+func Encode(dst, src []byte) int {
+	for i, v := range src {
+		dst[i*2] = hextable[v>>4]
+		dst[i*2+1] = hextable[v&0x0f]
+	}
+
+	return len(src) * 2
+}
+
+// ErrLength results from decoding an odd length slice.
+var ErrLength = errors.New("encoding/hex: odd length hex string")
+
+// InvalidByteError values describe errors resulting from an invalid byte in a hex string.
+type InvalidByteError byte
+
+func (e InvalidByteError) Error() string {
+	return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e))
+}
+
+func DecodedLen(x int) int { return x / 2 }
+
+// Decode decodes src into DecodedLen(len(src)) bytes, returning the actual
+// number of bytes written to dst.
+//
+// If Decode encounters invalid input, it returns an error describing the failure.
+func Decode(dst, src []byte) (int, error) {
+	if len(src)%2 == 1 {
+		return 0, ErrLength
+	}
+
+	for i := 0; i < len(src)/2; i++ {
+		a, ok := fromHexChar(src[i*2])
+		if !ok {
+			return 0, InvalidByteError(src[i*2])
+		}
+		b, ok := fromHexChar(src[i*2+1])
+		if !ok {
+			return 0, InvalidByteError(src[i*2+1])
+		}
+		dst[i] = (a << 4) | b
+	}
+
+	return len(src) / 2, nil
+}
+
+// fromHexChar converts a hex character into its value and a success flag.
+func fromHexChar(c byte) (byte, bool) {
+	switch {
+	case '0' <= c && c <= '9':
+		return c - '0', true
+	case 'a' <= c && c <= 'f':
+		return c - 'a' + 10, true
+	case 'A' <= c && c <= 'F':
+		return c - 'A' + 10, true
+	}
+
+	return 0, false
+}
+
+// EncodeToString returns the hexadecimal encoding of src.
+func EncodeToString(src []byte) string {
+	dst := make([]byte, EncodedLen(len(src)))
+	Encode(dst, src)
+	return string(dst)
+}
+
+// DecodeString returns the bytes represented by the hexadecimal string s.
+func DecodeString(s string) ([]byte, error) {
+	src := []byte(s)
+	dst := make([]byte, DecodedLen(len(src)))
+	_, err := Decode(dst, src)
+	if err != nil {
+		return nil, err
+	}
+	return dst, nil
+}
+
+// Dump returns a string that contains a hex dump of the given data. The format
+// of the hex dump matches the output of `hexdump -C` on the command line.
+func Dump(data []byte) string {
+	var buf bytes.Buffer
+	dumper := Dumper(&buf)
+	dumper.Write(data)
+	dumper.Close()
+	return string(buf.Bytes())
+}
+
+// Dumper returns a WriteCloser that writes a hex dump of all written data to
+// w. The format of the dump matches the output of `hexdump -C` on the command
+// line.
+func Dumper(w io.Writer) io.WriteCloser {
+	return &dumper{w: w}
+}
+
+type dumper struct {
+	w          io.Writer
+	rightChars [18]byte
+	buf        [14]byte
+	used       int  // number of bytes in the current line
+	n          uint // number of bytes, total
+}
+
+func toChar(b byte) byte {
+	if b < 32 || b > 126 {
+		return '.'
+	}
+	return b
+}
+
+func (h *dumper) Write(data []byte) (n int, err error) {
+	// Output lines look like:
+	// 00000010  2e 2f 30 31 32 33 34 35  36 37 38 39 3a 3b 3c 3d  |./0123456789:;<=|
+	// ^ offset                          ^ extra space              ^ ASCII of line.
+	for i := range data {
+		if h.used == 0 {
+			// At the beginning of a line we print the current
+			// offset in hex.
+			h.buf[0] = byte(h.n >> 24)
+			h.buf[1] = byte(h.n >> 16)
+			h.buf[2] = byte(h.n >> 8)
+			h.buf[3] = byte(h.n)
+			Encode(h.buf[4:], h.buf[:4])
+			h.buf[12] = ' '
+			h.buf[13] = ' '
+			_, err = h.w.Write(h.buf[4:])
+			if err != nil {
+				return
+			}
+		}
+		Encode(h.buf[:], data[i:i+1])
+		h.buf[2] = ' '
+		l := 3
+		if h.used == 7 {
+			// There's an additional space after the 8th byte.
+			h.buf[3] = ' '
+			l = 4
+		} else if h.used == 15 {
+			// At the end of the line there's an extra space and
+			// the bar for the right column.
+			h.buf[3] = ' '
+			h.buf[4] = '|'
+			l = 5
+		}
+		_, err = h.w.Write(h.buf[:l])
+		if err != nil {
+			return
+		}
+		n++
+		h.rightChars[h.used] = toChar(data[i])
+		h.used++
+		h.n++
+		if h.used == 16 {
+			h.rightChars[16] = '|'
+			h.rightChars[17] = '\n'
+			_, err = h.w.Write(h.rightChars[:])
+			if err != nil {
+				return
+			}
+			h.used = 0
+		}
+	}
+	return
+}
+
+func (h *dumper) Close() (err error) {
+	// See the comments in Write() for the details of this format.
+	if h.used == 0 {
+		return
+	}
+	h.buf[0] = ' '
+	h.buf[1] = ' '
+	h.buf[2] = ' '
+	h.buf[3] = ' '
+	h.buf[4] = '|'
+	nBytes := h.used
+	for h.used < 16 {
+		l := 3
+		if h.used == 7 {
+			l = 4
+		} else if h.used == 15 {
+			l = 5
+		}
+		_, err = h.w.Write(h.buf[:l])
+		if err != nil {
+			return
+		}
+		h.used++
+	}
+	h.rightChars[nBytes] = '|'
+	h.rightChars[nBytes+1] = '\n'
+	_, err = h.w.Write(h.rightChars[:nBytes+2])
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/hex/hex_test.go b/third_party/gofrontend/libgo/go/encoding/hex/hex_test.go
new file mode 100644
index 0000000..b969636
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/hex/hex_test.go
@@ -0,0 +1,153 @@
+// 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 hex
+
+import (
+	"bytes"
+	"testing"
+)
+
+type encDecTest struct {
+	enc string
+	dec []byte
+}
+
+var encDecTests = []encDecTest{
+	{"", []byte{}},
+	{"0001020304050607", []byte{0, 1, 2, 3, 4, 5, 6, 7}},
+	{"08090a0b0c0d0e0f", []byte{8, 9, 10, 11, 12, 13, 14, 15}},
+	{"f0f1f2f3f4f5f6f7", []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}},
+	{"f8f9fafbfcfdfeff", []byte{0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}},
+	{"67", []byte{'g'}},
+	{"e3a1", []byte{0xe3, 0xa1}},
+}
+
+func TestEncode(t *testing.T) {
+	for i, test := range encDecTests {
+		dst := make([]byte, EncodedLen(len(test.dec)))
+		n := Encode(dst, test.dec)
+		if n != len(dst) {
+			t.Errorf("#%d: bad return value: got: %d want: %d", i, n, len(dst))
+		}
+		if string(dst) != test.enc {
+			t.Errorf("#%d: got: %#v want: %#v", i, dst, test.enc)
+		}
+	}
+}
+
+func TestDecode(t *testing.T) {
+	// Case for decoding uppercase hex characters, since
+	// Encode always uses lowercase.
+	decTests := append(encDecTests, encDecTest{"F8F9FAFBFCFDFEFF", []byte{0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}})
+	for i, test := range decTests {
+		dst := make([]byte, DecodedLen(len(test.enc)))
+		n, err := Decode(dst, []byte(test.enc))
+		if err != nil {
+			t.Errorf("#%d: bad return value: got:%d want:%d", i, n, len(dst))
+		} else if !bytes.Equal(dst, test.dec) {
+			t.Errorf("#%d: got: %#v want: %#v", i, dst, test.dec)
+		}
+	}
+}
+
+func TestEncodeToString(t *testing.T) {
+	for i, test := range encDecTests {
+		s := EncodeToString(test.dec)
+		if s != test.enc {
+			t.Errorf("#%d got:%s want:%s", i, s, test.enc)
+		}
+	}
+}
+
+func TestDecodeString(t *testing.T) {
+	for i, test := range encDecTests {
+		dst, err := DecodeString(test.enc)
+		if err != nil {
+			t.Errorf("#%d: unexpected err value: %s", i, err)
+			continue
+		}
+		if !bytes.Equal(dst, test.dec) {
+			t.Errorf("#%d: got: %#v want: #%v", i, dst, test.dec)
+		}
+	}
+}
+
+type errTest struct {
+	in  string
+	err string
+}
+
+var errTests = []errTest{
+	{"0", "encoding/hex: odd length hex string"},
+	{"0g", "encoding/hex: invalid byte: U+0067 'g'"},
+	{"00gg", "encoding/hex: invalid byte: U+0067 'g'"},
+	{"0\x01", "encoding/hex: invalid byte: U+0001"},
+}
+
+func TestInvalidErr(t *testing.T) {
+	for i, test := range errTests {
+		dst := make([]byte, DecodedLen(len(test.in)))
+		_, err := Decode(dst, []byte(test.in))
+		if err == nil {
+			t.Errorf("#%d: expected error; got none", i)
+		} else if err.Error() != test.err {
+			t.Errorf("#%d: got: %v want: %v", i, err, test.err)
+		}
+	}
+}
+
+func TestInvalidStringErr(t *testing.T) {
+	for i, test := range errTests {
+		_, err := DecodeString(test.in)
+		if err == nil {
+			t.Errorf("#%d: expected error; got none", i)
+		} else if err.Error() != test.err {
+			t.Errorf("#%d: got: %v want: %v", i, err, test.err)
+		}
+	}
+}
+
+func TestDumper(t *testing.T) {
+	var in [40]byte
+	for i := range in {
+		in[i] = byte(i + 30)
+	}
+
+	for stride := 1; stride < len(in); stride++ {
+		var out bytes.Buffer
+		dumper := Dumper(&out)
+		done := 0
+		for done < len(in) {
+			todo := done + stride
+			if todo > len(in) {
+				todo = len(in)
+			}
+			dumper.Write(in[done:todo])
+			done = todo
+		}
+
+		dumper.Close()
+		if !bytes.Equal(out.Bytes(), expectedHexDump) {
+			t.Errorf("stride: %d failed. got:\n%s\nwant:\n%s", stride, out.Bytes(), expectedHexDump)
+		}
+	}
+}
+
+func TestDump(t *testing.T) {
+	var in [40]byte
+	for i := range in {
+		in[i] = byte(i + 30)
+	}
+
+	out := []byte(Dump(in[:]))
+	if !bytes.Equal(out, expectedHexDump) {
+		t.Errorf("got:\n%s\nwant:\n%s", out, expectedHexDump)
+	}
+}
+
+var expectedHexDump = []byte(`00000000  1e 1f 20 21 22 23 24 25  26 27 28 29 2a 2b 2c 2d  |.. !"#$%&'()*+,-|
+00000010  2e 2f 30 31 32 33 34 35  36 37 38 39 3a 3b 3c 3d  |./0123456789:;<=|
+00000020  3e 3f 40 41 42 43 44 45                           |>?@ABCDE|
+`)
diff --git a/third_party/gofrontend/libgo/go/encoding/json/bench_test.go b/third_party/gofrontend/libgo/go/encoding/json/bench_test.go
new file mode 100644
index 0000000..29dbc26
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/bench_test.go
@@ -0,0 +1,189 @@
+// 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.
+
+// Large data benchmark.
+// The JSON data is a summary of agl's changes in the
+// go, webkit, and chromium open source projects.
+// We benchmark converting between the JSON form
+// and in-memory data structures.
+
+package json
+
+import (
+	"bytes"
+	"compress/gzip"
+	"io/ioutil"
+	"os"
+	"testing"
+)
+
+type codeResponse struct {
+	Tree     *codeNode `json:"tree"`
+	Username string    `json:"username"`
+}
+
+type codeNode struct {
+	Name     string      `json:"name"`
+	Kids     []*codeNode `json:"kids"`
+	CLWeight float64     `json:"cl_weight"`
+	Touches  int         `json:"touches"`
+	MinT     int64       `json:"min_t"`
+	MaxT     int64       `json:"max_t"`
+	MeanT    int64       `json:"mean_t"`
+}
+
+var codeJSON []byte
+var codeStruct codeResponse
+
+func codeInit() {
+	f, err := os.Open("testdata/code.json.gz")
+	if err != nil {
+		panic(err)
+	}
+	defer f.Close()
+	gz, err := gzip.NewReader(f)
+	if err != nil {
+		panic(err)
+	}
+	data, err := ioutil.ReadAll(gz)
+	if err != nil {
+		panic(err)
+	}
+
+	codeJSON = data
+
+	if err := Unmarshal(codeJSON, &codeStruct); err != nil {
+		panic("unmarshal code.json: " + err.Error())
+	}
+
+	if data, err = Marshal(&codeStruct); err != nil {
+		panic("marshal code.json: " + err.Error())
+	}
+
+	if !bytes.Equal(data, codeJSON) {
+		println("different lengths", len(data), len(codeJSON))
+		for i := 0; i < len(data) && i < len(codeJSON); i++ {
+			if data[i] != codeJSON[i] {
+				println("re-marshal: changed at byte", i)
+				println("orig: ", string(codeJSON[i-10:i+10]))
+				println("new: ", string(data[i-10:i+10]))
+				break
+			}
+		}
+		panic("re-marshal code.json: different result")
+	}
+}
+
+func BenchmarkCodeEncoder(b *testing.B) {
+	if codeJSON == nil {
+		b.StopTimer()
+		codeInit()
+		b.StartTimer()
+	}
+	enc := NewEncoder(ioutil.Discard)
+	for i := 0; i < b.N; i++ {
+		if err := enc.Encode(&codeStruct); err != nil {
+			b.Fatal("Encode:", err)
+		}
+	}
+	b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeMarshal(b *testing.B) {
+	if codeJSON == nil {
+		b.StopTimer()
+		codeInit()
+		b.StartTimer()
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := Marshal(&codeStruct); err != nil {
+			b.Fatal("Marshal:", err)
+		}
+	}
+	b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeDecoder(b *testing.B) {
+	if codeJSON == nil {
+		b.StopTimer()
+		codeInit()
+		b.StartTimer()
+	}
+	var buf bytes.Buffer
+	dec := NewDecoder(&buf)
+	var r codeResponse
+	for i := 0; i < b.N; i++ {
+		buf.Write(codeJSON)
+		// hide EOF
+		buf.WriteByte('\n')
+		buf.WriteByte('\n')
+		buf.WriteByte('\n')
+		if err := dec.Decode(&r); err != nil {
+			b.Fatal("Decode:", err)
+		}
+	}
+	b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeUnmarshal(b *testing.B) {
+	if codeJSON == nil {
+		b.StopTimer()
+		codeInit()
+		b.StartTimer()
+	}
+	for i := 0; i < b.N; i++ {
+		var r codeResponse
+		if err := Unmarshal(codeJSON, &r); err != nil {
+			b.Fatal("Unmmarshal:", err)
+		}
+	}
+	b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeUnmarshalReuse(b *testing.B) {
+	if codeJSON == nil {
+		b.StopTimer()
+		codeInit()
+		b.StartTimer()
+	}
+	var r codeResponse
+	for i := 0; i < b.N; i++ {
+		if err := Unmarshal(codeJSON, &r); err != nil {
+			b.Fatal("Unmmarshal:", err)
+		}
+	}
+}
+
+func BenchmarkUnmarshalString(b *testing.B) {
+	data := []byte(`"hello, world"`)
+	var s string
+
+	for i := 0; i < b.N; i++ {
+		if err := Unmarshal(data, &s); err != nil {
+			b.Fatal("Unmarshal:", err)
+		}
+	}
+}
+
+func BenchmarkUnmarshalFloat64(b *testing.B) {
+	var f float64
+	data := []byte(`3.14`)
+
+	for i := 0; i < b.N; i++ {
+		if err := Unmarshal(data, &f); err != nil {
+			b.Fatal("Unmarshal:", err)
+		}
+	}
+}
+
+func BenchmarkUnmarshalInt64(b *testing.B) {
+	var x int64
+	data := []byte(`3`)
+
+	for i := 0; i < b.N; i++ {
+		if err := Unmarshal(data, &x); err != nil {
+			b.Fatal("Unmarshal:", err)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/decode.go b/third_party/gofrontend/libgo/go/encoding/json/decode.go
new file mode 100644
index 0000000..af1c908
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/decode.go
@@ -0,0 +1,1050 @@
+// Copyright 2010 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.
+
+// Represents JSON data structure using native Go types: booleans, floats,
+// strings, arrays, and maps.
+
+package json
+
+import (
+	"bytes"
+	"encoding"
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"reflect"
+	"runtime"
+	"strconv"
+	"unicode"
+	"unicode/utf16"
+	"unicode/utf8"
+)
+
+// Unmarshal parses the JSON-encoded data and stores the result
+// in the value pointed to by v.
+//
+// Unmarshal uses the inverse of the encodings that
+// Marshal uses, allocating maps, slices, and pointers as necessary,
+// with the following additional rules:
+//
+// To unmarshal JSON into a pointer, Unmarshal first handles the case of
+// the JSON being the JSON literal null.  In that case, Unmarshal sets
+// the pointer to nil.  Otherwise, Unmarshal unmarshals the JSON into
+// the value pointed at by the pointer.  If the pointer is nil, Unmarshal
+// allocates a new value for it to point to.
+//
+// To unmarshal JSON into a struct, Unmarshal matches incoming object
+// keys to the keys used by Marshal (either the struct field name or its tag),
+// preferring an exact match but also accepting a case-insensitive match.
+//
+// To unmarshal JSON into an interface value,
+// Unmarshal stores one of these in the interface value:
+//
+//	bool, for JSON booleans
+//	float64, for JSON numbers
+//	string, for JSON strings
+//	[]interface{}, for JSON arrays
+//	map[string]interface{}, for JSON objects
+//	nil for JSON null
+//
+// If a JSON value is not appropriate for a given target type,
+// or if a JSON number overflows the target type, Unmarshal
+// skips that field and completes the unmarshalling as best it can.
+// If no more serious errors are encountered, Unmarshal returns
+// an UnmarshalTypeError describing the earliest such error.
+//
+// The JSON null value unmarshals into an interface, map, pointer, or slice
+// by setting that Go value to nil. Because null is often used in JSON to mean
+// ``not present,'' unmarshaling a JSON null into any other Go type has no effect
+// on the value and produces no error.
+//
+// When unmarshaling quoted strings, invalid UTF-8 or
+// invalid UTF-16 surrogate pairs are not treated as an error.
+// Instead, they are replaced by the Unicode replacement
+// character U+FFFD.
+//
+func Unmarshal(data []byte, v interface{}) error {
+	// Check for well-formedness.
+	// Avoids filling out half a data structure
+	// before discovering a JSON syntax error.
+	var d decodeState
+	err := checkValid(data, &d.scan)
+	if err != nil {
+		return err
+	}
+
+	d.init(data)
+	return d.unmarshal(v)
+}
+
+// Unmarshaler is the interface implemented by objects
+// that can unmarshal a JSON description of themselves.
+// The input can be assumed to be a valid encoding of
+// a JSON value. UnmarshalJSON must copy the JSON data
+// if it wishes to retain the data after returning.
+type Unmarshaler interface {
+	UnmarshalJSON([]byte) error
+}
+
+// An UnmarshalTypeError describes a JSON value that was
+// not appropriate for a value of a specific Go type.
+type UnmarshalTypeError struct {
+	Value string       // description of JSON value - "bool", "array", "number -5"
+	Type  reflect.Type // type of Go value it could not be assigned to
+}
+
+func (e *UnmarshalTypeError) Error() string {
+	return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
+}
+
+// An UnmarshalFieldError describes a JSON object key that
+// led to an unexported (and therefore unwritable) struct field.
+// (No longer used; kept for compatibility.)
+type UnmarshalFieldError struct {
+	Key   string
+	Type  reflect.Type
+	Field reflect.StructField
+}
+
+func (e *UnmarshalFieldError) Error() string {
+	return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
+}
+
+// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
+// (The argument to Unmarshal must be a non-nil pointer.)
+type InvalidUnmarshalError struct {
+	Type reflect.Type
+}
+
+func (e *InvalidUnmarshalError) Error() string {
+	if e.Type == nil {
+		return "json: Unmarshal(nil)"
+	}
+
+	if e.Type.Kind() != reflect.Ptr {
+		return "json: Unmarshal(non-pointer " + e.Type.String() + ")"
+	}
+	return "json: Unmarshal(nil " + e.Type.String() + ")"
+}
+
+func (d *decodeState) unmarshal(v interface{}) (err error) {
+	defer func() {
+		if r := recover(); r != nil {
+			if _, ok := r.(runtime.Error); ok {
+				panic(r)
+			}
+			err = r.(error)
+		}
+	}()
+
+	rv := reflect.ValueOf(v)
+	if rv.Kind() != reflect.Ptr || rv.IsNil() {
+		return &InvalidUnmarshalError{reflect.TypeOf(v)}
+	}
+
+	d.scan.reset()
+	// We decode rv not rv.Elem because the Unmarshaler interface
+	// test must be applied at the top level of the value.
+	d.value(rv)
+	return d.savedError
+}
+
+// A Number represents a JSON number literal.
+type Number string
+
+// String returns the literal text of the number.
+func (n Number) String() string { return string(n) }
+
+// Float64 returns the number as a float64.
+func (n Number) Float64() (float64, error) {
+	return strconv.ParseFloat(string(n), 64)
+}
+
+// Int64 returns the number as an int64.
+func (n Number) Int64() (int64, error) {
+	return strconv.ParseInt(string(n), 10, 64)
+}
+
+// decodeState represents the state while decoding a JSON value.
+type decodeState struct {
+	data       []byte
+	off        int // read offset in data
+	scan       scanner
+	nextscan   scanner // for calls to nextValue
+	savedError error
+	tempstr    string // scratch space to avoid some allocations
+	useNumber  bool
+}
+
+// errPhase is used for errors that should not happen unless
+// there is a bug in the JSON decoder or something is editing
+// the data slice while the decoder executes.
+var errPhase = errors.New("JSON decoder out of sync - data changing underfoot?")
+
+func (d *decodeState) init(data []byte) *decodeState {
+	d.data = data
+	d.off = 0
+	d.savedError = nil
+	return d
+}
+
+// error aborts the decoding by panicking with err.
+func (d *decodeState) error(err error) {
+	panic(err)
+}
+
+// saveError saves the first err it is called with,
+// for reporting at the end of the unmarshal.
+func (d *decodeState) saveError(err error) {
+	if d.savedError == nil {
+		d.savedError = err
+	}
+}
+
+// next cuts off and returns the next full JSON value in d.data[d.off:].
+// The next value is known to be an object or array, not a literal.
+func (d *decodeState) next() []byte {
+	c := d.data[d.off]
+	item, rest, err := nextValue(d.data[d.off:], &d.nextscan)
+	if err != nil {
+		d.error(err)
+	}
+	d.off = len(d.data) - len(rest)
+
+	// Our scanner has seen the opening brace/bracket
+	// and thinks we're still in the middle of the object.
+	// invent a closing brace/bracket to get it out.
+	if c == '{' {
+		d.scan.step(&d.scan, '}')
+	} else {
+		d.scan.step(&d.scan, ']')
+	}
+
+	return item
+}
+
+// scanWhile processes bytes in d.data[d.off:] until it
+// receives a scan code not equal to op.
+// It updates d.off and returns the new scan code.
+func (d *decodeState) scanWhile(op int) int {
+	var newOp int
+	for {
+		if d.off >= len(d.data) {
+			newOp = d.scan.eof()
+			d.off = len(d.data) + 1 // mark processed EOF with len+1
+		} else {
+			c := int(d.data[d.off])
+			d.off++
+			newOp = d.scan.step(&d.scan, c)
+		}
+		if newOp != op {
+			break
+		}
+	}
+	return newOp
+}
+
+// value decodes a JSON value from d.data[d.off:] into the value.
+// it updates d.off to point past the decoded value.
+func (d *decodeState) value(v reflect.Value) {
+	if !v.IsValid() {
+		_, rest, err := nextValue(d.data[d.off:], &d.nextscan)
+		if err != nil {
+			d.error(err)
+		}
+		d.off = len(d.data) - len(rest)
+
+		// d.scan thinks we're still at the beginning of the item.
+		// Feed in an empty string - the shortest, simplest value -
+		// so that it knows we got to the end of the value.
+		if d.scan.redo {
+			// rewind.
+			d.scan.redo = false
+			d.scan.step = stateBeginValue
+		}
+		d.scan.step(&d.scan, '"')
+		d.scan.step(&d.scan, '"')
+
+		n := len(d.scan.parseState)
+		if n > 0 && d.scan.parseState[n-1] == parseObjectKey {
+			// d.scan thinks we just read an object key; finish the object
+			d.scan.step(&d.scan, ':')
+			d.scan.step(&d.scan, '"')
+			d.scan.step(&d.scan, '"')
+			d.scan.step(&d.scan, '}')
+		}
+
+		return
+	}
+
+	switch op := d.scanWhile(scanSkipSpace); op {
+	default:
+		d.error(errPhase)
+
+	case scanBeginArray:
+		d.array(v)
+
+	case scanBeginObject:
+		d.object(v)
+
+	case scanBeginLiteral:
+		d.literal(v)
+	}
+}
+
+// indirect walks down v allocating pointers as needed,
+// until it gets to a non-pointer.
+// if it encounters an Unmarshaler, indirect stops and returns that.
+// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
+func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
+	// If v is a named type and is addressable,
+	// start with its address, so that if the type has pointer methods,
+	// we find them.
+	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
+		v = v.Addr()
+	}
+	for {
+		// Load value from interface, but only if the result will be
+		// usefully addressable.
+		if v.Kind() == reflect.Interface && !v.IsNil() {
+			e := v.Elem()
+			if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
+				v = e
+				continue
+			}
+		}
+
+		if v.Kind() != reflect.Ptr {
+			break
+		}
+
+		if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
+			break
+		}
+		if v.IsNil() {
+			v.Set(reflect.New(v.Type().Elem()))
+		}
+		if v.Type().NumMethod() > 0 {
+			if u, ok := v.Interface().(Unmarshaler); ok {
+				return u, nil, reflect.Value{}
+			}
+			if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
+				return nil, u, reflect.Value{}
+			}
+		}
+		v = v.Elem()
+	}
+	return nil, nil, v
+}
+
+// array consumes an array from d.data[d.off-1:], decoding into the value v.
+// the first byte of the array ('[') has been read already.
+func (d *decodeState) array(v reflect.Value) {
+	// Check for unmarshaler.
+	u, ut, pv := d.indirect(v, false)
+	if u != nil {
+		d.off--
+		err := u.UnmarshalJSON(d.next())
+		if err != nil {
+			d.error(err)
+		}
+		return
+	}
+	if ut != nil {
+		d.saveError(&UnmarshalTypeError{"array", v.Type()})
+		d.off--
+		d.next()
+		return
+	}
+
+	v = pv
+
+	// Check type of target.
+	switch v.Kind() {
+	case reflect.Interface:
+		if v.NumMethod() == 0 {
+			// Decoding into nil interface?  Switch to non-reflect code.
+			v.Set(reflect.ValueOf(d.arrayInterface()))
+			return
+		}
+		// Otherwise it's invalid.
+		fallthrough
+	default:
+		d.saveError(&UnmarshalTypeError{"array", v.Type()})
+		d.off--
+		d.next()
+		return
+	case reflect.Array:
+	case reflect.Slice:
+		break
+	}
+
+	i := 0
+	for {
+		// Look ahead for ] - can only happen on first iteration.
+		op := d.scanWhile(scanSkipSpace)
+		if op == scanEndArray {
+			break
+		}
+
+		// Back up so d.value can have the byte we just read.
+		d.off--
+		d.scan.undo(op)
+
+		// Get element of array, growing if necessary.
+		if v.Kind() == reflect.Slice {
+			// Grow slice if necessary
+			if i >= v.Cap() {
+				newcap := v.Cap() + v.Cap()/2
+				if newcap < 4 {
+					newcap = 4
+				}
+				newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
+				reflect.Copy(newv, v)
+				v.Set(newv)
+			}
+			if i >= v.Len() {
+				v.SetLen(i + 1)
+			}
+		}
+
+		if i < v.Len() {
+			// Decode into element.
+			d.value(v.Index(i))
+		} else {
+			// Ran out of fixed array: skip.
+			d.value(reflect.Value{})
+		}
+		i++
+
+		// Next token must be , or ].
+		op = d.scanWhile(scanSkipSpace)
+		if op == scanEndArray {
+			break
+		}
+		if op != scanArrayValue {
+			d.error(errPhase)
+		}
+	}
+
+	if i < v.Len() {
+		if v.Kind() == reflect.Array {
+			// Array.  Zero the rest.
+			z := reflect.Zero(v.Type().Elem())
+			for ; i < v.Len(); i++ {
+				v.Index(i).Set(z)
+			}
+		} else {
+			v.SetLen(i)
+		}
+	}
+	if i == 0 && v.Kind() == reflect.Slice {
+		v.Set(reflect.MakeSlice(v.Type(), 0, 0))
+	}
+}
+
+// object consumes an object from d.data[d.off-1:], decoding into the value v.
+// the first byte of the object ('{') has been read already.
+func (d *decodeState) object(v reflect.Value) {
+	// Check for unmarshaler.
+	u, ut, pv := d.indirect(v, false)
+	if u != nil {
+		d.off--
+		err := u.UnmarshalJSON(d.next())
+		if err != nil {
+			d.error(err)
+		}
+		return
+	}
+	if ut != nil {
+		d.saveError(&UnmarshalTypeError{"object", v.Type()})
+		d.off--
+		d.next() // skip over { } in input
+		return
+	}
+	v = pv
+
+	// Decoding into nil interface?  Switch to non-reflect code.
+	if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
+		v.Set(reflect.ValueOf(d.objectInterface()))
+		return
+	}
+
+	// Check type of target: struct or map[string]T
+	switch v.Kind() {
+	case reflect.Map:
+		// map must have string kind
+		t := v.Type()
+		if t.Key().Kind() != reflect.String {
+			d.saveError(&UnmarshalTypeError{"object", v.Type()})
+			break
+		}
+		if v.IsNil() {
+			v.Set(reflect.MakeMap(t))
+		}
+	case reflect.Struct:
+
+	default:
+		d.saveError(&UnmarshalTypeError{"object", v.Type()})
+		d.off--
+		d.next() // skip over { } in input
+		return
+	}
+
+	var mapElem reflect.Value
+
+	for {
+		// Read opening " of string key or closing }.
+		op := d.scanWhile(scanSkipSpace)
+		if op == scanEndObject {
+			// closing } - can only happen on first iteration.
+			break
+		}
+		if op != scanBeginLiteral {
+			d.error(errPhase)
+		}
+
+		// Read key.
+		start := d.off - 1
+		op = d.scanWhile(scanContinue)
+		item := d.data[start : d.off-1]
+		key, ok := unquoteBytes(item)
+		if !ok {
+			d.error(errPhase)
+		}
+
+		// Figure out field corresponding to key.
+		var subv reflect.Value
+		destring := false // whether the value is wrapped in a string to be decoded first
+
+		if v.Kind() == reflect.Map {
+			elemType := v.Type().Elem()
+			if !mapElem.IsValid() {
+				mapElem = reflect.New(elemType).Elem()
+			} else {
+				mapElem.Set(reflect.Zero(elemType))
+			}
+			subv = mapElem
+		} else {
+			var f *field
+			fields := cachedTypeFields(v.Type())
+			for i := range fields {
+				ff := &fields[i]
+				if bytes.Equal(ff.nameBytes, key) {
+					f = ff
+					break
+				}
+				if f == nil && ff.equalFold(ff.nameBytes, key) {
+					f = ff
+				}
+			}
+			if f != nil {
+				subv = v
+				destring = f.quoted
+				for _, i := range f.index {
+					if subv.Kind() == reflect.Ptr {
+						if subv.IsNil() {
+							subv.Set(reflect.New(subv.Type().Elem()))
+						}
+						subv = subv.Elem()
+					}
+					subv = subv.Field(i)
+				}
+			}
+		}
+
+		// Read : before value.
+		if op == scanSkipSpace {
+			op = d.scanWhile(scanSkipSpace)
+		}
+		if op != scanObjectKey {
+			d.error(errPhase)
+		}
+
+		// Read value.
+		if destring {
+			d.value(reflect.ValueOf(&d.tempstr))
+			d.literalStore([]byte(d.tempstr), subv, true)
+			d.tempstr = "" // Zero scratch space for successive values.
+		} else {
+			d.value(subv)
+		}
+
+		// Write value back to map;
+		// if using struct, subv points into struct already.
+		if v.Kind() == reflect.Map {
+			kv := reflect.ValueOf(key).Convert(v.Type().Key())
+			v.SetMapIndex(kv, subv)
+		}
+
+		// Next token must be , or }.
+		op = d.scanWhile(scanSkipSpace)
+		if op == scanEndObject {
+			break
+		}
+		if op != scanObjectValue {
+			d.error(errPhase)
+		}
+	}
+}
+
+// literal consumes a literal from d.data[d.off-1:], decoding into the value v.
+// The first byte of the literal has been read already
+// (that's how the caller knows it's a literal).
+func (d *decodeState) literal(v reflect.Value) {
+	// All bytes inside literal return scanContinue op code.
+	start := d.off - 1
+	op := d.scanWhile(scanContinue)
+
+	// Scan read one byte too far; back up.
+	d.off--
+	d.scan.undo(op)
+
+	d.literalStore(d.data[start:d.off], v, false)
+}
+
+// convertNumber converts the number literal s to a float64 or a Number
+// depending on the setting of d.useNumber.
+func (d *decodeState) convertNumber(s string) (interface{}, error) {
+	if d.useNumber {
+		return Number(s), nil
+	}
+	f, err := strconv.ParseFloat(s, 64)
+	if err != nil {
+		return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0)}
+	}
+	return f, nil
+}
+
+var numberType = reflect.TypeOf(Number(""))
+
+// literalStore decodes a literal stored in item into v.
+//
+// fromQuoted indicates whether this literal came from unwrapping a
+// string from the ",string" struct tag option. this is used only to
+// produce more helpful error messages.
+func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) {
+	// Check for unmarshaler.
+	if len(item) == 0 {
+		//Empty string given
+		d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+		return
+	}
+	wantptr := item[0] == 'n' // null
+	u, ut, pv := d.indirect(v, wantptr)
+	if u != nil {
+		err := u.UnmarshalJSON(item)
+		if err != nil {
+			d.error(err)
+		}
+		return
+	}
+	if ut != nil {
+		if item[0] != '"' {
+			if fromQuoted {
+				d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+			} else {
+				d.saveError(&UnmarshalTypeError{"string", v.Type()})
+			}
+		}
+		s, ok := unquoteBytes(item)
+		if !ok {
+			if fromQuoted {
+				d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+			} else {
+				d.error(errPhase)
+			}
+		}
+		err := ut.UnmarshalText(s)
+		if err != nil {
+			d.error(err)
+		}
+		return
+	}
+
+	v = pv
+
+	switch c := item[0]; c {
+	case 'n': // null
+		switch v.Kind() {
+		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
+			v.Set(reflect.Zero(v.Type()))
+			// otherwise, ignore null for primitives/string
+		}
+	case 't', 'f': // true, false
+		value := c == 't'
+		switch v.Kind() {
+		default:
+			if fromQuoted {
+				d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+			} else {
+				d.saveError(&UnmarshalTypeError{"bool", v.Type()})
+			}
+		case reflect.Bool:
+			v.SetBool(value)
+		case reflect.Interface:
+			if v.NumMethod() == 0 {
+				v.Set(reflect.ValueOf(value))
+			} else {
+				d.saveError(&UnmarshalTypeError{"bool", v.Type()})
+			}
+		}
+
+	case '"': // string
+		s, ok := unquoteBytes(item)
+		if !ok {
+			if fromQuoted {
+				d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+			} else {
+				d.error(errPhase)
+			}
+		}
+		switch v.Kind() {
+		default:
+			d.saveError(&UnmarshalTypeError{"string", v.Type()})
+		case reflect.Slice:
+			if v.Type() != byteSliceType {
+				d.saveError(&UnmarshalTypeError{"string", v.Type()})
+				break
+			}
+			b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
+			n, err := base64.StdEncoding.Decode(b, s)
+			if err != nil {
+				d.saveError(err)
+				break
+			}
+			v.Set(reflect.ValueOf(b[0:n]))
+		case reflect.String:
+			v.SetString(string(s))
+		case reflect.Interface:
+			if v.NumMethod() == 0 {
+				v.Set(reflect.ValueOf(string(s)))
+			} else {
+				d.saveError(&UnmarshalTypeError{"string", v.Type()})
+			}
+		}
+
+	default: // number
+		if c != '-' && (c < '0' || c > '9') {
+			if fromQuoted {
+				d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+			} else {
+				d.error(errPhase)
+			}
+		}
+		s := string(item)
+		switch v.Kind() {
+		default:
+			if v.Kind() == reflect.String && v.Type() == numberType {
+				v.SetString(s)
+				break
+			}
+			if fromQuoted {
+				d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+			} else {
+				d.error(&UnmarshalTypeError{"number", v.Type()})
+			}
+		case reflect.Interface:
+			n, err := d.convertNumber(s)
+			if err != nil {
+				d.saveError(err)
+				break
+			}
+			if v.NumMethod() != 0 {
+				d.saveError(&UnmarshalTypeError{"number", v.Type()})
+				break
+			}
+			v.Set(reflect.ValueOf(n))
+
+		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+			n, err := strconv.ParseInt(s, 10, 64)
+			if err != nil || v.OverflowInt(n) {
+				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+				break
+			}
+			v.SetInt(n)
+
+		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+			n, err := strconv.ParseUint(s, 10, 64)
+			if err != nil || v.OverflowUint(n) {
+				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+				break
+			}
+			v.SetUint(n)
+
+		case reflect.Float32, reflect.Float64:
+			n, err := strconv.ParseFloat(s, v.Type().Bits())
+			if err != nil || v.OverflowFloat(n) {
+				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+				break
+			}
+			v.SetFloat(n)
+		}
+	}
+}
+
+// The xxxInterface routines build up a value to be stored
+// in an empty interface.  They are not strictly necessary,
+// but they avoid the weight of reflection in this common case.
+
+// valueInterface is like value but returns interface{}
+func (d *decodeState) valueInterface() interface{} {
+	switch d.scanWhile(scanSkipSpace) {
+	default:
+		d.error(errPhase)
+		panic("unreachable")
+	case scanBeginArray:
+		return d.arrayInterface()
+	case scanBeginObject:
+		return d.objectInterface()
+	case scanBeginLiteral:
+		return d.literalInterface()
+	}
+}
+
+// arrayInterface is like array but returns []interface{}.
+func (d *decodeState) arrayInterface() []interface{} {
+	var v = make([]interface{}, 0)
+	for {
+		// Look ahead for ] - can only happen on first iteration.
+		op := d.scanWhile(scanSkipSpace)
+		if op == scanEndArray {
+			break
+		}
+
+		// Back up so d.value can have the byte we just read.
+		d.off--
+		d.scan.undo(op)
+
+		v = append(v, d.valueInterface())
+
+		// Next token must be , or ].
+		op = d.scanWhile(scanSkipSpace)
+		if op == scanEndArray {
+			break
+		}
+		if op != scanArrayValue {
+			d.error(errPhase)
+		}
+	}
+	return v
+}
+
+// objectInterface is like object but returns map[string]interface{}.
+func (d *decodeState) objectInterface() map[string]interface{} {
+	m := make(map[string]interface{})
+	for {
+		// Read opening " of string key or closing }.
+		op := d.scanWhile(scanSkipSpace)
+		if op == scanEndObject {
+			// closing } - can only happen on first iteration.
+			break
+		}
+		if op != scanBeginLiteral {
+			d.error(errPhase)
+		}
+
+		// Read string key.
+		start := d.off - 1
+		op = d.scanWhile(scanContinue)
+		item := d.data[start : d.off-1]
+		key, ok := unquote(item)
+		if !ok {
+			d.error(errPhase)
+		}
+
+		// Read : before value.
+		if op == scanSkipSpace {
+			op = d.scanWhile(scanSkipSpace)
+		}
+		if op != scanObjectKey {
+			d.error(errPhase)
+		}
+
+		// Read value.
+		m[key] = d.valueInterface()
+
+		// Next token must be , or }.
+		op = d.scanWhile(scanSkipSpace)
+		if op == scanEndObject {
+			break
+		}
+		if op != scanObjectValue {
+			d.error(errPhase)
+		}
+	}
+	return m
+}
+
+// literalInterface is like literal but returns an interface value.
+func (d *decodeState) literalInterface() interface{} {
+	// All bytes inside literal return scanContinue op code.
+	start := d.off - 1
+	op := d.scanWhile(scanContinue)
+
+	// Scan read one byte too far; back up.
+	d.off--
+	d.scan.undo(op)
+	item := d.data[start:d.off]
+
+	switch c := item[0]; c {
+	case 'n': // null
+		return nil
+
+	case 't', 'f': // true, false
+		return c == 't'
+
+	case '"': // string
+		s, ok := unquote(item)
+		if !ok {
+			d.error(errPhase)
+		}
+		return s
+
+	default: // number
+		if c != '-' && (c < '0' || c > '9') {
+			d.error(errPhase)
+		}
+		n, err := d.convertNumber(string(item))
+		if err != nil {
+			d.saveError(err)
+		}
+		return n
+	}
+}
+
+// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
+// or it returns -1.
+func getu4(s []byte) rune {
+	if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
+		return -1
+	}
+	r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
+	if err != nil {
+		return -1
+	}
+	return rune(r)
+}
+
+// unquote converts a quoted JSON string literal s into an actual string t.
+// The rules are different than for Go, so cannot use strconv.Unquote.
+func unquote(s []byte) (t string, ok bool) {
+	s, ok = unquoteBytes(s)
+	t = string(s)
+	return
+}
+
+func unquoteBytes(s []byte) (t []byte, ok bool) {
+	if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
+		return
+	}
+	s = s[1 : len(s)-1]
+
+	// Check for unusual characters. If there are none,
+	// then no unquoting is needed, so return a slice of the
+	// original bytes.
+	r := 0
+	for r < len(s) {
+		c := s[r]
+		if c == '\\' || c == '"' || c < ' ' {
+			break
+		}
+		if c < utf8.RuneSelf {
+			r++
+			continue
+		}
+		rr, size := utf8.DecodeRune(s[r:])
+		if rr == utf8.RuneError && size == 1 {
+			break
+		}
+		r += size
+	}
+	if r == len(s) {
+		return s, true
+	}
+
+	b := make([]byte, len(s)+2*utf8.UTFMax)
+	w := copy(b, s[0:r])
+	for r < len(s) {
+		// Out of room?  Can only happen if s is full of
+		// malformed UTF-8 and we're replacing each
+		// byte with RuneError.
+		if w >= len(b)-2*utf8.UTFMax {
+			nb := make([]byte, (len(b)+utf8.UTFMax)*2)
+			copy(nb, b[0:w])
+			b = nb
+		}
+		switch c := s[r]; {
+		case c == '\\':
+			r++
+			if r >= len(s) {
+				return
+			}
+			switch s[r] {
+			default:
+				return
+			case '"', '\\', '/', '\'':
+				b[w] = s[r]
+				r++
+				w++
+			case 'b':
+				b[w] = '\b'
+				r++
+				w++
+			case 'f':
+				b[w] = '\f'
+				r++
+				w++
+			case 'n':
+				b[w] = '\n'
+				r++
+				w++
+			case 'r':
+				b[w] = '\r'
+				r++
+				w++
+			case 't':
+				b[w] = '\t'
+				r++
+				w++
+			case 'u':
+				r--
+				rr := getu4(s[r:])
+				if rr < 0 {
+					return
+				}
+				r += 6
+				if utf16.IsSurrogate(rr) {
+					rr1 := getu4(s[r:])
+					if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
+						// A valid pair; consume.
+						r += 6
+						w += utf8.EncodeRune(b[w:], dec)
+						break
+					}
+					// Invalid surrogate; fall back to replacement rune.
+					rr = unicode.ReplacementChar
+				}
+				w += utf8.EncodeRune(b[w:], rr)
+			}
+
+		// Quote, control characters are invalid.
+		case c == '"', c < ' ':
+			return
+
+		// ASCII
+		case c < utf8.RuneSelf:
+			b[w] = c
+			r++
+			w++
+
+		// Coerce to well-formed UTF-8.
+		default:
+			rr, size := utf8.DecodeRune(s[r:])
+			r += size
+			w += utf8.EncodeRune(b[w:], rr)
+		}
+	}
+	return b[0:w], true
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/decode_test.go b/third_party/gofrontend/libgo/go/encoding/json/decode_test.go
new file mode 100644
index 0000000..238a87f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/decode_test.go
@@ -0,0 +1,1356 @@
+// Copyright 2010 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 json
+
+import (
+	"bytes"
+	"encoding"
+	"fmt"
+	"image"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+)
+
+type T struct {
+	X string
+	Y int
+	Z int `json:"-"`
+}
+
+type U struct {
+	Alphabet string `json:"alpha"`
+}
+
+type V struct {
+	F1 interface{}
+	F2 int32
+	F3 Number
+}
+
+// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and
+// without UseNumber
+var ifaceNumAsFloat64 = map[string]interface{}{
+	"k1": float64(1),
+	"k2": "s",
+	"k3": []interface{}{float64(1), float64(2.0), float64(3e-3)},
+	"k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)},
+}
+
+var ifaceNumAsNumber = map[string]interface{}{
+	"k1": Number("1"),
+	"k2": "s",
+	"k3": []interface{}{Number("1"), Number("2.0"), Number("3e-3")},
+	"k4": map[string]interface{}{"kk1": "s", "kk2": Number("2")},
+}
+
+type tx struct {
+	x int
+}
+
+// A type that can unmarshal itself.
+
+type unmarshaler struct {
+	T bool
+}
+
+func (u *unmarshaler) UnmarshalJSON(b []byte) error {
+	*u = unmarshaler{true} // All we need to see that UnmarshalJSON is called.
+	return nil
+}
+
+type ustruct struct {
+	M unmarshaler
+}
+
+type unmarshalerText struct {
+	T bool
+}
+
+// needed for re-marshaling tests
+func (u *unmarshalerText) MarshalText() ([]byte, error) {
+	return []byte(""), nil
+}
+
+func (u *unmarshalerText) UnmarshalText(b []byte) error {
+	*u = unmarshalerText{true} // All we need to see that UnmarshalText is called.
+	return nil
+}
+
+var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil)
+
+type ustructText struct {
+	M unmarshalerText
+}
+
+var (
+	um0, um1 unmarshaler // target2 of unmarshaling
+	ump      = &um1
+	umtrue   = unmarshaler{true}
+	umslice  = []unmarshaler{{true}}
+	umslicep = new([]unmarshaler)
+	umstruct = ustruct{unmarshaler{true}}
+
+	um0T, um1T unmarshalerText // target2 of unmarshaling
+	umpT       = &um1T
+	umtrueT    = unmarshalerText{true}
+	umsliceT   = []unmarshalerText{{true}}
+	umslicepT  = new([]unmarshalerText)
+	umstructT  = ustructText{unmarshalerText{true}}
+)
+
+// Test data structures for anonymous fields.
+
+type Point struct {
+	Z int
+}
+
+type Top struct {
+	Level0 int
+	Embed0
+	*Embed0a
+	*Embed0b `json:"e,omitempty"` // treated as named
+	Embed0c  `json:"-"`           // ignored
+	Loop
+	Embed0p // has Point with X, Y, used
+	Embed0q // has Point with Z, used
+}
+
+type Embed0 struct {
+	Level1a int // overridden by Embed0a's Level1a with json tag
+	Level1b int // used because Embed0a's Level1b is renamed
+	Level1c int // used because Embed0a's Level1c is ignored
+	Level1d int // annihilated by Embed0a's Level1d
+	Level1e int `json:"x"` // annihilated by Embed0a.Level1e
+}
+
+type Embed0a struct {
+	Level1a int `json:"Level1a,omitempty"`
+	Level1b int `json:"LEVEL1B,omitempty"`
+	Level1c int `json:"-"`
+	Level1d int // annihilated by Embed0's Level1d
+	Level1f int `json:"x"` // annihilated by Embed0's Level1e
+}
+
+type Embed0b Embed0
+
+type Embed0c Embed0
+
+type Embed0p struct {
+	image.Point
+}
+
+type Embed0q struct {
+	Point
+}
+
+type Loop struct {
+	Loop1 int `json:",omitempty"`
+	Loop2 int `json:",omitempty"`
+	*Loop
+}
+
+// From reflect test:
+// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
+type S5 struct {
+	S6
+	S7
+	S8
+}
+
+type S6 struct {
+	X int
+}
+
+type S7 S6
+
+type S8 struct {
+	S9
+}
+
+type S9 struct {
+	X int
+	Y int
+}
+
+// From reflect test:
+// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
+type S10 struct {
+	S11
+	S12
+	S13
+}
+
+type S11 struct {
+	S6
+}
+
+type S12 struct {
+	S6
+}
+
+type S13 struct {
+	S8
+}
+
+type unmarshalTest struct {
+	in        string
+	ptr       interface{}
+	out       interface{}
+	err       error
+	useNumber bool
+}
+
+type Ambig struct {
+	// Given "hello", the first match should win.
+	First  int `json:"HELLO"`
+	Second int `json:"Hello"`
+}
+
+type XYZ struct {
+	X interface{}
+	Y interface{}
+	Z interface{}
+}
+
+var unmarshalTests = []unmarshalTest{
+	// basic types
+	{in: `true`, ptr: new(bool), out: true},
+	{in: `1`, ptr: new(int), out: 1},
+	{in: `1.2`, ptr: new(float64), out: 1.2},
+	{in: `-5`, ptr: new(int16), out: int16(-5)},
+	{in: `2`, ptr: new(Number), out: Number("2"), useNumber: true},
+	{in: `2`, ptr: new(Number), out: Number("2")},
+	{in: `2`, ptr: new(interface{}), out: float64(2.0)},
+	{in: `2`, ptr: new(interface{}), out: Number("2"), useNumber: true},
+	{in: `"a\u1234"`, ptr: new(string), out: "a\u1234"},
+	{in: `"http:\/\/"`, ptr: new(string), out: "http://"},
+	{in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
+	{in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
+	{in: "null", ptr: new(interface{}), out: nil},
+	{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf("")}},
+	{in: `{"x": 1}`, ptr: new(tx), out: tx{}},
+	{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
+	{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
+	{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64},
+	{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true},
+
+	// raw values with whitespace
+	{in: "\n true ", ptr: new(bool), out: true},
+	{in: "\t 1 ", ptr: new(int), out: 1},
+	{in: "\r 1.2 ", ptr: new(float64), out: 1.2},
+	{in: "\t -5 \n", ptr: new(int16), out: int16(-5)},
+	{in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"},
+
+	// Z has a "-" tag.
+	{in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}},
+
+	{in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}},
+	{in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}},
+	{in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}},
+
+	// syntax errors
+	{in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}},
+	{in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
+	{in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true},
+
+	// raw value errors
+	{in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
+	{in: " 42 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 5}},
+	{in: "\x01 true", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
+	{in: " false \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 8}},
+	{in: "\x01 1.2", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
+	{in: " 3.4 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 6}},
+	{in: "\x01 \"string\"", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
+	{in: " \"string\" \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 11}},
+
+	// array tests
+	{in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
+	{in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
+	{in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
+
+	// empty array to interface test
+	{in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
+	{in: `null`, ptr: new([]interface{}), out: []interface{}(nil)},
+	{in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}},
+	{in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}},
+
+	// composite tests
+	{in: allValueIndent, ptr: new(All), out: allValue},
+	{in: allValueCompact, ptr: new(All), out: allValue},
+	{in: allValueIndent, ptr: new(*All), out: &allValue},
+	{in: allValueCompact, ptr: new(*All), out: &allValue},
+	{in: pallValueIndent, ptr: new(All), out: pallValue},
+	{in: pallValueCompact, ptr: new(All), out: pallValue},
+	{in: pallValueIndent, ptr: new(*All), out: &pallValue},
+	{in: pallValueCompact, ptr: new(*All), out: &pallValue},
+
+	// unmarshal interface test
+	{in: `{"T":false}`, ptr: &um0, out: umtrue}, // use "false" so test will fail if custom unmarshaler is not called
+	{in: `{"T":false}`, ptr: &ump, out: &umtrue},
+	{in: `[{"T":false}]`, ptr: &umslice, out: umslice},
+	{in: `[{"T":false}]`, ptr: &umslicep, out: &umslice},
+	{in: `{"M":{"T":false}}`, ptr: &umstruct, out: umstruct},
+
+	// UnmarshalText interface test
+	{in: `"X"`, ptr: &um0T, out: umtrueT}, // use "false" so test will fail if custom unmarshaler is not called
+	{in: `"X"`, ptr: &umpT, out: &umtrueT},
+	{in: `["X"]`, ptr: &umsliceT, out: umsliceT},
+	{in: `["X"]`, ptr: &umslicepT, out: &umsliceT},
+	{in: `{"M":"X"}`, ptr: &umstructT, out: umstructT},
+
+	{
+		in: `{
+			"Level0": 1,
+			"Level1b": 2,
+			"Level1c": 3,
+			"x": 4,
+			"Level1a": 5,
+			"LEVEL1B": 6,
+			"e": {
+				"Level1a": 8,
+				"Level1b": 9,
+				"Level1c": 10,
+				"Level1d": 11,
+				"x": 12
+			},
+			"Loop1": 13,
+			"Loop2": 14,
+			"X": 15,
+			"Y": 16,
+			"Z": 17
+		}`,
+		ptr: new(Top),
+		out: Top{
+			Level0: 1,
+			Embed0: Embed0{
+				Level1b: 2,
+				Level1c: 3,
+			},
+			Embed0a: &Embed0a{
+				Level1a: 5,
+				Level1b: 6,
+			},
+			Embed0b: &Embed0b{
+				Level1a: 8,
+				Level1b: 9,
+				Level1c: 10,
+				Level1d: 11,
+				Level1e: 12,
+			},
+			Loop: Loop{
+				Loop1: 13,
+				Loop2: 14,
+			},
+			Embed0p: Embed0p{
+				Point: image.Point{X: 15, Y: 16},
+			},
+			Embed0q: Embed0q{
+				Point: Point{Z: 17},
+			},
+		},
+	},
+	{
+		in:  `{"hello": 1}`,
+		ptr: new(Ambig),
+		out: Ambig{First: 1},
+	},
+
+	{
+		in:  `{"X": 1,"Y":2}`,
+		ptr: new(S5),
+		out: S5{S8: S8{S9: S9{Y: 2}}},
+	},
+	{
+		in:  `{"X": 1,"Y":2}`,
+		ptr: new(S10),
+		out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}},
+	},
+
+	// invalid UTF-8 is coerced to valid UTF-8.
+	{
+		in:  "\"hello\xffworld\"",
+		ptr: new(string),
+		out: "hello\ufffdworld",
+	},
+	{
+		in:  "\"hello\xc2\xc2world\"",
+		ptr: new(string),
+		out: "hello\ufffd\ufffdworld",
+	},
+	{
+		in:  "\"hello\xc2\xffworld\"",
+		ptr: new(string),
+		out: "hello\ufffd\ufffdworld",
+	},
+	{
+		in:  "\"hello\\ud800world\"",
+		ptr: new(string),
+		out: "hello\ufffdworld",
+	},
+	{
+		in:  "\"hello\\ud800\\ud800world\"",
+		ptr: new(string),
+		out: "hello\ufffd\ufffdworld",
+	},
+	{
+		in:  "\"hello\\ud800\\ud800world\"",
+		ptr: new(string),
+		out: "hello\ufffd\ufffdworld",
+	},
+	{
+		in:  "\"hello\xed\xa0\x80\xed\xb0\x80world\"",
+		ptr: new(string),
+		out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld",
+	},
+}
+
+func TestMarshal(t *testing.T) {
+	b, err := Marshal(allValue)
+	if err != nil {
+		t.Fatalf("Marshal allValue: %v", err)
+	}
+	if string(b) != allValueCompact {
+		t.Errorf("Marshal allValueCompact")
+		diff(t, b, []byte(allValueCompact))
+		return
+	}
+
+	b, err = Marshal(pallValue)
+	if err != nil {
+		t.Fatalf("Marshal pallValue: %v", err)
+	}
+	if string(b) != pallValueCompact {
+		t.Errorf("Marshal pallValueCompact")
+		diff(t, b, []byte(pallValueCompact))
+		return
+	}
+}
+
+var badUTF8 = []struct {
+	in, out string
+}{
+	{"hello\xffworld", `"hello\ufffdworld"`},
+	{"", `""`},
+	{"\xff", `"\ufffd"`},
+	{"\xff\xff", `"\ufffd\ufffd"`},
+	{"a\xffb", `"a\ufffdb"`},
+	{"\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`},
+}
+
+func TestMarshalBadUTF8(t *testing.T) {
+	for _, tt := range badUTF8 {
+		b, err := Marshal(tt.in)
+		if string(b) != tt.out || err != nil {
+			t.Errorf("Marshal(%q) = %#q, %v, want %#q, nil", tt.in, b, err, tt.out)
+		}
+	}
+}
+
+func TestMarshalNumberZeroVal(t *testing.T) {
+	var n Number
+	out, err := Marshal(n)
+	if err != nil {
+		t.Fatal(err)
+	}
+	outStr := string(out)
+	if outStr != "0" {
+		t.Fatalf("Invalid zero val for Number: %q", outStr)
+	}
+}
+
+func TestMarshalEmbeds(t *testing.T) {
+	top := &Top{
+		Level0: 1,
+		Embed0: Embed0{
+			Level1b: 2,
+			Level1c: 3,
+		},
+		Embed0a: &Embed0a{
+			Level1a: 5,
+			Level1b: 6,
+		},
+		Embed0b: &Embed0b{
+			Level1a: 8,
+			Level1b: 9,
+			Level1c: 10,
+			Level1d: 11,
+			Level1e: 12,
+		},
+		Loop: Loop{
+			Loop1: 13,
+			Loop2: 14,
+		},
+		Embed0p: Embed0p{
+			Point: image.Point{X: 15, Y: 16},
+		},
+		Embed0q: Embed0q{
+			Point: Point{Z: 17},
+		},
+	}
+	b, err := Marshal(top)
+	if err != nil {
+		t.Fatal(err)
+	}
+	want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17}"
+	if string(b) != want {
+		t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want)
+	}
+}
+
+func TestUnmarshal(t *testing.T) {
+	for i, tt := range unmarshalTests {
+		var scan scanner
+		in := []byte(tt.in)
+		if err := checkValid(in, &scan); err != nil {
+			if !reflect.DeepEqual(err, tt.err) {
+				t.Errorf("#%d: checkValid: %#v", i, err)
+				continue
+			}
+		}
+		if tt.ptr == nil {
+			continue
+		}
+		// v = new(right-type)
+		v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
+		dec := NewDecoder(bytes.NewReader(in))
+		if tt.useNumber {
+			dec.UseNumber()
+		}
+		if err := dec.Decode(v.Interface()); !reflect.DeepEqual(err, tt.err) {
+			t.Errorf("#%d: %v want %v", i, err, tt.err)
+			continue
+		}
+		if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
+			t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
+			data, _ := Marshal(v.Elem().Interface())
+			println(string(data))
+			data, _ = Marshal(tt.out)
+			println(string(data))
+			continue
+		}
+
+		// Check round trip.
+		if tt.err == nil {
+			enc, err := Marshal(v.Interface())
+			if err != nil {
+				t.Errorf("#%d: error re-marshaling: %v", i, err)
+				continue
+			}
+			vv := reflect.New(reflect.TypeOf(tt.ptr).Elem())
+			dec = NewDecoder(bytes.NewReader(enc))
+			if tt.useNumber {
+				dec.UseNumber()
+			}
+			if err := dec.Decode(vv.Interface()); err != nil {
+				t.Errorf("#%d: error re-unmarshaling %#q: %v", i, enc, err)
+				continue
+			}
+			if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) {
+				t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface())
+				t.Errorf("     In: %q", strings.Map(noSpace, string(in)))
+				t.Errorf("Marshal: %q", strings.Map(noSpace, string(enc)))
+				continue
+			}
+		}
+	}
+}
+
+func TestUnmarshalMarshal(t *testing.T) {
+	initBig()
+	var v interface{}
+	if err := Unmarshal(jsonBig, &v); err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	b, err := Marshal(v)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	if !bytes.Equal(jsonBig, b) {
+		t.Errorf("Marshal jsonBig")
+		diff(t, b, jsonBig)
+		return
+	}
+}
+
+var numberTests = []struct {
+	in       string
+	i        int64
+	intErr   string
+	f        float64
+	floatErr string
+}{
+	{in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1},
+	{in: "-12", i: -12, f: -12.0},
+	{in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"},
+}
+
+// Independent of Decode, basic coverage of the accessors in Number
+func TestNumberAccessors(t *testing.T) {
+	for _, tt := range numberTests {
+		n := Number(tt.in)
+		if s := n.String(); s != tt.in {
+			t.Errorf("Number(%q).String() is %q", tt.in, s)
+		}
+		if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i {
+			t.Errorf("Number(%q).Int64() is %d", tt.in, i)
+		} else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) {
+			t.Errorf("Number(%q).Int64() wanted error %q but got: %v", tt.in, tt.intErr, err)
+		}
+		if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f {
+			t.Errorf("Number(%q).Float64() is %g", tt.in, f)
+		} else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) {
+			t.Errorf("Number(%q).Float64() wanted error %q but got: %v", tt.in, tt.floatErr, err)
+		}
+	}
+}
+
+func TestLargeByteSlice(t *testing.T) {
+	s0 := make([]byte, 2000)
+	for i := range s0 {
+		s0[i] = byte(i)
+	}
+	b, err := Marshal(s0)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	var s1 []byte
+	if err := Unmarshal(b, &s1); err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	if !bytes.Equal(s0, s1) {
+		t.Errorf("Marshal large byte slice")
+		diff(t, s0, s1)
+	}
+}
+
+type Xint struct {
+	X int
+}
+
+func TestUnmarshalInterface(t *testing.T) {
+	var xint Xint
+	var i interface{} = &xint
+	if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	if xint.X != 1 {
+		t.Fatalf("Did not write to xint")
+	}
+}
+
+func TestUnmarshalPtrPtr(t *testing.T) {
+	var xint Xint
+	pxint := &xint
+	if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	if xint.X != 1 {
+		t.Fatalf("Did not write to xint")
+	}
+}
+
+func TestEscape(t *testing.T) {
+	const input = `"foobar"<html>` + " [\u2028 \u2029]"
+	const expected = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"`
+	b, err := Marshal(input)
+	if err != nil {
+		t.Fatalf("Marshal error: %v", err)
+	}
+	if s := string(b); s != expected {
+		t.Errorf("Encoding of [%s]:\n got [%s]\nwant [%s]", input, s, expected)
+	}
+}
+
+// WrongString is a struct that's misusing the ,string modifier.
+type WrongString struct {
+	Message string `json:"result,string"`
+}
+
+type wrongStringTest struct {
+	in, err string
+}
+
+var wrongStringTests = []wrongStringTest{
+	{`{"result":"x"}`, `json: invalid use of ,string struct tag, trying to unmarshal "x" into string`},
+	{`{"result":"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "foo" into string`},
+	{`{"result":"123"}`, `json: invalid use of ,string struct tag, trying to unmarshal "123" into string`},
+}
+
+// If people misuse the ,string modifier, the error message should be
+// helpful, telling the user that they're doing it wrong.
+func TestErrorMessageFromMisusedString(t *testing.T) {
+	for n, tt := range wrongStringTests {
+		r := strings.NewReader(tt.in)
+		var s WrongString
+		err := NewDecoder(r).Decode(&s)
+		got := fmt.Sprintf("%v", err)
+		if got != tt.err {
+			t.Errorf("%d. got err = %q, want %q", n, got, tt.err)
+		}
+	}
+}
+
+func noSpace(c rune) rune {
+	if isSpace(c) {
+		return -1
+	}
+	return c
+}
+
+type All struct {
+	Bool    bool
+	Int     int
+	Int8    int8
+	Int16   int16
+	Int32   int32
+	Int64   int64
+	Uint    uint
+	Uint8   uint8
+	Uint16  uint16
+	Uint32  uint32
+	Uint64  uint64
+	Uintptr uintptr
+	Float32 float32
+	Float64 float64
+
+	Foo  string `json:"bar"`
+	Foo2 string `json:"bar2,dummyopt"`
+
+	IntStr int64 `json:",string"`
+
+	PBool    *bool
+	PInt     *int
+	PInt8    *int8
+	PInt16   *int16
+	PInt32   *int32
+	PInt64   *int64
+	PUint    *uint
+	PUint8   *uint8
+	PUint16  *uint16
+	PUint32  *uint32
+	PUint64  *uint64
+	PUintptr *uintptr
+	PFloat32 *float32
+	PFloat64 *float64
+
+	String  string
+	PString *string
+
+	Map   map[string]Small
+	MapP  map[string]*Small
+	PMap  *map[string]Small
+	PMapP *map[string]*Small
+
+	EmptyMap map[string]Small
+	NilMap   map[string]Small
+
+	Slice   []Small
+	SliceP  []*Small
+	PSlice  *[]Small
+	PSliceP *[]*Small
+
+	EmptySlice []Small
+	NilSlice   []Small
+
+	StringSlice []string
+	ByteSlice   []byte
+
+	Small   Small
+	PSmall  *Small
+	PPSmall **Small
+
+	Interface  interface{}
+	PInterface *interface{}
+
+	unexported int
+}
+
+type Small struct {
+	Tag string
+}
+
+var allValue = All{
+	Bool:    true,
+	Int:     2,
+	Int8:    3,
+	Int16:   4,
+	Int32:   5,
+	Int64:   6,
+	Uint:    7,
+	Uint8:   8,
+	Uint16:  9,
+	Uint32:  10,
+	Uint64:  11,
+	Uintptr: 12,
+	Float32: 14.1,
+	Float64: 15.1,
+	Foo:     "foo",
+	Foo2:    "foo2",
+	IntStr:  42,
+	String:  "16",
+	Map: map[string]Small{
+		"17": {Tag: "tag17"},
+		"18": {Tag: "tag18"},
+	},
+	MapP: map[string]*Small{
+		"19": {Tag: "tag19"},
+		"20": nil,
+	},
+	EmptyMap:    map[string]Small{},
+	Slice:       []Small{{Tag: "tag20"}, {Tag: "tag21"}},
+	SliceP:      []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}},
+	EmptySlice:  []Small{},
+	StringSlice: []string{"str24", "str25", "str26"},
+	ByteSlice:   []byte{27, 28, 29},
+	Small:       Small{Tag: "tag30"},
+	PSmall:      &Small{Tag: "tag31"},
+	Interface:   5.2,
+}
+
+var pallValue = All{
+	PBool:      &allValue.Bool,
+	PInt:       &allValue.Int,
+	PInt8:      &allValue.Int8,
+	PInt16:     &allValue.Int16,
+	PInt32:     &allValue.Int32,
+	PInt64:     &allValue.Int64,
+	PUint:      &allValue.Uint,
+	PUint8:     &allValue.Uint8,
+	PUint16:    &allValue.Uint16,
+	PUint32:    &allValue.Uint32,
+	PUint64:    &allValue.Uint64,
+	PUintptr:   &allValue.Uintptr,
+	PFloat32:   &allValue.Float32,
+	PFloat64:   &allValue.Float64,
+	PString:    &allValue.String,
+	PMap:       &allValue.Map,
+	PMapP:      &allValue.MapP,
+	PSlice:     &allValue.Slice,
+	PSliceP:    &allValue.SliceP,
+	PPSmall:    &allValue.PSmall,
+	PInterface: &allValue.Interface,
+}
+
+var allValueIndent = `{
+	"Bool": true,
+	"Int": 2,
+	"Int8": 3,
+	"Int16": 4,
+	"Int32": 5,
+	"Int64": 6,
+	"Uint": 7,
+	"Uint8": 8,
+	"Uint16": 9,
+	"Uint32": 10,
+	"Uint64": 11,
+	"Uintptr": 12,
+	"Float32": 14.1,
+	"Float64": 15.1,
+	"bar": "foo",
+	"bar2": "foo2",
+	"IntStr": "42",
+	"PBool": null,
+	"PInt": null,
+	"PInt8": null,
+	"PInt16": null,
+	"PInt32": null,
+	"PInt64": null,
+	"PUint": null,
+	"PUint8": null,
+	"PUint16": null,
+	"PUint32": null,
+	"PUint64": null,
+	"PUintptr": null,
+	"PFloat32": null,
+	"PFloat64": null,
+	"String": "16",
+	"PString": null,
+	"Map": {
+		"17": {
+			"Tag": "tag17"
+		},
+		"18": {
+			"Tag": "tag18"
+		}
+	},
+	"MapP": {
+		"19": {
+			"Tag": "tag19"
+		},
+		"20": null
+	},
+	"PMap": null,
+	"PMapP": null,
+	"EmptyMap": {},
+	"NilMap": null,
+	"Slice": [
+		{
+			"Tag": "tag20"
+		},
+		{
+			"Tag": "tag21"
+		}
+	],
+	"SliceP": [
+		{
+			"Tag": "tag22"
+		},
+		null,
+		{
+			"Tag": "tag23"
+		}
+	],
+	"PSlice": null,
+	"PSliceP": null,
+	"EmptySlice": [],
+	"NilSlice": null,
+	"StringSlice": [
+		"str24",
+		"str25",
+		"str26"
+	],
+	"ByteSlice": "Gxwd",
+	"Small": {
+		"Tag": "tag30"
+	},
+	"PSmall": {
+		"Tag": "tag31"
+	},
+	"PPSmall": null,
+	"Interface": 5.2,
+	"PInterface": null
+}`
+
+var allValueCompact = strings.Map(noSpace, allValueIndent)
+
+var pallValueIndent = `{
+	"Bool": false,
+	"Int": 0,
+	"Int8": 0,
+	"Int16": 0,
+	"Int32": 0,
+	"Int64": 0,
+	"Uint": 0,
+	"Uint8": 0,
+	"Uint16": 0,
+	"Uint32": 0,
+	"Uint64": 0,
+	"Uintptr": 0,
+	"Float32": 0,
+	"Float64": 0,
+	"bar": "",
+	"bar2": "",
+        "IntStr": "0",
+	"PBool": true,
+	"PInt": 2,
+	"PInt8": 3,
+	"PInt16": 4,
+	"PInt32": 5,
+	"PInt64": 6,
+	"PUint": 7,
+	"PUint8": 8,
+	"PUint16": 9,
+	"PUint32": 10,
+	"PUint64": 11,
+	"PUintptr": 12,
+	"PFloat32": 14.1,
+	"PFloat64": 15.1,
+	"String": "",
+	"PString": "16",
+	"Map": null,
+	"MapP": null,
+	"PMap": {
+		"17": {
+			"Tag": "tag17"
+		},
+		"18": {
+			"Tag": "tag18"
+		}
+	},
+	"PMapP": {
+		"19": {
+			"Tag": "tag19"
+		},
+		"20": null
+	},
+	"EmptyMap": null,
+	"NilMap": null,
+	"Slice": null,
+	"SliceP": null,
+	"PSlice": [
+		{
+			"Tag": "tag20"
+		},
+		{
+			"Tag": "tag21"
+		}
+	],
+	"PSliceP": [
+		{
+			"Tag": "tag22"
+		},
+		null,
+		{
+			"Tag": "tag23"
+		}
+	],
+	"EmptySlice": null,
+	"NilSlice": null,
+	"StringSlice": null,
+	"ByteSlice": null,
+	"Small": {
+		"Tag": ""
+	},
+	"PSmall": null,
+	"PPSmall": {
+		"Tag": "tag31"
+	},
+	"Interface": null,
+	"PInterface": 5.2
+}`
+
+var pallValueCompact = strings.Map(noSpace, pallValueIndent)
+
+func TestRefUnmarshal(t *testing.T) {
+	type S struct {
+		// Ref is defined in encode_test.go.
+		R0 Ref
+		R1 *Ref
+		R2 RefText
+		R3 *RefText
+	}
+	want := S{
+		R0: 12,
+		R1: new(Ref),
+		R2: 13,
+		R3: new(RefText),
+	}
+	*want.R1 = 12
+	*want.R3 = 13
+
+	var got S
+	if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("got %+v, want %+v", got, want)
+	}
+}
+
+// Test that the empty string doesn't panic decoding when ,string is specified
+// Issue 3450
+func TestEmptyString(t *testing.T) {
+	type T2 struct {
+		Number1 int `json:",string"`
+		Number2 int `json:",string"`
+	}
+	data := `{"Number1":"1", "Number2":""}`
+	dec := NewDecoder(strings.NewReader(data))
+	var t2 T2
+	err := dec.Decode(&t2)
+	if err == nil {
+		t.Fatal("Decode: did not return error")
+	}
+	if t2.Number1 != 1 {
+		t.Fatal("Decode: did not set Number1")
+	}
+}
+
+// Test that the returned error is non-nil when trying to unmarshal null string into int, for successive ,string option
+// Issue 7046
+func TestNullString(t *testing.T) {
+	type T struct {
+		A int `json:",string"`
+		B int `json:",string"`
+	}
+	data := []byte(`{"A": "1", "B": null}`)
+	var s T
+	err := Unmarshal(data, &s)
+	if err == nil {
+		t.Fatalf("expected error; got %v", s)
+	}
+}
+
+func intp(x int) *int {
+	p := new(int)
+	*p = x
+	return p
+}
+
+func intpp(x *int) **int {
+	pp := new(*int)
+	*pp = x
+	return pp
+}
+
+var interfaceSetTests = []struct {
+	pre  interface{}
+	json string
+	post interface{}
+}{
+	{"foo", `"bar"`, "bar"},
+	{"foo", `2`, 2.0},
+	{"foo", `true`, true},
+	{"foo", `null`, nil},
+
+	{nil, `null`, nil},
+	{new(int), `null`, nil},
+	{(*int)(nil), `null`, nil},
+	{new(*int), `null`, new(*int)},
+	{(**int)(nil), `null`, nil},
+	{intp(1), `null`, nil},
+	{intpp(nil), `null`, intpp(nil)},
+	{intpp(intp(1)), `null`, intpp(nil)},
+}
+
+func TestInterfaceSet(t *testing.T) {
+	for _, tt := range interfaceSetTests {
+		b := struct{ X interface{} }{tt.pre}
+		blob := `{"X":` + tt.json + `}`
+		if err := Unmarshal([]byte(blob), &b); err != nil {
+			t.Errorf("Unmarshal %#q: %v", blob, err)
+			continue
+		}
+		if !reflect.DeepEqual(b.X, tt.post) {
+			t.Errorf("Unmarshal %#q into %#v: X=%#v, want %#v", blob, tt.pre, b.X, tt.post)
+		}
+	}
+}
+
+// JSON null values should be ignored for primitives and string values instead of resulting in an error.
+// Issue 2540
+func TestUnmarshalNulls(t *testing.T) {
+	jsonData := []byte(`{
+		"Bool"    : null,
+		"Int"     : null,
+		"Int8"    : null,
+		"Int16"   : null,
+		"Int32"   : null,
+		"Int64"   : null,
+		"Uint"    : null,
+		"Uint8"   : null,
+		"Uint16"  : null,
+		"Uint32"  : null,
+		"Uint64"  : null,
+		"Float32" : null,
+		"Float64" : null,
+		"String"  : null}`)
+
+	nulls := All{
+		Bool:    true,
+		Int:     2,
+		Int8:    3,
+		Int16:   4,
+		Int32:   5,
+		Int64:   6,
+		Uint:    7,
+		Uint8:   8,
+		Uint16:  9,
+		Uint32:  10,
+		Uint64:  11,
+		Float32: 12.1,
+		Float64: 13.1,
+		String:  "14"}
+
+	err := Unmarshal(jsonData, &nulls)
+	if err != nil {
+		t.Errorf("Unmarshal of null values failed: %v", err)
+	}
+	if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 ||
+		nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 ||
+		nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" {
+
+		t.Errorf("Unmarshal of null values affected primitives")
+	}
+}
+
+func TestStringKind(t *testing.T) {
+	type stringKind string
+
+	var m1, m2 map[stringKind]int
+	m1 = map[stringKind]int{
+		"foo": 42,
+	}
+
+	data, err := Marshal(m1)
+	if err != nil {
+		t.Errorf("Unexpected error marshalling: %v", err)
+	}
+
+	err = Unmarshal(data, &m2)
+	if err != nil {
+		t.Errorf("Unexpected error unmarshalling: %v", err)
+	}
+
+	if !reflect.DeepEqual(m1, m2) {
+		t.Error("Items should be equal after encoding and then decoding")
+	}
+
+}
+
+var decodeTypeErrorTests = []struct {
+	dest interface{}
+	src  string
+}{
+	{new(string), `{"user": "name"}`}, // issue 4628.
+	{new(error), `{}`},                // issue 4222
+	{new(error), `[]`},
+	{new(error), `""`},
+	{new(error), `123`},
+	{new(error), `true`},
+}
+
+func TestUnmarshalTypeError(t *testing.T) {
+	for _, item := range decodeTypeErrorTests {
+		err := Unmarshal([]byte(item.src), item.dest)
+		if _, ok := err.(*UnmarshalTypeError); !ok {
+			t.Errorf("expected type error for Unmarshal(%q, type %T): got %T",
+				item.src, item.dest, err)
+		}
+	}
+}
+
+var unmarshalSyntaxTests = []string{
+	"tru",
+	"fals",
+	"nul",
+	"123e",
+	`"hello`,
+	`[1,2,3`,
+	`{"key":1`,
+	`{"key":1,`,
+}
+
+func TestUnmarshalSyntax(t *testing.T) {
+	var x interface{}
+	for _, src := range unmarshalSyntaxTests {
+		err := Unmarshal([]byte(src), &x)
+		if _, ok := err.(*SyntaxError); !ok {
+			t.Errorf("expected syntax error for Unmarshal(%q): got %T", src, err)
+		}
+	}
+}
+
+// Test handling of unexported fields that should be ignored.
+// Issue 4660
+type unexportedFields struct {
+	Name string
+	m    map[string]interface{} `json:"-"`
+	m2   map[string]interface{} `json:"abcd"`
+}
+
+func TestUnmarshalUnexported(t *testing.T) {
+	input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}}`
+	want := &unexportedFields{Name: "Bob"}
+
+	out := &unexportedFields{}
+	err := Unmarshal([]byte(input), out)
+	if err != nil {
+		t.Errorf("got error %v, expected nil", err)
+	}
+	if !reflect.DeepEqual(out, want) {
+		t.Errorf("got %q, want %q", out, want)
+	}
+}
+
+// Time3339 is a time.Time which encodes to and from JSON
+// as an RFC 3339 time in UTC.
+type Time3339 time.Time
+
+func (t *Time3339) UnmarshalJSON(b []byte) error {
+	if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
+		return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b)
+	}
+	tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1]))
+	if err != nil {
+		return err
+	}
+	*t = Time3339(tm)
+	return nil
+}
+
+func TestUnmarshalJSONLiteralError(t *testing.T) {
+	var t3 Time3339
+	err := Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3)
+	if err == nil {
+		t.Fatalf("expected error; got time %v", time.Time(t3))
+	}
+	if !strings.Contains(err.Error(), "range") {
+		t.Errorf("got err = %v; want out of range error", err)
+	}
+}
+
+// Test that extra object elements in an array do not result in a
+// "data changing underfoot" error.
+// Issue 3717
+func TestSkipArrayObjects(t *testing.T) {
+	json := `[{}]`
+	var dest [0]interface{}
+
+	err := Unmarshal([]byte(json), &dest)
+	if err != nil {
+		t.Errorf("got error %q, want nil", err)
+	}
+}
+
+// Test semantics of pre-filled struct fields and pre-filled map fields.
+// Issue 4900.
+func TestPrefilled(t *testing.T) {
+	ptrToMap := func(m map[string]interface{}) *map[string]interface{} { return &m }
+
+	// Values here change, cannot reuse table across runs.
+	var prefillTests = []struct {
+		in  string
+		ptr interface{}
+		out interface{}
+	}{
+		{
+			in:  `{"X": 1, "Y": 2}`,
+			ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5},
+			out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5},
+		},
+		{
+			in:  `{"X": 1, "Y": 2}`,
+			ptr: ptrToMap(map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}),
+			out: ptrToMap(map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}),
+		},
+	}
+
+	for _, tt := range prefillTests {
+		ptrstr := fmt.Sprintf("%v", tt.ptr)
+		err := Unmarshal([]byte(tt.in), tt.ptr) // tt.ptr edited here
+		if err != nil {
+			t.Errorf("Unmarshal: %v", err)
+		}
+		if !reflect.DeepEqual(tt.ptr, tt.out) {
+			t.Errorf("Unmarshal(%#q, %s): have %v, want %v", tt.in, ptrstr, tt.ptr, tt.out)
+		}
+	}
+}
+
+var invalidUnmarshalTests = []struct {
+	v    interface{}
+	want string
+}{
+	{nil, "json: Unmarshal(nil)"},
+	{struct{}{}, "json: Unmarshal(non-pointer struct {})"},
+	{(*int)(nil), "json: Unmarshal(nil *int)"},
+}
+
+func TestInvalidUnmarshal(t *testing.T) {
+	buf := []byte(`{"a":"1"}`)
+	for _, tt := range invalidUnmarshalTests {
+		err := Unmarshal(buf, tt.v)
+		if err == nil {
+			t.Errorf("Unmarshal expecting error, got nil")
+			continue
+		}
+		if got := err.Error(); got != tt.want {
+			t.Errorf("Unmarshal = %q; want %q", got, tt.want)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/encode.go b/third_party/gofrontend/libgo/go/encoding/json/encode.go
new file mode 100644
index 0000000..741ddd8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/encode.go
@@ -0,0 +1,1175 @@
+// Copyright 2010 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 json implements encoding and decoding of JSON objects as defined in
+// RFC 4627. The mapping between JSON objects and Go values is described
+// in the documentation for the Marshal and Unmarshal functions.
+//
+// See "JSON and Go" for an introduction to this package:
+// http://golang.org/doc/articles/json_and_go.html
+package json
+
+import (
+	"bytes"
+	"encoding"
+	"encoding/base64"
+	"math"
+	"reflect"
+	"runtime"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"unicode"
+	"unicode/utf8"
+)
+
+// Marshal returns the JSON encoding of v.
+//
+// Marshal traverses the value v recursively.
+// If an encountered value implements the Marshaler interface
+// and is not a nil pointer, Marshal calls its MarshalJSON method
+// to produce JSON.  The nil pointer exception is not strictly necessary
+// but mimics a similar, necessary exception in the behavior of
+// UnmarshalJSON.
+//
+// Otherwise, Marshal uses the following type-dependent default encodings:
+//
+// Boolean values encode as JSON booleans.
+//
+// Floating point, integer, and Number values encode as JSON numbers.
+//
+// String values encode as JSON strings. InvalidUTF8Error will be returned
+// if an invalid UTF-8 sequence is encountered.
+// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
+// to keep some browsers from misinterpreting JSON output as HTML.
+// Ampersand "&" is also escaped to "\u0026" for the same reason.
+//
+// Array and slice values encode as JSON arrays, except that
+// []byte encodes as a base64-encoded string, and a nil slice
+// encodes as the null JSON object.
+//
+// Struct values encode as JSON objects. Each exported struct field
+// becomes a member of the object unless
+//   - the field's tag is "-", or
+//   - the field is empty and its tag specifies the "omitempty" option.
+// The empty values are false, 0, any
+// nil pointer or interface value, and any array, slice, map, or string of
+// length zero. The object's default key string is the struct field name
+// but can be specified in the struct field's tag value. The "json" key in
+// the struct field's tag value is the key name, followed by an optional comma
+// and options. Examples:
+//
+//   // Field is ignored by this package.
+//   Field int `json:"-"`
+//
+//   // Field appears in JSON as key "myName".
+//   Field int `json:"myName"`
+//
+//   // Field appears in JSON as key "myName" and
+//   // the field is omitted from the object if its value is empty,
+//   // as defined above.
+//   Field int `json:"myName,omitempty"`
+//
+//   // Field appears in JSON as key "Field" (the default), but
+//   // the field is skipped if empty.
+//   // Note the leading comma.
+//   Field int `json:",omitempty"`
+//
+// The "string" option signals that a field is stored as JSON inside a
+// JSON-encoded string. It applies only to fields of string, floating point,
+// or integer types. This extra level of encoding is sometimes used when
+// communicating with JavaScript programs:
+//
+//    Int64String int64 `json:",string"`
+//
+// The key name will be used if it's a non-empty string consisting of
+// only Unicode letters, digits, dollar signs, percent signs, hyphens,
+// underscores and slashes.
+//
+// Anonymous struct fields are usually marshaled as if their inner exported fields
+// were fields in the outer struct, subject to the usual Go visibility rules amended
+// as described in the next paragraph.
+// An anonymous struct field with a name given in its JSON tag is treated as
+// having that name, rather than being anonymous.
+//
+// The Go visibility rules for struct fields are amended for JSON when
+// deciding which field to marshal or unmarshal. If there are
+// multiple fields at the same level, and that level is the least
+// nested (and would therefore be the nesting level selected by the
+// usual Go rules), the following extra rules apply:
+//
+// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
+// even if there are multiple untagged fields that would otherwise conflict.
+// 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
+// 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
+//
+// Handling of anonymous struct fields is new in Go 1.1.
+// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
+// an anonymous struct field in both current and earlier versions, give the field
+// a JSON tag of "-".
+//
+// Map values encode as JSON objects.
+// The map's key type must be string; the object keys are used directly
+// as map keys.
+//
+// Pointer values encode as the value pointed to.
+// A nil pointer encodes as the null JSON object.
+//
+// Interface values encode as the value contained in the interface.
+// A nil interface value encodes as the null JSON object.
+//
+// Channel, complex, and function values cannot be encoded in JSON.
+// Attempting to encode such a value causes Marshal to return
+// an UnsupportedTypeError.
+//
+// JSON cannot represent cyclic data structures and Marshal does not
+// handle them.  Passing cyclic structures to Marshal will result in
+// an infinite recursion.
+//
+func Marshal(v interface{}) ([]byte, error) {
+	e := &encodeState{}
+	err := e.marshal(v)
+	if err != nil {
+		return nil, err
+	}
+	return e.Bytes(), nil
+}
+
+// MarshalIndent is like Marshal but applies Indent to format the output.
+func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
+	b, err := Marshal(v)
+	if err != nil {
+		return nil, err
+	}
+	var buf bytes.Buffer
+	err = Indent(&buf, b, prefix, indent)
+	if err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
+}
+
+// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
+// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
+// so that the JSON will be safe to embed inside HTML <script> tags.
+// For historical reasons, web browsers don't honor standard HTML
+// escaping within <script> tags, so an alternative JSON encoding must
+// be used.
+func HTMLEscape(dst *bytes.Buffer, src []byte) {
+	// The characters can only appear in string literals,
+	// so just scan the string one byte at a time.
+	start := 0
+	for i, c := range src {
+		if c == '<' || c == '>' || c == '&' {
+			if start < i {
+				dst.Write(src[start:i])
+			}
+			dst.WriteString(`\u00`)
+			dst.WriteByte(hex[c>>4])
+			dst.WriteByte(hex[c&0xF])
+			start = i + 1
+		}
+		// Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
+		if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
+			if start < i {
+				dst.Write(src[start:i])
+			}
+			dst.WriteString(`\u202`)
+			dst.WriteByte(hex[src[i+2]&0xF])
+			start = i + 3
+		}
+	}
+	if start < len(src) {
+		dst.Write(src[start:])
+	}
+}
+
+// Marshaler is the interface implemented by objects that
+// can marshal themselves into valid JSON.
+type Marshaler interface {
+	MarshalJSON() ([]byte, error)
+}
+
+// An UnsupportedTypeError is returned by Marshal when attempting
+// to encode an unsupported value type.
+type UnsupportedTypeError struct {
+	Type reflect.Type
+}
+
+func (e *UnsupportedTypeError) Error() string {
+	return "json: unsupported type: " + e.Type.String()
+}
+
+type UnsupportedValueError struct {
+	Value reflect.Value
+	Str   string
+}
+
+func (e *UnsupportedValueError) Error() string {
+	return "json: unsupported value: " + e.Str
+}
+
+// Before Go 1.2, an InvalidUTF8Error was returned by Marshal when
+// attempting to encode a string value with invalid UTF-8 sequences.
+// As of Go 1.2, Marshal instead coerces the string to valid UTF-8 by
+// replacing invalid bytes with the Unicode replacement rune U+FFFD.
+// This error is no longer generated but is kept for backwards compatibility
+// with programs that might mention it.
+type InvalidUTF8Error struct {
+	S string // the whole string value that caused the error
+}
+
+func (e *InvalidUTF8Error) Error() string {
+	return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
+}
+
+type MarshalerError struct {
+	Type reflect.Type
+	Err  error
+}
+
+func (e *MarshalerError) Error() string {
+	return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Err.Error()
+}
+
+var hex = "0123456789abcdef"
+
+// An encodeState encodes JSON into a bytes.Buffer.
+type encodeState struct {
+	bytes.Buffer // accumulated output
+	scratch      [64]byte
+}
+
+var encodeStatePool sync.Pool
+
+func newEncodeState() *encodeState {
+	if v := encodeStatePool.Get(); v != nil {
+		e := v.(*encodeState)
+		e.Reset()
+		return e
+	}
+	return new(encodeState)
+}
+
+func (e *encodeState) marshal(v interface{}) (err error) {
+	defer func() {
+		if r := recover(); r != nil {
+			if _, ok := r.(runtime.Error); ok {
+				panic(r)
+			}
+			if s, ok := r.(string); ok {
+				panic(s)
+			}
+			err = r.(error)
+		}
+	}()
+	e.reflectValue(reflect.ValueOf(v))
+	return nil
+}
+
+func (e *encodeState) error(err error) {
+	panic(err)
+}
+
+var byteSliceType = reflect.TypeOf([]byte(nil))
+
+func isEmptyValue(v reflect.Value) bool {
+	switch v.Kind() {
+	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+		return v.Len() == 0
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return v.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.Interface, reflect.Ptr:
+		return v.IsNil()
+	}
+	return false
+}
+
+func (e *encodeState) reflectValue(v reflect.Value) {
+	valueEncoder(v)(e, v, false)
+}
+
+type encoderFunc func(e *encodeState, v reflect.Value, quoted bool)
+
+var encoderCache struct {
+	sync.RWMutex
+	m map[reflect.Type]encoderFunc
+}
+
+func valueEncoder(v reflect.Value) encoderFunc {
+	if !v.IsValid() {
+		return invalidValueEncoder
+	}
+	return typeEncoder(v.Type())
+}
+
+func typeEncoder(t reflect.Type) encoderFunc {
+	encoderCache.RLock()
+	f := encoderCache.m[t]
+	encoderCache.RUnlock()
+	if f != nil {
+		return f
+	}
+
+	// To deal with recursive types, populate the map with an
+	// indirect func before we build it. This type waits on the
+	// real func (f) to be ready and then calls it.  This indirect
+	// func is only used for recursive types.
+	encoderCache.Lock()
+	if encoderCache.m == nil {
+		encoderCache.m = make(map[reflect.Type]encoderFunc)
+	}
+	var wg sync.WaitGroup
+	wg.Add(1)
+	encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) {
+		wg.Wait()
+		f(e, v, quoted)
+	}
+	encoderCache.Unlock()
+
+	// Compute fields without lock.
+	// Might duplicate effort but won't hold other computations back.
+	f = newTypeEncoder(t, true)
+	wg.Done()
+	encoderCache.Lock()
+	encoderCache.m[t] = f
+	encoderCache.Unlock()
+	return f
+}
+
+var (
+	marshalerType     = reflect.TypeOf(new(Marshaler)).Elem()
+	textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
+)
+
+// newTypeEncoder constructs an encoderFunc for a type.
+// The returned encoder only checks CanAddr when allowAddr is true.
+func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
+	if t.Implements(marshalerType) {
+		return marshalerEncoder
+	}
+	if t.Kind() != reflect.Ptr && allowAddr {
+		if reflect.PtrTo(t).Implements(marshalerType) {
+			return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
+		}
+	}
+
+	if t.Implements(textMarshalerType) {
+		return textMarshalerEncoder
+	}
+	if t.Kind() != reflect.Ptr && allowAddr {
+		if reflect.PtrTo(t).Implements(textMarshalerType) {
+			return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
+		}
+	}
+
+	switch t.Kind() {
+	case reflect.Bool:
+		return boolEncoder
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return intEncoder
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return uintEncoder
+	case reflect.Float32:
+		return float32Encoder
+	case reflect.Float64:
+		return float64Encoder
+	case reflect.String:
+		return stringEncoder
+	case reflect.Interface:
+		return interfaceEncoder
+	case reflect.Struct:
+		return newStructEncoder(t)
+	case reflect.Map:
+		return newMapEncoder(t)
+	case reflect.Slice:
+		return newSliceEncoder(t)
+	case reflect.Array:
+		return newArrayEncoder(t)
+	case reflect.Ptr:
+		return newPtrEncoder(t)
+	default:
+		return unsupportedTypeEncoder
+	}
+}
+
+func invalidValueEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	e.WriteString("null")
+}
+
+func marshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	if v.Kind() == reflect.Ptr && v.IsNil() {
+		e.WriteString("null")
+		return
+	}
+	m := v.Interface().(Marshaler)
+	b, err := m.MarshalJSON()
+	if err == nil {
+		// copy JSON into buffer, checking validity.
+		err = compact(&e.Buffer, b, true)
+	}
+	if err != nil {
+		e.error(&MarshalerError{v.Type(), err})
+	}
+}
+
+func addrMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	va := v.Addr()
+	if va.IsNil() {
+		e.WriteString("null")
+		return
+	}
+	m := va.Interface().(Marshaler)
+	b, err := m.MarshalJSON()
+	if err == nil {
+		// copy JSON into buffer, checking validity.
+		err = compact(&e.Buffer, b, true)
+	}
+	if err != nil {
+		e.error(&MarshalerError{v.Type(), err})
+	}
+}
+
+func textMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	if v.Kind() == reflect.Ptr && v.IsNil() {
+		e.WriteString("null")
+		return
+	}
+	m := v.Interface().(encoding.TextMarshaler)
+	b, err := m.MarshalText()
+	if err == nil {
+		_, err = e.stringBytes(b)
+	}
+	if err != nil {
+		e.error(&MarshalerError{v.Type(), err})
+	}
+}
+
+func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	va := v.Addr()
+	if va.IsNil() {
+		e.WriteString("null")
+		return
+	}
+	m := va.Interface().(encoding.TextMarshaler)
+	b, err := m.MarshalText()
+	if err == nil {
+		_, err = e.stringBytes(b)
+	}
+	if err != nil {
+		e.error(&MarshalerError{v.Type(), err})
+	}
+}
+
+func boolEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	if quoted {
+		e.WriteByte('"')
+	}
+	if v.Bool() {
+		e.WriteString("true")
+	} else {
+		e.WriteString("false")
+	}
+	if quoted {
+		e.WriteByte('"')
+	}
+}
+
+func intEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
+	if quoted {
+		e.WriteByte('"')
+	}
+	e.Write(b)
+	if quoted {
+		e.WriteByte('"')
+	}
+}
+
+func uintEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
+	if quoted {
+		e.WriteByte('"')
+	}
+	e.Write(b)
+	if quoted {
+		e.WriteByte('"')
+	}
+}
+
+type floatEncoder int // number of bits
+
+func (bits floatEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
+	f := v.Float()
+	if math.IsInf(f, 0) || math.IsNaN(f) {
+		e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
+	}
+	b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, int(bits))
+	if quoted {
+		e.WriteByte('"')
+	}
+	e.Write(b)
+	if quoted {
+		e.WriteByte('"')
+	}
+}
+
+var (
+	float32Encoder = (floatEncoder(32)).encode
+	float64Encoder = (floatEncoder(64)).encode
+)
+
+func stringEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	if v.Type() == numberType {
+		numStr := v.String()
+		if numStr == "" {
+			numStr = "0" // Number's zero-val
+		}
+		e.WriteString(numStr)
+		return
+	}
+	if quoted {
+		sb, err := Marshal(v.String())
+		if err != nil {
+			e.error(err)
+		}
+		e.string(string(sb))
+	} else {
+		e.string(v.String())
+	}
+}
+
+func interfaceEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	if v.IsNil() {
+		e.WriteString("null")
+		return
+	}
+	e.reflectValue(v.Elem())
+}
+
+func unsupportedTypeEncoder(e *encodeState, v reflect.Value, quoted bool) {
+	e.error(&UnsupportedTypeError{v.Type()})
+}
+
+type structEncoder struct {
+	fields    []field
+	fieldEncs []encoderFunc
+}
+
+func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
+	e.WriteByte('{')
+	first := true
+	for i, f := range se.fields {
+		fv := fieldByIndex(v, f.index)
+		if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
+			continue
+		}
+		if first {
+			first = false
+		} else {
+			e.WriteByte(',')
+		}
+		e.string(f.name)
+		e.WriteByte(':')
+		se.fieldEncs[i](e, fv, f.quoted)
+	}
+	e.WriteByte('}')
+}
+
+func newStructEncoder(t reflect.Type) encoderFunc {
+	fields := cachedTypeFields(t)
+	se := &structEncoder{
+		fields:    fields,
+		fieldEncs: make([]encoderFunc, len(fields)),
+	}
+	for i, f := range fields {
+		se.fieldEncs[i] = typeEncoder(typeByIndex(t, f.index))
+	}
+	return se.encode
+}
+
+type mapEncoder struct {
+	elemEnc encoderFunc
+}
+
+func (me *mapEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+	if v.IsNil() {
+		e.WriteString("null")
+		return
+	}
+	e.WriteByte('{')
+	var sv stringValues = v.MapKeys()
+	sort.Sort(sv)
+	for i, k := range sv {
+		if i > 0 {
+			e.WriteByte(',')
+		}
+		e.string(k.String())
+		e.WriteByte(':')
+		me.elemEnc(e, v.MapIndex(k), false)
+	}
+	e.WriteByte('}')
+}
+
+func newMapEncoder(t reflect.Type) encoderFunc {
+	if t.Key().Kind() != reflect.String {
+		return unsupportedTypeEncoder
+	}
+	me := &mapEncoder{typeEncoder(t.Elem())}
+	return me.encode
+}
+
+func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) {
+	if v.IsNil() {
+		e.WriteString("null")
+		return
+	}
+	s := v.Bytes()
+	e.WriteByte('"')
+	if len(s) < 1024 {
+		// for small buffers, using Encode directly is much faster.
+		dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
+		base64.StdEncoding.Encode(dst, s)
+		e.Write(dst)
+	} else {
+		// for large buffers, avoid unnecessary extra temporary
+		// buffer space.
+		enc := base64.NewEncoder(base64.StdEncoding, e)
+		enc.Write(s)
+		enc.Close()
+	}
+	e.WriteByte('"')
+}
+
+// sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn't nil.
+type sliceEncoder struct {
+	arrayEnc encoderFunc
+}
+
+func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+	if v.IsNil() {
+		e.WriteString("null")
+		return
+	}
+	se.arrayEnc(e, v, false)
+}
+
+func newSliceEncoder(t reflect.Type) encoderFunc {
+	// Byte slices get special treatment; arrays don't.
+	if t.Elem().Kind() == reflect.Uint8 {
+		return encodeByteSlice
+	}
+	enc := &sliceEncoder{newArrayEncoder(t)}
+	return enc.encode
+}
+
+type arrayEncoder struct {
+	elemEnc encoderFunc
+}
+
+func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+	e.WriteByte('[')
+	n := v.Len()
+	for i := 0; i < n; i++ {
+		if i > 0 {
+			e.WriteByte(',')
+		}
+		ae.elemEnc(e, v.Index(i), false)
+	}
+	e.WriteByte(']')
+}
+
+func newArrayEncoder(t reflect.Type) encoderFunc {
+	enc := &arrayEncoder{typeEncoder(t.Elem())}
+	return enc.encode
+}
+
+type ptrEncoder struct {
+	elemEnc encoderFunc
+}
+
+func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+	if v.IsNil() {
+		e.WriteString("null")
+		return
+	}
+	pe.elemEnc(e, v.Elem(), false)
+}
+
+func newPtrEncoder(t reflect.Type) encoderFunc {
+	enc := &ptrEncoder{typeEncoder(t.Elem())}
+	return enc.encode
+}
+
+type condAddrEncoder struct {
+	canAddrEnc, elseEnc encoderFunc
+}
+
+func (ce *condAddrEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
+	if v.CanAddr() {
+		ce.canAddrEnc(e, v, quoted)
+	} else {
+		ce.elseEnc(e, v, quoted)
+	}
+}
+
+// newCondAddrEncoder returns an encoder that checks whether its value
+// CanAddr and delegates to canAddrEnc if so, else to elseEnc.
+func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
+	enc := &condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
+	return enc.encode
+}
+
+func isValidTag(s string) bool {
+	if s == "" {
+		return false
+	}
+	for _, c := range s {
+		switch {
+		case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
+			// Backslash and quote chars are reserved, but
+			// otherwise any punctuation chars are allowed
+			// in a tag name.
+		default:
+			if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+func fieldByIndex(v reflect.Value, index []int) reflect.Value {
+	for _, i := range index {
+		if v.Kind() == reflect.Ptr {
+			if v.IsNil() {
+				return reflect.Value{}
+			}
+			v = v.Elem()
+		}
+		v = v.Field(i)
+	}
+	return v
+}
+
+func typeByIndex(t reflect.Type, index []int) reflect.Type {
+	for _, i := range index {
+		if t.Kind() == reflect.Ptr {
+			t = t.Elem()
+		}
+		t = t.Field(i).Type
+	}
+	return t
+}
+
+// stringValues is a slice of reflect.Value holding *reflect.StringValue.
+// It implements the methods to sort by string.
+type stringValues []reflect.Value
+
+func (sv stringValues) Len() int           { return len(sv) }
+func (sv stringValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] }
+func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
+func (sv stringValues) get(i int) string   { return sv[i].String() }
+
+// NOTE: keep in sync with stringBytes below.
+func (e *encodeState) string(s string) (int, error) {
+	len0 := e.Len()
+	e.WriteByte('"')
+	start := 0
+	for i := 0; i < len(s); {
+		if b := s[i]; b < utf8.RuneSelf {
+			if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
+				i++
+				continue
+			}
+			if start < i {
+				e.WriteString(s[start:i])
+			}
+			switch b {
+			case '\\', '"':
+				e.WriteByte('\\')
+				e.WriteByte(b)
+			case '\n':
+				e.WriteByte('\\')
+				e.WriteByte('n')
+			case '\r':
+				e.WriteByte('\\')
+				e.WriteByte('r')
+			default:
+				// This encodes bytes < 0x20 except for \n and \r,
+				// as well as <, > and &. The latter are escaped because they
+				// can lead to security holes when user-controlled strings
+				// are rendered into JSON and served to some browsers.
+				e.WriteString(`\u00`)
+				e.WriteByte(hex[b>>4])
+				e.WriteByte(hex[b&0xF])
+			}
+			i++
+			start = i
+			continue
+		}
+		c, size := utf8.DecodeRuneInString(s[i:])
+		if c == utf8.RuneError && size == 1 {
+			if start < i {
+				e.WriteString(s[start:i])
+			}
+			e.WriteString(`\ufffd`)
+			i += size
+			start = i
+			continue
+		}
+		// U+2028 is LINE SEPARATOR.
+		// U+2029 is PARAGRAPH SEPARATOR.
+		// They are both technically valid characters in JSON strings,
+		// but don't work in JSONP, which has to be evaluated as JavaScript,
+		// and can lead to security holes there. It is valid JSON to
+		// escape them, so we do so unconditionally.
+		// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
+		if c == '\u2028' || c == '\u2029' {
+			if start < i {
+				e.WriteString(s[start:i])
+			}
+			e.WriteString(`\u202`)
+			e.WriteByte(hex[c&0xF])
+			i += size
+			start = i
+			continue
+		}
+		i += size
+	}
+	if start < len(s) {
+		e.WriteString(s[start:])
+	}
+	e.WriteByte('"')
+	return e.Len() - len0, nil
+}
+
+// NOTE: keep in sync with string above.
+func (e *encodeState) stringBytes(s []byte) (int, error) {
+	len0 := e.Len()
+	e.WriteByte('"')
+	start := 0
+	for i := 0; i < len(s); {
+		if b := s[i]; b < utf8.RuneSelf {
+			if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
+				i++
+				continue
+			}
+			if start < i {
+				e.Write(s[start:i])
+			}
+			switch b {
+			case '\\', '"':
+				e.WriteByte('\\')
+				e.WriteByte(b)
+			case '\n':
+				e.WriteByte('\\')
+				e.WriteByte('n')
+			case '\r':
+				e.WriteByte('\\')
+				e.WriteByte('r')
+			default:
+				// This encodes bytes < 0x20 except for \n and \r,
+				// as well as < and >. The latter are escaped because they
+				// can lead to security holes when user-controlled strings
+				// are rendered into JSON and served to some browsers.
+				e.WriteString(`\u00`)
+				e.WriteByte(hex[b>>4])
+				e.WriteByte(hex[b&0xF])
+			}
+			i++
+			start = i
+			continue
+		}
+		c, size := utf8.DecodeRune(s[i:])
+		if c == utf8.RuneError && size == 1 {
+			if start < i {
+				e.Write(s[start:i])
+			}
+			e.WriteString(`\ufffd`)
+			i += size
+			start = i
+			continue
+		}
+		// U+2028 is LINE SEPARATOR.
+		// U+2029 is PARAGRAPH SEPARATOR.
+		// They are both technically valid characters in JSON strings,
+		// but don't work in JSONP, which has to be evaluated as JavaScript,
+		// and can lead to security holes there. It is valid JSON to
+		// escape them, so we do so unconditionally.
+		// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
+		if c == '\u2028' || c == '\u2029' {
+			if start < i {
+				e.Write(s[start:i])
+			}
+			e.WriteString(`\u202`)
+			e.WriteByte(hex[c&0xF])
+			i += size
+			start = i
+			continue
+		}
+		i += size
+	}
+	if start < len(s) {
+		e.Write(s[start:])
+	}
+	e.WriteByte('"')
+	return e.Len() - len0, nil
+}
+
+// A field represents a single field found in a struct.
+type field struct {
+	name      string
+	nameBytes []byte                 // []byte(name)
+	equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent
+
+	tag       bool
+	index     []int
+	typ       reflect.Type
+	omitEmpty bool
+	quoted    bool
+}
+
+func fillField(f field) field {
+	f.nameBytes = []byte(f.name)
+	f.equalFold = foldFunc(f.nameBytes)
+	return f
+}
+
+// byName sorts field by name, breaking ties with depth,
+// then breaking ties with "name came from json tag", then
+// breaking ties with index sequence.
+type byName []field
+
+func (x byName) Len() int { return len(x) }
+
+func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+func (x byName) Less(i, j int) bool {
+	if x[i].name != x[j].name {
+		return x[i].name < x[j].name
+	}
+	if len(x[i].index) != len(x[j].index) {
+		return len(x[i].index) < len(x[j].index)
+	}
+	if x[i].tag != x[j].tag {
+		return x[i].tag
+	}
+	return byIndex(x).Less(i, j)
+}
+
+// byIndex sorts field by index sequence.
+type byIndex []field
+
+func (x byIndex) Len() int { return len(x) }
+
+func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+func (x byIndex) Less(i, j int) bool {
+	for k, xik := range x[i].index {
+		if k >= len(x[j].index) {
+			return false
+		}
+		if xik != x[j].index[k] {
+			return xik < x[j].index[k]
+		}
+	}
+	return len(x[i].index) < len(x[j].index)
+}
+
+// typeFields returns a list of fields that JSON should recognize for the given type.
+// The algorithm is breadth-first search over the set of structs to include - the top struct
+// and then any reachable anonymous structs.
+func typeFields(t reflect.Type) []field {
+	// Anonymous fields to explore at the current level and the next.
+	current := []field{}
+	next := []field{{typ: t}}
+
+	// Count of queued names for current level and the next.
+	count := map[reflect.Type]int{}
+	nextCount := map[reflect.Type]int{}
+
+	// Types already visited at an earlier level.
+	visited := map[reflect.Type]bool{}
+
+	// Fields found.
+	var fields []field
+
+	for len(next) > 0 {
+		current, next = next, current[:0]
+		count, nextCount = nextCount, map[reflect.Type]int{}
+
+		for _, f := range current {
+			if visited[f.typ] {
+				continue
+			}
+			visited[f.typ] = true
+
+			// Scan f.typ for fields to include.
+			for i := 0; i < f.typ.NumField(); i++ {
+				sf := f.typ.Field(i)
+				if sf.PkgPath != "" { // unexported
+					continue
+				}
+				tag := sf.Tag.Get("json")
+				if tag == "-" {
+					continue
+				}
+				name, opts := parseTag(tag)
+				if !isValidTag(name) {
+					name = ""
+				}
+				index := make([]int, len(f.index)+1)
+				copy(index, f.index)
+				index[len(f.index)] = i
+
+				ft := sf.Type
+				if ft.Name() == "" && ft.Kind() == reflect.Ptr {
+					// Follow pointer.
+					ft = ft.Elem()
+				}
+
+				// Record found field and index sequence.
+				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
+					tagged := name != ""
+					if name == "" {
+						name = sf.Name
+					}
+					fields = append(fields, fillField(field{
+						name:      name,
+						tag:       tagged,
+						index:     index,
+						typ:       ft,
+						omitEmpty: opts.Contains("omitempty"),
+						quoted:    opts.Contains("string"),
+					}))
+					if count[f.typ] > 1 {
+						// If there were multiple instances, add a second,
+						// so that the annihilation code will see a duplicate.
+						// It only cares about the distinction between 1 or 2,
+						// so don't bother generating any more copies.
+						fields = append(fields, fields[len(fields)-1])
+					}
+					continue
+				}
+
+				// Record new anonymous struct to explore in next round.
+				nextCount[ft]++
+				if nextCount[ft] == 1 {
+					next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft}))
+				}
+			}
+		}
+	}
+
+	sort.Sort(byName(fields))
+
+	// Delete all fields that are hidden by the Go rules for embedded fields,
+	// except that fields with JSON tags are promoted.
+
+	// The fields are sorted in primary order of name, secondary order
+	// of field index length. Loop over names; for each name, delete
+	// hidden fields by choosing the one dominant field that survives.
+	out := fields[:0]
+	for advance, i := 0, 0; i < len(fields); i += advance {
+		// One iteration per name.
+		// Find the sequence of fields with the name of this first field.
+		fi := fields[i]
+		name := fi.name
+		for advance = 1; i+advance < len(fields); advance++ {
+			fj := fields[i+advance]
+			if fj.name != name {
+				break
+			}
+		}
+		if advance == 1 { // Only one field with this name
+			out = append(out, fi)
+			continue
+		}
+		dominant, ok := dominantField(fields[i : i+advance])
+		if ok {
+			out = append(out, dominant)
+		}
+	}
+
+	fields = out
+	sort.Sort(byIndex(fields))
+
+	return fields
+}
+
+// dominantField looks through the fields, all of which are known to
+// have the same name, to find the single field that dominates the
+// others using Go's embedding rules, modified by the presence of
+// JSON tags. If there are multiple top-level fields, the boolean
+// will be false: This condition is an error in Go and we skip all
+// the fields.
+func dominantField(fields []field) (field, bool) {
+	// The fields are sorted in increasing index-length order. The winner
+	// must therefore be one with the shortest index length. Drop all
+	// longer entries, which is easy: just truncate the slice.
+	length := len(fields[0].index)
+	tagged := -1 // Index of first tagged field.
+	for i, f := range fields {
+		if len(f.index) > length {
+			fields = fields[:i]
+			break
+		}
+		if f.tag {
+			if tagged >= 0 {
+				// Multiple tagged fields at the same level: conflict.
+				// Return no field.
+				return field{}, false
+			}
+			tagged = i
+		}
+	}
+	if tagged >= 0 {
+		return fields[tagged], true
+	}
+	// All remaining fields have the same length. If there's more than one,
+	// we have a conflict (two fields named "X" at the same level) and we
+	// return no field.
+	if len(fields) > 1 {
+		return field{}, false
+	}
+	return fields[0], true
+}
+
+var fieldCache struct {
+	sync.RWMutex
+	m map[reflect.Type][]field
+}
+
+// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
+func cachedTypeFields(t reflect.Type) []field {
+	fieldCache.RLock()
+	f := fieldCache.m[t]
+	fieldCache.RUnlock()
+	if f != nil {
+		return f
+	}
+
+	// Compute fields without lock.
+	// Might duplicate effort but won't hold other computations back.
+	f = typeFields(t)
+	if f == nil {
+		f = []field{}
+	}
+
+	fieldCache.Lock()
+	if fieldCache.m == nil {
+		fieldCache.m = map[reflect.Type][]field{}
+	}
+	fieldCache.m[t] = f
+	fieldCache.Unlock()
+	return f
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/encode_test.go b/third_party/gofrontend/libgo/go/encoding/json/encode_test.go
new file mode 100644
index 0000000..2e89a78
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/encode_test.go
@@ -0,0 +1,454 @@
+// 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.
+
+package json
+
+import (
+	"bytes"
+	"math"
+	"reflect"
+	"testing"
+	"unicode"
+)
+
+type Optionals struct {
+	Sr string `json:"sr"`
+	So string `json:"so,omitempty"`
+	Sw string `json:"-"`
+
+	Ir int `json:"omitempty"` // actually named omitempty, not an option
+	Io int `json:"io,omitempty"`
+
+	Slr []string `json:"slr,random"`
+	Slo []string `json:"slo,omitempty"`
+
+	Mr map[string]interface{} `json:"mr"`
+	Mo map[string]interface{} `json:",omitempty"`
+
+	Fr float64 `json:"fr"`
+	Fo float64 `json:"fo,omitempty"`
+
+	Br bool `json:"br"`
+	Bo bool `json:"bo,omitempty"`
+
+	Ur uint `json:"ur"`
+	Uo uint `json:"uo,omitempty"`
+
+	Str struct{} `json:"str"`
+	Sto struct{} `json:"sto,omitempty"`
+}
+
+var optionalsExpected = `{
+ "sr": "",
+ "omitempty": 0,
+ "slr": null,
+ "mr": {},
+ "fr": 0,
+ "br": false,
+ "ur": 0,
+ "str": {},
+ "sto": {}
+}`
+
+func TestOmitEmpty(t *testing.T) {
+	var o Optionals
+	o.Sw = "something"
+	o.Mr = map[string]interface{}{}
+	o.Mo = map[string]interface{}{}
+
+	got, err := MarshalIndent(&o, "", " ")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got := string(got); got != optionalsExpected {
+		t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
+	}
+}
+
+type StringTag struct {
+	BoolStr bool   `json:",string"`
+	IntStr  int64  `json:",string"`
+	StrStr  string `json:",string"`
+}
+
+var stringTagExpected = `{
+ "BoolStr": "true",
+ "IntStr": "42",
+ "StrStr": "\"xzbit\""
+}`
+
+func TestStringTag(t *testing.T) {
+	var s StringTag
+	s.BoolStr = true
+	s.IntStr = 42
+	s.StrStr = "xzbit"
+	got, err := MarshalIndent(&s, "", " ")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got := string(got); got != stringTagExpected {
+		t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)
+	}
+
+	// Verify that it round-trips.
+	var s2 StringTag
+	err = NewDecoder(bytes.NewReader(got)).Decode(&s2)
+	if err != nil {
+		t.Fatalf("Decode: %v", err)
+	}
+	if !reflect.DeepEqual(s, s2) {
+		t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
+	}
+}
+
+// byte slices are special even if they're renamed types.
+type renamedByte byte
+type renamedByteSlice []byte
+type renamedRenamedByteSlice []renamedByte
+
+func TestEncodeRenamedByteSlice(t *testing.T) {
+	s := renamedByteSlice("abc")
+	result, err := Marshal(s)
+	if err != nil {
+		t.Fatal(err)
+	}
+	expect := `"YWJj"`
+	if string(result) != expect {
+		t.Errorf(" got %s want %s", result, expect)
+	}
+	r := renamedRenamedByteSlice("abc")
+	result, err = Marshal(r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(result) != expect {
+		t.Errorf(" got %s want %s", result, expect)
+	}
+}
+
+var unsupportedValues = []interface{}{
+	math.NaN(),
+	math.Inf(-1),
+	math.Inf(1),
+}
+
+func TestUnsupportedValues(t *testing.T) {
+	for _, v := range unsupportedValues {
+		if _, err := Marshal(v); err != nil {
+			if _, ok := err.(*UnsupportedValueError); !ok {
+				t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
+			}
+		} else {
+			t.Errorf("for %v, expected error", v)
+		}
+	}
+}
+
+// Ref has Marshaler and Unmarshaler methods with pointer receiver.
+type Ref int
+
+func (*Ref) MarshalJSON() ([]byte, error) {
+	return []byte(`"ref"`), nil
+}
+
+func (r *Ref) UnmarshalJSON([]byte) error {
+	*r = 12
+	return nil
+}
+
+// Val has Marshaler methods with value receiver.
+type Val int
+
+func (Val) MarshalJSON() ([]byte, error) {
+	return []byte(`"val"`), nil
+}
+
+// RefText has Marshaler and Unmarshaler methods with pointer receiver.
+type RefText int
+
+func (*RefText) MarshalText() ([]byte, error) {
+	return []byte(`"ref"`), nil
+}
+
+func (r *RefText) UnmarshalText([]byte) error {
+	*r = 13
+	return nil
+}
+
+// ValText has Marshaler methods with value receiver.
+type ValText int
+
+func (ValText) MarshalText() ([]byte, error) {
+	return []byte(`"val"`), nil
+}
+
+func TestRefValMarshal(t *testing.T) {
+	var s = struct {
+		R0 Ref
+		R1 *Ref
+		R2 RefText
+		R3 *RefText
+		V0 Val
+		V1 *Val
+		V2 ValText
+		V3 *ValText
+	}{
+		R0: 12,
+		R1: new(Ref),
+		R2: 14,
+		R3: new(RefText),
+		V0: 13,
+		V1: new(Val),
+		V2: 15,
+		V3: new(ValText),
+	}
+	const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
+	b, err := Marshal(&s)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	if got := string(b); got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
+
+// C implements Marshaler and returns unescaped JSON.
+type C int
+
+func (C) MarshalJSON() ([]byte, error) {
+	return []byte(`"<&>"`), nil
+}
+
+// CText implements Marshaler and returns unescaped text.
+type CText int
+
+func (CText) MarshalText() ([]byte, error) {
+	return []byte(`"<&>"`), nil
+}
+
+func TestMarshalerEscaping(t *testing.T) {
+	var c C
+	want := `"\u003c\u0026\u003e"`
+	b, err := Marshal(c)
+	if err != nil {
+		t.Fatalf("Marshal(c): %v", err)
+	}
+	if got := string(b); got != want {
+		t.Errorf("Marshal(c) = %#q, want %#q", got, want)
+	}
+
+	var ct CText
+	want = `"\"\u003c\u0026\u003e\""`
+	b, err = Marshal(ct)
+	if err != nil {
+		t.Fatalf("Marshal(ct): %v", err)
+	}
+	if got := string(b); got != want {
+		t.Errorf("Marshal(ct) = %#q, want %#q", got, want)
+	}
+}
+
+type IntType int
+
+type MyStruct struct {
+	IntType
+}
+
+func TestAnonymousNonstruct(t *testing.T) {
+	var i IntType = 11
+	a := MyStruct{i}
+	const want = `{"IntType":11}`
+
+	b, err := Marshal(a)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	if got := string(b); got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
+
+type BugA struct {
+	S string
+}
+
+type BugB struct {
+	BugA
+	S string
+}
+
+type BugC struct {
+	S string
+}
+
+// Legal Go: We never use the repeated embedded field (S).
+type BugX struct {
+	A int
+	BugA
+	BugB
+}
+
+// Issue 5245.
+func TestEmbeddedBug(t *testing.T) {
+	v := BugB{
+		BugA{"A"},
+		"B",
+	}
+	b, err := Marshal(v)
+	if err != nil {
+		t.Fatal("Marshal:", err)
+	}
+	want := `{"S":"B"}`
+	got := string(b)
+	if got != want {
+		t.Fatalf("Marshal: got %s want %s", got, want)
+	}
+	// Now check that the duplicate field, S, does not appear.
+	x := BugX{
+		A: 23,
+	}
+	b, err = Marshal(x)
+	if err != nil {
+		t.Fatal("Marshal:", err)
+	}
+	want = `{"A":23}`
+	got = string(b)
+	if got != want {
+		t.Fatalf("Marshal: got %s want %s", got, want)
+	}
+}
+
+type BugD struct { // Same as BugA after tagging.
+	XXX string `json:"S"`
+}
+
+// BugD's tagged S field should dominate BugA's.
+type BugY struct {
+	BugA
+	BugD
+}
+
+// Test that a field with a tag dominates untagged fields.
+func TestTaggedFieldDominates(t *testing.T) {
+	v := BugY{
+		BugA{"BugA"},
+		BugD{"BugD"},
+	}
+	b, err := Marshal(v)
+	if err != nil {
+		t.Fatal("Marshal:", err)
+	}
+	want := `{"S":"BugD"}`
+	got := string(b)
+	if got != want {
+		t.Fatalf("Marshal: got %s want %s", got, want)
+	}
+}
+
+// There are no tags here, so S should not appear.
+type BugZ struct {
+	BugA
+	BugC
+	BugY // Contains a tagged S field through BugD; should not dominate.
+}
+
+func TestDuplicatedFieldDisappears(t *testing.T) {
+	v := BugZ{
+		BugA{"BugA"},
+		BugC{"BugC"},
+		BugY{
+			BugA{"nested BugA"},
+			BugD{"nested BugD"},
+		},
+	}
+	b, err := Marshal(v)
+	if err != nil {
+		t.Fatal("Marshal:", err)
+	}
+	want := `{}`
+	got := string(b)
+	if got != want {
+		t.Fatalf("Marshal: got %s want %s", got, want)
+	}
+}
+
+func TestStringBytes(t *testing.T) {
+	// Test that encodeState.stringBytes and encodeState.string use the same encoding.
+	es := &encodeState{}
+	var r []rune
+	for i := '\u0000'; i <= unicode.MaxRune; i++ {
+		r = append(r, i)
+	}
+	s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too
+	_, err := es.string(s)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	esBytes := &encodeState{}
+	_, err = esBytes.stringBytes([]byte(s))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	enc := es.Buffer.String()
+	encBytes := esBytes.Buffer.String()
+	if enc != encBytes {
+		i := 0
+		for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] {
+			i++
+		}
+		enc = enc[i:]
+		encBytes = encBytes[i:]
+		i = 0
+		for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] {
+			i++
+		}
+		enc = enc[:len(enc)-i]
+		encBytes = encBytes[:len(encBytes)-i]
+
+		if len(enc) > 20 {
+			enc = enc[:20] + "..."
+		}
+		if len(encBytes) > 20 {
+			encBytes = encBytes[:20] + "..."
+		}
+
+		t.Errorf("encodings differ at %#q vs %#q", enc, encBytes)
+	}
+}
+
+func TestIssue6458(t *testing.T) {
+	type Foo struct {
+		M RawMessage
+	}
+	x := Foo{RawMessage(`"foo"`)}
+
+	b, err := Marshal(&x)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if want := `{"M":"foo"}`; string(b) != want {
+		t.Errorf("Marshal(&x) = %#q; want %#q", b, want)
+	}
+
+	b, err = Marshal(x)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if want := `{"M":"ImZvbyI="}`; string(b) != want {
+		t.Errorf("Marshal(x) = %#q; want %#q", b, want)
+	}
+}
+
+func TestHTMLEscape(t *testing.T) {
+	var b, want bytes.Buffer
+	m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`
+	want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))
+	HTMLEscape(&b, []byte(m))
+	if !bytes.Equal(b.Bytes(), want.Bytes()) {
+		t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes())
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/fold.go b/third_party/gofrontend/libgo/go/encoding/json/fold.go
new file mode 100644
index 0000000..d6f77c9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/fold.go
@@ -0,0 +1,143 @@
+// Copyright 2013 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 json
+
+import (
+	"bytes"
+	"unicode/utf8"
+)
+
+const (
+	caseMask     = ^byte(0x20) // Mask to ignore case in ASCII.
+	kelvin       = '\u212a'
+	smallLongEss = '\u017f'
+)
+
+// foldFunc returns one of four different case folding equivalence
+// functions, from most general (and slow) to fastest:
+//
+// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
+// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
+// 3) asciiEqualFold, no special, but includes non-letters (including _)
+// 4) simpleLetterEqualFold, no specials, no non-letters.
+//
+// The letters S and K are special because they map to 3 runes, not just 2:
+//  * S maps to s and to U+017F 'ſ' Latin small letter long s
+//  * k maps to K and to U+212A 'K' Kelvin sign
+// See http://play.golang.org/p/tTxjOc0OGo
+//
+// The returned function is specialized for matching against s and
+// should only be given s. It's not curried for performance reasons.
+func foldFunc(s []byte) func(s, t []byte) bool {
+	nonLetter := false
+	special := false // special letter
+	for _, b := range s {
+		if b >= utf8.RuneSelf {
+			return bytes.EqualFold
+		}
+		upper := b & caseMask
+		if upper < 'A' || upper > 'Z' {
+			nonLetter = true
+		} else if upper == 'K' || upper == 'S' {
+			// See above for why these letters are special.
+			special = true
+		}
+	}
+	if special {
+		return equalFoldRight
+	}
+	if nonLetter {
+		return asciiEqualFold
+	}
+	return simpleLetterEqualFold
+}
+
+// equalFoldRight is a specialization of bytes.EqualFold when s is
+// known to be all ASCII (including punctuation), but contains an 's',
+// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
+// See comments on foldFunc.
+func equalFoldRight(s, t []byte) bool {
+	for _, sb := range s {
+		if len(t) == 0 {
+			return false
+		}
+		tb := t[0]
+		if tb < utf8.RuneSelf {
+			if sb != tb {
+				sbUpper := sb & caseMask
+				if 'A' <= sbUpper && sbUpper <= 'Z' {
+					if sbUpper != tb&caseMask {
+						return false
+					}
+				} else {
+					return false
+				}
+			}
+			t = t[1:]
+			continue
+		}
+		// sb is ASCII and t is not. t must be either kelvin
+		// sign or long s; sb must be s, S, k, or K.
+		tr, size := utf8.DecodeRune(t)
+		switch sb {
+		case 's', 'S':
+			if tr != smallLongEss {
+				return false
+			}
+		case 'k', 'K':
+			if tr != kelvin {
+				return false
+			}
+		default:
+			return false
+		}
+		t = t[size:]
+
+	}
+	if len(t) > 0 {
+		return false
+	}
+	return true
+}
+
+// asciiEqualFold is a specialization of bytes.EqualFold for use when
+// s is all ASCII (but may contain non-letters) and contains no
+// special-folding letters.
+// See comments on foldFunc.
+func asciiEqualFold(s, t []byte) bool {
+	if len(s) != len(t) {
+		return false
+	}
+	for i, sb := range s {
+		tb := t[i]
+		if sb == tb {
+			continue
+		}
+		if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
+			if sb&caseMask != tb&caseMask {
+				return false
+			}
+		} else {
+			return false
+		}
+	}
+	return true
+}
+
+// simpleLetterEqualFold is a specialization of bytes.EqualFold for
+// use when s is all ASCII letters (no underscores, etc) and also
+// doesn't contain 'k', 'K', 's', or 'S'.
+// See comments on foldFunc.
+func simpleLetterEqualFold(s, t []byte) bool {
+	if len(s) != len(t) {
+		return false
+	}
+	for i, b := range s {
+		if b&caseMask != t[i]&caseMask {
+			return false
+		}
+	}
+	return true
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/fold_test.go b/third_party/gofrontend/libgo/go/encoding/json/fold_test.go
new file mode 100644
index 0000000..9fb9464
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/fold_test.go
@@ -0,0 +1,116 @@
+// Copyright 2013 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 json
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+	"unicode/utf8"
+)
+
+var foldTests = []struct {
+	fn   func(s, t []byte) bool
+	s, t string
+	want bool
+}{
+	{equalFoldRight, "", "", true},
+	{equalFoldRight, "a", "a", true},
+	{equalFoldRight, "", "a", false},
+	{equalFoldRight, "a", "", false},
+	{equalFoldRight, "a", "A", true},
+	{equalFoldRight, "AB", "ab", true},
+	{equalFoldRight, "AB", "ac", false},
+	{equalFoldRight, "sbkKc", "ſbKKc", true},
+	{equalFoldRight, "SbKkc", "ſbKKc", true},
+	{equalFoldRight, "SbKkc", "ſbKK", false},
+	{equalFoldRight, "e", "é", false},
+	{equalFoldRight, "s", "S", true},
+
+	{simpleLetterEqualFold, "", "", true},
+	{simpleLetterEqualFold, "abc", "abc", true},
+	{simpleLetterEqualFold, "abc", "ABC", true},
+	{simpleLetterEqualFold, "abc", "ABCD", false},
+	{simpleLetterEqualFold, "abc", "xxx", false},
+
+	{asciiEqualFold, "a_B", "A_b", true},
+	{asciiEqualFold, "aa@", "aa`", false}, // verify 0x40 and 0x60 aren't case-equivalent
+}
+
+func TestFold(t *testing.T) {
+	for i, tt := range foldTests {
+		if got := tt.fn([]byte(tt.s), []byte(tt.t)); got != tt.want {
+			t.Errorf("%d. %q, %q = %v; want %v", i, tt.s, tt.t, got, tt.want)
+		}
+		truth := strings.EqualFold(tt.s, tt.t)
+		if truth != tt.want {
+			t.Errorf("strings.EqualFold doesn't agree with case %d", i)
+		}
+	}
+}
+
+func TestFoldAgainstUnicode(t *testing.T) {
+	const bufSize = 5
+	buf1 := make([]byte, 0, bufSize)
+	buf2 := make([]byte, 0, bufSize)
+	var runes []rune
+	for i := 0x20; i <= 0x7f; i++ {
+		runes = append(runes, rune(i))
+	}
+	runes = append(runes, kelvin, smallLongEss)
+
+	funcs := []struct {
+		name   string
+		fold   func(s, t []byte) bool
+		letter bool // must be ASCII letter
+		simple bool // must be simple ASCII letter (not 'S' or 'K')
+	}{
+		{
+			name: "equalFoldRight",
+			fold: equalFoldRight,
+		},
+		{
+			name:   "asciiEqualFold",
+			fold:   asciiEqualFold,
+			simple: true,
+		},
+		{
+			name:   "simpleLetterEqualFold",
+			fold:   simpleLetterEqualFold,
+			simple: true,
+			letter: true,
+		},
+	}
+
+	for _, ff := range funcs {
+		for _, r := range runes {
+			if r >= utf8.RuneSelf {
+				continue
+			}
+			if ff.letter && !isASCIILetter(byte(r)) {
+				continue
+			}
+			if ff.simple && (r == 's' || r == 'S' || r == 'k' || r == 'K') {
+				continue
+			}
+			for _, r2 := range runes {
+				buf1 := append(buf1[:0], 'x')
+				buf2 := append(buf2[:0], 'x')
+				buf1 = buf1[:1+utf8.EncodeRune(buf1[1:bufSize], r)]
+				buf2 = buf2[:1+utf8.EncodeRune(buf2[1:bufSize], r2)]
+				buf1 = append(buf1, 'x')
+				buf2 = append(buf2, 'x')
+				want := bytes.EqualFold(buf1, buf2)
+				if got := ff.fold(buf1, buf2); got != want {
+					t.Errorf("%s(%q, %q) = %v; want %v", ff.name, buf1, buf2, got, want)
+				}
+			}
+		}
+	}
+}
+
+func isASCIILetter(b byte) bool {
+	return ('A' <= b && b <= 'Z') || ('a' <= b && b <= 'z')
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/indent.go b/third_party/gofrontend/libgo/go/encoding/json/indent.go
new file mode 100644
index 0000000..e1bacaf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/indent.go
@@ -0,0 +1,137 @@
+// Copyright 2010 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 json
+
+import "bytes"
+
+// Compact appends to dst the JSON-encoded src with
+// insignificant space characters elided.
+func Compact(dst *bytes.Buffer, src []byte) error {
+	return compact(dst, src, false)
+}
+
+func compact(dst *bytes.Buffer, src []byte, escape bool) error {
+	origLen := dst.Len()
+	var scan scanner
+	scan.reset()
+	start := 0
+	for i, c := range src {
+		if escape && (c == '<' || c == '>' || c == '&') {
+			if start < i {
+				dst.Write(src[start:i])
+			}
+			dst.WriteString(`\u00`)
+			dst.WriteByte(hex[c>>4])
+			dst.WriteByte(hex[c&0xF])
+			start = i + 1
+		}
+		// Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
+		if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
+			if start < i {
+				dst.Write(src[start:i])
+			}
+			dst.WriteString(`\u202`)
+			dst.WriteByte(hex[src[i+2]&0xF])
+			start = i + 3
+		}
+		v := scan.step(&scan, int(c))
+		if v >= scanSkipSpace {
+			if v == scanError {
+				break
+			}
+			if start < i {
+				dst.Write(src[start:i])
+			}
+			start = i + 1
+		}
+	}
+	if scan.eof() == scanError {
+		dst.Truncate(origLen)
+		return scan.err
+	}
+	if start < len(src) {
+		dst.Write(src[start:])
+	}
+	return nil
+}
+
+func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
+	dst.WriteByte('\n')
+	dst.WriteString(prefix)
+	for i := 0; i < depth; i++ {
+		dst.WriteString(indent)
+	}
+}
+
+// Indent appends to dst an indented form of the JSON-encoded src.
+// Each element in a JSON object or array begins on a new,
+// indented line beginning with prefix followed by one or more
+// copies of indent according to the indentation nesting.
+// The data appended to dst does not begin with the prefix nor
+// any indentation, and has no trailing newline, to make it
+// easier to embed inside other formatted JSON data.
+func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
+	origLen := dst.Len()
+	var scan scanner
+	scan.reset()
+	needIndent := false
+	depth := 0
+	for _, c := range src {
+		scan.bytes++
+		v := scan.step(&scan, int(c))
+		if v == scanSkipSpace {
+			continue
+		}
+		if v == scanError {
+			break
+		}
+		if needIndent && v != scanEndObject && v != scanEndArray {
+			needIndent = false
+			depth++
+			newline(dst, prefix, indent, depth)
+		}
+
+		// Emit semantically uninteresting bytes
+		// (in particular, punctuation in strings) unmodified.
+		if v == scanContinue {
+			dst.WriteByte(c)
+			continue
+		}
+
+		// Add spacing around real punctuation.
+		switch c {
+		case '{', '[':
+			// delay indent so that empty object and array are formatted as {} and [].
+			needIndent = true
+			dst.WriteByte(c)
+
+		case ',':
+			dst.WriteByte(c)
+			newline(dst, prefix, indent, depth)
+
+		case ':':
+			dst.WriteByte(c)
+			dst.WriteByte(' ')
+
+		case '}', ']':
+			if needIndent {
+				// suppress indent in empty object/array
+				needIndent = false
+			} else {
+				depth--
+				newline(dst, prefix, indent, depth)
+			}
+			dst.WriteByte(c)
+
+		default:
+			dst.WriteByte(c)
+		}
+	}
+	if scan.eof() == scanError {
+		dst.Truncate(origLen)
+		return scan.err
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/scanner.go b/third_party/gofrontend/libgo/go/encoding/json/scanner.go
new file mode 100644
index 0000000..a4609c8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/scanner.go
@@ -0,0 +1,623 @@
+// Copyright 2010 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 json
+
+// JSON value parser state machine.
+// Just about at the limit of what is reasonable to write by hand.
+// Some parts are a bit tedious, but overall it nicely factors out the
+// otherwise common code from the multiple scanning functions
+// in this package (Compact, Indent, checkValid, nextValue, etc).
+//
+// This file starts with two simple examples using the scanner
+// before diving into the scanner itself.
+
+import "strconv"
+
+// checkValid verifies that data is valid JSON-encoded data.
+// scan is passed in for use by checkValid to avoid an allocation.
+func checkValid(data []byte, scan *scanner) error {
+	scan.reset()
+	for _, c := range data {
+		scan.bytes++
+		if scan.step(scan, int(c)) == scanError {
+			return scan.err
+		}
+	}
+	if scan.eof() == scanError {
+		return scan.err
+	}
+	return nil
+}
+
+// nextValue splits data after the next whole JSON value,
+// returning that value and the bytes that follow it as separate slices.
+// scan is passed in for use by nextValue to avoid an allocation.
+func nextValue(data []byte, scan *scanner) (value, rest []byte, err error) {
+	scan.reset()
+	for i, c := range data {
+		v := scan.step(scan, int(c))
+		if v >= scanEnd {
+			switch v {
+			case scanError:
+				return nil, nil, scan.err
+			case scanEnd:
+				return data[0:i], data[i:], nil
+			}
+		}
+	}
+	if scan.eof() == scanError {
+		return nil, nil, scan.err
+	}
+	return data, nil, nil
+}
+
+// A SyntaxError is a description of a JSON syntax error.
+type SyntaxError struct {
+	msg    string // description of error
+	Offset int64  // error occurred after reading Offset bytes
+}
+
+func (e *SyntaxError) Error() string { return e.msg }
+
+// A scanner is a JSON scanning state machine.
+// Callers call scan.reset() and then pass bytes in one at a time
+// by calling scan.step(&scan, c) for each byte.
+// The return value, referred to as an opcode, tells the
+// caller about significant parsing events like beginning
+// and ending literals, objects, and arrays, so that the
+// caller can follow along if it wishes.
+// The return value scanEnd indicates that a single top-level
+// JSON value has been completed, *before* the byte that
+// just got passed in.  (The indication must be delayed in order
+// to recognize the end of numbers: is 123 a whole value or
+// the beginning of 12345e+6?).
+type scanner struct {
+	// The step is a func to be called to execute the next transition.
+	// Also tried using an integer constant and a single func
+	// with a switch, but using the func directly was 10% faster
+	// on a 64-bit Mac Mini, and it's nicer to read.
+	step func(*scanner, int) int
+
+	// Reached end of top-level value.
+	endTop bool
+
+	// Stack of what we're in the middle of - array values, object keys, object values.
+	parseState []int
+
+	// Error that happened, if any.
+	err error
+
+	// 1-byte redo (see undo method)
+	redo      bool
+	redoCode  int
+	redoState func(*scanner, int) int
+
+	// total bytes consumed, updated by decoder.Decode
+	bytes int64
+}
+
+// These values are returned by the state transition functions
+// assigned to scanner.state and the method scanner.eof.
+// They give details about the current state of the scan that
+// callers might be interested to know about.
+// It is okay to ignore the return value of any particular
+// call to scanner.state: if one call returns scanError,
+// every subsequent call will return scanError too.
+const (
+	// Continue.
+	scanContinue     = iota // uninteresting byte
+	scanBeginLiteral        // end implied by next result != scanContinue
+	scanBeginObject         // begin object
+	scanObjectKey           // just finished object key (string)
+	scanObjectValue         // just finished non-last object value
+	scanEndObject           // end object (implies scanObjectValue if possible)
+	scanBeginArray          // begin array
+	scanArrayValue          // just finished array value
+	scanEndArray            // end array (implies scanArrayValue if possible)
+	scanSkipSpace           // space byte; can skip; known to be last "continue" result
+
+	// Stop.
+	scanEnd   // top-level value ended *before* this byte; known to be first "stop" result
+	scanError // hit an error, scanner.err.
+)
+
+// These values are stored in the parseState stack.
+// They give the current state of a composite value
+// being scanned.  If the parser is inside a nested value
+// the parseState describes the nested state, outermost at entry 0.
+const (
+	parseObjectKey   = iota // parsing object key (before colon)
+	parseObjectValue        // parsing object value (after colon)
+	parseArrayValue         // parsing array value
+)
+
+// reset prepares the scanner for use.
+// It must be called before calling s.step.
+func (s *scanner) reset() {
+	s.step = stateBeginValue
+	s.parseState = s.parseState[0:0]
+	s.err = nil
+	s.redo = false
+	s.endTop = false
+}
+
+// eof tells the scanner that the end of input has been reached.
+// It returns a scan status just as s.step does.
+func (s *scanner) eof() int {
+	if s.err != nil {
+		return scanError
+	}
+	if s.endTop {
+		return scanEnd
+	}
+	s.step(s, ' ')
+	if s.endTop {
+		return scanEnd
+	}
+	if s.err == nil {
+		s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
+	}
+	return scanError
+}
+
+// pushParseState pushes a new parse state p onto the parse stack.
+func (s *scanner) pushParseState(p int) {
+	s.parseState = append(s.parseState, p)
+}
+
+// popParseState pops a parse state (already obtained) off the stack
+// and updates s.step accordingly.
+func (s *scanner) popParseState() {
+	n := len(s.parseState) - 1
+	s.parseState = s.parseState[0:n]
+	s.redo = false
+	if n == 0 {
+		s.step = stateEndTop
+		s.endTop = true
+	} else {
+		s.step = stateEndValue
+	}
+}
+
+func isSpace(c rune) bool {
+	return c == ' ' || c == '\t' || c == '\r' || c == '\n'
+}
+
+// stateBeginValueOrEmpty is the state after reading `[`.
+func stateBeginValueOrEmpty(s *scanner, c int) int {
+	if c <= ' ' && isSpace(rune(c)) {
+		return scanSkipSpace
+	}
+	if c == ']' {
+		return stateEndValue(s, c)
+	}
+	return stateBeginValue(s, c)
+}
+
+// stateBeginValue is the state at the beginning of the input.
+func stateBeginValue(s *scanner, c int) int {
+	if c <= ' ' && isSpace(rune(c)) {
+		return scanSkipSpace
+	}
+	switch c {
+	case '{':
+		s.step = stateBeginStringOrEmpty
+		s.pushParseState(parseObjectKey)
+		return scanBeginObject
+	case '[':
+		s.step = stateBeginValueOrEmpty
+		s.pushParseState(parseArrayValue)
+		return scanBeginArray
+	case '"':
+		s.step = stateInString
+		return scanBeginLiteral
+	case '-':
+		s.step = stateNeg
+		return scanBeginLiteral
+	case '0': // beginning of 0.123
+		s.step = state0
+		return scanBeginLiteral
+	case 't': // beginning of true
+		s.step = stateT
+		return scanBeginLiteral
+	case 'f': // beginning of false
+		s.step = stateF
+		return scanBeginLiteral
+	case 'n': // beginning of null
+		s.step = stateN
+		return scanBeginLiteral
+	}
+	if '1' <= c && c <= '9' { // beginning of 1234.5
+		s.step = state1
+		return scanBeginLiteral
+	}
+	return s.error(c, "looking for beginning of value")
+}
+
+// stateBeginStringOrEmpty is the state after reading `{`.
+func stateBeginStringOrEmpty(s *scanner, c int) int {
+	if c <= ' ' && isSpace(rune(c)) {
+		return scanSkipSpace
+	}
+	if c == '}' {
+		n := len(s.parseState)
+		s.parseState[n-1] = parseObjectValue
+		return stateEndValue(s, c)
+	}
+	return stateBeginString(s, c)
+}
+
+// stateBeginString is the state after reading `{"key": value,`.
+func stateBeginString(s *scanner, c int) int {
+	if c <= ' ' && isSpace(rune(c)) {
+		return scanSkipSpace
+	}
+	if c == '"' {
+		s.step = stateInString
+		return scanBeginLiteral
+	}
+	return s.error(c, "looking for beginning of object key string")
+}
+
+// stateEndValue is the state after completing a value,
+// such as after reading `{}` or `true` or `["x"`.
+func stateEndValue(s *scanner, c int) int {
+	n := len(s.parseState)
+	if n == 0 {
+		// Completed top-level before the current byte.
+		s.step = stateEndTop
+		s.endTop = true
+		return stateEndTop(s, c)
+	}
+	if c <= ' ' && isSpace(rune(c)) {
+		s.step = stateEndValue
+		return scanSkipSpace
+	}
+	ps := s.parseState[n-1]
+	switch ps {
+	case parseObjectKey:
+		if c == ':' {
+			s.parseState[n-1] = parseObjectValue
+			s.step = stateBeginValue
+			return scanObjectKey
+		}
+		return s.error(c, "after object key")
+	case parseObjectValue:
+		if c == ',' {
+			s.parseState[n-1] = parseObjectKey
+			s.step = stateBeginString
+			return scanObjectValue
+		}
+		if c == '}' {
+			s.popParseState()
+			return scanEndObject
+		}
+		return s.error(c, "after object key:value pair")
+	case parseArrayValue:
+		if c == ',' {
+			s.step = stateBeginValue
+			return scanArrayValue
+		}
+		if c == ']' {
+			s.popParseState()
+			return scanEndArray
+		}
+		return s.error(c, "after array element")
+	}
+	return s.error(c, "")
+}
+
+// stateEndTop is the state after finishing the top-level value,
+// such as after reading `{}` or `[1,2,3]`.
+// Only space characters should be seen now.
+func stateEndTop(s *scanner, c int) int {
+	if c != ' ' && c != '\t' && c != '\r' && c != '\n' {
+		// Complain about non-space byte on next call.
+		s.error(c, "after top-level value")
+	}
+	return scanEnd
+}
+
+// stateInString is the state after reading `"`.
+func stateInString(s *scanner, c int) int {
+	if c == '"' {
+		s.step = stateEndValue
+		return scanContinue
+	}
+	if c == '\\' {
+		s.step = stateInStringEsc
+		return scanContinue
+	}
+	if c < 0x20 {
+		return s.error(c, "in string literal")
+	}
+	return scanContinue
+}
+
+// stateInStringEsc is the state after reading `"\` during a quoted string.
+func stateInStringEsc(s *scanner, c int) int {
+	switch c {
+	case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
+		s.step = stateInString
+		return scanContinue
+	}
+	if c == 'u' {
+		s.step = stateInStringEscU
+		return scanContinue
+	}
+	return s.error(c, "in string escape code")
+}
+
+// stateInStringEscU is the state after reading `"\u` during a quoted string.
+func stateInStringEscU(s *scanner, c int) int {
+	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+		s.step = stateInStringEscU1
+		return scanContinue
+	}
+	// numbers
+	return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateInStringEscU1 is the state after reading `"\u1` during a quoted string.
+func stateInStringEscU1(s *scanner, c int) int {
+	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+		s.step = stateInStringEscU12
+		return scanContinue
+	}
+	// numbers
+	return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateInStringEscU12 is the state after reading `"\u12` during a quoted string.
+func stateInStringEscU12(s *scanner, c int) int {
+	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+		s.step = stateInStringEscU123
+		return scanContinue
+	}
+	// numbers
+	return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateInStringEscU123 is the state after reading `"\u123` during a quoted string.
+func stateInStringEscU123(s *scanner, c int) int {
+	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+		s.step = stateInString
+		return scanContinue
+	}
+	// numbers
+	return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateNeg is the state after reading `-` during a number.
+func stateNeg(s *scanner, c int) int {
+	if c == '0' {
+		s.step = state0
+		return scanContinue
+	}
+	if '1' <= c && c <= '9' {
+		s.step = state1
+		return scanContinue
+	}
+	return s.error(c, "in numeric literal")
+}
+
+// state1 is the state after reading a non-zero integer during a number,
+// such as after reading `1` or `100` but not `0`.
+func state1(s *scanner, c int) int {
+	if '0' <= c && c <= '9' {
+		s.step = state1
+		return scanContinue
+	}
+	return state0(s, c)
+}
+
+// state0 is the state after reading `0` during a number.
+func state0(s *scanner, c int) int {
+	if c == '.' {
+		s.step = stateDot
+		return scanContinue
+	}
+	if c == 'e' || c == 'E' {
+		s.step = stateE
+		return scanContinue
+	}
+	return stateEndValue(s, c)
+}
+
+// stateDot is the state after reading the integer and decimal point in a number,
+// such as after reading `1.`.
+func stateDot(s *scanner, c int) int {
+	if '0' <= c && c <= '9' {
+		s.step = stateDot0
+		return scanContinue
+	}
+	return s.error(c, "after decimal point in numeric literal")
+}
+
+// stateDot0 is the state after reading the integer, decimal point, and subsequent
+// digits of a number, such as after reading `3.14`.
+func stateDot0(s *scanner, c int) int {
+	if '0' <= c && c <= '9' {
+		s.step = stateDot0
+		return scanContinue
+	}
+	if c == 'e' || c == 'E' {
+		s.step = stateE
+		return scanContinue
+	}
+	return stateEndValue(s, c)
+}
+
+// stateE is the state after reading the mantissa and e in a number,
+// such as after reading `314e` or `0.314e`.
+func stateE(s *scanner, c int) int {
+	if c == '+' {
+		s.step = stateESign
+		return scanContinue
+	}
+	if c == '-' {
+		s.step = stateESign
+		return scanContinue
+	}
+	return stateESign(s, c)
+}
+
+// stateESign is the state after reading the mantissa, e, and sign in a number,
+// such as after reading `314e-` or `0.314e+`.
+func stateESign(s *scanner, c int) int {
+	if '0' <= c && c <= '9' {
+		s.step = stateE0
+		return scanContinue
+	}
+	return s.error(c, "in exponent of numeric literal")
+}
+
+// stateE0 is the state after reading the mantissa, e, optional sign,
+// and at least one digit of the exponent in a number,
+// such as after reading `314e-2` or `0.314e+1` or `3.14e0`.
+func stateE0(s *scanner, c int) int {
+	if '0' <= c && c <= '9' {
+		s.step = stateE0
+		return scanContinue
+	}
+	return stateEndValue(s, c)
+}
+
+// stateT is the state after reading `t`.
+func stateT(s *scanner, c int) int {
+	if c == 'r' {
+		s.step = stateTr
+		return scanContinue
+	}
+	return s.error(c, "in literal true (expecting 'r')")
+}
+
+// stateTr is the state after reading `tr`.
+func stateTr(s *scanner, c int) int {
+	if c == 'u' {
+		s.step = stateTru
+		return scanContinue
+	}
+	return s.error(c, "in literal true (expecting 'u')")
+}
+
+// stateTru is the state after reading `tru`.
+func stateTru(s *scanner, c int) int {
+	if c == 'e' {
+		s.step = stateEndValue
+		return scanContinue
+	}
+	return s.error(c, "in literal true (expecting 'e')")
+}
+
+// stateF is the state after reading `f`.
+func stateF(s *scanner, c int) int {
+	if c == 'a' {
+		s.step = stateFa
+		return scanContinue
+	}
+	return s.error(c, "in literal false (expecting 'a')")
+}
+
+// stateFa is the state after reading `fa`.
+func stateFa(s *scanner, c int) int {
+	if c == 'l' {
+		s.step = stateFal
+		return scanContinue
+	}
+	return s.error(c, "in literal false (expecting 'l')")
+}
+
+// stateFal is the state after reading `fal`.
+func stateFal(s *scanner, c int) int {
+	if c == 's' {
+		s.step = stateFals
+		return scanContinue
+	}
+	return s.error(c, "in literal false (expecting 's')")
+}
+
+// stateFals is the state after reading `fals`.
+func stateFals(s *scanner, c int) int {
+	if c == 'e' {
+		s.step = stateEndValue
+		return scanContinue
+	}
+	return s.error(c, "in literal false (expecting 'e')")
+}
+
+// stateN is the state after reading `n`.
+func stateN(s *scanner, c int) int {
+	if c == 'u' {
+		s.step = stateNu
+		return scanContinue
+	}
+	return s.error(c, "in literal null (expecting 'u')")
+}
+
+// stateNu is the state after reading `nu`.
+func stateNu(s *scanner, c int) int {
+	if c == 'l' {
+		s.step = stateNul
+		return scanContinue
+	}
+	return s.error(c, "in literal null (expecting 'l')")
+}
+
+// stateNul is the state after reading `nul`.
+func stateNul(s *scanner, c int) int {
+	if c == 'l' {
+		s.step = stateEndValue
+		return scanContinue
+	}
+	return s.error(c, "in literal null (expecting 'l')")
+}
+
+// stateError is the state after reaching a syntax error,
+// such as after reading `[1}` or `5.1.2`.
+func stateError(s *scanner, c int) int {
+	return scanError
+}
+
+// error records an error and switches to the error state.
+func (s *scanner) error(c int, context string) int {
+	s.step = stateError
+	s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
+	return scanError
+}
+
+// quoteChar formats c as a quoted character literal
+func quoteChar(c int) string {
+	// special cases - different from quoted strings
+	if c == '\'' {
+		return `'\''`
+	}
+	if c == '"' {
+		return `'"'`
+	}
+
+	// use quoted string with different quotation marks
+	s := strconv.Quote(string(c))
+	return "'" + s[1:len(s)-1] + "'"
+}
+
+// undo causes the scanner to return scanCode from the next state transition.
+// This gives callers a simple 1-byte undo mechanism.
+func (s *scanner) undo(scanCode int) {
+	if s.redo {
+		panic("json: invalid use of scanner")
+	}
+	s.redoCode = scanCode
+	s.redoState = s.step
+	s.step = stateRedo
+	s.redo = true
+}
+
+// stateRedo helps implement the scanner's 1-byte undo.
+func stateRedo(s *scanner, c int) int {
+	s.redo = false
+	s.step = s.redoState
+	return s.redoCode
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/scanner_test.go b/third_party/gofrontend/libgo/go/encoding/json/scanner_test.go
new file mode 100644
index 0000000..7880342
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/scanner_test.go
@@ -0,0 +1,315 @@
+// Copyright 2010 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 json
+
+import (
+	"bytes"
+	"math"
+	"math/rand"
+	"reflect"
+	"testing"
+)
+
+// Tests of simple examples.
+
+type example struct {
+	compact string
+	indent  string
+}
+
+var examples = []example{
+	{`1`, `1`},
+	{`{}`, `{}`},
+	{`[]`, `[]`},
+	{`{"":2}`, "{\n\t\"\": 2\n}"},
+	{`[3]`, "[\n\t3\n]"},
+	{`[1,2,3]`, "[\n\t1,\n\t2,\n\t3\n]"},
+	{`{"x":1}`, "{\n\t\"x\": 1\n}"},
+	{ex1, ex1i},
+}
+
+var ex1 = `[true,false,null,"x",1,1.5,0,-5e+2]`
+
+var ex1i = `[
+	true,
+	false,
+	null,
+	"x",
+	1,
+	1.5,
+	0,
+	-5e+2
+]`
+
+func TestCompact(t *testing.T) {
+	var buf bytes.Buffer
+	for _, tt := range examples {
+		buf.Reset()
+		if err := Compact(&buf, []byte(tt.compact)); err != nil {
+			t.Errorf("Compact(%#q): %v", tt.compact, err)
+		} else if s := buf.String(); s != tt.compact {
+			t.Errorf("Compact(%#q) = %#q, want original", tt.compact, s)
+		}
+
+		buf.Reset()
+		if err := Compact(&buf, []byte(tt.indent)); err != nil {
+			t.Errorf("Compact(%#q): %v", tt.indent, err)
+			continue
+		} else if s := buf.String(); s != tt.compact {
+			t.Errorf("Compact(%#q) = %#q, want %#q", tt.indent, s, tt.compact)
+		}
+	}
+}
+
+func TestCompactSeparators(t *testing.T) {
+	// U+2028 and U+2029 should be escaped inside strings.
+	// They should not appear outside strings.
+	tests := []struct {
+		in, compact string
+	}{
+		{"{\"\u2028\": 1}", `{"\u2028":1}`},
+		{"{\"\u2029\" :2}", `{"\u2029":2}`},
+	}
+	for _, tt := range tests {
+		var buf bytes.Buffer
+		if err := Compact(&buf, []byte(tt.in)); err != nil {
+			t.Errorf("Compact(%q): %v", tt.in, err)
+		} else if s := buf.String(); s != tt.compact {
+			t.Errorf("Compact(%q) = %q, want %q", tt.in, s, tt.compact)
+		}
+	}
+}
+
+func TestIndent(t *testing.T) {
+	var buf bytes.Buffer
+	for _, tt := range examples {
+		buf.Reset()
+		if err := Indent(&buf, []byte(tt.indent), "", "\t"); err != nil {
+			t.Errorf("Indent(%#q): %v", tt.indent, err)
+		} else if s := buf.String(); s != tt.indent {
+			t.Errorf("Indent(%#q) = %#q, want original", tt.indent, s)
+		}
+
+		buf.Reset()
+		if err := Indent(&buf, []byte(tt.compact), "", "\t"); err != nil {
+			t.Errorf("Indent(%#q): %v", tt.compact, err)
+			continue
+		} else if s := buf.String(); s != tt.indent {
+			t.Errorf("Indent(%#q) = %#q, want %#q", tt.compact, s, tt.indent)
+		}
+	}
+}
+
+// Tests of a large random structure.
+
+func TestCompactBig(t *testing.T) {
+	initBig()
+	var buf bytes.Buffer
+	if err := Compact(&buf, jsonBig); err != nil {
+		t.Fatalf("Compact: %v", err)
+	}
+	b := buf.Bytes()
+	if !bytes.Equal(b, jsonBig) {
+		t.Error("Compact(jsonBig) != jsonBig")
+		diff(t, b, jsonBig)
+		return
+	}
+}
+
+func TestIndentBig(t *testing.T) {
+	initBig()
+	var buf bytes.Buffer
+	if err := Indent(&buf, jsonBig, "", "\t"); err != nil {
+		t.Fatalf("Indent1: %v", err)
+	}
+	b := buf.Bytes()
+	if len(b) == len(jsonBig) {
+		// jsonBig is compact (no unnecessary spaces);
+		// indenting should make it bigger
+		t.Fatalf("Indent(jsonBig) did not get bigger")
+	}
+
+	// should be idempotent
+	var buf1 bytes.Buffer
+	if err := Indent(&buf1, b, "", "\t"); err != nil {
+		t.Fatalf("Indent2: %v", err)
+	}
+	b1 := buf1.Bytes()
+	if !bytes.Equal(b1, b) {
+		t.Error("Indent(Indent(jsonBig)) != Indent(jsonBig)")
+		diff(t, b1, b)
+		return
+	}
+
+	// should get back to original
+	buf1.Reset()
+	if err := Compact(&buf1, b); err != nil {
+		t.Fatalf("Compact: %v", err)
+	}
+	b1 = buf1.Bytes()
+	if !bytes.Equal(b1, jsonBig) {
+		t.Error("Compact(Indent(jsonBig)) != jsonBig")
+		diff(t, b1, jsonBig)
+		return
+	}
+}
+
+type indentErrorTest struct {
+	in  string
+	err error
+}
+
+var indentErrorTests = []indentErrorTest{
+	{`{"X": "foo", "Y"}`, &SyntaxError{"invalid character '}' after object key", 17}},
+	{`{"X": "foo" "Y": "bar"}`, &SyntaxError{"invalid character '\"' after object key:value pair", 13}},
+}
+
+func TestIndentErrors(t *testing.T) {
+	for i, tt := range indentErrorTests {
+		slice := make([]uint8, 0)
+		buf := bytes.NewBuffer(slice)
+		if err := Indent(buf, []uint8(tt.in), "", ""); err != nil {
+			if !reflect.DeepEqual(err, tt.err) {
+				t.Errorf("#%d: Indent: %#v", i, err)
+				continue
+			}
+		}
+	}
+}
+
+func TestNextValueBig(t *testing.T) {
+	initBig()
+	var scan scanner
+	item, rest, err := nextValue(jsonBig, &scan)
+	if err != nil {
+		t.Fatalf("nextValue: %s", err)
+	}
+	if len(item) != len(jsonBig) || &item[0] != &jsonBig[0] {
+		t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
+	}
+	if len(rest) != 0 {
+		t.Errorf("invalid rest: %d", len(rest))
+	}
+
+	item, rest, err = nextValue(append(jsonBig, "HELLO WORLD"...), &scan)
+	if err != nil {
+		t.Fatalf("nextValue extra: %s", err)
+	}
+	if len(item) != len(jsonBig) {
+		t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
+	}
+	if string(rest) != "HELLO WORLD" {
+		t.Errorf("invalid rest: %d", len(rest))
+	}
+}
+
+var benchScan scanner
+
+func BenchmarkSkipValue(b *testing.B) {
+	initBig()
+	for i := 0; i < b.N; i++ {
+		nextValue(jsonBig, &benchScan)
+	}
+	b.SetBytes(int64(len(jsonBig)))
+}
+
+func diff(t *testing.T, a, b []byte) {
+	for i := 0; ; i++ {
+		if i >= len(a) || i >= len(b) || a[i] != b[i] {
+			j := i - 10
+			if j < 0 {
+				j = 0
+			}
+			t.Errorf("diverge at %d: «%s» vs «%s»", i, trim(a[j:]), trim(b[j:]))
+			return
+		}
+	}
+}
+
+func trim(b []byte) []byte {
+	if len(b) > 20 {
+		return b[0:20]
+	}
+	return b
+}
+
+// Generate a random JSON object.
+
+var jsonBig []byte
+
+func initBig() {
+	n := 10000
+	if testing.Short() {
+		n = 100
+	}
+	b, err := Marshal(genValue(n))
+	if err != nil {
+		panic(err)
+	}
+	jsonBig = b
+}
+
+func genValue(n int) interface{} {
+	if n > 1 {
+		switch rand.Intn(2) {
+		case 0:
+			return genArray(n)
+		case 1:
+			return genMap(n)
+		}
+	}
+	switch rand.Intn(3) {
+	case 0:
+		return rand.Intn(2) == 0
+	case 1:
+		return rand.NormFloat64()
+	case 2:
+		return genString(30)
+	}
+	panic("unreachable")
+}
+
+func genString(stddev float64) string {
+	n := int(math.Abs(rand.NormFloat64()*stddev + stddev/2))
+	c := make([]rune, n)
+	for i := range c {
+		f := math.Abs(rand.NormFloat64()*64 + 32)
+		if f > 0x10ffff {
+			f = 0x10ffff
+		}
+		c[i] = rune(f)
+	}
+	return string(c)
+}
+
+func genArray(n int) []interface{} {
+	f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
+	if f > n {
+		f = n
+	}
+	if f < 1 {
+		f = 1
+	}
+	x := make([]interface{}, f)
+	for i := range x {
+		x[i] = genValue(((i+1)*n)/f - (i*n)/f)
+	}
+	return x
+}
+
+func genMap(n int) map[string]interface{} {
+	f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
+	if f > n {
+		f = n
+	}
+	if n > 0 && f == 0 {
+		f = 1
+	}
+	x := make(map[string]interface{})
+	for i := 0; i < f; i++ {
+		x[genString(10)] = genValue(((i+1)*n)/f - (i*n)/f)
+	}
+	return x
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/stream.go b/third_party/gofrontend/libgo/go/encoding/json/stream.go
new file mode 100644
index 0000000..1cb289f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/stream.go
@@ -0,0 +1,201 @@
+// Copyright 2010 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 json
+
+import (
+	"bytes"
+	"errors"
+	"io"
+)
+
+// A Decoder reads and decodes JSON objects from an input stream.
+type Decoder struct {
+	r    io.Reader
+	buf  []byte
+	d    decodeState
+	scan scanner
+	err  error
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may
+// read data from r beyond the JSON values requested.
+func NewDecoder(r io.Reader) *Decoder {
+	return &Decoder{r: r}
+}
+
+// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
+// Number instead of as a float64.
+func (dec *Decoder) UseNumber() { dec.d.useNumber = true }
+
+// Decode reads the next JSON-encoded value from its
+// input and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about
+// the conversion of JSON into a Go value.
+func (dec *Decoder) Decode(v interface{}) error {
+	if dec.err != nil {
+		return dec.err
+	}
+
+	n, err := dec.readValue()
+	if err != nil {
+		return err
+	}
+
+	// Don't save err from unmarshal into dec.err:
+	// the connection is still usable since we read a complete JSON
+	// object from it before the error happened.
+	dec.d.init(dec.buf[0:n])
+	err = dec.d.unmarshal(v)
+
+	// Slide rest of data down.
+	rest := copy(dec.buf, dec.buf[n:])
+	dec.buf = dec.buf[0:rest]
+
+	return err
+}
+
+// Buffered returns a reader of the data remaining in the Decoder's
+// buffer. The reader is valid until the next call to Decode.
+func (dec *Decoder) Buffered() io.Reader {
+	return bytes.NewReader(dec.buf)
+}
+
+// readValue reads a JSON value into dec.buf.
+// It returns the length of the encoding.
+func (dec *Decoder) readValue() (int, error) {
+	dec.scan.reset()
+
+	scanp := 0
+	var err error
+Input:
+	for {
+		// Look in the buffer for a new value.
+		for i, c := range dec.buf[scanp:] {
+			dec.scan.bytes++
+			v := dec.scan.step(&dec.scan, int(c))
+			if v == scanEnd {
+				scanp += i
+				break Input
+			}
+			// scanEnd is delayed one byte.
+			// We might block trying to get that byte from src,
+			// so instead invent a space byte.
+			if (v == scanEndObject || v == scanEndArray) && dec.scan.step(&dec.scan, ' ') == scanEnd {
+				scanp += i + 1
+				break Input
+			}
+			if v == scanError {
+				dec.err = dec.scan.err
+				return 0, dec.scan.err
+			}
+		}
+		scanp = len(dec.buf)
+
+		// Did the last read have an error?
+		// Delayed until now to allow buffer scan.
+		if err != nil {
+			if err == io.EOF {
+				if dec.scan.step(&dec.scan, ' ') == scanEnd {
+					break Input
+				}
+				if nonSpace(dec.buf) {
+					err = io.ErrUnexpectedEOF
+				}
+			}
+			dec.err = err
+			return 0, err
+		}
+
+		// Make room to read more into the buffer.
+		const minRead = 512
+		if cap(dec.buf)-len(dec.buf) < minRead {
+			newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
+			copy(newBuf, dec.buf)
+			dec.buf = newBuf
+		}
+
+		// Read.  Delay error for next iteration (after scan).
+		var n int
+		n, err = dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
+		dec.buf = dec.buf[0 : len(dec.buf)+n]
+	}
+	return scanp, nil
+}
+
+func nonSpace(b []byte) bool {
+	for _, c := range b {
+		if !isSpace(rune(c)) {
+			return true
+		}
+	}
+	return false
+}
+
+// An Encoder writes JSON objects to an output stream.
+type Encoder struct {
+	w   io.Writer
+	e   encodeState
+	err error
+}
+
+// NewEncoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+	return &Encoder{w: w}
+}
+
+// Encode writes the JSON encoding of v to the stream,
+// followed by a newline character.
+//
+// See the documentation for Marshal for details about the
+// conversion of Go values to JSON.
+func (enc *Encoder) Encode(v interface{}) error {
+	if enc.err != nil {
+		return enc.err
+	}
+	e := newEncodeState()
+	err := e.marshal(v)
+	if err != nil {
+		return err
+	}
+
+	// Terminate each value with a newline.
+	// This makes the output look a little nicer
+	// when debugging, and some kind of space
+	// is required if the encoded value was a number,
+	// so that the reader knows there aren't more
+	// digits coming.
+	e.WriteByte('\n')
+
+	if _, err = enc.w.Write(e.Bytes()); err != nil {
+		enc.err = err
+	}
+	encodeStatePool.Put(e)
+	return err
+}
+
+// RawMessage is a raw encoded JSON object.
+// It implements Marshaler and Unmarshaler and can
+// be used to delay JSON decoding or precompute a JSON encoding.
+type RawMessage []byte
+
+// MarshalJSON returns *m as the JSON encoding of m.
+func (m *RawMessage) MarshalJSON() ([]byte, error) {
+	return *m, nil
+}
+
+// UnmarshalJSON sets *m to a copy of data.
+func (m *RawMessage) UnmarshalJSON(data []byte) error {
+	if m == nil {
+		return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
+	}
+	*m = append((*m)[0:0], data...)
+	return nil
+}
+
+var _ Marshaler = (*RawMessage)(nil)
+var _ Unmarshaler = (*RawMessage)(nil)
diff --git a/third_party/gofrontend/libgo/go/encoding/json/stream_test.go b/third_party/gofrontend/libgo/go/encoding/json/stream_test.go
new file mode 100644
index 0000000..b562e87
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/stream_test.go
@@ -0,0 +1,206 @@
+// Copyright 2010 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 json
+
+import (
+	"bytes"
+	"io/ioutil"
+	"net"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+// Test values for the stream test.
+// One of each JSON kind.
+var streamTest = []interface{}{
+	0.1,
+	"hello",
+	nil,
+	true,
+	false,
+	[]interface{}{"a", "b", "c"},
+	map[string]interface{}{"K": "Kelvin", "ß": "long s"},
+	3.14, // another value to make sure something can follow map
+}
+
+var streamEncoded = `0.1
+"hello"
+null
+true
+false
+["a","b","c"]
+{"ß":"long s","K":"Kelvin"}
+3.14
+`
+
+func TestEncoder(t *testing.T) {
+	for i := 0; i <= len(streamTest); i++ {
+		var buf bytes.Buffer
+		enc := NewEncoder(&buf)
+		for j, v := range streamTest[0:i] {
+			if err := enc.Encode(v); err != nil {
+				t.Fatalf("encode #%d: %v", j, err)
+			}
+		}
+		if have, want := buf.String(), nlines(streamEncoded, i); have != want {
+			t.Errorf("encoding %d items: mismatch", i)
+			diff(t, []byte(have), []byte(want))
+			break
+		}
+	}
+}
+
+func TestDecoder(t *testing.T) {
+	for i := 0; i <= len(streamTest); i++ {
+		// Use stream without newlines as input,
+		// just to stress the decoder even more.
+		// Our test input does not include back-to-back numbers.
+		// Otherwise stripping the newlines would
+		// merge two adjacent JSON values.
+		var buf bytes.Buffer
+		for _, c := range nlines(streamEncoded, i) {
+			if c != '\n' {
+				buf.WriteRune(c)
+			}
+		}
+		out := make([]interface{}, i)
+		dec := NewDecoder(&buf)
+		for j := range out {
+			if err := dec.Decode(&out[j]); err != nil {
+				t.Fatalf("decode #%d/%d: %v", j, i, err)
+			}
+		}
+		if !reflect.DeepEqual(out, streamTest[0:i]) {
+			t.Errorf("decoding %d items: mismatch", i)
+			for j := range out {
+				if !reflect.DeepEqual(out[j], streamTest[j]) {
+					t.Errorf("#%d: have %v want %v", j, out[j], streamTest[j])
+				}
+			}
+			break
+		}
+	}
+}
+
+func TestDecoderBuffered(t *testing.T) {
+	r := strings.NewReader(`{"Name": "Gopher"} extra `)
+	var m struct {
+		Name string
+	}
+	d := NewDecoder(r)
+	err := d.Decode(&m)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if m.Name != "Gopher" {
+		t.Errorf("Name = %q; want Gopher", m.Name)
+	}
+	rest, err := ioutil.ReadAll(d.Buffered())
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, w := string(rest), " extra "; g != w {
+		t.Errorf("Remaining = %q; want %q", g, w)
+	}
+}
+
+func nlines(s string, n int) string {
+	if n <= 0 {
+		return ""
+	}
+	for i, c := range s {
+		if c == '\n' {
+			if n--; n == 0 {
+				return s[0 : i+1]
+			}
+		}
+	}
+	return s
+}
+
+func TestRawMessage(t *testing.T) {
+	// TODO(rsc): Should not need the * in *RawMessage
+	var data struct {
+		X  float64
+		Id *RawMessage
+		Y  float32
+	}
+	const raw = `["\u0056",null]`
+	const msg = `{"X":0.1,"Id":["\u0056",null],"Y":0.2}`
+	err := Unmarshal([]byte(msg), &data)
+	if err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	if string([]byte(*data.Id)) != raw {
+		t.Fatalf("Raw mismatch: have %#q want %#q", []byte(*data.Id), raw)
+	}
+	b, err := Marshal(&data)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	if string(b) != msg {
+		t.Fatalf("Marshal: have %#q want %#q", b, msg)
+	}
+}
+
+func TestNullRawMessage(t *testing.T) {
+	// TODO(rsc): Should not need the * in *RawMessage
+	var data struct {
+		X  float64
+		Id *RawMessage
+		Y  float32
+	}
+	data.Id = new(RawMessage)
+	const msg = `{"X":0.1,"Id":null,"Y":0.2}`
+	err := Unmarshal([]byte(msg), &data)
+	if err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	if data.Id != nil {
+		t.Fatalf("Raw mismatch: have non-nil, want nil")
+	}
+	b, err := Marshal(&data)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	if string(b) != msg {
+		t.Fatalf("Marshal: have %#q want %#q", b, msg)
+	}
+}
+
+var blockingTests = []string{
+	`{"x": 1}`,
+	`[1, 2, 3]`,
+}
+
+func TestBlocking(t *testing.T) {
+	for _, enc := range blockingTests {
+		r, w := net.Pipe()
+		go w.Write([]byte(enc))
+		var val interface{}
+
+		// If Decode reads beyond what w.Write writes above,
+		// it will block, and the test will deadlock.
+		if err := NewDecoder(r).Decode(&val); err != nil {
+			t.Errorf("decoding %s: %v", enc, err)
+		}
+		r.Close()
+		w.Close()
+	}
+}
+
+func BenchmarkEncoderEncode(b *testing.B) {
+	b.ReportAllocs()
+	type T struct {
+		X, Y string
+	}
+	v := &T{"foo", "bar"}
+	for i := 0; i < b.N; i++ {
+		if err := NewEncoder(ioutil.Discard).Encode(v); err != nil {
+			b.Fatal(err)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/tagkey_test.go b/third_party/gofrontend/libgo/go/encoding/json/tagkey_test.go
new file mode 100644
index 0000000..23e71c7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/tagkey_test.go
@@ -0,0 +1,115 @@
+// 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.
+
+package json
+
+import (
+	"testing"
+)
+
+type basicLatin2xTag struct {
+	V string `json:"$%-/"`
+}
+
+type basicLatin3xTag struct {
+	V string `json:"0123456789"`
+}
+
+type basicLatin4xTag struct {
+	V string `json:"ABCDEFGHIJKLMO"`
+}
+
+type basicLatin5xTag struct {
+	V string `json:"PQRSTUVWXYZ_"`
+}
+
+type basicLatin6xTag struct {
+	V string `json:"abcdefghijklmno"`
+}
+
+type basicLatin7xTag struct {
+	V string `json:"pqrstuvwxyz"`
+}
+
+type miscPlaneTag struct {
+	V string `json:"色は匂へど"`
+}
+
+type percentSlashTag struct {
+	V string `json:"text/html%"` // http://golang.org/issue/2718
+}
+
+type punctuationTag struct {
+	V string `json:"!#$%&()*+-./:<=>?@[]^_{|}~"` // http://golang.org/issue/3546
+}
+
+type emptyTag struct {
+	W string
+}
+
+type misnamedTag struct {
+	X string `jsom:"Misnamed"`
+}
+
+type badFormatTag struct {
+	Y string `:"BadFormat"`
+}
+
+type badCodeTag struct {
+	Z string `json:" !\"#&'()*+,."`
+}
+
+type spaceTag struct {
+	Q string `json:"With space"`
+}
+
+type unicodeTag struct {
+	W string `json:"Ελλάδα"`
+}
+
+var structTagObjectKeyTests = []struct {
+	raw   interface{}
+	value string
+	key   string
+}{
+	{basicLatin2xTag{"2x"}, "2x", "$%-/"},
+	{basicLatin3xTag{"3x"}, "3x", "0123456789"},
+	{basicLatin4xTag{"4x"}, "4x", "ABCDEFGHIJKLMO"},
+	{basicLatin5xTag{"5x"}, "5x", "PQRSTUVWXYZ_"},
+	{basicLatin6xTag{"6x"}, "6x", "abcdefghijklmno"},
+	{basicLatin7xTag{"7x"}, "7x", "pqrstuvwxyz"},
+	{miscPlaneTag{"いろはにほへと"}, "いろはにほへと", "色は匂へど"},
+	{emptyTag{"Pour Moi"}, "Pour Moi", "W"},
+	{misnamedTag{"Animal Kingdom"}, "Animal Kingdom", "X"},
+	{badFormatTag{"Orfevre"}, "Orfevre", "Y"},
+	{badCodeTag{"Reliable Man"}, "Reliable Man", "Z"},
+	{percentSlashTag{"brut"}, "brut", "text/html%"},
+	{punctuationTag{"Union Rags"}, "Union Rags", "!#$%&()*+-./:<=>?@[]^_{|}~"},
+	{spaceTag{"Perreddu"}, "Perreddu", "With space"},
+	{unicodeTag{"Loukanikos"}, "Loukanikos", "Ελλάδα"},
+}
+
+func TestStructTagObjectKey(t *testing.T) {
+	for _, tt := range structTagObjectKeyTests {
+		b, err := Marshal(tt.raw)
+		if err != nil {
+			t.Fatalf("Marshal(%#q) failed: %v", tt.raw, err)
+		}
+		var f interface{}
+		err = Unmarshal(b, &f)
+		if err != nil {
+			t.Fatalf("Unmarshal(%#q) failed: %v", b, err)
+		}
+		for i, v := range f.(map[string]interface{}) {
+			switch i {
+			case tt.key:
+				if s, ok := v.(string); !ok || s != tt.value {
+					t.Fatalf("Unexpected value: %#q, want %v", s, tt.value)
+				}
+			default:
+				t.Fatalf("Unexpected key: %#q, from %#q", i, b)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/tags.go b/third_party/gofrontend/libgo/go/encoding/json/tags.go
new file mode 100644
index 0000000..c38fd51
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/tags.go
@@ -0,0 +1,44 @@
+// 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.
+
+package json
+
+import (
+	"strings"
+)
+
+// tagOptions is the string following a comma in a struct field's "json"
+// tag, or the empty string. It does not include the leading comma.
+type tagOptions string
+
+// parseTag splits a struct field's json tag into its name and
+// comma-separated options.
+func parseTag(tag string) (string, tagOptions) {
+	if idx := strings.Index(tag, ","); idx != -1 {
+		return tag[:idx], tagOptions(tag[idx+1:])
+	}
+	return tag, tagOptions("")
+}
+
+// Contains reports whether a comma-separated list of options
+// contains a particular substr flag. substr must be surrounded by a
+// string boundary or commas.
+func (o tagOptions) Contains(optionName string) bool {
+	if len(o) == 0 {
+		return false
+	}
+	s := string(o)
+	for s != "" {
+		var next string
+		i := strings.Index(s, ",")
+		if i >= 0 {
+			s, next = s[:i], s[i+1:]
+		}
+		if s == optionName {
+			return true
+		}
+		s = next
+	}
+	return false
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/tags_test.go b/third_party/gofrontend/libgo/go/encoding/json/tags_test.go
new file mode 100644
index 0000000..91fb188
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/tags_test.go
@@ -0,0 +1,28 @@
+// 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.
+
+package json
+
+import (
+	"testing"
+)
+
+func TestTagParsing(t *testing.T) {
+	name, opts := parseTag("field,foobar,foo")
+	if name != "field" {
+		t.Fatalf("name = %q, want field", name)
+	}
+	for _, tt := range []struct {
+		opt  string
+		want bool
+	}{
+		{"foobar", true},
+		{"foo", true},
+		{"bar", false},
+	} {
+		if opts.Contains(tt.opt) != tt.want {
+			t.Errorf("Contains(%q) = %v", tt.opt, !tt.want)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/json/testdata/code.json.gz b/third_party/gofrontend/libgo/go/encoding/json/testdata/code.json.gz
new file mode 100644
index 0000000..0e2895b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/json/testdata/code.json.gz
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/encoding/pem/pem.go b/third_party/gofrontend/libgo/go/encoding/pem/pem.go
new file mode 100644
index 0000000..8ff7ee8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/pem/pem.go
@@ -0,0 +1,277 @@
+// 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 pem implements the PEM data encoding, which originated in Privacy
+// Enhanced Mail. The most common use of PEM encoding today is in TLS keys and
+// certificates. See RFC 1421.
+package pem
+
+import (
+	"bytes"
+	"encoding/base64"
+	"io"
+	"sort"
+)
+
+// A Block represents a PEM encoded structure.
+//
+// The encoded form is:
+//    -----BEGIN Type-----
+//    Headers
+//    base64-encoded Bytes
+//    -----END Type-----
+// where Headers is a possibly empty sequence of Key: Value lines.
+type Block struct {
+	Type    string            // The type, taken from the preamble (i.e. "RSA PRIVATE KEY").
+	Headers map[string]string // Optional headers.
+	Bytes   []byte            // The decoded bytes of the contents. Typically a DER encoded ASN.1 structure.
+}
+
+// getLine results the first \r\n or \n delineated line from the given byte
+// array. The line does not include trailing whitespace or the trailing new
+// line bytes. The remainder of the byte array (also not including the new line
+// bytes) is also returned and this will always be smaller than the original
+// argument.
+func getLine(data []byte) (line, rest []byte) {
+	i := bytes.Index(data, []byte{'\n'})
+	var j int
+	if i < 0 {
+		i = len(data)
+		j = i
+	} else {
+		j = i + 1
+		if i > 0 && data[i-1] == '\r' {
+			i--
+		}
+	}
+	return bytes.TrimRight(data[0:i], " \t"), data[j:]
+}
+
+// removeWhitespace returns a copy of its input with all spaces, tab and
+// newline characters removed.
+func removeWhitespace(data []byte) []byte {
+	result := make([]byte, len(data))
+	n := 0
+
+	for _, b := range data {
+		if b == ' ' || b == '\t' || b == '\r' || b == '\n' {
+			continue
+		}
+		result[n] = b
+		n++
+	}
+
+	return result[0:n]
+}
+
+var pemStart = []byte("\n-----BEGIN ")
+var pemEnd = []byte("\n-----END ")
+var pemEndOfLine = []byte("-----")
+
+// Decode will find the next PEM formatted block (certificate, private key
+// etc) in the input. It returns that block and the remainder of the input. If
+// no PEM data is found, p is nil and the whole of the input is returned in
+// rest.
+func Decode(data []byte) (p *Block, rest []byte) {
+	// pemStart begins with a newline. However, at the very beginning of
+	// the byte array, we'll accept the start string without it.
+	rest = data
+	if bytes.HasPrefix(data, pemStart[1:]) {
+		rest = rest[len(pemStart)-1 : len(data)]
+	} else if i := bytes.Index(data, pemStart); i >= 0 {
+		rest = rest[i+len(pemStart) : len(data)]
+	} else {
+		return nil, data
+	}
+
+	typeLine, rest := getLine(rest)
+	if !bytes.HasSuffix(typeLine, pemEndOfLine) {
+		return decodeError(data, rest)
+	}
+	typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)]
+
+	p = &Block{
+		Headers: make(map[string]string),
+		Type:    string(typeLine),
+	}
+
+	for {
+		// This loop terminates because getLine's second result is
+		// always smaller than its argument.
+		if len(rest) == 0 {
+			return nil, data
+		}
+		line, next := getLine(rest)
+
+		i := bytes.Index(line, []byte{':'})
+		if i == -1 {
+			break
+		}
+
+		// TODO(agl): need to cope with values that spread across lines.
+		key, val := line[0:i], line[i+1:]
+		key = bytes.TrimSpace(key)
+		val = bytes.TrimSpace(val)
+		p.Headers[string(key)] = string(val)
+		rest = next
+	}
+
+	i := bytes.Index(rest, pemEnd)
+	if i < 0 {
+		return decodeError(data, rest)
+	}
+	base64Data := removeWhitespace(rest[0:i])
+
+	p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
+	n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
+	if err != nil {
+		return decodeError(data, rest)
+	}
+	p.Bytes = p.Bytes[0:n]
+
+	_, rest = getLine(rest[i+len(pemEnd):])
+
+	return
+}
+
+func decodeError(data, rest []byte) (*Block, []byte) {
+	// If we get here then we have rejected a likely looking, but
+	// ultimately invalid PEM block. We need to start over from a new
+	// position.  We have consumed the preamble line and will have consumed
+	// any lines which could be header lines. However, a valid preamble
+	// line is not a valid header line, therefore we cannot have consumed
+	// the preamble line for the any subsequent block. Thus, we will always
+	// find any valid block, no matter what bytes precede it.
+	//
+	// For example, if the input is
+	//
+	//    -----BEGIN MALFORMED BLOCK-----
+	//    junk that may look like header lines
+	//   or data lines, but no END line
+	//
+	//    -----BEGIN ACTUAL BLOCK-----
+	//    realdata
+	//    -----END ACTUAL BLOCK-----
+	//
+	// we've failed to parse using the first BEGIN line
+	// and now will try again, using the second BEGIN line.
+	p, rest := Decode(rest)
+	if p == nil {
+		rest = data
+	}
+	return p, rest
+}
+
+const pemLineLength = 64
+
+type lineBreaker struct {
+	line [pemLineLength]byte
+	used int
+	out  io.Writer
+}
+
+func (l *lineBreaker) Write(b []byte) (n int, err error) {
+	if l.used+len(b) < pemLineLength {
+		copy(l.line[l.used:], b)
+		l.used += len(b)
+		return len(b), nil
+	}
+
+	n, err = l.out.Write(l.line[0:l.used])
+	if err != nil {
+		return
+	}
+	excess := pemLineLength - l.used
+	l.used = 0
+
+	n, err = l.out.Write(b[0:excess])
+	if err != nil {
+		return
+	}
+
+	n, err = l.out.Write([]byte{'\n'})
+	if err != nil {
+		return
+	}
+
+	return l.Write(b[excess:])
+}
+
+func (l *lineBreaker) Close() (err error) {
+	if l.used > 0 {
+		_, err = l.out.Write(l.line[0:l.used])
+		if err != nil {
+			return
+		}
+		_, err = l.out.Write([]byte{'\n'})
+	}
+
+	return
+}
+
+func writeHeader(out io.Writer, k, v string) error {
+	_, err := out.Write([]byte(k + ": " + v + "\n"))
+	return err
+}
+
+func Encode(out io.Writer, b *Block) error {
+	if _, err := out.Write(pemStart[1:]); err != nil {
+		return err
+	}
+	if _, err := out.Write([]byte(b.Type + "-----\n")); err != nil {
+		return err
+	}
+
+	if len(b.Headers) > 0 {
+		const procType = "Proc-Type"
+		h := make([]string, 0, len(b.Headers))
+		hasProcType := false
+		for k := range b.Headers {
+			if k == procType {
+				hasProcType = true
+				continue
+			}
+			h = append(h, k)
+		}
+		// The Proc-Type header must be written first.
+		// See RFC 1421, section 4.6.1.1
+		if hasProcType {
+			if err := writeHeader(out, procType, b.Headers[procType]); err != nil {
+				return err
+			}
+		}
+		// For consistency of output, write other headers sorted by key.
+		sort.Strings(h)
+		for _, k := range h {
+			if err := writeHeader(out, k, b.Headers[k]); err != nil {
+				return err
+			}
+		}
+		if _, err := out.Write([]byte{'\n'}); err != nil {
+			return err
+		}
+	}
+
+	var breaker lineBreaker
+	breaker.out = out
+
+	b64 := base64.NewEncoder(base64.StdEncoding, &breaker)
+	if _, err := b64.Write(b.Bytes); err != nil {
+		return err
+	}
+	b64.Close()
+	breaker.Close()
+
+	if _, err := out.Write(pemEnd[1:]); err != nil {
+		return err
+	}
+	_, err := out.Write([]byte(b.Type + "-----\n"))
+	return err
+}
+
+func EncodeToMemory(b *Block) []byte {
+	var buf bytes.Buffer
+	Encode(&buf, b)
+	return buf.Bytes()
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/pem/pem_test.go b/third_party/gofrontend/libgo/go/encoding/pem/pem_test.go
new file mode 100644
index 0000000..ccce42c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/pem/pem_test.go
@@ -0,0 +1,404 @@
+// 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 pem
+
+import (
+	"bytes"
+	"reflect"
+	"testing"
+)
+
+type GetLineTest struct {
+	in, out1, out2 string
+}
+
+var getLineTests = []GetLineTest{
+	{"abc", "abc", ""},
+	{"abc\r", "abc\r", ""},
+	{"abc\n", "abc", ""},
+	{"abc\r\n", "abc", ""},
+	{"abc\nd", "abc", "d"},
+	{"abc\r\nd", "abc", "d"},
+	{"\nabc", "", "abc"},
+	{"\r\nabc", "", "abc"},
+}
+
+func TestGetLine(t *testing.T) {
+	for i, test := range getLineTests {
+		x, y := getLine([]byte(test.in))
+		if string(x) != test.out1 || string(y) != test.out2 {
+			t.Errorf("#%d got:%+v,%+v want:%s,%s", i, x, y, test.out1, test.out2)
+		}
+	}
+}
+
+func TestDecode(t *testing.T) {
+	result, remainder := Decode([]byte(pemData))
+	if !reflect.DeepEqual(result, certificate) {
+		t.Errorf("#0 got:%#v want:%#v", result, certificate)
+	}
+	result, remainder = Decode(remainder)
+	if !reflect.DeepEqual(result, privateKey) {
+		t.Errorf("#1 got:%#v want:%#v", result, privateKey)
+	}
+	result, _ = Decode([]byte(pemPrivateKey2))
+	if !reflect.DeepEqual(result, privateKey2) {
+		t.Errorf("#2 got:%#v want:%#v", result, privateKey2)
+	}
+}
+
+func TestEncode(t *testing.T) {
+	r := EncodeToMemory(privateKey2)
+	if string(r) != pemPrivateKey2 {
+		t.Errorf("got:%s want:%s", r, pemPrivateKey2)
+	}
+}
+
+type lineBreakerTest struct {
+	in, out string
+}
+
+const sixtyFourCharString = "0123456789012345678901234567890123456789012345678901234567890123"
+
+var lineBreakerTests = []lineBreakerTest{
+	{"", ""},
+	{"a", "a\n"},
+	{"ab", "ab\n"},
+	{sixtyFourCharString, sixtyFourCharString + "\n"},
+	{sixtyFourCharString + "X", sixtyFourCharString + "\nX\n"},
+	{sixtyFourCharString + sixtyFourCharString, sixtyFourCharString + "\n" + sixtyFourCharString + "\n"},
+}
+
+func TestLineBreaker(t *testing.T) {
+	for i, test := range lineBreakerTests {
+		buf := new(bytes.Buffer)
+		var breaker lineBreaker
+		breaker.out = buf
+		_, err := breaker.Write([]byte(test.in))
+		if err != nil {
+			t.Errorf("#%d: error from Write: %s", i, err)
+			continue
+		}
+		err = breaker.Close()
+		if err != nil {
+			t.Errorf("#%d: error from Close: %s", i, err)
+			continue
+		}
+
+		if string(buf.Bytes()) != test.out {
+			t.Errorf("#%d: got:%s want:%s", i, string(buf.Bytes()), test.out)
+		}
+	}
+
+	for i, test := range lineBreakerTests {
+		buf := new(bytes.Buffer)
+		var breaker lineBreaker
+		breaker.out = buf
+
+		for i := 0; i < len(test.in); i++ {
+			_, err := breaker.Write([]byte(test.in[i : i+1]))
+			if err != nil {
+				t.Errorf("#%d: error from Write (byte by byte): %s", i, err)
+				continue
+			}
+		}
+		err := breaker.Close()
+		if err != nil {
+			t.Errorf("#%d: error from Close (byte by byte): %s", i, err)
+			continue
+		}
+
+		if string(buf.Bytes()) != test.out {
+			t.Errorf("#%d: (byte by byte) got:%s want:%s", i, string(buf.Bytes()), test.out)
+		}
+	}
+}
+
+var pemData = `verify return:0
+-----BEGIN CERTIFICATE-----
+sdlfkjskldfj
+  -----BEGIN CERTIFICATE-----
+---
+Certificate chain
+ 0 s:/C=AU/ST=Somewhere/L=Someplace/O=Foo Bar/CN=foo.example.com
+   i:/C=ZA/O=CA Inc./CN=CA Inc
+-----BEGIN CERTIFICATE-----
+testing
+-----BEGIN CERTIFICATE-----
+-----BEGIN CERTIFICATE----- 
+MIID6TCCA1ICAQEwDQYJKoZIhvcNAQEFBQAwgYsxCzAJBgNVBAYTAlVTMRMwEQYD
+VQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQK
+EwtHb29nbGUgSW5jLjEMMAoGA1UECxMDRW5nMQwwCgYDVQQDEwNhZ2wxHTAbBgkq 
+hkiG9w0BCQEWDmFnbEBnb29nbGUuY29tMB4XDTA5MDkwOTIyMDU0M1oXDTEwMDkw  
+OTIyMDU0M1owajELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAf  	  
+BgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEjMCEGA1UEAxMaZXVyb3Bh		  
+LnNmby5jb3JwLmdvb2dsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQC6pgYt7/EibBDumASF+S0qvqdL/f+nouJw2T1Qc8GmXF/iiUcrsgzh/Fd8
+pDhz/T96Qg9IyR4ztuc2MXrmPra+zAuSf5bevFReSqvpIt8Duv0HbDbcqs/XKPfB
+uMDe+of7a9GCywvAZ4ZUJcp0thqD9fKTTjUWOBzHY1uNE4RitrhmJCrbBGXbJ249
+bvgmb7jgdInH2PU7PT55hujvOoIsQW2osXBFRur4pF1wmVh4W4lTLD6pjfIMUcML
+ICHEXEN73PDic8KS3EtNYCwoIld+tpIBjE1QOb1KOyuJBNW6Esw9ALZn7stWdYcE
+qAwvv20egN2tEXqj7Q4/1ccyPZc3PQgC3FJ8Be2mtllM+80qf4dAaQ/fWvCtOrQ5
+pnfe9juQvCo8Y0VGlFcrSys/MzSg9LJ/24jZVgzQved/Qupsp89wVidwIzjt+WdS
+fyWfH0/v1aQLvu5cMYuW//C0W2nlYziL5blETntM8My2ybNARy3ICHxCBv2RNtPI
+WQVm+E9/W5rwh2IJR4DHn2LHwUVmT/hHNTdBLl5Uhwr4Wc7JhE7AVqb14pVNz1lr
+5jxsp//ncIwftb7mZQ3DF03Yna+jJhpzx8CQoeLT6aQCHyzmH68MrHHT4MALPyUs
+Pomjn71GNTtDeWAXibjCgdL6iHACCF6Htbl0zGlG0OAK+bdn0QIDAQABMA0GCSqG
+SIb3DQEBBQUAA4GBAOKnQDtqBV24vVqvesL5dnmyFpFPXBn3WdFfwD6DzEb21UVG
+5krmJiu+ViipORJPGMkgoL6BjU21XI95VQbun5P8vvg8Z+FnFsvRFY3e1CCzAVQY
+ZsUkLw2I7zI/dNlWdB8Xp7v+3w9sX5N3J/WuJ1KOO5m26kRlHQo7EzT3974g
+-----END CERTIFICATE-----   
+ 1 s:/C=ZA/O=Ca Inc./CN=CA Inc
+
+-----BEGIN RSA PRIVATE KEY-----   	
+Proc-Type: 4,ENCRYPTED	  
+DEK-Info: DES-EDE3-CBC,80C7C7A09690757A  	
+  	
+eQp5ZkH6CyHBz7BZfUPxyLCCmftsBJ7HlqGb8Ld21cSwnzWZ4/SIlhyrUtsfw7VR
+2TTwA+odo9ex7GdxOTaH8oZFumIRoiEjHsk8U7Bhntp+ekkPP79xunnN7hb7hkhr   
+yGDQZgA7s2cQHQ71v3gwT2BACAft26jCjbM1wgNzBnJ8M0Rzn68YWqaPtdBu8qb/
+zVR5JB1mnqvTSbFsfF5yMc6o2WQ9jJCl6KypnMl+BpL+dlvdjYVK4l9lYsB1Hs3d
++zDBbWxos818zzhS8/y6eIfiSG27cqrbhURbmgiSfDXjncK4m/pLcQ7mmBL6mFOr
+3Pj4jepzgOiFRL6MKE//h62fZvI1ErYr8VunHEykgKNhChDvb1RO6LEfqKBu+Ivw
+TB6fBhW3TCLMnVPYVoYwA+fHNTmZZm8BEonlIMfI+KktjWUg4Oia+NI6vKcPpFox
+hSnlGgCtvfEaq5/H4kHJp95eOpnFsLviw2seHNkz/LxJMRP1X428+DpYW/QD/0JU
+tJSuC/q9FUHL6RI3u/Asrv8pCb4+D7i1jW/AMIdJTtycOGsbPxQA7yHMWujHmeb1
+BTiHcL3s3KrJu1vDVrshvxfnz71KTeNnZH8UbOqT5i7fPGyXtY1XJddcbI/Q6tXf
+wHFsZc20TzSdsVLBtwksUacpbDogcEVMctnNrB8FIrB3vZEv9Q0Z1VeY7nmTpF+6
+a+z2P7acL7j6A6Pr3+q8P9CPiPC7zFonVzuVPyB8GchGR2hytyiOVpuD9+k8hcuw
+ZWAaUoVtWIQ52aKS0p19G99hhb+IVANC4akkdHV4SP8i7MVNZhfUmg==
+-----END RSA PRIVATE KEY-----`
+
+var certificate = &Block{Type: "CERTIFICATE",
+	Headers: map[string]string{},
+	Bytes: []uint8{0x30, 0x82, 0x3, 0xe9, 0x30, 0x82, 0x3, 0x52, 0x2, 0x1,
+		0x1, 0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd,
+		0x1, 0x1, 0x5, 0x5, 0x0, 0x30, 0x81, 0x8b, 0x31, 0xb, 0x30,
+		0x9, 0x6, 0x3, 0x55, 0x4, 0x6, 0x13, 0x2, 0x55, 0x53, 0x31,
+		0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4, 0x8, 0x13, 0xa, 0x43,
+		0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31,
+		0x16, 0x30, 0x14, 0x6, 0x3, 0x55, 0x4, 0x7, 0x13, 0xd, 0x53,
+		0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73,
+		0x63, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x6, 0x3, 0x55, 0x4, 0xa,
+		0x13, 0xb, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49,
+		0x6e, 0x63, 0x2e, 0x31, 0xc, 0x30, 0xa, 0x6, 0x3, 0x55, 0x4,
+		0xb, 0x13, 0x3, 0x45, 0x6e, 0x67, 0x31, 0xc, 0x30, 0xa, 0x6,
+		0x3, 0x55, 0x4, 0x3, 0x13, 0x3, 0x61, 0x67, 0x6c, 0x31, 0x1d,
+		0x30, 0x1b, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1,
+		0x9, 0x1, 0x16, 0xe, 0x61, 0x67, 0x6c, 0x40, 0x67, 0x6f, 0x6f,
+		0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17,
+		0xd, 0x30, 0x39, 0x30, 0x39, 0x30, 0x39, 0x32, 0x32, 0x30,
+		0x35, 0x34, 0x33, 0x5a, 0x17, 0xd, 0x31, 0x30, 0x30, 0x39,
+		0x30, 0x39, 0x32, 0x32, 0x30, 0x35, 0x34, 0x33, 0x5a, 0x30,
+		0x6a, 0x31, 0xb, 0x30, 0x9, 0x6, 0x3, 0x55, 0x4, 0x6, 0x13,
+		0x2, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4,
+		0x8, 0x13, 0xa, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61,
+		0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x6, 0x3, 0x55, 0x4, 0xa,
+		0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
+		0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+		0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x23, 0x30, 0x21,
+		0x6, 0x3, 0x55, 0x4, 0x3, 0x13, 0x1a, 0x65, 0x75, 0x72, 0x6f,
+		0x70, 0x61, 0x2e, 0x73, 0x66, 0x6f, 0x2e, 0x63, 0x6f, 0x72,
+		0x70, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+		0x6f, 0x6d, 0x30, 0x82, 0x2, 0x22, 0x30, 0xd, 0x6, 0x9, 0x2a,
+		0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x1, 0x5, 0x0, 0x3,
+		0x82, 0x2, 0xf, 0x0, 0x30, 0x82, 0x2, 0xa, 0x2, 0x82, 0x2, 0x1,
+		0x0, 0xba, 0xa6, 0x6, 0x2d, 0xef, 0xf1, 0x22, 0x6c, 0x10, 0xee,
+		0x98, 0x4, 0x85, 0xf9, 0x2d, 0x2a, 0xbe, 0xa7, 0x4b, 0xfd,
+		0xff, 0xa7, 0xa2, 0xe2, 0x70, 0xd9, 0x3d, 0x50, 0x73, 0xc1,
+		0xa6, 0x5c, 0x5f, 0xe2, 0x89, 0x47, 0x2b, 0xb2, 0xc, 0xe1,
+		0xfc, 0x57, 0x7c, 0xa4, 0x38, 0x73, 0xfd, 0x3f, 0x7a, 0x42,
+		0xf, 0x48, 0xc9, 0x1e, 0x33, 0xb6, 0xe7, 0x36, 0x31, 0x7a,
+		0xe6, 0x3e, 0xb6, 0xbe, 0xcc, 0xb, 0x92, 0x7f, 0x96, 0xde,
+		0xbc, 0x54, 0x5e, 0x4a, 0xab, 0xe9, 0x22, 0xdf, 0x3, 0xba,
+		0xfd, 0x7, 0x6c, 0x36, 0xdc, 0xaa, 0xcf, 0xd7, 0x28, 0xf7,
+		0xc1, 0xb8, 0xc0, 0xde, 0xfa, 0x87, 0xfb, 0x6b, 0xd1, 0x82,
+		0xcb, 0xb, 0xc0, 0x67, 0x86, 0x54, 0x25, 0xca, 0x74, 0xb6,
+		0x1a, 0x83, 0xf5, 0xf2, 0x93, 0x4e, 0x35, 0x16, 0x38, 0x1c,
+		0xc7, 0x63, 0x5b, 0x8d, 0x13, 0x84, 0x62, 0xb6, 0xb8, 0x66,
+		0x24, 0x2a, 0xdb, 0x4, 0x65, 0xdb, 0x27, 0x6e, 0x3d, 0x6e,
+		0xf8, 0x26, 0x6f, 0xb8, 0xe0, 0x74, 0x89, 0xc7, 0xd8, 0xf5,
+		0x3b, 0x3d, 0x3e, 0x79, 0x86, 0xe8, 0xef, 0x3a, 0x82, 0x2c,
+		0x41, 0x6d, 0xa8, 0xb1, 0x70, 0x45, 0x46, 0xea, 0xf8, 0xa4,
+		0x5d, 0x70, 0x99, 0x58, 0x78, 0x5b, 0x89, 0x53, 0x2c, 0x3e,
+		0xa9, 0x8d, 0xf2, 0xc, 0x51, 0xc3, 0xb, 0x20, 0x21, 0xc4, 0x5c,
+		0x43, 0x7b, 0xdc, 0xf0, 0xe2, 0x73, 0xc2, 0x92, 0xdc, 0x4b,
+		0x4d, 0x60, 0x2c, 0x28, 0x22, 0x57, 0x7e, 0xb6, 0x92, 0x1,
+		0x8c, 0x4d, 0x50, 0x39, 0xbd, 0x4a, 0x3b, 0x2b, 0x89, 0x4,
+		0xd5, 0xba, 0x12, 0xcc, 0x3d, 0x0, 0xb6, 0x67, 0xee, 0xcb,
+		0x56, 0x75, 0x87, 0x4, 0xa8, 0xc, 0x2f, 0xbf, 0x6d, 0x1e, 0x80,
+		0xdd, 0xad, 0x11, 0x7a, 0xa3, 0xed, 0xe, 0x3f, 0xd5, 0xc7,
+		0x32, 0x3d, 0x97, 0x37, 0x3d, 0x8, 0x2, 0xdc, 0x52, 0x7c, 0x5,
+		0xed, 0xa6, 0xb6, 0x59, 0x4c, 0xfb, 0xcd, 0x2a, 0x7f, 0x87,
+		0x40, 0x69, 0xf, 0xdf, 0x5a, 0xf0, 0xad, 0x3a, 0xb4, 0x39,
+		0xa6, 0x77, 0xde, 0xf6, 0x3b, 0x90, 0xbc, 0x2a, 0x3c, 0x63,
+		0x45, 0x46, 0x94, 0x57, 0x2b, 0x4b, 0x2b, 0x3f, 0x33, 0x34,
+		0xa0, 0xf4, 0xb2, 0x7f, 0xdb, 0x88, 0xd9, 0x56, 0xc, 0xd0,
+		0xbd, 0xe7, 0x7f, 0x42, 0xea, 0x6c, 0xa7, 0xcf, 0x70, 0x56,
+		0x27, 0x70, 0x23, 0x38, 0xed, 0xf9, 0x67, 0x52, 0x7f, 0x25,
+		0x9f, 0x1f, 0x4f, 0xef, 0xd5, 0xa4, 0xb, 0xbe, 0xee, 0x5c,
+		0x31, 0x8b, 0x96, 0xff, 0xf0, 0xb4, 0x5b, 0x69, 0xe5, 0x63,
+		0x38, 0x8b, 0xe5, 0xb9, 0x44, 0x4e, 0x7b, 0x4c, 0xf0, 0xcc,
+		0xb6, 0xc9, 0xb3, 0x40, 0x47, 0x2d, 0xc8, 0x8, 0x7c, 0x42, 0x6,
+		0xfd, 0x91, 0x36, 0xd3, 0xc8, 0x59, 0x5, 0x66, 0xf8, 0x4f,
+		0x7f, 0x5b, 0x9a, 0xf0, 0x87, 0x62, 0x9, 0x47, 0x80, 0xc7,
+		0x9f, 0x62, 0xc7, 0xc1, 0x45, 0x66, 0x4f, 0xf8, 0x47, 0x35,
+		0x37, 0x41, 0x2e, 0x5e, 0x54, 0x87, 0xa, 0xf8, 0x59, 0xce,
+		0xc9, 0x84, 0x4e, 0xc0, 0x56, 0xa6, 0xf5, 0xe2, 0x95, 0x4d,
+		0xcf, 0x59, 0x6b, 0xe6, 0x3c, 0x6c, 0xa7, 0xff, 0xe7, 0x70,
+		0x8c, 0x1f, 0xb5, 0xbe, 0xe6, 0x65, 0xd, 0xc3, 0x17, 0x4d,
+		0xd8, 0x9d, 0xaf, 0xa3, 0x26, 0x1a, 0x73, 0xc7, 0xc0, 0x90,
+		0xa1, 0xe2, 0xd3, 0xe9, 0xa4, 0x2, 0x1f, 0x2c, 0xe6, 0x1f,
+		0xaf, 0xc, 0xac, 0x71, 0xd3, 0xe0, 0xc0, 0xb, 0x3f, 0x25, 0x2c,
+		0x3e, 0x89, 0xa3, 0x9f, 0xbd, 0x46, 0x35, 0x3b, 0x43, 0x79,
+		0x60, 0x17, 0x89, 0xb8, 0xc2, 0x81, 0xd2, 0xfa, 0x88, 0x70,
+		0x2, 0x8, 0x5e, 0x87, 0xb5, 0xb9, 0x74, 0xcc, 0x69, 0x46, 0xd0,
+		0xe0, 0xa, 0xf9, 0xb7, 0x67, 0xd1, 0x2, 0x3, 0x1, 0x0, 0x1,
+		0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1,
+		0x1, 0x5, 0x5, 0x0, 0x3, 0x81, 0x81, 0x0, 0xe2, 0xa7, 0x40,
+		0x3b, 0x6a, 0x5, 0x5d, 0xb8, 0xbd, 0x5a, 0xaf, 0x7a, 0xc2,
+		0xf9, 0x76, 0x79, 0xb2, 0x16, 0x91, 0x4f, 0x5c, 0x19, 0xf7,
+		0x59, 0xd1, 0x5f, 0xc0, 0x3e, 0x83, 0xcc, 0x46, 0xf6, 0xd5,
+		0x45, 0x46, 0xe6, 0x4a, 0xe6, 0x26, 0x2b, 0xbe, 0x56, 0x28,
+		0xa9, 0x39, 0x12, 0x4f, 0x18, 0xc9, 0x20, 0xa0, 0xbe, 0x81,
+		0x8d, 0x4d, 0xb5, 0x5c, 0x8f, 0x79, 0x55, 0x6, 0xee, 0x9f,
+		0x93, 0xfc, 0xbe, 0xf8, 0x3c, 0x67, 0xe1, 0x67, 0x16, 0xcb,
+		0xd1, 0x15, 0x8d, 0xde, 0xd4, 0x20, 0xb3, 0x1, 0x54, 0x18,
+		0x66, 0xc5, 0x24, 0x2f, 0xd, 0x88, 0xef, 0x32, 0x3f, 0x74,
+		0xd9, 0x56, 0x74, 0x1f, 0x17, 0xa7, 0xbb, 0xfe, 0xdf, 0xf,
+		0x6c, 0x5f, 0x93, 0x77, 0x27, 0xf5, 0xae, 0x27, 0x52, 0x8e,
+		0x3b, 0x99, 0xb6, 0xea, 0x44, 0x65, 0x1d, 0xa, 0x3b, 0x13,
+		0x34, 0xf7, 0xf7, 0xbe, 0x20,
+	},
+}
+
+var privateKey = &Block{Type: "RSA PRIVATE KEY",
+	Headers: map[string]string{"DEK-Info": "DES-EDE3-CBC,80C7C7A09690757A", "Proc-Type": "4,ENCRYPTED"},
+	Bytes: []uint8{0x79, 0xa, 0x79, 0x66, 0x41, 0xfa, 0xb,
+		0x21, 0xc1, 0xcf, 0xb0, 0x59, 0x7d, 0x43, 0xf1, 0xc8, 0xb0,
+		0x82, 0x99, 0xfb, 0x6c, 0x4, 0x9e, 0xc7, 0x96, 0xa1, 0x9b,
+		0xf0, 0xb7, 0x76, 0xd5, 0xc4, 0xb0, 0x9f, 0x35, 0x99, 0xe3,
+		0xf4, 0x88, 0x96, 0x1c, 0xab, 0x52, 0xdb, 0x1f, 0xc3, 0xb5,
+		0x51, 0xd9, 0x34, 0xf0, 0x3, 0xea, 0x1d, 0xa3, 0xd7, 0xb1,
+		0xec, 0x67, 0x71, 0x39, 0x36, 0x87, 0xf2, 0x86, 0x45, 0xba,
+		0x62, 0x11, 0xa2, 0x21, 0x23, 0x1e, 0xc9, 0x3c, 0x53, 0xb0,
+		0x61, 0x9e, 0xda, 0x7e, 0x7a, 0x49, 0xf, 0x3f, 0xbf, 0x71,
+		0xba, 0x79, 0xcd, 0xee, 0x16, 0xfb, 0x86, 0x48, 0x6b, 0xc8,
+		0x60, 0xd0, 0x66, 0x0, 0x3b, 0xb3, 0x67, 0x10, 0x1d, 0xe,
+		0xf5, 0xbf, 0x78, 0x30, 0x4f, 0x60, 0x40, 0x8, 0x7, 0xed,
+		0xdb, 0xa8, 0xc2, 0x8d, 0xb3, 0x35, 0xc2, 0x3, 0x73, 0x6,
+		0x72, 0x7c, 0x33, 0x44, 0x73, 0x9f, 0xaf, 0x18, 0x5a, 0xa6,
+		0x8f, 0xb5, 0xd0, 0x6e, 0xf2, 0xa6, 0xff, 0xcd, 0x54, 0x79,
+		0x24, 0x1d, 0x66, 0x9e, 0xab, 0xd3, 0x49, 0xb1, 0x6c, 0x7c,
+		0x5e, 0x72, 0x31, 0xce, 0xa8, 0xd9, 0x64, 0x3d, 0x8c, 0x90,
+		0xa5, 0xe8, 0xac, 0xa9, 0x9c, 0xc9, 0x7e, 0x6, 0x92, 0xfe,
+		0x76, 0x5b, 0xdd, 0x8d, 0x85, 0x4a, 0xe2, 0x5f, 0x65, 0x62,
+		0xc0, 0x75, 0x1e, 0xcd, 0xdd, 0xfb, 0x30, 0xc1, 0x6d, 0x6c,
+		0x68, 0xb3, 0xcd, 0x7c, 0xcf, 0x38, 0x52, 0xf3, 0xfc, 0xba,
+		0x78, 0x87, 0xe2, 0x48, 0x6d, 0xbb, 0x72, 0xaa, 0xdb, 0x85,
+		0x44, 0x5b, 0x9a, 0x8, 0x92, 0x7c, 0x35, 0xe3, 0x9d, 0xc2,
+		0xb8, 0x9b, 0xfa, 0x4b, 0x71, 0xe, 0xe6, 0x98, 0x12, 0xfa,
+		0x98, 0x53, 0xab, 0xdc, 0xf8, 0xf8, 0x8d, 0xea, 0x73, 0x80,
+		0xe8, 0x85, 0x44, 0xbe, 0x8c, 0x28, 0x4f, 0xff, 0x87, 0xad,
+		0x9f, 0x66, 0xf2, 0x35, 0x12, 0xb6, 0x2b, 0xf1, 0x5b, 0xa7,
+		0x1c, 0x4c, 0xa4, 0x80, 0xa3, 0x61, 0xa, 0x10, 0xef, 0x6f,
+		0x54, 0x4e, 0xe8, 0xb1, 0x1f, 0xa8, 0xa0, 0x6e, 0xf8, 0x8b,
+		0xf0, 0x4c, 0x1e, 0x9f, 0x6, 0x15, 0xb7, 0x4c, 0x22, 0xcc,
+		0x9d, 0x53, 0xd8, 0x56, 0x86, 0x30, 0x3, 0xe7, 0xc7, 0x35,
+		0x39, 0x99, 0x66, 0x6f, 0x1, 0x12, 0x89, 0xe5, 0x20, 0xc7,
+		0xc8, 0xf8, 0xa9, 0x2d, 0x8d, 0x65, 0x20, 0xe0, 0xe8, 0x9a,
+		0xf8, 0xd2, 0x3a, 0xbc, 0xa7, 0xf, 0xa4, 0x5a, 0x31, 0x85,
+		0x29, 0xe5, 0x1a, 0x0, 0xad, 0xbd, 0xf1, 0x1a, 0xab, 0x9f,
+		0xc7, 0xe2, 0x41, 0xc9, 0xa7, 0xde, 0x5e, 0x3a, 0x99, 0xc5,
+		0xb0, 0xbb, 0xe2, 0xc3, 0x6b, 0x1e, 0x1c, 0xd9, 0x33, 0xfc,
+		0xbc, 0x49, 0x31, 0x13, 0xf5, 0x5f, 0x8d, 0xbc, 0xf8, 0x3a,
+		0x58, 0x5b, 0xf4, 0x3, 0xff, 0x42, 0x54, 0xb4, 0x94, 0xae,
+		0xb, 0xfa, 0xbd, 0x15, 0x41, 0xcb, 0xe9, 0x12, 0x37, 0xbb,
+		0xf0, 0x2c, 0xae, 0xff, 0x29, 0x9, 0xbe, 0x3e, 0xf, 0xb8,
+		0xb5, 0x8d, 0x6f, 0xc0, 0x30, 0x87, 0x49, 0x4e, 0xdc, 0x9c,
+		0x38, 0x6b, 0x1b, 0x3f, 0x14, 0x0, 0xef, 0x21, 0xcc, 0x5a,
+		0xe8, 0xc7, 0x99, 0xe6, 0xf5, 0x5, 0x38, 0x87, 0x70, 0xbd,
+		0xec, 0xdc, 0xaa, 0xc9, 0xbb, 0x5b, 0xc3, 0x56, 0xbb, 0x21,
+		0xbf, 0x17, 0xe7, 0xcf, 0xbd, 0x4a, 0x4d, 0xe3, 0x67, 0x64,
+		0x7f, 0x14, 0x6c, 0xea, 0x93, 0xe6, 0x2e, 0xdf, 0x3c, 0x6c,
+		0x97, 0xb5, 0x8d, 0x57, 0x25, 0xd7, 0x5c, 0x6c, 0x8f, 0xd0,
+		0xea, 0xd5, 0xdf, 0xc0, 0x71, 0x6c, 0x65, 0xcd, 0xb4, 0x4f,
+		0x34, 0x9d, 0xb1, 0x52, 0xc1, 0xb7, 0x9, 0x2c, 0x51, 0xa7,
+		0x29, 0x6c, 0x3a, 0x20, 0x70, 0x45, 0x4c, 0x72, 0xd9, 0xcd,
+		0xac, 0x1f, 0x5, 0x22, 0xb0, 0x77, 0xbd, 0x91, 0x2f, 0xf5,
+		0xd, 0x19, 0xd5, 0x57, 0x98, 0xee, 0x79, 0x93, 0xa4, 0x5f,
+		0xba, 0x6b, 0xec, 0xf6, 0x3f, 0xb6, 0x9c, 0x2f, 0xb8, 0xfa,
+		0x3, 0xa3, 0xeb, 0xdf, 0xea, 0xbc, 0x3f, 0xd0, 0x8f, 0x88,
+		0xf0, 0xbb, 0xcc, 0x5a, 0x27, 0x57, 0x3b, 0x95, 0x3f, 0x20,
+		0x7c, 0x19, 0xc8, 0x46, 0x47, 0x68, 0x72, 0xb7, 0x28, 0x8e,
+		0x56, 0x9b, 0x83, 0xf7, 0xe9, 0x3c, 0x85, 0xcb, 0xb0, 0x65,
+		0x60, 0x1a, 0x52, 0x85, 0x6d, 0x58, 0x84, 0x39, 0xd9, 0xa2,
+		0x92, 0xd2, 0x9d, 0x7d, 0x1b, 0xdf, 0x61, 0x85, 0xbf, 0x88,
+		0x54, 0x3, 0x42, 0xe1, 0xa9, 0x24, 0x74, 0x75, 0x78, 0x48,
+		0xff, 0x22, 0xec, 0xc5, 0x4d, 0x66, 0x17, 0xd4, 0x9a,
+	},
+}
+
+var privateKey2 = &Block{
+	Type: "RSA PRIVATE KEY",
+	Headers: map[string]string{
+		"Proc-Type":      "4,ENCRYPTED",
+		"DEK-Info":       "AES-128-CBC,BFCD243FEDBB40A4AA6DDAA1335473A4",
+		"Content-Domain": "RFC822",
+	},
+	Bytes: []uint8{
+		0xa8, 0x35, 0xcc, 0x2b, 0xb9, 0xcb, 0x21, 0xab, 0xc0,
+		0x9d, 0x76, 0x61, 0x0, 0xf4, 0x81, 0xad, 0x69, 0xd2,
+		0xc0, 0x42, 0x41, 0x3b, 0xe4, 0x3c, 0xaf, 0x59, 0x5e,
+		0x6d, 0x2a, 0x3c, 0x9c, 0xa1, 0xa4, 0x5e, 0x68, 0x37,
+		0xc4, 0x8c, 0x70, 0x1c, 0xa9, 0x18, 0xe6, 0xc2, 0x2b,
+		0x8a, 0x91, 0xdc, 0x2d, 0x1f, 0x8, 0x23, 0x39, 0xf1,
+		0x4b, 0x8b, 0x1b, 0x2f, 0x46, 0xb, 0xb2, 0x26, 0xba,
+		0x4f, 0x40, 0x80, 0x39, 0xc4, 0xb1, 0xcb, 0x3b, 0xb4,
+		0x65, 0x3f, 0x1b, 0xb2, 0xf7, 0x8, 0xd2, 0xc6, 0xd5,
+		0xa8, 0x9f, 0x23, 0x69, 0xb6, 0x3d, 0xf9, 0xac, 0x1c,
+		0xb3, 0x13, 0x87, 0x64, 0x4, 0x37, 0xdb, 0x40, 0xc8,
+		0x82, 0xc, 0xd0, 0xf8, 0x21, 0x7c, 0xdc, 0xbd, 0x9, 0x4,
+		0x20, 0x16, 0xb0, 0x97, 0xe2, 0x6d, 0x56, 0x1d, 0xe3,
+		0xec, 0xf0, 0xfc, 0xe2, 0x56, 0xad, 0xa4, 0x3, 0x70,
+		0x6d, 0x63, 0x3c, 0x1, 0xbe, 0x3e, 0x28, 0x38, 0x6f,
+		0xc0, 0xe6, 0xfd, 0x85, 0xd1, 0x53, 0xa8, 0x9b, 0xcb,
+		0xd4, 0x4, 0xb1, 0x73, 0xb9, 0x73, 0x32, 0xd6, 0x7a,
+		0xc6, 0x29, 0x25, 0xa5, 0xda, 0x17, 0x93, 0x7a, 0x10,
+		0xe8, 0x41, 0xfb, 0xa5, 0x17, 0x20, 0xf8, 0x4e, 0xe9,
+		0xe3, 0x8f, 0x51, 0x20, 0x13, 0xbb, 0xde, 0xb7, 0x93,
+		0xae, 0x13, 0x8a, 0xf6, 0x9, 0xf4, 0xa6, 0x41, 0xe0,
+		0x2b, 0x51, 0x1a, 0x30, 0x38, 0xd, 0xb1, 0x3b, 0x67,
+		0x87, 0x64, 0xf5, 0xca, 0x32, 0x67, 0xd1, 0xc8, 0xa5,
+		0x3d, 0x23, 0x72, 0xc4, 0x6, 0xaf, 0x8f, 0x7b, 0x26,
+		0xac, 0x3c, 0x75, 0x91, 0xa1, 0x0, 0x13, 0xc6, 0x5c,
+		0x49, 0xd5, 0x3c, 0xe7, 0xb2, 0xb2, 0x99, 0xe0, 0xd5,
+		0x25, 0xfa, 0xe2, 0x12, 0x80, 0x37, 0x85, 0xcf, 0x92,
+		0xca, 0x1b, 0x9f, 0xf3, 0x4e, 0xd8, 0x80, 0xef, 0x3c,
+		0xce, 0xcd, 0xf5, 0x90, 0x9e, 0xf9, 0xa7, 0xb2, 0xc,
+		0x49, 0x4, 0xf1, 0x9, 0x8f, 0xea, 0x63, 0xd2, 0x70,
+		0xbb, 0x86, 0xbf, 0x34, 0xab, 0xb2, 0x3, 0xb1, 0x59,
+		0x33, 0x16, 0x17, 0xb0, 0xdb, 0x77, 0x38, 0xf4, 0xb4,
+		0x94, 0xb, 0x25, 0x16, 0x7e, 0x22, 0xd4, 0xf9, 0x22,
+		0xb9, 0x78, 0xa3, 0x4, 0x84, 0x4, 0xd2, 0xda, 0x84,
+		0x2d, 0x63, 0xdd, 0xf8, 0x50, 0x6a, 0xf6, 0xe3, 0xf5,
+		0x65, 0x40, 0x7c, 0xa9,
+	},
+}
+
+var pemPrivateKey2 = `-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+Content-Domain: RFC822
+DEK-Info: AES-128-CBC,BFCD243FEDBB40A4AA6DDAA1335473A4
+
+qDXMK7nLIavAnXZhAPSBrWnSwEJBO+Q8r1lebSo8nKGkXmg3xIxwHKkY5sIripHc
+LR8IIznxS4sbL0YLsia6T0CAOcSxyzu0ZT8bsvcI0sbVqJ8jabY9+awcsxOHZAQ3
+20DIggzQ+CF83L0JBCAWsJfibVYd4+zw/OJWraQDcG1jPAG+Pig4b8Dm/YXRU6ib
+y9QEsXO5czLWesYpJaXaF5N6EOhB+6UXIPhO6eOPUSATu963k64TivYJ9KZB4CtR
+GjA4DbE7Z4dk9coyZ9HIpT0jcsQGr497Jqw8dZGhABPGXEnVPOeyspng1SX64hKA
+N4XPksobn/NO2IDvPM7N9ZCe+aeyDEkE8QmP6mPScLuGvzSrsgOxWTMWF7Dbdzj0
+tJQLJRZ+ItT5Irl4owSEBNLahC1j3fhQavbj9WVAfKk=
+-----END RSA PRIVATE KEY-----
+`
diff --git a/third_party/gofrontend/libgo/go/encoding/xml/atom_test.go b/third_party/gofrontend/libgo/go/encoding/xml/atom_test.go
new file mode 100644
index 0000000..a712843
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/xml/atom_test.go
@@ -0,0 +1,56 @@
+// 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.
+
+package xml
+
+import "time"
+
+var atomValue = &Feed{
+	XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
+	Title:   "Example Feed",
+	Link:    []Link{{Href: "http://example.org/"}},
+	Updated: ParseTime("2003-12-13T18:30:02Z"),
+	Author:  Person{Name: "John Doe"},
+	Id:      "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6",
+
+	Entry: []Entry{
+		{
+			Title:   "Atom-Powered Robots Run Amok",
+			Link:    []Link{{Href: "http://example.org/2003/12/13/atom03"}},
+			Id:      "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a",
+			Updated: ParseTime("2003-12-13T18:30:02Z"),
+			Summary: NewText("Some text."),
+		},
+	},
+}
+
+var atomXml = `` +
+	`<feed xmlns="http://www.w3.org/2005/Atom" updated="2003-12-13T18:30:02Z">` +
+	`<title>Example Feed</title>` +
+	`<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>` +
+	`<link href="http://example.org/"></link>` +
+	`<author><name>John Doe</name><uri></uri><email></email></author>` +
+	`<entry>` +
+	`<title>Atom-Powered Robots Run Amok</title>` +
+	`<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>` +
+	`<link href="http://example.org/2003/12/13/atom03"></link>` +
+	`<updated>2003-12-13T18:30:02Z</updated>` +
+	`<author><name></name><uri></uri><email></email></author>` +
+	`<summary>Some text.</summary>` +
+	`</entry>` +
+	`</feed>`
+
+func ParseTime(str string) time.Time {
+	t, err := time.Parse(time.RFC3339, str)
+	if err != nil {
+		panic(err)
+	}
+	return t
+}
+
+func NewText(text string) Text {
+	return Text{
+		Body: text,
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/xml/marshal.go b/third_party/gofrontend/libgo/go/encoding/xml/marshal.go
new file mode 100644
index 0000000..8c63420
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/xml/marshal.go
@@ -0,0 +1,938 @@
+// 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.
+
+package xml
+
+import (
+	"bufio"
+	"bytes"
+	"encoding"
+	"fmt"
+	"io"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+const (
+	// A generic XML header suitable for use with the output of Marshal.
+	// This is not automatically added to any output of this package,
+	// it is provided as a convenience.
+	Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
+)
+
+// Marshal returns the XML encoding of v.
+//
+// Marshal handles an array or slice by marshalling each of the elements.
+// Marshal handles a pointer by marshalling the value it points at or, if the
+// pointer is nil, by writing nothing.  Marshal handles an interface value by
+// marshalling the value it contains or, if the interface value is nil, by
+// writing nothing.  Marshal handles all other data by writing one or more XML
+// elements containing the data.
+//
+// The name for the XML elements is taken from, in order of preference:
+//     - the tag on the XMLName field, if the data is a struct
+//     - the value of the XMLName field of type xml.Name
+//     - the tag of the struct field used to obtain the data
+//     - the name of the struct field used to obtain the data
+//     - the name of the marshalled type
+//
+// The XML element for a struct contains marshalled elements for each of the
+// exported fields of the struct, with these exceptions:
+//     - the XMLName field, described above, is omitted.
+//     - a field with tag "-" is omitted.
+//     - a field with tag "name,attr" becomes an attribute with
+//       the given name in the XML element.
+//     - a field with tag ",attr" becomes an attribute with the
+//       field name in the XML element.
+//     - a field with tag ",chardata" is written as character data,
+//       not as an XML element.
+//     - a field with tag ",innerxml" is written verbatim, not subject
+//       to the usual marshalling procedure.
+//     - a field with tag ",comment" is written as an XML comment, not
+//       subject to the usual marshalling procedure. It must not contain
+//       the "--" string within it.
+//     - a field with a tag including the "omitempty" option is omitted
+//       if the field value is empty. The empty values are false, 0, any
+//       nil pointer or interface value, and any array, slice, map, or
+//       string of length zero.
+//     - an anonymous struct field is handled as if the fields of its
+//       value were part of the outer struct.
+//
+// If a field uses a tag "a>b>c", then the element c will be nested inside
+// parent elements a and b.  Fields that appear next to each other that name
+// the same parent will be enclosed in one XML element.
+//
+// See MarshalIndent for an example.
+//
+// Marshal will return an error if asked to marshal a channel, function, or map.
+func Marshal(v interface{}) ([]byte, error) {
+	var b bytes.Buffer
+	if err := NewEncoder(&b).Encode(v); err != nil {
+		return nil, err
+	}
+	return b.Bytes(), nil
+}
+
+// Marshaler is the interface implemented by objects that can marshal
+// themselves into valid XML elements.
+//
+// MarshalXML encodes the receiver as zero or more XML elements.
+// By convention, arrays or slices are typically encoded as a sequence
+// of elements, one per entry.
+// Using start as the element tag is not required, but doing so
+// will enable Unmarshal to match the XML elements to the correct
+// struct field.
+// One common implementation strategy is to construct a separate
+// value with a layout corresponding to the desired XML and then
+// to encode it using e.EncodeElement.
+// Another common strategy is to use repeated calls to e.EncodeToken
+// to generate the XML output one token at a time.
+// The sequence of encoded tokens must make up zero or more valid
+// XML elements.
+type Marshaler interface {
+	MarshalXML(e *Encoder, start StartElement) error
+}
+
+// MarshalerAttr is the interface implemented by objects that can marshal
+// themselves into valid XML attributes.
+//
+// MarshalXMLAttr returns an XML attribute with the encoded value of the receiver.
+// Using name as the attribute name is not required, but doing so
+// will enable Unmarshal to match the attribute to the correct
+// struct field.
+// If MarshalXMLAttr returns the zero attribute Attr{}, no attribute
+// will be generated in the output.
+// MarshalXMLAttr is used only for struct fields with the
+// "attr" option in the field tag.
+type MarshalerAttr interface {
+	MarshalXMLAttr(name Name) (Attr, error)
+}
+
+// MarshalIndent works like Marshal, but each XML element begins on a new
+// indented line that starts with prefix and is followed by one or more
+// copies of indent according to the nesting depth.
+func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
+	var b bytes.Buffer
+	enc := NewEncoder(&b)
+	enc.Indent(prefix, indent)
+	if err := enc.Encode(v); err != nil {
+		return nil, err
+	}
+	return b.Bytes(), nil
+}
+
+// An Encoder writes XML data to an output stream.
+type Encoder struct {
+	p printer
+}
+
+// NewEncoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+	e := &Encoder{printer{Writer: bufio.NewWriter(w)}}
+	e.p.encoder = e
+	return e
+}
+
+// Indent sets the encoder to generate XML in which each element
+// begins on a new indented line that starts with prefix and is followed by
+// one or more copies of indent according to the nesting depth.
+func (enc *Encoder) Indent(prefix, indent string) {
+	enc.p.prefix = prefix
+	enc.p.indent = indent
+}
+
+// Encode writes the XML encoding of v to the stream.
+//
+// See the documentation for Marshal for details about the conversion
+// of Go values to XML.
+//
+// Encode calls Flush before returning.
+func (enc *Encoder) Encode(v interface{}) error {
+	err := enc.p.marshalValue(reflect.ValueOf(v), nil, nil)
+	if err != nil {
+		return err
+	}
+	return enc.p.Flush()
+}
+
+// EncodeElement writes the XML encoding of v to the stream,
+// using start as the outermost tag in the encoding.
+//
+// See the documentation for Marshal for details about the conversion
+// of Go values to XML.
+//
+// EncodeElement calls Flush before returning.
+func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error {
+	err := enc.p.marshalValue(reflect.ValueOf(v), nil, &start)
+	if err != nil {
+		return err
+	}
+	return enc.p.Flush()
+}
+
+var (
+	endComment   = []byte("-->")
+	endProcInst  = []byte("?>")
+	endDirective = []byte(">")
+)
+
+// EncodeToken writes the given XML token to the stream.
+// It returns an error if StartElement and EndElement tokens are not properly matched.
+//
+// EncodeToken does not call Flush, because usually it is part of a larger operation
+// such as Encode or EncodeElement (or a custom Marshaler's MarshalXML invoked
+// during those), and those will call Flush when finished.
+// Callers that create an Encoder and then invoke EncodeToken directly, without
+// using Encode or EncodeElement, need to call Flush when finished to ensure
+// that the XML is written to the underlying writer.
+//
+// EncodeToken allows writing a ProcInst with Target set to "xml" only as the first token
+// in the stream.
+func (enc *Encoder) EncodeToken(t Token) error {
+	p := &enc.p
+	switch t := t.(type) {
+	case StartElement:
+		if err := p.writeStart(&t); err != nil {
+			return err
+		}
+	case EndElement:
+		if err := p.writeEnd(t.Name); err != nil {
+			return err
+		}
+	case CharData:
+		EscapeText(p, t)
+	case Comment:
+		if bytes.Contains(t, endComment) {
+			return fmt.Errorf("xml: EncodeToken of Comment containing --> marker")
+		}
+		p.WriteString("<!--")
+		p.Write(t)
+		p.WriteString("-->")
+		return p.cachedWriteError()
+	case ProcInst:
+		// First token to be encoded which is also a ProcInst with target of xml
+		// is the xml declaration.  The only ProcInst where target of xml is allowed.
+		if t.Target == "xml" && p.Buffered() != 0 {
+			return fmt.Errorf("xml: EncodeToken of ProcInst xml target only valid for xml declaration, first token encoded")
+		}
+		if !isNameString(t.Target) {
+			return fmt.Errorf("xml: EncodeToken of ProcInst with invalid Target")
+		}
+		if bytes.Contains(t.Inst, endProcInst) {
+			return fmt.Errorf("xml: EncodeToken of ProcInst containing ?> marker")
+		}
+		p.WriteString("<?")
+		p.WriteString(t.Target)
+		if len(t.Inst) > 0 {
+			p.WriteByte(' ')
+			p.Write(t.Inst)
+		}
+		p.WriteString("?>")
+	case Directive:
+		if bytes.Contains(t, endDirective) {
+			return fmt.Errorf("xml: EncodeToken of Directive containing > marker")
+		}
+		p.WriteString("<!")
+		p.Write(t)
+		p.WriteString(">")
+	}
+	return p.cachedWriteError()
+}
+
+// Flush flushes any buffered XML to the underlying writer.
+// See the EncodeToken documentation for details about when it is necessary.
+func (enc *Encoder) Flush() error {
+	return enc.p.Flush()
+}
+
+type printer struct {
+	*bufio.Writer
+	encoder    *Encoder
+	seq        int
+	indent     string
+	prefix     string
+	depth      int
+	indentedIn bool
+	putNewline bool
+	attrNS     map[string]string // map prefix -> name space
+	attrPrefix map[string]string // map name space -> prefix
+	prefixes   []string
+	tags       []Name
+}
+
+// createAttrPrefix finds the name space prefix attribute to use for the given name space,
+// defining a new prefix if necessary. It returns the prefix.
+func (p *printer) createAttrPrefix(url string) string {
+	if prefix := p.attrPrefix[url]; prefix != "" {
+		return prefix
+	}
+
+	// The "http://www.w3.org/XML/1998/namespace" name space is predefined as "xml"
+	// and must be referred to that way.
+	// (The "http://www.w3.org/2000/xmlns/" name space is also predefined as "xmlns",
+	// but users should not be trying to use that one directly - that's our job.)
+	if url == xmlURL {
+		return "xml"
+	}
+
+	// Need to define a new name space.
+	if p.attrPrefix == nil {
+		p.attrPrefix = make(map[string]string)
+		p.attrNS = make(map[string]string)
+	}
+
+	// Pick a name. We try to use the final element of the path
+	// but fall back to _.
+	prefix := strings.TrimRight(url, "/")
+	if i := strings.LastIndex(prefix, "/"); i >= 0 {
+		prefix = prefix[i+1:]
+	}
+	if prefix == "" || !isName([]byte(prefix)) || strings.Contains(prefix, ":") {
+		prefix = "_"
+	}
+	if strings.HasPrefix(prefix, "xml") {
+		// xmlanything is reserved.
+		prefix = "_" + prefix
+	}
+	if p.attrNS[prefix] != "" {
+		// Name is taken. Find a better one.
+		for p.seq++; ; p.seq++ {
+			if id := prefix + "_" + strconv.Itoa(p.seq); p.attrNS[id] == "" {
+				prefix = id
+				break
+			}
+		}
+	}
+
+	p.attrPrefix[url] = prefix
+	p.attrNS[prefix] = url
+
+	p.WriteString(`xmlns:`)
+	p.WriteString(prefix)
+	p.WriteString(`="`)
+	EscapeText(p, []byte(url))
+	p.WriteString(`" `)
+
+	p.prefixes = append(p.prefixes, prefix)
+
+	return prefix
+}
+
+// deleteAttrPrefix removes an attribute name space prefix.
+func (p *printer) deleteAttrPrefix(prefix string) {
+	delete(p.attrPrefix, p.attrNS[prefix])
+	delete(p.attrNS, prefix)
+}
+
+func (p *printer) markPrefix() {
+	p.prefixes = append(p.prefixes, "")
+}
+
+func (p *printer) popPrefix() {
+	for len(p.prefixes) > 0 {
+		prefix := p.prefixes[len(p.prefixes)-1]
+		p.prefixes = p.prefixes[:len(p.prefixes)-1]
+		if prefix == "" {
+			break
+		}
+		p.deleteAttrPrefix(prefix)
+	}
+}
+
+var (
+	marshalerType     = reflect.TypeOf((*Marshaler)(nil)).Elem()
+	marshalerAttrType = reflect.TypeOf((*MarshalerAttr)(nil)).Elem()
+	textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+)
+
+// marshalValue writes one or more XML elements representing val.
+// If val was obtained from a struct field, finfo must have its details.
+func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplate *StartElement) error {
+	if startTemplate != nil && startTemplate.Name.Local == "" {
+		return fmt.Errorf("xml: EncodeElement of StartElement with missing name")
+	}
+
+	if !val.IsValid() {
+		return nil
+	}
+	if finfo != nil && finfo.flags&fOmitEmpty != 0 && isEmptyValue(val) {
+		return nil
+	}
+
+	// Drill into interfaces and pointers.
+	// This can turn into an infinite loop given a cyclic chain,
+	// but it matches the Go 1 behavior.
+	for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
+		if val.IsNil() {
+			return nil
+		}
+		val = val.Elem()
+	}
+
+	kind := val.Kind()
+	typ := val.Type()
+
+	// Check for marshaler.
+	if val.CanInterface() && typ.Implements(marshalerType) {
+		return p.marshalInterface(val.Interface().(Marshaler), defaultStart(typ, finfo, startTemplate))
+	}
+	if val.CanAddr() {
+		pv := val.Addr()
+		if pv.CanInterface() && pv.Type().Implements(marshalerType) {
+			return p.marshalInterface(pv.Interface().(Marshaler), defaultStart(pv.Type(), finfo, startTemplate))
+		}
+	}
+
+	// Check for text marshaler.
+	if val.CanInterface() && typ.Implements(textMarshalerType) {
+		return p.marshalTextInterface(val.Interface().(encoding.TextMarshaler), defaultStart(typ, finfo, startTemplate))
+	}
+	if val.CanAddr() {
+		pv := val.Addr()
+		if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
+			return p.marshalTextInterface(pv.Interface().(encoding.TextMarshaler), defaultStart(pv.Type(), finfo, startTemplate))
+		}
+	}
+
+	// Slices and arrays iterate over the elements. They do not have an enclosing tag.
+	if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 {
+		for i, n := 0, val.Len(); i < n; i++ {
+			if err := p.marshalValue(val.Index(i), finfo, startTemplate); err != nil {
+				return err
+			}
+		}
+		return nil
+	}
+
+	tinfo, err := getTypeInfo(typ)
+	if err != nil {
+		return err
+	}
+
+	// Create start element.
+	// Precedence for the XML element name is:
+	// 0. startTemplate
+	// 1. XMLName field in underlying struct;
+	// 2. field name/tag in the struct field; and
+	// 3. type name
+	var start StartElement
+
+	if startTemplate != nil {
+		start.Name = startTemplate.Name
+		start.Attr = append(start.Attr, startTemplate.Attr...)
+	} else if tinfo.xmlname != nil {
+		xmlname := tinfo.xmlname
+		if xmlname.name != "" {
+			start.Name.Space, start.Name.Local = xmlname.xmlns, xmlname.name
+		} else if v, ok := xmlname.value(val).Interface().(Name); ok && v.Local != "" {
+			start.Name = v
+		}
+	}
+	if start.Name.Local == "" && finfo != nil {
+		start.Name.Space, start.Name.Local = finfo.xmlns, finfo.name
+	}
+	if start.Name.Local == "" {
+		name := typ.Name()
+		if name == "" {
+			return &UnsupportedTypeError{typ}
+		}
+		start.Name.Local = name
+	}
+
+	// Attributes
+	for i := range tinfo.fields {
+		finfo := &tinfo.fields[i]
+		if finfo.flags&fAttr == 0 {
+			continue
+		}
+		fv := finfo.value(val)
+		name := Name{Space: finfo.xmlns, Local: finfo.name}
+
+		if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
+			continue
+		}
+
+		if fv.Kind() == reflect.Interface && fv.IsNil() {
+			continue
+		}
+
+		if fv.CanInterface() && fv.Type().Implements(marshalerAttrType) {
+			attr, err := fv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
+			if err != nil {
+				return err
+			}
+			if attr.Name.Local != "" {
+				start.Attr = append(start.Attr, attr)
+			}
+			continue
+		}
+
+		if fv.CanAddr() {
+			pv := fv.Addr()
+			if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) {
+				attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
+				if err != nil {
+					return err
+				}
+				if attr.Name.Local != "" {
+					start.Attr = append(start.Attr, attr)
+				}
+				continue
+			}
+		}
+
+		if fv.CanInterface() && fv.Type().Implements(textMarshalerType) {
+			text, err := fv.Interface().(encoding.TextMarshaler).MarshalText()
+			if err != nil {
+				return err
+			}
+			start.Attr = append(start.Attr, Attr{name, string(text)})
+			continue
+		}
+
+		if fv.CanAddr() {
+			pv := fv.Addr()
+			if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
+				text, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
+				if err != nil {
+					return err
+				}
+				start.Attr = append(start.Attr, Attr{name, string(text)})
+				continue
+			}
+		}
+
+		// Dereference or skip nil pointer, interface values.
+		switch fv.Kind() {
+		case reflect.Ptr, reflect.Interface:
+			if fv.IsNil() {
+				continue
+			}
+			fv = fv.Elem()
+		}
+
+		s, b, err := p.marshalSimple(fv.Type(), fv)
+		if err != nil {
+			return err
+		}
+		if b != nil {
+			s = string(b)
+		}
+		start.Attr = append(start.Attr, Attr{name, s})
+	}
+
+	if err := p.writeStart(&start); err != nil {
+		return err
+	}
+
+	if val.Kind() == reflect.Struct {
+		err = p.marshalStruct(tinfo, val)
+	} else {
+		s, b, err1 := p.marshalSimple(typ, val)
+		if err1 != nil {
+			err = err1
+		} else if b != nil {
+			EscapeText(p, b)
+		} else {
+			p.EscapeString(s)
+		}
+	}
+	if err != nil {
+		return err
+	}
+
+	if err := p.writeEnd(start.Name); err != nil {
+		return err
+	}
+
+	return p.cachedWriteError()
+}
+
+// defaultStart returns the default start element to use,
+// given the reflect type, field info, and start template.
+func defaultStart(typ reflect.Type, finfo *fieldInfo, startTemplate *StartElement) StartElement {
+	var start StartElement
+	// Precedence for the XML element name is as above,
+	// except that we do not look inside structs for the first field.
+	if startTemplate != nil {
+		start.Name = startTemplate.Name
+		start.Attr = append(start.Attr, startTemplate.Attr...)
+	} else if finfo != nil && finfo.name != "" {
+		start.Name.Local = finfo.name
+		start.Name.Space = finfo.xmlns
+	} else if typ.Name() != "" {
+		start.Name.Local = typ.Name()
+	} else {
+		// Must be a pointer to a named type,
+		// since it has the Marshaler methods.
+		start.Name.Local = typ.Elem().Name()
+	}
+	return start
+}
+
+// marshalInterface marshals a Marshaler interface value.
+func (p *printer) marshalInterface(val Marshaler, start StartElement) error {
+	// Push a marker onto the tag stack so that MarshalXML
+	// cannot close the XML tags that it did not open.
+	p.tags = append(p.tags, Name{})
+	n := len(p.tags)
+
+	err := val.MarshalXML(p.encoder, start)
+	if err != nil {
+		return err
+	}
+
+	// Make sure MarshalXML closed all its tags. p.tags[n-1] is the mark.
+	if len(p.tags) > n {
+		return fmt.Errorf("xml: %s.MarshalXML wrote invalid XML: <%s> not closed", receiverType(val), p.tags[len(p.tags)-1].Local)
+	}
+	p.tags = p.tags[:n-1]
+	return nil
+}
+
+// marshalTextInterface marshals a TextMarshaler interface value.
+func (p *printer) marshalTextInterface(val encoding.TextMarshaler, start StartElement) error {
+	if err := p.writeStart(&start); err != nil {
+		return err
+	}
+	text, err := val.MarshalText()
+	if err != nil {
+		return err
+	}
+	EscapeText(p, text)
+	return p.writeEnd(start.Name)
+}
+
+// writeStart writes the given start element.
+func (p *printer) writeStart(start *StartElement) error {
+	if start.Name.Local == "" {
+		return fmt.Errorf("xml: start tag with no name")
+	}
+
+	p.tags = append(p.tags, start.Name)
+	p.markPrefix()
+
+	p.writeIndent(1)
+	p.WriteByte('<')
+	p.WriteString(start.Name.Local)
+
+	if start.Name.Space != "" {
+		p.WriteString(` xmlns="`)
+		p.EscapeString(start.Name.Space)
+		p.WriteByte('"')
+	}
+
+	// Attributes
+	for _, attr := range start.Attr {
+		name := attr.Name
+		if name.Local == "" {
+			continue
+		}
+		p.WriteByte(' ')
+		if name.Space != "" {
+			p.WriteString(p.createAttrPrefix(name.Space))
+			p.WriteByte(':')
+		}
+		p.WriteString(name.Local)
+		p.WriteString(`="`)
+		p.EscapeString(attr.Value)
+		p.WriteByte('"')
+	}
+	p.WriteByte('>')
+	return nil
+}
+
+func (p *printer) writeEnd(name Name) error {
+	if name.Local == "" {
+		return fmt.Errorf("xml: end tag with no name")
+	}
+	if len(p.tags) == 0 || p.tags[len(p.tags)-1].Local == "" {
+		return fmt.Errorf("xml: end tag </%s> without start tag", name.Local)
+	}
+	if top := p.tags[len(p.tags)-1]; top != name {
+		if top.Local != name.Local {
+			return fmt.Errorf("xml: end tag </%s> does not match start tag <%s>", name.Local, top.Local)
+		}
+		return fmt.Errorf("xml: end tag </%s> in namespace %s does not match start tag <%s> in namespace %s", name.Local, name.Space, top.Local, top.Space)
+	}
+	p.tags = p.tags[:len(p.tags)-1]
+
+	p.writeIndent(-1)
+	p.WriteByte('<')
+	p.WriteByte('/')
+	p.WriteString(name.Local)
+	p.WriteByte('>')
+	p.popPrefix()
+	return nil
+}
+
+func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) (string, []byte, error) {
+	switch val.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return strconv.FormatInt(val.Int(), 10), nil, nil
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return strconv.FormatUint(val.Uint(), 10), nil, nil
+	case reflect.Float32, reflect.Float64:
+		return strconv.FormatFloat(val.Float(), 'g', -1, val.Type().Bits()), nil, nil
+	case reflect.String:
+		return val.String(), nil, nil
+	case reflect.Bool:
+		return strconv.FormatBool(val.Bool()), nil, nil
+	case reflect.Array:
+		if typ.Elem().Kind() != reflect.Uint8 {
+			break
+		}
+		// [...]byte
+		var bytes []byte
+		if val.CanAddr() {
+			bytes = val.Slice(0, val.Len()).Bytes()
+		} else {
+			bytes = make([]byte, val.Len())
+			reflect.Copy(reflect.ValueOf(bytes), val)
+		}
+		return "", bytes, nil
+	case reflect.Slice:
+		if typ.Elem().Kind() != reflect.Uint8 {
+			break
+		}
+		// []byte
+		return "", val.Bytes(), nil
+	}
+	return "", nil, &UnsupportedTypeError{typ}
+}
+
+var ddBytes = []byte("--")
+
+func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
+	s := parentStack{p: p}
+	for i := range tinfo.fields {
+		finfo := &tinfo.fields[i]
+		if finfo.flags&fAttr != 0 {
+			continue
+		}
+		vf := finfo.value(val)
+
+		// Dereference or skip nil pointer, interface values.
+		switch vf.Kind() {
+		case reflect.Ptr, reflect.Interface:
+			if !vf.IsNil() {
+				vf = vf.Elem()
+			}
+		}
+
+		switch finfo.flags & fMode {
+		case fCharData:
+			if vf.CanInterface() && vf.Type().Implements(textMarshalerType) {
+				data, err := vf.Interface().(encoding.TextMarshaler).MarshalText()
+				if err != nil {
+					return err
+				}
+				Escape(p, data)
+				continue
+			}
+			if vf.CanAddr() {
+				pv := vf.Addr()
+				if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
+					data, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
+					if err != nil {
+						return err
+					}
+					Escape(p, data)
+					continue
+				}
+			}
+			var scratch [64]byte
+			switch vf.Kind() {
+			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+				Escape(p, strconv.AppendInt(scratch[:0], vf.Int(), 10))
+			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+				Escape(p, strconv.AppendUint(scratch[:0], vf.Uint(), 10))
+			case reflect.Float32, reflect.Float64:
+				Escape(p, strconv.AppendFloat(scratch[:0], vf.Float(), 'g', -1, vf.Type().Bits()))
+			case reflect.Bool:
+				Escape(p, strconv.AppendBool(scratch[:0], vf.Bool()))
+			case reflect.String:
+				if err := EscapeText(p, []byte(vf.String())); err != nil {
+					return err
+				}
+			case reflect.Slice:
+				if elem, ok := vf.Interface().([]byte); ok {
+					if err := EscapeText(p, elem); err != nil {
+						return err
+					}
+				}
+			}
+			continue
+
+		case fComment:
+			k := vf.Kind()
+			if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) {
+				return fmt.Errorf("xml: bad type for comment field of %s", val.Type())
+			}
+			if vf.Len() == 0 {
+				continue
+			}
+			p.writeIndent(0)
+			p.WriteString("<!--")
+			dashDash := false
+			dashLast := false
+			switch k {
+			case reflect.String:
+				s := vf.String()
+				dashDash = strings.Index(s, "--") >= 0
+				dashLast = s[len(s)-1] == '-'
+				if !dashDash {
+					p.WriteString(s)
+				}
+			case reflect.Slice:
+				b := vf.Bytes()
+				dashDash = bytes.Index(b, ddBytes) >= 0
+				dashLast = b[len(b)-1] == '-'
+				if !dashDash {
+					p.Write(b)
+				}
+			default:
+				panic("can't happen")
+			}
+			if dashDash {
+				return fmt.Errorf(`xml: comments must not contain "--"`)
+			}
+			if dashLast {
+				// "--->" is invalid grammar. Make it "- -->"
+				p.WriteByte(' ')
+			}
+			p.WriteString("-->")
+			continue
+
+		case fInnerXml:
+			iface := vf.Interface()
+			switch raw := iface.(type) {
+			case []byte:
+				p.Write(raw)
+				continue
+			case string:
+				p.WriteString(raw)
+				continue
+			}
+
+		case fElement, fElement | fAny:
+			if err := s.trim(finfo.parents); err != nil {
+				return err
+			}
+			if len(finfo.parents) > len(s.stack) {
+				if vf.Kind() != reflect.Ptr && vf.Kind() != reflect.Interface || !vf.IsNil() {
+					if err := s.push(finfo.parents[len(s.stack):]); err != nil {
+						return err
+					}
+				}
+			}
+		}
+		if err := p.marshalValue(vf, finfo, nil); err != nil {
+			return err
+		}
+	}
+	s.trim(nil)
+	return p.cachedWriteError()
+}
+
+// return the bufio Writer's cached write error
+func (p *printer) cachedWriteError() error {
+	_, err := p.Write(nil)
+	return err
+}
+
+func (p *printer) writeIndent(depthDelta int) {
+	if len(p.prefix) == 0 && len(p.indent) == 0 {
+		return
+	}
+	if depthDelta < 0 {
+		p.depth--
+		if p.indentedIn {
+			p.indentedIn = false
+			return
+		}
+		p.indentedIn = false
+	}
+	if p.putNewline {
+		p.WriteByte('\n')
+	} else {
+		p.putNewline = true
+	}
+	if len(p.prefix) > 0 {
+		p.WriteString(p.prefix)
+	}
+	if len(p.indent) > 0 {
+		for i := 0; i < p.depth; i++ {
+			p.WriteString(p.indent)
+		}
+	}
+	if depthDelta > 0 {
+		p.depth++
+		p.indentedIn = true
+	}
+}
+
+type parentStack struct {
+	p     *printer
+	stack []string
+}
+
+// trim updates the XML context to match the longest common prefix of the stack
+// and the given parents.  A closing tag will be written for every parent
+// popped.  Passing a zero slice or nil will close all the elements.
+func (s *parentStack) trim(parents []string) error {
+	split := 0
+	for ; split < len(parents) && split < len(s.stack); split++ {
+		if parents[split] != s.stack[split] {
+			break
+		}
+	}
+	for i := len(s.stack) - 1; i >= split; i-- {
+		if err := s.p.writeEnd(Name{Local: s.stack[i]}); err != nil {
+			return err
+		}
+	}
+	s.stack = parents[:split]
+	return nil
+}
+
+// push adds parent elements to the stack and writes open tags.
+func (s *parentStack) push(parents []string) error {
+	for i := 0; i < len(parents); i++ {
+		if err := s.p.writeStart(&StartElement{Name: Name{Local: parents[i]}}); err != nil {
+			return err
+		}
+	}
+	s.stack = append(s.stack, parents...)
+	return nil
+}
+
+// A MarshalXMLError is returned when Marshal encounters a type
+// that cannot be converted into XML.
+type UnsupportedTypeError struct {
+	Type reflect.Type
+}
+
+func (e *UnsupportedTypeError) Error() string {
+	return "xml: unsupported type: " + e.Type.String()
+}
+
+func isEmptyValue(v reflect.Value) bool {
+	switch v.Kind() {
+	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+		return v.Len() == 0
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return v.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.Interface, reflect.Ptr:
+		return v.IsNil()
+	}
+	return false
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/xml/marshal_test.go b/third_party/gofrontend/libgo/go/encoding/xml/marshal_test.go
new file mode 100644
index 0000000..14f73a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/xml/marshal_test.go
@@ -0,0 +1,1266 @@
+// 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.
+
+package xml
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"reflect"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+)
+
+type DriveType int
+
+const (
+	HyperDrive DriveType = iota
+	ImprobabilityDrive
+)
+
+type Passenger struct {
+	Name   []string `xml:"name"`
+	Weight float32  `xml:"weight"`
+}
+
+type Ship struct {
+	XMLName struct{} `xml:"spaceship"`
+
+	Name      string       `xml:"name,attr"`
+	Pilot     string       `xml:"pilot,attr"`
+	Drive     DriveType    `xml:"drive"`
+	Age       uint         `xml:"age"`
+	Passenger []*Passenger `xml:"passenger"`
+	secret    string
+}
+
+type NamedType string
+
+type Port struct {
+	XMLName struct{} `xml:"port"`
+	Type    string   `xml:"type,attr,omitempty"`
+	Comment string   `xml:",comment"`
+	Number  string   `xml:",chardata"`
+}
+
+type Domain struct {
+	XMLName struct{} `xml:"domain"`
+	Country string   `xml:",attr,omitempty"`
+	Name    []byte   `xml:",chardata"`
+	Comment []byte   `xml:",comment"`
+}
+
+type Book struct {
+	XMLName struct{} `xml:"book"`
+	Title   string   `xml:",chardata"`
+}
+
+type Event struct {
+	XMLName struct{} `xml:"event"`
+	Year    int      `xml:",chardata"`
+}
+
+type Movie struct {
+	XMLName struct{} `xml:"movie"`
+	Length  uint     `xml:",chardata"`
+}
+
+type Pi struct {
+	XMLName       struct{} `xml:"pi"`
+	Approximation float32  `xml:",chardata"`
+}
+
+type Universe struct {
+	XMLName struct{} `xml:"universe"`
+	Visible float64  `xml:",chardata"`
+}
+
+type Particle struct {
+	XMLName struct{} `xml:"particle"`
+	HasMass bool     `xml:",chardata"`
+}
+
+type Departure struct {
+	XMLName struct{}  `xml:"departure"`
+	When    time.Time `xml:",chardata"`
+}
+
+type SecretAgent struct {
+	XMLName   struct{} `xml:"agent"`
+	Handle    string   `xml:"handle,attr"`
+	Identity  string
+	Obfuscate string `xml:",innerxml"`
+}
+
+type NestedItems struct {
+	XMLName struct{} `xml:"result"`
+	Items   []string `xml:">item"`
+	Item1   []string `xml:"Items>item1"`
+}
+
+type NestedOrder struct {
+	XMLName struct{} `xml:"result"`
+	Field1  string   `xml:"parent>c"`
+	Field2  string   `xml:"parent>b"`
+	Field3  string   `xml:"parent>a"`
+}
+
+type MixedNested struct {
+	XMLName struct{} `xml:"result"`
+	A       string   `xml:"parent1>a"`
+	B       string   `xml:"b"`
+	C       string   `xml:"parent1>parent2>c"`
+	D       string   `xml:"parent1>d"`
+}
+
+type NilTest struct {
+	A interface{} `xml:"parent1>parent2>a"`
+	B interface{} `xml:"parent1>b"`
+	C interface{} `xml:"parent1>parent2>c"`
+}
+
+type Service struct {
+	XMLName struct{} `xml:"service"`
+	Domain  *Domain  `xml:"host>domain"`
+	Port    *Port    `xml:"host>port"`
+	Extra1  interface{}
+	Extra2  interface{} `xml:"host>extra2"`
+}
+
+var nilStruct *Ship
+
+type EmbedA struct {
+	EmbedC
+	EmbedB EmbedB
+	FieldA string
+}
+
+type EmbedB struct {
+	FieldB string
+	*EmbedC
+}
+
+type EmbedC struct {
+	FieldA1 string `xml:"FieldA>A1"`
+	FieldA2 string `xml:"FieldA>A2"`
+	FieldB  string
+	FieldC  string
+}
+
+type NameCasing struct {
+	XMLName struct{} `xml:"casing"`
+	Xy      string
+	XY      string
+	XyA     string `xml:"Xy,attr"`
+	XYA     string `xml:"XY,attr"`
+}
+
+type NamePrecedence struct {
+	XMLName     Name              `xml:"Parent"`
+	FromTag     XMLNameWithoutTag `xml:"InTag"`
+	FromNameVal XMLNameWithoutTag
+	FromNameTag XMLNameWithTag
+	InFieldName string
+}
+
+type XMLNameWithTag struct {
+	XMLName Name   `xml:"InXMLNameTag"`
+	Value   string `xml:",chardata"`
+}
+
+type XMLNameWithoutTag struct {
+	XMLName Name
+	Value   string `xml:",chardata"`
+}
+
+type NameInField struct {
+	Foo Name `xml:"ns foo"`
+}
+
+type AttrTest struct {
+	Int   int     `xml:",attr"`
+	Named int     `xml:"int,attr"`
+	Float float64 `xml:",attr"`
+	Uint8 uint8   `xml:",attr"`
+	Bool  bool    `xml:",attr"`
+	Str   string  `xml:",attr"`
+	Bytes []byte  `xml:",attr"`
+}
+
+type OmitAttrTest struct {
+	Int   int     `xml:",attr,omitempty"`
+	Named int     `xml:"int,attr,omitempty"`
+	Float float64 `xml:",attr,omitempty"`
+	Uint8 uint8   `xml:",attr,omitempty"`
+	Bool  bool    `xml:",attr,omitempty"`
+	Str   string  `xml:",attr,omitempty"`
+	Bytes []byte  `xml:",attr,omitempty"`
+}
+
+type OmitFieldTest struct {
+	Int   int           `xml:",omitempty"`
+	Named int           `xml:"int,omitempty"`
+	Float float64       `xml:",omitempty"`
+	Uint8 uint8         `xml:",omitempty"`
+	Bool  bool          `xml:",omitempty"`
+	Str   string        `xml:",omitempty"`
+	Bytes []byte        `xml:",omitempty"`
+	Ptr   *PresenceTest `xml:",omitempty"`
+}
+
+type AnyTest struct {
+	XMLName  struct{}  `xml:"a"`
+	Nested   string    `xml:"nested>value"`
+	AnyField AnyHolder `xml:",any"`
+}
+
+type AnyOmitTest struct {
+	XMLName  struct{}   `xml:"a"`
+	Nested   string     `xml:"nested>value"`
+	AnyField *AnyHolder `xml:",any,omitempty"`
+}
+
+type AnySliceTest struct {
+	XMLName  struct{}    `xml:"a"`
+	Nested   string      `xml:"nested>value"`
+	AnyField []AnyHolder `xml:",any"`
+}
+
+type AnyHolder struct {
+	XMLName Name
+	XML     string `xml:",innerxml"`
+}
+
+type RecurseA struct {
+	A string
+	B *RecurseB
+}
+
+type RecurseB struct {
+	A *RecurseA
+	B string
+}
+
+type PresenceTest struct {
+	Exists *struct{}
+}
+
+type IgnoreTest struct {
+	PublicSecret string `xml:"-"`
+}
+
+type MyBytes []byte
+
+type Data struct {
+	Bytes  []byte
+	Attr   []byte `xml:",attr"`
+	Custom MyBytes
+}
+
+type Plain struct {
+	V interface{}
+}
+
+type MyInt int
+
+type EmbedInt struct {
+	MyInt
+}
+
+type Strings struct {
+	X []string `xml:"A>B,omitempty"`
+}
+
+type PointerFieldsTest struct {
+	XMLName  Name    `xml:"dummy"`
+	Name     *string `xml:"name,attr"`
+	Age      *uint   `xml:"age,attr"`
+	Empty    *string `xml:"empty,attr"`
+	Contents *string `xml:",chardata"`
+}
+
+type ChardataEmptyTest struct {
+	XMLName  Name    `xml:"test"`
+	Contents *string `xml:",chardata"`
+}
+
+type MyMarshalerTest struct {
+}
+
+var _ Marshaler = (*MyMarshalerTest)(nil)
+
+func (m *MyMarshalerTest) MarshalXML(e *Encoder, start StartElement) error {
+	e.EncodeToken(start)
+	e.EncodeToken(CharData([]byte("hello world")))
+	e.EncodeToken(EndElement{start.Name})
+	return nil
+}
+
+type MyMarshalerAttrTest struct {
+}
+
+var _ MarshalerAttr = (*MyMarshalerAttrTest)(nil)
+
+func (m *MyMarshalerAttrTest) MarshalXMLAttr(name Name) (Attr, error) {
+	return Attr{name, "hello world"}, nil
+}
+
+type MarshalerStruct struct {
+	Foo MyMarshalerAttrTest `xml:",attr"`
+}
+
+type InnerStruct struct {
+	XMLName Name `xml:"testns outer"`
+}
+
+type OuterStruct struct {
+	InnerStruct
+	IntAttr int `xml:"int,attr"`
+}
+
+type OuterNamedStruct struct {
+	InnerStruct
+	XMLName Name `xml:"outerns test"`
+	IntAttr int  `xml:"int,attr"`
+}
+
+type OuterNamedOrderedStruct struct {
+	XMLName Name `xml:"outerns test"`
+	InnerStruct
+	IntAttr int `xml:"int,attr"`
+}
+
+type OuterOuterStruct struct {
+	OuterStruct
+}
+
+func ifaceptr(x interface{}) interface{} {
+	return &x
+}
+
+var (
+	nameAttr     = "Sarah"
+	ageAttr      = uint(12)
+	contentsAttr = "lorem ipsum"
+)
+
+// Unless explicitly stated as such (or *Plain), all of the
+// tests below are two-way tests. When introducing new tests,
+// please try to make them two-way as well to ensure that
+// marshalling and unmarshalling are as symmetrical as feasible.
+var marshalTests = []struct {
+	Value         interface{}
+	ExpectXML     string
+	MarshalOnly   bool
+	UnmarshalOnly bool
+}{
+	// Test nil marshals to nothing
+	{Value: nil, ExpectXML: ``, MarshalOnly: true},
+	{Value: nilStruct, ExpectXML: ``, MarshalOnly: true},
+
+	// Test value types
+	{Value: &Plain{true}, ExpectXML: `<Plain><V>true</V></Plain>`},
+	{Value: &Plain{false}, ExpectXML: `<Plain><V>false</V></Plain>`},
+	{Value: &Plain{int(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{int8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{int16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{int32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{uint(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{uint8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{uint16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{uint32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{float32(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},
+	{Value: &Plain{float64(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},
+	{Value: &Plain{uintptr(0xFFDD)}, ExpectXML: `<Plain><V>65501</V></Plain>`},
+	{Value: &Plain{"gopher"}, ExpectXML: `<Plain><V>gopher</V></Plain>`},
+	{Value: &Plain{[]byte("gopher")}, ExpectXML: `<Plain><V>gopher</V></Plain>`},
+	{Value: &Plain{"</>"}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
+	{Value: &Plain{[]byte("</>")}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
+	{Value: &Plain{[3]byte{'<', '/', '>'}}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
+	{Value: &Plain{NamedType("potato")}, ExpectXML: `<Plain><V>potato</V></Plain>`},
+	{Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+	{Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+	{Value: ifaceptr(true), MarshalOnly: true, ExpectXML: `<bool>true</bool>`},
+
+	// Test time.
+	{
+		Value:     &Plain{time.Unix(1e9, 123456789).UTC()},
+		ExpectXML: `<Plain><V>2001-09-09T01:46:40.123456789Z</V></Plain>`,
+	},
+
+	// A pointer to struct{} may be used to test for an element's presence.
+	{
+		Value:     &PresenceTest{new(struct{})},
+		ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
+	},
+	{
+		Value:     &PresenceTest{},
+		ExpectXML: `<PresenceTest></PresenceTest>`,
+	},
+
+	// A pointer to struct{} may be used to test for an element's presence.
+	{
+		Value:     &PresenceTest{new(struct{})},
+		ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
+	},
+	{
+		Value:     &PresenceTest{},
+		ExpectXML: `<PresenceTest></PresenceTest>`,
+	},
+
+	// A []byte field is only nil if the element was not found.
+	{
+		Value:         &Data{},
+		ExpectXML:     `<Data></Data>`,
+		UnmarshalOnly: true,
+	},
+	{
+		Value:         &Data{Bytes: []byte{}, Custom: MyBytes{}, Attr: []byte{}},
+		ExpectXML:     `<Data Attr=""><Bytes></Bytes><Custom></Custom></Data>`,
+		UnmarshalOnly: true,
+	},
+
+	// Check that []byte works, including named []byte types.
+	{
+		Value:     &Data{Bytes: []byte("ab"), Custom: MyBytes("cd"), Attr: []byte{'v'}},
+		ExpectXML: `<Data Attr="v"><Bytes>ab</Bytes><Custom>cd</Custom></Data>`,
+	},
+
+	// Test innerxml
+	{
+		Value: &SecretAgent{
+			Handle:    "007",
+			Identity:  "James Bond",
+			Obfuscate: "<redacted/>",
+		},
+		ExpectXML:   `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
+		MarshalOnly: true,
+	},
+	{
+		Value: &SecretAgent{
+			Handle:    "007",
+			Identity:  "James Bond",
+			Obfuscate: "<Identity>James Bond</Identity><redacted/>",
+		},
+		ExpectXML:     `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
+		UnmarshalOnly: true,
+	},
+
+	// Test structs
+	{Value: &Port{Type: "ssl", Number: "443"}, ExpectXML: `<port type="ssl">443</port>`},
+	{Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`},
+	{Value: &Port{Type: "<unix>"}, ExpectXML: `<port type="&lt;unix&gt;"></port>`},
+	{Value: &Port{Number: "443", Comment: "https"}, ExpectXML: `<port><!--https-->443</port>`},
+	{Value: &Port{Number: "443", Comment: "add space-"}, ExpectXML: `<port><!--add space- -->443</port>`, MarshalOnly: true},
+	{Value: &Domain{Name: []byte("google.com&friends")}, ExpectXML: `<domain>google.com&amp;friends</domain>`},
+	{Value: &Domain{Name: []byte("google.com"), Comment: []byte(" &friends ")}, ExpectXML: `<domain>google.com<!-- &friends --></domain>`},
+	{Value: &Book{Title: "Pride & Prejudice"}, ExpectXML: `<book>Pride &amp; Prejudice</book>`},
+	{Value: &Event{Year: -3114}, ExpectXML: `<event>-3114</event>`},
+	{Value: &Movie{Length: 13440}, ExpectXML: `<movie>13440</movie>`},
+	{Value: &Pi{Approximation: 3.14159265}, ExpectXML: `<pi>3.1415927</pi>`},
+	{Value: &Universe{Visible: 9.3e13}, ExpectXML: `<universe>9.3e+13</universe>`},
+	{Value: &Particle{HasMass: true}, ExpectXML: `<particle>true</particle>`},
+	{Value: &Departure{When: ParseTime("2013-01-09T00:15:00-09:00")}, ExpectXML: `<departure>2013-01-09T00:15:00-09:00</departure>`},
+	{Value: atomValue, ExpectXML: atomXml},
+	{
+		Value: &Ship{
+			Name:  "Heart of Gold",
+			Pilot: "Computer",
+			Age:   1,
+			Drive: ImprobabilityDrive,
+			Passenger: []*Passenger{
+				{
+					Name:   []string{"Zaphod", "Beeblebrox"},
+					Weight: 7.25,
+				},
+				{
+					Name:   []string{"Trisha", "McMillen"},
+					Weight: 5.5,
+				},
+				{
+					Name:   []string{"Ford", "Prefect"},
+					Weight: 7,
+				},
+				{
+					Name:   []string{"Arthur", "Dent"},
+					Weight: 6.75,
+				},
+			},
+		},
+		ExpectXML: `<spaceship name="Heart of Gold" pilot="Computer">` +
+			`<drive>` + strconv.Itoa(int(ImprobabilityDrive)) + `</drive>` +
+			`<age>1</age>` +
+			`<passenger>` +
+			`<name>Zaphod</name>` +
+			`<name>Beeblebrox</name>` +
+			`<weight>7.25</weight>` +
+			`</passenger>` +
+			`<passenger>` +
+			`<name>Trisha</name>` +
+			`<name>McMillen</name>` +
+			`<weight>5.5</weight>` +
+			`</passenger>` +
+			`<passenger>` +
+			`<name>Ford</name>` +
+			`<name>Prefect</name>` +
+			`<weight>7</weight>` +
+			`</passenger>` +
+			`<passenger>` +
+			`<name>Arthur</name>` +
+			`<name>Dent</name>` +
+			`<weight>6.75</weight>` +
+			`</passenger>` +
+			`</spaceship>`,
+	},
+
+	// Test a>b
+	{
+		Value: &NestedItems{Items: nil, Item1: nil},
+		ExpectXML: `<result>` +
+			`<Items>` +
+			`</Items>` +
+			`</result>`,
+	},
+	{
+		Value: &NestedItems{Items: []string{}, Item1: []string{}},
+		ExpectXML: `<result>` +
+			`<Items>` +
+			`</Items>` +
+			`</result>`,
+		MarshalOnly: true,
+	},
+	{
+		Value: &NestedItems{Items: nil, Item1: []string{"A"}},
+		ExpectXML: `<result>` +
+			`<Items>` +
+			`<item1>A</item1>` +
+			`</Items>` +
+			`</result>`,
+	},
+	{
+		Value: &NestedItems{Items: []string{"A", "B"}, Item1: nil},
+		ExpectXML: `<result>` +
+			`<Items>` +
+			`<item>A</item>` +
+			`<item>B</item>` +
+			`</Items>` +
+			`</result>`,
+	},
+	{
+		Value: &NestedItems{Items: []string{"A", "B"}, Item1: []string{"C"}},
+		ExpectXML: `<result>` +
+			`<Items>` +
+			`<item>A</item>` +
+			`<item>B</item>` +
+			`<item1>C</item1>` +
+			`</Items>` +
+			`</result>`,
+	},
+	{
+		Value: &NestedOrder{Field1: "C", Field2: "B", Field3: "A"},
+		ExpectXML: `<result>` +
+			`<parent>` +
+			`<c>C</c>` +
+			`<b>B</b>` +
+			`<a>A</a>` +
+			`</parent>` +
+			`</result>`,
+	},
+	{
+		Value: &NilTest{A: "A", B: nil, C: "C"},
+		ExpectXML: `<NilTest>` +
+			`<parent1>` +
+			`<parent2><a>A</a></parent2>` +
+			`<parent2><c>C</c></parent2>` +
+			`</parent1>` +
+			`</NilTest>`,
+		MarshalOnly: true, // Uses interface{}
+	},
+	{
+		Value: &MixedNested{A: "A", B: "B", C: "C", D: "D"},
+		ExpectXML: `<result>` +
+			`<parent1><a>A</a></parent1>` +
+			`<b>B</b>` +
+			`<parent1>` +
+			`<parent2><c>C</c></parent2>` +
+			`<d>D</d>` +
+			`</parent1>` +
+			`</result>`,
+	},
+	{
+		Value:     &Service{Port: &Port{Number: "80"}},
+		ExpectXML: `<service><host><port>80</port></host></service>`,
+	},
+	{
+		Value:     &Service{},
+		ExpectXML: `<service></service>`,
+	},
+	{
+		Value: &Service{Port: &Port{Number: "80"}, Extra1: "A", Extra2: "B"},
+		ExpectXML: `<service>` +
+			`<host><port>80</port></host>` +
+			`<Extra1>A</Extra1>` +
+			`<host><extra2>B</extra2></host>` +
+			`</service>`,
+		MarshalOnly: true,
+	},
+	{
+		Value: &Service{Port: &Port{Number: "80"}, Extra2: "example"},
+		ExpectXML: `<service>` +
+			`<host><port>80</port></host>` +
+			`<host><extra2>example</extra2></host>` +
+			`</service>`,
+		MarshalOnly: true,
+	},
+
+	// Test struct embedding
+	{
+		Value: &EmbedA{
+			EmbedC: EmbedC{
+				FieldA1: "", // Shadowed by A.A
+				FieldA2: "", // Shadowed by A.A
+				FieldB:  "A.C.B",
+				FieldC:  "A.C.C",
+			},
+			EmbedB: EmbedB{
+				FieldB: "A.B.B",
+				EmbedC: &EmbedC{
+					FieldA1: "A.B.C.A1",
+					FieldA2: "A.B.C.A2",
+					FieldB:  "", // Shadowed by A.B.B
+					FieldC:  "A.B.C.C",
+				},
+			},
+			FieldA: "A.A",
+		},
+		ExpectXML: `<EmbedA>` +
+			`<FieldB>A.C.B</FieldB>` +
+			`<FieldC>A.C.C</FieldC>` +
+			`<EmbedB>` +
+			`<FieldB>A.B.B</FieldB>` +
+			`<FieldA>` +
+			`<A1>A.B.C.A1</A1>` +
+			`<A2>A.B.C.A2</A2>` +
+			`</FieldA>` +
+			`<FieldC>A.B.C.C</FieldC>` +
+			`</EmbedB>` +
+			`<FieldA>A.A</FieldA>` +
+			`</EmbedA>`,
+	},
+
+	// Test that name casing matters
+	{
+		Value:     &NameCasing{Xy: "mixed", XY: "upper", XyA: "mixedA", XYA: "upperA"},
+		ExpectXML: `<casing Xy="mixedA" XY="upperA"><Xy>mixed</Xy><XY>upper</XY></casing>`,
+	},
+
+	// Test the order in which the XML element name is chosen
+	{
+		Value: &NamePrecedence{
+			FromTag:     XMLNameWithoutTag{Value: "A"},
+			FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "InXMLName"}, Value: "B"},
+			FromNameTag: XMLNameWithTag{Value: "C"},
+			InFieldName: "D",
+		},
+		ExpectXML: `<Parent>` +
+			`<InTag>A</InTag>` +
+			`<InXMLName>B</InXMLName>` +
+			`<InXMLNameTag>C</InXMLNameTag>` +
+			`<InFieldName>D</InFieldName>` +
+			`</Parent>`,
+		MarshalOnly: true,
+	},
+	{
+		Value: &NamePrecedence{
+			XMLName:     Name{Local: "Parent"},
+			FromTag:     XMLNameWithoutTag{XMLName: Name{Local: "InTag"}, Value: "A"},
+			FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "FromNameVal"}, Value: "B"},
+			FromNameTag: XMLNameWithTag{XMLName: Name{Local: "InXMLNameTag"}, Value: "C"},
+			InFieldName: "D",
+		},
+		ExpectXML: `<Parent>` +
+			`<InTag>A</InTag>` +
+			`<FromNameVal>B</FromNameVal>` +
+			`<InXMLNameTag>C</InXMLNameTag>` +
+			`<InFieldName>D</InFieldName>` +
+			`</Parent>`,
+		UnmarshalOnly: true,
+	},
+
+	// xml.Name works in a plain field as well.
+	{
+		Value:     &NameInField{Name{Space: "ns", Local: "foo"}},
+		ExpectXML: `<NameInField><foo xmlns="ns"></foo></NameInField>`,
+	},
+	{
+		Value:         &NameInField{Name{Space: "ns", Local: "foo"}},
+		ExpectXML:     `<NameInField><foo xmlns="ns"><ignore></ignore></foo></NameInField>`,
+		UnmarshalOnly: true,
+	},
+
+	// Marshaling zero xml.Name uses the tag or field name.
+	{
+		Value:       &NameInField{},
+		ExpectXML:   `<NameInField><foo xmlns="ns"></foo></NameInField>`,
+		MarshalOnly: true,
+	},
+
+	// Test attributes
+	{
+		Value: &AttrTest{
+			Int:   8,
+			Named: 9,
+			Float: 23.5,
+			Uint8: 255,
+			Bool:  true,
+			Str:   "str",
+			Bytes: []byte("byt"),
+		},
+		ExpectXML: `<AttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
+			` Bool="true" Str="str" Bytes="byt"></AttrTest>`,
+	},
+	{
+		Value: &AttrTest{Bytes: []byte{}},
+		ExpectXML: `<AttrTest Int="0" int="0" Float="0" Uint8="0"` +
+			` Bool="false" Str="" Bytes=""></AttrTest>`,
+	},
+	{
+		Value: &OmitAttrTest{
+			Int:   8,
+			Named: 9,
+			Float: 23.5,
+			Uint8: 255,
+			Bool:  true,
+			Str:   "str",
+			Bytes: []byte("byt"),
+		},
+		ExpectXML: `<OmitAttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
+			` Bool="true" Str="str" Bytes="byt"></OmitAttrTest>`,
+	},
+	{
+		Value:     &OmitAttrTest{},
+		ExpectXML: `<OmitAttrTest></OmitAttrTest>`,
+	},
+
+	// pointer fields
+	{
+		Value:       &PointerFieldsTest{Name: &nameAttr, Age: &ageAttr, Contents: &contentsAttr},
+		ExpectXML:   `<dummy name="Sarah" age="12">lorem ipsum</dummy>`,
+		MarshalOnly: true,
+	},
+
+	// empty chardata pointer field
+	{
+		Value:       &ChardataEmptyTest{},
+		ExpectXML:   `<test></test>`,
+		MarshalOnly: true,
+	},
+
+	// omitempty on fields
+	{
+		Value: &OmitFieldTest{
+			Int:   8,
+			Named: 9,
+			Float: 23.5,
+			Uint8: 255,
+			Bool:  true,
+			Str:   "str",
+			Bytes: []byte("byt"),
+			Ptr:   &PresenceTest{},
+		},
+		ExpectXML: `<OmitFieldTest>` +
+			`<Int>8</Int>` +
+			`<int>9</int>` +
+			`<Float>23.5</Float>` +
+			`<Uint8>255</Uint8>` +
+			`<Bool>true</Bool>` +
+			`<Str>str</Str>` +
+			`<Bytes>byt</Bytes>` +
+			`<Ptr></Ptr>` +
+			`</OmitFieldTest>`,
+	},
+	{
+		Value:     &OmitFieldTest{},
+		ExpectXML: `<OmitFieldTest></OmitFieldTest>`,
+	},
+
+	// Test ",any"
+	{
+		ExpectXML: `<a><nested><value>known</value></nested><other><sub>unknown</sub></other></a>`,
+		Value: &AnyTest{
+			Nested: "known",
+			AnyField: AnyHolder{
+				XMLName: Name{Local: "other"},
+				XML:     "<sub>unknown</sub>",
+			},
+		},
+	},
+	{
+		Value: &AnyTest{Nested: "known",
+			AnyField: AnyHolder{
+				XML:     "<unknown/>",
+				XMLName: Name{Local: "AnyField"},
+			},
+		},
+		ExpectXML: `<a><nested><value>known</value></nested><AnyField><unknown/></AnyField></a>`,
+	},
+	{
+		ExpectXML: `<a><nested><value>b</value></nested></a>`,
+		Value: &AnyOmitTest{
+			Nested: "b",
+		},
+	},
+	{
+		ExpectXML: `<a><nested><value>b</value></nested><c><d>e</d></c><g xmlns="f"><h>i</h></g></a>`,
+		Value: &AnySliceTest{
+			Nested: "b",
+			AnyField: []AnyHolder{
+				{
+					XMLName: Name{Local: "c"},
+					XML:     "<d>e</d>",
+				},
+				{
+					XMLName: Name{Space: "f", Local: "g"},
+					XML:     "<h>i</h>",
+				},
+			},
+		},
+	},
+	{
+		ExpectXML: `<a><nested><value>b</value></nested></a>`,
+		Value: &AnySliceTest{
+			Nested: "b",
+		},
+	},
+
+	// Test recursive types.
+	{
+		Value: &RecurseA{
+			A: "a1",
+			B: &RecurseB{
+				A: &RecurseA{"a2", nil},
+				B: "b1",
+			},
+		},
+		ExpectXML: `<RecurseA><A>a1</A><B><A><A>a2</A></A><B>b1</B></B></RecurseA>`,
+	},
+
+	// Test ignoring fields via "-" tag
+	{
+		ExpectXML: `<IgnoreTest></IgnoreTest>`,
+		Value:     &IgnoreTest{},
+	},
+	{
+		ExpectXML:   `<IgnoreTest></IgnoreTest>`,
+		Value:       &IgnoreTest{PublicSecret: "can't tell"},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IgnoreTest><PublicSecret>ignore me</PublicSecret></IgnoreTest>`,
+		Value:         &IgnoreTest{},
+		UnmarshalOnly: true,
+	},
+
+	// Test escaping.
+	{
+		ExpectXML: `<a><nested><value>dquote: &#34;; squote: &#39;; ampersand: &amp;; less: &lt;; greater: &gt;;</value></nested><empty></empty></a>`,
+		Value: &AnyTest{
+			Nested:   `dquote: "; squote: '; ampersand: &; less: <; greater: >;`,
+			AnyField: AnyHolder{XMLName: Name{Local: "empty"}},
+		},
+	},
+	{
+		ExpectXML: `<a><nested><value>newline: &#xA;; cr: &#xD;; tab: &#x9;;</value></nested><AnyField></AnyField></a>`,
+		Value: &AnyTest{
+			Nested:   "newline: \n; cr: \r; tab: \t;",
+			AnyField: AnyHolder{XMLName: Name{Local: "AnyField"}},
+		},
+	},
+	{
+		ExpectXML: "<a><nested><value>1\r2\r\n3\n\r4\n5</value></nested></a>",
+		Value: &AnyTest{
+			Nested: "1\n2\n3\n\n4\n5",
+		},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<EmbedInt><MyInt>42</MyInt></EmbedInt>`,
+		Value: &EmbedInt{
+			MyInt: 42,
+		},
+	},
+	// Test omitempty with parent chain; see golang.org/issue/4168.
+	{
+		ExpectXML: `<Strings><A></A></Strings>`,
+		Value:     &Strings{},
+	},
+	// Custom marshalers.
+	{
+		ExpectXML: `<MyMarshalerTest>hello world</MyMarshalerTest>`,
+		Value:     &MyMarshalerTest{},
+	},
+	{
+		ExpectXML: `<MarshalerStruct Foo="hello world"></MarshalerStruct>`,
+		Value:     &MarshalerStruct{},
+	},
+	{
+		ExpectXML: `<outer xmlns="testns" int="10"></outer>`,
+		Value:     &OuterStruct{IntAttr: 10},
+	},
+	{
+		ExpectXML: `<test xmlns="outerns" int="10"></test>`,
+		Value:     &OuterNamedStruct{XMLName: Name{Space: "outerns", Local: "test"}, IntAttr: 10},
+	},
+	{
+		ExpectXML: `<test xmlns="outerns" int="10"></test>`,
+		Value:     &OuterNamedOrderedStruct{XMLName: Name{Space: "outerns", Local: "test"}, IntAttr: 10},
+	},
+	{
+		ExpectXML: `<outer xmlns="testns" int="10"></outer>`,
+		Value:     &OuterOuterStruct{OuterStruct{IntAttr: 10}},
+	},
+}
+
+func TestMarshal(t *testing.T) {
+	for idx, test := range marshalTests {
+		if test.UnmarshalOnly {
+			continue
+		}
+		data, err := Marshal(test.Value)
+		if err != nil {
+			t.Errorf("#%d: Error: %s", idx, err)
+			continue
+		}
+		if got, want := string(data), test.ExpectXML; got != want {
+			if strings.Contains(want, "\n") {
+				t.Errorf("#%d: marshal(%#v):\nHAVE:\n%s\nWANT:\n%s", idx, test.Value, got, want)
+			} else {
+				t.Errorf("#%d: marshal(%#v):\nhave %#q\nwant %#q", idx, test.Value, got, want)
+			}
+		}
+	}
+}
+
+type AttrParent struct {
+	X string `xml:"X>Y,attr"`
+}
+
+type BadAttr struct {
+	Name []string `xml:"name,attr"`
+}
+
+var marshalErrorTests = []struct {
+	Value interface{}
+	Err   string
+	Kind  reflect.Kind
+}{
+	{
+		Value: make(chan bool),
+		Err:   "xml: unsupported type: chan bool",
+		Kind:  reflect.Chan,
+	},
+	{
+		Value: map[string]string{
+			"question": "What do you get when you multiply six by nine?",
+			"answer":   "42",
+		},
+		Err:  "xml: unsupported type: map[string]string",
+		Kind: reflect.Map,
+	},
+	{
+		Value: map[*Ship]bool{nil: false},
+		Err:   "xml: unsupported type: map[*xml.Ship]bool",
+		Kind:  reflect.Map,
+	},
+	{
+		Value: &Domain{Comment: []byte("f--bar")},
+		Err:   `xml: comments must not contain "--"`,
+	},
+	// Reject parent chain with attr, never worked; see golang.org/issue/5033.
+	{
+		Value: &AttrParent{},
+		Err:   `xml: X>Y chain not valid with attr flag`,
+	},
+	{
+		Value: BadAttr{[]string{"X", "Y"}},
+		Err:   `xml: unsupported type: []string`,
+	},
+}
+
+var marshalIndentTests = []struct {
+	Value     interface{}
+	Prefix    string
+	Indent    string
+	ExpectXML string
+}{
+	{
+		Value: &SecretAgent{
+			Handle:    "007",
+			Identity:  "James Bond",
+			Obfuscate: "<redacted/>",
+		},
+		Prefix:    "",
+		Indent:    "\t",
+		ExpectXML: fmt.Sprintf("<agent handle=\"007\">\n\t<Identity>James Bond</Identity><redacted/>\n</agent>"),
+	},
+}
+
+func TestMarshalErrors(t *testing.T) {
+	for idx, test := range marshalErrorTests {
+		data, err := Marshal(test.Value)
+		if err == nil {
+			t.Errorf("#%d: marshal(%#v) = [success] %q, want error %v", idx, test.Value, data, test.Err)
+			continue
+		}
+		if err.Error() != test.Err {
+			t.Errorf("#%d: marshal(%#v) = [error] %v, want %v", idx, test.Value, err, test.Err)
+		}
+		if test.Kind != reflect.Invalid {
+			if kind := err.(*UnsupportedTypeError).Type.Kind(); kind != test.Kind {
+				t.Errorf("#%d: marshal(%#v) = [error kind] %s, want %s", idx, test.Value, kind, test.Kind)
+			}
+		}
+	}
+}
+
+// Do invertibility testing on the various structures that we test
+func TestUnmarshal(t *testing.T) {
+	for i, test := range marshalTests {
+		if test.MarshalOnly {
+			continue
+		}
+		if _, ok := test.Value.(*Plain); ok {
+			continue
+		}
+
+		vt := reflect.TypeOf(test.Value)
+		dest := reflect.New(vt.Elem()).Interface()
+		err := Unmarshal([]byte(test.ExpectXML), dest)
+
+		switch fix := dest.(type) {
+		case *Feed:
+			fix.Author.InnerXML = ""
+			for i := range fix.Entry {
+				fix.Entry[i].Author.InnerXML = ""
+			}
+		}
+
+		if err != nil {
+			t.Errorf("#%d: unexpected error: %#v", i, err)
+		} else if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {
+			t.Errorf("#%d: unmarshal(%q):\nhave %#v\nwant %#v", i, test.ExpectXML, got, want)
+		}
+	}
+}
+
+func TestMarshalIndent(t *testing.T) {
+	for i, test := range marshalIndentTests {
+		data, err := MarshalIndent(test.Value, test.Prefix, test.Indent)
+		if err != nil {
+			t.Errorf("#%d: Error: %s", i, err)
+			continue
+		}
+		if got, want := string(data), test.ExpectXML; got != want {
+			t.Errorf("#%d: MarshalIndent:\nGot:%s\nWant:\n%s", i, got, want)
+		}
+	}
+}
+
+type limitedBytesWriter struct {
+	w      io.Writer
+	remain int // until writes fail
+}
+
+func (lw *limitedBytesWriter) Write(p []byte) (n int, err error) {
+	if lw.remain <= 0 {
+		println("error")
+		return 0, errors.New("write limit hit")
+	}
+	if len(p) > lw.remain {
+		p = p[:lw.remain]
+		n, _ = lw.w.Write(p)
+		lw.remain = 0
+		return n, errors.New("write limit hit")
+	}
+	n, err = lw.w.Write(p)
+	lw.remain -= n
+	return n, err
+}
+
+func TestMarshalWriteErrors(t *testing.T) {
+	var buf bytes.Buffer
+	const writeCap = 1024
+	w := &limitedBytesWriter{&buf, writeCap}
+	enc := NewEncoder(w)
+	var err error
+	var i int
+	const n = 4000
+	for i = 1; i <= n; i++ {
+		err = enc.Encode(&Passenger{
+			Name:   []string{"Alice", "Bob"},
+			Weight: 5,
+		})
+		if err != nil {
+			break
+		}
+	}
+	if err == nil {
+		t.Error("expected an error")
+	}
+	if i == n {
+		t.Errorf("expected to fail before the end")
+	}
+	if buf.Len() != writeCap {
+		t.Errorf("buf.Len() = %d; want %d", buf.Len(), writeCap)
+	}
+}
+
+func TestMarshalWriteIOErrors(t *testing.T) {
+	enc := NewEncoder(errWriter{})
+
+	expectErr := "unwritable"
+	err := enc.Encode(&Passenger{})
+	if err == nil || err.Error() != expectErr {
+		t.Errorf("EscapeTest = [error] %v, want %v", err, expectErr)
+	}
+}
+
+func TestMarshalFlush(t *testing.T) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	if err := enc.EncodeToken(CharData("hello world")); err != nil {
+		t.Fatalf("enc.EncodeToken: %v", err)
+	}
+	if buf.Len() > 0 {
+		t.Fatalf("enc.EncodeToken caused actual write: %q", buf.Bytes())
+	}
+	if err := enc.Flush(); err != nil {
+		t.Fatalf("enc.Flush: %v", err)
+	}
+	if buf.String() != "hello world" {
+		t.Fatalf("after enc.Flush, buf.String() = %q, want %q", buf.String(), "hello world")
+	}
+}
+
+func BenchmarkMarshal(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Marshal(atomValue)
+	}
+}
+
+func BenchmarkUnmarshal(b *testing.B) {
+	xml := []byte(atomXml)
+	for i := 0; i < b.N; i++ {
+		Unmarshal(xml, &Feed{})
+	}
+}
+
+// golang.org/issue/6556
+func TestStructPointerMarshal(t *testing.T) {
+	type A struct {
+		XMLName string `xml:"a"`
+		B       []interface{}
+	}
+	type C struct {
+		XMLName Name
+		Value   string `xml:"value"`
+	}
+
+	a := new(A)
+	a.B = append(a.B, &C{
+		XMLName: Name{Local: "c"},
+		Value:   "x",
+	})
+
+	b, err := Marshal(a)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if x := string(b); x != "<a><c><value>x</value></c></a>" {
+		t.Fatal(x)
+	}
+	var v A
+	err = Unmarshal(b, &v)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+var encodeTokenTests = []struct {
+	tok  Token
+	want string
+	ok   bool
+}{
+	{StartElement{Name{"space", "local"}, nil}, "<local xmlns=\"space\">", true},
+	{StartElement{Name{"space", ""}, nil}, "", false},
+	{EndElement{Name{"space", ""}}, "", false},
+	{CharData("foo"), "foo", true},
+	{Comment("foo"), "<!--foo-->", true},
+	{Comment("foo-->"), "", false},
+	{ProcInst{"Target", []byte("Instruction")}, "<?Target Instruction?>", true},
+	{ProcInst{"", []byte("Instruction")}, "", false},
+	{ProcInst{"Target", []byte("Instruction?>")}, "", false},
+	{Directive("foo"), "<!foo>", true},
+	{Directive("foo>"), "", false},
+}
+
+func TestEncodeToken(t *testing.T) {
+	for _, tt := range encodeTokenTests {
+		var buf bytes.Buffer
+		enc := NewEncoder(&buf)
+		err := enc.EncodeToken(tt.tok)
+		switch {
+		case !tt.ok && err == nil:
+			t.Errorf("enc.EncodeToken(%#v): expected error; got none", tt.tok)
+		case tt.ok && err != nil:
+			t.Fatalf("enc.EncodeToken: %v", err)
+		case !tt.ok && err != nil:
+			// expected error, got one
+		}
+		if err := enc.Flush(); err != nil {
+			t.Fatalf("enc.EncodeToken: %v", err)
+		}
+		if got := buf.String(); got != tt.want {
+			t.Errorf("enc.EncodeToken = %s; want: %s", got, tt.want)
+		}
+	}
+}
+
+func TestProcInstEncodeToken(t *testing.T) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+
+	if err := enc.EncodeToken(ProcInst{"xml", []byte("Instruction")}); err != nil {
+		t.Fatalf("enc.EncodeToken: expected to be able to encode xml target ProcInst as first token, %s", err)
+	}
+
+	if err := enc.EncodeToken(ProcInst{"Target", []byte("Instruction")}); err != nil {
+		t.Fatalf("enc.EncodeToken: expected to be able to add non-xml target ProcInst")
+	}
+
+	if err := enc.EncodeToken(ProcInst{"xml", []byte("Instruction")}); err == nil {
+		t.Fatalf("enc.EncodeToken: expected to not be allowed to encode xml target ProcInst when not first token")
+	}
+}
+
+func TestDecodeEncode(t *testing.T) {
+	var in, out bytes.Buffer
+	in.WriteString(`<?xml version="1.0" encoding="UTF-8"?>
+<?Target Instruction?>
+<root>
+</root>	
+`)
+	dec := NewDecoder(&in)
+	enc := NewEncoder(&out)
+	for tok, err := dec.Token(); err == nil; tok, err = dec.Token() {
+		err = enc.EncodeToken(tok)
+		if err != nil {
+			t.Fatalf("enc.EncodeToken: Unable to encode token (%#v), %v", tok, err)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/xml/read.go b/third_party/gofrontend/libgo/go/encoding/xml/read.go
new file mode 100644
index 0000000..75b9f2b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/xml/read.go
@@ -0,0 +1,692 @@
+// 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 xml
+
+import (
+	"bytes"
+	"encoding"
+	"errors"
+	"fmt"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+// BUG(rsc): Mapping between XML elements and data structures is inherently flawed:
+// an XML element is an order-dependent collection of anonymous
+// values, while a data structure is an order-independent collection
+// of named values.
+// See package json for a textual representation more suitable
+// to data structures.
+
+// Unmarshal parses the XML-encoded data and stores the result in
+// the value pointed to by v, which must be an arbitrary struct,
+// slice, or string. Well-formed data that does not fit into v is
+// discarded.
+//
+// Because Unmarshal uses the reflect package, it can only assign
+// to exported (upper case) fields.  Unmarshal uses a case-sensitive
+// comparison to match XML element names to tag values and struct
+// field names.
+//
+// Unmarshal maps an XML element to a struct using the following rules.
+// In the rules, the tag of a field refers to the value associated with the
+// key 'xml' in the struct field's tag (see the example above).
+//
+//   * If the struct has a field of type []byte or string with tag
+//      ",innerxml", Unmarshal accumulates the raw XML nested inside the
+//      element in that field.  The rest of the rules still apply.
+//
+//   * If the struct has a field named XMLName of type xml.Name,
+//      Unmarshal records the element name in that field.
+//
+//   * If the XMLName field has an associated tag of the form
+//      "name" or "namespace-URL name", the XML element must have
+//      the given name (and, optionally, name space) or else Unmarshal
+//      returns an error.
+//
+//   * If the XML element has an attribute whose name matches a
+//      struct field name with an associated tag containing ",attr" or
+//      the explicit name in a struct field tag of the form "name,attr",
+//      Unmarshal records the attribute value in that field.
+//
+//   * If the XML element contains character data, that data is
+//      accumulated in the first struct field that has tag ",chardata".
+//      The struct field may have type []byte or string.
+//      If there is no such field, the character data is discarded.
+//
+//   * If the XML element contains comments, they are accumulated in
+//      the first struct field that has tag ",comment".  The struct
+//      field may have type []byte or string.  If there is no such
+//      field, the comments are discarded.
+//
+//   * If the XML element contains a sub-element whose name matches
+//      the prefix of a tag formatted as "a" or "a>b>c", unmarshal
+//      will descend into the XML structure looking for elements with the
+//      given names, and will map the innermost elements to that struct
+//      field. A tag starting with ">" is equivalent to one starting
+//      with the field name followed by ">".
+//
+//   * If the XML element contains a sub-element whose name matches
+//      a struct field's XMLName tag and the struct field has no
+//      explicit name tag as per the previous rule, unmarshal maps
+//      the sub-element to that struct field.
+//
+//   * If the XML element contains a sub-element whose name matches a
+//      field without any mode flags (",attr", ",chardata", etc), Unmarshal
+//      maps the sub-element to that struct field.
+//
+//   * If the XML element contains a sub-element that hasn't matched any
+//      of the above rules and the struct has a field with tag ",any",
+//      unmarshal maps the sub-element to that struct field.
+//
+//   * An anonymous struct field is handled as if the fields of its
+//      value were part of the outer struct.
+//
+//   * A struct field with tag "-" is never unmarshalled into.
+//
+// Unmarshal maps an XML element to a string or []byte by saving the
+// concatenation of that element's character data in the string or
+// []byte. The saved []byte is never nil.
+//
+// Unmarshal maps an attribute value to a string or []byte by saving
+// the value in the string or slice.
+//
+// Unmarshal maps an XML element to a slice by extending the length of
+// the slice and mapping the element to the newly created value.
+//
+// Unmarshal maps an XML element or attribute value to a bool by
+// setting it to the boolean value represented by the string.
+//
+// Unmarshal maps an XML element or attribute value to an integer or
+// floating-point field by setting the field to the result of
+// interpreting the string value in decimal.  There is no check for
+// overflow.
+//
+// Unmarshal maps an XML element to an xml.Name by recording the
+// element name.
+//
+// Unmarshal maps an XML element to a pointer by setting the pointer
+// to a freshly allocated value and then mapping the element to that value.
+//
+func Unmarshal(data []byte, v interface{}) error {
+	return NewDecoder(bytes.NewReader(data)).Decode(v)
+}
+
+// Decode works like xml.Unmarshal, except it reads the decoder
+// stream to find the start element.
+func (d *Decoder) Decode(v interface{}) error {
+	return d.DecodeElement(v, nil)
+}
+
+// DecodeElement works like xml.Unmarshal except that it takes
+// a pointer to the start XML element to decode into v.
+// It is useful when a client reads some raw XML tokens itself
+// but also wants to defer to Unmarshal for some elements.
+func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
+	val := reflect.ValueOf(v)
+	if val.Kind() != reflect.Ptr {
+		return errors.New("non-pointer passed to Unmarshal")
+	}
+	return d.unmarshal(val.Elem(), start)
+}
+
+// An UnmarshalError represents an error in the unmarshalling process.
+type UnmarshalError string
+
+func (e UnmarshalError) Error() string { return string(e) }
+
+// Unmarshaler is the interface implemented by objects that can unmarshal
+// an XML element description of themselves.
+//
+// UnmarshalXML decodes a single XML element
+// beginning with the given start element.
+// If it returns an error, the outer call to Unmarshal stops and
+// returns that error.
+// UnmarshalXML must consume exactly one XML element.
+// One common implementation strategy is to unmarshal into
+// a separate value with a layout matching the expected XML
+// using d.DecodeElement,  and then to copy the data from
+// that value into the receiver.
+// Another common strategy is to use d.Token to process the
+// XML object one token at a time.
+// UnmarshalXML may not use d.RawToken.
+type Unmarshaler interface {
+	UnmarshalXML(d *Decoder, start StartElement) error
+}
+
+// UnmarshalerAttr is the interface implemented by objects that can unmarshal
+// an XML attribute description of themselves.
+//
+// UnmarshalXMLAttr decodes a single XML attribute.
+// If it returns an error, the outer call to Unmarshal stops and
+// returns that error.
+// UnmarshalXMLAttr is used only for struct fields with the
+// "attr" option in the field tag.
+type UnmarshalerAttr interface {
+	UnmarshalXMLAttr(attr Attr) error
+}
+
+// receiverType returns the receiver type to use in an expression like "%s.MethodName".
+func receiverType(val interface{}) string {
+	t := reflect.TypeOf(val)
+	if t.Name() != "" {
+		return t.String()
+	}
+	return "(" + t.String() + ")"
+}
+
+// unmarshalInterface unmarshals a single XML element into val.
+// start is the opening tag of the element.
+func (p *Decoder) unmarshalInterface(val Unmarshaler, start *StartElement) error {
+	// Record that decoder must stop at end tag corresponding to start.
+	p.pushEOF()
+
+	p.unmarshalDepth++
+	err := val.UnmarshalXML(p, *start)
+	p.unmarshalDepth--
+	if err != nil {
+		p.popEOF()
+		return err
+	}
+
+	if !p.popEOF() {
+		return fmt.Errorf("xml: %s.UnmarshalXML did not consume entire <%s> element", receiverType(val), start.Name.Local)
+	}
+
+	return nil
+}
+
+// unmarshalTextInterface unmarshals a single XML element into val.
+// The chardata contained in the element (but not its children)
+// is passed to the text unmarshaler.
+func (p *Decoder) unmarshalTextInterface(val encoding.TextUnmarshaler, start *StartElement) error {
+	var buf []byte
+	depth := 1
+	for depth > 0 {
+		t, err := p.Token()
+		if err != nil {
+			return err
+		}
+		switch t := t.(type) {
+		case CharData:
+			if depth == 1 {
+				buf = append(buf, t...)
+			}
+		case StartElement:
+			depth++
+		case EndElement:
+			depth--
+		}
+	}
+	return val.UnmarshalText(buf)
+}
+
+// unmarshalAttr unmarshals a single XML attribute into val.
+func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
+	if val.Kind() == reflect.Ptr {
+		if val.IsNil() {
+			val.Set(reflect.New(val.Type().Elem()))
+		}
+		val = val.Elem()
+	}
+
+	if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) {
+		// This is an unmarshaler with a non-pointer receiver,
+		// so it's likely to be incorrect, but we do what we're told.
+		return val.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
+	}
+	if val.CanAddr() {
+		pv := val.Addr()
+		if pv.CanInterface() && pv.Type().Implements(unmarshalerAttrType) {
+			return pv.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
+		}
+	}
+
+	// Not an UnmarshalerAttr; try encoding.TextUnmarshaler.
+	if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
+		// This is an unmarshaler with a non-pointer receiver,
+		// so it's likely to be incorrect, but we do what we're told.
+		return val.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
+	}
+	if val.CanAddr() {
+		pv := val.Addr()
+		if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
+			return pv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
+		}
+	}
+
+	copyValue(val, []byte(attr.Value))
+	return nil
+}
+
+var (
+	unmarshalerType     = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
+	unmarshalerAttrType = reflect.TypeOf((*UnmarshalerAttr)(nil)).Elem()
+	textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+)
+
+// Unmarshal a single XML element into val.
+func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
+	// Find start element if we need it.
+	if start == nil {
+		for {
+			tok, err := p.Token()
+			if err != nil {
+				return err
+			}
+			if t, ok := tok.(StartElement); ok {
+				start = &t
+				break
+			}
+		}
+	}
+
+	// Load value from interface, but only if the result will be
+	// usefully addressable.
+	if val.Kind() == reflect.Interface && !val.IsNil() {
+		e := val.Elem()
+		if e.Kind() == reflect.Ptr && !e.IsNil() {
+			val = e
+		}
+	}
+
+	if val.Kind() == reflect.Ptr {
+		if val.IsNil() {
+			val.Set(reflect.New(val.Type().Elem()))
+		}
+		val = val.Elem()
+	}
+
+	if val.CanInterface() && val.Type().Implements(unmarshalerType) {
+		// This is an unmarshaler with a non-pointer receiver,
+		// so it's likely to be incorrect, but we do what we're told.
+		return p.unmarshalInterface(val.Interface().(Unmarshaler), start)
+	}
+
+	if val.CanAddr() {
+		pv := val.Addr()
+		if pv.CanInterface() && pv.Type().Implements(unmarshalerType) {
+			return p.unmarshalInterface(pv.Interface().(Unmarshaler), start)
+		}
+	}
+
+	if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
+		return p.unmarshalTextInterface(val.Interface().(encoding.TextUnmarshaler), start)
+	}
+
+	if val.CanAddr() {
+		pv := val.Addr()
+		if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
+			return p.unmarshalTextInterface(pv.Interface().(encoding.TextUnmarshaler), start)
+		}
+	}
+
+	var (
+		data         []byte
+		saveData     reflect.Value
+		comment      []byte
+		saveComment  reflect.Value
+		saveXML      reflect.Value
+		saveXMLIndex int
+		saveXMLData  []byte
+		saveAny      reflect.Value
+		sv           reflect.Value
+		tinfo        *typeInfo
+		err          error
+	)
+
+	switch v := val; v.Kind() {
+	default:
+		return errors.New("unknown type " + v.Type().String())
+
+	case reflect.Interface:
+		// TODO: For now, simply ignore the field. In the near
+		//       future we may choose to unmarshal the start
+		//       element on it, if not nil.
+		return p.Skip()
+
+	case reflect.Slice:
+		typ := v.Type()
+		if typ.Elem().Kind() == reflect.Uint8 {
+			// []byte
+			saveData = v
+			break
+		}
+
+		// Slice of element values.
+		// Grow slice.
+		n := v.Len()
+		if n >= v.Cap() {
+			ncap := 2 * n
+			if ncap < 4 {
+				ncap = 4
+			}
+			new := reflect.MakeSlice(typ, n, ncap)
+			reflect.Copy(new, v)
+			v.Set(new)
+		}
+		v.SetLen(n + 1)
+
+		// Recur to read element into slice.
+		if err := p.unmarshal(v.Index(n), start); err != nil {
+			v.SetLen(n)
+			return err
+		}
+		return nil
+
+	case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.String:
+		saveData = v
+
+	case reflect.Struct:
+		typ := v.Type()
+		if typ == nameType {
+			v.Set(reflect.ValueOf(start.Name))
+			break
+		}
+
+		sv = v
+		tinfo, err = getTypeInfo(typ)
+		if err != nil {
+			return err
+		}
+
+		// Validate and assign element name.
+		if tinfo.xmlname != nil {
+			finfo := tinfo.xmlname
+			if finfo.name != "" && finfo.name != start.Name.Local {
+				return UnmarshalError("expected element type <" + finfo.name + "> but have <" + start.Name.Local + ">")
+			}
+			if finfo.xmlns != "" && finfo.xmlns != start.Name.Space {
+				e := "expected element <" + finfo.name + "> in name space " + finfo.xmlns + " but have "
+				if start.Name.Space == "" {
+					e += "no name space"
+				} else {
+					e += start.Name.Space
+				}
+				return UnmarshalError(e)
+			}
+			fv := finfo.value(sv)
+			if _, ok := fv.Interface().(Name); ok {
+				fv.Set(reflect.ValueOf(start.Name))
+			}
+		}
+
+		// Assign attributes.
+		// Also, determine whether we need to save character data or comments.
+		for i := range tinfo.fields {
+			finfo := &tinfo.fields[i]
+			switch finfo.flags & fMode {
+			case fAttr:
+				strv := finfo.value(sv)
+				// Look for attribute.
+				for _, a := range start.Attr {
+					if a.Name.Local == finfo.name && (finfo.xmlns == "" || finfo.xmlns == a.Name.Space) {
+						if err := p.unmarshalAttr(strv, a); err != nil {
+							return err
+						}
+						break
+					}
+				}
+
+			case fCharData:
+				if !saveData.IsValid() {
+					saveData = finfo.value(sv)
+				}
+
+			case fComment:
+				if !saveComment.IsValid() {
+					saveComment = finfo.value(sv)
+				}
+
+			case fAny, fAny | fElement:
+				if !saveAny.IsValid() {
+					saveAny = finfo.value(sv)
+				}
+
+			case fInnerXml:
+				if !saveXML.IsValid() {
+					saveXML = finfo.value(sv)
+					if p.saved == nil {
+						saveXMLIndex = 0
+						p.saved = new(bytes.Buffer)
+					} else {
+						saveXMLIndex = p.savedOffset()
+					}
+				}
+			}
+		}
+	}
+
+	// Find end element.
+	// Process sub-elements along the way.
+Loop:
+	for {
+		var savedOffset int
+		if saveXML.IsValid() {
+			savedOffset = p.savedOffset()
+		}
+		tok, err := p.Token()
+		if err != nil {
+			return err
+		}
+		switch t := tok.(type) {
+		case StartElement:
+			consumed := false
+			if sv.IsValid() {
+				consumed, err = p.unmarshalPath(tinfo, sv, nil, &t)
+				if err != nil {
+					return err
+				}
+				if !consumed && saveAny.IsValid() {
+					consumed = true
+					if err := p.unmarshal(saveAny, &t); err != nil {
+						return err
+					}
+				}
+			}
+			if !consumed {
+				if err := p.Skip(); err != nil {
+					return err
+				}
+			}
+
+		case EndElement:
+			if saveXML.IsValid() {
+				saveXMLData = p.saved.Bytes()[saveXMLIndex:savedOffset]
+				if saveXMLIndex == 0 {
+					p.saved = nil
+				}
+			}
+			break Loop
+
+		case CharData:
+			if saveData.IsValid() {
+				data = append(data, t...)
+			}
+
+		case Comment:
+			if saveComment.IsValid() {
+				comment = append(comment, t...)
+			}
+		}
+	}
+
+	if saveData.IsValid() && saveData.CanInterface() && saveData.Type().Implements(textUnmarshalerType) {
+		if err := saveData.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
+			return err
+		}
+		saveData = reflect.Value{}
+	}
+
+	if saveData.IsValid() && saveData.CanAddr() {
+		pv := saveData.Addr()
+		if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
+			if err := pv.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
+				return err
+			}
+			saveData = reflect.Value{}
+		}
+	}
+
+	if err := copyValue(saveData, data); err != nil {
+		return err
+	}
+
+	switch t := saveComment; t.Kind() {
+	case reflect.String:
+		t.SetString(string(comment))
+	case reflect.Slice:
+		t.Set(reflect.ValueOf(comment))
+	}
+
+	switch t := saveXML; t.Kind() {
+	case reflect.String:
+		t.SetString(string(saveXMLData))
+	case reflect.Slice:
+		t.Set(reflect.ValueOf(saveXMLData))
+	}
+
+	return nil
+}
+
+func copyValue(dst reflect.Value, src []byte) (err error) {
+	dst0 := dst
+
+	if dst.Kind() == reflect.Ptr {
+		if dst.IsNil() {
+			dst.Set(reflect.New(dst.Type().Elem()))
+		}
+		dst = dst.Elem()
+	}
+
+	// Save accumulated data.
+	switch dst.Kind() {
+	case reflect.Invalid:
+		// Probably a comment.
+	default:
+		return errors.New("cannot unmarshal into " + dst0.Type().String())
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		itmp, err := strconv.ParseInt(string(src), 10, dst.Type().Bits())
+		if err != nil {
+			return err
+		}
+		dst.SetInt(itmp)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		utmp, err := strconv.ParseUint(string(src), 10, dst.Type().Bits())
+		if err != nil {
+			return err
+		}
+		dst.SetUint(utmp)
+	case reflect.Float32, reflect.Float64:
+		ftmp, err := strconv.ParseFloat(string(src), dst.Type().Bits())
+		if err != nil {
+			return err
+		}
+		dst.SetFloat(ftmp)
+	case reflect.Bool:
+		value, err := strconv.ParseBool(strings.TrimSpace(string(src)))
+		if err != nil {
+			return err
+		}
+		dst.SetBool(value)
+	case reflect.String:
+		dst.SetString(string(src))
+	case reflect.Slice:
+		if len(src) == 0 {
+			// non-nil to flag presence
+			src = []byte{}
+		}
+		dst.SetBytes(src)
+	}
+	return nil
+}
+
+// unmarshalPath walks down an XML structure looking for wanted
+// paths, and calls unmarshal on them.
+// The consumed result tells whether XML elements have been consumed
+// from the Decoder until start's matching end element, or if it's
+// still untouched because start is uninteresting for sv's fields.
+func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
+	recurse := false
+Loop:
+	for i := range tinfo.fields {
+		finfo := &tinfo.fields[i]
+		if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) || finfo.xmlns != "" && finfo.xmlns != start.Name.Space {
+			continue
+		}
+		for j := range parents {
+			if parents[j] != finfo.parents[j] {
+				continue Loop
+			}
+		}
+		if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
+			// It's a perfect match, unmarshal the field.
+			return true, p.unmarshal(finfo.value(sv), start)
+		}
+		if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
+			// It's a prefix for the field. Break and recurse
+			// since it's not ok for one field path to be itself
+			// the prefix for another field path.
+			recurse = true
+
+			// We can reuse the same slice as long as we
+			// don't try to append to it.
+			parents = finfo.parents[:len(parents)+1]
+			break
+		}
+	}
+	if !recurse {
+		// We have no business with this element.
+		return false, nil
+	}
+	// The element is not a perfect match for any field, but one
+	// or more fields have the path to this element as a parent
+	// prefix. Recurse and attempt to match these.
+	for {
+		var tok Token
+		tok, err = p.Token()
+		if err != nil {
+			return true, err
+		}
+		switch t := tok.(type) {
+		case StartElement:
+			consumed2, err := p.unmarshalPath(tinfo, sv, parents, &t)
+			if err != nil {
+				return true, err
+			}
+			if !consumed2 {
+				if err := p.Skip(); err != nil {
+					return true, err
+				}
+			}
+		case EndElement:
+			return true, nil
+		}
+	}
+}
+
+// Skip reads tokens until it has consumed the end element
+// matching the most recent start element already consumed.
+// It recurs if it encounters a start element, so it can be used to
+// skip nested structures.
+// It returns nil if it finds an end element matching the start
+// element; otherwise it returns an error describing the problem.
+func (d *Decoder) Skip() error {
+	for {
+		tok, err := d.Token()
+		if err != nil {
+			return err
+		}
+		switch tok.(type) {
+		case StartElement:
+			if err := d.Skip(); err != nil {
+				return err
+			}
+		case EndElement:
+			return nil
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/xml/read_test.go b/third_party/gofrontend/libgo/go/encoding/xml/read_test.go
new file mode 100644
index 0000000..01f55d0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/xml/read_test.go
@@ -0,0 +1,714 @@
+// 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 xml
+
+import (
+	"io"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+)
+
+// Stripped down Atom feed data structures.
+
+func TestUnmarshalFeed(t *testing.T) {
+	var f Feed
+	if err := Unmarshal([]byte(atomFeedString), &f); err != nil {
+		t.Fatalf("Unmarshal: %s", err)
+	}
+	if !reflect.DeepEqual(f, atomFeed) {
+		t.Fatalf("have %#v\nwant %#v", f, atomFeed)
+	}
+}
+
+// hget http://codereview.appspot.com/rss/mine/rsc
+const atomFeedString = `
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us" updated="2009-10-04T01:35:58+00:00"><title>Code Review - My issues</title><link href="http://codereview.appspot.com/" rel="alternate"></link><link href="http://codereview.appspot.com/rss/mine/rsc" rel="self"></link><id>http://codereview.appspot.com/</id><author><name>rietveld&lt;&gt;</name></author><entry><title>rietveld: an attempt at pubsubhubbub
+</title><link href="http://codereview.appspot.com/126085" rel="alternate"></link><updated>2009-10-04T01:35:58+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:134d9179c41f806be79b3a5f7877d19a</id><summary type="html">
+  An attempt at adding pubsubhubbub support to Rietveld.
+http://code.google.com/p/pubsubhubbub
+http://code.google.com/p/rietveld/issues/detail?id=155
+
+The server side of the protocol is trivial:
+  1. add a &amp;lt;link rel=&amp;quot;hub&amp;quot; href=&amp;quot;hub-server&amp;quot;&amp;gt; tag to all
+     feeds that will be pubsubhubbubbed.
+  2. every time one of those feeds changes, tell the hub
+     with a simple POST request.
+
+I have tested this by adding debug prints to a local hub
+server and checking that the server got the right publish
+requests.
+
+I can&amp;#39;t quite get the server to work, but I think the bug
+is not in my code.  I think that the server expects to be
+able to grab the feed and see the feed&amp;#39;s actual URL in
+the link rel=&amp;quot;self&amp;quot;, but the default value for that drops
+the :port from the URL, and I cannot for the life of me
+figure out how to get the Atom generator deep inside
+django not to do that, or even where it is doing that,
+or even what code is running to generate the Atom feed.
+(I thought I knew but I added some assert False statements
+and it kept running!)
+
+Ignoring that particular problem, I would appreciate
+feedback on the right way to get the two values at
+the top of feeds.py marked NOTE(rsc).
+
+
+</summary></entry><entry><title>rietveld: correct tab handling
+</title><link href="http://codereview.appspot.com/124106" rel="alternate"></link><updated>2009-10-03T23:02:17+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:0a2a4f19bb815101f0ba2904aed7c35a</id><summary type="html">
+  This fixes the buggy tab rendering that can be seen at
+http://codereview.appspot.com/116075/diff/1/2
+
+The fundamental problem was that the tab code was
+not being told what column the text began in, so it
+didn&amp;#39;t know where to put the tab stops.  Another problem
+was that some of the code assumed that string byte
+offsets were the same as column offsets, which is only
+true if there are no tabs.
+
+In the process of fixing this, I cleaned up the arguments
+to Fold and ExpandTabs and renamed them Break and
+_ExpandTabs so that I could be sure that I found all the
+call sites.  I also wanted to verify that ExpandTabs was
+not being used from outside intra_region_diff.py.
+
+
+</summary></entry></feed> 	   `
+
+type Feed struct {
+	XMLName Name      `xml:"http://www.w3.org/2005/Atom feed"`
+	Title   string    `xml:"title"`
+	Id      string    `xml:"id"`
+	Link    []Link    `xml:"link"`
+	Updated time.Time `xml:"updated,attr"`
+	Author  Person    `xml:"author"`
+	Entry   []Entry   `xml:"entry"`
+}
+
+type Entry struct {
+	Title   string    `xml:"title"`
+	Id      string    `xml:"id"`
+	Link    []Link    `xml:"link"`
+	Updated time.Time `xml:"updated"`
+	Author  Person    `xml:"author"`
+	Summary Text      `xml:"summary"`
+}
+
+type Link struct {
+	Rel  string `xml:"rel,attr,omitempty"`
+	Href string `xml:"href,attr"`
+}
+
+type Person struct {
+	Name     string `xml:"name"`
+	URI      string `xml:"uri"`
+	Email    string `xml:"email"`
+	InnerXML string `xml:",innerxml"`
+}
+
+type Text struct {
+	Type string `xml:"type,attr,omitempty"`
+	Body string `xml:",chardata"`
+}
+
+var atomFeed = Feed{
+	XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
+	Title:   "Code Review - My issues",
+	Link: []Link{
+		{Rel: "alternate", Href: "http://codereview.appspot.com/"},
+		{Rel: "self", Href: "http://codereview.appspot.com/rss/mine/rsc"},
+	},
+	Id:      "http://codereview.appspot.com/",
+	Updated: ParseTime("2009-10-04T01:35:58+00:00"),
+	Author: Person{
+		Name:     "rietveld<>",
+		InnerXML: "<name>rietveld&lt;&gt;</name>",
+	},
+	Entry: []Entry{
+		{
+			Title: "rietveld: an attempt at pubsubhubbub\n",
+			Link: []Link{
+				{Rel: "alternate", Href: "http://codereview.appspot.com/126085"},
+			},
+			Updated: ParseTime("2009-10-04T01:35:58+00:00"),
+			Author: Person{
+				Name:     "email-address-removed",
+				InnerXML: "<name>email-address-removed</name>",
+			},
+			Id: "urn:md5:134d9179c41f806be79b3a5f7877d19a",
+			Summary: Text{
+				Type: "html",
+				Body: `
+  An attempt at adding pubsubhubbub support to Rietveld.
+http://code.google.com/p/pubsubhubbub
+http://code.google.com/p/rietveld/issues/detail?id=155
+
+The server side of the protocol is trivial:
+  1. add a &lt;link rel=&quot;hub&quot; href=&quot;hub-server&quot;&gt; tag to all
+     feeds that will be pubsubhubbubbed.
+  2. every time one of those feeds changes, tell the hub
+     with a simple POST request.
+
+I have tested this by adding debug prints to a local hub
+server and checking that the server got the right publish
+requests.
+
+I can&#39;t quite get the server to work, but I think the bug
+is not in my code.  I think that the server expects to be
+able to grab the feed and see the feed&#39;s actual URL in
+the link rel=&quot;self&quot;, but the default value for that drops
+the :port from the URL, and I cannot for the life of me
+figure out how to get the Atom generator deep inside
+django not to do that, or even where it is doing that,
+or even what code is running to generate the Atom feed.
+(I thought I knew but I added some assert False statements
+and it kept running!)
+
+Ignoring that particular problem, I would appreciate
+feedback on the right way to get the two values at
+the top of feeds.py marked NOTE(rsc).
+
+
+`,
+			},
+		},
+		{
+			Title: "rietveld: correct tab handling\n",
+			Link: []Link{
+				{Rel: "alternate", Href: "http://codereview.appspot.com/124106"},
+			},
+			Updated: ParseTime("2009-10-03T23:02:17+00:00"),
+			Author: Person{
+				Name:     "email-address-removed",
+				InnerXML: "<name>email-address-removed</name>",
+			},
+			Id: "urn:md5:0a2a4f19bb815101f0ba2904aed7c35a",
+			Summary: Text{
+				Type: "html",
+				Body: `
+  This fixes the buggy tab rendering that can be seen at
+http://codereview.appspot.com/116075/diff/1/2
+
+The fundamental problem was that the tab code was
+not being told what column the text began in, so it
+didn&#39;t know where to put the tab stops.  Another problem
+was that some of the code assumed that string byte
+offsets were the same as column offsets, which is only
+true if there are no tabs.
+
+In the process of fixing this, I cleaned up the arguments
+to Fold and ExpandTabs and renamed them Break and
+_ExpandTabs so that I could be sure that I found all the
+call sites.  I also wanted to verify that ExpandTabs was
+not being used from outside intra_region_diff.py.
+
+
+`,
+			},
+		},
+	},
+}
+
+const pathTestString = `
+<Result>
+    <Before>1</Before>
+    <Items>
+        <Item1>
+            <Value>A</Value>
+        </Item1>
+        <Item2>
+            <Value>B</Value>
+        </Item2>
+        <Item1>
+            <Value>C</Value>
+            <Value>D</Value>
+        </Item1>
+        <_>
+            <Value>E</Value>
+        </_>
+    </Items>
+    <After>2</After>
+</Result>
+`
+
+type PathTestItem struct {
+	Value string
+}
+
+type PathTestA struct {
+	Items         []PathTestItem `xml:">Item1"`
+	Before, After string
+}
+
+type PathTestB struct {
+	Other         []PathTestItem `xml:"Items>Item1"`
+	Before, After string
+}
+
+type PathTestC struct {
+	Values1       []string `xml:"Items>Item1>Value"`
+	Values2       []string `xml:"Items>Item2>Value"`
+	Before, After string
+}
+
+type PathTestSet struct {
+	Item1 []PathTestItem
+}
+
+type PathTestD struct {
+	Other         PathTestSet `xml:"Items"`
+	Before, After string
+}
+
+type PathTestE struct {
+	Underline     string `xml:"Items>_>Value"`
+	Before, After string
+}
+
+var pathTests = []interface{}{
+	&PathTestA{Items: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"},
+	&PathTestB{Other: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"},
+	&PathTestC{Values1: []string{"A", "C", "D"}, Values2: []string{"B"}, Before: "1", After: "2"},
+	&PathTestD{Other: PathTestSet{Item1: []PathTestItem{{"A"}, {"D"}}}, Before: "1", After: "2"},
+	&PathTestE{Underline: "E", Before: "1", After: "2"},
+}
+
+func TestUnmarshalPaths(t *testing.T) {
+	for _, pt := range pathTests {
+		v := reflect.New(reflect.TypeOf(pt).Elem()).Interface()
+		if err := Unmarshal([]byte(pathTestString), v); err != nil {
+			t.Fatalf("Unmarshal: %s", err)
+		}
+		if !reflect.DeepEqual(v, pt) {
+			t.Fatalf("have %#v\nwant %#v", v, pt)
+		}
+	}
+}
+
+type BadPathTestA struct {
+	First  string `xml:"items>item1"`
+	Other  string `xml:"items>item2"`
+	Second string `xml:"items"`
+}
+
+type BadPathTestB struct {
+	Other  string `xml:"items>item2>value"`
+	First  string `xml:"items>item1"`
+	Second string `xml:"items>item1>value"`
+}
+
+type BadPathTestC struct {
+	First  string
+	Second string `xml:"First"`
+}
+
+type BadPathTestD struct {
+	BadPathEmbeddedA
+	BadPathEmbeddedB
+}
+
+type BadPathEmbeddedA struct {
+	First string
+}
+
+type BadPathEmbeddedB struct {
+	Second string `xml:"First"`
+}
+
+var badPathTests = []struct {
+	v, e interface{}
+}{
+	{&BadPathTestA{}, &TagPathError{reflect.TypeOf(BadPathTestA{}), "First", "items>item1", "Second", "items"}},
+	{&BadPathTestB{}, &TagPathError{reflect.TypeOf(BadPathTestB{}), "First", "items>item1", "Second", "items>item1>value"}},
+	{&BadPathTestC{}, &TagPathError{reflect.TypeOf(BadPathTestC{}), "First", "", "Second", "First"}},
+	{&BadPathTestD{}, &TagPathError{reflect.TypeOf(BadPathTestD{}), "First", "", "Second", "First"}},
+}
+
+func TestUnmarshalBadPaths(t *testing.T) {
+	for _, tt := range badPathTests {
+		err := Unmarshal([]byte(pathTestString), tt.v)
+		if !reflect.DeepEqual(err, tt.e) {
+			t.Fatalf("Unmarshal with %#v didn't fail properly:\nhave %#v,\nwant %#v", tt.v, err, tt.e)
+		}
+	}
+}
+
+const OK = "OK"
+const withoutNameTypeData = `
+<?xml version="1.0" charset="utf-8"?>
+<Test3 Attr="OK" />`
+
+type TestThree struct {
+	XMLName Name   `xml:"Test3"`
+	Attr    string `xml:",attr"`
+}
+
+func TestUnmarshalWithoutNameType(t *testing.T) {
+	var x TestThree
+	if err := Unmarshal([]byte(withoutNameTypeData), &x); err != nil {
+		t.Fatalf("Unmarshal: %s", err)
+	}
+	if x.Attr != OK {
+		t.Fatalf("have %v\nwant %v", x.Attr, OK)
+	}
+}
+
+func TestUnmarshalAttr(t *testing.T) {
+	type ParamVal struct {
+		Int int `xml:"int,attr"`
+	}
+
+	type ParamPtr struct {
+		Int *int `xml:"int,attr"`
+	}
+
+	type ParamStringPtr struct {
+		Int *string `xml:"int,attr"`
+	}
+
+	x := []byte(`<Param int="1" />`)
+
+	p1 := &ParamPtr{}
+	if err := Unmarshal(x, p1); err != nil {
+		t.Fatalf("Unmarshal: %s", err)
+	}
+	if p1.Int == nil {
+		t.Fatalf("Unmarshal failed in to *int field")
+	} else if *p1.Int != 1 {
+		t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p1.Int, 1)
+	}
+
+	p2 := &ParamVal{}
+	if err := Unmarshal(x, p2); err != nil {
+		t.Fatalf("Unmarshal: %s", err)
+	}
+	if p2.Int != 1 {
+		t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p2.Int, 1)
+	}
+
+	p3 := &ParamStringPtr{}
+	if err := Unmarshal(x, p3); err != nil {
+		t.Fatalf("Unmarshal: %s", err)
+	}
+	if p3.Int == nil {
+		t.Fatalf("Unmarshal failed in to *string field")
+	} else if *p3.Int != "1" {
+		t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p3.Int, 1)
+	}
+}
+
+type Tables struct {
+	HTable string `xml:"http://www.w3.org/TR/html4/ table"`
+	FTable string `xml:"http://www.w3schools.com/furniture table"`
+}
+
+var tables = []struct {
+	xml string
+	tab Tables
+	ns  string
+}{
+	{
+		xml: `<Tables>` +
+			`<table xmlns="http://www.w3.org/TR/html4/">hello</table>` +
+			`<table xmlns="http://www.w3schools.com/furniture">world</table>` +
+			`</Tables>`,
+		tab: Tables{"hello", "world"},
+	},
+	{
+		xml: `<Tables>` +
+			`<table xmlns="http://www.w3schools.com/furniture">world</table>` +
+			`<table xmlns="http://www.w3.org/TR/html4/">hello</table>` +
+			`</Tables>`,
+		tab: Tables{"hello", "world"},
+	},
+	{
+		xml: `<Tables xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/">` +
+			`<f:table>world</f:table>` +
+			`<h:table>hello</h:table>` +
+			`</Tables>`,
+		tab: Tables{"hello", "world"},
+	},
+	{
+		xml: `<Tables>` +
+			`<table>bogus</table>` +
+			`</Tables>`,
+		tab: Tables{},
+	},
+	{
+		xml: `<Tables>` +
+			`<table>only</table>` +
+			`</Tables>`,
+		tab: Tables{HTable: "only"},
+		ns:  "http://www.w3.org/TR/html4/",
+	},
+	{
+		xml: `<Tables>` +
+			`<table>only</table>` +
+			`</Tables>`,
+		tab: Tables{FTable: "only"},
+		ns:  "http://www.w3schools.com/furniture",
+	},
+	{
+		xml: `<Tables>` +
+			`<table>only</table>` +
+			`</Tables>`,
+		tab: Tables{},
+		ns:  "something else entirely",
+	},
+}
+
+func TestUnmarshalNS(t *testing.T) {
+	for i, tt := range tables {
+		var dst Tables
+		var err error
+		if tt.ns != "" {
+			d := NewDecoder(strings.NewReader(tt.xml))
+			d.DefaultSpace = tt.ns
+			err = d.Decode(&dst)
+		} else {
+			err = Unmarshal([]byte(tt.xml), &dst)
+		}
+		if err != nil {
+			t.Errorf("#%d: Unmarshal: %v", i, err)
+			continue
+		}
+		want := tt.tab
+		if dst != want {
+			t.Errorf("#%d: dst=%+v, want %+v", i, dst, want)
+		}
+	}
+}
+
+func TestMarshalNS(t *testing.T) {
+	dst := Tables{"hello", "world"}
+	data, err := Marshal(&dst)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	want := `<Tables><table xmlns="http://www.w3.org/TR/html4/">hello</table><table xmlns="http://www.w3schools.com/furniture">world</table></Tables>`
+	str := string(data)
+	if str != want {
+		t.Errorf("have: %q\nwant: %q\n", str, want)
+	}
+}
+
+type TableAttrs struct {
+	TAttr TAttr
+}
+
+type TAttr struct {
+	HTable string `xml:"http://www.w3.org/TR/html4/ table,attr"`
+	FTable string `xml:"http://www.w3schools.com/furniture table,attr"`
+	Lang   string `xml:"http://www.w3.org/XML/1998/namespace lang,attr,omitempty"`
+	Other1 string `xml:"http://golang.org/xml/ other,attr,omitempty"`
+	Other2 string `xml:"http://golang.org/xmlfoo/ other,attr,omitempty"`
+	Other3 string `xml:"http://golang.org/json/ other,attr,omitempty"`
+	Other4 string `xml:"http://golang.org/2/json/ other,attr,omitempty"`
+}
+
+var tableAttrs = []struct {
+	xml string
+	tab TableAttrs
+	ns  string
+}{
+	{
+		xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` +
+			`h:table="hello" f:table="world" ` +
+			`/></TableAttrs>`,
+		tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}},
+	},
+	{
+		xml: `<TableAttrs><TAttr xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/" ` +
+			`h:table="hello" f:table="world" ` +
+			`/></TableAttrs>`,
+		tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}},
+	},
+	{
+		xml: `<TableAttrs><TAttr ` +
+			`h:table="hello" f:table="world" xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/" ` +
+			`/></TableAttrs>`,
+		tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}},
+	},
+	{
+		// Default space does not apply to attribute names.
+		xml: `<TableAttrs xmlns="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` +
+			`h:table="hello" table="world" ` +
+			`/></TableAttrs>`,
+		tab: TableAttrs{TAttr{HTable: "hello", FTable: ""}},
+	},
+	{
+		// Default space does not apply to attribute names.
+		xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture"><TAttr xmlns="http://www.w3.org/TR/html4/" ` +
+			`table="hello" f:table="world" ` +
+			`/></TableAttrs>`,
+		tab: TableAttrs{TAttr{HTable: "", FTable: "world"}},
+	},
+	{
+		xml: `<TableAttrs><TAttr ` +
+			`table="bogus" ` +
+			`/></TableAttrs>`,
+		tab: TableAttrs{},
+	},
+	{
+		// Default space does not apply to attribute names.
+		xml: `<TableAttrs xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` +
+			`h:table="hello" table="world" ` +
+			`/></TableAttrs>`,
+		tab: TableAttrs{TAttr{HTable: "hello", FTable: ""}},
+		ns:  "http://www.w3schools.com/furniture",
+	},
+	{
+		// Default space does not apply to attribute names.
+		xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture"><TAttr ` +
+			`table="hello" f:table="world" ` +
+			`/></TableAttrs>`,
+		tab: TableAttrs{TAttr{HTable: "", FTable: "world"}},
+		ns:  "http://www.w3.org/TR/html4/",
+	},
+	{
+		xml: `<TableAttrs><TAttr ` +
+			`table="bogus" ` +
+			`/></TableAttrs>`,
+		tab: TableAttrs{},
+		ns:  "something else entirely",
+	},
+}
+
+func TestUnmarshalNSAttr(t *testing.T) {
+	for i, tt := range tableAttrs {
+		var dst TableAttrs
+		var err error
+		if tt.ns != "" {
+			d := NewDecoder(strings.NewReader(tt.xml))
+			d.DefaultSpace = tt.ns
+			err = d.Decode(&dst)
+		} else {
+			err = Unmarshal([]byte(tt.xml), &dst)
+		}
+		if err != nil {
+			t.Errorf("#%d: Unmarshal: %v", i, err)
+			continue
+		}
+		want := tt.tab
+		if dst != want {
+			t.Errorf("#%d: dst=%+v, want %+v", i, dst, want)
+		}
+	}
+}
+
+func TestMarshalNSAttr(t *testing.T) {
+	src := TableAttrs{TAttr{"hello", "world", "en_US", "other1", "other2", "other3", "other4"}}
+	data, err := Marshal(&src)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	want := `<TableAttrs><TAttr xmlns:html4="http://www.w3.org/TR/html4/" html4:table="hello" xmlns:furniture="http://www.w3schools.com/furniture" furniture:table="world" xml:lang="en_US" xmlns:_xml="http://golang.org/xml/" _xml:other="other1" xmlns:_xmlfoo="http://golang.org/xmlfoo/" _xmlfoo:other="other2" xmlns:json="http://golang.org/json/" json:other="other3" xmlns:json_1="http://golang.org/2/json/" json_1:other="other4"></TAttr></TableAttrs>`
+	str := string(data)
+	if str != want {
+		t.Errorf("Marshal:\nhave: %#q\nwant: %#q\n", str, want)
+	}
+
+	var dst TableAttrs
+	if err := Unmarshal(data, &dst); err != nil {
+		t.Errorf("Unmarshal: %v", err)
+	}
+
+	if dst != src {
+		t.Errorf("Unmarshal = %q, want %q", dst, src)
+	}
+}
+
+type MyCharData struct {
+	body string
+}
+
+func (m *MyCharData) UnmarshalXML(d *Decoder, start StartElement) error {
+	for {
+		t, err := d.Token()
+		if err == io.EOF { // found end of element
+			break
+		}
+		if err != nil {
+			return err
+		}
+		if char, ok := t.(CharData); ok {
+			m.body += string(char)
+		}
+	}
+	return nil
+}
+
+var _ Unmarshaler = (*MyCharData)(nil)
+
+func (m *MyCharData) UnmarshalXMLAttr(attr Attr) error {
+	panic("must not call")
+}
+
+type MyAttr struct {
+	attr string
+}
+
+func (m *MyAttr) UnmarshalXMLAttr(attr Attr) error {
+	m.attr = attr.Value
+	return nil
+}
+
+var _ UnmarshalerAttr = (*MyAttr)(nil)
+
+type MyStruct struct {
+	Data *MyCharData
+	Attr *MyAttr `xml:",attr"`
+
+	Data2 MyCharData
+	Attr2 MyAttr `xml:",attr"`
+}
+
+func TestUnmarshaler(t *testing.T) {
+	xml := `<?xml version="1.0" encoding="utf-8"?>
+		<MyStruct Attr="attr1" Attr2="attr2">
+		<Data>hello <!-- comment -->world</Data>
+		<Data2>howdy <!-- comment -->world</Data2>
+		</MyStruct>
+	`
+
+	var m MyStruct
+	if err := Unmarshal([]byte(xml), &m); err != nil {
+		t.Fatal(err)
+	}
+
+	if m.Data == nil || m.Attr == nil || m.Data.body != "hello world" || m.Attr.attr != "attr1" || m.Data2.body != "howdy world" || m.Attr2.attr != "attr2" {
+		t.Errorf("m=%#+v\n", m)
+	}
+}
+
+type Pea struct {
+	Cotelydon string
+}
+
+type Pod struct {
+	Pea interface{} `xml:"Pea"`
+}
+
+// https://code.google.com/p/go/issues/detail?id=6836
+func TestUnmarshalIntoInterface(t *testing.T) {
+	pod := new(Pod)
+	pod.Pea = new(Pea)
+	xml := `<Pod><Pea><Cotelydon>Green stuff</Cotelydon></Pea></Pod>`
+	err := Unmarshal([]byte(xml), pod)
+	if err != nil {
+		t.Fatalf("failed to unmarshal %q: %v", xml, err)
+	}
+	pea, ok := pod.Pea.(*Pea)
+	if !ok {
+		t.Fatalf("unmarshalled into wrong type: have %T want *Pea", pod.Pea)
+	}
+	have, want := pea.Cotelydon, "Green stuff"
+	if have != want {
+		t.Errorf("failed to unmarshal into interface, have %q want %q", have, want)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/xml/typeinfo.go b/third_party/gofrontend/libgo/go/encoding/xml/typeinfo.go
new file mode 100644
index 0000000..22248d2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/xml/typeinfo.go
@@ -0,0 +1,363 @@
+// 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.
+
+package xml
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+	"sync"
+)
+
+// typeInfo holds details for the xml representation of a type.
+type typeInfo struct {
+	xmlname *fieldInfo
+	fields  []fieldInfo
+}
+
+// fieldInfo holds details for the xml representation of a single field.
+type fieldInfo struct {
+	idx     []int
+	name    string
+	xmlns   string
+	flags   fieldFlags
+	parents []string
+}
+
+type fieldFlags int
+
+const (
+	fElement fieldFlags = 1 << iota
+	fAttr
+	fCharData
+	fInnerXml
+	fComment
+	fAny
+
+	fOmitEmpty
+
+	fMode = fElement | fAttr | fCharData | fInnerXml | fComment | fAny
+)
+
+var tinfoMap = make(map[reflect.Type]*typeInfo)
+var tinfoLock sync.RWMutex
+
+var nameType = reflect.TypeOf(Name{})
+
+// getTypeInfo returns the typeInfo structure with details necessary
+// for marshalling and unmarshalling typ.
+func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
+	tinfoLock.RLock()
+	tinfo, ok := tinfoMap[typ]
+	tinfoLock.RUnlock()
+	if ok {
+		return tinfo, nil
+	}
+	tinfo = &typeInfo{}
+	if typ.Kind() == reflect.Struct && typ != nameType {
+		n := typ.NumField()
+		for i := 0; i < n; i++ {
+			f := typ.Field(i)
+			if f.PkgPath != "" || f.Tag.Get("xml") == "-" {
+				continue // Private field
+			}
+
+			// For embedded structs, embed its fields.
+			if f.Anonymous {
+				t := f.Type
+				if t.Kind() == reflect.Ptr {
+					t = t.Elem()
+				}
+				if t.Kind() == reflect.Struct {
+					inner, err := getTypeInfo(t)
+					if err != nil {
+						return nil, err
+					}
+					if tinfo.xmlname == nil {
+						tinfo.xmlname = inner.xmlname
+					}
+					for _, finfo := range inner.fields {
+						finfo.idx = append([]int{i}, finfo.idx...)
+						if err := addFieldInfo(typ, tinfo, &finfo); err != nil {
+							return nil, err
+						}
+					}
+					continue
+				}
+			}
+
+			finfo, err := structFieldInfo(typ, &f)
+			if err != nil {
+				return nil, err
+			}
+
+			if f.Name == "XMLName" {
+				tinfo.xmlname = finfo
+				continue
+			}
+
+			// Add the field if it doesn't conflict with other fields.
+			if err := addFieldInfo(typ, tinfo, finfo); err != nil {
+				return nil, err
+			}
+		}
+	}
+	tinfoLock.Lock()
+	tinfoMap[typ] = tinfo
+	tinfoLock.Unlock()
+	return tinfo, nil
+}
+
+// structFieldInfo builds and returns a fieldInfo for f.
+func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, error) {
+	finfo := &fieldInfo{idx: f.Index}
+
+	// Split the tag from the xml namespace if necessary.
+	tag := f.Tag.Get("xml")
+	if i := strings.Index(tag, " "); i >= 0 {
+		finfo.xmlns, tag = tag[:i], tag[i+1:]
+	}
+
+	// Parse flags.
+	tokens := strings.Split(tag, ",")
+	if len(tokens) == 1 {
+		finfo.flags = fElement
+	} else {
+		tag = tokens[0]
+		for _, flag := range tokens[1:] {
+			switch flag {
+			case "attr":
+				finfo.flags |= fAttr
+			case "chardata":
+				finfo.flags |= fCharData
+			case "innerxml":
+				finfo.flags |= fInnerXml
+			case "comment":
+				finfo.flags |= fComment
+			case "any":
+				finfo.flags |= fAny
+			case "omitempty":
+				finfo.flags |= fOmitEmpty
+			}
+		}
+
+		// Validate the flags used.
+		valid := true
+		switch mode := finfo.flags & fMode; mode {
+		case 0:
+			finfo.flags |= fElement
+		case fAttr, fCharData, fInnerXml, fComment, fAny:
+			if f.Name == "XMLName" || tag != "" && mode != fAttr {
+				valid = false
+			}
+		default:
+			// This will also catch multiple modes in a single field.
+			valid = false
+		}
+		if finfo.flags&fMode == fAny {
+			finfo.flags |= fElement
+		}
+		if finfo.flags&fOmitEmpty != 0 && finfo.flags&(fElement|fAttr) == 0 {
+			valid = false
+		}
+		if !valid {
+			return nil, fmt.Errorf("xml: invalid tag in field %s of type %s: %q",
+				f.Name, typ, f.Tag.Get("xml"))
+		}
+	}
+
+	// Use of xmlns without a name is not allowed.
+	if finfo.xmlns != "" && tag == "" {
+		return nil, fmt.Errorf("xml: namespace without name in field %s of type %s: %q",
+			f.Name, typ, f.Tag.Get("xml"))
+	}
+
+	if f.Name == "XMLName" {
+		// The XMLName field records the XML element name. Don't
+		// process it as usual because its name should default to
+		// empty rather than to the field name.
+		finfo.name = tag
+		return finfo, nil
+	}
+
+	if tag == "" {
+		// If the name part of the tag is completely empty, get
+		// default from XMLName of underlying struct if feasible,
+		// or field name otherwise.
+		if xmlname := lookupXMLName(f.Type); xmlname != nil {
+			finfo.xmlns, finfo.name = xmlname.xmlns, xmlname.name
+		} else {
+			finfo.name = f.Name
+		}
+		return finfo, nil
+	}
+
+	// Prepare field name and parents.
+	parents := strings.Split(tag, ">")
+	if parents[0] == "" {
+		parents[0] = f.Name
+	}
+	if parents[len(parents)-1] == "" {
+		return nil, fmt.Errorf("xml: trailing '>' in field %s of type %s", f.Name, typ)
+	}
+	finfo.name = parents[len(parents)-1]
+	if len(parents) > 1 {
+		if (finfo.flags & fElement) == 0 {
+			return nil, fmt.Errorf("xml: %s chain not valid with %s flag", tag, strings.Join(tokens[1:], ","))
+		}
+		finfo.parents = parents[:len(parents)-1]
+	}
+
+	// If the field type has an XMLName field, the names must match
+	// so that the behavior of both marshalling and unmarshalling
+	// is straightforward and unambiguous.
+	if finfo.flags&fElement != 0 {
+		ftyp := f.Type
+		xmlname := lookupXMLName(ftyp)
+		if xmlname != nil && xmlname.name != finfo.name {
+			return nil, fmt.Errorf("xml: name %q in tag of %s.%s conflicts with name %q in %s.XMLName",
+				finfo.name, typ, f.Name, xmlname.name, ftyp)
+		}
+	}
+	return finfo, nil
+}
+
+// lookupXMLName returns the fieldInfo for typ's XMLName field
+// in case it exists and has a valid xml field tag, otherwise
+// it returns nil.
+func lookupXMLName(typ reflect.Type) (xmlname *fieldInfo) {
+	for typ.Kind() == reflect.Ptr {
+		typ = typ.Elem()
+	}
+	if typ.Kind() != reflect.Struct {
+		return nil
+	}
+	for i, n := 0, typ.NumField(); i < n; i++ {
+		f := typ.Field(i)
+		if f.Name != "XMLName" {
+			continue
+		}
+		finfo, err := structFieldInfo(typ, &f)
+		if finfo.name != "" && err == nil {
+			return finfo
+		}
+		// Also consider errors as a non-existent field tag
+		// and let getTypeInfo itself report the error.
+		break
+	}
+	return nil
+}
+
+func min(a, b int) int {
+	if a <= b {
+		return a
+	}
+	return b
+}
+
+// addFieldInfo adds finfo to tinfo.fields if there are no
+// conflicts, or if conflicts arise from previous fields that were
+// obtained from deeper embedded structures than finfo. In the latter
+// case, the conflicting entries are dropped.
+// A conflict occurs when the path (parent + name) to a field is
+// itself a prefix of another path, or when two paths match exactly.
+// It is okay for field paths to share a common, shorter prefix.
+func addFieldInfo(typ reflect.Type, tinfo *typeInfo, newf *fieldInfo) error {
+	var conflicts []int
+Loop:
+	// First, figure all conflicts. Most working code will have none.
+	for i := range tinfo.fields {
+		oldf := &tinfo.fields[i]
+		if oldf.flags&fMode != newf.flags&fMode {
+			continue
+		}
+		if oldf.xmlns != "" && newf.xmlns != "" && oldf.xmlns != newf.xmlns {
+			continue
+		}
+		minl := min(len(newf.parents), len(oldf.parents))
+		for p := 0; p < minl; p++ {
+			if oldf.parents[p] != newf.parents[p] {
+				continue Loop
+			}
+		}
+		if len(oldf.parents) > len(newf.parents) {
+			if oldf.parents[len(newf.parents)] == newf.name {
+				conflicts = append(conflicts, i)
+			}
+		} else if len(oldf.parents) < len(newf.parents) {
+			if newf.parents[len(oldf.parents)] == oldf.name {
+				conflicts = append(conflicts, i)
+			}
+		} else {
+			if newf.name == oldf.name {
+				conflicts = append(conflicts, i)
+			}
+		}
+	}
+	// Without conflicts, add the new field and return.
+	if conflicts == nil {
+		tinfo.fields = append(tinfo.fields, *newf)
+		return nil
+	}
+
+	// If any conflict is shallower, ignore the new field.
+	// This matches the Go field resolution on embedding.
+	for _, i := range conflicts {
+		if len(tinfo.fields[i].idx) < len(newf.idx) {
+			return nil
+		}
+	}
+
+	// Otherwise, if any of them is at the same depth level, it's an error.
+	for _, i := range conflicts {
+		oldf := &tinfo.fields[i]
+		if len(oldf.idx) == len(newf.idx) {
+			f1 := typ.FieldByIndex(oldf.idx)
+			f2 := typ.FieldByIndex(newf.idx)
+			return &TagPathError{typ, f1.Name, f1.Tag.Get("xml"), f2.Name, f2.Tag.Get("xml")}
+		}
+	}
+
+	// Otherwise, the new field is shallower, and thus takes precedence,
+	// so drop the conflicting fields from tinfo and append the new one.
+	for c := len(conflicts) - 1; c >= 0; c-- {
+		i := conflicts[c]
+		copy(tinfo.fields[i:], tinfo.fields[i+1:])
+		tinfo.fields = tinfo.fields[:len(tinfo.fields)-1]
+	}
+	tinfo.fields = append(tinfo.fields, *newf)
+	return nil
+}
+
+// A TagPathError represents an error in the unmarshalling process
+// caused by the use of field tags with conflicting paths.
+type TagPathError struct {
+	Struct       reflect.Type
+	Field1, Tag1 string
+	Field2, Tag2 string
+}
+
+func (e *TagPathError) Error() string {
+	return fmt.Sprintf("%s field %q with tag %q conflicts with field %q with tag %q", e.Struct, e.Field1, e.Tag1, e.Field2, e.Tag2)
+}
+
+// value returns v's field value corresponding to finfo.
+// It's equivalent to v.FieldByIndex(finfo.idx), but initializes
+// and dereferences pointers as necessary.
+func (finfo *fieldInfo) value(v reflect.Value) reflect.Value {
+	for i, x := range finfo.idx {
+		if i > 0 {
+			t := v.Type()
+			if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct {
+				if v.IsNil() {
+					v.Set(reflect.New(v.Type().Elem()))
+				}
+				v = v.Elem()
+			}
+		}
+		v = v.Field(x)
+	}
+	return v
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/xml/xml.go b/third_party/gofrontend/libgo/go/encoding/xml/xml.go
new file mode 100644
index 0000000..b473cb8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/xml/xml.go
@@ -0,0 +1,1935 @@
+// 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 xml implements a simple XML 1.0 parser that
+// understands XML name spaces.
+package xml
+
+// References:
+//    Annotated XML spec: http://www.xml.com/axml/testaxml.htm
+//    XML name spaces: http://www.w3.org/TR/REC-xml-names/
+
+// TODO(rsc):
+//	Test error handling.
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"strconv"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// A SyntaxError represents a syntax error in the XML input stream.
+type SyntaxError struct {
+	Msg  string
+	Line int
+}
+
+func (e *SyntaxError) Error() string {
+	return "XML syntax error on line " + strconv.Itoa(e.Line) + ": " + e.Msg
+}
+
+// A Name represents an XML name (Local) annotated
+// with a name space identifier (Space).
+// In tokens returned by Decoder.Token, the Space identifier
+// is given as a canonical URL, not the short prefix used
+// in the document being parsed.
+type Name struct {
+	Space, Local string
+}
+
+// An Attr represents an attribute in an XML element (Name=Value).
+type Attr struct {
+	Name  Name
+	Value string
+}
+
+// A Token is an interface holding one of the token types:
+// StartElement, EndElement, CharData, Comment, ProcInst, or Directive.
+type Token interface{}
+
+// A StartElement represents an XML start element.
+type StartElement struct {
+	Name Name
+	Attr []Attr
+}
+
+func (e StartElement) Copy() StartElement {
+	attrs := make([]Attr, len(e.Attr))
+	copy(attrs, e.Attr)
+	e.Attr = attrs
+	return e
+}
+
+// End returns the corresponding XML end element.
+func (e StartElement) End() EndElement {
+	return EndElement{e.Name}
+}
+
+// An EndElement represents an XML end element.
+type EndElement struct {
+	Name Name
+}
+
+// A CharData represents XML character data (raw text),
+// in which XML escape sequences have been replaced by
+// the characters they represent.
+type CharData []byte
+
+func makeCopy(b []byte) []byte {
+	b1 := make([]byte, len(b))
+	copy(b1, b)
+	return b1
+}
+
+func (c CharData) Copy() CharData { return CharData(makeCopy(c)) }
+
+// A Comment represents an XML comment of the form <!--comment-->.
+// The bytes do not include the <!-- and --> comment markers.
+type Comment []byte
+
+func (c Comment) Copy() Comment { return Comment(makeCopy(c)) }
+
+// A ProcInst represents an XML processing instruction of the form <?target inst?>
+type ProcInst struct {
+	Target string
+	Inst   []byte
+}
+
+func (p ProcInst) Copy() ProcInst {
+	p.Inst = makeCopy(p.Inst)
+	return p
+}
+
+// A Directive represents an XML directive of the form <!text>.
+// The bytes do not include the <! and > markers.
+type Directive []byte
+
+func (d Directive) Copy() Directive { return Directive(makeCopy(d)) }
+
+// CopyToken returns a copy of a Token.
+func CopyToken(t Token) Token {
+	switch v := t.(type) {
+	case CharData:
+		return v.Copy()
+	case Comment:
+		return v.Copy()
+	case Directive:
+		return v.Copy()
+	case ProcInst:
+		return v.Copy()
+	case StartElement:
+		return v.Copy()
+	}
+	return t
+}
+
+// A Decoder represents an XML parser reading a particular input stream.
+// The parser assumes that its input is encoded in UTF-8.
+type Decoder struct {
+	// Strict defaults to true, enforcing the requirements
+	// of the XML specification.
+	// If set to false, the parser allows input containing common
+	// mistakes:
+	//	* If an element is missing an end tag, the parser invents
+	//	  end tags as necessary to keep the return values from Token
+	//	  properly balanced.
+	//	* In attribute values and character data, unknown or malformed
+	//	  character entities (sequences beginning with &) are left alone.
+	//
+	// Setting:
+	//
+	//	d.Strict = false;
+	//	d.AutoClose = HTMLAutoClose;
+	//	d.Entity = HTMLEntity
+	//
+	// creates a parser that can handle typical HTML.
+	//
+	// Strict mode does not enforce the requirements of the XML name spaces TR.
+	// In particular it does not reject name space tags using undefined prefixes.
+	// Such tags are recorded with the unknown prefix as the name space URL.
+	Strict bool
+
+	// When Strict == false, AutoClose indicates a set of elements to
+	// consider closed immediately after they are opened, regardless
+	// of whether an end element is present.
+	AutoClose []string
+
+	// Entity can be used to map non-standard entity names to string replacements.
+	// The parser behaves as if these standard mappings are present in the map,
+	// regardless of the actual map content:
+	//
+	//	"lt": "<",
+	//	"gt": ">",
+	//	"amp": "&",
+	//	"apos": "'",
+	//	"quot": `"`,
+	Entity map[string]string
+
+	// CharsetReader, if non-nil, defines a function to generate
+	// charset-conversion readers, converting from the provided
+	// non-UTF-8 charset into UTF-8. If CharsetReader is nil or
+	// returns an error, parsing stops with an error. One of the
+	// the CharsetReader's result values must be non-nil.
+	CharsetReader func(charset string, input io.Reader) (io.Reader, error)
+
+	// DefaultSpace sets the default name space used for unadorned tags,
+	// as if the entire XML stream were wrapped in an element containing
+	// the attribute xmlns="DefaultSpace".
+	DefaultSpace string
+
+	r              io.ByteReader
+	buf            bytes.Buffer
+	saved          *bytes.Buffer
+	stk            *stack
+	free           *stack
+	needClose      bool
+	toClose        Name
+	nextToken      Token
+	nextByte       int
+	ns             map[string]string
+	err            error
+	line           int
+	unmarshalDepth int
+}
+
+// NewDecoder creates a new XML parser reading from r.
+// If r does not implement io.ByteReader, NewDecoder will
+// do its own buffering.
+func NewDecoder(r io.Reader) *Decoder {
+	d := &Decoder{
+		ns:       make(map[string]string),
+		nextByte: -1,
+		line:     1,
+		Strict:   true,
+	}
+	d.switchToReader(r)
+	return d
+}
+
+// Token returns the next XML token in the input stream.
+// At the end of the input stream, Token returns nil, io.EOF.
+//
+// Slices of bytes in the returned token data refer to the
+// parser's internal buffer and remain valid only until the next
+// call to Token.  To acquire a copy of the bytes, call CopyToken
+// or the token's Copy method.
+//
+// Token expands self-closing elements such as <br/>
+// into separate start and end elements returned by successive calls.
+//
+// Token guarantees that the StartElement and EndElement
+// tokens it returns are properly nested and matched:
+// if Token encounters an unexpected end element,
+// it will return an error.
+//
+// Token implements XML name spaces as described by
+// http://www.w3.org/TR/REC-xml-names/.  Each of the
+// Name structures contained in the Token has the Space
+// set to the URL identifying its name space when known.
+// If Token encounters an unrecognized name space prefix,
+// it uses the prefix as the Space rather than report an error.
+func (d *Decoder) Token() (t Token, err error) {
+	if d.stk != nil && d.stk.kind == stkEOF {
+		err = io.EOF
+		return
+	}
+	if d.nextToken != nil {
+		t = d.nextToken
+		d.nextToken = nil
+	} else if t, err = d.rawToken(); err != nil {
+		return
+	}
+
+	if !d.Strict {
+		if t1, ok := d.autoClose(t); ok {
+			d.nextToken = t
+			t = t1
+		}
+	}
+	switch t1 := t.(type) {
+	case StartElement:
+		// In XML name spaces, the translations listed in the
+		// attributes apply to the element name and
+		// to the other attribute names, so process
+		// the translations first.
+		for _, a := range t1.Attr {
+			if a.Name.Space == "xmlns" {
+				v, ok := d.ns[a.Name.Local]
+				d.pushNs(a.Name.Local, v, ok)
+				d.ns[a.Name.Local] = a.Value
+			}
+			if a.Name.Space == "" && a.Name.Local == "xmlns" {
+				// Default space for untagged names
+				v, ok := d.ns[""]
+				d.pushNs("", v, ok)
+				d.ns[""] = a.Value
+			}
+		}
+
+		d.translate(&t1.Name, true)
+		for i := range t1.Attr {
+			d.translate(&t1.Attr[i].Name, false)
+		}
+		d.pushElement(t1.Name)
+		t = t1
+
+	case EndElement:
+		d.translate(&t1.Name, true)
+		if !d.popElement(&t1) {
+			return nil, d.err
+		}
+		t = t1
+	}
+	return
+}
+
+const xmlURL = "http://www.w3.org/XML/1998/namespace"
+
+// Apply name space translation to name n.
+// The default name space (for Space=="")
+// applies only to element names, not to attribute names.
+func (d *Decoder) translate(n *Name, isElementName bool) {
+	switch {
+	case n.Space == "xmlns":
+		return
+	case n.Space == "" && !isElementName:
+		return
+	case n.Space == "xml":
+		n.Space = xmlURL
+	case n.Space == "" && n.Local == "xmlns":
+		return
+	}
+	if v, ok := d.ns[n.Space]; ok {
+		n.Space = v
+	} else if n.Space == "" {
+		n.Space = d.DefaultSpace
+	}
+}
+
+func (d *Decoder) switchToReader(r io.Reader) {
+	// Get efficient byte at a time reader.
+	// Assume that if reader has its own
+	// ReadByte, it's efficient enough.
+	// Otherwise, use bufio.
+	if rb, ok := r.(io.ByteReader); ok {
+		d.r = rb
+	} else {
+		d.r = bufio.NewReader(r)
+	}
+}
+
+// Parsing state - stack holds old name space translations
+// and the current set of open elements.  The translations to pop when
+// ending a given tag are *below* it on the stack, which is
+// more work but forced on us by XML.
+type stack struct {
+	next *stack
+	kind int
+	name Name
+	ok   bool
+}
+
+const (
+	stkStart = iota
+	stkNs
+	stkEOF
+)
+
+func (d *Decoder) push(kind int) *stack {
+	s := d.free
+	if s != nil {
+		d.free = s.next
+	} else {
+		s = new(stack)
+	}
+	s.next = d.stk
+	s.kind = kind
+	d.stk = s
+	return s
+}
+
+func (d *Decoder) pop() *stack {
+	s := d.stk
+	if s != nil {
+		d.stk = s.next
+		s.next = d.free
+		d.free = s
+	}
+	return s
+}
+
+// Record that after the current element is finished
+// (that element is already pushed on the stack)
+// Token should return EOF until popEOF is called.
+func (d *Decoder) pushEOF() {
+	// Walk down stack to find Start.
+	// It might not be the top, because there might be stkNs
+	// entries above it.
+	start := d.stk
+	for start.kind != stkStart {
+		start = start.next
+	}
+	// The stkNs entries below a start are associated with that
+	// element too; skip over them.
+	for start.next != nil && start.next.kind == stkNs {
+		start = start.next
+	}
+	s := d.free
+	if s != nil {
+		d.free = s.next
+	} else {
+		s = new(stack)
+	}
+	s.kind = stkEOF
+	s.next = start.next
+	start.next = s
+}
+
+// Undo a pushEOF.
+// The element must have been finished, so the EOF should be at the top of the stack.
+func (d *Decoder) popEOF() bool {
+	if d.stk == nil || d.stk.kind != stkEOF {
+		return false
+	}
+	d.pop()
+	return true
+}
+
+// Record that we are starting an element with the given name.
+func (d *Decoder) pushElement(name Name) {
+	s := d.push(stkStart)
+	s.name = name
+}
+
+// Record that we are changing the value of ns[local].
+// The old value is url, ok.
+func (d *Decoder) pushNs(local string, url string, ok bool) {
+	s := d.push(stkNs)
+	s.name.Local = local
+	s.name.Space = url
+	s.ok = ok
+}
+
+// Creates a SyntaxError with the current line number.
+func (d *Decoder) syntaxError(msg string) error {
+	return &SyntaxError{Msg: msg, Line: d.line}
+}
+
+// Record that we are ending an element with the given name.
+// The name must match the record at the top of the stack,
+// which must be a pushElement record.
+// After popping the element, apply any undo records from
+// the stack to restore the name translations that existed
+// before we saw this element.
+func (d *Decoder) popElement(t *EndElement) bool {
+	s := d.pop()
+	name := t.Name
+	switch {
+	case s == nil || s.kind != stkStart:
+		d.err = d.syntaxError("unexpected end element </" + name.Local + ">")
+		return false
+	case s.name.Local != name.Local:
+		if !d.Strict {
+			d.needClose = true
+			d.toClose = t.Name
+			t.Name = s.name
+			return true
+		}
+		d.err = d.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">")
+		return false
+	case s.name.Space != name.Space:
+		d.err = d.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space +
+			"closed by </" + name.Local + "> in space " + name.Space)
+		return false
+	}
+
+	// Pop stack until a Start or EOF is on the top, undoing the
+	// translations that were associated with the element we just closed.
+	for d.stk != nil && d.stk.kind != stkStart && d.stk.kind != stkEOF {
+		s := d.pop()
+		if s.ok {
+			d.ns[s.name.Local] = s.name.Space
+		} else {
+			delete(d.ns, s.name.Local)
+		}
+	}
+
+	return true
+}
+
+// If the top element on the stack is autoclosing and
+// t is not the end tag, invent the end tag.
+func (d *Decoder) autoClose(t Token) (Token, bool) {
+	if d.stk == nil || d.stk.kind != stkStart {
+		return nil, false
+	}
+	name := strings.ToLower(d.stk.name.Local)
+	for _, s := range d.AutoClose {
+		if strings.ToLower(s) == name {
+			// This one should be auto closed if t doesn't close it.
+			et, ok := t.(EndElement)
+			if !ok || et.Name.Local != name {
+				return EndElement{d.stk.name}, true
+			}
+			break
+		}
+	}
+	return nil, false
+}
+
+var errRawToken = errors.New("xml: cannot use RawToken from UnmarshalXML method")
+
+// RawToken is like Token but does not verify that
+// start and end elements match and does not translate
+// name space prefixes to their corresponding URLs.
+func (d *Decoder) RawToken() (Token, error) {
+	if d.unmarshalDepth > 0 {
+		return nil, errRawToken
+	}
+	return d.rawToken()
+}
+
+func (d *Decoder) rawToken() (Token, error) {
+	if d.err != nil {
+		return nil, d.err
+	}
+	if d.needClose {
+		// The last element we read was self-closing and
+		// we returned just the StartElement half.
+		// Return the EndElement half now.
+		d.needClose = false
+		return EndElement{d.toClose}, nil
+	}
+
+	b, ok := d.getc()
+	if !ok {
+		return nil, d.err
+	}
+
+	if b != '<' {
+		// Text section.
+		d.ungetc(b)
+		data := d.text(-1, false)
+		if data == nil {
+			return nil, d.err
+		}
+		return CharData(data), nil
+	}
+
+	if b, ok = d.mustgetc(); !ok {
+		return nil, d.err
+	}
+	switch b {
+	case '/':
+		// </: End element
+		var name Name
+		if name, ok = d.nsname(); !ok {
+			if d.err == nil {
+				d.err = d.syntaxError("expected element name after </")
+			}
+			return nil, d.err
+		}
+		d.space()
+		if b, ok = d.mustgetc(); !ok {
+			return nil, d.err
+		}
+		if b != '>' {
+			d.err = d.syntaxError("invalid characters between </" + name.Local + " and >")
+			return nil, d.err
+		}
+		return EndElement{name}, nil
+
+	case '?':
+		// <?: Processing instruction.
+		// TODO(rsc): Should parse the <?xml declaration to make sure the version is 1.0.
+		var target string
+		if target, ok = d.name(); !ok {
+			if d.err == nil {
+				d.err = d.syntaxError("expected target name after <?")
+			}
+			return nil, d.err
+		}
+		d.space()
+		d.buf.Reset()
+		var b0 byte
+		for {
+			if b, ok = d.mustgetc(); !ok {
+				return nil, d.err
+			}
+			d.buf.WriteByte(b)
+			if b0 == '?' && b == '>' {
+				break
+			}
+			b0 = b
+		}
+		data := d.buf.Bytes()
+		data = data[0 : len(data)-2] // chop ?>
+
+		if target == "xml" {
+			enc := procInstEncoding(string(data))
+			if enc != "" && enc != "utf-8" && enc != "UTF-8" {
+				if d.CharsetReader == nil {
+					d.err = fmt.Errorf("xml: encoding %q declared but Decoder.CharsetReader is nil", enc)
+					return nil, d.err
+				}
+				newr, err := d.CharsetReader(enc, d.r.(io.Reader))
+				if err != nil {
+					d.err = fmt.Errorf("xml: opening charset %q: %v", enc, err)
+					return nil, d.err
+				}
+				if newr == nil {
+					panic("CharsetReader returned a nil Reader for charset " + enc)
+				}
+				d.switchToReader(newr)
+			}
+		}
+		return ProcInst{target, data}, nil
+
+	case '!':
+		// <!: Maybe comment, maybe CDATA.
+		if b, ok = d.mustgetc(); !ok {
+			return nil, d.err
+		}
+		switch b {
+		case '-': // <!-
+			// Probably <!-- for a comment.
+			if b, ok = d.mustgetc(); !ok {
+				return nil, d.err
+			}
+			if b != '-' {
+				d.err = d.syntaxError("invalid sequence <!- not part of <!--")
+				return nil, d.err
+			}
+			// Look for terminator.
+			d.buf.Reset()
+			var b0, b1 byte
+			for {
+				if b, ok = d.mustgetc(); !ok {
+					return nil, d.err
+				}
+				d.buf.WriteByte(b)
+				if b0 == '-' && b1 == '-' && b == '>' {
+					break
+				}
+				b0, b1 = b1, b
+			}
+			data := d.buf.Bytes()
+			data = data[0 : len(data)-3] // chop -->
+			return Comment(data), nil
+
+		case '[': // <![
+			// Probably <![CDATA[.
+			for i := 0; i < 6; i++ {
+				if b, ok = d.mustgetc(); !ok {
+					return nil, d.err
+				}
+				if b != "CDATA["[i] {
+					d.err = d.syntaxError("invalid <![ sequence")
+					return nil, d.err
+				}
+			}
+			// Have <![CDATA[.  Read text until ]]>.
+			data := d.text(-1, true)
+			if data == nil {
+				return nil, d.err
+			}
+			return CharData(data), nil
+		}
+
+		// Probably a directive: <!DOCTYPE ...>, <!ENTITY ...>, etc.
+		// We don't care, but accumulate for caller. Quoted angle
+		// brackets do not count for nesting.
+		d.buf.Reset()
+		d.buf.WriteByte(b)
+		inquote := uint8(0)
+		depth := 0
+		for {
+			if b, ok = d.mustgetc(); !ok {
+				return nil, d.err
+			}
+			if inquote == 0 && b == '>' && depth == 0 {
+				break
+			}
+		HandleB:
+			d.buf.WriteByte(b)
+			switch {
+			case b == inquote:
+				inquote = 0
+
+			case inquote != 0:
+				// in quotes, no special action
+
+			case b == '\'' || b == '"':
+				inquote = b
+
+			case b == '>' && inquote == 0:
+				depth--
+
+			case b == '<' && inquote == 0:
+				// Look for <!-- to begin comment.
+				s := "!--"
+				for i := 0; i < len(s); i++ {
+					if b, ok = d.mustgetc(); !ok {
+						return nil, d.err
+					}
+					if b != s[i] {
+						for j := 0; j < i; j++ {
+							d.buf.WriteByte(s[j])
+						}
+						depth++
+						goto HandleB
+					}
+				}
+
+				// Remove < that was written above.
+				d.buf.Truncate(d.buf.Len() - 1)
+
+				// Look for terminator.
+				var b0, b1 byte
+				for {
+					if b, ok = d.mustgetc(); !ok {
+						return nil, d.err
+					}
+					if b0 == '-' && b1 == '-' && b == '>' {
+						break
+					}
+					b0, b1 = b1, b
+				}
+			}
+		}
+		return Directive(d.buf.Bytes()), nil
+	}
+
+	// Must be an open element like <a href="foo">
+	d.ungetc(b)
+
+	var (
+		name  Name
+		empty bool
+		attr  []Attr
+	)
+	if name, ok = d.nsname(); !ok {
+		if d.err == nil {
+			d.err = d.syntaxError("expected element name after <")
+		}
+		return nil, d.err
+	}
+
+	attr = make([]Attr, 0, 4)
+	for {
+		d.space()
+		if b, ok = d.mustgetc(); !ok {
+			return nil, d.err
+		}
+		if b == '/' {
+			empty = true
+			if b, ok = d.mustgetc(); !ok {
+				return nil, d.err
+			}
+			if b != '>' {
+				d.err = d.syntaxError("expected /> in element")
+				return nil, d.err
+			}
+			break
+		}
+		if b == '>' {
+			break
+		}
+		d.ungetc(b)
+
+		n := len(attr)
+		if n >= cap(attr) {
+			nattr := make([]Attr, n, 2*cap(attr))
+			copy(nattr, attr)
+			attr = nattr
+		}
+		attr = attr[0 : n+1]
+		a := &attr[n]
+		if a.Name, ok = d.nsname(); !ok {
+			if d.err == nil {
+				d.err = d.syntaxError("expected attribute name in element")
+			}
+			return nil, d.err
+		}
+		d.space()
+		if b, ok = d.mustgetc(); !ok {
+			return nil, d.err
+		}
+		if b != '=' {
+			if d.Strict {
+				d.err = d.syntaxError("attribute name without = in element")
+				return nil, d.err
+			} else {
+				d.ungetc(b)
+				a.Value = a.Name.Local
+			}
+		} else {
+			d.space()
+			data := d.attrval()
+			if data == nil {
+				return nil, d.err
+			}
+			a.Value = string(data)
+		}
+	}
+	if empty {
+		d.needClose = true
+		d.toClose = name
+	}
+	return StartElement{name, attr}, nil
+}
+
+func (d *Decoder) attrval() []byte {
+	b, ok := d.mustgetc()
+	if !ok {
+		return nil
+	}
+	// Handle quoted attribute values
+	if b == '"' || b == '\'' {
+		return d.text(int(b), false)
+	}
+	// Handle unquoted attribute values for strict parsers
+	if d.Strict {
+		d.err = d.syntaxError("unquoted or missing attribute value in element")
+		return nil
+	}
+	// Handle unquoted attribute values for unstrict parsers
+	d.ungetc(b)
+	d.buf.Reset()
+	for {
+		b, ok = d.mustgetc()
+		if !ok {
+			return nil
+		}
+		// http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
+		if 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z' ||
+			'0' <= b && b <= '9' || b == '_' || b == ':' || b == '-' {
+			d.buf.WriteByte(b)
+		} else {
+			d.ungetc(b)
+			break
+		}
+	}
+	return d.buf.Bytes()
+}
+
+// Skip spaces if any
+func (d *Decoder) space() {
+	for {
+		b, ok := d.getc()
+		if !ok {
+			return
+		}
+		switch b {
+		case ' ', '\r', '\n', '\t':
+		default:
+			d.ungetc(b)
+			return
+		}
+	}
+}
+
+// Read a single byte.
+// If there is no byte to read, return ok==false
+// and leave the error in d.err.
+// Maintain line number.
+func (d *Decoder) getc() (b byte, ok bool) {
+	if d.err != nil {
+		return 0, false
+	}
+	if d.nextByte >= 0 {
+		b = byte(d.nextByte)
+		d.nextByte = -1
+	} else {
+		b, d.err = d.r.ReadByte()
+		if d.err != nil {
+			return 0, false
+		}
+		if d.saved != nil {
+			d.saved.WriteByte(b)
+		}
+	}
+	if b == '\n' {
+		d.line++
+	}
+	return b, true
+}
+
+// Return saved offset.
+// If we did ungetc (nextByte >= 0), have to back up one.
+func (d *Decoder) savedOffset() int {
+	n := d.saved.Len()
+	if d.nextByte >= 0 {
+		n--
+	}
+	return n
+}
+
+// Must read a single byte.
+// If there is no byte to read,
+// set d.err to SyntaxError("unexpected EOF")
+// and return ok==false
+func (d *Decoder) mustgetc() (b byte, ok bool) {
+	if b, ok = d.getc(); !ok {
+		if d.err == io.EOF {
+			d.err = d.syntaxError("unexpected EOF")
+		}
+	}
+	return
+}
+
+// Unread a single byte.
+func (d *Decoder) ungetc(b byte) {
+	if b == '\n' {
+		d.line--
+	}
+	d.nextByte = int(b)
+}
+
+var entity = map[string]int{
+	"lt":   '<',
+	"gt":   '>',
+	"amp":  '&',
+	"apos": '\'',
+	"quot": '"',
+}
+
+// Read plain text section (XML calls it character data).
+// If quote >= 0, we are in a quoted string and need to find the matching quote.
+// If cdata == true, we are in a <![CDATA[ section and need to find ]]>.
+// On failure return nil and leave the error in d.err.
+func (d *Decoder) text(quote int, cdata bool) []byte {
+	var b0, b1 byte
+	var trunc int
+	d.buf.Reset()
+Input:
+	for {
+		b, ok := d.getc()
+		if !ok {
+			if cdata {
+				if d.err == io.EOF {
+					d.err = d.syntaxError("unexpected EOF in CDATA section")
+				}
+				return nil
+			}
+			break Input
+		}
+
+		// <![CDATA[ section ends with ]]>.
+		// It is an error for ]]> to appear in ordinary text.
+		if b0 == ']' && b1 == ']' && b == '>' {
+			if cdata {
+				trunc = 2
+				break Input
+			}
+			d.err = d.syntaxError("unescaped ]]> not in CDATA section")
+			return nil
+		}
+
+		// Stop reading text if we see a <.
+		if b == '<' && !cdata {
+			if quote >= 0 {
+				d.err = d.syntaxError("unescaped < inside quoted string")
+				return nil
+			}
+			d.ungetc('<')
+			break Input
+		}
+		if quote >= 0 && b == byte(quote) {
+			break Input
+		}
+		if b == '&' && !cdata {
+			// Read escaped character expression up to semicolon.
+			// XML in all its glory allows a document to define and use
+			// its own character names with <!ENTITY ...> directives.
+			// Parsers are required to recognize lt, gt, amp, apos, and quot
+			// even if they have not been declared.
+			before := d.buf.Len()
+			d.buf.WriteByte('&')
+			var ok bool
+			var text string
+			var haveText bool
+			if b, ok = d.mustgetc(); !ok {
+				return nil
+			}
+			if b == '#' {
+				d.buf.WriteByte(b)
+				if b, ok = d.mustgetc(); !ok {
+					return nil
+				}
+				base := 10
+				if b == 'x' {
+					base = 16
+					d.buf.WriteByte(b)
+					if b, ok = d.mustgetc(); !ok {
+						return nil
+					}
+				}
+				start := d.buf.Len()
+				for '0' <= b && b <= '9' ||
+					base == 16 && 'a' <= b && b <= 'f' ||
+					base == 16 && 'A' <= b && b <= 'F' {
+					d.buf.WriteByte(b)
+					if b, ok = d.mustgetc(); !ok {
+						return nil
+					}
+				}
+				if b != ';' {
+					d.ungetc(b)
+				} else {
+					s := string(d.buf.Bytes()[start:])
+					d.buf.WriteByte(';')
+					n, err := strconv.ParseUint(s, base, 64)
+					if err == nil && n <= unicode.MaxRune {
+						text = string(n)
+						haveText = true
+					}
+				}
+			} else {
+				d.ungetc(b)
+				if !d.readName() {
+					if d.err != nil {
+						return nil
+					}
+					ok = false
+				}
+				if b, ok = d.mustgetc(); !ok {
+					return nil
+				}
+				if b != ';' {
+					d.ungetc(b)
+				} else {
+					name := d.buf.Bytes()[before+1:]
+					d.buf.WriteByte(';')
+					if isName(name) {
+						s := string(name)
+						if r, ok := entity[s]; ok {
+							text = string(r)
+							haveText = true
+						} else if d.Entity != nil {
+							text, haveText = d.Entity[s]
+						}
+					}
+				}
+			}
+
+			if haveText {
+				d.buf.Truncate(before)
+				d.buf.Write([]byte(text))
+				b0, b1 = 0, 0
+				continue Input
+			}
+			if !d.Strict {
+				b0, b1 = 0, 0
+				continue Input
+			}
+			ent := string(d.buf.Bytes()[before:])
+			if ent[len(ent)-1] != ';' {
+				ent += " (no semicolon)"
+			}
+			d.err = d.syntaxError("invalid character entity " + ent)
+			return nil
+		}
+
+		// We must rewrite unescaped \r and \r\n into \n.
+		if b == '\r' {
+			d.buf.WriteByte('\n')
+		} else if b1 == '\r' && b == '\n' {
+			// Skip \r\n--we already wrote \n.
+		} else {
+			d.buf.WriteByte(b)
+		}
+
+		b0, b1 = b1, b
+	}
+	data := d.buf.Bytes()
+	data = data[0 : len(data)-trunc]
+
+	// Inspect each rune for being a disallowed character.
+	buf := data
+	for len(buf) > 0 {
+		r, size := utf8.DecodeRune(buf)
+		if r == utf8.RuneError && size == 1 {
+			d.err = d.syntaxError("invalid UTF-8")
+			return nil
+		}
+		buf = buf[size:]
+		if !isInCharacterRange(r) {
+			d.err = d.syntaxError(fmt.Sprintf("illegal character code %U", r))
+			return nil
+		}
+	}
+
+	return data
+}
+
+// Decide whether the given rune is in the XML Character Range, per
+// the Char production of http://www.xml.com/axml/testaxml.htm,
+// Section 2.2 Characters.
+func isInCharacterRange(r rune) (inrange bool) {
+	return r == 0x09 ||
+		r == 0x0A ||
+		r == 0x0D ||
+		r >= 0x20 && r <= 0xDF77 ||
+		r >= 0xE000 && r <= 0xFFFD ||
+		r >= 0x10000 && r <= 0x10FFFF
+}
+
+// Get name space name: name with a : stuck in the middle.
+// The part before the : is the name space identifier.
+func (d *Decoder) nsname() (name Name, ok bool) {
+	s, ok := d.name()
+	if !ok {
+		return
+	}
+	i := strings.Index(s, ":")
+	if i < 0 {
+		name.Local = s
+	} else {
+		name.Space = s[0:i]
+		name.Local = s[i+1:]
+	}
+	return name, true
+}
+
+// Get name: /first(first|second)*/
+// Do not set d.err if the name is missing (unless unexpected EOF is received):
+// let the caller provide better context.
+func (d *Decoder) name() (s string, ok bool) {
+	d.buf.Reset()
+	if !d.readName() {
+		return "", false
+	}
+
+	// Now we check the characters.
+	s = d.buf.String()
+	if !isName([]byte(s)) {
+		d.err = d.syntaxError("invalid XML name: " + s)
+		return "", false
+	}
+	return s, true
+}
+
+// Read a name and append its bytes to d.buf.
+// The name is delimited by any single-byte character not valid in names.
+// All multi-byte characters are accepted; the caller must check their validity.
+func (d *Decoder) readName() (ok bool) {
+	var b byte
+	if b, ok = d.mustgetc(); !ok {
+		return
+	}
+	if b < utf8.RuneSelf && !isNameByte(b) {
+		d.ungetc(b)
+		return false
+	}
+	d.buf.WriteByte(b)
+
+	for {
+		if b, ok = d.mustgetc(); !ok {
+			return
+		}
+		if b < utf8.RuneSelf && !isNameByte(b) {
+			d.ungetc(b)
+			break
+		}
+		d.buf.WriteByte(b)
+	}
+	return true
+}
+
+func isNameByte(c byte) bool {
+	return 'A' <= c && c <= 'Z' ||
+		'a' <= c && c <= 'z' ||
+		'0' <= c && c <= '9' ||
+		c == '_' || c == ':' || c == '.' || c == '-'
+}
+
+func isName(s []byte) bool {
+	if len(s) == 0 {
+		return false
+	}
+	c, n := utf8.DecodeRune(s)
+	if c == utf8.RuneError && n == 1 {
+		return false
+	}
+	if !unicode.Is(first, c) {
+		return false
+	}
+	for n < len(s) {
+		s = s[n:]
+		c, n = utf8.DecodeRune(s)
+		if c == utf8.RuneError && n == 1 {
+			return false
+		}
+		if !unicode.Is(first, c) && !unicode.Is(second, c) {
+			return false
+		}
+	}
+	return true
+}
+
+func isNameString(s string) bool {
+	if len(s) == 0 {
+		return false
+	}
+	c, n := utf8.DecodeRuneInString(s)
+	if c == utf8.RuneError && n == 1 {
+		return false
+	}
+	if !unicode.Is(first, c) {
+		return false
+	}
+	for n < len(s) {
+		s = s[n:]
+		c, n = utf8.DecodeRuneInString(s)
+		if c == utf8.RuneError && n == 1 {
+			return false
+		}
+		if !unicode.Is(first, c) && !unicode.Is(second, c) {
+			return false
+		}
+	}
+	return true
+}
+
+// These tables were generated by cut and paste from Appendix B of
+// the XML spec at http://www.xml.com/axml/testaxml.htm
+// and then reformatting.  First corresponds to (Letter | '_' | ':')
+// and second corresponds to NameChar.
+
+var first = &unicode.RangeTable{
+	R16: []unicode.Range16{
+		{0x003A, 0x003A, 1},
+		{0x0041, 0x005A, 1},
+		{0x005F, 0x005F, 1},
+		{0x0061, 0x007A, 1},
+		{0x00C0, 0x00D6, 1},
+		{0x00D8, 0x00F6, 1},
+		{0x00F8, 0x00FF, 1},
+		{0x0100, 0x0131, 1},
+		{0x0134, 0x013E, 1},
+		{0x0141, 0x0148, 1},
+		{0x014A, 0x017E, 1},
+		{0x0180, 0x01C3, 1},
+		{0x01CD, 0x01F0, 1},
+		{0x01F4, 0x01F5, 1},
+		{0x01FA, 0x0217, 1},
+		{0x0250, 0x02A8, 1},
+		{0x02BB, 0x02C1, 1},
+		{0x0386, 0x0386, 1},
+		{0x0388, 0x038A, 1},
+		{0x038C, 0x038C, 1},
+		{0x038E, 0x03A1, 1},
+		{0x03A3, 0x03CE, 1},
+		{0x03D0, 0x03D6, 1},
+		{0x03DA, 0x03E0, 2},
+		{0x03E2, 0x03F3, 1},
+		{0x0401, 0x040C, 1},
+		{0x040E, 0x044F, 1},
+		{0x0451, 0x045C, 1},
+		{0x045E, 0x0481, 1},
+		{0x0490, 0x04C4, 1},
+		{0x04C7, 0x04C8, 1},
+		{0x04CB, 0x04CC, 1},
+		{0x04D0, 0x04EB, 1},
+		{0x04EE, 0x04F5, 1},
+		{0x04F8, 0x04F9, 1},
+		{0x0531, 0x0556, 1},
+		{0x0559, 0x0559, 1},
+		{0x0561, 0x0586, 1},
+		{0x05D0, 0x05EA, 1},
+		{0x05F0, 0x05F2, 1},
+		{0x0621, 0x063A, 1},
+		{0x0641, 0x064A, 1},
+		{0x0671, 0x06B7, 1},
+		{0x06BA, 0x06BE, 1},
+		{0x06C0, 0x06CE, 1},
+		{0x06D0, 0x06D3, 1},
+		{0x06D5, 0x06D5, 1},
+		{0x06E5, 0x06E6, 1},
+		{0x0905, 0x0939, 1},
+		{0x093D, 0x093D, 1},
+		{0x0958, 0x0961, 1},
+		{0x0985, 0x098C, 1},
+		{0x098F, 0x0990, 1},
+		{0x0993, 0x09A8, 1},
+		{0x09AA, 0x09B0, 1},
+		{0x09B2, 0x09B2, 1},
+		{0x09B6, 0x09B9, 1},
+		{0x09DC, 0x09DD, 1},
+		{0x09DF, 0x09E1, 1},
+		{0x09F0, 0x09F1, 1},
+		{0x0A05, 0x0A0A, 1},
+		{0x0A0F, 0x0A10, 1},
+		{0x0A13, 0x0A28, 1},
+		{0x0A2A, 0x0A30, 1},
+		{0x0A32, 0x0A33, 1},
+		{0x0A35, 0x0A36, 1},
+		{0x0A38, 0x0A39, 1},
+		{0x0A59, 0x0A5C, 1},
+		{0x0A5E, 0x0A5E, 1},
+		{0x0A72, 0x0A74, 1},
+		{0x0A85, 0x0A8B, 1},
+		{0x0A8D, 0x0A8D, 1},
+		{0x0A8F, 0x0A91, 1},
+		{0x0A93, 0x0AA8, 1},
+		{0x0AAA, 0x0AB0, 1},
+		{0x0AB2, 0x0AB3, 1},
+		{0x0AB5, 0x0AB9, 1},
+		{0x0ABD, 0x0AE0, 0x23},
+		{0x0B05, 0x0B0C, 1},
+		{0x0B0F, 0x0B10, 1},
+		{0x0B13, 0x0B28, 1},
+		{0x0B2A, 0x0B30, 1},
+		{0x0B32, 0x0B33, 1},
+		{0x0B36, 0x0B39, 1},
+		{0x0B3D, 0x0B3D, 1},
+		{0x0B5C, 0x0B5D, 1},
+		{0x0B5F, 0x0B61, 1},
+		{0x0B85, 0x0B8A, 1},
+		{0x0B8E, 0x0B90, 1},
+		{0x0B92, 0x0B95, 1},
+		{0x0B99, 0x0B9A, 1},
+		{0x0B9C, 0x0B9C, 1},
+		{0x0B9E, 0x0B9F, 1},
+		{0x0BA3, 0x0BA4, 1},
+		{0x0BA8, 0x0BAA, 1},
+		{0x0BAE, 0x0BB5, 1},
+		{0x0BB7, 0x0BB9, 1},
+		{0x0C05, 0x0C0C, 1},
+		{0x0C0E, 0x0C10, 1},
+		{0x0C12, 0x0C28, 1},
+		{0x0C2A, 0x0C33, 1},
+		{0x0C35, 0x0C39, 1},
+		{0x0C60, 0x0C61, 1},
+		{0x0C85, 0x0C8C, 1},
+		{0x0C8E, 0x0C90, 1},
+		{0x0C92, 0x0CA8, 1},
+		{0x0CAA, 0x0CB3, 1},
+		{0x0CB5, 0x0CB9, 1},
+		{0x0CDE, 0x0CDE, 1},
+		{0x0CE0, 0x0CE1, 1},
+		{0x0D05, 0x0D0C, 1},
+		{0x0D0E, 0x0D10, 1},
+		{0x0D12, 0x0D28, 1},
+		{0x0D2A, 0x0D39, 1},
+		{0x0D60, 0x0D61, 1},
+		{0x0E01, 0x0E2E, 1},
+		{0x0E30, 0x0E30, 1},
+		{0x0E32, 0x0E33, 1},
+		{0x0E40, 0x0E45, 1},
+		{0x0E81, 0x0E82, 1},
+		{0x0E84, 0x0E84, 1},
+		{0x0E87, 0x0E88, 1},
+		{0x0E8A, 0x0E8D, 3},
+		{0x0E94, 0x0E97, 1},
+		{0x0E99, 0x0E9F, 1},
+		{0x0EA1, 0x0EA3, 1},
+		{0x0EA5, 0x0EA7, 2},
+		{0x0EAA, 0x0EAB, 1},
+		{0x0EAD, 0x0EAE, 1},
+		{0x0EB0, 0x0EB0, 1},
+		{0x0EB2, 0x0EB3, 1},
+		{0x0EBD, 0x0EBD, 1},
+		{0x0EC0, 0x0EC4, 1},
+		{0x0F40, 0x0F47, 1},
+		{0x0F49, 0x0F69, 1},
+		{0x10A0, 0x10C5, 1},
+		{0x10D0, 0x10F6, 1},
+		{0x1100, 0x1100, 1},
+		{0x1102, 0x1103, 1},
+		{0x1105, 0x1107, 1},
+		{0x1109, 0x1109, 1},
+		{0x110B, 0x110C, 1},
+		{0x110E, 0x1112, 1},
+		{0x113C, 0x1140, 2},
+		{0x114C, 0x1150, 2},
+		{0x1154, 0x1155, 1},
+		{0x1159, 0x1159, 1},
+		{0x115F, 0x1161, 1},
+		{0x1163, 0x1169, 2},
+		{0x116D, 0x116E, 1},
+		{0x1172, 0x1173, 1},
+		{0x1175, 0x119E, 0x119E - 0x1175},
+		{0x11A8, 0x11AB, 0x11AB - 0x11A8},
+		{0x11AE, 0x11AF, 1},
+		{0x11B7, 0x11B8, 1},
+		{0x11BA, 0x11BA, 1},
+		{0x11BC, 0x11C2, 1},
+		{0x11EB, 0x11F0, 0x11F0 - 0x11EB},
+		{0x11F9, 0x11F9, 1},
+		{0x1E00, 0x1E9B, 1},
+		{0x1EA0, 0x1EF9, 1},
+		{0x1F00, 0x1F15, 1},
+		{0x1F18, 0x1F1D, 1},
+		{0x1F20, 0x1F45, 1},
+		{0x1F48, 0x1F4D, 1},
+		{0x1F50, 0x1F57, 1},
+		{0x1F59, 0x1F5B, 0x1F5B - 0x1F59},
+		{0x1F5D, 0x1F5D, 1},
+		{0x1F5F, 0x1F7D, 1},
+		{0x1F80, 0x1FB4, 1},
+		{0x1FB6, 0x1FBC, 1},
+		{0x1FBE, 0x1FBE, 1},
+		{0x1FC2, 0x1FC4, 1},
+		{0x1FC6, 0x1FCC, 1},
+		{0x1FD0, 0x1FD3, 1},
+		{0x1FD6, 0x1FDB, 1},
+		{0x1FE0, 0x1FEC, 1},
+		{0x1FF2, 0x1FF4, 1},
+		{0x1FF6, 0x1FFC, 1},
+		{0x2126, 0x2126, 1},
+		{0x212A, 0x212B, 1},
+		{0x212E, 0x212E, 1},
+		{0x2180, 0x2182, 1},
+		{0x3007, 0x3007, 1},
+		{0x3021, 0x3029, 1},
+		{0x3041, 0x3094, 1},
+		{0x30A1, 0x30FA, 1},
+		{0x3105, 0x312C, 1},
+		{0x4E00, 0x9FA5, 1},
+		{0xAC00, 0xD7A3, 1},
+	},
+}
+
+var second = &unicode.RangeTable{
+	R16: []unicode.Range16{
+		{0x002D, 0x002E, 1},
+		{0x0030, 0x0039, 1},
+		{0x00B7, 0x00B7, 1},
+		{0x02D0, 0x02D1, 1},
+		{0x0300, 0x0345, 1},
+		{0x0360, 0x0361, 1},
+		{0x0387, 0x0387, 1},
+		{0x0483, 0x0486, 1},
+		{0x0591, 0x05A1, 1},
+		{0x05A3, 0x05B9, 1},
+		{0x05BB, 0x05BD, 1},
+		{0x05BF, 0x05BF, 1},
+		{0x05C1, 0x05C2, 1},
+		{0x05C4, 0x0640, 0x0640 - 0x05C4},
+		{0x064B, 0x0652, 1},
+		{0x0660, 0x0669, 1},
+		{0x0670, 0x0670, 1},
+		{0x06D6, 0x06DC, 1},
+		{0x06DD, 0x06DF, 1},
+		{0x06E0, 0x06E4, 1},
+		{0x06E7, 0x06E8, 1},
+		{0x06EA, 0x06ED, 1},
+		{0x06F0, 0x06F9, 1},
+		{0x0901, 0x0903, 1},
+		{0x093C, 0x093C, 1},
+		{0x093E, 0x094C, 1},
+		{0x094D, 0x094D, 1},
+		{0x0951, 0x0954, 1},
+		{0x0962, 0x0963, 1},
+		{0x0966, 0x096F, 1},
+		{0x0981, 0x0983, 1},
+		{0x09BC, 0x09BC, 1},
+		{0x09BE, 0x09BF, 1},
+		{0x09C0, 0x09C4, 1},
+		{0x09C7, 0x09C8, 1},
+		{0x09CB, 0x09CD, 1},
+		{0x09D7, 0x09D7, 1},
+		{0x09E2, 0x09E3, 1},
+		{0x09E6, 0x09EF, 1},
+		{0x0A02, 0x0A3C, 0x3A},
+		{0x0A3E, 0x0A3F, 1},
+		{0x0A40, 0x0A42, 1},
+		{0x0A47, 0x0A48, 1},
+		{0x0A4B, 0x0A4D, 1},
+		{0x0A66, 0x0A6F, 1},
+		{0x0A70, 0x0A71, 1},
+		{0x0A81, 0x0A83, 1},
+		{0x0ABC, 0x0ABC, 1},
+		{0x0ABE, 0x0AC5, 1},
+		{0x0AC7, 0x0AC9, 1},
+		{0x0ACB, 0x0ACD, 1},
+		{0x0AE6, 0x0AEF, 1},
+		{0x0B01, 0x0B03, 1},
+		{0x0B3C, 0x0B3C, 1},
+		{0x0B3E, 0x0B43, 1},
+		{0x0B47, 0x0B48, 1},
+		{0x0B4B, 0x0B4D, 1},
+		{0x0B56, 0x0B57, 1},
+		{0x0B66, 0x0B6F, 1},
+		{0x0B82, 0x0B83, 1},
+		{0x0BBE, 0x0BC2, 1},
+		{0x0BC6, 0x0BC8, 1},
+		{0x0BCA, 0x0BCD, 1},
+		{0x0BD7, 0x0BD7, 1},
+		{0x0BE7, 0x0BEF, 1},
+		{0x0C01, 0x0C03, 1},
+		{0x0C3E, 0x0C44, 1},
+		{0x0C46, 0x0C48, 1},
+		{0x0C4A, 0x0C4D, 1},
+		{0x0C55, 0x0C56, 1},
+		{0x0C66, 0x0C6F, 1},
+		{0x0C82, 0x0C83, 1},
+		{0x0CBE, 0x0CC4, 1},
+		{0x0CC6, 0x0CC8, 1},
+		{0x0CCA, 0x0CCD, 1},
+		{0x0CD5, 0x0CD6, 1},
+		{0x0CE6, 0x0CEF, 1},
+		{0x0D02, 0x0D03, 1},
+		{0x0D3E, 0x0D43, 1},
+		{0x0D46, 0x0D48, 1},
+		{0x0D4A, 0x0D4D, 1},
+		{0x0D57, 0x0D57, 1},
+		{0x0D66, 0x0D6F, 1},
+		{0x0E31, 0x0E31, 1},
+		{0x0E34, 0x0E3A, 1},
+		{0x0E46, 0x0E46, 1},
+		{0x0E47, 0x0E4E, 1},
+		{0x0E50, 0x0E59, 1},
+		{0x0EB1, 0x0EB1, 1},
+		{0x0EB4, 0x0EB9, 1},
+		{0x0EBB, 0x0EBC, 1},
+		{0x0EC6, 0x0EC6, 1},
+		{0x0EC8, 0x0ECD, 1},
+		{0x0ED0, 0x0ED9, 1},
+		{0x0F18, 0x0F19, 1},
+		{0x0F20, 0x0F29, 1},
+		{0x0F35, 0x0F39, 2},
+		{0x0F3E, 0x0F3F, 1},
+		{0x0F71, 0x0F84, 1},
+		{0x0F86, 0x0F8B, 1},
+		{0x0F90, 0x0F95, 1},
+		{0x0F97, 0x0F97, 1},
+		{0x0F99, 0x0FAD, 1},
+		{0x0FB1, 0x0FB7, 1},
+		{0x0FB9, 0x0FB9, 1},
+		{0x20D0, 0x20DC, 1},
+		{0x20E1, 0x3005, 0x3005 - 0x20E1},
+		{0x302A, 0x302F, 1},
+		{0x3031, 0x3035, 1},
+		{0x3099, 0x309A, 1},
+		{0x309D, 0x309E, 1},
+		{0x30FC, 0x30FE, 1},
+	},
+}
+
+// HTMLEntity is an entity map containing translations for the
+// standard HTML entity characters.
+var HTMLEntity = htmlEntity
+
+var htmlEntity = map[string]string{
+	/*
+		hget http://www.w3.org/TR/html4/sgml/entities.html |
+		ssam '
+			,y /\&gt;/ x/\&lt;(.|\n)+/ s/\n/ /g
+			,x v/^\&lt;!ENTITY/d
+			,s/\&lt;!ENTITY ([^ ]+) .*U\+([0-9A-F][0-9A-F][0-9A-F][0-9A-F]) .+/	"\1": "\\u\2",/g
+		'
+	*/
+	"nbsp":     "\u00A0",
+	"iexcl":    "\u00A1",
+	"cent":     "\u00A2",
+	"pound":    "\u00A3",
+	"curren":   "\u00A4",
+	"yen":      "\u00A5",
+	"brvbar":   "\u00A6",
+	"sect":     "\u00A7",
+	"uml":      "\u00A8",
+	"copy":     "\u00A9",
+	"ordf":     "\u00AA",
+	"laquo":    "\u00AB",
+	"not":      "\u00AC",
+	"shy":      "\u00AD",
+	"reg":      "\u00AE",
+	"macr":     "\u00AF",
+	"deg":      "\u00B0",
+	"plusmn":   "\u00B1",
+	"sup2":     "\u00B2",
+	"sup3":     "\u00B3",
+	"acute":    "\u00B4",
+	"micro":    "\u00B5",
+	"para":     "\u00B6",
+	"middot":   "\u00B7",
+	"cedil":    "\u00B8",
+	"sup1":     "\u00B9",
+	"ordm":     "\u00BA",
+	"raquo":    "\u00BB",
+	"frac14":   "\u00BC",
+	"frac12":   "\u00BD",
+	"frac34":   "\u00BE",
+	"iquest":   "\u00BF",
+	"Agrave":   "\u00C0",
+	"Aacute":   "\u00C1",
+	"Acirc":    "\u00C2",
+	"Atilde":   "\u00C3",
+	"Auml":     "\u00C4",
+	"Aring":    "\u00C5",
+	"AElig":    "\u00C6",
+	"Ccedil":   "\u00C7",
+	"Egrave":   "\u00C8",
+	"Eacute":   "\u00C9",
+	"Ecirc":    "\u00CA",
+	"Euml":     "\u00CB",
+	"Igrave":   "\u00CC",
+	"Iacute":   "\u00CD",
+	"Icirc":    "\u00CE",
+	"Iuml":     "\u00CF",
+	"ETH":      "\u00D0",
+	"Ntilde":   "\u00D1",
+	"Ograve":   "\u00D2",
+	"Oacute":   "\u00D3",
+	"Ocirc":    "\u00D4",
+	"Otilde":   "\u00D5",
+	"Ouml":     "\u00D6",
+	"times":    "\u00D7",
+	"Oslash":   "\u00D8",
+	"Ugrave":   "\u00D9",
+	"Uacute":   "\u00DA",
+	"Ucirc":    "\u00DB",
+	"Uuml":     "\u00DC",
+	"Yacute":   "\u00DD",
+	"THORN":    "\u00DE",
+	"szlig":    "\u00DF",
+	"agrave":   "\u00E0",
+	"aacute":   "\u00E1",
+	"acirc":    "\u00E2",
+	"atilde":   "\u00E3",
+	"auml":     "\u00E4",
+	"aring":    "\u00E5",
+	"aelig":    "\u00E6",
+	"ccedil":   "\u00E7",
+	"egrave":   "\u00E8",
+	"eacute":   "\u00E9",
+	"ecirc":    "\u00EA",
+	"euml":     "\u00EB",
+	"igrave":   "\u00EC",
+	"iacute":   "\u00ED",
+	"icirc":    "\u00EE",
+	"iuml":     "\u00EF",
+	"eth":      "\u00F0",
+	"ntilde":   "\u00F1",
+	"ograve":   "\u00F2",
+	"oacute":   "\u00F3",
+	"ocirc":    "\u00F4",
+	"otilde":   "\u00F5",
+	"ouml":     "\u00F6",
+	"divide":   "\u00F7",
+	"oslash":   "\u00F8",
+	"ugrave":   "\u00F9",
+	"uacute":   "\u00FA",
+	"ucirc":    "\u00FB",
+	"uuml":     "\u00FC",
+	"yacute":   "\u00FD",
+	"thorn":    "\u00FE",
+	"yuml":     "\u00FF",
+	"fnof":     "\u0192",
+	"Alpha":    "\u0391",
+	"Beta":     "\u0392",
+	"Gamma":    "\u0393",
+	"Delta":    "\u0394",
+	"Epsilon":  "\u0395",
+	"Zeta":     "\u0396",
+	"Eta":      "\u0397",
+	"Theta":    "\u0398",
+	"Iota":     "\u0399",
+	"Kappa":    "\u039A",
+	"Lambda":   "\u039B",
+	"Mu":       "\u039C",
+	"Nu":       "\u039D",
+	"Xi":       "\u039E",
+	"Omicron":  "\u039F",
+	"Pi":       "\u03A0",
+	"Rho":      "\u03A1",
+	"Sigma":    "\u03A3",
+	"Tau":      "\u03A4",
+	"Upsilon":  "\u03A5",
+	"Phi":      "\u03A6",
+	"Chi":      "\u03A7",
+	"Psi":      "\u03A8",
+	"Omega":    "\u03A9",
+	"alpha":    "\u03B1",
+	"beta":     "\u03B2",
+	"gamma":    "\u03B3",
+	"delta":    "\u03B4",
+	"epsilon":  "\u03B5",
+	"zeta":     "\u03B6",
+	"eta":      "\u03B7",
+	"theta":    "\u03B8",
+	"iota":     "\u03B9",
+	"kappa":    "\u03BA",
+	"lambda":   "\u03BB",
+	"mu":       "\u03BC",
+	"nu":       "\u03BD",
+	"xi":       "\u03BE",
+	"omicron":  "\u03BF",
+	"pi":       "\u03C0",
+	"rho":      "\u03C1",
+	"sigmaf":   "\u03C2",
+	"sigma":    "\u03C3",
+	"tau":      "\u03C4",
+	"upsilon":  "\u03C5",
+	"phi":      "\u03C6",
+	"chi":      "\u03C7",
+	"psi":      "\u03C8",
+	"omega":    "\u03C9",
+	"thetasym": "\u03D1",
+	"upsih":    "\u03D2",
+	"piv":      "\u03D6",
+	"bull":     "\u2022",
+	"hellip":   "\u2026",
+	"prime":    "\u2032",
+	"Prime":    "\u2033",
+	"oline":    "\u203E",
+	"frasl":    "\u2044",
+	"weierp":   "\u2118",
+	"image":    "\u2111",
+	"real":     "\u211C",
+	"trade":    "\u2122",
+	"alefsym":  "\u2135",
+	"larr":     "\u2190",
+	"uarr":     "\u2191",
+	"rarr":     "\u2192",
+	"darr":     "\u2193",
+	"harr":     "\u2194",
+	"crarr":    "\u21B5",
+	"lArr":     "\u21D0",
+	"uArr":     "\u21D1",
+	"rArr":     "\u21D2",
+	"dArr":     "\u21D3",
+	"hArr":     "\u21D4",
+	"forall":   "\u2200",
+	"part":     "\u2202",
+	"exist":    "\u2203",
+	"empty":    "\u2205",
+	"nabla":    "\u2207",
+	"isin":     "\u2208",
+	"notin":    "\u2209",
+	"ni":       "\u220B",
+	"prod":     "\u220F",
+	"sum":      "\u2211",
+	"minus":    "\u2212",
+	"lowast":   "\u2217",
+	"radic":    "\u221A",
+	"prop":     "\u221D",
+	"infin":    "\u221E",
+	"ang":      "\u2220",
+	"and":      "\u2227",
+	"or":       "\u2228",
+	"cap":      "\u2229",
+	"cup":      "\u222A",
+	"int":      "\u222B",
+	"there4":   "\u2234",
+	"sim":      "\u223C",
+	"cong":     "\u2245",
+	"asymp":    "\u2248",
+	"ne":       "\u2260",
+	"equiv":    "\u2261",
+	"le":       "\u2264",
+	"ge":       "\u2265",
+	"sub":      "\u2282",
+	"sup":      "\u2283",
+	"nsub":     "\u2284",
+	"sube":     "\u2286",
+	"supe":     "\u2287",
+	"oplus":    "\u2295",
+	"otimes":   "\u2297",
+	"perp":     "\u22A5",
+	"sdot":     "\u22C5",
+	"lceil":    "\u2308",
+	"rceil":    "\u2309",
+	"lfloor":   "\u230A",
+	"rfloor":   "\u230B",
+	"lang":     "\u2329",
+	"rang":     "\u232A",
+	"loz":      "\u25CA",
+	"spades":   "\u2660",
+	"clubs":    "\u2663",
+	"hearts":   "\u2665",
+	"diams":    "\u2666",
+	"quot":     "\u0022",
+	"amp":      "\u0026",
+	"lt":       "\u003C",
+	"gt":       "\u003E",
+	"OElig":    "\u0152",
+	"oelig":    "\u0153",
+	"Scaron":   "\u0160",
+	"scaron":   "\u0161",
+	"Yuml":     "\u0178",
+	"circ":     "\u02C6",
+	"tilde":    "\u02DC",
+	"ensp":     "\u2002",
+	"emsp":     "\u2003",
+	"thinsp":   "\u2009",
+	"zwnj":     "\u200C",
+	"zwj":      "\u200D",
+	"lrm":      "\u200E",
+	"rlm":      "\u200F",
+	"ndash":    "\u2013",
+	"mdash":    "\u2014",
+	"lsquo":    "\u2018",
+	"rsquo":    "\u2019",
+	"sbquo":    "\u201A",
+	"ldquo":    "\u201C",
+	"rdquo":    "\u201D",
+	"bdquo":    "\u201E",
+	"dagger":   "\u2020",
+	"Dagger":   "\u2021",
+	"permil":   "\u2030",
+	"lsaquo":   "\u2039",
+	"rsaquo":   "\u203A",
+	"euro":     "\u20AC",
+}
+
+// HTMLAutoClose is the set of HTML elements that
+// should be considered to close automatically.
+var HTMLAutoClose = htmlAutoClose
+
+var htmlAutoClose = []string{
+	/*
+		hget http://www.w3.org/TR/html4/loose.dtd |
+		9 sed -n 's/<!ELEMENT ([^ ]*) +- O EMPTY.+/	"\1",/p' | tr A-Z a-z
+	*/
+	"basefont",
+	"br",
+	"area",
+	"link",
+	"img",
+	"param",
+	"hr",
+	"input",
+	"col",
+	"frame",
+	"isindex",
+	"base",
+	"meta",
+}
+
+var (
+	esc_quot = []byte("&#34;") // shorter than "&quot;"
+	esc_apos = []byte("&#39;") // shorter than "&apos;"
+	esc_amp  = []byte("&amp;")
+	esc_lt   = []byte("&lt;")
+	esc_gt   = []byte("&gt;")
+	esc_tab  = []byte("&#x9;")
+	esc_nl   = []byte("&#xA;")
+	esc_cr   = []byte("&#xD;")
+	esc_fffd = []byte("\uFFFD") // Unicode replacement character
+)
+
+// EscapeText writes to w the properly escaped XML equivalent
+// of the plain text data s.
+func EscapeText(w io.Writer, s []byte) error {
+	var esc []byte
+	last := 0
+	for i := 0; i < len(s); {
+		r, width := utf8.DecodeRune(s[i:])
+		i += width
+		switch r {
+		case '"':
+			esc = esc_quot
+		case '\'':
+			esc = esc_apos
+		case '&':
+			esc = esc_amp
+		case '<':
+			esc = esc_lt
+		case '>':
+			esc = esc_gt
+		case '\t':
+			esc = esc_tab
+		case '\n':
+			esc = esc_nl
+		case '\r':
+			esc = esc_cr
+		default:
+			if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
+				esc = esc_fffd
+				break
+			}
+			continue
+		}
+		if _, err := w.Write(s[last : i-width]); err != nil {
+			return err
+		}
+		if _, err := w.Write(esc); err != nil {
+			return err
+		}
+		last = i
+	}
+	if _, err := w.Write(s[last:]); err != nil {
+		return err
+	}
+	return nil
+}
+
+// EscapeString writes to p the properly escaped XML equivalent
+// of the plain text data s.
+func (p *printer) EscapeString(s string) {
+	var esc []byte
+	last := 0
+	for i := 0; i < len(s); {
+		r, width := utf8.DecodeRuneInString(s[i:])
+		i += width
+		switch r {
+		case '"':
+			esc = esc_quot
+		case '\'':
+			esc = esc_apos
+		case '&':
+			esc = esc_amp
+		case '<':
+			esc = esc_lt
+		case '>':
+			esc = esc_gt
+		case '\t':
+			esc = esc_tab
+		case '\n':
+			esc = esc_nl
+		case '\r':
+			esc = esc_cr
+		default:
+			if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
+				esc = esc_fffd
+				break
+			}
+			continue
+		}
+		p.WriteString(s[last : i-width])
+		p.Write(esc)
+		last = i
+	}
+	p.WriteString(s[last:])
+}
+
+// Escape is like EscapeText but omits the error return value.
+// It is provided for backwards compatibility with Go 1.0.
+// Code targeting Go 1.1 or later should use EscapeText.
+func Escape(w io.Writer, s []byte) {
+	EscapeText(w, s)
+}
+
+// procInstEncoding parses the `encoding="..."` or `encoding='...'`
+// value out of the provided string, returning "" if not found.
+func procInstEncoding(s string) string {
+	// TODO: this parsing is somewhat lame and not exact.
+	// It works for all actual cases, though.
+	idx := strings.Index(s, "encoding=")
+	if idx == -1 {
+		return ""
+	}
+	v := s[idx+len("encoding="):]
+	if v == "" {
+		return ""
+	}
+	if v[0] != '\'' && v[0] != '"' {
+		return ""
+	}
+	idx = strings.IndexRune(v[1:], rune(v[0]))
+	if idx == -1 {
+		return ""
+	}
+	return v[1 : idx+1]
+}
diff --git a/third_party/gofrontend/libgo/go/encoding/xml/xml_test.go b/third_party/gofrontend/libgo/go/encoding/xml/xml_test.go
new file mode 100644
index 0000000..7723ab1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/encoding/xml/xml_test.go
@@ -0,0 +1,726 @@
+// 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 xml
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"strings"
+	"testing"
+	"unicode/utf8"
+)
+
+const testInput = `
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<body xmlns:foo="ns1" xmlns="ns2" xmlns:tag="ns3" ` +
+	"\r\n\t" + `  >
+  <hello lang="en">World &lt;&gt;&apos;&quot; &#x767d;&#40300;翔</hello>
+  <query>&何; &is-it;</query>
+  <goodbye />
+  <outer foo:attr="value" xmlns:tag="ns4">
+    <inner/>
+  </outer>
+  <tag:name>
+    <![CDATA[Some text here.]]>
+  </tag:name>
+</body><!-- missing final newline -->`
+
+var testEntity = map[string]string{"何": "What", "is-it": "is it?"}
+
+var rawTokens = []Token{
+	CharData("\n"),
+	ProcInst{"xml", []byte(`version="1.0" encoding="UTF-8"`)},
+	CharData("\n"),
+	Directive(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`),
+	CharData("\n"),
+	StartElement{Name{"", "body"}, []Attr{{Name{"xmlns", "foo"}, "ns1"}, {Name{"", "xmlns"}, "ns2"}, {Name{"xmlns", "tag"}, "ns3"}}},
+	CharData("\n  "),
+	StartElement{Name{"", "hello"}, []Attr{{Name{"", "lang"}, "en"}}},
+	CharData("World <>'\" 白鵬翔"),
+	EndElement{Name{"", "hello"}},
+	CharData("\n  "),
+	StartElement{Name{"", "query"}, []Attr{}},
+	CharData("What is it?"),
+	EndElement{Name{"", "query"}},
+	CharData("\n  "),
+	StartElement{Name{"", "goodbye"}, []Attr{}},
+	EndElement{Name{"", "goodbye"}},
+	CharData("\n  "),
+	StartElement{Name{"", "outer"}, []Attr{{Name{"foo", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}},
+	CharData("\n    "),
+	StartElement{Name{"", "inner"}, []Attr{}},
+	EndElement{Name{"", "inner"}},
+	CharData("\n  "),
+	EndElement{Name{"", "outer"}},
+	CharData("\n  "),
+	StartElement{Name{"tag", "name"}, []Attr{}},
+	CharData("\n    "),
+	CharData("Some text here."),
+	CharData("\n  "),
+	EndElement{Name{"tag", "name"}},
+	CharData("\n"),
+	EndElement{Name{"", "body"}},
+	Comment(" missing final newline "),
+}
+
+var cookedTokens = []Token{
+	CharData("\n"),
+	ProcInst{"xml", []byte(`version="1.0" encoding="UTF-8"`)},
+	CharData("\n"),
+	Directive(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`),
+	CharData("\n"),
+	StartElement{Name{"ns2", "body"}, []Attr{{Name{"xmlns", "foo"}, "ns1"}, {Name{"", "xmlns"}, "ns2"}, {Name{"xmlns", "tag"}, "ns3"}}},
+	CharData("\n  "),
+	StartElement{Name{"ns2", "hello"}, []Attr{{Name{"", "lang"}, "en"}}},
+	CharData("World <>'\" 白鵬翔"),
+	EndElement{Name{"ns2", "hello"}},
+	CharData("\n  "),
+	StartElement{Name{"ns2", "query"}, []Attr{}},
+	CharData("What is it?"),
+	EndElement{Name{"ns2", "query"}},
+	CharData("\n  "),
+	StartElement{Name{"ns2", "goodbye"}, []Attr{}},
+	EndElement{Name{"ns2", "goodbye"}},
+	CharData("\n  "),
+	StartElement{Name{"ns2", "outer"}, []Attr{{Name{"ns1", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}},
+	CharData("\n    "),
+	StartElement{Name{"ns2", "inner"}, []Attr{}},
+	EndElement{Name{"ns2", "inner"}},
+	CharData("\n  "),
+	EndElement{Name{"ns2", "outer"}},
+	CharData("\n  "),
+	StartElement{Name{"ns3", "name"}, []Attr{}},
+	CharData("\n    "),
+	CharData("Some text here."),
+	CharData("\n  "),
+	EndElement{Name{"ns3", "name"}},
+	CharData("\n"),
+	EndElement{Name{"ns2", "body"}},
+	Comment(" missing final newline "),
+}
+
+const testInputAltEncoding = `
+<?xml version="1.0" encoding="x-testing-uppercase"?>
+<TAG>VALUE</TAG>`
+
+var rawTokensAltEncoding = []Token{
+	CharData("\n"),
+	ProcInst{"xml", []byte(`version="1.0" encoding="x-testing-uppercase"`)},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("value"),
+	EndElement{Name{"", "tag"}},
+}
+
+var xmlInput = []string{
+	// unexpected EOF cases
+	"<",
+	"<t",
+	"<t ",
+	"<t/",
+	"<!",
+	"<!-",
+	"<!--",
+	"<!--c-",
+	"<!--c--",
+	"<!d",
+	"<t></",
+	"<t></t",
+	"<?",
+	"<?p",
+	"<t a",
+	"<t a=",
+	"<t a='",
+	"<t a=''",
+	"<t/><![",
+	"<t/><![C",
+	"<t/><![CDATA[d",
+	"<t/><![CDATA[d]",
+	"<t/><![CDATA[d]]",
+
+	// other Syntax errors
+	"<>",
+	"<t/a",
+	"<0 />",
+	"<?0 >",
+	//	"<!0 >",	// let the Token() caller handle
+	"</0>",
+	"<t 0=''>",
+	"<t a='&'>",
+	"<t a='<'>",
+	"<t>&nbspc;</t>",
+	"<t a>",
+	"<t a=>",
+	"<t a=v>",
+	//	"<![CDATA[d]]>",	// let the Token() caller handle
+	"<t></e>",
+	"<t></>",
+	"<t></t!",
+	"<t>cdata]]></t>",
+}
+
+func TestRawToken(t *testing.T) {
+	d := NewDecoder(strings.NewReader(testInput))
+	d.Entity = testEntity
+	testRawToken(t, d, rawTokens)
+}
+
+const nonStrictInput = `
+<tag>non&entity</tag>
+<tag>&unknown;entity</tag>
+<tag>&#123</tag>
+<tag>&#zzz;</tag>
+<tag>&なまえ3;</tag>
+<tag>&lt-gt;</tag>
+<tag>&;</tag>
+<tag>&0a;</tag>
+`
+
+var nonStringEntity = map[string]string{"": "oops!", "0a": "oops!"}
+
+var nonStrictTokens = []Token{
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("non&entity"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&unknown;entity"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&#123"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&#zzz;"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&なまえ3;"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&lt-gt;"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&;"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&0a;"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+}
+
+func TestNonStrictRawToken(t *testing.T) {
+	d := NewDecoder(strings.NewReader(nonStrictInput))
+	d.Strict = false
+	testRawToken(t, d, nonStrictTokens)
+}
+
+type downCaser struct {
+	t *testing.T
+	r io.ByteReader
+}
+
+func (d *downCaser) ReadByte() (c byte, err error) {
+	c, err = d.r.ReadByte()
+	if c >= 'A' && c <= 'Z' {
+		c += 'a' - 'A'
+	}
+	return
+}
+
+func (d *downCaser) Read(p []byte) (int, error) {
+	d.t.Fatalf("unexpected Read call on downCaser reader")
+	panic("unreachable")
+}
+
+func TestRawTokenAltEncoding(t *testing.T) {
+	d := NewDecoder(strings.NewReader(testInputAltEncoding))
+	d.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
+		if charset != "x-testing-uppercase" {
+			t.Fatalf("unexpected charset %q", charset)
+		}
+		return &downCaser{t, input.(io.ByteReader)}, nil
+	}
+	testRawToken(t, d, rawTokensAltEncoding)
+}
+
+func TestRawTokenAltEncodingNoConverter(t *testing.T) {
+	d := NewDecoder(strings.NewReader(testInputAltEncoding))
+	token, err := d.RawToken()
+	if token == nil {
+		t.Fatalf("expected a token on first RawToken call")
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+	token, err = d.RawToken()
+	if token != nil {
+		t.Errorf("expected a nil token; got %#v", token)
+	}
+	if err == nil {
+		t.Fatalf("expected an error on second RawToken call")
+	}
+	const encoding = "x-testing-uppercase"
+	if !strings.Contains(err.Error(), encoding) {
+		t.Errorf("expected error to contain %q; got error: %v",
+			encoding, err)
+	}
+}
+
+func testRawToken(t *testing.T, d *Decoder, rawTokens []Token) {
+	for i, want := range rawTokens {
+		have, err := d.RawToken()
+		if err != nil {
+			t.Fatalf("token %d: unexpected error: %s", i, err)
+		}
+		if !reflect.DeepEqual(have, want) {
+			var shave, swant string
+			if _, ok := have.(CharData); ok {
+				shave = fmt.Sprintf("CharData(%q)", have)
+			} else {
+				shave = fmt.Sprintf("%#v", have)
+			}
+			if _, ok := want.(CharData); ok {
+				swant = fmt.Sprintf("CharData(%q)", want)
+			} else {
+				swant = fmt.Sprintf("%#v", want)
+			}
+			t.Errorf("token %d = %s, want %s", i, shave, swant)
+		}
+	}
+}
+
+// Ensure that directives (specifically !DOCTYPE) include the complete
+// text of any nested directives, noting that < and > do not change
+// nesting depth if they are in single or double quotes.
+
+var nestedDirectivesInput = `
+<!DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]>
+<!DOCTYPE [<!ENTITY xlt ">">]>
+<!DOCTYPE [<!ENTITY xlt "<">]>
+<!DOCTYPE [<!ENTITY xlt '>'>]>
+<!DOCTYPE [<!ENTITY xlt '<'>]>
+<!DOCTYPE [<!ENTITY xlt '">'>]>
+<!DOCTYPE [<!ENTITY xlt "'<">]>
+`
+
+var nestedDirectivesTokens = []Token{
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt ">">]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt "<">]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt '>'>]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt '<'>]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt '">'>]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt "'<">]`),
+	CharData("\n"),
+}
+
+func TestNestedDirectives(t *testing.T) {
+	d := NewDecoder(strings.NewReader(nestedDirectivesInput))
+
+	for i, want := range nestedDirectivesTokens {
+		have, err := d.Token()
+		if err != nil {
+			t.Fatalf("token %d: unexpected error: %s", i, err)
+		}
+		if !reflect.DeepEqual(have, want) {
+			t.Errorf("token %d = %#v want %#v", i, have, want)
+		}
+	}
+}
+
+func TestToken(t *testing.T) {
+	d := NewDecoder(strings.NewReader(testInput))
+	d.Entity = testEntity
+
+	for i, want := range cookedTokens {
+		have, err := d.Token()
+		if err != nil {
+			t.Fatalf("token %d: unexpected error: %s", i, err)
+		}
+		if !reflect.DeepEqual(have, want) {
+			t.Errorf("token %d = %#v want %#v", i, have, want)
+		}
+	}
+}
+
+func TestSyntax(t *testing.T) {
+	for i := range xmlInput {
+		d := NewDecoder(strings.NewReader(xmlInput[i]))
+		var err error
+		for _, err = d.Token(); err == nil; _, err = d.Token() {
+		}
+		if _, ok := err.(*SyntaxError); !ok {
+			t.Fatalf(`xmlInput "%s": expected SyntaxError not received`, xmlInput[i])
+		}
+	}
+}
+
+type allScalars struct {
+	True1     bool
+	True2     bool
+	False1    bool
+	False2    bool
+	Int       int
+	Int8      int8
+	Int16     int16
+	Int32     int32
+	Int64     int64
+	Uint      int
+	Uint8     uint8
+	Uint16    uint16
+	Uint32    uint32
+	Uint64    uint64
+	Uintptr   uintptr
+	Float32   float32
+	Float64   float64
+	String    string
+	PtrString *string
+}
+
+var all = allScalars{
+	True1:     true,
+	True2:     true,
+	False1:    false,
+	False2:    false,
+	Int:       1,
+	Int8:      -2,
+	Int16:     3,
+	Int32:     -4,
+	Int64:     5,
+	Uint:      6,
+	Uint8:     7,
+	Uint16:    8,
+	Uint32:    9,
+	Uint64:    10,
+	Uintptr:   11,
+	Float32:   13.0,
+	Float64:   14.0,
+	String:    "15",
+	PtrString: &sixteen,
+}
+
+var sixteen = "16"
+
+const testScalarsInput = `<allscalars>
+	<True1>true</True1>
+	<True2>1</True2>
+	<False1>false</False1>
+	<False2>0</False2>
+	<Int>1</Int>
+	<Int8>-2</Int8>
+	<Int16>3</Int16>
+	<Int32>-4</Int32>
+	<Int64>5</Int64>
+	<Uint>6</Uint>
+	<Uint8>7</Uint8>
+	<Uint16>8</Uint16>
+	<Uint32>9</Uint32>
+	<Uint64>10</Uint64>
+	<Uintptr>11</Uintptr>
+	<Float>12.0</Float>
+	<Float32>13.0</Float32>
+	<Float64>14.0</Float64>
+	<String>15</String>
+	<PtrString>16</PtrString>
+</allscalars>`
+
+func TestAllScalars(t *testing.T) {
+	var a allScalars
+	err := Unmarshal([]byte(testScalarsInput), &a)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !reflect.DeepEqual(a, all) {
+		t.Errorf("have %+v want %+v", a, all)
+	}
+}
+
+type item struct {
+	Field_a string
+}
+
+func TestIssue569(t *testing.T) {
+	data := `<item><Field_a>abcd</Field_a></item>`
+	var i item
+	err := Unmarshal([]byte(data), &i)
+
+	if err != nil || i.Field_a != "abcd" {
+		t.Fatal("Expecting abcd")
+	}
+}
+
+func TestUnquotedAttrs(t *testing.T) {
+	data := "<tag attr=azAZ09:-_\t>"
+	d := NewDecoder(strings.NewReader(data))
+	d.Strict = false
+	token, err := d.Token()
+	if _, ok := err.(*SyntaxError); ok {
+		t.Errorf("Unexpected error: %v", err)
+	}
+	if token.(StartElement).Name.Local != "tag" {
+		t.Errorf("Unexpected tag name: %v", token.(StartElement).Name.Local)
+	}
+	attr := token.(StartElement).Attr[0]
+	if attr.Value != "azAZ09:-_" {
+		t.Errorf("Unexpected attribute value: %v", attr.Value)
+	}
+	if attr.Name.Local != "attr" {
+		t.Errorf("Unexpected attribute name: %v", attr.Name.Local)
+	}
+}
+
+func TestValuelessAttrs(t *testing.T) {
+	tests := [][3]string{
+		{"<p nowrap>", "p", "nowrap"},
+		{"<p nowrap >", "p", "nowrap"},
+		{"<input checked/>", "input", "checked"},
+		{"<input checked />", "input", "checked"},
+	}
+	for _, test := range tests {
+		d := NewDecoder(strings.NewReader(test[0]))
+		d.Strict = false
+		token, err := d.Token()
+		if _, ok := err.(*SyntaxError); ok {
+			t.Errorf("Unexpected error: %v", err)
+		}
+		if token.(StartElement).Name.Local != test[1] {
+			t.Errorf("Unexpected tag name: %v", token.(StartElement).Name.Local)
+		}
+		attr := token.(StartElement).Attr[0]
+		if attr.Value != test[2] {
+			t.Errorf("Unexpected attribute value: %v", attr.Value)
+		}
+		if attr.Name.Local != test[2] {
+			t.Errorf("Unexpected attribute name: %v", attr.Name.Local)
+		}
+	}
+}
+
+func TestCopyTokenCharData(t *testing.T) {
+	data := []byte("same data")
+	var tok1 Token = CharData(data)
+	tok2 := CopyToken(tok1)
+	if !reflect.DeepEqual(tok1, tok2) {
+		t.Error("CopyToken(CharData) != CharData")
+	}
+	data[1] = 'o'
+	if reflect.DeepEqual(tok1, tok2) {
+		t.Error("CopyToken(CharData) uses same buffer.")
+	}
+}
+
+func TestCopyTokenStartElement(t *testing.T) {
+	elt := StartElement{Name{"", "hello"}, []Attr{{Name{"", "lang"}, "en"}}}
+	var tok1 Token = elt
+	tok2 := CopyToken(tok1)
+	if tok1.(StartElement).Attr[0].Value != "en" {
+		t.Error("CopyToken overwrote Attr[0]")
+	}
+	if !reflect.DeepEqual(tok1, tok2) {
+		t.Error("CopyToken(StartElement) != StartElement")
+	}
+	tok1.(StartElement).Attr[0] = Attr{Name{"", "lang"}, "de"}
+	if reflect.DeepEqual(tok1, tok2) {
+		t.Error("CopyToken(CharData) uses same buffer.")
+	}
+}
+
+func TestSyntaxErrorLineNum(t *testing.T) {
+	testInput := "<P>Foo<P>\n\n<P>Bar</>\n"
+	d := NewDecoder(strings.NewReader(testInput))
+	var err error
+	for _, err = d.Token(); err == nil; _, err = d.Token() {
+	}
+	synerr, ok := err.(*SyntaxError)
+	if !ok {
+		t.Error("Expected SyntaxError.")
+	}
+	if synerr.Line != 3 {
+		t.Error("SyntaxError didn't have correct line number.")
+	}
+}
+
+func TestTrailingRawToken(t *testing.T) {
+	input := `<FOO></FOO>  `
+	d := NewDecoder(strings.NewReader(input))
+	var err error
+	for _, err = d.RawToken(); err == nil; _, err = d.RawToken() {
+	}
+	if err != io.EOF {
+		t.Fatalf("d.RawToken() = _, %v, want _, io.EOF", err)
+	}
+}
+
+func TestTrailingToken(t *testing.T) {
+	input := `<FOO></FOO>  `
+	d := NewDecoder(strings.NewReader(input))
+	var err error
+	for _, err = d.Token(); err == nil; _, err = d.Token() {
+	}
+	if err != io.EOF {
+		t.Fatalf("d.Token() = _, %v, want _, io.EOF", err)
+	}
+}
+
+func TestEntityInsideCDATA(t *testing.T) {
+	input := `<test><![CDATA[ &val=foo ]]></test>`
+	d := NewDecoder(strings.NewReader(input))
+	var err error
+	for _, err = d.Token(); err == nil; _, err = d.Token() {
+	}
+	if err != io.EOF {
+		t.Fatalf("d.Token() = _, %v, want _, io.EOF", err)
+	}
+}
+
+var characterTests = []struct {
+	in  string
+	err string
+}{
+	{"\x12<doc/>", "illegal character code U+0012"},
+	{"<?xml version=\"1.0\"?>\x0b<doc/>", "illegal character code U+000B"},
+	{"\xef\xbf\xbe<doc/>", "illegal character code U+FFFE"},
+	{"<?xml version=\"1.0\"?><doc>\r\n<hiya/>\x07<toots/></doc>", "illegal character code U+0007"},
+	{"<?xml version=\"1.0\"?><doc \x12='value'>what's up</doc>", "expected attribute name in element"},
+	{"<doc>&abc\x01;</doc>", "invalid character entity &abc (no semicolon)"},
+	{"<doc>&\x01;</doc>", "invalid character entity & (no semicolon)"},
+	{"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity &\uFFFE;"},
+	{"<doc>&hello;</doc>", "invalid character entity &hello;"},
+}
+
+func TestDisallowedCharacters(t *testing.T) {
+
+	for i, tt := range characterTests {
+		d := NewDecoder(strings.NewReader(tt.in))
+		var err error
+
+		for err == nil {
+			_, err = d.Token()
+		}
+		synerr, ok := err.(*SyntaxError)
+		if !ok {
+			t.Fatalf("input %d d.Token() = _, %v, want _, *SyntaxError", i, err)
+		}
+		if synerr.Msg != tt.err {
+			t.Fatalf("input %d synerr.Msg wrong: want %q, got %q", i, tt.err, synerr.Msg)
+		}
+	}
+}
+
+type procInstEncodingTest struct {
+	expect, got string
+}
+
+var procInstTests = []struct {
+	input, expect string
+}{
+	{`version="1.0" encoding="utf-8"`, "utf-8"},
+	{`version="1.0" encoding='utf-8'`, "utf-8"},
+	{`version="1.0" encoding='utf-8' `, "utf-8"},
+	{`version="1.0" encoding=utf-8`, ""},
+	{`encoding="FOO" `, "FOO"},
+}
+
+func TestProcInstEncoding(t *testing.T) {
+	for _, test := range procInstTests {
+		got := procInstEncoding(test.input)
+		if got != test.expect {
+			t.Errorf("procInstEncoding(%q) = %q; want %q", test.input, got, test.expect)
+		}
+	}
+}
+
+// Ensure that directives with comments include the complete
+// text of any nested directives.
+
+var directivesWithCommentsInput = `
+<!DOCTYPE [<!-- a comment --><!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]>
+<!DOCTYPE [<!ENTITY go "Golang"><!-- a comment-->]>
+<!DOCTYPE <!-> <!> <!----> <!-->--> <!--->--> [<!ENTITY go "Golang"><!-- a comment-->]>
+`
+
+var directivesWithCommentsTokens = []Token{
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY go "Golang">]`),
+	CharData("\n"),
+	Directive(`DOCTYPE <!-> <!>    [<!ENTITY go "Golang">]`),
+	CharData("\n"),
+}
+
+func TestDirectivesWithComments(t *testing.T) {
+	d := NewDecoder(strings.NewReader(directivesWithCommentsInput))
+
+	for i, want := range directivesWithCommentsTokens {
+		have, err := d.Token()
+		if err != nil {
+			t.Fatalf("token %d: unexpected error: %s", i, err)
+		}
+		if !reflect.DeepEqual(have, want) {
+			t.Errorf("token %d = %#v want %#v", i, have, want)
+		}
+	}
+}
+
+// Writer whose Write method always returns an error.
+type errWriter struct{}
+
+func (errWriter) Write(p []byte) (n int, err error) { return 0, fmt.Errorf("unwritable") }
+
+func TestEscapeTextIOErrors(t *testing.T) {
+	expectErr := "unwritable"
+	err := EscapeText(errWriter{}, []byte{'A'})
+
+	if err == nil || err.Error() != expectErr {
+		t.Errorf("have %v, want %v", err, expectErr)
+	}
+}
+
+func TestEscapeTextInvalidChar(t *testing.T) {
+	input := []byte("A \x00 terminated string.")
+	expected := "A \uFFFD terminated string."
+
+	buff := new(bytes.Buffer)
+	if err := EscapeText(buff, input); err != nil {
+		t.Fatalf("have %v, want nil", err)
+	}
+	text := buff.String()
+
+	if text != expected {
+		t.Errorf("have %v, want %v", text, expected)
+	}
+}
+
+func TestIssue5880(t *testing.T) {
+	type T []byte
+	data, err := Marshal(T{192, 168, 0, 1})
+	if err != nil {
+		t.Errorf("Marshal error: %v", err)
+	}
+	if !utf8.Valid(data) {
+		t.Errorf("Marshal generated invalid UTF-8: %x", data)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/errors/errors.go b/third_party/gofrontend/libgo/go/errors/errors.go
new file mode 100644
index 0000000..3085a79
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/errors/errors.go
@@ -0,0 +1,20 @@
+// 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.
+
+// Package errors implements functions to manipulate errors.
+package errors
+
+// New returns an error that formats as the given text.
+func New(text string) error {
+	return &errorString{text}
+}
+
+// errorString is a trivial implementation of error.
+type errorString struct {
+	s string
+}
+
+func (e *errorString) Error() string {
+	return e.s
+}
diff --git a/third_party/gofrontend/libgo/go/errors/errors_test.go b/third_party/gofrontend/libgo/go/errors/errors_test.go
new file mode 100644
index 0000000..63c05d7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/errors/errors_test.go
@@ -0,0 +1,53 @@
+// 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.
+
+package errors_test
+
+import (
+	"errors"
+	"fmt"
+	"testing"
+)
+
+func TestNewEqual(t *testing.T) {
+	// Different allocations should not be equal.
+	if errors.New("abc") == errors.New("abc") {
+		t.Errorf(`New("abc") == New("abc")`)
+	}
+	if errors.New("abc") == errors.New("xyz") {
+		t.Errorf(`New("abc") == New("xyz")`)
+	}
+
+	// Same allocation should be equal to itself (not crash).
+	err := errors.New("jkl")
+	if err != err {
+		t.Errorf(`err != err`)
+	}
+}
+
+func TestErrorMethod(t *testing.T) {
+	err := errors.New("abc")
+	if err.Error() != "abc" {
+		t.Errorf(`New("abc").Error() = %q, want %q`, err.Error(), "abc")
+	}
+}
+
+func ExampleNew() {
+	err := errors.New("emit macho dwarf: elf header corrupted")
+	if err != nil {
+		fmt.Print(err)
+	}
+	// Output: emit macho dwarf: elf header corrupted
+}
+
+// The fmt package's Errorf function lets us use the package's formatting
+// features to create descriptive error messages.
+func ExampleNew_errorf() {
+	const name, id = "bimmler", 17
+	err := fmt.Errorf("user %q (id %d) not found", name, id)
+	if err != nil {
+		fmt.Print(err)
+	}
+	// Output: user "bimmler" (id 17) not found
+}
diff --git a/third_party/gofrontend/libgo/go/exp/README b/third_party/gofrontend/libgo/go/exp/README
new file mode 100644
index 0000000..e602e3a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/exp/README
@@ -0,0 +1,3 @@
+This directory tree contains experimental packages and
+unfinished code that is subject to even more change than the
+rest of the Go tree.
diff --git a/third_party/gofrontend/libgo/go/exp/proxy/direct.go b/third_party/gofrontend/libgo/go/exp/proxy/direct.go
new file mode 100644
index 0000000..4c5ad88
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/exp/proxy/direct.go
@@ -0,0 +1,18 @@
+// 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.
+
+package proxy
+
+import (
+	"net"
+)
+
+type direct struct{}
+
+// Direct is a direct proxy: one that makes network connections directly.
+var Direct = direct{}
+
+func (direct) Dial(network, addr string) (net.Conn, error) {
+	return net.Dial(network, addr)
+}
diff --git a/third_party/gofrontend/libgo/go/exp/proxy/per_host.go b/third_party/gofrontend/libgo/go/exp/proxy/per_host.go
new file mode 100644
index 0000000..0c627e9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/exp/proxy/per_host.go
@@ -0,0 +1,140 @@
+// 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.
+
+package proxy
+
+import (
+	"net"
+	"strings"
+)
+
+// A PerHost directs connections to a default Dailer unless the hostname
+// requested matches one of a number of exceptions.
+type PerHost struct {
+	def, bypass Dialer
+
+	bypassNetworks []*net.IPNet
+	bypassIPs      []net.IP
+	bypassZones    []string
+	bypassHosts    []string
+}
+
+// NewPerHost returns a PerHost Dialer that directs connections to either
+// defaultDialer or bypass, depending on whether the connection matches one of
+// the configured rules.
+func NewPerHost(defaultDialer, bypass Dialer) *PerHost {
+	return &PerHost{
+		def:    defaultDialer,
+		bypass: bypass,
+	}
+}
+
+// Dial connects to the address addr on the network net through either
+// defaultDialer or bypass.
+func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) {
+	host, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		return nil, err
+	}
+
+	return p.dialerForRequest(host).Dial(network, addr)
+}
+
+func (p *PerHost) dialerForRequest(host string) Dialer {
+	if ip := net.ParseIP(host); ip != nil {
+		for _, net := range p.bypassNetworks {
+			if net.Contains(ip) {
+				return p.bypass
+			}
+		}
+		for _, bypassIP := range p.bypassIPs {
+			if bypassIP.Equal(ip) {
+				return p.bypass
+			}
+		}
+		return p.def
+	}
+
+	for _, zone := range p.bypassZones {
+		if strings.HasSuffix(host, zone) {
+			return p.bypass
+		}
+		if host == zone[1:] {
+			// For a zone "example.com", we match "example.com"
+			// too.
+			return p.bypass
+		}
+	}
+	for _, bypassHost := range p.bypassHosts {
+		if bypassHost == host {
+			return p.bypass
+		}
+	}
+	return p.def
+}
+
+// AddFromString parses a string that contains comma-separated values
+// specifying hosts that should use the bypass proxy. Each value is either an
+// IP address, a CIDR range, a zone (*.example.com) or a hostname
+// (localhost). A best effort is made to parse the string and errors are
+// ignored.
+func (p *PerHost) AddFromString(s string) {
+	hosts := strings.Split(s, ",")
+	for _, host := range hosts {
+		host = strings.TrimSpace(host)
+		if len(host) == 0 {
+			continue
+		}
+		if strings.Contains(host, "/") {
+			// We assume that it's a CIDR address like 127.0.0.0/8
+			if _, net, err := net.ParseCIDR(host); err == nil {
+				p.AddNetwork(net)
+			}
+			continue
+		}
+		if ip := net.ParseIP(host); ip != nil {
+			p.AddIP(ip)
+			continue
+		}
+		if strings.HasPrefix(host, "*.") {
+			p.AddZone(host[1:])
+			continue
+		}
+		p.AddHost(host)
+	}
+}
+
+// AddIP specifies an IP address that will use the bypass proxy. Note that
+// this will only take effect if a literal IP address is dialed. A connection
+// to a named host will never match an IP.
+func (p *PerHost) AddIP(ip net.IP) {
+	p.bypassIPs = append(p.bypassIPs, ip)
+}
+
+// AddIP specifies an IP range that will use the bypass proxy. Note that this
+// will only take effect if a literal IP address is dialed. A connection to a
+// named host will never match.
+func (p *PerHost) AddNetwork(net *net.IPNet) {
+	p.bypassNetworks = append(p.bypassNetworks, net)
+}
+
+// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
+// "example.com" matches "example.com" and all of its subdomains.
+func (p *PerHost) AddZone(zone string) {
+	if strings.HasSuffix(zone, ".") {
+		zone = zone[:len(zone)-1]
+	}
+	if !strings.HasPrefix(zone, ".") {
+		zone = "." + zone
+	}
+	p.bypassZones = append(p.bypassZones, zone)
+}
+
+// AddHost specifies a hostname that will use the bypass proxy.
+func (p *PerHost) AddHost(host string) {
+	if strings.HasSuffix(host, ".") {
+		host = host[:len(host)-1]
+	}
+	p.bypassHosts = append(p.bypassHosts, host)
+}
diff --git a/third_party/gofrontend/libgo/go/exp/proxy/per_host_test.go b/third_party/gofrontend/libgo/go/exp/proxy/per_host_test.go
new file mode 100644
index 0000000..a7d8095
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/exp/proxy/per_host_test.go
@@ -0,0 +1,55 @@
+// 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.
+
+package proxy
+
+import (
+	"errors"
+	"net"
+	"reflect"
+	"testing"
+)
+
+type recordingProxy struct {
+	addrs []string
+}
+
+func (r *recordingProxy) Dial(network, addr string) (net.Conn, error) {
+	r.addrs = append(r.addrs, addr)
+	return nil, errors.New("recordingProxy")
+}
+
+func TestPerHost(t *testing.T) {
+	var def, bypass recordingProxy
+	perHost := NewPerHost(&def, &bypass)
+	perHost.AddFromString("localhost,*.zone,127.0.0.1,10.0.0.1/8,1000::/16")
+
+	expectedDef := []string{
+		"example.com:123",
+		"1.2.3.4:123",
+		"[1001::]:123",
+	}
+	expectedBypass := []string{
+		"localhost:123",
+		"zone:123",
+		"foo.zone:123",
+		"127.0.0.1:123",
+		"10.1.2.3:123",
+		"[1000::]:123",
+	}
+
+	for _, addr := range expectedDef {
+		perHost.Dial("tcp", addr)
+	}
+	for _, addr := range expectedBypass {
+		perHost.Dial("tcp", addr)
+	}
+
+	if !reflect.DeepEqual(expectedDef, def.addrs) {
+		t.Errorf("Hosts which went to the default proxy didn't match. Got %v, want %v", def.addrs, expectedDef)
+	}
+	if !reflect.DeepEqual(expectedBypass, bypass.addrs) {
+		t.Errorf("Hosts which went to the bypass proxy didn't match. Got %v, want %v", bypass.addrs, expectedBypass)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/exp/proxy/proxy.go b/third_party/gofrontend/libgo/go/exp/proxy/proxy.go
new file mode 100644
index 0000000..b6cfd45
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/exp/proxy/proxy.go
@@ -0,0 +1,94 @@
+// 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.
+
+// Package proxy provides support for a variety of protocols to proxy network
+// data.
+package proxy
+
+import (
+	"errors"
+	"net"
+	"net/url"
+	"os"
+)
+
+// A Dialer is a means to establish a connection.
+type Dialer interface {
+	// Dial connects to the given address via the proxy.
+	Dial(network, addr string) (c net.Conn, err error)
+}
+
+// Auth contains authentication parameters that specific Dialers may require.
+type Auth struct {
+	User, Password string
+}
+
+// DefaultDialer returns the dialer specified by the proxy related variables in
+// the environment.
+func FromEnvironment() Dialer {
+	allProxy := os.Getenv("all_proxy")
+	if len(allProxy) == 0 {
+		return Direct
+	}
+
+	proxyURL, err := url.Parse(allProxy)
+	if err != nil {
+		return Direct
+	}
+	proxy, err := FromURL(proxyURL, Direct)
+	if err != nil {
+		return Direct
+	}
+
+	noProxy := os.Getenv("no_proxy")
+	if len(noProxy) == 0 {
+		return proxy
+	}
+
+	perHost := NewPerHost(proxy, Direct)
+	perHost.AddFromString(noProxy)
+	return perHost
+}
+
+// proxySchemes is a map from URL schemes to a function that creates a Dialer
+// from a URL with such a scheme.
+var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error)
+
+// RegisterDialerType takes a URL scheme and a function to generate Dialers from
+// a URL with that scheme and a forwarding Dialer. Registered schemes are used
+// by FromURL.
+func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) {
+	if proxySchemes == nil {
+		proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error))
+	}
+	proxySchemes[scheme] = f
+}
+
+// FromURL returns a Dialer given a URL specification and an underlying
+// Dialer for it to make network requests.
+func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
+	var auth *Auth
+	if u.User != nil {
+		auth = new(Auth)
+		auth.User = u.User.Username()
+		if p, ok := u.User.Password(); ok {
+			auth.Password = p
+		}
+	}
+
+	switch u.Scheme {
+	case "socks5":
+		return SOCKS5("tcp", u.Host, auth, forward)
+	}
+
+	// If the scheme doesn't match any of the built-in schemes, see if it
+	// was registered by another package.
+	if proxySchemes != nil {
+		if f, ok := proxySchemes[u.Scheme]; ok {
+			return f(u, forward)
+		}
+	}
+
+	return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
+}
diff --git a/third_party/gofrontend/libgo/go/exp/proxy/proxy_test.go b/third_party/gofrontend/libgo/go/exp/proxy/proxy_test.go
new file mode 100644
index 0000000..4078bc7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/exp/proxy/proxy_test.go
@@ -0,0 +1,50 @@
+// 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.
+
+package proxy
+
+import (
+	"net"
+	"net/url"
+	"testing"
+)
+
+type testDialer struct {
+	network, addr string
+}
+
+func (t *testDialer) Dial(network, addr string) (net.Conn, error) {
+	t.network = network
+	t.addr = addr
+	return nil, t
+}
+
+func (t *testDialer) Error() string {
+	return "testDialer " + t.network + " " + t.addr
+}
+
+func TestFromURL(t *testing.T) {
+	u, err := url.Parse("socks5://user:password@1.2.3.4:5678")
+	if err != nil {
+		t.Fatalf("failed to parse URL: %s", err)
+	}
+
+	tp := &testDialer{}
+	proxy, err := FromURL(u, tp)
+	if err != nil {
+		t.Fatalf("FromURL failed: %s", err)
+	}
+
+	conn, err := proxy.Dial("tcp", "example.com:80")
+	if conn != nil {
+		t.Error("Dial unexpected didn't return an error")
+	}
+	if tp, ok := err.(*testDialer); ok {
+		if tp.network != "tcp" || tp.addr != "1.2.3.4:5678" {
+			t.Errorf("Dialer connected to wrong host. Wanted 1.2.3.4:5678, got: %v", tp)
+		}
+	} else {
+		t.Errorf("Unexpected error from Dial: %s", err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/exp/proxy/socks5.go b/third_party/gofrontend/libgo/go/exp/proxy/socks5.go
new file mode 100644
index 0000000..62fa5c9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/exp/proxy/socks5.go
@@ -0,0 +1,207 @@
+// 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.
+
+package proxy
+
+import (
+	"errors"
+	"io"
+	"net"
+	"strconv"
+)
+
+// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
+// with an optional username and password. See RFC 1928.
+func SOCKS5(network, addr string, auth *Auth, forward Dialer) (Dialer, error) {
+	s := &socks5{
+		network: network,
+		addr:    addr,
+		forward: forward,
+	}
+	if auth != nil {
+		s.user = auth.User
+		s.password = auth.Password
+	}
+
+	return s, nil
+}
+
+type socks5 struct {
+	user, password string
+	network, addr  string
+	forward        Dialer
+}
+
+const socks5Version = 5
+
+const (
+	socks5AuthNone     = 0
+	socks5AuthPassword = 2
+)
+
+const socks5Connect = 1
+
+const (
+	socks5IP4    = 1
+	socks5Domain = 3
+	socks5IP6    = 4
+)
+
+var socks5Errors = []string{
+	"",
+	"general failure",
+	"connection forbidden",
+	"network unreachable",
+	"host unreachable",
+	"connection refused",
+	"TTL expired",
+	"command not supported",
+	"address type not supported",
+}
+
+// Dial connects to the address addr on the network net via the SOCKS5 proxy.
+func (s *socks5) Dial(network, addr string) (net.Conn, error) {
+	switch network {
+	case "tcp", "tcp6", "tcp4":
+		break
+	default:
+		return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
+	}
+
+	conn, err := s.forward.Dial(s.network, s.addr)
+	if err != nil {
+		return nil, err
+	}
+	closeConn := &conn
+	defer func() {
+		if closeConn != nil {
+			(*closeConn).Close()
+		}
+	}()
+
+	host, portStr, err := net.SplitHostPort(addr)
+	if err != nil {
+		return nil, err
+	}
+
+	port, err := strconv.Atoi(portStr)
+	if err != nil {
+		return nil, errors.New("proxy: failed to parse port number: " + portStr)
+	}
+	if port < 1 || port > 0xffff {
+		return nil, errors.New("proxy: port number out of range: " + portStr)
+	}
+
+	// the size here is just an estimate
+	buf := make([]byte, 0, 6+len(host))
+
+	buf = append(buf, socks5Version)
+	if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
+		buf = append(buf, 2 /* num auth methods */, socks5AuthNone, socks5AuthPassword)
+	} else {
+		buf = append(buf, 1 /* num auth methods */, socks5AuthNone)
+	}
+
+	if _, err = conn.Write(buf); err != nil {
+		return nil, errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	if _, err = io.ReadFull(conn, buf[:2]); err != nil {
+		return nil, errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+	if buf[0] != 5 {
+		return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
+	}
+	if buf[1] == 0xff {
+		return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
+	}
+
+	if buf[1] == socks5AuthPassword {
+		buf = buf[:0]
+		buf = append(buf, socks5Version)
+		buf = append(buf, uint8(len(s.user)))
+		buf = append(buf, s.user...)
+		buf = append(buf, uint8(len(s.password)))
+		buf = append(buf, s.password...)
+
+		if _, err = conn.Write(buf); err != nil {
+			return nil, errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+		}
+
+		if _, err = io.ReadFull(conn, buf[:2]); err != nil {
+			return nil, errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+		}
+
+		if buf[1] != 0 {
+			return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
+		}
+	}
+
+	buf = buf[:0]
+	buf = append(buf, socks5Version, socks5Connect, 0 /* reserved */)
+
+	if ip := net.ParseIP(host); ip != nil {
+		if len(ip) == 4 {
+			buf = append(buf, socks5IP4)
+		} else {
+			buf = append(buf, socks5IP6)
+		}
+		buf = append(buf, []byte(ip)...)
+	} else {
+		buf = append(buf, socks5Domain)
+		buf = append(buf, byte(len(host)))
+		buf = append(buf, host...)
+	}
+	buf = append(buf, byte(port>>8), byte(port))
+
+	if _, err = conn.Write(buf); err != nil {
+		return nil, errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	if _, err = io.ReadFull(conn, buf[:4]); err != nil {
+		return nil, errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	failure := "unknown error"
+	if int(buf[1]) < len(socks5Errors) {
+		failure = socks5Errors[buf[1]]
+	}
+
+	if len(failure) > 0 {
+		return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
+	}
+
+	bytesToDiscard := 0
+	switch buf[3] {
+	case socks5IP4:
+		bytesToDiscard = 4
+	case socks5IP6:
+		bytesToDiscard = 16
+	case socks5Domain:
+		_, err := io.ReadFull(conn, buf[:1])
+		if err != nil {
+			return nil, errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+		}
+		bytesToDiscard = int(buf[0])
+	default:
+		return nil, errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
+	}
+
+	if cap(buf) < bytesToDiscard {
+		buf = make([]byte, bytesToDiscard)
+	} else {
+		buf = buf[:bytesToDiscard]
+	}
+	if _, err = io.ReadFull(conn, buf); err != nil {
+		return nil, errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	// Also need to discard the port number
+	if _, err = io.ReadFull(conn, buf[:2]); err != nil {
+		return nil, errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	closeConn = nil
+	return conn, nil
+}
diff --git a/third_party/gofrontend/libgo/go/exp/terminal/terminal.go b/third_party/gofrontend/libgo/go/exp/terminal/terminal.go
new file mode 100644
index 0000000..c1ed0c0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/exp/terminal/terminal.go
@@ -0,0 +1,520 @@
+// 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.
+
+package terminal
+
+import (
+	"io"
+	"sync"
+)
+
+// EscapeCodes contains escape sequences that can be written to the terminal in
+// order to achieve different styles of text.
+type EscapeCodes struct {
+	// Foreground colors
+	Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte
+
+	// Reset all attributes
+	Reset []byte
+}
+
+var vt100EscapeCodes = EscapeCodes{
+	Black:   []byte{keyEscape, '[', '3', '0', 'm'},
+	Red:     []byte{keyEscape, '[', '3', '1', 'm'},
+	Green:   []byte{keyEscape, '[', '3', '2', 'm'},
+	Yellow:  []byte{keyEscape, '[', '3', '3', 'm'},
+	Blue:    []byte{keyEscape, '[', '3', '4', 'm'},
+	Magenta: []byte{keyEscape, '[', '3', '5', 'm'},
+	Cyan:    []byte{keyEscape, '[', '3', '6', 'm'},
+	White:   []byte{keyEscape, '[', '3', '7', 'm'},
+
+	Reset: []byte{keyEscape, '[', '0', 'm'},
+}
+
+// Terminal contains the state for running a VT100 terminal that is capable of
+// reading lines of input.
+type Terminal struct {
+	// AutoCompleteCallback, if non-null, is called for each keypress
+	// with the full input line and the current position of the cursor.
+	// If it returns a nil newLine, the key press is processed normally.
+	// Otherwise it returns a replacement line and the new cursor position.
+	AutoCompleteCallback func(line []byte, pos, key int) (newLine []byte, newPos int)
+
+	// Escape contains a pointer to the escape codes for this terminal.
+	// It's always a valid pointer, although the escape codes themselves
+	// may be empty if the terminal doesn't support them.
+	Escape *EscapeCodes
+
+	// lock protects the terminal and the state in this object from
+	// concurrent processing of a key press and a Write() call.
+	lock sync.Mutex
+
+	c      io.ReadWriter
+	prompt string
+
+	// line is the current line being entered.
+	line []byte
+	// pos is the logical position of the cursor in line
+	pos int
+	// echo is true if local echo is enabled
+	echo bool
+
+	// cursorX contains the current X value of the cursor where the left
+	// edge is 0. cursorY contains the row number where the first row of
+	// the current line is 0.
+	cursorX, cursorY int
+	// maxLine is the greatest value of cursorY so far.
+	maxLine int
+
+	termWidth, termHeight int
+
+	// outBuf contains the terminal data to be sent.
+	outBuf []byte
+	// remainder contains the remainder of any partial key sequences after
+	// a read. It aliases into inBuf.
+	remainder []byte
+	inBuf     [256]byte
+}
+
+// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
+// a local terminal, that terminal must first have been put into raw mode.
+// prompt is a string that is written at the start of each input line (i.e.
+// "> ").
+func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
+	return &Terminal{
+		Escape:     &vt100EscapeCodes,
+		c:          c,
+		prompt:     prompt,
+		termWidth:  80,
+		termHeight: 24,
+		echo:       true,
+	}
+}
+
+const (
+	keyCtrlD     = 4
+	keyEnter     = '\r'
+	keyEscape    = 27
+	keyBackspace = 127
+	keyUnknown   = 256 + iota
+	keyUp
+	keyDown
+	keyLeft
+	keyRight
+	keyAltLeft
+	keyAltRight
+)
+
+// bytesToKey tries to parse a key sequence from b. If successful, it returns
+// the key and the remainder of the input. Otherwise it returns -1.
+func bytesToKey(b []byte) (int, []byte) {
+	if len(b) == 0 {
+		return -1, nil
+	}
+
+	if b[0] != keyEscape {
+		return int(b[0]), b[1:]
+	}
+
+	if len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
+		switch b[2] {
+		case 'A':
+			return keyUp, b[3:]
+		case 'B':
+			return keyDown, b[3:]
+		case 'C':
+			return keyRight, b[3:]
+		case 'D':
+			return keyLeft, b[3:]
+		}
+	}
+
+	if len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
+		switch b[5] {
+		case 'C':
+			return keyAltRight, b[6:]
+		case 'D':
+			return keyAltLeft, b[6:]
+		}
+	}
+
+	// If we get here then we have a key that we don't recognise, or a
+	// partial sequence. It's not clear how one should find the end of a
+	// sequence without knowing them all, but it seems that [a-zA-Z] only
+	// appears at the end of a sequence.
+	for i, c := range b[0:] {
+		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' {
+			return keyUnknown, b[i+1:]
+		}
+	}
+
+	return -1, b
+}
+
+// queue appends data to the end of t.outBuf
+func (t *Terminal) queue(data []byte) {
+	t.outBuf = append(t.outBuf, data...)
+}
+
+var eraseUnderCursor = []byte{' ', keyEscape, '[', 'D'}
+var space = []byte{' '}
+
+func isPrintable(key int) bool {
+	return key >= 32 && key < 127
+}
+
+// moveCursorToPos appends data to t.outBuf which will move the cursor to the
+// given, logical position in the text.
+func (t *Terminal) moveCursorToPos(pos int) {
+	if !t.echo {
+		return
+	}
+
+	x := len(t.prompt) + pos
+	y := x / t.termWidth
+	x = x % t.termWidth
+
+	up := 0
+	if y < t.cursorY {
+		up = t.cursorY - y
+	}
+
+	down := 0
+	if y > t.cursorY {
+		down = y - t.cursorY
+	}
+
+	left := 0
+	if x < t.cursorX {
+		left = t.cursorX - x
+	}
+
+	right := 0
+	if x > t.cursorX {
+		right = x - t.cursorX
+	}
+
+	t.cursorX = x
+	t.cursorY = y
+	t.move(up, down, left, right)
+}
+
+func (t *Terminal) move(up, down, left, right int) {
+	movement := make([]byte, 3*(up+down+left+right))
+	m := movement
+	for i := 0; i < up; i++ {
+		m[0] = keyEscape
+		m[1] = '['
+		m[2] = 'A'
+		m = m[3:]
+	}
+	for i := 0; i < down; i++ {
+		m[0] = keyEscape
+		m[1] = '['
+		m[2] = 'B'
+		m = m[3:]
+	}
+	for i := 0; i < left; i++ {
+		m[0] = keyEscape
+		m[1] = '['
+		m[2] = 'D'
+		m = m[3:]
+	}
+	for i := 0; i < right; i++ {
+		m[0] = keyEscape
+		m[1] = '['
+		m[2] = 'C'
+		m = m[3:]
+	}
+
+	t.queue(movement)
+}
+
+func (t *Terminal) clearLineToRight() {
+	op := []byte{keyEscape, '[', 'K'}
+	t.queue(op)
+}
+
+const maxLineLength = 4096
+
+// handleKey processes the given key and, optionally, returns a line of text
+// that the user has entered.
+func (t *Terminal) handleKey(key int) (line string, ok bool) {
+	switch key {
+	case keyBackspace:
+		if t.pos == 0 {
+			return
+		}
+		t.pos--
+		t.moveCursorToPos(t.pos)
+
+		copy(t.line[t.pos:], t.line[1+t.pos:])
+		t.line = t.line[:len(t.line)-1]
+		if t.echo {
+			t.writeLine(t.line[t.pos:])
+		}
+		t.queue(eraseUnderCursor)
+		t.moveCursorToPos(t.pos)
+	case keyAltLeft:
+		// move left by a word.
+		if t.pos == 0 {
+			return
+		}
+		t.pos--
+		for t.pos > 0 {
+			if t.line[t.pos] != ' ' {
+				break
+			}
+			t.pos--
+		}
+		for t.pos > 0 {
+			if t.line[t.pos] == ' ' {
+				t.pos++
+				break
+			}
+			t.pos--
+		}
+		t.moveCursorToPos(t.pos)
+	case keyAltRight:
+		// move right by a word.
+		for t.pos < len(t.line) {
+			if t.line[t.pos] == ' ' {
+				break
+			}
+			t.pos++
+		}
+		for t.pos < len(t.line) {
+			if t.line[t.pos] != ' ' {
+				break
+			}
+			t.pos++
+		}
+		t.moveCursorToPos(t.pos)
+	case keyLeft:
+		if t.pos == 0 {
+			return
+		}
+		t.pos--
+		t.moveCursorToPos(t.pos)
+	case keyRight:
+		if t.pos == len(t.line) {
+			return
+		}
+		t.pos++
+		t.moveCursorToPos(t.pos)
+	case keyEnter:
+		t.moveCursorToPos(len(t.line))
+		t.queue([]byte("\r\n"))
+		line = string(t.line)
+		ok = true
+		t.line = t.line[:0]
+		t.pos = 0
+		t.cursorX = 0
+		t.cursorY = 0
+		t.maxLine = 0
+	default:
+		if t.AutoCompleteCallback != nil {
+			t.lock.Unlock()
+			newLine, newPos := t.AutoCompleteCallback(t.line, t.pos, key)
+			t.lock.Lock()
+
+			if newLine != nil {
+				if t.echo {
+					t.moveCursorToPos(0)
+					t.writeLine(newLine)
+					for i := len(newLine); i < len(t.line); i++ {
+						t.writeLine(space)
+					}
+					t.moveCursorToPos(newPos)
+				}
+				t.line = newLine
+				t.pos = newPos
+				return
+			}
+		}
+		if !isPrintable(key) {
+			return
+		}
+		if len(t.line) == maxLineLength {
+			return
+		}
+		if len(t.line) == cap(t.line) {
+			newLine := make([]byte, len(t.line), 2*(1+len(t.line)))
+			copy(newLine, t.line)
+			t.line = newLine
+		}
+		t.line = t.line[:len(t.line)+1]
+		copy(t.line[t.pos+1:], t.line[t.pos:])
+		t.line[t.pos] = byte(key)
+		if t.echo {
+			t.writeLine(t.line[t.pos:])
+		}
+		t.pos++
+		t.moveCursorToPos(t.pos)
+	}
+	return
+}
+
+func (t *Terminal) writeLine(line []byte) {
+	for len(line) != 0 {
+		remainingOnLine := t.termWidth - t.cursorX
+		todo := len(line)
+		if todo > remainingOnLine {
+			todo = remainingOnLine
+		}
+		t.queue(line[:todo])
+		t.cursorX += todo
+		line = line[todo:]
+
+		if t.cursorX == t.termWidth {
+			t.cursorX = 0
+			t.cursorY++
+			if t.cursorY > t.maxLine {
+				t.maxLine = t.cursorY
+			}
+		}
+	}
+}
+
+func (t *Terminal) Write(buf []byte) (n int, err error) {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	if t.cursorX == 0 && t.cursorY == 0 {
+		// This is the easy case: there's nothing on the screen that we
+		// have to move out of the way.
+		return t.c.Write(buf)
+	}
+
+	// We have a prompt and possibly user input on the screen. We
+	// have to clear it first.
+	t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */)
+	t.cursorX = 0
+	t.clearLineToRight()
+
+	for t.cursorY > 0 {
+		t.move(1 /* up */, 0, 0, 0)
+		t.cursorY--
+		t.clearLineToRight()
+	}
+
+	if _, err = t.c.Write(t.outBuf); err != nil {
+		return
+	}
+	t.outBuf = t.outBuf[:0]
+
+	if n, err = t.c.Write(buf); err != nil {
+		return
+	}
+
+	t.queue([]byte(t.prompt))
+	chars := len(t.prompt)
+	if t.echo {
+		t.queue(t.line)
+		chars += len(t.line)
+	}
+	t.cursorX = chars % t.termWidth
+	t.cursorY = chars / t.termWidth
+	t.moveCursorToPos(t.pos)
+
+	if _, err = t.c.Write(t.outBuf); err != nil {
+		return
+	}
+	t.outBuf = t.outBuf[:0]
+	return
+}
+
+// ReadPassword temporarily changes the prompt and reads a password, without
+// echo, from the terminal.
+func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	oldPrompt := t.prompt
+	t.prompt = prompt
+	t.echo = false
+
+	line, err = t.readLine()
+
+	t.prompt = oldPrompt
+	t.echo = true
+
+	return
+}
+
+// ReadLine returns a line of input from the terminal.
+func (t *Terminal) ReadLine() (line string, err error) {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	return t.readLine()
+}
+
+func (t *Terminal) readLine() (line string, err error) {
+	// t.lock must be held at this point
+
+	if t.cursorX == 0 && t.cursorY == 0 {
+		t.writeLine([]byte(t.prompt))
+		t.c.Write(t.outBuf)
+		t.outBuf = t.outBuf[:0]
+	}
+
+	for {
+		rest := t.remainder
+		lineOk := false
+		for !lineOk {
+			var key int
+			key, rest = bytesToKey(rest)
+			if key < 0 {
+				break
+			}
+			if key == keyCtrlD {
+				return "", io.EOF
+			}
+			line, lineOk = t.handleKey(key)
+		}
+		if len(rest) > 0 {
+			n := copy(t.inBuf[:], rest)
+			t.remainder = t.inBuf[:n]
+		} else {
+			t.remainder = nil
+		}
+		t.c.Write(t.outBuf)
+		t.outBuf = t.outBuf[:0]
+		if lineOk {
+			return
+		}
+
+		// t.remainder is a slice at the beginning of t.inBuf
+		// containing a partial key sequence
+		readBuf := t.inBuf[len(t.remainder):]
+		var n int
+
+		t.lock.Unlock()
+		n, err = t.c.Read(readBuf)
+		t.lock.Lock()
+
+		if err != nil {
+			return
+		}
+
+		t.remainder = t.inBuf[:n+len(t.remainder)]
+	}
+	panic("unreachable")
+}
+
+// SetPrompt sets the prompt to be used when reading subsequent lines.
+func (t *Terminal) SetPrompt(prompt string) {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	t.prompt = prompt
+}
+
+func (t *Terminal) SetSize(width, height int) {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	t.termWidth, t.termHeight = width, height
+}
diff --git a/third_party/gofrontend/libgo/go/exp/terminal/terminal_test.go b/third_party/gofrontend/libgo/go/exp/terminal/terminal_test.go
new file mode 100644
index 0000000..a219721
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/exp/terminal/terminal_test.go
@@ -0,0 +1,110 @@
+// 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.
+
+package terminal
+
+import (
+	"io"
+	"testing"
+)
+
+type MockTerminal struct {
+	toSend       []byte
+	bytesPerRead int
+	received     []byte
+}
+
+func (c *MockTerminal) Read(data []byte) (n int, err error) {
+	n = len(data)
+	if n == 0 {
+		return
+	}
+	if n > len(c.toSend) {
+		n = len(c.toSend)
+	}
+	if n == 0 {
+		return 0, io.EOF
+	}
+	if c.bytesPerRead > 0 && n > c.bytesPerRead {
+		n = c.bytesPerRead
+	}
+	copy(data, c.toSend[:n])
+	c.toSend = c.toSend[n:]
+	return
+}
+
+func (c *MockTerminal) Write(data []byte) (n int, err error) {
+	c.received = append(c.received, data...)
+	return len(data), nil
+}
+
+func TestClose(t *testing.T) {
+	c := &MockTerminal{}
+	ss := NewTerminal(c, "> ")
+	line, err := ss.ReadLine()
+	if line != "" {
+		t.Errorf("Expected empty line but got: %s", line)
+	}
+	if err != io.EOF {
+		t.Errorf("Error should have been EOF but got: %s", err)
+	}
+}
+
+var keyPressTests = []struct {
+	in   string
+	line string
+	err  error
+}{
+	{
+		"",
+		"",
+		io.EOF,
+	},
+	{
+		"\r",
+		"",
+		nil,
+	},
+	{
+		"foo\r",
+		"foo",
+		nil,
+	},
+	{
+		"a\x1b[Cb\r", // right
+		"ab",
+		nil,
+	},
+	{
+		"a\x1b[Db\r", // left
+		"ba",
+		nil,
+	},
+	{
+		"a\177b\r", // backspace
+		"b",
+		nil,
+	},
+}
+
+func TestKeyPresses(t *testing.T) {
+	for i, test := range keyPressTests {
+		for j := 0; j < len(test.in); j++ {
+			c := &MockTerminal{
+				toSend:       []byte(test.in),
+				bytesPerRead: j,
+			}
+			ss := NewTerminal(c, "> ")
+			line, err := ss.ReadLine()
+			if line != test.line {
+				t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line)
+				break
+			}
+			if err != test.err {
+				t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err)
+				break
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/exp/terminal/util.go b/third_party/gofrontend/libgo/go/exp/terminal/util.go
new file mode 100644
index 0000000..211f41d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/exp/terminal/util.go
@@ -0,0 +1,118 @@
+// 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.
+
+// +build linux
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// 	oldState, err := terminal.MakeRaw(0)
+// 	if err != nil {
+// 	        panic(err)
+// 	}
+// 	defer terminal.Restore(0, oldState)
+package terminal
+
+import (
+	"io"
+	"syscall"
+	"unsafe"
+)
+
+// State contains the state of a terminal.
+type State struct {
+	termios syscall.Termios
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+	var termios syscall.Termios
+	err := syscall.Tcgetattr(fd, &termios)
+	return err == nil
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, error) {
+	var oldState State
+	if err := syscall.Tcgetattr(fd, &oldState.termios); err != nil {
+		return nil, err
+	}
+
+	newState := oldState.termios
+	newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF
+	newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG
+	if err := syscall.Tcsetattr(fd, syscall.TCSANOW, &newState); err != nil {
+		return nil, err
+	}
+
+	return &oldState, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, state *State) error {
+	err := syscall.Tcsetattr(fd, syscall.TCSANOW, &state.termios)
+	return err
+}
+
+//extern ioctl
+func ioctl(int, int, unsafe.Pointer) int
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+	var dimensions [4]uint16
+
+	if ioctl(fd, syscall.TIOCGWINSZ, unsafe.Pointer(&dimensions)) < 0 {
+		return -1, -1, syscall.GetErrno()
+	}
+	return int(dimensions[1]), int(dimensions[0]), nil
+}
+
+// ReadPassword reads a line of input from a terminal without local echo.  This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+	var oldState syscall.Termios
+	if err := syscall.Tcgetattr(fd, &oldState); err != nil {
+		return nil, err
+	}
+
+	newState := oldState
+	newState.Lflag &^= syscall.ECHO
+	if err := syscall.Tcsetattr(fd, syscall.TCSANOW, &newState); err != nil {
+		return nil, err
+	}
+
+	defer func() {
+		syscall.Tcsetattr(fd, syscall.TCSANOW, &oldState)
+	}()
+
+	var buf [16]byte
+	var ret []byte
+	for {
+		n, err := syscall.Read(fd, buf[:])
+		if err != nil {
+			return nil, err
+		}
+		if n == 0 {
+			if len(ret) == 0 {
+				return nil, io.EOF
+			}
+			break
+		}
+		if buf[n-1] == '\n' {
+			n--
+		}
+		ret = append(ret, buf[:n]...)
+		if n < len(buf) {
+			break
+		}
+	}
+
+	return ret, nil
+}
diff --git a/third_party/gofrontend/libgo/go/expvar/expvar.go b/third_party/gofrontend/libgo/go/expvar/expvar.go
new file mode 100644
index 0000000..9b6dab4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/expvar/expvar.go
@@ -0,0 +1,336 @@
+// 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 expvar provides a standardized interface to public variables, such
+// as operation counters in servers. It exposes these variables via HTTP at
+// /debug/vars in JSON format.
+//
+// Operations to set or modify these public variables are atomic.
+//
+// In addition to adding the HTTP handler, this package registers the
+// following variables:
+//
+//	cmdline   os.Args
+//	memstats  runtime.Memstats
+//
+// The package is sometimes only imported for the side effect of
+// registering its HTTP handler and the above variables.  To use it
+// this way, link this package into your program:
+//	import _ "expvar"
+//
+package expvar
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"log"
+	"net/http"
+	"os"
+	"runtime"
+	"sort"
+	"strconv"
+	"sync"
+)
+
+// Var is an abstract type for all exported variables.
+type Var interface {
+	String() string
+}
+
+// Int is a 64-bit integer variable that satisfies the Var interface.
+type Int struct {
+	mu sync.RWMutex
+	i  int64
+}
+
+func (v *Int) String() string {
+	v.mu.RLock()
+	defer v.mu.RUnlock()
+	return strconv.FormatInt(v.i, 10)
+}
+
+func (v *Int) Add(delta int64) {
+	v.mu.Lock()
+	defer v.mu.Unlock()
+	v.i += delta
+}
+
+func (v *Int) Set(value int64) {
+	v.mu.Lock()
+	defer v.mu.Unlock()
+	v.i = value
+}
+
+// Float is a 64-bit float variable that satisfies the Var interface.
+type Float struct {
+	mu sync.RWMutex
+	f  float64
+}
+
+func (v *Float) String() string {
+	v.mu.RLock()
+	defer v.mu.RUnlock()
+	return strconv.FormatFloat(v.f, 'g', -1, 64)
+}
+
+// Add adds delta to v.
+func (v *Float) Add(delta float64) {
+	v.mu.Lock()
+	defer v.mu.Unlock()
+	v.f += delta
+}
+
+// Set sets v to value.
+func (v *Float) Set(value float64) {
+	v.mu.Lock()
+	defer v.mu.Unlock()
+	v.f = value
+}
+
+// Map is a string-to-Var map variable that satisfies the Var interface.
+type Map struct {
+	mu   sync.RWMutex
+	m    map[string]Var
+	keys []string // sorted
+}
+
+// KeyValue represents a single entry in a Map.
+type KeyValue struct {
+	Key   string
+	Value Var
+}
+
+func (v *Map) String() string {
+	v.mu.RLock()
+	defer v.mu.RUnlock()
+	var b bytes.Buffer
+	fmt.Fprintf(&b, "{")
+	first := true
+	v.doLocked(func(kv KeyValue) {
+		if !first {
+			fmt.Fprintf(&b, ", ")
+		}
+		fmt.Fprintf(&b, "%q: %v", kv.Key, kv.Value)
+		first = false
+	})
+	fmt.Fprintf(&b, "}")
+	return b.String()
+}
+
+func (v *Map) Init() *Map {
+	v.m = make(map[string]Var)
+	return v
+}
+
+// updateKeys updates the sorted list of keys in v.keys.
+// must be called with v.mu held.
+func (v *Map) updateKeys() {
+	if len(v.m) == len(v.keys) {
+		// No new key.
+		return
+	}
+	v.keys = v.keys[:0]
+	for k := range v.m {
+		v.keys = append(v.keys, k)
+	}
+	sort.Strings(v.keys)
+}
+
+func (v *Map) Get(key string) Var {
+	v.mu.RLock()
+	defer v.mu.RUnlock()
+	return v.m[key]
+}
+
+func (v *Map) Set(key string, av Var) {
+	v.mu.Lock()
+	defer v.mu.Unlock()
+	v.m[key] = av
+	v.updateKeys()
+}
+
+func (v *Map) Add(key string, delta int64) {
+	v.mu.RLock()
+	av, ok := v.m[key]
+	v.mu.RUnlock()
+	if !ok {
+		// check again under the write lock
+		v.mu.Lock()
+		av, ok = v.m[key]
+		if !ok {
+			av = new(Int)
+			v.m[key] = av
+			v.updateKeys()
+		}
+		v.mu.Unlock()
+	}
+
+	// Add to Int; ignore otherwise.
+	if iv, ok := av.(*Int); ok {
+		iv.Add(delta)
+	}
+}
+
+// AddFloat adds delta to the *Float value stored under the given map key.
+func (v *Map) AddFloat(key string, delta float64) {
+	v.mu.RLock()
+	av, ok := v.m[key]
+	v.mu.RUnlock()
+	if !ok {
+		// check again under the write lock
+		v.mu.Lock()
+		av, ok = v.m[key]
+		if !ok {
+			av = new(Float)
+			v.m[key] = av
+			v.updateKeys()
+		}
+		v.mu.Unlock()
+	}
+
+	// Add to Float; ignore otherwise.
+	if iv, ok := av.(*Float); ok {
+		iv.Add(delta)
+	}
+}
+
+// Do calls f for each entry in the map.
+// The map is locked during the iteration,
+// but existing entries may be concurrently updated.
+func (v *Map) Do(f func(KeyValue)) {
+	v.mu.RLock()
+	defer v.mu.RUnlock()
+	v.doLocked(f)
+}
+
+// doLocked calls f for each entry in the map.
+// v.mu must be held for reads.
+func (v *Map) doLocked(f func(KeyValue)) {
+	for _, k := range v.keys {
+		f(KeyValue{k, v.m[k]})
+	}
+}
+
+// String is a string variable, and satisfies the Var interface.
+type String struct {
+	mu sync.RWMutex
+	s  string
+}
+
+func (v *String) String() string {
+	v.mu.RLock()
+	defer v.mu.RUnlock()
+	return strconv.Quote(v.s)
+}
+
+func (v *String) Set(value string) {
+	v.mu.Lock()
+	defer v.mu.Unlock()
+	v.s = value
+}
+
+// Func implements Var by calling the function
+// and formatting the returned value using JSON.
+type Func func() interface{}
+
+func (f Func) String() string {
+	v, _ := json.Marshal(f())
+	return string(v)
+}
+
+// All published variables.
+var (
+	mutex   sync.RWMutex
+	vars    = make(map[string]Var)
+	varKeys []string // sorted
+)
+
+// Publish declares a named exported variable. This should be called from a
+// package's init function when it creates its Vars. If the name is already
+// registered then this will log.Panic.
+func Publish(name string, v Var) {
+	mutex.Lock()
+	defer mutex.Unlock()
+	if _, existing := vars[name]; existing {
+		log.Panicln("Reuse of exported var name:", name)
+	}
+	vars[name] = v
+	varKeys = append(varKeys, name)
+	sort.Strings(varKeys)
+}
+
+// Get retrieves a named exported variable.
+func Get(name string) Var {
+	mutex.RLock()
+	defer mutex.RUnlock()
+	return vars[name]
+}
+
+// Convenience functions for creating new exported variables.
+
+func NewInt(name string) *Int {
+	v := new(Int)
+	Publish(name, v)
+	return v
+}
+
+func NewFloat(name string) *Float {
+	v := new(Float)
+	Publish(name, v)
+	return v
+}
+
+func NewMap(name string) *Map {
+	v := new(Map).Init()
+	Publish(name, v)
+	return v
+}
+
+func NewString(name string) *String {
+	v := new(String)
+	Publish(name, v)
+	return v
+}
+
+// Do calls f for each exported variable.
+// The global variable map is locked during the iteration,
+// but existing entries may be concurrently updated.
+func Do(f func(KeyValue)) {
+	mutex.RLock()
+	defer mutex.RUnlock()
+	for _, k := range varKeys {
+		f(KeyValue{k, vars[k]})
+	}
+}
+
+func expvarHandler(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json; charset=utf-8")
+	fmt.Fprintf(w, "{\n")
+	first := true
+	Do(func(kv KeyValue) {
+		if !first {
+			fmt.Fprintf(w, ",\n")
+		}
+		first = false
+		fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
+	})
+	fmt.Fprintf(w, "\n}\n")
+}
+
+func cmdline() interface{} {
+	return os.Args
+}
+
+func memstats() interface{} {
+	stats := new(runtime.MemStats)
+	runtime.ReadMemStats(stats)
+	return *stats
+}
+
+func init() {
+	http.HandleFunc("/debug/vars", expvarHandler)
+	Publish("cmdline", Func(cmdline))
+	Publish("memstats", Func(memstats))
+}
diff --git a/third_party/gofrontend/libgo/go/expvar/expvar_test.go b/third_party/gofrontend/libgo/go/expvar/expvar_test.go
new file mode 100644
index 0000000..765e3b7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/expvar/expvar_test.go
@@ -0,0 +1,167 @@
+// 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 expvar
+
+import (
+	"bytes"
+	"encoding/json"
+	"net/http/httptest"
+	"strconv"
+	"testing"
+)
+
+// RemoveAll removes all exported variables.
+// This is for tests only.
+func RemoveAll() {
+	mutex.Lock()
+	defer mutex.Unlock()
+	vars = make(map[string]Var)
+	varKeys = nil
+}
+
+func TestInt(t *testing.T) {
+	RemoveAll()
+	reqs := NewInt("requests")
+	if reqs.i != 0 {
+		t.Errorf("reqs.i = %v, want 0", reqs.i)
+	}
+	if reqs != Get("requests").(*Int) {
+		t.Errorf("Get() failed.")
+	}
+
+	reqs.Add(1)
+	reqs.Add(3)
+	if reqs.i != 4 {
+		t.Errorf("reqs.i = %v, want 4", reqs.i)
+	}
+
+	if s := reqs.String(); s != "4" {
+		t.Errorf("reqs.String() = %q, want \"4\"", s)
+	}
+
+	reqs.Set(-2)
+	if reqs.i != -2 {
+		t.Errorf("reqs.i = %v, want -2", reqs.i)
+	}
+}
+
+func TestFloat(t *testing.T) {
+	RemoveAll()
+	reqs := NewFloat("requests-float")
+	if reqs.f != 0.0 {
+		t.Errorf("reqs.f = %v, want 0", reqs.f)
+	}
+	if reqs != Get("requests-float").(*Float) {
+		t.Errorf("Get() failed.")
+	}
+
+	reqs.Add(1.5)
+	reqs.Add(1.25)
+	if reqs.f != 2.75 {
+		t.Errorf("reqs.f = %v, want 2.75", reqs.f)
+	}
+
+	if s := reqs.String(); s != "2.75" {
+		t.Errorf("reqs.String() = %q, want \"4.64\"", s)
+	}
+
+	reqs.Add(-2)
+	if reqs.f != 0.75 {
+		t.Errorf("reqs.f = %v, want 0.75", reqs.f)
+	}
+}
+
+func TestString(t *testing.T) {
+	RemoveAll()
+	name := NewString("my-name")
+	if name.s != "" {
+		t.Errorf("name.s = %q, want \"\"", name.s)
+	}
+
+	name.Set("Mike")
+	if name.s != "Mike" {
+		t.Errorf("name.s = %q, want \"Mike\"", name.s)
+	}
+
+	if s := name.String(); s != "\"Mike\"" {
+		t.Errorf("reqs.String() = %q, want \"\"Mike\"\"", s)
+	}
+}
+
+func TestMapCounter(t *testing.T) {
+	RemoveAll()
+	colors := NewMap("bike-shed-colors")
+
+	colors.Add("red", 1)
+	colors.Add("red", 2)
+	colors.Add("blue", 4)
+	colors.AddFloat(`green "midori"`, 4.125)
+	if x := colors.m["red"].(*Int).i; x != 3 {
+		t.Errorf("colors.m[\"red\"] = %v, want 3", x)
+	}
+	if x := colors.m["blue"].(*Int).i; x != 4 {
+		t.Errorf("colors.m[\"blue\"] = %v, want 4", x)
+	}
+	if x := colors.m[`green "midori"`].(*Float).f; x != 4.125 {
+		t.Errorf("colors.m[`green \"midori\"] = %v, want 3.14", x)
+	}
+
+	// colors.String() should be '{"red":3, "blue":4}',
+	// though the order of red and blue could vary.
+	s := colors.String()
+	var j interface{}
+	err := json.Unmarshal([]byte(s), &j)
+	if err != nil {
+		t.Errorf("colors.String() isn't valid JSON: %v", err)
+	}
+	m, ok := j.(map[string]interface{})
+	if !ok {
+		t.Error("colors.String() didn't produce a map.")
+	}
+	red := m["red"]
+	x, ok := red.(float64)
+	if !ok {
+		t.Error("red.Kind() is not a number.")
+	}
+	if x != 3 {
+		t.Errorf("red = %v, want 3", x)
+	}
+}
+
+func TestFunc(t *testing.T) {
+	RemoveAll()
+	var x interface{} = []string{"a", "b"}
+	f := Func(func() interface{} { return x })
+	if s, exp := f.String(), `["a","b"]`; s != exp {
+		t.Errorf(`f.String() = %q, want %q`, s, exp)
+	}
+
+	x = 17
+	if s, exp := f.String(), `17`; s != exp {
+		t.Errorf(`f.String() = %q, want %q`, s, exp)
+	}
+}
+
+func TestHandler(t *testing.T) {
+	RemoveAll()
+	m := NewMap("map1")
+	m.Add("a", 1)
+	m.Add("z", 2)
+	m2 := NewMap("map2")
+	for i := 0; i < 9; i++ {
+		m2.Add(strconv.Itoa(i), int64(i))
+	}
+	rr := httptest.NewRecorder()
+	rr.Body = new(bytes.Buffer)
+	expvarHandler(rr, nil)
+	want := `{
+"map1": {"a": 1, "z": 2},
+"map2": {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8}
+}
+`
+	if got := rr.Body.String(); got != want {
+		t.Errorf("HTTP handler wrote:\n%s\nWant:\n%s", got, want)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/flag/example_test.go b/third_party/gofrontend/libgo/go/flag/example_test.go
new file mode 100644
index 0000000..04a0d20
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/flag/example_test.go
@@ -0,0 +1,83 @@
+// 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.
+
+// These examples demonstrate more intricate uses of the flag package.
+package flag_test
+
+import (
+	"errors"
+	"flag"
+	"fmt"
+	"strings"
+	"time"
+)
+
+// Example 1: A single string flag called "species" with default value "gopher".
+var species = flag.String("species", "gopher", "the species we are studying")
+
+// Example 2: Two flags sharing a variable, so we can have a shorthand.
+// The order of initialization is undefined, so make sure both use the
+// same default value. They must be set up with an init function.
+var gopherType string
+
+func init() {
+	const (
+		defaultGopher = "pocket"
+		usage         = "the variety of gopher"
+	)
+	flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage)
+	flag.StringVar(&gopherType, "g", defaultGopher, usage+" (shorthand)")
+}
+
+// Example 3: A user-defined flag type, a slice of durations.
+type interval []time.Duration
+
+// String is the method to format the flag's value, part of the flag.Value interface.
+// The String method's output will be used in diagnostics.
+func (i *interval) String() string {
+	return fmt.Sprint(*i)
+}
+
+// Set is the method to set the flag value, part of the flag.Value interface.
+// Set's argument is a string to be parsed to set the flag.
+// It's a comma-separated list, so we split it.
+func (i *interval) Set(value string) error {
+	// If we wanted to allow the flag to be set multiple times,
+	// accumulating values, we would delete this if statement.
+	// That would permit usages such as
+	//	-deltaT 10s -deltaT 15s
+	// and other combinations.
+	if len(*i) > 0 {
+		return errors.New("interval flag already set")
+	}
+	for _, dt := range strings.Split(value, ",") {
+		duration, err := time.ParseDuration(dt)
+		if err != nil {
+			return err
+		}
+		*i = append(*i, duration)
+	}
+	return nil
+}
+
+// Define a flag to accumulate durations. Because it has a special type,
+// we need to use the Var function and therefore create the flag during
+// init.
+
+var intervalFlag interval
+
+func init() {
+	// Tie the command-line flag to the intervalFlag variable and
+	// set a usage message.
+	flag.Var(&intervalFlag, "deltaT", "comma-separated list of intervals to use between events")
+}
+
+func Example() {
+	// All the interesting pieces are with the variables declared above, but
+	// to enable the flag package to see the flags defined there, one must
+	// execute, typically at the start of main (not init!):
+	//	flag.Parse()
+	// We don't run it here because this is not a main function and
+	// the testing suite has already parsed the flags.
+}
diff --git a/third_party/gofrontend/libgo/go/flag/export_test.go b/third_party/gofrontend/libgo/go/flag/export_test.go
new file mode 100644
index 0000000..56cda58
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/flag/export_test.go
@@ -0,0 +1,17 @@
+// Copyright 2010 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 flag
+
+import "os"
+
+// Additional routines compiled into the package only during testing.
+
+// ResetForTesting clears all flag state and sets the usage function as directed.
+// After calling ResetForTesting, parse errors in flag handling will not
+// exit the program.
+func ResetForTesting(usage func()) {
+	CommandLine = NewFlagSet(os.Args[0], ContinueOnError)
+	Usage = usage
+}
diff --git a/third_party/gofrontend/libgo/go/flag/flag.go b/third_party/gofrontend/libgo/go/flag/flag.go
new file mode 100644
index 0000000..cd2a165
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/flag/flag.go
@@ -0,0 +1,849 @@
+// 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 flag implements command-line flag parsing.
+
+	Usage:
+
+	Define flags using flag.String(), Bool(), Int(), etc.
+
+	This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
+		import "flag"
+		var ip = flag.Int("flagname", 1234, "help message for flagname")
+	If you like, you can bind the flag to a variable using the Var() functions.
+		var flagvar int
+		func init() {
+			flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
+		}
+	Or you can create custom flags that satisfy the Value interface (with
+	pointer receivers) and couple them to flag parsing by
+		flag.Var(&flagVal, "name", "help message for flagname")
+	For such flags, the default value is just the initial value of the variable.
+
+	After all flags are defined, call
+		flag.Parse()
+	to parse the command line into the defined flags.
+
+	Flags may then be used directly. If you're using the flags themselves,
+	they are all pointers; if you bind to variables, they're values.
+		fmt.Println("ip has value ", *ip)
+		fmt.Println("flagvar has value ", flagvar)
+
+	After parsing, the arguments after the flag are available as the
+	slice flag.Args() or individually as flag.Arg(i).
+	The arguments are indexed from 0 through flag.NArg()-1.
+
+	Command line flag syntax:
+		-flag
+		-flag=x
+		-flag x  // non-boolean flags only
+	One or two minus signs may be used; they are equivalent.
+	The last form is not permitted for boolean flags because the
+	meaning of the command
+		cmd -x *
+	will change if there is a file called 0, false, etc.  You must
+	use the -flag=false form to turn off a boolean flag.
+
+	Flag parsing stops just before the first non-flag argument
+	("-" is a non-flag argument) or after the terminator "--".
+
+	Integer flags accept 1234, 0664, 0x1234 and may be negative.
+	Boolean flags may be:
+		1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False
+	Duration flags accept any input valid for time.ParseDuration.
+
+	The default set of command-line flags is controlled by
+	top-level functions.  The FlagSet type allows one to define
+	independent sets of flags, such as to implement subcommands
+	in a command-line interface. The methods of FlagSet are
+	analogous to the top-level functions for the command-line
+	flag set.
+*/
+package flag
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"os"
+	"sort"
+	"strconv"
+	"time"
+)
+
+// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined.
+var ErrHelp = errors.New("flag: help requested")
+
+// -- bool Value
+type boolValue bool
+
+func newBoolValue(val bool, p *bool) *boolValue {
+	*p = val
+	return (*boolValue)(p)
+}
+
+func (b *boolValue) Set(s string) error {
+	v, err := strconv.ParseBool(s)
+	*b = boolValue(v)
+	return err
+}
+
+func (b *boolValue) Get() interface{} { return bool(*b) }
+
+func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
+
+func (b *boolValue) IsBoolFlag() bool { return true }
+
+// optional interface to indicate boolean flags that can be
+// supplied without "=value" text
+type boolFlag interface {
+	Value
+	IsBoolFlag() bool
+}
+
+// -- int Value
+type intValue int
+
+func newIntValue(val int, p *int) *intValue {
+	*p = val
+	return (*intValue)(p)
+}
+
+func (i *intValue) Set(s string) error {
+	v, err := strconv.ParseInt(s, 0, 64)
+	*i = intValue(v)
+	return err
+}
+
+func (i *intValue) Get() interface{} { return int(*i) }
+
+func (i *intValue) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- int64 Value
+type int64Value int64
+
+func newInt64Value(val int64, p *int64) *int64Value {
+	*p = val
+	return (*int64Value)(p)
+}
+
+func (i *int64Value) Set(s string) error {
+	v, err := strconv.ParseInt(s, 0, 64)
+	*i = int64Value(v)
+	return err
+}
+
+func (i *int64Value) Get() interface{} { return int64(*i) }
+
+func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- uint Value
+type uintValue uint
+
+func newUintValue(val uint, p *uint) *uintValue {
+	*p = val
+	return (*uintValue)(p)
+}
+
+func (i *uintValue) Set(s string) error {
+	v, err := strconv.ParseUint(s, 0, 64)
+	*i = uintValue(v)
+	return err
+}
+
+func (i *uintValue) Get() interface{} { return uint(*i) }
+
+func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- uint64 Value
+type uint64Value uint64
+
+func newUint64Value(val uint64, p *uint64) *uint64Value {
+	*p = val
+	return (*uint64Value)(p)
+}
+
+func (i *uint64Value) Set(s string) error {
+	v, err := strconv.ParseUint(s, 0, 64)
+	*i = uint64Value(v)
+	return err
+}
+
+func (i *uint64Value) Get() interface{} { return uint64(*i) }
+
+func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- string Value
+type stringValue string
+
+func newStringValue(val string, p *string) *stringValue {
+	*p = val
+	return (*stringValue)(p)
+}
+
+func (s *stringValue) Set(val string) error {
+	*s = stringValue(val)
+	return nil
+}
+
+func (s *stringValue) Get() interface{} { return string(*s) }
+
+func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
+
+// -- float64 Value
+type float64Value float64
+
+func newFloat64Value(val float64, p *float64) *float64Value {
+	*p = val
+	return (*float64Value)(p)
+}
+
+func (f *float64Value) Set(s string) error {
+	v, err := strconv.ParseFloat(s, 64)
+	*f = float64Value(v)
+	return err
+}
+
+func (f *float64Value) Get() interface{} { return float64(*f) }
+
+func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// -- time.Duration Value
+type durationValue time.Duration
+
+func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
+	*p = val
+	return (*durationValue)(p)
+}
+
+func (d *durationValue) Set(s string) error {
+	v, err := time.ParseDuration(s)
+	*d = durationValue(v)
+	return err
+}
+
+func (d *durationValue) Get() interface{} { return time.Duration(*d) }
+
+func (d *durationValue) String() string { return (*time.Duration)(d).String() }
+
+// Value is the interface to the dynamic value stored in a flag.
+// (The default value is represented as a string.)
+//
+// If a Value has an IsBoolFlag() bool method returning true,
+// the command-line parser makes -name equivalent to -name=true
+// rather than using the next command-line argument.
+type Value interface {
+	String() string
+	Set(string) error
+}
+
+// Getter is an interface that allows the contents of a Value to be retrieved.
+// It wraps the Value interface, rather than being part of it, because it
+// appeared after Go 1 and its compatibility rules. All Value types provided
+// by this package satisfy the Getter interface.
+type Getter interface {
+	Value
+	Get() interface{}
+}
+
+// ErrorHandling defines how to handle flag parsing errors.
+type ErrorHandling int
+
+const (
+	ContinueOnError ErrorHandling = iota
+	ExitOnError
+	PanicOnError
+)
+
+// A FlagSet represents a set of defined flags.  The zero value of a FlagSet
+// has no name and has ContinueOnError error handling.
+type FlagSet struct {
+	// Usage is the function called when an error occurs while parsing flags.
+	// The field is a function (not a method) that may be changed to point to
+	// a custom error handler.
+	Usage func()
+
+	name          string
+	parsed        bool
+	actual        map[string]*Flag
+	formal        map[string]*Flag
+	args          []string // arguments after flags
+	errorHandling ErrorHandling
+	output        io.Writer // nil means stderr; use out() accessor
+}
+
+// A Flag represents the state of a flag.
+type Flag struct {
+	Name     string // name as it appears on command line
+	Usage    string // help message
+	Value    Value  // value as set
+	DefValue string // default value (as text); for usage message
+}
+
+// sortFlags returns the flags as a slice in lexicographical sorted order.
+func sortFlags(flags map[string]*Flag) []*Flag {
+	list := make(sort.StringSlice, len(flags))
+	i := 0
+	for _, f := range flags {
+		list[i] = f.Name
+		i++
+	}
+	list.Sort()
+	result := make([]*Flag, len(list))
+	for i, name := range list {
+		result[i] = flags[name]
+	}
+	return result
+}
+
+func (f *FlagSet) out() io.Writer {
+	if f.output == nil {
+		return os.Stderr
+	}
+	return f.output
+}
+
+// SetOutput sets the destination for usage and error messages.
+// If output is nil, os.Stderr is used.
+func (f *FlagSet) SetOutput(output io.Writer) {
+	f.output = output
+}
+
+// VisitAll visits the flags in lexicographical order, calling fn for each.
+// It visits all flags, even those not set.
+func (f *FlagSet) VisitAll(fn func(*Flag)) {
+	for _, flag := range sortFlags(f.formal) {
+		fn(flag)
+	}
+}
+
+// VisitAll visits the command-line flags in lexicographical order, calling
+// fn for each.  It visits all flags, even those not set.
+func VisitAll(fn func(*Flag)) {
+	CommandLine.VisitAll(fn)
+}
+
+// Visit visits the flags in lexicographical order, calling fn for each.
+// It visits only those flags that have been set.
+func (f *FlagSet) Visit(fn func(*Flag)) {
+	for _, flag := range sortFlags(f.actual) {
+		fn(flag)
+	}
+}
+
+// Visit visits the command-line flags in lexicographical order, calling fn
+// for each.  It visits only those flags that have been set.
+func Visit(fn func(*Flag)) {
+	CommandLine.Visit(fn)
+}
+
+// Lookup returns the Flag structure of the named flag, returning nil if none exists.
+func (f *FlagSet) Lookup(name string) *Flag {
+	return f.formal[name]
+}
+
+// Lookup returns the Flag structure of the named command-line flag,
+// returning nil if none exists.
+func Lookup(name string) *Flag {
+	return CommandLine.formal[name]
+}
+
+// Set sets the value of the named flag.
+func (f *FlagSet) Set(name, value string) error {
+	flag, ok := f.formal[name]
+	if !ok {
+		return fmt.Errorf("no such flag -%v", name)
+	}
+	err := flag.Value.Set(value)
+	if err != nil {
+		return err
+	}
+	if f.actual == nil {
+		f.actual = make(map[string]*Flag)
+	}
+	f.actual[name] = flag
+	return nil
+}
+
+// Set sets the value of the named command-line flag.
+func Set(name, value string) error {
+	return CommandLine.Set(name, value)
+}
+
+// PrintDefaults prints, to standard error unless configured
+// otherwise, the default values of all defined flags in the set.
+func (f *FlagSet) PrintDefaults() {
+	f.VisitAll(func(flag *Flag) {
+		format := "  -%s=%s: %s\n"
+		if _, ok := flag.Value.(*stringValue); ok {
+			// put quotes on the value
+			format = "  -%s=%q: %s\n"
+		}
+		fmt.Fprintf(f.out(), format, flag.Name, flag.DefValue, flag.Usage)
+	})
+}
+
+// PrintDefaults prints to standard error the default values of all defined command-line flags.
+func PrintDefaults() {
+	CommandLine.PrintDefaults()
+}
+
+// defaultUsage is the default function to print a usage message.
+func defaultUsage(f *FlagSet) {
+	if f.name == "" {
+		fmt.Fprintf(f.out(), "Usage:\n")
+	} else {
+		fmt.Fprintf(f.out(), "Usage of %s:\n", f.name)
+	}
+	f.PrintDefaults()
+}
+
+// NOTE: Usage is not just defaultUsage(CommandLine)
+// because it serves (via godoc flag Usage) as the example
+// for how to write your own usage function.
+
+// Usage prints to standard error a usage message documenting all defined command-line flags.
+// The function is a variable that may be changed to point to a custom function.
+var Usage = func() {
+	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
+	PrintDefaults()
+}
+
+// NFlag returns the number of flags that have been set.
+func (f *FlagSet) NFlag() int { return len(f.actual) }
+
+// NFlag returns the number of command-line flags that have been set.
+func NFlag() int { return len(CommandLine.actual) }
+
+// Arg returns the i'th argument.  Arg(0) is the first remaining argument
+// after flags have been processed.
+func (f *FlagSet) Arg(i int) string {
+	if i < 0 || i >= len(f.args) {
+		return ""
+	}
+	return f.args[i]
+}
+
+// Arg returns the i'th command-line argument.  Arg(0) is the first remaining argument
+// after flags have been processed.
+func Arg(i int) string {
+	return CommandLine.Arg(i)
+}
+
+// NArg is the number of arguments remaining after flags have been processed.
+func (f *FlagSet) NArg() int { return len(f.args) }
+
+// NArg is the number of arguments remaining after flags have been processed.
+func NArg() int { return len(CommandLine.args) }
+
+// Args returns the non-flag arguments.
+func (f *FlagSet) Args() []string { return f.args }
+
+// Args returns the non-flag command-line arguments.
+func Args() []string { return CommandLine.args }
+
+// BoolVar defines a bool flag with specified name, default value, and usage string.
+// The argument p points to a bool variable in which to store the value of the flag.
+func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
+	f.Var(newBoolValue(value, p), name, usage)
+}
+
+// BoolVar defines a bool flag with specified name, default value, and usage string.
+// The argument p points to a bool variable in which to store the value of the flag.
+func BoolVar(p *bool, name string, value bool, usage string) {
+	CommandLine.Var(newBoolValue(value, p), name, usage)
+}
+
+// Bool defines a bool flag with specified name, default value, and usage string.
+// The return value is the address of a bool variable that stores the value of the flag.
+func (f *FlagSet) Bool(name string, value bool, usage string) *bool {
+	p := new(bool)
+	f.BoolVar(p, name, value, usage)
+	return p
+}
+
+// Bool defines a bool flag with specified name, default value, and usage string.
+// The return value is the address of a bool variable that stores the value of the flag.
+func Bool(name string, value bool, usage string) *bool {
+	return CommandLine.Bool(name, value, usage)
+}
+
+// IntVar defines an int flag with specified name, default value, and usage string.
+// The argument p points to an int variable in which to store the value of the flag.
+func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
+	f.Var(newIntValue(value, p), name, usage)
+}
+
+// IntVar defines an int flag with specified name, default value, and usage string.
+// The argument p points to an int variable in which to store the value of the flag.
+func IntVar(p *int, name string, value int, usage string) {
+	CommandLine.Var(newIntValue(value, p), name, usage)
+}
+
+// Int defines an int flag with specified name, default value, and usage string.
+// The return value is the address of an int variable that stores the value of the flag.
+func (f *FlagSet) Int(name string, value int, usage string) *int {
+	p := new(int)
+	f.IntVar(p, name, value, usage)
+	return p
+}
+
+// Int defines an int flag with specified name, default value, and usage string.
+// The return value is the address of an int variable that stores the value of the flag.
+func Int(name string, value int, usage string) *int {
+	return CommandLine.Int(name, value, usage)
+}
+
+// Int64Var defines an int64 flag with specified name, default value, and usage string.
+// The argument p points to an int64 variable in which to store the value of the flag.
+func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) {
+	f.Var(newInt64Value(value, p), name, usage)
+}
+
+// Int64Var defines an int64 flag with specified name, default value, and usage string.
+// The argument p points to an int64 variable in which to store the value of the flag.
+func Int64Var(p *int64, name string, value int64, usage string) {
+	CommandLine.Var(newInt64Value(value, p), name, usage)
+}
+
+// Int64 defines an int64 flag with specified name, default value, and usage string.
+// The return value is the address of an int64 variable that stores the value of the flag.
+func (f *FlagSet) Int64(name string, value int64, usage string) *int64 {
+	p := new(int64)
+	f.Int64Var(p, name, value, usage)
+	return p
+}
+
+// Int64 defines an int64 flag with specified name, default value, and usage string.
+// The return value is the address of an int64 variable that stores the value of the flag.
+func Int64(name string, value int64, usage string) *int64 {
+	return CommandLine.Int64(name, value, usage)
+}
+
+// UintVar defines a uint flag with specified name, default value, and usage string.
+// The argument p points to a uint variable in which to store the value of the flag.
+func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) {
+	f.Var(newUintValue(value, p), name, usage)
+}
+
+// UintVar defines a uint flag with specified name, default value, and usage string.
+// The argument p points to a uint  variable in which to store the value of the flag.
+func UintVar(p *uint, name string, value uint, usage string) {
+	CommandLine.Var(newUintValue(value, p), name, usage)
+}
+
+// Uint defines a uint flag with specified name, default value, and usage string.
+// The return value is the address of a uint  variable that stores the value of the flag.
+func (f *FlagSet) Uint(name string, value uint, usage string) *uint {
+	p := new(uint)
+	f.UintVar(p, name, value, usage)
+	return p
+}
+
+// Uint defines a uint flag with specified name, default value, and usage string.
+// The return value is the address of a uint  variable that stores the value of the flag.
+func Uint(name string, value uint, usage string) *uint {
+	return CommandLine.Uint(name, value, usage)
+}
+
+// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
+// The argument p points to a uint64 variable in which to store the value of the flag.
+func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) {
+	f.Var(newUint64Value(value, p), name, usage)
+}
+
+// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
+// The argument p points to a uint64 variable in which to store the value of the flag.
+func Uint64Var(p *uint64, name string, value uint64, usage string) {
+	CommandLine.Var(newUint64Value(value, p), name, usage)
+}
+
+// Uint64 defines a uint64 flag with specified name, default value, and usage string.
+// The return value is the address of a uint64 variable that stores the value of the flag.
+func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 {
+	p := new(uint64)
+	f.Uint64Var(p, name, value, usage)
+	return p
+}
+
+// Uint64 defines a uint64 flag with specified name, default value, and usage string.
+// The return value is the address of a uint64 variable that stores the value of the flag.
+func Uint64(name string, value uint64, usage string) *uint64 {
+	return CommandLine.Uint64(name, value, usage)
+}
+
+// StringVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a string variable in which to store the value of the flag.
+func (f *FlagSet) StringVar(p *string, name string, value string, usage string) {
+	f.Var(newStringValue(value, p), name, usage)
+}
+
+// StringVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a string variable in which to store the value of the flag.
+func StringVar(p *string, name string, value string, usage string) {
+	CommandLine.Var(newStringValue(value, p), name, usage)
+}
+
+// String defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a string variable that stores the value of the flag.
+func (f *FlagSet) String(name string, value string, usage string) *string {
+	p := new(string)
+	f.StringVar(p, name, value, usage)
+	return p
+}
+
+// String defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a string variable that stores the value of the flag.
+func String(name string, value string, usage string) *string {
+	return CommandLine.String(name, value, usage)
+}
+
+// Float64Var defines a float64 flag with specified name, default value, and usage string.
+// The argument p points to a float64 variable in which to store the value of the flag.
+func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) {
+	f.Var(newFloat64Value(value, p), name, usage)
+}
+
+// Float64Var defines a float64 flag with specified name, default value, and usage string.
+// The argument p points to a float64 variable in which to store the value of the flag.
+func Float64Var(p *float64, name string, value float64, usage string) {
+	CommandLine.Var(newFloat64Value(value, p), name, usage)
+}
+
+// Float64 defines a float64 flag with specified name, default value, and usage string.
+// The return value is the address of a float64 variable that stores the value of the flag.
+func (f *FlagSet) Float64(name string, value float64, usage string) *float64 {
+	p := new(float64)
+	f.Float64Var(p, name, value, usage)
+	return p
+}
+
+// Float64 defines a float64 flag with specified name, default value, and usage string.
+// The return value is the address of a float64 variable that stores the value of the flag.
+func Float64(name string, value float64, usage string) *float64 {
+	return CommandLine.Float64(name, value, usage)
+}
+
+// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
+// The argument p points to a time.Duration variable in which to store the value of the flag.
+func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
+	f.Var(newDurationValue(value, p), name, usage)
+}
+
+// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
+// The argument p points to a time.Duration variable in which to store the value of the flag.
+func DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
+	CommandLine.Var(newDurationValue(value, p), name, usage)
+}
+
+// Duration defines a time.Duration flag with specified name, default value, and usage string.
+// The return value is the address of a time.Duration variable that stores the value of the flag.
+func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration {
+	p := new(time.Duration)
+	f.DurationVar(p, name, value, usage)
+	return p
+}
+
+// Duration defines a time.Duration flag with specified name, default value, and usage string.
+// The return value is the address of a time.Duration variable that stores the value of the flag.
+func Duration(name string, value time.Duration, usage string) *time.Duration {
+	return CommandLine.Duration(name, value, usage)
+}
+
+// Var defines a flag with the specified name and usage string. The type and
+// value of the flag are represented by the first argument, of type Value, which
+// typically holds a user-defined implementation of Value. For instance, the
+// caller could create a flag that turns a comma-separated string into a slice
+// of strings by giving the slice the methods of Value; in particular, Set would
+// decompose the comma-separated string into the slice.
+func (f *FlagSet) Var(value Value, name string, usage string) {
+	// Remember the default value as a string; it won't change.
+	flag := &Flag{name, usage, value, value.String()}
+	_, alreadythere := f.formal[name]
+	if alreadythere {
+		var msg string
+		if f.name == "" {
+			msg = fmt.Sprintf("flag redefined: %s", name)
+		} else {
+			msg = fmt.Sprintf("%s flag redefined: %s", f.name, name)
+		}
+		fmt.Fprintln(f.out(), msg)
+		panic(msg) // Happens only if flags are declared with identical names
+	}
+	if f.formal == nil {
+		f.formal = make(map[string]*Flag)
+	}
+	f.formal[name] = flag
+}
+
+// Var defines a flag with the specified name and usage string. The type and
+// value of the flag are represented by the first argument, of type Value, which
+// typically holds a user-defined implementation of Value. For instance, the
+// caller could create a flag that turns a comma-separated string into a slice
+// of strings by giving the slice the methods of Value; in particular, Set would
+// decompose the comma-separated string into the slice.
+func Var(value Value, name string, usage string) {
+	CommandLine.Var(value, name, usage)
+}
+
+// failf prints to standard error a formatted error and usage message and
+// returns the error.
+func (f *FlagSet) failf(format string, a ...interface{}) error {
+	err := fmt.Errorf(format, a...)
+	fmt.Fprintln(f.out(), err)
+	f.usage()
+	return err
+}
+
+// usage calls the Usage method for the flag set, or the usage function if
+// the flag set is CommandLine.
+func (f *FlagSet) usage() {
+	if f == CommandLine {
+		Usage()
+	} else if f.Usage == nil {
+		defaultUsage(f)
+	} else {
+		f.Usage()
+	}
+}
+
+// parseOne parses one flag. It reports whether a flag was seen.
+func (f *FlagSet) parseOne() (bool, error) {
+	if len(f.args) == 0 {
+		return false, nil
+	}
+	s := f.args[0]
+	if len(s) == 0 || s[0] != '-' || len(s) == 1 {
+		return false, nil
+	}
+	num_minuses := 1
+	if s[1] == '-' {
+		num_minuses++
+		if len(s) == 2 { // "--" terminates the flags
+			f.args = f.args[1:]
+			return false, nil
+		}
+	}
+	name := s[num_minuses:]
+	if len(name) == 0 || name[0] == '-' || name[0] == '=' {
+		return false, f.failf("bad flag syntax: %s", s)
+	}
+
+	// it's a flag. does it have an argument?
+	f.args = f.args[1:]
+	has_value := false
+	value := ""
+	for i := 1; i < len(name); i++ { // equals cannot be first
+		if name[i] == '=' {
+			value = name[i+1:]
+			has_value = true
+			name = name[0:i]
+			break
+		}
+	}
+	m := f.formal
+	flag, alreadythere := m[name] // BUG
+	if !alreadythere {
+		if name == "help" || name == "h" { // special case for nice help message.
+			f.usage()
+			return false, ErrHelp
+		}
+		return false, f.failf("flag provided but not defined: -%s", name)
+	}
+	if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
+		if has_value {
+			if err := fv.Set(value); err != nil {
+				return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err)
+			}
+		} else {
+			fv.Set("true")
+		}
+	} else {
+		// It must have a value, which might be the next argument.
+		if !has_value && len(f.args) > 0 {
+			// value is the next arg
+			has_value = true
+			value, f.args = f.args[0], f.args[1:]
+		}
+		if !has_value {
+			return false, f.failf("flag needs an argument: -%s", name)
+		}
+		if err := flag.Value.Set(value); err != nil {
+			return false, f.failf("invalid value %q for flag -%s: %v", value, name, err)
+		}
+	}
+	if f.actual == nil {
+		f.actual = make(map[string]*Flag)
+	}
+	f.actual[name] = flag
+	return true, nil
+}
+
+// Parse parses flag definitions from the argument list, which should not
+// include the command name.  Must be called after all flags in the FlagSet
+// are defined and before flags are accessed by the program.
+// The return value will be ErrHelp if -help was set but not defined.
+func (f *FlagSet) Parse(arguments []string) error {
+	f.parsed = true
+	f.args = arguments
+	for {
+		seen, err := f.parseOne()
+		if seen {
+			continue
+		}
+		if err == nil {
+			break
+		}
+		switch f.errorHandling {
+		case ContinueOnError:
+			return err
+		case ExitOnError:
+			os.Exit(2)
+		case PanicOnError:
+			panic(err)
+		}
+	}
+	return nil
+}
+
+// Parsed reports whether f.Parse has been called.
+func (f *FlagSet) Parsed() bool {
+	return f.parsed
+}
+
+// Parse parses the command-line flags from os.Args[1:].  Must be called
+// after all flags are defined and before flags are accessed by the program.
+func Parse() {
+	// Ignore errors; CommandLine is set for ExitOnError.
+	CommandLine.Parse(os.Args[1:])
+}
+
+// Parsed returns true if the command-line flags have been parsed.
+func Parsed() bool {
+	return CommandLine.Parsed()
+}
+
+// CommandLine is the default set of command-line flags, parsed from os.Args.
+// The top-level functions such as BoolVar, Arg, and on are wrappers for the
+// methods of CommandLine.
+var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
+
+// NewFlagSet returns a new, empty flag set with the specified name and
+// error handling property.
+func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
+	f := &FlagSet{
+		name:          name,
+		errorHandling: errorHandling,
+	}
+	return f
+}
+
+// Init sets the name and error handling property for a flag set.
+// By default, the zero FlagSet uses an empty name and the
+// ContinueOnError error handling policy.
+func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
+	f.name = name
+	f.errorHandling = errorHandling
+}
diff --git a/third_party/gofrontend/libgo/go/flag/flag_test.go b/third_party/gofrontend/libgo/go/flag/flag_test.go
new file mode 100644
index 0000000..2c03872
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/flag/flag_test.go
@@ -0,0 +1,369 @@
+// 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 flag_test
+
+import (
+	"bytes"
+	. "flag"
+	"fmt"
+	"os"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+)
+
+func boolString(s string) string {
+	if s == "0" {
+		return "false"
+	}
+	return "true"
+}
+
+func TestEverything(t *testing.T) {
+	ResetForTesting(nil)
+	Bool("test_bool", false, "bool value")
+	Int("test_int", 0, "int value")
+	Int64("test_int64", 0, "int64 value")
+	Uint("test_uint", 0, "uint value")
+	Uint64("test_uint64", 0, "uint64 value")
+	String("test_string", "0", "string value")
+	Float64("test_float64", 0, "float64 value")
+	Duration("test_duration", 0, "time.Duration value")
+
+	m := make(map[string]*Flag)
+	desired := "0"
+	visitor := func(f *Flag) {
+		if len(f.Name) > 5 && f.Name[0:5] == "test_" {
+			m[f.Name] = f
+			ok := false
+			switch {
+			case f.Value.String() == desired:
+				ok = true
+			case f.Name == "test_bool" && f.Value.String() == boolString(desired):
+				ok = true
+			case f.Name == "test_duration" && f.Value.String() == desired+"s":
+				ok = true
+			}
+			if !ok {
+				t.Error("Visit: bad value", f.Value.String(), "for", f.Name)
+			}
+		}
+	}
+	VisitAll(visitor)
+	if len(m) != 8 {
+		t.Error("VisitAll misses some flags")
+		for k, v := range m {
+			t.Log(k, *v)
+		}
+	}
+	m = make(map[string]*Flag)
+	Visit(visitor)
+	if len(m) != 0 {
+		t.Errorf("Visit sees unset flags")
+		for k, v := range m {
+			t.Log(k, *v)
+		}
+	}
+	// Now set all flags
+	Set("test_bool", "true")
+	Set("test_int", "1")
+	Set("test_int64", "1")
+	Set("test_uint", "1")
+	Set("test_uint64", "1")
+	Set("test_string", "1")
+	Set("test_float64", "1")
+	Set("test_duration", "1s")
+	desired = "1"
+	Visit(visitor)
+	if len(m) != 8 {
+		t.Error("Visit fails after set")
+		for k, v := range m {
+			t.Log(k, *v)
+		}
+	}
+	// Now test they're visited in sort order.
+	var flagNames []string
+	Visit(func(f *Flag) { flagNames = append(flagNames, f.Name) })
+	if !sort.StringsAreSorted(flagNames) {
+		t.Errorf("flag names not sorted: %v", flagNames)
+	}
+}
+
+func TestGet(t *testing.T) {
+	ResetForTesting(nil)
+	Bool("test_bool", true, "bool value")
+	Int("test_int", 1, "int value")
+	Int64("test_int64", 2, "int64 value")
+	Uint("test_uint", 3, "uint value")
+	Uint64("test_uint64", 4, "uint64 value")
+	String("test_string", "5", "string value")
+	Float64("test_float64", 6, "float64 value")
+	Duration("test_duration", 7, "time.Duration value")
+
+	visitor := func(f *Flag) {
+		if len(f.Name) > 5 && f.Name[0:5] == "test_" {
+			g, ok := f.Value.(Getter)
+			if !ok {
+				t.Errorf("Visit: value does not satisfy Getter: %T", f.Value)
+				return
+			}
+			switch f.Name {
+			case "test_bool":
+				ok = g.Get() == true
+			case "test_int":
+				ok = g.Get() == int(1)
+			case "test_int64":
+				ok = g.Get() == int64(2)
+			case "test_uint":
+				ok = g.Get() == uint(3)
+			case "test_uint64":
+				ok = g.Get() == uint64(4)
+			case "test_string":
+				ok = g.Get() == "5"
+			case "test_float64":
+				ok = g.Get() == float64(6)
+			case "test_duration":
+				ok = g.Get() == time.Duration(7)
+			}
+			if !ok {
+				t.Errorf("Visit: bad value %T(%v) for %s", g.Get(), g.Get(), f.Name)
+			}
+		}
+	}
+	VisitAll(visitor)
+}
+
+func TestUsage(t *testing.T) {
+	called := false
+	ResetForTesting(func() { called = true })
+	if CommandLine.Parse([]string{"-x"}) == nil {
+		t.Error("parse did not fail for unknown flag")
+	}
+	if !called {
+		t.Error("did not call Usage for unknown flag")
+	}
+}
+
+func testParse(f *FlagSet, t *testing.T) {
+	if f.Parsed() {
+		t.Error("f.Parse() = true before Parse")
+	}
+	boolFlag := f.Bool("bool", false, "bool value")
+	bool2Flag := f.Bool("bool2", false, "bool2 value")
+	intFlag := f.Int("int", 0, "int value")
+	int64Flag := f.Int64("int64", 0, "int64 value")
+	uintFlag := f.Uint("uint", 0, "uint value")
+	uint64Flag := f.Uint64("uint64", 0, "uint64 value")
+	stringFlag := f.String("string", "0", "string value")
+	float64Flag := f.Float64("float64", 0, "float64 value")
+	durationFlag := f.Duration("duration", 5*time.Second, "time.Duration value")
+	extra := "one-extra-argument"
+	args := []string{
+		"-bool",
+		"-bool2=true",
+		"--int", "22",
+		"--int64", "0x23",
+		"-uint", "24",
+		"--uint64", "25",
+		"-string", "hello",
+		"-float64", "2718e28",
+		"-duration", "2m",
+		extra,
+	}
+	if err := f.Parse(args); err != nil {
+		t.Fatal(err)
+	}
+	if !f.Parsed() {
+		t.Error("f.Parse() = false after Parse")
+	}
+	if *boolFlag != true {
+		t.Error("bool flag should be true, is ", *boolFlag)
+	}
+	if *bool2Flag != true {
+		t.Error("bool2 flag should be true, is ", *bool2Flag)
+	}
+	if *intFlag != 22 {
+		t.Error("int flag should be 22, is ", *intFlag)
+	}
+	if *int64Flag != 0x23 {
+		t.Error("int64 flag should be 0x23, is ", *int64Flag)
+	}
+	if *uintFlag != 24 {
+		t.Error("uint flag should be 24, is ", *uintFlag)
+	}
+	if *uint64Flag != 25 {
+		t.Error("uint64 flag should be 25, is ", *uint64Flag)
+	}
+	if *stringFlag != "hello" {
+		t.Error("string flag should be `hello`, is ", *stringFlag)
+	}
+	if *float64Flag != 2718e28 {
+		t.Error("float64 flag should be 2718e28, is ", *float64Flag)
+	}
+	if *durationFlag != 2*time.Minute {
+		t.Error("duration flag should be 2m, is ", *durationFlag)
+	}
+	if len(f.Args()) != 1 {
+		t.Error("expected one argument, got", len(f.Args()))
+	} else if f.Args()[0] != extra {
+		t.Errorf("expected argument %q got %q", extra, f.Args()[0])
+	}
+}
+
+func TestParse(t *testing.T) {
+	ResetForTesting(func() { t.Error("bad parse") })
+	testParse(CommandLine, t)
+}
+
+func TestFlagSetParse(t *testing.T) {
+	testParse(NewFlagSet("test", ContinueOnError), t)
+}
+
+// Declare a user-defined flag type.
+type flagVar []string
+
+func (f *flagVar) String() string {
+	return fmt.Sprint([]string(*f))
+}
+
+func (f *flagVar) Set(value string) error {
+	*f = append(*f, value)
+	return nil
+}
+
+func TestUserDefined(t *testing.T) {
+	var flags FlagSet
+	flags.Init("test", ContinueOnError)
+	var v flagVar
+	flags.Var(&v, "v", "usage")
+	if err := flags.Parse([]string{"-v", "1", "-v", "2", "-v=3"}); err != nil {
+		t.Error(err)
+	}
+	if len(v) != 3 {
+		t.Fatal("expected 3 args; got ", len(v))
+	}
+	expect := "[1 2 3]"
+	if v.String() != expect {
+		t.Errorf("expected value %q got %q", expect, v.String())
+	}
+}
+
+// Declare a user-defined boolean flag type.
+type boolFlagVar struct {
+	count int
+}
+
+func (b *boolFlagVar) String() string {
+	return fmt.Sprintf("%d", b.count)
+}
+
+func (b *boolFlagVar) Set(value string) error {
+	if value == "true" {
+		b.count++
+	}
+	return nil
+}
+
+func (b *boolFlagVar) IsBoolFlag() bool {
+	return b.count < 4
+}
+
+func TestUserDefinedBool(t *testing.T) {
+	var flags FlagSet
+	flags.Init("test", ContinueOnError)
+	var b boolFlagVar
+	var err error
+	flags.Var(&b, "b", "usage")
+	if err = flags.Parse([]string{"-b", "-b", "-b", "-b=true", "-b=false", "-b", "barg", "-b"}); err != nil {
+		if b.count < 4 {
+			t.Error(err)
+		}
+	}
+
+	if b.count != 4 {
+		t.Errorf("want: %d; got: %d", 4, b.count)
+	}
+
+	if err == nil {
+		t.Error("expected error; got none")
+	}
+}
+
+func TestSetOutput(t *testing.T) {
+	var flags FlagSet
+	var buf bytes.Buffer
+	flags.SetOutput(&buf)
+	flags.Init("test", ContinueOnError)
+	flags.Parse([]string{"-unknown"})
+	if out := buf.String(); !strings.Contains(out, "-unknown") {
+		t.Logf("expected output mentioning unknown; got %q", out)
+	}
+}
+
+// This tests that one can reset the flags. This still works but not well, and is
+// superseded by FlagSet.
+func TestChangingArgs(t *testing.T) {
+	ResetForTesting(func() { t.Fatal("bad parse") })
+	oldArgs := os.Args
+	defer func() { os.Args = oldArgs }()
+	os.Args = []string{"cmd", "-before", "subcmd", "-after", "args"}
+	before := Bool("before", false, "")
+	if err := CommandLine.Parse(os.Args[1:]); err != nil {
+		t.Fatal(err)
+	}
+	cmd := Arg(0)
+	os.Args = Args()
+	after := Bool("after", false, "")
+	Parse()
+	args := Args()
+
+	if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" {
+		t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args)
+	}
+}
+
+// Test that -help invokes the usage message and returns ErrHelp.
+func TestHelp(t *testing.T) {
+	var helpCalled = false
+	fs := NewFlagSet("help test", ContinueOnError)
+	fs.Usage = func() { helpCalled = true }
+	var flag bool
+	fs.BoolVar(&flag, "flag", false, "regular flag")
+	// Regular flag invocation should work
+	err := fs.Parse([]string{"-flag=true"})
+	if err != nil {
+		t.Fatal("expected no error; got ", err)
+	}
+	if !flag {
+		t.Error("flag was not set by -flag")
+	}
+	if helpCalled {
+		t.Error("help called for regular flag")
+		helpCalled = false // reset for next test
+	}
+	// Help flag should work as expected.
+	err = fs.Parse([]string{"-help"})
+	if err == nil {
+		t.Fatal("error expected")
+	}
+	if err != ErrHelp {
+		t.Fatal("expected ErrHelp; got ", err)
+	}
+	if !helpCalled {
+		t.Fatal("help was not called")
+	}
+	// If we define a help flag, that should override.
+	var help bool
+	fs.BoolVar(&help, "help", false, "help flag")
+	helpCalled = false
+	err = fs.Parse([]string{"-help"})
+	if err != nil {
+		t.Fatal("expected no error for defined -help; got ", err)
+	}
+	if helpCalled {
+		t.Fatal("help was called; should not have been for defined help flag")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/fmt/doc.go b/third_party/gofrontend/libgo/go/fmt/doc.go
new file mode 100644
index 0000000..02642d6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/fmt/doc.go
@@ -0,0 +1,272 @@
+// 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 fmt implements formatted I/O with functions analogous
+	to C's printf and scanf.  The format 'verbs' are derived from C's but
+	are simpler.
+
+
+	Printing
+
+	The verbs:
+
+	General:
+		%v	the value in a default format.
+			when printing structs, the plus flag (%+v) adds field names
+		%#v	a Go-syntax representation of the value
+		%T	a Go-syntax representation of the type of the value
+		%%	a literal percent sign; consumes no value
+
+	Boolean:
+		%t	the word true or false
+	Integer:
+		%b	base 2
+		%c	the character represented by the corresponding Unicode code point
+		%d	base 10
+		%o	base 8
+		%q	a single-quoted character literal safely escaped with Go syntax.
+		%x	base 16, with lower-case letters for a-f
+		%X	base 16, with upper-case letters for A-F
+		%U	Unicode format: U+1234; same as "U+%04X"
+	Floating-point and complex constituents:
+		%b	decimalless scientific notation with exponent a power of two,
+			in the manner of strconv.FormatFloat with the 'b' format,
+			e.g. -123456p-78
+		%e	scientific notation, e.g. -1234.456e+78
+		%E	scientific notation, e.g. -1234.456E+78
+		%f	decimal point but no exponent, e.g. 123.456
+		%F	synonym for %f
+		%g	whichever of %e or %f produces more compact output
+		%G	whichever of %E or %f produces more compact output
+	String and slice of bytes:
+		%s	the uninterpreted bytes of the string or slice
+		%q	a double-quoted string safely escaped with Go syntax
+		%x	base 16, lower-case, two characters per byte
+		%X	base 16, upper-case, two characters per byte
+	Pointer:
+		%p	base 16 notation, with leading 0x
+
+	There is no 'u' flag.  Integers are printed unsigned if they have unsigned type.
+	Similarly, there is no need to specify the size of the operand (int8, int64).
+
+	Width is specified by an optional decimal number immediately following the verb.
+	If absent, the width is whatever is necessary to represent the value.
+	Precision is specified after the (optional) width by a period followed by a
+	decimal number. If no period is present, a default precision is used.
+	A period with no following number specifies a precision of zero.
+	Examples:
+		%f:    default width, default precision
+		%9f    width 9, default precision
+		%.2f   default width, precision 2
+		%9.2f  width 9, precision 2
+		%9.f   width 9, precision 0
+
+	Width and precision are measured in units of Unicode code points.
+	(This differs from C's printf where the units are numbers
+	of bytes.) Either or both of the flags may be replaced with the
+	character '*', causing their values to be obtained from the next
+	operand, which must be of type int.
+
+	For most values, width is the minimum number of characters to output,
+	padding the formatted form with spaces if necessary.
+	For strings, precision is the maximum number of characters to output,
+	truncating if necessary.
+
+	For floating-point values, width sets the minimum width of the field and
+	precision sets the number of places after the decimal, if appropriate,
+	except that for %g/%G it sets the total number of digits. For example,
+	given 123.45 the format %6.2f prints 123.45 while %.4g prints 123.5.
+	The default precision for %e and %f is 6; for %g it is the smallest
+	number of digits necessary to identify the value uniquely.
+
+	For complex numbers, the width and precision apply to the two
+	components independently and the result is parenthesized, so %f applied
+	to 1.2+3.4i produces (1.200000+3.400000i).
+
+	Other flags:
+		+	always print a sign for numeric values;
+			guarantee ASCII-only output for %q (%+q)
+		-	pad with spaces on the right rather than the left (left-justify the field)
+		#	alternate format: add leading 0 for octal (%#o), 0x for hex (%#x);
+			0X for hex (%#X); suppress 0x for %p (%#p);
+			for %q, print a raw (backquoted) string if strconv.CanBackquote
+			returns true;
+			write e.g. U+0078 'x' if the character is printable for %U (%#U).
+		' '	(space) leave a space for elided sign in numbers (% d);
+			put spaces between bytes printing strings or slices in hex (% x, % X)
+		0	pad with leading zeros rather than spaces;
+			for numbers, this moves the padding after the sign
+
+	Flags are ignored by verbs that do not expect them.
+	For example there is no alternate decimal format, so %#d and %d
+	behave identically.
+
+	For each Printf-like function, there is also a Print function
+	that takes no format and is equivalent to saying %v for every
+	operand.  Another variant Println inserts blanks between
+	operands and appends a newline.
+
+	Regardless of the verb, if an operand is an interface value,
+	the internal concrete value is used, not the interface itself.
+	Thus:
+		var i interface{} = 23
+		fmt.Printf("%v\n", i)
+	will print 23.
+
+	Except when printed using the verbs %T and %p, special
+	formatting considerations apply for operands that implement
+	certain interfaces. In order of application:
+
+	1. If an operand implements the Formatter interface, it will
+	be invoked. Formatter provides fine control of formatting.
+
+	2. If the %v verb is used with the # flag (%#v) and the operand
+	implements the GoStringer interface, that will be invoked.
+
+	If the format (which is implicitly %v for Println etc.) is valid
+	for a string (%s %q %v %x %X), the following two rules apply:
+
+	3. If an operand implements the error interface, the Error method
+	will be invoked to convert the object to a string, which will then
+	be formatted as required by the verb (if any).
+
+	4. If an operand implements method String() string, that method
+	will be invoked to convert the object to a string, which will then
+	be formatted as required by the verb (if any).
+
+	For compound operands such as slices and structs, the format
+	applies to the elements of each operand, recursively, not to the
+	operand as a whole. Thus %q will quote each element of a slice
+	of strings, and %6.2f will control formatting for each element
+	of a floating-point array.
+
+	To avoid recursion in cases such as
+		type X string
+		func (x X) String() string { return Sprintf("<%s>", x) }
+	convert the value before recurring:
+		func (x X) String() string { return Sprintf("<%s>", string(x)) }
+
+	Explicit argument indexes:
+
+	In Printf, Sprintf, and Fprintf, the default behavior is for each
+	formatting verb to format successive arguments passed in the call.
+	However, the notation [n] immediately before the verb indicates that the
+	nth one-indexed argument is to be formatted instead. The same notation
+	before a '*' for a width or precision selects the argument index holding
+	the value. After processing a bracketed expression [n], arguments n+1,
+	n+2, etc. will be processed unless otherwise directed.
+
+	For example,
+		fmt.Sprintf("%[2]d %[1]d\n", 11, 22)
+	will yield "22, 11", while
+		fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6),
+	equivalent to
+		fmt.Sprintf("%6.2f", 12.0),
+	will yield " 12.00". Because an explicit index affects subsequent verbs,
+	this notation can be used to print the same values multiple times
+	by resetting the index for the first argument to be repeated:
+		fmt.Sprintf("%d %d %#[1]x %#x", 16, 17)
+	will yield "16 17 0x10 0x11".
+
+	Format errors:
+
+	If an invalid argument is given for a verb, such as providing
+	a string to %d, the generated string will contain a
+	description of the problem, as in these examples:
+
+		Wrong type or unknown verb: %!verb(type=value)
+			Printf("%d", hi):          %!d(string=hi)
+		Too many arguments: %!(EXTRA type=value)
+			Printf("hi", "guys"):      hi%!(EXTRA string=guys)
+		Too few arguments: %!verb(MISSING)
+			Printf("hi%d"):            hi %!d(MISSING)
+		Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC)
+			Printf("%*s", 4.5, "hi"):  %!(BADWIDTH)hi
+			Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi
+		Invalid or invalid use of argument index: %!(BADINDEX)
+			Printf("%*[2]d", 7):       %!d(BADINDEX)
+			Printf("%.[2]d", 7):       %!d(BADINDEX)
+
+	All errors begin with the string "%!" followed sometimes
+	by a single character (the verb) and end with a parenthesized
+	description.
+
+	If an Error or String method triggers a panic when called by a
+	print routine, the fmt package reformats the error message
+	from the panic, decorating it with an indication that it came
+	through the fmt package.  For example, if a String method
+	calls panic("bad"), the resulting formatted message will look
+	like
+		%!s(PANIC=bad)
+
+	The %!s just shows the print verb in use when the failure
+	occurred.
+
+	Scanning
+
+	An analogous set of functions scans formatted text to yield
+	values.  Scan, Scanf and Scanln read from os.Stdin; Fscan,
+	Fscanf and Fscanln read from a specified io.Reader; Sscan,
+	Sscanf and Sscanln read from an argument string.  Scanln,
+	Fscanln and Sscanln stop scanning at a newline and require that
+	the items be followed by one; Scanf, Fscanf and Sscanf require
+	newlines in the input to match newlines in the format; the other
+	routines treat newlines as spaces.
+
+	Scanf, Fscanf, and Sscanf parse the arguments according to a
+	format string, analogous to that of Printf.  For example, %x
+	will scan an integer as a hexadecimal number, and %v will scan
+	the default representation format for the value.
+
+	The formats behave analogously to those of Printf with the
+	following exceptions:
+
+		%p is not implemented
+		%T is not implemented
+		%e %E %f %F %g %G are all equivalent and scan any floating point or complex value
+		%s and %v on strings scan a space-delimited token
+		Flags # and + are not implemented.
+
+	The familiar base-setting prefixes 0 (octal) and 0x
+	(hexadecimal) are accepted when scanning integers without a
+	format or with the %v verb.
+
+	Width is interpreted in the input text (%5s means at most
+	five runes of input will be read to scan a string) but there
+	is no syntax for scanning with a precision (no %5.2f, just
+	%5f).
+
+	When scanning with a format, all non-empty runs of space
+	characters (except newline) are equivalent to a single
+	space in both the format and the input.  With that proviso,
+	text in the format string must match the input text; scanning
+	stops if it does not, with the return value of the function
+	indicating the number of arguments scanned.
+
+	In all the scanning functions, a carriage return followed
+	immediately by a newline is treated as a plain newline
+	(\r\n means the same as \n).
+
+	In all the scanning functions, if an operand implements method
+	Scan (that is, it implements the Scanner interface) that
+	method will be used to scan the text for that operand.  Also,
+	if the number of arguments scanned is less than the number of
+	arguments provided, an error is returned.
+
+	All arguments to be scanned must be either pointers to basic
+	types or implementations of the Scanner interface.
+
+	Note: Fscan etc. can read one character (rune) past the input
+	they return, which means that a loop calling a scan routine
+	may skip some of the input.  This is usually a problem only
+	when there is no space between input values.  If the reader
+	provided to Fscan implements ReadRune, that method will be used
+	to read characters.  If the reader also implements UnreadRune,
+	that method will be used to save the character and successive
+	calls will not lose data.  To attach ReadRune and UnreadRune
+	methods to a reader without that capability, use
+	bufio.NewReader.
+*/
+package fmt
diff --git a/third_party/gofrontend/libgo/go/fmt/export_test.go b/third_party/gofrontend/libgo/go/fmt/export_test.go
new file mode 100644
index 0000000..89d57ee
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/fmt/export_test.go
@@ -0,0 +1,7 @@
+// 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 fmt
+
+var IsSpace = isSpace
diff --git a/third_party/gofrontend/libgo/go/fmt/fmt_test.go b/third_party/gofrontend/libgo/go/fmt/fmt_test.go
new file mode 100644
index 0000000..8e69231
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/fmt/fmt_test.go
@@ -0,0 +1,1149 @@
+// 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 fmt_test
+
+import (
+	"bytes"
+	. "fmt"
+	"io"
+	"math"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+	"unicode"
+)
+
+type (
+	renamedBool       bool
+	renamedInt        int
+	renamedInt8       int8
+	renamedInt16      int16
+	renamedInt32      int32
+	renamedInt64      int64
+	renamedUint       uint
+	renamedUint8      uint8
+	renamedUint16     uint16
+	renamedUint32     uint32
+	renamedUint64     uint64
+	renamedUintptr    uintptr
+	renamedString     string
+	renamedBytes      []byte
+	renamedFloat32    float32
+	renamedFloat64    float64
+	renamedComplex64  complex64
+	renamedComplex128 complex128
+)
+
+func TestFmtInterface(t *testing.T) {
+	var i1 interface{}
+	i1 = "abc"
+	s := Sprintf("%s", i1)
+	if s != "abc" {
+		t.Errorf(`Sprintf("%%s", empty("abc")) = %q want %q`, s, "abc")
+	}
+}
+
+const b32 uint32 = 1<<32 - 1
+const b64 uint64 = 1<<64 - 1
+
+var array = [5]int{1, 2, 3, 4, 5}
+var iarray = [4]interface{}{1, "hello", 2.5, nil}
+var slice = array[:]
+var islice = iarray[:]
+
+type A struct {
+	i int
+	j uint
+	s string
+	x []int
+}
+
+type I int
+
+func (i I) String() string { return Sprintf("<%d>", int(i)) }
+
+type B struct {
+	I I
+	j int
+}
+
+type C struct {
+	i int
+	B
+}
+
+type F int
+
+func (f F) Format(s State, c rune) {
+	Fprintf(s, "<%c=F(%d)>", c, int(f))
+}
+
+type G int
+
+func (g G) GoString() string {
+	return Sprintf("GoString(%d)", int(g))
+}
+
+type S struct {
+	F F // a struct field that Formats
+	G G // a struct field that GoStrings
+}
+
+type SI struct {
+	I interface{}
+}
+
+// P is a type with a String method with pointer receiver for testing %p.
+type P int
+
+var pValue P
+
+func (p *P) String() string {
+	return "String(p)"
+}
+
+var barray = [5]renamedUint8{1, 2, 3, 4, 5}
+var bslice = barray[:]
+
+var b byte
+
+var fmtTests = []struct {
+	fmt string
+	val interface{}
+	out string
+}{
+	{"%d", 12345, "12345"},
+	{"%v", 12345, "12345"},
+	{"%t", true, "true"},
+
+	// basic string
+	{"%s", "abc", "abc"},
+	{"%x", "abc", "616263"},
+	{"%x", "xyz", "78797a"},
+	{"%X", "xyz", "78797A"},
+	{"%q", "abc", `"abc"`},
+
+	// basic bytes
+	{"%s", []byte("abc"), "abc"},
+	{"%x", []byte("abc"), "616263"},
+	{"% x", []byte("abc\xff"), "61 62 63 ff"},
+	{"%#x", []byte("abc\xff"), "0x610x620x630xff"},
+	{"%#X", []byte("abc\xff"), "0X610X620X630XFF"},
+	{"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"},
+	{"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"},
+	{"% X", []byte("abc\xff"), "61 62 63 FF"},
+	{"%x", []byte("xyz"), "78797a"},
+	{"%X", []byte("xyz"), "78797A"},
+	{"%q", []byte("abc"), `"abc"`},
+
+	// escaped strings
+	{"%#q", `abc`, "`abc`"},
+	{"%#q", `"`, "`\"`"},
+	{"1 %#q", `\n`, "1 `\\n`"},
+	{"2 %#q", "\n", `2 "\n"`},
+	{"%q", `"`, `"\""`},
+	{"%q", "\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`},
+	{"%q", "abc\xffdef", `"abc\xffdef"`},
+	{"%q", "\u263a", `"☺"`},
+	{"%+q", "\u263a", `"\u263a"`},
+	{"%q", "\U0010ffff", `"\U0010ffff"`},
+
+	// escaped characters
+	{"%q", 'x', `'x'`},
+	{"%q", 0, `'\x00'`},
+	{"%q", '\n', `'\n'`},
+	{"%q", '\u0e00', `'\u0e00'`},         // not a printable rune.
+	{"%q", '\U000c2345', `'\U000c2345'`}, // not a printable rune.
+	{"%q", int64(0x7FFFFFFF), `%!q(int64=2147483647)`},
+	{"%q", uint64(0xFFFFFFFF), `%!q(uint64=4294967295)`},
+	{"%q", '"', `'"'`},
+	{"%q", '\'', `'\''`},
+	{"%q", "\u263a", `"☺"`},
+	{"%+q", "\u263a", `"\u263a"`},
+
+	// width
+	{"%5s", "abc", "  abc"},
+	{"%2s", "\u263a", " ☺"},
+	{"%-5s", "abc", "abc  "},
+	{"%-8q", "abc", `"abc"   `},
+	{"%05s", "abc", "00abc"},
+	{"%08q", "abc", `000"abc"`},
+	{"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"},
+	{"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"},
+	{"%.5s", "日本語日本語", "日本語日本"},
+	{"%.5s", []byte("日本語日本語"), "日本語日本"},
+	{"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
+	{"%.3q", "日本語日本語", `"日本語"`},
+	{"%.3q", []byte("日本語日本語"), `"日本語"`},
+	{"%10.1q", "日本語日本語", `       "日"`},
+	{"%10v", nil, "     <nil>"},
+	{"%-10v", nil, "<nil>     "},
+
+	// integers
+	{"%d", 12345, "12345"},
+	{"%d", -12345, "-12345"},
+	{"%10d", 12345, "     12345"},
+	{"%10d", -12345, "    -12345"},
+	{"%+10d", 12345, "    +12345"},
+	{"%010d", 12345, "0000012345"},
+	{"%010d", -12345, "-000012345"},
+	{"%-10d", 12345, "12345     "},
+	{"%010.3d", 1, "       001"},
+	{"%010.3d", -1, "      -001"},
+	{"%+d", 12345, "+12345"},
+	{"%+d", -12345, "-12345"},
+	{"%+d", 0, "+0"},
+	{"% d", 0, " 0"},
+	{"% d", 12345, " 12345"},
+	{"%.0d", 0, ""},
+	{"%.d", 0, ""},
+
+	// unicode format
+	{"%U", 0x1, "U+0001"},
+	{"%U", uint(0x1), "U+0001"},
+	{"%.8U", 0x2, "U+00000002"},
+	{"%U", 0x1234, "U+1234"},
+	{"%U", 0x12345, "U+12345"},
+	{"%10.6U", 0xABC, "  U+000ABC"},
+	{"%-10.6U", 0xABC, "U+000ABC  "},
+	{"%U", '\n', `U+000A`},
+	{"%#U", '\n', `U+000A`},
+	{"%U", 'x', `U+0078`},
+	{"%#U", 'x', `U+0078 'x'`},
+	{"%U", '\u263a', `U+263A`},
+	{"%#U", '\u263a', `U+263A '☺'`},
+
+	// floats
+	{"%+.3e", 0.0, "+0.000e+00"},
+	{"%+.3e", 1.0, "+1.000e+00"},
+	{"%+.3f", -1.0, "-1.000"},
+	{"%+.3F", -1.0, "-1.000"},
+	{"%+.3F", float32(-1.0), "-1.000"},
+	{"%+07.2f", 1.0, "+001.00"},
+	{"%+07.2f", -1.0, "-001.00"},
+	{"%+10.2f", +1.0, "     +1.00"},
+	{"%+10.2f", -1.0, "     -1.00"},
+	{"% .3E", -1.0, "-1.000E+00"},
+	{"% .3e", 1.0, " 1.000e+00"},
+	{"%+.3g", 0.0, "+0"},
+	{"%+.3g", 1.0, "+1"},
+	{"%+.3g", -1.0, "-1"},
+	{"% .3g", -1.0, "-1"},
+	{"% .3g", 1.0, " 1"},
+	{"%b", float32(1.0), "8388608p-23"},
+	{"%b", 1.0, "4503599627370496p-52"},
+
+	// complex values
+	{"%+.3e", 0i, "(+0.000e+00+0.000e+00i)"},
+	{"%+.3f", 0i, "(+0.000+0.000i)"},
+	{"%+.3g", 0i, "(+0+0i)"},
+	{"%+.3e", 1 + 2i, "(+1.000e+00+2.000e+00i)"},
+	{"%+.3f", 1 + 2i, "(+1.000+2.000i)"},
+	{"%+.3g", 1 + 2i, "(+1+2i)"},
+	{"%.3e", 0i, "(0.000e+00+0.000e+00i)"},
+	{"%.3f", 0i, "(0.000+0.000i)"},
+	{"%.3F", 0i, "(0.000+0.000i)"},
+	{"%.3F", complex64(0i), "(0.000+0.000i)"},
+	{"%.3g", 0i, "(0+0i)"},
+	{"%.3e", 1 + 2i, "(1.000e+00+2.000e+00i)"},
+	{"%.3f", 1 + 2i, "(1.000+2.000i)"},
+	{"%.3g", 1 + 2i, "(1+2i)"},
+	{"%.3e", -1 - 2i, "(-1.000e+00-2.000e+00i)"},
+	{"%.3f", -1 - 2i, "(-1.000-2.000i)"},
+	{"%.3g", -1 - 2i, "(-1-2i)"},
+	{"% .3E", -1 - 2i, "(-1.000E+00-2.000E+00i)"},
+	{"%+.3g", complex64(1 + 2i), "(+1+2i)"},
+	{"%+.3g", complex128(1 + 2i), "(+1+2i)"},
+	{"%b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"},
+	{"%b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"},
+
+	// erroneous formats
+	{"", 2, "%!(EXTRA int=2)"},
+	{"%d", "hello", "%!d(string=hello)"},
+
+	// old test/fmt_test.go
+	{"%d", 1234, "1234"},
+	{"%d", -1234, "-1234"},
+	{"%d", uint(1234), "1234"},
+	{"%d", uint32(b32), "4294967295"},
+	{"%d", uint64(b64), "18446744073709551615"},
+	{"%o", 01234, "1234"},
+	{"%#o", 01234, "01234"},
+	{"%o", uint32(b32), "37777777777"},
+	{"%o", uint64(b64), "1777777777777777777777"},
+	{"%x", 0x1234abcd, "1234abcd"},
+	{"%#x", 0x1234abcd, "0x1234abcd"},
+	{"%x", b32 - 0x1234567, "fedcba98"},
+	{"%X", 0x1234abcd, "1234ABCD"},
+	{"%X", b32 - 0x1234567, "FEDCBA98"},
+	{"%#X", 0, "0X0"},
+	{"%x", b64, "ffffffffffffffff"},
+	{"%b", 7, "111"},
+	{"%b", b64, "1111111111111111111111111111111111111111111111111111111111111111"},
+	{"%b", -6, "-110"},
+	{"%e", 1.0, "1.000000e+00"},
+	{"%e", 1234.5678e3, "1.234568e+06"},
+	{"%e", 1234.5678e-8, "1.234568e-05"},
+	{"%e", -7.0, "-7.000000e+00"},
+	{"%e", -1e-9, "-1.000000e-09"},
+	{"%f", 1234.5678e3, "1234567.800000"},
+	{"%f", 1234.5678e-8, "0.000012"},
+	{"%f", -7.0, "-7.000000"},
+	{"%f", -1e-9, "-0.000000"},
+	{"%g", 1234.5678e3, "1.2345678e+06"},
+	{"%g", float32(1234.5678e3), "1.2345678e+06"},
+	{"%g", 1234.5678e-8, "1.2345678e-05"},
+	{"%g", -7.0, "-7"},
+	{"%g", -1e-9, "-1e-09"},
+	{"%g", float32(-1e-9), "-1e-09"},
+	{"%E", 1.0, "1.000000E+00"},
+	{"%E", 1234.5678e3, "1.234568E+06"},
+	{"%E", 1234.5678e-8, "1.234568E-05"},
+	{"%E", -7.0, "-7.000000E+00"},
+	{"%E", -1e-9, "-1.000000E-09"},
+	{"%G", 1234.5678e3, "1.2345678E+06"},
+	{"%G", float32(1234.5678e3), "1.2345678E+06"},
+	{"%G", 1234.5678e-8, "1.2345678E-05"},
+	{"%G", -7.0, "-7"},
+	{"%G", -1e-9, "-1E-09"},
+	{"%G", float32(-1e-9), "-1E-09"},
+	{"%c", 'x', "x"},
+	{"%c", 0xe4, "ä"},
+	{"%c", 0x672c, "本"},
+	{"%c", '日', "日"},
+	{"%20.8d", 1234, "            00001234"},
+	{"%20.8d", -1234, "           -00001234"},
+	{"%20d", 1234, "                1234"},
+	{"%-20.8d", 1234, "00001234            "},
+	{"%-20.8d", -1234, "-00001234           "},
+	{"%-#20.8x", 0x1234abc, "0x01234abc          "},
+	{"%-#20.8X", 0x1234abc, "0X01234ABC          "},
+	{"%-#20.8o", 01234, "00001234            "},
+	{"%.20b", 7, "00000000000000000111"},
+	{"%20.5s", "qwertyuiop", "               qwert"},
+	{"%.5s", "qwertyuiop", "qwert"},
+	{"%-20.5s", "qwertyuiop", "qwert               "},
+	{"%20c", 'x', "                   x"},
+	{"%-20c", 'x', "x                   "},
+	{"%20.6e", 1.2345e3, "        1.234500e+03"},
+	{"%20.6e", 1.2345e-3, "        1.234500e-03"},
+	{"%20e", 1.2345e3, "        1.234500e+03"},
+	{"%20e", 1.2345e-3, "        1.234500e-03"},
+	{"%20.8e", 1.2345e3, "      1.23450000e+03"},
+	{"%20f", 1.23456789e3, "         1234.567890"},
+	{"%20f", 1.23456789e-3, "            0.001235"},
+	{"%20f", 12345678901.23456789, "  12345678901.234568"},
+	{"%-20f", 1.23456789e3, "1234.567890         "},
+	{"%20.8f", 1.23456789e3, "       1234.56789000"},
+	{"%20.8f", 1.23456789e-3, "          0.00123457"},
+	{"%g", 1.23456789e3, "1234.56789"},
+	{"%g", 1.23456789e-3, "0.00123456789"},
+	{"%g", 1.23456789e20, "1.23456789e+20"},
+	{"%20e", math.Inf(1), "                +Inf"},
+	{"%-20f", math.Inf(-1), "-Inf                "},
+	{"%20g", math.NaN(), "                 NaN"},
+
+	// arrays
+	{"%v", array, "[1 2 3 4 5]"},
+	{"%v", iarray, "[1 hello 2.5 <nil>]"},
+	{"%v", barray, "[1 2 3 4 5]"},
+	{"%v", &array, "&[1 2 3 4 5]"},
+	{"%v", &iarray, "&[1 hello 2.5 <nil>]"},
+	{"%v", &barray, "&[1 2 3 4 5]"},
+
+	// slices
+	{"%v", slice, "[1 2 3 4 5]"},
+	{"%v", islice, "[1 hello 2.5 <nil>]"},
+	{"%v", bslice, "[1 2 3 4 5]"},
+	{"%v", &slice, "&[1 2 3 4 5]"},
+	{"%v", &islice, "&[1 hello 2.5 <nil>]"},
+	{"%v", &bslice, "&[1 2 3 4 5]"},
+
+	// complexes with %v
+	{"%v", 1 + 2i, "(1+2i)"},
+	{"%v", complex64(1 + 2i), "(1+2i)"},
+	{"%v", complex128(1 + 2i), "(1+2i)"},
+
+	// structs
+	{"%v", A{1, 2, "a", []int{1, 2}}, `{1 2 a [1 2]}`},
+	{"%+v", A{1, 2, "a", []int{1, 2}}, `{i:1 j:2 s:a x:[1 2]}`},
+
+	// +v on structs with Stringable items
+	{"%+v", B{1, 2}, `{I:<1> j:2}`},
+	{"%+v", C{1, B{2, 3}}, `{i:1 B:{I:<2> j:3}}`},
+
+	// other formats on Stringable items
+	{"%s", I(23), `<23>`},
+	{"%q", I(23), `"<23>"`},
+	{"%x", I(23), `3c32333e`},
+	{"%#x", I(23), `0x3c0x320x330x3e`},
+	{"%# x", I(23), `0x3c 0x32 0x33 0x3e`},
+	{"%d", I(23), `23`}, // Stringer applies only to string formats.
+
+	// go syntax
+	{"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`},
+	{"%#v", &b, "(*uint8)(0xPTR)"},
+	{"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"},
+	{"%#v", make(chan int), "(chan int)(0xPTR)"},
+	{"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"},
+	{"%#v", 1000000000, "1000000000"},
+	{"%#v", map[string]int{"a": 1}, `map[string]int{"a":1}`},
+	{"%#v", map[string]B{"a": {1, 2}}, `map[string]fmt_test.B{"a":fmt_test.B{I:1, j:2}}`},
+	{"%#v", []string{"a", "b"}, `[]string{"a", "b"}`},
+	{"%#v", SI{}, `fmt_test.SI{I:interface {}(nil)}`},
+	{"%#v", []int(nil), `[]int(nil)`},
+	{"%#v", []int{}, `[]int{}`},
+	{"%#v", array, `[5]int{1, 2, 3, 4, 5}`},
+	{"%#v", &array, `&[5]int{1, 2, 3, 4, 5}`},
+	{"%#v", iarray, `[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
+	{"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
+	{"%#v", map[int]byte(nil), `map[int]uint8(nil)`},
+	{"%#v", map[int]byte{}, `map[int]uint8{}`},
+	{"%#v", "foo", `"foo"`},
+	{"%#v", barray, `[5]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`},
+	{"%#v", bslice, `[]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`},
+	{"%#v", []byte(nil), "[]byte(nil)"},
+	{"%#v", []int32(nil), "[]int32(nil)"},
+
+	// slices with other formats
+	{"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`},
+	{"%x", []int{1, 2, 15}, `[1 2 f]`},
+	{"%d", []int{1, 2, 15}, `[1 2 15]`},
+	{"%d", []byte{1, 2, 15}, `[1 2 15]`},
+	{"%q", []string{"a", "b"}, `["a" "b"]`},
+
+	// renamings
+	{"%v", renamedBool(true), "true"},
+	{"%d", renamedBool(true), "%!d(fmt_test.renamedBool=true)"},
+	{"%o", renamedInt(8), "10"},
+	{"%d", renamedInt8(-9), "-9"},
+	{"%v", renamedInt16(10), "10"},
+	{"%v", renamedInt32(-11), "-11"},
+	{"%X", renamedInt64(255), "FF"},
+	{"%v", renamedUint(13), "13"},
+	{"%o", renamedUint8(14), "16"},
+	{"%X", renamedUint16(15), "F"},
+	{"%d", renamedUint32(16), "16"},
+	{"%X", renamedUint64(17), "11"},
+	{"%o", renamedUintptr(18), "22"},
+	{"%x", renamedString("thing"), "7468696e67"},
+	{"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`},
+	{"%q", renamedBytes([]byte("hello")), `"hello"`},
+	{"%x", []renamedUint8{'a', 'b', 'c'}, "616263"},
+	{"%s", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "hello"},
+	{"%q", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, `"hello"`},
+	{"%v", renamedFloat32(22), "22"},
+	{"%v", renamedFloat64(33), "33"},
+	{"%v", renamedComplex64(3 + 4i), "(3+4i)"},
+	{"%v", renamedComplex128(4 - 3i), "(4-3i)"},
+
+	// Formatter
+	{"%x", F(1), "<x=F(1)>"},
+	{"%x", G(2), "2"},
+	{"%+v", S{F(4), G(5)}, "{F:<v=F(4)> G:5}"},
+
+	// GoStringer
+	{"%#v", G(6), "GoString(6)"},
+	{"%#v", S{F(7), G(8)}, "fmt_test.S{F:<v=F(7)>, G:GoString(8)}"},
+
+	// %T
+	{"%T", (4 - 3i), "complex128"},
+	{"%T", renamedComplex128(4 - 3i), "fmt_test.renamedComplex128"},
+	{"%T", intVal, "int"},
+	{"%6T", &intVal, "  *int"},
+	{"%10T", nil, "     <nil>"},
+	{"%-10T", nil, "<nil>     "},
+
+	// %p
+	{"p0=%p", new(int), "p0=0xPTR"},
+	{"p1=%s", &pValue, "p1=String(p)"}, // String method...
+	{"p2=%p", &pValue, "p2=0xPTR"},     // ... not called with %p
+	{"p3=%p", (*int)(nil), "p3=0x0"},
+	{"p4=%#p", new(int), "p4=PTR"},
+
+	// %p on non-pointers
+	{"%p", make(chan int), "0xPTR"},
+	{"%p", make(map[int]int), "0xPTR"},
+	{"%p", make([]int, 1), "0xPTR"},
+	{"%p", 27, "%!p(int=27)"}, // not a pointer at all
+
+	// %q on pointers
+	{"%q", (*int)(nil), "%!q(*int=<nil>)"},
+	{"%q", new(int), "%!q(*int=0xPTR)"},
+
+	// %v on pointers formats 0 as <nil>
+	{"%v", (*int)(nil), "<nil>"},
+	{"%v", new(int), "0xPTR"},
+
+	// %d etc. pointers use specified base.
+	{"%d", new(int), "PTR_d"},
+	{"%o", new(int), "PTR_o"},
+	{"%x", new(int), "PTR_x"},
+
+	// %d on Stringer should give integer if possible
+	{"%s", time.Time{}.Month(), "January"},
+	{"%d", time.Time{}.Month(), "1"},
+
+	// erroneous things
+	{"%s %", "hello", "hello %!(NOVERB)"},
+	{"%s %.2", "hello", "hello %!(NOVERB)"},
+	{"%d", "hello", "%!d(string=hello)"},
+	{"no args", "hello", "no args%!(EXTRA string=hello)"},
+	{"%s", nil, "%!s(<nil>)"},
+	{"%T", nil, "<nil>"},
+	{"%-1", 100, "%!(NOVERB)%!(EXTRA int=100)"},
+
+	// The "<nil>" show up because maps are printed by
+	// first obtaining a list of keys and then looking up
+	// each key.  Since NaNs can be map keys but cannot
+	// be fetched directly, the lookup fails and returns a
+	// zero reflect.Value, which formats as <nil>.
+	// This test is just to check that it shows the two NaNs at all.
+	{"%v", map[float64]int{math.NaN(): 1, math.NaN(): 2}, "map[NaN:<nil> NaN:<nil>]"},
+
+	// Used to crash because nByte didn't allow for a sign.
+	{"%b", int64(-1 << 63), zeroFill("-1", 63, "")},
+
+	// Used to panic.
+	{"%0100d", 1, zeroFill("", 100, "1")},
+	{"%0100d", -1, zeroFill("-", 99, "1")},
+	{"%0.100f", 1.0, zeroFill("1.", 100, "")},
+	{"%0.100f", -1.0, zeroFill("-1.", 100, "")},
+
+	// Comparison of padding rules with C printf.
+	/*
+		C program:
+		#include <stdio.h>
+
+		char *format[] = {
+			"[%.2f]",
+			"[% .2f]",
+			"[%+.2f]",
+			"[%7.2f]",
+			"[% 7.2f]",
+			"[%+7.2f]",
+			"[%07.2f]",
+			"[% 07.2f]",
+			"[%+07.2f]",
+		};
+
+		int main(void) {
+			int i;
+			for(i = 0; i < 9; i++) {
+				printf("%s: ", format[i]);
+				printf(format[i], 1.0);
+				printf(" ");
+				printf(format[i], -1.0);
+				printf("\n");
+			}
+		}
+
+		Output:
+			[%.2f]: [1.00] [-1.00]
+			[% .2f]: [ 1.00] [-1.00]
+			[%+.2f]: [+1.00] [-1.00]
+			[%7.2f]: [   1.00] [  -1.00]
+			[% 7.2f]: [   1.00] [  -1.00]
+			[%+7.2f]: [  +1.00] [  -1.00]
+			[%07.2f]: [0001.00] [-001.00]
+			[% 07.2f]: [ 001.00] [-001.00]
+			[%+07.2f]: [+001.00] [-001.00]
+	*/
+	{"%.2f", 1.0, "1.00"},
+	{"%.2f", -1.0, "-1.00"},
+	{"% .2f", 1.0, " 1.00"},
+	{"% .2f", -1.0, "-1.00"},
+	{"%+.2f", 1.0, "+1.00"},
+	{"%+.2f", -1.0, "-1.00"},
+	{"%7.2f", 1.0, "   1.00"},
+	{"%7.2f", -1.0, "  -1.00"},
+	{"% 7.2f", 1.0, "   1.00"},
+	{"% 7.2f", -1.0, "  -1.00"},
+	{"%+7.2f", 1.0, "  +1.00"},
+	{"%+7.2f", -1.0, "  -1.00"},
+	{"%07.2f", 1.0, "0001.00"},
+	{"%07.2f", -1.0, "-001.00"},
+	{"% 07.2f", 1.0, " 001.00"},
+	{"% 07.2f", -1.0, "-001.00"},
+	{"%+07.2f", 1.0, "+001.00"},
+	{"%+07.2f", -1.0, "-001.00"},
+
+	// Complex numbers: exhaustively tested in TestComplexFormatting.
+	{"%7.2f", 1 + 2i, "(   1.00  +2.00i)"},
+	{"%+07.2f", -1 - 2i, "(-001.00-002.00i)"},
+	// Zero padding does not apply to infinities.
+	{"%020f", math.Inf(-1), "                -Inf"},
+	{"%020f", math.Inf(+1), "                +Inf"},
+	{"% 020f", math.Inf(-1), "                -Inf"},
+	{"% 020f", math.Inf(+1), "                 Inf"},
+	{"%+020f", math.Inf(-1), "                -Inf"},
+	{"%+020f", math.Inf(+1), "                +Inf"},
+	{"%20f", -1.0, "           -1.000000"},
+	// Make sure we can handle very large widths.
+	{"%0100f", -1.0, zeroFill("-", 99, "1.000000")},
+
+	// Complex fmt used to leave the plus flag set for future entries in the array
+	// causing +2+0i and +3+0i instead of 2+0i and 3+0i.
+	{"%v", []complex64{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"},
+	{"%v", []complex128{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"},
+
+	// Incomplete format specification caused crash.
+	{"%.", 3, "%!.(int=3)"},
+
+	// Used to panic with out-of-bounds for very large numeric representations.
+	// nByte is set to handle one bit per uint64 in %b format, with a negative number.
+	// See issue 6777.
+	{"%#064x", 1, zeroFill("0x", 64, "1")},
+	{"%#064x", -1, zeroFill("-0x", 63, "1")},
+	{"%#064b", 1, zeroFill("", 64, "1")},
+	{"%#064b", -1, zeroFill("-", 63, "1")},
+	{"%#064o", 1, zeroFill("", 64, "1")},
+	{"%#064o", -1, zeroFill("-", 63, "1")},
+	{"%#064d", 1, zeroFill("", 64, "1")},
+	{"%#064d", -1, zeroFill("-", 63, "1")},
+	// Test that we handle the crossover above the size of uint64
+	{"%#072x", 1, zeroFill("0x", 72, "1")},
+	{"%#072x", -1, zeroFill("-0x", 71, "1")},
+	{"%#072b", 1, zeroFill("", 72, "1")},
+	{"%#072b", -1, zeroFill("-", 71, "1")},
+	{"%#072o", 1, zeroFill("", 72, "1")},
+	{"%#072o", -1, zeroFill("-", 71, "1")},
+	{"%#072d", 1, zeroFill("", 72, "1")},
+	{"%#072d", -1, zeroFill("-", 71, "1")},
+
+	// Padding for complex numbers. Has been bad, then fixed, then bad again.
+	{"%+10.2f", +104.66 + 440.51i, "(   +104.66   +440.51i)"},
+	{"%+10.2f", -104.66 + 440.51i, "(   -104.66   +440.51i)"},
+	{"%+10.2f", +104.66 - 440.51i, "(   +104.66   -440.51i)"},
+	{"%+10.2f", -104.66 - 440.51i, "(   -104.66   -440.51i)"},
+	{"%+010.2f", +104.66 + 440.51i, "(+000104.66+000440.51i)"},
+	{"%+010.2f", -104.66 + 440.51i, "(-000104.66+000440.51i)"},
+	{"%+010.2f", +104.66 - 440.51i, "(+000104.66-000440.51i)"},
+	{"%+010.2f", -104.66 - 440.51i, "(-000104.66-000440.51i)"},
+}
+
+// zeroFill generates zero-filled strings of the specified width. The length
+// of the suffix (but not the prefix) is compensated for in the width calculation.
+func zeroFill(prefix string, width int, suffix string) string {
+	return prefix + strings.Repeat("0", width-len(suffix)) + suffix
+}
+
+func TestSprintf(t *testing.T) {
+	for _, tt := range fmtTests {
+		s := Sprintf(tt.fmt, tt.val)
+		if i := strings.Index(tt.out, "PTR"); i >= 0 {
+			pattern := "PTR"
+			chars := "0123456789abcdefABCDEF"
+			switch {
+			case strings.HasPrefix(tt.out[i:], "PTR_d"):
+				pattern = "PTR_d"
+				chars = chars[:10]
+			case strings.HasPrefix(tt.out[i:], "PTR_o"):
+				pattern = "PTR_o"
+				chars = chars[:8]
+			case strings.HasPrefix(tt.out[i:], "PTR_x"):
+				pattern = "PTR_x"
+			}
+			j := i
+			for ; j < len(s); j++ {
+				c := s[j]
+				if !strings.ContainsRune(chars, rune(c)) {
+					break
+				}
+			}
+			s = s[0:i] + pattern + s[j:]
+		}
+		if s != tt.out {
+			if _, ok := tt.val.(string); ok {
+				// Don't requote the already-quoted strings.
+				// It's too confusing to read the errors.
+				t.Errorf("Sprintf(%q, %q) = <%s> want <%s>", tt.fmt, tt.val, s, tt.out)
+			} else {
+				t.Errorf("Sprintf(%q, %v) = %q want %q", tt.fmt, tt.val, s, tt.out)
+			}
+		}
+	}
+}
+
+// TestComplexFormatting checks that a complex always formats to the same
+// thing as if done by hand with two singleton prints.
+func TestComplexFormatting(t *testing.T) {
+	var yesNo = []bool{true, false}
+	var signs = []float64{1, 0, -1}
+	for _, plus := range yesNo {
+		for _, zero := range yesNo {
+			for _, space := range yesNo {
+				for _, char := range "fFeEgG" {
+					realFmt := "%"
+					if zero {
+						realFmt += "0"
+					}
+					if space {
+						realFmt += " "
+					}
+					if plus {
+						realFmt += "+"
+					}
+					realFmt += "10.2"
+					realFmt += string(char)
+					// Imaginary part always has a sign, so force + and ignore space.
+					imagFmt := "%"
+					if zero {
+						imagFmt += "0"
+					}
+					imagFmt += "+"
+					imagFmt += "10.2"
+					imagFmt += string(char)
+					for _, realSign := range signs {
+						for _, imagSign := range signs {
+							one := Sprintf(realFmt, complex(realSign, imagSign))
+							two := Sprintf("("+realFmt+imagFmt+"i)", realSign, imagSign)
+							if one != two {
+								t.Error(f, one, two)
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+type SE []interface{} // slice of empty; notational compactness.
+
+var reorderTests = []struct {
+	fmt string
+	val SE
+	out string
+}{
+	{"%[1]d", SE{1}, "1"},
+	{"%[2]d", SE{2, 1}, "1"},
+	{"%[2]d %[1]d", SE{1, 2}, "2 1"},
+	{"%[2]*[1]d", SE{2, 5}, "    2"},
+	{"%6.2f", SE{12.0}, " 12.00"}, // Explicit version of next line.
+	{"%[3]*.[2]*[1]f", SE{12.0, 2, 6}, " 12.00"},
+	{"%[1]*.[2]*[3]f", SE{6, 2, 12.0}, " 12.00"},
+	{"%10f", SE{12.0}, " 12.000000"},
+	{"%[1]*[3]f", SE{10, 99, 12.0}, " 12.000000"},
+	{"%.6f", SE{12.0}, "12.000000"}, // Explicit version of next line.
+	{"%.[1]*[3]f", SE{6, 99, 12.0}, "12.000000"},
+	{"%6.f", SE{12.0}, "    12"}, //  // Explicit version of next line; empty precision means zero.
+	{"%[1]*.[3]f", SE{6, 3, 12.0}, "    12"},
+	// An actual use! Print the same arguments twice.
+	{"%d %d %d %#[1]o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015"},
+
+	// Erroneous cases.
+	{"%[d", SE{2, 1}, "%!d(BADINDEX)"},
+	{"%]d", SE{2, 1}, "%!](int=2)d%!(EXTRA int=1)"},
+	{"%[]d", SE{2, 1}, "%!d(BADINDEX)"},
+	{"%[-3]d", SE{2, 1}, "%!d(BADINDEX)"},
+	{"%[99]d", SE{2, 1}, "%!d(BADINDEX)"},
+	{"%[3]", SE{2, 1}, "%!(NOVERB)"},
+	{"%[1].2d", SE{5, 6}, "%!d(BADINDEX)"},
+	{"%[1]2d", SE{2, 1}, "%!d(BADINDEX)"},
+	{"%3.[2]d", SE{7}, "%!d(BADINDEX)"},
+	{"%.[2]d", SE{7}, "%!d(BADINDEX)"},
+	{"%d %d %d %#[1]o %#o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015 %!o(MISSING)"},
+	{"%[5]d %[2]d %d", SE{1, 2, 3}, "%!d(BADINDEX) 2 3"},
+	{"%d %[3]d %d", SE{1, 2}, "1 %!d(BADINDEX) 2"}, // Erroneous index does not affect sequence.
+}
+
+func TestReorder(t *testing.T) {
+	for _, tt := range reorderTests {
+		s := Sprintf(tt.fmt, tt.val...)
+		if s != tt.out {
+			t.Errorf("Sprintf(%q, %v) = <%s> want <%s>", tt.fmt, tt.val, s, tt.out)
+		} else {
+		}
+	}
+}
+
+func BenchmarkSprintfEmpty(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			Sprintf("")
+		}
+	})
+}
+
+func BenchmarkSprintfString(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			Sprintf("%s", "hello")
+		}
+	})
+}
+
+func BenchmarkSprintfInt(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			Sprintf("%d", 5)
+		}
+	})
+}
+
+func BenchmarkSprintfIntInt(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			Sprintf("%d %d", 5, 6)
+		}
+	})
+}
+
+func BenchmarkSprintfPrefixedInt(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			Sprintf("This is some meaningless prefix text that needs to be scanned %d", 6)
+		}
+	})
+}
+
+func BenchmarkSprintfFloat(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			Sprintf("%g", 5.23184)
+		}
+	})
+}
+
+func BenchmarkManyArgs(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		var buf bytes.Buffer
+		for pb.Next() {
+			buf.Reset()
+			Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world")
+		}
+	})
+}
+
+var mallocBuf bytes.Buffer
+
+// gccgo numbers are different because gccgo does not have escape
+// analysis yet.
+var mallocTest = []struct {
+	count int
+	desc  string
+	fn    func()
+}{
+	{5, `Sprintf("")`, func() { Sprintf("") }},
+	{5, `Sprintf("xxx")`, func() { Sprintf("xxx") }},
+	{5, `Sprintf("%x")`, func() { Sprintf("%x", 7) }},
+	{5, `Sprintf("%s")`, func() { Sprintf("%s", "hello") }},
+	{5, `Sprintf("%x %x")`, func() { Sprintf("%x %x", 7, 112) }},
+	// For %g we use a float32, not float64, to guarantee passing the argument
+	// does not need to allocate memory to store the result in a pointer-sized word.
+	{20, `Sprintf("%g")`, func() { Sprintf("%g", float32(3.14159)) }},
+	{5, `Fprintf(buf, "%x %x %x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x %x %x", 7, 8, 9) }},
+	{5, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }},
+}
+
+var _ bytes.Buffer
+
+func TestCountMallocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Skip("skipping; GOMAXPROCS>1")
+	}
+	for _, mt := range mallocTest {
+		mallocs := testing.AllocsPerRun(100, mt.fn)
+		if got, max := mallocs, float64(mt.count); got > max {
+			t.Errorf("%s: got %v allocs, want <=%v", mt.desc, got, max)
+		}
+	}
+}
+
+type flagPrinter struct{}
+
+func (*flagPrinter) Format(f State, c rune) {
+	s := "%"
+	for i := 0; i < 128; i++ {
+		if f.Flag(i) {
+			s += string(i)
+		}
+	}
+	if w, ok := f.Width(); ok {
+		s += Sprintf("%d", w)
+	}
+	if p, ok := f.Precision(); ok {
+		s += Sprintf(".%d", p)
+	}
+	s += string(c)
+	io.WriteString(f, "["+s+"]")
+}
+
+var flagtests = []struct {
+	in  string
+	out string
+}{
+	{"%a", "[%a]"},
+	{"%-a", "[%-a]"},
+	{"%+a", "[%+a]"},
+	{"%#a", "[%#a]"},
+	{"% a", "[% a]"},
+	{"%0a", "[%0a]"},
+	{"%1.2a", "[%1.2a]"},
+	{"%-1.2a", "[%-1.2a]"},
+	{"%+1.2a", "[%+1.2a]"},
+	{"%-+1.2a", "[%+-1.2a]"},
+	{"%-+1.2abc", "[%+-1.2a]bc"},
+	{"%-1.2abc", "[%-1.2a]bc"},
+}
+
+func TestFlagParser(t *testing.T) {
+	var flagprinter flagPrinter
+	for _, tt := range flagtests {
+		s := Sprintf(tt.in, &flagprinter)
+		if s != tt.out {
+			t.Errorf("Sprintf(%q, &flagprinter) => %q, want %q", tt.in, s, tt.out)
+		}
+	}
+}
+
+func TestStructPrinter(t *testing.T) {
+	var s struct {
+		a string
+		b string
+		c int
+	}
+	s.a = "abc"
+	s.b = "def"
+	s.c = 123
+	var tests = []struct {
+		fmt string
+		out string
+	}{
+		{"%v", "{abc def 123}"},
+		{"%+v", "{a:abc b:def c:123}"},
+	}
+	for _, tt := range tests {
+		out := Sprintf(tt.fmt, s)
+		if out != tt.out {
+			t.Errorf("Sprintf(%q, &s) = %q, want %q", tt.fmt, out, tt.out)
+		}
+	}
+}
+
+// presentInMap checks map printing using substrings so we don't depend on the
+// print order.
+func presentInMap(s string, a []string, t *testing.T) {
+	for i := 0; i < len(a); i++ {
+		loc := strings.Index(s, a[i])
+		if loc < 0 {
+			t.Errorf("map print: expected to find %q in %q", a[i], s)
+		}
+		// make sure the match ends here
+		loc += len(a[i])
+		if loc >= len(s) || (s[loc] != ' ' && s[loc] != ']') {
+			t.Errorf("map print: %q not properly terminated in %q", a[i], s)
+		}
+	}
+}
+
+func TestMapPrinter(t *testing.T) {
+	m0 := make(map[int]string)
+	s := Sprint(m0)
+	if s != "map[]" {
+		t.Errorf("empty map printed as %q not %q", s, "map[]")
+	}
+	m1 := map[int]string{1: "one", 2: "two", 3: "three"}
+	a := []string{"1:one", "2:two", "3:three"}
+	presentInMap(Sprintf("%v", m1), a, t)
+	presentInMap(Sprint(m1), a, t)
+}
+
+func TestEmptyMap(t *testing.T) {
+	const emptyMapStr = "map[]"
+	var m map[string]int
+	s := Sprint(m)
+	if s != emptyMapStr {
+		t.Errorf("nil map printed as %q not %q", s, emptyMapStr)
+	}
+	m = make(map[string]int)
+	s = Sprint(m)
+	if s != emptyMapStr {
+		t.Errorf("empty map printed as %q not %q", s, emptyMapStr)
+	}
+}
+
+// TestBlank checks that Sprint (and hence Print, Fprint) puts spaces in the
+// right places, that is, between arg pairs in which neither is a string.
+func TestBlank(t *testing.T) {
+	got := Sprint("<", 1, ">:", 1, 2, 3, "!")
+	expect := "<1>:1 2 3!"
+	if got != expect {
+		t.Errorf("got %q expected %q", got, expect)
+	}
+}
+
+// TestBlankln checks that Sprintln (and hence Println, Fprintln) puts spaces in
+// the right places, that is, between all arg pairs.
+func TestBlankln(t *testing.T) {
+	got := Sprintln("<", 1, ">:", 1, 2, 3, "!")
+	expect := "< 1 >: 1 2 3 !\n"
+	if got != expect {
+		t.Errorf("got %q expected %q", got, expect)
+	}
+}
+
+// TestFormatterPrintln checks Formatter with Sprint, Sprintln, Sprintf.
+func TestFormatterPrintln(t *testing.T) {
+	f := F(1)
+	expect := "<v=F(1)>\n"
+	s := Sprint(f, "\n")
+	if s != expect {
+		t.Errorf("Sprint wrong with Formatter: expected %q got %q", expect, s)
+	}
+	s = Sprintln(f)
+	if s != expect {
+		t.Errorf("Sprintln wrong with Formatter: expected %q got %q", expect, s)
+	}
+	s = Sprintf("%v\n", f)
+	if s != expect {
+		t.Errorf("Sprintf wrong with Formatter: expected %q got %q", expect, s)
+	}
+}
+
+func args(a ...interface{}) []interface{} { return a }
+
+var startests = []struct {
+	fmt string
+	in  []interface{}
+	out string
+}{
+	{"%*d", args(4, 42), "  42"},
+	{"%.*d", args(4, 42), "0042"},
+	{"%*.*d", args(8, 4, 42), "    0042"},
+	{"%0*d", args(4, 42), "0042"},
+	{"%-*d", args(4, 42), "42  "},
+
+	// erroneous
+	{"%*d", args(nil, 42), "%!(BADWIDTH)42"},
+	{"%.*d", args(nil, 42), "%!(BADPREC)42"},
+	{"%*d", args(5, "foo"), "%!d(string=  foo)"},
+	{"%*% %d", args(20, 5), "% 5"},
+	{"%*", args(4), "%!(NOVERB)"},
+	{"%*d", args(int32(4), 42), "%!(BADWIDTH)42"},
+}
+
+func TestWidthAndPrecision(t *testing.T) {
+	for _, tt := range startests {
+		s := Sprintf(tt.fmt, tt.in...)
+		if s != tt.out {
+			t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
+		}
+	}
+}
+
+// Panic is a type that panics in String.
+type Panic struct {
+	message interface{}
+}
+
+// Value receiver.
+func (p Panic) GoString() string {
+	panic(p.message)
+}
+
+// Value receiver.
+func (p Panic) String() string {
+	panic(p.message)
+}
+
+// PanicF is a type that panics in Format.
+type PanicF struct {
+	message interface{}
+}
+
+// Value receiver.
+func (p PanicF) Format(f State, c rune) {
+	panic(p.message)
+}
+
+var panictests = []struct {
+	fmt string
+	in  interface{}
+	out string
+}{
+	// String
+	{"%s", (*Panic)(nil), "<nil>"}, // nil pointer special case
+	{"%s", Panic{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"},
+	{"%s", Panic{3}, "%!s(PANIC=3)"},
+	// GoString
+	{"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case
+	{"%#v", Panic{io.ErrUnexpectedEOF}, "%!v(PANIC=unexpected EOF)"},
+	{"%#v", Panic{3}, "%!v(PANIC=3)"},
+	// Format
+	{"%s", (*PanicF)(nil), "<nil>"}, // nil pointer special case
+	{"%s", PanicF{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"},
+	{"%s", PanicF{3}, "%!s(PANIC=3)"},
+}
+
+func TestPanics(t *testing.T) {
+	for _, tt := range panictests {
+		s := Sprintf(tt.fmt, tt.in)
+		if s != tt.out {
+			t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
+		}
+	}
+}
+
+// recurCount tests that erroneous String routine doesn't cause fatal recursion.
+var recurCount = 0
+
+type Recur struct {
+	i      int
+	failed *bool
+}
+
+func (r *Recur) String() string {
+	if recurCount++; recurCount > 10 {
+		*r.failed = true
+		return "FAIL"
+	}
+	// This will call badVerb. Before the fix, that would cause us to recur into
+	// this routine to print %!p(value). Now we don't call the user's method
+	// during an error.
+	return Sprintf("recur@%p value: %d", r, r.i)
+}
+
+func TestBadVerbRecursion(t *testing.T) {
+	failed := false
+	r := &Recur{3, &failed}
+	Sprintf("recur@%p value: %d\n", &r, r.i)
+	if failed {
+		t.Error("fail with pointer")
+	}
+	failed = false
+	r = &Recur{4, &failed}
+	Sprintf("recur@%p, value: %d\n", r, r.i)
+	if failed {
+		t.Error("fail with value")
+	}
+}
+
+func TestIsSpace(t *testing.T) {
+	// This tests the internal isSpace function.
+	// IsSpace = isSpace is defined in export_test.go.
+	for i := rune(0); i <= unicode.MaxRune; i++ {
+		if IsSpace(i) != unicode.IsSpace(i) {
+			t.Errorf("isSpace(%U) = %v, want %v", i, IsSpace(i), unicode.IsSpace(i))
+		}
+	}
+}
+
+func TestNilDoesNotBecomeTyped(t *testing.T) {
+	type A struct{}
+	type B struct{}
+	var a *A = nil
+	var b B = B{}
+	got := Sprintf("%s %s %s %s %s", nil, a, nil, b, nil)
+	const expect = "%!s(<nil>) %!s(*fmt_test.A=<nil>) %!s(<nil>) {} %!s(<nil>)"
+	if got != expect {
+		t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/fmt/format.go b/third_party/gofrontend/libgo/go/fmt/format.go
new file mode 100644
index 0000000..a89c542
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/fmt/format.go
@@ -0,0 +1,492 @@
+// 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 fmt
+
+import (
+	"math"
+	"strconv"
+	"unicode/utf8"
+)
+
+const (
+	// %b of an int64, plus a sign.
+	// Hex can add 0x and we handle it specially.
+	nByte = 65
+
+	ldigits = "0123456789abcdef"
+	udigits = "0123456789ABCDEF"
+)
+
+const (
+	signed   = true
+	unsigned = false
+)
+
+var padZeroBytes = make([]byte, nByte)
+var padSpaceBytes = make([]byte, nByte)
+
+func init() {
+	for i := 0; i < nByte; i++ {
+		padZeroBytes[i] = '0'
+		padSpaceBytes[i] = ' '
+	}
+}
+
+// A fmt is the raw formatter used by Printf etc.
+// It prints into a buffer that must be set up separately.
+type fmt struct {
+	intbuf [nByte]byte
+	buf    *buffer
+	// width, precision
+	wid  int
+	prec int
+	// flags
+	widPresent  bool
+	precPresent bool
+	minus       bool
+	plus        bool
+	sharp       bool
+	space       bool
+	unicode     bool
+	uniQuote    bool // Use 'x'= prefix for %U if printable.
+	zero        bool
+}
+
+func (f *fmt) clearflags() {
+	f.wid = 0
+	f.widPresent = false
+	f.prec = 0
+	f.precPresent = false
+	f.minus = false
+	f.plus = false
+	f.sharp = false
+	f.space = false
+	f.unicode = false
+	f.uniQuote = false
+	f.zero = false
+}
+
+func (f *fmt) init(buf *buffer) {
+	f.buf = buf
+	f.clearflags()
+}
+
+// computePadding computes left and right padding widths (only one will be non-zero).
+func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) {
+	left := !f.minus
+	w := f.wid
+	if w < 0 {
+		left = false
+		w = -w
+	}
+	w -= width
+	if w > 0 {
+		if left && f.zero {
+			return padZeroBytes, w, 0
+		}
+		if left {
+			return padSpaceBytes, w, 0
+		} else {
+			// can't be zero padding on the right
+			return padSpaceBytes, 0, w
+		}
+	}
+	return
+}
+
+// writePadding generates n bytes of padding.
+func (f *fmt) writePadding(n int, padding []byte) {
+	for n > 0 {
+		m := n
+		if m > nByte {
+			m = nByte
+		}
+		f.buf.Write(padding[0:m])
+		n -= m
+	}
+}
+
+// pad appends b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus).
+func (f *fmt) pad(b []byte) {
+	if !f.widPresent || f.wid == 0 {
+		f.buf.Write(b)
+		return
+	}
+	padding, left, right := f.computePadding(len(b))
+	if left > 0 {
+		f.writePadding(left, padding)
+	}
+	f.buf.Write(b)
+	if right > 0 {
+		f.writePadding(right, padding)
+	}
+}
+
+// padString appends s to buf, padded on left (w > 0) or right (w < 0 or f.minus).
+func (f *fmt) padString(s string) {
+	if !f.widPresent || f.wid == 0 {
+		f.buf.WriteString(s)
+		return
+	}
+	padding, left, right := f.computePadding(utf8.RuneCountInString(s))
+	if left > 0 {
+		f.writePadding(left, padding)
+	}
+	f.buf.WriteString(s)
+	if right > 0 {
+		f.writePadding(right, padding)
+	}
+}
+
+var (
+	trueBytes  = []byte("true")
+	falseBytes = []byte("false")
+)
+
+// fmt_boolean formats a boolean.
+func (f *fmt) fmt_boolean(v bool) {
+	if v {
+		f.pad(trueBytes)
+	} else {
+		f.pad(falseBytes)
+	}
+}
+
+// integer; interprets prec but not wid.  Once formatted, result is sent to pad()
+// and then flags are cleared.
+func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
+	// precision of 0 and value of 0 means "print nothing"
+	if f.precPresent && f.prec == 0 && a == 0 {
+		return
+	}
+
+	var buf []byte = f.intbuf[0:]
+	if f.widPresent {
+		width := f.wid
+		if base == 16 && f.sharp {
+			// Also adds "0x".
+			width += 2
+		}
+		if width > nByte {
+			// We're going to need a bigger boat.
+			buf = make([]byte, width)
+		}
+	}
+
+	negative := signedness == signed && a < 0
+	if negative {
+		a = -a
+	}
+
+	// two ways to ask for extra leading zero digits: %.3d or %03d.
+	// apparently the first cancels the second.
+	prec := 0
+	if f.precPresent {
+		prec = f.prec
+		f.zero = false
+	} else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
+		prec = f.wid
+		if negative || f.plus || f.space {
+			prec-- // leave room for sign
+		}
+	}
+
+	// format a into buf, ending at buf[i].  (printing is easier right-to-left.)
+	// a is made into unsigned ua.  we could make things
+	// marginally faster by splitting the 32-bit case out into a separate
+	// block but it's not worth the duplication, so ua has 64 bits.
+	i := len(buf)
+	ua := uint64(a)
+	for ua >= base {
+		i--
+		buf[i] = digits[ua%base]
+		ua /= base
+	}
+	i--
+	buf[i] = digits[ua]
+	for i > 0 && prec > len(buf)-i {
+		i--
+		buf[i] = '0'
+	}
+
+	// Various prefixes: 0x, -, etc.
+	if f.sharp {
+		switch base {
+		case 8:
+			if buf[i] != '0' {
+				i--
+				buf[i] = '0'
+			}
+		case 16:
+			i--
+			buf[i] = 'x' + digits[10] - 'a'
+			i--
+			buf[i] = '0'
+		}
+	}
+	if f.unicode {
+		i--
+		buf[i] = '+'
+		i--
+		buf[i] = 'U'
+	}
+
+	if negative {
+		i--
+		buf[i] = '-'
+	} else if f.plus {
+		i--
+		buf[i] = '+'
+	} else if f.space {
+		i--
+		buf[i] = ' '
+	}
+
+	// If we want a quoted char for %#U, move the data up to make room.
+	if f.unicode && f.uniQuote && a >= 0 && a <= utf8.MaxRune && strconv.IsPrint(rune(a)) {
+		runeWidth := utf8.RuneLen(rune(a))
+		width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote
+		copy(buf[i-width:], buf[i:])   // guaranteed to have enough room.
+		i -= width
+		// Now put " 'x'" at the end.
+		j := len(buf) - width
+		buf[j] = ' '
+		j++
+		buf[j] = '\''
+		j++
+		utf8.EncodeRune(buf[j:], rune(a))
+		j += runeWidth
+		buf[j] = '\''
+	}
+
+	f.pad(buf[i:])
+}
+
+// truncate truncates the string to the specified precision, if present.
+func (f *fmt) truncate(s string) string {
+	if f.precPresent && f.prec < utf8.RuneCountInString(s) {
+		n := f.prec
+		for i := range s {
+			if n == 0 {
+				s = s[:i]
+				break
+			}
+			n--
+		}
+	}
+	return s
+}
+
+// fmt_s formats a string.
+func (f *fmt) fmt_s(s string) {
+	s = f.truncate(s)
+	f.padString(s)
+}
+
+// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
+func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
+	n := len(b)
+	if b == nil {
+		n = len(s)
+	}
+	x := digits[10] - 'a' + 'x'
+	// TODO: Avoid buffer by pre-padding.
+	var buf []byte
+	for i := 0; i < n; i++ {
+		if i > 0 && f.space {
+			buf = append(buf, ' ')
+		}
+		if f.sharp {
+			buf = append(buf, '0', x)
+		}
+		var c byte
+		if b == nil {
+			c = s[i]
+		} else {
+			c = b[i]
+		}
+		buf = append(buf, digits[c>>4], digits[c&0xF])
+	}
+	f.pad(buf)
+}
+
+// fmt_sx formats a string as a hexadecimal encoding of its bytes.
+func (f *fmt) fmt_sx(s, digits string) {
+	f.fmt_sbx(s, nil, digits)
+}
+
+// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
+func (f *fmt) fmt_bx(b []byte, digits string) {
+	f.fmt_sbx("", b, digits)
+}
+
+// fmt_q formats a string as a double-quoted, escaped Go string constant.
+func (f *fmt) fmt_q(s string) {
+	s = f.truncate(s)
+	var quoted string
+	if f.sharp && strconv.CanBackquote(s) {
+		quoted = "`" + s + "`"
+	} else {
+		if f.plus {
+			quoted = strconv.QuoteToASCII(s)
+		} else {
+			quoted = strconv.Quote(s)
+		}
+	}
+	f.padString(quoted)
+}
+
+// fmt_qc formats the integer as a single-quoted, escaped Go character constant.
+// If the character is not valid Unicode, it will print '\ufffd'.
+func (f *fmt) fmt_qc(c int64) {
+	var quoted []byte
+	if f.plus {
+		quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c))
+	} else {
+		quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c))
+	}
+	f.pad(quoted)
+}
+
+// floating-point
+
+func doPrec(f *fmt, def int) int {
+	if f.precPresent {
+		return f.prec
+	}
+	return def
+}
+
+// formatFloat formats a float64; it is an efficient equivalent to  f.pad(strconv.FormatFloat()...).
+func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
+	// Format number, reserving space for leading + sign if needed.
+	num := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n)
+	if num[1] == '-' || num[1] == '+' {
+		num = num[1:]
+	} else {
+		num[0] = '+'
+	}
+	// Special handling for infinity, which doesn't look like a number so shouldn't be padded with zeros.
+	if math.IsInf(v, 0) {
+		if f.zero {
+			defer func() { f.zero = true }()
+			f.zero = false
+		}
+	}
+	// num is now a signed version of the number.
+	// If we're zero padding, want the sign before the leading zeros.
+	// Achieve this by writing the sign out and then padding the unsigned number.
+	if f.zero && f.widPresent && f.wid > len(num) {
+		if f.space && v >= 0 {
+			f.buf.WriteByte(' ') // This is what C does: even with zero, f.space means space.
+			f.wid--
+		} else if f.plus || v < 0 {
+			f.buf.WriteByte(num[0])
+			f.wid--
+		}
+		f.pad(num[1:])
+		return
+	}
+	// f.space says to replace a leading + with a space.
+	if f.space && num[0] == '+' {
+		num[0] = ' '
+		f.pad(num)
+		return
+	}
+	// Now we know the sign is attached directly to the number, if present at all.
+	// We want a sign if asked for, if it's negative, or if it's infinity (+Inf vs. -Inf).
+	if f.plus || num[0] == '-' || math.IsInf(v, 0) {
+		f.pad(num)
+		return
+	}
+	// No sign to show and the number is positive; just print the unsigned number.
+	f.pad(num[1:])
+}
+
+// fmt_e64 formats a float64 in the form -1.23e+12.
+func (f *fmt) fmt_e64(v float64) { f.formatFloat(v, 'e', doPrec(f, 6), 64) }
+
+// fmt_E64 formats a float64 in the form -1.23E+12.
+func (f *fmt) fmt_E64(v float64) { f.formatFloat(v, 'E', doPrec(f, 6), 64) }
+
+// fmt_f64 formats a float64 in the form -1.23.
+func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) }
+
+// fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
+func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) }
+
+// fmt_G64 formats a float64 in the 'f' or 'E' form according to size.
+func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) }
+
+// fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
+func (f *fmt) fmt_fb64(v float64) { f.formatFloat(v, 'b', 0, 64) }
+
+// float32
+// cannot defer to float64 versions
+// because it will get rounding wrong in corner cases.
+
+// fmt_e32 formats a float32 in the form -1.23e+12.
+func (f *fmt) fmt_e32(v float32) { f.formatFloat(float64(v), 'e', doPrec(f, 6), 32) }
+
+// fmt_E32 formats a float32 in the form -1.23E+12.
+func (f *fmt) fmt_E32(v float32) { f.formatFloat(float64(v), 'E', doPrec(f, 6), 32) }
+
+// fmt_f32 formats a float32 in the form -1.23.
+func (f *fmt) fmt_f32(v float32) { f.formatFloat(float64(v), 'f', doPrec(f, 6), 32) }
+
+// fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
+func (f *fmt) fmt_g32(v float32) { f.formatFloat(float64(v), 'g', doPrec(f, -1), 32) }
+
+// fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
+func (f *fmt) fmt_G32(v float32) { f.formatFloat(float64(v), 'G', doPrec(f, -1), 32) }
+
+// fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
+func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
+
+// fmt_c64 formats a complex64 according to the verb.
+func (f *fmt) fmt_c64(v complex64, verb rune) {
+	f.fmt_complex(float64(real(v)), float64(imag(v)), 32, verb)
+}
+
+// fmt_c128 formats a complex128 according to the verb.
+func (f *fmt) fmt_c128(v complex128, verb rune) {
+	f.fmt_complex(real(v), imag(v), 64, verb)
+}
+
+// fmt_complex formats a complex number as (r+ji).
+func (f *fmt) fmt_complex(r, j float64, size int, verb rune) {
+	f.buf.WriteByte('(')
+	oldPlus := f.plus
+	oldSpace := f.space
+	oldWid := f.wid
+	for i := 0; ; i++ {
+		switch verb {
+		case 'b':
+			f.formatFloat(r, 'b', 0, size)
+		case 'e':
+			f.formatFloat(r, 'e', doPrec(f, 6), size)
+		case 'E':
+			f.formatFloat(r, 'E', doPrec(f, 6), size)
+		case 'f', 'F':
+			f.formatFloat(r, 'f', doPrec(f, 6), size)
+		case 'g':
+			f.formatFloat(r, 'g', doPrec(f, -1), size)
+		case 'G':
+			f.formatFloat(r, 'G', doPrec(f, -1), size)
+		}
+		if i != 0 {
+			break
+		}
+		// Imaginary part always has a sign.
+		f.plus = true
+		f.space = false
+		f.wid = oldWid
+		r = j
+	}
+	f.space = oldSpace
+	f.plus = oldPlus
+	f.wid = oldWid
+	f.buf.Write(irparenBytes)
+}
diff --git a/third_party/gofrontend/libgo/go/fmt/print.go b/third_party/gofrontend/libgo/go/fmt/print.go
new file mode 100644
index 0000000..302661f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/fmt/print.go
@@ -0,0 +1,1199 @@
+// 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 fmt
+
+import (
+	"errors"
+	"io"
+	"os"
+	"reflect"
+	"sync"
+	"unicode/utf8"
+)
+
+// Some constants in the form of bytes, to avoid string overhead.
+// Needlessly fastidious, I suppose.
+var (
+	commaSpaceBytes  = []byte(", ")
+	nilAngleBytes    = []byte("<nil>")
+	nilParenBytes    = []byte("(nil)")
+	nilBytes         = []byte("nil")
+	mapBytes         = []byte("map[")
+	percentBangBytes = []byte("%!")
+	missingBytes     = []byte("(MISSING)")
+	badIndexBytes    = []byte("(BADINDEX)")
+	panicBytes       = []byte("(PANIC=")
+	extraBytes       = []byte("%!(EXTRA ")
+	irparenBytes     = []byte("i)")
+	bytesBytes       = []byte("[]byte{")
+	badWidthBytes    = []byte("%!(BADWIDTH)")
+	badPrecBytes     = []byte("%!(BADPREC)")
+	noVerbBytes      = []byte("%!(NOVERB)")
+)
+
+// State represents the printer state passed to custom formatters.
+// It provides access to the io.Writer interface plus information about
+// the flags and options for the operand's format specifier.
+type State interface {
+	// Write is the function to call to emit formatted output to be printed.
+	Write(b []byte) (ret int, err error)
+	// Width returns the value of the width option and whether it has been set.
+	Width() (wid int, ok bool)
+	// Precision returns the value of the precision option and whether it has been set.
+	Precision() (prec int, ok bool)
+
+	// Flag reports whether the flag c, a character, has been set.
+	Flag(c int) bool
+}
+
+// Formatter is the interface implemented by values with a custom formatter.
+// The implementation of Format may call Sprint(f) or Fprint(f) etc.
+// to generate its output.
+type Formatter interface {
+	Format(f State, c rune)
+}
+
+// Stringer is implemented by any value that has a String method,
+// which defines the ``native'' format for that value.
+// The String method is used to print values passed as an operand
+// to any format that accepts a string or to an unformatted printer
+// such as Print.
+type Stringer interface {
+	String() string
+}
+
+// GoStringer is implemented by any value that has a GoString method,
+// which defines the Go syntax for that value.
+// The GoString method is used to print values passed as an operand
+// to a %#v format.
+type GoStringer interface {
+	GoString() string
+}
+
+// Use simple []byte instead of bytes.Buffer to avoid large dependency.
+type buffer []byte
+
+func (b *buffer) Write(p []byte) (n int, err error) {
+	*b = append(*b, p...)
+	return len(p), nil
+}
+
+func (b *buffer) WriteString(s string) (n int, err error) {
+	*b = append(*b, s...)
+	return len(s), nil
+}
+
+func (b *buffer) WriteByte(c byte) error {
+	*b = append(*b, c)
+	return nil
+}
+
+func (bp *buffer) WriteRune(r rune) error {
+	if r < utf8.RuneSelf {
+		*bp = append(*bp, byte(r))
+		return nil
+	}
+
+	b := *bp
+	n := len(b)
+	for n+utf8.UTFMax > cap(b) {
+		b = append(b, 0)
+	}
+	w := utf8.EncodeRune(b[n:n+utf8.UTFMax], r)
+	*bp = b[:n+w]
+	return nil
+}
+
+type pp struct {
+	n         int
+	panicking bool
+	erroring  bool // printing an error condition
+	buf       buffer
+	// arg holds the current item, as an interface{}.
+	arg interface{}
+	// value holds the current item, as a reflect.Value, and will be
+	// the zero Value if the item has not been reflected.
+	value reflect.Value
+	// reordered records whether the format string used argument reordering.
+	reordered bool
+	// goodArgNum records whether the most recent reordering directive was valid.
+	goodArgNum bool
+	runeBuf    [utf8.UTFMax]byte
+	fmt        fmt
+}
+
+var ppFree = sync.Pool{
+	New: func() interface{} { return new(pp) },
+}
+
+// newPrinter allocates a new pp struct or grab a cached one.
+func newPrinter() *pp {
+	p := ppFree.Get().(*pp)
+	p.panicking = false
+	p.erroring = false
+	p.fmt.init(&p.buf)
+	return p
+}
+
+// free saves used pp structs in ppFree; avoids an allocation per invocation.
+func (p *pp) free() {
+	// Don't hold on to pp structs with large buffers.
+	if cap(p.buf) > 1024 {
+		return
+	}
+	p.buf = p.buf[:0]
+	p.arg = nil
+	p.value = reflect.Value{}
+	ppFree.Put(p)
+}
+
+func (p *pp) Width() (wid int, ok bool) { return p.fmt.wid, p.fmt.widPresent }
+
+func (p *pp) Precision() (prec int, ok bool) { return p.fmt.prec, p.fmt.precPresent }
+
+func (p *pp) Flag(b int) bool {
+	switch b {
+	case '-':
+		return p.fmt.minus
+	case '+':
+		return p.fmt.plus
+	case '#':
+		return p.fmt.sharp
+	case ' ':
+		return p.fmt.space
+	case '0':
+		return p.fmt.zero
+	}
+	return false
+}
+
+func (p *pp) add(c rune) {
+	p.buf.WriteRune(c)
+}
+
+// Implement Write so we can call Fprintf on a pp (through State), for
+// recursive use in custom verbs.
+func (p *pp) Write(b []byte) (ret int, err error) {
+	return p.buf.Write(b)
+}
+
+// These routines end in 'f' and take a format string.
+
+// Fprintf formats according to a format specifier and writes to w.
+// It returns the number of bytes written and any write error encountered.
+func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
+	p := newPrinter()
+	p.doPrintf(format, a)
+	n, err = w.Write(p.buf)
+	p.free()
+	return
+}
+
+// Printf formats according to a format specifier and writes to standard output.
+// It returns the number of bytes written and any write error encountered.
+func Printf(format string, a ...interface{}) (n int, err error) {
+	return Fprintf(os.Stdout, format, a...)
+}
+
+// Sprintf formats according to a format specifier and returns the resulting string.
+func Sprintf(format string, a ...interface{}) string {
+	p := newPrinter()
+	p.doPrintf(format, a)
+	s := string(p.buf)
+	p.free()
+	return s
+}
+
+// Errorf formats according to a format specifier and returns the string
+// as a value that satisfies error.
+func Errorf(format string, a ...interface{}) error {
+	return errors.New(Sprintf(format, a...))
+}
+
+// These routines do not take a format string
+
+// Fprint formats using the default formats for its operands and writes to w.
+// Spaces are added between operands when neither is a string.
+// It returns the number of bytes written and any write error encountered.
+func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
+	p := newPrinter()
+	p.doPrint(a, false, false)
+	n, err = w.Write(p.buf)
+	p.free()
+	return
+}
+
+// Print formats using the default formats for its operands and writes to standard output.
+// Spaces are added between operands when neither is a string.
+// It returns the number of bytes written and any write error encountered.
+func Print(a ...interface{}) (n int, err error) {
+	return Fprint(os.Stdout, a...)
+}
+
+// Sprint formats using the default formats for its operands and returns the resulting string.
+// Spaces are added between operands when neither is a string.
+func Sprint(a ...interface{}) string {
+	p := newPrinter()
+	p.doPrint(a, false, false)
+	s := string(p.buf)
+	p.free()
+	return s
+}
+
+// These routines end in 'ln', do not take a format string,
+// always add spaces between operands, and add a newline
+// after the last operand.
+
+// Fprintln formats using the default formats for its operands and writes to w.
+// Spaces are always added between operands and a newline is appended.
+// It returns the number of bytes written and any write error encountered.
+func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
+	p := newPrinter()
+	p.doPrint(a, true, true)
+	n, err = w.Write(p.buf)
+	p.free()
+	return
+}
+
+// Println formats using the default formats for its operands and writes to standard output.
+// Spaces are always added between operands and a newline is appended.
+// It returns the number of bytes written and any write error encountered.
+func Println(a ...interface{}) (n int, err error) {
+	return Fprintln(os.Stdout, a...)
+}
+
+// Sprintln formats using the default formats for its operands and returns the resulting string.
+// Spaces are always added between operands and a newline is appended.
+func Sprintln(a ...interface{}) string {
+	p := newPrinter()
+	p.doPrint(a, true, true)
+	s := string(p.buf)
+	p.free()
+	return s
+}
+
+// getField gets the i'th field of the struct value.
+// If the field is itself is an interface, return a value for
+// the thing inside the interface, not the interface itself.
+func getField(v reflect.Value, i int) reflect.Value {
+	val := v.Field(i)
+	if val.Kind() == reflect.Interface && !val.IsNil() {
+		val = val.Elem()
+	}
+	return val
+}
+
+// parsenum converts ASCII to integer.  num is 0 (and isnum is false) if no number present.
+func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
+	if start >= end {
+		return 0, false, end
+	}
+	for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ {
+		num = num*10 + int(s[newi]-'0')
+		isnum = true
+	}
+	return
+}
+
+func (p *pp) unknownType(v interface{}) {
+	if v == nil {
+		p.buf.Write(nilAngleBytes)
+		return
+	}
+	p.buf.WriteByte('?')
+	p.buf.WriteString(reflect.TypeOf(v).String())
+	p.buf.WriteByte('?')
+}
+
+func (p *pp) badVerb(verb rune) {
+	p.erroring = true
+	p.add('%')
+	p.add('!')
+	p.add(verb)
+	p.add('(')
+	switch {
+	case p.arg != nil:
+		p.buf.WriteString(reflect.TypeOf(p.arg).String())
+		p.add('=')
+		p.printArg(p.arg, 'v', false, false, 0)
+	case p.value.IsValid():
+		p.buf.WriteString(p.value.Type().String())
+		p.add('=')
+		p.printValue(p.value, 'v', false, false, 0)
+	default:
+		p.buf.Write(nilAngleBytes)
+	}
+	p.add(')')
+	p.erroring = false
+}
+
+func (p *pp) fmtBool(v bool, verb rune) {
+	switch verb {
+	case 't', 'v':
+		p.fmt.fmt_boolean(v)
+	default:
+		p.badVerb(verb)
+	}
+}
+
+// fmtC formats a rune for the 'c' format.
+func (p *pp) fmtC(c int64) {
+	r := rune(c) // Check for overflow.
+	if int64(r) != c {
+		r = utf8.RuneError
+	}
+	w := utf8.EncodeRune(p.runeBuf[0:utf8.UTFMax], r)
+	p.fmt.pad(p.runeBuf[0:w])
+}
+
+func (p *pp) fmtInt64(v int64, verb rune) {
+	switch verb {
+	case 'b':
+		p.fmt.integer(v, 2, signed, ldigits)
+	case 'c':
+		p.fmtC(v)
+	case 'd', 'v':
+		p.fmt.integer(v, 10, signed, ldigits)
+	case 'o':
+		p.fmt.integer(v, 8, signed, ldigits)
+	case 'q':
+		if 0 <= v && v <= utf8.MaxRune {
+			p.fmt.fmt_qc(v)
+		} else {
+			p.badVerb(verb)
+		}
+	case 'x':
+		p.fmt.integer(v, 16, signed, ldigits)
+	case 'U':
+		p.fmtUnicode(v)
+	case 'X':
+		p.fmt.integer(v, 16, signed, udigits)
+	default:
+		p.badVerb(verb)
+	}
+}
+
+// fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x or
+// not, as requested, by temporarily setting the sharp flag.
+func (p *pp) fmt0x64(v uint64, leading0x bool) {
+	sharp := p.fmt.sharp
+	p.fmt.sharp = leading0x
+	p.fmt.integer(int64(v), 16, unsigned, ldigits)
+	p.fmt.sharp = sharp
+}
+
+// fmtUnicode formats a uint64 in U+1234 form by
+// temporarily turning on the unicode flag and tweaking the precision.
+func (p *pp) fmtUnicode(v int64) {
+	precPresent := p.fmt.precPresent
+	sharp := p.fmt.sharp
+	p.fmt.sharp = false
+	prec := p.fmt.prec
+	if !precPresent {
+		// If prec is already set, leave it alone; otherwise 4 is minimum.
+		p.fmt.prec = 4
+		p.fmt.precPresent = true
+	}
+	p.fmt.unicode = true // turn on U+
+	p.fmt.uniQuote = sharp
+	p.fmt.integer(int64(v), 16, unsigned, udigits)
+	p.fmt.unicode = false
+	p.fmt.uniQuote = false
+	p.fmt.prec = prec
+	p.fmt.precPresent = precPresent
+	p.fmt.sharp = sharp
+}
+
+func (p *pp) fmtUint64(v uint64, verb rune, goSyntax bool) {
+	switch verb {
+	case 'b':
+		p.fmt.integer(int64(v), 2, unsigned, ldigits)
+	case 'c':
+		p.fmtC(int64(v))
+	case 'd':
+		p.fmt.integer(int64(v), 10, unsigned, ldigits)
+	case 'v':
+		if goSyntax {
+			p.fmt0x64(v, true)
+		} else {
+			p.fmt.integer(int64(v), 10, unsigned, ldigits)
+		}
+	case 'o':
+		p.fmt.integer(int64(v), 8, unsigned, ldigits)
+	case 'q':
+		if 0 <= v && v <= utf8.MaxRune {
+			p.fmt.fmt_qc(int64(v))
+		} else {
+			p.badVerb(verb)
+		}
+	case 'x':
+		p.fmt.integer(int64(v), 16, unsigned, ldigits)
+	case 'X':
+		p.fmt.integer(int64(v), 16, unsigned, udigits)
+	case 'U':
+		p.fmtUnicode(int64(v))
+	default:
+		p.badVerb(verb)
+	}
+}
+
+func (p *pp) fmtFloat32(v float32, verb rune) {
+	switch verb {
+	case 'b':
+		p.fmt.fmt_fb32(v)
+	case 'e':
+		p.fmt.fmt_e32(v)
+	case 'E':
+		p.fmt.fmt_E32(v)
+	case 'f', 'F':
+		p.fmt.fmt_f32(v)
+	case 'g', 'v':
+		p.fmt.fmt_g32(v)
+	case 'G':
+		p.fmt.fmt_G32(v)
+	default:
+		p.badVerb(verb)
+	}
+}
+
+func (p *pp) fmtFloat64(v float64, verb rune) {
+	switch verb {
+	case 'b':
+		p.fmt.fmt_fb64(v)
+	case 'e':
+		p.fmt.fmt_e64(v)
+	case 'E':
+		p.fmt.fmt_E64(v)
+	case 'f', 'F':
+		p.fmt.fmt_f64(v)
+	case 'g', 'v':
+		p.fmt.fmt_g64(v)
+	case 'G':
+		p.fmt.fmt_G64(v)
+	default:
+		p.badVerb(verb)
+	}
+}
+
+func (p *pp) fmtComplex64(v complex64, verb rune) {
+	switch verb {
+	case 'b', 'e', 'E', 'f', 'F', 'g', 'G':
+		p.fmt.fmt_c64(v, verb)
+	case 'v':
+		p.fmt.fmt_c64(v, 'g')
+	default:
+		p.badVerb(verb)
+	}
+}
+
+func (p *pp) fmtComplex128(v complex128, verb rune) {
+	switch verb {
+	case 'b', 'e', 'E', 'f', 'F', 'g', 'G':
+		p.fmt.fmt_c128(v, verb)
+	case 'v':
+		p.fmt.fmt_c128(v, 'g')
+	default:
+		p.badVerb(verb)
+	}
+}
+
+func (p *pp) fmtString(v string, verb rune, goSyntax bool) {
+	switch verb {
+	case 'v':
+		if goSyntax {
+			p.fmt.fmt_q(v)
+		} else {
+			p.fmt.fmt_s(v)
+		}
+	case 's':
+		p.fmt.fmt_s(v)
+	case 'x':
+		p.fmt.fmt_sx(v, ldigits)
+	case 'X':
+		p.fmt.fmt_sx(v, udigits)
+	case 'q':
+		p.fmt.fmt_q(v)
+	default:
+		p.badVerb(verb)
+	}
+}
+
+func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, depth int) {
+	if verb == 'v' || verb == 'd' {
+		if goSyntax {
+			if v == nil {
+				if typ == nil {
+					p.buf.WriteString("[]byte(nil)")
+				} else {
+					p.buf.WriteString(typ.String())
+					p.buf.Write(nilParenBytes)
+				}
+				return
+			}
+			if typ == nil {
+				p.buf.Write(bytesBytes)
+			} else {
+				p.buf.WriteString(typ.String())
+				p.buf.WriteByte('{')
+			}
+		} else {
+			p.buf.WriteByte('[')
+		}
+		for i, c := range v {
+			if i > 0 {
+				if goSyntax {
+					p.buf.Write(commaSpaceBytes)
+				} else {
+					p.buf.WriteByte(' ')
+				}
+			}
+			p.printArg(c, 'v', p.fmt.plus, goSyntax, depth+1)
+		}
+		if goSyntax {
+			p.buf.WriteByte('}')
+		} else {
+			p.buf.WriteByte(']')
+		}
+		return
+	}
+	switch verb {
+	case 's':
+		p.fmt.fmt_s(string(v))
+	case 'x':
+		p.fmt.fmt_bx(v, ldigits)
+	case 'X':
+		p.fmt.fmt_bx(v, udigits)
+	case 'q':
+		p.fmt.fmt_q(string(v))
+	default:
+		p.badVerb(verb)
+	}
+}
+
+func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
+	use0x64 := true
+	switch verb {
+	case 'p', 'v':
+		// ok
+	case 'b', 'd', 'o', 'x', 'X':
+		use0x64 = false
+		// ok
+	default:
+		p.badVerb(verb)
+		return
+	}
+
+	var u uintptr
+	switch value.Kind() {
+	case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
+		u = value.Pointer()
+	default:
+		p.badVerb(verb)
+		return
+	}
+
+	if goSyntax {
+		p.add('(')
+		p.buf.WriteString(value.Type().String())
+		p.add(')')
+		p.add('(')
+		if u == 0 {
+			p.buf.Write(nilBytes)
+		} else {
+			p.fmt0x64(uint64(u), true)
+		}
+		p.add(')')
+	} else if verb == 'v' && u == 0 {
+		p.buf.Write(nilAngleBytes)
+	} else {
+		if use0x64 {
+			p.fmt0x64(uint64(u), !p.fmt.sharp)
+		} else {
+			p.fmtUint64(uint64(u), verb, false)
+		}
+	}
+}
+
+var (
+	intBits     = reflect.TypeOf(0).Bits()
+	uintptrBits = reflect.TypeOf(uintptr(0)).Bits()
+)
+
+func (p *pp) catchPanic(arg interface{}, verb rune) {
+	if err := recover(); err != nil {
+		// If it's a nil pointer, just say "<nil>". The likeliest causes are a
+		// Stringer that fails to guard against nil or a nil pointer for a
+		// value receiver, and in either case, "<nil>" is a nice result.
+		if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() {
+			p.buf.Write(nilAngleBytes)
+			return
+		}
+		// Otherwise print a concise panic message. Most of the time the panic
+		// value will print itself nicely.
+		if p.panicking {
+			// Nested panics; the recursion in printArg cannot succeed.
+			panic(err)
+		}
+		p.buf.Write(percentBangBytes)
+		p.add(verb)
+		p.buf.Write(panicBytes)
+		p.panicking = true
+		p.printArg(err, 'v', false, false, 0)
+		p.panicking = false
+		p.buf.WriteByte(')')
+	}
+}
+
+func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString, handled bool) {
+	if p.erroring {
+		return
+	}
+	// Is it a Formatter?
+	if formatter, ok := p.arg.(Formatter); ok {
+		handled = true
+		wasString = false
+		defer p.catchPanic(p.arg, verb)
+		formatter.Format(p, verb)
+		return
+	}
+	// Must not touch flags before Formatter looks at them.
+	if plus {
+		p.fmt.plus = false
+	}
+
+	// If we're doing Go syntax and the argument knows how to supply it, take care of it now.
+	if goSyntax {
+		p.fmt.sharp = false
+		if stringer, ok := p.arg.(GoStringer); ok {
+			wasString = false
+			handled = true
+			defer p.catchPanic(p.arg, verb)
+			// Print the result of GoString unadorned.
+			p.fmtString(stringer.GoString(), 's', false)
+			return
+		}
+	} else {
+		// If a string is acceptable according to the format, see if
+		// the value satisfies one of the string-valued interfaces.
+		// Println etc. set verb to %v, which is "stringable".
+		switch verb {
+		case 'v', 's', 'x', 'X', 'q':
+			// Is it an error or Stringer?
+			// The duplication in the bodies is necessary:
+			// setting wasString and handled, and deferring catchPanic,
+			// must happen before calling the method.
+			switch v := p.arg.(type) {
+			case error:
+				wasString = false
+				handled = true
+				defer p.catchPanic(p.arg, verb)
+				p.printArg(v.Error(), verb, plus, false, depth)
+				return
+
+			case Stringer:
+				wasString = false
+				handled = true
+				defer p.catchPanic(p.arg, verb)
+				p.printArg(v.String(), verb, plus, false, depth)
+				return
+			}
+		}
+	}
+	handled = false
+	return
+}
+
+func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+	p.arg = arg
+	p.value = reflect.Value{}
+
+	if arg == nil {
+		if verb == 'T' || verb == 'v' {
+			p.fmt.pad(nilAngleBytes)
+		} else {
+			p.badVerb(verb)
+		}
+		return false
+	}
+
+	// Special processing considerations.
+	// %T (the value's type) and %p (its address) are special; we always do them first.
+	switch verb {
+	case 'T':
+		p.printArg(reflect.TypeOf(arg).String(), 's', false, false, 0)
+		return false
+	case 'p':
+		p.fmtPointer(reflect.ValueOf(arg), verb, goSyntax)
+		return false
+	}
+
+	// Clear flags for base formatters.
+	// handleMethods needs them, so we must restore them later.
+	// We could call handleMethods here and avoid this work, but
+	// handleMethods is expensive enough to be worth delaying.
+	oldPlus := p.fmt.plus
+	oldSharp := p.fmt.sharp
+	if plus {
+		p.fmt.plus = false
+	}
+	if goSyntax {
+		p.fmt.sharp = false
+	}
+
+	// Some types can be done without reflection.
+	switch f := arg.(type) {
+	case bool:
+		p.fmtBool(f, verb)
+	case float32:
+		p.fmtFloat32(f, verb)
+	case float64:
+		p.fmtFloat64(f, verb)
+	case complex64:
+		p.fmtComplex64(f, verb)
+	case complex128:
+		p.fmtComplex128(f, verb)
+	case int:
+		p.fmtInt64(int64(f), verb)
+	case int8:
+		p.fmtInt64(int64(f), verb)
+	case int16:
+		p.fmtInt64(int64(f), verb)
+	case int32:
+		p.fmtInt64(int64(f), verb)
+	case int64:
+		p.fmtInt64(f, verb)
+	case uint:
+		p.fmtUint64(uint64(f), verb, goSyntax)
+	case uint8:
+		p.fmtUint64(uint64(f), verb, goSyntax)
+	case uint16:
+		p.fmtUint64(uint64(f), verb, goSyntax)
+	case uint32:
+		p.fmtUint64(uint64(f), verb, goSyntax)
+	case uint64:
+		p.fmtUint64(f, verb, goSyntax)
+	case uintptr:
+		p.fmtUint64(uint64(f), verb, goSyntax)
+	case string:
+		p.fmtString(f, verb, goSyntax)
+		wasString = verb == 's' || verb == 'v'
+	case []byte:
+		p.fmtBytes(f, verb, goSyntax, nil, depth)
+		wasString = verb == 's'
+	default:
+		// Restore flags in case handleMethods finds a Formatter.
+		p.fmt.plus = oldPlus
+		p.fmt.sharp = oldSharp
+		// If the type is not simple, it might have methods.
+		if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
+			return isString
+		}
+		// Need to use reflection
+		return p.printReflectValue(reflect.ValueOf(arg), verb, plus, goSyntax, depth)
+	}
+	p.arg = nil
+	return
+}
+
+// printValue is like printArg but starts with a reflect value, not an interface{} value.
+func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+	if !value.IsValid() {
+		if verb == 'T' || verb == 'v' {
+			p.buf.Write(nilAngleBytes)
+		} else {
+			p.badVerb(verb)
+		}
+		return false
+	}
+
+	// Special processing considerations.
+	// %T (the value's type) and %p (its address) are special; we always do them first.
+	switch verb {
+	case 'T':
+		p.printArg(value.Type().String(), 's', false, false, 0)
+		return false
+	case 'p':
+		p.fmtPointer(value, verb, goSyntax)
+		return false
+	}
+
+	// Handle values with special methods.
+	// Call always, even when arg == nil, because handleMethods clears p.fmt.plus for us.
+	p.arg = nil // Make sure it's cleared, for safety.
+	if value.CanInterface() {
+		p.arg = value.Interface()
+	}
+	if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
+		return isString
+	}
+
+	return p.printReflectValue(value, verb, plus, goSyntax, depth)
+}
+
+// printReflectValue is the fallback for both printArg and printValue.
+// It uses reflect to print the value.
+func (p *pp) printReflectValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+	oldValue := p.value
+	p.value = value
+BigSwitch:
+	switch f := value; f.Kind() {
+	case reflect.Bool:
+		p.fmtBool(f.Bool(), verb)
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		p.fmtInt64(f.Int(), verb)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		p.fmtUint64(f.Uint(), verb, goSyntax)
+	case reflect.Float32, reflect.Float64:
+		if f.Type().Size() == 4 {
+			p.fmtFloat32(float32(f.Float()), verb)
+		} else {
+			p.fmtFloat64(f.Float(), verb)
+		}
+	case reflect.Complex64, reflect.Complex128:
+		if f.Type().Size() == 8 {
+			p.fmtComplex64(complex64(f.Complex()), verb)
+		} else {
+			p.fmtComplex128(f.Complex(), verb)
+		}
+	case reflect.String:
+		p.fmtString(f.String(), verb, goSyntax)
+	case reflect.Map:
+		if goSyntax {
+			p.buf.WriteString(f.Type().String())
+			if f.IsNil() {
+				p.buf.WriteString("(nil)")
+				break
+			}
+			p.buf.WriteByte('{')
+		} else {
+			p.buf.Write(mapBytes)
+		}
+		keys := f.MapKeys()
+		for i, key := range keys {
+			if i > 0 {
+				if goSyntax {
+					p.buf.Write(commaSpaceBytes)
+				} else {
+					p.buf.WriteByte(' ')
+				}
+			}
+			p.printValue(key, verb, plus, goSyntax, depth+1)
+			p.buf.WriteByte(':')
+			p.printValue(f.MapIndex(key), verb, plus, goSyntax, depth+1)
+		}
+		if goSyntax {
+			p.buf.WriteByte('}')
+		} else {
+			p.buf.WriteByte(']')
+		}
+	case reflect.Struct:
+		if goSyntax {
+			p.buf.WriteString(value.Type().String())
+		}
+		p.add('{')
+		v := f
+		t := v.Type()
+		for i := 0; i < v.NumField(); i++ {
+			if i > 0 {
+				if goSyntax {
+					p.buf.Write(commaSpaceBytes)
+				} else {
+					p.buf.WriteByte(' ')
+				}
+			}
+			if plus || goSyntax {
+				if f := t.Field(i); f.Name != "" {
+					p.buf.WriteString(f.Name)
+					p.buf.WriteByte(':')
+				}
+			}
+			p.printValue(getField(v, i), verb, plus, goSyntax, depth+1)
+		}
+		p.buf.WriteByte('}')
+	case reflect.Interface:
+		value := f.Elem()
+		if !value.IsValid() {
+			if goSyntax {
+				p.buf.WriteString(f.Type().String())
+				p.buf.Write(nilParenBytes)
+			} else {
+				p.buf.Write(nilAngleBytes)
+			}
+		} else {
+			wasString = p.printValue(value, verb, plus, goSyntax, depth+1)
+		}
+	case reflect.Array, reflect.Slice:
+		// Byte slices are special.
+		if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 {
+			var bytes []byte
+			if f.Kind() == reflect.Slice {
+				bytes = f.Bytes()
+			} else if f.CanAddr() {
+				bytes = f.Slice(0, f.Len()).Bytes()
+			} else {
+				// We have an array, but we cannot Slice() a non-addressable array,
+				// so we build a slice by hand. This is a rare case but it would be nice
+				// if reflection could help a little more.
+				bytes = make([]byte, f.Len())
+				for i := range bytes {
+					bytes[i] = byte(f.Index(i).Uint())
+				}
+			}
+			p.fmtBytes(bytes, verb, goSyntax, typ, depth)
+			wasString = verb == 's'
+			break
+		}
+		if goSyntax {
+			p.buf.WriteString(value.Type().String())
+			if f.Kind() == reflect.Slice && f.IsNil() {
+				p.buf.WriteString("(nil)")
+				break
+			}
+			p.buf.WriteByte('{')
+		} else {
+			p.buf.WriteByte('[')
+		}
+		for i := 0; i < f.Len(); i++ {
+			if i > 0 {
+				if goSyntax {
+					p.buf.Write(commaSpaceBytes)
+				} else {
+					p.buf.WriteByte(' ')
+				}
+			}
+			p.printValue(f.Index(i), verb, plus, goSyntax, depth+1)
+		}
+		if goSyntax {
+			p.buf.WriteByte('}')
+		} else {
+			p.buf.WriteByte(']')
+		}
+	case reflect.Ptr:
+		v := f.Pointer()
+		// pointer to array or slice or struct?  ok at top level
+		// but not embedded (avoid loops)
+		if v != 0 && depth == 0 {
+			switch a := f.Elem(); a.Kind() {
+			case reflect.Array, reflect.Slice:
+				p.buf.WriteByte('&')
+				p.printValue(a, verb, plus, goSyntax, depth+1)
+				break BigSwitch
+			case reflect.Struct:
+				p.buf.WriteByte('&')
+				p.printValue(a, verb, plus, goSyntax, depth+1)
+				break BigSwitch
+			}
+		}
+		fallthrough
+	case reflect.Chan, reflect.Func, reflect.UnsafePointer:
+		p.fmtPointer(value, verb, goSyntax)
+	default:
+		p.unknownType(f)
+	}
+	p.value = oldValue
+	return wasString
+}
+
+// intFromArg gets the argNumth element of a. On return, isInt reports whether the argument has type int.
+func intFromArg(a []interface{}, argNum int) (num int, isInt bool, newArgNum int) {
+	newArgNum = argNum
+	if argNum < len(a) {
+		num, isInt = a[argNum].(int)
+		newArgNum = argNum + 1
+	}
+	return
+}
+
+// parseArgNumber returns the value of the bracketed number, minus 1
+// (explicit argument numbers are one-indexed but we want zero-indexed).
+// The opening bracket is known to be present at format[0].
+// The returned values are the index, the number of bytes to consume
+// up to the closing paren, if present, and whether the number parsed
+// ok. The bytes to consume will be 1 if no closing paren is present.
+func parseArgNumber(format string) (index int, wid int, ok bool) {
+	// Find closing bracket.
+	for i := 1; i < len(format); i++ {
+		if format[i] == ']' {
+			width, ok, newi := parsenum(format, 1, i)
+			if !ok || newi != i {
+				return 0, i + 1, false
+			}
+			return width - 1, i + 1, true // arg numbers are one-indexed and skip paren.
+		}
+	}
+	return 0, 1, false
+}
+
+// argNumber returns the next argument to evaluate, which is either the value of the passed-in
+// argNum or the value of the bracketed integer that begins format[i:]. It also returns
+// the new value of i, that is, the index of the next byte of the format to process.
+func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum, newi int, found bool) {
+	if len(format) <= i || format[i] != '[' {
+		return argNum, i, false
+	}
+	p.reordered = true
+	index, wid, ok := parseArgNumber(format[i:])
+	if ok && 0 <= index && index < numArgs {
+		return index, i + wid, true
+	}
+	p.goodArgNum = false
+	return argNum, i + wid, true
+}
+
+func (p *pp) doPrintf(format string, a []interface{}) {
+	end := len(format)
+	argNum := 0         // we process one argument per non-trivial format
+	afterIndex := false // previous item in format was an index like [3].
+	p.reordered = false
+	for i := 0; i < end; {
+		p.goodArgNum = true
+		lasti := i
+		for i < end && format[i] != '%' {
+			i++
+		}
+		if i > lasti {
+			p.buf.WriteString(format[lasti:i])
+		}
+		if i >= end {
+			// done processing format string
+			break
+		}
+
+		// Process one verb
+		i++
+
+		// Do we have flags?
+		p.fmt.clearflags()
+	F:
+		for ; i < end; i++ {
+			switch format[i] {
+			case '#':
+				p.fmt.sharp = true
+			case '0':
+				p.fmt.zero = true
+			case '+':
+				p.fmt.plus = true
+			case '-':
+				p.fmt.minus = true
+			case ' ':
+				p.fmt.space = true
+			default:
+				break F
+			}
+		}
+
+		// Do we have an explicit argument index?
+		argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
+
+		// Do we have width?
+		if i < end && format[i] == '*' {
+			i++
+			p.fmt.wid, p.fmt.widPresent, argNum = intFromArg(a, argNum)
+			if !p.fmt.widPresent {
+				p.buf.Write(badWidthBytes)
+			}
+			afterIndex = false
+		} else {
+			p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end)
+			if afterIndex && p.fmt.widPresent { // "%[3]2d"
+				p.goodArgNum = false
+			}
+		}
+
+		// Do we have precision?
+		if i+1 < end && format[i] == '.' {
+			i++
+			if afterIndex { // "%[3].2d"
+				p.goodArgNum = false
+			}
+			argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
+			if format[i] == '*' {
+				i++
+				p.fmt.prec, p.fmt.precPresent, argNum = intFromArg(a, argNum)
+				if !p.fmt.precPresent {
+					p.buf.Write(badPrecBytes)
+				}
+				afterIndex = false
+			} else {
+				p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i, end)
+				if !p.fmt.precPresent {
+					p.fmt.prec = 0
+					p.fmt.precPresent = true
+				}
+			}
+		}
+
+		if !afterIndex {
+			argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
+		}
+
+		if i >= end {
+			p.buf.Write(noVerbBytes)
+			continue
+		}
+		c, w := utf8.DecodeRuneInString(format[i:])
+		i += w
+		// percent is special - absorbs no operand
+		if c == '%' {
+			p.buf.WriteByte('%') // We ignore width and prec.
+			continue
+		}
+		if !p.goodArgNum {
+			p.buf.Write(percentBangBytes)
+			p.add(c)
+			p.buf.Write(badIndexBytes)
+			continue
+		} else if argNum >= len(a) { // out of operands
+			p.buf.Write(percentBangBytes)
+			p.add(c)
+			p.buf.Write(missingBytes)
+			continue
+		}
+		arg := a[argNum]
+		argNum++
+
+		goSyntax := c == 'v' && p.fmt.sharp
+		plus := c == 'v' && p.fmt.plus
+		p.printArg(arg, c, plus, goSyntax, 0)
+	}
+
+	// Check for extra arguments unless the call accessed the arguments
+	// out of order, in which case it's too expensive to detect if they've all
+	// been used and arguably OK if they're not.
+	if !p.reordered && argNum < len(a) {
+		p.buf.Write(extraBytes)
+		for ; argNum < len(a); argNum++ {
+			arg := a[argNum]
+			if arg != nil {
+				p.buf.WriteString(reflect.TypeOf(arg).String())
+				p.buf.WriteByte('=')
+			}
+			p.printArg(arg, 'v', false, false, 0)
+			if argNum+1 < len(a) {
+				p.buf.Write(commaSpaceBytes)
+			}
+		}
+		p.buf.WriteByte(')')
+	}
+}
+
+func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
+	prevString := false
+	for argNum := 0; argNum < len(a); argNum++ {
+		p.fmt.clearflags()
+		// always add spaces if we're doing Println
+		arg := a[argNum]
+		if argNum > 0 {
+			isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
+			if addspace || !isString && !prevString {
+				p.buf.WriteByte(' ')
+			}
+		}
+		prevString = p.printArg(arg, 'v', false, false, 0)
+	}
+	if addnewline {
+		p.buf.WriteByte('\n')
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/fmt/scan.go b/third_party/gofrontend/libgo/go/fmt/scan.go
new file mode 100644
index 0000000..8a337e4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/fmt/scan.go
@@ -0,0 +1,1168 @@
+// Copyright 2010 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 fmt
+
+import (
+	"errors"
+	"io"
+	"math"
+	"os"
+	"reflect"
+	"strconv"
+	"sync"
+	"unicode/utf8"
+)
+
+// runeUnreader is the interface to something that can unread runes.
+// If the object provided to Scan does not satisfy this interface,
+// a local buffer will be used to back up the input, but its contents
+// will be lost when Scan returns.
+type runeUnreader interface {
+	UnreadRune() error
+}
+
+// ScanState represents the scanner state passed to custom scanners.
+// Scanners may do rune-at-a-time scanning or ask the ScanState
+// to discover the next space-delimited token.
+type ScanState interface {
+	// ReadRune reads the next rune (Unicode code point) from the input.
+	// If invoked during Scanln, Fscanln, or Sscanln, ReadRune() will
+	// return EOF after returning the first '\n' or when reading beyond
+	// the specified width.
+	ReadRune() (r rune, size int, err error)
+	// UnreadRune causes the next call to ReadRune to return the same rune.
+	UnreadRune() error
+	// SkipSpace skips space in the input. Newlines are treated as space
+	// unless the scan operation is Scanln, Fscanln or Sscanln, in which case
+	// a newline is treated as EOF.
+	SkipSpace()
+	// Token skips space in the input if skipSpace is true, then returns the
+	// run of Unicode code points c satisfying f(c).  If f is nil,
+	// !unicode.IsSpace(c) is used; that is, the token will hold non-space
+	// characters.  Newlines are treated as space unless the scan operation
+	// is Scanln, Fscanln or Sscanln, in which case a newline is treated as
+	// EOF.  The returned slice points to shared data that may be overwritten
+	// by the next call to Token, a call to a Scan function using the ScanState
+	// as input, or when the calling Scan method returns.
+	Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
+	// Width returns the value of the width option and whether it has been set.
+	// The unit is Unicode code points.
+	Width() (wid int, ok bool)
+	// Because ReadRune is implemented by the interface, Read should never be
+	// called by the scanning routines and a valid implementation of
+	// ScanState may choose always to return an error from Read.
+	Read(buf []byte) (n int, err error)
+}
+
+// Scanner is implemented by any value that has a Scan method, which scans
+// the input for the representation of a value and stores the result in the
+// receiver, which must be a pointer to be useful.  The Scan method is called
+// for any argument to Scan, Scanf, or Scanln that implements it.
+type Scanner interface {
+	Scan(state ScanState, verb rune) error
+}
+
+// Scan scans text read from standard input, storing successive
+// space-separated values into successive arguments.  Newlines count
+// as space.  It returns the number of items successfully scanned.
+// If that is less than the number of arguments, err will report why.
+func Scan(a ...interface{}) (n int, err error) {
+	return Fscan(os.Stdin, a...)
+}
+
+// Scanln is similar to Scan, but stops scanning at a newline and
+// after the final item there must be a newline or EOF.
+func Scanln(a ...interface{}) (n int, err error) {
+	return Fscanln(os.Stdin, a...)
+}
+
+// Scanf scans text read from standard input, storing successive
+// space-separated values into successive arguments as determined by
+// the format.  It returns the number of items successfully scanned.
+func Scanf(format string, a ...interface{}) (n int, err error) {
+	return Fscanf(os.Stdin, format, a...)
+}
+
+type stringReader string
+
+func (r *stringReader) Read(b []byte) (n int, err error) {
+	n = copy(b, *r)
+	*r = (*r)[n:]
+	if n == 0 {
+		err = io.EOF
+	}
+	return
+}
+
+// Sscan scans the argument string, storing successive space-separated
+// values into successive arguments.  Newlines count as space.  It
+// returns the number of items successfully scanned.  If that is less
+// than the number of arguments, err will report why.
+func Sscan(str string, a ...interface{}) (n int, err error) {
+	return Fscan((*stringReader)(&str), a...)
+}
+
+// Sscanln is similar to Sscan, but stops scanning at a newline and
+// after the final item there must be a newline or EOF.
+func Sscanln(str string, a ...interface{}) (n int, err error) {
+	return Fscanln((*stringReader)(&str), a...)
+}
+
+// Sscanf scans the argument string, storing successive space-separated
+// values into successive arguments as determined by the format.  It
+// returns the number of items successfully parsed.
+func Sscanf(str string, format string, a ...interface{}) (n int, err error) {
+	return Fscanf((*stringReader)(&str), format, a...)
+}
+
+// Fscan scans text read from r, storing successive space-separated
+// values into successive arguments.  Newlines count as space.  It
+// returns the number of items successfully scanned.  If that is less
+// than the number of arguments, err will report why.
+func Fscan(r io.Reader, a ...interface{}) (n int, err error) {
+	s, old := newScanState(r, true, false)
+	n, err = s.doScan(a)
+	s.free(old)
+	return
+}
+
+// Fscanln is similar to Fscan, but stops scanning at a newline and
+// after the final item there must be a newline or EOF.
+func Fscanln(r io.Reader, a ...interface{}) (n int, err error) {
+	s, old := newScanState(r, false, true)
+	n, err = s.doScan(a)
+	s.free(old)
+	return
+}
+
+// Fscanf scans text read from r, storing successive space-separated
+// values into successive arguments as determined by the format.  It
+// returns the number of items successfully parsed.
+func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error) {
+	s, old := newScanState(r, false, false)
+	n, err = s.doScanf(format, a)
+	s.free(old)
+	return
+}
+
+// scanError represents an error generated by the scanning software.
+// It's used as a unique signature to identify such errors when recovering.
+type scanError struct {
+	err error
+}
+
+const eof = -1
+
+// ss is the internal implementation of ScanState.
+type ss struct {
+	rr       io.RuneReader // where to read input
+	buf      buffer        // token accumulator
+	peekRune rune          // one-rune lookahead
+	prevRune rune          // last rune returned by ReadRune
+	count    int           // runes consumed so far.
+	atEOF    bool          // already read EOF
+	ssave
+}
+
+// ssave holds the parts of ss that need to be
+// saved and restored on recursive scans.
+type ssave struct {
+	validSave bool // is or was a part of an actual ss.
+	nlIsEnd   bool // whether newline terminates scan
+	nlIsSpace bool // whether newline counts as white space
+	argLimit  int  // max value of ss.count for this arg; argLimit <= limit
+	limit     int  // max value of ss.count.
+	maxWid    int  // width of this arg.
+}
+
+// The Read method is only in ScanState so that ScanState
+// satisfies io.Reader. It will never be called when used as
+// intended, so there is no need to make it actually work.
+func (s *ss) Read(buf []byte) (n int, err error) {
+	return 0, errors.New("ScanState's Read should not be called. Use ReadRune")
+}
+
+func (s *ss) ReadRune() (r rune, size int, err error) {
+	if s.peekRune >= 0 {
+		s.count++
+		r = s.peekRune
+		size = utf8.RuneLen(r)
+		s.prevRune = r
+		s.peekRune = -1
+		return
+	}
+	if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.argLimit {
+		err = io.EOF
+		return
+	}
+
+	r, size, err = s.rr.ReadRune()
+	if err == nil {
+		s.count++
+		s.prevRune = r
+	} else if err == io.EOF {
+		s.atEOF = true
+	}
+	return
+}
+
+func (s *ss) Width() (wid int, ok bool) {
+	if s.maxWid == hugeWid {
+		return 0, false
+	}
+	return s.maxWid, true
+}
+
+// The public method returns an error; this private one panics.
+// If getRune reaches EOF, the return value is EOF (-1).
+func (s *ss) getRune() (r rune) {
+	r, _, err := s.ReadRune()
+	if err != nil {
+		if err == io.EOF {
+			return eof
+		}
+		s.error(err)
+	}
+	return
+}
+
+// mustReadRune turns io.EOF into a panic(io.ErrUnexpectedEOF).
+// It is called in cases such as string scanning where an EOF is a
+// syntax error.
+func (s *ss) mustReadRune() (r rune) {
+	r = s.getRune()
+	if r == eof {
+		s.error(io.ErrUnexpectedEOF)
+	}
+	return
+}
+
+func (s *ss) UnreadRune() error {
+	if u, ok := s.rr.(runeUnreader); ok {
+		u.UnreadRune()
+	} else {
+		s.peekRune = s.prevRune
+	}
+	s.prevRune = -1
+	s.count--
+	return nil
+}
+
+func (s *ss) error(err error) {
+	panic(scanError{err})
+}
+
+func (s *ss) errorString(err string) {
+	panic(scanError{errors.New(err)})
+}
+
+func (s *ss) Token(skipSpace bool, f func(rune) bool) (tok []byte, err error) {
+	defer func() {
+		if e := recover(); e != nil {
+			if se, ok := e.(scanError); ok {
+				err = se.err
+			} else {
+				panic(e)
+			}
+		}
+	}()
+	if f == nil {
+		f = notSpace
+	}
+	s.buf = s.buf[:0]
+	tok = s.token(skipSpace, f)
+	return
+}
+
+// space is a copy of the unicode.White_Space ranges,
+// to avoid depending on package unicode.
+var space = [][2]uint16{
+	{0x0009, 0x000d},
+	{0x0020, 0x0020},
+	{0x0085, 0x0085},
+	{0x00a0, 0x00a0},
+	{0x1680, 0x1680},
+	{0x2000, 0x200a},
+	{0x2028, 0x2029},
+	{0x202f, 0x202f},
+	{0x205f, 0x205f},
+	{0x3000, 0x3000},
+}
+
+func isSpace(r rune) bool {
+	if r >= 1<<16 {
+		return false
+	}
+	rx := uint16(r)
+	for _, rng := range space {
+		if rx < rng[0] {
+			return false
+		}
+		if rx <= rng[1] {
+			return true
+		}
+	}
+	return false
+}
+
+// notSpace is the default scanning function used in Token.
+func notSpace(r rune) bool {
+	return !isSpace(r)
+}
+
+// SkipSpace provides Scan methods the ability to skip space and newline
+// characters in keeping with the current scanning mode set by format strings
+// and Scan/Scanln.
+func (s *ss) SkipSpace() {
+	s.skipSpace(false)
+}
+
+// readRune is a structure to enable reading UTF-8 encoded code points
+// from an io.Reader.  It is used if the Reader given to the scanner does
+// not already implement io.RuneReader.
+type readRune struct {
+	reader  io.Reader
+	buf     [utf8.UTFMax]byte // used only inside ReadRune
+	pending int               // number of bytes in pendBuf; only >0 for bad UTF-8
+	pendBuf [utf8.UTFMax]byte // bytes left over
+}
+
+// readByte returns the next byte from the input, which may be
+// left over from a previous read if the UTF-8 was ill-formed.
+func (r *readRune) readByte() (b byte, err error) {
+	if r.pending > 0 {
+		b = r.pendBuf[0]
+		copy(r.pendBuf[0:], r.pendBuf[1:])
+		r.pending--
+		return
+	}
+	n, err := io.ReadFull(r.reader, r.pendBuf[0:1])
+	if n != 1 {
+		return 0, err
+	}
+	return r.pendBuf[0], err
+}
+
+// unread saves the bytes for the next read.
+func (r *readRune) unread(buf []byte) {
+	copy(r.pendBuf[r.pending:], buf)
+	r.pending += len(buf)
+}
+
+// ReadRune returns the next UTF-8 encoded code point from the
+// io.Reader inside r.
+func (r *readRune) ReadRune() (rr rune, size int, err error) {
+	r.buf[0], err = r.readByte()
+	if err != nil {
+		return 0, 0, err
+	}
+	if r.buf[0] < utf8.RuneSelf { // fast check for common ASCII case
+		rr = rune(r.buf[0])
+		return
+	}
+	var n int
+	for n = 1; !utf8.FullRune(r.buf[0:n]); n++ {
+		r.buf[n], err = r.readByte()
+		if err != nil {
+			if err == io.EOF {
+				err = nil
+				break
+			}
+			return
+		}
+	}
+	rr, size = utf8.DecodeRune(r.buf[0:n])
+	if size < n { // an error
+		r.unread(r.buf[size:n])
+	}
+	return
+}
+
+var ssFree = sync.Pool{
+	New: func() interface{} { return new(ss) },
+}
+
+// newScanState allocates a new ss struct or grab a cached one.
+func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) {
+	// If the reader is a *ss, then we've got a recursive
+	// call to Scan, so re-use the scan state.
+	s, ok := r.(*ss)
+	if ok {
+		old = s.ssave
+		s.limit = s.argLimit
+		s.nlIsEnd = nlIsEnd || s.nlIsEnd
+		s.nlIsSpace = nlIsSpace
+		return
+	}
+
+	s = ssFree.Get().(*ss)
+	if rr, ok := r.(io.RuneReader); ok {
+		s.rr = rr
+	} else {
+		s.rr = &readRune{reader: r}
+	}
+	s.nlIsSpace = nlIsSpace
+	s.nlIsEnd = nlIsEnd
+	s.prevRune = -1
+	s.peekRune = -1
+	s.atEOF = false
+	s.limit = hugeWid
+	s.argLimit = hugeWid
+	s.maxWid = hugeWid
+	s.validSave = true
+	s.count = 0
+	return
+}
+
+// free saves used ss structs in ssFree; avoid an allocation per invocation.
+func (s *ss) free(old ssave) {
+	// If it was used recursively, just restore the old state.
+	if old.validSave {
+		s.ssave = old
+		return
+	}
+	// Don't hold on to ss structs with large buffers.
+	if cap(s.buf) > 1024 {
+		return
+	}
+	s.buf = s.buf[:0]
+	s.rr = nil
+	ssFree.Put(s)
+}
+
+// skipSpace skips spaces and maybe newlines.
+func (s *ss) skipSpace(stopAtNewline bool) {
+	for {
+		r := s.getRune()
+		if r == eof {
+			return
+		}
+		if r == '\r' && s.peek("\n") {
+			continue
+		}
+		if r == '\n' {
+			if stopAtNewline {
+				break
+			}
+			if s.nlIsSpace {
+				continue
+			}
+			s.errorString("unexpected newline")
+			return
+		}
+		if !isSpace(r) {
+			s.UnreadRune()
+			break
+		}
+	}
+}
+
+// token returns the next space-delimited string from the input.  It
+// skips white space.  For Scanln, it stops at newlines.  For Scan,
+// newlines are treated as spaces.
+func (s *ss) token(skipSpace bool, f func(rune) bool) []byte {
+	if skipSpace {
+		s.skipSpace(false)
+	}
+	// read until white space or newline
+	for {
+		r := s.getRune()
+		if r == eof {
+			break
+		}
+		if !f(r) {
+			s.UnreadRune()
+			break
+		}
+		s.buf.WriteRune(r)
+	}
+	return s.buf
+}
+
+var complexError = errors.New("syntax error scanning complex number")
+var boolError = errors.New("syntax error scanning boolean")
+
+func indexRune(s string, r rune) int {
+	for i, c := range s {
+		if c == r {
+			return i
+		}
+	}
+	return -1
+}
+
+// consume reads the next rune in the input and reports whether it is in the ok string.
+// If accept is true, it puts the character into the input token.
+func (s *ss) consume(ok string, accept bool) bool {
+	r := s.getRune()
+	if r == eof {
+		return false
+	}
+	if indexRune(ok, r) >= 0 {
+		if accept {
+			s.buf.WriteRune(r)
+		}
+		return true
+	}
+	if r != eof && accept {
+		s.UnreadRune()
+	}
+	return false
+}
+
+// peek reports whether the next character is in the ok string, without consuming it.
+func (s *ss) peek(ok string) bool {
+	r := s.getRune()
+	if r != eof {
+		s.UnreadRune()
+	}
+	return indexRune(ok, r) >= 0
+}
+
+func (s *ss) notEOF() {
+	// Guarantee there is data to be read.
+	if r := s.getRune(); r == eof {
+		panic(io.EOF)
+	}
+	s.UnreadRune()
+}
+
+// accept checks the next rune in the input.  If it's a byte (sic) in the string, it puts it in the
+// buffer and returns true. Otherwise it return false.
+func (s *ss) accept(ok string) bool {
+	return s.consume(ok, true)
+}
+
+// okVerb verifies that the verb is present in the list, setting s.err appropriately if not.
+func (s *ss) okVerb(verb rune, okVerbs, typ string) bool {
+	for _, v := range okVerbs {
+		if v == verb {
+			return true
+		}
+	}
+	s.errorString("bad verb %" + string(verb) + " for " + typ)
+	return false
+}
+
+// scanBool returns the value of the boolean represented by the next token.
+func (s *ss) scanBool(verb rune) bool {
+	s.skipSpace(false)
+	s.notEOF()
+	if !s.okVerb(verb, "tv", "boolean") {
+		return false
+	}
+	// Syntax-checking a boolean is annoying.  We're not fastidious about case.
+	switch s.getRune() {
+	case '0':
+		return false
+	case '1':
+		return true
+	case 't', 'T':
+		if s.accept("rR") && (!s.accept("uU") || !s.accept("eE")) {
+			s.error(boolError)
+		}
+		return true
+	case 'f', 'F':
+		if s.accept("aA") && (!s.accept("lL") || !s.accept("sS") || !s.accept("eE")) {
+			s.error(boolError)
+		}
+		return false
+	}
+	return false
+}
+
+// Numerical elements
+const (
+	binaryDigits      = "01"
+	octalDigits       = "01234567"
+	decimalDigits     = "0123456789"
+	hexadecimalDigits = "0123456789aAbBcCdDeEfF"
+	sign              = "+-"
+	period            = "."
+	exponent          = "eEp"
+)
+
+// getBase returns the numeric base represented by the verb and its digit string.
+func (s *ss) getBase(verb rune) (base int, digits string) {
+	s.okVerb(verb, "bdoUxXv", "integer") // sets s.err
+	base = 10
+	digits = decimalDigits
+	switch verb {
+	case 'b':
+		base = 2
+		digits = binaryDigits
+	case 'o':
+		base = 8
+		digits = octalDigits
+	case 'x', 'X', 'U':
+		base = 16
+		digits = hexadecimalDigits
+	}
+	return
+}
+
+// scanNumber returns the numerical string with specified digits starting here.
+func (s *ss) scanNumber(digits string, haveDigits bool) string {
+	if !haveDigits {
+		s.notEOF()
+		if !s.accept(digits) {
+			s.errorString("expected integer")
+		}
+	}
+	for s.accept(digits) {
+	}
+	return string(s.buf)
+}
+
+// scanRune returns the next rune value in the input.
+func (s *ss) scanRune(bitSize int) int64 {
+	s.notEOF()
+	r := int64(s.getRune())
+	n := uint(bitSize)
+	x := (r << (64 - n)) >> (64 - n)
+	if x != r {
+		s.errorString("overflow on character value " + string(r))
+	}
+	return r
+}
+
+// scanBasePrefix reports whether the integer begins with a 0 or 0x,
+// and returns the base, digit string, and whether a zero was found.
+// It is called only if the verb is %v.
+func (s *ss) scanBasePrefix() (base int, digits string, found bool) {
+	if !s.peek("0") {
+		return 10, decimalDigits, false
+	}
+	s.accept("0")
+	found = true // We've put a digit into the token buffer.
+	// Special cases for '0' && '0x'
+	base, digits = 8, octalDigits
+	if s.peek("xX") {
+		s.consume("xX", false)
+		base, digits = 16, hexadecimalDigits
+	}
+	return
+}
+
+// scanInt returns the value of the integer represented by the next
+// token, checking for overflow.  Any error is stored in s.err.
+func (s *ss) scanInt(verb rune, bitSize int) int64 {
+	if verb == 'c' {
+		return s.scanRune(bitSize)
+	}
+	s.skipSpace(false)
+	s.notEOF()
+	base, digits := s.getBase(verb)
+	haveDigits := false
+	if verb == 'U' {
+		if !s.consume("U", false) || !s.consume("+", false) {
+			s.errorString("bad unicode format ")
+		}
+	} else {
+		s.accept(sign) // If there's a sign, it will be left in the token buffer.
+		if verb == 'v' {
+			base, digits, haveDigits = s.scanBasePrefix()
+		}
+	}
+	tok := s.scanNumber(digits, haveDigits)
+	i, err := strconv.ParseInt(tok, base, 64)
+	if err != nil {
+		s.error(err)
+	}
+	n := uint(bitSize)
+	x := (i << (64 - n)) >> (64 - n)
+	if x != i {
+		s.errorString("integer overflow on token " + tok)
+	}
+	return i
+}
+
+// scanUint returns the value of the unsigned integer represented
+// by the next token, checking for overflow.  Any error is stored in s.err.
+func (s *ss) scanUint(verb rune, bitSize int) uint64 {
+	if verb == 'c' {
+		return uint64(s.scanRune(bitSize))
+	}
+	s.skipSpace(false)
+	s.notEOF()
+	base, digits := s.getBase(verb)
+	haveDigits := false
+	if verb == 'U' {
+		if !s.consume("U", false) || !s.consume("+", false) {
+			s.errorString("bad unicode format ")
+		}
+	} else if verb == 'v' {
+		base, digits, haveDigits = s.scanBasePrefix()
+	}
+	tok := s.scanNumber(digits, haveDigits)
+	i, err := strconv.ParseUint(tok, base, 64)
+	if err != nil {
+		s.error(err)
+	}
+	n := uint(bitSize)
+	x := (i << (64 - n)) >> (64 - n)
+	if x != i {
+		s.errorString("unsigned integer overflow on token " + tok)
+	}
+	return i
+}
+
+// floatToken returns the floating-point number starting here, no longer than swid
+// if the width is specified. It's not rigorous about syntax because it doesn't check that
+// we have at least some digits, but Atof will do that.
+func (s *ss) floatToken() string {
+	s.buf = s.buf[:0]
+	// NaN?
+	if s.accept("nN") && s.accept("aA") && s.accept("nN") {
+		return string(s.buf)
+	}
+	// leading sign?
+	s.accept(sign)
+	// Inf?
+	if s.accept("iI") && s.accept("nN") && s.accept("fF") {
+		return string(s.buf)
+	}
+	// digits?
+	for s.accept(decimalDigits) {
+	}
+	// decimal point?
+	if s.accept(period) {
+		// fraction?
+		for s.accept(decimalDigits) {
+		}
+	}
+	// exponent?
+	if s.accept(exponent) {
+		// leading sign?
+		s.accept(sign)
+		// digits?
+		for s.accept(decimalDigits) {
+		}
+	}
+	return string(s.buf)
+}
+
+// complexTokens returns the real and imaginary parts of the complex number starting here.
+// The number might be parenthesized and has the format (N+Ni) where N is a floating-point
+// number and there are no spaces within.
+func (s *ss) complexTokens() (real, imag string) {
+	// TODO: accept N and Ni independently?
+	parens := s.accept("(")
+	real = s.floatToken()
+	s.buf = s.buf[:0]
+	// Must now have a sign.
+	if !s.accept("+-") {
+		s.error(complexError)
+	}
+	// Sign is now in buffer
+	imagSign := string(s.buf)
+	imag = s.floatToken()
+	if !s.accept("i") {
+		s.error(complexError)
+	}
+	if parens && !s.accept(")") {
+		s.error(complexError)
+	}
+	return real, imagSign + imag
+}
+
+// convertFloat converts the string to a float64value.
+func (s *ss) convertFloat(str string, n int) float64 {
+	if p := indexRune(str, 'p'); p >= 0 {
+		// Atof doesn't handle power-of-2 exponents,
+		// but they're easy to evaluate.
+		f, err := strconv.ParseFloat(str[:p], n)
+		if err != nil {
+			// Put full string into error.
+			if e, ok := err.(*strconv.NumError); ok {
+				e.Num = str
+			}
+			s.error(err)
+		}
+		m, err := strconv.Atoi(str[p+1:])
+		if err != nil {
+			// Put full string into error.
+			if e, ok := err.(*strconv.NumError); ok {
+				e.Num = str
+			}
+			s.error(err)
+		}
+		return math.Ldexp(f, m)
+	}
+	f, err := strconv.ParseFloat(str, n)
+	if err != nil {
+		s.error(err)
+	}
+	return f
+}
+
+// convertComplex converts the next token to a complex128 value.
+// The atof argument is a type-specific reader for the underlying type.
+// If we're reading complex64, atof will parse float32s and convert them
+// to float64's to avoid reproducing this code for each complex type.
+func (s *ss) scanComplex(verb rune, n int) complex128 {
+	if !s.okVerb(verb, floatVerbs, "complex") {
+		return 0
+	}
+	s.skipSpace(false)
+	s.notEOF()
+	sreal, simag := s.complexTokens()
+	real := s.convertFloat(sreal, n/2)
+	imag := s.convertFloat(simag, n/2)
+	return complex(real, imag)
+}
+
+// convertString returns the string represented by the next input characters.
+// The format of the input is determined by the verb.
+func (s *ss) convertString(verb rune) (str string) {
+	if !s.okVerb(verb, "svqx", "string") {
+		return ""
+	}
+	s.skipSpace(false)
+	s.notEOF()
+	switch verb {
+	case 'q':
+		str = s.quotedString()
+	case 'x':
+		str = s.hexString()
+	default:
+		str = string(s.token(true, notSpace)) // %s and %v just return the next word
+	}
+	return
+}
+
+// quotedString returns the double- or back-quoted string represented by the next input characters.
+func (s *ss) quotedString() string {
+	s.notEOF()
+	quote := s.getRune()
+	switch quote {
+	case '`':
+		// Back-quoted: Anything goes until EOF or back quote.
+		for {
+			r := s.mustReadRune()
+			if r == quote {
+				break
+			}
+			s.buf.WriteRune(r)
+		}
+		return string(s.buf)
+	case '"':
+		// Double-quoted: Include the quotes and let strconv.Unquote do the backslash escapes.
+		s.buf.WriteRune(quote)
+		for {
+			r := s.mustReadRune()
+			s.buf.WriteRune(r)
+			if r == '\\' {
+				// In a legal backslash escape, no matter how long, only the character
+				// immediately after the escape can itself be a backslash or quote.
+				// Thus we only need to protect the first character after the backslash.
+				s.buf.WriteRune(s.mustReadRune())
+			} else if r == '"' {
+				break
+			}
+		}
+		result, err := strconv.Unquote(string(s.buf))
+		if err != nil {
+			s.error(err)
+		}
+		return result
+	default:
+		s.errorString("expected quoted string")
+	}
+	return ""
+}
+
+// hexDigit returns the value of the hexadecimal digit
+func (s *ss) hexDigit(d rune) int {
+	digit := int(d)
+	switch digit {
+	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+		return digit - '0'
+	case 'a', 'b', 'c', 'd', 'e', 'f':
+		return 10 + digit - 'a'
+	case 'A', 'B', 'C', 'D', 'E', 'F':
+		return 10 + digit - 'A'
+	}
+	s.errorString("illegal hex digit")
+	return 0
+}
+
+// hexByte returns the next hex-encoded (two-character) byte from the input.
+// There must be either two hexadecimal digits or a space character in the input.
+func (s *ss) hexByte() (b byte, ok bool) {
+	rune1 := s.getRune()
+	if rune1 == eof {
+		return
+	}
+	if isSpace(rune1) {
+		s.UnreadRune()
+		return
+	}
+	rune2 := s.mustReadRune()
+	return byte(s.hexDigit(rune1)<<4 | s.hexDigit(rune2)), true
+}
+
+// hexString returns the space-delimited hexpair-encoded string.
+func (s *ss) hexString() string {
+	s.notEOF()
+	for {
+		b, ok := s.hexByte()
+		if !ok {
+			break
+		}
+		s.buf.WriteByte(b)
+	}
+	if len(s.buf) == 0 {
+		s.errorString("no hex data for %x string")
+		return ""
+	}
+	return string(s.buf)
+}
+
+const floatVerbs = "beEfFgGv"
+
+const hugeWid = 1 << 30
+
+// scanOne scans a single value, deriving the scanner from the type of the argument.
+func (s *ss) scanOne(verb rune, arg interface{}) {
+	s.buf = s.buf[:0]
+	var err error
+	// If the parameter has its own Scan method, use that.
+	if v, ok := arg.(Scanner); ok {
+		err = v.Scan(s, verb)
+		if err != nil {
+			if err == io.EOF {
+				err = io.ErrUnexpectedEOF
+			}
+			s.error(err)
+		}
+		return
+	}
+
+	switch v := arg.(type) {
+	case *bool:
+		*v = s.scanBool(verb)
+	case *complex64:
+		*v = complex64(s.scanComplex(verb, 64))
+	case *complex128:
+		*v = s.scanComplex(verb, 128)
+	case *int:
+		*v = int(s.scanInt(verb, intBits))
+	case *int8:
+		*v = int8(s.scanInt(verb, 8))
+	case *int16:
+		*v = int16(s.scanInt(verb, 16))
+	case *int32:
+		*v = int32(s.scanInt(verb, 32))
+	case *int64:
+		*v = s.scanInt(verb, 64)
+	case *uint:
+		*v = uint(s.scanUint(verb, intBits))
+	case *uint8:
+		*v = uint8(s.scanUint(verb, 8))
+	case *uint16:
+		*v = uint16(s.scanUint(verb, 16))
+	case *uint32:
+		*v = uint32(s.scanUint(verb, 32))
+	case *uint64:
+		*v = s.scanUint(verb, 64)
+	case *uintptr:
+		*v = uintptr(s.scanUint(verb, uintptrBits))
+	// Floats are tricky because you want to scan in the precision of the result, not
+	// scan in high precision and convert, in order to preserve the correct error condition.
+	case *float32:
+		if s.okVerb(verb, floatVerbs, "float32") {
+			s.skipSpace(false)
+			s.notEOF()
+			*v = float32(s.convertFloat(s.floatToken(), 32))
+		}
+	case *float64:
+		if s.okVerb(verb, floatVerbs, "float64") {
+			s.skipSpace(false)
+			s.notEOF()
+			*v = s.convertFloat(s.floatToken(), 64)
+		}
+	case *string:
+		*v = s.convertString(verb)
+	case *[]byte:
+		// We scan to string and convert so we get a copy of the data.
+		// If we scanned to bytes, the slice would point at the buffer.
+		*v = []byte(s.convertString(verb))
+	default:
+		val := reflect.ValueOf(v)
+		ptr := val
+		if ptr.Kind() != reflect.Ptr {
+			s.errorString("type not a pointer: " + val.Type().String())
+			return
+		}
+		switch v := ptr.Elem(); v.Kind() {
+		case reflect.Bool:
+			v.SetBool(s.scanBool(verb))
+		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+			v.SetInt(s.scanInt(verb, v.Type().Bits()))
+		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+			v.SetUint(s.scanUint(verb, v.Type().Bits()))
+		case reflect.String:
+			v.SetString(s.convertString(verb))
+		case reflect.Slice:
+			// For now, can only handle (renamed) []byte.
+			typ := v.Type()
+			if typ.Elem().Kind() != reflect.Uint8 {
+				s.errorString("can't scan type: " + val.Type().String())
+			}
+			str := s.convertString(verb)
+			v.Set(reflect.MakeSlice(typ, len(str), len(str)))
+			for i := 0; i < len(str); i++ {
+				v.Index(i).SetUint(uint64(str[i]))
+			}
+		case reflect.Float32, reflect.Float64:
+			s.skipSpace(false)
+			s.notEOF()
+			v.SetFloat(s.convertFloat(s.floatToken(), v.Type().Bits()))
+		case reflect.Complex64, reflect.Complex128:
+			v.SetComplex(s.scanComplex(verb, v.Type().Bits()))
+		default:
+			s.errorString("can't scan type: " + val.Type().String())
+		}
+	}
+}
+
+// errorHandler turns local panics into error returns.
+func errorHandler(errp *error) {
+	if e := recover(); e != nil {
+		if se, ok := e.(scanError); ok { // catch local error
+			*errp = se.err
+		} else if eof, ok := e.(error); ok && eof == io.EOF { // out of input
+			*errp = eof
+		} else {
+			panic(e)
+		}
+	}
+}
+
+// doScan does the real work for scanning without a format string.
+func (s *ss) doScan(a []interface{}) (numProcessed int, err error) {
+	defer errorHandler(&err)
+	for _, arg := range a {
+		s.scanOne('v', arg)
+		numProcessed++
+	}
+	// Check for newline if required.
+	if !s.nlIsSpace {
+		for {
+			r := s.getRune()
+			if r == '\n' || r == eof {
+				break
+			}
+			if !isSpace(r) {
+				s.errorString("expected newline")
+				break
+			}
+		}
+	}
+	return
+}
+
+// advance determines whether the next characters in the input match
+// those of the format.  It returns the number of bytes (sic) consumed
+// in the format. Newlines included, all runs of space characters in
+// either input or format behave as a single space. This routine also
+// handles the %% case.  If the return value is zero, either format
+// starts with a % (with no following %) or the input is empty.
+// If it is negative, the input did not match the string.
+func (s *ss) advance(format string) (i int) {
+	for i < len(format) {
+		fmtc, w := utf8.DecodeRuneInString(format[i:])
+		if fmtc == '%' {
+			// %% acts like a real percent
+			nextc, _ := utf8.DecodeRuneInString(format[i+w:]) // will not match % if string is empty
+			if nextc != '%' {
+				return
+			}
+			i += w // skip the first %
+		}
+		sawSpace := false
+		for isSpace(fmtc) && i < len(format) {
+			sawSpace = true
+			i += w
+			fmtc, w = utf8.DecodeRuneInString(format[i:])
+		}
+		if sawSpace {
+			// There was space in the format, so there should be space (EOF)
+			// in the input.
+			inputc := s.getRune()
+			if inputc == eof || inputc == '\n' {
+				// If we've reached a newline, stop now; don't read ahead.
+				return
+			}
+			if !isSpace(inputc) {
+				// Space in format but not in input: error
+				s.errorString("expected space in input to match format")
+			}
+			s.skipSpace(true)
+			continue
+		}
+		inputc := s.mustReadRune()
+		if fmtc != inputc {
+			s.UnreadRune()
+			return -1
+		}
+		i += w
+	}
+	return
+}
+
+// doScanf does the real work when scanning with a format string.
+//  At the moment, it handles only pointers to basic types.
+func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err error) {
+	defer errorHandler(&err)
+	end := len(format) - 1
+	// We process one item per non-trivial format
+	for i := 0; i <= end; {
+		w := s.advance(format[i:])
+		if w > 0 {
+			i += w
+			continue
+		}
+		// Either we failed to advance, we have a percent character, or we ran out of input.
+		if format[i] != '%' {
+			// Can't advance format.  Why not?
+			if w < 0 {
+				s.errorString("input does not match format")
+			}
+			// Otherwise at EOF; "too many operands" error handled below
+			break
+		}
+		i++ // % is one byte
+
+		// do we have 20 (width)?
+		var widPresent bool
+		s.maxWid, widPresent, i = parsenum(format, i, end)
+		if !widPresent {
+			s.maxWid = hugeWid
+		}
+		s.argLimit = s.limit
+		if f := s.count + s.maxWid; f < s.argLimit {
+			s.argLimit = f
+		}
+
+		c, w := utf8.DecodeRuneInString(format[i:])
+		i += w
+
+		if numProcessed >= len(a) { // out of operands
+			s.errorString("too few operands for format %" + format[i-w:])
+			break
+		}
+		arg := a[numProcessed]
+
+		s.scanOne(c, arg)
+		numProcessed++
+		s.argLimit = s.limit
+	}
+	if numProcessed < len(a) {
+		s.errorString("too many operands")
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/fmt/scan_test.go b/third_party/gofrontend/libgo/go/fmt/scan_test.go
new file mode 100644
index 0000000..d903f0c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/fmt/scan_test.go
@@ -0,0 +1,960 @@
+// 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 fmt_test
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	. "fmt"
+	"io"
+	"math"
+	"reflect"
+	"regexp"
+	"strings"
+	"testing"
+	"unicode/utf8"
+)
+
+type ScanTest struct {
+	text string
+	in   interface{}
+	out  interface{}
+}
+
+type ScanfTest struct {
+	format string
+	text   string
+	in     interface{}
+	out    interface{}
+}
+
+type ScanfMultiTest struct {
+	format string
+	text   string
+	in     []interface{}
+	out    []interface{}
+	err    string
+}
+
+var (
+	boolVal              bool
+	intVal               int
+	int8Val              int8
+	int16Val             int16
+	int32Val             int32
+	int64Val             int64
+	uintVal              uint
+	uint8Val             uint8
+	uint16Val            uint16
+	uint32Val            uint32
+	uint64Val            uint64
+	float32Val           float32
+	float64Val           float64
+	stringVal            string
+	bytesVal             []byte
+	runeVal              rune
+	complex64Val         complex64
+	complex128Val        complex128
+	renamedBoolVal       renamedBool
+	renamedIntVal        renamedInt
+	renamedInt8Val       renamedInt8
+	renamedInt16Val      renamedInt16
+	renamedInt32Val      renamedInt32
+	renamedInt64Val      renamedInt64
+	renamedUintVal       renamedUint
+	renamedUint8Val      renamedUint8
+	renamedUint16Val     renamedUint16
+	renamedUint32Val     renamedUint32
+	renamedUint64Val     renamedUint64
+	renamedUintptrVal    renamedUintptr
+	renamedStringVal     renamedString
+	renamedBytesVal      renamedBytes
+	renamedFloat32Val    renamedFloat32
+	renamedFloat64Val    renamedFloat64
+	renamedComplex64Val  renamedComplex64
+	renamedComplex128Val renamedComplex128
+)
+
+type FloatTest struct {
+	text string
+	in   float64
+	out  float64
+}
+
+// Xs accepts any non-empty run of the verb character
+type Xs string
+
+func (x *Xs) Scan(state ScanState, verb rune) error {
+	tok, err := state.Token(true, func(r rune) bool { return r == verb })
+	if err != nil {
+		return err
+	}
+	s := string(tok)
+	if !regexp.MustCompile("^" + string(verb) + "+$").MatchString(s) {
+		return errors.New("syntax error for xs")
+	}
+	*x = Xs(s)
+	return nil
+}
+
+var xVal Xs
+
+// IntString accepts an integer followed immediately by a string.
+// It tests the embedding of a scan within a scan.
+type IntString struct {
+	i int
+	s string
+}
+
+func (s *IntString) Scan(state ScanState, verb rune) error {
+	if _, err := Fscan(state, &s.i); err != nil {
+		return err
+	}
+
+	tok, err := state.Token(true, nil)
+	if err != nil {
+		return err
+	}
+	s.s = string(tok)
+	return nil
+}
+
+var intStringVal IntString
+
+// myStringReader implements Read but not ReadRune, allowing us to test our readRune wrapper
+// type that creates something that can read runes given only Read().
+type myStringReader struct {
+	r *strings.Reader
+}
+
+func (s *myStringReader) Read(p []byte) (n int, err error) {
+	return s.r.Read(p)
+}
+
+func newReader(s string) *myStringReader {
+	return &myStringReader{strings.NewReader(s)}
+}
+
+var scanTests = []ScanTest{
+	// Basic types
+	{"T\n", &boolVal, true},  // boolean test vals toggle to be sure they are written
+	{"F\n", &boolVal, false}, // restored to zero value
+	{"21\n", &intVal, 21},
+	{"0\n", &intVal, 0},
+	{"000\n", &intVal, 0},
+	{"0x10\n", &intVal, 0x10},
+	{"-0x10\n", &intVal, -0x10},
+	{"0377\n", &intVal, 0377},
+	{"-0377\n", &intVal, -0377},
+	{"0\n", &uintVal, uint(0)},
+	{"000\n", &uintVal, uint(0)},
+	{"0x10\n", &uintVal, uint(0x10)},
+	{"0377\n", &uintVal, uint(0377)},
+	{"22\n", &int8Val, int8(22)},
+	{"23\n", &int16Val, int16(23)},
+	{"24\n", &int32Val, int32(24)},
+	{"25\n", &int64Val, int64(25)},
+	{"127\n", &int8Val, int8(127)},
+	{"-21\n", &intVal, -21},
+	{"-22\n", &int8Val, int8(-22)},
+	{"-23\n", &int16Val, int16(-23)},
+	{"-24\n", &int32Val, int32(-24)},
+	{"-25\n", &int64Val, int64(-25)},
+	{"-128\n", &int8Val, int8(-128)},
+	{"+21\n", &intVal, +21},
+	{"+22\n", &int8Val, int8(+22)},
+	{"+23\n", &int16Val, int16(+23)},
+	{"+24\n", &int32Val, int32(+24)},
+	{"+25\n", &int64Val, int64(+25)},
+	{"+127\n", &int8Val, int8(+127)},
+	{"26\n", &uintVal, uint(26)},
+	{"27\n", &uint8Val, uint8(27)},
+	{"28\n", &uint16Val, uint16(28)},
+	{"29\n", &uint32Val, uint32(29)},
+	{"30\n", &uint64Val, uint64(30)},
+	{"255\n", &uint8Val, uint8(255)},
+	{"32767\n", &int16Val, int16(32767)},
+	{"2.3\n", &float64Val, 2.3},
+	{"2.3e1\n", &float32Val, float32(2.3e1)},
+	{"2.3e2\n", &float64Val, 2.3e2},
+	{"2.3p2\n", &float64Val, 2.3 * 4},
+	{"2.3p+2\n", &float64Val, 2.3 * 4},
+	{"2.3p+66\n", &float64Val, 2.3 * (1 << 32) * (1 << 32) * 4},
+	{"2.3p-66\n", &float64Val, 2.3 / ((1 << 32) * (1 << 32) * 4)},
+	{"2.35\n", &stringVal, "2.35"},
+	{"2345678\n", &bytesVal, []byte("2345678")},
+	{"(3.4e1-2i)\n", &complex128Val, 3.4e1 - 2i},
+	{"-3.45e1-3i\n", &complex64Val, complex64(-3.45e1 - 3i)},
+	{"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)},
+	{"hello\n", &stringVal, "hello"},
+
+	// Carriage-return followed by newline. (We treat \r\n as \n always.)
+	{"hello\r\n", &stringVal, "hello"},
+	{"27\r\n", &uint8Val, uint8(27)},
+
+	// Renamed types
+	{"true\n", &renamedBoolVal, renamedBool(true)},
+	{"F\n", &renamedBoolVal, renamedBool(false)},
+	{"101\n", &renamedIntVal, renamedInt(101)},
+	{"102\n", &renamedIntVal, renamedInt(102)},
+	{"103\n", &renamedUintVal, renamedUint(103)},
+	{"104\n", &renamedUintVal, renamedUint(104)},
+	{"105\n", &renamedInt8Val, renamedInt8(105)},
+	{"106\n", &renamedInt16Val, renamedInt16(106)},
+	{"107\n", &renamedInt32Val, renamedInt32(107)},
+	{"108\n", &renamedInt64Val, renamedInt64(108)},
+	{"109\n", &renamedUint8Val, renamedUint8(109)},
+	{"110\n", &renamedUint16Val, renamedUint16(110)},
+	{"111\n", &renamedUint32Val, renamedUint32(111)},
+	{"112\n", &renamedUint64Val, renamedUint64(112)},
+	{"113\n", &renamedUintptrVal, renamedUintptr(113)},
+	{"114\n", &renamedStringVal, renamedString("114")},
+	{"115\n", &renamedBytesVal, renamedBytes([]byte("115"))},
+
+	// Custom scanners.
+	{"  vvv ", &xVal, Xs("vvv")},
+	{" 1234hello", &intStringVal, IntString{1234, "hello"}},
+
+	// Fixed bugs
+	{"2147483648\n", &int64Val, int64(2147483648)}, // was: integer overflow
+}
+
+var scanfTests = []ScanfTest{
+	{"%v", "TRUE\n", &boolVal, true},
+	{"%t", "false\n", &boolVal, false},
+	{"%v", "-71\n", &intVal, -71},
+	{"%v", "0377\n", &intVal, 0377},
+	{"%v", "0x44\n", &intVal, 0x44},
+	{"%d", "72\n", &intVal, 72},
+	{"%c", "a\n", &runeVal, 'a'},
+	{"%c", "\u5072\n", &runeVal, '\u5072'},
+	{"%c", "\u1234\n", &runeVal, '\u1234'},
+	{"%d", "73\n", &int8Val, int8(73)},
+	{"%d", "+74\n", &int16Val, int16(74)},
+	{"%d", "75\n", &int32Val, int32(75)},
+	{"%d", "76\n", &int64Val, int64(76)},
+	{"%b", "1001001\n", &intVal, 73},
+	{"%o", "075\n", &intVal, 075},
+	{"%x", "a75\n", &intVal, 0xa75},
+	{"%v", "71\n", &uintVal, uint(71)},
+	{"%d", "72\n", &uintVal, uint(72)},
+	{"%d", "73\n", &uint8Val, uint8(73)},
+	{"%d", "74\n", &uint16Val, uint16(74)},
+	{"%d", "75\n", &uint32Val, uint32(75)},
+	{"%d", "76\n", &uint64Val, uint64(76)},
+	{"%b", "1001001\n", &uintVal, uint(73)},
+	{"%o", "075\n", &uintVal, uint(075)},
+	{"%x", "a75\n", &uintVal, uint(0xa75)},
+	{"%x", "A75\n", &uintVal, uint(0xa75)},
+	{"%U", "U+1234\n", &intVal, int(0x1234)},
+	{"%U", "U+4567\n", &uintVal, uint(0x4567)},
+
+	// Strings
+	{"%s", "using-%s\n", &stringVal, "using-%s"},
+	{"%x", "7573696e672d2578\n", &stringVal, "using-%x"},
+	{"%q", `"quoted\twith\\do\u0075bl\x65s"` + "\n", &stringVal, "quoted\twith\\doubles"},
+	{"%q", "`quoted with backs`\n", &stringVal, "quoted with backs"},
+
+	// Byte slices
+	{"%s", "bytes-%s\n", &bytesVal, []byte("bytes-%s")},
+	{"%x", "62797465732d2578\n", &bytesVal, []byte("bytes-%x")},
+	{"%q", `"bytes\rwith\vdo\u0075bl\x65s"` + "\n", &bytesVal, []byte("bytes\rwith\vdoubles")},
+	{"%q", "`bytes with backs`\n", &bytesVal, []byte("bytes with backs")},
+
+	// Renamed types
+	{"%v\n", "true\n", &renamedBoolVal, renamedBool(true)},
+	{"%t\n", "F\n", &renamedBoolVal, renamedBool(false)},
+	{"%v", "101\n", &renamedIntVal, renamedInt(101)},
+	{"%c", "\u0101\n", &renamedIntVal, renamedInt('\u0101')},
+	{"%o", "0146\n", &renamedIntVal, renamedInt(102)},
+	{"%v", "103\n", &renamedUintVal, renamedUint(103)},
+	{"%d", "104\n", &renamedUintVal, renamedUint(104)},
+	{"%d", "105\n", &renamedInt8Val, renamedInt8(105)},
+	{"%d", "106\n", &renamedInt16Val, renamedInt16(106)},
+	{"%d", "107\n", &renamedInt32Val, renamedInt32(107)},
+	{"%d", "108\n", &renamedInt64Val, renamedInt64(108)},
+	{"%x", "6D\n", &renamedUint8Val, renamedUint8(109)},
+	{"%o", "0156\n", &renamedUint16Val, renamedUint16(110)},
+	{"%d", "111\n", &renamedUint32Val, renamedUint32(111)},
+	{"%d", "112\n", &renamedUint64Val, renamedUint64(112)},
+	{"%d", "113\n", &renamedUintptrVal, renamedUintptr(113)},
+	{"%s", "114\n", &renamedStringVal, renamedString("114")},
+	{"%q", "\"1155\"\n", &renamedBytesVal, renamedBytes([]byte("1155"))},
+	{"%g", "116e1\n", &renamedFloat32Val, renamedFloat32(116e1)},
+	{"%g", "-11.7e+1", &renamedFloat64Val, renamedFloat64(-11.7e+1)},
+	{"%g", "11+6e1i\n", &renamedComplex64Val, renamedComplex64(11 + 6e1i)},
+	{"%g", "-11.+7e+1i", &renamedComplex128Val, renamedComplex128(-11. + 7e+1i)},
+
+	// Interesting formats
+	{"here is\tthe value:%d", "here is   the\tvalue:118\n", &intVal, 118},
+	{"%% %%:%d", "% %:119\n", &intVal, 119},
+
+	// Corner cases
+	{"%x", "FFFFFFFF\n", &uint32Val, uint32(0xFFFFFFFF)},
+
+	// Custom scanner.
+	{"%s", "  sss ", &xVal, Xs("sss")},
+	{"%2s", "sssss", &xVal, Xs("ss")},
+
+	// Fixed bugs
+	{"%d\n", "27\n", &intVal, 27},  // ok
+	{"%d\n", "28 \n", &intVal, 28}, // was: "unexpected newline"
+	{"%v", "0", &intVal, 0},        // was: "EOF"; 0 was taken as base prefix and not counted.
+	{"%v", "0", &uintVal, uint(0)}, // was: "EOF"; 0 was taken as base prefix and not counted.
+}
+
+var overflowTests = []ScanTest{
+	{"128", &int8Val, 0},
+	{"32768", &int16Val, 0},
+	{"-129", &int8Val, 0},
+	{"-32769", &int16Val, 0},
+	{"256", &uint8Val, 0},
+	{"65536", &uint16Val, 0},
+	{"1e100", &float32Val, 0},
+	{"1e500", &float64Val, 0},
+	{"(1e100+0i)", &complex64Val, 0},
+	{"(1+1e100i)", &complex64Val, 0},
+	{"(1-1e500i)", &complex128Val, 0},
+}
+
+var truth bool
+var i, j, k int
+var f float64
+var s, t string
+var c complex128
+var x, y Xs
+var z IntString
+var r1, r2, r3 rune
+
+var multiTests = []ScanfMultiTest{
+	{"", "", []interface{}{}, []interface{}{}, ""},
+	{"%d", "23", args(&i), args(23), ""},
+	{"%2s%3s", "22333", args(&s, &t), args("22", "333"), ""},
+	{"%2d%3d", "44555", args(&i, &j), args(44, 555), ""},
+	{"%2d.%3d", "66.777", args(&i, &j), args(66, 777), ""},
+	{"%d, %d", "23, 18", args(&i, &j), args(23, 18), ""},
+	{"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""},
+	{"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""},
+	{"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""},
+	{"%c%c%c", "2\u50c2X", args(&r1, &r2, &r3), args('2', '\u50c2', 'X'), ""},
+
+	// Custom scanners.
+	{"%e%f", "eefffff", args(&x, &y), args(Xs("ee"), Xs("fffff")), ""},
+	{"%4v%s", "12abcd", args(&z, &s), args(IntString{12, "ab"}, "cd"), ""},
+
+	// Errors
+	{"%t", "23 18", args(&i), nil, "bad verb"},
+	{"%d %d %d", "23 18", args(&i, &j), args(23, 18), "too few operands"},
+	{"%d %d", "23 18 27", args(&i, &j, &k), args(23, 18), "too many operands"},
+	{"%c", "\u0100", args(&int8Val), nil, "overflow"},
+	{"X%d", "10X", args(&intVal), nil, "input does not match format"},
+
+	// Bad UTF-8: should see every byte.
+	{"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""},
+
+	// Fixed bugs
+	{"%v%v", "FALSE23", args(&truth, &i), args(false, 23), ""},
+}
+
+func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, error)) {
+	for _, test := range scanTests {
+		var r io.Reader
+		if name == "StringReader" {
+			r = strings.NewReader(test.text)
+		} else {
+			r = newReader(test.text)
+		}
+		n, err := scan(r, test.in)
+		if err != nil {
+			m := ""
+			if n > 0 {
+				m = Sprintf(" (%d fields ok)", n)
+			}
+			t.Errorf("%s got error scanning %q: %s%s", name, test.text, err, m)
+			continue
+		}
+		if n != 1 {
+			t.Errorf("%s count error on entry %q: got %d", name, test.text, n)
+			continue
+		}
+		// The incoming value may be a pointer
+		v := reflect.ValueOf(test.in)
+		if p := v; p.Kind() == reflect.Ptr {
+			v = p.Elem()
+		}
+		val := v.Interface()
+		if !reflect.DeepEqual(val, test.out) {
+			t.Errorf("%s scanning %q: expected %#v got %#v, type %T", name, test.text, test.out, val, val)
+		}
+	}
+}
+
+func TestScan(t *testing.T) {
+	testScan("StringReader", t, Fscan)
+}
+
+func TestMyReaderScan(t *testing.T) {
+	testScan("myStringReader", t, Fscan)
+}
+
+func TestScanln(t *testing.T) {
+	testScan("StringReader", t, Fscanln)
+}
+
+func TestMyReaderScanln(t *testing.T) {
+	testScan("myStringReader", t, Fscanln)
+}
+
+func TestScanf(t *testing.T) {
+	for _, test := range scanfTests {
+		n, err := Sscanf(test.text, test.format, test.in)
+		if err != nil {
+			t.Errorf("got error scanning (%q, %q): %s", test.format, test.text, err)
+			continue
+		}
+		if n != 1 {
+			t.Errorf("count error on entry (%q, %q): got %d", test.format, test.text, n)
+			continue
+		}
+		// The incoming value may be a pointer
+		v := reflect.ValueOf(test.in)
+		if p := v; p.Kind() == reflect.Ptr {
+			v = p.Elem()
+		}
+		val := v.Interface()
+		if !reflect.DeepEqual(val, test.out) {
+			t.Errorf("scanning (%q, %q): expected %#v got %#v, type %T", test.format, test.text, test.out, val, val)
+		}
+	}
+}
+
+func TestScanOverflow(t *testing.T) {
+	// different machines and different types report errors with different strings.
+	re := regexp.MustCompile("overflow|too large|out of range|not representable")
+	for _, test := range overflowTests {
+		_, err := Sscan(test.text, test.in)
+		if err == nil {
+			t.Errorf("expected overflow scanning %q", test.text)
+			continue
+		}
+		if !re.MatchString(err.Error()) {
+			t.Errorf("expected overflow error scanning %q: %s", test.text, err)
+		}
+	}
+}
+
+func verifyNaN(str string, t *testing.T) {
+	var f float64
+	var f32 float32
+	var f64 float64
+	text := str + " " + str + " " + str
+	n, err := Fscan(strings.NewReader(text), &f, &f32, &f64)
+	if err != nil {
+		t.Errorf("got error scanning %q: %s", text, err)
+	}
+	if n != 3 {
+		t.Errorf("count error scanning %q: got %d", text, n)
+	}
+	if !math.IsNaN(float64(f)) || !math.IsNaN(float64(f32)) || !math.IsNaN(f64) {
+		t.Errorf("didn't get NaNs scanning %q: got %g %g %g", text, f, f32, f64)
+	}
+}
+
+func TestNaN(t *testing.T) {
+	for _, s := range []string{"nan", "NAN", "NaN"} {
+		verifyNaN(s, t)
+	}
+}
+
+func verifyInf(str string, t *testing.T) {
+	var f float64
+	var f32 float32
+	var f64 float64
+	text := str + " " + str + " " + str
+	n, err := Fscan(strings.NewReader(text), &f, &f32, &f64)
+	if err != nil {
+		t.Errorf("got error scanning %q: %s", text, err)
+	}
+	if n != 3 {
+		t.Errorf("count error scanning %q: got %d", text, n)
+	}
+	sign := 1
+	if str[0] == '-' {
+		sign = -1
+	}
+	if !math.IsInf(float64(f), sign) || !math.IsInf(float64(f32), sign) || !math.IsInf(f64, sign) {
+		t.Errorf("didn't get right Infs scanning %q: got %g %g %g", text, f, f32, f64)
+	}
+}
+
+func TestInf(t *testing.T) {
+	for _, s := range []string{"inf", "+inf", "-inf", "INF", "-INF", "+INF", "Inf", "-Inf", "+Inf"} {
+		verifyInf(s, t)
+	}
+}
+
+func testScanfMulti(name string, t *testing.T) {
+	sliceType := reflect.TypeOf(make([]interface{}, 1))
+	for _, test := range multiTests {
+		var r io.Reader
+		if name == "StringReader" {
+			r = strings.NewReader(test.text)
+		} else {
+			r = newReader(test.text)
+		}
+		n, err := Fscanf(r, test.format, test.in...)
+		if err != nil {
+			if test.err == "" {
+				t.Errorf("got error scanning (%q, %q): %q", test.format, test.text, err)
+			} else if strings.Index(err.Error(), test.err) < 0 {
+				t.Errorf("got wrong error scanning (%q, %q): %q; expected %q", test.format, test.text, err, test.err)
+			}
+			continue
+		}
+		if test.err != "" {
+			t.Errorf("expected error %q error scanning (%q, %q)", test.err, test.format, test.text)
+		}
+		if n != len(test.out) {
+			t.Errorf("count error on entry (%q, %q): expected %d got %d", test.format, test.text, len(test.out), n)
+			continue
+		}
+		// Convert the slice of pointers into a slice of values
+		resultVal := reflect.MakeSlice(sliceType, n, n)
+		for i := 0; i < n; i++ {
+			v := reflect.ValueOf(test.in[i]).Elem()
+			resultVal.Index(i).Set(v)
+		}
+		result := resultVal.Interface()
+		if !reflect.DeepEqual(result, test.out) {
+			t.Errorf("scanning (%q, %q): expected %#v got %#v", test.format, test.text, test.out, result)
+		}
+	}
+}
+
+func TestScanfMulti(t *testing.T) {
+	testScanfMulti("StringReader", t)
+}
+
+func TestMyReaderScanfMulti(t *testing.T) {
+	testScanfMulti("myStringReader", t)
+}
+
+func TestScanMultiple(t *testing.T) {
+	var a int
+	var s string
+	n, err := Sscan("123abc", &a, &s)
+	if n != 2 {
+		t.Errorf("Sscan count error: expected 2: got %d", n)
+	}
+	if err != nil {
+		t.Errorf("Sscan expected no error; got %s", err)
+	}
+	if a != 123 || s != "abc" {
+		t.Errorf("Sscan wrong values: got (%d %q) expected (123 \"abc\")", a, s)
+	}
+	n, err = Sscan("asdf", &s, &a)
+	if n != 1 {
+		t.Errorf("Sscan count error: expected 1: got %d", n)
+	}
+	if err == nil {
+		t.Errorf("Sscan expected error; got none: %s", err)
+	}
+	if s != "asdf" {
+		t.Errorf("Sscan wrong values: got %q expected \"asdf\"", s)
+	}
+}
+
+// Empty strings are not valid input when scanning a string.
+func TestScanEmpty(t *testing.T) {
+	var s1, s2 string
+	n, err := Sscan("abc", &s1, &s2)
+	if n != 1 {
+		t.Errorf("Sscan count error: expected 1: got %d", n)
+	}
+	if err == nil {
+		t.Error("Sscan <one item> expected error; got none")
+	}
+	if s1 != "abc" {
+		t.Errorf("Sscan wrong values: got %q expected \"abc\"", s1)
+	}
+	n, err = Sscan("", &s1, &s2)
+	if n != 0 {
+		t.Errorf("Sscan count error: expected 0: got %d", n)
+	}
+	if err == nil {
+		t.Error("Sscan <empty> expected error; got none")
+	}
+	// Quoted empty string is OK.
+	n, err = Sscanf(`""`, "%q", &s1)
+	if n != 1 {
+		t.Errorf("Sscanf count error: expected 1: got %d", n)
+	}
+	if err != nil {
+		t.Errorf("Sscanf <empty> expected no error with quoted string; got %s", err)
+	}
+}
+
+func TestScanNotPointer(t *testing.T) {
+	r := strings.NewReader("1")
+	var a int
+	_, err := Fscan(r, a)
+	if err == nil {
+		t.Error("expected error scanning non-pointer")
+	} else if strings.Index(err.Error(), "pointer") < 0 {
+		t.Errorf("expected pointer error scanning non-pointer, got: %s", err)
+	}
+}
+
+func TestScanlnNoNewline(t *testing.T) {
+	var a int
+	_, err := Sscanln("1 x\n", &a)
+	if err == nil {
+		t.Error("expected error scanning string missing newline")
+	} else if strings.Index(err.Error(), "newline") < 0 {
+		t.Errorf("expected newline error scanning string missing newline, got: %s", err)
+	}
+}
+
+func TestScanlnWithMiddleNewline(t *testing.T) {
+	r := strings.NewReader("123\n456\n")
+	var a, b int
+	_, err := Fscanln(r, &a, &b)
+	if err == nil {
+		t.Error("expected error scanning string with extra newline")
+	} else if strings.Index(err.Error(), "newline") < 0 {
+		t.Errorf("expected newline error scanning string with extra newline, got: %s", err)
+	}
+}
+
+// eofCounter is a special Reader that counts reads at end of file.
+type eofCounter struct {
+	reader   *strings.Reader
+	eofCount int
+}
+
+func (ec *eofCounter) Read(b []byte) (n int, err error) {
+	n, err = ec.reader.Read(b)
+	if n == 0 {
+		ec.eofCount++
+	}
+	return
+}
+
+// TestEOF verifies that when we scan, we see at most EOF once per call to a
+// Scan function, and then only when it's really an EOF.
+func TestEOF(t *testing.T) {
+	ec := &eofCounter{strings.NewReader("123\n"), 0}
+	var a int
+	n, err := Fscanln(ec, &a)
+	if err != nil {
+		t.Error("unexpected error", err)
+	}
+	if n != 1 {
+		t.Error("expected to scan one item, got", n)
+	}
+	if ec.eofCount != 0 {
+		t.Error("expected zero EOFs", ec.eofCount)
+		ec.eofCount = 0 // reset for next test
+	}
+	n, err = Fscanln(ec, &a)
+	if err == nil {
+		t.Error("expected error scanning empty string")
+	}
+	if n != 0 {
+		t.Error("expected to scan zero items, got", n)
+	}
+	if ec.eofCount != 1 {
+		t.Error("expected one EOF, got", ec.eofCount)
+	}
+}
+
+// TestEOFAtEndOfInput verifies that we see an EOF error if we run out of input.
+// This was a buglet: we used to get "expected integer".
+func TestEOFAtEndOfInput(t *testing.T) {
+	var i, j int
+	n, err := Sscanf("23", "%d %d", &i, &j)
+	if n != 1 || i != 23 {
+		t.Errorf("Sscanf expected one value of 23; got %d %d", n, i)
+	}
+	if err != io.EOF {
+		t.Errorf("Sscanf expected EOF; got %q", err)
+	}
+	n, err = Sscan("234", &i, &j)
+	if n != 1 || i != 234 {
+		t.Errorf("Sscan expected one value of 234; got %d %d", n, i)
+	}
+	if err != io.EOF {
+		t.Errorf("Sscan expected EOF; got %q", err)
+	}
+	// Trailing space is tougher.
+	n, err = Sscan("234 ", &i, &j)
+	if n != 1 || i != 234 {
+		t.Errorf("Sscan expected one value of 234; got %d %d", n, i)
+	}
+	if err != io.EOF {
+		t.Errorf("Sscan expected EOF; got %q", err)
+	}
+}
+
+var eofTests = []struct {
+	format string
+	v      interface{}
+}{
+	{"%s", &stringVal},
+	{"%q", &stringVal},
+	{"%x", &stringVal},
+	{"%v", &stringVal},
+	{"%v", &bytesVal},
+	{"%v", &intVal},
+	{"%v", &uintVal},
+	{"%v", &boolVal},
+	{"%v", &float32Val},
+	{"%v", &complex64Val},
+	{"%v", &renamedStringVal},
+	{"%v", &renamedBytesVal},
+	{"%v", &renamedIntVal},
+	{"%v", &renamedUintVal},
+	{"%v", &renamedBoolVal},
+	{"%v", &renamedFloat32Val},
+	{"%v", &renamedComplex64Val},
+}
+
+func TestEOFAllTypes(t *testing.T) {
+	for i, test := range eofTests {
+		if _, err := Sscanf("", test.format, test.v); err != io.EOF {
+			t.Errorf("#%d: %s %T not eof on empty string: %s", i, test.format, test.v, err)
+		}
+		if _, err := Sscanf("   ", test.format, test.v); err != io.EOF {
+			t.Errorf("#%d: %s %T not eof on trailing blanks: %s", i, test.format, test.v, err)
+		}
+	}
+}
+
+// TestUnreadRuneWithBufio verifies that, at least when using bufio, successive
+// calls to Fscan do not lose runes.
+func TestUnreadRuneWithBufio(t *testing.T) {
+	r := bufio.NewReader(strings.NewReader("123αb"))
+	var i int
+	var a string
+	n, err := Fscanf(r, "%d", &i)
+	if n != 1 || err != nil {
+		t.Errorf("reading int expected one item, no errors; got %d %q", n, err)
+	}
+	if i != 123 {
+		t.Errorf("expected 123; got %d", i)
+	}
+	n, err = Fscanf(r, "%s", &a)
+	if n != 1 || err != nil {
+		t.Errorf("reading string expected one item, no errors; got %d %q", n, err)
+	}
+	if a != "αb" {
+		t.Errorf("expected αb; got %q", a)
+	}
+}
+
+type TwoLines string
+
+// Scan attempts to read two lines into the object.  Scanln should prevent this
+// because it stops at newline; Scan and Scanf should be fine.
+func (t *TwoLines) Scan(state ScanState, verb rune) error {
+	chars := make([]rune, 0, 100)
+	for nlCount := 0; nlCount < 2; {
+		c, _, err := state.ReadRune()
+		if err != nil {
+			return err
+		}
+		chars = append(chars, c)
+		if c == '\n' {
+			nlCount++
+		}
+	}
+	*t = TwoLines(string(chars))
+	return nil
+}
+
+func TestMultiLine(t *testing.T) {
+	input := "abc\ndef\n"
+	// Sscan should work
+	var tscan TwoLines
+	n, err := Sscan(input, &tscan)
+	if n != 1 {
+		t.Errorf("Sscan: expected 1 item; got %d", n)
+	}
+	if err != nil {
+		t.Errorf("Sscan: expected no error; got %s", err)
+	}
+	if string(tscan) != input {
+		t.Errorf("Sscan: expected %q; got %q", input, tscan)
+	}
+	// Sscanf should work
+	var tscanf TwoLines
+	n, err = Sscanf(input, "%s", &tscanf)
+	if n != 1 {
+		t.Errorf("Sscanf: expected 1 item; got %d", n)
+	}
+	if err != nil {
+		t.Errorf("Sscanf: expected no error; got %s", err)
+	}
+	if string(tscanf) != input {
+		t.Errorf("Sscanf: expected %q; got %q", input, tscanf)
+	}
+	// Sscanln should not work
+	var tscanln TwoLines
+	n, err = Sscanln(input, &tscanln)
+	if n != 0 {
+		t.Errorf("Sscanln: expected 0 items; got %d: %q", n, tscanln)
+	}
+	if err == nil {
+		t.Error("Sscanln: expected error; got none")
+	} else if err != io.ErrUnexpectedEOF {
+		t.Errorf("Sscanln: expected io.ErrUnexpectedEOF (ha!); got %s", err)
+	}
+}
+
+// simpleReader is a strings.Reader that implements only Read, not ReadRune.
+// Good for testing readahead.
+type simpleReader struct {
+	sr *strings.Reader
+}
+
+func (s *simpleReader) Read(b []byte) (n int, err error) {
+	return s.sr.Read(b)
+}
+
+// TestLineByLineFscanf tests that Fscanf does not read past newline. Issue
+// 3481.
+func TestLineByLineFscanf(t *testing.T) {
+	r := &simpleReader{strings.NewReader("1\n2\n")}
+	var i, j int
+	n, err := Fscanf(r, "%v\n", &i)
+	if n != 1 || err != nil {
+		t.Fatalf("first read: %d %q", n, err)
+	}
+	n, err = Fscanf(r, "%v\n", &j)
+	if n != 1 || err != nil {
+		t.Fatalf("second read: %d %q", n, err)
+	}
+	if i != 1 || j != 2 {
+		t.Errorf("wrong values; wanted 1 2 got %d %d", i, j)
+	}
+}
+
+// RecursiveInt accepts a string matching %d.%d.%d....
+// and parses it into a linked list.
+// It allows us to benchmark recursive descent style scanners.
+type RecursiveInt struct {
+	i    int
+	next *RecursiveInt
+}
+
+func (r *RecursiveInt) Scan(state ScanState, verb rune) (err error) {
+	_, err = Fscan(state, &r.i)
+	if err != nil {
+		return
+	}
+	next := new(RecursiveInt)
+	_, err = Fscanf(state, ".%v", next)
+	if err != nil {
+		if err == io.ErrUnexpectedEOF {
+			err = nil
+		}
+		return
+	}
+	r.next = next
+	return
+}
+
+// scanInts performs the same scanning task as RecursiveInt.Scan
+// but without recurring through scanner, so we can compare
+// performance more directly.
+func scanInts(r *RecursiveInt, b *bytes.Buffer) (err error) {
+	r.next = nil
+	_, err = Fscan(b, &r.i)
+	if err != nil {
+		return
+	}
+	c, _, err := b.ReadRune()
+	if err != nil {
+		if err == io.EOF {
+			err = nil
+		}
+		return
+	}
+	if c != '.' {
+		return
+	}
+	next := new(RecursiveInt)
+	err = scanInts(next, b)
+	if err == nil {
+		r.next = next
+	}
+	return
+}
+
+func makeInts(n int) []byte {
+	var buf bytes.Buffer
+	Fprintf(&buf, "1")
+	for i := 1; i < n; i++ {
+		Fprintf(&buf, ".%d", i+1)
+	}
+	return buf.Bytes()
+}
+
+func TestScanInts(t *testing.T) {
+	testScanInts(t, scanInts)
+	testScanInts(t, func(r *RecursiveInt, b *bytes.Buffer) (err error) {
+		_, err = Fscan(b, r)
+		return
+	})
+}
+
+// 800 is small enough to not overflow the stack when using gccgo on a
+// platform that does not support split stack.
+const intCount = 800
+
+func testScanInts(t *testing.T, scan func(*RecursiveInt, *bytes.Buffer) error) {
+	r := new(RecursiveInt)
+	ints := makeInts(intCount)
+	buf := bytes.NewBuffer(ints)
+	err := scan(r, buf)
+	if err != nil {
+		t.Error("unexpected error", err)
+	}
+	i := 1
+	for ; r != nil; r = r.next {
+		if r.i != i {
+			t.Fatalf("bad scan: expected %d got %d", i, r.i)
+		}
+		i++
+	}
+	if i-1 != intCount {
+		t.Fatalf("bad scan count: expected %d got %d", intCount, i-1)
+	}
+}
+
+func BenchmarkScanInts(b *testing.B) {
+	b.ResetTimer()
+	ints := makeInts(intCount)
+	var r RecursiveInt
+	for i := b.N - 1; i >= 0; i-- {
+		buf := bytes.NewBuffer(ints)
+		b.StartTimer()
+		scanInts(&r, buf)
+		b.StopTimer()
+	}
+}
+
+func BenchmarkScanRecursiveInt(b *testing.B) {
+	b.ResetTimer()
+	ints := makeInts(intCount)
+	var r RecursiveInt
+	for i := b.N - 1; i >= 0; i-- {
+		buf := bytes.NewBuffer(ints)
+		b.StartTimer()
+		Fscan(buf, &r)
+		b.StopTimer()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/fmt/stringer_test.go b/third_party/gofrontend/libgo/go/fmt/stringer_test.go
new file mode 100644
index 0000000..0ca3f52
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/fmt/stringer_test.go
@@ -0,0 +1,61 @@
+// Copyright 2010 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 fmt_test
+
+import (
+	. "fmt"
+	"testing"
+)
+
+type TI int
+type TI8 int8
+type TI16 int16
+type TI32 int32
+type TI64 int64
+type TU uint
+type TU8 uint8
+type TU16 uint16
+type TU32 uint32
+type TU64 uint64
+type TUI uintptr
+type TF float64
+type TF32 float32
+type TF64 float64
+type TB bool
+type TS string
+
+func (v TI) String() string   { return Sprintf("I: %d", int(v)) }
+func (v TI8) String() string  { return Sprintf("I8: %d", int8(v)) }
+func (v TI16) String() string { return Sprintf("I16: %d", int16(v)) }
+func (v TI32) String() string { return Sprintf("I32: %d", int32(v)) }
+func (v TI64) String() string { return Sprintf("I64: %d", int64(v)) }
+func (v TU) String() string   { return Sprintf("U: %d", uint(v)) }
+func (v TU8) String() string  { return Sprintf("U8: %d", uint8(v)) }
+func (v TU16) String() string { return Sprintf("U16: %d", uint16(v)) }
+func (v TU32) String() string { return Sprintf("U32: %d", uint32(v)) }
+func (v TU64) String() string { return Sprintf("U64: %d", uint64(v)) }
+func (v TUI) String() string  { return Sprintf("UI: %d", uintptr(v)) }
+func (v TF) String() string   { return Sprintf("F: %f", float64(v)) }
+func (v TF32) String() string { return Sprintf("F32: %f", float32(v)) }
+func (v TF64) String() string { return Sprintf("F64: %f", float64(v)) }
+func (v TB) String() string   { return Sprintf("B: %t", bool(v)) }
+func (v TS) String() string   { return Sprintf("S: %q", string(v)) }
+
+func check(t *testing.T, got, want string) {
+	if got != want {
+		t.Error(got, "!=", want)
+	}
+}
+
+func TestStringer(t *testing.T) {
+	s := Sprintf("%v %v %v %v %v", TI(0), TI8(1), TI16(2), TI32(3), TI64(4))
+	check(t, s, "I: 0 I8: 1 I16: 2 I32: 3 I64: 4")
+	s = Sprintf("%v %v %v %v %v %v", TU(5), TU8(6), TU16(7), TU32(8), TU64(9), TUI(10))
+	check(t, s, "U: 5 U8: 6 U16: 7 U32: 8 U64: 9 UI: 10")
+	s = Sprintf("%v %v %v", TF(1.0), TF32(2.0), TF64(3.0))
+	check(t, s, "F: 1.000000 F32: 2.000000 F64: 3.000000")
+	s = Sprintf("%v %v", TB(true), TS("x"))
+	check(t, s, "B: true S: \"x\"")
+}
diff --git a/third_party/gofrontend/libgo/go/go/ast/ast.go b/third_party/gofrontend/libgo/go/go/ast/ast.go
new file mode 100644
index 0000000..6e635cd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/ast.go
@@ -0,0 +1,995 @@
+// 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 ast declares the types used to represent syntax trees for Go
+// packages.
+//
+package ast
+
+import (
+	"go/token"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// ----------------------------------------------------------------------------
+// Interfaces
+//
+// There are 3 main classes of nodes: Expressions and type nodes,
+// statement nodes, and declaration nodes. The node names usually
+// match the corresponding Go spec production names to which they
+// correspond. The node fields correspond to the individual parts
+// of the respective productions.
+//
+// All nodes contain position information marking the beginning of
+// the corresponding source text segment; it is accessible via the
+// Pos accessor method. Nodes may contain additional position info
+// for language constructs where comments may be found between parts
+// of the construct (typically any larger, parenthesized subpart).
+// That position information is needed to properly position comments
+// when printing the construct.
+
+// All node types implement the Node interface.
+type Node interface {
+	Pos() token.Pos // position of first character belonging to the node
+	End() token.Pos // position of first character immediately after the node
+}
+
+// All expression nodes implement the Expr interface.
+type Expr interface {
+	Node
+	exprNode()
+}
+
+// All statement nodes implement the Stmt interface.
+type Stmt interface {
+	Node
+	stmtNode()
+}
+
+// All declaration nodes implement the Decl interface.
+type Decl interface {
+	Node
+	declNode()
+}
+
+// ----------------------------------------------------------------------------
+// Comments
+
+// A Comment node represents a single //-style or /*-style comment.
+type Comment struct {
+	Slash token.Pos // position of "/" starting the comment
+	Text  string    // comment text (excluding '\n' for //-style comments)
+}
+
+func (c *Comment) Pos() token.Pos { return c.Slash }
+func (c *Comment) End() token.Pos { return token.Pos(int(c.Slash) + len(c.Text)) }
+
+// A CommentGroup represents a sequence of comments
+// with no other tokens and no empty lines between.
+//
+type CommentGroup struct {
+	List []*Comment // len(List) > 0
+}
+
+func (g *CommentGroup) Pos() token.Pos { return g.List[0].Pos() }
+func (g *CommentGroup) End() token.Pos { return g.List[len(g.List)-1].End() }
+
+func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' }
+
+func stripTrailingWhitespace(s string) string {
+	i := len(s)
+	for i > 0 && isWhitespace(s[i-1]) {
+		i--
+	}
+	return s[0:i]
+}
+
+// Text returns the text of the comment.
+// Comment markers (//, /*, and */), the first space of a line comment, and
+// leading and trailing empty lines are removed. Multiple empty lines are
+// reduced to one, and trailing space on lines is trimmed. Unless the result
+// is empty, it is newline-terminated.
+//
+func (g *CommentGroup) Text() string {
+	if g == nil {
+		return ""
+	}
+	comments := make([]string, len(g.List))
+	for i, c := range g.List {
+		comments[i] = string(c.Text)
+	}
+
+	lines := make([]string, 0, 10) // most comments are less than 10 lines
+	for _, c := range comments {
+		// Remove comment markers.
+		// The parser has given us exactly the comment text.
+		switch c[1] {
+		case '/':
+			//-style comment (no newline at the end)
+			c = c[2:]
+			// strip first space - required for Example tests
+			if len(c) > 0 && c[0] == ' ' {
+				c = c[1:]
+			}
+		case '*':
+			/*-style comment */
+			c = c[2 : len(c)-2]
+		}
+
+		// Split on newlines.
+		cl := strings.Split(c, "\n")
+
+		// Walk lines, stripping trailing white space and adding to list.
+		for _, l := range cl {
+			lines = append(lines, stripTrailingWhitespace(l))
+		}
+	}
+
+	// Remove leading blank lines; convert runs of
+	// interior blank lines to a single blank line.
+	n := 0
+	for _, line := range lines {
+		if line != "" || n > 0 && lines[n-1] != "" {
+			lines[n] = line
+			n++
+		}
+	}
+	lines = lines[0:n]
+
+	// Add final "" entry to get trailing newline from Join.
+	if n > 0 && lines[n-1] != "" {
+		lines = append(lines, "")
+	}
+
+	return strings.Join(lines, "\n")
+}
+
+// ----------------------------------------------------------------------------
+// Expressions and types
+
+// A Field represents a Field declaration list in a struct type,
+// a method list in an interface type, or a parameter/result declaration
+// in a signature.
+//
+type Field struct {
+	Doc     *CommentGroup // associated documentation; or nil
+	Names   []*Ident      // field/method/parameter names; or nil if anonymous field
+	Type    Expr          // field/method/parameter type
+	Tag     *BasicLit     // field tag; or nil
+	Comment *CommentGroup // line comments; or nil
+}
+
+func (f *Field) Pos() token.Pos {
+	if len(f.Names) > 0 {
+		return f.Names[0].Pos()
+	}
+	return f.Type.Pos()
+}
+
+func (f *Field) End() token.Pos {
+	if f.Tag != nil {
+		return f.Tag.End()
+	}
+	return f.Type.End()
+}
+
+// A FieldList represents a list of Fields, enclosed by parentheses or braces.
+type FieldList struct {
+	Opening token.Pos // position of opening parenthesis/brace, if any
+	List    []*Field  // field list; or nil
+	Closing token.Pos // position of closing parenthesis/brace, if any
+}
+
+func (f *FieldList) Pos() token.Pos {
+	if f.Opening.IsValid() {
+		return f.Opening
+	}
+	// the list should not be empty in this case;
+	// be conservative and guard against bad ASTs
+	if len(f.List) > 0 {
+		return f.List[0].Pos()
+	}
+	return token.NoPos
+}
+
+func (f *FieldList) End() token.Pos {
+	if f.Closing.IsValid() {
+		return f.Closing + 1
+	}
+	// the list should not be empty in this case;
+	// be conservative and guard against bad ASTs
+	if n := len(f.List); n > 0 {
+		return f.List[n-1].End()
+	}
+	return token.NoPos
+}
+
+// NumFields returns the number of (named and anonymous fields) in a FieldList.
+func (f *FieldList) NumFields() int {
+	n := 0
+	if f != nil {
+		for _, g := range f.List {
+			m := len(g.Names)
+			if m == 0 {
+				m = 1 // anonymous field
+			}
+			n += m
+		}
+	}
+	return n
+}
+
+// An expression is represented by a tree consisting of one
+// or more of the following concrete expression nodes.
+//
+type (
+	// A BadExpr node is a placeholder for expressions containing
+	// syntax errors for which no correct expression nodes can be
+	// created.
+	//
+	BadExpr struct {
+		From, To token.Pos // position range of bad expression
+	}
+
+	// An Ident node represents an identifier.
+	Ident struct {
+		NamePos token.Pos // identifier position
+		Name    string    // identifier name
+		Obj     *Object   // denoted object; or nil
+	}
+
+	// An Ellipsis node stands for the "..." type in a
+	// parameter list or the "..." length in an array type.
+	//
+	Ellipsis struct {
+		Ellipsis token.Pos // position of "..."
+		Elt      Expr      // ellipsis element type (parameter lists only); or nil
+	}
+
+	// A BasicLit node represents a literal of basic type.
+	BasicLit struct {
+		ValuePos token.Pos   // literal position
+		Kind     token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING
+		Value    string      // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 2.4i, 'a', '\x7f', "foo" or `\m\n\o`
+	}
+
+	// A FuncLit node represents a function literal.
+	FuncLit struct {
+		Type *FuncType  // function type
+		Body *BlockStmt // function body
+	}
+
+	// A CompositeLit node represents a composite literal.
+	CompositeLit struct {
+		Type   Expr      // literal type; or nil
+		Lbrace token.Pos // position of "{"
+		Elts   []Expr    // list of composite elements; or nil
+		Rbrace token.Pos // position of "}"
+	}
+
+	// A ParenExpr node represents a parenthesized expression.
+	ParenExpr struct {
+		Lparen token.Pos // position of "("
+		X      Expr      // parenthesized expression
+		Rparen token.Pos // position of ")"
+	}
+
+	// A SelectorExpr node represents an expression followed by a selector.
+	SelectorExpr struct {
+		X   Expr   // expression
+		Sel *Ident // field selector
+	}
+
+	// An IndexExpr node represents an expression followed by an index.
+	IndexExpr struct {
+		X      Expr      // expression
+		Lbrack token.Pos // position of "["
+		Index  Expr      // index expression
+		Rbrack token.Pos // position of "]"
+	}
+
+	// An SliceExpr node represents an expression followed by slice indices.
+	SliceExpr struct {
+		X      Expr      // expression
+		Lbrack token.Pos // position of "["
+		Low    Expr      // begin of slice range; or nil
+		High   Expr      // end of slice range; or nil
+		Max    Expr      // maximum capacity of slice; or nil
+		Slice3 bool      // true if 3-index slice (2 colons present)
+		Rbrack token.Pos // position of "]"
+	}
+
+	// A TypeAssertExpr node represents an expression followed by a
+	// type assertion.
+	//
+	TypeAssertExpr struct {
+		X      Expr      // expression
+		Lparen token.Pos // position of "("
+		Type   Expr      // asserted type; nil means type switch X.(type)
+		Rparen token.Pos // position of ")"
+	}
+
+	// A CallExpr node represents an expression followed by an argument list.
+	CallExpr struct {
+		Fun      Expr      // function expression
+		Lparen   token.Pos // position of "("
+		Args     []Expr    // function arguments; or nil
+		Ellipsis token.Pos // position of "...", if any
+		Rparen   token.Pos // position of ")"
+	}
+
+	// A StarExpr node represents an expression of the form "*" Expression.
+	// Semantically it could be a unary "*" expression, or a pointer type.
+	//
+	StarExpr struct {
+		Star token.Pos // position of "*"
+		X    Expr      // operand
+	}
+
+	// A UnaryExpr node represents a unary expression.
+	// Unary "*" expressions are represented via StarExpr nodes.
+	//
+	UnaryExpr struct {
+		OpPos token.Pos   // position of Op
+		Op    token.Token // operator
+		X     Expr        // operand
+	}
+
+	// A BinaryExpr node represents a binary expression.
+	BinaryExpr struct {
+		X     Expr        // left operand
+		OpPos token.Pos   // position of Op
+		Op    token.Token // operator
+		Y     Expr        // right operand
+	}
+
+	// A KeyValueExpr node represents (key : value) pairs
+	// in composite literals.
+	//
+	KeyValueExpr struct {
+		Key   Expr
+		Colon token.Pos // position of ":"
+		Value Expr
+	}
+)
+
+// The direction of a channel type is indicated by one
+// of the following constants.
+//
+type ChanDir int
+
+const (
+	SEND ChanDir = 1 << iota
+	RECV
+)
+
+// A type is represented by a tree consisting of one
+// or more of the following type-specific expression
+// nodes.
+//
+type (
+	// An ArrayType node represents an array or slice type.
+	ArrayType struct {
+		Lbrack token.Pos // position of "["
+		Len    Expr      // Ellipsis node for [...]T array types, nil for slice types
+		Elt    Expr      // element type
+	}
+
+	// A StructType node represents a struct type.
+	StructType struct {
+		Struct     token.Pos  // position of "struct" keyword
+		Fields     *FieldList // list of field declarations
+		Incomplete bool       // true if (source) fields are missing in the Fields list
+	}
+
+	// Pointer types are represented via StarExpr nodes.
+
+	// A FuncType node represents a function type.
+	FuncType struct {
+		Func    token.Pos  // position of "func" keyword (token.NoPos if there is no "func")
+		Params  *FieldList // (incoming) parameters; non-nil
+		Results *FieldList // (outgoing) results; or nil
+	}
+
+	// An InterfaceType node represents an interface type.
+	InterfaceType struct {
+		Interface  token.Pos  // position of "interface" keyword
+		Methods    *FieldList // list of methods
+		Incomplete bool       // true if (source) methods are missing in the Methods list
+	}
+
+	// A MapType node represents a map type.
+	MapType struct {
+		Map   token.Pos // position of "map" keyword
+		Key   Expr
+		Value Expr
+	}
+
+	// A ChanType node represents a channel type.
+	ChanType struct {
+		Begin token.Pos // position of "chan" keyword or "<-" (whichever comes first)
+		Arrow token.Pos // position of "<-" (token.NoPos if there is no "<-")
+		Dir   ChanDir   // channel direction
+		Value Expr      // value type
+	}
+)
+
+// Pos and End implementations for expression/type nodes.
+//
+func (x *BadExpr) Pos() token.Pos  { return x.From }
+func (x *Ident) Pos() token.Pos    { return x.NamePos }
+func (x *Ellipsis) Pos() token.Pos { return x.Ellipsis }
+func (x *BasicLit) Pos() token.Pos { return x.ValuePos }
+func (x *FuncLit) Pos() token.Pos  { return x.Type.Pos() }
+func (x *CompositeLit) Pos() token.Pos {
+	if x.Type != nil {
+		return x.Type.Pos()
+	}
+	return x.Lbrace
+}
+func (x *ParenExpr) Pos() token.Pos      { return x.Lparen }
+func (x *SelectorExpr) Pos() token.Pos   { return x.X.Pos() }
+func (x *IndexExpr) Pos() token.Pos      { return x.X.Pos() }
+func (x *SliceExpr) Pos() token.Pos      { return x.X.Pos() }
+func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() }
+func (x *CallExpr) Pos() token.Pos       { return x.Fun.Pos() }
+func (x *StarExpr) Pos() token.Pos       { return x.Star }
+func (x *UnaryExpr) Pos() token.Pos      { return x.OpPos }
+func (x *BinaryExpr) Pos() token.Pos     { return x.X.Pos() }
+func (x *KeyValueExpr) Pos() token.Pos   { return x.Key.Pos() }
+func (x *ArrayType) Pos() token.Pos      { return x.Lbrack }
+func (x *StructType) Pos() token.Pos     { return x.Struct }
+func (x *FuncType) Pos() token.Pos {
+	if x.Func.IsValid() || x.Params == nil { // see issue 3870
+		return x.Func
+	}
+	return x.Params.Pos() // interface method declarations have no "func" keyword
+}
+func (x *InterfaceType) Pos() token.Pos { return x.Interface }
+func (x *MapType) Pos() token.Pos       { return x.Map }
+func (x *ChanType) Pos() token.Pos      { return x.Begin }
+
+func (x *BadExpr) End() token.Pos { return x.To }
+func (x *Ident) End() token.Pos   { return token.Pos(int(x.NamePos) + len(x.Name)) }
+func (x *Ellipsis) End() token.Pos {
+	if x.Elt != nil {
+		return x.Elt.End()
+	}
+	return x.Ellipsis + 3 // len("...")
+}
+func (x *BasicLit) End() token.Pos       { return token.Pos(int(x.ValuePos) + len(x.Value)) }
+func (x *FuncLit) End() token.Pos        { return x.Body.End() }
+func (x *CompositeLit) End() token.Pos   { return x.Rbrace + 1 }
+func (x *ParenExpr) End() token.Pos      { return x.Rparen + 1 }
+func (x *SelectorExpr) End() token.Pos   { return x.Sel.End() }
+func (x *IndexExpr) End() token.Pos      { return x.Rbrack + 1 }
+func (x *SliceExpr) End() token.Pos      { return x.Rbrack + 1 }
+func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 }
+func (x *CallExpr) End() token.Pos       { return x.Rparen + 1 }
+func (x *StarExpr) End() token.Pos       { return x.X.End() }
+func (x *UnaryExpr) End() token.Pos      { return x.X.End() }
+func (x *BinaryExpr) End() token.Pos     { return x.Y.End() }
+func (x *KeyValueExpr) End() token.Pos   { return x.Value.End() }
+func (x *ArrayType) End() token.Pos      { return x.Elt.End() }
+func (x *StructType) End() token.Pos     { return x.Fields.End() }
+func (x *FuncType) End() token.Pos {
+	if x.Results != nil {
+		return x.Results.End()
+	}
+	return x.Params.End()
+}
+func (x *InterfaceType) End() token.Pos { return x.Methods.End() }
+func (x *MapType) End() token.Pos       { return x.Value.End() }
+func (x *ChanType) End() token.Pos      { return x.Value.End() }
+
+// exprNode() ensures that only expression/type nodes can be
+// assigned to an ExprNode.
+//
+func (*BadExpr) exprNode()        {}
+func (*Ident) exprNode()          {}
+func (*Ellipsis) exprNode()       {}
+func (*BasicLit) exprNode()       {}
+func (*FuncLit) exprNode()        {}
+func (*CompositeLit) exprNode()   {}
+func (*ParenExpr) exprNode()      {}
+func (*SelectorExpr) exprNode()   {}
+func (*IndexExpr) exprNode()      {}
+func (*SliceExpr) exprNode()      {}
+func (*TypeAssertExpr) exprNode() {}
+func (*CallExpr) exprNode()       {}
+func (*StarExpr) exprNode()       {}
+func (*UnaryExpr) exprNode()      {}
+func (*BinaryExpr) exprNode()     {}
+func (*KeyValueExpr) exprNode()   {}
+
+func (*ArrayType) exprNode()     {}
+func (*StructType) exprNode()    {}
+func (*FuncType) exprNode()      {}
+func (*InterfaceType) exprNode() {}
+func (*MapType) exprNode()       {}
+func (*ChanType) exprNode()      {}
+
+// ----------------------------------------------------------------------------
+// Convenience functions for Idents
+
+// NewIdent creates a new Ident without position.
+// Useful for ASTs generated by code other than the Go parser.
+//
+func NewIdent(name string) *Ident { return &Ident{token.NoPos, name, nil} }
+
+// IsExported reports whether name is an exported Go symbol
+// (that is, whether it begins with an upper-case letter).
+//
+func IsExported(name string) bool {
+	ch, _ := utf8.DecodeRuneInString(name)
+	return unicode.IsUpper(ch)
+}
+
+// IsExported reports whether id is an exported Go symbol
+// (that is, whether it begins with an uppercase letter).
+//
+func (id *Ident) IsExported() bool { return IsExported(id.Name) }
+
+func (id *Ident) String() string {
+	if id != nil {
+		return id.Name
+	}
+	return "<nil>"
+}
+
+// ----------------------------------------------------------------------------
+// Statements
+
+// A statement is represented by a tree consisting of one
+// or more of the following concrete statement nodes.
+//
+type (
+	// A BadStmt node is a placeholder for statements containing
+	// syntax errors for which no correct statement nodes can be
+	// created.
+	//
+	BadStmt struct {
+		From, To token.Pos // position range of bad statement
+	}
+
+	// A DeclStmt node represents a declaration in a statement list.
+	DeclStmt struct {
+		Decl Decl // *GenDecl with CONST, TYPE, or VAR token
+	}
+
+	// An EmptyStmt node represents an empty statement.
+	// The "position" of the empty statement is the position
+	// of the immediately preceding semicolon.
+	//
+	EmptyStmt struct {
+		Semicolon token.Pos // position of preceding ";"
+	}
+
+	// A LabeledStmt node represents a labeled statement.
+	LabeledStmt struct {
+		Label *Ident
+		Colon token.Pos // position of ":"
+		Stmt  Stmt
+	}
+
+	// An ExprStmt node represents a (stand-alone) expression
+	// in a statement list.
+	//
+	ExprStmt struct {
+		X Expr // expression
+	}
+
+	// A SendStmt node represents a send statement.
+	SendStmt struct {
+		Chan  Expr
+		Arrow token.Pos // position of "<-"
+		Value Expr
+	}
+
+	// An IncDecStmt node represents an increment or decrement statement.
+	IncDecStmt struct {
+		X      Expr
+		TokPos token.Pos   // position of Tok
+		Tok    token.Token // INC or DEC
+	}
+
+	// An AssignStmt node represents an assignment or
+	// a short variable declaration.
+	//
+	AssignStmt struct {
+		Lhs    []Expr
+		TokPos token.Pos   // position of Tok
+		Tok    token.Token // assignment token, DEFINE
+		Rhs    []Expr
+	}
+
+	// A GoStmt node represents a go statement.
+	GoStmt struct {
+		Go   token.Pos // position of "go" keyword
+		Call *CallExpr
+	}
+
+	// A DeferStmt node represents a defer statement.
+	DeferStmt struct {
+		Defer token.Pos // position of "defer" keyword
+		Call  *CallExpr
+	}
+
+	// A ReturnStmt node represents a return statement.
+	ReturnStmt struct {
+		Return  token.Pos // position of "return" keyword
+		Results []Expr    // result expressions; or nil
+	}
+
+	// A BranchStmt node represents a break, continue, goto,
+	// or fallthrough statement.
+	//
+	BranchStmt struct {
+		TokPos token.Pos   // position of Tok
+		Tok    token.Token // keyword token (BREAK, CONTINUE, GOTO, FALLTHROUGH)
+		Label  *Ident      // label name; or nil
+	}
+
+	// A BlockStmt node represents a braced statement list.
+	BlockStmt struct {
+		Lbrace token.Pos // position of "{"
+		List   []Stmt
+		Rbrace token.Pos // position of "}"
+	}
+
+	// An IfStmt node represents an if statement.
+	IfStmt struct {
+		If   token.Pos // position of "if" keyword
+		Init Stmt      // initialization statement; or nil
+		Cond Expr      // condition
+		Body *BlockStmt
+		Else Stmt // else branch; or nil
+	}
+
+	// A CaseClause represents a case of an expression or type switch statement.
+	CaseClause struct {
+		Case  token.Pos // position of "case" or "default" keyword
+		List  []Expr    // list of expressions or types; nil means default case
+		Colon token.Pos // position of ":"
+		Body  []Stmt    // statement list; or nil
+	}
+
+	// A SwitchStmt node represents an expression switch statement.
+	SwitchStmt struct {
+		Switch token.Pos  // position of "switch" keyword
+		Init   Stmt       // initialization statement; or nil
+		Tag    Expr       // tag expression; or nil
+		Body   *BlockStmt // CaseClauses only
+	}
+
+	// An TypeSwitchStmt node represents a type switch statement.
+	TypeSwitchStmt struct {
+		Switch token.Pos  // position of "switch" keyword
+		Init   Stmt       // initialization statement; or nil
+		Assign Stmt       // x := y.(type) or y.(type)
+		Body   *BlockStmt // CaseClauses only
+	}
+
+	// A CommClause node represents a case of a select statement.
+	CommClause struct {
+		Case  token.Pos // position of "case" or "default" keyword
+		Comm  Stmt      // send or receive statement; nil means default case
+		Colon token.Pos // position of ":"
+		Body  []Stmt    // statement list; or nil
+	}
+
+	// An SelectStmt node represents a select statement.
+	SelectStmt struct {
+		Select token.Pos  // position of "select" keyword
+		Body   *BlockStmt // CommClauses only
+	}
+
+	// A ForStmt represents a for statement.
+	ForStmt struct {
+		For  token.Pos // position of "for" keyword
+		Init Stmt      // initialization statement; or nil
+		Cond Expr      // condition; or nil
+		Post Stmt      // post iteration statement; or nil
+		Body *BlockStmt
+	}
+
+	// A RangeStmt represents a for statement with a range clause.
+	RangeStmt struct {
+		For        token.Pos   // position of "for" keyword
+		Key, Value Expr        // Value may be nil
+		TokPos     token.Pos   // position of Tok
+		Tok        token.Token // ASSIGN, DEFINE
+		X          Expr        // value to range over
+		Body       *BlockStmt
+	}
+)
+
+// Pos and End implementations for statement nodes.
+//
+func (s *BadStmt) Pos() token.Pos        { return s.From }
+func (s *DeclStmt) Pos() token.Pos       { return s.Decl.Pos() }
+func (s *EmptyStmt) Pos() token.Pos      { return s.Semicolon }
+func (s *LabeledStmt) Pos() token.Pos    { return s.Label.Pos() }
+func (s *ExprStmt) Pos() token.Pos       { return s.X.Pos() }
+func (s *SendStmt) Pos() token.Pos       { return s.Chan.Pos() }
+func (s *IncDecStmt) Pos() token.Pos     { return s.X.Pos() }
+func (s *AssignStmt) Pos() token.Pos     { return s.Lhs[0].Pos() }
+func (s *GoStmt) Pos() token.Pos         { return s.Go }
+func (s *DeferStmt) Pos() token.Pos      { return s.Defer }
+func (s *ReturnStmt) Pos() token.Pos     { return s.Return }
+func (s *BranchStmt) Pos() token.Pos     { return s.TokPos }
+func (s *BlockStmt) Pos() token.Pos      { return s.Lbrace }
+func (s *IfStmt) Pos() token.Pos         { return s.If }
+func (s *CaseClause) Pos() token.Pos     { return s.Case }
+func (s *SwitchStmt) Pos() token.Pos     { return s.Switch }
+func (s *TypeSwitchStmt) Pos() token.Pos { return s.Switch }
+func (s *CommClause) Pos() token.Pos     { return s.Case }
+func (s *SelectStmt) Pos() token.Pos     { return s.Select }
+func (s *ForStmt) Pos() token.Pos        { return s.For }
+func (s *RangeStmt) Pos() token.Pos      { return s.For }
+
+func (s *BadStmt) End() token.Pos  { return s.To }
+func (s *DeclStmt) End() token.Pos { return s.Decl.End() }
+func (s *EmptyStmt) End() token.Pos {
+	return s.Semicolon + 1 /* len(";") */
+}
+func (s *LabeledStmt) End() token.Pos { return s.Stmt.End() }
+func (s *ExprStmt) End() token.Pos    { return s.X.End() }
+func (s *SendStmt) End() token.Pos    { return s.Value.End() }
+func (s *IncDecStmt) End() token.Pos {
+	return s.TokPos + 2 /* len("++") */
+}
+func (s *AssignStmt) End() token.Pos { return s.Rhs[len(s.Rhs)-1].End() }
+func (s *GoStmt) End() token.Pos     { return s.Call.End() }
+func (s *DeferStmt) End() token.Pos  { return s.Call.End() }
+func (s *ReturnStmt) End() token.Pos {
+	if n := len(s.Results); n > 0 {
+		return s.Results[n-1].End()
+	}
+	return s.Return + 6 // len("return")
+}
+func (s *BranchStmt) End() token.Pos {
+	if s.Label != nil {
+		return s.Label.End()
+	}
+	return token.Pos(int(s.TokPos) + len(s.Tok.String()))
+}
+func (s *BlockStmt) End() token.Pos { return s.Rbrace + 1 }
+func (s *IfStmt) End() token.Pos {
+	if s.Else != nil {
+		return s.Else.End()
+	}
+	return s.Body.End()
+}
+func (s *CaseClause) End() token.Pos {
+	if n := len(s.Body); n > 0 {
+		return s.Body[n-1].End()
+	}
+	return s.Colon + 1
+}
+func (s *SwitchStmt) End() token.Pos     { return s.Body.End() }
+func (s *TypeSwitchStmt) End() token.Pos { return s.Body.End() }
+func (s *CommClause) End() token.Pos {
+	if n := len(s.Body); n > 0 {
+		return s.Body[n-1].End()
+	}
+	return s.Colon + 1
+}
+func (s *SelectStmt) End() token.Pos { return s.Body.End() }
+func (s *ForStmt) End() token.Pos    { return s.Body.End() }
+func (s *RangeStmt) End() token.Pos  { return s.Body.End() }
+
+// stmtNode() ensures that only statement nodes can be
+// assigned to a StmtNode.
+//
+func (*BadStmt) stmtNode()        {}
+func (*DeclStmt) stmtNode()       {}
+func (*EmptyStmt) stmtNode()      {}
+func (*LabeledStmt) stmtNode()    {}
+func (*ExprStmt) stmtNode()       {}
+func (*SendStmt) stmtNode()       {}
+func (*IncDecStmt) stmtNode()     {}
+func (*AssignStmt) stmtNode()     {}
+func (*GoStmt) stmtNode()         {}
+func (*DeferStmt) stmtNode()      {}
+func (*ReturnStmt) stmtNode()     {}
+func (*BranchStmt) stmtNode()     {}
+func (*BlockStmt) stmtNode()      {}
+func (*IfStmt) stmtNode()         {}
+func (*CaseClause) stmtNode()     {}
+func (*SwitchStmt) stmtNode()     {}
+func (*TypeSwitchStmt) stmtNode() {}
+func (*CommClause) stmtNode()     {}
+func (*SelectStmt) stmtNode()     {}
+func (*ForStmt) stmtNode()        {}
+func (*RangeStmt) stmtNode()      {}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+// A Spec node represents a single (non-parenthesized) import,
+// constant, type, or variable declaration.
+//
+type (
+	// The Spec type stands for any of *ImportSpec, *ValueSpec, and *TypeSpec.
+	Spec interface {
+		Node
+		specNode()
+	}
+
+	// An ImportSpec node represents a single package import.
+	ImportSpec struct {
+		Doc     *CommentGroup // associated documentation; or nil
+		Name    *Ident        // local package name (including "."); or nil
+		Path    *BasicLit     // import path
+		Comment *CommentGroup // line comments; or nil
+		EndPos  token.Pos     // end of spec (overrides Path.Pos if nonzero)
+	}
+
+	// A ValueSpec node represents a constant or variable declaration
+	// (ConstSpec or VarSpec production).
+	//
+	ValueSpec struct {
+		Doc     *CommentGroup // associated documentation; or nil
+		Names   []*Ident      // value names (len(Names) > 0)
+		Type    Expr          // value type; or nil
+		Values  []Expr        // initial values; or nil
+		Comment *CommentGroup // line comments; or nil
+	}
+
+	// A TypeSpec node represents a type declaration (TypeSpec production).
+	TypeSpec struct {
+		Doc     *CommentGroup // associated documentation; or nil
+		Name    *Ident        // type name
+		Type    Expr          // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
+		Comment *CommentGroup // line comments; or nil
+	}
+)
+
+// Pos and End implementations for spec nodes.
+//
+func (s *ImportSpec) Pos() token.Pos {
+	if s.Name != nil {
+		return s.Name.Pos()
+	}
+	return s.Path.Pos()
+}
+func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() }
+func (s *TypeSpec) Pos() token.Pos  { return s.Name.Pos() }
+
+func (s *ImportSpec) End() token.Pos {
+	if s.EndPos != 0 {
+		return s.EndPos
+	}
+	return s.Path.End()
+}
+
+func (s *ValueSpec) End() token.Pos {
+	if n := len(s.Values); n > 0 {
+		return s.Values[n-1].End()
+	}
+	if s.Type != nil {
+		return s.Type.End()
+	}
+	return s.Names[len(s.Names)-1].End()
+}
+func (s *TypeSpec) End() token.Pos { return s.Type.End() }
+
+// specNode() ensures that only spec nodes can be
+// assigned to a Spec.
+//
+func (*ImportSpec) specNode() {}
+func (*ValueSpec) specNode()  {}
+func (*TypeSpec) specNode()   {}
+
+// A declaration is represented by one of the following declaration nodes.
+//
+type (
+	// A BadDecl node is a placeholder for declarations containing
+	// syntax errors for which no correct declaration nodes can be
+	// created.
+	//
+	BadDecl struct {
+		From, To token.Pos // position range of bad declaration
+	}
+
+	// A GenDecl node (generic declaration node) represents an import,
+	// constant, type or variable declaration. A valid Lparen position
+	// (Lparen.Line > 0) indicates a parenthesized declaration.
+	//
+	// Relationship between Tok value and Specs element type:
+	//
+	//	token.IMPORT  *ImportSpec
+	//	token.CONST   *ValueSpec
+	//	token.TYPE    *TypeSpec
+	//	token.VAR     *ValueSpec
+	//
+	GenDecl struct {
+		Doc    *CommentGroup // associated documentation; or nil
+		TokPos token.Pos     // position of Tok
+		Tok    token.Token   // IMPORT, CONST, TYPE, VAR
+		Lparen token.Pos     // position of '(', if any
+		Specs  []Spec
+		Rparen token.Pos // position of ')', if any
+	}
+
+	// A FuncDecl node represents a function declaration.
+	FuncDecl struct {
+		Doc  *CommentGroup // associated documentation; or nil
+		Recv *FieldList    // receiver (methods); or nil (functions)
+		Name *Ident        // function/method name
+		Type *FuncType     // function signature: parameters, results, and position of "func" keyword
+		Body *BlockStmt    // function body; or nil (forward declaration)
+	}
+)
+
+// Pos and End implementations for declaration nodes.
+//
+func (d *BadDecl) Pos() token.Pos  { return d.From }
+func (d *GenDecl) Pos() token.Pos  { return d.TokPos }
+func (d *FuncDecl) Pos() token.Pos { return d.Type.Pos() }
+
+func (d *BadDecl) End() token.Pos { return d.To }
+func (d *GenDecl) End() token.Pos {
+	if d.Rparen.IsValid() {
+		return d.Rparen + 1
+	}
+	return d.Specs[0].End()
+}
+func (d *FuncDecl) End() token.Pos {
+	if d.Body != nil {
+		return d.Body.End()
+	}
+	return d.Type.End()
+}
+
+// declNode() ensures that only declaration nodes can be
+// assigned to a DeclNode.
+//
+func (*BadDecl) declNode()  {}
+func (*GenDecl) declNode()  {}
+func (*FuncDecl) declNode() {}
+
+// ----------------------------------------------------------------------------
+// Files and packages
+
+// A File node represents a Go source file.
+//
+// The Comments list contains all comments in the source file in order of
+// appearance, including the comments that are pointed to from other nodes
+// via Doc and Comment fields.
+//
+type File struct {
+	Doc        *CommentGroup   // associated documentation; or nil
+	Package    token.Pos       // position of "package" keyword
+	Name       *Ident          // package name
+	Decls      []Decl          // top-level declarations; or nil
+	Scope      *Scope          // package scope (this file only)
+	Imports    []*ImportSpec   // imports in this file
+	Unresolved []*Ident        // unresolved identifiers in this file
+	Comments   []*CommentGroup // list of all comments in the source file
+}
+
+func (f *File) Pos() token.Pos { return f.Package }
+func (f *File) End() token.Pos {
+	if n := len(f.Decls); n > 0 {
+		return f.Decls[n-1].End()
+	}
+	return f.Name.End()
+}
+
+// A Package node represents a set of source files
+// collectively building a Go package.
+//
+type Package struct {
+	Name    string             // package name
+	Scope   *Scope             // package scope across all files
+	Imports map[string]*Object // map of package id -> package object
+	Files   map[string]*File   // Go source files by filename
+}
+
+func (p *Package) Pos() token.Pos { return token.NoPos }
+func (p *Package) End() token.Pos { return token.NoPos }
diff --git a/third_party/gofrontend/libgo/go/go/ast/ast_test.go b/third_party/gofrontend/libgo/go/go/ast/ast_test.go
new file mode 100644
index 0000000..1a6a283
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/ast_test.go
@@ -0,0 +1,50 @@
+// 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 ast
+
+import (
+	"testing"
+)
+
+var comments = []struct {
+	list []string
+	text string
+}{
+	{[]string{"//"}, ""},
+	{[]string{"//   "}, ""},
+	{[]string{"//", "//", "//   "}, ""},
+	{[]string{"// foo   "}, "foo\n"},
+	{[]string{"//", "//", "// foo"}, "foo\n"},
+	{[]string{"// foo  bar  "}, "foo  bar\n"},
+	{[]string{"// foo", "// bar"}, "foo\nbar\n"},
+	{[]string{"// foo", "//", "//", "//", "// bar"}, "foo\n\nbar\n"},
+	{[]string{"// foo", "/* bar */"}, "foo\n bar\n"},
+	{[]string{"//", "//", "//", "// foo", "//", "//", "//"}, "foo\n"},
+
+	{[]string{"/**/"}, ""},
+	{[]string{"/*   */"}, ""},
+	{[]string{"/**/", "/**/", "/*   */"}, ""},
+	{[]string{"/* Foo   */"}, " Foo\n"},
+	{[]string{"/* Foo  Bar  */"}, " Foo  Bar\n"},
+	{[]string{"/* Foo*/", "/* Bar*/"}, " Foo\n Bar\n"},
+	{[]string{"/* Foo*/", "/**/", "/**/", "/**/", "// Bar"}, " Foo\n\nBar\n"},
+	{[]string{"/* Foo*/", "/*\n*/", "//", "/*\n*/", "// Bar"}, " Foo\n\nBar\n"},
+	{[]string{"/* Foo*/", "// Bar"}, " Foo\nBar\n"},
+	{[]string{"/* Foo\n Bar*/"}, " Foo\n Bar\n"},
+}
+
+func TestCommentText(t *testing.T) {
+	for i, c := range comments {
+		list := make([]*Comment, len(c.list))
+		for i, s := range c.list {
+			list[i] = &Comment{Text: s}
+		}
+
+		text := (&CommentGroup{list}).Text()
+		if text != c.text {
+			t.Errorf("case %d: got %q; expected %q", i, text, c.text)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/ast/commentmap.go b/third_party/gofrontend/libgo/go/go/ast/commentmap.go
new file mode 100644
index 0000000..ac999d6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/commentmap.go
@@ -0,0 +1,332 @@
+// 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 ast
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"sort"
+)
+
+type byPos []*CommentGroup
+
+func (a byPos) Len() int           { return len(a) }
+func (a byPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
+func (a byPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+// sortComments sorts the list of comment groups in source order.
+//
+func sortComments(list []*CommentGroup) {
+	// TODO(gri): Does it make sense to check for sorted-ness
+	//            first (because we know that sorted-ness is
+	//            very likely)?
+	if orderedList := byPos(list); !sort.IsSorted(orderedList) {
+		sort.Sort(orderedList)
+	}
+}
+
+// A CommentMap maps an AST node to a list of comment groups
+// associated with it. See NewCommentMap for a description of
+// the association.
+//
+type CommentMap map[Node][]*CommentGroup
+
+func (cmap CommentMap) addComment(n Node, c *CommentGroup) {
+	list := cmap[n]
+	if len(list) == 0 {
+		list = []*CommentGroup{c}
+	} else {
+		list = append(list, c)
+	}
+	cmap[n] = list
+}
+
+type byInterval []Node
+
+func (a byInterval) Len() int { return len(a) }
+func (a byInterval) Less(i, j int) bool {
+	pi, pj := a[i].Pos(), a[j].Pos()
+	return pi < pj || pi == pj && a[i].End() > a[j].End()
+}
+func (a byInterval) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+// nodeList returns the list of nodes of the AST n in source order.
+//
+func nodeList(n Node) []Node {
+	var list []Node
+	Inspect(n, func(n Node) bool {
+		// don't collect comments
+		switch n.(type) {
+		case nil, *CommentGroup, *Comment:
+			return false
+		}
+		list = append(list, n)
+		return true
+	})
+	// Note: The current implementation assumes that Inspect traverses the
+	//       AST in depth-first and thus _source_ order. If AST traversal
+	//       does not follow source order, the sorting call below will be
+	//       required.
+	// sort.Sort(byInterval(list))
+	return list
+}
+
+// A commentListReader helps iterating through a list of comment groups.
+//
+type commentListReader struct {
+	fset     *token.FileSet
+	list     []*CommentGroup
+	index    int
+	comment  *CommentGroup  // comment group at current index
+	pos, end token.Position // source interval of comment group at current index
+}
+
+func (r *commentListReader) eol() bool {
+	return r.index >= len(r.list)
+}
+
+func (r *commentListReader) next() {
+	if !r.eol() {
+		r.comment = r.list[r.index]
+		r.pos = r.fset.Position(r.comment.Pos())
+		r.end = r.fset.Position(r.comment.End())
+		r.index++
+	}
+}
+
+// A nodeStack keeps track of nested nodes.
+// A node lower on the stack lexically contains the nodes higher on the stack.
+//
+type nodeStack []Node
+
+// push pops all nodes that appear lexically before n
+// and then pushes n on the stack.
+//
+func (s *nodeStack) push(n Node) {
+	s.pop(n.Pos())
+	*s = append((*s), n)
+}
+
+// pop pops all nodes that appear lexically before pos
+// (i.e., whose lexical extent has ended before or at pos).
+// It returns the last node popped.
+//
+func (s *nodeStack) pop(pos token.Pos) (top Node) {
+	i := len(*s)
+	for i > 0 && (*s)[i-1].End() <= pos {
+		top = (*s)[i-1]
+		i--
+	}
+	*s = (*s)[0:i]
+	return top
+}
+
+// NewCommentMap creates a new comment map by associating comment groups
+// of the comments list with the nodes of the AST specified by node.
+//
+// A comment group g is associated with a node n if:
+//
+//   - g starts on the same line as n ends
+//   - g starts on the line immediately following n, and there is
+//     at least one empty line after g and before the next node
+//   - g starts before n and is not associated to the node before n
+//     via the previous rules
+//
+// NewCommentMap tries to associate a comment group to the "largest"
+// node possible: For instance, if the comment is a line comment
+// trailing an assignment, the comment is associated with the entire
+// assignment rather than just the last operand in the assignment.
+//
+func NewCommentMap(fset *token.FileSet, node Node, comments []*CommentGroup) CommentMap {
+	if len(comments) == 0 {
+		return nil // no comments to map
+	}
+
+	cmap := make(CommentMap)
+
+	// set up comment reader r
+	tmp := make([]*CommentGroup, len(comments))
+	copy(tmp, comments) // don't change incoming comments
+	sortComments(tmp)
+	r := commentListReader{fset: fset, list: tmp} // !r.eol() because len(comments) > 0
+	r.next()
+
+	// create node list in lexical order
+	nodes := nodeList(node)
+	nodes = append(nodes, nil) // append sentinel
+
+	// set up iteration variables
+	var (
+		p     Node           // previous node
+		pend  token.Position // end of p
+		pg    Node           // previous node group (enclosing nodes of "importance")
+		pgend token.Position // end of pg
+		stack nodeStack      // stack of node groups
+	)
+
+	for _, q := range nodes {
+		var qpos token.Position
+		if q != nil {
+			qpos = fset.Position(q.Pos()) // current node position
+		} else {
+			// set fake sentinel position to infinity so that
+			// all comments get processed before the sentinel
+			const infinity = 1 << 30
+			qpos.Offset = infinity
+			qpos.Line = infinity
+		}
+
+		// process comments before current node
+		for r.end.Offset <= qpos.Offset {
+			// determine recent node group
+			if top := stack.pop(r.comment.Pos()); top != nil {
+				pg = top
+				pgend = fset.Position(pg.End())
+			}
+			// Try to associate a comment first with a node group
+			// (i.e., a node of "importance" such as a declaration);
+			// if that fails, try to associate it with the most recent
+			// node.
+			// TODO(gri) try to simplify the logic below
+			var assoc Node
+			switch {
+			case pg != nil &&
+				(pgend.Line == r.pos.Line ||
+					pgend.Line+1 == r.pos.Line && r.end.Line+1 < qpos.Line):
+				// 1) comment starts on same line as previous node group ends, or
+				// 2) comment starts on the line immediately after the
+				//    previous node group and there is an empty line before
+				//    the current node
+				// => associate comment with previous node group
+				assoc = pg
+			case p != nil &&
+				(pend.Line == r.pos.Line ||
+					pend.Line+1 == r.pos.Line && r.end.Line+1 < qpos.Line ||
+					q == nil):
+				// same rules apply as above for p rather than pg,
+				// but also associate with p if we are at the end (q == nil)
+				assoc = p
+			default:
+				// otherwise, associate comment with current node
+				if q == nil {
+					// we can only reach here if there was no p
+					// which would imply that there were no nodes
+					panic("internal error: no comments should be associated with sentinel")
+				}
+				assoc = q
+			}
+			cmap.addComment(assoc, r.comment)
+			if r.eol() {
+				return cmap
+			}
+			r.next()
+		}
+
+		// update previous node
+		p = q
+		pend = fset.Position(p.End())
+
+		// update previous node group if we see an "important" node
+		switch q.(type) {
+		case *File, *Field, Decl, Spec, Stmt:
+			stack.push(q)
+		}
+	}
+
+	return cmap
+}
+
+// Update replaces an old node in the comment map with the new node
+// and returns the new node. Comments that were associated with the
+// old node are associated with the new node.
+//
+func (cmap CommentMap) Update(old, new Node) Node {
+	if list := cmap[old]; len(list) > 0 {
+		delete(cmap, old)
+		cmap[new] = append(cmap[new], list...)
+	}
+	return new
+}
+
+// Filter returns a new comment map consisting of only those
+// entries of cmap for which a corresponding node exists in
+// the AST specified by node.
+//
+func (cmap CommentMap) Filter(node Node) CommentMap {
+	umap := make(CommentMap)
+	Inspect(node, func(n Node) bool {
+		if g := cmap[n]; len(g) > 0 {
+			umap[n] = g
+		}
+		return true
+	})
+	return umap
+}
+
+// Comments returns the list of comment groups in the comment map.
+// The result is sorted is source order.
+//
+func (cmap CommentMap) Comments() []*CommentGroup {
+	list := make([]*CommentGroup, 0, len(cmap))
+	for _, e := range cmap {
+		list = append(list, e...)
+	}
+	sortComments(list)
+	return list
+}
+
+func summary(list []*CommentGroup) string {
+	const maxLen = 40
+	var buf bytes.Buffer
+
+	// collect comments text
+loop:
+	for _, group := range list {
+		// Note: CommentGroup.Text() does too much work for what we
+		//       need and would only replace this innermost loop.
+		//       Just do it explicitly.
+		for _, comment := range group.List {
+			if buf.Len() >= maxLen {
+				break loop
+			}
+			buf.WriteString(comment.Text)
+		}
+	}
+
+	// truncate if too long
+	if buf.Len() > maxLen {
+		buf.Truncate(maxLen - 3)
+		buf.WriteString("...")
+	}
+
+	// replace any invisibles with blanks
+	bytes := buf.Bytes()
+	for i, b := range bytes {
+		switch b {
+		case '\t', '\n', '\r':
+			bytes[i] = ' '
+		}
+	}
+
+	return string(bytes)
+}
+
+func (cmap CommentMap) String() string {
+	var buf bytes.Buffer
+	fmt.Fprintln(&buf, "CommentMap {")
+	for node, comment := range cmap {
+		// print name of identifiers; print node type for other nodes
+		var s string
+		if ident, ok := node.(*Ident); ok {
+			s = ident.Name
+		} else {
+			s = fmt.Sprintf("%T", node)
+		}
+		fmt.Fprintf(&buf, "\t%p  %20s:  %s\n", node, s, summary(comment))
+	}
+	fmt.Fprintln(&buf, "}")
+	return buf.String()
+}
diff --git a/third_party/gofrontend/libgo/go/go/ast/commentmap_test.go b/third_party/gofrontend/libgo/go/go/ast/commentmap_test.go
new file mode 100644
index 0000000..e372eab
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/commentmap_test.go
@@ -0,0 +1,143 @@
+// 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.
+
+// To avoid a cyclic dependency with go/parser, this file is in a separate package.
+
+package ast_test
+
+import (
+	"bytes"
+	"fmt"
+	. "go/ast"
+	"go/parser"
+	"go/token"
+	"sort"
+	"testing"
+)
+
+const src = `
+// the very first comment
+
+// package p
+package p /* the name is p */
+
+// imports
+import (
+	"bytes"     // bytes
+	"fmt"       // fmt
+	"go/ast"
+	"go/parser"
+)
+
+// T
+type T struct {
+	a, b, c int // associated with a, b, c
+	// associated with x, y
+	x, y float64    // float values
+	z    complex128 // complex value
+}
+// also associated with T
+
+// x
+var x = 0 // x = 0
+// also associated with x
+
+// f1
+func f1() {
+	/* associated with s1 */
+	s1()
+	// also associated with s1
+	
+	// associated with s2
+	
+	// also associated with s2
+	s2() // line comment for s2
+}
+// associated with f1
+// also associated with f1
+
+// associated with f2
+
+// f2
+func f2() {
+}
+
+func f3() {
+	i := 1 /* 1 */ + 2 // addition
+	_ = i
+}
+
+// the very last comment
+`
+
+// res maps a key of the form "line number: node type"
+// to the associated comments' text.
+//
+var res = map[string]string{
+	" 5: *ast.File":       "the very first comment\npackage p\n",
+	" 5: *ast.Ident":      " the name is p\n",
+	" 8: *ast.GenDecl":    "imports\n",
+	" 9: *ast.ImportSpec": "bytes\n",
+	"10: *ast.ImportSpec": "fmt\n",
+	"16: *ast.GenDecl":    "T\nalso associated with T\n",
+	"17: *ast.Field":      "associated with a, b, c\n",
+	"19: *ast.Field":      "associated with x, y\nfloat values\n",
+	"20: *ast.Field":      "complex value\n",
+	"25: *ast.GenDecl":    "x\nx = 0\nalso associated with x\n",
+	"29: *ast.FuncDecl":   "f1\nassociated with f1\nalso associated with f1\n",
+	"31: *ast.ExprStmt":   " associated with s1\nalso associated with s1\n",
+	"37: *ast.ExprStmt":   "associated with s2\nalso associated with s2\nline comment for s2\n",
+	"45: *ast.FuncDecl":   "associated with f2\nf2\n",
+	"49: *ast.AssignStmt": "addition\n",
+	"49: *ast.BasicLit":   " 1\n",
+	"50: *ast.Ident":      "the very last comment\n",
+}
+
+func ctext(list []*CommentGroup) string {
+	var buf bytes.Buffer
+	for _, g := range list {
+		buf.WriteString(g.Text())
+	}
+	return buf.String()
+}
+
+func TestCommentMap(t *testing.T) {
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+	cmap := NewCommentMap(fset, f, f.Comments)
+
+	// very correct association of comments
+	for n, list := range cmap {
+		key := fmt.Sprintf("%2d: %T", fset.Position(n.Pos()).Line, n)
+		got := ctext(list)
+		want := res[key]
+		if got != want {
+			t.Errorf("%s: got %q; want %q", key, got, want)
+		}
+	}
+
+	// verify that no comments got lost
+	if n := len(cmap.Comments()); n != len(f.Comments) {
+		t.Errorf("got %d comment groups in map; want %d", n, len(f.Comments))
+	}
+
+	// support code to update test:
+	// set genMap to true to generate res map
+	const genMap = false
+	if genMap {
+		out := make([]string, 0, len(cmap))
+		for n, list := range cmap {
+			out = append(out, fmt.Sprintf("\t\"%2d: %T\":\t%q,", fset.Position(n.Pos()).Line, n, ctext(list)))
+		}
+		sort.Strings(out)
+		for _, s := range out {
+			fmt.Println(s)
+		}
+	}
+}
+
+// TODO(gri): add tests for Filter.
diff --git a/third_party/gofrontend/libgo/go/go/ast/filter.go b/third_party/gofrontend/libgo/go/go/ast/filter.go
new file mode 100644
index 0000000..fc3eeb4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/filter.go
@@ -0,0 +1,466 @@
+// 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 ast
+
+import (
+	"go/token"
+	"sort"
+)
+
+// ----------------------------------------------------------------------------
+// Export filtering
+
+// exportFilter is a special filter function to extract exported nodes.
+func exportFilter(name string) bool {
+	return IsExported(name)
+}
+
+// FileExports trims the AST for a Go source file in place such that
+// only exported nodes remain: all top-level identifiers which are not exported
+// and their associated information (such as type, initial value, or function
+// body) are removed. Non-exported fields and methods of exported types are
+// stripped. The File.Comments list is not changed.
+//
+// FileExports returns true if there are exported declarations;
+// it returns false otherwise.
+//
+func FileExports(src *File) bool {
+	return filterFile(src, exportFilter, true)
+}
+
+// PackageExports trims the AST for a Go package in place such that
+// only exported nodes remain. The pkg.Files list is not changed, so that
+// file names and top-level package comments don't get lost.
+//
+// PackageExports returns true if there are exported declarations;
+// it returns false otherwise.
+//
+func PackageExports(pkg *Package) bool {
+	return filterPackage(pkg, exportFilter, true)
+}
+
+// ----------------------------------------------------------------------------
+// General filtering
+
+type Filter func(string) bool
+
+func filterIdentList(list []*Ident, f Filter) []*Ident {
+	j := 0
+	for _, x := range list {
+		if f(x.Name) {
+			list[j] = x
+			j++
+		}
+	}
+	return list[0:j]
+}
+
+// fieldName assumes that x is the type of an anonymous field and
+// returns the corresponding field name. If x is not an acceptable
+// anonymous field, the result is nil.
+//
+func fieldName(x Expr) *Ident {
+	switch t := x.(type) {
+	case *Ident:
+		return t
+	case *SelectorExpr:
+		if _, ok := t.X.(*Ident); ok {
+			return t.Sel
+		}
+	case *StarExpr:
+		return fieldName(t.X)
+	}
+	return nil
+}
+
+func filterFieldList(fields *FieldList, filter Filter, export bool) (removedFields bool) {
+	if fields == nil {
+		return false
+	}
+	list := fields.List
+	j := 0
+	for _, f := range list {
+		keepField := false
+		if len(f.Names) == 0 {
+			// anonymous field
+			name := fieldName(f.Type)
+			keepField = name != nil && filter(name.Name)
+		} else {
+			n := len(f.Names)
+			f.Names = filterIdentList(f.Names, filter)
+			if len(f.Names) < n {
+				removedFields = true
+			}
+			keepField = len(f.Names) > 0
+		}
+		if keepField {
+			if export {
+				filterType(f.Type, filter, export)
+			}
+			list[j] = f
+			j++
+		}
+	}
+	if j < len(list) {
+		removedFields = true
+	}
+	fields.List = list[0:j]
+	return
+}
+
+func filterParamList(fields *FieldList, filter Filter, export bool) bool {
+	if fields == nil {
+		return false
+	}
+	var b bool
+	for _, f := range fields.List {
+		if filterType(f.Type, filter, export) {
+			b = true
+		}
+	}
+	return b
+}
+
+func filterType(typ Expr, f Filter, export bool) bool {
+	switch t := typ.(type) {
+	case *Ident:
+		return f(t.Name)
+	case *ParenExpr:
+		return filterType(t.X, f, export)
+	case *ArrayType:
+		return filterType(t.Elt, f, export)
+	case *StructType:
+		if filterFieldList(t.Fields, f, export) {
+			t.Incomplete = true
+		}
+		return len(t.Fields.List) > 0
+	case *FuncType:
+		b1 := filterParamList(t.Params, f, export)
+		b2 := filterParamList(t.Results, f, export)
+		return b1 || b2
+	case *InterfaceType:
+		if filterFieldList(t.Methods, f, export) {
+			t.Incomplete = true
+		}
+		return len(t.Methods.List) > 0
+	case *MapType:
+		b1 := filterType(t.Key, f, export)
+		b2 := filterType(t.Value, f, export)
+		return b1 || b2
+	case *ChanType:
+		return filterType(t.Value, f, export)
+	}
+	return false
+}
+
+func filterSpec(spec Spec, f Filter, export bool) bool {
+	switch s := spec.(type) {
+	case *ValueSpec:
+		s.Names = filterIdentList(s.Names, f)
+		if len(s.Names) > 0 {
+			if export {
+				filterType(s.Type, f, export)
+			}
+			return true
+		}
+	case *TypeSpec:
+		if f(s.Name.Name) {
+			if export {
+				filterType(s.Type, f, export)
+			}
+			return true
+		}
+		if !export {
+			// For general filtering (not just exports),
+			// filter type even if name is not filtered
+			// out.
+			// If the type contains filtered elements,
+			// keep the declaration.
+			return filterType(s.Type, f, export)
+		}
+	}
+	return false
+}
+
+func filterSpecList(list []Spec, f Filter, export bool) []Spec {
+	j := 0
+	for _, s := range list {
+		if filterSpec(s, f, export) {
+			list[j] = s
+			j++
+		}
+	}
+	return list[0:j]
+}
+
+// FilterDecl trims the AST for a Go declaration in place by removing
+// all names (including struct field and interface method names, but
+// not from parameter lists) that don't pass through the filter f.
+//
+// FilterDecl returns true if there are any declared names left after
+// filtering; it returns false otherwise.
+//
+func FilterDecl(decl Decl, f Filter) bool {
+	return filterDecl(decl, f, false)
+}
+
+func filterDecl(decl Decl, f Filter, export bool) bool {
+	switch d := decl.(type) {
+	case *GenDecl:
+		d.Specs = filterSpecList(d.Specs, f, export)
+		return len(d.Specs) > 0
+	case *FuncDecl:
+		return f(d.Name.Name)
+	}
+	return false
+}
+
+// FilterFile trims the AST for a Go file in place by removing all
+// names from top-level declarations (including struct field and
+// interface method names, but not from parameter lists) that don't
+// pass through the filter f. If the declaration is empty afterwards,
+// the declaration is removed from the AST. The File.Comments list
+// is not changed.
+//
+// FilterFile returns true if there are any top-level declarations
+// left after filtering; it returns false otherwise.
+//
+func FilterFile(src *File, f Filter) bool {
+	return filterFile(src, f, false)
+}
+
+func filterFile(src *File, f Filter, export bool) bool {
+	j := 0
+	for _, d := range src.Decls {
+		if filterDecl(d, f, export) {
+			src.Decls[j] = d
+			j++
+		}
+	}
+	src.Decls = src.Decls[0:j]
+	return j > 0
+}
+
+// FilterPackage trims the AST for a Go package in place by removing
+// all names from top-level declarations (including struct field and
+// interface method names, but not from parameter lists) that don't
+// pass through the filter f. If the declaration is empty afterwards,
+// the declaration is removed from the AST. The pkg.Files list is not
+// changed, so that file names and top-level package comments don't get
+// lost.
+//
+// FilterPackage returns true if there are any top-level declarations
+// left after filtering; it returns false otherwise.
+//
+func FilterPackage(pkg *Package, f Filter) bool {
+	return filterPackage(pkg, f, false)
+}
+
+func filterPackage(pkg *Package, f Filter, export bool) bool {
+	hasDecls := false
+	for _, src := range pkg.Files {
+		if filterFile(src, f, export) {
+			hasDecls = true
+		}
+	}
+	return hasDecls
+}
+
+// ----------------------------------------------------------------------------
+// Merging of package files
+
+// The MergeMode flags control the behavior of MergePackageFiles.
+type MergeMode uint
+
+const (
+	// If set, duplicate function declarations are excluded.
+	FilterFuncDuplicates MergeMode = 1 << iota
+	// If set, comments that are not associated with a specific
+	// AST node (as Doc or Comment) are excluded.
+	FilterUnassociatedComments
+	// If set, duplicate import declarations are excluded.
+	FilterImportDuplicates
+)
+
+// nameOf returns the function (foo) or method name (foo.bar) for
+// the given function declaration. If the AST is incorrect for the
+// receiver, it assumes a function instead.
+//
+func nameOf(f *FuncDecl) string {
+	if r := f.Recv; r != nil && len(r.List) == 1 {
+		// looks like a correct receiver declaration
+		t := r.List[0].Type
+		// dereference pointer receiver types
+		if p, _ := t.(*StarExpr); p != nil {
+			t = p.X
+		}
+		// the receiver type must be a type name
+		if p, _ := t.(*Ident); p != nil {
+			return p.Name + "." + f.Name.Name
+		}
+		// otherwise assume a function instead
+	}
+	return f.Name.Name
+}
+
+// separator is an empty //-style comment that is interspersed between
+// different comment groups when they are concatenated into a single group
+//
+var separator = &Comment{token.NoPos, "//"}
+
+// MergePackageFiles creates a file AST by merging the ASTs of the
+// files belonging to a package. The mode flags control merging behavior.
+//
+func MergePackageFiles(pkg *Package, mode MergeMode) *File {
+	// Count the number of package docs, comments and declarations across
+	// all package files. Also, compute sorted list of filenames, so that
+	// subsequent iterations can always iterate in the same order.
+	ndocs := 0
+	ncomments := 0
+	ndecls := 0
+	filenames := make([]string, len(pkg.Files))
+	i := 0
+	for filename, f := range pkg.Files {
+		filenames[i] = filename
+		i++
+		if f.Doc != nil {
+			ndocs += len(f.Doc.List) + 1 // +1 for separator
+		}
+		ncomments += len(f.Comments)
+		ndecls += len(f.Decls)
+	}
+	sort.Strings(filenames)
+
+	// Collect package comments from all package files into a single
+	// CommentGroup - the collected package documentation. In general
+	// there should be only one file with a package comment; but it's
+	// better to collect extra comments than drop them on the floor.
+	var doc *CommentGroup
+	var pos token.Pos
+	if ndocs > 0 {
+		list := make([]*Comment, ndocs-1) // -1: no separator before first group
+		i := 0
+		for _, filename := range filenames {
+			f := pkg.Files[filename]
+			if f.Doc != nil {
+				if i > 0 {
+					// not the first group - add separator
+					list[i] = separator
+					i++
+				}
+				for _, c := range f.Doc.List {
+					list[i] = c
+					i++
+				}
+				if f.Package > pos {
+					// Keep the maximum package clause position as
+					// position for the package clause of the merged
+					// files.
+					pos = f.Package
+				}
+			}
+		}
+		doc = &CommentGroup{list}
+	}
+
+	// Collect declarations from all package files.
+	var decls []Decl
+	if ndecls > 0 {
+		decls = make([]Decl, ndecls)
+		funcs := make(map[string]int) // map of func name -> decls index
+		i := 0                        // current index
+		n := 0                        // number of filtered entries
+		for _, filename := range filenames {
+			f := pkg.Files[filename]
+			for _, d := range f.Decls {
+				if mode&FilterFuncDuplicates != 0 {
+					// A language entity may be declared multiple
+					// times in different package files; only at
+					// build time declarations must be unique.
+					// For now, exclude multiple declarations of
+					// functions - keep the one with documentation.
+					//
+					// TODO(gri): Expand this filtering to other
+					//            entities (const, type, vars) if
+					//            multiple declarations are common.
+					if f, isFun := d.(*FuncDecl); isFun {
+						name := nameOf(f)
+						if j, exists := funcs[name]; exists {
+							// function declared already
+							if decls[j] != nil && decls[j].(*FuncDecl).Doc == nil {
+								// existing declaration has no documentation;
+								// ignore the existing declaration
+								decls[j] = nil
+							} else {
+								// ignore the new declaration
+								d = nil
+							}
+							n++ // filtered an entry
+						} else {
+							funcs[name] = i
+						}
+					}
+				}
+				decls[i] = d
+				i++
+			}
+		}
+
+		// Eliminate nil entries from the decls list if entries were
+		// filtered. We do this using a 2nd pass in order to not disturb
+		// the original declaration order in the source (otherwise, this
+		// would also invalidate the monotonically increasing position
+		// info within a single file).
+		if n > 0 {
+			i = 0
+			for _, d := range decls {
+				if d != nil {
+					decls[i] = d
+					i++
+				}
+			}
+			decls = decls[0:i]
+		}
+	}
+
+	// Collect import specs from all package files.
+	var imports []*ImportSpec
+	if mode&FilterImportDuplicates != 0 {
+		seen := make(map[string]bool)
+		for _, filename := range filenames {
+			f := pkg.Files[filename]
+			for _, imp := range f.Imports {
+				if path := imp.Path.Value; !seen[path] {
+					// TODO: consider handling cases where:
+					// - 2 imports exist with the same import path but
+					//   have different local names (one should probably
+					//   keep both of them)
+					// - 2 imports exist but only one has a comment
+					// - 2 imports exist and they both have (possibly
+					//   different) comments
+					imports = append(imports, imp)
+					seen[path] = true
+				}
+			}
+		}
+	} else {
+		for _, f := range pkg.Files {
+			imports = append(imports, f.Imports...)
+		}
+	}
+
+	// Collect comments from all package files.
+	var comments []*CommentGroup
+	if mode&FilterUnassociatedComments == 0 {
+		comments = make([]*CommentGroup, ncomments)
+		i := 0
+		for _, f := range pkg.Files {
+			i += copy(comments[i:], f.Comments)
+		}
+	}
+
+	// TODO(gri) need to compute unresolved identifiers!
+	return &File{doc, pos, NewIdent(pkg.Name), decls, pkg.Scope, imports, nil, comments}
+}
diff --git a/third_party/gofrontend/libgo/go/go/ast/filter_test.go b/third_party/gofrontend/libgo/go/go/ast/filter_test.go
new file mode 100644
index 0000000..9fd86cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/filter_test.go
@@ -0,0 +1,86 @@
+// Copyright 2013 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.
+
+// To avoid a cyclic dependency with go/parser, this file is in a separate package.
+
+package ast_test
+
+import (
+	"bytes"
+	"go/ast"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"testing"
+)
+
+const input = `package p
+
+type t1 struct{}
+type t2 struct{}
+
+func f1() {}
+func f1() {}
+func f2() {}
+
+func (*t1) f1() {}
+func (t1) f1() {}
+func (t1) f2() {}
+
+func (t2) f1() {}
+func (t2) f2() {}
+func (x *t2) f2() {}
+`
+
+// Calling ast.MergePackageFiles with ast.FilterFuncDuplicates
+// keeps a duplicate entry with attached documentation in favor
+// of one without, and it favors duplicate entries appearing
+// later in the source over ones appearing earlier. This is why
+// (*t2).f2 is kept and t2.f2 is eliminated in this test case.
+//
+const golden = `package p
+
+type t1 struct{}
+type t2 struct{}
+
+func f1() {}
+func f2() {}
+
+func (t1) f1() {}
+func (t1) f2() {}
+
+func (t2) f1() {}
+
+func (x *t2) f2() {}
+`
+
+func TestFilterDuplicates(t *testing.T) {
+	// parse input
+	fset := token.NewFileSet()
+	file, err := parser.ParseFile(fset, "", input, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// create package
+	files := map[string]*ast.File{"": file}
+	pkg, err := ast.NewPackage(fset, files, nil, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// filter
+	merged := ast.MergePackageFiles(pkg, ast.FilterFuncDuplicates)
+
+	// pretty-print
+	var buf bytes.Buffer
+	if err := format.Node(&buf, fset, merged); err != nil {
+		t.Fatal(err)
+	}
+	output := buf.String()
+
+	if output != golden {
+		t.Errorf("incorrect output:\n%s", output)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/ast/import.go b/third_party/gofrontend/libgo/go/go/ast/import.go
new file mode 100644
index 0000000..d2770d1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/import.go
@@ -0,0 +1,196 @@
+// 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.
+
+package ast
+
+import (
+	"go/token"
+	"sort"
+	"strconv"
+)
+
+// SortImports sorts runs of consecutive import lines in import blocks in f.
+// It also removes duplicate imports when it is possible to do so without data loss.
+func SortImports(fset *token.FileSet, f *File) {
+	for _, d := range f.Decls {
+		d, ok := d.(*GenDecl)
+		if !ok || d.Tok != token.IMPORT {
+			// Not an import declaration, so we're done.
+			// Imports are always first.
+			break
+		}
+
+		if !d.Lparen.IsValid() {
+			// Not a block: sorted by default.
+			continue
+		}
+
+		// Identify and sort runs of specs on successive lines.
+		i := 0
+		specs := d.Specs[:0]
+		for j, s := range d.Specs {
+			if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line {
+				// j begins a new run.  End this one.
+				specs = append(specs, sortSpecs(fset, f, d.Specs[i:j])...)
+				i = j
+			}
+		}
+		specs = append(specs, sortSpecs(fset, f, d.Specs[i:])...)
+		d.Specs = specs
+
+		// Deduping can leave a blank line before the rparen; clean that up.
+		if len(d.Specs) > 0 {
+			lastSpec := d.Specs[len(d.Specs)-1]
+			lastLine := fset.Position(lastSpec.Pos()).Line
+			if rParenLine := fset.Position(d.Rparen).Line; rParenLine > lastLine+1 {
+				fset.File(d.Rparen).MergeLine(rParenLine - 1)
+			}
+		}
+	}
+}
+
+func importPath(s Spec) string {
+	t, err := strconv.Unquote(s.(*ImportSpec).Path.Value)
+	if err == nil {
+		return t
+	}
+	return ""
+}
+
+func importName(s Spec) string {
+	n := s.(*ImportSpec).Name
+	if n == nil {
+		return ""
+	}
+	return n.Name
+}
+
+func importComment(s Spec) string {
+	c := s.(*ImportSpec).Comment
+	if c == nil {
+		return ""
+	}
+	return c.Text()
+}
+
+// collapse indicates whether prev may be removed, leaving only next.
+func collapse(prev, next Spec) bool {
+	if importPath(next) != importPath(prev) || importName(next) != importName(prev) {
+		return false
+	}
+	return prev.(*ImportSpec).Comment == nil
+}
+
+type posSpan struct {
+	Start token.Pos
+	End   token.Pos
+}
+
+func sortSpecs(fset *token.FileSet, f *File, specs []Spec) []Spec {
+	// Can't short-circuit here even if specs are already sorted,
+	// since they might yet need deduplication.
+	// A lone import, however, may be safely ignored.
+	if len(specs) <= 1 {
+		return specs
+	}
+
+	// Record positions for specs.
+	pos := make([]posSpan, len(specs))
+	for i, s := range specs {
+		pos[i] = posSpan{s.Pos(), s.End()}
+	}
+
+	// Identify comments in this range.
+	// Any comment from pos[0].Start to the final line counts.
+	lastLine := fset.Position(pos[len(pos)-1].End).Line
+	cstart := len(f.Comments)
+	cend := len(f.Comments)
+	for i, g := range f.Comments {
+		if g.Pos() < pos[0].Start {
+			continue
+		}
+		if i < cstart {
+			cstart = i
+		}
+		if fset.Position(g.End()).Line > lastLine {
+			cend = i
+			break
+		}
+	}
+	comments := f.Comments[cstart:cend]
+
+	// Assign each comment to the import spec preceding it.
+	importComment := map[*ImportSpec][]*CommentGroup{}
+	specIndex := 0
+	for _, g := range comments {
+		for specIndex+1 < len(specs) && pos[specIndex+1].Start <= g.Pos() {
+			specIndex++
+		}
+		s := specs[specIndex].(*ImportSpec)
+		importComment[s] = append(importComment[s], g)
+	}
+
+	// Sort the import specs by import path.
+	// Remove duplicates, when possible without data loss.
+	// Reassign the import paths to have the same position sequence.
+	// Reassign each comment to abut the end of its spec.
+	// Sort the comments by new position.
+	sort.Sort(byImportSpec(specs))
+
+	// Dedup. Thanks to our sorting, we can just consider
+	// adjacent pairs of imports.
+	deduped := specs[:0]
+	for i, s := range specs {
+		if i == len(specs)-1 || !collapse(s, specs[i+1]) {
+			deduped = append(deduped, s)
+		} else {
+			p := s.Pos()
+			fset.File(p).MergeLine(fset.Position(p).Line)
+		}
+	}
+	specs = deduped
+
+	// Fix up comment positions
+	for i, s := range specs {
+		s := s.(*ImportSpec)
+		if s.Name != nil {
+			s.Name.NamePos = pos[i].Start
+		}
+		s.Path.ValuePos = pos[i].Start
+		s.EndPos = pos[i].End
+		for _, g := range importComment[s] {
+			for _, c := range g.List {
+				c.Slash = pos[i].End
+			}
+		}
+	}
+
+	sort.Sort(byCommentPos(comments))
+
+	return specs
+}
+
+type byImportSpec []Spec // slice of *ImportSpec
+
+func (x byImportSpec) Len() int      { return len(x) }
+func (x byImportSpec) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x byImportSpec) Less(i, j int) bool {
+	ipath := importPath(x[i])
+	jpath := importPath(x[j])
+	if ipath != jpath {
+		return ipath < jpath
+	}
+	iname := importName(x[i])
+	jname := importName(x[j])
+	if iname != jname {
+		return iname < jname
+	}
+	return importComment(x[i]) < importComment(x[j])
+}
+
+type byCommentPos []*CommentGroup
+
+func (x byCommentPos) Len() int           { return len(x) }
+func (x byCommentPos) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() }
diff --git a/third_party/gofrontend/libgo/go/go/ast/print.go b/third_party/gofrontend/libgo/go/go/ast/print.go
new file mode 100644
index 0000000..f15dc11
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/print.go
@@ -0,0 +1,251 @@
+// Copyright 2010 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.
+
+// This file contains printing support for ASTs.
+
+package ast
+
+import (
+	"fmt"
+	"go/token"
+	"io"
+	"os"
+	"reflect"
+)
+
+// A FieldFilter may be provided to Fprint to control the output.
+type FieldFilter func(name string, value reflect.Value) bool
+
+// NotNilFilter returns true for field values that are not nil;
+// it returns false otherwise.
+func NotNilFilter(_ string, v reflect.Value) bool {
+	switch v.Kind() {
+	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+		return !v.IsNil()
+	}
+	return true
+}
+
+// Fprint prints the (sub-)tree starting at AST node x to w.
+// If fset != nil, position information is interpreted relative
+// to that file set. Otherwise positions are printed as integer
+// values (file set specific offsets).
+//
+// A non-nil FieldFilter f may be provided to control the output:
+// struct fields for which f(fieldname, fieldvalue) is true are
+// printed; all others are filtered from the output. Unexported
+// struct fields are never printed.
+//
+func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (err error) {
+	// setup printer
+	p := printer{
+		output: w,
+		fset:   fset,
+		filter: f,
+		ptrmap: make(map[interface{}]int),
+		last:   '\n', // force printing of line number on first line
+	}
+
+	// install error handler
+	defer func() {
+		if e := recover(); e != nil {
+			err = e.(localError).err // re-panics if it's not a localError
+		}
+	}()
+
+	// print x
+	if x == nil {
+		p.printf("nil\n")
+		return
+	}
+	p.print(reflect.ValueOf(x))
+	p.printf("\n")
+
+	return
+}
+
+// Print prints x to standard output, skipping nil fields.
+// Print(fset, x) is the same as Fprint(os.Stdout, fset, x, NotNilFilter).
+func Print(fset *token.FileSet, x interface{}) error {
+	return Fprint(os.Stdout, fset, x, NotNilFilter)
+}
+
+type printer struct {
+	output io.Writer
+	fset   *token.FileSet
+	filter FieldFilter
+	ptrmap map[interface{}]int // *T -> line number
+	indent int                 // current indentation level
+	last   byte                // the last byte processed by Write
+	line   int                 // current line number
+}
+
+var indent = []byte(".  ")
+
+func (p *printer) Write(data []byte) (n int, err error) {
+	var m int
+	for i, b := range data {
+		// invariant: data[0:n] has been written
+		if b == '\n' {
+			m, err = p.output.Write(data[n : i+1])
+			n += m
+			if err != nil {
+				return
+			}
+			p.line++
+		} else if p.last == '\n' {
+			_, err = fmt.Fprintf(p.output, "%6d  ", p.line)
+			if err != nil {
+				return
+			}
+			for j := p.indent; j > 0; j-- {
+				_, err = p.output.Write(indent)
+				if err != nil {
+					return
+				}
+			}
+		}
+		p.last = b
+	}
+	if len(data) > n {
+		m, err = p.output.Write(data[n:])
+		n += m
+	}
+	return
+}
+
+// localError wraps locally caught errors so we can distinguish
+// them from genuine panics which we don't want to return as errors.
+type localError struct {
+	err error
+}
+
+// printf is a convenience wrapper that takes care of print errors.
+func (p *printer) printf(format string, args ...interface{}) {
+	if _, err := fmt.Fprintf(p, format, args...); err != nil {
+		panic(localError{err})
+	}
+}
+
+// Implementation note: Print is written for AST nodes but could be
+// used to print arbitrary data structures; such a version should
+// probably be in a different package.
+//
+// Note: This code detects (some) cycles created via pointers but
+// not cycles that are created via slices or maps containing the
+// same slice or map. Code for general data structures probably
+// should catch those as well.
+
+func (p *printer) print(x reflect.Value) {
+	if !NotNilFilter("", x) {
+		p.printf("nil")
+		return
+	}
+
+	switch x.Kind() {
+	case reflect.Interface:
+		p.print(x.Elem())
+
+	case reflect.Map:
+		p.printf("%s (len = %d) {", x.Type(), x.Len())
+		if x.Len() > 0 {
+			p.indent++
+			p.printf("\n")
+			for _, key := range x.MapKeys() {
+				p.print(key)
+				p.printf(": ")
+				p.print(x.MapIndex(key))
+				p.printf("\n")
+			}
+			p.indent--
+		}
+		p.printf("}")
+
+	case reflect.Ptr:
+		p.printf("*")
+		// type-checked ASTs may contain cycles - use ptrmap
+		// to keep track of objects that have been printed
+		// already and print the respective line number instead
+		ptr := x.Interface()
+		if line, exists := p.ptrmap[ptr]; exists {
+			p.printf("(obj @ %d)", line)
+		} else {
+			p.ptrmap[ptr] = p.line
+			p.print(x.Elem())
+		}
+
+	case reflect.Array:
+		p.printf("%s {", x.Type())
+		if x.Len() > 0 {
+			p.indent++
+			p.printf("\n")
+			for i, n := 0, x.Len(); i < n; i++ {
+				p.printf("%d: ", i)
+				p.print(x.Index(i))
+				p.printf("\n")
+			}
+			p.indent--
+		}
+		p.printf("}")
+
+	case reflect.Slice:
+		if s, ok := x.Interface().([]byte); ok {
+			p.printf("%#q", s)
+			return
+		}
+		p.printf("%s (len = %d) {", x.Type(), x.Len())
+		if x.Len() > 0 {
+			p.indent++
+			p.printf("\n")
+			for i, n := 0, x.Len(); i < n; i++ {
+				p.printf("%d: ", i)
+				p.print(x.Index(i))
+				p.printf("\n")
+			}
+			p.indent--
+		}
+		p.printf("}")
+
+	case reflect.Struct:
+		t := x.Type()
+		p.printf("%s {", t)
+		p.indent++
+		first := true
+		for i, n := 0, t.NumField(); i < n; i++ {
+			// exclude non-exported fields because their
+			// values cannot be accessed via reflection
+			if name := t.Field(i).Name; IsExported(name) {
+				value := x.Field(i)
+				if p.filter == nil || p.filter(name, value) {
+					if first {
+						p.printf("\n")
+						first = false
+					}
+					p.printf("%s: ", name)
+					p.print(value)
+					p.printf("\n")
+				}
+			}
+		}
+		p.indent--
+		p.printf("}")
+
+	default:
+		v := x.Interface()
+		switch v := v.(type) {
+		case string:
+			// print strings in quotes
+			p.printf("%q", v)
+			return
+		case token.Pos:
+			// position values can be printed nicely if we have a file set
+			if p.fset != nil {
+				p.printf("%s", p.fset.Position(v))
+				return
+			}
+		}
+		// default
+		p.printf("%v", v)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/ast/print_test.go b/third_party/gofrontend/libgo/go/go/ast/print_test.go
new file mode 100644
index 0000000..210f164
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/print_test.go
@@ -0,0 +1,97 @@
+// 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.
+
+package ast
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+)
+
+var tests = []struct {
+	x interface{} // x is printed as s
+	s string
+}{
+	// basic types
+	{nil, "0  nil"},
+	{true, "0  true"},
+	{42, "0  42"},
+	{3.14, "0  3.14"},
+	{1 + 2.718i, "0  (1+2.718i)"},
+	{"foobar", "0  \"foobar\""},
+
+	// maps
+	{map[Expr]string{}, `0  map[ast.Expr]string (len = 0) {}`},
+	{map[string]int{"a": 1},
+		`0  map[string]int (len = 1) {
+		1  .  "a": 1
+		2  }`},
+
+	// pointers
+	{new(int), "0  *0"},
+
+	// arrays
+	{[0]int{}, `0  [0]int {}`},
+	{[3]int{1, 2, 3},
+		`0  [3]int {
+		1  .  0: 1
+		2  .  1: 2
+		3  .  2: 3
+		4  }`},
+	{[...]int{42},
+		`0  [1]int {
+		1  .  0: 42
+		2  }`},
+
+	// slices
+	{[]int{}, `0  []int (len = 0) {}`},
+	{[]int{1, 2, 3},
+		`0  []int (len = 3) {
+		1  .  0: 1
+		2  .  1: 2
+		3  .  2: 3
+		4  }`},
+
+	// structs
+	{struct{}{}, `0  struct {} {}`},
+	{struct{ x int }{007}, `0  struct { x int } {}`},
+	{struct{ X, y int }{42, 991},
+		`0  struct { X int; y int } {
+		1  .  X: 42
+		2  }`},
+	{struct{ X, Y int }{42, 991},
+		`0  struct { X int; Y int } {
+		1  .  X: 42
+		2  .  Y: 991
+		3  }`},
+}
+
+// Split s into lines, trim whitespace from all lines, and return
+// the concatenated non-empty lines.
+func trim(s string) string {
+	lines := strings.Split(s, "\n")
+	i := 0
+	for _, line := range lines {
+		line = strings.TrimSpace(line)
+		if line != "" {
+			lines[i] = line
+			i++
+		}
+	}
+	return strings.Join(lines[0:i], "\n")
+}
+
+func TestPrint(t *testing.T) {
+	var buf bytes.Buffer
+	for _, test := range tests {
+		buf.Reset()
+		if err := Fprint(&buf, nil, test.x, nil); err != nil {
+			t.Errorf("Fprint failed: %s", err)
+		}
+		if s, ts := trim(buf.String()), trim(test.s); s != ts {
+			t.Errorf("got:\n%s\nexpected:\n%s\n", s, ts)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/ast/resolve.go b/third_party/gofrontend/libgo/go/go/ast/resolve.go
new file mode 100644
index 0000000..0406bfc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/resolve.go
@@ -0,0 +1,174 @@
+// 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.
+
+// This file implements NewPackage.
+
+package ast
+
+import (
+	"fmt"
+	"go/scanner"
+	"go/token"
+	"strconv"
+)
+
+type pkgBuilder struct {
+	fset   *token.FileSet
+	errors scanner.ErrorList
+}
+
+func (p *pkgBuilder) error(pos token.Pos, msg string) {
+	p.errors.Add(p.fset.Position(pos), msg)
+}
+
+func (p *pkgBuilder) errorf(pos token.Pos, format string, args ...interface{}) {
+	p.error(pos, fmt.Sprintf(format, args...))
+}
+
+func (p *pkgBuilder) declare(scope, altScope *Scope, obj *Object) {
+	alt := scope.Insert(obj)
+	if alt == nil && altScope != nil {
+		// see if there is a conflicting declaration in altScope
+		alt = altScope.Lookup(obj.Name)
+	}
+	if alt != nil {
+		prevDecl := ""
+		if pos := alt.Pos(); pos.IsValid() {
+			prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", p.fset.Position(pos))
+		}
+		p.error(obj.Pos(), fmt.Sprintf("%s redeclared in this block%s", obj.Name, prevDecl))
+	}
+}
+
+func resolve(scope *Scope, ident *Ident) bool {
+	for ; scope != nil; scope = scope.Outer {
+		if obj := scope.Lookup(ident.Name); obj != nil {
+			ident.Obj = obj
+			return true
+		}
+	}
+	return false
+}
+
+// An Importer resolves import paths to package Objects.
+// The imports map records the packages already imported,
+// indexed by package id (canonical import path).
+// An Importer must determine the canonical import path and
+// check the map to see if it is already present in the imports map.
+// If so, the Importer can return the map entry.  Otherwise, the
+// Importer should load the package data for the given path into
+// a new *Object (pkg), record pkg in the imports map, and then
+// return pkg.
+type Importer func(imports map[string]*Object, path string) (pkg *Object, err error)
+
+// NewPackage creates a new Package node from a set of File nodes. It resolves
+// unresolved identifiers across files and updates each file's Unresolved list
+// accordingly. If a non-nil importer and universe scope are provided, they are
+// used to resolve identifiers not declared in any of the package files. Any
+// remaining unresolved identifiers are reported as undeclared. If the files
+// belong to different packages, one package name is selected and files with
+// different package names are reported and then ignored.
+// The result is a package node and a scanner.ErrorList if there were errors.
+//
+func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer, universe *Scope) (*Package, error) {
+	var p pkgBuilder
+	p.fset = fset
+
+	// complete package scope
+	pkgName := ""
+	pkgScope := NewScope(universe)
+	for _, file := range files {
+		// package names must match
+		switch name := file.Name.Name; {
+		case pkgName == "":
+			pkgName = name
+		case name != pkgName:
+			p.errorf(file.Package, "package %s; expected %s", name, pkgName)
+			continue // ignore this file
+		}
+
+		// collect top-level file objects in package scope
+		for _, obj := range file.Scope.Objects {
+			p.declare(pkgScope, nil, obj)
+		}
+	}
+
+	// package global mapping of imported package ids to package objects
+	imports := make(map[string]*Object)
+
+	// complete file scopes with imports and resolve identifiers
+	for _, file := range files {
+		// ignore file if it belongs to a different package
+		// (error has already been reported)
+		if file.Name.Name != pkgName {
+			continue
+		}
+
+		// build file scope by processing all imports
+		importErrors := false
+		fileScope := NewScope(pkgScope)
+		for _, spec := range file.Imports {
+			if importer == nil {
+				importErrors = true
+				continue
+			}
+			path, _ := strconv.Unquote(spec.Path.Value)
+			pkg, err := importer(imports, path)
+			if err != nil {
+				p.errorf(spec.Path.Pos(), "could not import %s (%s)", path, err)
+				importErrors = true
+				continue
+			}
+			// TODO(gri) If a local package name != "." is provided,
+			// global identifier resolution could proceed even if the
+			// import failed. Consider adjusting the logic here a bit.
+
+			// local name overrides imported package name
+			name := pkg.Name
+			if spec.Name != nil {
+				name = spec.Name.Name
+			}
+
+			// add import to file scope
+			if name == "." {
+				// merge imported scope with file scope
+				for _, obj := range pkg.Data.(*Scope).Objects {
+					p.declare(fileScope, pkgScope, obj)
+				}
+			} else if name != "_" {
+				// declare imported package object in file scope
+				// (do not re-use pkg in the file scope but create
+				// a new object instead; the Decl field is different
+				// for different files)
+				obj := NewObj(Pkg, name)
+				obj.Decl = spec
+				obj.Data = pkg.Data
+				p.declare(fileScope, pkgScope, obj)
+			}
+		}
+
+		// resolve identifiers
+		if importErrors {
+			// don't use the universe scope without correct imports
+			// (objects in the universe may be shadowed by imports;
+			// with missing imports, identifiers might get resolved
+			// incorrectly to universe objects)
+			pkgScope.Outer = nil
+		}
+		i := 0
+		for _, ident := range file.Unresolved {
+			if !resolve(fileScope, ident) {
+				p.errorf(ident.Pos(), "undeclared name: %s", ident.Name)
+				file.Unresolved[i] = ident
+				i++
+			}
+
+		}
+		file.Unresolved = file.Unresolved[0:i]
+		pkgScope.Outer = universe // reset universe scope
+	}
+
+	p.errors.Sort()
+	return &Package{pkgName, pkgScope, imports, files}, p.errors.Err()
+}
diff --git a/third_party/gofrontend/libgo/go/go/ast/scope.go b/third_party/gofrontend/libgo/go/go/ast/scope.go
new file mode 100644
index 0000000..8df5b2c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/scope.go
@@ -0,0 +1,162 @@
+// 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.
+
+// This file implements scopes and the objects they contain.
+
+package ast
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+)
+
+// A Scope maintains the set of named language entities declared
+// in the scope and a link to the immediately surrounding (outer)
+// scope.
+//
+type Scope struct {
+	Outer   *Scope
+	Objects map[string]*Object
+}
+
+// NewScope creates a new scope nested in the outer scope.
+func NewScope(outer *Scope) *Scope {
+	const n = 4 // initial scope capacity
+	return &Scope{outer, make(map[string]*Object, n)}
+}
+
+// Lookup returns the object with the given name if it is
+// found in scope s, otherwise it returns nil. Outer scopes
+// are ignored.
+//
+func (s *Scope) Lookup(name string) *Object {
+	return s.Objects[name]
+}
+
+// Insert attempts to insert a named object obj into the scope s.
+// If the scope already contains an object alt with the same name,
+// Insert leaves the scope unchanged and returns alt. Otherwise
+// it inserts obj and returns nil."
+//
+func (s *Scope) Insert(obj *Object) (alt *Object) {
+	if alt = s.Objects[obj.Name]; alt == nil {
+		s.Objects[obj.Name] = obj
+	}
+	return
+}
+
+// Debugging support
+func (s *Scope) String() string {
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "scope %p {", s)
+	if s != nil && len(s.Objects) > 0 {
+		fmt.Fprintln(&buf)
+		for _, obj := range s.Objects {
+			fmt.Fprintf(&buf, "\t%s %s\n", obj.Kind, obj.Name)
+		}
+	}
+	fmt.Fprintf(&buf, "}\n")
+	return buf.String()
+}
+
+// ----------------------------------------------------------------------------
+// Objects
+
+// An Object describes a named language entity such as a package,
+// constant, type, variable, function (incl. methods), or label.
+//
+// The Data fields contains object-specific data:
+//
+//	Kind    Data type         Data value
+//	Pkg	*types.Package    package scope
+//	Con     int               iota for the respective declaration
+//	Con     != nil            constant value
+//	Typ     *Scope            (used as method scope during type checking - transient)
+//
+type Object struct {
+	Kind ObjKind
+	Name string      // declared name
+	Decl interface{} // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil
+	Data interface{} // object-specific data; or nil
+	Type interface{} // place holder for type information; may be nil
+}
+
+// NewObj creates a new object of a given kind and name.
+func NewObj(kind ObjKind, name string) *Object {
+	return &Object{Kind: kind, Name: name}
+}
+
+// Pos computes the source position of the declaration of an object name.
+// The result may be an invalid position if it cannot be computed
+// (obj.Decl may be nil or not correct).
+func (obj *Object) Pos() token.Pos {
+	name := obj.Name
+	switch d := obj.Decl.(type) {
+	case *Field:
+		for _, n := range d.Names {
+			if n.Name == name {
+				return n.Pos()
+			}
+		}
+	case *ImportSpec:
+		if d.Name != nil && d.Name.Name == name {
+			return d.Name.Pos()
+		}
+		return d.Path.Pos()
+	case *ValueSpec:
+		for _, n := range d.Names {
+			if n.Name == name {
+				return n.Pos()
+			}
+		}
+	case *TypeSpec:
+		if d.Name.Name == name {
+			return d.Name.Pos()
+		}
+	case *FuncDecl:
+		if d.Name.Name == name {
+			return d.Name.Pos()
+		}
+	case *LabeledStmt:
+		if d.Label.Name == name {
+			return d.Label.Pos()
+		}
+	case *AssignStmt:
+		for _, x := range d.Lhs {
+			if ident, isIdent := x.(*Ident); isIdent && ident.Name == name {
+				return ident.Pos()
+			}
+		}
+	case *Scope:
+		// predeclared object - nothing to do for now
+	}
+	return token.NoPos
+}
+
+// ObjKind describes what an object represents.
+type ObjKind int
+
+// The list of possible Object kinds.
+const (
+	Bad ObjKind = iota // for error handling
+	Pkg                // package
+	Con                // constant
+	Typ                // type
+	Var                // variable
+	Fun                // function or method
+	Lbl                // label
+)
+
+var objKindStrings = [...]string{
+	Bad: "bad",
+	Pkg: "package",
+	Con: "const",
+	Typ: "type",
+	Var: "var",
+	Fun: "func",
+	Lbl: "label",
+}
+
+func (kind ObjKind) String() string { return objKindStrings[kind] }
diff --git a/third_party/gofrontend/libgo/go/go/ast/walk.go b/third_party/gofrontend/libgo/go/go/ast/walk.go
new file mode 100644
index 0000000..fedffb3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/ast/walk.go
@@ -0,0 +1,384 @@
+// 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 ast
+
+import "fmt"
+
+// A Visitor's Visit method is invoked for each node encountered by Walk.
+// If the result visitor w is not nil, Walk visits each of the children
+// of node with the visitor w, followed by a call of w.Visit(nil).
+type Visitor interface {
+	Visit(node Node) (w Visitor)
+}
+
+// Helper functions for common node lists. They may be empty.
+
+func walkIdentList(v Visitor, list []*Ident) {
+	for _, x := range list {
+		Walk(v, x)
+	}
+}
+
+func walkExprList(v Visitor, list []Expr) {
+	for _, x := range list {
+		Walk(v, x)
+	}
+}
+
+func walkStmtList(v Visitor, list []Stmt) {
+	for _, x := range list {
+		Walk(v, x)
+	}
+}
+
+func walkDeclList(v Visitor, list []Decl) {
+	for _, x := range list {
+		Walk(v, x)
+	}
+}
+
+// TODO(gri): Investigate if providing a closure to Walk leads to
+//            simpler use (and may help eliminate Inspect in turn).
+
+// Walk traverses an AST in depth-first order: It starts by calling
+// v.Visit(node); node must not be nil. If the visitor w returned by
+// v.Visit(node) is not nil, Walk is invoked recursively with visitor
+// w for each of the non-nil children of node, followed by a call of
+// w.Visit(nil).
+//
+func Walk(v Visitor, node Node) {
+	if v = v.Visit(node); v == nil {
+		return
+	}
+
+	// walk children
+	// (the order of the cases matches the order
+	// of the corresponding node types in ast.go)
+	switch n := node.(type) {
+	// Comments and fields
+	case *Comment:
+		// nothing to do
+
+	case *CommentGroup:
+		for _, c := range n.List {
+			Walk(v, c)
+		}
+
+	case *Field:
+		if n.Doc != nil {
+			Walk(v, n.Doc)
+		}
+		walkIdentList(v, n.Names)
+		Walk(v, n.Type)
+		if n.Tag != nil {
+			Walk(v, n.Tag)
+		}
+		if n.Comment != nil {
+			Walk(v, n.Comment)
+		}
+
+	case *FieldList:
+		for _, f := range n.List {
+			Walk(v, f)
+		}
+
+	// Expressions
+	case *BadExpr, *Ident, *BasicLit:
+		// nothing to do
+
+	case *Ellipsis:
+		if n.Elt != nil {
+			Walk(v, n.Elt)
+		}
+
+	case *FuncLit:
+		Walk(v, n.Type)
+		Walk(v, n.Body)
+
+	case *CompositeLit:
+		if n.Type != nil {
+			Walk(v, n.Type)
+		}
+		walkExprList(v, n.Elts)
+
+	case *ParenExpr:
+		Walk(v, n.X)
+
+	case *SelectorExpr:
+		Walk(v, n.X)
+		Walk(v, n.Sel)
+
+	case *IndexExpr:
+		Walk(v, n.X)
+		Walk(v, n.Index)
+
+	case *SliceExpr:
+		Walk(v, n.X)
+		if n.Low != nil {
+			Walk(v, n.Low)
+		}
+		if n.High != nil {
+			Walk(v, n.High)
+		}
+		if n.Max != nil {
+			Walk(v, n.Max)
+		}
+
+	case *TypeAssertExpr:
+		Walk(v, n.X)
+		if n.Type != nil {
+			Walk(v, n.Type)
+		}
+
+	case *CallExpr:
+		Walk(v, n.Fun)
+		walkExprList(v, n.Args)
+
+	case *StarExpr:
+		Walk(v, n.X)
+
+	case *UnaryExpr:
+		Walk(v, n.X)
+
+	case *BinaryExpr:
+		Walk(v, n.X)
+		Walk(v, n.Y)
+
+	case *KeyValueExpr:
+		Walk(v, n.Key)
+		Walk(v, n.Value)
+
+	// Types
+	case *ArrayType:
+		if n.Len != nil {
+			Walk(v, n.Len)
+		}
+		Walk(v, n.Elt)
+
+	case *StructType:
+		Walk(v, n.Fields)
+
+	case *FuncType:
+		if n.Params != nil {
+			Walk(v, n.Params)
+		}
+		if n.Results != nil {
+			Walk(v, n.Results)
+		}
+
+	case *InterfaceType:
+		Walk(v, n.Methods)
+
+	case *MapType:
+		Walk(v, n.Key)
+		Walk(v, n.Value)
+
+	case *ChanType:
+		Walk(v, n.Value)
+
+	// Statements
+	case *BadStmt:
+		// nothing to do
+
+	case *DeclStmt:
+		Walk(v, n.Decl)
+
+	case *EmptyStmt:
+		// nothing to do
+
+	case *LabeledStmt:
+		Walk(v, n.Label)
+		Walk(v, n.Stmt)
+
+	case *ExprStmt:
+		Walk(v, n.X)
+
+	case *SendStmt:
+		Walk(v, n.Chan)
+		Walk(v, n.Value)
+
+	case *IncDecStmt:
+		Walk(v, n.X)
+
+	case *AssignStmt:
+		walkExprList(v, n.Lhs)
+		walkExprList(v, n.Rhs)
+
+	case *GoStmt:
+		Walk(v, n.Call)
+
+	case *DeferStmt:
+		Walk(v, n.Call)
+
+	case *ReturnStmt:
+		walkExprList(v, n.Results)
+
+	case *BranchStmt:
+		if n.Label != nil {
+			Walk(v, n.Label)
+		}
+
+	case *BlockStmt:
+		walkStmtList(v, n.List)
+
+	case *IfStmt:
+		if n.Init != nil {
+			Walk(v, n.Init)
+		}
+		Walk(v, n.Cond)
+		Walk(v, n.Body)
+		if n.Else != nil {
+			Walk(v, n.Else)
+		}
+
+	case *CaseClause:
+		walkExprList(v, n.List)
+		walkStmtList(v, n.Body)
+
+	case *SwitchStmt:
+		if n.Init != nil {
+			Walk(v, n.Init)
+		}
+		if n.Tag != nil {
+			Walk(v, n.Tag)
+		}
+		Walk(v, n.Body)
+
+	case *TypeSwitchStmt:
+		if n.Init != nil {
+			Walk(v, n.Init)
+		}
+		Walk(v, n.Assign)
+		Walk(v, n.Body)
+
+	case *CommClause:
+		if n.Comm != nil {
+			Walk(v, n.Comm)
+		}
+		walkStmtList(v, n.Body)
+
+	case *SelectStmt:
+		Walk(v, n.Body)
+
+	case *ForStmt:
+		if n.Init != nil {
+			Walk(v, n.Init)
+		}
+		if n.Cond != nil {
+			Walk(v, n.Cond)
+		}
+		if n.Post != nil {
+			Walk(v, n.Post)
+		}
+		Walk(v, n.Body)
+
+	case *RangeStmt:
+		Walk(v, n.Key)
+		if n.Value != nil {
+			Walk(v, n.Value)
+		}
+		Walk(v, n.X)
+		Walk(v, n.Body)
+
+	// Declarations
+	case *ImportSpec:
+		if n.Doc != nil {
+			Walk(v, n.Doc)
+		}
+		if n.Name != nil {
+			Walk(v, n.Name)
+		}
+		Walk(v, n.Path)
+		if n.Comment != nil {
+			Walk(v, n.Comment)
+		}
+
+	case *ValueSpec:
+		if n.Doc != nil {
+			Walk(v, n.Doc)
+		}
+		walkIdentList(v, n.Names)
+		if n.Type != nil {
+			Walk(v, n.Type)
+		}
+		walkExprList(v, n.Values)
+		if n.Comment != nil {
+			Walk(v, n.Comment)
+		}
+
+	case *TypeSpec:
+		if n.Doc != nil {
+			Walk(v, n.Doc)
+		}
+		Walk(v, n.Name)
+		Walk(v, n.Type)
+		if n.Comment != nil {
+			Walk(v, n.Comment)
+		}
+
+	case *BadDecl:
+		// nothing to do
+
+	case *GenDecl:
+		if n.Doc != nil {
+			Walk(v, n.Doc)
+		}
+		for _, s := range n.Specs {
+			Walk(v, s)
+		}
+
+	case *FuncDecl:
+		if n.Doc != nil {
+			Walk(v, n.Doc)
+		}
+		if n.Recv != nil {
+			Walk(v, n.Recv)
+		}
+		Walk(v, n.Name)
+		Walk(v, n.Type)
+		if n.Body != nil {
+			Walk(v, n.Body)
+		}
+
+	// Files and packages
+	case *File:
+		if n.Doc != nil {
+			Walk(v, n.Doc)
+		}
+		Walk(v, n.Name)
+		walkDeclList(v, n.Decls)
+		// don't walk n.Comments - they have been
+		// visited already through the individual
+		// nodes
+
+	case *Package:
+		for _, f := range n.Files {
+			Walk(v, f)
+		}
+
+	default:
+		fmt.Printf("ast.Walk: unexpected node type %T", n)
+		panic("ast.Walk")
+	}
+
+	v.Visit(nil)
+}
+
+type inspector func(Node) bool
+
+func (f inspector) Visit(node Node) Visitor {
+	if f(node) {
+		return f
+	}
+	return nil
+}
+
+// Inspect traverses an AST in depth-first order: It starts by calling
+// f(node); node must not be nil. If f returns true, Inspect invokes f
+// for all the non-nil children of node, recursively.
+//
+func Inspect(node Node, f func(Node) bool) {
+	Walk(inspector(f), node)
+}
diff --git a/third_party/gofrontend/libgo/go/go/build/build.go b/third_party/gofrontend/libgo/go/go/build/build.go
new file mode 100644
index 0000000..1032c93
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/build/build.go
@@ -0,0 +1,1223 @@
+// 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.
+
+package build
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/doc"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+	pathpkg "path"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strconv"
+	"strings"
+	"unicode"
+)
+
+// A Context specifies the supporting context for a build.
+type Context struct {
+	GOARCH      string // target architecture
+	GOOS        string // target operating system
+	GOROOT      string // Go root
+	GOPATH      string // Go path
+	CgoEnabled  bool   // whether cgo can be used
+	UseAllFiles bool   // use files regardless of +build lines, file names
+	Compiler    string // compiler to assume when computing target paths
+
+	// The build and release tags specify build constraints
+	// that should be considered satisfied when processing +build lines.
+	// Clients creating a new context may customize BuildTags, which
+	// defaults to empty, but it is usually an error to customize ReleaseTags,
+	// which defaults to the list of Go releases the current release is compatible with.
+	// In addition to the BuildTags and ReleaseTags, build constraints
+	// consider the values of GOARCH and GOOS as satisfied tags.
+	BuildTags   []string
+	ReleaseTags []string
+
+	// The install suffix specifies a suffix to use in the name of the installation
+	// directory. By default it is empty, but custom builds that need to keep
+	// their outputs separate can set InstallSuffix to do so. For example, when
+	// using the race detector, the go command uses InstallSuffix = "race", so
+	// that on a Linux/386 system, packages are written to a directory named
+	// "linux_386_race" instead of the usual "linux_386".
+	InstallSuffix string
+
+	// By default, Import uses the operating system's file system calls
+	// to read directories and files.  To read from other sources,
+	// callers can set the following functions.  They all have default
+	// behaviors that use the local file system, so clients need only set
+	// the functions whose behaviors they wish to change.
+
+	// JoinPath joins the sequence of path fragments into a single path.
+	// If JoinPath is nil, Import uses filepath.Join.
+	JoinPath func(elem ...string) string
+
+	// SplitPathList splits the path list into a slice of individual paths.
+	// If SplitPathList is nil, Import uses filepath.SplitList.
+	SplitPathList func(list string) []string
+
+	// IsAbsPath reports whether path is an absolute path.
+	// If IsAbsPath is nil, Import uses filepath.IsAbs.
+	IsAbsPath func(path string) bool
+
+	// IsDir reports whether the path names a directory.
+	// If IsDir is nil, Import calls os.Stat and uses the result's IsDir method.
+	IsDir func(path string) bool
+
+	// HasSubdir reports whether dir is a subdirectory of
+	// (perhaps multiple levels below) root.
+	// If so, HasSubdir sets rel to a slash-separated path that
+	// can be joined to root to produce a path equivalent to dir.
+	// If HasSubdir is nil, Import uses an implementation built on
+	// filepath.EvalSymlinks.
+	HasSubdir func(root, dir string) (rel string, ok bool)
+
+	// ReadDir returns a slice of os.FileInfo, sorted by Name,
+	// describing the content of the named directory.
+	// If ReadDir is nil, Import uses ioutil.ReadDir.
+	ReadDir func(dir string) (fi []os.FileInfo, err error)
+
+	// OpenFile opens a file (not a directory) for reading.
+	// If OpenFile is nil, Import uses os.Open.
+	OpenFile func(path string) (r io.ReadCloser, err error)
+}
+
+// joinPath calls ctxt.JoinPath (if not nil) or else filepath.Join.
+func (ctxt *Context) joinPath(elem ...string) string {
+	if f := ctxt.JoinPath; f != nil {
+		return f(elem...)
+	}
+	return filepath.Join(elem...)
+}
+
+// splitPathList calls ctxt.SplitPathList (if not nil) or else filepath.SplitList.
+func (ctxt *Context) splitPathList(s string) []string {
+	if f := ctxt.SplitPathList; f != nil {
+		return f(s)
+	}
+	return filepath.SplitList(s)
+}
+
+// isAbsPath calls ctxt.IsAbsSPath (if not nil) or else filepath.IsAbs.
+func (ctxt *Context) isAbsPath(path string) bool {
+	if f := ctxt.IsAbsPath; f != nil {
+		return f(path)
+	}
+	return filepath.IsAbs(path)
+}
+
+// isDir calls ctxt.IsDir (if not nil) or else uses os.Stat.
+func (ctxt *Context) isDir(path string) bool {
+	if f := ctxt.IsDir; f != nil {
+		return f(path)
+	}
+	fi, err := os.Stat(path)
+	return err == nil && fi.IsDir()
+}
+
+// hasSubdir calls ctxt.HasSubdir (if not nil) or else uses
+// the local file system to answer the question.
+func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) {
+	if f := ctxt.HasSubdir; f != nil {
+		return f(root, dir)
+	}
+
+	// Try using paths we received.
+	if rel, ok = hasSubdir(root, dir); ok {
+		return
+	}
+
+	// Try expanding symlinks and comparing
+	// expanded against unexpanded and
+	// expanded against expanded.
+	rootSym, _ := filepath.EvalSymlinks(root)
+	dirSym, _ := filepath.EvalSymlinks(dir)
+
+	if rel, ok = hasSubdir(rootSym, dir); ok {
+		return
+	}
+	if rel, ok = hasSubdir(root, dirSym); ok {
+		return
+	}
+	return hasSubdir(rootSym, dirSym)
+}
+
+func hasSubdir(root, dir string) (rel string, ok bool) {
+	const sep = string(filepath.Separator)
+	root = filepath.Clean(root)
+	if !strings.HasSuffix(root, sep) {
+		root += sep
+	}
+	dir = filepath.Clean(dir)
+	if !strings.HasPrefix(dir, root) {
+		return "", false
+	}
+	return filepath.ToSlash(dir[len(root):]), true
+}
+
+// readDir calls ctxt.ReadDir (if not nil) or else ioutil.ReadDir.
+func (ctxt *Context) readDir(path string) ([]os.FileInfo, error) {
+	if f := ctxt.ReadDir; f != nil {
+		return f(path)
+	}
+	return ioutil.ReadDir(path)
+}
+
+// openFile calls ctxt.OpenFile (if not nil) or else os.Open.
+func (ctxt *Context) openFile(path string) (io.ReadCloser, error) {
+	if fn := ctxt.OpenFile; fn != nil {
+		return fn(path)
+	}
+
+	f, err := os.Open(path)
+	if err != nil {
+		return nil, err // nil interface
+	}
+	return f, nil
+}
+
+// isFile determines whether path is a file by trying to open it.
+// It reuses openFile instead of adding another function to the
+// list in Context.
+func (ctxt *Context) isFile(path string) bool {
+	f, err := ctxt.openFile(path)
+	if err != nil {
+		return false
+	}
+	f.Close()
+	return true
+}
+
+// gopath returns the list of Go path directories.
+func (ctxt *Context) gopath() []string {
+	var all []string
+	for _, p := range ctxt.splitPathList(ctxt.GOPATH) {
+		if p == "" || p == ctxt.GOROOT {
+			// Empty paths are uninteresting.
+			// If the path is the GOROOT, ignore it.
+			// People sometimes set GOPATH=$GOROOT, which is useless
+			// but would cause us to find packages with import paths
+			// like "pkg/math".
+			// Do not get confused by this common mistake.
+			continue
+		}
+		if strings.HasPrefix(p, "~") {
+			// Path segments starting with ~ on Unix are almost always
+			// users who have incorrectly quoted ~ while setting GOPATH,
+			// preventing it from expanding to $HOME.
+			// The situation is made more confusing by the fact that
+			// bash allows quoted ~ in $PATH (most shells do not).
+			// Do not get confused by this, and do not try to use the path.
+			// It does not exist, and printing errors about it confuses
+			// those users even more, because they think "sure ~ exists!".
+			// The go command diagnoses this situation and prints a
+			// useful error.
+			// On Windows, ~ is used in short names, such as c:\progra~1
+			// for c:\program files.
+			continue
+		}
+		all = append(all, p)
+	}
+	return all
+}
+
+// SrcDirs returns a list of package source root directories.
+// It draws from the current Go root and Go path but omits directories
+// that do not exist.
+func (ctxt *Context) SrcDirs() []string {
+	var all []string
+	if ctxt.GOROOT != "" {
+		dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg")
+		if ctxt.isDir(dir) {
+			all = append(all, dir)
+		}
+	}
+	for _, p := range ctxt.gopath() {
+		dir := ctxt.joinPath(p, "src")
+		if ctxt.isDir(dir) {
+			all = append(all, dir)
+		}
+	}
+	return all
+}
+
+// Default is the default Context for builds.
+// It uses the GOARCH, GOOS, GOROOT, and GOPATH environment variables
+// if set, or else the compiled code's GOARCH, GOOS, and GOROOT.
+var Default Context = defaultContext()
+
+var cgoEnabled = map[string]bool{
+	"darwin/386":      true,
+	"darwin/amd64":    true,
+	"dragonfly/386":   true,
+	"dragonfly/amd64": true,
+	"freebsd/386":     true,
+	"freebsd/amd64":   true,
+	"freebsd/arm":     true,
+	"linux/386":       true,
+	"linux/amd64":     true,
+	"linux/arm":       true,
+	"linux/s390":      true,
+	"linux/s390x":     true,
+	"netbsd/386":      true,
+	"netbsd/amd64":    true,
+	"netbsd/arm":      true,
+	"openbsd/386":     true,
+	"openbsd/amd64":   true,
+	"windows/386":     true,
+	"windows/amd64":   true,
+}
+
+func defaultContext() Context {
+	var c Context
+
+	c.GOARCH = envOr("GOARCH", runtime.GOARCH)
+	c.GOOS = envOr("GOOS", runtime.GOOS)
+	c.GOROOT = runtime.GOROOT()
+	c.GOPATH = envOr("GOPATH", "")
+	c.Compiler = runtime.Compiler
+
+	// Each major Go release in the Go 1.x series should add a tag here.
+	// Old tags should not be removed. That is, the go1.x tag is present
+	// in all releases >= Go 1.x. Code that requires Go 1.x or later should
+	// say "+build go1.x", and code that should only be built before Go 1.x
+	// (perhaps it is the stub to use in that case) should say "+build !go1.x".
+	//
+	// When we reach Go 1.4 the line will read
+	//	c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4"}
+	// and so on.
+	c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3"}
+
+	switch os.Getenv("CGO_ENABLED") {
+	case "1":
+		c.CgoEnabled = true
+	case "0":
+		c.CgoEnabled = false
+	default:
+		// cgo must be explicitly enabled for cross compilation builds
+		if runtime.GOARCH == c.GOARCH && runtime.GOOS == c.GOOS {
+			c.CgoEnabled = cgoEnabled[c.GOOS+"/"+c.GOARCH]
+			break
+		}
+		c.CgoEnabled = false
+	}
+
+	return c
+}
+
+func envOr(name, def string) string {
+	s := os.Getenv(name)
+	if s == "" {
+		return def
+	}
+	return s
+}
+
+// An ImportMode controls the behavior of the Import method.
+type ImportMode uint
+
+const (
+	// If FindOnly is set, Import stops after locating the directory
+	// that should contain the sources for a package.  It does not
+	// read any files in the directory.
+	FindOnly ImportMode = 1 << iota
+
+	// If AllowBinary is set, Import can be satisfied by a compiled
+	// package object without corresponding sources.
+	AllowBinary
+)
+
+// A Package describes the Go package found in a directory.
+type Package struct {
+	Dir         string   // directory containing package sources
+	Name        string   // package name
+	Doc         string   // documentation synopsis
+	ImportPath  string   // import path of package ("" if unknown)
+	Root        string   // root of Go tree where this package lives
+	SrcRoot     string   // package source root directory ("" if unknown)
+	PkgRoot     string   // package install root directory ("" if unknown)
+	BinDir      string   // command install directory ("" if unknown)
+	Goroot      bool     // package found in Go root
+	PkgObj      string   // installed .a file
+	AllTags     []string // tags that can influence file selection in this directory
+	ConflictDir string   // this directory shadows Dir in $GOPATH
+
+	// Source files
+	GoFiles        []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+	CgoFiles       []string // .go source files that import "C"
+	IgnoredGoFiles []string // .go source files ignored for this build
+	CFiles         []string // .c source files
+	CXXFiles       []string // .cc, .cpp and .cxx source files
+	MFiles         []string // .m (Objective-C) source files
+	HFiles         []string // .h, .hh, .hpp and .hxx source files
+	SFiles         []string // .s source files
+	SwigFiles      []string // .swig files
+	SwigCXXFiles   []string // .swigcxx files
+	SysoFiles      []string // .syso system object files to add to archive
+
+	// Cgo directives
+	CgoCFLAGS    []string // Cgo CFLAGS directives
+	CgoCPPFLAGS  []string // Cgo CPPFLAGS directives
+	CgoCXXFLAGS  []string // Cgo CXXFLAGS directives
+	CgoLDFLAGS   []string // Cgo LDFLAGS directives
+	CgoPkgConfig []string // Cgo pkg-config directives
+
+	// Dependency information
+	Imports   []string                    // imports from GoFiles, CgoFiles
+	ImportPos map[string][]token.Position // line information for Imports
+
+	// Test information
+	TestGoFiles    []string                    // _test.go files in package
+	TestImports    []string                    // imports from TestGoFiles
+	TestImportPos  map[string][]token.Position // line information for TestImports
+	XTestGoFiles   []string                    // _test.go files outside package
+	XTestImports   []string                    // imports from XTestGoFiles
+	XTestImportPos map[string][]token.Position // line information for XTestImports
+}
+
+// IsCommand reports whether the package is considered a
+// command to be installed (not just a library).
+// Packages named "main" are treated as commands.
+func (p *Package) IsCommand() bool {
+	return p.Name == "main"
+}
+
+// ImportDir is like Import but processes the Go package found in
+// the named directory.
+func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) {
+	return ctxt.Import(".", dir, mode)
+}
+
+// NoGoError is the error used by Import to describe a directory
+// containing no buildable Go source files. (It may still contain
+// test files, files hidden by build tags, and so on.)
+type NoGoError struct {
+	Dir string
+}
+
+func (e *NoGoError) Error() string {
+	return "no buildable Go source files in " + e.Dir
+}
+
+func nameExt(name string) string {
+	i := strings.LastIndex(name, ".")
+	if i < 0 {
+		return ""
+	}
+	return name[i:]
+}
+
+// Import returns details about the Go package named by the import path,
+// interpreting local import paths relative to the srcDir directory.
+// If the path is a local import path naming a package that can be imported
+// using a standard import path, the returned package will set p.ImportPath
+// to that path.
+//
+// In the directory containing the package, .go, .c, .h, and .s files are
+// considered part of the package except for:
+//
+//	- .go files in package documentation
+//	- files starting with _ or . (likely editor temporary files)
+//	- files with build constraints not satisfied by the context
+//
+// If an error occurs, Import returns a non-nil error and a non-nil
+// *Package containing partial information.
+//
+func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) {
+	p := &Package{
+		ImportPath: path,
+	}
+	if path == "" {
+		return p, fmt.Errorf("import %q: invalid import path", path)
+	}
+
+	var pkga string
+	var pkgerr error
+	switch ctxt.Compiler {
+	case "gccgo":
+		dir, elem := pathpkg.Split(p.ImportPath)
+		pkga = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + dir + "lib" + elem + ".a"
+	case "gc":
+		suffix := ""
+		if ctxt.InstallSuffix != "" {
+			suffix = "_" + ctxt.InstallSuffix
+		}
+		pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix + "/" + p.ImportPath + ".a"
+	default:
+		// Save error for end of function.
+		pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)
+	}
+
+	binaryOnly := false
+	if IsLocalImport(path) {
+		pkga = "" // local imports have no installed path
+		if srcDir == "" {
+			return p, fmt.Errorf("import %q: import relative to unknown directory", path)
+		}
+		if !ctxt.isAbsPath(path) {
+			p.Dir = ctxt.joinPath(srcDir, path)
+		}
+		// Determine canonical import path, if any.
+		if ctxt.GOROOT != "" {
+			root := ctxt.joinPath(ctxt.GOROOT, "src", "pkg")
+			if sub, ok := ctxt.hasSubdir(root, p.Dir); ok {
+				p.Goroot = true
+				p.ImportPath = sub
+				p.Root = ctxt.GOROOT
+				goto Found
+			}
+		}
+		all := ctxt.gopath()
+		for i, root := range all {
+			rootsrc := ctxt.joinPath(root, "src")
+			if sub, ok := ctxt.hasSubdir(rootsrc, p.Dir); ok {
+				// We found a potential import path for dir,
+				// but check that using it wouldn't find something
+				// else first.
+				if ctxt.GOROOT != "" {
+					if dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", sub); ctxt.isDir(dir) {
+						p.ConflictDir = dir
+						goto Found
+					}
+				}
+				for _, earlyRoot := range all[:i] {
+					if dir := ctxt.joinPath(earlyRoot, "src", sub); ctxt.isDir(dir) {
+						p.ConflictDir = dir
+						goto Found
+					}
+				}
+
+				// sub would not name some other directory instead of this one.
+				// Record it.
+				p.ImportPath = sub
+				p.Root = root
+				goto Found
+			}
+		}
+		// It's okay that we didn't find a root containing dir.
+		// Keep going with the information we have.
+	} else {
+		if strings.HasPrefix(path, "/") {
+			return p, fmt.Errorf("import %q: cannot import absolute path", path)
+		}
+
+		// tried records the location of unsuccessful package lookups
+		var tried struct {
+			goroot string
+			gopath []string
+		}
+
+		// Determine directory from import path.
+		if ctxt.GOROOT != "" {
+			dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", path)
+			isDir := ctxt.isDir(dir)
+			binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga))
+			if isDir || binaryOnly {
+				p.Dir = dir
+				p.Goroot = true
+				p.Root = ctxt.GOROOT
+				goto Found
+			}
+			tried.goroot = dir
+		}
+		for _, root := range ctxt.gopath() {
+			dir := ctxt.joinPath(root, "src", path)
+			isDir := ctxt.isDir(dir)
+			binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(root, pkga))
+			if isDir || binaryOnly {
+				p.Dir = dir
+				p.Root = root
+				goto Found
+			}
+			tried.gopath = append(tried.gopath, dir)
+		}
+
+		// package was not found
+		var paths []string
+		if tried.goroot != "" {
+			paths = append(paths, fmt.Sprintf("\t%s (from $GOROOT)", tried.goroot))
+		} else {
+			paths = append(paths, "\t($GOROOT not set)")
+		}
+		var i int
+		var format = "\t%s (from $GOPATH)"
+		for ; i < len(tried.gopath); i++ {
+			if i > 0 {
+				format = "\t%s"
+			}
+			paths = append(paths, fmt.Sprintf(format, tried.gopath[i]))
+		}
+		if i == 0 {
+			paths = append(paths, "\t($GOPATH not set)")
+		}
+		return p, fmt.Errorf("cannot find package %q in any of:\n%s", path, strings.Join(paths, "\n"))
+	}
+
+Found:
+	if p.Root != "" {
+		if p.Goroot {
+			p.SrcRoot = ctxt.joinPath(p.Root, "src", "pkg")
+		} else {
+			p.SrcRoot = ctxt.joinPath(p.Root, "src")
+		}
+		p.PkgRoot = ctxt.joinPath(p.Root, "pkg")
+		p.BinDir = ctxt.joinPath(p.Root, "bin")
+		if pkga != "" {
+			p.PkgObj = ctxt.joinPath(p.Root, pkga)
+		}
+	}
+
+	if mode&FindOnly != 0 {
+		return p, pkgerr
+	}
+	if binaryOnly && (mode&AllowBinary) != 0 {
+		return p, pkgerr
+	}
+
+	dirs, err := ctxt.readDir(p.Dir)
+	if err != nil {
+		return p, err
+	}
+
+	var Sfiles []string // files with ".S" (capital S)
+	var firstFile string
+	imported := make(map[string][]token.Position)
+	testImported := make(map[string][]token.Position)
+	xTestImported := make(map[string][]token.Position)
+	allTags := make(map[string]bool)
+	fset := token.NewFileSet()
+	for _, d := range dirs {
+		if d.IsDir() {
+			continue
+		}
+
+		name := d.Name()
+		ext := nameExt(name)
+
+		match, data, filename, err := ctxt.matchFile(p.Dir, name, true, allTags)
+		if err != nil {
+			return p, err
+		}
+		if !match {
+			if ext == ".go" {
+				p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
+			}
+			continue
+		}
+
+		// Going to save the file.  For non-Go files, can stop here.
+		switch ext {
+		case ".c":
+			p.CFiles = append(p.CFiles, name)
+			continue
+		case ".cc", ".cpp", ".cxx":
+			p.CXXFiles = append(p.CXXFiles, name)
+			continue
+		case ".m":
+			p.MFiles = append(p.MFiles, name)
+			continue
+		case ".h", ".hh", ".hpp", ".hxx":
+			p.HFiles = append(p.HFiles, name)
+			continue
+		case ".s":
+			p.SFiles = append(p.SFiles, name)
+			continue
+		case ".S":
+			Sfiles = append(Sfiles, name)
+			continue
+		case ".swig":
+			p.SwigFiles = append(p.SwigFiles, name)
+			continue
+		case ".swigcxx":
+			p.SwigCXXFiles = append(p.SwigCXXFiles, name)
+			continue
+		case ".syso":
+			// binary objects to add to package archive
+			// Likely of the form foo_windows.syso, but
+			// the name was vetted above with goodOSArchFile.
+			p.SysoFiles = append(p.SysoFiles, name)
+			continue
+		}
+
+		pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments)
+		if err != nil {
+			return p, err
+		}
+
+		pkg := pf.Name.Name
+		if pkg == "documentation" {
+			p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
+			continue
+		}
+
+		isTest := strings.HasSuffix(name, "_test.go")
+		isXTest := false
+		if isTest && strings.HasSuffix(pkg, "_test") {
+			isXTest = true
+			pkg = pkg[:len(pkg)-len("_test")]
+		}
+
+		if p.Name == "" {
+			p.Name = pkg
+			firstFile = name
+		} else if pkg != p.Name {
+			return p, fmt.Errorf("found packages %s (%s) and %s (%s) in %s", p.Name, firstFile, pkg, name, p.Dir)
+		}
+		if pf.Doc != nil && p.Doc == "" {
+			p.Doc = doc.Synopsis(pf.Doc.Text())
+		}
+
+		// Record imports and information about cgo.
+		isCgo := false
+		for _, decl := range pf.Decls {
+			d, ok := decl.(*ast.GenDecl)
+			if !ok {
+				continue
+			}
+			for _, dspec := range d.Specs {
+				spec, ok := dspec.(*ast.ImportSpec)
+				if !ok {
+					continue
+				}
+				quoted := spec.Path.Value
+				path, err := strconv.Unquote(quoted)
+				if err != nil {
+					log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted)
+				}
+				if isXTest {
+					xTestImported[path] = append(xTestImported[path], fset.Position(spec.Pos()))
+				} else if isTest {
+					testImported[path] = append(testImported[path], fset.Position(spec.Pos()))
+				} else {
+					imported[path] = append(imported[path], fset.Position(spec.Pos()))
+				}
+				if path == "C" {
+					if isTest {
+						return p, fmt.Errorf("use of cgo in test %s not supported", filename)
+					}
+					cg := spec.Doc
+					if cg == nil && len(d.Specs) == 1 {
+						cg = d.Doc
+					}
+					if cg != nil {
+						if err := ctxt.saveCgo(filename, p, cg); err != nil {
+							return p, err
+						}
+					}
+					isCgo = true
+				}
+			}
+		}
+		if isCgo {
+			allTags["cgo"] = true
+			if ctxt.CgoEnabled {
+				p.CgoFiles = append(p.CgoFiles, name)
+			} else {
+				p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
+			}
+		} else if isXTest {
+			p.XTestGoFiles = append(p.XTestGoFiles, name)
+		} else if isTest {
+			p.TestGoFiles = append(p.TestGoFiles, name)
+		} else {
+			p.GoFiles = append(p.GoFiles, name)
+		}
+	}
+	if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
+		return p, &NoGoError{p.Dir}
+	}
+
+	for tag := range allTags {
+		p.AllTags = append(p.AllTags, tag)
+	}
+	sort.Strings(p.AllTags)
+
+	p.Imports, p.ImportPos = cleanImports(imported)
+	p.TestImports, p.TestImportPos = cleanImports(testImported)
+	p.XTestImports, p.XTestImportPos = cleanImports(xTestImported)
+
+	// add the .S files only if we are using cgo
+	// (which means gcc will compile them).
+	// The standard assemblers expect .s files.
+	if len(p.CgoFiles) > 0 {
+		p.SFiles = append(p.SFiles, Sfiles...)
+		sort.Strings(p.SFiles)
+	}
+
+	return p, pkgerr
+}
+
+// MatchFile reports whether the file with the given name in the given directory
+// matches the context and would be included in a Package created by ImportDir
+// of that directory.
+//
+// MatchFile considers the name of the file and may use ctxt.OpenFile to
+// read some or all of the file's content.
+func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) {
+	match, _, _, err = ctxt.matchFile(dir, name, false, nil)
+	return
+}
+
+// matchFile determines whether the file with the given name in the given directory
+// should be included in the package being constructed.
+// It returns the data read from the file.
+// If returnImports is true and name denotes a Go program, matchFile reads
+// until the end of the imports (and returns that data) even though it only
+// considers text until the first non-comment.
+// If allTags is non-nil, matchFile records any encountered build tag
+// by setting allTags[tag] = true.
+func (ctxt *Context) matchFile(dir, name string, returnImports bool, allTags map[string]bool) (match bool, data []byte, filename string, err error) {
+	if strings.HasPrefix(name, "_") ||
+		strings.HasPrefix(name, ".") {
+		return
+	}
+
+	i := strings.LastIndex(name, ".")
+	if i < 0 {
+		i = len(name)
+	}
+	ext := name[i:]
+
+	if !ctxt.goodOSArchFile(name, allTags) && !ctxt.UseAllFiles {
+		return
+	}
+
+	switch ext {
+	case ".go", ".c", ".cc", ".cxx", ".cpp", ".m", ".s", ".h", ".hh", ".hpp", ".hxx", ".S", ".swig", ".swigcxx":
+		// tentatively okay - read to make sure
+	case ".syso":
+		// binary, no reading
+		match = true
+		return
+	default:
+		// skip
+		return
+	}
+
+	filename = ctxt.joinPath(dir, name)
+	f, err := ctxt.openFile(filename)
+	if err != nil {
+		return
+	}
+
+	if strings.HasSuffix(filename, ".go") {
+		data, err = readImports(f, false)
+	} else {
+		data, err = readComments(f)
+	}
+	f.Close()
+	if err != nil {
+		err = fmt.Errorf("read %s: %v", filename, err)
+		return
+	}
+
+	// Look for +build comments to accept or reject the file.
+	if !ctxt.shouldBuild(data, allTags) && !ctxt.UseAllFiles {
+		return
+	}
+
+	match = true
+	return
+}
+
+func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.Position) {
+	all := make([]string, 0, len(m))
+	for path := range m {
+		all = append(all, path)
+	}
+	sort.Strings(all)
+	return all, m
+}
+
+// Import is shorthand for Default.Import.
+func Import(path, srcDir string, mode ImportMode) (*Package, error) {
+	return Default.Import(path, srcDir, mode)
+}
+
+// ImportDir is shorthand for Default.ImportDir.
+func ImportDir(dir string, mode ImportMode) (*Package, error) {
+	return Default.ImportDir(dir, mode)
+}
+
+var slashslash = []byte("//")
+
+// shouldBuild reports whether it is okay to use this file,
+// The rule is that in the file's leading run of // comments
+// and blank lines, which must be followed by a blank line
+// (to avoid including a Go package clause doc comment),
+// lines beginning with '// +build' are taken as build directives.
+//
+// The file is accepted only if each such line lists something
+// matching the file.  For example:
+//
+//	// +build windows linux
+//
+// marks the file as applicable only on Windows and Linux.
+//
+func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool) bool {
+	// Pass 1. Identify leading run of // comments and blank lines,
+	// which must be followed by a blank line.
+	end := 0
+	p := content
+	for len(p) > 0 {
+		line := p
+		if i := bytes.IndexByte(line, '\n'); i >= 0 {
+			line, p = line[:i], p[i+1:]
+		} else {
+			p = p[len(p):]
+		}
+		line = bytes.TrimSpace(line)
+		if len(line) == 0 { // Blank line
+			end = len(content) - len(p)
+			continue
+		}
+		if !bytes.HasPrefix(line, slashslash) { // Not comment line
+			break
+		}
+	}
+	content = content[:end]
+
+	// Pass 2.  Process each line in the run.
+	p = content
+	allok := true
+	for len(p) > 0 {
+		line := p
+		if i := bytes.IndexByte(line, '\n'); i >= 0 {
+			line, p = line[:i], p[i+1:]
+		} else {
+			p = p[len(p):]
+		}
+		line = bytes.TrimSpace(line)
+		if bytes.HasPrefix(line, slashslash) {
+			line = bytes.TrimSpace(line[len(slashslash):])
+			if len(line) > 0 && line[0] == '+' {
+				// Looks like a comment +line.
+				f := strings.Fields(string(line))
+				if f[0] == "+build" {
+					ok := false
+					for _, tok := range f[1:] {
+						if ctxt.match(tok, allTags) {
+							ok = true
+						}
+					}
+					if !ok {
+						allok = false
+					}
+				}
+			}
+		}
+	}
+
+	return allok
+}
+
+// saveCgo saves the information from the #cgo lines in the import "C" comment.
+// These lines set CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS and pkg-config directives
+// that affect the way cgo's C code is built.
+//
+// TODO(rsc): This duplicates code in cgo.
+// Once the dust settles, remove this code from cgo.
+func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) error {
+	text := cg.Text()
+	for _, line := range strings.Split(text, "\n") {
+		orig := line
+
+		// Line is
+		//	#cgo [GOOS/GOARCH...] LDFLAGS: stuff
+		//
+		line = strings.TrimSpace(line)
+		if len(line) < 5 || line[:4] != "#cgo" || (line[4] != ' ' && line[4] != '\t') {
+			continue
+		}
+
+		// Split at colon.
+		line = strings.TrimSpace(line[4:])
+		i := strings.Index(line, ":")
+		if i < 0 {
+			return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
+		}
+		line, argstr := line[:i], line[i+1:]
+
+		// Parse GOOS/GOARCH stuff.
+		f := strings.Fields(line)
+		if len(f) < 1 {
+			return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
+		}
+
+		cond, verb := f[:len(f)-1], f[len(f)-1]
+		if len(cond) > 0 {
+			ok := false
+			for _, c := range cond {
+				if ctxt.match(c, nil) {
+					ok = true
+					break
+				}
+			}
+			if !ok {
+				continue
+			}
+		}
+
+		args, err := splitQuoted(argstr)
+		if err != nil {
+			return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
+		}
+		for _, arg := range args {
+			if !safeCgoName(arg) {
+				return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg)
+			}
+		}
+
+		switch verb {
+		case "CFLAGS":
+			di.CgoCFLAGS = append(di.CgoCFLAGS, args...)
+		case "CPPFLAGS":
+			di.CgoCPPFLAGS = append(di.CgoCPPFLAGS, args...)
+		case "CXXFLAGS":
+			di.CgoCXXFLAGS = append(di.CgoCXXFLAGS, args...)
+		case "LDFLAGS":
+			di.CgoLDFLAGS = append(di.CgoLDFLAGS, args...)
+		case "pkg-config":
+			di.CgoPkgConfig = append(di.CgoPkgConfig, args...)
+		default:
+			return fmt.Errorf("%s: invalid #cgo verb: %s", filename, orig)
+		}
+	}
+	return nil
+}
+
+// NOTE: $ is not safe for the shell, but it is allowed here because of linker options like -Wl,$ORIGIN.
+// We never pass these arguments to a shell (just to programs we construct argv for), so this should be okay.
+// See golang.org/issue/6038.
+var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$")
+
+func safeCgoName(s string) bool {
+	if s == "" {
+		return false
+	}
+	for i := 0; i < len(s); i++ {
+		if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
+			return false
+		}
+	}
+	return true
+}
+
+// splitQuoted splits the string s around each instance of one or more consecutive
+// white space characters while taking into account quotes and escaping, and
+// returns an array of substrings of s or an empty list if s contains only white space.
+// Single quotes and double quotes are recognized to prevent splitting within the
+// quoted region, and are removed from the resulting substrings. If a quote in s
+// isn't closed err will be set and r will have the unclosed argument as the
+// last element.  The backslash is used for escaping.
+//
+// For example, the following string:
+//
+//     a b:"c d" 'e''f'  "g\""
+//
+// Would be parsed as:
+//
+//     []string{"a", "b:c d", "ef", `g"`}
+//
+func splitQuoted(s string) (r []string, err error) {
+	var args []string
+	arg := make([]rune, len(s))
+	escaped := false
+	quoted := false
+	quote := '\x00'
+	i := 0
+	for _, rune := range s {
+		switch {
+		case escaped:
+			escaped = false
+		case rune == '\\':
+			escaped = true
+			continue
+		case quote != '\x00':
+			if rune == quote {
+				quote = '\x00'
+				continue
+			}
+		case rune == '"' || rune == '\'':
+			quoted = true
+			quote = rune
+			continue
+		case unicode.IsSpace(rune):
+			if quoted || i > 0 {
+				quoted = false
+				args = append(args, string(arg[:i]))
+				i = 0
+			}
+			continue
+		}
+		arg[i] = rune
+		i++
+	}
+	if quoted || i > 0 {
+		args = append(args, string(arg[:i]))
+	}
+	if quote != 0 {
+		err = errors.New("unclosed quote")
+	} else if escaped {
+		err = errors.New("unfinished escaping")
+	}
+	return args, err
+}
+
+// match returns true if the name is one of:
+//
+//	$GOOS
+//	$GOARCH
+//	cgo (if cgo is enabled)
+//	!cgo (if cgo is disabled)
+//	ctxt.Compiler
+//	!ctxt.Compiler
+//	tag (if tag is listed in ctxt.BuildTags or ctxt.ReleaseTags)
+//	!tag (if tag is not listed in ctxt.BuildTags or ctxt.ReleaseTags)
+//	a comma-separated list of any of these
+//
+func (ctxt *Context) match(name string, allTags map[string]bool) bool {
+	if name == "" {
+		if allTags != nil {
+			allTags[name] = true
+		}
+		return false
+	}
+	if i := strings.Index(name, ","); i >= 0 {
+		// comma-separated list
+		ok1 := ctxt.match(name[:i], allTags)
+		ok2 := ctxt.match(name[i+1:], allTags)
+		return ok1 && ok2
+	}
+	if strings.HasPrefix(name, "!!") { // bad syntax, reject always
+		return false
+	}
+	if strings.HasPrefix(name, "!") { // negation
+		return len(name) > 1 && !ctxt.match(name[1:], allTags)
+	}
+
+	if allTags != nil {
+		allTags[name] = true
+	}
+
+	// Tags must be letters, digits, underscores or dots.
+	// Unlike in Go identifiers, all digits are fine (e.g., "386").
+	for _, c := range name {
+		if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
+			return false
+		}
+	}
+
+	// special tags
+	if ctxt.CgoEnabled && name == "cgo" {
+		return true
+	}
+	if name == ctxt.GOOS || name == ctxt.GOARCH || name == ctxt.Compiler {
+		return true
+	}
+
+	// other tags
+	for _, tag := range ctxt.BuildTags {
+		if tag == name {
+			return true
+		}
+	}
+	for _, tag := range ctxt.ReleaseTags {
+		if tag == name {
+			return true
+		}
+	}
+
+	return false
+}
+
+// goodOSArchFile returns false if the name contains a $GOOS or $GOARCH
+// suffix which does not match the current system.
+// The recognized name formats are:
+//
+//     name_$(GOOS).*
+//     name_$(GOARCH).*
+//     name_$(GOOS)_$(GOARCH).*
+//     name_$(GOOS)_test.*
+//     name_$(GOARCH)_test.*
+//     name_$(GOOS)_$(GOARCH)_test.*
+//
+func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool {
+	if dot := strings.Index(name, "."); dot != -1 {
+		name = name[:dot]
+	}
+	l := strings.Split(name, "_")
+	if n := len(l); n > 0 && l[n-1] == "test" {
+		l = l[:n-1]
+	}
+	n := len(l)
+	if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] {
+		if allTags != nil {
+			allTags[l[n-2]] = true
+			allTags[l[n-1]] = true
+		}
+		return l[n-2] == ctxt.GOOS && l[n-1] == ctxt.GOARCH
+	}
+	if n >= 1 && knownOS[l[n-1]] {
+		if allTags != nil {
+			allTags[l[n-1]] = true
+		}
+		return l[n-1] == ctxt.GOOS
+	}
+	if n >= 1 && knownArch[l[n-1]] {
+		if allTags != nil {
+			allTags[l[n-1]] = true
+		}
+		return l[n-1] == ctxt.GOARCH
+	}
+	return true
+}
+
+var knownOS = make(map[string]bool)
+var knownArch = make(map[string]bool)
+
+func init() {
+	for _, v := range strings.Fields(goosList) {
+		knownOS[v] = true
+	}
+	for _, v := range strings.Fields(goarchList) {
+		knownArch[v] = true
+	}
+}
+
+// ToolDir is the directory containing build tools.
+var ToolDir = filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
+
+// IsLocalImport reports whether the import path is
+// a local import path, like ".", "..", "./foo", or "../foo".
+func IsLocalImport(path string) bool {
+	return path == "." || path == ".." ||
+		strings.HasPrefix(path, "./") || strings.HasPrefix(path, "../")
+}
+
+// ArchChar returns the architecture character for the given goarch.
+// For example, ArchChar("amd64") returns "6".
+func ArchChar(goarch string) (string, error) {
+	switch goarch {
+	case "386":
+		return "8", nil
+	case "amd64", "amd64p32":
+		return "6", nil
+	case "arm":
+		return "5", nil
+	case "arm64":
+		return "7", nil
+	}
+	return "", errors.New("unsupported GOARCH " + goarch)
+}
diff --git a/third_party/gofrontend/libgo/go/go/build/build_test.go b/third_party/gofrontend/libgo/go/go/build/build_test.go
new file mode 100644
index 0000000..fca8d4b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/build/build_test.go
@@ -0,0 +1,186 @@
+// 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.
+
+package build
+
+import (
+	"io"
+	"os"
+	"path/filepath"
+	"reflect"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+func TestMatch(t *testing.T) {
+	ctxt := Default
+	what := "default"
+	match := func(tag string, want map[string]bool) {
+		m := make(map[string]bool)
+		if !ctxt.match(tag, m) {
+			t.Errorf("%s context should match %s, does not", what, tag)
+		}
+		if !reflect.DeepEqual(m, want) {
+			t.Errorf("%s tags = %v, want %v", tag, m, want)
+		}
+	}
+	nomatch := func(tag string, want map[string]bool) {
+		m := make(map[string]bool)
+		if ctxt.match(tag, m) {
+			t.Errorf("%s context should NOT match %s, does", what, tag)
+		}
+		if !reflect.DeepEqual(m, want) {
+			t.Errorf("%s tags = %v, want %v", tag, m, want)
+		}
+	}
+
+	match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true})
+	match(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+	nomatch(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+
+	what = "modified"
+	ctxt.BuildTags = []string{"foo"}
+	match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true})
+	match(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+	nomatch(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+	match(runtime.GOOS+","+runtime.GOARCH+",!bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
+	nomatch(runtime.GOOS+","+runtime.GOARCH+",bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
+	nomatch("!", map[string]bool{})
+}
+
+func TestDotSlashImport(t *testing.T) {
+	p, err := ImportDir("testdata/other", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(p.Imports) != 1 || p.Imports[0] != "./file" {
+		t.Fatalf("testdata/other: Imports=%v, want [./file]", p.Imports)
+	}
+
+	p1, err := Import("./file", "testdata/other", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if p1.Name != "file" {
+		t.Fatalf("./file: Name=%q, want %q", p1.Name, "file")
+	}
+	dir := filepath.Clean("testdata/other/file") // Clean to use \ on Windows
+	if p1.Dir != dir {
+		t.Fatalf("./file: Dir=%q, want %q", p1.Name, dir)
+	}
+}
+
+func TestEmptyImport(t *testing.T) {
+	p, err := Import("", Default.GOROOT, FindOnly)
+	if err == nil {
+		t.Fatal(`Import("") returned nil error.`)
+	}
+	if p == nil {
+		t.Fatal(`Import("") returned nil package.`)
+	}
+	if p.ImportPath != "" {
+		t.Fatalf("ImportPath=%q, want %q.", p.ImportPath, "")
+	}
+}
+
+func TestLocalDirectory(t *testing.T) {
+	cwd, err := os.Getwd()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	p, err := ImportDir(cwd, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if p.ImportPath != "go/build" {
+		t.Fatalf("ImportPath=%q, want %q", p.ImportPath, "go/build")
+	}
+}
+
+func TestShouldBuild(t *testing.T) {
+	const file1 = "// +build tag1\n\n" +
+		"package main\n"
+	want1 := map[string]bool{"tag1": true}
+
+	const file2 = "// +build cgo\n\n" +
+		"// This package implements parsing of tags like\n" +
+		"// +build tag1\n" +
+		"package build"
+	want2 := map[string]bool{"cgo": true}
+
+	const file3 = "// Copyright The Go Authors.\n\n" +
+		"package build\n\n" +
+		"// shouldBuild checks tags given by lines of the form\n" +
+		"// +build tag\n" +
+		"func shouldBuild(content []byte)\n"
+	want3 := map[string]bool{}
+
+	ctx := &Context{BuildTags: []string{"tag1"}}
+	m := map[string]bool{}
+	if !ctx.shouldBuild([]byte(file1), m) {
+		t.Errorf("shouldBuild(file1) = false, want true")
+	}
+	if !reflect.DeepEqual(m, want1) {
+		t.Errorf("shoudBuild(file1) tags = %v, want %v", m, want1)
+	}
+
+	m = map[string]bool{}
+	if ctx.shouldBuild([]byte(file2), m) {
+		t.Errorf("shouldBuild(file2) = true, want fakse")
+	}
+	if !reflect.DeepEqual(m, want2) {
+		t.Errorf("shoudBuild(file2) tags = %v, want %v", m, want2)
+	}
+
+	m = map[string]bool{}
+	ctx = &Context{BuildTags: nil}
+	if !ctx.shouldBuild([]byte(file3), m) {
+		t.Errorf("shouldBuild(file3) = false, want true")
+	}
+	if !reflect.DeepEqual(m, want3) {
+		t.Errorf("shoudBuild(file3) tags = %v, want %v", m, want3)
+	}
+}
+
+type readNopCloser struct {
+	io.Reader
+}
+
+func (r readNopCloser) Close() error {
+	return nil
+}
+
+var matchFileTests = []struct {
+	name  string
+	data  string
+	match bool
+}{
+	{"foo_arm.go", "", true},
+	{"foo1_arm.go", "// +build linux\n\npackage main\n", false},
+	{"foo_darwin.go", "", false},
+	{"foo.go", "", true},
+	{"foo1.go", "// +build linux\n\npackage main\n", false},
+	{"foo.badsuffix", "", false},
+}
+
+func TestMatchFile(t *testing.T) {
+	for _, tt := range matchFileTests {
+		ctxt := Context{GOARCH: "arm", GOOS: "plan9"}
+		ctxt.OpenFile = func(path string) (r io.ReadCloser, err error) {
+			if path != "x+"+tt.name {
+				t.Fatalf("OpenFile asked for %q, expected %q", path, "x+"+tt.name)
+			}
+			return &readNopCloser{strings.NewReader(tt.data)}, nil
+		}
+		ctxt.JoinPath = func(elem ...string) string {
+			return strings.Join(elem, "+")
+		}
+		match, err := ctxt.MatchFile("x", tt.name)
+		if match != tt.match || err != nil {
+			t.Fatalf("MatchFile(%q) = %v, %v, want %v, nil", tt.name, match, err, tt.match)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/build/deps_test.go b/third_party/gofrontend/libgo/go/go/build/deps_test.go
new file mode 100644
index 0000000..3a795fd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/build/deps_test.go
@@ -0,0 +1,442 @@
+// 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.
+
+// This file exercises the import parser but also checks that
+// some low-level packages do not have new dependencies added.
+
+package build
+
+import (
+	"runtime"
+	"sort"
+	"testing"
+)
+
+// pkgDeps defines the expected dependencies between packages in
+// the Go source tree.  It is a statement of policy.
+// Changes should not be made to this map without prior discussion.
+//
+// The map contains two kinds of entries:
+// 1) Lower-case keys are standard import paths and list the
+// allowed imports in that package.
+// 2) Upper-case keys define aliases for package sets, which can then
+// be used as dependencies by other rules.
+//
+// DO NOT CHANGE THIS DATA TO FIX BUILDS.
+//
+var pkgDeps = map[string][]string{
+	// L0 is the lowest level, core, nearly unavoidable packages.
+	"errors":      {},
+	"io":          {"errors", "sync"},
+	"runtime":     {"unsafe"},
+	"sync":        {"runtime", "sync/atomic", "unsafe"},
+	"sync/atomic": {"unsafe"},
+	"unsafe":      {},
+
+	"L0": {
+		"errors",
+		"io",
+		"runtime",
+		"sync",
+		"sync/atomic",
+		"unsafe",
+	},
+
+	// L1 adds simple functions and strings processing,
+	// but not Unicode tables.
+	"math":          {"unsafe"},
+	"math/cmplx":    {"math"},
+	"math/rand":     {"L0", "math"},
+	"sort":          {},
+	"strconv":       {"L0", "unicode/utf8", "math"},
+	"unicode/utf16": {},
+	"unicode/utf8":  {},
+
+	"L1": {
+		"L0",
+		"math",
+		"math/cmplx",
+		"math/rand",
+		"sort",
+		"strconv",
+		"unicode/utf16",
+		"unicode/utf8",
+	},
+
+	// L2 adds Unicode and strings processing.
+	"bufio":   {"L0", "unicode/utf8", "bytes"},
+	"bytes":   {"L0", "unicode", "unicode/utf8"},
+	"path":    {"L0", "unicode/utf8", "strings"},
+	"strings": {"L0", "unicode", "unicode/utf8"},
+	"unicode": {},
+
+	"L2": {
+		"L1",
+		"bufio",
+		"bytes",
+		"path",
+		"strings",
+		"unicode",
+	},
+
+	// L3 adds reflection and some basic utility packages
+	// and interface definitions, but nothing that makes
+	// system calls.
+	"crypto":              {"L2", "hash"},          // interfaces
+	"crypto/cipher":       {"L2", "crypto/subtle"}, // interfaces
+	"crypto/subtle":       {},
+	"encoding/base32":     {"L2"},
+	"encoding/base64":     {"L2"},
+	"encoding/binary":     {"L2", "reflect"},
+	"hash":                {"L2"}, // interfaces
+	"hash/adler32":        {"L2", "hash"},
+	"hash/crc32":          {"L2", "hash"},
+	"hash/crc64":          {"L2", "hash"},
+	"hash/fnv":            {"L2", "hash"},
+	"image":               {"L2", "image/color"}, // interfaces
+	"image/color":         {"L2"},                // interfaces
+	"image/color/palette": {"L2", "image/color"},
+	"reflect":             {"L2"},
+
+	"L3": {
+		"L2",
+		"crypto",
+		"crypto/cipher",
+		"crypto/subtle",
+		"encoding/base32",
+		"encoding/base64",
+		"encoding/binary",
+		"hash",
+		"hash/adler32",
+		"hash/crc32",
+		"hash/crc64",
+		"hash/fnv",
+		"image",
+		"image/color",
+		"image/color/palette",
+		"reflect",
+	},
+
+	// End of linear dependency definitions.
+
+	// Operating system access.
+	"syscall":       {"L0", "unicode/utf16"},
+	"time":          {"L0", "syscall"},
+	"os":            {"L1", "os", "syscall", "time"},
+	"path/filepath": {"L2", "os", "syscall"},
+	"io/ioutil":     {"L2", "os", "path/filepath", "time"},
+	"os/exec":       {"L2", "os", "path/filepath", "syscall"},
+	"os/signal":     {"L2", "os", "syscall"},
+
+	// OS enables basic operating system functionality,
+	// but not direct use of package syscall, nor os/signal.
+	"OS": {
+		"io/ioutil",
+		"os",
+		"os/exec",
+		"path/filepath",
+		"time",
+	},
+
+	// Formatted I/O: few dependencies (L1) but we must add reflect.
+	"fmt": {"L1", "os", "reflect"},
+	"log": {"L1", "os", "fmt", "time"},
+
+	// Packages used by testing must be low-level (L2+fmt).
+	"regexp":         {"L2", "regexp/syntax"},
+	"regexp/syntax":  {"L2"},
+	"runtime/debug":  {"L2", "fmt", "io/ioutil", "os", "time"},
+	"runtime/pprof":  {"L2", "fmt", "text/tabwriter"},
+	"text/tabwriter": {"L2"},
+
+	"testing":        {"L2", "flag", "fmt", "os", "runtime/pprof", "time"},
+	"testing/iotest": {"L2", "log"},
+	"testing/quick":  {"L2", "flag", "fmt", "reflect"},
+
+	// L4 is defined as L3+fmt+log+time, because in general once
+	// you're using L3 packages, use of fmt, log, or time is not a big deal.
+	"L4": {
+		"L3",
+		"fmt",
+		"log",
+		"time",
+	},
+
+	// Go parser.
+	"go/ast":     {"L4", "OS", "go/scanner", "go/token"},
+	"go/doc":     {"L4", "go/ast", "go/token", "regexp", "text/template"},
+	"go/parser":  {"L4", "OS", "go/ast", "go/scanner", "go/token"},
+	"go/printer": {"L4", "OS", "go/ast", "go/scanner", "go/token", "text/tabwriter"},
+	"go/scanner": {"L4", "OS", "go/token"},
+	"go/token":   {"L4"},
+
+	"GOPARSER": {
+		"go/ast",
+		"go/doc",
+		"go/parser",
+		"go/printer",
+		"go/scanner",
+		"go/token",
+	},
+
+	// One of a kind.
+	"archive/tar":         {"L4", "OS", "syscall"},
+	"archive/zip":         {"L4", "OS", "compress/flate"},
+	"compress/bzip2":      {"L4"},
+	"compress/flate":      {"L4"},
+	"compress/gzip":       {"L4", "compress/flate"},
+	"compress/lzw":        {"L4"},
+	"compress/zlib":       {"L4", "compress/flate"},
+	"database/sql":        {"L4", "container/list", "database/sql/driver"},
+	"database/sql/driver": {"L4", "time"},
+	"debug/dwarf":         {"L4"},
+	"debug/elf":           {"L4", "OS", "debug/dwarf"},
+	"debug/gosym":         {"L4"},
+	"debug/macho":         {"L4", "OS", "debug/dwarf"},
+	"debug/pe":            {"L4", "OS", "debug/dwarf"},
+	"encoding":            {"L4"},
+	"encoding/ascii85":    {"L4"},
+	"encoding/asn1":       {"L4", "math/big"},
+	"encoding/csv":        {"L4"},
+	"encoding/gob":        {"L4", "OS", "encoding"},
+	"encoding/hex":        {"L4"},
+	"encoding/json":       {"L4", "encoding"},
+	"encoding/pem":        {"L4"},
+	"encoding/xml":        {"L4", "encoding"},
+	"flag":                {"L4", "OS"},
+	"go/build":            {"L4", "OS", "GOPARSER"},
+	"html":                {"L4"},
+	"image/draw":          {"L4"},
+	"image/gif":           {"L4", "compress/lzw", "image/color/palette", "image/draw"},
+	"image/jpeg":          {"L4"},
+	"image/png":           {"L4", "compress/zlib"},
+	"index/suffixarray":   {"L4", "regexp"},
+	"math/big":            {"L4"},
+	"mime":                {"L4", "OS", "syscall"},
+	"net/url":             {"L4"},
+	"text/scanner":        {"L4", "OS"},
+	"text/template/parse": {"L4"},
+
+	"html/template": {
+		"L4", "OS", "encoding/json", "html", "text/template",
+		"text/template/parse",
+	},
+	"text/template": {
+		"L4", "OS", "net/url", "text/template/parse",
+	},
+
+	// Cgo.
+	"runtime/cgo": {"L0", "C"},
+	"CGO":         {"C", "runtime/cgo"},
+
+	// Fake entry to satisfy the pseudo-import "C"
+	// that shows up in programs that use cgo.
+	"C": {},
+
+	// Plan 9 alone needs io/ioutil and os.
+	"os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
+
+	// Basic networking.
+	// Because net must be used by any package that wants to
+	// do networking portably, it must have a small dependency set: just L1+basic os.
+	"net": {"L1", "CGO", "os", "syscall", "time"},
+
+	// NET enables use of basic network-related packages.
+	"NET": {
+		"net",
+		"mime",
+		"net/textproto",
+		"net/url",
+	},
+
+	// Uses of networking.
+	"log/syslog":    {"L4", "OS", "net"},
+	"net/mail":      {"L4", "NET", "OS"},
+	"net/textproto": {"L4", "OS", "net"},
+
+	// Core crypto.
+	"crypto/aes":    {"L3"},
+	"crypto/des":    {"L3"},
+	"crypto/hmac":   {"L3"},
+	"crypto/md5":    {"L3"},
+	"crypto/rc4":    {"L3"},
+	"crypto/sha1":   {"L3"},
+	"crypto/sha256": {"L3"},
+	"crypto/sha512": {"L3"},
+
+	"CRYPTO": {
+		"crypto/aes",
+		"crypto/des",
+		"crypto/hmac",
+		"crypto/md5",
+		"crypto/rc4",
+		"crypto/sha1",
+		"crypto/sha256",
+		"crypto/sha512",
+	},
+
+	// Random byte, number generation.
+	// This would be part of core crypto except that it imports
+	// math/big, which imports fmt.
+	"crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall"},
+
+	// Mathematical crypto: dependencies on fmt (L4) and math/big.
+	// We could avoid some of the fmt, but math/big imports fmt anyway.
+	"crypto/dsa":      {"L4", "CRYPTO", "math/big"},
+	"crypto/ecdsa":    {"L4", "CRYPTO", "crypto/elliptic", "math/big"},
+	"crypto/elliptic": {"L4", "CRYPTO", "math/big"},
+	"crypto/rsa":      {"L4", "CRYPTO", "crypto/rand", "math/big"},
+
+	"CRYPTO-MATH": {
+		"CRYPTO",
+		"crypto/dsa",
+		"crypto/ecdsa",
+		"crypto/elliptic",
+		"crypto/rand",
+		"crypto/rsa",
+		"encoding/asn1",
+		"math/big",
+	},
+
+	// SSL/TLS.
+	"crypto/tls": {
+		"L4", "CRYPTO-MATH", "CGO", "OS",
+		"container/list", "crypto/x509", "encoding/pem", "net", "syscall",
+	},
+	"crypto/x509": {
+		"L4", "CRYPTO-MATH", "OS", "CGO",
+		"crypto/x509/pkix", "encoding/pem", "encoding/hex", "net", "syscall",
+	},
+	"crypto/x509/pkix": {"L4", "CRYPTO-MATH"},
+
+	// Simple net+crypto-aware packages.
+	"mime/multipart": {"L4", "OS", "mime", "crypto/rand", "net/textproto"},
+	"net/smtp":       {"L4", "CRYPTO", "NET", "crypto/tls"},
+
+	// HTTP, kingpin of dependencies.
+	"net/http": {
+		"L4", "NET", "OS",
+		"compress/gzip", "crypto/tls", "mime/multipart", "runtime/debug",
+	},
+
+	// HTTP-using packages.
+	"expvar":            {"L4", "OS", "encoding/json", "net/http"},
+	"net/http/cgi":      {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"},
+	"net/http/fcgi":     {"L4", "NET", "OS", "net/http", "net/http/cgi"},
+	"net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"},
+	"net/http/httputil": {"L4", "NET", "OS", "net/http"},
+	"net/http/pprof":    {"L4", "OS", "html/template", "net/http", "runtime/pprof"},
+	"net/rpc":           {"L4", "NET", "encoding/gob", "net/http", "text/template"},
+	"net/rpc/jsonrpc":   {"L4", "NET", "encoding/json", "net/rpc"},
+}
+
+// isMacro reports whether p is a package dependency macro
+// (uppercase name).
+func isMacro(p string) bool {
+	return 'A' <= p[0] && p[0] <= 'Z'
+}
+
+func allowed(pkg string) map[string]bool {
+	m := map[string]bool{}
+	var allow func(string)
+	allow = func(p string) {
+		if m[p] {
+			return
+		}
+		m[p] = true // set even for macros, to avoid loop on cycle
+
+		// Upper-case names are macro-expanded.
+		if isMacro(p) {
+			for _, pp := range pkgDeps[p] {
+				allow(pp)
+			}
+		}
+	}
+	for _, pp := range pkgDeps[pkg] {
+		allow(pp)
+	}
+	return m
+}
+
+var bools = []bool{false, true}
+var geese = []string{"darwin", "dragonfly", "freebsd", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows"}
+var goarches = []string{"386", "amd64", "arm", "arm64"}
+
+type osPkg struct {
+	goos, pkg string
+}
+
+// allowedErrors are the operating systems and packages known to contain errors
+// (currently just "no Go source files")
+var allowedErrors = map[osPkg]bool{
+	osPkg{"windows", "log/syslog"}: true,
+	osPkg{"plan9", "log/syslog"}:   true,
+}
+
+func TestDependencies(t *testing.T) {
+	if runtime.GOOS == "nacl" {
+		// NaCl tests run in a limited file system and we do not
+		// provide access to every source file.
+		t.Skip("skipping on NaCl")
+	}
+	var all []string
+
+	for k := range pkgDeps {
+		all = append(all, k)
+	}
+	sort.Strings(all)
+
+	ctxt := Default
+	test := func(mustImport bool) {
+		for _, pkg := range all {
+			if isMacro(pkg) {
+				continue
+			}
+			if pkg == "runtime/cgo" && !ctxt.CgoEnabled {
+				continue
+			}
+			p, err := ctxt.Import(pkg, "", 0)
+			if err != nil {
+				if allowedErrors[osPkg{ctxt.GOOS, pkg}] {
+					continue
+				}
+				if !ctxt.CgoEnabled && pkg == "runtime/cgo" {
+					continue
+				}
+				// Some of the combinations we try might not
+				// be reasonable (like arm,plan9,cgo), so ignore
+				// errors for the auto-generated combinations.
+				if !mustImport {
+					continue
+				}
+				t.Errorf("%s/%s/cgo=%v %v", ctxt.GOOS, ctxt.GOARCH, ctxt.CgoEnabled, err)
+				continue
+			}
+			ok := allowed(pkg)
+			var bad []string
+			for _, imp := range p.Imports {
+				if !ok[imp] {
+					bad = append(bad, imp)
+				}
+			}
+			if bad != nil {
+				t.Errorf("%s/%s/cgo=%v unexpected dependency: %s imports %v", ctxt.GOOS, ctxt.GOARCH, ctxt.CgoEnabled, pkg, bad)
+			}
+		}
+	}
+	test(true)
+
+	if testing.Short() {
+		t.Logf("skipping other systems")
+		return
+	}
+
+	for _, ctxt.GOOS = range geese {
+		for _, ctxt.GOARCH = range goarches {
+			for _, ctxt.CgoEnabled = range bools {
+				test(false)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/build/doc.go b/third_party/gofrontend/libgo/go/go/build/doc.go
new file mode 100644
index 0000000..f17f76c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/build/doc.go
@@ -0,0 +1,137 @@
+// 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.
+
+// Package build gathers information about Go packages.
+//
+// Go Path
+//
+// The Go path is a list of directory trees containing Go source code.
+// It is consulted to resolve imports that cannot be found in the standard
+// Go tree.  The default path is the value of the GOPATH environment
+// variable, interpreted as a path list appropriate to the operating system
+// (on Unix, the variable is a colon-separated string;
+// on Windows, a semicolon-separated string;
+// on Plan 9, a list).
+//
+// Each directory listed in the Go path must have a prescribed structure:
+//
+// The src/ directory holds source code.  The path below 'src' determines
+// the import path or executable name.
+//
+// The pkg/ directory holds installed package objects.
+// As in the Go tree, each target operating system and
+// architecture pair has its own subdirectory of pkg
+// (pkg/GOOS_GOARCH).
+//
+// If DIR is a directory listed in the Go path, a package with
+// source in DIR/src/foo/bar can be imported as "foo/bar" and
+// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a"
+// (or, for gccgo, "DIR/pkg/gccgo/foo/libbar.a").
+//
+// The bin/ directory holds compiled commands.
+// Each command is named for its source directory, but only
+// using the final element, not the entire path.  That is, the
+// command with source in DIR/src/foo/quux is installed into
+// DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
+// so that you can add DIR/bin to your PATH to get at the
+// installed commands.
+//
+// Here's an example directory layout:
+//
+//	GOPATH=/home/user/gocode
+//
+//	/home/user/gocode/
+//	    src/
+//	        foo/
+//	            bar/               (go code in package bar)
+//	                x.go
+//	            quux/              (go code in package main)
+//	                y.go
+//	    bin/
+//	        quux                   (installed command)
+//	    pkg/
+//	        linux_amd64/
+//	            foo/
+//	                bar.a          (installed package object)
+//
+// Build Constraints
+//
+// A build constraint, also known as a build tag, is a line comment that begins
+//
+//	// +build
+//
+// that lists the conditions under which a file should be included in the package.
+// Constraints may appear in any kind of source file (not just Go), but
+// they must appear near the top of the file, preceded
+// only by blank lines and other line comments. These rules mean that in Go
+// files a build constraint must appear before the package clause.
+//
+// To distinguish build constraints from package documentation, a series of
+// build constraints must be followed by a blank line.
+//
+// A build constraint is evaluated as the OR of space-separated options;
+// each option evaluates as the AND of its comma-separated terms;
+// and each term is an alphanumeric word or, preceded by !, its negation.
+// That is, the build constraint:
+//
+//	// +build linux,386 darwin,!cgo
+//
+// corresponds to the boolean formula:
+//
+//	(linux AND 386) OR (darwin AND (NOT cgo))
+//
+// A file may have multiple build constraints. The overall constraint is the AND
+// of the individual constraints. That is, the build constraints:
+//
+//	// +build linux darwin
+//	// +build 386
+//
+// corresponds to the boolean formula:
+//
+//	(linux OR darwin) AND 386
+//
+// During a particular build, the following words are satisfied:
+//
+//	- the target operating system, as spelled by runtime.GOOS
+//	- the target architecture, as spelled by runtime.GOARCH
+//	- the compiler being used, either "gc" or "gccgo"
+//	- "cgo", if ctxt.CgoEnabled is true
+//	- "go1.1", from Go version 1.1 onward
+//	- "go1.2", from Go version 1.2 onward
+//	- "go1.3", from Go version 1.3 onward
+//	- any additional words listed in ctxt.BuildTags
+//
+// If a file's name, after stripping the extension and a possible _test suffix,
+// matches any of the following patterns:
+//	*_GOOS
+// 	*_GOARCH
+// 	*_GOOS_GOARCH
+// (example: source_windows_amd64.go) or the literals:
+//	GOOS
+// 	GOARCH
+// (example: windows.go) where GOOS and GOARCH represent any known operating
+// system and architecture values respectively, then the file is considered to
+// have an implicit build constraint requiring those terms.
+//
+// To keep a file from being considered for the build:
+//
+//	// +build ignore
+//
+// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
+//
+// To build a file only when using cgo, and only on Linux and OS X:
+//
+//	// +build linux,cgo darwin,cgo
+//
+// Such a file is usually paired with another file implementing the
+// default functionality for other systems, which in this case would
+// carry the constraint:
+//
+//	// +build !linux,!darwin !cgo
+//
+// Naming a file dns_windows.go will cause it to be included only when
+// building the package for Windows; similarly, math_386.s will be included
+// only when building the package for 32-bit x86.
+//
+package build
diff --git a/third_party/gofrontend/libgo/go/go/build/read.go b/third_party/gofrontend/libgo/go/go/build/read.go
new file mode 100644
index 0000000..c8079df
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/build/read.go
@@ -0,0 +1,238 @@
+// 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 build
+
+import (
+	"bufio"
+	"errors"
+	"io"
+)
+
+type importReader struct {
+	b    *bufio.Reader
+	buf  []byte
+	peek byte
+	err  error
+	eof  bool
+	nerr int
+}
+
+func isIdent(c byte) bool {
+	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= 0x80
+}
+
+var (
+	errSyntax = errors.New("syntax error")
+	errNUL    = errors.New("unexpected NUL in input")
+)
+
+// syntaxError records a syntax error, but only if an I/O error has not already been recorded.
+func (r *importReader) syntaxError() {
+	if r.err == nil {
+		r.err = errSyntax
+	}
+}
+
+// readByte reads the next byte from the input, saves it in buf, and returns it.
+// If an error occurs, readByte records the error in r.err and returns 0.
+func (r *importReader) readByte() byte {
+	c, err := r.b.ReadByte()
+	if err == nil {
+		r.buf = append(r.buf, c)
+		if c == 0 {
+			err = errNUL
+		}
+	}
+	if err != nil {
+		if err == io.EOF {
+			r.eof = true
+		} else if r.err == nil {
+			r.err = err
+		}
+		c = 0
+	}
+	return c
+}
+
+// peekByte returns the next byte from the input reader but does not advance beyond it.
+// If skipSpace is set, peekByte skips leading spaces and comments.
+func (r *importReader) peekByte(skipSpace bool) byte {
+	if r.err != nil {
+		if r.nerr++; r.nerr > 10000 {
+			panic("go/build: import reader looping")
+		}
+		return 0
+	}
+
+	// Use r.peek as first input byte.
+	// Don't just return r.peek here: it might have been left by peekByte(false)
+	// and this might be peekByte(true).
+	c := r.peek
+	if c == 0 {
+		c = r.readByte()
+	}
+	for r.err == nil && !r.eof {
+		if skipSpace {
+			// For the purposes of this reader, semicolons are never necessary to
+			// understand the input and are treated as spaces.
+			switch c {
+			case ' ', '\f', '\t', '\r', '\n', ';':
+				c = r.readByte()
+				continue
+
+			case '/':
+				c = r.readByte()
+				if c == '/' {
+					for c != '\n' && r.err == nil && !r.eof {
+						c = r.readByte()
+					}
+				} else if c == '*' {
+					var c1 byte
+					for (c != '*' || c1 != '/') && r.err == nil {
+						if r.eof {
+							r.syntaxError()
+						}
+						c, c1 = c1, r.readByte()
+					}
+				} else {
+					r.syntaxError()
+				}
+				c = r.readByte()
+				continue
+			}
+		}
+		break
+	}
+	r.peek = c
+	return r.peek
+}
+
+// nextByte is like peekByte but advances beyond the returned byte.
+func (r *importReader) nextByte(skipSpace bool) byte {
+	c := r.peekByte(skipSpace)
+	r.peek = 0
+	return c
+}
+
+// readKeyword reads the given keyword from the input.
+// If the keyword is not present, readKeyword records a syntax error.
+func (r *importReader) readKeyword(kw string) {
+	r.peekByte(true)
+	for i := 0; i < len(kw); i++ {
+		if r.nextByte(false) != kw[i] {
+			r.syntaxError()
+			return
+		}
+	}
+	if isIdent(r.peekByte(false)) {
+		r.syntaxError()
+	}
+}
+
+// readIdent reads an identifier from the input.
+// If an identifier is not present, readIdent records a syntax error.
+func (r *importReader) readIdent() {
+	c := r.peekByte(true)
+	if !isIdent(c) {
+		r.syntaxError()
+		return
+	}
+	for isIdent(r.peekByte(false)) {
+		r.peek = 0
+	}
+}
+
+// readString reads a quoted string literal from the input.
+// If an identifier is not present, readString records a syntax error.
+func (r *importReader) readString() {
+	switch r.nextByte(true) {
+	case '`':
+		for r.err == nil {
+			if r.nextByte(false) == '`' {
+				break
+			}
+			if r.eof {
+				r.syntaxError()
+			}
+		}
+	case '"':
+		for r.err == nil {
+			c := r.nextByte(false)
+			if c == '"' {
+				break
+			}
+			if r.eof || c == '\n' {
+				r.syntaxError()
+			}
+			if c == '\\' {
+				r.nextByte(false)
+			}
+		}
+	default:
+		r.syntaxError()
+	}
+}
+
+// readImport reads an import clause - optional identifier followed by quoted string -
+// from the input.
+func (r *importReader) readImport() {
+	c := r.peekByte(true)
+	if c == '.' {
+		r.peek = 0
+	} else if isIdent(c) {
+		r.readIdent()
+	}
+	r.readString()
+}
+
+// readComments is like ioutil.ReadAll, except that it only reads the leading
+// block of comments in the file.
+func readComments(f io.Reader) ([]byte, error) {
+	r := &importReader{b: bufio.NewReader(f)}
+	r.peekByte(true)
+	if r.err == nil && !r.eof {
+		// Didn't reach EOF, so must have found a non-space byte. Remove it.
+		r.buf = r.buf[:len(r.buf)-1]
+	}
+	return r.buf, r.err
+}
+
+// readImports is like ioutil.ReadAll, except that it expects a Go file as input
+// and stops reading the input once the imports have completed.
+func readImports(f io.Reader, reportSyntaxError bool) ([]byte, error) {
+	r := &importReader{b: bufio.NewReader(f)}
+
+	r.readKeyword("package")
+	r.readIdent()
+	for r.peekByte(true) == 'i' {
+		r.readKeyword("import")
+		if r.peekByte(true) == '(' {
+			r.nextByte(false)
+			for r.peekByte(true) != ')' && r.err == nil {
+				r.readImport()
+			}
+			r.nextByte(false)
+		} else {
+			r.readImport()
+		}
+	}
+
+	// If we stopped successfully before EOF, we read a byte that told us we were done.
+	// Return all but that last byte, which would cause a syntax error if we let it through.
+	if r.err == nil && !r.eof {
+		return r.buf[:len(r.buf)-1], nil
+	}
+
+	// If we stopped for a syntax error, consume the whole file so that
+	// we are sure we don't change the errors that go/parser returns.
+	if r.err == errSyntax && !reportSyntaxError {
+		r.err = nil
+		for r.err == nil && !r.eof {
+			r.readByte()
+		}
+	}
+
+	return r.buf, r.err
+}
diff --git a/third_party/gofrontend/libgo/go/go/build/read_test.go b/third_party/gofrontend/libgo/go/go/build/read_test.go
new file mode 100644
index 0000000..2dcc120
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/build/read_test.go
@@ -0,0 +1,226 @@
+// 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 build
+
+import (
+	"io"
+	"strings"
+	"testing"
+)
+
+const quote = "`"
+
+type readTest struct {
+	// Test input contains ℙ where readImports should stop.
+	in  string
+	err string
+}
+
+var readImportsTests = []readTest{
+	{
+		`package p`,
+		"",
+	},
+	{
+		`package p; import "x"`,
+		"",
+	},
+	{
+		`package p; import . "x"`,
+		"",
+	},
+	{
+		`package p; import "x";ℙvar x = 1`,
+		"",
+	},
+	{
+		`package p
+		
+		// comment
+		
+		import "x"
+		import _ "x"
+		import a "x"
+		
+		/* comment */
+		
+		import (
+			"x" /* comment */
+			_ "x"
+			a "x" // comment
+			` + quote + `x` + quote + `
+			_ /*comment*/ ` + quote + `x` + quote + `
+			a ` + quote + `x` + quote + `
+		)
+		import (
+		)
+		import ()
+		import()import()import()
+		import();import();import()
+		
+		ℙvar x = 1
+		`,
+		"",
+	},
+}
+
+var readCommentsTests = []readTest{
+	{
+		`ℙpackage p`,
+		"",
+	},
+	{
+		`ℙpackage p; import "x"`,
+		"",
+	},
+	{
+		`ℙpackage p; import . "x"`,
+		"",
+	},
+	{
+		`// foo
+
+		/* bar */
+
+		/* quux */ // baz
+		
+		/*/ zot */
+
+		// asdf
+		ℙHello, world`,
+		"",
+	},
+}
+
+func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) {
+	for i, tt := range tests {
+		var in, testOut string
+		j := strings.Index(tt.in, "ℙ")
+		if j < 0 {
+			in = tt.in
+			testOut = tt.in
+		} else {
+			in = tt.in[:j] + tt.in[j+len("ℙ"):]
+			testOut = tt.in[:j]
+		}
+		r := strings.NewReader(in)
+		buf, err := read(r)
+		if err != nil {
+			if tt.err == "" {
+				t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf))
+				continue
+			}
+			if !strings.Contains(err.Error(), tt.err) {
+				t.Errorf("#%d: err=%q, expected %q", i, err, tt.err)
+				continue
+			}
+			continue
+		}
+		if err == nil && tt.err != "" {
+			t.Errorf("#%d: success, expected %q", i, tt.err)
+			continue
+		}
+
+		out := string(buf)
+		if out != testOut {
+			t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut)
+		}
+	}
+}
+
+func TestReadImports(t *testing.T) {
+	testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return readImports(r, true) })
+}
+
+func TestReadComments(t *testing.T) {
+	testRead(t, readCommentsTests, readComments)
+}
+
+var readFailuresTests = []readTest{
+	{
+		`package`,
+		"syntax error",
+	},
+	{
+		"package p\n\x00\nimport `math`\n",
+		"unexpected NUL in input",
+	},
+	{
+		`package p; import`,
+		"syntax error",
+	},
+	{
+		`package p; import "`,
+		"syntax error",
+	},
+	{
+		"package p; import ` \n\n",
+		"syntax error",
+	},
+	{
+		`package p; import "x`,
+		"syntax error",
+	},
+	{
+		`package p; import _`,
+		"syntax error",
+	},
+	{
+		`package p; import _ "`,
+		"syntax error",
+	},
+	{
+		`package p; import _ "x`,
+		"syntax error",
+	},
+	{
+		`package p; import .`,
+		"syntax error",
+	},
+	{
+		`package p; import . "`,
+		"syntax error",
+	},
+	{
+		`package p; import . "x`,
+		"syntax error",
+	},
+	{
+		`package p; import (`,
+		"syntax error",
+	},
+	{
+		`package p; import ("`,
+		"syntax error",
+	},
+	{
+		`package p; import ("x`,
+		"syntax error",
+	},
+	{
+		`package p; import ("x"`,
+		"syntax error",
+	},
+}
+
+func TestReadFailures(t *testing.T) {
+	// Errors should be reported (true arg to readImports).
+	testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return readImports(r, true) })
+}
+
+func TestReadFailuresIgnored(t *testing.T) {
+	// Syntax errors should not be reported (false arg to readImports).
+	// Instead, entire file should be the output and no error.
+	// Convert tests not to return syntax errors.
+	tests := make([]readTest, len(readFailuresTests))
+	copy(tests, readFailuresTests)
+	for i := range tests {
+		tt := &tests[i]
+		if !strings.Contains(tt.err, "NUL") {
+			tt.err = ""
+		}
+	}
+	testRead(t, tests, func(r io.Reader) ([]byte, error) { return readImports(r, false) })
+}
diff --git a/third_party/gofrontend/libgo/go/go/build/syslist.go b/third_party/gofrontend/libgo/go/go/build/syslist.go
new file mode 100644
index 0000000..84712bd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/build/syslist.go
@@ -0,0 +1,8 @@
+// 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.
+
+package build
+
+const goosList = "darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows "
+const goarchList = "386 amd64 amd64p32 arm arm64 alpha m68k mipso32 mipsn32 mipsn64 mipso64 ppc ppc64 s390 s390x sparc sparc64 "
diff --git a/third_party/gofrontend/libgo/go/go/build/syslist_test.go b/third_party/gofrontend/libgo/go/go/build/syslist_test.go
new file mode 100644
index 0000000..3be2928
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/build/syslist_test.go
@@ -0,0 +1,62 @@
+// 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.
+
+package build
+
+import (
+	"runtime"
+	"testing"
+)
+
+var (
+	thisOS    = runtime.GOOS
+	thisArch  = runtime.GOARCH
+	otherOS   = anotherOS()
+	otherArch = anotherArch()
+)
+
+func anotherOS() string {
+	if thisOS != "darwin" {
+		return "darwin"
+	}
+	return "linux"
+}
+
+func anotherArch() string {
+	if thisArch != "amd64" {
+		return "amd64"
+	}
+	return "386"
+}
+
+type GoodFileTest struct {
+	name   string
+	result bool
+}
+
+var tests = []GoodFileTest{
+	{"file.go", true},
+	{"file.c", true},
+	{"file_foo.go", true},
+	{"file_" + thisArch + ".go", true},
+	{"file_" + otherArch + ".go", false},
+	{"file_" + thisOS + ".go", true},
+	{"file_" + otherOS + ".go", false},
+	{"file_" + thisOS + "_" + thisArch + ".go", true},
+	{"file_" + otherOS + "_" + thisArch + ".go", false},
+	{"file_" + thisOS + "_" + otherArch + ".go", false},
+	{"file_" + otherOS + "_" + otherArch + ".go", false},
+	{"file_foo_" + thisArch + ".go", true},
+	{"file_foo_" + otherArch + ".go", false},
+	{"file_" + thisOS + ".c", true},
+	{"file_" + otherOS + ".c", false},
+}
+
+func TestGoodOSArch(t *testing.T) {
+	for _, test := range tests {
+		if Default.goodOSArchFile(test.name, make(map[string]bool)) != test.result {
+			t.Fatalf("goodOSArchFile(%q) != %v", test.name, test.result)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/build/testdata/other/file/file.go b/third_party/gofrontend/libgo/go/go/build/testdata/other/file/file.go
new file mode 100644
index 0000000..bbfd3e9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/build/testdata/other/file/file.go
@@ -0,0 +1,5 @@
+// Test data - not compiled.
+
+package file
+
+func F() {}
diff --git a/third_party/gofrontend/libgo/go/go/build/testdata/other/main.go b/third_party/gofrontend/libgo/go/go/build/testdata/other/main.go
new file mode 100644
index 0000000..e090435
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/build/testdata/other/main.go
@@ -0,0 +1,11 @@
+// Test data - not compiled.
+
+package main
+
+import (
+	"./file"
+)
+
+func main() {
+	file.F()
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/comment.go b/third_party/gofrontend/libgo/go/go/doc/comment.go
new file mode 100644
index 0000000..f414ca4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/comment.go
@@ -0,0 +1,480 @@
+// 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.
+
+// Godoc comment extraction and comment -> HTML formatting.
+
+package doc
+
+import (
+	"io"
+	"regexp"
+	"strings"
+	"text/template" // for HTMLEscape
+	"unicode"
+	"unicode/utf8"
+)
+
+var (
+	ldquo = []byte("&ldquo;")
+	rdquo = []byte("&rdquo;")
+)
+
+// Escape comment text for HTML. If nice is set,
+// also turn `` into &ldquo; and '' into &rdquo;.
+func commentEscape(w io.Writer, text string, nice bool) {
+	last := 0
+	if nice {
+		for i := 0; i < len(text)-1; i++ {
+			ch := text[i]
+			if ch == text[i+1] && (ch == '`' || ch == '\'') {
+				template.HTMLEscape(w, []byte(text[last:i]))
+				last = i + 2
+				switch ch {
+				case '`':
+					w.Write(ldquo)
+				case '\'':
+					w.Write(rdquo)
+				}
+				i++ // loop will add one more
+			}
+		}
+	}
+	template.HTMLEscape(w, []byte(text[last:]))
+}
+
+const (
+	// Regexp for Go identifiers
+	identRx = `[\pL_][\pL_0-9]*`
+
+	// Regexp for URLs
+	protocol = `https?|ftp|file|gopher|mailto|news|nntp|telnet|wais|prospero`
+	hostPart = `[a-zA-Z0-9_@\-]+`
+	filePart = `[a-zA-Z0-9_?%#~&/\-+=()]+` // parentheses may not be matching; see pairedParensPrefixLen
+	urlRx    = `(` + protocol + `)://` +   // http://
+		hostPart + `([.:]` + hostPart + `)*/?` + // //www.google.com:8080/
+		filePart + `([:.,]` + filePart + `)*`
+)
+
+var matchRx = regexp.MustCompile(`(` + urlRx + `)|(` + identRx + `)`)
+
+var (
+	html_a      = []byte(`<a href="`)
+	html_aq     = []byte(`">`)
+	html_enda   = []byte("</a>")
+	html_i      = []byte("<i>")
+	html_endi   = []byte("</i>")
+	html_p      = []byte("<p>\n")
+	html_endp   = []byte("</p>\n")
+	html_pre    = []byte("<pre>")
+	html_endpre = []byte("</pre>\n")
+	html_h      = []byte(`<h3 id="`)
+	html_hq     = []byte(`">`)
+	html_endh   = []byte("</h3>\n")
+)
+
+// pairedParensPrefixLen returns the length of the longest prefix of s containing paired parentheses.
+func pairedParensPrefixLen(s string) int {
+	parens := 0
+	l := len(s)
+	for i, ch := range s {
+		switch ch {
+		case '(':
+			if parens == 0 {
+				l = i
+			}
+			parens++
+		case ')':
+			parens--
+			if parens == 0 {
+				l = len(s)
+			} else if parens < 0 {
+				return i
+			}
+		}
+	}
+	return l
+}
+
+// Emphasize and escape a line of text for HTML. URLs are converted into links;
+// if the URL also appears in the words map, the link is taken from the map (if
+// the corresponding map value is the empty string, the URL is not converted
+// into a link). Go identifiers that appear in the words map are italicized; if
+// the corresponding map value is not the empty string, it is considered a URL
+// and the word is converted into a link. If nice is set, the remaining text's
+// appearance is improved where it makes sense (e.g., `` is turned into &ldquo;
+// and '' into &rdquo;).
+func emphasize(w io.Writer, line string, words map[string]string, nice bool) {
+	for {
+		m := matchRx.FindStringSubmatchIndex(line)
+		if m == nil {
+			break
+		}
+		// m >= 6 (two parenthesized sub-regexps in matchRx, 1st one is urlRx)
+
+		// write text before match
+		commentEscape(w, line[0:m[0]], nice)
+
+		// adjust match if necessary
+		match := line[m[0]:m[1]]
+		if n := pairedParensPrefixLen(match); n < len(match) {
+			// match contains unpaired parentheses (rare);
+			// redo matching with shortened line for correct indices
+			m = matchRx.FindStringSubmatchIndex(line[:m[0]+n])
+			match = match[:n]
+		}
+
+		// analyze match
+		url := ""
+		italics := false
+		if words != nil {
+			url, italics = words[match]
+		}
+		if m[2] >= 0 {
+			// match against first parenthesized sub-regexp; must be match against urlRx
+			if !italics {
+				// no alternative URL in words list, use match instead
+				url = match
+			}
+			italics = false // don't italicize URLs
+		}
+
+		// write match
+		if len(url) > 0 {
+			w.Write(html_a)
+			template.HTMLEscape(w, []byte(url))
+			w.Write(html_aq)
+		}
+		if italics {
+			w.Write(html_i)
+		}
+		commentEscape(w, match, nice)
+		if italics {
+			w.Write(html_endi)
+		}
+		if len(url) > 0 {
+			w.Write(html_enda)
+		}
+
+		// advance
+		line = line[m[1]:]
+	}
+	commentEscape(w, line, nice)
+}
+
+func indentLen(s string) int {
+	i := 0
+	for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
+		i++
+	}
+	return i
+}
+
+func isBlank(s string) bool {
+	return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
+}
+
+func commonPrefix(a, b string) string {
+	i := 0
+	for i < len(a) && i < len(b) && a[i] == b[i] {
+		i++
+	}
+	return a[0:i]
+}
+
+func unindent(block []string) {
+	if len(block) == 0 {
+		return
+	}
+
+	// compute maximum common white prefix
+	prefix := block[0][0:indentLen(block[0])]
+	for _, line := range block {
+		if !isBlank(line) {
+			prefix = commonPrefix(prefix, line[0:indentLen(line)])
+		}
+	}
+	n := len(prefix)
+
+	// remove
+	for i, line := range block {
+		if !isBlank(line) {
+			block[i] = line[n:]
+		}
+	}
+}
+
+// heading returns the trimmed line if it passes as a section heading;
+// otherwise it returns the empty string.
+func heading(line string) string {
+	line = strings.TrimSpace(line)
+	if len(line) == 0 {
+		return ""
+	}
+
+	// a heading must start with an uppercase letter
+	r, _ := utf8.DecodeRuneInString(line)
+	if !unicode.IsLetter(r) || !unicode.IsUpper(r) {
+		return ""
+	}
+
+	// it must end in a letter or digit:
+	r, _ = utf8.DecodeLastRuneInString(line)
+	if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
+		return ""
+	}
+
+	// exclude lines with illegal characters
+	if strings.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 {
+		return ""
+	}
+
+	// allow "'" for possessive "'s" only
+	for b := line; ; {
+		i := strings.IndexRune(b, '\'')
+		if i < 0 {
+			break
+		}
+		if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') {
+			return "" // not followed by "s "
+		}
+		b = b[i+2:]
+	}
+
+	return line
+}
+
+type op int
+
+const (
+	opPara op = iota
+	opHead
+	opPre
+)
+
+type block struct {
+	op    op
+	lines []string
+}
+
+var nonAlphaNumRx = regexp.MustCompile(`[^a-zA-Z0-9]`)
+
+func anchorID(line string) string {
+	// Add a "hdr-" prefix to avoid conflicting with IDs used for package symbols.
+	return "hdr-" + nonAlphaNumRx.ReplaceAllString(line, "_")
+}
+
+// ToHTML converts comment text to formatted HTML.
+// The comment was prepared by DocReader,
+// so it is known not to have leading, trailing blank lines
+// nor to have trailing spaces at the end of lines.
+// The comment markers have already been removed.
+//
+// Each span of unindented non-blank lines is converted into
+// a single paragraph. There is one exception to the rule: a span that
+// consists of a single line, is followed by another paragraph span,
+// begins with a capital letter, and contains no punctuation
+// is formatted as a heading.
+//
+// A span of indented lines is converted into a <pre> block,
+// with the common indent prefix removed.
+//
+// URLs in the comment text are converted into links; if the URL also appears
+// in the words map, the link is taken from the map (if the corresponding map
+// value is the empty string, the URL is not converted into a link).
+//
+// Go identifiers that appear in the words map are italicized; if the corresponding
+// map value is not the empty string, it is considered a URL and the word is converted
+// into a link.
+func ToHTML(w io.Writer, text string, words map[string]string) {
+	for _, b := range blocks(text) {
+		switch b.op {
+		case opPara:
+			w.Write(html_p)
+			for _, line := range b.lines {
+				emphasize(w, line, words, true)
+			}
+			w.Write(html_endp)
+		case opHead:
+			w.Write(html_h)
+			id := ""
+			for _, line := range b.lines {
+				if id == "" {
+					id = anchorID(line)
+					w.Write([]byte(id))
+					w.Write(html_hq)
+				}
+				commentEscape(w, line, true)
+			}
+			if id == "" {
+				w.Write(html_hq)
+			}
+			w.Write(html_endh)
+		case opPre:
+			w.Write(html_pre)
+			for _, line := range b.lines {
+				emphasize(w, line, nil, false)
+			}
+			w.Write(html_endpre)
+		}
+	}
+}
+
+func blocks(text string) []block {
+	var (
+		out  []block
+		para []string
+
+		lastWasBlank   = false
+		lastWasHeading = false
+	)
+
+	close := func() {
+		if para != nil {
+			out = append(out, block{opPara, para})
+			para = nil
+		}
+	}
+
+	lines := strings.SplitAfter(text, "\n")
+	unindent(lines)
+	for i := 0; i < len(lines); {
+		line := lines[i]
+		if isBlank(line) {
+			// close paragraph
+			close()
+			i++
+			lastWasBlank = true
+			continue
+		}
+		if indentLen(line) > 0 {
+			// close paragraph
+			close()
+
+			// count indented or blank lines
+			j := i + 1
+			for j < len(lines) && (isBlank(lines[j]) || indentLen(lines[j]) > 0) {
+				j++
+			}
+			// but not trailing blank lines
+			for j > i && isBlank(lines[j-1]) {
+				j--
+			}
+			pre := lines[i:j]
+			i = j
+
+			unindent(pre)
+
+			// put those lines in a pre block
+			out = append(out, block{opPre, pre})
+			lastWasHeading = false
+			continue
+		}
+
+		if lastWasBlank && !lastWasHeading && i+2 < len(lines) &&
+			isBlank(lines[i+1]) && !isBlank(lines[i+2]) && indentLen(lines[i+2]) == 0 {
+			// current line is non-blank, surrounded by blank lines
+			// and the next non-blank line is not indented: this
+			// might be a heading.
+			if head := heading(line); head != "" {
+				close()
+				out = append(out, block{opHead, []string{head}})
+				i += 2
+				lastWasHeading = true
+				continue
+			}
+		}
+
+		// open paragraph
+		lastWasBlank = false
+		lastWasHeading = false
+		para = append(para, lines[i])
+		i++
+	}
+	close()
+
+	return out
+}
+
+// ToText prepares comment text for presentation in textual output.
+// It wraps paragraphs of text to width or fewer Unicode code points
+// and then prefixes each line with the indent.  In preformatted sections
+// (such as program text), it prefixes each non-blank line with preIndent.
+func ToText(w io.Writer, text string, indent, preIndent string, width int) {
+	l := lineWrapper{
+		out:    w,
+		width:  width,
+		indent: indent,
+	}
+	for _, b := range blocks(text) {
+		switch b.op {
+		case opPara:
+			// l.write will add leading newline if required
+			for _, line := range b.lines {
+				l.write(line)
+			}
+			l.flush()
+		case opHead:
+			w.Write(nl)
+			for _, line := range b.lines {
+				l.write(line + "\n")
+			}
+			l.flush()
+		case opPre:
+			w.Write(nl)
+			for _, line := range b.lines {
+				if isBlank(line) {
+					w.Write([]byte("\n"))
+				} else {
+					w.Write([]byte(preIndent))
+					w.Write([]byte(line))
+				}
+			}
+		}
+	}
+}
+
+type lineWrapper struct {
+	out       io.Writer
+	printed   bool
+	width     int
+	indent    string
+	n         int
+	pendSpace int
+}
+
+var nl = []byte("\n")
+var space = []byte(" ")
+
+func (l *lineWrapper) write(text string) {
+	if l.n == 0 && l.printed {
+		l.out.Write(nl) // blank line before new paragraph
+	}
+	l.printed = true
+
+	for _, f := range strings.Fields(text) {
+		w := utf8.RuneCountInString(f)
+		// wrap if line is too long
+		if l.n > 0 && l.n+l.pendSpace+w > l.width {
+			l.out.Write(nl)
+			l.n = 0
+			l.pendSpace = 0
+		}
+		if l.n == 0 {
+			l.out.Write([]byte(l.indent))
+		}
+		l.out.Write(space[:l.pendSpace])
+		l.out.Write([]byte(f))
+		l.n += l.pendSpace + w
+		l.pendSpace = 1
+	}
+}
+
+func (l *lineWrapper) flush() {
+	if l.n == 0 {
+		return
+	}
+	l.out.Write(nl)
+	l.pendSpace = 0
+	l.n = 0
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/comment_test.go b/third_party/gofrontend/libgo/go/go/doc/comment_test.go
new file mode 100644
index 0000000..ad65c2a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/comment_test.go
@@ -0,0 +1,207 @@
+// 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.
+
+package doc
+
+import (
+	"bytes"
+	"reflect"
+	"testing"
+)
+
+var headingTests = []struct {
+	line string
+	ok   bool
+}{
+	{"Section", true},
+	{"A typical usage", true},
+	{"ΔΛΞ is Greek", true},
+	{"Foo 42", true},
+	{"", false},
+	{"section", false},
+	{"A typical usage:", false},
+	{"This code:", false},
+	{"δ is Greek", false},
+	{"Foo §", false},
+	{"Fermat's Last Sentence", true},
+	{"Fermat's", true},
+	{"'sX", false},
+	{"Ted 'Too' Bar", false},
+	{"Use n+m", false},
+	{"Scanning:", false},
+	{"N:M", false},
+}
+
+func TestIsHeading(t *testing.T) {
+	for _, tt := range headingTests {
+		if h := heading(tt.line); (len(h) > 0) != tt.ok {
+			t.Errorf("isHeading(%q) = %v, want %v", tt.line, h, tt.ok)
+		}
+	}
+}
+
+var blocksTests = []struct {
+	in   string
+	out  []block
+	text string
+}{
+	{
+		in: `Para 1.
+Para 1 line 2.
+
+Para 2.
+
+Section
+
+Para 3.
+
+	pre
+	pre1
+
+Para 4.
+
+	pre
+	pre1
+
+	pre2
+
+Para 5.
+
+
+	pre
+
+
+	pre1
+	pre2
+
+Para 6.
+	pre
+	pre2
+`,
+		out: []block{
+			{opPara, []string{"Para 1.\n", "Para 1 line 2.\n"}},
+			{opPara, []string{"Para 2.\n"}},
+			{opHead, []string{"Section"}},
+			{opPara, []string{"Para 3.\n"}},
+			{opPre, []string{"pre\n", "pre1\n"}},
+			{opPara, []string{"Para 4.\n"}},
+			{opPre, []string{"pre\n", "pre1\n", "\n", "pre2\n"}},
+			{opPara, []string{"Para 5.\n"}},
+			{opPre, []string{"pre\n", "\n", "\n", "pre1\n", "pre2\n"}},
+			{opPara, []string{"Para 6.\n"}},
+			{opPre, []string{"pre\n", "pre2\n"}},
+		},
+		text: `.   Para 1. Para 1 line 2.
+
+.   Para 2.
+
+
+.   Section
+
+.   Para 3.
+
+$	pre
+$	pre1
+
+.   Para 4.
+
+$	pre
+$	pre1
+
+$	pre2
+
+.   Para 5.
+
+$	pre
+
+
+$	pre1
+$	pre2
+
+.   Para 6.
+
+$	pre
+$	pre2
+`,
+	},
+}
+
+func TestBlocks(t *testing.T) {
+	for i, tt := range blocksTests {
+		b := blocks(tt.in)
+		if !reflect.DeepEqual(b, tt.out) {
+			t.Errorf("#%d: mismatch\nhave: %v\nwant: %v", i, b, tt.out)
+		}
+	}
+}
+
+func TestToText(t *testing.T) {
+	var buf bytes.Buffer
+	for i, tt := range blocksTests {
+		ToText(&buf, tt.in, ".   ", "$\t", 40)
+		if have := buf.String(); have != tt.text {
+			t.Errorf("#%d: mismatch\nhave: %s\nwant: %s\nhave vs want:\n%q\n%q", i, have, tt.text, have, tt.text)
+		}
+		buf.Reset()
+	}
+}
+
+var emphasizeTests = []struct {
+	in, out string
+}{
+	{"http://www.google.com/", `<a href="http://www.google.com/">http://www.google.com/</a>`},
+	{"https://www.google.com/", `<a href="https://www.google.com/">https://www.google.com/</a>`},
+	{"http://www.google.com/path.", `<a href="http://www.google.com/path">http://www.google.com/path</a>.`},
+	{"http://en.wikipedia.org/wiki/Camellia_(cipher)", `<a href="http://en.wikipedia.org/wiki/Camellia_(cipher)">http://en.wikipedia.org/wiki/Camellia_(cipher)</a>`},
+	{"(http://www.google.com/)", `(<a href="http://www.google.com/">http://www.google.com/</a>)`},
+	{"http://gmail.com)", `<a href="http://gmail.com">http://gmail.com</a>)`},
+	{"((http://gmail.com))", `((<a href="http://gmail.com">http://gmail.com</a>))`},
+	{"http://gmail.com ((http://gmail.com)) ()", `<a href="http://gmail.com">http://gmail.com</a> ((<a href="http://gmail.com">http://gmail.com</a>)) ()`},
+	{"Foo bar http://example.com/ quux!", `Foo bar <a href="http://example.com/">http://example.com/</a> quux!`},
+	{"Hello http://example.com/%2f/ /world.", `Hello <a href="http://example.com/%2f/">http://example.com/%2f/</a> /world.`},
+	{"Lorem http: ipsum //host/path", "Lorem http: ipsum //host/path"},
+	{"javascript://is/not/linked", "javascript://is/not/linked"},
+}
+
+func TestEmphasize(t *testing.T) {
+	for i, tt := range emphasizeTests {
+		var buf bytes.Buffer
+		emphasize(&buf, tt.in, nil, true)
+		out := buf.String()
+		if out != tt.out {
+			t.Errorf("#%d: mismatch\nhave: %v\nwant: %v", i, out, tt.out)
+		}
+	}
+}
+
+var pairedParensPrefixLenTests = []struct {
+	in, out string
+}{
+	{"", ""},
+	{"foo", "foo"},
+	{"()", "()"},
+	{"foo()", "foo()"},
+	{"foo()()()", "foo()()()"},
+	{"foo()((()()))", "foo()((()()))"},
+	{"foo()((()()))bar", "foo()((()()))bar"},
+	{"foo)", "foo"},
+	{"foo))", "foo"},
+	{"foo)))))", "foo"},
+	{"(foo", ""},
+	{"((foo", ""},
+	{"(((((foo", ""},
+	{"(foo)", "(foo)"},
+	{"((((foo))))", "((((foo))))"},
+	{"foo()())", "foo()()"},
+	{"foo((()())", "foo"},
+	{"foo((()())) (() foo ", "foo((()())) "},
+}
+
+func TestPairedParensPrefixLen(t *testing.T) {
+	for i, tt := range pairedParensPrefixLenTests {
+		if out := tt.in[:pairedParensPrefixLen(tt.in)]; out != tt.out {
+			t.Errorf("#%d: mismatch\nhave: %q\nwant: %q", i, out, tt.out)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/doc.go b/third_party/gofrontend/libgo/go/go/doc/doc.go
new file mode 100644
index 0000000..4264940
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/doc.go
@@ -0,0 +1,111 @@
+// 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 doc extracts source code documentation from a Go AST.
+package doc
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// Package is the documentation for an entire package.
+type Package struct {
+	Doc        string
+	Name       string
+	ImportPath string
+	Imports    []string
+	Filenames  []string
+	Notes      map[string][]*Note
+	// DEPRECATED. For backward compatibility Bugs is still populated,
+	// but all new code should use Notes instead.
+	Bugs []string
+
+	// declarations
+	Consts []*Value
+	Types  []*Type
+	Vars   []*Value
+	Funcs  []*Func
+}
+
+// Value is the documentation for a (possibly grouped) var or const declaration.
+type Value struct {
+	Doc   string
+	Names []string // var or const names in declaration order
+	Decl  *ast.GenDecl
+
+	order int
+}
+
+// Type is the documentation for a type declaration.
+type Type struct {
+	Doc  string
+	Name string
+	Decl *ast.GenDecl
+
+	// associated declarations
+	Consts  []*Value // sorted list of constants of (mostly) this type
+	Vars    []*Value // sorted list of variables of (mostly) this type
+	Funcs   []*Func  // sorted list of functions returning this type
+	Methods []*Func  // sorted list of methods (including embedded ones) of this type
+}
+
+// Func is the documentation for a func declaration.
+type Func struct {
+	Doc  string
+	Name string
+	Decl *ast.FuncDecl
+
+	// methods
+	// (for functions, these fields have the respective zero value)
+	Recv  string // actual   receiver "T" or "*T"
+	Orig  string // original receiver "T" or "*T"
+	Level int    // embedding level; 0 means not embedded
+}
+
+// A Note represents a marked comment starting with "MARKER(uid): note body".
+// Any note with a marker of 2 or more upper case [A-Z] letters and a uid of
+// at least one character is recognized. The ":" following the uid is optional.
+// Notes are collected in the Package.Notes map indexed by the notes marker.
+type Note struct {
+	Pos, End token.Pos // position range of the comment containing the marker
+	UID      string    // uid found with the marker
+	Body     string    // note body text
+}
+
+// Mode values control the operation of New.
+type Mode int
+
+const (
+	// extract documentation for all package-level declarations,
+	// not just exported ones
+	AllDecls Mode = 1 << iota
+
+	// show all embedded methods, not just the ones of
+	// invisible (unexported) anonymous fields
+	AllMethods
+)
+
+// New computes the package documentation for the given package AST.
+// New takes ownership of the AST pkg and may edit or overwrite it.
+//
+func New(pkg *ast.Package, importPath string, mode Mode) *Package {
+	var r reader
+	r.readPackage(pkg, mode)
+	r.computeMethodSets()
+	r.cleanupTypes()
+	return &Package{
+		Doc:        r.doc,
+		Name:       pkg.Name,
+		ImportPath: importPath,
+		Imports:    sortedKeys(r.imports),
+		Filenames:  r.filenames,
+		Notes:      r.notes,
+		Bugs:       noteBodies(r.notes["BUG"]),
+		Consts:     sortedValues(r.values, token.CONST),
+		Types:      sortedTypes(r.types, mode&AllMethods != 0),
+		Vars:       sortedValues(r.values, token.VAR),
+		Funcs:      sortedFuncs(r.funcs, true),
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/doc_test.go b/third_party/gofrontend/libgo/go/go/doc/doc_test.go
new file mode 100644
index 0000000..ad8ba53
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/doc_test.go
@@ -0,0 +1,146 @@
+// 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 doc
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"regexp"
+	"strings"
+	"testing"
+	"text/template"
+)
+
+var update = flag.Bool("update", false, "update golden (.out) files")
+var files = flag.String("files", "", "consider only Go test files matching this regular expression")
+
+const dataDir = "testdata"
+
+var templateTxt = readTemplate("template.txt")
+
+func readTemplate(filename string) *template.Template {
+	t := template.New(filename)
+	t.Funcs(template.FuncMap{
+		"node":     nodeFmt,
+		"synopsis": synopsisFmt,
+		"indent":   indentFmt,
+	})
+	return template.Must(t.ParseFiles(filepath.Join(dataDir, filename)))
+}
+
+func nodeFmt(node interface{}, fset *token.FileSet) string {
+	var buf bytes.Buffer
+	printer.Fprint(&buf, fset, node)
+	return strings.Replace(strings.TrimSpace(buf.String()), "\n", "\n\t", -1)
+}
+
+func synopsisFmt(s string) string {
+	const n = 64
+	if len(s) > n {
+		// cut off excess text and go back to a word boundary
+		s = s[0:n]
+		if i := strings.LastIndexAny(s, "\t\n "); i >= 0 {
+			s = s[0:i]
+		}
+		s = strings.TrimSpace(s) + " ..."
+	}
+	return "// " + strings.Replace(s, "\n", " ", -1)
+}
+
+func indentFmt(indent, s string) string {
+	end := ""
+	if strings.HasSuffix(s, "\n") {
+		end = "\n"
+		s = s[:len(s)-1]
+	}
+	return indent + strings.Replace(s, "\n", "\n"+indent, -1) + end
+}
+
+func isGoFile(fi os.FileInfo) bool {
+	name := fi.Name()
+	return !fi.IsDir() &&
+		len(name) > 0 && name[0] != '.' && // ignore .files
+		filepath.Ext(name) == ".go"
+}
+
+type bundle struct {
+	*Package
+	FSet *token.FileSet
+}
+
+func test(t *testing.T, mode Mode) {
+	// determine file filter
+	filter := isGoFile
+	if *files != "" {
+		rx, err := regexp.Compile(*files)
+		if err != nil {
+			t.Fatal(err)
+		}
+		filter = func(fi os.FileInfo) bool {
+			return isGoFile(fi) && rx.MatchString(fi.Name())
+		}
+	}
+
+	// get packages
+	fset := token.NewFileSet()
+	pkgs, err := parser.ParseDir(fset, dataDir, filter, parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// test packages
+	for _, pkg := range pkgs {
+		importpath := dataDir + "/" + pkg.Name
+		doc := New(pkg, importpath, mode)
+
+		// golden files always use / in filenames - canonicalize them
+		for i, filename := range doc.Filenames {
+			doc.Filenames[i] = filepath.ToSlash(filename)
+		}
+
+		// print documentation
+		var buf bytes.Buffer
+		if err := templateTxt.Execute(&buf, bundle{doc, fset}); err != nil {
+			t.Error(err)
+			continue
+		}
+		got := buf.Bytes()
+
+		// update golden file if necessary
+		golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
+		if *update {
+			err := ioutil.WriteFile(golden, got, 0644)
+			if err != nil {
+				t.Error(err)
+			}
+			continue
+		}
+
+		// get golden file
+		want, err := ioutil.ReadFile(golden)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		// compare
+		if !bytes.Equal(got, want) {
+			t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want)
+		}
+	}
+}
+
+func Test(t *testing.T) {
+	test(t, 0)
+	test(t, AllDecls)
+	test(t, AllMethods)
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/example.go b/third_party/gofrontend/libgo/go/go/doc/example.go
new file mode 100644
index 0000000..c414e54
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/example.go
@@ -0,0 +1,355 @@
+// 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.
+
+// Extract example functions from file ASTs.
+
+package doc
+
+import (
+	"go/ast"
+	"go/token"
+	"path"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// An Example represents an example function found in a source files.
+type Example struct {
+	Name        string // name of the item being exemplified
+	Doc         string // example function doc string
+	Code        ast.Node
+	Play        *ast.File // a whole program version of the example
+	Comments    []*ast.CommentGroup
+	Output      string // expected output
+	EmptyOutput bool   // expect empty output
+	Order       int    // original source code order
+}
+
+// Examples returns the examples found in the files, sorted by Name field.
+// The Order fields record the order in which the examples were encountered.
+//
+// Playable Examples must be in a package whose name ends in "_test".
+// An Example is "playable" (the Play field is non-nil) in either of these
+// circumstances:
+//   - The example function is self-contained: the function references only
+//     identifiers from other packages (or predeclared identifiers, such as
+//     "int") and the test file does not include a dot import.
+//   - The entire test file is the example: the file contains exactly one
+//     example function, zero test or benchmark functions, and at least one
+//     top-level function, type, variable, or constant declaration other
+//     than the example function.
+func Examples(files ...*ast.File) []*Example {
+	var list []*Example
+	for _, file := range files {
+		hasTests := false // file contains tests or benchmarks
+		numDecl := 0      // number of non-import declarations in the file
+		var flist []*Example
+		for _, decl := range file.Decls {
+			if g, ok := decl.(*ast.GenDecl); ok && g.Tok != token.IMPORT {
+				numDecl++
+				continue
+			}
+			f, ok := decl.(*ast.FuncDecl)
+			if !ok {
+				continue
+			}
+			numDecl++
+			name := f.Name.Name
+			if isTest(name, "Test") || isTest(name, "Benchmark") {
+				hasTests = true
+				continue
+			}
+			if !isTest(name, "Example") {
+				continue
+			}
+			var doc string
+			if f.Doc != nil {
+				doc = f.Doc.Text()
+			}
+			output, hasOutput := exampleOutput(f.Body, file.Comments)
+			flist = append(flist, &Example{
+				Name:        name[len("Example"):],
+				Doc:         doc,
+				Code:        f.Body,
+				Play:        playExample(file, f.Body),
+				Comments:    file.Comments,
+				Output:      output,
+				EmptyOutput: output == "" && hasOutput,
+				Order:       len(flist),
+			})
+		}
+		if !hasTests && numDecl > 1 && len(flist) == 1 {
+			// If this file only has one example function, some
+			// other top-level declarations, and no tests or
+			// benchmarks, use the whole file as the example.
+			flist[0].Code = file
+			flist[0].Play = playExampleFile(file)
+		}
+		list = append(list, flist...)
+	}
+	sort.Sort(exampleByName(list))
+	return list
+}
+
+var outputPrefix = regexp.MustCompile(`(?i)^[[:space:]]*output:`)
+
+// Extracts the expected output and whether there was a valid output comment
+func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) (output string, ok bool) {
+	if _, last := lastComment(b, comments); last != nil {
+		// test that it begins with the correct prefix
+		text := last.Text()
+		if loc := outputPrefix.FindStringIndex(text); loc != nil {
+			text = text[loc[1]:]
+			// Strip zero or more spaces followed by \n or a single space.
+			text = strings.TrimLeft(text, " ")
+			if len(text) > 0 && text[0] == '\n' {
+				text = text[1:]
+			}
+			return text, true
+		}
+	}
+	return "", false // no suitable comment found
+}
+
+// isTest tells whether name looks like a test, example, or benchmark.
+// It is a Test (say) if there is a character after Test that is not a
+// lower-case letter. (We don't want Testiness.)
+func isTest(name, prefix string) bool {
+	if !strings.HasPrefix(name, prefix) {
+		return false
+	}
+	if len(name) == len(prefix) { // "Test" is ok
+		return true
+	}
+	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
+	return !unicode.IsLower(rune)
+}
+
+type exampleByName []*Example
+
+func (s exampleByName) Len() int           { return len(s) }
+func (s exampleByName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s exampleByName) Less(i, j int) bool { return s[i].Name < s[j].Name }
+
+// playExample synthesizes a new *ast.File based on the provided
+// file with the provided function body as the body of main.
+func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
+	if !strings.HasSuffix(file.Name.Name, "_test") {
+		// We don't support examples that are part of the
+		// greater package (yet).
+		return nil
+	}
+
+	// Find top-level declarations in the file.
+	topDecls := make(map[*ast.Object]bool)
+	for _, decl := range file.Decls {
+		switch d := decl.(type) {
+		case *ast.FuncDecl:
+			topDecls[d.Name.Obj] = true
+		case *ast.GenDecl:
+			for _, spec := range d.Specs {
+				switch s := spec.(type) {
+				case *ast.TypeSpec:
+					topDecls[s.Name.Obj] = true
+				case *ast.ValueSpec:
+					for _, id := range s.Names {
+						topDecls[id.Obj] = true
+					}
+				}
+			}
+		}
+	}
+
+	// Find unresolved identifiers and uses of top-level declarations.
+	unresolved := make(map[string]bool)
+	usesTopDecl := false
+	var inspectFunc func(ast.Node) bool
+	inspectFunc = func(n ast.Node) bool {
+		// For selector expressions, only inspect the left hand side.
+		// (For an expression like fmt.Println, only add "fmt" to the
+		// set of unresolved names, not "Println".)
+		if e, ok := n.(*ast.SelectorExpr); ok {
+			ast.Inspect(e.X, inspectFunc)
+			return false
+		}
+		// For key value expressions, only inspect the value
+		// as the key should be resolved by the type of the
+		// composite literal.
+		if e, ok := n.(*ast.KeyValueExpr); ok {
+			ast.Inspect(e.Value, inspectFunc)
+			return false
+		}
+		if id, ok := n.(*ast.Ident); ok {
+			if id.Obj == nil {
+				unresolved[id.Name] = true
+			} else if topDecls[id.Obj] {
+				usesTopDecl = true
+			}
+		}
+		return true
+	}
+	ast.Inspect(body, inspectFunc)
+	if usesTopDecl {
+		// We don't support examples that are not self-contained (yet).
+		return nil
+	}
+
+	// Remove predeclared identifiers from unresolved list.
+	for n := range unresolved {
+		if predeclaredTypes[n] || predeclaredConstants[n] || predeclaredFuncs[n] {
+			delete(unresolved, n)
+		}
+	}
+
+	// Use unresolved identifiers to determine the imports used by this
+	// example. The heuristic assumes package names match base import
+	// paths for imports w/o renames (should be good enough most of the time).
+	namedImports := make(map[string]string) // [name]path
+	var blankImports []ast.Spec             // _ imports
+	for _, s := range file.Imports {
+		p, err := strconv.Unquote(s.Path.Value)
+		if err != nil {
+			continue
+		}
+		n := path.Base(p)
+		if s.Name != nil {
+			n = s.Name.Name
+			switch n {
+			case "_":
+				blankImports = append(blankImports, s)
+				continue
+			case ".":
+				// We can't resolve dot imports (yet).
+				return nil
+			}
+		}
+		if unresolved[n] {
+			namedImports[n] = p
+			delete(unresolved, n)
+		}
+	}
+
+	// If there are other unresolved identifiers, give up because this
+	// synthesized file is not going to build.
+	if len(unresolved) > 0 {
+		return nil
+	}
+
+	// Include documentation belonging to blank imports.
+	var comments []*ast.CommentGroup
+	for _, s := range blankImports {
+		if c := s.(*ast.ImportSpec).Doc; c != nil {
+			comments = append(comments, c)
+		}
+	}
+
+	// Include comments that are inside the function body.
+	for _, c := range file.Comments {
+		if body.Pos() <= c.Pos() && c.End() <= body.End() {
+			comments = append(comments, c)
+		}
+	}
+
+	// Strip "Output:" comment and adjust body end position.
+	body, comments = stripOutputComment(body, comments)
+
+	// Synthesize import declaration.
+	importDecl := &ast.GenDecl{
+		Tok:    token.IMPORT,
+		Lparen: 1, // Need non-zero Lparen and Rparen so that printer
+		Rparen: 1, // treats this as a factored import.
+	}
+	for n, p := range namedImports {
+		s := &ast.ImportSpec{Path: &ast.BasicLit{Value: strconv.Quote(p)}}
+		if path.Base(p) != n {
+			s.Name = ast.NewIdent(n)
+		}
+		importDecl.Specs = append(importDecl.Specs, s)
+	}
+	importDecl.Specs = append(importDecl.Specs, blankImports...)
+
+	// Synthesize main function.
+	funcDecl := &ast.FuncDecl{
+		Name: ast.NewIdent("main"),
+		Type: &ast.FuncType{Params: &ast.FieldList{}}, // FuncType.Params must be non-nil
+		Body: body,
+	}
+
+	// Synthesize file.
+	return &ast.File{
+		Name:     ast.NewIdent("main"),
+		Decls:    []ast.Decl{importDecl, funcDecl},
+		Comments: comments,
+	}
+}
+
+// playExampleFile takes a whole file example and synthesizes a new *ast.File
+// such that the example is function main in package main.
+func playExampleFile(file *ast.File) *ast.File {
+	// Strip copyright comment if present.
+	comments := file.Comments
+	if len(comments) > 0 && strings.HasPrefix(comments[0].Text(), "Copyright") {
+		comments = comments[1:]
+	}
+
+	// Copy declaration slice, rewriting the ExampleX function to main.
+	var decls []ast.Decl
+	for _, d := range file.Decls {
+		if f, ok := d.(*ast.FuncDecl); ok && isTest(f.Name.Name, "Example") {
+			// Copy the FuncDecl, as it may be used elsewhere.
+			newF := *f
+			newF.Name = ast.NewIdent("main")
+			newF.Body, comments = stripOutputComment(f.Body, comments)
+			d = &newF
+		}
+		decls = append(decls, d)
+	}
+
+	// Copy the File, as it may be used elsewhere.
+	f := *file
+	f.Name = ast.NewIdent("main")
+	f.Decls = decls
+	f.Comments = comments
+	return &f
+}
+
+// stripOutputComment finds and removes an "Output:" comment from body
+// and comments, and adjusts the body block's end position.
+func stripOutputComment(body *ast.BlockStmt, comments []*ast.CommentGroup) (*ast.BlockStmt, []*ast.CommentGroup) {
+	// Do nothing if no "Output:" comment found.
+	i, last := lastComment(body, comments)
+	if last == nil || !outputPrefix.MatchString(last.Text()) {
+		return body, comments
+	}
+
+	// Copy body and comments, as the originals may be used elsewhere.
+	newBody := &ast.BlockStmt{
+		Lbrace: body.Lbrace,
+		List:   body.List,
+		Rbrace: last.Pos(),
+	}
+	newComments := make([]*ast.CommentGroup, len(comments)-1)
+	copy(newComments, comments[:i])
+	copy(newComments[i:], comments[i+1:])
+	return newBody, newComments
+}
+
+// lastComment returns the last comment inside the provided block.
+func lastComment(b *ast.BlockStmt, c []*ast.CommentGroup) (i int, last *ast.CommentGroup) {
+	pos, end := b.Pos(), b.End()
+	for j, cg := range c {
+		if cg.Pos() < pos {
+			continue
+		}
+		if cg.End() > end {
+			break
+		}
+		i, last = j, cg
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/example_test.go b/third_party/gofrontend/libgo/go/go/doc/example_test.go
new file mode 100644
index 0000000..e154ea8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/example_test.go
@@ -0,0 +1,191 @@
+// Copyright 2013 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 doc_test
+
+import (
+	"bytes"
+	"go/doc"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"strings"
+	"testing"
+)
+
+const exampleTestFile = `
+package foo_test
+
+import (
+	"flag"
+	"fmt"
+	"log"
+	"os/exec"
+)
+
+func ExampleHello() {
+	fmt.Println("Hello, world!")
+	// Output: Hello, world!
+}
+
+func ExampleImport() {
+	out, err := exec.Command("date").Output()
+	if err != nil {
+		log.Fatal(err)
+	}
+	fmt.Printf("The date is %s\n", out)
+}
+
+func ExampleKeyValue() {
+	v := struct {
+		a string
+		b int
+	}{
+		a: "A",
+		b: 1,
+	}
+	fmt.Print(v)
+	// Output: a: "A", b: 1
+}
+
+func ExampleKeyValueImport() {
+	f := flag.Flag{
+		Name: "play",
+	}
+	fmt.Print(f)
+	// Output: Name: "play"
+}
+
+var keyValueTopDecl = struct {
+	a string
+	b int
+}{
+	a: "B",
+	b: 2,
+}
+
+func ExampleKeyValueTopDecl() {
+	fmt.Print(keyValueTopDecl)
+}
+`
+
+var exampleTestCases = []struct {
+	Name, Play, Output string
+}{
+	{
+		Name:   "Hello",
+		Play:   exampleHelloPlay,
+		Output: "Hello, world!\n",
+	},
+	{
+		Name: "Import",
+		Play: exampleImportPlay,
+	},
+	{
+		Name:   "KeyValue",
+		Play:   exampleKeyValuePlay,
+		Output: "a: \"A\", b: 1\n",
+	},
+	{
+		Name:   "KeyValueImport",
+		Play:   exampleKeyValueImportPlay,
+		Output: "Name: \"play\"\n",
+	},
+	{
+		Name: "KeyValueTopDecl",
+		Play: "<nil>",
+	},
+}
+
+const exampleHelloPlay = `package main
+
+import (
+	"fmt"
+)
+
+func main() {
+	fmt.Println("Hello, world!")
+}
+`
+const exampleImportPlay = `package main
+
+import (
+	"fmt"
+	"log"
+	"os/exec"
+)
+
+func main() {
+	out, err := exec.Command("date").Output()
+	if err != nil {
+		log.Fatal(err)
+	}
+	fmt.Printf("The date is %s\n", out)
+}
+`
+
+const exampleKeyValuePlay = `package main
+
+import (
+	"fmt"
+)
+
+func main() {
+	v := struct {
+		a string
+		b int
+	}{
+		a: "A",
+		b: 1,
+	}
+	fmt.Print(v)
+}
+`
+
+const exampleKeyValueImportPlay = `package main
+
+import (
+	"flag"
+	"fmt"
+)
+
+func main() {
+	f := flag.Flag{
+		Name: "play",
+	}
+	fmt.Print(f)
+}
+`
+
+func TestExamples(t *testing.T) {
+	fset := token.NewFileSet()
+	file, err := parser.ParseFile(fset, "test.go", strings.NewReader(exampleTestFile), parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for i, e := range doc.Examples(file) {
+		c := exampleTestCases[i]
+		if e.Name != c.Name {
+			t.Errorf("got Name == %q, want %q", e.Name, c.Name)
+		}
+		if w := c.Play; w != "" {
+			var g string // hah
+			if e.Play == nil {
+				g = "<nil>"
+			} else {
+				var buf bytes.Buffer
+				if err := format.Node(&buf, fset, e.Play); err != nil {
+					t.Fatal(err)
+				}
+				g = buf.String()
+			}
+			if g != w {
+				t.Errorf("%s: got Play == %q, want %q", c.Name, g, w)
+			}
+		}
+		if g, w := e.Output, c.Output; g != w {
+			t.Errorf("%s: got Output == %q, want %q", c.Name, g, w)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/exports.go b/third_party/gofrontend/libgo/go/go/doc/exports.go
new file mode 100644
index 0000000..ff01285
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/exports.go
@@ -0,0 +1,199 @@
+// 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.
+
+// This file implements export filtering of an AST.
+
+package doc
+
+import "go/ast"
+
+// filterIdentList removes unexported names from list in place
+// and returns the resulting list.
+//
+func filterIdentList(list []*ast.Ident) []*ast.Ident {
+	j := 0
+	for _, x := range list {
+		if ast.IsExported(x.Name) {
+			list[j] = x
+			j++
+		}
+	}
+	return list[0:j]
+}
+
+// removeErrorField removes anonymous fields named "error" from an interface.
+// This is called when "error" has been determined to be a local name,
+// not the predeclared type.
+//
+func removeErrorField(ityp *ast.InterfaceType) {
+	list := ityp.Methods.List // we know that ityp.Methods != nil
+	j := 0
+	for _, field := range list {
+		keepField := true
+		if n := len(field.Names); n == 0 {
+			// anonymous field
+			if fname, _ := baseTypeName(field.Type); fname == "error" {
+				keepField = false
+			}
+		}
+		if keepField {
+			list[j] = field
+			j++
+		}
+	}
+	if j < len(list) {
+		ityp.Incomplete = true
+	}
+	ityp.Methods.List = list[0:j]
+}
+
+// filterFieldList removes unexported fields (field names) from the field list
+// in place and returns true if fields were removed. Anonymous fields are
+// recorded with the parent type. filterType is called with the types of
+// all remaining fields.
+//
+func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp *ast.InterfaceType) (removedFields bool) {
+	if fields == nil {
+		return
+	}
+	list := fields.List
+	j := 0
+	for _, field := range list {
+		keepField := false
+		if n := len(field.Names); n == 0 {
+			// anonymous field
+			fname := r.recordAnonymousField(parent, field.Type)
+			if ast.IsExported(fname) {
+				keepField = true
+			} else if ityp != nil && fname == "error" {
+				// possibly the predeclared error interface; keep
+				// it for now but remember this interface so that
+				// it can be fixed if error is also defined locally
+				keepField = true
+				r.remember(ityp)
+			}
+		} else {
+			field.Names = filterIdentList(field.Names)
+			if len(field.Names) < n {
+				removedFields = true
+			}
+			if len(field.Names) > 0 {
+				keepField = true
+			}
+		}
+		if keepField {
+			r.filterType(nil, field.Type)
+			list[j] = field
+			j++
+		}
+	}
+	if j < len(list) {
+		removedFields = true
+	}
+	fields.List = list[0:j]
+	return
+}
+
+// filterParamList applies filterType to each parameter type in fields.
+//
+func (r *reader) filterParamList(fields *ast.FieldList) {
+	if fields != nil {
+		for _, f := range fields.List {
+			r.filterType(nil, f.Type)
+		}
+	}
+}
+
+// filterType strips any unexported struct fields or method types from typ
+// in place. If fields (or methods) have been removed, the corresponding
+// struct or interface type has the Incomplete field set to true.
+//
+func (r *reader) filterType(parent *namedType, typ ast.Expr) {
+	switch t := typ.(type) {
+	case *ast.Ident:
+		// nothing to do
+	case *ast.ParenExpr:
+		r.filterType(nil, t.X)
+	case *ast.ArrayType:
+		r.filterType(nil, t.Elt)
+	case *ast.StructType:
+		if r.filterFieldList(parent, t.Fields, nil) {
+			t.Incomplete = true
+		}
+	case *ast.FuncType:
+		r.filterParamList(t.Params)
+		r.filterParamList(t.Results)
+	case *ast.InterfaceType:
+		if r.filterFieldList(parent, t.Methods, t) {
+			t.Incomplete = true
+		}
+	case *ast.MapType:
+		r.filterType(nil, t.Key)
+		r.filterType(nil, t.Value)
+	case *ast.ChanType:
+		r.filterType(nil, t.Value)
+	}
+}
+
+func (r *reader) filterSpec(spec ast.Spec) bool {
+	switch s := spec.(type) {
+	case *ast.ImportSpec:
+		// always keep imports so we can collect them
+		return true
+	case *ast.ValueSpec:
+		s.Names = filterIdentList(s.Names)
+		if len(s.Names) > 0 {
+			r.filterType(nil, s.Type)
+			return true
+		}
+	case *ast.TypeSpec:
+		if name := s.Name.Name; ast.IsExported(name) {
+			r.filterType(r.lookupType(s.Name.Name), s.Type)
+			return true
+		} else if name == "error" {
+			// special case: remember that error is declared locally
+			r.errorDecl = true
+		}
+	}
+	return false
+}
+
+func (r *reader) filterSpecList(list []ast.Spec) []ast.Spec {
+	j := 0
+	for _, s := range list {
+		if r.filterSpec(s) {
+			list[j] = s
+			j++
+		}
+	}
+	return list[0:j]
+}
+
+func (r *reader) filterDecl(decl ast.Decl) bool {
+	switch d := decl.(type) {
+	case *ast.GenDecl:
+		d.Specs = r.filterSpecList(d.Specs)
+		return len(d.Specs) > 0
+	case *ast.FuncDecl:
+		// ok to filter these methods early because any
+		// conflicting method will be filtered here, too -
+		// thus, removing these methods early will not lead
+		// to the false removal of possible conflicts
+		return ast.IsExported(d.Name.Name)
+	}
+	return false
+}
+
+// fileExports removes unexported declarations from src in place.
+//
+func (r *reader) fileExports(src *ast.File) {
+	j := 0
+	for _, d := range src.Decls {
+		if r.filterDecl(d) {
+			src.Decls[j] = d
+			j++
+		}
+	}
+	src.Decls = src.Decls[0:j]
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/filter.go b/third_party/gofrontend/libgo/go/go/doc/filter.go
new file mode 100644
index 0000000..a6f243f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/filter.go
@@ -0,0 +1,105 @@
+// 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 doc
+
+import "go/ast"
+
+type Filter func(string) bool
+
+func matchFields(fields *ast.FieldList, f Filter) bool {
+	if fields != nil {
+		for _, field := range fields.List {
+			for _, name := range field.Names {
+				if f(name.Name) {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+func matchDecl(d *ast.GenDecl, f Filter) bool {
+	for _, d := range d.Specs {
+		switch v := d.(type) {
+		case *ast.ValueSpec:
+			for _, name := range v.Names {
+				if f(name.Name) {
+					return true
+				}
+			}
+		case *ast.TypeSpec:
+			if f(v.Name.Name) {
+				return true
+			}
+			switch t := v.Type.(type) {
+			case *ast.StructType:
+				if matchFields(t.Fields, f) {
+					return true
+				}
+			case *ast.InterfaceType:
+				if matchFields(t.Methods, f) {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+func filterValues(a []*Value, f Filter) []*Value {
+	w := 0
+	for _, vd := range a {
+		if matchDecl(vd.Decl, f) {
+			a[w] = vd
+			w++
+		}
+	}
+	return a[0:w]
+}
+
+func filterFuncs(a []*Func, f Filter) []*Func {
+	w := 0
+	for _, fd := range a {
+		if f(fd.Name) {
+			a[w] = fd
+			w++
+		}
+	}
+	return a[0:w]
+}
+
+func filterTypes(a []*Type, f Filter) []*Type {
+	w := 0
+	for _, td := range a {
+		n := 0 // number of matches
+		if matchDecl(td.Decl, f) {
+			n = 1
+		} else {
+			// type name doesn't match, but we may have matching consts, vars, factories or methods
+			td.Consts = filterValues(td.Consts, f)
+			td.Vars = filterValues(td.Vars, f)
+			td.Funcs = filterFuncs(td.Funcs, f)
+			td.Methods = filterFuncs(td.Methods, f)
+			n += len(td.Consts) + len(td.Vars) + len(td.Funcs) + len(td.Methods)
+		}
+		if n > 0 {
+			a[w] = td
+			w++
+		}
+	}
+	return a[0:w]
+}
+
+// Filter eliminates documentation for names that don't pass through the filter f.
+// TODO(gri): Recognize "Type.Method" as a name.
+//
+func (p *Package) Filter(f Filter) {
+	p.Consts = filterValues(p.Consts, f)
+	p.Vars = filterValues(p.Vars, f)
+	p.Types = filterTypes(p.Types, f)
+	p.Funcs = filterFuncs(p.Funcs, f)
+	p.Doc = "" // don't show top-level package doc
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/headscan.go b/third_party/gofrontend/libgo/go/go/doc/headscan.go
new file mode 100644
index 0000000..f559347
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/headscan.go
@@ -0,0 +1,113 @@
+// 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.
+
+// +build ignore
+
+/*
+	The headscan command extracts comment headings from package files;
+	it is used to detect false positives which may require an adjustment
+	to the comment formatting heuristics in comment.go.
+
+	Usage: headscan [-root root_directory]
+
+	By default, the $GOROOT/src directory is scanned.
+*/
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/doc"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strings"
+)
+
+var (
+	root    = flag.String("root", filepath.Join(runtime.GOROOT(), "src"), "root of filesystem tree to scan")
+	verbose = flag.Bool("v", false, "verbose mode")
+)
+
+const (
+	html_h    = "<h3>"
+	html_endh = "</h3>\n"
+)
+
+func isGoFile(fi os.FileInfo) bool {
+	return strings.HasSuffix(fi.Name(), ".go") &&
+		!strings.HasSuffix(fi.Name(), "_test.go")
+}
+
+func appendHeadings(list []string, comment string) []string {
+	var buf bytes.Buffer
+	doc.ToHTML(&buf, comment, nil)
+	for s := buf.String(); ; {
+		i := strings.Index(s, html_h)
+		if i < 0 {
+			break
+		}
+		i += len(html_h)
+		j := strings.Index(s, html_endh)
+		if j < 0 {
+			list = append(list, s[i:]) // incorrect HTML
+			break
+		}
+		list = append(list, s[i:j])
+		s = s[j+len(html_endh):]
+	}
+	return list
+}
+
+func main() {
+	flag.Parse()
+	fset := token.NewFileSet()
+	nheadings := 0
+	err := filepath.Walk(*root, func(path string, fi os.FileInfo, err error) error {
+		if !fi.IsDir() {
+			return nil
+		}
+		pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments)
+		if err != nil {
+			if *verbose {
+				fmt.Fprintln(os.Stderr, err)
+			}
+			return nil
+		}
+		for _, pkg := range pkgs {
+			d := doc.New(pkg, path, doc.Mode(0))
+			list := appendHeadings(nil, d.Doc)
+			for _, d := range d.Consts {
+				list = appendHeadings(list, d.Doc)
+			}
+			for _, d := range d.Types {
+				list = appendHeadings(list, d.Doc)
+			}
+			for _, d := range d.Vars {
+				list = appendHeadings(list, d.Doc)
+			}
+			for _, d := range d.Funcs {
+				list = appendHeadings(list, d.Doc)
+			}
+			if len(list) > 0 {
+				// directories may contain multiple packages;
+				// print path and package name
+				fmt.Printf("%s (package %s)\n", path, pkg.Name)
+				for _, h := range list {
+					fmt.Printf("\t%s\n", h)
+				}
+				nheadings += len(list)
+			}
+		}
+		return nil
+	})
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+	fmt.Println(nheadings, "headings found")
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/reader.go b/third_party/gofrontend/libgo/go/go/doc/reader.go
new file mode 100644
index 0000000..ed82c47
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/reader.go
@@ -0,0 +1,853 @@
+// 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 doc
+
+import (
+	"go/ast"
+	"go/token"
+	"regexp"
+	"sort"
+	"strconv"
+)
+
+// ----------------------------------------------------------------------------
+// function/method sets
+//
+// Internally, we treat functions like methods and collect them in method sets.
+
+// A methodSet describes a set of methods. Entries where Decl == nil are conflict
+// entries (more then one method with the same name at the same embedding level).
+//
+type methodSet map[string]*Func
+
+// recvString returns a string representation of recv of the
+// form "T", "*T", or "BADRECV" (if not a proper receiver type).
+//
+func recvString(recv ast.Expr) string {
+	switch t := recv.(type) {
+	case *ast.Ident:
+		return t.Name
+	case *ast.StarExpr:
+		return "*" + recvString(t.X)
+	}
+	return "BADRECV"
+}
+
+// set creates the corresponding Func for f and adds it to mset.
+// If there are multiple f's with the same name, set keeps the first
+// one with documentation; conflicts are ignored.
+//
+func (mset methodSet) set(f *ast.FuncDecl) {
+	name := f.Name.Name
+	if g := mset[name]; g != nil && g.Doc != "" {
+		// A function with the same name has already been registered;
+		// since it has documentation, assume f is simply another
+		// implementation and ignore it. This does not happen if the
+		// caller is using go/build.ScanDir to determine the list of
+		// files implementing a package.
+		return
+	}
+	// function doesn't exist or has no documentation; use f
+	recv := ""
+	if f.Recv != nil {
+		var typ ast.Expr
+		// be careful in case of incorrect ASTs
+		if list := f.Recv.List; len(list) == 1 {
+			typ = list[0].Type
+		}
+		recv = recvString(typ)
+	}
+	mset[name] = &Func{
+		Doc:  f.Doc.Text(),
+		Name: name,
+		Decl: f,
+		Recv: recv,
+		Orig: recv,
+	}
+	f.Doc = nil // doc consumed - remove from AST
+}
+
+// add adds method m to the method set; m is ignored if the method set
+// already contains a method with the same name at the same or a higher
+// level then m.
+//
+func (mset methodSet) add(m *Func) {
+	old := mset[m.Name]
+	if old == nil || m.Level < old.Level {
+		mset[m.Name] = m
+		return
+	}
+	if old != nil && m.Level == old.Level {
+		// conflict - mark it using a method with nil Decl
+		mset[m.Name] = &Func{
+			Name:  m.Name,
+			Level: m.Level,
+		}
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Named types
+
+// baseTypeName returns the name of the base type of x (or "")
+// and whether the type is imported or not.
+//
+func baseTypeName(x ast.Expr) (name string, imported bool) {
+	switch t := x.(type) {
+	case *ast.Ident:
+		return t.Name, false
+	case *ast.SelectorExpr:
+		if _, ok := t.X.(*ast.Ident); ok {
+			// only possible for qualified type names;
+			// assume type is imported
+			return t.Sel.Name, true
+		}
+	case *ast.StarExpr:
+		return baseTypeName(t.X)
+	}
+	return
+}
+
+// An embeddedSet describes a set of embedded types.
+type embeddedSet map[*namedType]bool
+
+// A namedType represents a named unqualified (package local, or possibly
+// predeclared) type. The namedType for a type name is always found via
+// reader.lookupType.
+//
+type namedType struct {
+	doc  string       // doc comment for type
+	name string       // type name
+	decl *ast.GenDecl // nil if declaration hasn't been seen yet
+
+	isEmbedded bool        // true if this type is embedded
+	isStruct   bool        // true if this type is a struct
+	embedded   embeddedSet // true if the embedded type is a pointer
+
+	// associated declarations
+	values  []*Value // consts and vars
+	funcs   methodSet
+	methods methodSet
+}
+
+// ----------------------------------------------------------------------------
+// AST reader
+
+// reader accumulates documentation for a single package.
+// It modifies the AST: Comments (declaration documentation)
+// that have been collected by the reader are set to nil
+// in the respective AST nodes so that they are not printed
+// twice (once when printing the documentation and once when
+// printing the corresponding AST node).
+//
+type reader struct {
+	mode Mode
+
+	// package properties
+	doc       string // package documentation, if any
+	filenames []string
+	notes     map[string][]*Note
+
+	// declarations
+	imports map[string]int
+	values  []*Value // consts and vars
+	types   map[string]*namedType
+	funcs   methodSet
+
+	// support for package-local error type declarations
+	errorDecl bool                 // if set, type "error" was declared locally
+	fixlist   []*ast.InterfaceType // list of interfaces containing anonymous field "error"
+}
+
+func (r *reader) isVisible(name string) bool {
+	return r.mode&AllDecls != 0 || ast.IsExported(name)
+}
+
+// lookupType returns the base type with the given name.
+// If the base type has not been encountered yet, a new
+// type with the given name but no associated declaration
+// is added to the type map.
+//
+func (r *reader) lookupType(name string) *namedType {
+	if name == "" || name == "_" {
+		return nil // no type docs for anonymous types
+	}
+	if typ, found := r.types[name]; found {
+		return typ
+	}
+	// type not found - add one without declaration
+	typ := &namedType{
+		name:     name,
+		embedded: make(embeddedSet),
+		funcs:    make(methodSet),
+		methods:  make(methodSet),
+	}
+	r.types[name] = typ
+	return typ
+}
+
+// recordAnonymousField registers fieldType as the type of an
+// anonymous field in the parent type. If the field is imported
+// (qualified name) or the parent is nil, the field is ignored.
+// The function returns the field name.
+//
+func (r *reader) recordAnonymousField(parent *namedType, fieldType ast.Expr) (fname string) {
+	fname, imp := baseTypeName(fieldType)
+	if parent == nil || imp {
+		return
+	}
+	if ftype := r.lookupType(fname); ftype != nil {
+		ftype.isEmbedded = true
+		_, ptr := fieldType.(*ast.StarExpr)
+		parent.embedded[ftype] = ptr
+	}
+	return
+}
+
+func (r *reader) readDoc(comment *ast.CommentGroup) {
+	// By convention there should be only one package comment
+	// but collect all of them if there are more then one.
+	text := comment.Text()
+	if r.doc == "" {
+		r.doc = text
+		return
+	}
+	r.doc += "\n" + text
+}
+
+func (r *reader) remember(typ *ast.InterfaceType) {
+	r.fixlist = append(r.fixlist, typ)
+}
+
+func specNames(specs []ast.Spec) []string {
+	names := make([]string, 0, len(specs)) // reasonable estimate
+	for _, s := range specs {
+		// s guaranteed to be an *ast.ValueSpec by readValue
+		for _, ident := range s.(*ast.ValueSpec).Names {
+			names = append(names, ident.Name)
+		}
+	}
+	return names
+}
+
+// readValue processes a const or var declaration.
+//
+func (r *reader) readValue(decl *ast.GenDecl) {
+	// determine if decl should be associated with a type
+	// Heuristic: For each typed entry, determine the type name, if any.
+	//            If there is exactly one type name that is sufficiently
+	//            frequent, associate the decl with the respective type.
+	domName := ""
+	domFreq := 0
+	prev := ""
+	n := 0
+	for _, spec := range decl.Specs {
+		s, ok := spec.(*ast.ValueSpec)
+		if !ok {
+			continue // should not happen, but be conservative
+		}
+		name := ""
+		switch {
+		case s.Type != nil:
+			// a type is present; determine its name
+			if n, imp := baseTypeName(s.Type); !imp {
+				name = n
+			}
+		case decl.Tok == token.CONST:
+			// no type is present but we have a constant declaration;
+			// use the previous type name (w/o more type information
+			// we cannot handle the case of unnamed variables with
+			// initializer expressions except for some trivial cases)
+			name = prev
+		}
+		if name != "" {
+			// entry has a named type
+			if domName != "" && domName != name {
+				// more than one type name - do not associate
+				// with any type
+				domName = ""
+				break
+			}
+			domName = name
+			domFreq++
+		}
+		prev = name
+		n++
+	}
+
+	// nothing to do w/o a legal declaration
+	if n == 0 {
+		return
+	}
+
+	// determine values list with which to associate the Value for this decl
+	values := &r.values
+	const threshold = 0.75
+	if domName != "" && r.isVisible(domName) && domFreq >= int(float64(len(decl.Specs))*threshold) {
+		// typed entries are sufficiently frequent
+		if typ := r.lookupType(domName); typ != nil {
+			values = &typ.values // associate with that type
+		}
+	}
+
+	*values = append(*values, &Value{
+		Doc:   decl.Doc.Text(),
+		Names: specNames(decl.Specs),
+		Decl:  decl,
+		order: len(*values),
+	})
+	decl.Doc = nil // doc consumed - remove from AST
+}
+
+// fields returns a struct's fields or an interface's methods.
+//
+func fields(typ ast.Expr) (list []*ast.Field, isStruct bool) {
+	var fields *ast.FieldList
+	switch t := typ.(type) {
+	case *ast.StructType:
+		fields = t.Fields
+		isStruct = true
+	case *ast.InterfaceType:
+		fields = t.Methods
+	}
+	if fields != nil {
+		list = fields.List
+	}
+	return
+}
+
+// readType processes a type declaration.
+//
+func (r *reader) readType(decl *ast.GenDecl, spec *ast.TypeSpec) {
+	typ := r.lookupType(spec.Name.Name)
+	if typ == nil {
+		return // no name or blank name - ignore the type
+	}
+
+	// A type should be added at most once, so typ.decl
+	// should be nil - if it is not, simply overwrite it.
+	typ.decl = decl
+
+	// compute documentation
+	doc := spec.Doc
+	spec.Doc = nil // doc consumed - remove from AST
+	if doc == nil {
+		// no doc associated with the spec, use the declaration doc, if any
+		doc = decl.Doc
+	}
+	decl.Doc = nil // doc consumed - remove from AST
+	typ.doc = doc.Text()
+
+	// record anonymous fields (they may contribute methods)
+	// (some fields may have been recorded already when filtering
+	// exports, but that's ok)
+	var list []*ast.Field
+	list, typ.isStruct = fields(spec.Type)
+	for _, field := range list {
+		if len(field.Names) == 0 {
+			r.recordAnonymousField(typ, field.Type)
+		}
+	}
+}
+
+// readFunc processes a func or method declaration.
+//
+func (r *reader) readFunc(fun *ast.FuncDecl) {
+	// strip function body
+	fun.Body = nil
+
+	// associate methods with the receiver type, if any
+	if fun.Recv != nil {
+		// method
+		recvTypeName, imp := baseTypeName(fun.Recv.List[0].Type)
+		if imp {
+			// should not happen (incorrect AST);
+			// don't show this method
+			return
+		}
+		if typ := r.lookupType(recvTypeName); typ != nil {
+			typ.methods.set(fun)
+		}
+		// otherwise ignore the method
+		// TODO(gri): There may be exported methods of non-exported types
+		// that can be called because of exported values (consts, vars, or
+		// function results) of that type. Could determine if that is the
+		// case and then show those methods in an appropriate section.
+		return
+	}
+
+	// associate factory functions with the first visible result type, if any
+	if fun.Type.Results.NumFields() >= 1 {
+		res := fun.Type.Results.List[0]
+		if len(res.Names) <= 1 {
+			// exactly one (named or anonymous) result associated
+			// with the first type in result signature (there may
+			// be more than one result)
+			if n, imp := baseTypeName(res.Type); !imp && r.isVisible(n) {
+				if typ := r.lookupType(n); typ != nil {
+					// associate function with typ
+					typ.funcs.set(fun)
+					return
+				}
+			}
+		}
+	}
+
+	// just an ordinary function
+	r.funcs.set(fun)
+}
+
+var (
+	noteMarker    = `([A-Z][A-Z]+)\(([^)]+)\):?`                    // MARKER(uid), MARKER at least 2 chars, uid at least 1 char
+	noteMarkerRx  = regexp.MustCompile(`^[ \t]*` + noteMarker)      // MARKER(uid) at text start
+	noteCommentRx = regexp.MustCompile(`^/[/*][ \t]*` + noteMarker) // MARKER(uid) at comment start
+)
+
+// readNote collects a single note from a sequence of comments.
+//
+func (r *reader) readNote(list []*ast.Comment) {
+	text := (&ast.CommentGroup{List: list}).Text()
+	if m := noteMarkerRx.FindStringSubmatchIndex(text); m != nil {
+		// The note body starts after the marker.
+		// We remove any formatting so that we don't
+		// get spurious line breaks/indentation when
+		// showing the TODO body.
+		body := clean(text[m[1]:], keepNL)
+		if body != "" {
+			marker := text[m[2]:m[3]]
+			r.notes[marker] = append(r.notes[marker], &Note{
+				Pos:  list[0].Pos(),
+				End:  list[len(list)-1].End(),
+				UID:  text[m[4]:m[5]],
+				Body: body,
+			})
+		}
+	}
+}
+
+// readNotes extracts notes from comments.
+// A note must start at the beginning of a comment with "MARKER(uid):"
+// and is followed by the note body (e.g., "// BUG(gri): fix this").
+// The note ends at the end of the comment group or at the start of
+// another note in the same comment group, whichever comes first.
+//
+func (r *reader) readNotes(comments []*ast.CommentGroup) {
+	for _, group := range comments {
+		i := -1 // comment index of most recent note start, valid if >= 0
+		list := group.List
+		for j, c := range list {
+			if noteCommentRx.MatchString(c.Text) {
+				if i >= 0 {
+					r.readNote(list[i:j])
+				}
+				i = j
+			}
+		}
+		if i >= 0 {
+			r.readNote(list[i:])
+		}
+	}
+}
+
+// readFile adds the AST for a source file to the reader.
+//
+func (r *reader) readFile(src *ast.File) {
+	// add package documentation
+	if src.Doc != nil {
+		r.readDoc(src.Doc)
+		src.Doc = nil // doc consumed - remove from AST
+	}
+
+	// add all declarations
+	for _, decl := range src.Decls {
+		switch d := decl.(type) {
+		case *ast.GenDecl:
+			switch d.Tok {
+			case token.IMPORT:
+				// imports are handled individually
+				for _, spec := range d.Specs {
+					if s, ok := spec.(*ast.ImportSpec); ok {
+						if import_, err := strconv.Unquote(s.Path.Value); err == nil {
+							r.imports[import_] = 1
+						}
+					}
+				}
+			case token.CONST, token.VAR:
+				// constants and variables are always handled as a group
+				r.readValue(d)
+			case token.TYPE:
+				// types are handled individually
+				if len(d.Specs) == 1 && !d.Lparen.IsValid() {
+					// common case: single declaration w/o parentheses
+					// (if a single declaration is parenthesized,
+					// create a new fake declaration below, so that
+					// go/doc type declarations always appear w/o
+					// parentheses)
+					if s, ok := d.Specs[0].(*ast.TypeSpec); ok {
+						r.readType(d, s)
+					}
+					break
+				}
+				for _, spec := range d.Specs {
+					if s, ok := spec.(*ast.TypeSpec); ok {
+						// use an individual (possibly fake) declaration
+						// for each type; this also ensures that each type
+						// gets to (re-)use the declaration documentation
+						// if there's none associated with the spec itself
+						fake := &ast.GenDecl{
+							Doc: d.Doc,
+							// don't use the existing TokPos because it
+							// will lead to the wrong selection range for
+							// the fake declaration if there are more
+							// than one type in the group (this affects
+							// src/cmd/godoc/godoc.go's posLink_urlFunc)
+							TokPos: s.Pos(),
+							Tok:    token.TYPE,
+							Specs:  []ast.Spec{s},
+						}
+						r.readType(fake, s)
+					}
+				}
+			}
+		case *ast.FuncDecl:
+			r.readFunc(d)
+		}
+	}
+
+	// collect MARKER(...): annotations
+	r.readNotes(src.Comments)
+	src.Comments = nil // consumed unassociated comments - remove from AST
+}
+
+func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
+	// initialize reader
+	r.filenames = make([]string, len(pkg.Files))
+	r.imports = make(map[string]int)
+	r.mode = mode
+	r.types = make(map[string]*namedType)
+	r.funcs = make(methodSet)
+	r.notes = make(map[string][]*Note)
+
+	// sort package files before reading them so that the
+	// result does not depend on map iteration order
+	i := 0
+	for filename := range pkg.Files {
+		r.filenames[i] = filename
+		i++
+	}
+	sort.Strings(r.filenames)
+
+	// process files in sorted order
+	for _, filename := range r.filenames {
+		f := pkg.Files[filename]
+		if mode&AllDecls == 0 {
+			r.fileExports(f)
+		}
+		r.readFile(f)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func {
+	if f == nil || f.Decl == nil || f.Decl.Recv == nil || len(f.Decl.Recv.List) != 1 {
+		return f // shouldn't happen, but be safe
+	}
+
+	// copy existing receiver field and set new type
+	newField := *f.Decl.Recv.List[0]
+	origPos := newField.Type.Pos()
+	_, origRecvIsPtr := newField.Type.(*ast.StarExpr)
+	newIdent := &ast.Ident{NamePos: origPos, Name: recvTypeName}
+	var typ ast.Expr = newIdent
+	if !embeddedIsPtr && origRecvIsPtr {
+		newIdent.NamePos++ // '*' is one character
+		typ = &ast.StarExpr{Star: origPos, X: newIdent}
+	}
+	newField.Type = typ
+
+	// copy existing receiver field list and set new receiver field
+	newFieldList := *f.Decl.Recv
+	newFieldList.List = []*ast.Field{&newField}
+
+	// copy existing function declaration and set new receiver field list
+	newFuncDecl := *f.Decl
+	newFuncDecl.Recv = &newFieldList
+
+	// copy existing function documentation and set new declaration
+	newF := *f
+	newF.Decl = &newFuncDecl
+	newF.Recv = recvString(typ)
+	// the Orig field never changes
+	newF.Level = level
+
+	return &newF
+}
+
+// collectEmbeddedMethods collects the embedded methods of typ in mset.
+//
+func (r *reader) collectEmbeddedMethods(mset methodSet, typ *namedType, recvTypeName string, embeddedIsPtr bool, level int, visited embeddedSet) {
+	visited[typ] = true
+	for embedded, isPtr := range typ.embedded {
+		// Once an embedded type is embedded as a pointer type
+		// all embedded types in those types are treated like
+		// pointer types for the purpose of the receiver type
+		// computation; i.e., embeddedIsPtr is sticky for this
+		// embedding hierarchy.
+		thisEmbeddedIsPtr := embeddedIsPtr || isPtr
+		for _, m := range embedded.methods {
+			// only top-level methods are embedded
+			if m.Level == 0 {
+				mset.add(customizeRecv(m, recvTypeName, thisEmbeddedIsPtr, level))
+			}
+		}
+		if !visited[embedded] {
+			r.collectEmbeddedMethods(mset, embedded, recvTypeName, thisEmbeddedIsPtr, level+1, visited)
+		}
+	}
+	delete(visited, typ)
+}
+
+// computeMethodSets determines the actual method sets for each type encountered.
+//
+func (r *reader) computeMethodSets() {
+	for _, t := range r.types {
+		// collect embedded methods for t
+		if t.isStruct {
+			// struct
+			r.collectEmbeddedMethods(t.methods, t, t.name, false, 1, make(embeddedSet))
+		} else {
+			// interface
+			// TODO(gri) fix this
+		}
+	}
+
+	// if error was declared locally, don't treat it as exported field anymore
+	if r.errorDecl {
+		for _, ityp := range r.fixlist {
+			removeErrorField(ityp)
+		}
+	}
+}
+
+// cleanupTypes removes the association of functions and methods with
+// types that have no declaration. Instead, these functions and methods
+// are shown at the package level. It also removes types with missing
+// declarations or which are not visible.
+//
+func (r *reader) cleanupTypes() {
+	for _, t := range r.types {
+		visible := r.isVisible(t.name)
+		if t.decl == nil && (predeclaredTypes[t.name] || t.isEmbedded && visible) {
+			// t.name is a predeclared type (and was not redeclared in this package),
+			// or it was embedded somewhere but its declaration is missing (because
+			// the AST is incomplete): move any associated values, funcs, and methods
+			// back to the top-level so that they are not lost.
+			// 1) move values
+			r.values = append(r.values, t.values...)
+			// 2) move factory functions
+			for name, f := range t.funcs {
+				// in a correct AST, package-level function names
+				// are all different - no need to check for conflicts
+				r.funcs[name] = f
+			}
+			// 3) move methods
+			for name, m := range t.methods {
+				// don't overwrite functions with the same name - drop them
+				if _, found := r.funcs[name]; !found {
+					r.funcs[name] = m
+				}
+			}
+		}
+		// remove types w/o declaration or which are not visible
+		if t.decl == nil || !visible {
+			delete(r.types, t.name)
+		}
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Sorting
+
+type data struct {
+	n    int
+	swap func(i, j int)
+	less func(i, j int) bool
+}
+
+func (d *data) Len() int           { return d.n }
+func (d *data) Swap(i, j int)      { d.swap(i, j) }
+func (d *data) Less(i, j int) bool { return d.less(i, j) }
+
+// sortBy is a helper function for sorting
+func sortBy(less func(i, j int) bool, swap func(i, j int), n int) {
+	sort.Sort(&data{n, swap, less})
+}
+
+func sortedKeys(m map[string]int) []string {
+	list := make([]string, len(m))
+	i := 0
+	for key := range m {
+		list[i] = key
+		i++
+	}
+	sort.Strings(list)
+	return list
+}
+
+// sortingName returns the name to use when sorting d into place.
+//
+func sortingName(d *ast.GenDecl) string {
+	if len(d.Specs) == 1 {
+		if s, ok := d.Specs[0].(*ast.ValueSpec); ok {
+			return s.Names[0].Name
+		}
+	}
+	return ""
+}
+
+func sortedValues(m []*Value, tok token.Token) []*Value {
+	list := make([]*Value, len(m)) // big enough in any case
+	i := 0
+	for _, val := range m {
+		if val.Decl.Tok == tok {
+			list[i] = val
+			i++
+		}
+	}
+	list = list[0:i]
+
+	sortBy(
+		func(i, j int) bool {
+			if ni, nj := sortingName(list[i].Decl), sortingName(list[j].Decl); ni != nj {
+				return ni < nj
+			}
+			return list[i].order < list[j].order
+		},
+		func(i, j int) { list[i], list[j] = list[j], list[i] },
+		len(list),
+	)
+
+	return list
+}
+
+func sortedTypes(m map[string]*namedType, allMethods bool) []*Type {
+	list := make([]*Type, len(m))
+	i := 0
+	for _, t := range m {
+		list[i] = &Type{
+			Doc:     t.doc,
+			Name:    t.name,
+			Decl:    t.decl,
+			Consts:  sortedValues(t.values, token.CONST),
+			Vars:    sortedValues(t.values, token.VAR),
+			Funcs:   sortedFuncs(t.funcs, true),
+			Methods: sortedFuncs(t.methods, allMethods),
+		}
+		i++
+	}
+
+	sortBy(
+		func(i, j int) bool { return list[i].Name < list[j].Name },
+		func(i, j int) { list[i], list[j] = list[j], list[i] },
+		len(list),
+	)
+
+	return list
+}
+
+func removeStar(s string) string {
+	if len(s) > 0 && s[0] == '*' {
+		return s[1:]
+	}
+	return s
+}
+
+func sortedFuncs(m methodSet, allMethods bool) []*Func {
+	list := make([]*Func, len(m))
+	i := 0
+	for _, m := range m {
+		// determine which methods to include
+		switch {
+		case m.Decl == nil:
+			// exclude conflict entry
+		case allMethods, m.Level == 0, !ast.IsExported(removeStar(m.Orig)):
+			// forced inclusion, method not embedded, or method
+			// embedded but original receiver type not exported
+			list[i] = m
+			i++
+		}
+	}
+	list = list[0:i]
+	sortBy(
+		func(i, j int) bool { return list[i].Name < list[j].Name },
+		func(i, j int) { list[i], list[j] = list[j], list[i] },
+		len(list),
+	)
+	return list
+}
+
+// noteBodies returns a list of note body strings given a list of notes.
+// This is only used to populate the deprecated Package.Bugs field.
+//
+func noteBodies(notes []*Note) []string {
+	var list []string
+	for _, n := range notes {
+		list = append(list, n.Body)
+	}
+	return list
+}
+
+// ----------------------------------------------------------------------------
+// Predeclared identifiers
+
+var predeclaredTypes = map[string]bool{
+	"bool":       true,
+	"byte":       true,
+	"complex64":  true,
+	"complex128": true,
+	"error":      true,
+	"float32":    true,
+	"float64":    true,
+	"int":        true,
+	"int8":       true,
+	"int16":      true,
+	"int32":      true,
+	"int64":      true,
+	"rune":       true,
+	"string":     true,
+	"uint":       true,
+	"uint8":      true,
+	"uint16":     true,
+	"uint32":     true,
+	"uint64":     true,
+	"uintptr":    true,
+}
+
+var predeclaredFuncs = map[string]bool{
+	"append":  true,
+	"cap":     true,
+	"close":   true,
+	"complex": true,
+	"copy":    true,
+	"delete":  true,
+	"imag":    true,
+	"len":     true,
+	"make":    true,
+	"new":     true,
+	"panic":   true,
+	"print":   true,
+	"println": true,
+	"real":    true,
+	"recover": true,
+}
+
+var predeclaredConstants = map[string]bool{
+	"false": true,
+	"iota":  true,
+	"nil":   true,
+	"true":  true,
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/synopsis.go b/third_party/gofrontend/libgo/go/go/doc/synopsis.go
new file mode 100644
index 0000000..c90080b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/synopsis.go
@@ -0,0 +1,82 @@
+// 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 doc
+
+import (
+	"strings"
+	"unicode"
+)
+
+// firstSentenceLen returns the length of the first sentence in s.
+// The sentence ends after the first period followed by space and
+// not preceded by exactly one uppercase letter.
+//
+func firstSentenceLen(s string) int {
+	var ppp, pp, p rune
+	for i, q := range s {
+		if q == '\n' || q == '\r' || q == '\t' {
+			q = ' '
+		}
+		if q == ' ' && p == '.' && (!unicode.IsUpper(pp) || unicode.IsUpper(ppp)) {
+			return i
+		}
+		if p == '。' || p == '.' {
+			return i
+		}
+		ppp, pp, p = pp, p, q
+	}
+	return len(s)
+}
+
+const (
+	keepNL = 1 << iota
+)
+
+// clean replaces each sequence of space, \n, \r, or \t characters
+// with a single space and removes any trailing and leading spaces.
+// If the keepNL flag is set, newline characters are passed through
+// instead of being change to spaces.
+func clean(s string, flags int) string {
+	var b []byte
+	p := byte(' ')
+	for i := 0; i < len(s); i++ {
+		q := s[i]
+		if (flags&keepNL) == 0 && q == '\n' || q == '\r' || q == '\t' {
+			q = ' '
+		}
+		if q != ' ' || p != ' ' {
+			b = append(b, q)
+			p = q
+		}
+	}
+	// remove trailing blank, if any
+	if n := len(b); n > 0 && p == ' ' {
+		b = b[0 : n-1]
+	}
+	return string(b)
+}
+
+// Synopsis returns a cleaned version of the first sentence in s.
+// That sentence ends after the first period followed by space and
+// not preceded by exactly one uppercase letter. The result string
+// has no \n, \r, or \t characters and uses only single spaces between
+// words. If s starts with any of the IllegalPrefixes, the result
+// is the empty string.
+//
+func Synopsis(s string) string {
+	s = clean(s[0:firstSentenceLen(s)], 0)
+	for _, prefix := range IllegalPrefixes {
+		if strings.HasPrefix(strings.ToLower(s), prefix) {
+			return ""
+		}
+	}
+	return s
+}
+
+var IllegalPrefixes = []string{
+	"copyright",
+	"all rights",
+	"author",
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/synopsis_test.go b/third_party/gofrontend/libgo/go/go/doc/synopsis_test.go
new file mode 100644
index 0000000..59b253c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/synopsis_test.go
@@ -0,0 +1,51 @@
+// 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 doc
+
+import "testing"
+
+var tests = []struct {
+	txt string
+	fsl int
+	syn string
+}{
+	{"", 0, ""},
+	{"foo", 3, "foo"},
+	{"foo.", 4, "foo."},
+	{"foo.bar", 7, "foo.bar"},
+	{"  foo.  ", 6, "foo."},
+	{"  foo\t  bar.\n", 12, "foo bar."},
+	{"  foo\t  bar.\n", 12, "foo bar."},
+	{"a  b\n\nc\r\rd\t\t", 12, "a b c d"},
+	{"a  b\n\nc\r\rd\t\t  . BLA", 15, "a b c d ."},
+	{"Package poems by T.S.Eliot. To rhyme...", 27, "Package poems by T.S.Eliot."},
+	{"Package poems by T. S. Eliot. To rhyme...", 29, "Package poems by T. S. Eliot."},
+	{"foo implements the foo ABI. The foo ABI is...", 27, "foo implements the foo ABI."},
+	{"Package\nfoo. ..", 12, "Package foo."},
+	{"P . Q.", 3, "P ."},
+	{"P. Q.   ", 8, "P. Q."},
+	{"Package Καλημέρα κόσμε.", 36, "Package Καλημέρα κόσμε."},
+	{"Package こんにちは 世界\n", 31, "Package こんにちは 世界"},
+	{"Package こんにちは。世界", 26, "Package こんにちは。"},
+	{"Package 안녕.世界", 17, "Package 안녕."},
+	{"Package foo does bar.", 21, "Package foo does bar."},
+	{"Copyright 2012 Google, Inc. Package foo does bar.", 27, ""},
+	{"All Rights reserved. Package foo does bar.", 20, ""},
+	{"All rights reserved. Package foo does bar.", 20, ""},
+	{"Authors: foo@bar.com. Package foo does bar.", 21, ""},
+}
+
+func TestSynopsis(t *testing.T) {
+	for _, e := range tests {
+		fsl := firstSentenceLen(e.txt)
+		if fsl != e.fsl {
+			t.Errorf("got fsl = %d; want %d for %q\n", fsl, e.fsl, e.txt)
+		}
+		syn := Synopsis(e.txt)
+		if syn != e.syn {
+			t.Errorf("got syn = %q; want %q for %q\n", syn, e.syn, e.txt)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/a.0.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/a.0.golden
new file mode 100644
index 0000000..7e680b8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/a.0.golden
@@ -0,0 +1,52 @@
+// comment 0  comment 1 
+PACKAGE a
+
+IMPORTPATH
+	testdata/a
+
+FILENAMES
+	testdata/a0.go
+	testdata/a1.go
+
+BUGS .Bugs is now deprecated, please use .Notes instead
+	bug0
+
+	bug1
+
+
+BUGS
+BUG(uid)	bug0
+
+BUG(uid)	bug1
+
+
+NOTES
+NOTE(uid)	
+
+NOTE(foo)	1 of 4 - this is the first line of note 1
+	- note 1 continues on this 2nd line
+	- note 1 continues on this 3rd line
+
+NOTE(foo)	2 of 4
+
+NOTE(bar)	3 of 4
+
+NOTE(bar)	4 of 4
+	- this is the last line of note 4
+
+NOTE(bam)	This note which contains a (parenthesized) subphrase
+	 must appear in its entirety.
+
+NOTE(xxx)	The ':' after the marker and uid is optional.
+
+
+SECBUGS
+SECBUG(uid)	sec hole 0
+	need to fix asap
+
+
+TODOS
+TODO(uid)	todo0
+
+TODO(uid)	todo1
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/a.1.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/a.1.golden
new file mode 100644
index 0000000..7e680b8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/a.1.golden
@@ -0,0 +1,52 @@
+// comment 0  comment 1 
+PACKAGE a
+
+IMPORTPATH
+	testdata/a
+
+FILENAMES
+	testdata/a0.go
+	testdata/a1.go
+
+BUGS .Bugs is now deprecated, please use .Notes instead
+	bug0
+
+	bug1
+
+
+BUGS
+BUG(uid)	bug0
+
+BUG(uid)	bug1
+
+
+NOTES
+NOTE(uid)	
+
+NOTE(foo)	1 of 4 - this is the first line of note 1
+	- note 1 continues on this 2nd line
+	- note 1 continues on this 3rd line
+
+NOTE(foo)	2 of 4
+
+NOTE(bar)	3 of 4
+
+NOTE(bar)	4 of 4
+	- this is the last line of note 4
+
+NOTE(bam)	This note which contains a (parenthesized) subphrase
+	 must appear in its entirety.
+
+NOTE(xxx)	The ':' after the marker and uid is optional.
+
+
+SECBUGS
+SECBUG(uid)	sec hole 0
+	need to fix asap
+
+
+TODOS
+TODO(uid)	todo0
+
+TODO(uid)	todo1
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/a.2.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/a.2.golden
new file mode 100644
index 0000000..7e680b8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/a.2.golden
@@ -0,0 +1,52 @@
+// comment 0  comment 1 
+PACKAGE a
+
+IMPORTPATH
+	testdata/a
+
+FILENAMES
+	testdata/a0.go
+	testdata/a1.go
+
+BUGS .Bugs is now deprecated, please use .Notes instead
+	bug0
+
+	bug1
+
+
+BUGS
+BUG(uid)	bug0
+
+BUG(uid)	bug1
+
+
+NOTES
+NOTE(uid)	
+
+NOTE(foo)	1 of 4 - this is the first line of note 1
+	- note 1 continues on this 2nd line
+	- note 1 continues on this 3rd line
+
+NOTE(foo)	2 of 4
+
+NOTE(bar)	3 of 4
+
+NOTE(bar)	4 of 4
+	- this is the last line of note 4
+
+NOTE(bam)	This note which contains a (parenthesized) subphrase
+	 must appear in its entirety.
+
+NOTE(xxx)	The ':' after the marker and uid is optional.
+
+
+SECBUGS
+SECBUG(uid)	sec hole 0
+	need to fix asap
+
+
+TODOS
+TODO(uid)	todo0
+
+TODO(uid)	todo1
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/a0.go b/third_party/gofrontend/libgo/go/go/doc/testdata/a0.go
new file mode 100644
index 0000000..2420c8a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/a0.go
@@ -0,0 +1,40 @@
+// 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.
+
+// comment 0
+package a
+
+//BUG(uid): bug0
+
+//TODO(uid): todo0
+
+// A note with some spaces after it, should be ignored (watch out for
+// emacs modes that remove trailing whitespace).
+//NOTE(uid):
+
+// SECBUG(uid): sec hole 0
+// need to fix asap
+
+// Multiple notes may be in the same comment group and should be
+// recognized individually. Notes may start in the middle of a
+// comment group as long as they start at the beginning of an
+// individual comment.
+//
+// NOTE(foo): 1 of 4 - this is the first line of note 1
+// - note 1 continues on this 2nd line
+// - note 1 continues on this 3rd line
+// NOTE(foo): 2 of 4
+// NOTE(bar): 3 of 4
+/* NOTE(bar): 4 of 4 */
+// - this is the last line of note 4
+//
+//
+
+// NOTE(bam): This note which contains a (parenthesized) subphrase
+//            must appear in its entirety.
+
+// NOTE(xxx) The ':' after the marker and uid is optional.
+
+// NOTE(): NO uid - should not show up.
+// NOTE()  NO uid - should not show up.
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/a1.go b/third_party/gofrontend/libgo/go/go/doc/testdata/a1.go
new file mode 100644
index 0000000..9fad1e0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/a1.go
@@ -0,0 +1,12 @@
+// 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.
+
+// comment 1
+package a
+
+//BUG(uid): bug1
+
+//TODO(uid): todo1
+
+//TODO(): ignored
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/b.0.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/b.0.golden
new file mode 100644
index 0000000..9d93392
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/b.0.golden
@@ -0,0 +1,71 @@
+// 
+PACKAGE b
+
+IMPORTPATH
+	testdata/b
+
+IMPORTS
+	a
+
+FILENAMES
+	testdata/b.go
+
+CONSTANTS
+	// 
+	const (
+		C1	notExported	= iota
+		C2
+	
+		C4
+		C5
+	)
+
+	// 
+	const C notExported = 0
+
+	// 
+	const Pi = 3.14	// Pi
+
+
+VARIABLES
+	// 
+	var (
+		U1, U2, U4, U5	notExported
+	
+		U7	notExported	= 7
+	)
+
+	// 
+	var MaxInt int	// MaxInt
+
+	// 
+	var V notExported
+
+	// 
+	var V1, V2, V4, V5 notExported
+
+
+FUNCTIONS
+	// 
+	func F(x int) int
+
+	// 
+	func F1() notExported
+
+	// Always under the package functions list. 
+	func NotAFactory() int
+
+	// Associated with uint type if AllDecls is set. 
+	func UintFactory() uint
+
+
+TYPES
+	// 
+	type T struct{}	// T
+
+	// 
+	var V T	// v
+
+	// 
+	func (x *T) M()
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/b.1.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/b.1.golden
new file mode 100644
index 0000000..66c47b5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/b.1.golden
@@ -0,0 +1,83 @@
+// 
+PACKAGE b
+
+IMPORTPATH
+	testdata/b
+
+IMPORTS
+	a
+
+FILENAMES
+	testdata/b.go
+
+CONSTANTS
+	// 
+	const Pi = 3.14	// Pi
+
+
+VARIABLES
+	// 
+	var MaxInt int	// MaxInt
+
+
+FUNCTIONS
+	// 
+	func F(x int) int
+
+	// Always under the package functions list. 
+	func NotAFactory() int
+
+
+TYPES
+	// 
+	type T struct{}	// T
+
+	// 
+	var V T	// v
+
+	// 
+	func (x *T) M()
+
+	// 
+	type notExported int
+
+	// 
+	const (
+		C1	notExported	= iota
+		C2
+		c3
+		C4
+		C5
+	)
+
+	// 
+	const C notExported = 0
+
+	// 
+	var (
+		U1, U2, u3, U4, U5	notExported
+		u6			notExported
+		U7			notExported	= 7
+	)
+
+	// 
+	var V notExported
+
+	// 
+	var V1, V2, v3, V4, V5 notExported
+
+	// 
+	func F1() notExported
+
+	// 
+	func f2() notExported
+
+	// Should only appear if AllDecls is set. 
+	type uint struct{}	// overrides a predeclared type uint
+
+	// Associated with uint type if AllDecls is set. 
+	func UintFactory() uint
+
+	// Associated with uint type if AllDecls is set. 
+	func uintFactory() uint
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/b.2.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/b.2.golden
new file mode 100644
index 0000000..9d93392
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/b.2.golden
@@ -0,0 +1,71 @@
+// 
+PACKAGE b
+
+IMPORTPATH
+	testdata/b
+
+IMPORTS
+	a
+
+FILENAMES
+	testdata/b.go
+
+CONSTANTS
+	// 
+	const (
+		C1	notExported	= iota
+		C2
+	
+		C4
+		C5
+	)
+
+	// 
+	const C notExported = 0
+
+	// 
+	const Pi = 3.14	// Pi
+
+
+VARIABLES
+	// 
+	var (
+		U1, U2, U4, U5	notExported
+	
+		U7	notExported	= 7
+	)
+
+	// 
+	var MaxInt int	// MaxInt
+
+	// 
+	var V notExported
+
+	// 
+	var V1, V2, V4, V5 notExported
+
+
+FUNCTIONS
+	// 
+	func F(x int) int
+
+	// 
+	func F1() notExported
+
+	// Always under the package functions list. 
+	func NotAFactory() int
+
+	// Associated with uint type if AllDecls is set. 
+	func UintFactory() uint
+
+
+TYPES
+	// 
+	type T struct{}	// T
+
+	// 
+	var V T	// v
+
+	// 
+	func (x *T) M()
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/b.go b/third_party/gofrontend/libgo/go/go/doc/testdata/b.go
new file mode 100644
index 0000000..e50663b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/b.go
@@ -0,0 +1,58 @@
+// 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 b
+
+import "a"
+
+// ----------------------------------------------------------------------------
+// Basic declarations
+
+const Pi = 3.14   // Pi
+var MaxInt int    // MaxInt
+type T struct{}   // T
+var V T           // v
+func F(x int) int {} // F
+func (x *T) M()   {} // M
+
+// Corner cases: association with (presumed) predeclared types
+
+// Always under the package functions list.
+func NotAFactory() int {}
+
+// Associated with uint type if AllDecls is set.
+func UintFactory() uint {}
+
+// Associated with uint type if AllDecls is set.
+func uintFactory() uint {}
+
+// Should only appear if AllDecls is set.
+type uint struct{} // overrides a predeclared type uint
+
+// ----------------------------------------------------------------------------
+// Exported declarations associated with non-exported types must always be shown.
+
+type notExported int
+
+const C notExported = 0
+
+const (
+	C1 notExported = iota
+	C2
+	c3
+	C4
+	C5
+)
+
+var V notExported
+var V1, V2, v3, V4, V5 notExported
+
+var (
+	U1, U2, u3, U4, U5 notExported
+	u6                 notExported
+	U7                 notExported = 7
+)
+
+func F1() notExported {}
+func f2() notExported {}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/benchmark.go b/third_party/gofrontend/libgo/go/go/doc/testdata/benchmark.go
new file mode 100644
index 0000000..905e496
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/benchmark.go
@@ -0,0 +1,293 @@
+// 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 testing
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"runtime"
+	"time"
+)
+
+var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
+var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
+
+// An internal type but exported because it is cross-package; part of the implementation
+// of go test.
+type InternalBenchmark struct {
+	Name string
+	F    func(b *B)
+}
+
+// B is a type passed to Benchmark functions to manage benchmark
+// timing and to specify the number of iterations to run.
+type B struct {
+	common
+	N         int
+	benchmark InternalBenchmark
+	bytes     int64
+	timerOn   bool
+	result    BenchmarkResult
+}
+
+// StartTimer starts timing a test.  This function is called automatically
+// before a benchmark starts, but it can also used to resume timing after
+// a call to StopTimer.
+func (b *B) StartTimer() {
+	if !b.timerOn {
+		b.start = time.Now()
+		b.timerOn = true
+	}
+}
+
+// StopTimer stops timing a test.  This can be used to pause the timer
+// while performing complex initialization that you don't
+// want to measure.
+func (b *B) StopTimer() {
+	if b.timerOn {
+		b.duration += time.Now().Sub(b.start)
+		b.timerOn = false
+	}
+}
+
+// ResetTimer sets the elapsed benchmark time to zero.
+// It does not affect whether the timer is running.
+func (b *B) ResetTimer() {
+	if b.timerOn {
+		b.start = time.Now()
+	}
+	b.duration = 0
+}
+
+// SetBytes records the number of bytes processed in a single operation.
+// If this is called, the benchmark will report ns/op and MB/s.
+func (b *B) SetBytes(n int64) { b.bytes = n }
+
+func (b *B) nsPerOp() int64 {
+	if b.N <= 0 {
+		return 0
+	}
+	return b.duration.Nanoseconds() / int64(b.N)
+}
+
+// runN runs a single benchmark for the specified number of iterations.
+func (b *B) runN(n int) {
+	// Try to get a comparable environment for each run
+	// by clearing garbage from previous runs.
+	runtime.GC()
+	b.N = n
+	b.ResetTimer()
+	b.StartTimer()
+	b.benchmark.F(b)
+	b.StopTimer()
+}
+
+func min(x, y int) int {
+	if x > y {
+		return y
+	}
+	return x
+}
+
+func max(x, y int) int {
+	if x < y {
+		return y
+	}
+	return x
+}
+
+// roundDown10 rounds a number down to the nearest power of 10.
+func roundDown10(n int) int {
+	var tens = 0
+	// tens = floor(log_10(n))
+	for n > 10 {
+		n = n / 10
+		tens++
+	}
+	// result = 10^tens
+	result := 1
+	for i := 0; i < tens; i++ {
+		result *= 10
+	}
+	return result
+}
+
+// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
+func roundUp(n int) int {
+	base := roundDown10(n)
+	if n < (2 * base) {
+		return 2 * base
+	}
+	if n < (5 * base) {
+		return 5 * base
+	}
+	return 10 * base
+}
+
+// run times the benchmark function in a separate goroutine.
+func (b *B) run() BenchmarkResult {
+	go b.launch()
+	<-b.signal
+	return b.result
+}
+
+// launch launches the benchmark function.  It gradually increases the number
+// of benchmark iterations until the benchmark runs for a second in order
+// to get a reasonable measurement.  It prints timing information in this form
+//		testing.BenchmarkHello	100000		19 ns/op
+// launch is run by the fun function as a separate goroutine.
+func (b *B) launch() {
+	// Run the benchmark for a single iteration in case it's expensive.
+	n := 1
+
+	// Signal that we're done whether we return normally
+	// or by FailNow's runtime.Goexit.
+	defer func() {
+		b.signal <- b
+	}()
+
+	b.runN(n)
+	// Run the benchmark for at least the specified amount of time.
+	d := *benchTime
+	for !b.failed && b.duration < d && n < 1e9 {
+		last := n
+		// Predict iterations/sec.
+		if b.nsPerOp() == 0 {
+			n = 1e9
+		} else {
+			n = int(d.Nanoseconds() / b.nsPerOp())
+		}
+		// Run more iterations than we think we'll need for a second (1.5x).
+		// Don't grow too fast in case we had timing errors previously.
+		// Be sure to run at least one more than last time.
+		n = max(min(n+n/2, 100*last), last+1)
+		// Round up to something easy to read.
+		n = roundUp(n)
+		b.runN(n)
+	}
+	b.result = BenchmarkResult{b.N, b.duration, b.bytes}
+}
+
+// The results of a benchmark run.
+type BenchmarkResult struct {
+	N     int           // The number of iterations.
+	T     time.Duration // The total time taken.
+	Bytes int64         // Bytes processed in one iteration.
+}
+
+func (r BenchmarkResult) NsPerOp() int64 {
+	if r.N <= 0 {
+		return 0
+	}
+	return r.T.Nanoseconds() / int64(r.N)
+}
+
+func (r BenchmarkResult) mbPerSec() float64 {
+	if r.Bytes <= 0 || r.T <= 0 || r.N <= 0 {
+		return 0
+	}
+	return (float64(r.Bytes) * float64(r.N) / 1e6) / r.T.Seconds()
+}
+
+func (r BenchmarkResult) String() string {
+	mbs := r.mbPerSec()
+	mb := ""
+	if mbs != 0 {
+		mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
+	}
+	nsop := r.NsPerOp()
+	ns := fmt.Sprintf("%10d ns/op", nsop)
+	if r.N > 0 && nsop < 100 {
+		// The format specifiers here make sure that
+		// the ones digits line up for all three possible formats.
+		if nsop < 10 {
+			ns = fmt.Sprintf("%13.2f ns/op", float64(r.T.Nanoseconds())/float64(r.N))
+		} else {
+			ns = fmt.Sprintf("%12.1f ns/op", float64(r.T.Nanoseconds())/float64(r.N))
+		}
+	}
+	return fmt.Sprintf("%8d\t%s%s", r.N, ns, mb)
+}
+
+// An internal function but exported because it is cross-package; part of the implementation
+// of go test.
+func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
+	// If no flag was specified, don't run benchmarks.
+	if len(*matchBenchmarks) == 0 {
+		return
+	}
+	for _, Benchmark := range benchmarks {
+		matched, err := matchString(*matchBenchmarks, Benchmark.Name)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.bench: %s\n", err)
+			os.Exit(1)
+		}
+		if !matched {
+			continue
+		}
+		for _, procs := range cpuList {
+			runtime.GOMAXPROCS(procs)
+			b := &B{
+				common: common{
+					signal: make(chan interface{}),
+				},
+				benchmark: Benchmark,
+			}
+			benchName := Benchmark.Name
+			if procs != 1 {
+				benchName = fmt.Sprintf("%s-%d", Benchmark.Name, procs)
+			}
+			fmt.Printf("%s\t", benchName)
+			r := b.run()
+			if b.failed {
+				// The output could be very long here, but probably isn't.
+				// We print it all, regardless, because we don't want to trim the reason
+				// the benchmark failed.
+				fmt.Printf("--- FAIL: %s\n%s", benchName, b.output)
+				continue
+			}
+			fmt.Printf("%v\n", r)
+			// Unlike with tests, we ignore the -chatty flag and always print output for
+			// benchmarks since the output generation time will skew the results.
+			if len(b.output) > 0 {
+				b.trimOutput()
+				fmt.Printf("--- BENCH: %s\n%s", benchName, b.output)
+			}
+			if p := runtime.GOMAXPROCS(-1); p != procs {
+				fmt.Fprintf(os.Stderr, "testing: %s left GOMAXPROCS set to %d\n", benchName, p)
+			}
+		}
+	}
+}
+
+// trimOutput shortens the output from a benchmark, which can be very long.
+func (b *B) trimOutput() {
+	// The output is likely to appear multiple times because the benchmark
+	// is run multiple times, but at least it will be seen. This is not a big deal
+	// because benchmarks rarely print, but just in case, we trim it if it's too long.
+	const maxNewlines = 10
+	for nlCount, j := 0, 0; j < len(b.output); j++ {
+		if b.output[j] == '\n' {
+			nlCount++
+			if nlCount >= maxNewlines {
+				b.output = append(b.output[:j], "\n\t... [output truncated]\n"...)
+				break
+			}
+		}
+	}
+}
+
+// Benchmark benchmarks a single function. Useful for creating
+// custom benchmarks that do not use go test.
+func Benchmark(f func(b *B)) BenchmarkResult {
+	b := &B{
+		common: common{
+			signal: make(chan interface{}),
+		},
+		benchmark: InternalBenchmark{"", f},
+	}
+	return b.run()
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.0.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.0.golden
new file mode 100644
index 0000000..5804859
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.0.golden
@@ -0,0 +1,20 @@
+// 
+PACKAGE bugpara
+
+IMPORTPATH
+	testdata/bugpara
+
+FILENAMES
+	testdata/bugpara.go
+
+BUGS .Bugs is now deprecated, please use .Notes instead
+	Sometimes bugs have multiple paragraphs.
+	
+	Like this one.
+
+
+BUGS
+BUG(rsc)	Sometimes bugs have multiple paragraphs.
+	
+	Like this one.
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.1.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.1.golden
new file mode 100644
index 0000000..5804859
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.1.golden
@@ -0,0 +1,20 @@
+// 
+PACKAGE bugpara
+
+IMPORTPATH
+	testdata/bugpara
+
+FILENAMES
+	testdata/bugpara.go
+
+BUGS .Bugs is now deprecated, please use .Notes instead
+	Sometimes bugs have multiple paragraphs.
+	
+	Like this one.
+
+
+BUGS
+BUG(rsc)	Sometimes bugs have multiple paragraphs.
+	
+	Like this one.
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.2.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.2.golden
new file mode 100644
index 0000000..5804859
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.2.golden
@@ -0,0 +1,20 @@
+// 
+PACKAGE bugpara
+
+IMPORTPATH
+	testdata/bugpara
+
+FILENAMES
+	testdata/bugpara.go
+
+BUGS .Bugs is now deprecated, please use .Notes instead
+	Sometimes bugs have multiple paragraphs.
+	
+	Like this one.
+
+
+BUGS
+BUG(rsc)	Sometimes bugs have multiple paragraphs.
+	
+	Like this one.
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.go b/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.go
new file mode 100644
index 0000000..f5345a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/bugpara.go
@@ -0,0 +1,5 @@
+package bugpara
+
+// BUG(rsc): Sometimes bugs have multiple paragraphs.
+//
+// Like this one.
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/c.0.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/c.0.golden
new file mode 100644
index 0000000..e21959b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/c.0.golden
@@ -0,0 +1,48 @@
+// 
+PACKAGE c
+
+IMPORTPATH
+	testdata/c
+
+IMPORTS
+	a
+
+FILENAMES
+	testdata/c.go
+
+TYPES
+	// A (should see this) 
+	type A struct{}
+
+	// B (should see this) 
+	type B struct{}
+
+	// C (should see this) 
+	type C struct{}
+
+	// D (should see this) 
+	type D struct{}
+
+	// E1 (should see this) 
+	type E1 struct{}
+
+	// E (should see this for E2 and E3) 
+	type E2 struct{}
+
+	// E (should see this for E2 and E3) 
+	type E3 struct{}
+
+	// E4 (should see this) 
+	type E4 struct{}
+
+	// 
+	type T1 struct{}
+
+	// 
+	func (t1 *T1) M()
+
+	// T2 must not show methods of local T1 
+	type T2 struct {
+		a.T1	// not the same as locally declared T1
+	}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/c.1.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/c.1.golden
new file mode 100644
index 0000000..e21959b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/c.1.golden
@@ -0,0 +1,48 @@
+// 
+PACKAGE c
+
+IMPORTPATH
+	testdata/c
+
+IMPORTS
+	a
+
+FILENAMES
+	testdata/c.go
+
+TYPES
+	// A (should see this) 
+	type A struct{}
+
+	// B (should see this) 
+	type B struct{}
+
+	// C (should see this) 
+	type C struct{}
+
+	// D (should see this) 
+	type D struct{}
+
+	// E1 (should see this) 
+	type E1 struct{}
+
+	// E (should see this for E2 and E3) 
+	type E2 struct{}
+
+	// E (should see this for E2 and E3) 
+	type E3 struct{}
+
+	// E4 (should see this) 
+	type E4 struct{}
+
+	// 
+	type T1 struct{}
+
+	// 
+	func (t1 *T1) M()
+
+	// T2 must not show methods of local T1 
+	type T2 struct {
+		a.T1	// not the same as locally declared T1
+	}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/c.2.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/c.2.golden
new file mode 100644
index 0000000..e21959b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/c.2.golden
@@ -0,0 +1,48 @@
+// 
+PACKAGE c
+
+IMPORTPATH
+	testdata/c
+
+IMPORTS
+	a
+
+FILENAMES
+	testdata/c.go
+
+TYPES
+	// A (should see this) 
+	type A struct{}
+
+	// B (should see this) 
+	type B struct{}
+
+	// C (should see this) 
+	type C struct{}
+
+	// D (should see this) 
+	type D struct{}
+
+	// E1 (should see this) 
+	type E1 struct{}
+
+	// E (should see this for E2 and E3) 
+	type E2 struct{}
+
+	// E (should see this for E2 and E3) 
+	type E3 struct{}
+
+	// E4 (should see this) 
+	type E4 struct{}
+
+	// 
+	type T1 struct{}
+
+	// 
+	func (t1 *T1) M()
+
+	// T2 must not show methods of local T1 
+	type T2 struct {
+		a.T1	// not the same as locally declared T1
+	}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/c.go b/third_party/gofrontend/libgo/go/go/doc/testdata/c.go
new file mode 100644
index 0000000..e0f3919
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/c.go
@@ -0,0 +1,62 @@
+// 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 c
+
+import "a"
+
+// ----------------------------------------------------------------------------
+// Test that empty declarations don't cause problems
+
+const ()
+
+type ()
+
+var ()
+
+// ----------------------------------------------------------------------------
+// Test that types with documentation on both, the Decl and the Spec node
+// are handled correctly.
+
+// A (should see this)
+type A struct{}
+
+// B (should see this)
+type (
+	B struct{}
+)
+
+type (
+	// C (should see this)
+	C struct{}
+)
+
+// D (should not see this)
+type (
+	// D (should see this)
+	D struct{}
+)
+
+// E (should see this for E2 and E3)
+type (
+	// E1 (should see this)
+	E1 struct{}
+	E2 struct{}
+	E3 struct{}
+	// E4 (should see this)
+	E4 struct{}
+)
+
+// ----------------------------------------------------------------------------
+// Test that local and imported types are different when
+// handling anonymous fields.
+
+type T1 struct{}
+
+func (t1 *T1) M() {}
+
+// T2 must not show methods of local T1
+type T2 struct {
+	a.T1 // not the same as locally declared T1
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/d.0.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/d.0.golden
new file mode 100644
index 0000000..c005199
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/d.0.golden
@@ -0,0 +1,104 @@
+// 
+PACKAGE d
+
+IMPORTPATH
+	testdata/d
+
+FILENAMES
+	testdata/d1.go
+	testdata/d2.go
+
+CONSTANTS
+	// CBx constants should appear before CAx constants. 
+	const (
+		CB2	= iota	// before CB1
+		CB1		// before CB0
+		CB0		// at end
+	)
+
+	// CAx constants should appear after CBx constants. 
+	const (
+		CA2	= iota	// before CA1
+		CA1		// before CA0
+		CA0		// at end
+	)
+
+	// C0 should be first. 
+	const C0 = 0
+
+	// C1 should be second. 
+	const C1 = 1
+
+	// C2 should be third. 
+	const C2 = 2
+
+	// 
+	const (
+		// Single const declarations inside ()'s are considered ungrouped
+		// and show up in sorted order.
+		Cungrouped = 0
+	)
+
+
+VARIABLES
+	// VBx variables should appear before VAx variables. 
+	var (
+		VB2	int	// before VB1
+		VB1	int	// before VB0
+		VB0	int	// at end
+	)
+
+	// VAx variables should appear after VBx variables. 
+	var (
+		VA2	int	// before VA1
+		VA1	int	// before VA0
+		VA0	int	// at end
+	)
+
+	// V0 should be first. 
+	var V0 uintptr
+
+	// V1 should be second. 
+	var V1 uint
+
+	// V2 should be third. 
+	var V2 int
+
+	// 
+	var (
+		// Single var declarations inside ()'s are considered ungrouped
+		// and show up in sorted order.
+		Vungrouped = 0
+	)
+
+
+FUNCTIONS
+	// F0 should be first. 
+	func F0()
+
+	// F1 should be second. 
+	func F1()
+
+	// F2 should be third. 
+	func F2()
+
+
+TYPES
+	// T0 should be first. 
+	type T0 struct{}
+
+	// T1 should be second. 
+	type T1 struct{}
+
+	// T2 should be third. 
+	type T2 struct{}
+
+	// TG0 should be first. 
+	type TG0 struct{}
+
+	// TG1 should be second. 
+	type TG1 struct{}
+
+	// TG2 should be third. 
+	type TG2 struct{}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/d.1.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/d.1.golden
new file mode 100644
index 0000000..c005199
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/d.1.golden
@@ -0,0 +1,104 @@
+// 
+PACKAGE d
+
+IMPORTPATH
+	testdata/d
+
+FILENAMES
+	testdata/d1.go
+	testdata/d2.go
+
+CONSTANTS
+	// CBx constants should appear before CAx constants. 
+	const (
+		CB2	= iota	// before CB1
+		CB1		// before CB0
+		CB0		// at end
+	)
+
+	// CAx constants should appear after CBx constants. 
+	const (
+		CA2	= iota	// before CA1
+		CA1		// before CA0
+		CA0		// at end
+	)
+
+	// C0 should be first. 
+	const C0 = 0
+
+	// C1 should be second. 
+	const C1 = 1
+
+	// C2 should be third. 
+	const C2 = 2
+
+	// 
+	const (
+		// Single const declarations inside ()'s are considered ungrouped
+		// and show up in sorted order.
+		Cungrouped = 0
+	)
+
+
+VARIABLES
+	// VBx variables should appear before VAx variables. 
+	var (
+		VB2	int	// before VB1
+		VB1	int	// before VB0
+		VB0	int	// at end
+	)
+
+	// VAx variables should appear after VBx variables. 
+	var (
+		VA2	int	// before VA1
+		VA1	int	// before VA0
+		VA0	int	// at end
+	)
+
+	// V0 should be first. 
+	var V0 uintptr
+
+	// V1 should be second. 
+	var V1 uint
+
+	// V2 should be third. 
+	var V2 int
+
+	// 
+	var (
+		// Single var declarations inside ()'s are considered ungrouped
+		// and show up in sorted order.
+		Vungrouped = 0
+	)
+
+
+FUNCTIONS
+	// F0 should be first. 
+	func F0()
+
+	// F1 should be second. 
+	func F1()
+
+	// F2 should be third. 
+	func F2()
+
+
+TYPES
+	// T0 should be first. 
+	type T0 struct{}
+
+	// T1 should be second. 
+	type T1 struct{}
+
+	// T2 should be third. 
+	type T2 struct{}
+
+	// TG0 should be first. 
+	type TG0 struct{}
+
+	// TG1 should be second. 
+	type TG1 struct{}
+
+	// TG2 should be third. 
+	type TG2 struct{}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/d.2.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/d.2.golden
new file mode 100644
index 0000000..c005199
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/d.2.golden
@@ -0,0 +1,104 @@
+// 
+PACKAGE d
+
+IMPORTPATH
+	testdata/d
+
+FILENAMES
+	testdata/d1.go
+	testdata/d2.go
+
+CONSTANTS
+	// CBx constants should appear before CAx constants. 
+	const (
+		CB2	= iota	// before CB1
+		CB1		// before CB0
+		CB0		// at end
+	)
+
+	// CAx constants should appear after CBx constants. 
+	const (
+		CA2	= iota	// before CA1
+		CA1		// before CA0
+		CA0		// at end
+	)
+
+	// C0 should be first. 
+	const C0 = 0
+
+	// C1 should be second. 
+	const C1 = 1
+
+	// C2 should be third. 
+	const C2 = 2
+
+	// 
+	const (
+		// Single const declarations inside ()'s are considered ungrouped
+		// and show up in sorted order.
+		Cungrouped = 0
+	)
+
+
+VARIABLES
+	// VBx variables should appear before VAx variables. 
+	var (
+		VB2	int	// before VB1
+		VB1	int	// before VB0
+		VB0	int	// at end
+	)
+
+	// VAx variables should appear after VBx variables. 
+	var (
+		VA2	int	// before VA1
+		VA1	int	// before VA0
+		VA0	int	// at end
+	)
+
+	// V0 should be first. 
+	var V0 uintptr
+
+	// V1 should be second. 
+	var V1 uint
+
+	// V2 should be third. 
+	var V2 int
+
+	// 
+	var (
+		// Single var declarations inside ()'s are considered ungrouped
+		// and show up in sorted order.
+		Vungrouped = 0
+	)
+
+
+FUNCTIONS
+	// F0 should be first. 
+	func F0()
+
+	// F1 should be second. 
+	func F1()
+
+	// F2 should be third. 
+	func F2()
+
+
+TYPES
+	// T0 should be first. 
+	type T0 struct{}
+
+	// T1 should be second. 
+	type T1 struct{}
+
+	// T2 should be third. 
+	type T2 struct{}
+
+	// TG0 should be first. 
+	type TG0 struct{}
+
+	// TG1 should be second. 
+	type TG1 struct{}
+
+	// TG2 should be third. 
+	type TG2 struct{}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/d1.go b/third_party/gofrontend/libgo/go/go/doc/testdata/d1.go
new file mode 100644
index 0000000..ebd6941
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/d1.go
@@ -0,0 +1,57 @@
+// 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.
+
+// Test cases for sort order of declarations.
+
+package d
+
+// C2 should be third.
+const C2 = 2
+
+// V2 should be third.
+var V2 int
+
+// CBx constants should appear before CAx constants.
+const (
+	CB2 = iota // before CB1
+	CB1        // before CB0
+	CB0        // at end
+)
+
+// VBx variables should appear before VAx variables.
+var (
+	VB2 int // before VB1
+	VB1 int // before VB0
+	VB0 int // at end
+)
+
+const (
+	// Single const declarations inside ()'s are considered ungrouped
+	// and show up in sorted order.
+	Cungrouped = 0
+)
+
+var (
+	// Single var declarations inside ()'s are considered ungrouped
+	// and show up in sorted order.
+	Vungrouped = 0
+)
+
+// T2 should be third.
+type T2 struct{}
+
+// Grouped types are sorted nevertheless.
+type (
+	// TG2 should be third.
+	TG2 struct{}
+
+	// TG1 should be second.
+	TG1 struct{}
+
+	// TG0 should be first.
+	TG0 struct{}
+)
+
+// F2 should be third.
+func F2() {}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/d2.go b/third_party/gofrontend/libgo/go/go/doc/testdata/d2.go
new file mode 100644
index 0000000..2f56f4f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/d2.go
@@ -0,0 +1,45 @@
+// 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.
+
+// Test cases for sort order of declarations.
+
+package d
+
+// C1 should be second.
+const C1 = 1
+
+// C0 should be first.
+const C0 = 0
+
+// V1 should be second.
+var V1 uint
+
+// V0 should be first.
+var V0 uintptr
+
+// CAx constants should appear after CBx constants.
+const (
+	CA2 = iota // before CA1
+	CA1        // before CA0
+	CA0        // at end
+)
+
+// VAx variables should appear after VBx variables.
+var (
+	VA2 int // before VA1
+	VA1 int // before VA0
+	VA0 int // at end
+)
+
+// T1 should be second.
+type T1 struct{}
+
+// T0 should be first.
+type T0 struct{}
+
+// F1 should be second.
+func F1() {}
+
+// F0 should be first.
+func F0() {}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/e.0.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/e.0.golden
new file mode 100644
index 0000000..6987e58
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/e.0.golden
@@ -0,0 +1,109 @@
+// The package e is a go/doc test for embedded methods. 
+PACKAGE e
+
+IMPORTPATH
+	testdata/e
+
+FILENAMES
+	testdata/e.go
+
+TYPES
+	// T1 has no embedded (level 1) M method due to conflict. 
+	type T1 struct {
+		// contains filtered or unexported fields
+	}
+
+	// T2 has only M as top-level method. 
+	type T2 struct {
+		// contains filtered or unexported fields
+	}
+
+	// T2.M should appear as method of T2. 
+	func (T2) M()
+
+	// T3 has only M as top-level method. 
+	type T3 struct {
+		// contains filtered or unexported fields
+	}
+
+	// T3.M should appear as method of T3. 
+	func (T3) M()
+
+	// 
+	type T4 struct{}
+
+	// T4.M should appear as method of T5 only if AllMethods is set. 
+	func (*T4) M()
+
+	// 
+	type T5 struct {
+		T4
+	}
+
+	// 
+	type U1 struct {
+		*U1
+	}
+
+	// U1.M should appear as method of U1. 
+	func (*U1) M()
+
+	// 
+	type U2 struct {
+		*U3
+	}
+
+	// U2.M should appear as method of U2 and as method of U3 only if ...
+	func (*U2) M()
+
+	// 
+	type U3 struct {
+		*U2
+	}
+
+	// U3.N should appear as method of U3 and as method of U2 only if ...
+	func (*U3) N()
+
+	// 
+	type U4 struct {
+		// contains filtered or unexported fields
+	}
+
+	// U4.M should appear as method of U4. 
+	func (*U4) M()
+
+	// 
+	type V1 struct {
+		*V2
+		*V5
+	}
+
+	// 
+	type V2 struct {
+		*V3
+	}
+
+	// 
+	type V3 struct {
+		*V4
+	}
+
+	// 
+	type V4 struct {
+		*V5
+	}
+
+	// V4.M should appear as method of V2 and V3 if AllMethods is set. 
+	func (*V4) M()
+
+	// 
+	type V5 struct {
+		*V6
+	}
+
+	// 
+	type V6 struct{}
+
+	// V6.M should appear as method of V1 and V5 if AllMethods is set. 
+	func (*V6) M()
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/e.1.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/e.1.golden
new file mode 100644
index 0000000..cbe22e0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/e.1.golden
@@ -0,0 +1,144 @@
+// The package e is a go/doc test for embedded methods. 
+PACKAGE e
+
+IMPORTPATH
+	testdata/e
+
+FILENAMES
+	testdata/e.go
+
+TYPES
+	// T1 has no embedded (level 1) M method due to conflict. 
+	type T1 struct {
+		t1
+		t2
+	}
+
+	// T2 has only M as top-level method. 
+	type T2 struct {
+		t1
+	}
+
+	// T2.M should appear as method of T2. 
+	func (T2) M()
+
+	// T3 has only M as top-level method. 
+	type T3 struct {
+		t1e
+		t2e
+	}
+
+	// T3.M should appear as method of T3. 
+	func (T3) M()
+
+	// 
+	type T4 struct{}
+
+	// T4.M should appear as method of T5 only if AllMethods is set. 
+	func (*T4) M()
+
+	// 
+	type T5 struct {
+		T4
+	}
+
+	// 
+	type U1 struct {
+		*U1
+	}
+
+	// U1.M should appear as method of U1. 
+	func (*U1) M()
+
+	// 
+	type U2 struct {
+		*U3
+	}
+
+	// U2.M should appear as method of U2 and as method of U3 only if ...
+	func (*U2) M()
+
+	// 
+	type U3 struct {
+		*U2
+	}
+
+	// U3.N should appear as method of U3 and as method of U2 only if ...
+	func (*U3) N()
+
+	// 
+	type U4 struct {
+		*u5
+	}
+
+	// U4.M should appear as method of U4. 
+	func (*U4) M()
+
+	// 
+	type V1 struct {
+		*V2
+		*V5
+	}
+
+	// 
+	type V2 struct {
+		*V3
+	}
+
+	// 
+	type V3 struct {
+		*V4
+	}
+
+	// 
+	type V4 struct {
+		*V5
+	}
+
+	// V4.M should appear as method of V2 and V3 if AllMethods is set. 
+	func (*V4) M()
+
+	// 
+	type V5 struct {
+		*V6
+	}
+
+	// 
+	type V6 struct{}
+
+	// V6.M should appear as method of V1 and V5 if AllMethods is set. 
+	func (*V6) M()
+
+	// 
+	type t1 struct{}
+
+	// t1.M should not appear as method in a Tx type. 
+	func (t1) M()
+
+	// 
+	type t1e struct {
+		t1
+	}
+
+	// t1.M should not appear as method in a Tx type. 
+	func (t1e) M()
+
+	// 
+	type t2 struct{}
+
+	// t2.M should not appear as method in a Tx type. 
+	func (t2) M()
+
+	// 
+	type t2e struct {
+		t2
+	}
+
+	// t2.M should not appear as method in a Tx type. 
+	func (t2e) M()
+
+	// 
+	type u5 struct {
+		*U4
+	}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/e.2.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/e.2.golden
new file mode 100644
index 0000000..e7b05e8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/e.2.golden
@@ -0,0 +1,130 @@
+// The package e is a go/doc test for embedded methods. 
+PACKAGE e
+
+IMPORTPATH
+	testdata/e
+
+FILENAMES
+	testdata/e.go
+
+TYPES
+	// T1 has no embedded (level 1) M method due to conflict. 
+	type T1 struct {
+		// contains filtered or unexported fields
+	}
+
+	// T2 has only M as top-level method. 
+	type T2 struct {
+		// contains filtered or unexported fields
+	}
+
+	// T2.M should appear as method of T2. 
+	func (T2) M()
+
+	// T3 has only M as top-level method. 
+	type T3 struct {
+		// contains filtered or unexported fields
+	}
+
+	// T3.M should appear as method of T3. 
+	func (T3) M()
+
+	// 
+	type T4 struct{}
+
+	// T4.M should appear as method of T5 only if AllMethods is set. 
+	func (*T4) M()
+
+	// 
+	type T5 struct {
+		T4
+	}
+
+	// T4.M should appear as method of T5 only if AllMethods is set. 
+	func (*T5) M()
+
+	// 
+	type U1 struct {
+		*U1
+	}
+
+	// U1.M should appear as method of U1. 
+	func (*U1) M()
+
+	// 
+	type U2 struct {
+		*U3
+	}
+
+	// U2.M should appear as method of U2 and as method of U3 only if ...
+	func (*U2) M()
+
+	// U3.N should appear as method of U3 and as method of U2 only if ...
+	func (U2) N()
+
+	// 
+	type U3 struct {
+		*U2
+	}
+
+	// U2.M should appear as method of U2 and as method of U3 only if ...
+	func (U3) M()
+
+	// U3.N should appear as method of U3 and as method of U2 only if ...
+	func (*U3) N()
+
+	// 
+	type U4 struct {
+		// contains filtered or unexported fields
+	}
+
+	// U4.M should appear as method of U4. 
+	func (*U4) M()
+
+	// 
+	type V1 struct {
+		*V2
+		*V5
+	}
+
+	// V6.M should appear as method of V1 and V5 if AllMethods is set. 
+	func (V1) M()
+
+	// 
+	type V2 struct {
+		*V3
+	}
+
+	// V4.M should appear as method of V2 and V3 if AllMethods is set. 
+	func (V2) M()
+
+	// 
+	type V3 struct {
+		*V4
+	}
+
+	// V4.M should appear as method of V2 and V3 if AllMethods is set. 
+	func (V3) M()
+
+	// 
+	type V4 struct {
+		*V5
+	}
+
+	// V4.M should appear as method of V2 and V3 if AllMethods is set. 
+	func (*V4) M()
+
+	// 
+	type V5 struct {
+		*V6
+	}
+
+	// V6.M should appear as method of V1 and V5 if AllMethods is set. 
+	func (V5) M()
+
+	// 
+	type V6 struct{}
+
+	// V6.M should appear as method of V1 and V5 if AllMethods is set. 
+	func (*V6) M()
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/e.go b/third_party/gofrontend/libgo/go/go/doc/testdata/e.go
new file mode 100644
index 0000000..ec432e3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/e.go
@@ -0,0 +1,147 @@
+// 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.
+
+// The package e is a go/doc test for embedded methods.
+package e
+
+// ----------------------------------------------------------------------------
+// Conflicting methods M must not show up.
+
+type t1 struct{}
+
+// t1.M should not appear as method in a Tx type.
+func (t1) M() {}
+
+type t2 struct{}
+
+// t2.M should not appear as method in a Tx type.
+func (t2) M() {}
+
+// T1 has no embedded (level 1) M method due to conflict.
+type T1 struct {
+	t1
+	t2
+}
+
+// ----------------------------------------------------------------------------
+// Higher-level method M wins over lower-level method M.
+
+// T2 has only M as top-level method.
+type T2 struct {
+	t1
+}
+
+// T2.M should appear as method of T2.
+func (T2) M() {}
+
+// ----------------------------------------------------------------------------
+// Higher-level method M wins over lower-level conflicting methods M.
+
+type t1e struct {
+	t1
+}
+
+type t2e struct {
+	t2
+}
+
+// T3 has only M as top-level method.
+type T3 struct {
+	t1e
+	t2e
+}
+
+// T3.M should appear as method of T3.
+func (T3) M() {}
+
+// ----------------------------------------------------------------------------
+// Don't show conflicting methods M embedded via an exported and non-exported
+// type.
+
+// T1 has no embedded (level 1) M method due to conflict.
+type T4 struct {
+	t2
+	T2
+}
+
+// ----------------------------------------------------------------------------
+// Don't show embedded methods of exported anonymous fields unless AllMethods
+// is set.
+
+type T4 struct{}
+
+// T4.M should appear as method of T5 only if AllMethods is set.
+func (*T4) M() {}
+
+type T5 struct {
+	T4
+}
+
+// ----------------------------------------------------------------------------
+// Recursive type declarations must not lead to endless recursion.
+
+type U1 struct {
+	*U1
+}
+
+// U1.M should appear as method of U1.
+func (*U1) M() {}
+
+type U2 struct {
+	*U3
+}
+
+// U2.M should appear as method of U2 and as method of U3 only if AllMethods is set.
+func (*U2) M() {}
+
+type U3 struct {
+	*U2
+}
+
+// U3.N should appear as method of U3 and as method of U2 only if AllMethods is set.
+func (*U3) N() {}
+
+type U4 struct {
+	*u5
+}
+
+// U4.M should appear as method of U4.
+func (*U4) M() {}
+
+type u5 struct {
+	*U4
+}
+
+// ----------------------------------------------------------------------------
+// A higher-level embedded type (and its methods) wins over the same type (and
+// its methods) embedded at a lower level.
+
+type V1 struct {
+	*V2
+	*V5
+}
+
+type V2 struct {
+	*V3
+}
+
+type V3 struct {
+	*V4
+}
+
+type V4 struct {
+	*V5
+}
+
+type V5 struct {
+	*V6
+}
+
+type V6 struct{}
+
+// V4.M should appear as method of V2 and V3 if AllMethods is set.
+func (*V4) M() {}
+
+// V6.M should appear as method of V1 and V5 if AllMethods is set.
+func (*V6) M() {}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/error1.0.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/error1.0.golden
new file mode 100644
index 0000000..6c6fe5d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/error1.0.golden
@@ -0,0 +1,30 @@
+// 
+PACKAGE error1
+
+IMPORTPATH
+	testdata/error1
+
+FILENAMES
+	testdata/error1.go
+
+TYPES
+	// 
+	type I0 interface {
+		// When embedded, the predeclared error interface
+		// must remain visible in interface types.
+		error
+	}
+
+	// 
+	type S0 struct {
+		// contains filtered or unexported fields
+	}
+
+	// 
+	type T0 struct {
+		ExportedField interface {
+			// error should be visible
+			error
+		}
+	}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/error1.1.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/error1.1.golden
new file mode 100644
index 0000000..a8dc2e7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/error1.1.golden
@@ -0,0 +1,32 @@
+// 
+PACKAGE error1
+
+IMPORTPATH
+	testdata/error1
+
+FILENAMES
+	testdata/error1.go
+
+TYPES
+	// 
+	type I0 interface {
+		// When embedded, the predeclared error interface
+		// must remain visible in interface types.
+		error
+	}
+
+	// 
+	type S0 struct {
+		// In struct types, an embedded error must only be visible
+		// if AllDecls is set.
+		error
+	}
+
+	// 
+	type T0 struct {
+		ExportedField interface {
+			// error should be visible
+			error
+		}
+	}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/error1.2.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/error1.2.golden
new file mode 100644
index 0000000..6c6fe5d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/error1.2.golden
@@ -0,0 +1,30 @@
+// 
+PACKAGE error1
+
+IMPORTPATH
+	testdata/error1
+
+FILENAMES
+	testdata/error1.go
+
+TYPES
+	// 
+	type I0 interface {
+		// When embedded, the predeclared error interface
+		// must remain visible in interface types.
+		error
+	}
+
+	// 
+	type S0 struct {
+		// contains filtered or unexported fields
+	}
+
+	// 
+	type T0 struct {
+		ExportedField interface {
+			// error should be visible
+			error
+		}
+	}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/error1.go b/third_party/gofrontend/libgo/go/go/doc/testdata/error1.go
new file mode 100644
index 0000000..3c777a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/error1.go
@@ -0,0 +1,24 @@
+// 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 error1
+
+type I0 interface {
+	// When embedded, the predeclared error interface
+	// must remain visible in interface types.
+	error
+}
+
+type T0 struct {
+	ExportedField interface {
+		// error should be visible
+		error
+	}
+}
+
+type S0 struct {
+	// In struct types, an embedded error must only be visible
+	// if AllDecls is set.
+	error
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/error2.0.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/error2.0.golden
new file mode 100644
index 0000000..dedfe41
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/error2.0.golden
@@ -0,0 +1,27 @@
+// 
+PACKAGE error2
+
+IMPORTPATH
+	testdata/error2
+
+FILENAMES
+	testdata/error2.go
+
+TYPES
+	// 
+	type I0 interface {
+		// contains filtered or unexported methods
+	}
+
+	// 
+	type S0 struct {
+		// contains filtered or unexported fields
+	}
+
+	// 
+	type T0 struct {
+		ExportedField interface {
+			// contains filtered or unexported methods
+		}
+	}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/error2.1.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/error2.1.golden
new file mode 100644
index 0000000..dbcc1b0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/error2.1.golden
@@ -0,0 +1,37 @@
+// 
+PACKAGE error2
+
+IMPORTPATH
+	testdata/error2
+
+FILENAMES
+	testdata/error2.go
+
+TYPES
+	// 
+	type I0 interface {
+		// When embedded, the locally-declared error interface
+		// is only visible if all declarations are shown.
+		error
+	}
+
+	// 
+	type S0 struct {
+		// In struct types, an embedded error must only be visible
+		// if AllDecls is set.
+		error
+	}
+
+	// 
+	type T0 struct {
+		ExportedField interface {
+			// error should not be visible
+			error
+		}
+	}
+
+	// This error declaration shadows the predeclared error type. 
+	type error interface {
+		Error() string
+	}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/error2.2.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/error2.2.golden
new file mode 100644
index 0000000..dedfe41
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/error2.2.golden
@@ -0,0 +1,27 @@
+// 
+PACKAGE error2
+
+IMPORTPATH
+	testdata/error2
+
+FILENAMES
+	testdata/error2.go
+
+TYPES
+	// 
+	type I0 interface {
+		// contains filtered or unexported methods
+	}
+
+	// 
+	type S0 struct {
+		// contains filtered or unexported fields
+	}
+
+	// 
+	type T0 struct {
+		ExportedField interface {
+			// contains filtered or unexported methods
+		}
+	}
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/error2.go b/third_party/gofrontend/libgo/go/go/doc/testdata/error2.go
new file mode 100644
index 0000000..6ee96c2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/error2.go
@@ -0,0 +1,29 @@
+// 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 error2
+
+type I0 interface {
+	// When embedded, the locally-declared error interface
+	// is only visible if all declarations are shown.
+	error
+}
+
+type T0 struct {
+	ExportedField interface {
+		// error should not be visible
+		error
+	}
+}
+
+type S0 struct {
+	// In struct types, an embedded error must only be visible
+	// if AllDecls is set.
+	error
+}
+
+// This error declaration shadows the predeclared error type.
+type error interface {
+	Error() string
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/example.go b/third_party/gofrontend/libgo/go/go/doc/testdata/example.go
new file mode 100644
index 0000000..fdeda13
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/example.go
@@ -0,0 +1,81 @@
+// 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 testing
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"time"
+)
+
+type InternalExample struct {
+	Name   string
+	F      func()
+	Output string
+}
+
+func RunExamples(examples []InternalExample) (ok bool) {
+	ok = true
+
+	var eg InternalExample
+
+	stdout, stderr := os.Stdout, os.Stderr
+	defer func() {
+		os.Stdout, os.Stderr = stdout, stderr
+		if e := recover(); e != nil {
+			fmt.Printf("--- FAIL: %s\npanic: %v\n", eg.Name, e)
+			os.Exit(1)
+		}
+	}()
+
+	for _, eg = range examples {
+		if *chatty {
+			fmt.Printf("=== RUN: %s\n", eg.Name)
+		}
+
+		// capture stdout and stderr
+		r, w, err := os.Pipe()
+		if err != nil {
+			fmt.Fprintln(os.Stderr, err)
+			os.Exit(1)
+		}
+		os.Stdout, os.Stderr = w, w
+		outC := make(chan string)
+		go func() {
+			buf := new(bytes.Buffer)
+			_, err := io.Copy(buf, r)
+			if err != nil {
+				fmt.Fprintf(stderr, "testing: copying pipe: %v\n", err)
+				os.Exit(1)
+			}
+			outC <- buf.String()
+		}()
+
+		// run example
+		t0 := time.Now()
+		eg.F()
+		dt := time.Now().Sub(t0)
+
+		// close pipe, restore stdout/stderr, get output
+		w.Close()
+		os.Stdout, os.Stderr = stdout, stderr
+		out := <-outC
+
+		// report any errors
+		tstr := fmt.Sprintf("(%.2f seconds)", dt.Seconds())
+		if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e {
+			fmt.Printf("--- FAIL: %s %s\ngot:\n%s\nwant:\n%s\n",
+				eg.Name, tstr, g, e)
+			ok = false
+		} else if *chatty {
+			fmt.Printf("--- PASS: %s %s\n", eg.Name, tstr)
+		}
+	}
+
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/f.0.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/f.0.golden
new file mode 100644
index 0000000..8175901
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/f.0.golden
@@ -0,0 +1,13 @@
+// The package f is a go/doc test for functions and factory ...
+PACKAGE f
+
+IMPORTPATH
+	testdata/f
+
+FILENAMES
+	testdata/f.go
+
+FUNCTIONS
+	// Exported must always be visible. Was issue 2824. 
+	func Exported() private
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/f.1.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/f.1.golden
new file mode 100644
index 0000000..ba68e88
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/f.1.golden
@@ -0,0 +1,16 @@
+// The package f is a go/doc test for functions and factory ...
+PACKAGE f
+
+IMPORTPATH
+	testdata/f
+
+FILENAMES
+	testdata/f.go
+
+TYPES
+	// 
+	type private struct{}
+
+	// Exported must always be visible. Was issue 2824. 
+	func Exported() private
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/f.2.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/f.2.golden
new file mode 100644
index 0000000..8175901
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/f.2.golden
@@ -0,0 +1,13 @@
+// The package f is a go/doc test for functions and factory ...
+PACKAGE f
+
+IMPORTPATH
+	testdata/f
+
+FILENAMES
+	testdata/f.go
+
+FUNCTIONS
+	// Exported must always be visible. Was issue 2824. 
+	func Exported() private
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/f.go b/third_party/gofrontend/libgo/go/go/doc/testdata/f.go
new file mode 100644
index 0000000..7e9add9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/f.go
@@ -0,0 +1,14 @@
+// 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.
+
+// The package f is a go/doc test for functions and factory methods.
+package f
+
+// ----------------------------------------------------------------------------
+// Factory functions for non-exported types must not get lost.
+
+type private struct{}
+
+// Exported must always be visible. Was issue 2824.
+func Exported() private {}
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/template.txt b/third_party/gofrontend/libgo/go/go/doc/testdata/template.txt
new file mode 100644
index 0000000..1b07382
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/template.txt
@@ -0,0 +1,68 @@
+{{synopsis .Doc}}
+PACKAGE {{.Name}}
+
+IMPORTPATH
+	{{.ImportPath}}
+
+{{with .Imports}}IMPORTS
+{{range .}}	{{.}}
+{{end}}
+{{end}}{{/*
+
+*/}}FILENAMES
+{{range .Filenames}}	{{.}}
+{{end}}{{/*
+
+*/}}{{with .Consts}}
+CONSTANTS
+{{range .}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{end}}{{/*
+
+*/}}{{with .Vars}}
+VARIABLES
+{{range .}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{end}}{{/*
+
+*/}}{{with .Funcs}}
+FUNCTIONS
+{{range .}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{end}}{{/*
+
+*/}}{{with .Types}}
+TYPES
+{{range .}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{range .Consts}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{/*
+
+*/}}{{range .Vars}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{/*
+
+*/}}{{range .Funcs}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{/*
+
+*/}}{{range .Methods}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{end}}{{end}}{{/*
+
+*/}}{{with .Bugs}}
+BUGS .Bugs is now deprecated, please use .Notes instead
+{{range .}}{{indent "\t" .}}
+{{end}}{{end}}{{with .Notes}}{{range $marker, $content := .}}
+{{$marker}}S
+{{range $content}}{{$marker}}({{.UID}}){{indent "\t" .Body}}
+{{end}}{{end}}{{end}}
\ No newline at end of file
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/testing.0.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/testing.0.golden
new file mode 100644
index 0000000..f8348f1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/testing.0.golden
@@ -0,0 +1,156 @@
+// Package testing provides support for automated testing of Go ...
+PACKAGE testing
+
+IMPORTPATH
+	testdata/testing
+
+IMPORTS
+	bytes
+	flag
+	fmt
+	io
+	os
+	runtime
+	runtime/pprof
+	strconv
+	strings
+	time
+
+FILENAMES
+	testdata/benchmark.go
+	testdata/example.go
+	testdata/testing.go
+
+FUNCTIONS
+	// An internal function but exported because it is cross-package; ...
+	func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)
+
+	// An internal function but exported because it is cross-package; ...
+	func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)
+
+	// 
+	func RunExamples(examples []InternalExample) (ok bool)
+
+	// 
+	func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)
+
+	// Short reports whether the -test.short flag is set. 
+	func Short() bool
+
+
+TYPES
+	// B is a type passed to Benchmark functions to manage benchmark ...
+	type B struct {
+		N int
+		// contains filtered or unexported fields
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *B) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *B) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *B) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *B) FailNow()
+
+	// Failed reports whether the function has failed. 
+	func (c *B) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *B) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *B) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *B) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *B) Logf(format string, args ...interface{})
+
+	// ResetTimer sets the elapsed benchmark time to zero. It does not ...
+	func (b *B) ResetTimer()
+
+	// SetBytes records the number of bytes processed in a single ...
+	func (b *B) SetBytes(n int64)
+
+	// StartTimer starts timing a test.  This function is called ...
+	func (b *B) StartTimer()
+
+	// StopTimer stops timing a test.  This can be used to pause the ...
+	func (b *B) StopTimer()
+
+	// The results of a benchmark run. 
+	type BenchmarkResult struct {
+		N	int		// The number of iterations.
+		T	time.Duration	// The total time taken.
+		Bytes	int64		// Bytes processed in one iteration.
+	}
+
+	// Benchmark benchmarks a single function. Useful for creating ...
+	func Benchmark(f func(b *B)) BenchmarkResult
+
+	// 
+	func (r BenchmarkResult) NsPerOp() int64
+
+	// 
+	func (r BenchmarkResult) String() string
+
+	// An internal type but exported because it is cross-package; part ...
+	type InternalBenchmark struct {
+		Name	string
+		F	func(b *B)
+	}
+
+	// 
+	type InternalExample struct {
+		Name	string
+		F	func()
+		Output	string
+	}
+
+	// An internal type but exported because it is cross-package; part ...
+	type InternalTest struct {
+		Name	string
+		F	func(*T)
+	}
+
+	// T is a type passed to Test functions to manage test state and ...
+	type T struct {
+		// contains filtered or unexported fields
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *T) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *T) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *T) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *T) FailNow()
+
+	// Failed reports whether the function has failed. 
+	func (c *T) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *T) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *T) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *T) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *T) Logf(format string, args ...interface{})
+
+	// Parallel signals that this test is to be run in parallel with ...
+	func (t *T) Parallel()
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/testing.1.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/testing.1.golden
new file mode 100644
index 0000000..282bb10
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/testing.1.golden
@@ -0,0 +1,298 @@
+// Package testing provides support for automated testing of Go ...
+PACKAGE testing
+
+IMPORTPATH
+	testdata/testing
+
+IMPORTS
+	bytes
+	flag
+	fmt
+	io
+	os
+	runtime
+	runtime/pprof
+	strconv
+	strings
+	time
+
+FILENAMES
+	testdata/benchmark.go
+	testdata/example.go
+	testdata/testing.go
+
+VARIABLES
+	// 
+	var (
+		// The short flag requests that tests run more quickly, but its functionality
+		// is provided by test writers themselves.  The testing package is just its
+		// home.  The all.bash installation script sets it to make installation more
+		// efficient, but by default the flag is off so a plain "go test" will do a
+		// full test of the package.
+		short	= flag.Bool("test.short", false, "run smaller test suite to save time")
+	
+		// Report as tests are run; default is silent for success.
+		chatty		= flag.Bool("test.v", false, "verbose: print additional output")
+		match		= flag.String("test.run", "", "regular expression to select tests to run")
+		memProfile	= flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
+		memProfileRate	= flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
+		cpuProfile	= flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
+		timeout		= flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
+		cpuListStr	= flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+		parallel	= flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+	
+		cpuList	[]int
+	)
+
+	// 
+	var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
+
+	// 
+	var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
+
+	// 
+	var timer *time.Timer
+
+
+FUNCTIONS
+	// An internal function but exported because it is cross-package; ...
+	func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)
+
+	// An internal function but exported because it is cross-package; ...
+	func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)
+
+	// 
+	func RunExamples(examples []InternalExample) (ok bool)
+
+	// 
+	func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)
+
+	// Short reports whether the -test.short flag is set. 
+	func Short() bool
+
+	// after runs after all testing. 
+	func after()
+
+	// alarm is called if the timeout expires. 
+	func alarm()
+
+	// before runs before all testing. 
+	func before()
+
+	// decorate inserts the final newline if needed and indentation ...
+	func decorate(s string, addFileLine bool) string
+
+	// 
+	func max(x, y int) int
+
+	// 
+	func min(x, y int) int
+
+	// 
+	func parseCpuList()
+
+	// roundDown10 rounds a number down to the nearest power of 10. 
+	func roundDown10(n int) int
+
+	// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX]. 
+	func roundUp(n int) int
+
+	// startAlarm starts an alarm if requested. 
+	func startAlarm()
+
+	// stopAlarm turns off the alarm. 
+	func stopAlarm()
+
+	// 
+	func tRunner(t *T, test *InternalTest)
+
+
+TYPES
+	// B is a type passed to Benchmark functions to manage benchmark ...
+	type B struct {
+		common
+		N		int
+		benchmark	InternalBenchmark
+		bytes		int64
+		timerOn		bool
+		result		BenchmarkResult
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *B) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *B) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *B) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *B) FailNow()
+
+	// Failed reports whether the function has failed. 
+	func (c *B) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *B) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *B) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *B) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *B) Logf(format string, args ...interface{})
+
+	// ResetTimer sets the elapsed benchmark time to zero. It does not ...
+	func (b *B) ResetTimer()
+
+	// SetBytes records the number of bytes processed in a single ...
+	func (b *B) SetBytes(n int64)
+
+	// StartTimer starts timing a test.  This function is called ...
+	func (b *B) StartTimer()
+
+	// StopTimer stops timing a test.  This can be used to pause the ...
+	func (b *B) StopTimer()
+
+	// launch launches the benchmark function.  It gradually increases ...
+	func (b *B) launch()
+
+	// log generates the output. It's always at the same stack depth. 
+	func (c *B) log(s string)
+
+	// 
+	func (b *B) nsPerOp() int64
+
+	// run times the benchmark function in a separate goroutine. 
+	func (b *B) run() BenchmarkResult
+
+	// runN runs a single benchmark for the specified number of ...
+	func (b *B) runN(n int)
+
+	// trimOutput shortens the output from a benchmark, which can be ...
+	func (b *B) trimOutput()
+
+	// The results of a benchmark run. 
+	type BenchmarkResult struct {
+		N	int		// The number of iterations.
+		T	time.Duration	// The total time taken.
+		Bytes	int64		// Bytes processed in one iteration.
+	}
+
+	// Benchmark benchmarks a single function. Useful for creating ...
+	func Benchmark(f func(b *B)) BenchmarkResult
+
+	// 
+	func (r BenchmarkResult) NsPerOp() int64
+
+	// 
+	func (r BenchmarkResult) String() string
+
+	// 
+	func (r BenchmarkResult) mbPerSec() float64
+
+	// An internal type but exported because it is cross-package; part ...
+	type InternalBenchmark struct {
+		Name	string
+		F	func(b *B)
+	}
+
+	// 
+	type InternalExample struct {
+		Name	string
+		F	func()
+		Output	string
+	}
+
+	// An internal type but exported because it is cross-package; part ...
+	type InternalTest struct {
+		Name	string
+		F	func(*T)
+	}
+
+	// T is a type passed to Test functions to manage test state and ...
+	type T struct {
+		common
+		name		string		// Name of test.
+		startParallel	chan bool	// Parallel tests will wait on this.
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *T) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *T) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *T) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *T) FailNow()
+
+	// Failed reports whether the function has failed. 
+	func (c *T) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *T) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *T) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *T) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *T) Logf(format string, args ...interface{})
+
+	// Parallel signals that this test is to be run in parallel with ...
+	func (t *T) Parallel()
+
+	// log generates the output. It's always at the same stack depth. 
+	func (c *T) log(s string)
+
+	// 
+	func (t *T) report()
+
+	// common holds the elements common between T and B and captures ...
+	type common struct {
+		output		[]byte		// Output generated by test or benchmark.
+		failed		bool		// Test or benchmark has failed.
+		start		time.Time	// Time test or benchmark started
+		duration	time.Duration
+		self		interface{}		// To be sent on signal channel when done.
+		signal		chan interface{}	// Output for serial tests.
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *common) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *common) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *common) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *common) FailNow()
+
+	// Failed reports whether the function has failed. 
+	func (c *common) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *common) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *common) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *common) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *common) Logf(format string, args ...interface{})
+
+	// log generates the output. It's always at the same stack depth. 
+	func (c *common) log(s string)
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/testing.2.golden b/third_party/gofrontend/libgo/go/go/doc/testdata/testing.2.golden
new file mode 100644
index 0000000..f8348f1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/testing.2.golden
@@ -0,0 +1,156 @@
+// Package testing provides support for automated testing of Go ...
+PACKAGE testing
+
+IMPORTPATH
+	testdata/testing
+
+IMPORTS
+	bytes
+	flag
+	fmt
+	io
+	os
+	runtime
+	runtime/pprof
+	strconv
+	strings
+	time
+
+FILENAMES
+	testdata/benchmark.go
+	testdata/example.go
+	testdata/testing.go
+
+FUNCTIONS
+	// An internal function but exported because it is cross-package; ...
+	func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)
+
+	// An internal function but exported because it is cross-package; ...
+	func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)
+
+	// 
+	func RunExamples(examples []InternalExample) (ok bool)
+
+	// 
+	func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)
+
+	// Short reports whether the -test.short flag is set. 
+	func Short() bool
+
+
+TYPES
+	// B is a type passed to Benchmark functions to manage benchmark ...
+	type B struct {
+		N int
+		// contains filtered or unexported fields
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *B) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *B) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *B) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *B) FailNow()
+
+	// Failed reports whether the function has failed. 
+	func (c *B) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *B) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *B) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *B) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *B) Logf(format string, args ...interface{})
+
+	// ResetTimer sets the elapsed benchmark time to zero. It does not ...
+	func (b *B) ResetTimer()
+
+	// SetBytes records the number of bytes processed in a single ...
+	func (b *B) SetBytes(n int64)
+
+	// StartTimer starts timing a test.  This function is called ...
+	func (b *B) StartTimer()
+
+	// StopTimer stops timing a test.  This can be used to pause the ...
+	func (b *B) StopTimer()
+
+	// The results of a benchmark run. 
+	type BenchmarkResult struct {
+		N	int		// The number of iterations.
+		T	time.Duration	// The total time taken.
+		Bytes	int64		// Bytes processed in one iteration.
+	}
+
+	// Benchmark benchmarks a single function. Useful for creating ...
+	func Benchmark(f func(b *B)) BenchmarkResult
+
+	// 
+	func (r BenchmarkResult) NsPerOp() int64
+
+	// 
+	func (r BenchmarkResult) String() string
+
+	// An internal type but exported because it is cross-package; part ...
+	type InternalBenchmark struct {
+		Name	string
+		F	func(b *B)
+	}
+
+	// 
+	type InternalExample struct {
+		Name	string
+		F	func()
+		Output	string
+	}
+
+	// An internal type but exported because it is cross-package; part ...
+	type InternalTest struct {
+		Name	string
+		F	func(*T)
+	}
+
+	// T is a type passed to Test functions to manage test state and ...
+	type T struct {
+		// contains filtered or unexported fields
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *T) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *T) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *T) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *T) FailNow()
+
+	// Failed reports whether the function has failed. 
+	func (c *T) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *T) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *T) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *T) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *T) Logf(format string, args ...interface{})
+
+	// Parallel signals that this test is to be run in parallel with ...
+	func (t *T) Parallel()
+
diff --git a/third_party/gofrontend/libgo/go/go/doc/testdata/testing.go b/third_party/gofrontend/libgo/go/go/doc/testdata/testing.go
new file mode 100644
index 0000000..93ed494
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/doc/testdata/testing.go
@@ -0,0 +1,404 @@
+// 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 testing provides support for automated testing of Go packages.
+// It is intended to be used in concert with the ``go test'' utility, which automates
+// execution of any function of the form
+//     func TestXxx(*testing.T)
+// where Xxx can be any alphanumeric string (but the first letter must not be in
+// [a-z]) and serves to identify the test routine.
+// These TestXxx routines should be declared within the package they are testing.
+//
+// Functions of the form
+//     func BenchmarkXxx(*testing.B)
+// are considered benchmarks, and are executed by go test when the -test.bench
+// flag is provided.
+//
+// A sample benchmark function looks like this:
+//     func BenchmarkHello(b *testing.B) {
+//         for i := 0; i < b.N; i++ {
+//             fmt.Sprintf("hello")
+//         }
+//     }
+// The benchmark package will vary b.N until the benchmark function lasts
+// long enough to be timed reliably.  The output
+//     testing.BenchmarkHello    10000000    282 ns/op
+// means that the loop ran 10000000 times at a speed of 282 ns per loop.
+//
+// If a benchmark needs some expensive setup before running, the timer
+// may be stopped:
+//     func BenchmarkBigLen(b *testing.B) {
+//         b.StopTimer()
+//         big := NewBig()
+//         b.StartTimer()
+//         for i := 0; i < b.N; i++ {
+//             big.Len()
+//         }
+//     }
+package testing
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"runtime"
+	"runtime/pprof"
+	"strconv"
+	"strings"
+	"time"
+)
+
+var (
+	// The short flag requests that tests run more quickly, but its functionality
+	// is provided by test writers themselves.  The testing package is just its
+	// home.  The all.bash installation script sets it to make installation more
+	// efficient, but by default the flag is off so a plain "go test" will do a
+	// full test of the package.
+	short = flag.Bool("test.short", false, "run smaller test suite to save time")
+
+	// Report as tests are run; default is silent for success.
+	chatty         = flag.Bool("test.v", false, "verbose: print additional output")
+	match          = flag.String("test.run", "", "regular expression to select tests to run")
+	memProfile     = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
+	memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
+	cpuProfile     = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
+	timeout        = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
+	cpuListStr     = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+	parallel       = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+
+	cpuList []int
+)
+
+// common holds the elements common between T and B and
+// captures common methods such as Errorf.
+type common struct {
+	output   []byte    // Output generated by test or benchmark.
+	failed   bool      // Test or benchmark has failed.
+	start    time.Time // Time test or benchmark started
+	duration time.Duration
+	self     interface{}      // To be sent on signal channel when done.
+	signal   chan interface{} // Output for serial tests.
+}
+
+// Short reports whether the -test.short flag is set.
+func Short() bool {
+	return *short
+}
+
+// decorate inserts the final newline if needed and indentation tabs for formatting.
+// If addFileLine is true, it also prefixes the string with the file and line of the call site.
+func decorate(s string, addFileLine bool) string {
+	if addFileLine {
+		_, file, line, ok := runtime.Caller(3) // decorate + log + public function.
+		if ok {
+			// Truncate file name at last file name separator.
+			if index := strings.LastIndex(file, "/"); index >= 0 {
+				file = file[index+1:]
+			} else if index = strings.LastIndex(file, "\\"); index >= 0 {
+				file = file[index+1:]
+			}
+		} else {
+			file = "???"
+			line = 1
+		}
+		s = fmt.Sprintf("%s:%d: %s", file, line, s)
+	}
+	s = "\t" + s // Every line is indented at least one tab.
+	n := len(s)
+	if n > 0 && s[n-1] != '\n' {
+		s += "\n"
+		n++
+	}
+	for i := 0; i < n-1; i++ { // -1 to avoid final newline
+		if s[i] == '\n' {
+			// Second and subsequent lines are indented an extra tab.
+			return s[0:i+1] + "\t" + decorate(s[i+1:n], false)
+		}
+	}
+	return s
+}
+
+// T is a type passed to Test functions to manage test state and support formatted test logs.
+// Logs are accumulated during execution and dumped to standard error when done.
+type T struct {
+	common
+	name          string    // Name of test.
+	startParallel chan bool // Parallel tests will wait on this.
+}
+
+// Fail marks the function as having failed but continues execution.
+func (c *common) Fail() { c.failed = true }
+
+// Failed reports whether the function has failed.
+func (c *common) Failed() bool { return c.failed }
+
+// FailNow marks the function as having failed and stops its execution.
+// Execution will continue at the next Test.
+func (c *common) FailNow() {
+	c.Fail()
+
+	// Calling runtime.Goexit will exit the goroutine, which
+	// will run the deferred functions in this goroutine,
+	// which will eventually run the deferred lines in tRunner,
+	// which will signal to the test loop that this test is done.
+	//
+	// A previous version of this code said:
+	//
+	//	c.duration = ...
+	//	c.signal <- c.self
+	//	runtime.Goexit()
+	//
+	// This previous version duplicated code (those lines are in
+	// tRunner no matter what), but worse the goroutine teardown
+	// implicit in runtime.Goexit was not guaranteed to complete
+	// before the test exited.  If a test deferred an important cleanup
+	// function (like removing temporary files), there was no guarantee
+	// it would run on a test failure.  Because we send on c.signal during
+	// a top-of-stack deferred function now, we know that the send
+	// only happens after any other stacked defers have completed.
+	runtime.Goexit()
+}
+
+// log generates the output. It's always at the same stack depth.
+func (c *common) log(s string) {
+	c.output = append(c.output, decorate(s, true)...)
+}
+
+// Log formats its arguments using default formatting, analogous to Println(),
+// and records the text in the error log.
+func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
+
+// Logf formats its arguments according to the format, analogous to Printf(),
+// and records the text in the error log.
+func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
+
+// Error is equivalent to Log() followed by Fail().
+func (c *common) Error(args ...interface{}) {
+	c.log(fmt.Sprintln(args...))
+	c.Fail()
+}
+
+// Errorf is equivalent to Logf() followed by Fail().
+func (c *common) Errorf(format string, args ...interface{}) {
+	c.log(fmt.Sprintf(format, args...))
+	c.Fail()
+}
+
+// Fatal is equivalent to Log() followed by FailNow().
+func (c *common) Fatal(args ...interface{}) {
+	c.log(fmt.Sprintln(args...))
+	c.FailNow()
+}
+
+// Fatalf is equivalent to Logf() followed by FailNow().
+func (c *common) Fatalf(format string, args ...interface{}) {
+	c.log(fmt.Sprintf(format, args...))
+	c.FailNow()
+}
+
+// Parallel signals that this test is to be run in parallel with (and only with)
+// other parallel tests in this CPU group.
+func (t *T) Parallel() {
+	t.signal <- (*T)(nil) // Release main testing loop
+	<-t.startParallel     // Wait for serial tests to finish
+}
+
+// An internal type but exported because it is cross-package; part of the implementation
+// of go test.
+type InternalTest struct {
+	Name string
+	F    func(*T)
+}
+
+func tRunner(t *T, test *InternalTest) {
+	t.start = time.Now()
+
+	// When this goroutine is done, either because test.F(t)
+	// returned normally or because a test failure triggered
+	// a call to runtime.Goexit, record the duration and send
+	// a signal saying that the test is done.
+	defer func() {
+		t.duration = time.Now().Sub(t.start)
+		t.signal <- t
+	}()
+
+	test.F(t)
+}
+
+// An internal function but exported because it is cross-package; part of the implementation
+// of go test.
+func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
+	flag.Parse()
+	parseCpuList()
+
+	before()
+	startAlarm()
+	testOk := RunTests(matchString, tests)
+	exampleOk := RunExamples(examples)
+	if !testOk || !exampleOk {
+		fmt.Println("FAIL")
+		os.Exit(1)
+	}
+	fmt.Println("PASS")
+	stopAlarm()
+	RunBenchmarks(matchString, benchmarks)
+	after()
+}
+
+func (t *T) report() {
+	tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
+	format := "--- %s: %s %s\n%s"
+	if t.failed {
+		fmt.Printf(format, "FAIL", t.name, tstr, t.output)
+	} else if *chatty {
+		fmt.Printf(format, "PASS", t.name, tstr, t.output)
+	}
+}
+
+func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
+	ok = true
+	if len(tests) == 0 {
+		fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
+		return
+	}
+	for _, procs := range cpuList {
+		runtime.GOMAXPROCS(procs)
+		// We build a new channel tree for each run of the loop.
+		// collector merges in one channel all the upstream signals from parallel tests.
+		// If all tests pump to the same channel, a bug can occur where a test
+		// kicks off a goroutine that Fails, yet the test still delivers a completion signal,
+		// which skews the counting.
+		var collector = make(chan interface{})
+
+		numParallel := 0
+		startParallel := make(chan bool)
+
+		for i := 0; i < len(tests); i++ {
+			matched, err := matchString(*match, tests[i].Name)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err)
+				os.Exit(1)
+			}
+			if !matched {
+				continue
+			}
+			testName := tests[i].Name
+			if procs != 1 {
+				testName = fmt.Sprintf("%s-%d", tests[i].Name, procs)
+			}
+			t := &T{
+				common: common{
+					signal: make(chan interface{}),
+				},
+				name:          testName,
+				startParallel: startParallel,
+			}
+			t.self = t
+			if *chatty {
+				fmt.Printf("=== RUN %s\n", t.name)
+			}
+			go tRunner(t, &tests[i])
+			out := (<-t.signal).(*T)
+			if out == nil { // Parallel run.
+				go func() {
+					collector <- <-t.signal
+				}()
+				numParallel++
+				continue
+			}
+			t.report()
+			ok = ok && !out.failed
+		}
+
+		running := 0
+		for numParallel+running > 0 {
+			if running < *parallel && numParallel > 0 {
+				startParallel <- true
+				running++
+				numParallel--
+				continue
+			}
+			t := (<-collector).(*T)
+			t.report()
+			ok = ok && !t.failed
+			running--
+		}
+	}
+	return
+}
+
+// before runs before all testing.
+func before() {
+	if *memProfileRate > 0 {
+		runtime.MemProfileRate = *memProfileRate
+	}
+	if *cpuProfile != "" {
+		f, err := os.Create(*cpuProfile)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: %s", err)
+			return
+		}
+		if err := pprof.StartCPUProfile(f); err != nil {
+			fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s", err)
+			f.Close()
+			return
+		}
+		// Could save f so after can call f.Close; not worth the effort.
+	}
+
+}
+
+// after runs after all testing.
+func after() {
+	if *cpuProfile != "" {
+		pprof.StopCPUProfile() // flushes profile to disk
+	}
+	if *memProfile != "" {
+		f, err := os.Create(*memProfile)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: %s", err)
+			return
+		}
+		if err = pprof.WriteHeapProfile(f); err != nil {
+			fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *memProfile, err)
+		}
+		f.Close()
+	}
+}
+
+var timer *time.Timer
+
+// startAlarm starts an alarm if requested.
+func startAlarm() {
+	if *timeout > 0 {
+		timer = time.AfterFunc(*timeout, alarm)
+	}
+}
+
+// stopAlarm turns off the alarm.
+func stopAlarm() {
+	if *timeout > 0 {
+		timer.Stop()
+	}
+}
+
+// alarm is called if the timeout expires.
+func alarm() {
+	panic("test timed out")
+}
+
+func parseCpuList() {
+	if len(*cpuListStr) == 0 {
+		cpuList = append(cpuList, runtime.GOMAXPROCS(-1))
+	} else {
+		for _, val := range strings.Split(*cpuListStr, ",") {
+			cpu, err := strconv.Atoi(val)
+			if err != nil || cpu <= 0 {
+				fmt.Fprintf(os.Stderr, "testing: invalid value %q for -test.cpu", val)
+				os.Exit(1)
+			}
+			cpuList = append(cpuList, cpu)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/format/format.go b/third_party/gofrontend/libgo/go/go/format/format.go
new file mode 100644
index 0000000..3d00a64
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/format/format.go
@@ -0,0 +1,199 @@
+// 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 format implements standard formatting of Go source.
+package format
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"io"
+	"strings"
+)
+
+var config = printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 8}
+
+// Node formats node in canonical gofmt style and writes the result to dst.
+//
+// The node type must be *ast.File, *printer.CommentedNode, []ast.Decl,
+// []ast.Stmt, or assignment-compatible to ast.Expr, ast.Decl, ast.Spec,
+// or ast.Stmt. Node does not modify node. Imports are not sorted for
+// nodes representing partial source files (i.e., if the node is not an
+// *ast.File or a *printer.CommentedNode not wrapping an *ast.File).
+//
+// The function may return early (before the entire result is written)
+// and return a formatting error, for instance due to an incorrect AST.
+//
+func Node(dst io.Writer, fset *token.FileSet, node interface{}) error {
+	// Determine if we have a complete source file (file != nil).
+	var file *ast.File
+	var cnode *printer.CommentedNode
+	switch n := node.(type) {
+	case *ast.File:
+		file = n
+	case *printer.CommentedNode:
+		if f, ok := n.Node.(*ast.File); ok {
+			file = f
+			cnode = n
+		}
+	}
+
+	// Sort imports if necessary.
+	if file != nil && hasUnsortedImports(file) {
+		// Make a copy of the AST because ast.SortImports is destructive.
+		// TODO(gri) Do this more efficiently.
+		var buf bytes.Buffer
+		err := config.Fprint(&buf, fset, file)
+		if err != nil {
+			return err
+		}
+		file, err = parser.ParseFile(fset, "", buf.Bytes(), parser.ParseComments)
+		if err != nil {
+			// We should never get here. If we do, provide good diagnostic.
+			return fmt.Errorf("format.Node internal error (%s)", err)
+		}
+		ast.SortImports(fset, file)
+
+		// Use new file with sorted imports.
+		node = file
+		if cnode != nil {
+			node = &printer.CommentedNode{Node: file, Comments: cnode.Comments}
+		}
+	}
+
+	return config.Fprint(dst, fset, node)
+}
+
+// Source formats src in canonical gofmt style and returns the result
+// or an (I/O or syntax) error. src is expected to be a syntactically
+// correct Go source file, or a list of Go declarations or statements.
+//
+// If src is a partial source file, the leading and trailing space of src
+// is applied to the result (such that it has the same leading and trailing
+// space as src), and the result is indented by the same amount as the first
+// line of src containing code. Imports are not sorted for partial source files.
+//
+func Source(src []byte) ([]byte, error) {
+	fset := token.NewFileSet()
+	node, err := parse(fset, src)
+	if err != nil {
+		return nil, err
+	}
+
+	var buf bytes.Buffer
+	if file, ok := node.(*ast.File); ok {
+		// Complete source file.
+		ast.SortImports(fset, file)
+		err := config.Fprint(&buf, fset, file)
+		if err != nil {
+			return nil, err
+		}
+
+	} else {
+		// Partial source file.
+		// Determine and prepend leading space.
+		i, j := 0, 0
+		for j < len(src) && isSpace(src[j]) {
+			if src[j] == '\n' {
+				i = j + 1 // index of last line in leading space
+			}
+			j++
+		}
+		buf.Write(src[:i])
+
+		// Determine indentation of first code line.
+		// Spaces are ignored unless there are no tabs,
+		// in which case spaces count as one tab.
+		indent := 0
+		hasSpace := false
+		for _, b := range src[i:j] {
+			switch b {
+			case ' ':
+				hasSpace = true
+			case '\t':
+				indent++
+			}
+		}
+		if indent == 0 && hasSpace {
+			indent = 1
+		}
+
+		// Format the source.
+		cfg := config
+		cfg.Indent = indent
+		err := cfg.Fprint(&buf, fset, node)
+		if err != nil {
+			return nil, err
+		}
+
+		// Determine and append trailing space.
+		i = len(src)
+		for i > 0 && isSpace(src[i-1]) {
+			i--
+		}
+		buf.Write(src[i:])
+	}
+
+	return buf.Bytes(), nil
+}
+
+func hasUnsortedImports(file *ast.File) bool {
+	for _, d := range file.Decls {
+		d, ok := d.(*ast.GenDecl)
+		if !ok || d.Tok != token.IMPORT {
+			// Not an import declaration, so we're done.
+			// Imports are always first.
+			return false
+		}
+		if d.Lparen.IsValid() {
+			// For now assume all grouped imports are unsorted.
+			// TODO(gri) Should check if they are sorted already.
+			return true
+		}
+		// Ungrouped imports are sorted by default.
+	}
+	return false
+}
+
+func isSpace(b byte) bool {
+	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
+}
+
+func parse(fset *token.FileSet, src []byte) (interface{}, error) {
+	// Try as a complete source file.
+	file, err := parser.ParseFile(fset, "", src, parser.ParseComments)
+	if err == nil {
+		return file, nil
+	}
+	// If the source is missing a package clause, try as a source fragment; otherwise fail.
+	if !strings.Contains(err.Error(), "expected 'package'") {
+		return nil, err
+	}
+
+	// Try as a declaration list by prepending a package clause in front of src.
+	// Use ';' not '\n' to keep line numbers intact.
+	psrc := append([]byte("package p;"), src...)
+	file, err = parser.ParseFile(fset, "", psrc, parser.ParseComments)
+	if err == nil {
+		return file.Decls, nil
+	}
+	// If the source is missing a declaration, try as a statement list; otherwise fail.
+	if !strings.Contains(err.Error(), "expected declaration") {
+		return nil, err
+	}
+
+	// Try as statement list by wrapping a function around src.
+	fsrc := append(append([]byte("package p; func _() {"), src...), '}')
+	file, err = parser.ParseFile(fset, "", fsrc, parser.ParseComments)
+	if err == nil {
+		return file.Decls[0].(*ast.FuncDecl).Body.List, nil
+	}
+
+	// Failed, and out of options.
+	return nil, err
+}
diff --git a/third_party/gofrontend/libgo/go/go/format/format_test.go b/third_party/gofrontend/libgo/go/go/format/format_test.go
new file mode 100644
index 0000000..93f0992
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/format/format_test.go
@@ -0,0 +1,124 @@
+// 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 format
+
+import (
+	"bytes"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+const testfile = "format_test.go"
+
+func diff(t *testing.T, dst, src []byte) {
+	line := 1
+	offs := 0 // line offset
+	for i := 0; i < len(dst) && i < len(src); i++ {
+		d := dst[i]
+		s := src[i]
+		if d != s {
+			t.Errorf("dst:%d: %s\n", line, dst[offs:i+1])
+			t.Errorf("src:%d: %s\n", line, src[offs:i+1])
+			return
+		}
+		if s == '\n' {
+			line++
+			offs = i + 1
+		}
+	}
+	if len(dst) != len(src) {
+		t.Errorf("len(dst) = %d, len(src) = %d\nsrc = %q", len(dst), len(src), src)
+	}
+}
+
+func TestNode(t *testing.T) {
+	src, err := ioutil.ReadFile(testfile)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	fset := token.NewFileSet()
+	file, err := parser.ParseFile(fset, testfile, src, parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var buf bytes.Buffer
+
+	if err = Node(&buf, fset, file); err != nil {
+		t.Fatal("Node failed:", err)
+	}
+
+	diff(t, buf.Bytes(), src)
+}
+
+func TestSource(t *testing.T) {
+	src, err := ioutil.ReadFile(testfile)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	res, err := Source(src)
+	if err != nil {
+		t.Fatal("Source failed:", err)
+	}
+
+	diff(t, res, src)
+}
+
+// Test cases that are expected to fail are marked by the prefix "ERROR".
+var tests = []string{
+	// declaration lists
+	`import "go/format"`,
+	"var x int",
+	"var x int\n\ntype T struct{}",
+
+	// statement lists
+	"x := 0",
+	"f(a, b, c)\nvar x int = f(1, 2, 3)",
+
+	// indentation, leading and trailing space
+	"\tx := 0\n\tgo f()",
+	"\tx := 0\n\tgo f()\n\n\n",
+	"\n\t\t\n\n\tx := 0\n\tgo f()\n\n\n",
+	"\n\t\t\n\n\t\t\tx := 0\n\t\t\tgo f()\n\n\n",
+	"\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\nfoo\n`\n\n\n", // no indentation inside raw strings
+
+	// erroneous programs
+	"ERROR1 + 2 +",
+	"ERRORx :=  0",
+}
+
+func String(s string) (string, error) {
+	res, err := Source([]byte(s))
+	if err != nil {
+		return "", err
+	}
+	return string(res), nil
+}
+
+func TestPartial(t *testing.T) {
+	for _, src := range tests {
+		if strings.HasPrefix(src, "ERROR") {
+			// test expected to fail
+			src = src[5:] // remove ERROR prefix
+			res, err := String(src)
+			if err == nil && res == src {
+				t.Errorf("formatting succeeded but was expected to fail:\n%q", src)
+			}
+		} else {
+			// test expected to succeed
+			res, err := String(src)
+			if err != nil {
+				t.Errorf("formatting failed (%s):\n%q", err, src)
+			} else if res != src {
+				t.Errorf("formatting incorrect:\nsource: %q\nresult: %q", src, res)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/parser/error_test.go b/third_party/gofrontend/libgo/go/go/parser/error_test.go
new file mode 100644
index 0000000..8506077
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/parser/error_test.go
@@ -0,0 +1,183 @@
+// 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.
+
+// This file implements a parser test harness. The files in the testdata
+// directory are parsed and the errors reported are compared against the
+// error messages expected in the test files. The test files must end in
+// .src rather than .go so that they are not disturbed by gofmt runs.
+//
+// Expected errors are indicated in the test files by putting a comment
+// of the form /* ERROR "rx" */ immediately following an offending token.
+// The harness will verify that an error matching the regular expression
+// rx is reported at that source position.
+//
+// For instance, the following test file indicates that a "not declared"
+// error should be reported for the undeclared variable x:
+//
+//	package p
+//	func f() {
+//		_ = x /* ERROR "not declared" */ + 1
+//	}
+
+package parser
+
+import (
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"path/filepath"
+	"regexp"
+	"strings"
+	"testing"
+)
+
+const testdata = "testdata"
+
+var fsetErrs *token.FileSet
+
+// getFile assumes that each filename occurs at most once
+func getFile(filename string) (file *token.File) {
+	fsetErrs.Iterate(func(f *token.File) bool {
+		if f.Name() == filename {
+			if file != nil {
+				panic(filename + " used multiple times")
+			}
+			file = f
+		}
+		return true
+	})
+	return file
+}
+
+func getPos(filename string, offset int) token.Pos {
+	if f := getFile(filename); f != nil {
+		return f.Pos(offset)
+	}
+	return token.NoPos
+}
+
+// ERROR comments must be of the form /* ERROR "rx" */ and rx is
+// a regular expression that matches the expected error message.
+// The special form /* ERROR HERE "rx" */ must be used for error
+// messages that appear immediately after a token, rather than at
+// a token's position.
+//
+var errRx = regexp.MustCompile(`^/\* *ERROR *(HERE)? *"([^"]*)" *\*/$`)
+
+// expectedErrors collects the regular expressions of ERROR comments found
+// in files and returns them as a map of error positions to error messages.
+//
+func expectedErrors(t *testing.T, filename string, src []byte) map[token.Pos]string {
+	errors := make(map[token.Pos]string)
+
+	var s scanner.Scanner
+	// file was parsed already - do not add it again to the file
+	// set otherwise the position information returned here will
+	// not match the position information collected by the parser
+	s.Init(getFile(filename), src, nil, scanner.ScanComments)
+	var prev token.Pos // position of last non-comment, non-semicolon token
+	var here token.Pos // position immediately after the token at position prev
+
+	for {
+		pos, tok, lit := s.Scan()
+		switch tok {
+		case token.EOF:
+			return errors
+		case token.COMMENT:
+			s := errRx.FindStringSubmatch(lit)
+			if len(s) == 3 {
+				pos := prev
+				if s[1] == "HERE" {
+					pos = here
+				}
+				errors[pos] = string(s[2])
+			}
+		default:
+			prev = pos
+			var l int // token length
+			if tok.IsLiteral() {
+				l = len(lit)
+			} else {
+				l = len(tok.String())
+			}
+			here = prev + token.Pos(l)
+		}
+	}
+}
+
+// compareErrors compares the map of expected error messages with the list
+// of found errors and reports discrepancies.
+//
+func compareErrors(t *testing.T, expected map[token.Pos]string, found scanner.ErrorList) {
+	for _, error := range found {
+		// error.Pos is a token.Position, but we want
+		// a token.Pos so we can do a map lookup
+		pos := getPos(error.Pos.Filename, error.Pos.Offset)
+		if msg, found := expected[pos]; found {
+			// we expect a message at pos; check if it matches
+			rx, err := regexp.Compile(msg)
+			if err != nil {
+				t.Errorf("%s: %v", error.Pos, err)
+				continue
+			}
+			if match := rx.MatchString(error.Msg); !match {
+				t.Errorf("%s: %q does not match %q", error.Pos, error.Msg, msg)
+				continue
+			}
+			// we have a match - eliminate this error
+			delete(expected, pos)
+		} else {
+			// To keep in mind when analyzing failed test output:
+			// If the same error position occurs multiple times in errors,
+			// this message will be triggered (because the first error at
+			// the position removes this position from the expected errors).
+			t.Errorf("%s: unexpected error: %s", error.Pos, error.Msg)
+		}
+	}
+
+	// there should be no expected errors left
+	if len(expected) > 0 {
+		t.Errorf("%d errors not reported:", len(expected))
+		for pos, msg := range expected {
+			t.Errorf("%s: %s\n", fsetErrs.Position(pos), msg)
+		}
+	}
+}
+
+func checkErrors(t *testing.T, filename string, input interface{}) {
+	src, err := readSource(filename, input)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	_, err = ParseFile(fsetErrs, filename, src, DeclarationErrors|AllErrors)
+	found, ok := err.(scanner.ErrorList)
+	if err != nil && !ok {
+		t.Error(err)
+		return
+	}
+	found.RemoveMultiples()
+
+	// we are expecting the following errors
+	// (collect these after parsing a file so that it is found in the file set)
+	expected := expectedErrors(t, filename, src)
+
+	// verify errors returned by the parser
+	compareErrors(t, expected, found)
+}
+
+func TestErrors(t *testing.T) {
+	fsetErrs = token.NewFileSet()
+	list, err := ioutil.ReadDir(testdata)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, fi := range list {
+		name := fi.Name()
+		if !fi.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".src") {
+			checkErrors(t, filepath.Join(testdata, name), nil)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/parser/interface.go b/third_party/gofrontend/libgo/go/go/parser/interface.go
new file mode 100644
index 0000000..57da4dd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/parser/interface.go
@@ -0,0 +1,198 @@
+// 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.
+
+// This file contains the exported entry points for invoking the parser.
+
+package parser
+
+import (
+	"bytes"
+	"errors"
+	"go/ast"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+// If src != nil, readSource converts src to a []byte if possible;
+// otherwise it returns an error. If src == nil, readSource returns
+// the result of reading the file specified by filename.
+//
+func readSource(filename string, src interface{}) ([]byte, error) {
+	if src != nil {
+		switch s := src.(type) {
+		case string:
+			return []byte(s), nil
+		case []byte:
+			return s, nil
+		case *bytes.Buffer:
+			// is io.Reader, but src is already available in []byte form
+			if s != nil {
+				return s.Bytes(), nil
+			}
+		case io.Reader:
+			var buf bytes.Buffer
+			if _, err := io.Copy(&buf, s); err != nil {
+				return nil, err
+			}
+			return buf.Bytes(), nil
+		}
+		return nil, errors.New("invalid source")
+	}
+	return ioutil.ReadFile(filename)
+}
+
+// A Mode value is a set of flags (or 0).
+// They control the amount of source code parsed and other optional
+// parser functionality.
+//
+type Mode uint
+
+const (
+	PackageClauseOnly Mode             = 1 << iota // stop parsing after package clause
+	ImportsOnly                                    // stop parsing after import declarations
+	ParseComments                                  // parse comments and add them to AST
+	Trace                                          // print a trace of parsed productions
+	DeclarationErrors                              // report declaration errors
+	SpuriousErrors                                 // same as AllErrors, for backward-compatibility
+	AllErrors         = SpuriousErrors             // report all errors (not just the first 10 on different lines)
+)
+
+// ParseFile parses the source code of a single Go source file and returns
+// the corresponding ast.File node. The source code may be provided via
+// the filename of the source file, or via the src parameter.
+//
+// If src != nil, ParseFile parses the source from src and the filename is
+// only used when recording position information. The type of the argument
+// for the src parameter must be string, []byte, or io.Reader.
+// If src == nil, ParseFile parses the file specified by filename.
+//
+// The mode parameter controls the amount of source text parsed and other
+// optional parser functionality. Position information is recorded in the
+// file set fset.
+//
+// If the source couldn't be read, the returned AST is nil and the error
+// indicates the specific failure. If the source was read but syntax
+// errors were found, the result is a partial AST (with ast.Bad* nodes
+// representing the fragments of erroneous source code). Multiple errors
+// are returned via a scanner.ErrorList which is sorted by file position.
+//
+func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (f *ast.File, err error) {
+	// get source
+	text, err := readSource(filename, src)
+	if err != nil {
+		return nil, err
+	}
+
+	var p parser
+	defer func() {
+		if e := recover(); e != nil {
+			_ = e.(bailout) // re-panics if it's not a bailout
+		}
+
+		// set result values
+		if f == nil {
+			// source is not a valid Go source file - satisfy
+			// ParseFile API and return a valid (but) empty
+			// *ast.File
+			f = &ast.File{
+				Name:  new(ast.Ident),
+				Scope: ast.NewScope(nil),
+			}
+		}
+
+		p.errors.Sort()
+		err = p.errors.Err()
+	}()
+
+	// parse source
+	p.init(fset, filename, text, mode)
+	f = p.parseFile()
+
+	return
+}
+
+// ParseDir calls ParseFile for all files with names ending in ".go" in the
+// directory specified by path and returns a map of package name -> package
+// AST with all the packages found.
+//
+// If filter != nil, only the files with os.FileInfo entries passing through
+// the filter (and ending in ".go") are considered. The mode bits are passed
+// to ParseFile unchanged. Position information is recorded in fset.
+//
+// If the directory couldn't be read, a nil map and the respective error are
+// returned. If a parse error occurred, a non-nil but incomplete map and the
+// first error encountered are returned.
+//
+func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error) {
+	fd, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer fd.Close()
+
+	list, err := fd.Readdir(-1)
+	if err != nil {
+		return nil, err
+	}
+
+	pkgs = make(map[string]*ast.Package)
+	for _, d := range list {
+		if strings.HasSuffix(d.Name(), ".go") && (filter == nil || filter(d)) {
+			filename := filepath.Join(path, d.Name())
+			if src, err := ParseFile(fset, filename, nil, mode); err == nil {
+				name := src.Name.Name
+				pkg, found := pkgs[name]
+				if !found {
+					pkg = &ast.Package{
+						Name:  name,
+						Files: make(map[string]*ast.File),
+					}
+					pkgs[name] = pkg
+				}
+				pkg.Files[filename] = src
+			} else if first == nil {
+				first = err
+			}
+		}
+	}
+
+	return
+}
+
+// ParseExpr is a convenience function for obtaining the AST of an expression x.
+// The position information recorded in the AST is undefined. The filename used
+// in error messages is the empty string.
+//
+func ParseExpr(x string) (ast.Expr, error) {
+	var p parser
+	p.init(token.NewFileSet(), "", []byte(x), 0)
+
+	// Set up pkg-level scopes to avoid nil-pointer errors.
+	// This is not needed for a correct expression x as the
+	// parser will be ok with a nil topScope, but be cautious
+	// in case of an erroneous x.
+	p.openScope()
+	p.pkgScope = p.topScope
+	e := p.parseRhsOrType()
+	p.closeScope()
+	assert(p.topScope == nil, "unbalanced scopes")
+
+	// If a semicolon was inserted, consume it;
+	// report an error if there's more tokens.
+	if p.tok == token.SEMICOLON {
+		p.next()
+	}
+	p.expect(token.EOF)
+
+	if p.errors.Len() > 0 {
+		p.errors.Sort()
+		return nil, p.errors.Err()
+	}
+
+	return e, nil
+}
diff --git a/third_party/gofrontend/libgo/go/go/parser/parser.go b/third_party/gofrontend/libgo/go/go/parser/parser.go
new file mode 100644
index 0000000..00dd532
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/parser/parser.go
@@ -0,0 +1,2478 @@
+// 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 parser implements a parser for Go source files. Input may be
+// provided in a variety of forms (see the various Parse* functions); the
+// output is an abstract syntax tree (AST) representing the Go source. The
+// parser is invoked through one of the Parse* functions.
+//
+package parser
+
+import (
+	"fmt"
+	"go/ast"
+	"go/scanner"
+	"go/token"
+	"strconv"
+	"strings"
+	"unicode"
+)
+
+// The parser structure holds the parser's internal state.
+type parser struct {
+	file    *token.File
+	errors  scanner.ErrorList
+	scanner scanner.Scanner
+
+	// Tracing/debugging
+	mode   Mode // parsing mode
+	trace  bool // == (mode & Trace != 0)
+	indent int  // indentation used for tracing output
+
+	// Comments
+	comments    []*ast.CommentGroup
+	leadComment *ast.CommentGroup // last lead comment
+	lineComment *ast.CommentGroup // last line comment
+
+	// Next token
+	pos token.Pos   // token position
+	tok token.Token // one token look-ahead
+	lit string      // token literal
+
+	// Error recovery
+	// (used to limit the number of calls to syncXXX functions
+	// w/o making scanning progress - avoids potential endless
+	// loops across multiple parser functions during error recovery)
+	syncPos token.Pos // last synchronization position
+	syncCnt int       // number of calls to syncXXX without progress
+
+	// Non-syntactic parser control
+	exprLev int  // < 0: in control clause, >= 0: in expression
+	inRhs   bool // if set, the parser is parsing a rhs expression
+
+	// Ordinary identifier scopes
+	pkgScope   *ast.Scope        // pkgScope.Outer == nil
+	topScope   *ast.Scope        // top-most scope; may be pkgScope
+	unresolved []*ast.Ident      // unresolved identifiers
+	imports    []*ast.ImportSpec // list of imports
+
+	// Label scopes
+	// (maintained by open/close LabelScope)
+	labelScope  *ast.Scope     // label scope for current function
+	targetStack [][]*ast.Ident // stack of unresolved labels
+}
+
+func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) {
+	p.file = fset.AddFile(filename, -1, len(src))
+	var m scanner.Mode
+	if mode&ParseComments != 0 {
+		m = scanner.ScanComments
+	}
+	eh := func(pos token.Position, msg string) { p.errors.Add(pos, msg) }
+	p.scanner.Init(p.file, src, eh, m)
+
+	p.mode = mode
+	p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
+
+	p.next()
+}
+
+// ----------------------------------------------------------------------------
+// Scoping support
+
+func (p *parser) openScope() {
+	p.topScope = ast.NewScope(p.topScope)
+}
+
+func (p *parser) closeScope() {
+	p.topScope = p.topScope.Outer
+}
+
+func (p *parser) openLabelScope() {
+	p.labelScope = ast.NewScope(p.labelScope)
+	p.targetStack = append(p.targetStack, nil)
+}
+
+func (p *parser) closeLabelScope() {
+	// resolve labels
+	n := len(p.targetStack) - 1
+	scope := p.labelScope
+	for _, ident := range p.targetStack[n] {
+		ident.Obj = scope.Lookup(ident.Name)
+		if ident.Obj == nil && p.mode&DeclarationErrors != 0 {
+			p.error(ident.Pos(), fmt.Sprintf("label %s undefined", ident.Name))
+		}
+	}
+	// pop label scope
+	p.targetStack = p.targetStack[0:n]
+	p.labelScope = p.labelScope.Outer
+}
+
+func (p *parser) declare(decl, data interface{}, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) {
+	for _, ident := range idents {
+		assert(ident.Obj == nil, "identifier already declared or resolved")
+		obj := ast.NewObj(kind, ident.Name)
+		// remember the corresponding declaration for redeclaration
+		// errors and global variable resolution/typechecking phase
+		obj.Decl = decl
+		obj.Data = data
+		ident.Obj = obj
+		if ident.Name != "_" {
+			if alt := scope.Insert(obj); alt != nil && p.mode&DeclarationErrors != 0 {
+				prevDecl := ""
+				if pos := alt.Pos(); pos.IsValid() {
+					prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", p.file.Position(pos))
+				}
+				p.error(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
+			}
+		}
+	}
+}
+
+func (p *parser) shortVarDecl(decl *ast.AssignStmt, list []ast.Expr) {
+	// Go spec: A short variable declaration may redeclare variables
+	// provided they were originally declared in the same block with
+	// the same type, and at least one of the non-blank variables is new.
+	n := 0 // number of new variables
+	for _, x := range list {
+		if ident, isIdent := x.(*ast.Ident); isIdent {
+			assert(ident.Obj == nil, "identifier already declared or resolved")
+			obj := ast.NewObj(ast.Var, ident.Name)
+			// remember corresponding assignment for other tools
+			obj.Decl = decl
+			ident.Obj = obj
+			if ident.Name != "_" {
+				if alt := p.topScope.Insert(obj); alt != nil {
+					ident.Obj = alt // redeclaration
+				} else {
+					n++ // new declaration
+				}
+			}
+		} else {
+			p.errorExpected(x.Pos(), "identifier on left side of :=")
+		}
+	}
+	if n == 0 && p.mode&DeclarationErrors != 0 {
+		p.error(list[0].Pos(), "no new variables on left side of :=")
+	}
+}
+
+// The unresolved object is a sentinel to mark identifiers that have been added
+// to the list of unresolved identifiers. The sentinel is only used for verifying
+// internal consistency.
+var unresolved = new(ast.Object)
+
+// If x is an identifier, tryResolve attempts to resolve x by looking up
+// the object it denotes. If no object is found and collectUnresolved is
+// set, x is marked as unresolved and collected in the list of unresolved
+// identifiers.
+//
+func (p *parser) tryResolve(x ast.Expr, collectUnresolved bool) {
+	// nothing to do if x is not an identifier or the blank identifier
+	ident, _ := x.(*ast.Ident)
+	if ident == nil {
+		return
+	}
+	assert(ident.Obj == nil, "identifier already declared or resolved")
+	if ident.Name == "_" {
+		return
+	}
+	// try to resolve the identifier
+	for s := p.topScope; s != nil; s = s.Outer {
+		if obj := s.Lookup(ident.Name); obj != nil {
+			ident.Obj = obj
+			return
+		}
+	}
+	// all local scopes are known, so any unresolved identifier
+	// must be found either in the file scope, package scope
+	// (perhaps in another file), or universe scope --- collect
+	// them so that they can be resolved later
+	if collectUnresolved {
+		ident.Obj = unresolved
+		p.unresolved = append(p.unresolved, ident)
+	}
+}
+
+func (p *parser) resolve(x ast.Expr) {
+	p.tryResolve(x, true)
+}
+
+// ----------------------------------------------------------------------------
+// Parsing support
+
+func (p *parser) printTrace(a ...interface{}) {
+	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
+	const n = len(dots)
+	pos := p.file.Position(p.pos)
+	fmt.Printf("%5d:%3d: ", pos.Line, pos.Column)
+	i := 2 * p.indent
+	for i > n {
+		fmt.Print(dots)
+		i -= n
+	}
+	// i <= n
+	fmt.Print(dots[0:i])
+	fmt.Println(a...)
+}
+
+func trace(p *parser, msg string) *parser {
+	p.printTrace(msg, "(")
+	p.indent++
+	return p
+}
+
+// Usage pattern: defer un(trace(p, "..."))
+func un(p *parser) {
+	p.indent--
+	p.printTrace(")")
+}
+
+// Advance to the next token.
+func (p *parser) next0() {
+	// Because of one-token look-ahead, print the previous token
+	// when tracing as it provides a more readable output. The
+	// very first token (!p.pos.IsValid()) is not initialized
+	// (it is token.ILLEGAL), so don't print it .
+	if p.trace && p.pos.IsValid() {
+		s := p.tok.String()
+		switch {
+		case p.tok.IsLiteral():
+			p.printTrace(s, p.lit)
+		case p.tok.IsOperator(), p.tok.IsKeyword():
+			p.printTrace("\"" + s + "\"")
+		default:
+			p.printTrace(s)
+		}
+	}
+
+	p.pos, p.tok, p.lit = p.scanner.Scan()
+}
+
+// Consume a comment and return it and the line on which it ends.
+func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
+	// /*-style comments may end on a different line than where they start.
+	// Scan the comment for '\n' chars and adjust endline accordingly.
+	endline = p.file.Line(p.pos)
+	if p.lit[1] == '*' {
+		// don't use range here - no need to decode Unicode code points
+		for i := 0; i < len(p.lit); i++ {
+			if p.lit[i] == '\n' {
+				endline++
+			}
+		}
+	}
+
+	comment = &ast.Comment{Slash: p.pos, Text: p.lit}
+	p.next0()
+
+	return
+}
+
+// Consume a group of adjacent comments, add it to the parser's
+// comments list, and return it together with the line at which
+// the last comment in the group ends. A non-comment token or n
+// empty lines terminate a comment group.
+//
+func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) {
+	var list []*ast.Comment
+	endline = p.file.Line(p.pos)
+	for p.tok == token.COMMENT && p.file.Line(p.pos) <= endline+n {
+		var comment *ast.Comment
+		comment, endline = p.consumeComment()
+		list = append(list, comment)
+	}
+
+	// add comment group to the comments list
+	comments = &ast.CommentGroup{List: list}
+	p.comments = append(p.comments, comments)
+
+	return
+}
+
+// Advance to the next non-comment token. In the process, collect
+// any comment groups encountered, and remember the last lead and
+// and line comments.
+//
+// A lead comment is a comment group that starts and ends in a
+// line without any other tokens and that is followed by a non-comment
+// token on the line immediately after the comment group.
+//
+// A line comment is a comment group that follows a non-comment
+// token on the same line, and that has no tokens after it on the line
+// where it ends.
+//
+// Lead and line comments may be considered documentation that is
+// stored in the AST.
+//
+func (p *parser) next() {
+	p.leadComment = nil
+	p.lineComment = nil
+	prev := p.pos
+	p.next0()
+
+	if p.tok == token.COMMENT {
+		var comment *ast.CommentGroup
+		var endline int
+
+		if p.file.Line(p.pos) == p.file.Line(prev) {
+			// The comment is on same line as the previous token; it
+			// cannot be a lead comment but may be a line comment.
+			comment, endline = p.consumeCommentGroup(0)
+			if p.file.Line(p.pos) != endline {
+				// The next token is on a different line, thus
+				// the last comment group is a line comment.
+				p.lineComment = comment
+			}
+		}
+
+		// consume successor comments, if any
+		endline = -1
+		for p.tok == token.COMMENT {
+			comment, endline = p.consumeCommentGroup(1)
+		}
+
+		if endline+1 == p.file.Line(p.pos) {
+			// The next token is following on the line immediately after the
+			// comment group, thus the last comment group is a lead comment.
+			p.leadComment = comment
+		}
+	}
+}
+
+// A bailout panic is raised to indicate early termination.
+type bailout struct{}
+
+func (p *parser) error(pos token.Pos, msg string) {
+	epos := p.file.Position(pos)
+
+	// If AllErrors is not set, discard errors reported on the same line
+	// as the last recorded error and stop parsing if there are more than
+	// 10 errors.
+	if p.mode&AllErrors == 0 {
+		n := len(p.errors)
+		if n > 0 && p.errors[n-1].Pos.Line == epos.Line {
+			return // discard - likely a spurious error
+		}
+		if n > 10 {
+			panic(bailout{})
+		}
+	}
+
+	p.errors.Add(epos, msg)
+}
+
+func (p *parser) errorExpected(pos token.Pos, msg string) {
+	msg = "expected " + msg
+	if pos == p.pos {
+		// the error happened at the current position;
+		// make the error message more specific
+		if p.tok == token.SEMICOLON && p.lit == "\n" {
+			msg += ", found newline"
+		} else {
+			msg += ", found '" + p.tok.String() + "'"
+			if p.tok.IsLiteral() {
+				msg += " " + p.lit
+			}
+		}
+	}
+	p.error(pos, msg)
+}
+
+func (p *parser) expect(tok token.Token) token.Pos {
+	pos := p.pos
+	if p.tok != tok {
+		p.errorExpected(pos, "'"+tok.String()+"'")
+	}
+	p.next() // make progress
+	return pos
+}
+
+// expectClosing is like expect but provides a better error message
+// for the common case of a missing comma before a newline.
+//
+func (p *parser) expectClosing(tok token.Token, context string) token.Pos {
+	if p.tok != tok && p.tok == token.SEMICOLON && p.lit == "\n" {
+		p.error(p.pos, "missing ',' before newline in "+context)
+		p.next()
+	}
+	return p.expect(tok)
+}
+
+func (p *parser) expectSemi() {
+	// semicolon is optional before a closing ')' or '}'
+	if p.tok != token.RPAREN && p.tok != token.RBRACE {
+		if p.tok == token.SEMICOLON {
+			p.next()
+		} else {
+			p.errorExpected(p.pos, "';'")
+			syncStmt(p)
+		}
+	}
+}
+
+func (p *parser) atComma(context string) bool {
+	if p.tok == token.COMMA {
+		return true
+	}
+	if p.tok == token.SEMICOLON && p.lit == "\n" {
+		p.error(p.pos, "missing ',' before newline in "+context)
+		return true // "insert" the comma and continue
+
+	}
+	return false
+}
+
+func assert(cond bool, msg string) {
+	if !cond {
+		panic("go/parser internal error: " + msg)
+	}
+}
+
+// syncStmt advances to the next statement.
+// Used for synchronization after an error.
+//
+func syncStmt(p *parser) {
+	for {
+		switch p.tok {
+		case token.BREAK, token.CONST, token.CONTINUE, token.DEFER,
+			token.FALLTHROUGH, token.FOR, token.GO, token.GOTO,
+			token.IF, token.RETURN, token.SELECT, token.SWITCH,
+			token.TYPE, token.VAR:
+			// Return only if parser made some progress since last
+			// sync or if it has not reached 10 sync calls without
+			// progress. Otherwise consume at least one token to
+			// avoid an endless parser loop (it is possible that
+			// both parseOperand and parseStmt call syncStmt and
+			// correctly do not advance, thus the need for the
+			// invocation limit p.syncCnt).
+			if p.pos == p.syncPos && p.syncCnt < 10 {
+				p.syncCnt++
+				return
+			}
+			if p.pos > p.syncPos {
+				p.syncPos = p.pos
+				p.syncCnt = 0
+				return
+			}
+			// Reaching here indicates a parser bug, likely an
+			// incorrect token list in this function, but it only
+			// leads to skipping of possibly correct code if a
+			// previous error is present, and thus is preferred
+			// over a non-terminating parse.
+		case token.EOF:
+			return
+		}
+		p.next()
+	}
+}
+
+// syncDecl advances to the next declaration.
+// Used for synchronization after an error.
+//
+func syncDecl(p *parser) {
+	for {
+		switch p.tok {
+		case token.CONST, token.TYPE, token.VAR:
+			// see comments in syncStmt
+			if p.pos == p.syncPos && p.syncCnt < 10 {
+				p.syncCnt++
+				return
+			}
+			if p.pos > p.syncPos {
+				p.syncPos = p.pos
+				p.syncCnt = 0
+				return
+			}
+		case token.EOF:
+			return
+		}
+		p.next()
+	}
+}
+
+// safePos returns a valid file position for a given position: If pos
+// is valid to begin with, safePos returns pos. If pos is out-of-range,
+// safePos returns the EOF position.
+//
+// This is hack to work around "artificial" end positions in the AST which
+// are computed by adding 1 to (presumably valid) token positions. If the
+// token positions are invalid due to parse errors, the resulting end position
+// may be past the file's EOF position, which would lead to panics if used
+// later on.
+//
+func (p *parser) safePos(pos token.Pos) (res token.Pos) {
+	defer func() {
+		if recover() != nil {
+			res = token.Pos(p.file.Base() + p.file.Size()) // EOF position
+		}
+	}()
+	_ = p.file.Offset(pos) // trigger a panic if position is out-of-range
+	return pos
+}
+
+// ----------------------------------------------------------------------------
+// Identifiers
+
+func (p *parser) parseIdent() *ast.Ident {
+	pos := p.pos
+	name := "_"
+	if p.tok == token.IDENT {
+		name = p.lit
+		p.next()
+	} else {
+		p.expect(token.IDENT) // use expect() error handling
+	}
+	return &ast.Ident{NamePos: pos, Name: name}
+}
+
+func (p *parser) parseIdentList() (list []*ast.Ident) {
+	if p.trace {
+		defer un(trace(p, "IdentList"))
+	}
+
+	list = append(list, p.parseIdent())
+	for p.tok == token.COMMA {
+		p.next()
+		list = append(list, p.parseIdent())
+	}
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Common productions
+
+// If lhs is set, result list elements which are identifiers are not resolved.
+func (p *parser) parseExprList(lhs bool) (list []ast.Expr) {
+	if p.trace {
+		defer un(trace(p, "ExpressionList"))
+	}
+
+	list = append(list, p.checkExpr(p.parseExpr(lhs)))
+	for p.tok == token.COMMA {
+		p.next()
+		list = append(list, p.checkExpr(p.parseExpr(lhs)))
+	}
+
+	return
+}
+
+func (p *parser) parseLhsList() []ast.Expr {
+	old := p.inRhs
+	p.inRhs = false
+	list := p.parseExprList(true)
+	switch p.tok {
+	case token.DEFINE:
+		// lhs of a short variable declaration
+		// but doesn't enter scope until later:
+		// caller must call p.shortVarDecl(p.makeIdentList(list))
+		// at appropriate time.
+	case token.COLON:
+		// lhs of a label declaration or a communication clause of a select
+		// statement (parseLhsList is not called when parsing the case clause
+		// of a switch statement):
+		// - labels are declared by the caller of parseLhsList
+		// - for communication clauses, if there is a stand-alone identifier
+		//   followed by a colon, we have a syntax error; there is no need
+		//   to resolve the identifier in that case
+	default:
+		// identifiers must be declared elsewhere
+		for _, x := range list {
+			p.resolve(x)
+		}
+	}
+	p.inRhs = old
+	return list
+}
+
+func (p *parser) parseRhsList() []ast.Expr {
+	old := p.inRhs
+	p.inRhs = true
+	list := p.parseExprList(false)
+	p.inRhs = old
+	return list
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+func (p *parser) parseType() ast.Expr {
+	if p.trace {
+		defer un(trace(p, "Type"))
+	}
+
+	typ := p.tryType()
+
+	if typ == nil {
+		pos := p.pos
+		p.errorExpected(pos, "type")
+		p.next() // make progress
+		return &ast.BadExpr{From: pos, To: p.pos}
+	}
+
+	return typ
+}
+
+// If the result is an identifier, it is not resolved.
+func (p *parser) parseTypeName() ast.Expr {
+	if p.trace {
+		defer un(trace(p, "TypeName"))
+	}
+
+	ident := p.parseIdent()
+	// don't resolve ident yet - it may be a parameter or field name
+
+	if p.tok == token.PERIOD {
+		// ident is a package name
+		p.next()
+		p.resolve(ident)
+		sel := p.parseIdent()
+		return &ast.SelectorExpr{X: ident, Sel: sel}
+	}
+
+	return ident
+}
+
+func (p *parser) parseArrayType() ast.Expr {
+	if p.trace {
+		defer un(trace(p, "ArrayType"))
+	}
+
+	lbrack := p.expect(token.LBRACK)
+	var len ast.Expr
+	// always permit ellipsis for more fault-tolerant parsing
+	if p.tok == token.ELLIPSIS {
+		len = &ast.Ellipsis{Ellipsis: p.pos}
+		p.next()
+	} else if p.tok != token.RBRACK {
+		len = p.parseRhs()
+	}
+	p.expect(token.RBRACK)
+	elt := p.parseType()
+
+	return &ast.ArrayType{Lbrack: lbrack, Len: len, Elt: elt}
+}
+
+func (p *parser) makeIdentList(list []ast.Expr) []*ast.Ident {
+	idents := make([]*ast.Ident, len(list))
+	for i, x := range list {
+		ident, isIdent := x.(*ast.Ident)
+		if !isIdent {
+			if _, isBad := x.(*ast.BadExpr); !isBad {
+				// only report error if it's a new one
+				p.errorExpected(x.Pos(), "identifier")
+			}
+			ident = &ast.Ident{NamePos: x.Pos(), Name: "_"}
+		}
+		idents[i] = ident
+	}
+	return idents
+}
+
+func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
+	if p.trace {
+		defer un(trace(p, "FieldDecl"))
+	}
+
+	doc := p.leadComment
+
+	// FieldDecl
+	list, typ := p.parseVarList(false)
+
+	// Tag
+	var tag *ast.BasicLit
+	if p.tok == token.STRING {
+		tag = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
+		p.next()
+	}
+
+	// analyze case
+	var idents []*ast.Ident
+	if typ != nil {
+		// IdentifierList Type
+		idents = p.makeIdentList(list)
+	} else {
+		// ["*"] TypeName (AnonymousField)
+		typ = list[0] // we always have at least one element
+		if n := len(list); n > 1 || !isTypeName(deref(typ)) {
+			pos := typ.Pos()
+			p.errorExpected(pos, "anonymous field")
+			typ = &ast.BadExpr{From: pos, To: p.safePos(list[n-1].End())}
+		}
+	}
+
+	p.expectSemi() // call before accessing p.linecomment
+
+	field := &ast.Field{Doc: doc, Names: idents, Type: typ, Tag: tag, Comment: p.lineComment}
+	p.declare(field, nil, scope, ast.Var, idents...)
+	p.resolve(typ)
+
+	return field
+}
+
+func (p *parser) parseStructType() *ast.StructType {
+	if p.trace {
+		defer un(trace(p, "StructType"))
+	}
+
+	pos := p.expect(token.STRUCT)
+	lbrace := p.expect(token.LBRACE)
+	scope := ast.NewScope(nil) // struct scope
+	var list []*ast.Field
+	for p.tok == token.IDENT || p.tok == token.MUL || p.tok == token.LPAREN {
+		// a field declaration cannot start with a '(' but we accept
+		// it here for more robust parsing and better error messages
+		// (parseFieldDecl will check and complain if necessary)
+		list = append(list, p.parseFieldDecl(scope))
+	}
+	rbrace := p.expect(token.RBRACE)
+
+	return &ast.StructType{
+		Struct: pos,
+		Fields: &ast.FieldList{
+			Opening: lbrace,
+			List:    list,
+			Closing: rbrace,
+		},
+	}
+}
+
+func (p *parser) parsePointerType() *ast.StarExpr {
+	if p.trace {
+		defer un(trace(p, "PointerType"))
+	}
+
+	star := p.expect(token.MUL)
+	base := p.parseType()
+
+	return &ast.StarExpr{Star: star, X: base}
+}
+
+// If the result is an identifier, it is not resolved.
+func (p *parser) tryVarType(isParam bool) ast.Expr {
+	if isParam && p.tok == token.ELLIPSIS {
+		pos := p.pos
+		p.next()
+		typ := p.tryIdentOrType() // don't use parseType so we can provide better error message
+		if typ != nil {
+			p.resolve(typ)
+		} else {
+			p.error(pos, "'...' parameter is missing type")
+			typ = &ast.BadExpr{From: pos, To: p.pos}
+		}
+		return &ast.Ellipsis{Ellipsis: pos, Elt: typ}
+	}
+	return p.tryIdentOrType()
+}
+
+// If the result is an identifier, it is not resolved.
+func (p *parser) parseVarType(isParam bool) ast.Expr {
+	typ := p.tryVarType(isParam)
+	if typ == nil {
+		pos := p.pos
+		p.errorExpected(pos, "type")
+		p.next() // make progress
+		typ = &ast.BadExpr{From: pos, To: p.pos}
+	}
+	return typ
+}
+
+// If any of the results are identifiers, they are not resolved.
+func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) {
+	if p.trace {
+		defer un(trace(p, "VarList"))
+	}
+
+	// a list of identifiers looks like a list of type names
+	//
+	// parse/tryVarType accepts any type (including parenthesized
+	// ones) even though the syntax does not permit them here: we
+	// accept them all for more robust parsing and complain later
+	for typ := p.parseVarType(isParam); typ != nil; {
+		list = append(list, typ)
+		if p.tok != token.COMMA {
+			break
+		}
+		p.next()
+		typ = p.tryVarType(isParam) // maybe nil as in: func f(int,) {}
+	}
+
+	// if we had a list of identifiers, it must be followed by a type
+	typ = p.tryVarType(isParam)
+
+	return
+}
+
+func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params []*ast.Field) {
+	if p.trace {
+		defer un(trace(p, "ParameterList"))
+	}
+
+	// ParameterDecl
+	list, typ := p.parseVarList(ellipsisOk)
+
+	// analyze case
+	if typ != nil {
+		// IdentifierList Type
+		idents := p.makeIdentList(list)
+		field := &ast.Field{Names: idents, Type: typ}
+		params = append(params, field)
+		// Go spec: The scope of an identifier denoting a function
+		// parameter or result variable is the function body.
+		p.declare(field, nil, scope, ast.Var, idents...)
+		p.resolve(typ)
+		if p.tok == token.COMMA {
+			p.next()
+		}
+		for p.tok != token.RPAREN && p.tok != token.EOF {
+			idents := p.parseIdentList()
+			typ := p.parseVarType(ellipsisOk)
+			field := &ast.Field{Names: idents, Type: typ}
+			params = append(params, field)
+			// Go spec: The scope of an identifier denoting a function
+			// parameter or result variable is the function body.
+			p.declare(field, nil, scope, ast.Var, idents...)
+			p.resolve(typ)
+			if !p.atComma("parameter list") {
+				break
+			}
+			p.next()
+		}
+	} else {
+		// Type { "," Type } (anonymous parameters)
+		params = make([]*ast.Field, len(list))
+		for i, typ := range list {
+			p.resolve(typ)
+			params[i] = &ast.Field{Type: typ}
+		}
+	}
+
+	return
+}
+
+func (p *parser) parseParameters(scope *ast.Scope, ellipsisOk bool) *ast.FieldList {
+	if p.trace {
+		defer un(trace(p, "Parameters"))
+	}
+
+	var params []*ast.Field
+	lparen := p.expect(token.LPAREN)
+	if p.tok != token.RPAREN {
+		params = p.parseParameterList(scope, ellipsisOk)
+	}
+	rparen := p.expect(token.RPAREN)
+
+	return &ast.FieldList{Opening: lparen, List: params, Closing: rparen}
+}
+
+func (p *parser) parseResult(scope *ast.Scope) *ast.FieldList {
+	if p.trace {
+		defer un(trace(p, "Result"))
+	}
+
+	if p.tok == token.LPAREN {
+		return p.parseParameters(scope, false)
+	}
+
+	typ := p.tryType()
+	if typ != nil {
+		list := make([]*ast.Field, 1)
+		list[0] = &ast.Field{Type: typ}
+		return &ast.FieldList{List: list}
+	}
+
+	return nil
+}
+
+func (p *parser) parseSignature(scope *ast.Scope) (params, results *ast.FieldList) {
+	if p.trace {
+		defer un(trace(p, "Signature"))
+	}
+
+	params = p.parseParameters(scope, true)
+	results = p.parseResult(scope)
+
+	return
+}
+
+func (p *parser) parseFuncType() (*ast.FuncType, *ast.Scope) {
+	if p.trace {
+		defer un(trace(p, "FuncType"))
+	}
+
+	pos := p.expect(token.FUNC)
+	scope := ast.NewScope(p.topScope) // function scope
+	params, results := p.parseSignature(scope)
+
+	return &ast.FuncType{Func: pos, Params: params, Results: results}, scope
+}
+
+func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field {
+	if p.trace {
+		defer un(trace(p, "MethodSpec"))
+	}
+
+	doc := p.leadComment
+	var idents []*ast.Ident
+	var typ ast.Expr
+	x := p.parseTypeName()
+	if ident, isIdent := x.(*ast.Ident); isIdent && p.tok == token.LPAREN {
+		// method
+		idents = []*ast.Ident{ident}
+		scope := ast.NewScope(nil) // method scope
+		params, results := p.parseSignature(scope)
+		typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results}
+	} else {
+		// embedded interface
+		typ = x
+		p.resolve(typ)
+	}
+	p.expectSemi() // call before accessing p.linecomment
+
+	spec := &ast.Field{Doc: doc, Names: idents, Type: typ, Comment: p.lineComment}
+	p.declare(spec, nil, scope, ast.Fun, idents...)
+
+	return spec
+}
+
+func (p *parser) parseInterfaceType() *ast.InterfaceType {
+	if p.trace {
+		defer un(trace(p, "InterfaceType"))
+	}
+
+	pos := p.expect(token.INTERFACE)
+	lbrace := p.expect(token.LBRACE)
+	scope := ast.NewScope(nil) // interface scope
+	var list []*ast.Field
+	for p.tok == token.IDENT {
+		list = append(list, p.parseMethodSpec(scope))
+	}
+	rbrace := p.expect(token.RBRACE)
+
+	return &ast.InterfaceType{
+		Interface: pos,
+		Methods: &ast.FieldList{
+			Opening: lbrace,
+			List:    list,
+			Closing: rbrace,
+		},
+	}
+}
+
+func (p *parser) parseMapType() *ast.MapType {
+	if p.trace {
+		defer un(trace(p, "MapType"))
+	}
+
+	pos := p.expect(token.MAP)
+	p.expect(token.LBRACK)
+	key := p.parseType()
+	p.expect(token.RBRACK)
+	value := p.parseType()
+
+	return &ast.MapType{Map: pos, Key: key, Value: value}
+}
+
+func (p *parser) parseChanType() *ast.ChanType {
+	if p.trace {
+		defer un(trace(p, "ChanType"))
+	}
+
+	pos := p.pos
+	dir := ast.SEND | ast.RECV
+	var arrow token.Pos
+	if p.tok == token.CHAN {
+		p.next()
+		if p.tok == token.ARROW {
+			arrow = p.pos
+			p.next()
+			dir = ast.SEND
+		}
+	} else {
+		arrow = p.expect(token.ARROW)
+		p.expect(token.CHAN)
+		dir = ast.RECV
+	}
+	value := p.parseType()
+
+	return &ast.ChanType{Begin: pos, Arrow: arrow, Dir: dir, Value: value}
+}
+
+// If the result is an identifier, it is not resolved.
+func (p *parser) tryIdentOrType() ast.Expr {
+	switch p.tok {
+	case token.IDENT:
+		return p.parseTypeName()
+	case token.LBRACK:
+		return p.parseArrayType()
+	case token.STRUCT:
+		return p.parseStructType()
+	case token.MUL:
+		return p.parsePointerType()
+	case token.FUNC:
+		typ, _ := p.parseFuncType()
+		return typ
+	case token.INTERFACE:
+		return p.parseInterfaceType()
+	case token.MAP:
+		return p.parseMapType()
+	case token.CHAN, token.ARROW:
+		return p.parseChanType()
+	case token.LPAREN:
+		lparen := p.pos
+		p.next()
+		typ := p.parseType()
+		rparen := p.expect(token.RPAREN)
+		return &ast.ParenExpr{Lparen: lparen, X: typ, Rparen: rparen}
+	}
+
+	// no type found
+	return nil
+}
+
+func (p *parser) tryType() ast.Expr {
+	typ := p.tryIdentOrType()
+	if typ != nil {
+		p.resolve(typ)
+	}
+	return typ
+}
+
+// ----------------------------------------------------------------------------
+// Blocks
+
+func (p *parser) parseStmtList() (list []ast.Stmt) {
+	if p.trace {
+		defer un(trace(p, "StatementList"))
+	}
+
+	for p.tok != token.CASE && p.tok != token.DEFAULT && p.tok != token.RBRACE && p.tok != token.EOF {
+		list = append(list, p.parseStmt())
+	}
+
+	return
+}
+
+func (p *parser) parseBody(scope *ast.Scope) *ast.BlockStmt {
+	if p.trace {
+		defer un(trace(p, "Body"))
+	}
+
+	lbrace := p.expect(token.LBRACE)
+	p.topScope = scope // open function scope
+	p.openLabelScope()
+	list := p.parseStmtList()
+	p.closeLabelScope()
+	p.closeScope()
+	rbrace := p.expect(token.RBRACE)
+
+	return &ast.BlockStmt{Lbrace: lbrace, List: list, Rbrace: rbrace}
+}
+
+func (p *parser) parseBlockStmt() *ast.BlockStmt {
+	if p.trace {
+		defer un(trace(p, "BlockStmt"))
+	}
+
+	lbrace := p.expect(token.LBRACE)
+	p.openScope()
+	list := p.parseStmtList()
+	p.closeScope()
+	rbrace := p.expect(token.RBRACE)
+
+	return &ast.BlockStmt{Lbrace: lbrace, List: list, Rbrace: rbrace}
+}
+
+// ----------------------------------------------------------------------------
+// Expressions
+
+func (p *parser) parseFuncTypeOrLit() ast.Expr {
+	if p.trace {
+		defer un(trace(p, "FuncTypeOrLit"))
+	}
+
+	typ, scope := p.parseFuncType()
+	if p.tok != token.LBRACE {
+		// function type only
+		return typ
+	}
+
+	p.exprLev++
+	body := p.parseBody(scope)
+	p.exprLev--
+
+	return &ast.FuncLit{Type: typ, Body: body}
+}
+
+// parseOperand may return an expression or a raw type (incl. array
+// types of the form [...]T. Callers must verify the result.
+// If lhs is set and the result is an identifier, it is not resolved.
+//
+func (p *parser) parseOperand(lhs bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "Operand"))
+	}
+
+	switch p.tok {
+	case token.IDENT:
+		x := p.parseIdent()
+		if !lhs {
+			p.resolve(x)
+		}
+		return x
+
+	case token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING:
+		x := &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
+		p.next()
+		return x
+
+	case token.LPAREN:
+		lparen := p.pos
+		p.next()
+		p.exprLev++
+		x := p.parseRhsOrType() // types may be parenthesized: (some type)
+		p.exprLev--
+		rparen := p.expect(token.RPAREN)
+		return &ast.ParenExpr{Lparen: lparen, X: x, Rparen: rparen}
+
+	case token.FUNC:
+		return p.parseFuncTypeOrLit()
+	}
+
+	if typ := p.tryIdentOrType(); typ != nil {
+		// could be type for composite literal or conversion
+		_, isIdent := typ.(*ast.Ident)
+		assert(!isIdent, "type cannot be identifier")
+		return typ
+	}
+
+	// we have an error
+	pos := p.pos
+	p.errorExpected(pos, "operand")
+	syncStmt(p)
+	return &ast.BadExpr{From: pos, To: p.pos}
+}
+
+func (p *parser) parseSelector(x ast.Expr) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "Selector"))
+	}
+
+	sel := p.parseIdent()
+
+	return &ast.SelectorExpr{X: x, Sel: sel}
+}
+
+func (p *parser) parseTypeAssertion(x ast.Expr) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "TypeAssertion"))
+	}
+
+	lparen := p.expect(token.LPAREN)
+	var typ ast.Expr
+	if p.tok == token.TYPE {
+		// type switch: typ == nil
+		p.next()
+	} else {
+		typ = p.parseType()
+	}
+	rparen := p.expect(token.RPAREN)
+
+	return &ast.TypeAssertExpr{X: x, Type: typ, Lparen: lparen, Rparen: rparen}
+}
+
+func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "IndexOrSlice"))
+	}
+
+	const N = 3 // change the 3 to 2 to disable 3-index slices
+	lbrack := p.expect(token.LBRACK)
+	p.exprLev++
+	var index [N]ast.Expr
+	var colons [N - 1]token.Pos
+	if p.tok != token.COLON {
+		index[0] = p.parseRhs()
+	}
+	ncolons := 0
+	for p.tok == token.COLON && ncolons < len(colons) {
+		colons[ncolons] = p.pos
+		ncolons++
+		p.next()
+		if p.tok != token.COLON && p.tok != token.RBRACK && p.tok != token.EOF {
+			index[ncolons] = p.parseRhs()
+		}
+	}
+	p.exprLev--
+	rbrack := p.expect(token.RBRACK)
+
+	if ncolons > 0 {
+		// slice expression
+		slice3 := false
+		if ncolons == 2 {
+			slice3 = true
+			// Check presence of 2nd and 3rd index here rather than during type-checking
+			// to prevent erroneous programs from passing through gofmt (was issue 7305).
+			if index[1] == nil {
+				p.error(colons[0], "2nd index required in 3-index slice")
+				index[1] = &ast.BadExpr{From: colons[0] + 1, To: colons[1]}
+			}
+			if index[2] == nil {
+				p.error(colons[1], "3rd index required in 3-index slice")
+				index[2] = &ast.BadExpr{From: colons[1] + 1, To: rbrack}
+			}
+		}
+		return &ast.SliceExpr{X: x, Lbrack: lbrack, Low: index[0], High: index[1], Max: index[2], Slice3: slice3, Rbrack: rbrack}
+	}
+
+	return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: index[0], Rbrack: rbrack}
+}
+
+func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr {
+	if p.trace {
+		defer un(trace(p, "CallOrConversion"))
+	}
+
+	lparen := p.expect(token.LPAREN)
+	p.exprLev++
+	var list []ast.Expr
+	var ellipsis token.Pos
+	for p.tok != token.RPAREN && p.tok != token.EOF && !ellipsis.IsValid() {
+		list = append(list, p.parseRhsOrType()) // builtins may expect a type: make(some type, ...)
+		if p.tok == token.ELLIPSIS {
+			ellipsis = p.pos
+			p.next()
+		}
+		if !p.atComma("argument list") {
+			break
+		}
+		p.next()
+	}
+	p.exprLev--
+	rparen := p.expectClosing(token.RPAREN, "argument list")
+
+	return &ast.CallExpr{Fun: fun, Lparen: lparen, Args: list, Ellipsis: ellipsis, Rparen: rparen}
+}
+
+func (p *parser) parseElement(keyOk bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "Element"))
+	}
+
+	if p.tok == token.LBRACE {
+		return p.parseLiteralValue(nil)
+	}
+
+	// Because the parser doesn't know the composite literal type, it cannot
+	// know if a key that's an identifier is a struct field name or a name
+	// denoting a value. The former is not resolved by the parser or the
+	// resolver.
+	//
+	// Instead, _try_ to resolve such a key if possible. If it resolves,
+	// it a) has correctly resolved, or b) incorrectly resolved because
+	// the key is a struct field with a name matching another identifier.
+	// In the former case we are done, and in the latter case we don't
+	// care because the type checker will do a separate field lookup.
+	//
+	// If the key does not resolve, it a) must be defined at the top
+	// level in another file of the same package, the universe scope, or be
+	// undeclared; or b) it is a struct field. In the former case, the type
+	// checker can do a top-level lookup, and in the latter case it will do
+	// a separate field lookup.
+	x := p.checkExpr(p.parseExpr(keyOk))
+	if keyOk {
+		if p.tok == token.COLON {
+			colon := p.pos
+			p.next()
+			// Try to resolve the key but don't collect it
+			// as unresolved identifier if it fails so that
+			// we don't get (possibly false) errors about
+			// undeclared names.
+			p.tryResolve(x, false)
+			return &ast.KeyValueExpr{Key: x, Colon: colon, Value: p.parseElement(false)}
+		}
+		p.resolve(x) // not a key
+	}
+
+	return x
+}
+
+func (p *parser) parseElementList() (list []ast.Expr) {
+	if p.trace {
+		defer un(trace(p, "ElementList"))
+	}
+
+	for p.tok != token.RBRACE && p.tok != token.EOF {
+		list = append(list, p.parseElement(true))
+		if !p.atComma("composite literal") {
+			break
+		}
+		p.next()
+	}
+
+	return
+}
+
+func (p *parser) parseLiteralValue(typ ast.Expr) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "LiteralValue"))
+	}
+
+	lbrace := p.expect(token.LBRACE)
+	var elts []ast.Expr
+	p.exprLev++
+	if p.tok != token.RBRACE {
+		elts = p.parseElementList()
+	}
+	p.exprLev--
+	rbrace := p.expectClosing(token.RBRACE, "composite literal")
+	return &ast.CompositeLit{Type: typ, Lbrace: lbrace, Elts: elts, Rbrace: rbrace}
+}
+
+// checkExpr checks that x is an expression (and not a type).
+func (p *parser) checkExpr(x ast.Expr) ast.Expr {
+	switch unparen(x).(type) {
+	case *ast.BadExpr:
+	case *ast.Ident:
+	case *ast.BasicLit:
+	case *ast.FuncLit:
+	case *ast.CompositeLit:
+	case *ast.ParenExpr:
+		panic("unreachable")
+	case *ast.SelectorExpr:
+	case *ast.IndexExpr:
+	case *ast.SliceExpr:
+	case *ast.TypeAssertExpr:
+		// If t.Type == nil we have a type assertion of the form
+		// y.(type), which is only allowed in type switch expressions.
+		// It's hard to exclude those but for the case where we are in
+		// a type switch. Instead be lenient and test this in the type
+		// checker.
+	case *ast.CallExpr:
+	case *ast.StarExpr:
+	case *ast.UnaryExpr:
+	case *ast.BinaryExpr:
+	default:
+		// all other nodes are not proper expressions
+		p.errorExpected(x.Pos(), "expression")
+		x = &ast.BadExpr{From: x.Pos(), To: p.safePos(x.End())}
+	}
+	return x
+}
+
+// isTypeName returns true iff x is a (qualified) TypeName.
+func isTypeName(x ast.Expr) bool {
+	switch t := x.(type) {
+	case *ast.BadExpr:
+	case *ast.Ident:
+	case *ast.SelectorExpr:
+		_, isIdent := t.X.(*ast.Ident)
+		return isIdent
+	default:
+		return false // all other nodes are not type names
+	}
+	return true
+}
+
+// isLiteralType returns true iff x is a legal composite literal type.
+func isLiteralType(x ast.Expr) bool {
+	switch t := x.(type) {
+	case *ast.BadExpr:
+	case *ast.Ident:
+	case *ast.SelectorExpr:
+		_, isIdent := t.X.(*ast.Ident)
+		return isIdent
+	case *ast.ArrayType:
+	case *ast.StructType:
+	case *ast.MapType:
+	default:
+		return false // all other nodes are not legal composite literal types
+	}
+	return true
+}
+
+// If x is of the form *T, deref returns T, otherwise it returns x.
+func deref(x ast.Expr) ast.Expr {
+	if p, isPtr := x.(*ast.StarExpr); isPtr {
+		x = p.X
+	}
+	return x
+}
+
+// If x is of the form (T), unparen returns unparen(T), otherwise it returns x.
+func unparen(x ast.Expr) ast.Expr {
+	if p, isParen := x.(*ast.ParenExpr); isParen {
+		x = unparen(p.X)
+	}
+	return x
+}
+
+// checkExprOrType checks that x is an expression or a type
+// (and not a raw type such as [...]T).
+//
+func (p *parser) checkExprOrType(x ast.Expr) ast.Expr {
+	switch t := unparen(x).(type) {
+	case *ast.ParenExpr:
+		panic("unreachable")
+	case *ast.UnaryExpr:
+	case *ast.ArrayType:
+		if len, isEllipsis := t.Len.(*ast.Ellipsis); isEllipsis {
+			p.error(len.Pos(), "expected array length, found '...'")
+			x = &ast.BadExpr{From: x.Pos(), To: p.safePos(x.End())}
+		}
+	}
+
+	// all other nodes are expressions or types
+	return x
+}
+
+// If lhs is set and the result is an identifier, it is not resolved.
+func (p *parser) parsePrimaryExpr(lhs bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "PrimaryExpr"))
+	}
+
+	x := p.parseOperand(lhs)
+L:
+	for {
+		switch p.tok {
+		case token.PERIOD:
+			p.next()
+			if lhs {
+				p.resolve(x)
+			}
+			switch p.tok {
+			case token.IDENT:
+				x = p.parseSelector(p.checkExprOrType(x))
+			case token.LPAREN:
+				x = p.parseTypeAssertion(p.checkExpr(x))
+			default:
+				pos := p.pos
+				p.errorExpected(pos, "selector or type assertion")
+				p.next() // make progress
+				x = &ast.BadExpr{From: pos, To: p.pos}
+			}
+		case token.LBRACK:
+			if lhs {
+				p.resolve(x)
+			}
+			x = p.parseIndexOrSlice(p.checkExpr(x))
+		case token.LPAREN:
+			if lhs {
+				p.resolve(x)
+			}
+			x = p.parseCallOrConversion(p.checkExprOrType(x))
+		case token.LBRACE:
+			if isLiteralType(x) && (p.exprLev >= 0 || !isTypeName(x)) {
+				if lhs {
+					p.resolve(x)
+				}
+				x = p.parseLiteralValue(x)
+			} else {
+				break L
+			}
+		default:
+			break L
+		}
+		lhs = false // no need to try to resolve again
+	}
+
+	return x
+}
+
+// If lhs is set and the result is an identifier, it is not resolved.
+func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "UnaryExpr"))
+	}
+
+	switch p.tok {
+	case token.ADD, token.SUB, token.NOT, token.XOR, token.AND:
+		pos, op := p.pos, p.tok
+		p.next()
+		x := p.parseUnaryExpr(false)
+		return &ast.UnaryExpr{OpPos: pos, Op: op, X: p.checkExpr(x)}
+
+	case token.ARROW:
+		// channel type or receive expression
+		arrow := p.pos
+		p.next()
+
+		// If the next token is token.CHAN we still don't know if it
+		// is a channel type or a receive operation - we only know
+		// once we have found the end of the unary expression. There
+		// are two cases:
+		//
+		//   <- type  => (<-type) must be channel type
+		//   <- expr  => <-(expr) is a receive from an expression
+		//
+		// In the first case, the arrow must be re-associated with
+		// the channel type parsed already:
+		//
+		//   <- (chan type)    =>  (<-chan type)
+		//   <- (chan<- type)  =>  (<-chan (<-type))
+
+		x := p.parseUnaryExpr(false)
+
+		// determine which case we have
+		if typ, ok := x.(*ast.ChanType); ok {
+			// (<-type)
+
+			// re-associate position info and <-
+			dir := ast.SEND
+			for ok && dir == ast.SEND {
+				if typ.Dir == ast.RECV {
+					// error: (<-type) is (<-(<-chan T))
+					p.errorExpected(typ.Arrow, "'chan'")
+				}
+				arrow, typ.Begin, typ.Arrow = typ.Arrow, arrow, arrow
+				dir, typ.Dir = typ.Dir, ast.RECV
+				typ, ok = typ.Value.(*ast.ChanType)
+			}
+			if dir == ast.SEND {
+				p.errorExpected(arrow, "channel type")
+			}
+
+			return x
+		}
+
+		// <-(expr)
+		return &ast.UnaryExpr{OpPos: arrow, Op: token.ARROW, X: p.checkExpr(x)}
+
+	case token.MUL:
+		// pointer type or unary "*" expression
+		pos := p.pos
+		p.next()
+		x := p.parseUnaryExpr(false)
+		return &ast.StarExpr{Star: pos, X: p.checkExprOrType(x)}
+	}
+
+	return p.parsePrimaryExpr(lhs)
+}
+
+func (p *parser) tokPrec() (token.Token, int) {
+	tok := p.tok
+	if p.inRhs && tok == token.ASSIGN {
+		tok = token.EQL
+	}
+	return tok, tok.Precedence()
+}
+
+// If lhs is set and the result is an identifier, it is not resolved.
+func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "BinaryExpr"))
+	}
+
+	x := p.parseUnaryExpr(lhs)
+	for _, prec := p.tokPrec(); prec >= prec1; prec-- {
+		for {
+			op, oprec := p.tokPrec()
+			if oprec != prec {
+				break
+			}
+			pos := p.expect(op)
+			if lhs {
+				p.resolve(x)
+				lhs = false
+			}
+			y := p.parseBinaryExpr(false, prec+1)
+			x = &ast.BinaryExpr{X: p.checkExpr(x), OpPos: pos, Op: op, Y: p.checkExpr(y)}
+		}
+	}
+
+	return x
+}
+
+// If lhs is set and the result is an identifier, it is not resolved.
+// The result may be a type or even a raw type ([...]int). Callers must
+// check the result (using checkExpr or checkExprOrType), depending on
+// context.
+func (p *parser) parseExpr(lhs bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "Expression"))
+	}
+
+	return p.parseBinaryExpr(lhs, token.LowestPrec+1)
+}
+
+func (p *parser) parseRhs() ast.Expr {
+	old := p.inRhs
+	p.inRhs = true
+	x := p.checkExpr(p.parseExpr(false))
+	p.inRhs = old
+	return x
+}
+
+func (p *parser) parseRhsOrType() ast.Expr {
+	old := p.inRhs
+	p.inRhs = true
+	x := p.checkExprOrType(p.parseExpr(false))
+	p.inRhs = old
+	return x
+}
+
+// ----------------------------------------------------------------------------
+// Statements
+
+// Parsing modes for parseSimpleStmt.
+const (
+	basic = iota
+	labelOk
+	rangeOk
+)
+
+// parseSimpleStmt returns true as 2nd result if it parsed the assignment
+// of a range clause (with mode == rangeOk). The returned statement is an
+// assignment with a right-hand side that is a single unary expression of
+// the form "range x". No guarantees are given for the left-hand side.
+func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) {
+	if p.trace {
+		defer un(trace(p, "SimpleStmt"))
+	}
+
+	x := p.parseLhsList()
+
+	switch p.tok {
+	case
+		token.DEFINE, token.ASSIGN, token.ADD_ASSIGN,
+		token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN,
+		token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN,
+		token.XOR_ASSIGN, token.SHL_ASSIGN, token.SHR_ASSIGN, token.AND_NOT_ASSIGN:
+		// assignment statement, possibly part of a range clause
+		pos, tok := p.pos, p.tok
+		p.next()
+		var y []ast.Expr
+		isRange := false
+		if mode == rangeOk && p.tok == token.RANGE && (tok == token.DEFINE || tok == token.ASSIGN) {
+			pos := p.pos
+			p.next()
+			y = []ast.Expr{&ast.UnaryExpr{OpPos: pos, Op: token.RANGE, X: p.parseRhs()}}
+			isRange = true
+		} else {
+			y = p.parseRhsList()
+		}
+		as := &ast.AssignStmt{Lhs: x, TokPos: pos, Tok: tok, Rhs: y}
+		if tok == token.DEFINE {
+			p.shortVarDecl(as, x)
+		}
+		return as, isRange
+	}
+
+	if len(x) > 1 {
+		p.errorExpected(x[0].Pos(), "1 expression")
+		// continue with first expression
+	}
+
+	switch p.tok {
+	case token.COLON:
+		// labeled statement
+		colon := p.pos
+		p.next()
+		if label, isIdent := x[0].(*ast.Ident); mode == labelOk && isIdent {
+			// Go spec: The scope of a label is the body of the function
+			// in which it is declared and excludes the body of any nested
+			// function.
+			stmt := &ast.LabeledStmt{Label: label, Colon: colon, Stmt: p.parseStmt()}
+			p.declare(stmt, nil, p.labelScope, ast.Lbl, label)
+			return stmt, false
+		}
+		// The label declaration typically starts at x[0].Pos(), but the label
+		// declaration may be erroneous due to a token after that position (and
+		// before the ':'). If SpuriousErrors is not set, the (only) error re-
+		// ported for the line is the illegal label error instead of the token
+		// before the ':' that caused the problem. Thus, use the (latest) colon
+		// position for error reporting.
+		p.error(colon, "illegal label declaration")
+		return &ast.BadStmt{From: x[0].Pos(), To: colon + 1}, false
+
+	case token.ARROW:
+		// send statement
+		arrow := p.pos
+		p.next()
+		y := p.parseRhs()
+		return &ast.SendStmt{Chan: x[0], Arrow: arrow, Value: y}, false
+
+	case token.INC, token.DEC:
+		// increment or decrement
+		s := &ast.IncDecStmt{X: x[0], TokPos: p.pos, Tok: p.tok}
+		p.next()
+		return s, false
+	}
+
+	// expression
+	return &ast.ExprStmt{X: x[0]}, false
+}
+
+func (p *parser) parseCallExpr(callType string) *ast.CallExpr {
+	x := p.parseRhsOrType() // could be a conversion: (some type)(x)
+	if call, isCall := x.(*ast.CallExpr); isCall {
+		return call
+	}
+	if _, isBad := x.(*ast.BadExpr); !isBad {
+		// only report error if it's a new one
+		p.error(p.safePos(x.End()), fmt.Sprintf("function must be invoked in %s statement", callType))
+	}
+	return nil
+}
+
+func (p *parser) parseGoStmt() ast.Stmt {
+	if p.trace {
+		defer un(trace(p, "GoStmt"))
+	}
+
+	pos := p.expect(token.GO)
+	call := p.parseCallExpr("go")
+	p.expectSemi()
+	if call == nil {
+		return &ast.BadStmt{From: pos, To: pos + 2} // len("go")
+	}
+
+	return &ast.GoStmt{Go: pos, Call: call}
+}
+
+func (p *parser) parseDeferStmt() ast.Stmt {
+	if p.trace {
+		defer un(trace(p, "DeferStmt"))
+	}
+
+	pos := p.expect(token.DEFER)
+	call := p.parseCallExpr("defer")
+	p.expectSemi()
+	if call == nil {
+		return &ast.BadStmt{From: pos, To: pos + 5} // len("defer")
+	}
+
+	return &ast.DeferStmt{Defer: pos, Call: call}
+}
+
+func (p *parser) parseReturnStmt() *ast.ReturnStmt {
+	if p.trace {
+		defer un(trace(p, "ReturnStmt"))
+	}
+
+	pos := p.pos
+	p.expect(token.RETURN)
+	var x []ast.Expr
+	if p.tok != token.SEMICOLON && p.tok != token.RBRACE {
+		x = p.parseRhsList()
+	}
+	p.expectSemi()
+
+	return &ast.ReturnStmt{Return: pos, Results: x}
+}
+
+func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt {
+	if p.trace {
+		defer un(trace(p, "BranchStmt"))
+	}
+
+	pos := p.expect(tok)
+	var label *ast.Ident
+	if tok != token.FALLTHROUGH && p.tok == token.IDENT {
+		label = p.parseIdent()
+		// add to list of unresolved targets
+		n := len(p.targetStack) - 1
+		p.targetStack[n] = append(p.targetStack[n], label)
+	}
+	p.expectSemi()
+
+	return &ast.BranchStmt{TokPos: pos, Tok: tok, Label: label}
+}
+
+func (p *parser) makeExpr(s ast.Stmt, kind string) ast.Expr {
+	if s == nil {
+		return nil
+	}
+	if es, isExpr := s.(*ast.ExprStmt); isExpr {
+		return p.checkExpr(es.X)
+	}
+	p.error(s.Pos(), fmt.Sprintf("expected %s, found simple statement (missing parentheses around composite literal?)", kind))
+	return &ast.BadExpr{From: s.Pos(), To: p.safePos(s.End())}
+}
+
+func (p *parser) parseIfStmt() *ast.IfStmt {
+	if p.trace {
+		defer un(trace(p, "IfStmt"))
+	}
+
+	pos := p.expect(token.IF)
+	p.openScope()
+	defer p.closeScope()
+
+	var s ast.Stmt
+	var x ast.Expr
+	{
+		prevLev := p.exprLev
+		p.exprLev = -1
+		if p.tok == token.SEMICOLON {
+			p.next()
+			x = p.parseRhs()
+		} else {
+			s, _ = p.parseSimpleStmt(basic)
+			if p.tok == token.SEMICOLON {
+				p.next()
+				x = p.parseRhs()
+			} else {
+				x = p.makeExpr(s, "boolean expression")
+				s = nil
+			}
+		}
+		p.exprLev = prevLev
+	}
+
+	body := p.parseBlockStmt()
+	var else_ ast.Stmt
+	if p.tok == token.ELSE {
+		p.next()
+		else_ = p.parseStmt()
+	} else {
+		p.expectSemi()
+	}
+
+	return &ast.IfStmt{If: pos, Init: s, Cond: x, Body: body, Else: else_}
+}
+
+func (p *parser) parseTypeList() (list []ast.Expr) {
+	if p.trace {
+		defer un(trace(p, "TypeList"))
+	}
+
+	list = append(list, p.parseType())
+	for p.tok == token.COMMA {
+		p.next()
+		list = append(list, p.parseType())
+	}
+
+	return
+}
+
+func (p *parser) parseCaseClause(typeSwitch bool) *ast.CaseClause {
+	if p.trace {
+		defer un(trace(p, "CaseClause"))
+	}
+
+	pos := p.pos
+	var list []ast.Expr
+	if p.tok == token.CASE {
+		p.next()
+		if typeSwitch {
+			list = p.parseTypeList()
+		} else {
+			list = p.parseRhsList()
+		}
+	} else {
+		p.expect(token.DEFAULT)
+	}
+
+	colon := p.expect(token.COLON)
+	p.openScope()
+	body := p.parseStmtList()
+	p.closeScope()
+
+	return &ast.CaseClause{Case: pos, List: list, Colon: colon, Body: body}
+}
+
+func isTypeSwitchAssert(x ast.Expr) bool {
+	a, ok := x.(*ast.TypeAssertExpr)
+	return ok && a.Type == nil
+}
+
+func isTypeSwitchGuard(s ast.Stmt) bool {
+	switch t := s.(type) {
+	case *ast.ExprStmt:
+		// x.(nil)
+		return isTypeSwitchAssert(t.X)
+	case *ast.AssignStmt:
+		// v := x.(nil)
+		return len(t.Lhs) == 1 && t.Tok == token.DEFINE && len(t.Rhs) == 1 && isTypeSwitchAssert(t.Rhs[0])
+	}
+	return false
+}
+
+func (p *parser) parseSwitchStmt() ast.Stmt {
+	if p.trace {
+		defer un(trace(p, "SwitchStmt"))
+	}
+
+	pos := p.expect(token.SWITCH)
+	p.openScope()
+	defer p.closeScope()
+
+	var s1, s2 ast.Stmt
+	if p.tok != token.LBRACE {
+		prevLev := p.exprLev
+		p.exprLev = -1
+		if p.tok != token.SEMICOLON {
+			s2, _ = p.parseSimpleStmt(basic)
+		}
+		if p.tok == token.SEMICOLON {
+			p.next()
+			s1 = s2
+			s2 = nil
+			if p.tok != token.LBRACE {
+				// A TypeSwitchGuard may declare a variable in addition
+				// to the variable declared in the initial SimpleStmt.
+				// Introduce extra scope to avoid redeclaration errors:
+				//
+				//	switch t := 0; t := x.(T) { ... }
+				//
+				// (this code is not valid Go because the first t
+				// cannot be accessed and thus is never used, the extra
+				// scope is needed for the correct error message).
+				//
+				// If we don't have a type switch, s2 must be an expression.
+				// Having the extra nested but empty scope won't affect it.
+				p.openScope()
+				defer p.closeScope()
+				s2, _ = p.parseSimpleStmt(basic)
+			}
+		}
+		p.exprLev = prevLev
+	}
+
+	typeSwitch := isTypeSwitchGuard(s2)
+	lbrace := p.expect(token.LBRACE)
+	var list []ast.Stmt
+	for p.tok == token.CASE || p.tok == token.DEFAULT {
+		list = append(list, p.parseCaseClause(typeSwitch))
+	}
+	rbrace := p.expect(token.RBRACE)
+	p.expectSemi()
+	body := &ast.BlockStmt{Lbrace: lbrace, List: list, Rbrace: rbrace}
+
+	if typeSwitch {
+		return &ast.TypeSwitchStmt{Switch: pos, Init: s1, Assign: s2, Body: body}
+	}
+
+	return &ast.SwitchStmt{Switch: pos, Init: s1, Tag: p.makeExpr(s2, "switch expression"), Body: body}
+}
+
+func (p *parser) parseCommClause() *ast.CommClause {
+	if p.trace {
+		defer un(trace(p, "CommClause"))
+	}
+
+	p.openScope()
+	pos := p.pos
+	var comm ast.Stmt
+	if p.tok == token.CASE {
+		p.next()
+		lhs := p.parseLhsList()
+		if p.tok == token.ARROW {
+			// SendStmt
+			if len(lhs) > 1 {
+				p.errorExpected(lhs[0].Pos(), "1 expression")
+				// continue with first expression
+			}
+			arrow := p.pos
+			p.next()
+			rhs := p.parseRhs()
+			comm = &ast.SendStmt{Chan: lhs[0], Arrow: arrow, Value: rhs}
+		} else {
+			// RecvStmt
+			if tok := p.tok; tok == token.ASSIGN || tok == token.DEFINE {
+				// RecvStmt with assignment
+				if len(lhs) > 2 {
+					p.errorExpected(lhs[0].Pos(), "1 or 2 expressions")
+					// continue with first two expressions
+					lhs = lhs[0:2]
+				}
+				pos := p.pos
+				p.next()
+				rhs := p.parseRhs()
+				as := &ast.AssignStmt{Lhs: lhs, TokPos: pos, Tok: tok, Rhs: []ast.Expr{rhs}}
+				if tok == token.DEFINE {
+					p.shortVarDecl(as, lhs)
+				}
+				comm = as
+			} else {
+				// lhs must be single receive operation
+				if len(lhs) > 1 {
+					p.errorExpected(lhs[0].Pos(), "1 expression")
+					// continue with first expression
+				}
+				comm = &ast.ExprStmt{X: lhs[0]}
+			}
+		}
+	} else {
+		p.expect(token.DEFAULT)
+	}
+
+	colon := p.expect(token.COLON)
+	body := p.parseStmtList()
+	p.closeScope()
+
+	return &ast.CommClause{Case: pos, Comm: comm, Colon: colon, Body: body}
+}
+
+func (p *parser) parseSelectStmt() *ast.SelectStmt {
+	if p.trace {
+		defer un(trace(p, "SelectStmt"))
+	}
+
+	pos := p.expect(token.SELECT)
+	lbrace := p.expect(token.LBRACE)
+	var list []ast.Stmt
+	for p.tok == token.CASE || p.tok == token.DEFAULT {
+		list = append(list, p.parseCommClause())
+	}
+	rbrace := p.expect(token.RBRACE)
+	p.expectSemi()
+	body := &ast.BlockStmt{Lbrace: lbrace, List: list, Rbrace: rbrace}
+
+	return &ast.SelectStmt{Select: pos, Body: body}
+}
+
+func (p *parser) parseForStmt() ast.Stmt {
+	if p.trace {
+		defer un(trace(p, "ForStmt"))
+	}
+
+	pos := p.expect(token.FOR)
+	p.openScope()
+	defer p.closeScope()
+
+	var s1, s2, s3 ast.Stmt
+	var isRange bool
+	if p.tok != token.LBRACE {
+		prevLev := p.exprLev
+		p.exprLev = -1
+		if p.tok != token.SEMICOLON {
+			s2, isRange = p.parseSimpleStmt(rangeOk)
+		}
+		if !isRange && p.tok == token.SEMICOLON {
+			p.next()
+			s1 = s2
+			s2 = nil
+			if p.tok != token.SEMICOLON {
+				s2, _ = p.parseSimpleStmt(basic)
+			}
+			p.expectSemi()
+			if p.tok != token.LBRACE {
+				s3, _ = p.parseSimpleStmt(basic)
+			}
+		}
+		p.exprLev = prevLev
+	}
+
+	body := p.parseBlockStmt()
+	p.expectSemi()
+
+	if isRange {
+		as := s2.(*ast.AssignStmt)
+		// check lhs
+		var key, value ast.Expr
+		switch len(as.Lhs) {
+		case 2:
+			key, value = as.Lhs[0], as.Lhs[1]
+		case 1:
+			key = as.Lhs[0]
+		default:
+			p.errorExpected(as.Lhs[0].Pos(), "1 or 2 expressions")
+			return &ast.BadStmt{From: pos, To: p.safePos(body.End())}
+		}
+		// parseSimpleStmt returned a right-hand side that
+		// is a single unary expression of the form "range x"
+		x := as.Rhs[0].(*ast.UnaryExpr).X
+		return &ast.RangeStmt{
+			For:    pos,
+			Key:    key,
+			Value:  value,
+			TokPos: as.TokPos,
+			Tok:    as.Tok,
+			X:      x,
+			Body:   body,
+		}
+	}
+
+	// regular for statement
+	return &ast.ForStmt{
+		For:  pos,
+		Init: s1,
+		Cond: p.makeExpr(s2, "boolean or range expression"),
+		Post: s3,
+		Body: body,
+	}
+}
+
+func (p *parser) parseStmt() (s ast.Stmt) {
+	if p.trace {
+		defer un(trace(p, "Statement"))
+	}
+
+	switch p.tok {
+	case token.CONST, token.TYPE, token.VAR:
+		s = &ast.DeclStmt{Decl: p.parseDecl(syncStmt)}
+	case
+		// tokens that may start an expression
+		token.IDENT, token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING, token.FUNC, token.LPAREN, // operands
+		token.LBRACK, token.STRUCT, // composite types
+		token.ADD, token.SUB, token.MUL, token.AND, token.XOR, token.ARROW, token.NOT: // unary operators
+		s, _ = p.parseSimpleStmt(labelOk)
+		// because of the required look-ahead, labeled statements are
+		// parsed by parseSimpleStmt - don't expect a semicolon after
+		// them
+		if _, isLabeledStmt := s.(*ast.LabeledStmt); !isLabeledStmt {
+			p.expectSemi()
+		}
+	case token.GO:
+		s = p.parseGoStmt()
+	case token.DEFER:
+		s = p.parseDeferStmt()
+	case token.RETURN:
+		s = p.parseReturnStmt()
+	case token.BREAK, token.CONTINUE, token.GOTO, token.FALLTHROUGH:
+		s = p.parseBranchStmt(p.tok)
+	case token.LBRACE:
+		s = p.parseBlockStmt()
+		p.expectSemi()
+	case token.IF:
+		s = p.parseIfStmt()
+	case token.SWITCH:
+		s = p.parseSwitchStmt()
+	case token.SELECT:
+		s = p.parseSelectStmt()
+	case token.FOR:
+		s = p.parseForStmt()
+	case token.SEMICOLON:
+		s = &ast.EmptyStmt{Semicolon: p.pos}
+		p.next()
+	case token.RBRACE:
+		// a semicolon may be omitted before a closing "}"
+		s = &ast.EmptyStmt{Semicolon: p.pos}
+	default:
+		// no statement found
+		pos := p.pos
+		p.errorExpected(pos, "statement")
+		syncStmt(p)
+		s = &ast.BadStmt{From: pos, To: p.pos}
+	}
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+type parseSpecFunction func(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
+
+func isValidImport(lit string) bool {
+	const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
+	s, _ := strconv.Unquote(lit) // go/scanner returns a legal string literal
+	for _, r := range s {
+		if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
+			return false
+		}
+	}
+	return s != ""
+}
+
+func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
+	if p.trace {
+		defer un(trace(p, "ImportSpec"))
+	}
+
+	var ident *ast.Ident
+	switch p.tok {
+	case token.PERIOD:
+		ident = &ast.Ident{NamePos: p.pos, Name: "."}
+		p.next()
+	case token.IDENT:
+		ident = p.parseIdent()
+	}
+
+	pos := p.pos
+	var path string
+	if p.tok == token.STRING {
+		path = p.lit
+		if !isValidImport(path) {
+			p.error(pos, "invalid import path: "+path)
+		}
+		p.next()
+	} else {
+		p.expect(token.STRING) // use expect() error handling
+	}
+	p.expectSemi() // call before accessing p.linecomment
+
+	// collect imports
+	spec := &ast.ImportSpec{
+		Doc:     doc,
+		Name:    ident,
+		Path:    &ast.BasicLit{ValuePos: pos, Kind: token.STRING, Value: path},
+		Comment: p.lineComment,
+	}
+	p.imports = append(p.imports, spec)
+
+	return spec
+}
+
+func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec {
+	if p.trace {
+		defer un(trace(p, keyword.String()+"Spec"))
+	}
+
+	idents := p.parseIdentList()
+	typ := p.tryType()
+	var values []ast.Expr
+	// always permit optional initialization for more tolerant parsing
+	if p.tok == token.ASSIGN {
+		p.next()
+		values = p.parseRhsList()
+	}
+	p.expectSemi() // call before accessing p.linecomment
+
+	// Go spec: The scope of a constant or variable identifier declared inside
+	// a function begins at the end of the ConstSpec or VarSpec and ends at
+	// the end of the innermost containing block.
+	// (Global identifiers are resolved in a separate phase after parsing.)
+	spec := &ast.ValueSpec{
+		Doc:     doc,
+		Names:   idents,
+		Type:    typ,
+		Values:  values,
+		Comment: p.lineComment,
+	}
+	kind := ast.Con
+	if keyword == token.VAR {
+		kind = ast.Var
+	}
+	p.declare(spec, iota, p.topScope, kind, idents...)
+
+	return spec
+}
+
+func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
+	if p.trace {
+		defer un(trace(p, "TypeSpec"))
+	}
+
+	ident := p.parseIdent()
+
+	// Go spec: The scope of a type identifier declared inside a function begins
+	// at the identifier in the TypeSpec and ends at the end of the innermost
+	// containing block.
+	// (Global identifiers are resolved in a separate phase after parsing.)
+	spec := &ast.TypeSpec{Doc: doc, Name: ident}
+	p.declare(spec, nil, p.topScope, ast.Typ, ident)
+
+	spec.Type = p.parseType()
+	p.expectSemi() // call before accessing p.linecomment
+	spec.Comment = p.lineComment
+
+	return spec
+}
+
+func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl {
+	if p.trace {
+		defer un(trace(p, "GenDecl("+keyword.String()+")"))
+	}
+
+	doc := p.leadComment
+	pos := p.expect(keyword)
+	var lparen, rparen token.Pos
+	var list []ast.Spec
+	if p.tok == token.LPAREN {
+		lparen = p.pos
+		p.next()
+		for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ {
+			list = append(list, f(p.leadComment, keyword, iota))
+		}
+		rparen = p.expect(token.RPAREN)
+		p.expectSemi()
+	} else {
+		list = append(list, f(nil, keyword, 0))
+	}
+
+	return &ast.GenDecl{
+		Doc:    doc,
+		TokPos: pos,
+		Tok:    keyword,
+		Lparen: lparen,
+		Specs:  list,
+		Rparen: rparen,
+	}
+}
+
+func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
+	if p.trace {
+		defer un(trace(p, "Receiver"))
+	}
+
+	par := p.parseParameters(scope, false)
+
+	// must have exactly one receiver
+	if par.NumFields() != 1 {
+		p.errorExpected(par.Opening, "exactly one receiver")
+		par.List = []*ast.Field{{Type: &ast.BadExpr{From: par.Opening, To: par.Closing + 1}}}
+		return par
+	}
+
+	// recv type must be of the form ["*"] identifier
+	recv := par.List[0]
+	base := deref(recv.Type)
+	if _, isIdent := base.(*ast.Ident); !isIdent {
+		if _, isBad := base.(*ast.BadExpr); !isBad {
+			// only report error if it's a new one
+			p.errorExpected(base.Pos(), "(unqualified) identifier")
+		}
+		par.List = []*ast.Field{
+			{Type: &ast.BadExpr{From: recv.Pos(), To: p.safePos(recv.End())}},
+		}
+	}
+
+	return par
+}
+
+func (p *parser) parseFuncDecl() *ast.FuncDecl {
+	if p.trace {
+		defer un(trace(p, "FunctionDecl"))
+	}
+
+	doc := p.leadComment
+	pos := p.expect(token.FUNC)
+	scope := ast.NewScope(p.topScope) // function scope
+
+	var recv *ast.FieldList
+	if p.tok == token.LPAREN {
+		recv = p.parseReceiver(scope)
+	}
+
+	ident := p.parseIdent()
+
+	params, results := p.parseSignature(scope)
+
+	var body *ast.BlockStmt
+	if p.tok == token.LBRACE {
+		body = p.parseBody(scope)
+	}
+	p.expectSemi()
+
+	decl := &ast.FuncDecl{
+		Doc:  doc,
+		Recv: recv,
+		Name: ident,
+		Type: &ast.FuncType{
+			Func:    pos,
+			Params:  params,
+			Results: results,
+		},
+		Body: body,
+	}
+	if recv == nil {
+		// Go spec: The scope of an identifier denoting a constant, type,
+		// variable, or function (but not method) declared at top level
+		// (outside any function) is the package block.
+		//
+		// init() functions cannot be referred to and there may
+		// be more than one - don't put them in the pkgScope
+		if ident.Name != "init" {
+			p.declare(decl, nil, p.pkgScope, ast.Fun, ident)
+		}
+	}
+
+	return decl
+}
+
+func (p *parser) parseDecl(sync func(*parser)) ast.Decl {
+	if p.trace {
+		defer un(trace(p, "Declaration"))
+	}
+
+	var f parseSpecFunction
+	switch p.tok {
+	case token.CONST, token.VAR:
+		f = p.parseValueSpec
+
+	case token.TYPE:
+		f = p.parseTypeSpec
+
+	case token.FUNC:
+		return p.parseFuncDecl()
+
+	default:
+		pos := p.pos
+		p.errorExpected(pos, "declaration")
+		sync(p)
+		return &ast.BadDecl{From: pos, To: p.pos}
+	}
+
+	return p.parseGenDecl(p.tok, f)
+}
+
+// ----------------------------------------------------------------------------
+// Source files
+
+func (p *parser) parseFile() *ast.File {
+	if p.trace {
+		defer un(trace(p, "File"))
+	}
+
+	// Don't bother parsing the rest if we had errors scanning the first token.
+	// Likely not a Go source file at all.
+	if p.errors.Len() != 0 {
+		return nil
+	}
+
+	// package clause
+	doc := p.leadComment
+	pos := p.expect(token.PACKAGE)
+	// Go spec: The package clause is not a declaration;
+	// the package name does not appear in any scope.
+	ident := p.parseIdent()
+	if ident.Name == "_" && p.mode&DeclarationErrors != 0 {
+		p.error(p.pos, "invalid package name _")
+	}
+	p.expectSemi()
+
+	// Don't bother parsing the rest if we had errors parsing the package clause.
+	// Likely not a Go source file at all.
+	if p.errors.Len() != 0 {
+		return nil
+	}
+
+	p.openScope()
+	p.pkgScope = p.topScope
+	var decls []ast.Decl
+	if p.mode&PackageClauseOnly == 0 {
+		// import decls
+		for p.tok == token.IMPORT {
+			decls = append(decls, p.parseGenDecl(token.IMPORT, p.parseImportSpec))
+		}
+
+		if p.mode&ImportsOnly == 0 {
+			// rest of package body
+			for p.tok != token.EOF {
+				decls = append(decls, p.parseDecl(syncDecl))
+			}
+		}
+	}
+	p.closeScope()
+	assert(p.topScope == nil, "unbalanced scopes")
+	assert(p.labelScope == nil, "unbalanced label scopes")
+
+	// resolve global identifiers within the same file
+	i := 0
+	for _, ident := range p.unresolved {
+		// i <= index for current ident
+		assert(ident.Obj == unresolved, "object already resolved")
+		ident.Obj = p.pkgScope.Lookup(ident.Name) // also removes unresolved sentinel
+		if ident.Obj == nil {
+			p.unresolved[i] = ident
+			i++
+		}
+	}
+
+	return &ast.File{
+		Doc:        doc,
+		Package:    pos,
+		Name:       ident,
+		Decls:      decls,
+		Scope:      p.pkgScope,
+		Imports:    p.imports,
+		Unresolved: p.unresolved[0:i],
+		Comments:   p.comments,
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/parser/parser_test.go b/third_party/gofrontend/libgo/go/go/parser/parser_test.go
new file mode 100644
index 0000000..2797ea5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/parser/parser_test.go
@@ -0,0 +1,431 @@
+// 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 parser
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"strings"
+	"testing"
+)
+
+var fset = token.NewFileSet()
+
+var validFiles = []string{
+	"parser.go",
+	"parser_test.go",
+	"error_test.go",
+	"short_test.go",
+}
+
+func TestParse(t *testing.T) {
+	for _, filename := range validFiles {
+		_, err := ParseFile(fset, filename, nil, DeclarationErrors)
+		if err != nil {
+			t.Fatalf("ParseFile(%s): %v", filename, err)
+		}
+	}
+}
+
+func nameFilter(filename string) bool {
+	switch filename {
+	case "parser.go", "interface.go", "parser_test.go":
+		return true
+	case "parser.go.orig":
+		return true // permit but should be ignored by ParseDir
+	}
+	return false
+}
+
+func dirFilter(f os.FileInfo) bool { return nameFilter(f.Name()) }
+
+func TestParseDir(t *testing.T) {
+	path := "."
+	pkgs, err := ParseDir(fset, path, dirFilter, 0)
+	if err != nil {
+		t.Fatalf("ParseDir(%s): %v", path, err)
+	}
+	if n := len(pkgs); n != 1 {
+		t.Errorf("got %d packages; want 1", n)
+	}
+	pkg := pkgs["parser"]
+	if pkg == nil {
+		t.Errorf(`package "parser" not found`)
+		return
+	}
+	if n := len(pkg.Files); n != 3 {
+		t.Errorf("got %d package files; want 3", n)
+	}
+	for filename := range pkg.Files {
+		if !nameFilter(filename) {
+			t.Errorf("unexpected package file: %s", filename)
+		}
+	}
+}
+
+func TestParseExpr(t *testing.T) {
+	// just kicking the tires:
+	// a valid arithmetic expression
+	src := "a + b"
+	x, err := ParseExpr(src)
+	if err != nil {
+		t.Fatalf("ParseExpr(%s): %v", src, err)
+	}
+	// sanity check
+	if _, ok := x.(*ast.BinaryExpr); !ok {
+		t.Errorf("ParseExpr(%s): got %T, want *ast.BinaryExpr", src, x)
+	}
+
+	// a valid type expression
+	src = "struct{x *int}"
+	x, err = ParseExpr(src)
+	if err != nil {
+		t.Fatalf("ParseExpr(%s): %v", src, err)
+	}
+	// sanity check
+	if _, ok := x.(*ast.StructType); !ok {
+		t.Errorf("ParseExpr(%s): got %T, want *ast.StructType", src, x)
+	}
+
+	// an invalid expression
+	src = "a + *"
+	_, err = ParseExpr(src)
+	if err == nil {
+		t.Fatalf("ParseExpr(%s): got no error", src)
+	}
+
+	// a valid expression followed by extra tokens is invalid
+	src = "a[i] := x"
+	_, err = ParseExpr(src)
+	if err == nil {
+		t.Fatalf("ParseExpr(%s): got no error", src)
+	}
+
+	// ParseExpr must not crash
+	for _, src := range valids {
+		ParseExpr(src)
+	}
+}
+
+func TestColonEqualsScope(t *testing.T) {
+	f, err := ParseFile(fset, "", `package p; func f() { x, y, z := x, y, z }`, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// RHS refers to undefined globals; LHS does not.
+	as := f.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.AssignStmt)
+	for _, v := range as.Rhs {
+		id := v.(*ast.Ident)
+		if id.Obj != nil {
+			t.Errorf("rhs %s has Obj, should not", id.Name)
+		}
+	}
+	for _, v := range as.Lhs {
+		id := v.(*ast.Ident)
+		if id.Obj == nil {
+			t.Errorf("lhs %s does not have Obj, should", id.Name)
+		}
+	}
+}
+
+func TestVarScope(t *testing.T) {
+	f, err := ParseFile(fset, "", `package p; func f() { var x, y, z = x, y, z }`, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// RHS refers to undefined globals; LHS does not.
+	as := f.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.DeclStmt).Decl.(*ast.GenDecl).Specs[0].(*ast.ValueSpec)
+	for _, v := range as.Values {
+		id := v.(*ast.Ident)
+		if id.Obj != nil {
+			t.Errorf("rhs %s has Obj, should not", id.Name)
+		}
+	}
+	for _, id := range as.Names {
+		if id.Obj == nil {
+			t.Errorf("lhs %s does not have Obj, should", id.Name)
+		}
+	}
+}
+
+func TestObjects(t *testing.T) {
+	const src = `
+package p
+import fmt "fmt"
+const pi = 3.14
+type T struct{}
+var x int
+func f() { L: }
+`
+
+	f, err := ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	objects := map[string]ast.ObjKind{
+		"p":   ast.Bad, // not in a scope
+		"fmt": ast.Bad, // not resolved yet
+		"pi":  ast.Con,
+		"T":   ast.Typ,
+		"x":   ast.Var,
+		"int": ast.Bad, // not resolved yet
+		"f":   ast.Fun,
+		"L":   ast.Lbl,
+	}
+
+	ast.Inspect(f, func(n ast.Node) bool {
+		if ident, ok := n.(*ast.Ident); ok {
+			obj := ident.Obj
+			if obj == nil {
+				if objects[ident.Name] != ast.Bad {
+					t.Errorf("no object for %s", ident.Name)
+				}
+				return true
+			}
+			if obj.Name != ident.Name {
+				t.Errorf("names don't match: obj.Name = %s, ident.Name = %s", obj.Name, ident.Name)
+			}
+			kind := objects[ident.Name]
+			if obj.Kind != kind {
+				t.Errorf("%s: obj.Kind = %s; want %s", ident.Name, obj.Kind, kind)
+			}
+		}
+		return true
+	})
+}
+
+func TestUnresolved(t *testing.T) {
+	f, err := ParseFile(fset, "", `
+package p
+//
+func f1a(int)
+func f2a(byte, int, float)
+func f3a(a, b int, c float)
+func f4a(...complex)
+func f5a(a s1a, b ...complex)
+//
+func f1b(*int)
+func f2b([]byte, (int), *float)
+func f3b(a, b *int, c []float)
+func f4b(...*complex)
+func f5b(a s1a, b ...[]complex)
+//
+type s1a struct { int }
+type s2a struct { byte; int; s1a }
+type s3a struct { a, b int; c float }
+//
+type s1b struct { *int }
+type s2b struct { byte; int; *float }
+type s3b struct { a, b *s3b; c []float }
+`, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	want := "int " + // f1a
+		"byte int float " + // f2a
+		"int float " + // f3a
+		"complex " + // f4a
+		"complex " + // f5a
+		//
+		"int " + // f1b
+		"byte int float " + // f2b
+		"int float " + // f3b
+		"complex " + // f4b
+		"complex " + // f5b
+		//
+		"int " + // s1a
+		"byte int " + // s2a
+		"int float " + // s3a
+		//
+		"int " + // s1a
+		"byte int float " + // s2a
+		"float " // s3a
+
+	// collect unresolved identifiers
+	var buf bytes.Buffer
+	for _, u := range f.Unresolved {
+		buf.WriteString(u.Name)
+		buf.WriteByte(' ')
+	}
+	got := buf.String()
+
+	if got != want {
+		t.Errorf("\ngot:  %s\nwant: %s", got, want)
+	}
+}
+
+var imports = map[string]bool{
+	`"a"`:        true,
+	"`a`":        true,
+	`"a/b"`:      true,
+	`"a.b"`:      true,
+	`"m\x61th"`:  true,
+	`"greek/αβ"`: true,
+	`""`:         false,
+
+	// Each of these pairs tests both `` vs "" strings
+	// and also use of invalid characters spelled out as
+	// escape sequences and written directly.
+	// For example `"\x00"` tests import "\x00"
+	// while "`\x00`" tests import `<actual-NUL-byte>`.
+	`"\x00"`:     false,
+	"`\x00`":     false,
+	`"\x7f"`:     false,
+	"`\x7f`":     false,
+	`"a!"`:       false,
+	"`a!`":       false,
+	`"a b"`:      false,
+	"`a b`":      false,
+	`"a\\b"`:     false,
+	"`a\\b`":     false,
+	"\"`a`\"":    false,
+	"`\"a\"`":    false,
+	`"\x80\x80"`: false,
+	"`\x80\x80`": false,
+	`"\xFFFD"`:   false,
+	"`\xFFFD`":   false,
+}
+
+func TestImports(t *testing.T) {
+	for path, isValid := range imports {
+		src := fmt.Sprintf("package p; import %s", path)
+		_, err := ParseFile(fset, "", src, 0)
+		switch {
+		case err != nil && isValid:
+			t.Errorf("ParseFile(%s): got %v; expected no error", src, err)
+		case err == nil && !isValid:
+			t.Errorf("ParseFile(%s): got no error; expected one", src)
+		}
+	}
+}
+
+func TestCommentGroups(t *testing.T) {
+	f, err := ParseFile(fset, "", `
+package p /* 1a */ /* 1b */      /* 1c */ // 1d
+/* 2a
+*/
+// 2b
+const pi = 3.1415
+/* 3a */ // 3b
+/* 3c */ const e = 2.7182
+
+// Example from issue 3139
+func ExampleCount() {
+	fmt.Println(strings.Count("cheese", "e"))
+	fmt.Println(strings.Count("five", "")) // before & after each rune
+	// Output:
+	// 3
+	// 5
+}
+`, ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+	expected := [][]string{
+		{"/* 1a */", "/* 1b */", "/* 1c */", "// 1d"},
+		{"/* 2a\n*/", "// 2b"},
+		{"/* 3a */", "// 3b", "/* 3c */"},
+		{"// Example from issue 3139"},
+		{"// before & after each rune"},
+		{"// Output:", "// 3", "// 5"},
+	}
+	if len(f.Comments) != len(expected) {
+		t.Fatalf("got %d comment groups; expected %d", len(f.Comments), len(expected))
+	}
+	for i, exp := range expected {
+		got := f.Comments[i].List
+		if len(got) != len(exp) {
+			t.Errorf("got %d comments in group %d; expected %d", len(got), i, len(exp))
+			continue
+		}
+		for j, exp := range exp {
+			got := got[j].Text
+			if got != exp {
+				t.Errorf("got %q in group %d; expected %q", got, i, exp)
+			}
+		}
+	}
+}
+
+func getField(file *ast.File, fieldname string) *ast.Field {
+	parts := strings.Split(fieldname, ".")
+	for _, d := range file.Decls {
+		if d, ok := d.(*ast.GenDecl); ok && d.Tok == token.TYPE {
+			for _, s := range d.Specs {
+				if s, ok := s.(*ast.TypeSpec); ok && s.Name.Name == parts[0] {
+					if s, ok := s.Type.(*ast.StructType); ok {
+						for _, f := range s.Fields.List {
+							for _, name := range f.Names {
+								if name.Name == parts[1] {
+									return f
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// Don't use ast.CommentGroup.Text() - we want to see exact comment text.
+func commentText(c *ast.CommentGroup) string {
+	var buf bytes.Buffer
+	if c != nil {
+		for _, c := range c.List {
+			buf.WriteString(c.Text)
+		}
+	}
+	return buf.String()
+}
+
+func checkFieldComments(t *testing.T, file *ast.File, fieldname, lead, line string) {
+	f := getField(file, fieldname)
+	if f == nil {
+		t.Fatalf("field not found: %s", fieldname)
+	}
+	if got := commentText(f.Doc); got != lead {
+		t.Errorf("got lead comment %q; expected %q", got, lead)
+	}
+	if got := commentText(f.Comment); got != line {
+		t.Errorf("got line comment %q; expected %q", got, line)
+	}
+}
+
+func TestLeadAndLineComments(t *testing.T) {
+	f, err := ParseFile(fset, "", `
+package p
+type T struct {
+	/* F1 lead comment */
+	//
+	F1 int  /* F1 */ // line comment
+	// F2 lead
+	// comment
+	F2 int  // F2 line comment
+	// f3 lead comment
+	f3 int  // f3 line comment
+}
+`, ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+	checkFieldComments(t, f, "T.F1", "/* F1 lead comment *///", "/* F1 */// line comment")
+	checkFieldComments(t, f, "T.F2", "// F2 lead// comment", "// F2 line comment")
+	checkFieldComments(t, f, "T.f3", "// f3 lead comment", "// f3 line comment")
+	ast.FileExports(f)
+	checkFieldComments(t, f, "T.F1", "/* F1 lead comment *///", "/* F1 */// line comment")
+	checkFieldComments(t, f, "T.F2", "// F2 lead// comment", "// F2 line comment")
+	if getField(f, "T.f3") != nil {
+		t.Error("not expected to find T.f3")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/parser/performance_test.go b/third_party/gofrontend/libgo/go/go/parser/performance_test.go
new file mode 100644
index 0000000..f2732c0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/parser/performance_test.go
@@ -0,0 +1,30 @@
+// 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 parser
+
+import (
+	"go/token"
+	"io/ioutil"
+	"testing"
+)
+
+var src = readFile("parser.go")
+
+func readFile(filename string) []byte {
+	data, err := ioutil.ReadFile(filename)
+	if err != nil {
+		panic(err)
+	}
+	return data
+}
+
+func BenchmarkParse(b *testing.B) {
+	b.SetBytes(int64(len(src)))
+	for i := 0; i < b.N; i++ {
+		if _, err := ParseFile(token.NewFileSet(), "", src, ParseComments); err != nil {
+			b.Fatalf("benchmark failed due to parse error: %s", err)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/parser/short_test.go b/third_party/gofrontend/libgo/go/go/parser/short_test.go
new file mode 100644
index 0000000..b794060
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/parser/short_test.go
@@ -0,0 +1,98 @@
+// 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.
+
+// This file contains test cases for short valid and invalid programs.
+
+package parser
+
+import "testing"
+
+var valids = []string{
+	"package p\n",
+	`package p;`,
+	`package p; import "fmt"; func f() { fmt.Println("Hello, World!") };`,
+	`package p; func f() { if f(T{}) {} };`,
+	`package p; func f() { _ = <-chan int(nil) };`,
+	`package p; func f() { _ = (<-chan int)(nil) };`,
+	`package p; func f() { _ = (<-chan <-chan int)(nil) };`,
+	`package p; func f() { _ = <-chan <-chan <-chan <-chan <-int(nil) };`,
+	`package p; func f(func() func() func());`,
+	`package p; func f(...T);`,
+	`package p; func f(float, ...int);`,
+	`package p; func f(x int, a ...int) { f(0, a...); f(1, a...,) };`,
+	`package p; func f(int,) {};`,
+	`package p; func f(...int,) {};`,
+	`package p; func f(x ...int,) {};`,
+	`package p; type T []int; var a []bool; func f() { if a[T{42}[0]] {} };`,
+	`package p; type T []int; func g(int) bool { return true }; func f() { if g(T{42}[0]) {} };`,
+	`package p; type T []int; func f() { for _ = range []int{T{42}[0]} {} };`,
+	`package p; var a = T{{1, 2}, {3, 4}}`,
+	`package p; func f() { select { case <- c: case c <- d: case c <- <- d: case <-c <- d: } };`,
+	`package p; func f() { select { case x := (<-c): } };`,
+	`package p; func f() { if ; true {} };`,
+	`package p; func f() { switch ; {} };`,
+	`package p; func f() { for _ = range "foo" + "bar" {} };`,
+	`package p; func f() { var s []int; g(s[:], s[i:], s[:j], s[i:j], s[i:j:k], s[:j:k]) };`,
+	`package p; var ( _ = (struct {*T}).m; _ = (interface {T}).m )`,
+}
+
+func TestValid(t *testing.T) {
+	for _, src := range valids {
+		checkErrors(t, src, src)
+	}
+}
+
+var invalids = []string{
+	`foo /* ERROR "expected 'package'" */ !`,
+	`package p; func f() { if { /* ERROR "expected operand" */ } };`,
+	`package p; func f() { if ; { /* ERROR "expected operand" */ } };`,
+	`package p; func f() { if f(); { /* ERROR "expected operand" */ } };`,
+	`package p; func f() { if _ /* ERROR "expected boolean expression" */ = range x; true {} };`,
+	`package p; func f() { switch _ /* ERROR "expected switch expression" */ = range x; true {} };`,
+	`package p; func f() { for _ = range x ; /* ERROR "expected '{'" */ ; {} };`,
+	`package p; func f() { for ; ; _ = range /* ERROR "expected operand" */ x {} };`,
+	`package p; func f() { for ; _ /* ERROR "expected boolean or range expression" */ = range x ; {} };`,
+	`package p; func f() { switch t /* ERROR "expected switch expression" */ = t.(type) {} };`,
+	`package p; func f() { switch t /* ERROR "expected switch expression" */ , t = t.(type) {} };`,
+	`package p; func f() { switch t /* ERROR "expected switch expression" */ = t.(type), t {} };`,
+	`package p; var a = [ /* ERROR "expected expression" */ 1]int;`,
+	`package p; var a = [ /* ERROR "expected expression" */ ...]int;`,
+	`package p; var a = struct /* ERROR "expected expression" */ {}`,
+	`package p; var a = func /* ERROR "expected expression" */ ();`,
+	`package p; var a = interface /* ERROR "expected expression" */ {}`,
+	`package p; var a = [ /* ERROR "expected expression" */ ]int`,
+	`package p; var a = map /* ERROR "expected expression" */ [int]int`,
+	`package p; var a = chan /* ERROR "expected expression" */ int;`,
+	`package p; var a = []int{[ /* ERROR "expected expression" */ ]int};`,
+	`package p; var a = ( /* ERROR "expected expression" */ []int);`,
+	`package p; var a = a[[ /* ERROR "expected expression" */ ]int:[]int];`,
+	`package p; var a = <- /* ERROR "expected expression" */ chan int;`,
+	`package p; func f() { select { case _ <- chan /* ERROR "expected expression" */ int: } };`,
+	`package p; func f() { _ = (<-<- /* ERROR "expected 'chan'" */ chan int)(nil) };`,
+	`package p; func f() { _ = (<-chan<-chan<-chan<-chan<-chan<- /* ERROR "expected channel type" */ int)(nil) };`,
+	`package p; func f() { var t []int; t /* ERROR "expected identifier on left side of :=" */ [0] := 0 };`,
+	`package p; func f() { if x := g(); x = /* ERROR "expected '=='" */ 0 {}};`,
+	`package p; func f() { _ = x = /* ERROR "expected '=='" */ 0 {}};`,
+	`package p; func f() { _ = 1 == func()int { var x bool; x = x = /* ERROR "expected '=='" */ true; return x }() };`,
+	`package p; func f() { var s []int; _ = s[] /* ERROR "expected operand" */ };`,
+	`package p; func f() { var s []int; _ = s[i:j: /* ERROR "3rd index required" */ ] };`,
+	`package p; func f() { var s []int; _ = s[i: /* ERROR "2nd index required" */ :k] };`,
+	`package p; func f() { var s []int; _ = s[i: /* ERROR "2nd index required" */ :] };`,
+	`package p; func f() { var s []int; _ = s[: /* ERROR "2nd index required" */ :] };`,
+	`package p; func f() { var s []int; _ = s[: /* ERROR "2nd index required" */ ::] };`,
+	`package p; func f() { var s []int; _ = s[i:j:k: /* ERROR "expected ']'" */ l] };`,
+	`package p; func f() { for x /* ERROR "boolean or range expression" */ = []string {} }`,
+	`package p; func f() { for x /* ERROR "boolean or range expression" */ := []string {} }`,
+	`package p; func f() { for i /* ERROR "boolean or range expression" */ , x = []string {} }`,
+	`package p; func f() { for i /* ERROR "boolean or range expression" */ , x := []string {} }`,
+	`package p; func f() { go f /* ERROR HERE "function must be invoked" */ }`,
+	`package p; func f() { defer func() {} /* ERROR HERE "function must be invoked" */ }`,
+	`package p; func f() { go func() { func() { f(x func /* ERROR "expected '\)'" */ (){}) } } }`,
+}
+
+func TestInvalid(t *testing.T) {
+	for _, src := range invalids {
+		checkErrors(t, src, src)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/parser/testdata/commas.src b/third_party/gofrontend/libgo/go/go/parser/testdata/commas.src
new file mode 100644
index 0000000..af6e706
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/parser/testdata/commas.src
@@ -0,0 +1,19 @@
+// 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.
+
+// Test case for error messages/parser synchronization
+// after missing commas.
+
+package p
+
+var _ = []int{
+	0 /* ERROR "missing ','" */
+}
+
+var _ = []int{
+	0,
+	1,
+	2,
+	3 /* ERROR "missing ','" */
+}
diff --git a/third_party/gofrontend/libgo/go/go/parser/testdata/issue3106.src b/third_party/gofrontend/libgo/go/go/parser/testdata/issue3106.src
new file mode 100644
index 0000000..82796c8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/parser/testdata/issue3106.src
@@ -0,0 +1,46 @@
+// 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.
+
+// Test case for issue 3106: Better synchronization of
+// parser after certain syntax errors.
+
+package main
+
+func f() {
+	var m Mutex
+	c := MakeCond(&m)
+	percent := 0
+	const step = 10
+	for i := 0; i < 5; i++ {
+		go func() {
+			for {
+				// Emulates some useful work.
+				time.Sleep(1e8)
+				m.Lock()
+				defer
+				if /* ERROR "expected operand, found 'if'" */ percent == 100 {
+					m.Unlock()
+					break
+				}
+				percent++
+				if percent % step == 0 {
+					//c.Signal()
+				}
+				m.Unlock()
+			}
+		}()
+	}
+	for {
+		m.Lock()
+		if percent == 0 || percent % step != 0 {
+			c.Wait()
+		}
+		fmt.Print(",")
+		if percent == 100 {
+			m.Unlock()
+			break
+		}
+		m.Unlock()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/nodes.go b/third_party/gofrontend/libgo/go/go/printer/nodes.go
new file mode 100644
index 0000000..04b5f1a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/nodes.go
@@ -0,0 +1,1599 @@
+// 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.
+
+// This file implements printing of AST nodes; specifically
+// expressions, statements, declarations, and files. It uses
+// the print functionality implemented in printer.go.
+
+package printer
+
+import (
+	"bytes"
+	"go/ast"
+	"go/token"
+	"unicode/utf8"
+)
+
+// Formatting issues:
+// - better comment formatting for /*-style comments at the end of a line (e.g. a declaration)
+//   when the comment spans multiple lines; if such a comment is just two lines, formatting is
+//   not idempotent
+// - formatting of expression lists
+// - should use blank instead of tab to separate one-line function bodies from
+//   the function header unless there is a group of consecutive one-liners
+
+// ----------------------------------------------------------------------------
+// Common AST nodes.
+
+// Print as many newlines as necessary (but at least min newlines) to get to
+// the current line. ws is printed before the first line break. If newSection
+// is set, the first line break is printed as formfeed. Returns true if any
+// line break was printed; returns false otherwise.
+//
+// TODO(gri): linebreak may add too many lines if the next statement at "line"
+//            is preceded by comments because the computation of n assumes
+//            the current position before the comment and the target position
+//            after the comment. Thus, after interspersing such comments, the
+//            space taken up by them is not considered to reduce the number of
+//            linebreaks. At the moment there is no easy way to know about
+//            future (not yet interspersed) comments in this function.
+//
+func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (printedBreak bool) {
+	n := nlimit(line - p.pos.Line)
+	if n < min {
+		n = min
+	}
+	if n > 0 {
+		p.print(ws)
+		if newSection {
+			p.print(formfeed)
+			n--
+		}
+		for ; n > 0; n-- {
+			p.print(newline)
+		}
+		printedBreak = true
+	}
+	return
+}
+
+// setComment sets g as the next comment if g != nil and if node comments
+// are enabled - this mode is used when printing source code fragments such
+// as exports only. It assumes that there is no pending comment in p.comments
+// and at most one pending comment in the p.comment cache.
+func (p *printer) setComment(g *ast.CommentGroup) {
+	if g == nil || !p.useNodeComments {
+		return
+	}
+	if p.comments == nil {
+		// initialize p.comments lazily
+		p.comments = make([]*ast.CommentGroup, 1)
+	} else if p.cindex < len(p.comments) {
+		// for some reason there are pending comments; this
+		// should never happen - handle gracefully and flush
+		// all comments up to g, ignore anything after that
+		p.flush(p.posFor(g.List[0].Pos()), token.ILLEGAL)
+		p.comments = p.comments[0:1]
+		// in debug mode, report error
+		p.internalError("setComment found pending comments")
+	}
+	p.comments[0] = g
+	p.cindex = 0
+	// don't overwrite any pending comment in the p.comment cache
+	// (there may be a pending comment when a line comment is
+	// immediately followed by a lead comment with no other
+	// tokens between)
+	if p.commentOffset == infinity {
+		p.nextComment() // get comment ready for use
+	}
+}
+
+type exprListMode uint
+
+const (
+	commaTerm exprListMode = 1 << iota // list is optionally terminated by a comma
+	noIndent                           // no extra indentation in multi-line lists
+)
+
+// If indent is set, a multi-line identifier list is indented after the
+// first linebreak encountered.
+func (p *printer) identList(list []*ast.Ident, indent bool) {
+	// convert into an expression list so we can re-use exprList formatting
+	xlist := make([]ast.Expr, len(list))
+	for i, x := range list {
+		xlist[i] = x
+	}
+	var mode exprListMode
+	if !indent {
+		mode = noIndent
+	}
+	p.exprList(token.NoPos, xlist, 1, mode, token.NoPos)
+}
+
+// Print a list of expressions. If the list spans multiple
+// source lines, the original line breaks are respected between
+// expressions.
+//
+// TODO(gri) Consider rewriting this to be independent of []ast.Expr
+//           so that we can use the algorithm for any kind of list
+//           (e.g., pass list via a channel over which to range).
+func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, next0 token.Pos) {
+	if len(list) == 0 {
+		return
+	}
+
+	prev := p.posFor(prev0)
+	next := p.posFor(next0)
+	line := p.lineFor(list[0].Pos())
+	endLine := p.lineFor(list[len(list)-1].End())
+
+	if prev.IsValid() && prev.Line == line && line == endLine {
+		// all list entries on a single line
+		for i, x := range list {
+			if i > 0 {
+				// use position of expression following the comma as
+				// comma position for correct comment placement
+				p.print(x.Pos(), token.COMMA, blank)
+			}
+			p.expr0(x, depth)
+		}
+		return
+	}
+
+	// list entries span multiple lines;
+	// use source code positions to guide line breaks
+
+	// don't add extra indentation if noIndent is set;
+	// i.e., pretend that the first line is already indented
+	ws := ignore
+	if mode&noIndent == 0 {
+		ws = indent
+	}
+
+	// the first linebreak is always a formfeed since this section must not
+	// depend on any previous formatting
+	prevBreak := -1 // index of last expression that was followed by a linebreak
+	if prev.IsValid() && prev.Line < line && p.linebreak(line, 0, ws, true) {
+		ws = ignore
+		prevBreak = 0
+	}
+
+	// initialize expression/key size: a zero value indicates expr/key doesn't fit on a single line
+	size := 0
+
+	// print all list elements
+	for i, x := range list {
+		prevLine := line
+		line = p.lineFor(x.Pos())
+
+		// determine if the next linebreak, if any, needs to use formfeed:
+		// in general, use the entire node size to make the decision; for
+		// key:value expressions, use the key size
+		// TODO(gri) for a better result, should probably incorporate both
+		//           the key and the node size into the decision process
+		useFF := true
+
+		// determine element size: all bets are off if we don't have
+		// position information for the previous and next token (likely
+		// generated code - simply ignore the size in this case by setting
+		// it to 0)
+		prevSize := size
+		const infinity = 1e6 // larger than any source line
+		size = p.nodeSize(x, infinity)
+		pair, isPair := x.(*ast.KeyValueExpr)
+		if size <= infinity && prev.IsValid() && next.IsValid() {
+			// x fits on a single line
+			if isPair {
+				size = p.nodeSize(pair.Key, infinity) // size <= infinity
+			}
+		} else {
+			// size too large or we don't have good layout information
+			size = 0
+		}
+
+		// if the previous line and the current line had single-
+		// line-expressions and the key sizes are small or the
+		// the ratio between the key sizes does not exceed a
+		// threshold, align columns and do not use formfeed
+		if prevSize > 0 && size > 0 {
+			const smallSize = 20
+			if prevSize <= smallSize && size <= smallSize {
+				useFF = false
+			} else {
+				const r = 4 // threshold
+				ratio := float64(size) / float64(prevSize)
+				useFF = ratio <= 1.0/r || r <= ratio
+			}
+		}
+
+		if i > 0 {
+			needsLinebreak := prevLine < line && prevLine > 0 && line > 0
+			// use position of expression following the comma as
+			// comma position for correct comment placement, but
+			// only if the expression is on the same line
+			if !needsLinebreak {
+				p.print(x.Pos())
+			}
+			p.print(token.COMMA)
+			needsBlank := true
+			if needsLinebreak {
+				// lines are broken using newlines so comments remain aligned
+				// unless forceFF is set or there are multiple expressions on
+				// the same line in which case formfeed is used
+				if p.linebreak(line, 0, ws, useFF || prevBreak+1 < i) {
+					ws = ignore
+					prevBreak = i
+					needsBlank = false // we got a line break instead
+				}
+			}
+			if needsBlank {
+				p.print(blank)
+			}
+		}
+
+		if isPair && size > 0 && len(list) > 1 {
+			// we have a key:value expression that fits onto one line and
+			// is in a list with more then one entry: use a column for the
+			// key such that consecutive entries can align if possible
+			p.expr(pair.Key)
+			p.print(pair.Colon, token.COLON, vtab)
+			p.expr(pair.Value)
+		} else {
+			p.expr0(x, depth)
+		}
+	}
+
+	if mode&commaTerm != 0 && next.IsValid() && p.pos.Line < next.Line {
+		// print a terminating comma if the next token is on a new line
+		p.print(token.COMMA)
+		if ws == ignore && mode&noIndent == 0 {
+			// unindent if we indented
+			p.print(unindent)
+		}
+		p.print(formfeed) // terminating comma needs a line break to look good
+		return
+	}
+
+	if ws == ignore && mode&noIndent == 0 {
+		// unindent if we indented
+		p.print(unindent)
+	}
+}
+
+func (p *printer) parameters(fields *ast.FieldList) {
+	p.print(fields.Opening, token.LPAREN)
+	if len(fields.List) > 0 {
+		prevLine := p.lineFor(fields.Opening)
+		ws := indent
+		for i, par := range fields.List {
+			// determine par begin and end line (may be different
+			// if there are multiple parameter names for this par
+			// or the type is on a separate line)
+			var parLineBeg int
+			if len(par.Names) > 0 {
+				parLineBeg = p.lineFor(par.Names[0].Pos())
+			} else {
+				parLineBeg = p.lineFor(par.Type.Pos())
+			}
+			var parLineEnd = p.lineFor(par.Type.End())
+			// separating "," if needed
+			needsLinebreak := 0 < prevLine && prevLine < parLineBeg
+			if i > 0 {
+				// use position of parameter following the comma as
+				// comma position for correct comma placement, but
+				// only if the next parameter is on the same line
+				if !needsLinebreak {
+					p.print(par.Pos())
+				}
+				p.print(token.COMMA)
+			}
+			// separator if needed (linebreak or blank)
+			if needsLinebreak && p.linebreak(parLineBeg, 0, ws, true) {
+				// break line if the opening "(" or previous parameter ended on a different line
+				ws = ignore
+			} else if i > 0 {
+				p.print(blank)
+			}
+			// parameter names
+			if len(par.Names) > 0 {
+				// Very subtle: If we indented before (ws == ignore), identList
+				// won't indent again. If we didn't (ws == indent), identList will
+				// indent if the identList spans multiple lines, and it will outdent
+				// again at the end (and still ws == indent). Thus, a subsequent indent
+				// by a linebreak call after a type, or in the next multi-line identList
+				// will do the right thing.
+				p.identList(par.Names, ws == indent)
+				p.print(blank)
+			}
+			// parameter type
+			p.expr(stripParensAlways(par.Type))
+			prevLine = parLineEnd
+		}
+		// if the closing ")" is on a separate line from the last parameter,
+		// print an additional "," and line break
+		if closing := p.lineFor(fields.Closing); 0 < prevLine && prevLine < closing {
+			p.print(token.COMMA)
+			p.linebreak(closing, 0, ignore, true)
+		}
+		// unindent if we indented
+		if ws == ignore {
+			p.print(unindent)
+		}
+	}
+	p.print(fields.Closing, token.RPAREN)
+}
+
+func (p *printer) signature(params, result *ast.FieldList) {
+	if params != nil {
+		p.parameters(params)
+	} else {
+		p.print(token.LPAREN, token.RPAREN)
+	}
+	n := result.NumFields()
+	if n > 0 {
+		// result != nil
+		p.print(blank)
+		if n == 1 && result.List[0].Names == nil {
+			// single anonymous result; no ()'s
+			p.expr(stripParensAlways(result.List[0].Type))
+			return
+		}
+		p.parameters(result)
+	}
+}
+
+func identListSize(list []*ast.Ident, maxSize int) (size int) {
+	for i, x := range list {
+		if i > 0 {
+			size += len(", ")
+		}
+		size += utf8.RuneCountInString(x.Name)
+		if size >= maxSize {
+			break
+		}
+	}
+	return
+}
+
+func (p *printer) isOneLineFieldList(list []*ast.Field) bool {
+	if len(list) != 1 {
+		return false // allow only one field
+	}
+	f := list[0]
+	if f.Tag != nil || f.Comment != nil {
+		return false // don't allow tags or comments
+	}
+	// only name(s) and type
+	const maxSize = 30 // adjust as appropriate, this is an approximate value
+	namesSize := identListSize(f.Names, maxSize)
+	if namesSize > 0 {
+		namesSize = 1 // blank between names and types
+	}
+	typeSize := p.nodeSize(f.Type, maxSize)
+	return namesSize+typeSize <= maxSize
+}
+
+func (p *printer) setLineComment(text string) {
+	p.setComment(&ast.CommentGroup{List: []*ast.Comment{{Slash: token.NoPos, Text: text}}})
+}
+
+func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {
+	lbrace := fields.Opening
+	list := fields.List
+	rbrace := fields.Closing
+	hasComments := isIncomplete || p.commentBefore(p.posFor(rbrace))
+	srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.lineFor(lbrace) == p.lineFor(rbrace)
+
+	if !hasComments && srcIsOneLine {
+		// possibly a one-line struct/interface
+		if len(list) == 0 {
+			// no blank between keyword and {} in this case
+			p.print(lbrace, token.LBRACE, rbrace, token.RBRACE)
+			return
+		} else if isStruct && p.isOneLineFieldList(list) { // for now ignore interfaces
+			// small enough - print on one line
+			// (don't use identList and ignore source line breaks)
+			p.print(lbrace, token.LBRACE, blank)
+			f := list[0]
+			for i, x := range f.Names {
+				if i > 0 {
+					// no comments so no need for comma position
+					p.print(token.COMMA, blank)
+				}
+				p.expr(x)
+			}
+			if len(f.Names) > 0 {
+				p.print(blank)
+			}
+			p.expr(f.Type)
+			p.print(blank, rbrace, token.RBRACE)
+			return
+		}
+	}
+	// hasComments || !srcIsOneLine
+
+	p.print(blank, lbrace, token.LBRACE, indent)
+	if hasComments || len(list) > 0 {
+		p.print(formfeed)
+	}
+
+	if isStruct {
+
+		sep := vtab
+		if len(list) == 1 {
+			sep = blank
+		}
+		var line int
+		for i, f := range list {
+			if i > 0 {
+				p.linebreak(p.lineFor(f.Pos()), 1, ignore, p.linesFrom(line) > 0)
+			}
+			extraTabs := 0
+			p.setComment(f.Doc)
+			p.recordLine(&line)
+			if len(f.Names) > 0 {
+				// named fields
+				p.identList(f.Names, false)
+				p.print(sep)
+				p.expr(f.Type)
+				extraTabs = 1
+			} else {
+				// anonymous field
+				p.expr(f.Type)
+				extraTabs = 2
+			}
+			if f.Tag != nil {
+				if len(f.Names) > 0 && sep == vtab {
+					p.print(sep)
+				}
+				p.print(sep)
+				p.expr(f.Tag)
+				extraTabs = 0
+			}
+			if f.Comment != nil {
+				for ; extraTabs > 0; extraTabs-- {
+					p.print(sep)
+				}
+				p.setComment(f.Comment)
+			}
+		}
+		if isIncomplete {
+			if len(list) > 0 {
+				p.print(formfeed)
+			}
+			p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment
+			p.setLineComment("// contains filtered or unexported fields")
+		}
+
+	} else { // interface
+
+		var line int
+		for i, f := range list {
+			if i > 0 {
+				p.linebreak(p.lineFor(f.Pos()), 1, ignore, p.linesFrom(line) > 0)
+			}
+			p.setComment(f.Doc)
+			p.recordLine(&line)
+			if ftyp, isFtyp := f.Type.(*ast.FuncType); isFtyp {
+				// method
+				p.expr(f.Names[0])
+				p.signature(ftyp.Params, ftyp.Results)
+			} else {
+				// embedded interface
+				p.expr(f.Type)
+			}
+			p.setComment(f.Comment)
+		}
+		if isIncomplete {
+			if len(list) > 0 {
+				p.print(formfeed)
+			}
+			p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment
+			p.setLineComment("// contains filtered or unexported methods")
+		}
+
+	}
+	p.print(unindent, formfeed, rbrace, token.RBRACE)
+}
+
+// ----------------------------------------------------------------------------
+// Expressions
+
+func walkBinary(e *ast.BinaryExpr) (has4, has5 bool, maxProblem int) {
+	switch e.Op.Precedence() {
+	case 4:
+		has4 = true
+	case 5:
+		has5 = true
+	}
+
+	switch l := e.X.(type) {
+	case *ast.BinaryExpr:
+		if l.Op.Precedence() < e.Op.Precedence() {
+			// parens will be inserted.
+			// pretend this is an *ast.ParenExpr and do nothing.
+			break
+		}
+		h4, h5, mp := walkBinary(l)
+		has4 = has4 || h4
+		has5 = has5 || h5
+		if maxProblem < mp {
+			maxProblem = mp
+		}
+	}
+
+	switch r := e.Y.(type) {
+	case *ast.BinaryExpr:
+		if r.Op.Precedence() <= e.Op.Precedence() {
+			// parens will be inserted.
+			// pretend this is an *ast.ParenExpr and do nothing.
+			break
+		}
+		h4, h5, mp := walkBinary(r)
+		has4 = has4 || h4
+		has5 = has5 || h5
+		if maxProblem < mp {
+			maxProblem = mp
+		}
+
+	case *ast.StarExpr:
+		if e.Op == token.QUO { // `*/`
+			maxProblem = 5
+		}
+
+	case *ast.UnaryExpr:
+		switch e.Op.String() + r.Op.String() {
+		case "/*", "&&", "&^":
+			maxProblem = 5
+		case "++", "--":
+			if maxProblem < 4 {
+				maxProblem = 4
+			}
+		}
+	}
+	return
+}
+
+func cutoff(e *ast.BinaryExpr, depth int) int {
+	has4, has5, maxProblem := walkBinary(e)
+	if maxProblem > 0 {
+		return maxProblem + 1
+	}
+	if has4 && has5 {
+		if depth == 1 {
+			return 5
+		}
+		return 4
+	}
+	if depth == 1 {
+		return 6
+	}
+	return 4
+}
+
+func diffPrec(expr ast.Expr, prec int) int {
+	x, ok := expr.(*ast.BinaryExpr)
+	if !ok || prec != x.Op.Precedence() {
+		return 1
+	}
+	return 0
+}
+
+func reduceDepth(depth int) int {
+	depth--
+	if depth < 1 {
+		depth = 1
+	}
+	return depth
+}
+
+// Format the binary expression: decide the cutoff and then format.
+// Let's call depth == 1 Normal mode, and depth > 1 Compact mode.
+// (Algorithm suggestion by Russ Cox.)
+//
+// The precedences are:
+//	5             *  /  %  <<  >>  &  &^
+//	4             +  -  |  ^
+//	3             ==  !=  <  <=  >  >=
+//	2             &&
+//	1             ||
+//
+// The only decision is whether there will be spaces around levels 4 and 5.
+// There are never spaces at level 6 (unary), and always spaces at levels 3 and below.
+//
+// To choose the cutoff, look at the whole expression but excluding primary
+// expressions (function calls, parenthesized exprs), and apply these rules:
+//
+//	1) If there is a binary operator with a right side unary operand
+//	   that would clash without a space, the cutoff must be (in order):
+//
+//		/*	6
+//		&&	6
+//		&^	6
+//		++	5
+//		--	5
+//
+//         (Comparison operators always have spaces around them.)
+//
+//	2) If there is a mix of level 5 and level 4 operators, then the cutoff
+//	   is 5 (use spaces to distinguish precedence) in Normal mode
+//	   and 4 (never use spaces) in Compact mode.
+//
+//	3) If there are no level 4 operators or no level 5 operators, then the
+//	   cutoff is 6 (always use spaces) in Normal mode
+//	   and 4 (never use spaces) in Compact mode.
+//
+func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int) {
+	prec := x.Op.Precedence()
+	if prec < prec1 {
+		// parenthesis needed
+		// Note: The parser inserts an ast.ParenExpr node; thus this case
+		//       can only occur if the AST is created in a different way.
+		p.print(token.LPAREN)
+		p.expr0(x, reduceDepth(depth)) // parentheses undo one level of depth
+		p.print(token.RPAREN)
+		return
+	}
+
+	printBlank := prec < cutoff
+
+	ws := indent
+	p.expr1(x.X, prec, depth+diffPrec(x.X, prec))
+	if printBlank {
+		p.print(blank)
+	}
+	xline := p.pos.Line // before the operator (it may be on the next line!)
+	yline := p.lineFor(x.Y.Pos())
+	p.print(x.OpPos, x.Op)
+	if xline != yline && xline > 0 && yline > 0 {
+		// at least one line break, but respect an extra empty line
+		// in the source
+		if p.linebreak(yline, 1, ws, true) {
+			ws = ignore
+			printBlank = false // no blank after line break
+		}
+	}
+	if printBlank {
+		p.print(blank)
+	}
+	p.expr1(x.Y, prec+1, depth+1)
+	if ws == ignore {
+		p.print(unindent)
+	}
+}
+
+func isBinary(expr ast.Expr) bool {
+	_, ok := expr.(*ast.BinaryExpr)
+	return ok
+}
+
+func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
+	p.print(expr.Pos())
+
+	switch x := expr.(type) {
+	case *ast.BadExpr:
+		p.print("BadExpr")
+
+	case *ast.Ident:
+		p.print(x)
+
+	case *ast.BinaryExpr:
+		if depth < 1 {
+			p.internalError("depth < 1:", depth)
+			depth = 1
+		}
+		p.binaryExpr(x, prec1, cutoff(x, depth), depth)
+
+	case *ast.KeyValueExpr:
+		p.expr(x.Key)
+		p.print(x.Colon, token.COLON, blank)
+		p.expr(x.Value)
+
+	case *ast.StarExpr:
+		const prec = token.UnaryPrec
+		if prec < prec1 {
+			// parenthesis needed
+			p.print(token.LPAREN)
+			p.print(token.MUL)
+			p.expr(x.X)
+			p.print(token.RPAREN)
+		} else {
+			// no parenthesis needed
+			p.print(token.MUL)
+			p.expr(x.X)
+		}
+
+	case *ast.UnaryExpr:
+		const prec = token.UnaryPrec
+		if prec < prec1 {
+			// parenthesis needed
+			p.print(token.LPAREN)
+			p.expr(x)
+			p.print(token.RPAREN)
+		} else {
+			// no parenthesis needed
+			p.print(x.Op)
+			if x.Op == token.RANGE {
+				// TODO(gri) Remove this code if it cannot be reached.
+				p.print(blank)
+			}
+			p.expr1(x.X, prec, depth)
+		}
+
+	case *ast.BasicLit:
+		p.print(x)
+
+	case *ast.FuncLit:
+		p.expr(x.Type)
+		p.adjBlock(p.distanceFrom(x.Type.Pos()), blank, x.Body)
+
+	case *ast.ParenExpr:
+		if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
+			// don't print parentheses around an already parenthesized expression
+			// TODO(gri) consider making this more general and incorporate precedence levels
+			p.expr0(x.X, reduceDepth(depth)) // parentheses undo one level of depth
+		} else {
+			p.print(token.LPAREN)
+			p.expr0(x.X, reduceDepth(depth)) // parentheses undo one level of depth
+			p.print(x.Rparen, token.RPAREN)
+		}
+
+	case *ast.SelectorExpr:
+		p.expr1(x.X, token.HighestPrec, depth)
+		p.print(token.PERIOD)
+		if line := p.lineFor(x.Sel.Pos()); p.pos.IsValid() && p.pos.Line < line {
+			p.print(indent, newline, x.Sel.Pos(), x.Sel, unindent)
+		} else {
+			p.print(x.Sel.Pos(), x.Sel)
+		}
+
+	case *ast.TypeAssertExpr:
+		p.expr1(x.X, token.HighestPrec, depth)
+		p.print(token.PERIOD, x.Lparen, token.LPAREN)
+		if x.Type != nil {
+			p.expr(x.Type)
+		} else {
+			p.print(token.TYPE)
+		}
+		p.print(x.Rparen, token.RPAREN)
+
+	case *ast.IndexExpr:
+		// TODO(gri): should treat[] like parentheses and undo one level of depth
+		p.expr1(x.X, token.HighestPrec, 1)
+		p.print(x.Lbrack, token.LBRACK)
+		p.expr0(x.Index, depth+1)
+		p.print(x.Rbrack, token.RBRACK)
+
+	case *ast.SliceExpr:
+		// TODO(gri): should treat[] like parentheses and undo one level of depth
+		p.expr1(x.X, token.HighestPrec, 1)
+		p.print(x.Lbrack, token.LBRACK)
+		indices := []ast.Expr{x.Low, x.High}
+		if x.Max != nil {
+			indices = append(indices, x.Max)
+		}
+		for i, y := range indices {
+			if i > 0 {
+				// blanks around ":" if both sides exist and either side is a binary expression
+				// TODO(gri) once we have committed a variant of a[i:j:k] we may want to fine-
+				//           tune the formatting here
+				x := indices[i-1]
+				if depth <= 1 && x != nil && y != nil && (isBinary(x) || isBinary(y)) {
+					p.print(blank, token.COLON, blank)
+				} else {
+					p.print(token.COLON)
+				}
+			}
+			if y != nil {
+				p.expr0(y, depth+1)
+			}
+		}
+		p.print(x.Rbrack, token.RBRACK)
+
+	case *ast.CallExpr:
+		if len(x.Args) > 1 {
+			depth++
+		}
+		if _, ok := x.Fun.(*ast.FuncType); ok {
+			// conversions to literal function types require parentheses around the type
+			p.print(token.LPAREN)
+			p.expr1(x.Fun, token.HighestPrec, depth)
+			p.print(token.RPAREN)
+		} else {
+			p.expr1(x.Fun, token.HighestPrec, depth)
+		}
+		p.print(x.Lparen, token.LPAREN)
+		if x.Ellipsis.IsValid() {
+			p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis)
+			p.print(x.Ellipsis, token.ELLIPSIS)
+			if x.Rparen.IsValid() && p.lineFor(x.Ellipsis) < p.lineFor(x.Rparen) {
+				p.print(token.COMMA, formfeed)
+			}
+		} else {
+			p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen)
+		}
+		p.print(x.Rparen, token.RPAREN)
+
+	case *ast.CompositeLit:
+		// composite literal elements that are composite literals themselves may have the type omitted
+		if x.Type != nil {
+			p.expr1(x.Type, token.HighestPrec, depth)
+		}
+		p.print(x.Lbrace, token.LBRACE)
+		p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace)
+		// do not insert extra line break following a /*-style comment
+		// before the closing '}' as it might break the code if there
+		// is no trailing ','
+		mode := noExtraLinebreak
+		// do not insert extra blank following a /*-style comment
+		// before the closing '}' unless the literal is empty
+		if len(x.Elts) > 0 {
+			mode |= noExtraBlank
+		}
+		p.print(mode, x.Rbrace, token.RBRACE, mode)
+
+	case *ast.Ellipsis:
+		p.print(token.ELLIPSIS)
+		if x.Elt != nil {
+			p.expr(x.Elt)
+		}
+
+	case *ast.ArrayType:
+		p.print(token.LBRACK)
+		if x.Len != nil {
+			p.expr(x.Len)
+		}
+		p.print(token.RBRACK)
+		p.expr(x.Elt)
+
+	case *ast.StructType:
+		p.print(token.STRUCT)
+		p.fieldList(x.Fields, true, x.Incomplete)
+
+	case *ast.FuncType:
+		p.print(token.FUNC)
+		p.signature(x.Params, x.Results)
+
+	case *ast.InterfaceType:
+		p.print(token.INTERFACE)
+		p.fieldList(x.Methods, false, x.Incomplete)
+
+	case *ast.MapType:
+		p.print(token.MAP, token.LBRACK)
+		p.expr(x.Key)
+		p.print(token.RBRACK)
+		p.expr(x.Value)
+
+	case *ast.ChanType:
+		switch x.Dir {
+		case ast.SEND | ast.RECV:
+			p.print(token.CHAN)
+		case ast.RECV:
+			p.print(token.ARROW, token.CHAN) // x.Arrow and x.Pos() are the same
+		case ast.SEND:
+			p.print(token.CHAN, x.Arrow, token.ARROW)
+		}
+		p.print(blank)
+		p.expr(x.Value)
+
+	default:
+		panic("unreachable")
+	}
+
+	return
+}
+
+func (p *printer) expr0(x ast.Expr, depth int) {
+	p.expr1(x, token.LowestPrec, depth)
+}
+
+func (p *printer) expr(x ast.Expr) {
+	const depth = 1
+	p.expr1(x, token.LowestPrec, depth)
+}
+
+// ----------------------------------------------------------------------------
+// Statements
+
+// Print the statement list indented, but without a newline after the last statement.
+// Extra line breaks between statements in the source are respected but at most one
+// empty line is printed between statements.
+func (p *printer) stmtList(list []ast.Stmt, nindent int, nextIsRBrace bool) {
+	if nindent > 0 {
+		p.print(indent)
+	}
+	var line int
+	i := 0
+	for _, s := range list {
+		// ignore empty statements (was issue 3466)
+		if _, isEmpty := s.(*ast.EmptyStmt); !isEmpty {
+			// nindent == 0 only for lists of switch/select case clauses;
+			// in those cases each clause is a new section
+			if len(p.output) > 0 {
+				// only print line break if we are not at the beginning of the output
+				// (i.e., we are not printing only a partial program)
+				p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || nindent == 0 || p.linesFrom(line) > 0)
+			}
+			p.recordLine(&line)
+			p.stmt(s, nextIsRBrace && i == len(list)-1)
+			// labeled statements put labels on a separate line, but here
+			// we only care about the start line of the actual statement
+			// without label - correct line for each label
+			for t := s; ; {
+				lt, _ := t.(*ast.LabeledStmt)
+				if lt == nil {
+					break
+				}
+				line++
+				t = lt.Stmt
+			}
+			i++
+		}
+	}
+	if nindent > 0 {
+		p.print(unindent)
+	}
+}
+
+// block prints an *ast.BlockStmt; it always spans at least two lines.
+func (p *printer) block(b *ast.BlockStmt, nindent int) {
+	p.print(b.Lbrace, token.LBRACE)
+	p.stmtList(b.List, nindent, true)
+	p.linebreak(p.lineFor(b.Rbrace), 1, ignore, true)
+	p.print(b.Rbrace, token.RBRACE)
+}
+
+func isTypeName(x ast.Expr) bool {
+	switch t := x.(type) {
+	case *ast.Ident:
+		return true
+	case *ast.SelectorExpr:
+		return isTypeName(t.X)
+	}
+	return false
+}
+
+func stripParens(x ast.Expr) ast.Expr {
+	if px, strip := x.(*ast.ParenExpr); strip {
+		// parentheses must not be stripped if there are any
+		// unparenthesized composite literals starting with
+		// a type name
+		ast.Inspect(px.X, func(node ast.Node) bool {
+			switch x := node.(type) {
+			case *ast.ParenExpr:
+				// parentheses protect enclosed composite literals
+				return false
+			case *ast.CompositeLit:
+				if isTypeName(x.Type) {
+					strip = false // do not strip parentheses
+				}
+				return false
+			}
+			// in all other cases, keep inspecting
+			return true
+		})
+		if strip {
+			return stripParens(px.X)
+		}
+	}
+	return x
+}
+
+func stripParensAlways(x ast.Expr) ast.Expr {
+	if x, ok := x.(*ast.ParenExpr); ok {
+		return stripParensAlways(x.X)
+	}
+	return x
+}
+
+func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, post ast.Stmt) {
+	p.print(blank)
+	needsBlank := false
+	if init == nil && post == nil {
+		// no semicolons required
+		if expr != nil {
+			p.expr(stripParens(expr))
+			needsBlank = true
+		}
+	} else {
+		// all semicolons required
+		// (they are not separators, print them explicitly)
+		if init != nil {
+			p.stmt(init, false)
+		}
+		p.print(token.SEMICOLON, blank)
+		if expr != nil {
+			p.expr(stripParens(expr))
+			needsBlank = true
+		}
+		if isForStmt {
+			p.print(token.SEMICOLON, blank)
+			needsBlank = false
+			if post != nil {
+				p.stmt(post, false)
+				needsBlank = true
+			}
+		}
+	}
+	if needsBlank {
+		p.print(blank)
+	}
+}
+
+// indentList reports whether an expression list would look better if it
+// were indented wholesale (starting with the very first element, rather
+// than starting at the first line break).
+//
+func (p *printer) indentList(list []ast.Expr) bool {
+	// Heuristic: indentList returns true if there are more than one multi-
+	// line element in the list, or if there is any element that is not
+	// starting on the same line as the previous one ends.
+	if len(list) >= 2 {
+		var b = p.lineFor(list[0].Pos())
+		var e = p.lineFor(list[len(list)-1].End())
+		if 0 < b && b < e {
+			// list spans multiple lines
+			n := 0 // multi-line element count
+			line := b
+			for _, x := range list {
+				xb := p.lineFor(x.Pos())
+				xe := p.lineFor(x.End())
+				if line < xb {
+					// x is not starting on the same
+					// line as the previous one ended
+					return true
+				}
+				if xb < xe {
+					// x is a multi-line element
+					n++
+				}
+				line = xe
+			}
+			return n > 1
+		}
+	}
+	return false
+}
+
+func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
+	p.print(stmt.Pos())
+
+	switch s := stmt.(type) {
+	case *ast.BadStmt:
+		p.print("BadStmt")
+
+	case *ast.DeclStmt:
+		p.decl(s.Decl)
+
+	case *ast.EmptyStmt:
+		// nothing to do
+
+	case *ast.LabeledStmt:
+		// a "correcting" unindent immediately following a line break
+		// is applied before the line break if there is no comment
+		// between (see writeWhitespace)
+		p.print(unindent)
+		p.expr(s.Label)
+		p.print(s.Colon, token.COLON, indent)
+		if e, isEmpty := s.Stmt.(*ast.EmptyStmt); isEmpty {
+			if !nextIsRBrace {
+				p.print(newline, e.Pos(), token.SEMICOLON)
+				break
+			}
+		} else {
+			p.linebreak(p.lineFor(s.Stmt.Pos()), 1, ignore, true)
+		}
+		p.stmt(s.Stmt, nextIsRBrace)
+
+	case *ast.ExprStmt:
+		const depth = 1
+		p.expr0(s.X, depth)
+
+	case *ast.SendStmt:
+		const depth = 1
+		p.expr0(s.Chan, depth)
+		p.print(blank, s.Arrow, token.ARROW, blank)
+		p.expr0(s.Value, depth)
+
+	case *ast.IncDecStmt:
+		const depth = 1
+		p.expr0(s.X, depth+1)
+		p.print(s.TokPos, s.Tok)
+
+	case *ast.AssignStmt:
+		var depth = 1
+		if len(s.Lhs) > 1 && len(s.Rhs) > 1 {
+			depth++
+		}
+		p.exprList(s.Pos(), s.Lhs, depth, 0, s.TokPos)
+		p.print(blank, s.TokPos, s.Tok, blank)
+		p.exprList(s.TokPos, s.Rhs, depth, 0, token.NoPos)
+
+	case *ast.GoStmt:
+		p.print(token.GO, blank)
+		p.expr(s.Call)
+
+	case *ast.DeferStmt:
+		p.print(token.DEFER, blank)
+		p.expr(s.Call)
+
+	case *ast.ReturnStmt:
+		p.print(token.RETURN)
+		if s.Results != nil {
+			p.print(blank)
+			// Use indentList heuristic to make corner cases look
+			// better (issue 1207). A more systematic approach would
+			// always indent, but this would cause significant
+			// reformatting of the code base and not necessarily
+			// lead to more nicely formatted code in general.
+			if p.indentList(s.Results) {
+				p.print(indent)
+				p.exprList(s.Pos(), s.Results, 1, noIndent, token.NoPos)
+				p.print(unindent)
+			} else {
+				p.exprList(s.Pos(), s.Results, 1, 0, token.NoPos)
+			}
+		}
+
+	case *ast.BranchStmt:
+		p.print(s.Tok)
+		if s.Label != nil {
+			p.print(blank)
+			p.expr(s.Label)
+		}
+
+	case *ast.BlockStmt:
+		p.block(s, 1)
+
+	case *ast.IfStmt:
+		p.print(token.IF)
+		p.controlClause(false, s.Init, s.Cond, nil)
+		p.block(s.Body, 1)
+		if s.Else != nil {
+			p.print(blank, token.ELSE, blank)
+			switch s.Else.(type) {
+			case *ast.BlockStmt, *ast.IfStmt:
+				p.stmt(s.Else, nextIsRBrace)
+			default:
+				p.print(token.LBRACE, indent, formfeed)
+				p.stmt(s.Else, true)
+				p.print(unindent, formfeed, token.RBRACE)
+			}
+		}
+
+	case *ast.CaseClause:
+		if s.List != nil {
+			p.print(token.CASE, blank)
+			p.exprList(s.Pos(), s.List, 1, 0, s.Colon)
+		} else {
+			p.print(token.DEFAULT)
+		}
+		p.print(s.Colon, token.COLON)
+		p.stmtList(s.Body, 1, nextIsRBrace)
+
+	case *ast.SwitchStmt:
+		p.print(token.SWITCH)
+		p.controlClause(false, s.Init, s.Tag, nil)
+		p.block(s.Body, 0)
+
+	case *ast.TypeSwitchStmt:
+		p.print(token.SWITCH)
+		if s.Init != nil {
+			p.print(blank)
+			p.stmt(s.Init, false)
+			p.print(token.SEMICOLON)
+		}
+		p.print(blank)
+		p.stmt(s.Assign, false)
+		p.print(blank)
+		p.block(s.Body, 0)
+
+	case *ast.CommClause:
+		if s.Comm != nil {
+			p.print(token.CASE, blank)
+			p.stmt(s.Comm, false)
+		} else {
+			p.print(token.DEFAULT)
+		}
+		p.print(s.Colon, token.COLON)
+		p.stmtList(s.Body, 1, nextIsRBrace)
+
+	case *ast.SelectStmt:
+		p.print(token.SELECT, blank)
+		body := s.Body
+		if len(body.List) == 0 && !p.commentBefore(p.posFor(body.Rbrace)) {
+			// print empty select statement w/o comments on one line
+			p.print(body.Lbrace, token.LBRACE, body.Rbrace, token.RBRACE)
+		} else {
+			p.block(body, 0)
+		}
+
+	case *ast.ForStmt:
+		p.print(token.FOR)
+		p.controlClause(true, s.Init, s.Cond, s.Post)
+		p.block(s.Body, 1)
+
+	case *ast.RangeStmt:
+		p.print(token.FOR, blank)
+		p.expr(s.Key)
+		if s.Value != nil {
+			// use position of value following the comma as
+			// comma position for correct comment placement
+			p.print(s.Value.Pos(), token.COMMA, blank)
+			p.expr(s.Value)
+		}
+		p.print(blank, s.TokPos, s.Tok, blank, token.RANGE, blank)
+		p.expr(stripParens(s.X))
+		p.print(blank)
+		p.block(s.Body, 1)
+
+	default:
+		panic("unreachable")
+	}
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+// The keepTypeColumn function determines if the type column of a series of
+// consecutive const or var declarations must be kept, or if initialization
+// values (V) can be placed in the type column (T) instead. The i'th entry
+// in the result slice is true if the type column in spec[i] must be kept.
+//
+// For example, the declaration:
+//
+//	const (
+//		foobar int = 42 // comment
+//		x          = 7  // comment
+//		foo
+//              bar = 991
+//	)
+//
+// leads to the type/values matrix below. A run of value columns (V) can
+// be moved into the type column if there is no type for any of the values
+// in that column (we only move entire columns so that they align properly).
+//
+//	matrix        formatted     result
+//                    matrix
+//	T  V    ->    T  V     ->   true      there is a T and so the type
+//	-  V          -  V          true      column must be kept
+//	-  -          -  -          false
+//	-  V          V  -          false     V is moved into T column
+//
+func keepTypeColumn(specs []ast.Spec) []bool {
+	m := make([]bool, len(specs))
+
+	populate := func(i, j int, keepType bool) {
+		if keepType {
+			for ; i < j; i++ {
+				m[i] = true
+			}
+		}
+	}
+
+	i0 := -1 // if i0 >= 0 we are in a run and i0 is the start of the run
+	var keepType bool
+	for i, s := range specs {
+		t := s.(*ast.ValueSpec)
+		if t.Values != nil {
+			if i0 < 0 {
+				// start of a run of ValueSpecs with non-nil Values
+				i0 = i
+				keepType = false
+			}
+		} else {
+			if i0 >= 0 {
+				// end of a run
+				populate(i0, i, keepType)
+				i0 = -1
+			}
+		}
+		if t.Type != nil {
+			keepType = true
+		}
+	}
+	if i0 >= 0 {
+		// end of a run
+		populate(i0, len(specs), keepType)
+	}
+
+	return m
+}
+
+func (p *printer) valueSpec(s *ast.ValueSpec, keepType bool) {
+	p.setComment(s.Doc)
+	p.identList(s.Names, false) // always present
+	extraTabs := 3
+	if s.Type != nil || keepType {
+		p.print(vtab)
+		extraTabs--
+	}
+	if s.Type != nil {
+		p.expr(s.Type)
+	}
+	if s.Values != nil {
+		p.print(vtab, token.ASSIGN, blank)
+		p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos)
+		extraTabs--
+	}
+	if s.Comment != nil {
+		for ; extraTabs > 0; extraTabs-- {
+			p.print(vtab)
+		}
+		p.setComment(s.Comment)
+	}
+}
+
+// The parameter n is the number of specs in the group. If doIndent is set,
+// multi-line identifier lists in the spec are indented when the first
+// linebreak is encountered.
+//
+func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
+	switch s := spec.(type) {
+	case *ast.ImportSpec:
+		p.setComment(s.Doc)
+		if s.Name != nil {
+			p.expr(s.Name)
+			p.print(blank)
+		}
+		p.expr(s.Path)
+		p.setComment(s.Comment)
+		p.print(s.EndPos)
+
+	case *ast.ValueSpec:
+		if n != 1 {
+			p.internalError("expected n = 1; got", n)
+		}
+		p.setComment(s.Doc)
+		p.identList(s.Names, doIndent) // always present
+		if s.Type != nil {
+			p.print(blank)
+			p.expr(s.Type)
+		}
+		if s.Values != nil {
+			p.print(blank, token.ASSIGN, blank)
+			p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos)
+		}
+		p.setComment(s.Comment)
+
+	case *ast.TypeSpec:
+		p.setComment(s.Doc)
+		p.expr(s.Name)
+		if n == 1 {
+			p.print(blank)
+		} else {
+			p.print(vtab)
+		}
+		p.expr(s.Type)
+		p.setComment(s.Comment)
+
+	default:
+		panic("unreachable")
+	}
+}
+
+func (p *printer) genDecl(d *ast.GenDecl) {
+	p.setComment(d.Doc)
+	p.print(d.Pos(), d.Tok, blank)
+
+	if d.Lparen.IsValid() {
+		// group of parenthesized declarations
+		p.print(d.Lparen, token.LPAREN)
+		if n := len(d.Specs); n > 0 {
+			p.print(indent, formfeed)
+			if n > 1 && (d.Tok == token.CONST || d.Tok == token.VAR) {
+				// two or more grouped const/var declarations:
+				// determine if the type column must be kept
+				keepType := keepTypeColumn(d.Specs)
+				var line int
+				for i, s := range d.Specs {
+					if i > 0 {
+						p.linebreak(p.lineFor(s.Pos()), 1, ignore, p.linesFrom(line) > 0)
+					}
+					p.recordLine(&line)
+					p.valueSpec(s.(*ast.ValueSpec), keepType[i])
+				}
+			} else {
+				var line int
+				for i, s := range d.Specs {
+					if i > 0 {
+						p.linebreak(p.lineFor(s.Pos()), 1, ignore, p.linesFrom(line) > 0)
+					}
+					p.recordLine(&line)
+					p.spec(s, n, false)
+				}
+			}
+			p.print(unindent, formfeed)
+		}
+		p.print(d.Rparen, token.RPAREN)
+
+	} else {
+		// single declaration
+		p.spec(d.Specs[0], 1, true)
+	}
+}
+
+// nodeSize determines the size of n in chars after formatting.
+// The result is <= maxSize if the node fits on one line with at
+// most maxSize chars and the formatted output doesn't contain
+// any control chars. Otherwise, the result is > maxSize.
+//
+func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
+	// nodeSize invokes the printer, which may invoke nodeSize
+	// recursively. For deep composite literal nests, this can
+	// lead to an exponential algorithm. Remember previous
+	// results to prune the recursion (was issue 1628).
+	if size, found := p.nodeSizes[n]; found {
+		return size
+	}
+
+	size = maxSize + 1 // assume n doesn't fit
+	p.nodeSizes[n] = size
+
+	// nodeSize computation must be independent of particular
+	// style so that we always get the same decision; print
+	// in RawFormat
+	cfg := Config{Mode: RawFormat}
+	var buf bytes.Buffer
+	if err := cfg.fprint(&buf, p.fset, n, p.nodeSizes); err != nil {
+		return
+	}
+	if buf.Len() <= maxSize {
+		for _, ch := range buf.Bytes() {
+			if ch < ' ' {
+				return
+			}
+		}
+		size = buf.Len() // n fits
+		p.nodeSizes[n] = size
+	}
+	return
+}
+
+// bodySize is like nodeSize but it is specialized for *ast.BlockStmt's.
+func (p *printer) bodySize(b *ast.BlockStmt, maxSize int) int {
+	pos1 := b.Pos()
+	pos2 := b.Rbrace
+	if pos1.IsValid() && pos2.IsValid() && p.lineFor(pos1) != p.lineFor(pos2) {
+		// opening and closing brace are on different lines - don't make it a one-liner
+		return maxSize + 1
+	}
+	if len(b.List) > 5 {
+		// too many statements - don't make it a one-liner
+		return maxSize + 1
+	}
+	// otherwise, estimate body size
+	bodySize := p.commentSizeBefore(p.posFor(pos2))
+	for i, s := range b.List {
+		if bodySize > maxSize {
+			break // no need to continue
+		}
+		if i > 0 {
+			bodySize += 2 // space for a semicolon and blank
+		}
+		bodySize += p.nodeSize(s, maxSize)
+	}
+	return bodySize
+}
+
+// adjBlock prints an "adjacent" block (e.g., a for-loop or function body) following
+// a header (e.g., a for-loop control clause or function signature) of given headerSize.
+// If the header's and block's size are "small enough" and the block is "simple enough",
+// the block is printed on the current line, without line breaks, spaced from the header
+// by sep. Otherwise the block's opening "{" is printed on the current line, followed by
+// lines for the block's statements and its closing "}".
+//
+func (p *printer) adjBlock(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
+	if b == nil {
+		return
+	}
+
+	const maxSize = 100
+	if headerSize+p.bodySize(b, maxSize) <= maxSize {
+		p.print(sep, b.Lbrace, token.LBRACE)
+		if len(b.List) > 0 {
+			p.print(blank)
+			for i, s := range b.List {
+				if i > 0 {
+					p.print(token.SEMICOLON, blank)
+				}
+				p.stmt(s, i == len(b.List)-1)
+			}
+			p.print(blank)
+		}
+		p.print(noExtraLinebreak, b.Rbrace, token.RBRACE, noExtraLinebreak)
+		return
+	}
+
+	if sep != ignore {
+		p.print(blank) // always use blank
+	}
+	p.block(b, 1)
+}
+
+// distanceFrom returns the column difference between from and p.pos (the current
+// estimated position) if both are on the same line; if they are on different lines
+// (or unknown) the result is infinity.
+func (p *printer) distanceFrom(from token.Pos) int {
+	if from.IsValid() && p.pos.IsValid() {
+		if f := p.posFor(from); f.Line == p.pos.Line {
+			return p.pos.Column - f.Column
+		}
+	}
+	return infinity
+}
+
+func (p *printer) funcDecl(d *ast.FuncDecl) {
+	p.setComment(d.Doc)
+	p.print(d.Pos(), token.FUNC, blank)
+	if d.Recv != nil {
+		p.parameters(d.Recv) // method: print receiver
+		p.print(blank)
+	}
+	p.expr(d.Name)
+	p.signature(d.Type.Params, d.Type.Results)
+	p.adjBlock(p.distanceFrom(d.Pos()), vtab, d.Body)
+}
+
+func (p *printer) decl(decl ast.Decl) {
+	switch d := decl.(type) {
+	case *ast.BadDecl:
+		p.print(d.Pos(), "BadDecl")
+	case *ast.GenDecl:
+		p.genDecl(d)
+	case *ast.FuncDecl:
+		p.funcDecl(d)
+	default:
+		panic("unreachable")
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Files
+
+func declToken(decl ast.Decl) (tok token.Token) {
+	tok = token.ILLEGAL
+	switch d := decl.(type) {
+	case *ast.GenDecl:
+		tok = d.Tok
+	case *ast.FuncDecl:
+		tok = token.FUNC
+	}
+	return
+}
+
+func (p *printer) declList(list []ast.Decl) {
+	tok := token.ILLEGAL
+	for _, d := range list {
+		prev := tok
+		tok = declToken(d)
+		// If the declaration token changed (e.g., from CONST to TYPE)
+		// or the next declaration has documentation associated with it,
+		// print an empty line between top-level declarations.
+		// (because p.linebreak is called with the position of d, which
+		// is past any documentation, the minimum requirement is satisfied
+		// even w/o the extra getDoc(d) nil-check - leave it in case the
+		// linebreak logic improves - there's already a TODO).
+		if len(p.output) > 0 {
+			// only print line break if we are not at the beginning of the output
+			// (i.e., we are not printing only a partial program)
+			min := 1
+			if prev != tok || getDoc(d) != nil {
+				min = 2
+			}
+			p.linebreak(p.lineFor(d.Pos()), min, ignore, false)
+		}
+		p.decl(d)
+	}
+}
+
+func (p *printer) file(src *ast.File) {
+	p.setComment(src.Doc)
+	p.print(src.Pos(), token.PACKAGE, blank)
+	p.expr(src.Name)
+	p.declList(src.Decls)
+	p.print(newline)
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/performance_test.go b/third_party/gofrontend/libgo/go/go/printer/performance_test.go
new file mode 100644
index 0000000..5b29aff
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/performance_test.go
@@ -0,0 +1,58 @@
+// 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.
+
+// This file implements a simple printer performance benchmark:
+// go test -bench=BenchmarkPrint
+
+package printer
+
+import (
+	"bytes"
+	"go/ast"
+	"go/parser"
+	"io"
+	"io/ioutil"
+	"log"
+	"testing"
+)
+
+var testfile *ast.File
+
+func testprint(out io.Writer, file *ast.File) {
+	if err := (&Config{TabIndent | UseSpaces, 8, 0}).Fprint(out, fset, file); err != nil {
+		log.Fatalf("print error: %s", err)
+	}
+}
+
+// cannot initialize in init because (printer) Fprint launches goroutines.
+func initialize() {
+	const filename = "testdata/parser.go"
+
+	src, err := ioutil.ReadFile(filename)
+	if err != nil {
+		log.Fatalf("%s", err)
+	}
+
+	file, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
+	if err != nil {
+		log.Fatalf("%s", err)
+	}
+
+	var buf bytes.Buffer
+	testprint(&buf, file)
+	if !bytes.Equal(buf.Bytes(), src) {
+		log.Fatalf("print error: %s not idempotent", filename)
+	}
+
+	testfile = file
+}
+
+func BenchmarkPrint(b *testing.B) {
+	if testfile == nil {
+		initialize()
+	}
+	for i := 0; i < b.N; i++ {
+		testprint(ioutil.Discard, testfile)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/printer.go b/third_party/gofrontend/libgo/go/go/printer/printer.go
new file mode 100644
index 0000000..280c697
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/printer.go
@@ -0,0 +1,1292 @@
+// 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 printer implements printing of AST nodes.
+package printer
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"os"
+	"strconv"
+	"strings"
+	"text/tabwriter"
+	"unicode"
+)
+
+const (
+	maxNewlines = 2     // max. number of newlines between source text
+	debug       = false // enable for debugging
+	infinity    = 1 << 30
+)
+
+type whiteSpace byte
+
+const (
+	ignore   = whiteSpace(0)
+	blank    = whiteSpace(' ')
+	vtab     = whiteSpace('\v')
+	newline  = whiteSpace('\n')
+	formfeed = whiteSpace('\f')
+	indent   = whiteSpace('>')
+	unindent = whiteSpace('<')
+)
+
+// A pmode value represents the current printer mode.
+type pmode int
+
+const (
+	noExtraBlank     pmode = 1 << iota // disables extra blank after /*-style comment
+	noExtraLinebreak                   // disables extra line break after /*-style comment
+)
+
+type commentInfo struct {
+	cindex         int               // current comment index
+	comment        *ast.CommentGroup // = printer.comments[cindex]; or nil
+	commentOffset  int               // = printer.posFor(printer.comments[cindex].List[0].Pos()).Offset; or infinity
+	commentNewline bool              // true if the comment group contains newlines
+}
+
+type printer struct {
+	// Configuration (does not change after initialization)
+	Config
+	fset *token.FileSet
+
+	// Current state
+	output      []byte       // raw printer result
+	indent      int          // current indentation
+	mode        pmode        // current printer mode
+	impliedSemi bool         // if set, a linebreak implies a semicolon
+	lastTok     token.Token  // last token printed (token.ILLEGAL if it's whitespace)
+	prevOpen    token.Token  // previous non-brace "open" token (, [, or token.ILLEGAL
+	wsbuf       []whiteSpace // delayed white space
+
+	// Positions
+	// The out position differs from the pos position when the result
+	// formatting differs from the source formatting (in the amount of
+	// white space). If there's a difference and SourcePos is set in
+	// ConfigMode, //line comments are used in the output to restore
+	// original source positions for a reader.
+	pos     token.Position // current position in AST (source) space
+	out     token.Position // current position in output space
+	last    token.Position // value of pos after calling writeString
+	linePtr *int           // if set, record out.Line for the next token in *linePtr
+
+	// The list of all source comments, in order of appearance.
+	comments        []*ast.CommentGroup // may be nil
+	useNodeComments bool                // if not set, ignore lead and line comments of nodes
+
+	// Information about p.comments[p.cindex]; set up by nextComment.
+	commentInfo
+
+	// Cache of already computed node sizes.
+	nodeSizes map[ast.Node]int
+
+	// Cache of most recently computed line position.
+	cachedPos  token.Pos
+	cachedLine int // line corresponding to cachedPos
+}
+
+func (p *printer) init(cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node]int) {
+	p.Config = *cfg
+	p.fset = fset
+	p.pos = token.Position{Line: 1, Column: 1}
+	p.out = token.Position{Line: 1, Column: 1}
+	p.wsbuf = make([]whiteSpace, 0, 16) // whitespace sequences are short
+	p.nodeSizes = nodeSizes
+	p.cachedPos = -1
+}
+
+func (p *printer) internalError(msg ...interface{}) {
+	if debug {
+		fmt.Print(p.pos.String() + ": ")
+		fmt.Println(msg...)
+		panic("go/printer")
+	}
+}
+
+// commentsHaveNewline reports whether a list of comments belonging to
+// an *ast.CommentGroup contains newlines. Because the position information
+// may only be partially correct, we also have to read the comment text.
+func (p *printer) commentsHaveNewline(list []*ast.Comment) bool {
+	// len(list) > 0
+	line := p.lineFor(list[0].Pos())
+	for i, c := range list {
+		if i > 0 && p.lineFor(list[i].Pos()) != line {
+			// not all comments on the same line
+			return true
+		}
+		if t := c.Text; len(t) >= 2 && (t[1] == '/' || strings.Contains(t, "\n")) {
+			return true
+		}
+	}
+	_ = line
+	return false
+}
+
+func (p *printer) nextComment() {
+	for p.cindex < len(p.comments) {
+		c := p.comments[p.cindex]
+		p.cindex++
+		if list := c.List; len(list) > 0 {
+			p.comment = c
+			p.commentOffset = p.posFor(list[0].Pos()).Offset
+			p.commentNewline = p.commentsHaveNewline(list)
+			return
+		}
+		// we should not reach here (correct ASTs don't have empty
+		// ast.CommentGroup nodes), but be conservative and try again
+	}
+	// no more comments
+	p.commentOffset = infinity
+}
+
+// commentBefore returns true iff the current comment group occurs
+// before the next position in the source code and printing it does
+// not introduce implicit semicolons.
+//
+func (p *printer) commentBefore(next token.Position) bool {
+	return p.commentOffset < next.Offset && (!p.impliedSemi || !p.commentNewline)
+}
+
+// commentSizeBefore returns the estimated size of the
+// comments on the same line before the next position.
+//
+func (p *printer) commentSizeBefore(next token.Position) int {
+	// save/restore current p.commentInfo (p.nextComment() modifies it)
+	defer func(info commentInfo) {
+		p.commentInfo = info
+	}(p.commentInfo)
+
+	size := 0
+	for p.commentBefore(next) {
+		for _, c := range p.comment.List {
+			size += len(c.Text)
+		}
+		p.nextComment()
+	}
+	return size
+}
+
+// recordLine records the output line number for the next non-whitespace
+// token in *linePtr. It is used to compute an accurate line number for a
+// formatted construct, independent of pending (not yet emitted) whitespace
+// or comments.
+//
+func (p *printer) recordLine(linePtr *int) {
+	p.linePtr = linePtr
+}
+
+// linesFrom returns the number of output lines between the current
+// output line and the line argument, ignoring any pending (not yet
+// emitted) whitespace or comments. It is used to compute an accurate
+// size (in number of lines) for a formatted construct.
+//
+func (p *printer) linesFrom(line int) int {
+	return p.out.Line - line
+}
+
+func (p *printer) posFor(pos token.Pos) token.Position {
+	// not used frequently enough to cache entire token.Position
+	return p.fset.Position(pos)
+}
+
+func (p *printer) lineFor(pos token.Pos) int {
+	if pos != p.cachedPos {
+		p.cachedPos = pos
+		p.cachedLine = p.fset.Position(pos).Line
+	}
+	return p.cachedLine
+}
+
+// atLineBegin emits a //line comment if necessary and prints indentation.
+func (p *printer) atLineBegin(pos token.Position) {
+	// write a //line comment if necessary
+	if p.Config.Mode&SourcePos != 0 && pos.IsValid() && (p.out.Line != pos.Line || p.out.Filename != pos.Filename) {
+		p.output = append(p.output, tabwriter.Escape) // protect '\n' in //line from tabwriter interpretation
+		p.output = append(p.output, fmt.Sprintf("//line %s:%d\n", pos.Filename, pos.Line)...)
+		p.output = append(p.output, tabwriter.Escape)
+		// p.out must match the //line comment
+		p.out.Filename = pos.Filename
+		p.out.Line = pos.Line
+	}
+
+	// write indentation
+	// use "hard" htabs - indentation columns
+	// must not be discarded by the tabwriter
+	n := p.Config.Indent + p.indent // include base indentation
+	for i := 0; i < n; i++ {
+		p.output = append(p.output, '\t')
+	}
+
+	// update positions
+	p.pos.Offset += n
+	p.pos.Column += n
+	p.out.Column += n
+}
+
+// writeByte writes ch n times to p.output and updates p.pos.
+func (p *printer) writeByte(ch byte, n int) {
+	if p.out.Column == 1 {
+		p.atLineBegin(p.pos)
+	}
+
+	for i := 0; i < n; i++ {
+		p.output = append(p.output, ch)
+	}
+
+	// update positions
+	p.pos.Offset += n
+	if ch == '\n' || ch == '\f' {
+		p.pos.Line += n
+		p.out.Line += n
+		p.pos.Column = 1
+		p.out.Column = 1
+		return
+	}
+	p.pos.Column += n
+	p.out.Column += n
+}
+
+// writeString writes the string s to p.output and updates p.pos, p.out,
+// and p.last. If isLit is set, s is escaped w/ tabwriter.Escape characters
+// to protect s from being interpreted by the tabwriter.
+//
+// Note: writeString is only used to write Go tokens, literals, and
+// comments, all of which must be written literally. Thus, it is correct
+// to always set isLit = true. However, setting it explicitly only when
+// needed (i.e., when we don't know that s contains no tabs or line breaks)
+// avoids processing extra escape characters and reduces run time of the
+// printer benchmark by up to 10%.
+//
+func (p *printer) writeString(pos token.Position, s string, isLit bool) {
+	if p.out.Column == 1 {
+		p.atLineBegin(pos)
+	}
+
+	if pos.IsValid() {
+		// update p.pos (if pos is invalid, continue with existing p.pos)
+		// Note: Must do this after handling line beginnings because
+		// atLineBegin updates p.pos if there's indentation, but p.pos
+		// is the position of s.
+		p.pos = pos
+	}
+
+	if isLit {
+		// Protect s such that is passes through the tabwriter
+		// unchanged. Note that valid Go programs cannot contain
+		// tabwriter.Escape bytes since they do not appear in legal
+		// UTF-8 sequences.
+		p.output = append(p.output, tabwriter.Escape)
+	}
+
+	if debug {
+		p.output = append(p.output, fmt.Sprintf("/*%s*/", pos)...) // do not update p.pos!
+	}
+	p.output = append(p.output, s...)
+
+	// update positions
+	nlines := 0
+	var li int // index of last newline; valid if nlines > 0
+	for i := 0; i < len(s); i++ {
+		// Go tokens cannot contain '\f' - no need to look for it
+		if s[i] == '\n' {
+			nlines++
+			li = i
+		}
+	}
+	p.pos.Offset += len(s)
+	if nlines > 0 {
+		p.pos.Line += nlines
+		p.out.Line += nlines
+		c := len(s) - li
+		p.pos.Column = c
+		p.out.Column = c
+	} else {
+		p.pos.Column += len(s)
+		p.out.Column += len(s)
+	}
+
+	if isLit {
+		p.output = append(p.output, tabwriter.Escape)
+	}
+
+	p.last = p.pos
+}
+
+// writeCommentPrefix writes the whitespace before a comment.
+// If there is any pending whitespace, it consumes as much of
+// it as is likely to help position the comment nicely.
+// pos is the comment position, next the position of the item
+// after all pending comments, prev is the previous comment in
+// a group of comments (or nil), and tok is the next token.
+//
+func (p *printer) writeCommentPrefix(pos, next token.Position, prev, comment *ast.Comment, tok token.Token) {
+	if len(p.output) == 0 {
+		// the comment is the first item to be printed - don't write any whitespace
+		return
+	}
+
+	if pos.IsValid() && pos.Filename != p.last.Filename {
+		// comment in a different file - separate with newlines
+		p.writeByte('\f', maxNewlines)
+		return
+	}
+
+	if pos.Line == p.last.Line && (prev == nil || prev.Text[1] != '/') {
+		// comment on the same line as last item:
+		// separate with at least one separator
+		hasSep := false
+		if prev == nil {
+			// first comment of a comment group
+			j := 0
+			for i, ch := range p.wsbuf {
+				switch ch {
+				case blank:
+					// ignore any blanks before a comment
+					p.wsbuf[i] = ignore
+					continue
+				case vtab:
+					// respect existing tabs - important
+					// for proper formatting of commented structs
+					hasSep = true
+					continue
+				case indent:
+					// apply pending indentation
+					continue
+				}
+				j = i
+				break
+			}
+			p.writeWhitespace(j)
+		}
+		// make sure there is at least one separator
+		if !hasSep {
+			sep := byte('\t')
+			if pos.Line == next.Line {
+				// next item is on the same line as the comment
+				// (which must be a /*-style comment): separate
+				// with a blank instead of a tab
+				sep = ' '
+			}
+			p.writeByte(sep, 1)
+		}
+
+	} else {
+		// comment on a different line:
+		// separate with at least one line break
+		droppedLinebreak := false
+		j := 0
+		for i, ch := range p.wsbuf {
+			switch ch {
+			case blank, vtab:
+				// ignore any horizontal whitespace before line breaks
+				p.wsbuf[i] = ignore
+				continue
+			case indent:
+				// apply pending indentation
+				continue
+			case unindent:
+				// if this is not the last unindent, apply it
+				// as it is (likely) belonging to the last
+				// construct (e.g., a multi-line expression list)
+				// and is not part of closing a block
+				if i+1 < len(p.wsbuf) && p.wsbuf[i+1] == unindent {
+					continue
+				}
+				// if the next token is not a closing }, apply the unindent
+				// if it appears that the comment is aligned with the
+				// token; otherwise assume the unindent is part of a
+				// closing block and stop (this scenario appears with
+				// comments before a case label where the comments
+				// apply to the next case instead of the current one)
+				if tok != token.RBRACE && pos.Column == next.Column {
+					continue
+				}
+			case newline, formfeed:
+				p.wsbuf[i] = ignore
+				droppedLinebreak = prev == nil // record only if first comment of a group
+			}
+			j = i
+			break
+		}
+		p.writeWhitespace(j)
+
+		// determine number of linebreaks before the comment
+		n := 0
+		if pos.IsValid() && p.last.IsValid() {
+			n = pos.Line - p.last.Line
+			if n < 0 { // should never happen
+				n = 0
+			}
+		}
+
+		// at the package scope level only (p.indent == 0),
+		// add an extra newline if we dropped one before:
+		// this preserves a blank line before documentation
+		// comments at the package scope level (issue 2570)
+		if p.indent == 0 && droppedLinebreak {
+			n++
+		}
+
+		// make sure there is at least one line break
+		// if the previous comment was a line comment
+		if n == 0 && prev != nil && prev.Text[1] == '/' {
+			n = 1
+		}
+
+		if n > 0 {
+			// use formfeeds to break columns before a comment;
+			// this is analogous to using formfeeds to separate
+			// individual lines of /*-style comments
+			p.writeByte('\f', nlimit(n))
+		}
+	}
+}
+
+// Returns true if s contains only white space
+// (only tabs and blanks can appear in the printer's context).
+//
+func isBlank(s string) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] > ' ' {
+			return false
+		}
+	}
+	return true
+}
+
+// commonPrefix returns the common prefix of a and b.
+func commonPrefix(a, b string) string {
+	i := 0
+	for i < len(a) && i < len(b) && a[i] == b[i] && (a[i] <= ' ' || a[i] == '*') {
+		i++
+	}
+	return a[0:i]
+}
+
+// trimRight returns s with trailing whitespace removed.
+func trimRight(s string) string {
+	return strings.TrimRightFunc(s, unicode.IsSpace)
+}
+
+// stripCommonPrefix removes a common prefix from /*-style comment lines (unless no
+// comment line is indented, all but the first line have some form of space prefix).
+// The prefix is computed using heuristics such that is likely that the comment
+// contents are nicely laid out after re-printing each line using the printer's
+// current indentation.
+//
+func stripCommonPrefix(lines []string) {
+	if len(lines) <= 1 {
+		return // at most one line - nothing to do
+	}
+	// len(lines) > 1
+
+	// The heuristic in this function tries to handle a few
+	// common patterns of /*-style comments: Comments where
+	// the opening /* and closing */ are aligned and the
+	// rest of the comment text is aligned and indented with
+	// blanks or tabs, cases with a vertical "line of stars"
+	// on the left, and cases where the closing */ is on the
+	// same line as the last comment text.
+
+	// Compute maximum common white prefix of all but the first,
+	// last, and blank lines, and replace blank lines with empty
+	// lines (the first line starts with /* and has no prefix).
+	// In case of two-line comments, consider the last line for
+	// the prefix computation since otherwise the prefix would
+	// be empty.
+	//
+	// Note that the first and last line are never empty (they
+	// contain the opening /* and closing */ respectively) and
+	// thus they can be ignored by the blank line check.
+	var prefix string
+	if len(lines) > 2 {
+		first := true
+		for i, line := range lines[1 : len(lines)-1] {
+			switch {
+			case isBlank(line):
+				lines[1+i] = "" // range starts with lines[1]
+			case first:
+				prefix = commonPrefix(line, line)
+				first = false
+			default:
+				prefix = commonPrefix(prefix, line)
+			}
+		}
+	} else { // len(lines) == 2, lines cannot be blank (contain /* and */)
+		line := lines[1]
+		prefix = commonPrefix(line, line)
+	}
+
+	/*
+	 * Check for vertical "line of stars" and correct prefix accordingly.
+	 */
+	lineOfStars := false
+	if i := strings.Index(prefix, "*"); i >= 0 {
+		// Line of stars present.
+		if i > 0 && prefix[i-1] == ' ' {
+			i-- // remove trailing blank from prefix so stars remain aligned
+		}
+		prefix = prefix[0:i]
+		lineOfStars = true
+	} else {
+		// No line of stars present.
+		// Determine the white space on the first line after the /*
+		// and before the beginning of the comment text, assume two
+		// blanks instead of the /* unless the first character after
+		// the /* is a tab. If the first comment line is empty but
+		// for the opening /*, assume up to 3 blanks or a tab. This
+		// whitespace may be found as suffix in the common prefix.
+		first := lines[0]
+		if isBlank(first[2:]) {
+			// no comment text on the first line:
+			// reduce prefix by up to 3 blanks or a tab
+			// if present - this keeps comment text indented
+			// relative to the /* and */'s if it was indented
+			// in the first place
+			i := len(prefix)
+			for n := 0; n < 3 && i > 0 && prefix[i-1] == ' '; n++ {
+				i--
+			}
+			if i == len(prefix) && i > 0 && prefix[i-1] == '\t' {
+				i--
+			}
+			prefix = prefix[0:i]
+		} else {
+			// comment text on the first line
+			suffix := make([]byte, len(first))
+			n := 2 // start after opening /*
+			for n < len(first) && first[n] <= ' ' {
+				suffix[n] = first[n]
+				n++
+			}
+			if n > 2 && suffix[2] == '\t' {
+				// assume the '\t' compensates for the /*
+				suffix = suffix[2:n]
+			} else {
+				// otherwise assume two blanks
+				suffix[0], suffix[1] = ' ', ' '
+				suffix = suffix[0:n]
+			}
+			// Shorten the computed common prefix by the length of
+			// suffix, if it is found as suffix of the prefix.
+			prefix = strings.TrimSuffix(prefix, string(suffix))
+		}
+	}
+
+	// Handle last line: If it only contains a closing */, align it
+	// with the opening /*, otherwise align the text with the other
+	// lines.
+	last := lines[len(lines)-1]
+	closing := "*/"
+	i := strings.Index(last, closing) // i >= 0 (closing is always present)
+	if isBlank(last[0:i]) {
+		// last line only contains closing */
+		if lineOfStars {
+			closing = " */" // add blank to align final star
+		}
+		lines[len(lines)-1] = prefix + closing
+	} else {
+		// last line contains more comment text - assume
+		// it is aligned like the other lines and include
+		// in prefix computation
+		prefix = commonPrefix(prefix, last)
+	}
+
+	// Remove the common prefix from all but the first and empty lines.
+	for i, line := range lines {
+		if i > 0 && line != "" {
+			lines[i] = line[len(prefix):]
+		}
+	}
+}
+
+func (p *printer) writeComment(comment *ast.Comment) {
+	text := comment.Text
+	pos := p.posFor(comment.Pos())
+
+	const linePrefix = "//line "
+	if strings.HasPrefix(text, linePrefix) && (!pos.IsValid() || pos.Column == 1) {
+		// possibly a line directive
+		ldir := strings.TrimSpace(text[len(linePrefix):])
+		if i := strings.LastIndex(ldir, ":"); i >= 0 {
+			if line, err := strconv.Atoi(ldir[i+1:]); err == nil && line > 0 {
+				// The line directive we are about to print changed
+				// the Filename and Line number used for subsequent
+				// tokens. We have to update our AST-space position
+				// accordingly and suspend indentation temporarily.
+				indent := p.indent
+				p.indent = 0
+				defer func() {
+					p.pos.Filename = ldir[:i]
+					p.pos.Line = line
+					p.pos.Column = 1
+					p.indent = indent
+				}()
+			}
+		}
+	}
+
+	// shortcut common case of //-style comments
+	if text[1] == '/' {
+		p.writeString(pos, trimRight(text), true)
+		return
+	}
+
+	// for /*-style comments, print line by line and let the
+	// write function take care of the proper indentation
+	lines := strings.Split(text, "\n")
+
+	// The comment started in the first column but is going
+	// to be indented. For an idempotent result, add indentation
+	// to all lines such that they look like they were indented
+	// before - this will make sure the common prefix computation
+	// is the same independent of how many times formatting is
+	// applied (was issue 1835).
+	if pos.IsValid() && pos.Column == 1 && p.indent > 0 {
+		for i, line := range lines[1:] {
+			lines[1+i] = "   " + line
+		}
+	}
+
+	stripCommonPrefix(lines)
+
+	// write comment lines, separated by formfeed,
+	// without a line break after the last line
+	for i, line := range lines {
+		if i > 0 {
+			p.writeByte('\f', 1)
+			pos = p.pos
+		}
+		if len(line) > 0 {
+			p.writeString(pos, trimRight(line), true)
+		}
+	}
+}
+
+// writeCommentSuffix writes a line break after a comment if indicated
+// and processes any leftover indentation information. If a line break
+// is needed, the kind of break (newline vs formfeed) depends on the
+// pending whitespace. The writeCommentSuffix result indicates if a
+// newline was written or if a formfeed was dropped from the whitespace
+// buffer.
+//
+func (p *printer) writeCommentSuffix(needsLinebreak bool) (wroteNewline, droppedFF bool) {
+	for i, ch := range p.wsbuf {
+		switch ch {
+		case blank, vtab:
+			// ignore trailing whitespace
+			p.wsbuf[i] = ignore
+		case indent, unindent:
+			// don't lose indentation information
+		case newline, formfeed:
+			// if we need a line break, keep exactly one
+			// but remember if we dropped any formfeeds
+			if needsLinebreak {
+				needsLinebreak = false
+				wroteNewline = true
+			} else {
+				if ch == formfeed {
+					droppedFF = true
+				}
+				p.wsbuf[i] = ignore
+			}
+		}
+	}
+	p.writeWhitespace(len(p.wsbuf))
+
+	// make sure we have a line break
+	if needsLinebreak {
+		p.writeByte('\n', 1)
+		wroteNewline = true
+	}
+
+	return
+}
+
+// intersperseComments consumes all comments that appear before the next token
+// tok and prints it together with the buffered whitespace (i.e., the whitespace
+// that needs to be written before the next token). A heuristic is used to mix
+// the comments and whitespace. The intersperseComments result indicates if a
+// newline was written or if a formfeed was dropped from the whitespace buffer.
+//
+func (p *printer) intersperseComments(next token.Position, tok token.Token) (wroteNewline, droppedFF bool) {
+	var last *ast.Comment
+	for p.commentBefore(next) {
+		for _, c := range p.comment.List {
+			p.writeCommentPrefix(p.posFor(c.Pos()), next, last, c, tok)
+			p.writeComment(c)
+			last = c
+		}
+		p.nextComment()
+	}
+
+	if last != nil {
+		// if the last comment is a /*-style comment and the next item
+		// follows on the same line but is not a comma, and not a "closing"
+		// token immediately following its corresponding "opening" token,
+		// add an extra blank for separation unless explicitly disabled
+		if p.mode&noExtraBlank == 0 &&
+			last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line &&
+			tok != token.COMMA &&
+			(tok != token.RPAREN || p.prevOpen == token.LPAREN) &&
+			(tok != token.RBRACK || p.prevOpen == token.LBRACK) {
+			p.writeByte(' ', 1)
+		}
+		// ensure that there is a line break after a //-style comment,
+		// before a closing '}' unless explicitly disabled, or at eof
+		needsLinebreak :=
+			last.Text[1] == '/' ||
+				tok == token.RBRACE && p.mode&noExtraLinebreak == 0 ||
+				tok == token.EOF
+		return p.writeCommentSuffix(needsLinebreak)
+	}
+
+	// no comment was written - we should never reach here since
+	// intersperseComments should not be called in that case
+	p.internalError("intersperseComments called without pending comments")
+	return
+}
+
+// whiteWhitespace writes the first n whitespace entries.
+func (p *printer) writeWhitespace(n int) {
+	// write entries
+	for i := 0; i < n; i++ {
+		switch ch := p.wsbuf[i]; ch {
+		case ignore:
+			// ignore!
+		case indent:
+			p.indent++
+		case unindent:
+			p.indent--
+			if p.indent < 0 {
+				p.internalError("negative indentation:", p.indent)
+				p.indent = 0
+			}
+		case newline, formfeed:
+			// A line break immediately followed by a "correcting"
+			// unindent is swapped with the unindent - this permits
+			// proper label positioning. If a comment is between
+			// the line break and the label, the unindent is not
+			// part of the comment whitespace prefix and the comment
+			// will be positioned correctly indented.
+			if i+1 < n && p.wsbuf[i+1] == unindent {
+				// Use a formfeed to terminate the current section.
+				// Otherwise, a long label name on the next line leading
+				// to a wide column may increase the indentation column
+				// of lines before the label; effectively leading to wrong
+				// indentation.
+				p.wsbuf[i], p.wsbuf[i+1] = unindent, formfeed
+				i-- // do it again
+				continue
+			}
+			fallthrough
+		default:
+			p.writeByte(byte(ch), 1)
+		}
+	}
+
+	// shift remaining entries down
+	l := copy(p.wsbuf, p.wsbuf[n:])
+	p.wsbuf = p.wsbuf[:l]
+}
+
+// ----------------------------------------------------------------------------
+// Printing interface
+
+// nlines limits n to maxNewlines.
+func nlimit(n int) int {
+	if n > maxNewlines {
+		n = maxNewlines
+	}
+	return n
+}
+
+func mayCombine(prev token.Token, next byte) (b bool) {
+	switch prev {
+	case token.INT:
+		b = next == '.' // 1.
+	case token.ADD:
+		b = next == '+' // ++
+	case token.SUB:
+		b = next == '-' // --
+	case token.QUO:
+		b = next == '*' // /*
+	case token.LSS:
+		b = next == '-' || next == '<' // <- or <<
+	case token.AND:
+		b = next == '&' || next == '^' // && or &^
+	}
+	return
+}
+
+// print prints a list of "items" (roughly corresponding to syntactic
+// tokens, but also including whitespace and formatting information).
+// It is the only print function that should be called directly from
+// any of the AST printing functions in nodes.go.
+//
+// Whitespace is accumulated until a non-whitespace token appears. Any
+// comments that need to appear before that token are printed first,
+// taking into account the amount and structure of any pending white-
+// space for best comment placement. Then, any leftover whitespace is
+// printed, followed by the actual token.
+//
+func (p *printer) print(args ...interface{}) {
+	for _, arg := range args {
+		// information about the current arg
+		var data string
+		var isLit bool
+		var impliedSemi bool // value for p.impliedSemi after this arg
+
+		// record previous opening token, if any
+		switch p.lastTok {
+		case token.ILLEGAL:
+			// ignore (white space)
+		case token.LPAREN, token.LBRACK:
+			p.prevOpen = p.lastTok
+		default:
+			// other tokens followed any opening token
+			p.prevOpen = token.ILLEGAL
+		}
+
+		switch x := arg.(type) {
+		case pmode:
+			// toggle printer mode
+			p.mode ^= x
+			continue
+
+		case whiteSpace:
+			if x == ignore {
+				// don't add ignore's to the buffer; they
+				// may screw up "correcting" unindents (see
+				// LabeledStmt)
+				continue
+			}
+			i := len(p.wsbuf)
+			if i == cap(p.wsbuf) {
+				// Whitespace sequences are very short so this should
+				// never happen. Handle gracefully (but possibly with
+				// bad comment placement) if it does happen.
+				p.writeWhitespace(i)
+				i = 0
+			}
+			p.wsbuf = p.wsbuf[0 : i+1]
+			p.wsbuf[i] = x
+			if x == newline || x == formfeed {
+				// newlines affect the current state (p.impliedSemi)
+				// and not the state after printing arg (impliedSemi)
+				// because comments can be interspersed before the arg
+				// in this case
+				p.impliedSemi = false
+			}
+			p.lastTok = token.ILLEGAL
+			continue
+
+		case *ast.Ident:
+			data = x.Name
+			impliedSemi = true
+			p.lastTok = token.IDENT
+
+		case *ast.BasicLit:
+			data = x.Value
+			isLit = true
+			impliedSemi = true
+			p.lastTok = x.Kind
+
+		case token.Token:
+			s := x.String()
+			if mayCombine(p.lastTok, s[0]) {
+				// the previous and the current token must be
+				// separated by a blank otherwise they combine
+				// into a different incorrect token sequence
+				// (except for token.INT followed by a '.' this
+				// should never happen because it is taken care
+				// of via binary expression formatting)
+				if len(p.wsbuf) != 0 {
+					p.internalError("whitespace buffer not empty")
+				}
+				p.wsbuf = p.wsbuf[0:1]
+				p.wsbuf[0] = ' '
+			}
+			data = s
+			// some keywords followed by a newline imply a semicolon
+			switch x {
+			case token.BREAK, token.CONTINUE, token.FALLTHROUGH, token.RETURN,
+				token.INC, token.DEC, token.RPAREN, token.RBRACK, token.RBRACE:
+				impliedSemi = true
+			}
+			p.lastTok = x
+
+		case token.Pos:
+			if x.IsValid() {
+				p.pos = p.posFor(x) // accurate position of next item
+			}
+			continue
+
+		case string:
+			// incorrect AST - print error message
+			data = x
+			isLit = true
+			impliedSemi = true
+			p.lastTok = token.STRING
+
+		default:
+			fmt.Fprintf(os.Stderr, "print: unsupported argument %v (%T)\n", arg, arg)
+			panic("go/printer type")
+		}
+		// data != ""
+
+		next := p.pos // estimated/accurate position of next item
+		wroteNewline, droppedFF := p.flush(next, p.lastTok)
+
+		// intersperse extra newlines if present in the source and
+		// if they don't cause extra semicolons (don't do this in
+		// flush as it will cause extra newlines at the end of a file)
+		if !p.impliedSemi {
+			n := nlimit(next.Line - p.pos.Line)
+			// don't exceed maxNewlines if we already wrote one
+			if wroteNewline && n == maxNewlines {
+				n = maxNewlines - 1
+			}
+			if n > 0 {
+				ch := byte('\n')
+				if droppedFF {
+					ch = '\f' // use formfeed since we dropped one before
+				}
+				p.writeByte(ch, n)
+				impliedSemi = false
+			}
+		}
+
+		// the next token starts now - record its line number if requested
+		if p.linePtr != nil {
+			*p.linePtr = p.out.Line
+			p.linePtr = nil
+		}
+
+		p.writeString(next, data, isLit)
+		p.impliedSemi = impliedSemi
+	}
+}
+
+// flush prints any pending comments and whitespace occurring textually
+// before the position of the next token tok. The flush result indicates
+// if a newline was written or if a formfeed was dropped from the whitespace
+// buffer.
+//
+func (p *printer) flush(next token.Position, tok token.Token) (wroteNewline, droppedFF bool) {
+	if p.commentBefore(next) {
+		// if there are comments before the next item, intersperse them
+		wroteNewline, droppedFF = p.intersperseComments(next, tok)
+	} else {
+		// otherwise, write any leftover whitespace
+		p.writeWhitespace(len(p.wsbuf))
+	}
+	return
+}
+
+// getNode returns the ast.CommentGroup associated with n, if any.
+func getDoc(n ast.Node) *ast.CommentGroup {
+	switch n := n.(type) {
+	case *ast.Field:
+		return n.Doc
+	case *ast.ImportSpec:
+		return n.Doc
+	case *ast.ValueSpec:
+		return n.Doc
+	case *ast.TypeSpec:
+		return n.Doc
+	case *ast.GenDecl:
+		return n.Doc
+	case *ast.FuncDecl:
+		return n.Doc
+	case *ast.File:
+		return n.Doc
+	}
+	return nil
+}
+
+func (p *printer) printNode(node interface{}) error {
+	// unpack *CommentedNode, if any
+	var comments []*ast.CommentGroup
+	if cnode, ok := node.(*CommentedNode); ok {
+		node = cnode.Node
+		comments = cnode.Comments
+	}
+
+	if comments != nil {
+		// commented node - restrict comment list to relevant range
+		n, ok := node.(ast.Node)
+		if !ok {
+			goto unsupported
+		}
+		beg := n.Pos()
+		end := n.End()
+		// if the node has associated documentation,
+		// include that commentgroup in the range
+		// (the comment list is sorted in the order
+		// of the comment appearance in the source code)
+		if doc := getDoc(n); doc != nil {
+			beg = doc.Pos()
+		}
+		// token.Pos values are global offsets, we can
+		// compare them directly
+		i := 0
+		for i < len(comments) && comments[i].End() < beg {
+			i++
+		}
+		j := i
+		for j < len(comments) && comments[j].Pos() < end {
+			j++
+		}
+		if i < j {
+			p.comments = comments[i:j]
+		}
+	} else if n, ok := node.(*ast.File); ok {
+		// use ast.File comments, if any
+		p.comments = n.Comments
+	}
+
+	// if there are no comments, use node comments
+	p.useNodeComments = p.comments == nil
+
+	// get comments ready for use
+	p.nextComment()
+
+	// format node
+	switch n := node.(type) {
+	case ast.Expr:
+		p.expr(n)
+	case ast.Stmt:
+		// A labeled statement will un-indent to position the label.
+		// Set p.indent to 1 so we don't get indent "underflow".
+		if _, ok := n.(*ast.LabeledStmt); ok {
+			p.indent = 1
+		}
+		p.stmt(n, false)
+	case ast.Decl:
+		p.decl(n)
+	case ast.Spec:
+		p.spec(n, 1, false)
+	case []ast.Stmt:
+		// A labeled statement will un-indent to position the label.
+		// Set p.indent to 1 so we don't get indent "underflow".
+		for _, s := range n {
+			if _, ok := s.(*ast.LabeledStmt); ok {
+				p.indent = 1
+			}
+		}
+		p.stmtList(n, 0, false)
+	case []ast.Decl:
+		p.declList(n)
+	case *ast.File:
+		p.file(n)
+	default:
+		goto unsupported
+	}
+
+	return nil
+
+unsupported:
+	return fmt.Errorf("go/printer: unsupported node type %T", node)
+}
+
+// ----------------------------------------------------------------------------
+// Trimmer
+
+// A trimmer is an io.Writer filter for stripping tabwriter.Escape
+// characters, trailing blanks and tabs, and for converting formfeed
+// and vtab characters into newlines and htabs (in case no tabwriter
+// is used). Text bracketed by tabwriter.Escape characters is passed
+// through unchanged.
+//
+type trimmer struct {
+	output io.Writer
+	state  int
+	space  []byte
+}
+
+// trimmer is implemented as a state machine.
+// It can be in one of the following states:
+const (
+	inSpace  = iota // inside space
+	inEscape        // inside text bracketed by tabwriter.Escapes
+	inText          // inside text
+)
+
+func (p *trimmer) resetSpace() {
+	p.state = inSpace
+	p.space = p.space[0:0]
+}
+
+// Design note: It is tempting to eliminate extra blanks occurring in
+//              whitespace in this function as it could simplify some
+//              of the blanks logic in the node printing functions.
+//              However, this would mess up any formatting done by
+//              the tabwriter.
+
+var aNewline = []byte("\n")
+
+func (p *trimmer) Write(data []byte) (n int, err error) {
+	// invariants:
+	// p.state == inSpace:
+	//	p.space is unwritten
+	// p.state == inEscape, inText:
+	//	data[m:n] is unwritten
+	m := 0
+	var b byte
+	for n, b = range data {
+		if b == '\v' {
+			b = '\t' // convert to htab
+		}
+		switch p.state {
+		case inSpace:
+			switch b {
+			case '\t', ' ':
+				p.space = append(p.space, b)
+			case '\n', '\f':
+				p.resetSpace() // discard trailing space
+				_, err = p.output.Write(aNewline)
+			case tabwriter.Escape:
+				_, err = p.output.Write(p.space)
+				p.state = inEscape
+				m = n + 1 // +1: skip tabwriter.Escape
+			default:
+				_, err = p.output.Write(p.space)
+				p.state = inText
+				m = n
+			}
+		case inEscape:
+			if b == tabwriter.Escape {
+				_, err = p.output.Write(data[m:n])
+				p.resetSpace()
+			}
+		case inText:
+			switch b {
+			case '\t', ' ':
+				_, err = p.output.Write(data[m:n])
+				p.resetSpace()
+				p.space = append(p.space, b)
+			case '\n', '\f':
+				_, err = p.output.Write(data[m:n])
+				p.resetSpace()
+				_, err = p.output.Write(aNewline)
+			case tabwriter.Escape:
+				_, err = p.output.Write(data[m:n])
+				p.state = inEscape
+				m = n + 1 // +1: skip tabwriter.Escape
+			}
+		default:
+			panic("unreachable")
+		}
+		if err != nil {
+			return
+		}
+	}
+	n = len(data)
+
+	switch p.state {
+	case inEscape, inText:
+		_, err = p.output.Write(data[m:n])
+		p.resetSpace()
+	}
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Public interface
+
+// A Mode value is a set of flags (or 0). They control printing.
+type Mode uint
+
+const (
+	RawFormat Mode = 1 << iota // do not use a tabwriter; if set, UseSpaces is ignored
+	TabIndent                  // use tabs for indentation independent of UseSpaces
+	UseSpaces                  // use spaces instead of tabs for alignment
+	SourcePos                  // emit //line comments to preserve original source positions
+)
+
+// A Config node controls the output of Fprint.
+type Config struct {
+	Mode     Mode // default: 0
+	Tabwidth int  // default: 8
+	Indent   int  // default: 0 (all code is indented at least by this much)
+}
+
+// fprint implements Fprint and takes a nodesSizes map for setting up the printer state.
+func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{}, nodeSizes map[ast.Node]int) (err error) {
+	// print node
+	var p printer
+	p.init(cfg, fset, nodeSizes)
+	if err = p.printNode(node); err != nil {
+		return
+	}
+	// print outstanding comments
+	p.impliedSemi = false // EOF acts like a newline
+	p.flush(token.Position{Offset: infinity, Line: infinity}, token.EOF)
+
+	// redirect output through a trimmer to eliminate trailing whitespace
+	// (Input to a tabwriter must be untrimmed since trailing tabs provide
+	// formatting information. The tabwriter could provide trimming
+	// functionality but no tabwriter is used when RawFormat is set.)
+	output = &trimmer{output: output}
+
+	// redirect output through a tabwriter if necessary
+	if cfg.Mode&RawFormat == 0 {
+		minwidth := cfg.Tabwidth
+
+		padchar := byte('\t')
+		if cfg.Mode&UseSpaces != 0 {
+			padchar = ' '
+		}
+
+		twmode := tabwriter.DiscardEmptyColumns
+		if cfg.Mode&TabIndent != 0 {
+			minwidth = 0
+			twmode |= tabwriter.TabIndent
+		}
+
+		output = tabwriter.NewWriter(output, minwidth, cfg.Tabwidth, 1, padchar, twmode)
+	}
+
+	// write printer result via tabwriter/trimmer to output
+	if _, err = output.Write(p.output); err != nil {
+		return
+	}
+
+	// flush tabwriter, if any
+	if tw, _ := output.(*tabwriter.Writer); tw != nil {
+		err = tw.Flush()
+	}
+
+	return
+}
+
+// A CommentedNode bundles an AST node and corresponding comments.
+// It may be provided as argument to any of the Fprint functions.
+//
+type CommentedNode struct {
+	Node     interface{} // *ast.File, or ast.Expr, ast.Decl, ast.Spec, or ast.Stmt
+	Comments []*ast.CommentGroup
+}
+
+// Fprint "pretty-prints" an AST node to output for a given configuration cfg.
+// Position information is interpreted relative to the file set fset.
+// The node type must be *ast.File, *CommentedNode, []ast.Decl, []ast.Stmt,
+// or assignment-compatible to ast.Expr, ast.Decl, ast.Spec, or ast.Stmt.
+//
+func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{}) error {
+	return cfg.fprint(output, fset, node, make(map[ast.Node]int))
+}
+
+// Fprint "pretty-prints" an AST node to output.
+// It calls Config.Fprint with default settings.
+//
+func Fprint(output io.Writer, fset *token.FileSet, node interface{}) error {
+	return (&Config{Tabwidth: 8}).Fprint(output, fset, node)
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/printer_test.go b/third_party/gofrontend/libgo/go/go/printer/printer_test.go
new file mode 100644
index 0000000..306928a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/printer_test.go
@@ -0,0 +1,569 @@
+// 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 printer
+
+import (
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"path/filepath"
+	"testing"
+	"time"
+)
+
+const (
+	dataDir  = "testdata"
+	tabwidth = 8
+)
+
+var update = flag.Bool("update", false, "update golden files")
+
+var fset = token.NewFileSet()
+
+type checkMode uint
+
+const (
+	export checkMode = 1 << iota
+	rawFormat
+	idempotent
+)
+
+// format parses src, prints the corresponding AST, verifies the resulting
+// src is syntactically correct, and returns the resulting src or an error
+// if any.
+func format(src []byte, mode checkMode) ([]byte, error) {
+	// parse src
+	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
+	if err != nil {
+		return nil, fmt.Errorf("parse: %s\n%s", err, src)
+	}
+
+	// filter exports if necessary
+	if mode&export != 0 {
+		ast.FileExports(f) // ignore result
+		f.Comments = nil   // don't print comments that are not in AST
+	}
+
+	// determine printer configuration
+	cfg := Config{Tabwidth: tabwidth}
+	if mode&rawFormat != 0 {
+		cfg.Mode |= RawFormat
+	}
+
+	// print AST
+	var buf bytes.Buffer
+	if err := cfg.Fprint(&buf, fset, f); err != nil {
+		return nil, fmt.Errorf("print: %s", err)
+	}
+
+	// make sure formatted output is syntactically correct
+	res := buf.Bytes()
+	if _, err := parser.ParseFile(fset, "", res, 0); err != nil {
+		return nil, fmt.Errorf("re-parse: %s\n%s", err, buf.Bytes())
+	}
+
+	return res, nil
+}
+
+// lineAt returns the line in text starting at offset offs.
+func lineAt(text []byte, offs int) []byte {
+	i := offs
+	for i < len(text) && text[i] != '\n' {
+		i++
+	}
+	return text[offs:i]
+}
+
+// diff compares a and b.
+func diff(aname, bname string, a, b []byte) error {
+	var buf bytes.Buffer // holding long error message
+
+	// compare lengths
+	if len(a) != len(b) {
+		fmt.Fprintf(&buf, "\nlength changed: len(%s) = %d, len(%s) = %d", aname, len(a), bname, len(b))
+	}
+
+	// compare contents
+	line := 1
+	offs := 1
+	for i := 0; i < len(a) && i < len(b); i++ {
+		ch := a[i]
+		if ch != b[i] {
+			fmt.Fprintf(&buf, "\n%s:%d:%d: %s", aname, line, i-offs+1, lineAt(a, offs))
+			fmt.Fprintf(&buf, "\n%s:%d:%d: %s", bname, line, i-offs+1, lineAt(b, offs))
+			fmt.Fprintf(&buf, "\n\n")
+			break
+		}
+		if ch == '\n' {
+			line++
+			offs = i + 1
+		}
+	}
+
+	if buf.Len() > 0 {
+		return errors.New(buf.String())
+	}
+	return nil
+}
+
+func runcheck(t *testing.T, source, golden string, mode checkMode) {
+	src, err := ioutil.ReadFile(source)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	res, err := format(src, mode)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	// update golden files if necessary
+	if *update {
+		if err := ioutil.WriteFile(golden, res, 0644); err != nil {
+			t.Error(err)
+		}
+		return
+	}
+
+	// get golden
+	gld, err := ioutil.ReadFile(golden)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	// formatted source and golden must be the same
+	if err := diff(source, golden, res, gld); err != nil {
+		t.Error(err)
+		return
+	}
+
+	if mode&idempotent != 0 {
+		// formatting golden must be idempotent
+		// (This is very difficult to achieve in general and for now
+		// it is only checked for files explicitly marked as such.)
+		res, err = format(gld, mode)
+		if err := diff(golden, fmt.Sprintf("format(%s)", golden), gld, res); err != nil {
+			t.Errorf("golden is not idempotent: %s", err)
+		}
+	}
+}
+
+func check(t *testing.T, source, golden string, mode checkMode) {
+	// start a timer to produce a time-out signal
+	tc := make(chan int)
+	go func() {
+		time.Sleep(10 * time.Second) // plenty of a safety margin, even for very slow machines
+		tc <- 0
+	}()
+
+	// run the test
+	cc := make(chan int)
+	go func() {
+		runcheck(t, source, golden, mode)
+		cc <- 0
+	}()
+
+	// wait for the first finisher
+	select {
+	case <-tc:
+		// test running past time out
+		t.Errorf("%s: running too slowly", source)
+	case <-cc:
+		// test finished within allotted time margin
+	}
+}
+
+type entry struct {
+	source, golden string
+	mode           checkMode
+}
+
+// Use go test -update to create/update the respective golden files.
+var data = []entry{
+	{"empty.input", "empty.golden", idempotent},
+	{"comments.input", "comments.golden", 0},
+	{"comments.input", "comments.x", export},
+	{"comments2.input", "comments2.golden", idempotent},
+	{"linebreaks.input", "linebreaks.golden", idempotent},
+	{"expressions.input", "expressions.golden", idempotent},
+	{"expressions.input", "expressions.raw", rawFormat | idempotent},
+	{"declarations.input", "declarations.golden", 0},
+	{"statements.input", "statements.golden", 0},
+	{"slow.input", "slow.golden", idempotent},
+}
+
+func TestFiles(t *testing.T) {
+	for _, e := range data {
+		source := filepath.Join(dataDir, e.source)
+		golden := filepath.Join(dataDir, e.golden)
+		check(t, source, golden, e.mode)
+		// TODO(gri) check that golden is idempotent
+		//check(t, golden, golden, e.mode)
+	}
+}
+
+// TestLineComments, using a simple test case, checks that consecutive line
+// comments are properly terminated with a newline even if the AST position
+// information is incorrect.
+//
+func TestLineComments(t *testing.T) {
+	const src = `// comment 1
+	// comment 2
+	// comment 3
+	package main
+	`
+
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
+	if err != nil {
+		panic(err) // error in test
+	}
+
+	var buf bytes.Buffer
+	fset = token.NewFileSet() // use the wrong file set
+	Fprint(&buf, fset, f)
+
+	nlines := 0
+	for _, ch := range buf.Bytes() {
+		if ch == '\n' {
+			nlines++
+		}
+	}
+
+	const expected = 3
+	if nlines < expected {
+		t.Errorf("got %d, expected %d\n", nlines, expected)
+		t.Errorf("result:\n%s", buf.Bytes())
+	}
+}
+
+// Verify that the printer can be invoked during initialization.
+func init() {
+	const name = "foobar"
+	var buf bytes.Buffer
+	if err := Fprint(&buf, fset, &ast.Ident{Name: name}); err != nil {
+		panic(err) // error in test
+	}
+	// in debug mode, the result contains additional information;
+	// ignore it
+	if s := buf.String(); !debug && s != name {
+		panic("got " + s + ", want " + name)
+	}
+}
+
+// Verify that the printer doesn't crash if the AST contains BadXXX nodes.
+func TestBadNodes(t *testing.T) {
+	const src = "package p\n("
+	const res = "package p\nBadDecl\n"
+	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
+	if err == nil {
+		t.Error("expected illegal program") // error in test
+	}
+	var buf bytes.Buffer
+	Fprint(&buf, fset, f)
+	if buf.String() != res {
+		t.Errorf("got %q, expected %q", buf.String(), res)
+	}
+}
+
+// testComment verifies that f can be parsed again after printing it
+// with its first comment set to comment at any possible source offset.
+func testComment(t *testing.T, f *ast.File, srclen int, comment *ast.Comment) {
+	f.Comments[0].List[0] = comment
+	var buf bytes.Buffer
+	for offs := 0; offs <= srclen; offs++ {
+		buf.Reset()
+		// Printing f should result in a correct program no
+		// matter what the (incorrect) comment position is.
+		if err := Fprint(&buf, fset, f); err != nil {
+			t.Error(err)
+		}
+		if _, err := parser.ParseFile(fset, "", buf.Bytes(), 0); err != nil {
+			t.Fatalf("incorrect program for pos = %d:\n%s", comment.Slash, buf.String())
+		}
+		// Position information is just an offset.
+		// Move comment one byte down in the source.
+		comment.Slash++
+	}
+}
+
+// Verify that the printer produces a correct program
+// even if the position information of comments introducing newlines
+// is incorrect.
+func TestBadComments(t *testing.T) {
+	const src = `
+// first comment - text and position changed by test
+package p
+import "fmt"
+const pi = 3.14 // rough circle
+var (
+	x, y, z int = 1, 2, 3
+	u, v float64
+)
+func fibo(n int) {
+	if n < 2 {
+		return n /* seed values */
+	}
+	return fibo(n-1) + fibo(n-2)
+}
+`
+
+	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
+	if err != nil {
+		t.Error(err) // error in test
+	}
+
+	comment := f.Comments[0].List[0]
+	pos := comment.Pos()
+	if fset.Position(pos).Offset != 1 {
+		t.Error("expected offset 1") // error in test
+	}
+
+	testComment(t, f, len(src), &ast.Comment{Slash: pos, Text: "//-style comment"})
+	testComment(t, f, len(src), &ast.Comment{Slash: pos, Text: "/*-style comment */"})
+	testComment(t, f, len(src), &ast.Comment{Slash: pos, Text: "/*-style \n comment */"})
+	testComment(t, f, len(src), &ast.Comment{Slash: pos, Text: "/*-style comment \n\n\n */"})
+}
+
+type visitor chan *ast.Ident
+
+func (v visitor) Visit(n ast.Node) (w ast.Visitor) {
+	if ident, ok := n.(*ast.Ident); ok {
+		v <- ident
+	}
+	return v
+}
+
+// idents is an iterator that returns all idents in f via the result channel.
+func idents(f *ast.File) <-chan *ast.Ident {
+	v := make(visitor)
+	go func() {
+		ast.Walk(v, f)
+		close(v)
+	}()
+	return v
+}
+
+// identCount returns the number of identifiers found in f.
+func identCount(f *ast.File) int {
+	n := 0
+	for _ = range idents(f) {
+		n++
+	}
+	return n
+}
+
+// Verify that the SourcePos mode emits correct //line comments
+// by testing that position information for matching identifiers
+// is maintained.
+func TestSourcePos(t *testing.T) {
+	const src = `
+package p
+import ( "go/printer"; "math" )
+const pi = 3.14; var x = 0
+type t struct{ x, y, z int; u, v, w float32 }
+func (t *t) foo(a, b, c int) int {
+	return a*t.x + b*t.y +
+		// two extra lines here
+		// ...
+		c*t.z
+}
+`
+
+	// parse original
+	f1, err := parser.ParseFile(fset, "src", src, parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// pretty-print original
+	var buf bytes.Buffer
+	err = (&Config{Mode: UseSpaces | SourcePos, Tabwidth: 8}).Fprint(&buf, fset, f1)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// parse pretty printed original
+	// (//line comments must be interpreted even w/o parser.ParseComments set)
+	f2, err := parser.ParseFile(fset, "", buf.Bytes(), 0)
+	if err != nil {
+		t.Fatalf("%s\n%s", err, buf.Bytes())
+	}
+
+	// At this point the position information of identifiers in f2 should
+	// match the position information of corresponding identifiers in f1.
+
+	// number of identifiers must be > 0 (test should run) and must match
+	n1 := identCount(f1)
+	n2 := identCount(f2)
+	if n1 == 0 {
+		t.Fatal("got no idents")
+	}
+	if n2 != n1 {
+		t.Errorf("got %d idents; want %d", n2, n1)
+	}
+
+	// verify that all identifiers have correct line information
+	i2range := idents(f2)
+	for i1 := range idents(f1) {
+		i2 := <-i2range
+
+		if i2.Name != i1.Name {
+			t.Errorf("got ident %s; want %s", i2.Name, i1.Name)
+		}
+
+		l1 := fset.Position(i1.Pos()).Line
+		l2 := fset.Position(i2.Pos()).Line
+		if l2 != l1 {
+			t.Errorf("got line %d; want %d for %s", l2, l1, i1.Name)
+		}
+	}
+
+	if t.Failed() {
+		t.Logf("\n%s", buf.Bytes())
+	}
+}
+
+var decls = []string{
+	`import "fmt"`,
+	"const pi = 3.1415\nconst e = 2.71828\n\nvar x = pi",
+	"func sum(x, y int) int\t{ return x + y }",
+}
+
+func TestDeclLists(t *testing.T) {
+	for _, src := range decls {
+		file, err := parser.ParseFile(fset, "", "package p;"+src, parser.ParseComments)
+		if err != nil {
+			panic(err) // error in test
+		}
+
+		var buf bytes.Buffer
+		err = Fprint(&buf, fset, file.Decls) // only print declarations
+		if err != nil {
+			panic(err) // error in test
+		}
+
+		out := buf.String()
+		if out != src {
+			t.Errorf("\ngot : %q\nwant: %q\n", out, src)
+		}
+	}
+}
+
+var stmts = []string{
+	"i := 0",
+	"select {}\nvar a, b = 1, 2\nreturn a + b",
+	"go f()\ndefer func() {}()",
+}
+
+func TestStmtLists(t *testing.T) {
+	for _, src := range stmts {
+		file, err := parser.ParseFile(fset, "", "package p; func _() {"+src+"}", parser.ParseComments)
+		if err != nil {
+			panic(err) // error in test
+		}
+
+		var buf bytes.Buffer
+		err = Fprint(&buf, fset, file.Decls[0].(*ast.FuncDecl).Body.List) // only print statements
+		if err != nil {
+			panic(err) // error in test
+		}
+
+		out := buf.String()
+		if out != src {
+			t.Errorf("\ngot : %q\nwant: %q\n", out, src)
+		}
+	}
+}
+
+func TestBaseIndent(t *testing.T) {
+	// The testfile must not contain multi-line raw strings since those
+	// are not indented (because their values must not change) and make
+	// this test fail.
+	const filename = "printer.go"
+	src, err := ioutil.ReadFile(filename)
+	if err != nil {
+		panic(err) // error in test
+	}
+
+	file, err := parser.ParseFile(fset, filename, src, 0)
+	if err != nil {
+		panic(err) // error in test
+	}
+
+	var buf bytes.Buffer
+	for indent := 0; indent < 4; indent++ {
+		buf.Reset()
+		(&Config{Tabwidth: tabwidth, Indent: indent}).Fprint(&buf, fset, file)
+		// all code must be indented by at least 'indent' tabs
+		lines := bytes.Split(buf.Bytes(), []byte{'\n'})
+		for i, line := range lines {
+			if len(line) == 0 {
+				continue // empty lines don't have indentation
+			}
+			n := 0
+			for j, b := range line {
+				if b != '\t' {
+					// end of indentation
+					n = j
+					break
+				}
+			}
+			if n < indent {
+				t.Errorf("line %d: got only %d tabs; want at least %d: %q", i, n, indent, line)
+			}
+		}
+	}
+}
+
+// TestFuncType tests that an ast.FuncType with a nil Params field
+// can be printed (per go/ast specification). Test case for issue 3870.
+func TestFuncType(t *testing.T) {
+	src := &ast.File{
+		Name: &ast.Ident{Name: "p"},
+		Decls: []ast.Decl{
+			&ast.FuncDecl{
+				Name: &ast.Ident{Name: "f"},
+				Type: &ast.FuncType{},
+			},
+		},
+	}
+
+	var buf bytes.Buffer
+	if err := Fprint(&buf, fset, src); err != nil {
+		t.Fatal(err)
+	}
+	got := buf.String()
+
+	const want = `package p
+
+func f()
+`
+
+	if got != want {
+		t.Fatalf("got:\n%s\nwant:\n%s\n", got, want)
+	}
+}
+
+// TextX is a skeleton test that can be filled in for debugging one-off cases.
+// Do not remove.
+func TestX(t *testing.T) {
+	const src = `
+package p
+func _() {}
+`
+	_, err := format([]byte(src), 0)
+	if err != nil {
+		t.Error(err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/comments.golden b/third_party/gofrontend/libgo/go/go/printer/testdata/comments.golden
new file mode 100644
index 0000000..b1af795
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/comments.golden
@@ -0,0 +1,643 @@
+// 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.
+
+// This is a package for testing comment placement by go/printer.
+//
+package main
+
+import "fmt"	// fmt
+
+const c0 = 0	// zero
+const (
+	c1	= iota	// c1
+	c2		// c2
+)
+
+// Alignment of comments in declarations>
+const (
+	_	T	= iota	// comment
+	_			// comment
+	_			// comment
+	_	= iota + 10
+	_	// comments
+
+	_		= 10	// comment
+	_	T	= 20	// comment
+)
+
+const (
+	_____	= iota	// foo
+	_		// bar
+	_	= 0	// bal
+	_		// bat
+)
+
+const (
+	_	T	= iota	// comment
+	_			// comment
+	_			// comment
+	_	= iota + 10
+	_		// comment
+	_		= 10
+	_		= 20	// comment
+	_	T	= 0	// comment
+)
+
+// The SZ struct; it is empty.
+type SZ struct{}
+
+// The S0 struct; no field is exported.
+type S0 struct {
+	int
+	x, y, z	int	// 3 unexported fields
+}
+
+// The S1 struct; some fields are not exported.
+type S1 struct {
+	S0
+	A, B, C	float	// 3 exported fields
+	D, b, c	int	// 2 unexported fields
+}
+
+// The S2 struct; all fields are exported.
+type S2 struct {
+	S1
+	A, B, C	float	// 3 exported fields
+}
+
+// The IZ interface; it is empty.
+type SZ interface{}
+
+// The I0 interface; no method is exported.
+type I0 interface {
+	f(x int) int	// unexported method
+}
+
+// The I1 interface; some methods are not exported.
+type I1 interface {
+	I0
+	F(x float) float	// exported methods
+	g(x int) int		// unexported method
+}
+
+// The I2 interface; all methods are exported.
+type I2 interface {
+	I0
+	F(x float) float	// exported method
+	G(x float) float	// exported method
+}
+
+// The S3 struct; all comments except for the last one must appear in the export.
+type S3 struct {
+	// lead comment for F1
+	F1	int	// line comment for F1
+	// lead comment for F2
+	F2	int	// line comment for F2
+	f3	int	// f3 is not exported
+}
+
+// This comment group should be separated
+// with a newline from the next comment
+// group.
+
+// This comment should NOT be associated with the next declaration.
+
+var x int	// x
+var ()
+
+// This comment SHOULD be associated with f0.
+func f0() {
+	const pi = 3.14	// pi
+	var s1 struct{}	/* an empty struct */	/* foo */
+	// a struct constructor
+	// --------------------
+	var s2 struct{} = struct{}{}
+	x := pi
+}
+
+//
+// This comment should be associated with f1, with one blank line before the comment.
+//
+func f1() {
+	f0()
+	/* 1 */
+	// 2
+	/* 3 */
+	/* 4 */
+	f0()
+}
+
+func _() {
+	// this comment should be properly indented
+}
+
+func _(x int) int {
+	if x < 0 {	// the tab printed before this comment's // must not affect the remaining lines
+		return -x	// this statement should be properly indented
+	}
+	if x < 0 {	/* the tab printed before this comment's /* must not affect the remaining lines */
+		return -x	// this statement should be properly indented
+	}
+	return x
+}
+
+func typeswitch(x interface{}) {
+	switch v := x.(type) {
+	case bool, int, float:
+	case string:
+	default:
+	}
+
+	switch x.(type) {
+	}
+
+	switch v0, ok := x.(int); v := x.(type) {
+	}
+
+	switch v0, ok := x.(int); x.(type) {
+	case byte:	// this comment should be on the same line as the keyword
+		// this comment should be normally indented
+		_ = 0
+	case bool, int, float:
+		// this comment should be indented
+	case string:
+	default:
+		// this comment should be indented
+	}
+	// this comment should not be indented
+}
+
+//
+// Indentation of comments after possibly indented multi-line constructs
+// (test cases for issue 3147).
+//
+
+func _() {
+	s := 1 +
+		2
+	// should be indented like s
+}
+
+func _() {
+	s := 1 +
+		2	// comment
+	// should be indented like s
+}
+
+func _() {
+	s := 1 +
+		2	// comment
+	// should be indented like s
+	_ = 0
+}
+
+func _() {
+	s := 1 +
+		2
+	// should be indented like s
+	_ = 0
+}
+
+func _() {
+	s := 1 +
+		2
+
+	// should be indented like s
+}
+
+func _() {
+	s := 1 +
+		2	// comment
+
+	// should be indented like s
+}
+
+func _() {
+	s := 1 +
+		2	// comment
+
+	// should be indented like s
+	_ = 0
+}
+
+func _() {
+	s := 1 +
+		2
+
+	// should be indented like s
+	_ = 0
+}
+
+// Test case from issue 3147.
+func f() {
+	templateText := "a" +	// A
+		"b" +	// B
+		"c"	// C
+
+	// should be aligned with f()
+	f()
+}
+
+// Modified test case from issue 3147.
+func f() {
+	templateText := "a" +	// A
+		"b" +	// B
+		"c"	// C
+
+		// may not be aligned with f() (source is not aligned)
+	f()
+}
+
+//
+// Test cases for alignment of lines in general comments.
+//
+
+func _() {
+	/* freestanding comment
+	   aligned		line
+	   aligned line
+	*/
+}
+
+func _() {
+	/* freestanding comment
+	   aligned		line
+	   aligned line
+	*/
+}
+
+func _() {
+	/* freestanding comment
+	   aligned		line
+	   aligned line */
+}
+
+func _() {
+	/*	freestanding comment
+		aligned		line
+		aligned line
+	*/
+}
+
+func _() {
+	/*	freestanding comment
+		aligned		line
+		aligned line
+	*/
+}
+
+func _() {
+	/*	freestanding comment
+		aligned		line
+		aligned line */
+}
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned		line
+	   aligned line
+	*/
+}
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned		line
+	   aligned line
+	*/
+}
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned		line
+	   aligned line */
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned		line
+		aligned line
+	*/
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned		line
+		aligned line
+	*/
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned		line
+		aligned line */
+}
+
+func _() {
+	/* freestanding comment
+	   aligned line
+	*/
+}
+
+func _() {
+	/* freestanding comment
+	   aligned line
+	*/
+}
+
+func _() {
+	/* freestanding comment
+	   aligned line */
+}
+
+func _() {
+	/*	freestanding comment
+		aligned line
+	*/
+}
+
+func _() {
+	/*	freestanding comment
+		aligned line
+	*/
+}
+
+func _() {
+	/*	freestanding comment
+		aligned line */
+}
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned line
+	*/
+}
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned line
+	*/
+}
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned line */
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned line
+	*/
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned line
+	*/
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned line */
+}
+
+/*
+ * line
+ * of
+ * stars
+ */
+
+/* another line
+ * of
+ * stars */
+
+/*	and another line
+ *	of
+ *	stars */
+
+/* a line of
+ * stars */
+
+/*	and another line of
+ *	stars */
+
+/* a line of stars
+ */
+
+/*	and another line of
+ */
+
+/* a line of stars
+ */
+
+/*	and another line of
+ */
+
+/*
+aligned in middle
+here
+        not here
+*/
+
+/*
+blank line in middle:
+
+with no leading spaces on blank line.
+*/
+
+/*
+   aligned in middle
+   here
+           not here
+*/
+
+/*
+	blank line in middle:
+
+	with no leading spaces on blank line.
+*/
+
+func _() {
+	/*
+	 * line
+	 * of
+	 * stars
+	 */
+
+	/*
+		aligned in middle
+		here
+			not here
+	*/
+
+	/*
+		blank line in middle:
+
+		with no leading spaces on blank line.
+	*/
+}
+
+// Some interesting interspersed comments.
+// See below for more common cases.
+func _( /* this */ x /* is */ /* an */ int) {
+}
+
+func _( /* no params - extra blank before and after comment */ )	{}
+func _(a, b int /* params - no extra blank after comment */)		{}
+
+func _()	{ f( /* no args - extra blank before and after comment */ ) }
+func _()	{ f(a, b /* args - no extra blank after comment */) }
+
+func _() {
+	f( /* no args - extra blank before and after comment */ )
+	f(a, b /* args - no extra blank after comment */)
+}
+
+func ( /* comment1 */ T /* comment2 */) _()	{}
+
+func _()	{ /* "short-ish one-line functions with comments are formatted as multi-line functions */ }
+func _()	{ x := 0; /* comment */ y = x /* comment */ }
+
+func _() {
+	_ = 0
+	/* closing curly brace should be on new line */
+}
+
+func _() {
+	_ = []int{0, 1 /* don't introduce a newline after this comment - was issue 1365 */}
+}
+
+// Test cases from issue 1542:
+// Comments must not be placed before commas and cause invalid programs.
+func _() {
+	var a = []int{1, 2	/*jasldf*/}
+	_ = a
+}
+
+func _() {
+	var a = []int{1, 2}/*jasldf
+	 */
+
+	_ = a
+}
+
+func _() {
+	var a = []int{1, 2}// jasldf
+
+	_ = a
+}
+
+// Comments immediately adjacent to punctuation followed by a newline
+// remain after the punctuation (looks better and permits alignment of
+// comments).
+func _() {
+	_ = T{
+		1,	// comment after comma
+		2,	/* comment after comma */
+		3,	// comment after comma
+	}
+	_ = T{
+		1,	// comment after comma
+		2,	/* comment after comma */
+		3,	// comment after comma
+	}
+	_ = T{
+		/* comment before literal */ 1,
+		2,	/* comment before comma - ok to move after comma */
+		3,	/* comment before comma - ok to move after comma */
+	}
+
+	for i = 0;	// comment after semicolon
+	i < 9;		/* comment after semicolon */
+	i++ {		// comment after opening curly brace
+	}
+
+	// TODO(gri) the last comment in this example should be aligned */
+	for i = 0;	// comment after semicolon
+	i < 9;		/* comment before semicolon - ok to move after semicolon */
+	i++ /* comment before opening curly brace */ {
+	}
+}
+
+// If there is no newline following punctuation, commas move before the punctuation.
+// This way, commas interspersed in lists stay with the respective expression.
+func f(x /* comment */, y int, z int /* comment */, u, v, w int /* comment */) {
+	f(x /* comment */, y)
+	f(x,	/* comment */
+		y)
+	f(
+		x,	/* comment */
+	)
+}
+
+func g(
+	x int,	/* comment */
+) {
+}
+
+type _ struct {
+	a, b /* comment */, c int
+}
+
+type _ struct {
+	a, b /* comment */, c int
+}
+
+func _() {
+	for a /* comment */, b := range x {
+	}
+}
+
+// Print line directives correctly.
+
+// The following is a legal line directive.
+//line foo:1
+func _() {
+	_ = 0
+	// The following is a legal line directive. It must not be indented:
+//line foo:2
+	_ = 1
+
+	// The following is not a legal line directive (it doesn't start in column 1):
+	//line foo:2
+	_ = 2
+
+	// The following is not a legal line directive (negative line number):
+	//line foo:-3
+	_ = 3
+}
+
+// Line comments with tabs
+func _() {
+	var finput *bufio.Reader	// input file
+	var stderr *bufio.Writer
+	var ftable *bufio.Writer	// y.go file
+	var foutput *bufio.Writer	// y.output file
+
+	var oflag string	// -o [y.go]		- y.go file
+	var vflag string	// -v [y.output]	- y.output file
+	var lflag bool		// -l			- disable line directives
+}
+
+// Trailing white space in comments should be trimmed
+func _() {
+	// This comment has 4 blanks following that should be trimmed:
+	/* Each line of this comment has blanks or tabs following that should be trimmed:
+	   line 2:
+	   line 3:
+	*/
+}
+
+/* This comment is the last entry in this file. It must be printed and should be followed by a newline */
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/comments.input b/third_party/gofrontend/libgo/go/go/printer/testdata/comments.input
new file mode 100644
index 0000000..983e2b2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/comments.input
@@ -0,0 +1,648 @@
+// 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.
+
+// This is a package for testing comment placement by go/printer.
+//
+package main
+
+import "fmt"  // fmt
+
+const c0 = 0  // zero
+const (
+	c1 = iota  // c1
+	c2  // c2
+)
+
+// Alignment of comments in declarations>
+const (
+	_ T = iota  // comment
+	_  // comment
+	_  // comment
+	_ = iota+10
+	_  // comments
+
+	_ = 10  // comment
+	_ T = 20  // comment
+)
+
+const (
+	_____ = iota // foo
+	_ // bar
+	_  = 0    // bal
+	_ // bat
+)
+
+const (
+	_ T = iota // comment
+	_ // comment
+	_ // comment
+	_ = iota + 10
+	_ // comment
+	_ = 10
+	_ = 20 // comment
+	_ T = 0 // comment
+)
+
+// The SZ struct; it is empty.
+type SZ struct {}
+
+// The S0 struct; no field is exported.
+type S0 struct {
+	int
+	x, y, z int  // 3 unexported fields
+}
+
+// The S1 struct; some fields are not exported.
+type S1 struct {
+	S0
+	A, B, C float  // 3 exported fields
+	D, b, c int  // 2 unexported fields
+}
+
+// The S2 struct; all fields are exported.
+type S2 struct {
+	S1
+	A, B, C float  // 3 exported fields
+}
+
+// The IZ interface; it is empty.
+type SZ interface {}
+
+// The I0 interface; no method is exported.
+type I0 interface {
+	f(x int) int  // unexported method
+}
+
+// The I1 interface; some methods are not exported.
+type I1 interface {
+	I0
+	F(x float) float  // exported methods
+	g(x int) int  // unexported method
+}
+
+// The I2 interface; all methods are exported.
+type I2 interface {
+	I0
+	F(x float) float  // exported method
+	G(x float) float  // exported method
+}
+
+// The S3 struct; all comments except for the last one must appear in the export.
+type S3 struct {
+	// lead comment for F1
+	F1 int // line comment for F1
+	// lead comment for F2
+	F2 int // line comment for F2
+	f3 int // f3 is not exported
+}
+
+// This comment group should be separated
+// with a newline from the next comment
+// group.
+
+// This comment should NOT be associated with the next declaration.
+
+var x int  // x
+var ()
+
+
+// This comment SHOULD be associated with f0.
+func f0() {
+	const pi = 3.14  // pi
+	var s1 struct {}  /* an empty struct */ /* foo */
+	// a struct constructor
+	// --------------------
+	var s2 struct {} = struct {}{}
+	x := pi
+}
+//
+// This comment should be associated with f1, with one blank line before the comment.
+//
+func f1() {
+	f0()
+	/* 1 */
+	// 2
+	/* 3 */
+	/* 4 */
+	f0()
+}
+
+
+func _() {
+// this comment should be properly indented
+}
+
+
+func _(x int) int {
+	if x < 0 {  // the tab printed before this comment's // must not affect the remaining lines
+		return -x  // this statement should be properly indented
+	}
+	if x < 0 {  /* the tab printed before this comment's /* must not affect the remaining lines */
+		return -x  // this statement should be properly indented
+	}
+	return x
+}
+
+
+func typeswitch(x interface{}) {
+	switch v := x.(type) {
+	case bool, int, float:
+	case string:
+	default:
+	}
+
+	switch x.(type) {
+	}
+
+	switch v0, ok := x.(int); v := x.(type) {
+	}
+
+	switch v0, ok := x.(int); x.(type) {
+	case byte:  // this comment should be on the same line as the keyword
+		// this comment should be normally indented
+		_ = 0
+	case bool, int, float:
+		// this comment should be indented
+	case string:
+	default:
+		// this comment should be indented
+	}
+	// this comment should not be indented
+}
+
+//
+// Indentation of comments after possibly indented multi-line constructs
+// (test cases for issue 3147).
+//
+
+func _() {
+	s := 1 +
+		2
+// should be indented like s
+}
+
+func _() {
+	s := 1 +
+		2 // comment
+		// should be indented like s
+}
+
+func _() {
+	s := 1 +
+		2 // comment
+	// should be indented like s
+	_ = 0
+}
+
+func _() {
+	s := 1 +
+		2
+	// should be indented like s
+	_ = 0
+}
+
+func _() {
+	s := 1 +
+		2
+
+// should be indented like s
+}
+
+func _() {
+	s := 1 +
+		2 // comment
+
+		// should be indented like s
+}
+
+func _() {
+	s := 1 +
+		2 // comment
+
+	// should be indented like s
+	_ = 0
+}
+
+func _() {
+	s := 1 +
+		2
+
+	// should be indented like s
+	_ = 0
+}
+
+// Test case from issue 3147.
+func f() {
+	templateText := "a" + // A
+		"b" + // B
+		"c" // C
+
+	// should be aligned with f()
+	f()
+}
+
+// Modified test case from issue 3147.
+func f() {
+	templateText := "a" + // A
+		"b" + // B
+		"c" // C
+
+		// may not be aligned with f() (source is not aligned)
+	f()
+}
+
+//
+// Test cases for alignment of lines in general comments.
+//
+
+func _() {
+	/* freestanding comment
+	   aligned		line
+	   aligned line
+	*/
+}
+
+func _() {
+	/* freestanding comment
+	   aligned		line
+	   aligned line
+	   */
+}
+
+func _() {
+	/* freestanding comment
+	   aligned		line
+	   aligned line */
+}
+
+func _() {
+	/*	freestanding comment
+		aligned		line
+		aligned line
+	*/
+}
+
+func _() {
+	/*	freestanding comment
+		aligned		line
+		aligned line
+		*/
+}
+
+func _() {
+	/*	freestanding comment
+		aligned		line
+		aligned line */
+}
+
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned		line
+	   aligned line
+	*/
+}
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned		line
+	   aligned line
+	   */
+}
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned		line
+	   aligned line */
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned		line
+		aligned line
+	*/
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned		line
+		aligned line
+		*/
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned		line
+		aligned line */
+}
+
+func _() {
+	/* freestanding comment
+	   aligned line
+	*/
+}
+
+func _() {
+	/* freestanding comment
+	   aligned line
+	   */
+}
+
+func _() {
+	/* freestanding comment
+	   aligned line */
+}
+
+func _() {
+	/*	freestanding comment
+		aligned line
+	*/
+}
+
+func _() {
+	/*	freestanding comment
+		aligned line
+		*/
+}
+
+func _() {
+	/*	freestanding comment
+		aligned line */
+}
+
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned line
+	*/
+}
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned line
+	   */
+}
+
+func _() {
+	/*
+	   freestanding comment
+	   aligned line */
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned line
+	*/
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned line
+		*/
+}
+
+func _() {
+	/*
+		freestanding comment
+		aligned line */
+}
+
+/*
+ * line
+ * of
+ * stars
+ */
+
+/* another line
+ * of
+ * stars */
+
+/*	and another line
+ *	of
+ *	stars */
+
+/* a line of
+ * stars */
+
+/*	and another line of
+ *	stars */
+
+/* a line of stars
+*/
+
+/*	and another line of
+*/
+
+/* a line of stars
+ */
+
+/*	and another line of
+ */
+
+/*
+aligned in middle
+here
+        not here
+*/
+
+/*
+blank line in middle:
+
+with no leading spaces on blank line.
+*/
+
+/*
+   aligned in middle
+   here
+           not here
+*/
+
+/*
+	blank line in middle:
+
+	with no leading spaces on blank line.
+*/
+
+func _() {
+	/*
+	 * line
+	 * of
+	 * stars
+	 */
+
+	/*
+	aligned in middle
+	here
+		not here
+	*/
+
+	/*
+	blank line in middle:
+
+	with no leading spaces on blank line.
+*/
+}
+
+
+// Some interesting interspersed comments.
+// See below for more common cases.
+func _(/* this */x/* is *//* an */ int) {
+}
+
+func _(/* no params - extra blank before and after comment */) {}
+func _(a, b int /* params - no extra blank after comment */) {}
+
+func _() { f(/* no args - extra blank before and after comment */) }
+func _() { f(a, b /* args - no extra blank after comment */) }
+
+func _() {
+	f(/* no args - extra blank before and after comment */)
+	f(a, b /* args - no extra blank after comment */)
+}
+
+func (/* comment1 */ T /* comment2 */) _() {}
+
+func _() { /* "short-ish one-line functions with comments are formatted as multi-line functions */ }
+func _() { x := 0; /* comment */ y = x /* comment */ }
+
+func _() {
+	_ = 0
+	/* closing curly brace should be on new line */ }
+
+func _() {
+	_ = []int{0, 1 /* don't introduce a newline after this comment - was issue 1365 */}
+}
+
+// Test cases from issue 1542:
+// Comments must not be placed before commas and cause invalid programs.
+func _() {
+	var a = []int{1, 2, /*jasldf*/
+	}
+	_ = a
+}
+
+func _() {
+	var a = []int{1, 2, /*jasldf
+						*/
+	}
+	_ = a
+}
+
+func _() {
+	var a = []int{1, 2, // jasldf
+	}
+	_ = a
+}
+
+// Comments immediately adjacent to punctuation followed by a newline
+// remain after the punctuation (looks better and permits alignment of
+// comments).
+func _() {
+	_ = T{
+		1,    // comment after comma
+		2,    /* comment after comma */
+		3  ,  // comment after comma
+	}
+	_ = T{
+		1  ,// comment after comma
+		2  ,/* comment after comma */
+		3,// comment after comma
+	}
+	_ = T{
+		/* comment before literal */1,
+		2/* comment before comma - ok to move after comma */,
+		3  /* comment before comma - ok to move after comma */  ,
+	}
+
+	for
+		i=0;// comment after semicolon
+		i<9;/* comment after semicolon */
+		i++{// comment after opening curly brace
+	}
+
+	// TODO(gri) the last comment in this example should be aligned */
+	for
+		i=0;// comment after semicolon
+		i<9/* comment before semicolon - ok to move after semicolon */;
+		i++ /* comment before opening curly brace */ {
+	}
+}
+
+// If there is no newline following punctuation, commas move before the punctuation.
+// This way, commas interspersed in lists stay with the respective expression.
+func f(x/* comment */, y int, z int /* comment */, u, v, w int /* comment */) {
+	f(x /* comment */, y)
+	f(x /* comment */, 
+	y)
+	f(
+		x /* comment */,
+	)
+}
+
+func g(
+	x int /* comment */,
+) {}
+
+type _ struct {
+	a, b /* comment */, c int
+}
+
+type _ struct { a, b /* comment */, c int }
+
+func _() {
+	for a /* comment */, b := range x {
+	}
+}
+
+// Print line directives correctly.
+
+// The following is a legal line directive.
+//line foo:1
+func _() {
+	_ = 0
+// The following is a legal line directive. It must not be indented:
+//line foo:2
+	_ = 1
+
+// The following is not a legal line directive (it doesn't start in column 1):
+	//line foo:2
+	_ = 2
+
+// The following is not a legal line directive (negative line number):
+//line foo:-3
+	_ = 3
+}
+
+// Line comments with tabs
+func _() {
+var	finput		*bufio.Reader			// input file
+var	stderr		*bufio.Writer
+var	ftable		*bufio.Writer			// y.go file
+var	foutput		*bufio.Writer			// y.output file
+
+var	oflag		string				// -o [y.go]		- y.go file
+var	vflag		string				// -v [y.output]	- y.output file
+var	lflag		bool				// -l			- disable line directives
+}
+
+// Trailing white space in comments should be trimmed
+func _() {
+// This comment has 4 blanks following that should be trimmed:    
+/* Each line of this comment has blanks or tabs following that should be trimmed:	
+   line 2:    
+   line 3:    			
+*/
+}
+
+/* This comment is the last entry in this file. It must be printed and should be followed by a newline */
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/comments.x b/third_party/gofrontend/libgo/go/go/printer/testdata/comments.x
new file mode 100644
index 0000000..ae77292
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/comments.x
@@ -0,0 +1,56 @@
+// This is a package for testing comment placement by go/printer.
+//
+package main
+
+// The SZ struct; it is empty.
+type SZ struct{}
+
+// The S0 struct; no field is exported.
+type S0 struct {
+	// contains filtered or unexported fields
+}
+
+// The S1 struct; some fields are not exported.
+type S1 struct {
+	S0
+	A, B, C	float	// 3 exported fields
+	D	int	// 2 unexported fields
+	// contains filtered or unexported fields
+}
+
+// The S2 struct; all fields are exported.
+type S2 struct {
+	S1
+	A, B, C	float	// 3 exported fields
+}
+
+// The IZ interface; it is empty.
+type SZ interface{}
+
+// The I0 interface; no method is exported.
+type I0 interface {
+	// contains filtered or unexported methods
+}
+
+// The I1 interface; some methods are not exported.
+type I1 interface {
+	I0
+	F(x float) float	// exported methods
+	// contains filtered or unexported methods
+}
+
+// The I2 interface; all methods are exported.
+type I2 interface {
+	I0
+	F(x float) float	// exported method
+	G(x float) float	// exported method
+}
+
+// The S3 struct; all comments except for the last one must appear in the export.
+type S3 struct {
+	// lead comment for F1
+	F1	int	// line comment for F1
+	// lead comment for F2
+	F2	int	// line comment for F2
+	// contains filtered or unexported fields
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/comments2.golden b/third_party/gofrontend/libgo/go/go/printer/testdata/comments2.golden
new file mode 100644
index 0000000..7676a26
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/comments2.golden
@@ -0,0 +1,105 @@
+// 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.
+
+// This is a package for testing comment placement by go/printer.
+//
+package main
+
+// Test cases for idempotent comment formatting (was issue 1835).
+/*
+c1a
+*/
+/*
+   c1b
+*/
+/* foo
+c1c
+*/
+/* foo
+   c1d
+*/
+/*
+c1e
+foo */
+/*
+   c1f
+   foo */
+
+func f() {
+	/*
+	   c2a
+	*/
+	/*
+	   c2b
+	*/
+	/* foo
+	   c2c
+	*/
+	/* foo
+	   c2d
+	*/
+	/*
+	   c2e
+	   foo */
+	/*
+	   c2f
+	   foo */
+}
+
+func g() {
+	/*
+	   c3a
+	*/
+	/*
+	   c3b
+	*/
+	/* foo
+	   c3c
+	*/
+	/* foo
+	   c3d
+	*/
+	/*
+	   c3e
+	   foo */
+	/*
+	   c3f
+	   foo */
+}
+
+// Test case taken literally from issue 1835.
+func main() {
+	/*
+	   prints test 5 times
+	*/
+	for i := 0; i < 5; i++ {
+		println("test")
+	}
+}
+
+func issue5623() {
+L:
+	_ = yyyyyyyyyyyyyyyy			// comment - should be aligned
+	_ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx	/* comment */
+
+	_ = yyyyyyyyyyyyyyyy			/* comment - should be aligned */
+	_ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx	// comment
+
+LLLLLLL:
+	_ = yyyyyyyyyyyyyyyy			// comment - should be aligned
+	_ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx	// comment
+
+LL:
+LLLLL:
+	_ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx	/* comment */
+	_ = yyyyyyyyyyyyyyyy			/* comment - should be aligned */
+
+	_ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx	// comment
+	_ = yyyyyyyyyyyyyyyy			// comment - should be aligned
+
+	// test case from issue
+label:
+	mask := uint64(1)<<c - 1		// Allocation mask
+	used := atomic.LoadUint64(&h.used)	// Current allocations
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/comments2.input b/third_party/gofrontend/libgo/go/go/printer/testdata/comments2.input
new file mode 100644
index 0000000..4a055c8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/comments2.input
@@ -0,0 +1,105 @@
+// 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.
+
+// This is a package for testing comment placement by go/printer.
+//
+package main
+
+// Test cases for idempotent comment formatting (was issue 1835).
+/*
+c1a
+*/
+/*
+   c1b
+*/
+/* foo
+c1c
+*/
+/* foo
+   c1d
+*/
+/*
+c1e
+foo */
+/*
+   c1f
+   foo */
+
+func f() {
+/*
+c2a
+*/
+/*
+   c2b
+*/
+/* foo
+c2c
+*/
+/* foo
+   c2d
+*/
+/*
+c2e
+foo */
+/*
+   c2f
+   foo */
+}
+
+func g() {
+/*
+c3a
+*/
+/*
+   c3b
+*/
+/* foo
+c3c
+*/
+/* foo
+   c3d
+*/
+/*
+c3e
+foo */
+/*
+   c3f
+   foo */
+}
+
+// Test case taken literally from issue 1835.
+func main() {
+/*
+prints test 5 times
+*/
+   for i := 0; i < 5; i++ {
+      println("test")
+   }
+}
+
+func issue5623() {
+L:
+   _ = yyyyyyyyyyyyyyyy // comment - should be aligned
+   _ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx /* comment */
+
+   _ = yyyyyyyyyyyyyyyy /* comment - should be aligned */
+   _ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx // comment
+
+LLLLLLL:
+   _ = yyyyyyyyyyyyyyyy // comment - should be aligned
+   _ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx // comment
+
+LL:
+LLLLL:
+   _ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx /* comment */
+   _ = yyyyyyyyyyyyyyyy /* comment - should be aligned */
+
+   _ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx // comment
+   _ = yyyyyyyyyyyyyyyy // comment - should be aligned
+
+// test case from issue
+label:
+   mask := uint64(1)<<c - 1 // Allocation mask
+   used := atomic.LoadUint64(&h.used) // Current allocations
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/declarations.golden b/third_party/gofrontend/libgo/go/go/printer/testdata/declarations.golden
new file mode 100644
index 0000000..a27f21f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/declarations.golden
@@ -0,0 +1,955 @@
+// 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 imports
+
+import "io"
+
+import (
+	_ "io"
+)
+
+import _ "io"
+
+import (
+	"io"
+	"io"
+	"io"
+)
+
+import (
+	"io"
+	aLongRename "io"
+
+	b "io"
+)
+
+import (
+	"unrenamed"
+	renamed "renameMe"
+	. "io"
+	_ "io"
+	"io"
+	. "os"
+)
+
+// no newlines between consecutive single imports, but
+// respect extra line breaks in the source (at most one empty line)
+import _ "io"
+import _ "io"
+import _ "io"
+
+import _ "os"
+import _ "os"
+import _ "os"
+
+import _ "fmt"
+import _ "fmt"
+import _ "fmt"
+
+import "foo"	// a comment
+import "bar"	// a comment
+
+import (
+	_ "foo"
+	// a comment
+	"bar"
+	"foo"	// a comment
+	"bar"	// a comment
+)
+
+// comments + renames
+import (
+	"unrenamed"	// a comment
+	renamed "renameMe"
+	. "io"		/* a comment */
+	_ "io/ioutil"	// a comment
+	"io"		// testing alignment
+	. "os"
+	// a comment
+)
+
+// a case that caused problems in the past (comment placement)
+import (
+	. "fmt"
+	"io"
+	"malloc"	// for the malloc count test only
+	"math"
+	"strings"
+	"testing"
+)
+
+// more import examples
+import (
+	"xxx"
+	"much_longer_name"	// comment
+	"short_name"		// comment
+)
+
+import (
+	_ "xxx"
+	"much_longer_name"	// comment
+)
+
+import (
+	mymath "math"
+	"/foo/bar/long_package_path"	// a comment
+)
+
+import (
+	"package_a"	// comment
+	"package_b"
+	my_better_c "package_c"	// comment
+	"package_d"		// comment
+	my_e "package_e"	// comment
+
+	"package_a"	// comment
+	"package_bb"
+	"package_ccc"	// comment
+	"package_dddd"	// comment
+)
+
+// at least one empty line between declarations of different kind
+import _ "io"
+
+var _ int
+
+// at least one empty line between declarations of the same kind
+// if there is associated documentation (was issue 2570)
+type T1 struct{}
+
+// T2 comment
+type T2 struct {
+}	// should be a two-line struct
+
+// T3 comment
+type T2 struct {
+}	// should be a two-line struct
+
+// printing of constant literals
+const (
+	_	= "foobar"
+	_	= "a۰۱۸"
+	_	= "foo६४"
+	_	= "bar9876"
+	_	= 0
+	_	= 1
+	_	= 123456789012345678890
+	_	= 01234567
+	_	= 0xcafebabe
+	_	= 0.
+	_	= .0
+	_	= 3.14159265
+	_	= 1e0
+	_	= 1e+100
+	_	= 1e-100
+	_	= 2.71828e-1000
+	_	= 0i
+	_	= 1i
+	_	= 012345678901234567889i
+	_	= 123456789012345678890i
+	_	= 0.i
+	_	= .0i
+	_	= 3.14159265i
+	_	= 1e0i
+	_	= 1e+100i
+	_	= 1e-100i
+	_	= 2.71828e-1000i
+	_	= 'a'
+	_	= '\000'
+	_	= '\xFF'
+	_	= '\uff16'
+	_	= '\U0000ff16'
+	_	= `foobar`
+	_	= `foo
+---
+---
+bar`
+)
+
+func _() {
+	type _ int
+	type _ *int
+	type _ []int
+	type _ map[string]int
+	type _ chan int
+	type _ func() int
+
+	var _ int
+	var _ *int
+	var _ []int
+	var _ map[string]int
+	var _ chan int
+	var _ func() int
+
+	type _ struct{}
+	type _ *struct{}
+	type _ []struct{}
+	type _ map[string]struct{}
+	type _ chan struct{}
+	type _ func() struct{}
+
+	type _ interface{}
+	type _ *interface{}
+	type _ []interface{}
+	type _ map[string]interface{}
+	type _ chan interface{}
+	type _ func() interface{}
+
+	var _ struct{}
+	var _ *struct{}
+	var _ []struct{}
+	var _ map[string]struct{}
+	var _ chan struct{}
+	var _ func() struct{}
+
+	var _ interface{}
+	var _ *interface{}
+	var _ []interface{}
+	var _ map[string]interface{}
+	var _ chan interface{}
+	var _ func() interface{}
+}
+
+// don't lose blank lines in grouped declarations
+const (
+	_	int	= 0
+	_	float	= 1
+
+	_	string	= "foo"
+
+	_	= iota
+	_
+
+	// a comment
+	_
+
+	_
+)
+
+type (
+	_	int
+	_	struct{}
+
+	_	interface{}
+
+	// a comment
+	_	map[string]int
+)
+
+var (
+	_	int	= 0
+	_	float	= 1
+
+	_	string	= "foo"
+
+	_	bool
+
+	// a comment
+	_	bool
+)
+
+// don't lose blank lines in this struct
+type _ struct {
+	String	struct {
+		Str, Len int
+	}
+	Slice	struct {
+		Array, Len, Cap int
+	}
+	Eface	struct {
+		Typ, Ptr int
+	}
+
+	UncommonType	struct {
+		Name, PkgPath int
+	}
+	CommonType	struct {
+		Size, Hash, Alg, Align, FieldAlign, String, UncommonType int
+	}
+	Type	struct {
+		Typ, Ptr int
+	}
+	StructField	struct {
+		Name, PkgPath, Typ, Tag, Offset int
+	}
+	StructType	struct {
+		Fields int
+	}
+	PtrType	struct {
+		Elem int
+	}
+	SliceType	struct {
+		Elem int
+	}
+	ArrayType	struct {
+		Elem, Len int
+	}
+
+	Stktop	struct {
+		Stackguard, Stackbase, Gobuf int
+	}
+	Gobuf	struct {
+		Sp, Pc, G int
+	}
+	G	struct {
+		Stackbase, Sched, Status, Alllink int
+	}
+}
+
+// no blank lines in empty structs and interfaces, but leave 1- or 2-line layout alone
+type _ struct{}
+type _ struct {
+}
+
+type _ interface{}
+type _ interface {
+}
+
+// no tabs for single or ungrouped decls
+func _() {
+	const xxxxxx = 0
+	type x int
+	var xxx int
+	var yyyy float = 3.14
+	var zzzzz = "bar"
+
+	const (
+		xxxxxx = 0
+	)
+	type (
+		x int
+	)
+	var (
+		xxx int
+	)
+	var (
+		yyyy float = 3.14
+	)
+	var (
+		zzzzz = "bar"
+	)
+}
+
+// tabs for multiple or grouped decls
+func _() {
+	// no entry has a type
+	const (
+		zzzzzz	= 1
+		z	= 2
+		zzz	= 3
+	)
+	// some entries have a type
+	const (
+		xxxxxx			= 1
+		x			= 2
+		xxx			= 3
+		yyyyyyyy	float	= iota
+		yyyy			= "bar"
+		yyy
+		yy	= 2
+	)
+}
+
+func _() {
+	// no entry has a type
+	var (
+		zzzzzz	= 1
+		z	= 2
+		zzz	= 3
+	)
+	// no entry has a value
+	var (
+		_	int
+		_	float
+		_	string
+
+		_	int	// comment
+		_	float	// comment
+		_	string	// comment
+	)
+	// some entries have a type
+	var (
+		xxxxxx		int
+		x		float
+		xxx		string
+		yyyyyyyy	int	= 1234
+		y		float	= 3.14
+		yyyy			= "bar"
+		yyy		string	= "foo"
+	)
+	// mixed entries - all comments should be aligned
+	var (
+		a, b, c			int
+		x			= 10
+		d			int			// comment
+		y				= 20		// comment
+		f, ff, fff, ffff	int	= 0, 1, 2, 3	// comment
+	)
+	// respect original line breaks
+	var _ = []T{
+		T{0x20, "Telugu"},
+	}
+	var _ = []T{
+		// respect original line breaks
+		T{0x20, "Telugu"},
+	}
+}
+
+// use the formatted output rather than the input to decide when to align
+// (was issue 4505)
+const (
+	short		= 2 * (1 + 2)
+	aMuchLongerName	= 3
+)
+
+var (
+	short		= X{}
+	aMuchLongerName	= X{}
+
+	x1	= X{}	// foo
+	x2	= X{}	// foo
+)
+
+func _() {
+	type (
+		xxxxxx	int
+		x	float
+		xxx	string
+		xxxxx	[]x
+		xx	struct{}
+		xxxxxxx	struct {
+			_, _	int
+			_	float
+		}
+		xxxx	chan<- string
+	)
+}
+
+// alignment of "=" in consecutive lines (extended example from issue 1414)
+const (
+	umax	uint	= ^uint(0)		// maximum value for a uint
+	bpu		= 1 << (5 + umax>>63)	// bits per uint
+	foo
+	bar	= -1
+)
+
+// typical enum
+const (
+	a	MyType	= iota
+	abcd
+	b
+	c
+	def
+)
+
+// excerpt from godoc.go
+var (
+	goroot		= flag.String("goroot", runtime.GOROOT(), "Go root directory")
+	testDir		= flag.String("testdir", "", "Go root subdirectory - for testing only (faster startups)")
+	pkgPath		= flag.String("path", "", "additional package directories (colon-separated)")
+	filter		= flag.String("filter", "", "filter file containing permitted package directory paths")
+	filterMin	= flag.Int("filter_minutes", 0, "filter file update interval in minutes; disabled if <= 0")
+	filterDelay	delayTime	// actual filter update interval in minutes; usually filterDelay == filterMin, but filterDelay may back off exponentially
+)
+
+// formatting of structs
+type _ struct{}
+
+type _ struct { /* this comment should be visible */
+}
+
+type _ struct {
+	// this comment should be visible and properly indented
+}
+
+type _ struct {	// this comment must not change indentation
+	f			int
+	f, ff, fff, ffff	int
+}
+
+type _ struct {
+	string
+}
+
+type _ struct {
+	string	// comment
+}
+
+type _ struct {
+	string "tag"
+}
+
+type _ struct {
+	string "tag"	// comment
+}
+
+type _ struct {
+	f int
+}
+
+type _ struct {
+	f int	// comment
+}
+
+type _ struct {
+	f int "tag"
+}
+
+type _ struct {
+	f int "tag"	// comment
+}
+
+type _ struct {
+	bool
+	a, b, c			int
+	int			"tag"
+	ES				// comment
+	float			"tag"	// comment
+	f			int	// comment
+	f, ff, fff, ffff	int	// comment
+	g			float	"tag"
+	h			float	"tag"	// comment
+}
+
+type _ struct {
+	a, b,
+	c, d	int	// this line should be indented
+	u, v, w, x	float	// this line should be indented
+	p, q,
+	r, s	float	// this line should be indented
+}
+
+// difficult cases
+type _ struct {
+	bool		// comment
+	text	[]byte	// comment
+}
+
+// formatting of interfaces
+type EI interface{}
+
+type _ interface {
+	EI
+}
+
+type _ interface {
+	f()
+	fffff()
+}
+
+type _ interface {
+	EI
+	f()
+	fffffg()
+}
+
+type _ interface {	// this comment must not change indentation
+	EI				// here's a comment
+	f()				// no blank between identifier and ()
+	fffff()				// no blank between identifier and ()
+	gggggggggggg(x, y, z int)	// hurray
+}
+
+// formatting of variable declarations
+func _() {
+	type day struct {
+		n		int
+		short, long	string
+	}
+	var (
+		Sunday		= day{0, "SUN", "Sunday"}
+		Monday		= day{1, "MON", "Monday"}
+		Tuesday		= day{2, "TUE", "Tuesday"}
+		Wednesday	= day{3, "WED", "Wednesday"}
+		Thursday	= day{4, "THU", "Thursday"}
+		Friday		= day{5, "FRI", "Friday"}
+		Saturday	= day{6, "SAT", "Saturday"}
+	)
+}
+
+// formatting of multi-line variable declarations
+var a1, b1, c1 int	// all on one line
+
+var a2, b2,
+	c2 int	// this line should be indented
+
+var (
+	a3, b3,
+	c3, d3	int	// this line should be indented
+	a4, b4, c4	int	// this line should be indented
+)
+
+// Test case from issue 3304: multi-line declarations must end
+// a formatting section and not influence indentation of the
+// next line.
+var (
+	minRefreshTimeSec	= flag.Int64("min_refresh_time_sec", 604800,
+		"minimum time window between two refreshes for a given user.")
+	x	= flag.Int64("refresh_user_rollout_percent", 100,
+		"temporary flag to ramp up the refresh user rpc")
+	aVeryLongVariableName	= stats.GetVarInt("refresh-user-count")
+)
+
+func _() {
+	var privateKey2 = &Block{Type:	"RSA PRIVATE KEY",
+		Headers:	map[string]string{},
+		Bytes: []uint8{0x30, 0x82, 0x1, 0x3a, 0x2, 0x1, 0x0, 0x2,
+			0x41, 0x0, 0xb2, 0x99, 0xf, 0x49, 0xc4, 0x7d, 0xfa, 0x8c,
+			0xd4, 0x0, 0xae, 0x6a, 0x4d, 0x1b, 0x8a, 0x3b, 0x6a, 0x13,
+			0x64, 0x2b, 0x23, 0xf2, 0x8b, 0x0, 0x3b, 0xfb, 0x97, 0x79,
+		},
+	}
+}
+
+func _() {
+	var Universe = Scope{
+		Names: map[string]*Ident{
+			// basic types
+			"bool":		nil,
+			"byte":		nil,
+			"int8":		nil,
+			"int16":	nil,
+			"int32":	nil,
+			"int64":	nil,
+			"uint8":	nil,
+			"uint16":	nil,
+			"uint32":	nil,
+			"uint64":	nil,
+			"float32":	nil,
+			"float64":	nil,
+			"string":	nil,
+
+			// convenience types
+			"int":		nil,
+			"uint":		nil,
+			"uintptr":	nil,
+			"float":	nil,
+
+			// constants
+			"false":	nil,
+			"true":		nil,
+			"iota":		nil,
+			"nil":		nil,
+
+			// functions
+			"cap":		nil,
+			"len":		nil,
+			"new":		nil,
+			"make":		nil,
+			"panic":	nil,
+			"panicln":	nil,
+			"print":	nil,
+			"println":	nil,
+		},
+	}
+}
+
+// alignment of map composite entries
+var _ = map[int]int{
+	// small key sizes: always align even if size ratios are large
+	a:			a,
+	abcdefghabcdefgh:	a,
+	ab:			a,
+	abc:			a,
+	abcdefgabcdefg:		a,
+	abcd:			a,
+	abcde:			a,
+	abcdef:			a,
+
+	// mixed key sizes: align when key sizes change within accepted ratio
+	abcdefgh:		a,
+	abcdefghabcdefg:	a,
+	abcdefghij:		a,
+	abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij:	a,	// outlier - do not align with previous line
+	abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij:		a,	// align with previous line
+
+	ab:	a,	// do not align with previous line
+	abcde:	a,	// align with previous line
+}
+
+// alignment of map composite entries: test cases from issue 3965
+// aligned
+var _ = T1{
+	a:			x,
+	b:			y,
+	cccccccccccccccccccc:	z,
+}
+
+// not aligned
+var _ = T2{
+	a:	x,
+	b:	y,
+	ccccccccccccccccccccc:	z,
+}
+
+// aligned
+var _ = T3{
+	aaaaaaaaaaaaaaaaaaaa:	x,
+	b:			y,
+	c:			z,
+}
+
+// not aligned
+var _ = T4{
+	aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:	x,
+	b:	y,
+	c:	z,
+}
+
+func _() {
+	var _ = T{
+		a,	// must introduce trailing comma
+	}
+}
+
+// formatting of function results
+func _() func()				{}
+func _() func(int)			{ return nil }
+func _() func(int) int			{ return nil }
+func _() func(int) func(int) func()	{ return nil }
+
+// formatting of consecutive single-line functions
+func _()	{}
+func _()	{}
+func _()	{}
+
+func _()	{}	// an empty line before this function
+func _()	{}
+func _()	{}
+
+func _()		{ f(1, 2, 3) }
+func _(x int) int	{ y := x; return y + 1 }
+func _() int		{ type T struct{}; var x T; return x }
+
+// these must remain multi-line since they are multi-line in the source
+func _() {
+	f(1, 2, 3)
+}
+func _(x int) int {
+	y := x
+	return y + 1
+}
+func _() int {
+	type T struct{}
+	var x T
+	return x
+}
+
+// making function declarations safe for new semicolon rules
+func _()	{ /* single-line function because of "short-ish" comment */ }
+func _() { /* multi-line function because of "long-ish" comment - much more comment text is following here */ /* and more */
+}
+
+func _() {
+	/* multi-line func because block is on multiple lines */
+}
+
+// ellipsis parameters
+func _(...int)
+func _(...*int)
+func _(...[]int)
+func _(...struct{})
+func _(bool, ...interface{})
+func _(bool, ...func())
+func _(bool, ...func(...int))
+func _(bool, ...map[string]int)
+func _(bool, ...chan int)
+
+func _(b bool, x ...int)
+func _(b bool, x ...*int)
+func _(b bool, x ...[]int)
+func _(b bool, x ...struct{})
+func _(x ...interface{})
+func _(x ...func())
+func _(x ...func(...int))
+func _(x ...map[string]int)
+func _(x ...chan int)
+
+// these parameter lists must remain multi-line since they are multi-line in the source
+func _(bool,
+	int) {
+}
+func _(x bool,
+	y int) {
+}
+func _(x,
+	y bool) {
+}
+func _(bool,	// comment
+	int) {
+}
+func _(x bool,	// comment
+	y int) {
+}
+func _(x,	// comment
+	y bool) {
+}
+func _(bool,	// comment
+	// comment
+	int) {
+}
+func _(x bool,	// comment
+	// comment
+	y int) {
+}
+func _(x,	// comment
+	// comment
+	y bool) {
+}
+func _(bool,
+	// comment
+	int) {
+}
+func _(x bool,
+	// comment
+	y int) {
+}
+func _(x,
+	// comment
+	y bool) {
+}
+func _(x,	// comment
+	y,	// comment
+	z bool) {
+}
+func _(x,	// comment
+	y,	// comment
+	z bool) {
+}
+func _(x int,	// comment
+	y float,	// comment
+	z bool) {
+}
+
+// properly indent multi-line signatures
+func ManageStatus(in <-chan *Status, req <-chan Request,
+	stat chan<- *TargetInfo,
+	TargetHistorySize int) {
+}
+
+func MultiLineSignature0(
+	a, b, c int,
+) {
+}
+
+func MultiLineSignature1(
+	a, b, c int,
+	u, v, w float,
+) {
+}
+
+func MultiLineSignature2(
+	a, b,
+	c int,
+) {
+}
+
+func MultiLineSignature3(
+	a, b,
+	c int, u, v,
+	w float,
+	x ...int) {
+}
+
+func MultiLineSignature4(
+	a, b, c int,
+	u, v,
+	w float,
+	x ...int) {
+}
+
+func MultiLineSignature5(
+	a, b, c int,
+	u, v, w float,
+	p, q,
+	r string,
+	x ...int) {
+}
+
+// make sure it also works for methods in interfaces
+type _ interface {
+	MultiLineSignature0(
+		a, b, c int,
+	)
+
+	MultiLineSignature1(
+		a, b, c int,
+		u, v, w float,
+	)
+
+	MultiLineSignature2(
+		a, b,
+		c int,
+	)
+
+	MultiLineSignature3(
+		a, b,
+		c int, u, v,
+		w float,
+		x ...int)
+
+	MultiLineSignature4(
+		a, b, c int,
+		u, v,
+		w float,
+		x ...int)
+
+	MultiLineSignature5(
+		a, b, c int,
+		u, v, w float,
+		p, q,
+		r string,
+		x ...int)
+}
+
+// omit superfluous parentheses in parameter lists
+func _(int)
+func _(int)
+func _(x int)
+func _(x int)
+func _(x, y int)
+func _(x, y int)
+
+func _() int
+func _() int
+func _() int
+
+func _() (x int)
+func _() (x int)
+func _() (x int)
+
+// special cases: some channel types require parentheses
+func _(x chan (<-chan int))
+func _(x chan (<-chan int))
+func _(x chan (<-chan int))
+
+func _(x chan<- (chan int))
+func _(x chan<- (chan int))
+func _(x chan<- (chan int))
+
+// don't introduce comma after last parameter if the closing ) is on the same line
+// even if the parameter type itself is multi-line (test cases from issue 4533)
+func _(...interface{})
+func _(...interface {
+	m()
+	n()
+})	// no extra comma between } and )
+
+func (t *T) _(...interface{})
+func (t *T) _(...interface {
+	m()
+	n()
+})	// no extra comma between } and )
+
+func _(interface{})
+func _(interface {
+	m()
+})	// no extra comma between } and )
+
+func _(struct{})
+func _(struct {
+	x	int
+	y	int
+})	// no extra comma between } and )
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/declarations.input b/third_party/gofrontend/libgo/go/go/printer/testdata/declarations.input
new file mode 100644
index 0000000..d9951d3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/declarations.input
@@ -0,0 +1,967 @@
+// 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 imports
+
+import "io"
+
+import (
+	_ "io"
+)
+
+import _ "io"
+
+import (
+	"io"
+	"io"
+	"io"
+)
+
+import (
+	"io"
+	aLongRename "io"
+
+	b "io"
+)
+
+import (
+       "unrenamed"
+       renamed "renameMe"
+       . "io"
+       _ "io"
+       "io"
+       . "os"
+)
+
+// no newlines between consecutive single imports, but
+// respect extra line breaks in the source (at most one empty line)
+import _ "io"
+import _ "io"
+import _ "io"
+
+import _ "os"
+import _ "os"
+import _ "os"
+
+
+import _ "fmt"
+import _ "fmt"
+import _ "fmt"
+
+import "foo"  // a comment
+import "bar"  // a comment
+
+import (
+	_ "foo"
+	// a comment
+	"bar"
+	"foo"  // a comment
+	"bar"  // a comment
+)
+
+// comments + renames
+import (
+       "unrenamed" // a comment
+       renamed "renameMe"
+       . "io" /* a comment */
+       _ "io/ioutil" // a comment
+       "io" // testing alignment
+       . "os"
+       // a comment
+)
+
+// a case that caused problems in the past (comment placement)
+import (
+	. "fmt"
+	"io"
+	"malloc"	// for the malloc count test only
+	"math"
+	"strings"
+	"testing"
+)
+
+// more import examples
+import (
+	"xxx"
+	"much_longer_name" // comment
+	"short_name" // comment
+)
+
+import (
+	_ "xxx"
+	"much_longer_name" // comment
+)
+
+import (
+	mymath "math"
+	"/foo/bar/long_package_path" // a comment
+)
+
+import (
+	"package_a" // comment
+	"package_b"
+	my_better_c "package_c" // comment
+	"package_d" // comment
+	my_e "package_e" // comment
+
+	"package_a"    // comment
+	"package_bb"
+	"package_ccc"  // comment
+	"package_dddd" // comment
+)
+
+// at least one empty line between declarations of different kind
+import _ "io"
+var _ int
+
+// at least one empty line between declarations of the same kind
+// if there is associated documentation (was issue 2570)
+type T1 struct{}
+// T2 comment
+type T2 struct {
+} // should be a two-line struct
+
+
+// T3 comment
+type T2 struct {
+
+
+} // should be a two-line struct
+
+
+// printing of constant literals
+const (
+	_ = "foobar"
+	_ = "a۰۱۸"
+	_ = "foo६४"
+	_ = "bar9876"
+	_ = 0
+	_ = 1
+	_ = 123456789012345678890
+	_ = 01234567
+	_ = 0xcafebabe
+	_ = 0.
+	_ = .0
+	_ = 3.14159265
+	_ = 1e0
+	_ = 1e+100
+	_ = 1e-100
+	_ = 2.71828e-1000
+	_ = 0i
+	_ = 1i
+	_ = 012345678901234567889i
+	_ = 123456789012345678890i
+	_ = 0.i
+	_ = .0i
+	_ = 3.14159265i
+	_ = 1e0i
+	_ = 1e+100i
+	_ = 1e-100i
+	_ = 2.71828e-1000i
+	_ = 'a'
+	_ = '\000'
+	_ = '\xFF'
+	_ = '\uff16'
+	_ = '\U0000ff16'
+	_ = `foobar`
+	_ = `foo
+---
+---
+bar`
+)
+
+
+func _() {
+	type _ int
+	type _ *int
+	type _ []int
+	type _ map[string]int
+	type _ chan int
+	type _ func() int
+
+	var _ int
+	var _ *int
+	var _ []int
+	var _ map[string]int
+	var _ chan int
+	var _ func() int
+
+	type _ struct{}
+	type _ *struct{}
+	type _ []struct{}
+	type _ map[string]struct{}
+	type _ chan struct{}
+	type _ func() struct{}
+
+	type _ interface{}
+	type _ *interface{}
+	type _ []interface{}
+	type _ map[string]interface{}
+	type _ chan interface{}
+	type _ func() interface{}
+
+	var _ struct{}
+	var _ *struct{}
+	var _ []struct{}
+	var _ map[string]struct{}
+	var _ chan struct{}
+	var _ func() struct{}
+
+	var _ interface{}
+	var _ *interface{}
+	var _ []interface{}
+	var _ map[string]interface{}
+	var _ chan interface{}
+	var _ func() interface{}
+}
+
+
+// don't lose blank lines in grouped declarations
+const (
+	_ int = 0
+	_ float = 1
+
+	_ string = "foo"
+
+	_ = iota
+	_
+	
+	// a comment
+	_
+
+	_
+)
+
+
+type (
+	_ int
+	_ struct {}
+	
+	_ interface{}
+	
+	// a comment
+	_ map[string]int
+)
+
+
+var (
+	_ int = 0
+	_ float = 1
+
+	_ string = "foo"
+
+	_ bool
+	
+	// a comment
+	_ bool
+)
+
+
+// don't lose blank lines in this struct
+type _ struct {
+	String struct {
+		Str, Len int
+	}
+	Slice struct {
+		Array, Len, Cap int
+	}
+	Eface struct {
+		Typ, Ptr int
+	}
+
+	UncommonType struct {
+		Name, PkgPath int
+	}
+	CommonType struct {
+		Size, Hash, Alg, Align, FieldAlign, String, UncommonType int
+	}
+	Type struct {
+		Typ, Ptr int
+	}
+	StructField struct {
+		Name, PkgPath, Typ, Tag, Offset int
+	}
+	StructType struct {
+		Fields int
+	}
+	PtrType struct {
+		Elem int
+	}
+	SliceType struct {
+		Elem int
+	}
+	ArrayType struct {
+		Elem, Len int
+	}
+
+	Stktop struct {
+		Stackguard, Stackbase, Gobuf int
+	}
+	Gobuf struct {
+		Sp, Pc, G int
+	}
+	G struct {
+		Stackbase, Sched, Status, Alllink int
+	}
+}
+
+
+// no blank lines in empty structs and interfaces, but leave 1- or 2-line layout alone
+type _ struct{            }
+type _ struct {
+
+}
+
+type _ interface{            }
+type _ interface {
+
+}
+
+
+// no tabs for single or ungrouped decls
+func _() {
+	const xxxxxx = 0
+	type x int
+	var xxx int
+	var yyyy float = 3.14
+	var zzzzz = "bar"
+
+	const (
+		xxxxxx = 0
+	)
+	type (
+		x int
+	)
+	var (
+		xxx int
+	)
+	var (
+		yyyy float = 3.14
+	)
+	var (
+		zzzzz = "bar"
+	)
+}
+
+// tabs for multiple or grouped decls
+func _() {
+	// no entry has a type
+	const (
+		zzzzzz = 1
+		z = 2
+		zzz = 3
+	)
+	// some entries have a type
+	const (
+		xxxxxx = 1
+		x = 2
+		xxx = 3
+		yyyyyyyy float = iota
+		yyyy = "bar"
+		yyy
+		yy = 2
+	)
+}
+
+func _() {
+	// no entry has a type
+	var (
+		zzzzzz = 1
+		z = 2
+		zzz = 3
+	)
+	// no entry has a value
+	var (
+		_ int
+		_ float
+		_ string
+
+		_ int  // comment
+		_ float  // comment
+		_ string  // comment
+	)
+	// some entries have a type
+	var (
+		xxxxxx int
+		x float
+		xxx string
+		yyyyyyyy int = 1234
+		y float = 3.14
+		yyyy = "bar"
+		yyy string = "foo"
+	)
+	// mixed entries - all comments should be aligned
+	var (
+		a, b, c int
+		x = 10
+		d int  // comment
+		y = 20  // comment
+		f, ff, fff, ffff int = 0, 1, 2, 3  // comment
+	)
+	// respect original line breaks
+	var _ = []T {
+		T{0x20,	"Telugu"},
+	}
+	var _ = []T {
+		// respect original line breaks
+		T{0x20,	"Telugu"},
+	}
+}
+
+// use the formatted output rather than the input to decide when to align
+// (was issue 4505)
+const (
+	short = 2 * (
+	1 + 2)
+	aMuchLongerName = 3
+)
+
+var (
+	short = X{
+	}
+	aMuchLongerName = X{}
+
+	x1 = X{} // foo
+	x2 = X{
+	} // foo
+)
+
+func _() {
+	type (
+		xxxxxx int
+		x float
+		xxx string
+		xxxxx []x
+		xx struct{}
+		xxxxxxx struct {
+			_, _ int
+			_ float
+		}
+		xxxx chan<- string
+	)
+}
+
+// alignment of "=" in consecutive lines (extended example from issue 1414)
+const (
+	umax uint                  = ^uint(0) // maximum value for a uint
+	bpu  = 1 << (5 + umax>>63)            // bits per uint
+	foo
+	bar  = -1
+)
+
+// typical enum
+const (
+	a MyType = iota
+	abcd
+	b
+	c
+	def
+)
+
+// excerpt from godoc.go
+var (
+	goroot = flag.String("goroot", runtime.GOROOT(), "Go root directory")
+	testDir = flag.String("testdir", "", "Go root subdirectory - for testing only (faster startups)")
+	pkgPath = flag.String("path", "", "additional package directories (colon-separated)")
+	filter = flag.String("filter", "", "filter file containing permitted package directory paths")
+	filterMin = flag.Int("filter_minutes", 0, "filter file update interval in minutes; disabled if <= 0")
+	filterDelay delayTime // actual filter update interval in minutes; usually filterDelay == filterMin, but filterDelay may back off exponentially
+)
+
+
+// formatting of structs
+type _ struct{}
+
+type _ struct{ /* this comment should be visible */ }
+
+type _ struct{
+	// this comment should be visible and properly indented
+}
+
+type _ struct {  // this comment must not change indentation
+	f int
+	f, ff, fff, ffff int
+}
+
+type _ struct {
+	string
+}
+
+type _ struct {
+	string  // comment
+}
+
+type _ struct {
+	string "tag"
+}
+
+type _ struct {
+	string "tag"  // comment
+}
+
+type _ struct {
+	f int
+}
+
+type _ struct {
+	f int  // comment
+}
+
+type _ struct {
+	f int "tag"
+}
+
+type _ struct {
+	f int "tag"  // comment
+}
+
+type _ struct {
+	bool
+	a, b, c int
+	int "tag"
+	ES // comment
+	float "tag"  // comment
+	f int  // comment
+	f, ff, fff, ffff int  // comment
+	g float "tag"
+	h float "tag"  // comment
+}
+
+type _ struct { a, b,
+c, d int  // this line should be indented
+u, v, w, x float // this line should be indented
+p, q,
+r, s float // this line should be indented
+}
+
+
+// difficult cases
+type _ struct {
+	bool  // comment
+	text []byte  // comment
+}
+
+
+// formatting of interfaces
+type EI interface{}
+
+type _ interface {
+	EI
+}
+
+type _ interface {
+	f()
+	fffff()
+}
+
+type _ interface {
+	EI
+	f()
+	fffffg()
+}
+
+type _ interface {  // this comment must not change indentation
+	EI  // here's a comment
+	f()  // no blank between identifier and ()
+	fffff()  // no blank between identifier and ()
+	gggggggggggg(x, y, z int) ()  // hurray
+}
+
+
+// formatting of variable declarations
+func _() {
+	type day struct { n int; short, long string }
+	var (
+		Sunday = day{ 0, "SUN", "Sunday" }
+		Monday = day{ 1, "MON", "Monday" }
+		Tuesday = day{ 2, "TUE", "Tuesday" }
+		Wednesday = day{ 3, "WED", "Wednesday" }
+		Thursday = day{ 4, "THU", "Thursday" }
+		Friday = day{ 5, "FRI", "Friday" }
+		Saturday = day{ 6, "SAT", "Saturday" }
+	)
+}
+
+
+// formatting of multi-line variable declarations
+var a1, b1, c1 int  // all on one line
+
+var a2, b2,
+c2 int  // this line should be indented
+
+var (a3, b3,
+c3, d3 int  // this line should be indented
+a4, b4, c4 int  // this line should be indented
+)
+
+// Test case from issue 3304: multi-line declarations must end
+// a formatting section and not influence indentation of the
+// next line.
+var (
+	minRefreshTimeSec = flag.Int64("min_refresh_time_sec", 604800,
+		"minimum time window between two refreshes for a given user.")
+	x = flag.Int64("refresh_user_rollout_percent", 100,
+		"temporary flag to ramp up the refresh user rpc")
+	aVeryLongVariableName = stats.GetVarInt("refresh-user-count")
+)
+
+func _() {
+	var privateKey2 = &Block{Type: "RSA PRIVATE KEY",
+					Headers: map[string]string{},
+					Bytes: []uint8{0x30, 0x82, 0x1, 0x3a, 0x2, 0x1, 0x0, 0x2,
+			0x41, 0x0, 0xb2, 0x99, 0xf, 0x49, 0xc4, 0x7d, 0xfa, 0x8c,
+			0xd4, 0x0, 0xae, 0x6a, 0x4d, 0x1b, 0x8a, 0x3b, 0x6a, 0x13,
+			0x64, 0x2b, 0x23, 0xf2, 0x8b, 0x0, 0x3b, 0xfb, 0x97, 0x79,
+		},
+	}
+}
+
+
+func _() {
+	var Universe = Scope {
+		Names: map[string]*Ident {
+			// basic types
+			"bool": nil,
+			"byte": nil,
+			"int8": nil,
+			"int16": nil,
+			"int32": nil,
+			"int64": nil,
+			"uint8": nil,
+			"uint16": nil,
+			"uint32": nil,
+			"uint64": nil,
+			"float32": nil,
+			"float64": nil,
+			"string": nil,
+
+			// convenience types
+			"int": nil,
+			"uint": nil,
+			"uintptr": nil,
+			"float": nil,
+
+			// constants
+			"false": nil,
+			"true": nil,
+			"iota": nil,
+			"nil": nil,
+
+			// functions
+			"cap": nil,
+			"len": nil,
+			"new": nil,
+			"make": nil,
+			"panic": nil,
+			"panicln": nil,
+			"print": nil,
+			"println": nil,
+		},
+	}
+}
+
+
+// alignment of map composite entries
+var _ = map[int]int{
+	// small key sizes: always align even if size ratios are large
+	a: a,
+	abcdefghabcdefgh: a,
+	ab: a,
+	abc: a,
+	abcdefgabcdefg: a,
+	abcd: a,
+	abcde: a,
+	abcdef: a,
+
+	// mixed key sizes: align when key sizes change within accepted ratio
+	abcdefgh: a,
+	abcdefghabcdefg: a,
+	abcdefghij: a,
+	abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij: a, // outlier - do not align with previous line
+	abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij: a, // align with previous line
+
+	ab: a, // do not align with previous line
+	abcde: a, // align with previous line
+}
+
+// alignment of map composite entries: test cases from issue 3965
+// aligned
+var _ = T1{
+	a:                    x,
+	b:                    y,
+	cccccccccccccccccccc: z,
+}
+
+// not aligned
+var _ = T2{
+	a: x,
+	b: y,
+	ccccccccccccccccccccc: z,
+}
+
+// aligned
+var _ = T3{
+	aaaaaaaaaaaaaaaaaaaa: x,
+	b:                    y,
+	c:                    z,
+}
+
+// not aligned
+var _ = T4{
+	aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: x,
+	b:                                       y,
+	c:                                       z,
+}
+
+
+func _() {
+	var _ = T{
+		a,	// must introduce trailing comma
+	}
+}
+
+
+// formatting of function results
+func _() func() {}
+func _() func(int) { return nil }
+func _() func(int) int { return nil }
+func _() func(int) func(int) func() { return nil }
+
+
+// formatting of consecutive single-line functions
+func _() {}
+func _() {}
+func _() {}
+
+func _() {}  // an empty line before this function
+func _() {}
+func _() {}
+
+func _() { f(1, 2, 3) }
+func _(x int) int { y := x; return y+1 }
+func _() int { type T struct{}; var x T; return x }
+
+// these must remain multi-line since they are multi-line in the source
+func _() {
+	f(1, 2, 3)
+}
+func _(x int) int {
+	y := x; return y+1
+}
+func _() int {
+	type T struct{}; var x T; return x
+}
+
+
+// making function declarations safe for new semicolon rules
+func _() { /* single-line function because of "short-ish" comment */ }
+func _() { /* multi-line function because of "long-ish" comment - much more comment text is following here */ /* and more */ }
+
+func _() {
+/* multi-line func because block is on multiple lines */ }
+
+
+// ellipsis parameters
+func _(...int)
+func _(...*int)
+func _(...[]int)
+func _(...struct{})
+func _(bool, ...interface{})
+func _(bool, ...func())
+func _(bool, ...func(...int))
+func _(bool, ...map[string]int)
+func _(bool, ...chan int)
+
+func _(b bool, x ...int)
+func _(b bool, x ...*int)
+func _(b bool, x ...[]int)
+func _(b bool, x ...struct{})
+func _(x ...interface{})
+func _(x ...func())
+func _(x ...func(...int))
+func _(x ...map[string]int)
+func _(x ...chan int)
+
+
+// these parameter lists must remain multi-line since they are multi-line in the source
+func _(bool,
+int) {
+}
+func _(x bool,
+y int) {
+}
+func _(x,
+y bool) {
+}
+func _(bool, // comment
+int) {
+}
+func _(x bool, // comment
+y int) {
+}
+func _(x, // comment
+y bool) {
+}
+func _(bool, // comment
+// comment
+int) {
+}
+func _(x bool, // comment
+// comment
+y int) {
+}
+func _(x, // comment
+// comment
+y bool) {
+}
+func _(bool,
+// comment
+int) {
+}
+func _(x bool,
+// comment
+y int) {
+}
+func _(x,
+// comment
+y bool) {
+}
+func _(x, // comment
+y,// comment
+z bool) {
+}
+func _(x, // comment
+	y,// comment
+	z bool) {
+}
+func _(x int,	// comment
+	y float,	// comment
+	z bool) {
+}
+
+
+// properly indent multi-line signatures
+func ManageStatus(in <-chan *Status, req <-chan Request,
+stat chan<- *TargetInfo,
+TargetHistorySize int) {
+}
+
+func MultiLineSignature0(
+a, b, c int,
+) {}
+
+func MultiLineSignature1(
+a, b, c int,
+u, v, w float,
+) {}
+
+func MultiLineSignature2(
+a, b,
+c int,
+) {}
+
+func MultiLineSignature3(
+a, b,
+c int, u, v,
+w float,
+		x ...int) {}
+
+func MultiLineSignature4(
+a, b, c int,
+u, v,
+w float,
+		x ...int) {}
+
+func MultiLineSignature5(
+a, b, c int,
+u, v, w float,
+p, q,
+r string,
+		x ...int) {}
+
+// make sure it also works for methods in interfaces
+type _ interface {
+MultiLineSignature0(
+a, b, c int,
+)
+
+MultiLineSignature1(
+a, b, c int,
+u, v, w float,
+)
+
+MultiLineSignature2(
+a, b,
+c int,
+)
+
+MultiLineSignature3(
+a, b,
+c int, u, v,
+w float,
+		x ...int)
+
+MultiLineSignature4(
+a, b, c int,
+u, v,
+w float,
+		x ...int)
+
+MultiLineSignature5(
+a, b, c int,
+u, v, w float,
+p, q,
+r string,
+		x ...int)
+}
+
+// omit superfluous parentheses in parameter lists
+func _((int))
+func _((((((int))))))
+func _(x (int))
+func _(x (((((int))))))
+func _(x, y (int))
+func _(x, y (((((int))))))
+
+func _() (int)
+func _() ((int))
+func _() ((((((int))))))
+
+func _() (x int)
+func _() (x (int))
+func _() (x (((((int))))))
+
+// special cases: some channel types require parentheses
+func _(x chan(<-chan int))
+func _(x (chan(<-chan int)))
+func _(x ((((chan(<-chan int))))))
+
+func _(x chan<-(chan int))
+func _(x (chan<-(chan int)))
+func _(x ((((chan<-(chan int))))))
+
+// don't introduce comma after last parameter if the closing ) is on the same line
+// even if the parameter type itself is multi-line (test cases from issue 4533)
+func _(...interface{})
+func _(...interface {
+	m()
+	n()
+}) // no extra comma between } and )
+
+func (t *T) _(...interface{})
+func (t *T) _(...interface {
+	m()
+	n()
+}) // no extra comma between } and )
+
+func _(interface{})
+func _(interface {
+	m()
+}) // no extra comma between } and )
+
+func _(struct{})
+func _(struct {
+	x int
+	y int
+}) // no extra comma between } and )
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/empty.golden b/third_party/gofrontend/libgo/go/go/printer/testdata/empty.golden
new file mode 100644
index 0000000..a055f47
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/empty.golden
@@ -0,0 +1,5 @@
+// a comment at the beginning of the file
+
+package empty
+
+// a comment at the end of the file
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/empty.input b/third_party/gofrontend/libgo/go/go/printer/testdata/empty.input
new file mode 100644
index 0000000..a055f47
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/empty.input
@@ -0,0 +1,5 @@
+// a comment at the beginning of the file
+
+package empty
+
+// a comment at the end of the file
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/expressions.golden b/third_party/gofrontend/libgo/go/go/printer/testdata/expressions.golden
new file mode 100644
index 0000000..fbe8275
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/expressions.golden
@@ -0,0 +1,681 @@
+// 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 expressions
+
+type T struct {
+	x, y, z int
+}
+
+var (
+	a, b, c, d, e						int
+	under_bar						int
+	longIdentifier1, longIdentifier2, longIdentifier3	int
+	t0, t1, t2						T
+	s							string
+	p							*int
+)
+
+func _() {
+	// no spaces around simple or parenthesized expressions
+	_ = (a + 0)
+	_ = a + b
+	_ = a + b + c
+	_ = a + b - c
+	_ = a - b - c
+	_ = a + (b * c)
+	_ = a + (b / c)
+	_ = a - (b % c)
+	_ = 1 + a
+	_ = a + 1
+	_ = a + b + 1
+	_ = s[a]
+	_ = s[a:]
+	_ = s[:b]
+	_ = s[1:2]
+	_ = s[a:b]
+	_ = s[0:len(s)]
+	_ = s[0] << 1
+	_ = (s[0] << 1) & 0xf
+	_ = s[0]<<2 | s[1]>>4
+	_ = "foo" + s
+	_ = s + "foo"
+	_ = 'a' + 'b'
+	_ = len(s) / 2
+	_ = len(t0.x) / a
+
+	// spaces around expressions of different precedence or expressions containing spaces
+	_ = a + -b
+	_ = a - ^b
+	_ = a / *p
+	_ = a + b*c
+	_ = 1 + b*c
+	_ = a + 2*c
+	_ = a + c*2
+	_ = 1 + 2*3
+	_ = s[1 : 2*3]
+	_ = s[a : b-c]
+	_ = s[0:]
+	_ = s[a+b]
+	_ = s[:b-c]
+	_ = s[a+b:]
+	_ = a[a<<b+1]
+	_ = a[a<<b+1:]
+	_ = s[a+b : len(s)]
+	_ = s[len(s):-a]
+	_ = s[a : len(s)+1]
+	_ = s[a:len(s)+1] + s
+
+	// spaces around operators with equal or lower precedence than comparisons
+	_ = a == b
+	_ = a != b
+	_ = a > b
+	_ = a >= b
+	_ = a < b
+	_ = a <= b
+	_ = a < b && c > d
+	_ = a < b || c > d
+
+	// spaces around "long" operands
+	_ = a + longIdentifier1
+	_ = longIdentifier1 + a
+	_ = longIdentifier1 + longIdentifier2*longIdentifier3
+	_ = s + "a longer string"
+
+	// some selected cases
+	_ = a + t0.x
+	_ = a + t0.x + t1.x*t2.x
+	_ = a + b + c + d + e + 2*3
+	_ = a + b + c + 2*3 + d + e
+	_ = (a + b + c) * 2
+	_ = a - b + c - d + (a + b + c) + d&e
+	_ = under_bar - 1
+	_ = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
+	_ = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx)
+
+	// the parser does not restrict expressions that may appear as statements
+	true
+	42
+	"foo"
+	x
+	(x)
+	a + b
+	a + b + c
+	a + (b * c)
+	a + (b / c)
+	1 + a
+	a + 1
+	s[a]
+	x << 1
+	(s[0] << 1) & 0xf
+	"foo" + s
+	x == y
+	x < y || z > 42
+}
+
+// slice expressions with cap
+func _() {
+	_ = x[a:b:c]
+	_ = x[a:b : c+d]
+	_ = x[a : b+d : c]
+	_ = x[a : b+d : c+d]
+	_ = x[a+d : b:c]
+	_ = x[a+d : b : c+d]
+	_ = x[a+d : b+d : c]
+	_ = x[a+d : b+d : c+d]
+
+	_ = x[:b:c]
+	_ = x[:b : c+d]
+	_ = x[:b+d : c]
+	_ = x[:b+d : c+d]
+}
+
+func _() {
+	_ = a + b
+	_ = a + b + c
+	_ = a + b*c
+	_ = a + (b * c)
+	_ = (a + b) * c
+	_ = a + (b * c * d)
+	_ = a + (b*c + d)
+
+	_ = 1 << x
+	_ = -1 << x
+	_ = 1<<x - 1
+	_ = -1<<x - 1
+
+	_ = f(a + b)
+	_ = f(a + b + c)
+	_ = f(a + b*c)
+	_ = f(a + (b * c))
+	_ = f(1<<x-1, 1<<x-2)
+
+	_ = 1<<d.logWindowSize - 1
+
+	buf = make(x, 2*cap(b.buf)+n)
+
+	dst[i*3+2] = dbuf[0] << 2
+	dst[i*3+2] = dbuf[0]<<2 | dbuf[1]>>4
+
+	b.buf = b.buf[0 : b.off+m+n]
+	b.buf = b.buf[0 : b.off+m*n]
+	f(b.buf[0 : b.off+m+n])
+
+	signed += ' ' * 8
+	tw.octal(header[148:155], chksum)
+
+	_ = x > 0 && i >= 0
+
+	x1, x0 := x>>w2, x&m2
+	z0 = t1<<w2 + t0
+	z1 = (t1 + t0>>w2) >> w2
+	q1, r1 := x1/d1, x1%d1
+	r1 = r1*b2 | x0>>w2
+	x1 = (x1 << z) | (x0 >> (uint(w) - z))
+	x1 = x1<<z | x0>>(uint(w)-z)
+
+	_ = buf[0 : len(buf)+1]
+	_ = buf[0 : n+1]
+
+	a, b = b, a
+	a = b + c
+	a = b*c + d
+	_ = a*b + c
+	_ = a - b - c
+	_ = a - (b - c)
+	_ = a - b*c
+	_ = a - (b * c)
+	_ = a * b / c
+	_ = a / *b
+	_ = x[a|^b]
+	_ = x[a / *b]
+	_ = a & ^b
+	_ = a + +b
+	_ = a - -b
+	_ = x[a*-b]
+	_ = x[a + +b]
+	_ = x ^ y ^ z
+	_ = b[a>>24] ^ b[(a>>16)&0xFF] ^ b[(a>>8)&0xFF] ^ b[a&0xFF]
+	_ = len(longVariableName) * 2
+
+	_ = token(matchType + xlength<<lengthShift + xoffset)
+}
+
+func f(x int, args ...int) {
+	f(0, args...)
+	f(1, args)
+	f(2, args[0])
+
+	// make sure syntactically legal code remains syntactically legal
+	f(3, 42 ...)	// a blank must remain between 42 and ...
+	f(4, 42....)
+	f(5, 42....)
+	f(6, 42.0...)
+	f(7, 42.0...)
+	f(8, .42...)
+	f(9, .42...)
+	f(10, 42e0...)
+	f(11, 42e0...)
+
+	_ = 42 .x	// a blank must remain between 42 and .x
+	_ = 42..x
+	_ = 42..x
+	_ = 42.0.x
+	_ = 42.0.x
+	_ = .42.x
+	_ = .42.x
+	_ = 42e0.x
+	_ = 42e0.x
+
+	// a blank must remain between the binary operator and the 2nd operand
+	_ = x / *y
+	_ = x < -1
+	_ = x < <-1
+	_ = x + +1
+	_ = x - -1
+	_ = x & &x
+	_ = x & ^x
+
+	_ = f(x / *y, x < -1, x < <-1, x + +1, x - -1, x & &x, x & ^x)
+}
+
+func _() {
+	_ = T{}
+	_ = struct{}{}
+	_ = [10]T{}
+	_ = [...]T{}
+	_ = []T{}
+	_ = map[int]T{}
+}
+
+// one-line structs/interfaces in composite literals (up to a threshold)
+func _() {
+	_ = struct{}{}
+	_ = struct{ x int }{0}
+	_ = struct{ x, y, z int }{0, 1, 2}
+	_ = struct{ int }{0}
+	_ = struct{ s struct{ int } }{struct{ int }{0}}
+}
+
+func _() {
+	// do not modify literals
+	_ = "tab1	tab2	tab3	end"	// string contains 3 tabs
+	_ = "tab1 tab2 tab3 end"	// same string with 3 blanks - may be unaligned because editors see tabs in strings
+	_ = ""				// this comment should be aligned with the one on the previous line
+	_ = ``
+	_ = `
+`
+	_ = `foo
+		bar`
+	_ = `three spaces before the end of the line starting here:   
+they must not be removed`
+}
+
+func _() {
+	// smart handling of indentation for multi-line raw strings
+	var _ = ``
+	var _ = `foo`
+	var _ = `foo
+bar`
+
+	var _ = ``
+	var _ = `foo`
+	var _ =
+	// the next line should remain indented
+	`foo
+bar`
+
+	var _ =	// comment
+	``
+	var _ =	// comment
+	`foo`
+	var _ =	// comment
+	// the next line should remain indented
+	`foo
+bar`
+
+	var _ = /* comment */ ``
+	var _ = /* comment */ `foo`
+	var _ = /* comment */ `foo
+bar`
+
+	var _ =	/* comment */
+	``
+	var _ =	/* comment */
+	`foo`
+	var _ =	/* comment */
+	// the next line should remain indented
+	`foo
+bar`
+
+	var board = []int(
+		`...........
+...........
+....●●●....
+....●●●....
+..●●●●●●●..
+..●●●○●●●..
+..●●●●●●●..
+....●●●....
+....●●●....
+...........
+...........
+`)
+
+	var state = S{
+		"foo",
+		// the next line should remain indented
+		`...........
+...........
+....●●●....
+....●●●....
+..●●●●●●●..
+..●●●○●●●..
+..●●●●●●●..
+....●●●....
+....●●●....
+...........
+...........
+`,
+		"bar",
+	}
+}
+
+func _() {
+	// one-line function literals (body is on a single line)
+	_ = func() {}
+	_ = func() int { return 0 }
+	_ = func(x, y int) bool { m := (x + y) / 2; return m < 0 }
+
+	// multi-line function literals (body is not on one line)
+	_ = func() {
+	}
+	_ = func() int {
+		return 0
+	}
+	_ = func(x, y int) bool {
+		m := (x + y) / 2
+		return x < y
+	}
+
+	f(func() {
+	})
+	f(func() int {
+		return 0
+	})
+	f(func(x, y int) bool {
+		m := (x + y) / 2
+		return x < y
+	})
+}
+
+func _() {
+	_ = [][]int{
+		[]int{1},
+		[]int{1, 2},
+		[]int{1, 2, 3},
+	}
+	_ = [][]int{
+		{1},
+		[]int{1, 2},
+		[]int{1, 2, 3},
+	}
+	_ = [][]int{
+		{1},
+		{1, 2},
+		{1, 2, 3},
+	}
+	_ = [][]int{{1}, {1, 2}, {1, 2, 3}}
+}
+
+// various multi-line expressions
+func _() {
+	// do not add extra indentation to multi-line string lists
+	_ = "foo" + "bar"
+	_ = "foo" +
+		"bar" +
+		"bah"
+	_ = []string{
+		"abc" +
+			"def",
+		"foo" +
+			"bar",
+	}
+}
+
+const _ = F1 +
+	`string = "%s";` +
+	`ptr = *;` +
+	`datafmt.T2 = s ["-" p "-"];`
+
+const _ = `datafmt "datafmt";` +
+	`default = "%v";` +
+	`array = *;` +
+	`datafmt.T3 = s  {" " a a / ","};`
+
+const _ = `datafmt "datafmt";` +
+	`default = "%v";` +
+	`array = *;` +
+	`datafmt.T3 = s  {" " a a / ","};`
+
+func _() {
+	_ = F1 +
+		`string = "%s";` +
+		`ptr = *;` +
+		`datafmt.T2 = s ["-" p "-"];`
+
+	_ =
+		`datafmt "datafmt";` +
+			`default = "%v";` +
+			`array = *;` +
+			`datafmt.T3 = s  {" " a a / ","};`
+
+	_ = `datafmt "datafmt";` +
+		`default = "%v";` +
+		`array = *;` +
+		`datafmt.T3 = s  {" " a a / ","};`
+}
+
+func _() {
+	// respect source lines in multi-line expressions
+	_ = a +
+		b +
+		c
+	_ = a < b ||
+		b < a
+	_ = "933262154439441526816992388562667004907159682643816214685929" +
+		"638952175999932299156089414639761565182862536979208272237582" +
+		"51185210916864000000000000000000000000"	// 100!
+	_ = "170141183460469231731687303715884105727"	// prime
+}
+
+// Alignment after overlong lines
+const (
+	_	= "991"
+	_	= "2432902008176640000"	// 20!
+	_	= "933262154439441526816992388562667004907159682643816214685929" +
+		"638952175999932299156089414639761565182862536979208272237582" +
+		"51185210916864000000000000000000000000"	// 100!
+	_	= "170141183460469231731687303715884105727"	// prime
+)
+
+// Correct placement of operators and comments in multi-line expressions
+func _() {
+	_ = a +	// comment
+		b +	// comment
+		c
+	_ = "a" +
+		"b" +	// comment
+		"c"
+	_ = "ba0408" + "7265717569726564"	// field 71, encoding 2, string "required"
+}
+
+// Correct placement of terminating comma/closing parentheses in multi-line calls.
+func _() {
+	f(1,
+		2,
+		3)
+	f(1,
+		2,
+		3,
+	)
+	f(1,
+		2,
+		3)	// comment
+	f(1,
+		2,
+		3,	// comment
+	)
+	f(1,
+		2,
+		3)	// comment
+	f(1,
+		2,
+		3,	// comment
+	)
+}
+
+// Align comments in multi-line lists of single-line expressions.
+var txpix = [NCOL]draw.Color{
+	draw.Yellow,		// yellow
+	draw.Cyan,		// cyan
+	draw.Green,		// lime green
+	draw.GreyBlue,		// slate
+	draw.Red,		/* red */
+	draw.GreyGreen,		/* olive green */
+	draw.Blue,		/* blue */
+	draw.Color(0xFF55AAFF),	/* pink */
+	draw.Color(0xFFAAFFFF),	/* lavender */
+	draw.Color(0xBB005DFF),	/* maroon */
+}
+
+func same(t, u *Time) bool {
+	// respect source lines in multi-line expressions
+	return t.Year == u.Year &&
+		t.Month == u.Month &&
+		t.Day == u.Day &&
+		t.Hour == u.Hour &&
+		t.Minute == u.Minute &&
+		t.Second == u.Second &&
+		t.Weekday == u.Weekday &&
+		t.ZoneOffset == u.ZoneOffset &&
+		t.Zone == u.Zone
+}
+
+func (p *parser) charClass() {
+	// respect source lines in multi-line expressions
+	if cc.negate && len(cc.ranges) == 2 &&
+		cc.ranges[0] == '\n' && cc.ranges[1] == '\n' {
+		nl := new(_NotNl)
+		p.re.add(nl)
+	}
+}
+
+func addState(s []state, inst instr, match []int) {
+	// handle comments correctly in multi-line expressions
+	for i := 0; i < l; i++ {
+		if s[i].inst.index() == index &&	// same instruction
+			s[i].match[0] < pos {	// earlier match already going; leftmost wins
+			return s
+		}
+	}
+}
+
+func (self *T) foo(x int) *T	{ return self }
+
+func _()	{ module.Func1().Func2() }
+
+func _() {
+	_ = new(T).
+		foo(1).
+		foo(2).
+		foo(3)
+
+	_ = new(T).
+		foo(1).
+		foo(2).	// inline comments
+		foo(3)
+
+	_ = new(T).foo(1).foo(2).foo(3)
+
+	// handle multiline argument list correctly
+	_ = new(T).
+		foo(
+		1).
+		foo(2)
+
+	_ = new(T).foo(
+		1).foo(2)
+
+	_ = Array[3+
+		4]
+
+	_ = Method(1, 2,
+		3)
+
+	_ = new(T).
+		foo().
+		bar().(*Type)
+
+	_ = new(T).
+		foo().
+		bar().(*Type).
+		baz()
+
+	_ = new(T).
+		foo().
+		bar()["idx"]
+
+	_ = new(T).
+		foo().
+		bar()["idx"].
+		baz()
+
+	_ = new(T).
+		foo().
+		bar()[1:2]
+
+	_ = new(T).
+		foo().
+		bar()[1:2].
+		baz()
+
+	_ = new(T).
+		Field.
+		Array[3+
+		4].
+		Table["foo"].
+		Blob.(*Type).
+		Slices[1:4].
+		Method(1, 2,
+		3).
+		Thingy
+
+	_ = a.b.c
+	_ = a.
+		b.
+		c
+	_ = a.b().c
+	_ = a.
+		b().
+		c
+	_ = a.b[0].c
+	_ = a.
+		b[0].
+		c
+	_ = a.b[0:].c
+	_ = a.
+		b[0:].
+		c
+	_ = a.b.(T).c
+	_ = a.
+		b.(T).
+		c
+}
+
+// Don't introduce extra newlines in strangely formatted expression lists.
+func f() {
+	// os.Open parameters should remain on two lines
+	if writer, err = os.Open(outfile, s.O_WRONLY|os.O_CREATE|
+		os.O_TRUNC, 0666); err != nil {
+		log.Fatal(err)
+	}
+}
+
+// Handle multi-line argument lists ending in ... correctly.
+// Was issue 3130.
+func _() {
+	_ = append(s, a...)
+	_ = append(
+		s, a...)
+	_ = append(s,
+		a...)
+	_ = append(
+		s,
+		a...)
+	_ = append(s, a...,
+	)
+	_ = append(s,
+		a...,
+	)
+	_ = append(
+		s,
+		a...,
+	)
+}
+
+// Literal function types in conversions must be parenthesized;
+// for now go/parser accepts the unparenthesized form where it
+// is non-ambiguous.
+func _() {
+	// these conversions should be rewritten to look
+	// the same as the parenthesized conversions below
+	_ = (func())(nil)
+	_ = (func(x int) float)(nil)
+	_ = (func() func() func())(nil)
+
+	_ = (func())(nil)
+	_ = (func(x int) float)(nil)
+	_ = (func() func() func())(nil)
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/expressions.input b/third_party/gofrontend/libgo/go/go/printer/testdata/expressions.input
new file mode 100644
index 0000000..f4d20fa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/expressions.input
@@ -0,0 +1,710 @@
+// 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 expressions
+
+type T struct {
+	x, y, z int
+}
+
+var (
+	a, b, c, d, e int
+	under_bar int
+	longIdentifier1, longIdentifier2, longIdentifier3 int
+	t0, t1, t2 T
+	s string
+	p *int
+)
+
+
+func _() {
+	// no spaces around simple or parenthesized expressions
+	_ = (a+0)
+	_ = a+b
+	_ = a+b+c
+	_ = a+b-c
+	_ = a-b-c
+	_ = a+(b*c)
+	_ = a+(b/c)
+	_ = a-(b%c)
+	_ = 1+a
+	_ = a+1
+	_ = a+b+1
+	_ = s[a]
+	_ = s[a:]
+	_ = s[:b]
+	_ = s[1:2]
+	_ = s[a:b]
+	_ = s[0:len(s)]
+	_ = s[0]<<1
+	_ = (s[0]<<1)&0xf
+	_ = s[0] << 2 | s[1] >> 4
+	_ = "foo"+s
+	_ = s+"foo"
+	_ = 'a'+'b'
+	_ = len(s)/2
+	_ = len(t0.x)/a
+
+	// spaces around expressions of different precedence or expressions containing spaces
+	_ = a + -b
+	_ = a - ^b
+	_ = a / *p
+	_ = a + b*c
+	_ = 1 + b*c
+	_ = a + 2*c
+	_ = a + c*2
+	_ = 1 + 2*3
+	_ = s[1 : 2*3]
+	_ = s[a : b-c]
+	_ = s[0:]
+	_ = s[a+b]
+	_ = s[: b-c]
+	_ = s[a+b :]
+	_ = a[a<<b+1]
+	_ = a[a<<b+1 :]
+	_ = s[a+b : len(s)]
+	_ = s[len(s) : -a]
+	_ = s[a : len(s)+1]
+	_ = s[a : len(s)+1]+s
+
+	// spaces around operators with equal or lower precedence than comparisons
+	_ = a == b
+	_ = a != b
+	_ = a > b
+	_ = a >= b
+	_ = a < b
+	_ = a <= b
+	_ = a < b && c > d
+	_ = a < b || c > d
+
+	// spaces around "long" operands
+	_ = a + longIdentifier1
+	_ = longIdentifier1 + a
+	_ = longIdentifier1 + longIdentifier2 * longIdentifier3
+	_ = s + "a longer string"
+
+	// some selected cases
+	_ = a + t0.x
+	_ = a + t0.x + t1.x * t2.x
+	_ = a + b + c + d + e + 2*3
+	_ = a + b + c + 2*3 + d + e
+	_ = (a+b+c)*2
+	_ = a - b + c - d + (a+b+c) + d&e
+	_ = under_bar-1
+	_ = Open(dpath + "/file", O_WRONLY | O_CREAT, 0666)
+	_ = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx)
+
+	// the parser does not restrict expressions that may appear as statements
+	true
+	42
+	"foo"
+	x
+	(x)
+	a+b
+	a+b+c
+	a+(b*c)
+	a+(b/c)
+	1+a
+	a+1
+	s[a]
+	x<<1
+	(s[0]<<1)&0xf
+	"foo"+s
+	x == y
+	x < y || z > 42
+}
+
+
+// slice expressions with cap
+func _() {
+	_ = x[a:b:c]
+	_ = x[a:b:c+d]
+	_ = x[a:b+d:c]
+	_ = x[a:b+d:c+d]
+	_ = x[a+d:b:c]
+	_ = x[a+d:b:c+d]
+	_ = x[a+d:b+d:c]
+	_ = x[a+d:b+d:c+d]
+
+	_ = x[:b:c]
+	_ = x[:b:c+d]
+	_ = x[:b+d:c]
+	_ = x[:b+d:c+d]
+}
+
+func _() {
+	_ = a+b
+	_ = a+b+c
+	_ = a+b*c
+	_ = a+(b*c)
+	_ = (a+b)*c
+	_ = a+(b*c*d)
+	_ = a+(b*c+d)
+
+	_ = 1<<x
+	_ = -1<<x
+	_ = 1<<x-1
+	_ = -1<<x-1
+
+	_ = f(a+b)
+	_ = f(a+b+c)
+	_ = f(a+b*c)
+	_ = f(a+(b*c))
+	_ = f(1<<x-1, 1<<x-2)
+
+	_ = 1<<d.logWindowSize-1
+
+	buf = make(x, 2*cap(b.buf) + n)
+
+	dst[i*3+2] = dbuf[0]<<2
+	dst[i*3+2] = dbuf[0]<<2 | dbuf[1]>>4
+
+	b.buf = b.buf[0:b.off+m+n]
+	b.buf = b.buf[0:b.off+m*n]
+	f(b.buf[0:b.off+m+n])
+
+	signed += ' '*8
+	tw.octal(header[148:155], chksum)
+
+	_ = x > 0 && i >= 0
+
+	x1, x0 := x>>w2, x&m2
+	z0 = t1<<w2+t0
+	z1 = (t1+t0>>w2)>>w2
+	q1, r1 := x1/d1, x1%d1
+	r1 = r1*b2 | x0>>w2
+	x1 = (x1<<z)|(x0>>(uint(w)-z))
+	x1 = x1<<z | x0>>(uint(w)-z)
+
+	_ = buf[0:len(buf)+1]
+	_ = buf[0:n+1]
+
+	a,b = b,a
+	a = b+c
+	a = b*c+d
+	_ = a*b+c
+	_ = a-b-c
+	_ = a-(b-c)
+	_ = a-b*c
+	_ = a-(b*c)
+	_ = a*b/c
+	_ = a/ *b
+	_ = x[a|^b]
+	_ = x[a/ *b]
+	_ = a& ^b
+	_ = a+ +b
+	_ = a- -b
+	_ = x[a*-b]
+	_ = x[a+ +b]
+	_ = x^y^z
+	_ = b[a>>24] ^ b[(a>>16)&0xFF] ^ b[(a>>8)&0xFF] ^ b[a&0xFF]
+	_ = len(longVariableName)*2
+
+	_ = token(matchType + xlength<<lengthShift + xoffset)
+}
+
+
+func f(x int, args ...int) {
+	f(0, args...)
+	f(1, args)
+	f(2, args[0])
+
+	// make sure syntactically legal code remains syntactically legal
+	f(3, 42 ...) // a blank must remain between 42 and ...
+	f(4, 42. ...)
+	f(5, 42....)
+	f(6, 42.0 ...)
+	f(7, 42.0...)
+	f(8, .42 ...)
+	f(9, .42...)
+	f(10, 42e0 ...)
+	f(11, 42e0...)
+
+	_ = 42 .x // a blank must remain between 42 and .x
+	_ = 42. .x
+	_ = 42..x
+	_ = 42.0 .x
+	_ = 42.0.x
+	_ = .42 .x
+	_ = .42.x
+	_ = 42e0 .x
+	_ = 42e0.x
+
+	// a blank must remain between the binary operator and the 2nd operand
+	_ = x/ *y
+	_ = x< -1
+	_ = x< <-1
+	_ = x+ +1
+	_ = x- -1
+	_ = x& &x
+	_ = x& ^x
+
+	_ = f(x/ *y, x< -1, x< <-1, x+ +1, x- -1, x& &x, x& ^x)
+}
+
+
+func _() {
+	_ = T{}
+	_ = struct{}{}
+	_ = [10]T{}
+	_ = [...]T{}
+	_ = []T{}
+	_ = map[int]T{}
+}
+
+
+// one-line structs/interfaces in composite literals (up to a threshold)
+func _() {
+	_ = struct{}{}
+	_ = struct{ x int }{0}
+	_ = struct{ x, y, z int }{0, 1, 2}
+	_ = struct{ int }{0}
+	_ = struct{ s struct { int } }{struct{ int}{0} }
+}
+
+
+func _() {
+	// do not modify literals
+	_ = "tab1	tab2	tab3	end"  // string contains 3 tabs
+	_ = "tab1 tab2 tab3 end"  // same string with 3 blanks - may be unaligned because editors see tabs in strings
+	_ = ""  // this comment should be aligned with the one on the previous line
+	_ = ``
+	_ = `
+`
+_ = `foo
+		bar`
+	_ = `three spaces before the end of the line starting here:   
+they must not be removed`
+}
+
+
+func _() {
+	// smart handling of indentation for multi-line raw strings
+	var _ = ``
+	var _ = `foo`
+	var _ = `foo
+bar`
+
+
+var _ =
+	``
+var _ =
+	`foo`
+var _ =
+	// the next line should remain indented
+	`foo
+bar`
+
+
+	var _ = // comment
+		``
+	var _ = // comment
+		`foo`
+	var _ = // comment
+		// the next line should remain indented
+		`foo
+bar`
+
+
+var _ = /* comment */ ``
+var _ = /* comment */ `foo`
+var _ = /* comment */ `foo
+bar`
+
+
+	var _ = /* comment */
+		``
+	var _ = /* comment */
+		`foo`
+	var _ = /* comment */
+		// the next line should remain indented
+		`foo
+bar`
+
+
+var board = []int(
+	`...........
+...........
+....●●●....
+....●●●....
+..●●●●●●●..
+..●●●○●●●..
+..●●●●●●●..
+....●●●....
+....●●●....
+...........
+...........
+`)
+
+
+	var state = S{
+		"foo",
+		// the next line should remain indented
+		`...........
+...........
+....●●●....
+....●●●....
+..●●●●●●●..
+..●●●○●●●..
+..●●●●●●●..
+....●●●....
+....●●●....
+...........
+...........
+`,
+		"bar",
+	}
+}
+
+
+func _() {
+	// one-line function literals (body is on a single line)
+	_ = func() {}
+	_ = func() int { return 0 }
+	_ = func(x, y int) bool { m := (x+y)/2; return m < 0 }
+
+	// multi-line function literals (body is not on one line)
+	_ = func() {
+	}
+	_ = func() int {
+		return 0
+	}
+	_ = func(x, y int) bool {
+		m := (x+y)/2; return x < y }
+
+	f(func() {
+	})
+	f(func() int {
+		return 0
+	})
+	f(func(x, y int) bool {
+		m := (x+y)/2; return x < y })
+}
+
+
+func _() {
+	_ = [][]int {
+		[]int{1},
+		[]int{1, 2},
+		[]int{1, 2, 3},
+	}
+	_ = [][]int {
+		{1},
+		[]int{1, 2},
+		[]int{1, 2, 3},
+	}
+	_ = [][]int {
+		{1},
+		{1, 2},
+		{1, 2, 3},
+	}
+	_ = [][]int {{1}, {1, 2}, {1, 2, 3}}
+}
+
+
+// various multi-line expressions
+func _() {
+	// do not add extra indentation to multi-line string lists
+	_ = "foo" + "bar"
+	_ = "foo" +
+	"bar" +
+	"bah"
+	_ = []string {
+		"abc" +
+		"def",
+		"foo" +
+		"bar",
+	}
+}
+
+
+const _ = F1 +
+	`string = "%s";` +
+	`ptr = *;` +
+	`datafmt.T2 = s ["-" p "-"];`
+
+
+const _ =
+	`datafmt "datafmt";` +
+	`default = "%v";` +
+	`array = *;` +
+	`datafmt.T3 = s  {" " a a / ","};`
+
+
+const _ = `datafmt "datafmt";` +
+`default = "%v";` +
+`array = *;` +
+`datafmt.T3 = s  {" " a a / ","};`
+
+
+func _() {
+	_ = F1 +
+		`string = "%s";` +
+		`ptr = *;` +
+		`datafmt.T2 = s ["-" p "-"];`
+
+	_ =
+		`datafmt "datafmt";` +
+		`default = "%v";` +
+		`array = *;` +
+		`datafmt.T3 = s  {" " a a / ","};`
+
+	_ = `datafmt "datafmt";` +
+	`default = "%v";` +
+	`array = *;` +
+	`datafmt.T3 = s  {" " a a / ","};`
+}
+
+
+func _() {
+	// respect source lines in multi-line expressions
+	_ = a+
+	b+
+	c
+	_ = a < b ||
+		b < a
+	_ = "933262154439441526816992388562667004907159682643816214685929" +
+	"638952175999932299156089414639761565182862536979208272237582" +
+	"51185210916864000000000000000000000000"  // 100!
+	_ = "170141183460469231731687303715884105727"  // prime
+}
+
+
+// Alignment after overlong lines
+const (
+	_ = "991"
+	_ = "2432902008176640000"  // 20!
+	_ = "933262154439441526816992388562667004907159682643816214685929" +
+	"638952175999932299156089414639761565182862536979208272237582" +
+	"51185210916864000000000000000000000000"  // 100!
+	_ = "170141183460469231731687303715884105727"  // prime
+)
+
+
+// Correct placement of operators and comments in multi-line expressions
+func _() {
+	_ = a +  // comment
+		b +  // comment
+		c
+	_ = "a"	+
+		"b" +	// comment
+		"c"
+	_ = "ba0408" + "7265717569726564"     // field 71, encoding 2, string "required"
+}
+
+
+// Correct placement of terminating comma/closing parentheses in multi-line calls.
+func _() {
+	f(1,
+		2,
+		3)
+	f(1,
+		2,
+		3,
+	)
+	f(1,
+		2,
+		3)  // comment
+	f(1,
+		2,
+		3,  // comment
+	)
+	f(1,
+		2,
+		3)// comment
+	f(1,
+		2,
+		3,// comment
+	)
+}
+
+
+// Align comments in multi-line lists of single-line expressions.
+var txpix = [NCOL]draw.Color{
+	draw.Yellow, // yellow
+	draw.Cyan, // cyan
+	draw.Green, // lime green
+	draw.GreyBlue, // slate
+	draw.Red, /* red */
+	draw.GreyGreen, /* olive green */
+	draw.Blue, /* blue */
+	draw.Color(0xFF55AAFF), /* pink */
+	draw.Color(0xFFAAFFFF), /* lavender */
+	draw.Color(0xBB005DFF), /* maroon */
+}
+
+
+func same(t, u *Time) bool {
+	// respect source lines in multi-line expressions
+	return t.Year == u.Year &&
+		t.Month == u.Month &&
+		t.Day == u.Day &&
+		t.Hour == u.Hour &&
+		t.Minute == u.Minute &&
+		t.Second == u.Second &&
+		t.Weekday == u.Weekday &&
+		t.ZoneOffset == u.ZoneOffset &&
+		t.Zone == u.Zone
+}
+
+
+func (p *parser) charClass() {
+	// respect source lines in multi-line expressions
+	if cc.negate && len(cc.ranges) == 2 &&
+		cc.ranges[0] == '\n' && cc.ranges[1] == '\n' {
+		nl := new(_NotNl)
+		p.re.add(nl)
+	}
+}
+
+
+func addState(s []state, inst instr, match []int) {
+	// handle comments correctly in multi-line expressions
+	for i := 0; i < l; i++ {
+		if s[i].inst.index() == index && // same instruction
+		   s[i].match[0] < pos {	// earlier match already going; leftmost wins
+		   	return s
+		 }
+	}
+}
+
+func (self *T) foo(x int) *T { return self }
+
+func _() { module.Func1().Func2() }
+
+func _() {
+	_ = new(T).
+		foo(1).
+			foo(2).
+		foo(3)
+
+	_ = new(T).
+	foo(1).
+	foo(2). // inline comments
+	foo(3)
+
+	_ = new(T).foo(1).foo(2).foo(3)
+
+	// handle multiline argument list correctly
+	_ = new(T).
+	foo(
+		1).
+		foo(2)
+
+	_ = new(T).foo(
+		1).foo(2)
+
+	_ = Array[3 +
+4]
+
+	_ = Method(1, 2,
+		3)
+
+	_ = new(T).
+   foo().
+   bar() . (*Type)
+
+	_ = new(T).
+foo().
+bar().(*Type).
+baz()
+
+	_ = new(T).
+	foo().
+	bar()["idx"]
+
+	_ = new(T).
+	foo().
+	bar()["idx"]	.
+	baz()
+
+	_ = new(T).
+	foo().
+	bar()[1:2]
+
+	_ = new(T).
+	foo().
+	bar()[1:2].
+	baz()
+
+	_ = new(T).
+		Field.
+		Array[3+
+       		4].
+		Table ["foo"].
+		Blob. (*Type).
+	Slices[1:4].
+	Method(1, 2,
+	3).
+		Thingy
+
+	_ = a.b.c
+	_ = a.
+	b.
+	c
+	_ = a.b().c
+	_ = a.
+	b().
+	c
+	_ = a.b[0].c
+	_ = a.
+	b[0].
+	c
+	_ = a.b[0:].c
+	_ = a.
+	b[0:].
+	c
+	_ = a.b.(T).c
+	_ = a.
+	b.
+	(T).
+	c
+}
+
+
+// Don't introduce extra newlines in strangely formatted expression lists.
+func f() {
+	// os.Open parameters should remain on two lines
+	if writer, err = os.Open(outfile, s.O_WRONLY|os.O_CREATE|
+		os.O_TRUNC, 0666); err != nil {
+	    log.Fatal(err)
+	}
+}
+
+// Handle multi-line argument lists ending in ... correctly.
+// Was issue 3130.
+func _() {
+	_ = append(s, a...)
+	_ = append(
+		s, a...)
+	_ = append(s,
+		a...)
+	_ = append(
+		s,
+		a...)
+	_ = append(s, a...,
+	)
+	_ = append(s,
+		a...,
+	)
+	_ = append(
+		s,
+		a...,
+	)
+}
+
+// Literal function types in conversions must be parenthesized;
+// for now go/parser accepts the unparenthesized form where it
+// is non-ambiguous.
+func _() {
+	// these conversions should be rewritten to look
+	// the same as the parenthesized conversions below
+	_ = func()()(nil)
+	_ = func(x int)(float)(nil)
+	_ = func() func() func()()(nil)
+
+	_ = (func()())(nil)
+	_ = (func(x int)(float))(nil)
+	_ = (func() func() func()())(nil)
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/expressions.raw b/third_party/gofrontend/libgo/go/go/printer/testdata/expressions.raw
new file mode 100644
index 0000000..97bc81d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/expressions.raw
@@ -0,0 +1,681 @@
+// 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 expressions
+
+type T struct {
+	x, y, z int
+}
+
+var (
+	a, b, c, d, e	int
+	under_bar	int
+	longIdentifier1, longIdentifier2, longIdentifier3	int
+	t0, t1, t2	T
+	s	string
+	p	*int
+)
+
+func _() {
+	// no spaces around simple or parenthesized expressions
+	_ = (a + 0)
+	_ = a + b
+	_ = a + b + c
+	_ = a + b - c
+	_ = a - b - c
+	_ = a + (b * c)
+	_ = a + (b / c)
+	_ = a - (b % c)
+	_ = 1 + a
+	_ = a + 1
+	_ = a + b + 1
+	_ = s[a]
+	_ = s[a:]
+	_ = s[:b]
+	_ = s[1:2]
+	_ = s[a:b]
+	_ = s[0:len(s)]
+	_ = s[0] << 1
+	_ = (s[0] << 1) & 0xf
+	_ = s[0]<<2 | s[1]>>4
+	_ = "foo" + s
+	_ = s + "foo"
+	_ = 'a' + 'b'
+	_ = len(s) / 2
+	_ = len(t0.x) / a
+
+	// spaces around expressions of different precedence or expressions containing spaces
+	_ = a + -b
+	_ = a - ^b
+	_ = a / *p
+	_ = a + b*c
+	_ = 1 + b*c
+	_ = a + 2*c
+	_ = a + c*2
+	_ = 1 + 2*3
+	_ = s[1 : 2*3]
+	_ = s[a : b-c]
+	_ = s[0:]
+	_ = s[a+b]
+	_ = s[:b-c]
+	_ = s[a+b:]
+	_ = a[a<<b+1]
+	_ = a[a<<b+1:]
+	_ = s[a+b : len(s)]
+	_ = s[len(s):-a]
+	_ = s[a : len(s)+1]
+	_ = s[a:len(s)+1] + s
+
+	// spaces around operators with equal or lower precedence than comparisons
+	_ = a == b
+	_ = a != b
+	_ = a > b
+	_ = a >= b
+	_ = a < b
+	_ = a <= b
+	_ = a < b && c > d
+	_ = a < b || c > d
+
+	// spaces around "long" operands
+	_ = a + longIdentifier1
+	_ = longIdentifier1 + a
+	_ = longIdentifier1 + longIdentifier2*longIdentifier3
+	_ = s + "a longer string"
+
+	// some selected cases
+	_ = a + t0.x
+	_ = a + t0.x + t1.x*t2.x
+	_ = a + b + c + d + e + 2*3
+	_ = a + b + c + 2*3 + d + e
+	_ = (a + b + c) * 2
+	_ = a - b + c - d + (a + b + c) + d&e
+	_ = under_bar - 1
+	_ = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
+	_ = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx)
+
+	// the parser does not restrict expressions that may appear as statements
+	true
+	42
+	"foo"
+	x
+	(x)
+	a + b
+	a + b + c
+	a + (b * c)
+	a + (b / c)
+	1 + a
+	a + 1
+	s[a]
+	x << 1
+	(s[0] << 1) & 0xf
+	"foo" + s
+	x == y
+	x < y || z > 42
+}
+
+// slice expressions with cap
+func _() {
+	_ = x[a:b:c]
+	_ = x[a:b : c+d]
+	_ = x[a : b+d : c]
+	_ = x[a : b+d : c+d]
+	_ = x[a+d : b:c]
+	_ = x[a+d : b : c+d]
+	_ = x[a+d : b+d : c]
+	_ = x[a+d : b+d : c+d]
+
+	_ = x[:b:c]
+	_ = x[:b : c+d]
+	_ = x[:b+d : c]
+	_ = x[:b+d : c+d]
+}
+
+func _() {
+	_ = a + b
+	_ = a + b + c
+	_ = a + b*c
+	_ = a + (b * c)
+	_ = (a + b) * c
+	_ = a + (b * c * d)
+	_ = a + (b*c + d)
+
+	_ = 1 << x
+	_ = -1 << x
+	_ = 1<<x - 1
+	_ = -1<<x - 1
+
+	_ = f(a + b)
+	_ = f(a + b + c)
+	_ = f(a + b*c)
+	_ = f(a + (b * c))
+	_ = f(1<<x-1, 1<<x-2)
+
+	_ = 1<<d.logWindowSize - 1
+
+	buf = make(x, 2*cap(b.buf)+n)
+
+	dst[i*3+2] = dbuf[0] << 2
+	dst[i*3+2] = dbuf[0]<<2 | dbuf[1]>>4
+
+	b.buf = b.buf[0 : b.off+m+n]
+	b.buf = b.buf[0 : b.off+m*n]
+	f(b.buf[0 : b.off+m+n])
+
+	signed += ' ' * 8
+	tw.octal(header[148:155], chksum)
+
+	_ = x > 0 && i >= 0
+
+	x1, x0 := x>>w2, x&m2
+	z0 = t1<<w2 + t0
+	z1 = (t1 + t0>>w2) >> w2
+	q1, r1 := x1/d1, x1%d1
+	r1 = r1*b2 | x0>>w2
+	x1 = (x1 << z) | (x0 >> (uint(w) - z))
+	x1 = x1<<z | x0>>(uint(w)-z)
+
+	_ = buf[0 : len(buf)+1]
+	_ = buf[0 : n+1]
+
+	a, b = b, a
+	a = b + c
+	a = b*c + d
+	_ = a*b + c
+	_ = a - b - c
+	_ = a - (b - c)
+	_ = a - b*c
+	_ = a - (b * c)
+	_ = a * b / c
+	_ = a / *b
+	_ = x[a|^b]
+	_ = x[a / *b]
+	_ = a & ^b
+	_ = a + +b
+	_ = a - -b
+	_ = x[a*-b]
+	_ = x[a + +b]
+	_ = x ^ y ^ z
+	_ = b[a>>24] ^ b[(a>>16)&0xFF] ^ b[(a>>8)&0xFF] ^ b[a&0xFF]
+	_ = len(longVariableName) * 2
+
+	_ = token(matchType + xlength<<lengthShift + xoffset)
+}
+
+func f(x int, args ...int) {
+	f(0, args...)
+	f(1, args)
+	f(2, args[0])
+
+	// make sure syntactically legal code remains syntactically legal
+	f(3, 42 ...)	// a blank must remain between 42 and ...
+	f(4, 42....)
+	f(5, 42....)
+	f(6, 42.0...)
+	f(7, 42.0...)
+	f(8, .42...)
+	f(9, .42...)
+	f(10, 42e0...)
+	f(11, 42e0...)
+
+	_ = 42 .x	// a blank must remain between 42 and .x
+	_ = 42..x
+	_ = 42..x
+	_ = 42.0.x
+	_ = 42.0.x
+	_ = .42.x
+	_ = .42.x
+	_ = 42e0.x
+	_ = 42e0.x
+
+	// a blank must remain between the binary operator and the 2nd operand
+	_ = x / *y
+	_ = x < -1
+	_ = x < <-1
+	_ = x + +1
+	_ = x - -1
+	_ = x & &x
+	_ = x & ^x
+
+	_ = f(x / *y, x < -1, x < <-1, x + +1, x - -1, x & &x, x & ^x)
+}
+
+func _() {
+	_ = T{}
+	_ = struct{}{}
+	_ = [10]T{}
+	_ = [...]T{}
+	_ = []T{}
+	_ = map[int]T{}
+}
+
+// one-line structs/interfaces in composite literals (up to a threshold)
+func _() {
+	_ = struct{}{}
+	_ = struct{ x int }{0}
+	_ = struct{ x, y, z int }{0, 1, 2}
+	_ = struct{ int }{0}
+	_ = struct{ s struct{ int } }{struct{ int }{0}}
+}
+
+func _() {
+	// do not modify literals
+	_ = "tab1	tab2	tab3	end"	// string contains 3 tabs
+	_ = "tab1 tab2 tab3 end"	// same string with 3 blanks - may be unaligned because editors see tabs in strings
+	_ = ""	// this comment should be aligned with the one on the previous line
+	_ = ``
+	_ = `
+`
+	_ = `foo
+		bar`
+	_ = `three spaces before the end of the line starting here:   
+they must not be removed`
+}
+
+func _() {
+	// smart handling of indentation for multi-line raw strings
+	var _ = ``
+	var _ = `foo`
+	var _ = `foo
+bar`
+
+	var _ = ``
+	var _ = `foo`
+	var _ =
+	// the next line should remain indented
+	`foo
+bar`
+
+	var _ =	// comment
+	``
+	var _ =	// comment
+	`foo`
+	var _ =	// comment
+	// the next line should remain indented
+	`foo
+bar`
+
+	var _ = /* comment */ ``
+	var _ = /* comment */ `foo`
+	var _ = /* comment */ `foo
+bar`
+
+	var _ =	/* comment */
+	``
+	var _ =	/* comment */
+	`foo`
+	var _ =	/* comment */
+	// the next line should remain indented
+	`foo
+bar`
+
+	var board = []int(
+		`...........
+...........
+....●●●....
+....●●●....
+..●●●●●●●..
+..●●●○●●●..
+..●●●●●●●..
+....●●●....
+....●●●....
+...........
+...........
+`)
+
+	var state = S{
+		"foo",
+		// the next line should remain indented
+		`...........
+...........
+....●●●....
+....●●●....
+..●●●●●●●..
+..●●●○●●●..
+..●●●●●●●..
+....●●●....
+....●●●....
+...........
+...........
+`,
+		"bar",
+	}
+}
+
+func _() {
+	// one-line function literals (body is on a single line)
+	_ = func() {}
+	_ = func() int { return 0 }
+	_ = func(x, y int) bool { m := (x + y) / 2; return m < 0 }
+
+	// multi-line function literals (body is not on one line)
+	_ = func() {
+	}
+	_ = func() int {
+		return 0
+	}
+	_ = func(x, y int) bool {
+		m := (x + y) / 2
+		return x < y
+	}
+
+	f(func() {
+	})
+	f(func() int {
+		return 0
+	})
+	f(func(x, y int) bool {
+		m := (x + y) / 2
+		return x < y
+	})
+}
+
+func _() {
+	_ = [][]int{
+		[]int{1},
+		[]int{1, 2},
+		[]int{1, 2, 3},
+	}
+	_ = [][]int{
+		{1},
+		[]int{1, 2},
+		[]int{1, 2, 3},
+	}
+	_ = [][]int{
+		{1},
+		{1, 2},
+		{1, 2, 3},
+	}
+	_ = [][]int{{1}, {1, 2}, {1, 2, 3}}
+}
+
+// various multi-line expressions
+func _() {
+	// do not add extra indentation to multi-line string lists
+	_ = "foo" + "bar"
+	_ = "foo" +
+		"bar" +
+		"bah"
+	_ = []string{
+		"abc" +
+			"def",
+		"foo" +
+			"bar",
+	}
+}
+
+const _ = F1 +
+	`string = "%s";` +
+	`ptr = *;` +
+	`datafmt.T2 = s ["-" p "-"];`
+
+const _ = `datafmt "datafmt";` +
+	`default = "%v";` +
+	`array = *;` +
+	`datafmt.T3 = s  {" " a a / ","};`
+
+const _ = `datafmt "datafmt";` +
+	`default = "%v";` +
+	`array = *;` +
+	`datafmt.T3 = s  {" " a a / ","};`
+
+func _() {
+	_ = F1 +
+		`string = "%s";` +
+		`ptr = *;` +
+		`datafmt.T2 = s ["-" p "-"];`
+
+	_ =
+		`datafmt "datafmt";` +
+			`default = "%v";` +
+			`array = *;` +
+			`datafmt.T3 = s  {" " a a / ","};`
+
+	_ = `datafmt "datafmt";` +
+		`default = "%v";` +
+		`array = *;` +
+		`datafmt.T3 = s  {" " a a / ","};`
+}
+
+func _() {
+	// respect source lines in multi-line expressions
+	_ = a +
+		b +
+		c
+	_ = a < b ||
+		b < a
+	_ = "933262154439441526816992388562667004907159682643816214685929" +
+		"638952175999932299156089414639761565182862536979208272237582" +
+		"51185210916864000000000000000000000000"	// 100!
+	_ = "170141183460469231731687303715884105727"	// prime
+}
+
+// Alignment after overlong lines
+const (
+	_	= "991"
+	_	= "2432902008176640000"		// 20!
+	_	= "933262154439441526816992388562667004907159682643816214685929" +
+		"638952175999932299156089414639761565182862536979208272237582" +
+		"51185210916864000000000000000000000000"	// 100!
+	_	= "170141183460469231731687303715884105727"		// prime
+)
+
+// Correct placement of operators and comments in multi-line expressions
+func _() {
+	_ = a +	// comment
+		b +	// comment
+		c
+	_ = "a" +
+		"b" +	// comment
+		"c"
+	_ = "ba0408" + "7265717569726564"	// field 71, encoding 2, string "required"
+}
+
+// Correct placement of terminating comma/closing parentheses in multi-line calls.
+func _() {
+	f(1,
+		2,
+		3)
+	f(1,
+		2,
+		3,
+	)
+	f(1,
+		2,
+		3)	// comment
+	f(1,
+		2,
+		3,	// comment
+	)
+	f(1,
+		2,
+		3)	// comment
+	f(1,
+		2,
+		3,	// comment
+	)
+}
+
+// Align comments in multi-line lists of single-line expressions.
+var txpix = [NCOL]draw.Color{
+	draw.Yellow,	// yellow
+	draw.Cyan,	// cyan
+	draw.Green,	// lime green
+	draw.GreyBlue,	// slate
+	draw.Red,	/* red */
+	draw.GreyGreen,	/* olive green */
+	draw.Blue,	/* blue */
+	draw.Color(0xFF55AAFF),	/* pink */
+	draw.Color(0xFFAAFFFF),	/* lavender */
+	draw.Color(0xBB005DFF),	/* maroon */
+}
+
+func same(t, u *Time) bool {
+	// respect source lines in multi-line expressions
+	return t.Year == u.Year &&
+		t.Month == u.Month &&
+		t.Day == u.Day &&
+		t.Hour == u.Hour &&
+		t.Minute == u.Minute &&
+		t.Second == u.Second &&
+		t.Weekday == u.Weekday &&
+		t.ZoneOffset == u.ZoneOffset &&
+		t.Zone == u.Zone
+}
+
+func (p *parser) charClass() {
+	// respect source lines in multi-line expressions
+	if cc.negate && len(cc.ranges) == 2 &&
+		cc.ranges[0] == '\n' && cc.ranges[1] == '\n' {
+		nl := new(_NotNl)
+		p.re.add(nl)
+	}
+}
+
+func addState(s []state, inst instr, match []int) {
+	// handle comments correctly in multi-line expressions
+	for i := 0; i < l; i++ {
+		if s[i].inst.index() == index &&	// same instruction
+			s[i].match[0] < pos {	// earlier match already going; leftmost wins
+			return s
+		}
+	}
+}
+
+func (self *T) foo(x int) *T	{ return self }
+
+func _()	{ module.Func1().Func2() }
+
+func _() {
+	_ = new(T).
+		foo(1).
+		foo(2).
+		foo(3)
+
+	_ = new(T).
+		foo(1).
+		foo(2).	// inline comments
+		foo(3)
+
+	_ = new(T).foo(1).foo(2).foo(3)
+
+	// handle multiline argument list correctly
+	_ = new(T).
+		foo(
+		1).
+		foo(2)
+
+	_ = new(T).foo(
+		1).foo(2)
+
+	_ = Array[3+
+		4]
+
+	_ = Method(1, 2,
+		3)
+
+	_ = new(T).
+		foo().
+		bar().(*Type)
+
+	_ = new(T).
+		foo().
+		bar().(*Type).
+		baz()
+
+	_ = new(T).
+		foo().
+		bar()["idx"]
+
+	_ = new(T).
+		foo().
+		bar()["idx"].
+		baz()
+
+	_ = new(T).
+		foo().
+		bar()[1:2]
+
+	_ = new(T).
+		foo().
+		bar()[1:2].
+		baz()
+
+	_ = new(T).
+		Field.
+		Array[3+
+		4].
+		Table["foo"].
+		Blob.(*Type).
+		Slices[1:4].
+		Method(1, 2,
+		3).
+		Thingy
+
+	_ = a.b.c
+	_ = a.
+		b.
+		c
+	_ = a.b().c
+	_ = a.
+		b().
+		c
+	_ = a.b[0].c
+	_ = a.
+		b[0].
+		c
+	_ = a.b[0:].c
+	_ = a.
+		b[0:].
+		c
+	_ = a.b.(T).c
+	_ = a.
+		b.(T).
+		c
+}
+
+// Don't introduce extra newlines in strangely formatted expression lists.
+func f() {
+	// os.Open parameters should remain on two lines
+	if writer, err = os.Open(outfile, s.O_WRONLY|os.O_CREATE|
+		os.O_TRUNC, 0666); err != nil {
+		log.Fatal(err)
+	}
+}
+
+// Handle multi-line argument lists ending in ... correctly.
+// Was issue 3130.
+func _() {
+	_ = append(s, a...)
+	_ = append(
+		s, a...)
+	_ = append(s,
+		a...)
+	_ = append(
+		s,
+		a...)
+	_ = append(s, a...,
+	)
+	_ = append(s,
+		a...,
+	)
+	_ = append(
+		s,
+		a...,
+	)
+}
+
+// Literal function types in conversions must be parenthesized;
+// for now go/parser accepts the unparenthesized form where it
+// is non-ambiguous.
+func _() {
+	// these conversions should be rewritten to look
+	// the same as the parenthesized conversions below
+	_ = (func())(nil)
+	_ = (func(x int) float)(nil)
+	_ = (func() func() func())(nil)
+
+	_ = (func())(nil)
+	_ = (func(x int) float)(nil)
+	_ = (func() func() func())(nil)
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/linebreaks.golden b/third_party/gofrontend/libgo/go/go/printer/testdata/linebreaks.golden
new file mode 100644
index 0000000..006cf17
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/linebreaks.golden
@@ -0,0 +1,275 @@
+// 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 linebreaks
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+type writerTestEntry struct {
+	header		*Header
+	contents	string
+}
+
+type writerTest struct {
+	file	string	// filename of expected output
+	entries	[]*writerTestEntry
+}
+
+var writerTests = []*writerTest{
+	&writerTest{
+		file:	"testdata/writer.tar",
+		entries: []*writerTestEntry{
+			&writerTestEntry{
+				header: &Header{
+					Name:		"small.txt",
+					Mode:		0640,
+					Uid:		73025,
+					Gid:		5000,
+					Size:		5,
+					Mtime:		1246508266,
+					Typeflag:	'0',
+					Uname:		"dsymonds",
+					Gname:		"eng",
+				},
+				contents:	"Kilts",
+			},
+			&writerTestEntry{
+				header: &Header{
+					Name:		"small2.txt",
+					Mode:		0640,
+					Uid:		73025,
+					Gid:		5000,
+					Size:		11,
+					Mtime:		1245217492,
+					Typeflag:	'0',
+					Uname:		"dsymonds",
+					Gname:		"eng",
+				},
+				contents:	"Google.com\n",
+			},
+		},
+	},
+	// The truncated test file was produced using these commands:
+	//   dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
+	//   tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
+	&writerTest{
+		file:	"testdata/writer-big.tar",
+		entries: []*writerTestEntry{
+			&writerTestEntry{
+				header: &Header{
+					Name:		"tmp/16gig.txt",
+					Mode:		0640,
+					Uid:		73025,
+					Gid:		5000,
+					Size:		16 << 30,
+					Mtime:		1254699560,
+					Typeflag:	'0',
+					Uname:		"dsymonds",
+					Gname:		"eng",
+				},
+				// no contents
+			},
+		},
+	},
+}
+
+type untarTest struct {
+	file	string
+	headers	[]*Header
+}
+
+var untarTests = []*untarTest{
+	&untarTest{
+		file:	"testdata/gnu.tar",
+		headers: []*Header{
+			&Header{
+				Name:		"small.txt",
+				Mode:		0640,
+				Uid:		73025,
+				Gid:		5000,
+				Size:		5,
+				Mtime:		1244428340,
+				Typeflag:	'0',
+				Uname:		"dsymonds",
+				Gname:		"eng",
+			},
+			&Header{
+				Name:		"small2.txt",
+				Mode:		0640,
+				Uid:		73025,
+				Gid:		5000,
+				Size:		11,
+				Mtime:		1244436044,
+				Typeflag:	'0',
+				Uname:		"dsymonds",
+				Gname:		"eng",
+			},
+		},
+	},
+	&untarTest{
+		file:	"testdata/star.tar",
+		headers: []*Header{
+			&Header{
+				Name:		"small.txt",
+				Mode:		0640,
+				Uid:		73025,
+				Gid:		5000,
+				Size:		5,
+				Mtime:		1244592783,
+				Typeflag:	'0',
+				Uname:		"dsymonds",
+				Gname:		"eng",
+				Atime:		1244592783,
+				Ctime:		1244592783,
+			},
+			&Header{
+				Name:		"small2.txt",
+				Mode:		0640,
+				Uid:		73025,
+				Gid:		5000,
+				Size:		11,
+				Mtime:		1244592783,
+				Typeflag:	'0',
+				Uname:		"dsymonds",
+				Gname:		"eng",
+				Atime:		1244592783,
+				Ctime:		1244592783,
+			},
+		},
+	},
+	&untarTest{
+		file:	"testdata/v7.tar",
+		headers: []*Header{
+			&Header{
+				Name:		"small.txt",
+				Mode:		0444,
+				Uid:		73025,
+				Gid:		5000,
+				Size:		5,
+				Mtime:		1244593104,
+				Typeflag:	'\x00',
+			},
+			&Header{
+				Name:		"small2.txt",
+				Mode:		0444,
+				Uid:		73025,
+				Gid:		5000,
+				Size:		11,
+				Mtime:		1244593104,
+				Typeflag:	'\x00',
+			},
+		},
+	},
+}
+
+var facts = map[int]string{
+	0:	"1",
+	1:	"1",
+	2:	"2",
+	10:	"3628800",
+	20:	"2432902008176640000",
+	100: "933262154439441526816992388562667004907159682643816214685929" +
+		"638952175999932299156089414639761565182862536979208272237582" +
+		"51185210916864000000000000000000000000",
+}
+
+func usage() {
+	fmt.Fprintf(os.Stderr,
+		// TODO(gri): the 2nd string of this string list should not be indented
+		"usage: godoc package [name ...]\n"+
+			"	godoc -http=:6060\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func TestReader(t *testing.T) {
+testLoop:
+	for i, test := range untarTests {
+		f, err := os.Open(test.file, os.O_RDONLY, 0444)
+		if err != nil {
+			t.Errorf("test %d: Unexpected error: %v", i, err)
+			continue
+		}
+		tr := NewReader(f)
+		for j, header := range test.headers {
+			hdr, err := tr.Next()
+			if err != nil || hdr == nil {
+				t.Errorf("test %d, entry %d: Didn't get entry: %v", i, j, err)
+				f.Close()
+				continue testLoop
+			}
+			if !reflect.DeepEqual(hdr, header) {
+				t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v",
+					i, j, *hdr, *header)
+			}
+		}
+		hdr, err := tr.Next()
+		if hdr != nil || err != nil {
+			t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, err)
+		}
+		f.Close()
+	}
+}
+
+// Respect line breaks in function calls.
+func _() {
+	f(x)
+	f(x,
+		x)
+	f(x,
+		x,
+	)
+	f(
+		x,
+		x)
+	f(
+		x,
+		x,
+	)
+}
+
+// Respect line breaks in function declarations.
+func _(x T)	{}
+func _(x T,
+	y T) {
+}
+func _(x T,
+	y T,
+) {
+}
+func _(
+	x T,
+	y T) {
+}
+func _(
+	x T,
+	y T,
+) {
+}
+
+// Example from issue 2597.
+func ManageStatus0(
+	in <-chan *Status,
+	req <-chan Request,
+	stat chan<- *TargetInfo,
+	TargetHistorySize int) {
+}
+
+func ManageStatus1(
+	in <-chan *Status,
+	req <-chan Request,
+	stat chan<- *TargetInfo,
+	TargetHistorySize int,
+) {
+}
+
+// There should be exactly one linebreak after this comment.
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/linebreaks.input b/third_party/gofrontend/libgo/go/go/printer/testdata/linebreaks.input
new file mode 100644
index 0000000..e782bb0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/linebreaks.input
@@ -0,0 +1,271 @@
+// 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 linebreaks
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+type writerTestEntry struct {
+	header *Header
+	contents string
+}
+
+type writerTest struct {
+	file string  // filename of expected output
+	entries []*writerTestEntry
+}
+
+var writerTests = []*writerTest{
+	&writerTest{
+		file: "testdata/writer.tar",
+		entries: []*writerTestEntry{
+			&writerTestEntry{
+				header: &Header{
+					Name: "small.txt",
+					Mode: 0640,
+					Uid: 73025,
+					Gid: 5000,
+					Size: 5,
+					Mtime: 1246508266,
+					Typeflag: '0',
+					Uname: "dsymonds",
+					Gname: "eng",
+				},
+				contents: "Kilts",
+			},
+			&writerTestEntry{
+				header: &Header{
+					Name: "small2.txt",
+					Mode: 0640,
+					Uid: 73025,
+					Gid: 5000,
+					Size: 11,
+					Mtime: 1245217492,
+					Typeflag: '0',
+					Uname: "dsymonds",
+					Gname: "eng",
+				},
+				contents: "Google.com\n",
+			},
+		},
+	},
+	// The truncated test file was produced using these commands:
+	//   dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
+	//   tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
+	&writerTest{
+		file: "testdata/writer-big.tar",
+		entries: []*writerTestEntry{
+			&writerTestEntry{
+				header: &Header{
+					Name: "tmp/16gig.txt",
+					Mode: 0640,
+					Uid: 73025,
+					Gid: 5000,
+					Size: 16 << 30,
+					Mtime: 1254699560,
+					Typeflag: '0',
+					Uname: "dsymonds",
+					Gname: "eng",
+				},
+				// no contents
+			},
+		},
+	},
+}
+
+type untarTest struct {
+	file string
+	headers []*Header
+}
+
+var untarTests = []*untarTest{
+	&untarTest{
+		file: "testdata/gnu.tar",
+		headers: []*Header{
+			&Header{
+				Name: "small.txt",
+				Mode: 0640,
+				Uid: 73025,
+				Gid: 5000,
+				Size: 5,
+				Mtime: 1244428340,
+				Typeflag: '0',
+				Uname: "dsymonds",
+				Gname: "eng",
+			},
+			&Header{
+				Name: "small2.txt",
+				Mode: 0640,
+				Uid: 73025,
+				Gid: 5000,
+				Size: 11,
+				Mtime: 1244436044,
+				Typeflag: '0',
+				Uname: "dsymonds",
+				Gname: "eng",
+			},
+		},
+	},
+	&untarTest{
+		file: "testdata/star.tar",
+		headers: []*Header{
+			&Header{
+				Name: "small.txt",
+				Mode: 0640,
+				Uid: 73025,
+				Gid: 5000,
+				Size: 5,
+				Mtime: 1244592783,
+				Typeflag: '0',
+				Uname: "dsymonds",
+				Gname: "eng",
+				Atime: 1244592783,
+				Ctime: 1244592783,
+			},
+			&Header{
+				Name: "small2.txt",
+				Mode: 0640,
+				Uid: 73025,
+				Gid: 5000,
+				Size: 11,
+				Mtime: 1244592783,
+				Typeflag: '0',
+				Uname: "dsymonds",
+				Gname: "eng",
+				Atime: 1244592783,
+				Ctime: 1244592783,
+			},
+		},
+	},
+	&untarTest{
+		file: "testdata/v7.tar",
+		headers: []*Header{
+			&Header{
+				Name: "small.txt",
+				Mode: 0444,
+				Uid: 73025,
+				Gid: 5000,
+				Size: 5,
+				Mtime: 1244593104,
+				Typeflag: '\x00',
+			},
+			&Header{
+				Name: "small2.txt",
+				Mode: 0444,
+				Uid: 73025,
+				Gid: 5000,
+				Size: 11,
+				Mtime: 1244593104,
+				Typeflag: '\x00',
+			},
+		},
+	},
+}
+
+var facts = map[int] string {
+	0: "1",
+	1: "1",
+	2: "2",
+	10: "3628800",
+	20: "2432902008176640000",
+	100: "933262154439441526816992388562667004907159682643816214685929" +
+		"638952175999932299156089414639761565182862536979208272237582" +
+		"51185210916864000000000000000000000000",
+}
+
+func usage() {
+	fmt.Fprintf(os.Stderr,
+		// TODO(gri): the 2nd string of this string list should not be indented
+		"usage: godoc package [name ...]\n" +
+		"	godoc -http=:6060\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func TestReader(t *testing.T) {
+testLoop:
+	for i, test := range untarTests {
+		f, err := os.Open(test.file, os.O_RDONLY, 0444)
+		if err != nil {
+			t.Errorf("test %d: Unexpected error: %v", i, err)
+			continue
+		}
+		tr := NewReader(f)
+		for j, header := range test.headers {
+			hdr, err := tr.Next()
+			if err != nil || hdr == nil {
+				t.Errorf("test %d, entry %d: Didn't get entry: %v", i, j, err)
+				f.Close()
+				continue testLoop
+			}
+			if !reflect.DeepEqual(hdr, header) {
+				t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v",
+					 i, j, *hdr, *header)
+			}
+		}
+		hdr, err := tr.Next()
+		if hdr != nil || err != nil {
+			t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, err)
+		}
+		f.Close()
+	}
+}
+
+// Respect line breaks in function calls.
+func _() {
+	f(x)
+	f(x,
+	  x)
+	f(x,
+	  x,
+	)
+	f(
+	  x,
+	  x)
+	f(
+	  x,
+	  x,
+	)
+}
+
+// Respect line breaks in function declarations.
+func _(x T) {}
+func _(x T,
+       y T) {}
+func _(x T,
+       y T,
+) {}
+func _(
+       x T,
+       y T) {}
+func _(
+       x T,
+       y T,
+) {}
+
+// Example from issue 2597.
+func ManageStatus0(
+	in <-chan *Status,
+	req <-chan Request,
+	stat chan<- *TargetInfo,
+	TargetHistorySize int) {
+}
+    
+func ManageStatus1(
+	in <-chan *Status,
+	req <-chan Request,
+	stat chan<- *TargetInfo,
+	TargetHistorySize int,
+) {
+}
+    
+// There should be exactly one linebreak after this comment.
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/parser.go b/third_party/gofrontend/libgo/go/go/printer/testdata/parser.go
new file mode 100644
index 0000000..dba8bbd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/parser.go
@@ -0,0 +1,2153 @@
+// 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 parser implements a parser for Go source files. Input may be
+// provided in a variety of forms (see the various Parse* functions); the
+// output is an abstract syntax tree (AST) representing the Go source. The
+// parser is invoked through one of the Parse* functions.
+
+package parser
+
+import (
+	"fmt"
+	"go/ast"
+	"go/scanner"
+	"go/token"
+)
+
+// The mode parameter to the Parse* functions is a set of flags (or 0).
+// They control the amount of source code parsed and other optional
+// parser functionality.
+//
+const (
+	PackageClauseOnly uint = 1 << iota // parsing stops after package clause
+	ImportsOnly                        // parsing stops after import declarations
+	ParseComments                      // parse comments and add them to AST
+	Trace                              // print a trace of parsed productions
+	DeclarationErrors                  // report declaration errors
+)
+
+// The parser structure holds the parser's internal state.
+type parser struct {
+	file *token.File
+	scanner.ErrorVector
+	scanner scanner.Scanner
+
+	// Tracing/debugging
+	mode   uint // parsing mode
+	trace  bool // == (mode & Trace != 0)
+	indent uint // indentation used for tracing output
+
+	// Comments
+	comments    []*ast.CommentGroup
+	leadComment *ast.CommentGroup // last lead comment
+	lineComment *ast.CommentGroup // last line comment
+
+	// Next token
+	pos token.Pos   // token position
+	tok token.Token // one token look-ahead
+	lit string      // token literal
+
+	// Non-syntactic parser control
+	exprLev int // < 0: in control clause, >= 0: in expression
+
+	// Ordinary identifier scopes
+	pkgScope   *ast.Scope        // pkgScope.Outer == nil
+	topScope   *ast.Scope        // top-most scope; may be pkgScope
+	unresolved []*ast.Ident      // unresolved identifiers
+	imports    []*ast.ImportSpec // list of imports
+
+	// Label scope
+	// (maintained by open/close LabelScope)
+	labelScope  *ast.Scope     // label scope for current function
+	targetStack [][]*ast.Ident // stack of unresolved labels
+}
+
+// scannerMode returns the scanner mode bits given the parser's mode bits.
+func scannerMode(mode uint) uint {
+	var m uint = scanner.InsertSemis
+	if mode&ParseComments != 0 {
+		m |= scanner.ScanComments
+	}
+	return m
+}
+
+func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode uint) {
+	p.file = fset.AddFile(filename, fset.Base(), len(src))
+	p.scanner.Init(p.file, src, p, scannerMode(mode))
+
+	p.mode = mode
+	p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
+
+	p.next()
+
+	// set up the pkgScope here (as opposed to in parseFile) because
+	// there are other parser entry points (ParseExpr, etc.)
+	p.openScope()
+	p.pkgScope = p.topScope
+
+	// for the same reason, set up a label scope
+	p.openLabelScope()
+}
+
+// ----------------------------------------------------------------------------
+// Scoping support
+
+func (p *parser) openScope() {
+	p.topScope = ast.NewScope(p.topScope)
+}
+
+func (p *parser) closeScope() {
+	p.topScope = p.topScope.Outer
+}
+
+func (p *parser) openLabelScope() {
+	p.labelScope = ast.NewScope(p.labelScope)
+	p.targetStack = append(p.targetStack, nil)
+}
+
+func (p *parser) closeLabelScope() {
+	// resolve labels
+	n := len(p.targetStack) - 1
+	scope := p.labelScope
+	for _, ident := range p.targetStack[n] {
+		ident.Obj = scope.Lookup(ident.Name)
+		if ident.Obj == nil && p.mode&DeclarationErrors != 0 {
+			p.error(ident.Pos(), fmt.Sprintf("label %s undefined", ident.Name))
+		}
+	}
+	// pop label scope
+	p.targetStack = p.targetStack[0:n]
+	p.labelScope = p.labelScope.Outer
+}
+
+func (p *parser) declare(decl interface{}, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) {
+	for _, ident := range idents {
+		assert(ident.Obj == nil, "identifier already declared or resolved")
+		if ident.Name != "_" {
+			obj := ast.NewObj(kind, ident.Name)
+			// remember the corresponding declaration for redeclaration
+			// errors and global variable resolution/typechecking phase
+			obj.Decl = decl
+			if alt := scope.Insert(obj); alt != nil && p.mode&DeclarationErrors != 0 {
+				prevDecl := ""
+				if pos := alt.Pos(); pos.IsValid() {
+					prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", p.file.Position(pos))
+				}
+				p.error(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
+			}
+			ident.Obj = obj
+		}
+	}
+}
+
+func (p *parser) shortVarDecl(idents []*ast.Ident) {
+	// Go spec: A short variable declaration may redeclare variables
+	// provided they were originally declared in the same block with
+	// the same type, and at least one of the non-blank variables is new.
+	n := 0 // number of new variables
+	for _, ident := range idents {
+		assert(ident.Obj == nil, "identifier already declared or resolved")
+		if ident.Name != "_" {
+			obj := ast.NewObj(ast.Var, ident.Name)
+			// short var declarations cannot have redeclaration errors
+			// and are not global => no need to remember the respective
+			// declaration
+			alt := p.topScope.Insert(obj)
+			if alt == nil {
+				n++ // new declaration
+				alt = obj
+			}
+			ident.Obj = alt
+		}
+	}
+	if n == 0 && p.mode&DeclarationErrors != 0 {
+		p.error(idents[0].Pos(), "no new variables on left side of :=")
+	}
+}
+
+// The unresolved object is a sentinel to mark identifiers that have been added
+// to the list of unresolved identifiers. The sentinel is only used for verifying
+// internal consistency.
+var unresolved = new(ast.Object)
+
+func (p *parser) resolve(x ast.Expr) {
+	// nothing to do if x is not an identifier or the blank identifier
+	ident, _ := x.(*ast.Ident)
+	if ident == nil {
+		return
+	}
+	assert(ident.Obj == nil, "identifier already declared or resolved")
+	if ident.Name == "_" {
+		return
+	}
+	// try to resolve the identifier
+	for s := p.topScope; s != nil; s = s.Outer {
+		if obj := s.Lookup(ident.Name); obj != nil {
+			ident.Obj = obj
+			return
+		}
+	}
+	// all local scopes are known, so any unresolved identifier
+	// must be found either in the file scope, package scope
+	// (perhaps in another file), or universe scope --- collect
+	// them so that they can be resolved later
+	ident.Obj = unresolved
+	p.unresolved = append(p.unresolved, ident)
+}
+
+// ----------------------------------------------------------------------------
+// Parsing support
+
+func (p *parser) printTrace(a ...interface{}) {
+	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " +
+		". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
+	const n = uint(len(dots))
+	pos := p.file.Position(p.pos)
+	fmt.Printf("%5d:%3d: ", pos.Line, pos.Column)
+	i := 2 * p.indent
+	for ; i > n; i -= n {
+		fmt.Print(dots)
+	}
+	fmt.Print(dots[0:i])
+	fmt.Println(a...)
+}
+
+func trace(p *parser, msg string) *parser {
+	p.printTrace(msg, "(")
+	p.indent++
+	return p
+}
+
+// Usage pattern: defer un(trace(p, "..."));
+func un(p *parser) {
+	p.indent--
+	p.printTrace(")")
+}
+
+// Advance to the next token.
+func (p *parser) next0() {
+	// Because of one-token look-ahead, print the previous token
+	// when tracing as it provides a more readable output. The
+	// very first token (!p.pos.IsValid()) is not initialized
+	// (it is token.ILLEGAL), so don't print it .
+	if p.trace && p.pos.IsValid() {
+		s := p.tok.String()
+		switch {
+		case p.tok.IsLiteral():
+			p.printTrace(s, p.lit)
+		case p.tok.IsOperator(), p.tok.IsKeyword():
+			p.printTrace("\"" + s + "\"")
+		default:
+			p.printTrace(s)
+		}
+	}
+
+	p.pos, p.tok, p.lit = p.scanner.Scan()
+}
+
+// Consume a comment and return it and the line on which it ends.
+func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
+	// /*-style comments may end on a different line than where they start.
+	// Scan the comment for '\n' chars and adjust endline accordingly.
+	endline = p.file.Line(p.pos)
+	if p.lit[1] == '*' {
+		// don't use range here - no need to decode Unicode code points
+		for i := 0; i < len(p.lit); i++ {
+			if p.lit[i] == '\n' {
+				endline++
+			}
+		}
+	}
+
+	comment = &ast.Comment{p.pos, p.lit}
+	p.next0()
+
+	return
+}
+
+// Consume a group of adjacent comments, add it to the parser's
+// comments list, and return it together with the line at which
+// the last comment in the group ends. An empty line or non-comment
+// token terminates a comment group.
+//
+func (p *parser) consumeCommentGroup() (comments *ast.CommentGroup, endline int) {
+	var list []*ast.Comment
+	endline = p.file.Line(p.pos)
+	for p.tok == token.COMMENT && endline+1 >= p.file.Line(p.pos) {
+		var comment *ast.Comment
+		comment, endline = p.consumeComment()
+		list = append(list, comment)
+	}
+
+	// add comment group to the comments list
+	comments = &ast.CommentGroup{list}
+	p.comments = append(p.comments, comments)
+
+	return
+}
+
+// Advance to the next non-comment token. In the process, collect
+// any comment groups encountered, and remember the last lead and
+// and line comments.
+//
+// A lead comment is a comment group that starts and ends in a
+// line without any other tokens and that is followed by a non-comment
+// token on the line immediately after the comment group.
+//
+// A line comment is a comment group that follows a non-comment
+// token on the same line, and that has no tokens after it on the line
+// where it ends.
+//
+// Lead and line comments may be considered documentation that is
+// stored in the AST.
+//
+func (p *parser) next() {
+	p.leadComment = nil
+	p.lineComment = nil
+	line := p.file.Line(p.pos) // current line
+	p.next0()
+
+	if p.tok == token.COMMENT {
+		var comment *ast.CommentGroup
+		var endline int
+
+		if p.file.Line(p.pos) == line {
+			// The comment is on same line as the previous token; it
+			// cannot be a lead comment but may be a line comment.
+			comment, endline = p.consumeCommentGroup()
+			if p.file.Line(p.pos) != endline {
+				// The next token is on a different line, thus
+				// the last comment group is a line comment.
+				p.lineComment = comment
+			}
+		}
+
+		// consume successor comments, if any
+		endline = -1
+		for p.tok == token.COMMENT {
+			comment, endline = p.consumeCommentGroup()
+		}
+
+		if endline+1 == p.file.Line(p.pos) {
+			// The next token is following on the line immediately after the
+			// comment group, thus the last comment group is a lead comment.
+			p.leadComment = comment
+		}
+	}
+}
+
+func (p *parser) error(pos token.Pos, msg string) {
+	p.Error(p.file.Position(pos), msg)
+}
+
+func (p *parser) errorExpected(pos token.Pos, msg string) {
+	msg = "expected " + msg
+	if pos == p.pos {
+		// the error happened at the current position;
+		// make the error message more specific
+		if p.tok == token.SEMICOLON && p.lit[0] == '\n' {
+			msg += ", found newline"
+		} else {
+			msg += ", found '" + p.tok.String() + "'"
+			if p.tok.IsLiteral() {
+				msg += " " + p.lit
+			}
+		}
+	}
+	p.error(pos, msg)
+}
+
+func (p *parser) expect(tok token.Token) token.Pos {
+	pos := p.pos
+	if p.tok != tok {
+		p.errorExpected(pos, "'"+tok.String()+"'")
+	}
+	p.next() // make progress
+	return pos
+}
+
+func (p *parser) expectSemi() {
+	if p.tok != token.RPAREN && p.tok != token.RBRACE {
+		p.expect(token.SEMICOLON)
+	}
+}
+
+func assert(cond bool, msg string) {
+	if !cond {
+		panic("go/parser internal error: " + msg)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Identifiers
+
+func (p *parser) parseIdent() *ast.Ident {
+	pos := p.pos
+	name := "_"
+	if p.tok == token.IDENT {
+		name = p.lit
+		p.next()
+	} else {
+		p.expect(token.IDENT) // use expect() error handling
+	}
+	return &ast.Ident{pos, name, nil}
+}
+
+func (p *parser) parseIdentList() (list []*ast.Ident) {
+	if p.trace {
+		defer un(trace(p, "IdentList"))
+	}
+
+	list = append(list, p.parseIdent())
+	for p.tok == token.COMMA {
+		p.next()
+		list = append(list, p.parseIdent())
+	}
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Common productions
+
+// If lhs is set, result list elements which are identifiers are not resolved.
+func (p *parser) parseExprList(lhs bool) (list []ast.Expr) {
+	if p.trace {
+		defer un(trace(p, "ExpressionList"))
+	}
+
+	list = append(list, p.parseExpr(lhs))
+	for p.tok == token.COMMA {
+		p.next()
+		list = append(list, p.parseExpr(lhs))
+	}
+
+	return
+}
+
+func (p *parser) parseLhsList() []ast.Expr {
+	list := p.parseExprList(true)
+	switch p.tok {
+	case token.DEFINE:
+		// lhs of a short variable declaration
+		p.shortVarDecl(p.makeIdentList(list))
+	case token.COLON:
+		// lhs of a label declaration or a communication clause of a select
+		// statement (parseLhsList is not called when parsing the case clause
+		// of a switch statement):
+		// - labels are declared by the caller of parseLhsList
+		// - for communication clauses, if there is a stand-alone identifier
+		//   followed by a colon, we have a syntax error; there is no need
+		//   to resolve the identifier in that case
+	default:
+		// identifiers must be declared elsewhere
+		for _, x := range list {
+			p.resolve(x)
+		}
+	}
+	return list
+}
+
+func (p *parser) parseRhsList() []ast.Expr {
+	return p.parseExprList(false)
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+func (p *parser) parseType() ast.Expr {
+	if p.trace {
+		defer un(trace(p, "Type"))
+	}
+
+	typ := p.tryType()
+
+	if typ == nil {
+		pos := p.pos
+		p.errorExpected(pos, "type")
+		p.next() // make progress
+		return &ast.BadExpr{pos, p.pos}
+	}
+
+	return typ
+}
+
+// If the result is an identifier, it is not resolved.
+func (p *parser) parseTypeName() ast.Expr {
+	if p.trace {
+		defer un(trace(p, "TypeName"))
+	}
+
+	ident := p.parseIdent()
+	// don't resolve ident yet - it may be a parameter or field name
+
+	if p.tok == token.PERIOD {
+		// ident is a package name
+		p.next()
+		p.resolve(ident)
+		sel := p.parseIdent()
+		return &ast.SelectorExpr{ident, sel}
+	}
+
+	return ident
+}
+
+func (p *parser) parseArrayType(ellipsisOk bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "ArrayType"))
+	}
+
+	lbrack := p.expect(token.LBRACK)
+	var len ast.Expr
+	if ellipsisOk && p.tok == token.ELLIPSIS {
+		len = &ast.Ellipsis{p.pos, nil}
+		p.next()
+	} else if p.tok != token.RBRACK {
+		len = p.parseRhs()
+	}
+	p.expect(token.RBRACK)
+	elt := p.parseType()
+
+	return &ast.ArrayType{lbrack, len, elt}
+}
+
+func (p *parser) makeIdentList(list []ast.Expr) []*ast.Ident {
+	idents := make([]*ast.Ident, len(list))
+	for i, x := range list {
+		ident, isIdent := x.(*ast.Ident)
+		if !isIdent {
+			pos := x.(ast.Expr).Pos()
+			p.errorExpected(pos, "identifier")
+			ident = &ast.Ident{pos, "_", nil}
+		}
+		idents[i] = ident
+	}
+	return idents
+}
+
+func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
+	if p.trace {
+		defer un(trace(p, "FieldDecl"))
+	}
+
+	doc := p.leadComment
+
+	// fields
+	list, typ := p.parseVarList(false)
+
+	// optional tag
+	var tag *ast.BasicLit
+	if p.tok == token.STRING {
+		tag = &ast.BasicLit{p.pos, p.tok, p.lit}
+		p.next()
+	}
+
+	// analyze case
+	var idents []*ast.Ident
+	if typ != nil {
+		// IdentifierList Type
+		idents = p.makeIdentList(list)
+	} else {
+		// ["*"] TypeName (AnonymousField)
+		typ = list[0] // we always have at least one element
+		p.resolve(typ)
+		if n := len(list); n > 1 || !isTypeName(deref(typ)) {
+			pos := typ.Pos()
+			p.errorExpected(pos, "anonymous field")
+			typ = &ast.BadExpr{pos, list[n-1].End()}
+		}
+	}
+
+	p.expectSemi() // call before accessing p.linecomment
+
+	field := &ast.Field{doc, idents, typ, tag, p.lineComment}
+	p.declare(field, scope, ast.Var, idents...)
+
+	return field
+}
+
+func (p *parser) parseStructType() *ast.StructType {
+	if p.trace {
+		defer un(trace(p, "StructType"))
+	}
+
+	pos := p.expect(token.STRUCT)
+	lbrace := p.expect(token.LBRACE)
+	scope := ast.NewScope(nil) // struct scope
+	var list []*ast.Field
+	for p.tok == token.IDENT || p.tok == token.MUL || p.tok == token.LPAREN {
+		// a field declaration cannot start with a '(' but we accept
+		// it here for more robust parsing and better error messages
+		// (parseFieldDecl will check and complain if necessary)
+		list = append(list, p.parseFieldDecl(scope))
+	}
+	rbrace := p.expect(token.RBRACE)
+
+	// TODO(gri): store struct scope in AST
+	return &ast.StructType{pos, &ast.FieldList{lbrace, list, rbrace}, false}
+}
+
+func (p *parser) parsePointerType() *ast.StarExpr {
+	if p.trace {
+		defer un(trace(p, "PointerType"))
+	}
+
+	star := p.expect(token.MUL)
+	base := p.parseType()
+
+	return &ast.StarExpr{star, base}
+}
+
+func (p *parser) tryVarType(isParam bool) ast.Expr {
+	if isParam && p.tok == token.ELLIPSIS {
+		pos := p.pos
+		p.next()
+		typ := p.tryIdentOrType(isParam) // don't use parseType so we can provide better error message
+		if typ == nil {
+			p.error(pos, "'...' parameter is missing type")
+			typ = &ast.BadExpr{pos, p.pos}
+		}
+		if p.tok != token.RPAREN {
+			p.error(pos, "can use '...' with last parameter type only")
+		}
+		return &ast.Ellipsis{pos, typ}
+	}
+	return p.tryIdentOrType(false)
+}
+
+func (p *parser) parseVarType(isParam bool) ast.Expr {
+	typ := p.tryVarType(isParam)
+	if typ == nil {
+		pos := p.pos
+		p.errorExpected(pos, "type")
+		p.next() // make progress
+		typ = &ast.BadExpr{pos, p.pos}
+	}
+	return typ
+}
+
+func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) {
+	if p.trace {
+		defer un(trace(p, "VarList"))
+	}
+
+	// a list of identifiers looks like a list of type names
+	for {
+		// parseVarType accepts any type (including parenthesized ones)
+		// even though the syntax does not permit them here: we
+		// accept them all for more robust parsing and complain
+		// afterwards
+		list = append(list, p.parseVarType(isParam))
+		if p.tok != token.COMMA {
+			break
+		}
+		p.next()
+	}
+
+	// if we had a list of identifiers, it must be followed by a type
+	typ = p.tryVarType(isParam)
+	if typ != nil {
+		p.resolve(typ)
+	}
+
+	return
+}
+
+func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params []*ast.Field) {
+	if p.trace {
+		defer un(trace(p, "ParameterList"))
+	}
+
+	list, typ := p.parseVarList(ellipsisOk)
+	if typ != nil {
+		// IdentifierList Type
+		idents := p.makeIdentList(list)
+		field := &ast.Field{nil, idents, typ, nil, nil}
+		params = append(params, field)
+		// Go spec: The scope of an identifier denoting a function
+		// parameter or result variable is the function body.
+		p.declare(field, scope, ast.Var, idents...)
+		if p.tok == token.COMMA {
+			p.next()
+		}
+
+		for p.tok != token.RPAREN && p.tok != token.EOF {
+			idents := p.parseIdentList()
+			typ := p.parseVarType(ellipsisOk)
+			field := &ast.Field{nil, idents, typ, nil, nil}
+			params = append(params, field)
+			// Go spec: The scope of an identifier denoting a function
+			// parameter or result variable is the function body.
+			p.declare(field, scope, ast.Var, idents...)
+			if p.tok != token.COMMA {
+				break
+			}
+			p.next()
+		}
+
+	} else {
+		// Type { "," Type } (anonymous parameters)
+		params = make([]*ast.Field, len(list))
+		for i, x := range list {
+			p.resolve(x)
+			params[i] = &ast.Field{Type: x}
+		}
+	}
+
+	return
+}
+
+func (p *parser) parseParameters(scope *ast.Scope, ellipsisOk bool) *ast.FieldList {
+	if p.trace {
+		defer un(trace(p, "Parameters"))
+	}
+
+	var params []*ast.Field
+	lparen := p.expect(token.LPAREN)
+	if p.tok != token.RPAREN {
+		params = p.parseParameterList(scope, ellipsisOk)
+	}
+	rparen := p.expect(token.RPAREN)
+
+	return &ast.FieldList{lparen, params, rparen}
+}
+
+func (p *parser) parseResult(scope *ast.Scope) *ast.FieldList {
+	if p.trace {
+		defer un(trace(p, "Result"))
+	}
+
+	if p.tok == token.LPAREN {
+		return p.parseParameters(scope, false)
+	}
+
+	typ := p.tryType()
+	if typ != nil {
+		list := make([]*ast.Field, 1)
+		list[0] = &ast.Field{Type: typ}
+		return &ast.FieldList{List: list}
+	}
+
+	return nil
+}
+
+func (p *parser) parseSignature(scope *ast.Scope) (params, results *ast.FieldList) {
+	if p.trace {
+		defer un(trace(p, "Signature"))
+	}
+
+	params = p.parseParameters(scope, true)
+	results = p.parseResult(scope)
+
+	return
+}
+
+func (p *parser) parseFuncType() (*ast.FuncType, *ast.Scope) {
+	if p.trace {
+		defer un(trace(p, "FuncType"))
+	}
+
+	pos := p.expect(token.FUNC)
+	scope := ast.NewScope(p.topScope) // function scope
+	params, results := p.parseSignature(scope)
+
+	return &ast.FuncType{pos, params, results}, scope
+}
+
+func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field {
+	if p.trace {
+		defer un(trace(p, "MethodSpec"))
+	}
+
+	doc := p.leadComment
+	var idents []*ast.Ident
+	var typ ast.Expr
+	x := p.parseTypeName()
+	if ident, isIdent := x.(*ast.Ident); isIdent && p.tok == token.LPAREN {
+		// method
+		idents = []*ast.Ident{ident}
+		scope := ast.NewScope(nil) // method scope
+		params, results := p.parseSignature(scope)
+		typ = &ast.FuncType{token.NoPos, params, results}
+	} else {
+		// embedded interface
+		typ = x
+	}
+	p.expectSemi() // call before accessing p.linecomment
+
+	spec := &ast.Field{doc, idents, typ, nil, p.lineComment}
+	p.declare(spec, scope, ast.Fun, idents...)
+
+	return spec
+}
+
+func (p *parser) parseInterfaceType() *ast.InterfaceType {
+	if p.trace {
+		defer un(trace(p, "InterfaceType"))
+	}
+
+	pos := p.expect(token.INTERFACE)
+	lbrace := p.expect(token.LBRACE)
+	scope := ast.NewScope(nil) // interface scope
+	var list []*ast.Field
+	for p.tok == token.IDENT {
+		list = append(list, p.parseMethodSpec(scope))
+	}
+	rbrace := p.expect(token.RBRACE)
+
+	// TODO(gri): store interface scope in AST
+	return &ast.InterfaceType{pos, &ast.FieldList{lbrace, list, rbrace}, false}
+}
+
+func (p *parser) parseMapType() *ast.MapType {
+	if p.trace {
+		defer un(trace(p, "MapType"))
+	}
+
+	pos := p.expect(token.MAP)
+	p.expect(token.LBRACK)
+	key := p.parseType()
+	p.expect(token.RBRACK)
+	value := p.parseType()
+
+	return &ast.MapType{pos, key, value}
+}
+
+func (p *parser) parseChanType() *ast.ChanType {
+	if p.trace {
+		defer un(trace(p, "ChanType"))
+	}
+
+	pos := p.pos
+	dir := ast.SEND | ast.RECV
+	if p.tok == token.CHAN {
+		p.next()
+		if p.tok == token.ARROW {
+			p.next()
+			dir = ast.SEND
+		}
+	} else {
+		p.expect(token.ARROW)
+		p.expect(token.CHAN)
+		dir = ast.RECV
+	}
+	value := p.parseType()
+
+	return &ast.ChanType{pos, dir, value}
+}
+
+// If the result is an identifier, it is not resolved.
+func (p *parser) tryIdentOrType(ellipsisOk bool) ast.Expr {
+	switch p.tok {
+	case token.IDENT:
+		return p.parseTypeName()
+	case token.LBRACK:
+		return p.parseArrayType(ellipsisOk)
+	case token.STRUCT:
+		return p.parseStructType()
+	case token.MUL:
+		return p.parsePointerType()
+	case token.FUNC:
+		typ, _ := p.parseFuncType()
+		return typ
+	case token.INTERFACE:
+		return p.parseInterfaceType()
+	case token.MAP:
+		return p.parseMapType()
+	case token.CHAN, token.ARROW:
+		return p.parseChanType()
+	case token.LPAREN:
+		lparen := p.pos
+		p.next()
+		typ := p.parseType()
+		rparen := p.expect(token.RPAREN)
+		return &ast.ParenExpr{lparen, typ, rparen}
+	}
+
+	// no type found
+	return nil
+}
+
+func (p *parser) tryType() ast.Expr {
+	typ := p.tryIdentOrType(false)
+	if typ != nil {
+		p.resolve(typ)
+	}
+	return typ
+}
+
+// ----------------------------------------------------------------------------
+// Blocks
+
+func (p *parser) parseStmtList() (list []ast.Stmt) {
+	if p.trace {
+		defer un(trace(p, "StatementList"))
+	}
+
+	for p.tok != token.CASE && p.tok != token.DEFAULT && p.tok != token.RBRACE && p.tok != token.EOF {
+		list = append(list, p.parseStmt())
+	}
+
+	return
+}
+
+func (p *parser) parseBody(scope *ast.Scope) *ast.BlockStmt {
+	if p.trace {
+		defer un(trace(p, "Body"))
+	}
+
+	lbrace := p.expect(token.LBRACE)
+	p.topScope = scope // open function scope
+	p.openLabelScope()
+	list := p.parseStmtList()
+	p.closeLabelScope()
+	p.closeScope()
+	rbrace := p.expect(token.RBRACE)
+
+	return &ast.BlockStmt{lbrace, list, rbrace}
+}
+
+func (p *parser) parseBlockStmt() *ast.BlockStmt {
+	if p.trace {
+		defer un(trace(p, "BlockStmt"))
+	}
+
+	lbrace := p.expect(token.LBRACE)
+	p.openScope()
+	list := p.parseStmtList()
+	p.closeScope()
+	rbrace := p.expect(token.RBRACE)
+
+	return &ast.BlockStmt{lbrace, list, rbrace}
+}
+
+// ----------------------------------------------------------------------------
+// Expressions
+
+func (p *parser) parseFuncTypeOrLit() ast.Expr {
+	if p.trace {
+		defer un(trace(p, "FuncTypeOrLit"))
+	}
+
+	typ, scope := p.parseFuncType()
+	if p.tok != token.LBRACE {
+		// function type only
+		return typ
+	}
+
+	p.exprLev++
+	body := p.parseBody(scope)
+	p.exprLev--
+
+	return &ast.FuncLit{typ, body}
+}
+
+// parseOperand may return an expression or a raw type (incl. array
+// types of the form [...]T. Callers must verify the result.
+// If lhs is set and the result is an identifier, it is not resolved.
+//
+func (p *parser) parseOperand(lhs bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "Operand"))
+	}
+
+	switch p.tok {
+	case token.IDENT:
+		x := p.parseIdent()
+		if !lhs {
+			p.resolve(x)
+		}
+		return x
+
+	case token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING:
+		x := &ast.BasicLit{p.pos, p.tok, p.lit}
+		p.next()
+		return x
+
+	case token.LPAREN:
+		lparen := p.pos
+		p.next()
+		p.exprLev++
+		x := p.parseRhs()
+		p.exprLev--
+		rparen := p.expect(token.RPAREN)
+		return &ast.ParenExpr{lparen, x, rparen}
+
+	case token.FUNC:
+		return p.parseFuncTypeOrLit()
+
+	default:
+		if typ := p.tryIdentOrType(true); typ != nil {
+			// could be type for composite literal or conversion
+			_, isIdent := typ.(*ast.Ident)
+			assert(!isIdent, "type cannot be identifier")
+			return typ
+		}
+	}
+
+	pos := p.pos
+	p.errorExpected(pos, "operand")
+	p.next() // make progress
+	return &ast.BadExpr{pos, p.pos}
+}
+
+func (p *parser) parseSelector(x ast.Expr) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "Selector"))
+	}
+
+	sel := p.parseIdent()
+
+	return &ast.SelectorExpr{x, sel}
+}
+
+func (p *parser) parseTypeAssertion(x ast.Expr) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "TypeAssertion"))
+	}
+
+	p.expect(token.LPAREN)
+	var typ ast.Expr
+	if p.tok == token.TYPE {
+		// type switch: typ == nil
+		p.next()
+	} else {
+		typ = p.parseType()
+	}
+	p.expect(token.RPAREN)
+
+	return &ast.TypeAssertExpr{x, typ}
+}
+
+func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "IndexOrSlice"))
+	}
+
+	lbrack := p.expect(token.LBRACK)
+	p.exprLev++
+	var low, high ast.Expr
+	isSlice := false
+	if p.tok != token.COLON {
+		low = p.parseRhs()
+	}
+	if p.tok == token.COLON {
+		isSlice = true
+		p.next()
+		if p.tok != token.RBRACK {
+			high = p.parseRhs()
+		}
+	}
+	p.exprLev--
+	rbrack := p.expect(token.RBRACK)
+
+	if isSlice {
+		return &ast.SliceExpr{x, lbrack, low, high, rbrack}
+	}
+	return &ast.IndexExpr{x, lbrack, low, rbrack}
+}
+
+func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr {
+	if p.trace {
+		defer un(trace(p, "CallOrConversion"))
+	}
+
+	lparen := p.expect(token.LPAREN)
+	p.exprLev++
+	var list []ast.Expr
+	var ellipsis token.Pos
+	for p.tok != token.RPAREN && p.tok != token.EOF && !ellipsis.IsValid() {
+		list = append(list, p.parseRhs())
+		if p.tok == token.ELLIPSIS {
+			ellipsis = p.pos
+			p.next()
+		}
+		if p.tok != token.COMMA {
+			break
+		}
+		p.next()
+	}
+	p.exprLev--
+	rparen := p.expect(token.RPAREN)
+
+	return &ast.CallExpr{fun, lparen, list, ellipsis, rparen}
+}
+
+func (p *parser) parseElement(keyOk bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "Element"))
+	}
+
+	if p.tok == token.LBRACE {
+		return p.parseLiteralValue(nil)
+	}
+
+	x := p.parseExpr(keyOk) // don't resolve if map key
+	if keyOk {
+		if p.tok == token.COLON {
+			colon := p.pos
+			p.next()
+			return &ast.KeyValueExpr{x, colon, p.parseElement(false)}
+		}
+		p.resolve(x) // not a map key
+	}
+
+	return x
+}
+
+func (p *parser) parseElementList() (list []ast.Expr) {
+	if p.trace {
+		defer un(trace(p, "ElementList"))
+	}
+
+	for p.tok != token.RBRACE && p.tok != token.EOF {
+		list = append(list, p.parseElement(true))
+		if p.tok != token.COMMA {
+			break
+		}
+		p.next()
+	}
+
+	return
+}
+
+func (p *parser) parseLiteralValue(typ ast.Expr) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "LiteralValue"))
+	}
+
+	lbrace := p.expect(token.LBRACE)
+	var elts []ast.Expr
+	p.exprLev++
+	if p.tok != token.RBRACE {
+		elts = p.parseElementList()
+	}
+	p.exprLev--
+	rbrace := p.expect(token.RBRACE)
+	return &ast.CompositeLit{typ, lbrace, elts, rbrace}
+}
+
+// checkExpr checks that x is an expression (and not a type).
+func (p *parser) checkExpr(x ast.Expr) ast.Expr {
+	switch t := unparen(x).(type) {
+	case *ast.BadExpr:
+	case *ast.Ident:
+	case *ast.BasicLit:
+	case *ast.FuncLit:
+	case *ast.CompositeLit:
+	case *ast.ParenExpr:
+		panic("unreachable")
+	case *ast.SelectorExpr:
+	case *ast.IndexExpr:
+	case *ast.SliceExpr:
+	case *ast.TypeAssertExpr:
+		if t.Type == nil {
+			// the form X.(type) is only allowed in type switch expressions
+			p.errorExpected(x.Pos(), "expression")
+			x = &ast.BadExpr{x.Pos(), x.End()}
+		}
+	case *ast.CallExpr:
+	case *ast.StarExpr:
+	case *ast.UnaryExpr:
+		if t.Op == token.RANGE {
+			// the range operator is only allowed at the top of a for statement
+			p.errorExpected(x.Pos(), "expression")
+			x = &ast.BadExpr{x.Pos(), x.End()}
+		}
+	case *ast.BinaryExpr:
+	default:
+		// all other nodes are not proper expressions
+		p.errorExpected(x.Pos(), "expression")
+		x = &ast.BadExpr{x.Pos(), x.End()}
+	}
+	return x
+}
+
+// isTypeName returns true iff x is a (qualified) TypeName.
+func isTypeName(x ast.Expr) bool {
+	switch t := x.(type) {
+	case *ast.BadExpr:
+	case *ast.Ident:
+	case *ast.SelectorExpr:
+		_, isIdent := t.X.(*ast.Ident)
+		return isIdent
+	default:
+		return false // all other nodes are not type names
+	}
+	return true
+}
+
+// isLiteralType returns true iff x is a legal composite literal type.
+func isLiteralType(x ast.Expr) bool {
+	switch t := x.(type) {
+	case *ast.BadExpr:
+	case *ast.Ident:
+	case *ast.SelectorExpr:
+		_, isIdent := t.X.(*ast.Ident)
+		return isIdent
+	case *ast.ArrayType:
+	case *ast.StructType:
+	case *ast.MapType:
+	default:
+		return false // all other nodes are not legal composite literal types
+	}
+	return true
+}
+
+// If x is of the form *T, deref returns T, otherwise it returns x.
+func deref(x ast.Expr) ast.Expr {
+	if p, isPtr := x.(*ast.StarExpr); isPtr {
+		x = p.X
+	}
+	return x
+}
+
+// If x is of the form (T), unparen returns unparen(T), otherwise it returns x.
+func unparen(x ast.Expr) ast.Expr {
+	if p, isParen := x.(*ast.ParenExpr); isParen {
+		x = unparen(p.X)
+	}
+	return x
+}
+
+// checkExprOrType checks that x is an expression or a type
+// (and not a raw type such as [...]T).
+//
+func (p *parser) checkExprOrType(x ast.Expr) ast.Expr {
+	switch t := unparen(x).(type) {
+	case *ast.ParenExpr:
+		panic("unreachable")
+	case *ast.UnaryExpr:
+		if t.Op == token.RANGE {
+			// the range operator is only allowed at the top of a for statement
+			p.errorExpected(x.Pos(), "expression")
+			x = &ast.BadExpr{x.Pos(), x.End()}
+		}
+	case *ast.ArrayType:
+		if len, isEllipsis := t.Len.(*ast.Ellipsis); isEllipsis {
+			p.error(len.Pos(), "expected array length, found '...'")
+			x = &ast.BadExpr{x.Pos(), x.End()}
+		}
+	}
+
+	// all other nodes are expressions or types
+	return x
+}
+
+// If lhs is set and the result is an identifier, it is not resolved.
+func (p *parser) parsePrimaryExpr(lhs bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "PrimaryExpr"))
+	}
+
+	x := p.parseOperand(lhs)
+L:
+	for {
+		switch p.tok {
+		case token.PERIOD:
+			p.next()
+			if lhs {
+				p.resolve(x)
+			}
+			switch p.tok {
+			case token.IDENT:
+				x = p.parseSelector(p.checkExpr(x))
+			case token.LPAREN:
+				x = p.parseTypeAssertion(p.checkExpr(x))
+			default:
+				pos := p.pos
+				p.next() // make progress
+				p.errorExpected(pos, "selector or type assertion")
+				x = &ast.BadExpr{pos, p.pos}
+			}
+		case token.LBRACK:
+			if lhs {
+				p.resolve(x)
+			}
+			x = p.parseIndexOrSlice(p.checkExpr(x))
+		case token.LPAREN:
+			if lhs {
+				p.resolve(x)
+			}
+			x = p.parseCallOrConversion(p.checkExprOrType(x))
+		case token.LBRACE:
+			if isLiteralType(x) && (p.exprLev >= 0 || !isTypeName(x)) {
+				if lhs {
+					p.resolve(x)
+				}
+				x = p.parseLiteralValue(x)
+			} else {
+				break L
+			}
+		default:
+			break L
+		}
+		lhs = false // no need to try to resolve again
+	}
+
+	return x
+}
+
+// If lhs is set and the result is an identifier, it is not resolved.
+func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "UnaryExpr"))
+	}
+
+	switch p.tok {
+	case token.ADD, token.SUB, token.NOT, token.XOR, token.AND, token.RANGE:
+		pos, op := p.pos, p.tok
+		p.next()
+		x := p.parseUnaryExpr(false)
+		return &ast.UnaryExpr{pos, op, p.checkExpr(x)}
+
+	case token.ARROW:
+		// channel type or receive expression
+		pos := p.pos
+		p.next()
+		if p.tok == token.CHAN {
+			p.next()
+			value := p.parseType()
+			return &ast.ChanType{pos, ast.RECV, value}
+		}
+
+		x := p.parseUnaryExpr(false)
+		return &ast.UnaryExpr{pos, token.ARROW, p.checkExpr(x)}
+
+	case token.MUL:
+		// pointer type or unary "*" expression
+		pos := p.pos
+		p.next()
+		x := p.parseUnaryExpr(false)
+		return &ast.StarExpr{pos, p.checkExprOrType(x)}
+	}
+
+	return p.parsePrimaryExpr(lhs)
+}
+
+// If lhs is set and the result is an identifier, it is not resolved.
+func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "BinaryExpr"))
+	}
+
+	x := p.parseUnaryExpr(lhs)
+	for prec := p.tok.Precedence(); prec >= prec1; prec-- {
+		for p.tok.Precedence() == prec {
+			pos, op := p.pos, p.tok
+			p.next()
+			if lhs {
+				p.resolve(x)
+				lhs = false
+			}
+			y := p.parseBinaryExpr(false, prec+1)
+			x = &ast.BinaryExpr{p.checkExpr(x), pos, op, p.checkExpr(y)}
+		}
+	}
+
+	return x
+}
+
+// If lhs is set and the result is an identifier, it is not resolved.
+// TODO(gri): parseExpr may return a type or even a raw type ([..]int) -
+//            should reject when a type/raw type is obviously not allowed
+func (p *parser) parseExpr(lhs bool) ast.Expr {
+	if p.trace {
+		defer un(trace(p, "Expression"))
+	}
+
+	return p.parseBinaryExpr(lhs, token.LowestPrec+1)
+}
+
+func (p *parser) parseRhs() ast.Expr {
+	return p.parseExpr(false)
+}
+
+// ----------------------------------------------------------------------------
+// Statements
+
+func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt {
+	if p.trace {
+		defer un(trace(p, "SimpleStmt"))
+	}
+
+	x := p.parseLhsList()
+
+	switch p.tok {
+	case
+		token.DEFINE, token.ASSIGN, token.ADD_ASSIGN,
+		token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN,
+		token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN,
+		token.XOR_ASSIGN, token.SHL_ASSIGN, token.SHR_ASSIGN, token.AND_NOT_ASSIGN:
+		// assignment statement
+		pos, tok := p.pos, p.tok
+		p.next()
+		y := p.parseRhsList()
+		return &ast.AssignStmt{x, pos, tok, y}
+	}
+
+	if len(x) > 1 {
+		p.errorExpected(x[0].Pos(), "1 expression")
+		// continue with first expression
+	}
+
+	switch p.tok {
+	case token.COLON:
+		// labeled statement
+		colon := p.pos
+		p.next()
+		if label, isIdent := x[0].(*ast.Ident); labelOk && isIdent {
+			// Go spec: The scope of a label is the body of the function
+			// in which it is declared and excludes the body of any nested
+			// function.
+			stmt := &ast.LabeledStmt{label, colon, p.parseStmt()}
+			p.declare(stmt, p.labelScope, ast.Lbl, label)
+			return stmt
+		}
+		p.error(x[0].Pos(), "illegal label declaration")
+		return &ast.BadStmt{x[0].Pos(), colon + 1}
+
+	case token.ARROW:
+		// send statement
+		arrow := p.pos
+		p.next() // consume "<-"
+		y := p.parseRhs()
+		return &ast.SendStmt{x[0], arrow, y}
+
+	case token.INC, token.DEC:
+		// increment or decrement
+		s := &ast.IncDecStmt{x[0], p.pos, p.tok}
+		p.next() // consume "++" or "--"
+		return s
+	}
+
+	// expression
+	return &ast.ExprStmt{x[0]}
+}
+
+func (p *parser) parseCallExpr() *ast.CallExpr {
+	x := p.parseRhs()
+	if call, isCall := x.(*ast.CallExpr); isCall {
+		return call
+	}
+	p.errorExpected(x.Pos(), "function/method call")
+	return nil
+}
+
+func (p *parser) parseGoStmt() ast.Stmt {
+	if p.trace {
+		defer un(trace(p, "GoStmt"))
+	}
+
+	pos := p.expect(token.GO)
+	call := p.parseCallExpr()
+	p.expectSemi()
+	if call == nil {
+		return &ast.BadStmt{pos, pos + 2} // len("go")
+	}
+
+	return &ast.GoStmt{pos, call}
+}
+
+func (p *parser) parseDeferStmt() ast.Stmt {
+	if p.trace {
+		defer un(trace(p, "DeferStmt"))
+	}
+
+	pos := p.expect(token.DEFER)
+	call := p.parseCallExpr()
+	p.expectSemi()
+	if call == nil {
+		return &ast.BadStmt{pos, pos + 5} // len("defer")
+	}
+
+	return &ast.DeferStmt{pos, call}
+}
+
+func (p *parser) parseReturnStmt() *ast.ReturnStmt {
+	if p.trace {
+		defer un(trace(p, "ReturnStmt"))
+	}
+
+	pos := p.pos
+	p.expect(token.RETURN)
+	var x []ast.Expr
+	if p.tok != token.SEMICOLON && p.tok != token.RBRACE {
+		x = p.parseRhsList()
+	}
+	p.expectSemi()
+
+	return &ast.ReturnStmt{pos, x}
+}
+
+func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt {
+	if p.trace {
+		defer un(trace(p, "BranchStmt"))
+	}
+
+	pos := p.expect(tok)
+	var label *ast.Ident
+	if tok != token.FALLTHROUGH && p.tok == token.IDENT {
+		label = p.parseIdent()
+		// add to list of unresolved targets
+		n := len(p.targetStack) - 1
+		p.targetStack[n] = append(p.targetStack[n], label)
+	}
+	p.expectSemi()
+
+	return &ast.BranchStmt{pos, tok, label}
+}
+
+func (p *parser) makeExpr(s ast.Stmt) ast.Expr {
+	if s == nil {
+		return nil
+	}
+	if es, isExpr := s.(*ast.ExprStmt); isExpr {
+		return p.checkExpr(es.X)
+	}
+	p.error(s.Pos(), "expected condition, found simple statement")
+	return &ast.BadExpr{s.Pos(), s.End()}
+}
+
+func (p *parser) parseIfStmt() *ast.IfStmt {
+	if p.trace {
+		defer un(trace(p, "IfStmt"))
+	}
+
+	pos := p.expect(token.IF)
+	p.openScope()
+	defer p.closeScope()
+
+	var s ast.Stmt
+	var x ast.Expr
+	{
+		prevLev := p.exprLev
+		p.exprLev = -1
+		if p.tok == token.SEMICOLON {
+			p.next()
+			x = p.parseRhs()
+		} else {
+			s = p.parseSimpleStmt(false)
+			if p.tok == token.SEMICOLON {
+				p.next()
+				x = p.parseRhs()
+			} else {
+				x = p.makeExpr(s)
+				s = nil
+			}
+		}
+		p.exprLev = prevLev
+	}
+
+	body := p.parseBlockStmt()
+	var else_ ast.Stmt
+	if p.tok == token.ELSE {
+		p.next()
+		else_ = p.parseStmt()
+	} else {
+		p.expectSemi()
+	}
+
+	return &ast.IfStmt{pos, s, x, body, else_}
+}
+
+func (p *parser) parseTypeList() (list []ast.Expr) {
+	if p.trace {
+		defer un(trace(p, "TypeList"))
+	}
+
+	list = append(list, p.parseType())
+	for p.tok == token.COMMA {
+		p.next()
+		list = append(list, p.parseType())
+	}
+
+	return
+}
+
+func (p *parser) parseCaseClause(exprSwitch bool) *ast.CaseClause {
+	if p.trace {
+		defer un(trace(p, "CaseClause"))
+	}
+
+	pos := p.pos
+	var list []ast.Expr
+	if p.tok == token.CASE {
+		p.next()
+		if exprSwitch {
+			list = p.parseRhsList()
+		} else {
+			list = p.parseTypeList()
+		}
+	} else {
+		p.expect(token.DEFAULT)
+	}
+
+	colon := p.expect(token.COLON)
+	p.openScope()
+	body := p.parseStmtList()
+	p.closeScope()
+
+	return &ast.CaseClause{pos, list, colon, body}
+}
+
+func isExprSwitch(s ast.Stmt) bool {
+	if s == nil {
+		return true
+	}
+	if e, ok := s.(*ast.ExprStmt); ok {
+		if a, ok := e.X.(*ast.TypeAssertExpr); ok {
+			return a.Type != nil // regular type assertion
+		}
+		return true
+	}
+	return false
+}
+
+func (p *parser) parseSwitchStmt() ast.Stmt {
+	if p.trace {
+		defer un(trace(p, "SwitchStmt"))
+	}
+
+	pos := p.expect(token.SWITCH)
+	p.openScope()
+	defer p.closeScope()
+
+	var s1, s2 ast.Stmt
+	if p.tok != token.LBRACE {
+		prevLev := p.exprLev
+		p.exprLev = -1
+		if p.tok != token.SEMICOLON {
+			s2 = p.parseSimpleStmt(false)
+		}
+		if p.tok == token.SEMICOLON {
+			p.next()
+			s1 = s2
+			s2 = nil
+			if p.tok != token.LBRACE {
+				s2 = p.parseSimpleStmt(false)
+			}
+		}
+		p.exprLev = prevLev
+	}
+
+	exprSwitch := isExprSwitch(s2)
+	lbrace := p.expect(token.LBRACE)
+	var list []ast.Stmt
+	for p.tok == token.CASE || p.tok == token.DEFAULT {
+		list = append(list, p.parseCaseClause(exprSwitch))
+	}
+	rbrace := p.expect(token.RBRACE)
+	p.expectSemi()
+	body := &ast.BlockStmt{lbrace, list, rbrace}
+
+	if exprSwitch {
+		return &ast.SwitchStmt{pos, s1, p.makeExpr(s2), body}
+	}
+	// type switch
+	// TODO(gri): do all the checks!
+	return &ast.TypeSwitchStmt{pos, s1, s2, body}
+}
+
+func (p *parser) parseCommClause() *ast.CommClause {
+	if p.trace {
+		defer un(trace(p, "CommClause"))
+	}
+
+	p.openScope()
+	pos := p.pos
+	var comm ast.Stmt
+	if p.tok == token.CASE {
+		p.next()
+		lhs := p.parseLhsList()
+		if p.tok == token.ARROW {
+			// SendStmt
+			if len(lhs) > 1 {
+				p.errorExpected(lhs[0].Pos(), "1 expression")
+				// continue with first expression
+			}
+			arrow := p.pos
+			p.next()
+			rhs := p.parseRhs()
+			comm = &ast.SendStmt{lhs[0], arrow, rhs}
+		} else {
+			// RecvStmt
+			pos := p.pos
+			tok := p.tok
+			var rhs ast.Expr
+			if tok == token.ASSIGN || tok == token.DEFINE {
+				// RecvStmt with assignment
+				if len(lhs) > 2 {
+					p.errorExpected(lhs[0].Pos(), "1 or 2 expressions")
+					// continue with first two expressions
+					lhs = lhs[0:2]
+				}
+				p.next()
+				rhs = p.parseRhs()
+			} else {
+				// rhs must be single receive operation
+				if len(lhs) > 1 {
+					p.errorExpected(lhs[0].Pos(), "1 expression")
+					// continue with first expression
+				}
+				rhs = lhs[0]
+				lhs = nil // there is no lhs
+			}
+			if x, isUnary := rhs.(*ast.UnaryExpr); !isUnary || x.Op != token.ARROW {
+				p.errorExpected(rhs.Pos(), "send or receive operation")
+				rhs = &ast.BadExpr{rhs.Pos(), rhs.End()}
+			}
+			if lhs != nil {
+				comm = &ast.AssignStmt{lhs, pos, tok, []ast.Expr{rhs}}
+			} else {
+				comm = &ast.ExprStmt{rhs}
+			}
+		}
+	} else {
+		p.expect(token.DEFAULT)
+	}
+
+	colon := p.expect(token.COLON)
+	body := p.parseStmtList()
+	p.closeScope()
+
+	return &ast.CommClause{pos, comm, colon, body}
+}
+
+func (p *parser) parseSelectStmt() *ast.SelectStmt {
+	if p.trace {
+		defer un(trace(p, "SelectStmt"))
+	}
+
+	pos := p.expect(token.SELECT)
+	lbrace := p.expect(token.LBRACE)
+	var list []ast.Stmt
+	for p.tok == token.CASE || p.tok == token.DEFAULT {
+		list = append(list, p.parseCommClause())
+	}
+	rbrace := p.expect(token.RBRACE)
+	p.expectSemi()
+	body := &ast.BlockStmt{lbrace, list, rbrace}
+
+	return &ast.SelectStmt{pos, body}
+}
+
+func (p *parser) parseForStmt() ast.Stmt {
+	if p.trace {
+		defer un(trace(p, "ForStmt"))
+	}
+
+	pos := p.expect(token.FOR)
+	p.openScope()
+	defer p.closeScope()
+
+	var s1, s2, s3 ast.Stmt
+	if p.tok != token.LBRACE {
+		prevLev := p.exprLev
+		p.exprLev = -1
+		if p.tok != token.SEMICOLON {
+			s2 = p.parseSimpleStmt(false)
+		}
+		if p.tok == token.SEMICOLON {
+			p.next()
+			s1 = s2
+			s2 = nil
+			if p.tok != token.SEMICOLON {
+				s2 = p.parseSimpleStmt(false)
+			}
+			p.expectSemi()
+			if p.tok != token.LBRACE {
+				s3 = p.parseSimpleStmt(false)
+			}
+		}
+		p.exprLev = prevLev
+	}
+
+	body := p.parseBlockStmt()
+	p.expectSemi()
+
+	if as, isAssign := s2.(*ast.AssignStmt); isAssign {
+		// possibly a for statement with a range clause; check assignment operator
+		if as.Tok != token.ASSIGN && as.Tok != token.DEFINE {
+			p.errorExpected(as.TokPos, "'=' or ':='")
+			return &ast.BadStmt{pos, body.End()}
+		}
+		// check lhs
+		var key, value ast.Expr
+		switch len(as.Lhs) {
+		case 2:
+			key, value = as.Lhs[0], as.Lhs[1]
+		case 1:
+			key = as.Lhs[0]
+		default:
+			p.errorExpected(as.Lhs[0].Pos(), "1 or 2 expressions")
+			return &ast.BadStmt{pos, body.End()}
+		}
+		// check rhs
+		if len(as.Rhs) != 1 {
+			p.errorExpected(as.Rhs[0].Pos(), "1 expression")
+			return &ast.BadStmt{pos, body.End()}
+		}
+		if rhs, isUnary := as.Rhs[0].(*ast.UnaryExpr); isUnary && rhs.Op == token.RANGE {
+			// rhs is range expression
+			// (any short variable declaration was handled by parseSimpleStat above)
+			return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, rhs.X, body}
+		}
+		p.errorExpected(s2.Pos(), "range clause")
+		return &ast.BadStmt{pos, body.End()}
+	}
+
+	// regular for statement
+	return &ast.ForStmt{pos, s1, p.makeExpr(s2), s3, body}
+}
+
+func (p *parser) parseStmt() (s ast.Stmt) {
+	if p.trace {
+		defer un(trace(p, "Statement"))
+	}
+
+	switch p.tok {
+	case token.CONST, token.TYPE, token.VAR:
+		s = &ast.DeclStmt{p.parseDecl()}
+	case
+		// tokens that may start a top-level expression
+		token.IDENT, token.INT, token.FLOAT, token.CHAR, token.STRING, token.FUNC, token.LPAREN, // operand
+		token.LBRACK, token.STRUCT, // composite type
+		token.MUL, token.AND, token.ARROW, token.ADD, token.SUB, token.XOR: // unary operators
+		s = p.parseSimpleStmt(true)
+		// because of the required look-ahead, labeled statements are
+		// parsed by parseSimpleStmt - don't expect a semicolon after
+		// them
+		if _, isLabeledStmt := s.(*ast.LabeledStmt); !isLabeledStmt {
+			p.expectSemi()
+		}
+	case token.GO:
+		s = p.parseGoStmt()
+	case token.DEFER:
+		s = p.parseDeferStmt()
+	case token.RETURN:
+		s = p.parseReturnStmt()
+	case token.BREAK, token.CONTINUE, token.GOTO, token.FALLTHROUGH:
+		s = p.parseBranchStmt(p.tok)
+	case token.LBRACE:
+		s = p.parseBlockStmt()
+		p.expectSemi()
+	case token.IF:
+		s = p.parseIfStmt()
+	case token.SWITCH:
+		s = p.parseSwitchStmt()
+	case token.SELECT:
+		s = p.parseSelectStmt()
+	case token.FOR:
+		s = p.parseForStmt()
+	case token.SEMICOLON:
+		s = &ast.EmptyStmt{p.pos}
+		p.next()
+	case token.RBRACE:
+		// a semicolon may be omitted before a closing "}"
+		s = &ast.EmptyStmt{p.pos}
+	default:
+		// no statement found
+		pos := p.pos
+		p.errorExpected(pos, "statement")
+		p.next() // make progress
+		s = &ast.BadStmt{pos, p.pos}
+	}
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+type parseSpecFunction func(p *parser, doc *ast.CommentGroup, iota int) ast.Spec
+
+func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
+	if p.trace {
+		defer un(trace(p, "ImportSpec"))
+	}
+
+	var ident *ast.Ident
+	switch p.tok {
+	case token.PERIOD:
+		ident = &ast.Ident{p.pos, ".", nil}
+		p.next()
+	case token.IDENT:
+		ident = p.parseIdent()
+	}
+
+	var path *ast.BasicLit
+	if p.tok == token.STRING {
+		path = &ast.BasicLit{p.pos, p.tok, p.lit}
+		p.next()
+	} else {
+		p.expect(token.STRING) // use expect() error handling
+	}
+	p.expectSemi() // call before accessing p.linecomment
+
+	// collect imports
+	spec := &ast.ImportSpec{doc, ident, path, p.lineComment}
+	p.imports = append(p.imports, spec)
+
+	return spec
+}
+
+func parseConstSpec(p *parser, doc *ast.CommentGroup, iota int) ast.Spec {
+	if p.trace {
+		defer un(trace(p, "ConstSpec"))
+	}
+
+	idents := p.parseIdentList()
+	typ := p.tryType()
+	var values []ast.Expr
+	if typ != nil || p.tok == token.ASSIGN || iota == 0 {
+		p.expect(token.ASSIGN)
+		values = p.parseRhsList()
+	}
+	p.expectSemi() // call before accessing p.linecomment
+
+	// Go spec: The scope of a constant or variable identifier declared inside
+	// a function begins at the end of the ConstSpec or VarSpec and ends at
+	// the end of the innermost containing block.
+	// (Global identifiers are resolved in a separate phase after parsing.)
+	spec := &ast.ValueSpec{doc, idents, typ, values, p.lineComment}
+	p.declare(spec, p.topScope, ast.Con, idents...)
+
+	return spec
+}
+
+func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
+	if p.trace {
+		defer un(trace(p, "TypeSpec"))
+	}
+
+	ident := p.parseIdent()
+
+	// Go spec: The scope of a type identifier declared inside a function begins
+	// at the identifier in the TypeSpec and ends at the end of the innermost
+	// containing block.
+	// (Global identifiers are resolved in a separate phase after parsing.)
+	spec := &ast.TypeSpec{doc, ident, nil, nil}
+	p.declare(spec, p.topScope, ast.Typ, ident)
+
+	spec.Type = p.parseType()
+	p.expectSemi() // call before accessing p.linecomment
+	spec.Comment = p.lineComment
+
+	return spec
+}
+
+func parseVarSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
+	if p.trace {
+		defer un(trace(p, "VarSpec"))
+	}
+
+	idents := p.parseIdentList()
+	typ := p.tryType()
+	var values []ast.Expr
+	if typ == nil || p.tok == token.ASSIGN {
+		p.expect(token.ASSIGN)
+		values = p.parseRhsList()
+	}
+	p.expectSemi() // call before accessing p.linecomment
+
+	// Go spec: The scope of a constant or variable identifier declared inside
+	// a function begins at the end of the ConstSpec or VarSpec and ends at
+	// the end of the innermost containing block.
+	// (Global identifiers are resolved in a separate phase after parsing.)
+	spec := &ast.ValueSpec{doc, idents, typ, values, p.lineComment}
+	p.declare(spec, p.topScope, ast.Var, idents...)
+
+	return spec
+}
+
+func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl {
+	if p.trace {
+		defer un(trace(p, "GenDecl("+keyword.String()+")"))
+	}
+
+	doc := p.leadComment
+	pos := p.expect(keyword)
+	var lparen, rparen token.Pos
+	var list []ast.Spec
+	if p.tok == token.LPAREN {
+		lparen = p.pos
+		p.next()
+		for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ {
+			list = append(list, f(p, p.leadComment, iota))
+		}
+		rparen = p.expect(token.RPAREN)
+		p.expectSemi()
+	} else {
+		list = append(list, f(p, nil, 0))
+	}
+
+	return &ast.GenDecl{doc, pos, keyword, lparen, list, rparen}
+}
+
+func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
+	if p.trace {
+		defer un(trace(p, "Receiver"))
+	}
+
+	pos := p.pos
+	par := p.parseParameters(scope, false)
+
+	// must have exactly one receiver
+	if par.NumFields() != 1 {
+		p.errorExpected(pos, "exactly one receiver")
+		// TODO determine a better range for BadExpr below
+		par.List = []*ast.Field{{Type: &ast.BadExpr{pos, pos}}}
+		return par
+	}
+
+	// recv type must be of the form ["*"] identifier
+	recv := par.List[0]
+	base := deref(recv.Type)
+	if _, isIdent := base.(*ast.Ident); !isIdent {
+		p.errorExpected(base.Pos(), "(unqualified) identifier")
+		par.List = []*ast.Field{{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
+	}
+
+	return par
+}
+
+func (p *parser) parseFuncDecl() *ast.FuncDecl {
+	if p.trace {
+		defer un(trace(p, "FunctionDecl"))
+	}
+
+	doc := p.leadComment
+	pos := p.expect(token.FUNC)
+	scope := ast.NewScope(p.topScope) // function scope
+
+	var recv *ast.FieldList
+	if p.tok == token.LPAREN {
+		recv = p.parseReceiver(scope)
+	}
+
+	ident := p.parseIdent()
+
+	params, results := p.parseSignature(scope)
+
+	var body *ast.BlockStmt
+	if p.tok == token.LBRACE {
+		body = p.parseBody(scope)
+	}
+	p.expectSemi()
+
+	decl := &ast.FuncDecl{doc, recv, ident, &ast.FuncType{pos, params, results}, body}
+	if recv == nil {
+		// Go spec: The scope of an identifier denoting a constant, type,
+		// variable, or function (but not method) declared at top level
+		// (outside any function) is the package block.
+		//
+		// init() functions cannot be referred to and there may
+		// be more than one - don't put them in the pkgScope
+		if ident.Name != "init" {
+			p.declare(decl, p.pkgScope, ast.Fun, ident)
+		}
+	}
+
+	return decl
+}
+
+func (p *parser) parseDecl() ast.Decl {
+	if p.trace {
+		defer un(trace(p, "Declaration"))
+	}
+
+	var f parseSpecFunction
+	switch p.tok {
+	case token.CONST:
+		f = parseConstSpec
+
+	case token.TYPE:
+		f = parseTypeSpec
+
+	case token.VAR:
+		f = parseVarSpec
+
+	case token.FUNC:
+		return p.parseFuncDecl()
+
+	default:
+		pos := p.pos
+		p.errorExpected(pos, "declaration")
+		p.next() // make progress
+		decl := &ast.BadDecl{pos, p.pos}
+		return decl
+	}
+
+	return p.parseGenDecl(p.tok, f)
+}
+
+func (p *parser) parseDeclList() (list []ast.Decl) {
+	if p.trace {
+		defer un(trace(p, "DeclList"))
+	}
+
+	for p.tok != token.EOF {
+		list = append(list, p.parseDecl())
+	}
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Source files
+
+func (p *parser) parseFile() *ast.File {
+	if p.trace {
+		defer un(trace(p, "File"))
+	}
+
+	// package clause
+	doc := p.leadComment
+	pos := p.expect(token.PACKAGE)
+	// Go spec: The package clause is not a declaration;
+	// the package name does not appear in any scope.
+	ident := p.parseIdent()
+	if ident.Name == "_" {
+		p.error(p.pos, "invalid package name _")
+	}
+	p.expectSemi()
+
+	var decls []ast.Decl
+
+	// Don't bother parsing the rest if we had errors already.
+	// Likely not a Go source file at all.
+
+	if p.ErrorCount() == 0 && p.mode&PackageClauseOnly == 0 {
+		// import decls
+		for p.tok == token.IMPORT {
+			decls = append(decls, p.parseGenDecl(token.IMPORT, parseImportSpec))
+		}
+
+		if p.mode&ImportsOnly == 0 {
+			// rest of package body
+			for p.tok != token.EOF {
+				decls = append(decls, p.parseDecl())
+			}
+		}
+	}
+
+	assert(p.topScope == p.pkgScope, "imbalanced scopes")
+
+	// resolve global identifiers within the same file
+	i := 0
+	for _, ident := range p.unresolved {
+		// i <= index for current ident
+		assert(ident.Obj == unresolved, "object already resolved")
+		ident.Obj = p.pkgScope.Lookup(ident.Name) // also removes unresolved sentinel
+		if ident.Obj == nil {
+			p.unresolved[i] = ident
+			i++
+		}
+	}
+
+	// TODO(gri): store p.imports in AST
+	return &ast.File{doc, pos, ident, decls, p.pkgScope, p.imports, p.unresolved[0:i], p.comments}
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/slow.golden b/third_party/gofrontend/libgo/go/go/printer/testdata/slow.golden
new file mode 100644
index 0000000..43a15cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/slow.golden
@@ -0,0 +1,85 @@
+// 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.
+
+package deepequal_test
+
+import (
+	"testing"
+	"google3/spam/archer/frontend/deepequal"
+)
+
+func TestTwoNilValues(t *testing.T) {
+	if err := deepequal.Check(nil, nil); err != nil {
+		t.Errorf("expected nil, saw %v", err)
+	}
+}
+
+type Foo struct {
+	bar	*Bar
+	bang	*Bar
+}
+
+type Bar struct {
+	baz	*Baz
+	foo	[]*Foo
+}
+
+type Baz struct {
+	entries		map[int]interface{}
+	whatever	string
+}
+
+func newFoo() *Foo {
+	return &Foo{bar: &Bar{baz: &Baz{
+		entries: map[int]interface{}{
+			42:	&Foo{},
+			21:	&Bar{},
+			11:	&Baz{whatever: "it's just a test"}}}},
+		bang: &Bar{foo: []*Foo{
+			&Foo{bar: &Bar{baz: &Baz{
+				entries: map[int]interface{}{
+					43:	&Foo{},
+					22:	&Bar{},
+					13:	&Baz{whatever: "this is nuts"}}}},
+				bang: &Bar{foo: []*Foo{
+					&Foo{bar: &Bar{baz: &Baz{
+						entries: map[int]interface{}{
+							61:	&Foo{},
+							71:	&Bar{},
+							11:	&Baz{whatever: "no, it's Go"}}}},
+						bang: &Bar{foo: []*Foo{
+							&Foo{bar: &Bar{baz: &Baz{
+								entries: map[int]interface{}{
+									0:	&Foo{},
+									-2:	&Bar{},
+									-11:	&Baz{whatever: "we need to go deeper"}}}},
+								bang: &Bar{foo: []*Foo{
+									&Foo{bar: &Bar{baz: &Baz{
+										entries: map[int]interface{}{
+											-2:	&Foo{},
+											-5:	&Bar{},
+											-7:	&Baz{whatever: "are you serious?"}}}},
+										bang:	&Bar{foo: []*Foo{}}},
+									&Foo{bar: &Bar{baz: &Baz{
+										entries: map[int]interface{}{
+											-100:	&Foo{},
+											50:	&Bar{},
+											20:	&Baz{whatever: "na, not really ..."}}}},
+										bang:	&Bar{foo: []*Foo{}}}}}}}}},
+					&Foo{bar: &Bar{baz: &Baz{
+						entries: map[int]interface{}{
+							2:	&Foo{},
+							1:	&Bar{},
+							-1:	&Baz{whatever: "... it's just a test."}}}},
+						bang:	&Bar{foo: []*Foo{}}}}}}}}}
+}
+
+func TestElaborate(t *testing.T) {
+	a := newFoo()
+	b := newFoo()
+
+	if err := deepequal.Check(a, b); err != nil {
+		t.Errorf("expected nil, saw %v", err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/slow.input b/third_party/gofrontend/libgo/go/go/printer/testdata/slow.input
new file mode 100644
index 0000000..0e5a23d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/slow.input
@@ -0,0 +1,85 @@
+// 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.
+
+package deepequal_test
+
+import (
+        "testing"
+        "google3/spam/archer/frontend/deepequal"
+)
+
+func TestTwoNilValues(t *testing.T) {
+        if err := deepequal.Check(nil, nil); err != nil {
+                t.Errorf("expected nil, saw %v", err)
+        }
+}
+
+type Foo struct {
+        bar *Bar
+        bang *Bar
+}
+
+type Bar struct {
+        baz *Baz
+        foo []*Foo
+}
+
+type Baz struct {
+        entries  map[int]interface{}
+        whatever string
+}
+
+func newFoo() (*Foo) {
+return &Foo{bar: &Bar{ baz: &Baz{
+entries: map[int]interface{}{
+42: &Foo{},
+21: &Bar{},
+11: &Baz{ whatever: "it's just a test" }}}},
+        bang: &Bar{foo: []*Foo{
+&Foo{bar: &Bar{ baz: &Baz{
+entries: map[int]interface{}{
+43: &Foo{},
+22: &Bar{},
+13: &Baz{ whatever: "this is nuts" }}}},
+        bang: &Bar{foo: []*Foo{
+&Foo{bar: &Bar{ baz: &Baz{
+entries: map[int]interface{}{
+61: &Foo{},
+71: &Bar{},
+11: &Baz{ whatever: "no, it's Go" }}}},
+        bang: &Bar{foo: []*Foo{
+&Foo{bar: &Bar{ baz: &Baz{
+entries: map[int]interface{}{
+0: &Foo{},
+-2: &Bar{},
+-11: &Baz{ whatever: "we need to go deeper" }}}},
+        bang: &Bar{foo: []*Foo{
+&Foo{bar: &Bar{ baz: &Baz{
+entries: map[int]interface{}{
+-2: &Foo{},
+-5: &Bar{},
+-7: &Baz{ whatever: "are you serious?" }}}},
+        bang: &Bar{foo: []*Foo{}}},
+&Foo{bar: &Bar{ baz: &Baz{
+entries: map[int]interface{}{
+-100: &Foo{},
+50: &Bar{},
+20: &Baz{ whatever: "na, not really ..." }}}},
+        bang: &Bar{foo: []*Foo{}}}}}}}}},
+&Foo{bar: &Bar{ baz: &Baz{
+entries: map[int]interface{}{
+2: &Foo{},
+1: &Bar{},
+-1: &Baz{ whatever: "... it's just a test." }}}},
+        bang: &Bar{foo: []*Foo{}}}}}}}}}
+}
+
+func TestElaborate(t *testing.T) {
+        a := newFoo()
+        b := newFoo()
+
+        if err := deepequal.Check(a, b); err != nil {
+                t.Errorf("expected nil, saw %v", err)
+        }
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/statements.golden b/third_party/gofrontend/libgo/go/go/printer/testdata/statements.golden
new file mode 100644
index 0000000..3b298f9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/statements.golden
@@ -0,0 +1,635 @@
+// 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 statements
+
+var expr bool
+
+func use(x interface{})	{}
+
+// Formatting of multi-line return statements.
+func _f() {
+	return
+	return x, y, z
+	return T{}
+	return T{1, 2, 3},
+		x, y, z
+	return T{1, 2, 3},
+		x, y,
+		z
+	return T{1,
+		2,
+		3}
+	return T{1,
+		2,
+		3,
+	}
+	return T{
+		1,
+		2,
+		3}
+	return T{
+		1,
+		2,
+		3,
+	}
+	return T{
+		1,
+		T{1, 2, 3},
+		3,
+	}
+	return T{
+		1,
+		T{1,
+			2, 3},
+		3,
+	}
+	return T{
+		1,
+		T{1,
+			2,
+			3},
+		3,
+	}
+	return T{
+		1,
+		2,
+	}, nil
+	return T{
+			1,
+			2,
+		},
+		T{
+			x:	3,
+			y:	4,
+		}, nil
+	return T{
+			1,
+			2,
+		},
+		nil
+	return T{
+			1,
+			2,
+		},
+		T{
+			x:	3,
+			y:	4,
+		},
+		nil
+	return x + y +
+		z
+	return func() {}
+	return func() {
+			_ = 0
+		}, T{
+			1, 2,
+		}
+	return func() {
+		_ = 0
+	}
+	return func() T {
+		return T{
+			1, 2,
+		}
+	}
+}
+
+// Formatting of multi-line returns: test cases from issue 1207.
+func F() (*T, os.Error) {
+	return &T{
+			X:	1,
+			Y:	2,
+		},
+		nil
+}
+
+func G() (*T, *T, os.Error) {
+	return &T{
+			X:	1,
+			Y:	2,
+		},
+		&T{
+			X:	3,
+			Y:	4,
+		},
+		nil
+}
+
+func _() interface{} {
+	return &fileStat{
+		name:		basename(file.name),
+		size:		mkSize(d.FileSizeHigh, d.FileSizeLow),
+		modTime:	mkModTime(d.LastWriteTime),
+		mode:		mkMode(d.FileAttributes),
+		sys:		mkSysFromFI(&d),
+	}, nil
+}
+
+// Formatting of if-statement headers.
+func _() {
+	if true {
+	}
+	if true {
+	}	// no semicolon printed
+	if expr {
+	}
+	if expr {
+	}	// no semicolon printed
+	if expr {
+	}	// no parens printed
+	if expr {
+	}	// no semicolon and parens printed
+	if x := expr; true {
+		use(x)
+	}
+	if x := expr; expr {
+		use(x)
+	}
+}
+
+// Formatting of switch-statement headers.
+func _() {
+	switch {
+	}
+	switch {
+	}	// no semicolon printed
+	switch expr {
+	}
+	switch expr {
+	}	// no semicolon printed
+	switch expr {
+	}	// no parens printed
+	switch expr {
+	}	// no semicolon and parens printed
+	switch x := expr; {
+	default:
+		use(
+			x)
+	}
+	switch x := expr; expr {
+	default:
+		use(x)
+	}
+}
+
+// Formatting of switch statement bodies.
+func _() {
+	switch {
+	}
+
+	switch x := 0; x {
+	case 1:
+		use(x)
+		use(x)	// followed by an empty line
+
+	case 2:	// followed by an empty line
+
+		use(x)	// followed by an empty line
+
+	case 3:	// no empty lines
+		use(x)
+		use(x)
+	}
+
+	switch x {
+	case 0:
+		use(x)
+	case 1:	// this comment should have no effect on the previous or next line
+		use(x)
+	}
+
+	switch x := 0; x {
+	case 1:
+		x = 0
+		// this comment should be indented
+	case 2:
+		x = 0
+	// this comment should not be indented, it is aligned with the next case
+	case 3:
+		x = 0
+		/* indented comment
+		   aligned
+		   aligned
+		*/
+		// bla
+		/* and more */
+	case 4:
+		x = 0
+	/* not indented comment
+	   aligned
+	   aligned
+	*/
+	// bla
+	/* and more */
+	case 5:
+	}
+}
+
+// Formatting of selected select statements.
+func _() {
+	select {}
+	select { /* this comment should not be tab-aligned because the closing } is on the same line */
+	}
+	select {	/* this comment should be tab-aligned */
+	}
+	select {	// this comment should be tab-aligned
+	}
+	select {
+	case <-c:
+	}
+}
+
+// Formatting of for-statement headers for single-line for-loops.
+func _() {
+	for {
+	}
+	for expr {
+	}
+	for expr {
+	}	// no parens printed
+	for {
+	}	// no semicolons printed
+	for x := expr; ; {
+		use(x)
+	}
+	for expr {
+	}	// no semicolons printed
+	for expr {
+	}	// no semicolons and parens printed
+	for ; ; expr = false {
+	}
+	for x := expr; expr; {
+		use(x)
+	}
+	for x := expr; ; expr = false {
+		use(x)
+	}
+	for ; expr; expr = false {
+	}
+	for x := expr; expr; expr = false {
+		use(x)
+	}
+	for x := range []int{} {
+		use(x)
+	}
+	for x := range []int{} {
+		use(x)
+	}	// no parens printed
+}
+
+// Formatting of for-statement headers for multi-line for-loops.
+func _() {
+	for {
+	}
+	for expr {
+	}
+	for expr {
+	}	// no parens printed
+	for {
+	}	// no semicolons printed
+	for x := expr; ; {
+		use(x)
+	}
+	for expr {
+	}	// no semicolons printed
+	for expr {
+	}	// no semicolons and parens printed
+	for ; ; expr = false {
+	}
+	for x := expr; expr; {
+		use(x)
+	}
+	for x := expr; ; expr = false {
+		use(x)
+	}
+	for ; expr; expr = false {
+	}
+	for x := expr; expr; expr = false {
+		use(x)
+	}
+	for x := range []int{} {
+		use(x)
+	}
+	for x := range []int{} {
+		use(x)
+	}	// no parens printed
+}
+
+// Formatting of selected short single- and multi-line statements.
+func _() {
+	if cond {
+	}
+	if cond {
+	}	// multiple lines
+	if cond {
+	} else {
+	}	// else clause always requires multiple lines
+
+	for {
+	}
+	for i := 0; i < len(a); 1++ {
+	}
+	for i := 0; i < len(a); 1++ {
+		a[i] = i
+	}
+	for i := 0; i < len(a); 1++ {
+		a[i] = i
+	}	// multiple lines
+
+	for i := range a {
+	}
+	for i := range a {
+		a[i] = i
+	}
+	for i := range a {
+		a[i] = i
+	}	// multiple lines
+
+	go func() {
+		for {
+			a <- <-b
+		}
+	}()
+	defer func() {
+		if x := recover(); x != nil {
+			err = fmt.Sprintf("error: %s", x.msg)
+		}
+	}()
+}
+
+// Don't remove mandatory parentheses around composite literals in control clauses.
+func _() {
+	// strip parentheses - no composite literals or composite literals don't start with a type name
+	if x {
+	}
+	if x {
+	}
+	if []T{} {
+	}
+	if []T{} {
+	}
+	if []T{} {
+	}
+
+	for x {
+	}
+	for x {
+	}
+	for []T{} {
+	}
+	for []T{} {
+	}
+	for []T{} {
+	}
+
+	switch x {
+	}
+	switch x {
+	}
+	switch []T{} {
+	}
+	switch []T{} {
+	}
+
+	for _ = range []T{T{42}} {
+	}
+
+	// leave parentheses - composite literals start with a type name
+	if (T{}) {
+	}
+	if (T{}) {
+	}
+	if (T{}) {
+	}
+
+	for (T{}) {
+	}
+	for (T{}) {
+	}
+	for (T{}) {
+	}
+
+	switch (T{}) {
+	}
+	switch (T{}) {
+	}
+
+	for _ = range (T1{T{42}}) {
+	}
+
+	if x == (T{42}[0]) {
+	}
+	if (x == T{42}[0]) {
+	}
+	if x == (T{42}[0]) {
+	}
+	if x == (T{42}[0]) {
+	}
+	if x == (T{42}[0]) {
+	}
+	if x == a+b*(T{42}[0]) {
+	}
+	if (x == a+b*T{42}[0]) {
+	}
+	if x == a+b*(T{42}[0]) {
+	}
+	if x == a+(b * (T{42}[0])) {
+	}
+	if x == a+b*(T{42}[0]) {
+	}
+	if (a + b*(T{42}[0])) == x {
+	}
+	if (a + b*(T{42}[0])) == x {
+	}
+
+	if struct{ x bool }{false}.x {
+	}
+	if (struct{ x bool }{false}.x) == false {
+	}
+	if struct{ x bool }{false}.x == false {
+	}
+}
+
+// Extra empty lines inside functions. Do respect source code line
+// breaks between statement boundaries but print at most one empty
+// line at a time.
+func _() {
+
+	const _ = 0
+
+	const _ = 1
+	type _ int
+	type _ float
+
+	var _ = 0
+	var x = 1
+
+	// Each use(x) call below should have at most one empty line before and after.
+	// Known bug: The first use call may have more than one empty line before
+	//            (see go/printer/nodes.go, func linebreak).
+
+	use(x)
+
+	if x < x {
+
+		use(x)
+
+	} else {
+
+		use(x)
+
+	}
+}
+
+// Formatting around labels.
+func _() {
+L:
+}
+
+func _() {
+	// this comment should be indented
+L:	// no semicolon needed
+}
+
+func _() {
+	switch 0 {
+	case 0:
+	L0:
+		;	// semicolon required
+	case 1:
+	L1:
+		;	// semicolon required
+	default:
+	L2:	// no semicolon needed
+	}
+}
+
+func _() {
+	f()
+L1:
+	f()
+L2:
+	;
+L3:
+}
+
+func _() {
+	// this comment should be indented
+L:
+}
+
+func _() {
+L:
+	_ = 0
+}
+
+func _() {
+	// this comment should be indented
+L:
+	_ = 0
+}
+
+func _() {
+	for {
+	L1:
+		_ = 0
+	L2:
+		_ = 0
+	}
+}
+
+func _() {
+	// this comment should be indented
+	for {
+	L1:
+		_ = 0
+	L2:
+		_ = 0
+	}
+}
+
+func _() {
+	if true {
+		_ = 0
+	}
+	_ = 0	// the indentation here should not be affected by the long label name
+AnOverlongLabel:
+	_ = 0
+
+	if true {
+		_ = 0
+	}
+	_ = 0
+
+L:
+	_ = 0
+}
+
+func _() {
+	for {
+		goto L
+	}
+L:
+
+	MoreCode()
+}
+
+func _() {
+	for {
+		goto L
+	}
+L:	// A comment on the same line as the label, followed by a single empty line.
+	// Known bug: There may be more than one empty line before MoreCode()
+	//            (see go/printer/nodes.go, func linebreak).
+
+	MoreCode()
+}
+
+func _() {
+	for {
+		goto L
+	}
+L:
+
+	// There should be a single empty line before this comment.
+	MoreCode()
+}
+
+func _() {
+	for {
+		goto AVeryLongLabelThatShouldNotAffectFormatting
+	}
+AVeryLongLabelThatShouldNotAffectFormatting:
+	// There should be a single empty line after this comment.
+
+	// There should be a single empty line before this comment.
+	MoreCode()
+}
+
+// Formatting of empty statements.
+func _() {
+
+}
+
+func _() {
+}
+
+func _() {
+}
+
+func _() {
+	f()
+}
+
+func _() {
+L:
+	;
+}
+
+func _() {
+L:
+	;
+	f()
+}
diff --git a/third_party/gofrontend/libgo/go/go/printer/testdata/statements.input b/third_party/gofrontend/libgo/go/go/printer/testdata/statements.input
new file mode 100644
index 0000000..e7fcc0e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/printer/testdata/statements.input
@@ -0,0 +1,550 @@
+// 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 statements
+
+var expr bool
+
+func use(x interface{}) {}
+
+// Formatting of multi-line return statements.
+func _f() {
+	return
+	return x, y, z
+	return T{}
+	return T{1, 2, 3},
+		x, y, z
+	return T{1, 2, 3},
+		x, y,
+		z
+	return T{1,
+		2,
+		3}
+	return T{1,
+		2,
+		3,
+	}
+	return T{
+		1,
+		2,
+		3}
+	return T{
+		1,
+		2,
+		3,
+	}
+	return T{
+		1,
+		T{1, 2, 3},
+		3,
+	}
+	return T{
+		1,
+		T{1,
+			2, 3},
+		3,
+	}
+	return T{
+		1,
+		T{1,
+			2,
+			3},
+		3,
+	}
+	return T{
+			1,
+			2,
+		}, nil
+	return T{
+			1,
+			2,
+		},
+		T{
+			x: 3,
+			y: 4,
+		}, nil
+	return T{
+			1,
+			2,
+		},
+		nil
+	return T{
+			1,
+			2,
+		},
+		T{
+			x: 3,
+			y: 4,
+		},
+		nil
+	return x + y +
+		z
+	return func() {}
+	return func() {
+		_ = 0
+	}, T{
+		1, 2,
+	}
+	return func() {
+		_ = 0
+	}
+	return func() T {
+		return T {
+			1, 2,
+		}
+	}
+}
+
+// Formatting of multi-line returns: test cases from issue 1207.
+func F() (*T, os.Error) {
+       return &T{
+               X: 1,
+               Y: 2,
+       },
+               nil
+}
+
+func G() (*T, *T, os.Error) {
+       return &T{
+               X: 1,
+               Y: 2,
+       },
+               &T{
+                       X: 3,
+                       Y: 4,
+               },
+               nil
+}
+
+func _() interface{} {
+	return &fileStat{
+			name:    basename(file.name),
+			size:    mkSize(d.FileSizeHigh, d.FileSizeLow),
+			modTime: mkModTime(d.LastWriteTime),
+			mode:    mkMode(d.FileAttributes),
+			sys:     mkSysFromFI(&d),
+		}, nil
+}
+
+// Formatting of if-statement headers.
+func _() {
+	if true {}
+	if; true {}  // no semicolon printed
+	if expr{}
+	if;expr{}  // no semicolon printed
+	if (expr){}  // no parens printed
+	if;((expr)){}  // no semicolon and parens printed
+	if x:=expr;true{
+	use(x)}
+	if x:=expr; expr {use(x)}
+}
+
+
+// Formatting of switch-statement headers.
+func _() {
+	switch {}
+	switch;{}  // no semicolon printed
+	switch expr {}
+	switch;expr{}  // no semicolon printed
+	switch (expr) {}  // no parens printed
+	switch;((expr)){}  // no semicolon and parens printed
+	switch x := expr; { default:use(
+x)
+	}
+	switch x := expr; expr {default:use(x)}
+}
+
+
+// Formatting of switch statement bodies.
+func _() {
+	switch {
+	}
+
+	switch x := 0; x {
+	case 1:
+		use(x)
+		use(x)  // followed by an empty line
+
+	case 2:  // followed by an empty line
+
+		use(x)  // followed by an empty line
+
+	case 3:  // no empty lines
+		use(x)
+		use(x)
+	}
+
+	switch x {
+	case 0:
+		use(x)
+	case 1:  // this comment should have no effect on the previous or next line
+		use(x)
+	}
+
+	switch x := 0; x {
+	case 1:
+		x = 0
+		// this comment should be indented
+	case 2:
+		x = 0
+	// this comment should not be indented, it is aligned with the next case
+	case 3:
+		x = 0
+		/* indented comment
+		   aligned
+		   aligned
+		*/
+		// bla
+		/* and more */
+	case 4:
+		x = 0
+	/* not indented comment
+	   aligned
+	   aligned
+	*/
+	// bla
+	/* and more */
+	case 5:
+	}
+}
+
+
+// Formatting of selected select statements.
+func _() {
+	select {
+	}
+	select { /* this comment should not be tab-aligned because the closing } is on the same line */ }
+	select { /* this comment should be tab-aligned */
+	}
+	select { // this comment should be tab-aligned
+	}
+	select { case <-c: }
+}
+
+
+// Formatting of for-statement headers for single-line for-loops.
+func _() {
+	for{}
+	for expr {}
+	for (expr) {}  // no parens printed
+	for;;{}  // no semicolons printed
+	for x :=expr;; {use( x)}
+	for; expr;{}  // no semicolons printed
+	for; ((expr));{}  // no semicolons and parens printed
+	for; ; expr = false {}
+	for x :=expr; expr; {use(x)}
+	for x := expr;; expr=false {use(x)}
+	for;expr;expr =false {}
+	for x := expr;expr;expr = false { use(x) }
+	for x := range []int{} { use(x) }
+	for x := range (([]int{})) { use(x) }  // no parens printed
+}
+
+
+// Formatting of for-statement headers for multi-line for-loops.
+func _() {
+	for{
+	}
+	for expr {
+	}
+	for (expr) {
+	}  // no parens printed
+	for;;{
+	}  // no semicolons printed
+	for x :=expr;; {use( x)
+	}
+	for; expr;{
+	}  // no semicolons printed
+	for; ((expr));{
+	}  // no semicolons and parens printed
+	for; ; expr = false {
+	}
+	for x :=expr; expr; {use(x)
+	}
+	for x := expr;; expr=false {use(x)
+	}
+	for;expr;expr =false {
+	}
+	for x := expr;expr;expr = false {
+	use(x)
+	}
+	for x := range []int{} {
+	use(x) }
+	for x := range (([]int{})) {
+	use(x) }  // no parens printed
+}
+
+
+// Formatting of selected short single- and multi-line statements.
+func _() {
+	if cond {}
+	if cond {
+	} // multiple lines
+	if cond {} else {} // else clause always requires multiple lines
+
+	for {}
+	for i := 0; i < len(a); 1++ {}
+	for i := 0; i < len(a); 1++ { a[i] = i }
+	for i := 0; i < len(a); 1++ { a[i] = i
+	} // multiple lines
+
+	for i := range a {}
+	for i := range a { a[i] = i }
+	for i := range a { a[i] = i
+	} // multiple lines
+
+	go func() { for { a <- <-b } }()
+	defer func() { if x := recover(); x != nil { err = fmt.Sprintf("error: %s", x.msg) } }()
+}
+
+
+// Don't remove mandatory parentheses around composite literals in control clauses.
+func _() {
+	// strip parentheses - no composite literals or composite literals don't start with a type name
+	if (x) {}
+	if (((x))) {}
+	if ([]T{}) {}
+	if (([]T{})) {}
+	if ; (((([]T{})))) {}
+
+	for (x) {}
+	for (((x))) {}
+	for ([]T{}) {}
+	for (([]T{})) {}
+	for ; (((([]T{})))) ; {}
+
+	switch (x) {}
+	switch (((x))) {}
+	switch ([]T{}) {}
+	switch ; (((([]T{})))) {}
+
+	for _ = range ((([]T{T{42}}))) {}
+
+	// leave parentheses - composite literals start with a type name
+	if (T{}) {}
+	if ((T{})) {}
+	if ; ((((T{})))) {}
+
+	for (T{}) {}
+	for ((T{})) {}
+	for ; ((((T{})))) ; {}
+
+	switch (T{}) {}
+	switch ; ((((T{})))) {}
+
+	for _ = range (((T1{T{42}}))) {}
+
+	if x == (T{42}[0]) {}
+	if (x == T{42}[0]) {}
+	if (x == (T{42}[0])) {}
+	if (x == (((T{42}[0])))) {}
+	if (((x == (T{42}[0])))) {}
+	if x == a + b*(T{42}[0]) {}
+	if (x == a + b*T{42}[0]) {}
+	if (x == a + b*(T{42}[0])) {}
+	if (x == a + ((b * (T{42}[0])))) {}
+	if (((x == a + b * (T{42}[0])))) {}
+	if (((a + b * (T{42}[0])) == x)) {}
+	if (((a + b * (T{42}[0])))) == x {}
+
+	if (struct{x bool}{false}.x) {}
+	if (struct{x bool}{false}.x) == false {}
+	if (struct{x bool}{false}.x == false) {}
+}
+
+
+// Extra empty lines inside functions. Do respect source code line
+// breaks between statement boundaries but print at most one empty
+// line at a time.
+func _() {
+
+	const _ = 0
+
+	const _ = 1
+	type _ int
+	type _ float
+
+	var _ = 0
+	var x = 1
+
+	// Each use(x) call below should have at most one empty line before and after.
+	// Known bug: The first use call may have more than one empty line before
+	//            (see go/printer/nodes.go, func linebreak).
+
+
+
+	use(x)
+
+	if x < x {
+
+		use(x)
+
+	} else {
+
+		use(x)
+
+	}
+}
+
+
+// Formatting around labels.
+func _() {
+	L:
+}
+
+
+func _() {
+	// this comment should be indented
+	L: ;  // no semicolon needed
+}
+
+
+func _() {
+	switch 0 {
+	case 0:
+		L0: ;  // semicolon required
+	case 1:
+		L1: ;  // semicolon required
+	default:
+		L2: ;  // no semicolon needed
+	}
+}
+
+
+func _() {
+	f()
+L1:
+	f()
+L2:
+	;
+L3:
+}
+
+
+func _() {
+	// this comment should be indented
+	L:
+}
+
+
+func _() {
+	L: _ = 0
+}
+
+
+func _() {
+	// this comment should be indented
+	L: _ = 0
+}
+
+
+func _() {
+	for {
+	L1: _ = 0
+	L2:
+		_ = 0
+	}
+}
+
+
+func _() {
+		// this comment should be indented
+	for {
+	L1: _ = 0
+	L2:
+		_ = 0
+	}
+}
+
+
+func _() {
+	if true {
+		_ = 0
+	}
+	_ = 0  // the indentation here should not be affected by the long label name
+AnOverlongLabel:
+	_ = 0
+	
+	if true {
+		_ = 0
+	}
+	_ = 0
+
+L:	_ = 0
+}
+
+
+func _() {
+	for {
+		goto L
+	}
+L:
+
+	MoreCode()
+}
+
+
+func _() {
+	for {
+		goto L
+	}
+L:	// A comment on the same line as the label, followed by a single empty line.
+	// Known bug: There may be more than one empty line before MoreCode()
+	//            (see go/printer/nodes.go, func linebreak).
+
+
+
+
+	MoreCode()
+}
+
+
+func _() {
+	for {
+		goto L
+	}
+L:
+
+
+
+
+	// There should be a single empty line before this comment.
+	MoreCode()
+}
+
+
+func _() {
+	for {
+		goto AVeryLongLabelThatShouldNotAffectFormatting
+	}
+AVeryLongLabelThatShouldNotAffectFormatting:
+	// There should be a single empty line after this comment.
+
+	// There should be a single empty line before this comment.
+	MoreCode()
+}
+
+
+// Formatting of empty statements.
+func _() {
+	;;;;;;;;;;;;;;;;;;;;;;;;;
+}
+
+func _() {;;;;;;;;;;;;;;;;;;;;;;;;;
+}
+
+func _() {;;;;;;;;;;;;;;;;;;;;;;;;;}
+
+func _() {
+f();;;;;;;;;;;;;;;;;;;;;;;;;
+}
+
+func _() {
+L:;;;;;;;;;;;;
+}
+
+func _() {
+L:;;;;;;;;;;;;
+	f()
+}
diff --git a/third_party/gofrontend/libgo/go/go/scanner/errors.go b/third_party/gofrontend/libgo/go/go/scanner/errors.go
new file mode 100644
index 0000000..22de69c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/scanner/errors.go
@@ -0,0 +1,126 @@
+// 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 scanner
+
+import (
+	"fmt"
+	"go/token"
+	"io"
+	"sort"
+)
+
+// In an ErrorList, an error is represented by an *Error.
+// The position Pos, if valid, points to the beginning of
+// the offending token, and the error condition is described
+// by Msg.
+//
+type Error struct {
+	Pos token.Position
+	Msg string
+}
+
+// Error implements the error interface.
+func (e Error) Error() string {
+	if e.Pos.Filename != "" || e.Pos.IsValid() {
+		// don't print "<unknown position>"
+		// TODO(gri) reconsider the semantics of Position.IsValid
+		return e.Pos.String() + ": " + e.Msg
+	}
+	return e.Msg
+}
+
+// ErrorList is a list of *Errors.
+// The zero value for an ErrorList is an empty ErrorList ready to use.
+//
+type ErrorList []*Error
+
+// Add adds an Error with given position and error message to an ErrorList.
+func (p *ErrorList) Add(pos token.Position, msg string) {
+	*p = append(*p, &Error{pos, msg})
+}
+
+// Reset resets an ErrorList to no errors.
+func (p *ErrorList) Reset() { *p = (*p)[0:0] }
+
+// ErrorList implements the sort Interface.
+func (p ErrorList) Len() int      { return len(p) }
+func (p ErrorList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p ErrorList) Less(i, j int) bool {
+	e := &p[i].Pos
+	f := &p[j].Pos
+	// Note that it is not sufficient to simply compare file offsets because
+	// the offsets do not reflect modified line information (through //line
+	// comments).
+	if e.Filename < f.Filename {
+		return true
+	}
+	if e.Filename == f.Filename {
+		if e.Line < f.Line {
+			return true
+		}
+		if e.Line == f.Line {
+			return e.Column < f.Column
+		}
+	}
+	return false
+}
+
+// Sort sorts an ErrorList. *Error entries are sorted by position,
+// other errors are sorted by error message, and before any *Error
+// entry.
+//
+func (p ErrorList) Sort() {
+	sort.Sort(p)
+}
+
+// RemoveMultiples sorts an ErrorList and removes all but the first error per line.
+func (p *ErrorList) RemoveMultiples() {
+	sort.Sort(p)
+	var last token.Position // initial last.Line is != any legal error line
+	i := 0
+	for _, e := range *p {
+		if e.Pos.Filename != last.Filename || e.Pos.Line != last.Line {
+			last = e.Pos
+			(*p)[i] = e
+			i++
+		}
+	}
+	(*p) = (*p)[0:i]
+}
+
+// An ErrorList implements the error interface.
+func (p ErrorList) Error() string {
+	switch len(p) {
+	case 0:
+		return "no errors"
+	case 1:
+		return p[0].Error()
+	}
+	return fmt.Sprintf("%s (and %d more errors)", p[0], len(p)-1)
+}
+
+// Err returns an error equivalent to this error list.
+// If the list is empty, Err returns nil.
+func (p ErrorList) Err() error {
+	if len(p) == 0 {
+		return nil
+	}
+	return p
+}
+
+// PrintError is a utility function that prints a list of errors to w,
+// one error per line, if the err parameter is an ErrorList. Otherwise
+// it prints the err string.
+//
+func PrintError(w io.Writer, err error) {
+	if list, ok := err.(ErrorList); ok {
+		for _, e := range list {
+			fmt.Fprintf(w, "%s\n", e)
+		}
+	} else if err != nil {
+		fmt.Fprintf(w, "%s\n", err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/scanner/scanner.go b/third_party/gofrontend/libgo/go/go/scanner/scanner.go
new file mode 100644
index 0000000..cec82ea
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/scanner/scanner.go
@@ -0,0 +1,760 @@
+// 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 scanner implements a scanner for Go source text.
+// It takes a []byte as source which can then be tokenized
+// through repeated calls to the Scan method.
+//
+package scanner
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"path/filepath"
+	"strconv"
+	"unicode"
+	"unicode/utf8"
+)
+
+// An ErrorHandler may be provided to Scanner.Init. If a syntax error is
+// encountered and a handler was installed, the handler is called with a
+// position and an error message. The position points to the beginning of
+// the offending token.
+//
+type ErrorHandler func(pos token.Position, msg string)
+
+// A Scanner holds the scanner's internal state while processing
+// a given text.  It can be allocated as part of another data
+// structure but must be initialized via Init before use.
+//
+type Scanner struct {
+	// immutable state
+	file *token.File  // source file handle
+	dir  string       // directory portion of file.Name()
+	src  []byte       // source
+	err  ErrorHandler // error reporting; or nil
+	mode Mode         // scanning mode
+
+	// scanning state
+	ch         rune // current character
+	offset     int  // character offset
+	rdOffset   int  // reading offset (position after current character)
+	lineOffset int  // current line offset
+	insertSemi bool // insert a semicolon before next newline
+
+	// public state - ok to modify
+	ErrorCount int // number of errors encountered
+}
+
+const bom = 0xFEFF // byte order mark, only permitted as very first character
+
+// Read the next Unicode char into s.ch.
+// s.ch < 0 means end-of-file.
+//
+func (s *Scanner) next() {
+	if s.rdOffset < len(s.src) {
+		s.offset = s.rdOffset
+		if s.ch == '\n' {
+			s.lineOffset = s.offset
+			s.file.AddLine(s.offset)
+		}
+		r, w := rune(s.src[s.rdOffset]), 1
+		switch {
+		case r == 0:
+			s.error(s.offset, "illegal character NUL")
+		case r >= 0x80:
+			// not ASCII
+			r, w = utf8.DecodeRune(s.src[s.rdOffset:])
+			if r == utf8.RuneError && w == 1 {
+				s.error(s.offset, "illegal UTF-8 encoding")
+			} else if r == bom && s.offset > 0 {
+				s.error(s.offset, "illegal byte order mark")
+			}
+		}
+		s.rdOffset += w
+		s.ch = r
+	} else {
+		s.offset = len(s.src)
+		if s.ch == '\n' {
+			s.lineOffset = s.offset
+			s.file.AddLine(s.offset)
+		}
+		s.ch = -1 // eof
+	}
+}
+
+// A mode value is a set of flags (or 0).
+// They control scanner behavior.
+//
+type Mode uint
+
+const (
+	ScanComments    Mode = 1 << iota // return comments as COMMENT tokens
+	dontInsertSemis                  // do not automatically insert semicolons - for testing only
+)
+
+// Init prepares the scanner s to tokenize the text src by setting the
+// scanner at the beginning of src. The scanner uses the file set file
+// for position information and it adds line information for each line.
+// It is ok to re-use the same file when re-scanning the same file as
+// line information which is already present is ignored. Init causes a
+// panic if the file size does not match the src size.
+//
+// Calls to Scan will invoke the error handler err if they encounter a
+// syntax error and err is not nil. Also, for each error encountered,
+// the Scanner field ErrorCount is incremented by one. The mode parameter
+// determines how comments are handled.
+//
+// Note that Init may call err if there is an error in the first character
+// of the file.
+//
+func (s *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode) {
+	// Explicitly initialize all fields since a scanner may be reused.
+	if file.Size() != len(src) {
+		panic(fmt.Sprintf("file size (%d) does not match src len (%d)", file.Size(), len(src)))
+	}
+	s.file = file
+	s.dir, _ = filepath.Split(file.Name())
+	s.src = src
+	s.err = err
+	s.mode = mode
+
+	s.ch = ' '
+	s.offset = 0
+	s.rdOffset = 0
+	s.lineOffset = 0
+	s.insertSemi = false
+	s.ErrorCount = 0
+
+	s.next()
+	if s.ch == bom {
+		s.next() // ignore BOM at file beginning
+	}
+}
+
+func (s *Scanner) error(offs int, msg string) {
+	if s.err != nil {
+		s.err(s.file.Position(s.file.Pos(offs)), msg)
+	}
+	s.ErrorCount++
+}
+
+var prefix = []byte("//line ")
+
+func (s *Scanner) interpretLineComment(text []byte) {
+	if bytes.HasPrefix(text, prefix) {
+		// get filename and line number, if any
+		if i := bytes.LastIndex(text, []byte{':'}); i > 0 {
+			if line, err := strconv.Atoi(string(text[i+1:])); err == nil && line > 0 {
+				// valid //line filename:line comment
+				filename := string(bytes.TrimSpace(text[len(prefix):i]))
+				if filename != "" {
+					filename = filepath.Clean(filename)
+					if !filepath.IsAbs(filename) {
+						// make filename relative to current directory
+						filename = filepath.Join(s.dir, filename)
+					}
+				}
+				// update scanner position
+				s.file.AddLineInfo(s.lineOffset+len(text)+1, filename, line) // +len(text)+1 since comment applies to next line
+			}
+		}
+	}
+}
+
+func (s *Scanner) scanComment() string {
+	// initial '/' already consumed; s.ch == '/' || s.ch == '*'
+	offs := s.offset - 1 // position of initial '/'
+	hasCR := false
+
+	if s.ch == '/' {
+		//-style comment
+		s.next()
+		for s.ch != '\n' && s.ch >= 0 {
+			if s.ch == '\r' {
+				hasCR = true
+			}
+			s.next()
+		}
+		if offs == s.lineOffset {
+			// comment starts at the beginning of the current line
+			s.interpretLineComment(s.src[offs:s.offset])
+		}
+		goto exit
+	}
+
+	/*-style comment */
+	s.next()
+	for s.ch >= 0 {
+		ch := s.ch
+		if ch == '\r' {
+			hasCR = true
+		}
+		s.next()
+		if ch == '*' && s.ch == '/' {
+			s.next()
+			goto exit
+		}
+	}
+
+	s.error(offs, "comment not terminated")
+
+exit:
+	lit := s.src[offs:s.offset]
+	if hasCR {
+		lit = stripCR(lit)
+	}
+
+	return string(lit)
+}
+
+func (s *Scanner) findLineEnd() bool {
+	// initial '/' already consumed
+
+	defer func(offs int) {
+		// reset scanner state to where it was upon calling findLineEnd
+		s.ch = '/'
+		s.offset = offs
+		s.rdOffset = offs + 1
+		s.next() // consume initial '/' again
+	}(s.offset - 1)
+
+	// read ahead until a newline, EOF, or non-comment token is found
+	for s.ch == '/' || s.ch == '*' {
+		if s.ch == '/' {
+			//-style comment always contains a newline
+			return true
+		}
+		/*-style comment: look for newline */
+		s.next()
+		for s.ch >= 0 {
+			ch := s.ch
+			if ch == '\n' {
+				return true
+			}
+			s.next()
+			if ch == '*' && s.ch == '/' {
+				s.next()
+				break
+			}
+		}
+		s.skipWhitespace() // s.insertSemi is set
+		if s.ch < 0 || s.ch == '\n' {
+			return true
+		}
+		if s.ch != '/' {
+			// non-comment token
+			return false
+		}
+		s.next() // consume '/'
+	}
+
+	return false
+}
+
+func isLetter(ch rune) bool {
+	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
+}
+
+func isDigit(ch rune) bool {
+	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
+}
+
+func (s *Scanner) scanIdentifier() string {
+	offs := s.offset
+	for isLetter(s.ch) || isDigit(s.ch) {
+		s.next()
+	}
+	return string(s.src[offs:s.offset])
+}
+
+func digitVal(ch rune) int {
+	switch {
+	case '0' <= ch && ch <= '9':
+		return int(ch - '0')
+	case 'a' <= ch && ch <= 'f':
+		return int(ch - 'a' + 10)
+	case 'A' <= ch && ch <= 'F':
+		return int(ch - 'A' + 10)
+	}
+	return 16 // larger than any legal digit val
+}
+
+func (s *Scanner) scanMantissa(base int) {
+	for digitVal(s.ch) < base {
+		s.next()
+	}
+}
+
+func (s *Scanner) scanNumber(seenDecimalPoint bool) (token.Token, string) {
+	// digitVal(s.ch) < 10
+	offs := s.offset
+	tok := token.INT
+
+	if seenDecimalPoint {
+		offs--
+		tok = token.FLOAT
+		s.scanMantissa(10)
+		goto exponent
+	}
+
+	if s.ch == '0' {
+		// int or float
+		offs := s.offset
+		s.next()
+		if s.ch == 'x' || s.ch == 'X' {
+			// hexadecimal int
+			s.next()
+			s.scanMantissa(16)
+			if s.offset-offs <= 2 {
+				// only scanned "0x" or "0X"
+				s.error(offs, "illegal hexadecimal number")
+			}
+		} else {
+			// octal int or float
+			seenDecimalDigit := false
+			s.scanMantissa(8)
+			if s.ch == '8' || s.ch == '9' {
+				// illegal octal int or float
+				seenDecimalDigit = true
+				s.scanMantissa(10)
+			}
+			if s.ch == '.' || s.ch == 'e' || s.ch == 'E' || s.ch == 'i' {
+				goto fraction
+			}
+			// octal int
+			if seenDecimalDigit {
+				s.error(offs, "illegal octal number")
+			}
+		}
+		goto exit
+	}
+
+	// decimal int or float
+	s.scanMantissa(10)
+
+fraction:
+	if s.ch == '.' {
+		tok = token.FLOAT
+		s.next()
+		s.scanMantissa(10)
+	}
+
+exponent:
+	if s.ch == 'e' || s.ch == 'E' {
+		tok = token.FLOAT
+		s.next()
+		if s.ch == '-' || s.ch == '+' {
+			s.next()
+		}
+		s.scanMantissa(10)
+	}
+
+	if s.ch == 'i' {
+		tok = token.IMAG
+		s.next()
+	}
+
+exit:
+	return tok, string(s.src[offs:s.offset])
+}
+
+// scanEscape parses an escape sequence where rune is the accepted
+// escaped quote. In case of a syntax error, it stops at the offending
+// character (without consuming it) and returns false. Otherwise
+// it returns true.
+func (s *Scanner) scanEscape(quote rune) bool {
+	offs := s.offset
+
+	var n int
+	var base, max uint32
+	switch s.ch {
+	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
+		s.next()
+		return true
+	case '0', '1', '2', '3', '4', '5', '6', '7':
+		n, base, max = 3, 8, 255
+	case 'x':
+		s.next()
+		n, base, max = 2, 16, 255
+	case 'u':
+		s.next()
+		n, base, max = 4, 16, unicode.MaxRune
+	case 'U':
+		s.next()
+		n, base, max = 8, 16, unicode.MaxRune
+	default:
+		msg := "unknown escape sequence"
+		if s.ch < 0 {
+			msg = "escape sequence not terminated"
+		}
+		s.error(offs, msg)
+		return false
+	}
+
+	var x uint32
+	for n > 0 {
+		d := uint32(digitVal(s.ch))
+		if d >= base {
+			msg := fmt.Sprintf("illegal character %#U in escape sequence", s.ch)
+			if s.ch < 0 {
+				msg = "escape sequence not terminated"
+			}
+			s.error(s.offset, msg)
+			return false
+		}
+		x = x*base + d
+		s.next()
+		n--
+	}
+
+	if x > max || 0xD800 <= x && x < 0xE000 {
+		s.error(offs, "escape sequence is invalid Unicode code point")
+		return false
+	}
+
+	return true
+}
+
+func (s *Scanner) scanRune() string {
+	// '\'' opening already consumed
+	offs := s.offset - 1
+
+	valid := true
+	n := 0
+	for {
+		ch := s.ch
+		if ch == '\n' || ch < 0 {
+			// only report error if we don't have one already
+			if valid {
+				s.error(offs, "rune literal not terminated")
+				valid = false
+			}
+			break
+		}
+		s.next()
+		if ch == '\'' {
+			break
+		}
+		n++
+		if ch == '\\' {
+			if !s.scanEscape('\'') {
+				valid = false
+			}
+			// continue to read to closing quote
+		}
+	}
+
+	if valid && n != 1 {
+		s.error(offs, "illegal rune literal")
+	}
+
+	return string(s.src[offs:s.offset])
+}
+
+func (s *Scanner) scanString() string {
+	// '"' opening already consumed
+	offs := s.offset - 1
+
+	for {
+		ch := s.ch
+		if ch == '\n' || ch < 0 {
+			s.error(offs, "string literal not terminated")
+			break
+		}
+		s.next()
+		if ch == '"' {
+			break
+		}
+		if ch == '\\' {
+			s.scanEscape('"')
+		}
+	}
+
+	return string(s.src[offs:s.offset])
+}
+
+func stripCR(b []byte) []byte {
+	c := make([]byte, len(b))
+	i := 0
+	for _, ch := range b {
+		if ch != '\r' {
+			c[i] = ch
+			i++
+		}
+	}
+	return c[:i]
+}
+
+func (s *Scanner) scanRawString() string {
+	// '`' opening already consumed
+	offs := s.offset - 1
+
+	hasCR := false
+	for {
+		ch := s.ch
+		if ch < 0 {
+			s.error(offs, "raw string literal not terminated")
+			break
+		}
+		s.next()
+		if ch == '`' {
+			break
+		}
+		if ch == '\r' {
+			hasCR = true
+		}
+	}
+
+	lit := s.src[offs:s.offset]
+	if hasCR {
+		lit = stripCR(lit)
+	}
+
+	return string(lit)
+}
+
+func (s *Scanner) skipWhitespace() {
+	for s.ch == ' ' || s.ch == '\t' || s.ch == '\n' && !s.insertSemi || s.ch == '\r' {
+		s.next()
+	}
+}
+
+// Helper functions for scanning multi-byte tokens such as >> += >>= .
+// Different routines recognize different length tok_i based on matches
+// of ch_i. If a token ends in '=', the result is tok1 or tok3
+// respectively. Otherwise, the result is tok0 if there was no other
+// matching character, or tok2 if the matching character was ch2.
+
+func (s *Scanner) switch2(tok0, tok1 token.Token) token.Token {
+	if s.ch == '=' {
+		s.next()
+		return tok1
+	}
+	return tok0
+}
+
+func (s *Scanner) switch3(tok0, tok1 token.Token, ch2 rune, tok2 token.Token) token.Token {
+	if s.ch == '=' {
+		s.next()
+		return tok1
+	}
+	if s.ch == ch2 {
+		s.next()
+		return tok2
+	}
+	return tok0
+}
+
+func (s *Scanner) switch4(tok0, tok1 token.Token, ch2 rune, tok2, tok3 token.Token) token.Token {
+	if s.ch == '=' {
+		s.next()
+		return tok1
+	}
+	if s.ch == ch2 {
+		s.next()
+		if s.ch == '=' {
+			s.next()
+			return tok3
+		}
+		return tok2
+	}
+	return tok0
+}
+
+// Scan scans the next token and returns the token position, the token,
+// and its literal string if applicable. The source end is indicated by
+// token.EOF.
+//
+// If the returned token is a literal (token.IDENT, token.INT, token.FLOAT,
+// token.IMAG, token.CHAR, token.STRING) or token.COMMENT, the literal string
+// has the corresponding value.
+//
+// If the returned token is a keyword, the literal string is the keyword.
+//
+// If the returned token is token.SEMICOLON, the corresponding
+// literal string is ";" if the semicolon was present in the source,
+// and "\n" if the semicolon was inserted because of a newline or
+// at EOF.
+//
+// If the returned token is token.ILLEGAL, the literal string is the
+// offending character.
+//
+// In all other cases, Scan returns an empty literal string.
+//
+// For more tolerant parsing, Scan will return a valid token if
+// possible even if a syntax error was encountered. Thus, even
+// if the resulting token sequence contains no illegal tokens,
+// a client may not assume that no error occurred. Instead it
+// must check the scanner's ErrorCount or the number of calls
+// of the error handler, if there was one installed.
+//
+// Scan adds line information to the file added to the file
+// set with Init. Token positions are relative to that file
+// and thus relative to the file set.
+//
+func (s *Scanner) Scan() (pos token.Pos, tok token.Token, lit string) {
+scanAgain:
+	s.skipWhitespace()
+
+	// current token start
+	pos = s.file.Pos(s.offset)
+
+	// determine token value
+	insertSemi := false
+	switch ch := s.ch; {
+	case isLetter(ch):
+		lit = s.scanIdentifier()
+		if len(lit) > 1 {
+			// keywords are longer than one letter - avoid lookup otherwise
+			tok = token.Lookup(lit)
+			switch tok {
+			case token.IDENT, token.BREAK, token.CONTINUE, token.FALLTHROUGH, token.RETURN:
+				insertSemi = true
+			}
+		} else {
+			insertSemi = true
+			tok = token.IDENT
+		}
+	case '0' <= ch && ch <= '9':
+		insertSemi = true
+		tok, lit = s.scanNumber(false)
+	default:
+		s.next() // always make progress
+		switch ch {
+		case -1:
+			if s.insertSemi {
+				s.insertSemi = false // EOF consumed
+				return pos, token.SEMICOLON, "\n"
+			}
+			tok = token.EOF
+		case '\n':
+			// we only reach here if s.insertSemi was
+			// set in the first place and exited early
+			// from s.skipWhitespace()
+			s.insertSemi = false // newline consumed
+			return pos, token.SEMICOLON, "\n"
+		case '"':
+			insertSemi = true
+			tok = token.STRING
+			lit = s.scanString()
+		case '\'':
+			insertSemi = true
+			tok = token.CHAR
+			lit = s.scanRune()
+		case '`':
+			insertSemi = true
+			tok = token.STRING
+			lit = s.scanRawString()
+		case ':':
+			tok = s.switch2(token.COLON, token.DEFINE)
+		case '.':
+			if '0' <= s.ch && s.ch <= '9' {
+				insertSemi = true
+				tok, lit = s.scanNumber(true)
+			} else if s.ch == '.' {
+				s.next()
+				if s.ch == '.' {
+					s.next()
+					tok = token.ELLIPSIS
+				}
+			} else {
+				tok = token.PERIOD
+			}
+		case ',':
+			tok = token.COMMA
+		case ';':
+			tok = token.SEMICOLON
+			lit = ";"
+		case '(':
+			tok = token.LPAREN
+		case ')':
+			insertSemi = true
+			tok = token.RPAREN
+		case '[':
+			tok = token.LBRACK
+		case ']':
+			insertSemi = true
+			tok = token.RBRACK
+		case '{':
+			tok = token.LBRACE
+		case '}':
+			insertSemi = true
+			tok = token.RBRACE
+		case '+':
+			tok = s.switch3(token.ADD, token.ADD_ASSIGN, '+', token.INC)
+			if tok == token.INC {
+				insertSemi = true
+			}
+		case '-':
+			tok = s.switch3(token.SUB, token.SUB_ASSIGN, '-', token.DEC)
+			if tok == token.DEC {
+				insertSemi = true
+			}
+		case '*':
+			tok = s.switch2(token.MUL, token.MUL_ASSIGN)
+		case '/':
+			if s.ch == '/' || s.ch == '*' {
+				// comment
+				if s.insertSemi && s.findLineEnd() {
+					// reset position to the beginning of the comment
+					s.ch = '/'
+					s.offset = s.file.Offset(pos)
+					s.rdOffset = s.offset + 1
+					s.insertSemi = false // newline consumed
+					return pos, token.SEMICOLON, "\n"
+				}
+				lit = s.scanComment()
+				if s.mode&ScanComments == 0 {
+					// skip comment
+					s.insertSemi = false // newline consumed
+					goto scanAgain
+				}
+				tok = token.COMMENT
+			} else {
+				tok = s.switch2(token.QUO, token.QUO_ASSIGN)
+			}
+		case '%':
+			tok = s.switch2(token.REM, token.REM_ASSIGN)
+		case '^':
+			tok = s.switch2(token.XOR, token.XOR_ASSIGN)
+		case '<':
+			if s.ch == '-' {
+				s.next()
+				tok = token.ARROW
+			} else {
+				tok = s.switch4(token.LSS, token.LEQ, '<', token.SHL, token.SHL_ASSIGN)
+			}
+		case '>':
+			tok = s.switch4(token.GTR, token.GEQ, '>', token.SHR, token.SHR_ASSIGN)
+		case '=':
+			tok = s.switch2(token.ASSIGN, token.EQL)
+		case '!':
+			tok = s.switch2(token.NOT, token.NEQ)
+		case '&':
+			if s.ch == '^' {
+				s.next()
+				tok = s.switch2(token.AND_NOT, token.AND_NOT_ASSIGN)
+			} else {
+				tok = s.switch3(token.AND, token.AND_ASSIGN, '&', token.LAND)
+			}
+		case '|':
+			tok = s.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR)
+		default:
+			// next reports unexpected BOMs - don't repeat
+			if ch != bom {
+				s.error(s.file.Offset(pos), fmt.Sprintf("illegal character %#U", ch))
+			}
+			insertSemi = s.insertSemi // preserve insertSemi info
+			tok = token.ILLEGAL
+			lit = string(ch)
+		}
+	}
+	if s.mode&dontInsertSemis == 0 {
+		s.insertSemi = insertSemi
+	}
+
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/go/scanner/scanner_test.go b/third_party/gofrontend/libgo/go/go/scanner/scanner_test.go
new file mode 100644
index 0000000..fc450d8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/scanner/scanner_test.go
@@ -0,0 +1,775 @@
+// 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 scanner
+
+import (
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"runtime"
+	"testing"
+)
+
+var fset = token.NewFileSet()
+
+const /* class */ (
+	special = iota
+	literal
+	operator
+	keyword
+)
+
+func tokenclass(tok token.Token) int {
+	switch {
+	case tok.IsLiteral():
+		return literal
+	case tok.IsOperator():
+		return operator
+	case tok.IsKeyword():
+		return keyword
+	}
+	return special
+}
+
+type elt struct {
+	tok   token.Token
+	lit   string
+	class int
+}
+
+var tokens = [...]elt{
+	// Special tokens
+	{token.COMMENT, "/* a comment */", special},
+	{token.COMMENT, "// a comment \n", special},
+	{token.COMMENT, "/*\r*/", special},
+	{token.COMMENT, "//\r\n", special},
+
+	// Identifiers and basic type literals
+	{token.IDENT, "foobar", literal},
+	{token.IDENT, "a۰۱۸", literal},
+	{token.IDENT, "foo६४", literal},
+	{token.IDENT, "bar9876", literal},
+	{token.IDENT, "ŝ", literal},    // was bug (issue 4000)
+	{token.IDENT, "ŝfoo", literal}, // was bug (issue 4000)
+	{token.INT, "0", literal},
+	{token.INT, "1", literal},
+	{token.INT, "123456789012345678890", literal},
+	{token.INT, "01234567", literal},
+	{token.INT, "0xcafebabe", literal},
+	{token.FLOAT, "0.", literal},
+	{token.FLOAT, ".0", literal},
+	{token.FLOAT, "3.14159265", literal},
+	{token.FLOAT, "1e0", literal},
+	{token.FLOAT, "1e+100", literal},
+	{token.FLOAT, "1e-100", literal},
+	{token.FLOAT, "2.71828e-1000", literal},
+	{token.IMAG, "0i", literal},
+	{token.IMAG, "1i", literal},
+	{token.IMAG, "012345678901234567889i", literal},
+	{token.IMAG, "123456789012345678890i", literal},
+	{token.IMAG, "0.i", literal},
+	{token.IMAG, ".0i", literal},
+	{token.IMAG, "3.14159265i", literal},
+	{token.IMAG, "1e0i", literal},
+	{token.IMAG, "1e+100i", literal},
+	{token.IMAG, "1e-100i", literal},
+	{token.IMAG, "2.71828e-1000i", literal},
+	{token.CHAR, "'a'", literal},
+	{token.CHAR, "'\\000'", literal},
+	{token.CHAR, "'\\xFF'", literal},
+	{token.CHAR, "'\\uff16'", literal},
+	{token.CHAR, "'\\U0000ff16'", literal},
+	{token.STRING, "`foobar`", literal},
+	{token.STRING, "`" + `foo
+	                        bar` +
+		"`",
+		literal,
+	},
+	{token.STRING, "`\r`", literal},
+	{token.STRING, "`foo\r\nbar`", literal},
+
+	// Operators and delimiters
+	{token.ADD, "+", operator},
+	{token.SUB, "-", operator},
+	{token.MUL, "*", operator},
+	{token.QUO, "/", operator},
+	{token.REM, "%", operator},
+
+	{token.AND, "&", operator},
+	{token.OR, "|", operator},
+	{token.XOR, "^", operator},
+	{token.SHL, "<<", operator},
+	{token.SHR, ">>", operator},
+	{token.AND_NOT, "&^", operator},
+
+	{token.ADD_ASSIGN, "+=", operator},
+	{token.SUB_ASSIGN, "-=", operator},
+	{token.MUL_ASSIGN, "*=", operator},
+	{token.QUO_ASSIGN, "/=", operator},
+	{token.REM_ASSIGN, "%=", operator},
+
+	{token.AND_ASSIGN, "&=", operator},
+	{token.OR_ASSIGN, "|=", operator},
+	{token.XOR_ASSIGN, "^=", operator},
+	{token.SHL_ASSIGN, "<<=", operator},
+	{token.SHR_ASSIGN, ">>=", operator},
+	{token.AND_NOT_ASSIGN, "&^=", operator},
+
+	{token.LAND, "&&", operator},
+	{token.LOR, "||", operator},
+	{token.ARROW, "<-", operator},
+	{token.INC, "++", operator},
+	{token.DEC, "--", operator},
+
+	{token.EQL, "==", operator},
+	{token.LSS, "<", operator},
+	{token.GTR, ">", operator},
+	{token.ASSIGN, "=", operator},
+	{token.NOT, "!", operator},
+
+	{token.NEQ, "!=", operator},
+	{token.LEQ, "<=", operator},
+	{token.GEQ, ">=", operator},
+	{token.DEFINE, ":=", operator},
+	{token.ELLIPSIS, "...", operator},
+
+	{token.LPAREN, "(", operator},
+	{token.LBRACK, "[", operator},
+	{token.LBRACE, "{", operator},
+	{token.COMMA, ",", operator},
+	{token.PERIOD, ".", operator},
+
+	{token.RPAREN, ")", operator},
+	{token.RBRACK, "]", operator},
+	{token.RBRACE, "}", operator},
+	{token.SEMICOLON, ";", operator},
+	{token.COLON, ":", operator},
+
+	// Keywords
+	{token.BREAK, "break", keyword},
+	{token.CASE, "case", keyword},
+	{token.CHAN, "chan", keyword},
+	{token.CONST, "const", keyword},
+	{token.CONTINUE, "continue", keyword},
+
+	{token.DEFAULT, "default", keyword},
+	{token.DEFER, "defer", keyword},
+	{token.ELSE, "else", keyword},
+	{token.FALLTHROUGH, "fallthrough", keyword},
+	{token.FOR, "for", keyword},
+
+	{token.FUNC, "func", keyword},
+	{token.GO, "go", keyword},
+	{token.GOTO, "goto", keyword},
+	{token.IF, "if", keyword},
+	{token.IMPORT, "import", keyword},
+
+	{token.INTERFACE, "interface", keyword},
+	{token.MAP, "map", keyword},
+	{token.PACKAGE, "package", keyword},
+	{token.RANGE, "range", keyword},
+	{token.RETURN, "return", keyword},
+
+	{token.SELECT, "select", keyword},
+	{token.STRUCT, "struct", keyword},
+	{token.SWITCH, "switch", keyword},
+	{token.TYPE, "type", keyword},
+	{token.VAR, "var", keyword},
+}
+
+const whitespace = "  \t  \n\n\n" // to separate tokens
+
+var source = func() []byte {
+	var src []byte
+	for _, t := range tokens {
+		src = append(src, t.lit...)
+		src = append(src, whitespace...)
+	}
+	return src
+}()
+
+func newlineCount(s string) int {
+	n := 0
+	for i := 0; i < len(s); i++ {
+		if s[i] == '\n' {
+			n++
+		}
+	}
+	return n
+}
+
+func checkPos(t *testing.T, lit string, p token.Pos, expected token.Position) {
+	pos := fset.Position(p)
+	if pos.Filename != expected.Filename {
+		t.Errorf("bad filename for %q: got %s, expected %s", lit, pos.Filename, expected.Filename)
+	}
+	if pos.Offset != expected.Offset {
+		t.Errorf("bad position for %q: got %d, expected %d", lit, pos.Offset, expected.Offset)
+	}
+	if pos.Line != expected.Line {
+		t.Errorf("bad line for %q: got %d, expected %d", lit, pos.Line, expected.Line)
+	}
+	if pos.Column != expected.Column {
+		t.Errorf("bad column for %q: got %d, expected %d", lit, pos.Column, expected.Column)
+	}
+}
+
+// Verify that calling Scan() provides the correct results.
+func TestScan(t *testing.T) {
+	whitespace_linecount := newlineCount(whitespace)
+
+	// error handler
+	eh := func(_ token.Position, msg string) {
+		t.Errorf("error handler called (msg = %s)", msg)
+	}
+
+	// verify scan
+	var s Scanner
+	s.Init(fset.AddFile("", fset.Base(), len(source)), source, eh, ScanComments|dontInsertSemis)
+
+	// set up expected position
+	epos := token.Position{
+		Filename: "",
+		Offset:   0,
+		Line:     1,
+		Column:   1,
+	}
+
+	index := 0
+	for {
+		pos, tok, lit := s.Scan()
+
+		// check position
+		if tok == token.EOF {
+			// correction for EOF
+			epos.Line = newlineCount(string(source))
+			epos.Column = 2
+		}
+		checkPos(t, lit, pos, epos)
+
+		// check token
+		e := elt{token.EOF, "", special}
+		if index < len(tokens) {
+			e = tokens[index]
+			index++
+		}
+		if tok != e.tok {
+			t.Errorf("bad token for %q: got %s, expected %s", lit, tok, e.tok)
+		}
+
+		// check token class
+		if tokenclass(tok) != e.class {
+			t.Errorf("bad class for %q: got %d, expected %d", lit, tokenclass(tok), e.class)
+		}
+
+		// check literal
+		elit := ""
+		switch e.tok {
+		case token.COMMENT:
+			// no CRs in comments
+			elit = string(stripCR([]byte(e.lit)))
+			//-style comment literal doesn't contain newline
+			if elit[1] == '/' {
+				elit = elit[0 : len(elit)-1]
+			}
+		case token.IDENT:
+			elit = e.lit
+		case token.SEMICOLON:
+			elit = ";"
+		default:
+			if e.tok.IsLiteral() {
+				// no CRs in raw string literals
+				elit = e.lit
+				if elit[0] == '`' {
+					elit = string(stripCR([]byte(elit)))
+				}
+			} else if e.tok.IsKeyword() {
+				elit = e.lit
+			}
+		}
+		if lit != elit {
+			t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, elit)
+		}
+
+		if tok == token.EOF {
+			break
+		}
+
+		// update position
+		epos.Offset += len(e.lit) + len(whitespace)
+		epos.Line += newlineCount(e.lit) + whitespace_linecount
+
+	}
+
+	if s.ErrorCount != 0 {
+		t.Errorf("found %d errors", s.ErrorCount)
+	}
+}
+
+func checkSemi(t *testing.T, line string, mode Mode) {
+	var S Scanner
+	file := fset.AddFile("TestSemis", fset.Base(), len(line))
+	S.Init(file, []byte(line), nil, mode)
+	pos, tok, lit := S.Scan()
+	for tok != token.EOF {
+		if tok == token.ILLEGAL {
+			// the illegal token literal indicates what
+			// kind of semicolon literal to expect
+			semiLit := "\n"
+			if lit[0] == '#' {
+				semiLit = ";"
+			}
+			// next token must be a semicolon
+			semiPos := file.Position(pos)
+			semiPos.Offset++
+			semiPos.Column++
+			pos, tok, lit = S.Scan()
+			if tok == token.SEMICOLON {
+				if lit != semiLit {
+					t.Errorf(`bad literal for %q: got %q, expected %q`, line, lit, semiLit)
+				}
+				checkPos(t, line, pos, semiPos)
+			} else {
+				t.Errorf("bad token for %q: got %s, expected ;", line, tok)
+			}
+		} else if tok == token.SEMICOLON {
+			t.Errorf("bad token for %q: got ;, expected no ;", line)
+		}
+		pos, tok, lit = S.Scan()
+	}
+}
+
+var lines = []string{
+	// # indicates a semicolon present in the source
+	// $ indicates an automatically inserted semicolon
+	"",
+	"\ufeff#;", // first BOM is ignored
+	"#;",
+	"foo$\n",
+	"123$\n",
+	"1.2$\n",
+	"'x'$\n",
+	`"x"` + "$\n",
+	"`x`$\n",
+
+	"+\n",
+	"-\n",
+	"*\n",
+	"/\n",
+	"%\n",
+
+	"&\n",
+	"|\n",
+	"^\n",
+	"<<\n",
+	">>\n",
+	"&^\n",
+
+	"+=\n",
+	"-=\n",
+	"*=\n",
+	"/=\n",
+	"%=\n",
+
+	"&=\n",
+	"|=\n",
+	"^=\n",
+	"<<=\n",
+	">>=\n",
+	"&^=\n",
+
+	"&&\n",
+	"||\n",
+	"<-\n",
+	"++$\n",
+	"--$\n",
+
+	"==\n",
+	"<\n",
+	">\n",
+	"=\n",
+	"!\n",
+
+	"!=\n",
+	"<=\n",
+	">=\n",
+	":=\n",
+	"...\n",
+
+	"(\n",
+	"[\n",
+	"{\n",
+	",\n",
+	".\n",
+
+	")$\n",
+	"]$\n",
+	"}$\n",
+	"#;\n",
+	":\n",
+
+	"break$\n",
+	"case\n",
+	"chan\n",
+	"const\n",
+	"continue$\n",
+
+	"default\n",
+	"defer\n",
+	"else\n",
+	"fallthrough$\n",
+	"for\n",
+
+	"func\n",
+	"go\n",
+	"goto\n",
+	"if\n",
+	"import\n",
+
+	"interface\n",
+	"map\n",
+	"package\n",
+	"range\n",
+	"return$\n",
+
+	"select\n",
+	"struct\n",
+	"switch\n",
+	"type\n",
+	"var\n",
+
+	"foo$//comment\n",
+	"foo$//comment",
+	"foo$/*comment*/\n",
+	"foo$/*\n*/",
+	"foo$/*comment*/    \n",
+	"foo$/*\n*/    ",
+
+	"foo    $// comment\n",
+	"foo    $// comment",
+	"foo    $/*comment*/\n",
+	"foo    $/*\n*/",
+	"foo    $/*  */ /* \n */ bar$/**/\n",
+	"foo    $/*0*/ /*1*/ /*2*/\n",
+
+	"foo    $/*comment*/    \n",
+	"foo    $/*0*/ /*1*/ /*2*/    \n",
+	"foo	$/**/ /*-------------*/       /*----\n*/bar       $/*  \n*/baa$\n",
+	"foo    $/* an EOF terminates a line */",
+	"foo    $/* an EOF terminates a line */ /*",
+	"foo    $/* an EOF terminates a line */ //",
+
+	"package main$\n\nfunc main() {\n\tif {\n\t\treturn /* */ }$\n}$\n",
+	"package main$",
+}
+
+func TestSemis(t *testing.T) {
+	for _, line := range lines {
+		checkSemi(t, line, 0)
+		checkSemi(t, line, ScanComments)
+
+		// if the input ended in newlines, the input must tokenize the
+		// same with or without those newlines
+		for i := len(line) - 1; i >= 0 && line[i] == '\n'; i-- {
+			checkSemi(t, line[0:i], 0)
+			checkSemi(t, line[0:i], ScanComments)
+		}
+	}
+}
+
+type segment struct {
+	srcline  string // a line of source text
+	filename string // filename for current token
+	line     int    // line number for current token
+}
+
+var segments = []segment{
+	// exactly one token per line since the test consumes one token per segment
+	{"  line1", filepath.Join("dir", "TestLineComments"), 1},
+	{"\nline2", filepath.Join("dir", "TestLineComments"), 2},
+	{"\nline3  //line File1.go:100", filepath.Join("dir", "TestLineComments"), 3}, // bad line comment, ignored
+	{"\nline4", filepath.Join("dir", "TestLineComments"), 4},
+	{"\n//line File1.go:100\n  line100", filepath.Join("dir", "File1.go"), 100},
+	{"\n//line  \t :42\n  line1", "", 42},
+	{"\n//line File2.go:200\n  line200", filepath.Join("dir", "File2.go"), 200},
+	{"\n//line foo\t:42\n  line42", filepath.Join("dir", "foo"), 42},
+	{"\n //line foo:42\n  line44", filepath.Join("dir", "foo"), 44},           // bad line comment, ignored
+	{"\n//line foo 42\n  line46", filepath.Join("dir", "foo"), 46},            // bad line comment, ignored
+	{"\n//line foo:42 extra text\n  line48", filepath.Join("dir", "foo"), 48}, // bad line comment, ignored
+	{"\n//line ./foo:42\n  line42", filepath.Join("dir", "foo"), 42},
+	{"\n//line a/b/c/File1.go:100\n  line100", filepath.Join("dir", "a", "b", "c", "File1.go"), 100},
+}
+
+var unixsegments = []segment{
+	{"\n//line /bar:42\n  line42", "/bar", 42},
+}
+
+var winsegments = []segment{
+	{"\n//line c:\\bar:42\n  line42", "c:\\bar", 42},
+	{"\n//line c:\\dir\\File1.go:100\n  line100", "c:\\dir\\File1.go", 100},
+}
+
+// Verify that comments of the form "//line filename:line" are interpreted correctly.
+func TestLineComments(t *testing.T) {
+	segs := segments
+	if runtime.GOOS == "windows" {
+		segs = append(segs, winsegments...)
+	} else {
+		segs = append(segs, unixsegments...)
+	}
+
+	// make source
+	var src string
+	for _, e := range segs {
+		src += e.srcline
+	}
+
+	// verify scan
+	var S Scanner
+	file := fset.AddFile(filepath.Join("dir", "TestLineComments"), fset.Base(), len(src))
+	S.Init(file, []byte(src), nil, dontInsertSemis)
+	for _, s := range segs {
+		p, _, lit := S.Scan()
+		pos := file.Position(p)
+		checkPos(t, lit, p, token.Position{
+			Filename: s.filename,
+			Offset:   pos.Offset,
+			Line:     s.line,
+			Column:   pos.Column,
+		})
+	}
+
+	if S.ErrorCount != 0 {
+		t.Errorf("found %d errors", S.ErrorCount)
+	}
+}
+
+// Verify that initializing the same scanner more than once works correctly.
+func TestInit(t *testing.T) {
+	var s Scanner
+
+	// 1st init
+	src1 := "if true { }"
+	f1 := fset.AddFile("src1", fset.Base(), len(src1))
+	s.Init(f1, []byte(src1), nil, dontInsertSemis)
+	if f1.Size() != len(src1) {
+		t.Errorf("bad file size: got %d, expected %d", f1.Size(), len(src1))
+	}
+	s.Scan()              // if
+	s.Scan()              // true
+	_, tok, _ := s.Scan() // {
+	if tok != token.LBRACE {
+		t.Errorf("bad token: got %s, expected %s", tok, token.LBRACE)
+	}
+
+	// 2nd init
+	src2 := "go true { ]"
+	f2 := fset.AddFile("src2", fset.Base(), len(src2))
+	s.Init(f2, []byte(src2), nil, dontInsertSemis)
+	if f2.Size() != len(src2) {
+		t.Errorf("bad file size: got %d, expected %d", f2.Size(), len(src2))
+	}
+	_, tok, _ = s.Scan() // go
+	if tok != token.GO {
+		t.Errorf("bad token: got %s, expected %s", tok, token.GO)
+	}
+
+	if s.ErrorCount != 0 {
+		t.Errorf("found %d errors", s.ErrorCount)
+	}
+}
+
+func TestStdErrorHander(t *testing.T) {
+	const src = "@\n" + // illegal character, cause an error
+		"@ @\n" + // two errors on the same line
+		"//line File2:20\n" +
+		"@\n" + // different file, but same line
+		"//line File2:1\n" +
+		"@ @\n" + // same file, decreasing line number
+		"//line File1:1\n" +
+		"@ @ @" // original file, line 1 again
+
+	var list ErrorList
+	eh := func(pos token.Position, msg string) { list.Add(pos, msg) }
+
+	var s Scanner
+	s.Init(fset.AddFile("File1", fset.Base(), len(src)), []byte(src), eh, dontInsertSemis)
+	for {
+		if _, tok, _ := s.Scan(); tok == token.EOF {
+			break
+		}
+	}
+
+	if len(list) != s.ErrorCount {
+		t.Errorf("found %d errors, expected %d", len(list), s.ErrorCount)
+	}
+
+	if len(list) != 9 {
+		t.Errorf("found %d raw errors, expected 9", len(list))
+		PrintError(os.Stderr, list)
+	}
+
+	list.Sort()
+	if len(list) != 9 {
+		t.Errorf("found %d sorted errors, expected 9", len(list))
+		PrintError(os.Stderr, list)
+	}
+
+	list.RemoveMultiples()
+	if len(list) != 4 {
+		t.Errorf("found %d one-per-line errors, expected 4", len(list))
+		PrintError(os.Stderr, list)
+	}
+}
+
+type errorCollector struct {
+	cnt int            // number of errors encountered
+	msg string         // last error message encountered
+	pos token.Position // last error position encountered
+}
+
+func checkError(t *testing.T, src string, tok token.Token, pos int, lit, err string) {
+	var s Scanner
+	var h errorCollector
+	eh := func(pos token.Position, msg string) {
+		h.cnt++
+		h.msg = msg
+		h.pos = pos
+	}
+	s.Init(fset.AddFile("", fset.Base(), len(src)), []byte(src), eh, ScanComments|dontInsertSemis)
+	_, tok0, lit0 := s.Scan()
+	if tok0 != tok {
+		t.Errorf("%q: got %s, expected %s", src, tok0, tok)
+	}
+	if tok0 != token.ILLEGAL && lit0 != lit {
+		t.Errorf("%q: got literal %q, expected %q", src, lit0, lit)
+	}
+	cnt := 0
+	if err != "" {
+		cnt = 1
+	}
+	if h.cnt != cnt {
+		t.Errorf("%q: got cnt %d, expected %d", src, h.cnt, cnt)
+	}
+	if h.msg != err {
+		t.Errorf("%q: got msg %q, expected %q", src, h.msg, err)
+	}
+	if h.pos.Offset != pos {
+		t.Errorf("%q: got offset %d, expected %d", src, h.pos.Offset, pos)
+	}
+}
+
+var errors = []struct {
+	src string
+	tok token.Token
+	pos int
+	lit string
+	err string
+}{
+	{"\a", token.ILLEGAL, 0, "", "illegal character U+0007"},
+	{`#`, token.ILLEGAL, 0, "", "illegal character U+0023 '#'"},
+	{`…`, token.ILLEGAL, 0, "", "illegal character U+2026 '…'"},
+	{`' '`, token.CHAR, 0, `' '`, ""},
+	{`''`, token.CHAR, 0, `''`, "illegal rune literal"},
+	{`'12'`, token.CHAR, 0, `'12'`, "illegal rune literal"},
+	{`'123'`, token.CHAR, 0, `'123'`, "illegal rune literal"},
+	{`'\0'`, token.CHAR, 3, `'\0'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\07'`, token.CHAR, 4, `'\07'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\8'`, token.CHAR, 2, `'\8'`, "unknown escape sequence"},
+	{`'\08'`, token.CHAR, 3, `'\08'`, "illegal character U+0038 '8' in escape sequence"},
+	{`'\x'`, token.CHAR, 3, `'\x'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\x0'`, token.CHAR, 4, `'\x0'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\x0g'`, token.CHAR, 4, `'\x0g'`, "illegal character U+0067 'g' in escape sequence"},
+	{`'\u'`, token.CHAR, 3, `'\u'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\u0'`, token.CHAR, 4, `'\u0'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\u00'`, token.CHAR, 5, `'\u00'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\u000'`, token.CHAR, 6, `'\u000'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\u000`, token.CHAR, 6, `'\u000`, "escape sequence not terminated"},
+	{`'\u0000'`, token.CHAR, 0, `'\u0000'`, ""},
+	{`'\U'`, token.CHAR, 3, `'\U'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\U0'`, token.CHAR, 4, `'\U0'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\U00'`, token.CHAR, 5, `'\U00'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\U000'`, token.CHAR, 6, `'\U000'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\U0000'`, token.CHAR, 7, `'\U0000'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\U00000'`, token.CHAR, 8, `'\U00000'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\U000000'`, token.CHAR, 9, `'\U000000'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\U0000000'`, token.CHAR, 10, `'\U0000000'`, "illegal character U+0027 ''' in escape sequence"},
+	{`'\U0000000`, token.CHAR, 10, `'\U0000000`, "escape sequence not terminated"},
+	{`'\U00000000'`, token.CHAR, 0, `'\U00000000'`, ""},
+	{`'\Uffffffff'`, token.CHAR, 2, `'\Uffffffff'`, "escape sequence is invalid Unicode code point"},
+	{`'`, token.CHAR, 0, `'`, "rune literal not terminated"},
+	{`'\`, token.CHAR, 2, `'\`, "escape sequence not terminated"},
+	{"'\n", token.CHAR, 0, "'", "rune literal not terminated"},
+	{"'\n   ", token.CHAR, 0, "'", "rune literal not terminated"},
+	{`""`, token.STRING, 0, `""`, ""},
+	{`"abc`, token.STRING, 0, `"abc`, "string literal not terminated"},
+	{"\"abc\n", token.STRING, 0, `"abc`, "string literal not terminated"},
+	{"\"abc\n   ", token.STRING, 0, `"abc`, "string literal not terminated"},
+	{"``", token.STRING, 0, "``", ""},
+	{"`", token.STRING, 0, "`", "raw string literal not terminated"},
+	{"/**/", token.COMMENT, 0, "/**/", ""},
+	{"/*", token.COMMENT, 0, "/*", "comment not terminated"},
+	{"077", token.INT, 0, "077", ""},
+	{"078.", token.FLOAT, 0, "078.", ""},
+	{"07801234567.", token.FLOAT, 0, "07801234567.", ""},
+	{"078e0", token.FLOAT, 0, "078e0", ""},
+	{"078", token.INT, 0, "078", "illegal octal number"},
+	{"07800000009", token.INT, 0, "07800000009", "illegal octal number"},
+	{"0x", token.INT, 0, "0x", "illegal hexadecimal number"},
+	{"0X", token.INT, 0, "0X", "illegal hexadecimal number"},
+	{"\"abc\x00def\"", token.STRING, 4, "\"abc\x00def\"", "illegal character NUL"},
+	{"\"abc\x80def\"", token.STRING, 4, "\"abc\x80def\"", "illegal UTF-8 encoding"},
+	{"\ufeff\ufeff", token.ILLEGAL, 3, "\ufeff\ufeff", "illegal byte order mark"},                        // only first BOM is ignored
+	{"//\ufeff", token.COMMENT, 2, "//\ufeff", "illegal byte order mark"},                                // only first BOM is ignored
+	{"'\ufeff" + `'`, token.CHAR, 1, "'\ufeff" + `'`, "illegal byte order mark"},                         // only first BOM is ignored
+	{`"` + "abc\ufeffdef" + `"`, token.STRING, 4, `"` + "abc\ufeffdef" + `"`, "illegal byte order mark"}, // only first BOM is ignored
+}
+
+func TestScanErrors(t *testing.T) {
+	for _, e := range errors {
+		checkError(t, e.src, e.tok, e.pos, e.lit, e.err)
+	}
+}
+
+func BenchmarkScan(b *testing.B) {
+	b.StopTimer()
+	fset := token.NewFileSet()
+	file := fset.AddFile("", fset.Base(), len(source))
+	var s Scanner
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		s.Init(file, source, nil, ScanComments)
+		for {
+			_, tok, _ := s.Scan()
+			if tok == token.EOF {
+				break
+			}
+		}
+	}
+}
+
+func BenchmarkScanFile(b *testing.B) {
+	b.StopTimer()
+	const filename = "scanner.go"
+	src, err := ioutil.ReadFile(filename)
+	if err != nil {
+		panic(err)
+	}
+	fset := token.NewFileSet()
+	file := fset.AddFile(filename, fset.Base(), len(src))
+	b.SetBytes(int64(len(src)))
+	var s Scanner
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		s.Init(file, src, nil, ScanComments)
+		for {
+			_, tok, _ := s.Scan()
+			if tok == token.EOF {
+				break
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/token/position.go b/third_party/gofrontend/libgo/go/go/token/position.go
new file mode 100644
index 0000000..e6f0ae6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/token/position.go
@@ -0,0 +1,464 @@
+// Copyright 2010 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.
+
+// TODO(gri) consider making this a separate package outside the go directory.
+
+package token
+
+import (
+	"fmt"
+	"sort"
+	"sync"
+)
+
+// -----------------------------------------------------------------------------
+// Positions
+
+// Position describes an arbitrary source position
+// including the file, line, and column location.
+// A Position is valid if the line number is > 0.
+//
+type Position struct {
+	Filename string // filename, if any
+	Offset   int    // offset, starting at 0
+	Line     int    // line number, starting at 1
+	Column   int    // column number, starting at 1 (character count)
+}
+
+// IsValid returns true if the position is valid.
+func (pos *Position) IsValid() bool { return pos.Line > 0 }
+
+// String returns a string in one of several forms:
+//
+//	file:line:column    valid position with file name
+//	line:column         valid position without file name
+//	file                invalid position with file name
+//	-                   invalid position without file name
+//
+func (pos Position) String() string {
+	s := pos.Filename
+	if pos.IsValid() {
+		if s != "" {
+			s += ":"
+		}
+		s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
+	}
+	if s == "" {
+		s = "-"
+	}
+	return s
+}
+
+// Pos is a compact encoding of a source position within a file set.
+// It can be converted into a Position for a more convenient, but much
+// larger, representation.
+//
+// The Pos value for a given file is a number in the range [base, base+size],
+// where base and size are specified when adding the file to the file set via
+// AddFile.
+//
+// To create the Pos value for a specific source offset, first add
+// the respective file to the current file set (via FileSet.AddFile)
+// and then call File.Pos(offset) for that file. Given a Pos value p
+// for a specific file set fset, the corresponding Position value is
+// obtained by calling fset.Position(p).
+//
+// Pos values can be compared directly with the usual comparison operators:
+// If two Pos values p and q are in the same file, comparing p and q is
+// equivalent to comparing the respective source file offsets. If p and q
+// are in different files, p < q is true if the file implied by p was added
+// to the respective file set before the file implied by q.
+//
+type Pos int
+
+// The zero value for Pos is NoPos; there is no file and line information
+// associated with it, and NoPos().IsValid() is false. NoPos is always
+// smaller than any other Pos value. The corresponding Position value
+// for NoPos is the zero value for Position.
+//
+const NoPos Pos = 0
+
+// IsValid returns true if the position is valid.
+func (p Pos) IsValid() bool {
+	return p != NoPos
+}
+
+// -----------------------------------------------------------------------------
+// File
+
+// A File is a handle for a file belonging to a FileSet.
+// A File has a name, size, and line offset table.
+//
+type File struct {
+	set  *FileSet
+	name string // file name as provided to AddFile
+	base int    // Pos value range for this file is [base...base+size]
+	size int    // file size as provided to AddFile
+
+	// lines and infos are protected by set.mutex
+	lines []int // lines contains the offset of the first character for each line (the first entry is always 0)
+	infos []lineInfo
+}
+
+// Name returns the file name of file f as registered with AddFile.
+func (f *File) Name() string {
+	return f.name
+}
+
+// Base returns the base offset of file f as registered with AddFile.
+func (f *File) Base() int {
+	return f.base
+}
+
+// Size returns the size of file f as registered with AddFile.
+func (f *File) Size() int {
+	return f.size
+}
+
+// LineCount returns the number of lines in file f.
+func (f *File) LineCount() int {
+	f.set.mutex.RLock()
+	n := len(f.lines)
+	f.set.mutex.RUnlock()
+	return n
+}
+
+// AddLine adds the line offset for a new line.
+// The line offset must be larger than the offset for the previous line
+// and smaller than the file size; otherwise the line offset is ignored.
+//
+func (f *File) AddLine(offset int) {
+	f.set.mutex.Lock()
+	if i := len(f.lines); (i == 0 || f.lines[i-1] < offset) && offset < f.size {
+		f.lines = append(f.lines, offset)
+	}
+	f.set.mutex.Unlock()
+}
+
+// MergeLine merges a line with the following line. It is akin to replacing
+// the newline character at the end of the line with a space (to not change the
+// remaining offsets). To obtain the line number, consult e.g. Position.Line.
+// MergeLine will panic if given an invalid line number.
+//
+func (f *File) MergeLine(line int) {
+	if line <= 0 {
+		panic("illegal line number (line numbering starts at 1)")
+	}
+	f.set.mutex.Lock()
+	defer f.set.mutex.Unlock()
+	if line >= len(f.lines) {
+		panic("illegal line number")
+	}
+	// To merge the line numbered <line> with the line numbered <line+1>,
+	// we need to remove the entry in lines corresponding to the line
+	// numbered <line+1>. The entry in lines corresponding to the line
+	// numbered <line+1> is located at index <line>, since indices in lines
+	// are 0-based and line numbers are 1-based.
+	copy(f.lines[line:], f.lines[line+1:])
+	f.lines = f.lines[:len(f.lines)-1]
+}
+
+// SetLines sets the line offsets for a file and returns true if successful.
+// The line offsets are the offsets of the first character of each line;
+// for instance for the content "ab\nc\n" the line offsets are {0, 3}.
+// An empty file has an empty line offset table.
+// Each line offset must be larger than the offset for the previous line
+// and smaller than the file size; otherwise SetLines fails and returns
+// false.
+//
+func (f *File) SetLines(lines []int) bool {
+	// verify validity of lines table
+	size := f.size
+	for i, offset := range lines {
+		if i > 0 && offset <= lines[i-1] || size <= offset {
+			return false
+		}
+	}
+
+	// set lines table
+	f.set.mutex.Lock()
+	f.lines = lines
+	f.set.mutex.Unlock()
+	return true
+}
+
+// SetLinesForContent sets the line offsets for the given file content.
+func (f *File) SetLinesForContent(content []byte) {
+	var lines []int
+	line := 0
+	for offset, b := range content {
+		if line >= 0 {
+			lines = append(lines, line)
+		}
+		line = -1
+		if b == '\n' {
+			line = offset + 1
+		}
+	}
+
+	// set lines table
+	f.set.mutex.Lock()
+	f.lines = lines
+	f.set.mutex.Unlock()
+}
+
+// A lineInfo object describes alternative file and line number
+// information (such as provided via a //line comment in a .go
+// file) for a given file offset.
+type lineInfo struct {
+	// fields are exported to make them accessible to gob
+	Offset   int
+	Filename string
+	Line     int
+}
+
+// AddLineInfo adds alternative file and line number information for
+// a given file offset. The offset must be larger than the offset for
+// the previously added alternative line info and smaller than the
+// file size; otherwise the information is ignored.
+//
+// AddLineInfo is typically used to register alternative position
+// information for //line filename:line comments in source files.
+//
+func (f *File) AddLineInfo(offset int, filename string, line int) {
+	f.set.mutex.Lock()
+	if i := len(f.infos); i == 0 || f.infos[i-1].Offset < offset && offset < f.size {
+		f.infos = append(f.infos, lineInfo{offset, filename, line})
+	}
+	f.set.mutex.Unlock()
+}
+
+// Pos returns the Pos value for the given file offset;
+// the offset must be <= f.Size().
+// f.Pos(f.Offset(p)) == p.
+//
+func (f *File) Pos(offset int) Pos {
+	if offset > f.size {
+		panic("illegal file offset")
+	}
+	return Pos(f.base + offset)
+}
+
+// Offset returns the offset for the given file position p;
+// p must be a valid Pos value in that file.
+// f.Offset(f.Pos(offset)) == offset.
+//
+func (f *File) Offset(p Pos) int {
+	if int(p) < f.base || int(p) > f.base+f.size {
+		panic("illegal Pos value")
+	}
+	return int(p) - f.base
+}
+
+// Line returns the line number for the given file position p;
+// p must be a Pos value in that file or NoPos.
+//
+func (f *File) Line(p Pos) int {
+	// TODO(gri) this can be implemented much more efficiently
+	return f.Position(p).Line
+}
+
+func searchLineInfos(a []lineInfo, x int) int {
+	return sort.Search(len(a), func(i int) bool { return a[i].Offset > x }) - 1
+}
+
+// info returns the file name, line, and column number for a file offset.
+func (f *File) info(offset int) (filename string, line, column int) {
+	filename = f.name
+	if i := searchInts(f.lines, offset); i >= 0 {
+		line, column = i+1, offset-f.lines[i]+1
+	}
+	if len(f.infos) > 0 {
+		// almost no files have extra line infos
+		if i := searchLineInfos(f.infos, offset); i >= 0 {
+			alt := &f.infos[i]
+			filename = alt.Filename
+			if i := searchInts(f.lines, alt.Offset); i >= 0 {
+				line += alt.Line - i - 1
+			}
+		}
+	}
+	return
+}
+
+func (f *File) position(p Pos) (pos Position) {
+	offset := int(p) - f.base
+	pos.Offset = offset
+	pos.Filename, pos.Line, pos.Column = f.info(offset)
+	return
+}
+
+// Position returns the Position value for the given file position p;
+// p must be a Pos value in that file or NoPos.
+//
+func (f *File) Position(p Pos) (pos Position) {
+	if p != NoPos {
+		if int(p) < f.base || int(p) > f.base+f.size {
+			panic("illegal Pos value")
+		}
+		pos = f.position(p)
+	}
+	return
+}
+
+// -----------------------------------------------------------------------------
+// FileSet
+
+// A FileSet represents a set of source files.
+// Methods of file sets are synchronized; multiple goroutines
+// may invoke them concurrently.
+//
+type FileSet struct {
+	mutex sync.RWMutex // protects the file set
+	base  int          // base offset for the next file
+	files []*File      // list of files in the order added to the set
+	last  *File        // cache of last file looked up
+}
+
+// NewFileSet creates a new file set.
+func NewFileSet() *FileSet {
+	return &FileSet{
+		base: 1, // 0 == NoPos
+	}
+}
+
+// Base returns the minimum base offset that must be provided to
+// AddFile when adding the next file.
+//
+func (s *FileSet) Base() int {
+	s.mutex.RLock()
+	b := s.base
+	s.mutex.RUnlock()
+	return b
+
+}
+
+// AddFile adds a new file with a given filename, base offset, and file size
+// to the file set s and returns the file. Multiple files may have the same
+// name. The base offset must not be smaller than the FileSet's Base(), and
+// size must not be negative. As a special case, if a negative base is provided,
+// the current value of the FileSet's Base() is used instead.
+//
+// Adding the file will set the file set's Base() value to base + size + 1
+// as the minimum base value for the next file. The following relationship
+// exists between a Pos value p for a given file offset offs:
+//
+//	int(p) = base + offs
+//
+// with offs in the range [0, size] and thus p in the range [base, base+size].
+// For convenience, File.Pos may be used to create file-specific position
+// values from a file offset.
+//
+func (s *FileSet) AddFile(filename string, base, size int) *File {
+	s.mutex.Lock()
+	defer s.mutex.Unlock()
+	if base < 0 {
+		base = s.base
+	}
+	if base < s.base || size < 0 {
+		panic("illegal base or size")
+	}
+	// base >= s.base && size >= 0
+	f := &File{s, filename, base, size, []int{0}, nil}
+	base += size + 1 // +1 because EOF also has a position
+	if base < 0 {
+		panic("token.Pos offset overflow (> 2G of source code in file set)")
+	}
+	// add the file to the file set
+	s.base = base
+	s.files = append(s.files, f)
+	s.last = f
+	return f
+}
+
+// Iterate calls f for the files in the file set in the order they were added
+// until f returns false.
+//
+func (s *FileSet) Iterate(f func(*File) bool) {
+	for i := 0; ; i++ {
+		var file *File
+		s.mutex.RLock()
+		if i < len(s.files) {
+			file = s.files[i]
+		}
+		s.mutex.RUnlock()
+		if file == nil || !f(file) {
+			break
+		}
+	}
+}
+
+func searchFiles(a []*File, x int) int {
+	return sort.Search(len(a), func(i int) bool { return a[i].base > x }) - 1
+}
+
+func (s *FileSet) file(p Pos) *File {
+	s.mutex.RLock()
+	// common case: p is in last file
+	if f := s.last; f != nil && f.base <= int(p) && int(p) <= f.base+f.size {
+		s.mutex.RUnlock()
+		return f
+	}
+	// p is not in last file - search all files
+	if i := searchFiles(s.files, int(p)); i >= 0 {
+		f := s.files[i]
+		// f.base <= int(p) by definition of searchFiles
+		if int(p) <= f.base+f.size {
+			s.mutex.RUnlock()
+			s.mutex.Lock()
+			s.last = f // race is ok - s.last is only a cache
+			s.mutex.Unlock()
+			return f
+		}
+	}
+	s.mutex.RUnlock()
+	return nil
+}
+
+// File returns the file that contains the position p.
+// If no such file is found (for instance for p == NoPos),
+// the result is nil.
+//
+func (s *FileSet) File(p Pos) (f *File) {
+	if p != NoPos {
+		f = s.file(p)
+	}
+	return
+}
+
+// Position converts a Pos in the fileset into a general Position.
+func (s *FileSet) Position(p Pos) (pos Position) {
+	if p != NoPos {
+		if f := s.file(p); f != nil {
+			pos = f.position(p)
+		}
+	}
+	return
+}
+
+// -----------------------------------------------------------------------------
+// Helper functions
+
+func searchInts(a []int, x int) int {
+	// This function body is a manually inlined version of:
+	//
+	//   return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1
+	//
+	// With better compiler optimizations, this may not be needed in the
+	// future, but at the moment this change improves the go/printer
+	// benchmark performance by ~30%. This has a direct impact on the
+	// speed of gofmt and thus seems worthwhile (2011-04-29).
+	// TODO(gri): Remove this when compilers have caught up.
+	i, j := 0, len(a)
+	for i < j {
+		h := i + (j-i)/2 // avoid overflow when computing h
+		// i ≤ h < j
+		if a[h] <= x {
+			i = h + 1
+		} else {
+			j = h
+		}
+	}
+	return i - 1
+}
diff --git a/third_party/gofrontend/libgo/go/go/token/position_test.go b/third_party/gofrontend/libgo/go/go/token/position_test.go
new file mode 100644
index 0000000..ef6cfd9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/token/position_test.go
@@ -0,0 +1,238 @@
+// Copyright 2010 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 token
+
+import (
+	"fmt"
+	"math/rand"
+	"sync"
+	"testing"
+)
+
+func checkPos(t *testing.T, msg string, p, q Position) {
+	if p.Filename != q.Filename {
+		t.Errorf("%s: expected filename = %q; got %q", msg, q.Filename, p.Filename)
+	}
+	if p.Offset != q.Offset {
+		t.Errorf("%s: expected offset = %d; got %d", msg, q.Offset, p.Offset)
+	}
+	if p.Line != q.Line {
+		t.Errorf("%s: expected line = %d; got %d", msg, q.Line, p.Line)
+	}
+	if p.Column != q.Column {
+		t.Errorf("%s: expected column = %d; got %d", msg, q.Column, p.Column)
+	}
+}
+
+func TestNoPos(t *testing.T) {
+	if NoPos.IsValid() {
+		t.Errorf("NoPos should not be valid")
+	}
+	var fset *FileSet
+	checkPos(t, "nil NoPos", fset.Position(NoPos), Position{})
+	fset = NewFileSet()
+	checkPos(t, "fset NoPos", fset.Position(NoPos), Position{})
+}
+
+var tests = []struct {
+	filename string
+	source   []byte // may be nil
+	size     int
+	lines    []int
+}{
+	{"a", []byte{}, 0, []int{}},
+	{"b", []byte("01234"), 5, []int{0}},
+	{"c", []byte("\n\n\n\n\n\n\n\n\n"), 9, []int{0, 1, 2, 3, 4, 5, 6, 7, 8}},
+	{"d", nil, 100, []int{0, 5, 10, 20, 30, 70, 71, 72, 80, 85, 90, 99}},
+	{"e", nil, 777, []int{0, 80, 100, 120, 130, 180, 267, 455, 500, 567, 620}},
+	{"f", []byte("package p\n\nimport \"fmt\""), 23, []int{0, 10, 11}},
+	{"g", []byte("package p\n\nimport \"fmt\"\n"), 24, []int{0, 10, 11}},
+	{"h", []byte("package p\n\nimport \"fmt\"\n "), 25, []int{0, 10, 11, 24}},
+}
+
+func linecol(lines []int, offs int) (int, int) {
+	prevLineOffs := 0
+	for line, lineOffs := range lines {
+		if offs < lineOffs {
+			return line, offs - prevLineOffs + 1
+		}
+		prevLineOffs = lineOffs
+	}
+	return len(lines), offs - prevLineOffs + 1
+}
+
+func verifyPositions(t *testing.T, fset *FileSet, f *File, lines []int) {
+	for offs := 0; offs < f.Size(); offs++ {
+		p := f.Pos(offs)
+		offs2 := f.Offset(p)
+		if offs2 != offs {
+			t.Errorf("%s, Offset: expected offset %d; got %d", f.Name(), offs, offs2)
+		}
+		line, col := linecol(lines, offs)
+		msg := fmt.Sprintf("%s (offs = %d, p = %d)", f.Name(), offs, p)
+		checkPos(t, msg, f.Position(f.Pos(offs)), Position{f.Name(), offs, line, col})
+		checkPos(t, msg, fset.Position(p), Position{f.Name(), offs, line, col})
+	}
+}
+
+func makeTestSource(size int, lines []int) []byte {
+	src := make([]byte, size)
+	for _, offs := range lines {
+		if offs > 0 {
+			src[offs-1] = '\n'
+		}
+	}
+	return src
+}
+
+func TestPositions(t *testing.T) {
+	const delta = 7 // a non-zero base offset increment
+	fset := NewFileSet()
+	for _, test := range tests {
+		// verify consistency of test case
+		if test.source != nil && len(test.source) != test.size {
+			t.Errorf("%s: inconsistent test case: expected file size %d; got %d", test.filename, test.size, len(test.source))
+		}
+
+		// add file and verify name and size
+		f := fset.AddFile(test.filename, fset.Base()+delta, test.size)
+		if f.Name() != test.filename {
+			t.Errorf("expected filename %q; got %q", test.filename, f.Name())
+		}
+		if f.Size() != test.size {
+			t.Errorf("%s: expected file size %d; got %d", f.Name(), test.size, f.Size())
+		}
+		if fset.File(f.Pos(0)) != f {
+			t.Errorf("%s: f.Pos(0) was not found in f", f.Name())
+		}
+
+		// add lines individually and verify all positions
+		for i, offset := range test.lines {
+			f.AddLine(offset)
+			if f.LineCount() != i+1 {
+				t.Errorf("%s, AddLine: expected line count %d; got %d", f.Name(), i+1, f.LineCount())
+			}
+			// adding the same offset again should be ignored
+			f.AddLine(offset)
+			if f.LineCount() != i+1 {
+				t.Errorf("%s, AddLine: expected unchanged line count %d; got %d", f.Name(), i+1, f.LineCount())
+			}
+			verifyPositions(t, fset, f, test.lines[0:i+1])
+		}
+
+		// add lines with SetLines and verify all positions
+		if ok := f.SetLines(test.lines); !ok {
+			t.Errorf("%s: SetLines failed", f.Name())
+		}
+		if f.LineCount() != len(test.lines) {
+			t.Errorf("%s, SetLines: expected line count %d; got %d", f.Name(), len(test.lines), f.LineCount())
+		}
+		verifyPositions(t, fset, f, test.lines)
+
+		// add lines with SetLinesForContent and verify all positions
+		src := test.source
+		if src == nil {
+			// no test source available - create one from scratch
+			src = makeTestSource(test.size, test.lines)
+		}
+		f.SetLinesForContent(src)
+		if f.LineCount() != len(test.lines) {
+			t.Errorf("%s, SetLinesForContent: expected line count %d; got %d", f.Name(), len(test.lines), f.LineCount())
+		}
+		verifyPositions(t, fset, f, test.lines)
+	}
+}
+
+func TestLineInfo(t *testing.T) {
+	fset := NewFileSet()
+	f := fset.AddFile("foo", fset.Base(), 500)
+	lines := []int{0, 42, 77, 100, 210, 220, 277, 300, 333, 401}
+	// add lines individually and provide alternative line information
+	for _, offs := range lines {
+		f.AddLine(offs)
+		f.AddLineInfo(offs, "bar", 42)
+	}
+	// verify positions for all offsets
+	for offs := 0; offs <= f.Size(); offs++ {
+		p := f.Pos(offs)
+		_, col := linecol(lines, offs)
+		msg := fmt.Sprintf("%s (offs = %d, p = %d)", f.Name(), offs, p)
+		checkPos(t, msg, f.Position(f.Pos(offs)), Position{"bar", offs, 42, col})
+		checkPos(t, msg, fset.Position(p), Position{"bar", offs, 42, col})
+	}
+}
+
+func TestFiles(t *testing.T) {
+	fset := NewFileSet()
+	for i, test := range tests {
+		base := fset.Base()
+		if i%2 == 1 {
+			// Setting a negative base is equivalent to
+			// fset.Base(), so test some of each.
+			base = -1
+		}
+		fset.AddFile(test.filename, base, test.size)
+		j := 0
+		fset.Iterate(func(f *File) bool {
+			if f.Name() != tests[j].filename {
+				t.Errorf("expected filename = %s; got %s", tests[j].filename, f.Name())
+			}
+			j++
+			return true
+		})
+		if j != i+1 {
+			t.Errorf("expected %d files; got %d", i+1, j)
+		}
+	}
+}
+
+// FileSet.File should return nil if Pos is past the end of the FileSet.
+func TestFileSetPastEnd(t *testing.T) {
+	fset := NewFileSet()
+	for _, test := range tests {
+		fset.AddFile(test.filename, fset.Base(), test.size)
+	}
+	if f := fset.File(Pos(fset.Base())); f != nil {
+		t.Errorf("expected nil, got %v", f)
+	}
+}
+
+func TestFileSetCacheUnlikely(t *testing.T) {
+	fset := NewFileSet()
+	offsets := make(map[string]int)
+	for _, test := range tests {
+		offsets[test.filename] = fset.Base()
+		fset.AddFile(test.filename, fset.Base(), test.size)
+	}
+	for file, pos := range offsets {
+		f := fset.File(Pos(pos))
+		if f.Name() != file {
+			t.Errorf("expecting %q at position %d, got %q", file, pos, f.Name())
+		}
+	}
+}
+
+// issue 4345. Test concurrent use of FileSet.Pos does not trigger a
+// race in the FileSet position cache.
+func TestFileSetRace(t *testing.T) {
+	fset := NewFileSet()
+	for i := 0; i < 100; i++ {
+		fset.AddFile(fmt.Sprintf("file-%d", i), fset.Base(), 1031)
+	}
+	max := int32(fset.Base())
+	var stop sync.WaitGroup
+	r := rand.New(rand.NewSource(7))
+	for i := 0; i < 2; i++ {
+		r := rand.New(rand.NewSource(r.Int63()))
+		stop.Add(1)
+		go func() {
+			for i := 0; i < 1000; i++ {
+				fset.Position(Pos(r.Int31n(max)))
+			}
+			stop.Done()
+		}()
+	}
+	stop.Wait()
+}
diff --git a/third_party/gofrontend/libgo/go/go/token/serialize.go b/third_party/gofrontend/libgo/go/go/token/serialize.go
new file mode 100644
index 0000000..4adc8f9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/token/serialize.go
@@ -0,0 +1,56 @@
+// 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.
+
+package token
+
+type serializedFile struct {
+	// fields correspond 1:1 to fields with same (lower-case) name in File
+	Name  string
+	Base  int
+	Size  int
+	Lines []int
+	Infos []lineInfo
+}
+
+type serializedFileSet struct {
+	Base  int
+	Files []serializedFile
+}
+
+// Read calls decode to deserialize a file set into s; s must not be nil.
+func (s *FileSet) Read(decode func(interface{}) error) error {
+	var ss serializedFileSet
+	if err := decode(&ss); err != nil {
+		return err
+	}
+
+	s.mutex.Lock()
+	s.base = ss.Base
+	files := make([]*File, len(ss.Files))
+	for i := 0; i < len(ss.Files); i++ {
+		f := &ss.Files[i]
+		files[i] = &File{s, f.Name, f.Base, f.Size, f.Lines, f.Infos}
+	}
+	s.files = files
+	s.last = nil
+	s.mutex.Unlock()
+
+	return nil
+}
+
+// Write calls encode to serialize the file set s.
+func (s *FileSet) Write(encode func(interface{}) error) error {
+	var ss serializedFileSet
+
+	s.mutex.Lock()
+	ss.Base = s.base
+	files := make([]serializedFile, len(s.files))
+	for i, f := range s.files {
+		files[i] = serializedFile{f.name, f.base, f.size, f.lines, f.infos}
+	}
+	ss.Files = files
+	s.mutex.Unlock()
+
+	return encode(ss)
+}
diff --git a/third_party/gofrontend/libgo/go/go/token/serialize_test.go b/third_party/gofrontend/libgo/go/go/token/serialize_test.go
new file mode 100644
index 0000000..4e925ad
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/token/serialize_test.go
@@ -0,0 +1,111 @@
+// 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.
+
+package token
+
+import (
+	"bytes"
+	"encoding/gob"
+	"fmt"
+	"testing"
+)
+
+// equal returns nil if p and q describe the same file set;
+// otherwise it returns an error describing the discrepancy.
+func equal(p, q *FileSet) error {
+	if p == q {
+		// avoid deadlock if p == q
+		return nil
+	}
+
+	// not strictly needed for the test
+	p.mutex.Lock()
+	q.mutex.Lock()
+	defer q.mutex.Unlock()
+	defer p.mutex.Unlock()
+
+	if p.base != q.base {
+		return fmt.Errorf("different bases: %d != %d", p.base, q.base)
+	}
+
+	if len(p.files) != len(q.files) {
+		return fmt.Errorf("different number of files: %d != %d", len(p.files), len(q.files))
+	}
+
+	for i, f := range p.files {
+		g := q.files[i]
+		if f.set != p {
+			return fmt.Errorf("wrong fileset for %q", f.name)
+		}
+		if g.set != q {
+			return fmt.Errorf("wrong fileset for %q", g.name)
+		}
+		if f.name != g.name {
+			return fmt.Errorf("different filenames: %q != %q", f.name, g.name)
+		}
+		if f.base != g.base {
+			return fmt.Errorf("different base for %q: %d != %d", f.name, f.base, g.base)
+		}
+		if f.size != g.size {
+			return fmt.Errorf("different size for %q: %d != %d", f.name, f.size, g.size)
+		}
+		for j, l := range f.lines {
+			m := g.lines[j]
+			if l != m {
+				return fmt.Errorf("different offsets for %q", f.name)
+			}
+		}
+		for j, l := range f.infos {
+			m := g.infos[j]
+			if l.Offset != m.Offset || l.Filename != m.Filename || l.Line != m.Line {
+				return fmt.Errorf("different infos for %q", f.name)
+			}
+		}
+	}
+
+	// we don't care about .last - it's just a cache
+	return nil
+}
+
+func checkSerialize(t *testing.T, p *FileSet) {
+	var buf bytes.Buffer
+	encode := func(x interface{}) error {
+		return gob.NewEncoder(&buf).Encode(x)
+	}
+	if err := p.Write(encode); err != nil {
+		t.Errorf("writing fileset failed: %s", err)
+		return
+	}
+	q := NewFileSet()
+	decode := func(x interface{}) error {
+		return gob.NewDecoder(&buf).Decode(x)
+	}
+	if err := q.Read(decode); err != nil {
+		t.Errorf("reading fileset failed: %s", err)
+		return
+	}
+	if err := equal(p, q); err != nil {
+		t.Errorf("filesets not identical: %s", err)
+	}
+}
+
+func TestSerialization(t *testing.T) {
+	p := NewFileSet()
+	checkSerialize(t, p)
+	// add some files
+	for i := 0; i < 10; i++ {
+		f := p.AddFile(fmt.Sprintf("file%d", i), p.Base()+i, i*100)
+		checkSerialize(t, p)
+		// add some lines and alternative file infos
+		line := 1000
+		for offs := 0; offs < f.Size(); offs += 40 + i {
+			f.AddLine(offs)
+			if offs%7 == 0 {
+				f.AddLineInfo(offs, fmt.Sprintf("file%d", offs), line)
+				line += 33
+			}
+		}
+		checkSerialize(t, p)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/go/token/token.go b/third_party/gofrontend/libgo/go/go/token/token.go
new file mode 100644
index 0000000..865f63f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/token/token.go
@@ -0,0 +1,308 @@
+// 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 token defines constants representing the lexical tokens of the Go
+// programming language and basic operations on tokens (printing, predicates).
+//
+package token
+
+import "strconv"
+
+// Token is the set of lexical tokens of the Go programming language.
+type Token int
+
+// The list of tokens.
+const (
+	// Special tokens
+	ILLEGAL Token = iota
+	EOF
+	COMMENT
+
+	literal_beg
+	// Identifiers and basic type literals
+	// (these tokens stand for classes of literals)
+	IDENT  // main
+	INT    // 12345
+	FLOAT  // 123.45
+	IMAG   // 123.45i
+	CHAR   // 'a'
+	STRING // "abc"
+	literal_end
+
+	operator_beg
+	// Operators and delimiters
+	ADD // +
+	SUB // -
+	MUL // *
+	QUO // /
+	REM // %
+
+	AND     // &
+	OR      // |
+	XOR     // ^
+	SHL     // <<
+	SHR     // >>
+	AND_NOT // &^
+
+	ADD_ASSIGN // +=
+	SUB_ASSIGN // -=
+	MUL_ASSIGN // *=
+	QUO_ASSIGN // /=
+	REM_ASSIGN // %=
+
+	AND_ASSIGN     // &=
+	OR_ASSIGN      // |=
+	XOR_ASSIGN     // ^=
+	SHL_ASSIGN     // <<=
+	SHR_ASSIGN     // >>=
+	AND_NOT_ASSIGN // &^=
+
+	LAND  // &&
+	LOR   // ||
+	ARROW // <-
+	INC   // ++
+	DEC   // --
+
+	EQL    // ==
+	LSS    // <
+	GTR    // >
+	ASSIGN // =
+	NOT    // !
+
+	NEQ      // !=
+	LEQ      // <=
+	GEQ      // >=
+	DEFINE   // :=
+	ELLIPSIS // ...
+
+	LPAREN // (
+	LBRACK // [
+	LBRACE // {
+	COMMA  // ,
+	PERIOD // .
+
+	RPAREN    // )
+	RBRACK    // ]
+	RBRACE    // }
+	SEMICOLON // ;
+	COLON     // :
+	operator_end
+
+	keyword_beg
+	// Keywords
+	BREAK
+	CASE
+	CHAN
+	CONST
+	CONTINUE
+
+	DEFAULT
+	DEFER
+	ELSE
+	FALLTHROUGH
+	FOR
+
+	FUNC
+	GO
+	GOTO
+	IF
+	IMPORT
+
+	INTERFACE
+	MAP
+	PACKAGE
+	RANGE
+	RETURN
+
+	SELECT
+	STRUCT
+	SWITCH
+	TYPE
+	VAR
+	keyword_end
+)
+
+var tokens = [...]string{
+	ILLEGAL: "ILLEGAL",
+
+	EOF:     "EOF",
+	COMMENT: "COMMENT",
+
+	IDENT:  "IDENT",
+	INT:    "INT",
+	FLOAT:  "FLOAT",
+	IMAG:   "IMAG",
+	CHAR:   "CHAR",
+	STRING: "STRING",
+
+	ADD: "+",
+	SUB: "-",
+	MUL: "*",
+	QUO: "/",
+	REM: "%",
+
+	AND:     "&",
+	OR:      "|",
+	XOR:     "^",
+	SHL:     "<<",
+	SHR:     ">>",
+	AND_NOT: "&^",
+
+	ADD_ASSIGN: "+=",
+	SUB_ASSIGN: "-=",
+	MUL_ASSIGN: "*=",
+	QUO_ASSIGN: "/=",
+	REM_ASSIGN: "%=",
+
+	AND_ASSIGN:     "&=",
+	OR_ASSIGN:      "|=",
+	XOR_ASSIGN:     "^=",
+	SHL_ASSIGN:     "<<=",
+	SHR_ASSIGN:     ">>=",
+	AND_NOT_ASSIGN: "&^=",
+
+	LAND:  "&&",
+	LOR:   "||",
+	ARROW: "<-",
+	INC:   "++",
+	DEC:   "--",
+
+	EQL:    "==",
+	LSS:    "<",
+	GTR:    ">",
+	ASSIGN: "=",
+	NOT:    "!",
+
+	NEQ:      "!=",
+	LEQ:      "<=",
+	GEQ:      ">=",
+	DEFINE:   ":=",
+	ELLIPSIS: "...",
+
+	LPAREN: "(",
+	LBRACK: "[",
+	LBRACE: "{",
+	COMMA:  ",",
+	PERIOD: ".",
+
+	RPAREN:    ")",
+	RBRACK:    "]",
+	RBRACE:    "}",
+	SEMICOLON: ";",
+	COLON:     ":",
+
+	BREAK:    "break",
+	CASE:     "case",
+	CHAN:     "chan",
+	CONST:    "const",
+	CONTINUE: "continue",
+
+	DEFAULT:     "default",
+	DEFER:       "defer",
+	ELSE:        "else",
+	FALLTHROUGH: "fallthrough",
+	FOR:         "for",
+
+	FUNC:   "func",
+	GO:     "go",
+	GOTO:   "goto",
+	IF:     "if",
+	IMPORT: "import",
+
+	INTERFACE: "interface",
+	MAP:       "map",
+	PACKAGE:   "package",
+	RANGE:     "range",
+	RETURN:    "return",
+
+	SELECT: "select",
+	STRUCT: "struct",
+	SWITCH: "switch",
+	TYPE:   "type",
+	VAR:    "var",
+}
+
+// String returns the string corresponding to the token tok.
+// For operators, delimiters, and keywords the string is the actual
+// token character sequence (e.g., for the token ADD, the string is
+// "+"). For all other tokens the string corresponds to the token
+// constant name (e.g. for the token IDENT, the string is "IDENT").
+//
+func (tok Token) String() string {
+	s := ""
+	if 0 <= tok && tok < Token(len(tokens)) {
+		s = tokens[tok]
+	}
+	if s == "" {
+		s = "token(" + strconv.Itoa(int(tok)) + ")"
+	}
+	return s
+}
+
+// A set of constants for precedence-based expression parsing.
+// Non-operators have lowest precedence, followed by operators
+// starting with precedence 1 up to unary operators. The highest
+// precedence serves as "catch-all" precedence for selector,
+// indexing, and other operator and delimiter tokens.
+//
+const (
+	LowestPrec  = 0 // non-operators
+	UnaryPrec   = 6
+	HighestPrec = 7
+)
+
+// Precedence returns the operator precedence of the binary
+// operator op. If op is not a binary operator, the result
+// is LowestPrecedence.
+//
+func (op Token) Precedence() int {
+	switch op {
+	case LOR:
+		return 1
+	case LAND:
+		return 2
+	case EQL, NEQ, LSS, LEQ, GTR, GEQ:
+		return 3
+	case ADD, SUB, OR, XOR:
+		return 4
+	case MUL, QUO, REM, SHL, SHR, AND, AND_NOT:
+		return 5
+	}
+	return LowestPrec
+}
+
+var keywords map[string]Token
+
+func init() {
+	keywords = make(map[string]Token)
+	for i := keyword_beg + 1; i < keyword_end; i++ {
+		keywords[tokens[i]] = i
+	}
+}
+
+// Lookup maps an identifier to its keyword token or IDENT (if not a keyword).
+//
+func Lookup(ident string) Token {
+	if tok, is_keyword := keywords[ident]; is_keyword {
+		return tok
+	}
+	return IDENT
+}
+
+// Predicates
+
+// IsLiteral returns true for tokens corresponding to identifiers
+// and basic type literals; it returns false otherwise.
+//
+func (tok Token) IsLiteral() bool { return literal_beg < tok && tok < literal_end }
+
+// IsOperator returns true for tokens corresponding to operators and
+// delimiters; it returns false otherwise.
+//
+func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator_end }
+
+// IsKeyword returns true for tokens corresponding to keywords;
+// it returns false otherwise.
+//
+func (tok Token) IsKeyword() bool { return keyword_beg < tok && tok < keyword_end }
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/builtins.src b/third_party/gofrontend/libgo/go/go/types/testdata/builtins.src
new file mode 100644
index 0000000..6c848fc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/builtins.src
@@ -0,0 +1,302 @@
+// 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.
+
+// builtin calls
+
+package builtins
+
+import "unsafe"
+
+func _append() {
+	var x int
+	var s []byte
+	_0 := append /* ERROR "argument" */ ()
+	_1 := append("foo" /* ERROR "not a typed slice" */)
+	_2 := append(nil /* ERROR "not a typed slice" */, s)
+	_3 := append(x /* ERROR "not a typed slice" */, s)
+	_4 := append(s)
+	append /* ERROR "not used" */ (s)
+}
+
+func _cap() {
+	var a [10]bool
+	var p *[20]int
+	var s []int
+	var c chan string
+	_0 := cap /* ERROR "argument" */ ()
+	_1 := cap /* ERROR "argument" */ (1, 2)
+	_2 := cap(42 /* ERROR "invalid" */)
+	const _3 = cap(a)
+	assert(_3 == 10)
+	const _4 = cap(p)
+	assert(_4 == 20)
+	_5 := cap(c)
+	cap /* ERROR "not used" */ (c)
+}
+
+func _close() {
+	var c chan int
+	var r <-chan int
+	close /* ERROR "argument" */ ()
+	close /* ERROR "argument" */ (1, 2)
+	close(42 /* ERROR "not a channel" */)
+	close(r /* ERROR "receive-only channel" */)
+	close(c)
+}
+
+func _complex() {
+	var i32 int32
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	_ = complex /* ERROR "argument" */ ()
+	_ = complex /* ERROR "argument" */ (1)
+	_ = complex(true /* ERROR "invalid argument" */ , 0)
+	_ = complex(i32 /* ERROR "invalid argument" */ , 0)
+	_ = complex("foo" /* ERROR "invalid argument" */ , 0)
+	_ = complex(c64 /* ERROR "invalid argument" */ , 0)
+	_ = complex(0, true /* ERROR "invalid argument" */ )
+	_ = complex(0, i32 /* ERROR "invalid argument" */ )
+	_ = complex(0, "foo" /* ERROR "invalid argument" */ )
+	_ = complex(0, c64 /* ERROR "invalid argument" */ )
+	_ = complex(f32, f32)
+	_ = complex(f32, 1)
+	_ = complex(f32, 1.0)
+	_ = complex(f32, 'a')
+	_ = complex(f64, f64)
+	_ = complex(f64, 1)
+	_ = complex(f64, 1.0)
+	_ = complex(f64, 'a')
+	_ = complex(f32 /* ERROR "mismatched types" */, f64)
+	_ = complex(f64 /* ERROR "mismatched types" */, f32)
+	_ = complex(1, 1)
+	_ = complex(1, 1.1)
+	_ = complex(1, 'a')
+	complex /* ERROR "not used" */ (1, 2)
+}
+
+func _copy() {
+	copy /* ERROR "not enough arguments" */ ()
+	copy /* ERROR "not enough arguments" */ ("foo")
+	copy([ /* ERROR "copy expects slice arguments" */ ...]int{}, []int{})
+	copy([ /* ERROR "copy expects slice arguments" */ ]int{}, [...]int{})
+	copy([ /* ERROR "different element types" */ ]int8{}, "foo")
+
+	// spec examples
+	var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
+	var s = make([]int, 6)
+	var b = make([]byte, 5)
+	n1 := copy(s, a[0:])            // n1 == 6, s == []int{0, 1, 2, 3, 4, 5}
+	n2 := copy(s, s[2:])            // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
+	n3 := copy(b, "Hello, World!")  // n3 == 5, b == []byte("Hello")
+}
+
+func _delete() {
+	var m map[string]int
+	var s string
+	delete /* ERROR "argument" */ ()
+	delete /* ERROR "argument" */ (1)
+	delete /* ERROR "argument" */ (1, 2, 3)
+	delete(m, 0 /* ERROR "not assignable" */)
+	delete(m, s)
+}
+
+func _imag() {
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	var c128 complex128
+	_ = imag /* ERROR "argument" */ ()
+	_ = imag /* ERROR "argument" */ (1, 2)
+	_ = imag(10 /* ERROR "must be a complex number" */)
+	_ = imag(2.7182818 /* ERROR "must be a complex number" */)
+	_ = imag("foo" /* ERROR "must be a complex number" */)
+	const _5 = imag(1 + 2i)
+	assert(_5 == 2)
+	f32 = _5
+	f64 = _5
+	const _6 = imag(0i)
+	assert(_6 == 0)
+	f32 = imag(c64)
+	f64 = imag(c128)
+	f32 = imag /* ERROR "cannot assign" */ (c128)
+	f64 = imag /* ERROR "cannot assign" */ (c64)
+	imag /* ERROR "not used" */ (c64)
+}
+
+func _len() {
+	const c = "foobar"
+	var a [10]bool
+	var p *[20]int
+	var s []int
+	var m map[string]complex128
+	_ = len /* ERROR "argument" */ ()
+	_ = len /* ERROR "argument" */ (1, 2)
+	_ = len(42 /* ERROR "invalid" */)
+	const _3 = len(c)
+	assert(_3 == 6)
+	const _4 = len(a)
+	assert(_4 == 10)
+	const _5 = len(p)
+	assert(_5 == 20)
+	_ = len(m)
+	len /* ERROR "not used" */ (c)
+
+	// esoteric case
+	var t string
+	var hash map[interface{}][]*[10]int
+	const n = len /* ERROR "not constant" */ (hash[recover()][len(t)])
+	assert /* ERROR "failed" */ (n == 10)
+	var ch <-chan int
+	const nn = len /* ERROR "not constant" */ (hash[<-ch][len(t)])
+	_ = nn // TODO(gri) remove this once unused constants get type-checked
+}
+
+func _make() {
+	n := 0
+
+	_ = make /* ERROR "argument" */ ()
+	_ = make(1 /* ERROR "not a type" */)
+	_ = make(int /* ERROR "cannot make" */)
+
+	// slices
+	_ = make/* ERROR "arguments" */ ([]int)
+	_ = make/* ERROR "arguments" */ ([]int, 2, 3, 4)
+	_ = make([]int, int /* ERROR "not an expression" */)
+	_ = make([]int, 10, float32 /* ERROR "not an expression" */)
+	_ = make([]int, "foo" /* ERROR "must be an integer" */)
+	_ = make([]int, 10, 2.3 /* ERROR "must be an integer" */)
+	_ = make([]int, 5, 10.0)
+	_ = make([]int, 0i)
+	_ = make([]int, - /* ERROR "must not be negative" */ 1, 10)
+	_ = make([]int, 0, - /* ERROR "must not be negative" */ 1)
+	_ = make([]int, - /* ERROR "must not be negative" */ 1, - /* ERROR "must not be negative" */ 1)
+	_ = make([]int, 1<<100, 1<<100)  // run-time panic
+	_ = make([]int, 1 /* ERROR "length and capacity swapped" */ <<100 + 1, 1<<100)
+	_ = make([]int, 1 /* ERROR "length and capacity swapped" */ <<100, 12345)
+
+	// maps
+	_ = make /* ERROR "arguments" */ (map[int]string, 10, 20)
+	_ = make(map[int]float32, int /* ERROR "not an expression" */)
+	_ = make(map[int]float32, "foo" /* ERROR "must be an integer" */)
+	_ = make(map[int]float32, 10)
+	_ = make(map[int]float32, n)
+	_ = make(map[int]float32, int64(n))
+
+	// channels
+	_ = make /* ERROR "arguments" */ (chan int, 10, 20)
+	_ = make(chan int, int /* ERROR "not an expression" */)
+	_ = make(chan<- int, "foo" /* ERROR "must be an integer" */)
+	_ = make(<-chan float64, 10)
+	_ = make(chan chan int, n)
+	_ = make(chan string, int64(n))
+
+	make /* ERROR "not used" */ ([]int, 10)
+}
+
+func _new() {
+	_ = new /* ERROR "argument" */ ()
+	_ = new /* ERROR "argument" */ (1, 2)
+	_ = new("foo" /* ERROR "not a type" */)
+	p := new(float64)
+	_ = new(struct{ x, y int })
+	q := new(*float64)
+	_ = *p == **q
+	new /* ERROR "not used" */ (int)
+}
+
+func _real() {
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	var c128 complex128
+	_ = real /* ERROR "argument" */ ()
+	_ = real /* ERROR "argument" */ (1, 2)
+	_ = real(10 /* ERROR "must be a complex number" */)
+	_ = real(2.7182818 /* ERROR "must be a complex number" */)
+	_ = real("foo" /* ERROR "must be a complex number" */)
+	const _5 = real(1 + 2i)
+	assert(_5 == 1)
+	f32 = _5
+	f64 = _5
+	const _6 = real(0i)
+	assert(_6 == 0)
+	f32 = real(c64)
+	f64 = real(c128)
+	f32 = real /* ERROR "cannot assign" */ (c128)
+	f64 = real /* ERROR "cannot assign" */ (c64)
+	real /* ERROR "not used" */ (c64)
+}
+
+func _recover() {
+	_ = recover()
+	_ = recover /* ERROR "argument" */ (10)
+	recover()
+}
+
+func _Alignof() {
+	var x int
+	_ = unsafe /* ERROR "argument" */ .Alignof()
+	_ = unsafe /* ERROR "argument" */ .Alignof(1, 2)
+	_ = unsafe.Alignof(int /* ERROR "not an expression" */)
+	_ = unsafe.Alignof(42)
+	_ = unsafe.Alignof(new(struct{}))
+	unsafe /* ERROR "not used" */ .Alignof(x)
+}
+
+func _Offsetof() {
+	var x struct{ f int }
+	_ = unsafe /* ERROR "argument" */ .Offsetof()
+	_ = unsafe /* ERROR "argument" */ .Offsetof(1, 2)
+	_ = unsafe.Offsetof(int /* ERROR "not an expression" */)
+	_ = unsafe.Offsetof(x /* ERROR "not a selector" */)
+	_ = unsafe.Offsetof(x.f)
+	_ = unsafe.Offsetof((x.f))
+	_ = unsafe.Offsetof((((((((x))).f)))))
+	unsafe /* ERROR "not used" */ .Offsetof(x.f)
+}
+
+func _Sizeof() {
+	var x int
+	_ = unsafe /* ERROR "argument" */ .Sizeof()
+	_ = unsafe /* ERROR "argument" */ .Sizeof(1, 2)
+	_ = unsafe.Sizeof(int /* ERROR "not an expression" */)
+	_ = unsafe.Sizeof(42)
+	_ = unsafe.Sizeof(new(complex128))
+	unsafe /* ERROR "not used" */ .Sizeof(x)
+
+	// basic types have size guarantees
+	assert(unsafe.Sizeof(byte(0)) == 1)
+	assert(unsafe.Sizeof(uint8(0)) == 1)
+	assert(unsafe.Sizeof(int8(0)) == 1)
+	assert(unsafe.Sizeof(uint16(0)) == 2)
+	assert(unsafe.Sizeof(int16(0)) == 2)
+	assert(unsafe.Sizeof(uint32(0)) == 4)
+	assert(unsafe.Sizeof(int32(0)) == 4)
+	assert(unsafe.Sizeof(float32(0)) == 4)
+	assert(unsafe.Sizeof(uint64(0)) == 8)
+	assert(unsafe.Sizeof(int64(0)) == 8)
+	assert(unsafe.Sizeof(float64(0)) == 8)
+	assert(unsafe.Sizeof(complex64(0)) == 8)
+	assert(unsafe.Sizeof(complex128(0)) == 16)
+}
+
+// self-testing only
+func _assert() {
+	var x int
+	assert /* ERROR "argument" */ ()
+	assert /* ERROR "argument" */ (1, 2)
+	assert("foo" /* ERROR "boolean constant" */ )
+	assert(x /* ERROR "boolean constant" */)
+	assert(true)
+	assert /* ERROR "failed" */ (false) 
+}
+
+// self-testing only
+func _trace() {
+	// Uncomment the code below to test trace - will produce console output
+	// _ = trace /* ERROR "no value" */ ()
+	// _ = trace(1)
+	// _ = trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar")
+}
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/const0.src b/third_party/gofrontend/libgo/go/go/types/testdata/const0.src
new file mode 100644
index 0000000..a2ca344
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/const0.src
@@ -0,0 +1,215 @@
+// 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.
+
+// constant declarations
+
+package const0
+
+// constants declarations must be initialized by constants
+var x = 0
+const c0 = x /* ERROR "not constant" */
+
+// untyped constants
+const (
+	// boolean values
+	ub0 = false
+	ub1 = true
+	ub2 = 2 < 1
+	ub3 = ui1 == uf1
+	ub4 = true /* ERROR "cannot convert" */ == 0
+
+	// integer values
+	ui0 = 0
+	ui1 = 1
+	ui2 = 42
+	ui3 = 3141592653589793238462643383279502884197169399375105820974944592307816406286
+	ui4 = -10
+
+	ui5 = ui0 + ui1
+	ui6 = ui1 - ui1
+	ui7 = ui2 * ui1
+	ui8 = ui3 / ui3
+	ui9 = ui3 % ui3
+
+	ui10 = 1 / 0 /* ERROR "division by zero" */
+	ui11 = ui1 / 0 /* ERROR "division by zero" */
+	ui12 = ui3 / ui0 /* ERROR "division by zero" */
+	ui13 = 1 % 0 /* ERROR "division by zero" */
+	ui14 = ui1 % 0 /* ERROR "division by zero" */
+	ui15 = ui3 % ui0 /* ERROR "division by zero" */
+
+	ui16 = ui2 & ui3
+	ui17 = ui2 | ui3
+	ui18 = ui2 ^ ui3
+
+	// floating point values
+	uf0 = 0.
+	uf1 = 1.
+	uf2 = 4.2e1
+	uf3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
+	uf4 = 1e-1
+
+	uf5 = uf0 + uf1
+	uf6 = uf1 - uf1
+	uf7 = uf2 * uf1
+	uf8 = uf3 / uf3
+	uf9 = uf3 /* ERROR "not defined" */ % uf3
+
+	uf10 = 1 / 0 /* ERROR "division by zero" */
+	uf11 = uf1 / 0 /* ERROR "division by zero" */
+	uf12 = uf3 / uf0 /* ERROR "division by zero" */
+
+	uf16 = uf2 /* ERROR "not defined" */ & uf3
+	uf17 = uf2 /* ERROR "not defined" */ | uf3
+	uf18 = uf2 /* ERROR "not defined" */ ^ uf3
+
+	// complex values
+	uc0 = 0.i
+	uc1 = 1.i
+	uc2 = 4.2e1i
+	uc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i
+	uc4 = 1e-1i
+
+	uc5 = uc0 + uc1
+	uc6 = uc1 - uc1
+	uc7 = uc2 * uc1
+	uc8 = uc3 / uc3
+	uc9 = uc3 /* ERROR "not defined" */ % uc3
+
+	uc10 = 1 / 0 /* ERROR "division by zero" */
+	uc11 = uc1 / 0 /* ERROR "division by zero" */
+	uc12 = uc3 / uc0 /* ERROR "division by zero" */
+
+	uc16 = uc2 /* ERROR "not defined" */ & uc3
+	uc17 = uc2 /* ERROR "not defined" */ | uc3
+	uc18 = uc2 /* ERROR "not defined" */ ^ uc3
+)
+
+type (
+	mybool bool
+	myint int
+	myfloat float64
+	mycomplex complex128
+)
+
+// typed constants
+const (
+	// boolean values
+	tb0 bool = false
+	tb1 bool = true
+	tb2 mybool = 2 < 1
+	tb3 mybool = ti1 /* ERROR "cannot compare" */ == tf1
+
+	// integer values
+	ti0 int8 = ui0
+	ti1 int32 = ui1
+	ti2 int64 = ui2
+	ti3 myint = ui3 /* ERROR "overflows" */
+	ti4 myint = ui4
+
+	ti5 = ti0 /* ERROR "mismatched types" */ + ti1
+	ti6 = ti1 - ti1
+	ti7 = ti2 /* ERROR "mismatched types" */ * ti1
+	//ti8 = ti3 / ti3 // TODO(gri) enable this
+	//ti9 = ti3 % ti3 // TODO(gri) enable this
+
+	ti10 = 1 / 0 /* ERROR "division by zero" */
+	ti11 = ti1 / 0 /* ERROR "division by zero" */
+	ti12 = ti3 /* ERROR "mismatched types" */ / ti0
+	ti13 = 1 % 0 /* ERROR "division by zero" */
+	ti14 = ti1 % 0 /* ERROR "division by zero" */
+	ti15 = ti3 /* ERROR "mismatched types" */ % ti0
+
+	ti16 = ti2 /* ERROR "mismatched types" */ & ti3
+	ti17 = ti2 /* ERROR "mismatched types" */ | ti4
+	ti18 = ti2 ^ ti5 // no mismatched types error because the type of ti5 is unknown
+
+	// floating point values
+	tf0 float32 = 0.
+	tf1 float32 = 1.
+	tf2 float64 = 4.2e1
+	tf3 myfloat = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
+	tf4 myfloat = 1e-1
+
+	tf5 = tf0 + tf1
+	tf6 = tf1 - tf1
+	tf7 = tf2 /* ERROR "mismatched types" */ * tf1
+	// tf8 = tf3 / tf3 // TODO(gri) enable this
+	tf9 = tf3 /* ERROR "not defined" */ % tf3
+
+	tf10 = 1 / 0 /* ERROR "division by zero" */
+	tf11 = tf1 / 0 /* ERROR "division by zero" */
+	tf12 = tf3 /* ERROR "mismatched types" */ / tf0
+
+	tf16 = tf2 /* ERROR "mismatched types" */ & tf3
+	tf17 = tf2 /* ERROR "mismatched types" */ | tf3
+	tf18 = tf2 /* ERROR "mismatched types" */ ^ tf3
+
+	// complex values
+	tc0 = 0.i
+	tc1 = 1.i
+	tc2 = 4.2e1i
+	tc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i
+	tc4 = 1e-1i
+
+	tc5 = tc0 + tc1
+	tc6 = tc1 - tc1
+	tc7 = tc2 * tc1
+	tc8 = tc3 / tc3
+	tc9 = tc3 /* ERROR "not defined" */ % tc3
+
+	tc10 = 1 / 0 /* ERROR "division by zero" */
+	tc11 = tc1 / 0 /* ERROR "division by zero" */
+	tc12 = tc3 / tc0 /* ERROR "division by zero" */
+
+	tc16 = tc2 /* ERROR "not defined" */ & tc3
+	tc17 = tc2 /* ERROR "not defined" */ | tc3
+	tc18 = tc2 /* ERROR "not defined" */ ^ tc3
+)
+
+// initialization cycles
+const (
+	a /* ERROR "cycle" */ = a
+	b /* ERROR "cycle" */ , c /* ERROR "cycle" */, d, e = e, d, c, b // TODO(gri) should only have one cycle error
+	f float64 = d
+)
+
+// multiple initialization
+const (
+	a1, a2, a3 = 7, 3.1415926, "foo"
+	b1, b2, b3 = b3, b1, 42
+	_p0 = assert(a1 == 7)
+	_p1 = assert(a2 == 3.1415926)
+	_p2 = assert(a3 == "foo")
+	_p3 = assert(b1 == 42)
+	_p4 = assert(b2 == 42)
+	_p5 = assert(b3 == 42)
+)
+
+// iota
+const (
+	iota0 = iota
+	iota1 = iota
+	iota2 = iota*2
+	_a0 = assert(iota0 == 0)
+	_a1 = assert(iota1 == 1)
+	_a2 = assert(iota2 == 4)
+	iota6 = iota*3
+
+	iota7
+	iota8
+	_a3 = assert(iota7 == 21)
+	_a4 = assert(iota8 == 24)
+)
+
+const (
+	_b0 = iota
+	_b1 = assert(iota + iota2 == 5)
+)
+
+// special cases
+const (
+	_n0 = nil /* ERROR "invalid constant type" */
+	_n1 = [ /* ERROR "not constant" */ ]int{}
+)
\ No newline at end of file
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/conversions.src b/third_party/gofrontend/libgo/go/go/types/testdata/conversions.src
new file mode 100644
index 0000000..1b15183
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/conversions.src
@@ -0,0 +1,18 @@
+// 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.
+
+// conversions
+
+package conversions
+
+// argument count
+var (
+	_v0 = int /* ERROR "one argument" */ ()
+	_v1 = int /* ERROR "one argument" */ (1, 2)
+)
+
+//
+var (
+	_v2 = int8(0)
+)
\ No newline at end of file
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/decls0.src b/third_party/gofrontend/libgo/go/go/types/testdata/decls0.src
new file mode 100644
index 0000000..33d4b38
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/decls0.src
@@ -0,0 +1,177 @@
+// 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.
+
+// type declarations
+
+package decls0
+
+import (
+	"unsafe"
+	// we can have multiple blank imports (was bug)
+	_ "math"
+	_ "net/rpc"
+)
+
+const pi = 3.1415
+
+type (
+	N undeclared /* ERROR "undeclared" */
+	B bool
+	I int32
+	A [10]P
+	T struct {
+		x, y P
+	}
+	P *T
+	R (*R)
+	F func(A) I
+	Y interface {
+		f(A) I
+	}
+	S [](((P)))
+	M map[I]F
+	C chan<- I
+
+	// blank types must be typechecked
+	_ pi /* ERROR "not a type" */
+	_ struct{}
+	_ struct{ pi /* ERROR "not a type" */ }
+)
+
+
+// invalid array types
+type (
+	iA0 [... /* ERROR "invalid use of '...'" */ ]byte
+	iA1 [1 /* ERROR "invalid array length" */ <<100]int
+	iA2 [- /* ERROR "invalid array length" */ 1]complex128
+	iA3 ["foo" /* ERROR "invalid array length" */ ]string
+)
+
+
+type (
+	p1 pi /* ERROR "no single field or method foo" */ .foo
+	p2 unsafe.Pointer
+)
+
+
+type (
+	Pi pi /* ERROR "not a type" */
+
+	a /* ERROR "illegal cycle" */ a
+	a /* ERROR "redeclared" */ int
+
+	// where the cycle error appears depends on the
+	// order in which declarations are processed
+	// (which depends on the order in which a map
+	// is iterated through)
+	b /* ERROR "illegal cycle" */ c
+	c d
+	d e
+	e b
+
+	t *t
+
+	U V
+	V *W
+	W U
+
+	P1 *S2
+	P2 P1
+
+	S0 struct {
+	}
+	S1 struct {
+		a, b, c int
+		u, v, a /* ERROR "redeclared" */ float32
+	}
+	S2 struct {
+		U // anonymous field
+		// TODO(gri) recognize double-declaration below
+		// U /* ERROR "redeclared" */ int
+	}
+	S3 struct {
+		x S2
+	}
+	S4/* ERROR "illegal cycle" */ struct {
+		S4
+	}
+	S5 /* ERROR "illegal cycle" */ struct {
+		S6
+	}
+	S6 struct {
+		field S7
+	}
+	S7 struct {
+		S5
+	}
+
+	L1 []L1
+	L2 []int
+
+	A1 [10.0]int
+	A2 /* ERROR "illegal cycle" */ [10]A2
+	A3 /* ERROR "illegal cycle" */ [10]struct {
+		x A4
+	}
+	A4 [10]A3
+
+	F1 func()
+	F2 func(x, y, z float32)
+	F3 func(x, y, x /* ERROR "redeclared" */ float32)
+	F4 func() (x, y, x /* ERROR "redeclared" */ float32)
+	F5 func(x int) (x /* ERROR "redeclared" */ float32)
+	F6 func(x ...int)
+
+	I1 interface{}
+	I2 interface {
+		m1()
+	}
+	I3 interface { /* ERROR "multiple methods named m1" */
+		m1()
+		m1 /* ERROR "redeclared" */ ()
+	}
+	I4 interface {
+		m1(x, y, x /* ERROR "redeclared" */ float32)
+		m2() (x, y, x /* ERROR "redeclared" */ float32)
+		m3(x int) (x /* ERROR "redeclared" */ float32)
+	}
+	I5 interface {
+		m1(I5)
+	}
+	I6 interface {
+		S0 /* ERROR "not an interface" */
+	}
+	I7 interface {
+		I1
+		I1
+	}
+	I8 /* ERROR "illegal cycle" */ interface {
+		I8
+	}
+	// Use I09 (rather than I9) because it appears lexically before
+	// I10 so that we get the illegal cycle here rather then in the
+	// declaration of I10. If the implementation sorts by position
+	// rather than name, the error message will still be here.
+	I09 /* ERROR "illegal cycle" */ interface {
+		I10
+	}
+	I10 interface {
+		I11
+	}
+	I11 interface {
+		I09
+	}
+
+	C1 chan int
+	C2 <-chan int
+	C3 chan<- C3
+	C4 chan C5
+	C5 chan C6
+	C6 chan C4
+
+	M1 map[Last]string
+	M2 map[string]M2
+
+	Last int
+)
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/decls1.src b/third_party/gofrontend/libgo/go/go/types/testdata/decls1.src
new file mode 100644
index 0000000..dd63ba9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/decls1.src
@@ -0,0 +1,132 @@
+// 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.
+
+// variable declarations
+
+package decls1
+
+import (
+	"math"
+)
+
+// Global variables without initialization
+var (
+	a, b bool
+	c byte
+	d uint8
+	r rune
+	i int
+	j, k, l int
+	x, y float32
+	xx, yy float64
+	u, v complex64
+	uu, vv complex128
+	s, t string
+	array []byte
+	iface interface{}
+	
+	blank _ /* ERROR "cannot use _" */
+)
+
+// Global variables with initialization
+var (
+	s1 = i + j
+	s2 = i /* ERROR "mismatched types" */ + x
+	s3 = c + d
+	s4 = s + t
+	s5 = s /* ERROR "invalid operation" */ / t
+	s6 = array[t1]
+	s7 = array[x /* ERROR "index" */]
+	s8 = &a
+	s10 = &42 /* ERROR "cannot take address" */
+	s11 = &v
+	s12 = -(u + *t11) / *&v
+	s13 = a /* ERROR "shifted operand" */ << d
+	s14 = i << j /* ERROR "must be unsigned" */ 
+	s18 = math.Pi * 10.0
+	s19 = s1 /* ERROR "cannot call" */ ()
+ 	s20 = f0 /* ERROR "no value" */ ()
+	s21 = f6(1, s1, i)
+	s22 = f6(1, s1, uu /* ERROR "cannot assign" */ )
+	
+	t1 int = i + j
+	t2 int = i /* ERROR "mismatched types" */ + x
+	t3 int = c /* ERROR "cannot assign" */ + d
+	t4 string = s + t
+	t5 string = s /* ERROR "invalid operation" */ / t
+	t6 byte = array[t1]
+	t7 byte = array[x /* ERROR "index" */]
+	t8 *int = & /* ERROR "cannot assign" */ a
+	t10 *int = &42 /* ERROR "cannot take address" */
+	t11 *complex64 = &v
+	t12 complex64 = -(u + *t11) / *&v
+	t13 int = a /* ERROR "shifted operand" */ << d
+	t14 int = i << j /* ERROR "must be unsigned" */ 
+	t15 math /* ERROR "not in selector" */
+	t16 math.xxx /* ERROR "unexported" */
+	t17 math /* ERROR "not a type" */ .Pi
+	t18 float64 = math.Pi * 10.0
+	t19 int = t1 /* ERROR "cannot call" */ ()
+	t20 int = f0 /* ERROR "no value" */ ()
+)
+
+// Various more complex expressions
+var (
+	u1 = x /* ERROR "not an interface" */ .(int)
+	u2 = iface.([]int)
+	u3 = iface.(a /* ERROR "not a type" */ )
+	u4, ok = iface.(int)
+	u5 /* ERROR "assignment count mismatch" */ , ok2, ok3 = iface.(int)
+)
+
+// Constant expression initializations
+var (
+	v1 = 1 /* ERROR "cannot convert" */ + "foo"
+	v2 = c + 255
+	v3 = c + 256 /* ERROR "overflows" */
+	v4 = r + 2147483647
+	v5 = r + 2147483648 /* ERROR "overflows" */
+	v6 = 42
+	v7 = v6 + 2147483647
+	v8 = v6 + 2147483648 /* ERROR "overflows" */
+	v9 = i + 1 << 10
+	v10 byte = 1024 /* ERROR "overflows" */
+	v11 = xx/yy*yy - xx
+	v12 = true && false
+	v13 = nil /* ERROR "use of untyped nil" */
+)
+
+// Multiple assignment expressions
+var (
+	m1a, m1b = 1, 2
+	m2a /* ERROR "assignment count mismatch" */ , m2b, m2c = 1, 2
+	m3a /* ERROR "assignment count mismatch" */ , m3b = 1, 2, 3
+)
+
+// Declaration of parameters and results
+func f0() {}
+func f1(a /* ERROR "not a type" */) {}
+func f2(a, b, c d /* ERROR "not a type" */) {}
+
+func f3() int {}
+func f4() a /* ERROR "not a type" */ {}
+func f5() (a, b, c d /* ERROR "not a type" */) {}
+
+func f6(a, b, c int) complex128 { return 0 }
+
+// Declaration of receivers
+type T struct{}
+
+func (T) m0() {}
+func (*T) m1() {}
+func (x T) m2() {}
+func (x *T) m3() {}
+
+
+// Initialization functions
+func init() {}
+func /* ERROR "no arguments and no return values" */ init(int) {}
+func /* ERROR "no arguments and no return values" */ init() int { return 0 }
+func /* ERROR "no arguments and no return values" */ init(int) int {}
+func (T) init(int) int { return 0 }
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/decls2a.src b/third_party/gofrontend/libgo/go/go/types/testdata/decls2a.src
new file mode 100644
index 0000000..3867be7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/decls2a.src
@@ -0,0 +1,67 @@
+// 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.
+
+// method declarations
+
+package decls2
+
+import "time"
+
+// T1 declared before its methods.
+type T1 struct{
+	f int
+}
+
+func (T1) m() {}
+func (T1) m /* ERROR "redeclared" */ () {}
+func (x *T1) f /* ERROR "field and method" */ () {}
+
+// T2's method declared before the type.
+func (*T2) f /* ERROR "field and method" */ () {}
+
+type T2 struct {
+	f int
+}
+
+// Methods declared without a declared type.
+func (undeclared /* ERROR "undeclared" */) m() {}
+func (x *undeclared /* ERROR "undeclared" */) m() {}
+
+// TODO(gri) try to get rid of double error reporting here
+func (pi /* ERROR "not a type" */) m1() {}
+func (x pi /* ERROR "not a type" */) m2() {}
+func (x *pi /* ERROR "not a type" */ ) m3() {} // TODO(gri) not closing the last /* comment crashes the system
+
+// Blank types.
+type _ struct { m int }
+type _ struct { m int }
+
+// TODO(gri) blank idents not fully checked - disabled for now
+// func (_ /* ERROR "cannot use _" */) m() {}
+// func (_ /* ERROR "cannot use _" */) m() {}
+
+// Methods with receiver base type declared in another file.
+func (T3) m1() {}
+func (*T3) m2() {}
+func (x T3) m3() {}
+func (x *T3) f /* ERROR "field and method" */ () {}
+
+// Methods of non-struct type.
+type T4 func()
+
+func (self T4) m() func() { return self }
+
+// Methods associated with an interface.
+type T5 interface {
+	m() int
+}
+
+func (T5 /* ERROR "invalid receiver" */) m1() {}
+func (T5 /* ERROR "invalid receiver" */) m2() {}
+
+// Methods associated with non-local or unnamed types.
+func (int /* ERROR "non-local type" */ ) m() {}
+func ([ /* ERROR "expected" */ ]int) m() {}
+func (time /* ERROR "expected" */ .Time) m() {}
+func (x interface /* ERROR "expected" */ {}) m() {}
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/decls2b.src b/third_party/gofrontend/libgo/go/go/types/testdata/decls2b.src
new file mode 100644
index 0000000..c7f9ddf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/decls2b.src
@@ -0,0 +1,28 @@
+// 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.
+
+// method declarations
+
+package decls2
+
+const pi = 3.1415
+
+func (T1) m /* ERROR "redeclared" */ () {}
+
+type T3 struct {
+	f *T3
+}
+
+type T6 struct {
+	x int
+}
+
+func (t *T6) m1() int {
+	return t.x
+}
+
+func f() {
+	var t *T6
+	t.m1()
+}
\ No newline at end of file
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/decls3.src b/third_party/gofrontend/libgo/go/go/types/testdata/decls3.src
new file mode 100644
index 0000000..4bc7d41
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/decls3.src
@@ -0,0 +1,231 @@
+// 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.
+
+// embedded types
+
+package decls3
+
+// fields with the same name at the same level cancel each other out
+
+func _() {
+	type (
+		T1 struct { X int }
+		T2 struct { X int }
+		T3 struct { T1; T2 } // X is embedded twice at the same level via T1->X, T2->X
+	)
+
+	var t T3
+	_ = t /* ERROR "no single field or method" */ .X
+}
+
+func _() {
+	type (
+		T1 struct { X int }
+		T2 struct { T1 }
+		T3 struct { T1 }
+		T4 struct { T2; T3 } // X is embedded twice at the same level via T2->T1->X, T3->T1->X
+	)
+
+	var t T4
+	_ = t /* ERROR "no single field or method" */ .X
+}
+
+func issue4355() {
+	type (
+	    T1 struct {X int}
+	    T2 struct {T1}
+	    T3 struct {T2}
+	    T4 struct {T2}
+	    T5 struct {T3; T4} // X is embedded twice at the same level via T3->T2->T1->X, T4->T2->T1->X
+	)	
+
+	var t T5
+	_ = t /* ERROR "no single field or method" */ .X
+}
+
+// Borrowed from the FieldByName test cases in reflect/all_test.go.
+
+type D1 struct {
+	d int
+}
+type D2 struct {
+	d int
+}
+
+type S0 struct {
+	A, B, C int
+	D1
+	D2
+}
+
+type S1 struct {
+	B int
+	S0
+}
+
+type S2 struct {
+	A int
+	*S1
+}
+
+type S1x struct {
+	S1
+}
+
+type S1y struct {
+	S1
+}
+
+type S3 struct {
+	S1x
+	S2
+	D, E int
+	*S1y
+}
+
+type S4 struct {
+	*S4
+	A int
+}
+
+// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
+type S5 struct {
+	S6
+	S7
+	S8
+}
+
+type S6 struct {
+	X int
+}
+
+type S7 S6
+
+type S8 struct {
+	S9
+}
+
+type S9 struct {
+	X int
+	Y int
+}
+
+// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
+type S10 struct {
+	S11
+	S12
+	S13
+}
+
+type S11 struct {
+	S6
+}
+
+type S12 struct {
+	S6
+}
+
+type S13 struct {
+	S8
+}
+
+func _() {
+	_ = struct /* ERROR "no single field or method" */ {}{}.Foo
+	_ = S0{}.A
+	_ = S0 /* ERROR "no single field or method" */ {}.D
+	_ = S1{}.A
+	_ = S1{}.B
+	_ = S1{}.S0
+	_ = S1{}.C
+	_ = S2{}.A
+	_ = S2{}.S1
+	_ = S2{}.B
+	_ = S2{}.C
+	_ = S2 /* ERROR "no single field or method" */ {}.D
+	_ = S3 /* ERROR "no single field or method" */ {}.S1
+	_ = S3{}.A
+	_ = S3 /* ERROR "no single field or method" */ {}.B
+	_ = S3{}.D
+	_ = S3{}.E
+	_ = S4{}.A
+	_ = S4 /* ERROR "no single field or method" */ {}.B
+	_ = S5 /* ERROR "no single field or method" */ {}.X
+	_ = S5{}.Y
+	_ = S10 /* ERROR "no single field or method" */ {}.X
+	_ = S10{}.Y
+}
+
+// Borrowed from the FieldByName benchmark in reflect/all_test.go.
+
+type R0 struct {
+	*R1
+	*R2
+	*R3
+	*R4
+}
+
+type R1 struct {
+	*R5
+	*R6
+	*R7
+	*R8
+}
+
+type R2 R1
+type R3 R1
+type R4 R1
+
+type R5 struct {
+	*R9
+	*R10
+	*R11
+	*R12
+}
+
+type R6 R5
+type R7 R5
+type R8 R5
+
+type R9 struct {
+	*R13
+	*R14
+	*R15
+	*R16
+}
+
+type R10 R9
+type R11 R9
+type R12 R9
+
+type R13 struct {
+	*R17
+	*R18
+	*R19
+	*R20
+}
+
+type R14 R13
+type R15 R13
+type R16 R13
+
+type R17 struct {
+	*R21
+	*R22
+	*R23
+	*R24
+}
+
+type R18 R17
+type R19 R17
+type R20 R17
+
+type R21 struct {
+	X int
+}
+
+type R22 R21
+type R23 R21
+type R24 R21
+
+var _ = R0 /* ERROR "no single field or method" */ {}.X
\ No newline at end of file
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/expr0.src b/third_party/gofrontend/libgo/go/go/types/testdata/expr0.src
new file mode 100644
index 0000000..c3233d3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/expr0.src
@@ -0,0 +1,151 @@
+// 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.
+
+// unary expressions
+
+package expr0 
+
+var (
+	// bool
+	b0 = true
+	b1 bool = b0
+	b2 = !true
+	b3 = !b1
+	b4 bool = !true
+	b5 bool = !b4
+	b6 = +b0 /* ERROR "not defined" */
+	b7 = -b0 /* ERROR "not defined" */
+	b8 = ^b0 /* ERROR "not defined" */
+	b9 = *b0 /* ERROR "cannot indirect" */
+	b10 = &true /* ERROR "cannot take address" */
+	b11 = &b0
+	b12 = <-b0 /* ERROR "cannot receive" */
+
+	// int
+	i0 = 1
+	i1 int = i0
+	i2 = +1
+	i3 = +i0
+	i4 int = +1
+	i5 int = +i4
+	i6 = -1
+	i7 = -i0
+	i8 int = -1
+	i9 int = -i4
+	i10 = !i0 /* ERROR "not defined" */
+	i11 = ^1
+	i12 = ^i0
+	i13 int = ^1
+	i14 int = ^i4
+	i15 = *i0 /* ERROR "cannot indirect" */
+	i16 = &i0
+	i17 = *i16
+	i18 = <-i16 /* ERROR "cannot receive" */
+
+	// uint
+	u0 = uint(1)
+	u1 uint = u0
+	u2 = +1
+	u3 = +u0
+	u4 uint = +1
+	u5 uint = +u4
+	u6 = -1
+	u7 = -u0
+	u8 uint = - /* ERROR "overflows" */ 1
+	u9 uint = -u4
+	u10 = !u0 /* ERROR "not defined" */
+	u11 = ^1
+	u12 = ^i0
+	u13 uint = ^ /* ERROR "overflows" */ 1
+	u14 uint = ^u4
+	u15 = *u0 /* ERROR "cannot indirect" */
+	u16 = &u0
+	u17 = *u16
+	u18 = <-u16 /* ERROR "cannot receive" */
+	u19 = ^uint(0)
+
+	// float64
+	f0 = float64(1)
+	f1 float64 = f0
+	f2 = +1
+	f3 = +f0
+	f4 float64 = +1
+	f5 float64 = +f4 /* ERROR not defined */
+	f6 = -1
+	f7 = -f0
+	f8 float64 = -1
+	f9 float64 = -f4
+	f10 = !f0 /* ERROR "not defined" */
+	f11 = ^1
+	f12 = ^i0
+	f13 float64 = ^1
+	f14 float64 = ^f4 /* ERROR "not defined" */
+	f15 = *f0 /* ERROR "cannot indirect" */
+	f16 = &f0
+	f17 = *u16
+	f18 = <-u16 /* ERROR "cannot receive" */
+
+	// complex128
+	c0 = complex128(1)
+	c1 complex128 = c0
+	c2 = +1
+	c3 = +c0
+	c4 complex128 = +1
+	c5 complex128 = +c4 /* ERROR not defined */
+	c6 = -1
+	c7 = -c0
+	c8 complex128 = -1
+	c9 complex128 = -c4
+	c10 = !c0 /* ERROR "not defined" */
+	c11 = ^1
+	c12 = ^i0
+	c13 complex128 = ^1
+	c14 complex128 = ^c4 /* ERROR "not defined" */
+	c15 = *c0 /* ERROR "cannot indirect" */
+	c16 = &c0
+	c17 = *u16
+	c18 = <-u16 /* ERROR "cannot receive" */
+
+	// string
+	s0 = "foo"
+	s1 = +"foo" /* ERROR "not defined" */
+	s2 = -s0 /* ERROR "not defined" */
+	s3 = !s0 /* ERROR "not defined" */
+	s4 = ^s0 /* ERROR "not defined" */
+	s5 = *s4 /* ERROR "cannot indirect" */
+	s6 = &s4
+	s7 = *s6
+	s8 = <-s7  /* ERROR "cannot receive" */
+
+	// channel
+	ch chan int
+	rc <-chan float64
+	sc chan <- string
+	ch0 = +ch /* ERROR "not defined" */
+	ch1 = -ch /* ERROR "not defined" */
+	ch2 = !ch /* ERROR "not defined" */
+	ch3 = ^ch /* ERROR "not defined" */
+	ch4 = *ch /* ERROR "cannot indirect" */
+	ch5 = &ch
+	ch6 = *ch5
+	ch7 = <-ch
+	ch8 = <-rc
+	ch9 = <-sc /* ERROR "cannot receive" */
+)
+
+// address of composite literals
+type T struct{x, y int}
+
+func f() T { return T{} }
+
+var (
+	_ = &T{1, 2}
+	_ = &[...]int{}
+	_ = &[]int{}
+	_ = &[]int{}
+	_ = &map[string]T{}
+	_ = &(T{1, 2})
+	_ = &((((T{1, 2}))))
+	_ = &f /* ERROR "cannot take address" */ ()
+)
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/expr1.src b/third_party/gofrontend/libgo/go/go/types/testdata/expr1.src
new file mode 100644
index 0000000..8ef0aed
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/expr1.src
@@ -0,0 +1,7 @@
+// 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.
+
+// binary expressions
+
+package expr1
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/expr2.src b/third_party/gofrontend/libgo/go/go/types/testdata/expr2.src
new file mode 100644
index 0000000..674be40
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/expr2.src
@@ -0,0 +1,23 @@
+// 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.
+
+// comparisons
+
+package expr2
+
+func _bool() {
+	const t = true == true
+	const f = true == false
+	_ = t /* ERROR "cannot compare" */ < f
+	_ = 0 /* ERROR "cannot convert" */ == t
+	var b bool
+	var x, y float32
+	b = x < y
+	_ = struct{b bool}{x < y}
+}
+
+// corner cases
+var (
+	v0 = nil /* ERROR "cannot compare" */ == nil
+)
\ No newline at end of file
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/expr3.src b/third_party/gofrontend/libgo/go/go/types/testdata/expr3.src
new file mode 100644
index 0000000..519e3f5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/expr3.src
@@ -0,0 +1,367 @@
+// 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.
+
+// various expressions
+
+package expr3
+
+func shifts1() {
+	var (
+		i0 int
+		u0 uint
+	)
+
+	var (
+		v0 = 1<<0
+		v1 = 1<<i0 /* ERROR "must be unsigned" */
+		v2 = 1<<u0
+		v3 = 1<<"foo" /* ERROR "must be unsigned" */
+		v4 = 1<<- /* ERROR "stupid shift" */ 1
+		v5 = 1<<1025 /* ERROR "stupid shift" */
+		v6 = 1 /* ERROR "overflows" */ <<100
+
+		v10 uint = 1 << 0
+		v11 uint = 1 << u0
+		v12 float32 = 1 /* ERROR "must be integer" */ << u0
+	)
+}
+
+func shifts2() {
+	// TODO(gri) enable commented out tests below.
+	var (
+		s uint = 33
+		i = 1<<s           // 1 has type int
+		j int32 = 1<<s     // 1 has type int32; j == 0
+		k = uint64(1<<s)   // 1 has type uint64; k == 1<<33
+		m int = 1.0<<s     // 1.0 has type int
+	//	n = 1.0<<s != 0    // 1.0 has type int; n == false if ints are 32bits in size
+		o = 1<<s == 2<<s   // 1 and 2 have type int; o == true if ints are 32bits in size
+	//	p = 1<<s == 1 /* ERROR "overflows" */ <<33  // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
+		u = 1.0 /* ERROR "must be integer" */ <<s         // illegal: 1.0 has type float64, cannot shift
+		v float32 = 1 /* ERROR "must be integer" */ <<s   // illegal: 1 has type float32, cannot shift
+		w int64 = 1.0<<33  // 1.0<<33 is a constant shift expression
+	)
+}
+
+// TODO(gri) The error messages below depond on adjusting the spec
+//           to reflect what gc is doing at the moment (the spec
+//           asks for run-time errors at the moment - see issue 4231).
+//
+func indexes() {
+	_ = 1 /* ERROR "cannot index" */ [0]
+	_ = indexes /* ERROR "cannot index" */ [0]
+	_ = ( /* ERROR "cannot slice" */ 12 + 3)[1:2]
+
+	var a [10]int
+	_ = a[true /* ERROR "must be integer" */ ]
+	_ = a["foo" /* ERROR "must be integer" */ ]
+	_ = a[1.1 /* ERROR "must be integer" */ ]
+	_ = a[1.0]
+	_ = a[- /* ERROR "index .* negative" */ 1]
+	_ = a[- /* ERROR "index .* negative" */ 1 :]
+	_ = a[: - /* ERROR "index .* negative" */ 1]
+	var a0 int
+	a0 = a[0]
+	var a1 int32
+	a1 = a /* ERROR "cannot assign" */ [1] 
+	_ = a[9]
+	_ = a[10 /* ERROR "index .* out of bounds" */ ]
+	_ = a[1 /* ERROR "stupid index" */ <<100]
+	_ = a[10:]
+	_ = a[:10]
+	_ = a[10:10]
+	_ = a[11 /* ERROR "index .* out of bounds" */ :]
+	_ = a[: 11 /* ERROR "index .* out of bounds" */ ]
+	_ = a[: 1 /* ERROR "stupid index" */ <<100]
+
+	pa := &a
+	_ = pa[9]
+	_ = pa[10 /* ERROR "index .* out of bounds" */ ]
+	_ = pa[1 /* ERROR "stupid index" */ <<100]
+	_ = pa[10:]
+	_ = pa[:10]
+	_ = pa[10:10]
+	_ = pa[11 /* ERROR "index .* out of bounds" */ :]
+	_ = pa[: 11 /* ERROR "index .* out of bounds" */ ]
+	_ = pa[: 1 /* ERROR "stupid index" */ <<100]
+
+	var b [0]int
+	_ = b[0 /* ERROR "index .* out of bounds" */ ]
+	_ = b[:]
+	_ = b[0:]
+	_ = b[:0]
+	_ = b[0:0]
+
+	var s []int
+	_ = s[- /* ERROR "index .* negative" */ 1]
+	_ = s[- /* ERROR "index .* negative" */ 1 :]
+	_ = s[: - /* ERROR "index .* negative" */ 1]
+	_ = s[0]
+	_ = s[1 : 2]
+	_ = s[2 /* ERROR "inverted slice range" */ : 1]
+	_ = s[2 :]
+	_ = s[: 1 /* ERROR "stupid index" */ <<100]
+	_ = s[1 /* ERROR "stupid index" */ <<100 :]
+	_ = s[1 /* ERROR "stupid index" */ <<100 : 1 /* ERROR "stupid index" */ <<100]
+
+	var t string
+	_ = t[- /* ERROR "index .* negative" */ 1]
+	_ = t[- /* ERROR "index .* negative" */ 1 :]
+	_ = t[: - /* ERROR "index .* negative" */ 1]
+	var t0 byte
+	t0 = t[0]
+	var t1 rune
+	t1 = t /* ERROR "cannot assign" */ [2]
+	_ = ("foo" + "bar")[5]
+	_ = ("foo" + "bar")[6 /* ERROR "index .* out of bounds" */ ]
+
+	const c = "foo"
+	_ = c[- /* ERROR "index .* negative" */ 1]
+	_ = c[- /* ERROR "index .* negative" */ 1 :]
+	_ = c[: - /* ERROR "index .* negative" */ 1]
+	var c0 byte
+	c0 = c[0]
+	var c2 float32
+	c2 = c /* ERROR "cannot assign" */ [2]
+	_ = c[3 /* ERROR "index .* out of bounds" */ ]
+	_ = ""[0 /* ERROR "index .* out of bounds" */ ]
+
+	_ = s[1<<30] // no compile-time error here
+}
+
+type T struct {
+	x int
+}
+
+func (*T) m() {}
+
+func method_expressions() {
+	_ = T /* ERROR "no single field or method" */ .a
+	_ = T /* ERROR "has no method" */ .x
+	_ = T.m
+	var f func(*T) = (*T).m
+	var g func(*T) = ( /* ERROR "cannot assign" */ T).m
+}
+
+func struct_literals() {
+	type T0 struct {
+		a, b, c int
+	}
+
+	type T1 struct {
+		T0
+		a, b int
+		u float64
+		s string
+	}
+
+	// keyed elements
+	_ = T1{}
+	_ = T1{a: 0, 1 /* ERROR "mixture of .* elements" */ }
+	_ = T1{aa /* ERROR "unknown field" */ : 0}
+	_ = T1{1 /* ERROR "invalid field name" */ : 0}
+	_ = T1{a: 0, s: "foo", u: 0, a /* ERROR "duplicate field" */: 10}
+	_ = T1{a: "foo" /* ERROR "cannot use" */ }
+	_ = T1{c /* ERROR "unknown field" */ : 0}
+	_ = T1{T0: { /* ERROR "missing type" */ }}
+	_ = T1{T0: T0{}}
+	_ = T1{T0 /* ERROR "invalid field name" */ .a: 0}
+
+	// unkeyed elements
+	_ = T0{1, 2, 3}
+	_ = T0{1, b /* ERROR "mixture" */ : 2, 3}
+	_ = T0{1, 2} /* ERROR "too few values" */
+	_ = T0{1, 2, 3, 4  /* ERROR "too many values" */ }
+	_ = T0{1, "foo" /* ERROR "cannot use" */, 3.4  /* ERROR "cannot use" */}
+}
+
+func array_literals() {
+	type A0 [0]int
+	_ = A0{}
+	_ = A0{0 /* ERROR "index .* out of bounds" */}
+	_ = A0{0 /* ERROR "index .* out of bounds" */ : 0}
+
+	type A1 [10]int
+	_ = A1{}
+	_ = A1{0, 1, 2}
+	_ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+	_ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /* ERROR "index .* out of bounds" */ }
+	_ = A1{- /* ERROR "index .* negative" */ 1: 0}
+	_ = A1{8: 8, 9}
+	_ = A1{8: 8, 9, 10 /* ERROR "index .* out of bounds" */ }
+	_ = A1{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	_ = A1{5: 5, 6, 7, 3: 3, 4}
+	_ = A1{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
+	_ = A1{10 /* ERROR "index .* out of bounds" */ : 10, 10 /* ERROR "index .* out of bounds" */ : 10}
+	_ = A1{5: 5, 6, 7, 3: 3, 1 /* ERROR "stupid index" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
+	_ = A1{5: 5, 6, 7, 4: 4, 1 /* ERROR "stupid index" */ <<100: 4}
+	_ = A1{2.0}
+	_ = A1{2.1 /* ERROR "cannot use" */ }
+	_ = A1{"foo" /* ERROR "cannot use" */ }
+
+	a0 := [...]int{}
+	assert(len(a0) == 0)
+	
+	a1 := [...]int{0, 1, 2}
+	assert(len(a1) == 3)
+	var a13 [3]int
+	var a14 [4]int
+	a13 = a1
+	a14 = a1 /* ERROR "cannot assign" */
+	
+	a2 := [...]int{- /* ERROR "index .* negative" */ 1: 0}
+
+	a3 := [...]int{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	assert(len(a3) == 5) // somewhat arbitrary
+
+	a4 := [...]complex128{0, 1, 2, 1<<10-2: -1i, 1i, 400: 10, 12, 14}
+	assert(len(a4) == 1024)
+
+	// from the spec
+	type Point struct { x, y float32 }
+	_ = [...]Point{Point{1.5, -3.5}, Point{0, 0}}
+	_ = [...]Point{{1.5, -3.5}, {0, 0}}
+	_ = [][]int{[]int{1, 2, 3}, []int{4, 5}}
+	_ = [][]int{{1, 2, 3}, {4, 5}}
+	_ = [...]*Point{&Point{1.5, -3.5}, &Point{0, 0}}
+	_ = [...]*Point{{1.5, -3.5}, {0, 0}}
+}
+
+func slice_literals() {
+	type S0 []int
+	_ = S0{}
+	_ = S0{0, 1, 2}
+	_ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+	_ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+	_ = S0{- /* ERROR "index .* negative" */ 1: 0}
+	_ = S0{8: 8, 9}
+	_ = S0{8: 8, 9, 10}
+	_ = S0{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	_ = S0{5: 5, 6, 7, 3: 3, 4}
+	_ = S0{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
+	_ = S0{10: 10, 10 /* ERROR "duplicate index" */ : 10}
+	_ = S0{5: 5, 6, 7, 3: 3, 1 /* ERROR "stupid index" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
+	_ = S0{5: 5, 6, 7, 4: 4, 1 /* ERROR "stupid index" */ <<100: 4}
+	_ = S0{2.0}
+	_ = S0{2.1 /* ERROR "cannot use" */ }
+	_ = S0{"foo" /* ERROR "cannot use" */ }
+
+	// indices must be resolved correctly
+	// (for details, see comment in go/parser/parser.go, method parseElement)
+	index1 := 1
+	_ = S0{index1: 1}
+	_ = S0{index2: 2}
+	_ = S0{index3 /* ERROR "undeclared name" */ : 3}
+}
+
+var index2 int = 2
+
+func map_literals() {
+	type M0 map[string]int
+
+	_ = M0{}
+	_ = M0{1 /* ERROR "missing key" */ }
+	_ = M0{1 /* ERROR "cannot use .* as string key" */ : 2}
+	_ = M0{"foo": "bar" /* ERROR "cannot use .* as int value" */ }
+	_ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 }
+
+	// map keys must be resolved correctly
+	// (for detials, see comment in go/parser/parser.go, method parseElement)
+	key1 := "foo"
+	_ = M0{key1: 1}
+	_ = M0{key2: 2}
+	_ = M0{key3 /* ERROR "undeclared name" */ : 2}
+}
+
+var key2 string = "bar"
+
+type I interface {
+	m()
+}
+
+type I2 interface {
+	m(int)
+}
+
+type T1 struct{}
+type T2 struct{}
+
+func (T2) m(int) {}
+
+func type_asserts() {
+	var x int
+	_ = x /* ERROR "not an interface" */ .(int)
+
+	var e interface{}
+	var ok bool
+	x, ok = e.(int)
+
+	var t I
+	_ = t /* ERROR "use of .* outside type switch" */ .(type)
+	_ = t.(T)
+	_ = t.(T1 /* ERROR "missing method m" */ )
+	_ = t.(T2 /* ERROR "wrong type for method m" */ )
+	_ = t.(I2 /* ERROR "wrong type for method m" */ )
+}
+
+func f0() {}
+func f1(x int) {}
+func f2(u float32, s string) {}
+func fs(s []byte) {}
+func fv(x ...int) {}
+func fi(x ... interface{}) {}
+
+func g0() {}
+func g1() int { return 0}
+func g2() (u float32, s string) { return }
+func gs() []byte { return nil }
+
+func _calls() {
+	var x int
+	var y float32
+	var s []int
+
+	f0()
+	_ = f0 /* ERROR "used as value" */ ()
+	f0(g0 /* ERROR "too many arguments" */ )
+
+	f1(0)
+	f1(x)
+	f1(10.0)
+	f1 /* ERROR "too few arguments" */ ()
+	f1(x, y /* ERROR "too many arguments" */ )
+	f1(s /* ERROR "cannot assign" */ )
+	f1(x ... /* ERROR "cannot use ..." */ )
+	f1(g0 /* ERROR "used as value" */ ())
+	f1(g1())
+	// f1(g2()) // TODO(gri) missing position in error message
+
+	f2 /* ERROR "too few arguments" */ ()
+	f2 /* ERROR "too few arguments" */ (3.14)
+	f2(3.14, "foo")
+	f2(x /* ERROR "cannot assign" */ , "foo")
+	f2(g0 /* ERROR "used as value" */ ())
+	f2 /* ERROR "too few arguments" */ (g1 /* ERROR "cannot assign" */ ())
+	f2(g2())
+
+	fs /* ERROR "too few arguments" */ ()
+	fs(g0 /* ERROR "used as value" */ ())
+	fs(g1 /* ERROR "cannot assign" */ ())
+	// fs(g2()) // TODO(gri) missing position in error message
+	fs(gs())
+
+	fv()
+	fv(1, 2.0, x)
+	fv(s /* ERROR "cannot assign" */ )
+	fv(s...)
+	fv(1, s /* ERROR "can only use ... with matching parameter" */ ...)
+	fv(gs /* ERROR "cannot assign" */ ())
+	fv(gs /* ERROR "cannot assign" */ ()...)
+
+	fi()
+	fi(1, 2.0, x, 3.14, "foo")
+	fi(g2())
+	fi(0, g2)
+	fi(0, g2 /* ERROR "2-valued expression" */ ())
+}
\ No newline at end of file
diff --git a/third_party/gofrontend/libgo/go/go/types/testdata/stmt0.src b/third_party/gofrontend/libgo/go/go/types/testdata/stmt0.src
new file mode 100644
index 0000000..ca36834
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/go/types/testdata/stmt0.src
@@ -0,0 +1,274 @@
+// 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.
+
+// statements
+
+package stmt0
+
+func _() {
+	b, i, f, c, s := false, 1, 1.0, 1i, "foo"
+	b = i /* ERROR "cannot assign" */
+	i = f /* ERROR "cannot assign" */
+	f = c /* ERROR "cannot assign" */
+	c = s /* ERROR "cannot assign" */
+	s = b /* ERROR "cannot assign" */
+
+	v0 /* ERROR "mismatch" */, v1, v2 := 1, 2, 3, 4
+
+	b = true
+
+	i += 1
+	i += "foo" /* ERROR "cannot convert.*int" */
+
+	f -= 1
+	f -= "foo" /* ERROR "cannot convert.*float64" */
+
+	c *= 1
+	c /= 0 /* ERROR "division by zero" */
+
+	s += "bar"
+	s += 1 /* ERROR "cannot convert.*string" */
+}
+
+func _incdecs() {
+	const c = 3.14
+	c /* ERROR "cannot assign" */ ++
+	s := "foo"
+	s /* ERROR "cannot convert" */ --
+	3.14 /* ERROR "cannot assign" */ ++
+	var (
+		x int
+		y float32
+		z complex128
+	)
+	x++
+	y--
+	z++
+}
+
+func _sends() {
+	var ch chan int
+	var rch <-chan int
+	var x int
+	x /* ERROR "cannot send" */ <- x
+	rch /* ERROR "cannot send" */ <- x
+	ch /* ERROR "cannot send" */ <- "foo"
+	ch <- x
+}
+
+func _selects() {
+	select {}
+	var (
+		ch chan int
+		sc chan <- bool
+		x int
+	)
+	select {
+	case <-ch:
+		ch <- x
+	case t, ok := <-ch:
+		x = t
+	case <-sc /* ERROR "cannot receive from send-only channel" */ :
+	}
+	select {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+}
+
+func _gos() {
+	go 1 /* ERROR "expected function/method call" */
+	go _gos()
+	var c chan int
+	go close(c)
+	go len(c) // TODO(gri) this should not be legal
+}
+
+func _defers() {
+	defer 1 /* ERROR "expected function/method call" */
+	defer _defers()
+	var c chan int
+	defer close(c)
+	defer len(c) // TODO(gri) this should not be legal
+}
+
+func _switches() {
+	var x int
+
+	switch x {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+
+	switch {
+	case 1  /* ERROR "cannot convert" */ :
+	}
+
+	switch int32(x) {
+	case 1, 2:
+	case x /* ERROR "cannot compare" */ :
+	}
+
+	switch x {
+	case 1 /* ERROR "overflows int" */ << 100:
+	}
+
+	switch x {
+	case 1:
+	case 1 /* ERROR "duplicate case" */ :
+	case 2, 3, 4:
+	case 1 /* ERROR "duplicate case" */ :
+	}
+
+	// TODO(gri) duplicate 64bit values that don't fit into an int64 are not yet detected
+	switch uint64(x) {
+	case 1<<64-1:
+	case 1<<64-1:
+	}
+}
+
+type I interface {
+	m()
+}
+
+type I2 interface {
+	m(int)
+}
+
+type T struct{}
+type T1 struct{}
+type T2 struct{}
+
+func (T) m() {}
+func (T2) m(int) {}
+
+func _typeswitches() {
+	var i int
+	var x interface{}
+
+	switch x.(type) {}
+	switch (x /* ERROR "outside type switch" */ .(type)) {}
+
+	switch x.(type) {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+
+	switch x := x.(type) {}
+
+	switch x := x.(type) {
+	case int:
+		var y int = x
+	}
+
+	switch x := i /* ERROR "not an interface" */ .(type) {}
+
+	switch t := x.(type) {
+	case nil:
+		var v bool = t /* ERROR "cannot assign" */
+	case int:
+		var v int = t
+	case float32, complex64:
+		var v float32 = t /* ERROR "cannot assign" */
+	default:
+		var v float32 = t /* ERROR "cannot assign" */
+	}
+
+	var t I
+	switch t.(type) {
+	case T:
+	case T1 /* ERROR "missing method m" */ :
+	case T2 /* ERROR "wrong type for method m" */ :
+	case I2 /* ERROR "wrong type for method m" */ :
+	}
+}
+
+func _rangeloops() {
+	var (
+		x int
+		a [10]float32
+		b []string
+		p *[10]complex128
+		pp **[10]complex128
+		s string
+		m map[int]bool
+		c chan int
+		sc chan<- int
+		rc <-chan int
+	)
+
+	for _ = range x /* ERROR "cannot range over" */ {}
+	for i := range x /* ERROR "cannot range over" */ {}
+
+	for i := range a {
+		var ii int
+		ii = i
+	}
+	for i, x := range a {
+		var ii int
+		ii = i
+		var xx float64
+		xx = x /* ERROR "cannot assign" */
+	}
+	var ii int
+	var xx float32
+	for ii, xx := range a {}
+
+	for i := range b {
+		var ii int
+		ii = i
+	}
+	for i, x := range b {
+		var ii int
+		ii = i
+		var xx string
+		xx = x
+	}
+
+	for i := range s {
+		var ii int
+		ii = i
+	}
+	for i, x := range s {
+		var ii int
+		ii = i
+		var xx rune
+		xx = x
+	}
+
+	for _, x := range p {
+		var xx complex128
+		xx = x
+	}
+
+	for _, x := range pp /* ERROR "cannot range over" */ {}
+
+	for k := range m {
+		var kk int32
+		kk = k /* ERROR "cannot assign" */
+	}
+	for k, v := range m {
+		var kk int
+		kk = k
+		if v {}
+	}
+
+	for _, _ /* ERROR "only one iteration variable" */ = range c {}
+	for e := range c {
+		var ee int
+		ee = e
+	}
+	for _ = range sc /* ERROR "cannot range over send-only channel" */ {}
+	for _ = range rc {}
+
+	// constant strings
+	const cs = "foo"
+	for i, x := range cs {}
+	for i, x := range "" {
+		var ii int
+		ii = i
+		var xx rune
+		xx = x
+	}
+}
\ No newline at end of file
diff --git a/third_party/gofrontend/libgo/go/hash/adler32/adler32.go b/third_party/gofrontend/libgo/go/hash/adler32/adler32.go
new file mode 100644
index 0000000..7c80796
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/adler32/adler32.go
@@ -0,0 +1,78 @@
+// 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 adler32 implements the Adler-32 checksum.
+//
+// It is defined in RFC 1950:
+//	Adler-32 is composed of two sums accumulated per byte: s1 is
+//	the sum of all bytes, s2 is the sum of all s1 values. Both sums
+//	are done modulo 65521. s1 is initialized to 1, s2 to zero.  The
+//	Adler-32 checksum is stored as s2*65536 + s1 in most-
+//	significant-byte first (network) order.
+package adler32
+
+import "hash"
+
+const (
+	// mod is the largest prime that is less than 65536.
+	mod = 65521
+	// nmax is the largest n such that
+	// 255 * n * (n+1) / 2 + (n+1) * (mod-1) <= 2^32-1.
+	// It is mentioned in RFC 1950 (search for "5552").
+	nmax = 5552
+)
+
+// The size of an Adler-32 checksum in bytes.
+const Size = 4
+
+// digest represents the partial evaluation of a checksum.
+// The low 16 bits are s1, the high 16 bits are s2.
+type digest uint32
+
+func (d *digest) Reset() { *d = 1 }
+
+// New returns a new hash.Hash32 computing the Adler-32 checksum.
+func New() hash.Hash32 {
+	d := new(digest)
+	d.Reset()
+	return d
+}
+
+func (d *digest) Size() int { return Size }
+
+func (d *digest) BlockSize() int { return 1 }
+
+// Add p to the running checksum d.
+func update(d digest, p []byte) digest {
+	s1, s2 := uint32(d&0xffff), uint32(d>>16)
+	for len(p) > 0 {
+		var q []byte
+		if len(p) > nmax {
+			p, q = p[:nmax], p[nmax:]
+		}
+		for _, x := range p {
+			s1 += uint32(x)
+			s2 += s1
+		}
+		s1 %= mod
+		s2 %= mod
+		p = q
+	}
+	return digest(s2<<16 | s1)
+}
+
+func (d *digest) Write(p []byte) (nn int, err error) {
+	*d = update(*d, p)
+	return len(p), nil
+}
+
+func (d *digest) Sum32() uint32 { return uint32(*d) }
+
+func (d *digest) Sum(in []byte) []byte {
+	s := uint32(*d)
+	return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
+}
+
+// Checksum returns the Adler-32 checksum of data.
+func Checksum(data []byte) uint32 { return uint32(update(1, data)) }
diff --git a/third_party/gofrontend/libgo/go/hash/adler32/adler32_test.go b/third_party/gofrontend/libgo/go/hash/adler32/adler32_test.go
new file mode 100644
index 0000000..0e9c938
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/adler32/adler32_test.go
@@ -0,0 +1,105 @@
+// 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 adler32
+
+import (
+	"strings"
+	"testing"
+)
+
+var golden = []struct {
+	out uint32
+	in  string
+}{
+	{0x00000001, ""},
+	{0x00620062, "a"},
+	{0x012600c4, "ab"},
+	{0x024d0127, "abc"},
+	{0x03d8018b, "abcd"},
+	{0x05c801f0, "abcde"},
+	{0x081e0256, "abcdef"},
+	{0x0adb02bd, "abcdefg"},
+	{0x0e000325, "abcdefgh"},
+	{0x118e038e, "abcdefghi"},
+	{0x158603f8, "abcdefghij"},
+	{0x3f090f02, "Discard medicine more than two years old."},
+	{0x46d81477, "He who has a shady past knows that nice guys finish last."},
+	{0x40ee0ee1, "I wouldn't marry him with a ten foot pole."},
+	{0x16661315, "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+	{0x5b2e1480, "The days of the digital watch are numbered.  -Tom Stoppard"},
+	{0x8c3c09ea, "Nepal premier won't resign."},
+	{0x45ac18fd, "For every action there is an equal and opposite government program."},
+	{0x53c61462, "His money is twice tainted: 'taint yours and 'taint mine."},
+	{0x7e511e63, "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+	{0xe4801a6a, "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+	{0x61b507df, "size:  a.out:  bad magic"},
+	{0xb8631171, "The major problem is with sendmail.  -Mark Horton"},
+	{0x8b5e1904, "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
+	{0x7cc6102b, "If the enemy is within range, then so are you."},
+	{0x700318e7, "It's well we cannot hear the screams/That we create in others' dreams."},
+	{0x1e601747, "You remind me of a TV show, but that's all right: I watch it anyway."},
+	{0xb55b0b09, "C is as portable as Stonehedge!!"},
+	{0x39111dd0, "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+	{0x91dd304f, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
+	{0x2e5d1316, "How can you write a big system without C++?  -Paul Glick"},
+	{0xd0201df6, "'Invariant assertions' is the most elegant programming technique!  -Tom Szymanski"},
+	{0x211297c8, strings.Repeat("\xff", 5548) + "8"},
+	{0xbaa198c8, strings.Repeat("\xff", 5549) + "9"},
+	{0x553499be, strings.Repeat("\xff", 5550) + "0"},
+	{0xf0c19abe, strings.Repeat("\xff", 5551) + "1"},
+	{0x8d5c9bbe, strings.Repeat("\xff", 5552) + "2"},
+	{0x2af69cbe, strings.Repeat("\xff", 5553) + "3"},
+	{0xc9809dbe, strings.Repeat("\xff", 5554) + "4"},
+	{0x69189ebe, strings.Repeat("\xff", 5555) + "5"},
+	{0x86af0001, strings.Repeat("\x00", 1e5)},
+	{0x79660b4d, strings.Repeat("a", 1e5)},
+	{0x110588ee, strings.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1e4)},
+}
+
+// checksum is a slow but simple implementation of the Adler-32 checksum.
+// It is a straight port of the sample code in RFC 1950 section 9.
+func checksum(p []byte) uint32 {
+	s1, s2 := uint32(1), uint32(0)
+	for _, x := range p {
+		s1 = (s1 + uint32(x)) % mod
+		s2 = (s2 + s1) % mod
+	}
+	return s2<<16 | s1
+}
+
+func TestGolden(t *testing.T) {
+	for _, g := range golden {
+		in := g.in
+		if len(in) > 220 {
+			in = in[:100] + "..." + in[len(in)-100:]
+		}
+		p := []byte(g.in)
+		if got := checksum(p); got != g.out {
+			t.Errorf("simple implementation: checksum(%q) = 0x%x want 0x%x", in, got, g.out)
+			continue
+		}
+		if got := Checksum(p); got != g.out {
+			t.Errorf("optimized implementation: Checksum(%q) = 0x%x want 0x%x", in, got, g.out)
+			continue
+		}
+	}
+}
+
+func BenchmarkAdler32KB(b *testing.B) {
+	b.SetBytes(1024)
+	data := make([]byte, 1024)
+	for i := range data {
+		data[i] = byte(i)
+	}
+	h := New()
+	in := make([]byte, 0, h.Size())
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		h.Reset()
+		h.Write(data)
+		h.Sum(in)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/hash/crc32/crc32.go b/third_party/gofrontend/libgo/go/hash/crc32/crc32.go
new file mode 100644
index 0000000..a2a21a0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/crc32/crc32.go
@@ -0,0 +1,135 @@
+// 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 crc32 implements the 32-bit cyclic redundancy check, or CRC-32,
+// checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for
+// information.
+package crc32
+
+import (
+	"hash"
+	"sync"
+)
+
+// The size of a CRC-32 checksum in bytes.
+const Size = 4
+
+// Predefined polynomials.
+const (
+	// Far and away the most common CRC-32 polynomial.
+	// Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, mpeg-2, ...
+	IEEE = 0xedb88320
+
+	// Castagnoli's polynomial, used in iSCSI.
+	// Has better error detection characteristics than IEEE.
+	// http://dx.doi.org/10.1109/26.231911
+	Castagnoli = 0x82f63b78
+
+	// Koopman's polynomial.
+	// Also has better error detection characteristics than IEEE.
+	// http://dx.doi.org/10.1109/DSN.2002.1028931
+	Koopman = 0xeb31d82e
+)
+
+// Table is a 256-word table representing the polynomial for efficient processing.
+type Table [256]uint32
+
+// castagnoliTable points to a lazily initialized Table for the Castagnoli
+// polynomial. MakeTable will always return this value when asked to make a
+// Castagnoli table so we can compare against it to find when the caller is
+// using this polynomial.
+var castagnoliTable *Table
+var castagnoliOnce sync.Once
+
+func castagnoliInit() {
+	castagnoliTable = makeTable(Castagnoli)
+}
+
+// IEEETable is the table for the IEEE polynomial.
+var IEEETable = makeTable(IEEE)
+
+// MakeTable returns the Table constructed from the specified polynomial.
+func MakeTable(poly uint32) *Table {
+	switch poly {
+	case IEEE:
+		return IEEETable
+	case Castagnoli:
+		castagnoliOnce.Do(castagnoliInit)
+		return castagnoliTable
+	}
+	return makeTable(poly)
+}
+
+// makeTable returns the Table constructed from the specified polynomial.
+func makeTable(poly uint32) *Table {
+	t := new(Table)
+	for i := 0; i < 256; i++ {
+		crc := uint32(i)
+		for j := 0; j < 8; j++ {
+			if crc&1 == 1 {
+				crc = (crc >> 1) ^ poly
+			} else {
+				crc >>= 1
+			}
+		}
+		t[i] = crc
+	}
+	return t
+}
+
+// digest represents the partial evaluation of a checksum.
+type digest struct {
+	crc uint32
+	tab *Table
+}
+
+// New creates a new hash.Hash32 computing the CRC-32 checksum
+// using the polynomial represented by the Table.
+func New(tab *Table) hash.Hash32 { return &digest{0, tab} }
+
+// NewIEEE creates a new hash.Hash32 computing the CRC-32 checksum
+// using the IEEE polynomial.
+func NewIEEE() hash.Hash32 { return New(IEEETable) }
+
+func (d *digest) Size() int { return Size }
+
+func (d *digest) BlockSize() int { return 1 }
+
+func (d *digest) Reset() { d.crc = 0 }
+
+func update(crc uint32, tab *Table, p []byte) uint32 {
+	crc = ^crc
+	for _, v := range p {
+		crc = tab[byte(crc)^v] ^ (crc >> 8)
+	}
+	return ^crc
+}
+
+// Update returns the result of adding the bytes in p to the crc.
+func Update(crc uint32, tab *Table, p []byte) uint32 {
+	if tab == castagnoliTable {
+		return updateCastagnoli(crc, p)
+	}
+	return update(crc, tab, p)
+}
+
+func (d *digest) Write(p []byte) (n int, err error) {
+	d.crc = Update(d.crc, d.tab, p)
+	return len(p), nil
+}
+
+func (d *digest) Sum32() uint32 { return d.crc }
+
+func (d *digest) Sum(in []byte) []byte {
+	s := d.Sum32()
+	return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
+}
+
+// Checksum returns the CRC-32 checksum of data
+// using the polynomial represented by the Table.
+func Checksum(data []byte, tab *Table) uint32 { return Update(0, tab, data) }
+
+// ChecksumIEEE returns the CRC-32 checksum of data
+// using the IEEE polynomial.
+func ChecksumIEEE(data []byte) uint32 { return update(0, IEEETable, data) }
diff --git a/third_party/gofrontend/libgo/go/hash/crc32/crc32_amd64x.go b/third_party/gofrontend/libgo/go/hash/crc32/crc32_amd64x.go
new file mode 100644
index 0000000..b7e3599
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/crc32/crc32_amd64x.go
@@ -0,0 +1,27 @@
+// 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.
+
+// +build amd64 amd64p32
+
+package crc32
+
+// This file contains the code to call the SSE 4.2 version of the Castagnoli
+// CRC.
+
+// haveSSE42 is defined in crc_amd64.s and uses CPUID to test for SSE 4.2
+// support.
+func haveSSE42() bool
+
+// castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32
+// instruction.
+func castagnoliSSE42(crc uint32, p []byte) uint32
+
+var sse42 = haveSSE42()
+
+func updateCastagnoli(crc uint32, p []byte) uint32 {
+	if sse42 {
+		return castagnoliSSE42(crc, p)
+	}
+	return update(crc, castagnoliTable, p)
+}
diff --git a/third_party/gofrontend/libgo/go/hash/crc32/crc32_generic.go b/third_party/gofrontend/libgo/go/hash/crc32/crc32_generic.go
new file mode 100644
index 0000000..c3fdcd6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/crc32/crc32_generic.go
@@ -0,0 +1,14 @@
+// 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.
+
+// +build 386 arm
+
+package crc32
+
+// The file contains the generic version of updateCastagnoli which just calls
+// the software implementation.
+
+func updateCastagnoli(crc uint32, p []byte) uint32 {
+	return update(crc, castagnoliTable, p)
+}
diff --git a/third_party/gofrontend/libgo/go/hash/crc32/crc32_test.go b/third_party/gofrontend/libgo/go/hash/crc32/crc32_test.go
new file mode 100644
index 0000000..75dc26e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/crc32/crc32_test.go
@@ -0,0 +1,99 @@
+// 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 crc32
+
+import (
+	"io"
+	"testing"
+)
+
+type test struct {
+	ieee, castagnoli uint32
+	in               string
+}
+
+var golden = []test{
+	{0x0, 0x0, ""},
+	{0xe8b7be43, 0xc1d04330, "a"},
+	{0x9e83486d, 0xe2a22936, "ab"},
+	{0x352441c2, 0x364b3fb7, "abc"},
+	{0xed82cd11, 0x92c80a31, "abcd"},
+	{0x8587d865, 0xc450d697, "abcde"},
+	{0x4b8e39ef, 0x53bceff1, "abcdef"},
+	{0x312a6aa6, 0xe627f441, "abcdefg"},
+	{0xaeef2a50, 0xa9421b7, "abcdefgh"},
+	{0x8da988af, 0x2ddc99fc, "abcdefghi"},
+	{0x3981703a, 0xe6599437, "abcdefghij"},
+	{0x6b9cdfe7, 0xb2cc01fe, "Discard medicine more than two years old."},
+	{0xc90ef73f, 0xe28207f, "He who has a shady past knows that nice guys finish last."},
+	{0xb902341f, 0xbe93f964, "I wouldn't marry him with a ten foot pole."},
+	{0x42080e8, 0x9e3be0c3, "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+	{0x154c6d11, 0xf505ef04, "The days of the digital watch are numbered.  -Tom Stoppard"},
+	{0x4c418325, 0x85d3dc82, "Nepal premier won't resign."},
+	{0x33955150, 0xc5142380, "For every action there is an equal and opposite government program."},
+	{0x26216a4b, 0x75eb77dd, "His money is twice tainted: 'taint yours and 'taint mine."},
+	{0x1abbe45e, 0x91ebe9f7, "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+	{0xc89a94f7, 0xf0b1168e, "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+	{0xab3abe14, 0x572b74e2, "size:  a.out:  bad magic"},
+	{0xbab102b6, 0x8a58a6d5, "The major problem is with sendmail.  -Mark Horton"},
+	{0x999149d7, 0x9c426c50, "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
+	{0x6d52a33c, 0x735400a4, "If the enemy is within range, then so are you."},
+	{0x90631e8d, 0xbec49c95, "It's well we cannot hear the screams/That we create in others' dreams."},
+	{0x78309130, 0xa95a2079, "You remind me of a TV show, but that's all right: I watch it anyway."},
+	{0x7d0a377f, 0xde2e65c5, "C is as portable as Stonehedge!!"},
+	{0x8c79fd79, 0x297a88ed, "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+	{0xa20b7167, 0x66ed1d8b, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
+	{0x8e0bb443, 0xdcded527, "How can you write a big system without C++?  -Paul Glick"},
+}
+
+func TestGolden(t *testing.T) {
+	castagnoliTab := MakeTable(Castagnoli)
+
+	for _, g := range golden {
+		ieee := NewIEEE()
+		io.WriteString(ieee, g.in)
+		s := ieee.Sum32()
+		if s != g.ieee {
+			t.Errorf("IEEE(%s) = 0x%x want 0x%x", g.in, s, g.ieee)
+		}
+
+		castagnoli := New(castagnoliTab)
+		io.WriteString(castagnoli, g.in)
+		s = castagnoli.Sum32()
+		if s != g.castagnoli {
+			t.Errorf("Castagnoli(%s) = 0x%x want 0x%x", g.in, s, g.castagnoli)
+		}
+
+		if len(g.in) > 0 {
+			// The SSE4.2 implementation of this has code to deal
+			// with misaligned data so we ensure that we test that
+			// too.
+			castagnoli = New(castagnoliTab)
+			io.WriteString(castagnoli, g.in[:1])
+			io.WriteString(castagnoli, g.in[1:])
+			s = castagnoli.Sum32()
+			if s != g.castagnoli {
+				t.Errorf("Castagnoli[misaligned](%s) = 0x%x want 0x%x", g.in, s, g.castagnoli)
+			}
+		}
+	}
+}
+
+func BenchmarkCrc32KB(b *testing.B) {
+	b.SetBytes(1024)
+	data := make([]byte, 1024)
+	for i := range data {
+		data[i] = byte(i)
+	}
+	h := NewIEEE()
+	in := make([]byte, 0, h.Size())
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		h.Reset()
+		h.Write(data)
+		h.Sum(in)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/hash/crc64/crc64.go b/third_party/gofrontend/libgo/go/hash/crc64/crc64.go
new file mode 100644
index 0000000..6925867
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/crc64/crc64.go
@@ -0,0 +1,87 @@
+// 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 crc64 implements the 64-bit cyclic redundancy check, or CRC-64,
+// checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for
+// information.
+package crc64
+
+import "hash"
+
+// The size of a CRC-64 checksum in bytes.
+const Size = 8
+
+// Predefined polynomials.
+const (
+	// The ISO polynomial, defined in ISO 3309 and used in HDLC.
+	ISO = 0xD800000000000000
+
+	// The ECMA polynomial, defined in ECMA 182.
+	ECMA = 0xC96C5795D7870F42
+)
+
+// Table is a 256-word table representing the polynomial for efficient processing.
+type Table [256]uint64
+
+// MakeTable returns the Table constructed from the specified polynomial.
+func MakeTable(poly uint64) *Table {
+	t := new(Table)
+	for i := 0; i < 256; i++ {
+		crc := uint64(i)
+		for j := 0; j < 8; j++ {
+			if crc&1 == 1 {
+				crc = (crc >> 1) ^ poly
+			} else {
+				crc >>= 1
+			}
+		}
+		t[i] = crc
+	}
+	return t
+}
+
+// digest represents the partial evaluation of a checksum.
+type digest struct {
+	crc uint64
+	tab *Table
+}
+
+// New creates a new hash.Hash64 computing the CRC-64 checksum
+// using the polynomial represented by the Table.
+func New(tab *Table) hash.Hash64 { return &digest{0, tab} }
+
+func (d *digest) Size() int { return Size }
+
+func (d *digest) BlockSize() int { return 1 }
+
+func (d *digest) Reset() { d.crc = 0 }
+
+func update(crc uint64, tab *Table, p []byte) uint64 {
+	crc = ^crc
+	for _, v := range p {
+		crc = tab[byte(crc)^v] ^ (crc >> 8)
+	}
+	return ^crc
+}
+
+// Update returns the result of adding the bytes in p to the crc.
+func Update(crc uint64, tab *Table, p []byte) uint64 {
+	return update(crc, tab, p)
+}
+
+func (d *digest) Write(p []byte) (n int, err error) {
+	d.crc = update(d.crc, d.tab, p)
+	return len(p), nil
+}
+
+func (d *digest) Sum64() uint64 { return d.crc }
+
+func (d *digest) Sum(in []byte) []byte {
+	s := d.Sum64()
+	return append(in, byte(s>>56), byte(s>>48), byte(s>>40), byte(s>>32), byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
+}
+
+// Checksum returns the CRC-64 checksum of data
+// using the polynomial represented by the Table.
+func Checksum(data []byte, tab *Table) uint64 { return update(0, tab, data) }
diff --git a/third_party/gofrontend/libgo/go/hash/crc64/crc64_test.go b/third_party/gofrontend/libgo/go/hash/crc64/crc64_test.go
new file mode 100644
index 0000000..81a87b5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/crc64/crc64_test.go
@@ -0,0 +1,81 @@
+// 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 crc64
+
+import (
+	"io"
+	"testing"
+)
+
+type test struct {
+	out uint64
+	in  string
+}
+
+var golden = []test{
+	{0x0, ""},
+	{0x3420000000000000, "a"},
+	{0x36c4200000000000, "ab"},
+	{0x3776c42000000000, "abc"},
+	{0x336776c420000000, "abcd"},
+	{0x32d36776c4200000, "abcde"},
+	{0x3002d36776c42000, "abcdef"},
+	{0x31b002d36776c420, "abcdefg"},
+	{0xe21b002d36776c4, "abcdefgh"},
+	{0x8b6e21b002d36776, "abcdefghi"},
+	{0x7f5b6e21b002d367, "abcdefghij"},
+	{0x8ec0e7c835bf9cdf, "Discard medicine more than two years old."},
+	{0xc7db1759e2be5ab4, "He who has a shady past knows that nice guys finish last."},
+	{0xfbf9d9603a6fa020, "I wouldn't marry him with a ten foot pole."},
+	{0xeafc4211a6daa0ef, "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+	{0x3e05b21c7a4dc4da, "The days of the digital watch are numbered.  -Tom Stoppard"},
+	{0x5255866ad6ef28a6, "Nepal premier won't resign."},
+	{0x8a79895be1e9c361, "For every action there is an equal and opposite government program."},
+	{0x8878963a649d4916, "His money is twice tainted: 'taint yours and 'taint mine."},
+	{0xa7b9d53ea87eb82f, "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+	{0xdb6805c0966a2f9c, "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+	{0xf3553c65dacdadd2, "size:  a.out:  bad magic"},
+	{0x9d5e034087a676b9, "The major problem is with sendmail.  -Mark Horton"},
+	{0xa6db2d7f8da96417, "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
+	{0x325e00cd2fe819f9, "If the enemy is within range, then so are you."},
+	{0x88c6600ce58ae4c6, "It's well we cannot hear the screams/That we create in others' dreams."},
+	{0x28c4a3f3b769e078, "You remind me of a TV show, but that's all right: I watch it anyway."},
+	{0xa698a34c9d9f1dca, "C is as portable as Stonehedge!!"},
+	{0xf6c1e2a8c26c5cfc, "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+	{0xd402559dfe9b70c, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
+	{0xdb6efff26aa94946, "How can you write a big system without C++?  -Paul Glick"},
+}
+
+var tab = MakeTable(ISO)
+
+func TestGolden(t *testing.T) {
+	for i := 0; i < len(golden); i++ {
+		g := golden[i]
+		c := New(tab)
+		io.WriteString(c, g.in)
+		s := c.Sum64()
+		if s != g.out {
+			t.Errorf("crc64(%s) = 0x%x want 0x%x", g.in, s, g.out)
+			t.FailNow()
+		}
+	}
+}
+
+func BenchmarkCrc64KB(b *testing.B) {
+	b.SetBytes(1024)
+	data := make([]byte, 1024)
+	for i := range data {
+		data[i] = byte(i)
+	}
+	h := New(tab)
+	in := make([]byte, 0, h.Size())
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		h.Reset()
+		h.Write(data)
+		h.Sum(in)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/hash/fnv/fnv.go b/third_party/gofrontend/libgo/go/hash/fnv/fnv.go
new file mode 100644
index 0000000..c020661
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/fnv/fnv.go
@@ -0,0 +1,131 @@
+// 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.
+
+// Package fnv implements FNV-1 and FNV-1a, non-cryptographic hash functions
+// created by Glenn Fowler, Landon Curt Noll, and Phong Vo.
+// See
+// http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function.
+package fnv
+
+import (
+	"hash"
+)
+
+type (
+	sum32  uint32
+	sum32a uint32
+	sum64  uint64
+	sum64a uint64
+)
+
+const (
+	offset32 = 2166136261
+	offset64 = 14695981039346656037
+	prime32  = 16777619
+	prime64  = 1099511628211
+)
+
+// New32 returns a new 32-bit FNV-1 hash.Hash.
+func New32() hash.Hash32 {
+	var s sum32 = offset32
+	return &s
+}
+
+// New32a returns a new 32-bit FNV-1a hash.Hash.
+func New32a() hash.Hash32 {
+	var s sum32a = offset32
+	return &s
+}
+
+// New64 returns a new 64-bit FNV-1 hash.Hash.
+func New64() hash.Hash64 {
+	var s sum64 = offset64
+	return &s
+}
+
+// New64a returns a new 64-bit FNV-1a hash.Hash.
+func New64a() hash.Hash64 {
+	var s sum64a = offset64
+	return &s
+}
+
+func (s *sum32) Reset()  { *s = offset32 }
+func (s *sum32a) Reset() { *s = offset32 }
+func (s *sum64) Reset()  { *s = offset64 }
+func (s *sum64a) Reset() { *s = offset64 }
+
+func (s *sum32) Sum32() uint32  { return uint32(*s) }
+func (s *sum32a) Sum32() uint32 { return uint32(*s) }
+func (s *sum64) Sum64() uint64  { return uint64(*s) }
+func (s *sum64a) Sum64() uint64 { return uint64(*s) }
+
+func (s *sum32) Write(data []byte) (int, error) {
+	hash := *s
+	for _, c := range data {
+		hash *= prime32
+		hash ^= sum32(c)
+	}
+	*s = hash
+	return len(data), nil
+}
+
+func (s *sum32a) Write(data []byte) (int, error) {
+	hash := *s
+	for _, c := range data {
+		hash ^= sum32a(c)
+		hash *= prime32
+	}
+	*s = hash
+	return len(data), nil
+}
+
+func (s *sum64) Write(data []byte) (int, error) {
+	hash := *s
+	for _, c := range data {
+		hash *= prime64
+		hash ^= sum64(c)
+	}
+	*s = hash
+	return len(data), nil
+}
+
+func (s *sum64a) Write(data []byte) (int, error) {
+	hash := *s
+	for _, c := range data {
+		hash ^= sum64a(c)
+		hash *= prime64
+	}
+	*s = hash
+	return len(data), nil
+}
+
+func (s *sum32) Size() int  { return 4 }
+func (s *sum32a) Size() int { return 4 }
+func (s *sum64) Size() int  { return 8 }
+func (s *sum64a) Size() int { return 8 }
+
+func (s *sum32) BlockSize() int  { return 1 }
+func (s *sum32a) BlockSize() int { return 1 }
+func (s *sum64) BlockSize() int  { return 1 }
+func (s *sum64a) BlockSize() int { return 1 }
+
+func (s *sum32) Sum(in []byte) []byte {
+	v := uint32(*s)
+	return append(in, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
+
+func (s *sum32a) Sum(in []byte) []byte {
+	v := uint32(*s)
+	return append(in, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
+
+func (s *sum64) Sum(in []byte) []byte {
+	v := uint64(*s)
+	return append(in, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
+
+func (s *sum64a) Sum(in []byte) []byte {
+	v := uint64(*s)
+	return append(in, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
diff --git a/third_party/gofrontend/libgo/go/hash/fnv/fnv_test.go b/third_party/gofrontend/libgo/go/hash/fnv/fnv_test.go
new file mode 100644
index 0000000..89d39b3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/fnv/fnv_test.go
@@ -0,0 +1,165 @@
+// 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.
+
+package fnv
+
+import (
+	"bytes"
+	"encoding/binary"
+	"hash"
+	"testing"
+)
+
+type golden struct {
+	sum  []byte
+	text string
+}
+
+var golden32 = []golden{
+	{[]byte{0x81, 0x1c, 0x9d, 0xc5}, ""},
+	{[]byte{0x05, 0x0c, 0x5d, 0x7e}, "a"},
+	{[]byte{0x70, 0x77, 0x2d, 0x38}, "ab"},
+	{[]byte{0x43, 0x9c, 0x2f, 0x4b}, "abc"},
+}
+
+var golden32a = []golden{
+	{[]byte{0x81, 0x1c, 0x9d, 0xc5}, ""},
+	{[]byte{0xe4, 0x0c, 0x29, 0x2c}, "a"},
+	{[]byte{0x4d, 0x25, 0x05, 0xca}, "ab"},
+	{[]byte{0x1a, 0x47, 0xe9, 0x0b}, "abc"},
+}
+
+var golden64 = []golden{
+	{[]byte{0xcb, 0xf2, 0x9c, 0xe4, 0x84, 0x22, 0x23, 0x25}, ""},
+	{[]byte{0xaf, 0x63, 0xbd, 0x4c, 0x86, 0x01, 0xb7, 0xbe}, "a"},
+	{[]byte{0x08, 0x32, 0x67, 0x07, 0xb4, 0xeb, 0x37, 0xb8}, "ab"},
+	{[]byte{0xd8, 0xdc, 0xca, 0x18, 0x6b, 0xaf, 0xad, 0xcb}, "abc"},
+}
+
+var golden64a = []golden{
+	{[]byte{0xcb, 0xf2, 0x9c, 0xe4, 0x84, 0x22, 0x23, 0x25}, ""},
+	{[]byte{0xaf, 0x63, 0xdc, 0x4c, 0x86, 0x01, 0xec, 0x8c}, "a"},
+	{[]byte{0x08, 0x9c, 0x44, 0x07, 0xb5, 0x45, 0x98, 0x6a}, "ab"},
+	{[]byte{0xe7, 0x1f, 0xa2, 0x19, 0x05, 0x41, 0x57, 0x4b}, "abc"},
+}
+
+func TestGolden32(t *testing.T) {
+	testGolden(t, New32(), golden32)
+}
+
+func TestGolden32a(t *testing.T) {
+	testGolden(t, New32a(), golden32a)
+}
+
+func TestGolden64(t *testing.T) {
+	testGolden(t, New64(), golden64)
+}
+
+func TestGolden64a(t *testing.T) {
+	testGolden(t, New64a(), golden64a)
+}
+
+func testGolden(t *testing.T, hash hash.Hash, gold []golden) {
+	for _, g := range gold {
+		hash.Reset()
+		done, error := hash.Write([]byte(g.text))
+		if error != nil {
+			t.Fatalf("write error: %s", error)
+		}
+		if done != len(g.text) {
+			t.Fatalf("wrote only %d out of %d bytes", done, len(g.text))
+		}
+		if actual := hash.Sum(nil); !bytes.Equal(g.sum, actual) {
+			t.Errorf("hash(%q) = 0x%x want 0x%x", g.text, actual, g.sum)
+		}
+	}
+}
+
+func TestIntegrity32(t *testing.T) {
+	testIntegrity(t, New32())
+}
+
+func TestIntegrity32a(t *testing.T) {
+	testIntegrity(t, New32a())
+}
+
+func TestIntegrity64(t *testing.T) {
+	testIntegrity(t, New64())
+}
+
+func TestIntegrity64a(t *testing.T) {
+	testIntegrity(t, New64a())
+}
+
+func testIntegrity(t *testing.T, h hash.Hash) {
+	data := []byte{'1', '2', 3, 4, 5}
+	h.Write(data)
+	sum := h.Sum(nil)
+
+	if size := h.Size(); size != len(sum) {
+		t.Fatalf("Size()=%d but len(Sum())=%d", size, len(sum))
+	}
+
+	if a := h.Sum(nil); !bytes.Equal(sum, a) {
+		t.Fatalf("first Sum()=0x%x, second Sum()=0x%x", sum, a)
+	}
+
+	h.Reset()
+	h.Write(data)
+	if a := h.Sum(nil); !bytes.Equal(sum, a) {
+		t.Fatalf("Sum()=0x%x, but after Reset() Sum()=0x%x", sum, a)
+	}
+
+	h.Reset()
+	h.Write(data[:2])
+	h.Write(data[2:])
+	if a := h.Sum(nil); !bytes.Equal(sum, a) {
+		t.Fatalf("Sum()=0x%x, but with partial writes, Sum()=0x%x", sum, a)
+	}
+
+	switch h.Size() {
+	case 4:
+		sum32 := h.(hash.Hash32).Sum32()
+		if sum32 != binary.BigEndian.Uint32(sum) {
+			t.Fatalf("Sum()=0x%x, but Sum32()=0x%x", sum, sum32)
+		}
+	case 8:
+		sum64 := h.(hash.Hash64).Sum64()
+		if sum64 != binary.BigEndian.Uint64(sum) {
+			t.Fatalf("Sum()=0x%x, but Sum64()=0x%x", sum, sum64)
+		}
+	}
+}
+
+func BenchmarkFnv32KB(b *testing.B) {
+	benchmarkKB(b, New32())
+}
+
+func BenchmarkFnv32aKB(b *testing.B) {
+	benchmarkKB(b, New32a())
+}
+
+func BenchmarkFnv64KB(b *testing.B) {
+	benchmarkKB(b, New64())
+}
+
+func BenchmarkFnv64aKB(b *testing.B) {
+	benchmarkKB(b, New64a())
+}
+
+func benchmarkKB(b *testing.B, h hash.Hash) {
+	b.SetBytes(1024)
+	data := make([]byte, 1024)
+	for i := range data {
+		data[i] = byte(i)
+	}
+	in := make([]byte, 0, h.Size())
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		h.Reset()
+		h.Write(data)
+		h.Sum(in)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/hash/hash.go b/third_party/gofrontend/libgo/go/hash/hash.go
new file mode 100644
index 0000000..8d138d0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/hash/hash.go
@@ -0,0 +1,43 @@
+// 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 hash provides interfaces for hash functions.
+package hash
+
+import "io"
+
+// Hash is the common interface implemented by all hash functions.
+type Hash interface {
+	// Write (via the embedded io.Writer interface) adds more data to the running hash.
+	// It never returns an error.
+	io.Writer
+
+	// Sum appends the current hash to b and returns the resulting slice.
+	// It does not change the underlying hash state.
+	Sum(b []byte) []byte
+
+	// Reset resets the Hash to its initial state.
+	Reset()
+
+	// Size returns the number of bytes Sum will return.
+	Size() int
+
+	// BlockSize returns the hash's underlying block size.
+	// The Write method must be able to accept any amount
+	// of data, but it may operate more efficiently if all writes
+	// are a multiple of the block size.
+	BlockSize() int
+}
+
+// Hash32 is the common interface implemented by all 32-bit hash functions.
+type Hash32 interface {
+	Hash
+	Sum32() uint32
+}
+
+// Hash64 is the common interface implemented by all 64-bit hash functions.
+type Hash64 interface {
+	Hash
+	Sum64() uint64
+}
diff --git a/third_party/gofrontend/libgo/go/html/entity.go b/third_party/gofrontend/libgo/go/html/entity.go
new file mode 100644
index 0000000..af8a007
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/entity.go
@@ -0,0 +1,2253 @@
+// Copyright 2010 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 html
+
+// All entities that do not end with ';' are 6 or fewer bytes long.
+const longestEntityWithoutSemicolon = 6
+
+// entity is a map from HTML entity names to their values. The semicolon matters:
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html
+// lists both "amp" and "amp;" as two separate entries.
+//
+// Note that the HTML5 list is larger than the HTML4 list at
+// http://www.w3.org/TR/html4/sgml/entities.html
+var entity = map[string]rune{
+	"AElig;":                           '\U000000C6',
+	"AMP;":                             '\U00000026',
+	"Aacute;":                          '\U000000C1',
+	"Abreve;":                          '\U00000102',
+	"Acirc;":                           '\U000000C2',
+	"Acy;":                             '\U00000410',
+	"Afr;":                             '\U0001D504',
+	"Agrave;":                          '\U000000C0',
+	"Alpha;":                           '\U00000391',
+	"Amacr;":                           '\U00000100',
+	"And;":                             '\U00002A53',
+	"Aogon;":                           '\U00000104',
+	"Aopf;":                            '\U0001D538',
+	"ApplyFunction;":                   '\U00002061',
+	"Aring;":                           '\U000000C5',
+	"Ascr;":                            '\U0001D49C',
+	"Assign;":                          '\U00002254',
+	"Atilde;":                          '\U000000C3',
+	"Auml;":                            '\U000000C4',
+	"Backslash;":                       '\U00002216',
+	"Barv;":                            '\U00002AE7',
+	"Barwed;":                          '\U00002306',
+	"Bcy;":                             '\U00000411',
+	"Because;":                         '\U00002235',
+	"Bernoullis;":                      '\U0000212C',
+	"Beta;":                            '\U00000392',
+	"Bfr;":                             '\U0001D505',
+	"Bopf;":                            '\U0001D539',
+	"Breve;":                           '\U000002D8',
+	"Bscr;":                            '\U0000212C',
+	"Bumpeq;":                          '\U0000224E',
+	"CHcy;":                            '\U00000427',
+	"COPY;":                            '\U000000A9',
+	"Cacute;":                          '\U00000106',
+	"Cap;":                             '\U000022D2',
+	"CapitalDifferentialD;":            '\U00002145',
+	"Cayleys;":                         '\U0000212D',
+	"Ccaron;":                          '\U0000010C',
+	"Ccedil;":                          '\U000000C7',
+	"Ccirc;":                           '\U00000108',
+	"Cconint;":                         '\U00002230',
+	"Cdot;":                            '\U0000010A',
+	"Cedilla;":                         '\U000000B8',
+	"CenterDot;":                       '\U000000B7',
+	"Cfr;":                             '\U0000212D',
+	"Chi;":                             '\U000003A7',
+	"CircleDot;":                       '\U00002299',
+	"CircleMinus;":                     '\U00002296',
+	"CirclePlus;":                      '\U00002295',
+	"CircleTimes;":                     '\U00002297',
+	"ClockwiseContourIntegral;":        '\U00002232',
+	"CloseCurlyDoubleQuote;":           '\U0000201D',
+	"CloseCurlyQuote;":                 '\U00002019',
+	"Colon;":                           '\U00002237',
+	"Colone;":                          '\U00002A74',
+	"Congruent;":                       '\U00002261',
+	"Conint;":                          '\U0000222F',
+	"ContourIntegral;":                 '\U0000222E',
+	"Copf;":                            '\U00002102',
+	"Coproduct;":                       '\U00002210',
+	"CounterClockwiseContourIntegral;": '\U00002233',
+	"Cross;":                    '\U00002A2F',
+	"Cscr;":                     '\U0001D49E',
+	"Cup;":                      '\U000022D3',
+	"CupCap;":                   '\U0000224D',
+	"DD;":                       '\U00002145',
+	"DDotrahd;":                 '\U00002911',
+	"DJcy;":                     '\U00000402',
+	"DScy;":                     '\U00000405',
+	"DZcy;":                     '\U0000040F',
+	"Dagger;":                   '\U00002021',
+	"Darr;":                     '\U000021A1',
+	"Dashv;":                    '\U00002AE4',
+	"Dcaron;":                   '\U0000010E',
+	"Dcy;":                      '\U00000414',
+	"Del;":                      '\U00002207',
+	"Delta;":                    '\U00000394',
+	"Dfr;":                      '\U0001D507',
+	"DiacriticalAcute;":         '\U000000B4',
+	"DiacriticalDot;":           '\U000002D9',
+	"DiacriticalDoubleAcute;":   '\U000002DD',
+	"DiacriticalGrave;":         '\U00000060',
+	"DiacriticalTilde;":         '\U000002DC',
+	"Diamond;":                  '\U000022C4',
+	"DifferentialD;":            '\U00002146',
+	"Dopf;":                     '\U0001D53B',
+	"Dot;":                      '\U000000A8',
+	"DotDot;":                   '\U000020DC',
+	"DotEqual;":                 '\U00002250',
+	"DoubleContourIntegral;":    '\U0000222F',
+	"DoubleDot;":                '\U000000A8',
+	"DoubleDownArrow;":          '\U000021D3',
+	"DoubleLeftArrow;":          '\U000021D0',
+	"DoubleLeftRightArrow;":     '\U000021D4',
+	"DoubleLeftTee;":            '\U00002AE4',
+	"DoubleLongLeftArrow;":      '\U000027F8',
+	"DoubleLongLeftRightArrow;": '\U000027FA',
+	"DoubleLongRightArrow;":     '\U000027F9',
+	"DoubleRightArrow;":         '\U000021D2',
+	"DoubleRightTee;":           '\U000022A8',
+	"DoubleUpArrow;":            '\U000021D1',
+	"DoubleUpDownArrow;":        '\U000021D5',
+	"DoubleVerticalBar;":        '\U00002225',
+	"DownArrow;":                '\U00002193',
+	"DownArrowBar;":             '\U00002913',
+	"DownArrowUpArrow;":         '\U000021F5',
+	"DownBreve;":                '\U00000311',
+	"DownLeftRightVector;":      '\U00002950',
+	"DownLeftTeeVector;":        '\U0000295E',
+	"DownLeftVector;":           '\U000021BD',
+	"DownLeftVectorBar;":        '\U00002956',
+	"DownRightTeeVector;":       '\U0000295F',
+	"DownRightVector;":          '\U000021C1',
+	"DownRightVectorBar;":       '\U00002957',
+	"DownTee;":                  '\U000022A4',
+	"DownTeeArrow;":             '\U000021A7',
+	"Downarrow;":                '\U000021D3',
+	"Dscr;":                     '\U0001D49F',
+	"Dstrok;":                   '\U00000110',
+	"ENG;":                      '\U0000014A',
+	"ETH;":                      '\U000000D0',
+	"Eacute;":                   '\U000000C9',
+	"Ecaron;":                   '\U0000011A',
+	"Ecirc;":                    '\U000000CA',
+	"Ecy;":                      '\U0000042D',
+	"Edot;":                     '\U00000116',
+	"Efr;":                      '\U0001D508',
+	"Egrave;":                   '\U000000C8',
+	"Element;":                  '\U00002208',
+	"Emacr;":                    '\U00000112',
+	"EmptySmallSquare;":         '\U000025FB',
+	"EmptyVerySmallSquare;":     '\U000025AB',
+	"Eogon;":                    '\U00000118',
+	"Eopf;":                     '\U0001D53C',
+	"Epsilon;":                  '\U00000395',
+	"Equal;":                    '\U00002A75',
+	"EqualTilde;":               '\U00002242',
+	"Equilibrium;":              '\U000021CC',
+	"Escr;":                     '\U00002130',
+	"Esim;":                     '\U00002A73',
+	"Eta;":                      '\U00000397',
+	"Euml;":                     '\U000000CB',
+	"Exists;":                   '\U00002203',
+	"ExponentialE;":             '\U00002147',
+	"Fcy;":                      '\U00000424',
+	"Ffr;":                      '\U0001D509',
+	"FilledSmallSquare;":        '\U000025FC',
+	"FilledVerySmallSquare;":    '\U000025AA',
+	"Fopf;":                     '\U0001D53D',
+	"ForAll;":                   '\U00002200',
+	"Fouriertrf;":               '\U00002131',
+	"Fscr;":                     '\U00002131',
+	"GJcy;":                     '\U00000403',
+	"GT;":                       '\U0000003E',
+	"Gamma;":                    '\U00000393',
+	"Gammad;":                   '\U000003DC',
+	"Gbreve;":                   '\U0000011E',
+	"Gcedil;":                   '\U00000122',
+	"Gcirc;":                    '\U0000011C',
+	"Gcy;":                      '\U00000413',
+	"Gdot;":                     '\U00000120',
+	"Gfr;":                      '\U0001D50A',
+	"Gg;":                       '\U000022D9',
+	"Gopf;":                     '\U0001D53E',
+	"GreaterEqual;":             '\U00002265',
+	"GreaterEqualLess;":         '\U000022DB',
+	"GreaterFullEqual;":         '\U00002267',
+	"GreaterGreater;":           '\U00002AA2',
+	"GreaterLess;":              '\U00002277',
+	"GreaterSlantEqual;":        '\U00002A7E',
+	"GreaterTilde;":             '\U00002273',
+	"Gscr;":                     '\U0001D4A2',
+	"Gt;":                       '\U0000226B',
+	"HARDcy;":                   '\U0000042A',
+	"Hacek;":                    '\U000002C7',
+	"Hat;":                      '\U0000005E',
+	"Hcirc;":                    '\U00000124',
+	"Hfr;":                      '\U0000210C',
+	"HilbertSpace;":             '\U0000210B',
+	"Hopf;":                     '\U0000210D',
+	"HorizontalLine;":           '\U00002500',
+	"Hscr;":                     '\U0000210B',
+	"Hstrok;":                   '\U00000126',
+	"HumpDownHump;":             '\U0000224E',
+	"HumpEqual;":                '\U0000224F',
+	"IEcy;":                     '\U00000415',
+	"IJlig;":                    '\U00000132',
+	"IOcy;":                     '\U00000401',
+	"Iacute;":                   '\U000000CD',
+	"Icirc;":                    '\U000000CE',
+	"Icy;":                      '\U00000418',
+	"Idot;":                     '\U00000130',
+	"Ifr;":                      '\U00002111',
+	"Igrave;":                   '\U000000CC',
+	"Im;":                       '\U00002111',
+	"Imacr;":                    '\U0000012A',
+	"ImaginaryI;":               '\U00002148',
+	"Implies;":                  '\U000021D2',
+	"Int;":                      '\U0000222C',
+	"Integral;":                 '\U0000222B',
+	"Intersection;":             '\U000022C2',
+	"InvisibleComma;":           '\U00002063',
+	"InvisibleTimes;":           '\U00002062',
+	"Iogon;":                    '\U0000012E',
+	"Iopf;":                     '\U0001D540',
+	"Iota;":                     '\U00000399',
+	"Iscr;":                     '\U00002110',
+	"Itilde;":                   '\U00000128',
+	"Iukcy;":                    '\U00000406',
+	"Iuml;":                     '\U000000CF',
+	"Jcirc;":                    '\U00000134',
+	"Jcy;":                      '\U00000419',
+	"Jfr;":                      '\U0001D50D',
+	"Jopf;":                     '\U0001D541',
+	"Jscr;":                     '\U0001D4A5',
+	"Jsercy;":                   '\U00000408',
+	"Jukcy;":                    '\U00000404',
+	"KHcy;":                     '\U00000425',
+	"KJcy;":                     '\U0000040C',
+	"Kappa;":                    '\U0000039A',
+	"Kcedil;":                   '\U00000136',
+	"Kcy;":                      '\U0000041A',
+	"Kfr;":                      '\U0001D50E',
+	"Kopf;":                     '\U0001D542',
+	"Kscr;":                     '\U0001D4A6',
+	"LJcy;":                     '\U00000409',
+	"LT;":                       '\U0000003C',
+	"Lacute;":                   '\U00000139',
+	"Lambda;":                   '\U0000039B',
+	"Lang;":                     '\U000027EA',
+	"Laplacetrf;":               '\U00002112',
+	"Larr;":                     '\U0000219E',
+	"Lcaron;":                   '\U0000013D',
+	"Lcedil;":                   '\U0000013B',
+	"Lcy;":                      '\U0000041B',
+	"LeftAngleBracket;":         '\U000027E8',
+	"LeftArrow;":                '\U00002190',
+	"LeftArrowBar;":             '\U000021E4',
+	"LeftArrowRightArrow;":      '\U000021C6',
+	"LeftCeiling;":              '\U00002308',
+	"LeftDoubleBracket;":        '\U000027E6',
+	"LeftDownTeeVector;":        '\U00002961',
+	"LeftDownVector;":           '\U000021C3',
+	"LeftDownVectorBar;":        '\U00002959',
+	"LeftFloor;":                '\U0000230A',
+	"LeftRightArrow;":           '\U00002194',
+	"LeftRightVector;":          '\U0000294E',
+	"LeftTee;":                  '\U000022A3',
+	"LeftTeeArrow;":             '\U000021A4',
+	"LeftTeeVector;":            '\U0000295A',
+	"LeftTriangle;":             '\U000022B2',
+	"LeftTriangleBar;":          '\U000029CF',
+	"LeftTriangleEqual;":        '\U000022B4',
+	"LeftUpDownVector;":         '\U00002951',
+	"LeftUpTeeVector;":          '\U00002960',
+	"LeftUpVector;":             '\U000021BF',
+	"LeftUpVectorBar;":          '\U00002958',
+	"LeftVector;":               '\U000021BC',
+	"LeftVectorBar;":            '\U00002952',
+	"Leftarrow;":                '\U000021D0',
+	"Leftrightarrow;":           '\U000021D4',
+	"LessEqualGreater;":         '\U000022DA',
+	"LessFullEqual;":            '\U00002266',
+	"LessGreater;":              '\U00002276',
+	"LessLess;":                 '\U00002AA1',
+	"LessSlantEqual;":           '\U00002A7D',
+	"LessTilde;":                '\U00002272',
+	"Lfr;":                      '\U0001D50F',
+	"Ll;":                       '\U000022D8',
+	"Lleftarrow;":               '\U000021DA',
+	"Lmidot;":                   '\U0000013F',
+	"LongLeftArrow;":            '\U000027F5',
+	"LongLeftRightArrow;":       '\U000027F7',
+	"LongRightArrow;":           '\U000027F6',
+	"Longleftarrow;":            '\U000027F8',
+	"Longleftrightarrow;":       '\U000027FA',
+	"Longrightarrow;":           '\U000027F9',
+	"Lopf;":                     '\U0001D543',
+	"LowerLeftArrow;":           '\U00002199',
+	"LowerRightArrow;":          '\U00002198',
+	"Lscr;":                     '\U00002112',
+	"Lsh;":                      '\U000021B0',
+	"Lstrok;":                   '\U00000141',
+	"Lt;":                       '\U0000226A',
+	"Map;":                      '\U00002905',
+	"Mcy;":                      '\U0000041C',
+	"MediumSpace;":              '\U0000205F',
+	"Mellintrf;":                '\U00002133',
+	"Mfr;":                      '\U0001D510',
+	"MinusPlus;":                '\U00002213',
+	"Mopf;":                     '\U0001D544',
+	"Mscr;":                     '\U00002133',
+	"Mu;":                       '\U0000039C',
+	"NJcy;":                     '\U0000040A',
+	"Nacute;":                   '\U00000143',
+	"Ncaron;":                   '\U00000147',
+	"Ncedil;":                   '\U00000145',
+	"Ncy;":                      '\U0000041D',
+	"NegativeMediumSpace;":      '\U0000200B',
+	"NegativeThickSpace;":       '\U0000200B',
+	"NegativeThinSpace;":        '\U0000200B',
+	"NegativeVeryThinSpace;":    '\U0000200B',
+	"NestedGreaterGreater;":     '\U0000226B',
+	"NestedLessLess;":           '\U0000226A',
+	"NewLine;":                  '\U0000000A',
+	"Nfr;":                      '\U0001D511',
+	"NoBreak;":                  '\U00002060',
+	"NonBreakingSpace;":         '\U000000A0',
+	"Nopf;":                     '\U00002115',
+	"Not;":                      '\U00002AEC',
+	"NotCongruent;":             '\U00002262',
+	"NotCupCap;":                '\U0000226D',
+	"NotDoubleVerticalBar;":     '\U00002226',
+	"NotElement;":               '\U00002209',
+	"NotEqual;":                 '\U00002260',
+	"NotExists;":                '\U00002204',
+	"NotGreater;":               '\U0000226F',
+	"NotGreaterEqual;":          '\U00002271',
+	"NotGreaterLess;":           '\U00002279',
+	"NotGreaterTilde;":          '\U00002275',
+	"NotLeftTriangle;":          '\U000022EA',
+	"NotLeftTriangleEqual;":     '\U000022EC',
+	"NotLess;":                  '\U0000226E',
+	"NotLessEqual;":             '\U00002270',
+	"NotLessGreater;":           '\U00002278',
+	"NotLessTilde;":             '\U00002274',
+	"NotPrecedes;":              '\U00002280',
+	"NotPrecedesSlantEqual;":    '\U000022E0',
+	"NotReverseElement;":        '\U0000220C',
+	"NotRightTriangle;":         '\U000022EB',
+	"NotRightTriangleEqual;":    '\U000022ED',
+	"NotSquareSubsetEqual;":     '\U000022E2',
+	"NotSquareSupersetEqual;":   '\U000022E3',
+	"NotSubsetEqual;":           '\U00002288',
+	"NotSucceeds;":              '\U00002281',
+	"NotSucceedsSlantEqual;":    '\U000022E1',
+	"NotSupersetEqual;":         '\U00002289',
+	"NotTilde;":                 '\U00002241',
+	"NotTildeEqual;":            '\U00002244',
+	"NotTildeFullEqual;":        '\U00002247',
+	"NotTildeTilde;":            '\U00002249',
+	"NotVerticalBar;":           '\U00002224',
+	"Nscr;":                     '\U0001D4A9',
+	"Ntilde;":                   '\U000000D1',
+	"Nu;":                       '\U0000039D',
+	"OElig;":                    '\U00000152',
+	"Oacute;":                   '\U000000D3',
+	"Ocirc;":                    '\U000000D4',
+	"Ocy;":                      '\U0000041E',
+	"Odblac;":                   '\U00000150',
+	"Ofr;":                      '\U0001D512',
+	"Ograve;":                   '\U000000D2',
+	"Omacr;":                    '\U0000014C',
+	"Omega;":                    '\U000003A9',
+	"Omicron;":                  '\U0000039F',
+	"Oopf;":                     '\U0001D546',
+	"OpenCurlyDoubleQuote;":     '\U0000201C',
+	"OpenCurlyQuote;":           '\U00002018',
+	"Or;":                       '\U00002A54',
+	"Oscr;":                     '\U0001D4AA',
+	"Oslash;":                   '\U000000D8',
+	"Otilde;":                   '\U000000D5',
+	"Otimes;":                   '\U00002A37',
+	"Ouml;":                     '\U000000D6',
+	"OverBar;":                  '\U0000203E',
+	"OverBrace;":                '\U000023DE',
+	"OverBracket;":              '\U000023B4',
+	"OverParenthesis;":          '\U000023DC',
+	"PartialD;":                 '\U00002202',
+	"Pcy;":                      '\U0000041F',
+	"Pfr;":                      '\U0001D513',
+	"Phi;":                      '\U000003A6',
+	"Pi;":                       '\U000003A0',
+	"PlusMinus;":                '\U000000B1',
+	"Poincareplane;":            '\U0000210C',
+	"Popf;":                     '\U00002119',
+	"Pr;":                       '\U00002ABB',
+	"Precedes;":                 '\U0000227A',
+	"PrecedesEqual;":            '\U00002AAF',
+	"PrecedesSlantEqual;":       '\U0000227C',
+	"PrecedesTilde;":            '\U0000227E',
+	"Prime;":                    '\U00002033',
+	"Product;":                  '\U0000220F',
+	"Proportion;":               '\U00002237',
+	"Proportional;":             '\U0000221D',
+	"Pscr;":                     '\U0001D4AB',
+	"Psi;":                      '\U000003A8',
+	"QUOT;":                     '\U00000022',
+	"Qfr;":                      '\U0001D514',
+	"Qopf;":                     '\U0000211A',
+	"Qscr;":                     '\U0001D4AC',
+	"RBarr;":                    '\U00002910',
+	"REG;":                      '\U000000AE',
+	"Racute;":                   '\U00000154',
+	"Rang;":                     '\U000027EB',
+	"Rarr;":                     '\U000021A0',
+	"Rarrtl;":                   '\U00002916',
+	"Rcaron;":                   '\U00000158',
+	"Rcedil;":                   '\U00000156',
+	"Rcy;":                      '\U00000420',
+	"Re;":                       '\U0000211C',
+	"ReverseElement;":           '\U0000220B',
+	"ReverseEquilibrium;":       '\U000021CB',
+	"ReverseUpEquilibrium;":     '\U0000296F',
+	"Rfr;":                      '\U0000211C',
+	"Rho;":                      '\U000003A1',
+	"RightAngleBracket;":        '\U000027E9',
+	"RightArrow;":               '\U00002192',
+	"RightArrowBar;":            '\U000021E5',
+	"RightArrowLeftArrow;":      '\U000021C4',
+	"RightCeiling;":             '\U00002309',
+	"RightDoubleBracket;":       '\U000027E7',
+	"RightDownTeeVector;":       '\U0000295D',
+	"RightDownVector;":          '\U000021C2',
+	"RightDownVectorBar;":       '\U00002955',
+	"RightFloor;":               '\U0000230B',
+	"RightTee;":                 '\U000022A2',
+	"RightTeeArrow;":            '\U000021A6',
+	"RightTeeVector;":           '\U0000295B',
+	"RightTriangle;":            '\U000022B3',
+	"RightTriangleBar;":         '\U000029D0',
+	"RightTriangleEqual;":       '\U000022B5',
+	"RightUpDownVector;":        '\U0000294F',
+	"RightUpTeeVector;":         '\U0000295C',
+	"RightUpVector;":            '\U000021BE',
+	"RightUpVectorBar;":         '\U00002954',
+	"RightVector;":              '\U000021C0',
+	"RightVectorBar;":           '\U00002953',
+	"Rightarrow;":               '\U000021D2',
+	"Ropf;":                     '\U0000211D',
+	"RoundImplies;":             '\U00002970',
+	"Rrightarrow;":              '\U000021DB',
+	"Rscr;":                     '\U0000211B',
+	"Rsh;":                      '\U000021B1',
+	"RuleDelayed;":              '\U000029F4',
+	"SHCHcy;":                   '\U00000429',
+	"SHcy;":                     '\U00000428',
+	"SOFTcy;":                   '\U0000042C',
+	"Sacute;":                   '\U0000015A',
+	"Sc;":                       '\U00002ABC',
+	"Scaron;":                   '\U00000160',
+	"Scedil;":                   '\U0000015E',
+	"Scirc;":                    '\U0000015C',
+	"Scy;":                      '\U00000421',
+	"Sfr;":                      '\U0001D516',
+	"ShortDownArrow;":           '\U00002193',
+	"ShortLeftArrow;":           '\U00002190',
+	"ShortRightArrow;":          '\U00002192',
+	"ShortUpArrow;":             '\U00002191',
+	"Sigma;":                    '\U000003A3',
+	"SmallCircle;":              '\U00002218',
+	"Sopf;":                     '\U0001D54A',
+	"Sqrt;":                     '\U0000221A',
+	"Square;":                   '\U000025A1',
+	"SquareIntersection;":       '\U00002293',
+	"SquareSubset;":             '\U0000228F',
+	"SquareSubsetEqual;":        '\U00002291',
+	"SquareSuperset;":           '\U00002290',
+	"SquareSupersetEqual;":      '\U00002292',
+	"SquareUnion;":              '\U00002294',
+	"Sscr;":                     '\U0001D4AE',
+	"Star;":                     '\U000022C6',
+	"Sub;":                      '\U000022D0',
+	"Subset;":                   '\U000022D0',
+	"SubsetEqual;":              '\U00002286',
+	"Succeeds;":                 '\U0000227B',
+	"SucceedsEqual;":            '\U00002AB0',
+	"SucceedsSlantEqual;":       '\U0000227D',
+	"SucceedsTilde;":            '\U0000227F',
+	"SuchThat;":                 '\U0000220B',
+	"Sum;":                      '\U00002211',
+	"Sup;":                      '\U000022D1',
+	"Superset;":                 '\U00002283',
+	"SupersetEqual;":            '\U00002287',
+	"Supset;":                   '\U000022D1',
+	"THORN;":                    '\U000000DE',
+	"TRADE;":                    '\U00002122',
+	"TSHcy;":                    '\U0000040B',
+	"TScy;":                     '\U00000426',
+	"Tab;":                      '\U00000009',
+	"Tau;":                      '\U000003A4',
+	"Tcaron;":                   '\U00000164',
+	"Tcedil;":                   '\U00000162',
+	"Tcy;":                      '\U00000422',
+	"Tfr;":                      '\U0001D517',
+	"Therefore;":                '\U00002234',
+	"Theta;":                    '\U00000398',
+	"ThinSpace;":                '\U00002009',
+	"Tilde;":                    '\U0000223C',
+	"TildeEqual;":               '\U00002243',
+	"TildeFullEqual;":           '\U00002245',
+	"TildeTilde;":               '\U00002248',
+	"Topf;":                     '\U0001D54B',
+	"TripleDot;":                '\U000020DB',
+	"Tscr;":                     '\U0001D4AF',
+	"Tstrok;":                   '\U00000166',
+	"Uacute;":                   '\U000000DA',
+	"Uarr;":                     '\U0000219F',
+	"Uarrocir;":                 '\U00002949',
+	"Ubrcy;":                    '\U0000040E',
+	"Ubreve;":                   '\U0000016C',
+	"Ucirc;":                    '\U000000DB',
+	"Ucy;":                      '\U00000423',
+	"Udblac;":                   '\U00000170',
+	"Ufr;":                      '\U0001D518',
+	"Ugrave;":                   '\U000000D9',
+	"Umacr;":                    '\U0000016A',
+	"UnderBar;":                 '\U0000005F',
+	"UnderBrace;":               '\U000023DF',
+	"UnderBracket;":             '\U000023B5',
+	"UnderParenthesis;":         '\U000023DD',
+	"Union;":                    '\U000022C3',
+	"UnionPlus;":                '\U0000228E',
+	"Uogon;":                    '\U00000172',
+	"Uopf;":                     '\U0001D54C',
+	"UpArrow;":                  '\U00002191',
+	"UpArrowBar;":               '\U00002912',
+	"UpArrowDownArrow;":         '\U000021C5',
+	"UpDownArrow;":              '\U00002195',
+	"UpEquilibrium;":            '\U0000296E',
+	"UpTee;":                    '\U000022A5',
+	"UpTeeArrow;":               '\U000021A5',
+	"Uparrow;":                  '\U000021D1',
+	"Updownarrow;":              '\U000021D5',
+	"UpperLeftArrow;":           '\U00002196',
+	"UpperRightArrow;":          '\U00002197',
+	"Upsi;":                     '\U000003D2',
+	"Upsilon;":                  '\U000003A5',
+	"Uring;":                    '\U0000016E',
+	"Uscr;":                     '\U0001D4B0',
+	"Utilde;":                   '\U00000168',
+	"Uuml;":                     '\U000000DC',
+	"VDash;":                    '\U000022AB',
+	"Vbar;":                     '\U00002AEB',
+	"Vcy;":                      '\U00000412',
+	"Vdash;":                    '\U000022A9',
+	"Vdashl;":                   '\U00002AE6',
+	"Vee;":                      '\U000022C1',
+	"Verbar;":                   '\U00002016',
+	"Vert;":                     '\U00002016',
+	"VerticalBar;":              '\U00002223',
+	"VerticalLine;":             '\U0000007C',
+	"VerticalSeparator;":        '\U00002758',
+	"VerticalTilde;":            '\U00002240',
+	"VeryThinSpace;":            '\U0000200A',
+	"Vfr;":                      '\U0001D519',
+	"Vopf;":                     '\U0001D54D',
+	"Vscr;":                     '\U0001D4B1',
+	"Vvdash;":                   '\U000022AA',
+	"Wcirc;":                    '\U00000174',
+	"Wedge;":                    '\U000022C0',
+	"Wfr;":                      '\U0001D51A',
+	"Wopf;":                     '\U0001D54E',
+	"Wscr;":                     '\U0001D4B2',
+	"Xfr;":                      '\U0001D51B',
+	"Xi;":                       '\U0000039E',
+	"Xopf;":                     '\U0001D54F',
+	"Xscr;":                     '\U0001D4B3',
+	"YAcy;":                     '\U0000042F',
+	"YIcy;":                     '\U00000407',
+	"YUcy;":                     '\U0000042E',
+	"Yacute;":                   '\U000000DD',
+	"Ycirc;":                    '\U00000176',
+	"Ycy;":                      '\U0000042B',
+	"Yfr;":                      '\U0001D51C',
+	"Yopf;":                     '\U0001D550',
+	"Yscr;":                     '\U0001D4B4',
+	"Yuml;":                     '\U00000178',
+	"ZHcy;":                     '\U00000416',
+	"Zacute;":                   '\U00000179',
+	"Zcaron;":                   '\U0000017D',
+	"Zcy;":                      '\U00000417',
+	"Zdot;":                     '\U0000017B',
+	"ZeroWidthSpace;":           '\U0000200B',
+	"Zeta;":                     '\U00000396',
+	"Zfr;":                      '\U00002128',
+	"Zopf;":                     '\U00002124',
+	"Zscr;":                     '\U0001D4B5',
+	"aacute;":                   '\U000000E1',
+	"abreve;":                   '\U00000103',
+	"ac;":                       '\U0000223E',
+	"acd;":                      '\U0000223F',
+	"acirc;":                    '\U000000E2',
+	"acute;":                    '\U000000B4',
+	"acy;":                      '\U00000430',
+	"aelig;":                    '\U000000E6',
+	"af;":                       '\U00002061',
+	"afr;":                      '\U0001D51E',
+	"agrave;":                   '\U000000E0',
+	"alefsym;":                  '\U00002135',
+	"aleph;":                    '\U00002135',
+	"alpha;":                    '\U000003B1',
+	"amacr;":                    '\U00000101',
+	"amalg;":                    '\U00002A3F',
+	"amp;":                      '\U00000026',
+	"and;":                      '\U00002227',
+	"andand;":                   '\U00002A55',
+	"andd;":                     '\U00002A5C',
+	"andslope;":                 '\U00002A58',
+	"andv;":                     '\U00002A5A',
+	"ang;":                      '\U00002220',
+	"ange;":                     '\U000029A4',
+	"angle;":                    '\U00002220',
+	"angmsd;":                   '\U00002221',
+	"angmsdaa;":                 '\U000029A8',
+	"angmsdab;":                 '\U000029A9',
+	"angmsdac;":                 '\U000029AA',
+	"angmsdad;":                 '\U000029AB',
+	"angmsdae;":                 '\U000029AC',
+	"angmsdaf;":                 '\U000029AD',
+	"angmsdag;":                 '\U000029AE',
+	"angmsdah;":                 '\U000029AF',
+	"angrt;":                    '\U0000221F',
+	"angrtvb;":                  '\U000022BE',
+	"angrtvbd;":                 '\U0000299D',
+	"angsph;":                   '\U00002222',
+	"angst;":                    '\U000000C5',
+	"angzarr;":                  '\U0000237C',
+	"aogon;":                    '\U00000105',
+	"aopf;":                     '\U0001D552',
+	"ap;":                       '\U00002248',
+	"apE;":                      '\U00002A70',
+	"apacir;":                   '\U00002A6F',
+	"ape;":                      '\U0000224A',
+	"apid;":                     '\U0000224B',
+	"apos;":                     '\U00000027',
+	"approx;":                   '\U00002248',
+	"approxeq;":                 '\U0000224A',
+	"aring;":                    '\U000000E5',
+	"ascr;":                     '\U0001D4B6',
+	"ast;":                      '\U0000002A',
+	"asymp;":                    '\U00002248',
+	"asympeq;":                  '\U0000224D',
+	"atilde;":                   '\U000000E3',
+	"auml;":                     '\U000000E4',
+	"awconint;":                 '\U00002233',
+	"awint;":                    '\U00002A11',
+	"bNot;":                     '\U00002AED',
+	"backcong;":                 '\U0000224C',
+	"backepsilon;":              '\U000003F6',
+	"backprime;":                '\U00002035',
+	"backsim;":                  '\U0000223D',
+	"backsimeq;":                '\U000022CD',
+	"barvee;":                   '\U000022BD',
+	"barwed;":                   '\U00002305',
+	"barwedge;":                 '\U00002305',
+	"bbrk;":                     '\U000023B5',
+	"bbrktbrk;":                 '\U000023B6',
+	"bcong;":                    '\U0000224C',
+	"bcy;":                      '\U00000431',
+	"bdquo;":                    '\U0000201E',
+	"becaus;":                   '\U00002235',
+	"because;":                  '\U00002235',
+	"bemptyv;":                  '\U000029B0',
+	"bepsi;":                    '\U000003F6',
+	"bernou;":                   '\U0000212C',
+	"beta;":                     '\U000003B2',
+	"beth;":                     '\U00002136',
+	"between;":                  '\U0000226C',
+	"bfr;":                      '\U0001D51F',
+	"bigcap;":                   '\U000022C2',
+	"bigcirc;":                  '\U000025EF',
+	"bigcup;":                   '\U000022C3',
+	"bigodot;":                  '\U00002A00',
+	"bigoplus;":                 '\U00002A01',
+	"bigotimes;":                '\U00002A02',
+	"bigsqcup;":                 '\U00002A06',
+	"bigstar;":                  '\U00002605',
+	"bigtriangledown;":          '\U000025BD',
+	"bigtriangleup;":            '\U000025B3',
+	"biguplus;":                 '\U00002A04',
+	"bigvee;":                   '\U000022C1',
+	"bigwedge;":                 '\U000022C0',
+	"bkarow;":                   '\U0000290D',
+	"blacklozenge;":             '\U000029EB',
+	"blacksquare;":              '\U000025AA',
+	"blacktriangle;":            '\U000025B4',
+	"blacktriangledown;":        '\U000025BE',
+	"blacktriangleleft;":        '\U000025C2',
+	"blacktriangleright;":       '\U000025B8',
+	"blank;":                    '\U00002423',
+	"blk12;":                    '\U00002592',
+	"blk14;":                    '\U00002591',
+	"blk34;":                    '\U00002593',
+	"block;":                    '\U00002588',
+	"bnot;":                     '\U00002310',
+	"bopf;":                     '\U0001D553',
+	"bot;":                      '\U000022A5',
+	"bottom;":                   '\U000022A5',
+	"bowtie;":                   '\U000022C8',
+	"boxDL;":                    '\U00002557',
+	"boxDR;":                    '\U00002554',
+	"boxDl;":                    '\U00002556',
+	"boxDr;":                    '\U00002553',
+	"boxH;":                     '\U00002550',
+	"boxHD;":                    '\U00002566',
+	"boxHU;":                    '\U00002569',
+	"boxHd;":                    '\U00002564',
+	"boxHu;":                    '\U00002567',
+	"boxUL;":                    '\U0000255D',
+	"boxUR;":                    '\U0000255A',
+	"boxUl;":                    '\U0000255C',
+	"boxUr;":                    '\U00002559',
+	"boxV;":                     '\U00002551',
+	"boxVH;":                    '\U0000256C',
+	"boxVL;":                    '\U00002563',
+	"boxVR;":                    '\U00002560',
+	"boxVh;":                    '\U0000256B',
+	"boxVl;":                    '\U00002562',
+	"boxVr;":                    '\U0000255F',
+	"boxbox;":                   '\U000029C9',
+	"boxdL;":                    '\U00002555',
+	"boxdR;":                    '\U00002552',
+	"boxdl;":                    '\U00002510',
+	"boxdr;":                    '\U0000250C',
+	"boxh;":                     '\U00002500',
+	"boxhD;":                    '\U00002565',
+	"boxhU;":                    '\U00002568',
+	"boxhd;":                    '\U0000252C',
+	"boxhu;":                    '\U00002534',
+	"boxminus;":                 '\U0000229F',
+	"boxplus;":                  '\U0000229E',
+	"boxtimes;":                 '\U000022A0',
+	"boxuL;":                    '\U0000255B',
+	"boxuR;":                    '\U00002558',
+	"boxul;":                    '\U00002518',
+	"boxur;":                    '\U00002514',
+	"boxv;":                     '\U00002502',
+	"boxvH;":                    '\U0000256A',
+	"boxvL;":                    '\U00002561',
+	"boxvR;":                    '\U0000255E',
+	"boxvh;":                    '\U0000253C',
+	"boxvl;":                    '\U00002524',
+	"boxvr;":                    '\U0000251C',
+	"bprime;":                   '\U00002035',
+	"breve;":                    '\U000002D8',
+	"brvbar;":                   '\U000000A6',
+	"bscr;":                     '\U0001D4B7',
+	"bsemi;":                    '\U0000204F',
+	"bsim;":                     '\U0000223D',
+	"bsime;":                    '\U000022CD',
+	"bsol;":                     '\U0000005C',
+	"bsolb;":                    '\U000029C5',
+	"bsolhsub;":                 '\U000027C8',
+	"bull;":                     '\U00002022',
+	"bullet;":                   '\U00002022',
+	"bump;":                     '\U0000224E',
+	"bumpE;":                    '\U00002AAE',
+	"bumpe;":                    '\U0000224F',
+	"bumpeq;":                   '\U0000224F',
+	"cacute;":                   '\U00000107',
+	"cap;":                      '\U00002229',
+	"capand;":                   '\U00002A44',
+	"capbrcup;":                 '\U00002A49',
+	"capcap;":                   '\U00002A4B',
+	"capcup;":                   '\U00002A47',
+	"capdot;":                   '\U00002A40',
+	"caret;":                    '\U00002041',
+	"caron;":                    '\U000002C7',
+	"ccaps;":                    '\U00002A4D',
+	"ccaron;":                   '\U0000010D',
+	"ccedil;":                   '\U000000E7',
+	"ccirc;":                    '\U00000109',
+	"ccups;":                    '\U00002A4C',
+	"ccupssm;":                  '\U00002A50',
+	"cdot;":                     '\U0000010B',
+	"cedil;":                    '\U000000B8',
+	"cemptyv;":                  '\U000029B2',
+	"cent;":                     '\U000000A2',
+	"centerdot;":                '\U000000B7',
+	"cfr;":                      '\U0001D520',
+	"chcy;":                     '\U00000447',
+	"check;":                    '\U00002713',
+	"checkmark;":                '\U00002713',
+	"chi;":                      '\U000003C7',
+	"cir;":                      '\U000025CB',
+	"cirE;":                     '\U000029C3',
+	"circ;":                     '\U000002C6',
+	"circeq;":                   '\U00002257',
+	"circlearrowleft;":          '\U000021BA',
+	"circlearrowright;":         '\U000021BB',
+	"circledR;":                 '\U000000AE',
+	"circledS;":                 '\U000024C8',
+	"circledast;":               '\U0000229B',
+	"circledcirc;":              '\U0000229A',
+	"circleddash;":              '\U0000229D',
+	"cire;":                     '\U00002257',
+	"cirfnint;":                 '\U00002A10',
+	"cirmid;":                   '\U00002AEF',
+	"cirscir;":                  '\U000029C2',
+	"clubs;":                    '\U00002663',
+	"clubsuit;":                 '\U00002663',
+	"colon;":                    '\U0000003A',
+	"colone;":                   '\U00002254',
+	"coloneq;":                  '\U00002254',
+	"comma;":                    '\U0000002C',
+	"commat;":                   '\U00000040',
+	"comp;":                     '\U00002201',
+	"compfn;":                   '\U00002218',
+	"complement;":               '\U00002201',
+	"complexes;":                '\U00002102',
+	"cong;":                     '\U00002245',
+	"congdot;":                  '\U00002A6D',
+	"conint;":                   '\U0000222E',
+	"copf;":                     '\U0001D554',
+	"coprod;":                   '\U00002210',
+	"copy;":                     '\U000000A9',
+	"copysr;":                   '\U00002117',
+	"crarr;":                    '\U000021B5',
+	"cross;":                    '\U00002717',
+	"cscr;":                     '\U0001D4B8',
+	"csub;":                     '\U00002ACF',
+	"csube;":                    '\U00002AD1',
+	"csup;":                     '\U00002AD0',
+	"csupe;":                    '\U00002AD2',
+	"ctdot;":                    '\U000022EF',
+	"cudarrl;":                  '\U00002938',
+	"cudarrr;":                  '\U00002935',
+	"cuepr;":                    '\U000022DE',
+	"cuesc;":                    '\U000022DF',
+	"cularr;":                   '\U000021B6',
+	"cularrp;":                  '\U0000293D',
+	"cup;":                      '\U0000222A',
+	"cupbrcap;":                 '\U00002A48',
+	"cupcap;":                   '\U00002A46',
+	"cupcup;":                   '\U00002A4A',
+	"cupdot;":                   '\U0000228D',
+	"cupor;":                    '\U00002A45',
+	"curarr;":                   '\U000021B7',
+	"curarrm;":                  '\U0000293C',
+	"curlyeqprec;":              '\U000022DE',
+	"curlyeqsucc;":              '\U000022DF',
+	"curlyvee;":                 '\U000022CE',
+	"curlywedge;":               '\U000022CF',
+	"curren;":                   '\U000000A4',
+	"curvearrowleft;":           '\U000021B6',
+	"curvearrowright;":          '\U000021B7',
+	"cuvee;":                    '\U000022CE',
+	"cuwed;":                    '\U000022CF',
+	"cwconint;":                 '\U00002232',
+	"cwint;":                    '\U00002231',
+	"cylcty;":                   '\U0000232D',
+	"dArr;":                     '\U000021D3',
+	"dHar;":                     '\U00002965',
+	"dagger;":                   '\U00002020',
+	"daleth;":                   '\U00002138',
+	"darr;":                     '\U00002193',
+	"dash;":                     '\U00002010',
+	"dashv;":                    '\U000022A3',
+	"dbkarow;":                  '\U0000290F',
+	"dblac;":                    '\U000002DD',
+	"dcaron;":                   '\U0000010F',
+	"dcy;":                      '\U00000434',
+	"dd;":                       '\U00002146',
+	"ddagger;":                  '\U00002021',
+	"ddarr;":                    '\U000021CA',
+	"ddotseq;":                  '\U00002A77',
+	"deg;":                      '\U000000B0',
+	"delta;":                    '\U000003B4',
+	"demptyv;":                  '\U000029B1',
+	"dfisht;":                   '\U0000297F',
+	"dfr;":                      '\U0001D521',
+	"dharl;":                    '\U000021C3',
+	"dharr;":                    '\U000021C2',
+	"diam;":                     '\U000022C4',
+	"diamond;":                  '\U000022C4',
+	"diamondsuit;":              '\U00002666',
+	"diams;":                    '\U00002666',
+	"die;":                      '\U000000A8',
+	"digamma;":                  '\U000003DD',
+	"disin;":                    '\U000022F2',
+	"div;":                      '\U000000F7',
+	"divide;":                   '\U000000F7',
+	"divideontimes;":            '\U000022C7',
+	"divonx;":                   '\U000022C7',
+	"djcy;":                     '\U00000452',
+	"dlcorn;":                   '\U0000231E',
+	"dlcrop;":                   '\U0000230D',
+	"dollar;":                   '\U00000024',
+	"dopf;":                     '\U0001D555',
+	"dot;":                      '\U000002D9',
+	"doteq;":                    '\U00002250',
+	"doteqdot;":                 '\U00002251',
+	"dotminus;":                 '\U00002238',
+	"dotplus;":                  '\U00002214',
+	"dotsquare;":                '\U000022A1',
+	"doublebarwedge;":           '\U00002306',
+	"downarrow;":                '\U00002193',
+	"downdownarrows;":           '\U000021CA',
+	"downharpoonleft;":          '\U000021C3',
+	"downharpoonright;":         '\U000021C2',
+	"drbkarow;":                 '\U00002910',
+	"drcorn;":                   '\U0000231F',
+	"drcrop;":                   '\U0000230C',
+	"dscr;":                     '\U0001D4B9',
+	"dscy;":                     '\U00000455',
+	"dsol;":                     '\U000029F6',
+	"dstrok;":                   '\U00000111',
+	"dtdot;":                    '\U000022F1',
+	"dtri;":                     '\U000025BF',
+	"dtrif;":                    '\U000025BE',
+	"duarr;":                    '\U000021F5',
+	"duhar;":                    '\U0000296F',
+	"dwangle;":                  '\U000029A6',
+	"dzcy;":                     '\U0000045F',
+	"dzigrarr;":                 '\U000027FF',
+	"eDDot;":                    '\U00002A77',
+	"eDot;":                     '\U00002251',
+	"eacute;":                   '\U000000E9',
+	"easter;":                   '\U00002A6E',
+	"ecaron;":                   '\U0000011B',
+	"ecir;":                     '\U00002256',
+	"ecirc;":                    '\U000000EA',
+	"ecolon;":                   '\U00002255',
+	"ecy;":                      '\U0000044D',
+	"edot;":                     '\U00000117',
+	"ee;":                       '\U00002147',
+	"efDot;":                    '\U00002252',
+	"efr;":                      '\U0001D522',
+	"eg;":                       '\U00002A9A',
+	"egrave;":                   '\U000000E8',
+	"egs;":                      '\U00002A96',
+	"egsdot;":                   '\U00002A98',
+	"el;":                       '\U00002A99',
+	"elinters;":                 '\U000023E7',
+	"ell;":                      '\U00002113',
+	"els;":                      '\U00002A95',
+	"elsdot;":                   '\U00002A97',
+	"emacr;":                    '\U00000113',
+	"empty;":                    '\U00002205',
+	"emptyset;":                 '\U00002205',
+	"emptyv;":                   '\U00002205',
+	"emsp;":                     '\U00002003',
+	"emsp13;":                   '\U00002004',
+	"emsp14;":                   '\U00002005',
+	"eng;":                      '\U0000014B',
+	"ensp;":                     '\U00002002',
+	"eogon;":                    '\U00000119',
+	"eopf;":                     '\U0001D556',
+	"epar;":                     '\U000022D5',
+	"eparsl;":                   '\U000029E3',
+	"eplus;":                    '\U00002A71',
+	"epsi;":                     '\U000003B5',
+	"epsilon;":                  '\U000003B5',
+	"epsiv;":                    '\U000003F5',
+	"eqcirc;":                   '\U00002256',
+	"eqcolon;":                  '\U00002255',
+	"eqsim;":                    '\U00002242',
+	"eqslantgtr;":               '\U00002A96',
+	"eqslantless;":              '\U00002A95',
+	"equals;":                   '\U0000003D',
+	"equest;":                   '\U0000225F',
+	"equiv;":                    '\U00002261',
+	"equivDD;":                  '\U00002A78',
+	"eqvparsl;":                 '\U000029E5',
+	"erDot;":                    '\U00002253',
+	"erarr;":                    '\U00002971',
+	"escr;":                     '\U0000212F',
+	"esdot;":                    '\U00002250',
+	"esim;":                     '\U00002242',
+	"eta;":                      '\U000003B7',
+	"eth;":                      '\U000000F0',
+	"euml;":                     '\U000000EB',
+	"euro;":                     '\U000020AC',
+	"excl;":                     '\U00000021',
+	"exist;":                    '\U00002203',
+	"expectation;":              '\U00002130',
+	"exponentiale;":             '\U00002147',
+	"fallingdotseq;":            '\U00002252',
+	"fcy;":                      '\U00000444',
+	"female;":                   '\U00002640',
+	"ffilig;":                   '\U0000FB03',
+	"fflig;":                    '\U0000FB00',
+	"ffllig;":                   '\U0000FB04',
+	"ffr;":                      '\U0001D523',
+	"filig;":                    '\U0000FB01',
+	"flat;":                     '\U0000266D',
+	"fllig;":                    '\U0000FB02',
+	"fltns;":                    '\U000025B1',
+	"fnof;":                     '\U00000192',
+	"fopf;":                     '\U0001D557',
+	"forall;":                   '\U00002200',
+	"fork;":                     '\U000022D4',
+	"forkv;":                    '\U00002AD9',
+	"fpartint;":                 '\U00002A0D',
+	"frac12;":                   '\U000000BD',
+	"frac13;":                   '\U00002153',
+	"frac14;":                   '\U000000BC',
+	"frac15;":                   '\U00002155',
+	"frac16;":                   '\U00002159',
+	"frac18;":                   '\U0000215B',
+	"frac23;":                   '\U00002154',
+	"frac25;":                   '\U00002156',
+	"frac34;":                   '\U000000BE',
+	"frac35;":                   '\U00002157',
+	"frac38;":                   '\U0000215C',
+	"frac45;":                   '\U00002158',
+	"frac56;":                   '\U0000215A',
+	"frac58;":                   '\U0000215D',
+	"frac78;":                   '\U0000215E',
+	"frasl;":                    '\U00002044',
+	"frown;":                    '\U00002322',
+	"fscr;":                     '\U0001D4BB',
+	"gE;":                       '\U00002267',
+	"gEl;":                      '\U00002A8C',
+	"gacute;":                   '\U000001F5',
+	"gamma;":                    '\U000003B3',
+	"gammad;":                   '\U000003DD',
+	"gap;":                      '\U00002A86',
+	"gbreve;":                   '\U0000011F',
+	"gcirc;":                    '\U0000011D',
+	"gcy;":                      '\U00000433',
+	"gdot;":                     '\U00000121',
+	"ge;":                       '\U00002265',
+	"gel;":                      '\U000022DB',
+	"geq;":                      '\U00002265',
+	"geqq;":                     '\U00002267',
+	"geqslant;":                 '\U00002A7E',
+	"ges;":                      '\U00002A7E',
+	"gescc;":                    '\U00002AA9',
+	"gesdot;":                   '\U00002A80',
+	"gesdoto;":                  '\U00002A82',
+	"gesdotol;":                 '\U00002A84',
+	"gesles;":                   '\U00002A94',
+	"gfr;":                      '\U0001D524',
+	"gg;":                       '\U0000226B',
+	"ggg;":                      '\U000022D9',
+	"gimel;":                    '\U00002137',
+	"gjcy;":                     '\U00000453',
+	"gl;":                       '\U00002277',
+	"glE;":                      '\U00002A92',
+	"gla;":                      '\U00002AA5',
+	"glj;":                      '\U00002AA4',
+	"gnE;":                      '\U00002269',
+	"gnap;":                     '\U00002A8A',
+	"gnapprox;":                 '\U00002A8A',
+	"gne;":                      '\U00002A88',
+	"gneq;":                     '\U00002A88',
+	"gneqq;":                    '\U00002269',
+	"gnsim;":                    '\U000022E7',
+	"gopf;":                     '\U0001D558',
+	"grave;":                    '\U00000060',
+	"gscr;":                     '\U0000210A',
+	"gsim;":                     '\U00002273',
+	"gsime;":                    '\U00002A8E',
+	"gsiml;":                    '\U00002A90',
+	"gt;":                       '\U0000003E',
+	"gtcc;":                     '\U00002AA7',
+	"gtcir;":                    '\U00002A7A',
+	"gtdot;":                    '\U000022D7',
+	"gtlPar;":                   '\U00002995',
+	"gtquest;":                  '\U00002A7C',
+	"gtrapprox;":                '\U00002A86',
+	"gtrarr;":                   '\U00002978',
+	"gtrdot;":                   '\U000022D7',
+	"gtreqless;":                '\U000022DB',
+	"gtreqqless;":               '\U00002A8C',
+	"gtrless;":                  '\U00002277',
+	"gtrsim;":                   '\U00002273',
+	"hArr;":                     '\U000021D4',
+	"hairsp;":                   '\U0000200A',
+	"half;":                     '\U000000BD',
+	"hamilt;":                   '\U0000210B',
+	"hardcy;":                   '\U0000044A',
+	"harr;":                     '\U00002194',
+	"harrcir;":                  '\U00002948',
+	"harrw;":                    '\U000021AD',
+	"hbar;":                     '\U0000210F',
+	"hcirc;":                    '\U00000125',
+	"hearts;":                   '\U00002665',
+	"heartsuit;":                '\U00002665',
+	"hellip;":                   '\U00002026',
+	"hercon;":                   '\U000022B9',
+	"hfr;":                      '\U0001D525',
+	"hksearow;":                 '\U00002925',
+	"hkswarow;":                 '\U00002926',
+	"hoarr;":                    '\U000021FF',
+	"homtht;":                   '\U0000223B',
+	"hookleftarrow;":            '\U000021A9',
+	"hookrightarrow;":           '\U000021AA',
+	"hopf;":                     '\U0001D559',
+	"horbar;":                   '\U00002015',
+	"hscr;":                     '\U0001D4BD',
+	"hslash;":                   '\U0000210F',
+	"hstrok;":                   '\U00000127',
+	"hybull;":                   '\U00002043',
+	"hyphen;":                   '\U00002010',
+	"iacute;":                   '\U000000ED',
+	"ic;":                       '\U00002063',
+	"icirc;":                    '\U000000EE',
+	"icy;":                      '\U00000438',
+	"iecy;":                     '\U00000435',
+	"iexcl;":                    '\U000000A1',
+	"iff;":                      '\U000021D4',
+	"ifr;":                      '\U0001D526',
+	"igrave;":                   '\U000000EC',
+	"ii;":                       '\U00002148',
+	"iiiint;":                   '\U00002A0C',
+	"iiint;":                    '\U0000222D',
+	"iinfin;":                   '\U000029DC',
+	"iiota;":                    '\U00002129',
+	"ijlig;":                    '\U00000133',
+	"imacr;":                    '\U0000012B',
+	"image;":                    '\U00002111',
+	"imagline;":                 '\U00002110',
+	"imagpart;":                 '\U00002111',
+	"imath;":                    '\U00000131',
+	"imof;":                     '\U000022B7',
+	"imped;":                    '\U000001B5',
+	"in;":                       '\U00002208',
+	"incare;":                   '\U00002105',
+	"infin;":                    '\U0000221E',
+	"infintie;":                 '\U000029DD',
+	"inodot;":                   '\U00000131',
+	"int;":                      '\U0000222B',
+	"intcal;":                   '\U000022BA',
+	"integers;":                 '\U00002124',
+	"intercal;":                 '\U000022BA',
+	"intlarhk;":                 '\U00002A17',
+	"intprod;":                  '\U00002A3C',
+	"iocy;":                     '\U00000451',
+	"iogon;":                    '\U0000012F',
+	"iopf;":                     '\U0001D55A',
+	"iota;":                     '\U000003B9',
+	"iprod;":                    '\U00002A3C',
+	"iquest;":                   '\U000000BF',
+	"iscr;":                     '\U0001D4BE',
+	"isin;":                     '\U00002208',
+	"isinE;":                    '\U000022F9',
+	"isindot;":                  '\U000022F5',
+	"isins;":                    '\U000022F4',
+	"isinsv;":                   '\U000022F3',
+	"isinv;":                    '\U00002208',
+	"it;":                       '\U00002062',
+	"itilde;":                   '\U00000129',
+	"iukcy;":                    '\U00000456',
+	"iuml;":                     '\U000000EF',
+	"jcirc;":                    '\U00000135',
+	"jcy;":                      '\U00000439',
+	"jfr;":                      '\U0001D527',
+	"jmath;":                    '\U00000237',
+	"jopf;":                     '\U0001D55B',
+	"jscr;":                     '\U0001D4BF',
+	"jsercy;":                   '\U00000458',
+	"jukcy;":                    '\U00000454',
+	"kappa;":                    '\U000003BA',
+	"kappav;":                   '\U000003F0',
+	"kcedil;":                   '\U00000137',
+	"kcy;":                      '\U0000043A',
+	"kfr;":                      '\U0001D528',
+	"kgreen;":                   '\U00000138',
+	"khcy;":                     '\U00000445',
+	"kjcy;":                     '\U0000045C',
+	"kopf;":                     '\U0001D55C',
+	"kscr;":                     '\U0001D4C0',
+	"lAarr;":                    '\U000021DA',
+	"lArr;":                     '\U000021D0',
+	"lAtail;":                   '\U0000291B',
+	"lBarr;":                    '\U0000290E',
+	"lE;":                       '\U00002266',
+	"lEg;":                      '\U00002A8B',
+	"lHar;":                     '\U00002962',
+	"lacute;":                   '\U0000013A',
+	"laemptyv;":                 '\U000029B4',
+	"lagran;":                   '\U00002112',
+	"lambda;":                   '\U000003BB',
+	"lang;":                     '\U000027E8',
+	"langd;":                    '\U00002991',
+	"langle;":                   '\U000027E8',
+	"lap;":                      '\U00002A85',
+	"laquo;":                    '\U000000AB',
+	"larr;":                     '\U00002190',
+	"larrb;":                    '\U000021E4',
+	"larrbfs;":                  '\U0000291F',
+	"larrfs;":                   '\U0000291D',
+	"larrhk;":                   '\U000021A9',
+	"larrlp;":                   '\U000021AB',
+	"larrpl;":                   '\U00002939',
+	"larrsim;":                  '\U00002973',
+	"larrtl;":                   '\U000021A2',
+	"lat;":                      '\U00002AAB',
+	"latail;":                   '\U00002919',
+	"late;":                     '\U00002AAD',
+	"lbarr;":                    '\U0000290C',
+	"lbbrk;":                    '\U00002772',
+	"lbrace;":                   '\U0000007B',
+	"lbrack;":                   '\U0000005B',
+	"lbrke;":                    '\U0000298B',
+	"lbrksld;":                  '\U0000298F',
+	"lbrkslu;":                  '\U0000298D',
+	"lcaron;":                   '\U0000013E',
+	"lcedil;":                   '\U0000013C',
+	"lceil;":                    '\U00002308',
+	"lcub;":                     '\U0000007B',
+	"lcy;":                      '\U0000043B',
+	"ldca;":                     '\U00002936',
+	"ldquo;":                    '\U0000201C',
+	"ldquor;":                   '\U0000201E',
+	"ldrdhar;":                  '\U00002967',
+	"ldrushar;":                 '\U0000294B',
+	"ldsh;":                     '\U000021B2',
+	"le;":                       '\U00002264',
+	"leftarrow;":                '\U00002190',
+	"leftarrowtail;":            '\U000021A2',
+	"leftharpoondown;":          '\U000021BD',
+	"leftharpoonup;":            '\U000021BC',
+	"leftleftarrows;":           '\U000021C7',
+	"leftrightarrow;":           '\U00002194',
+	"leftrightarrows;":          '\U000021C6',
+	"leftrightharpoons;":        '\U000021CB',
+	"leftrightsquigarrow;":      '\U000021AD',
+	"leftthreetimes;":           '\U000022CB',
+	"leg;":                      '\U000022DA',
+	"leq;":                      '\U00002264',
+	"leqq;":                     '\U00002266',
+	"leqslant;":                 '\U00002A7D',
+	"les;":                      '\U00002A7D',
+	"lescc;":                    '\U00002AA8',
+	"lesdot;":                   '\U00002A7F',
+	"lesdoto;":                  '\U00002A81',
+	"lesdotor;":                 '\U00002A83',
+	"lesges;":                   '\U00002A93',
+	"lessapprox;":               '\U00002A85',
+	"lessdot;":                  '\U000022D6',
+	"lesseqgtr;":                '\U000022DA',
+	"lesseqqgtr;":               '\U00002A8B',
+	"lessgtr;":                  '\U00002276',
+	"lesssim;":                  '\U00002272',
+	"lfisht;":                   '\U0000297C',
+	"lfloor;":                   '\U0000230A',
+	"lfr;":                      '\U0001D529',
+	"lg;":                       '\U00002276',
+	"lgE;":                      '\U00002A91',
+	"lhard;":                    '\U000021BD',
+	"lharu;":                    '\U000021BC',
+	"lharul;":                   '\U0000296A',
+	"lhblk;":                    '\U00002584',
+	"ljcy;":                     '\U00000459',
+	"ll;":                       '\U0000226A',
+	"llarr;":                    '\U000021C7',
+	"llcorner;":                 '\U0000231E',
+	"llhard;":                   '\U0000296B',
+	"lltri;":                    '\U000025FA',
+	"lmidot;":                   '\U00000140',
+	"lmoust;":                   '\U000023B0',
+	"lmoustache;":               '\U000023B0',
+	"lnE;":                      '\U00002268',
+	"lnap;":                     '\U00002A89',
+	"lnapprox;":                 '\U00002A89',
+	"lne;":                      '\U00002A87',
+	"lneq;":                     '\U00002A87',
+	"lneqq;":                    '\U00002268',
+	"lnsim;":                    '\U000022E6',
+	"loang;":                    '\U000027EC',
+	"loarr;":                    '\U000021FD',
+	"lobrk;":                    '\U000027E6',
+	"longleftarrow;":            '\U000027F5',
+	"longleftrightarrow;":       '\U000027F7',
+	"longmapsto;":               '\U000027FC',
+	"longrightarrow;":           '\U000027F6',
+	"looparrowleft;":            '\U000021AB',
+	"looparrowright;":           '\U000021AC',
+	"lopar;":                    '\U00002985',
+	"lopf;":                     '\U0001D55D',
+	"loplus;":                   '\U00002A2D',
+	"lotimes;":                  '\U00002A34',
+	"lowast;":                   '\U00002217',
+	"lowbar;":                   '\U0000005F',
+	"loz;":                      '\U000025CA',
+	"lozenge;":                  '\U000025CA',
+	"lozf;":                     '\U000029EB',
+	"lpar;":                     '\U00000028',
+	"lparlt;":                   '\U00002993',
+	"lrarr;":                    '\U000021C6',
+	"lrcorner;":                 '\U0000231F',
+	"lrhar;":                    '\U000021CB',
+	"lrhard;":                   '\U0000296D',
+	"lrm;":                      '\U0000200E',
+	"lrtri;":                    '\U000022BF',
+	"lsaquo;":                   '\U00002039',
+	"lscr;":                     '\U0001D4C1',
+	"lsh;":                      '\U000021B0',
+	"lsim;":                     '\U00002272',
+	"lsime;":                    '\U00002A8D',
+	"lsimg;":                    '\U00002A8F',
+	"lsqb;":                     '\U0000005B',
+	"lsquo;":                    '\U00002018',
+	"lsquor;":                   '\U0000201A',
+	"lstrok;":                   '\U00000142',
+	"lt;":                       '\U0000003C',
+	"ltcc;":                     '\U00002AA6',
+	"ltcir;":                    '\U00002A79',
+	"ltdot;":                    '\U000022D6',
+	"lthree;":                   '\U000022CB',
+	"ltimes;":                   '\U000022C9',
+	"ltlarr;":                   '\U00002976',
+	"ltquest;":                  '\U00002A7B',
+	"ltrPar;":                   '\U00002996',
+	"ltri;":                     '\U000025C3',
+	"ltrie;":                    '\U000022B4',
+	"ltrif;":                    '\U000025C2',
+	"lurdshar;":                 '\U0000294A',
+	"luruhar;":                  '\U00002966',
+	"mDDot;":                    '\U0000223A',
+	"macr;":                     '\U000000AF',
+	"male;":                     '\U00002642',
+	"malt;":                     '\U00002720',
+	"maltese;":                  '\U00002720',
+	"map;":                      '\U000021A6',
+	"mapsto;":                   '\U000021A6',
+	"mapstodown;":               '\U000021A7',
+	"mapstoleft;":               '\U000021A4',
+	"mapstoup;":                 '\U000021A5',
+	"marker;":                   '\U000025AE',
+	"mcomma;":                   '\U00002A29',
+	"mcy;":                      '\U0000043C',
+	"mdash;":                    '\U00002014',
+	"measuredangle;":            '\U00002221',
+	"mfr;":                      '\U0001D52A',
+	"mho;":                      '\U00002127',
+	"micro;":                    '\U000000B5',
+	"mid;":                      '\U00002223',
+	"midast;":                   '\U0000002A',
+	"midcir;":                   '\U00002AF0',
+	"middot;":                   '\U000000B7',
+	"minus;":                    '\U00002212',
+	"minusb;":                   '\U0000229F',
+	"minusd;":                   '\U00002238',
+	"minusdu;":                  '\U00002A2A',
+	"mlcp;":                     '\U00002ADB',
+	"mldr;":                     '\U00002026',
+	"mnplus;":                   '\U00002213',
+	"models;":                   '\U000022A7',
+	"mopf;":                     '\U0001D55E',
+	"mp;":                       '\U00002213',
+	"mscr;":                     '\U0001D4C2',
+	"mstpos;":                   '\U0000223E',
+	"mu;":                       '\U000003BC',
+	"multimap;":                 '\U000022B8',
+	"mumap;":                    '\U000022B8',
+	"nLeftarrow;":               '\U000021CD',
+	"nLeftrightarrow;":          '\U000021CE',
+	"nRightarrow;":              '\U000021CF',
+	"nVDash;":                   '\U000022AF',
+	"nVdash;":                   '\U000022AE',
+	"nabla;":                    '\U00002207',
+	"nacute;":                   '\U00000144',
+	"nap;":                      '\U00002249',
+	"napos;":                    '\U00000149',
+	"napprox;":                  '\U00002249',
+	"natur;":                    '\U0000266E',
+	"natural;":                  '\U0000266E',
+	"naturals;":                 '\U00002115',
+	"nbsp;":                     '\U000000A0',
+	"ncap;":                     '\U00002A43',
+	"ncaron;":                   '\U00000148',
+	"ncedil;":                   '\U00000146',
+	"ncong;":                    '\U00002247',
+	"ncup;":                     '\U00002A42',
+	"ncy;":                      '\U0000043D',
+	"ndash;":                    '\U00002013',
+	"ne;":                       '\U00002260',
+	"neArr;":                    '\U000021D7',
+	"nearhk;":                   '\U00002924',
+	"nearr;":                    '\U00002197',
+	"nearrow;":                  '\U00002197',
+	"nequiv;":                   '\U00002262',
+	"nesear;":                   '\U00002928',
+	"nexist;":                   '\U00002204',
+	"nexists;":                  '\U00002204',
+	"nfr;":                      '\U0001D52B',
+	"nge;":                      '\U00002271',
+	"ngeq;":                     '\U00002271',
+	"ngsim;":                    '\U00002275',
+	"ngt;":                      '\U0000226F',
+	"ngtr;":                     '\U0000226F',
+	"nhArr;":                    '\U000021CE',
+	"nharr;":                    '\U000021AE',
+	"nhpar;":                    '\U00002AF2',
+	"ni;":                       '\U0000220B',
+	"nis;":                      '\U000022FC',
+	"nisd;":                     '\U000022FA',
+	"niv;":                      '\U0000220B',
+	"njcy;":                     '\U0000045A',
+	"nlArr;":                    '\U000021CD',
+	"nlarr;":                    '\U0000219A',
+	"nldr;":                     '\U00002025',
+	"nle;":                      '\U00002270',
+	"nleftarrow;":               '\U0000219A',
+	"nleftrightarrow;":          '\U000021AE',
+	"nleq;":                     '\U00002270',
+	"nless;":                    '\U0000226E',
+	"nlsim;":                    '\U00002274',
+	"nlt;":                      '\U0000226E',
+	"nltri;":                    '\U000022EA',
+	"nltrie;":                   '\U000022EC',
+	"nmid;":                     '\U00002224',
+	"nopf;":                     '\U0001D55F',
+	"not;":                      '\U000000AC',
+	"notin;":                    '\U00002209',
+	"notinva;":                  '\U00002209',
+	"notinvb;":                  '\U000022F7',
+	"notinvc;":                  '\U000022F6',
+	"notni;":                    '\U0000220C',
+	"notniva;":                  '\U0000220C',
+	"notnivb;":                  '\U000022FE',
+	"notnivc;":                  '\U000022FD',
+	"npar;":                     '\U00002226',
+	"nparallel;":                '\U00002226',
+	"npolint;":                  '\U00002A14',
+	"npr;":                      '\U00002280',
+	"nprcue;":                   '\U000022E0',
+	"nprec;":                    '\U00002280',
+	"nrArr;":                    '\U000021CF',
+	"nrarr;":                    '\U0000219B',
+	"nrightarrow;":              '\U0000219B',
+	"nrtri;":                    '\U000022EB',
+	"nrtrie;":                   '\U000022ED',
+	"nsc;":                      '\U00002281',
+	"nsccue;":                   '\U000022E1',
+	"nscr;":                     '\U0001D4C3',
+	"nshortmid;":                '\U00002224',
+	"nshortparallel;":           '\U00002226',
+	"nsim;":                     '\U00002241',
+	"nsime;":                    '\U00002244',
+	"nsimeq;":                   '\U00002244',
+	"nsmid;":                    '\U00002224',
+	"nspar;":                    '\U00002226',
+	"nsqsube;":                  '\U000022E2',
+	"nsqsupe;":                  '\U000022E3',
+	"nsub;":                     '\U00002284',
+	"nsube;":                    '\U00002288',
+	"nsubseteq;":                '\U00002288',
+	"nsucc;":                    '\U00002281',
+	"nsup;":                     '\U00002285',
+	"nsupe;":                    '\U00002289',
+	"nsupseteq;":                '\U00002289',
+	"ntgl;":                     '\U00002279',
+	"ntilde;":                   '\U000000F1',
+	"ntlg;":                     '\U00002278',
+	"ntriangleleft;":            '\U000022EA',
+	"ntrianglelefteq;":          '\U000022EC',
+	"ntriangleright;":           '\U000022EB',
+	"ntrianglerighteq;":         '\U000022ED',
+	"nu;":                       '\U000003BD',
+	"num;":                      '\U00000023',
+	"numero;":                   '\U00002116',
+	"numsp;":                    '\U00002007',
+	"nvDash;":                   '\U000022AD',
+	"nvHarr;":                   '\U00002904',
+	"nvdash;":                   '\U000022AC',
+	"nvinfin;":                  '\U000029DE',
+	"nvlArr;":                   '\U00002902',
+	"nvrArr;":                   '\U00002903',
+	"nwArr;":                    '\U000021D6',
+	"nwarhk;":                   '\U00002923',
+	"nwarr;":                    '\U00002196',
+	"nwarrow;":                  '\U00002196',
+	"nwnear;":                   '\U00002927',
+	"oS;":                       '\U000024C8',
+	"oacute;":                   '\U000000F3',
+	"oast;":                     '\U0000229B',
+	"ocir;":                     '\U0000229A',
+	"ocirc;":                    '\U000000F4',
+	"ocy;":                      '\U0000043E',
+	"odash;":                    '\U0000229D',
+	"odblac;":                   '\U00000151',
+	"odiv;":                     '\U00002A38',
+	"odot;":                     '\U00002299',
+	"odsold;":                   '\U000029BC',
+	"oelig;":                    '\U00000153',
+	"ofcir;":                    '\U000029BF',
+	"ofr;":                      '\U0001D52C',
+	"ogon;":                     '\U000002DB',
+	"ograve;":                   '\U000000F2',
+	"ogt;":                      '\U000029C1',
+	"ohbar;":                    '\U000029B5',
+	"ohm;":                      '\U000003A9',
+	"oint;":                     '\U0000222E',
+	"olarr;":                    '\U000021BA',
+	"olcir;":                    '\U000029BE',
+	"olcross;":                  '\U000029BB',
+	"oline;":                    '\U0000203E',
+	"olt;":                      '\U000029C0',
+	"omacr;":                    '\U0000014D',
+	"omega;":                    '\U000003C9',
+	"omicron;":                  '\U000003BF',
+	"omid;":                     '\U000029B6',
+	"ominus;":                   '\U00002296',
+	"oopf;":                     '\U0001D560',
+	"opar;":                     '\U000029B7',
+	"operp;":                    '\U000029B9',
+	"oplus;":                    '\U00002295',
+	"or;":                       '\U00002228',
+	"orarr;":                    '\U000021BB',
+	"ord;":                      '\U00002A5D',
+	"order;":                    '\U00002134',
+	"orderof;":                  '\U00002134',
+	"ordf;":                     '\U000000AA',
+	"ordm;":                     '\U000000BA',
+	"origof;":                   '\U000022B6',
+	"oror;":                     '\U00002A56',
+	"orslope;":                  '\U00002A57',
+	"orv;":                      '\U00002A5B',
+	"oscr;":                     '\U00002134',
+	"oslash;":                   '\U000000F8',
+	"osol;":                     '\U00002298',
+	"otilde;":                   '\U000000F5',
+	"otimes;":                   '\U00002297',
+	"otimesas;":                 '\U00002A36',
+	"ouml;":                     '\U000000F6',
+	"ovbar;":                    '\U0000233D',
+	"par;":                      '\U00002225',
+	"para;":                     '\U000000B6',
+	"parallel;":                 '\U00002225',
+	"parsim;":                   '\U00002AF3',
+	"parsl;":                    '\U00002AFD',
+	"part;":                     '\U00002202',
+	"pcy;":                      '\U0000043F',
+	"percnt;":                   '\U00000025',
+	"period;":                   '\U0000002E',
+	"permil;":                   '\U00002030',
+	"perp;":                     '\U000022A5',
+	"pertenk;":                  '\U00002031',
+	"pfr;":                      '\U0001D52D',
+	"phi;":                      '\U000003C6',
+	"phiv;":                     '\U000003D5',
+	"phmmat;":                   '\U00002133',
+	"phone;":                    '\U0000260E',
+	"pi;":                       '\U000003C0',
+	"pitchfork;":                '\U000022D4',
+	"piv;":                      '\U000003D6',
+	"planck;":                   '\U0000210F',
+	"planckh;":                  '\U0000210E',
+	"plankv;":                   '\U0000210F',
+	"plus;":                     '\U0000002B',
+	"plusacir;":                 '\U00002A23',
+	"plusb;":                    '\U0000229E',
+	"pluscir;":                  '\U00002A22',
+	"plusdo;":                   '\U00002214',
+	"plusdu;":                   '\U00002A25',
+	"pluse;":                    '\U00002A72',
+	"plusmn;":                   '\U000000B1',
+	"plussim;":                  '\U00002A26',
+	"plustwo;":                  '\U00002A27',
+	"pm;":                       '\U000000B1',
+	"pointint;":                 '\U00002A15',
+	"popf;":                     '\U0001D561',
+	"pound;":                    '\U000000A3',
+	"pr;":                       '\U0000227A',
+	"prE;":                      '\U00002AB3',
+	"prap;":                     '\U00002AB7',
+	"prcue;":                    '\U0000227C',
+	"pre;":                      '\U00002AAF',
+	"prec;":                     '\U0000227A',
+	"precapprox;":               '\U00002AB7',
+	"preccurlyeq;":              '\U0000227C',
+	"preceq;":                   '\U00002AAF',
+	"precnapprox;":              '\U00002AB9',
+	"precneqq;":                 '\U00002AB5',
+	"precnsim;":                 '\U000022E8',
+	"precsim;":                  '\U0000227E',
+	"prime;":                    '\U00002032',
+	"primes;":                   '\U00002119',
+	"prnE;":                     '\U00002AB5',
+	"prnap;":                    '\U00002AB9',
+	"prnsim;":                   '\U000022E8',
+	"prod;":                     '\U0000220F',
+	"profalar;":                 '\U0000232E',
+	"profline;":                 '\U00002312',
+	"profsurf;":                 '\U00002313',
+	"prop;":                     '\U0000221D',
+	"propto;":                   '\U0000221D',
+	"prsim;":                    '\U0000227E',
+	"prurel;":                   '\U000022B0',
+	"pscr;":                     '\U0001D4C5',
+	"psi;":                      '\U000003C8',
+	"puncsp;":                   '\U00002008',
+	"qfr;":                      '\U0001D52E',
+	"qint;":                     '\U00002A0C',
+	"qopf;":                     '\U0001D562',
+	"qprime;":                   '\U00002057',
+	"qscr;":                     '\U0001D4C6',
+	"quaternions;":              '\U0000210D',
+	"quatint;":                  '\U00002A16',
+	"quest;":                    '\U0000003F',
+	"questeq;":                  '\U0000225F',
+	"quot;":                     '\U00000022',
+	"rAarr;":                    '\U000021DB',
+	"rArr;":                     '\U000021D2',
+	"rAtail;":                   '\U0000291C',
+	"rBarr;":                    '\U0000290F',
+	"rHar;":                     '\U00002964',
+	"racute;":                   '\U00000155',
+	"radic;":                    '\U0000221A',
+	"raemptyv;":                 '\U000029B3',
+	"rang;":                     '\U000027E9',
+	"rangd;":                    '\U00002992',
+	"range;":                    '\U000029A5',
+	"rangle;":                   '\U000027E9',
+	"raquo;":                    '\U000000BB',
+	"rarr;":                     '\U00002192',
+	"rarrap;":                   '\U00002975',
+	"rarrb;":                    '\U000021E5',
+	"rarrbfs;":                  '\U00002920',
+	"rarrc;":                    '\U00002933',
+	"rarrfs;":                   '\U0000291E',
+	"rarrhk;":                   '\U000021AA',
+	"rarrlp;":                   '\U000021AC',
+	"rarrpl;":                   '\U00002945',
+	"rarrsim;":                  '\U00002974',
+	"rarrtl;":                   '\U000021A3',
+	"rarrw;":                    '\U0000219D',
+	"ratail;":                   '\U0000291A',
+	"ratio;":                    '\U00002236',
+	"rationals;":                '\U0000211A',
+	"rbarr;":                    '\U0000290D',
+	"rbbrk;":                    '\U00002773',
+	"rbrace;":                   '\U0000007D',
+	"rbrack;":                   '\U0000005D',
+	"rbrke;":                    '\U0000298C',
+	"rbrksld;":                  '\U0000298E',
+	"rbrkslu;":                  '\U00002990',
+	"rcaron;":                   '\U00000159',
+	"rcedil;":                   '\U00000157',
+	"rceil;":                    '\U00002309',
+	"rcub;":                     '\U0000007D',
+	"rcy;":                      '\U00000440',
+	"rdca;":                     '\U00002937',
+	"rdldhar;":                  '\U00002969',
+	"rdquo;":                    '\U0000201D',
+	"rdquor;":                   '\U0000201D',
+	"rdsh;":                     '\U000021B3',
+	"real;":                     '\U0000211C',
+	"realine;":                  '\U0000211B',
+	"realpart;":                 '\U0000211C',
+	"reals;":                    '\U0000211D',
+	"rect;":                     '\U000025AD',
+	"reg;":                      '\U000000AE',
+	"rfisht;":                   '\U0000297D',
+	"rfloor;":                   '\U0000230B',
+	"rfr;":                      '\U0001D52F',
+	"rhard;":                    '\U000021C1',
+	"rharu;":                    '\U000021C0',
+	"rharul;":                   '\U0000296C',
+	"rho;":                      '\U000003C1',
+	"rhov;":                     '\U000003F1',
+	"rightarrow;":               '\U00002192',
+	"rightarrowtail;":           '\U000021A3',
+	"rightharpoondown;":         '\U000021C1',
+	"rightharpoonup;":           '\U000021C0',
+	"rightleftarrows;":          '\U000021C4',
+	"rightleftharpoons;":        '\U000021CC',
+	"rightrightarrows;":         '\U000021C9',
+	"rightsquigarrow;":          '\U0000219D',
+	"rightthreetimes;":          '\U000022CC',
+	"ring;":                     '\U000002DA',
+	"risingdotseq;":             '\U00002253',
+	"rlarr;":                    '\U000021C4',
+	"rlhar;":                    '\U000021CC',
+	"rlm;":                      '\U0000200F',
+	"rmoust;":                   '\U000023B1',
+	"rmoustache;":               '\U000023B1',
+	"rnmid;":                    '\U00002AEE',
+	"roang;":                    '\U000027ED',
+	"roarr;":                    '\U000021FE',
+	"robrk;":                    '\U000027E7',
+	"ropar;":                    '\U00002986',
+	"ropf;":                     '\U0001D563',
+	"roplus;":                   '\U00002A2E',
+	"rotimes;":                  '\U00002A35',
+	"rpar;":                     '\U00000029',
+	"rpargt;":                   '\U00002994',
+	"rppolint;":                 '\U00002A12',
+	"rrarr;":                    '\U000021C9',
+	"rsaquo;":                   '\U0000203A',
+	"rscr;":                     '\U0001D4C7',
+	"rsh;":                      '\U000021B1',
+	"rsqb;":                     '\U0000005D',
+	"rsquo;":                    '\U00002019',
+	"rsquor;":                   '\U00002019',
+	"rthree;":                   '\U000022CC',
+	"rtimes;":                   '\U000022CA',
+	"rtri;":                     '\U000025B9',
+	"rtrie;":                    '\U000022B5',
+	"rtrif;":                    '\U000025B8',
+	"rtriltri;":                 '\U000029CE',
+	"ruluhar;":                  '\U00002968',
+	"rx;":                       '\U0000211E',
+	"sacute;":                   '\U0000015B',
+	"sbquo;":                    '\U0000201A',
+	"sc;":                       '\U0000227B',
+	"scE;":                      '\U00002AB4',
+	"scap;":                     '\U00002AB8',
+	"scaron;":                   '\U00000161',
+	"sccue;":                    '\U0000227D',
+	"sce;":                      '\U00002AB0',
+	"scedil;":                   '\U0000015F',
+	"scirc;":                    '\U0000015D',
+	"scnE;":                     '\U00002AB6',
+	"scnap;":                    '\U00002ABA',
+	"scnsim;":                   '\U000022E9',
+	"scpolint;":                 '\U00002A13',
+	"scsim;":                    '\U0000227F',
+	"scy;":                      '\U00000441',
+	"sdot;":                     '\U000022C5',
+	"sdotb;":                    '\U000022A1',
+	"sdote;":                    '\U00002A66',
+	"seArr;":                    '\U000021D8',
+	"searhk;":                   '\U00002925',
+	"searr;":                    '\U00002198',
+	"searrow;":                  '\U00002198',
+	"sect;":                     '\U000000A7',
+	"semi;":                     '\U0000003B',
+	"seswar;":                   '\U00002929',
+	"setminus;":                 '\U00002216',
+	"setmn;":                    '\U00002216',
+	"sext;":                     '\U00002736',
+	"sfr;":                      '\U0001D530',
+	"sfrown;":                   '\U00002322',
+	"sharp;":                    '\U0000266F',
+	"shchcy;":                   '\U00000449',
+	"shcy;":                     '\U00000448',
+	"shortmid;":                 '\U00002223',
+	"shortparallel;":            '\U00002225',
+	"shy;":                      '\U000000AD',
+	"sigma;":                    '\U000003C3',
+	"sigmaf;":                   '\U000003C2',
+	"sigmav;":                   '\U000003C2',
+	"sim;":                      '\U0000223C',
+	"simdot;":                   '\U00002A6A',
+	"sime;":                     '\U00002243',
+	"simeq;":                    '\U00002243',
+	"simg;":                     '\U00002A9E',
+	"simgE;":                    '\U00002AA0',
+	"siml;":                     '\U00002A9D',
+	"simlE;":                    '\U00002A9F',
+	"simne;":                    '\U00002246',
+	"simplus;":                  '\U00002A24',
+	"simrarr;":                  '\U00002972',
+	"slarr;":                    '\U00002190',
+	"smallsetminus;":            '\U00002216',
+	"smashp;":                   '\U00002A33',
+	"smeparsl;":                 '\U000029E4',
+	"smid;":                     '\U00002223',
+	"smile;":                    '\U00002323',
+	"smt;":                      '\U00002AAA',
+	"smte;":                     '\U00002AAC',
+	"softcy;":                   '\U0000044C',
+	"sol;":                      '\U0000002F',
+	"solb;":                     '\U000029C4',
+	"solbar;":                   '\U0000233F',
+	"sopf;":                     '\U0001D564',
+	"spades;":                   '\U00002660',
+	"spadesuit;":                '\U00002660',
+	"spar;":                     '\U00002225',
+	"sqcap;":                    '\U00002293',
+	"sqcup;":                    '\U00002294',
+	"sqsub;":                    '\U0000228F',
+	"sqsube;":                   '\U00002291',
+	"sqsubset;":                 '\U0000228F',
+	"sqsubseteq;":               '\U00002291',
+	"sqsup;":                    '\U00002290',
+	"sqsupe;":                   '\U00002292',
+	"sqsupset;":                 '\U00002290',
+	"sqsupseteq;":               '\U00002292',
+	"squ;":                      '\U000025A1',
+	"square;":                   '\U000025A1',
+	"squarf;":                   '\U000025AA',
+	"squf;":                     '\U000025AA',
+	"srarr;":                    '\U00002192',
+	"sscr;":                     '\U0001D4C8',
+	"ssetmn;":                   '\U00002216',
+	"ssmile;":                   '\U00002323',
+	"sstarf;":                   '\U000022C6',
+	"star;":                     '\U00002606',
+	"starf;":                    '\U00002605',
+	"straightepsilon;":          '\U000003F5',
+	"straightphi;":              '\U000003D5',
+	"strns;":                    '\U000000AF',
+	"sub;":                      '\U00002282',
+	"subE;":                     '\U00002AC5',
+	"subdot;":                   '\U00002ABD',
+	"sube;":                     '\U00002286',
+	"subedot;":                  '\U00002AC3',
+	"submult;":                  '\U00002AC1',
+	"subnE;":                    '\U00002ACB',
+	"subne;":                    '\U0000228A',
+	"subplus;":                  '\U00002ABF',
+	"subrarr;":                  '\U00002979',
+	"subset;":                   '\U00002282',
+	"subseteq;":                 '\U00002286',
+	"subseteqq;":                '\U00002AC5',
+	"subsetneq;":                '\U0000228A',
+	"subsetneqq;":               '\U00002ACB',
+	"subsim;":                   '\U00002AC7',
+	"subsub;":                   '\U00002AD5',
+	"subsup;":                   '\U00002AD3',
+	"succ;":                     '\U0000227B',
+	"succapprox;":               '\U00002AB8',
+	"succcurlyeq;":              '\U0000227D',
+	"succeq;":                   '\U00002AB0',
+	"succnapprox;":              '\U00002ABA',
+	"succneqq;":                 '\U00002AB6',
+	"succnsim;":                 '\U000022E9',
+	"succsim;":                  '\U0000227F',
+	"sum;":                      '\U00002211',
+	"sung;":                     '\U0000266A',
+	"sup;":                      '\U00002283',
+	"sup1;":                     '\U000000B9',
+	"sup2;":                     '\U000000B2',
+	"sup3;":                     '\U000000B3',
+	"supE;":                     '\U00002AC6',
+	"supdot;":                   '\U00002ABE',
+	"supdsub;":                  '\U00002AD8',
+	"supe;":                     '\U00002287',
+	"supedot;":                  '\U00002AC4',
+	"suphsol;":                  '\U000027C9',
+	"suphsub;":                  '\U00002AD7',
+	"suplarr;":                  '\U0000297B',
+	"supmult;":                  '\U00002AC2',
+	"supnE;":                    '\U00002ACC',
+	"supne;":                    '\U0000228B',
+	"supplus;":                  '\U00002AC0',
+	"supset;":                   '\U00002283',
+	"supseteq;":                 '\U00002287',
+	"supseteqq;":                '\U00002AC6',
+	"supsetneq;":                '\U0000228B',
+	"supsetneqq;":               '\U00002ACC',
+	"supsim;":                   '\U00002AC8',
+	"supsub;":                   '\U00002AD4',
+	"supsup;":                   '\U00002AD6',
+	"swArr;":                    '\U000021D9',
+	"swarhk;":                   '\U00002926',
+	"swarr;":                    '\U00002199',
+	"swarrow;":                  '\U00002199',
+	"swnwar;":                   '\U0000292A',
+	"szlig;":                    '\U000000DF',
+	"target;":                   '\U00002316',
+	"tau;":                      '\U000003C4',
+	"tbrk;":                     '\U000023B4',
+	"tcaron;":                   '\U00000165',
+	"tcedil;":                   '\U00000163',
+	"tcy;":                      '\U00000442',
+	"tdot;":                     '\U000020DB',
+	"telrec;":                   '\U00002315',
+	"tfr;":                      '\U0001D531',
+	"there4;":                   '\U00002234',
+	"therefore;":                '\U00002234',
+	"theta;":                    '\U000003B8',
+	"thetasym;":                 '\U000003D1',
+	"thetav;":                   '\U000003D1',
+	"thickapprox;":              '\U00002248',
+	"thicksim;":                 '\U0000223C',
+	"thinsp;":                   '\U00002009',
+	"thkap;":                    '\U00002248',
+	"thksim;":                   '\U0000223C',
+	"thorn;":                    '\U000000FE',
+	"tilde;":                    '\U000002DC',
+	"times;":                    '\U000000D7',
+	"timesb;":                   '\U000022A0',
+	"timesbar;":                 '\U00002A31',
+	"timesd;":                   '\U00002A30',
+	"tint;":                     '\U0000222D',
+	"toea;":                     '\U00002928',
+	"top;":                      '\U000022A4',
+	"topbot;":                   '\U00002336',
+	"topcir;":                   '\U00002AF1',
+	"topf;":                     '\U0001D565',
+	"topfork;":                  '\U00002ADA',
+	"tosa;":                     '\U00002929',
+	"tprime;":                   '\U00002034',
+	"trade;":                    '\U00002122',
+	"triangle;":                 '\U000025B5',
+	"triangledown;":             '\U000025BF',
+	"triangleleft;":             '\U000025C3',
+	"trianglelefteq;":           '\U000022B4',
+	"triangleq;":                '\U0000225C',
+	"triangleright;":            '\U000025B9',
+	"trianglerighteq;":          '\U000022B5',
+	"tridot;":                   '\U000025EC',
+	"trie;":                     '\U0000225C',
+	"triminus;":                 '\U00002A3A',
+	"triplus;":                  '\U00002A39',
+	"trisb;":                    '\U000029CD',
+	"tritime;":                  '\U00002A3B',
+	"trpezium;":                 '\U000023E2',
+	"tscr;":                     '\U0001D4C9',
+	"tscy;":                     '\U00000446',
+	"tshcy;":                    '\U0000045B',
+	"tstrok;":                   '\U00000167',
+	"twixt;":                    '\U0000226C',
+	"twoheadleftarrow;":         '\U0000219E',
+	"twoheadrightarrow;":        '\U000021A0',
+	"uArr;":                     '\U000021D1',
+	"uHar;":                     '\U00002963',
+	"uacute;":                   '\U000000FA',
+	"uarr;":                     '\U00002191',
+	"ubrcy;":                    '\U0000045E',
+	"ubreve;":                   '\U0000016D',
+	"ucirc;":                    '\U000000FB',
+	"ucy;":                      '\U00000443',
+	"udarr;":                    '\U000021C5',
+	"udblac;":                   '\U00000171',
+	"udhar;":                    '\U0000296E',
+	"ufisht;":                   '\U0000297E',
+	"ufr;":                      '\U0001D532',
+	"ugrave;":                   '\U000000F9',
+	"uharl;":                    '\U000021BF',
+	"uharr;":                    '\U000021BE',
+	"uhblk;":                    '\U00002580',
+	"ulcorn;":                   '\U0000231C',
+	"ulcorner;":                 '\U0000231C',
+	"ulcrop;":                   '\U0000230F',
+	"ultri;":                    '\U000025F8',
+	"umacr;":                    '\U0000016B',
+	"uml;":                      '\U000000A8',
+	"uogon;":                    '\U00000173',
+	"uopf;":                     '\U0001D566',
+	"uparrow;":                  '\U00002191',
+	"updownarrow;":              '\U00002195',
+	"upharpoonleft;":            '\U000021BF',
+	"upharpoonright;":           '\U000021BE',
+	"uplus;":                    '\U0000228E',
+	"upsi;":                     '\U000003C5',
+	"upsih;":                    '\U000003D2',
+	"upsilon;":                  '\U000003C5',
+	"upuparrows;":               '\U000021C8',
+	"urcorn;":                   '\U0000231D',
+	"urcorner;":                 '\U0000231D',
+	"urcrop;":                   '\U0000230E',
+	"uring;":                    '\U0000016F',
+	"urtri;":                    '\U000025F9',
+	"uscr;":                     '\U0001D4CA',
+	"utdot;":                    '\U000022F0',
+	"utilde;":                   '\U00000169',
+	"utri;":                     '\U000025B5',
+	"utrif;":                    '\U000025B4',
+	"uuarr;":                    '\U000021C8',
+	"uuml;":                     '\U000000FC',
+	"uwangle;":                  '\U000029A7',
+	"vArr;":                     '\U000021D5',
+	"vBar;":                     '\U00002AE8',
+	"vBarv;":                    '\U00002AE9',
+	"vDash;":                    '\U000022A8',
+	"vangrt;":                   '\U0000299C',
+	"varepsilon;":               '\U000003F5',
+	"varkappa;":                 '\U000003F0',
+	"varnothing;":               '\U00002205',
+	"varphi;":                   '\U000003D5',
+	"varpi;":                    '\U000003D6',
+	"varpropto;":                '\U0000221D',
+	"varr;":                     '\U00002195',
+	"varrho;":                   '\U000003F1',
+	"varsigma;":                 '\U000003C2',
+	"vartheta;":                 '\U000003D1',
+	"vartriangleleft;":          '\U000022B2',
+	"vartriangleright;":         '\U000022B3',
+	"vcy;":                      '\U00000432',
+	"vdash;":                    '\U000022A2',
+	"vee;":                      '\U00002228',
+	"veebar;":                   '\U000022BB',
+	"veeeq;":                    '\U0000225A',
+	"vellip;":                   '\U000022EE',
+	"verbar;":                   '\U0000007C',
+	"vert;":                     '\U0000007C',
+	"vfr;":                      '\U0001D533',
+	"vltri;":                    '\U000022B2',
+	"vopf;":                     '\U0001D567',
+	"vprop;":                    '\U0000221D',
+	"vrtri;":                    '\U000022B3',
+	"vscr;":                     '\U0001D4CB',
+	"vzigzag;":                  '\U0000299A',
+	"wcirc;":                    '\U00000175',
+	"wedbar;":                   '\U00002A5F',
+	"wedge;":                    '\U00002227',
+	"wedgeq;":                   '\U00002259',
+	"weierp;":                   '\U00002118',
+	"wfr;":                      '\U0001D534',
+	"wopf;":                     '\U0001D568',
+	"wp;":                       '\U00002118',
+	"wr;":                       '\U00002240',
+	"wreath;":                   '\U00002240',
+	"wscr;":                     '\U0001D4CC',
+	"xcap;":                     '\U000022C2',
+	"xcirc;":                    '\U000025EF',
+	"xcup;":                     '\U000022C3',
+	"xdtri;":                    '\U000025BD',
+	"xfr;":                      '\U0001D535',
+	"xhArr;":                    '\U000027FA',
+	"xharr;":                    '\U000027F7',
+	"xi;":                       '\U000003BE',
+	"xlArr;":                    '\U000027F8',
+	"xlarr;":                    '\U000027F5',
+	"xmap;":                     '\U000027FC',
+	"xnis;":                     '\U000022FB',
+	"xodot;":                    '\U00002A00',
+	"xopf;":                     '\U0001D569',
+	"xoplus;":                   '\U00002A01',
+	"xotime;":                   '\U00002A02',
+	"xrArr;":                    '\U000027F9',
+	"xrarr;":                    '\U000027F6',
+	"xscr;":                     '\U0001D4CD',
+	"xsqcup;":                   '\U00002A06',
+	"xuplus;":                   '\U00002A04',
+	"xutri;":                    '\U000025B3',
+	"xvee;":                     '\U000022C1',
+	"xwedge;":                   '\U000022C0',
+	"yacute;":                   '\U000000FD',
+	"yacy;":                     '\U0000044F',
+	"ycirc;":                    '\U00000177',
+	"ycy;":                      '\U0000044B',
+	"yen;":                      '\U000000A5',
+	"yfr;":                      '\U0001D536',
+	"yicy;":                     '\U00000457',
+	"yopf;":                     '\U0001D56A',
+	"yscr;":                     '\U0001D4CE',
+	"yucy;":                     '\U0000044E',
+	"yuml;":                     '\U000000FF',
+	"zacute;":                   '\U0000017A',
+	"zcaron;":                   '\U0000017E',
+	"zcy;":                      '\U00000437',
+	"zdot;":                     '\U0000017C',
+	"zeetrf;":                   '\U00002128',
+	"zeta;":                     '\U000003B6',
+	"zfr;":                      '\U0001D537',
+	"zhcy;":                     '\U00000436',
+	"zigrarr;":                  '\U000021DD',
+	"zopf;":                     '\U0001D56B',
+	"zscr;":                     '\U0001D4CF',
+	"zwj;":                      '\U0000200D',
+	"zwnj;":                     '\U0000200C',
+	"AElig":                     '\U000000C6',
+	"AMP":                       '\U00000026',
+	"Aacute":                    '\U000000C1',
+	"Acirc":                     '\U000000C2',
+	"Agrave":                    '\U000000C0',
+	"Aring":                     '\U000000C5',
+	"Atilde":                    '\U000000C3',
+	"Auml":                      '\U000000C4',
+	"COPY":                      '\U000000A9',
+	"Ccedil":                    '\U000000C7',
+	"ETH":                       '\U000000D0',
+	"Eacute":                    '\U000000C9',
+	"Ecirc":                     '\U000000CA',
+	"Egrave":                    '\U000000C8',
+	"Euml":                      '\U000000CB',
+	"GT":                        '\U0000003E',
+	"Iacute":                    '\U000000CD',
+	"Icirc":                     '\U000000CE',
+	"Igrave":                    '\U000000CC',
+	"Iuml":                      '\U000000CF',
+	"LT":                        '\U0000003C',
+	"Ntilde":                    '\U000000D1',
+	"Oacute":                    '\U000000D3',
+	"Ocirc":                     '\U000000D4',
+	"Ograve":                    '\U000000D2',
+	"Oslash":                    '\U000000D8',
+	"Otilde":                    '\U000000D5',
+	"Ouml":                      '\U000000D6',
+	"QUOT":                      '\U00000022',
+	"REG":                       '\U000000AE',
+	"THORN":                     '\U000000DE',
+	"Uacute":                    '\U000000DA',
+	"Ucirc":                     '\U000000DB',
+	"Ugrave":                    '\U000000D9',
+	"Uuml":                      '\U000000DC',
+	"Yacute":                    '\U000000DD',
+	"aacute":                    '\U000000E1',
+	"acirc":                     '\U000000E2',
+	"acute":                     '\U000000B4',
+	"aelig":                     '\U000000E6',
+	"agrave":                    '\U000000E0',
+	"amp":                       '\U00000026',
+	"aring":                     '\U000000E5',
+	"atilde":                    '\U000000E3',
+	"auml":                      '\U000000E4',
+	"brvbar":                    '\U000000A6',
+	"ccedil":                    '\U000000E7',
+	"cedil":                     '\U000000B8',
+	"cent":                      '\U000000A2',
+	"copy":                      '\U000000A9',
+	"curren":                    '\U000000A4',
+	"deg":                       '\U000000B0',
+	"divide":                    '\U000000F7',
+	"eacute":                    '\U000000E9',
+	"ecirc":                     '\U000000EA',
+	"egrave":                    '\U000000E8',
+	"eth":                       '\U000000F0',
+	"euml":                      '\U000000EB',
+	"frac12":                    '\U000000BD',
+	"frac14":                    '\U000000BC',
+	"frac34":                    '\U000000BE',
+	"gt":                        '\U0000003E',
+	"iacute":                    '\U000000ED',
+	"icirc":                     '\U000000EE',
+	"iexcl":                     '\U000000A1',
+	"igrave":                    '\U000000EC',
+	"iquest":                    '\U000000BF',
+	"iuml":                      '\U000000EF',
+	"laquo":                     '\U000000AB',
+	"lt":                        '\U0000003C',
+	"macr":                      '\U000000AF',
+	"micro":                     '\U000000B5',
+	"middot":                    '\U000000B7',
+	"nbsp":                      '\U000000A0',
+	"not":                       '\U000000AC',
+	"ntilde":                    '\U000000F1',
+	"oacute":                    '\U000000F3',
+	"ocirc":                     '\U000000F4',
+	"ograve":                    '\U000000F2',
+	"ordf":                      '\U000000AA',
+	"ordm":                      '\U000000BA',
+	"oslash":                    '\U000000F8',
+	"otilde":                    '\U000000F5',
+	"ouml":                      '\U000000F6',
+	"para":                      '\U000000B6',
+	"plusmn":                    '\U000000B1',
+	"pound":                     '\U000000A3',
+	"quot":                      '\U00000022',
+	"raquo":                     '\U000000BB',
+	"reg":                       '\U000000AE',
+	"sect":                      '\U000000A7',
+	"shy":                       '\U000000AD',
+	"sup1":                      '\U000000B9',
+	"sup2":                      '\U000000B2',
+	"sup3":                      '\U000000B3',
+	"szlig":                     '\U000000DF',
+	"thorn":                     '\U000000FE',
+	"times":                     '\U000000D7',
+	"uacute":                    '\U000000FA',
+	"ucirc":                     '\U000000FB',
+	"ugrave":                    '\U000000F9',
+	"uml":                       '\U000000A8',
+	"uuml":                      '\U000000FC',
+	"yacute":                    '\U000000FD',
+	"yen":                       '\U000000A5',
+	"yuml":                      '\U000000FF',
+}
+
+// HTML entities that are two unicode codepoints.
+var entity2 = map[string][2]rune{
+	// TODO(nigeltao): Handle replacements that are wider than their names.
+	// "nLt;":                     {'\u226A', '\u20D2'},
+	// "nGt;":                     {'\u226B', '\u20D2'},
+	"NotEqualTilde;":           {'\u2242', '\u0338'},
+	"NotGreaterFullEqual;":     {'\u2267', '\u0338'},
+	"NotGreaterGreater;":       {'\u226B', '\u0338'},
+	"NotGreaterSlantEqual;":    {'\u2A7E', '\u0338'},
+	"NotHumpDownHump;":         {'\u224E', '\u0338'},
+	"NotHumpEqual;":            {'\u224F', '\u0338'},
+	"NotLeftTriangleBar;":      {'\u29CF', '\u0338'},
+	"NotLessLess;":             {'\u226A', '\u0338'},
+	"NotLessSlantEqual;":       {'\u2A7D', '\u0338'},
+	"NotNestedGreaterGreater;": {'\u2AA2', '\u0338'},
+	"NotNestedLessLess;":       {'\u2AA1', '\u0338'},
+	"NotPrecedesEqual;":        {'\u2AAF', '\u0338'},
+	"NotRightTriangleBar;":     {'\u29D0', '\u0338'},
+	"NotSquareSubset;":         {'\u228F', '\u0338'},
+	"NotSquareSuperset;":       {'\u2290', '\u0338'},
+	"NotSubset;":               {'\u2282', '\u20D2'},
+	"NotSucceedsEqual;":        {'\u2AB0', '\u0338'},
+	"NotSucceedsTilde;":        {'\u227F', '\u0338'},
+	"NotSuperset;":             {'\u2283', '\u20D2'},
+	"ThickSpace;":              {'\u205F', '\u200A'},
+	"acE;":                     {'\u223E', '\u0333'},
+	"bne;":                     {'\u003D', '\u20E5'},
+	"bnequiv;":                 {'\u2261', '\u20E5'},
+	"caps;":                    {'\u2229', '\uFE00'},
+	"cups;":                    {'\u222A', '\uFE00'},
+	"fjlig;":                   {'\u0066', '\u006A'},
+	"gesl;":                    {'\u22DB', '\uFE00'},
+	"gvertneqq;":               {'\u2269', '\uFE00'},
+	"gvnE;":                    {'\u2269', '\uFE00'},
+	"lates;":                   {'\u2AAD', '\uFE00'},
+	"lesg;":                    {'\u22DA', '\uFE00'},
+	"lvertneqq;":               {'\u2268', '\uFE00'},
+	"lvnE;":                    {'\u2268', '\uFE00'},
+	"nGg;":                     {'\u22D9', '\u0338'},
+	"nGtv;":                    {'\u226B', '\u0338'},
+	"nLl;":                     {'\u22D8', '\u0338'},
+	"nLtv;":                    {'\u226A', '\u0338'},
+	"nang;":                    {'\u2220', '\u20D2'},
+	"napE;":                    {'\u2A70', '\u0338'},
+	"napid;":                   {'\u224B', '\u0338'},
+	"nbump;":                   {'\u224E', '\u0338'},
+	"nbumpe;":                  {'\u224F', '\u0338'},
+	"ncongdot;":                {'\u2A6D', '\u0338'},
+	"nedot;":                   {'\u2250', '\u0338'},
+	"nesim;":                   {'\u2242', '\u0338'},
+	"ngE;":                     {'\u2267', '\u0338'},
+	"ngeqq;":                   {'\u2267', '\u0338'},
+	"ngeqslant;":               {'\u2A7E', '\u0338'},
+	"nges;":                    {'\u2A7E', '\u0338'},
+	"nlE;":                     {'\u2266', '\u0338'},
+	"nleqq;":                   {'\u2266', '\u0338'},
+	"nleqslant;":               {'\u2A7D', '\u0338'},
+	"nles;":                    {'\u2A7D', '\u0338'},
+	"notinE;":                  {'\u22F9', '\u0338'},
+	"notindot;":                {'\u22F5', '\u0338'},
+	"nparsl;":                  {'\u2AFD', '\u20E5'},
+	"npart;":                   {'\u2202', '\u0338'},
+	"npre;":                    {'\u2AAF', '\u0338'},
+	"npreceq;":                 {'\u2AAF', '\u0338'},
+	"nrarrc;":                  {'\u2933', '\u0338'},
+	"nrarrw;":                  {'\u219D', '\u0338'},
+	"nsce;":                    {'\u2AB0', '\u0338'},
+	"nsubE;":                   {'\u2AC5', '\u0338'},
+	"nsubset;":                 {'\u2282', '\u20D2'},
+	"nsubseteqq;":              {'\u2AC5', '\u0338'},
+	"nsucceq;":                 {'\u2AB0', '\u0338'},
+	"nsupE;":                   {'\u2AC6', '\u0338'},
+	"nsupset;":                 {'\u2283', '\u20D2'},
+	"nsupseteqq;":              {'\u2AC6', '\u0338'},
+	"nvap;":                    {'\u224D', '\u20D2'},
+	"nvge;":                    {'\u2265', '\u20D2'},
+	"nvgt;":                    {'\u003E', '\u20D2'},
+	"nvle;":                    {'\u2264', '\u20D2'},
+	"nvlt;":                    {'\u003C', '\u20D2'},
+	"nvltrie;":                 {'\u22B4', '\u20D2'},
+	"nvrtrie;":                 {'\u22B5', '\u20D2'},
+	"nvsim;":                   {'\u223C', '\u20D2'},
+	"race;":                    {'\u223D', '\u0331'},
+	"smtes;":                   {'\u2AAC', '\uFE00'},
+	"sqcaps;":                  {'\u2293', '\uFE00'},
+	"sqcups;":                  {'\u2294', '\uFE00'},
+	"varsubsetneq;":            {'\u228A', '\uFE00'},
+	"varsubsetneqq;":           {'\u2ACB', '\uFE00'},
+	"varsupsetneq;":            {'\u228B', '\uFE00'},
+	"varsupsetneqq;":           {'\u2ACC', '\uFE00'},
+	"vnsub;":                   {'\u2282', '\u20D2'},
+	"vnsup;":                   {'\u2283', '\u20D2'},
+	"vsubnE;":                  {'\u2ACB', '\uFE00'},
+	"vsubne;":                  {'\u228A', '\uFE00'},
+	"vsupnE;":                  {'\u2ACC', '\uFE00'},
+	"vsupne;":                  {'\u228B', '\uFE00'},
+}
diff --git a/third_party/gofrontend/libgo/go/html/entity_test.go b/third_party/gofrontend/libgo/go/html/entity_test.go
new file mode 100644
index 0000000..b53f866
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/entity_test.go
@@ -0,0 +1,29 @@
+// Copyright 2010 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 html
+
+import (
+	"testing"
+	"unicode/utf8"
+)
+
+func TestEntityLength(t *testing.T) {
+	// We verify that the length of UTF-8 encoding of each value is <= 1 + len(key).
+	// The +1 comes from the leading "&". This property implies that the length of
+	// unescaped text is <= the length of escaped text.
+	for k, v := range entity {
+		if 1+len(k) < utf8.RuneLen(v) {
+			t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v))
+		}
+		if len(k) > longestEntityWithoutSemicolon && k[len(k)-1] != ';' {
+			t.Errorf("entity name %s is %d characters, but longestEntityWithoutSemicolon=%d", k, len(k), longestEntityWithoutSemicolon)
+		}
+	}
+	for k, v := range entity2 {
+		if 1+len(k) < utf8.RuneLen(v[0])+utf8.RuneLen(v[1]) {
+			t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v[0]) + string(v[1]))
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/html/escape.go b/third_party/gofrontend/libgo/go/html/escape.go
new file mode 100644
index 0000000..dd5dfa7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/escape.go
@@ -0,0 +1,250 @@
+// Copyright 2010 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 html provides functions for escaping and unescaping HTML text.
+package html
+
+import (
+	"bytes"
+	"strings"
+	"unicode/utf8"
+)
+
+type writer interface {
+	WriteString(string) (int, error)
+}
+
+// These replacements permit compatibility with old numeric entities that
+// assumed Windows-1252 encoding.
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
+var replacementTable = [...]rune{
+	'\u20AC', // First entry is what 0x80 should be replaced with.
+	'\u0081',
+	'\u201A',
+	'\u0192',
+	'\u201E',
+	'\u2026',
+	'\u2020',
+	'\u2021',
+	'\u02C6',
+	'\u2030',
+	'\u0160',
+	'\u2039',
+	'\u0152',
+	'\u008D',
+	'\u017D',
+	'\u008F',
+	'\u0090',
+	'\u2018',
+	'\u2019',
+	'\u201C',
+	'\u201D',
+	'\u2022',
+	'\u2013',
+	'\u2014',
+	'\u02DC',
+	'\u2122',
+	'\u0161',
+	'\u203A',
+	'\u0153',
+	'\u009D',
+	'\u017E',
+	'\u0178', // Last entry is 0x9F.
+	// 0x00->'\uFFFD' is handled programmatically.
+	// 0x0D->'\u000D' is a no-op.
+}
+
+// unescapeEntity reads an entity like "&lt;" from b[src:] and writes the
+// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
+// Precondition: b[src] == '&' && dst <= src.
+// attribute should be true if parsing an attribute value.
+func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
+	// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
+
+	// i starts at 1 because we already know that s[0] == '&'.
+	i, s := 1, b[src:]
+
+	if len(s) <= 1 {
+		b[dst] = b[src]
+		return dst + 1, src + 1
+	}
+
+	if s[i] == '#' {
+		if len(s) <= 3 { // We need to have at least "&#.".
+			b[dst] = b[src]
+			return dst + 1, src + 1
+		}
+		i++
+		c := s[i]
+		hex := false
+		if c == 'x' || c == 'X' {
+			hex = true
+			i++
+		}
+
+		x := '\x00'
+		for i < len(s) {
+			c = s[i]
+			i++
+			if hex {
+				if '0' <= c && c <= '9' {
+					x = 16*x + rune(c) - '0'
+					continue
+				} else if 'a' <= c && c <= 'f' {
+					x = 16*x + rune(c) - 'a' + 10
+					continue
+				} else if 'A' <= c && c <= 'F' {
+					x = 16*x + rune(c) - 'A' + 10
+					continue
+				}
+			} else if '0' <= c && c <= '9' {
+				x = 10*x + rune(c) - '0'
+				continue
+			}
+			if c != ';' {
+				i--
+			}
+			break
+		}
+
+		if i <= 3 { // No characters matched.
+			b[dst] = b[src]
+			return dst + 1, src + 1
+		}
+
+		if 0x80 <= x && x <= 0x9F {
+			// Replace characters from Windows-1252 with UTF-8 equivalents.
+			x = replacementTable[x-0x80]
+		} else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
+			// Replace invalid characters with the replacement character.
+			x = '\uFFFD'
+		}
+
+		return dst + utf8.EncodeRune(b[dst:], x), src + i
+	}
+
+	// Consume the maximum number of characters possible, with the
+	// consumed characters matching one of the named references.
+
+	for i < len(s) {
+		c := s[i]
+		i++
+		// Lower-cased characters are more common in entities, so we check for them first.
+		if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
+			continue
+		}
+		if c != ';' {
+			i--
+		}
+		break
+	}
+
+	entityName := string(s[1:i])
+	if entityName == "" {
+		// No-op.
+	} else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' {
+		// No-op.
+	} else if x := entity[entityName]; x != 0 {
+		return dst + utf8.EncodeRune(b[dst:], x), src + i
+	} else if x := entity2[entityName]; x[0] != 0 {
+		dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
+		return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
+	} else if !attribute {
+		maxLen := len(entityName) - 1
+		if maxLen > longestEntityWithoutSemicolon {
+			maxLen = longestEntityWithoutSemicolon
+		}
+		for j := maxLen; j > 1; j-- {
+			if x := entity[entityName[:j]]; x != 0 {
+				return dst + utf8.EncodeRune(b[dst:], x), src + j + 1
+			}
+		}
+	}
+
+	dst1, src1 = dst+i, src+i
+	copy(b[dst:dst1], b[src:src1])
+	return dst1, src1
+}
+
+// unescape unescapes b's entities in-place, so that "a&lt;b" becomes "a<b".
+func unescape(b []byte) []byte {
+	for i, c := range b {
+		if c == '&' {
+			dst, src := unescapeEntity(b, i, i, false)
+			for src < len(b) {
+				c := b[src]
+				if c == '&' {
+					dst, src = unescapeEntity(b, dst, src, false)
+				} else {
+					b[dst] = c
+					dst, src = dst+1, src+1
+				}
+			}
+			return b[0:dst]
+		}
+	}
+	return b
+}
+
+const escapedChars = `&'<>"`
+
+func escape(w writer, s string) error {
+	i := strings.IndexAny(s, escapedChars)
+	for i != -1 {
+		if _, err := w.WriteString(s[:i]); err != nil {
+			return err
+		}
+		var esc string
+		switch s[i] {
+		case '&':
+			esc = "&amp;"
+		case '\'':
+			// "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
+			esc = "&#39;"
+		case '<':
+			esc = "&lt;"
+		case '>':
+			esc = "&gt;"
+		case '"':
+			// "&#34;" is shorter than "&quot;".
+			esc = "&#34;"
+		default:
+			panic("unrecognized escape character")
+		}
+		s = s[i+1:]
+		if _, err := w.WriteString(esc); err != nil {
+			return err
+		}
+		i = strings.IndexAny(s, escapedChars)
+	}
+	_, err := w.WriteString(s)
+	return err
+}
+
+// EscapeString escapes special characters like "<" to become "&lt;". It
+// escapes only five such characters: <, >, &, ' and ".
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
+// always true.
+func EscapeString(s string) string {
+	if strings.IndexAny(s, escapedChars) == -1 {
+		return s
+	}
+	var buf bytes.Buffer
+	escape(&buf, s)
+	return buf.String()
+}
+
+// UnescapeString unescapes entities like "&lt;" to become "<". It unescapes a
+// larger range of entities than EscapeString escapes. For example, "&aacute;"
+// unescapes to "á", as does "&#225;" and "&xE1;".
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
+// always true.
+func UnescapeString(s string) string {
+	for _, c := range s {
+		if c == '&' {
+			return string(unescape([]byte(s)))
+		}
+	}
+	return s
+}
diff --git a/third_party/gofrontend/libgo/go/html/escape_test.go b/third_party/gofrontend/libgo/go/html/escape_test.go
new file mode 100644
index 0000000..2d7ad8a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/escape_test.go
@@ -0,0 +1,115 @@
+// Copyright 2013 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 html
+
+import "testing"
+
+type unescapeTest struct {
+	// A short description of the test case.
+	desc string
+	// The HTML text.
+	html string
+	// The unescaped text.
+	unescaped string
+}
+
+var unescapeTests = []unescapeTest{
+	// Handle no entities.
+	{
+		"copy",
+		"A\ttext\nstring",
+		"A\ttext\nstring",
+	},
+	// Handle simple named entities.
+	{
+		"simple",
+		"&amp; &gt; &lt;",
+		"& > <",
+	},
+	// Handle hitting the end of the string.
+	{
+		"stringEnd",
+		"&amp &amp",
+		"& &",
+	},
+	// Handle entities with two codepoints.
+	{
+		"multiCodepoint",
+		"text &gesl; blah",
+		"text \u22db\ufe00 blah",
+	},
+	// Handle decimal numeric entities.
+	{
+		"decimalEntity",
+		"Delta = &#916; ",
+		"Delta = Δ ",
+	},
+	// Handle hexadecimal numeric entities.
+	{
+		"hexadecimalEntity",
+		"Lambda = &#x3bb; = &#X3Bb ",
+		"Lambda = λ = λ ",
+	},
+	// Handle numeric early termination.
+	{
+		"numericEnds",
+		"&# &#x &#128;43 &copy = &#169f = &#xa9",
+		"&# &#x €43 © = ©f = ©",
+	},
+	// Handle numeric ISO-8859-1 entity replacements.
+	{
+		"numericReplacements",
+		"Footnote&#x87;",
+		"Footnote‡",
+	},
+	// Handle single ampersand.
+	{
+		"copySingleAmpersand",
+		"&",
+		"&",
+	},
+	// Handle ampersand followed by non-entity.
+	{
+		"copyAmpersandNonEntity",
+		"text &test",
+		"text &test",
+	},
+	// Handle "&#".
+	{
+		"copyAmpersandHash",
+		"text &#",
+		"text &#",
+	},
+}
+
+func TestUnescape(t *testing.T) {
+	for _, tt := range unescapeTests {
+		unescaped := UnescapeString(tt.html)
+		if unescaped != tt.unescaped {
+			t.Errorf("TestUnescape %s: want %q, got %q", tt.desc, tt.unescaped, unescaped)
+		}
+	}
+}
+
+func TestUnescapeEscape(t *testing.T) {
+	ss := []string{
+		``,
+		`abc def`,
+		`a & b`,
+		`a&amp;b`,
+		`a &amp b`,
+		`&quot;`,
+		`"`,
+		`"<&>"`,
+		`&quot;&lt;&amp;&gt;&quot;`,
+		`3&5==1 && 0<1, "0&lt;1", a+acute=&aacute;`,
+		`The special characters are: <, >, &, ' and "`,
+	}
+	for _, s := range ss {
+		if got := UnescapeString(EscapeString(s)); got != s {
+			t.Errorf("got %q want %q", got, s)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/attr.go b/third_party/gofrontend/libgo/go/html/template/attr.go
new file mode 100644
index 0000000..d65d340
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/attr.go
@@ -0,0 +1,175 @@
+// 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.
+
+package template
+
+import (
+	"strings"
+)
+
+// attrTypeMap[n] describes the value of the given attribute.
+// If an attribute affects (or can mask) the encoding or interpretation of
+// other content, or affects the contents, idempotency, or credentials of a
+// network message, then the value in this map is contentTypeUnsafe.
+// This map is derived from HTML5, specifically
+// http://www.w3.org/TR/html5/Overview.html#attributes-1
+// as well as "%URI"-typed attributes from
+// http://www.w3.org/TR/html4/index/attributes.html
+var attrTypeMap = map[string]contentType{
+	"accept":          contentTypePlain,
+	"accept-charset":  contentTypeUnsafe,
+	"action":          contentTypeURL,
+	"alt":             contentTypePlain,
+	"archive":         contentTypeURL,
+	"async":           contentTypeUnsafe,
+	"autocomplete":    contentTypePlain,
+	"autofocus":       contentTypePlain,
+	"autoplay":        contentTypePlain,
+	"background":      contentTypeURL,
+	"border":          contentTypePlain,
+	"checked":         contentTypePlain,
+	"cite":            contentTypeURL,
+	"challenge":       contentTypeUnsafe,
+	"charset":         contentTypeUnsafe,
+	"class":           contentTypePlain,
+	"classid":         contentTypeURL,
+	"codebase":        contentTypeURL,
+	"cols":            contentTypePlain,
+	"colspan":         contentTypePlain,
+	"content":         contentTypeUnsafe,
+	"contenteditable": contentTypePlain,
+	"contextmenu":     contentTypePlain,
+	"controls":        contentTypePlain,
+	"coords":          contentTypePlain,
+	"crossorigin":     contentTypeUnsafe,
+	"data":            contentTypeURL,
+	"datetime":        contentTypePlain,
+	"default":         contentTypePlain,
+	"defer":           contentTypeUnsafe,
+	"dir":             contentTypePlain,
+	"dirname":         contentTypePlain,
+	"disabled":        contentTypePlain,
+	"draggable":       contentTypePlain,
+	"dropzone":        contentTypePlain,
+	"enctype":         contentTypeUnsafe,
+	"for":             contentTypePlain,
+	"form":            contentTypeUnsafe,
+	"formaction":      contentTypeURL,
+	"formenctype":     contentTypeUnsafe,
+	"formmethod":      contentTypeUnsafe,
+	"formnovalidate":  contentTypeUnsafe,
+	"formtarget":      contentTypePlain,
+	"headers":         contentTypePlain,
+	"height":          contentTypePlain,
+	"hidden":          contentTypePlain,
+	"high":            contentTypePlain,
+	"href":            contentTypeURL,
+	"hreflang":        contentTypePlain,
+	"http-equiv":      contentTypeUnsafe,
+	"icon":            contentTypeURL,
+	"id":              contentTypePlain,
+	"ismap":           contentTypePlain,
+	"keytype":         contentTypeUnsafe,
+	"kind":            contentTypePlain,
+	"label":           contentTypePlain,
+	"lang":            contentTypePlain,
+	"language":        contentTypeUnsafe,
+	"list":            contentTypePlain,
+	"longdesc":        contentTypeURL,
+	"loop":            contentTypePlain,
+	"low":             contentTypePlain,
+	"manifest":        contentTypeURL,
+	"max":             contentTypePlain,
+	"maxlength":       contentTypePlain,
+	"media":           contentTypePlain,
+	"mediagroup":      contentTypePlain,
+	"method":          contentTypeUnsafe,
+	"min":             contentTypePlain,
+	"multiple":        contentTypePlain,
+	"name":            contentTypePlain,
+	"novalidate":      contentTypeUnsafe,
+	// Skip handler names from
+	// http://www.w3.org/TR/html5/webappapis.html#event-handlers-on-elements,-document-objects,-and-window-objects
+	// since we have special handling in attrType.
+	"open":        contentTypePlain,
+	"optimum":     contentTypePlain,
+	"pattern":     contentTypeUnsafe,
+	"placeholder": contentTypePlain,
+	"poster":      contentTypeURL,
+	"profile":     contentTypeURL,
+	"preload":     contentTypePlain,
+	"pubdate":     contentTypePlain,
+	"radiogroup":  contentTypePlain,
+	"readonly":    contentTypePlain,
+	"rel":         contentTypeUnsafe,
+	"required":    contentTypePlain,
+	"reversed":    contentTypePlain,
+	"rows":        contentTypePlain,
+	"rowspan":     contentTypePlain,
+	"sandbox":     contentTypeUnsafe,
+	"spellcheck":  contentTypePlain,
+	"scope":       contentTypePlain,
+	"scoped":      contentTypePlain,
+	"seamless":    contentTypePlain,
+	"selected":    contentTypePlain,
+	"shape":       contentTypePlain,
+	"size":        contentTypePlain,
+	"sizes":       contentTypePlain,
+	"span":        contentTypePlain,
+	"src":         contentTypeURL,
+	"srcdoc":      contentTypeHTML,
+	"srclang":     contentTypePlain,
+	"start":       contentTypePlain,
+	"step":        contentTypePlain,
+	"style":       contentTypeCSS,
+	"tabindex":    contentTypePlain,
+	"target":      contentTypePlain,
+	"title":       contentTypePlain,
+	"type":        contentTypeUnsafe,
+	"usemap":      contentTypeURL,
+	"value":       contentTypeUnsafe,
+	"width":       contentTypePlain,
+	"wrap":        contentTypePlain,
+	"xmlns":       contentTypeURL,
+}
+
+// attrType returns a conservative (upper-bound on authority) guess at the
+// type of the named attribute.
+func attrType(name string) contentType {
+	name = strings.ToLower(name)
+	if strings.HasPrefix(name, "data-") {
+		// Strip data- so that custom attribute heuristics below are
+		// widely applied.
+		// Treat data-action as URL below.
+		name = name[5:]
+	} else if colon := strings.IndexRune(name, ':'); colon != -1 {
+		if name[:colon] == "xmlns" {
+			return contentTypeURL
+		}
+		// Treat svg:href and xlink:href as href below.
+		name = name[colon+1:]
+	}
+	if t, ok := attrTypeMap[name]; ok {
+		return t
+	}
+	// Treat partial event handler names as script.
+	if strings.HasPrefix(name, "on") {
+		return contentTypeJS
+	}
+
+	// Heuristics to prevent "javascript:..." injection in custom
+	// data attributes and custom attributes like g:tweetUrl.
+	// http://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes
+	// "Custom data attributes are intended to store custom data
+	//  private to the page or application, for which there are no
+	//  more appropriate attributes or elements."
+	// Developers seem to store URL content in data URLs that start
+	// or end with "URI" or "URL".
+	if strings.Contains(name, "src") ||
+		strings.Contains(name, "uri") ||
+		strings.Contains(name, "url") {
+		return contentTypeURL
+	}
+	return contentTypePlain
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/clone_test.go b/third_party/gofrontend/libgo/go/html/template/clone_test.go
new file mode 100644
index 0000000..e11bff2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/clone_test.go
@@ -0,0 +1,188 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"errors"
+	"io/ioutil"
+	"testing"
+	"text/template/parse"
+)
+
+func TestAddParseTree(t *testing.T) {
+	root := Must(New("root").Parse(`{{define "a"}} {{.}} {{template "b"}} {{.}} "></a>{{end}}`))
+	tree, err := parse.Parse("t", `{{define "b"}}<a href="{{end}}`, "", "", nil, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	added := Must(root.AddParseTree("b", tree["b"]))
+	b := new(bytes.Buffer)
+	err = added.ExecuteTemplate(b, "a", "1>0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got, want := b.String(), ` 1&gt;0 <a href=" 1%3e0 "></a>`; got != want {
+		t.Errorf("got %q want %q", got, want)
+	}
+}
+
+func TestClone(t *testing.T) {
+	// The {{.}} will be executed with data "<i>*/" in different contexts.
+	// In the t0 template, it will be in a text context.
+	// In the t1 template, it will be in a URL context.
+	// In the t2 template, it will be in a JavaScript context.
+	// In the t3 template, it will be in a CSS context.
+	const tmpl = `{{define "a"}}{{template "lhs"}}{{.}}{{template "rhs"}}{{end}}`
+	b := new(bytes.Buffer)
+
+	// Create an incomplete template t0.
+	t0 := Must(New("t0").Parse(tmpl))
+
+	// Clone t0 as t1.
+	t1 := Must(t0.Clone())
+	Must(t1.Parse(`{{define "lhs"}} <a href=" {{end}}`))
+	Must(t1.Parse(`{{define "rhs"}} "></a> {{end}}`))
+
+	// Execute t1.
+	b.Reset()
+	if err := t1.ExecuteTemplate(b, "a", "<i>*/"); err != nil {
+		t.Fatal(err)
+	}
+	if got, want := b.String(), ` <a href=" %3ci%3e*/ "></a> `; got != want {
+		t.Errorf("t1: got %q want %q", got, want)
+	}
+
+	// Clone t0 as t2.
+	t2 := Must(t0.Clone())
+	Must(t2.Parse(`{{define "lhs"}} <p onclick="javascript: {{end}}`))
+	Must(t2.Parse(`{{define "rhs"}} "></p> {{end}}`))
+
+	// Execute t2.
+	b.Reset()
+	if err := t2.ExecuteTemplate(b, "a", "<i>*/"); err != nil {
+		t.Fatal(err)
+	}
+	if got, want := b.String(), ` <p onclick="javascript: &#34;\u003ci\u003e*/&#34; "></p> `; got != want {
+		t.Errorf("t2: got %q want %q", got, want)
+	}
+
+	// Clone t0 as t3, but do not execute t3 yet.
+	t3 := Must(t0.Clone())
+	Must(t3.Parse(`{{define "lhs"}} <style> {{end}}`))
+	Must(t3.Parse(`{{define "rhs"}} </style> {{end}}`))
+
+	// Complete t0.
+	Must(t0.Parse(`{{define "lhs"}} ( {{end}}`))
+	Must(t0.Parse(`{{define "rhs"}} ) {{end}}`))
+
+	// Clone t0 as t4. Redefining the "lhs" template should fail.
+	t4 := Must(t0.Clone())
+	if _, err := t4.Parse(`{{define "lhs"}} FAIL {{end}}`); err == nil {
+		t.Error(`redefine "lhs": got nil err want non-nil`)
+	}
+
+	// Execute t0.
+	b.Reset()
+	if err := t0.ExecuteTemplate(b, "a", "<i>*/"); err != nil {
+		t.Fatal(err)
+	}
+	if got, want := b.String(), ` ( &lt;i&gt;*/ ) `; got != want {
+		t.Errorf("t0: got %q want %q", got, want)
+	}
+
+	// Clone t0. This should fail, as t0 has already executed.
+	if _, err := t0.Clone(); err == nil {
+		t.Error(`t0.Clone(): got nil err want non-nil`)
+	}
+
+	// Similarly, cloning sub-templates should fail.
+	if _, err := t0.Lookup("a").Clone(); err == nil {
+		t.Error(`t0.Lookup("a").Clone(): got nil err want non-nil`)
+	}
+	if _, err := t0.Lookup("lhs").Clone(); err == nil {
+		t.Error(`t0.Lookup("lhs").Clone(): got nil err want non-nil`)
+	}
+
+	// Execute t3.
+	b.Reset()
+	if err := t3.ExecuteTemplate(b, "a", "<i>*/"); err != nil {
+		t.Fatal(err)
+	}
+	if got, want := b.String(), ` <style> ZgotmplZ </style> `; got != want {
+		t.Errorf("t3: got %q want %q", got, want)
+	}
+}
+
+func TestTemplates(t *testing.T) {
+	names := []string{"t0", "a", "lhs", "rhs"}
+	// Some template definitions borrowed from TestClone.
+	const tmpl = `
+		{{define "a"}}{{template "lhs"}}{{.}}{{template "rhs"}}{{end}}
+		{{define "lhs"}} <a href=" {{end}}
+		{{define "rhs"}} "></a> {{end}}`
+	t0 := Must(New("t0").Parse(tmpl))
+	templates := t0.Templates()
+	if len(templates) != len(names) {
+		t.Errorf("expected %d templates; got %d", len(names), len(templates))
+	}
+	for _, name := range names {
+		found := false
+		for _, tmpl := range templates {
+			if name == tmpl.text.Name() {
+				found = true
+				break
+			}
+		}
+		if !found {
+			t.Error("could not find template", name)
+		}
+	}
+}
+
+// This used to crash; http://golang.org/issue/3281
+func TestCloneCrash(t *testing.T) {
+	t1 := New("all")
+	Must(t1.New("t1").Parse(`{{define "foo"}}foo{{end}}`))
+	t1.Clone()
+}
+
+// Ensure that this guarantee from the docs is upheld:
+// "Further calls to Parse in the copy will add templates
+// to the copy but not to the original."
+func TestCloneThenParse(t *testing.T) {
+	t0 := Must(New("t0").Parse(`{{define "a"}}{{template "embedded"}}{{end}}`))
+	t1 := Must(t0.Clone())
+	Must(t1.Parse(`{{define "embedded"}}t1{{end}}`))
+	if len(t0.Templates())+1 != len(t1.Templates()) {
+		t.Error("adding a template to a clone added it to the original")
+	}
+	// double check that the embedded template isn't available in the original
+	err := t0.ExecuteTemplate(ioutil.Discard, "a", nil)
+	if err == nil {
+		t.Error("expected 'no such template' error")
+	}
+}
+
+// https://code.google.com/p/go/issues/detail?id=5980
+func TestFuncMapWorksAfterClone(t *testing.T) {
+	funcs := FuncMap{"customFunc": func() (string, error) {
+		return "", errors.New("issue5980")
+	}}
+
+	// get the expected error output (no clone)
+	uncloned := Must(New("").Funcs(funcs).Parse("{{customFunc}}"))
+	wantErr := uncloned.Execute(ioutil.Discard, nil)
+
+	// toClone must be the same as uncloned. It has to be recreated from scratch,
+	// since cloning cannot occur after execution.
+	toClone := Must(New("").Funcs(funcs).Parse("{{customFunc}}"))
+	cloned := Must(toClone.Clone())
+	gotErr := cloned.Execute(ioutil.Discard, nil)
+
+	if wantErr.Error() != gotErr.Error() {
+		t.Errorf("clone error message mismatch want %q got %q", wantErr, gotErr)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/content.go b/third_party/gofrontend/libgo/go/html/template/content.go
new file mode 100644
index 0000000..3715ed5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/content.go
@@ -0,0 +1,136 @@
+// 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.
+
+package template
+
+import (
+	"fmt"
+	"reflect"
+)
+
+// Strings of content from a trusted source.
+type (
+	// CSS encapsulates known safe content that matches any of:
+	//   1. The CSS3 stylesheet production, such as `p { color: purple }`.
+	//   2. The CSS3 rule production, such as `a[href=~"https:"].foo#bar`.
+	//   3. CSS3 declaration productions, such as `color: red; margin: 2px`.
+	//   4. The CSS3 value production, such as `rgba(0, 0, 255, 127)`.
+	// See http://www.w3.org/TR/css3-syntax/#parsing and
+	// https://web.archive.org/web/20090211114933/http://w3.org/TR/css3-syntax#style
+	CSS string
+
+	// HTML encapsulates a known safe HTML document fragment.
+	// It should not be used for HTML from a third-party, or HTML with
+	// unclosed tags or comments. The outputs of a sound HTML sanitizer
+	// and a template escaped by this package are fine for use with HTML.
+	HTML string
+
+	// HTMLAttr encapsulates an HTML attribute from a trusted source,
+	// for example, ` dir="ltr"`.
+	HTMLAttr string
+
+	// JS encapsulates a known safe EcmaScript5 Expression, for example,
+	// `(x + y * z())`.
+	// Template authors are responsible for ensuring that typed expressions
+	// do not break the intended precedence and that there is no
+	// statement/expression ambiguity as when passing an expression like
+	// "{ foo: bar() }\n['foo']()", which is both a valid Expression and a
+	// valid Program with a very different meaning.
+	JS string
+
+	// JSStr encapsulates a sequence of characters meant to be embedded
+	// between quotes in a JavaScript expression.
+	// The string must match a series of StringCharacters:
+	//   StringCharacter :: SourceCharacter but not `\` or LineTerminator
+	//                    | EscapeSequence
+	// Note that LineContinuations are not allowed.
+	// JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
+	JSStr string
+
+	// URL encapsulates a known safe URL or URL substring (see RFC 3986).
+	// A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()`
+	// from a trusted source should go in the page, but by default dynamic
+	// `javascript:` URLs are filtered out since they are a frequently
+	// exploited injection vector.
+	URL string
+)
+
+type contentType uint8
+
+const (
+	contentTypePlain contentType = iota
+	contentTypeCSS
+	contentTypeHTML
+	contentTypeHTMLAttr
+	contentTypeJS
+	contentTypeJSStr
+	contentTypeURL
+	// contentTypeUnsafe is used in attr.go for values that affect how
+	// embedded content and network messages are formed, vetted,
+	// or interpreted; or which credentials network messages carry.
+	contentTypeUnsafe
+)
+
+// indirect returns the value, after dereferencing as many times
+// as necessary to reach the base type (or nil).
+func indirect(a interface{}) interface{} {
+	if a == nil {
+		return nil
+	}
+	if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
+		// Avoid creating a reflect.Value if it's not a pointer.
+		return a
+	}
+	v := reflect.ValueOf(a)
+	for v.Kind() == reflect.Ptr && !v.IsNil() {
+		v = v.Elem()
+	}
+	return v.Interface()
+}
+
+var (
+	errorType       = reflect.TypeOf((*error)(nil)).Elem()
+	fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+)
+
+// indirectToStringerOrError returns the value, after dereferencing as many times
+// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
+// or error,
+func indirectToStringerOrError(a interface{}) interface{} {
+	if a == nil {
+		return nil
+	}
+	v := reflect.ValueOf(a)
+	for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
+		v = v.Elem()
+	}
+	return v.Interface()
+}
+
+// stringify converts its arguments to a string and the type of the content.
+// All pointers are dereferenced, as in the text/template package.
+func stringify(args ...interface{}) (string, contentType) {
+	if len(args) == 1 {
+		switch s := indirect(args[0]).(type) {
+		case string:
+			return s, contentTypePlain
+		case CSS:
+			return string(s), contentTypeCSS
+		case HTML:
+			return string(s), contentTypeHTML
+		case HTMLAttr:
+			return string(s), contentTypeHTMLAttr
+		case JS:
+			return string(s), contentTypeJS
+		case JSStr:
+			return string(s), contentTypeJSStr
+		case URL:
+			return string(s), contentTypeURL
+		}
+	}
+	for i, arg := range args {
+		args[i] = indirectToStringerOrError(arg)
+	}
+	return fmt.Sprint(args...), contentTypePlain
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/content_test.go b/third_party/gofrontend/libgo/go/html/template/content_test.go
new file mode 100644
index 0000000..5f3ffe2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/content_test.go
@@ -0,0 +1,280 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+func TestTypedContent(t *testing.T) {
+	data := []interface{}{
+		`<b> "foo%" O'Reilly &bar;`,
+		CSS(`a[href =~ "//example.com"]#foo`),
+		HTML(`Hello, <b>World</b> &amp;tc!`),
+		HTMLAttr(` dir="ltr"`),
+		JS(`c && alert("Hello, World!");`),
+		JSStr(`Hello, World & O'Reilly\x21`),
+		URL(`greeting=H%69&addressee=(World)`),
+	}
+
+	// For each content sensitive escaper, see how it does on
+	// each of the typed strings above.
+	tests := []struct {
+		// A template containing a single {{.}}.
+		input string
+		want  []string
+	}{
+		{
+			`<style>{{.}} { color: blue }</style>`,
+			[]string{
+				`ZgotmplZ`,
+				// Allowed but not escaped.
+				`a[href =~ "//example.com"]#foo`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+			},
+		},
+		{
+			`<div style="{{.}}">`,
+			[]string{
+				`ZgotmplZ`,
+				// Allowed and HTML escaped.
+				`a[href =~ &#34;//example.com&#34;]#foo`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+			},
+		},
+		{
+			`{{.}}`,
+			[]string{
+				`&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
+				`a[href =~ &#34;//example.com&#34;]#foo`,
+				// Not escaped.
+				`Hello, <b>World</b> &amp;tc!`,
+				` dir=&#34;ltr&#34;`,
+				`c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
+				`Hello, World &amp; O&#39;Reilly\x21`,
+				`greeting=H%69&amp;addressee=(World)`,
+			},
+		},
+		{
+			`<a{{.}}>`,
+			[]string{
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				// Allowed and HTML escaped.
+				` dir="ltr"`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+			},
+		},
+		{
+			`<a title={{.}}>`,
+			[]string{
+				`&lt;b&gt;&#32;&#34;foo%&#34;&#32;O&#39;Reilly&#32;&amp;bar;`,
+				`a[href&#32;&#61;~&#32;&#34;//example.com&#34;]#foo`,
+				// Tags stripped, spaces escaped, entity not re-escaped.
+				`Hello,&#32;World&#32;&amp;tc!`,
+				`&#32;dir&#61;&#34;ltr&#34;`,
+				`c&#32;&amp;&amp;&#32;alert(&#34;Hello,&#32;World!&#34;);`,
+				`Hello,&#32;World&#32;&amp;&#32;O&#39;Reilly\x21`,
+				`greeting&#61;H%69&amp;addressee&#61;(World)`,
+			},
+		},
+		{
+			`<a title='{{.}}'>`,
+			[]string{
+				`&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
+				`a[href =~ &#34;//example.com&#34;]#foo`,
+				// Tags stripped, entity not re-escaped.
+				`Hello, World &amp;tc!`,
+				` dir=&#34;ltr&#34;`,
+				`c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
+				`Hello, World &amp; O&#39;Reilly\x21`,
+				`greeting=H%69&amp;addressee=(World)`,
+			},
+		},
+		{
+			`<textarea>{{.}}</textarea>`,
+			[]string{
+				`&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
+				`a[href =~ &#34;//example.com&#34;]#foo`,
+				// Angle brackets escaped to prevent injection of close tags, entity not re-escaped.
+				`Hello, &lt;b&gt;World&lt;/b&gt; &amp;tc!`,
+				` dir=&#34;ltr&#34;`,
+				`c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
+				`Hello, World &amp; O&#39;Reilly\x21`,
+				`greeting=H%69&amp;addressee=(World)`,
+			},
+		},
+		{
+			`<script>alert({{.}})</script>`,
+			[]string{
+				`"\u003cb\u003e \"foo%\" O'Reilly \u0026bar;"`,
+				`"a[href =~ \"//example.com\"]#foo"`,
+				`"Hello, \u003cb\u003eWorld\u003c/b\u003e \u0026amp;tc!"`,
+				`" dir=\"ltr\""`,
+				// Not escaped.
+				`c && alert("Hello, World!");`,
+				// Escape sequence not over-escaped.
+				`"Hello, World & O'Reilly\x21"`,
+				`"greeting=H%69\u0026addressee=(World)"`,
+			},
+		},
+		{
+			`<button onclick="alert({{.}})">`,
+			[]string{
+				`&#34;\u003cb\u003e \&#34;foo%\&#34; O&#39;Reilly \u0026bar;&#34;`,
+				`&#34;a[href =~ \&#34;//example.com\&#34;]#foo&#34;`,
+				`&#34;Hello, \u003cb\u003eWorld\u003c/b\u003e \u0026amp;tc!&#34;`,
+				`&#34; dir=\&#34;ltr\&#34;&#34;`,
+				// Not JS escaped but HTML escaped.
+				`c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
+				// Escape sequence not over-escaped.
+				`&#34;Hello, World &amp; O&#39;Reilly\x21&#34;`,
+				`&#34;greeting=H%69\u0026addressee=(World)&#34;`,
+			},
+		},
+		{
+			`<script>alert("{{.}}")</script>`,
+			[]string{
+				`\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
+				`a[href =~ \x22\/\/example.com\x22]#foo`,
+				`Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
+				` dir=\x22ltr\x22`,
+				`c \x26\x26 alert(\x22Hello, World!\x22);`,
+				// Escape sequence not over-escaped.
+				`Hello, World \x26 O\x27Reilly\x21`,
+				`greeting=H%69\x26addressee=(World)`,
+			},
+		},
+		{
+			`<button onclick='alert("{{.}}")'>`,
+			[]string{
+				`\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
+				`a[href =~ \x22\/\/example.com\x22]#foo`,
+				`Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
+				` dir=\x22ltr\x22`,
+				`c \x26\x26 alert(\x22Hello, World!\x22);`,
+				// Escape sequence not over-escaped.
+				`Hello, World \x26 O\x27Reilly\x21`,
+				`greeting=H%69\x26addressee=(World)`,
+			},
+		},
+		{
+			`<a href="?q={{.}}">`,
+			[]string{
+				`%3cb%3e%20%22foo%25%22%20O%27Reilly%20%26bar%3b`,
+				`a%5bhref%20%3d~%20%22%2f%2fexample.com%22%5d%23foo`,
+				`Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
+				`%20dir%3d%22ltr%22`,
+				`c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
+				`Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
+				// Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is done.
+				`greeting=H%69&amp;addressee=%28World%29`,
+			},
+		},
+		{
+			`<style>body { background: url('?img={{.}}') }</style>`,
+			[]string{
+				`%3cb%3e%20%22foo%25%22%20O%27Reilly%20%26bar%3b`,
+				`a%5bhref%20%3d~%20%22%2f%2fexample.com%22%5d%23foo`,
+				`Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
+				`%20dir%3d%22ltr%22`,
+				`c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
+				`Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
+				// Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is not done.
+				`greeting=H%69&addressee=%28World%29`,
+			},
+		},
+	}
+
+	for _, test := range tests {
+		tmpl := Must(New("x").Parse(test.input))
+		pre := strings.Index(test.input, "{{.}}")
+		post := len(test.input) - (pre + 5)
+		var b bytes.Buffer
+		for i, x := range data {
+			b.Reset()
+			if err := tmpl.Execute(&b, x); err != nil {
+				t.Errorf("%q with %v: %s", test.input, x, err)
+				continue
+			}
+			if want, got := test.want[i], b.String()[pre:b.Len()-post]; want != got {
+				t.Errorf("%q with %v:\nwant\n\t%q,\ngot\n\t%q\n", test.input, x, want, got)
+				continue
+			}
+		}
+	}
+}
+
+// Test that we print using the String method. Was issue 3073.
+type stringer struct {
+	v int
+}
+
+func (s *stringer) String() string {
+	return fmt.Sprintf("string=%d", s.v)
+}
+
+type errorer struct {
+	v int
+}
+
+func (s *errorer) Error() string {
+	return fmt.Sprintf("error=%d", s.v)
+}
+
+func TestStringer(t *testing.T) {
+	s := &stringer{3}
+	b := new(bytes.Buffer)
+	tmpl := Must(New("x").Parse("{{.}}"))
+	if err := tmpl.Execute(b, s); err != nil {
+		t.Fatal(err)
+	}
+	var expect = "string=3"
+	if b.String() != expect {
+		t.Errorf("expected %q got %q", expect, b.String())
+	}
+	e := &errorer{7}
+	b.Reset()
+	if err := tmpl.Execute(b, e); err != nil {
+		t.Fatal(err)
+	}
+	expect = "error=7"
+	if b.String() != expect {
+		t.Errorf("expected %q got %q", expect, b.String())
+	}
+}
+
+// https://code.google.com/p/go/issues/detail?id=5982
+func TestEscapingNilNonemptyInterfaces(t *testing.T) {
+	tmpl := Must(New("x").Parse("{{.E}}"))
+
+	got := new(bytes.Buffer)
+	testData := struct{ E error }{} // any non-empty interface here will do; error is just ready at hand
+	tmpl.Execute(got, testData)
+
+	// Use this data instead of just hard-coding "&lt;nil&gt;" to avoid
+	// dependencies on the html escaper and the behavior of fmt w.r.t. nil.
+	want := new(bytes.Buffer)
+	data := struct{ E string }{E: fmt.Sprint(nil)}
+	tmpl.Execute(want, data)
+
+	if !bytes.Equal(want.Bytes(), got.Bytes()) {
+		t.Errorf("expected %q got %q", string(want.Bytes()), string(got.Bytes()))
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/context.go b/third_party/gofrontend/libgo/go/html/template/context.go
new file mode 100644
index 0000000..59e794d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/context.go
@@ -0,0 +1,339 @@
+// 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.
+
+package template
+
+import (
+	"fmt"
+)
+
+// context describes the state an HTML parser must be in when it reaches the
+// portion of HTML produced by evaluating a particular template node.
+//
+// The zero value of type context is the start context for a template that
+// produces an HTML fragment as defined at
+// http://www.w3.org/TR/html5/syntax.html#the-end
+// where the context element is null.
+type context struct {
+	state   state
+	delim   delim
+	urlPart urlPart
+	jsCtx   jsCtx
+	attr    attr
+	element element
+	err     *Error
+}
+
+func (c context) String() string {
+	return fmt.Sprintf("{%v %v %v %v %v %v %v}", c.state, c.delim, c.urlPart, c.jsCtx, c.attr, c.element, c.err)
+}
+
+// eq reports whether two contexts are equal.
+func (c context) eq(d context) bool {
+	return c.state == d.state &&
+		c.delim == d.delim &&
+		c.urlPart == d.urlPart &&
+		c.jsCtx == d.jsCtx &&
+		c.attr == d.attr &&
+		c.element == d.element &&
+		c.err == d.err
+}
+
+// mangle produces an identifier that includes a suffix that distinguishes it
+// from template names mangled with different contexts.
+func (c context) mangle(templateName string) string {
+	// The mangled name for the default context is the input templateName.
+	if c.state == stateText {
+		return templateName
+	}
+	s := templateName + "$htmltemplate_" + c.state.String()
+	if c.delim != 0 {
+		s += "_" + c.delim.String()
+	}
+	if c.urlPart != 0 {
+		s += "_" + c.urlPart.String()
+	}
+	if c.jsCtx != 0 {
+		s += "_" + c.jsCtx.String()
+	}
+	if c.attr != 0 {
+		s += "_" + c.attr.String()
+	}
+	if c.element != 0 {
+		s += "_" + c.element.String()
+	}
+	return s
+}
+
+// state describes a high-level HTML parser state.
+//
+// It bounds the top of the element stack, and by extension the HTML insertion
+// mode, but also contains state that does not correspond to anything in the
+// HTML5 parsing algorithm because a single token production in the HTML
+// grammar may contain embedded actions in a template. For instance, the quoted
+// HTML attribute produced by
+//     <div title="Hello {{.World}}">
+// is a single token in HTML's grammar but in a template spans several nodes.
+type state uint8
+
+const (
+	// stateText is parsed character data. An HTML parser is in
+	// this state when its parse position is outside an HTML tag,
+	// directive, comment, and special element body.
+	stateText state = iota
+	// stateTag occurs before an HTML attribute or the end of a tag.
+	stateTag
+	// stateAttrName occurs inside an attribute name.
+	// It occurs between the ^'s in ` ^name^ = value`.
+	stateAttrName
+	// stateAfterName occurs after an attr name has ended but before any
+	// equals sign. It occurs between the ^'s in ` name^ ^= value`.
+	stateAfterName
+	// stateBeforeValue occurs after the equals sign but before the value.
+	// It occurs between the ^'s in ` name =^ ^value`.
+	stateBeforeValue
+	// stateHTMLCmt occurs inside an <!-- HTML comment -->.
+	stateHTMLCmt
+	// stateRCDATA occurs inside an RCDATA element (<textarea> or <title>)
+	// as described at http://www.w3.org/TR/html5/syntax.html#elements-0
+	stateRCDATA
+	// stateAttr occurs inside an HTML attribute whose content is text.
+	stateAttr
+	// stateURL occurs inside an HTML attribute whose content is a URL.
+	stateURL
+	// stateJS occurs inside an event handler or script element.
+	stateJS
+	// stateJSDqStr occurs inside a JavaScript double quoted string.
+	stateJSDqStr
+	// stateJSSqStr occurs inside a JavaScript single quoted string.
+	stateJSSqStr
+	// stateJSRegexp occurs inside a JavaScript regexp literal.
+	stateJSRegexp
+	// stateJSBlockCmt occurs inside a JavaScript /* block comment */.
+	stateJSBlockCmt
+	// stateJSLineCmt occurs inside a JavaScript // line comment.
+	stateJSLineCmt
+	// stateCSS occurs inside a <style> element or style attribute.
+	stateCSS
+	// stateCSSDqStr occurs inside a CSS double quoted string.
+	stateCSSDqStr
+	// stateCSSSqStr occurs inside a CSS single quoted string.
+	stateCSSSqStr
+	// stateCSSDqURL occurs inside a CSS double quoted url("...").
+	stateCSSDqURL
+	// stateCSSSqURL occurs inside a CSS single quoted url('...').
+	stateCSSSqURL
+	// stateCSSURL occurs inside a CSS unquoted url(...).
+	stateCSSURL
+	// stateCSSBlockCmt occurs inside a CSS /* block comment */.
+	stateCSSBlockCmt
+	// stateCSSLineCmt occurs inside a CSS // line comment.
+	stateCSSLineCmt
+	// stateError is an infectious error state outside any valid
+	// HTML/CSS/JS construct.
+	stateError
+)
+
+var stateNames = [...]string{
+	stateText:        "stateText",
+	stateTag:         "stateTag",
+	stateAttrName:    "stateAttrName",
+	stateAfterName:   "stateAfterName",
+	stateBeforeValue: "stateBeforeValue",
+	stateHTMLCmt:     "stateHTMLCmt",
+	stateRCDATA:      "stateRCDATA",
+	stateAttr:        "stateAttr",
+	stateURL:         "stateURL",
+	stateJS:          "stateJS",
+	stateJSDqStr:     "stateJSDqStr",
+	stateJSSqStr:     "stateJSSqStr",
+	stateJSRegexp:    "stateJSRegexp",
+	stateJSBlockCmt:  "stateJSBlockCmt",
+	stateJSLineCmt:   "stateJSLineCmt",
+	stateCSS:         "stateCSS",
+	stateCSSDqStr:    "stateCSSDqStr",
+	stateCSSSqStr:    "stateCSSSqStr",
+	stateCSSDqURL:    "stateCSSDqURL",
+	stateCSSSqURL:    "stateCSSSqURL",
+	stateCSSURL:      "stateCSSURL",
+	stateCSSBlockCmt: "stateCSSBlockCmt",
+	stateCSSLineCmt:  "stateCSSLineCmt",
+	stateError:       "stateError",
+}
+
+func (s state) String() string {
+	if int(s) < len(stateNames) {
+		return stateNames[s]
+	}
+	return fmt.Sprintf("illegal state %d", int(s))
+}
+
+// isComment is true for any state that contains content meant for template
+// authors & maintainers, not for end-users or machines.
+func isComment(s state) bool {
+	switch s {
+	case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateCSSBlockCmt, stateCSSLineCmt:
+		return true
+	}
+	return false
+}
+
+// isInTag return whether s occurs solely inside an HTML tag.
+func isInTag(s state) bool {
+	switch s {
+	case stateTag, stateAttrName, stateAfterName, stateBeforeValue, stateAttr:
+		return true
+	}
+	return false
+}
+
+// delim is the delimiter that will end the current HTML attribute.
+type delim uint8
+
+const (
+	// delimNone occurs outside any attribute.
+	delimNone delim = iota
+	// delimDoubleQuote occurs when a double quote (") closes the attribute.
+	delimDoubleQuote
+	// delimSingleQuote occurs when a single quote (') closes the attribute.
+	delimSingleQuote
+	// delimSpaceOrTagEnd occurs when a space or right angle bracket (>)
+	// closes the attribute.
+	delimSpaceOrTagEnd
+)
+
+var delimNames = [...]string{
+	delimNone:          "delimNone",
+	delimDoubleQuote:   "delimDoubleQuote",
+	delimSingleQuote:   "delimSingleQuote",
+	delimSpaceOrTagEnd: "delimSpaceOrTagEnd",
+}
+
+func (d delim) String() string {
+	if int(d) < len(delimNames) {
+		return delimNames[d]
+	}
+	return fmt.Sprintf("illegal delim %d", int(d))
+}
+
+// urlPart identifies a part in an RFC 3986 hierarchical URL to allow different
+// encoding strategies.
+type urlPart uint8
+
+const (
+	// urlPartNone occurs when not in a URL, or possibly at the start:
+	// ^ in "^http://auth/path?k=v#frag".
+	urlPartNone urlPart = iota
+	// urlPartPreQuery occurs in the scheme, authority, or path; between the
+	// ^s in "h^ttp://auth/path^?k=v#frag".
+	urlPartPreQuery
+	// urlPartQueryOrFrag occurs in the query portion between the ^s in
+	// "http://auth/path?^k=v#frag^".
+	urlPartQueryOrFrag
+	// urlPartUnknown occurs due to joining of contexts both before and
+	// after the query separator.
+	urlPartUnknown
+)
+
+var urlPartNames = [...]string{
+	urlPartNone:        "urlPartNone",
+	urlPartPreQuery:    "urlPartPreQuery",
+	urlPartQueryOrFrag: "urlPartQueryOrFrag",
+	urlPartUnknown:     "urlPartUnknown",
+}
+
+func (u urlPart) String() string {
+	if int(u) < len(urlPartNames) {
+		return urlPartNames[u]
+	}
+	return fmt.Sprintf("illegal urlPart %d", int(u))
+}
+
+// jsCtx determines whether a '/' starts a regular expression literal or a
+// division operator.
+type jsCtx uint8
+
+const (
+	// jsCtxRegexp occurs where a '/' would start a regexp literal.
+	jsCtxRegexp jsCtx = iota
+	// jsCtxDivOp occurs where a '/' would start a division operator.
+	jsCtxDivOp
+	// jsCtxUnknown occurs where a '/' is ambiguous due to context joining.
+	jsCtxUnknown
+)
+
+func (c jsCtx) String() string {
+	switch c {
+	case jsCtxRegexp:
+		return "jsCtxRegexp"
+	case jsCtxDivOp:
+		return "jsCtxDivOp"
+	case jsCtxUnknown:
+		return "jsCtxUnknown"
+	}
+	return fmt.Sprintf("illegal jsCtx %d", int(c))
+}
+
+// element identifies the HTML element when inside a start tag or special body.
+// Certain HTML element (for example <script> and <style>) have bodies that are
+// treated differently from stateText so the element type is necessary to
+// transition into the correct context at the end of a tag and to identify the
+// end delimiter for the body.
+type element uint8
+
+const (
+	// elementNone occurs outside a special tag or special element body.
+	elementNone element = iota
+	// elementScript corresponds to the raw text <script> element.
+	elementScript
+	// elementStyle corresponds to the raw text <style> element.
+	elementStyle
+	// elementTextarea corresponds to the RCDATA <textarea> element.
+	elementTextarea
+	// elementTitle corresponds to the RCDATA <title> element.
+	elementTitle
+)
+
+var elementNames = [...]string{
+	elementNone:     "elementNone",
+	elementScript:   "elementScript",
+	elementStyle:    "elementStyle",
+	elementTextarea: "elementTextarea",
+	elementTitle:    "elementTitle",
+}
+
+func (e element) String() string {
+	if int(e) < len(elementNames) {
+		return elementNames[e]
+	}
+	return fmt.Sprintf("illegal element %d", int(e))
+}
+
+// attr identifies the most recent HTML attribute when inside a start tag.
+type attr uint8
+
+const (
+	// attrNone corresponds to a normal attribute or no attribute.
+	attrNone attr = iota
+	// attrScript corresponds to an event handler attribute.
+	attrScript
+	// attrStyle corresponds to the style attribute whose value is CSS.
+	attrStyle
+	// attrURL corresponds to an attribute whose value is a URL.
+	attrURL
+)
+
+var attrNames = [...]string{
+	attrNone:   "attrNone",
+	attrScript: "attrScript",
+	attrStyle:  "attrStyle",
+	attrURL:    "attrURL",
+}
+
+func (a attr) String() string {
+	if int(a) < len(attrNames) {
+		return attrNames[a]
+	}
+	return fmt.Sprintf("illegal attr %d", int(a))
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/css.go b/third_party/gofrontend/libgo/go/html/template/css.go
new file mode 100644
index 0000000..634f183
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/css.go
@@ -0,0 +1,268 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"fmt"
+	"unicode"
+	"unicode/utf8"
+)
+
+// endsWithCSSKeyword reports whether b ends with an ident that
+// case-insensitively matches the lower-case kw.
+func endsWithCSSKeyword(b []byte, kw string) bool {
+	i := len(b) - len(kw)
+	if i < 0 {
+		// Too short.
+		return false
+	}
+	if i != 0 {
+		r, _ := utf8.DecodeLastRune(b[:i])
+		if isCSSNmchar(r) {
+			// Too long.
+			return false
+		}
+	}
+	// Many CSS keywords, such as "!important" can have characters encoded,
+	// but the URI production does not allow that according to
+	// http://www.w3.org/TR/css3-syntax/#TOK-URI
+	// This does not attempt to recognize encoded keywords. For example,
+	// given "\75\72\6c" and "url" this return false.
+	return string(bytes.ToLower(b[i:])) == kw
+}
+
+// isCSSNmchar reports whether rune is allowed anywhere in a CSS identifier.
+func isCSSNmchar(r rune) bool {
+	// Based on the CSS3 nmchar production but ignores multi-rune escape
+	// sequences.
+	// http://www.w3.org/TR/css3-syntax/#SUBTOK-nmchar
+	return 'a' <= r && r <= 'z' ||
+		'A' <= r && r <= 'Z' ||
+		'0' <= r && r <= '9' ||
+		r == '-' ||
+		r == '_' ||
+		// Non-ASCII cases below.
+		0x80 <= r && r <= 0xd7ff ||
+		0xe000 <= r && r <= 0xfffd ||
+		0x10000 <= r && r <= 0x10ffff
+}
+
+// decodeCSS decodes CSS3 escapes given a sequence of stringchars.
+// If there is no change, it returns the input, otherwise it returns a slice
+// backed by a new array.
+// http://www.w3.org/TR/css3-syntax/#SUBTOK-stringchar defines stringchar.
+func decodeCSS(s []byte) []byte {
+	i := bytes.IndexByte(s, '\\')
+	if i == -1 {
+		return s
+	}
+	// The UTF-8 sequence for a codepoint is never longer than 1 + the
+	// number hex digits need to represent that codepoint, so len(s) is an
+	// upper bound on the output length.
+	b := make([]byte, 0, len(s))
+	for len(s) != 0 {
+		i := bytes.IndexByte(s, '\\')
+		if i == -1 {
+			i = len(s)
+		}
+		b, s = append(b, s[:i]...), s[i:]
+		if len(s) < 2 {
+			break
+		}
+		// http://www.w3.org/TR/css3-syntax/#SUBTOK-escape
+		// escape ::= unicode | '\' [#x20-#x7E#x80-#xD7FF#xE000-#xFFFD#x10000-#x10FFFF]
+		if isHex(s[1]) {
+			// http://www.w3.org/TR/css3-syntax/#SUBTOK-unicode
+			//   unicode ::= '\' [0-9a-fA-F]{1,6} wc?
+			j := 2
+			for j < len(s) && j < 7 && isHex(s[j]) {
+				j++
+			}
+			r := hexDecode(s[1:j])
+			if r > unicode.MaxRune {
+				r, j = r/16, j-1
+			}
+			n := utf8.EncodeRune(b[len(b):cap(b)], r)
+			// The optional space at the end allows a hex
+			// sequence to be followed by a literal hex.
+			// string(decodeCSS([]byte(`\A B`))) == "\nB"
+			b, s = b[:len(b)+n], skipCSSSpace(s[j:])
+		} else {
+			// `\\` decodes to `\` and `\"` to `"`.
+			_, n := utf8.DecodeRune(s[1:])
+			b, s = append(b, s[1:1+n]...), s[1+n:]
+		}
+	}
+	return b
+}
+
+// isHex reports whether the given character is a hex digit.
+func isHex(c byte) bool {
+	return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
+}
+
+// hexDecode decodes a short hex digit sequence: "10" -> 16.
+func hexDecode(s []byte) rune {
+	n := '\x00'
+	for _, c := range s {
+		n <<= 4
+		switch {
+		case '0' <= c && c <= '9':
+			n |= rune(c - '0')
+		case 'a' <= c && c <= 'f':
+			n |= rune(c-'a') + 10
+		case 'A' <= c && c <= 'F':
+			n |= rune(c-'A') + 10
+		default:
+			panic(fmt.Sprintf("Bad hex digit in %q", s))
+		}
+	}
+	return n
+}
+
+// skipCSSSpace returns a suffix of c, skipping over a single space.
+func skipCSSSpace(c []byte) []byte {
+	if len(c) == 0 {
+		return c
+	}
+	// wc ::= #x9 | #xA | #xC | #xD | #x20
+	switch c[0] {
+	case '\t', '\n', '\f', ' ':
+		return c[1:]
+	case '\r':
+		// This differs from CSS3's wc production because it contains a
+		// probable spec error whereby wc contains all the single byte
+		// sequences in nl (newline) but not CRLF.
+		if len(c) >= 2 && c[1] == '\n' {
+			return c[2:]
+		}
+		return c[1:]
+	}
+	return c
+}
+
+// isCSSSpace reports whether b is a CSS space char as defined in wc.
+func isCSSSpace(b byte) bool {
+	switch b {
+	case '\t', '\n', '\f', '\r', ' ':
+		return true
+	}
+	return false
+}
+
+// cssEscaper escapes HTML and CSS special characters using \<hex>+ escapes.
+func cssEscaper(args ...interface{}) string {
+	s, _ := stringify(args...)
+	var b bytes.Buffer
+	written := 0
+	for i, r := range s {
+		var repl string
+		switch r {
+		case 0:
+			repl = `\0`
+		case '\t':
+			repl = `\9`
+		case '\n':
+			repl = `\a`
+		case '\f':
+			repl = `\c`
+		case '\r':
+			repl = `\d`
+		// Encode HTML specials as hex so the output can be embedded
+		// in HTML attributes without further encoding.
+		case '"':
+			repl = `\22`
+		case '&':
+			repl = `\26`
+		case '\'':
+			repl = `\27`
+		case '(':
+			repl = `\28`
+		case ')':
+			repl = `\29`
+		case '+':
+			repl = `\2b`
+		case '/':
+			repl = `\2f`
+		case ':':
+			repl = `\3a`
+		case ';':
+			repl = `\3b`
+		case '<':
+			repl = `\3c`
+		case '>':
+			repl = `\3e`
+		case '\\':
+			repl = `\\`
+		case '{':
+			repl = `\7b`
+		case '}':
+			repl = `\7d`
+		default:
+			continue
+		}
+		b.WriteString(s[written:i])
+		b.WriteString(repl)
+		written = i + utf8.RuneLen(r)
+		if repl != `\\` && (written == len(s) || isHex(s[written]) || isCSSSpace(s[written])) {
+			b.WriteByte(' ')
+		}
+	}
+	if written == 0 {
+		return s
+	}
+	b.WriteString(s[written:])
+	return b.String()
+}
+
+var expressionBytes = []byte("expression")
+var mozBindingBytes = []byte("mozbinding")
+
+// cssValueFilter allows innocuous CSS values in the output including CSS
+// quantities (10px or 25%), ID or class literals (#foo, .bar), keyword values
+// (inherit, blue), and colors (#888).
+// It filters out unsafe values, such as those that affect token boundaries,
+// and anything that might execute scripts.
+func cssValueFilter(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeCSS {
+		return s
+	}
+	b, id := decodeCSS([]byte(s)), make([]byte, 0, 64)
+
+	// CSS3 error handling is specified as honoring string boundaries per
+	// http://www.w3.org/TR/css3-syntax/#error-handling :
+	//     Malformed declarations. User agents must handle unexpected
+	//     tokens encountered while parsing a declaration by reading until
+	//     the end of the declaration, while observing the rules for
+	//     matching pairs of (), [], {}, "", and '', and correctly handling
+	//     escapes. For example, a malformed declaration may be missing a
+	//     property, colon (:) or value.
+	// So we need to make sure that values do not have mismatched bracket
+	// or quote characters to prevent the browser from restarting parsing
+	// inside a string that might embed JavaScript source.
+	for i, c := range b {
+		switch c {
+		case 0, '"', '\'', '(', ')', '/', ';', '@', '[', '\\', ']', '`', '{', '}':
+			return filterFailsafe
+		case '-':
+			// Disallow <!-- or -->.
+			// -- should not appear in valid identifiers.
+			if i != 0 && b[i-1] == '-' {
+				return filterFailsafe
+			}
+		default:
+			if c < 0x80 && isCSSNmchar(rune(c)) {
+				id = append(id, c)
+			}
+		}
+	}
+	id = bytes.ToLower(id)
+	if bytes.Index(id, expressionBytes) != -1 || bytes.Index(id, mozBindingBytes) != -1 {
+		return filterFailsafe
+	}
+	return string(b)
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/css_test.go b/third_party/gofrontend/libgo/go/html/template/css_test.go
new file mode 100644
index 0000000..a735638
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/css_test.go
@@ -0,0 +1,281 @@
+// 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.
+
+package template
+
+import (
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func TestEndsWithCSSKeyword(t *testing.T) {
+	tests := []struct {
+		css, kw string
+		want    bool
+	}{
+		{"", "url", false},
+		{"url", "url", true},
+		{"URL", "url", true},
+		{"Url", "url", true},
+		{"url", "important", false},
+		{"important", "important", true},
+		{"image-url", "url", false},
+		{"imageurl", "url", false},
+		{"image url", "url", true},
+	}
+	for _, test := range tests {
+		got := endsWithCSSKeyword([]byte(test.css), test.kw)
+		if got != test.want {
+			t.Errorf("want %t but got %t for css=%v, kw=%v", test.want, got, test.css, test.kw)
+		}
+	}
+}
+
+func TestIsCSSNmchar(t *testing.T) {
+	tests := []struct {
+		rune rune
+		want bool
+	}{
+		{0, false},
+		{'0', true},
+		{'9', true},
+		{'A', true},
+		{'Z', true},
+		{'a', true},
+		{'z', true},
+		{'_', true},
+		{'-', true},
+		{':', false},
+		{';', false},
+		{' ', false},
+		{0x7f, false},
+		{0x80, true},
+		{0x1234, true},
+		{0xd800, false},
+		{0xdc00, false},
+		{0xfffe, false},
+		{0x10000, true},
+		{0x110000, false},
+	}
+	for _, test := range tests {
+		got := isCSSNmchar(test.rune)
+		if got != test.want {
+			t.Errorf("%q: want %t but got %t", string(test.rune), test.want, got)
+		}
+	}
+}
+
+func TestDecodeCSS(t *testing.T) {
+	tests := []struct {
+		css, want string
+	}{
+		{``, ``},
+		{`foo`, `foo`},
+		{`foo\`, `foo`},
+		{`foo\\`, `foo\`},
+		{`\`, ``},
+		{`\A`, "\n"},
+		{`\a`, "\n"},
+		{`\0a`, "\n"},
+		{`\00000a`, "\n"},
+		{`\000000a`, "\u0000a"},
+		{`\1234 5`, "\u1234" + "5"},
+		{`\1234\20 5`, "\u1234" + " 5"},
+		{`\1234\A 5`, "\u1234" + "\n5"},
+		{"\\1234\t5", "\u1234" + "5"},
+		{"\\1234\n5", "\u1234" + "5"},
+		{"\\1234\r\n5", "\u1234" + "5"},
+		{`\12345`, "\U00012345"},
+		{`\\`, `\`},
+		{`\\ `, `\ `},
+		{`\"`, `"`},
+		{`\'`, `'`},
+		{`\.`, `.`},
+		{`\. .`, `. .`},
+		{
+			`The \3c i\3equick\3c/i\3e,\d\A\3cspan style=\27 color:brown\27\3e brown\3c/span\3e  fox jumps\2028over the \3c canine class=\22lazy\22 \3e dog\3c/canine\3e`,
+			"The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>",
+		},
+	}
+	for _, test := range tests {
+		got1 := string(decodeCSS([]byte(test.css)))
+		if got1 != test.want {
+			t.Errorf("%q: want\n\t%q\nbut got\n\t%q", test.css, test.want, got1)
+		}
+		recoded := cssEscaper(got1)
+		if got2 := string(decodeCSS([]byte(recoded))); got2 != test.want {
+			t.Errorf("%q: escape & decode not dual for %q", test.css, recoded)
+		}
+	}
+}
+
+func TestHexDecode(t *testing.T) {
+	for i := 0; i < 0x200000; i += 101 /* coprime with 16 */ {
+		s := strconv.FormatInt(int64(i), 16)
+		if got := int(hexDecode([]byte(s))); got != i {
+			t.Errorf("%s: want %d but got %d", s, i, got)
+		}
+		s = strings.ToUpper(s)
+		if got := int(hexDecode([]byte(s))); got != i {
+			t.Errorf("%s: want %d but got %d", s, i, got)
+		}
+	}
+}
+
+func TestSkipCSSSpace(t *testing.T) {
+	tests := []struct {
+		css, want string
+	}{
+		{"", ""},
+		{"foo", "foo"},
+		{"\n", ""},
+		{"\r\n", ""},
+		{"\r", ""},
+		{"\t", ""},
+		{" ", ""},
+		{"\f", ""},
+		{" foo", "foo"},
+		{"  foo", " foo"},
+		{`\20`, `\20`},
+	}
+	for _, test := range tests {
+		got := string(skipCSSSpace([]byte(test.css)))
+		if got != test.want {
+			t.Errorf("%q: want %q but got %q", test.css, test.want, got)
+		}
+	}
+}
+
+func TestCSSEscaper(t *testing.T) {
+	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !"#$%&'()*+,-./` +
+		`0123456789:;<=>?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\]^_` +
+		"`abcdefghijklmno" +
+		"pqrstuvwxyz{|}~\x7f" +
+		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+	want := ("\\0\x01\x02\x03\x04\x05\x06\x07" +
+		"\x08\\9 \\a\x0b\\c \\d\x0E\x0F" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17" +
+		"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !\22#$%\26\27\28\29*\2b,-.\2f ` +
+		`0123456789\3a\3b\3c=\3e?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\\]^_` +
+		"`abcdefghijklmno" +
+		`pqrstuvwxyz\7b|\7d~` + "\u007f" +
+		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+	got := cssEscaper(input)
+	if got != want {
+		t.Errorf("encode: want\n\t%q\nbut got\n\t%q", want, got)
+	}
+
+	got = string(decodeCSS([]byte(got)))
+	if input != got {
+		t.Errorf("decode: want\n\t%q\nbut got\n\t%q", input, got)
+	}
+}
+
+func TestCSSValueFilter(t *testing.T) {
+	tests := []struct {
+		css, want string
+	}{
+		{"", ""},
+		{"foo", "foo"},
+		{"0", "0"},
+		{"0px", "0px"},
+		{"-5px", "-5px"},
+		{"1.25in", "1.25in"},
+		{"+.33em", "+.33em"},
+		{"100%", "100%"},
+		{"12.5%", "12.5%"},
+		{".foo", ".foo"},
+		{"#bar", "#bar"},
+		{"corner-radius", "corner-radius"},
+		{"-moz-corner-radius", "-moz-corner-radius"},
+		{"#000", "#000"},
+		{"#48f", "#48f"},
+		{"#123456", "#123456"},
+		{"U+00-FF, U+980-9FF", "U+00-FF, U+980-9FF"},
+		{"color: red", "color: red"},
+		{"<!--", "ZgotmplZ"},
+		{"-->", "ZgotmplZ"},
+		{"<![CDATA[", "ZgotmplZ"},
+		{"]]>", "ZgotmplZ"},
+		{"</style", "ZgotmplZ"},
+		{`"`, "ZgotmplZ"},
+		{`'`, "ZgotmplZ"},
+		{"`", "ZgotmplZ"},
+		{"\x00", "ZgotmplZ"},
+		{"/* foo */", "ZgotmplZ"},
+		{"//", "ZgotmplZ"},
+		{"[href=~", "ZgotmplZ"},
+		{"expression(alert(1337))", "ZgotmplZ"},
+		{"-expression(alert(1337))", "ZgotmplZ"},
+		{"expression", "ZgotmplZ"},
+		{"Expression", "ZgotmplZ"},
+		{"EXPRESSION", "ZgotmplZ"},
+		{"-moz-binding", "ZgotmplZ"},
+		{"-expr\x00ession(alert(1337))", "ZgotmplZ"},
+		{`-expr\0ession(alert(1337))`, "ZgotmplZ"},
+		{`-express\69on(alert(1337))`, "ZgotmplZ"},
+		{`-express\69 on(alert(1337))`, "ZgotmplZ"},
+		{`-exp\72 ession(alert(1337))`, "ZgotmplZ"},
+		{`-exp\52 ession(alert(1337))`, "ZgotmplZ"},
+		{`-exp\000052 ession(alert(1337))`, "ZgotmplZ"},
+		{`-expre\0000073sion`, "-expre\x073sion"},
+		{`@import url evil.css`, "ZgotmplZ"},
+	}
+	for _, test := range tests {
+		got := cssValueFilter(test.css)
+		if got != test.want {
+			t.Errorf("%q: want %q but got %q", test.css, test.want, got)
+		}
+	}
+}
+
+func BenchmarkCSSEscaper(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		cssEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
+
+func BenchmarkCSSEscaperNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		cssEscaper("The quick, brown fox jumps over the lazy dog.")
+	}
+}
+
+func BenchmarkDecodeCSS(b *testing.B) {
+	s := []byte(`The \3c i\3equick\3c/i\3e,\d\A\3cspan style=\27 color:brown\27\3e brown\3c/span\3e fox jumps\2028over the \3c canine class=\22lazy\22 \3edog\3c/canine\3e`)
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		decodeCSS(s)
+	}
+}
+
+func BenchmarkDecodeCSSNoSpecials(b *testing.B) {
+	s := []byte("The quick, brown fox jumps over the lazy dog.")
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		decodeCSS(s)
+	}
+}
+
+func BenchmarkCSSValueFilter(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		cssValueFilter(`  e\78preS\0Sio/**/n(alert(1337))`)
+	}
+}
+
+func BenchmarkCSSValueFilterOk(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		cssValueFilter(`Times New Roman`)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/doc.go b/third_party/gofrontend/libgo/go/html/template/doc.go
new file mode 100644
index 0000000..d422ada
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/doc.go
@@ -0,0 +1,191 @@
+// 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.
+
+/*
+Package template (html/template) implements data-driven templates for
+generating HTML output safe against code injection. It provides the
+same interface as package text/template and should be used instead of
+text/template whenever the output is HTML.
+
+The documentation here focuses on the security features of the package.
+For information about how to program the templates themselves, see the
+documentation for text/template.
+
+Introduction
+
+This package wraps package text/template so you can share its template API
+to parse and execute HTML templates safely.
+
+  tmpl, err := template.New("name").Parse(...)
+  // Error checking elided
+  err = tmpl.Execute(out, data)
+
+If successful, tmpl will now be injection-safe. Otherwise, err is an error
+defined in the docs for ErrorCode.
+
+HTML templates treat data values as plain text which should be encoded so they
+can be safely embedded in an HTML document. The escaping is contextual, so
+actions can appear within JavaScript, CSS, and URI contexts.
+
+The security model used by this package assumes that template authors are
+trusted, while Execute's data parameter is not. More details are
+provided below.
+
+Example
+
+  import "text/template"
+  ...
+  t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
+  err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
+
+produces
+
+  Hello, <script>alert('you have been pwned')</script>!
+
+but the contextual autoescaping in html/template
+
+  import "html/template"
+  ...
+  t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
+  err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
+
+produces safe, escaped HTML output
+
+  Hello, &lt;script&gt;alert(&#39;you have been pwned&#39;)&lt;/script&gt;!
+
+
+Contexts
+
+This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing
+functions to each simple action pipeline, so given the excerpt
+
+  <a href="/search?q={{.}}">{{.}}</a>
+
+At parse time each {{.}} is overwritten to add escaping functions as necessary.
+In this case it becomes
+
+  <a href="/search?q={{. | urlquery}}">{{. | html}}</a>
+
+
+Errors
+
+See the documentation of ErrorCode for details.
+
+
+A fuller picture
+
+The rest of this package comment may be skipped on first reading; it includes
+details necessary to understand escaping contexts and error messages. Most users
+will not need to understand these details.
+
+
+Contexts
+
+Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows
+how {{.}} appears when used in the context to the left.
+
+  Context                          {{.}} After
+  {{.}}                            O'Reilly: How are &lt;i&gt;you&lt;/i&gt;?
+  <a title='{{.}}'>                O&#39;Reilly: How are you?
+  <a href="/{{.}}">                O&#39;Reilly: How are %3ci%3eyou%3c/i%3e?
+  <a href="?q={{.}}">              O&#39;Reilly%3a%20How%20are%3ci%3e...%3f
+  <a onx='f("{{.}}")'>             O\x27Reilly: How are \x3ci\x3eyou...?
+  <a onx='f({{.}})'>               "O\x27Reilly: How are \x3ci\x3eyou...?"
+  <a onx='pattern = /{{.}}/;'>     O\x27Reilly: How are \x3ci\x3eyou...\x3f
+
+If used in an unsafe context, then the value might be filtered out:
+
+  Context                          {{.}} After
+  <a href="{{.}}">                 #ZgotmplZ
+
+since "O'Reilly:" is not an allowed protocol like "http:".
+
+
+If {{.}} is the innocuous word, `left`, then it can appear more widely,
+
+  Context                              {{.}} After
+  {{.}}                                left
+  <a title='{{.}}'>                    left
+  <a href='{{.}}'>                     left
+  <a href='/{{.}}'>                    left
+  <a href='?dir={{.}}'>                left
+  <a style="border-{{.}}: 4px">        left
+  <a style="align: {{.}}">             left
+  <a style="background: '{{.}}'>       left
+  <a style="background: url('{{.}}')>  left
+  <style>p.{{.}} {color:red}</style>   left
+
+Non-string values can be used in JavaScript contexts.
+If {{.}} is
+
+  struct{A,B string}{ "foo", "bar" }
+
+in the escaped template
+
+  <script>var pair = {{.}};</script>
+
+then the template output is
+
+  <script>var pair = {"A": "foo", "B": "bar"};</script>
+
+See package json to understand how non-string content is marshalled for
+embedding in JavaScript contexts.
+
+
+Typed Strings
+
+By default, this package assumes that all pipelines produce a plain text string.
+It adds escaping pipeline stages necessary to correctly and safely embed that
+plain text string in the appropriate context.
+
+When a data value is not plain text, you can make sure it is not over-escaped
+by marking it with its type.
+
+Types HTML, JS, URL, and others from content.go can carry safe content that is
+exempted from escaping.
+
+The template
+
+  Hello, {{.}}!
+
+can be invoked with
+
+  tmpl.Execute(out, HTML(`<b>World</b>`))
+
+to produce
+
+  Hello, <b>World</b>!
+
+instead of the
+
+  Hello, &lt;b&gt;World&lt;b&gt;!
+
+that would have been produced if {{.}} was a regular string.
+
+
+Security Model
+
+http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.
+
+This package assumes that template authors are trusted, that Execute's data
+parameter is not, and seeks to preserve the properties below in the face
+of untrusted data:
+
+Structure Preservation Property:
+"... when a template author writes an HTML tag in a safe templating language,
+the browser will interpret the corresponding portion of the output as a tag
+regardless of the values of untrusted data, and similarly for other structures
+such as attribute boundaries and JS and CSS string boundaries."
+
+Code Effect Property:
+"... only code specified by the template author should run as a result of
+injecting the template output into a page and all code specified by the
+template author should run as a result of the same."
+
+Least Surprise Property:
+"A developer (or code reviewer) familiar with HTML, CSS, and JavaScript, who
+knows that contextual autoescaping happens should be able to look at a {{.}}
+and correctly infer what sanitization happens."
+*/
+package template
diff --git a/third_party/gofrontend/libgo/go/html/template/error.go b/third_party/gofrontend/libgo/go/html/template/error.go
new file mode 100644
index 0000000..46e49cc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/error.go
@@ -0,0 +1,197 @@
+// 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.
+
+package template
+
+import (
+	"fmt"
+)
+
+// Error describes a problem encountered during template Escaping.
+type Error struct {
+	// ErrorCode describes the kind of error.
+	ErrorCode ErrorCode
+	// Name is the name of the template in which the error was encountered.
+	Name string
+	// Line is the line number of the error in the template source or 0.
+	Line int
+	// Description is a human-readable description of the problem.
+	Description string
+}
+
+// ErrorCode is a code for a kind of error.
+type ErrorCode int
+
+// We define codes for each error that manifests while escaping templates, but
+// escaped templates may also fail at runtime.
+//
+// Output: "ZgotmplZ"
+// Example:
+//   <img src="{{.X}}">
+//   where {{.X}} evaluates to `javascript:...`
+// Discussion:
+//   "ZgotmplZ" is a special value that indicates that unsafe content reached a
+//   CSS or URL context at runtime. The output of the example will be
+//     <img src="#ZgotmplZ">
+//   If the data comes from a trusted source, use content types to exempt it
+//   from filtering: URL(`javascript:...`).
+const (
+	// OK indicates the lack of an error.
+	OK ErrorCode = iota
+
+	// ErrAmbigContext: "... appears in an ambiguous URL context"
+	// Example:
+	//   <a href="
+	//      {{if .C}}
+	//        /path/
+	//      {{else}}
+	//        /search?q=
+	//      {{end}}
+	//      {{.X}}
+	//   ">
+	// Discussion:
+	//   {{.X}} is in an ambiguous URL context since, depending on {{.C}},
+	//  it may be either a URL suffix or a query parameter.
+	//   Moving {{.X}} into the condition removes the ambiguity:
+	//   <a href="{{if .C}}/path/{{.X}}{{else}}/search?q={{.X}}">
+	ErrAmbigContext
+
+	// ErrBadHTML: "expected space, attr name, or end of tag, but got ...",
+	//   "... in unquoted attr", "... in attribute name"
+	// Example:
+	//   <a href = /search?q=foo>
+	//   <href=foo>
+	//   <form na<e=...>
+	//   <option selected<
+	// Discussion:
+	//   This is often due to a typo in an HTML element, but some runes
+	//   are banned in tag names, attribute names, and unquoted attribute
+	//   values because they can tickle parser ambiguities.
+	//   Quoting all attributes is the best policy.
+	ErrBadHTML
+
+	// ErrBranchEnd: "{{if}} branches end in different contexts"
+	// Example:
+	//   {{if .C}}<a href="{{end}}{{.X}}
+	// Discussion:
+	//   Package html/template statically examines each path through an
+	//   {{if}}, {{range}}, or {{with}} to escape any following pipelines.
+	//   The example is ambiguous since {{.X}} might be an HTML text node,
+	//   or a URL prefix in an HTML attribute. The context of {{.X}} is
+	//   used to figure out how to escape it, but that context depends on
+	//   the run-time value of {{.C}} which is not statically known.
+	//
+	//   The problem is usually something like missing quotes or angle
+	//   brackets, or can be avoided by refactoring to put the two contexts
+	//   into different branches of an if, range or with. If the problem
+	//   is in a {{range}} over a collection that should never be empty,
+	//   adding a dummy {{else}} can help.
+	ErrBranchEnd
+
+	// ErrEndContext: "... ends in a non-text context: ..."
+	// Examples:
+	//   <div
+	//   <div title="no close quote>
+	//   <script>f()
+	// Discussion:
+	//   Executed templates should produce a DocumentFragment of HTML.
+	//   Templates that end without closing tags will trigger this error.
+	//   Templates that should not be used in an HTML context or that
+	//   produce incomplete Fragments should not be executed directly.
+	//
+	//   {{define "main"}} <script>{{template "helper"}}</script> {{end}}
+	//   {{define "helper"}} document.write(' <div title=" ') {{end}}
+	//
+	//   "helper" does not produce a valid document fragment, so should
+	//   not be Executed directly.
+	ErrEndContext
+
+	// ErrNoSuchTemplate: "no such template ..."
+	// Examples:
+	//   {{define "main"}}<div {{template "attrs"}}>{{end}}
+	//   {{define "attrs"}}href="{{.URL}}"{{end}}
+	// Discussion:
+	//   Package html/template looks through template calls to compute the
+	//   context.
+	//   Here the {{.URL}} in "attrs" must be treated as a URL when called
+	//   from "main", but you will get this error if "attrs" is not defined
+	//   when "main" is parsed.
+	ErrNoSuchTemplate
+
+	// ErrOutputContext: "cannot compute output context for template ..."
+	// Examples:
+	//   {{define "t"}}{{if .T}}{{template "t" .T}}{{end}}{{.H}}",{{end}}
+	// Discussion:
+	//   A recursive template does not end in the same context in which it
+	//   starts, and a reliable output context cannot be computed.
+	//   Look for typos in the named template.
+	//   If the template should not be called in the named start context,
+	//   look for calls to that template in unexpected contexts.
+	//   Maybe refactor recursive templates to not be recursive.
+	ErrOutputContext
+
+	// ErrPartialCharset: "unfinished JS regexp charset in ..."
+	// Example:
+	//     <script>var pattern = /foo[{{.Chars}}]/</script>
+	// Discussion:
+	//   Package html/template does not support interpolation into regular
+	//   expression literal character sets.
+	ErrPartialCharset
+
+	// ErrPartialEscape: "unfinished escape sequence in ..."
+	// Example:
+	//   <script>alert("\{{.X}}")</script>
+	// Discussion:
+	//   Package html/template does not support actions following a
+	//   backslash.
+	//   This is usually an error and there are better solutions; for
+	//   example
+	//     <script>alert("{{.X}}")</script>
+	//   should work, and if {{.X}} is a partial escape sequence such as
+	//   "xA0", mark the whole sequence as safe content: JSStr(`\xA0`)
+	ErrPartialEscape
+
+	// ErrRangeLoopReentry: "on range loop re-entry: ..."
+	// Example:
+	//   <script>var x = [{{range .}}'{{.}},{{end}}]</script>
+	// Discussion:
+	//   If an iteration through a range would cause it to end in a
+	//   different context than an earlier pass, there is no single context.
+	//   In the example, there is missing a quote, so it is not clear
+	//   whether {{.}} is meant to be inside a JS string or in a JS value
+	//   context.  The second iteration would produce something like
+	//
+	//     <script>var x = ['firstValue,'secondValue]</script>
+	ErrRangeLoopReentry
+
+	// ErrSlashAmbig: '/' could start a division or regexp.
+	// Example:
+	//   <script>
+	//     {{if .C}}var x = 1{{end}}
+	//     /-{{.N}}/i.test(x) ? doThis : doThat();
+	//   </script>
+	// Discussion:
+	//   The example above could produce `var x = 1/-2/i.test(s)...`
+	//   in which the first '/' is a mathematical division operator or it
+	//   could produce `/-2/i.test(s)` in which the first '/' starts a
+	//   regexp literal.
+	//   Look for missing semicolons inside branches, and maybe add
+	//   parentheses to make it clear which interpretation you intend.
+	ErrSlashAmbig
+)
+
+func (e *Error) Error() string {
+	if e.Line != 0 {
+		return fmt.Sprintf("html/template:%s:%d: %s", e.Name, e.Line, e.Description)
+	} else if e.Name != "" {
+		return fmt.Sprintf("html/template:%s: %s", e.Name, e.Description)
+	}
+	return "html/template: " + e.Description
+}
+
+// errorf creates an error given a format string f and args.
+// The template Name still needs to be supplied.
+func errorf(k ErrorCode, line int, f string, args ...interface{}) *Error {
+	return &Error{k, "", line, fmt.Sprintf(f, args...)}
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/escape.go b/third_party/gofrontend/libgo/go/html/template/escape.go
new file mode 100644
index 0000000..4e37982
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/escape.go
@@ -0,0 +1,815 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"fmt"
+	"html"
+	"io"
+	"text/template"
+	"text/template/parse"
+)
+
+// escapeTemplates rewrites the named templates, which must be
+// associated with t, to guarantee that the output of any of the named
+// templates is properly escaped.  Names should include the names of
+// all templates that might be Executed but need not include helper
+// templates.  If no error is returned, then the named templates have
+// been modified.  Otherwise the named templates have been rendered
+// unusable.
+func escapeTemplates(tmpl *Template, names ...string) error {
+	e := newEscaper(tmpl)
+	for _, name := range names {
+		c, _ := e.escapeTree(context{}, name, 0)
+		var err error
+		if c.err != nil {
+			err, c.err.Name = c.err, name
+		} else if c.state != stateText {
+			err = &Error{ErrEndContext, name, 0, fmt.Sprintf("ends in a non-text context: %v", c)}
+		}
+		if err != nil {
+			// Prevent execution of unsafe templates.
+			for _, name := range names {
+				if t := tmpl.set[name]; t != nil {
+					t.text.Tree = nil
+					t.Tree = nil
+				}
+			}
+			return err
+		}
+	}
+	e.commit()
+	for _, name := range names {
+		if t := tmpl.set[name]; t != nil {
+			t.escaped = true
+			t.Tree = t.text.Tree
+		}
+	}
+	return nil
+}
+
+// funcMap maps command names to functions that render their inputs safe.
+var funcMap = template.FuncMap{
+	"html_template_attrescaper":     attrEscaper,
+	"html_template_commentescaper":  commentEscaper,
+	"html_template_cssescaper":      cssEscaper,
+	"html_template_cssvaluefilter":  cssValueFilter,
+	"html_template_htmlnamefilter":  htmlNameFilter,
+	"html_template_htmlescaper":     htmlEscaper,
+	"html_template_jsregexpescaper": jsRegexpEscaper,
+	"html_template_jsstrescaper":    jsStrEscaper,
+	"html_template_jsvalescaper":    jsValEscaper,
+	"html_template_nospaceescaper":  htmlNospaceEscaper,
+	"html_template_rcdataescaper":   rcdataEscaper,
+	"html_template_urlescaper":      urlEscaper,
+	"html_template_urlfilter":       urlFilter,
+	"html_template_urlnormalizer":   urlNormalizer,
+}
+
+// equivEscapers matches contextual escapers to equivalent template builtins.
+var equivEscapers = map[string]string{
+	"html_template_attrescaper":    "html",
+	"html_template_htmlescaper":    "html",
+	"html_template_nospaceescaper": "html",
+	"html_template_rcdataescaper":  "html",
+	"html_template_urlescaper":     "urlquery",
+	"html_template_urlnormalizer":  "urlquery",
+}
+
+// escaper collects type inferences about templates and changes needed to make
+// templates injection safe.
+type escaper struct {
+	tmpl *Template
+	// output[templateName] is the output context for a templateName that
+	// has been mangled to include its input context.
+	output map[string]context
+	// derived[c.mangle(name)] maps to a template derived from the template
+	// named name templateName for the start context c.
+	derived map[string]*template.Template
+	// called[templateName] is a set of called mangled template names.
+	called map[string]bool
+	// xxxNodeEdits are the accumulated edits to apply during commit.
+	// Such edits are not applied immediately in case a template set
+	// executes a given template in different escaping contexts.
+	actionNodeEdits   map[*parse.ActionNode][]string
+	templateNodeEdits map[*parse.TemplateNode]string
+	textNodeEdits     map[*parse.TextNode][]byte
+}
+
+// newEscaper creates a blank escaper for the given set.
+func newEscaper(t *Template) *escaper {
+	return &escaper{
+		t,
+		map[string]context{},
+		map[string]*template.Template{},
+		map[string]bool{},
+		map[*parse.ActionNode][]string{},
+		map[*parse.TemplateNode]string{},
+		map[*parse.TextNode][]byte{},
+	}
+}
+
+// filterFailsafe is an innocuous word that is emitted in place of unsafe values
+// by sanitizer functions. It is not a keyword in any programming language,
+// contains no special characters, is not empty, and when it appears in output
+// it is distinct enough that a developer can find the source of the problem
+// via a search engine.
+const filterFailsafe = "ZgotmplZ"
+
+// escape escapes a template node.
+func (e *escaper) escape(c context, n parse.Node) context {
+	switch n := n.(type) {
+	case *parse.ActionNode:
+		return e.escapeAction(c, n)
+	case *parse.IfNode:
+		return e.escapeBranch(c, &n.BranchNode, "if")
+	case *parse.ListNode:
+		return e.escapeList(c, n)
+	case *parse.RangeNode:
+		return e.escapeBranch(c, &n.BranchNode, "range")
+	case *parse.TemplateNode:
+		return e.escapeTemplate(c, n)
+	case *parse.TextNode:
+		return e.escapeText(c, n)
+	case *parse.WithNode:
+		return e.escapeBranch(c, &n.BranchNode, "with")
+	}
+	panic("escaping " + n.String() + " is unimplemented")
+}
+
+// escapeAction escapes an action template node.
+func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {
+	if len(n.Pipe.Decl) != 0 {
+		// A local variable assignment, not an interpolation.
+		return c
+	}
+	c = nudge(c)
+	s := make([]string, 0, 3)
+	switch c.state {
+	case stateError:
+		return c
+	case stateURL, stateCSSDqStr, stateCSSSqStr, stateCSSDqURL, stateCSSSqURL, stateCSSURL:
+		switch c.urlPart {
+		case urlPartNone:
+			s = append(s, "html_template_urlfilter")
+			fallthrough
+		case urlPartPreQuery:
+			switch c.state {
+			case stateCSSDqStr, stateCSSSqStr:
+				s = append(s, "html_template_cssescaper")
+			default:
+				s = append(s, "html_template_urlnormalizer")
+			}
+		case urlPartQueryOrFrag:
+			s = append(s, "html_template_urlescaper")
+		case urlPartUnknown:
+			return context{
+				state: stateError,
+				err:   errorf(ErrAmbigContext, n.Line, "%s appears in an ambiguous URL context", n),
+			}
+		default:
+			panic(c.urlPart.String())
+		}
+	case stateJS:
+		s = append(s, "html_template_jsvalescaper")
+		// A slash after a value starts a div operator.
+		c.jsCtx = jsCtxDivOp
+	case stateJSDqStr, stateJSSqStr:
+		s = append(s, "html_template_jsstrescaper")
+	case stateJSRegexp:
+		s = append(s, "html_template_jsregexpescaper")
+	case stateCSS:
+		s = append(s, "html_template_cssvaluefilter")
+	case stateText:
+		s = append(s, "html_template_htmlescaper")
+	case stateRCDATA:
+		s = append(s, "html_template_rcdataescaper")
+	case stateAttr:
+		// Handled below in delim check.
+	case stateAttrName, stateTag:
+		c.state = stateAttrName
+		s = append(s, "html_template_htmlnamefilter")
+	default:
+		if isComment(c.state) {
+			s = append(s, "html_template_commentescaper")
+		} else {
+			panic("unexpected state " + c.state.String())
+		}
+	}
+	switch c.delim {
+	case delimNone:
+		// No extra-escaping needed for raw text content.
+	case delimSpaceOrTagEnd:
+		s = append(s, "html_template_nospaceescaper")
+	default:
+		s = append(s, "html_template_attrescaper")
+	}
+	e.editActionNode(n, s)
+	return c
+}
+
+// allIdents returns the names of the identifiers under the Ident field of the node,
+// which might be a singleton (Identifier) or a slice (Field).
+func allIdents(node parse.Node) []string {
+	switch node := node.(type) {
+	case *parse.IdentifierNode:
+		return []string{node.Ident}
+	case *parse.FieldNode:
+		return node.Ident
+	}
+	panic("unidentified node type in allIdents")
+}
+
+// ensurePipelineContains ensures that the pipeline has commands with
+// the identifiers in s in order.
+// If the pipeline already has some of the sanitizers, do not interfere.
+// For example, if p is (.X | html) and s is ["escapeJSVal", "html"] then it
+// has one matching, "html", and one to insert, "escapeJSVal", to produce
+// (.X | escapeJSVal | html).
+func ensurePipelineContains(p *parse.PipeNode, s []string) {
+	if len(s) == 0 {
+		return
+	}
+	n := len(p.Cmds)
+	// Find the identifiers at the end of the command chain.
+	idents := p.Cmds
+	for i := n - 1; i >= 0; i-- {
+		if cmd := p.Cmds[i]; len(cmd.Args) != 0 {
+			if _, ok := cmd.Args[0].(*parse.IdentifierNode); ok {
+				continue
+			}
+		}
+		idents = p.Cmds[i+1:]
+	}
+	dups := 0
+	for _, idNode := range idents {
+		for _, ident := range allIdents(idNode.Args[0]) {
+			if escFnsEq(s[dups], ident) {
+				dups++
+				if dups == len(s) {
+					return
+				}
+			}
+		}
+	}
+	newCmds := make([]*parse.CommandNode, n-len(idents), n+len(s)-dups)
+	copy(newCmds, p.Cmds)
+	// Merge existing identifier commands with the sanitizers needed.
+	for _, idNode := range idents {
+		pos := idNode.Args[0].Position()
+		for _, ident := range allIdents(idNode.Args[0]) {
+			i := indexOfStr(ident, s, escFnsEq)
+			if i != -1 {
+				for _, name := range s[:i] {
+					newCmds = appendCmd(newCmds, newIdentCmd(name, pos))
+				}
+				s = s[i+1:]
+			}
+		}
+		newCmds = appendCmd(newCmds, idNode)
+	}
+	// Create any remaining sanitizers.
+	for _, name := range s {
+		newCmds = appendCmd(newCmds, newIdentCmd(name, p.Position()))
+	}
+	p.Cmds = newCmds
+}
+
+// redundantFuncs[a][b] implies that funcMap[b](funcMap[a](x)) == funcMap[a](x)
+// for all x.
+var redundantFuncs = map[string]map[string]bool{
+	"html_template_commentescaper": {
+		"html_template_attrescaper":    true,
+		"html_template_nospaceescaper": true,
+		"html_template_htmlescaper":    true,
+	},
+	"html_template_cssescaper": {
+		"html_template_attrescaper": true,
+	},
+	"html_template_jsregexpescaper": {
+		"html_template_attrescaper": true,
+	},
+	"html_template_jsstrescaper": {
+		"html_template_attrescaper": true,
+	},
+	"html_template_urlescaper": {
+		"html_template_urlnormalizer": true,
+	},
+}
+
+// appendCmd appends the given command to the end of the command pipeline
+// unless it is redundant with the last command.
+func appendCmd(cmds []*parse.CommandNode, cmd *parse.CommandNode) []*parse.CommandNode {
+	if n := len(cmds); n != 0 {
+		last, ok := cmds[n-1].Args[0].(*parse.IdentifierNode)
+		next, _ := cmd.Args[0].(*parse.IdentifierNode)
+		if ok && redundantFuncs[last.Ident][next.Ident] {
+			return cmds
+		}
+	}
+	return append(cmds, cmd)
+}
+
+// indexOfStr is the first i such that eq(s, strs[i]) or -1 if s was not found.
+func indexOfStr(s string, strs []string, eq func(a, b string) bool) int {
+	for i, t := range strs {
+		if eq(s, t) {
+			return i
+		}
+	}
+	return -1
+}
+
+// escFnsEq reports whether the two escaping functions are equivalent.
+func escFnsEq(a, b string) bool {
+	if e := equivEscapers[a]; e != "" {
+		a = e
+	}
+	if e := equivEscapers[b]; e != "" {
+		b = e
+	}
+	return a == b
+}
+
+// newIdentCmd produces a command containing a single identifier node.
+func newIdentCmd(identifier string, pos parse.Pos) *parse.CommandNode {
+	return &parse.CommandNode{
+		NodeType: parse.NodeCommand,
+		Args:     []parse.Node{parse.NewIdentifier(identifier).SetPos(pos)},
+	}
+}
+
+// nudge returns the context that would result from following empty string
+// transitions from the input context.
+// For example, parsing:
+//     `<a href=`
+// will end in context{stateBeforeValue, attrURL}, but parsing one extra rune:
+//     `<a href=x`
+// will end in context{stateURL, delimSpaceOrTagEnd, ...}.
+// There are two transitions that happen when the 'x' is seen:
+// (1) Transition from a before-value state to a start-of-value state without
+//     consuming any character.
+// (2) Consume 'x' and transition past the first value character.
+// In this case, nudging produces the context after (1) happens.
+func nudge(c context) context {
+	switch c.state {
+	case stateTag:
+		// In `<foo {{.}}`, the action should emit an attribute.
+		c.state = stateAttrName
+	case stateBeforeValue:
+		// In `<foo bar={{.}}`, the action is an undelimited value.
+		c.state, c.delim, c.attr = attrStartStates[c.attr], delimSpaceOrTagEnd, attrNone
+	case stateAfterName:
+		// In `<foo bar {{.}}`, the action is an attribute name.
+		c.state, c.attr = stateAttrName, attrNone
+	}
+	return c
+}
+
+// join joins the two contexts of a branch template node. The result is an
+// error context if either of the input contexts are error contexts, or if the
+// the input contexts differ.
+func join(a, b context, line int, nodeName string) context {
+	if a.state == stateError {
+		return a
+	}
+	if b.state == stateError {
+		return b
+	}
+	if a.eq(b) {
+		return a
+	}
+
+	c := a
+	c.urlPart = b.urlPart
+	if c.eq(b) {
+		// The contexts differ only by urlPart.
+		c.urlPart = urlPartUnknown
+		return c
+	}
+
+	c = a
+	c.jsCtx = b.jsCtx
+	if c.eq(b) {
+		// The contexts differ only by jsCtx.
+		c.jsCtx = jsCtxUnknown
+		return c
+	}
+
+	// Allow a nudged context to join with an unnudged one.
+	// This means that
+	//   <p title={{if .C}}{{.}}{{end}}
+	// ends in an unquoted value state even though the else branch
+	// ends in stateBeforeValue.
+	if c, d := nudge(a), nudge(b); !(c.eq(a) && d.eq(b)) {
+		if e := join(c, d, line, nodeName); e.state != stateError {
+			return e
+		}
+	}
+
+	return context{
+		state: stateError,
+		err:   errorf(ErrBranchEnd, line, "{{%s}} branches end in different contexts: %v, %v", nodeName, a, b),
+	}
+}
+
+// escapeBranch escapes a branch template node: "if", "range" and "with".
+func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) context {
+	c0 := e.escapeList(c, n.List)
+	if nodeName == "range" && c0.state != stateError {
+		// The "true" branch of a "range" node can execute multiple times.
+		// We check that executing n.List once results in the same context
+		// as executing n.List twice.
+		c1, _ := e.escapeListConditionally(c0, n.List, nil)
+		c0 = join(c0, c1, n.Line, nodeName)
+		if c0.state == stateError {
+			// Make clear that this is a problem on loop re-entry
+			// since developers tend to overlook that branch when
+			// debugging templates.
+			c0.err.Line = n.Line
+			c0.err.Description = "on range loop re-entry: " + c0.err.Description
+			return c0
+		}
+	}
+	c1 := e.escapeList(c, n.ElseList)
+	return join(c0, c1, n.Line, nodeName)
+}
+
+// escapeList escapes a list template node.
+func (e *escaper) escapeList(c context, n *parse.ListNode) context {
+	if n == nil {
+		return c
+	}
+	for _, m := range n.Nodes {
+		c = e.escape(c, m)
+	}
+	return c
+}
+
+// escapeListConditionally escapes a list node but only preserves edits and
+// inferences in e if the inferences and output context satisfy filter.
+// It returns the best guess at an output context, and the result of the filter
+// which is the same as whether e was updated.
+func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter func(*escaper, context) bool) (context, bool) {
+	e1 := newEscaper(e.tmpl)
+	// Make type inferences available to f.
+	for k, v := range e.output {
+		e1.output[k] = v
+	}
+	c = e1.escapeList(c, n)
+	ok := filter != nil && filter(e1, c)
+	if ok {
+		// Copy inferences and edits from e1 back into e.
+		for k, v := range e1.output {
+			e.output[k] = v
+		}
+		for k, v := range e1.derived {
+			e.derived[k] = v
+		}
+		for k, v := range e1.called {
+			e.called[k] = v
+		}
+		for k, v := range e1.actionNodeEdits {
+			e.editActionNode(k, v)
+		}
+		for k, v := range e1.templateNodeEdits {
+			e.editTemplateNode(k, v)
+		}
+		for k, v := range e1.textNodeEdits {
+			e.editTextNode(k, v)
+		}
+	}
+	return c, ok
+}
+
+// escapeTemplate escapes a {{template}} call node.
+func (e *escaper) escapeTemplate(c context, n *parse.TemplateNode) context {
+	c, name := e.escapeTree(c, n.Name, n.Line)
+	if name != n.Name {
+		e.editTemplateNode(n, name)
+	}
+	return c
+}
+
+// escapeTree escapes the named template starting in the given context as
+// necessary and returns its output context.
+func (e *escaper) escapeTree(c context, name string, line int) (context, string) {
+	// Mangle the template name with the input context to produce a reliable
+	// identifier.
+	dname := c.mangle(name)
+	e.called[dname] = true
+	if out, ok := e.output[dname]; ok {
+		// Already escaped.
+		return out, dname
+	}
+	t := e.template(name)
+	if t == nil {
+		// Two cases: The template exists but is empty, or has never been mentioned at
+		// all. Distinguish the cases in the error messages.
+		if e.tmpl.set[name] != nil {
+			return context{
+				state: stateError,
+				err:   errorf(ErrNoSuchTemplate, line, "%q is an incomplete or empty template", name),
+			}, dname
+		}
+		return context{
+			state: stateError,
+			err:   errorf(ErrNoSuchTemplate, line, "no such template %q", name),
+		}, dname
+	}
+	if dname != name {
+		// Use any template derived during an earlier call to escapeTemplate
+		// with different top level templates, or clone if necessary.
+		dt := e.template(dname)
+		if dt == nil {
+			dt = template.New(dname)
+			dt.Tree = &parse.Tree{Name: dname, Root: t.Root.CopyList()}
+			e.derived[dname] = dt
+		}
+		t = dt
+	}
+	return e.computeOutCtx(c, t), dname
+}
+
+// computeOutCtx takes a template and its start context and computes the output
+// context while storing any inferences in e.
+func (e *escaper) computeOutCtx(c context, t *template.Template) context {
+	// Propagate context over the body.
+	c1, ok := e.escapeTemplateBody(c, t)
+	if !ok {
+		// Look for a fixed point by assuming c1 as the output context.
+		if c2, ok2 := e.escapeTemplateBody(c1, t); ok2 {
+			c1, ok = c2, true
+		}
+		// Use c1 as the error context if neither assumption worked.
+	}
+	if !ok && c1.state != stateError {
+		return context{
+			state: stateError,
+			// TODO: Find the first node with a line in t.text.Tree.Root
+			err: errorf(ErrOutputContext, 0, "cannot compute output context for template %s", t.Name()),
+		}
+	}
+	return c1
+}
+
+// escapeTemplateBody escapes the given template assuming the given output
+// context, and returns the best guess at the output context and whether the
+// assumption was correct.
+func (e *escaper) escapeTemplateBody(c context, t *template.Template) (context, bool) {
+	filter := func(e1 *escaper, c1 context) bool {
+		if c1.state == stateError {
+			// Do not update the input escaper, e.
+			return false
+		}
+		if !e1.called[t.Name()] {
+			// If t is not recursively called, then c1 is an
+			// accurate output context.
+			return true
+		}
+		// c1 is accurate if it matches our assumed output context.
+		return c.eq(c1)
+	}
+	// We need to assume an output context so that recursive template calls
+	// take the fast path out of escapeTree instead of infinitely recursing.
+	// Naively assuming that the input context is the same as the output
+	// works >90% of the time.
+	e.output[t.Name()] = c
+	return e.escapeListConditionally(c, t.Tree.Root, filter)
+}
+
+// delimEnds maps each delim to a string of characters that terminate it.
+var delimEnds = [...]string{
+	delimDoubleQuote: `"`,
+	delimSingleQuote: "'",
+	// Determined empirically by running the below in various browsers.
+	// var div = document.createElement("DIV");
+	// for (var i = 0; i < 0x10000; ++i) {
+	//   div.innerHTML = "<span title=x" + String.fromCharCode(i) + "-bar>";
+	//   if (div.getElementsByTagName("SPAN")[0].title.indexOf("bar") < 0)
+	//     document.write("<p>U+" + i.toString(16));
+	// }
+	delimSpaceOrTagEnd: " \t\n\f\r>",
+}
+
+var doctypeBytes = []byte("<!DOCTYPE")
+
+// escapeText escapes a text template node.
+func (e *escaper) escapeText(c context, n *parse.TextNode) context {
+	s, written, i, b := n.Text, 0, 0, new(bytes.Buffer)
+	for i != len(s) {
+		c1, nread := contextAfterText(c, s[i:])
+		i1 := i + nread
+		if c.state == stateText || c.state == stateRCDATA {
+			end := i1
+			if c1.state != c.state {
+				for j := end - 1; j >= i; j-- {
+					if s[j] == '<' {
+						end = j
+						break
+					}
+				}
+			}
+			for j := i; j < end; j++ {
+				if s[j] == '<' && !bytes.HasPrefix(bytes.ToUpper(s[j:]), doctypeBytes) {
+					b.Write(s[written:j])
+					b.WriteString("&lt;")
+					written = j + 1
+				}
+			}
+		} else if isComment(c.state) && c.delim == delimNone {
+			switch c.state {
+			case stateJSBlockCmt:
+				// http://es5.github.com/#x7.4:
+				// "Comments behave like white space and are
+				// discarded except that, if a MultiLineComment
+				// contains a line terminator character, then
+				// the entire comment is considered to be a
+				// LineTerminator for purposes of parsing by
+				// the syntactic grammar."
+				if bytes.IndexAny(s[written:i1], "\n\r\u2028\u2029") != -1 {
+					b.WriteByte('\n')
+				} else {
+					b.WriteByte(' ')
+				}
+			case stateCSSBlockCmt:
+				b.WriteByte(' ')
+			}
+			written = i1
+		}
+		if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {
+			// Preserve the portion between written and the comment start.
+			cs := i1 - 2
+			if c1.state == stateHTMLCmt {
+				// "<!--" instead of "/*" or "//"
+				cs -= 2
+			}
+			b.Write(s[written:cs])
+			written = i1
+		}
+		if i == i1 && c.state == c1.state {
+			panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))
+		}
+		c, i = c1, i1
+	}
+
+	if written != 0 && c.state != stateError {
+		if !isComment(c.state) || c.delim != delimNone {
+			b.Write(n.Text[written:])
+		}
+		e.editTextNode(n, b.Bytes())
+	}
+	return c
+}
+
+// contextAfterText starts in context c, consumes some tokens from the front of
+// s, then returns the context after those tokens and the unprocessed suffix.
+func contextAfterText(c context, s []byte) (context, int) {
+	if c.delim == delimNone {
+		c1, i := tSpecialTagEnd(c, s)
+		if i == 0 {
+			// A special end tag (`</script>`) has been seen and
+			// all content preceding it has been consumed.
+			return c1, 0
+		}
+		// Consider all content up to any end tag.
+		return transitionFunc[c.state](c, s[:i])
+	}
+
+	i := bytes.IndexAny(s, delimEnds[c.delim])
+	if i == -1 {
+		i = len(s)
+	}
+	if c.delim == delimSpaceOrTagEnd {
+		// http://www.w3.org/TR/html5/syntax.html#attribute-value-(unquoted)-state
+		// lists the runes below as error characters.
+		// Error out because HTML parsers may differ on whether
+		// "<a id= onclick=f("     ends inside id's or onclick's value,
+		// "<a class=`foo "        ends inside a value,
+		// "<a style=font:'Arial'" needs open-quote fixup.
+		// IE treats '`' as a quotation character.
+		if j := bytes.IndexAny(s[:i], "\"'<=`"); j >= 0 {
+			return context{
+				state: stateError,
+				err:   errorf(ErrBadHTML, 0, "%q in unquoted attr: %q", s[j:j+1], s[:i]),
+			}, len(s)
+		}
+	}
+	if i == len(s) {
+		// Remain inside the attribute.
+		// Decode the value so non-HTML rules can easily handle
+		//     <button onclick="alert(&quot;Hi!&quot;)">
+		// without having to entity decode token boundaries.
+		for u := []byte(html.UnescapeString(string(s))); len(u) != 0; {
+			c1, i1 := transitionFunc[c.state](c, u)
+			c, u = c1, u[i1:]
+		}
+		return c, len(s)
+	}
+	if c.delim != delimSpaceOrTagEnd {
+		// Consume any quote.
+		i++
+	}
+	// On exiting an attribute, we discard all state information
+	// except the state and element.
+	return context{state: stateTag, element: c.element}, i
+}
+
+// editActionNode records a change to an action pipeline for later commit.
+func (e *escaper) editActionNode(n *parse.ActionNode, cmds []string) {
+	if _, ok := e.actionNodeEdits[n]; ok {
+		panic(fmt.Sprintf("node %s shared between templates", n))
+	}
+	e.actionNodeEdits[n] = cmds
+}
+
+// editTemplateNode records a change to a {{template}} callee for later commit.
+func (e *escaper) editTemplateNode(n *parse.TemplateNode, callee string) {
+	if _, ok := e.templateNodeEdits[n]; ok {
+		panic(fmt.Sprintf("node %s shared between templates", n))
+	}
+	e.templateNodeEdits[n] = callee
+}
+
+// editTextNode records a change to a text node for later commit.
+func (e *escaper) editTextNode(n *parse.TextNode, text []byte) {
+	if _, ok := e.textNodeEdits[n]; ok {
+		panic(fmt.Sprintf("node %s shared between templates", n))
+	}
+	e.textNodeEdits[n] = text
+}
+
+// commit applies changes to actions and template calls needed to contextually
+// autoescape content and adds any derived templates to the set.
+func (e *escaper) commit() {
+	for name := range e.output {
+		e.template(name).Funcs(funcMap)
+	}
+	for _, t := range e.derived {
+		if _, err := e.tmpl.text.AddParseTree(t.Name(), t.Tree); err != nil {
+			panic("error adding derived template")
+		}
+	}
+	for n, s := range e.actionNodeEdits {
+		ensurePipelineContains(n.Pipe, s)
+	}
+	for n, name := range e.templateNodeEdits {
+		n.Name = name
+	}
+	for n, s := range e.textNodeEdits {
+		n.Text = s
+	}
+}
+
+// template returns the named template given a mangled template name.
+func (e *escaper) template(name string) *template.Template {
+	t := e.tmpl.text.Lookup(name)
+	if t == nil {
+		t = e.derived[name]
+	}
+	return t
+}
+
+// Forwarding functions so that clients need only import this package
+// to reach the general escaping functions of text/template.
+
+// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
+func HTMLEscape(w io.Writer, b []byte) {
+	template.HTMLEscape(w, b)
+}
+
+// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
+func HTMLEscapeString(s string) string {
+	return template.HTMLEscapeString(s)
+}
+
+// HTMLEscaper returns the escaped HTML equivalent of the textual
+// representation of its arguments.
+func HTMLEscaper(args ...interface{}) string {
+	return template.HTMLEscaper(args...)
+}
+
+// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
+func JSEscape(w io.Writer, b []byte) {
+	template.JSEscape(w, b)
+}
+
+// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
+func JSEscapeString(s string) string {
+	return template.JSEscapeString(s)
+}
+
+// JSEscaper returns the escaped JavaScript equivalent of the textual
+// representation of its arguments.
+func JSEscaper(args ...interface{}) string {
+	return template.JSEscaper(args...)
+}
+
+// URLQueryEscaper returns the escaped value of the textual representation of
+// its arguments in a form suitable for embedding in a URL query.
+func URLQueryEscaper(args ...interface{}) string {
+	return template.URLQueryEscaper(args...)
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/escape_test.go b/third_party/gofrontend/libgo/go/html/template/escape_test.go
new file mode 100644
index 0000000..3ccf93e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/escape_test.go
@@ -0,0 +1,1692 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"os"
+	"strings"
+	"testing"
+	"text/template"
+	"text/template/parse"
+)
+
+type badMarshaler struct{}
+
+func (x *badMarshaler) MarshalJSON() ([]byte, error) {
+	// Keys in valid JSON must be double quoted as must all strings.
+	return []byte("{ foo: 'not quite valid JSON' }"), nil
+}
+
+type goodMarshaler struct{}
+
+func (x *goodMarshaler) MarshalJSON() ([]byte, error) {
+	return []byte(`{ "<foo>": "O'Reilly" }`), nil
+}
+
+func TestEscape(t *testing.T) {
+	data := struct {
+		F, T    bool
+		C, G, H string
+		A, E    []string
+		B, M    json.Marshaler
+		N       int
+		Z       *int
+		W       HTML
+	}{
+		F: false,
+		T: true,
+		C: "<Cincinatti>",
+		G: "<Goodbye>",
+		H: "<Hello>",
+		A: []string{"<a>", "<b>"},
+		E: []string{},
+		N: 42,
+		B: &badMarshaler{},
+		M: &goodMarshaler{},
+		Z: nil,
+		W: HTML(`&iexcl;<b class="foo">Hello</b>, <textarea>O'World</textarea>!`),
+	}
+	pdata := &data
+
+	tests := []struct {
+		name   string
+		input  string
+		output string
+	}{
+		{
+			"if",
+			"{{if .T}}Hello{{end}}, {{.C}}!",
+			"Hello, &lt;Cincinatti&gt;!",
+		},
+		{
+			"else",
+			"{{if .F}}{{.H}}{{else}}{{.G}}{{end}}!",
+			"&lt;Goodbye&gt;!",
+		},
+		{
+			"overescaping1",
+			"Hello, {{.C | html}}!",
+			"Hello, &lt;Cincinatti&gt;!",
+		},
+		{
+			"overescaping2",
+			"Hello, {{html .C}}!",
+			"Hello, &lt;Cincinatti&gt;!",
+		},
+		{
+			"overescaping3",
+			"{{with .C}}{{$msg := .}}Hello, {{$msg}}!{{end}}",
+			"Hello, &lt;Cincinatti&gt;!",
+		},
+		{
+			"assignment",
+			"{{if $x := .H}}{{$x}}{{end}}",
+			"&lt;Hello&gt;",
+		},
+		{
+			"withBody",
+			"{{with .H}}{{.}}{{end}}",
+			"&lt;Hello&gt;",
+		},
+		{
+			"withElse",
+			"{{with .E}}{{.}}{{else}}{{.H}}{{end}}",
+			"&lt;Hello&gt;",
+		},
+		{
+			"rangeBody",
+			"{{range .A}}{{.}}{{end}}",
+			"&lt;a&gt;&lt;b&gt;",
+		},
+		{
+			"rangeElse",
+			"{{range .E}}{{.}}{{else}}{{.H}}{{end}}",
+			"&lt;Hello&gt;",
+		},
+		{
+			"nonStringValue",
+			"{{.T}}",
+			"true",
+		},
+		{
+			"constant",
+			`<a href="/search?q={{"'a<b'"}}">`,
+			`<a href="/search?q=%27a%3cb%27">`,
+		},
+		{
+			"multipleAttrs",
+			"<a b=1 c={{.H}}>",
+			"<a b=1 c=&lt;Hello&gt;>",
+		},
+		{
+			"urlStartRel",
+			`<a href='{{"/foo/bar?a=b&c=d"}}'>`,
+			`<a href='/foo/bar?a=b&amp;c=d'>`,
+		},
+		{
+			"urlStartAbsOk",
+			`<a href='{{"http://example.com/foo/bar?a=b&c=d"}}'>`,
+			`<a href='http://example.com/foo/bar?a=b&amp;c=d'>`,
+		},
+		{
+			"protocolRelativeURLStart",
+			`<a href='{{"//example.com:8000/foo/bar?a=b&c=d"}}'>`,
+			`<a href='//example.com:8000/foo/bar?a=b&amp;c=d'>`,
+		},
+		{
+			"pathRelativeURLStart",
+			`<a href="{{"/javascript:80/foo/bar"}}">`,
+			`<a href="/javascript:80/foo/bar">`,
+		},
+		{
+			"dangerousURLStart",
+			`<a href='{{"javascript:alert(%22pwned%22)"}}'>`,
+			`<a href='#ZgotmplZ'>`,
+		},
+		{
+			"dangerousURLStart2",
+			`<a href='  {{"javascript:alert(%22pwned%22)"}}'>`,
+			`<a href='  #ZgotmplZ'>`,
+		},
+		{
+			"nonHierURL",
+			`<a href={{"mailto:Muhammed \"The Greatest\" Ali <m.ali@example.com>"}}>`,
+			`<a href=mailto:Muhammed%20%22The%20Greatest%22%20Ali%20%3cm.ali@example.com%3e>`,
+		},
+		{
+			"urlPath",
+			`<a href='http://{{"javascript:80"}}/foo'>`,
+			`<a href='http://javascript:80/foo'>`,
+		},
+		{
+			"urlQuery",
+			`<a href='/search?q={{.H}}'>`,
+			`<a href='/search?q=%3cHello%3e'>`,
+		},
+		{
+			"urlFragment",
+			`<a href='/faq#{{.H}}'>`,
+			`<a href='/faq#%3cHello%3e'>`,
+		},
+		{
+			"urlBranch",
+			`<a href="{{if .F}}/foo?a=b{{else}}/bar{{end}}">`,
+			`<a href="/bar">`,
+		},
+		{
+			"urlBranchConflictMoot",
+			`<a href="{{if .T}}/foo?a={{else}}/bar#{{end}}{{.C}}">`,
+			`<a href="/foo?a=%3cCincinatti%3e">`,
+		},
+		{
+			"jsStrValue",
+			"<button onclick='alert({{.H}})'>",
+			`<button onclick='alert(&#34;\u003cHello\u003e&#34;)'>`,
+		},
+		{
+			"jsNumericValue",
+			"<button onclick='alert({{.N}})'>",
+			`<button onclick='alert( 42 )'>`,
+		},
+		{
+			"jsBoolValue",
+			"<button onclick='alert({{.T}})'>",
+			`<button onclick='alert( true )'>`,
+		},
+		{
+			"jsNilValue",
+			"<button onclick='alert(typeof{{.Z}})'>",
+			`<button onclick='alert(typeof null )'>`,
+		},
+		{
+			"jsObjValue",
+			"<button onclick='alert({{.A}})'>",
+			`<button onclick='alert([&#34;\u003ca\u003e&#34;,&#34;\u003cb\u003e&#34;])'>`,
+		},
+		{
+			"jsObjValueScript",
+			"<script>alert({{.A}})</script>",
+			`<script>alert(["\u003ca\u003e","\u003cb\u003e"])</script>`,
+		},
+		{
+			"jsObjValueNotOverEscaped",
+			"<button onclick='alert({{.A | html}})'>",
+			`<button onclick='alert([&#34;\u003ca\u003e&#34;,&#34;\u003cb\u003e&#34;])'>`,
+		},
+		{
+			"jsStr",
+			"<button onclick='alert(&quot;{{.H}}&quot;)'>",
+			`<button onclick='alert(&quot;\x3cHello\x3e&quot;)'>`,
+		},
+		{
+			"badMarshaler",
+			`<button onclick='alert(1/{{.B}}in numbers)'>`,
+			`<button onclick='alert(1/ /* json: error calling MarshalJSON for type *template.badMarshaler: invalid character &#39;f&#39; looking for beginning of object key string */null in numbers)'>`,
+		},
+		{
+			"jsMarshaler",
+			`<button onclick='alert({{.M}})'>`,
+			`<button onclick='alert({&#34;\u003cfoo\u003e&#34;:&#34;O&#39;Reilly&#34;})'>`,
+		},
+		{
+			"jsStrNotUnderEscaped",
+			"<button onclick='alert({{.C | urlquery}})'>",
+			// URL escaped, then quoted for JS.
+			`<button onclick='alert(&#34;%3CCincinatti%3E&#34;)'>`,
+		},
+		{
+			"jsRe",
+			`<button onclick='alert(/{{"foo+bar"}}/.test(""))'>`,
+			`<button onclick='alert(/foo\x2bbar/.test(""))'>`,
+		},
+		{
+			"jsReBlank",
+			`<script>alert(/{{""}}/.test(""));</script>`,
+			`<script>alert(/(?:)/.test(""));</script>`,
+		},
+		{
+			"jsReAmbigOk",
+			`<script>{{if true}}var x = 1{{end}}</script>`,
+			// The {if} ends in an ambiguous jsCtx but there is
+			// no slash following so we shouldn't care.
+			`<script>var x = 1</script>`,
+		},
+		{
+			"styleBidiKeywordPassed",
+			`<p style="dir: {{"ltr"}}">`,
+			`<p style="dir: ltr">`,
+		},
+		{
+			"styleBidiPropNamePassed",
+			`<p style="border-{{"left"}}: 0; border-{{"right"}}: 1in">`,
+			`<p style="border-left: 0; border-right: 1in">`,
+		},
+		{
+			"styleExpressionBlocked",
+			`<p style="width: {{"expression(alert(1337))"}}">`,
+			`<p style="width: ZgotmplZ">`,
+		},
+		{
+			"styleTagSelectorPassed",
+			`<style>{{"p"}} { color: pink }</style>`,
+			`<style>p { color: pink }</style>`,
+		},
+		{
+			"styleIDPassed",
+			`<style>p{{"#my-ID"}} { font: Arial }</style>`,
+			`<style>p#my-ID { font: Arial }</style>`,
+		},
+		{
+			"styleClassPassed",
+			`<style>p{{".my_class"}} { font: Arial }</style>`,
+			`<style>p.my_class { font: Arial }</style>`,
+		},
+		{
+			"styleQuantityPassed",
+			`<a style="left: {{"2em"}}; top: {{0}}">`,
+			`<a style="left: 2em; top: 0">`,
+		},
+		{
+			"stylePctPassed",
+			`<table style=width:{{"100%"}}>`,
+			`<table style=width:100%>`,
+		},
+		{
+			"styleColorPassed",
+			`<p style="color: {{"#8ff"}}; background: {{"#000"}}">`,
+			`<p style="color: #8ff; background: #000">`,
+		},
+		{
+			"styleObfuscatedExpressionBlocked",
+			`<p style="width: {{"  e\\78preS\x00Sio/**/n(alert(1337))"}}">`,
+			`<p style="width: ZgotmplZ">`,
+		},
+		{
+			"styleMozBindingBlocked",
+			`<p style="{{"-moz-binding(alert(1337))"}}: ...">`,
+			`<p style="ZgotmplZ: ...">`,
+		},
+		{
+			"styleObfuscatedMozBindingBlocked",
+			`<p style="{{"  -mo\\7a-B\x00I/**/nding(alert(1337))"}}: ...">`,
+			`<p style="ZgotmplZ: ...">`,
+		},
+		{
+			"styleFontNameString",
+			`<p style='font-family: "{{"Times New Roman"}}"'>`,
+			`<p style='font-family: "Times New Roman"'>`,
+		},
+		{
+			"styleFontNameString",
+			`<p style='font-family: "{{"Times New Roman"}}", "{{"sans-serif"}}"'>`,
+			`<p style='font-family: "Times New Roman", "sans-serif"'>`,
+		},
+		{
+			"styleFontNameUnquoted",
+			`<p style='font-family: {{"Times New Roman"}}'>`,
+			`<p style='font-family: Times New Roman'>`,
+		},
+		{
+			"styleURLQueryEncoded",
+			`<p style="background: url(/img?name={{"O'Reilly Animal(1)<2>.png"}})">`,
+			`<p style="background: url(/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png)">`,
+		},
+		{
+			"styleQuotedURLQueryEncoded",
+			`<p style="background: url('/img?name={{"O'Reilly Animal(1)<2>.png"}}')">`,
+			`<p style="background: url('/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png')">`,
+		},
+		{
+			"styleStrQueryEncoded",
+			`<p style="background: '/img?name={{"O'Reilly Animal(1)<2>.png"}}'">`,
+			`<p style="background: '/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png'">`,
+		},
+		{
+			"styleURLBadProtocolBlocked",
+			`<a style="background: url('{{"javascript:alert(1337)"}}')">`,
+			`<a style="background: url('#ZgotmplZ')">`,
+		},
+		{
+			"styleStrBadProtocolBlocked",
+			`<a style="background: '{{"vbscript:alert(1337)"}}'">`,
+			`<a style="background: '#ZgotmplZ'">`,
+		},
+		{
+			"styleStrEncodedProtocolEncoded",
+			`<a style="background: '{{"javascript\\3a alert(1337)"}}'">`,
+			// The CSS string 'javascript\\3a alert(1337)' does not contains a colon.
+			`<a style="background: 'javascript\\3a alert\28 1337\29 '">`,
+		},
+		{
+			"styleURLGoodProtocolPassed",
+			`<a style="background: url('{{"http://oreilly.com/O'Reilly Animals(1)<2>;{}.html"}}')">`,
+			`<a style="background: url('http://oreilly.com/O%27Reilly%20Animals%281%29%3c2%3e;%7b%7d.html')">`,
+		},
+		{
+			"styleStrGoodProtocolPassed",
+			`<a style="background: '{{"http://oreilly.com/O'Reilly Animals(1)<2>;{}.html"}}'">`,
+			`<a style="background: 'http\3a\2f\2foreilly.com\2fO\27Reilly Animals\28 1\29\3c 2\3e\3b\7b\7d.html'">`,
+		},
+		{
+			"styleURLEncodedForHTMLInAttr",
+			`<a style="background: url('{{"/search?img=foo&size=icon"}}')">`,
+			`<a style="background: url('/search?img=foo&amp;size=icon')">`,
+		},
+		{
+			"styleURLNotEncodedForHTMLInCdata",
+			`<style>body { background: url('{{"/search?img=foo&size=icon"}}') }</style>`,
+			`<style>body { background: url('/search?img=foo&size=icon') }</style>`,
+		},
+		{
+			"styleURLMixedCase",
+			`<p style="background: URL(#{{.H}})">`,
+			`<p style="background: URL(#%3cHello%3e)">`,
+		},
+		{
+			"stylePropertyPairPassed",
+			`<a style='{{"color: red"}}'>`,
+			`<a style='color: red'>`,
+		},
+		{
+			"styleStrSpecialsEncoded",
+			`<a style="font-family: '{{"/**/'\";:// \\"}}', &quot;{{"/**/'\";:// \\"}}&quot;">`,
+			`<a style="font-family: '\2f**\2f\27\22\3b\3a\2f\2f  \\', &quot;\2f**\2f\27\22\3b\3a\2f\2f  \\&quot;">`,
+		},
+		{
+			"styleURLSpecialsEncoded",
+			`<a style="border-image: url({{"/**/'\";:// \\"}}), url(&quot;{{"/**/'\";:// \\"}}&quot;), url('{{"/**/'\";:// \\"}}'), 'http://www.example.com/?q={{"/**/'\";:// \\"}}''">`,
+			`<a style="border-image: url(/**/%27%22;://%20%5c), url(&quot;/**/%27%22;://%20%5c&quot;), url('/**/%27%22;://%20%5c'), 'http://www.example.com/?q=%2f%2a%2a%2f%27%22%3b%3a%2f%2f%20%5c''">`,
+		},
+		{
+			"HTML comment",
+			"<b>Hello, <!-- name of world -->{{.C}}</b>",
+			"<b>Hello, &lt;Cincinatti&gt;</b>",
+		},
+		{
+			"HTML comment not first < in text node.",
+			"<<!-- -->!--",
+			"&lt;!--",
+		},
+		{
+			"HTML normalization 1",
+			"a < b",
+			"a &lt; b",
+		},
+		{
+			"HTML normalization 2",
+			"a << b",
+			"a &lt;&lt; b",
+		},
+		{
+			"HTML normalization 3",
+			"a<<!-- --><!-- -->b",
+			"a&lt;b",
+		},
+		{
+			"HTML doctype not normalized",
+			"<!DOCTYPE html>Hello, World!",
+			"<!DOCTYPE html>Hello, World!",
+		},
+		{
+			"HTML doctype not case-insensitive",
+			"<!doCtYPE htMl>Hello, World!",
+			"<!doCtYPE htMl>Hello, World!",
+		},
+		{
+			"No doctype injection",
+			`<!{{"DOCTYPE"}}`,
+			"&lt;!DOCTYPE",
+		},
+		{
+			"Split HTML comment",
+			"<b>Hello, <!-- name of {{if .T}}city -->{{.C}}{{else}}world -->{{.W}}{{end}}</b>",
+			"<b>Hello, &lt;Cincinatti&gt;</b>",
+		},
+		{
+			"JS line comment",
+			"<script>for (;;) { if (c()) break// foo not a label\n" +
+				"foo({{.T}});}</script>",
+			"<script>for (;;) { if (c()) break\n" +
+				"foo( true );}</script>",
+		},
+		{
+			"JS multiline block comment",
+			"<script>for (;;) { if (c()) break/* foo not a label\n" +
+				" */foo({{.T}});}</script>",
+			// Newline separates break from call. If newline
+			// removed, then break will consume label leaving
+			// code invalid.
+			"<script>for (;;) { if (c()) break\n" +
+				"foo( true );}</script>",
+		},
+		{
+			"JS single-line block comment",
+			"<script>for (;;) {\n" +
+				"if (c()) break/* foo a label */foo;" +
+				"x({{.T}});}</script>",
+			// Newline separates break from call. If newline
+			// removed, then break will consume label leaving
+			// code invalid.
+			"<script>for (;;) {\n" +
+				"if (c()) break foo;" +
+				"x( true );}</script>",
+		},
+		{
+			"JS block comment flush with mathematical division",
+			"<script>var a/*b*//c\nd</script>",
+			"<script>var a /c\nd</script>",
+		},
+		{
+			"JS mixed comments",
+			"<script>var a/*b*///c\nd</script>",
+			"<script>var a \nd</script>",
+		},
+		{
+			"CSS comments",
+			"<style>p// paragraph\n" +
+				`{border: 1px/* color */{{"#00f"}}}</style>`,
+			"<style>p\n" +
+				"{border: 1px #00f}</style>",
+		},
+		{
+			"JS attr block comment",
+			`<a onclick="f(&quot;&quot;); /* alert({{.H}}) */">`,
+			// Attribute comment tests should pass if the comments
+			// are successfully elided.
+			`<a onclick="f(&quot;&quot;); /* alert() */">`,
+		},
+		{
+			"JS attr line comment",
+			`<a onclick="// alert({{.G}})">`,
+			`<a onclick="// alert()">`,
+		},
+		{
+			"CSS attr block comment",
+			`<a style="/* color: {{.H}} */">`,
+			`<a style="/* color:  */">`,
+		},
+		{
+			"CSS attr line comment",
+			`<a style="// color: {{.G}}">`,
+			`<a style="// color: ">`,
+		},
+		{
+			"HTML substitution commented out",
+			"<p><!-- {{.H}} --></p>",
+			"<p></p>",
+		},
+		{
+			"Comment ends flush with start",
+			"<!--{{.}}--><script>/*{{.}}*///{{.}}\n</script><style>/*{{.}}*///{{.}}\n</style><a onclick='/*{{.}}*///{{.}}' style='/*{{.}}*///{{.}}'>",
+			"<script> \n</script><style> \n</style><a onclick='/**///' style='/**///'>",
+		},
+		{
+			"typed HTML in text",
+			`{{.W}}`,
+			`&iexcl;<b class="foo">Hello</b>, <textarea>O'World</textarea>!`,
+		},
+		{
+			"typed HTML in attribute",
+			`<div title="{{.W}}">`,
+			`<div title="&iexcl;Hello, O&#39;World!">`,
+		},
+		{
+			"typed HTML in script",
+			`<button onclick="alert({{.W}})">`,
+			`<button onclick="alert(&#34;\u0026iexcl;\u003cb class=\&#34;foo\&#34;\u003eHello\u003c/b\u003e, \u003ctextarea\u003eO&#39;World\u003c/textarea\u003e!&#34;)">`,
+		},
+		{
+			"typed HTML in RCDATA",
+			`<textarea>{{.W}}</textarea>`,
+			`<textarea>&iexcl;&lt;b class=&#34;foo&#34;&gt;Hello&lt;/b&gt;, &lt;textarea&gt;O&#39;World&lt;/textarea&gt;!</textarea>`,
+		},
+		{
+			"range in textarea",
+			"<textarea>{{range .A}}{{.}}{{end}}</textarea>",
+			"<textarea>&lt;a&gt;&lt;b&gt;</textarea>",
+		},
+		{
+			"No tag injection",
+			`{{"10$"}}<{{"script src,evil.org/pwnd.js"}}...`,
+			`10$&lt;script src,evil.org/pwnd.js...`,
+		},
+		{
+			"No comment injection",
+			`<{{"!--"}}`,
+			`&lt;!--`,
+		},
+		{
+			"No RCDATA end tag injection",
+			`<textarea><{{"/textarea "}}...</textarea>`,
+			`<textarea>&lt;/textarea ...</textarea>`,
+		},
+		{
+			"optional attrs",
+			`<img class="{{"iconClass"}}"` +
+				`{{if .T}} id="{{"<iconId>"}}"{{end}}` +
+				// Double quotes inside if/else.
+				` src=` +
+				`{{if .T}}"?{{"<iconPath>"}}"` +
+				`{{else}}"images/cleardot.gif"{{end}}` +
+				// Missing space before title, but it is not a
+				// part of the src attribute.
+				`{{if .T}}title="{{"<title>"}}"{{end}}` +
+				// Quotes outside if/else.
+				` alt="` +
+				`{{if .T}}{{"<alt>"}}` +
+				`{{else}}{{if .F}}{{"<title>"}}{{end}}` +
+				`{{end}}"` +
+				`>`,
+			`<img class="iconClass" id="&lt;iconId&gt;" src="?%3ciconPath%3e"title="&lt;title&gt;" alt="&lt;alt&gt;">`,
+		},
+		{
+			"conditional valueless attr name",
+			`<input{{if .T}} checked{{end}} name=n>`,
+			`<input checked name=n>`,
+		},
+		{
+			"conditional dynamic valueless attr name 1",
+			`<input{{if .T}} {{"checked"}}{{end}} name=n>`,
+			`<input checked name=n>`,
+		},
+		{
+			"conditional dynamic valueless attr name 2",
+			`<input {{if .T}}{{"checked"}} {{end}}name=n>`,
+			`<input checked name=n>`,
+		},
+		{
+			"dynamic attribute name",
+			`<img on{{"load"}}="alert({{"loaded"}})">`,
+			// Treated as JS since quotes are inserted.
+			`<img onload="alert(&#34;loaded&#34;)">`,
+		},
+		{
+			"bad dynamic attribute name 1",
+			// Allow checked, selected, disabled, but not JS or
+			// CSS attributes.
+			`<input {{"onchange"}}="{{"doEvil()"}}">`,
+			`<input ZgotmplZ="doEvil()">`,
+		},
+		{
+			"bad dynamic attribute name 2",
+			`<div {{"sTyle"}}="{{"color: expression(alert(1337))"}}">`,
+			`<div ZgotmplZ="color: expression(alert(1337))">`,
+		},
+		{
+			"bad dynamic attribute name 3",
+			// Allow title or alt, but not a URL.
+			`<img {{"src"}}="{{"javascript:doEvil()"}}">`,
+			`<img ZgotmplZ="javascript:doEvil()">`,
+		},
+		{
+			"bad dynamic attribute name 4",
+			// Structure preservation requires values to associate
+			// with a consistent attribute.
+			`<input checked {{""}}="Whose value am I?">`,
+			`<input checked ZgotmplZ="Whose value am I?">`,
+		},
+		{
+			"dynamic element name",
+			`<h{{3}}><table><t{{"head"}}>...</h{{3}}>`,
+			`<h3><table><thead>...</h3>`,
+		},
+		{
+			"bad dynamic element name",
+			// Dynamic element names are typically used to switch
+			// between (thead, tfoot, tbody), (ul, ol), (th, td),
+			// and other replaceable sets.
+			// We do not currently easily support (ul, ol).
+			// If we do change to support that, this test should
+			// catch failures to filter out special tag names which
+			// would violate the structure preservation property --
+			// if any special tag name could be substituted, then
+			// the content could be raw text/RCDATA for some inputs
+			// and regular HTML content for others.
+			`<{{"script"}}>{{"doEvil()"}}</{{"script"}}>`,
+			`&lt;script>doEvil()&lt;/script>`,
+		},
+	}
+
+	for _, test := range tests {
+		tmpl := New(test.name)
+		tmpl = Must(tmpl.Parse(test.input))
+		// Check for bug 6459: Tree field was not set in Parse.
+		if tmpl.Tree != tmpl.text.Tree {
+			t.Errorf("%s: tree not set properly", test.name)
+			continue
+		}
+		b := new(bytes.Buffer)
+		if err := tmpl.Execute(b, data); err != nil {
+			t.Errorf("%s: template execution failed: %s", test.name, err)
+			continue
+		}
+		if w, g := test.output, b.String(); w != g {
+			t.Errorf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g)
+			continue
+		}
+		b.Reset()
+		if err := tmpl.Execute(b, pdata); err != nil {
+			t.Errorf("%s: template execution failed for pointer: %s", test.name, err)
+			continue
+		}
+		if w, g := test.output, b.String(); w != g {
+			t.Errorf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g)
+			continue
+		}
+		if tmpl.Tree != tmpl.text.Tree {
+			t.Errorf("%s: tree mismatch", test.name)
+			continue
+		}
+	}
+}
+
+func TestEscapeSet(t *testing.T) {
+	type dataItem struct {
+		Children []*dataItem
+		X        string
+	}
+
+	data := dataItem{
+		Children: []*dataItem{
+			{X: "foo"},
+			{X: "<bar>"},
+			{
+				Children: []*dataItem{
+					{X: "baz"},
+				},
+			},
+		},
+	}
+
+	tests := []struct {
+		inputs map[string]string
+		want   string
+	}{
+		// The trivial set.
+		{
+			map[string]string{
+				"main": ``,
+			},
+			``,
+		},
+		// A template called in the start context.
+		{
+			map[string]string{
+				"main": `Hello, {{template "helper"}}!`,
+				// Not a valid top level HTML template.
+				// "<b" is not a full tag.
+				"helper": `{{"<World>"}}`,
+			},
+			`Hello, &lt;World&gt;!`,
+		},
+		// A template called in a context other than the start.
+		{
+			map[string]string{
+				"main": `<a onclick='a = {{template "helper"}};'>`,
+				// Not a valid top level HTML template.
+				// "<b" is not a full tag.
+				"helper": `{{"<a>"}}<b`,
+			},
+			`<a onclick='a = &#34;\u003ca\u003e&#34;<b;'>`,
+		},
+		// A recursive template that ends in its start context.
+		{
+			map[string]string{
+				"main": `{{range .Children}}{{template "main" .}}{{else}}{{.X}} {{end}}`,
+			},
+			`foo &lt;bar&gt; baz `,
+		},
+		// A recursive helper template that ends in its start context.
+		{
+			map[string]string{
+				"main":   `{{template "helper" .}}`,
+				"helper": `{{if .Children}}<ul>{{range .Children}}<li>{{template "main" .}}</li>{{end}}</ul>{{else}}{{.X}}{{end}}`,
+			},
+			`<ul><li>foo</li><li>&lt;bar&gt;</li><li><ul><li>baz</li></ul></li></ul>`,
+		},
+		// Co-recursive templates that end in its start context.
+		{
+			map[string]string{
+				"main":   `<blockquote>{{range .Children}}{{template "helper" .}}{{end}}</blockquote>`,
+				"helper": `{{if .Children}}{{template "main" .}}{{else}}{{.X}}<br>{{end}}`,
+			},
+			`<blockquote>foo<br>&lt;bar&gt;<br><blockquote>baz<br></blockquote></blockquote>`,
+		},
+		// A template that is called in two different contexts.
+		{
+			map[string]string{
+				"main":   `<button onclick="title='{{template "helper"}}'; ...">{{template "helper"}}</button>`,
+				"helper": `{{11}} of {{"<100>"}}`,
+			},
+			`<button onclick="title='11 of \x3c100\x3e'; ...">11 of &lt;100&gt;</button>`,
+		},
+		// A non-recursive template that ends in a different context.
+		// helper starts in jsCtxRegexp and ends in jsCtxDivOp.
+		{
+			map[string]string{
+				"main":   `<script>var x={{template "helper"}}/{{"42"}};</script>`,
+				"helper": "{{126}}",
+			},
+			`<script>var x= 126 /"42";</script>`,
+		},
+		// A recursive template that ends in a similar context.
+		{
+			map[string]string{
+				"main":      `<script>var x=[{{template "countdown" 4}}];</script>`,
+				"countdown": `{{.}}{{if .}},{{template "countdown" . | pred}}{{end}}`,
+			},
+			`<script>var x=[ 4 , 3 , 2 , 1 , 0 ];</script>`,
+		},
+		// A recursive template that ends in a different context.
+		/*
+			{
+				map[string]string{
+					"main":   `<a href="/foo{{template "helper" .}}">`,
+					"helper": `{{if .Children}}{{range .Children}}{{template "helper" .}}{{end}}{{else}}?x={{.X}}{{end}}`,
+				},
+				`<a href="/foo?x=foo?x=%3cbar%3e?x=baz">`,
+			},
+		*/
+	}
+
+	// pred is a template function that returns the predecessor of a
+	// natural number for testing recursive templates.
+	fns := FuncMap{"pred": func(a ...interface{}) (interface{}, error) {
+		if len(a) == 1 {
+			if i, _ := a[0].(int); i > 0 {
+				return i - 1, nil
+			}
+		}
+		return nil, fmt.Errorf("undefined pred(%v)", a)
+	}}
+
+	for _, test := range tests {
+		source := ""
+		for name, body := range test.inputs {
+			source += fmt.Sprintf("{{define %q}}%s{{end}} ", name, body)
+		}
+		tmpl, err := New("root").Funcs(fns).Parse(source)
+		if err != nil {
+			t.Errorf("error parsing %q: %v", source, err)
+			continue
+		}
+		var b bytes.Buffer
+
+		if err := tmpl.ExecuteTemplate(&b, "main", data); err != nil {
+			t.Errorf("%q executing %v", err.Error(), tmpl.Lookup("main"))
+			continue
+		}
+		if got := b.String(); test.want != got {
+			t.Errorf("want\n\t%q\ngot\n\t%q", test.want, got)
+		}
+	}
+
+}
+
+func TestErrors(t *testing.T) {
+	tests := []struct {
+		input string
+		err   string
+	}{
+		// Non-error cases.
+		{
+			"{{if .Cond}}<a>{{else}}<b>{{end}}",
+			"",
+		},
+		{
+			"{{if .Cond}}<a>{{end}}",
+			"",
+		},
+		{
+			"{{if .Cond}}{{else}}<b>{{end}}",
+			"",
+		},
+		{
+			"{{with .Cond}}<div>{{end}}",
+			"",
+		},
+		{
+			"{{range .Items}}<a>{{end}}",
+			"",
+		},
+		{
+			"<a href='/foo?{{range .Items}}&{{.K}}={{.V}}{{end}}'>",
+			"",
+		},
+		// Error cases.
+		{
+			"{{if .Cond}}<a{{end}}",
+			"z:1: {{if}} branches",
+		},
+		{
+			"{{if .Cond}}\n{{else}}\n<a{{end}}",
+			"z:1: {{if}} branches",
+		},
+		{
+			// Missing quote in the else branch.
+			`{{if .Cond}}<a href="foo">{{else}}<a href="bar>{{end}}`,
+			"z:1: {{if}} branches",
+		},
+		{
+			// Different kind of attribute: href implies a URL.
+			"<a {{if .Cond}}href='{{else}}title='{{end}}{{.X}}'>",
+			"z:1: {{if}} branches",
+		},
+		{
+			"\n{{with .X}}<a{{end}}",
+			"z:2: {{with}} branches",
+		},
+		{
+			"\n{{with .X}}<a>{{else}}<a{{end}}",
+			"z:2: {{with}} branches",
+		},
+		{
+			"{{range .Items}}<a{{end}}",
+			`z:1: on range loop re-entry: "<" in attribute name: "<a"`,
+		},
+		{
+			"\n{{range .Items}} x='<a{{end}}",
+			"z:2: on range loop re-entry: {{range}} branches",
+		},
+		{
+			"<a b=1 c={{.H}}",
+			"z: ends in a non-text context: {stateAttr delimSpaceOrTagEnd",
+		},
+		{
+			"<script>foo();",
+			"z: ends in a non-text context: {stateJS",
+		},
+		{
+			`<a href="{{if .F}}/foo?a={{else}}/bar/{{end}}{{.H}}">`,
+			"z:1: {{.H}} appears in an ambiguous URL context",
+		},
+		{
+			`<a onclick="alert('Hello \`,
+			`unfinished escape sequence in JS string: "Hello \\"`,
+		},
+		{
+			`<a onclick='alert("Hello\, World\`,
+			`unfinished escape sequence in JS string: "Hello\\, World\\"`,
+		},
+		{
+			`<a onclick='alert(/x+\`,
+			`unfinished escape sequence in JS string: "x+\\"`,
+		},
+		{
+			`<a onclick="/foo[\]/`,
+			`unfinished JS regexp charset: "foo[\\]/"`,
+		},
+		{
+			// It is ambiguous whether 1.5 should be 1\.5 or 1.5.
+			// Either `var x = 1/- 1.5 /i.test(x)`
+			// where `i.test(x)` is a method call of reference i,
+			// or `/-1\.5/i.test(x)` which is a method call on a
+			// case insensitive regular expression.
+			`<script>{{if false}}var x = 1{{end}}/-{{"1.5"}}/i.test(x)</script>`,
+			`'/' could start a division or regexp: "/-"`,
+		},
+		{
+			`{{template "foo"}}`,
+			"z:1: no such template \"foo\"",
+		},
+		{
+			`<div{{template "y"}}>` +
+				// Illegal starting in stateTag but not in stateText.
+				`{{define "y"}} foo<b{{end}}`,
+			`"<" in attribute name: " foo<b"`,
+		},
+		{
+			`<script>reverseList = [{{template "t"}}]</script>` +
+				// Missing " after recursive call.
+				`{{define "t"}}{{if .Tail}}{{template "t" .Tail}}{{end}}{{.Head}}",{{end}}`,
+			`: cannot compute output context for template t$htmltemplate_stateJS_elementScript`,
+		},
+		{
+			`<input type=button value=onclick=>`,
+			`html/template:z: "=" in unquoted attr: "onclick="`,
+		},
+		{
+			`<input type=button value= onclick=>`,
+			`html/template:z: "=" in unquoted attr: "onclick="`,
+		},
+		{
+			`<input type=button value= 1+1=2>`,
+			`html/template:z: "=" in unquoted attr: "1+1=2"`,
+		},
+		{
+			"<a class=`foo>",
+			"html/template:z: \"`\" in unquoted attr: \"`foo\"",
+		},
+		{
+			`<a style=font:'Arial'>`,
+			`html/template:z: "'" in unquoted attr: "font:'Arial'"`,
+		},
+		{
+			`<a=foo>`,
+			`: expected space, attr name, or end of tag, but got "=foo>"`,
+		},
+	}
+
+	for _, test := range tests {
+		buf := new(bytes.Buffer)
+		tmpl, err := New("z").Parse(test.input)
+		if err != nil {
+			t.Errorf("input=%q: unexpected parse error %s\n", test.input, err)
+			continue
+		}
+		err = tmpl.Execute(buf, nil)
+		var got string
+		if err != nil {
+			got = err.Error()
+		}
+		if test.err == "" {
+			if got != "" {
+				t.Errorf("input=%q: unexpected error %q", test.input, got)
+			}
+			continue
+		}
+		if strings.Index(got, test.err) == -1 {
+			t.Errorf("input=%q: error\n\t%q\ndoes not contain expected string\n\t%q", test.input, got, test.err)
+			continue
+		}
+	}
+}
+
+func TestEscapeText(t *testing.T) {
+	tests := []struct {
+		input  string
+		output context
+	}{
+		{
+			``,
+			context{},
+		},
+		{
+			`Hello, World!`,
+			context{},
+		},
+		{
+			// An orphaned "<" is OK.
+			`I <3 Ponies!`,
+			context{},
+		},
+		{
+			`<a`,
+			context{state: stateTag},
+		},
+		{
+			`<a `,
+			context{state: stateTag},
+		},
+		{
+			`<a>`,
+			context{state: stateText},
+		},
+		{
+			`<a href`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a on`,
+			context{state: stateAttrName, attr: attrScript},
+		},
+		{
+			`<a href `,
+			context{state: stateAfterName, attr: attrURL},
+		},
+		{
+			`<a style  =  `,
+			context{state: stateBeforeValue, attr: attrStyle},
+		},
+		{
+			`<a href=`,
+			context{state: stateBeforeValue, attr: attrURL},
+		},
+		{
+			`<a href=x`,
+			context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href=x `,
+			context{state: stateTag},
+		},
+		{
+			`<a href=>`,
+			context{state: stateText},
+		},
+		{
+			`<a href=x>`,
+			context{state: stateText},
+		},
+		{
+			`<a href ='`,
+			context{state: stateURL, delim: delimSingleQuote},
+		},
+		{
+			`<a href=''`,
+			context{state: stateTag},
+		},
+		{
+			`<a href= "`,
+			context{state: stateURL, delim: delimDoubleQuote},
+		},
+		{
+			`<a href=""`,
+			context{state: stateTag},
+		},
+		{
+			`<a title="`,
+			context{state: stateAttr, delim: delimDoubleQuote},
+		},
+		{
+			`<a HREF='http:`,
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a Href='/`,
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href='"`,
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href="'`,
+			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href='&apos;`,
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href="&quot;`,
+			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href="&#34;`,
+			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href=&quot;`,
+			context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery},
+		},
+		{
+			`<img alt="1">`,
+			context{state: stateText},
+		},
+		{
+			`<img alt="1>"`,
+			context{state: stateTag},
+		},
+		{
+			`<img alt="1>">`,
+			context{state: stateText},
+		},
+		{
+			`<input checked type="checkbox"`,
+			context{state: stateTag},
+		},
+		{
+			`<a onclick="`,
+			context{state: stateJS, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="//foo`,
+			context{state: stateJSLineCmt, delim: delimDoubleQuote},
+		},
+		{
+			"<a onclick='//\n",
+			context{state: stateJS, delim: delimSingleQuote},
+		},
+		{
+			"<a onclick='//\r\n",
+			context{state: stateJS, delim: delimSingleQuote},
+		},
+		{
+			"<a onclick='//\u2028",
+			context{state: stateJS, delim: delimSingleQuote},
+		},
+		{
+			`<a onclick="/*`,
+			context{state: stateJSBlockCmt, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/*/`,
+			context{state: stateJSBlockCmt, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/**/`,
+			context{state: stateJS, delim: delimDoubleQuote},
+		},
+		{
+			`<a onkeypress="&quot;`,
+			context{state: stateJSDqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick='&quot;foo&quot;`,
+			context{state: stateJS, delim: delimSingleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<a onclick=&#39;foo&#39;`,
+			context{state: stateJS, delim: delimSpaceOrTagEnd, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<a onclick=&#39;foo`,
+			context{state: stateJSSqStr, delim: delimSpaceOrTagEnd},
+		},
+		{
+			`<a onclick="&quot;foo'`,
+			context{state: stateJSDqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="'foo&quot;`,
+			context{state: stateJSSqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<A ONCLICK="'`,
+			context{state: stateJSSqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/`,
+			context{state: stateJSRegexp, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="'foo'`,
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<a onclick="'foo\'`,
+			context{state: stateJSSqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="'foo\'`,
+			context{state: stateJSSqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/foo/`,
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<script>/foo/ /=`,
+			context{state: stateJS, element: elementScript},
+		},
+		{
+			`<a onclick="1 /foo`,
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<a onclick="1 /*c*/ /foo`,
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<a onclick="/foo[/]`,
+			context{state: stateJSRegexp, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/foo\/`,
+			context{state: stateJSRegexp, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/foo/`,
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<input checked style="`,
+			context{state: stateCSS, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="//`,
+			context{state: stateCSSLineCmt, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="//</script>`,
+			context{state: stateCSSLineCmt, delim: delimDoubleQuote},
+		},
+		{
+			"<a style='//\n",
+			context{state: stateCSS, delim: delimSingleQuote},
+		},
+		{
+			"<a style='//\r",
+			context{state: stateCSS, delim: delimSingleQuote},
+		},
+		{
+			`<a style="/*`,
+			context{state: stateCSSBlockCmt, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="/*/`,
+			context{state: stateCSSBlockCmt, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="/**/`,
+			context{state: stateCSS, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: '`,
+			context{state: stateCSSSqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: &quot;`,
+			context{state: stateCSSDqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: '/foo?img=`,
+			context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag},
+		},
+		{
+			`<a style="background: '/`,
+			context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url(&#x22;/`,
+			context{state: stateCSSDqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url('/`,
+			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url('/)`,
+			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url('/ `,
+			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url(/`,
+			context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url( `,
+			context{state: stateCSSURL, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: url( /image?name=`,
+			context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag},
+		},
+		{
+			`<a style="background: url(x)`,
+			context{state: stateCSS, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: url('x'`,
+			context{state: stateCSS, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: url( x `,
+			context{state: stateCSS, delim: delimDoubleQuote},
+		},
+		{
+			`<!-- foo`,
+			context{state: stateHTMLCmt},
+		},
+		{
+			`<!-->`,
+			context{state: stateHTMLCmt},
+		},
+		{
+			`<!--->`,
+			context{state: stateHTMLCmt},
+		},
+		{
+			`<!-- foo -->`,
+			context{state: stateText},
+		},
+		{
+			`<script`,
+			context{state: stateTag, element: elementScript},
+		},
+		{
+			`<script `,
+			context{state: stateTag, element: elementScript},
+		},
+		{
+			`<script src="foo.js" `,
+			context{state: stateTag, element: elementScript},
+		},
+		{
+			`<script src='foo.js' `,
+			context{state: stateTag, element: elementScript},
+		},
+		{
+			`<script type=text/javascript `,
+			context{state: stateTag, element: elementScript},
+		},
+		{
+			`<script>foo`,
+			context{state: stateJS, jsCtx: jsCtxDivOp, element: elementScript},
+		},
+		{
+			`<script>foo</script>`,
+			context{state: stateText},
+		},
+		{
+			`<script>foo</script><!--`,
+			context{state: stateHTMLCmt},
+		},
+		{
+			`<script>document.write("<p>foo</p>");`,
+			context{state: stateJS, element: elementScript},
+		},
+		{
+			`<script>document.write("<p>foo<\/script>");`,
+			context{state: stateJS, element: elementScript},
+		},
+		{
+			`<script>document.write("<script>alert(1)</script>");`,
+			context{state: stateText},
+		},
+		{
+			`<Script>`,
+			context{state: stateJS, element: elementScript},
+		},
+		{
+			`<SCRIPT>foo`,
+			context{state: stateJS, jsCtx: jsCtxDivOp, element: elementScript},
+		},
+		{
+			`<textarea>value`,
+			context{state: stateRCDATA, element: elementTextarea},
+		},
+		{
+			`<textarea>value</TEXTAREA>`,
+			context{state: stateText},
+		},
+		{
+			`<textarea name=html><b`,
+			context{state: stateRCDATA, element: elementTextarea},
+		},
+		{
+			`<title>value`,
+			context{state: stateRCDATA, element: elementTitle},
+		},
+		{
+			`<style>value`,
+			context{state: stateCSS, element: elementStyle},
+		},
+		{
+			`<a xlink:href`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a xmlns`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a xmlns:foo`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a xmlnsxyz`,
+			context{state: stateAttrName},
+		},
+		{
+			`<a data-url`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a data-iconUri`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a data-urlItem`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a g:`,
+			context{state: stateAttrName},
+		},
+		{
+			`<a g:url`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a g:iconUri`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a g:urlItem`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a g:value`,
+			context{state: stateAttrName},
+		},
+		{
+			`<a svg:style='`,
+			context{state: stateCSS, delim: delimSingleQuote},
+		},
+		{
+			`<svg:font-face`,
+			context{state: stateTag},
+		},
+		{
+			`<svg:a svg:onclick="`,
+			context{state: stateJS, delim: delimDoubleQuote},
+		},
+	}
+
+	for _, test := range tests {
+		b, e := []byte(test.input), newEscaper(nil)
+		c := e.escapeText(context{}, &parse.TextNode{NodeType: parse.NodeText, Text: b})
+		if !test.output.eq(c) {
+			t.Errorf("input %q: want context\n\t%v\ngot\n\t%v", test.input, test.output, c)
+			continue
+		}
+		if test.input != string(b) {
+			t.Errorf("input %q: text node was modified: want %q got %q", test.input, test.input, b)
+			continue
+		}
+	}
+}
+
+func TestEnsurePipelineContains(t *testing.T) {
+	tests := []struct {
+		input, output string
+		ids           []string
+	}{
+		{
+			"{{.X}}",
+			".X",
+			[]string{},
+		},
+		{
+			"{{.X | html}}",
+			".X | html",
+			[]string{},
+		},
+		{
+			"{{.X}}",
+			".X | html",
+			[]string{"html"},
+		},
+		{
+			"{{.X | html}}",
+			".X | html | urlquery",
+			[]string{"urlquery"},
+		},
+		{
+			"{{.X | html | urlquery}}",
+			".X | html | urlquery",
+			[]string{"urlquery"},
+		},
+		{
+			"{{.X | html | urlquery}}",
+			".X | html | urlquery",
+			[]string{"html", "urlquery"},
+		},
+		{
+			"{{.X | html | urlquery}}",
+			".X | html | urlquery",
+			[]string{"html"},
+		},
+		{
+			"{{.X | urlquery}}",
+			".X | html | urlquery",
+			[]string{"html", "urlquery"},
+		},
+		{
+			"{{.X | html | print}}",
+			".X | urlquery | html | print",
+			[]string{"urlquery", "html"},
+		},
+		{
+			"{{($).X | html | print}}",
+			"($).X | urlquery | html | print",
+			[]string{"urlquery", "html"},
+		},
+	}
+	for i, test := range tests {
+		tmpl := template.Must(template.New("test").Parse(test.input))
+		action, ok := (tmpl.Tree.Root.Nodes[0].(*parse.ActionNode))
+		if !ok {
+			t.Errorf("#%d: First node is not an action: %s", i, test.input)
+			continue
+		}
+		pipe := action.Pipe
+		ensurePipelineContains(pipe, test.ids)
+		got := pipe.String()
+		if got != test.output {
+			t.Errorf("#%d: %s, %v: want\n\t%s\ngot\n\t%s", i, test.input, test.ids, test.output, got)
+		}
+	}
+}
+
+func TestEscapeErrorsNotIgnorable(t *testing.T) {
+	var b bytes.Buffer
+	tmpl, _ := New("dangerous").Parse("<a")
+	err := tmpl.Execute(&b, nil)
+	if err == nil {
+		t.Errorf("Expected error")
+	} else if b.Len() != 0 {
+		t.Errorf("Emitted output despite escaping failure")
+	}
+}
+
+func TestEscapeSetErrorsNotIgnorable(t *testing.T) {
+	var b bytes.Buffer
+	tmpl, err := New("root").Parse(`{{define "t"}}<a{{end}}`)
+	if err != nil {
+		t.Errorf("failed to parse set: %q", err)
+	}
+	err = tmpl.ExecuteTemplate(&b, "t", nil)
+	if err == nil {
+		t.Errorf("Expected error")
+	} else if b.Len() != 0 {
+		t.Errorf("Emitted output despite escaping failure")
+	}
+}
+
+func TestRedundantFuncs(t *testing.T) {
+	inputs := []interface{}{
+		"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+			"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+			` !"#$%&'()*+,-./` +
+			`0123456789:;<=>?` +
+			`@ABCDEFGHIJKLMNO` +
+			`PQRSTUVWXYZ[\]^_` +
+			"`abcdefghijklmno" +
+			"pqrstuvwxyz{|}~\x7f" +
+			"\u00A0\u0100\u2028\u2029\ufeff\ufdec\ufffd\uffff\U0001D11E" +
+			"&amp;%22\\",
+		CSS(`a[href =~ "//example.com"]#foo`),
+		HTML(`Hello, <b>World</b> &amp;tc!`),
+		HTMLAttr(` dir="ltr"`),
+		JS(`c && alert("Hello, World!");`),
+		JSStr(`Hello, World & O'Reilly\x21`),
+		URL(`greeting=H%69&addressee=(World)`),
+	}
+
+	for n0, m := range redundantFuncs {
+		f0 := funcMap[n0].(func(...interface{}) string)
+		for n1 := range m {
+			f1 := funcMap[n1].(func(...interface{}) string)
+			for _, input := range inputs {
+				want := f0(input)
+				if got := f1(want); want != got {
+					t.Errorf("%s %s with %T %q: want\n\t%q,\ngot\n\t%q", n0, n1, input, input, want, got)
+				}
+			}
+		}
+	}
+}
+
+func TestIndirectPrint(t *testing.T) {
+	a := 3
+	ap := &a
+	b := "hello"
+	bp := &b
+	bpp := &bp
+	tmpl := Must(New("t").Parse(`{{.}}`))
+	var buf bytes.Buffer
+	err := tmpl.Execute(&buf, ap)
+	if err != nil {
+		t.Errorf("Unexpected error: %s", err)
+	} else if buf.String() != "3" {
+		t.Errorf(`Expected "3"; got %q`, buf.String())
+	}
+	buf.Reset()
+	err = tmpl.Execute(&buf, bpp)
+	if err != nil {
+		t.Errorf("Unexpected error: %s", err)
+	} else if buf.String() != "hello" {
+		t.Errorf(`Expected "hello"; got %q`, buf.String())
+	}
+}
+
+// This is a test for issue 3272.
+func TestEmptyTemplate(t *testing.T) {
+	page := Must(New("page").ParseFiles(os.DevNull))
+	if err := page.ExecuteTemplate(os.Stdout, "page", "nothing"); err == nil {
+		t.Fatal("expected error")
+	}
+}
+
+type Issue7379 int
+
+func (Issue7379) SomeMethod(x int) string {
+	return fmt.Sprintf("<%d>", x)
+}
+
+// This is a test for issue 7379: type assertion error caused panic, and then
+// the code to handle the panic breaks escaping. It's hard to see the second
+// problem once the first is fixed, but its fix is trivial so we let that go. See
+// the discussion for issue 7379.
+func TestPipeToMethodIsEscaped(t *testing.T) {
+	tmpl := Must(New("x").Parse("<html>{{0 | .SomeMethod}}</html>\n"))
+	tryExec := func() string {
+		defer func() {
+			panicValue := recover()
+			if panicValue != nil {
+				t.Errorf("panicked: %v\n", panicValue)
+			}
+		}()
+		var b bytes.Buffer
+		tmpl.Execute(&b, Issue7379(0))
+		return b.String()
+	}
+	for i := 0; i < 3; i++ {
+		str := tryExec()
+		const expect = "<html>&lt;0&gt;</html>\n"
+		if str != expect {
+			t.Errorf("expected %q got %q", expect, str)
+		}
+	}
+}
+
+func BenchmarkEscapedExecute(b *testing.B) {
+	tmpl := Must(New("t").Parse(`<a onclick="alert('{{.}}')">{{.}}</a>`))
+	var buf bytes.Buffer
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		tmpl.Execute(&buf, "foo & 'bar' & baz")
+		buf.Reset()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/html.go b/third_party/gofrontend/libgo/go/html/template/html.go
new file mode 100644
index 0000000..9c069ef
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/html.go
@@ -0,0 +1,257 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"unicode/utf8"
+)
+
+// htmlNospaceEscaper escapes for inclusion in unquoted attribute values.
+func htmlNospaceEscaper(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeHTML {
+		return htmlReplacer(stripTags(s), htmlNospaceNormReplacementTable, false)
+	}
+	return htmlReplacer(s, htmlNospaceReplacementTable, false)
+}
+
+// attrEscaper escapes for inclusion in quoted attribute values.
+func attrEscaper(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeHTML {
+		return htmlReplacer(stripTags(s), htmlNormReplacementTable, true)
+	}
+	return htmlReplacer(s, htmlReplacementTable, true)
+}
+
+// rcdataEscaper escapes for inclusion in an RCDATA element body.
+func rcdataEscaper(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeHTML {
+		return htmlReplacer(s, htmlNormReplacementTable, true)
+	}
+	return htmlReplacer(s, htmlReplacementTable, true)
+}
+
+// htmlEscaper escapes for inclusion in HTML text.
+func htmlEscaper(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeHTML {
+		return s
+	}
+	return htmlReplacer(s, htmlReplacementTable, true)
+}
+
+// htmlReplacementTable contains the runes that need to be escaped
+// inside a quoted attribute value or in a text node.
+var htmlReplacementTable = []string{
+	// http://www.w3.org/TR/html5/syntax.html#attribute-value-(unquoted)-state
+	// U+0000 NULL Parse error. Append a U+FFFD REPLACEMENT
+	// CHARACTER character to the current attribute's value.
+	// "
+	// and similarly
+	// http://www.w3.org/TR/html5/syntax.html#before-attribute-value-state
+	0:    "\uFFFD",
+	'"':  "&#34;",
+	'&':  "&amp;",
+	'\'': "&#39;",
+	'+':  "&#43;",
+	'<':  "&lt;",
+	'>':  "&gt;",
+}
+
+// htmlNormReplacementTable is like htmlReplacementTable but without '&' to
+// avoid over-encoding existing entities.
+var htmlNormReplacementTable = []string{
+	0:    "\uFFFD",
+	'"':  "&#34;",
+	'\'': "&#39;",
+	'+':  "&#43;",
+	'<':  "&lt;",
+	'>':  "&gt;",
+}
+
+// htmlNospaceReplacementTable contains the runes that need to be escaped
+// inside an unquoted attribute value.
+// The set of runes escaped is the union of the HTML specials and
+// those determined by running the JS below in browsers:
+// <div id=d></div>
+// <script>(function () {
+// var a = [], d = document.getElementById("d"), i, c, s;
+// for (i = 0; i < 0x10000; ++i) {
+//   c = String.fromCharCode(i);
+//   d.innerHTML = "<span title=" + c + "lt" + c + "></span>"
+//   s = d.getElementsByTagName("SPAN")[0];
+//   if (!s || s.title !== c + "lt" + c) { a.push(i.toString(16)); }
+// }
+// document.write(a.join(", "));
+// })()</script>
+var htmlNospaceReplacementTable = []string{
+	0:    "&#xfffd;",
+	'\t': "&#9;",
+	'\n': "&#10;",
+	'\v': "&#11;",
+	'\f': "&#12;",
+	'\r': "&#13;",
+	' ':  "&#32;",
+	'"':  "&#34;",
+	'&':  "&amp;",
+	'\'': "&#39;",
+	'+':  "&#43;",
+	'<':  "&lt;",
+	'=':  "&#61;",
+	'>':  "&gt;",
+	// A parse error in the attribute value (unquoted) and
+	// before attribute value states.
+	// Treated as a quoting character by IE.
+	'`': "&#96;",
+}
+
+// htmlNospaceNormReplacementTable is like htmlNospaceReplacementTable but
+// without '&' to avoid over-encoding existing entities.
+var htmlNospaceNormReplacementTable = []string{
+	0:    "&#xfffd;",
+	'\t': "&#9;",
+	'\n': "&#10;",
+	'\v': "&#11;",
+	'\f': "&#12;",
+	'\r': "&#13;",
+	' ':  "&#32;",
+	'"':  "&#34;",
+	'\'': "&#39;",
+	'+':  "&#43;",
+	'<':  "&lt;",
+	'=':  "&#61;",
+	'>':  "&gt;",
+	// A parse error in the attribute value (unquoted) and
+	// before attribute value states.
+	// Treated as a quoting character by IE.
+	'`': "&#96;",
+}
+
+// htmlReplacer returns s with runes replaced according to replacementTable
+// and when badRunes is true, certain bad runes are allowed through unescaped.
+func htmlReplacer(s string, replacementTable []string, badRunes bool) string {
+	written, b := 0, new(bytes.Buffer)
+	for i, r := range s {
+		if int(r) < len(replacementTable) {
+			if repl := replacementTable[r]; len(repl) != 0 {
+				b.WriteString(s[written:i])
+				b.WriteString(repl)
+				// Valid as long as replacementTable doesn't
+				// include anything above 0x7f.
+				written = i + utf8.RuneLen(r)
+			}
+		} else if badRunes {
+			// No-op.
+			// IE does not allow these ranges in unquoted attrs.
+		} else if 0xfdd0 <= r && r <= 0xfdef || 0xfff0 <= r && r <= 0xffff {
+			fmt.Fprintf(b, "%s&#x%x;", s[written:i], r)
+			written = i + utf8.RuneLen(r)
+		}
+	}
+	if written == 0 {
+		return s
+	}
+	b.WriteString(s[written:])
+	return b.String()
+}
+
+// stripTags takes a snippet of HTML and returns only the text content.
+// For example, `<b>&iexcl;Hi!</b> <script>...</script>` -> `&iexcl;Hi! `.
+func stripTags(html string) string {
+	var b bytes.Buffer
+	s, c, i, allText := []byte(html), context{}, 0, true
+	// Using the transition funcs helps us avoid mangling
+	// `<div title="1>2">` or `I <3 Ponies!`.
+	for i != len(s) {
+		if c.delim == delimNone {
+			st := c.state
+			// Use RCDATA instead of parsing into JS or CSS styles.
+			if c.element != elementNone && !isInTag(st) {
+				st = stateRCDATA
+			}
+			d, nread := transitionFunc[st](c, s[i:])
+			i1 := i + nread
+			if c.state == stateText || c.state == stateRCDATA {
+				// Emit text up to the start of the tag or comment.
+				j := i1
+				if d.state != c.state {
+					for j1 := j - 1; j1 >= i; j1-- {
+						if s[j1] == '<' {
+							j = j1
+							break
+						}
+					}
+				}
+				b.Write(s[i:j])
+			} else {
+				allText = false
+			}
+			c, i = d, i1
+			continue
+		}
+		i1 := i + bytes.IndexAny(s[i:], delimEnds[c.delim])
+		if i1 < i {
+			break
+		}
+		if c.delim != delimSpaceOrTagEnd {
+			// Consume any quote.
+			i1++
+		}
+		c, i = context{state: stateTag, element: c.element}, i1
+	}
+	if allText {
+		return html
+	} else if c.state == stateText || c.state == stateRCDATA {
+		b.Write(s[i:])
+	}
+	return b.String()
+}
+
+// htmlNameFilter accepts valid parts of an HTML attribute or tag name or
+// a known-safe HTML attribute.
+func htmlNameFilter(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeHTMLAttr {
+		return s
+	}
+	if len(s) == 0 {
+		// Avoid violation of structure preservation.
+		// <input checked {{.K}}={{.V}}>.
+		// Without this, if .K is empty then .V is the value of
+		// checked, but otherwise .V is the value of the attribute
+		// named .K.
+		return filterFailsafe
+	}
+	s = strings.ToLower(s)
+	if t := attrType(s); t != contentTypePlain {
+		// TODO: Split attr and element name part filters so we can whitelist
+		// attributes.
+		return filterFailsafe
+	}
+	for _, r := range s {
+		switch {
+		case '0' <= r && r <= '9':
+		case 'a' <= r && r <= 'z':
+		default:
+			return filterFailsafe
+		}
+	}
+	return s
+}
+
+// commentEscaper returns the empty string regardless of input.
+// Comment content does not correspond to any parsed structure or
+// human-readable content, so the simplest and most secure policy is to drop
+// content interpolated into comments.
+// This approach is equally valid whether or not static comment content is
+// removed from the template.
+func commentEscaper(args ...interface{}) string {
+	return ""
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/html_test.go b/third_party/gofrontend/libgo/go/html/template/html_test.go
new file mode 100644
index 0000000..b9b9703
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/html_test.go
@@ -0,0 +1,94 @@
+// 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.
+
+package template
+
+import (
+	"html"
+	"strings"
+	"testing"
+)
+
+func TestHTMLNospaceEscaper(t *testing.T) {
+	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !"#$%&'()*+,-./` +
+		`0123456789:;<=>?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\]^_` +
+		"`abcdefghijklmno" +
+		"pqrstuvwxyz{|}~\x7f" +
+		"\u00A0\u0100\u2028\u2029\ufeff\ufdec\U0001D11E")
+
+	want := ("&#xfffd;\x01\x02\x03\x04\x05\x06\x07" +
+		"\x08&#9;&#10;&#11;&#12;&#13;\x0E\x0F" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17" +
+		"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		`&#32;!&#34;#$%&amp;&#39;()*&#43;,-./` +
+		`0123456789:;&lt;&#61;&gt;?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\]^_` +
+		`&#96;abcdefghijklmno` +
+		`pqrstuvwxyz{|}~` + "\u007f" +
+		"\u00A0\u0100\u2028\u2029\ufeff&#xfdec;\U0001D11E")
+
+	got := htmlNospaceEscaper(input)
+	if got != want {
+		t.Errorf("encode: want\n\t%q\nbut got\n\t%q", want, got)
+	}
+
+	got, want = html.UnescapeString(got), strings.Replace(input, "\x00", "\ufffd", 1)
+	if want != got {
+		t.Errorf("decode: want\n\t%q\nbut got\n\t%q", want, got)
+	}
+}
+
+func TestStripTags(t *testing.T) {
+	tests := []struct {
+		input, want string
+	}{
+		{"", ""},
+		{"Hello, World!", "Hello, World!"},
+		{"foo&amp;bar", "foo&amp;bar"},
+		{`Hello <a href="www.example.com/">World</a>!`, "Hello World!"},
+		{"Foo <textarea>Bar</textarea> Baz", "Foo Bar Baz"},
+		{"Foo <!-- Bar --> Baz", "Foo  Baz"},
+		{"<", "<"},
+		{"foo < bar", "foo < bar"},
+		{`Foo<script type="text/javascript">alert(1337)</script>Bar`, "FooBar"},
+		{`Foo<div title="1>2">Bar`, "FooBar"},
+		{`I <3 Ponies!`, `I <3 Ponies!`},
+		{`<script>foo()</script>`, ``},
+	}
+
+	for _, test := range tests {
+		if got := stripTags(test.input); got != test.want {
+			t.Errorf("%q: want %q, got %q", test.input, test.want, got)
+		}
+	}
+}
+
+func BenchmarkHTMLNospaceEscaper(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		htmlNospaceEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
+
+func BenchmarkHTMLNospaceEscaperNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		htmlNospaceEscaper("The_quick,_brown_fox_jumps_over_the_lazy_dog.")
+	}
+}
+
+func BenchmarkStripTags(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		stripTags("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
+
+func BenchmarkStripTagsNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		stripTags("The quick, brown fox jumps over the lazy dog.")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/js.go b/third_party/gofrontend/libgo/go/html/template/js.go
new file mode 100644
index 0000000..999a61e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/js.go
@@ -0,0 +1,362 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"reflect"
+	"strings"
+	"unicode/utf8"
+)
+
+// nextJSCtx returns the context that determines whether a slash after the
+// given run of tokens starts a regular expression instead of a division
+// operator: / or /=.
+//
+// This assumes that the token run does not include any string tokens, comment
+// tokens, regular expression literal tokens, or division operators.
+//
+// This fails on some valid but nonsensical JavaScript programs like
+// "x = ++/foo/i" which is quite different than "x++/foo/i", but is not known to
+// fail on any known useful programs. It is based on the draft
+// JavaScript 2.0 lexical grammar and requires one token of lookbehind:
+// http://www.mozilla.org/js/language/js20-2000-07/rationale/syntax.html
+func nextJSCtx(s []byte, preceding jsCtx) jsCtx {
+	s = bytes.TrimRight(s, "\t\n\f\r \u2028\u2029")
+	if len(s) == 0 {
+		return preceding
+	}
+
+	// All cases below are in the single-byte UTF-8 group.
+	switch c, n := s[len(s)-1], len(s); c {
+	case '+', '-':
+		// ++ and -- are not regexp preceders, but + and - are whether
+		// they are used as infix or prefix operators.
+		start := n - 1
+		// Count the number of adjacent dashes or pluses.
+		for start > 0 && s[start-1] == c {
+			start--
+		}
+		if (n-start)&1 == 1 {
+			// Reached for trailing minus signs since "---" is the
+			// same as "-- -".
+			return jsCtxRegexp
+		}
+		return jsCtxDivOp
+	case '.':
+		// Handle "42."
+		if n != 1 && '0' <= s[n-2] && s[n-2] <= '9' {
+			return jsCtxDivOp
+		}
+		return jsCtxRegexp
+	// Suffixes for all punctuators from section 7.7 of the language spec
+	// that only end binary operators not handled above.
+	case ',', '<', '>', '=', '*', '%', '&', '|', '^', '?':
+		return jsCtxRegexp
+	// Suffixes for all punctuators from section 7.7 of the language spec
+	// that are prefix operators not handled above.
+	case '!', '~':
+		return jsCtxRegexp
+	// Matches all the punctuators from section 7.7 of the language spec
+	// that are open brackets not handled above.
+	case '(', '[':
+		return jsCtxRegexp
+	// Matches all the punctuators from section 7.7 of the language spec
+	// that precede expression starts.
+	case ':', ';', '{':
+		return jsCtxRegexp
+	// CAVEAT: the close punctuators ('}', ']', ')') precede div ops and
+	// are handled in the default except for '}' which can precede a
+	// division op as in
+	//    ({ valueOf: function () { return 42 } } / 2
+	// which is valid, but, in practice, developers don't divide object
+	// literals, so our heuristic works well for code like
+	//    function () { ... }  /foo/.test(x) && sideEffect();
+	// The ')' punctuator can precede a regular expression as in
+	//     if (b) /foo/.test(x) && ...
+	// but this is much less likely than
+	//     (a + b) / c
+	case '}':
+		return jsCtxRegexp
+	default:
+		// Look for an IdentifierName and see if it is a keyword that
+		// can precede a regular expression.
+		j := n
+		for j > 0 && isJSIdentPart(rune(s[j-1])) {
+			j--
+		}
+		if regexpPrecederKeywords[string(s[j:])] {
+			return jsCtxRegexp
+		}
+	}
+	// Otherwise is a punctuator not listed above, or
+	// a string which precedes a div op, or an identifier
+	// which precedes a div op.
+	return jsCtxDivOp
+}
+
+// regexpPrecederKeywords is a set of reserved JS keywords that can precede a
+// regular expression in JS source.
+var regexpPrecederKeywords = map[string]bool{
+	"break":      true,
+	"case":       true,
+	"continue":   true,
+	"delete":     true,
+	"do":         true,
+	"else":       true,
+	"finally":    true,
+	"in":         true,
+	"instanceof": true,
+	"return":     true,
+	"throw":      true,
+	"try":        true,
+	"typeof":     true,
+	"void":       true,
+}
+
+var jsonMarshalType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
+
+// indirectToJSONMarshaler returns the value, after dereferencing as many times
+// as necessary to reach the base type (or nil) or an implementation of json.Marshal.
+func indirectToJSONMarshaler(a interface{}) interface{} {
+	v := reflect.ValueOf(a)
+	for !v.Type().Implements(jsonMarshalType) && v.Kind() == reflect.Ptr && !v.IsNil() {
+		v = v.Elem()
+	}
+	return v.Interface()
+}
+
+// jsValEscaper escapes its inputs to a JS Expression (section 11.14) that has
+// neither side-effects nor free variables outside (NaN, Infinity).
+func jsValEscaper(args ...interface{}) string {
+	var a interface{}
+	if len(args) == 1 {
+		a = indirectToJSONMarshaler(args[0])
+		switch t := a.(type) {
+		case JS:
+			return string(t)
+		case JSStr:
+			// TODO: normalize quotes.
+			return `"` + string(t) + `"`
+		case json.Marshaler:
+			// Do not treat as a Stringer.
+		case fmt.Stringer:
+			a = t.String()
+		}
+	} else {
+		for i, arg := range args {
+			args[i] = indirectToJSONMarshaler(arg)
+		}
+		a = fmt.Sprint(args...)
+	}
+	// TODO: detect cycles before calling Marshal which loops infinitely on
+	// cyclic data. This may be an unacceptable DoS risk.
+
+	b, err := json.Marshal(a)
+	if err != nil {
+		// Put a space before comment so that if it is flush against
+		// a division operator it is not turned into a line comment:
+		//     x/{{y}}
+		// turning into
+		//     x//* error marshalling y:
+		//          second line of error message */null
+		return fmt.Sprintf(" /* %s */null ", strings.Replace(err.Error(), "*/", "* /", -1))
+	}
+
+	// TODO: maybe post-process output to prevent it from containing
+	// "<!--", "-->", "<![CDATA[", "]]>", or "</script"
+	// in case custom marshallers produce output containing those.
+
+	// TODO: Maybe abbreviate \u00ab to \xab to produce more compact output.
+	if len(b) == 0 {
+		// In, `x=y/{{.}}*z` a json.Marshaler that produces "" should
+		// not cause the output `x=y/*z`.
+		return " null "
+	}
+	first, _ := utf8.DecodeRune(b)
+	last, _ := utf8.DecodeLastRune(b)
+	var buf bytes.Buffer
+	// Prevent IdentifierNames and NumericLiterals from running into
+	// keywords: in, instanceof, typeof, void
+	pad := isJSIdentPart(first) || isJSIdentPart(last)
+	if pad {
+		buf.WriteByte(' ')
+	}
+	written := 0
+	// Make sure that json.Marshal escapes codepoints U+2028 & U+2029
+	// so it falls within the subset of JSON which is valid JS.
+	for i := 0; i < len(b); {
+		rune, n := utf8.DecodeRune(b[i:])
+		repl := ""
+		if rune == 0x2028 {
+			repl = `\u2028`
+		} else if rune == 0x2029 {
+			repl = `\u2029`
+		}
+		if repl != "" {
+			buf.Write(b[written:i])
+			buf.WriteString(repl)
+			written = i + n
+		}
+		i += n
+	}
+	if buf.Len() != 0 {
+		buf.Write(b[written:])
+		if pad {
+			buf.WriteByte(' ')
+		}
+		b = buf.Bytes()
+	}
+	return string(b)
+}
+
+// jsStrEscaper produces a string that can be included between quotes in
+// JavaScript source, in JavaScript embedded in an HTML5 <script> element,
+// or in an HTML5 event handler attribute such as onclick.
+func jsStrEscaper(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeJSStr {
+		return replace(s, jsStrNormReplacementTable)
+	}
+	return replace(s, jsStrReplacementTable)
+}
+
+// jsRegexpEscaper behaves like jsStrEscaper but escapes regular expression
+// specials so the result is treated literally when included in a regular
+// expression literal. /foo{{.X}}bar/ matches the string "foo" followed by
+// the literal text of {{.X}} followed by the string "bar".
+func jsRegexpEscaper(args ...interface{}) string {
+	s, _ := stringify(args...)
+	s = replace(s, jsRegexpReplacementTable)
+	if s == "" {
+		// /{{.X}}/ should not produce a line comment when .X == "".
+		return "(?:)"
+	}
+	return s
+}
+
+// replace replaces each rune r of s with replacementTable[r], provided that
+// r < len(replacementTable). If replacementTable[r] is the empty string then
+// no replacement is made.
+// It also replaces runes U+2028 and U+2029 with the raw strings `\u2028` and
+// `\u2029`.
+func replace(s string, replacementTable []string) string {
+	var b bytes.Buffer
+	written := 0
+	for i, r := range s {
+		var repl string
+		switch {
+		case int(r) < len(replacementTable) && replacementTable[r] != "":
+			repl = replacementTable[r]
+		case r == '\u2028':
+			repl = `\u2028`
+		case r == '\u2029':
+			repl = `\u2029`
+		default:
+			continue
+		}
+		b.WriteString(s[written:i])
+		b.WriteString(repl)
+		written = i + utf8.RuneLen(r)
+	}
+	if written == 0 {
+		return s
+	}
+	b.WriteString(s[written:])
+	return b.String()
+}
+
+var jsStrReplacementTable = []string{
+	0:    `\0`,
+	'\t': `\t`,
+	'\n': `\n`,
+	'\v': `\x0b`, // "\v" == "v" on IE 6.
+	'\f': `\f`,
+	'\r': `\r`,
+	// Encode HTML specials as hex so the output can be embedded
+	// in HTML attributes without further encoding.
+	'"':  `\x22`,
+	'&':  `\x26`,
+	'\'': `\x27`,
+	'+':  `\x2b`,
+	'/':  `\/`,
+	'<':  `\x3c`,
+	'>':  `\x3e`,
+	'\\': `\\`,
+}
+
+// jsStrNormReplacementTable is like jsStrReplacementTable but does not
+// overencode existing escapes since this table has no entry for `\`.
+var jsStrNormReplacementTable = []string{
+	0:    `\0`,
+	'\t': `\t`,
+	'\n': `\n`,
+	'\v': `\x0b`, // "\v" == "v" on IE 6.
+	'\f': `\f`,
+	'\r': `\r`,
+	// Encode HTML specials as hex so the output can be embedded
+	// in HTML attributes without further encoding.
+	'"':  `\x22`,
+	'&':  `\x26`,
+	'\'': `\x27`,
+	'+':  `\x2b`,
+	'/':  `\/`,
+	'<':  `\x3c`,
+	'>':  `\x3e`,
+}
+
+var jsRegexpReplacementTable = []string{
+	0:    `\0`,
+	'\t': `\t`,
+	'\n': `\n`,
+	'\v': `\x0b`, // "\v" == "v" on IE 6.
+	'\f': `\f`,
+	'\r': `\r`,
+	// Encode HTML specials as hex so the output can be embedded
+	// in HTML attributes without further encoding.
+	'"':  `\x22`,
+	'$':  `\$`,
+	'&':  `\x26`,
+	'\'': `\x27`,
+	'(':  `\(`,
+	')':  `\)`,
+	'*':  `\*`,
+	'+':  `\x2b`,
+	'-':  `\-`,
+	'.':  `\.`,
+	'/':  `\/`,
+	'<':  `\x3c`,
+	'>':  `\x3e`,
+	'?':  `\?`,
+	'[':  `\[`,
+	'\\': `\\`,
+	']':  `\]`,
+	'^':  `\^`,
+	'{':  `\{`,
+	'|':  `\|`,
+	'}':  `\}`,
+}
+
+// isJSIdentPart reports whether the given rune is a JS identifier part.
+// It does not handle all the non-Latin letters, joiners, and combining marks,
+// but it does handle every codepoint that can occur in a numeric literal or
+// a keyword.
+func isJSIdentPart(r rune) bool {
+	switch {
+	case r == '$':
+		return true
+	case '0' <= r && r <= '9':
+		return true
+	case 'A' <= r && r <= 'Z':
+		return true
+	case r == '_':
+		return true
+	case 'a' <= r && r <= 'z':
+		return true
+	}
+	return false
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/js_test.go b/third_party/gofrontend/libgo/go/html/template/js_test.go
new file mode 100644
index 0000000..311e1d2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/js_test.go
@@ -0,0 +1,401 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"math"
+	"strings"
+	"testing"
+)
+
+func TestNextJsCtx(t *testing.T) {
+	tests := []struct {
+		jsCtx jsCtx
+		s     string
+	}{
+		// Statement terminators precede regexps.
+		{jsCtxRegexp, ";"},
+		// This is not airtight.
+		//     ({ valueOf: function () { return 1 } } / 2)
+		// is valid JavaScript but in practice, devs do not do this.
+		// A block followed by a statement starting with a RegExp is
+		// much more common:
+		//     while (x) {...} /foo/.test(x) || panic()
+		{jsCtxRegexp, "}"},
+		// But member, call, grouping, and array expression terminators
+		// precede div ops.
+		{jsCtxDivOp, ")"},
+		{jsCtxDivOp, "]"},
+		// At the start of a primary expression, array, or expression
+		// statement, expect a regexp.
+		{jsCtxRegexp, "("},
+		{jsCtxRegexp, "["},
+		{jsCtxRegexp, "{"},
+		// Assignment operators precede regexps as do all exclusively
+		// prefix and binary operators.
+		{jsCtxRegexp, "="},
+		{jsCtxRegexp, "+="},
+		{jsCtxRegexp, "*="},
+		{jsCtxRegexp, "*"},
+		{jsCtxRegexp, "!"},
+		// Whether the + or - is infix or prefix, it cannot precede a
+		// div op.
+		{jsCtxRegexp, "+"},
+		{jsCtxRegexp, "-"},
+		// An incr/decr op precedes a div operator.
+		// This is not airtight. In (g = ++/h/i) a regexp follows a
+		// pre-increment operator, but in practice devs do not try to
+		// increment or decrement regular expressions.
+		// (g++/h/i) where ++ is a postfix operator on g is much more
+		// common.
+		{jsCtxDivOp, "--"},
+		{jsCtxDivOp, "++"},
+		{jsCtxDivOp, "x--"},
+		// When we have many dashes or pluses, then they are grouped
+		// left to right.
+		{jsCtxRegexp, "x---"}, // A postfix -- then a -.
+		// return followed by a slash returns the regexp literal or the
+		// slash starts a regexp literal in an expression statement that
+		// is dead code.
+		{jsCtxRegexp, "return"},
+		{jsCtxRegexp, "return "},
+		{jsCtxRegexp, "return\t"},
+		{jsCtxRegexp, "return\n"},
+		{jsCtxRegexp, "return\u2028"},
+		// Identifiers can be divided and cannot validly be preceded by
+		// a regular expressions. Semicolon insertion cannot happen
+		// between an identifier and a regular expression on a new line
+		// because the one token lookahead for semicolon insertion has
+		// to conclude that it could be a div binary op and treat it as
+		// such.
+		{jsCtxDivOp, "x"},
+		{jsCtxDivOp, "x "},
+		{jsCtxDivOp, "x\t"},
+		{jsCtxDivOp, "x\n"},
+		{jsCtxDivOp, "x\u2028"},
+		{jsCtxDivOp, "preturn"},
+		// Numbers precede div ops.
+		{jsCtxDivOp, "0"},
+		// Dots that are part of a number are div preceders.
+		{jsCtxDivOp, "0."},
+	}
+
+	for _, test := range tests {
+		if nextJSCtx([]byte(test.s), jsCtxRegexp) != test.jsCtx {
+			t.Errorf("want %s got %q", test.jsCtx, test.s)
+		}
+		if nextJSCtx([]byte(test.s), jsCtxDivOp) != test.jsCtx {
+			t.Errorf("want %s got %q", test.jsCtx, test.s)
+		}
+	}
+
+	if nextJSCtx([]byte("   "), jsCtxRegexp) != jsCtxRegexp {
+		t.Error("Blank tokens")
+	}
+
+	if nextJSCtx([]byte("   "), jsCtxDivOp) != jsCtxDivOp {
+		t.Error("Blank tokens")
+	}
+}
+
+func TestJSValEscaper(t *testing.T) {
+	tests := []struct {
+		x  interface{}
+		js string
+	}{
+		{int(42), " 42 "},
+		{uint(42), " 42 "},
+		{int16(42), " 42 "},
+		{uint16(42), " 42 "},
+		{int32(-42), " -42 "},
+		{uint32(42), " 42 "},
+		{int16(-42), " -42 "},
+		{uint16(42), " 42 "},
+		{int64(-42), " -42 "},
+		{uint64(42), " 42 "},
+		{uint64(1) << 53, " 9007199254740992 "},
+		// ulp(1 << 53) > 1 so this loses precision in JS
+		// but it is still a representable integer literal.
+		{uint64(1)<<53 + 1, " 9007199254740993 "},
+		{float32(1.0), " 1 "},
+		{float32(-1.0), " -1 "},
+		{float32(0.5), " 0.5 "},
+		{float32(-0.5), " -0.5 "},
+		{float32(1.0) / float32(256), " 0.00390625 "},
+		{float32(0), " 0 "},
+		{math.Copysign(0, -1), " -0 "},
+		{float64(1.0), " 1 "},
+		{float64(-1.0), " -1 "},
+		{float64(0.5), " 0.5 "},
+		{float64(-0.5), " -0.5 "},
+		{float64(0), " 0 "},
+		{math.Copysign(0, -1), " -0 "},
+		{"", `""`},
+		{"foo", `"foo"`},
+		// Newlines.
+		{"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`},
+		// "\v" == "v" on IE 6 so use "\x0b" instead.
+		{"\t\x0b", `"\u0009\u000b"`},
+		{struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
+		{[]interface{}{}, "[]"},
+		{[]interface{}{42, "foo", nil}, `[42,"foo",null]`},
+		{[]string{"<!--", "</script>", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`},
+		{"<!--", `"\u003c!--"`},
+		{"-->", `"--\u003e"`},
+		{"<![CDATA[", `"\u003c![CDATA["`},
+		{"]]>", `"]]\u003e"`},
+		{"</script", `"\u003c/script"`},
+		{"\U0001D11E", "\"\U0001D11E\""}, // or "\uD834\uDD1E"
+	}
+
+	for _, test := range tests {
+		if js := jsValEscaper(test.x); js != test.js {
+			t.Errorf("%+v: want\n\t%q\ngot\n\t%q", test.x, test.js, js)
+		}
+		// Make sure that escaping corner cases are not broken
+		// by nesting.
+		a := []interface{}{test.x}
+		want := "[" + strings.TrimSpace(test.js) + "]"
+		if js := jsValEscaper(a); js != want {
+			t.Errorf("%+v: want\n\t%q\ngot\n\t%q", a, want, js)
+		}
+	}
+}
+
+func TestJSStrEscaper(t *testing.T) {
+	tests := []struct {
+		x   interface{}
+		esc string
+	}{
+		{"", ``},
+		{"foo", `foo`},
+		{"\u0000", `\0`},
+		{"\t", `\t`},
+		{"\n", `\n`},
+		{"\r", `\r`},
+		{"\u2028", `\u2028`},
+		{"\u2029", `\u2029`},
+		{"\\", `\\`},
+		{"\\n", `\\n`},
+		{"foo\r\nbar", `foo\r\nbar`},
+		// Preserve attribute boundaries.
+		{`"`, `\x22`},
+		{`'`, `\x27`},
+		// Allow embedding in HTML without further escaping.
+		{`&amp;`, `\x26amp;`},
+		// Prevent breaking out of text node and element boundaries.
+		{"</script>", `\x3c\/script\x3e`},
+		{"<![CDATA[", `\x3c![CDATA[`},
+		{"]]>", `]]\x3e`},
+		// http://dev.w3.org/html5/markup/aria/syntax.html#escaping-text-span
+		//   "The text in style, script, title, and textarea elements
+		//   must not have an escaping text span start that is not
+		//   followed by an escaping text span end."
+		// Furthermore, spoofing an escaping text span end could lead
+		// to different interpretation of a </script> sequence otherwise
+		// masked by the escaping text span, and spoofing a start could
+		// allow regular text content to be interpreted as script
+		// allowing script execution via a combination of a JS string
+		// injection followed by an HTML text injection.
+		{"<!--", `\x3c!--`},
+		{"-->", `--\x3e`},
+		// From http://code.google.com/p/doctype/wiki/ArticleUtf7
+		{"+ADw-script+AD4-alert(1)+ADw-/script+AD4-",
+			`\x2bADw-script\x2bAD4-alert(1)\x2bADw-\/script\x2bAD4-`,
+		},
+		// Invalid UTF-8 sequence
+		{"foo\xA0bar", "foo\xA0bar"},
+		// Invalid unicode scalar value.
+		{"foo\xed\xa0\x80bar", "foo\xed\xa0\x80bar"},
+	}
+
+	for _, test := range tests {
+		esc := jsStrEscaper(test.x)
+		if esc != test.esc {
+			t.Errorf("%q: want %q got %q", test.x, test.esc, esc)
+		}
+	}
+}
+
+func TestJSRegexpEscaper(t *testing.T) {
+	tests := []struct {
+		x   interface{}
+		esc string
+	}{
+		{"", `(?:)`},
+		{"foo", `foo`},
+		{"\u0000", `\0`},
+		{"\t", `\t`},
+		{"\n", `\n`},
+		{"\r", `\r`},
+		{"\u2028", `\u2028`},
+		{"\u2029", `\u2029`},
+		{"\\", `\\`},
+		{"\\n", `\\n`},
+		{"foo\r\nbar", `foo\r\nbar`},
+		// Preserve attribute boundaries.
+		{`"`, `\x22`},
+		{`'`, `\x27`},
+		// Allow embedding in HTML without further escaping.
+		{`&amp;`, `\x26amp;`},
+		// Prevent breaking out of text node and element boundaries.
+		{"</script>", `\x3c\/script\x3e`},
+		{"<![CDATA[", `\x3c!\[CDATA\[`},
+		{"]]>", `\]\]\x3e`},
+		// Escaping text spans.
+		{"<!--", `\x3c!\-\-`},
+		{"-->", `\-\-\x3e`},
+		{"*", `\*`},
+		{"+", `\x2b`},
+		{"?", `\?`},
+		{"[](){}", `\[\]\(\)\{\}`},
+		{"$foo|x.y", `\$foo\|x\.y`},
+		{"x^y", `x\^y`},
+	}
+
+	for _, test := range tests {
+		esc := jsRegexpEscaper(test.x)
+		if esc != test.esc {
+			t.Errorf("%q: want %q got %q", test.x, test.esc, esc)
+		}
+	}
+}
+
+func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) {
+	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !"#$%&'()*+,-./` +
+		`0123456789:;<=>?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\]^_` +
+		"`abcdefghijklmno" +
+		"pqrstuvwxyz{|}~\x7f" +
+		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+	tests := []struct {
+		name    string
+		escaper func(...interface{}) string
+		escaped string
+	}{
+		{
+			"jsStrEscaper",
+			jsStrEscaper,
+			"\\0\x01\x02\x03\x04\x05\x06\x07" +
+				"\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
+				"\x10\x11\x12\x13\x14\x15\x16\x17" +
+				"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+				` !\x22#$%\x26\x27()*\x2b,-.\/` +
+				`0123456789:;\x3c=\x3e?` +
+				`@ABCDEFGHIJKLMNO` +
+				`PQRSTUVWXYZ[\\]^_` +
+				"`abcdefghijklmno" +
+				"pqrstuvwxyz{|}~\x7f" +
+				"\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
+		},
+		{
+			"jsRegexpEscaper",
+			jsRegexpEscaper,
+			"\\0\x01\x02\x03\x04\x05\x06\x07" +
+				"\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
+				"\x10\x11\x12\x13\x14\x15\x16\x17" +
+				"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+				` !\x22#\$%\x26\x27\(\)\*\x2b,\-\.\/` +
+				`0123456789:;\x3c=\x3e\?` +
+				`@ABCDEFGHIJKLMNO` +
+				`PQRSTUVWXYZ\[\\\]\^_` +
+				"`abcdefghijklmno" +
+				`pqrstuvwxyz\{\|\}~` + "\u007f" +
+				"\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
+		},
+	}
+
+	for _, test := range tests {
+		if s := test.escaper(input); s != test.escaped {
+			t.Errorf("%s once: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
+			continue
+		}
+
+		// Escape it rune by rune to make sure that any
+		// fast-path checking does not break escaping.
+		var buf bytes.Buffer
+		for _, c := range input {
+			buf.WriteString(test.escaper(string(c)))
+		}
+
+		if s := buf.String(); s != test.escaped {
+			t.Errorf("%s rune-wise: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
+			continue
+		}
+	}
+}
+
+func BenchmarkJSValEscaperWithNum(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsValEscaper(3.141592654)
+	}
+}
+
+func BenchmarkJSValEscaperWithStr(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsValEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
+
+func BenchmarkJSValEscaperWithStrNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsValEscaper("The quick, brown fox jumps over the lazy dog")
+	}
+}
+
+func BenchmarkJSValEscaperWithObj(b *testing.B) {
+	o := struct {
+		S string
+		N int
+	}{
+		"The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>\u2028",
+		42,
+	}
+	for i := 0; i < b.N; i++ {
+		jsValEscaper(o)
+	}
+}
+
+func BenchmarkJSValEscaperWithObjNoSpecials(b *testing.B) {
+	o := struct {
+		S string
+		N int
+	}{
+		"The quick, brown fox jumps over the lazy dog",
+		42,
+	}
+	for i := 0; i < b.N; i++ {
+		jsValEscaper(o)
+	}
+}
+
+func BenchmarkJSStrEscaperNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsStrEscaper("The quick, brown fox jumps over the lazy dog.")
+	}
+}
+
+func BenchmarkJSStrEscaper(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsStrEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
+
+func BenchmarkJSRegexpEscaperNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsRegexpEscaper("The quick, brown fox jumps over the lazy dog")
+	}
+}
+
+func BenchmarkJSRegexpEscaper(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsRegexpEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/template.go b/third_party/gofrontend/libgo/go/html/template/template.go
new file mode 100644
index 0000000..d389658
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/template.go
@@ -0,0 +1,381 @@
+// 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.
+
+package template
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"path/filepath"
+	"sync"
+	"text/template"
+	"text/template/parse"
+)
+
+// Template is a specialized Template from "text/template" that produces a safe
+// HTML document fragment.
+type Template struct {
+	escaped bool
+	// We could embed the text/template field, but it's safer not to because
+	// we need to keep our version of the name space and the underlying
+	// template's in sync.
+	text *template.Template
+	// The underlying template's parse tree, updated to be HTML-safe.
+	Tree       *parse.Tree
+	*nameSpace // common to all associated templates
+}
+
+// nameSpace is the data structure shared by all templates in an association.
+type nameSpace struct {
+	mu  sync.Mutex
+	set map[string]*Template
+}
+
+// Templates returns a slice of the templates associated with t, including t
+// itself.
+func (t *Template) Templates() []*Template {
+	ns := t.nameSpace
+	ns.mu.Lock()
+	defer ns.mu.Unlock()
+	// Return a slice so we don't expose the map.
+	m := make([]*Template, 0, len(ns.set))
+	for _, v := range ns.set {
+		m = append(m, v)
+	}
+	return m
+}
+
+// escape escapes all associated templates.
+func (t *Template) escape() error {
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	if !t.escaped {
+		if err := escapeTemplates(t, t.Name()); err != nil {
+			return err
+		}
+		t.escaped = true
+	}
+	return nil
+}
+
+// Execute applies a parsed template to the specified data object,
+// writing the output to wr.
+// If an error occurs executing the template or writing its output,
+// execution stops, but partial results may already have been written to
+// the output writer.
+// A template may be executed safely in parallel.
+func (t *Template) Execute(wr io.Writer, data interface{}) error {
+	if err := t.escape(); err != nil {
+		return err
+	}
+	return t.text.Execute(wr, data)
+}
+
+// ExecuteTemplate applies the template associated with t that has the given
+// name to the specified data object and writes the output to wr.
+// If an error occurs executing the template or writing its output,
+// execution stops, but partial results may already have been written to
+// the output writer.
+// A template may be executed safely in parallel.
+func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
+	tmpl, err := t.lookupAndEscapeTemplate(name)
+	if err != nil {
+		return err
+	}
+	return tmpl.text.Execute(wr, data)
+}
+
+// lookupAndEscapeTemplate guarantees that the template with the given name
+// is escaped, or returns an error if it cannot be. It returns the named
+// template.
+func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) {
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	tmpl = t.set[name]
+	if tmpl == nil {
+		return nil, fmt.Errorf("html/template: %q is undefined", name)
+	}
+	if tmpl.text.Tree == nil || tmpl.text.Root == nil {
+		return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
+	}
+	if t.text.Lookup(name) == nil {
+		panic("html/template internal error: template escaping out of sync")
+	}
+	if tmpl != nil && !tmpl.escaped {
+		err = escapeTemplates(tmpl, name)
+	}
+	return tmpl, err
+}
+
+// Parse parses a string into a template. Nested template definitions
+// will be associated with the top-level template t. Parse may be
+// called multiple times to parse definitions of templates to associate
+// with t. It is an error if a resulting template is non-empty (contains
+// content other than template definitions) and would replace a
+// non-empty template with the same name.  (In multiple calls to Parse
+// with the same receiver template, only one call can contain text
+// other than space, comments, and template definitions.)
+func (t *Template) Parse(src string) (*Template, error) {
+	t.nameSpace.mu.Lock()
+	t.escaped = false
+	t.nameSpace.mu.Unlock()
+	ret, err := t.text.Parse(src)
+	if err != nil {
+		return nil, err
+	}
+	// In general, all the named templates might have changed underfoot.
+	// Regardless, some new ones may have been defined.
+	// The template.Template set has been updated; update ours.
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	for _, v := range ret.Templates() {
+		name := v.Name()
+		tmpl := t.set[name]
+		if tmpl == nil {
+			tmpl = t.new(name)
+		}
+		// Restore our record of this text/template to its unescaped original state.
+		tmpl.escaped = false
+		tmpl.text = v
+		tmpl.Tree = v.Tree
+	}
+	return t, nil
+}
+
+// AddParseTree creates a new template with the name and parse tree
+// and associates it with t.
+//
+// It returns an error if t has already been executed.
+func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	if t.escaped {
+		return nil, fmt.Errorf("html/template: cannot AddParseTree to %q after it has executed", t.Name())
+	}
+	text, err := t.text.AddParseTree(name, tree)
+	if err != nil {
+		return nil, err
+	}
+	ret := &Template{
+		false,
+		text,
+		text.Tree,
+		t.nameSpace,
+	}
+	t.set[name] = ret
+	return ret, nil
+}
+
+// Clone returns a duplicate of the template, including all associated
+// templates. The actual representation is not copied, but the name space of
+// associated templates is, so further calls to Parse in the copy will add
+// templates to the copy but not to the original. Clone can be used to prepare
+// common templates and use them with variant definitions for other templates
+// by adding the variants after the clone is made.
+//
+// It returns an error if t has already been executed.
+func (t *Template) Clone() (*Template, error) {
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	if t.escaped {
+		return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
+	}
+	textClone, err := t.text.Clone()
+	if err != nil {
+		return nil, err
+	}
+	ret := &Template{
+		false,
+		textClone,
+		textClone.Tree,
+		&nameSpace{
+			set: make(map[string]*Template),
+		},
+	}
+	for _, x := range textClone.Templates() {
+		name := x.Name()
+		src := t.set[name]
+		if src == nil || src.escaped {
+			return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
+		}
+		x.Tree = x.Tree.Copy()
+		ret.set[name] = &Template{
+			false,
+			x,
+			x.Tree,
+			ret.nameSpace,
+		}
+	}
+	return ret, nil
+}
+
+// New allocates a new HTML template with the given name.
+func New(name string) *Template {
+	tmpl := &Template{
+		false,
+		template.New(name),
+		nil,
+		&nameSpace{
+			set: make(map[string]*Template),
+		},
+	}
+	tmpl.set[name] = tmpl
+	return tmpl
+}
+
+// New allocates a new HTML template associated with the given one
+// and with the same delimiters. The association, which is transitive,
+// allows one template to invoke another with a {{template}} action.
+func (t *Template) New(name string) *Template {
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	return t.new(name)
+}
+
+// new is the implementation of New, without the lock.
+func (t *Template) new(name string) *Template {
+	tmpl := &Template{
+		false,
+		t.text.New(name),
+		nil,
+		t.nameSpace,
+	}
+	tmpl.set[name] = tmpl
+	return tmpl
+}
+
+// Name returns the name of the template.
+func (t *Template) Name() string {
+	return t.text.Name()
+}
+
+// FuncMap is the type of the map defining the mapping from names to
+// functions. Each function must have either a single return value, or two
+// return values of which the second has type error. In that case, if the
+// second (error) argument evaluates to non-nil during execution, execution
+// terminates and Execute returns that error. FuncMap has the same base type
+// as FuncMap in "text/template", copied here so clients need not import
+// "text/template".
+type FuncMap map[string]interface{}
+
+// Funcs adds the elements of the argument map to the template's function map.
+// It panics if a value in the map is not a function with appropriate return
+// type. However, it is legal to overwrite elements of the map. The return
+// value is the template, so calls can be chained.
+func (t *Template) Funcs(funcMap FuncMap) *Template {
+	t.text.Funcs(template.FuncMap(funcMap))
+	return t
+}
+
+// Delims sets the action delimiters to the specified strings, to be used in
+// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
+// definitions will inherit the settings. An empty delimiter stands for the
+// corresponding default: {{ or }}.
+// The return value is the template, so calls can be chained.
+func (t *Template) Delims(left, right string) *Template {
+	t.text.Delims(left, right)
+	return t
+}
+
+// Lookup returns the template with the given name that is associated with t,
+// or nil if there is no such template.
+func (t *Template) Lookup(name string) *Template {
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	return t.set[name]
+}
+
+// Must is a helper that wraps a call to a function returning (*Template, error)
+// and panics if the error is non-nil. It is intended for use in variable initializations
+// such as
+//	var t = template.Must(template.New("name").Parse("html"))
+func Must(t *Template, err error) *Template {
+	if err != nil {
+		panic(err)
+	}
+	return t
+}
+
+// ParseFiles creates a new Template and parses the template definitions from
+// the named files. The returned template's name will have the (base) name and
+// (parsed) contents of the first file. There must be at least one file.
+// If an error occurs, parsing stops and the returned *Template is nil.
+func ParseFiles(filenames ...string) (*Template, error) {
+	return parseFiles(nil, filenames...)
+}
+
+// ParseFiles parses the named files and associates the resulting templates with
+// t. If an error occurs, parsing stops and the returned template is nil;
+// otherwise it is t. There must be at least one file.
+func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
+	return parseFiles(t, filenames...)
+}
+
+// parseFiles is the helper for the method and function. If the argument
+// template is nil, it is created from the first file.
+func parseFiles(t *Template, filenames ...string) (*Template, error) {
+	if len(filenames) == 0 {
+		// Not really a problem, but be consistent.
+		return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
+	}
+	for _, filename := range filenames {
+		b, err := ioutil.ReadFile(filename)
+		if err != nil {
+			return nil, err
+		}
+		s := string(b)
+		name := filepath.Base(filename)
+		// First template becomes return value if not already defined,
+		// and we use that one for subsequent New calls to associate
+		// all the templates together. Also, if this file has the same name
+		// as t, this file becomes the contents of t, so
+		//  t, err := New(name).Funcs(xxx).ParseFiles(name)
+		// works. Otherwise we create a new template associated with t.
+		var tmpl *Template
+		if t == nil {
+			t = New(name)
+		}
+		if name == t.Name() {
+			tmpl = t
+		} else {
+			tmpl = t.New(name)
+		}
+		_, err = tmpl.Parse(s)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return t, nil
+}
+
+// ParseGlob creates a new Template and parses the template definitions from the
+// files identified by the pattern, which must match at least one file. The
+// returned template will have the (base) name and (parsed) contents of the
+// first file matched by the pattern. ParseGlob is equivalent to calling
+// ParseFiles with the list of files matched by the pattern.
+func ParseGlob(pattern string) (*Template, error) {
+	return parseGlob(nil, pattern)
+}
+
+// ParseGlob parses the template definitions in the files identified by the
+// pattern and associates the resulting templates with t. The pattern is
+// processed by filepath.Glob and must match at least one file. ParseGlob is
+// equivalent to calling t.ParseFiles with the list of files matched by the
+// pattern.
+func (t *Template) ParseGlob(pattern string) (*Template, error) {
+	return parseGlob(t, pattern)
+}
+
+// parseGlob is the implementation of the function and method ParseGlob.
+func parseGlob(t *Template, pattern string) (*Template, error) {
+	filenames, err := filepath.Glob(pattern)
+	if err != nil {
+		return nil, err
+	}
+	if len(filenames) == 0 {
+		return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern)
+	}
+	return parseFiles(t, filenames...)
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/transition.go b/third_party/gofrontend/libgo/go/html/template/transition.go
new file mode 100644
index 0000000..7f30a7a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/transition.go
@@ -0,0 +1,550 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"strings"
+)
+
+// transitionFunc is the array of context transition functions for text nodes.
+// A transition function takes a context and template text input, and returns
+// the updated context and the number of bytes consumed from the front of the
+// input.
+var transitionFunc = [...]func(context, []byte) (context, int){
+	stateText:        tText,
+	stateTag:         tTag,
+	stateAttrName:    tAttrName,
+	stateAfterName:   tAfterName,
+	stateBeforeValue: tBeforeValue,
+	stateHTMLCmt:     tHTMLCmt,
+	stateRCDATA:      tSpecialTagEnd,
+	stateAttr:        tAttr,
+	stateURL:         tURL,
+	stateJS:          tJS,
+	stateJSDqStr:     tJSDelimited,
+	stateJSSqStr:     tJSDelimited,
+	stateJSRegexp:    tJSDelimited,
+	stateJSBlockCmt:  tBlockCmt,
+	stateJSLineCmt:   tLineCmt,
+	stateCSS:         tCSS,
+	stateCSSDqStr:    tCSSStr,
+	stateCSSSqStr:    tCSSStr,
+	stateCSSDqURL:    tCSSStr,
+	stateCSSSqURL:    tCSSStr,
+	stateCSSURL:      tCSSStr,
+	stateCSSBlockCmt: tBlockCmt,
+	stateCSSLineCmt:  tLineCmt,
+	stateError:       tError,
+}
+
+var commentStart = []byte("<!--")
+var commentEnd = []byte("-->")
+
+// tText is the context transition function for the text state.
+func tText(c context, s []byte) (context, int) {
+	k := 0
+	for {
+		i := k + bytes.IndexByte(s[k:], '<')
+		if i < k || i+1 == len(s) {
+			return c, len(s)
+		} else if i+4 <= len(s) && bytes.Equal(commentStart, s[i:i+4]) {
+			return context{state: stateHTMLCmt}, i + 4
+		}
+		i++
+		end := false
+		if s[i] == '/' {
+			if i+1 == len(s) {
+				return c, len(s)
+			}
+			end, i = true, i+1
+		}
+		j, e := eatTagName(s, i)
+		if j != i {
+			if end {
+				e = elementNone
+			}
+			// We've found an HTML tag.
+			return context{state: stateTag, element: e}, j
+		}
+		k = j
+	}
+}
+
+var elementContentType = [...]state{
+	elementNone:     stateText,
+	elementScript:   stateJS,
+	elementStyle:    stateCSS,
+	elementTextarea: stateRCDATA,
+	elementTitle:    stateRCDATA,
+}
+
+// tTag is the context transition function for the tag state.
+func tTag(c context, s []byte) (context, int) {
+	// Find the attribute name.
+	i := eatWhiteSpace(s, 0)
+	if i == len(s) {
+		return c, len(s)
+	}
+	if s[i] == '>' {
+		return context{
+			state:   elementContentType[c.element],
+			element: c.element,
+		}, i + 1
+	}
+	j, err := eatAttrName(s, i)
+	if err != nil {
+		return context{state: stateError, err: err}, len(s)
+	}
+	state, attr := stateTag, attrNone
+	if i == j {
+		return context{
+			state: stateError,
+			err:   errorf(ErrBadHTML, 0, "expected space, attr name, or end of tag, but got %q", s[i:]),
+		}, len(s)
+	}
+	switch attrType(string(s[i:j])) {
+	case contentTypeURL:
+		attr = attrURL
+	case contentTypeCSS:
+		attr = attrStyle
+	case contentTypeJS:
+		attr = attrScript
+	}
+	if j == len(s) {
+		state = stateAttrName
+	} else {
+		state = stateAfterName
+	}
+	return context{state: state, element: c.element, attr: attr}, j
+}
+
+// tAttrName is the context transition function for stateAttrName.
+func tAttrName(c context, s []byte) (context, int) {
+	i, err := eatAttrName(s, 0)
+	if err != nil {
+		return context{state: stateError, err: err}, len(s)
+	} else if i != len(s) {
+		c.state = stateAfterName
+	}
+	return c, i
+}
+
+// tAfterName is the context transition function for stateAfterName.
+func tAfterName(c context, s []byte) (context, int) {
+	// Look for the start of the value.
+	i := eatWhiteSpace(s, 0)
+	if i == len(s) {
+		return c, len(s)
+	} else if s[i] != '=' {
+		// Occurs due to tag ending '>', and valueless attribute.
+		c.state = stateTag
+		return c, i
+	}
+	c.state = stateBeforeValue
+	// Consume the "=".
+	return c, i + 1
+}
+
+var attrStartStates = [...]state{
+	attrNone:   stateAttr,
+	attrScript: stateJS,
+	attrStyle:  stateCSS,
+	attrURL:    stateURL,
+}
+
+// tBeforeValue is the context transition function for stateBeforeValue.
+func tBeforeValue(c context, s []byte) (context, int) {
+	i := eatWhiteSpace(s, 0)
+	if i == len(s) {
+		return c, len(s)
+	}
+	// Find the attribute delimiter.
+	delim := delimSpaceOrTagEnd
+	switch s[i] {
+	case '\'':
+		delim, i = delimSingleQuote, i+1
+	case '"':
+		delim, i = delimDoubleQuote, i+1
+	}
+	c.state, c.delim, c.attr = attrStartStates[c.attr], delim, attrNone
+	return c, i
+}
+
+// tHTMLCmt is the context transition function for stateHTMLCmt.
+func tHTMLCmt(c context, s []byte) (context, int) {
+	if i := bytes.Index(s, commentEnd); i != -1 {
+		return context{}, i + 3
+	}
+	return c, len(s)
+}
+
+// specialTagEndMarkers maps element types to the character sequence that
+// case-insensitively signals the end of the special tag body.
+var specialTagEndMarkers = [...]string{
+	elementScript:   "</script",
+	elementStyle:    "</style",
+	elementTextarea: "</textarea",
+	elementTitle:    "</title",
+}
+
+// tSpecialTagEnd is the context transition function for raw text and RCDATA
+// element states.
+func tSpecialTagEnd(c context, s []byte) (context, int) {
+	if c.element != elementNone {
+		if i := strings.Index(strings.ToLower(string(s)), specialTagEndMarkers[c.element]); i != -1 {
+			return context{}, i
+		}
+	}
+	return c, len(s)
+}
+
+// tAttr is the context transition function for the attribute state.
+func tAttr(c context, s []byte) (context, int) {
+	return c, len(s)
+}
+
+// tURL is the context transition function for the URL state.
+func tURL(c context, s []byte) (context, int) {
+	if bytes.IndexAny(s, "#?") >= 0 {
+		c.urlPart = urlPartQueryOrFrag
+	} else if len(s) != eatWhiteSpace(s, 0) && c.urlPart == urlPartNone {
+		// HTML5 uses "Valid URL potentially surrounded by spaces" for
+		// attrs: http://www.w3.org/TR/html5/index.html#attributes-1
+		c.urlPart = urlPartPreQuery
+	}
+	return c, len(s)
+}
+
+// tJS is the context transition function for the JS state.
+func tJS(c context, s []byte) (context, int) {
+	i := bytes.IndexAny(s, `"'/`)
+	if i == -1 {
+		// Entire input is non string, comment, regexp tokens.
+		c.jsCtx = nextJSCtx(s, c.jsCtx)
+		return c, len(s)
+	}
+	c.jsCtx = nextJSCtx(s[:i], c.jsCtx)
+	switch s[i] {
+	case '"':
+		c.state, c.jsCtx = stateJSDqStr, jsCtxRegexp
+	case '\'':
+		c.state, c.jsCtx = stateJSSqStr, jsCtxRegexp
+	case '/':
+		switch {
+		case i+1 < len(s) && s[i+1] == '/':
+			c.state, i = stateJSLineCmt, i+1
+		case i+1 < len(s) && s[i+1] == '*':
+			c.state, i = stateJSBlockCmt, i+1
+		case c.jsCtx == jsCtxRegexp:
+			c.state = stateJSRegexp
+		case c.jsCtx == jsCtxDivOp:
+			c.jsCtx = jsCtxRegexp
+		default:
+			return context{
+				state: stateError,
+				err:   errorf(ErrSlashAmbig, 0, "'/' could start a division or regexp: %.32q", s[i:]),
+			}, len(s)
+		}
+	default:
+		panic("unreachable")
+	}
+	return c, i + 1
+}
+
+// tJSDelimited is the context transition function for the JS string and regexp
+// states.
+func tJSDelimited(c context, s []byte) (context, int) {
+	specials := `\"`
+	switch c.state {
+	case stateJSSqStr:
+		specials = `\'`
+	case stateJSRegexp:
+		specials = `\/[]`
+	}
+
+	k, inCharset := 0, false
+	for {
+		i := k + bytes.IndexAny(s[k:], specials)
+		if i < k {
+			break
+		}
+		switch s[i] {
+		case '\\':
+			i++
+			if i == len(s) {
+				return context{
+					state: stateError,
+					err:   errorf(ErrPartialEscape, 0, "unfinished escape sequence in JS string: %q", s),
+				}, len(s)
+			}
+		case '[':
+			inCharset = true
+		case ']':
+			inCharset = false
+		default:
+			// end delimiter
+			if !inCharset {
+				c.state, c.jsCtx = stateJS, jsCtxDivOp
+				return c, i + 1
+			}
+		}
+		k = i + 1
+	}
+
+	if inCharset {
+		// This can be fixed by making context richer if interpolation
+		// into charsets is desired.
+		return context{
+			state: stateError,
+			err:   errorf(ErrPartialCharset, 0, "unfinished JS regexp charset: %q", s),
+		}, len(s)
+	}
+
+	return c, len(s)
+}
+
+var blockCommentEnd = []byte("*/")
+
+// tBlockCmt is the context transition function for /*comment*/ states.
+func tBlockCmt(c context, s []byte) (context, int) {
+	i := bytes.Index(s, blockCommentEnd)
+	if i == -1 {
+		return c, len(s)
+	}
+	switch c.state {
+	case stateJSBlockCmt:
+		c.state = stateJS
+	case stateCSSBlockCmt:
+		c.state = stateCSS
+	default:
+		panic(c.state.String())
+	}
+	return c, i + 2
+}
+
+// tLineCmt is the context transition function for //comment states.
+func tLineCmt(c context, s []byte) (context, int) {
+	var lineTerminators string
+	var endState state
+	switch c.state {
+	case stateJSLineCmt:
+		lineTerminators, endState = "\n\r\u2028\u2029", stateJS
+	case stateCSSLineCmt:
+		lineTerminators, endState = "\n\f\r", stateCSS
+		// Line comments are not part of any published CSS standard but
+		// are supported by the 4 major browsers.
+		// This defines line comments as
+		//     LINECOMMENT ::= "//" [^\n\f\d]*
+		// since http://www.w3.org/TR/css3-syntax/#SUBTOK-nl defines
+		// newlines:
+		//     nl ::= #xA | #xD #xA | #xD | #xC
+	default:
+		panic(c.state.String())
+	}
+
+	i := bytes.IndexAny(s, lineTerminators)
+	if i == -1 {
+		return c, len(s)
+	}
+	c.state = endState
+	// Per section 7.4 of EcmaScript 5 : http://es5.github.com/#x7.4
+	// "However, the LineTerminator at the end of the line is not
+	// considered to be part of the single-line comment; it is
+	// recognized separately by the lexical grammar and becomes part
+	// of the stream of input elements for the syntactic grammar."
+	return c, i
+}
+
+// tCSS is the context transition function for the CSS state.
+func tCSS(c context, s []byte) (context, int) {
+	// CSS quoted strings are almost never used except for:
+	// (1) URLs as in background: "/foo.png"
+	// (2) Multiword font-names as in font-family: "Times New Roman"
+	// (3) List separators in content values as in inline-lists:
+	//    <style>
+	//    ul.inlineList { list-style: none; padding:0 }
+	//    ul.inlineList > li { display: inline }
+	//    ul.inlineList > li:before { content: ", " }
+	//    ul.inlineList > li:first-child:before { content: "" }
+	//    </style>
+	//    <ul class=inlineList><li>One<li>Two<li>Three</ul>
+	// (4) Attribute value selectors as in a[href="http://example.com/"]
+	//
+	// We conservatively treat all strings as URLs, but make some
+	// allowances to avoid confusion.
+	//
+	// In (1), our conservative assumption is justified.
+	// In (2), valid font names do not contain ':', '?', or '#', so our
+	// conservative assumption is fine since we will never transition past
+	// urlPartPreQuery.
+	// In (3), our protocol heuristic should not be tripped, and there
+	// should not be non-space content after a '?' or '#', so as long as
+	// we only %-encode RFC 3986 reserved characters we are ok.
+	// In (4), we should URL escape for URL attributes, and for others we
+	// have the attribute name available if our conservative assumption
+	// proves problematic for real code.
+
+	k := 0
+	for {
+		i := k + bytes.IndexAny(s[k:], `("'/`)
+		if i < k {
+			return c, len(s)
+		}
+		switch s[i] {
+		case '(':
+			// Look for url to the left.
+			p := bytes.TrimRight(s[:i], "\t\n\f\r ")
+			if endsWithCSSKeyword(p, "url") {
+				j := len(s) - len(bytes.TrimLeft(s[i+1:], "\t\n\f\r "))
+				switch {
+				case j != len(s) && s[j] == '"':
+					c.state, j = stateCSSDqURL, j+1
+				case j != len(s) && s[j] == '\'':
+					c.state, j = stateCSSSqURL, j+1
+				default:
+					c.state = stateCSSURL
+				}
+				return c, j
+			}
+		case '/':
+			if i+1 < len(s) {
+				switch s[i+1] {
+				case '/':
+					c.state = stateCSSLineCmt
+					return c, i + 2
+				case '*':
+					c.state = stateCSSBlockCmt
+					return c, i + 2
+				}
+			}
+		case '"':
+			c.state = stateCSSDqStr
+			return c, i + 1
+		case '\'':
+			c.state = stateCSSSqStr
+			return c, i + 1
+		}
+		k = i + 1
+	}
+}
+
+// tCSSStr is the context transition function for the CSS string and URL states.
+func tCSSStr(c context, s []byte) (context, int) {
+	var endAndEsc string
+	switch c.state {
+	case stateCSSDqStr, stateCSSDqURL:
+		endAndEsc = `\"`
+	case stateCSSSqStr, stateCSSSqURL:
+		endAndEsc = `\'`
+	case stateCSSURL:
+		// Unquoted URLs end with a newline or close parenthesis.
+		// The below includes the wc (whitespace character) and nl.
+		endAndEsc = "\\\t\n\f\r )"
+	default:
+		panic(c.state.String())
+	}
+
+	k := 0
+	for {
+		i := k + bytes.IndexAny(s[k:], endAndEsc)
+		if i < k {
+			c, nread := tURL(c, decodeCSS(s[k:]))
+			return c, k + nread
+		}
+		if s[i] == '\\' {
+			i++
+			if i == len(s) {
+				return context{
+					state: stateError,
+					err:   errorf(ErrPartialEscape, 0, "unfinished escape sequence in CSS string: %q", s),
+				}, len(s)
+			}
+		} else {
+			c.state = stateCSS
+			return c, i + 1
+		}
+		c, _ = tURL(c, decodeCSS(s[:i+1]))
+		k = i + 1
+	}
+}
+
+// tError is the context transition function for the error state.
+func tError(c context, s []byte) (context, int) {
+	return c, len(s)
+}
+
+// eatAttrName returns the largest j such that s[i:j] is an attribute name.
+// It returns an error if s[i:] does not look like it begins with an
+// attribute name, such as encountering a quote mark without a preceding
+// equals sign.
+func eatAttrName(s []byte, i int) (int, *Error) {
+	for j := i; j < len(s); j++ {
+		switch s[j] {
+		case ' ', '\t', '\n', '\f', '\r', '=', '>':
+			return j, nil
+		case '\'', '"', '<':
+			// These result in a parse warning in HTML5 and are
+			// indicative of serious problems if seen in an attr
+			// name in a template.
+			return -1, errorf(ErrBadHTML, 0, "%q in attribute name: %.32q", s[j:j+1], s)
+		default:
+			// No-op.
+		}
+	}
+	return len(s), nil
+}
+
+var elementNameMap = map[string]element{
+	"script":   elementScript,
+	"style":    elementStyle,
+	"textarea": elementTextarea,
+	"title":    elementTitle,
+}
+
+// asciiAlpha reports whether c is an ASCII letter.
+func asciiAlpha(c byte) bool {
+	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
+}
+
+// asciiAlphaNum reports whether c is an ASCII letter or digit.
+func asciiAlphaNum(c byte) bool {
+	return asciiAlpha(c) || '0' <= c && c <= '9'
+}
+
+// eatTagName returns the largest j such that s[i:j] is a tag name and the tag type.
+func eatTagName(s []byte, i int) (int, element) {
+	if i == len(s) || !asciiAlpha(s[i]) {
+		return i, elementNone
+	}
+	j := i + 1
+	for j < len(s) {
+		x := s[j]
+		if asciiAlphaNum(x) {
+			j++
+			continue
+		}
+		// Allow "x-y" or "x:y" but not "x-", "-y", or "x--y".
+		if (x == ':' || x == '-') && j+1 < len(s) && asciiAlphaNum(s[j+1]) {
+			j += 2
+			continue
+		}
+		break
+	}
+	return j, elementNameMap[strings.ToLower(string(s[i:j]))]
+}
+
+// eatWhiteSpace returns the largest j such that s[i:j] is white space.
+func eatWhiteSpace(s []byte, i int) int {
+	for j := i; j < len(s); j++ {
+		switch s[j] {
+		case ' ', '\t', '\n', '\f', '\r':
+			// No-op.
+		default:
+			return j
+		}
+	}
+	return len(s)
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/url.go b/third_party/gofrontend/libgo/go/html/template/url.go
new file mode 100644
index 0000000..2ca76bf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/url.go
@@ -0,0 +1,105 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+)
+
+// urlFilter returns its input unless it contains an unsafe protocol in which
+// case it defangs the entire URL.
+func urlFilter(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeURL {
+		return s
+	}
+	if i := strings.IndexRune(s, ':'); i >= 0 && strings.IndexRune(s[:i], '/') < 0 {
+		protocol := strings.ToLower(s[:i])
+		if protocol != "http" && protocol != "https" && protocol != "mailto" {
+			return "#" + filterFailsafe
+		}
+	}
+	return s
+}
+
+// urlEscaper produces an output that can be embedded in a URL query.
+// The output can be embedded in an HTML attribute without further escaping.
+func urlEscaper(args ...interface{}) string {
+	return urlProcessor(false, args...)
+}
+
+// urlEscaper normalizes URL content so it can be embedded in a quote-delimited
+// string or parenthesis delimited url(...).
+// The normalizer does not encode all HTML specials. Specifically, it does not
+// encode '&' so correct embedding in an HTML attribute requires escaping of
+// '&' to '&amp;'.
+func urlNormalizer(args ...interface{}) string {
+	return urlProcessor(true, args...)
+}
+
+// urlProcessor normalizes (when norm is true) or escapes its input to produce
+// a valid hierarchical or opaque URL part.
+func urlProcessor(norm bool, args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeURL {
+		norm = true
+	}
+	var b bytes.Buffer
+	written := 0
+	// The byte loop below assumes that all URLs use UTF-8 as the
+	// content-encoding. This is similar to the URI to IRI encoding scheme
+	// defined in section 3.1 of  RFC 3987, and behaves the same as the
+	// EcmaScript builtin encodeURIComponent.
+	// It should not cause any misencoding of URLs in pages with
+	// Content-type: text/html;charset=UTF-8.
+	for i, n := 0, len(s); i < n; i++ {
+		c := s[i]
+		switch c {
+		// Single quote and parens are sub-delims in RFC 3986, but we
+		// escape them so the output can be embedded in single
+		// quoted attributes and unquoted CSS url(...) constructs.
+		// Single quotes are reserved in URLs, but are only used in
+		// the obsolete "mark" rule in an appendix in RFC 3986
+		// so can be safely encoded.
+		case '!', '#', '$', '&', '*', '+', ',', '/', ':', ';', '=', '?', '@', '[', ']':
+			if norm {
+				continue
+			}
+		// Unreserved according to RFC 3986 sec 2.3
+		// "For consistency, percent-encoded octets in the ranges of
+		// ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D),
+		// period (%2E), underscore (%5F), or tilde (%7E) should not be
+		// created by URI producers
+		case '-', '.', '_', '~':
+			continue
+		case '%':
+			// When normalizing do not re-encode valid escapes.
+			if norm && i+2 < len(s) && isHex(s[i+1]) && isHex(s[i+2]) {
+				continue
+			}
+		default:
+			// Unreserved according to RFC 3986 sec 2.3
+			if 'a' <= c && c <= 'z' {
+				continue
+			}
+			if 'A' <= c && c <= 'Z' {
+				continue
+			}
+			if '0' <= c && c <= '9' {
+				continue
+			}
+		}
+		b.WriteString(s[written:i])
+		fmt.Fprintf(&b, "%%%02x", c)
+		written = i + 1
+	}
+	if written == 0 {
+		return s
+	}
+	b.WriteString(s[written:])
+	return b.String()
+}
diff --git a/third_party/gofrontend/libgo/go/html/template/url_test.go b/third_party/gofrontend/libgo/go/html/template/url_test.go
new file mode 100644
index 0000000..5182e9d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/html/template/url_test.go
@@ -0,0 +1,112 @@
+// 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.
+
+package template
+
+import (
+	"testing"
+)
+
+func TestURLNormalizer(t *testing.T) {
+	tests := []struct {
+		url, want string
+	}{
+		{"", ""},
+		{
+			"http://example.com:80/foo/bar?q=foo%20&bar=x+y#frag",
+			"http://example.com:80/foo/bar?q=foo%20&bar=x+y#frag",
+		},
+		{" ", "%20"},
+		{"%7c", "%7c"},
+		{"%7C", "%7C"},
+		{"%2", "%252"},
+		{"%", "%25"},
+		{"%z", "%25z"},
+		{"/foo|bar/%5c\u1234", "/foo%7cbar/%5c%e1%88%b4"},
+	}
+	for _, test := range tests {
+		if got := urlNormalizer(test.url); test.want != got {
+			t.Errorf("%q: want\n\t%q\nbut got\n\t%q", test.url, test.want, got)
+		}
+		if test.want != urlNormalizer(test.want) {
+			t.Errorf("not idempotent: %q", test.want)
+		}
+	}
+}
+
+func TestURLFilters(t *testing.T) {
+	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !"#$%&'()*+,-./` +
+		`0123456789:;<=>?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\]^_` +
+		"`abcdefghijklmno" +
+		"pqrstuvwxyz{|}~\x7f" +
+		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+	tests := []struct {
+		name    string
+		escaper func(...interface{}) string
+		escaped string
+	}{
+		{
+			"urlEscaper",
+			urlEscaper,
+			"%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f" +
+				"%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f" +
+				"%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f" +
+				"0123456789%3a%3b%3c%3d%3e%3f" +
+				"%40ABCDEFGHIJKLMNO" +
+				"PQRSTUVWXYZ%5b%5c%5d%5e_" +
+				"%60abcdefghijklmno" +
+				"pqrstuvwxyz%7b%7c%7d~%7f" +
+				"%c2%a0%c4%80%e2%80%a8%e2%80%a9%ef%bb%bf%f0%9d%84%9e",
+		},
+		{
+			"urlNormalizer",
+			urlNormalizer,
+			"%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f" +
+				"%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f" +
+				"%20!%22#$%25&%27%28%29*+,-./" +
+				"0123456789:;%3c=%3e?" +
+				"@ABCDEFGHIJKLMNO" +
+				"PQRSTUVWXYZ[%5c]%5e_" +
+				"%60abcdefghijklmno" +
+				"pqrstuvwxyz%7b%7c%7d~%7f" +
+				"%c2%a0%c4%80%e2%80%a8%e2%80%a9%ef%bb%bf%f0%9d%84%9e",
+		},
+	}
+
+	for _, test := range tests {
+		if s := test.escaper(input); s != test.escaped {
+			t.Errorf("%s: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
+			continue
+		}
+	}
+}
+
+func BenchmarkURLEscaper(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		urlEscaper("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
+	}
+}
+
+func BenchmarkURLEscaperNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		urlEscaper("TheQuickBrownFoxJumpsOverTheLazyDog.")
+	}
+}
+
+func BenchmarkURLNormalizer(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		urlNormalizer("The quick brown fox jumps over the lazy dog.\n")
+	}
+}
+
+func BenchmarkURLNormalizerNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		urlNormalizer("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/color/color.go b/third_party/gofrontend/libgo/go/image/color/color.go
new file mode 100644
index 0000000..ff596a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/color/color.go
@@ -0,0 +1,297 @@
+// 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.
+
+// Package color implements a basic color library.
+package color
+
+// Color can convert itself to alpha-premultiplied 16-bits per channel RGBA.
+// The conversion may be lossy.
+type Color interface {
+	// RGBA returns the alpha-premultiplied red, green, blue and alpha values
+	// for the color. Each value ranges within [0, 0xFFFF], but is represented
+	// by a uint32 so that multiplying by a blend factor up to 0xFFFF will not
+	// overflow.
+	RGBA() (r, g, b, a uint32)
+}
+
+// RGBA represents a traditional 32-bit alpha-premultiplied color,
+// having 8 bits for each of red, green, blue and alpha.
+type RGBA struct {
+	R, G, B, A uint8
+}
+
+func (c RGBA) RGBA() (r, g, b, a uint32) {
+	r = uint32(c.R)
+	r |= r << 8
+	g = uint32(c.G)
+	g |= g << 8
+	b = uint32(c.B)
+	b |= b << 8
+	a = uint32(c.A)
+	a |= a << 8
+	return
+}
+
+// RGBA64 represents a 64-bit alpha-premultiplied color,
+// having 16 bits for each of red, green, blue and alpha.
+type RGBA64 struct {
+	R, G, B, A uint16
+}
+
+func (c RGBA64) RGBA() (r, g, b, a uint32) {
+	return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
+}
+
+// NRGBA represents a non-alpha-premultiplied 32-bit color.
+type NRGBA struct {
+	R, G, B, A uint8
+}
+
+func (c NRGBA) RGBA() (r, g, b, a uint32) {
+	r = uint32(c.R)
+	r |= r << 8
+	r *= uint32(c.A)
+	r /= 0xff
+	g = uint32(c.G)
+	g |= g << 8
+	g *= uint32(c.A)
+	g /= 0xff
+	b = uint32(c.B)
+	b |= b << 8
+	b *= uint32(c.A)
+	b /= 0xff
+	a = uint32(c.A)
+	a |= a << 8
+	return
+}
+
+// NRGBA64 represents a non-alpha-premultiplied 64-bit color,
+// having 16 bits for each of red, green, blue and alpha.
+type NRGBA64 struct {
+	R, G, B, A uint16
+}
+
+func (c NRGBA64) RGBA() (r, g, b, a uint32) {
+	r = uint32(c.R)
+	r *= uint32(c.A)
+	r /= 0xffff
+	g = uint32(c.G)
+	g *= uint32(c.A)
+	g /= 0xffff
+	b = uint32(c.B)
+	b *= uint32(c.A)
+	b /= 0xffff
+	a = uint32(c.A)
+	return
+}
+
+// Alpha represents an 8-bit alpha color.
+type Alpha struct {
+	A uint8
+}
+
+func (c Alpha) RGBA() (r, g, b, a uint32) {
+	a = uint32(c.A)
+	a |= a << 8
+	return a, a, a, a
+}
+
+// Alpha16 represents a 16-bit alpha color.
+type Alpha16 struct {
+	A uint16
+}
+
+func (c Alpha16) RGBA() (r, g, b, a uint32) {
+	a = uint32(c.A)
+	return a, a, a, a
+}
+
+// Gray represents an 8-bit grayscale color.
+type Gray struct {
+	Y uint8
+}
+
+func (c Gray) RGBA() (r, g, b, a uint32) {
+	y := uint32(c.Y)
+	y |= y << 8
+	return y, y, y, 0xffff
+}
+
+// Gray16 represents a 16-bit grayscale color.
+type Gray16 struct {
+	Y uint16
+}
+
+func (c Gray16) RGBA() (r, g, b, a uint32) {
+	y := uint32(c.Y)
+	return y, y, y, 0xffff
+}
+
+// Model can convert any Color to one from its own color model. The conversion
+// may be lossy.
+type Model interface {
+	Convert(c Color) Color
+}
+
+// ModelFunc returns a Model that invokes f to implement the conversion.
+func ModelFunc(f func(Color) Color) Model {
+	// Note: using *modelFunc as the implementation
+	// means that callers can still use comparisons
+	// like m == RGBAModel.  This is not possible if
+	// we use the func value directly, because funcs
+	// are no longer comparable.
+	return &modelFunc{f}
+}
+
+type modelFunc struct {
+	f func(Color) Color
+}
+
+func (m *modelFunc) Convert(c Color) Color {
+	return m.f(c)
+}
+
+// Models for the standard color types.
+var (
+	RGBAModel    Model = ModelFunc(rgbaModel)
+	RGBA64Model  Model = ModelFunc(rgba64Model)
+	NRGBAModel   Model = ModelFunc(nrgbaModel)
+	NRGBA64Model Model = ModelFunc(nrgba64Model)
+	AlphaModel   Model = ModelFunc(alphaModel)
+	Alpha16Model Model = ModelFunc(alpha16Model)
+	GrayModel    Model = ModelFunc(grayModel)
+	Gray16Model  Model = ModelFunc(gray16Model)
+)
+
+func rgbaModel(c Color) Color {
+	if _, ok := c.(RGBA); ok {
+		return c
+	}
+	r, g, b, a := c.RGBA()
+	return RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
+}
+
+func rgba64Model(c Color) Color {
+	if _, ok := c.(RGBA64); ok {
+		return c
+	}
+	r, g, b, a := c.RGBA()
+	return RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
+func nrgbaModel(c Color) Color {
+	if _, ok := c.(NRGBA); ok {
+		return c
+	}
+	r, g, b, a := c.RGBA()
+	if a == 0xffff {
+		return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
+	}
+	if a == 0 {
+		return NRGBA{0, 0, 0, 0}
+	}
+	// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
+	r = (r * 0xffff) / a
+	g = (g * 0xffff) / a
+	b = (b * 0xffff) / a
+	return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
+}
+
+func nrgba64Model(c Color) Color {
+	if _, ok := c.(NRGBA64); ok {
+		return c
+	}
+	r, g, b, a := c.RGBA()
+	if a == 0xffff {
+		return NRGBA64{uint16(r), uint16(g), uint16(b), 0xffff}
+	}
+	if a == 0 {
+		return NRGBA64{0, 0, 0, 0}
+	}
+	// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
+	r = (r * 0xffff) / a
+	g = (g * 0xffff) / a
+	b = (b * 0xffff) / a
+	return NRGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
+func alphaModel(c Color) Color {
+	if _, ok := c.(Alpha); ok {
+		return c
+	}
+	_, _, _, a := c.RGBA()
+	return Alpha{uint8(a >> 8)}
+}
+
+func alpha16Model(c Color) Color {
+	if _, ok := c.(Alpha16); ok {
+		return c
+	}
+	_, _, _, a := c.RGBA()
+	return Alpha16{uint16(a)}
+}
+
+func grayModel(c Color) Color {
+	if _, ok := c.(Gray); ok {
+		return c
+	}
+	r, g, b, _ := c.RGBA()
+	y := (299*r + 587*g + 114*b + 500) / 1000
+	return Gray{uint8(y >> 8)}
+}
+
+func gray16Model(c Color) Color {
+	if _, ok := c.(Gray16); ok {
+		return c
+	}
+	r, g, b, _ := c.RGBA()
+	y := (299*r + 587*g + 114*b + 500) / 1000
+	return Gray16{uint16(y)}
+}
+
+// Palette is a palette of colors.
+type Palette []Color
+
+// Convert returns the palette color closest to c in Euclidean R,G,B space.
+func (p Palette) Convert(c Color) Color {
+	if len(p) == 0 {
+		return nil
+	}
+	return p[p.Index(c)]
+}
+
+// Index returns the index of the palette color closest to c in Euclidean
+// R,G,B space.
+func (p Palette) Index(c Color) int {
+	// A batch version of this computation is in image/draw/draw.go.
+
+	cr, cg, cb, _ := c.RGBA()
+	ret, bestSSD := 0, uint32(1<<32-1)
+	for i, v := range p {
+		vr, vg, vb, _ := v.RGBA()
+		// We shift by 1 bit to avoid potential uint32 overflow in
+		// sum-squared-difference.
+		delta := (int32(cr) - int32(vr)) >> 1
+		ssd := uint32(delta * delta)
+		delta = (int32(cg) - int32(vg)) >> 1
+		ssd += uint32(delta * delta)
+		delta = (int32(cb) - int32(vb)) >> 1
+		ssd += uint32(delta * delta)
+		if ssd < bestSSD {
+			if ssd == 0 {
+				return i
+			}
+			ret, bestSSD = i, ssd
+		}
+	}
+	return ret
+}
+
+// Standard colors.
+var (
+	Black       = Gray16{0}
+	White       = Gray16{0xffff}
+	Transparent = Alpha16{0}
+	Opaque      = Alpha16{0xffff}
+)
diff --git a/third_party/gofrontend/libgo/go/image/color/palette/gen.go b/third_party/gofrontend/libgo/go/image/color/palette/gen.go
new file mode 100644
index 0000000..4f4d883
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/color/palette/gen.go
@@ -0,0 +1,101 @@
+// Copyright 2013 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.
+
+// +build ignore
+
+package main
+
+// This program generates palette.go. Invoke it as
+//	go run gen.go | gofmt > palette.go
+
+import (
+	"fmt"
+)
+
+func main() {
+	fmt.Println(`// Copyright 2013 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.`)
+	fmt.Println()
+	fmt.Println("// generated by go run gen.go; DO NOT EDIT")
+	fmt.Println()
+	fmt.Println("// Package palette provides standard color palettes.")
+	fmt.Println("package palette")
+	fmt.Println()
+	fmt.Println(`import "image/color"`)
+	fmt.Println()
+	printPlan9()
+	printWebSafe()
+}
+
+func printPlan9() {
+	c, lines := [3]int{}, [256]string{}
+	for r, i := 0, 0; r != 4; r++ {
+		for v := 0; v != 4; v, i = v+1, i+16 {
+			for g, j := 0, v-r; g != 4; g++ {
+				for b := 0; b != 4; b, j = b+1, j+1 {
+					den := r
+					if g > den {
+						den = g
+					}
+					if b > den {
+						den = b
+					}
+					if den == 0 {
+						c[0] = 0x11 * v
+						c[1] = 0x11 * v
+						c[2] = 0x11 * v
+					} else {
+						num := 17 * (4*den + v)
+						c[0] = r * num / den
+						c[1] = g * num / den
+						c[2] = b * num / den
+					}
+					lines[i+(j&0x0f)] =
+						fmt.Sprintf("\tcolor.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", c[0], c[1], c[2])
+				}
+			}
+		}
+	}
+	fmt.Println("// Plan9 is a 256-color palette that partitions the 24-bit RGB space")
+	fmt.Println("// into 4×4×4 subdivision, with 4 shades in each subcube. Compared to the")
+	fmt.Println("// WebSafe, the idea is to reduce the color resolution by dicing the")
+	fmt.Println("// color cube into fewer cells, and to use the extra space to increase the")
+	fmt.Println("// intensity resolution. This results in 16 gray shades (4 gray subcubes with")
+	fmt.Println("// 4 samples in each), 13 shades of each primary and secondary color (3")
+	fmt.Println("// subcubes with 4 samples plus black) and a reasonable selection of colors")
+	fmt.Println("// covering the rest of the color cube. The advantage is better representation")
+	fmt.Println("// of continuous tones.")
+	fmt.Println("//")
+	fmt.Println("// This palette was used in the Plan 9 Operating System, described at")
+	fmt.Println("// http://plan9.bell-labs.com/magic/man2html/6/color")
+	fmt.Println("var Plan9 = []color.Color{")
+	for _, line := range lines {
+		fmt.Println(line)
+	}
+	fmt.Println("}")
+	fmt.Println()
+}
+
+func printWebSafe() {
+	lines := [6 * 6 * 6]string{}
+	for r := 0; r < 6; r++ {
+		for g := 0; g < 6; g++ {
+			for b := 0; b < 6; b++ {
+				lines[36*r+6*g+b] =
+					fmt.Sprintf("\tcolor.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", 0x33*r, 0x33*g, 0x33*b)
+			}
+		}
+	}
+	fmt.Println("// WebSafe is a 216-color palette that was popularized by early versions")
+	fmt.Println("// of Netscape Navigator. It is also known as the Netscape Color Cube.")
+	fmt.Println("//")
+	fmt.Println("// See http://en.wikipedia.org/wiki/Web_colors#Web-safe_colors for details.")
+	fmt.Println("var WebSafe = []color.Color{")
+	for _, line := range lines {
+		fmt.Println(line)
+	}
+	fmt.Println("}")
+	fmt.Println()
+}
diff --git a/third_party/gofrontend/libgo/go/image/color/palette/palette.go b/third_party/gofrontend/libgo/go/image/color/palette/palette.go
new file mode 100644
index 0000000..f761e53
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/color/palette/palette.go
@@ -0,0 +1,504 @@
+// Copyright 2013 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.
+
+// generated by go run gen.go; DO NOT EDIT
+
+// Package palette provides standard color palettes.
+package palette
+
+import "image/color"
+
+// Plan9 is a 256-color palette that partitions the 24-bit RGB space
+// into 4×4×4 subdivision, with 4 shades in each subcube. Compared to the
+// WebSafe, the idea is to reduce the color resolution by dicing the
+// color cube into fewer cells, and to use the extra space to increase the
+// intensity resolution. This results in 16 gray shades (4 gray subcubes with
+// 4 samples in each), 13 shades of each primary and secondary color (3
+// subcubes with 4 samples plus black) and a reasonable selection of colors
+// covering the rest of the color cube. The advantage is better representation
+// of continuous tones.
+//
+// This palette was used in the Plan 9 Operating System, described at
+// http://plan9.bell-labs.com/magic/man2html/6/color
+var Plan9 = []color.Color{
+	color.RGBA{0x00, 0x00, 0x00, 0xff},
+	color.RGBA{0x00, 0x00, 0x44, 0xff},
+	color.RGBA{0x00, 0x00, 0x88, 0xff},
+	color.RGBA{0x00, 0x00, 0xcc, 0xff},
+	color.RGBA{0x00, 0x44, 0x00, 0xff},
+	color.RGBA{0x00, 0x44, 0x44, 0xff},
+	color.RGBA{0x00, 0x44, 0x88, 0xff},
+	color.RGBA{0x00, 0x44, 0xcc, 0xff},
+	color.RGBA{0x00, 0x88, 0x00, 0xff},
+	color.RGBA{0x00, 0x88, 0x44, 0xff},
+	color.RGBA{0x00, 0x88, 0x88, 0xff},
+	color.RGBA{0x00, 0x88, 0xcc, 0xff},
+	color.RGBA{0x00, 0xcc, 0x00, 0xff},
+	color.RGBA{0x00, 0xcc, 0x44, 0xff},
+	color.RGBA{0x00, 0xcc, 0x88, 0xff},
+	color.RGBA{0x00, 0xcc, 0xcc, 0xff},
+	color.RGBA{0x00, 0xdd, 0xdd, 0xff},
+	color.RGBA{0x11, 0x11, 0x11, 0xff},
+	color.RGBA{0x00, 0x00, 0x55, 0xff},
+	color.RGBA{0x00, 0x00, 0x99, 0xff},
+	color.RGBA{0x00, 0x00, 0xdd, 0xff},
+	color.RGBA{0x00, 0x55, 0x00, 0xff},
+	color.RGBA{0x00, 0x55, 0x55, 0xff},
+	color.RGBA{0x00, 0x4c, 0x99, 0xff},
+	color.RGBA{0x00, 0x49, 0xdd, 0xff},
+	color.RGBA{0x00, 0x99, 0x00, 0xff},
+	color.RGBA{0x00, 0x99, 0x4c, 0xff},
+	color.RGBA{0x00, 0x99, 0x99, 0xff},
+	color.RGBA{0x00, 0x93, 0xdd, 0xff},
+	color.RGBA{0x00, 0xdd, 0x00, 0xff},
+	color.RGBA{0x00, 0xdd, 0x49, 0xff},
+	color.RGBA{0x00, 0xdd, 0x93, 0xff},
+	color.RGBA{0x00, 0xee, 0x9e, 0xff},
+	color.RGBA{0x00, 0xee, 0xee, 0xff},
+	color.RGBA{0x22, 0x22, 0x22, 0xff},
+	color.RGBA{0x00, 0x00, 0x66, 0xff},
+	color.RGBA{0x00, 0x00, 0xaa, 0xff},
+	color.RGBA{0x00, 0x00, 0xee, 0xff},
+	color.RGBA{0x00, 0x66, 0x00, 0xff},
+	color.RGBA{0x00, 0x66, 0x66, 0xff},
+	color.RGBA{0x00, 0x55, 0xaa, 0xff},
+	color.RGBA{0x00, 0x4f, 0xee, 0xff},
+	color.RGBA{0x00, 0xaa, 0x00, 0xff},
+	color.RGBA{0x00, 0xaa, 0x55, 0xff},
+	color.RGBA{0x00, 0xaa, 0xaa, 0xff},
+	color.RGBA{0x00, 0x9e, 0xee, 0xff},
+	color.RGBA{0x00, 0xee, 0x00, 0xff},
+	color.RGBA{0x00, 0xee, 0x4f, 0xff},
+	color.RGBA{0x00, 0xff, 0x55, 0xff},
+	color.RGBA{0x00, 0xff, 0xaa, 0xff},
+	color.RGBA{0x00, 0xff, 0xff, 0xff},
+	color.RGBA{0x33, 0x33, 0x33, 0xff},
+	color.RGBA{0x00, 0x00, 0x77, 0xff},
+	color.RGBA{0x00, 0x00, 0xbb, 0xff},
+	color.RGBA{0x00, 0x00, 0xff, 0xff},
+	color.RGBA{0x00, 0x77, 0x00, 0xff},
+	color.RGBA{0x00, 0x77, 0x77, 0xff},
+	color.RGBA{0x00, 0x5d, 0xbb, 0xff},
+	color.RGBA{0x00, 0x55, 0xff, 0xff},
+	color.RGBA{0x00, 0xbb, 0x00, 0xff},
+	color.RGBA{0x00, 0xbb, 0x5d, 0xff},
+	color.RGBA{0x00, 0xbb, 0xbb, 0xff},
+	color.RGBA{0x00, 0xaa, 0xff, 0xff},
+	color.RGBA{0x00, 0xff, 0x00, 0xff},
+	color.RGBA{0x44, 0x00, 0x44, 0xff},
+	color.RGBA{0x44, 0x00, 0x88, 0xff},
+	color.RGBA{0x44, 0x00, 0xcc, 0xff},
+	color.RGBA{0x44, 0x44, 0x00, 0xff},
+	color.RGBA{0x44, 0x44, 0x44, 0xff},
+	color.RGBA{0x44, 0x44, 0x88, 0xff},
+	color.RGBA{0x44, 0x44, 0xcc, 0xff},
+	color.RGBA{0x44, 0x88, 0x00, 0xff},
+	color.RGBA{0x44, 0x88, 0x44, 0xff},
+	color.RGBA{0x44, 0x88, 0x88, 0xff},
+	color.RGBA{0x44, 0x88, 0xcc, 0xff},
+	color.RGBA{0x44, 0xcc, 0x00, 0xff},
+	color.RGBA{0x44, 0xcc, 0x44, 0xff},
+	color.RGBA{0x44, 0xcc, 0x88, 0xff},
+	color.RGBA{0x44, 0xcc, 0xcc, 0xff},
+	color.RGBA{0x44, 0x00, 0x00, 0xff},
+	color.RGBA{0x55, 0x00, 0x00, 0xff},
+	color.RGBA{0x55, 0x00, 0x55, 0xff},
+	color.RGBA{0x4c, 0x00, 0x99, 0xff},
+	color.RGBA{0x49, 0x00, 0xdd, 0xff},
+	color.RGBA{0x55, 0x55, 0x00, 0xff},
+	color.RGBA{0x55, 0x55, 0x55, 0xff},
+	color.RGBA{0x4c, 0x4c, 0x99, 0xff},
+	color.RGBA{0x49, 0x49, 0xdd, 0xff},
+	color.RGBA{0x4c, 0x99, 0x00, 0xff},
+	color.RGBA{0x4c, 0x99, 0x4c, 0xff},
+	color.RGBA{0x4c, 0x99, 0x99, 0xff},
+	color.RGBA{0x49, 0x93, 0xdd, 0xff},
+	color.RGBA{0x49, 0xdd, 0x00, 0xff},
+	color.RGBA{0x49, 0xdd, 0x49, 0xff},
+	color.RGBA{0x49, 0xdd, 0x93, 0xff},
+	color.RGBA{0x49, 0xdd, 0xdd, 0xff},
+	color.RGBA{0x4f, 0xee, 0xee, 0xff},
+	color.RGBA{0x66, 0x00, 0x00, 0xff},
+	color.RGBA{0x66, 0x00, 0x66, 0xff},
+	color.RGBA{0x55, 0x00, 0xaa, 0xff},
+	color.RGBA{0x4f, 0x00, 0xee, 0xff},
+	color.RGBA{0x66, 0x66, 0x00, 0xff},
+	color.RGBA{0x66, 0x66, 0x66, 0xff},
+	color.RGBA{0x55, 0x55, 0xaa, 0xff},
+	color.RGBA{0x4f, 0x4f, 0xee, 0xff},
+	color.RGBA{0x55, 0xaa, 0x00, 0xff},
+	color.RGBA{0x55, 0xaa, 0x55, 0xff},
+	color.RGBA{0x55, 0xaa, 0xaa, 0xff},
+	color.RGBA{0x4f, 0x9e, 0xee, 0xff},
+	color.RGBA{0x4f, 0xee, 0x00, 0xff},
+	color.RGBA{0x4f, 0xee, 0x4f, 0xff},
+	color.RGBA{0x4f, 0xee, 0x9e, 0xff},
+	color.RGBA{0x55, 0xff, 0xaa, 0xff},
+	color.RGBA{0x55, 0xff, 0xff, 0xff},
+	color.RGBA{0x77, 0x00, 0x00, 0xff},
+	color.RGBA{0x77, 0x00, 0x77, 0xff},
+	color.RGBA{0x5d, 0x00, 0xbb, 0xff},
+	color.RGBA{0x55, 0x00, 0xff, 0xff},
+	color.RGBA{0x77, 0x77, 0x00, 0xff},
+	color.RGBA{0x77, 0x77, 0x77, 0xff},
+	color.RGBA{0x5d, 0x5d, 0xbb, 0xff},
+	color.RGBA{0x55, 0x55, 0xff, 0xff},
+	color.RGBA{0x5d, 0xbb, 0x00, 0xff},
+	color.RGBA{0x5d, 0xbb, 0x5d, 0xff},
+	color.RGBA{0x5d, 0xbb, 0xbb, 0xff},
+	color.RGBA{0x55, 0xaa, 0xff, 0xff},
+	color.RGBA{0x55, 0xff, 0x00, 0xff},
+	color.RGBA{0x55, 0xff, 0x55, 0xff},
+	color.RGBA{0x88, 0x00, 0x88, 0xff},
+	color.RGBA{0x88, 0x00, 0xcc, 0xff},
+	color.RGBA{0x88, 0x44, 0x00, 0xff},
+	color.RGBA{0x88, 0x44, 0x44, 0xff},
+	color.RGBA{0x88, 0x44, 0x88, 0xff},
+	color.RGBA{0x88, 0x44, 0xcc, 0xff},
+	color.RGBA{0x88, 0x88, 0x00, 0xff},
+	color.RGBA{0x88, 0x88, 0x44, 0xff},
+	color.RGBA{0x88, 0x88, 0x88, 0xff},
+	color.RGBA{0x88, 0x88, 0xcc, 0xff},
+	color.RGBA{0x88, 0xcc, 0x00, 0xff},
+	color.RGBA{0x88, 0xcc, 0x44, 0xff},
+	color.RGBA{0x88, 0xcc, 0x88, 0xff},
+	color.RGBA{0x88, 0xcc, 0xcc, 0xff},
+	color.RGBA{0x88, 0x00, 0x00, 0xff},
+	color.RGBA{0x88, 0x00, 0x44, 0xff},
+	color.RGBA{0x99, 0x00, 0x4c, 0xff},
+	color.RGBA{0x99, 0x00, 0x99, 0xff},
+	color.RGBA{0x93, 0x00, 0xdd, 0xff},
+	color.RGBA{0x99, 0x4c, 0x00, 0xff},
+	color.RGBA{0x99, 0x4c, 0x4c, 0xff},
+	color.RGBA{0x99, 0x4c, 0x99, 0xff},
+	color.RGBA{0x93, 0x49, 0xdd, 0xff},
+	color.RGBA{0x99, 0x99, 0x00, 0xff},
+	color.RGBA{0x99, 0x99, 0x4c, 0xff},
+	color.RGBA{0x99, 0x99, 0x99, 0xff},
+	color.RGBA{0x93, 0x93, 0xdd, 0xff},
+	color.RGBA{0x93, 0xdd, 0x00, 0xff},
+	color.RGBA{0x93, 0xdd, 0x49, 0xff},
+	color.RGBA{0x93, 0xdd, 0x93, 0xff},
+	color.RGBA{0x93, 0xdd, 0xdd, 0xff},
+	color.RGBA{0x99, 0x00, 0x00, 0xff},
+	color.RGBA{0xaa, 0x00, 0x00, 0xff},
+	color.RGBA{0xaa, 0x00, 0x55, 0xff},
+	color.RGBA{0xaa, 0x00, 0xaa, 0xff},
+	color.RGBA{0x9e, 0x00, 0xee, 0xff},
+	color.RGBA{0xaa, 0x55, 0x00, 0xff},
+	color.RGBA{0xaa, 0x55, 0x55, 0xff},
+	color.RGBA{0xaa, 0x55, 0xaa, 0xff},
+	color.RGBA{0x9e, 0x4f, 0xee, 0xff},
+	color.RGBA{0xaa, 0xaa, 0x00, 0xff},
+	color.RGBA{0xaa, 0xaa, 0x55, 0xff},
+	color.RGBA{0xaa, 0xaa, 0xaa, 0xff},
+	color.RGBA{0x9e, 0x9e, 0xee, 0xff},
+	color.RGBA{0x9e, 0xee, 0x00, 0xff},
+	color.RGBA{0x9e, 0xee, 0x4f, 0xff},
+	color.RGBA{0x9e, 0xee, 0x9e, 0xff},
+	color.RGBA{0x9e, 0xee, 0xee, 0xff},
+	color.RGBA{0xaa, 0xff, 0xff, 0xff},
+	color.RGBA{0xbb, 0x00, 0x00, 0xff},
+	color.RGBA{0xbb, 0x00, 0x5d, 0xff},
+	color.RGBA{0xbb, 0x00, 0xbb, 0xff},
+	color.RGBA{0xaa, 0x00, 0xff, 0xff},
+	color.RGBA{0xbb, 0x5d, 0x00, 0xff},
+	color.RGBA{0xbb, 0x5d, 0x5d, 0xff},
+	color.RGBA{0xbb, 0x5d, 0xbb, 0xff},
+	color.RGBA{0xaa, 0x55, 0xff, 0xff},
+	color.RGBA{0xbb, 0xbb, 0x00, 0xff},
+	color.RGBA{0xbb, 0xbb, 0x5d, 0xff},
+	color.RGBA{0xbb, 0xbb, 0xbb, 0xff},
+	color.RGBA{0xaa, 0xaa, 0xff, 0xff},
+	color.RGBA{0xaa, 0xff, 0x00, 0xff},
+	color.RGBA{0xaa, 0xff, 0x55, 0xff},
+	color.RGBA{0xaa, 0xff, 0xaa, 0xff},
+	color.RGBA{0xcc, 0x00, 0xcc, 0xff},
+	color.RGBA{0xcc, 0x44, 0x00, 0xff},
+	color.RGBA{0xcc, 0x44, 0x44, 0xff},
+	color.RGBA{0xcc, 0x44, 0x88, 0xff},
+	color.RGBA{0xcc, 0x44, 0xcc, 0xff},
+	color.RGBA{0xcc, 0x88, 0x00, 0xff},
+	color.RGBA{0xcc, 0x88, 0x44, 0xff},
+	color.RGBA{0xcc, 0x88, 0x88, 0xff},
+	color.RGBA{0xcc, 0x88, 0xcc, 0xff},
+	color.RGBA{0xcc, 0xcc, 0x00, 0xff},
+	color.RGBA{0xcc, 0xcc, 0x44, 0xff},
+	color.RGBA{0xcc, 0xcc, 0x88, 0xff},
+	color.RGBA{0xcc, 0xcc, 0xcc, 0xff},
+	color.RGBA{0xcc, 0x00, 0x00, 0xff},
+	color.RGBA{0xcc, 0x00, 0x44, 0xff},
+	color.RGBA{0xcc, 0x00, 0x88, 0xff},
+	color.RGBA{0xdd, 0x00, 0x93, 0xff},
+	color.RGBA{0xdd, 0x00, 0xdd, 0xff},
+	color.RGBA{0xdd, 0x49, 0x00, 0xff},
+	color.RGBA{0xdd, 0x49, 0x49, 0xff},
+	color.RGBA{0xdd, 0x49, 0x93, 0xff},
+	color.RGBA{0xdd, 0x49, 0xdd, 0xff},
+	color.RGBA{0xdd, 0x93, 0x00, 0xff},
+	color.RGBA{0xdd, 0x93, 0x49, 0xff},
+	color.RGBA{0xdd, 0x93, 0x93, 0xff},
+	color.RGBA{0xdd, 0x93, 0xdd, 0xff},
+	color.RGBA{0xdd, 0xdd, 0x00, 0xff},
+	color.RGBA{0xdd, 0xdd, 0x49, 0xff},
+	color.RGBA{0xdd, 0xdd, 0x93, 0xff},
+	color.RGBA{0xdd, 0xdd, 0xdd, 0xff},
+	color.RGBA{0xdd, 0x00, 0x00, 0xff},
+	color.RGBA{0xdd, 0x00, 0x49, 0xff},
+	color.RGBA{0xee, 0x00, 0x4f, 0xff},
+	color.RGBA{0xee, 0x00, 0x9e, 0xff},
+	color.RGBA{0xee, 0x00, 0xee, 0xff},
+	color.RGBA{0xee, 0x4f, 0x00, 0xff},
+	color.RGBA{0xee, 0x4f, 0x4f, 0xff},
+	color.RGBA{0xee, 0x4f, 0x9e, 0xff},
+	color.RGBA{0xee, 0x4f, 0xee, 0xff},
+	color.RGBA{0xee, 0x9e, 0x00, 0xff},
+	color.RGBA{0xee, 0x9e, 0x4f, 0xff},
+	color.RGBA{0xee, 0x9e, 0x9e, 0xff},
+	color.RGBA{0xee, 0x9e, 0xee, 0xff},
+	color.RGBA{0xee, 0xee, 0x00, 0xff},
+	color.RGBA{0xee, 0xee, 0x4f, 0xff},
+	color.RGBA{0xee, 0xee, 0x9e, 0xff},
+	color.RGBA{0xee, 0xee, 0xee, 0xff},
+	color.RGBA{0xee, 0x00, 0x00, 0xff},
+	color.RGBA{0xff, 0x00, 0x00, 0xff},
+	color.RGBA{0xff, 0x00, 0x55, 0xff},
+	color.RGBA{0xff, 0x00, 0xaa, 0xff},
+	color.RGBA{0xff, 0x00, 0xff, 0xff},
+	color.RGBA{0xff, 0x55, 0x00, 0xff},
+	color.RGBA{0xff, 0x55, 0x55, 0xff},
+	color.RGBA{0xff, 0x55, 0xaa, 0xff},
+	color.RGBA{0xff, 0x55, 0xff, 0xff},
+	color.RGBA{0xff, 0xaa, 0x00, 0xff},
+	color.RGBA{0xff, 0xaa, 0x55, 0xff},
+	color.RGBA{0xff, 0xaa, 0xaa, 0xff},
+	color.RGBA{0xff, 0xaa, 0xff, 0xff},
+	color.RGBA{0xff, 0xff, 0x00, 0xff},
+	color.RGBA{0xff, 0xff, 0x55, 0xff},
+	color.RGBA{0xff, 0xff, 0xaa, 0xff},
+	color.RGBA{0xff, 0xff, 0xff, 0xff},
+}
+
+// WebSafe is a 216-color palette that was popularized by early versions
+// of Netscape Navigator. It is also known as the Netscape Color Cube.
+//
+// See http://en.wikipedia.org/wiki/Web_colors#Web-safe_colors for details.
+var WebSafe = []color.Color{
+	color.RGBA{0x00, 0x00, 0x00, 0xff},
+	color.RGBA{0x00, 0x00, 0x33, 0xff},
+	color.RGBA{0x00, 0x00, 0x66, 0xff},
+	color.RGBA{0x00, 0x00, 0x99, 0xff},
+	color.RGBA{0x00, 0x00, 0xcc, 0xff},
+	color.RGBA{0x00, 0x00, 0xff, 0xff},
+	color.RGBA{0x00, 0x33, 0x00, 0xff},
+	color.RGBA{0x00, 0x33, 0x33, 0xff},
+	color.RGBA{0x00, 0x33, 0x66, 0xff},
+	color.RGBA{0x00, 0x33, 0x99, 0xff},
+	color.RGBA{0x00, 0x33, 0xcc, 0xff},
+	color.RGBA{0x00, 0x33, 0xff, 0xff},
+	color.RGBA{0x00, 0x66, 0x00, 0xff},
+	color.RGBA{0x00, 0x66, 0x33, 0xff},
+	color.RGBA{0x00, 0x66, 0x66, 0xff},
+	color.RGBA{0x00, 0x66, 0x99, 0xff},
+	color.RGBA{0x00, 0x66, 0xcc, 0xff},
+	color.RGBA{0x00, 0x66, 0xff, 0xff},
+	color.RGBA{0x00, 0x99, 0x00, 0xff},
+	color.RGBA{0x00, 0x99, 0x33, 0xff},
+	color.RGBA{0x00, 0x99, 0x66, 0xff},
+	color.RGBA{0x00, 0x99, 0x99, 0xff},
+	color.RGBA{0x00, 0x99, 0xcc, 0xff},
+	color.RGBA{0x00, 0x99, 0xff, 0xff},
+	color.RGBA{0x00, 0xcc, 0x00, 0xff},
+	color.RGBA{0x00, 0xcc, 0x33, 0xff},
+	color.RGBA{0x00, 0xcc, 0x66, 0xff},
+	color.RGBA{0x00, 0xcc, 0x99, 0xff},
+	color.RGBA{0x00, 0xcc, 0xcc, 0xff},
+	color.RGBA{0x00, 0xcc, 0xff, 0xff},
+	color.RGBA{0x00, 0xff, 0x00, 0xff},
+	color.RGBA{0x00, 0xff, 0x33, 0xff},
+	color.RGBA{0x00, 0xff, 0x66, 0xff},
+	color.RGBA{0x00, 0xff, 0x99, 0xff},
+	color.RGBA{0x00, 0xff, 0xcc, 0xff},
+	color.RGBA{0x00, 0xff, 0xff, 0xff},
+	color.RGBA{0x33, 0x00, 0x00, 0xff},
+	color.RGBA{0x33, 0x00, 0x33, 0xff},
+	color.RGBA{0x33, 0x00, 0x66, 0xff},
+	color.RGBA{0x33, 0x00, 0x99, 0xff},
+	color.RGBA{0x33, 0x00, 0xcc, 0xff},
+	color.RGBA{0x33, 0x00, 0xff, 0xff},
+	color.RGBA{0x33, 0x33, 0x00, 0xff},
+	color.RGBA{0x33, 0x33, 0x33, 0xff},
+	color.RGBA{0x33, 0x33, 0x66, 0xff},
+	color.RGBA{0x33, 0x33, 0x99, 0xff},
+	color.RGBA{0x33, 0x33, 0xcc, 0xff},
+	color.RGBA{0x33, 0x33, 0xff, 0xff},
+	color.RGBA{0x33, 0x66, 0x00, 0xff},
+	color.RGBA{0x33, 0x66, 0x33, 0xff},
+	color.RGBA{0x33, 0x66, 0x66, 0xff},
+	color.RGBA{0x33, 0x66, 0x99, 0xff},
+	color.RGBA{0x33, 0x66, 0xcc, 0xff},
+	color.RGBA{0x33, 0x66, 0xff, 0xff},
+	color.RGBA{0x33, 0x99, 0x00, 0xff},
+	color.RGBA{0x33, 0x99, 0x33, 0xff},
+	color.RGBA{0x33, 0x99, 0x66, 0xff},
+	color.RGBA{0x33, 0x99, 0x99, 0xff},
+	color.RGBA{0x33, 0x99, 0xcc, 0xff},
+	color.RGBA{0x33, 0x99, 0xff, 0xff},
+	color.RGBA{0x33, 0xcc, 0x00, 0xff},
+	color.RGBA{0x33, 0xcc, 0x33, 0xff},
+	color.RGBA{0x33, 0xcc, 0x66, 0xff},
+	color.RGBA{0x33, 0xcc, 0x99, 0xff},
+	color.RGBA{0x33, 0xcc, 0xcc, 0xff},
+	color.RGBA{0x33, 0xcc, 0xff, 0xff},
+	color.RGBA{0x33, 0xff, 0x00, 0xff},
+	color.RGBA{0x33, 0xff, 0x33, 0xff},
+	color.RGBA{0x33, 0xff, 0x66, 0xff},
+	color.RGBA{0x33, 0xff, 0x99, 0xff},
+	color.RGBA{0x33, 0xff, 0xcc, 0xff},
+	color.RGBA{0x33, 0xff, 0xff, 0xff},
+	color.RGBA{0x66, 0x00, 0x00, 0xff},
+	color.RGBA{0x66, 0x00, 0x33, 0xff},
+	color.RGBA{0x66, 0x00, 0x66, 0xff},
+	color.RGBA{0x66, 0x00, 0x99, 0xff},
+	color.RGBA{0x66, 0x00, 0xcc, 0xff},
+	color.RGBA{0x66, 0x00, 0xff, 0xff},
+	color.RGBA{0x66, 0x33, 0x00, 0xff},
+	color.RGBA{0x66, 0x33, 0x33, 0xff},
+	color.RGBA{0x66, 0x33, 0x66, 0xff},
+	color.RGBA{0x66, 0x33, 0x99, 0xff},
+	color.RGBA{0x66, 0x33, 0xcc, 0xff},
+	color.RGBA{0x66, 0x33, 0xff, 0xff},
+	color.RGBA{0x66, 0x66, 0x00, 0xff},
+	color.RGBA{0x66, 0x66, 0x33, 0xff},
+	color.RGBA{0x66, 0x66, 0x66, 0xff},
+	color.RGBA{0x66, 0x66, 0x99, 0xff},
+	color.RGBA{0x66, 0x66, 0xcc, 0xff},
+	color.RGBA{0x66, 0x66, 0xff, 0xff},
+	color.RGBA{0x66, 0x99, 0x00, 0xff},
+	color.RGBA{0x66, 0x99, 0x33, 0xff},
+	color.RGBA{0x66, 0x99, 0x66, 0xff},
+	color.RGBA{0x66, 0x99, 0x99, 0xff},
+	color.RGBA{0x66, 0x99, 0xcc, 0xff},
+	color.RGBA{0x66, 0x99, 0xff, 0xff},
+	color.RGBA{0x66, 0xcc, 0x00, 0xff},
+	color.RGBA{0x66, 0xcc, 0x33, 0xff},
+	color.RGBA{0x66, 0xcc, 0x66, 0xff},
+	color.RGBA{0x66, 0xcc, 0x99, 0xff},
+	color.RGBA{0x66, 0xcc, 0xcc, 0xff},
+	color.RGBA{0x66, 0xcc, 0xff, 0xff},
+	color.RGBA{0x66, 0xff, 0x00, 0xff},
+	color.RGBA{0x66, 0xff, 0x33, 0xff},
+	color.RGBA{0x66, 0xff, 0x66, 0xff},
+	color.RGBA{0x66, 0xff, 0x99, 0xff},
+	color.RGBA{0x66, 0xff, 0xcc, 0xff},
+	color.RGBA{0x66, 0xff, 0xff, 0xff},
+	color.RGBA{0x99, 0x00, 0x00, 0xff},
+	color.RGBA{0x99, 0x00, 0x33, 0xff},
+	color.RGBA{0x99, 0x00, 0x66, 0xff},
+	color.RGBA{0x99, 0x00, 0x99, 0xff},
+	color.RGBA{0x99, 0x00, 0xcc, 0xff},
+	color.RGBA{0x99, 0x00, 0xff, 0xff},
+	color.RGBA{0x99, 0x33, 0x00, 0xff},
+	color.RGBA{0x99, 0x33, 0x33, 0xff},
+	color.RGBA{0x99, 0x33, 0x66, 0xff},
+	color.RGBA{0x99, 0x33, 0x99, 0xff},
+	color.RGBA{0x99, 0x33, 0xcc, 0xff},
+	color.RGBA{0x99, 0x33, 0xff, 0xff},
+	color.RGBA{0x99, 0x66, 0x00, 0xff},
+	color.RGBA{0x99, 0x66, 0x33, 0xff},
+	color.RGBA{0x99, 0x66, 0x66, 0xff},
+	color.RGBA{0x99, 0x66, 0x99, 0xff},
+	color.RGBA{0x99, 0x66, 0xcc, 0xff},
+	color.RGBA{0x99, 0x66, 0xff, 0xff},
+	color.RGBA{0x99, 0x99, 0x00, 0xff},
+	color.RGBA{0x99, 0x99, 0x33, 0xff},
+	color.RGBA{0x99, 0x99, 0x66, 0xff},
+	color.RGBA{0x99, 0x99, 0x99, 0xff},
+	color.RGBA{0x99, 0x99, 0xcc, 0xff},
+	color.RGBA{0x99, 0x99, 0xff, 0xff},
+	color.RGBA{0x99, 0xcc, 0x00, 0xff},
+	color.RGBA{0x99, 0xcc, 0x33, 0xff},
+	color.RGBA{0x99, 0xcc, 0x66, 0xff},
+	color.RGBA{0x99, 0xcc, 0x99, 0xff},
+	color.RGBA{0x99, 0xcc, 0xcc, 0xff},
+	color.RGBA{0x99, 0xcc, 0xff, 0xff},
+	color.RGBA{0x99, 0xff, 0x00, 0xff},
+	color.RGBA{0x99, 0xff, 0x33, 0xff},
+	color.RGBA{0x99, 0xff, 0x66, 0xff},
+	color.RGBA{0x99, 0xff, 0x99, 0xff},
+	color.RGBA{0x99, 0xff, 0xcc, 0xff},
+	color.RGBA{0x99, 0xff, 0xff, 0xff},
+	color.RGBA{0xcc, 0x00, 0x00, 0xff},
+	color.RGBA{0xcc, 0x00, 0x33, 0xff},
+	color.RGBA{0xcc, 0x00, 0x66, 0xff},
+	color.RGBA{0xcc, 0x00, 0x99, 0xff},
+	color.RGBA{0xcc, 0x00, 0xcc, 0xff},
+	color.RGBA{0xcc, 0x00, 0xff, 0xff},
+	color.RGBA{0xcc, 0x33, 0x00, 0xff},
+	color.RGBA{0xcc, 0x33, 0x33, 0xff},
+	color.RGBA{0xcc, 0x33, 0x66, 0xff},
+	color.RGBA{0xcc, 0x33, 0x99, 0xff},
+	color.RGBA{0xcc, 0x33, 0xcc, 0xff},
+	color.RGBA{0xcc, 0x33, 0xff, 0xff},
+	color.RGBA{0xcc, 0x66, 0x00, 0xff},
+	color.RGBA{0xcc, 0x66, 0x33, 0xff},
+	color.RGBA{0xcc, 0x66, 0x66, 0xff},
+	color.RGBA{0xcc, 0x66, 0x99, 0xff},
+	color.RGBA{0xcc, 0x66, 0xcc, 0xff},
+	color.RGBA{0xcc, 0x66, 0xff, 0xff},
+	color.RGBA{0xcc, 0x99, 0x00, 0xff},
+	color.RGBA{0xcc, 0x99, 0x33, 0xff},
+	color.RGBA{0xcc, 0x99, 0x66, 0xff},
+	color.RGBA{0xcc, 0x99, 0x99, 0xff},
+	color.RGBA{0xcc, 0x99, 0xcc, 0xff},
+	color.RGBA{0xcc, 0x99, 0xff, 0xff},
+	color.RGBA{0xcc, 0xcc, 0x00, 0xff},
+	color.RGBA{0xcc, 0xcc, 0x33, 0xff},
+	color.RGBA{0xcc, 0xcc, 0x66, 0xff},
+	color.RGBA{0xcc, 0xcc, 0x99, 0xff},
+	color.RGBA{0xcc, 0xcc, 0xcc, 0xff},
+	color.RGBA{0xcc, 0xcc, 0xff, 0xff},
+	color.RGBA{0xcc, 0xff, 0x00, 0xff},
+	color.RGBA{0xcc, 0xff, 0x33, 0xff},
+	color.RGBA{0xcc, 0xff, 0x66, 0xff},
+	color.RGBA{0xcc, 0xff, 0x99, 0xff},
+	color.RGBA{0xcc, 0xff, 0xcc, 0xff},
+	color.RGBA{0xcc, 0xff, 0xff, 0xff},
+	color.RGBA{0xff, 0x00, 0x00, 0xff},
+	color.RGBA{0xff, 0x00, 0x33, 0xff},
+	color.RGBA{0xff, 0x00, 0x66, 0xff},
+	color.RGBA{0xff, 0x00, 0x99, 0xff},
+	color.RGBA{0xff, 0x00, 0xcc, 0xff},
+	color.RGBA{0xff, 0x00, 0xff, 0xff},
+	color.RGBA{0xff, 0x33, 0x00, 0xff},
+	color.RGBA{0xff, 0x33, 0x33, 0xff},
+	color.RGBA{0xff, 0x33, 0x66, 0xff},
+	color.RGBA{0xff, 0x33, 0x99, 0xff},
+	color.RGBA{0xff, 0x33, 0xcc, 0xff},
+	color.RGBA{0xff, 0x33, 0xff, 0xff},
+	color.RGBA{0xff, 0x66, 0x00, 0xff},
+	color.RGBA{0xff, 0x66, 0x33, 0xff},
+	color.RGBA{0xff, 0x66, 0x66, 0xff},
+	color.RGBA{0xff, 0x66, 0x99, 0xff},
+	color.RGBA{0xff, 0x66, 0xcc, 0xff},
+	color.RGBA{0xff, 0x66, 0xff, 0xff},
+	color.RGBA{0xff, 0x99, 0x00, 0xff},
+	color.RGBA{0xff, 0x99, 0x33, 0xff},
+	color.RGBA{0xff, 0x99, 0x66, 0xff},
+	color.RGBA{0xff, 0x99, 0x99, 0xff},
+	color.RGBA{0xff, 0x99, 0xcc, 0xff},
+	color.RGBA{0xff, 0x99, 0xff, 0xff},
+	color.RGBA{0xff, 0xcc, 0x00, 0xff},
+	color.RGBA{0xff, 0xcc, 0x33, 0xff},
+	color.RGBA{0xff, 0xcc, 0x66, 0xff},
+	color.RGBA{0xff, 0xcc, 0x99, 0xff},
+	color.RGBA{0xff, 0xcc, 0xcc, 0xff},
+	color.RGBA{0xff, 0xcc, 0xff, 0xff},
+	color.RGBA{0xff, 0xff, 0x00, 0xff},
+	color.RGBA{0xff, 0xff, 0x33, 0xff},
+	color.RGBA{0xff, 0xff, 0x66, 0xff},
+	color.RGBA{0xff, 0xff, 0x99, 0xff},
+	color.RGBA{0xff, 0xff, 0xcc, 0xff},
+	color.RGBA{0xff, 0xff, 0xff, 0xff},
+}
diff --git a/third_party/gofrontend/libgo/go/image/color/ycbcr.go b/third_party/gofrontend/libgo/go/image/color/ycbcr.go
new file mode 100644
index 0000000..4c2f29e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/color/ycbcr.go
@@ -0,0 +1,99 @@
+// 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.
+
+package color
+
+// RGBToYCbCr converts an RGB triple to a Y'CbCr triple.
+func RGBToYCbCr(r, g, b uint8) (uint8, uint8, uint8) {
+	// The JFIF specification says:
+	//	Y' =  0.2990*R + 0.5870*G + 0.1140*B
+	//	Cb = -0.1687*R - 0.3313*G + 0.5000*B + 128
+	//	Cr =  0.5000*R - 0.4187*G - 0.0813*B + 128
+	// http://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
+	r1 := int(r)
+	g1 := int(g)
+	b1 := int(b)
+	yy := (19595*r1 + 38470*g1 + 7471*b1 + 1<<15) >> 16
+	cb := (-11056*r1 - 21712*g1 + 32768*b1 + 257<<15) >> 16
+	cr := (32768*r1 - 27440*g1 - 5328*b1 + 257<<15) >> 16
+	if yy < 0 {
+		yy = 0
+	} else if yy > 255 {
+		yy = 255
+	}
+	if cb < 0 {
+		cb = 0
+	} else if cb > 255 {
+		cb = 255
+	}
+	if cr < 0 {
+		cr = 0
+	} else if cr > 255 {
+		cr = 255
+	}
+	return uint8(yy), uint8(cb), uint8(cr)
+}
+
+// YCbCrToRGB converts a Y'CbCr triple to an RGB triple.
+func YCbCrToRGB(y, cb, cr uint8) (uint8, uint8, uint8) {
+	// The JFIF specification says:
+	//	R = Y' + 1.40200*(Cr-128)
+	//	G = Y' - 0.34414*(Cb-128) - 0.71414*(Cr-128)
+	//	B = Y' + 1.77200*(Cb-128)
+	// http://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
+	yy1 := int(y)<<16 + 1<<15
+	cb1 := int(cb) - 128
+	cr1 := int(cr) - 128
+	r := (yy1 + 91881*cr1) >> 16
+	g := (yy1 - 22554*cb1 - 46802*cr1) >> 16
+	b := (yy1 + 116130*cb1) >> 16
+	if r < 0 {
+		r = 0
+	} else if r > 255 {
+		r = 255
+	}
+	if g < 0 {
+		g = 0
+	} else if g > 255 {
+		g = 255
+	}
+	if b < 0 {
+		b = 0
+	} else if b > 255 {
+		b = 255
+	}
+	return uint8(r), uint8(g), uint8(b)
+}
+
+// YCbCr represents a fully opaque 24-bit Y'CbCr color, having 8 bits each for
+// one luma and two chroma components.
+//
+// JPEG, VP8, the MPEG family and other codecs use this color model. Such
+// codecs often use the terms YUV and Y'CbCr interchangeably, but strictly
+// speaking, the term YUV applies only to analog video signals, and Y' (luma)
+// is Y (luminance) after applying gamma correction.
+//
+// Conversion between RGB and Y'CbCr is lossy and there are multiple, slightly
+// different formulae for converting between the two. This package follows
+// the JFIF specification at http://www.w3.org/Graphics/JPEG/jfif3.pdf.
+type YCbCr struct {
+	Y, Cb, Cr uint8
+}
+
+func (c YCbCr) RGBA() (uint32, uint32, uint32, uint32) {
+	r, g, b := YCbCrToRGB(c.Y, c.Cb, c.Cr)
+	return uint32(r) * 0x101, uint32(g) * 0x101, uint32(b) * 0x101, 0xffff
+}
+
+// YCbCrModel is the Model for Y'CbCr colors.
+var YCbCrModel Model = ModelFunc(yCbCrModel)
+
+func yCbCrModel(c Color) Color {
+	if _, ok := c.(YCbCr); ok {
+		return c
+	}
+	r, g, b, _ := c.RGBA()
+	y, u, v := RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
+	return YCbCr{y, u, v}
+}
diff --git a/third_party/gofrontend/libgo/go/image/color/ycbcr_test.go b/third_party/gofrontend/libgo/go/image/color/ycbcr_test.go
new file mode 100644
index 0000000..92a0e6f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/color/ycbcr_test.go
@@ -0,0 +1,33 @@
+// 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.
+
+package color
+
+import (
+	"testing"
+)
+
+func delta(x, y uint8) uint8 {
+	if x >= y {
+		return x - y
+	}
+	return y - x
+}
+
+// Test that a subset of RGB space can be converted to YCbCr and back to within
+// 1/256 tolerance.
+func TestRoundtrip(t *testing.T) {
+	for r := 0; r < 255; r += 7 {
+		for g := 0; g < 255; g += 5 {
+			for b := 0; b < 255; b += 3 {
+				r0, g0, b0 := uint8(r), uint8(g), uint8(b)
+				y, cb, cr := RGBToYCbCr(r0, g0, b0)
+				r1, g1, b1 := YCbCrToRGB(y, cb, cr)
+				if delta(r0, r1) > 1 || delta(g0, g1) > 1 || delta(b0, b1) > 1 {
+					t.Fatalf("r0, g0, b0 = %d, %d, %d   r1, g1, b1 = %d, %d, %d", r0, g0, b0, r1, g1, b1)
+				}
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/decode_example_test.go b/third_party/gofrontend/libgo/go/image/decode_example_test.go
new file mode 100644
index 0000000..21e90fe
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/decode_example_test.go
@@ -0,0 +1,140 @@
+// 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.
+
+// This example demonstrates decoding a JPEG image and examining its pixels.
+package image_test
+
+import (
+	"encoding/base64"
+	"fmt"
+	"image"
+	"log"
+	"strings"
+
+	// Package image/jpeg is not used explicitly in the code below,
+	// but is imported for its initialization side-effect, which allows
+	// image.Decode to understand JPEG formatted images. Uncomment these
+	// two lines to also understand GIF and PNG images:
+	// _ "image/gif"
+	// _ "image/png"
+	_ "image/jpeg"
+)
+
+func Example() {
+	// Decode the JPEG data. If reading from file, create a reader with
+	//
+	// reader, err := os.Open("testdata/video-001.q50.420.jpeg")
+	// if err != nil {
+	//     log.Fatal(err)
+	// }
+	// defer reader.Close()
+	reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(data))
+	m, _, err := image.Decode(reader)
+	if err != nil {
+		log.Fatal(err)
+	}
+	bounds := m.Bounds()
+
+	// Calculate a 16-bin histogram for m's red, green, blue and alpha components.
+	//
+	// An image's bounds do not necessarily start at (0, 0), so the two loops start
+	// at bounds.Min.Y and bounds.Min.X. Looping over Y first and X second is more
+	// likely to result in better memory access patterns than X first and Y second.
+	var histogram [16][4]int
+	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
+		for x := bounds.Min.X; x < bounds.Max.X; x++ {
+			r, g, b, a := m.At(x, y).RGBA()
+			// A color's RGBA method returns values in the range [0, 65535].
+			// Shifting by 12 reduces this to the range [0, 15].
+			histogram[r>>12][0]++
+			histogram[g>>12][1]++
+			histogram[b>>12][2]++
+			histogram[a>>12][3]++
+		}
+	}
+
+	// Print the results.
+	fmt.Printf("%-14s %6s %6s %6s %6s\n", "bin", "red", "green", "blue", "alpha")
+	for i, x := range histogram {
+		fmt.Printf("0x%04x-0x%04x: %6d %6d %6d %6d\n", i<<12, (i+1)<<12-1, x[0], x[1], x[2], x[3])
+	}
+	// Output:
+	// bin               red  green   blue  alpha
+	// 0x0000-0x0fff:    353    759   7228      0
+	// 0x1000-0x1fff:    629   2944   1036      0
+	// 0x2000-0x2fff:   1075   2319    984      0
+	// 0x3000-0x3fff:    838   2291    988      0
+	// 0x4000-0x4fff:    540   1302    542      0
+	// 0x5000-0x5fff:    319    971    263      0
+	// 0x6000-0x6fff:    316    377    178      0
+	// 0x7000-0x7fff:    581    280    216      0
+	// 0x8000-0x8fff:   3457    228    274      0
+	// 0x9000-0x9fff:   2294    237    334      0
+	// 0xa000-0xafff:    938    283    370      0
+	// 0xb000-0xbfff:    322    338    401      0
+	// 0xc000-0xcfff:    229    386    295      0
+	// 0xd000-0xdfff:    263    416    281      0
+	// 0xe000-0xefff:    538    433    312      0
+	// 0xf000-0xffff:   2758   1886   1748  15450
+}
+
+const data = `
+/9j/4AAQSkZJRgABAQIAHAAcAAD/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdA
+SFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2Nj
+Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wAARCABnAJYDASIAAhEBAxEB/8QA
+HwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIh
+MUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVW
+V1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG
+x8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQF
+BgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAV
+YnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE
+hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq
+8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDlwKMD0pwzSiuK57QzGDxS7D6in8Y5ximnAPUfSlcq4m3ilUYp
+2OKXHvRcVxnTtS7c07HNFK4DQPakC4PNOA+tOx70XAjK/So5gBGP94fzqfvUVx/qxx/EP51UXqRP4WSE
+cmgjilP3jSEZqS0IO/NGDnpUiocDg/McDjvV6HTPOdVWYgsM5KcfzzQ2JySM2jp6VYu7SWzmMUwG4cgj
+kMPUVBjjtTGtRu0Zopw+lFFxhinrGzuqqMsxAA9yaXFSRv5cqSEcIwYj6GpuZ30O30fSLKzhUpbpNMv3
+5XGTn29BV28jt7pPLuIVljPBBFVreYx+VbqAjycgt3x14zRcNOxGyVFHQkIc/wA61exyKLbuzjdZ046d
+ftEuTEw3Rk9SPT8P8Kpbea3tchbyVae4JkjbbGpGdwOM89Af6ViFTWUtGdcXoM2+woK1JtpNtTcoZt+l
+Jt7ZqTbRtouFyPFRXI/c9D94fzqzioLsfuD/ALw/nVReqIn8LJCOTSY+tSMOTmkIpXLRu+F0t5pJxPHG
+wjjUAuBjJJz1+laD6Pai+WaK9SBX6puzn6ZP+NV/Dkdtc6ZNbyAFwxLAHDYPv6VoQ21nPNEEiQGEFRtk
+Gf0NaWTOeW7Of8QwGG4MRZnEbYXPJwRnOR0zWNXW+KrqBLUWi5EjbWCgcAA9c/gRXKYqZaGlK/LqMH0F
+FLtHvRSNiYD2pSDTgpp6p0ywUHoTULXYxcktzrdCf7Xo8LP/AKyEmMNjJ46dfbFWJ5TDGNwB9lFUvDV9
+YrbfYGbyrjcWG88S57g+vtV26ZIvMlumKwwjLZ6V0WfU54yTvYwtbubea2WNWbzg4bYQeBgj8OtYeKhj
+u4y2HQxqxOD1xzxmrWAQCCGB6EGsaikndmsJxeiYzBo280/Z7UbayuaXGY5oIp+2lx9KLjIsVDeD/Rj/
+ALy/zq1t96r3y4tT/vL/ADq4P3kRP4WSleTSFKkkKoCW4GaqNcMxIjXj1pxjKT0FKrGC1Nrw3vGrKkYz
+5kTAr6455/HH510UdwPtRgWCbzF5+YYUf4Vwun39xpmoR3qASMmQUJwGU9Rnt/8AWrpbrxhb8/ZdOmaQ
+gAGZwFH5ZJrpVKVlY5ZYhN6kXiu2eO/ikZlIljAAB5yM549OawSOOlPuLqe+umuLqTfM4OSOAo7ADsKh
+hl/cRsTuJHPv7mlKi3sVTxNtGP20VJhThgSQaK52mnZnUqsWrpkyeUrr5pABOAPU1AGaXUCWJISHGPfP
+P8qL7BiKnsMg46H3qrbzupbj5mPTPTpXVSglG551SpzSsXJ4/MBUgYIxyKpySyGBYJriV1D7kRpCVH4V
+bSeNJ4xchni3DeqnBI+td7F4b0mKIRjT45VbktJlzk455+n6VtYzv2PNwFZWBHBGKVJDGVC54/nXQeMN
+NttLNkba1jgWVWDmM8bhg4/nzXLSSbXVj6fyNKUdNRp21RtIRJGrjuM0u3FQ2DbodvcEkfQmrW2vLqLl
+k0ejCXNFMj2/jQV9qkxSYNRcsZiq2oI32N2CkhWXJxwOe9XMcVt6hoPn6dFaW0wgRpNzvKDlz6+/0rai
+ryv2Jm9LHJai+ZRGCBjnr71ErdAxAY9B611t1Y2cunbbaOQ3FvKZI3UqGlZMbiWwfcfhV231iwvLSM3U
+lt5Uq52TuZG+hGMA12xXJGxxzjzybOQtNOvb5j9ktZJhnBIHyg+5PFX38JayqK/2eLJIBUTgkDA9q7ex
+itrSHFpGsUbndhRgc+g7VNIyfZJAoJZUbb3I46CtFJMylBo8sdWhmYMuCnylc9wef5VUT7+1chc5NS7h
+sUZO5RtIPUH3pkBDOxxxmqM9TQtn+WilhHfHaik43KTG3Z4IyPyrNVjGCsZ+dmwv6V3cXhSG8sYpJLud
+JJIwxChdoJGcYx/Wkg8DafA4knvLiQr/ALqj+VQpKw3FtnFFfvbiSMgZJ6/jXp2n3d9cQRBTFsKD96EP
+oOxPU/8A68VVtbbRtMVntbePKDLTSHJH/Aj/AEqHTvE66rq72VugMMcbSGTnL4wMAfjT5n0HyW3L+s6b
+baxaJBdzN+7bcrxkAhun0rz3VNCv7e7lgigknWI43xLu6jjIHTjtXqfkpPGVYsBkghTikgsYIN/lhgXb
+cxLkknp/ShczQ7xtY8vtEmhkj8yGRBuCnehUcnHcVtmwfJ/fQ8e7f/E12txZW91C0U6b42xlST2OR/Ko
+Bo1gM/uW55/1jf41nOipu7LhV5FZHIGzI6zwj/vr/Ck+yr3uYf8Ax7/CutbQdMb71tn/ALaN/jSf8I/p
+X/PoP++2/wAan6rAr6wzkWt0II+1Rc/7Lf4Vd1eeCSKBbdZDdShYoiZNoyfY10P/AAj2lf8APmP++2/x
+oPh/SjKspsozIuNrZORjp3qo0FHYPb3OZt7ae3SzjuItsiRSAgnccl/UA+3Q1yNjKLR4ZZYY5VD7tkv3
+WwO/+e1evPp9nI257aJm6bioz1z1+tY+s6Hplnot9PbWMMcqwOFcLyOO1bJWMZSTOPHi+9w3mosrlyd2
+9lCj02g9P/1e9a3hzxAbl2ikZRcdQueHHt7j864Y8Z4I4oRzG6urFWU5BHBB7HNJxTFGbR6he6Vpmtgm
+eLy5zwZI/lb8fX8azIvBUUTHdfSFP4QsYB/HNZ+k+KEnRY75hHOvAk6K/v7H9K6yyvlnQBmDZ6GsnzR0
+N0oy1RzOtaN/Y1tHNFO06u+zYy4I4Jzx9KKveJblXuordSGES5b6n/62PzorKVdp2LjQTVyWz8UWEWlq
+jSgyxfJt6EgdDzWTdeLIZGO7zHI/hVajGmWWP+PWL8qwlAIURrhpMAHHJA71pRcZrToZzcoEuo6heakA
+GHk245CZ6/X1qPTLq40q+W5t2QybSpDAkEEc55/zilk5k2r91eKhLDzWz2rpsczbbuemeD76fUNG865I
+MiysmQMZAAwa3a5j4ftu0ByP+fh/5CulkLLG7INzhSVHqe1Fh3uOoqn9qQQxyhndmHIxwOmSR2xQ13KD
+KoiBZOV9JBnt707MVy5RWdNdy7wRGf3bfMinnO1jg+vY03WXLaJO3mhQ20b0zwpYf0qlG7S7icrJs08U
+VwumgC+YiQyeVtZH567hzj8aSL949oGhE/2v5pJCDkksQwBHC4/+vXQ8LZ2uYxxCavY7us/xCcaBfn0h
+b+VP0bnSrb94ZMJgOecj1rl/GfidUE2k2gy5+SeQjgA/wj3rlas2jdao48qrjLAGkSKPk4Gc1WMj92I+
+lIJnU8OfxPWo5inBokmtQTmM4OOh71b0q6vbFmWCbaxHyqQGAP0PT8KhSTzVyo5ocSKA5VfTOTmqsmRd
+pl99XjPzThzK3zOeOSeveirNmkgg/fIpYsTkYORxRXmzlTjJqx6EVUcU7mhkKCzdAK59QI9zYxtG1fYU
+UVtgtmY4nZEa8Ak9aqFv3rfSiiu1nMeifDv/AJF+T/r4f+QrqqKKQwzQenNFFMCOKFIgNuThdoJ5OPSk
+ubeK6t3gnXdG4wwziiii/UTKMOg6dbzJLFE4dSCP3rEdeOM8805tDsGMvySgSsS6rM6gk9eAcUUVftZt
+3uyVGNthuq3Eei6DK8H7sRR7YuMgHtXkc8rzTNLM26RyWY+p70UVnLY0iEsUipG7rhZBlDkc1HgYoorM
+0HwyBXGeRjmrcUhMg2ghezd//rUUVcTKW5s2jZtY/QDaOKKKK8ip8bPRj8KP/9k=
+`
diff --git a/third_party/gofrontend/libgo/go/image/decode_test.go b/third_party/gofrontend/libgo/go/image/decode_test.go
new file mode 100644
index 0000000..8dee57e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/decode_test.go
@@ -0,0 +1,120 @@
+// 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.
+
+package image_test
+
+import (
+	"bufio"
+	"image"
+	"image/color"
+	"os"
+	"testing"
+
+	_ "image/gif"
+	_ "image/jpeg"
+	_ "image/png"
+)
+
+type imageTest struct {
+	goldenFilename string
+	filename       string
+	tolerance      int
+}
+
+var imageTests = []imageTest{
+	{"testdata/video-001.png", "testdata/video-001.png", 0},
+	// GIF images are restricted to a 256-color palette and the conversion
+	// to GIF loses significant image quality.
+	{"testdata/video-001.png", "testdata/video-001.gif", 64 << 8},
+	{"testdata/video-001.png", "testdata/video-001.interlaced.gif", 64 << 8},
+	{"testdata/video-001.png", "testdata/video-001.5bpp.gif", 128 << 8},
+	// JPEG is a lossy format and hence needs a non-zero tolerance.
+	{"testdata/video-001.png", "testdata/video-001.jpeg", 8 << 8},
+	{"testdata/video-001.png", "testdata/video-001.progressive.jpeg", 8 << 8},
+	// Grayscale images.
+	{"testdata/video-005.gray.png", "testdata/video-005.gray.jpeg", 8 << 8},
+	{"testdata/video-005.gray.png", "testdata/video-005.gray.png", 0},
+}
+
+func decode(filename string) (image.Image, string, error) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, "", err
+	}
+	defer f.Close()
+	return image.Decode(bufio.NewReader(f))
+}
+
+func decodeConfig(filename string) (image.Config, string, error) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return image.Config{}, "", err
+	}
+	defer f.Close()
+	return image.DecodeConfig(bufio.NewReader(f))
+}
+
+func delta(u0, u1 uint32) int {
+	d := int(u0) - int(u1)
+	if d < 0 {
+		return -d
+	}
+	return d
+}
+
+func withinTolerance(c0, c1 color.Color, tolerance int) bool {
+	r0, g0, b0, a0 := c0.RGBA()
+	r1, g1, b1, a1 := c1.RGBA()
+	r := delta(r0, r1)
+	g := delta(g0, g1)
+	b := delta(b0, b1)
+	a := delta(a0, a1)
+	return r <= tolerance && g <= tolerance && b <= tolerance && a <= tolerance
+}
+
+func TestDecode(t *testing.T) {
+	golden := make(map[string]image.Image)
+loop:
+	for _, it := range imageTests {
+		g := golden[it.goldenFilename]
+		if g == nil {
+			var err error
+			g, _, err = decode(it.goldenFilename)
+			if err != nil {
+				t.Errorf("%s: %v", it.goldenFilename, err)
+				continue loop
+			}
+			golden[it.goldenFilename] = g
+		}
+		m, imageFormat, err := decode(it.filename)
+		if err != nil {
+			t.Errorf("%s: %v", it.filename, err)
+			continue loop
+		}
+		b := g.Bounds()
+		if !b.Eq(m.Bounds()) {
+			t.Errorf("%s: want bounds %v got %v", it.filename, b, m.Bounds())
+			continue loop
+		}
+		for y := b.Min.Y; y < b.Max.Y; y++ {
+			for x := b.Min.X; x < b.Max.X; x++ {
+				if !withinTolerance(g.At(x, y), m.At(x, y), it.tolerance) {
+					t.Errorf("%s: at (%d, %d), want %v got %v", it.filename, x, y, g.At(x, y), m.At(x, y))
+					continue loop
+				}
+			}
+		}
+		if imageFormat == "gif" {
+			// Each frame of a GIF can have a frame-local palette override the
+			// GIF-global palette. Thus, image.Decode can yield a different ColorModel
+			// than image.DecodeConfig.
+			continue
+		}
+		c, _, err := decodeConfig(it.filename)
+		if m.ColorModel() != c.ColorModel {
+			t.Errorf("%s: color models differ", it.filename)
+			continue loop
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/draw/bench_test.go b/third_party/gofrontend/libgo/go/image/draw/bench_test.go
new file mode 100644
index 0000000..cc62e25
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/draw/bench_test.go
@@ -0,0 +1,206 @@
+// 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.
+
+package draw
+
+import (
+	"image"
+	"image/color"
+	"testing"
+)
+
+const (
+	dstw, dsth = 640, 480
+	srcw, srch = 400, 300
+)
+
+// bench benchmarks drawing src and mask images onto a dst image with the
+// given op and the color models to create those images from.
+// The created images' pixels are initialized to non-zero values.
+func bench(b *testing.B, dcm, scm, mcm color.Model, op Op) {
+	b.StopTimer()
+
+	var dst Image
+	switch dcm {
+	case color.RGBAModel:
+		dst1 := image.NewRGBA(image.Rect(0, 0, dstw, dsth))
+		for y := 0; y < dsth; y++ {
+			for x := 0; x < dstw; x++ {
+				dst1.SetRGBA(x, y, color.RGBA{
+					uint8(5 * x % 0x100),
+					uint8(7 * y % 0x100),
+					uint8((7*x + 5*y) % 0x100),
+					0xff,
+				})
+			}
+		}
+		dst = dst1
+	case color.RGBA64Model:
+		dst1 := image.NewRGBA64(image.Rect(0, 0, dstw, dsth))
+		for y := 0; y < dsth; y++ {
+			for x := 0; x < dstw; x++ {
+				dst1.SetRGBA64(x, y, color.RGBA64{
+					uint16(53 * x % 0x10000),
+					uint16(59 * y % 0x10000),
+					uint16((59*x + 53*y) % 0x10000),
+					0xffff,
+				})
+			}
+		}
+		dst = dst1
+	default:
+		b.Fatal("unknown destination color model", dcm)
+	}
+
+	var src image.Image
+	switch scm {
+	case nil:
+		src = &image.Uniform{C: color.RGBA{0x11, 0x22, 0x33, 0xff}}
+	case color.RGBAModel:
+		src1 := image.NewRGBA(image.Rect(0, 0, srcw, srch))
+		for y := 0; y < srch; y++ {
+			for x := 0; x < srcw; x++ {
+				src1.SetRGBA(x, y, color.RGBA{
+					uint8(13 * x % 0x80),
+					uint8(11 * y % 0x80),
+					uint8((11*x + 13*y) % 0x80),
+					0x7f,
+				})
+			}
+		}
+		src = src1
+	case color.RGBA64Model:
+		src1 := image.NewRGBA64(image.Rect(0, 0, srcw, srch))
+		for y := 0; y < srch; y++ {
+			for x := 0; x < srcw; x++ {
+				src1.SetRGBA64(x, y, color.RGBA64{
+					uint16(103 * x % 0x8000),
+					uint16(101 * y % 0x8000),
+					uint16((101*x + 103*y) % 0x8000),
+					0x7fff,
+				})
+			}
+		}
+		src = src1
+	case color.NRGBAModel:
+		src1 := image.NewNRGBA(image.Rect(0, 0, srcw, srch))
+		for y := 0; y < srch; y++ {
+			for x := 0; x < srcw; x++ {
+				src1.SetNRGBA(x, y, color.NRGBA{
+					uint8(13 * x % 0x100),
+					uint8(11 * y % 0x100),
+					uint8((11*x + 13*y) % 0x100),
+					0x7f,
+				})
+			}
+		}
+		src = src1
+	case color.YCbCrModel:
+		yy := make([]uint8, srcw*srch)
+		cb := make([]uint8, srcw*srch)
+		cr := make([]uint8, srcw*srch)
+		for i := range yy {
+			yy[i] = uint8(3 * i % 0x100)
+			cb[i] = uint8(5 * i % 0x100)
+			cr[i] = uint8(7 * i % 0x100)
+		}
+		src = &image.YCbCr{
+			Y:              yy,
+			Cb:             cb,
+			Cr:             cr,
+			YStride:        srcw,
+			CStride:        srcw,
+			SubsampleRatio: image.YCbCrSubsampleRatio444,
+			Rect:           image.Rect(0, 0, srcw, srch),
+		}
+	default:
+		b.Fatal("unknown source color model", scm)
+	}
+
+	var mask image.Image
+	switch mcm {
+	case nil:
+		// No-op.
+	case color.AlphaModel:
+		mask1 := image.NewAlpha(image.Rect(0, 0, srcw, srch))
+		for y := 0; y < srch; y++ {
+			for x := 0; x < srcw; x++ {
+				a := uint8((23*x + 29*y) % 0x100)
+				// Glyph masks are typically mostly zero,
+				// so we only set a quarter of mask1's pixels.
+				if a >= 0xc0 {
+					mask1.SetAlpha(x, y, color.Alpha{a})
+				}
+			}
+		}
+		mask = mask1
+	default:
+		b.Fatal("unknown mask color model", mcm)
+	}
+
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		// Scatter the destination rectangle to draw into.
+		x := 3 * i % (dstw - srcw)
+		y := 7 * i % (dsth - srch)
+
+		DrawMask(dst, dst.Bounds().Add(image.Pt(x, y)), src, image.ZP, mask, image.ZP, op)
+	}
+}
+
+// The BenchmarkFoo functions exercise a drawFoo fast-path function in draw.go.
+
+func BenchmarkFillOver(b *testing.B) {
+	bench(b, color.RGBAModel, nil, nil, Over)
+}
+
+func BenchmarkFillSrc(b *testing.B) {
+	bench(b, color.RGBAModel, nil, nil, Src)
+}
+
+func BenchmarkCopyOver(b *testing.B) {
+	bench(b, color.RGBAModel, color.RGBAModel, nil, Over)
+}
+
+func BenchmarkCopySrc(b *testing.B) {
+	bench(b, color.RGBAModel, color.RGBAModel, nil, Src)
+}
+
+func BenchmarkNRGBAOver(b *testing.B) {
+	bench(b, color.RGBAModel, color.NRGBAModel, nil, Over)
+}
+
+func BenchmarkNRGBASrc(b *testing.B) {
+	bench(b, color.RGBAModel, color.NRGBAModel, nil, Src)
+}
+
+func BenchmarkYCbCr(b *testing.B) {
+	bench(b, color.RGBAModel, color.YCbCrModel, nil, Over)
+}
+
+func BenchmarkGlyphOver(b *testing.B) {
+	bench(b, color.RGBAModel, nil, color.AlphaModel, Over)
+}
+
+func BenchmarkRGBA(b *testing.B) {
+	bench(b, color.RGBAModel, color.RGBA64Model, nil, Src)
+}
+
+// The BenchmarkGenericFoo functions exercise the generic, slow-path code.
+
+func BenchmarkGenericOver(b *testing.B) {
+	bench(b, color.RGBA64Model, color.RGBA64Model, nil, Over)
+}
+
+func BenchmarkGenericMaskOver(b *testing.B) {
+	bench(b, color.RGBA64Model, color.RGBA64Model, color.AlphaModel, Over)
+}
+
+func BenchmarkGenericSrc(b *testing.B) {
+	bench(b, color.RGBA64Model, color.RGBA64Model, nil, Src)
+}
+
+func BenchmarkGenericMaskSrc(b *testing.B) {
+	bench(b, color.RGBA64Model, color.RGBA64Model, color.AlphaModel, Src)
+}
diff --git a/third_party/gofrontend/libgo/go/image/draw/clip_test.go b/third_party/gofrontend/libgo/go/image/draw/clip_test.go
new file mode 100644
index 0000000..65381f7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/draw/clip_test.go
@@ -0,0 +1,193 @@
+// 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.
+
+package draw
+
+import (
+	"image"
+	"testing"
+)
+
+type clipTest struct {
+	desc          string
+	r, dr, sr, mr image.Rectangle
+	sp, mp        image.Point
+	nilMask       bool
+	r0            image.Rectangle
+	sp0, mp0      image.Point
+}
+
+var clipTests = []clipTest{
+	// The following tests all have a nil mask.
+	{
+		"basic",
+		image.Rect(0, 0, 100, 100),
+		image.Rect(0, 0, 100, 100),
+		image.Rect(0, 0, 100, 100),
+		image.ZR,
+		image.ZP,
+		image.ZP,
+		true,
+		image.Rect(0, 0, 100, 100),
+		image.ZP,
+		image.ZP,
+	},
+	{
+		"clip dr",
+		image.Rect(0, 0, 100, 100),
+		image.Rect(40, 40, 60, 60),
+		image.Rect(0, 0, 100, 100),
+		image.ZR,
+		image.ZP,
+		image.ZP,
+		true,
+		image.Rect(40, 40, 60, 60),
+		image.Pt(40, 40),
+		image.ZP,
+	},
+	{
+		"clip sr",
+		image.Rect(0, 0, 100, 100),
+		image.Rect(0, 0, 100, 100),
+		image.Rect(20, 20, 80, 80),
+		image.ZR,
+		image.ZP,
+		image.ZP,
+		true,
+		image.Rect(20, 20, 80, 80),
+		image.Pt(20, 20),
+		image.ZP,
+	},
+	{
+		"clip dr and sr",
+		image.Rect(0, 0, 100, 100),
+		image.Rect(0, 0, 50, 100),
+		image.Rect(20, 20, 80, 80),
+		image.ZR,
+		image.ZP,
+		image.ZP,
+		true,
+		image.Rect(20, 20, 50, 80),
+		image.Pt(20, 20),
+		image.ZP,
+	},
+	{
+		"clip dr and sr, sp outside sr (top-left)",
+		image.Rect(0, 0, 100, 100),
+		image.Rect(0, 0, 50, 100),
+		image.Rect(20, 20, 80, 80),
+		image.ZR,
+		image.Pt(15, 8),
+		image.ZP,
+		true,
+		image.Rect(5, 12, 50, 72),
+		image.Pt(20, 20),
+		image.ZP,
+	},
+	{
+		"clip dr and sr, sp outside sr (middle-left)",
+		image.Rect(0, 0, 100, 100),
+		image.Rect(0, 0, 50, 100),
+		image.Rect(20, 20, 80, 80),
+		image.ZR,
+		image.Pt(15, 66),
+		image.ZP,
+		true,
+		image.Rect(5, 0, 50, 14),
+		image.Pt(20, 66),
+		image.ZP,
+	},
+	{
+		"clip dr and sr, sp outside sr (bottom-left)",
+		image.Rect(0, 0, 100, 100),
+		image.Rect(0, 0, 50, 100),
+		image.Rect(20, 20, 80, 80),
+		image.ZR,
+		image.Pt(15, 91),
+		image.ZP,
+		true,
+		image.ZR,
+		image.Pt(15, 91),
+		image.ZP,
+	},
+	{
+		"clip dr and sr, sp inside sr",
+		image.Rect(0, 0, 100, 100),
+		image.Rect(0, 0, 50, 100),
+		image.Rect(20, 20, 80, 80),
+		image.ZR,
+		image.Pt(44, 33),
+		image.ZP,
+		true,
+		image.Rect(0, 0, 36, 47),
+		image.Pt(44, 33),
+		image.ZP,
+	},
+
+	// The following tests all have a non-nil mask.
+	{
+		"basic mask",
+		image.Rect(0, 0, 80, 80),
+		image.Rect(20, 0, 100, 80),
+		image.Rect(0, 0, 50, 49),
+		image.Rect(0, 0, 46, 47),
+		image.ZP,
+		image.ZP,
+		false,
+		image.Rect(20, 0, 46, 47),
+		image.Pt(20, 0),
+		image.Pt(20, 0),
+	},
+	// TODO(nigeltao): write more tests.
+}
+
+func TestClip(t *testing.T) {
+	dst0 := image.NewRGBA(image.Rect(0, 0, 100, 100))
+	src0 := image.NewRGBA(image.Rect(0, 0, 100, 100))
+	mask0 := image.NewRGBA(image.Rect(0, 0, 100, 100))
+	for _, c := range clipTests {
+		dst := dst0.SubImage(c.dr).(*image.RGBA)
+		src := src0.SubImage(c.sr).(*image.RGBA)
+		var mask image.Image
+		if !c.nilMask {
+			mask = mask0.SubImage(c.mr)
+		}
+		r, sp, mp := c.r, c.sp, c.mp
+		clip(dst, &r, src, &sp, mask, &mp)
+
+		// Check that the actual results equal the expected results.
+		if !c.r0.Eq(r) {
+			t.Errorf("%s: clip rectangle want %v got %v", c.desc, c.r0, r)
+			continue
+		}
+		if !c.sp0.Eq(sp) {
+			t.Errorf("%s: sp want %v got %v", c.desc, c.sp0, sp)
+			continue
+		}
+		if !c.nilMask {
+			if !c.mp0.Eq(mp) {
+				t.Errorf("%s: mp want %v got %v", c.desc, c.mp0, mp)
+				continue
+			}
+		}
+
+		// Check that the clipped rectangle is contained by the dst / src / mask
+		// rectangles, in their respective co-ordinate spaces.
+		if !r.In(c.dr) {
+			t.Errorf("%s: c.dr %v does not contain r %v", c.desc, c.dr, r)
+		}
+		// sr is r translated into src's co-ordinate space.
+		sr := r.Add(c.sp.Sub(c.dr.Min))
+		if !sr.In(c.sr) {
+			t.Errorf("%s: c.sr %v does not contain sr %v", c.desc, c.sr, sr)
+		}
+		if !c.nilMask {
+			// mr is r translated into mask's co-ordinate space.
+			mr := r.Add(c.mp.Sub(c.dr.Min))
+			if !mr.In(c.mr) {
+				t.Errorf("%s: c.mr %v does not contain mr %v", c.desc, c.mr, mr)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/draw/draw.go b/third_party/gofrontend/libgo/go/image/draw/draw.go
new file mode 100644
index 0000000..661230e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/draw/draw.go
@@ -0,0 +1,673 @@
+// 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 draw provides image composition functions.
+//
+// See "The Go image/draw package" for an introduction to this package:
+// http://golang.org/doc/articles/image_draw.html
+package draw
+
+import (
+	"image"
+	"image/color"
+)
+
+// m is the maximum color value returned by image.Color.RGBA.
+const m = 1<<16 - 1
+
+// Image is an image.Image with a Set method to change a single pixel.
+type Image interface {
+	image.Image
+	Set(x, y int, c color.Color)
+}
+
+// Quantizer produces a palette for an image.
+type Quantizer interface {
+	// Quantize appends up to cap(p) - len(p) colors to p and returns the
+	// updated palette suitable for converting m to a paletted image.
+	Quantize(p color.Palette, m image.Image) color.Palette
+}
+
+// Op is a Porter-Duff compositing operator.
+type Op int
+
+const (
+	// Over specifies ``(src in mask) over dst''.
+	Over Op = iota
+	// Src specifies ``src in mask''.
+	Src
+)
+
+// Draw implements the Drawer interface by calling the Draw function with this
+// Op.
+func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
+	DrawMask(dst, r, src, sp, nil, image.Point{}, op)
+}
+
+// Drawer contains the Draw method.
+type Drawer interface {
+	// Draw aligns r.Min in dst with sp in src and then replaces the
+	// rectangle r in dst with the result of drawing src on dst.
+	Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
+}
+
+// FloydSteinberg is a Drawer that is the Src Op with Floyd-Steinberg error
+// diffusion.
+var FloydSteinberg Drawer = floydSteinberg{}
+
+type floydSteinberg struct{}
+
+func (floydSteinberg) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
+	clip(dst, &r, src, &sp, nil, nil)
+	if r.Empty() {
+		return
+	}
+	drawPaletted(dst, r, src, sp, true)
+}
+
+// clip clips r against each image's bounds (after translating into the
+// destination image's co-ordinate space) and shifts the points sp and mp by
+// the same amount as the change in r.Min.
+func clip(dst Image, r *image.Rectangle, src image.Image, sp *image.Point, mask image.Image, mp *image.Point) {
+	orig := r.Min
+	*r = r.Intersect(dst.Bounds())
+	*r = r.Intersect(src.Bounds().Add(orig.Sub(*sp)))
+	if mask != nil {
+		*r = r.Intersect(mask.Bounds().Add(orig.Sub(*mp)))
+	}
+	dx := r.Min.X - orig.X
+	dy := r.Min.Y - orig.Y
+	if dx == 0 && dy == 0 {
+		return
+	}
+	(*sp).X += dx
+	(*sp).Y += dy
+	(*mp).X += dx
+	(*mp).Y += dy
+}
+
+func processBackward(dst Image, r image.Rectangle, src image.Image, sp image.Point) bool {
+	return image.Image(dst) == src &&
+		r.Overlaps(r.Add(sp.Sub(r.Min))) &&
+		(sp.Y < r.Min.Y || (sp.Y == r.Min.Y && sp.X < r.Min.X))
+}
+
+// Draw calls DrawMask with a nil mask.
+func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op) {
+	DrawMask(dst, r, src, sp, nil, image.Point{}, op)
+}
+
+// DrawMask aligns r.Min in dst with sp in src and mp in mask and then replaces the rectangle r
+// in dst with the result of a Porter-Duff composition. A nil mask is treated as opaque.
+func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
+	clip(dst, &r, src, &sp, mask, &mp)
+	if r.Empty() {
+		return
+	}
+
+	// Fast paths for special cases. If none of them apply, then we fall back to a general but slow implementation.
+	switch dst0 := dst.(type) {
+	case *image.RGBA:
+		if op == Over {
+			if mask == nil {
+				switch src0 := src.(type) {
+				case *image.Uniform:
+					drawFillOver(dst0, r, src0)
+					return
+				case *image.RGBA:
+					drawCopyOver(dst0, r, src0, sp)
+					return
+				case *image.NRGBA:
+					drawNRGBAOver(dst0, r, src0, sp)
+					return
+				case *image.YCbCr:
+					if drawYCbCr(dst0, r, src0, sp) {
+						return
+					}
+				}
+			} else if mask0, ok := mask.(*image.Alpha); ok {
+				switch src0 := src.(type) {
+				case *image.Uniform:
+					drawGlyphOver(dst0, r, src0, mask0, mp)
+					return
+				}
+			}
+		} else {
+			if mask == nil {
+				switch src0 := src.(type) {
+				case *image.Uniform:
+					drawFillSrc(dst0, r, src0)
+					return
+				case *image.RGBA:
+					drawCopySrc(dst0, r, src0, sp)
+					return
+				case *image.NRGBA:
+					drawNRGBASrc(dst0, r, src0, sp)
+					return
+				case *image.YCbCr:
+					if drawYCbCr(dst0, r, src0, sp) {
+						return
+					}
+				}
+			}
+		}
+		drawRGBA(dst0, r, src, sp, mask, mp, op)
+		return
+	case *image.Paletted:
+		if op == Src && mask == nil && !processBackward(dst, r, src, sp) {
+			drawPaletted(dst0, r, src, sp, false)
+		}
+	}
+
+	x0, x1, dx := r.Min.X, r.Max.X, 1
+	y0, y1, dy := r.Min.Y, r.Max.Y, 1
+	if processBackward(dst, r, src, sp) {
+		x0, x1, dx = x1-1, x0-1, -1
+		y0, y1, dy = y1-1, y0-1, -1
+	}
+
+	var out color.RGBA64
+	sy := sp.Y + y0 - r.Min.Y
+	my := mp.Y + y0 - r.Min.Y
+	for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
+		sx := sp.X + x0 - r.Min.X
+		mx := mp.X + x0 - r.Min.X
+		for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx {
+			ma := uint32(m)
+			if mask != nil {
+				_, _, _, ma = mask.At(mx, my).RGBA()
+			}
+			switch {
+			case ma == 0:
+				if op == Over {
+					// No-op.
+				} else {
+					dst.Set(x, y, color.Transparent)
+				}
+			case ma == m && op == Src:
+				dst.Set(x, y, src.At(sx, sy))
+			default:
+				sr, sg, sb, sa := src.At(sx, sy).RGBA()
+				if op == Over {
+					dr, dg, db, da := dst.At(x, y).RGBA()
+					a := m - (sa * ma / m)
+					out.R = uint16((dr*a + sr*ma) / m)
+					out.G = uint16((dg*a + sg*ma) / m)
+					out.B = uint16((db*a + sb*ma) / m)
+					out.A = uint16((da*a + sa*ma) / m)
+				} else {
+					out.R = uint16(sr * ma / m)
+					out.G = uint16(sg * ma / m)
+					out.B = uint16(sb * ma / m)
+					out.A = uint16(sa * ma / m)
+				}
+				// The third argument is &out instead of out (and out is
+				// declared outside of the inner loop) to avoid the implicit
+				// conversion to color.Color here allocating memory in the
+				// inner loop if sizeof(color.RGBA64) > sizeof(uintptr).
+				dst.Set(x, y, &out)
+			}
+		}
+	}
+}
+
+func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
+	sr, sg, sb, sa := src.RGBA()
+	// The 0x101 is here for the same reason as in drawRGBA.
+	a := (m - sa) * 0x101
+	i0 := dst.PixOffset(r.Min.X, r.Min.Y)
+	i1 := i0 + r.Dx()*4
+	for y := r.Min.Y; y != r.Max.Y; y++ {
+		for i := i0; i < i1; i += 4 {
+			dr := uint32(dst.Pix[i+0])
+			dg := uint32(dst.Pix[i+1])
+			db := uint32(dst.Pix[i+2])
+			da := uint32(dst.Pix[i+3])
+
+			dst.Pix[i+0] = uint8((dr*a/m + sr) >> 8)
+			dst.Pix[i+1] = uint8((dg*a/m + sg) >> 8)
+			dst.Pix[i+2] = uint8((db*a/m + sb) >> 8)
+			dst.Pix[i+3] = uint8((da*a/m + sa) >> 8)
+		}
+		i0 += dst.Stride
+		i1 += dst.Stride
+	}
+}
+
+func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
+	sr, sg, sb, sa := src.RGBA()
+	// The built-in copy function is faster than a straightforward for loop to fill the destination with
+	// the color, but copy requires a slice source. We therefore use a for loop to fill the first row, and
+	// then use the first row as the slice source for the remaining rows.
+	i0 := dst.PixOffset(r.Min.X, r.Min.Y)
+	i1 := i0 + r.Dx()*4
+	for i := i0; i < i1; i += 4 {
+		dst.Pix[i+0] = uint8(sr >> 8)
+		dst.Pix[i+1] = uint8(sg >> 8)
+		dst.Pix[i+2] = uint8(sb >> 8)
+		dst.Pix[i+3] = uint8(sa >> 8)
+	}
+	firstRow := dst.Pix[i0:i1]
+	for y := r.Min.Y + 1; y < r.Max.Y; y++ {
+		i0 += dst.Stride
+		i1 += dst.Stride
+		copy(dst.Pix[i0:i1], firstRow)
+	}
+}
+
+func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
+	dx, dy := r.Dx(), r.Dy()
+	d0 := dst.PixOffset(r.Min.X, r.Min.Y)
+	s0 := src.PixOffset(sp.X, sp.Y)
+	var (
+		ddelta, sdelta int
+		i0, i1, idelta int
+	)
+	if r.Min.Y < sp.Y || r.Min.Y == sp.Y && r.Min.X <= sp.X {
+		ddelta = dst.Stride
+		sdelta = src.Stride
+		i0, i1, idelta = 0, dx*4, +4
+	} else {
+		// If the source start point is higher than the destination start point, or equal height but to the left,
+		// then we compose the rows in right-to-left, bottom-up order instead of left-to-right, top-down.
+		d0 += (dy - 1) * dst.Stride
+		s0 += (dy - 1) * src.Stride
+		ddelta = -dst.Stride
+		sdelta = -src.Stride
+		i0, i1, idelta = (dx-1)*4, -4, -4
+	}
+	for ; dy > 0; dy-- {
+		dpix := dst.Pix[d0:]
+		spix := src.Pix[s0:]
+		for i := i0; i != i1; i += idelta {
+			sr := uint32(spix[i+0]) * 0x101
+			sg := uint32(spix[i+1]) * 0x101
+			sb := uint32(spix[i+2]) * 0x101
+			sa := uint32(spix[i+3]) * 0x101
+
+			dr := uint32(dpix[i+0])
+			dg := uint32(dpix[i+1])
+			db := uint32(dpix[i+2])
+			da := uint32(dpix[i+3])
+
+			// The 0x101 is here for the same reason as in drawRGBA.
+			a := (m - sa) * 0x101
+
+			dpix[i+0] = uint8((dr*a/m + sr) >> 8)
+			dpix[i+1] = uint8((dg*a/m + sg) >> 8)
+			dpix[i+2] = uint8((db*a/m + sb) >> 8)
+			dpix[i+3] = uint8((da*a/m + sa) >> 8)
+		}
+		d0 += ddelta
+		s0 += sdelta
+	}
+}
+
+func drawCopySrc(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
+	n, dy := 4*r.Dx(), r.Dy()
+	d0 := dst.PixOffset(r.Min.X, r.Min.Y)
+	s0 := src.PixOffset(sp.X, sp.Y)
+	var ddelta, sdelta int
+	if r.Min.Y <= sp.Y {
+		ddelta = dst.Stride
+		sdelta = src.Stride
+	} else {
+		// If the source start point is higher than the destination start point, then we compose the rows
+		// in bottom-up order instead of top-down. Unlike the drawCopyOver function, we don't have to
+		// check the x co-ordinates because the built-in copy function can handle overlapping slices.
+		d0 += (dy - 1) * dst.Stride
+		s0 += (dy - 1) * src.Stride
+		ddelta = -dst.Stride
+		sdelta = -src.Stride
+	}
+	for ; dy > 0; dy-- {
+		copy(dst.Pix[d0:d0+n], src.Pix[s0:s0+n])
+		d0 += ddelta
+		s0 += sdelta
+	}
+}
+
+func drawNRGBAOver(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image.Point) {
+	i0 := (r.Min.X - dst.Rect.Min.X) * 4
+	i1 := (r.Max.X - dst.Rect.Min.X) * 4
+	si0 := (sp.X - src.Rect.Min.X) * 4
+	yMax := r.Max.Y - dst.Rect.Min.Y
+
+	y := r.Min.Y - dst.Rect.Min.Y
+	sy := sp.Y - src.Rect.Min.Y
+	for ; y != yMax; y, sy = y+1, sy+1 {
+		dpix := dst.Pix[y*dst.Stride:]
+		spix := src.Pix[sy*src.Stride:]
+
+		for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
+			// Convert from non-premultiplied color to pre-multiplied color.
+			sa := uint32(spix[si+3]) * 0x101
+			sr := uint32(spix[si+0]) * sa / 0xff
+			sg := uint32(spix[si+1]) * sa / 0xff
+			sb := uint32(spix[si+2]) * sa / 0xff
+
+			dr := uint32(dpix[i+0])
+			dg := uint32(dpix[i+1])
+			db := uint32(dpix[i+2])
+			da := uint32(dpix[i+3])
+
+			// The 0x101 is here for the same reason as in drawRGBA.
+			a := (m - sa) * 0x101
+
+			dpix[i+0] = uint8((dr*a/m + sr) >> 8)
+			dpix[i+1] = uint8((dg*a/m + sg) >> 8)
+			dpix[i+2] = uint8((db*a/m + sb) >> 8)
+			dpix[i+3] = uint8((da*a/m + sa) >> 8)
+		}
+	}
+}
+
+func drawNRGBASrc(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image.Point) {
+	i0 := (r.Min.X - dst.Rect.Min.X) * 4
+	i1 := (r.Max.X - dst.Rect.Min.X) * 4
+	si0 := (sp.X - src.Rect.Min.X) * 4
+	yMax := r.Max.Y - dst.Rect.Min.Y
+
+	y := r.Min.Y - dst.Rect.Min.Y
+	sy := sp.Y - src.Rect.Min.Y
+	for ; y != yMax; y, sy = y+1, sy+1 {
+		dpix := dst.Pix[y*dst.Stride:]
+		spix := src.Pix[sy*src.Stride:]
+
+		for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
+			// Convert from non-premultiplied color to pre-multiplied color.
+			sa := uint32(spix[si+3]) * 0x101
+			sr := uint32(spix[si+0]) * sa / 0xff
+			sg := uint32(spix[si+1]) * sa / 0xff
+			sb := uint32(spix[si+2]) * sa / 0xff
+
+			dpix[i+0] = uint8(sr >> 8)
+			dpix[i+1] = uint8(sg >> 8)
+			dpix[i+2] = uint8(sb >> 8)
+			dpix[i+3] = uint8(sa >> 8)
+		}
+	}
+}
+
+func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) (ok bool) {
+	// An image.YCbCr is always fully opaque, and so if the mask is implicitly nil
+	// (i.e. fully opaque) then the op is effectively always Src.
+	x0 := (r.Min.X - dst.Rect.Min.X) * 4
+	x1 := (r.Max.X - dst.Rect.Min.X) * 4
+	y0 := r.Min.Y - dst.Rect.Min.Y
+	y1 := r.Max.Y - dst.Rect.Min.Y
+	switch src.SubsampleRatio {
+	case image.YCbCrSubsampleRatio444:
+		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
+			dpix := dst.Pix[y*dst.Stride:]
+			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
+			ci := (sy-src.Rect.Min.Y)*src.CStride + (sp.X - src.Rect.Min.X)
+			for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
+				rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
+				dpix[x+0] = rr
+				dpix[x+1] = gg
+				dpix[x+2] = bb
+				dpix[x+3] = 255
+			}
+		}
+	case image.YCbCrSubsampleRatio422:
+		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
+			dpix := dst.Pix[y*dst.Stride:]
+			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
+			ciBase := (sy-src.Rect.Min.Y)*src.CStride - src.Rect.Min.X/2
+			for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
+				ci := ciBase + sx/2
+				rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
+				dpix[x+0] = rr
+				dpix[x+1] = gg
+				dpix[x+2] = bb
+				dpix[x+3] = 255
+			}
+		}
+	case image.YCbCrSubsampleRatio420:
+		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
+			dpix := dst.Pix[y*dst.Stride:]
+			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
+			ciBase := (sy/2-src.Rect.Min.Y/2)*src.CStride - src.Rect.Min.X/2
+			for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
+				ci := ciBase + sx/2
+				rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
+				dpix[x+0] = rr
+				dpix[x+1] = gg
+				dpix[x+2] = bb
+				dpix[x+3] = 255
+			}
+		}
+	case image.YCbCrSubsampleRatio440:
+		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
+			dpix := dst.Pix[y*dst.Stride:]
+			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
+			ci := (sy/2-src.Rect.Min.Y/2)*src.CStride + (sp.X - src.Rect.Min.X)
+			for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
+				rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
+				dpix[x+0] = rr
+				dpix[x+1] = gg
+				dpix[x+2] = bb
+				dpix[x+3] = 255
+			}
+		}
+	default:
+		return false
+	}
+	return true
+}
+
+func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) {
+	i0 := dst.PixOffset(r.Min.X, r.Min.Y)
+	i1 := i0 + r.Dx()*4
+	mi0 := mask.PixOffset(mp.X, mp.Y)
+	sr, sg, sb, sa := src.RGBA()
+	for y, my := r.Min.Y, mp.Y; y != r.Max.Y; y, my = y+1, my+1 {
+		for i, mi := i0, mi0; i < i1; i, mi = i+4, mi+1 {
+			ma := uint32(mask.Pix[mi])
+			if ma == 0 {
+				continue
+			}
+			ma |= ma << 8
+
+			dr := uint32(dst.Pix[i+0])
+			dg := uint32(dst.Pix[i+1])
+			db := uint32(dst.Pix[i+2])
+			da := uint32(dst.Pix[i+3])
+
+			// The 0x101 is here for the same reason as in drawRGBA.
+			a := (m - (sa * ma / m)) * 0x101
+
+			dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
+			dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
+			dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
+			dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
+		}
+		i0 += dst.Stride
+		i1 += dst.Stride
+		mi0 += mask.Stride
+	}
+}
+
+func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
+	x0, x1, dx := r.Min.X, r.Max.X, 1
+	y0, y1, dy := r.Min.Y, r.Max.Y, 1
+	if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
+		if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
+			x0, x1, dx = x1-1, x0-1, -1
+			y0, y1, dy = y1-1, y0-1, -1
+		}
+	}
+
+	sy := sp.Y + y0 - r.Min.Y
+	my := mp.Y + y0 - r.Min.Y
+	sx0 := sp.X + x0 - r.Min.X
+	mx0 := mp.X + x0 - r.Min.X
+	sx1 := sx0 + (x1 - x0)
+	i0 := dst.PixOffset(x0, y0)
+	di := dx * 4
+	for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
+		for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
+			ma := uint32(m)
+			if mask != nil {
+				_, _, _, ma = mask.At(mx, my).RGBA()
+			}
+			sr, sg, sb, sa := src.At(sx, sy).RGBA()
+			if op == Over {
+				dr := uint32(dst.Pix[i+0])
+				dg := uint32(dst.Pix[i+1])
+				db := uint32(dst.Pix[i+2])
+				da := uint32(dst.Pix[i+3])
+
+				// dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255].
+				// We work in 16-bit color, and so would normally do:
+				// dr |= dr << 8
+				// and similarly for dg, db and da, but instead we multiply a
+				// (which is a 16-bit color, ranging in [0,65535]) by 0x101.
+				// This yields the same result, but is fewer arithmetic operations.
+				a := (m - (sa * ma / m)) * 0x101
+
+				dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
+				dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
+				dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
+				dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
+
+			} else {
+				dst.Pix[i+0] = uint8(sr * ma / m >> 8)
+				dst.Pix[i+1] = uint8(sg * ma / m >> 8)
+				dst.Pix[i+2] = uint8(sb * ma / m >> 8)
+				dst.Pix[i+3] = uint8(sa * ma / m >> 8)
+			}
+		}
+		i0 += dy * dst.Stride
+	}
+}
+
+// clamp clamps i to the interval [0, 0xffff].
+func clamp(i int32) int32 {
+	if i < 0 {
+		return 0
+	}
+	if i > 0xffff {
+		return 0xffff
+	}
+	return i
+}
+
+func drawPaletted(dst Image, r image.Rectangle, src image.Image, sp image.Point, floydSteinberg bool) {
+	// TODO(nigeltao): handle the case where the dst and src overlap.
+	// Does it even make sense to try and do Floyd-Steinberg whilst
+	// walking the image backward (right-to-left bottom-to-top)?
+
+	// If dst is an *image.Paletted, we have a fast path for dst.Set and
+	// dst.At. The dst.Set equivalent is a batch version of the algorithm
+	// used by color.Palette's Index method in image/color/color.go, plus
+	// optional Floyd-Steinberg error diffusion.
+	palette, pix, stride := [][3]int32(nil), []byte(nil), 0
+	if p, ok := dst.(*image.Paletted); ok {
+		palette = make([][3]int32, len(p.Palette))
+		for i, col := range p.Palette {
+			r, g, b, _ := col.RGBA()
+			palette[i][0] = int32(r)
+			palette[i][1] = int32(g)
+			palette[i][2] = int32(b)
+		}
+		pix, stride = p.Pix[p.PixOffset(r.Min.X, r.Min.Y):], p.Stride
+	}
+
+	// quantErrorCurr and quantErrorNext are the Floyd-Steinberg quantization
+	// errors that have been propagated to the pixels in the current and next
+	// rows. The +2 simplifies calculation near the edges.
+	var quantErrorCurr, quantErrorNext [][3]int32
+	if floydSteinberg {
+		quantErrorCurr = make([][3]int32, r.Dx()+2)
+		quantErrorNext = make([][3]int32, r.Dx()+2)
+	}
+
+	// Loop over each source pixel.
+	out := color.RGBA64{A: 0xffff}
+	for y := 0; y != r.Dy(); y++ {
+		for x := 0; x != r.Dx(); x++ {
+			// er, eg and eb are the pixel's R,G,B values plus the
+			// optional Floyd-Steinberg error.
+			sr, sg, sb, _ := src.At(sp.X+x, sp.Y+y).RGBA()
+			er, eg, eb := int32(sr), int32(sg), int32(sb)
+			if floydSteinberg {
+				er = clamp(er + quantErrorCurr[x+1][0]/16)
+				eg = clamp(eg + quantErrorCurr[x+1][1]/16)
+				eb = clamp(eb + quantErrorCurr[x+1][2]/16)
+			}
+
+			if palette != nil {
+				// Find the closest palette color in Euclidean R,G,B space: the
+				// one that minimizes sum-squared-difference. We shift by 1 bit
+				// to avoid potential uint32 overflow in sum-squared-difference.
+				// TODO(nigeltao): consider smarter algorithms.
+				bestIndex, bestSSD := 0, uint32(1<<32-1)
+				for index, p := range palette {
+					delta := (er - p[0]) >> 1
+					ssd := uint32(delta * delta)
+					delta = (eg - p[1]) >> 1
+					ssd += uint32(delta * delta)
+					delta = (eb - p[2]) >> 1
+					ssd += uint32(delta * delta)
+					if ssd < bestSSD {
+						bestIndex, bestSSD = index, ssd
+						if ssd == 0 {
+							break
+						}
+					}
+				}
+				pix[y*stride+x] = byte(bestIndex)
+
+				if !floydSteinberg {
+					continue
+				}
+				er -= int32(palette[bestIndex][0])
+				eg -= int32(palette[bestIndex][1])
+				eb -= int32(palette[bestIndex][2])
+
+			} else {
+				out.R = uint16(er)
+				out.G = uint16(eg)
+				out.B = uint16(eb)
+				// The third argument is &out instead of out (and out is
+				// declared outside of the inner loop) to avoid the implicit
+				// conversion to color.Color here allocating memory in the
+				// inner loop if sizeof(color.RGBA64) > sizeof(uintptr).
+				dst.Set(r.Min.X+x, r.Min.Y+y, &out)
+
+				if !floydSteinberg {
+					continue
+				}
+				sr, sg, sb, _ = dst.At(r.Min.X+x, r.Min.Y+y).RGBA()
+				er -= int32(sr)
+				eg -= int32(sg)
+				eb -= int32(sb)
+			}
+
+			// Propagate the Floyd-Steinberg quantization error.
+			quantErrorNext[x+0][0] += er * 3
+			quantErrorNext[x+0][1] += eg * 3
+			quantErrorNext[x+0][2] += eb * 3
+			quantErrorNext[x+1][0] += er * 5
+			quantErrorNext[x+1][1] += eg * 5
+			quantErrorNext[x+1][2] += eb * 5
+			quantErrorNext[x+2][0] += er * 1
+			quantErrorNext[x+2][1] += eg * 1
+			quantErrorNext[x+2][2] += eb * 1
+			quantErrorCurr[x+2][0] += er * 7
+			quantErrorCurr[x+2][1] += eg * 7
+			quantErrorCurr[x+2][2] += eb * 7
+		}
+
+		// Recycle the quantization error buffers.
+		if floydSteinberg {
+			quantErrorCurr, quantErrorNext = quantErrorNext, quantErrorCurr
+			for i := range quantErrorNext {
+				quantErrorNext[i] = [3]int32{}
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/draw/draw_test.go b/third_party/gofrontend/libgo/go/image/draw/draw_test.go
new file mode 100644
index 0000000..0dd7fbd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/draw/draw_test.go
@@ -0,0 +1,429 @@
+// Copyright 2010 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 draw
+
+import (
+	"image"
+	"image/color"
+	"image/png"
+	"os"
+	"testing"
+)
+
+func eq(c0, c1 color.Color) bool {
+	r0, g0, b0, a0 := c0.RGBA()
+	r1, g1, b1, a1 := c1.RGBA()
+	return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
+}
+
+func fillBlue(alpha int) image.Image {
+	return image.NewUniform(color.RGBA{0, 0, uint8(alpha), uint8(alpha)})
+}
+
+func fillAlpha(alpha int) image.Image {
+	return image.NewUniform(color.Alpha{uint8(alpha)})
+}
+
+func vgradGreen(alpha int) image.Image {
+	m := image.NewRGBA(image.Rect(0, 0, 16, 16))
+	for y := 0; y < 16; y++ {
+		for x := 0; x < 16; x++ {
+			m.Set(x, y, color.RGBA{0, uint8(y * alpha / 15), 0, uint8(alpha)})
+		}
+	}
+	return m
+}
+
+func vgradAlpha(alpha int) image.Image {
+	m := image.NewAlpha(image.Rect(0, 0, 16, 16))
+	for y := 0; y < 16; y++ {
+		for x := 0; x < 16; x++ {
+			m.Set(x, y, color.Alpha{uint8(y * alpha / 15)})
+		}
+	}
+	return m
+}
+
+func vgradGreenNRGBA(alpha int) image.Image {
+	m := image.NewNRGBA(image.Rect(0, 0, 16, 16))
+	for y := 0; y < 16; y++ {
+		for x := 0; x < 16; x++ {
+			m.Set(x, y, color.RGBA{0, uint8(y * 0x11), 0, uint8(alpha)})
+		}
+	}
+	return m
+}
+
+func vgradCr() image.Image {
+	m := &image.YCbCr{
+		Y:              make([]byte, 16*16),
+		Cb:             make([]byte, 16*16),
+		Cr:             make([]byte, 16*16),
+		YStride:        16,
+		CStride:        16,
+		SubsampleRatio: image.YCbCrSubsampleRatio444,
+		Rect:           image.Rect(0, 0, 16, 16),
+	}
+	for y := 0; y < 16; y++ {
+		for x := 0; x < 16; x++ {
+			m.Cr[y*m.CStride+x] = uint8(y * 0x11)
+		}
+	}
+	return m
+}
+
+func hgradRed(alpha int) Image {
+	m := image.NewRGBA(image.Rect(0, 0, 16, 16))
+	for y := 0; y < 16; y++ {
+		for x := 0; x < 16; x++ {
+			m.Set(x, y, color.RGBA{uint8(x * alpha / 15), 0, 0, uint8(alpha)})
+		}
+	}
+	return m
+}
+
+func gradYellow(alpha int) Image {
+	m := image.NewRGBA(image.Rect(0, 0, 16, 16))
+	for y := 0; y < 16; y++ {
+		for x := 0; x < 16; x++ {
+			m.Set(x, y, color.RGBA{uint8(x * alpha / 15), uint8(y * alpha / 15), 0, uint8(alpha)})
+		}
+	}
+	return m
+}
+
+type drawTest struct {
+	desc     string
+	src      image.Image
+	mask     image.Image
+	op       Op
+	expected color.Color
+}
+
+var drawTests = []drawTest{
+	// Uniform mask (0% opaque).
+	{"nop", vgradGreen(255), fillAlpha(0), Over, color.RGBA{136, 0, 0, 255}},
+	{"clear", vgradGreen(255), fillAlpha(0), Src, color.RGBA{0, 0, 0, 0}},
+	// Uniform mask (100%, 75%, nil) and uniform source.
+	// At (x, y) == (8, 8):
+	// The destination pixel is {136, 0, 0, 255}.
+	// The source pixel is {0, 0, 90, 90}.
+	{"fill", fillBlue(90), fillAlpha(255), Over, color.RGBA{88, 0, 90, 255}},
+	{"fillSrc", fillBlue(90), fillAlpha(255), Src, color.RGBA{0, 0, 90, 90}},
+	{"fillAlpha", fillBlue(90), fillAlpha(192), Over, color.RGBA{100, 0, 68, 255}},
+	{"fillAlphaSrc", fillBlue(90), fillAlpha(192), Src, color.RGBA{0, 0, 68, 68}},
+	{"fillNil", fillBlue(90), nil, Over, color.RGBA{88, 0, 90, 255}},
+	{"fillNilSrc", fillBlue(90), nil, Src, color.RGBA{0, 0, 90, 90}},
+	// Uniform mask (100%, 75%, nil) and variable source.
+	// At (x, y) == (8, 8):
+	// The destination pixel is {136, 0, 0, 255}.
+	// The source pixel is {0, 48, 0, 90}.
+	{"copy", vgradGreen(90), fillAlpha(255), Over, color.RGBA{88, 48, 0, 255}},
+	{"copySrc", vgradGreen(90), fillAlpha(255), Src, color.RGBA{0, 48, 0, 90}},
+	{"copyAlpha", vgradGreen(90), fillAlpha(192), Over, color.RGBA{100, 36, 0, 255}},
+	{"copyAlphaSrc", vgradGreen(90), fillAlpha(192), Src, color.RGBA{0, 36, 0, 68}},
+	{"copyNil", vgradGreen(90), nil, Over, color.RGBA{88, 48, 0, 255}},
+	{"copyNilSrc", vgradGreen(90), nil, Src, color.RGBA{0, 48, 0, 90}},
+	// Uniform mask (100%, 75%, nil) and variable NRGBA source.
+	// At (x, y) == (8, 8):
+	// The destination pixel is {136, 0, 0, 255}.
+	// The source pixel is {0, 136, 0, 90} in NRGBA-space, which is {0, 48, 0, 90} in RGBA-space.
+	// The result pixel is different than in the "copy*" test cases because of rounding errors.
+	{"nrgba", vgradGreenNRGBA(90), fillAlpha(255), Over, color.RGBA{88, 46, 0, 255}},
+	{"nrgbaSrc", vgradGreenNRGBA(90), fillAlpha(255), Src, color.RGBA{0, 46, 0, 90}},
+	{"nrgbaAlpha", vgradGreenNRGBA(90), fillAlpha(192), Over, color.RGBA{100, 34, 0, 255}},
+	{"nrgbaAlphaSrc", vgradGreenNRGBA(90), fillAlpha(192), Src, color.RGBA{0, 34, 0, 68}},
+	{"nrgbaNil", vgradGreenNRGBA(90), nil, Over, color.RGBA{88, 46, 0, 255}},
+	{"nrgbaNilSrc", vgradGreenNRGBA(90), nil, Src, color.RGBA{0, 46, 0, 90}},
+	// Uniform mask (100%, 75%, nil) and variable YCbCr source.
+	// At (x, y) == (8, 8):
+	// The destination pixel is {136, 0, 0, 255}.
+	// The source pixel is {0, 0, 136} in YCbCr-space, which is {11, 38, 0, 255} in RGB-space.
+	{"ycbcr", vgradCr(), fillAlpha(255), Over, color.RGBA{11, 38, 0, 255}},
+	{"ycbcrSrc", vgradCr(), fillAlpha(255), Src, color.RGBA{11, 38, 0, 255}},
+	{"ycbcrAlpha", vgradCr(), fillAlpha(192), Over, color.RGBA{42, 28, 0, 255}},
+	{"ycbcrAlphaSrc", vgradCr(), fillAlpha(192), Src, color.RGBA{8, 28, 0, 192}},
+	{"ycbcrNil", vgradCr(), nil, Over, color.RGBA{11, 38, 0, 255}},
+	{"ycbcrNilSrc", vgradCr(), nil, Src, color.RGBA{11, 38, 0, 255}},
+	// Variable mask and variable source.
+	// At (x, y) == (8, 8):
+	// The destination pixel is {136, 0, 0, 255}.
+	// The source pixel is {0, 0, 255, 255}.
+	// The mask pixel's alpha is 102, or 40%.
+	{"generic", fillBlue(255), vgradAlpha(192), Over, color.RGBA{81, 0, 102, 255}},
+	{"genericSrc", fillBlue(255), vgradAlpha(192), Src, color.RGBA{0, 0, 102, 102}},
+}
+
+func makeGolden(dst image.Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) image.Image {
+	// Since golden is a newly allocated image, we don't have to check if the
+	// input source and mask images and the output golden image overlap.
+	b := dst.Bounds()
+	sb := src.Bounds()
+	mb := image.Rect(-1e9, -1e9, 1e9, 1e9)
+	if mask != nil {
+		mb = mask.Bounds()
+	}
+	golden := image.NewRGBA(image.Rect(0, 0, b.Max.X, b.Max.Y))
+	for y := r.Min.Y; y < r.Max.Y; y++ {
+		sy := y + sp.Y - r.Min.Y
+		my := y + mp.Y - r.Min.Y
+		for x := r.Min.X; x < r.Max.X; x++ {
+			if !(image.Pt(x, y).In(b)) {
+				continue
+			}
+			sx := x + sp.X - r.Min.X
+			if !(image.Pt(sx, sy).In(sb)) {
+				continue
+			}
+			mx := x + mp.X - r.Min.X
+			if !(image.Pt(mx, my).In(mb)) {
+				continue
+			}
+
+			const M = 1<<16 - 1
+			var dr, dg, db, da uint32
+			if op == Over {
+				dr, dg, db, da = dst.At(x, y).RGBA()
+			}
+			sr, sg, sb, sa := src.At(sx, sy).RGBA()
+			ma := uint32(M)
+			if mask != nil {
+				_, _, _, ma = mask.At(mx, my).RGBA()
+			}
+			a := M - (sa * ma / M)
+			golden.Set(x, y, color.RGBA64{
+				uint16((dr*a + sr*ma) / M),
+				uint16((dg*a + sg*ma) / M),
+				uint16((db*a + sb*ma) / M),
+				uint16((da*a + sa*ma) / M),
+			})
+		}
+	}
+	return golden.SubImage(b)
+}
+
+func TestDraw(t *testing.T) {
+	rr := []image.Rectangle{
+		image.Rect(0, 0, 0, 0),
+		image.Rect(0, 0, 16, 16),
+		image.Rect(3, 5, 12, 10),
+		image.Rect(0, 0, 9, 9),
+		image.Rect(8, 8, 16, 16),
+		image.Rect(8, 0, 9, 16),
+		image.Rect(0, 8, 16, 9),
+		image.Rect(8, 8, 9, 9),
+		image.Rect(8, 8, 8, 8),
+	}
+	for _, r := range rr {
+	loop:
+		for _, test := range drawTests {
+			dst := hgradRed(255).(*image.RGBA).SubImage(r).(Image)
+			// Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation.
+			golden := makeGolden(dst, image.Rect(0, 0, 16, 16), test.src, image.ZP, test.mask, image.ZP, test.op)
+			b := dst.Bounds()
+			if !b.Eq(golden.Bounds()) {
+				t.Errorf("draw %v %s: bounds %v versus %v", r, test.desc, dst.Bounds(), golden.Bounds())
+				continue
+			}
+			// Draw the same combination onto the actual dst using the optimized DrawMask implementation.
+			DrawMask(dst, image.Rect(0, 0, 16, 16), test.src, image.ZP, test.mask, image.ZP, test.op)
+			if image.Pt(8, 8).In(r) {
+				// Check that the resultant pixel at (8, 8) matches what we expect
+				// (the expected value can be verified by hand).
+				if !eq(dst.At(8, 8), test.expected) {
+					t.Errorf("draw %v %s: at (8, 8) %v versus %v", r, test.desc, dst.At(8, 8), test.expected)
+					continue
+				}
+			}
+			// Check that the resultant dst image matches the golden output.
+			for y := b.Min.Y; y < b.Max.Y; y++ {
+				for x := b.Min.X; x < b.Max.X; x++ {
+					if !eq(dst.At(x, y), golden.At(x, y)) {
+						t.Errorf("draw %v %s: at (%d, %d), %v versus golden %v", r, test.desc, x, y, dst.At(x, y), golden.At(x, y))
+						continue loop
+					}
+				}
+			}
+		}
+	}
+}
+
+func TestDrawOverlap(t *testing.T) {
+	for _, op := range []Op{Over, Src} {
+		for yoff := -2; yoff <= 2; yoff++ {
+		loop:
+			for xoff := -2; xoff <= 2; xoff++ {
+				m := gradYellow(127).(*image.RGBA)
+				dst := m.SubImage(image.Rect(5, 5, 10, 10)).(*image.RGBA)
+				src := m.SubImage(image.Rect(5+xoff, 5+yoff, 10+xoff, 10+yoff)).(*image.RGBA)
+				b := dst.Bounds()
+				// Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation.
+				golden := makeGolden(dst, b, src, src.Bounds().Min, nil, image.ZP, op)
+				if !b.Eq(golden.Bounds()) {
+					t.Errorf("drawOverlap xoff=%d,yoff=%d: bounds %v versus %v", xoff, yoff, dst.Bounds(), golden.Bounds())
+					continue
+				}
+				// Draw the same combination onto the actual dst using the optimized DrawMask implementation.
+				DrawMask(dst, b, src, src.Bounds().Min, nil, image.ZP, op)
+				// Check that the resultant dst image matches the golden output.
+				for y := b.Min.Y; y < b.Max.Y; y++ {
+					for x := b.Min.X; x < b.Max.X; x++ {
+						if !eq(dst.At(x, y), golden.At(x, y)) {
+							t.Errorf("drawOverlap xoff=%d,yoff=%d: at (%d, %d), %v versus golden %v", xoff, yoff, x, y, dst.At(x, y), golden.At(x, y))
+							continue loop
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+// TestNonZeroSrcPt checks drawing with a non-zero src point parameter.
+func TestNonZeroSrcPt(t *testing.T) {
+	a := image.NewRGBA(image.Rect(0, 0, 1, 1))
+	b := image.NewRGBA(image.Rect(0, 0, 2, 2))
+	b.Set(0, 0, color.RGBA{0, 0, 0, 5})
+	b.Set(1, 0, color.RGBA{0, 0, 5, 5})
+	b.Set(0, 1, color.RGBA{0, 5, 0, 5})
+	b.Set(1, 1, color.RGBA{5, 0, 0, 5})
+	Draw(a, image.Rect(0, 0, 1, 1), b, image.Pt(1, 1), Over)
+	if !eq(color.RGBA{5, 0, 0, 5}, a.At(0, 0)) {
+		t.Errorf("non-zero src pt: want %v got %v", color.RGBA{5, 0, 0, 5}, a.At(0, 0))
+	}
+}
+
+func TestFill(t *testing.T) {
+	rr := []image.Rectangle{
+		image.Rect(0, 0, 0, 0),
+		image.Rect(0, 0, 40, 30),
+		image.Rect(10, 0, 40, 30),
+		image.Rect(0, 20, 40, 30),
+		image.Rect(10, 20, 40, 30),
+		image.Rect(10, 20, 15, 25),
+		image.Rect(10, 0, 35, 30),
+		image.Rect(0, 15, 40, 16),
+		image.Rect(24, 24, 25, 25),
+		image.Rect(23, 23, 26, 26),
+		image.Rect(22, 22, 27, 27),
+		image.Rect(21, 21, 28, 28),
+		image.Rect(20, 20, 29, 29),
+	}
+	for _, r := range rr {
+		m := image.NewRGBA(image.Rect(0, 0, 40, 30)).SubImage(r).(*image.RGBA)
+		b := m.Bounds()
+		c := color.RGBA{11, 0, 0, 255}
+		src := &image.Uniform{C: c}
+		check := func(desc string) {
+			for y := b.Min.Y; y < b.Max.Y; y++ {
+				for x := b.Min.X; x < b.Max.X; x++ {
+					if !eq(c, m.At(x, y)) {
+						t.Errorf("%s fill: at (%d, %d), sub-image bounds=%v: want %v got %v", desc, x, y, r, c, m.At(x, y))
+						return
+					}
+				}
+			}
+		}
+		// Draw 1 pixel at a time.
+		for y := b.Min.Y; y < b.Max.Y; y++ {
+			for x := b.Min.X; x < b.Max.X; x++ {
+				DrawMask(m, image.Rect(x, y, x+1, y+1), src, image.ZP, nil, image.ZP, Src)
+			}
+		}
+		check("pixel")
+		// Draw 1 row at a time.
+		c = color.RGBA{0, 22, 0, 255}
+		src = &image.Uniform{C: c}
+		for y := b.Min.Y; y < b.Max.Y; y++ {
+			DrawMask(m, image.Rect(b.Min.X, y, b.Max.X, y+1), src, image.ZP, nil, image.ZP, Src)
+		}
+		check("row")
+		// Draw 1 column at a time.
+		c = color.RGBA{0, 0, 33, 255}
+		src = &image.Uniform{C: c}
+		for x := b.Min.X; x < b.Max.X; x++ {
+			DrawMask(m, image.Rect(x, b.Min.Y, x+1, b.Max.Y), src, image.ZP, nil, image.ZP, Src)
+		}
+		check("column")
+		// Draw the whole image at once.
+		c = color.RGBA{44, 55, 66, 77}
+		src = &image.Uniform{C: c}
+		DrawMask(m, b, src, image.ZP, nil, image.ZP, Src)
+		check("whole")
+	}
+}
+
+// TestFloydSteinbergCheckerboard tests that the result of Floyd-Steinberg
+// error diffusion of a uniform 50% gray source image with a black-and-white
+// palette is a checkerboard pattern.
+func TestFloydSteinbergCheckerboard(t *testing.T) {
+	b := image.Rect(0, 0, 640, 480)
+	// We can't represent 50% exactly, but 0x7fff / 0xffff is close enough.
+	src := &image.Uniform{color.Gray16{0x7fff}}
+	dst := image.NewPaletted(b, color.Palette{color.Black, color.White})
+	FloydSteinberg.Draw(dst, b, src, image.Point{})
+	nErr := 0
+	for y := b.Min.Y; y < b.Max.Y; y++ {
+		for x := b.Min.X; x < b.Max.X; x++ {
+			got := dst.Pix[dst.PixOffset(x, y)]
+			want := uint8(x+y) % 2
+			if got != want {
+				t.Errorf("at (%d, %d): got %d, want %d", x, y, got, want)
+				if nErr++; nErr == 10 {
+					t.Fatal("there may be more errors")
+				}
+			}
+		}
+	}
+}
+
+// embeddedPaletted is an Image that behaves like an *image.Paletted but whose
+// type is not *image.Paletted.
+type embeddedPaletted struct {
+	*image.Paletted
+}
+
+// TestPaletted tests that the drawPaletted function behaves the same
+// regardless of whether dst is an *image.Paletted.
+func TestPaletted(t *testing.T) {
+	f, err := os.Open("../testdata/video-001.png")
+	if err != nil {
+		t.Fatalf("open: %v", err)
+	}
+	defer f.Close()
+	src, err := png.Decode(f)
+	if err != nil {
+		t.Fatalf("decode: %v", err)
+	}
+	b := src.Bounds()
+
+	cgaPalette := color.Palette{
+		color.RGBA{0x00, 0x00, 0x00, 0xff},
+		color.RGBA{0x55, 0xff, 0xff, 0xff},
+		color.RGBA{0xff, 0x55, 0xff, 0xff},
+		color.RGBA{0xff, 0xff, 0xff, 0xff},
+	}
+	drawers := map[string]Drawer{
+		"src":             Src,
+		"floyd-steinberg": FloydSteinberg,
+	}
+
+loop:
+	for dName, d := range drawers {
+		dst0 := image.NewPaletted(b, cgaPalette)
+		dst1 := image.NewPaletted(b, cgaPalette)
+		d.Draw(dst0, b, src, image.Point{})
+		d.Draw(embeddedPaletted{dst1}, b, src, image.Point{})
+		for y := b.Min.Y; y < b.Max.Y; y++ {
+			for x := b.Min.X; x < b.Max.X; x++ {
+				if !eq(dst0.At(x, y), dst1.At(x, y)) {
+					t.Errorf("%s: at (%d, %d), %v versus %v",
+						dName, x, y, dst0.At(x, y), dst1.At(x, y))
+					continue loop
+				}
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/format.go b/third_party/gofrontend/libgo/go/image/format.go
new file mode 100644
index 0000000..3668de4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/format.go
@@ -0,0 +1,100 @@
+// Copyright 2010 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 image
+
+import (
+	"bufio"
+	"errors"
+	"io"
+)
+
+// ErrFormat indicates that decoding encountered an unknown format.
+var ErrFormat = errors.New("image: unknown format")
+
+// A format holds an image format's name, magic header and how to decode it.
+type format struct {
+	name, magic  string
+	decode       func(io.Reader) (Image, error)
+	decodeConfig func(io.Reader) (Config, error)
+}
+
+// Formats is the list of registered formats.
+var formats []format
+
+// RegisterFormat registers an image format for use by Decode.
+// Name is the name of the format, like "jpeg" or "png".
+// Magic is the magic prefix that identifies the format's encoding. The magic
+// string can contain "?" wildcards that each match any one byte.
+// Decode is the function that decodes the encoded image.
+// DecodeConfig is the function that decodes just its configuration.
+func RegisterFormat(name, magic string, decode func(io.Reader) (Image, error), decodeConfig func(io.Reader) (Config, error)) {
+	formats = append(formats, format{name, magic, decode, decodeConfig})
+}
+
+// A reader is an io.Reader that can also peek ahead.
+type reader interface {
+	io.Reader
+	Peek(int) ([]byte, error)
+}
+
+// asReader converts an io.Reader to a reader.
+func asReader(r io.Reader) reader {
+	if rr, ok := r.(reader); ok {
+		return rr
+	}
+	return bufio.NewReader(r)
+}
+
+// Match reports whether magic matches b. Magic may contain "?" wildcards.
+func match(magic string, b []byte) bool {
+	if len(magic) != len(b) {
+		return false
+	}
+	for i, c := range b {
+		if magic[i] != c && magic[i] != '?' {
+			return false
+		}
+	}
+	return true
+}
+
+// Sniff determines the format of r's data.
+func sniff(r reader) format {
+	for _, f := range formats {
+		b, err := r.Peek(len(f.magic))
+		if err == nil && match(f.magic, b) {
+			return f
+		}
+	}
+	return format{}
+}
+
+// Decode decodes an image that has been encoded in a registered format.
+// The string returned is the format name used during format registration.
+// Format registration is typically done by an init function in the codec-
+// specific package.
+func Decode(r io.Reader) (Image, string, error) {
+	rr := asReader(r)
+	f := sniff(rr)
+	if f.decode == nil {
+		return nil, "", ErrFormat
+	}
+	m, err := f.decode(rr)
+	return m, f.name, err
+}
+
+// DecodeConfig decodes the color model and dimensions of an image that has
+// been encoded in a registered format. The string returned is the format name
+// used during format registration. Format registration is typically done by
+// an init function in the codec-specific package.
+func DecodeConfig(r io.Reader) (Config, string, error) {
+	rr := asReader(r)
+	f := sniff(rr)
+	if f.decodeConfig == nil {
+		return Config{}, "", ErrFormat
+	}
+	c, err := f.decodeConfig(rr)
+	return c, f.name, err
+}
diff --git a/third_party/gofrontend/libgo/go/image/geom.go b/third_party/gofrontend/libgo/go/image/geom.go
new file mode 100644
index 0000000..6ebaf67
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/geom.go
@@ -0,0 +1,234 @@
+// Copyright 2010 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 image
+
+import (
+	"strconv"
+)
+
+// A Point is an X, Y coordinate pair. The axes increase right and down.
+type Point struct {
+	X, Y int
+}
+
+// String returns a string representation of p like "(3,4)".
+func (p Point) String() string {
+	return "(" + strconv.Itoa(p.X) + "," + strconv.Itoa(p.Y) + ")"
+}
+
+// Add returns the vector p+q.
+func (p Point) Add(q Point) Point {
+	return Point{p.X + q.X, p.Y + q.Y}
+}
+
+// Sub returns the vector p-q.
+func (p Point) Sub(q Point) Point {
+	return Point{p.X - q.X, p.Y - q.Y}
+}
+
+// Mul returns the vector p*k.
+func (p Point) Mul(k int) Point {
+	return Point{p.X * k, p.Y * k}
+}
+
+// Div returns the vector p/k.
+func (p Point) Div(k int) Point {
+	return Point{p.X / k, p.Y / k}
+}
+
+// In reports whether p is in r.
+func (p Point) In(r Rectangle) bool {
+	return r.Min.X <= p.X && p.X < r.Max.X &&
+		r.Min.Y <= p.Y && p.Y < r.Max.Y
+}
+
+// Mod returns the point q in r such that p.X-q.X is a multiple of r's width
+// and p.Y-q.Y is a multiple of r's height.
+func (p Point) Mod(r Rectangle) Point {
+	w, h := r.Dx(), r.Dy()
+	p = p.Sub(r.Min)
+	p.X = p.X % w
+	if p.X < 0 {
+		p.X += w
+	}
+	p.Y = p.Y % h
+	if p.Y < 0 {
+		p.Y += h
+	}
+	return p.Add(r.Min)
+}
+
+// Eq reports whether p and q are equal.
+func (p Point) Eq(q Point) bool {
+	return p.X == q.X && p.Y == q.Y
+}
+
+// ZP is the zero Point.
+var ZP Point
+
+// Pt is shorthand for Point{X, Y}.
+func Pt(X, Y int) Point {
+	return Point{X, Y}
+}
+
+// A Rectangle contains the points with Min.X <= X < Max.X, Min.Y <= Y < Max.Y.
+// It is well-formed if Min.X <= Max.X and likewise for Y. Points are always
+// well-formed. A rectangle's methods always return well-formed outputs for
+// well-formed inputs.
+type Rectangle struct {
+	Min, Max Point
+}
+
+// String returns a string representation of r like "(3,4)-(6,5)".
+func (r Rectangle) String() string {
+	return r.Min.String() + "-" + r.Max.String()
+}
+
+// Dx returns r's width.
+func (r Rectangle) Dx() int {
+	return r.Max.X - r.Min.X
+}
+
+// Dy returns r's height.
+func (r Rectangle) Dy() int {
+	return r.Max.Y - r.Min.Y
+}
+
+// Size returns r's width and height.
+func (r Rectangle) Size() Point {
+	return Point{
+		r.Max.X - r.Min.X,
+		r.Max.Y - r.Min.Y,
+	}
+}
+
+// Add returns the rectangle r translated by p.
+func (r Rectangle) Add(p Point) Rectangle {
+	return Rectangle{
+		Point{r.Min.X + p.X, r.Min.Y + p.Y},
+		Point{r.Max.X + p.X, r.Max.Y + p.Y},
+	}
+}
+
+// Sub returns the rectangle r translated by -p.
+func (r Rectangle) Sub(p Point) Rectangle {
+	return Rectangle{
+		Point{r.Min.X - p.X, r.Min.Y - p.Y},
+		Point{r.Max.X - p.X, r.Max.Y - p.Y},
+	}
+}
+
+// Inset returns the rectangle r inset by n, which may be negative. If either
+// of r's dimensions is less than 2*n then an empty rectangle near the center
+// of r will be returned.
+func (r Rectangle) Inset(n int) Rectangle {
+	if r.Dx() < 2*n {
+		r.Min.X = (r.Min.X + r.Max.X) / 2
+		r.Max.X = r.Min.X
+	} else {
+		r.Min.X += n
+		r.Max.X -= n
+	}
+	if r.Dy() < 2*n {
+		r.Min.Y = (r.Min.Y + r.Max.Y) / 2
+		r.Max.Y = r.Min.Y
+	} else {
+		r.Min.Y += n
+		r.Max.Y -= n
+	}
+	return r
+}
+
+// Intersect returns the largest rectangle contained by both r and s. If the
+// two rectangles do not overlap then the zero rectangle will be returned.
+func (r Rectangle) Intersect(s Rectangle) Rectangle {
+	if r.Min.X < s.Min.X {
+		r.Min.X = s.Min.X
+	}
+	if r.Min.Y < s.Min.Y {
+		r.Min.Y = s.Min.Y
+	}
+	if r.Max.X > s.Max.X {
+		r.Max.X = s.Max.X
+	}
+	if r.Max.Y > s.Max.Y {
+		r.Max.Y = s.Max.Y
+	}
+	if r.Min.X > r.Max.X || r.Min.Y > r.Max.Y {
+		return ZR
+	}
+	return r
+}
+
+// Union returns the smallest rectangle that contains both r and s.
+func (r Rectangle) Union(s Rectangle) Rectangle {
+	if r.Min.X > s.Min.X {
+		r.Min.X = s.Min.X
+	}
+	if r.Min.Y > s.Min.Y {
+		r.Min.Y = s.Min.Y
+	}
+	if r.Max.X < s.Max.X {
+		r.Max.X = s.Max.X
+	}
+	if r.Max.Y < s.Max.Y {
+		r.Max.Y = s.Max.Y
+	}
+	return r
+}
+
+// Empty reports whether the rectangle contains no points.
+func (r Rectangle) Empty() bool {
+	return r.Min.X >= r.Max.X || r.Min.Y >= r.Max.Y
+}
+
+// Eq reports whether r and s are equal.
+func (r Rectangle) Eq(s Rectangle) bool {
+	return r.Min.X == s.Min.X && r.Min.Y == s.Min.Y &&
+		r.Max.X == s.Max.X && r.Max.Y == s.Max.Y
+}
+
+// Overlaps reports whether r and s have a non-empty intersection.
+func (r Rectangle) Overlaps(s Rectangle) bool {
+	return r.Min.X < s.Max.X && s.Min.X < r.Max.X &&
+		r.Min.Y < s.Max.Y && s.Min.Y < r.Max.Y
+}
+
+// In reports whether every point in r is in s.
+func (r Rectangle) In(s Rectangle) bool {
+	if r.Empty() {
+		return true
+	}
+	// Note that r.Max is an exclusive bound for r, so that r.In(s)
+	// does not require that r.Max.In(s).
+	return s.Min.X <= r.Min.X && r.Max.X <= s.Max.X &&
+		s.Min.Y <= r.Min.Y && r.Max.Y <= s.Max.Y
+}
+
+// Canon returns the canonical version of r. The returned rectangle has minimum
+// and maximum coordinates swapped if necessary so that it is well-formed.
+func (r Rectangle) Canon() Rectangle {
+	if r.Max.X < r.Min.X {
+		r.Min.X, r.Max.X = r.Max.X, r.Min.X
+	}
+	if r.Max.Y < r.Min.Y {
+		r.Min.Y, r.Max.Y = r.Max.Y, r.Min.Y
+	}
+	return r
+}
+
+// ZR is the zero Rectangle.
+var ZR Rectangle
+
+// Rect is shorthand for Rectangle{Pt(x0, y0), Pt(x1, y1)}.
+func Rect(x0, y0, x1, y1 int) Rectangle {
+	if x0 > x1 {
+		x0, x1 = x1, x0
+	}
+	if y0 > y1 {
+		y0, y1 = y1, y0
+	}
+	return Rectangle{Point{x0, y0}, Point{x1, y1}}
+}
diff --git a/third_party/gofrontend/libgo/go/image/gif/reader.go b/third_party/gofrontend/libgo/go/image/gif/reader.go
new file mode 100644
index 0000000..926710a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/gif/reader.go
@@ -0,0 +1,460 @@
+// 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.
+
+// Package gif implements a GIF image decoder and encoder.
+//
+// The GIF specification is at http://www.w3.org/Graphics/GIF/spec-gif89a.txt.
+package gif
+
+import (
+	"bufio"
+	"compress/lzw"
+	"errors"
+	"fmt"
+	"image"
+	"image/color"
+	"io"
+)
+
+var (
+	errNotEnough = errors.New("gif: not enough image data")
+	errTooMuch   = errors.New("gif: too much image data")
+	errBadPixel  = errors.New("gif: invalid pixel value")
+)
+
+// If the io.Reader does not also have ReadByte, then decode will introduce its own buffering.
+type reader interface {
+	io.Reader
+	io.ByteReader
+}
+
+// Masks etc.
+const (
+	// Fields.
+	fColorMapFollows = 1 << 7
+
+	// Image fields.
+	ifLocalColorTable = 1 << 7
+	ifInterlace       = 1 << 6
+	ifPixelSizeMask   = 7
+
+	// Graphic control flags.
+	gcTransparentColorSet = 1 << 0
+)
+
+// Section indicators.
+const (
+	sExtension       = 0x21
+	sImageDescriptor = 0x2C
+	sTrailer         = 0x3B
+)
+
+// Extensions.
+const (
+	eText           = 0x01 // Plain Text
+	eGraphicControl = 0xF9 // Graphic Control
+	eComment        = 0xFE // Comment
+	eApplication    = 0xFF // Application
+)
+
+// decoder is the type used to decode a GIF file.
+type decoder struct {
+	r reader
+
+	// From header.
+	vers            string
+	width           int
+	height          int
+	flags           byte
+	headerFields    byte
+	backgroundIndex byte
+	loopCount       int
+	delayTime       int
+
+	// Unused from header.
+	aspect byte
+
+	// From image descriptor.
+	imageFields byte
+
+	// From graphics control.
+	transparentIndex    byte
+	hasTransparentIndex bool
+
+	// Computed.
+	pixelSize      uint
+	globalColorMap color.Palette
+
+	// Used when decoding.
+	delay []int
+	image []*image.Paletted
+	tmp   [1024]byte // must be at least 768 so we can read color map
+}
+
+// blockReader parses the block structure of GIF image data, which
+// comprises (n, (n bytes)) blocks, with 1 <= n <= 255.  It is the
+// reader given to the LZW decoder, which is thus immune to the
+// blocking.  After the LZW decoder completes, there will be a 0-byte
+// block remaining (0, ()), which is consumed when checking that the
+// blockReader is exhausted.
+type blockReader struct {
+	r     reader
+	slice []byte
+	err   error
+	tmp   [256]byte
+}
+
+func (b *blockReader) Read(p []byte) (int, error) {
+	if b.err != nil {
+		return 0, b.err
+	}
+	if len(p) == 0 {
+		return 0, nil
+	}
+	if len(b.slice) == 0 {
+		var blockLen uint8
+		blockLen, b.err = b.r.ReadByte()
+		if b.err != nil {
+			return 0, b.err
+		}
+		if blockLen == 0 {
+			b.err = io.EOF
+			return 0, b.err
+		}
+		b.slice = b.tmp[0:blockLen]
+		if _, b.err = io.ReadFull(b.r, b.slice); b.err != nil {
+			return 0, b.err
+		}
+	}
+	n := copy(p, b.slice)
+	b.slice = b.slice[n:]
+	return n, nil
+}
+
+// decode reads a GIF image from r and stores the result in d.
+func (d *decoder) decode(r io.Reader, configOnly bool) error {
+	// Add buffering if r does not provide ReadByte.
+	if rr, ok := r.(reader); ok {
+		d.r = rr
+	} else {
+		d.r = bufio.NewReader(r)
+	}
+
+	err := d.readHeaderAndScreenDescriptor()
+	if err != nil {
+		return err
+	}
+	if configOnly {
+		return nil
+	}
+
+	if d.headerFields&fColorMapFollows != 0 {
+		if d.globalColorMap, err = d.readColorMap(); err != nil {
+			return err
+		}
+	}
+
+	for {
+		c, err := d.r.ReadByte()
+		if err != nil {
+			return err
+		}
+		switch c {
+		case sExtension:
+			if err = d.readExtension(); err != nil {
+				return err
+			}
+
+		case sImageDescriptor:
+			m, err := d.newImageFromDescriptor()
+			if err != nil {
+				return err
+			}
+			if d.imageFields&fColorMapFollows != 0 {
+				m.Palette, err = d.readColorMap()
+				if err != nil {
+					return err
+				}
+			} else {
+				m.Palette = d.globalColorMap
+			}
+			if d.hasTransparentIndex && int(d.transparentIndex) < len(m.Palette) {
+				m.Palette[d.transparentIndex] = color.RGBA{}
+			}
+			litWidth, err := d.r.ReadByte()
+			if err != nil {
+				return err
+			}
+			if litWidth < 2 || litWidth > 8 {
+				return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth)
+			}
+			// A wonderfully Go-like piece of magic.
+			br := &blockReader{r: d.r}
+			lzwr := lzw.NewReader(br, lzw.LSB, int(litWidth))
+			defer lzwr.Close()
+			if _, err = io.ReadFull(lzwr, m.Pix); err != nil {
+				if err != io.ErrUnexpectedEOF {
+					return err
+				}
+				return errNotEnough
+			}
+			// Both lzwr and br should be exhausted. Reading from them
+			// should yield (0, io.EOF).
+			if n, err := lzwr.Read(d.tmp[:1]); n != 0 || err != io.EOF {
+				if err != nil {
+					return err
+				}
+				return errTooMuch
+			}
+			if n, err := br.Read(d.tmp[:1]); n != 0 || err != io.EOF {
+				if err != nil {
+					return err
+				}
+				return errTooMuch
+			}
+
+			// Check that the color indexes are inside the palette.
+			if len(m.Palette) < 256 {
+				for _, pixel := range m.Pix {
+					if int(pixel) >= len(m.Palette) {
+						return errBadPixel
+					}
+				}
+			}
+
+			// Undo the interlacing if necessary.
+			if d.imageFields&ifInterlace != 0 {
+				uninterlace(m)
+			}
+
+			d.image = append(d.image, m)
+			d.delay = append(d.delay, d.delayTime)
+			// The GIF89a spec, Section 23 (Graphic Control Extension) says:
+			// "The scope of this extension is the first graphic rendering block
+			// to follow." We therefore reset the GCE fields to zero.
+			d.delayTime = 0
+			d.hasTransparentIndex = false
+
+		case sTrailer:
+			if len(d.image) == 0 {
+				return io.ErrUnexpectedEOF
+			}
+			return nil
+
+		default:
+			return fmt.Errorf("gif: unknown block type: 0x%.2x", c)
+		}
+	}
+}
+
+func (d *decoder) readHeaderAndScreenDescriptor() error {
+	_, err := io.ReadFull(d.r, d.tmp[0:13])
+	if err != nil {
+		return err
+	}
+	d.vers = string(d.tmp[0:6])
+	if d.vers != "GIF87a" && d.vers != "GIF89a" {
+		return fmt.Errorf("gif: can't recognize format %s", d.vers)
+	}
+	d.width = int(d.tmp[6]) + int(d.tmp[7])<<8
+	d.height = int(d.tmp[8]) + int(d.tmp[9])<<8
+	d.headerFields = d.tmp[10]
+	d.backgroundIndex = d.tmp[11]
+	d.aspect = d.tmp[12]
+	d.loopCount = -1
+	d.pixelSize = uint(d.headerFields&7) + 1
+	return nil
+}
+
+func (d *decoder) readColorMap() (color.Palette, error) {
+	if d.pixelSize > 8 {
+		return nil, fmt.Errorf("gif: can't handle %d bits per pixel", d.pixelSize)
+	}
+	numColors := 1 << d.pixelSize
+	if d.imageFields&ifLocalColorTable != 0 {
+		numColors = 1 << ((d.imageFields & ifPixelSizeMask) + 1)
+	}
+	numValues := 3 * numColors
+	_, err := io.ReadFull(d.r, d.tmp[0:numValues])
+	if err != nil {
+		return nil, fmt.Errorf("gif: short read on color map: %s", err)
+	}
+	colorMap := make(color.Palette, numColors)
+	j := 0
+	for i := range colorMap {
+		colorMap[i] = color.RGBA{d.tmp[j+0], d.tmp[j+1], d.tmp[j+2], 0xFF}
+		j += 3
+	}
+	return colorMap, nil
+}
+
+func (d *decoder) readExtension() error {
+	extension, err := d.r.ReadByte()
+	if err != nil {
+		return err
+	}
+	size := 0
+	switch extension {
+	case eText:
+		size = 13
+	case eGraphicControl:
+		return d.readGraphicControl()
+	case eComment:
+		// nothing to do but read the data.
+	case eApplication:
+		b, err := d.r.ReadByte()
+		if err != nil {
+			return err
+		}
+		// The spec requires size be 11, but Adobe sometimes uses 10.
+		size = int(b)
+	default:
+		return fmt.Errorf("gif: unknown extension 0x%.2x", extension)
+	}
+	if size > 0 {
+		if _, err := io.ReadFull(d.r, d.tmp[0:size]); err != nil {
+			return err
+		}
+	}
+
+	// Application Extension with "NETSCAPE2.0" as string and 1 in data means
+	// this extension defines a loop count.
+	if extension == eApplication && string(d.tmp[:size]) == "NETSCAPE2.0" {
+		n, err := d.readBlock()
+		if n == 0 || err != nil {
+			return err
+		}
+		if n == 3 && d.tmp[0] == 1 {
+			d.loopCount = int(d.tmp[1]) | int(d.tmp[2])<<8
+		}
+	}
+	for {
+		n, err := d.readBlock()
+		if n == 0 || err != nil {
+			return err
+		}
+	}
+}
+
+func (d *decoder) readGraphicControl() error {
+	if _, err := io.ReadFull(d.r, d.tmp[0:6]); err != nil {
+		return fmt.Errorf("gif: can't read graphic control: %s", err)
+	}
+	d.flags = d.tmp[1]
+	d.delayTime = int(d.tmp[2]) | int(d.tmp[3])<<8
+	if d.flags&gcTransparentColorSet != 0 {
+		d.transparentIndex = d.tmp[4]
+		d.hasTransparentIndex = true
+	}
+	return nil
+}
+
+func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) {
+	if _, err := io.ReadFull(d.r, d.tmp[0:9]); err != nil {
+		return nil, fmt.Errorf("gif: can't read image descriptor: %s", err)
+	}
+	left := int(d.tmp[0]) + int(d.tmp[1])<<8
+	top := int(d.tmp[2]) + int(d.tmp[3])<<8
+	width := int(d.tmp[4]) + int(d.tmp[5])<<8
+	height := int(d.tmp[6]) + int(d.tmp[7])<<8
+	d.imageFields = d.tmp[8]
+
+	// The GIF89a spec, Section 20 (Image Descriptor) says:
+	// "Each image must fit within the boundaries of the Logical
+	// Screen, as defined in the Logical Screen Descriptor."
+	bounds := image.Rect(left, top, left+width, top+height)
+	if bounds != bounds.Intersect(image.Rect(0, 0, d.width, d.height)) {
+		return nil, errors.New("gif: frame bounds larger than image bounds")
+	}
+	return image.NewPaletted(bounds, nil), nil
+}
+
+func (d *decoder) readBlock() (int, error) {
+	n, err := d.r.ReadByte()
+	if n == 0 || err != nil {
+		return 0, err
+	}
+	return io.ReadFull(d.r, d.tmp[0:n])
+}
+
+// interlaceScan defines the ordering for a pass of the interlace algorithm.
+type interlaceScan struct {
+	skip, start int
+}
+
+// interlacing represents the set of scans in an interlaced GIF image.
+var interlacing = []interlaceScan{
+	{8, 0}, // Group 1 : Every 8th. row, starting with row 0.
+	{8, 4}, // Group 2 : Every 8th. row, starting with row 4.
+	{4, 2}, // Group 3 : Every 4th. row, starting with row 2.
+	{2, 1}, // Group 4 : Every 2nd. row, starting with row 1.
+}
+
+// uninterlace rearranges the pixels in m to account for interlaced input.
+func uninterlace(m *image.Paletted) {
+	var nPix []uint8
+	dx := m.Bounds().Dx()
+	dy := m.Bounds().Dy()
+	nPix = make([]uint8, dx*dy)
+	offset := 0 // steps through the input by sequential scan lines.
+	for _, pass := range interlacing {
+		nOffset := pass.start * dx // steps through the output as defined by pass.
+		for y := pass.start; y < dy; y += pass.skip {
+			copy(nPix[nOffset:nOffset+dx], m.Pix[offset:offset+dx])
+			offset += dx
+			nOffset += dx * pass.skip
+		}
+	}
+	m.Pix = nPix
+}
+
+// Decode reads a GIF image from r and returns the first embedded
+// image as an image.Image.
+func Decode(r io.Reader) (image.Image, error) {
+	var d decoder
+	if err := d.decode(r, false); err != nil {
+		return nil, err
+	}
+	return d.image[0], nil
+}
+
+// GIF represents the possibly multiple images stored in a GIF file.
+type GIF struct {
+	Image     []*image.Paletted // The successive images.
+	Delay     []int             // The successive delay times, one per frame, in 100ths of a second.
+	LoopCount int               // The loop count.
+}
+
+// DecodeAll reads a GIF image from r and returns the sequential frames
+// and timing information.
+func DecodeAll(r io.Reader) (*GIF, error) {
+	var d decoder
+	if err := d.decode(r, false); err != nil {
+		return nil, err
+	}
+	gif := &GIF{
+		Image:     d.image,
+		LoopCount: d.loopCount,
+		Delay:     d.delay,
+	}
+	return gif, nil
+}
+
+// DecodeConfig returns the global color model and dimensions of a GIF image
+// without decoding the entire image.
+func DecodeConfig(r io.Reader) (image.Config, error) {
+	var d decoder
+	if err := d.decode(r, true); err != nil {
+		return image.Config{}, err
+	}
+	return image.Config{
+		ColorModel: d.globalColorMap,
+		Width:      d.width,
+		Height:     d.height,
+	}, nil
+}
+
+func init() {
+	image.RegisterFormat("gif", "GIF8?a", Decode, DecodeConfig)
+}
diff --git a/third_party/gofrontend/libgo/go/image/gif/reader_test.go b/third_party/gofrontend/libgo/go/image/gif/reader_test.go
new file mode 100644
index 0000000..fc2041e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/gif/reader_test.go
@@ -0,0 +1,201 @@
+// Copyright 2013 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 gif
+
+import (
+	"bytes"
+	"compress/lzw"
+	"image"
+	"image/color"
+	"reflect"
+	"testing"
+)
+
+// header, palette and trailer are parts of a valid 2x1 GIF image.
+const (
+	headerStr = "GIF89a" +
+		"\x02\x00\x01\x00" + // width=2, height=1
+		"\x80\x00\x00" // headerFields=(a color map of 2 pixels), backgroundIndex, aspect
+	paletteStr = "\x10\x20\x30\x40\x50\x60" // the color map, also known as a palette
+	trailerStr = "\x3b"
+)
+
+func TestDecode(t *testing.T) {
+	// lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes.
+	lzwEncode := func(n int) []byte {
+		b := &bytes.Buffer{}
+		w := lzw.NewWriter(b, lzw.LSB, 2)
+		w.Write(make([]byte, n))
+		w.Close()
+		return b.Bytes()
+	}
+
+	testCases := []struct {
+		nPix    int  // The number of pixels in the image data.
+		extra   bool // Whether to write an extra block after the LZW-encoded data.
+		wantErr error
+	}{
+		{0, false, errNotEnough},
+		{1, false, errNotEnough},
+		{2, false, nil},
+		{2, true, errTooMuch},
+		{3, false, errTooMuch},
+	}
+	for _, tc := range testCases {
+		b := &bytes.Buffer{}
+		b.WriteString(headerStr)
+		b.WriteString(paletteStr)
+		// Write an image with bounds 2x1 but tc.nPix pixels. If tc.nPix != 2
+		// then this should result in an invalid GIF image. First, write a
+		// magic 0x2c (image descriptor) byte, bounds=(0,0)-(2,1), a flags
+		// byte, and 2-bit LZW literals.
+		b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
+		if tc.nPix > 0 {
+			enc := lzwEncode(tc.nPix)
+			if len(enc) > 0xff {
+				t.Errorf("nPix=%d, extra=%t: compressed length %d is too large", tc.nPix, tc.extra, len(enc))
+				continue
+			}
+			b.WriteByte(byte(len(enc)))
+			b.Write(enc)
+		}
+		if tc.extra {
+			b.WriteString("\x01\x02") // A 1-byte payload with an 0x02 byte.
+		}
+		b.WriteByte(0x00) // An empty block signifies the end of the image data.
+		b.WriteString(trailerStr)
+
+		got, err := Decode(b)
+		if err != tc.wantErr {
+			t.Errorf("nPix=%d, extra=%t\ngot  %v\nwant %v", tc.nPix, tc.extra, err, tc.wantErr)
+		}
+
+		if tc.wantErr != nil {
+			continue
+		}
+		want := &image.Paletted{
+			Pix:    []uint8{0, 0},
+			Stride: 2,
+			Rect:   image.Rect(0, 0, 2, 1),
+			Palette: color.Palette{
+				color.RGBA{0x10, 0x20, 0x30, 0xff},
+				color.RGBA{0x40, 0x50, 0x60, 0xff},
+			},
+		}
+		if !reflect.DeepEqual(got, want) {
+			t.Errorf("nPix=%d, extra=%t\ngot  %v\nwant %v", tc.nPix, tc.extra, got, want)
+		}
+	}
+}
+
+// testGIF is a simple GIF that we can modify to test different scenarios.
+var testGIF = []byte{
+	'G', 'I', 'F', '8', '9', 'a',
+	1, 0, 1, 0, // w=1, h=1 (6)
+	128, 0, 0, // headerFields, bg, aspect (10)
+	0, 0, 0, 1, 1, 1, // color map and graphics control (13)
+	0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0xff, 0x00, // (19)
+	// frame 1 (0,0 - 1,1)
+	0x2c,
+	0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x01, 0x00, // (32)
+	0x00,
+	0x02, 0x02, 0x4c, 0x01, 0x00, // lzw pixels
+	// trailer
+	0x3b,
+}
+
+func try(t *testing.T, b []byte, want string) {
+	_, err := DecodeAll(bytes.NewReader(b))
+	var got string
+	if err != nil {
+		got = err.Error()
+	}
+	if got != want {
+		t.Fatalf("got %v, want %v", got, want)
+	}
+}
+
+func TestBounds(t *testing.T) {
+	// Make a local copy of testGIF.
+	gif := make([]byte, len(testGIF))
+	copy(gif, testGIF)
+	// Make the bounds too big, just by one.
+	gif[32] = 2
+	want := "gif: frame bounds larger than image bounds"
+	try(t, gif, want)
+
+	// Make the bounds too small; does not trigger bounds
+	// check, but now there's too much data.
+	gif[32] = 0
+	want = "gif: too much image data"
+	try(t, gif, want)
+	gif[32] = 1
+
+	// Make the bounds really big, expect an error.
+	want = "gif: frame bounds larger than image bounds"
+	for i := 0; i < 4; i++ {
+		gif[32+i] = 0xff
+	}
+	try(t, gif, want)
+}
+
+func TestNoPalette(t *testing.T) {
+	b := &bytes.Buffer{}
+
+	// Manufacture a GIF with no palette, so any pixel at all
+	// will be invalid.
+	b.WriteString(headerStr[:len(headerStr)-3])
+	b.WriteString("\x00\x00\x00") // No global palette.
+
+	// Image descriptor: 2x1, no local palette.
+	b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
+
+	// Encode the pixels: neither is in range, because there is no palette.
+	pix := []byte{0, 128}
+	enc := &bytes.Buffer{}
+	w := lzw.NewWriter(enc, lzw.LSB, 2)
+	w.Write(pix)
+	w.Close()
+	b.WriteByte(byte(len(enc.Bytes())))
+	b.Write(enc.Bytes())
+	b.WriteByte(0x00) // An empty block signifies the end of the image data.
+
+	b.WriteString(trailerStr)
+
+	try(t, b.Bytes(), "gif: invalid pixel value")
+}
+
+func TestPixelOutsidePaletteRange(t *testing.T) {
+	for _, pval := range []byte{0, 1, 2, 3, 255} {
+		b := &bytes.Buffer{}
+
+		// Manufacture a GIF with a 2 color palette.
+		b.WriteString(headerStr)
+		b.WriteString(paletteStr)
+
+		// Image descriptor: 2x1, no local palette.
+		b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
+
+		// Encode the pixels; some pvals trigger the expected error.
+		pix := []byte{pval, pval}
+		enc := &bytes.Buffer{}
+		w := lzw.NewWriter(enc, lzw.LSB, 2)
+		w.Write(pix)
+		w.Close()
+		b.WriteByte(byte(len(enc.Bytes())))
+		b.Write(enc.Bytes())
+		b.WriteByte(0x00) // An empty block signifies the end of the image data.
+
+		b.WriteString(trailerStr)
+
+		// No error expected, unless the pixels are beyond the 2 color palette.
+		want := ""
+		if pval >= 2 {
+			want = "gif: invalid pixel value"
+		}
+		try(t, b.Bytes(), want)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/gif/writer.go b/third_party/gofrontend/libgo/go/image/gif/writer.go
new file mode 100644
index 0000000..15cd40f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/gif/writer.go
@@ -0,0 +1,323 @@
+// Copyright 2013 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 gif
+
+import (
+	"bufio"
+	"compress/lzw"
+	"errors"
+	"image"
+	"image/color"
+	"image/color/palette"
+	"image/draw"
+	"io"
+)
+
+// Graphic control extension fields.
+const (
+	gcLabel     = 0xF9
+	gcBlockSize = 0x04
+)
+
+var log2Lookup = [8]int{2, 4, 8, 16, 32, 64, 128, 256}
+
+func log2(x int) int {
+	for i, v := range log2Lookup {
+		if x <= v {
+			return i
+		}
+	}
+	return -1
+}
+
+// Little-endian.
+func writeUint16(b []uint8, u uint16) {
+	b[0] = uint8(u)
+	b[1] = uint8(u >> 8)
+}
+
+// writer is a buffered writer.
+type writer interface {
+	Flush() error
+	io.Writer
+	io.ByteWriter
+}
+
+// encoder encodes an image to the GIF format.
+type encoder struct {
+	// w is the writer to write to. err is the first error encountered during
+	// writing. All attempted writes after the first error become no-ops.
+	w   writer
+	err error
+	// g is a reference to the data that is being encoded.
+	g *GIF
+	// buf is a scratch buffer. It must be at least 768 so we can write the color map.
+	buf [1024]byte
+}
+
+// blockWriter writes the block structure of GIF image data, which
+// comprises (n, (n bytes)) blocks, with 1 <= n <= 255. It is the
+// writer given to the LZW encoder, which is thus immune to the
+// blocking.
+type blockWriter struct {
+	e *encoder
+}
+
+func (b blockWriter) Write(data []byte) (int, error) {
+	if b.e.err != nil {
+		return 0, b.e.err
+	}
+	if len(data) == 0 {
+		return 0, nil
+	}
+	total := 0
+	for total < len(data) {
+		n := copy(b.e.buf[1:256], data[total:])
+		total += n
+		b.e.buf[0] = uint8(n)
+
+		n, b.e.err = b.e.w.Write(b.e.buf[:n+1])
+		if b.e.err != nil {
+			return 0, b.e.err
+		}
+	}
+	return total, b.e.err
+}
+
+func (e *encoder) flush() {
+	if e.err != nil {
+		return
+	}
+	e.err = e.w.Flush()
+}
+
+func (e *encoder) write(p []byte) {
+	if e.err != nil {
+		return
+	}
+	_, e.err = e.w.Write(p)
+}
+
+func (e *encoder) writeByte(b byte) {
+	if e.err != nil {
+		return
+	}
+	e.err = e.w.WriteByte(b)
+}
+
+func (e *encoder) writeHeader() {
+	if e.err != nil {
+		return
+	}
+	_, e.err = io.WriteString(e.w, "GIF89a")
+	if e.err != nil {
+		return
+	}
+
+	pm := e.g.Image[0]
+	// Logical screen width and height.
+	writeUint16(e.buf[0:2], uint16(pm.Bounds().Dx()))
+	writeUint16(e.buf[2:4], uint16(pm.Bounds().Dy()))
+	e.write(e.buf[:4])
+
+	// All frames have a local color table, so a global color table
+	// is not needed.
+	e.buf[0] = 0x00
+	e.buf[1] = 0x00 // Background Color Index.
+	e.buf[2] = 0x00 // Pixel Aspect Ratio.
+	e.write(e.buf[:3])
+
+	// Add animation info if necessary.
+	if len(e.g.Image) > 1 {
+		e.buf[0] = 0x21 // Extension Introducer.
+		e.buf[1] = 0xff // Application Label.
+		e.buf[2] = 0x0b // Block Size.
+		e.write(e.buf[:3])
+		_, e.err = io.WriteString(e.w, "NETSCAPE2.0") // Application Identifier.
+		if e.err != nil {
+			return
+		}
+		e.buf[0] = 0x03 // Block Size.
+		e.buf[1] = 0x01 // Sub-block Index.
+		writeUint16(e.buf[2:4], uint16(e.g.LoopCount))
+		e.buf[4] = 0x00 // Block Terminator.
+		e.write(e.buf[:5])
+	}
+}
+
+func (e *encoder) writeColorTable(p color.Palette, size int) {
+	if e.err != nil {
+		return
+	}
+
+	for i := 0; i < log2Lookup[size]; i++ {
+		if i < len(p) {
+			r, g, b, _ := p[i].RGBA()
+			e.buf[3*i+0] = uint8(r >> 8)
+			e.buf[3*i+1] = uint8(g >> 8)
+			e.buf[3*i+2] = uint8(b >> 8)
+		} else {
+			// Pad with black.
+			e.buf[3*i+0] = 0x00
+			e.buf[3*i+1] = 0x00
+			e.buf[3*i+2] = 0x00
+		}
+	}
+	e.write(e.buf[:3*log2Lookup[size]])
+}
+
+func (e *encoder) writeImageBlock(pm *image.Paletted, delay int) {
+	if e.err != nil {
+		return
+	}
+
+	if len(pm.Palette) == 0 {
+		e.err = errors.New("gif: cannot encode image block with empty palette")
+		return
+	}
+
+	b := pm.Bounds()
+	if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 || b.Min.X < 0 || b.Min.X >= 1<<16 || b.Min.Y < 0 || b.Min.Y >= 1<<16 {
+		e.err = errors.New("gif: image block is too large to encode")
+		return
+	}
+
+	transparentIndex := -1
+	for i, c := range pm.Palette {
+		if _, _, _, a := c.RGBA(); a == 0 {
+			transparentIndex = i
+			break
+		}
+	}
+
+	if delay > 0 || transparentIndex != -1 {
+		e.buf[0] = sExtension  // Extension Introducer.
+		e.buf[1] = gcLabel     // Graphic Control Label.
+		e.buf[2] = gcBlockSize // Block Size.
+		if transparentIndex != -1 {
+			e.buf[3] = 0x01
+		} else {
+			e.buf[3] = 0x00
+		}
+		writeUint16(e.buf[4:6], uint16(delay)) // Delay Time (1/100ths of a second)
+
+		// Transparent color index.
+		if transparentIndex != -1 {
+			e.buf[6] = uint8(transparentIndex)
+		} else {
+			e.buf[6] = 0x00
+		}
+		e.buf[7] = 0x00 // Block Terminator.
+		e.write(e.buf[:8])
+	}
+	e.buf[0] = sImageDescriptor
+	writeUint16(e.buf[1:3], uint16(b.Min.X))
+	writeUint16(e.buf[3:5], uint16(b.Min.Y))
+	writeUint16(e.buf[5:7], uint16(b.Dx()))
+	writeUint16(e.buf[7:9], uint16(b.Dy()))
+	e.write(e.buf[:9])
+
+	paddedSize := log2(len(pm.Palette)) // Size of Local Color Table: 2^(1+n).
+	// Interlacing is not supported.
+	e.writeByte(0x80 | uint8(paddedSize))
+
+	// Local Color Table.
+	e.writeColorTable(pm.Palette, paddedSize)
+
+	litWidth := paddedSize + 1
+	if litWidth < 2 {
+		litWidth = 2
+	}
+	e.writeByte(uint8(litWidth)) // LZW Minimum Code Size.
+
+	lzww := lzw.NewWriter(blockWriter{e: e}, lzw.LSB, litWidth)
+	_, e.err = lzww.Write(pm.Pix)
+	if e.err != nil {
+		lzww.Close()
+		return
+	}
+	lzww.Close()
+	e.writeByte(0x00) // Block Terminator.
+}
+
+// Options are the encoding parameters.
+type Options struct {
+	// NumColors is the maximum number of colors used in the image.
+	// It ranges from 1 to 256.
+	NumColors int
+
+	// Quantizer is used to produce a palette with size NumColors.
+	// palette.Plan9 is used in place of a nil Quantizer.
+	Quantizer draw.Quantizer
+
+	// Drawer is used to convert the source image to the desired palette.
+	// draw.FloydSteinberg is used in place of a nil Drawer.
+	Drawer draw.Drawer
+}
+
+// EncodeAll writes the images in g to w in GIF format with the
+// given loop count and delay between frames.
+func EncodeAll(w io.Writer, g *GIF) error {
+	if len(g.Image) == 0 {
+		return errors.New("gif: must provide at least one image")
+	}
+
+	if len(g.Image) != len(g.Delay) {
+		return errors.New("gif: mismatched image and delay lengths")
+	}
+	if g.LoopCount < 0 {
+		g.LoopCount = 0
+	}
+
+	e := encoder{g: g}
+	if ww, ok := w.(writer); ok {
+		e.w = ww
+	} else {
+		e.w = bufio.NewWriter(w)
+	}
+
+	e.writeHeader()
+	for i, pm := range g.Image {
+		e.writeImageBlock(pm, g.Delay[i])
+	}
+	e.writeByte(sTrailer)
+	e.flush()
+	return e.err
+}
+
+// Encode writes the Image m to w in GIF format.
+func Encode(w io.Writer, m image.Image, o *Options) error {
+	// Check for bounds and size restrictions.
+	b := m.Bounds()
+	if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 {
+		return errors.New("gif: image is too large to encode")
+	}
+
+	opts := Options{}
+	if o != nil {
+		opts = *o
+	}
+	if opts.NumColors < 1 || 256 < opts.NumColors {
+		opts.NumColors = 256
+	}
+	if opts.Drawer == nil {
+		opts.Drawer = draw.FloydSteinberg
+	}
+
+	pm, ok := m.(*image.Paletted)
+	if !ok || len(pm.Palette) > opts.NumColors {
+		// TODO: Pick a better sub-sample of the Plan 9 palette.
+		pm = image.NewPaletted(b, palette.Plan9[:opts.NumColors])
+		if opts.Quantizer != nil {
+			pm.Palette = opts.Quantizer.Quantize(make(color.Palette, 0, opts.NumColors), m)
+		}
+		opts.Drawer.Draw(pm, b, m, image.ZP)
+	}
+
+	return EncodeAll(w, &GIF{
+		Image: []*image.Paletted{pm},
+		Delay: []int{0},
+	})
+}
diff --git a/third_party/gofrontend/libgo/go/image/gif/writer_test.go b/third_party/gofrontend/libgo/go/image/gif/writer_test.go
new file mode 100644
index 0000000..c1ada76
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/gif/writer_test.go
@@ -0,0 +1,204 @@
+// Copyright 2013 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 gif
+
+import (
+	"bytes"
+	"image"
+	"image/color"
+	_ "image/png"
+	"io/ioutil"
+	"math/rand"
+	"os"
+	"testing"
+)
+
+func readImg(filename string) (image.Image, error) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	m, _, err := image.Decode(f)
+	return m, err
+}
+
+func readGIF(filename string) (*GIF, error) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	return DecodeAll(f)
+}
+
+func delta(u0, u1 uint32) int64 {
+	d := int64(u0) - int64(u1)
+	if d < 0 {
+		return -d
+	}
+	return d
+}
+
+// averageDelta returns the average delta in RGB space. The two images must
+// have the same bounds.
+func averageDelta(m0, m1 image.Image) int64 {
+	b := m0.Bounds()
+	var sum, n int64
+	for y := b.Min.Y; y < b.Max.Y; y++ {
+		for x := b.Min.X; x < b.Max.X; x++ {
+			c0 := m0.At(x, y)
+			c1 := m1.At(x, y)
+			r0, g0, b0, _ := c0.RGBA()
+			r1, g1, b1, _ := c1.RGBA()
+			sum += delta(r0, r1)
+			sum += delta(g0, g1)
+			sum += delta(b0, b1)
+			n += 3
+		}
+	}
+	return sum / n
+}
+
+var testCase = []struct {
+	filename  string
+	tolerance int64
+}{
+	{"../testdata/video-001.png", 1 << 12},
+	{"../testdata/video-001.gif", 0},
+	{"../testdata/video-001.interlaced.gif", 0},
+}
+
+func TestWriter(t *testing.T) {
+	for _, tc := range testCase {
+		m0, err := readImg(tc.filename)
+		if err != nil {
+			t.Error(tc.filename, err)
+			continue
+		}
+		var buf bytes.Buffer
+		err = Encode(&buf, m0, nil)
+		if err != nil {
+			t.Error(tc.filename, err)
+			continue
+		}
+		m1, err := Decode(&buf)
+		if err != nil {
+			t.Error(tc.filename, err)
+			continue
+		}
+		if m0.Bounds() != m1.Bounds() {
+			t.Errorf("%s, bounds differ: %v and %v", tc.filename, m0.Bounds(), m1.Bounds())
+			continue
+		}
+		// Compare the average delta to the tolerance level.
+		avgDelta := averageDelta(m0, m1)
+		if avgDelta > tc.tolerance {
+			t.Errorf("%s: average delta is too high. expected: %d, got %d", tc.filename, tc.tolerance, avgDelta)
+			continue
+		}
+	}
+}
+
+var frames = []string{
+	"../testdata/video-001.gif",
+	"../testdata/video-005.gray.gif",
+}
+
+func TestEncodeAll(t *testing.T) {
+	g0 := &GIF{
+		Image:     make([]*image.Paletted, len(frames)),
+		Delay:     make([]int, len(frames)),
+		LoopCount: 5,
+	}
+	for i, f := range frames {
+		m, err := readGIF(f)
+		if err != nil {
+			t.Error(f, err)
+		}
+		g0.Image[i] = m.Image[0]
+	}
+	var buf bytes.Buffer
+	if err := EncodeAll(&buf, g0); err != nil {
+		t.Fatal("EncodeAll:", err)
+	}
+	g1, err := DecodeAll(&buf)
+	if err != nil {
+		t.Fatal("DecodeAll:", err)
+	}
+	if g0.LoopCount != g1.LoopCount {
+		t.Errorf("loop counts differ: %d and %d", g0.LoopCount, g1.LoopCount)
+	}
+	for i := range g0.Image {
+		m0, m1 := g0.Image[i], g1.Image[i]
+		if m0.Bounds() != m1.Bounds() {
+			t.Errorf("%s, bounds differ: %v and %v", frames[i], m0.Bounds(), m1.Bounds())
+		}
+		d0, d1 := g0.Delay[i], g1.Delay[i]
+		if d0 != d1 {
+			t.Errorf("%s: delay values differ: %d and %d", frames[i], d0, d1)
+		}
+	}
+
+	g1.Delay = make([]int, 1)
+	if err := EncodeAll(ioutil.Discard, g1); err == nil {
+		t.Error("expected error from mismatched delay and image slice lengths")
+	}
+	if err := EncodeAll(ioutil.Discard, &GIF{}); err == nil {
+		t.Error("expected error from providing empty gif")
+	}
+}
+
+func BenchmarkEncode(b *testing.B) {
+	b.StopTimer()
+
+	bo := image.Rect(0, 0, 640, 480)
+	rnd := rand.New(rand.NewSource(123))
+
+	// Restrict to a 256-color paletted image to avoid quantization path.
+	palette := make(color.Palette, 256)
+	for i := range palette {
+		palette[i] = color.RGBA{
+			uint8(rnd.Intn(256)),
+			uint8(rnd.Intn(256)),
+			uint8(rnd.Intn(256)),
+			255,
+		}
+	}
+	img := image.NewPaletted(image.Rect(0, 0, 640, 480), palette)
+	for y := bo.Min.Y; y < bo.Max.Y; y++ {
+		for x := bo.Min.X; x < bo.Max.X; x++ {
+			img.Set(x, y, palette[rnd.Intn(256)])
+		}
+	}
+
+	b.SetBytes(640 * 480 * 4)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img, nil)
+	}
+}
+
+func BenchmarkQuantizedEncode(b *testing.B) {
+	b.StopTimer()
+	img := image.NewRGBA(image.Rect(0, 0, 640, 480))
+	bo := img.Bounds()
+	rnd := rand.New(rand.NewSource(123))
+	for y := bo.Min.Y; y < bo.Max.Y; y++ {
+		for x := bo.Min.X; x < bo.Max.X; x++ {
+			img.SetRGBA(x, y, color.RGBA{
+				uint8(rnd.Intn(256)),
+				uint8(rnd.Intn(256)),
+				uint8(rnd.Intn(256)),
+				255,
+			})
+		}
+	}
+	b.SetBytes(640 * 480 * 4)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img, nil)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/image.go b/third_party/gofrontend/libgo/go/image/image.go
new file mode 100644
index 0000000..32a89ef
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/image.go
@@ -0,0 +1,904 @@
+// 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 image implements a basic 2-D image library.
+//
+// The fundamental interface is called Image. An Image contains colors, which
+// are described in the image/color package.
+//
+// Values of the Image interface are created either by calling functions such
+// as NewRGBA and NewPaletted, or by calling Decode on an io.Reader containing
+// image data in a format such as GIF, JPEG or PNG. Decoding any particular
+// image format requires the prior registration of a decoder function.
+// Registration is typically automatic as a side effect of initializing that
+// format's package so that, to decode a PNG image, it suffices to have
+//	import _ "image/png"
+// in a program's main package. The _ means to import a package purely for its
+// initialization side effects.
+//
+// See "The Go image package" for more details:
+// http://golang.org/doc/articles/image_package.html
+package image
+
+import (
+	"image/color"
+)
+
+// Config holds an image's color model and dimensions.
+type Config struct {
+	ColorModel    color.Model
+	Width, Height int
+}
+
+// Image is a finite rectangular grid of color.Color values taken from a color
+// model.
+type Image interface {
+	// ColorModel returns the Image's color model.
+	ColorModel() color.Model
+	// Bounds returns the domain for which At can return non-zero color.
+	// The bounds do not necessarily contain the point (0, 0).
+	Bounds() Rectangle
+	// At returns the color of the pixel at (x, y).
+	// At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
+	// At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
+	At(x, y int) color.Color
+}
+
+// PalettedImage is an image whose colors may come from a limited palette.
+// If m is a PalettedImage and m.ColorModel() returns a PalettedColorModel p,
+// then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's
+// color model is not a PalettedColorModel, then ColorIndexAt's behavior is
+// undefined.
+type PalettedImage interface {
+	// ColorIndexAt returns the palette index of the pixel at (x, y).
+	ColorIndexAt(x, y int) uint8
+	Image
+}
+
+// RGBA is an in-memory image whose At method returns color.RGBA values.
+type RGBA struct {
+	// Pix holds the image's pixels, in R, G, B, A order. The pixel at
+	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
+	Pix []uint8
+	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
+	Stride int
+	// Rect is the image's bounds.
+	Rect Rectangle
+}
+
+func (p *RGBA) ColorModel() color.Model { return color.RGBAModel }
+
+func (p *RGBA) Bounds() Rectangle { return p.Rect }
+
+func (p *RGBA) At(x, y int) color.Color {
+	if !(Point{x, y}.In(p.Rect)) {
+		return color.RGBA{}
+	}
+	i := p.PixOffset(x, y)
+	return color.RGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *RGBA) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+}
+
+func (p *RGBA) Set(x, y int, c color.Color) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	c1 := color.RGBAModel.Convert(c).(color.RGBA)
+	p.Pix[i+0] = c1.R
+	p.Pix[i+1] = c1.G
+	p.Pix[i+2] = c1.B
+	p.Pix[i+3] = c1.A
+}
+
+func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i+0] = c.R
+	p.Pix[i+1] = c.G
+	p.Pix[i+2] = c.B
+	p.Pix[i+3] = c.A
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *RGBA) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &RGBA{}
+	}
+	i := p.PixOffset(r.Min.X, r.Min.Y)
+	return &RGBA{
+		Pix:    p.Pix[i:],
+		Stride: p.Stride,
+		Rect:   r,
+	}
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *RGBA) Opaque() bool {
+	if p.Rect.Empty() {
+		return true
+	}
+	i0, i1 := 3, p.Rect.Dx()*4
+	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
+		for i := i0; i < i1; i += 4 {
+			if p.Pix[i] != 0xff {
+				return false
+			}
+		}
+		i0 += p.Stride
+		i1 += p.Stride
+	}
+	return true
+}
+
+// NewRGBA returns a new RGBA with the given bounds.
+func NewRGBA(r Rectangle) *RGBA {
+	w, h := r.Dx(), r.Dy()
+	buf := make([]uint8, 4*w*h)
+	return &RGBA{buf, 4 * w, r}
+}
+
+// RGBA64 is an in-memory image whose At method returns color.RGBA64 values.
+type RGBA64 struct {
+	// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
+	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
+	Pix []uint8
+	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
+	Stride int
+	// Rect is the image's bounds.
+	Rect Rectangle
+}
+
+func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
+
+func (p *RGBA64) Bounds() Rectangle { return p.Rect }
+
+func (p *RGBA64) At(x, y int) color.Color {
+	if !(Point{x, y}.In(p.Rect)) {
+		return color.RGBA64{}
+	}
+	i := p.PixOffset(x, y)
+	return color.RGBA64{
+		uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
+		uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
+		uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
+		uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
+	}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *RGBA64) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+}
+
+func (p *RGBA64) Set(x, y int, c color.Color) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
+	p.Pix[i+0] = uint8(c1.R >> 8)
+	p.Pix[i+1] = uint8(c1.R)
+	p.Pix[i+2] = uint8(c1.G >> 8)
+	p.Pix[i+3] = uint8(c1.G)
+	p.Pix[i+4] = uint8(c1.B >> 8)
+	p.Pix[i+5] = uint8(c1.B)
+	p.Pix[i+6] = uint8(c1.A >> 8)
+	p.Pix[i+7] = uint8(c1.A)
+}
+
+func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i+0] = uint8(c.R >> 8)
+	p.Pix[i+1] = uint8(c.R)
+	p.Pix[i+2] = uint8(c.G >> 8)
+	p.Pix[i+3] = uint8(c.G)
+	p.Pix[i+4] = uint8(c.B >> 8)
+	p.Pix[i+5] = uint8(c.B)
+	p.Pix[i+6] = uint8(c.A >> 8)
+	p.Pix[i+7] = uint8(c.A)
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *RGBA64) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &RGBA64{}
+	}
+	i := p.PixOffset(r.Min.X, r.Min.Y)
+	return &RGBA64{
+		Pix:    p.Pix[i:],
+		Stride: p.Stride,
+		Rect:   r,
+	}
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *RGBA64) Opaque() bool {
+	if p.Rect.Empty() {
+		return true
+	}
+	i0, i1 := 6, p.Rect.Dx()*8
+	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
+		for i := i0; i < i1; i += 8 {
+			if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
+				return false
+			}
+		}
+		i0 += p.Stride
+		i1 += p.Stride
+	}
+	return true
+}
+
+// NewRGBA64 returns a new RGBA64 with the given bounds.
+func NewRGBA64(r Rectangle) *RGBA64 {
+	w, h := r.Dx(), r.Dy()
+	pix := make([]uint8, 8*w*h)
+	return &RGBA64{pix, 8 * w, r}
+}
+
+// NRGBA is an in-memory image whose At method returns color.NRGBA values.
+type NRGBA struct {
+	// Pix holds the image's pixels, in R, G, B, A order. The pixel at
+	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
+	Pix []uint8
+	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
+	Stride int
+	// Rect is the image's bounds.
+	Rect Rectangle
+}
+
+func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
+
+func (p *NRGBA) Bounds() Rectangle { return p.Rect }
+
+func (p *NRGBA) At(x, y int) color.Color {
+	if !(Point{x, y}.In(p.Rect)) {
+		return color.NRGBA{}
+	}
+	i := p.PixOffset(x, y)
+	return color.NRGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *NRGBA) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+}
+
+func (p *NRGBA) Set(x, y int, c color.Color) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
+	p.Pix[i+0] = c1.R
+	p.Pix[i+1] = c1.G
+	p.Pix[i+2] = c1.B
+	p.Pix[i+3] = c1.A
+}
+
+func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i+0] = c.R
+	p.Pix[i+1] = c.G
+	p.Pix[i+2] = c.B
+	p.Pix[i+3] = c.A
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *NRGBA) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &NRGBA{}
+	}
+	i := p.PixOffset(r.Min.X, r.Min.Y)
+	return &NRGBA{
+		Pix:    p.Pix[i:],
+		Stride: p.Stride,
+		Rect:   r,
+	}
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *NRGBA) Opaque() bool {
+	if p.Rect.Empty() {
+		return true
+	}
+	i0, i1 := 3, p.Rect.Dx()*4
+	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
+		for i := i0; i < i1; i += 4 {
+			if p.Pix[i] != 0xff {
+				return false
+			}
+		}
+		i0 += p.Stride
+		i1 += p.Stride
+	}
+	return true
+}
+
+// NewNRGBA returns a new NRGBA with the given bounds.
+func NewNRGBA(r Rectangle) *NRGBA {
+	w, h := r.Dx(), r.Dy()
+	pix := make([]uint8, 4*w*h)
+	return &NRGBA{pix, 4 * w, r}
+}
+
+// NRGBA64 is an in-memory image whose At method returns color.NRGBA64 values.
+type NRGBA64 struct {
+	// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
+	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
+	Pix []uint8
+	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
+	Stride int
+	// Rect is the image's bounds.
+	Rect Rectangle
+}
+
+func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
+
+func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
+
+func (p *NRGBA64) At(x, y int) color.Color {
+	if !(Point{x, y}.In(p.Rect)) {
+		return color.NRGBA64{}
+	}
+	i := p.PixOffset(x, y)
+	return color.NRGBA64{
+		uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
+		uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
+		uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
+		uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
+	}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *NRGBA64) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+}
+
+func (p *NRGBA64) Set(x, y int, c color.Color) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
+	p.Pix[i+0] = uint8(c1.R >> 8)
+	p.Pix[i+1] = uint8(c1.R)
+	p.Pix[i+2] = uint8(c1.G >> 8)
+	p.Pix[i+3] = uint8(c1.G)
+	p.Pix[i+4] = uint8(c1.B >> 8)
+	p.Pix[i+5] = uint8(c1.B)
+	p.Pix[i+6] = uint8(c1.A >> 8)
+	p.Pix[i+7] = uint8(c1.A)
+}
+
+func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i+0] = uint8(c.R >> 8)
+	p.Pix[i+1] = uint8(c.R)
+	p.Pix[i+2] = uint8(c.G >> 8)
+	p.Pix[i+3] = uint8(c.G)
+	p.Pix[i+4] = uint8(c.B >> 8)
+	p.Pix[i+5] = uint8(c.B)
+	p.Pix[i+6] = uint8(c.A >> 8)
+	p.Pix[i+7] = uint8(c.A)
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *NRGBA64) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &NRGBA64{}
+	}
+	i := p.PixOffset(r.Min.X, r.Min.Y)
+	return &NRGBA64{
+		Pix:    p.Pix[i:],
+		Stride: p.Stride,
+		Rect:   r,
+	}
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *NRGBA64) Opaque() bool {
+	if p.Rect.Empty() {
+		return true
+	}
+	i0, i1 := 6, p.Rect.Dx()*8
+	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
+		for i := i0; i < i1; i += 8 {
+			if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
+				return false
+			}
+		}
+		i0 += p.Stride
+		i1 += p.Stride
+	}
+	return true
+}
+
+// NewNRGBA64 returns a new NRGBA64 with the given bounds.
+func NewNRGBA64(r Rectangle) *NRGBA64 {
+	w, h := r.Dx(), r.Dy()
+	pix := make([]uint8, 8*w*h)
+	return &NRGBA64{pix, 8 * w, r}
+}
+
+// Alpha is an in-memory image whose At method returns color.Alpha values.
+type Alpha struct {
+	// Pix holds the image's pixels, as alpha values. The pixel at
+	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
+	Pix []uint8
+	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
+	Stride int
+	// Rect is the image's bounds.
+	Rect Rectangle
+}
+
+func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
+
+func (p *Alpha) Bounds() Rectangle { return p.Rect }
+
+func (p *Alpha) At(x, y int) color.Color {
+	if !(Point{x, y}.In(p.Rect)) {
+		return color.Alpha{}
+	}
+	i := p.PixOffset(x, y)
+	return color.Alpha{p.Pix[i]}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Alpha) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
+}
+
+func (p *Alpha) Set(x, y int, c color.Color) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
+}
+
+func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i] = c.A
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *Alpha) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &Alpha{}
+	}
+	i := p.PixOffset(r.Min.X, r.Min.Y)
+	return &Alpha{
+		Pix:    p.Pix[i:],
+		Stride: p.Stride,
+		Rect:   r,
+	}
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *Alpha) Opaque() bool {
+	if p.Rect.Empty() {
+		return true
+	}
+	i0, i1 := 0, p.Rect.Dx()
+	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
+		for i := i0; i < i1; i++ {
+			if p.Pix[i] != 0xff {
+				return false
+			}
+		}
+		i0 += p.Stride
+		i1 += p.Stride
+	}
+	return true
+}
+
+// NewAlpha returns a new Alpha with the given bounds.
+func NewAlpha(r Rectangle) *Alpha {
+	w, h := r.Dx(), r.Dy()
+	pix := make([]uint8, 1*w*h)
+	return &Alpha{pix, 1 * w, r}
+}
+
+// Alpha16 is an in-memory image whose At method returns color.Alpha64 values.
+type Alpha16 struct {
+	// Pix holds the image's pixels, as alpha values in big-endian format. The pixel at
+	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
+	Pix []uint8
+	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
+	Stride int
+	// Rect is the image's bounds.
+	Rect Rectangle
+}
+
+func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
+
+func (p *Alpha16) Bounds() Rectangle { return p.Rect }
+
+func (p *Alpha16) At(x, y int) color.Color {
+	if !(Point{x, y}.In(p.Rect)) {
+		return color.Alpha16{}
+	}
+	i := p.PixOffset(x, y)
+	return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Alpha16) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+}
+
+func (p *Alpha16) Set(x, y int, c color.Color) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
+	p.Pix[i+0] = uint8(c1.A >> 8)
+	p.Pix[i+1] = uint8(c1.A)
+}
+
+func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i+0] = uint8(c.A >> 8)
+	p.Pix[i+1] = uint8(c.A)
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *Alpha16) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &Alpha16{}
+	}
+	i := p.PixOffset(r.Min.X, r.Min.Y)
+	return &Alpha16{
+		Pix:    p.Pix[i:],
+		Stride: p.Stride,
+		Rect:   r,
+	}
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *Alpha16) Opaque() bool {
+	if p.Rect.Empty() {
+		return true
+	}
+	i0, i1 := 0, p.Rect.Dx()*2
+	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
+		for i := i0; i < i1; i += 2 {
+			if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
+				return false
+			}
+		}
+		i0 += p.Stride
+		i1 += p.Stride
+	}
+	return true
+}
+
+// NewAlpha16 returns a new Alpha16 with the given bounds.
+func NewAlpha16(r Rectangle) *Alpha16 {
+	w, h := r.Dx(), r.Dy()
+	pix := make([]uint8, 2*w*h)
+	return &Alpha16{pix, 2 * w, r}
+}
+
+// Gray is an in-memory image whose At method returns color.Gray values.
+type Gray struct {
+	// Pix holds the image's pixels, as gray values. The pixel at
+	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
+	Pix []uint8
+	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
+	Stride int
+	// Rect is the image's bounds.
+	Rect Rectangle
+}
+
+func (p *Gray) ColorModel() color.Model { return color.GrayModel }
+
+func (p *Gray) Bounds() Rectangle { return p.Rect }
+
+func (p *Gray) At(x, y int) color.Color {
+	if !(Point{x, y}.In(p.Rect)) {
+		return color.Gray{}
+	}
+	i := p.PixOffset(x, y)
+	return color.Gray{p.Pix[i]}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Gray) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
+}
+
+func (p *Gray) Set(x, y int, c color.Color) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
+}
+
+func (p *Gray) SetGray(x, y int, c color.Gray) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i] = c.Y
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *Gray) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &Gray{}
+	}
+	i := p.PixOffset(r.Min.X, r.Min.Y)
+	return &Gray{
+		Pix:    p.Pix[i:],
+		Stride: p.Stride,
+		Rect:   r,
+	}
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *Gray) Opaque() bool {
+	return true
+}
+
+// NewGray returns a new Gray with the given bounds.
+func NewGray(r Rectangle) *Gray {
+	w, h := r.Dx(), r.Dy()
+	pix := make([]uint8, 1*w*h)
+	return &Gray{pix, 1 * w, r}
+}
+
+// Gray16 is an in-memory image whose At method returns color.Gray16 values.
+type Gray16 struct {
+	// Pix holds the image's pixels, as gray values in big-endian format. The pixel at
+	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
+	Pix []uint8
+	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
+	Stride int
+	// Rect is the image's bounds.
+	Rect Rectangle
+}
+
+func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
+
+func (p *Gray16) Bounds() Rectangle { return p.Rect }
+
+func (p *Gray16) At(x, y int) color.Color {
+	if !(Point{x, y}.In(p.Rect)) {
+		return color.Gray16{}
+	}
+	i := p.PixOffset(x, y)
+	return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Gray16) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+}
+
+func (p *Gray16) Set(x, y int, c color.Color) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	c1 := color.Gray16Model.Convert(c).(color.Gray16)
+	p.Pix[i+0] = uint8(c1.Y >> 8)
+	p.Pix[i+1] = uint8(c1.Y)
+}
+
+func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i+0] = uint8(c.Y >> 8)
+	p.Pix[i+1] = uint8(c.Y)
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *Gray16) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &Gray16{}
+	}
+	i := p.PixOffset(r.Min.X, r.Min.Y)
+	return &Gray16{
+		Pix:    p.Pix[i:],
+		Stride: p.Stride,
+		Rect:   r,
+	}
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *Gray16) Opaque() bool {
+	return true
+}
+
+// NewGray16 returns a new Gray16 with the given bounds.
+func NewGray16(r Rectangle) *Gray16 {
+	w, h := r.Dx(), r.Dy()
+	pix := make([]uint8, 2*w*h)
+	return &Gray16{pix, 2 * w, r}
+}
+
+// Paletted is an in-memory image of uint8 indices into a given palette.
+type Paletted struct {
+	// Pix holds the image's pixels, as palette indices. The pixel at
+	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
+	Pix []uint8
+	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
+	Stride int
+	// Rect is the image's bounds.
+	Rect Rectangle
+	// Palette is the image's palette.
+	Palette color.Palette
+}
+
+func (p *Paletted) ColorModel() color.Model { return p.Palette }
+
+func (p *Paletted) Bounds() Rectangle { return p.Rect }
+
+func (p *Paletted) At(x, y int) color.Color {
+	if len(p.Palette) == 0 {
+		return nil
+	}
+	if !(Point{x, y}.In(p.Rect)) {
+		return p.Palette[0]
+	}
+	i := p.PixOffset(x, y)
+	return p.Palette[p.Pix[i]]
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Paletted) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
+}
+
+func (p *Paletted) Set(x, y int, c color.Color) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i] = uint8(p.Palette.Index(c))
+}
+
+func (p *Paletted) ColorIndexAt(x, y int) uint8 {
+	if !(Point{x, y}.In(p.Rect)) {
+		return 0
+	}
+	i := p.PixOffset(x, y)
+	return p.Pix[i]
+}
+
+func (p *Paletted) SetColorIndex(x, y int, index uint8) {
+	if !(Point{x, y}.In(p.Rect)) {
+		return
+	}
+	i := p.PixOffset(x, y)
+	p.Pix[i] = index
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *Paletted) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &Paletted{
+			Palette: p.Palette,
+		}
+	}
+	i := p.PixOffset(r.Min.X, r.Min.Y)
+	return &Paletted{
+		Pix:     p.Pix[i:],
+		Stride:  p.Stride,
+		Rect:    p.Rect.Intersect(r),
+		Palette: p.Palette,
+	}
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *Paletted) Opaque() bool {
+	var present [256]bool
+	i0, i1 := 0, p.Rect.Dx()
+	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
+		for _, c := range p.Pix[i0:i1] {
+			present[c] = true
+		}
+		i0 += p.Stride
+		i1 += p.Stride
+	}
+	for i, c := range p.Palette {
+		if !present[i] {
+			continue
+		}
+		_, _, _, a := c.RGBA()
+		if a != 0xffff {
+			return false
+		}
+	}
+	return true
+}
+
+// NewPaletted returns a new Paletted with the given width, height and palette.
+func NewPaletted(r Rectangle, p color.Palette) *Paletted {
+	w, h := r.Dx(), r.Dy()
+	pix := make([]uint8, 1*w*h)
+	return &Paletted{pix, 1 * w, r, p}
+}
diff --git a/third_party/gofrontend/libgo/go/image/image_test.go b/third_party/gofrontend/libgo/go/image/image_test.go
new file mode 100644
index 0000000..799c1a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/image_test.go
@@ -0,0 +1,113 @@
+// 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.
+
+package image
+
+import (
+	"image/color"
+	"testing"
+)
+
+type image interface {
+	Image
+	Opaque() bool
+	Set(int, int, color.Color)
+	SubImage(Rectangle) Image
+}
+
+func cmp(t *testing.T, cm color.Model, c0, c1 color.Color) bool {
+	r0, g0, b0, a0 := cm.Convert(c0).RGBA()
+	r1, g1, b1, a1 := cm.Convert(c1).RGBA()
+	return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
+}
+
+func TestImage(t *testing.T) {
+	testImage := []image{
+		NewRGBA(Rect(0, 0, 10, 10)),
+		NewRGBA64(Rect(0, 0, 10, 10)),
+		NewNRGBA(Rect(0, 0, 10, 10)),
+		NewNRGBA64(Rect(0, 0, 10, 10)),
+		NewAlpha(Rect(0, 0, 10, 10)),
+		NewAlpha16(Rect(0, 0, 10, 10)),
+		NewGray(Rect(0, 0, 10, 10)),
+		NewGray16(Rect(0, 0, 10, 10)),
+		NewPaletted(Rect(0, 0, 10, 10), color.Palette{
+			Transparent,
+			Opaque,
+		}),
+	}
+	for _, m := range testImage {
+		if !Rect(0, 0, 10, 10).Eq(m.Bounds()) {
+			t.Errorf("%T: want bounds %v, got %v", m, Rect(0, 0, 10, 10), m.Bounds())
+			continue
+		}
+		if !cmp(t, m.ColorModel(), Transparent, m.At(6, 3)) {
+			t.Errorf("%T: at (6, 3), want a zero color, got %v", m, m.At(6, 3))
+			continue
+		}
+		m.Set(6, 3, Opaque)
+		if !cmp(t, m.ColorModel(), Opaque, m.At(6, 3)) {
+			t.Errorf("%T: at (6, 3), want a non-zero color, got %v", m, m.At(6, 3))
+			continue
+		}
+		if !m.SubImage(Rect(6, 3, 7, 4)).(image).Opaque() {
+			t.Errorf("%T: at (6, 3) was not opaque", m)
+			continue
+		}
+		m = m.SubImage(Rect(3, 2, 9, 8)).(image)
+		if !Rect(3, 2, 9, 8).Eq(m.Bounds()) {
+			t.Errorf("%T: sub-image want bounds %v, got %v", m, Rect(3, 2, 9, 8), m.Bounds())
+			continue
+		}
+		if !cmp(t, m.ColorModel(), Opaque, m.At(6, 3)) {
+			t.Errorf("%T: sub-image at (6, 3), want a non-zero color, got %v", m, m.At(6, 3))
+			continue
+		}
+		if !cmp(t, m.ColorModel(), Transparent, m.At(3, 3)) {
+			t.Errorf("%T: sub-image at (3, 3), want a zero color, got %v", m, m.At(3, 3))
+			continue
+		}
+		m.Set(3, 3, Opaque)
+		if !cmp(t, m.ColorModel(), Opaque, m.At(3, 3)) {
+			t.Errorf("%T: sub-image at (3, 3), want a non-zero color, got %v", m, m.At(3, 3))
+			continue
+		}
+		// Test that taking an empty sub-image starting at a corner does not panic.
+		m.SubImage(Rect(0, 0, 0, 0))
+		m.SubImage(Rect(10, 0, 10, 0))
+		m.SubImage(Rect(0, 10, 0, 10))
+		m.SubImage(Rect(10, 10, 10, 10))
+	}
+}
+
+func Test16BitsPerColorChannel(t *testing.T) {
+	testColorModel := []color.Model{
+		color.RGBA64Model,
+		color.NRGBA64Model,
+		color.Alpha16Model,
+		color.Gray16Model,
+	}
+	for _, cm := range testColorModel {
+		c := cm.Convert(color.RGBA64{0x1234, 0x1234, 0x1234, 0x1234}) // Premultiplied alpha.
+		r, _, _, _ := c.RGBA()
+		if r != 0x1234 {
+			t.Errorf("%T: want red value 0x%04x got 0x%04x", c, 0x1234, r)
+			continue
+		}
+	}
+	testImage := []image{
+		NewRGBA64(Rect(0, 0, 10, 10)),
+		NewNRGBA64(Rect(0, 0, 10, 10)),
+		NewAlpha16(Rect(0, 0, 10, 10)),
+		NewGray16(Rect(0, 0, 10, 10)),
+	}
+	for _, m := range testImage {
+		m.Set(1, 2, color.NRGBA64{0xffff, 0xffff, 0xffff, 0x1357}) // Non-premultiplied alpha.
+		r, _, _, _ := m.At(1, 2).RGBA()
+		if r != 0x1357 {
+			t.Errorf("%T: want red value 0x%04x got 0x%04x", m, 0x1357, r)
+			continue
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/jpeg/dct_test.go b/third_party/gofrontend/libgo/go/image/jpeg/dct_test.go
new file mode 100644
index 0000000..845e758
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/jpeg/dct_test.go
@@ -0,0 +1,299 @@
+// 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 jpeg
+
+import (
+	"bytes"
+	"fmt"
+	"math"
+	"math/rand"
+	"testing"
+)
+
+func benchmarkDCT(b *testing.B, f func(*block)) {
+	b.StopTimer()
+	blocks := make([]block, 0, b.N*len(testBlocks))
+	for i := 0; i < b.N; i++ {
+		blocks = append(blocks, testBlocks[:]...)
+	}
+	b.StartTimer()
+	for i := range blocks {
+		f(&blocks[i])
+	}
+}
+
+func BenchmarkFDCT(b *testing.B) {
+	benchmarkDCT(b, fdct)
+}
+
+func BenchmarkIDCT(b *testing.B) {
+	benchmarkDCT(b, idct)
+}
+
+func TestDCT(t *testing.T) {
+	blocks := make([]block, len(testBlocks))
+	copy(blocks, testBlocks[:])
+
+	// Append some randomly generated blocks of varying sparseness.
+	r := rand.New(rand.NewSource(123))
+	for i := 0; i < 100; i++ {
+		b := block{}
+		n := r.Int() % 64
+		for j := 0; j < n; j++ {
+			b[r.Int()%len(b)] = r.Int31() % 256
+		}
+		blocks = append(blocks, b)
+	}
+
+	// Check that the FDCT and IDCT functions are inverses, after a scale and
+	// level shift. Scaling reduces the rounding errors in the conversion from
+	// floats to ints.
+	for i, b := range blocks {
+		got, want := b, b
+		for j := range got {
+			got[j] = (got[j] - 128) * 8
+		}
+		slowFDCT(&got)
+		slowIDCT(&got)
+		for j := range got {
+			got[j] = got[j]/8 + 128
+		}
+		if differ(&got, &want) {
+			t.Errorf("i=%d: IDCT(FDCT)\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
+		}
+	}
+
+	// Check that the optimized and slow FDCT implementations agree.
+	// The fdct function already does a scale and level shift.
+	for i, b := range blocks {
+		got, want := b, b
+		fdct(&got)
+		for j := range want {
+			want[j] = (want[j] - 128) * 8
+		}
+		slowFDCT(&want)
+		if differ(&got, &want) {
+			t.Errorf("i=%d: FDCT\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
+		}
+	}
+
+	// Check that the optimized and slow IDCT implementations agree.
+	for i, b := range blocks {
+		got, want := b, b
+		idct(&got)
+		slowIDCT(&want)
+		if differ(&got, &want) {
+			t.Errorf("i=%d: IDCT\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
+		}
+	}
+}
+
+// differ reports whether any pair-wise elements in b0 and b1 differ by 2 or
+// more. That tolerance is because there isn't a single definitive decoding of
+// a given JPEG image, even before the YCbCr to RGB conversion; implementations
+// can have different IDCT rounding errors.
+func differ(b0, b1 *block) bool {
+	for i := range b0 {
+		delta := b0[i] - b1[i]
+		if delta < -2 || +2 < delta {
+			return true
+		}
+	}
+	return false
+}
+
+// alpha returns 1 if i is 0 and returns √2 otherwise.
+func alpha(i int) float64 {
+	if i == 0 {
+		return 1
+	}
+	return math.Sqrt2
+}
+
+var cosines [32]float64 // cosines[k] = cos(π/2 * k/8)
+
+func init() {
+	for k := range cosines {
+		cosines[k] = math.Cos(math.Pi * float64(k) / 16)
+	}
+}
+
+// slowFDCT performs the 8*8 2-dimensional forward discrete cosine transform:
+//
+//	dst[u,v] = (1/8) * Σ_x Σ_y alpha(u) * alpha(v) * src[x,y] *
+//		cos((π/2) * (2*x + 1) * u / 8) *
+//		cos((π/2) * (2*y + 1) * v / 8)
+//
+// x and y are in pixel space, and u and v are in transform space.
+//
+// b acts as both dst and src.
+func slowFDCT(b *block) {
+	var dst [blockSize]float64
+	for v := 0; v < 8; v++ {
+		for u := 0; u < 8; u++ {
+			sum := 0.0
+			for y := 0; y < 8; y++ {
+				for x := 0; x < 8; x++ {
+					sum += alpha(u) * alpha(v) * float64(b[8*y+x]) *
+						cosines[((2*x+1)*u)%32] *
+						cosines[((2*y+1)*v)%32]
+				}
+			}
+			dst[8*v+u] = sum / 8
+		}
+	}
+	// Convert from float64 to int32.
+	for i := range dst {
+		b[i] = int32(dst[i] + 0.5)
+	}
+}
+
+// slowIDCT performs the 8*8 2-dimensional inverse discrete cosine transform:
+//
+//	dst[x,y] = (1/8) * Σ_u Σ_v alpha(u) * alpha(v) * src[u,v] *
+//		cos((π/2) * (2*x + 1) * u / 8) *
+//		cos((π/2) * (2*y + 1) * v / 8)
+//
+// x and y are in pixel space, and u and v are in transform space.
+//
+// b acts as both dst and src.
+func slowIDCT(b *block) {
+	var dst [blockSize]float64
+	for y := 0; y < 8; y++ {
+		for x := 0; x < 8; x++ {
+			sum := 0.0
+			for v := 0; v < 8; v++ {
+				for u := 0; u < 8; u++ {
+					sum += alpha(u) * alpha(v) * float64(b[8*v+u]) *
+						cosines[((2*x+1)*u)%32] *
+						cosines[((2*y+1)*v)%32]
+				}
+			}
+			dst[8*y+x] = sum / 8
+		}
+	}
+	// Convert from float64 to int32.
+	for i := range dst {
+		b[i] = int32(dst[i] + 0.5)
+	}
+}
+
+func (b *block) String() string {
+	s := bytes.NewBuffer(nil)
+	fmt.Fprintf(s, "{\n")
+	for y := 0; y < 8; y++ {
+		fmt.Fprintf(s, "\t")
+		for x := 0; x < 8; x++ {
+			fmt.Fprintf(s, "0x%04x, ", uint16(b[8*y+x]))
+		}
+		fmt.Fprintln(s)
+	}
+	fmt.Fprintf(s, "}")
+	return s.String()
+}
+
+// testBlocks are the first 10 pre-IDCT blocks from ../testdata/video-001.jpeg.
+var testBlocks = [10]block{
+	{
+		0x7f, 0xf6, 0x01, 0x07, 0xff, 0x00, 0x00, 0x00,
+		0xf5, 0x01, 0xfa, 0x01, 0xfe, 0x00, 0x01, 0x00,
+		0x05, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0xff, 0xf8, 0x00, 0x01, 0xff, 0x00, 0x00,
+		0x00, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00,
+		0xff, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01,
+		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x01, 0xff, 0x01, 0x00, 0xfe,
+	},
+	{
+		0x29, 0x07, 0x00, 0xfc, 0x01, 0x01, 0x00, 0x00,
+		0x07, 0x00, 0x03, 0x00, 0x01, 0x00, 0xff, 0xff,
+		0xff, 0xfd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x04, 0x00, 0xff, 0x01, 0x00, 0x00,
+		0x01, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0xfa, 0x01, 0x00, 0x01, 0x00, 0x01, 0xff,
+		0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x02,
+	},
+	{
+		0xc5, 0xfa, 0x01, 0x00, 0x00, 0x01, 0x00, 0xff,
+		0x02, 0xff, 0x01, 0x00, 0x01, 0x00, 0xff, 0x00,
+		0xff, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00,
+		0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+		0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	},
+	{
+		0x86, 0x05, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00,
+		0xf2, 0x06, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
+		0xf6, 0xfa, 0xf9, 0x00, 0xff, 0x01, 0x00, 0x00,
+		0xf9, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
+		0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0x01, 0x00,
+		0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01,
+		0x00, 0x01, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00,
+	},
+	{
+		0x24, 0xfe, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
+		0x08, 0xfd, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00,
+		0x06, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00,
+		0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
+		0x01, 0x00, 0x01, 0xff, 0x00, 0x01, 0x00, 0x00,
+		0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x01,
+	},
+	{
+		0xcd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+		0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+		0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
+		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff,
+	},
+	{
+		0x81, 0xfe, 0x05, 0xff, 0x01, 0xff, 0x01, 0x00,
+		0xef, 0xf9, 0x00, 0xf9, 0x00, 0xff, 0x00, 0xff,
+		0x05, 0xf9, 0x00, 0xf8, 0x01, 0xff, 0x01, 0xff,
+		0x00, 0xff, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01,
+		0xff, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00,
+		0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
+	},
+	{
+		0x28, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x0b, 0x02, 0x01, 0x03, 0x00, 0xff, 0x00, 0x01,
+		0xfe, 0x02, 0x01, 0x03, 0xff, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0xfd, 0x00, 0x01, 0x00, 0xff, 0x00,
+		0x01, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x00, 0xff,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01,
+	},
+	{
+		0xdf, 0xf9, 0xfe, 0x00, 0x03, 0x01, 0xff, 0xff,
+		0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0xff, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01,
+		0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01,
+		0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+		0x00, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x01,
+		0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+	},
+	{
+		0x88, 0xfd, 0x00, 0x00, 0xff, 0x00, 0x01, 0xff,
+		0xe1, 0x06, 0x06, 0x01, 0xff, 0x00, 0x01, 0x00,
+		0x08, 0x00, 0xfa, 0x00, 0xff, 0xff, 0xff, 0xff,
+		0x08, 0x01, 0x00, 0xff, 0x01, 0xff, 0x00, 0x00,
+		0xf5, 0xff, 0x00, 0x01, 0xff, 0x01, 0x01, 0x00,
+		0xff, 0xff, 0x01, 0xff, 0x01, 0x00, 0x01, 0x00,
+		0x00, 0x01, 0x01, 0xff, 0x00, 0xff, 0x00, 0x01,
+		0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
+	},
+}
diff --git a/third_party/gofrontend/libgo/go/image/jpeg/fdct.go b/third_party/gofrontend/libgo/go/image/jpeg/fdct.go
new file mode 100644
index 0000000..3f8be4e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/jpeg/fdct.go
@@ -0,0 +1,190 @@
+// 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.
+
+package jpeg
+
+// This file implements a Forward Discrete Cosine Transformation.
+
+/*
+It is based on the code in jfdctint.c from the Independent JPEG Group,
+found at http://www.ijg.org/files/jpegsrc.v8c.tar.gz.
+
+The "LEGAL ISSUES" section of the README in that archive says:
+
+In plain English:
+
+1. We don't promise that this software works.  (But if you find any bugs,
+   please let us know!)
+2. You can use this software for whatever you want.  You don't have to pay us.
+3. You may not pretend that you wrote this software.  If you use it in a
+   program, you must acknowledge somewhere in your documentation that
+   you've used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose.  This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-2011, Thomas G. Lane, Guido Vollbeding.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library.  If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it.  This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+*/
+
+// Trigonometric constants in 13-bit fixed point format.
+const (
+	fix_0_298631336 = 2446
+	fix_0_390180644 = 3196
+	fix_0_541196100 = 4433
+	fix_0_765366865 = 6270
+	fix_0_899976223 = 7373
+	fix_1_175875602 = 9633
+	fix_1_501321110 = 12299
+	fix_1_847759065 = 15137
+	fix_1_961570560 = 16069
+	fix_2_053119869 = 16819
+	fix_2_562915447 = 20995
+	fix_3_072711026 = 25172
+)
+
+const (
+	constBits     = 13
+	pass1Bits     = 2
+	centerJSample = 128
+)
+
+// fdct performs a forward DCT on an 8x8 block of coefficients, including a
+// level shift.
+func fdct(b *block) {
+	// Pass 1: process rows.
+	for y := 0; y < 8; y++ {
+		x0 := b[y*8+0]
+		x1 := b[y*8+1]
+		x2 := b[y*8+2]
+		x3 := b[y*8+3]
+		x4 := b[y*8+4]
+		x5 := b[y*8+5]
+		x6 := b[y*8+6]
+		x7 := b[y*8+7]
+
+		tmp0 := x0 + x7
+		tmp1 := x1 + x6
+		tmp2 := x2 + x5
+		tmp3 := x3 + x4
+
+		tmp10 := tmp0 + tmp3
+		tmp12 := tmp0 - tmp3
+		tmp11 := tmp1 + tmp2
+		tmp13 := tmp1 - tmp2
+
+		tmp0 = x0 - x7
+		tmp1 = x1 - x6
+		tmp2 = x2 - x5
+		tmp3 = x3 - x4
+
+		b[y*8+0] = (tmp10 + tmp11 - 8*centerJSample) << pass1Bits
+		b[y*8+4] = (tmp10 - tmp11) << pass1Bits
+		z1 := (tmp12 + tmp13) * fix_0_541196100
+		z1 += 1 << (constBits - pass1Bits - 1)
+		b[y*8+2] = (z1 + tmp12*fix_0_765366865) >> (constBits - pass1Bits)
+		b[y*8+6] = (z1 - tmp13*fix_1_847759065) >> (constBits - pass1Bits)
+
+		tmp10 = tmp0 + tmp3
+		tmp11 = tmp1 + tmp2
+		tmp12 = tmp0 + tmp2
+		tmp13 = tmp1 + tmp3
+		z1 = (tmp12 + tmp13) * fix_1_175875602
+		z1 += 1 << (constBits - pass1Bits - 1)
+		tmp0 = tmp0 * fix_1_501321110
+		tmp1 = tmp1 * fix_3_072711026
+		tmp2 = tmp2 * fix_2_053119869
+		tmp3 = tmp3 * fix_0_298631336
+		tmp10 = tmp10 * -fix_0_899976223
+		tmp11 = tmp11 * -fix_2_562915447
+		tmp12 = tmp12 * -fix_0_390180644
+		tmp13 = tmp13 * -fix_1_961570560
+
+		tmp12 += z1
+		tmp13 += z1
+		b[y*8+1] = (tmp0 + tmp10 + tmp12) >> (constBits - pass1Bits)
+		b[y*8+3] = (tmp1 + tmp11 + tmp13) >> (constBits - pass1Bits)
+		b[y*8+5] = (tmp2 + tmp11 + tmp12) >> (constBits - pass1Bits)
+		b[y*8+7] = (tmp3 + tmp10 + tmp13) >> (constBits - pass1Bits)
+	}
+	// Pass 2: process columns.
+	// We remove pass1Bits scaling, but leave results scaled up by an overall factor of 8.
+	for x := 0; x < 8; x++ {
+		tmp0 := b[0*8+x] + b[7*8+x]
+		tmp1 := b[1*8+x] + b[6*8+x]
+		tmp2 := b[2*8+x] + b[5*8+x]
+		tmp3 := b[3*8+x] + b[4*8+x]
+
+		tmp10 := tmp0 + tmp3 + 1<<(pass1Bits-1)
+		tmp12 := tmp0 - tmp3
+		tmp11 := tmp1 + tmp2
+		tmp13 := tmp1 - tmp2
+
+		tmp0 = b[0*8+x] - b[7*8+x]
+		tmp1 = b[1*8+x] - b[6*8+x]
+		tmp2 = b[2*8+x] - b[5*8+x]
+		tmp3 = b[3*8+x] - b[4*8+x]
+
+		b[0*8+x] = (tmp10 + tmp11) >> pass1Bits
+		b[4*8+x] = (tmp10 - tmp11) >> pass1Bits
+
+		z1 := (tmp12 + tmp13) * fix_0_541196100
+		z1 += 1 << (constBits + pass1Bits - 1)
+		b[2*8+x] = (z1 + tmp12*fix_0_765366865) >> (constBits + pass1Bits)
+		b[6*8+x] = (z1 - tmp13*fix_1_847759065) >> (constBits + pass1Bits)
+
+		tmp10 = tmp0 + tmp3
+		tmp11 = tmp1 + tmp2
+		tmp12 = tmp0 + tmp2
+		tmp13 = tmp1 + tmp3
+		z1 = (tmp12 + tmp13) * fix_1_175875602
+		z1 += 1 << (constBits + pass1Bits - 1)
+		tmp0 = tmp0 * fix_1_501321110
+		tmp1 = tmp1 * fix_3_072711026
+		tmp2 = tmp2 * fix_2_053119869
+		tmp3 = tmp3 * fix_0_298631336
+		tmp10 = tmp10 * -fix_0_899976223
+		tmp11 = tmp11 * -fix_2_562915447
+		tmp12 = tmp12 * -fix_0_390180644
+		tmp13 = tmp13 * -fix_1_961570560
+
+		tmp12 += z1
+		tmp13 += z1
+		b[1*8+x] = (tmp0 + tmp10 + tmp12) >> (constBits + pass1Bits)
+		b[3*8+x] = (tmp1 + tmp11 + tmp13) >> (constBits + pass1Bits)
+		b[5*8+x] = (tmp2 + tmp11 + tmp12) >> (constBits + pass1Bits)
+		b[7*8+x] = (tmp3 + tmp10 + tmp13) >> (constBits + pass1Bits)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/jpeg/huffman.go b/third_party/gofrontend/libgo/go/image/jpeg/huffman.go
new file mode 100644
index 0000000..f53d873
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/jpeg/huffman.go
@@ -0,0 +1,219 @@
+// 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 jpeg
+
+import "io"
+
+// Each code is at most 16 bits long.
+const maxCodeLength = 16
+
+// Each decoded value is a uint8, so there are at most 256 such values.
+const maxNumValues = 256
+
+// Bit stream for the Huffman decoder.
+// The n least significant bits of a form the unread bits, to be read in MSB to LSB order.
+type bits struct {
+	a uint32 // accumulator.
+	m uint32 // mask. m==1<<(n-1) when n>0, with m==0 when n==0.
+	n int    // the number of unread bits in a.
+}
+
+// Huffman table decoder, specified in section C.
+type huffman struct {
+	l        [maxCodeLength]int
+	length   int                 // sum of l[i].
+	val      [maxNumValues]uint8 // the decoded values, as sorted by their encoding.
+	size     [maxNumValues]int   // size[i] is the number of bits to encode val[i].
+	code     [maxNumValues]int   // code[i] is the encoding of val[i].
+	minCode  [maxCodeLength]int  // min codes of length i, or -1 if no codes of that length.
+	maxCode  [maxCodeLength]int  // max codes of length i, or -1 if no codes of that length.
+	valIndex [maxCodeLength]int  // index into val of minCode[i].
+}
+
+// Reads bytes from the io.Reader to ensure that bits.n is at least n.
+func (d *decoder) ensureNBits(n int) error {
+	for d.b.n < n {
+		c, err := d.r.ReadByte()
+		if err != nil {
+			if err == io.EOF {
+				return FormatError("short Huffman data")
+			}
+			return err
+		}
+		d.b.a = d.b.a<<8 | uint32(c)
+		d.b.n += 8
+		if d.b.m == 0 {
+			d.b.m = 1 << 7
+		} else {
+			d.b.m <<= 8
+		}
+		// Byte stuffing, specified in section F.1.2.3.
+		if c == 0xff {
+			c, err = d.r.ReadByte()
+			if err != nil {
+				if err == io.EOF {
+					return FormatError("short Huffman data")
+				}
+				return err
+			}
+			if c != 0x00 {
+				return FormatError("missing 0xff00 sequence")
+			}
+		}
+	}
+	return nil
+}
+
+// The composition of RECEIVE and EXTEND, specified in section F.2.2.1.
+func (d *decoder) receiveExtend(t uint8) (int32, error) {
+	if d.b.n < int(t) {
+		if err := d.ensureNBits(int(t)); err != nil {
+			return 0, err
+		}
+	}
+	d.b.n -= int(t)
+	d.b.m >>= t
+	s := int32(1) << t
+	x := int32(d.b.a>>uint8(d.b.n)) & (s - 1)
+	if x < s>>1 {
+		x += ((-1) << t) + 1
+	}
+	return x, nil
+}
+
+// Processes a Define Huffman Table marker, and initializes a huffman struct from its contents.
+// Specified in section B.2.4.2.
+func (d *decoder) processDHT(n int) error {
+	for n > 0 {
+		if n < 17 {
+			return FormatError("DHT has wrong length")
+		}
+		_, err := io.ReadFull(d.r, d.tmp[0:17])
+		if err != nil {
+			return err
+		}
+		tc := d.tmp[0] >> 4
+		if tc > maxTc {
+			return FormatError("bad Tc value")
+		}
+		th := d.tmp[0] & 0x0f
+		if th > maxTh || !d.progressive && th > 1 {
+			return FormatError("bad Th value")
+		}
+		h := &d.huff[tc][th]
+
+		// Read l and val (and derive length).
+		h.length = 0
+		for i := 0; i < maxCodeLength; i++ {
+			h.l[i] = int(d.tmp[i+1])
+			h.length += h.l[i]
+		}
+		if h.length == 0 {
+			return FormatError("Huffman table has zero length")
+		}
+		if h.length > maxNumValues {
+			return FormatError("Huffman table has excessive length")
+		}
+		n -= h.length + 17
+		if n < 0 {
+			return FormatError("DHT has wrong length")
+		}
+		_, err = io.ReadFull(d.r, h.val[0:h.length])
+		if err != nil {
+			return err
+		}
+
+		// Derive size.
+		k := 0
+		for i := 0; i < maxCodeLength; i++ {
+			for j := 0; j < h.l[i]; j++ {
+				h.size[k] = i + 1
+				k++
+			}
+		}
+
+		// Derive code.
+		code := 0
+		size := h.size[0]
+		for i := 0; i < h.length; i++ {
+			if size != h.size[i] {
+				code <<= uint8(h.size[i] - size)
+				size = h.size[i]
+			}
+			h.code[i] = code
+			code++
+		}
+
+		// Derive minCode, maxCode, and valIndex.
+		k = 0
+		index := 0
+		for i := 0; i < maxCodeLength; i++ {
+			if h.l[i] == 0 {
+				h.minCode[i] = -1
+				h.maxCode[i] = -1
+				h.valIndex[i] = -1
+			} else {
+				h.minCode[i] = k
+				h.maxCode[i] = k + h.l[i] - 1
+				h.valIndex[i] = index
+				k += h.l[i]
+				index += h.l[i]
+			}
+			k <<= 1
+		}
+	}
+	return nil
+}
+
+// Returns the next Huffman-coded value from the bit stream, decoded according to h.
+// TODO(nigeltao): This decoding algorithm is simple, but slow. A lookahead table, instead of always
+// peeling off only 1 bit at time, ought to be faster.
+func (d *decoder) decodeHuffman(h *huffman) (uint8, error) {
+	if h.length == 0 {
+		return 0, FormatError("uninitialized Huffman table")
+	}
+	for i, code := 0, 0; i < maxCodeLength; i++ {
+		if d.b.n == 0 {
+			if err := d.ensureNBits(1); err != nil {
+				return 0, err
+			}
+		}
+		if d.b.a&d.b.m != 0 {
+			code |= 1
+		}
+		d.b.n--
+		d.b.m >>= 1
+		if code <= h.maxCode[i] {
+			return h.val[h.valIndex[i]+code-h.minCode[i]], nil
+		}
+		code <<= 1
+	}
+	return 0, FormatError("bad Huffman code")
+}
+
+func (d *decoder) decodeBit() (bool, error) {
+	if d.b.n == 0 {
+		if err := d.ensureNBits(1); err != nil {
+			return false, err
+		}
+	}
+	ret := d.b.a&d.b.m != 0
+	d.b.n--
+	d.b.m >>= 1
+	return ret, nil
+}
+
+func (d *decoder) decodeBits(n int) (uint32, error) {
+	if d.b.n < n {
+		if err := d.ensureNBits(n); err != nil {
+			return 0, err
+		}
+	}
+	ret := d.b.a >> uint(d.b.n-n)
+	ret &= (1 << uint(n)) - 1
+	d.b.n -= n
+	d.b.m >>= uint(n)
+	return ret, nil
+}
diff --git a/third_party/gofrontend/libgo/go/image/jpeg/idct.go b/third_party/gofrontend/libgo/go/image/jpeg/idct.go
new file mode 100644
index 0000000..46fcaec
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/jpeg/idct.go
@@ -0,0 +1,192 @@
+// 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 jpeg
+
+// This is a Go translation of idct.c from
+//
+// http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_IEC_13818-4_2004_Conformance_Testing/Video/verifier/mpeg2decode_960109.tar.gz
+//
+// which carries the following notice:
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose.  In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders.  Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+const blockSize = 64 // A DCT block is 8x8.
+
+type block [blockSize]int32
+
+const (
+	w1 = 2841 // 2048*sqrt(2)*cos(1*pi/16)
+	w2 = 2676 // 2048*sqrt(2)*cos(2*pi/16)
+	w3 = 2408 // 2048*sqrt(2)*cos(3*pi/16)
+	w5 = 1609 // 2048*sqrt(2)*cos(5*pi/16)
+	w6 = 1108 // 2048*sqrt(2)*cos(6*pi/16)
+	w7 = 565  // 2048*sqrt(2)*cos(7*pi/16)
+
+	w1pw7 = w1 + w7
+	w1mw7 = w1 - w7
+	w2pw6 = w2 + w6
+	w2mw6 = w2 - w6
+	w3pw5 = w3 + w5
+	w3mw5 = w3 - w5
+
+	r2 = 181 // 256/sqrt(2)
+)
+
+// idct performs a 2-D Inverse Discrete Cosine Transformation.
+//
+// The input coefficients should already have been multiplied by the
+// appropriate quantization table. We use fixed-point computation, with the
+// number of bits for the fractional component varying over the intermediate
+// stages.
+//
+// For more on the actual algorithm, see Z. Wang, "Fast algorithms for the
+// discrete W transform and for the discrete Fourier transform", IEEE Trans. on
+// ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984.
+func idct(src *block) {
+	// Horizontal 1-D IDCT.
+	for y := 0; y < 8; y++ {
+		y8 := y * 8
+		// If all the AC components are zero, then the IDCT is trivial.
+		if src[y8+1] == 0 && src[y8+2] == 0 && src[y8+3] == 0 &&
+			src[y8+4] == 0 && src[y8+5] == 0 && src[y8+6] == 0 && src[y8+7] == 0 {
+			dc := src[y8+0] << 3
+			src[y8+0] = dc
+			src[y8+1] = dc
+			src[y8+2] = dc
+			src[y8+3] = dc
+			src[y8+4] = dc
+			src[y8+5] = dc
+			src[y8+6] = dc
+			src[y8+7] = dc
+			continue
+		}
+
+		// Prescale.
+		x0 := (src[y8+0] << 11) + 128
+		x1 := src[y8+4] << 11
+		x2 := src[y8+6]
+		x3 := src[y8+2]
+		x4 := src[y8+1]
+		x5 := src[y8+7]
+		x6 := src[y8+5]
+		x7 := src[y8+3]
+
+		// Stage 1.
+		x8 := w7 * (x4 + x5)
+		x4 = x8 + w1mw7*x4
+		x5 = x8 - w1pw7*x5
+		x8 = w3 * (x6 + x7)
+		x6 = x8 - w3mw5*x6
+		x7 = x8 - w3pw5*x7
+
+		// Stage 2.
+		x8 = x0 + x1
+		x0 -= x1
+		x1 = w6 * (x3 + x2)
+		x2 = x1 - w2pw6*x2
+		x3 = x1 + w2mw6*x3
+		x1 = x4 + x6
+		x4 -= x6
+		x6 = x5 + x7
+		x5 -= x7
+
+		// Stage 3.
+		x7 = x8 + x3
+		x8 -= x3
+		x3 = x0 + x2
+		x0 -= x2
+		x2 = (r2*(x4+x5) + 128) >> 8
+		x4 = (r2*(x4-x5) + 128) >> 8
+
+		// Stage 4.
+		src[y8+0] = (x7 + x1) >> 8
+		src[y8+1] = (x3 + x2) >> 8
+		src[y8+2] = (x0 + x4) >> 8
+		src[y8+3] = (x8 + x6) >> 8
+		src[y8+4] = (x8 - x6) >> 8
+		src[y8+5] = (x0 - x4) >> 8
+		src[y8+6] = (x3 - x2) >> 8
+		src[y8+7] = (x7 - x1) >> 8
+	}
+
+	// Vertical 1-D IDCT.
+	for x := 0; x < 8; x++ {
+		// Similar to the horizontal 1-D IDCT case, if all the AC components are zero, then the IDCT is trivial.
+		// However, after performing the horizontal 1-D IDCT, there are typically non-zero AC components, so
+		// we do not bother to check for the all-zero case.
+
+		// Prescale.
+		y0 := (src[8*0+x] << 8) + 8192
+		y1 := src[8*4+x] << 8
+		y2 := src[8*6+x]
+		y3 := src[8*2+x]
+		y4 := src[8*1+x]
+		y5 := src[8*7+x]
+		y6 := src[8*5+x]
+		y7 := src[8*3+x]
+
+		// Stage 1.
+		y8 := w7*(y4+y5) + 4
+		y4 = (y8 + w1mw7*y4) >> 3
+		y5 = (y8 - w1pw7*y5) >> 3
+		y8 = w3*(y6+y7) + 4
+		y6 = (y8 - w3mw5*y6) >> 3
+		y7 = (y8 - w3pw5*y7) >> 3
+
+		// Stage 2.
+		y8 = y0 + y1
+		y0 -= y1
+		y1 = w6*(y3+y2) + 4
+		y2 = (y1 - w2pw6*y2) >> 3
+		y3 = (y1 + w2mw6*y3) >> 3
+		y1 = y4 + y6
+		y4 -= y6
+		y6 = y5 + y7
+		y5 -= y7
+
+		// Stage 3.
+		y7 = y8 + y3
+		y8 -= y3
+		y3 = y0 + y2
+		y0 -= y2
+		y2 = (r2*(y4+y5) + 128) >> 8
+		y4 = (r2*(y4-y5) + 128) >> 8
+
+		// Stage 4.
+		src[8*0+x] = (y7 + y1) >> 14
+		src[8*1+x] = (y3 + y2) >> 14
+		src[8*2+x] = (y0 + y4) >> 14
+		src[8*3+x] = (y8 + y6) >> 14
+		src[8*4+x] = (y8 - y6) >> 14
+		src[8*5+x] = (y0 - y4) >> 14
+		src[8*6+x] = (y3 - y2) >> 14
+		src[8*7+x] = (y7 - y1) >> 14
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/jpeg/reader.go b/third_party/gofrontend/libgo/go/image/jpeg/reader.go
new file mode 100644
index 0000000..356d562
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/jpeg/reader.go
@@ -0,0 +1,377 @@
+// 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 jpeg implements a JPEG image decoder and encoder.
+//
+// JPEG is defined in ITU-T T.81: http://www.w3.org/Graphics/JPEG/itu-t81.pdf.
+package jpeg
+
+import (
+	"bufio"
+	"image"
+	"image/color"
+	"io"
+)
+
+// TODO(nigeltao): fix up the doc comment style so that sentences start with
+// the name of the type or function that they annotate.
+
+// A FormatError reports that the input is not a valid JPEG.
+type FormatError string
+
+func (e FormatError) Error() string { return "invalid JPEG format: " + string(e) }
+
+// An UnsupportedError reports that the input uses a valid but unimplemented JPEG feature.
+type UnsupportedError string
+
+func (e UnsupportedError) Error() string { return "unsupported JPEG feature: " + string(e) }
+
+// Component specification, specified in section B.2.2.
+type component struct {
+	h  int   // Horizontal sampling factor.
+	v  int   // Vertical sampling factor.
+	c  uint8 // Component identifier.
+	tq uint8 // Quantization table destination selector.
+}
+
+const (
+	dcTable = 0
+	acTable = 1
+	maxTc   = 1
+	maxTh   = 3
+	maxTq   = 3
+
+	// A grayscale JPEG image has only a Y component.
+	nGrayComponent = 1
+	// A color JPEG image has Y, Cb and Cr components.
+	nColorComponent = 3
+
+	// We only support 4:4:4, 4:4:0, 4:2:2 and 4:2:0 downsampling, and therefore the
+	// number of luma samples per chroma sample is at most 2 in the horizontal
+	// and 2 in the vertical direction.
+	maxH = 2
+	maxV = 2
+)
+
+const (
+	soiMarker   = 0xd8 // Start Of Image.
+	eoiMarker   = 0xd9 // End Of Image.
+	sof0Marker  = 0xc0 // Start Of Frame (Baseline).
+	sof2Marker  = 0xc2 // Start Of Frame (Progressive).
+	dhtMarker   = 0xc4 // Define Huffman Table.
+	dqtMarker   = 0xdb // Define Quantization Table.
+	sosMarker   = 0xda // Start Of Scan.
+	driMarker   = 0xdd // Define Restart Interval.
+	rst0Marker  = 0xd0 // ReSTart (0).
+	rst7Marker  = 0xd7 // ReSTart (7).
+	app0Marker  = 0xe0 // APPlication specific (0).
+	app15Marker = 0xef // APPlication specific (15).
+	comMarker   = 0xfe // COMment.
+)
+
+// unzig maps from the zig-zag ordering to the natural ordering. For example,
+// unzig[3] is the column and row of the fourth element in zig-zag order. The
+// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2).
+var unzig = [blockSize]int{
+	0, 1, 8, 16, 9, 2, 3, 10,
+	17, 24, 32, 25, 18, 11, 4, 5,
+	12, 19, 26, 33, 40, 48, 41, 34,
+	27, 20, 13, 6, 7, 14, 21, 28,
+	35, 42, 49, 56, 57, 50, 43, 36,
+	29, 22, 15, 23, 30, 37, 44, 51,
+	58, 59, 52, 45, 38, 31, 39, 46,
+	53, 60, 61, 54, 47, 55, 62, 63,
+}
+
+// If the passed in io.Reader does not also have ReadByte, then Decode will introduce its own buffering.
+type Reader interface {
+	io.Reader
+	ReadByte() (c byte, err error)
+}
+
+type decoder struct {
+	r             Reader
+	b             bits
+	width, height int
+	img1          *image.Gray
+	img3          *image.YCbCr
+	ri            int // Restart Interval.
+	nComp         int
+	progressive   bool
+	eobRun        uint16 // End-of-Band run, specified in section G.1.2.2.
+	comp          [nColorComponent]component
+	progCoeffs    [nColorComponent][]block // Saved state between progressive-mode scans.
+	huff          [maxTc + 1][maxTh + 1]huffman
+	quant         [maxTq + 1]block // Quantization tables, in zig-zag order.
+	tmp           [1024]byte
+}
+
+// Reads and ignores the next n bytes.
+func (d *decoder) ignore(n int) error {
+	for n > 0 {
+		m := len(d.tmp)
+		if m > n {
+			m = n
+		}
+		_, err := io.ReadFull(d.r, d.tmp[0:m])
+		if err != nil {
+			return err
+		}
+		n -= m
+	}
+	return nil
+}
+
+// Specified in section B.2.2.
+func (d *decoder) processSOF(n int) error {
+	switch n {
+	case 6 + 3*nGrayComponent:
+		d.nComp = nGrayComponent
+	case 6 + 3*nColorComponent:
+		d.nComp = nColorComponent
+	default:
+		return UnsupportedError("SOF has wrong length")
+	}
+	_, err := io.ReadFull(d.r, d.tmp[:n])
+	if err != nil {
+		return err
+	}
+	// We only support 8-bit precision.
+	if d.tmp[0] != 8 {
+		return UnsupportedError("precision")
+	}
+	d.height = int(d.tmp[1])<<8 + int(d.tmp[2])
+	d.width = int(d.tmp[3])<<8 + int(d.tmp[4])
+	if int(d.tmp[5]) != d.nComp {
+		return UnsupportedError("SOF has wrong number of image components")
+	}
+	for i := 0; i < d.nComp; i++ {
+		d.comp[i].c = d.tmp[6+3*i]
+		d.comp[i].tq = d.tmp[8+3*i]
+		if d.nComp == nGrayComponent {
+			// If a JPEG image has only one component, section A.2 says "this data
+			// is non-interleaved by definition" and section A.2.2 says "[in this
+			// case...] the order of data units within a scan shall be left-to-right
+			// and top-to-bottom... regardless of the values of H_1 and V_1". Section
+			// 4.8.2 also says "[for non-interleaved data], the MCU is defined to be
+			// one data unit". Similarly, section A.1.1 explains that it is the ratio
+			// of H_i to max_j(H_j) that matters, and similarly for V. For grayscale
+			// images, H_1 is the maximum H_j for all components j, so that ratio is
+			// always 1. The component's (h, v) is effectively always (1, 1): even if
+			// the nominal (h, v) is (2, 1), a 20x5 image is encoded in three 8x8
+			// MCUs, not two 16x8 MCUs.
+			d.comp[i].h = 1
+			d.comp[i].v = 1
+			continue
+		}
+		hv := d.tmp[7+3*i]
+		d.comp[i].h = int(hv >> 4)
+		d.comp[i].v = int(hv & 0x0f)
+		// For color images, we only support 4:4:4, 4:4:0, 4:2:2 or 4:2:0 chroma
+		// downsampling ratios. This implies that the (h, v) values for the Y
+		// component are either (1, 1), (1, 2), (2, 1) or (2, 2), and the (h, v)
+		// values for the Cr and Cb components must be (1, 1).
+		if i == 0 {
+			if hv != 0x11 && hv != 0x21 && hv != 0x22 && hv != 0x12 {
+				return UnsupportedError("luma/chroma downsample ratio")
+			}
+		} else if hv != 0x11 {
+			return UnsupportedError("luma/chroma downsample ratio")
+		}
+	}
+	return nil
+}
+
+// Specified in section B.2.4.1.
+func (d *decoder) processDQT(n int) error {
+	const qtLength = 1 + blockSize
+	for ; n >= qtLength; n -= qtLength {
+		_, err := io.ReadFull(d.r, d.tmp[0:qtLength])
+		if err != nil {
+			return err
+		}
+		pq := d.tmp[0] >> 4
+		if pq != 0 {
+			return UnsupportedError("bad Pq value")
+		}
+		tq := d.tmp[0] & 0x0f
+		if tq > maxTq {
+			return FormatError("bad Tq value")
+		}
+		for i := range d.quant[tq] {
+			d.quant[tq][i] = int32(d.tmp[i+1])
+		}
+	}
+	if n != 0 {
+		return FormatError("DQT has wrong length")
+	}
+	return nil
+}
+
+// Specified in section B.2.4.4.
+func (d *decoder) processDRI(n int) error {
+	if n != 2 {
+		return FormatError("DRI has wrong length")
+	}
+	_, err := io.ReadFull(d.r, d.tmp[0:2])
+	if err != nil {
+		return err
+	}
+	d.ri = int(d.tmp[0])<<8 + int(d.tmp[1])
+	return nil
+}
+
+// decode reads a JPEG image from r and returns it as an image.Image.
+func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
+	if rr, ok := r.(Reader); ok {
+		d.r = rr
+	} else {
+		d.r = bufio.NewReader(r)
+	}
+
+	// Check for the Start Of Image marker.
+	_, err := io.ReadFull(d.r, d.tmp[0:2])
+	if err != nil {
+		return nil, err
+	}
+	if d.tmp[0] != 0xff || d.tmp[1] != soiMarker {
+		return nil, FormatError("missing SOI marker")
+	}
+
+	// Process the remaining segments until the End Of Image marker.
+	for {
+		_, err := io.ReadFull(d.r, d.tmp[0:2])
+		if err != nil {
+			return nil, err
+		}
+		for d.tmp[0] != 0xff {
+			// Strictly speaking, this is a format error. However, libjpeg is
+			// liberal in what it accepts. As of version 9, next_marker in
+			// jdmarker.c treats this as a warning (JWRN_EXTRANEOUS_DATA) and
+			// continues to decode the stream. Even before next_marker sees
+			// extraneous data, jpeg_fill_bit_buffer in jdhuff.c reads as many
+			// bytes as it can, possibly past the end of a scan's data. It
+			// effectively puts back any markers that it overscanned (e.g. an
+			// "\xff\xd9" EOI marker), but it does not put back non-marker data,
+			// and thus it can silently ignore a small number of extraneous
+			// non-marker bytes before next_marker has a chance to see them (and
+			// print a warning).
+			//
+			// We are therefore also liberal in what we accept. Extraneous data
+			// is silently ignored.
+			//
+			// This is similar to, but not exactly the same as, the restart
+			// mechanism within a scan (the RST[0-7] markers).
+			//
+			// Note that extraneous 0xff bytes in e.g. SOS data are escaped as
+			// "\xff\x00", and so are detected a little further down below.
+			d.tmp[0] = d.tmp[1]
+			d.tmp[1], err = d.r.ReadByte()
+			if err != nil {
+				return nil, err
+			}
+		}
+		marker := d.tmp[1]
+		if marker == 0 {
+			// Treat "\xff\x00" as extraneous data.
+			continue
+		}
+		for marker == 0xff {
+			// Section B.1.1.2 says, "Any marker may optionally be preceded by any
+			// number of fill bytes, which are bytes assigned code X'FF'".
+			marker, err = d.r.ReadByte()
+			if err != nil {
+				return nil, err
+			}
+		}
+		if marker == eoiMarker { // End Of Image.
+			break
+		}
+		if rst0Marker <= marker && marker <= rst7Marker {
+			// Figures B.2 and B.16 of the specification suggest that restart markers should
+			// only occur between Entropy Coded Segments and not after the final ECS.
+			// However, some encoders may generate incorrect JPEGs with a final restart
+			// marker. That restart marker will be seen here instead of inside the processSOS
+			// method, and is ignored as a harmless error. Restart markers have no extra data,
+			// so we check for this before we read the 16-bit length of the segment.
+			continue
+		}
+
+		// Read the 16-bit length of the segment. The value includes the 2 bytes for the
+		// length itself, so we subtract 2 to get the number of remaining bytes.
+		_, err = io.ReadFull(d.r, d.tmp[0:2])
+		if err != nil {
+			return nil, err
+		}
+		n := int(d.tmp[0])<<8 + int(d.tmp[1]) - 2
+		if n < 0 {
+			return nil, FormatError("short segment length")
+		}
+
+		switch {
+		case marker == sof0Marker || marker == sof2Marker: // Start Of Frame.
+			d.progressive = marker == sof2Marker
+			err = d.processSOF(n)
+			if configOnly {
+				return nil, err
+			}
+		case marker == dhtMarker: // Define Huffman Table.
+			err = d.processDHT(n)
+		case marker == dqtMarker: // Define Quantization Table.
+			err = d.processDQT(n)
+		case marker == sosMarker: // Start Of Scan.
+			err = d.processSOS(n)
+		case marker == driMarker: // Define Restart Interval.
+			err = d.processDRI(n)
+		case app0Marker <= marker && marker <= app15Marker || marker == comMarker: // APPlication specific, or COMment.
+			err = d.ignore(n)
+		default:
+			err = UnsupportedError("unknown marker")
+		}
+		if err != nil {
+			return nil, err
+		}
+	}
+	if d.img1 != nil {
+		return d.img1, nil
+	}
+	if d.img3 != nil {
+		return d.img3, nil
+	}
+	return nil, FormatError("missing SOS marker")
+}
+
+// Decode reads a JPEG image from r and returns it as an image.Image.
+func Decode(r io.Reader) (image.Image, error) {
+	var d decoder
+	return d.decode(r, false)
+}
+
+// DecodeConfig returns the color model and dimensions of a JPEG image without
+// decoding the entire image.
+func DecodeConfig(r io.Reader) (image.Config, error) {
+	var d decoder
+	if _, err := d.decode(r, true); err != nil {
+		return image.Config{}, err
+	}
+	switch d.nComp {
+	case nGrayComponent:
+		return image.Config{
+			ColorModel: color.GrayModel,
+			Width:      d.width,
+			Height:     d.height,
+		}, nil
+	case nColorComponent:
+		return image.Config{
+			ColorModel: color.YCbCrModel,
+			Width:      d.width,
+			Height:     d.height,
+		}, nil
+	}
+	return image.Config{}, FormatError("missing SOF marker")
+}
+
+func init() {
+	image.RegisterFormat("jpeg", "\xff\xd8", Decode, DecodeConfig)
+}
diff --git a/third_party/gofrontend/libgo/go/image/jpeg/reader_test.go b/third_party/gofrontend/libgo/go/image/jpeg/reader_test.go
new file mode 100644
index 0000000..926bb04
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/jpeg/reader_test.go
@@ -0,0 +1,225 @@
+// 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 jpeg
+
+import (
+	"bytes"
+	"fmt"
+	"image"
+	"image/color"
+	"io/ioutil"
+	"math/rand"
+	"os"
+	"strings"
+	"testing"
+)
+
+// TestDecodeProgressive tests that decoding the baseline and progressive
+// versions of the same image result in exactly the same pixel data, in YCbCr
+// space for color images, and Y space for grayscale images.
+func TestDecodeProgressive(t *testing.T) {
+	testCases := []string{
+		"../testdata/video-001",
+		"../testdata/video-001.q50.420",
+		"../testdata/video-001.q50.422",
+		"../testdata/video-001.q50.440",
+		"../testdata/video-001.q50.444",
+		"../testdata/video-005.gray.q50",
+		"../testdata/video-005.gray.q50.2x2",
+		"../testdata/video-001.separate.dc.progression",
+	}
+	for _, tc := range testCases {
+		m0, err := decodeFile(tc + ".jpeg")
+		if err != nil {
+			t.Errorf("%s: %v", tc+".jpeg", err)
+			continue
+		}
+		m1, err := decodeFile(tc + ".progressive.jpeg")
+		if err != nil {
+			t.Errorf("%s: %v", tc+".progressive.jpeg", err)
+			continue
+		}
+		if m0.Bounds() != m1.Bounds() {
+			t.Errorf("%s: bounds differ: %v and %v", tc, m0.Bounds(), m1.Bounds())
+			continue
+		}
+		// All of the video-*.jpeg files are 150x103.
+		if m0.Bounds() != image.Rect(0, 0, 150, 103) {
+			t.Errorf("%s: bad bounds: %v", tc, m0.Bounds())
+			continue
+		}
+
+		switch m0 := m0.(type) {
+		case *image.YCbCr:
+			m1 := m1.(*image.YCbCr)
+			if err := check(m0.Bounds(), m0.Y, m1.Y, m0.YStride, m1.YStride); err != nil {
+				t.Errorf("%s (Y): %v", tc, err)
+				continue
+			}
+			if err := check(m0.Bounds(), m0.Cb, m1.Cb, m0.CStride, m1.CStride); err != nil {
+				t.Errorf("%s (Cb): %v", tc, err)
+				continue
+			}
+			if err := check(m0.Bounds(), m0.Cr, m1.Cr, m0.CStride, m1.CStride); err != nil {
+				t.Errorf("%s (Cr): %v", tc, err)
+				continue
+			}
+		case *image.Gray:
+			m1 := m1.(*image.Gray)
+			if err := check(m0.Bounds(), m0.Pix, m1.Pix, m0.Stride, m1.Stride); err != nil {
+				t.Errorf("%s: %v", tc, err)
+				continue
+			}
+		default:
+			t.Errorf("%s: unexpected image type %T", tc, m0)
+			continue
+		}
+	}
+}
+
+func decodeFile(filename string) (image.Image, error) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	return Decode(f)
+
+}
+
+// check checks that the two pix data are equal, within the given bounds.
+func check(bounds image.Rectangle, pix0, pix1 []byte, stride0, stride1 int) error {
+	if stride0 <= 0 || stride0%8 != 0 {
+		return fmt.Errorf("bad stride %d", stride0)
+	}
+	if stride1 <= 0 || stride1%8 != 0 {
+		return fmt.Errorf("bad stride %d", stride1)
+	}
+	// Compare the two pix data, one 8x8 block at a time.
+	for y := 0; y < len(pix0)/stride0 && y < len(pix1)/stride1; y += 8 {
+		for x := 0; x < stride0 && x < stride1; x += 8 {
+			if x >= bounds.Max.X || y >= bounds.Max.Y {
+				// We don't care if the two pix data differ if the 8x8 block is
+				// entirely outside of the image's bounds. For example, this can
+				// occur with a 4:2:0 chroma subsampling and a 1x1 image. Baseline
+				// decoding works on the one 16x16 MCU as a whole; progressive
+				// decoding's first pass works on that 16x16 MCU as a whole but
+				// refinement passes only process one 8x8 block within the MCU.
+				continue
+			}
+
+			for j := 0; j < 8; j++ {
+				for i := 0; i < 8; i++ {
+					index0 := (y+j)*stride0 + (x + i)
+					index1 := (y+j)*stride1 + (x + i)
+					if pix0[index0] != pix1[index1] {
+						return fmt.Errorf("blocks at (%d, %d) differ:\n%sand\n%s", x, y,
+							pixString(pix0, stride0, x, y),
+							pixString(pix1, stride1, x, y),
+						)
+					}
+				}
+			}
+		}
+	}
+	return nil
+}
+
+func pixString(pix []byte, stride, x, y int) string {
+	s := bytes.NewBuffer(nil)
+	for j := 0; j < 8; j++ {
+		fmt.Fprintf(s, "\t")
+		for i := 0; i < 8; i++ {
+			fmt.Fprintf(s, "%02x ", pix[(y+j)*stride+(x+i)])
+		}
+		fmt.Fprintf(s, "\n")
+	}
+	return s.String()
+}
+
+func TestExtraneousData(t *testing.T) {
+	// Encode a 1x1 red image.
+	src := image.NewRGBA(image.Rect(0, 0, 1, 1))
+	src.Set(0, 0, color.RGBA{0xff, 0x00, 0x00, 0xff})
+	buf := new(bytes.Buffer)
+	if err := Encode(buf, src, nil); err != nil {
+		t.Fatalf("encode: %v", err)
+	}
+	enc := buf.String()
+	// Sanity check that the encoded JPEG is long enough, that it ends in a
+	// "\xff\xd9" EOI marker, and that it contains a "\xff\xda" SOS marker
+	// somewhere in the final 64 bytes.
+	if len(enc) < 64 {
+		t.Fatalf("encoded JPEG is too short: %d bytes", len(enc))
+	}
+	if got, want := enc[len(enc)-2:], "\xff\xd9"; got != want {
+		t.Fatalf("encoded JPEG ends with %q, want %q", got, want)
+	}
+	if s := enc[len(enc)-64:]; !strings.Contains(s, "\xff\xda") {
+		t.Fatalf("encoded JPEG does not contain a SOS marker (ff da) near the end: % x", s)
+	}
+	// Test that adding some random junk between the SOS marker and the
+	// EOI marker does not affect the decoding.
+	rnd := rand.New(rand.NewSource(1))
+	for i, nerr := 0, 0; i < 1000 && nerr < 10; i++ {
+		buf.Reset()
+		// Write all but the trailing "\xff\xd9" EOI marker.
+		buf.WriteString(enc[:len(enc)-2])
+		// Write some random extraneous data.
+		for n := rnd.Intn(10); n > 0; n-- {
+			if x := byte(rnd.Intn(256)); x != 0xff {
+				buf.WriteByte(x)
+			} else {
+				// The JPEG format escapes a SOS 0xff data byte as "\xff\x00".
+				buf.WriteString("\xff\x00")
+			}
+		}
+		// Write the "\xff\xd9" EOI marker.
+		buf.WriteString("\xff\xd9")
+
+		// Check that we can still decode the resultant image.
+		got, err := Decode(buf)
+		if err != nil {
+			t.Errorf("could not decode image #%d: %v", i, err)
+			nerr++
+			continue
+		}
+		if got.Bounds() != src.Bounds() {
+			t.Errorf("image #%d, bounds differ: %v and %v", i, got.Bounds(), src.Bounds())
+			nerr++
+			continue
+		}
+		if averageDelta(got, src) > 2<<8 {
+			t.Errorf("image #%d changed too much after a round trip", i)
+			nerr++
+			continue
+		}
+	}
+}
+
+func benchmarkDecode(b *testing.B, filename string) {
+	b.StopTimer()
+	data, err := ioutil.ReadFile(filename)
+	if err != nil {
+		b.Fatal(err)
+	}
+	cfg, err := DecodeConfig(bytes.NewReader(data))
+	if err != nil {
+		b.Fatal(err)
+	}
+	b.SetBytes(int64(cfg.Width * cfg.Height * 4))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Decode(bytes.NewReader(data))
+	}
+}
+
+func BenchmarkDecodeBaseline(b *testing.B) {
+	benchmarkDecode(b, "../testdata/video-001.jpeg")
+}
+
+func BenchmarkDecodeProgressive(b *testing.B) {
+	benchmarkDecode(b, "../testdata/video-001.progressive.jpeg")
+}
diff --git a/third_party/gofrontend/libgo/go/image/jpeg/scan.go b/third_party/gofrontend/libgo/go/image/jpeg/scan.go
new file mode 100644
index 0000000..559235d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/jpeg/scan.go
@@ -0,0 +1,439 @@
+// 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 jpeg
+
+import (
+	"image"
+	"io"
+)
+
+// makeImg allocates and initializes the destination image.
+func (d *decoder) makeImg(h0, v0, mxx, myy int) {
+	if d.nComp == nGrayComponent {
+		m := image.NewGray(image.Rect(0, 0, 8*mxx, 8*myy))
+		d.img1 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.Gray)
+		return
+	}
+	var subsampleRatio image.YCbCrSubsampleRatio
+	switch {
+	case h0 == 1 && v0 == 1:
+		subsampleRatio = image.YCbCrSubsampleRatio444
+	case h0 == 1 && v0 == 2:
+		subsampleRatio = image.YCbCrSubsampleRatio440
+	case h0 == 2 && v0 == 1:
+		subsampleRatio = image.YCbCrSubsampleRatio422
+	case h0 == 2 && v0 == 2:
+		subsampleRatio = image.YCbCrSubsampleRatio420
+	default:
+		panic("unreachable")
+	}
+	m := image.NewYCbCr(image.Rect(0, 0, 8*h0*mxx, 8*v0*myy), subsampleRatio)
+	d.img3 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.YCbCr)
+}
+
+// Specified in section B.2.3.
+func (d *decoder) processSOS(n int) error {
+	if d.nComp == 0 {
+		return FormatError("missing SOF marker")
+	}
+	if n < 6 || 4+2*d.nComp < n || n%2 != 0 {
+		return FormatError("SOS has wrong length")
+	}
+	_, err := io.ReadFull(d.r, d.tmp[:n])
+	if err != nil {
+		return err
+	}
+	nComp := int(d.tmp[0])
+	if n != 4+2*nComp {
+		return FormatError("SOS length inconsistent with number of components")
+	}
+	var scan [nColorComponent]struct {
+		compIndex uint8
+		td        uint8 // DC table selector.
+		ta        uint8 // AC table selector.
+	}
+	for i := 0; i < nComp; i++ {
+		cs := d.tmp[1+2*i] // Component selector.
+		compIndex := -1
+		for j, comp := range d.comp {
+			if cs == comp.c {
+				compIndex = j
+			}
+		}
+		if compIndex < 0 {
+			return FormatError("unknown component selector")
+		}
+		scan[i].compIndex = uint8(compIndex)
+		scan[i].td = d.tmp[2+2*i] >> 4
+		scan[i].ta = d.tmp[2+2*i] & 0x0f
+	}
+
+	// zigStart and zigEnd are the spectral selection bounds.
+	// ah and al are the successive approximation high and low values.
+	// The spec calls these values Ss, Se, Ah and Al.
+	//
+	// For progressive JPEGs, these are the two more-or-less independent
+	// aspects of progression. Spectral selection progression is when not
+	// all of a block's 64 DCT coefficients are transmitted in one pass.
+	// For example, three passes could transmit coefficient 0 (the DC
+	// component), coefficients 1-5, and coefficients 6-63, in zig-zag
+	// order. Successive approximation is when not all of the bits of a
+	// band of coefficients are transmitted in one pass. For example,
+	// three passes could transmit the 6 most significant bits, followed
+	// by the second-least significant bit, followed by the least
+	// significant bit.
+	//
+	// For baseline JPEGs, these parameters are hard-coded to 0/63/0/0.
+	zigStart, zigEnd, ah, al := int32(0), int32(blockSize-1), uint32(0), uint32(0)
+	if d.progressive {
+		zigStart = int32(d.tmp[1+2*nComp])
+		zigEnd = int32(d.tmp[2+2*nComp])
+		ah = uint32(d.tmp[3+2*nComp] >> 4)
+		al = uint32(d.tmp[3+2*nComp] & 0x0f)
+		if (zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || blockSize <= zigEnd {
+			return FormatError("bad spectral selection bounds")
+		}
+		if zigStart != 0 && nComp != 1 {
+			return FormatError("progressive AC coefficients for more than one component")
+		}
+		if ah != 0 && ah != al+1 {
+			return FormatError("bad successive approximation values")
+		}
+	}
+
+	// mxx and myy are the number of MCUs (Minimum Coded Units) in the image.
+	h0, v0 := d.comp[0].h, d.comp[0].v // The h and v values from the Y components.
+	mxx := (d.width + 8*h0 - 1) / (8 * h0)
+	myy := (d.height + 8*v0 - 1) / (8 * v0)
+	if d.img1 == nil && d.img3 == nil {
+		d.makeImg(h0, v0, mxx, myy)
+	}
+	if d.progressive {
+		for i := 0; i < nComp; i++ {
+			compIndex := scan[i].compIndex
+			if d.progCoeffs[compIndex] == nil {
+				d.progCoeffs[compIndex] = make([]block, mxx*myy*d.comp[compIndex].h*d.comp[compIndex].v)
+			}
+		}
+	}
+
+	d.b = bits{}
+	mcu, expectedRST := 0, uint8(rst0Marker)
+	var (
+		// b is the decoded coefficients, in natural (not zig-zag) order.
+		b  block
+		dc [nColorComponent]int32
+		// mx0 and my0 are the location of the current (in terms of 8x8 blocks).
+		// For example, with 4:2:0 chroma subsampling, the block whose top left
+		// pixel co-ordinates are (16, 8) is the third block in the first row:
+		// mx0 is 2 and my0 is 0, even though the pixel is in the second MCU.
+		// TODO(nigeltao): rename mx0 and my0 to bx and by?
+		mx0, my0   int
+		blockCount int
+	)
+	for my := 0; my < myy; my++ {
+		for mx := 0; mx < mxx; mx++ {
+			for i := 0; i < nComp; i++ {
+				compIndex := scan[i].compIndex
+				qt := &d.quant[d.comp[compIndex].tq]
+				for j := 0; j < d.comp[compIndex].h*d.comp[compIndex].v; j++ {
+					// The blocks are traversed one MCU at a time. For 4:2:0 chroma
+					// subsampling, there are four Y 8x8 blocks in every 16x16 MCU.
+					//
+					// For a baseline 32x16 pixel image, the Y blocks visiting order is:
+					//	0 1 4 5
+					//	2 3 6 7
+					//
+					// For progressive images, the interleaved scans (those with nComp > 1)
+					// are traversed as above, but non-interleaved scans are traversed left
+					// to right, top to bottom:
+					//	0 1 2 3
+					//	4 5 6 7
+					// Only DC scans (zigStart == 0) can be interleaved. AC scans must have
+					// only one component.
+					//
+					// To further complicate matters, for non-interleaved scans, there is no
+					// data for any blocks that are inside the image at the MCU level but
+					// outside the image at the pixel level. For example, a 24x16 pixel 4:2:0
+					// progressive image consists of two 16x16 MCUs. The interleaved scans
+					// will process 8 Y blocks:
+					//	0 1 4 5
+					//	2 3 6 7
+					// The non-interleaved scans will process only 6 Y blocks:
+					//	0 1 2
+					//	3 4 5
+					if nComp != 1 {
+						mx0, my0 = d.comp[compIndex].h*mx, d.comp[compIndex].v*my
+						if h0 == 1 {
+							my0 += j
+						} else {
+							mx0 += j % 2
+							my0 += j / 2
+						}
+					} else {
+						q := mxx * d.comp[compIndex].h
+						mx0 = blockCount % q
+						my0 = blockCount / q
+						blockCount++
+						if mx0*8 >= d.width || my0*8 >= d.height {
+							continue
+						}
+					}
+
+					// Load the previous partially decoded coefficients, if applicable.
+					if d.progressive {
+						b = d.progCoeffs[compIndex][my0*mxx*d.comp[compIndex].h+mx0]
+					} else {
+						b = block{}
+					}
+
+					if ah != 0 {
+						if err := d.refine(&b, &d.huff[acTable][scan[i].ta], zigStart, zigEnd, 1<<al); err != nil {
+							return err
+						}
+					} else {
+						zig := zigStart
+						if zig == 0 {
+							zig++
+							// Decode the DC coefficient, as specified in section F.2.2.1.
+							value, err := d.decodeHuffman(&d.huff[dcTable][scan[i].td])
+							if err != nil {
+								return err
+							}
+							if value > 16 {
+								return UnsupportedError("excessive DC component")
+							}
+							dcDelta, err := d.receiveExtend(value)
+							if err != nil {
+								return err
+							}
+							dc[compIndex] += dcDelta
+							b[0] = dc[compIndex] << al
+						}
+
+						if zig <= zigEnd && d.eobRun > 0 {
+							d.eobRun--
+						} else {
+							// Decode the AC coefficients, as specified in section F.2.2.2.
+							for ; zig <= zigEnd; zig++ {
+								value, err := d.decodeHuffman(&d.huff[acTable][scan[i].ta])
+								if err != nil {
+									return err
+								}
+								val0 := value >> 4
+								val1 := value & 0x0f
+								if val1 != 0 {
+									zig += int32(val0)
+									if zig > zigEnd {
+										break
+									}
+									ac, err := d.receiveExtend(val1)
+									if err != nil {
+										return err
+									}
+									b[unzig[zig]] = ac << al
+								} else {
+									if val0 != 0x0f {
+										d.eobRun = uint16(1 << val0)
+										if val0 != 0 {
+											bits, err := d.decodeBits(int(val0))
+											if err != nil {
+												return err
+											}
+											d.eobRun |= uint16(bits)
+										}
+										d.eobRun--
+										break
+									}
+									zig += 0x0f
+								}
+							}
+						}
+					}
+
+					if d.progressive {
+						if zigEnd != blockSize-1 || al != 0 {
+							// We haven't completely decoded this 8x8 block. Save the coefficients.
+							d.progCoeffs[compIndex][my0*mxx*d.comp[compIndex].h+mx0] = b
+							// At this point, we could execute the rest of the loop body to dequantize and
+							// perform the inverse DCT, to save early stages of a progressive image to the
+							// *image.YCbCr buffers (the whole point of progressive encoding), but in Go,
+							// the jpeg.Decode function does not return until the entire image is decoded,
+							// so we "continue" here to avoid wasted computation.
+							continue
+						}
+					}
+
+					// Dequantize, perform the inverse DCT and store the block to the image.
+					for zig := 0; zig < blockSize; zig++ {
+						b[unzig[zig]] *= qt[zig]
+					}
+					idct(&b)
+					dst, stride := []byte(nil), 0
+					if d.nComp == nGrayComponent {
+						dst, stride = d.img1.Pix[8*(my0*d.img1.Stride+mx0):], d.img1.Stride
+					} else {
+						switch compIndex {
+						case 0:
+							dst, stride = d.img3.Y[8*(my0*d.img3.YStride+mx0):], d.img3.YStride
+						case 1:
+							dst, stride = d.img3.Cb[8*(my0*d.img3.CStride+mx0):], d.img3.CStride
+						case 2:
+							dst, stride = d.img3.Cr[8*(my0*d.img3.CStride+mx0):], d.img3.CStride
+						default:
+							return UnsupportedError("too many components")
+						}
+					}
+					// Level shift by +128, clip to [0, 255], and write to dst.
+					for y := 0; y < 8; y++ {
+						y8 := y * 8
+						yStride := y * stride
+						for x := 0; x < 8; x++ {
+							c := b[y8+x]
+							if c < -128 {
+								c = 0
+							} else if c > 127 {
+								c = 255
+							} else {
+								c += 128
+							}
+							dst[yStride+x] = uint8(c)
+						}
+					}
+				} // for j
+			} // for i
+			mcu++
+			if d.ri > 0 && mcu%d.ri == 0 && mcu < mxx*myy {
+				// A more sophisticated decoder could use RST[0-7] markers to resynchronize from corrupt input,
+				// but this one assumes well-formed input, and hence the restart marker follows immediately.
+				_, err := io.ReadFull(d.r, d.tmp[0:2])
+				if err != nil {
+					return err
+				}
+				if d.tmp[0] != 0xff || d.tmp[1] != expectedRST {
+					return FormatError("bad RST marker")
+				}
+				expectedRST++
+				if expectedRST == rst7Marker+1 {
+					expectedRST = rst0Marker
+				}
+				// Reset the Huffman decoder.
+				d.b = bits{}
+				// Reset the DC components, as per section F.2.1.3.1.
+				dc = [nColorComponent]int32{}
+				// Reset the progressive decoder state, as per section G.1.2.2.
+				d.eobRun = 0
+			}
+		} // for mx
+	} // for my
+
+	return nil
+}
+
+// refine decodes a successive approximation refinement block, as specified in
+// section G.1.2.
+func (d *decoder) refine(b *block, h *huffman, zigStart, zigEnd, delta int32) error {
+	// Refining a DC component is trivial.
+	if zigStart == 0 {
+		if zigEnd != 0 {
+			panic("unreachable")
+		}
+		bit, err := d.decodeBit()
+		if err != nil {
+			return err
+		}
+		if bit {
+			b[0] |= delta
+		}
+		return nil
+	}
+
+	// Refining AC components is more complicated; see sections G.1.2.2 and G.1.2.3.
+	zig := zigStart
+	if d.eobRun == 0 {
+	loop:
+		for ; zig <= zigEnd; zig++ {
+			z := int32(0)
+			value, err := d.decodeHuffman(h)
+			if err != nil {
+				return err
+			}
+			val0 := value >> 4
+			val1 := value & 0x0f
+
+			switch val1 {
+			case 0:
+				if val0 != 0x0f {
+					d.eobRun = uint16(1 << val0)
+					if val0 != 0 {
+						bits, err := d.decodeBits(int(val0))
+						if err != nil {
+							return err
+						}
+						d.eobRun |= uint16(bits)
+					}
+					break loop
+				}
+			case 1:
+				z = delta
+				bit, err := d.decodeBit()
+				if err != nil {
+					return err
+				}
+				if !bit {
+					z = -z
+				}
+			default:
+				return FormatError("unexpected Huffman code")
+			}
+
+			zig, err = d.refineNonZeroes(b, zig, zigEnd, int32(val0), delta)
+			if err != nil {
+				return err
+			}
+			if zig > zigEnd {
+				return FormatError("too many coefficients")
+			}
+			if z != 0 {
+				b[unzig[zig]] = z
+			}
+		}
+	}
+	if d.eobRun > 0 {
+		d.eobRun--
+		if _, err := d.refineNonZeroes(b, zig, zigEnd, -1, delta); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// refineNonZeroes refines non-zero entries of b in zig-zag order. If nz >= 0,
+// the first nz zero entries are skipped over.
+func (d *decoder) refineNonZeroes(b *block, zig, zigEnd, nz, delta int32) (int32, error) {
+	for ; zig <= zigEnd; zig++ {
+		u := unzig[zig]
+		if b[u] == 0 {
+			if nz == 0 {
+				break
+			}
+			nz--
+			continue
+		}
+		bit, err := d.decodeBit()
+		if err != nil {
+			return 0, err
+		}
+		if !bit {
+			continue
+		}
+		if b[u] >= 0 {
+			b[u] += delta
+		} else {
+			b[u] -= delta
+		}
+	}
+	return zig, nil
+}
diff --git a/third_party/gofrontend/libgo/go/image/jpeg/writer.go b/third_party/gofrontend/libgo/go/image/jpeg/writer.go
new file mode 100644
index 0000000..c58fbf3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/jpeg/writer.go
@@ -0,0 +1,553 @@
+// 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.
+
+package jpeg
+
+import (
+	"bufio"
+	"errors"
+	"image"
+	"image/color"
+	"io"
+)
+
+// min returns the minimum of two integers.
+func min(x, y int) int {
+	if x < y {
+		return x
+	}
+	return y
+}
+
+// div returns a/b rounded to the nearest integer, instead of rounded to zero.
+func div(a, b int32) int32 {
+	if a >= 0 {
+		return (a + (b >> 1)) / b
+	}
+	return -((-a + (b >> 1)) / b)
+}
+
+// bitCount counts the number of bits needed to hold an integer.
+var bitCount = [256]byte{
+	0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+}
+
+type quantIndex int
+
+const (
+	quantIndexLuminance quantIndex = iota
+	quantIndexChrominance
+	nQuantIndex
+)
+
+// unscaledQuant are the unscaled quantization tables in zig-zag order. Each
+// encoder copies and scales the tables according to its quality parameter.
+// The values are derived from section K.1 after converting from natural to
+// zig-zag order.
+var unscaledQuant = [nQuantIndex][blockSize]byte{
+	// Luminance.
+	{
+		16, 11, 12, 14, 12, 10, 16, 14,
+		13, 14, 18, 17, 16, 19, 24, 40,
+		26, 24, 22, 22, 24, 49, 35, 37,
+		29, 40, 58, 51, 61, 60, 57, 51,
+		56, 55, 64, 72, 92, 78, 64, 68,
+		87, 69, 55, 56, 80, 109, 81, 87,
+		95, 98, 103, 104, 103, 62, 77, 113,
+		121, 112, 100, 120, 92, 101, 103, 99,
+	},
+	// Chrominance.
+	{
+		17, 18, 18, 24, 21, 24, 47, 26,
+		26, 47, 99, 66, 56, 66, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+	},
+}
+
+type huffIndex int
+
+const (
+	huffIndexLuminanceDC huffIndex = iota
+	huffIndexLuminanceAC
+	huffIndexChrominanceDC
+	huffIndexChrominanceAC
+	nHuffIndex
+)
+
+// huffmanSpec specifies a Huffman encoding.
+type huffmanSpec struct {
+	// count[i] is the number of codes of length i bits.
+	count [16]byte
+	// value[i] is the decoded value of the i'th codeword.
+	value []byte
+}
+
+// theHuffmanSpec is the Huffman encoding specifications.
+// This encoder uses the same Huffman encoding for all images.
+var theHuffmanSpec = [nHuffIndex]huffmanSpec{
+	// Luminance DC.
+	{
+		[16]byte{0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},
+		[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
+	},
+	// Luminance AC.
+	{
+		[16]byte{0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125},
+		[]byte{
+			0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+			0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+			0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+			0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+			0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+			0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+			0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+			0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+			0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+			0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+			0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+			0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+			0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+			0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+			0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+			0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+			0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+			0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+			0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+			0xf9, 0xfa,
+		},
+	},
+	// Chrominance DC.
+	{
+		[16]byte{0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
+		[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
+	},
+	// Chrominance AC.
+	{
+		[16]byte{0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119},
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+			0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+			0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+			0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+			0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+			0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+			0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+			0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+			0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+			0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+			0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+			0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+			0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+			0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+			0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+			0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+			0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+			0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+			0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+			0xf9, 0xfa,
+		},
+	},
+}
+
+// huffmanLUT is a compiled look-up table representation of a huffmanSpec.
+// Each value maps to a uint32 of which the 8 most significant bits hold the
+// codeword size in bits and the 24 least significant bits hold the codeword.
+// The maximum codeword size is 16 bits.
+type huffmanLUT []uint32
+
+func (h *huffmanLUT) init(s huffmanSpec) {
+	maxValue := 0
+	for _, v := range s.value {
+		if int(v) > maxValue {
+			maxValue = int(v)
+		}
+	}
+	*h = make([]uint32, maxValue+1)
+	code, k := uint32(0), 0
+	for i := 0; i < len(s.count); i++ {
+		nBits := uint32(i+1) << 24
+		for j := uint8(0); j < s.count[i]; j++ {
+			(*h)[s.value[k]] = nBits | code
+			code++
+			k++
+		}
+		code <<= 1
+	}
+}
+
+// theHuffmanLUT are compiled representations of theHuffmanSpec.
+var theHuffmanLUT [4]huffmanLUT
+
+func init() {
+	for i, s := range theHuffmanSpec {
+		theHuffmanLUT[i].init(s)
+	}
+}
+
+// writer is a buffered writer.
+type writer interface {
+	Flush() error
+	io.Writer
+	io.ByteWriter
+}
+
+// encoder encodes an image to the JPEG format.
+type encoder struct {
+	// w is the writer to write to. err is the first error encountered during
+	// writing. All attempted writes after the first error become no-ops.
+	w   writer
+	err error
+	// buf is a scratch buffer.
+	buf [16]byte
+	// bits and nBits are accumulated bits to write to w.
+	bits, nBits uint32
+	// quant is the scaled quantization tables, in zig-zag order.
+	quant [nQuantIndex][blockSize]byte
+}
+
+func (e *encoder) flush() {
+	if e.err != nil {
+		return
+	}
+	e.err = e.w.Flush()
+}
+
+func (e *encoder) write(p []byte) {
+	if e.err != nil {
+		return
+	}
+	_, e.err = e.w.Write(p)
+}
+
+func (e *encoder) writeByte(b byte) {
+	if e.err != nil {
+		return
+	}
+	e.err = e.w.WriteByte(b)
+}
+
+// emit emits the least significant nBits bits of bits to the bitstream.
+// The precondition is bits < 1<<nBits && nBits <= 16.
+func (e *encoder) emit(bits, nBits uint32) {
+	nBits += e.nBits
+	bits <<= 32 - nBits
+	bits |= e.bits
+	for nBits >= 8 {
+		b := uint8(bits >> 24)
+		e.writeByte(b)
+		if b == 0xff {
+			e.writeByte(0x00)
+		}
+		bits <<= 8
+		nBits -= 8
+	}
+	e.bits, e.nBits = bits, nBits
+}
+
+// emitHuff emits the given value with the given Huffman encoder.
+func (e *encoder) emitHuff(h huffIndex, value int32) {
+	x := theHuffmanLUT[h][value]
+	e.emit(x&(1<<24-1), x>>24)
+}
+
+// emitHuffRLE emits a run of runLength copies of value encoded with the given
+// Huffman encoder.
+func (e *encoder) emitHuffRLE(h huffIndex, runLength, value int32) {
+	a, b := value, value
+	if a < 0 {
+		a, b = -value, value-1
+	}
+	var nBits uint32
+	if a < 0x100 {
+		nBits = uint32(bitCount[a])
+	} else {
+		nBits = 8 + uint32(bitCount[a>>8])
+	}
+	e.emitHuff(h, runLength<<4|int32(nBits))
+	if nBits > 0 {
+		e.emit(uint32(b)&(1<<nBits-1), nBits)
+	}
+}
+
+// writeMarkerHeader writes the header for a marker with the given length.
+func (e *encoder) writeMarkerHeader(marker uint8, markerlen int) {
+	e.buf[0] = 0xff
+	e.buf[1] = marker
+	e.buf[2] = uint8(markerlen >> 8)
+	e.buf[3] = uint8(markerlen & 0xff)
+	e.write(e.buf[:4])
+}
+
+// writeDQT writes the Define Quantization Table marker.
+func (e *encoder) writeDQT() {
+	const markerlen = 2 + int(nQuantIndex)*(1+blockSize)
+	e.writeMarkerHeader(dqtMarker, markerlen)
+	for i := range e.quant {
+		e.writeByte(uint8(i))
+		e.write(e.quant[i][:])
+	}
+}
+
+// writeSOF0 writes the Start Of Frame (Baseline) marker.
+func (e *encoder) writeSOF0(size image.Point) {
+	const markerlen = 8 + 3*nColorComponent
+	e.writeMarkerHeader(sof0Marker, markerlen)
+	e.buf[0] = 8 // 8-bit color.
+	e.buf[1] = uint8(size.Y >> 8)
+	e.buf[2] = uint8(size.Y & 0xff)
+	e.buf[3] = uint8(size.X >> 8)
+	e.buf[4] = uint8(size.X & 0xff)
+	e.buf[5] = nColorComponent
+	for i := 0; i < nColorComponent; i++ {
+		e.buf[3*i+6] = uint8(i + 1)
+		// We use 4:2:0 chroma subsampling.
+		e.buf[3*i+7] = "\x22\x11\x11"[i]
+		e.buf[3*i+8] = "\x00\x01\x01"[i]
+	}
+	e.write(e.buf[:3*(nColorComponent-1)+9])
+}
+
+// writeDHT writes the Define Huffman Table marker.
+func (e *encoder) writeDHT() {
+	markerlen := 2
+	for _, s := range theHuffmanSpec {
+		markerlen += 1 + 16 + len(s.value)
+	}
+	e.writeMarkerHeader(dhtMarker, markerlen)
+	for i, s := range theHuffmanSpec {
+		e.writeByte("\x00\x10\x01\x11"[i])
+		e.write(s.count[:])
+		e.write(s.value)
+	}
+}
+
+// writeBlock writes a block of pixel data using the given quantization table,
+// returning the post-quantized DC value of the DCT-transformed block.
+// b is in natural (not zig-zag) order.
+func (e *encoder) writeBlock(b *block, q quantIndex, prevDC int32) int32 {
+	fdct(b)
+	// Emit the DC delta.
+	dc := div(b[0], 8*int32(e.quant[q][0]))
+	e.emitHuffRLE(huffIndex(2*q+0), 0, dc-prevDC)
+	// Emit the AC components.
+	h, runLength := huffIndex(2*q+1), int32(0)
+	for zig := 1; zig < blockSize; zig++ {
+		ac := div(b[unzig[zig]], 8*int32(e.quant[q][zig]))
+		if ac == 0 {
+			runLength++
+		} else {
+			for runLength > 15 {
+				e.emitHuff(h, 0xf0)
+				runLength -= 16
+			}
+			e.emitHuffRLE(h, runLength, ac)
+			runLength = 0
+		}
+	}
+	if runLength > 0 {
+		e.emitHuff(h, 0x00)
+	}
+	return dc
+}
+
+// toYCbCr converts the 8x8 region of m whose top-left corner is p to its
+// YCbCr values.
+func toYCbCr(m image.Image, p image.Point, yBlock, cbBlock, crBlock *block) {
+	b := m.Bounds()
+	xmax := b.Max.X - 1
+	ymax := b.Max.Y - 1
+	for j := 0; j < 8; j++ {
+		for i := 0; i < 8; i++ {
+			r, g, b, _ := m.At(min(p.X+i, xmax), min(p.Y+j, ymax)).RGBA()
+			yy, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
+			yBlock[8*j+i] = int32(yy)
+			cbBlock[8*j+i] = int32(cb)
+			crBlock[8*j+i] = int32(cr)
+		}
+	}
+}
+
+// rgbaToYCbCr is a specialized version of toYCbCr for image.RGBA images.
+func rgbaToYCbCr(m *image.RGBA, p image.Point, yBlock, cbBlock, crBlock *block) {
+	b := m.Bounds()
+	xmax := b.Max.X - 1
+	ymax := b.Max.Y - 1
+	for j := 0; j < 8; j++ {
+		sj := p.Y + j
+		if sj > ymax {
+			sj = ymax
+		}
+		offset := (sj-b.Min.Y)*m.Stride - b.Min.X*4
+		for i := 0; i < 8; i++ {
+			sx := p.X + i
+			if sx > xmax {
+				sx = xmax
+			}
+			pix := m.Pix[offset+sx*4:]
+			yy, cb, cr := color.RGBToYCbCr(pix[0], pix[1], pix[2])
+			yBlock[8*j+i] = int32(yy)
+			cbBlock[8*j+i] = int32(cb)
+			crBlock[8*j+i] = int32(cr)
+		}
+	}
+}
+
+// scale scales the 16x16 region represented by the 4 src blocks to the 8x8
+// dst block.
+func scale(dst *block, src *[4]block) {
+	for i := 0; i < 4; i++ {
+		dstOff := (i&2)<<4 | (i&1)<<2
+		for y := 0; y < 4; y++ {
+			for x := 0; x < 4; x++ {
+				j := 16*y + 2*x
+				sum := src[i][j] + src[i][j+1] + src[i][j+8] + src[i][j+9]
+				dst[8*y+x+dstOff] = (sum + 2) >> 2
+			}
+		}
+	}
+}
+
+// sosHeader is the SOS marker "\xff\xda" followed by 12 bytes:
+//	- the marker length "\x00\x0c",
+//	- the number of components "\x03",
+//	- component 1 uses DC table 0 and AC table 0 "\x01\x00",
+//	- component 2 uses DC table 1 and AC table 1 "\x02\x11",
+//	- component 3 uses DC table 1 and AC table 1 "\x03\x11",
+//	- the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for
+//	  sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al)
+//	  should be 0x00, 0x3f, 0x00<<4 | 0x00.
+var sosHeader = []byte{
+	0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
+	0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
+}
+
+// writeSOS writes the StartOfScan marker.
+func (e *encoder) writeSOS(m image.Image) {
+	e.write(sosHeader)
+	var (
+		// Scratch buffers to hold the YCbCr values.
+		// The blocks are in natural (not zig-zag) order.
+		b      block
+		cb, cr [4]block
+		// DC components are delta-encoded.
+		prevDCY, prevDCCb, prevDCCr int32
+	)
+	bounds := m.Bounds()
+	rgba, _ := m.(*image.RGBA)
+	for y := bounds.Min.Y; y < bounds.Max.Y; y += 16 {
+		for x := bounds.Min.X; x < bounds.Max.X; x += 16 {
+			for i := 0; i < 4; i++ {
+				xOff := (i & 1) * 8
+				yOff := (i & 2) * 4
+				p := image.Pt(x+xOff, y+yOff)
+				if rgba != nil {
+					rgbaToYCbCr(rgba, p, &b, &cb[i], &cr[i])
+				} else {
+					toYCbCr(m, p, &b, &cb[i], &cr[i])
+				}
+				prevDCY = e.writeBlock(&b, 0, prevDCY)
+			}
+			scale(&b, &cb)
+			prevDCCb = e.writeBlock(&b, 1, prevDCCb)
+			scale(&b, &cr)
+			prevDCCr = e.writeBlock(&b, 1, prevDCCr)
+		}
+	}
+	// Pad the last byte with 1's.
+	e.emit(0x7f, 7)
+}
+
+// DefaultQuality is the default quality encoding parameter.
+const DefaultQuality = 75
+
+// Options are the encoding parameters.
+// Quality ranges from 1 to 100 inclusive, higher is better.
+type Options struct {
+	Quality int
+}
+
+// Encode writes the Image m to w in JPEG 4:2:0 baseline format with the given
+// options. Default parameters are used if a nil *Options is passed.
+func Encode(w io.Writer, m image.Image, o *Options) error {
+	b := m.Bounds()
+	if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 {
+		return errors.New("jpeg: image is too large to encode")
+	}
+	var e encoder
+	if ww, ok := w.(writer); ok {
+		e.w = ww
+	} else {
+		e.w = bufio.NewWriter(w)
+	}
+	// Clip quality to [1, 100].
+	quality := DefaultQuality
+	if o != nil {
+		quality = o.Quality
+		if quality < 1 {
+			quality = 1
+		} else if quality > 100 {
+			quality = 100
+		}
+	}
+	// Convert from a quality rating to a scaling factor.
+	var scale int
+	if quality < 50 {
+		scale = 5000 / quality
+	} else {
+		scale = 200 - quality*2
+	}
+	// Initialize the quantization tables.
+	for i := range e.quant {
+		for j := range e.quant[i] {
+			x := int(unscaledQuant[i][j])
+			x = (x*scale + 50) / 100
+			if x < 1 {
+				x = 1
+			} else if x > 255 {
+				x = 255
+			}
+			e.quant[i][j] = uint8(x)
+		}
+	}
+	// Write the Start Of Image marker.
+	e.buf[0] = 0xff
+	e.buf[1] = 0xd8
+	e.write(e.buf[:2])
+	// Write the quantization tables.
+	e.writeDQT()
+	// Write the image dimensions.
+	e.writeSOF0(b.Size())
+	// Write the Huffman tables.
+	e.writeDHT()
+	// Write the image data.
+	e.writeSOS(m)
+	// Write the End Of Image marker.
+	e.buf[0] = 0xff
+	e.buf[1] = 0xd9
+	e.write(e.buf[:2])
+	e.flush()
+	return e.err
+}
diff --git a/third_party/gofrontend/libgo/go/image/jpeg/writer_test.go b/third_party/gofrontend/libgo/go/image/jpeg/writer_test.go
new file mode 100644
index 0000000..514b455
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/jpeg/writer_test.go
@@ -0,0 +1,204 @@
+// 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.
+
+package jpeg
+
+import (
+	"bytes"
+	"fmt"
+	"image"
+	"image/color"
+	"image/png"
+	"io/ioutil"
+	"math/rand"
+	"os"
+	"testing"
+)
+
+// zigzag maps from the natural ordering to the zig-zag ordering. For example,
+// zigzag[0*8 + 3] is the zig-zag sequence number of the element in the fourth
+// column and first row.
+var zigzag = [blockSize]int{
+	0, 1, 5, 6, 14, 15, 27, 28,
+	2, 4, 7, 13, 16, 26, 29, 42,
+	3, 8, 12, 17, 25, 30, 41, 43,
+	9, 11, 18, 24, 31, 40, 44, 53,
+	10, 19, 23, 32, 39, 45, 52, 54,
+	20, 22, 33, 38, 46, 51, 55, 60,
+	21, 34, 37, 47, 50, 56, 59, 61,
+	35, 36, 48, 49, 57, 58, 62, 63,
+}
+
+func TestZigUnzig(t *testing.T) {
+	for i := 0; i < blockSize; i++ {
+		if unzig[zigzag[i]] != i {
+			t.Errorf("unzig[zigzag[%d]] == %d", i, unzig[zigzag[i]])
+		}
+		if zigzag[unzig[i]] != i {
+			t.Errorf("zigzag[unzig[%d]] == %d", i, zigzag[unzig[i]])
+		}
+	}
+}
+
+// unscaledQuantInNaturalOrder are the unscaled quantization tables in
+// natural (not zig-zag) order, as specified in section K.1.
+var unscaledQuantInNaturalOrder = [nQuantIndex][blockSize]byte{
+	// Luminance.
+	{
+		16, 11, 10, 16, 24, 40, 51, 61,
+		12, 12, 14, 19, 26, 58, 60, 55,
+		14, 13, 16, 24, 40, 57, 69, 56,
+		14, 17, 22, 29, 51, 87, 80, 62,
+		18, 22, 37, 56, 68, 109, 103, 77,
+		24, 35, 55, 64, 81, 104, 113, 92,
+		49, 64, 78, 87, 103, 121, 120, 101,
+		72, 92, 95, 98, 112, 100, 103, 99,
+	},
+	// Chrominance.
+	{
+		17, 18, 24, 47, 99, 99, 99, 99,
+		18, 21, 26, 66, 99, 99, 99, 99,
+		24, 26, 56, 99, 99, 99, 99, 99,
+		47, 66, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+	},
+}
+
+func TestUnscaledQuant(t *testing.T) {
+	bad := false
+	for i := quantIndex(0); i < nQuantIndex; i++ {
+		for zig := 0; zig < blockSize; zig++ {
+			got := unscaledQuant[i][zig]
+			want := unscaledQuantInNaturalOrder[i][unzig[zig]]
+			if got != want {
+				t.Errorf("i=%d, zig=%d: got %d, want %d", i, zig, got, want)
+				bad = true
+			}
+		}
+	}
+	if bad {
+		names := [nQuantIndex]string{"Luminance", "Chrominance"}
+		buf := &bytes.Buffer{}
+		for i, name := range names {
+			fmt.Fprintf(buf, "// %s.\n{\n", name)
+			for zig := 0; zig < blockSize; zig++ {
+				fmt.Fprintf(buf, "%d, ", unscaledQuantInNaturalOrder[i][unzig[zig]])
+				if zig%8 == 7 {
+					buf.WriteString("\n")
+				}
+			}
+			buf.WriteString("},\n")
+		}
+		t.Logf("expected unscaledQuant values:\n%s", buf.String())
+	}
+}
+
+var testCase = []struct {
+	filename  string
+	quality   int
+	tolerance int64
+}{
+	{"../testdata/video-001.png", 1, 24 << 8},
+	{"../testdata/video-001.png", 20, 12 << 8},
+	{"../testdata/video-001.png", 60, 8 << 8},
+	{"../testdata/video-001.png", 80, 6 << 8},
+	{"../testdata/video-001.png", 90, 4 << 8},
+	{"../testdata/video-001.png", 100, 2 << 8},
+}
+
+func delta(u0, u1 uint32) int64 {
+	d := int64(u0) - int64(u1)
+	if d < 0 {
+		return -d
+	}
+	return d
+}
+
+func readPng(filename string) (image.Image, error) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	return png.Decode(f)
+}
+
+func TestWriter(t *testing.T) {
+	for _, tc := range testCase {
+		// Read the image.
+		m0, err := readPng(tc.filename)
+		if err != nil {
+			t.Error(tc.filename, err)
+			continue
+		}
+		// Encode that image as JPEG.
+		var buf bytes.Buffer
+		err = Encode(&buf, m0, &Options{Quality: tc.quality})
+		if err != nil {
+			t.Error(tc.filename, err)
+			continue
+		}
+		// Decode that JPEG.
+		m1, err := Decode(&buf)
+		if err != nil {
+			t.Error(tc.filename, err)
+			continue
+		}
+		if m0.Bounds() != m1.Bounds() {
+			t.Errorf("%s, bounds differ: %v and %v", tc.filename, m0.Bounds(), m1.Bounds())
+			continue
+		}
+		// Compare the average delta to the tolerance level.
+		if averageDelta(m0, m1) > tc.tolerance {
+			t.Errorf("%s, quality=%d: average delta is too high", tc.filename, tc.quality)
+			continue
+		}
+	}
+}
+
+// averageDelta returns the average delta in RGB space. The two images must
+// have the same bounds.
+func averageDelta(m0, m1 image.Image) int64 {
+	b := m0.Bounds()
+	var sum, n int64
+	for y := b.Min.Y; y < b.Max.Y; y++ {
+		for x := b.Min.X; x < b.Max.X; x++ {
+			c0 := m0.At(x, y)
+			c1 := m1.At(x, y)
+			r0, g0, b0, _ := c0.RGBA()
+			r1, g1, b1, _ := c1.RGBA()
+			sum += delta(r0, r1)
+			sum += delta(g0, g1)
+			sum += delta(b0, b1)
+			n += 3
+		}
+	}
+	return sum / n
+}
+
+func BenchmarkEncode(b *testing.B) {
+	b.StopTimer()
+	img := image.NewRGBA(image.Rect(0, 0, 640, 480))
+	bo := img.Bounds()
+	rnd := rand.New(rand.NewSource(123))
+	for y := bo.Min.Y; y < bo.Max.Y; y++ {
+		for x := bo.Min.X; x < bo.Max.X; x++ {
+			img.SetRGBA(x, y, color.RGBA{
+				uint8(rnd.Intn(256)),
+				uint8(rnd.Intn(256)),
+				uint8(rnd.Intn(256)),
+				255,
+			})
+		}
+	}
+	b.SetBytes(640 * 480 * 4)
+	b.StartTimer()
+	options := &Options{Quality: 90}
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img, options)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/names.go b/third_party/gofrontend/libgo/go/image/names.go
new file mode 100644
index 0000000..8985f49
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/names.go
@@ -0,0 +1,52 @@
+// Copyright 2010 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 image
+
+import (
+	"image/color"
+)
+
+var (
+	// Black is an opaque black uniform image.
+	Black = NewUniform(color.Black)
+	// White is an opaque white uniform image.
+	White = NewUniform(color.White)
+	// Transparent is a fully transparent uniform image.
+	Transparent = NewUniform(color.Transparent)
+	// Opaque is a fully opaque uniform image.
+	Opaque = NewUniform(color.Opaque)
+)
+
+// Uniform is an infinite-sized Image of uniform color.
+// It implements the color.Color, color.Model, and Image interfaces.
+type Uniform struct {
+	C color.Color
+}
+
+func (c *Uniform) RGBA() (r, g, b, a uint32) {
+	return c.C.RGBA()
+}
+
+func (c *Uniform) ColorModel() color.Model {
+	return c
+}
+
+func (c *Uniform) Convert(color.Color) color.Color {
+	return c.C
+}
+
+func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }
+
+func (c *Uniform) At(x, y int) color.Color { return c.C }
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (c *Uniform) Opaque() bool {
+	_, _, _, a := c.C.RGBA()
+	return a == 0xffff
+}
+
+func NewUniform(c color.Color) *Uniform {
+	return &Uniform{c}
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/paeth.go b/third_party/gofrontend/libgo/go/image/png/paeth.go
new file mode 100644
index 0000000..37978aa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/paeth.go
@@ -0,0 +1,70 @@
+// 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 png
+
+// paeth implements the Paeth filter function, as per the PNG specification.
+func paeth(a, b, c uint8) uint8 {
+	// This is an optimized version of the sample code in the PNG spec.
+	// For example, the sample code starts with:
+	//	p := int(a) + int(b) - int(c)
+	//	pa := abs(p - int(a))
+	// but the optimized form uses fewer arithmetic operations:
+	//	pa := int(b) - int(c)
+	//	pa = abs(pa)
+	pc := int(c)
+	pa := int(b) - pc
+	pb := int(a) - pc
+	pc = pa + pb
+	if pa < 0 {
+		pa = -pa
+	}
+	if pb < 0 {
+		pb = -pb
+	}
+	if pc < 0 {
+		pc = -pc
+	}
+	if pa <= pb && pa <= pc {
+		return a
+	} else if pb <= pc {
+		return b
+	}
+	return c
+}
+
+// filterPaeth applies the Paeth filter to the cdat slice.
+// cdat is the current row's data, pdat is the previous row's data.
+func filterPaeth(cdat, pdat []byte, bytesPerPixel int) {
+	var a, b, c, pa, pb, pc int
+	for i := 0; i < bytesPerPixel; i++ {
+		a, c = 0, 0
+		for j := i; j < len(cdat); j += bytesPerPixel {
+			b = int(pdat[j])
+			pa = b - c
+			pb = a - c
+			pc = pa + pb
+			if pa < 0 {
+				pa = -pa
+			}
+			if pb < 0 {
+				pb = -pb
+			}
+			if pc < 0 {
+				pc = -pc
+			}
+			if pa <= pb && pa <= pc {
+				// No-op.
+			} else if pb <= pc {
+				a = b
+			} else {
+				a = c
+			}
+			a += int(cdat[j])
+			a &= 0xff
+			cdat[j] = uint8(a)
+			c = b
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/paeth_test.go b/third_party/gofrontend/libgo/go/image/png/paeth_test.go
new file mode 100644
index 0000000..bb08486
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/paeth_test.go
@@ -0,0 +1,91 @@
+// 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 png
+
+import (
+	"bytes"
+	"math/rand"
+	"testing"
+)
+
+func abs(x int) int {
+	if x < 0 {
+		return -x
+	}
+	return x
+}
+
+// slowPaeth is a slow but simple implementation of the Paeth function.
+// It is a straight port of the sample code in the PNG spec, section 9.4.
+func slowPaeth(a, b, c uint8) uint8 {
+	p := int(a) + int(b) - int(c)
+	pa := abs(p - int(a))
+	pb := abs(p - int(b))
+	pc := abs(p - int(c))
+	if pa <= pb && pa <= pc {
+		return a
+	} else if pb <= pc {
+		return b
+	}
+	return c
+}
+
+// slowFilterPaeth is a slow but simple implementation of func filterPaeth.
+func slowFilterPaeth(cdat, pdat []byte, bytesPerPixel int) {
+	for i := 0; i < bytesPerPixel; i++ {
+		cdat[i] += paeth(0, pdat[i], 0)
+	}
+	for i := bytesPerPixel; i < len(cdat); i++ {
+		cdat[i] += paeth(cdat[i-bytesPerPixel], pdat[i], pdat[i-bytesPerPixel])
+	}
+}
+
+func TestPaeth(t *testing.T) {
+	for a := 0; a < 256; a += 15 {
+		for b := 0; b < 256; b += 15 {
+			for c := 0; c < 256; c += 15 {
+				got := paeth(uint8(a), uint8(b), uint8(c))
+				want := slowPaeth(uint8(a), uint8(b), uint8(c))
+				if got != want {
+					t.Errorf("a, b, c = %d, %d, %d: got %d, want %d", a, b, c, got, want)
+				}
+			}
+		}
+	}
+}
+
+func BenchmarkPaeth(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		paeth(uint8(i>>16), uint8(i>>8), uint8(i))
+	}
+}
+
+func TestPaethDecode(t *testing.T) {
+	pdat0 := make([]byte, 32)
+	pdat1 := make([]byte, 32)
+	pdat2 := make([]byte, 32)
+	cdat0 := make([]byte, 32)
+	cdat1 := make([]byte, 32)
+	cdat2 := make([]byte, 32)
+	r := rand.New(rand.NewSource(1))
+	for bytesPerPixel := 1; bytesPerPixel <= 8; bytesPerPixel++ {
+		for i := 0; i < 100; i++ {
+			for j := range pdat0 {
+				pdat0[j] = uint8(r.Uint32())
+				cdat0[j] = uint8(r.Uint32())
+			}
+			copy(pdat1, pdat0)
+			copy(pdat2, pdat0)
+			copy(cdat1, cdat0)
+			copy(cdat2, cdat0)
+			filterPaeth(cdat1, pdat1, bytesPerPixel)
+			slowFilterPaeth(cdat2, pdat2, bytesPerPixel)
+			if !bytes.Equal(cdat1, cdat2) {
+				t.Errorf("bytesPerPixel: %d\npdat0: % x\ncdat0: % x\ngot:   % x\nwant:  % x", bytesPerPixel, pdat0, cdat0, cdat1, cdat2)
+				break
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/reader.go b/third_party/gofrontend/libgo/go/image/png/reader.go
new file mode 100644
index 0000000..dfe2991
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/reader.go
@@ -0,0 +1,699 @@
+// 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 png implements a PNG image decoder and encoder.
+//
+// The PNG specification is at http://www.w3.org/TR/PNG/.
+package png
+
+import (
+	"compress/zlib"
+	"encoding/binary"
+	"fmt"
+	"hash"
+	"hash/crc32"
+	"image"
+	"image/color"
+	"io"
+)
+
+// Color type, as per the PNG spec.
+const (
+	ctGrayscale      = 0
+	ctTrueColor      = 2
+	ctPaletted       = 3
+	ctGrayscaleAlpha = 4
+	ctTrueColorAlpha = 6
+)
+
+// A cb is a combination of color type and bit depth.
+const (
+	cbInvalid = iota
+	cbG1
+	cbG2
+	cbG4
+	cbG8
+	cbGA8
+	cbTC8
+	cbP1
+	cbP2
+	cbP4
+	cbP8
+	cbTCA8
+	cbG16
+	cbGA16
+	cbTC16
+	cbTCA16
+)
+
+// Filter type, as per the PNG spec.
+const (
+	ftNone    = 0
+	ftSub     = 1
+	ftUp      = 2
+	ftAverage = 3
+	ftPaeth   = 4
+	nFilter   = 5
+)
+
+// Decoding stage.
+// The PNG specification says that the IHDR, PLTE (if present), IDAT and IEND
+// chunks must appear in that order. There may be multiple IDAT chunks, and
+// IDAT chunks must be sequential (i.e. they may not have any other chunks
+// between them).
+// http://www.w3.org/TR/PNG/#5ChunkOrdering
+const (
+	dsStart = iota
+	dsSeenIHDR
+	dsSeenPLTE
+	dsSeenIDAT
+	dsSeenIEND
+)
+
+const pngHeader = "\x89PNG\r\n\x1a\n"
+
+type decoder struct {
+	r             io.Reader
+	img           image.Image
+	crc           hash.Hash32
+	width, height int
+	depth         int
+	palette       color.Palette
+	cb            int
+	stage         int
+	idatLength    uint32
+	tmp           [3 * 256]byte
+}
+
+// A FormatError reports that the input is not a valid PNG.
+type FormatError string
+
+func (e FormatError) Error() string { return "png: invalid format: " + string(e) }
+
+var chunkOrderError = FormatError("chunk out of order")
+
+// An UnsupportedError reports that the input uses a valid but unimplemented PNG feature.
+type UnsupportedError string
+
+func (e UnsupportedError) Error() string { return "png: unsupported feature: " + string(e) }
+
+func min(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}
+
+func (d *decoder) parseIHDR(length uint32) error {
+	if length != 13 {
+		return FormatError("bad IHDR length")
+	}
+	if _, err := io.ReadFull(d.r, d.tmp[:13]); err != nil {
+		return err
+	}
+	d.crc.Write(d.tmp[:13])
+	if d.tmp[10] != 0 || d.tmp[11] != 0 || d.tmp[12] != 0 {
+		return UnsupportedError("compression, filter or interlace method")
+	}
+	w := int32(binary.BigEndian.Uint32(d.tmp[0:4]))
+	h := int32(binary.BigEndian.Uint32(d.tmp[4:8]))
+	if w < 0 || h < 0 {
+		return FormatError("negative dimension")
+	}
+	nPixels := int64(w) * int64(h)
+	if nPixels != int64(int(nPixels)) {
+		return UnsupportedError("dimension overflow")
+	}
+	d.cb = cbInvalid
+	d.depth = int(d.tmp[8])
+	switch d.depth {
+	case 1:
+		switch d.tmp[9] {
+		case ctGrayscale:
+			d.cb = cbG1
+		case ctPaletted:
+			d.cb = cbP1
+		}
+	case 2:
+		switch d.tmp[9] {
+		case ctGrayscale:
+			d.cb = cbG2
+		case ctPaletted:
+			d.cb = cbP2
+		}
+	case 4:
+		switch d.tmp[9] {
+		case ctGrayscale:
+			d.cb = cbG4
+		case ctPaletted:
+			d.cb = cbP4
+		}
+	case 8:
+		switch d.tmp[9] {
+		case ctGrayscale:
+			d.cb = cbG8
+		case ctTrueColor:
+			d.cb = cbTC8
+		case ctPaletted:
+			d.cb = cbP8
+		case ctGrayscaleAlpha:
+			d.cb = cbGA8
+		case ctTrueColorAlpha:
+			d.cb = cbTCA8
+		}
+	case 16:
+		switch d.tmp[9] {
+		case ctGrayscale:
+			d.cb = cbG16
+		case ctTrueColor:
+			d.cb = cbTC16
+		case ctGrayscaleAlpha:
+			d.cb = cbGA16
+		case ctTrueColorAlpha:
+			d.cb = cbTCA16
+		}
+	}
+	if d.cb == cbInvalid {
+		return UnsupportedError(fmt.Sprintf("bit depth %d, color type %d", d.tmp[8], d.tmp[9]))
+	}
+	d.width, d.height = int(w), int(h)
+	return d.verifyChecksum()
+}
+
+func (d *decoder) parsePLTE(length uint32) error {
+	np := int(length / 3) // The number of palette entries.
+	if length%3 != 0 || np <= 0 || np > 256 || np > 1<<uint(d.depth) {
+		return FormatError("bad PLTE length")
+	}
+	n, err := io.ReadFull(d.r, d.tmp[:3*np])
+	if err != nil {
+		return err
+	}
+	d.crc.Write(d.tmp[:n])
+	switch d.cb {
+	case cbP1, cbP2, cbP4, cbP8:
+		d.palette = make(color.Palette, 256)
+		for i := 0; i < np; i++ {
+			d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
+		}
+		for i := np; i < 256; i++ {
+			// Initialize the rest of the palette to opaque black. The spec (section
+			// 11.2.3) says that "any out-of-range pixel value found in the image data
+			// is an error", but some real-world PNG files have out-of-range pixel
+			// values. We fall back to opaque black, the same as libpng 1.5.13;
+			// ImageMagick 6.5.7 returns an error.
+			d.palette[i] = color.RGBA{0x00, 0x00, 0x00, 0xff}
+		}
+		d.palette = d.palette[:np]
+	case cbTC8, cbTCA8, cbTC16, cbTCA16:
+		// As per the PNG spec, a PLTE chunk is optional (and for practical purposes,
+		// ignorable) for the ctTrueColor and ctTrueColorAlpha color types (section 4.1.2).
+	default:
+		return FormatError("PLTE, color type mismatch")
+	}
+	return d.verifyChecksum()
+}
+
+func (d *decoder) parsetRNS(length uint32) error {
+	if length > 256 {
+		return FormatError("bad tRNS length")
+	}
+	n, err := io.ReadFull(d.r, d.tmp[:length])
+	if err != nil {
+		return err
+	}
+	d.crc.Write(d.tmp[:n])
+	switch d.cb {
+	case cbG8, cbG16:
+		return UnsupportedError("grayscale transparency")
+	case cbTC8, cbTC16:
+		return UnsupportedError("truecolor transparency")
+	case cbP1, cbP2, cbP4, cbP8:
+		if len(d.palette) < n {
+			d.palette = d.palette[:n]
+		}
+		for i := 0; i < n; i++ {
+			rgba := d.palette[i].(color.RGBA)
+			d.palette[i] = color.NRGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
+		}
+	case cbGA8, cbGA16, cbTCA8, cbTCA16:
+		return FormatError("tRNS, color type mismatch")
+	}
+	return d.verifyChecksum()
+}
+
+// Read presents one or more IDAT chunks as one continuous stream (minus the
+// intermediate chunk headers and footers). If the PNG data looked like:
+//   ... len0 IDAT xxx crc0 len1 IDAT yy crc1 len2 IEND crc2
+// then this reader presents xxxyy. For well-formed PNG data, the decoder state
+// immediately before the first Read call is that d.r is positioned between the
+// first IDAT and xxx, and the decoder state immediately after the last Read
+// call is that d.r is positioned between yy and crc1.
+func (d *decoder) Read(p []byte) (int, error) {
+	if len(p) == 0 {
+		return 0, nil
+	}
+	for d.idatLength == 0 {
+		// We have exhausted an IDAT chunk. Verify the checksum of that chunk.
+		if err := d.verifyChecksum(); err != nil {
+			return 0, err
+		}
+		// Read the length and chunk type of the next chunk, and check that
+		// it is an IDAT chunk.
+		if _, err := io.ReadFull(d.r, d.tmp[:8]); err != nil {
+			return 0, err
+		}
+		d.idatLength = binary.BigEndian.Uint32(d.tmp[:4])
+		if string(d.tmp[4:8]) != "IDAT" {
+			return 0, FormatError("not enough pixel data")
+		}
+		d.crc.Reset()
+		d.crc.Write(d.tmp[4:8])
+	}
+	if int(d.idatLength) < 0 {
+		return 0, UnsupportedError("IDAT chunk length overflow")
+	}
+	n, err := d.r.Read(p[:min(len(p), int(d.idatLength))])
+	d.crc.Write(p[:n])
+	d.idatLength -= uint32(n)
+	return n, err
+}
+
+// decode decodes the IDAT data into an image.
+func (d *decoder) decode() (image.Image, error) {
+	r, err := zlib.NewReader(d)
+	if err != nil {
+		return nil, err
+	}
+	defer r.Close()
+	bitsPerPixel := 0
+	pixOffset := 0
+	var (
+		gray     *image.Gray
+		rgba     *image.RGBA
+		paletted *image.Paletted
+		nrgba    *image.NRGBA
+		gray16   *image.Gray16
+		rgba64   *image.RGBA64
+		nrgba64  *image.NRGBA64
+		img      image.Image
+	)
+	switch d.cb {
+	case cbG1, cbG2, cbG4, cbG8:
+		bitsPerPixel = d.depth
+		gray = image.NewGray(image.Rect(0, 0, d.width, d.height))
+		img = gray
+	case cbGA8:
+		bitsPerPixel = 16
+		nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
+		img = nrgba
+	case cbTC8:
+		bitsPerPixel = 24
+		rgba = image.NewRGBA(image.Rect(0, 0, d.width, d.height))
+		img = rgba
+	case cbP1, cbP2, cbP4, cbP8:
+		bitsPerPixel = d.depth
+		paletted = image.NewPaletted(image.Rect(0, 0, d.width, d.height), d.palette)
+		img = paletted
+	case cbTCA8:
+		bitsPerPixel = 32
+		nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
+		img = nrgba
+	case cbG16:
+		bitsPerPixel = 16
+		gray16 = image.NewGray16(image.Rect(0, 0, d.width, d.height))
+		img = gray16
+	case cbGA16:
+		bitsPerPixel = 32
+		nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height))
+		img = nrgba64
+	case cbTC16:
+		bitsPerPixel = 48
+		rgba64 = image.NewRGBA64(image.Rect(0, 0, d.width, d.height))
+		img = rgba64
+	case cbTCA16:
+		bitsPerPixel = 64
+		nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height))
+		img = nrgba64
+	}
+	bytesPerPixel := (bitsPerPixel + 7) / 8
+
+	// cr and pr are the bytes for the current and previous row.
+	// The +1 is for the per-row filter type, which is at cr[0].
+	cr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8)
+	pr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8)
+
+	for y := 0; y < d.height; y++ {
+		// Read the decompressed bytes.
+		_, err := io.ReadFull(r, cr)
+		if err != nil {
+			return nil, err
+		}
+
+		// Apply the filter.
+		cdat := cr[1:]
+		pdat := pr[1:]
+		switch cr[0] {
+		case ftNone:
+			// No-op.
+		case ftSub:
+			for i := bytesPerPixel; i < len(cdat); i++ {
+				cdat[i] += cdat[i-bytesPerPixel]
+			}
+		case ftUp:
+			for i, p := range pdat {
+				cdat[i] += p
+			}
+		case ftAverage:
+			for i := 0; i < bytesPerPixel; i++ {
+				cdat[i] += pdat[i] / 2
+			}
+			for i := bytesPerPixel; i < len(cdat); i++ {
+				cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2)
+			}
+		case ftPaeth:
+			filterPaeth(cdat, pdat, bytesPerPixel)
+		default:
+			return nil, FormatError("bad filter type")
+		}
+
+		// Convert from bytes to colors.
+		switch d.cb {
+		case cbG1:
+			for x := 0; x < d.width; x += 8 {
+				b := cdat[x/8]
+				for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
+					gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
+					b <<= 1
+				}
+			}
+		case cbG2:
+			for x := 0; x < d.width; x += 4 {
+				b := cdat[x/4]
+				for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
+					gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
+					b <<= 2
+				}
+			}
+		case cbG4:
+			for x := 0; x < d.width; x += 2 {
+				b := cdat[x/2]
+				for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
+					gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
+					b <<= 4
+				}
+			}
+		case cbG8:
+			copy(gray.Pix[pixOffset:], cdat)
+			pixOffset += gray.Stride
+		case cbGA8:
+			for x := 0; x < d.width; x++ {
+				ycol := cdat[2*x+0]
+				nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
+			}
+		case cbTC8:
+			pix, i, j := rgba.Pix, pixOffset, 0
+			for x := 0; x < d.width; x++ {
+				pix[i+0] = cdat[j+0]
+				pix[i+1] = cdat[j+1]
+				pix[i+2] = cdat[j+2]
+				pix[i+3] = 0xff
+				i += 4
+				j += 3
+			}
+			pixOffset += rgba.Stride
+		case cbP1:
+			for x := 0; x < d.width; x += 8 {
+				b := cdat[x/8]
+				for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
+					idx := b >> 7
+					if len(paletted.Palette) <= int(idx) {
+						paletted.Palette = paletted.Palette[:int(idx)+1]
+					}
+					paletted.SetColorIndex(x+x2, y, idx)
+					b <<= 1
+				}
+			}
+		case cbP2:
+			for x := 0; x < d.width; x += 4 {
+				b := cdat[x/4]
+				for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
+					idx := b >> 6
+					if len(paletted.Palette) <= int(idx) {
+						paletted.Palette = paletted.Palette[:int(idx)+1]
+					}
+					paletted.SetColorIndex(x+x2, y, idx)
+					b <<= 2
+				}
+			}
+		case cbP4:
+			for x := 0; x < d.width; x += 2 {
+				b := cdat[x/2]
+				for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
+					idx := b >> 4
+					if len(paletted.Palette) <= int(idx) {
+						paletted.Palette = paletted.Palette[:int(idx)+1]
+					}
+					paletted.SetColorIndex(x+x2, y, idx)
+					b <<= 4
+				}
+			}
+		case cbP8:
+			if len(paletted.Palette) != 255 {
+				for x := 0; x < d.width; x++ {
+					if len(paletted.Palette) <= int(cdat[x]) {
+						paletted.Palette = paletted.Palette[:int(cdat[x])+1]
+					}
+				}
+			}
+			copy(paletted.Pix[pixOffset:], cdat)
+			pixOffset += paletted.Stride
+		case cbTCA8:
+			copy(nrgba.Pix[pixOffset:], cdat)
+			pixOffset += nrgba.Stride
+		case cbG16:
+			for x := 0; x < d.width; x++ {
+				ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
+				gray16.SetGray16(x, y, color.Gray16{ycol})
+			}
+		case cbGA16:
+			for x := 0; x < d.width; x++ {
+				ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1])
+				acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3])
+				nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
+			}
+		case cbTC16:
+			for x := 0; x < d.width; x++ {
+				rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
+				gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
+				bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
+				rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
+			}
+		case cbTCA16:
+			for x := 0; x < d.width; x++ {
+				rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1])
+				gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
+				bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
+				acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
+				nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
+			}
+		}
+
+		// The current row for y is the previous row for y+1.
+		pr, cr = cr, pr
+	}
+
+	// Check for EOF, to verify the zlib checksum.
+	n := 0
+	for i := 0; n == 0 && err == nil; i++ {
+		if i == 100 {
+			return nil, io.ErrNoProgress
+		}
+		n, err = r.Read(pr[:1])
+	}
+	if err != nil && err != io.EOF {
+		return nil, FormatError(err.Error())
+	}
+	if n != 0 || d.idatLength != 0 {
+		return nil, FormatError("too much pixel data")
+	}
+
+	return img, nil
+}
+
+func (d *decoder) parseIDAT(length uint32) (err error) {
+	d.idatLength = length
+	d.img, err = d.decode()
+	if err != nil {
+		return err
+	}
+	return d.verifyChecksum()
+}
+
+func (d *decoder) parseIEND(length uint32) error {
+	if length != 0 {
+		return FormatError("bad IEND length")
+	}
+	return d.verifyChecksum()
+}
+
+func (d *decoder) parseChunk() error {
+	// Read the length and chunk type.
+	n, err := io.ReadFull(d.r, d.tmp[:8])
+	if err != nil {
+		return err
+	}
+	length := binary.BigEndian.Uint32(d.tmp[:4])
+	d.crc.Reset()
+	d.crc.Write(d.tmp[4:8])
+
+	// Read the chunk data.
+	switch string(d.tmp[4:8]) {
+	case "IHDR":
+		if d.stage != dsStart {
+			return chunkOrderError
+		}
+		d.stage = dsSeenIHDR
+		return d.parseIHDR(length)
+	case "PLTE":
+		if d.stage != dsSeenIHDR {
+			return chunkOrderError
+		}
+		d.stage = dsSeenPLTE
+		return d.parsePLTE(length)
+	case "tRNS":
+		if d.stage != dsSeenPLTE {
+			return chunkOrderError
+		}
+		return d.parsetRNS(length)
+	case "IDAT":
+		if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.cb == cbP8 && d.stage == dsSeenIHDR) {
+			return chunkOrderError
+		}
+		d.stage = dsSeenIDAT
+		return d.parseIDAT(length)
+	case "IEND":
+		if d.stage != dsSeenIDAT {
+			return chunkOrderError
+		}
+		d.stage = dsSeenIEND
+		return d.parseIEND(length)
+	}
+	// Ignore this chunk (of a known length).
+	var ignored [4096]byte
+	for length > 0 {
+		n, err = io.ReadFull(d.r, ignored[:min(len(ignored), int(length))])
+		if err != nil {
+			return err
+		}
+		d.crc.Write(ignored[:n])
+		length -= uint32(n)
+	}
+	return d.verifyChecksum()
+}
+
+func (d *decoder) verifyChecksum() error {
+	if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil {
+		return err
+	}
+	if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() {
+		return FormatError("invalid checksum")
+	}
+	return nil
+}
+
+func (d *decoder) checkHeader() error {
+	_, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)])
+	if err != nil {
+		return err
+	}
+	if string(d.tmp[:len(pngHeader)]) != pngHeader {
+		return FormatError("not a PNG file")
+	}
+	return nil
+}
+
+// Decode reads a PNG image from r and returns it as an image.Image.
+// The type of Image returned depends on the PNG contents.
+func Decode(r io.Reader) (image.Image, error) {
+	d := &decoder{
+		r:   r,
+		crc: crc32.NewIEEE(),
+	}
+	if err := d.checkHeader(); err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		return nil, err
+	}
+	for d.stage != dsSeenIEND {
+		if err := d.parseChunk(); err != nil {
+			if err == io.EOF {
+				err = io.ErrUnexpectedEOF
+			}
+			return nil, err
+		}
+	}
+	return d.img, nil
+}
+
+// DecodeConfig returns the color model and dimensions of a PNG image without
+// decoding the entire image.
+func DecodeConfig(r io.Reader) (image.Config, error) {
+	d := &decoder{
+		r:   r,
+		crc: crc32.NewIEEE(),
+	}
+	if err := d.checkHeader(); err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		return image.Config{}, err
+	}
+	for {
+		if err := d.parseChunk(); err != nil {
+			if err == io.EOF {
+				err = io.ErrUnexpectedEOF
+			}
+			return image.Config{}, err
+		}
+		paletted := d.cb == cbP8 || d.cb == cbP4 || d.cb == cbP2 || d.cb == cbP1
+		if d.stage == dsSeenIHDR && !paletted {
+			break
+		}
+		if d.stage == dsSeenPLTE && paletted {
+			break
+		}
+	}
+	var cm color.Model
+	switch d.cb {
+	case cbG1, cbG2, cbG4, cbG8:
+		cm = color.GrayModel
+	case cbGA8:
+		cm = color.NRGBAModel
+	case cbTC8:
+		cm = color.RGBAModel
+	case cbP1, cbP2, cbP4, cbP8:
+		cm = d.palette
+	case cbTCA8:
+		cm = color.NRGBAModel
+	case cbG16:
+		cm = color.Gray16Model
+	case cbGA16:
+		cm = color.NRGBA64Model
+	case cbTC16:
+		cm = color.RGBA64Model
+	case cbTCA16:
+		cm = color.NRGBA64Model
+	}
+	return image.Config{
+		ColorModel: cm,
+		Width:      d.width,
+		Height:     d.height,
+	}, nil
+}
+
+func init() {
+	image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/reader_test.go b/third_party/gofrontend/libgo/go/image/png/reader_test.go
new file mode 100644
index 0000000..ac0d949
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/reader_test.go
@@ -0,0 +1,350 @@
+// 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 png
+
+import (
+	"bufio"
+	"fmt"
+	"image"
+	"image/color"
+	"io"
+	"io/ioutil"
+	"os"
+	"strings"
+	"testing"
+)
+
+var filenames = []string{
+	"basn0g01",
+	"basn0g01-30",
+	"basn0g02",
+	"basn0g02-29",
+	"basn0g04",
+	"basn0g04-31",
+	"basn0g08",
+	"basn0g16",
+	"basn2c08",
+	"basn2c16",
+	"basn3p01",
+	"basn3p02",
+	"basn3p04",
+	"basn3p08",
+	"basn3p08-trns",
+	"basn4a08",
+	"basn4a16",
+	"basn6a08",
+	"basn6a16",
+}
+
+var filenamesPaletted = []string{
+	"basn3p01",
+	"basn3p02",
+	"basn3p04",
+	"basn3p08",
+	"basn3p08-trns",
+}
+
+var filenamesShort = []string{
+	"basn0g01",
+	"basn0g04-31",
+	"basn6a16",
+}
+
+func readPNG(filename string) (image.Image, error) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	return Decode(f)
+}
+
+// An approximation of the sng command-line tool.
+func sng(w io.WriteCloser, filename string, png image.Image) {
+	defer w.Close()
+	bounds := png.Bounds()
+	cm := png.ColorModel()
+	var bitdepth int
+	switch cm {
+	case color.RGBAModel, color.NRGBAModel, color.AlphaModel, color.GrayModel:
+		bitdepth = 8
+	default:
+		bitdepth = 16
+	}
+	cpm, _ := cm.(color.Palette)
+	var paletted *image.Paletted
+	if cpm != nil {
+		switch {
+		case len(cpm) <= 2:
+			bitdepth = 1
+		case len(cpm) <= 4:
+			bitdepth = 2
+		case len(cpm) <= 16:
+			bitdepth = 4
+		default:
+			bitdepth = 8
+		}
+		paletted = png.(*image.Paletted)
+	}
+
+	// Write the filename and IHDR.
+	io.WriteString(w, "#SNG: from "+filename+".png\nIHDR {\n")
+	fmt.Fprintf(w, "    width: %d; height: %d; bitdepth: %d;\n", bounds.Dx(), bounds.Dy(), bitdepth)
+	switch {
+	case cm == color.RGBAModel, cm == color.RGBA64Model:
+		io.WriteString(w, "    using color;\n")
+	case cm == color.NRGBAModel, cm == color.NRGBA64Model:
+		io.WriteString(w, "    using color alpha;\n")
+	case cm == color.GrayModel, cm == color.Gray16Model:
+		io.WriteString(w, "    using grayscale;\n")
+	case cpm != nil:
+		io.WriteString(w, "    using color palette;\n")
+	default:
+		io.WriteString(w, "unknown PNG decoder color model\n")
+	}
+	io.WriteString(w, "}\n")
+
+	// We fake a gAMA output. The test files have a gAMA chunk but the go PNG parser ignores it
+	// (the PNG spec section 11.3 says "Ancillary chunks may be ignored by a decoder").
+	io.WriteString(w, "gAMA {1.0000}\n")
+
+	// Write the PLTE and tRNS (if applicable).
+	if cpm != nil {
+		lastAlpha := -1
+		io.WriteString(w, "PLTE {\n")
+		for i, c := range cpm {
+			var r, g, b, a uint8
+			switch c := c.(type) {
+			case color.RGBA:
+				r, g, b, a = c.R, c.G, c.B, 0xff
+			case color.NRGBA:
+				r, g, b, a = c.R, c.G, c.B, c.A
+			default:
+				panic("unknown palette color type")
+			}
+			if a != 0xff {
+				lastAlpha = i
+			}
+			fmt.Fprintf(w, "    (%3d,%3d,%3d)     # rgb = (0x%02x,0x%02x,0x%02x)\n", r, g, b, r, g, b)
+		}
+		io.WriteString(w, "}\n")
+		if lastAlpha != -1 {
+			io.WriteString(w, "tRNS {\n")
+			for i := 0; i <= lastAlpha; i++ {
+				_, _, _, a := cpm[i].RGBA()
+				a >>= 8
+				fmt.Fprintf(w, " %d", a)
+			}
+			io.WriteString(w, "}\n")
+		}
+	}
+
+	// Write the IMAGE.
+	io.WriteString(w, "IMAGE {\n    pixels hex\n")
+	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
+		switch {
+		case cm == color.GrayModel:
+			for x := bounds.Min.X; x < bounds.Max.X; x++ {
+				gray := png.At(x, y).(color.Gray)
+				fmt.Fprintf(w, "%02x", gray.Y)
+			}
+		case cm == color.Gray16Model:
+			for x := bounds.Min.X; x < bounds.Max.X; x++ {
+				gray16 := png.At(x, y).(color.Gray16)
+				fmt.Fprintf(w, "%04x ", gray16.Y)
+			}
+		case cm == color.RGBAModel:
+			for x := bounds.Min.X; x < bounds.Max.X; x++ {
+				rgba := png.At(x, y).(color.RGBA)
+				fmt.Fprintf(w, "%02x%02x%02x ", rgba.R, rgba.G, rgba.B)
+			}
+		case cm == color.RGBA64Model:
+			for x := bounds.Min.X; x < bounds.Max.X; x++ {
+				rgba64 := png.At(x, y).(color.RGBA64)
+				fmt.Fprintf(w, "%04x%04x%04x ", rgba64.R, rgba64.G, rgba64.B)
+			}
+		case cm == color.NRGBAModel:
+			for x := bounds.Min.X; x < bounds.Max.X; x++ {
+				nrgba := png.At(x, y).(color.NRGBA)
+				fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
+			}
+		case cm == color.NRGBA64Model:
+			for x := bounds.Min.X; x < bounds.Max.X; x++ {
+				nrgba64 := png.At(x, y).(color.NRGBA64)
+				fmt.Fprintf(w, "%04x%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B, nrgba64.A)
+			}
+		case cpm != nil:
+			var b, c int
+			for x := bounds.Min.X; x < bounds.Max.X; x++ {
+				b = b<<uint(bitdepth) | int(paletted.ColorIndexAt(x, y))
+				c++
+				if c == 8/bitdepth {
+					fmt.Fprintf(w, "%02x", b)
+					b = 0
+					c = 0
+				}
+			}
+		}
+		io.WriteString(w, "\n")
+	}
+	io.WriteString(w, "}\n")
+}
+
+func TestReader(t *testing.T) {
+	names := filenames
+	if testing.Short() {
+		names = filenamesShort
+	}
+	for _, fn := range names {
+		// Read the .png file.
+		img, err := readPNG("testdata/pngsuite/" + fn + ".png")
+		if err != nil {
+			t.Error(fn, err)
+			continue
+		}
+
+		if fn == "basn4a16" {
+			// basn4a16.sng is gray + alpha but sng() will produce true color + alpha
+			// so we just check a single random pixel.
+			c := img.At(2, 1).(color.NRGBA64)
+			if c.R != 0x11a7 || c.G != 0x11a7 || c.B != 0x11a7 || c.A != 0x1085 {
+				t.Error(fn, fmt.Errorf("wrong pixel value at (2, 1): %x", c))
+			}
+			continue
+		}
+
+		piper, pipew := io.Pipe()
+		pb := bufio.NewScanner(piper)
+		go sng(pipew, fn, img)
+		defer piper.Close()
+
+		// Read the .sng file.
+		sf, err := os.Open("testdata/pngsuite/" + fn + ".sng")
+		if err != nil {
+			t.Error(fn, err)
+			continue
+		}
+		defer sf.Close()
+		sb := bufio.NewScanner(sf)
+		if err != nil {
+			t.Error(fn, err)
+			continue
+		}
+
+		// Compare the two, in SNG format, line by line.
+		for {
+			pdone := pb.Scan()
+			sdone := sb.Scan()
+			if pdone && sdone {
+				break
+			}
+			if pdone || sdone {
+				t.Errorf("%s: Different sizes", fn)
+				break
+			}
+			ps := pb.Text()
+			ss := sb.Text()
+			if ps != ss {
+				t.Errorf("%s: Mismatch\n%sversus\n%s\n", fn, ps, ss)
+				break
+			}
+		}
+		if pb.Err() != nil {
+			t.Error(fn, pb.Err())
+		}
+		if sb.Err() != nil {
+			t.Error(fn, sb.Err())
+		}
+	}
+}
+
+var readerErrors = []struct {
+	file string
+	err  string
+}{
+	{"invalid-zlib.png", "zlib: invalid checksum"},
+	{"invalid-crc32.png", "invalid checksum"},
+	{"invalid-noend.png", "unexpected EOF"},
+	{"invalid-trunc.png", "unexpected EOF"},
+}
+
+func TestReaderError(t *testing.T) {
+	for _, tt := range readerErrors {
+		img, err := readPNG("testdata/" + tt.file)
+		if err == nil {
+			t.Errorf("decoding %s: missing error", tt.file)
+			continue
+		}
+		if !strings.Contains(err.Error(), tt.err) {
+			t.Errorf("decoding %s: %s, want %s", tt.file, err, tt.err)
+		}
+		if img != nil {
+			t.Errorf("decoding %s: have image + error", tt.file)
+		}
+	}
+}
+
+func TestPalettedDecodeConfig(t *testing.T) {
+	for _, fn := range filenamesPaletted {
+		f, err := os.Open("testdata/pngsuite/" + fn + ".png")
+		if err != nil {
+			t.Errorf("%s: open failed: %v", fn, err)
+			continue
+		}
+		defer f.Close()
+		cfg, err := DecodeConfig(f)
+		if err != nil {
+			t.Errorf("%s: %v", fn, err)
+			continue
+		}
+		pal, ok := cfg.ColorModel.(color.Palette)
+		if !ok {
+			t.Errorf("%s: expected paletted color model", fn)
+			continue
+		}
+		if pal == nil {
+			t.Errorf("%s: palette not initialized", fn)
+			continue
+		}
+	}
+}
+
+func benchmarkDecode(b *testing.B, filename string, bytesPerPixel int) {
+	b.StopTimer()
+	data, err := ioutil.ReadFile(filename)
+	if err != nil {
+		b.Fatal(err)
+	}
+	s := string(data)
+	cfg, err := DecodeConfig(strings.NewReader(s))
+	if err != nil {
+		b.Fatal(err)
+	}
+	b.SetBytes(int64(cfg.Width * cfg.Height * bytesPerPixel))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Decode(strings.NewReader(s))
+	}
+}
+
+func BenchmarkDecodeGray(b *testing.B) {
+	benchmarkDecode(b, "testdata/benchGray.png", 1)
+}
+
+func BenchmarkDecodeNRGBAGradient(b *testing.B) {
+	benchmarkDecode(b, "testdata/benchNRGBA-gradient.png", 4)
+}
+
+func BenchmarkDecodeNRGBAOpaque(b *testing.B) {
+	benchmarkDecode(b, "testdata/benchNRGBA-opaque.png", 4)
+}
+
+func BenchmarkDecodePaletted(b *testing.B) {
+	benchmarkDecode(b, "testdata/benchPaletted.png", 1)
+}
+
+func BenchmarkDecodeRGB(b *testing.B) {
+	benchmarkDecode(b, "testdata/benchRGB.png", 4)
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/benchGray.png b/third_party/gofrontend/libgo/go/image/png/testdata/benchGray.png
new file mode 100644
index 0000000..42bc6c3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/benchGray.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/benchNRGBA-gradient.png b/third_party/gofrontend/libgo/go/image/png/testdata/benchNRGBA-gradient.png
new file mode 100644
index 0000000..961934c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/benchNRGBA-gradient.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/benchNRGBA-opaque.png b/third_party/gofrontend/libgo/go/image/png/testdata/benchNRGBA-opaque.png
new file mode 100644
index 0000000..ca4f4a0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/benchNRGBA-opaque.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/benchPaletted.png b/third_party/gofrontend/libgo/go/image/png/testdata/benchPaletted.png
new file mode 100644
index 0000000..4b4d5b9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/benchPaletted.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/benchRGB.png b/third_party/gofrontend/libgo/go/image/png/testdata/benchRGB.png
new file mode 100644
index 0000000..31ac65a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/benchRGB.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/invalid-crc32.png b/third_party/gofrontend/libgo/go/image/png/testdata/invalid-crc32.png
new file mode 100644
index 0000000..e5be408
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/invalid-crc32.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/invalid-noend.png b/third_party/gofrontend/libgo/go/image/png/testdata/invalid-noend.png
new file mode 100644
index 0000000..9137270
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/invalid-noend.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/invalid-trunc.png b/third_party/gofrontend/libgo/go/image/png/testdata/invalid-trunc.png
new file mode 100644
index 0000000..d0748cf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/invalid-trunc.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/invalid-zlib.png b/third_party/gofrontend/libgo/go/image/png/testdata/invalid-zlib.png
new file mode 100644
index 0000000..c6d051c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/invalid-zlib.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/README b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/README
new file mode 100644
index 0000000..c0f78bd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/README
@@ -0,0 +1,21 @@
+The *.png and README.original files in this directory are copied from
+libpng.org, specifically contrib/pngsuite/* in libpng-1.2.40.tar.gz.
+README.original gives the following license for those files:
+
+	Permission to use, copy, and distribute these images for any purpose
+	and without fee is hereby granted.
+
+
+The files basn0g01-30.png, basn0g02-29.png and basn0g04-31.png are in fact
+not part of pngsuite but were created from files in pngsuite. Their non-power-
+of-two sizes makes them useful for testing bit-depths smaller than a byte.
+
+basn3a08.png was generated from basn6a08.png using the pngnq tool, which
+converted it to the 8-bit paletted image with alpha values in tRNS chunk.
+
+The *.sng files in this directory were generated from the *.png files
+by the sng command-line tool and some hand editing. The files
+basn0g0{1,2,4}.sng were actually generated by first converting the PNG
+to a bitdepth of 8 and then running sng on them. basn4a08.sng was generated
+by from a 16-bit rgba version of basn4a08.png rather than the original
+gray + alpha.
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/README.original b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/README.original
new file mode 100644
index 0000000..714d12c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/README.original
@@ -0,0 +1,85 @@
+
+pngsuite
+--------
+(c) Willem van Schaik, 1999
+
+Permission to use, copy, and distribute these images for any purpose and
+without fee is hereby granted.
+
+These 15 images are part of the much larger PngSuite test-set of 
+images, available for developers of PNG supporting software. The 
+complete set, available at http:/www.schaik.com/pngsuite/, contains 
+a variety of images to test interlacing, gamma settings, ancillary
+chunks, etc.
+
+The images in this directory represent the basic PNG color-types:
+grayscale (1-16 bit deep), full color (8 or 16 bit), paletted
+(1-8 bit) and grayscale or color images with alpha channel. You
+can use them to test the proper functioning of PNG software.
+
+    filename      depth type
+    ------------ ------ --------------
+    basn0g01.png  1-bit grayscale
+    basn0g02.png  2-bit grayscale
+    basn0g04.png  4-bit grayscale
+    basn0g08.png  8-bit grayscale
+    basn0g16.png 16-bit grayscale
+    basn2c08.png  8-bit truecolor
+    basn2c16.png 16-bit truecolor
+    basn3p01.png  1-bit paletted
+    basn3p02.png  2-bit paletted
+    basn3p04.png  4-bit paletted
+    basn3p08.png  8-bit paletted
+    basn4a08.png  8-bit gray with alpha
+    basn4a16.png 16-bit gray with alpha
+    basn6a08.png  8-bit RGBA
+    basn6a16.png 16-bit RGBA
+
+Here is the correct result of typing "pngtest -m *.png" in
+this directory:
+
+Testing basn0g01.png: PASS (524 zero samples)
+ Filter 0 was used 32 times
+Testing basn0g02.png: PASS (448 zero samples)
+ Filter 0 was used 32 times
+Testing basn0g04.png: PASS (520 zero samples)
+ Filter 0 was used 32 times
+Testing basn0g08.png: PASS (3 zero samples)
+ Filter 1 was used 9 times
+ Filter 4 was used 23 times
+Testing basn0g16.png: PASS (1 zero samples)
+ Filter 1 was used 1 times
+ Filter 2 was used 31 times
+Testing basn2c08.png: PASS (6 zero samples)
+ Filter 1 was used 5 times
+ Filter 4 was used 27 times
+Testing basn2c16.png: PASS (592 zero samples)
+ Filter 1 was used 1 times
+ Filter 4 was used 31 times
+Testing basn3p01.png: PASS (512 zero samples)
+ Filter 0 was used 32 times
+Testing basn3p02.png: PASS (448 zero samples)
+ Filter 0 was used 32 times
+Testing basn3p04.png: PASS (544 zero samples)
+ Filter 0 was used 32 times
+Testing basn3p08.png: PASS (4 zero samples)
+ Filter 0 was used 32 times
+Testing basn4a08.png: PASS (32 zero samples)
+ Filter 1 was used 1 times
+ Filter 4 was used 31 times
+Testing basn4a16.png: PASS (64 zero samples)
+ Filter 0 was used 1 times
+ Filter 1 was used 2 times
+ Filter 2 was used 1 times
+ Filter 4 was used 28 times
+Testing basn6a08.png: PASS (160 zero samples)
+ Filter 1 was used 1 times
+ Filter 4 was used 31 times
+Testing basn6a16.png: PASS (1072 zero samples)
+ Filter 1 was used 4 times
+ Filter 4 was used 28 times
+libpng passes test
+
+Willem van Schaik
+<willem@schaik.com>
+October 1999
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01-30.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01-30.png
new file mode 100644
index 0000000..007750c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01-30.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01-30.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01-30.sng
new file mode 100644
index 0000000..7fa3571
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01-30.sng
@@ -0,0 +1,39 @@
+#SNG: from basn0g01-30.png
+IHDR {
+    width: 30; height: 30; bitdepth: 8;
+    using grayscale;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000
+ffffffff0000ffffffffffff0000ffffffffffffffffffffffffff000000
+ffffffff0000ffffffffffff0000ffffffffffffffffffffffff00000000
+ffffffff0000ffffffffffff0000ffffffffffffffffffffff0000000000
+ffffffff0000ffff0000ffff0000ffffffffffffffffffff000000000000
+ffffffff0000ffff0000ffff0000ffffffffffffffffff00000000000000
+ffffffff0000ffff0000ffff0000ffffffffffffffff0000000000000000
+ffffffffff0000000000000000ffffffffffffffff000000000000000000
+ffffffffff0000000000000000ffffffffffffff00000000000000000000
+ffffffffffff0000ffff0000ffffffffffffff0000000000000000000000
+ffffffffffff0000ffff0000ffffffffffff000000000000000000000000
+ffffffffffffffffffffffffffffffffff00000000000000000000000000
+ffffffffffffffffffffffffffffffff0000000000000000000000000000
+ffffffffffffffffffffffffffffff000000000000000000000000000000
+ffffffffffffffffffffffffffff00000000000000000000000000000000
+ffffffffffffffffffffffffff00000000000000ffffffffffffff000000
+ffffffffffffffffffffffff0000000000000000ffffffffffffff000000
+ffffffffffffffffffffff000000000000000000ffff00000000ffff0000
+ffffffffffffffffffff00000000000000000000ffff00000000ffff0000
+ffffffffffffffffff0000000000000000000000ffffffffffffff000000
+ffffffffffffffff000000000000000000000000ffffffffffffff000000
+ffffffffffffff00000000000000000000000000ffff00000000ffff0000
+ffffffffffff0000000000000000000000000000ffff00000000ffff0000
+ffffffffff000000000000000000000000000000ffffffffffffff000000
+ffffffff00000000000000000000000000000000ffffffffffffff000000
+ffffff000000000000000000000000000000000000000000000000000000
+ffff00000000000000000000000000000000000000000000000000000000
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01.png
new file mode 100644
index 0000000..e31e1c7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01.sng
new file mode 100644
index 0000000..2ce069d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g01.sng
@@ -0,0 +1,41 @@
+#SNG: from basn0g01.png
+IHDR {
+    width: 32; height: 32; bitdepth: 8;
+    using grayscale;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000
+ffffffff0000ffffffffffff0000ffffffffffffffffffffffffff0000000000
+ffffffff0000ffffffffffff0000ffffffffffffffffffffffff000000000000
+ffffffff0000ffffffffffff0000ffffffffffffffffffffff00000000000000
+ffffffff0000ffff0000ffff0000ffffffffffffffffffff0000000000000000
+ffffffff0000ffff0000ffff0000ffffffffffffffffff000000000000000000
+ffffffff0000ffff0000ffff0000ffffffffffffffff00000000000000000000
+ffffffffff0000000000000000ffffffffffffffff0000000000000000000000
+ffffffffff0000000000000000ffffffffffffff000000000000000000000000
+ffffffffffff0000ffff0000ffffffffffffff00000000000000000000000000
+ffffffffffff0000ffff0000ffffffffffff0000000000000000000000000000
+ffffffffffffffffffffffffffffffffff000000000000000000000000000000
+ffffffffffffffffffffffffffffffff00000000000000000000000000000000
+ffffffffffffffffffffffffffffff0000000000000000000000000000000000
+ffffffffffffffffffffffffffff000000000000000000000000000000000000
+ffffffffffffffffffffffffff00000000000000ffffffffffffff0000000000
+ffffffffffffffffffffffff0000000000000000ffffffffffffff0000000000
+ffffffffffffffffffffff000000000000000000ffff00000000ffff00000000
+ffffffffffffffffffff00000000000000000000ffff00000000ffff00000000
+ffffffffffffffffff0000000000000000000000ffffffffffffff0000000000
+ffffffffffffffff000000000000000000000000ffffffffffffff0000000000
+ffffffffffffff00000000000000000000000000ffff00000000ffff00000000
+ffffffffffff0000000000000000000000000000ffff00000000ffff00000000
+ffffffffff000000000000000000000000000000ffffffffffffff0000000000
+ffffffff00000000000000000000000000000000ffffffffffffff0000000000
+ffffff0000000000000000000000000000000000000000000000000000000000
+ffff000000000000000000000000000000000000000000000000000000000000
+ff00000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02-29.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02-29.png
new file mode 100644
index 0000000..d17d8f8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02-29.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02-29.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02-29.sng
new file mode 100644
index 0000000..afb5dba
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02-29.sng
@@ -0,0 +1,38 @@
+#SNG: from basn0g02-29.png
+IHDR {
+    width: 29; height: 29; bitdepth: 8;
+    using grayscale;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaff
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aa
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aa
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aa
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aa
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaff
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aa
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02.png
new file mode 100644
index 0000000..68809dd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02.sng
new file mode 100644
index 0000000..bb53d75
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g02.sng
@@ -0,0 +1,41 @@
+#SNG: from basn0g02.png
+IHDR {
+    width: 32; height: 32; bitdepth: 8;
+    using grayscale;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00000000
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00000000
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00000000
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00000000
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055555555
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055555555
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055555555
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055555555
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaa
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaa
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaa
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaa
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff
+0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00000000
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00000000
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00000000
+55555555aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff00000000
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055555555
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055555555
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055555555
+aaaaaaaaffffffff0000000055555555aaaaaaaaffffffff0000000055555555
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaa
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaa
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaa
+ffffffff0000000055555555aaaaaaaaffffffff0000000055555555aaaaaaaa
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04-31.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04-31.png
new file mode 100644
index 0000000..e30644d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04-31.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04-31.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04-31.sng
new file mode 100644
index 0000000..7f7948e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04-31.sng
@@ -0,0 +1,40 @@
+#SNG: from basn0g04-31.png
+IHDR {
+    width: 31; height: 31; bitdepth: 8;
+    using grayscale;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+00000000111111112222222233333333444444445555555566666666777777
+00000000111111112222222233333333444444445555555566666666777777
+00000000111111112222222233333333444444445555555566666666777777
+00000000111111112222222233333333444444445555555566666666777777
+11111111222222223333333344444444555555556666666677777777888888
+11111111222222223333333344444444555555556666666677777777888888
+11111111222222223333333344444444555555556666666677777777888888
+11111111222222223333333344444444555555556666666677777777888888
+22222222333333334444444455555555666666667777777788888888999999
+22222222333333334444444455555555666666667777777788888888999999
+22222222333333334444444455555555666666667777777788888888999999
+22222222333333334444444455555555666666667777777788888888999999
+33333333444444445555555566666666777777778888888899999999aaaaaa
+33333333444444445555555566666666777777778888888899999999aaaaaa
+33333333444444445555555566666666777777778888888899999999aaaaaa
+33333333444444445555555566666666777777778888888899999999aaaaaa
+444444445555555566666666777777778888888899999999aaaaaaaabbbbbb
+444444445555555566666666777777778888888899999999aaaaaaaabbbbbb
+444444445555555566666666777777778888888899999999aaaaaaaabbbbbb
+444444445555555566666666777777778888888899999999aaaaaaaabbbbbb
+5555555566666666777777778888888899999999aaaaaaaabbbbbbbbcccccc
+5555555566666666777777778888888899999999aaaaaaaabbbbbbbbcccccc
+5555555566666666777777778888888899999999aaaaaaaabbbbbbbbcccccc
+5555555566666666777777778888888899999999aaaaaaaabbbbbbbbcccccc
+66666666777777778888888899999999aaaaaaaabbbbbbbbccccccccdddddd
+66666666777777778888888899999999aaaaaaaabbbbbbbbccccccccdddddd
+66666666777777778888888899999999aaaaaaaabbbbbbbbccccccccdddddd
+66666666777777778888888899999999aaaaaaaabbbbbbbbccccccccdddddd
+777777778888888899999999aaaaaaaabbbbbbbbccccccccddddddddeeeeee
+777777778888888899999999aaaaaaaabbbbbbbbccccccccddddddddeeeeee
+777777778888888899999999aaaaaaaabbbbbbbbccccccccddddddddeeeeee
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04.png
new file mode 100644
index 0000000..6fa089c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04.sng
new file mode 100644
index 0000000..a95ad01
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g04.sng
@@ -0,0 +1,41 @@
+#SNG: from basn0g04.png
+IHDR {
+    width: 32; height: 32; bitdepth: 8;
+    using grayscale;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+0000000011111111222222223333333344444444555555556666666677777777
+0000000011111111222222223333333344444444555555556666666677777777
+0000000011111111222222223333333344444444555555556666666677777777
+0000000011111111222222223333333344444444555555556666666677777777
+1111111122222222333333334444444455555555666666667777777788888888
+1111111122222222333333334444444455555555666666667777777788888888
+1111111122222222333333334444444455555555666666667777777788888888
+1111111122222222333333334444444455555555666666667777777788888888
+2222222233333333444444445555555566666666777777778888888899999999
+2222222233333333444444445555555566666666777777778888888899999999
+2222222233333333444444445555555566666666777777778888888899999999
+2222222233333333444444445555555566666666777777778888888899999999
+33333333444444445555555566666666777777778888888899999999aaaaaaaa
+33333333444444445555555566666666777777778888888899999999aaaaaaaa
+33333333444444445555555566666666777777778888888899999999aaaaaaaa
+33333333444444445555555566666666777777778888888899999999aaaaaaaa
+444444445555555566666666777777778888888899999999aaaaaaaabbbbbbbb
+444444445555555566666666777777778888888899999999aaaaaaaabbbbbbbb
+444444445555555566666666777777778888888899999999aaaaaaaabbbbbbbb
+444444445555555566666666777777778888888899999999aaaaaaaabbbbbbbb
+5555555566666666777777778888888899999999aaaaaaaabbbbbbbbcccccccc
+5555555566666666777777778888888899999999aaaaaaaabbbbbbbbcccccccc
+5555555566666666777777778888888899999999aaaaaaaabbbbbbbbcccccccc
+5555555566666666777777778888888899999999aaaaaaaabbbbbbbbcccccccc
+66666666777777778888888899999999aaaaaaaabbbbbbbbccccccccdddddddd
+66666666777777778888888899999999aaaaaaaabbbbbbbbccccccccdddddddd
+66666666777777778888888899999999aaaaaaaabbbbbbbbccccccccdddddddd
+66666666777777778888888899999999aaaaaaaabbbbbbbbccccccccdddddddd
+777777778888888899999999aaaaaaaabbbbbbbbccccccccddddddddeeeeeeee
+777777778888888899999999aaaaaaaabbbbbbbbccccccccddddddddeeeeeeee
+777777778888888899999999aaaaaaaabbbbbbbbccccccccddddddddeeeeeeee
+777777778888888899999999aaaaaaaabbbbbbbbccccccccddddddddeeeeeeee
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g08.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g08.png
new file mode 100644
index 0000000..bf522ee
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g08.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g08.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g08.sng
new file mode 100644
index 0000000..7389eb7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g08.sng
@@ -0,0 +1,41 @@
+#SNG: from basn0g08.png
+IHDR {
+    width: 32; height: 32; bitdepth: 8;
+    using grayscale;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
+404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f
+808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f
+a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf
+c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf
+e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+fefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0df
+dedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bf
+bebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f
+9e9d9c9b9a999897969594939291908f8e8d8c8b8a898887868584838281807f
+7e7d7c7b7a797877767574737271706f6e6d6c6b6a696867666564636261605f
+5e5d5c5b5a595857565554535251504f4e4d4c4b4a494847464544434241403f
+3e3d3c3b3a393837363534333231302f2e2d2c2b2a292827262524232221201f
+1e1d1c1b1a191817161514131211100f0e0d0c0b0a0908070605040302010001
+02030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021
+22232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041
+42434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6061
+62636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081
+82838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1
+a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1
+c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1
+e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfefffefd
+fcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedd
+dcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bfbebd
+bcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f9e9d
+9c9b9a999897969594939291908f8e8d8c8b8a898887868584838281807f7e7d
+7c7b7a797877767574737271706f6e6d6c6b6a696867666564636261605f5e5d
+5c5b5a595857565554535251504f4e4d4c4b4a494847464544434241403f3e3d
+3c3b3a393837363534333231302f2e2d2c2b2a292827262524232221201f1e1d
+1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100010203
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g16.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g16.png
new file mode 100644
index 0000000..318ebca
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g16.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g16.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g16.sng
new file mode 100644
index 0000000..922391a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn0g16.sng
@@ -0,0 +1,41 @@
+#SNG: from basn0g16.png
+IHDR {
+    width: 32; height: 32; bitdepth: 16;
+    using grayscale;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+0000 0900 1200 1b00 2400 2d00 3600 3f00 4800 5100 5a00 6300 6c00 7500 7e00 8700 9000 9900 a200 ab00 b400 bd00 c600 cf00 d800 e100 ea00 f300 fc00 f0ff d5ff baff 
+0200 0b00 1400 1d00 2600 2f00 3800 4100 4a00 5300 5c00 6500 6e00 7700 8000 8900 9200 9b00 a400 ad00 b600 bf00 c800 d100 da00 e300 ec00 f500 fe00 eaff cfff b4ff 
+0400 0d00 1600 1f00 2800 3100 3a00 4300 4c00 5500 5e00 6700 7000 7900 8200 8b00 9400 9d00 a600 af00 b800 c100 ca00 d300 dc00 e500 ee00 f700 ffff e4ff c9ff aeff 
+0600 0f00 1800 2100 2a00 3300 3c00 4500 4e00 5700 6000 6900 7200 7b00 8400 8d00 9600 9f00 a800 b100 ba00 c300 cc00 d500 de00 e700 f000 f900 f9ff deff c3ff a8ff 
+0800 1100 1a00 2300 2c00 3500 3e00 4700 5000 5900 6200 6b00 7400 7d00 8600 8f00 9800 a100 aa00 b300 bc00 c500 ce00 d700 e000 e900 f200 fb00 f3ff d8ff bdff a2ff 
+0a00 1300 1c00 2500 2e00 3700 4000 4900 5200 5b00 6400 6d00 7600 7f00 8800 9100 9a00 a300 ac00 b500 be00 c700 d000 d900 e200 eb00 f400 fd00 edff d2ff b7ff 9cff 
+0c00 1500 1e00 2700 3000 3900 4200 4b00 5400 5d00 6600 6f00 7800 8100 8a00 9300 9c00 a500 ae00 b700 c000 c900 d200 db00 e400 ed00 f600 ff00 e7ff ccff b1ff 96ff 
+0e00 1700 2000 2900 3200 3b00 4400 4d00 5600 5f00 6800 7100 7a00 8300 8c00 9500 9e00 a700 b000 b900 c200 cb00 d400 dd00 e600 ef00 f800 fcff e1ff c6ff abff 90ff 
+1000 1900 2200 2b00 3400 3d00 4600 4f00 5800 6100 6a00 7300 7c00 8500 8e00 9700 a000 a900 b200 bb00 c400 cd00 d600 df00 e800 f100 fa00 f6ff dbff c0ff a5ff 8aff 
+1200 1b00 2400 2d00 3600 3f00 4800 5100 5a00 6300 6c00 7500 7e00 8700 9000 9900 a200 ab00 b400 bd00 c600 cf00 d800 e100 ea00 f300 fc00 f0ff d5ff baff 9fff 84ff 
+1400 1d00 2600 2f00 3800 4100 4a00 5300 5c00 6500 6e00 7700 8000 8900 9200 9b00 a400 ad00 b600 bf00 c800 d100 da00 e300 ec00 f500 fe00 eaff cfff b4ff 99ff 7eff 
+1600 1f00 2800 3100 3a00 4300 4c00 5500 5e00 6700 7000 7900 8200 8b00 9400 9d00 a600 af00 b800 c100 ca00 d300 dc00 e500 ee00 f700 ffff e4ff c9ff aeff 93ff 78ff 
+1800 2100 2a00 3300 3c00 4500 4e00 5700 6000 6900 7200 7b00 8400 8d00 9600 9f00 a800 b100 ba00 c300 cc00 d500 de00 e700 f000 f900 f9ff deff c3ff a8ff 8dff 72ff 
+1a00 2300 2c00 3500 3e00 4700 5000 5900 6200 6b00 7400 7d00 8600 8f00 9800 a100 aa00 b300 bc00 c500 ce00 d700 e000 e900 f200 fb00 f3ff d8ff bdff a2ff 87ff 6cff 
+1c00 2500 2e00 3700 4000 4900 5200 5b00 6400 6d00 7600 7f00 8800 9100 9a00 a300 ac00 b500 be00 c700 d000 d900 e200 eb00 f400 fd00 edff d2ff b7ff 9cff 81ff 66ff 
+1e00 2700 3000 3900 4200 4b00 5400 5d00 6600 6f00 7800 8100 8a00 9300 9c00 a500 ae00 b700 c000 c900 d200 db00 e400 ed00 f600 ff00 e7ff ccff b1ff 96ff 7bff 60ff 
+2000 2900 3200 3b00 4400 4d00 5600 5f00 6800 7100 7a00 8300 8c00 9500 9e00 a700 b000 b900 c200 cb00 d400 dd00 e600 ef00 f800 fcff e1ff c6ff abff 90ff 75ff 5aff 
+2200 2b00 3400 3d00 4600 4f00 5800 6100 6a00 7300 7c00 8500 8e00 9700 a000 a900 b200 bb00 c400 cd00 d600 df00 e800 f100 fa00 f6ff dbff c0ff a5ff 8aff 6fff 54ff 
+2400 2d00 3600 3f00 4800 5100 5a00 6300 6c00 7500 7e00 8700 9000 9900 a200 ab00 b400 bd00 c600 cf00 d800 e100 ea00 f300 fc00 f0ff d5ff baff 9fff 84ff 69ff 4eff 
+2600 2f00 3800 4100 4a00 5300 5c00 6500 6e00 7700 8000 8900 9200 9b00 a400 ad00 b600 bf00 c800 d100 da00 e300 ec00 f500 fe00 eaff cfff b4ff 99ff 7eff 63ff 48ff 
+2800 3100 3a00 4300 4c00 5500 5e00 6700 7000 7900 8200 8b00 9400 9d00 a600 af00 b800 c100 ca00 d300 dc00 e500 ee00 f700 ffff e4ff c9ff aeff 93ff 78ff 5dff 42ff 
+2a00 3300 3c00 4500 4e00 5700 6000 6900 7200 7b00 8400 8d00 9600 9f00 a800 b100 ba00 c300 cc00 d500 de00 e700 f000 f900 f9ff deff c3ff a8ff 8dff 72ff 57ff 3cff 
+2c00 3500 3e00 4700 5000 5900 6200 6b00 7400 7d00 8600 8f00 9800 a100 aa00 b300 bc00 c500 ce00 d700 e000 e900 f200 fb00 f3ff d8ff bdff a2ff 87ff 6cff 51ff 36ff 
+2e00 3700 4000 4900 5200 5b00 6400 6d00 7600 7f00 8800 9100 9a00 a300 ac00 b500 be00 c700 d000 d900 e200 eb00 f400 fd00 edff d2ff b7ff 9cff 81ff 66ff 4bff 30ff 
+3000 3900 4200 4b00 5400 5d00 6600 6f00 7800 8100 8a00 9300 9c00 a500 ae00 b700 c000 c900 d200 db00 e400 ed00 f600 ff00 e7ff ccff b1ff 96ff 7bff 60ff 45ff 2aff 
+3200 3b00 4400 4d00 5600 5f00 6800 7100 7a00 8300 8c00 9500 9e00 a700 b000 b900 c200 cb00 d400 dd00 e600 ef00 f800 fcff e1ff c6ff abff 90ff 75ff 5aff 3fff 24ff 
+3400 3d00 4600 4f00 5800 6100 6a00 7300 7c00 8500 8e00 9700 a000 a900 b200 bb00 c400 cd00 d600 df00 e800 f100 fa00 f6ff dbff c0ff a5ff 8aff 6fff 54ff 39ff 1eff 
+3600 3f00 4800 5100 5a00 6300 6c00 7500 7e00 8700 9000 9900 a200 ab00 b400 bd00 c600 cf00 d800 e100 ea00 f300 fc00 f0ff d5ff baff 9fff 84ff 69ff 4eff 33ff 18ff 
+3800 4100 4a00 5300 5c00 6500 6e00 7700 8000 8900 9200 9b00 a400 ad00 b600 bf00 c800 d100 da00 e300 ec00 f500 fe00 eaff cfff b4ff 99ff 7eff 63ff 48ff 2dff 12ff 
+3a00 4300 4c00 5500 5e00 6700 7000 7900 8200 8b00 9400 9d00 a600 af00 b800 c100 ca00 d300 dc00 e500 ee00 f700 ffff e4ff c9ff aeff 93ff 78ff 5dff 42ff 27ff 0cff 
+3c00 4500 4e00 5700 6000 6900 7200 7b00 8400 8d00 9600 9f00 a800 b100 ba00 c300 cc00 d500 de00 e700 f000 f900 f9ff deff c3ff a8ff 8dff 72ff 57ff 3cff 21ff 06ff 
+3e00 4700 5000 5900 6200 6b00 7400 7d00 8600 8f00 9800 a100 aa00 b300 bc00 c500 ce00 d700 e000 e900 f200 fb00 f3ff d8ff bdff a2ff 87ff 6cff 51ff 36ff 1bff 00ff 
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c08.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c08.png
new file mode 100644
index 0000000..21d2f91
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c08.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c08.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c08.sng
new file mode 100644
index 0000000..09a6131
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c08.sng
@@ -0,0 +1,41 @@
+#SNG: from basn2c08.png
+IHDR {
+    width: 32; height: 32; bitdepth: 8;
+    using color;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+ffffff fffffe fffffd fffffc fffffb fffffa fffff9 fffff8 fffff7 fffff6 fffff5 fffff4 fffff3 fffff2 fffff1 fffff0 ffffef ffffee ffffed ffffec ffffeb ffffea ffffe9 ffffe8 ffffe7 ffffe6 ffffe5 ffffe4 ffffe3 ffffe2 ffffe1 ffffe0 
+ffffdf ffffde ffffdd ffffdc ffffdb ffffda ffffd9 ffffd8 ffffd7 ffffd6 ffffd5 ffffd4 ffffd3 ffffd2 ffffd1 ffffd0 ffffcf ffffce ffffcd ffffcc ffffcb ffffca ffffc9 ffffc8 ffffc7 ffffc6 ffffc5 ffffc4 ffffc3 ffffc2 ffffc1 ffffc0 
+ffffbf ffffbe ffffbd ffffbc ffffbb ffffba ffffb9 ffffb8 ffffb7 ffffb6 ffffb5 ffffb4 ffffb3 ffffb2 ffffb1 ffffb0 ffffaf ffffae ffffad ffffac ffffab ffffaa ffffa9 ffffa8 ffffa7 ffffa6 ffffa5 ffffa4 ffffa3 ffffa2 ffffa1 ffffa0 
+ffff9f ffff9e ffff9d ffff9c ffff9b ffff9a ffff99 ffff98 ffff97 ffff96 ffff95 ffff94 ffff93 ffff92 ffff91 ffff90 ffff8f ffff8e ffff8d ffff8c ffff8b ffff8a ffff89 ffff88 ffff87 ffff86 ffff85 ffff84 ffff83 ffff82 ffff81 ffff80 
+ffff7f ffff7e ffff7d ffff7c ffff7b ffff7a ffff79 ffff78 ffff77 ffff76 ffff75 ffff74 ffff73 ffff72 ffff71 ffff70 ffff6f ffff6e ffff6d ffff6c ffff6b ffff6a ffff69 ffff68 ffff67 ffff66 ffff65 ffff64 ffff63 ffff62 ffff61 ffff60 
+ffff5f ffff5e ffff5d ffff5c ffff5b ffff5a ffff59 ffff58 ffff57 ffff56 ffff55 ffff54 ffff53 ffff52 ffff51 ffff50 ffff4f ffff4e ffff4d ffff4c ffff4b ffff4a ffff49 ffff48 ffff47 ffff46 ffff45 ffff44 ffff43 ffff42 ffff41 ffff40 
+ffff3f ffff3e ffff3d ffff3c ffff3b ffff3a ffff39 ffff38 ffff37 ffff36 ffff35 ffff34 ffff33 ffff32 ffff31 ffff30 ffff2f ffff2e ffff2d ffff2c ffff2b ffff2a ffff29 ffff28 ffff27 ffff26 ffff25 ffff24 ffff23 ffff22 ffff21 ffff20 
+ffff1f ffff1e ffff1d ffff1c ffff1b ffff1a ffff19 ffff18 ffff17 ffff16 ffff15 ffff14 ffff13 ffff12 ffff11 ffff10 ffff0f ffff0e ffff0d ffff0c ffff0b ffff0a ffff09 ffff08 ffff07 ffff06 ffff05 ffff04 ffff03 ffff02 ffff01 ffff00 
+ffffff fffeff fffdff fffcff fffbff fffaff fff9ff fff8ff fff7ff fff6ff fff5ff fff4ff fff3ff fff2ff fff1ff fff0ff ffefff ffeeff ffedff ffecff ffebff ffeaff ffe9ff ffe8ff ffe7ff ffe6ff ffe5ff ffe4ff ffe3ff ffe2ff ffe1ff ffe0ff 
+ffdfff ffdeff ffddff ffdcff ffdbff ffdaff ffd9ff ffd8ff ffd7ff ffd6ff ffd5ff ffd4ff ffd3ff ffd2ff ffd1ff ffd0ff ffcfff ffceff ffcdff ffccff ffcbff ffcaff ffc9ff ffc8ff ffc7ff ffc6ff ffc5ff ffc4ff ffc3ff ffc2ff ffc1ff ffc0ff 
+ffbfff ffbeff ffbdff ffbcff ffbbff ffbaff ffb9ff ffb8ff ffb7ff ffb6ff ffb5ff ffb4ff ffb3ff ffb2ff ffb1ff ffb0ff ffafff ffaeff ffadff ffacff ffabff ffaaff ffa9ff ffa8ff ffa7ff ffa6ff ffa5ff ffa4ff ffa3ff ffa2ff ffa1ff ffa0ff 
+ff9fff ff9eff ff9dff ff9cff ff9bff ff9aff ff99ff ff98ff ff97ff ff96ff ff95ff ff94ff ff93ff ff92ff ff91ff ff90ff ff8fff ff8eff ff8dff ff8cff ff8bff ff8aff ff89ff ff88ff ff87ff ff86ff ff85ff ff84ff ff83ff ff82ff ff81ff ff80ff 
+ff7fff ff7eff ff7dff ff7cff ff7bff ff7aff ff79ff ff78ff ff77ff ff76ff ff75ff ff74ff ff73ff ff72ff ff71ff ff70ff ff6fff ff6eff ff6dff ff6cff ff6bff ff6aff ff69ff ff68ff ff67ff ff66ff ff65ff ff64ff ff63ff ff62ff ff61ff ff60ff 
+ff5fff ff5eff ff5dff ff5cff ff5bff ff5aff ff59ff ff58ff ff57ff ff56ff ff55ff ff54ff ff53ff ff52ff ff51ff ff50ff ff4fff ff4eff ff4dff ff4cff ff4bff ff4aff ff49ff ff48ff ff47ff ff46ff ff45ff ff44ff ff43ff ff42ff ff41ff ff40ff 
+ff3fff ff3eff ff3dff ff3cff ff3bff ff3aff ff39ff ff38ff ff37ff ff36ff ff35ff ff34ff ff33ff ff32ff ff31ff ff30ff ff2fff ff2eff ff2dff ff2cff ff2bff ff2aff ff29ff ff28ff ff27ff ff26ff ff25ff ff24ff ff23ff ff22ff ff21ff ff20ff 
+ff1fff ff1eff ff1dff ff1cff ff1bff ff1aff ff19ff ff18ff ff17ff ff16ff ff15ff ff14ff ff13ff ff12ff ff11ff ff10ff ff0fff ff0eff ff0dff ff0cff ff0bff ff0aff ff09ff ff08ff ff07ff ff06ff ff05ff ff04ff ff03ff ff02ff ff01ff ff00ff 
+ffffff feffff fdffff fcffff fbffff faffff f9ffff f8ffff f7ffff f6ffff f5ffff f4ffff f3ffff f2ffff f1ffff f0ffff efffff eeffff edffff ecffff ebffff eaffff e9ffff e8ffff e7ffff e6ffff e5ffff e4ffff e3ffff e2ffff e1ffff e0ffff 
+dfffff deffff ddffff dcffff dbffff daffff d9ffff d8ffff d7ffff d6ffff d5ffff d4ffff d3ffff d2ffff d1ffff d0ffff cfffff ceffff cdffff ccffff cbffff caffff c9ffff c8ffff c7ffff c6ffff c5ffff c4ffff c3ffff c2ffff c1ffff c0ffff 
+bfffff beffff bdffff bcffff bbffff baffff b9ffff b8ffff b7ffff b6ffff b5ffff b4ffff b3ffff b2ffff b1ffff b0ffff afffff aeffff adffff acffff abffff aaffff a9ffff a8ffff a7ffff a6ffff a5ffff a4ffff a3ffff a2ffff a1ffff a0ffff 
+9fffff 9effff 9dffff 9cffff 9bffff 9affff 99ffff 98ffff 97ffff 96ffff 95ffff 94ffff 93ffff 92ffff 91ffff 90ffff 8fffff 8effff 8dffff 8cffff 8bffff 8affff 89ffff 88ffff 87ffff 86ffff 85ffff 84ffff 83ffff 82ffff 81ffff 80ffff 
+7fffff 7effff 7dffff 7cffff 7bffff 7affff 79ffff 78ffff 77ffff 76ffff 75ffff 74ffff 73ffff 72ffff 71ffff 70ffff 6fffff 6effff 6dffff 6cffff 6bffff 6affff 69ffff 68ffff 67ffff 66ffff 65ffff 64ffff 63ffff 62ffff 61ffff 60ffff 
+5fffff 5effff 5dffff 5cffff 5bffff 5affff 59ffff 58ffff 57ffff 56ffff 55ffff 54ffff 53ffff 52ffff 51ffff 50ffff 4fffff 4effff 4dffff 4cffff 4bffff 4affff 49ffff 48ffff 47ffff 46ffff 45ffff 44ffff 43ffff 42ffff 41ffff 40ffff 
+3fffff 3effff 3dffff 3cffff 3bffff 3affff 39ffff 38ffff 37ffff 36ffff 35ffff 34ffff 33ffff 32ffff 31ffff 30ffff 2fffff 2effff 2dffff 2cffff 2bffff 2affff 29ffff 28ffff 27ffff 26ffff 25ffff 24ffff 23ffff 22ffff 21ffff 20ffff 
+1fffff 1effff 1dffff 1cffff 1bffff 1affff 19ffff 18ffff 17ffff 16ffff 15ffff 14ffff 13ffff 12ffff 11ffff 10ffff 0fffff 0effff 0dffff 0cffff 0bffff 0affff 09ffff 08ffff 07ffff 06ffff 05ffff 04ffff 03ffff 02ffff 01ffff 00ffff 
+ffffff fefefe fdfdfd fcfcfc fbfbfb fafafa f9f9f9 f8f8f8 f7f7f7 f6f6f6 f5f5f5 f4f4f4 f3f3f3 f2f2f2 f1f1f1 f0f0f0 efefef eeeeee ededed ececec ebebeb eaeaea e9e9e9 e8e8e8 e7e7e7 e6e6e6 e5e5e5 e4e4e4 e3e3e3 e2e2e2 e1e1e1 e0e0e0 
+dfdfdf dedede dddddd dcdcdc dbdbdb dadada d9d9d9 d8d8d8 d7d7d7 d6d6d6 d5d5d5 d4d4d4 d3d3d3 d2d2d2 d1d1d1 d0d0d0 cfcfcf cecece cdcdcd cccccc cbcbcb cacaca c9c9c9 c8c8c8 c7c7c7 c6c6c6 c5c5c5 c4c4c4 c3c3c3 c2c2c2 c1c1c1 c0c0c0 
+bfbfbf bebebe bdbdbd bcbcbc bbbbbb bababa b9b9b9 b8b8b8 b7b7b7 b6b6b6 b5b5b5 b4b4b4 b3b3b3 b2b2b2 b1b1b1 b0b0b0 afafaf aeaeae adadad acacac ababab aaaaaa a9a9a9 a8a8a8 a7a7a7 a6a6a6 a5a5a5 a4a4a4 a3a3a3 a2a2a2 a1a1a1 a0a0a0 
+9f9f9f 9e9e9e 9d9d9d 9c9c9c 9b9b9b 9a9a9a 999999 989898 979797 969696 959595 949494 939393 929292 919191 909090 8f8f8f 8e8e8e 8d8d8d 8c8c8c 8b8b8b 8a8a8a 898989 888888 878787 868686 858585 848484 838383 828282 818181 808080 
+7f7f7f 7e7e7e 7d7d7d 7c7c7c 7b7b7b 7a7a7a 797979 787878 777777 767676 757575 747474 737373 727272 717171 707070 6f6f6f 6e6e6e 6d6d6d 6c6c6c 6b6b6b 6a6a6a 696969 686868 676767 666666 656565 646464 636363 626262 616161 606060 
+5f5f5f 5e5e5e 5d5d5d 5c5c5c 5b5b5b 5a5a5a 595959 585858 575757 565656 555555 545454 535353 525252 515151 505050 4f4f4f 4e4e4e 4d4d4d 4c4c4c 4b4b4b 4a4a4a 494949 484848 474747 464646 454545 444444 434343 424242 414141 404040 
+3f3f3f 3e3e3e 3d3d3d 3c3c3c 3b3b3b 3a3a3a 393939 383838 373737 363636 353535 343434 333333 323232 313131 303030 2f2f2f 2e2e2e 2d2d2d 2c2c2c 2b2b2b 2a2a2a 292929 282828 272727 262626 252525 242424 232323 222222 212121 202020 
+1f1f1f 1e1e1e 1d1d1d 1c1c1c 1b1b1b 1a1a1a 191919 181818 171717 161616 151515 141414 131313 121212 111111 101010 0f0f0f 0e0e0e 0d0d0d 0c0c0c 0b0b0b 0a0a0a 090909 080808 070707 060606 050505 040404 030303 020202 010101 000000 
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c16.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c16.png
new file mode 100644
index 0000000..1bd4a4d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c16.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c16.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c16.sng
new file mode 100644
index 0000000..bac7c9d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn2c16.sng
@@ -0,0 +1,41 @@
+#SNG: from basn2c16.png
+IHDR {
+    width: 32; height: 32; bitdepth: 16;
+    using color;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+ffffffff0000 f7bdffff0000 ef7bffff0000 e739ffff0000 def7ffff0000 d6b5ffff0000 ce73ffff0000 c631ffff0000 bdefffff0000 b5adffff0000 ad6bffff0000 a529ffff0000 9ce7ffff0000 94a5ffff0000 8c63ffff0000 8421ffff0000 7bdeffff0000 739cffff0000 6b5affff0000 6318ffff0000 5ad6ffff0000 5294ffff0000 4a52ffff0000 4210ffff0000 39ceffff0000 318cffff0000 294affff0000 2108ffff0000 18c6ffff0000 1084ffff0000 0842ffff0000 0000ffff0000 
+fffff7bd0000 f7bdf7bd0000 ef7bf7bd0000 e739f7bd0000 def7f7bd0000 d6b5f7bd0000 ce73f7bd0000 c631f7bd0000 bdeff7bd0000 b5adf7bd0000 ad6bf7bd0000 a529f7bd0000 9ce7f7bd0000 94a5f7bd0000 8c63f7bd0000 8421f7bd0000 7bdef7bd0000 739cf7bd0000 6b5af7bd0000 6318f7bd0000 5ad6f7bd0000 5294f7bd0000 4a52f7bd0000 4210f7bd0000 39cef7bd0000 318cf7bd0000 294af7bd0000 2108f7bd0000 18c6f7bd0000 1084f7bd0000 0842f7bd0000 0000f7bd0842 
+ffffef7b0000 f7bdef7b0000 ef7bef7b0000 e739ef7b0000 def7ef7b0000 d6b5ef7b0000 ce73ef7b0000 c631ef7b0000 bdefef7b0000 b5adef7b0000 ad6bef7b0000 a529ef7b0000 9ce7ef7b0000 94a5ef7b0000 8c63ef7b0000 8421ef7b0000 7bdeef7b0000 739cef7b0000 6b5aef7b0000 6318ef7b0000 5ad6ef7b0000 5294ef7b0000 4a52ef7b0000 4210ef7b0000 39ceef7b0000 318cef7b0000 294aef7b0000 2108ef7b0000 18c6ef7b0000 1084ef7b0000 0842ef7b0842 0000ef7b1084 
+ffffe7390000 f7bde7390000 ef7be7390000 e739e7390000 def7e7390000 d6b5e7390000 ce73e7390000 c631e7390000 bdefe7390000 b5ade7390000 ad6be7390000 a529e7390000 9ce7e7390000 94a5e7390000 8c63e7390000 8421e7390000 7bdee7390000 739ce7390000 6b5ae7390000 6318e7390000 5ad6e7390000 5294e7390000 4a52e7390000 4210e7390000 39cee7390000 318ce7390000 294ae7390000 2108e7390000 18c6e7390000 1084e7390842 0842e7391084 0000e73918c6 
+ffffdef70000 f7bddef70000 ef7bdef70000 e739def70000 def7def70000 d6b5def70000 ce73def70000 c631def70000 bdefdef70000 b5addef70000 ad6bdef70000 a529def70000 9ce7def70000 94a5def70000 8c63def70000 8421def70000 7bdedef70000 739cdef70000 6b5adef70000 6318def70000 5ad6def70000 5294def70000 4a52def70000 4210def70000 39cedef70000 318cdef70000 294adef70000 2108def70000 18c6def70842 1084def71084 0842def718c6 0000def72108 
+ffffd6b50000 f7bdd6b50000 ef7bd6b50000 e739d6b50000 def7d6b50000 d6b5d6b50000 ce73d6b50000 c631d6b50000 bdefd6b50000 b5add6b50000 ad6bd6b50000 a529d6b50000 9ce7d6b50000 94a5d6b50000 8c63d6b50000 8421d6b50000 7bded6b50000 739cd6b50000 6b5ad6b50000 6318d6b50000 5ad6d6b50000 5294d6b50000 4a52d6b50000 4210d6b50000 39ced6b50000 318cd6b50000 294ad6b50000 2108d6b50842 18c6d6b51084 1084d6b518c6 0842d6b52108 0000d6b5294a 
+ffffce730000 f7bdce730000 ef7bce730000 e739ce730000 def7ce730000 d6b5ce730000 ce73ce730000 c631ce730000 bdefce730000 b5adce730000 ad6bce730000 a529ce730000 9ce7ce730000 94a5ce730000 8c63ce730000 8421ce730000 7bdece730000 739cce730000 6b5ace730000 6318ce730000 5ad6ce730000 5294ce730000 4a52ce730000 4210ce730000 39cece730000 318cce730000 294ace730842 2108ce731084 18c6ce7318c6 1084ce732108 0842ce73294a 0000ce73318c 
+ffffc6310000 f7bdc6310000 ef7bc6310000 e739c6310000 def7c6310000 d6b5c6310000 ce73c6310000 c631c6310000 bdefc6310000 b5adc6310000 ad6bc6310000 a529c6310000 9ce7c6310000 94a5c6310000 8c63c6310000 8421c6310000 7bdec6310000 739cc6310000 6b5ac6310000 6318c6310000 5ad6c6310000 5294c6310000 4a52c6310000 4210c6310000 39cec6310000 318cc6310842 294ac6311084 2108c63118c6 18c6c6312108 1084c631294a 0842c631318c 0000c63139ce 
+ffffbdef0000 f7bdbdef0000 ef7bbdef0000 e739bdef0000 def7bdef0000 d6b5bdef0000 ce73bdef0000 c631bdef0000 bdefbdef0000 b5adbdef0000 ad6bbdef0000 a529bdef0000 9ce7bdef0000 94a5bdef0000 8c63bdef0000 8421bdef0000 7bdebdef0000 739cbdef0000 6b5abdef0000 6318bdef0000 5ad6bdef0000 5294bdef0000 4a52bdef0000 4210bdef0000 39cebdef0842 318cbdef1084 294abdef18c6 2108bdef2108 18c6bdef294a 1084bdef318c 0842bdef39ce 0000bdef4210 
+ffffb5ad0000 f7bdb5ad0000 ef7bb5ad0000 e739b5ad0000 def7b5ad0000 d6b5b5ad0000 ce73b5ad0000 c631b5ad0000 bdefb5ad0000 b5adb5ad0000 ad6bb5ad0000 a529b5ad0000 9ce7b5ad0000 94a5b5ad0000 8c63b5ad0000 8421b5ad0000 7bdeb5ad0000 739cb5ad0000 6b5ab5ad0000 6318b5ad0000 5ad6b5ad0000 5294b5ad0000 4a52b5ad0000 4210b5ad0842 39ceb5ad1084 318cb5ad18c6 294ab5ad2108 2108b5ad294a 18c6b5ad318c 1084b5ad39ce 0842b5ad4210 0000b5ad4a52 
+ffffad6b0000 f7bdad6b0000 ef7bad6b0000 e739ad6b0000 def7ad6b0000 d6b5ad6b0000 ce73ad6b0000 c631ad6b0000 bdefad6b0000 b5adad6b0000 ad6bad6b0000 a529ad6b0000 9ce7ad6b0000 94a5ad6b0000 8c63ad6b0000 8421ad6b0000 7bdead6b0000 739cad6b0000 6b5aad6b0000 6318ad6b0000 5ad6ad6b0000 5294ad6b0000 4a52ad6b0842 4210ad6b1084 39cead6b18c6 318cad6b2108 294aad6b294a 2108ad6b318c 18c6ad6b39ce 1084ad6b4210 0842ad6b4a52 0000ad6b5294 
+ffffa5290000 f7bda5290000 ef7ba5290000 e739a5290000 def7a5290000 d6b5a5290000 ce73a5290000 c631a5290000 bdefa5290000 b5ada5290000 ad6ba5290000 a529a5290000 9ce7a5290000 94a5a5290000 8c63a5290000 8421a5290000 7bdea5290000 739ca5290000 6b5aa5290000 6318a5290000 5ad6a5290000 5294a5290842 4a52a5291084 4210a52918c6 39cea5292108 318ca529294a 294aa529318c 2108a52939ce 18c6a5294210 1084a5294a52 0842a5295294 0000a5295ad6 
+ffff9ce70000 f7bd9ce70000 ef7b9ce70000 e7399ce70000 def79ce70000 d6b59ce70000 ce739ce70000 c6319ce70000 bdef9ce70000 b5ad9ce70000 ad6b9ce70000 a5299ce70000 9ce79ce70000 94a59ce70000 8c639ce70000 84219ce70000 7bde9ce70000 739c9ce70000 6b5a9ce70000 63189ce70000 5ad69ce70842 52949ce71084 4a529ce718c6 42109ce72108 39ce9ce7294a 318c9ce7318c 294a9ce739ce 21089ce74210 18c69ce74a52 10849ce75294 08429ce75ad6 00009ce76318 
+ffff94a50000 f7bd94a50000 ef7b94a50000 e73994a50000 def794a50000 d6b594a50000 ce7394a50000 c63194a50000 bdef94a50000 b5ad94a50000 ad6b94a50000 a52994a50000 9ce794a50000 94a594a50000 8c6394a50000 842194a50000 7bde94a50000 739c94a50000 6b5a94a50000 631894a50842 5ad694a51084 529494a518c6 4a5294a52108 421094a5294a 39ce94a5318c 318c94a539ce 294a94a54210 210894a54a52 18c694a55294 108494a55ad6 084294a56318 000094a56b5a 
+ffff8c630000 f7bd8c630000 ef7b8c630000 e7398c630000 def78c630000 d6b58c630000 ce738c630000 c6318c630000 bdef8c630000 b5ad8c630000 ad6b8c630000 a5298c630000 9ce78c630000 94a58c630000 8c638c630000 84218c630000 7bde8c630000 739c8c630000 6b5a8c630842 63188c631084 5ad68c6318c6 52948c632108 4a528c63294a 42108c63318c 39ce8c6339ce 318c8c634210 294a8c634a52 21088c635294 18c68c635ad6 10848c636318 08428c636b5a 00008c63739c 
+ffff84210000 f7bd84210000 ef7b84210000 e73984210000 def784210000 d6b584210000 ce7384210000 c63184210000 bdef84210000 b5ad84210000 ad6b84210000 a52984210000 9ce784210000 94a584210000 8c6384210000 842184210000 7bde84210000 739c84210842 6b5a84211084 6318842118c6 5ad684212108 52948421294a 4a528421318c 4210842139ce 39ce84214210 318c84214a52 294a84215294 210884215ad6 18c684216318 108484216b5a 08428421739c 000084217bde 
+ffff7bde0000 f7bd7bde0000 ef7b7bde0000 e7397bde0000 def77bde0000 d6b57bde0000 ce737bde0000 c6317bde0000 bdef7bde0000 b5ad7bde0000 ad6b7bde0000 a5297bde0000 9ce77bde0000 94a57bde0000 8c637bde0000 84217bde0000 7bde7bde0842 739c7bde1084 6b5a7bde18c6 63187bde2108 5ad67bde294a 52947bde318c 4a527bde39ce 42107bde4210 39ce7bde4a52 318c7bde5294 294a7bde5ad6 21087bde6318 18c67bde6b5a 10847bde739c 08427bde7bde 00007bde8421 
+ffff739c0000 f7bd739c0000 ef7b739c0000 e739739c0000 def7739c0000 d6b5739c0000 ce73739c0000 c631739c0000 bdef739c0000 b5ad739c0000 ad6b739c0000 a529739c0000 9ce7739c0000 94a5739c0000 8c63739c0000 8421739c0842 7bde739c1084 739c739c18c6 6b5a739c2108 6318739c294a 5ad6739c318c 5294739c39ce 4a52739c4210 4210739c4a52 39ce739c5294 318c739c5ad6 294a739c6318 2108739c6b5a 18c6739c739c 1084739c7bde 0842739c8421 0000739c8c63 
+ffff6b5a0000 f7bd6b5a0000 ef7b6b5a0000 e7396b5a0000 def76b5a0000 d6b56b5a0000 ce736b5a0000 c6316b5a0000 bdef6b5a0000 b5ad6b5a0000 ad6b6b5a0000 a5296b5a0000 9ce76b5a0000 94a56b5a0000 8c636b5a0842 84216b5a1084 7bde6b5a18c6 739c6b5a2108 6b5a6b5a294a 63186b5a318c 5ad66b5a39ce 52946b5a4210 4a526b5a4a52 42106b5a5294 39ce6b5a5ad6 318c6b5a6318 294a6b5a6b5a 21086b5a739c 18c66b5a7bde 10846b5a8421 08426b5a8c63 00006b5a94a5 
+ffff63180000 f7bd63180000 ef7b63180000 e73963180000 def763180000 d6b563180000 ce7363180000 c63163180000 bdef63180000 b5ad63180000 ad6b63180000 a52963180000 9ce763180000 94a563180842 8c6363181084 8421631818c6 7bde63182108 739c6318294a 6b5a6318318c 6318631839ce 5ad663184210 529463184a52 4a5263185294 421063185ad6 39ce63186318 318c63186b5a 294a6318739c 210863187bde 18c663188421 108463188c63 0842631894a5 000063189ce7 
+ffff5ad60000 f7bd5ad60000 ef7b5ad60000 e7395ad60000 def75ad60000 d6b55ad60000 ce735ad60000 c6315ad60000 bdef5ad60000 b5ad5ad60000 ad6b5ad60000 a5295ad60000 9ce75ad60842 94a55ad61084 8c635ad618c6 84215ad62108 7bde5ad6294a 739c5ad6318c 6b5a5ad639ce 63185ad64210 5ad65ad64a52 52945ad65294 4a525ad65ad6 42105ad66318 39ce5ad66b5a 318c5ad6739c 294a5ad67bde 21085ad68421 18c65ad68c63 10845ad694a5 08425ad69ce7 00005ad6a529 
+ffff52940000 f7bd52940000 ef7b52940000 e73952940000 def752940000 d6b552940000 ce7352940000 c63152940000 bdef52940000 b5ad52940000 ad6b52940000 a52952940842 9ce752941084 94a5529418c6 8c6352942108 84215294294a 7bde5294318c 739c529439ce 6b5a52944210 631852944a52 5ad652945294 529452945ad6 4a5252946318 421052946b5a 39ce5294739c 318c52947bde 294a52948421 210852948c63 18c6529494a5 108452949ce7 08425294a529 00005294ad6b 
+ffff4a520000 f7bd4a520000 ef7b4a520000 e7394a520000 def74a520000 d6b54a520000 ce734a520000 c6314a520000 bdef4a520000 b5ad4a520000 ad6b4a520842 a5294a521084 9ce74a5218c6 94a54a522108 8c634a52294a 84214a52318c 7bde4a5239ce 739c4a524210 6b5a4a524a52 63184a525294 5ad64a525ad6 52944a526318 4a524a526b5a 42104a52739c 39ce4a527bde 318c4a528421 294a4a528c63 21084a5294a5 18c64a529ce7 10844a52a529 08424a52ad6b 00004a52b5ad 
+ffff42100000 f7bd42100000 ef7b42100000 e73942100000 def742100000 d6b542100000 ce7342100000 c63142100000 bdef42100000 b5ad42100842 ad6b42101084 a529421018c6 9ce742102108 94a54210294a 8c634210318c 8421421039ce 7bde42104210 739c42104a52 6b5a42105294 631842105ad6 5ad642106318 529442106b5a 4a524210739c 421042107bde 39ce42108421 318c42108c63 294a421094a5 210842109ce7 18c64210a529 10844210ad6b 08424210b5ad 00004210bdef 
+ffff39ce0000 f7bd39ce0000 ef7b39ce0000 e73939ce0000 def739ce0000 d6b539ce0000 ce7339ce0000 c63139ce0000 bdef39ce0842 b5ad39ce1084 ad6b39ce18c6 a52939ce2108 9ce739ce294a 94a539ce318c 8c6339ce39ce 842139ce4210 7bde39ce4a52 739c39ce5294 6b5a39ce5ad6 631839ce6318 5ad639ce6b5a 529439ce739c 4a5239ce7bde 421039ce8421 39ce39ce8c63 318c39ce94a5 294a39ce9ce7 210839cea529 18c639cead6b 108439ceb5ad 084239cebdef 000039cec631 
+ffff318c0000 f7bd318c0000 ef7b318c0000 e739318c0000 def7318c0000 d6b5318c0000 ce73318c0000 c631318c0842 bdef318c1084 b5ad318c18c6 ad6b318c2108 a529318c294a 9ce7318c318c 94a5318c39ce 8c63318c4210 8421318c4a52 7bde318c5294 739c318c5ad6 6b5a318c6318 6318318c6b5a 5ad6318c739c 5294318c7bde 4a52318c8421 4210318c8c63 39ce318c94a5 318c318c9ce7 294a318ca529 2108318cad6b 18c6318cb5ad 1084318cbdef 0842318cc631 0000318cce73 
+ffff294a0000 f7bd294a0000 ef7b294a0000 e739294a0000 def7294a0000 d6b5294a0000 ce73294a0842 c631294a1084 bdef294a18c6 b5ad294a2108 ad6b294a294a a529294a318c 9ce7294a39ce 94a5294a4210 8c63294a4a52 8421294a5294 7bde294a5ad6 739c294a6318 6b5a294a6b5a 6318294a739c 5ad6294a7bde 5294294a8421 4a52294a8c63 4210294a94a5 39ce294a9ce7 318c294aa529 294a294aad6b 2108294ab5ad 18c6294abdef 1084294ac631 0842294ace73 0000294ad6b5 
+ffff21080000 f7bd21080000 ef7b21080000 e73921080000 def721080000 d6b521080842 ce7321081084 c631210818c6 bdef21082108 b5ad2108294a ad6b2108318c a529210839ce 9ce721084210 94a521084a52 8c6321085294 842121085ad6 7bde21086318 739c21086b5a 6b5a2108739c 631821087bde 5ad621088421 529421088c63 4a52210894a5 421021089ce7 39ce2108a529 318c2108ad6b 294a2108b5ad 21082108bdef 18c62108c631 10842108ce73 08422108d6b5 00002108def7 
+ffff18c60000 f7bd18c60000 ef7b18c60000 e73918c60000 def718c60842 d6b518c61084 ce7318c618c6 c63118c62108 bdef18c6294a b5ad18c6318c ad6b18c639ce a52918c64210 9ce718c64a52 94a518c65294 8c6318c65ad6 842118c66318 7bde18c66b5a 739c18c6739c 6b5a18c67bde 631818c68421 5ad618c68c63 529418c694a5 4a5218c69ce7 421018c6a529 39ce18c6ad6b 318c18c6b5ad 294a18c6bdef 210818c6c631 18c618c6ce73 108418c6d6b5 084218c6def7 000018c6e739 
+ffff10840000 f7bd10840000 ef7b10840000 e73910840842 def710841084 d6b5108418c6 ce7310842108 c6311084294a bdef1084318c b5ad108439ce ad6b10844210 a52910844a52 9ce710845294 94a510845ad6 8c6310846318 842110846b5a 7bde1084739c 739c10847bde 6b5a10848421 631810848c63 5ad6108494a5 529410849ce7 4a521084a529 42101084ad6b 39ce1084b5ad 318c1084bdef 294a1084c631 21081084ce73 18c61084d6b5 10841084def7 08421084e739 00001084ef7b 
+ffff08420000 f7bd08420000 ef7b08420842 e73908421084 def7084218c6 d6b508422108 ce730842294a c6310842318c bdef084239ce b5ad08424210 ad6b08424a52 a52908425294 9ce708425ad6 94a508426318 8c6308426b5a 84210842739c 7bde08427bde 739c08428421 6b5a08428c63 6318084294a5 5ad608429ce7 52940842a529 4a520842ad6b 42100842b5ad 39ce0842bdef 318c0842c631 294a0842ce73 21080842d6b5 18c60842def7 10840842e739 08420842ef7b 00000842f7bd 
+ffff00000000 f7bd00000842 ef7b00001084 e739000018c6 def700002108 d6b50000294a ce730000318c c631000039ce bdef00004210 b5ad00004a52 ad6b00005294 a52900005ad6 9ce700006318 94a500006b5a 8c630000739c 842100007bde 7bde00008421 739c00008c63 6b5a000094a5 631800009ce7 5ad60000a529 52940000ad6b 4a520000b5ad 42100000bdef 39ce0000c631 318c0000ce73 294a0000d6b5 21080000def7 18c60000e739 10840000ef7b 08420000f7bd 00000000ffff 
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p01.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p01.png
new file mode 100644
index 0000000..a21db59
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p01.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p01.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p01.sng
new file mode 100644
index 0000000..a8b3ce8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p01.sng
@@ -0,0 +1,45 @@
+#SNG: from basn3p01.png
+IHDR {
+    width: 32; height: 32; bitdepth: 1;
+    using color palette;
+}
+gAMA {1.0000}
+PLTE {
+    (238,255, 34)     # rgb = (0xee,0xff,0x22)
+    ( 34,102,255)     # rgb = (0x22,0x66,0xff)
+}
+IMAGE {
+    pixels hex
+0f0f0f0f
+0f0f0f0f
+0f0f0f0f
+0f0f0f0f
+f0f0f0f0
+f0f0f0f0
+f0f0f0f0
+f0f0f0f0
+0f0f0f0f
+0f0f0f0f
+0f0f0f0f
+0f0f0f0f
+f0f0f0f0
+f0f0f0f0
+f0f0f0f0
+f0f0f0f0
+0f0f0f0f
+0f0f0f0f
+0f0f0f0f
+0f0f0f0f
+f0f0f0f0
+f0f0f0f0
+f0f0f0f0
+f0f0f0f0
+0f0f0f0f
+0f0f0f0f
+0f0f0f0f
+0f0f0f0f
+f0f0f0f0
+f0f0f0f0
+f0f0f0f0
+f0f0f0f0
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p02.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p02.png
new file mode 100644
index 0000000..1d0ab61
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p02.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p02.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p02.sng
new file mode 100644
index 0000000..ab3fb37
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p02.sng
@@ -0,0 +1,47 @@
+#SNG: from basn3p02.png
+IHDR {
+    width: 32; height: 32; bitdepth: 2;
+    using color palette;
+}
+gAMA {1.0000}
+PLTE {
+    (  0,255,  0)     # rgb = (0x00,0xff,0x00)
+    (255,  0,  0)     # rgb = (0xff,0x00,0x00)
+    (255,255,  0)     # rgb = (0xff,0xff,0x00)
+    (  0,  0,255)     # rgb = (0x00,0x00,0xff)
+}
+IMAGE {
+    pixels hex
+ff55aa00ff55aa00
+ff55aa00ff55aa00
+ff55aa00ff55aa00
+ff55aa00ff55aa00
+00ff55aa00ff55aa
+00ff55aa00ff55aa
+00ff55aa00ff55aa
+00ff55aa00ff55aa
+aa00ff55aa00ff55
+aa00ff55aa00ff55
+aa00ff55aa00ff55
+aa00ff55aa00ff55
+55aa00ff55aa00ff
+55aa00ff55aa00ff
+55aa00ff55aa00ff
+55aa00ff55aa00ff
+ff55aa00ff55aa00
+ff55aa00ff55aa00
+ff55aa00ff55aa00
+ff55aa00ff55aa00
+00ff55aa00ff55aa
+00ff55aa00ff55aa
+00ff55aa00ff55aa
+00ff55aa00ff55aa
+aa00ff55aa00ff55
+aa00ff55aa00ff55
+aa00ff55aa00ff55
+aa00ff55aa00ff55
+55aa00ff55aa00ff
+55aa00ff55aa00ff
+55aa00ff55aa00ff
+55aa00ff55aa00ff
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p04.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p04.png
new file mode 100644
index 0000000..6dc6eac
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p04.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p04.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p04.sng
new file mode 100644
index 0000000..a2b2fb5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p04.sng
@@ -0,0 +1,58 @@
+#SNG: from basn3p04.png
+IHDR {
+    width: 32; height: 32; bitdepth: 4;
+    using color palette;
+}
+gAMA {1.0000}
+PLTE {
+    ( 34,  0,255)     # rgb = (0x22,0x00,0xff)
+    (  0,255,255)     # rgb = (0x00,0xff,0xff)
+    (136,  0,255)     # rgb = (0x88,0x00,0xff)
+    ( 34,255,  0)     # rgb = (0x22,0xff,0x00)
+    (  0,153,255)     # rgb = (0x00,0x99,0xff)
+    (255,102,  0)     # rgb = (0xff,0x66,0x00)
+    (221,  0,255)     # rgb = (0xdd,0x00,0xff)
+    (119,255,  0)     # rgb = (0x77,0xff,0x00)
+    (255,  0,  0)     # rgb = (0xff,0x00,0x00)
+    (  0,255,153)     # rgb = (0x00,0xff,0x99)
+    (221,255,  0)     # rgb = (0xdd,0xff,0x00)
+    (255,  0,187)     # rgb = (0xff,0x00,0xbb)
+    (255,187,  0)     # rgb = (0xff,0xbb,0x00)
+    (  0, 68,255)     # rgb = (0x00,0x44,0xff)
+    (  0,255, 68)     # rgb = (0x00,0xff,0x44)
+}
+IMAGE {
+    pixels hex
+88885555ccccaaaa77773333eeee9999
+88885555ccccaaaa77773333eeee9999
+88885555ccccaaaa77773333eeee9999
+88885555ccccaaaa77773333eeee9999
+5555ccccaaaa77773333eeee99991111
+5555ccccaaaa77773333eeee99991111
+5555ccccaaaa77773333eeee99991111
+5555ccccaaaa77773333eeee99991111
+ccccaaaa77773333eeee999911114444
+ccccaaaa77773333eeee999911114444
+ccccaaaa77773333eeee999911114444
+ccccaaaa77773333eeee999911114444
+aaaa77773333eeee999911114444dddd
+aaaa77773333eeee999911114444dddd
+aaaa77773333eeee999911114444dddd
+aaaa77773333eeee999911114444dddd
+77773333eeee999911114444dddd0000
+77773333eeee999911114444dddd0000
+77773333eeee999911114444dddd0000
+77773333eeee999911114444dddd0000
+3333eeee999911114444dddd00002222
+3333eeee999911114444dddd00002222
+3333eeee999911114444dddd00002222
+3333eeee999911114444dddd00002222
+eeee999911114444dddd000022226666
+eeee999911114444dddd000022226666
+eeee999911114444dddd000022226666
+eeee999911114444dddd000022226666
+999911114444dddd000022226666bbbb
+999911114444dddd000022226666bbbb
+999911114444dddd000022226666bbbb
+999911114444dddd000022226666bbbb
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08-trns.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08-trns.png
new file mode 100644
index 0000000..b0fc0c1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08-trns.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08-trns.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08-trns.sng
new file mode 100644
index 0000000..78dc367
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08-trns.sng
@@ -0,0 +1,301 @@
+#SNG: from basn3p08-trns.png
+IHDR {
+    width: 32; height: 32; bitdepth: 8;
+    using color palette;
+}
+gAMA {1.0000}
+PLTE {
+    (255,  3,  7)     # rgb = (0xff,0x03,0x07)
+    (255,  4,  7)     # rgb = (0xff,0x04,0x07)
+    (255,  9,  7)     # rgb = (0xff,0x09,0x07)
+    (217, 14,  7)     # rgb = (0xd9,0x0e,0x07)
+    (255, 14,  7)     # rgb = (0xff,0x0e,0x07)
+    (  2, 22, 19)     # rgb = (0x02,0x16,0x13)
+    (255, 26,  7)     # rgb = (0xff,0x1a,0x07)
+    (255, 31,  7)     # rgb = (0xff,0x1f,0x07)
+    ( 10, 37, 14)     # rgb = (0x0a,0x25,0x0e)
+    (179, 37,  6)     # rgb = (0xb3,0x25,0x06)
+    (254, 42,  7)     # rgb = (0xfe,0x2a,0x07)
+    (255, 45,  7)     # rgb = (0xff,0x2d,0x07)
+    ( 25, 46,  9)     # rgb = (0x19,0x2e,0x09)
+    (  0, 48,254)     # rgb = (0x00,0x30,0xfe)
+    (  0, 48,255)     # rgb = (0x00,0x30,0xff)
+    (  0, 49,255)     # rgb = (0x00,0x31,0xff)
+    (  0, 51,254)     # rgb = (0x00,0x33,0xfe)
+    (  0, 52,255)     # rgb = (0x00,0x34,0xff)
+    (255, 53,  7)     # rgb = (0xff,0x35,0x07)
+    (  0, 54,252)     # rgb = (0x00,0x36,0xfc)
+    (254, 57,  7)     # rgb = (0xfe,0x39,0x07)
+    (251, 57,  7)     # rgb = (0xfb,0x39,0x07)
+    (247, 59,  7)     # rgb = (0xf7,0x3b,0x07)
+    (  0, 59, 61)     # rgb = (0x00,0x3b,0x3d)
+    (  0, 62,255)     # rgb = (0x00,0x3e,0xff)
+    (142, 63,  5)     # rgb = (0x8e,0x3f,0x05)
+    (  0, 63,250)     # rgb = (0x00,0x3f,0xfa)
+    (255, 63,  7)     # rgb = (0xff,0x3f,0x07)
+    (253, 68,  7)     # rgb = (0xfd,0x44,0x07)
+    (  0, 73,255)     # rgb = (0x00,0x49,0xff)
+    (  0, 73,246)     # rgb = (0x00,0x49,0xf6)
+    (255, 75,  7)     # rgb = (0xff,0x4b,0x07)
+    ( 82, 85,  9)     # rgb = (0x52,0x55,0x09)
+    (255, 85,  7)     # rgb = (0xff,0x55,0x07)
+    (  0, 89,255)     # rgb = (0x00,0x59,0xff)
+    (  0, 91,237)     # rgb = (0x00,0x5b,0xed)
+    (255, 94,  7)     # rgb = (0xff,0x5e,0x07)
+    (241,100,  7)     # rgb = (0xf1,0x64,0x07)
+    (  0,101,255)     # rgb = (0x00,0x65,0xff)
+    (253,105,  7)     # rgb = (0xfd,0x69,0x07)
+    (  0,107,223)     # rgb = (0x00,0x6b,0xdf)
+    (255,106,  7)     # rgb = (0xff,0x6a,0x07)
+    (  1,110, 95)     # rgb = (0x01,0x6e,0x5f)
+    (255,115,  7)     # rgb = (0xff,0x73,0x07)
+    (  0,117,255)     # rgb = (0x00,0x75,0xff)
+    (255,124,  7)     # rgb = (0xff,0x7c,0x07)
+    (118,126, 10)     # rgb = (0x76,0x7e,0x0a)
+    (  0,130,250)     # rgb = (0x00,0x82,0xfa)
+    (  0,132,255)     # rgb = (0x00,0x84,0xff)
+    (  0,134,207)     # rgb = (0x00,0x86,0xcf)
+    (255,134,  7)     # rgb = (0xff,0x86,0x07)
+    (  0,136,249)     # rgb = (0x00,0x88,0xf9)
+    (219,140,  6)     # rgb = (0xdb,0x8c,0x06)
+    (  0,140,252)     # rgb = (0x00,0x8c,0xfc)
+    (  0,140,255)     # rgb = (0x00,0x8c,0xff)
+    (  1,142,136)     # rgb = (0x01,0x8e,0x88)
+    (255,143,  7)     # rgb = (0xff,0x8f,0x07)
+    (243,150,  7)     # rgb = (0xf3,0x96,0x07)
+    (198,152,  7)     # rgb = (0xc6,0x98,0x07)
+    (165,153,  7)     # rgb = (0xa5,0x99,0x07)
+    (  0,157,255)     # rgb = (0x00,0x9d,0xff)
+    (255,158,  7)     # rgb = (0xff,0x9e,0x07)
+    ( 70,159,  4)     # rgb = (0x46,0x9f,0x04)
+    (  0,160,251)     # rgb = (0x00,0xa0,0xfb)
+    (203,163,  6)     # rgb = (0xcb,0xa3,0x06)
+    (  0,163,239)     # rgb = (0x00,0xa3,0xef)
+    (  1,164,178)     # rgb = (0x01,0xa4,0xb2)
+    (255,166,  7)     # rgb = (0xff,0xa6,0x07)
+    (  1,169,165)     # rgb = (0x01,0xa9,0xa5)
+    (  1,170,255)     # rgb = (0x01,0xaa,0xff)
+    (232,172,  6)     # rgb = (0xe8,0xac,0x06)
+    (255,175,  7)     # rgb = (0xff,0xaf,0x07)
+    (185,176,131)     # rgb = (0xb9,0xb0,0x83)
+    (  1,179,225)     # rgb = (0x01,0xb3,0xe1)
+    (188,179,118)     # rgb = (0xbc,0xb3,0x76)
+    (199,180,  6)     # rgb = (0xc7,0xb4,0x06)
+    (  1,182,255)     # rgb = (0x01,0xb6,0xff)
+    (  1,184,249)     # rgb = (0x01,0xb8,0xf9)
+    (255,184,  7)     # rgb = (0xff,0xb8,0x07)
+    (207,186, 71)     # rgb = (0xcf,0xba,0x47)
+    (193,187,  6)     # rgb = (0xc1,0xbb,0x06)
+    (253,191,  7)     # rgb = (0xfd,0xbf,0x07)
+    (218,193, 48)     # rgb = (0xda,0xc1,0x30)
+    (  1,193,157)     # rgb = (0x01,0xc1,0x9d)
+    (  1,196,244)     # rgb = (0x01,0xc4,0xf4)
+    (  1,196,254)     # rgb = (0x01,0xc4,0xfe)
+    ( 48,199,  3)     # rgb = (0x30,0xc7,0x03)
+    (164,199,  5)     # rgb = (0xa4,0xc7,0x05)
+    (220,202,  6)     # rgb = (0xdc,0xca,0x06)
+    (253,203,  7)     # rgb = (0xfd,0xcb,0x07)
+    (  1,204,204)     # rgb = (0x01,0xcc,0xcc)
+    (251,209,  7)     # rgb = (0xfb,0xd1,0x07)
+    (231,208, 24)     # rgb = (0xe7,0xd0,0x18)
+    (  1,210,254)     # rgb = (0x01,0xd2,0xfe)
+    (  2,211,146)     # rgb = (0x02,0xd3,0x92)
+    (  1,212,156)     # rgb = (0x01,0xd4,0x9c)
+    (  1,213,252)     # rgb = (0x01,0xd5,0xfc)
+    (237,219, 15)     # rgb = (0xed,0xdb,0x0f)
+    (  1,218,240)     # rgb = (0x01,0xda,0xf0)
+    (165,220,  5)     # rgb = (0xa5,0xdc,0x05)
+    (  1,221,250)     # rgb = (0x01,0xdd,0xfa)
+    (249,221,  6)     # rgb = (0xf9,0xdd,0x06)
+    (146,222,  4)     # rgb = (0x92,0xde,0x04)
+    (  1,224,184)     # rgb = (0x01,0xe0,0xb8)
+    (  2,224,155)     # rgb = (0x02,0xe0,0x9b)
+    (244,225, 10)     # rgb = (0xf4,0xe1,0x0a)
+    (249,227,  7)     # rgb = (0xf9,0xe3,0x07)
+    (  2,229,133)     # rgb = (0x02,0xe5,0x85)
+    (192,228,  6)     # rgb = (0xc0,0xe4,0x06)
+    ( 37,230,  3)     # rgb = (0x25,0xe6,0x03)
+    (246,230,  7)     # rgb = (0xf6,0xe6,0x07)
+    (143,232,  4)     # rgb = (0x8f,0xe8,0x04)
+    (244,233,  8)     # rgb = (0xf4,0xe9,0x08)
+    (  2,236,139)     # rgb = (0x02,0xec,0x8b)
+    (  1,236,227)     # rgb = (0x01,0xec,0xe3)
+    (  1,238,238)     # rgb = (0x01,0xee,0xee)
+    (101,241,  4)     # rgb = (0x65,0xf1,0x04)
+    (  1,241,218)     # rgb = (0x01,0xf1,0xda)
+    (  1,240,232)     # rgb = (0x01,0xf0,0xe8)
+    (167,240,  5)     # rgb = (0xa7,0xf0,0x05)
+    ( 27,243,  2)     # rgb = (0x1b,0xf3,0x02)
+    (126,243,  4)     # rgb = (0x7e,0xf3,0x04)
+    (  2,246,113)     # rgb = (0x02,0xf6,0x71)
+    (133,248,  5)     # rgb = (0x85,0xf8,0x05)
+    ( 22,250,  1)     # rgb = (0x16,0xfa,0x01)
+    (  2,249,219)     # rgb = (0x02,0xf9,0xdb)
+    (148,250,  5)     # rgb = (0x94,0xfa,0x05)
+    (  2,250,199)     # rgb = (0x02,0xfa,0xc7)
+    (183,252,  5)     # rgb = (0xb7,0xfc,0x05)
+    (176,252,  5)     # rgb = (0xb0,0xfc,0x05)
+    (  2,252,211)     # rgb = (0x02,0xfc,0xd3)
+    (  2,252,190)     # rgb = (0x02,0xfc,0xbe)
+    (164,251,  5)     # rgb = (0xa4,0xfb,0x05)
+    ( 12,254,128)     # rgb = (0x0c,0xfe,0x80)
+    (192,253,  5)     # rgb = (0xc0,0xfd,0x05)
+    (164,253,  5)     # rgb = (0xa4,0xfd,0x05)
+    ( 26,254, 85)     # rgb = (0x1a,0xfe,0x55)
+    ( 14,254,  1)     # rgb = (0x0e,0xfe,0x01)
+    (133,253,  5)     # rgb = (0x85,0xfd,0x05)
+    (  4,253,180)     # rgb = (0x04,0xfd,0xb4)
+    (196,253,  5)     # rgb = (0xc4,0xfd,0x05)
+    (  2,253,198)     # rgb = (0x02,0xfd,0xc6)
+    (  3,255, 91)     # rgb = (0x03,0xff,0x5b)
+    (  3,255, 80)     # rgb = (0x03,0xff,0x50)
+    (186,255,  5)     # rgb = (0xba,0xff,0x05)
+    (  9,255,  2)     # rgb = (0x09,0xff,0x02)
+    (  3,255,118)     # rgb = (0x03,0xff,0x76)
+    (  9,255,  3)     # rgb = (0x09,0xff,0x03)
+    ( 10,255,  1)     # rgb = (0x0a,0xff,0x01)
+    (  3,255, 76)     # rgb = (0x03,0xff,0x4c)
+    (  3,255, 86)     # rgb = (0x03,0xff,0x56)
+    (  3,255, 82)     # rgb = (0x03,0xff,0x52)
+    ( 13,255,  1)     # rgb = (0x0d,0xff,0x01)
+    (  3,255, 49)     # rgb = (0x03,0xff,0x31)
+    (  3,255,101)     # rgb = (0x03,0xff,0x65)
+    ( 61,255, 32)     # rgb = (0x3d,0xff,0x20)
+    (129,255,  5)     # rgb = (0x81,0xff,0x05)
+    (177,255,  5)     # rgb = (0xb1,0xff,0x05)
+    (  3,255, 37)     # rgb = (0x03,0xff,0x25)
+    (149,255,  5)     # rgb = (0x95,0xff,0x05)
+    (  7,255,  6)     # rgb = (0x07,0xff,0x06)
+    (192,255,  5)     # rgb = (0xc0,0xff,0x05)
+    (  2,255,131)     # rgb = (0x02,0xff,0x83)
+    (  3,255, 98)     # rgb = (0x03,0xff,0x62)
+    ( 85,255, 11)     # rgb = (0x55,0xff,0x0b)
+    (  2,255,163)     # rgb = (0x02,0xff,0xa3)
+    (  2,255,149)     # rgb = (0x02,0xff,0x95)
+    (  4,255, 23)     # rgb = (0x04,0xff,0x17)
+    (  6,255, 12)     # rgb = (0x06,0xff,0x0c)
+    (  3,255, 67)     # rgb = (0x03,0xff,0x43)
+    (160,255,  5)     # rgb = (0xa0,0xff,0x05)
+    (119,255,  6)     # rgb = (0x77,0xff,0x06)
+    (102,255,  8)     # rgb = (0x66,0xff,0x08)
+    (255,255,255)     # rgb = (0xff,0xff,0xff)
+    (254,254,254)     # rgb = (0xfe,0xfe,0xfe)
+    (254,254,254)     # rgb = (0xfe,0xfe,0xfe)
+    (252,252,252)     # rgb = (0xfc,0xfc,0xfc)
+    (252,252,252)     # rgb = (0xfc,0xfc,0xfc)
+    (250,250,250)     # rgb = (0xfa,0xfa,0xfa)
+    (250,250,250)     # rgb = (0xfa,0xfa,0xfa)
+    (248,248,248)     # rgb = (0xf8,0xf8,0xf8)
+    (248,248,248)     # rgb = (0xf8,0xf8,0xf8)
+    (247,247,247)     # rgb = (0xf7,0xf7,0xf7)
+    (245,245,245)     # rgb = (0xf5,0xf5,0xf5)
+    (245,245,245)     # rgb = (0xf5,0xf5,0xf5)
+    (243,243,243)     # rgb = (0xf3,0xf3,0xf3)
+    (243,243,243)     # rgb = (0xf3,0xf3,0xf3)
+    (241,241,241)     # rgb = (0xf1,0xf1,0xf1)
+    (241,241,241)     # rgb = (0xf1,0xf1,0xf1)
+    (239,239,239)     # rgb = (0xef,0xef,0xef)
+    (238,238,238)     # rgb = (0xee,0xee,0xee)
+    (238,238,238)     # rgb = (0xee,0xee,0xee)
+    (236,236,236)     # rgb = (0xec,0xec,0xec)
+    (236,236,236)     # rgb = (0xec,0xec,0xec)
+    (234,234,234)     # rgb = (0xea,0xea,0xea)
+    (234,234,234)     # rgb = (0xea,0xea,0xea)
+    (232,232,232)     # rgb = (0xe8,0xe8,0xe8)
+    (231,231,231)     # rgb = (0xe7,0xe7,0xe7)
+    (231,231,231)     # rgb = (0xe7,0xe7,0xe7)
+    (229,229,229)     # rgb = (0xe5,0xe5,0xe5)
+    (229,229,229)     # rgb = (0xe5,0xe5,0xe5)
+    (227,227,227)     # rgb = (0xe3,0xe3,0xe3)
+    (226,226,226)     # rgb = (0xe2,0xe2,0xe2)
+    (226,226,226)     # rgb = (0xe2,0xe2,0xe2)
+    (224,224,224)     # rgb = (0xe0,0xe0,0xe0)
+    (224,224,224)     # rgb = (0xe0,0xe0,0xe0)
+    (222,222,222)     # rgb = (0xde,0xde,0xde)
+    (222,222,222)     # rgb = (0xde,0xde,0xde)
+    (220,220,220)     # rgb = (0xdc,0xdc,0xdc)
+    (219,219,219)     # rgb = (0xdb,0xdb,0xdb)
+    (219,219,219)     # rgb = (0xdb,0xdb,0xdb)
+    (217,217,217)     # rgb = (0xd9,0xd9,0xd9)
+    (217,217,217)     # rgb = (0xd9,0xd9,0xd9)
+    (215,215,215)     # rgb = (0xd7,0xd7,0xd7)
+    (214,214,214)     # rgb = (0xd6,0xd6,0xd6)
+    (214,214,214)     # rgb = (0xd6,0xd6,0xd6)
+    (212,212,212)     # rgb = (0xd4,0xd4,0xd4)
+    (212,212,212)     # rgb = (0xd4,0xd4,0xd4)
+    (210,210,210)     # rgb = (0xd2,0xd2,0xd2)
+    (209,209,209)     # rgb = (0xd1,0xd1,0xd1)
+    (209,209,209)     # rgb = (0xd1,0xd1,0xd1)
+    (207,207,207)     # rgb = (0xcf,0xcf,0xcf)
+    (205,205,205)     # rgb = (0xcd,0xcd,0xcd)
+    (205,205,205)     # rgb = (0xcd,0xcd,0xcd)
+    (204,204,204)     # rgb = (0xcc,0xcc,0xcc)
+    (204,204,204)     # rgb = (0xcc,0xcc,0xcc)
+    (202,202,202)     # rgb = (0xca,0xca,0xca)
+    (201,201,201)     # rgb = (0xc9,0xc9,0xc9)
+    (201,201,201)     # rgb = (0xc9,0xc9,0xc9)
+    (199,199,199)     # rgb = (0xc7,0xc7,0xc7)
+    (199,199,199)     # rgb = (0xc7,0xc7,0xc7)
+    (197,197,197)     # rgb = (0xc5,0xc5,0xc5)
+    (196,196,196)     # rgb = (0xc4,0xc4,0xc4)
+    (196,196,196)     # rgb = (0xc4,0xc4,0xc4)
+    (194,194,194)     # rgb = (0xc2,0xc2,0xc2)
+    (193,193,193)     # rgb = (0xc1,0xc1,0xc1)
+    (193,193,193)     # rgb = (0xc1,0xc1,0xc1)
+    (191,191,191)     # rgb = (0xbf,0xbf,0xbf)
+    (191,191,191)     # rgb = (0xbf,0xbf,0xbf)
+    (189,189,189)     # rgb = (0xbd,0xbd,0xbd)
+    (188,188,188)     # rgb = (0xbc,0xbc,0xbc)
+    (188,188,188)     # rgb = (0xbc,0xbc,0xbc)
+    (186,186,186)     # rgb = (0xba,0xba,0xba)
+    (185,185,185)     # rgb = (0xb9,0xb9,0xb9)
+    (185,185,185)     # rgb = (0xb9,0xb9,0xb9)
+    (183,183,183)     # rgb = (0xb7,0xb7,0xb7)
+    (182,182,182)     # rgb = (0xb6,0xb6,0xb6)
+    (182,182,182)     # rgb = (0xb6,0xb6,0xb6)
+    (180,180,180)     # rgb = (0xb4,0xb4,0xb4)
+    (178,178,178)     # rgb = (0xb2,0xb2,0xb2)
+    (178,178,178)     # rgb = (0xb2,0xb2,0xb2)
+    (177,177,177)     # rgb = (0xb1,0xb1,0xb1)
+    (177,177,177)     # rgb = (0xb1,0xb1,0xb1)
+    (175,175,175)     # rgb = (0xaf,0xaf,0xaf)
+    (174,174,174)     # rgb = (0xae,0xae,0xae)
+    (174,174,174)     # rgb = (0xae,0xae,0xae)
+}
+tRNS {
+ 197 187 190 194 186 4 186 189 4 195 84 191 5 193 175 163 205 150 191 213 88 75 67 8 147 191 220 203 95 151 223 199 8 207 156 227 199 65 163 98 226 204 12 202 167 201 11 65 178 228 205 74 59 87 178 19 201 99 18 14 184 204 184 96 22 61 227 199 22 193 97 197 254 59 253 28 192 102 199 247 58 198 244 30 109 202 188 32 96 196 60 203 239 202 230 41 207 237 119 53 213 209 37 55 45 230 214 233 92 185 223 50 230 57 124 217 43 133 221 95 198 47 233 99 194 221 107 138 152 144 226 140 133 220 172 125 218 196 118 225 161 223 235 238 200 155 147 146 172 236 236 151 183 150 234 216 217 211 151 219 132 185 145 147 217 138 144 137 142 151 217 217 213}
+IMAGE {
+    pixels hex
+0520201616160a0a0a0a0a0a0a0a010101010101010101000000000000000000
+053a3a161616160a0a0a0a0a0a0a0a0a0a06060606060607070707070707071b
+053a3a3a161616161615151c1c1c1c1c1c1c12121212121b1b1b1b1b1b1b1b1b
+053a3a3a3a252525252527272727272727272724242424242424212121212121
+053a3a3a4034343425252727272727393939392d2d2d2d2d2d2d323232323232
+053a3a404034343434343939393939393939394747474343433d3d3d3d3d3d3d
+053a404b4b4b50505046464646464646464659595959595151514e5b5b616161
+053a404b4b4b50505058585858585858588c8c8c595959595b656a6e70707070
+053a4b4b4b4b5050506c5858585858588c8c8c8c8c8c5965656a6a6e70707070
+053b4b4b4b636363506c6c6c6c6c6c8781808c8c8c86a1a1a1906e6e70707070
+053b4b5757636363636c6c6c6c7787878181808c8c86a1a190909d9d9d9daa70
+053b576666666f6363777777777e8787848481808086a19090aaaaaaaa9f9f9f
+053b576666797979797b7b7b7b7b8a8a8a8a848480809c9c9c9c9c9c9c9c9c9c
+053b66747474747474747b7b7b7b8a8a8a8a8a8aacacacacacacacacacaca4a4
+052e7474747474747474747b7b7b8a8a8a6d6d6d6d6d6d6da4a4a4a4a4a4a4a4
+052e7474747474747474a0a0a0a0a0a09393936d6d6d6d787878787878787878
+05207474747474a0a0a0a0a0a0a0a0a093939191949494948989898989898989
+052a2a2a7171717171a7a7a7a7a7a7a7a7a79e9e9e9e9e9e9e9e959595959595
+052a53536871717171717171a9a9a9a9a9a9a9a9a9a9a9a99595959595959595
+053753536871717171717171a3a3a3a3a3a3a3a3979797979a9a9a9a8e8e8e8e
+05445353686871717171717171a5a2a2a2a2a2929292928585857a7a7a7a7a7a
+054453535f68687171717171a5a5a5a5a5a5a6a6a6a6a68b8b8b8b8b8b8b8b6b
+054444535f686767676767677272727f7f8383838383838d8d8d8d8d8d8d8b8b
+054444535f6767675a5a5a627272727275757f7f7f7f5d73737d7d7d82828282
+0544445367675a5a5a5a4d546262727272757575755d5d5d7373737376767676
+054444535349495a5a5a4d4d54626262626275754c5d5d5d5d60646464767676
+054444444949494949494d4d4d5454546262624c4c4c4c4c5555556060646464
+05444444444941414133353f3f3f3f3f3f4d3636363c3c454545454531313131
+05444444442f2f2f2f333535353535352c2c2c2c2c3030303030282828282828
+053744442f2f2f2f2f2f333535351d1d22222222262626262323232323232323
+053737372f2f2f2f2f2f2f331818181818181d1d1d1d1d131a1a1a1a1a1e1e1e
+052a37372f2f2f2f2f2f18111111110f0e0e0e0e0d0d0d0d0d0d0d0d0d0d0d13
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08.png
new file mode 100644
index 0000000..0e07f48
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08.sng
new file mode 100644
index 0000000..0423bb2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn3p08.sng
@@ -0,0 +1,299 @@
+#SNG: from basn3p08.png
+IHDR {
+    width: 32; height: 32; bitdepth: 8;
+    using color palette;
+}
+gAMA {1.0000}
+PLTE {
+    ( 34, 68,  0)     # rgb = (0x22,0x44,0x00)
+    (245,255,237)     # rgb = (0xf5,0xff,0xed)
+    (119,255,119)     # rgb = (0x77,0xff,0x77)
+    (203,255,255)     # rgb = (0xcb,0xff,0xff)
+    ( 17, 10,  0)     # rgb = (0x11,0x0a,0x00)
+    ( 58,119,  0)     # rgb = (0x3a,0x77,0x00)
+    ( 34, 34,255)     # rgb = (0x22,0x22,0xff)
+    (255, 17,255)     # rgb = (0xff,0x11,0xff)
+    ( 17,  0,  0)     # rgb = (0x11,0x00,0x00)
+    ( 34, 34,  0)     # rgb = (0x22,0x22,0x00)
+    (255,172, 85)     # rgb = (0xff,0xac,0x55)
+    (102,255,102)     # rgb = (0x66,0xff,0x66)
+    (255,102,102)     # rgb = (0xff,0x66,0x66)
+    (255,  1,255)     # rgb = (0xff,0x01,0xff)
+    ( 34, 18,  0)     # rgb = (0x22,0x12,0x00)
+    (220,255,255)     # rgb = (0xdc,0xff,0xff)
+    (204,255,153)     # rgb = (0xcc,0xff,0x99)
+    ( 68, 68,255)     # rgb = (0x44,0x44,0xff)
+    (  0, 85, 85)     # rgb = (0x00,0x55,0x55)
+    ( 34,  0,  0)     # rgb = (0x22,0x00,0x00)
+    (203,203,255)     # rgb = (0xcb,0xcb,0xff)
+    ( 68, 68,  0)     # rgb = (0x44,0x44,0x00)
+    ( 85,255, 85)     # rgb = (0x55,0xff,0x55)
+    (203,203,  0)     # rgb = (0xcb,0xcb,0x00)
+    ( 51, 26,  0)     # rgb = (0x33,0x1a,0x00)
+    (255,236,220)     # rgb = (0xff,0xec,0xdc)
+    (237,255,255)     # rgb = (0xed,0xff,0xff)
+    (228,255,203)     # rgb = (0xe4,0xff,0xcb)
+    (255,220,220)     # rgb = (0xff,0xdc,0xdc)
+    ( 68,255, 68)     # rgb = (0x44,0xff,0x44)
+    (102,102,255)     # rgb = (0x66,0x66,0xff)
+    ( 51,  0,  0)     # rgb = (0x33,0x00,0x00)
+    ( 68, 34,  0)     # rgb = (0x44,0x22,0x00)
+    (237,237,255)     # rgb = (0xed,0xed,0xff)
+    (102,102,  0)     # rgb = (0x66,0x66,0x00)
+    (255,164, 68)     # rgb = (0xff,0xa4,0x44)
+    (255,255,170)     # rgb = (0xff,0xff,0xaa)
+    (237,237,  0)     # rgb = (0xed,0xed,0x00)
+    (  0,203,203)     # rgb = (0x00,0xcb,0xcb)
+    (254,255,255)     # rgb = (0xfe,0xff,0xff)
+    (253,255,254)     # rgb = (0xfd,0xff,0xfe)
+    (255,255,  1)     # rgb = (0xff,0xff,0x01)
+    ( 51,255, 51)     # rgb = (0x33,0xff,0x33)
+    ( 85, 42,  0)     # rgb = (0x55,0x2a,0x00)
+    (  1,  1,255)     # rgb = (0x01,0x01,0xff)
+    (136,136,255)     # rgb = (0x88,0x88,0xff)
+    (  0,170,170)     # rgb = (0x00,0xaa,0xaa)
+    (  1,  1,  0)     # rgb = (0x01,0x01,0x00)
+    ( 68,  0,  0)     # rgb = (0x44,0x00,0x00)
+    (136,136,  0)     # rgb = (0x88,0x88,0x00)
+    (255,228,203)     # rgb = (0xff,0xe4,0xcb)
+    (186, 91,  0)     # rgb = (0xba,0x5b,0x00)
+    ( 34,255, 34)     # rgb = (0x22,0xff,0x22)
+    (102, 50,  0)     # rgb = (0x66,0x32,0x00)
+    (255,255,153)     # rgb = (0xff,0xff,0x99)
+    (170,170,255)     # rgb = (0xaa,0xaa,0xff)
+    ( 85,  0,  0)     # rgb = (0x55,0x00,0x00)
+    (170,170,  0)     # rgb = (0xaa,0xaa,0x00)
+    (203, 99,  0)     # rgb = (0xcb,0x63,0x00)
+    ( 17,255, 17)     # rgb = (0x11,0xff,0x11)
+    (212,255,170)     # rgb = (0xd4,0xff,0xaa)
+    (119, 58,  0)     # rgb = (0x77,0x3a,0x00)
+    (255, 68, 68)     # rgb = (0xff,0x44,0x44)
+    (220,107,  0)     # rgb = (0xdc,0x6b,0x00)
+    (102,  0,  0)     # rgb = (0x66,0x00,0x00)
+    (  1,255,  1)     # rgb = (0x01,0xff,0x01)
+    (136, 66,  0)     # rgb = (0x88,0x42,0x00)
+    (236,255,220)     # rgb = (0xec,0xff,0xdc)
+    (107,220,  0)     # rgb = (0x6b,0xdc,0x00)
+    (255,220,186)     # rgb = (0xff,0xdc,0xba)
+    (  0, 51, 51)     # rgb = (0x00,0x33,0x33)
+    (  0,237,  0)     # rgb = (0x00,0xed,0x00)
+    (237,115,  0)     # rgb = (0xed,0x73,0x00)
+    (255,255,136)     # rgb = (0xff,0xff,0x88)
+    (153, 74,  0)     # rgb = (0x99,0x4a,0x00)
+    ( 17,255,255)     # rgb = (0x11,0xff,0xff)
+    (119,  0,  0)     # rgb = (0x77,0x00,0x00)
+    (255,131,  1)     # rgb = (0xff,0x83,0x01)
+    (255,186,186)     # rgb = (0xff,0xba,0xba)
+    (254,123,  0)     # rgb = (0xfe,0x7b,0x00)
+    (255,254,255)     # rgb = (0xff,0xfe,0xff)
+    (  0,203,  0)     # rgb = (0x00,0xcb,0x00)
+    (255,153,153)     # rgb = (0xff,0x99,0x99)
+    ( 34,255,255)     # rgb = (0x22,0xff,0xff)
+    (136,  0,  0)     # rgb = (0x88,0x00,0x00)
+    (255,255,119)     # rgb = (0xff,0xff,0x77)
+    (  0,136,136)     # rgb = (0x00,0x88,0x88)
+    (255,220,255)     # rgb = (0xff,0xdc,0xff)
+    ( 26, 51,  0)     # rgb = (0x1a,0x33,0x00)
+    (  0,  0,170)     # rgb = (0x00,0x00,0xaa)
+    ( 51,255,255)     # rgb = (0x33,0xff,0xff)
+    (  0,153,  0)     # rgb = (0x00,0x99,0x00)
+    (153,  0,  0)     # rgb = (0x99,0x00,0x00)
+    (  0,  0,  1)     # rgb = (0x00,0x00,0x01)
+    ( 50,102,  0)     # rgb = (0x32,0x66,0x00)
+    (255,186,255)     # rgb = (0xff,0xba,0xff)
+    ( 68,255,255)     # rgb = (0x44,0xff,0xff)
+    (255,170,255)     # rgb = (0xff,0xaa,0xff)
+    (  0,119,  0)     # rgb = (0x00,0x77,0x00)
+    (  0,254,254)     # rgb = (0x00,0xfe,0xfe)
+    (170,  0,  0)     # rgb = (0xaa,0x00,0x00)
+    ( 74,153,  0)     # rgb = (0x4a,0x99,0x00)
+    (255,255,102)     # rgb = (0xff,0xff,0x66)
+    (255, 34, 34)     # rgb = (0xff,0x22,0x22)
+    (  0,  0,153)     # rgb = (0x00,0x00,0x99)
+    (139,255, 17)     # rgb = (0x8b,0xff,0x11)
+    ( 85,255,255)     # rgb = (0x55,0xff,0xff)
+    (255,  1,  1)     # rgb = (0xff,0x01,0x01)
+    (255,136,255)     # rgb = (0xff,0x88,0xff)
+    (  0, 85,  0)     # rgb = (0x00,0x55,0x00)
+    (  0, 17, 17)     # rgb = (0x00,0x11,0x11)
+    (255,255,254)     # rgb = (0xff,0xff,0xfe)
+    (255,253,254)     # rgb = (0xff,0xfd,0xfe)
+    (164,255, 68)     # rgb = (0xa4,0xff,0x44)
+    (102,255,255)     # rgb = (0x66,0xff,0xff)
+    (255,102,255)     # rgb = (0xff,0x66,0xff)
+    (  0, 51,  0)     # rgb = (0x00,0x33,0x00)
+    (255,255, 85)     # rgb = (0xff,0xff,0x55)
+    (255,119,119)     # rgb = (0xff,0x77,0x77)
+    (  0,  0,136)     # rgb = (0x00,0x00,0x88)
+    (255, 68,255)     # rgb = (0xff,0x44,0xff)
+    (  0, 17,  0)     # rgb = (0x00,0x11,0x00)
+    (119,255,255)     # rgb = (0x77,0xff,0xff)
+    (  0,102,102)     # rgb = (0x00,0x66,0x66)
+    (255,255,237)     # rgb = (0xff,0xff,0xed)
+    (  0,  1,  0)     # rgb = (0x00,0x01,0x00)
+    (255,245,237)     # rgb = (0xff,0xf5,0xed)
+    ( 17, 17,255)     # rgb = (0x11,0x11,0xff)
+    (255,255, 68)     # rgb = (0xff,0xff,0x44)
+    (255, 34,255)     # rgb = (0xff,0x22,0xff)
+    (255,237,237)     # rgb = (0xff,0xed,0xed)
+    ( 17, 17,  0)     # rgb = (0x11,0x11,0x00)
+    (136,255,255)     # rgb = (0x88,0xff,0xff)
+    (  0,  0,119)     # rgb = (0x00,0x00,0x77)
+    (147,255, 34)     # rgb = (0x93,0xff,0x22)
+    (  0,220,220)     # rgb = (0x00,0xdc,0xdc)
+    ( 51, 51,255)     # rgb = (0x33,0x33,0xff)
+    (254,  0,254)     # rgb = (0xfe,0x00,0xfe)
+    (186,186,255)     # rgb = (0xba,0xba,0xff)
+    (153,255,255)     # rgb = (0x99,0xff,0xff)
+    ( 51, 51,  0)     # rgb = (0x33,0x33,0x00)
+    ( 99,203,  0)     # rgb = (0x63,0xcb,0x00)
+    (186,186,  0)     # rgb = (0xba,0xba,0x00)
+    (172,255, 85)     # rgb = (0xac,0xff,0x55)
+    (255,255,220)     # rgb = (0xff,0xff,0xdc)
+    (255,255, 51)     # rgb = (0xff,0xff,0x33)
+    (123,254,  0)     # rgb = (0x7b,0xfe,0x00)
+    (237,  0,237)     # rgb = (0xed,0x00,0xed)
+    ( 85, 85,255)     # rgb = (0x55,0x55,0xff)
+    (170,255,255)     # rgb = (0xaa,0xff,0xff)
+    (220,220,255)     # rgb = (0xdc,0xdc,0xff)
+    ( 85, 85,  0)     # rgb = (0x55,0x55,0x00)
+    (  0,  0,102)     # rgb = (0x00,0x00,0x66)
+    (220,220,  0)     # rgb = (0xdc,0xdc,0x00)
+    (220,  0,220)     # rgb = (0xdc,0x00,0xdc)
+    (131,255,  1)     # rgb = (0x83,0xff,0x01)
+    (119,119,255)     # rgb = (0x77,0x77,0xff)
+    (254,254,255)     # rgb = (0xfe,0xfe,0xff)
+    (255,255,203)     # rgb = (0xff,0xff,0xcb)
+    (255, 85, 85)     # rgb = (0xff,0x55,0x55)
+    (119,119,  0)     # rgb = (0x77,0x77,0x00)
+    (254,254,  0)     # rgb = (0xfe,0xfe,0x00)
+    (203,  0,203)     # rgb = (0xcb,0x00,0xcb)
+    (  0,  0,254)     # rgb = (0x00,0x00,0xfe)
+    (  1,  2,  0)     # rgb = (0x01,0x02,0x00)
+    (  1,  0,  0)     # rgb = (0x01,0x00,0x00)
+    ( 18, 34,  0)     # rgb = (0x12,0x22,0x00)
+    (255,255, 34)     # rgb = (0xff,0xff,0x22)
+    (  0, 68, 68)     # rgb = (0x00,0x44,0x44)
+    (155,255, 51)     # rgb = (0x9b,0xff,0x33)
+    (255,212,170)     # rgb = (0xff,0xd4,0xaa)
+    (  0,  0, 85)     # rgb = (0x00,0x00,0x55)
+    (153,153,255)     # rgb = (0x99,0x99,0xff)
+    (153,153,  0)     # rgb = (0x99,0x99,0x00)
+    (186,  0,186)     # rgb = (0xba,0x00,0xba)
+    ( 42, 85,  0)     # rgb = (0x2a,0x55,0x00)
+    (255,203,203)     # rgb = (0xff,0xcb,0xcb)
+    (180,255,102)     # rgb = (0xb4,0xff,0x66)
+    (255,155, 51)     # rgb = (0xff,0x9b,0x33)
+    (255,255,186)     # rgb = (0xff,0xff,0xba)
+    (170,  0,170)     # rgb = (0xaa,0x00,0xaa)
+    ( 66,136,  0)     # rgb = (0x42,0x88,0x00)
+    ( 83,170,  0)     # rgb = (0x53,0xaa,0x00)
+    (255,170,170)     # rgb = (0xff,0xaa,0xaa)
+    (  0,  0,237)     # rgb = (0x00,0x00,0xed)
+    (  0,186,186)     # rgb = (0x00,0xba,0xba)
+    (255,255, 17)     # rgb = (0xff,0xff,0x11)
+    (  0,254,  0)     # rgb = (0x00,0xfe,0x00)
+    (  0,  0, 68)     # rgb = (0x00,0x00,0x44)
+    (  0,153,153)     # rgb = (0x00,0x99,0x99)
+    (153,  0,153)     # rgb = (0x99,0x00,0x99)
+    (255,204,153)     # rgb = (0xff,0xcc,0x99)
+    (186,  0,  0)     # rgb = (0xba,0x00,0x00)
+    (136,  0,136)     # rgb = (0x88,0x00,0x88)
+    (  0,220,  0)     # rgb = (0x00,0xdc,0x00)
+    (255,147, 34)     # rgb = (0xff,0x93,0x22)
+    (  0,  0,220)     # rgb = (0x00,0x00,0xdc)
+    (254,255,254)     # rgb = (0xfe,0xff,0xfe)
+    (170, 83,  0)     # rgb = (0xaa,0x53,0x00)
+    (119,  0,119)     # rgb = (0x77,0x00,0x77)
+    (  2,  1,  0)     # rgb = (0x02,0x01,0x00)
+    (203,  0,  0)     # rgb = (0xcb,0x00,0x00)
+    (  0,  0, 51)     # rgb = (0x00,0x00,0x33)
+    (255,237,255)     # rgb = (0xff,0xed,0xff)
+    (  0,186,  0)     # rgb = (0x00,0xba,0x00)
+    (255, 51, 51)     # rgb = (0xff,0x33,0x33)
+    (237,255,237)     # rgb = (0xed,0xff,0xed)
+    (255,196,136)     # rgb = (0xff,0xc4,0x88)
+    (188,255,119)     # rgb = (0xbc,0xff,0x77)
+    (  0,170,  0)     # rgb = (0x00,0xaa,0x00)
+    (102,  0,102)     # rgb = (0x66,0x00,0x66)
+    (  0, 34, 34)     # rgb = (0x00,0x22,0x22)
+    (220,  0,  0)     # rgb = (0xdc,0x00,0x00)
+    (255,203,255)     # rgb = (0xff,0xcb,0xff)
+    (220,255,220)     # rgb = (0xdc,0xff,0xdc)
+    (255,139, 17)     # rgb = (0xff,0x8b,0x11)
+    (  0,  0,203)     # rgb = (0x00,0x00,0xcb)
+    (  0,  1,  1)     # rgb = (0x00,0x01,0x01)
+    ( 85,  0, 85)     # rgb = (0x55,0x00,0x55)
+    (  0,136,  0)     # rgb = (0x00,0x88,0x00)
+    (  0,  0, 34)     # rgb = (0x00,0x00,0x22)
+    (  1,255,255)     # rgb = (0x01,0xff,0xff)
+    (203,255,203)     # rgb = (0xcb,0xff,0xcb)
+    (237,  0,  0)     # rgb = (0xed,0x00,0x00)
+    (255,136,136)     # rgb = (0xff,0x88,0x88)
+    ( 68,  0, 68)     # rgb = (0x44,0x00,0x44)
+    ( 91,186,  0)     # rgb = (0x5b,0xba,0x00)
+    (255,188,119)     # rgb = (0xff,0xbc,0x77)
+    (255,153,255)     # rgb = (0xff,0x99,0xff)
+    (  0,102,  0)     # rgb = (0x00,0x66,0x00)
+    (186,255,186)     # rgb = (0xba,0xff,0xba)
+    (  0,119,119)     # rgb = (0x00,0x77,0x77)
+    (115,237,  0)     # rgb = (0x73,0xed,0x00)
+    (254,  0,  0)     # rgb = (0xfe,0x00,0x00)
+    ( 51,  0, 51)     # rgb = (0x33,0x00,0x33)
+    (  0,  0,186)     # rgb = (0x00,0x00,0xba)
+    (255,119,255)     # rgb = (0xff,0x77,0xff)
+    (  0, 68,  0)     # rgb = (0x00,0x44,0x00)
+    (170,255,170)     # rgb = (0xaa,0xff,0xaa)
+    (255,254,254)     # rgb = (0xff,0xfe,0xfe)
+    (  0,  0, 17)     # rgb = (0x00,0x00,0x11)
+    ( 34,  0, 34)     # rgb = (0x22,0x00,0x22)
+    (196,255,136)     # rgb = (0xc4,0xff,0x88)
+    (  0,237,237)     # rgb = (0x00,0xed,0xed)
+    (153,255,153)     # rgb = (0x99,0xff,0x99)
+    (255, 85,255)     # rgb = (0xff,0x55,0xff)
+    (  0, 34,  0)     # rgb = (0x00,0x22,0x00)
+    (255,180,102)     # rgb = (0xff,0xb4,0x66)
+    ( 17,  0, 17)     # rgb = (0x11,0x00,0x11)
+    ( 10, 17,  0)     # rgb = (0x0a,0x11,0x00)
+    (255, 17, 17)     # rgb = (0xff,0x11,0x11)
+    (220,255,186)     # rgb = (0xdc,0xff,0xba)
+    (186,255,255)     # rgb = (0xba,0xff,0xff)
+    (136,255,136)     # rgb = (0x88,0xff,0x88)
+    (  1,  0,  1)     # rgb = (0x01,0x00,0x01)
+    (255, 51,255)     # rgb = (0xff,0x33,0xff)
+}
+IMAGE {
+    pixels hex
+a5a5a5a5a4a4a4a42f2f2f2fc8c8c8c87d7d7d7dd9d9d9d95d5d5d5dfefefefe
+080808080404040483838383f9f9f9f9797979796e6e6e6ef0f0f0f0f8f8f8f8
+131313130e0e0e0e09090909a6a6a6a6f6f6f6f6d3d3d3d3dcdcdcdcf1f1f1f1
+1f1f1f1f181818188c8c8c8c585858587474747446464646cacacacaeaeaeaea
+30303030202020201515151500000000ededededa8a8a8a8bcbcbcbce1e1e1e1
+383838382b2b2b2b97979797afafafaf6d6d6d6d12121212ababababdadadada
+4040404035353535222222225e5e5e5ee5e5e5e57b7b7b7b98989898d2d2d2d2
+4c4c4c4c3d3d3d3da0a0a0a00505050562626262e7e7e7e785858585c7c7c7c7
+545454544242424231313131b5b5b5b5dbdbdbdb5656565677777777c1c1c1c1
+5c5c5c5c4a4a4a4aadadadad656565655b5b5b5bbdbdbdbd68686868bebebebe
+64646464c6c6c6c639393939b6b6b6b6d1d1d1d12e2e2e2e59595959b4b4b4b4
+c0c0c0c0333333338e8e8e8ee2e2e2e2ccccccccb9b9b9b9ebebebebaeaeaeae
+c9c9c9c93a3a3a3a171717178d8d8d8d5151515126262626d8d8d8d8a2a2a2a2
+d4d4d4d43f3f3f3f9999999944444444c2c2c2c287878787c4c4c4c49a9a9a9a
+dfdfdfdf4848484825252525e8e8e8e847474747f3f3f3f3b8b8b8b893939393
+e9e9e9e94f4f4f4fa1a1a1a192929292bbbbbbbb63636363a3a3a3a389898989
+6b6b6b6b4d4d4d4d292929299b9b9b9b41414141dddddddd2c2c2c2c0d0d0d0d
+fafafafad7d7d7d7babababa696969693b3b3b3b4b4b4b4b7f7f7f7f07070707
+67676767c3c3c3c3a7a7a7a78686868634343434535353530606060681818181
+cdcdcdcdb2b2b2b291919191a9a9a9a92a2a2a2a5a5a5a5a88888888ffffffff
+3e3e3e3e2323232380808080717171711d1d1d1d606060601111111178787878
+9f9f9f9f0a0a0a0a757575758f8f8f8f161616166a6a6a6a94949494f5f5f5f5
+0c0c0c0cf7f7f7f766666666b1b1b1b10b0b0b0b727272721e1e1e1e73737373
+76767676e3e3e3e355555555d0d0d0d0020202027a7a7a7a9c9c9c9cecececec
+e0e0e0e0cfcfcfcf49494949f2f2f2f2fdfdfdfd848484842d2d2d2d6c6c6c6c
+52525252bfbfbfbf3636363610101010f4f4f4f48b8b8b8bacacacace4e4e4e4
+b7b7b7b7aaaaaaaa242424243c3c3c3ceeeeeeee959595953737373761616161
+4e4e4e4e45454545b3b3b3b3fbfbfbfbe6e6e6e6fcfcfcfc8a8a8a8a5f5f5f5f
+b0b0b0b0323232329e9e9e9e1b1b1b1bdededede0303030314141414d5d5d5d5
+1c1c1c1c191919199090909043434343d6d6d6d60f0f0f0f9696969657575757
+828282827e7e7e7e7c7c7c7c01010101cececece1a1a1a1a21212121cbcbcbcb
+efefefef707070706f6f6f6f28282828c5c5c5c5272727279d9d9d9d50505050
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a08.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a08.png
new file mode 100644
index 0000000..3bb0dd0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a08.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a08.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a08.sng
new file mode 100644
index 0000000..cc4096f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a08.sng
@@ -0,0 +1,41 @@
+#SNG: from basn4a08.png
+IHDR {
+    width: 32; height: 32; bitdepth: 8;
+    using color alpha;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+ffffff00 ffffff08 ffffff10 ffffff18 ffffff20 ffffff29 ffffff31 ffffff39 ffffff41 ffffff4a ffffff52 ffffff5a ffffff62 ffffff6a ffffff73 ffffff7b ffffff83 ffffff8b ffffff94 ffffff9c ffffffa4 ffffffac ffffffb4 ffffffbd ffffffc5 ffffffcd ffffffd5 ffffffde ffffffe6 ffffffee fffffff6 ffffffff 
+f6f6f600 f6f6f608 f6f6f610 f6f6f618 f6f6f620 f6f6f629 f6f6f631 f6f6f639 f6f6f641 f6f6f64a f6f6f652 f6f6f65a f6f6f662 f6f6f66a f6f6f673 f6f6f67b f6f6f683 f6f6f68b f6f6f694 f6f6f69c f6f6f6a4 f6f6f6ac f6f6f6b4 f6f6f6bd f6f6f6c5 f6f6f6cd f6f6f6d5 f6f6f6de f6f6f6e6 f6f6f6ee f6f6f6f6 f6f6f6ff 
+eeeeee00 eeeeee08 eeeeee10 eeeeee18 eeeeee20 eeeeee29 eeeeee31 eeeeee39 eeeeee41 eeeeee4a eeeeee52 eeeeee5a eeeeee62 eeeeee6a eeeeee73 eeeeee7b eeeeee83 eeeeee8b eeeeee94 eeeeee9c eeeeeea4 eeeeeeac eeeeeeb4 eeeeeebd eeeeeec5 eeeeeecd eeeeeed5 eeeeeede eeeeeee6 eeeeeeee eeeeeef6 eeeeeeff 
+e6e6e600 e6e6e608 e6e6e610 e6e6e618 e6e6e620 e6e6e629 e6e6e631 e6e6e639 e6e6e641 e6e6e64a e6e6e652 e6e6e65a e6e6e662 e6e6e66a e6e6e673 e6e6e67b e6e6e683 e6e6e68b e6e6e694 e6e6e69c e6e6e6a4 e6e6e6ac e6e6e6b4 e6e6e6bd e6e6e6c5 e6e6e6cd e6e6e6d5 e6e6e6de e6e6e6e6 e6e6e6ee e6e6e6f6 e6e6e6ff 
+dedede00 dedede08 dedede10 dedede18 dedede20 dedede29 dedede31 dedede39 dedede41 dedede4a dedede52 dedede5a dedede62 dedede6a dedede73 dedede7b dedede83 dedede8b dedede94 dedede9c dededea4 dededeac dededeb4 dededebd dededec5 dededecd dededed5 dededede dededee6 dededeee dededef6 dededeff 
+d5d5d500 d5d5d508 d5d5d510 d5d5d518 d5d5d520 d5d5d529 d5d5d531 d5d5d539 d5d5d541 d5d5d54a d5d5d552 d5d5d55a d5d5d562 d5d5d56a d5d5d573 d5d5d57b d5d5d583 d5d5d58b d5d5d594 d5d5d59c d5d5d5a4 d5d5d5ac d5d5d5b4 d5d5d5bd d5d5d5c5 d5d5d5cd d5d5d5d5 d5d5d5de d5d5d5e6 d5d5d5ee d5d5d5f6 d5d5d5ff 
+cdcdcd00 cdcdcd08 cdcdcd10 cdcdcd18 cdcdcd20 cdcdcd29 cdcdcd31 cdcdcd39 cdcdcd41 cdcdcd4a cdcdcd52 cdcdcd5a cdcdcd62 cdcdcd6a cdcdcd73 cdcdcd7b cdcdcd83 cdcdcd8b cdcdcd94 cdcdcd9c cdcdcda4 cdcdcdac cdcdcdb4 cdcdcdbd cdcdcdc5 cdcdcdcd cdcdcdd5 cdcdcdde cdcdcde6 cdcdcdee cdcdcdf6 cdcdcdff 
+c5c5c500 c5c5c508 c5c5c510 c5c5c518 c5c5c520 c5c5c529 c5c5c531 c5c5c539 c5c5c541 c5c5c54a c5c5c552 c5c5c55a c5c5c562 c5c5c56a c5c5c573 c5c5c57b c5c5c583 c5c5c58b c5c5c594 c5c5c59c c5c5c5a4 c5c5c5ac c5c5c5b4 c5c5c5bd c5c5c5c5 c5c5c5cd c5c5c5d5 c5c5c5de c5c5c5e6 c5c5c5ee c5c5c5f6 c5c5c5ff 
+bdbdbd00 bdbdbd08 bdbdbd10 bdbdbd18 bdbdbd20 bdbdbd29 bdbdbd31 bdbdbd39 bdbdbd41 bdbdbd4a bdbdbd52 bdbdbd5a bdbdbd62 bdbdbd6a bdbdbd73 bdbdbd7b bdbdbd83 bdbdbd8b bdbdbd94 bdbdbd9c bdbdbda4 bdbdbdac bdbdbdb4 bdbdbdbd bdbdbdc5 bdbdbdcd bdbdbdd5 bdbdbdde bdbdbde6 bdbdbdee bdbdbdf6 bdbdbdff 
+b4b4b400 b4b4b408 b4b4b410 b4b4b418 b4b4b420 b4b4b429 b4b4b431 b4b4b439 b4b4b441 b4b4b44a b4b4b452 b4b4b45a b4b4b462 b4b4b46a b4b4b473 b4b4b47b b4b4b483 b4b4b48b b4b4b494 b4b4b49c b4b4b4a4 b4b4b4ac b4b4b4b4 b4b4b4bd b4b4b4c5 b4b4b4cd b4b4b4d5 b4b4b4de b4b4b4e6 b4b4b4ee b4b4b4f6 b4b4b4ff 
+acacac00 acacac08 acacac10 acacac18 acacac20 acacac29 acacac31 acacac39 acacac41 acacac4a acacac52 acacac5a acacac62 acacac6a acacac73 acacac7b acacac83 acacac8b acacac94 acacac9c acacaca4 acacacac acacacb4 acacacbd acacacc5 acacaccd acacacd5 acacacde acacace6 acacacee acacacf6 acacacff 
+a4a4a400 a4a4a408 a4a4a410 a4a4a418 a4a4a420 a4a4a429 a4a4a431 a4a4a439 a4a4a441 a4a4a44a a4a4a452 a4a4a45a a4a4a462 a4a4a46a a4a4a473 a4a4a47b a4a4a483 a4a4a48b a4a4a494 a4a4a49c a4a4a4a4 a4a4a4ac a4a4a4b4 a4a4a4bd a4a4a4c5 a4a4a4cd a4a4a4d5 a4a4a4de a4a4a4e6 a4a4a4ee a4a4a4f6 a4a4a4ff 
+9c9c9c00 9c9c9c08 9c9c9c10 9c9c9c18 9c9c9c20 9c9c9c29 9c9c9c31 9c9c9c39 9c9c9c41 9c9c9c4a 9c9c9c52 9c9c9c5a 9c9c9c62 9c9c9c6a 9c9c9c73 9c9c9c7b 9c9c9c83 9c9c9c8b 9c9c9c94 9c9c9c9c 9c9c9ca4 9c9c9cac 9c9c9cb4 9c9c9cbd 9c9c9cc5 9c9c9ccd 9c9c9cd5 9c9c9cde 9c9c9ce6 9c9c9cee 9c9c9cf6 9c9c9cff 
+94949400 94949408 94949410 94949418 94949420 94949429 94949431 94949439 94949441 9494944a 94949452 9494945a 94949462 9494946a 94949473 9494947b 94949483 9494948b 94949494 9494949c 949494a4 949494ac 949494b4 949494bd 949494c5 949494cd 949494d5 949494de 949494e6 949494ee 949494f6 949494ff 
+8b8b8b00 8b8b8b08 8b8b8b10 8b8b8b18 8b8b8b20 8b8b8b29 8b8b8b31 8b8b8b39 8b8b8b41 8b8b8b4a 8b8b8b52 8b8b8b5a 8b8b8b62 8b8b8b6a 8b8b8b73 8b8b8b7b 8b8b8b83 8b8b8b8b 8b8b8b94 8b8b8b9c 8b8b8ba4 8b8b8bac 8b8b8bb4 8b8b8bbd 8b8b8bc5 8b8b8bcd 8b8b8bd5 8b8b8bde 8b8b8be6 8b8b8bee 8b8b8bf6 8b8b8bff 
+83838300 83838308 83838310 83838318 83838320 83838329 83838331 83838339 83838341 8383834a 83838352 8383835a 83838362 8383836a 83838373 8383837b 83838383 8383838b 83838394 8383839c 838383a4 838383ac 838383b4 838383bd 838383c5 838383cd 838383d5 838383de 838383e6 838383ee 838383f6 838383ff 
+7b7b7b00 7b7b7b08 7b7b7b10 7b7b7b18 7b7b7b20 7b7b7b29 7b7b7b31 7b7b7b39 7b7b7b41 7b7b7b4a 7b7b7b52 7b7b7b5a 7b7b7b62 7b7b7b6a 7b7b7b73 7b7b7b7b 7b7b7b83 7b7b7b8b 7b7b7b94 7b7b7b9c 7b7b7ba4 7b7b7bac 7b7b7bb4 7b7b7bbd 7b7b7bc5 7b7b7bcd 7b7b7bd5 7b7b7bde 7b7b7be6 7b7b7bee 7b7b7bf6 7b7b7bff 
+73737300 73737308 73737310 73737318 73737320 73737329 73737331 73737339 73737341 7373734a 73737352 7373735a 73737362 7373736a 73737373 7373737b 73737383 7373738b 73737394 7373739c 737373a4 737373ac 737373b4 737373bd 737373c5 737373cd 737373d5 737373de 737373e6 737373ee 737373f6 737373ff 
+6a6a6a00 6a6a6a08 6a6a6a10 6a6a6a18 6a6a6a20 6a6a6a29 6a6a6a31 6a6a6a39 6a6a6a41 6a6a6a4a 6a6a6a52 6a6a6a5a 6a6a6a62 6a6a6a6a 6a6a6a73 6a6a6a7b 6a6a6a83 6a6a6a8b 6a6a6a94 6a6a6a9c 6a6a6aa4 6a6a6aac 6a6a6ab4 6a6a6abd 6a6a6ac5 6a6a6acd 6a6a6ad5 6a6a6ade 6a6a6ae6 6a6a6aee 6a6a6af6 6a6a6aff 
+62626200 62626208 62626210 62626218 62626220 62626229 62626231 62626239 62626241 6262624a 62626252 6262625a 62626262 6262626a 62626273 6262627b 62626283 6262628b 62626294 6262629c 626262a4 626262ac 626262b4 626262bd 626262c5 626262cd 626262d5 626262de 626262e6 626262ee 626262f6 626262ff 
+5a5a5a00 5a5a5a08 5a5a5a10 5a5a5a18 5a5a5a20 5a5a5a29 5a5a5a31 5a5a5a39 5a5a5a41 5a5a5a4a 5a5a5a52 5a5a5a5a 5a5a5a62 5a5a5a6a 5a5a5a73 5a5a5a7b 5a5a5a83 5a5a5a8b 5a5a5a94 5a5a5a9c 5a5a5aa4 5a5a5aac 5a5a5ab4 5a5a5abd 5a5a5ac5 5a5a5acd 5a5a5ad5 5a5a5ade 5a5a5ae6 5a5a5aee 5a5a5af6 5a5a5aff 
+52525200 52525208 52525210 52525218 52525220 52525229 52525231 52525239 52525241 5252524a 52525252 5252525a 52525262 5252526a 52525273 5252527b 52525283 5252528b 52525294 5252529c 525252a4 525252ac 525252b4 525252bd 525252c5 525252cd 525252d5 525252de 525252e6 525252ee 525252f6 525252ff 
+4a4a4a00 4a4a4a08 4a4a4a10 4a4a4a18 4a4a4a20 4a4a4a29 4a4a4a31 4a4a4a39 4a4a4a41 4a4a4a4a 4a4a4a52 4a4a4a5a 4a4a4a62 4a4a4a6a 4a4a4a73 4a4a4a7b 4a4a4a83 4a4a4a8b 4a4a4a94 4a4a4a9c 4a4a4aa4 4a4a4aac 4a4a4ab4 4a4a4abd 4a4a4ac5 4a4a4acd 4a4a4ad5 4a4a4ade 4a4a4ae6 4a4a4aee 4a4a4af6 4a4a4aff 
+41414100 41414108 41414110 41414118 41414120 41414129 41414131 41414139 41414141 4141414a 41414152 4141415a 41414162 4141416a 41414173 4141417b 41414183 4141418b 41414194 4141419c 414141a4 414141ac 414141b4 414141bd 414141c5 414141cd 414141d5 414141de 414141e6 414141ee 414141f6 414141ff 
+39393900 39393908 39393910 39393918 39393920 39393929 39393931 39393939 39393941 3939394a 39393952 3939395a 39393962 3939396a 39393973 3939397b 39393983 3939398b 39393994 3939399c 393939a4 393939ac 393939b4 393939bd 393939c5 393939cd 393939d5 393939de 393939e6 393939ee 393939f6 393939ff 
+31313100 31313108 31313110 31313118 31313120 31313129 31313131 31313139 31313141 3131314a 31313152 3131315a 31313162 3131316a 31313173 3131317b 31313183 3131318b 31313194 3131319c 313131a4 313131ac 313131b4 313131bd 313131c5 313131cd 313131d5 313131de 313131e6 313131ee 313131f6 313131ff 
+29292900 29292908 29292910 29292918 29292920 29292929 29292931 29292939 29292941 2929294a 29292952 2929295a 29292962 2929296a 29292973 2929297b 29292983 2929298b 29292994 2929299c 292929a4 292929ac 292929b4 292929bd 292929c5 292929cd 292929d5 292929de 292929e6 292929ee 292929f6 292929ff 
+20202000 20202008 20202010 20202018 20202020 20202029 20202031 20202039 20202041 2020204a 20202052 2020205a 20202062 2020206a 20202073 2020207b 20202083 2020208b 20202094 2020209c 202020a4 202020ac 202020b4 202020bd 202020c5 202020cd 202020d5 202020de 202020e6 202020ee 202020f6 202020ff 
+18181800 18181808 18181810 18181818 18181820 18181829 18181831 18181839 18181841 1818184a 18181852 1818185a 18181862 1818186a 18181873 1818187b 18181883 1818188b 18181894 1818189c 181818a4 181818ac 181818b4 181818bd 181818c5 181818cd 181818d5 181818de 181818e6 181818ee 181818f6 181818ff 
+10101000 10101008 10101010 10101018 10101020 10101029 10101031 10101039 10101041 1010104a 10101052 1010105a 10101062 1010106a 10101073 1010107b 10101083 1010108b 10101094 1010109c 101010a4 101010ac 101010b4 101010bd 101010c5 101010cd 101010d5 101010de 101010e6 101010ee 101010f6 101010ff 
+08080800 08080808 08080810 08080818 08080820 08080829 08080831 08080839 08080841 0808084a 08080852 0808085a 08080862 0808086a 08080873 0808087b 08080883 0808088b 08080894 0808089c 080808a4 080808ac 080808b4 080808bd 080808c5 080808cd 080808d5 080808de 080808e6 080808ee 080808f6 080808ff 
+00000000 00000008 00000010 00000018 00000020 00000029 00000031 00000039 00000041 0000004a 00000052 0000005a 00000062 0000006a 00000073 0000007b 00000083 0000008b 00000094 0000009c 000000a4 000000ac 000000b4 000000bd 000000c5 000000cd 000000d5 000000de 000000e6 000000ee 000000f6 000000ff 
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a16.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a16.png
new file mode 100644
index 0000000..6dbee9f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a16.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a16.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a16.sng
new file mode 100644
index 0000000..d3b9b47
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn4a16.sng
@@ -0,0 +1,41 @@
+#SNG: from basn4a16.png
+IHDR {
+    width: 32; height: 32; bitdepth: 16;
+    using grayscale alpha;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+00000000 10840000 21080000 318c0000 42100000 52940000 63180000 739c0000 84200000 94a40000 a5280000 b5ac0000 c6300000 d6b40000 e7380000 f7bc0000 f7bc0000 e7380000 d6b40000 c6300000 b5ac0000 a5280000 94a40000 84200000 739c0000 63180000 52940000 42100000 318c0000 21080000 10840000 00000000 
+10840000 00001085 11a71085 234f1085 34f61085 469e1085 58461085 69ed1085 7b951085 8d3d1085 9ee41085 b08c1085 c2341085 d3db1085 e5831085 f72b1085 f72b1085 e5831085 d3db1085 c2341085 b08c1085 9ee41085 8d3d1085 7b951085 69ed1085 58461085 469e1085 34f61085 234f1085 11a71085 00001085 10840000 
+21080000 11a71085 00002109 12f62109 25ec2109 38e32109 4bd92109 5ed02109 71c62109 84bd2109 97b32109 aaa92109 bda02109 d0962109 e38d2109 f6832109 f6832109 e38d2109 d0962109 bda02109 aaa92109 97b32109 84bd2109 71c62109 5ed02109 4bd92109 38e32109 25ec2109 12f62109 00002109 11a71085 21080000 
+318c0000 234f1085 12f62109 0000318d 147a318d 28f5318d 3d70318d 51eb318d 6665318d 7ae0318d 8f5b318d a3d6318d b851318d cccb318d e146318d f5c1318d f5c1318d e146318d cccb318d b851318d a3d6318d 8f5b318d 7ae0318d 6665318d 51eb318d 3d70318d 28f5318d 147a318d 0000318d 12f62109 234f1085 318c0000 
+42100000 34f61085 25ec2109 147a318d 00004211 16424211 2c854211 42c84211 590a4211 6f4d4211 85904211 9bd24211 b2154211 c8584211 de9a4211 f4dd4211 f4dd4211 de9a4211 c8584211 b2154211 9bd24211 85904211 6f4d4211 590a4211 42c84211 2c854211 16424211 00004211 147a318d 25ec2109 34f61085 42100000 
+52940000 469e1085 38e32109 28f5318d 16424211 00005295 18615295 30c25295 49245295 61855295 79e75295 92485295 aaa95295 c30b5295 db6c5295 f3ce5295 f3ce5295 db6c5295 c30b5295 aaa95295 92485295 79e75295 61855295 49245295 30c25295 18615295 00005295 16424211 28f5318d 38e32109 469e1085 52940000 
+63180000 58461085 4bd92109 3d70318d 2c854211 18615295 00006319 1af26319 35e46319 50d76319 6bc96319 86bc6319 a1ae6319 bca06319 d7936319 f2856319 f2856319 d7936319 bca06319 a1ae6319 86bc6319 6bc96319 50d76319 35e46319 1af26319 00006319 18615295 2c854211 3d70318d 4bd92109 58461085 63180000 
+739c0000 69ed1085 5ed02109 51eb318d 42c84211 30c25295 1af26319 0000739d 1e1d739d 3c3b739d 5a59739d 7877739d 9695739d b4b3739d d2d1739d f0ef739d f0ef739d d2d1739d b4b3739d 9695739d 7877739d 5a59739d 3c3b739d 1e1d739d 0000739d 1af26319 30c25295 42c84211 51eb318d 5ed02109 69ed1085 739c0000 
+84200000 7b951085 71c62109 6665318d 590a4211 49245295 35e46319 1e1d739d 00008421 22218421 44438421 66658421 88878421 aaa98421 cccb8421 eeed8421 eeed8421 cccb8421 aaa98421 88878421 66658421 44438421 22218421 00008421 1e1d739d 35e46319 49245295 590a4211 6665318d 71c62109 7b951085 84200000 
+94a40000 8d3d1085 84bd2109 7ae0318d 6f4d4211 61855295 50d76319 3c3b739d 22218421 000094a5 276294a5 4ec494a5 762694a5 9d8994a5 c4eb94a5 ec4d94a5 ec4d94a5 c4eb94a5 9d8994a5 762694a5 4ec494a5 276294a5 000094a5 22218421 3c3b739d 50d76319 61855295 6f4d4211 7ae0318d 84bd2109 8d3d1085 94a40000 
+a5280000 9ee41085 97b32109 8f5b318d 85904211 79e75295 6bc96319 5a59739d 44438421 276294a5 0000a529 2e8ba529 5d16a529 8ba2a529 ba2da529 e8b9a529 e8b9a529 ba2da529 8ba2a529 5d16a529 2e8ba529 0000a529 276294a5 44438421 5a59739d 6bc96319 79e75295 85904211 8f5b318d 97b32109 9ee41085 a5280000 
+b5ac0000 b08c1085 aaa92109 a3d6318d 9bd24211 92485295 86bc6319 7877739d 66658421 4ec494a5 2e8ba529 0000b5ad 38e3b5ad 71c6b5ad aaa9b5ad e38db5ad e38db5ad aaa9b5ad 71c6b5ad 38e3b5ad 0000b5ad 2e8ba529 4ec494a5 66658421 7877739d 86bc6319 92485295 9bd24211 a3d6318d aaa92109 b08c1085 b5ac0000 
+c6300000 c2341085 bda02109 b851318d b2154211 aaa95295 a1ae6319 9695739d 88878421 762694a5 5d16a529 38e3b5ad 0000c631 4924c631 9248c631 db6cc631 db6cc631 9248c631 4924c631 0000c631 38e3b5ad 5d16a529 762694a5 88878421 9695739d a1ae6319 aaa95295 b2154211 b851318d bda02109 c2341085 c6300000 
+d6b40000 d3db1085 d0962109 cccb318d c8584211 c30b5295 bca06319 b4b3739d aaa98421 9d8994a5 8ba2a529 71c6b5ad 4924c631 0000d6b5 6665d6b5 cccbd6b5 cccbd6b5 6665d6b5 0000d6b5 4924c631 71c6b5ad 8ba2a529 9d8994a5 aaa98421 b4b3739d bca06319 c30b5295 c8584211 cccb318d d0962109 d3db1085 d6b40000 
+e7380000 e5831085 e38d2109 e146318d de9a4211 db6c5295 d7936319 d2d1739d cccb8421 c4eb94a5 ba2da529 aaa9b5ad 9248c631 6665d6b5 0000e739 aaa9e739 aaa9e739 0000e739 6665d6b5 9248c631 aaa9b5ad ba2da529 c4eb94a5 cccb8421 d2d1739d d7936319 db6c5295 de9a4211 e146318d e38d2109 e5831085 e7380000 
+f7bc0000 f72b1085 f6832109 f5c1318d f4dd4211 f3ce5295 f2856319 f0ef739d eeed8421 ec4d94a5 e8b9a529 e38db5ad db6cc631 cccbd6b5 aaa9e739 0000f7bd 0000f7bd aaa9e739 cccbd6b5 db6cc631 e38db5ad e8b9a529 ec4d94a5 eeed8421 f0ef739d f2856319 f3ce5295 f4dd4211 f5c1318d f6832109 f72b1085 f7bc0000 
+f7bc0000 f72b1085 f6832109 f5c1318d f4dd4211 f3ce5295 f2856319 f0ef739d eeed8421 ec4d94a5 e8b9a529 e38db5ad db6cc631 cccbd6b5 aaa9e739 0000f7bd 0000f7bd aaa9e739 cccbd6b5 db6cc631 e38db5ad e8b9a529 ec4d94a5 eeed8421 f0ef739d f2856319 f3ce5295 f4dd4211 f5c1318d f6832109 f72b1085 f7bc0000 
+e7380000 e5831085 e38d2109 e146318d de9a4211 db6c5295 d7936319 d2d1739d cccb8421 c4eb94a5 ba2da529 aaa9b5ad 9248c631 6665d6b5 0000e739 aaa9e739 aaa9e739 0000e739 6665d6b5 9248c631 aaa9b5ad ba2da529 c4eb94a5 cccb8421 d2d1739d d7936319 db6c5295 de9a4211 e146318d e38d2109 e5831085 e7380000 
+d6b40000 d3db1085 d0962109 cccb318d c8584211 c30b5295 bca06319 b4b3739d aaa98421 9d8994a5 8ba2a529 71c6b5ad 4924c631 0000d6b5 6665d6b5 cccbd6b5 cccbd6b5 6665d6b5 0000d6b5 4924c631 71c6b5ad 8ba2a529 9d8994a5 aaa98421 b4b3739d bca06319 c30b5295 c8584211 cccb318d d0962109 d3db1085 d6b40000 
+c6300000 c2341085 bda02109 b851318d b2154211 aaa95295 a1ae6319 9695739d 88878421 762694a5 5d16a529 38e3b5ad 0000c631 4924c631 9248c631 db6cc631 db6cc631 9248c631 4924c631 0000c631 38e3b5ad 5d16a529 762694a5 88878421 9695739d a1ae6319 aaa95295 b2154211 b851318d bda02109 c2341085 c6300000 
+b5ac0000 b08c1085 aaa92109 a3d6318d 9bd24211 92485295 86bc6319 7877739d 66658421 4ec494a5 2e8ba529 0000b5ad 38e3b5ad 71c6b5ad aaa9b5ad e38db5ad e38db5ad aaa9b5ad 71c6b5ad 38e3b5ad 0000b5ad 2e8ba529 4ec494a5 66658421 7877739d 86bc6319 92485295 9bd24211 a3d6318d aaa92109 b08c1085 b5ac0000 
+a5280000 9ee41085 97b32109 8f5b318d 85904211 79e75295 6bc96319 5a59739d 44438421 276294a5 0000a529 2e8ba529 5d16a529 8ba2a529 ba2da529 e8b9a529 e8b9a529 ba2da529 8ba2a529 5d16a529 2e8ba529 0000a529 276294a5 44438421 5a59739d 6bc96319 79e75295 85904211 8f5b318d 97b32109 9ee41085 a5280000 
+94a40000 8d3d1085 84bd2109 7ae0318d 6f4d4211 61855295 50d76319 3c3b739d 22218421 000094a5 276294a5 4ec494a5 762694a5 9d8994a5 c4eb94a5 ec4d94a5 ec4d94a5 c4eb94a5 9d8994a5 762694a5 4ec494a5 276294a5 000094a5 22218421 3c3b739d 50d76319 61855295 6f4d4211 7ae0318d 84bd2109 8d3d1085 94a40000 
+84200000 7b951085 71c62109 6665318d 590a4211 49245295 35e46319 1e1d739d 00008421 22218421 44438421 66658421 88878421 aaa98421 cccb8421 eeed8421 eeed8421 cccb8421 aaa98421 88878421 66658421 44438421 22218421 00008421 1e1d739d 35e46319 49245295 590a4211 6665318d 71c62109 7b951085 84200000 
+739c0000 69ed1085 5ed02109 51eb318d 42c84211 30c25295 1af26319 0000739d 1e1d739d 3c3b739d 5a59739d 7877739d 9695739d b4b3739d d2d1739d f0ef739d f0ef739d d2d1739d b4b3739d 9695739d 7877739d 5a59739d 3c3b739d 1e1d739d 0000739d 1af26319 30c25295 42c84211 51eb318d 5ed02109 69ed1085 739c0000 
+63180000 58461085 4bd92109 3d70318d 2c854211 18615295 00006319 1af26319 35e46319 50d76319 6bc96319 86bc6319 a1ae6319 bca06319 d7936319 f2856319 f2856319 d7936319 bca06319 a1ae6319 86bc6319 6bc96319 50d76319 35e46319 1af26319 00006319 18615295 2c854211 3d70318d 4bd92109 58461085 63180000 
+52940000 469e1085 38e32109 28f5318d 16424211 00005295 18615295 30c25295 49245295 61855295 79e75295 92485295 aaa95295 c30b5295 db6c5295 f3ce5295 f3ce5295 db6c5295 c30b5295 aaa95295 92485295 79e75295 61855295 49245295 30c25295 18615295 00005295 16424211 28f5318d 38e32109 469e1085 52940000 
+42100000 34f61085 25ec2109 147a318d 00004211 16424211 2c854211 42c84211 590a4211 6f4d4211 85904211 9bd24211 b2154211 c8584211 de9a4211 f4dd4211 f4dd4211 de9a4211 c8584211 b2154211 9bd24211 85904211 6f4d4211 590a4211 42c84211 2c854211 16424211 00004211 147a318d 25ec2109 34f61085 42100000 
+318c0000 234f1085 12f62109 0000318d 147a318d 28f5318d 3d70318d 51eb318d 6665318d 7ae0318d 8f5b318d a3d6318d b851318d cccb318d e146318d f5c1318d f5c1318d e146318d cccb318d b851318d a3d6318d 8f5b318d 7ae0318d 6665318d 51eb318d 3d70318d 28f5318d 147a318d 0000318d 12f62109 234f1085 318c0000 
+21080000 11a71085 00002109 12f62109 25ec2109 38e32109 4bd92109 5ed02109 71c62109 84bd2109 97b32109 aaa92109 bda02109 d0962109 e38d2109 f6832109 f6832109 e38d2109 d0962109 bda02109 aaa92109 97b32109 84bd2109 71c62109 5ed02109 4bd92109 38e32109 25ec2109 12f62109 00002109 11a71085 21080000 
+10840000 00001085 11a71085 234f1085 34f61085 469e1085 58461085 69ed1085 7b951085 8d3d1085 9ee41085 b08c1085 c2341085 d3db1085 e5831085 f72b1085 f72b1085 e5831085 d3db1085 c2341085 b08c1085 9ee41085 8d3d1085 7b951085 69ed1085 58461085 469e1085 34f61085 234f1085 11a71085 00001085 10840000 
+00000000 10840000 21080000 318c0000 42100000 52940000 63180000 739c0000 84200000 94a40000 a5280000 b5ac0000 c6300000 d6b40000 e7380000 f7bc0000 f7bc0000 e7380000 d6b40000 c6300000 b5ac0000 a5280000 94a40000 84200000 739c0000 63180000 52940000 42100000 318c0000 21080000 10840000 00000000 
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a08.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a08.png
new file mode 100644
index 0000000..6106230
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a08.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a08.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a08.sng
new file mode 100644
index 0000000..c1e0bf4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a08.sng
@@ -0,0 +1,41 @@
+#SNG: from basn6a08.png
+IHDR {
+    width: 32; height: 32; bitdepth: 8;
+    using color alpha;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+ff000800 ff000808 ff000810 ff000818 ff000820 ff000829 ff000831 ff000839 ff000841 ff00084a ff000852 ff00085a ff000862 ff00086a ff000873 ff00087b ff000883 ff00088b ff000894 ff00089c ff0008a4 ff0008ac ff0008b4 ff0008bd ff0008c5 ff0008cd ff0008d5 ff0008de ff0008e6 ff0008ee ff0008f6 ff0008ff 
+ff1f0800 ff1f0808 ff1f0810 ff1f0818 ff1f0820 ff1f0829 ff1f0831 ff1f0839 ff1f0841 ff1f084a ff1f0852 ff1f085a ff1f0862 ff1f086a ff1f0873 ff1f087b ff1f0883 ff1f088b ff1f0894 ff1f089c ff1f08a4 ff1f08ac ff1f08b4 ff1f08bd ff1f08c5 ff1f08cd ff1f08d5 ff1f08de ff1f08e6 ff1f08ee ff1f08f6 ff1f08ff 
+ff3f0800 ff3f0808 ff3f0810 ff3f0818 ff3f0820 ff3f0829 ff3f0831 ff3f0839 ff3f0841 ff3f084a ff3f0852 ff3f085a ff3f0862 ff3f086a ff3f0873 ff3f087b ff3f0883 ff3f088b ff3f0894 ff3f089c ff3f08a4 ff3f08ac ff3f08b4 ff3f08bd ff3f08c5 ff3f08cd ff3f08d5 ff3f08de ff3f08e6 ff3f08ee ff3f08f6 ff3f08ff 
+ff5f0800 ff5f0808 ff5f0810 ff5f0818 ff5f0820 ff5f0829 ff5f0831 ff5f0839 ff5f0841 ff5f084a ff5f0852 ff5f085a ff5f0862 ff5f086a ff5f0873 ff5f087b ff5f0883 ff5f088b ff5f0894 ff5f089c ff5f08a4 ff5f08ac ff5f08b4 ff5f08bd ff5f08c5 ff5f08cd ff5f08d5 ff5f08de ff5f08e6 ff5f08ee ff5f08f6 ff5f08ff 
+ff7f0700 ff7f0708 ff7f0710 ff7f0718 ff7f0720 ff7f0729 ff7f0731 ff7f0739 ff7f0741 ff7f074a ff7f0752 ff7f075a ff7f0762 ff7f076a ff7f0773 ff7f077b ff7f0783 ff7f078b ff7f0794 ff7f079c ff7f07a4 ff7f07ac ff7f07b4 ff7f07bd ff7f07c5 ff7f07cd ff7f07d5 ff7f07de ff7f07e6 ff7f07ee ff7f07f6 ff7f07ff 
+ff9f0700 ff9f0708 ff9f0710 ff9f0718 ff9f0720 ff9f0729 ff9f0731 ff9f0739 ff9f0741 ff9f074a ff9f0752 ff9f075a ff9f0762 ff9f076a ff9f0773 ff9f077b ff9f0783 ff9f078b ff9f0794 ff9f079c ff9f07a4 ff9f07ac ff9f07b4 ff9f07bd ff9f07c5 ff9f07cd ff9f07d5 ff9f07de ff9f07e6 ff9f07ee ff9f07f6 ff9f07ff 
+ffbf0700 ffbf0708 ffbf0710 ffbf0718 ffbf0720 ffbf0729 ffbf0731 ffbf0739 ffbf0741 ffbf074a ffbf0752 ffbf075a ffbf0762 ffbf076a ffbf0773 ffbf077b ffbf0783 ffbf078b ffbf0794 ffbf079c ffbf07a4 ffbf07ac ffbf07b4 ffbf07bd ffbf07c5 ffbf07cd ffbf07d5 ffbf07de ffbf07e6 ffbf07ee ffbf07f6 ffbf07ff 
+ffdf0700 ffdf0708 ffdf0710 ffdf0718 ffdf0720 ffdf0729 ffdf0731 ffdf0739 ffdf0741 ffdf074a ffdf0752 ffdf075a ffdf0762 ffdf076a ffdf0773 ffdf077b ffdf0783 ffdf078b ffdf0794 ffdf079c ffdf07a4 ffdf07ac ffdf07b4 ffdf07bd ffdf07c5 ffdf07cd ffdf07d5 ffdf07de ffdf07e6 ffdf07ee ffdf07f6 ffdf07ff 
+ffff0600 ffff0608 ffff0610 ffff0618 ffff0620 ffff0629 ffff0631 ffff0639 ffff0641 ffff064a ffff0652 ffff065a ffff0662 ffff066a ffff0673 ffff067b ffff0683 ffff068b ffff0694 ffff069c ffff06a4 ffff06ac ffff06b4 ffff06bd ffff06c5 ffff06cd ffff06d5 ffff06de ffff06e6 ffff06ee ffff06f6 ffff06ff 
+e0ff0600 e0ff0608 e0ff0610 e0ff0618 e0ff0620 e0ff0629 e0ff0631 e0ff0639 e0ff0641 e0ff064a e0ff0652 e0ff065a e0ff0662 e0ff066a e0ff0673 e0ff067b e0ff0683 e0ff068b e0ff0694 e0ff069c e0ff06a4 e0ff06ac e0ff06b4 e0ff06bd e0ff06c5 e0ff06cd e0ff06d5 e0ff06de e0ff06e6 e0ff06ee e0ff06f6 e0ff06ff 
+c0ff0600 c0ff0608 c0ff0610 c0ff0618 c0ff0620 c0ff0629 c0ff0631 c0ff0639 c0ff0641 c0ff064a c0ff0652 c0ff065a c0ff0662 c0ff066a c0ff0673 c0ff067b c0ff0683 c0ff068b c0ff0694 c0ff069c c0ff06a4 c0ff06ac c0ff06b4 c0ff06bd c0ff06c5 c0ff06cd c0ff06d5 c0ff06de c0ff06e6 c0ff06ee c0ff06f6 c0ff06ff 
+a0ff0500 a0ff0508 a0ff0510 a0ff0518 a0ff0520 a0ff0529 a0ff0531 a0ff0539 a0ff0541 a0ff054a a0ff0552 a0ff055a a0ff0562 a0ff056a a0ff0573 a0ff057b a0ff0583 a0ff058b a0ff0594 a0ff059c a0ff05a4 a0ff05ac a0ff05b4 a0ff05bd a0ff05c5 a0ff05cd a0ff05d5 a0ff05de a0ff05e6 a0ff05ee a0ff05f6 a0ff05ff 
+80ff0500 80ff0508 80ff0510 80ff0518 80ff0520 80ff0529 80ff0531 80ff0539 80ff0541 80ff054a 80ff0552 80ff055a 80ff0562 80ff056a 80ff0573 80ff057b 80ff0583 80ff058b 80ff0594 80ff059c 80ff05a4 80ff05ac 80ff05b4 80ff05bd 80ff05c5 80ff05cd 80ff05d5 80ff05de 80ff05e6 80ff05ee 80ff05f6 80ff05ff 
+60ff0500 60ff0508 60ff0510 60ff0518 60ff0520 60ff0529 60ff0531 60ff0539 60ff0541 60ff054a 60ff0552 60ff055a 60ff0562 60ff056a 60ff0573 60ff057b 60ff0583 60ff058b 60ff0594 60ff059c 60ff05a4 60ff05ac 60ff05b4 60ff05bd 60ff05c5 60ff05cd 60ff05d5 60ff05de 60ff05e6 60ff05ee 60ff05f6 60ff05ff 
+40ff0500 40ff0508 40ff0510 40ff0518 40ff0520 40ff0529 40ff0531 40ff0539 40ff0541 40ff054a 40ff0552 40ff055a 40ff0562 40ff056a 40ff0573 40ff057b 40ff0583 40ff058b 40ff0594 40ff059c 40ff05a4 40ff05ac 40ff05b4 40ff05bd 40ff05c5 40ff05cd 40ff05d5 40ff05de 40ff05e6 40ff05ee 40ff05f6 40ff05ff 
+20ff0400 20ff0408 20ff0410 20ff0418 20ff0420 20ff0429 20ff0431 20ff0439 20ff0441 20ff044a 20ff0452 20ff045a 20ff0462 20ff046a 20ff0473 20ff047b 20ff0483 20ff048b 20ff0494 20ff049c 20ff04a4 20ff04ac 20ff04b4 20ff04bd 20ff04c5 20ff04cd 20ff04d5 20ff04de 20ff04e6 20ff04ee 20ff04f6 20ff04ff 
+04ff0000 04ff0008 04ff0010 04ff0018 04ff0020 04ff0029 04ff0031 04ff0039 04ff0041 04ff004a 04ff0052 04ff005a 04ff0062 04ff006a 04ff0073 04ff007b 04ff0083 04ff008b 04ff0094 04ff009c 04ff00a4 04ff00ac 04ff00b4 04ff00bd 04ff00c5 04ff00cd 04ff00d5 04ff00de 04ff00e6 04ff00ee 04ff00f6 04ff00ff 
+04ff1f00 04ff1f08 04ff1f10 04ff1f18 04ff1f20 04ff1f29 04ff1f31 04ff1f39 04ff1f41 04ff1f4a 04ff1f52 04ff1f5a 04ff1f62 04ff1f6a 04ff1f73 04ff1f7b 04ff1f83 04ff1f8b 04ff1f94 04ff1f9c 04ff1fa4 04ff1fac 04ff1fb4 04ff1fbd 04ff1fc5 04ff1fcd 04ff1fd5 04ff1fde 04ff1fe6 04ff1fee 04ff1ff6 04ff1fff 
+03ff3f00 03ff3f08 03ff3f10 03ff3f18 03ff3f20 03ff3f29 03ff3f31 03ff3f39 03ff3f41 03ff3f4a 03ff3f52 03ff3f5a 03ff3f62 03ff3f6a 03ff3f73 03ff3f7b 03ff3f83 03ff3f8b 03ff3f94 03ff3f9c 03ff3fa4 03ff3fac 03ff3fb4 03ff3fbd 03ff3fc5 03ff3fcd 03ff3fd5 03ff3fde 03ff3fe6 03ff3fee 03ff3ff6 03ff3fff 
+03ff5f00 03ff5f08 03ff5f10 03ff5f18 03ff5f20 03ff5f29 03ff5f31 03ff5f39 03ff5f41 03ff5f4a 03ff5f52 03ff5f5a 03ff5f62 03ff5f6a 03ff5f73 03ff5f7b 03ff5f83 03ff5f8b 03ff5f94 03ff5f9c 03ff5fa4 03ff5fac 03ff5fb4 03ff5fbd 03ff5fc5 03ff5fcd 03ff5fd5 03ff5fde 03ff5fe6 03ff5fee 03ff5ff6 03ff5fff 
+03ff7f00 03ff7f08 03ff7f10 03ff7f18 03ff7f20 03ff7f29 03ff7f31 03ff7f39 03ff7f41 03ff7f4a 03ff7f52 03ff7f5a 03ff7f62 03ff7f6a 03ff7f73 03ff7f7b 03ff7f83 03ff7f8b 03ff7f94 03ff7f9c 03ff7fa4 03ff7fac 03ff7fb4 03ff7fbd 03ff7fc5 03ff7fcd 03ff7fd5 03ff7fde 03ff7fe6 03ff7fee 03ff7ff6 03ff7fff 
+03ff9f00 03ff9f08 03ff9f10 03ff9f18 03ff9f20 03ff9f29 03ff9f31 03ff9f39 03ff9f41 03ff9f4a 03ff9f52 03ff9f5a 03ff9f62 03ff9f6a 03ff9f73 03ff9f7b 03ff9f83 03ff9f8b 03ff9f94 03ff9f9c 03ff9fa4 03ff9fac 03ff9fb4 03ff9fbd 03ff9fc5 03ff9fcd 03ff9fd5 03ff9fde 03ff9fe6 03ff9fee 03ff9ff6 03ff9fff 
+02ffbf00 02ffbf08 02ffbf10 02ffbf18 02ffbf20 02ffbf29 02ffbf31 02ffbf39 02ffbf41 02ffbf4a 02ffbf52 02ffbf5a 02ffbf62 02ffbf6a 02ffbf73 02ffbf7b 02ffbf83 02ffbf8b 02ffbf94 02ffbf9c 02ffbfa4 02ffbfac 02ffbfb4 02ffbfbd 02ffbfc5 02ffbfcd 02ffbfd5 02ffbfde 02ffbfe6 02ffbfee 02ffbff6 02ffbfff 
+02ffdf00 02ffdf08 02ffdf10 02ffdf18 02ffdf20 02ffdf29 02ffdf31 02ffdf39 02ffdf41 02ffdf4a 02ffdf52 02ffdf5a 02ffdf62 02ffdf6a 02ffdf73 02ffdf7b 02ffdf83 02ffdf8b 02ffdf94 02ffdf9c 02ffdfa4 02ffdfac 02ffdfb4 02ffdfbd 02ffdfc5 02ffdfcd 02ffdfd5 02ffdfde 02ffdfe6 02ffdfee 02ffdff6 02ffdfff 
+02ffff00 02ffff08 02ffff10 02ffff18 02ffff20 02ffff29 02ffff31 02ffff39 02ffff41 02ffff4a 02ffff52 02ffff5a 02ffff62 02ffff6a 02ffff73 02ffff7b 02ffff83 02ffff8b 02ffff94 02ffff9c 02ffffa4 02ffffac 02ffffb4 02ffffbd 02ffffc5 02ffffcd 02ffffd5 02ffffde 02ffffe6 02ffffee 02fffff6 02ffffff 
+01e0ff00 01e0ff08 01e0ff10 01e0ff18 01e0ff20 01e0ff29 01e0ff31 01e0ff39 01e0ff41 01e0ff4a 01e0ff52 01e0ff5a 01e0ff62 01e0ff6a 01e0ff73 01e0ff7b 01e0ff83 01e0ff8b 01e0ff94 01e0ff9c 01e0ffa4 01e0ffac 01e0ffb4 01e0ffbd 01e0ffc5 01e0ffcd 01e0ffd5 01e0ffde 01e0ffe6 01e0ffee 01e0fff6 01e0ffff 
+01c0ff00 01c0ff08 01c0ff10 01c0ff18 01c0ff20 01c0ff29 01c0ff31 01c0ff39 01c0ff41 01c0ff4a 01c0ff52 01c0ff5a 01c0ff62 01c0ff6a 01c0ff73 01c0ff7b 01c0ff83 01c0ff8b 01c0ff94 01c0ff9c 01c0ffa4 01c0ffac 01c0ffb4 01c0ffbd 01c0ffc5 01c0ffcd 01c0ffd5 01c0ffde 01c0ffe6 01c0ffee 01c0fff6 01c0ffff 
+01a0ff00 01a0ff08 01a0ff10 01a0ff18 01a0ff20 01a0ff29 01a0ff31 01a0ff39 01a0ff41 01a0ff4a 01a0ff52 01a0ff5a 01a0ff62 01a0ff6a 01a0ff73 01a0ff7b 01a0ff83 01a0ff8b 01a0ff94 01a0ff9c 01a0ffa4 01a0ffac 01a0ffb4 01a0ffbd 01a0ffc5 01a0ffcd 01a0ffd5 01a0ffde 01a0ffe6 01a0ffee 01a0fff6 01a0ffff 
+0180ff00 0180ff08 0180ff10 0180ff18 0180ff20 0180ff29 0180ff31 0180ff39 0180ff41 0180ff4a 0180ff52 0180ff5a 0180ff62 0180ff6a 0180ff73 0180ff7b 0180ff83 0180ff8b 0180ff94 0180ff9c 0180ffa4 0180ffac 0180ffb4 0180ffbd 0180ffc5 0180ffcd 0180ffd5 0180ffde 0180ffe6 0180ffee 0180fff6 0180ffff 
+0060ff00 0060ff08 0060ff10 0060ff18 0060ff20 0060ff29 0060ff31 0060ff39 0060ff41 0060ff4a 0060ff52 0060ff5a 0060ff62 0060ff6a 0060ff73 0060ff7b 0060ff83 0060ff8b 0060ff94 0060ff9c 0060ffa4 0060ffac 0060ffb4 0060ffbd 0060ffc5 0060ffcd 0060ffd5 0060ffde 0060ffe6 0060ffee 0060fff6 0060ffff 
+0040ff00 0040ff08 0040ff10 0040ff18 0040ff20 0040ff29 0040ff31 0040ff39 0040ff41 0040ff4a 0040ff52 0040ff5a 0040ff62 0040ff6a 0040ff73 0040ff7b 0040ff83 0040ff8b 0040ff94 0040ff9c 0040ffa4 0040ffac 0040ffb4 0040ffbd 0040ffc5 0040ffcd 0040ffd5 0040ffde 0040ffe6 0040ffee 0040fff6 0040ffff 
+0020ff00 0020ff08 0020ff10 0020ff18 0020ff20 0020ff29 0020ff31 0020ff39 0020ff41 0020ff4a 0020ff52 0020ff5a 0020ff62 0020ff6a 0020ff73 0020ff7b 0020ff83 0020ff8b 0020ff94 0020ff9c 0020ffa4 0020ffac 0020ffb4 0020ffbd 0020ffc5 0020ffcd 0020ffd5 0020ffde 0020ffe6 0020ffee 0020fff6 0020ffff 
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a16.png b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a16.png
new file mode 100644
index 0000000..a9bf3cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a16.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a16.sng b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a16.sng
new file mode 100644
index 0000000..13c70a4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/testdata/pngsuite/basn6a16.sng
@@ -0,0 +1,41 @@
+#SNG: from basn6a16.png
+IHDR {
+    width: 32; height: 32; bitdepth: 16;
+    using color alpha;
+}
+gAMA {1.0000}
+IMAGE {
+    pixels hex
+ffffffff00000000 f7bcffff00000000 ef7affff00000000 e738ffff00000000 def6ffff00000000 d6b4ffff00000000 ce72ffff00000000 c630ffff00000000 bdeeffff00000000 b5acffff00000000 ad6affff00000000 a528ffff00000000 9ce6ffff00000000 94a4ffff00000000 8c62ffff00000000 8420ffff00000000 7bdeffff00000000 739cffff00000000 6b5affff00000000 6318ffff00000000 5ad6ffff00000000 5294ffff00000000 4a52ffff00000000 4210ffff00000000 39ceffff00000000 318cffff00000000 294affff00000000 2108ffff00000000 18c6ffff00000000 1084ffff00000000 0842ffff00000000 0000ffff00000000 
+fffff7bc00000000 ffffffff00001085 f72bffff00001085 ee57ffff00001085 e583ffff00001085 dcafffff00001085 d3dbffff00001085 cb08ffff00001085 c234ffff00001085 b960ffff00001085 b08cffff00001085 a7b8ffff00001085 9ee4ffff00001085 9611ffff00001085 8d3dffff00001085 8469ffff00001085 7b95ffff00001085 72c1ffff00001085 69edffff00001085 611affff00001085 5846ffff00001085 4f72ffff00001085 469effff00001085 3dcaffff00001085 34f6ffff00001085 2c23ffff00001085 234fffff00001085 1a7bffff00001085 11a7ffff00001085 08d3ffff00001085 0000ffff00001085 0000f7bc08420000 
+ffffef7a00000000 fffff72b00001085 ffffffff00002109 f683ffff00002109 ed08ffff00002109 e38dffff00002109 da12ffff00002109 d096ffff00002109 c71bffff00002109 bda0ffff00002109 b425ffff00002109 aaa9ffff00002109 a12effff00002109 97b3ffff00002109 8e38ffff00002109 84bdffff00002109 7b41ffff00002109 71c6ffff00002109 684bffff00002109 5ed0ffff00002109 5554ffff00002109 4bd9ffff00002109 425effff00002109 38e3ffff00002109 2f68ffff00002109 25ecffff00002109 1c71ffff00002109 12f6ffff00002109 097bffff00002109 0000ffff00002109 0000f72b08d31085 0000ef7a10840000 
+ffffe73800000000 ffffee5700001085 fffff68300002109 ffffffff0000318d f5c1ffff0000318d eb84ffff0000318d e146ffff0000318d d709ffff0000318d ccccffff0000318d c28effff0000318d b851ffff0000318d ae13ffff0000318d a3d6ffff0000318d 9998ffff0000318d 8f5bffff0000318d 851effff0000318d 7ae0ffff0000318d 70a3ffff0000318d 6665ffff0000318d 5c28ffff0000318d 51ebffff0000318d 47adffff0000318d 3d70ffff0000318d 3332ffff0000318d 28f5ffff0000318d 1eb8ffff0000318d 147affff0000318d 0a3dffff0000318d 0000ffff0000318d 0000f683097b2109 0000ee5711a71085 0000e73818c60000 
+ffffdef600000000 ffffe58300001085 ffffed0800002109 fffff5c10000318d ffffffff00004211 f4ddffff00004211 e9bcffff00004211 de9affff00004211 d379ffff00004211 c858ffff00004211 bd36ffff00004211 b215ffff00004211 a6f4ffff00004211 9bd2ffff00004211 90b1ffff00004211 8590ffff00004211 7a6effff00004211 6f4dffff00004211 642cffff00004211 590affff00004211 4de9ffff00004211 42c8ffff00004211 37a6ffff00004211 2c85ffff00004211 2164ffff00004211 1642ffff00004211 0b21ffff00004211 0000ffff00004211 0000f5c10a3d318d 0000ed0812f62109 0000e5831a7b1085 0000def621080000 
+ffffd6b400000000 ffffdcaf00001085 ffffe38d00002109 ffffeb840000318d fffff4dd00004211 ffffffff00005295 f3ceffff00005295 e79dffff00005295 db6cffff00005295 cf3cffff00005295 c30bffff00005295 b6daffff00005295 aaa9ffff00005295 9e79ffff00005295 9248ffff00005295 8617ffff00005295 79e7ffff00005295 6db6ffff00005295 6185ffff00005295 5554ffff00005295 4924ffff00005295 3cf3ffff00005295 30c2ffff00005295 2492ffff00005295 1861ffff00005295 0c30ffff00005295 0000ffff00005295 0000f4dd0b214211 0000eb84147a318d 0000e38d1c712109 0000dcaf234f1085 0000d6b4294a0000 
+ffffce7200000000 ffffd3db00001085 ffffda1200002109 ffffe1460000318d ffffe9bc00004211 fffff3ce00005295 ffffffff00006319 f285ffff00006319 e50cffff00006319 d793ffff00006319 ca1affff00006319 bca0ffff00006319 af27ffff00006319 a1aeffff00006319 9435ffff00006319 86bcffff00006319 7942ffff00006319 6bc9ffff00006319 5e50ffff00006319 50d7ffff00006319 435effff00006319 35e4ffff00006319 286bffff00006319 1af2ffff00006319 0d79ffff00006319 0000ffff00006319 0000f3ce0c305295 0000e9bc16424211 0000e1461eb8318d 0000da1225ec2109 0000d3db2c231085 0000ce72318c0000 
+ffffc63000000000 ffffcb0800001085 ffffd09600002109 ffffd7090000318d ffffde9a00004211 ffffe79d00005295 fffff28500006319 ffffffff0000739d f0f0ffff0000739d e1e1ffff0000739d d2d2ffff0000739d c3c3ffff0000739d b4b3ffff0000739d a5a4ffff0000739d 9695ffff0000739d 8786ffff0000739d 7877ffff0000739d 6968ffff0000739d 5a59ffff0000739d 4b4affff0000739d 3c3bffff0000739d 2d2cffff0000739d 1e1dffff0000739d 0f0effff0000739d 0000ffff0000739d 0000f2850d796319 0000e79d18615295 0000de9a21644211 0000d70928f5318d 0000d0962f682109 0000cb0834f61085 0000c63039ce0000 
+ffffbdee00000000 ffffc23400001085 ffffc71b00002109 ffffcccc0000318d ffffd37900004211 ffffdb6c00005295 ffffe50c00006319 fffff0f00000739d ffffffff00008421 eeeeffff00008421 ddddffff00008421 ccccffff00008421 bbbaffff00008421 aaa9ffff00008421 9998ffff00008421 8887ffff00008421 7776ffff00008421 6665ffff00008421 5554ffff00008421 4443ffff00008421 3332ffff00008421 2221ffff00008421 1110ffff00008421 0000ffff00008421 0000f0f00f0e739d 0000e50c1af26319 0000db6c24925295 0000d3792c854211 0000cccc3332318d 0000c71b38e32109 0000c2343dca1085 0000bdee42100000 
+ffffb5ac00000000 ffffb96000001085 ffffbda000002109 ffffc28e0000318d ffffc85800004211 ffffcf3c00005295 ffffd79300006319 ffffe1e10000739d ffffeeee00008421 ffffffff000094a5 ec4dffff000094a5 d89cffff000094a5 c4ebffff000094a5 b13affff000094a5 9d89ffff000094a5 89d8ffff000094a5 7626ffff000094a5 6275ffff000094a5 4ec4ffff000094a5 3b13ffff000094a5 2762ffff000094a5 13b1ffff000094a5 0000ffff000094a5 0000eeee11108421 0000e1e11e1d739d 0000d793286b6319 0000cf3c30c25295 0000c85837a64211 0000c28e3d70318d 0000bda0425e2109 0000b960469e1085 0000b5ac4a520000 
+ffffad6a00000000 ffffb08c00001085 ffffb42500002109 ffffb8510000318d ffffbd3600004211 ffffc30b00005295 ffffca1a00006319 ffffd2d20000739d ffffdddd00008421 ffffec4d000094a5 ffffffff0000a529 e8b9ffff0000a529 d173ffff0000a529 ba2dffff0000a529 a2e8ffff0000a529 8ba2ffff0000a529 745cffff0000a529 5d16ffff0000a529 45d1ffff0000a529 2e8bffff0000a529 1745ffff0000a529 0000ffff0000a529 0000ec4d13b194a5 0000dddd22218421 0000d2d22d2c739d 0000ca1a35e46319 0000c30b3cf35295 0000bd3642c84211 0000b85147ad318d 0000b4254bd92109 0000b08c4f721085 0000ad6a52940000 
+ffffa52800000000 ffffa7b800001085 ffffaaa900002109 ffffae130000318d ffffb21500004211 ffffb6da00005295 ffffbca000006319 ffffc3c30000739d ffffcccc00008421 ffffd89c000094a5 ffffe8b90000a529 ffffffff0000b5ad e38dffff0000b5ad c71bffff0000b5ad aaa9ffff0000b5ad 8e38ffff0000b5ad 71c6ffff0000b5ad 5554ffff0000b5ad 38e3ffff0000b5ad 1c71ffff0000b5ad 0000ffff0000b5ad 0000e8b91745a529 0000d89c276294a5 0000cccc33328421 0000c3c33c3b739d 0000bca0435e6319 0000b6da49245295 0000b2154de94211 0000ae1351eb318d 0000aaa955542109 0000a7b858461085 0000a5285ad60000 
+ffff9ce600000000 ffff9ee400001085 ffffa12e00002109 ffffa3d60000318d ffffa6f400004211 ffffaaa900005295 ffffaf2700006319 ffffb4b30000739d ffffbbba00008421 ffffc4eb000094a5 ffffd1730000a529 ffffe38d0000b5ad ffffffff0000c631 db6cffff0000c631 b6daffff0000c631 9248ffff0000c631 6db6ffff0000c631 4924ffff0000c631 2492ffff0000c631 0000ffff0000c631 0000e38d1c71b5ad 0000d1732e8ba529 0000c4eb3b1394a5 0000bbba44438421 0000b4b34b4a739d 0000af2750d76319 0000aaa955545295 0000a6f4590a4211 0000a3d65c28318d 0000a12e5ed02109 00009ee4611a1085 00009ce663180000 
+ffff94a400000000 ffff961100001085 ffff97b300002109 ffff99980000318d ffff9bd200004211 ffff9e7900005295 ffffa1ae00006319 ffffa5a40000739d ffffaaa900008421 ffffb13a000094a5 ffffba2d0000a529 ffffc71b0000b5ad ffffdb6c0000c631 ffffffff0000d6b5 ccccffff0000d6b5 9998ffff0000d6b5 6665ffff0000d6b5 3332ffff0000d6b5 0000ffff0000d6b5 0000db6c2492c631 0000c71b38e3b5ad 0000ba2d45d1a529 0000b13a4ec494a5 0000aaa955548421 0000a5a45a59739d 0000a1ae5e506319 00009e7961855295 00009bd2642c4211 000099986665318d 000097b3684b2109 0000961169ed1085 000094a46b5a0000 
+ffff8c6200000000 ffff8d3d00001085 ffff8e3800002109 ffff8f5b0000318d ffff90b100004211 ffff924800005295 ffff943500006319 ffff96950000739d ffff999800008421 ffff9d89000094a5 ffffa2e80000a529 ffffaaa90000b5ad ffffb6da0000c631 ffffcccc0000d6b5 ffffffff0000e739 aaa9ffff0000e739 5554ffff0000e739 0000ffff0000e739 0000cccc3332d6b5 0000b6da4924c631 0000aaa95554b5ad 0000a2e85d16a529 00009d89627594a5 0000999866658421 000096956968739d 000094356bc96319 000092486db65295 000090b16f4d4211 00008f5b70a3318d 00008e3871c62109 00008d3d72c11085 00008c62739c0000 
+ffff842000000000 ffff846900001085 ffff84bd00002109 ffff851e0000318d ffff859000004211 ffff861700005295 ffff86bc00006319 ffff87860000739d ffff888700008421 ffff89d8000094a5 ffff8ba20000a529 ffff8e380000b5ad ffff92480000c631 ffff99980000d6b5 ffffaaa90000e739 ffffffff0000f7bd 0000ffff0000f7bd 0000aaa95554e739 000099986665d6b5 000092486db6c631 00008e3871c6b5ad 00008ba2745ca529 000089d8762694a5 0000888777768421 000087867877739d 000086bc79426319 0000861779e75295 000085907a6e4211 0000851e7ae0318d 000084bd7b412109 000084697b951085 000084207bde0000 
+ffff7bde00000000 ffff7b9500001085 ffff7b4100002109 ffff7ae00000318d ffff7a6e00004211 ffff79e700005295 ffff794200006319 ffff78770000739d ffff777600008421 ffff7626000094a5 ffff745c0000a529 ffff71c60000b5ad ffff6db60000c631 ffff66650000d6b5 ffff55540000e739 ffff00000000f7bd 00000000fffff7bd 00005554aaa9e739 000066659998d6b5 00006db69248c631 000071c68e38b5ad 0000745c8ba2a529 0000762689d894a5 0000777688878421 000078778786739d 0000794286bc6319 000079e786175295 00007a6e85904211 00007ae0851e318d 00007b4184bd2109 00007b9584691085 00007bde84200000 
+ffff739c00000000 ffff72c100001085 ffff71c600002109 ffff70a30000318d ffff6f4d00004211 ffff6db600005295 ffff6bc900006319 ffff69680000739d ffff666500008421 ffff6275000094a5 ffff5d160000a529 ffff55540000b5ad ffff49240000c631 ffff33320000d6b5 ffff00000000e739 aaa900005554e739 55540000aaa9e739 00000000ffffe739 00003332ccccd6b5 00004924b6dac631 00005554aaa9b5ad 00005d16a2e8a529 000062759d8994a5 0000666599988421 000069689695739d 00006bc994356319 00006db692485295 00006f4d90b14211 000070a38f5b318d 000071c68e382109 000072c18d3d1085 0000739c8c620000 
+ffff6b5a00000000 ffff69ed00001085 ffff684b00002109 ffff66650000318d ffff642c00004211 ffff618500005295 ffff5e5000006319 ffff5a590000739d ffff555400008421 ffff4ec4000094a5 ffff45d10000a529 ffff38e30000b5ad ffff24920000c631 ffff00000000d6b5 cccc00003332d6b5 999800006665d6b5 666500009998d6b5 33320000ccccd6b5 00000000ffffd6b5 00002492db6cc631 000038e3c71bb5ad 000045d1ba2da529 00004ec4b13a94a5 00005554aaa98421 00005a59a5a4739d 00005e50a1ae6319 000061859e795295 0000642c9bd24211 000066659998318d 0000684b97b32109 000069ed96111085 00006b5a94a40000 
+ffff631800000000 ffff611a00001085 ffff5ed000002109 ffff5c280000318d ffff590a00004211 ffff555400005295 ffff50d700006319 ffff4b4a0000739d ffff444300008421 ffff3b13000094a5 ffff2e8b0000a529 ffff1c710000b5ad ffff00000000c631 db6c00002492c631 b6da00004924c631 924800006db6c631 6db600009248c631 49240000b6dac631 24920000db6cc631 00000000ffffc631 00001c71e38db5ad 00002e8bd173a529 00003b13c4eb94a5 00004443bbba8421 00004b4ab4b3739d 000050d7af276319 00005554aaa95295 0000590aa6f44211 00005c28a3d6318d 00005ed0a12e2109 0000611a9ee41085 000063189ce60000 
+ffff5ad600000000 ffff584600001085 ffff555400002109 ffff51eb0000318d ffff4de900004211 ffff492400005295 ffff435e00006319 ffff3c3b0000739d ffff333200008421 ffff2762000094a5 ffff17450000a529 ffff00000000b5ad e38d00001c71b5ad c71b000038e3b5ad aaa900005554b5ad 8e38000071c6b5ad 71c600008e38b5ad 55540000aaa9b5ad 38e30000c71bb5ad 1c710000e38db5ad 00000000ffffb5ad 00001745e8b9a529 00002762d89c94a5 00003332cccc8421 00003c3bc3c3739d 0000435ebca06319 00004924b6da5295 00004de9b2154211 000051ebae13318d 00005554aaa92109 00005846a7b81085 00005ad6a5280000 
+ffff529400000000 ffff4f7200001085 ffff4bd900002109 ffff47ad0000318d ffff42c800004211 ffff3cf300005295 ffff35e400006319 ffff2d2c0000739d ffff222100008421 ffff13b1000094a5 ffff00000000a529 e8b900001745a529 d17300002e8ba529 ba2d000045d1a529 a2e800005d16a529 8ba20000745ca529 745c00008ba2a529 5d160000a2e8a529 45d10000ba2da529 2e8b0000d173a529 17450000e8b9a529 00000000ffffa529 000013b1ec4d94a5 00002221dddd8421 00002d2cd2d2739d 000035e4ca1a6319 00003cf3c30b5295 000042c8bd364211 000047adb851318d 00004bd9b4252109 00004f72b08c1085 00005294ad6a0000 
+ffff4a5200000000 ffff469e00001085 ffff425e00002109 ffff3d700000318d ffff37a600004211 ffff30c200005295 ffff286b00006319 ffff1e1d0000739d ffff111000008421 ffff0000000094a5 ec4d000013b194a5 d89c0000276294a5 c4eb00003b1394a5 b13a00004ec494a5 9d890000627594a5 89d80000762694a5 7626000089d894a5 627500009d8994a5 4ec40000b13a94a5 3b130000c4eb94a5 27620000d89c94a5 13b10000ec4d94a5 00000000ffff94a5 00001110eeee8421 00001e1de1e1739d 0000286bd7936319 000030c2cf3c5295 000037a6c8584211 00003d70c28e318d 0000425ebda02109 0000469eb9601085 00004a52b5ac0000 
+ffff421000000000 ffff3dca00001085 ffff38e300002109 ffff33320000318d ffff2c8500004211 ffff249200005295 ffff1af200006319 ffff0f0e0000739d ffff000000008421 eeee000011108421 dddd000022218421 cccc000033328421 bbba000044438421 aaa9000055548421 9998000066658421 8887000077768421 7776000088878421 6665000099988421 55540000aaa98421 44430000bbba8421 33320000cccc8421 22210000dddd8421 11100000eeee8421 00000000ffff8421 00000f0ef0f0739d 00001af2e50c6319 00002492db6c5295 00002c85d3794211 00003332cccc318d 000038e3c71b2109 00003dcac2341085 00004210bdee0000 
+ffff39ce00000000 ffff34f600001085 ffff2f6800002109 ffff28f50000318d ffff216400004211 ffff186100005295 ffff0d7900006319 ffff00000000739d f0f000000f0e739d e1e100001e1d739d d2d200002d2c739d c3c300003c3b739d b4b300004b4a739d a5a400005a59739d 969500006968739d 878600007877739d 787700008786739d 696800009695739d 5a590000a5a4739d 4b4a0000b4b3739d 3c3b0000c3c3739d 2d2c0000d2d2739d 1e1d0000e1e1739d 0f0e0000f0f0739d 00000000ffff739d 00000d79f2856319 00001861e79d5295 00002164de9a4211 000028f5d709318d 00002f68d0962109 000034f6cb081085 000039cec6300000 
+ffff318c00000000 ffff2c2300001085 ffff25ec00002109 ffff1eb80000318d ffff164200004211 ffff0c3000005295 ffff000000006319 f28500000d796319 e50c00001af26319 d7930000286b6319 ca1a000035e46319 bca00000435e6319 af27000050d76319 a1ae00005e506319 943500006bc96319 86bc000079426319 7942000086bc6319 6bc9000094356319 5e500000a1ae6319 50d70000af276319 435e0000bca06319 35e40000ca1a6319 286b0000d7936319 1af20000e50c6319 0d790000f2856319 00000000ffff6319 00000c30f3ce5295 00001642e9bc4211 00001eb8e146318d 000025ecda122109 00002c23d3db1085 0000318cce720000 
+ffff294a00000000 ffff234f00001085 ffff1c7100002109 ffff147a0000318d ffff0b2100004211 ffff000000005295 f3ce00000c305295 e79d000018615295 db6c000024925295 cf3c000030c25295 c30b00003cf35295 b6da000049245295 aaa9000055545295 9e79000061855295 924800006db65295 8617000079e75295 79e7000086175295 6db6000092485295 618500009e795295 55540000aaa95295 49240000b6da5295 3cf30000c30b5295 30c20000cf3c5295 24920000db6c5295 18610000e79d5295 0c300000f3ce5295 00000000ffff5295 00000b21f4dd4211 0000147aeb84318d 00001c71e38d2109 0000234fdcaf1085 0000294ad6b40000 
+ffff210800000000 ffff1a7b00001085 ffff12f600002109 ffff0a3d0000318d ffff000000004211 f4dd00000b214211 e9bc000016424211 de9a000021644211 d37900002c854211 c858000037a64211 bd36000042c84211 b21500004de94211 a6f40000590a4211 9bd20000642c4211 90b100006f4d4211 859000007a6e4211 7a6e000085904211 6f4d000090b14211 642c00009bd24211 590a0000a6f44211 4de90000b2154211 42c80000bd364211 37a60000c8584211 2c850000d3794211 21640000de9a4211 16420000e9bc4211 0b210000f4dd4211 00000000ffff4211 00000a3df5c1318d 000012f6ed082109 00001a7be5831085 00002108def60000 
+ffff18c600000000 ffff11a700001085 ffff097b00002109 ffff00000000318d f5c100000a3d318d eb840000147a318d e14600001eb8318d d709000028f5318d cccc00003332318d c28e00003d70318d b851000047ad318d ae13000051eb318d a3d600005c28318d 999800006665318d 8f5b000070a3318d 851e00007ae0318d 7ae00000851e318d 70a300008f5b318d 666500009998318d 5c280000a3d6318d 51eb0000ae13318d 47ad0000b851318d 3d700000c28e318d 33320000cccc318d 28f50000d709318d 1eb80000e146318d 147a0000eb84318d 0a3d0000f5c1318d 00000000ffff318d 0000097bf6832109 000011a7ee571085 000018c6e7380000 
+ffff108400000000 ffff08d300001085 ffff000000002109 f6830000097b2109 ed08000012f62109 e38d00001c712109 da12000025ec2109 d09600002f682109 c71b000038e32109 bda00000425e2109 b42500004bd92109 aaa9000055542109 a12e00005ed02109 97b30000684b2109 8e38000071c62109 84bd00007b412109 7b41000084bd2109 71c600008e382109 684b000097b32109 5ed00000a12e2109 55540000aaa92109 4bd90000b4252109 425e0000bda02109 38e30000c71b2109 2f680000d0962109 25ec0000da122109 1c710000e38d2109 12f60000ed082109 097b0000f6832109 00000000ffff2109 000008d3f72b1085 00001084ef7a0000 
+ffff084200000000 ffff000000001085 f72b000008d31085 ee57000011a71085 e58300001a7b1085 dcaf0000234f1085 d3db00002c231085 cb08000034f61085 c23400003dca1085 b9600000469e1085 b08c00004f721085 a7b8000058461085 9ee40000611a1085 9611000069ed1085 8d3d000072c11085 846900007b951085 7b95000084691085 72c100008d3d1085 69ed000096111085 611a00009ee41085 58460000a7b81085 4f720000b08c1085 469e0000b9601085 3dca0000c2341085 34f60000cb081085 2c230000d3db1085 234f0000dcaf1085 1a7b0000e5831085 11a70000ee571085 08d30000f72b1085 00000000ffff1085 00000842f7bc0000 
+ffff000000000000 f7bc000008420000 ef7a000010840000 e738000018c60000 def6000021080000 d6b40000294a0000 ce720000318c0000 c630000039ce0000 bdee000042100000 b5ac00004a520000 ad6a000052940000 a52800005ad60000 9ce6000063180000 94a400006b5a0000 8c620000739c0000 842000007bde0000 7bde000084200000 739c00008c620000 6b5a000094a40000 631800009ce60000 5ad60000a5280000 52940000ad6a0000 4a520000b5ac0000 42100000bdee0000 39ce0000c6300000 318c0000ce720000 294a0000d6b40000 21080000def60000 18c60000e7380000 10840000ef7a0000 08420000f7bc0000 00000000ffff0000 
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/writer.go b/third_party/gofrontend/libgo/go/image/png/writer.go
new file mode 100644
index 0000000..629452c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/writer.go
@@ -0,0 +1,482 @@
+// 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 png
+
+import (
+	"bufio"
+	"compress/zlib"
+	"hash/crc32"
+	"image"
+	"image/color"
+	"io"
+	"strconv"
+)
+
+type encoder struct {
+	w      io.Writer
+	m      image.Image
+	cb     int
+	err    error
+	header [8]byte
+	footer [4]byte
+	tmp    [4 * 256]byte
+}
+
+// Big-endian.
+func writeUint32(b []uint8, u uint32) {
+	b[0] = uint8(u >> 24)
+	b[1] = uint8(u >> 16)
+	b[2] = uint8(u >> 8)
+	b[3] = uint8(u >> 0)
+}
+
+type opaquer interface {
+	Opaque() bool
+}
+
+// Returns whether or not the image is fully opaque.
+func opaque(m image.Image) bool {
+	if o, ok := m.(opaquer); ok {
+		return o.Opaque()
+	}
+	b := m.Bounds()
+	for y := b.Min.Y; y < b.Max.Y; y++ {
+		for x := b.Min.X; x < b.Max.X; x++ {
+			_, _, _, a := m.At(x, y).RGBA()
+			if a != 0xffff {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+// The absolute value of a byte interpreted as a signed int8.
+func abs8(d uint8) int {
+	if d < 128 {
+		return int(d)
+	}
+	return 256 - int(d)
+}
+
+func (e *encoder) writeChunk(b []byte, name string) {
+	if e.err != nil {
+		return
+	}
+	n := uint32(len(b))
+	if int(n) != len(b) {
+		e.err = UnsupportedError(name + " chunk is too large: " + strconv.Itoa(len(b)))
+		return
+	}
+	writeUint32(e.header[:4], n)
+	e.header[4] = name[0]
+	e.header[5] = name[1]
+	e.header[6] = name[2]
+	e.header[7] = name[3]
+	crc := crc32.NewIEEE()
+	crc.Write(e.header[4:8])
+	crc.Write(b)
+	writeUint32(e.footer[:4], crc.Sum32())
+
+	_, e.err = e.w.Write(e.header[:8])
+	if e.err != nil {
+		return
+	}
+	_, e.err = e.w.Write(b)
+	if e.err != nil {
+		return
+	}
+	_, e.err = e.w.Write(e.footer[:4])
+}
+
+func (e *encoder) writeIHDR() {
+	b := e.m.Bounds()
+	writeUint32(e.tmp[0:4], uint32(b.Dx()))
+	writeUint32(e.tmp[4:8], uint32(b.Dy()))
+	// Set bit depth and color type.
+	switch e.cb {
+	case cbG8:
+		e.tmp[8] = 8
+		e.tmp[9] = ctGrayscale
+	case cbTC8:
+		e.tmp[8] = 8
+		e.tmp[9] = ctTrueColor
+	case cbP8:
+		e.tmp[8] = 8
+		e.tmp[9] = ctPaletted
+	case cbTCA8:
+		e.tmp[8] = 8
+		e.tmp[9] = ctTrueColorAlpha
+	case cbG16:
+		e.tmp[8] = 16
+		e.tmp[9] = ctGrayscale
+	case cbTC16:
+		e.tmp[8] = 16
+		e.tmp[9] = ctTrueColor
+	case cbTCA16:
+		e.tmp[8] = 16
+		e.tmp[9] = ctTrueColorAlpha
+	}
+	e.tmp[10] = 0 // default compression method
+	e.tmp[11] = 0 // default filter method
+	e.tmp[12] = 0 // non-interlaced
+	e.writeChunk(e.tmp[:13], "IHDR")
+}
+
+func (e *encoder) writePLTEAndTRNS(p color.Palette) {
+	if len(p) < 1 || len(p) > 256 {
+		e.err = FormatError("bad palette length: " + strconv.Itoa(len(p)))
+		return
+	}
+	last := -1
+	for i, c := range p {
+		c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
+		e.tmp[3*i+0] = c1.R
+		e.tmp[3*i+1] = c1.G
+		e.tmp[3*i+2] = c1.B
+		if c1.A != 0xff {
+			last = i
+		}
+		e.tmp[3*256+i] = c1.A
+	}
+	e.writeChunk(e.tmp[:3*len(p)], "PLTE")
+	if last != -1 {
+		e.writeChunk(e.tmp[3*256:3*256+1+last], "tRNS")
+	}
+}
+
+// An encoder is an io.Writer that satisfies writes by writing PNG IDAT chunks,
+// including an 8-byte header and 4-byte CRC checksum per Write call. Such calls
+// should be relatively infrequent, since writeIDATs uses a bufio.Writer.
+//
+// This method should only be called from writeIDATs (via writeImage).
+// No other code should treat an encoder as an io.Writer.
+func (e *encoder) Write(b []byte) (int, error) {
+	e.writeChunk(b, "IDAT")
+	if e.err != nil {
+		return 0, e.err
+	}
+	return len(b), nil
+}
+
+// Chooses the filter to use for encoding the current row, and applies it.
+// The return value is the index of the filter and also of the row in cr that has had it applied.
+func filter(cr *[nFilter][]byte, pr []byte, bpp int) int {
+	// We try all five filter types, and pick the one that minimizes the sum of absolute differences.
+	// This is the same heuristic that libpng uses, although the filters are attempted in order of
+	// estimated most likely to be minimal (ftUp, ftPaeth, ftNone, ftSub, ftAverage), rather than
+	// in their enumeration order (ftNone, ftSub, ftUp, ftAverage, ftPaeth).
+	cdat0 := cr[0][1:]
+	cdat1 := cr[1][1:]
+	cdat2 := cr[2][1:]
+	cdat3 := cr[3][1:]
+	cdat4 := cr[4][1:]
+	pdat := pr[1:]
+	n := len(cdat0)
+
+	// The up filter.
+	sum := 0
+	for i := 0; i < n; i++ {
+		cdat2[i] = cdat0[i] - pdat[i]
+		sum += abs8(cdat2[i])
+	}
+	best := sum
+	filter := ftUp
+
+	// The Paeth filter.
+	sum = 0
+	for i := 0; i < bpp; i++ {
+		cdat4[i] = cdat0[i] - paeth(0, pdat[i], 0)
+		sum += abs8(cdat4[i])
+	}
+	for i := bpp; i < n; i++ {
+		cdat4[i] = cdat0[i] - paeth(cdat0[i-bpp], pdat[i], pdat[i-bpp])
+		sum += abs8(cdat4[i])
+		if sum >= best {
+			break
+		}
+	}
+	if sum < best {
+		best = sum
+		filter = ftPaeth
+	}
+
+	// The none filter.
+	sum = 0
+	for i := 0; i < n; i++ {
+		sum += abs8(cdat0[i])
+		if sum >= best {
+			break
+		}
+	}
+	if sum < best {
+		best = sum
+		filter = ftNone
+	}
+
+	// The sub filter.
+	sum = 0
+	for i := 0; i < bpp; i++ {
+		cdat1[i] = cdat0[i]
+		sum += abs8(cdat1[i])
+	}
+	for i := bpp; i < n; i++ {
+		cdat1[i] = cdat0[i] - cdat0[i-bpp]
+		sum += abs8(cdat1[i])
+		if sum >= best {
+			break
+		}
+	}
+	if sum < best {
+		best = sum
+		filter = ftSub
+	}
+
+	// The average filter.
+	sum = 0
+	for i := 0; i < bpp; i++ {
+		cdat3[i] = cdat0[i] - pdat[i]/2
+		sum += abs8(cdat3[i])
+	}
+	for i := bpp; i < n; i++ {
+		cdat3[i] = cdat0[i] - uint8((int(cdat0[i-bpp])+int(pdat[i]))/2)
+		sum += abs8(cdat3[i])
+		if sum >= best {
+			break
+		}
+	}
+	if sum < best {
+		best = sum
+		filter = ftAverage
+	}
+
+	return filter
+}
+
+func writeImage(w io.Writer, m image.Image, cb int) error {
+	zw := zlib.NewWriter(w)
+	defer zw.Close()
+
+	bpp := 0 // Bytes per pixel.
+
+	switch cb {
+	case cbG8:
+		bpp = 1
+	case cbTC8:
+		bpp = 3
+	case cbP8:
+		bpp = 1
+	case cbTCA8:
+		bpp = 4
+	case cbTC16:
+		bpp = 6
+	case cbTCA16:
+		bpp = 8
+	case cbG16:
+		bpp = 2
+	}
+	// cr[*] and pr are the bytes for the current and previous row.
+	// cr[0] is unfiltered (or equivalently, filtered with the ftNone filter).
+	// cr[ft], for non-zero filter types ft, are buffers for transforming cr[0] under the
+	// other PNG filter types. These buffers are allocated once and re-used for each row.
+	// The +1 is for the per-row filter type, which is at cr[*][0].
+	b := m.Bounds()
+	var cr [nFilter][]uint8
+	for i := range cr {
+		cr[i] = make([]uint8, 1+bpp*b.Dx())
+		cr[i][0] = uint8(i)
+	}
+	pr := make([]uint8, 1+bpp*b.Dx())
+
+	gray, _ := m.(*image.Gray)
+	rgba, _ := m.(*image.RGBA)
+	paletted, _ := m.(*image.Paletted)
+	nrgba, _ := m.(*image.NRGBA)
+
+	for y := b.Min.Y; y < b.Max.Y; y++ {
+		// Convert from colors to bytes.
+		i := 1
+		switch cb {
+		case cbG8:
+			if gray != nil {
+				offset := (y - b.Min.Y) * gray.Stride
+				copy(cr[0][1:], gray.Pix[offset:offset+b.Dx()])
+			} else {
+				for x := b.Min.X; x < b.Max.X; x++ {
+					c := color.GrayModel.Convert(m.At(x, y)).(color.Gray)
+					cr[0][i] = c.Y
+					i++
+				}
+			}
+		case cbTC8:
+			// We have previously verified that the alpha value is fully opaque.
+			cr0 := cr[0]
+			stride, pix := 0, []byte(nil)
+			if rgba != nil {
+				stride, pix = rgba.Stride, rgba.Pix
+			} else if nrgba != nil {
+				stride, pix = nrgba.Stride, nrgba.Pix
+			}
+			if stride != 0 {
+				j0 := (y - b.Min.Y) * stride
+				j1 := j0 + b.Dx()*4
+				for j := j0; j < j1; j += 4 {
+					cr0[i+0] = pix[j+0]
+					cr0[i+1] = pix[j+1]
+					cr0[i+2] = pix[j+2]
+					i += 3
+				}
+			} else {
+				for x := b.Min.X; x < b.Max.X; x++ {
+					r, g, b, _ := m.At(x, y).RGBA()
+					cr0[i+0] = uint8(r >> 8)
+					cr0[i+1] = uint8(g >> 8)
+					cr0[i+2] = uint8(b >> 8)
+					i += 3
+				}
+			}
+		case cbP8:
+			if paletted != nil {
+				offset := (y - b.Min.Y) * paletted.Stride
+				copy(cr[0][1:], paletted.Pix[offset:offset+b.Dx()])
+			} else {
+				pi := m.(image.PalettedImage)
+				for x := b.Min.X; x < b.Max.X; x++ {
+					cr[0][i] = pi.ColorIndexAt(x, y)
+					i += 1
+				}
+			}
+		case cbTCA8:
+			if nrgba != nil {
+				offset := (y - b.Min.Y) * nrgba.Stride
+				copy(cr[0][1:], nrgba.Pix[offset:offset+b.Dx()*4])
+			} else {
+				// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
+				for x := b.Min.X; x < b.Max.X; x++ {
+					c := color.NRGBAModel.Convert(m.At(x, y)).(color.NRGBA)
+					cr[0][i+0] = c.R
+					cr[0][i+1] = c.G
+					cr[0][i+2] = c.B
+					cr[0][i+3] = c.A
+					i += 4
+				}
+			}
+		case cbG16:
+			for x := b.Min.X; x < b.Max.X; x++ {
+				c := color.Gray16Model.Convert(m.At(x, y)).(color.Gray16)
+				cr[0][i+0] = uint8(c.Y >> 8)
+				cr[0][i+1] = uint8(c.Y)
+				i += 2
+			}
+		case cbTC16:
+			// We have previously verified that the alpha value is fully opaque.
+			for x := b.Min.X; x < b.Max.X; x++ {
+				r, g, b, _ := m.At(x, y).RGBA()
+				cr[0][i+0] = uint8(r >> 8)
+				cr[0][i+1] = uint8(r)
+				cr[0][i+2] = uint8(g >> 8)
+				cr[0][i+3] = uint8(g)
+				cr[0][i+4] = uint8(b >> 8)
+				cr[0][i+5] = uint8(b)
+				i += 6
+			}
+		case cbTCA16:
+			// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
+			for x := b.Min.X; x < b.Max.X; x++ {
+				c := color.NRGBA64Model.Convert(m.At(x, y)).(color.NRGBA64)
+				cr[0][i+0] = uint8(c.R >> 8)
+				cr[0][i+1] = uint8(c.R)
+				cr[0][i+2] = uint8(c.G >> 8)
+				cr[0][i+3] = uint8(c.G)
+				cr[0][i+4] = uint8(c.B >> 8)
+				cr[0][i+5] = uint8(c.B)
+				cr[0][i+6] = uint8(c.A >> 8)
+				cr[0][i+7] = uint8(c.A)
+				i += 8
+			}
+		}
+
+		// Apply the filter.
+		f := filter(&cr, pr, bpp)
+
+		// Write the compressed bytes.
+		if _, err := zw.Write(cr[f]); err != nil {
+			return err
+		}
+
+		// The current row for y is the previous row for y+1.
+		pr, cr[0] = cr[0], pr
+	}
+	return nil
+}
+
+// Write the actual image data to one or more IDAT chunks.
+func (e *encoder) writeIDATs() {
+	if e.err != nil {
+		return
+	}
+	var bw *bufio.Writer
+	bw = bufio.NewWriterSize(e, 1<<15)
+	e.err = writeImage(bw, e.m, e.cb)
+	if e.err != nil {
+		return
+	}
+	e.err = bw.Flush()
+}
+
+func (e *encoder) writeIEND() { e.writeChunk(nil, "IEND") }
+
+// Encode writes the Image m to w in PNG format. Any Image may be encoded, but
+// images that are not image.NRGBA might be encoded lossily.
+func Encode(w io.Writer, m image.Image) error {
+	// Obviously, negative widths and heights are invalid. Furthermore, the PNG
+	// spec section 11.2.2 says that zero is invalid. Excessively large images are
+	// also rejected.
+	mw, mh := int64(m.Bounds().Dx()), int64(m.Bounds().Dy())
+	if mw <= 0 || mh <= 0 || mw >= 1<<32 || mh >= 1<<32 {
+		return FormatError("invalid image size: " + strconv.FormatInt(mw, 10) + "x" + strconv.FormatInt(mh, 10))
+	}
+
+	var e encoder
+	e.w = w
+	e.m = m
+
+	var pal color.Palette
+	// cbP8 encoding needs PalettedImage's ColorIndexAt method.
+	if _, ok := m.(image.PalettedImage); ok {
+		pal, _ = m.ColorModel().(color.Palette)
+	}
+	if pal != nil {
+		e.cb = cbP8
+	} else {
+		switch m.ColorModel() {
+		case color.GrayModel:
+			e.cb = cbG8
+		case color.Gray16Model:
+			e.cb = cbG16
+		case color.RGBAModel, color.NRGBAModel, color.AlphaModel:
+			if opaque(m) {
+				e.cb = cbTC8
+			} else {
+				e.cb = cbTCA8
+			}
+		default:
+			if opaque(m) {
+				e.cb = cbTC16
+			} else {
+				e.cb = cbTCA16
+			}
+		}
+	}
+
+	_, e.err = io.WriteString(w, pngHeader)
+	e.writeIHDR()
+	if pal != nil {
+		e.writePLTEAndTRNS(pal)
+	}
+	e.writeIDATs()
+	e.writeIEND()
+	return e.err
+}
diff --git a/third_party/gofrontend/libgo/go/image/png/writer_test.go b/third_party/gofrontend/libgo/go/image/png/writer_test.go
new file mode 100644
index 0000000..3116fc9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/png/writer_test.go
@@ -0,0 +1,191 @@
+// 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 png
+
+import (
+	"bytes"
+	"fmt"
+	"image"
+	"image/color"
+	"io/ioutil"
+	"testing"
+)
+
+func diff(m0, m1 image.Image) error {
+	b0, b1 := m0.Bounds(), m1.Bounds()
+	if !b0.Size().Eq(b1.Size()) {
+		return fmt.Errorf("dimensions differ: %v vs %v", b0, b1)
+	}
+	dx := b1.Min.X - b0.Min.X
+	dy := b1.Min.Y - b0.Min.Y
+	for y := b0.Min.Y; y < b0.Max.Y; y++ {
+		for x := b0.Min.X; x < b0.Max.X; x++ {
+			c0 := m0.At(x, y)
+			c1 := m1.At(x+dx, y+dy)
+			r0, g0, b0, a0 := c0.RGBA()
+			r1, g1, b1, a1 := c1.RGBA()
+			if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 {
+				return fmt.Errorf("colors differ at (%d, %d): %v vs %v", x, y, c0, c1)
+			}
+		}
+	}
+	return nil
+}
+
+func encodeDecode(m image.Image) (image.Image, error) {
+	var b bytes.Buffer
+	err := Encode(&b, m)
+	if err != nil {
+		return nil, err
+	}
+	m, err = Decode(&b)
+	if err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+func TestWriter(t *testing.T) {
+	// The filenames variable is declared in reader_test.go.
+	names := filenames
+	if testing.Short() {
+		names = filenamesShort
+	}
+	for _, fn := range names {
+		qfn := "testdata/pngsuite/" + fn + ".png"
+		// Read the image.
+		m0, err := readPNG(qfn)
+		if err != nil {
+			t.Error(fn, err)
+			continue
+		}
+		// Read the image again, encode it, and decode it.
+		m1, err := readPNG(qfn)
+		if err != nil {
+			t.Error(fn, err)
+			return
+		}
+		m2, err := encodeDecode(m1)
+		if err != nil {
+			t.Error(fn, err)
+			return
+		}
+		// Compare the two.
+		err = diff(m0, m2)
+		if err != nil {
+			t.Error(fn, err)
+			continue
+		}
+	}
+}
+
+func TestSubImage(t *testing.T) {
+	m0 := image.NewRGBA(image.Rect(0, 0, 256, 256))
+	for y := 0; y < 256; y++ {
+		for x := 0; x < 256; x++ {
+			m0.Set(x, y, color.RGBA{uint8(x), uint8(y), 0, 255})
+		}
+	}
+	m0 = m0.SubImage(image.Rect(50, 30, 250, 130)).(*image.RGBA)
+	m1, err := encodeDecode(m0)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	err = diff(m0, m1)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+}
+
+func BenchmarkEncodeGray(b *testing.B) {
+	b.StopTimer()
+	img := image.NewGray(image.Rect(0, 0, 640, 480))
+	b.SetBytes(640 * 480 * 1)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img)
+	}
+}
+
+func BenchmarkEncodeNRGBOpaque(b *testing.B) {
+	b.StopTimer()
+	img := image.NewNRGBA(image.Rect(0, 0, 640, 480))
+	// Set all pixels to 0xFF alpha to force opaque mode.
+	bo := img.Bounds()
+	for y := bo.Min.Y; y < bo.Max.Y; y++ {
+		for x := bo.Min.X; x < bo.Max.X; x++ {
+			img.Set(x, y, color.NRGBA{0, 0, 0, 255})
+		}
+	}
+	if !img.Opaque() {
+		b.Fatal("expected image to be opaque")
+	}
+	b.SetBytes(640 * 480 * 4)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img)
+	}
+}
+
+func BenchmarkEncodeNRGBA(b *testing.B) {
+	b.StopTimer()
+	img := image.NewNRGBA(image.Rect(0, 0, 640, 480))
+	if img.Opaque() {
+		b.Fatal("expected image not to be opaque")
+	}
+	b.SetBytes(640 * 480 * 4)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img)
+	}
+}
+
+func BenchmarkEncodePaletted(b *testing.B) {
+	b.StopTimer()
+	img := image.NewPaletted(image.Rect(0, 0, 640, 480), color.Palette{
+		color.RGBA{0, 0, 0, 255},
+		color.RGBA{255, 255, 255, 255},
+	})
+	b.SetBytes(640 * 480 * 1)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img)
+	}
+}
+
+func BenchmarkEncodeRGBOpaque(b *testing.B) {
+	b.StopTimer()
+	img := image.NewRGBA(image.Rect(0, 0, 640, 480))
+	// Set all pixels to 0xFF alpha to force opaque mode.
+	bo := img.Bounds()
+	for y := bo.Min.Y; y < bo.Max.Y; y++ {
+		for x := bo.Min.X; x < bo.Max.X; x++ {
+			img.Set(x, y, color.RGBA{0, 0, 0, 255})
+		}
+	}
+	if !img.Opaque() {
+		b.Fatal("expected image to be opaque")
+	}
+	b.SetBytes(640 * 480 * 4)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img)
+	}
+}
+
+func BenchmarkEncodeRGBA(b *testing.B) {
+	b.StopTimer()
+	img := image.NewRGBA(image.Rect(0, 0, 640, 480))
+	if img.Opaque() {
+		b.Fatal("expected image not to be opaque")
+	}
+	b.SetBytes(640 * 480 * 4)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.5bpp.gif b/third_party/gofrontend/libgo/go/image/testdata/video-001.5bpp.gif
new file mode 100644
index 0000000..ce53104
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.5bpp.gif
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.gif b/third_party/gofrontend/libgo/go/image/testdata/video-001.gif
new file mode 100644
index 0000000..ca06af6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.gif
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.interlaced.gif b/third_party/gofrontend/libgo/go/image/testdata/video-001.interlaced.gif
new file mode 100644
index 0000000..590594e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.interlaced.gif
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.jpeg
new file mode 100644
index 0000000..1b87c93
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.png b/third_party/gofrontend/libgo/go/image/testdata/video-001.png
new file mode 100644
index 0000000..d3468bb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.progressive.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.progressive.jpeg
new file mode 100644
index 0000000..b8cae23
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.progressive.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.420.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.420.jpeg
new file mode 100644
index 0000000..83fb0f8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.420.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.420.progressive.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.420.progressive.jpeg
new file mode 100644
index 0000000..b048eb2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.420.progressive.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.422.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.422.jpeg
new file mode 100644
index 0000000..60fff4f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.422.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.422.progressive.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.422.progressive.jpeg
new file mode 100644
index 0000000..926d005
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.422.progressive.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.440.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.440.jpeg
new file mode 100644
index 0000000..32eeeae
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.440.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.440.progressive.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.440.progressive.jpeg
new file mode 100644
index 0000000..e641a3b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.440.progressive.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.444.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.444.jpeg
new file mode 100644
index 0000000..7d57433
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.444.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.444.progressive.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.444.progressive.jpeg
new file mode 100644
index 0000000..ff7d5f9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.q50.444.progressive.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.separate.dc.progression.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.separate.dc.progression.jpeg
new file mode 100644
index 0000000..107f0fa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.separate.dc.progression.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-001.separate.dc.progression.progressive.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-001.separate.dc.progression.progressive.jpeg
new file mode 100644
index 0000000..a1d493e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-001.separate.dc.progression.progressive.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.gif b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.gif
new file mode 100644
index 0000000..23350d6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.gif
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.jpeg
new file mode 100644
index 0000000..f9d6e5c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.png b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.png
new file mode 100644
index 0000000..0b0ee75
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.png
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.2x2.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.2x2.jpeg
new file mode 100644
index 0000000..630b615
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.2x2.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.2x2.progressive.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.2x2.progressive.jpeg
new file mode 100644
index 0000000..c6b9360
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.2x2.progressive.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.jpeg
new file mode 100644
index 0000000..c65b5a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.progressive.jpeg b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.progressive.jpeg
new file mode 100644
index 0000000..24b70e8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/testdata/video-005.gray.q50.progressive.jpeg
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/image/ycbcr.go b/third_party/gofrontend/libgo/go/image/ycbcr.go
new file mode 100644
index 0000000..5b73bef
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/ycbcr.go
@@ -0,0 +1,153 @@
+// 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.
+
+package image
+
+import (
+	"image/color"
+)
+
+// YCbCrSubsampleRatio is the chroma subsample ratio used in a YCbCr image.
+type YCbCrSubsampleRatio int
+
+const (
+	YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
+	YCbCrSubsampleRatio422
+	YCbCrSubsampleRatio420
+	YCbCrSubsampleRatio440
+)
+
+func (s YCbCrSubsampleRatio) String() string {
+	switch s {
+	case YCbCrSubsampleRatio444:
+		return "YCbCrSubsampleRatio444"
+	case YCbCrSubsampleRatio422:
+		return "YCbCrSubsampleRatio422"
+	case YCbCrSubsampleRatio420:
+		return "YCbCrSubsampleRatio420"
+	case YCbCrSubsampleRatio440:
+		return "YCbCrSubsampleRatio440"
+	}
+	return "YCbCrSubsampleRatioUnknown"
+}
+
+// YCbCr is an in-memory image of Y'CbCr colors. There is one Y sample per
+// pixel, but each Cb and Cr sample can span one or more pixels.
+// YStride is the Y slice index delta between vertically adjacent pixels.
+// CStride is the Cb and Cr slice index delta between vertically adjacent pixels
+// that map to separate chroma samples.
+// It is not an absolute requirement, but YStride and len(Y) are typically
+// multiples of 8, and:
+//	For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1.
+//	For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2.
+//	For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4.
+//	For 4:4:0, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/2.
+type YCbCr struct {
+	Y, Cb, Cr      []uint8
+	YStride        int
+	CStride        int
+	SubsampleRatio YCbCrSubsampleRatio
+	Rect           Rectangle
+}
+
+func (p *YCbCr) ColorModel() color.Model {
+	return color.YCbCrModel
+}
+
+func (p *YCbCr) Bounds() Rectangle {
+	return p.Rect
+}
+
+func (p *YCbCr) At(x, y int) color.Color {
+	if !(Point{x, y}.In(p.Rect)) {
+		return color.YCbCr{}
+	}
+	yi := p.YOffset(x, y)
+	ci := p.COffset(x, y)
+	return color.YCbCr{
+		p.Y[yi],
+		p.Cb[ci],
+		p.Cr[ci],
+	}
+}
+
+// YOffset returns the index of the first element of Y that corresponds to
+// the pixel at (x, y).
+func (p *YCbCr) YOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.YStride + (x - p.Rect.Min.X)
+}
+
+// COffset returns the index of the first element of Cb or Cr that corresponds
+// to the pixel at (x, y).
+func (p *YCbCr) COffset(x, y int) int {
+	switch p.SubsampleRatio {
+	case YCbCrSubsampleRatio422:
+		return (y-p.Rect.Min.Y)*p.CStride + (x/2 - p.Rect.Min.X/2)
+	case YCbCrSubsampleRatio420:
+		return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2)
+	case YCbCrSubsampleRatio440:
+		return (y/2-p.Rect.Min.Y/2)*p.CStride + (x - p.Rect.Min.X)
+	}
+	// Default to 4:4:4 subsampling.
+	return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *YCbCr) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &YCbCr{
+			SubsampleRatio: p.SubsampleRatio,
+		}
+	}
+	yi := p.YOffset(r.Min.X, r.Min.Y)
+	ci := p.COffset(r.Min.X, r.Min.Y)
+	return &YCbCr{
+		Y:              p.Y[yi:],
+		Cb:             p.Cb[ci:],
+		Cr:             p.Cr[ci:],
+		SubsampleRatio: p.SubsampleRatio,
+		YStride:        p.YStride,
+		CStride:        p.CStride,
+		Rect:           r,
+	}
+}
+
+func (p *YCbCr) Opaque() bool {
+	return true
+}
+
+// NewYCbCr returns a new YCbCr with the given bounds and subsample ratio.
+func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
+	w, h, cw, ch := r.Dx(), r.Dy(), 0, 0
+	switch subsampleRatio {
+	case YCbCrSubsampleRatio422:
+		cw = (r.Max.X+1)/2 - r.Min.X/2
+		ch = h
+	case YCbCrSubsampleRatio420:
+		cw = (r.Max.X+1)/2 - r.Min.X/2
+		ch = (r.Max.Y+1)/2 - r.Min.Y/2
+	case YCbCrSubsampleRatio440:
+		cw = w
+		ch = (r.Max.Y+1)/2 - r.Min.Y/2
+	default:
+		// Default to 4:4:4 subsampling.
+		cw = w
+		ch = h
+	}
+	b := make([]byte, w*h+2*cw*ch)
+	return &YCbCr{
+		Y:              b[:w*h],
+		Cb:             b[w*h+0*cw*ch : w*h+1*cw*ch],
+		Cr:             b[w*h+1*cw*ch : w*h+2*cw*ch],
+		SubsampleRatio: subsampleRatio,
+		YStride:        w,
+		CStride:        cw,
+		Rect:           r,
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/image/ycbcr_test.go b/third_party/gofrontend/libgo/go/image/ycbcr_test.go
new file mode 100644
index 0000000..a5f4482
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/image/ycbcr_test.go
@@ -0,0 +1,107 @@
+// 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 image
+
+import (
+	"image/color"
+	"testing"
+)
+
+func TestYCbCr(t *testing.T) {
+	rects := []Rectangle{
+		Rect(0, 0, 16, 16),
+		Rect(1, 0, 16, 16),
+		Rect(0, 1, 16, 16),
+		Rect(1, 1, 16, 16),
+		Rect(1, 1, 15, 16),
+		Rect(1, 1, 16, 15),
+		Rect(1, 1, 15, 15),
+		Rect(2, 3, 14, 15),
+		Rect(7, 0, 7, 16),
+		Rect(0, 8, 16, 8),
+		Rect(0, 0, 10, 11),
+		Rect(5, 6, 16, 16),
+		Rect(7, 7, 8, 8),
+		Rect(7, 8, 8, 9),
+		Rect(8, 7, 9, 8),
+		Rect(8, 8, 9, 9),
+		Rect(7, 7, 17, 17),
+		Rect(8, 8, 17, 17),
+		Rect(9, 9, 17, 17),
+		Rect(10, 10, 17, 17),
+	}
+	subsampleRatios := []YCbCrSubsampleRatio{
+		YCbCrSubsampleRatio444,
+		YCbCrSubsampleRatio422,
+		YCbCrSubsampleRatio420,
+		YCbCrSubsampleRatio440,
+	}
+	deltas := []Point{
+		Pt(0, 0),
+		Pt(1000, 1001),
+		Pt(5001, -400),
+		Pt(-701, -801),
+	}
+	for _, r := range rects {
+		for _, subsampleRatio := range subsampleRatios {
+			for _, delta := range deltas {
+				testYCbCr(t, r, subsampleRatio, delta)
+			}
+		}
+		if testing.Short() {
+			break
+		}
+	}
+}
+
+func testYCbCr(t *testing.T, r Rectangle, subsampleRatio YCbCrSubsampleRatio, delta Point) {
+	// Create a YCbCr image m, whose bounds are r translated by (delta.X, delta.Y).
+	r1 := r.Add(delta)
+	m := NewYCbCr(r1, subsampleRatio)
+
+	// Test that the image buffer is reasonably small even if (delta.X, delta.Y) is far from the origin.
+	if len(m.Y) > 100*100 {
+		t.Errorf("r=%v, subsampleRatio=%v, delta=%v: image buffer is too large",
+			r, subsampleRatio, delta)
+		return
+	}
+
+	// Initialize m's pixels. For 422 and 420 subsampling, some of the Cb and Cr elements
+	// will be set multiple times. That's OK. We just want to avoid a uniform image.
+	for y := r1.Min.Y; y < r1.Max.Y; y++ {
+		for x := r1.Min.X; x < r1.Max.X; x++ {
+			yi := m.YOffset(x, y)
+			ci := m.COffset(x, y)
+			m.Y[yi] = uint8(16*y + x)
+			m.Cb[ci] = uint8(y + 16*x)
+			m.Cr[ci] = uint8(y + 16*x)
+		}
+	}
+
+	// Make various sub-images of m.
+	for y0 := delta.Y + 3; y0 < delta.Y+7; y0++ {
+		for y1 := delta.Y + 8; y1 < delta.Y+13; y1++ {
+			for x0 := delta.X + 3; x0 < delta.X+7; x0++ {
+				for x1 := delta.X + 8; x1 < delta.X+13; x1++ {
+					subRect := Rect(x0, y0, x1, y1)
+					sub := m.SubImage(subRect).(*YCbCr)
+
+					// For each point in the sub-image's bounds, check that m.At(x, y) equals sub.At(x, y).
+					for y := sub.Rect.Min.Y; y < sub.Rect.Max.Y; y++ {
+						for x := sub.Rect.Min.X; x < sub.Rect.Max.X; x++ {
+							color0 := m.At(x, y).(color.YCbCr)
+							color1 := sub.At(x, y).(color.YCbCr)
+							if color0 != color1 {
+								t.Errorf("r=%v, subsampleRatio=%v, delta=%v, x=%d, y=%d, color0=%v, color1=%v",
+									r, subsampleRatio, delta, x, y, color0, color1)
+								return
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/index/suffixarray/qsufsort.go b/third_party/gofrontend/libgo/go/index/suffixarray/qsufsort.go
new file mode 100644
index 0000000..9c36a98
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/index/suffixarray/qsufsort.go
@@ -0,0 +1,168 @@
+// 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.
+
+// This algorithm is based on "Faster Suffix Sorting"
+//   by N. Jesper Larsson and Kunihiko Sadakane
+// paper: http://www.larsson.dogma.net/ssrev-tr.pdf
+// code:  http://www.larsson.dogma.net/qsufsort.c
+
+// This algorithm computes the suffix array sa by computing its inverse.
+// Consecutive groups of suffixes in sa are labeled as sorted groups or
+// unsorted groups. For a given pass of the sorter, all suffixes are ordered
+// up to their first h characters, and sa is h-ordered. Suffixes in their
+// final positions and unambiguously sorted in h-order are in a sorted group.
+// Consecutive groups of suffixes with identical first h characters are an
+// unsorted group. In each pass of the algorithm, unsorted groups are sorted
+// according to the group number of their following suffix.
+
+// In the implementation, if sa[i] is negative, it indicates that i is
+// the first element of a sorted group of length -sa[i], and can be skipped.
+// An unsorted group sa[i:k] is given the group number of the index of its
+// last element, k-1. The group numbers are stored in the inverse slice (inv),
+// and when all groups are sorted, this slice is the inverse suffix array.
+
+package suffixarray
+
+import "sort"
+
+func qsufsort(data []byte) []int {
+	// initial sorting by first byte of suffix
+	sa := sortedByFirstByte(data)
+	if len(sa) < 2 {
+		return sa
+	}
+	// initialize the group lookup table
+	// this becomes the inverse of the suffix array when all groups are sorted
+	inv := initGroups(sa, data)
+
+	// the index starts 1-ordered
+	sufSortable := &suffixSortable{sa: sa, inv: inv, h: 1}
+
+	for sa[0] > -len(sa) { // until all suffixes are one big sorted group
+		// The suffixes are h-ordered, make them 2*h-ordered
+		pi := 0 // pi is first position of first group
+		sl := 0 // sl is negated length of sorted groups
+		for pi < len(sa) {
+			if s := sa[pi]; s < 0 { // if pi starts sorted group
+				pi -= s // skip over sorted group
+				sl += s // add negated length to sl
+			} else { // if pi starts unsorted group
+				if sl != 0 {
+					sa[pi+sl] = sl // combine sorted groups before pi
+					sl = 0
+				}
+				pk := inv[s] + 1 // pk-1 is last position of unsorted group
+				sufSortable.sa = sa[pi:pk]
+				sort.Sort(sufSortable)
+				sufSortable.updateGroups(pi)
+				pi = pk // next group
+			}
+		}
+		if sl != 0 { // if the array ends with a sorted group
+			sa[pi+sl] = sl // combine sorted groups at end of sa
+		}
+
+		sufSortable.h *= 2 // double sorted depth
+	}
+
+	for i := range sa { // reconstruct suffix array from inverse
+		sa[inv[i]] = i
+	}
+	return sa
+}
+
+func sortedByFirstByte(data []byte) []int {
+	// total byte counts
+	var count [256]int
+	for _, b := range data {
+		count[b]++
+	}
+	// make count[b] equal index of first occurrence of b in sorted array
+	sum := 0
+	for b := range count {
+		count[b], sum = sum, count[b]+sum
+	}
+	// iterate through bytes, placing index into the correct spot in sa
+	sa := make([]int, len(data))
+	for i, b := range data {
+		sa[count[b]] = i
+		count[b]++
+	}
+	return sa
+}
+
+func initGroups(sa []int, data []byte) []int {
+	// label contiguous same-letter groups with the same group number
+	inv := make([]int, len(data))
+	prevGroup := len(sa) - 1
+	groupByte := data[sa[prevGroup]]
+	for i := len(sa) - 1; i >= 0; i-- {
+		if b := data[sa[i]]; b < groupByte {
+			if prevGroup == i+1 {
+				sa[i+1] = -1
+			}
+			groupByte = b
+			prevGroup = i
+		}
+		inv[sa[i]] = prevGroup
+		if prevGroup == 0 {
+			sa[0] = -1
+		}
+	}
+	// Separate out the final suffix to the start of its group.
+	// This is necessary to ensure the suffix "a" is before "aba"
+	// when using a potentially unstable sort.
+	lastByte := data[len(data)-1]
+	s := -1
+	for i := range sa {
+		if sa[i] >= 0 {
+			if data[sa[i]] == lastByte && s == -1 {
+				s = i
+			}
+			if sa[i] == len(sa)-1 {
+				sa[i], sa[s] = sa[s], sa[i]
+				inv[sa[s]] = s
+				sa[s] = -1 // mark it as an isolated sorted group
+				break
+			}
+		}
+	}
+	return inv
+}
+
+type suffixSortable struct {
+	sa  []int
+	inv []int
+	h   int
+	buf []int // common scratch space
+}
+
+func (x *suffixSortable) Len() int           { return len(x.sa) }
+func (x *suffixSortable) Less(i, j int) bool { return x.inv[x.sa[i]+x.h] < x.inv[x.sa[j]+x.h] }
+func (x *suffixSortable) Swap(i, j int)      { x.sa[i], x.sa[j] = x.sa[j], x.sa[i] }
+
+func (x *suffixSortable) updateGroups(offset int) {
+	bounds := x.buf[0:0]
+	group := x.inv[x.sa[0]+x.h]
+	for i := 1; i < len(x.sa); i++ {
+		if g := x.inv[x.sa[i]+x.h]; g > group {
+			bounds = append(bounds, i)
+			group = g
+		}
+	}
+	bounds = append(bounds, len(x.sa))
+	x.buf = bounds
+
+	// update the group numberings after all new groups are determined
+	prev := 0
+	for _, b := range bounds {
+		for i := prev; i < b; i++ {
+			x.inv[x.sa[i]] = offset + b - 1
+		}
+		if b-prev == 1 {
+			x.sa[prev] = -1
+		}
+		prev = b
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/index/suffixarray/suffixarray.go b/third_party/gofrontend/libgo/go/index/suffixarray/suffixarray.go
new file mode 100644
index 0000000..c59ae6e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/index/suffixarray/suffixarray.go
@@ -0,0 +1,307 @@
+// Copyright 2010 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 suffixarray implements substring search in logarithmic time using
+// an in-memory suffix array.
+//
+// Example use:
+//
+//	// create index for some data
+//	index := suffixarray.New(data)
+//
+//	// lookup byte slice s
+//	offsets1 := index.Lookup(s, -1) // the list of all indices where s occurs in data
+//	offsets2 := index.Lookup(s, 3)  // the list of at most 3 indices where s occurs in data
+//
+package suffixarray
+
+import (
+	"bytes"
+	"encoding/binary"
+	"io"
+	"regexp"
+	"sort"
+)
+
+// Index implements a suffix array for fast substring search.
+type Index struct {
+	data []byte
+	sa   []int // suffix array for data; len(sa) == len(data)
+}
+
+// New creates a new Index for data.
+// Index creation time is O(N*log(N)) for N = len(data).
+func New(data []byte) *Index {
+	return &Index{data, qsufsort(data)}
+}
+
+// writeInt writes an int x to w using buf to buffer the write.
+func writeInt(w io.Writer, buf []byte, x int) error {
+	binary.PutVarint(buf, int64(x))
+	_, err := w.Write(buf[0:binary.MaxVarintLen64])
+	return err
+}
+
+// readInt reads an int x from r using buf to buffer the read and returns x.
+func readInt(r io.Reader, buf []byte) (int, error) {
+	_, err := io.ReadFull(r, buf[0:binary.MaxVarintLen64]) // ok to continue with error
+	x, _ := binary.Varint(buf)
+	return int(x), err
+}
+
+// writeSlice writes data[:n] to w and returns n.
+// It uses buf to buffer the write.
+func writeSlice(w io.Writer, buf []byte, data []int) (n int, err error) {
+	// encode as many elements as fit into buf
+	p := binary.MaxVarintLen64
+	for ; n < len(data) && p+binary.MaxVarintLen64 <= len(buf); n++ {
+		p += binary.PutUvarint(buf[p:], uint64(data[n]))
+	}
+
+	// update buffer size
+	binary.PutVarint(buf, int64(p))
+
+	// write buffer
+	_, err = w.Write(buf[0:p])
+	return
+}
+
+// readSlice reads data[:n] from r and returns n.
+// It uses buf to buffer the read.
+func readSlice(r io.Reader, buf []byte, data []int) (n int, err error) {
+	// read buffer size
+	var size int
+	size, err = readInt(r, buf)
+	if err != nil {
+		return
+	}
+
+	// read buffer w/o the size
+	if _, err = io.ReadFull(r, buf[binary.MaxVarintLen64:size]); err != nil {
+		return
+	}
+
+	// decode as many elements as present in buf
+	for p := binary.MaxVarintLen64; p < size; n++ {
+		x, w := binary.Uvarint(buf[p:])
+		data[n] = int(x)
+		p += w
+	}
+
+	return
+}
+
+const bufSize = 16 << 10 // reasonable for BenchmarkSaveRestore
+
+// Read reads the index from r into x; x must not be nil.
+func (x *Index) Read(r io.Reader) error {
+	// buffer for all reads
+	buf := make([]byte, bufSize)
+
+	// read length
+	n, err := readInt(r, buf)
+	if err != nil {
+		return err
+	}
+
+	// allocate space
+	if 2*n < cap(x.data) || cap(x.data) < n {
+		// new data is significantly smaller or larger then
+		// existing buffers - allocate new ones
+		x.data = make([]byte, n)
+		x.sa = make([]int, n)
+	} else {
+		// re-use existing buffers
+		x.data = x.data[0:n]
+		x.sa = x.sa[0:n]
+	}
+
+	// read data
+	if _, err := io.ReadFull(r, x.data); err != nil {
+		return err
+	}
+
+	// read index
+	for sa := x.sa; len(sa) > 0; {
+		n, err := readSlice(r, buf, sa)
+		if err != nil {
+			return err
+		}
+		sa = sa[n:]
+	}
+	return nil
+}
+
+// Write writes the index x to w.
+func (x *Index) Write(w io.Writer) error {
+	// buffer for all writes
+	buf := make([]byte, bufSize)
+
+	// write length
+	if err := writeInt(w, buf, len(x.data)); err != nil {
+		return err
+	}
+
+	// write data
+	if _, err := w.Write(x.data); err != nil {
+		return err
+	}
+
+	// write index
+	for sa := x.sa; len(sa) > 0; {
+		n, err := writeSlice(w, buf, sa)
+		if err != nil {
+			return err
+		}
+		sa = sa[n:]
+	}
+	return nil
+}
+
+// Bytes returns the data over which the index was created.
+// It must not be modified.
+//
+func (x *Index) Bytes() []byte {
+	return x.data
+}
+
+func (x *Index) at(i int) []byte {
+	return x.data[x.sa[i]:]
+}
+
+// lookupAll returns a slice into the matching region of the index.
+// The runtime is O(log(N)*len(s)).
+func (x *Index) lookupAll(s []byte) []int {
+	// find matching suffix index range [i:j]
+	// find the first index where s would be the prefix
+	i := sort.Search(len(x.sa), func(i int) bool { return bytes.Compare(x.at(i), s) >= 0 })
+	// starting at i, find the first index at which s is not a prefix
+	j := i + sort.Search(len(x.sa)-i, func(j int) bool { return !bytes.HasPrefix(x.at(j+i), s) })
+	return x.sa[i:j]
+}
+
+// Lookup returns an unsorted list of at most n indices where the byte string s
+// occurs in the indexed data. If n < 0, all occurrences are returned.
+// The result is nil if s is empty, s is not found, or n == 0.
+// Lookup time is O(log(N)*len(s) + len(result)) where N is the
+// size of the indexed data.
+//
+func (x *Index) Lookup(s []byte, n int) (result []int) {
+	if len(s) > 0 && n != 0 {
+		matches := x.lookupAll(s)
+		if n < 0 || len(matches) < n {
+			n = len(matches)
+		}
+		// 0 <= n <= len(matches)
+		if n > 0 {
+			result = make([]int, n)
+			copy(result, matches)
+		}
+	}
+	return
+}
+
+// FindAllIndex returns a sorted list of non-overlapping matches of the
+// regular expression r, where a match is a pair of indices specifying
+// the matched slice of x.Bytes(). If n < 0, all matches are returned
+// in successive order. Otherwise, at most n matches are returned and
+// they may not be successive. The result is nil if there are no matches,
+// or if n == 0.
+//
+func (x *Index) FindAllIndex(r *regexp.Regexp, n int) (result [][]int) {
+	// a non-empty literal prefix is used to determine possible
+	// match start indices with Lookup
+	prefix, complete := r.LiteralPrefix()
+	lit := []byte(prefix)
+
+	// worst-case scenario: no literal prefix
+	if prefix == "" {
+		return r.FindAllIndex(x.data, n)
+	}
+
+	// if regexp is a literal just use Lookup and convert its
+	// result into match pairs
+	if complete {
+		// Lookup returns indices that may belong to overlapping matches.
+		// After eliminating them, we may end up with fewer than n matches.
+		// If we don't have enough at the end, redo the search with an
+		// increased value n1, but only if Lookup returned all the requested
+		// indices in the first place (if it returned fewer than that then
+		// there cannot be more).
+		for n1 := n; ; n1 += 2 * (n - len(result)) /* overflow ok */ {
+			indices := x.Lookup(lit, n1)
+			if len(indices) == 0 {
+				return
+			}
+			sort.Ints(indices)
+			pairs := make([]int, 2*len(indices))
+			result = make([][]int, len(indices))
+			count := 0
+			prev := 0
+			for _, i := range indices {
+				if count == n {
+					break
+				}
+				// ignore indices leading to overlapping matches
+				if prev <= i {
+					j := 2 * count
+					pairs[j+0] = i
+					pairs[j+1] = i + len(lit)
+					result[count] = pairs[j : j+2]
+					count++
+					prev = i + len(lit)
+				}
+			}
+			result = result[0:count]
+			if len(result) >= n || len(indices) != n1 {
+				// found all matches or there's no chance to find more
+				// (n and n1 can be negative)
+				break
+			}
+		}
+		if len(result) == 0 {
+			result = nil
+		}
+		return
+	}
+
+	// regexp has a non-empty literal prefix; Lookup(lit) computes
+	// the indices of possible complete matches; use these as starting
+	// points for anchored searches
+	// (regexp "^" matches beginning of input, not beginning of line)
+	r = regexp.MustCompile("^" + r.String()) // compiles because r compiled
+
+	// same comment about Lookup applies here as in the loop above
+	for n1 := n; ; n1 += 2 * (n - len(result)) /* overflow ok */ {
+		indices := x.Lookup(lit, n1)
+		if len(indices) == 0 {
+			return
+		}
+		sort.Ints(indices)
+		result = result[0:0]
+		prev := 0
+		for _, i := range indices {
+			if len(result) == n {
+				break
+			}
+			m := r.FindIndex(x.data[i:]) // anchored search - will not run off
+			// ignore indices leading to overlapping matches
+			if m != nil && prev <= i {
+				m[0] = i // correct m
+				m[1] += i
+				result = append(result, m)
+				prev = m[1]
+			}
+		}
+		if len(result) >= n || len(indices) != n1 {
+			// found all matches or there's no chance to find more
+			// (n and n1 can be negative)
+			break
+		}
+	}
+	if len(result) == 0 {
+		result = nil
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/index/suffixarray/suffixarray_test.go b/third_party/gofrontend/libgo/go/index/suffixarray/suffixarray_test.go
new file mode 100644
index 0000000..df3e449
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/index/suffixarray/suffixarray_test.go
@@ -0,0 +1,304 @@
+// Copyright 2010 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 suffixarray
+
+import (
+	"bytes"
+	"math/rand"
+	"regexp"
+	"sort"
+	"strings"
+	"testing"
+)
+
+type testCase struct {
+	name     string   // name of test case
+	source   string   // source to index
+	patterns []string // patterns to lookup
+}
+
+var testCases = []testCase{
+	{
+		"empty string",
+		"",
+		[]string{
+			"",
+			"foo",
+			"(foo)",
+			".*",
+			"a*",
+		},
+	},
+
+	{
+		"all a's",
+		"aaaaaaaaaa", // 10 a's
+		[]string{
+			"",
+			"a",
+			"aa",
+			"aaa",
+			"aaaa",
+			"aaaaa",
+			"aaaaaa",
+			"aaaaaaa",
+			"aaaaaaaa",
+			"aaaaaaaaa",
+			"aaaaaaaaaa",
+			"aaaaaaaaaaa", // 11 a's
+			".",
+			".*",
+			"a+",
+			"aa+",
+			"aaaa[b]?",
+			"aaa*",
+		},
+	},
+
+	{
+		"abc",
+		"abc",
+		[]string{
+			"a",
+			"b",
+			"c",
+			"ab",
+			"bc",
+			"abc",
+			"a.c",
+			"a(b|c)",
+			"abc?",
+		},
+	},
+
+	{
+		"barbara*3",
+		"barbarabarbarabarbara",
+		[]string{
+			"a",
+			"bar",
+			"rab",
+			"arab",
+			"barbar",
+			"bara?bar",
+		},
+	},
+
+	{
+		"typing drill",
+		"Now is the time for all good men to come to the aid of their country.",
+		[]string{
+			"Now",
+			"the time",
+			"to come the aid",
+			"is the time for all good men to come to the aid of their",
+			"to (come|the)?",
+		},
+	},
+
+	{
+		"godoc simulation",
+		"package main\n\nimport(\n    \"rand\"\n    ",
+		[]string{},
+	},
+}
+
+// find all occurrences of s in source; report at most n occurrences
+func find(src, s string, n int) []int {
+	var res []int
+	if s != "" && n != 0 {
+		// find at most n occurrences of s in src
+		for i := -1; n < 0 || len(res) < n; {
+			j := strings.Index(src[i+1:], s)
+			if j < 0 {
+				break
+			}
+			i += j + 1
+			res = append(res, i)
+		}
+	}
+	return res
+}
+
+func testLookup(t *testing.T, tc *testCase, x *Index, s string, n int) {
+	res := x.Lookup([]byte(s), n)
+	exp := find(tc.source, s, n)
+
+	// check that the lengths match
+	if len(res) != len(exp) {
+		t.Errorf("test %q, lookup %q (n = %d): expected %d results; got %d", tc.name, s, n, len(exp), len(res))
+	}
+
+	// if n >= 0 the number of results is limited --- unless n >= all results,
+	// we may obtain different positions from the Index and from find (because
+	// Index may not find the results in the same order as find) => in general
+	// we cannot simply check that the res and exp lists are equal
+
+	// check that each result is in fact a correct match and there are no duplicates
+	sort.Ints(res)
+	for i, r := range res {
+		if r < 0 || len(tc.source) <= r {
+			t.Errorf("test %q, lookup %q, result %d (n = %d): index %d out of range [0, %d[", tc.name, s, i, n, r, len(tc.source))
+		} else if !strings.HasPrefix(tc.source[r:], s) {
+			t.Errorf("test %q, lookup %q, result %d (n = %d): index %d not a match", tc.name, s, i, n, r)
+		}
+		if i > 0 && res[i-1] == r {
+			t.Errorf("test %q, lookup %q, result %d (n = %d): found duplicate index %d", tc.name, s, i, n, r)
+		}
+	}
+
+	if n < 0 {
+		// all results computed - sorted res and exp must be equal
+		for i, r := range res {
+			e := exp[i]
+			if r != e {
+				t.Errorf("test %q, lookup %q, result %d: expected index %d; got %d", tc.name, s, i, e, r)
+			}
+		}
+	}
+}
+
+func testFindAllIndex(t *testing.T, tc *testCase, x *Index, rx *regexp.Regexp, n int) {
+	res := x.FindAllIndex(rx, n)
+	exp := rx.FindAllStringIndex(tc.source, n)
+
+	// check that the lengths match
+	if len(res) != len(exp) {
+		t.Errorf("test %q, FindAllIndex %q (n = %d): expected %d results; got %d", tc.name, rx, n, len(exp), len(res))
+	}
+
+	// if n >= 0 the number of results is limited --- unless n >= all results,
+	// we may obtain different positions from the Index and from regexp (because
+	// Index may not find the results in the same order as regexp) => in general
+	// we cannot simply check that the res and exp lists are equal
+
+	// check that each result is in fact a correct match and the result is sorted
+	for i, r := range res {
+		if r[0] < 0 || r[0] > r[1] || len(tc.source) < r[1] {
+			t.Errorf("test %q, FindAllIndex %q, result %d (n == %d): illegal match [%d, %d]", tc.name, rx, i, n, r[0], r[1])
+		} else if !rx.MatchString(tc.source[r[0]:r[1]]) {
+			t.Errorf("test %q, FindAllIndex %q, result %d (n = %d): [%d, %d] not a match", tc.name, rx, i, n, r[0], r[1])
+		}
+	}
+
+	if n < 0 {
+		// all results computed - sorted res and exp must be equal
+		for i, r := range res {
+			e := exp[i]
+			if r[0] != e[0] || r[1] != e[1] {
+				t.Errorf("test %q, FindAllIndex %q, result %d: expected match [%d, %d]; got [%d, %d]",
+					tc.name, rx, i, e[0], e[1], r[0], r[1])
+			}
+		}
+	}
+}
+
+func testLookups(t *testing.T, tc *testCase, x *Index, n int) {
+	for _, pat := range tc.patterns {
+		testLookup(t, tc, x, pat, n)
+		if rx, err := regexp.Compile(pat); err == nil {
+			testFindAllIndex(t, tc, x, rx, n)
+		}
+	}
+}
+
+// index is used to hide the sort.Interface
+type index Index
+
+func (x *index) Len() int           { return len(x.sa) }
+func (x *index) Less(i, j int) bool { return bytes.Compare(x.at(i), x.at(j)) < 0 }
+func (x *index) Swap(i, j int)      { x.sa[i], x.sa[j] = x.sa[j], x.sa[i] }
+func (a *index) at(i int) []byte    { return a.data[a.sa[i]:] }
+
+func testConstruction(t *testing.T, tc *testCase, x *Index) {
+	if !sort.IsSorted((*index)(x)) {
+		t.Errorf("failed testConstruction %s", tc.name)
+	}
+}
+
+func equal(x, y *Index) bool {
+	if !bytes.Equal(x.data, y.data) {
+		return false
+	}
+	for i, j := range x.sa {
+		if j != y.sa[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// returns the serialized index size
+func testSaveRestore(t *testing.T, tc *testCase, x *Index) int {
+	var buf bytes.Buffer
+	if err := x.Write(&buf); err != nil {
+		t.Errorf("failed writing index %s (%s)", tc.name, err)
+	}
+	size := buf.Len()
+	var y Index
+	if err := y.Read(&buf); err != nil {
+		t.Errorf("failed reading index %s (%s)", tc.name, err)
+	}
+	if !equal(x, &y) {
+		t.Errorf("restored index doesn't match saved index %s", tc.name)
+	}
+	return size
+}
+
+func TestIndex(t *testing.T) {
+	for _, tc := range testCases {
+		x := New([]byte(tc.source))
+		testConstruction(t, &tc, x)
+		testSaveRestore(t, &tc, x)
+		testLookups(t, &tc, x, 0)
+		testLookups(t, &tc, x, 1)
+		testLookups(t, &tc, x, 10)
+		testLookups(t, &tc, x, 2e9)
+		testLookups(t, &tc, x, -1)
+	}
+}
+
+// Of all possible inputs, the random bytes have the least amount of substring
+// repetition, and the repeated bytes have the most. For most algorithms,
+// the running time of every input will be between these two.
+func benchmarkNew(b *testing.B, random bool) {
+	b.StopTimer()
+	data := make([]byte, 1e6)
+	if random {
+		for i := range data {
+			data[i] = byte(rand.Intn(256))
+		}
+	}
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		New(data)
+	}
+}
+
+func BenchmarkNewIndexRandom(b *testing.B) {
+	benchmarkNew(b, true)
+}
+func BenchmarkNewIndexRepeat(b *testing.B) {
+	benchmarkNew(b, false)
+}
+
+func BenchmarkSaveRestore(b *testing.B) {
+	b.StopTimer()
+	r := rand.New(rand.NewSource(0x5a77a1)) // guarantee always same sequence
+	data := make([]byte, 10<<20)            // 10MB of data to index
+	for i := range data {
+		data[i] = byte(r.Intn(256))
+	}
+	x := New(data)
+	size := testSaveRestore(nil, nil, x)       // verify correctness
+	buf := bytes.NewBuffer(make([]byte, size)) // avoid growing
+	b.SetBytes(int64(size))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		x.Write(buf)
+		var y Index
+		y.Read(buf)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/io/io.go b/third_party/gofrontend/libgo/go/io/io.go
new file mode 100644
index 0000000..022fdb6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/io/io.go
@@ -0,0 +1,493 @@
+// 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 io provides basic interfaces to I/O primitives.
+// Its primary job is to wrap existing implementations of such primitives,
+// such as those in package os, into shared public interfaces that
+// abstract the functionality, plus some other related primitives.
+//
+// Because these interfaces and primitives wrap lower-level operations with
+// various implementations, unless otherwise informed clients should not
+// assume they are safe for parallel execution.
+package io
+
+import (
+	"errors"
+)
+
+// ErrShortWrite means that a write accepted fewer bytes than requested
+// but failed to return an explicit error.
+var ErrShortWrite = errors.New("short write")
+
+// ErrShortBuffer means that a read required a longer buffer than was provided.
+var ErrShortBuffer = errors.New("short buffer")
+
+// EOF is the error returned by Read when no more input is available.
+// Functions should return EOF only to signal a graceful end of input.
+// If the EOF occurs unexpectedly in a structured data stream,
+// the appropriate error is either ErrUnexpectedEOF or some other error
+// giving more detail.
+var EOF = errors.New("EOF")
+
+// ErrUnexpectedEOF means that EOF was encountered in the
+// middle of reading a fixed-size block or data structure.
+var ErrUnexpectedEOF = errors.New("unexpected EOF")
+
+// ErrNoProgress is returned by some clients of an io.Reader when
+// many calls to Read have failed to return any data or error,
+// usually the sign of a broken io.Reader implementation.
+var ErrNoProgress = errors.New("multiple Read calls return no data or error")
+
+// Reader is the interface that wraps the basic Read method.
+//
+// Read reads up to len(p) bytes into p.  It returns the number of bytes
+// read (0 <= n <= len(p)) and any error encountered.  Even if Read
+// returns n < len(p), it may use all of p as scratch space during the call.
+// If some data is available but not len(p) bytes, Read conventionally
+// returns what is available instead of waiting for more.
+//
+// When Read encounters an error or end-of-file condition after
+// successfully reading n > 0 bytes, it returns the number of
+// bytes read.  It may return the (non-nil) error from the same call
+// or return the error (and n == 0) from a subsequent call.
+// An instance of this general case is that a Reader returning
+// a non-zero number of bytes at the end of the input stream may
+// return either err == EOF or err == nil.  The next Read should
+// return 0, EOF regardless.
+//
+// Callers should always process the n > 0 bytes returned before
+// considering the error err.  Doing so correctly handles I/O errors
+// that happen after reading some bytes and also both of the
+// allowed EOF behaviors.
+//
+// Implementations of Read are discouraged from returning a
+// zero byte count with a nil error, and callers should treat
+// that situation as a no-op.
+type Reader interface {
+	Read(p []byte) (n int, err error)
+}
+
+// Writer is the interface that wraps the basic Write method.
+//
+// Write writes len(p) bytes from p to the underlying data stream.
+// It returns the number of bytes written from p (0 <= n <= len(p))
+// and any error encountered that caused the write to stop early.
+// Write must return a non-nil error if it returns n < len(p).
+// Write must not modify the slice data, even temporarily.
+type Writer interface {
+	Write(p []byte) (n int, err error)
+}
+
+// Closer is the interface that wraps the basic Close method.
+//
+// The behavior of Close after the first call is undefined.
+// Specific implementations may document their own behavior.
+type Closer interface {
+	Close() error
+}
+
+// Seeker is the interface that wraps the basic Seek method.
+//
+// Seek sets the offset for the next Read or Write to offset,
+// interpreted according to whence: 0 means relative to the origin of
+// the file, 1 means relative to the current offset, and 2 means
+// relative to the end.  Seek returns the new offset and an error, if
+// any.
+//
+// Seeking to a negative offset is an error. Seeking to any positive
+// offset is legal, but the behavior of subsequent I/O operations on
+// the underlying object is implementation-dependent.
+type Seeker interface {
+	Seek(offset int64, whence int) (int64, error)
+}
+
+// ReadWriter is the interface that groups the basic Read and Write methods.
+type ReadWriter interface {
+	Reader
+	Writer
+}
+
+// ReadCloser is the interface that groups the basic Read and Close methods.
+type ReadCloser interface {
+	Reader
+	Closer
+}
+
+// WriteCloser is the interface that groups the basic Write and Close methods.
+type WriteCloser interface {
+	Writer
+	Closer
+}
+
+// ReadWriteCloser is the interface that groups the basic Read, Write and Close methods.
+type ReadWriteCloser interface {
+	Reader
+	Writer
+	Closer
+}
+
+// ReadSeeker is the interface that groups the basic Read and Seek methods.
+type ReadSeeker interface {
+	Reader
+	Seeker
+}
+
+// WriteSeeker is the interface that groups the basic Write and Seek methods.
+type WriteSeeker interface {
+	Writer
+	Seeker
+}
+
+// ReadWriteSeeker is the interface that groups the basic Read, Write and Seek methods.
+type ReadWriteSeeker interface {
+	Reader
+	Writer
+	Seeker
+}
+
+// ReaderFrom is the interface that wraps the ReadFrom method.
+//
+// ReadFrom reads data from r until EOF or error.
+// The return value n is the number of bytes read.
+// Any error except io.EOF encountered during the read is also returned.
+//
+// The Copy function uses ReaderFrom if available.
+type ReaderFrom interface {
+	ReadFrom(r Reader) (n int64, err error)
+}
+
+// WriterTo is the interface that wraps the WriteTo method.
+//
+// WriteTo writes data to w until there's no more data to write or
+// when an error occurs. The return value n is the number of bytes
+// written. Any error encountered during the write is also returned.
+//
+// The Copy function uses WriterTo if available.
+type WriterTo interface {
+	WriteTo(w Writer) (n int64, err error)
+}
+
+// ReaderAt is the interface that wraps the basic ReadAt method.
+//
+// ReadAt reads len(p) bytes into p starting at offset off in the
+// underlying input source.  It returns the number of bytes
+// read (0 <= n <= len(p)) and any error encountered.
+//
+// When ReadAt returns n < len(p), it returns a non-nil error
+// explaining why more bytes were not returned.  In this respect,
+// ReadAt is stricter than Read.
+//
+// Even if ReadAt returns n < len(p), it may use all of p as scratch
+// space during the call.  If some data is available but not len(p) bytes,
+// ReadAt blocks until either all the data is available or an error occurs.
+// In this respect ReadAt is different from Read.
+//
+// If the n = len(p) bytes returned by ReadAt are at the end of the
+// input source, ReadAt may return either err == EOF or err == nil.
+//
+// If ReadAt is reading from an input source with a seek offset,
+// ReadAt should not affect nor be affected by the underlying
+// seek offset.
+//
+// Clients of ReadAt can execute parallel ReadAt calls on the
+// same input source.
+type ReaderAt interface {
+	ReadAt(p []byte, off int64) (n int, err error)
+}
+
+// WriterAt is the interface that wraps the basic WriteAt method.
+//
+// WriteAt writes len(p) bytes from p to the underlying data stream
+// at offset off.  It returns the number of bytes written from p (0 <= n <= len(p))
+// and any error encountered that caused the write to stop early.
+// WriteAt must return a non-nil error if it returns n < len(p).
+//
+// If WriteAt is writing to a destination with a seek offset,
+// WriteAt should not affect nor be affected by the underlying
+// seek offset.
+//
+// Clients of WriteAt can execute parallel WriteAt calls on the same
+// destination if the ranges do not overlap.
+type WriterAt interface {
+	WriteAt(p []byte, off int64) (n int, err error)
+}
+
+// ByteReader is the interface that wraps the ReadByte method.
+//
+// ReadByte reads and returns the next byte from the input.
+// If no byte is available, err will be set.
+type ByteReader interface {
+	ReadByte() (c byte, err error)
+}
+
+// ByteScanner is the interface that adds the UnreadByte method to the
+// basic ReadByte method.
+//
+// UnreadByte causes the next call to ReadByte to return the same byte
+// as the previous call to ReadByte.
+// It may be an error to call UnreadByte twice without an intervening
+// call to ReadByte.
+type ByteScanner interface {
+	ByteReader
+	UnreadByte() error
+}
+
+// ByteWriter is the interface that wraps the WriteByte method.
+type ByteWriter interface {
+	WriteByte(c byte) error
+}
+
+// RuneReader is the interface that wraps the ReadRune method.
+//
+// ReadRune reads a single UTF-8 encoded Unicode character
+// and returns the rune and its size in bytes. If no character is
+// available, err will be set.
+type RuneReader interface {
+	ReadRune() (r rune, size int, err error)
+}
+
+// RuneScanner is the interface that adds the UnreadRune method to the
+// basic ReadRune method.
+//
+// UnreadRune causes the next call to ReadRune to return the same rune
+// as the previous call to ReadRune.
+// It may be an error to call UnreadRune twice without an intervening
+// call to ReadRune.
+type RuneScanner interface {
+	RuneReader
+	UnreadRune() error
+}
+
+// stringWriter is the interface that wraps the WriteString method.
+type stringWriter interface {
+	WriteString(s string) (n int, err error)
+}
+
+// WriteString writes the contents of the string s to w, which accepts an array of bytes.
+// If w already implements a WriteString method, it is invoked directly.
+func WriteString(w Writer, s string) (n int, err error) {
+	if sw, ok := w.(stringWriter); ok {
+		return sw.WriteString(s)
+	}
+	return w.Write([]byte(s))
+}
+
+// ReadAtLeast reads from r into buf until it has read at least min bytes.
+// It returns the number of bytes copied and an error if fewer bytes were read.
+// The error is EOF only if no bytes were read.
+// If an EOF happens after reading fewer than min bytes,
+// ReadAtLeast returns ErrUnexpectedEOF.
+// If min is greater than the length of buf, ReadAtLeast returns ErrShortBuffer.
+// On return, n >= min if and only if err == nil.
+func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) {
+	if len(buf) < min {
+		return 0, ErrShortBuffer
+	}
+	for n < min && err == nil {
+		var nn int
+		nn, err = r.Read(buf[n:])
+		n += nn
+	}
+	if n >= min {
+		err = nil
+	} else if n > 0 && err == EOF {
+		err = ErrUnexpectedEOF
+	}
+	return
+}
+
+// ReadFull reads exactly len(buf) bytes from r into buf.
+// It returns the number of bytes copied and an error if fewer bytes were read.
+// The error is EOF only if no bytes were read.
+// If an EOF happens after reading some but not all the bytes,
+// ReadFull returns ErrUnexpectedEOF.
+// On return, n == len(buf) if and only if err == nil.
+func ReadFull(r Reader, buf []byte) (n int, err error) {
+	return ReadAtLeast(r, buf, len(buf))
+}
+
+// CopyN copies n bytes (or until an error) from src to dst.
+// It returns the number of bytes copied and the earliest
+// error encountered while copying.
+// On return, written == n if and only if err == nil.
+//
+// If dst implements the ReaderFrom interface,
+// the copy is implemented using it.
+func CopyN(dst Writer, src Reader, n int64) (written int64, err error) {
+	written, err = Copy(dst, LimitReader(src, n))
+	if written == n {
+		return n, nil
+	}
+	if written < n && err == nil {
+		// src stopped early; must have been EOF.
+		err = EOF
+	}
+	return
+}
+
+// Copy copies from src to dst until either EOF is reached
+// on src or an error occurs.  It returns the number of bytes
+// copied and the first error encountered while copying, if any.
+//
+// A successful Copy returns err == nil, not err == EOF.
+// Because Copy is defined to read from src until EOF, it does
+// not treat an EOF from Read as an error to be reported.
+//
+// If src implements the WriterTo interface,
+// the copy is implemented by calling src.WriteTo(dst).
+// Otherwise, if dst implements the ReaderFrom interface,
+// the copy is implemented by calling dst.ReadFrom(src).
+func Copy(dst Writer, src Reader) (written int64, err error) {
+	// If the reader has a WriteTo method, use it to do the copy.
+	// Avoids an allocation and a copy.
+	if wt, ok := src.(WriterTo); ok {
+		return wt.WriteTo(dst)
+	}
+	// Similarly, if the writer has a ReadFrom method, use it to do the copy.
+	if rt, ok := dst.(ReaderFrom); ok {
+		return rt.ReadFrom(src)
+	}
+	buf := make([]byte, 32*1024)
+	for {
+		nr, er := src.Read(buf)
+		if nr > 0 {
+			nw, ew := dst.Write(buf[0:nr])
+			if nw > 0 {
+				written += int64(nw)
+			}
+			if ew != nil {
+				err = ew
+				break
+			}
+			if nr != nw {
+				err = ErrShortWrite
+				break
+			}
+		}
+		if er == EOF {
+			break
+		}
+		if er != nil {
+			err = er
+			break
+		}
+	}
+	return written, err
+}
+
+// LimitReader returns a Reader that reads from r
+// but stops with EOF after n bytes.
+// The underlying implementation is a *LimitedReader.
+func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} }
+
+// A LimitedReader reads from R but limits the amount of
+// data returned to just N bytes. Each call to Read
+// updates N to reflect the new amount remaining.
+type LimitedReader struct {
+	R Reader // underlying reader
+	N int64  // max bytes remaining
+}
+
+func (l *LimitedReader) Read(p []byte) (n int, err error) {
+	if l.N <= 0 {
+		return 0, EOF
+	}
+	if int64(len(p)) > l.N {
+		p = p[0:l.N]
+	}
+	n, err = l.R.Read(p)
+	l.N -= int64(n)
+	return
+}
+
+// NewSectionReader returns a SectionReader that reads from r
+// starting at offset off and stops with EOF after n bytes.
+func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader {
+	return &SectionReader{r, off, off, off + n}
+}
+
+// SectionReader implements Read, Seek, and ReadAt on a section
+// of an underlying ReaderAt.
+type SectionReader struct {
+	r     ReaderAt
+	base  int64
+	off   int64
+	limit int64
+}
+
+func (s *SectionReader) Read(p []byte) (n int, err error) {
+	if s.off >= s.limit {
+		return 0, EOF
+	}
+	if max := s.limit - s.off; int64(len(p)) > max {
+		p = p[0:max]
+	}
+	n, err = s.r.ReadAt(p, s.off)
+	s.off += int64(n)
+	return
+}
+
+var errWhence = errors.New("Seek: invalid whence")
+var errOffset = errors.New("Seek: invalid offset")
+
+func (s *SectionReader) Seek(offset int64, whence int) (int64, error) {
+	switch whence {
+	default:
+		return 0, errWhence
+	case 0:
+		offset += s.base
+	case 1:
+		offset += s.off
+	case 2:
+		offset += s.limit
+	}
+	if offset < s.base {
+		return 0, errOffset
+	}
+	s.off = offset
+	return offset - s.base, nil
+}
+
+func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error) {
+	if off < 0 || off >= s.limit-s.base {
+		return 0, EOF
+	}
+	off += s.base
+	if max := s.limit - off; int64(len(p)) > max {
+		p = p[0:max]
+		n, err = s.r.ReadAt(p, off)
+		if err == nil {
+			err = EOF
+		}
+		return n, err
+	}
+	return s.r.ReadAt(p, off)
+}
+
+// Size returns the size of the section in bytes.
+func (s *SectionReader) Size() int64 { return s.limit - s.base }
+
+// TeeReader returns a Reader that writes to w what it reads from r.
+// All reads from r performed through it are matched with
+// corresponding writes to w.  There is no internal buffering -
+// the write must complete before the read completes.
+// Any error encountered while writing is reported as a read error.
+func TeeReader(r Reader, w Writer) Reader {
+	return &teeReader{r, w}
+}
+
+type teeReader struct {
+	r Reader
+	w Writer
+}
+
+func (t *teeReader) Read(p []byte) (n int, err error) {
+	n, err = t.r.Read(p)
+	if n > 0 {
+		if n, err := t.w.Write(p[:n]); err != nil {
+			return n, err
+		}
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/io/io_test.go b/third_party/gofrontend/libgo/go/io/io_test.go
new file mode 100644
index 0000000..57db1fb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/io/io_test.go
@@ -0,0 +1,341 @@
+// 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 io_test
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	. "io"
+	"strings"
+	"testing"
+)
+
+// An version of bytes.Buffer without ReadFrom and WriteTo
+type Buffer struct {
+	bytes.Buffer
+	ReaderFrom // conflicts with and hides bytes.Buffer's ReaderFrom.
+	WriterTo   // conflicts with and hides bytes.Buffer's WriterTo.
+}
+
+// Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy and CopyN.
+
+func TestCopy(t *testing.T) {
+	rb := new(Buffer)
+	wb := new(Buffer)
+	rb.WriteString("hello, world.")
+	Copy(wb, rb)
+	if wb.String() != "hello, world." {
+		t.Errorf("Copy did not work properly")
+	}
+}
+
+func TestCopyReadFrom(t *testing.T) {
+	rb := new(Buffer)
+	wb := new(bytes.Buffer) // implements ReadFrom.
+	rb.WriteString("hello, world.")
+	Copy(wb, rb)
+	if wb.String() != "hello, world." {
+		t.Errorf("Copy did not work properly")
+	}
+}
+
+func TestCopyWriteTo(t *testing.T) {
+	rb := new(bytes.Buffer) // implements WriteTo.
+	wb := new(Buffer)
+	rb.WriteString("hello, world.")
+	Copy(wb, rb)
+	if wb.String() != "hello, world." {
+		t.Errorf("Copy did not work properly")
+	}
+}
+
+// Version of bytes.Buffer that checks whether WriteTo was called or not
+type writeToChecker struct {
+	bytes.Buffer
+	writeToCalled bool
+}
+
+func (wt *writeToChecker) WriteTo(w Writer) (int64, error) {
+	wt.writeToCalled = true
+	return wt.Buffer.WriteTo(w)
+}
+
+// It's preferable to choose WriterTo over ReaderFrom, since a WriterTo can issue one large write,
+// while the ReaderFrom must read until EOF, potentially allocating when running out of buffer.
+// Make sure that we choose WriterTo when both are implemented.
+func TestCopyPriority(t *testing.T) {
+	rb := new(writeToChecker)
+	wb := new(bytes.Buffer)
+	rb.WriteString("hello, world.")
+	Copy(wb, rb)
+	if wb.String() != "hello, world." {
+		t.Errorf("Copy did not work properly")
+	} else if !rb.writeToCalled {
+		t.Errorf("WriteTo was not prioritized over ReadFrom")
+	}
+}
+
+func TestCopyN(t *testing.T) {
+	rb := new(Buffer)
+	wb := new(Buffer)
+	rb.WriteString("hello, world.")
+	CopyN(wb, rb, 5)
+	if wb.String() != "hello" {
+		t.Errorf("CopyN did not work properly")
+	}
+}
+
+func TestCopyNReadFrom(t *testing.T) {
+	rb := new(Buffer)
+	wb := new(bytes.Buffer) // implements ReadFrom.
+	rb.WriteString("hello")
+	CopyN(wb, rb, 5)
+	if wb.String() != "hello" {
+		t.Errorf("CopyN did not work properly")
+	}
+}
+
+func TestCopyNWriteTo(t *testing.T) {
+	rb := new(bytes.Buffer) // implements WriteTo.
+	wb := new(Buffer)
+	rb.WriteString("hello, world.")
+	CopyN(wb, rb, 5)
+	if wb.String() != "hello" {
+		t.Errorf("CopyN did not work properly")
+	}
+}
+
+type noReadFrom struct {
+	w Writer
+}
+
+func (w *noReadFrom) Write(p []byte) (n int, err error) {
+	return w.w.Write(p)
+}
+
+type wantedAndErrReader struct{}
+
+func (wantedAndErrReader) Read(p []byte) (int, error) {
+	return len(p), errors.New("wantedAndErrReader error")
+}
+
+func TestCopyNEOF(t *testing.T) {
+	// Test that EOF behavior is the same regardless of whether
+	// argument to CopyN has ReadFrom.
+
+	b := new(bytes.Buffer)
+
+	n, err := CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3)
+	if n != 3 || err != nil {
+		t.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err)
+	}
+
+	n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4)
+	if n != 3 || err != EOF {
+		t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err)
+	}
+
+	n, err = CopyN(b, strings.NewReader("foo"), 3) // b has read from
+	if n != 3 || err != nil {
+		t.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err)
+	}
+
+	n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from
+	if n != 3 || err != EOF {
+		t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err)
+	}
+
+	n, err = CopyN(b, wantedAndErrReader{}, 5)
+	if n != 5 || err != nil {
+		t.Errorf("CopyN(bytes.Buffer, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err)
+	}
+
+	n, err = CopyN(&noReadFrom{b}, wantedAndErrReader{}, 5)
+	if n != 5 || err != nil {
+		t.Errorf("CopyN(noReadFrom, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err)
+	}
+}
+
+func TestReadAtLeast(t *testing.T) {
+	var rb bytes.Buffer
+	testReadAtLeast(t, &rb)
+}
+
+// A version of bytes.Buffer that returns n > 0, err on Read
+// when the input is exhausted.
+type dataAndErrorBuffer struct {
+	err error
+	bytes.Buffer
+}
+
+func (r *dataAndErrorBuffer) Read(p []byte) (n int, err error) {
+	n, err = r.Buffer.Read(p)
+	if n > 0 && r.Buffer.Len() == 0 && err == nil {
+		err = r.err
+	}
+	return
+}
+
+func TestReadAtLeastWithDataAndEOF(t *testing.T) {
+	var rb dataAndErrorBuffer
+	rb.err = EOF
+	testReadAtLeast(t, &rb)
+}
+
+func TestReadAtLeastWithDataAndError(t *testing.T) {
+	var rb dataAndErrorBuffer
+	rb.err = fmt.Errorf("fake error")
+	testReadAtLeast(t, &rb)
+}
+
+func testReadAtLeast(t *testing.T, rb ReadWriter) {
+	rb.Write([]byte("0123"))
+	buf := make([]byte, 2)
+	n, err := ReadAtLeast(rb, buf, 2)
+	if err != nil {
+		t.Error(err)
+	}
+	n, err = ReadAtLeast(rb, buf, 4)
+	if err != ErrShortBuffer {
+		t.Errorf("expected ErrShortBuffer got %v", err)
+	}
+	if n != 0 {
+		t.Errorf("expected to have read 0 bytes, got %v", n)
+	}
+	n, err = ReadAtLeast(rb, buf, 1)
+	if err != nil {
+		t.Error(err)
+	}
+	if n != 2 {
+		t.Errorf("expected to have read 2 bytes, got %v", n)
+	}
+	n, err = ReadAtLeast(rb, buf, 2)
+	if err != EOF {
+		t.Errorf("expected EOF, got %v", err)
+	}
+	if n != 0 {
+		t.Errorf("expected to have read 0 bytes, got %v", n)
+	}
+	rb.Write([]byte("4"))
+	n, err = ReadAtLeast(rb, buf, 2)
+	want := ErrUnexpectedEOF
+	if rb, ok := rb.(*dataAndErrorBuffer); ok && rb.err != EOF {
+		want = rb.err
+	}
+	if err != want {
+		t.Errorf("expected %v, got %v", want, err)
+	}
+	if n != 1 {
+		t.Errorf("expected to have read 1 bytes, got %v", n)
+	}
+}
+
+func TestTeeReader(t *testing.T) {
+	src := []byte("hello, world")
+	dst := make([]byte, len(src))
+	rb := bytes.NewBuffer(src)
+	wb := new(bytes.Buffer)
+	r := TeeReader(rb, wb)
+	if n, err := ReadFull(r, dst); err != nil || n != len(src) {
+		t.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n, err, len(src))
+	}
+	if !bytes.Equal(dst, src) {
+		t.Errorf("bytes read = %q want %q", dst, src)
+	}
+	if !bytes.Equal(wb.Bytes(), src) {
+		t.Errorf("bytes written = %q want %q", wb.Bytes(), src)
+	}
+	if n, err := r.Read(dst); n != 0 || err != EOF {
+		t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err)
+	}
+	rb = bytes.NewBuffer(src)
+	pr, pw := Pipe()
+	pr.Close()
+	r = TeeReader(rb, pw)
+	if n, err := ReadFull(r, dst); n != 0 || err != ErrClosedPipe {
+		t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err)
+	}
+}
+
+func TestSectionReader_ReadAt(t *testing.T) {
+	dat := "a long sample data, 1234567890"
+	tests := []struct {
+		data   string
+		off    int
+		n      int
+		bufLen int
+		at     int
+		exp    string
+		err    error
+	}{
+		{data: "", off: 0, n: 10, bufLen: 2, at: 0, exp: "", err: EOF},
+		{data: dat, off: 0, n: len(dat), bufLen: 0, at: 0, exp: "", err: nil},
+		{data: dat, off: len(dat), n: 1, bufLen: 1, at: 0, exp: "", err: EOF},
+		{data: dat, off: 0, n: len(dat) + 2, bufLen: len(dat), at: 0, exp: dat, err: nil},
+		{data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 0, exp: dat[:len(dat)/2], err: nil},
+		{data: dat, off: 0, n: len(dat), bufLen: len(dat), at: 0, exp: dat, err: nil},
+		{data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[2 : 2+len(dat)/2], err: nil},
+		{data: dat, off: 3, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[5 : 5+len(dat)/2], err: nil},
+		{data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 - 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: nil},
+		{data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 + 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: EOF},
+		{data: dat, off: 0, n: 0, bufLen: 0, at: -1, exp: "", err: EOF},
+		{data: dat, off: 0, n: 0, bufLen: 0, at: 1, exp: "", err: EOF},
+	}
+	for i, tt := range tests {
+		r := strings.NewReader(tt.data)
+		s := NewSectionReader(r, int64(tt.off), int64(tt.n))
+		buf := make([]byte, tt.bufLen)
+		if n, err := s.ReadAt(buf, int64(tt.at)); n != len(tt.exp) || string(buf[:n]) != tt.exp || err != tt.err {
+			t.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i, tt.at, buf[:n], err, tt.exp, tt.err)
+		}
+	}
+}
+
+func TestSectionReader_Seek(t *testing.T) {
+	// Verifies that NewSectionReader's Seeker behaves like bytes.NewReader (which is like strings.NewReader)
+	br := bytes.NewReader([]byte("foo"))
+	sr := NewSectionReader(br, 0, int64(len("foo")))
+
+	for whence := 0; whence <= 2; whence++ {
+		for offset := int64(-3); offset <= 4; offset++ {
+			brOff, brErr := br.Seek(offset, whence)
+			srOff, srErr := sr.Seek(offset, whence)
+			if (brErr != nil) != (srErr != nil) || brOff != srOff {
+				t.Errorf("For whence %d, offset %d: bytes.Reader.Seek = (%v, %v) != SectionReader.Seek = (%v, %v)",
+					whence, offset, brOff, brErr, srErr, srOff)
+			}
+		}
+	}
+
+	// And verify we can just seek past the end and get an EOF
+	got, err := sr.Seek(100, 0)
+	if err != nil || got != 100 {
+		t.Errorf("Seek = %v, %v; want 100, nil", got, err)
+	}
+
+	n, err := sr.Read(make([]byte, 10))
+	if n != 0 || err != EOF {
+		t.Errorf("Read = %v, %v; want 0, EOF", n, err)
+	}
+}
+
+func TestSectionReader_Size(t *testing.T) {
+	tests := []struct {
+		data string
+		want int64
+	}{
+		{"a long sample data, 1234567890", 30},
+		{"", 0},
+	}
+
+	for _, tt := range tests {
+		r := strings.NewReader(tt.data)
+		sr := NewSectionReader(r, 0, int64(len(tt.data)))
+		if got := sr.Size(); got != tt.want {
+			t.Errorf("Size = %v; want %v", got, tt.want)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/io/ioutil/ioutil.go b/third_party/gofrontend/libgo/go/io/ioutil/ioutil.go
new file mode 100644
index 0000000..909a815
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/io/ioutil/ioutil.go
@@ -0,0 +1,165 @@
+// 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 ioutil implements some I/O utility functions.
+package ioutil
+
+import (
+	"bytes"
+	"io"
+	"os"
+	"sort"
+	"sync"
+)
+
+// readAll reads from r until an error or EOF and returns the data it read
+// from the internal buffer allocated with a specified capacity.
+func readAll(r io.Reader, capacity int64) (b []byte, err error) {
+	buf := bytes.NewBuffer(make([]byte, 0, capacity))
+	// If the buffer overflows, we will get bytes.ErrTooLarge.
+	// Return that as an error. Any other panic remains.
+	defer func() {
+		e := recover()
+		if e == nil {
+			return
+		}
+		if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
+			err = panicErr
+		} else {
+			panic(e)
+		}
+	}()
+	_, err = buf.ReadFrom(r)
+	return buf.Bytes(), err
+}
+
+// ReadAll reads from r until an error or EOF and returns the data it read.
+// A successful call returns err == nil, not err == EOF. Because ReadAll is
+// defined to read from src until EOF, it does not treat an EOF from Read
+// as an error to be reported.
+func ReadAll(r io.Reader) ([]byte, error) {
+	return readAll(r, bytes.MinRead)
+}
+
+// ReadFile reads the file named by filename and returns the contents.
+// A successful call returns err == nil, not err == EOF. Because ReadFile
+// reads the whole file, it does not treat an EOF from Read as an error
+// to be reported.
+func ReadFile(filename string) ([]byte, error) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	// It's a good but not certain bet that FileInfo will tell us exactly how much to
+	// read, so let's try it but be prepared for the answer to be wrong.
+	var n int64
+
+	if fi, err := f.Stat(); err == nil {
+		// Don't preallocate a huge buffer, just in case.
+		if size := fi.Size(); size < 1e9 {
+			n = size
+		}
+	}
+	// As initial capacity for readAll, use n + a little extra in case Size is zero,
+	// and to avoid another allocation after Read has filled the buffer.  The readAll
+	// call will read into its allocated internal buffer cheaply.  If the size was
+	// wrong, we'll either waste some space off the end or reallocate as needed, but
+	// in the overwhelmingly common case we'll get it just right.
+	return readAll(f, n+bytes.MinRead)
+}
+
+// WriteFile writes data to a file named by filename.
+// If the file does not exist, WriteFile creates it with permissions perm;
+// otherwise WriteFile truncates it before writing.
+func WriteFile(filename string, data []byte, perm os.FileMode) error {
+	f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
+	if err != nil {
+		return err
+	}
+	n, err := f.Write(data)
+	if err == nil && n < len(data) {
+		err = io.ErrShortWrite
+	}
+	if err1 := f.Close(); err == nil {
+		err = err1
+	}
+	return err
+}
+
+// byName implements sort.Interface.
+type byName []os.FileInfo
+
+func (f byName) Len() int           { return len(f) }
+func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
+func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
+
+// ReadDir reads the directory named by dirname and returns
+// a list of sorted directory entries.
+func ReadDir(dirname string) ([]os.FileInfo, error) {
+	f, err := os.Open(dirname)
+	if err != nil {
+		return nil, err
+	}
+	list, err := f.Readdir(-1)
+	f.Close()
+	if err != nil {
+		return nil, err
+	}
+	sort.Sort(byName(list))
+	return list, nil
+}
+
+type nopCloser struct {
+	io.Reader
+}
+
+func (nopCloser) Close() error { return nil }
+
+// NopCloser returns a ReadCloser with a no-op Close method wrapping
+// the provided Reader r.
+func NopCloser(r io.Reader) io.ReadCloser {
+	return nopCloser{r}
+}
+
+type devNull int
+
+// devNull implements ReaderFrom as an optimization so io.Copy to
+// ioutil.Discard can avoid doing unnecessary work.
+var _ io.ReaderFrom = devNull(0)
+
+func (devNull) Write(p []byte) (int, error) {
+	return len(p), nil
+}
+
+func (devNull) WriteString(s string) (int, error) {
+	return len(s), nil
+}
+
+var blackHolePool = sync.Pool{
+	New: func() interface{} {
+		b := make([]byte, 8192)
+		return &b
+	},
+}
+
+func (devNull) ReadFrom(r io.Reader) (n int64, err error) {
+	bufp := blackHolePool.Get().(*[]byte)
+	readSize := 0
+	for {
+		readSize, err = r.Read(*bufp)
+		n += int64(readSize)
+		if err != nil {
+			blackHolePool.Put(bufp)
+			if err == io.EOF {
+				return n, nil
+			}
+			return
+		}
+	}
+}
+
+// Discard is an io.Writer on which all Write calls succeed
+// without doing anything.
+var Discard io.Writer = devNull(0)
diff --git a/third_party/gofrontend/libgo/go/io/ioutil/ioutil_test.go b/third_party/gofrontend/libgo/go/io/ioutil/ioutil_test.go
new file mode 100644
index 0000000..81fc602
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/io/ioutil/ioutil_test.go
@@ -0,0 +1,97 @@
+// 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 ioutil
+
+import (
+	"os"
+	"testing"
+)
+
+func checkSize(t *testing.T, path string, size int64) {
+	dir, err := os.Stat(path)
+	if err != nil {
+		t.Fatalf("Stat %q (looking for size %d): %s", path, size, err)
+	}
+	if dir.Size() != size {
+		t.Errorf("Stat %q: size %d want %d", path, dir.Size(), size)
+	}
+}
+
+func TestReadFile(t *testing.T) {
+	filename := "rumpelstilzchen"
+	contents, err := ReadFile(filename)
+	if err == nil {
+		t.Fatalf("ReadFile %s: error expected, none found", filename)
+	}
+
+	filename = "ioutil_test.go"
+	contents, err = ReadFile(filename)
+	if err != nil {
+		t.Fatalf("ReadFile %s: %v", filename, err)
+	}
+
+	checkSize(t, filename, int64(len(contents)))
+}
+
+func TestWriteFile(t *testing.T) {
+	f, err := TempFile("", "ioutil-test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	filename := f.Name()
+	data := "Programming today is a race between software engineers striving to " +
+		"build bigger and better idiot-proof programs, and the Universe trying " +
+		"to produce bigger and better idiots. So far, the Universe is winning."
+
+	if err := WriteFile(filename, []byte(data), 0644); err != nil {
+		t.Fatalf("WriteFile %s: %v", filename, err)
+	}
+
+	contents, err := ReadFile(filename)
+	if err != nil {
+		t.Fatalf("ReadFile %s: %v", filename, err)
+	}
+
+	if string(contents) != data {
+		t.Fatalf("contents = %q\nexpected = %q", string(contents), data)
+	}
+
+	// cleanup
+	f.Close()
+	os.Remove(filename) // ignore error
+}
+
+func TestReadDir(t *testing.T) {
+	dirname := "rumpelstilzchen"
+	_, err := ReadDir(dirname)
+	if err == nil {
+		t.Fatalf("ReadDir %s: error expected, none found", dirname)
+	}
+
+	/* Does not work in gccgo testing environment.
+	dirname = ".."
+	list, err := ReadDir(dirname)
+	if err != nil {
+		t.Fatalf("ReadDir %s: %v", dirname, err)
+	}
+
+	foundFile := false
+	foundSubDir := false
+	for _, dir := range list {
+		switch {
+		case !dir.IsDir() && dir.Name() == "io_test.go":
+			foundFile = true
+		case dir.IsDir() && dir.Name() == "ioutil":
+			foundSubDir = true
+		}
+	}
+	if !foundFile {
+		t.Fatalf("ReadDir %s: io_test.go file not found", dirname)
+	}
+	if !foundSubDir {
+		t.Fatalf("ReadDir %s: ioutil directory not found", dirname)
+	}
+	*/
+}
diff --git a/third_party/gofrontend/libgo/go/io/ioutil/tempfile.go b/third_party/gofrontend/libgo/go/io/ioutil/tempfile.go
new file mode 100644
index 0000000..4a06e97
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/io/ioutil/tempfile.go
@@ -0,0 +1,95 @@
+// Copyright 2010 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 ioutil
+
+import (
+	"os"
+	"path/filepath"
+	"strconv"
+	"sync"
+	"time"
+)
+
+// Random number state.
+// We generate random temporary file names so that there's a good
+// chance the file doesn't exist yet - keeps the number of tries in
+// TempFile to a minimum.
+var rand uint32
+var randmu sync.Mutex
+
+func reseed() uint32 {
+	return uint32(time.Now().UnixNano() + int64(os.Getpid()))
+}
+
+func nextSuffix() string {
+	randmu.Lock()
+	r := rand
+	if r == 0 {
+		r = reseed()
+	}
+	r = r*1664525 + 1013904223 // constants from Numerical Recipes
+	rand = r
+	randmu.Unlock()
+	return strconv.Itoa(int(1e9 + r%1e9))[1:]
+}
+
+// TempFile creates a new temporary file in the directory dir
+// with a name beginning with prefix, opens the file for reading
+// and writing, and returns the resulting *os.File.
+// If dir is the empty string, TempFile uses the default directory
+// for temporary files (see os.TempDir).
+// Multiple programs calling TempFile simultaneously
+// will not choose the same file.  The caller can use f.Name()
+// to find the pathname of the file.  It is the caller's responsibility
+// to remove the file when no longer needed.
+func TempFile(dir, prefix string) (f *os.File, err error) {
+	if dir == "" {
+		dir = os.TempDir()
+	}
+
+	nconflict := 0
+	for i := 0; i < 10000; i++ {
+		name := filepath.Join(dir, prefix+nextSuffix())
+		f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
+		if os.IsExist(err) {
+			if nconflict++; nconflict > 10 {
+				rand = reseed()
+			}
+			continue
+		}
+		break
+	}
+	return
+}
+
+// TempDir creates a new temporary directory in the directory dir
+// with a name beginning with prefix and returns the path of the
+// new directory.  If dir is the empty string, TempDir uses the
+// default directory for temporary files (see os.TempDir).
+// Multiple programs calling TempDir simultaneously
+// will not choose the same directory.  It is the caller's responsibility
+// to remove the directory when no longer needed.
+func TempDir(dir, prefix string) (name string, err error) {
+	if dir == "" {
+		dir = os.TempDir()
+	}
+
+	nconflict := 0
+	for i := 0; i < 10000; i++ {
+		try := filepath.Join(dir, prefix+nextSuffix())
+		err = os.Mkdir(try, 0700)
+		if os.IsExist(err) {
+			if nconflict++; nconflict > 10 {
+				rand = reseed()
+			}
+			continue
+		}
+		if err == nil {
+			name = try
+		}
+		break
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/io/ioutil/tempfile_test.go b/third_party/gofrontend/libgo/go/io/ioutil/tempfile_test.go
new file mode 100644
index 0000000..d2a132a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/io/ioutil/tempfile_test.go
@@ -0,0 +1,53 @@
+// Copyright 2010 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 ioutil
+
+import (
+	"os"
+	"path/filepath"
+	"regexp"
+	"testing"
+)
+
+func TestTempFile(t *testing.T) {
+	f, err := TempFile("/_not_exists_", "foo")
+	if f != nil || err == nil {
+		t.Errorf("TempFile(`/_not_exists_`, `foo`) = %v, %v", f, err)
+	}
+
+	dir := os.TempDir()
+	f, err = TempFile(dir, "ioutil_test")
+	if f == nil || err != nil {
+		t.Errorf("TempFile(dir, `ioutil_test`) = %v, %v", f, err)
+	}
+	if f != nil {
+		f.Close()
+		os.Remove(f.Name())
+		re := regexp.MustCompile("^" + regexp.QuoteMeta(filepath.Join(dir, "ioutil_test")) + "[0-9]+$")
+		if !re.MatchString(f.Name()) {
+			t.Errorf("TempFile(`"+dir+"`, `ioutil_test`) created bad name %s", f.Name())
+		}
+	}
+}
+
+func TestTempDir(t *testing.T) {
+	name, err := TempDir("/_not_exists_", "foo")
+	if name != "" || err == nil {
+		t.Errorf("TempDir(`/_not_exists_`, `foo`) = %v, %v", name, err)
+	}
+
+	dir := os.TempDir()
+	name, err = TempDir(dir, "ioutil_test")
+	if name == "" || err != nil {
+		t.Errorf("TempDir(dir, `ioutil_test`) = %v, %v", name, err)
+	}
+	if name != "" {
+		os.Remove(name)
+		re := regexp.MustCompile("^" + regexp.QuoteMeta(filepath.Join(dir, "ioutil_test")) + "[0-9]+$")
+		if !re.MatchString(name) {
+			t.Errorf("TempDir(`"+dir+"`, `ioutil_test`) created bad name %s", name)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/io/multi.go b/third_party/gofrontend/libgo/go/io/multi.go
new file mode 100644
index 0000000..e26cc53
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/io/multi.go
@@ -0,0 +1,61 @@
+// Copyright 2010 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 io
+
+type multiReader struct {
+	readers []Reader
+}
+
+func (mr *multiReader) Read(p []byte) (n int, err error) {
+	for len(mr.readers) > 0 {
+		n, err = mr.readers[0].Read(p)
+		if n > 0 || err != EOF {
+			if err == EOF {
+				// Don't return EOF yet. There may be more bytes
+				// in the remaining readers.
+				err = nil
+			}
+			return
+		}
+		mr.readers = mr.readers[1:]
+	}
+	return 0, EOF
+}
+
+// MultiReader returns a Reader that's the logical concatenation of
+// the provided input readers.  They're read sequentially.  Once all
+// inputs have returned EOF, Read will return EOF.  If any of the readers
+// return a non-nil, non-EOF error, Read will return that error.
+func MultiReader(readers ...Reader) Reader {
+	r := make([]Reader, len(readers))
+	copy(r, readers)
+	return &multiReader{r}
+}
+
+type multiWriter struct {
+	writers []Writer
+}
+
+func (t *multiWriter) Write(p []byte) (n int, err error) {
+	for _, w := range t.writers {
+		n, err = w.Write(p)
+		if err != nil {
+			return
+		}
+		if n != len(p) {
+			err = ErrShortWrite
+			return
+		}
+	}
+	return len(p), nil
+}
+
+// MultiWriter creates a writer that duplicates its writes to all the
+// provided writers, similar to the Unix tee(1) command.
+func MultiWriter(writers ...Writer) Writer {
+	w := make([]Writer, len(writers))
+	copy(w, writers)
+	return &multiWriter{w}
+}
diff --git a/third_party/gofrontend/libgo/go/io/multi_test.go b/third_party/gofrontend/libgo/go/io/multi_test.go
new file mode 100644
index 0000000..56c6769
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/io/multi_test.go
@@ -0,0 +1,115 @@
+// Copyright 2010 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 io_test
+
+import (
+	"bytes"
+	"crypto/sha1"
+	"fmt"
+	. "io"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+func TestMultiReader(t *testing.T) {
+	var mr Reader
+	var buf []byte
+	nread := 0
+	withFooBar := func(tests func()) {
+		r1 := strings.NewReader("foo ")
+		r2 := strings.NewReader("")
+		r3 := strings.NewReader("bar")
+		mr = MultiReader(r1, r2, r3)
+		buf = make([]byte, 20)
+		tests()
+	}
+	expectRead := func(size int, expected string, eerr error) {
+		nread++
+		n, gerr := mr.Read(buf[0:size])
+		if n != len(expected) {
+			t.Errorf("#%d, expected %d bytes; got %d",
+				nread, len(expected), n)
+		}
+		got := string(buf[0:n])
+		if got != expected {
+			t.Errorf("#%d, expected %q; got %q",
+				nread, expected, got)
+		}
+		if gerr != eerr {
+			t.Errorf("#%d, expected error %v; got %v",
+				nread, eerr, gerr)
+		}
+		buf = buf[n:]
+	}
+	withFooBar(func() {
+		expectRead(2, "fo", nil)
+		expectRead(5, "o ", nil)
+		expectRead(5, "bar", nil)
+		expectRead(5, "", EOF)
+	})
+	withFooBar(func() {
+		expectRead(4, "foo ", nil)
+		expectRead(1, "b", nil)
+		expectRead(3, "ar", nil)
+		expectRead(1, "", EOF)
+	})
+	withFooBar(func() {
+		expectRead(5, "foo ", nil)
+	})
+}
+
+func TestMultiWriter(t *testing.T) {
+	sha1 := sha1.New()
+	sink := new(bytes.Buffer)
+	mw := MultiWriter(sha1, sink)
+
+	sourceString := "My input text."
+	source := strings.NewReader(sourceString)
+	written, err := Copy(mw, source)
+
+	if written != int64(len(sourceString)) {
+		t.Errorf("short write of %d, not %d", written, len(sourceString))
+	}
+
+	if err != nil {
+		t.Errorf("unexpected error: %v", err)
+	}
+
+	sha1hex := fmt.Sprintf("%x", sha1.Sum(nil))
+	if sha1hex != "01cb303fa8c30a64123067c5aa6284ba7ec2d31b" {
+		t.Error("incorrect sha1 value")
+	}
+
+	if sink.String() != sourceString {
+		t.Errorf("expected %q; got %q", sourceString, sink.String())
+	}
+}
+
+// Test that MultiReader copies the input slice and is insulated from future modification.
+func TestMultiReaderCopy(t *testing.T) {
+	slice := []Reader{strings.NewReader("hello world")}
+	r := MultiReader(slice...)
+	slice[0] = nil
+	data, err := ioutil.ReadAll(r)
+	if err != nil || string(data) != "hello world" {
+		t.Errorf("ReadAll() = %q, %v, want %q, nil", data, err, "hello world")
+	}
+}
+
+// Test that MultiWriter copies the input slice and is insulated from future modification.
+func TestMultiWriterCopy(t *testing.T) {
+	var buf bytes.Buffer
+	slice := []Writer{&buf}
+	w := MultiWriter(slice...)
+	slice[0] = nil
+	n, err := w.Write([]byte("hello world"))
+	if err != nil || n != 11 {
+		t.Errorf("Write(`hello world`) = %d, %v, want 11, nil", n, err)
+	}
+	if buf.String() != "hello world" {
+		t.Errorf("buf.String() = %q, want %q", buf.String(), "hello world")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/io/pipe.go b/third_party/gofrontend/libgo/go/io/pipe.go
new file mode 100644
index 0000000..f65354a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/io/pipe.go
@@ -0,0 +1,193 @@
+// 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.
+
+// Pipe adapter to connect code expecting an io.Reader
+// with code expecting an io.Writer.
+
+package io
+
+import (
+	"errors"
+	"sync"
+)
+
+// ErrClosedPipe is the error used for read or write operations on a closed pipe.
+var ErrClosedPipe = errors.New("io: read/write on closed pipe")
+
+type pipeResult struct {
+	n   int
+	err error
+}
+
+// A pipe is the shared pipe structure underlying PipeReader and PipeWriter.
+type pipe struct {
+	rl    sync.Mutex // gates readers one at a time
+	wl    sync.Mutex // gates writers one at a time
+	l     sync.Mutex // protects remaining fields
+	data  []byte     // data remaining in pending write
+	rwait sync.Cond  // waiting reader
+	wwait sync.Cond  // waiting writer
+	rerr  error      // if reader closed, error to give writes
+	werr  error      // if writer closed, error to give reads
+}
+
+func (p *pipe) read(b []byte) (n int, err error) {
+	// One reader at a time.
+	p.rl.Lock()
+	defer p.rl.Unlock()
+
+	p.l.Lock()
+	defer p.l.Unlock()
+	for {
+		if p.rerr != nil {
+			return 0, ErrClosedPipe
+		}
+		if p.data != nil {
+			break
+		}
+		if p.werr != nil {
+			return 0, p.werr
+		}
+		p.rwait.Wait()
+	}
+	n = copy(b, p.data)
+	p.data = p.data[n:]
+	if len(p.data) == 0 {
+		p.data = nil
+		p.wwait.Signal()
+	}
+	return
+}
+
+var zero [0]byte
+
+func (p *pipe) write(b []byte) (n int, err error) {
+	// pipe uses nil to mean not available
+	if b == nil {
+		b = zero[:]
+	}
+
+	// One writer at a time.
+	p.wl.Lock()
+	defer p.wl.Unlock()
+
+	p.l.Lock()
+	defer p.l.Unlock()
+	if p.werr != nil {
+		err = ErrClosedPipe
+		return
+	}
+	p.data = b
+	p.rwait.Signal()
+	for {
+		if p.data == nil {
+			break
+		}
+		if p.rerr != nil {
+			err = p.rerr
+			break
+		}
+		if p.werr != nil {
+			err = ErrClosedPipe
+		}
+		p.wwait.Wait()
+	}
+	n = len(b) - len(p.data)
+	p.data = nil // in case of rerr or werr
+	return
+}
+
+func (p *pipe) rclose(err error) {
+	if err == nil {
+		err = ErrClosedPipe
+	}
+	p.l.Lock()
+	defer p.l.Unlock()
+	p.rerr = err
+	p.rwait.Signal()
+	p.wwait.Signal()
+}
+
+func (p *pipe) wclose(err error) {
+	if err == nil {
+		err = EOF
+	}
+	p.l.Lock()
+	defer p.l.Unlock()
+	p.werr = err
+	p.rwait.Signal()
+	p.wwait.Signal()
+}
+
+// A PipeReader is the read half of a pipe.
+type PipeReader struct {
+	p *pipe
+}
+
+// Read implements the standard Read interface:
+// it reads data from the pipe, blocking until a writer
+// arrives or the write end is closed.
+// If the write end is closed with an error, that error is
+// returned as err; otherwise err is EOF.
+func (r *PipeReader) Read(data []byte) (n int, err error) {
+	return r.p.read(data)
+}
+
+// Close closes the reader; subsequent writes to the
+// write half of the pipe will return the error ErrClosedPipe.
+func (r *PipeReader) Close() error {
+	return r.CloseWithError(nil)
+}
+
+// CloseWithError closes the reader; subsequent writes
+// to the write half of the pipe will return the error err.
+func (r *PipeReader) CloseWithError(err error) error {
+	r.p.rclose(err)
+	return nil
+}
+
+// A PipeWriter is the write half of a pipe.
+type PipeWriter struct {
+	p *pipe
+}
+
+// Write implements the standard Write interface:
+// it writes data to the pipe, blocking until readers
+// have consumed all the data or the read end is closed.
+// If the read end is closed with an error, that err is
+// returned as err; otherwise err is ErrClosedPipe.
+func (w *PipeWriter) Write(data []byte) (n int, err error) {
+	return w.p.write(data)
+}
+
+// Close closes the writer; subsequent reads from the
+// read half of the pipe will return no bytes and EOF.
+func (w *PipeWriter) Close() error {
+	return w.CloseWithError(nil)
+}
+
+// CloseWithError closes the writer; subsequent reads from the
+// read half of the pipe will return no bytes and the error err.
+func (w *PipeWriter) CloseWithError(err error) error {
+	w.p.wclose(err)
+	return nil
+}
+
+// Pipe creates a synchronous in-memory pipe.
+// It can be used to connect code expecting an io.Reader
+// with code expecting an io.Writer.
+// Reads on one end are matched with writes on the other,
+// copying data directly between the two; there is no internal buffering.
+// It is safe to call Read and Write in parallel with each other or with
+// Close. Close will complete once pending I/O is done. Parallel calls to
+// Read, and parallel calls to Write, are also safe:
+// the individual calls will be gated sequentially.
+func Pipe() (*PipeReader, *PipeWriter) {
+	p := new(pipe)
+	p.rwait.L = &p.l
+	p.wwait.L = &p.l
+	r := &PipeReader{p}
+	w := &PipeWriter{p}
+	return r, w
+}
diff --git a/third_party/gofrontend/libgo/go/io/pipe_test.go b/third_party/gofrontend/libgo/go/io/pipe_test.go
new file mode 100644
index 0000000..b16e653
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/io/pipe_test.go
@@ -0,0 +1,302 @@
+// 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 io_test
+
+import (
+	"fmt"
+	. "io"
+	"testing"
+	"time"
+)
+
+func checkWrite(t *testing.T, w Writer, data []byte, c chan int) {
+	n, err := w.Write(data)
+	if err != nil {
+		t.Errorf("write: %v", err)
+	}
+	if n != len(data) {
+		t.Errorf("short write: %d != %d", n, len(data))
+	}
+	c <- 0
+}
+
+// Test a single read/write pair.
+func TestPipe1(t *testing.T) {
+	c := make(chan int)
+	r, w := Pipe()
+	var buf = make([]byte, 64)
+	go checkWrite(t, w, []byte("hello, world"), c)
+	n, err := r.Read(buf)
+	if err != nil {
+		t.Errorf("read: %v", err)
+	} else if n != 12 || string(buf[0:12]) != "hello, world" {
+		t.Errorf("bad read: got %q", buf[0:n])
+	}
+	<-c
+	r.Close()
+	w.Close()
+}
+
+func reader(t *testing.T, r Reader, c chan int) {
+	var buf = make([]byte, 64)
+	for {
+		n, err := r.Read(buf)
+		if err == EOF {
+			c <- 0
+			break
+		}
+		if err != nil {
+			t.Errorf("read: %v", err)
+		}
+		c <- n
+	}
+}
+
+// Test a sequence of read/write pairs.
+func TestPipe2(t *testing.T) {
+	c := make(chan int)
+	r, w := Pipe()
+	go reader(t, r, c)
+	var buf = make([]byte, 64)
+	for i := 0; i < 5; i++ {
+		p := buf[0 : 5+i*10]
+		n, err := w.Write(p)
+		if n != len(p) {
+			t.Errorf("wrote %d, got %d", len(p), n)
+		}
+		if err != nil {
+			t.Errorf("write: %v", err)
+		}
+		nn := <-c
+		if nn != n {
+			t.Errorf("wrote %d, read got %d", n, nn)
+		}
+	}
+	w.Close()
+	nn := <-c
+	if nn != 0 {
+		t.Errorf("final read got %d", nn)
+	}
+}
+
+type pipeReturn struct {
+	n   int
+	err error
+}
+
+// Test a large write that requires multiple reads to satisfy.
+func writer(w WriteCloser, buf []byte, c chan pipeReturn) {
+	n, err := w.Write(buf)
+	w.Close()
+	c <- pipeReturn{n, err}
+}
+
+func TestPipe3(t *testing.T) {
+	c := make(chan pipeReturn)
+	r, w := Pipe()
+	var wdat = make([]byte, 128)
+	for i := 0; i < len(wdat); i++ {
+		wdat[i] = byte(i)
+	}
+	go writer(w, wdat, c)
+	var rdat = make([]byte, 1024)
+	tot := 0
+	for n := 1; n <= 256; n *= 2 {
+		nn, err := r.Read(rdat[tot : tot+n])
+		if err != nil && err != EOF {
+			t.Fatalf("read: %v", err)
+		}
+
+		// only final two reads should be short - 1 byte, then 0
+		expect := n
+		if n == 128 {
+			expect = 1
+		} else if n == 256 {
+			expect = 0
+			if err != EOF {
+				t.Fatalf("read at end: %v", err)
+			}
+		}
+		if nn != expect {
+			t.Fatalf("read %d, expected %d, got %d", n, expect, nn)
+		}
+		tot += nn
+	}
+	pr := <-c
+	if pr.n != 128 || pr.err != nil {
+		t.Fatalf("write 128: %d, %v", pr.n, pr.err)
+	}
+	if tot != 128 {
+		t.Fatalf("total read %d != 128", tot)
+	}
+	for i := 0; i < 128; i++ {
+		if rdat[i] != byte(i) {
+			t.Fatalf("rdat[%d] = %d", i, rdat[i])
+		}
+	}
+}
+
+// Test read after/before writer close.
+
+type closer interface {
+	CloseWithError(error) error
+	Close() error
+}
+
+type pipeTest struct {
+	async          bool
+	err            error
+	closeWithError bool
+}
+
+func (p pipeTest) String() string {
+	return fmt.Sprintf("async=%v err=%v closeWithError=%v", p.async, p.err, p.closeWithError)
+}
+
+var pipeTests = []pipeTest{
+	{true, nil, false},
+	{true, nil, true},
+	{true, ErrShortWrite, true},
+	{false, nil, false},
+	{false, nil, true},
+	{false, ErrShortWrite, true},
+}
+
+func delayClose(t *testing.T, cl closer, ch chan int, tt pipeTest) {
+	time.Sleep(1 * time.Millisecond)
+	var err error
+	if tt.closeWithError {
+		err = cl.CloseWithError(tt.err)
+	} else {
+		err = cl.Close()
+	}
+	if err != nil {
+		t.Errorf("delayClose: %v", err)
+	}
+	ch <- 0
+}
+
+func TestPipeReadClose(t *testing.T) {
+	for _, tt := range pipeTests {
+		c := make(chan int, 1)
+		r, w := Pipe()
+		if tt.async {
+			go delayClose(t, w, c, tt)
+		} else {
+			delayClose(t, w, c, tt)
+		}
+		var buf = make([]byte, 64)
+		n, err := r.Read(buf)
+		<-c
+		want := tt.err
+		if want == nil {
+			want = EOF
+		}
+		if err != want {
+			t.Errorf("read from closed pipe: %v want %v", err, want)
+		}
+		if n != 0 {
+			t.Errorf("read on closed pipe returned %d", n)
+		}
+		if err = r.Close(); err != nil {
+			t.Errorf("r.Close: %v", err)
+		}
+	}
+}
+
+// Test close on Read side during Read.
+func TestPipeReadClose2(t *testing.T) {
+	c := make(chan int, 1)
+	r, _ := Pipe()
+	go delayClose(t, r, c, pipeTest{})
+	n, err := r.Read(make([]byte, 64))
+	<-c
+	if n != 0 || err != ErrClosedPipe {
+		t.Errorf("read from closed pipe: %v, %v want %v, %v", n, err, 0, ErrClosedPipe)
+	}
+}
+
+// Test write after/before reader close.
+
+func TestPipeWriteClose(t *testing.T) {
+	for _, tt := range pipeTests {
+		c := make(chan int, 1)
+		r, w := Pipe()
+		if tt.async {
+			go delayClose(t, r, c, tt)
+		} else {
+			delayClose(t, r, c, tt)
+		}
+		n, err := WriteString(w, "hello, world")
+		<-c
+		expect := tt.err
+		if expect == nil {
+			expect = ErrClosedPipe
+		}
+		if err != expect {
+			t.Errorf("write on closed pipe: %v want %v", err, expect)
+		}
+		if n != 0 {
+			t.Errorf("write on closed pipe returned %d", n)
+		}
+		if err = w.Close(); err != nil {
+			t.Errorf("w.Close: %v", err)
+		}
+	}
+}
+
+func TestWriteEmpty(t *testing.T) {
+	r, w := Pipe()
+	go func() {
+		w.Write([]byte{})
+		w.Close()
+	}()
+	var b [2]byte
+	ReadFull(r, b[0:2])
+	r.Close()
+}
+
+func TestWriteNil(t *testing.T) {
+	r, w := Pipe()
+	go func() {
+		w.Write(nil)
+		w.Close()
+	}()
+	var b [2]byte
+	ReadFull(r, b[0:2])
+	r.Close()
+}
+
+func TestWriteAfterWriterClose(t *testing.T) {
+	r, w := Pipe()
+
+	done := make(chan bool)
+	var writeErr error
+	go func() {
+		_, err := w.Write([]byte("hello"))
+		if err != nil {
+			t.Errorf("got error: %q; expected none", err)
+		}
+		w.Close()
+		_, writeErr = w.Write([]byte("world"))
+		done <- true
+	}()
+
+	buf := make([]byte, 100)
+	var result string
+	n, err := ReadFull(r, buf)
+	if err != nil && err != ErrUnexpectedEOF {
+		t.Fatalf("got: %q; want: %q", err, ErrUnexpectedEOF)
+	}
+	result = string(buf[0:n])
+	<-done
+
+	if result != "hello" {
+		t.Errorf("got: %q; want: %q", result, "hello")
+	}
+	if writeErr != ErrClosedPipe {
+		t.Errorf("got: %q; want: %q", writeErr, ErrClosedPipe)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/log/log.go b/third_party/gofrontend/libgo/go/log/log.go
new file mode 100644
index 0000000..d37e437
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/log/log.go
@@ -0,0 +1,322 @@
+// 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 log implements a simple logging package. It defines a type, Logger,
+// with methods for formatting output. It also has a predefined 'standard'
+// Logger accessible through helper functions Print[f|ln], Fatal[f|ln], and
+// Panic[f|ln], which are easier to use than creating a Logger manually.
+// That logger writes to standard error and prints the date and time
+// of each logged message.
+// The Fatal functions call os.Exit(1) after writing the log message.
+// The Panic functions call panic after writing the log message.
+package log
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"runtime"
+	"sync"
+	"time"
+)
+
+// These flags define which text to prefix to each log entry generated by the Logger.
+const (
+	// Bits or'ed together to control what's printed. There is no control over the
+	// order they appear (the order listed here) or the format they present (as
+	// described in the comments).  A colon appears after these items:
+	//	2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
+	Ldate         = 1 << iota     // the date: 2009/01/23
+	Ltime                         // the time: 01:23:23
+	Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.
+	Llongfile                     // full file name and line number: /a/b/c/d.go:23
+	Lshortfile                    // final file name element and line number: d.go:23. overrides Llongfile
+	LstdFlags     = Ldate | Ltime // initial values for the standard logger
+)
+
+// A Logger represents an active logging object that generates lines of
+// output to an io.Writer.  Each logging operation makes a single call to
+// the Writer's Write method.  A Logger can be used simultaneously from
+// multiple goroutines; it guarantees to serialize access to the Writer.
+type Logger struct {
+	mu     sync.Mutex // ensures atomic writes; protects the following fields
+	prefix string     // prefix to write at beginning of each line
+	flag   int        // properties
+	out    io.Writer  // destination for output
+	buf    []byte     // for accumulating text to write
+}
+
+// New creates a new Logger.   The out variable sets the
+// destination to which log data will be written.
+// The prefix appears at the beginning of each generated log line.
+// The flag argument defines the logging properties.
+func New(out io.Writer, prefix string, flag int) *Logger {
+	return &Logger{out: out, prefix: prefix, flag: flag}
+}
+
+var std = New(os.Stderr, "", LstdFlags)
+
+// Cheap integer to fixed-width decimal ASCII.  Give a negative width to avoid zero-padding.
+// Knows the buffer has capacity.
+func itoa(buf *[]byte, i int, wid int) {
+	var u uint = uint(i)
+	if u == 0 && wid <= 1 {
+		*buf = append(*buf, '0')
+		return
+	}
+
+	// Assemble decimal in reverse order.
+	var b [32]byte
+	bp := len(b)
+	for ; u > 0 || wid > 0; u /= 10 {
+		bp--
+		wid--
+		b[bp] = byte(u%10) + '0'
+	}
+	*buf = append(*buf, b[bp:]...)
+}
+
+func (l *Logger) formatHeader(buf *[]byte, t time.Time, file string, line int) {
+	*buf = append(*buf, l.prefix...)
+	if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
+		if l.flag&Ldate != 0 {
+			year, month, day := t.Date()
+			itoa(buf, year, 4)
+			*buf = append(*buf, '/')
+			itoa(buf, int(month), 2)
+			*buf = append(*buf, '/')
+			itoa(buf, day, 2)
+			*buf = append(*buf, ' ')
+		}
+		if l.flag&(Ltime|Lmicroseconds) != 0 {
+			hour, min, sec := t.Clock()
+			itoa(buf, hour, 2)
+			*buf = append(*buf, ':')
+			itoa(buf, min, 2)
+			*buf = append(*buf, ':')
+			itoa(buf, sec, 2)
+			if l.flag&Lmicroseconds != 0 {
+				*buf = append(*buf, '.')
+				itoa(buf, t.Nanosecond()/1e3, 6)
+			}
+			*buf = append(*buf, ' ')
+		}
+	}
+	if l.flag&(Lshortfile|Llongfile) != 0 {
+		if l.flag&Lshortfile != 0 {
+			short := file
+			for i := len(file) - 1; i > 0; i-- {
+				if file[i] == '/' {
+					short = file[i+1:]
+					break
+				}
+			}
+			file = short
+		}
+		*buf = append(*buf, file...)
+		*buf = append(*buf, ':')
+		itoa(buf, line, -1)
+		*buf = append(*buf, ": "...)
+	}
+}
+
+// Output writes the output for a logging event.  The string s contains
+// the text to print after the prefix specified by the flags of the
+// Logger.  A newline is appended if the last character of s is not
+// already a newline.  Calldepth is used to recover the PC and is
+// provided for generality, although at the moment on all pre-defined
+// paths it will be 2.
+func (l *Logger) Output(calldepth int, s string) error {
+	now := time.Now() // get this early.
+	var file string
+	var line int
+	l.mu.Lock()
+	defer l.mu.Unlock()
+	if l.flag&(Lshortfile|Llongfile) != 0 {
+		// release lock while getting caller info - it's expensive.
+		l.mu.Unlock()
+		var ok bool
+		_, file, line, ok = runtime.Caller(calldepth)
+		if !ok {
+			file = "???"
+			line = 0
+		}
+		l.mu.Lock()
+	}
+	l.buf = l.buf[:0]
+	l.formatHeader(&l.buf, now, file, line)
+	l.buf = append(l.buf, s...)
+	if len(s) > 0 && s[len(s)-1] != '\n' {
+		l.buf = append(l.buf, '\n')
+	}
+	_, err := l.out.Write(l.buf)
+	return err
+}
+
+// Printf calls l.Output to print to the logger.
+// Arguments are handled in the manner of fmt.Printf.
+func (l *Logger) Printf(format string, v ...interface{}) {
+	l.Output(2, fmt.Sprintf(format, v...))
+}
+
+// Print calls l.Output to print to the logger.
+// Arguments are handled in the manner of fmt.Print.
+func (l *Logger) Print(v ...interface{}) { l.Output(2, fmt.Sprint(v...)) }
+
+// Println calls l.Output to print to the logger.
+// Arguments are handled in the manner of fmt.Println.
+func (l *Logger) Println(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) }
+
+// Fatal is equivalent to l.Print() followed by a call to os.Exit(1).
+func (l *Logger) Fatal(v ...interface{}) {
+	l.Output(2, fmt.Sprint(v...))
+	os.Exit(1)
+}
+
+// Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).
+func (l *Logger) Fatalf(format string, v ...interface{}) {
+	l.Output(2, fmt.Sprintf(format, v...))
+	os.Exit(1)
+}
+
+// Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).
+func (l *Logger) Fatalln(v ...interface{}) {
+	l.Output(2, fmt.Sprintln(v...))
+	os.Exit(1)
+}
+
+// Panic is equivalent to l.Print() followed by a call to panic().
+func (l *Logger) Panic(v ...interface{}) {
+	s := fmt.Sprint(v...)
+	l.Output(2, s)
+	panic(s)
+}
+
+// Panicf is equivalent to l.Printf() followed by a call to panic().
+func (l *Logger) Panicf(format string, v ...interface{}) {
+	s := fmt.Sprintf(format, v...)
+	l.Output(2, s)
+	panic(s)
+}
+
+// Panicln is equivalent to l.Println() followed by a call to panic().
+func (l *Logger) Panicln(v ...interface{}) {
+	s := fmt.Sprintln(v...)
+	l.Output(2, s)
+	panic(s)
+}
+
+// Flags returns the output flags for the logger.
+func (l *Logger) Flags() int {
+	l.mu.Lock()
+	defer l.mu.Unlock()
+	return l.flag
+}
+
+// SetFlags sets the output flags for the logger.
+func (l *Logger) SetFlags(flag int) {
+	l.mu.Lock()
+	defer l.mu.Unlock()
+	l.flag = flag
+}
+
+// Prefix returns the output prefix for the logger.
+func (l *Logger) Prefix() string {
+	l.mu.Lock()
+	defer l.mu.Unlock()
+	return l.prefix
+}
+
+// SetPrefix sets the output prefix for the logger.
+func (l *Logger) SetPrefix(prefix string) {
+	l.mu.Lock()
+	defer l.mu.Unlock()
+	l.prefix = prefix
+}
+
+// SetOutput sets the output destination for the standard logger.
+func SetOutput(w io.Writer) {
+	std.mu.Lock()
+	defer std.mu.Unlock()
+	std.out = w
+}
+
+// Flags returns the output flags for the standard logger.
+func Flags() int {
+	return std.Flags()
+}
+
+// SetFlags sets the output flags for the standard logger.
+func SetFlags(flag int) {
+	std.SetFlags(flag)
+}
+
+// Prefix returns the output prefix for the standard logger.
+func Prefix() string {
+	return std.Prefix()
+}
+
+// SetPrefix sets the output prefix for the standard logger.
+func SetPrefix(prefix string) {
+	std.SetPrefix(prefix)
+}
+
+// These functions write to the standard logger.
+
+// Print calls Output to print to the standard logger.
+// Arguments are handled in the manner of fmt.Print.
+func Print(v ...interface{}) {
+	std.Output(2, fmt.Sprint(v...))
+}
+
+// Printf calls Output to print to the standard logger.
+// Arguments are handled in the manner of fmt.Printf.
+func Printf(format string, v ...interface{}) {
+	std.Output(2, fmt.Sprintf(format, v...))
+}
+
+// Println calls Output to print to the standard logger.
+// Arguments are handled in the manner of fmt.Println.
+func Println(v ...interface{}) {
+	std.Output(2, fmt.Sprintln(v...))
+}
+
+// Fatal is equivalent to Print() followed by a call to os.Exit(1).
+func Fatal(v ...interface{}) {
+	std.Output(2, fmt.Sprint(v...))
+	os.Exit(1)
+}
+
+// Fatalf is equivalent to Printf() followed by a call to os.Exit(1).
+func Fatalf(format string, v ...interface{}) {
+	std.Output(2, fmt.Sprintf(format, v...))
+	os.Exit(1)
+}
+
+// Fatalln is equivalent to Println() followed by a call to os.Exit(1).
+func Fatalln(v ...interface{}) {
+	std.Output(2, fmt.Sprintln(v...))
+	os.Exit(1)
+}
+
+// Panic is equivalent to Print() followed by a call to panic().
+func Panic(v ...interface{}) {
+	s := fmt.Sprint(v...)
+	std.Output(2, s)
+	panic(s)
+}
+
+// Panicf is equivalent to Printf() followed by a call to panic().
+func Panicf(format string, v ...interface{}) {
+	s := fmt.Sprintf(format, v...)
+	std.Output(2, s)
+	panic(s)
+}
+
+// Panicln is equivalent to Println() followed by a call to panic().
+func Panicln(v ...interface{}) {
+	s := fmt.Sprintln(v...)
+	std.Output(2, s)
+	panic(s)
+}
diff --git a/third_party/gofrontend/libgo/go/log/log_test.go b/third_party/gofrontend/libgo/go/log/log_test.go
new file mode 100644
index 0000000..158c3d9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/log/log_test.go
@@ -0,0 +1,119 @@
+// 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 log
+
+// These tests are too simple.
+
+import (
+	"bytes"
+	"os"
+	"regexp"
+	"testing"
+)
+
+const (
+	Rdate         = `[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]`
+	Rtime         = `[0-9][0-9]:[0-9][0-9]:[0-9][0-9]`
+	Rmicroseconds = `\.[0-9][0-9][0-9][0-9][0-9][0-9]`
+	Rline         = `(54|56):` // must update if the calls to l.Printf / l.Print below move
+	Rlongfile     = `.*/[A-Za-z0-9_\-]+\.go:` + Rline
+	Rshortfile    = `[A-Za-z0-9_\-]+\.go:` + Rline
+)
+
+type tester struct {
+	flag    int
+	prefix  string
+	pattern string // regexp that log output must match; we add ^ and expected_text$ always
+}
+
+var tests = []tester{
+	// individual pieces:
+	{0, "", ""},
+	{0, "XXX", "XXX"},
+	{Ldate, "", Rdate + " "},
+	{Ltime, "", Rtime + " "},
+	{Ltime | Lmicroseconds, "", Rtime + Rmicroseconds + " "},
+	{Lmicroseconds, "", Rtime + Rmicroseconds + " "}, // microsec implies time
+	{Llongfile, "", Rlongfile + " "},
+	{Lshortfile, "", Rshortfile + " "},
+	{Llongfile | Lshortfile, "", Rshortfile + " "}, // shortfile overrides longfile
+	// everything at once:
+	{Ldate | Ltime | Lmicroseconds | Llongfile, "XXX", "XXX" + Rdate + " " + Rtime + Rmicroseconds + " " + Rlongfile + " "},
+	{Ldate | Ltime | Lmicroseconds | Lshortfile, "XXX", "XXX" + Rdate + " " + Rtime + Rmicroseconds + " " + Rshortfile + " "},
+}
+
+// Test using Println("hello", 23, "world") or using Printf("hello %d world", 23)
+func testPrint(t *testing.T, flag int, prefix string, pattern string, useFormat bool) {
+	buf := new(bytes.Buffer)
+	SetOutput(buf)
+	SetFlags(flag)
+	SetPrefix(prefix)
+	if useFormat {
+		Printf("hello %d world", 23)
+	} else {
+		Println("hello", 23, "world")
+	}
+	line := buf.String()
+	line = line[0 : len(line)-1]
+	pattern = "^" + pattern + "hello 23 world$"
+	matched, err4 := regexp.MatchString(pattern, line)
+	if err4 != nil {
+		t.Fatal("pattern did not compile:", err4)
+	}
+	if !matched {
+		t.Errorf("log output should match %q is %q", pattern, line)
+	}
+	SetOutput(os.Stderr)
+}
+
+func TestAll(t *testing.T) {
+	for _, testcase := range tests {
+		testPrint(t, testcase.flag, testcase.prefix, testcase.pattern, false)
+		testPrint(t, testcase.flag, testcase.prefix, testcase.pattern, true)
+	}
+}
+
+func TestOutput(t *testing.T) {
+	const testString = "test"
+	var b bytes.Buffer
+	l := New(&b, "", 0)
+	l.Println(testString)
+	if expect := testString + "\n"; b.String() != expect {
+		t.Errorf("log output should match %q is %q", expect, b.String())
+	}
+}
+
+func TestFlagAndPrefixSetting(t *testing.T) {
+	var b bytes.Buffer
+	l := New(&b, "Test:", LstdFlags)
+	f := l.Flags()
+	if f != LstdFlags {
+		t.Errorf("Flags 1: expected %x got %x", LstdFlags, f)
+	}
+	l.SetFlags(f | Lmicroseconds)
+	f = l.Flags()
+	if f != LstdFlags|Lmicroseconds {
+		t.Errorf("Flags 2: expected %x got %x", LstdFlags|Lmicroseconds, f)
+	}
+	p := l.Prefix()
+	if p != "Test:" {
+		t.Errorf(`Prefix: expected "Test:" got %q`, p)
+	}
+	l.SetPrefix("Reality:")
+	p = l.Prefix()
+	if p != "Reality:" {
+		t.Errorf(`Prefix: expected "Reality:" got %q`, p)
+	}
+	// Verify a log message looks right, with our prefix and microseconds present.
+	l.Print("hello")
+	pattern := "^Reality:" + Rdate + " " + Rtime + Rmicroseconds + " hello\n"
+	matched, err := regexp.Match(pattern, b.Bytes())
+	if err != nil {
+		t.Fatalf("pattern %q did not compile: %s", pattern, err)
+	}
+	if !matched {
+		t.Error("message did not match pattern")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/log/syslog/syslog.go b/third_party/gofrontend/libgo/go/log/syslog/syslog.go
new file mode 100644
index 0000000..5e09599
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/log/syslog/syslog.go
@@ -0,0 +1,319 @@
+// 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.
+
+// +build !windows,!nacl,!plan9
+
+// Package syslog provides a simple interface to the system log
+// service. It can send messages to the syslog daemon using UNIX
+// domain sockets, UDP or TCP.
+//
+// Only one call to Dial is necessary. On write failures,
+// the syslog client will attempt to reconnect to the server
+// and write again.
+package syslog
+
+import (
+	"errors"
+	"fmt"
+	"log"
+	"net"
+	"os"
+	"strings"
+	"sync"
+	"time"
+)
+
+// The Priority is a combination of the syslog facility and
+// severity. For example, LOG_ALERT | LOG_FTP sends an alert severity
+// message from the FTP facility. The default severity is LOG_EMERG;
+// the default facility is LOG_KERN.
+type Priority int
+
+const severityMask = 0x07
+const facilityMask = 0xf8
+
+const (
+	// Severity.
+
+	// From /usr/include/sys/syslog.h.
+	// These are the same on Linux, BSD, and OS X.
+	LOG_EMERG Priority = iota
+	LOG_ALERT
+	LOG_CRIT
+	LOG_ERR
+	LOG_WARNING
+	LOG_NOTICE
+	LOG_INFO
+	LOG_DEBUG
+)
+
+const (
+	// Facility.
+
+	// From /usr/include/sys/syslog.h.
+	// These are the same up to LOG_FTP on Linux, BSD, and OS X.
+	LOG_KERN Priority = iota << 3
+	LOG_USER
+	LOG_MAIL
+	LOG_DAEMON
+	LOG_AUTH
+	LOG_SYSLOG
+	LOG_LPR
+	LOG_NEWS
+	LOG_UUCP
+	LOG_CRON
+	LOG_AUTHPRIV
+	LOG_FTP
+	_ // unused
+	_ // unused
+	_ // unused
+	_ // unused
+	LOG_LOCAL0
+	LOG_LOCAL1
+	LOG_LOCAL2
+	LOG_LOCAL3
+	LOG_LOCAL4
+	LOG_LOCAL5
+	LOG_LOCAL6
+	LOG_LOCAL7
+)
+
+// A Writer is a connection to a syslog server.
+type Writer struct {
+	priority Priority
+	tag      string
+	hostname string
+	network  string
+	raddr    string
+
+	mu   sync.Mutex // guards conn
+	conn serverConn
+}
+
+// This interface and the separate syslog_unix.go file exist for
+// Solaris support as implemented by gccgo.  On Solaris you can not
+// simply open a TCP connection to the syslog daemon.  The gccgo
+// sources have a syslog_solaris.go file that implements unixSyslog to
+// return a type that satisfies this interface and simply calls the C
+// library syslog function.
+type serverConn interface {
+	writeString(p Priority, hostname, tag, s, nl string) error
+	close() error
+}
+
+type netConn struct {
+	local bool
+	conn  net.Conn
+}
+
+// New establishes a new connection to the system log daemon.  Each
+// write to the returned writer sends a log message with the given
+// priority and prefix.
+func New(priority Priority, tag string) (w *Writer, err error) {
+	return Dial("", "", priority, tag)
+}
+
+// Dial establishes a connection to a log daemon by connecting to
+// address raddr on the specified network.  Each write to the returned
+// writer sends a log message with the given facility, severity and
+// tag.
+// If network is empty, Dial will connect to the local syslog server.
+func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) {
+	if priority < 0 || priority > LOG_LOCAL7|LOG_DEBUG {
+		return nil, errors.New("log/syslog: invalid priority")
+	}
+
+	if tag == "" {
+		tag = os.Args[0]
+	}
+	hostname, _ := os.Hostname()
+
+	w := &Writer{
+		priority: priority,
+		tag:      tag,
+		hostname: hostname,
+		network:  network,
+		raddr:    raddr,
+	}
+
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	err := w.connect()
+	if err != nil {
+		return nil, err
+	}
+	return w, err
+}
+
+// connect makes a connection to the syslog server.
+// It must be called with w.mu held.
+func (w *Writer) connect() (err error) {
+	if w.conn != nil {
+		// ignore err from close, it makes sense to continue anyway
+		w.conn.close()
+		w.conn = nil
+	}
+
+	if w.network == "" {
+		w.conn, err = unixSyslog()
+		if w.hostname == "" {
+			w.hostname = "localhost"
+		}
+	} else {
+		var c net.Conn
+		c, err = net.Dial(w.network, w.raddr)
+		if err == nil {
+			w.conn = &netConn{conn: c}
+			if w.hostname == "" {
+				w.hostname = c.LocalAddr().String()
+			}
+		}
+	}
+	return
+}
+
+// Write sends a log message to the syslog daemon.
+func (w *Writer) Write(b []byte) (int, error) {
+	return w.writeAndRetry(w.priority, string(b))
+}
+
+// Close closes a connection to the syslog daemon.
+func (w *Writer) Close() error {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	if w.conn != nil {
+		err := w.conn.close()
+		w.conn = nil
+		return err
+	}
+	return nil
+}
+
+// Emerg logs a message with severity LOG_EMERG, ignoring the severity
+// passed to New.
+func (w *Writer) Emerg(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_EMERG, m)
+	return err
+}
+
+// Alert logs a message with severity LOG_ALERT, ignoring the severity
+// passed to New.
+func (w *Writer) Alert(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_ALERT, m)
+	return err
+}
+
+// Crit logs a message with severity LOG_CRIT, ignoring the severity
+// passed to New.
+func (w *Writer) Crit(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_CRIT, m)
+	return err
+}
+
+// Err logs a message with severity LOG_ERR, ignoring the severity
+// passed to New.
+func (w *Writer) Err(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_ERR, m)
+	return err
+}
+
+// Warning logs a message with severity LOG_WARNING, ignoring the
+// severity passed to New.
+func (w *Writer) Warning(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_WARNING, m)
+	return err
+}
+
+// Notice logs a message with severity LOG_NOTICE, ignoring the
+// severity passed to New.
+func (w *Writer) Notice(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_NOTICE, m)
+	return err
+}
+
+// Info logs a message with severity LOG_INFO, ignoring the severity
+// passed to New.
+func (w *Writer) Info(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_INFO, m)
+	return err
+}
+
+// Debug logs a message with severity LOG_DEBUG, ignoring the severity
+// passed to New.
+func (w *Writer) Debug(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_DEBUG, m)
+	return err
+}
+
+func (w *Writer) writeAndRetry(p Priority, s string) (int, error) {
+	pr := (w.priority & facilityMask) | (p & severityMask)
+
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	if w.conn != nil {
+		if n, err := w.write(pr, s); err == nil {
+			return n, err
+		}
+	}
+	if err := w.connect(); err != nil {
+		return 0, err
+	}
+	return w.write(pr, s)
+}
+
+// write generates and writes a syslog formatted string. The
+// format is as follows: <PRI>TIMESTAMP HOSTNAME TAG[PID]: MSG
+func (w *Writer) write(p Priority, msg string) (int, error) {
+	// ensure it ends in a \n
+	nl := ""
+	if !strings.HasSuffix(msg, "\n") {
+		nl = "\n"
+	}
+
+	err := w.conn.writeString(p, w.hostname, w.tag, msg, nl)
+	if err != nil {
+		return 0, err
+	}
+	// Note: return the length of the input, not the number of
+	// bytes printed by Fprintf, because this must behave like
+	// an io.Writer.
+	return len(msg), nil
+}
+
+func (n *netConn) writeString(p Priority, hostname, tag, msg, nl string) error {
+	if n.local {
+		// Compared to the network form below, the changes are:
+		//	1. Use time.Stamp instead of time.RFC3339.
+		//	2. Drop the hostname field from the Fprintf.
+		timestamp := time.Now().Format(time.Stamp)
+		_, err := fmt.Fprintf(n.conn, "<%d>%s %s[%d]: %s%s",
+			p, timestamp,
+			tag, os.Getpid(), msg, nl)
+		return err
+	}
+	timestamp := time.Now().Format(time.RFC3339)
+	_, err := fmt.Fprintf(n.conn, "<%d>%s %s %s[%d]: %s%s",
+		p, timestamp, hostname,
+		tag, os.Getpid(), msg, nl)
+	return err
+}
+
+func (n *netConn) close() error {
+	return n.conn.Close()
+}
+
+// NewLogger creates a log.Logger whose output is written to
+// the system log service with the specified priority. The logFlag
+// argument is the flag set passed through to log.New to create
+// the Logger.
+func NewLogger(p Priority, logFlag int) (*log.Logger, error) {
+	s, err := New(p, "")
+	if err != nil {
+		return nil, err
+	}
+	return log.New(s, "", logFlag), nil
+}
diff --git a/third_party/gofrontend/libgo/go/log/syslog/syslog_c.c b/third_party/gofrontend/libgo/go/log/syslog/syslog_c.c
new file mode 100644
index 0000000..5b33d78
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/log/syslog/syslog_c.c
@@ -0,0 +1,21 @@
+/* syslog_c.c -- call syslog for Go.
+
+   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.  */
+
+#include <syslog.h>
+
+#include "runtime.h"
+
+/* We need to use a C function to call the syslog function, because we
+   can't represent a C varargs function in Go.  */
+
+void syslog_c(intgo, const char*)
+  __asm__ (GOSYM_PREFIX "log_syslog.syslog_c");
+
+void
+syslog_c (intgo priority, const char *msg)
+{
+  syslog (priority, "%s", msg);
+}
diff --git a/third_party/gofrontend/libgo/go/log/syslog/syslog_libc.go b/third_party/gofrontend/libgo/go/log/syslog/syslog_libc.go
new file mode 100644
index 0000000..cf370ef
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/log/syslog/syslog_libc.go
@@ -0,0 +1,41 @@
+// 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.
+
+// gccgo specific implementation of syslog for Solaris.  Solaris uses
+// STREAMS to communicate with syslogd.  That is enough of a pain that
+// we just call the libc function.
+
+package syslog
+
+import (
+	"fmt"
+	"os"
+	"syscall"
+	"time"
+)
+
+func unixSyslog() (conn serverConn, err error) {
+	return libcConn(0), nil
+}
+
+type libcConn int
+
+func syslog_c(int, *byte)
+
+func (libcConn) writeString(p Priority, hostname, tag, msg, nl string) error {
+	timestamp := time.Now().Format(time.RFC3339)
+	log := fmt.Sprintf("%s %s %s[%d]: %s%s", timestamp, hostname, tag, os.Getpid(), msg, nl)
+	buf, err := syscall.BytePtrFromString(log)
+	if err != nil {
+		return err
+	}
+	syscall.Entersyscall()
+	syslog_c(int(p), buf)
+	syscall.Exitsyscall()
+	return nil
+}
+
+func (libcConn) close() error {
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/log/syslog/syslog_plan9.go b/third_party/gofrontend/libgo/go/log/syslog/syslog_plan9.go
new file mode 100644
index 0000000..0c05f6f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/log/syslog/syslog_plan9.go
@@ -0,0 +1,8 @@
+// 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 syslog provides a simple interface to the system log service.
+package syslog
+
+// BUG(akumar): This package is not implemented on Plan 9 yet.
diff --git a/third_party/gofrontend/libgo/go/log/syslog/syslog_test.go b/third_party/gofrontend/libgo/go/log/syslog/syslog_test.go
new file mode 100644
index 0000000..24a460f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/log/syslog/syslog_test.go
@@ -0,0 +1,358 @@
+// 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.
+
+// +build !windows,!nacl,!plan9
+
+package syslog
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	"os"
+	"sync"
+	"testing"
+	"time"
+)
+
+func runPktSyslog(c net.PacketConn, done chan<- string) {
+	var buf [4096]byte
+	var rcvd string
+	ct := 0
+	for {
+		var n int
+		var err error
+
+		c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		n, _, err = c.ReadFrom(buf[:])
+		rcvd += string(buf[:n])
+		if err != nil {
+			if oe, ok := err.(*net.OpError); ok {
+				if ct < 3 && oe.Temporary() {
+					ct++
+					continue
+				}
+			}
+			break
+		}
+	}
+	c.Close()
+	done <- rcvd
+}
+
+var crashy = false
+
+func runStreamSyslog(l net.Listener, done chan<- string, wg *sync.WaitGroup) {
+	for {
+		var c net.Conn
+		var err error
+		if c, err = l.Accept(); err != nil {
+			return
+		}
+		wg.Add(1)
+		go func(c net.Conn) {
+			defer wg.Done()
+			c.SetReadDeadline(time.Now().Add(5 * time.Second))
+			b := bufio.NewReader(c)
+			for ct := 1; !crashy || ct&7 != 0; ct++ {
+				s, err := b.ReadString('\n')
+				if err != nil {
+					break
+				}
+				done <- s
+			}
+			c.Close()
+		}(c)
+	}
+}
+
+func startServer(n, la string, done chan<- string) (addr string, sock io.Closer, wg *sync.WaitGroup) {
+	if n == "udp" || n == "tcp" {
+		la = "127.0.0.1:0"
+	} else {
+		// unix and unixgram: choose an address if none given
+		if la == "" {
+			// use ioutil.TempFile to get a name that is unique
+			f, err := ioutil.TempFile("", "syslogtest")
+			if err != nil {
+				log.Fatal("TempFile: ", err)
+			}
+			f.Close()
+			la = f.Name()
+		}
+		os.Remove(la)
+	}
+
+	wg = new(sync.WaitGroup)
+	if n == "udp" || n == "unixgram" {
+		l, e := net.ListenPacket(n, la)
+		if e != nil {
+			log.Fatalf("startServer failed: %v", e)
+		}
+		addr = l.LocalAddr().String()
+		sock = l
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			runPktSyslog(l, done)
+		}()
+	} else {
+		l, e := net.Listen(n, la)
+		if e != nil {
+			log.Fatalf("startServer failed: %v", e)
+		}
+		addr = l.Addr().String()
+		sock = l
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			runStreamSyslog(l, done, wg)
+		}()
+	}
+	return
+}
+
+func TestWithSimulated(t *testing.T) {
+	msg := "Test 123"
+	transport := []string{"unix", "unixgram", "udp", "tcp"}
+
+	for _, tr := range transport {
+		done := make(chan string)
+		addr, sock, srvWG := startServer(tr, "", done)
+		defer srvWG.Wait()
+		defer sock.Close()
+		if tr == "unix" || tr == "unixgram" {
+			defer os.Remove(addr)
+		}
+		s, err := Dial(tr, addr, LOG_INFO|LOG_USER, "syslog_test")
+		if err != nil {
+			t.Fatalf("Dial() failed: %v", err)
+		}
+		err = s.Info(msg)
+		if err != nil {
+			t.Fatalf("log failed: %v", err)
+		}
+		check(t, msg, <-done)
+		s.Close()
+	}
+}
+
+func TestFlap(t *testing.T) {
+	net := "unix"
+	done := make(chan string)
+	addr, sock, srvWG := startServer(net, "", done)
+	defer srvWG.Wait()
+	defer os.Remove(addr)
+	defer sock.Close()
+
+	s, err := Dial(net, addr, LOG_INFO|LOG_USER, "syslog_test")
+	if err != nil {
+		t.Fatalf("Dial() failed: %v", err)
+	}
+	msg := "Moo 2"
+	err = s.Info(msg)
+	if err != nil {
+		t.Fatalf("log failed: %v", err)
+	}
+	check(t, msg, <-done)
+
+	// restart the server
+	_, sock2, srvWG2 := startServer(net, addr, done)
+	defer srvWG2.Wait()
+	defer sock2.Close()
+
+	// and try retransmitting
+	msg = "Moo 3"
+	err = s.Info(msg)
+	if err != nil {
+		t.Fatalf("log failed: %v", err)
+	}
+	check(t, msg, <-done)
+
+	s.Close()
+}
+
+func TestNew(t *testing.T) {
+	if LOG_LOCAL7 != 23<<3 {
+		t.Fatalf("LOG_LOCAL7 has wrong value")
+	}
+	if testing.Short() {
+		// Depends on syslog daemon running, and sometimes it's not.
+		t.Skip("skipping syslog test during -short")
+	}
+
+	s, err := New(LOG_INFO|LOG_USER, "the_tag")
+	if err != nil {
+		t.Fatalf("New() failed: %s", err)
+	}
+	// Don't send any messages.
+	s.Close()
+}
+
+func TestNewLogger(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping syslog test during -short")
+	}
+	f, err := NewLogger(LOG_USER|LOG_INFO, 0)
+	if f == nil {
+		t.Error(err)
+	}
+}
+
+func TestDial(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping syslog test during -short")
+	}
+	f, err := Dial("", "", (LOG_LOCAL7|LOG_DEBUG)+1, "syslog_test")
+	if f != nil {
+		t.Fatalf("Should have trapped bad priority")
+	}
+	f, err = Dial("", "", -1, "syslog_test")
+	if f != nil {
+		t.Fatalf("Should have trapped bad priority")
+	}
+	l, err := Dial("", "", LOG_USER|LOG_ERR, "syslog_test")
+	if err != nil {
+		t.Fatalf("Dial() failed: %s", err)
+	}
+	l.Close()
+}
+
+func check(t *testing.T, in, out string) {
+	tmpl := fmt.Sprintf("<%d>%%s %%s syslog_test[%%d]: %s\n", LOG_USER+LOG_INFO, in)
+	if hostname, err := os.Hostname(); err != nil {
+		t.Error("Error retrieving hostname")
+	} else {
+		var parsedHostname, timestamp string
+		var pid int
+		if n, err := fmt.Sscanf(out, tmpl, &timestamp, &parsedHostname, &pid); n != 3 || err != nil || hostname != parsedHostname {
+			t.Errorf("Got %q, does not match template %q (%d %s)", out, tmpl, n, err)
+		}
+	}
+}
+
+func TestWrite(t *testing.T) {
+	tests := []struct {
+		pri Priority
+		pre string
+		msg string
+		exp string
+	}{
+		{LOG_USER | LOG_ERR, "syslog_test", "", "%s %s syslog_test[%d]: \n"},
+		{LOG_USER | LOG_ERR, "syslog_test", "write test", "%s %s syslog_test[%d]: write test\n"},
+		// Write should not add \n if there already is one
+		{LOG_USER | LOG_ERR, "syslog_test", "write test 2\n", "%s %s syslog_test[%d]: write test 2\n"},
+	}
+
+	if hostname, err := os.Hostname(); err != nil {
+		t.Fatalf("Error retrieving hostname")
+	} else {
+		for _, test := range tests {
+			done := make(chan string)
+			addr, sock, srvWG := startServer("udp", "", done)
+			defer srvWG.Wait()
+			defer sock.Close()
+			l, err := Dial("udp", addr, test.pri, test.pre)
+			if err != nil {
+				t.Fatalf("syslog.Dial() failed: %v", err)
+			}
+			defer l.Close()
+			_, err = io.WriteString(l, test.msg)
+			if err != nil {
+				t.Fatalf("WriteString() failed: %v", err)
+			}
+			rcvd := <-done
+			test.exp = fmt.Sprintf("<%d>", test.pri) + test.exp
+			var parsedHostname, timestamp string
+			var pid int
+			if n, err := fmt.Sscanf(rcvd, test.exp, &timestamp, &parsedHostname, &pid); n != 3 || err != nil || hostname != parsedHostname {
+				t.Errorf("s.Info() = '%q', didn't match '%q' (%d %s)", rcvd, test.exp, n, err)
+			}
+		}
+	}
+}
+
+func TestConcurrentWrite(t *testing.T) {
+	addr, sock, srvWG := startServer("udp", "", make(chan string, 1))
+	defer srvWG.Wait()
+	defer sock.Close()
+	w, err := Dial("udp", addr, LOG_USER|LOG_ERR, "how's it going?")
+	if err != nil {
+		t.Fatalf("syslog.Dial() failed: %v", err)
+	}
+	var wg sync.WaitGroup
+	for i := 0; i < 10; i++ {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			err := w.Info("test")
+			if err != nil {
+				t.Errorf("Info() failed: %v", err)
+				return
+			}
+		}()
+	}
+	wg.Wait()
+}
+
+func TestConcurrentReconnect(t *testing.T) {
+	crashy = true
+	defer func() { crashy = false }()
+
+	const N = 10
+	const M = 100
+	net := "unix"
+	done := make(chan string, N*M)
+	addr, sock, srvWG := startServer(net, "", done)
+	defer os.Remove(addr)
+
+	// count all the messages arriving
+	count := make(chan int)
+	go func() {
+		ct := 0
+		for _ = range done {
+			ct++
+			// we are looking for 500 out of 1000 events
+			// here because lots of log messages are lost
+			// in buffers (kernel and/or bufio)
+			if ct > N*M/2 {
+				break
+			}
+		}
+		count <- ct
+	}()
+
+	var wg sync.WaitGroup
+	wg.Add(N)
+	for i := 0; i < N; i++ {
+		go func() {
+			defer wg.Done()
+			w, err := Dial(net, addr, LOG_USER|LOG_ERR, "tag")
+			if err != nil {
+				t.Fatalf("syslog.Dial() failed: %v", err)
+			}
+			defer w.Close()
+			for i := 0; i < M; i++ {
+				err := w.Info("test")
+				if err != nil {
+					t.Errorf("Info() failed: %v", err)
+					return
+				}
+			}
+		}()
+	}
+	wg.Wait()
+	sock.Close()
+	srvWG.Wait()
+	close(done)
+
+	select {
+	case <-count:
+	case <-time.After(100 * time.Millisecond):
+		t.Error("timeout in concurrent reconnect")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/log/syslog/syslog_unix.go b/third_party/gofrontend/libgo/go/log/syslog/syslog_unix.go
new file mode 100644
index 0000000..f6d2f1b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/log/syslog/syslog_unix.go
@@ -0,0 +1,31 @@
+// 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.
+
+// +build !windows,!nacl,!plan9
+
+package syslog
+
+import (
+	"errors"
+	"net"
+)
+
+// unixSyslog opens a connection to the syslog daemon running on the
+// local machine using a Unix domain socket.
+
+func unixSyslog() (conn serverConn, err error) {
+	logTypes := []string{"unixgram", "unix"}
+	logPaths := []string{"/dev/log", "/var/run/syslog"}
+	for _, network := range logTypes {
+		for _, path := range logPaths {
+			conn, err := net.Dial(network, path)
+			if err != nil {
+				continue
+			} else {
+				return &netConn{conn: conn, local: true}, nil
+			}
+		}
+	}
+	return nil, errors.New("Unix syslog delivery error")
+}
diff --git a/third_party/gofrontend/libgo/go/log/syslog/syslog_windows.go b/third_party/gofrontend/libgo/go/log/syslog/syslog_windows.go
new file mode 100644
index 0000000..8d99e2e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/log/syslog/syslog_windows.go
@@ -0,0 +1,8 @@
+// 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 syslog provides a simple interface to the system log service.
+package syslog
+
+// BUG(brainman): This package is not implemented on Windows yet.
diff --git a/third_party/gofrontend/libgo/go/math/abs.go b/third_party/gofrontend/libgo/go/math/abs.go
new file mode 100644
index 0000000..433d0f7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/abs.go
@@ -0,0 +1,28 @@
+// 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 math
+
+// Abs returns the absolute value of x.
+//
+// Special cases are:
+//	Abs(±Inf) = +Inf
+//	Abs(NaN) = NaN
+
+//extern fabs
+func libc_fabs(float64) float64
+
+func Abs(x float64) float64 {
+	return libc_fabs(x)
+}
+
+func abs(x float64) float64 {
+	switch {
+	case x < 0:
+		return -x
+	case x == 0:
+		return 0 // return correctly abs(-0)
+	}
+	return x
+}
diff --git a/third_party/gofrontend/libgo/go/math/acosh.go b/third_party/gofrontend/libgo/go/math/acosh.go
new file mode 100644
index 0000000..e394008
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/acosh.go
@@ -0,0 +1,60 @@
+// Copyright 2010 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 math
+
+// The original C code, the long comment, and the constants
+// below are from FreeBSD's /usr/src/lib/msun/src/e_acosh.c
+// and came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+//
+// __ieee754_acosh(x)
+// Method :
+//	Based on
+//	        acosh(x) = log [ x + sqrt(x*x-1) ]
+//	we have
+//	        acosh(x) := log(x)+ln2,	if x is large; else
+//	        acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
+//	        acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
+//
+// Special cases:
+//	acosh(x) is NaN with signal if x<1.
+//	acosh(NaN) is NaN without signal.
+//
+
+// Acosh returns the inverse hyperbolic cosine of x.
+//
+// Special cases are:
+//	Acosh(+Inf) = +Inf
+//	Acosh(x) = NaN if x < 1
+//	Acosh(NaN) = NaN
+func Acosh(x float64) float64 {
+	const (
+		Ln2   = 6.93147180559945286227e-01 // 0x3FE62E42FEFA39EF
+		Large = 1 << 28                    // 2**28
+	)
+	// first case is special case
+	switch {
+	case x < 1 || IsNaN(x):
+		return NaN()
+	case x == 1:
+		return 0
+	case x >= Large:
+		return Log(x) + Ln2 // x > 2**28
+	case x > 2:
+		return Log(2*x - 1/(x+Sqrt(x*x-1))) // 2**28 > x > 2
+	}
+	t := x - 1
+	return Log1p(t + Sqrt(2*t+t*t)) // 2 >= x > 1
+}
diff --git a/third_party/gofrontend/libgo/go/math/all_test.go b/third_party/gofrontend/libgo/go/math/all_test.go
new file mode 100644
index 0000000..0d8b10f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/all_test.go
@@ -0,0 +1,2935 @@
+// 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 math_test
+
+import (
+	"fmt"
+	. "math"
+	"testing"
+)
+
+var vf = []float64{
+	4.9790119248836735e+00,
+	7.7388724745781045e+00,
+	-2.7688005719200159e-01,
+	-5.0106036182710749e+00,
+	9.6362937071984173e+00,
+	2.9263772392439646e+00,
+	5.2290834314593066e+00,
+	2.7279399104360102e+00,
+	1.8253080916808550e+00,
+	-8.6859247685756013e+00,
+}
+
+// The expected results below were computed by the high precision calculators
+// at http://keisan.casio.com/.  More exact input values (array vf[], above)
+// were obtained by printing them with "%.26f".  The answers were calculated
+// to 26 digits (by using the "Digit number" drop-down control of each
+// calculator).
+var acos = []float64{
+	1.0496193546107222142571536e+00,
+	6.8584012813664425171660692e-01,
+	1.5984878714577160325521819e+00,
+	2.0956199361475859327461799e+00,
+	2.7053008467824138592616927e-01,
+	1.2738121680361776018155625e+00,
+	1.0205369421140629186287407e+00,
+	1.2945003481781246062157835e+00,
+	1.3872364345374451433846657e+00,
+	2.6231510803970463967294145e+00,
+}
+var acosh = []float64{
+	2.4743347004159012494457618e+00,
+	2.8576385344292769649802701e+00,
+	7.2796961502981066190593175e-01,
+	2.4796794418831451156471977e+00,
+	3.0552020742306061857212962e+00,
+	2.044238592688586588942468e+00,
+	2.5158701513104513595766636e+00,
+	1.99050839282411638174299e+00,
+	1.6988625798424034227205445e+00,
+	2.9611454842470387925531875e+00,
+}
+var asin = []float64{
+	5.2117697218417440497416805e-01,
+	8.8495619865825236751471477e-01,
+	-02.769154466281941332086016e-02,
+	-5.2482360935268931351485822e-01,
+	1.3002662421166552333051524e+00,
+	2.9698415875871901741575922e-01,
+	5.5025938468083370060258102e-01,
+	2.7629597861677201301553823e-01,
+	1.83559892257451475846656e-01,
+	-1.0523547536021497774980928e+00,
+}
+var asinh = []float64{
+	2.3083139124923523427628243e+00,
+	2.743551594301593620039021e+00,
+	-2.7345908534880091229413487e-01,
+	-2.3145157644718338650499085e+00,
+	2.9613652154015058521951083e+00,
+	1.7949041616585821933067568e+00,
+	2.3564032905983506405561554e+00,
+	1.7287118790768438878045346e+00,
+	1.3626658083714826013073193e+00,
+	-2.8581483626513914445234004e+00,
+}
+var atan = []float64{
+	1.372590262129621651920085e+00,
+	1.442290609645298083020664e+00,
+	-2.7011324359471758245192595e-01,
+	-1.3738077684543379452781531e+00,
+	1.4673921193587666049154681e+00,
+	1.2415173565870168649117764e+00,
+	1.3818396865615168979966498e+00,
+	1.2194305844639670701091426e+00,
+	1.0696031952318783760193244e+00,
+	-1.4561721938838084990898679e+00,
+}
+var atanh = []float64{
+	5.4651163712251938116878204e-01,
+	1.0299474112843111224914709e+00,
+	-2.7695084420740135145234906e-02,
+	-5.5072096119207195480202529e-01,
+	1.9943940993171843235906642e+00,
+	3.01448604578089708203017e-01,
+	5.8033427206942188834370595e-01,
+	2.7987997499441511013958297e-01,
+	1.8459947964298794318714228e-01,
+	-1.3273186910532645867272502e+00,
+}
+var atan2 = []float64{
+	1.1088291730037004444527075e+00,
+	9.1218183188715804018797795e-01,
+	1.5984772603216203736068915e+00,
+	2.0352918654092086637227327e+00,
+	8.0391819139044720267356014e-01,
+	1.2861075249894661588866752e+00,
+	1.0889904479131695712182587e+00,
+	1.3044821793397925293797357e+00,
+	1.3902530903455392306872261e+00,
+	2.2859857424479142655411058e+00,
+}
+var cbrt = []float64{
+	1.7075799841925094446722675e+00,
+	1.9779982212970353936691498e+00,
+	-6.5177429017779910853339447e-01,
+	-1.7111838886544019873338113e+00,
+	2.1279920909827937423960472e+00,
+	1.4303536770460741452312367e+00,
+	1.7357021059106154902341052e+00,
+	1.3972633462554328350552916e+00,
+	1.2221149580905388454977636e+00,
+	-2.0556003730500069110343596e+00,
+}
+var ceil = []float64{
+	5.0000000000000000e+00,
+	8.0000000000000000e+00,
+	0.0000000000000000e+00,
+	-5.0000000000000000e+00,
+	1.0000000000000000e+01,
+	3.0000000000000000e+00,
+	6.0000000000000000e+00,
+	3.0000000000000000e+00,
+	2.0000000000000000e+00,
+	-8.0000000000000000e+00,
+}
+var copysign = []float64{
+	-4.9790119248836735e+00,
+	-7.7388724745781045e+00,
+	-2.7688005719200159e-01,
+	-5.0106036182710749e+00,
+	-9.6362937071984173e+00,
+	-2.9263772392439646e+00,
+	-5.2290834314593066e+00,
+	-2.7279399104360102e+00,
+	-1.8253080916808550e+00,
+	-8.6859247685756013e+00,
+}
+var cos = []float64{
+	2.634752140995199110787593e-01,
+	1.148551260848219865642039e-01,
+	9.6191297325640768154550453e-01,
+	2.938141150061714816890637e-01,
+	-9.777138189897924126294461e-01,
+	-9.7693041344303219127199518e-01,
+	4.940088096948647263961162e-01,
+	-9.1565869021018925545016502e-01,
+	-2.517729313893103197176091e-01,
+	-7.39241351595676573201918e-01,
+}
+
+// Results for 100000 * Pi + vf[i]
+var cosLarge = []float64{
+	2.634752141185559426744e-01,
+	1.14855126055543100712e-01,
+	9.61912973266488928113e-01,
+	2.9381411499556122552e-01,
+	-9.777138189880161924641e-01,
+	-9.76930413445147608049e-01,
+	4.940088097314976789841e-01,
+	-9.15658690217517835002e-01,
+	-2.51772931436786954751e-01,
+	-7.3924135157173099849e-01,
+}
+var cosh = []float64{
+	7.2668796942212842775517446e+01,
+	1.1479413465659254502011135e+03,
+	1.0385767908766418550935495e+00,
+	7.5000957789658051428857788e+01,
+	7.655246669605357888468613e+03,
+	9.3567491758321272072888257e+00,
+	9.331351599270605471131735e+01,
+	7.6833430994624643209296404e+00,
+	3.1829371625150718153881164e+00,
+	2.9595059261916188501640911e+03,
+}
+var erf = []float64{
+	5.1865354817738701906913566e-01,
+	7.2623875834137295116929844e-01,
+	-3.123458688281309990629839e-02,
+	-5.2143121110253302920437013e-01,
+	8.2704742671312902508629582e-01,
+	3.2101767558376376743993945e-01,
+	5.403990312223245516066252e-01,
+	3.0034702916738588551174831e-01,
+	2.0369924417882241241559589e-01,
+	-7.8069386968009226729944677e-01,
+}
+var erfc = []float64{
+	4.8134645182261298093086434e-01,
+	2.7376124165862704883070156e-01,
+	1.0312345868828130999062984e+00,
+	1.5214312111025330292043701e+00,
+	1.7295257328687097491370418e-01,
+	6.7898232441623623256006055e-01,
+	4.596009687776754483933748e-01,
+	6.9965297083261411448825169e-01,
+	7.9630075582117758758440411e-01,
+	1.7806938696800922672994468e+00,
+}
+var exp = []float64{
+	1.4533071302642137507696589e+02,
+	2.2958822575694449002537581e+03,
+	7.5814542574851666582042306e-01,
+	6.6668778421791005061482264e-03,
+	1.5310493273896033740861206e+04,
+	1.8659907517999328638667732e+01,
+	1.8662167355098714543942057e+02,
+	1.5301332413189378961665788e+01,
+	6.2047063430646876349125085e+00,
+	1.6894712385826521111610438e-04,
+}
+var expm1 = []float64{
+	5.105047796122957327384770212e-02,
+	8.046199708567344080562675439e-02,
+	-2.764970978891639815187418703e-03,
+	-4.8871434888875355394330300273e-02,
+	1.0115864277221467777117227494e-01,
+	2.969616407795910726014621657e-02,
+	5.368214487944892300914037972e-02,
+	2.765488851131274068067445335e-02,
+	1.842068661871398836913874273e-02,
+	-8.3193870863553801814961137573e-02,
+}
+var exp2 = []float64{
+	3.1537839463286288034313104e+01,
+	2.1361549283756232296144849e+02,
+	8.2537402562185562902577219e-01,
+	3.1021158628740294833424229e-02,
+	7.9581744110252191462569661e+02,
+	7.6019905892596359262696423e+00,
+	3.7506882048388096973183084e+01,
+	6.6250893439173561733216375e+00,
+	3.5438267900243941544605339e+00,
+	2.4281533133513300984289196e-03,
+}
+var fabs = []float64{
+	4.9790119248836735e+00,
+	7.7388724745781045e+00,
+	2.7688005719200159e-01,
+	5.0106036182710749e+00,
+	9.6362937071984173e+00,
+	2.9263772392439646e+00,
+	5.2290834314593066e+00,
+	2.7279399104360102e+00,
+	1.8253080916808550e+00,
+	8.6859247685756013e+00,
+}
+var fdim = []float64{
+	4.9790119248836735e+00,
+	7.7388724745781045e+00,
+	0.0000000000000000e+00,
+	0.0000000000000000e+00,
+	9.6362937071984173e+00,
+	2.9263772392439646e+00,
+	5.2290834314593066e+00,
+	2.7279399104360102e+00,
+	1.8253080916808550e+00,
+	0.0000000000000000e+00,
+}
+var floor = []float64{
+	4.0000000000000000e+00,
+	7.0000000000000000e+00,
+	-1.0000000000000000e+00,
+	-6.0000000000000000e+00,
+	9.0000000000000000e+00,
+	2.0000000000000000e+00,
+	5.0000000000000000e+00,
+	2.0000000000000000e+00,
+	1.0000000000000000e+00,
+	-9.0000000000000000e+00,
+}
+var fmod = []float64{
+	4.197615023265299782906368e-02,
+	2.261127525421895434476482e+00,
+	3.231794108794261433104108e-02,
+	4.989396381728925078391512e+00,
+	3.637062928015826201999516e-01,
+	1.220868282268106064236690e+00,
+	4.770916568540693347699744e+00,
+	1.816180268691969246219742e+00,
+	8.734595415957246977711748e-01,
+	1.314075231424398637614104e+00,
+}
+
+type fi struct {
+	f float64
+	i int
+}
+
+var frexp = []fi{
+	{6.2237649061045918750e-01, 3},
+	{9.6735905932226306250e-01, 3},
+	{-5.5376011438400318000e-01, -1},
+	{-6.2632545228388436250e-01, 3},
+	{6.02268356699901081250e-01, 4},
+	{7.3159430981099115000e-01, 2},
+	{6.5363542893241332500e-01, 3},
+	{6.8198497760900255000e-01, 2},
+	{9.1265404584042750000e-01, 1},
+	{-5.4287029803597508250e-01, 4},
+}
+var gamma = []float64{
+	2.3254348370739963835386613898e+01,
+	2.991153837155317076427529816e+03,
+	-4.561154336726758060575129109e+00,
+	7.719403468842639065959210984e-01,
+	1.6111876618855418534325755566e+05,
+	1.8706575145216421164173224946e+00,
+	3.4082787447257502836734201635e+01,
+	1.579733951448952054898583387e+00,
+	9.3834586598354592860187267089e-01,
+	-2.093995902923148389186189429e-05,
+}
+var j0 = []float64{
+	-1.8444682230601672018219338e-01,
+	2.27353668906331975435892e-01,
+	9.809259936157051116270273e-01,
+	-1.741170131426226587841181e-01,
+	-2.1389448451144143352039069e-01,
+	-2.340905848928038763337414e-01,
+	-1.0029099691890912094586326e-01,
+	-1.5466726714884328135358907e-01,
+	3.252650187653420388714693e-01,
+	-8.72218484409407250005360235e-03,
+}
+var j1 = []float64{
+	-3.251526395295203422162967e-01,
+	1.893581711430515718062564e-01,
+	-1.3711761352467242914491514e-01,
+	3.287486536269617297529617e-01,
+	1.3133899188830978473849215e-01,
+	3.660243417832986825301766e-01,
+	-3.4436769271848174665420672e-01,
+	4.329481396640773768835036e-01,
+	5.8181350531954794639333955e-01,
+	-2.7030574577733036112996607e-01,
+}
+var j2 = []float64{
+	5.3837518920137802565192769e-02,
+	-1.7841678003393207281244667e-01,
+	9.521746934916464142495821e-03,
+	4.28958355470987397983072e-02,
+	2.4115371837854494725492872e-01,
+	4.842458532394520316844449e-01,
+	-3.142145220618633390125946e-02,
+	4.720849184745124761189957e-01,
+	3.122312022520957042957497e-01,
+	7.096213118930231185707277e-02,
+}
+var jM3 = []float64{
+	-3.684042080996403091021151e-01,
+	2.8157665936340887268092661e-01,
+	4.401005480841948348343589e-04,
+	3.629926999056814081597135e-01,
+	3.123672198825455192489266e-02,
+	-2.958805510589623607540455e-01,
+	-3.2033177696533233403289416e-01,
+	-2.592737332129663376736604e-01,
+	-1.0241334641061485092351251e-01,
+	-2.3762660886100206491674503e-01,
+}
+var lgamma = []fi{
+	{3.146492141244545774319734e+00, 1},
+	{8.003414490659126375852113e+00, 1},
+	{1.517575735509779707488106e+00, -1},
+	{-2.588480028182145853558748e-01, 1},
+	{1.1989897050205555002007985e+01, 1},
+	{6.262899811091257519386906e-01, 1},
+	{3.5287924899091566764846037e+00, 1},
+	{4.5725644770161182299423372e-01, 1},
+	{-6.363667087767961257654854e-02, 1},
+	{-1.077385130910300066425564e+01, -1},
+}
+var log = []float64{
+	1.605231462693062999102599e+00,
+	2.0462560018708770653153909e+00,
+	-1.2841708730962657801275038e+00,
+	1.6115563905281545116286206e+00,
+	2.2655365644872016636317461e+00,
+	1.0737652208918379856272735e+00,
+	1.6542360106073546632707956e+00,
+	1.0035467127723465801264487e+00,
+	6.0174879014578057187016475e-01,
+	2.161703872847352815363655e+00,
+}
+var logb = []float64{
+	2.0000000000000000e+00,
+	2.0000000000000000e+00,
+	-2.0000000000000000e+00,
+	2.0000000000000000e+00,
+	3.0000000000000000e+00,
+	1.0000000000000000e+00,
+	2.0000000000000000e+00,
+	1.0000000000000000e+00,
+	0.0000000000000000e+00,
+	3.0000000000000000e+00,
+}
+var log10 = []float64{
+	6.9714316642508290997617083e-01,
+	8.886776901739320576279124e-01,
+	-5.5770832400658929815908236e-01,
+	6.998900476822994346229723e-01,
+	9.8391002850684232013281033e-01,
+	4.6633031029295153334285302e-01,
+	7.1842557117242328821552533e-01,
+	4.3583479968917773161304553e-01,
+	2.6133617905227038228626834e-01,
+	9.3881606348649405716214241e-01,
+}
+var log1p = []float64{
+	4.8590257759797794104158205e-02,
+	7.4540265965225865330849141e-02,
+	-2.7726407903942672823234024e-03,
+	-5.1404917651627649094953380e-02,
+	9.1998280672258624681335010e-02,
+	2.8843762576593352865894824e-02,
+	5.0969534581863707268992645e-02,
+	2.6913947602193238458458594e-02,
+	1.8088493239630770262045333e-02,
+	-9.0865245631588989681559268e-02,
+}
+var log2 = []float64{
+	2.3158594707062190618898251e+00,
+	2.9521233862883917703341018e+00,
+	-1.8526669502700329984917062e+00,
+	2.3249844127278861543568029e+00,
+	3.268478366538305087466309e+00,
+	1.5491157592596970278166492e+00,
+	2.3865580889631732407886495e+00,
+	1.447811865817085365540347e+00,
+	8.6813999540425116282815557e-01,
+	3.118679457227342224364709e+00,
+}
+var modf = [][2]float64{
+	{4.0000000000000000e+00, 9.7901192488367350108546816e-01},
+	{7.0000000000000000e+00, 7.3887247457810456552351752e-01},
+	{0.0000000000000000e+00, -2.7688005719200159404635997e-01},
+	{-5.0000000000000000e+00, -1.060361827107492160848778e-02},
+	{9.0000000000000000e+00, 6.3629370719841737980004837e-01},
+	{2.0000000000000000e+00, 9.2637723924396464525443662e-01},
+	{5.0000000000000000e+00, 2.2908343145930665230025625e-01},
+	{2.0000000000000000e+00, 7.2793991043601025126008608e-01},
+	{1.0000000000000000e+00, 8.2530809168085506044576505e-01},
+	{-8.0000000000000000e+00, -6.8592476857560136238589621e-01},
+}
+var nextafter = []float64{
+	4.97901192488367438926388786e+00,
+	7.73887247457810545370193722e+00,
+	-2.7688005719200153853520874e-01,
+	-5.01060361827107403343006808e+00,
+	9.63629370719841915615688777e+00,
+	2.92637723924396508934364647e+00,
+	5.22908343145930754047867595e+00,
+	2.72793991043601069534929593e+00,
+	1.82530809168085528249036997e+00,
+	-8.68592476857559958602905681e+00,
+}
+var pow = []float64{
+	9.5282232631648411840742957e+04,
+	5.4811599352999901232411871e+07,
+	5.2859121715894396531132279e-01,
+	9.7587991957286474464259698e-06,
+	4.328064329346044846740467e+09,
+	8.4406761805034547437659092e+02,
+	1.6946633276191194947742146e+05,
+	5.3449040147551939075312879e+02,
+	6.688182138451414936380374e+01,
+	2.0609869004248742886827439e-09,
+}
+var remainder = []float64{
+	4.197615023265299782906368e-02,
+	2.261127525421895434476482e+00,
+	3.231794108794261433104108e-02,
+	-2.120723654214984321697556e-02,
+	3.637062928015826201999516e-01,
+	1.220868282268106064236690e+00,
+	-4.581668629186133046005125e-01,
+	-9.117596417440410050403443e-01,
+	8.734595415957246977711748e-01,
+	1.314075231424398637614104e+00,
+}
+var signbit = []bool{
+	false,
+	false,
+	true,
+	true,
+	false,
+	false,
+	false,
+	false,
+	false,
+	true,
+}
+var sin = []float64{
+	-9.6466616586009283766724726e-01,
+	9.9338225271646545763467022e-01,
+	-2.7335587039794393342449301e-01,
+	9.5586257685042792878173752e-01,
+	-2.099421066779969164496634e-01,
+	2.135578780799860532750616e-01,
+	-8.694568971167362743327708e-01,
+	4.019566681155577786649878e-01,
+	9.6778633541687993721617774e-01,
+	-6.734405869050344734943028e-01,
+}
+
+// Results for 100000 * Pi + vf[i]
+var sinLarge = []float64{
+	-9.646661658548936063912e-01,
+	9.933822527198506903752e-01,
+	-2.7335587036246899796e-01,
+	9.55862576853689321268e-01,
+	-2.099421066862688873691e-01,
+	2.13557878070308981163e-01,
+	-8.694568970959221300497e-01,
+	4.01956668098863248917e-01,
+	9.67786335404528727927e-01,
+	-6.7344058693131973066e-01,
+}
+var sinh = []float64{
+	7.2661916084208532301448439e+01,
+	1.1479409110035194500526446e+03,
+	-2.8043136512812518927312641e-01,
+	-7.499429091181587232835164e+01,
+	7.6552466042906758523925934e+03,
+	9.3031583421672014313789064e+00,
+	9.330815755828109072810322e+01,
+	7.6179893137269146407361477e+00,
+	3.021769180549615819524392e+00,
+	-2.95950575724449499189888e+03,
+}
+var sqrt = []float64{
+	2.2313699659365484748756904e+00,
+	2.7818829009464263511285458e+00,
+	5.2619393496314796848143251e-01,
+	2.2384377628763938724244104e+00,
+	3.1042380236055381099288487e+00,
+	1.7106657298385224403917771e+00,
+	2.286718922705479046148059e+00,
+	1.6516476350711159636222979e+00,
+	1.3510396336454586262419247e+00,
+	2.9471892997524949215723329e+00,
+}
+var tan = []float64{
+	-3.661316565040227801781974e+00,
+	8.64900232648597589369854e+00,
+	-2.8417941955033612725238097e-01,
+	3.253290185974728640827156e+00,
+	2.147275640380293804770778e-01,
+	-2.18600910711067004921551e-01,
+	-1.760002817872367935518928e+00,
+	-4.389808914752818126249079e-01,
+	-3.843885560201130679995041e+00,
+	9.10988793377685105753416e-01,
+}
+
+// Results for 100000 * Pi + vf[i]
+var tanLarge = []float64{
+	-3.66131656475596512705e+00,
+	8.6490023287202547927e+00,
+	-2.841794195104782406e-01,
+	3.2532901861033120983e+00,
+	2.14727564046880001365e-01,
+	-2.18600910700688062874e-01,
+	-1.760002817699722747043e+00,
+	-4.38980891453536115952e-01,
+	-3.84388555942723509071e+00,
+	9.1098879344275101051e-01,
+}
+var tanh = []float64{
+	9.9990531206936338549262119e-01,
+	9.9999962057085294197613294e-01,
+	-2.7001505097318677233756845e-01,
+	-9.9991110943061718603541401e-01,
+	9.9999999146798465745022007e-01,
+	9.9427249436125236705001048e-01,
+	9.9994257600983138572705076e-01,
+	9.9149409509772875982054701e-01,
+	9.4936501296239685514466577e-01,
+	-9.9999994291374030946055701e-01,
+}
+var trunc = []float64{
+	4.0000000000000000e+00,
+	7.0000000000000000e+00,
+	-0.0000000000000000e+00,
+	-5.0000000000000000e+00,
+	9.0000000000000000e+00,
+	2.0000000000000000e+00,
+	5.0000000000000000e+00,
+	2.0000000000000000e+00,
+	1.0000000000000000e+00,
+	-8.0000000000000000e+00,
+}
+var y0 = []float64{
+	-3.053399153780788357534855e-01,
+	1.7437227649515231515503649e-01,
+	-8.6221781263678836910392572e-01,
+	-3.100664880987498407872839e-01,
+	1.422200649300982280645377e-01,
+	4.000004067997901144239363e-01,
+	-3.3340749753099352392332536e-01,
+	4.5399790746668954555205502e-01,
+	4.8290004112497761007536522e-01,
+	2.7036697826604756229601611e-01,
+}
+var y1 = []float64{
+	0.15494213737457922210218611,
+	-0.2165955142081145245075746,
+	-2.4644949631241895201032829,
+	0.1442740489541836405154505,
+	0.2215379960518984777080163,
+	0.3038800915160754150565448,
+	0.0691107642452362383808547,
+	0.2380116417809914424860165,
+	-0.20849492979459761009678934,
+	0.0242503179793232308250804,
+}
+var y2 = []float64{
+	0.3675780219390303613394936,
+	-0.23034826393250119879267257,
+	-16.939677983817727205631397,
+	0.367653980523052152867791,
+	-0.0962401471767804440353136,
+	-0.1923169356184851105200523,
+	0.35984072054267882391843766,
+	-0.2794987252299739821654982,
+	-0.7113490692587462579757954,
+	-0.2647831587821263302087457,
+}
+var yM3 = []float64{
+	-0.14035984421094849100895341,
+	-0.097535139617792072703973,
+	242.25775994555580176377379,
+	-0.1492267014802818619511046,
+	0.26148702629155918694500469,
+	0.56675383593895176530394248,
+	-0.206150264009006981070575,
+	0.64784284687568332737963658,
+	1.3503631555901938037008443,
+	0.1461869756579956803341844,
+}
+
+// arguments and expected results for special cases
+var vfacosSC = []float64{
+	-Pi,
+	1,
+	Pi,
+	NaN(),
+}
+var acosSC = []float64{
+	NaN(),
+	0,
+	NaN(),
+	NaN(),
+}
+
+var vfacoshSC = []float64{
+	Inf(-1),
+	0.5,
+	1,
+	Inf(1),
+	NaN(),
+}
+var acoshSC = []float64{
+	NaN(),
+	NaN(),
+	0,
+	Inf(1),
+	NaN(),
+}
+
+var vfasinSC = []float64{
+	-Pi,
+	Copysign(0, -1),
+	0,
+	Pi,
+	NaN(),
+}
+var asinSC = []float64{
+	NaN(),
+	Copysign(0, -1),
+	0,
+	NaN(),
+	NaN(),
+}
+
+var vfasinhSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var asinhSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+
+var vfatanSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var atanSC = []float64{
+	-Pi / 2,
+	Copysign(0, -1),
+	0,
+	Pi / 2,
+	NaN(),
+}
+
+var vfatanhSC = []float64{
+	Inf(-1),
+	-Pi,
+	-1,
+	Copysign(0, -1),
+	0,
+	1,
+	Pi,
+	Inf(1),
+	NaN(),
+}
+var atanhSC = []float64{
+	NaN(),
+	NaN(),
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+	NaN(),
+	NaN(),
+}
+var vfatan2SC = [][2]float64{
+	{Inf(-1), Inf(-1)},
+	{Inf(-1), -Pi},
+	{Inf(-1), 0},
+	{Inf(-1), +Pi},
+	{Inf(-1), Inf(1)},
+	{Inf(-1), NaN()},
+	{-Pi, Inf(-1)},
+	{-Pi, 0},
+	{-Pi, Inf(1)},
+	{-Pi, NaN()},
+	{Copysign(0, -1), Inf(-1)},
+	{Copysign(0, -1), -Pi},
+	{Copysign(0, -1), Copysign(0, -1)},
+	{Copysign(0, -1), 0},
+	{Copysign(0, -1), +Pi},
+	{Copysign(0, -1), Inf(1)},
+	{Copysign(0, -1), NaN()},
+	{0, Inf(-1)},
+	{0, -Pi},
+	{0, Copysign(0, -1)},
+	{0, 0},
+	{0, +Pi},
+	{0, Inf(1)},
+	{0, NaN()},
+	{+Pi, Inf(-1)},
+	{+Pi, 0},
+	{+Pi, Inf(1)},
+	{+Pi, NaN()},
+	{Inf(1), Inf(-1)},
+	{Inf(1), -Pi},
+	{Inf(1), 0},
+	{Inf(1), +Pi},
+	{Inf(1), Inf(1)},
+	{Inf(1), NaN()},
+	{NaN(), NaN()},
+}
+var atan2SC = []float64{
+	-3 * Pi / 4,     // atan2(-Inf, -Inf)
+	-Pi / 2,         // atan2(-Inf, -Pi)
+	-Pi / 2,         // atan2(-Inf, +0)
+	-Pi / 2,         // atan2(-Inf, +Pi)
+	-Pi / 4,         // atan2(-Inf, +Inf)
+	NaN(),           // atan2(-Inf, NaN)
+	-Pi,             // atan2(-Pi, -Inf)
+	-Pi / 2,         // atan2(-Pi, +0)
+	Copysign(0, -1), // atan2(-Pi, Inf)
+	NaN(),           // atan2(-Pi, NaN)
+	-Pi,             // atan2(-0, -Inf)
+	-Pi,             // atan2(-0, -Pi)
+	-Pi,             // atan2(-0, -0)
+	Copysign(0, -1), // atan2(-0, +0)
+	Copysign(0, -1), // atan2(-0, +Pi)
+	Copysign(0, -1), // atan2(-0, +Inf)
+	NaN(),           // atan2(-0, NaN)
+	Pi,              // atan2(+0, -Inf)
+	Pi,              // atan2(+0, -Pi)
+	Pi,              // atan2(+0, -0)
+	0,               // atan2(+0, +0)
+	0,               // atan2(+0, +Pi)
+	0,               // atan2(+0, +Inf)
+	NaN(),           // atan2(+0, NaN)
+	Pi,              // atan2(+Pi, -Inf)
+	Pi / 2,          // atan2(+Pi, +0)
+	0,               // atan2(+Pi, +Inf)
+	NaN(),           // atan2(+Pi, NaN)
+	3 * Pi / 4,      // atan2(+Inf, -Inf)
+	Pi / 2,          // atan2(+Inf, -Pi)
+	Pi / 2,          // atan2(+Inf, +0)
+	Pi / 2,          // atan2(+Inf, +Pi)
+	Pi / 4,          // atan2(+Inf, +Inf)
+	NaN(),           // atan2(+Inf, NaN)
+	NaN(),           // atan2(NaN, NaN)
+}
+
+var vfcbrtSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var cbrtSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+
+var vfceilSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var ceilSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+
+var vfcopysignSC = []float64{
+	Inf(-1),
+	Inf(1),
+	NaN(),
+}
+var copysignSC = []float64{
+	Inf(-1),
+	Inf(-1),
+	NaN(),
+}
+
+var vfcosSC = []float64{
+	Inf(-1),
+	Inf(1),
+	NaN(),
+}
+var cosSC = []float64{
+	NaN(),
+	NaN(),
+	NaN(),
+}
+
+var vfcoshSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var coshSC = []float64{
+	Inf(1),
+	1,
+	1,
+	Inf(1),
+	NaN(),
+}
+
+var vferfSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var erfSC = []float64{
+	-1,
+	Copysign(0, -1),
+	0,
+	1,
+	NaN(),
+}
+
+var vferfcSC = []float64{
+	Inf(-1),
+	Inf(1),
+	NaN(),
+}
+var erfcSC = []float64{
+	2,
+	0,
+	NaN(),
+}
+
+var vfexpSC = []float64{
+	Inf(-1),
+	-2000,
+	2000,
+	Inf(1),
+	NaN(),
+}
+var expSC = []float64{
+	0,
+	0,
+	Inf(1),
+	Inf(1),
+	NaN(),
+}
+
+var vfexpm1SC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var expm1SC = []float64{
+	-1,
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+
+var vffabsSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var fabsSC = []float64{
+	Inf(1),
+	0,
+	0,
+	Inf(1),
+	NaN(),
+}
+
+var vffdimSC = [][2]float64{
+	{Inf(-1), Inf(-1)},
+	{Inf(-1), Inf(1)},
+	{Inf(-1), NaN()},
+	{Copysign(0, -1), Copysign(0, -1)},
+	{Copysign(0, -1), 0},
+	{0, Copysign(0, -1)},
+	{0, 0},
+	{Inf(1), Inf(-1)},
+	{Inf(1), Inf(1)},
+	{Inf(1), NaN()},
+	{NaN(), Inf(-1)},
+	{NaN(), Copysign(0, -1)},
+	{NaN(), 0},
+	{NaN(), Inf(1)},
+	{NaN(), NaN()},
+}
+var fdimSC = []float64{
+	NaN(),
+	0,
+	NaN(),
+	0,
+	0,
+	0,
+	0,
+	Inf(1),
+	NaN(),
+	NaN(),
+	NaN(),
+	NaN(),
+	NaN(),
+	NaN(),
+	NaN(),
+}
+var fmaxSC = []float64{
+	Inf(-1),
+	Inf(1),
+	NaN(),
+	Copysign(0, -1),
+	0,
+	0,
+	0,
+	Inf(1),
+	Inf(1),
+	Inf(1),
+	NaN(),
+	NaN(),
+	NaN(),
+	Inf(1),
+	NaN(),
+}
+var fminSC = []float64{
+	Inf(-1),
+	Inf(-1),
+	Inf(-1),
+	Copysign(0, -1),
+	Copysign(0, -1),
+	Copysign(0, -1),
+	0,
+	Inf(-1),
+	Inf(1),
+	NaN(),
+	Inf(-1),
+	NaN(),
+	NaN(),
+	NaN(),
+	NaN(),
+}
+
+var vffmodSC = [][2]float64{
+	{Inf(-1), Inf(-1)},
+	{Inf(-1), -Pi},
+	{Inf(-1), 0},
+	{Inf(-1), Pi},
+	{Inf(-1), Inf(1)},
+	{Inf(-1), NaN()},
+	{-Pi, Inf(-1)},
+	{-Pi, 0},
+	{-Pi, Inf(1)},
+	{-Pi, NaN()},
+	{Copysign(0, -1), Inf(-1)},
+	{Copysign(0, -1), 0},
+	{Copysign(0, -1), Inf(1)},
+	{Copysign(0, -1), NaN()},
+	{0, Inf(-1)},
+	{0, 0},
+	{0, Inf(1)},
+	{0, NaN()},
+	{Pi, Inf(-1)},
+	{Pi, 0},
+	{Pi, Inf(1)},
+	{Pi, NaN()},
+	{Inf(1), Inf(-1)},
+	{Inf(1), -Pi},
+	{Inf(1), 0},
+	{Inf(1), Pi},
+	{Inf(1), Inf(1)},
+	{Inf(1), NaN()},
+	{NaN(), Inf(-1)},
+	{NaN(), -Pi},
+	{NaN(), 0},
+	{NaN(), Pi},
+	{NaN(), Inf(1)},
+	{NaN(), NaN()},
+}
+var fmodSC = []float64{
+	NaN(),           // fmod(-Inf, -Inf)
+	NaN(),           // fmod(-Inf, -Pi)
+	NaN(),           // fmod(-Inf, 0)
+	NaN(),           // fmod(-Inf, Pi)
+	NaN(),           // fmod(-Inf, +Inf)
+	NaN(),           // fmod(-Inf, NaN)
+	-Pi,             // fmod(-Pi, -Inf)
+	NaN(),           // fmod(-Pi, 0)
+	-Pi,             // fmod(-Pi, +Inf)
+	NaN(),           // fmod(-Pi, NaN)
+	Copysign(0, -1), // fmod(-0, -Inf)
+	NaN(),           // fmod(-0, 0)
+	Copysign(0, -1), // fmod(-0, Inf)
+	NaN(),           // fmod(-0, NaN)
+	0,               // fmod(0, -Inf)
+	NaN(),           // fmod(0, 0)
+	0,               // fmod(0, +Inf)
+	NaN(),           // fmod(0, NaN)
+	Pi,              // fmod(Pi, -Inf)
+	NaN(),           // fmod(Pi, 0)
+	Pi,              // fmod(Pi, +Inf)
+	NaN(),           // fmod(Pi, NaN)
+	NaN(),           // fmod(+Inf, -Inf)
+	NaN(),           // fmod(+Inf, -Pi)
+	NaN(),           // fmod(+Inf, 0)
+	NaN(),           // fmod(+Inf, Pi)
+	NaN(),           // fmod(+Inf, +Inf)
+	NaN(),           // fmod(+Inf, NaN)
+	NaN(),           // fmod(NaN, -Inf)
+	NaN(),           // fmod(NaN, -Pi)
+	NaN(),           // fmod(NaN, 0)
+	NaN(),           // fmod(NaN, Pi)
+	NaN(),           // fmod(NaN, +Inf)
+	NaN(),           // fmod(NaN, NaN)
+}
+
+var vffrexpSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var frexpSC = []fi{
+	{Inf(-1), 0},
+	{Copysign(0, -1), 0},
+	{0, 0},
+	{Inf(1), 0},
+	{NaN(), 0},
+}
+
+var vfgammaSC = []float64{
+	Inf(-1),
+	-3,
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var gammaSC = []float64{
+	NaN(),
+	NaN(),
+	Inf(-1),
+	Inf(1),
+	Inf(1),
+	NaN(),
+}
+
+var vfhypotSC = [][2]float64{
+	{Inf(-1), Inf(-1)},
+	{Inf(-1), 0},
+	{Inf(-1), Inf(1)},
+	{Inf(-1), NaN()},
+	{Copysign(0, -1), Copysign(0, -1)},
+	{Copysign(0, -1), 0},
+	{0, Copysign(0, -1)},
+	{0, 0}, // +0, +0
+	{0, Inf(-1)},
+	{0, Inf(1)},
+	{0, NaN()},
+	{Inf(1), Inf(-1)},
+	{Inf(1), 0},
+	{Inf(1), Inf(1)},
+	{Inf(1), NaN()},
+	{NaN(), Inf(-1)},
+	{NaN(), 0},
+	{NaN(), Inf(1)},
+	{NaN(), NaN()},
+}
+var hypotSC = []float64{
+	Inf(1),
+	Inf(1),
+	Inf(1),
+	Inf(1),
+	0,
+	0,
+	0,
+	0,
+	Inf(1),
+	Inf(1),
+	NaN(),
+	Inf(1),
+	Inf(1),
+	Inf(1),
+	Inf(1),
+	Inf(1),
+	NaN(),
+	Inf(1),
+	NaN(),
+}
+
+var vfilogbSC = []float64{
+	Inf(-1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var ilogbSC = []int{
+	MaxInt32,
+	MinInt32,
+	MaxInt32,
+	MaxInt32,
+}
+
+var vfj0SC = []float64{
+	Inf(-1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var j0SC = []float64{
+	0,
+	1,
+	0,
+	NaN(),
+}
+var j1SC = []float64{
+	0,
+	0,
+	0,
+	NaN(),
+}
+var j2SC = []float64{
+	0,
+	0,
+	0,
+	NaN(),
+}
+var jM3SC = []float64{
+	0,
+	0,
+	0,
+	NaN(),
+}
+
+var vfldexpSC = []fi{
+	{0, 0},
+	{0, -1075},
+	{0, 1024},
+	{Copysign(0, -1), 0},
+	{Copysign(0, -1), -1075},
+	{Copysign(0, -1), 1024},
+	{Inf(1), 0},
+	{Inf(1), -1024},
+	{Inf(-1), 0},
+	{Inf(-1), -1024},
+	{NaN(), -1024},
+}
+var ldexpSC = []float64{
+	0,
+	0,
+	0,
+	Copysign(0, -1),
+	Copysign(0, -1),
+	Copysign(0, -1),
+	Inf(1),
+	Inf(1),
+	Inf(-1),
+	Inf(-1),
+	NaN(),
+}
+
+var vflgammaSC = []float64{
+	Inf(-1),
+	-3,
+	0,
+	1,
+	2,
+	Inf(1),
+	NaN(),
+}
+var lgammaSC = []fi{
+	{Inf(-1), 1},
+	{Inf(1), 1},
+	{Inf(1), 1},
+	{0, 1},
+	{0, 1},
+	{Inf(1), 1},
+	{NaN(), 1},
+}
+
+var vflogSC = []float64{
+	Inf(-1),
+	-Pi,
+	Copysign(0, -1),
+	0,
+	1,
+	Inf(1),
+	NaN(),
+}
+var logSC = []float64{
+	NaN(),
+	NaN(),
+	Inf(-1),
+	Inf(-1),
+	0,
+	Inf(1),
+	NaN(),
+}
+
+var vflogbSC = []float64{
+	Inf(-1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var logbSC = []float64{
+	Inf(1),
+	Inf(-1),
+	Inf(1),
+	NaN(),
+}
+
+var vflog1pSC = []float64{
+	Inf(-1),
+	-Pi,
+	-1,
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var log1pSC = []float64{
+	NaN(),
+	NaN(),
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+
+var vfmodfSC = []float64{
+	Inf(-1),
+	Inf(1),
+	NaN(),
+}
+var modfSC = [][2]float64{
+	{Inf(-1), NaN()}, // [2]float64{Copysign(0, -1), Inf(-1)},
+	{Inf(1), NaN()},  // [2]float64{0, Inf(1)},
+	{NaN(), NaN()},
+}
+
+var vfnextafterSC = [][2]float64{
+	{0, 0},
+	{0, Copysign(0, -1)},
+	{0, -1},
+	{0, NaN()},
+	{Copysign(0, -1), 1},
+	{Copysign(0, -1), 0},
+	{Copysign(0, -1), Copysign(0, -1)},
+	{Copysign(0, -1), -1},
+	{NaN(), 0},
+	{NaN(), NaN()},
+}
+var nextafterSC = []float64{
+	0,
+	0,
+	-4.9406564584124654418e-324, // Float64frombits(0x8000000000000001)
+	NaN(),
+	4.9406564584124654418e-324, // Float64frombits(0x0000000000000001)
+	Copysign(0, -1),
+	Copysign(0, -1),
+	-4.9406564584124654418e-324, // Float64frombits(0x8000000000000001)
+	NaN(),
+	NaN(),
+}
+
+var vfpowSC = [][2]float64{
+	{Inf(-1), -Pi},
+	{Inf(-1), -3},
+	{Inf(-1), Copysign(0, -1)},
+	{Inf(-1), 0},
+	{Inf(-1), 1},
+	{Inf(-1), 3},
+	{Inf(-1), Pi},
+	{Inf(-1), NaN()},
+
+	{-Pi, Inf(-1)},
+	{-Pi, -Pi},
+	{-Pi, Copysign(0, -1)},
+	{-Pi, 0},
+	{-Pi, 1},
+	{-Pi, Pi},
+	{-Pi, Inf(1)},
+	{-Pi, NaN()},
+
+	{-1, Inf(-1)},
+	{-1, Inf(1)},
+	{-1, NaN()},
+	{-1 / 2, Inf(-1)},
+	{-1 / 2, Inf(1)},
+	{Copysign(0, -1), Inf(-1)},
+	{Copysign(0, -1), -Pi},
+	{Copysign(0, -1), -3},
+	{Copysign(0, -1), 3},
+	{Copysign(0, -1), Pi},
+	{Copysign(0, -1), Inf(1)},
+
+	{0, Inf(-1)},
+	{0, -Pi},
+	{0, -3},
+	{0, Copysign(0, -1)},
+	{0, 0},
+	{0, 3},
+	{0, Pi},
+	{0, Inf(1)},
+	{0, NaN()},
+
+	{1 / 2, Inf(-1)},
+	{1 / 2, Inf(1)},
+	{1, Inf(-1)},
+	{1, Inf(1)},
+	{1, NaN()},
+
+	{Pi, Inf(-1)},
+	{Pi, Copysign(0, -1)},
+	{Pi, 0},
+	{Pi, 1},
+	{Pi, Inf(1)},
+	{Pi, NaN()},
+	{Inf(1), -Pi},
+	{Inf(1), Copysign(0, -1)},
+	{Inf(1), 0},
+	{Inf(1), 1},
+	{Inf(1), Pi},
+	{Inf(1), NaN()},
+	{NaN(), -Pi},
+	{NaN(), Copysign(0, -1)},
+	{NaN(), 0},
+	{NaN(), 1},
+	{NaN(), Pi},
+	{NaN(), NaN()},
+}
+var powSC = []float64{
+	0,               // pow(-Inf, -Pi)
+	Copysign(0, -1), // pow(-Inf, -3)
+	1,               // pow(-Inf, -0)
+	1,               // pow(-Inf, +0)
+	Inf(-1),         // pow(-Inf, 1)
+	Inf(-1),         // pow(-Inf, 3)
+	Inf(1),          // pow(-Inf, Pi)
+	NaN(),           // pow(-Inf, NaN)
+	0,               // pow(-Pi, -Inf)
+	NaN(),           // pow(-Pi, -Pi)
+	1,               // pow(-Pi, -0)
+	1,               // pow(-Pi, +0)
+	-Pi,             // pow(-Pi, 1)
+	NaN(),           // pow(-Pi, Pi)
+	Inf(1),          // pow(-Pi, +Inf)
+	NaN(),           // pow(-Pi, NaN)
+	1,               // pow(-1, -Inf) IEEE 754-2008
+	1,               // pow(-1, +Inf) IEEE 754-2008
+	NaN(),           // pow(-1, NaN)
+	Inf(1),          // pow(-1/2, -Inf)
+	0,               // pow(-1/2, +Inf)
+	Inf(1),          // pow(-0, -Inf)
+	Inf(1),          // pow(-0, -Pi)
+	Inf(-1),         // pow(-0, -3) IEEE 754-2008
+	Copysign(0, -1), // pow(-0, 3) IEEE 754-2008
+	0,               // pow(-0, +Pi)
+	0,               // pow(-0, +Inf)
+	Inf(1),          // pow(+0, -Inf)
+	Inf(1),          // pow(+0, -Pi)
+	Inf(1),          // pow(+0, -3)
+	1,               // pow(+0, -0)
+	1,               // pow(+0, +0)
+	0,               // pow(+0, 3)
+	0,               // pow(+0, +Pi)
+	0,               // pow(+0, +Inf)
+	NaN(),           // pow(+0, NaN)
+	Inf(1),          // pow(1/2, -Inf)
+	0,               // pow(1/2, +Inf)
+	1,               // pow(1, -Inf) IEEE 754-2008
+	1,               // pow(1, +Inf) IEEE 754-2008
+	1,               // pow(1, NaN) IEEE 754-2008
+	0,               // pow(+Pi, -Inf)
+	1,               // pow(+Pi, -0)
+	1,               // pow(+Pi, +0)
+	Pi,              // pow(+Pi, 1)
+	Inf(1),          // pow(+Pi, +Inf)
+	NaN(),           // pow(+Pi, NaN)
+	0,               // pow(+Inf, -Pi)
+	1,               // pow(+Inf, -0)
+	1,               // pow(+Inf, +0)
+	Inf(1),          // pow(+Inf, 1)
+	Inf(1),          // pow(+Inf, Pi)
+	NaN(),           // pow(+Inf, NaN)
+	NaN(),           // pow(NaN, -Pi)
+	1,               // pow(NaN, -0)
+	1,               // pow(NaN, +0)
+	NaN(),           // pow(NaN, 1)
+	NaN(),           // pow(NaN, +Pi)
+	NaN(),           // pow(NaN, NaN)
+}
+
+var vfpow10SC = []int{
+	MinInt32,
+	MaxInt32,
+	-325,
+	309,
+}
+
+var pow10SC = []float64{
+	0,      // pow10(MinInt32)
+	Inf(1), // pow10(MaxInt32)
+	0,      // pow10(-325)
+	Inf(1), // pow10(309)
+}
+
+var vfsignbitSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var signbitSC = []bool{
+	true,
+	true,
+	false,
+	false,
+	false,
+}
+
+var vfsinSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var sinSC = []float64{
+	NaN(),
+	Copysign(0, -1),
+	0,
+	NaN(),
+	NaN(),
+}
+
+var vfsinhSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var sinhSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+
+var vfsqrtSC = []float64{
+	Inf(-1),
+	-Pi,
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var sqrtSC = []float64{
+	NaN(),
+	NaN(),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+
+var vftanhSC = []float64{
+	Inf(-1),
+	Copysign(0, -1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var tanhSC = []float64{
+	-1,
+	Copysign(0, -1),
+	0,
+	1,
+	NaN(),
+}
+
+var vfy0SC = []float64{
+	Inf(-1),
+	0,
+	Inf(1),
+	NaN(),
+}
+var y0SC = []float64{
+	NaN(),
+	Inf(-1),
+	0,
+	NaN(),
+}
+var y1SC = []float64{
+	NaN(),
+	Inf(-1),
+	0,
+	NaN(),
+}
+var y2SC = []float64{
+	NaN(),
+	Inf(-1),
+	0,
+	NaN(),
+}
+var yM3SC = []float64{
+	NaN(),
+	Inf(1),
+	0,
+	NaN(),
+}
+
+// arguments and expected results for boundary cases
+const (
+	SmallestNormalFloat64   = 2.2250738585072014e-308 // 2**-1022
+	LargestSubnormalFloat64 = SmallestNormalFloat64 - SmallestNonzeroFloat64
+)
+
+var vffrexpBC = []float64{
+	SmallestNormalFloat64,
+	LargestSubnormalFloat64,
+	SmallestNonzeroFloat64,
+	MaxFloat64,
+	-SmallestNormalFloat64,
+	-LargestSubnormalFloat64,
+	-SmallestNonzeroFloat64,
+	-MaxFloat64,
+}
+var frexpBC = []fi{
+	{0.5, -1021},
+	{0.99999999999999978, -1022},
+	{0.5, -1073},
+	{0.99999999999999989, 1024},
+	{-0.5, -1021},
+	{-0.99999999999999978, -1022},
+	{-0.5, -1073},
+	{-0.99999999999999989, 1024},
+}
+
+var vfldexpBC = []fi{
+	{SmallestNormalFloat64, -52},
+	{LargestSubnormalFloat64, -51},
+	{SmallestNonzeroFloat64, 1074},
+	{MaxFloat64, -(1023 + 1074)},
+	{1, -1075},
+	{-1, -1075},
+	{1, 1024},
+	{-1, 1024},
+}
+var ldexpBC = []float64{
+	SmallestNonzeroFloat64,
+	1e-323, // 2**-1073
+	1,
+	1e-323, // 2**-1073
+	0,
+	Copysign(0, -1),
+	Inf(1),
+	Inf(-1),
+}
+
+var logbBC = []float64{
+	-1022,
+	-1023,
+	-1074,
+	1023,
+	-1022,
+	-1023,
+	-1074,
+	1023,
+}
+
+func tolerance(a, b, e float64) bool {
+	d := a - b
+	if d < 0 {
+		d = -d
+	}
+
+	if a != 0 {
+		e = e * a
+		if e < 0 {
+			e = -e
+		}
+	}
+	return d < e
+}
+func kindaclose(a, b float64) bool { return tolerance(a, b, 1e-8) }
+func close(a, b float64) bool      { return tolerance(a, b, 1e-14) }
+func veryclose(a, b float64) bool  { return tolerance(a, b, 4e-16) }
+func soclose(a, b, e float64) bool { return tolerance(a, b, e) }
+func alike(a, b float64) bool {
+	switch {
+	case IsNaN(a) && IsNaN(b):
+		return true
+	case a == b:
+		return Signbit(a) == Signbit(b)
+	}
+	return false
+}
+
+func TestNaN(t *testing.T) {
+	f64 := NaN()
+	if f64 == f64 {
+		t.Fatalf("NaN() returns %g, expected NaN", f64)
+	}
+	f32 := float32(f64)
+	if f32 == f32 {
+		t.Fatalf("float32(NaN()) is %g, expected NaN", f32)
+	}
+}
+
+func TestAcos(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := vf[i] / 10
+		if f := Acos(a); !close(acos[i], f) {
+			t.Errorf("Acos(%g) = %g, want %g", a, f, acos[i])
+		}
+	}
+	for i := 0; i < len(vfacosSC); i++ {
+		if f := Acos(vfacosSC[i]); !alike(acosSC[i], f) {
+			t.Errorf("Acos(%g) = %g, want %g", vfacosSC[i], f, acosSC[i])
+		}
+	}
+}
+
+func TestAcosh(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := 1 + Abs(vf[i])
+		if f := Acosh(a); !veryclose(acosh[i], f) {
+			t.Errorf("Acosh(%g) = %g, want %g", a, f, acosh[i])
+		}
+	}
+	for i := 0; i < len(vfacoshSC); i++ {
+		if f := Acosh(vfacoshSC[i]); !alike(acoshSC[i], f) {
+			t.Errorf("Acosh(%g) = %g, want %g", vfacoshSC[i], f, acoshSC[i])
+		}
+	}
+}
+
+func TestAsin(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := vf[i] / 10
+		if f := Asin(a); !veryclose(asin[i], f) {
+			t.Errorf("Asin(%g) = %g, want %g", a, f, asin[i])
+		}
+	}
+	for i := 0; i < len(vfasinSC); i++ {
+		if f := Asin(vfasinSC[i]); !alike(asinSC[i], f) {
+			t.Errorf("Asin(%g) = %g, want %g", vfasinSC[i], f, asinSC[i])
+		}
+	}
+}
+
+func TestAsinh(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Asinh(vf[i]); !veryclose(asinh[i], f) {
+			t.Errorf("Asinh(%g) = %g, want %g", vf[i], f, asinh[i])
+		}
+	}
+	for i := 0; i < len(vfasinhSC); i++ {
+		if f := Asinh(vfasinhSC[i]); !alike(asinhSC[i], f) {
+			t.Errorf("Asinh(%g) = %g, want %g", vfasinhSC[i], f, asinhSC[i])
+		}
+	}
+}
+
+func TestAtan(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Atan(vf[i]); !veryclose(atan[i], f) {
+			t.Errorf("Atan(%g) = %g, want %g", vf[i], f, atan[i])
+		}
+	}
+	for i := 0; i < len(vfatanSC); i++ {
+		if f := Atan(vfatanSC[i]); !alike(atanSC[i], f) {
+			t.Errorf("Atan(%g) = %g, want %g", vfatanSC[i], f, atanSC[i])
+		}
+	}
+}
+
+func TestAtanh(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := vf[i] / 10
+		if f := Atanh(a); !veryclose(atanh[i], f) {
+			t.Errorf("Atanh(%g) = %g, want %g", a, f, atanh[i])
+		}
+	}
+	for i := 0; i < len(vfatanhSC); i++ {
+		if f := Atanh(vfatanhSC[i]); !alike(atanhSC[i], f) {
+			t.Errorf("Atanh(%g) = %g, want %g", vfatanhSC[i], f, atanhSC[i])
+		}
+	}
+}
+
+func TestAtan2(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Atan2(10, vf[i]); !veryclose(atan2[i], f) {
+			t.Errorf("Atan2(10, %g) = %g, want %g", vf[i], f, atan2[i])
+		}
+	}
+	for i := 0; i < len(vfatan2SC); i++ {
+		if f := Atan2(vfatan2SC[i][0], vfatan2SC[i][1]); !alike(atan2SC[i], f) {
+			t.Errorf("Atan2(%g, %g) = %g, want %g", vfatan2SC[i][0], vfatan2SC[i][1], f, atan2SC[i])
+		}
+	}
+}
+
+func TestCbrt(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Cbrt(vf[i]); !veryclose(cbrt[i], f) {
+			t.Errorf("Cbrt(%g) = %g, want %g", vf[i], f, cbrt[i])
+		}
+	}
+	for i := 0; i < len(vfcbrtSC); i++ {
+		if f := Cbrt(vfcbrtSC[i]); !alike(cbrtSC[i], f) {
+			t.Errorf("Cbrt(%g) = %g, want %g", vfcbrtSC[i], f, cbrtSC[i])
+		}
+	}
+}
+
+func TestCeil(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Ceil(vf[i]); ceil[i] != f {
+			t.Errorf("Ceil(%g) = %g, want %g", vf[i], f, ceil[i])
+		}
+	}
+	for i := 0; i < len(vfceilSC); i++ {
+		if f := Ceil(vfceilSC[i]); !alike(ceilSC[i], f) {
+			t.Errorf("Ceil(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i])
+		}
+	}
+}
+
+func TestCopysign(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Copysign(vf[i], -1); copysign[i] != f {
+			t.Errorf("Copysign(%g, -1) = %g, want %g", vf[i], f, copysign[i])
+		}
+	}
+	for i := 0; i < len(vf); i++ {
+		if f := Copysign(vf[i], 1); -copysign[i] != f {
+			t.Errorf("Copysign(%g, 1) = %g, want %g", vf[i], f, -copysign[i])
+		}
+	}
+	for i := 0; i < len(vfcopysignSC); i++ {
+		if f := Copysign(vfcopysignSC[i], -1); !alike(copysignSC[i], f) {
+			t.Errorf("Copysign(%g, -1) = %g, want %g", vfcopysignSC[i], f, copysignSC[i])
+		}
+	}
+}
+
+func TestCos(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Cos(vf[i]); !veryclose(cos[i], f) {
+			t.Errorf("Cos(%g) = %g, want %g", vf[i], f, cos[i])
+		}
+	}
+	for i := 0; i < len(vfcosSC); i++ {
+		if f := Cos(vfcosSC[i]); !alike(cosSC[i], f) {
+			t.Errorf("Cos(%g) = %g, want %g", vfcosSC[i], f, cosSC[i])
+		}
+	}
+}
+
+func TestCosh(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Cosh(vf[i]); !close(cosh[i], f) {
+			t.Errorf("Cosh(%g) = %g, want %g", vf[i], f, cosh[i])
+		}
+	}
+	for i := 0; i < len(vfcoshSC); i++ {
+		if f := Cosh(vfcoshSC[i]); !alike(coshSC[i], f) {
+			t.Errorf("Cosh(%g) = %g, want %g", vfcoshSC[i], f, coshSC[i])
+		}
+	}
+}
+
+func TestErf(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := vf[i] / 10
+		if f := Erf(a); !veryclose(erf[i], f) {
+			t.Errorf("Erf(%g) = %g, want %g", a, f, erf[i])
+		}
+	}
+	for i := 0; i < len(vferfSC); i++ {
+		if f := Erf(vferfSC[i]); !alike(erfSC[i], f) {
+			t.Errorf("Erf(%g) = %g, want %g", vferfSC[i], f, erfSC[i])
+		}
+	}
+}
+
+func TestErfc(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := vf[i] / 10
+		if f := Erfc(a); !veryclose(erfc[i], f) {
+			t.Errorf("Erfc(%g) = %g, want %g", a, f, erfc[i])
+		}
+	}
+	for i := 0; i < len(vferfcSC); i++ {
+		if f := Erfc(vferfcSC[i]); !alike(erfcSC[i], f) {
+			t.Errorf("Erfc(%g) = %g, want %g", vferfcSC[i], f, erfcSC[i])
+		}
+	}
+}
+
+func TestExp(t *testing.T) {
+	testExp(t, Exp, "Exp")
+	testExp(t, ExpGo, "ExpGo")
+}
+
+func testExp(t *testing.T, Exp func(float64) float64, name string) {
+	for i := 0; i < len(vf); i++ {
+		if f := Exp(vf[i]); !close(exp[i], f) {
+			t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp[i])
+		}
+	}
+	for i := 0; i < len(vfexpSC); i++ {
+		if f := Exp(vfexpSC[i]); !alike(expSC[i], f) {
+			t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i])
+		}
+	}
+}
+
+func TestExpm1(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := vf[i] / 100
+		if f := Expm1(a); !veryclose(expm1[i], f) {
+			t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1[i])
+		}
+	}
+	for i := 0; i < len(vfexpm1SC); i++ {
+		if f := Expm1(vfexpm1SC[i]); !alike(expm1SC[i], f) {
+			t.Errorf("Expm1(%g) = %g, want %g", vfexpm1SC[i], f, expm1SC[i])
+		}
+	}
+}
+
+func TestExp2(t *testing.T) {
+	testExp2(t, Exp2, "Exp2")
+	testExp2(t, Exp2Go, "Exp2Go")
+}
+
+func testExp2(t *testing.T, Exp2 func(float64) float64, name string) {
+	for i := 0; i < len(vf); i++ {
+		if f := Exp2(vf[i]); !close(exp2[i], f) {
+			t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp2[i])
+		}
+	}
+	for i := 0; i < len(vfexpSC); i++ {
+		if f := Exp2(vfexpSC[i]); !alike(expSC[i], f) {
+			t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i])
+		}
+	}
+	for n := -1074; n < 1024; n++ {
+		f := Exp2(float64(n))
+		vf := Ldexp(1, n)
+		if f != vf {
+			t.Errorf("%s(%d) = %g, want %g", name, n, f, vf)
+		}
+	}
+}
+
+func TestAbs(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Abs(vf[i]); fabs[i] != f {
+			t.Errorf("Abs(%g) = %g, want %g", vf[i], f, fabs[i])
+		}
+	}
+	for i := 0; i < len(vffabsSC); i++ {
+		if f := Abs(vffabsSC[i]); !alike(fabsSC[i], f) {
+			t.Errorf("Abs(%g) = %g, want %g", vffabsSC[i], f, fabsSC[i])
+		}
+	}
+}
+
+func TestDim(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Dim(vf[i], 0); fdim[i] != f {
+			t.Errorf("Dim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i])
+		}
+	}
+	for i := 0; i < len(vffdimSC); i++ {
+		if f := Dim(vffdimSC[i][0], vffdimSC[i][1]); !alike(fdimSC[i], f) {
+			t.Errorf("Dim(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fdimSC[i])
+		}
+	}
+}
+
+func TestFloor(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Floor(vf[i]); floor[i] != f {
+			t.Errorf("Floor(%g) = %g, want %g", vf[i], f, floor[i])
+		}
+	}
+	for i := 0; i < len(vfceilSC); i++ {
+		if f := Floor(vfceilSC[i]); !alike(ceilSC[i], f) {
+			t.Errorf("Floor(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i])
+		}
+	}
+}
+
+func TestMax(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Max(vf[i], ceil[i]); ceil[i] != f {
+			t.Errorf("Max(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i])
+		}
+	}
+	for i := 0; i < len(vffdimSC); i++ {
+		if f := Max(vffdimSC[i][0], vffdimSC[i][1]); !alike(fmaxSC[i], f) {
+			t.Errorf("Max(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fmaxSC[i])
+		}
+	}
+}
+
+func TestMin(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Min(vf[i], floor[i]); floor[i] != f {
+			t.Errorf("Min(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i])
+		}
+	}
+	for i := 0; i < len(vffdimSC); i++ {
+		if f := Min(vffdimSC[i][0], vffdimSC[i][1]); !alike(fminSC[i], f) {
+			t.Errorf("Min(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fminSC[i])
+		}
+	}
+}
+
+func TestMod(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Mod(10, vf[i]); fmod[i] != f {
+			t.Errorf("Mod(10, %g) = %g, want %g", vf[i], f, fmod[i])
+		}
+	}
+	for i := 0; i < len(vffmodSC); i++ {
+		if f := Mod(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) {
+			t.Errorf("Mod(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i])
+		}
+	}
+}
+
+func TestFrexp(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f, j := Frexp(vf[i]); !veryclose(frexp[i].f, f) || frexp[i].i != j {
+			t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vf[i], f, j, frexp[i].f, frexp[i].i)
+		}
+	}
+	for i := 0; i < len(vffrexpSC); i++ {
+		if f, j := Frexp(vffrexpSC[i]); !alike(frexpSC[i].f, f) || frexpSC[i].i != j {
+			t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpSC[i], f, j, frexpSC[i].f, frexpSC[i].i)
+		}
+	}
+	for i := 0; i < len(vffrexpBC); i++ {
+		if f, j := Frexp(vffrexpBC[i]); !alike(frexpBC[i].f, f) || frexpBC[i].i != j {
+			t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpBC[i], f, j, frexpBC[i].f, frexpBC[i].i)
+		}
+	}
+}
+
+func TestGamma(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Gamma(vf[i]); !close(gamma[i], f) {
+			t.Errorf("Gamma(%g) = %g, want %g", vf[i], f, gamma[i])
+		}
+	}
+	for i := 0; i < len(vfgammaSC); i++ {
+		if f := Gamma(vfgammaSC[i]); !alike(gammaSC[i], f) {
+			t.Errorf("Gamma(%g) = %g, want %g", vfgammaSC[i], f, gammaSC[i])
+		}
+	}
+}
+
+func TestHypot(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Abs(1e200 * tanh[i] * Sqrt(2))
+		if f := Hypot(1e200*tanh[i], 1e200*tanh[i]); !veryclose(a, f) {
+			t.Errorf("Hypot(%g, %g) = %g, want %g", 1e200*tanh[i], 1e200*tanh[i], f, a)
+		}
+	}
+	for i := 0; i < len(vfhypotSC); i++ {
+		if f := Hypot(vfhypotSC[i][0], vfhypotSC[i][1]); !alike(hypotSC[i], f) {
+			t.Errorf("Hypot(%g, %g) = %g, want %g", vfhypotSC[i][0], vfhypotSC[i][1], f, hypotSC[i])
+		}
+	}
+}
+
+func TestHypotGo(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Abs(1e200 * tanh[i] * Sqrt(2))
+		if f := HypotGo(1e200*tanh[i], 1e200*tanh[i]); !veryclose(a, f) {
+			t.Errorf("HypotGo(%g, %g) = %g, want %g", 1e200*tanh[i], 1e200*tanh[i], f, a)
+		}
+	}
+	for i := 0; i < len(vfhypotSC); i++ {
+		if f := HypotGo(vfhypotSC[i][0], vfhypotSC[i][1]); !alike(hypotSC[i], f) {
+			t.Errorf("HypotGo(%g, %g) = %g, want %g", vfhypotSC[i][0], vfhypotSC[i][1], f, hypotSC[i])
+		}
+	}
+}
+
+func TestIlogb(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := frexp[i].i - 1 // adjust because fr in the interval [½, 1)
+		if e := Ilogb(vf[i]); a != e {
+			t.Errorf("Ilogb(%g) = %d, want %d", vf[i], e, a)
+		}
+	}
+	for i := 0; i < len(vflogbSC); i++ {
+		if e := Ilogb(vflogbSC[i]); ilogbSC[i] != e {
+			t.Errorf("Ilogb(%g) = %d, want %d", vflogbSC[i], e, ilogbSC[i])
+		}
+	}
+	for i := 0; i < len(vffrexpBC); i++ {
+		if e := Ilogb(vffrexpBC[i]); int(logbBC[i]) != e {
+			t.Errorf("Ilogb(%g) = %d, want %d", vffrexpBC[i], e, int(logbBC[i]))
+		}
+	}
+}
+
+func TestJ0(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := J0(vf[i]); !soclose(j0[i], f, 4e-14) {
+			t.Errorf("J0(%g) = %g, want %g", vf[i], f, j0[i])
+		}
+	}
+	for i := 0; i < len(vfj0SC); i++ {
+		if f := J0(vfj0SC[i]); !alike(j0SC[i], f) {
+			t.Errorf("J0(%g) = %g, want %g", vfj0SC[i], f, j0SC[i])
+		}
+	}
+}
+
+func TestJ1(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := J1(vf[i]); !close(j1[i], f) {
+			t.Errorf("J1(%g) = %g, want %g", vf[i], f, j1[i])
+		}
+	}
+	for i := 0; i < len(vfj0SC); i++ {
+		if f := J1(vfj0SC[i]); !alike(j1SC[i], f) {
+			t.Errorf("J1(%g) = %g, want %g", vfj0SC[i], f, j1SC[i])
+		}
+	}
+}
+
+func TestJn(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Jn(2, vf[i]); !close(j2[i], f) {
+			t.Errorf("Jn(2, %g) = %g, want %g", vf[i], f, j2[i])
+		}
+		if f := Jn(-3, vf[i]); !close(jM3[i], f) {
+			t.Errorf("Jn(-3, %g) = %g, want %g", vf[i], f, jM3[i])
+		}
+	}
+	for i := 0; i < len(vfj0SC); i++ {
+		if f := Jn(2, vfj0SC[i]); !alike(j2SC[i], f) {
+			t.Errorf("Jn(2, %g) = %g, want %g", vfj0SC[i], f, j2SC[i])
+		}
+		if f := Jn(-3, vfj0SC[i]); !alike(jM3SC[i], f) {
+			t.Errorf("Jn(-3, %g) = %g, want %g", vfj0SC[i], f, jM3SC[i])
+		}
+	}
+}
+
+func TestLdexp(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Ldexp(frexp[i].f, frexp[i].i); !veryclose(vf[i], f) {
+			t.Errorf("Ldexp(%g, %d) = %g, want %g", frexp[i].f, frexp[i].i, f, vf[i])
+		}
+	}
+	for i := 0; i < len(vffrexpSC); i++ {
+		if f := Ldexp(frexpSC[i].f, frexpSC[i].i); !alike(vffrexpSC[i], f) {
+			t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpSC[i].f, frexpSC[i].i, f, vffrexpSC[i])
+		}
+	}
+	for i := 0; i < len(vfldexpSC); i++ {
+		if f := Ldexp(vfldexpSC[i].f, vfldexpSC[i].i); !alike(ldexpSC[i], f) {
+			t.Errorf("Ldexp(%g, %d) = %g, want %g", vfldexpSC[i].f, vfldexpSC[i].i, f, ldexpSC[i])
+		}
+	}
+	for i := 0; i < len(vffrexpBC); i++ {
+		if f := Ldexp(frexpBC[i].f, frexpBC[i].i); !alike(vffrexpBC[i], f) {
+			t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpBC[i].f, frexpBC[i].i, f, vffrexpBC[i])
+		}
+	}
+	for i := 0; i < len(vfldexpBC); i++ {
+		if f := Ldexp(vfldexpBC[i].f, vfldexpBC[i].i); !alike(ldexpBC[i], f) {
+			t.Errorf("Ldexp(%g, %d) = %g, want %g", vfldexpBC[i].f, vfldexpBC[i].i, f, ldexpBC[i])
+		}
+	}
+}
+
+func TestLgamma(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f, s := Lgamma(vf[i]); !close(lgamma[i].f, f) || lgamma[i].i != s {
+			t.Errorf("Lgamma(%g) = %g, %d, want %g, %d", vf[i], f, s, lgamma[i].f, lgamma[i].i)
+		}
+	}
+	for i := 0; i < len(vflgammaSC); i++ {
+		if f, s := Lgamma(vflgammaSC[i]); !alike(lgammaSC[i].f, f) || lgammaSC[i].i != s {
+			t.Errorf("Lgamma(%g) = %g, %d, want %g, %d", vflgammaSC[i], f, s, lgammaSC[i].f, lgammaSC[i].i)
+		}
+	}
+}
+
+func TestLog(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Abs(vf[i])
+		if f := Log(a); log[i] != f {
+			t.Errorf("Log(%g) = %g, want %g", a, f, log[i])
+		}
+	}
+	if f := Log(10); f != Ln10 {
+		t.Errorf("Log(%g) = %g, want %g", 10.0, f, Ln10)
+	}
+	for i := 0; i < len(vflogSC); i++ {
+		if f := Log(vflogSC[i]); !alike(logSC[i], f) {
+			t.Errorf("Log(%g) = %g, want %g", vflogSC[i], f, logSC[i])
+		}
+	}
+}
+
+func TestLogb(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Logb(vf[i]); logb[i] != f {
+			t.Errorf("Logb(%g) = %g, want %g", vf[i], f, logb[i])
+		}
+	}
+	for i := 0; i < len(vflogbSC); i++ {
+		if f := Logb(vflogbSC[i]); !alike(logbSC[i], f) {
+			t.Errorf("Logb(%g) = %g, want %g", vflogbSC[i], f, logbSC[i])
+		}
+	}
+	for i := 0; i < len(vffrexpBC); i++ {
+		if f := Logb(vffrexpBC[i]); !alike(logbBC[i], f) {
+			t.Errorf("Logb(%g) = %g, want %g", vffrexpBC[i], f, logbBC[i])
+		}
+	}
+}
+
+func TestLog10(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Abs(vf[i])
+		if f := Log10(a); !veryclose(log10[i], f) {
+			t.Errorf("Log10(%g) = %g, want %g", a, f, log10[i])
+		}
+	}
+	if f := Log10(E); f != Log10E {
+		t.Errorf("Log10(%g) = %g, want %g", E, f, Log10E)
+	}
+	for i := 0; i < len(vflogSC); i++ {
+		if f := Log10(vflogSC[i]); !alike(logSC[i], f) {
+			t.Errorf("Log10(%g) = %g, want %g", vflogSC[i], f, logSC[i])
+		}
+	}
+}
+
+func TestLog1p(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := vf[i] / 100
+		if f := Log1p(a); !veryclose(log1p[i], f) {
+			t.Errorf("Log1p(%g) = %g, want %g", a, f, log1p[i])
+		}
+	}
+	a := 9.0
+	if f := Log1p(a); f != Ln10 {
+		t.Errorf("Log1p(%g) = %g, want %g", a, f, Ln10)
+	}
+	for i := 0; i < len(vflogSC); i++ {
+		if f := Log1p(vflog1pSC[i]); !alike(log1pSC[i], f) {
+			t.Errorf("Log1p(%g) = %g, want %g", vflog1pSC[i], f, log1pSC[i])
+		}
+	}
+}
+
+func TestLog2(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Abs(vf[i])
+		if f := Log2(a); !veryclose(log2[i], f) {
+			t.Errorf("Log2(%g) = %g, want %g", a, f, log2[i])
+		}
+	}
+	if f := Log2(E); f != Log2E {
+		t.Errorf("Log2(%g) = %g, want %g", E, f, Log2E)
+	}
+	for i := 0; i < len(vflogSC); i++ {
+		if f := Log2(vflogSC[i]); !alike(logSC[i], f) {
+			t.Errorf("Log2(%g) = %g, want %g", vflogSC[i], f, logSC[i])
+		}
+	}
+	for i := -1074; i <= 1023; i++ {
+		f := Ldexp(1, i)
+		l := Log2(f)
+		if l != float64(i) {
+			t.Errorf("Log2(2**%d) = %g, want %d", i, l, i)
+		}
+	}
+}
+
+func TestModf(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f, g := Modf(vf[i]); !veryclose(modf[i][0], f) || !veryclose(modf[i][1], g) {
+			t.Errorf("Modf(%g) = %g, %g, want %g, %g", vf[i], f, g, modf[i][0], modf[i][1])
+		}
+	}
+	for i := 0; i < len(vfmodfSC); i++ {
+		if f, g := Modf(vfmodfSC[i]); !alike(modfSC[i][0], f) || !alike(modfSC[i][1], g) {
+			t.Errorf("Modf(%g) = %g, %g, want %g, %g", vfmodfSC[i], f, g, modfSC[i][0], modfSC[i][1])
+		}
+	}
+}
+
+func TestNextafter(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Nextafter(vf[i], 10); nextafter[i] != f {
+			t.Errorf("Nextafter(%g, %g) = %g want %g", vf[i], 10.0, f, nextafter[i])
+		}
+	}
+	for i := 0; i < len(vfnextafterSC); i++ {
+		if f := Nextafter(vfnextafterSC[i][0], vfnextafterSC[i][1]); !alike(nextafterSC[i], f) {
+			t.Errorf("Nextafter(%g, %g) = %g want %g", vfnextafterSC[i][0], vfnextafterSC[i][1], f, nextafterSC[i])
+		}
+	}
+}
+
+func TestPow(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Pow(10, vf[i]); !close(pow[i], f) {
+			t.Errorf("Pow(10, %g) = %g, want %g", vf[i], f, pow[i])
+		}
+	}
+	for i := 0; i < len(vfpowSC); i++ {
+		if f := Pow(vfpowSC[i][0], vfpowSC[i][1]); !alike(powSC[i], f) {
+			t.Errorf("Pow(%g, %g) = %g, want %g", vfpowSC[i][0], vfpowSC[i][1], f, powSC[i])
+		}
+	}
+}
+
+func TestPow10(t *testing.T) {
+	for i := 0; i < len(vfpow10SC); i++ {
+		if f := Pow10(vfpow10SC[i]); !alike(pow10SC[i], f) {
+			t.Errorf("Pow10(%d) = %g, want %g", vfpow10SC[i], f, pow10SC[i])
+		}
+	}
+}
+
+func TestRemainder(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Remainder(10, vf[i]); remainder[i] != f {
+			t.Errorf("Remainder(10, %g) = %g, want %g", vf[i], f, remainder[i])
+		}
+	}
+	for i := 0; i < len(vffmodSC); i++ {
+		if f := Remainder(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) {
+			t.Errorf("Remainder(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i])
+		}
+	}
+}
+
+func TestSignbit(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Signbit(vf[i]); signbit[i] != f {
+			t.Errorf("Signbit(%g) = %t, want %t", vf[i], f, signbit[i])
+		}
+	}
+	for i := 0; i < len(vfsignbitSC); i++ {
+		if f := Signbit(vfsignbitSC[i]); signbitSC[i] != f {
+			t.Errorf("Signbit(%g) = %t, want %t", vfsignbitSC[i], f, signbitSC[i])
+		}
+	}
+}
+func TestSin(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Sin(vf[i]); !veryclose(sin[i], f) {
+			t.Errorf("Sin(%g) = %g, want %g", vf[i], f, sin[i])
+		}
+	}
+	for i := 0; i < len(vfsinSC); i++ {
+		if f := Sin(vfsinSC[i]); !alike(sinSC[i], f) {
+			t.Errorf("Sin(%g) = %g, want %g", vfsinSC[i], f, sinSC[i])
+		}
+	}
+}
+
+func TestSincos(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if s, c := Sincos(vf[i]); !veryclose(sin[i], s) || !veryclose(cos[i], c) {
+			t.Errorf("Sincos(%g) = %g, %g want %g, %g", vf[i], s, c, sin[i], cos[i])
+		}
+	}
+}
+
+func TestSinh(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Sinh(vf[i]); !close(sinh[i], f) {
+			t.Errorf("Sinh(%g) = %g, want %g", vf[i], f, sinh[i])
+		}
+	}
+	for i := 0; i < len(vfsinhSC); i++ {
+		if f := Sinh(vfsinhSC[i]); !alike(sinhSC[i], f) {
+			t.Errorf("Sinh(%g) = %g, want %g", vfsinhSC[i], f, sinhSC[i])
+		}
+	}
+}
+
+func TestSqrt(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Abs(vf[i])
+		if f := SqrtGo(a); sqrt[i] != f {
+			t.Errorf("SqrtGo(%g) = %g, want %g", a, f, sqrt[i])
+		}
+		a = Abs(vf[i])
+		if f := Sqrt(a); sqrt[i] != f {
+			t.Errorf("Sqrt(%g) = %g, want %g", a, f, sqrt[i])
+		}
+	}
+	for i := 0; i < len(vfsqrtSC); i++ {
+		if f := SqrtGo(vfsqrtSC[i]); !alike(sqrtSC[i], f) {
+			t.Errorf("SqrtGo(%g) = %g, want %g", vfsqrtSC[i], f, sqrtSC[i])
+		}
+		if f := Sqrt(vfsqrtSC[i]); !alike(sqrtSC[i], f) {
+			t.Errorf("Sqrt(%g) = %g, want %g", vfsqrtSC[i], f, sqrtSC[i])
+		}
+	}
+}
+
+func TestTan(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Tan(vf[i]); !veryclose(tan[i], f) {
+			t.Errorf("Tan(%g) = %g, want %g", vf[i], f, tan[i])
+		}
+	}
+	// same special cases as Sin
+	for i := 0; i < len(vfsinSC); i++ {
+		if f := Tan(vfsinSC[i]); !alike(sinSC[i], f) {
+			t.Errorf("Tan(%g) = %g, want %g", vfsinSC[i], f, sinSC[i])
+		}
+	}
+}
+
+func TestTanh(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Tanh(vf[i]); !veryclose(tanh[i], f) {
+			t.Errorf("Tanh(%g) = %g, want %g", vf[i], f, tanh[i])
+		}
+	}
+	for i := 0; i < len(vftanhSC); i++ {
+		if f := Tanh(vftanhSC[i]); !alike(tanhSC[i], f) {
+			t.Errorf("Tanh(%g) = %g, want %g", vftanhSC[i], f, tanhSC[i])
+		}
+	}
+}
+
+func TestTrunc(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Trunc(vf[i]); trunc[i] != f {
+			t.Errorf("Trunc(%g) = %g, want %g", vf[i], f, trunc[i])
+		}
+	}
+	for i := 0; i < len(vfceilSC); i++ {
+		if f := Trunc(vfceilSC[i]); !alike(ceilSC[i], f) {
+			t.Errorf("Trunc(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i])
+		}
+	}
+}
+
+func TestY0(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Abs(vf[i])
+		if f := Y0(a); !close(y0[i], f) {
+			t.Errorf("Y0(%g) = %g, want %g", a, f, y0[i])
+		}
+	}
+	for i := 0; i < len(vfy0SC); i++ {
+		if f := Y0(vfy0SC[i]); !alike(y0SC[i], f) {
+			t.Errorf("Y0(%g) = %g, want %g", vfy0SC[i], f, y0SC[i])
+		}
+	}
+}
+
+func TestY1(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Abs(vf[i])
+		if f := Y1(a); !soclose(y1[i], f, 2e-14) {
+			t.Errorf("Y1(%g) = %g, want %g", a, f, y1[i])
+		}
+	}
+	for i := 0; i < len(vfy0SC); i++ {
+		if f := Y1(vfy0SC[i]); !alike(y1SC[i], f) {
+			t.Errorf("Y1(%g) = %g, want %g", vfy0SC[i], f, y1SC[i])
+		}
+	}
+}
+
+func TestYn(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Abs(vf[i])
+		if f := Yn(2, a); !close(y2[i], f) {
+			t.Errorf("Yn(2, %g) = %g, want %g", a, f, y2[i])
+		}
+		if f := Yn(-3, a); !close(yM3[i], f) {
+			t.Errorf("Yn(-3, %g) = %g, want %g", a, f, yM3[i])
+		}
+	}
+	for i := 0; i < len(vfy0SC); i++ {
+		if f := Yn(2, vfy0SC[i]); !alike(y2SC[i], f) {
+			t.Errorf("Yn(2, %g) = %g, want %g", vfy0SC[i], f, y2SC[i])
+		}
+		if f := Yn(-3, vfy0SC[i]); !alike(yM3SC[i], f) {
+			t.Errorf("Yn(-3, %g) = %g, want %g", vfy0SC[i], f, yM3SC[i])
+		}
+	}
+}
+
+// Check that math functions of high angle values
+// return accurate results. [Since (vf[i] + large) - large != vf[i],
+// testing for Trig(vf[i] + large) == Trig(vf[i]), where large is
+// a multiple of 2*Pi, is misleading.]
+func TestLargeCos(t *testing.T) {
+	large := float64(100000 * Pi)
+	for i := 0; i < len(vf); i++ {
+		f1 := cosLarge[i]
+		f2 := Cos(vf[i] + large)
+		if !close(f1, f2) {
+			t.Errorf("Cos(%g) = %g, want %g", vf[i]+large, f2, f1)
+		}
+	}
+}
+
+func TestLargeSin(t *testing.T) {
+	large := float64(100000 * Pi)
+	for i := 0; i < len(vf); i++ {
+		f1 := sinLarge[i]
+		f2 := Sin(vf[i] + large)
+		if !close(f1, f2) {
+			t.Errorf("Sin(%g) = %g, want %g", vf[i]+large, f2, f1)
+		}
+	}
+}
+
+func TestLargeSincos(t *testing.T) {
+	large := float64(100000 * Pi)
+	for i := 0; i < len(vf); i++ {
+		f1, g1 := sinLarge[i], cosLarge[i]
+		f2, g2 := Sincos(vf[i] + large)
+		if !close(f1, f2) || !close(g1, g2) {
+			t.Errorf("Sincos(%g) = %g, %g, want %g, %g", vf[i]+large, f2, g2, f1, g1)
+		}
+	}
+}
+
+func TestLargeTan(t *testing.T) {
+	large := float64(100000 * Pi)
+	for i := 0; i < len(vf); i++ {
+		f1 := tanLarge[i]
+		f2 := Tan(vf[i] + large)
+		if !close(f1, f2) {
+			t.Errorf("Tan(%g) = %g, want %g", vf[i]+large, f2, f1)
+		}
+	}
+}
+
+// Check that math constants are accepted by compiler
+// and have right value (assumes strconv.ParseFloat works).
+// http://code.google.com/p/go/issues/detail?id=201
+
+type floatTest struct {
+	val  interface{}
+	name string
+	str  string
+}
+
+var floatTests = []floatTest{
+	{float64(MaxFloat64), "MaxFloat64", "1.7976931348623157e+308"},
+	{float64(SmallestNonzeroFloat64), "SmallestNonzeroFloat64", "5e-324"},
+	{float32(MaxFloat32), "MaxFloat32", "3.4028235e+38"},
+	{float32(SmallestNonzeroFloat32), "SmallestNonzeroFloat32", "1e-45"},
+}
+
+func TestFloatMinMax(t *testing.T) {
+	for _, tt := range floatTests {
+		s := fmt.Sprint(tt.val)
+		if s != tt.str {
+			t.Errorf("Sprint(%v) = %s, want %s", tt.name, s, tt.str)
+		}
+	}
+}
+
+// Benchmarks
+
+func BenchmarkAcos(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Acos(.5)
+	}
+}
+
+func BenchmarkAcosh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Acosh(1.5)
+	}
+}
+
+func BenchmarkAsin(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Asin(.5)
+	}
+}
+
+func BenchmarkAsinh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Asinh(.5)
+	}
+}
+
+func BenchmarkAtan(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Atan(.5)
+	}
+}
+
+func BenchmarkAtanh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Atanh(.5)
+	}
+}
+
+func BenchmarkAtan2(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Atan2(.5, 1)
+	}
+}
+
+func BenchmarkCbrt(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Cbrt(10)
+	}
+}
+
+func BenchmarkCeil(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Ceil(.5)
+	}
+}
+
+func BenchmarkCopysign(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Copysign(.5, -1)
+	}
+}
+
+func BenchmarkCos(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Cos(.5)
+	}
+}
+
+func BenchmarkCosh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Cosh(2.5)
+	}
+}
+
+func BenchmarkErf(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Erf(.5)
+	}
+}
+
+func BenchmarkErfc(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Erfc(.5)
+	}
+}
+
+func BenchmarkExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Exp(.5)
+	}
+}
+
+func BenchmarkExpGo(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ExpGo(.5)
+	}
+}
+
+func BenchmarkExpm1(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Expm1(.5)
+	}
+}
+
+func BenchmarkExp2(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Exp2(.5)
+	}
+}
+
+func BenchmarkExp2Go(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Exp2Go(.5)
+	}
+}
+
+func BenchmarkAbs(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Abs(.5)
+	}
+}
+
+func BenchmarkDim(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Dim(10, 3)
+	}
+}
+
+func BenchmarkFloor(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Floor(.5)
+	}
+}
+
+func BenchmarkMax(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Max(10, 3)
+	}
+}
+
+func BenchmarkMin(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Min(10, 3)
+	}
+}
+
+func BenchmarkMod(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Mod(10, 3)
+	}
+}
+
+func BenchmarkFrexp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Frexp(8)
+	}
+}
+
+func BenchmarkGamma(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Gamma(2.5)
+	}
+}
+
+func BenchmarkHypot(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Hypot(3, 4)
+	}
+}
+
+func BenchmarkHypotGo(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		HypotGo(3, 4)
+	}
+}
+
+func BenchmarkIlogb(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Ilogb(.5)
+	}
+}
+
+func BenchmarkJ0(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		J0(2.5)
+	}
+}
+
+func BenchmarkJ1(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		J1(2.5)
+	}
+}
+
+func BenchmarkJn(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Jn(2, 2.5)
+	}
+}
+
+func BenchmarkLdexp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Ldexp(.5, 2)
+	}
+}
+
+func BenchmarkLgamma(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Lgamma(2.5)
+	}
+}
+
+func BenchmarkLog(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Log(.5)
+	}
+}
+
+func BenchmarkLogb(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Logb(.5)
+	}
+}
+
+func BenchmarkLog1p(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Log1p(.5)
+	}
+}
+
+func BenchmarkLog10(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Log10(.5)
+	}
+}
+
+func BenchmarkLog2(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Log2(.5)
+	}
+}
+
+func BenchmarkModf(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Modf(1.5)
+	}
+}
+
+func BenchmarkNextafter(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Nextafter(.5, 1)
+	}
+}
+
+func BenchmarkPowInt(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Pow(2, 2)
+	}
+}
+
+func BenchmarkPowFrac(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Pow(2.5, 1.5)
+	}
+}
+
+func BenchmarkPow10Pos(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Pow10(300)
+	}
+}
+
+func BenchmarkPow10Neg(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Pow10(-300)
+	}
+}
+
+func BenchmarkRemainder(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Remainder(10, 3)
+	}
+}
+
+func BenchmarkSignbit(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Signbit(2.5)
+	}
+}
+
+func BenchmarkSin(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sin(.5)
+	}
+}
+
+func BenchmarkSincos(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sincos(.5)
+	}
+}
+
+func BenchmarkSinh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sinh(2.5)
+	}
+}
+
+func BenchmarkSqrt(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sqrt(10)
+	}
+}
+
+func BenchmarkSqrtGo(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		SqrtGo(10)
+	}
+}
+
+func BenchmarkTan(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Tan(.5)
+	}
+}
+
+func BenchmarkTanh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Tanh(2.5)
+	}
+}
+func BenchmarkTrunc(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Trunc(.5)
+	}
+}
+
+func BenchmarkY0(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Y0(2.5)
+	}
+}
+
+func BenchmarkY1(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Y1(2.5)
+	}
+}
+
+func BenchmarkYn(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Yn(2, 2.5)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/math/asin.go b/third_party/gofrontend/libgo/go/math/asin.go
new file mode 100644
index 0000000..46a5fe9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/asin.go
@@ -0,0 +1,67 @@
+// 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 math
+
+/*
+	Floating-point arcsine and arccosine.
+
+	They are implemented by computing the arctangent
+	after appropriate range reduction.
+*/
+
+// Asin returns the arcsine, in radians, of x.
+//
+// Special cases are:
+//	Asin(±0) = ±0
+//	Asin(x) = NaN if x < -1 or x > 1
+
+//extern asin
+func libc_asin(float64) float64
+
+func Asin(x float64) float64 {
+	return libc_asin(x)
+}
+
+func asin(x float64) float64 {
+	if x == 0 {
+		return x // special case
+	}
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+	if x > 1 {
+		return NaN() // special case
+	}
+
+	temp := Sqrt(1 - x*x)
+	if x > 0.7 {
+		temp = Pi/2 - satan(temp/x)
+	} else {
+		temp = satan(x / temp)
+	}
+
+	if sign {
+		temp = -temp
+	}
+	return temp
+}
+
+// Acos returns the arccosine, in radians, of x.
+//
+// Special case is:
+//	Acos(x) = NaN if x < -1 or x > 1
+
+//extern acos
+func libc_acos(float64) float64
+
+func Acos(x float64) float64 {
+	return libc_acos(x)
+}
+
+func acos(x float64) float64 {
+	return Pi/2 - Asin(x)
+}
diff --git a/third_party/gofrontend/libgo/go/math/asinh.go b/third_party/gofrontend/libgo/go/math/asinh.go
new file mode 100644
index 0000000..ff2de02
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/asinh.go
@@ -0,0 +1,69 @@
+// Copyright 2010 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 math
+
+// The original C code, the long comment, and the constants
+// below are from FreeBSD's /usr/src/lib/msun/src/s_asinh.c
+// and came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+//
+// asinh(x)
+// Method :
+//	Based on
+//	        asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
+//	we have
+//	asinh(x) := x  if  1+x*x=1,
+//	         := sign(x)*(log(x)+ln2)) for large |x|, else
+//	         := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
+//	         := sign(x)*log1p(|x| + x**2/(1 + sqrt(1+x**2)))
+//
+
+// Asinh returns the inverse hyperbolic sine of x.
+//
+// Special cases are:
+//	Asinh(±0) = ±0
+//	Asinh(±Inf) = ±Inf
+//	Asinh(NaN) = NaN
+func Asinh(x float64) float64 {
+	const (
+		Ln2      = 6.93147180559945286227e-01 // 0x3FE62E42FEFA39EF
+		NearZero = 1.0 / (1 << 28)            // 2**-28
+		Large    = 1 << 28                    // 2**28
+	)
+	// special cases
+	if IsNaN(x) || IsInf(x, 0) {
+		return x
+	}
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+	var temp float64
+	switch {
+	case x > Large:
+		temp = Log(x) + Ln2 // |x| > 2**28
+	case x > 2:
+		temp = Log(2*x + 1/(Sqrt(x*x+1)+x)) // 2**28 > |x| > 2.0
+	case x < NearZero:
+		temp = x // |x| < 2**-28
+	default:
+		temp = Log1p(x + x*x/(1+Sqrt(1+x*x))) // 2.0 > |x| > 2**-28
+	}
+	if sign {
+		temp = -temp
+	}
+	return temp
+}
diff --git a/third_party/gofrontend/libgo/go/math/atan.go b/third_party/gofrontend/libgo/go/math/atan.go
new file mode 100644
index 0000000..d942bce
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/atan.go
@@ -0,0 +1,111 @@
+// 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 math
+
+/*
+	Floating-point arctangent.
+*/
+
+// The original C code, the long comment, and the constants below were
+// from http://netlib.sandia.gov/cephes/cmath/atan.c, available from
+// http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a version of the original C.
+//
+// atan.c
+// Inverse circular tangent (arctangent)
+//
+// SYNOPSIS:
+// double x, y, atan();
+// y = atan( x );
+//
+// DESCRIPTION:
+// Returns radian angle between -pi/2 and +pi/2 whose tangent is x.
+//
+// Range reduction is from three intervals into the interval from zero to 0.66.
+// The approximant uses a rational function of degree 4/5 of the form
+// x + x**3 P(x)/Q(x).
+//
+// ACCURACY:
+//                      Relative error:
+// arithmetic   domain    # trials  peak     rms
+//    DEC       -10, 10   50000     2.4e-17  8.3e-18
+//    IEEE      -10, 10   10^6      1.8e-16  5.0e-17
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+// xatan evaluates a series valid in the range [0, 0.66].
+func xatan(x float64) float64 {
+	const (
+		P0 = -8.750608600031904122785e-01
+		P1 = -1.615753718733365076637e+01
+		P2 = -7.500855792314704667340e+01
+		P3 = -1.228866684490136173410e+02
+		P4 = -6.485021904942025371773e+01
+		Q0 = +2.485846490142306297962e+01
+		Q1 = +1.650270098316988542046e+02
+		Q2 = +4.328810604912902668951e+02
+		Q3 = +4.853903996359136964868e+02
+		Q4 = +1.945506571482613964425e+02
+	)
+	z := x * x
+	z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4)
+	z = x*z + x
+	return z
+}
+
+// satan reduces its argument (known to be positive)
+// to the range [0, 0.66] and calls xatan.
+func satan(x float64) float64 {
+	const (
+		Morebits = 6.123233995736765886130e-17 // pi/2 = PIO2 + Morebits
+		Tan3pio8 = 2.41421356237309504880      // tan(3*pi/8)
+	)
+	if x <= 0.66 {
+		return xatan(x)
+	}
+	if x > Tan3pio8 {
+		return Pi/2 - xatan(1/x) + Morebits
+	}
+	return Pi/4 + xatan((x-1)/(x+1)) + 0.5*Morebits
+}
+
+// Atan returns the arctangent, in radians, of x.
+//
+// Special cases are:
+//	Atan(±0) = ±0
+//	Atan(±Inf) = ±Pi/2
+
+//extern atan
+func libc_atan(float64) float64
+
+func Atan(x float64) float64 {
+	return libc_atan(x)
+}
+
+func atan(x float64) float64 {
+	if x == 0 {
+		return x
+	}
+	if x > 0 {
+		return satan(x)
+	}
+	return -satan(-x)
+}
diff --git a/third_party/gofrontend/libgo/go/math/atan2.go b/third_party/gofrontend/libgo/go/math/atan2.go
new file mode 100644
index 0000000..48ed9a9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/atan2.go
@@ -0,0 +1,77 @@
+// 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 math
+
+// Atan2 returns the arc tangent of y/x, using
+// the signs of the two to determine the quadrant
+// of the return value.
+//
+// Special cases are (in order):
+//	Atan2(y, NaN) = NaN
+//	Atan2(NaN, x) = NaN
+//	Atan2(+0, x>=0) = +0
+//	Atan2(-0, x>=0) = -0
+//	Atan2(+0, x<=-0) = +Pi
+//	Atan2(-0, x<=-0) = -Pi
+//	Atan2(y>0, 0) = +Pi/2
+//	Atan2(y<0, 0) = -Pi/2
+//	Atan2(+Inf, +Inf) = +Pi/4
+//	Atan2(-Inf, +Inf) = -Pi/4
+//	Atan2(+Inf, -Inf) = 3Pi/4
+//	Atan2(-Inf, -Inf) = -3Pi/4
+//	Atan2(y, +Inf) = 0
+//	Atan2(y>0, -Inf) = +Pi
+//	Atan2(y<0, -Inf) = -Pi
+//	Atan2(+Inf, x) = +Pi/2
+//	Atan2(-Inf, x) = -Pi/2
+
+//extern atan2
+func libc_atan2(float64, float64) float64
+
+func Atan2(y, x float64) float64 {
+	return libc_atan2(y, x)
+}
+
+func atan2(y, x float64) float64 {
+	// special cases
+	switch {
+	case IsNaN(y) || IsNaN(x):
+		return NaN()
+	case y == 0:
+		if x >= 0 && !Signbit(x) {
+			return Copysign(0, y)
+		}
+		return Copysign(Pi, y)
+	case x == 0:
+		return Copysign(Pi/2, y)
+	case IsInf(x, 0):
+		if IsInf(x, 1) {
+			switch {
+			case IsInf(y, 0):
+				return Copysign(Pi/4, y)
+			default:
+				return Copysign(0, y)
+			}
+		}
+		switch {
+		case IsInf(y, 0):
+			return Copysign(3*Pi/4, y)
+		default:
+			return Copysign(Pi, y)
+		}
+	case IsInf(y, 0):
+		return Copysign(Pi/2, y)
+	}
+
+	// Call atan and determine the quadrant.
+	q := Atan(y / x)
+	if x < 0 {
+		if q <= 0 {
+			return q + Pi
+		}
+		return q - Pi
+	}
+	return q
+}
diff --git a/third_party/gofrontend/libgo/go/math/atanh.go b/third_party/gofrontend/libgo/go/math/atanh.go
new file mode 100644
index 0000000..113d5c1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/atanh.go
@@ -0,0 +1,77 @@
+// Copyright 2010 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 math
+
+// The original C code, the long comment, and the constants
+// below are from FreeBSD's /usr/src/lib/msun/src/e_atanh.c
+// and came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+//
+// __ieee754_atanh(x)
+// Method :
+//	1. Reduce x to positive by atanh(-x) = -atanh(x)
+//	2. For x>=0.5
+//	            1              2x                          x
+//	atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+//	            2             1 - x                      1 - x
+//
+//	For x<0.5
+//	atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
+//
+// Special cases:
+//	atanh(x) is NaN if |x| > 1 with signal;
+//	atanh(NaN) is that NaN with no signal;
+//	atanh(+-1) is +-INF with signal.
+//
+
+// Atanh returns the inverse hyperbolic tangent of x.
+//
+// Special cases are:
+//	Atanh(1) = +Inf
+//	Atanh(±0) = ±0
+//	Atanh(-1) = -Inf
+//	Atanh(x) = NaN if x < -1 or x > 1
+//	Atanh(NaN) = NaN
+func Atanh(x float64) float64 {
+	const NearZero = 1.0 / (1 << 28) // 2**-28
+	// special cases
+	switch {
+	case x < -1 || x > 1 || IsNaN(x):
+		return NaN()
+	case x == 1:
+		return Inf(1)
+	case x == -1:
+		return Inf(-1)
+	}
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+	var temp float64
+	switch {
+	case x < NearZero:
+		temp = x
+	case x < 0.5:
+		temp = x + x
+		temp = 0.5 * Log1p(temp+temp*x/(1-x))
+	default:
+		temp = 0.5 * Log1p((x+x)/(1-x))
+	}
+	if sign {
+		temp = -temp
+	}
+	return temp
+}
diff --git a/third_party/gofrontend/libgo/go/math/big/arith.go b/third_party/gofrontend/libgo/go/math/big/arith.go
new file mode 100644
index 0000000..c5ff425
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/arith.go
@@ -0,0 +1,254 @@
+// 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.
+
+// This file provides Go implementations of elementary multi-precision
+// arithmetic operations on word vectors. Needed for platforms without
+// assembly implementations of these routines.
+
+package big
+
+// A Word represents a single digit of a multi-precision unsigned integer.
+type Word uintptr
+
+const (
+	// Compute the size _S of a Word in bytes.
+	_m    = ^Word(0)
+	_logS = _m>>8&1 + _m>>16&1 + _m>>32&1
+	_S    = 1 << _logS
+
+	_W = _S << 3 // word size in bits
+	_B = 1 << _W // digit base
+	_M = _B - 1  // digit mask
+
+	_W2 = _W / 2   // half word size in bits
+	_B2 = 1 << _W2 // half digit base
+	_M2 = _B2 - 1  // half digit mask
+)
+
+// ----------------------------------------------------------------------------
+// Elementary operations on words
+//
+// These operations are used by the vector operations below.
+
+// z1<<_W + z0 = x+y+c, with c == 0 or 1
+func addWW_g(x, y, c Word) (z1, z0 Word) {
+	yc := y + c
+	z0 = x + yc
+	if z0 < x || yc < y {
+		z1 = 1
+	}
+	return
+}
+
+// z1<<_W + z0 = x-y-c, with c == 0 or 1
+func subWW_g(x, y, c Word) (z1, z0 Word) {
+	yc := y + c
+	z0 = x - yc
+	if z0 > x || yc < y {
+		z1 = 1
+	}
+	return
+}
+
+// z1<<_W + z0 = x*y
+func mulWW(x, y Word) (z1, z0 Word) { return mulWW_g(x, y) }
+
+// Adapted from Warren, Hacker's Delight, p. 132.
+func mulWW_g(x, y Word) (z1, z0 Word) {
+	x0 := x & _M2
+	x1 := x >> _W2
+	y0 := y & _M2
+	y1 := y >> _W2
+	w0 := x0 * y0
+	t := x1*y0 + w0>>_W2
+	w1 := t & _M2
+	w2 := t >> _W2
+	w1 += x0 * y1
+	z1 = x1*y1 + w2 + w1>>_W2
+	z0 = x * y
+	return
+}
+
+// z1<<_W + z0 = x*y + c
+func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
+	z1, zz0 := mulWW(x, y)
+	if z0 = zz0 + c; z0 < zz0 {
+		z1++
+	}
+	return
+}
+
+// Length of x in bits.
+func bitLen(x Word) (n int) { return bitLen_g(x) }
+func bitLen_g(x Word) (n int) {
+	for ; x >= 0x8000; x >>= 16 {
+		n += 16
+	}
+	if x >= 0x80 {
+		x >>= 8
+		n += 8
+	}
+	if x >= 0x8 {
+		x >>= 4
+		n += 4
+	}
+	if x >= 0x2 {
+		x >>= 2
+		n += 2
+	}
+	if x >= 0x1 {
+		n++
+	}
+	return
+}
+
+// log2 computes the integer binary logarithm of x.
+// The result is the integer n for which 2^n <= x < 2^(n+1).
+// If x == 0, the result is -1.
+func log2(x Word) int {
+	return bitLen(x) - 1
+}
+
+// Number of leading zeros in x.
+func leadingZeros(x Word) uint {
+	return uint(_W - bitLen(x))
+}
+
+// q = (u1<<_W + u0 - r)/y
+func divWW(x1, x0, y Word) (q, r Word) { return divWW_g(x1, x0, y) }
+
+// Adapted from Warren, Hacker's Delight, p. 152.
+func divWW_g(u1, u0, v Word) (q, r Word) {
+	if u1 >= v {
+		return 1<<_W - 1, 1<<_W - 1
+	}
+
+	s := leadingZeros(v)
+	v <<= s
+
+	vn1 := v >> _W2
+	vn0 := v & _M2
+	un32 := u1<<s | u0>>(_W-s)
+	un10 := u0 << s
+	un1 := un10 >> _W2
+	un0 := un10 & _M2
+	q1 := un32 / vn1
+	rhat := un32 - q1*vn1
+
+	for q1 >= _B2 || q1*vn0 > _B2*rhat+un1 {
+		q1--
+		rhat += vn1
+		if rhat >= _B2 {
+			break
+		}
+	}
+
+	un21 := un32*_B2 + un1 - q1*v
+	q0 := un21 / vn1
+	rhat = un21 - q0*vn1
+
+	for q0 >= _B2 || q0*vn0 > _B2*rhat+un0 {
+		q0--
+		rhat += vn1
+		if rhat >= _B2 {
+			break
+		}
+	}
+
+	return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s
+}
+
+func addVV(z, x, y []Word) (c Word) { return addVV_g(z, x, y) }
+func addVV_g(z, x, y []Word) (c Word) {
+	for i := range z {
+		c, z[i] = addWW_g(x[i], y[i], c)
+	}
+	return
+}
+
+func subVV(z, x, y []Word) (c Word) { return subVV_g(z, x, y) }
+func subVV_g(z, x, y []Word) (c Word) {
+	for i := range z {
+		c, z[i] = subWW_g(x[i], y[i], c)
+	}
+	return
+}
+
+func addVW(z, x []Word, y Word) (c Word) { return addVW_g(z, x, y) }
+func addVW_g(z, x []Word, y Word) (c Word) {
+	c = y
+	for i := range z {
+		c, z[i] = addWW_g(x[i], c, 0)
+	}
+	return
+}
+
+func subVW(z, x []Word, y Word) (c Word) { return subVW_g(z, x, y) }
+func subVW_g(z, x []Word, y Word) (c Word) {
+	c = y
+	for i := range z {
+		c, z[i] = subWW_g(x[i], c, 0)
+	}
+	return
+}
+
+func shlVU(z, x []Word, s uint) (c Word) { return shlVU_g(z, x, s) }
+func shlVU_g(z, x []Word, s uint) (c Word) {
+	if n := len(z); n > 0 {
+		ŝ := _W - s
+		w1 := x[n-1]
+		c = w1 >> ŝ
+		for i := n - 1; i > 0; i-- {
+			w := w1
+			w1 = x[i-1]
+			z[i] = w<<s | w1>>ŝ
+		}
+		z[0] = w1 << s
+	}
+	return
+}
+
+func shrVU(z, x []Word, s uint) (c Word) { return shrVU_g(z, x, s) }
+func shrVU_g(z, x []Word, s uint) (c Word) {
+	if n := len(z); n > 0 {
+		ŝ := _W - s
+		w1 := x[0]
+		c = w1 << ŝ
+		for i := 0; i < n-1; i++ {
+			w := w1
+			w1 = x[i+1]
+			z[i] = w>>s | w1<<ŝ
+		}
+		z[n-1] = w1 >> s
+	}
+	return
+}
+
+func mulAddVWW(z, x []Word, y, r Word) (c Word) { return mulAddVWW_g(z, x, y, r) }
+func mulAddVWW_g(z, x []Word, y, r Word) (c Word) {
+	c = r
+	for i := range z {
+		c, z[i] = mulAddWWW_g(x[i], y, c)
+	}
+	return
+}
+
+func addMulVVW(z, x []Word, y Word) (c Word) { return addMulVVW_g(z, x, y) }
+func addMulVVW_g(z, x []Word, y Word) (c Word) {
+	for i := range z {
+		z1, z0 := mulAddWWW_g(x[i], y, z[i])
+		c, z[i] = addWW_g(z0, c, 0)
+		c += z1
+	}
+	return
+}
+
+func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) { return divWVW_g(z, xn, x, y) }
+func divWVW_g(z []Word, xn Word, x []Word, y Word) (r Word) {
+	r = xn
+	for i := len(z) - 1; i >= 0; i-- {
+		z[i], r = divWW_g(r, x[i], y)
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/math/big/arith_decl.go b/third_party/gofrontend/libgo/go/math/big/arith_decl.go
new file mode 100644
index 0000000..068cc8d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/arith_decl.go
@@ -0,0 +1,19 @@
+// Copyright 2010 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 big
+
+// implemented in arith_$GOARCH.s
+func mulWW(x, y Word) (z1, z0 Word)
+func divWW(x1, x0, y Word) (q, r Word)
+func addVV(z, x, y []Word) (c Word)
+func subVV(z, x, y []Word) (c Word)
+func addVW(z, x []Word, y Word) (c Word)
+func subVW(z, x []Word, y Word) (c Word)
+func shlVU(z, x []Word, s uint) (c Word)
+func shrVU(z, x []Word, s uint) (c Word)
+func mulAddVWW(z, x []Word, y, r Word) (c Word)
+func addMulVVW(z, x []Word, y Word) (c Word)
+func divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
+func bitLen(x Word) (n int)
diff --git a/third_party/gofrontend/libgo/go/math/big/arith_test.go b/third_party/gofrontend/libgo/go/math/big/arith_test.go
new file mode 100644
index 0000000..3615a65
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/arith_test.go
@@ -0,0 +1,456 @@
+// 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 big
+
+import (
+	"math/rand"
+	"testing"
+)
+
+type funWW func(x, y, c Word) (z1, z0 Word)
+type argWW struct {
+	x, y, c, z1, z0 Word
+}
+
+var sumWW = []argWW{
+	{0, 0, 0, 0, 0},
+	{0, 1, 0, 0, 1},
+	{0, 0, 1, 0, 1},
+	{0, 1, 1, 0, 2},
+	{12345, 67890, 0, 0, 80235},
+	{12345, 67890, 1, 0, 80236},
+	{_M, 1, 0, 1, 0},
+	{_M, 0, 1, 1, 0},
+	{_M, 1, 1, 1, 1},
+	{_M, _M, 0, 1, _M - 1},
+	{_M, _M, 1, 1, _M},
+}
+
+func testFunWW(t *testing.T, msg string, f funWW, a argWW) {
+	z1, z0 := f(a.x, a.y, a.c)
+	if z1 != a.z1 || z0 != a.z0 {
+		t.Errorf("%s%+v\n\tgot z1:z0 = %#x:%#x; want %#x:%#x", msg, a, z1, z0, a.z1, a.z0)
+	}
+}
+
+func TestFunWW(t *testing.T) {
+	for _, a := range sumWW {
+		arg := a
+		testFunWW(t, "addWW_g", addWW_g, arg)
+
+		arg = argWW{a.y, a.x, a.c, a.z1, a.z0}
+		testFunWW(t, "addWW_g symmetric", addWW_g, arg)
+
+		arg = argWW{a.z0, a.x, a.c, a.z1, a.y}
+		testFunWW(t, "subWW_g", subWW_g, arg)
+
+		arg = argWW{a.z0, a.y, a.c, a.z1, a.x}
+		testFunWW(t, "subWW_g symmetric", subWW_g, arg)
+	}
+}
+
+type funVV func(z, x, y []Word) (c Word)
+type argVV struct {
+	z, x, y nat
+	c       Word
+}
+
+var sumVV = []argVV{
+	{},
+	{nat{0}, nat{0}, nat{0}, 0},
+	{nat{1}, nat{1}, nat{0}, 0},
+	{nat{0}, nat{_M}, nat{1}, 1},
+	{nat{80235}, nat{12345}, nat{67890}, 0},
+	{nat{_M - 1}, nat{_M}, nat{_M}, 1},
+	{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, nat{1, 0, 0, 0}, 1},
+	{nat{0, 0, 0, _M}, nat{_M, _M, _M, _M - 1}, nat{1, 0, 0, 0}, 0},
+	{nat{0, 0, 0, 0}, nat{_M, 0, _M, 0}, nat{1, _M, 0, _M}, 1},
+}
+
+func testFunVV(t *testing.T, msg string, f funVV, a argVV) {
+	z := make(nat, len(a.z))
+	c := f(z, a.x, a.y)
+	for i, zi := range z {
+		if zi != a.z[i] {
+			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
+			break
+		}
+	}
+	if c != a.c {
+		t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
+	}
+}
+
+func TestFunVV(t *testing.T) {
+	for _, a := range sumVV {
+		arg := a
+		testFunVV(t, "addVV_g", addVV_g, arg)
+		testFunVV(t, "addVV", addVV, arg)
+
+		arg = argVV{a.z, a.y, a.x, a.c}
+		testFunVV(t, "addVV_g symmetric", addVV_g, arg)
+		testFunVV(t, "addVV symmetric", addVV, arg)
+
+		arg = argVV{a.x, a.z, a.y, a.c}
+		testFunVV(t, "subVV_g", subVV_g, arg)
+		testFunVV(t, "subVV", subVV, arg)
+
+		arg = argVV{a.y, a.z, a.x, a.c}
+		testFunVV(t, "subVV_g symmetric", subVV_g, arg)
+		testFunVV(t, "subVV symmetric", subVV, arg)
+	}
+}
+
+// Always the same seed for reproducible results.
+var rnd = rand.New(rand.NewSource(0))
+
+func rndW() Word {
+	return Word(rnd.Int63()<<1 | rnd.Int63n(2))
+}
+
+func rndV(n int) []Word {
+	v := make([]Word, n)
+	for i := range v {
+		v[i] = rndW()
+	}
+	return v
+}
+
+func benchmarkFunVV(b *testing.B, f funVV, n int) {
+	x := rndV(n)
+	y := rndV(n)
+	z := make([]Word, n)
+	b.SetBytes(int64(n * _W))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		f(z, x, y)
+	}
+}
+
+func BenchmarkAddVV_1(b *testing.B)   { benchmarkFunVV(b, addVV, 1) }
+func BenchmarkAddVV_2(b *testing.B)   { benchmarkFunVV(b, addVV, 2) }
+func BenchmarkAddVV_3(b *testing.B)   { benchmarkFunVV(b, addVV, 3) }
+func BenchmarkAddVV_4(b *testing.B)   { benchmarkFunVV(b, addVV, 4) }
+func BenchmarkAddVV_5(b *testing.B)   { benchmarkFunVV(b, addVV, 5) }
+func BenchmarkAddVV_1e1(b *testing.B) { benchmarkFunVV(b, addVV, 1e1) }
+func BenchmarkAddVV_1e2(b *testing.B) { benchmarkFunVV(b, addVV, 1e2) }
+func BenchmarkAddVV_1e3(b *testing.B) { benchmarkFunVV(b, addVV, 1e3) }
+func BenchmarkAddVV_1e4(b *testing.B) { benchmarkFunVV(b, addVV, 1e4) }
+func BenchmarkAddVV_1e5(b *testing.B) { benchmarkFunVV(b, addVV, 1e5) }
+
+type funVW func(z, x []Word, y Word) (c Word)
+type argVW struct {
+	z, x nat
+	y    Word
+	c    Word
+}
+
+var sumVW = []argVW{
+	{},
+	{nil, nil, 2, 2},
+	{nat{0}, nat{0}, 0, 0},
+	{nat{1}, nat{0}, 1, 0},
+	{nat{1}, nat{1}, 0, 0},
+	{nat{0}, nat{_M}, 1, 1},
+	{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, 1, 1},
+}
+
+var prodVW = []argVW{
+	{},
+	{nat{0}, nat{0}, 0, 0},
+	{nat{0}, nat{_M}, 0, 0},
+	{nat{0}, nat{0}, _M, 0},
+	{nat{1}, nat{1}, 1, 0},
+	{nat{22793}, nat{991}, 23, 0},
+	{nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0},
+	{nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0},
+	{nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0},
+	{nat{_M << 1 & _M}, nat{_M}, 1 << 1, _M >> (_W - 1)},
+	{nat{_M << 7 & _M}, nat{_M}, 1 << 7, _M >> (_W - 7)},
+	{nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, _M >> (_W - 7)},
+}
+
+var lshVW = []argVW{
+	{},
+	{nat{0}, nat{0}, 0, 0},
+	{nat{0}, nat{0}, 1, 0},
+	{nat{0}, nat{0}, 20, 0},
+
+	{nat{_M}, nat{_M}, 0, 0},
+	{nat{_M << 1 & _M}, nat{_M}, 1, 1},
+	{nat{_M << 20 & _M}, nat{_M}, 20, _M >> (_W - 20)},
+
+	{nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0},
+	{nat{_M << 1 & _M, _M, _M}, nat{_M, _M, _M}, 1, 1},
+	{nat{_M << 20 & _M, _M, _M}, nat{_M, _M, _M}, 20, _M >> (_W - 20)},
+}
+
+var rshVW = []argVW{
+	{},
+	{nat{0}, nat{0}, 0, 0},
+	{nat{0}, nat{0}, 1, 0},
+	{nat{0}, nat{0}, 20, 0},
+
+	{nat{_M}, nat{_M}, 0, 0},
+	{nat{_M >> 1}, nat{_M}, 1, _M << (_W - 1) & _M},
+	{nat{_M >> 20}, nat{_M}, 20, _M << (_W - 20) & _M},
+
+	{nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0},
+	{nat{_M, _M, _M >> 1}, nat{_M, _M, _M}, 1, _M << (_W - 1) & _M},
+	{nat{_M, _M, _M >> 20}, nat{_M, _M, _M}, 20, _M << (_W - 20) & _M},
+}
+
+func testFunVW(t *testing.T, msg string, f funVW, a argVW) {
+	z := make(nat, len(a.z))
+	c := f(z, a.x, a.y)
+	for i, zi := range z {
+		if zi != a.z[i] {
+			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
+			break
+		}
+	}
+	if c != a.c {
+		t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
+	}
+}
+
+func makeFunVW(f func(z, x []Word, s uint) (c Word)) funVW {
+	return func(z, x []Word, s Word) (c Word) {
+		return f(z, x, uint(s))
+	}
+}
+
+func TestFunVW(t *testing.T) {
+	for _, a := range sumVW {
+		arg := a
+		testFunVW(t, "addVW_g", addVW_g, arg)
+		testFunVW(t, "addVW", addVW, arg)
+
+		arg = argVW{a.x, a.z, a.y, a.c}
+		testFunVW(t, "subVW_g", subVW_g, arg)
+		testFunVW(t, "subVW", subVW, arg)
+	}
+
+	shlVW_g := makeFunVW(shlVU_g)
+	shlVW := makeFunVW(shlVU)
+	for _, a := range lshVW {
+		arg := a
+		testFunVW(t, "shlVU_g", shlVW_g, arg)
+		testFunVW(t, "shlVU", shlVW, arg)
+	}
+
+	shrVW_g := makeFunVW(shrVU_g)
+	shrVW := makeFunVW(shrVU)
+	for _, a := range rshVW {
+		arg := a
+		testFunVW(t, "shrVU_g", shrVW_g, arg)
+		testFunVW(t, "shrVU", shrVW, arg)
+	}
+}
+
+func benchmarkFunVW(b *testing.B, f funVW, n int) {
+	x := rndV(n)
+	y := rndW()
+	z := make([]Word, n)
+	b.SetBytes(int64(n * _W))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		f(z, x, y)
+	}
+}
+
+func BenchmarkAddVW_1(b *testing.B)   { benchmarkFunVW(b, addVW, 1) }
+func BenchmarkAddVW_2(b *testing.B)   { benchmarkFunVW(b, addVW, 2) }
+func BenchmarkAddVW_3(b *testing.B)   { benchmarkFunVW(b, addVW, 3) }
+func BenchmarkAddVW_4(b *testing.B)   { benchmarkFunVW(b, addVW, 4) }
+func BenchmarkAddVW_5(b *testing.B)   { benchmarkFunVW(b, addVW, 5) }
+func BenchmarkAddVW_1e1(b *testing.B) { benchmarkFunVW(b, addVW, 1e1) }
+func BenchmarkAddVW_1e2(b *testing.B) { benchmarkFunVW(b, addVW, 1e2) }
+func BenchmarkAddVW_1e3(b *testing.B) { benchmarkFunVW(b, addVW, 1e3) }
+func BenchmarkAddVW_1e4(b *testing.B) { benchmarkFunVW(b, addVW, 1e4) }
+func BenchmarkAddVW_1e5(b *testing.B) { benchmarkFunVW(b, addVW, 1e5) }
+
+type funVWW func(z, x []Word, y, r Word) (c Word)
+type argVWW struct {
+	z, x nat
+	y, r Word
+	c    Word
+}
+
+var prodVWW = []argVWW{
+	{},
+	{nat{0}, nat{0}, 0, 0, 0},
+	{nat{991}, nat{0}, 0, 991, 0},
+	{nat{0}, nat{_M}, 0, 0, 0},
+	{nat{991}, nat{_M}, 0, 991, 0},
+	{nat{0}, nat{0}, _M, 0, 0},
+	{nat{991}, nat{0}, _M, 991, 0},
+	{nat{1}, nat{1}, 1, 0, 0},
+	{nat{992}, nat{1}, 1, 991, 0},
+	{nat{22793}, nat{991}, 23, 0, 0},
+	{nat{22800}, nat{991}, 23, 7, 0},
+	{nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0, 0},
+	{nat{7, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 7, 0},
+	{nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0, 0},
+	{nat{991, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 991, 0},
+	{nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0, 0},
+	{nat{991, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 991, 0},
+	{nat{_M << 1 & _M}, nat{_M}, 1 << 1, 0, _M >> (_W - 1)},
+	{nat{_M<<1&_M + 1}, nat{_M}, 1 << 1, 1, _M >> (_W - 1)},
+	{nat{_M << 7 & _M}, nat{_M}, 1 << 7, 0, _M >> (_W - 7)},
+	{nat{_M<<7&_M + 1<<6}, nat{_M}, 1 << 7, 1 << 6, _M >> (_W - 7)},
+	{nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 0, _M >> (_W - 7)},
+	{nat{_M<<7&_M + 1<<6, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 1 << 6, _M >> (_W - 7)},
+}
+
+func testFunVWW(t *testing.T, msg string, f funVWW, a argVWW) {
+	z := make(nat, len(a.z))
+	c := f(z, a.x, a.y, a.r)
+	for i, zi := range z {
+		if zi != a.z[i] {
+			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
+			break
+		}
+	}
+	if c != a.c {
+		t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
+	}
+}
+
+// TODO(gri) mulAddVWW and divWVW are symmetric operations but
+//           their signature is not symmetric. Try to unify.
+
+type funWVW func(z []Word, xn Word, x []Word, y Word) (r Word)
+type argWVW struct {
+	z  nat
+	xn Word
+	x  nat
+	y  Word
+	r  Word
+}
+
+func testFunWVW(t *testing.T, msg string, f funWVW, a argWVW) {
+	z := make(nat, len(a.z))
+	r := f(z, a.xn, a.x, a.y)
+	for i, zi := range z {
+		if zi != a.z[i] {
+			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
+			break
+		}
+	}
+	if r != a.r {
+		t.Errorf("%s%+v\n\tgot r = %#x; want %#x", msg, a, r, a.r)
+	}
+}
+
+func TestFunVWW(t *testing.T) {
+	for _, a := range prodVWW {
+		arg := a
+		testFunVWW(t, "mulAddVWW_g", mulAddVWW_g, arg)
+		testFunVWW(t, "mulAddVWW", mulAddVWW, arg)
+
+		if a.y != 0 && a.r < a.y {
+			arg := argWVW{a.x, a.c, a.z, a.y, a.r}
+			testFunWVW(t, "divWVW_g", divWVW_g, arg)
+			testFunWVW(t, "divWVW", divWVW, arg)
+		}
+	}
+}
+
+var mulWWTests = []struct {
+	x, y Word
+	q, r Word
+}{
+	{_M, _M, _M - 1, 1},
+	// 32 bit only: {0xc47dfa8c, 50911, 0x98a4, 0x998587f4},
+}
+
+func TestMulWW(t *testing.T) {
+	for i, test := range mulWWTests {
+		q, r := mulWW_g(test.x, test.y)
+		if q != test.q || r != test.r {
+			t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
+		}
+	}
+}
+
+var mulAddWWWTests = []struct {
+	x, y, c Word
+	q, r    Word
+}{
+	// TODO(agl): These will only work on 64-bit platforms.
+	// {15064310297182388543, 0xe7df04d2d35d5d80, 13537600649892366549, 13644450054494335067, 10832252001440893781},
+	// {15064310297182388543, 0xdab2f18048baa68d, 13644450054494335067, 12869334219691522700, 14233854684711418382},
+	{_M, _M, 0, _M - 1, 1},
+	{_M, _M, _M, _M, 0},
+}
+
+func TestMulAddWWW(t *testing.T) {
+	for i, test := range mulAddWWWTests {
+		q, r := mulAddWWW_g(test.x, test.y, test.c)
+		if q != test.q || r != test.r {
+			t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
+		}
+	}
+}
+
+func benchmarkAddMulVVW(b *testing.B, n int) {
+	x := rndV(n)
+	y := rndW()
+	z := make([]Word, n)
+	b.SetBytes(int64(n * _W))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		addMulVVW(z, x, y)
+	}
+}
+
+func BenchmarkAddMulVVW_1(b *testing.B)   { benchmarkAddMulVVW(b, 1) }
+func BenchmarkAddMulVVW_2(b *testing.B)   { benchmarkAddMulVVW(b, 2) }
+func BenchmarkAddMulVVW_3(b *testing.B)   { benchmarkAddMulVVW(b, 3) }
+func BenchmarkAddMulVVW_4(b *testing.B)   { benchmarkAddMulVVW(b, 4) }
+func BenchmarkAddMulVVW_5(b *testing.B)   { benchmarkAddMulVVW(b, 5) }
+func BenchmarkAddMulVVW_1e1(b *testing.B) { benchmarkAddMulVVW(b, 1e1) }
+func BenchmarkAddMulVVW_1e2(b *testing.B) { benchmarkAddMulVVW(b, 1e2) }
+func BenchmarkAddMulVVW_1e3(b *testing.B) { benchmarkAddMulVVW(b, 1e3) }
+func BenchmarkAddMulVVW_1e4(b *testing.B) { benchmarkAddMulVVW(b, 1e4) }
+func BenchmarkAddMulVVW_1e5(b *testing.B) { benchmarkAddMulVVW(b, 1e5) }
+
+func testWordBitLen(t *testing.T, fname string, f func(Word) int) {
+	for i := 0; i <= _W; i++ {
+		x := Word(1) << uint(i-1) // i == 0 => x == 0
+		n := f(x)
+		if n != i {
+			t.Errorf("got %d; want %d for %s(%#x)", n, i, fname, x)
+		}
+	}
+}
+
+func TestWordBitLen(t *testing.T) {
+	testWordBitLen(t, "bitLen", bitLen)
+	testWordBitLen(t, "bitLen_g", bitLen_g)
+}
+
+// runs b.N iterations of bitLen called on a Word containing (1 << nbits)-1.
+func benchmarkBitLenN(b *testing.B, nbits uint) {
+	testword := Word((uint64(1) << nbits) - 1)
+	for i := 0; i < b.N; i++ {
+		bitLen(testword)
+	}
+}
+
+// Individual bitLen tests.  Numbers chosen to examine both sides
+// of powers-of-two boundaries.
+func BenchmarkBitLen0(b *testing.B)  { benchmarkBitLenN(b, 0) }
+func BenchmarkBitLen1(b *testing.B)  { benchmarkBitLenN(b, 1) }
+func BenchmarkBitLen2(b *testing.B)  { benchmarkBitLenN(b, 2) }
+func BenchmarkBitLen3(b *testing.B)  { benchmarkBitLenN(b, 3) }
+func BenchmarkBitLen4(b *testing.B)  { benchmarkBitLenN(b, 4) }
+func BenchmarkBitLen5(b *testing.B)  { benchmarkBitLenN(b, 5) }
+func BenchmarkBitLen8(b *testing.B)  { benchmarkBitLenN(b, 8) }
+func BenchmarkBitLen9(b *testing.B)  { benchmarkBitLenN(b, 9) }
+func BenchmarkBitLen16(b *testing.B) { benchmarkBitLenN(b, 16) }
+func BenchmarkBitLen17(b *testing.B) { benchmarkBitLenN(b, 17) }
+func BenchmarkBitLen31(b *testing.B) { benchmarkBitLenN(b, 31) }
diff --git a/third_party/gofrontend/libgo/go/math/big/calibrate_test.go b/third_party/gofrontend/libgo/go/math/big/calibrate_test.go
new file mode 100644
index 0000000..f69ffbf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/calibrate_test.go
@@ -0,0 +1,88 @@
+// 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.
+
+// This file prints execution times for the Mul benchmark
+// given different Karatsuba thresholds. The result may be
+// used to manually fine-tune the threshold constant. The
+// results are somewhat fragile; use repeated runs to get
+// a clear picture.
+
+// Usage: go test -run=TestCalibrate -calibrate
+
+package big
+
+import (
+	"flag"
+	"fmt"
+	"testing"
+	"time"
+)
+
+var calibrate = flag.Bool("calibrate", false, "run calibration test")
+
+func karatsubaLoad(b *testing.B) {
+	BenchmarkMul(b)
+}
+
+// measureKaratsuba returns the time to run a Karatsuba-relevant benchmark
+// given Karatsuba threshold th.
+func measureKaratsuba(th int) time.Duration {
+	th, karatsubaThreshold = karatsubaThreshold, th
+	res := testing.Benchmark(karatsubaLoad)
+	karatsubaThreshold = th
+	return time.Duration(res.NsPerOp())
+}
+
+func computeThresholds() {
+	fmt.Printf("Multiplication times for varying Karatsuba thresholds\n")
+	fmt.Printf("(run repeatedly for good results)\n")
+
+	// determine Tk, the work load execution time using basic multiplication
+	Tb := measureKaratsuba(1e9) // th == 1e9 => Karatsuba multiplication disabled
+	fmt.Printf("Tb = %10s\n", Tb)
+
+	// thresholds
+	th := 4
+	th1 := -1
+	th2 := -1
+
+	var deltaOld time.Duration
+	for count := -1; count != 0 && th < 128; count-- {
+		// determine Tk, the work load execution time using Karatsuba multiplication
+		Tk := measureKaratsuba(th)
+
+		// improvement over Tb
+		delta := (Tb - Tk) * 100 / Tb
+
+		fmt.Printf("th = %3d  Tk = %10s  %4d%%", th, Tk, delta)
+
+		// determine break-even point
+		if Tk < Tb && th1 < 0 {
+			th1 = th
+			fmt.Print("  break-even point")
+		}
+
+		// determine diminishing return
+		if 0 < delta && delta < deltaOld && th2 < 0 {
+			th2 = th
+			fmt.Print("  diminishing return")
+		}
+		deltaOld = delta
+
+		fmt.Println()
+
+		// trigger counter
+		if th1 >= 0 && th2 >= 0 && count < 0 {
+			count = 10 // this many extra measurements after we got both thresholds
+		}
+
+		th++
+	}
+}
+
+func TestCalibrate(t *testing.T) {
+	if *calibrate {
+		computeThresholds()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/math/big/gcd_test.go b/third_party/gofrontend/libgo/go/math/big/gcd_test.go
new file mode 100644
index 0000000..c0b9f58
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/gcd_test.go
@@ -0,0 +1,47 @@
+// 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.
+
+// This file implements a GCD benchmark.
+// Usage: go test math/big -test.bench GCD
+
+package big
+
+import (
+	"math/rand"
+	"testing"
+)
+
+// randInt returns a pseudo-random Int in the range [1<<(size-1), (1<<size) - 1]
+func randInt(r *rand.Rand, size uint) *Int {
+	n := new(Int).Lsh(intOne, size-1)
+	x := new(Int).Rand(r, n)
+	return x.Add(x, n) // make sure result > 1<<(size-1)
+}
+
+func runGCD(b *testing.B, aSize, bSize uint) {
+	b.StopTimer()
+	var r = rand.New(rand.NewSource(1234))
+	aa := randInt(r, aSize)
+	bb := randInt(r, bSize)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		new(Int).GCD(nil, nil, aa, bb)
+	}
+}
+
+func BenchmarkGCD10x10(b *testing.B)         { runGCD(b, 10, 10) }
+func BenchmarkGCD10x100(b *testing.B)        { runGCD(b, 10, 100) }
+func BenchmarkGCD10x1000(b *testing.B)       { runGCD(b, 10, 1000) }
+func BenchmarkGCD10x10000(b *testing.B)      { runGCD(b, 10, 10000) }
+func BenchmarkGCD10x100000(b *testing.B)     { runGCD(b, 10, 100000) }
+func BenchmarkGCD100x100(b *testing.B)       { runGCD(b, 100, 100) }
+func BenchmarkGCD100x1000(b *testing.B)      { runGCD(b, 100, 1000) }
+func BenchmarkGCD100x10000(b *testing.B)     { runGCD(b, 100, 10000) }
+func BenchmarkGCD100x100000(b *testing.B)    { runGCD(b, 100, 100000) }
+func BenchmarkGCD1000x1000(b *testing.B)     { runGCD(b, 1000, 1000) }
+func BenchmarkGCD1000x10000(b *testing.B)    { runGCD(b, 1000, 10000) }
+func BenchmarkGCD1000x100000(b *testing.B)   { runGCD(b, 1000, 100000) }
+func BenchmarkGCD10000x10000(b *testing.B)   { runGCD(b, 10000, 10000) }
+func BenchmarkGCD10000x100000(b *testing.B)  { runGCD(b, 10000, 100000) }
+func BenchmarkGCD100000x100000(b *testing.B) { runGCD(b, 100000, 100000) }
diff --git a/third_party/gofrontend/libgo/go/math/big/hilbert_test.go b/third_party/gofrontend/libgo/go/math/big/hilbert_test.go
new file mode 100644
index 0000000..1a84341
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/hilbert_test.go
@@ -0,0 +1,160 @@
+// 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.
+
+// A little test program and benchmark for rational arithmetics.
+// Computes a Hilbert matrix, its inverse, multiplies them
+// and verifies that the product is the identity matrix.
+
+package big
+
+import (
+	"fmt"
+	"testing"
+)
+
+type matrix struct {
+	n, m int
+	a    []*Rat
+}
+
+func (a *matrix) at(i, j int) *Rat {
+	if !(0 <= i && i < a.n && 0 <= j && j < a.m) {
+		panic("index out of range")
+	}
+	return a.a[i*a.m+j]
+}
+
+func (a *matrix) set(i, j int, x *Rat) {
+	if !(0 <= i && i < a.n && 0 <= j && j < a.m) {
+		panic("index out of range")
+	}
+	a.a[i*a.m+j] = x
+}
+
+func newMatrix(n, m int) *matrix {
+	if !(0 <= n && 0 <= m) {
+		panic("illegal matrix")
+	}
+	a := new(matrix)
+	a.n = n
+	a.m = m
+	a.a = make([]*Rat, n*m)
+	return a
+}
+
+func newUnit(n int) *matrix {
+	a := newMatrix(n, n)
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			x := NewRat(0, 1)
+			if i == j {
+				x.SetInt64(1)
+			}
+			a.set(i, j, x)
+		}
+	}
+	return a
+}
+
+func newHilbert(n int) *matrix {
+	a := newMatrix(n, n)
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			a.set(i, j, NewRat(1, int64(i+j+1)))
+		}
+	}
+	return a
+}
+
+func newInverseHilbert(n int) *matrix {
+	a := newMatrix(n, n)
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			x1 := new(Rat).SetInt64(int64(i + j + 1))
+			x2 := new(Rat).SetInt(new(Int).Binomial(int64(n+i), int64(n-j-1)))
+			x3 := new(Rat).SetInt(new(Int).Binomial(int64(n+j), int64(n-i-1)))
+			x4 := new(Rat).SetInt(new(Int).Binomial(int64(i+j), int64(i)))
+
+			x1.Mul(x1, x2)
+			x1.Mul(x1, x3)
+			x1.Mul(x1, x4)
+			x1.Mul(x1, x4)
+
+			if (i+j)&1 != 0 {
+				x1.Neg(x1)
+			}
+
+			a.set(i, j, x1)
+		}
+	}
+	return a
+}
+
+func (a *matrix) mul(b *matrix) *matrix {
+	if a.m != b.n {
+		panic("illegal matrix multiply")
+	}
+	c := newMatrix(a.n, b.m)
+	for i := 0; i < c.n; i++ {
+		for j := 0; j < c.m; j++ {
+			x := NewRat(0, 1)
+			for k := 0; k < a.m; k++ {
+				x.Add(x, new(Rat).Mul(a.at(i, k), b.at(k, j)))
+			}
+			c.set(i, j, x)
+		}
+	}
+	return c
+}
+
+func (a *matrix) eql(b *matrix) bool {
+	if a.n != b.n || a.m != b.m {
+		return false
+	}
+	for i := 0; i < a.n; i++ {
+		for j := 0; j < a.m; j++ {
+			if a.at(i, j).Cmp(b.at(i, j)) != 0 {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+func (a *matrix) String() string {
+	s := ""
+	for i := 0; i < a.n; i++ {
+		for j := 0; j < a.m; j++ {
+			s += fmt.Sprintf("\t%s", a.at(i, j))
+		}
+		s += "\n"
+	}
+	return s
+}
+
+func doHilbert(t *testing.T, n int) {
+	a := newHilbert(n)
+	b := newInverseHilbert(n)
+	I := newUnit(n)
+	ab := a.mul(b)
+	if !ab.eql(I) {
+		if t == nil {
+			panic("Hilbert failed")
+		}
+		t.Errorf("a   = %s\n", a)
+		t.Errorf("b   = %s\n", b)
+		t.Errorf("a*b = %s\n", ab)
+		t.Errorf("I   = %s\n", I)
+	}
+}
+
+func TestHilbert(t *testing.T) {
+	doHilbert(t, 10)
+}
+
+func BenchmarkHilbert(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		doHilbert(nil, 10)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/math/big/int.go b/third_party/gofrontend/libgo/go/math/big/int.go
new file mode 100644
index 0000000..269949d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/int.go
@@ -0,0 +1,1011 @@
+// 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.
+
+// This file implements signed multi-precision integers.
+
+package big
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"math/rand"
+	"strings"
+)
+
+// An Int represents a signed multi-precision integer.
+// The zero value for an Int represents the value 0.
+type Int struct {
+	neg bool // sign
+	abs nat  // absolute value of the integer
+}
+
+var intOne = &Int{false, natOne}
+
+// Sign returns:
+//
+//	-1 if x <  0
+//	 0 if x == 0
+//	+1 if x >  0
+//
+func (x *Int) Sign() int {
+	if len(x.abs) == 0 {
+		return 0
+	}
+	if x.neg {
+		return -1
+	}
+	return 1
+}
+
+// SetInt64 sets z to x and returns z.
+func (z *Int) SetInt64(x int64) *Int {
+	neg := false
+	if x < 0 {
+		neg = true
+		x = -x
+	}
+	z.abs = z.abs.setUint64(uint64(x))
+	z.neg = neg
+	return z
+}
+
+// SetUint64 sets z to x and returns z.
+func (z *Int) SetUint64(x uint64) *Int {
+	z.abs = z.abs.setUint64(x)
+	z.neg = false
+	return z
+}
+
+// NewInt allocates and returns a new Int set to x.
+func NewInt(x int64) *Int {
+	return new(Int).SetInt64(x)
+}
+
+// Set sets z to x and returns z.
+func (z *Int) Set(x *Int) *Int {
+	if z != x {
+		z.abs = z.abs.set(x.abs)
+		z.neg = x.neg
+	}
+	return z
+}
+
+// Bits provides raw (unchecked but fast) access to x by returning its
+// absolute value as a little-endian Word slice. The result and x share
+// the same underlying array.
+// Bits is intended to support implementation of missing low-level Int
+// functionality outside this package; it should be avoided otherwise.
+func (x *Int) Bits() []Word {
+	return x.abs
+}
+
+// SetBits provides raw (unchecked but fast) access to z by setting its
+// value to abs, interpreted as a little-endian Word slice, and returning
+// z. The result and abs share the same underlying array.
+// SetBits is intended to support implementation of missing low-level Int
+// functionality outside this package; it should be avoided otherwise.
+func (z *Int) SetBits(abs []Word) *Int {
+	z.abs = nat(abs).norm()
+	z.neg = false
+	return z
+}
+
+// Abs sets z to |x| (the absolute value of x) and returns z.
+func (z *Int) Abs(x *Int) *Int {
+	z.Set(x)
+	z.neg = false
+	return z
+}
+
+// Neg sets z to -x and returns z.
+func (z *Int) Neg(x *Int) *Int {
+	z.Set(x)
+	z.neg = len(z.abs) > 0 && !z.neg // 0 has no sign
+	return z
+}
+
+// Add sets z to the sum x+y and returns z.
+func (z *Int) Add(x, y *Int) *Int {
+	neg := x.neg
+	if x.neg == y.neg {
+		// x + y == x + y
+		// (-x) + (-y) == -(x + y)
+		z.abs = z.abs.add(x.abs, y.abs)
+	} else {
+		// x + (-y) == x - y == -(y - x)
+		// (-x) + y == y - x == -(x - y)
+		if x.abs.cmp(y.abs) >= 0 {
+			z.abs = z.abs.sub(x.abs, y.abs)
+		} else {
+			neg = !neg
+			z.abs = z.abs.sub(y.abs, x.abs)
+		}
+	}
+	z.neg = len(z.abs) > 0 && neg // 0 has no sign
+	return z
+}
+
+// Sub sets z to the difference x-y and returns z.
+func (z *Int) Sub(x, y *Int) *Int {
+	neg := x.neg
+	if x.neg != y.neg {
+		// x - (-y) == x + y
+		// (-x) - y == -(x + y)
+		z.abs = z.abs.add(x.abs, y.abs)
+	} else {
+		// x - y == x - y == -(y - x)
+		// (-x) - (-y) == y - x == -(x - y)
+		if x.abs.cmp(y.abs) >= 0 {
+			z.abs = z.abs.sub(x.abs, y.abs)
+		} else {
+			neg = !neg
+			z.abs = z.abs.sub(y.abs, x.abs)
+		}
+	}
+	z.neg = len(z.abs) > 0 && neg // 0 has no sign
+	return z
+}
+
+// Mul sets z to the product x*y and returns z.
+func (z *Int) Mul(x, y *Int) *Int {
+	// x * y == x * y
+	// x * (-y) == -(x * y)
+	// (-x) * y == -(x * y)
+	// (-x) * (-y) == x * y
+	z.abs = z.abs.mul(x.abs, y.abs)
+	z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
+	return z
+}
+
+// MulRange sets z to the product of all integers
+// in the range [a, b] inclusively and returns z.
+// If a > b (empty range), the result is 1.
+func (z *Int) MulRange(a, b int64) *Int {
+	switch {
+	case a > b:
+		return z.SetInt64(1) // empty range
+	case a <= 0 && b >= 0:
+		return z.SetInt64(0) // range includes 0
+	}
+	// a <= b && (b < 0 || a > 0)
+
+	neg := false
+	if a < 0 {
+		neg = (b-a)&1 == 0
+		a, b = -b, -a
+	}
+
+	z.abs = z.abs.mulRange(uint64(a), uint64(b))
+	z.neg = neg
+	return z
+}
+
+// Binomial sets z to the binomial coefficient of (n, k) and returns z.
+func (z *Int) Binomial(n, k int64) *Int {
+	var a, b Int
+	a.MulRange(n-k+1, n)
+	b.MulRange(1, k)
+	return z.Quo(&a, &b)
+}
+
+// Quo sets z to the quotient x/y for y != 0 and returns z.
+// If y == 0, a division-by-zero run-time panic occurs.
+// Quo implements truncated division (like Go); see QuoRem for more details.
+func (z *Int) Quo(x, y *Int) *Int {
+	z.abs, _ = z.abs.div(nil, x.abs, y.abs)
+	z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
+	return z
+}
+
+// Rem sets z to the remainder x%y for y != 0 and returns z.
+// If y == 0, a division-by-zero run-time panic occurs.
+// Rem implements truncated modulus (like Go); see QuoRem for more details.
+func (z *Int) Rem(x, y *Int) *Int {
+	_, z.abs = nat(nil).div(z.abs, x.abs, y.abs)
+	z.neg = len(z.abs) > 0 && x.neg // 0 has no sign
+	return z
+}
+
+// QuoRem sets z to the quotient x/y and r to the remainder x%y
+// and returns the pair (z, r) for y != 0.
+// If y == 0, a division-by-zero run-time panic occurs.
+//
+// QuoRem implements T-division and modulus (like Go):
+//
+//	q = x/y      with the result truncated to zero
+//	r = x - y*q
+//
+// (See Daan Leijen, ``Division and Modulus for Computer Scientists''.)
+// See DivMod for Euclidean division and modulus (unlike Go).
+//
+func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) {
+	z.abs, r.abs = z.abs.div(r.abs, x.abs, y.abs)
+	z.neg, r.neg = len(z.abs) > 0 && x.neg != y.neg, len(r.abs) > 0 && x.neg // 0 has no sign
+	return z, r
+}
+
+// Div sets z to the quotient x/y for y != 0 and returns z.
+// If y == 0, a division-by-zero run-time panic occurs.
+// Div implements Euclidean division (unlike Go); see DivMod for more details.
+func (z *Int) Div(x, y *Int) *Int {
+	y_neg := y.neg // z may be an alias for y
+	var r Int
+	z.QuoRem(x, y, &r)
+	if r.neg {
+		if y_neg {
+			z.Add(z, intOne)
+		} else {
+			z.Sub(z, intOne)
+		}
+	}
+	return z
+}
+
+// Mod sets z to the modulus x%y for y != 0 and returns z.
+// If y == 0, a division-by-zero run-time panic occurs.
+// Mod implements Euclidean modulus (unlike Go); see DivMod for more details.
+func (z *Int) Mod(x, y *Int) *Int {
+	y0 := y // save y
+	if z == y || alias(z.abs, y.abs) {
+		y0 = new(Int).Set(y)
+	}
+	var q Int
+	q.QuoRem(x, y, z)
+	if z.neg {
+		if y0.neg {
+			z.Sub(z, y0)
+		} else {
+			z.Add(z, y0)
+		}
+	}
+	return z
+}
+
+// DivMod sets z to the quotient x div y and m to the modulus x mod y
+// and returns the pair (z, m) for y != 0.
+// If y == 0, a division-by-zero run-time panic occurs.
+//
+// DivMod implements Euclidean division and modulus (unlike Go):
+//
+//	q = x div y  such that
+//	m = x - y*q  with 0 <= m < |q|
+//
+// (See Raymond T. Boute, ``The Euclidean definition of the functions
+// div and mod''. ACM Transactions on Programming Languages and
+// Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992.
+// ACM press.)
+// See QuoRem for T-division and modulus (like Go).
+//
+func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) {
+	y0 := y // save y
+	if z == y || alias(z.abs, y.abs) {
+		y0 = new(Int).Set(y)
+	}
+	z.QuoRem(x, y, m)
+	if m.neg {
+		if y0.neg {
+			z.Add(z, intOne)
+			m.Sub(m, y0)
+		} else {
+			z.Sub(z, intOne)
+			m.Add(m, y0)
+		}
+	}
+	return z, m
+}
+
+// Cmp compares x and y and returns:
+//
+//   -1 if x <  y
+//    0 if x == y
+//   +1 if x >  y
+//
+func (x *Int) Cmp(y *Int) (r int) {
+	// x cmp y == x cmp y
+	// x cmp (-y) == x
+	// (-x) cmp y == y
+	// (-x) cmp (-y) == -(x cmp y)
+	switch {
+	case x.neg == y.neg:
+		r = x.abs.cmp(y.abs)
+		if x.neg {
+			r = -r
+		}
+	case x.neg:
+		r = -1
+	default:
+		r = 1
+	}
+	return
+}
+
+func (x *Int) String() string {
+	switch {
+	case x == nil:
+		return "<nil>"
+	case x.neg:
+		return "-" + x.abs.decimalString()
+	}
+	return x.abs.decimalString()
+}
+
+func charset(ch rune) string {
+	switch ch {
+	case 'b':
+		return lowercaseDigits[0:2]
+	case 'o':
+		return lowercaseDigits[0:8]
+	case 'd', 's', 'v':
+		return lowercaseDigits[0:10]
+	case 'x':
+		return lowercaseDigits[0:16]
+	case 'X':
+		return uppercaseDigits[0:16]
+	}
+	return "" // unknown format
+}
+
+// write count copies of text to s
+func writeMultiple(s fmt.State, text string, count int) {
+	if len(text) > 0 {
+		b := []byte(text)
+		for ; count > 0; count-- {
+			s.Write(b)
+		}
+	}
+}
+
+// Format is a support routine for fmt.Formatter. It accepts
+// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x'
+// (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
+// Also supported are the full suite of package fmt's format
+// verbs for integral types, including '+', '-', and ' '
+// for sign control, '#' for leading zero in octal and for
+// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X"
+// respectively, specification of minimum digits precision,
+// output field width, space or zero padding, and left or
+// right justification.
+//
+func (x *Int) Format(s fmt.State, ch rune) {
+	cs := charset(ch)
+
+	// special cases
+	switch {
+	case cs == "":
+		// unknown format
+		fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
+		return
+	case x == nil:
+		fmt.Fprint(s, "<nil>")
+		return
+	}
+
+	// determine sign character
+	sign := ""
+	switch {
+	case x.neg:
+		sign = "-"
+	case s.Flag('+'): // supersedes ' ' when both specified
+		sign = "+"
+	case s.Flag(' '):
+		sign = " "
+	}
+
+	// determine prefix characters for indicating output base
+	prefix := ""
+	if s.Flag('#') {
+		switch ch {
+		case 'o': // octal
+			prefix = "0"
+		case 'x': // hexadecimal
+			prefix = "0x"
+		case 'X':
+			prefix = "0X"
+		}
+	}
+
+	// determine digits with base set by len(cs) and digit characters from cs
+	digits := x.abs.string(cs)
+
+	// number of characters for the three classes of number padding
+	var left int   // space characters to left of digits for right justification ("%8d")
+	var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
+	var right int  // space characters to right of digits for left justification ("%-8d")
+
+	// determine number padding from precision: the least number of digits to output
+	precision, precisionSet := s.Precision()
+	if precisionSet {
+		switch {
+		case len(digits) < precision:
+			zeroes = precision - len(digits) // count of zero padding
+		case digits == "0" && precision == 0:
+			return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
+		}
+	}
+
+	// determine field pad from width: the least number of characters to output
+	length := len(sign) + len(prefix) + zeroes + len(digits)
+	if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
+		switch d := width - length; {
+		case s.Flag('-'):
+			// pad on the right with spaces; supersedes '0' when both specified
+			right = d
+		case s.Flag('0') && !precisionSet:
+			// pad with zeroes unless precision also specified
+			zeroes = d
+		default:
+			// pad on the left with spaces
+			left = d
+		}
+	}
+
+	// print number as [left pad][sign][prefix][zero pad][digits][right pad]
+	writeMultiple(s, " ", left)
+	writeMultiple(s, sign, 1)
+	writeMultiple(s, prefix, 1)
+	writeMultiple(s, "0", zeroes)
+	writeMultiple(s, digits, 1)
+	writeMultiple(s, " ", right)
+}
+
+// scan sets z to the integer value corresponding to the longest possible prefix
+// read from r representing a signed integer number in a given conversion base.
+// It returns z, the actual conversion base used, and an error, if any. In the
+// error case, the value of z is undefined but the returned value is nil. The
+// syntax follows the syntax of integer literals in Go.
+//
+// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// is 0, the string prefix determines the actual conversion base. A prefix of
+// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
+// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
+//
+func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, error) {
+	// determine sign
+	ch, _, err := r.ReadRune()
+	if err != nil {
+		return nil, 0, err
+	}
+	neg := false
+	switch ch {
+	case '-':
+		neg = true
+	case '+': // nothing to do
+	default:
+		r.UnreadRune()
+	}
+
+	// determine mantissa
+	z.abs, base, err = z.abs.scan(r, base)
+	if err != nil {
+		return nil, base, err
+	}
+	z.neg = len(z.abs) > 0 && neg // 0 has no sign
+
+	return z, base, nil
+}
+
+// Scan is a support routine for fmt.Scanner; it sets z to the value of
+// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
+// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
+func (z *Int) Scan(s fmt.ScanState, ch rune) error {
+	s.SkipSpace() // skip leading space characters
+	base := 0
+	switch ch {
+	case 'b':
+		base = 2
+	case 'o':
+		base = 8
+	case 'd':
+		base = 10
+	case 'x', 'X':
+		base = 16
+	case 's', 'v':
+		// let scan determine the base
+	default:
+		return errors.New("Int.Scan: invalid verb")
+	}
+	_, _, err := z.scan(s, base)
+	return err
+}
+
+// Int64 returns the int64 representation of x.
+// If x cannot be represented in an int64, the result is undefined.
+func (x *Int) Int64() int64 {
+	v := int64(x.Uint64())
+	if x.neg {
+		v = -v
+	}
+	return v
+}
+
+// Uint64 returns the uint64 representation of x.
+// If x cannot be represented in a uint64, the result is undefined.
+func (x *Int) Uint64() uint64 {
+	if len(x.abs) == 0 {
+		return 0
+	}
+	v := uint64(x.abs[0])
+	if _W == 32 && len(x.abs) > 1 {
+		v |= uint64(x.abs[1]) << 32
+	}
+	return v
+}
+
+// SetString sets z to the value of s, interpreted in the given base,
+// and returns z and a boolean indicating success. If SetString fails,
+// the value of z is undefined but the returned value is nil.
+//
+// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// is 0, the string prefix determines the actual conversion base. A prefix of
+// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
+// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
+//
+func (z *Int) SetString(s string, base int) (*Int, bool) {
+	r := strings.NewReader(s)
+	_, _, err := z.scan(r, base)
+	if err != nil {
+		return nil, false
+	}
+	_, _, err = r.ReadRune()
+	if err != io.EOF {
+		return nil, false
+	}
+	return z, true // err == io.EOF => scan consumed all of s
+}
+
+// SetBytes interprets buf as the bytes of a big-endian unsigned
+// integer, sets z to that value, and returns z.
+func (z *Int) SetBytes(buf []byte) *Int {
+	z.abs = z.abs.setBytes(buf)
+	z.neg = false
+	return z
+}
+
+// Bytes returns the absolute value of x as a big-endian byte slice.
+func (x *Int) Bytes() []byte {
+	buf := make([]byte, len(x.abs)*_S)
+	return buf[x.abs.bytes(buf):]
+}
+
+// BitLen returns the length of the absolute value of x in bits.
+// The bit length of 0 is 0.
+func (x *Int) BitLen() int {
+	return x.abs.bitLen()
+}
+
+// Exp sets z = x**y mod |m| (i.e. the sign of m is ignored), and returns z.
+// If y <= 0, the result is 1 mod |m|; if m == nil or m == 0, z = x**y.
+// See Knuth, volume 2, section 4.6.3.
+func (z *Int) Exp(x, y, m *Int) *Int {
+	var yWords nat
+	if !y.neg {
+		yWords = y.abs
+	}
+	// y >= 0
+
+	var mWords nat
+	if m != nil {
+		mWords = m.abs // m.abs may be nil for m == 0
+	}
+
+	z.abs = z.abs.expNN(x.abs, yWords, mWords)
+	z.neg = len(z.abs) > 0 && x.neg && len(yWords) > 0 && yWords[0]&1 == 1 // 0 has no sign
+	return z
+}
+
+// GCD sets z to the greatest common divisor of a and b, which both must
+// be > 0, and returns z.
+// If x and y are not nil, GCD sets x and y such that z = a*x + b*y.
+// If either a or b is <= 0, GCD sets z = x = y = 0.
+func (z *Int) GCD(x, y, a, b *Int) *Int {
+	if a.Sign() <= 0 || b.Sign() <= 0 {
+		z.SetInt64(0)
+		if x != nil {
+			x.SetInt64(0)
+		}
+		if y != nil {
+			y.SetInt64(0)
+		}
+		return z
+	}
+	if x == nil && y == nil {
+		return z.binaryGCD(a, b)
+	}
+
+	A := new(Int).Set(a)
+	B := new(Int).Set(b)
+
+	X := new(Int)
+	Y := new(Int).SetInt64(1)
+
+	lastX := new(Int).SetInt64(1)
+	lastY := new(Int)
+
+	q := new(Int)
+	temp := new(Int)
+
+	for len(B.abs) > 0 {
+		r := new(Int)
+		q, r = q.QuoRem(A, B, r)
+
+		A, B = B, r
+
+		temp.Set(X)
+		X.Mul(X, q)
+		X.neg = !X.neg
+		X.Add(X, lastX)
+		lastX.Set(temp)
+
+		temp.Set(Y)
+		Y.Mul(Y, q)
+		Y.neg = !Y.neg
+		Y.Add(Y, lastY)
+		lastY.Set(temp)
+	}
+
+	if x != nil {
+		*x = *lastX
+	}
+
+	if y != nil {
+		*y = *lastY
+	}
+
+	*z = *A
+	return z
+}
+
+// binaryGCD sets z to the greatest common divisor of a and b, which both must
+// be > 0, and returns z.
+// See Knuth, The Art of Computer Programming, Vol. 2, Section 4.5.2, Algorithm B.
+func (z *Int) binaryGCD(a, b *Int) *Int {
+	u := z
+	v := new(Int)
+
+	// use one Euclidean iteration to ensure that u and v are approx. the same size
+	switch {
+	case len(a.abs) > len(b.abs):
+		u.Set(b)
+		v.Rem(a, b)
+	case len(a.abs) < len(b.abs):
+		u.Set(a)
+		v.Rem(b, a)
+	default:
+		u.Set(a)
+		v.Set(b)
+	}
+
+	// v might be 0 now
+	if len(v.abs) == 0 {
+		return u
+	}
+	// u > 0 && v > 0
+
+	// determine largest k such that u = u' << k, v = v' << k
+	k := u.abs.trailingZeroBits()
+	if vk := v.abs.trailingZeroBits(); vk < k {
+		k = vk
+	}
+	u.Rsh(u, k)
+	v.Rsh(v, k)
+
+	// determine t (we know that u > 0)
+	t := new(Int)
+	if u.abs[0]&1 != 0 {
+		// u is odd
+		t.Neg(v)
+	} else {
+		t.Set(u)
+	}
+
+	for len(t.abs) > 0 {
+		// reduce t
+		t.Rsh(t, t.abs.trailingZeroBits())
+		if t.neg {
+			v, t = t, v
+			v.neg = len(v.abs) > 0 && !v.neg // 0 has no sign
+		} else {
+			u, t = t, u
+		}
+		t.Sub(u, v)
+	}
+
+	return z.Lsh(u, k)
+}
+
+// ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
+// If it returns true, x is prime with probability 1 - 1/4^n.
+// If it returns false, x is not prime.
+func (x *Int) ProbablyPrime(n int) bool {
+	return !x.neg && x.abs.probablyPrime(n)
+}
+
+// Rand sets z to a pseudo-random number in [0, n) and returns z.
+func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
+	z.neg = false
+	if n.neg == true || len(n.abs) == 0 {
+		z.abs = nil
+		return z
+	}
+	z.abs = z.abs.random(rnd, n.abs, n.abs.bitLen())
+	return z
+}
+
+// ModInverse sets z to the multiplicative inverse of g in the group ℤ/pℤ (where
+// p is a prime) and returns z.
+func (z *Int) ModInverse(g, p *Int) *Int {
+	var d Int
+	d.GCD(z, nil, g, p)
+	// x and y are such that g*x + p*y = d. Since p is prime, d = 1. Taking
+	// that modulo p results in g*x = 1, therefore x is the inverse element.
+	if z.neg {
+		z.Add(z, p)
+	}
+	return z
+}
+
+// Lsh sets z = x << n and returns z.
+func (z *Int) Lsh(x *Int, n uint) *Int {
+	z.abs = z.abs.shl(x.abs, n)
+	z.neg = x.neg
+	return z
+}
+
+// Rsh sets z = x >> n and returns z.
+func (z *Int) Rsh(x *Int, n uint) *Int {
+	if x.neg {
+		// (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1)
+		t := z.abs.sub(x.abs, natOne) // no underflow because |x| > 0
+		t = t.shr(t, n)
+		z.abs = t.add(t, natOne)
+		z.neg = true // z cannot be zero if x is negative
+		return z
+	}
+
+	z.abs = z.abs.shr(x.abs, n)
+	z.neg = false
+	return z
+}
+
+// Bit returns the value of the i'th bit of x. That is, it
+// returns (x>>i)&1. The bit index i must be >= 0.
+func (x *Int) Bit(i int) uint {
+	if i == 0 {
+		// optimization for common case: odd/even test of x
+		if len(x.abs) > 0 {
+			return uint(x.abs[0] & 1) // bit 0 is same for -x
+		}
+		return 0
+	}
+	if i < 0 {
+		panic("negative bit index")
+	}
+	if x.neg {
+		t := nat(nil).sub(x.abs, natOne)
+		return t.bit(uint(i)) ^ 1
+	}
+
+	return x.abs.bit(uint(i))
+}
+
+// SetBit sets z to x, with x's i'th bit set to b (0 or 1).
+// That is, if b is 1 SetBit sets z = x | (1 << i);
+// if b is 0 SetBit sets z = x &^ (1 << i). If b is not 0 or 1,
+// SetBit will panic.
+func (z *Int) SetBit(x *Int, i int, b uint) *Int {
+	if i < 0 {
+		panic("negative bit index")
+	}
+	if x.neg {
+		t := z.abs.sub(x.abs, natOne)
+		t = t.setBit(t, uint(i), b^1)
+		z.abs = t.add(t, natOne)
+		z.neg = len(z.abs) > 0
+		return z
+	}
+	z.abs = z.abs.setBit(x.abs, uint(i), b)
+	z.neg = false
+	return z
+}
+
+// And sets z = x & y and returns z.
+func (z *Int) And(x, y *Int) *Int {
+	if x.neg == y.neg {
+		if x.neg {
+			// (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1)
+			x1 := nat(nil).sub(x.abs, natOne)
+			y1 := nat(nil).sub(y.abs, natOne)
+			z.abs = z.abs.add(z.abs.or(x1, y1), natOne)
+			z.neg = true // z cannot be zero if x and y are negative
+			return z
+		}
+
+		// x & y == x & y
+		z.abs = z.abs.and(x.abs, y.abs)
+		z.neg = false
+		return z
+	}
+
+	// x.neg != y.neg
+	if x.neg {
+		x, y = y, x // & is symmetric
+	}
+
+	// x & (-y) == x & ^(y-1) == x &^ (y-1)
+	y1 := nat(nil).sub(y.abs, natOne)
+	z.abs = z.abs.andNot(x.abs, y1)
+	z.neg = false
+	return z
+}
+
+// AndNot sets z = x &^ y and returns z.
+func (z *Int) AndNot(x, y *Int) *Int {
+	if x.neg == y.neg {
+		if x.neg {
+			// (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1)
+			x1 := nat(nil).sub(x.abs, natOne)
+			y1 := nat(nil).sub(y.abs, natOne)
+			z.abs = z.abs.andNot(y1, x1)
+			z.neg = false
+			return z
+		}
+
+		// x &^ y == x &^ y
+		z.abs = z.abs.andNot(x.abs, y.abs)
+		z.neg = false
+		return z
+	}
+
+	if x.neg {
+		// (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1)
+		x1 := nat(nil).sub(x.abs, natOne)
+		z.abs = z.abs.add(z.abs.or(x1, y.abs), natOne)
+		z.neg = true // z cannot be zero if x is negative and y is positive
+		return z
+	}
+
+	// x &^ (-y) == x &^ ^(y-1) == x & (y-1)
+	y1 := nat(nil).add(y.abs, natOne)
+	z.abs = z.abs.and(x.abs, y1)
+	z.neg = false
+	return z
+}
+
+// Or sets z = x | y and returns z.
+func (z *Int) Or(x, y *Int) *Int {
+	if x.neg == y.neg {
+		if x.neg {
+			// (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1)
+			x1 := nat(nil).sub(x.abs, natOne)
+			y1 := nat(nil).sub(y.abs, natOne)
+			z.abs = z.abs.add(z.abs.and(x1, y1), natOne)
+			z.neg = true // z cannot be zero if x and y are negative
+			return z
+		}
+
+		// x | y == x | y
+		z.abs = z.abs.or(x.abs, y.abs)
+		z.neg = false
+		return z
+	}
+
+	// x.neg != y.neg
+	if x.neg {
+		x, y = y, x // | is symmetric
+	}
+
+	// x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1)
+	y1 := nat(nil).sub(y.abs, natOne)
+	z.abs = z.abs.add(z.abs.andNot(y1, x.abs), natOne)
+	z.neg = true // z cannot be zero if one of x or y is negative
+	return z
+}
+
+// Xor sets z = x ^ y and returns z.
+func (z *Int) Xor(x, y *Int) *Int {
+	if x.neg == y.neg {
+		if x.neg {
+			// (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1)
+			x1 := nat(nil).sub(x.abs, natOne)
+			y1 := nat(nil).sub(y.abs, natOne)
+			z.abs = z.abs.xor(x1, y1)
+			z.neg = false
+			return z
+		}
+
+		// x ^ y == x ^ y
+		z.abs = z.abs.xor(x.abs, y.abs)
+		z.neg = false
+		return z
+	}
+
+	// x.neg != y.neg
+	if x.neg {
+		x, y = y, x // ^ is symmetric
+	}
+
+	// x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1)
+	y1 := nat(nil).sub(y.abs, natOne)
+	z.abs = z.abs.add(z.abs.xor(x.abs, y1), natOne)
+	z.neg = true // z cannot be zero if only one of x or y is negative
+	return z
+}
+
+// Not sets z = ^x and returns z.
+func (z *Int) Not(x *Int) *Int {
+	if x.neg {
+		// ^(-x) == ^(^(x-1)) == x-1
+		z.abs = z.abs.sub(x.abs, natOne)
+		z.neg = false
+		return z
+	}
+
+	// ^x == -x-1 == -(x+1)
+	z.abs = z.abs.add(x.abs, natOne)
+	z.neg = true // z cannot be zero if x is positive
+	return z
+}
+
+// Gob codec version. Permits backward-compatible changes to the encoding.
+const intGobVersion byte = 1
+
+// GobEncode implements the gob.GobEncoder interface.
+func (x *Int) GobEncode() ([]byte, error) {
+	if x == nil {
+		return nil, nil
+	}
+	buf := make([]byte, 1+len(x.abs)*_S) // extra byte for version and sign bit
+	i := x.abs.bytes(buf) - 1            // i >= 0
+	b := intGobVersion << 1              // make space for sign bit
+	if x.neg {
+		b |= 1
+	}
+	buf[i] = b
+	return buf[i:], nil
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (z *Int) GobDecode(buf []byte) error {
+	if len(buf) == 0 {
+		// Other side sent a nil or default value.
+		*z = Int{}
+		return nil
+	}
+	b := buf[0]
+	if b>>1 != intGobVersion {
+		return errors.New(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1))
+	}
+	z.neg = b&1 != 0
+	z.abs = z.abs.setBytes(buf[1:])
+	return nil
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (z *Int) MarshalJSON() ([]byte, error) {
+	// TODO(gri): get rid of the []byte/string conversions
+	return []byte(z.String()), nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (z *Int) UnmarshalJSON(text []byte) error {
+	// TODO(gri): get rid of the []byte/string conversions
+	if _, ok := z.SetString(string(text), 0); !ok {
+		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
+	}
+	return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface
+func (z *Int) MarshalText() (text []byte, err error) {
+	return []byte(z.String()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface
+func (z *Int) UnmarshalText(text []byte) error {
+	if _, ok := z.SetString(string(text), 0); !ok {
+		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/math/big/int_test.go b/third_party/gofrontend/libgo/go/math/big/int_test.go
new file mode 100644
index 0000000..299dc72
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/int_test.go
@@ -0,0 +1,1601 @@
+// 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 big
+
+import (
+	"bytes"
+	"encoding/gob"
+	"encoding/hex"
+	"encoding/json"
+	"encoding/xml"
+	"fmt"
+	"math/rand"
+	"testing"
+	"testing/quick"
+)
+
+func isNormalized(x *Int) bool {
+	if len(x.abs) == 0 {
+		return !x.neg
+	}
+	// len(x.abs) > 0
+	return x.abs[len(x.abs)-1] != 0
+}
+
+type funZZ func(z, x, y *Int) *Int
+type argZZ struct {
+	z, x, y *Int
+}
+
+var sumZZ = []argZZ{
+	{NewInt(0), NewInt(0), NewInt(0)},
+	{NewInt(1), NewInt(1), NewInt(0)},
+	{NewInt(1111111110), NewInt(123456789), NewInt(987654321)},
+	{NewInt(-1), NewInt(-1), NewInt(0)},
+	{NewInt(864197532), NewInt(-123456789), NewInt(987654321)},
+	{NewInt(-1111111110), NewInt(-123456789), NewInt(-987654321)},
+}
+
+var prodZZ = []argZZ{
+	{NewInt(0), NewInt(0), NewInt(0)},
+	{NewInt(0), NewInt(1), NewInt(0)},
+	{NewInt(1), NewInt(1), NewInt(1)},
+	{NewInt(-991 * 991), NewInt(991), NewInt(-991)},
+	// TODO(gri) add larger products
+}
+
+func TestSignZ(t *testing.T) {
+	var zero Int
+	for _, a := range sumZZ {
+		s := a.z.Sign()
+		e := a.z.Cmp(&zero)
+		if s != e {
+			t.Errorf("got %d; want %d for z = %v", s, e, a.z)
+		}
+	}
+}
+
+func TestSetZ(t *testing.T) {
+	for _, a := range sumZZ {
+		var z Int
+		z.Set(a.z)
+		if !isNormalized(&z) {
+			t.Errorf("%v is not normalized", z)
+		}
+		if (&z).Cmp(a.z) != 0 {
+			t.Errorf("got z = %v; want %v", z, a.z)
+		}
+	}
+}
+
+func TestAbsZ(t *testing.T) {
+	var zero Int
+	for _, a := range sumZZ {
+		var z Int
+		z.Abs(a.z)
+		var e Int
+		e.Set(a.z)
+		if e.Cmp(&zero) < 0 {
+			e.Sub(&zero, &e)
+		}
+		if z.Cmp(&e) != 0 {
+			t.Errorf("got z = %v; want %v", z, e)
+		}
+	}
+}
+
+func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) {
+	var z Int
+	f(&z, a.x, a.y)
+	if !isNormalized(&z) {
+		t.Errorf("%s%v is not normalized", msg, z)
+	}
+	if (&z).Cmp(a.z) != 0 {
+		t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z)
+	}
+}
+
+func TestSumZZ(t *testing.T) {
+	AddZZ := func(z, x, y *Int) *Int { return z.Add(x, y) }
+	SubZZ := func(z, x, y *Int) *Int { return z.Sub(x, y) }
+	for _, a := range sumZZ {
+		arg := a
+		testFunZZ(t, "AddZZ", AddZZ, arg)
+
+		arg = argZZ{a.z, a.y, a.x}
+		testFunZZ(t, "AddZZ symmetric", AddZZ, arg)
+
+		arg = argZZ{a.x, a.z, a.y}
+		testFunZZ(t, "SubZZ", SubZZ, arg)
+
+		arg = argZZ{a.y, a.z, a.x}
+		testFunZZ(t, "SubZZ symmetric", SubZZ, arg)
+	}
+}
+
+func TestProdZZ(t *testing.T) {
+	MulZZ := func(z, x, y *Int) *Int { return z.Mul(x, y) }
+	for _, a := range prodZZ {
+		arg := a
+		testFunZZ(t, "MulZZ", MulZZ, arg)
+
+		arg = argZZ{a.z, a.y, a.x}
+		testFunZZ(t, "MulZZ symmetric", MulZZ, arg)
+	}
+}
+
+// mulBytes returns x*y via grade school multiplication. Both inputs
+// and the result are assumed to be in big-endian representation (to
+// match the semantics of Int.Bytes and Int.SetBytes).
+func mulBytes(x, y []byte) []byte {
+	z := make([]byte, len(x)+len(y))
+
+	// multiply
+	k0 := len(z) - 1
+	for j := len(y) - 1; j >= 0; j-- {
+		d := int(y[j])
+		if d != 0 {
+			k := k0
+			carry := 0
+			for i := len(x) - 1; i >= 0; i-- {
+				t := int(z[k]) + int(x[i])*d + carry
+				z[k], carry = byte(t), t>>8
+				k--
+			}
+			z[k] = byte(carry)
+		}
+		k0--
+	}
+
+	// normalize (remove leading 0's)
+	i := 0
+	for i < len(z) && z[i] == 0 {
+		i++
+	}
+
+	return z[i:]
+}
+
+func checkMul(a, b []byte) bool {
+	var x, y, z1 Int
+	x.SetBytes(a)
+	y.SetBytes(b)
+	z1.Mul(&x, &y)
+
+	var z2 Int
+	z2.SetBytes(mulBytes(a, b))
+
+	return z1.Cmp(&z2) == 0
+}
+
+func TestMul(t *testing.T) {
+	if err := quick.Check(checkMul, nil); err != nil {
+		t.Error(err)
+	}
+}
+
+var mulRangesZ = []struct {
+	a, b int64
+	prod string
+}{
+	// entirely positive ranges are covered by mulRangesN
+	{-1, 1, "0"},
+	{-2, -1, "2"},
+	{-3, -2, "6"},
+	{-3, -1, "-6"},
+	{1, 3, "6"},
+	{-10, -10, "-10"},
+	{0, -1, "1"},                      // empty range
+	{-1, -100, "1"},                   // empty range
+	{-1, 1, "0"},                      // range includes 0
+	{-1e9, 0, "0"},                    // range includes 0
+	{-1e9, 1e9, "0"},                  // range includes 0
+	{-10, -1, "3628800"},              // 10!
+	{-20, -2, "-2432902008176640000"}, // -20!
+	{-99, -1,
+		"-933262154439441526816992388562667004907159682643816214685929" +
+			"638952175999932299156089414639761565182862536979208272237582" +
+			"511852109168640000000000000000000000", // -99!
+	},
+}
+
+func TestMulRangeZ(t *testing.T) {
+	var tmp Int
+	// test entirely positive ranges
+	for i, r := range mulRangesN {
+		prod := tmp.MulRange(int64(r.a), int64(r.b)).String()
+		if prod != r.prod {
+			t.Errorf("#%da: got %s; want %s", i, prod, r.prod)
+		}
+	}
+	// test other ranges
+	for i, r := range mulRangesZ {
+		prod := tmp.MulRange(r.a, r.b).String()
+		if prod != r.prod {
+			t.Errorf("#%db: got %s; want %s", i, prod, r.prod)
+		}
+	}
+}
+
+var stringTests = []struct {
+	in   string
+	out  string
+	base int
+	val  int64
+	ok   bool
+}{
+	{in: "", ok: false},
+	{in: "a", ok: false},
+	{in: "z", ok: false},
+	{in: "+", ok: false},
+	{in: "-", ok: false},
+	{in: "0b", ok: false},
+	{in: "0x", ok: false},
+	{in: "2", base: 2, ok: false},
+	{in: "0b2", base: 0, ok: false},
+	{in: "08", ok: false},
+	{in: "8", base: 8, ok: false},
+	{in: "0xg", base: 0, ok: false},
+	{in: "g", base: 16, ok: false},
+	{"0", "0", 0, 0, true},
+	{"0", "0", 10, 0, true},
+	{"0", "0", 16, 0, true},
+	{"+0", "0", 0, 0, true},
+	{"-0", "0", 0, 0, true},
+	{"10", "10", 0, 10, true},
+	{"10", "10", 10, 10, true},
+	{"10", "10", 16, 16, true},
+	{"-10", "-10", 16, -16, true},
+	{"+10", "10", 16, 16, true},
+	{"0x10", "16", 0, 16, true},
+	{in: "0x10", base: 16, ok: false},
+	{"-0x10", "-16", 0, -16, true},
+	{"+0x10", "16", 0, 16, true},
+	{"00", "0", 0, 0, true},
+	{"0", "0", 8, 0, true},
+	{"07", "7", 0, 7, true},
+	{"7", "7", 8, 7, true},
+	{"023", "19", 0, 19, true},
+	{"23", "23", 8, 19, true},
+	{"cafebabe", "cafebabe", 16, 0xcafebabe, true},
+	{"0b0", "0", 0, 0, true},
+	{"-111", "-111", 2, -7, true},
+	{"-0b111", "-7", 0, -7, true},
+	{"0b1001010111", "599", 0, 0x257, true},
+	{"1001010111", "1001010111", 2, 0x257, true},
+}
+
+func format(base int) string {
+	switch base {
+	case 2:
+		return "%b"
+	case 8:
+		return "%o"
+	case 16:
+		return "%x"
+	}
+	return "%d"
+}
+
+func TestGetString(t *testing.T) {
+	z := new(Int)
+	for i, test := range stringTests {
+		if !test.ok {
+			continue
+		}
+		z.SetInt64(test.val)
+
+		if test.base == 10 {
+			s := z.String()
+			if s != test.out {
+				t.Errorf("#%da got %s; want %s", i, s, test.out)
+			}
+		}
+
+		s := fmt.Sprintf(format(test.base), z)
+		if s != test.out {
+			t.Errorf("#%db got %s; want %s", i, s, test.out)
+		}
+	}
+}
+
+func TestSetString(t *testing.T) {
+	tmp := new(Int)
+	for i, test := range stringTests {
+		// initialize to a non-zero value so that issues with parsing
+		// 0 are detected
+		tmp.SetInt64(1234567890)
+		n1, ok1 := new(Int).SetString(test.in, test.base)
+		n2, ok2 := tmp.SetString(test.in, test.base)
+		expected := NewInt(test.val)
+		if ok1 != test.ok || ok2 != test.ok {
+			t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
+			continue
+		}
+		if !ok1 {
+			if n1 != nil {
+				t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
+			}
+			continue
+		}
+		if !ok2 {
+			if n2 != nil {
+				t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
+			}
+			continue
+		}
+
+		if ok1 && !isNormalized(n1) {
+			t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
+		}
+		if ok2 && !isNormalized(n2) {
+			t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
+		}
+
+		if n1.Cmp(expected) != 0 {
+			t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
+		}
+		if n2.Cmp(expected) != 0 {
+			t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
+		}
+	}
+}
+
+var formatTests = []struct {
+	input  string
+	format string
+	output string
+}{
+	{"<nil>", "%x", "<nil>"},
+	{"<nil>", "%#x", "<nil>"},
+	{"<nil>", "%#y", "%!y(big.Int=<nil>)"},
+
+	{"10", "%b", "1010"},
+	{"10", "%o", "12"},
+	{"10", "%d", "10"},
+	{"10", "%v", "10"},
+	{"10", "%x", "a"},
+	{"10", "%X", "A"},
+	{"-10", "%X", "-A"},
+	{"10", "%y", "%!y(big.Int=10)"},
+	{"-10", "%y", "%!y(big.Int=-10)"},
+
+	{"10", "%#b", "1010"},
+	{"10", "%#o", "012"},
+	{"10", "%#d", "10"},
+	{"10", "%#v", "10"},
+	{"10", "%#x", "0xa"},
+	{"10", "%#X", "0XA"},
+	{"-10", "%#X", "-0XA"},
+	{"10", "%#y", "%!y(big.Int=10)"},
+	{"-10", "%#y", "%!y(big.Int=-10)"},
+
+	{"1234", "%d", "1234"},
+	{"1234", "%3d", "1234"},
+	{"1234", "%4d", "1234"},
+	{"-1234", "%d", "-1234"},
+	{"1234", "% 5d", " 1234"},
+	{"1234", "%+5d", "+1234"},
+	{"1234", "%-5d", "1234 "},
+	{"1234", "%x", "4d2"},
+	{"1234", "%X", "4D2"},
+	{"-1234", "%3x", "-4d2"},
+	{"-1234", "%4x", "-4d2"},
+	{"-1234", "%5x", " -4d2"},
+	{"-1234", "%-5x", "-4d2 "},
+	{"1234", "%03d", "1234"},
+	{"1234", "%04d", "1234"},
+	{"1234", "%05d", "01234"},
+	{"1234", "%06d", "001234"},
+	{"-1234", "%06d", "-01234"},
+	{"1234", "%+06d", "+01234"},
+	{"1234", "% 06d", " 01234"},
+	{"1234", "%-6d", "1234  "},
+	{"1234", "%-06d", "1234  "},
+	{"-1234", "%-06d", "-1234 "},
+
+	{"1234", "%.3d", "1234"},
+	{"1234", "%.4d", "1234"},
+	{"1234", "%.5d", "01234"},
+	{"1234", "%.6d", "001234"},
+	{"-1234", "%.3d", "-1234"},
+	{"-1234", "%.4d", "-1234"},
+	{"-1234", "%.5d", "-01234"},
+	{"-1234", "%.6d", "-001234"},
+
+	{"1234", "%8.3d", "    1234"},
+	{"1234", "%8.4d", "    1234"},
+	{"1234", "%8.5d", "   01234"},
+	{"1234", "%8.6d", "  001234"},
+	{"-1234", "%8.3d", "   -1234"},
+	{"-1234", "%8.4d", "   -1234"},
+	{"-1234", "%8.5d", "  -01234"},
+	{"-1234", "%8.6d", " -001234"},
+
+	{"1234", "%+8.3d", "   +1234"},
+	{"1234", "%+8.4d", "   +1234"},
+	{"1234", "%+8.5d", "  +01234"},
+	{"1234", "%+8.6d", " +001234"},
+	{"-1234", "%+8.3d", "   -1234"},
+	{"-1234", "%+8.4d", "   -1234"},
+	{"-1234", "%+8.5d", "  -01234"},
+	{"-1234", "%+8.6d", " -001234"},
+
+	{"1234", "% 8.3d", "    1234"},
+	{"1234", "% 8.4d", "    1234"},
+	{"1234", "% 8.5d", "   01234"},
+	{"1234", "% 8.6d", "  001234"},
+	{"-1234", "% 8.3d", "   -1234"},
+	{"-1234", "% 8.4d", "   -1234"},
+	{"-1234", "% 8.5d", "  -01234"},
+	{"-1234", "% 8.6d", " -001234"},
+
+	{"1234", "%.3x", "4d2"},
+	{"1234", "%.4x", "04d2"},
+	{"1234", "%.5x", "004d2"},
+	{"1234", "%.6x", "0004d2"},
+	{"-1234", "%.3x", "-4d2"},
+	{"-1234", "%.4x", "-04d2"},
+	{"-1234", "%.5x", "-004d2"},
+	{"-1234", "%.6x", "-0004d2"},
+
+	{"1234", "%8.3x", "     4d2"},
+	{"1234", "%8.4x", "    04d2"},
+	{"1234", "%8.5x", "   004d2"},
+	{"1234", "%8.6x", "  0004d2"},
+	{"-1234", "%8.3x", "    -4d2"},
+	{"-1234", "%8.4x", "   -04d2"},
+	{"-1234", "%8.5x", "  -004d2"},
+	{"-1234", "%8.6x", " -0004d2"},
+
+	{"1234", "%+8.3x", "    +4d2"},
+	{"1234", "%+8.4x", "   +04d2"},
+	{"1234", "%+8.5x", "  +004d2"},
+	{"1234", "%+8.6x", " +0004d2"},
+	{"-1234", "%+8.3x", "    -4d2"},
+	{"-1234", "%+8.4x", "   -04d2"},
+	{"-1234", "%+8.5x", "  -004d2"},
+	{"-1234", "%+8.6x", " -0004d2"},
+
+	{"1234", "% 8.3x", "     4d2"},
+	{"1234", "% 8.4x", "    04d2"},
+	{"1234", "% 8.5x", "   004d2"},
+	{"1234", "% 8.6x", "  0004d2"},
+	{"1234", "% 8.7x", " 00004d2"},
+	{"1234", "% 8.8x", " 000004d2"},
+	{"-1234", "% 8.3x", "    -4d2"},
+	{"-1234", "% 8.4x", "   -04d2"},
+	{"-1234", "% 8.5x", "  -004d2"},
+	{"-1234", "% 8.6x", " -0004d2"},
+	{"-1234", "% 8.7x", "-00004d2"},
+	{"-1234", "% 8.8x", "-000004d2"},
+
+	{"1234", "%-8.3d", "1234    "},
+	{"1234", "%-8.4d", "1234    "},
+	{"1234", "%-8.5d", "01234   "},
+	{"1234", "%-8.6d", "001234  "},
+	{"1234", "%-8.7d", "0001234 "},
+	{"1234", "%-8.8d", "00001234"},
+	{"-1234", "%-8.3d", "-1234   "},
+	{"-1234", "%-8.4d", "-1234   "},
+	{"-1234", "%-8.5d", "-01234  "},
+	{"-1234", "%-8.6d", "-001234 "},
+	{"-1234", "%-8.7d", "-0001234"},
+	{"-1234", "%-8.8d", "-00001234"},
+
+	{"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1
+
+	{"0", "%.d", ""},
+	{"0", "%.0d", ""},
+	{"0", "%3.d", ""},
+}
+
+func TestFormat(t *testing.T) {
+	for i, test := range formatTests {
+		var x *Int
+		if test.input != "<nil>" {
+			var ok bool
+			x, ok = new(Int).SetString(test.input, 0)
+			if !ok {
+				t.Errorf("#%d failed reading input %s", i, test.input)
+			}
+		}
+		output := fmt.Sprintf(test.format, x)
+		if output != test.output {
+			t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
+		}
+	}
+}
+
+var scanTests = []struct {
+	input     string
+	format    string
+	output    string
+	remaining int
+}{
+	{"1010", "%b", "10", 0},
+	{"0b1010", "%v", "10", 0},
+	{"12", "%o", "10", 0},
+	{"012", "%v", "10", 0},
+	{"10", "%d", "10", 0},
+	{"10", "%v", "10", 0},
+	{"a", "%x", "10", 0},
+	{"0xa", "%v", "10", 0},
+	{"A", "%X", "10", 0},
+	{"-A", "%X", "-10", 0},
+	{"+0b1011001", "%v", "89", 0},
+	{"0xA", "%v", "10", 0},
+	{"0 ", "%v", "0", 1},
+	{"2+3", "%v", "2", 2},
+	{"0XABC 12", "%v", "2748", 3},
+}
+
+func TestScan(t *testing.T) {
+	var buf bytes.Buffer
+	for i, test := range scanTests {
+		x := new(Int)
+		buf.Reset()
+		buf.WriteString(test.input)
+		if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
+			t.Errorf("#%d error: %s", i, err)
+		}
+		if x.String() != test.output {
+			t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
+		}
+		if buf.Len() != test.remaining {
+			t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
+		}
+	}
+}
+
+// Examples from the Go Language Spec, section "Arithmetic operators"
+var divisionSignsTests = []struct {
+	x, y int64
+	q, r int64 // T-division
+	d, m int64 // Euclidian division
+}{
+	{5, 3, 1, 2, 1, 2},
+	{-5, 3, -1, -2, -2, 1},
+	{5, -3, -1, 2, -1, 2},
+	{-5, -3, 1, -2, 2, 1},
+	{1, 2, 0, 1, 0, 1},
+	{8, 4, 2, 0, 2, 0},
+}
+
+func TestDivisionSigns(t *testing.T) {
+	for i, test := range divisionSignsTests {
+		x := NewInt(test.x)
+		y := NewInt(test.y)
+		q := NewInt(test.q)
+		r := NewInt(test.r)
+		d := NewInt(test.d)
+		m := NewInt(test.m)
+
+		q1 := new(Int).Quo(x, y)
+		r1 := new(Int).Rem(x, y)
+		if !isNormalized(q1) {
+			t.Errorf("#%d Quo: %v is not normalized", i, *q1)
+		}
+		if !isNormalized(r1) {
+			t.Errorf("#%d Rem: %v is not normalized", i, *r1)
+		}
+		if q1.Cmp(q) != 0 || r1.Cmp(r) != 0 {
+			t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q1, r1, q, r)
+		}
+
+		q2, r2 := new(Int).QuoRem(x, y, new(Int))
+		if !isNormalized(q2) {
+			t.Errorf("#%d Quo: %v is not normalized", i, *q2)
+		}
+		if !isNormalized(r2) {
+			t.Errorf("#%d Rem: %v is not normalized", i, *r2)
+		}
+		if q2.Cmp(q) != 0 || r2.Cmp(r) != 0 {
+			t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q2, r2, q, r)
+		}
+
+		d1 := new(Int).Div(x, y)
+		m1 := new(Int).Mod(x, y)
+		if !isNormalized(d1) {
+			t.Errorf("#%d Div: %v is not normalized", i, *d1)
+		}
+		if !isNormalized(m1) {
+			t.Errorf("#%d Mod: %v is not normalized", i, *m1)
+		}
+		if d1.Cmp(d) != 0 || m1.Cmp(m) != 0 {
+			t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d1, m1, d, m)
+		}
+
+		d2, m2 := new(Int).DivMod(x, y, new(Int))
+		if !isNormalized(d2) {
+			t.Errorf("#%d Div: %v is not normalized", i, *d2)
+		}
+		if !isNormalized(m2) {
+			t.Errorf("#%d Mod: %v is not normalized", i, *m2)
+		}
+		if d2.Cmp(d) != 0 || m2.Cmp(m) != 0 {
+			t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d2, m2, d, m)
+		}
+	}
+}
+
+func checkSetBytes(b []byte) bool {
+	hex1 := hex.EncodeToString(new(Int).SetBytes(b).Bytes())
+	hex2 := hex.EncodeToString(b)
+
+	for len(hex1) < len(hex2) {
+		hex1 = "0" + hex1
+	}
+
+	for len(hex1) > len(hex2) {
+		hex2 = "0" + hex2
+	}
+
+	return hex1 == hex2
+}
+
+func TestSetBytes(t *testing.T) {
+	if err := quick.Check(checkSetBytes, nil); err != nil {
+		t.Error(err)
+	}
+}
+
+func checkBytes(b []byte) bool {
+	b2 := new(Int).SetBytes(b).Bytes()
+	return bytes.Equal(b, b2)
+}
+
+func TestBytes(t *testing.T) {
+	if err := quick.Check(checkSetBytes, nil); err != nil {
+		t.Error(err)
+	}
+}
+
+func checkQuo(x, y []byte) bool {
+	u := new(Int).SetBytes(x)
+	v := new(Int).SetBytes(y)
+
+	if len(v.abs) == 0 {
+		return true
+	}
+
+	r := new(Int)
+	q, r := new(Int).QuoRem(u, v, r)
+
+	if r.Cmp(v) >= 0 {
+		return false
+	}
+
+	uprime := new(Int).Set(q)
+	uprime.Mul(uprime, v)
+	uprime.Add(uprime, r)
+
+	return uprime.Cmp(u) == 0
+}
+
+var quoTests = []struct {
+	x, y string
+	q, r string
+}{
+	{
+		"476217953993950760840509444250624797097991362735329973741718102894495832294430498335824897858659711275234906400899559094370964723884706254265559534144986498357",
+		"9353930466774385905609975137998169297361893554149986716853295022578535724979483772383667534691121982974895531435241089241440253066816724367338287092081996",
+		"50911",
+		"1",
+	},
+	{
+		"11510768301994997771168",
+		"1328165573307167369775",
+		"8",
+		"885443715537658812968",
+	},
+}
+
+func TestQuo(t *testing.T) {
+	if err := quick.Check(checkQuo, nil); err != nil {
+		t.Error(err)
+	}
+
+	for i, test := range quoTests {
+		x, _ := new(Int).SetString(test.x, 10)
+		y, _ := new(Int).SetString(test.y, 10)
+		expectedQ, _ := new(Int).SetString(test.q, 10)
+		expectedR, _ := new(Int).SetString(test.r, 10)
+
+		r := new(Int)
+		q, r := new(Int).QuoRem(x, y, r)
+
+		if q.Cmp(expectedQ) != 0 || r.Cmp(expectedR) != 0 {
+			t.Errorf("#%d got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR)
+		}
+	}
+}
+
+func TestQuoStepD6(t *testing.T) {
+	// See Knuth, Volume 2, section 4.3.1, exercise 21. This code exercises
+	// a code path which only triggers 1 in 10^{-19} cases.
+
+	u := &Int{false, nat{0, 0, 1 + 1<<(_W-1), _M ^ (1 << (_W - 1))}}
+	v := &Int{false, nat{5, 2 + 1<<(_W-1), 1 << (_W - 1)}}
+
+	r := new(Int)
+	q, r := new(Int).QuoRem(u, v, r)
+	const expectedQ64 = "18446744073709551613"
+	const expectedR64 = "3138550867693340382088035895064302439801311770021610913807"
+	const expectedQ32 = "4294967293"
+	const expectedR32 = "39614081266355540837921718287"
+	if q.String() != expectedQ64 && q.String() != expectedQ32 ||
+		r.String() != expectedR64 && r.String() != expectedR32 {
+		t.Errorf("got (%s, %s) want (%s, %s) or (%s, %s)", q, r, expectedQ64, expectedR64, expectedQ32, expectedR32)
+	}
+}
+
+var bitLenTests = []struct {
+	in  string
+	out int
+}{
+	{"-1", 1},
+	{"0", 0},
+	{"1", 1},
+	{"2", 2},
+	{"4", 3},
+	{"0xabc", 12},
+	{"0x8000", 16},
+	{"0x80000000", 32},
+	{"0x800000000000", 48},
+	{"0x8000000000000000", 64},
+	{"0x80000000000000000000", 80},
+	{"-0x4000000000000000000000", 87},
+}
+
+func TestBitLen(t *testing.T) {
+	for i, test := range bitLenTests {
+		x, ok := new(Int).SetString(test.in, 0)
+		if !ok {
+			t.Errorf("#%d test input invalid: %s", i, test.in)
+			continue
+		}
+
+		if n := x.BitLen(); n != test.out {
+			t.Errorf("#%d got %d want %d", i, n, test.out)
+		}
+	}
+}
+
+var expTests = []struct {
+	x, y, m string
+	out     string
+}{
+	// y <= 0
+	{"0", "0", "", "1"},
+	{"1", "0", "", "1"},
+	{"-10", "0", "", "1"},
+	{"1234", "-1", "", "1"},
+
+	// m == 1
+	{"0", "0", "1", "0"},
+	{"1", "0", "1", "0"},
+	{"-10", "0", "1", "0"},
+	{"1234", "-1", "1", "0"},
+
+	// misc
+	{"5", "-7", "", "1"},
+	{"-5", "-7", "", "1"},
+	{"5", "0", "", "1"},
+	{"-5", "0", "", "1"},
+	{"5", "1", "", "5"},
+	{"-5", "1", "", "-5"},
+	{"-2", "3", "2", "0"},
+	{"5", "2", "", "25"},
+	{"1", "65537", "2", "1"},
+	{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"},
+	{"0x8000000000000000", "2", "6719", "4944"},
+	{"0x8000000000000000", "3", "6719", "5447"},
+	{"0x8000000000000000", "1000", "6719", "1603"},
+	{"0x8000000000000000", "1000000", "6719", "3199"},
+	{"0x8000000000000000", "-1000000", "6719", "1"},
+	{
+		"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
+		"298472983472983471903246121093472394872319615612417471234712061",
+		"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
+		"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
+	},
+}
+
+func TestExp(t *testing.T) {
+	for i, test := range expTests {
+		x, ok1 := new(Int).SetString(test.x, 0)
+		y, ok2 := new(Int).SetString(test.y, 0)
+		out, ok3 := new(Int).SetString(test.out, 0)
+
+		var ok4 bool
+		var m *Int
+
+		if len(test.m) == 0 {
+			m, ok4 = nil, true
+		} else {
+			m, ok4 = new(Int).SetString(test.m, 0)
+		}
+
+		if !ok1 || !ok2 || !ok3 || !ok4 {
+			t.Errorf("#%d: error in input", i)
+			continue
+		}
+
+		z1 := new(Int).Exp(x, y, m)
+		if !isNormalized(z1) {
+			t.Errorf("#%d: %v is not normalized", i, *z1)
+		}
+		if z1.Cmp(out) != 0 {
+			t.Errorf("#%d: got %s want %s", i, z1, out)
+		}
+
+		if m == nil {
+			// the result should be the same as for m == 0;
+			// specifically, there should be no div-zero panic
+			m = &Int{abs: nat{}} // m != nil && len(m.abs) == 0
+			z2 := new(Int).Exp(x, y, m)
+			if z2.Cmp(z1) != 0 {
+				t.Errorf("#%d: got %s want %s", i, z1, z2)
+			}
+		}
+	}
+}
+
+func checkGcd(aBytes, bBytes []byte) bool {
+	x := new(Int)
+	y := new(Int)
+	a := new(Int).SetBytes(aBytes)
+	b := new(Int).SetBytes(bBytes)
+
+	d := new(Int).GCD(x, y, a, b)
+	x.Mul(x, a)
+	y.Mul(y, b)
+	x.Add(x, y)
+
+	return x.Cmp(d) == 0
+}
+
+var gcdTests = []struct {
+	d, x, y, a, b string
+}{
+	// a <= 0 || b <= 0
+	{"0", "0", "0", "0", "0"},
+	{"0", "0", "0", "0", "7"},
+	{"0", "0", "0", "11", "0"},
+	{"0", "0", "0", "-77", "35"},
+	{"0", "0", "0", "64515", "-24310"},
+	{"0", "0", "0", "-64515", "-24310"},
+
+	{"1", "-9", "47", "120", "23"},
+	{"7", "1", "-2", "77", "35"},
+	{"935", "-3", "8", "64515", "24310"},
+	{"935000000000000000", "-3", "8", "64515000000000000000", "24310000000000000000"},
+	{"1", "-221", "22059940471369027483332068679400581064239780177629666810348940098015901108344", "98920366548084643601728869055592650835572950932266967461790948584315647051443", "991"},
+
+	// test early exit (after one Euclidean iteration) in binaryGCD
+	{"1", "", "", "1", "98920366548084643601728869055592650835572950932266967461790948584315647051443"},
+}
+
+func testGcd(t *testing.T, d, x, y, a, b *Int) {
+	var X *Int
+	if x != nil {
+		X = new(Int)
+	}
+	var Y *Int
+	if y != nil {
+		Y = new(Int)
+	}
+
+	D := new(Int).GCD(X, Y, a, b)
+	if D.Cmp(d) != 0 {
+		t.Errorf("GCD(%s, %s): got d = %s, want %s", a, b, D, d)
+	}
+	if x != nil && X.Cmp(x) != 0 {
+		t.Errorf("GCD(%s, %s): got x = %s, want %s", a, b, X, x)
+	}
+	if y != nil && Y.Cmp(y) != 0 {
+		t.Errorf("GCD(%s, %s): got y = %s, want %s", a, b, Y, y)
+	}
+
+	// binaryGCD requires a > 0 && b > 0
+	if a.Sign() <= 0 || b.Sign() <= 0 {
+		return
+	}
+
+	D.binaryGCD(a, b)
+	if D.Cmp(d) != 0 {
+		t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, D, d)
+	}
+}
+
+func TestGcd(t *testing.T) {
+	for _, test := range gcdTests {
+		d, _ := new(Int).SetString(test.d, 0)
+		x, _ := new(Int).SetString(test.x, 0)
+		y, _ := new(Int).SetString(test.y, 0)
+		a, _ := new(Int).SetString(test.a, 0)
+		b, _ := new(Int).SetString(test.b, 0)
+
+		testGcd(t, d, nil, nil, a, b)
+		testGcd(t, d, x, nil, a, b)
+		testGcd(t, d, nil, y, a, b)
+		testGcd(t, d, x, y, a, b)
+	}
+
+	quick.Check(checkGcd, nil)
+}
+
+var primes = []string{
+	"2",
+	"3",
+	"5",
+	"7",
+	"11",
+
+	"13756265695458089029",
+	"13496181268022124907",
+	"10953742525620032441",
+	"17908251027575790097",
+
+	// http://code.google.com/p/go/issues/detail?id=638
+	"18699199384836356663",
+
+	"98920366548084643601728869055592650835572950932266967461790948584315647051443",
+	"94560208308847015747498523884063394671606671904944666360068158221458669711639",
+
+	// http://primes.utm.edu/lists/small/small3.html
+	"449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163",
+	"230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593",
+	"5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993",
+	"203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123",
+}
+
+var composites = []string{
+	"21284175091214687912771199898307297748211672914763848041968395774954376176754",
+	"6084766654921918907427900243509372380954290099172559290432744450051395395951",
+	"84594350493221918389213352992032324280367711247940675652888030554255915464401",
+	"82793403787388584738507275144194252681",
+}
+
+func TestProbablyPrime(t *testing.T) {
+	nreps := 20
+	if testing.Short() {
+		nreps = 1
+	}
+	for i, s := range primes {
+		p, _ := new(Int).SetString(s, 10)
+		if !p.ProbablyPrime(nreps) {
+			t.Errorf("#%d prime found to be non-prime (%s)", i, s)
+		}
+	}
+
+	for i, s := range composites {
+		c, _ := new(Int).SetString(s, 10)
+		if c.ProbablyPrime(nreps) {
+			t.Errorf("#%d composite found to be prime (%s)", i, s)
+		}
+		if testing.Short() {
+			break
+		}
+	}
+}
+
+type intShiftTest struct {
+	in    string
+	shift uint
+	out   string
+}
+
+var rshTests = []intShiftTest{
+	{"0", 0, "0"},
+	{"-0", 0, "0"},
+	{"0", 1, "0"},
+	{"0", 2, "0"},
+	{"1", 0, "1"},
+	{"1", 1, "0"},
+	{"1", 2, "0"},
+	{"2", 0, "2"},
+	{"2", 1, "1"},
+	{"-1", 0, "-1"},
+	{"-1", 1, "-1"},
+	{"-1", 10, "-1"},
+	{"-100", 2, "-25"},
+	{"-100", 3, "-13"},
+	{"-100", 100, "-1"},
+	{"4294967296", 0, "4294967296"},
+	{"4294967296", 1, "2147483648"},
+	{"4294967296", 2, "1073741824"},
+	{"18446744073709551616", 0, "18446744073709551616"},
+	{"18446744073709551616", 1, "9223372036854775808"},
+	{"18446744073709551616", 2, "4611686018427387904"},
+	{"18446744073709551616", 64, "1"},
+	{"340282366920938463463374607431768211456", 64, "18446744073709551616"},
+	{"340282366920938463463374607431768211456", 128, "1"},
+}
+
+func TestRsh(t *testing.T) {
+	for i, test := range rshTests {
+		in, _ := new(Int).SetString(test.in, 10)
+		expected, _ := new(Int).SetString(test.out, 10)
+		out := new(Int).Rsh(in, test.shift)
+
+		if !isNormalized(out) {
+			t.Errorf("#%d: %v is not normalized", i, *out)
+		}
+		if out.Cmp(expected) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, expected)
+		}
+	}
+}
+
+func TestRshSelf(t *testing.T) {
+	for i, test := range rshTests {
+		z, _ := new(Int).SetString(test.in, 10)
+		expected, _ := new(Int).SetString(test.out, 10)
+		z.Rsh(z, test.shift)
+
+		if !isNormalized(z) {
+			t.Errorf("#%d: %v is not normalized", i, *z)
+		}
+		if z.Cmp(expected) != 0 {
+			t.Errorf("#%d: got %s want %s", i, z, expected)
+		}
+	}
+}
+
+var lshTests = []intShiftTest{
+	{"0", 0, "0"},
+	{"0", 1, "0"},
+	{"0", 2, "0"},
+	{"1", 0, "1"},
+	{"1", 1, "2"},
+	{"1", 2, "4"},
+	{"2", 0, "2"},
+	{"2", 1, "4"},
+	{"2", 2, "8"},
+	{"-87", 1, "-174"},
+	{"4294967296", 0, "4294967296"},
+	{"4294967296", 1, "8589934592"},
+	{"4294967296", 2, "17179869184"},
+	{"18446744073709551616", 0, "18446744073709551616"},
+	{"9223372036854775808", 1, "18446744073709551616"},
+	{"4611686018427387904", 2, "18446744073709551616"},
+	{"1", 64, "18446744073709551616"},
+	{"18446744073709551616", 64, "340282366920938463463374607431768211456"},
+	{"1", 128, "340282366920938463463374607431768211456"},
+}
+
+func TestLsh(t *testing.T) {
+	for i, test := range lshTests {
+		in, _ := new(Int).SetString(test.in, 10)
+		expected, _ := new(Int).SetString(test.out, 10)
+		out := new(Int).Lsh(in, test.shift)
+
+		if !isNormalized(out) {
+			t.Errorf("#%d: %v is not normalized", i, *out)
+		}
+		if out.Cmp(expected) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, expected)
+		}
+	}
+}
+
+func TestLshSelf(t *testing.T) {
+	for i, test := range lshTests {
+		z, _ := new(Int).SetString(test.in, 10)
+		expected, _ := new(Int).SetString(test.out, 10)
+		z.Lsh(z, test.shift)
+
+		if !isNormalized(z) {
+			t.Errorf("#%d: %v is not normalized", i, *z)
+		}
+		if z.Cmp(expected) != 0 {
+			t.Errorf("#%d: got %s want %s", i, z, expected)
+		}
+	}
+}
+
+func TestLshRsh(t *testing.T) {
+	for i, test := range rshTests {
+		in, _ := new(Int).SetString(test.in, 10)
+		out := new(Int).Lsh(in, test.shift)
+		out = out.Rsh(out, test.shift)
+
+		if !isNormalized(out) {
+			t.Errorf("#%d: %v is not normalized", i, *out)
+		}
+		if in.Cmp(out) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, in)
+		}
+	}
+	for i, test := range lshTests {
+		in, _ := new(Int).SetString(test.in, 10)
+		out := new(Int).Lsh(in, test.shift)
+		out.Rsh(out, test.shift)
+
+		if !isNormalized(out) {
+			t.Errorf("#%d: %v is not normalized", i, *out)
+		}
+		if in.Cmp(out) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, in)
+		}
+	}
+}
+
+var int64Tests = []int64{
+	0,
+	1,
+	-1,
+	4294967295,
+	-4294967295,
+	4294967296,
+	-4294967296,
+	9223372036854775807,
+	-9223372036854775807,
+	-9223372036854775808,
+}
+
+func TestInt64(t *testing.T) {
+	for i, testVal := range int64Tests {
+		in := NewInt(testVal)
+		out := in.Int64()
+
+		if out != testVal {
+			t.Errorf("#%d got %d want %d", i, out, testVal)
+		}
+	}
+}
+
+var uint64Tests = []uint64{
+	0,
+	1,
+	4294967295,
+	4294967296,
+	8589934591,
+	8589934592,
+	9223372036854775807,
+	9223372036854775808,
+	18446744073709551615, // 1<<64 - 1
+}
+
+func TestUint64(t *testing.T) {
+	in := new(Int)
+	for i, testVal := range uint64Tests {
+		in.SetUint64(testVal)
+		out := in.Uint64()
+
+		if out != testVal {
+			t.Errorf("#%d got %d want %d", i, out, testVal)
+		}
+
+		str := fmt.Sprint(testVal)
+		strOut := in.String()
+		if strOut != str {
+			t.Errorf("#%d.String got %s want %s", i, strOut, str)
+		}
+	}
+}
+
+var bitwiseTests = []struct {
+	x, y                 string
+	and, or, xor, andNot string
+}{
+	{"0x00", "0x00", "0x00", "0x00", "0x00", "0x00"},
+	{"0x00", "0x01", "0x00", "0x01", "0x01", "0x00"},
+	{"0x01", "0x00", "0x00", "0x01", "0x01", "0x01"},
+	{"-0x01", "0x00", "0x00", "-0x01", "-0x01", "-0x01"},
+	{"-0xaf", "-0x50", "-0xf0", "-0x0f", "0xe1", "0x41"},
+	{"0x00", "-0x01", "0x00", "-0x01", "-0x01", "0x00"},
+	{"0x01", "0x01", "0x01", "0x01", "0x00", "0x00"},
+	{"-0x01", "-0x01", "-0x01", "-0x01", "0x00", "0x00"},
+	{"0x07", "0x08", "0x00", "0x0f", "0x0f", "0x07"},
+	{"0x05", "0x0f", "0x05", "0x0f", "0x0a", "0x00"},
+	{"0x013ff6", "0x9a4e", "0x1a46", "0x01bffe", "0x01a5b8", "0x0125b0"},
+	{"-0x013ff6", "0x9a4e", "0x800a", "-0x0125b2", "-0x01a5bc", "-0x01c000"},
+	{"-0x013ff6", "-0x9a4e", "-0x01bffe", "-0x1a46", "0x01a5b8", "0x8008"},
+	{
+		"0x1000009dc6e3d9822cba04129bcbe3401",
+		"0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
+		"0x1000001186210100001000009048c2001",
+		"0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd",
+		"0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc",
+		"0x8c40c2d8822caa04120b8321400",
+	},
+	{
+		"0x1000009dc6e3d9822cba04129bcbe3401",
+		"-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
+		"0x8c40c2d8822caa04120b8321401",
+		"-0xb9bd7d543685789d57ca918e82229142459020483cd2014001fd",
+		"-0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fe",
+		"0x1000001186210100001000009048c2000",
+	},
+	{
+		"-0x1000009dc6e3d9822cba04129bcbe3401",
+		"-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
+		"-0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd",
+		"-0x1000001186210100001000009048c2001",
+		"0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc",
+		"0xb9bd7d543685789d57ca918e82229142459020483cd2014001fc",
+	},
+}
+
+type bitFun func(z, x, y *Int) *Int
+
+func testBitFun(t *testing.T, msg string, f bitFun, x, y *Int, exp string) {
+	expected := new(Int)
+	expected.SetString(exp, 0)
+
+	out := f(new(Int), x, y)
+	if out.Cmp(expected) != 0 {
+		t.Errorf("%s: got %s want %s", msg, out, expected)
+	}
+}
+
+func testBitFunSelf(t *testing.T, msg string, f bitFun, x, y *Int, exp string) {
+	self := new(Int)
+	self.Set(x)
+	expected := new(Int)
+	expected.SetString(exp, 0)
+
+	self = f(self, self, y)
+	if self.Cmp(expected) != 0 {
+		t.Errorf("%s: got %s want %s", msg, self, expected)
+	}
+}
+
+func altBit(x *Int, i int) uint {
+	z := new(Int).Rsh(x, uint(i))
+	z = z.And(z, NewInt(1))
+	if z.Cmp(new(Int)) != 0 {
+		return 1
+	}
+	return 0
+}
+
+func altSetBit(z *Int, x *Int, i int, b uint) *Int {
+	one := NewInt(1)
+	m := one.Lsh(one, uint(i))
+	switch b {
+	case 1:
+		return z.Or(x, m)
+	case 0:
+		return z.AndNot(x, m)
+	}
+	panic("set bit is not 0 or 1")
+}
+
+func testBitset(t *testing.T, x *Int) {
+	n := x.BitLen()
+	z := new(Int).Set(x)
+	z1 := new(Int).Set(x)
+	for i := 0; i < n+10; i++ {
+		old := z.Bit(i)
+		old1 := altBit(z1, i)
+		if old != old1 {
+			t.Errorf("bitset: inconsistent value for Bit(%s, %d), got %v want %v", z1, i, old, old1)
+		}
+		z := new(Int).SetBit(z, i, 1)
+		z1 := altSetBit(new(Int), z1, i, 1)
+		if z.Bit(i) == 0 {
+			t.Errorf("bitset: bit %d of %s got 0 want 1", i, x)
+		}
+		if z.Cmp(z1) != 0 {
+			t.Errorf("bitset: inconsistent value after SetBit 1, got %s want %s", z, z1)
+		}
+		z.SetBit(z, i, 0)
+		altSetBit(z1, z1, i, 0)
+		if z.Bit(i) != 0 {
+			t.Errorf("bitset: bit %d of %s got 1 want 0", i, x)
+		}
+		if z.Cmp(z1) != 0 {
+			t.Errorf("bitset: inconsistent value after SetBit 0, got %s want %s", z, z1)
+		}
+		altSetBit(z1, z1, i, old)
+		z.SetBit(z, i, old)
+		if z.Cmp(z1) != 0 {
+			t.Errorf("bitset: inconsistent value after SetBit old, got %s want %s", z, z1)
+		}
+	}
+	if z.Cmp(x) != 0 {
+		t.Errorf("bitset: got %s want %s", z, x)
+	}
+}
+
+var bitsetTests = []struct {
+	x string
+	i int
+	b uint
+}{
+	{"0", 0, 0},
+	{"0", 200, 0},
+	{"1", 0, 1},
+	{"1", 1, 0},
+	{"-1", 0, 1},
+	{"-1", 200, 1},
+	{"0x2000000000000000000000000000", 108, 0},
+	{"0x2000000000000000000000000000", 109, 1},
+	{"0x2000000000000000000000000000", 110, 0},
+	{"-0x2000000000000000000000000001", 108, 1},
+	{"-0x2000000000000000000000000001", 109, 0},
+	{"-0x2000000000000000000000000001", 110, 1},
+}
+
+func TestBitSet(t *testing.T) {
+	for _, test := range bitwiseTests {
+		x := new(Int)
+		x.SetString(test.x, 0)
+		testBitset(t, x)
+		x = new(Int)
+		x.SetString(test.y, 0)
+		testBitset(t, x)
+	}
+	for i, test := range bitsetTests {
+		x := new(Int)
+		x.SetString(test.x, 0)
+		b := x.Bit(test.i)
+		if b != test.b {
+			t.Errorf("#%d got %v want %v", i, b, test.b)
+		}
+	}
+	z := NewInt(1)
+	z.SetBit(NewInt(0), 2, 1)
+	if z.Cmp(NewInt(4)) != 0 {
+		t.Errorf("destination leaked into result; got %s want 4", z)
+	}
+}
+
+func BenchmarkBitset(b *testing.B) {
+	z := new(Int)
+	z.SetBit(z, 512, 1)
+	b.ResetTimer()
+	b.StartTimer()
+	for i := b.N - 1; i >= 0; i-- {
+		z.SetBit(z, i&512, 1)
+	}
+}
+
+func BenchmarkBitsetNeg(b *testing.B) {
+	z := NewInt(-1)
+	z.SetBit(z, 512, 0)
+	b.ResetTimer()
+	b.StartTimer()
+	for i := b.N - 1; i >= 0; i-- {
+		z.SetBit(z, i&512, 0)
+	}
+}
+
+func BenchmarkBitsetOrig(b *testing.B) {
+	z := new(Int)
+	altSetBit(z, z, 512, 1)
+	b.ResetTimer()
+	b.StartTimer()
+	for i := b.N - 1; i >= 0; i-- {
+		altSetBit(z, z, i&512, 1)
+	}
+}
+
+func BenchmarkBitsetNegOrig(b *testing.B) {
+	z := NewInt(-1)
+	altSetBit(z, z, 512, 0)
+	b.ResetTimer()
+	b.StartTimer()
+	for i := b.N - 1; i >= 0; i-- {
+		altSetBit(z, z, i&512, 0)
+	}
+}
+
+func TestBitwise(t *testing.T) {
+	x := new(Int)
+	y := new(Int)
+	for _, test := range bitwiseTests {
+		x.SetString(test.x, 0)
+		y.SetString(test.y, 0)
+
+		testBitFun(t, "and", (*Int).And, x, y, test.and)
+		testBitFunSelf(t, "and", (*Int).And, x, y, test.and)
+		testBitFun(t, "andNot", (*Int).AndNot, x, y, test.andNot)
+		testBitFunSelf(t, "andNot", (*Int).AndNot, x, y, test.andNot)
+		testBitFun(t, "or", (*Int).Or, x, y, test.or)
+		testBitFunSelf(t, "or", (*Int).Or, x, y, test.or)
+		testBitFun(t, "xor", (*Int).Xor, x, y, test.xor)
+		testBitFunSelf(t, "xor", (*Int).Xor, x, y, test.xor)
+	}
+}
+
+var notTests = []struct {
+	in  string
+	out string
+}{
+	{"0", "-1"},
+	{"1", "-2"},
+	{"7", "-8"},
+	{"0", "-1"},
+	{"-81910", "81909"},
+	{
+		"298472983472983471903246121093472394872319615612417471234712061",
+		"-298472983472983471903246121093472394872319615612417471234712062",
+	},
+}
+
+func TestNot(t *testing.T) {
+	in := new(Int)
+	out := new(Int)
+	expected := new(Int)
+	for i, test := range notTests {
+		in.SetString(test.in, 10)
+		expected.SetString(test.out, 10)
+		out = out.Not(in)
+		if out.Cmp(expected) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, expected)
+		}
+		out = out.Not(out)
+		if out.Cmp(in) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, in)
+		}
+	}
+}
+
+var modInverseTests = []struct {
+	element string
+	prime   string
+}{
+	{"1", "7"},
+	{"1", "13"},
+	{"239487239847", "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919"},
+}
+
+func TestModInverse(t *testing.T) {
+	var element, prime Int
+	one := NewInt(1)
+	for i, test := range modInverseTests {
+		(&element).SetString(test.element, 10)
+		(&prime).SetString(test.prime, 10)
+		inverse := new(Int).ModInverse(&element, &prime)
+		inverse.Mul(inverse, &element)
+		inverse.Mod(inverse, &prime)
+		if inverse.Cmp(one) != 0 {
+			t.Errorf("#%d: failed (e·e^(-1)=%s)", i, inverse)
+		}
+	}
+}
+
+var encodingTests = []string{
+	"-539345864568634858364538753846587364875430589374589",
+	"-678645873",
+	"-100",
+	"-2",
+	"-1",
+	"0",
+	"1",
+	"2",
+	"10",
+	"42",
+	"1234567890",
+	"298472983472983471903246121093472394872319615612417471234712061",
+}
+
+func TestIntGobEncoding(t *testing.T) {
+	var medium bytes.Buffer
+	enc := gob.NewEncoder(&medium)
+	dec := gob.NewDecoder(&medium)
+	for _, test := range encodingTests {
+		medium.Reset() // empty buffer for each test case (in case of failures)
+		var tx Int
+		tx.SetString(test, 10)
+		if err := enc.Encode(&tx); err != nil {
+			t.Errorf("encoding of %s failed: %s", &tx, err)
+		}
+		var rx Int
+		if err := dec.Decode(&rx); err != nil {
+			t.Errorf("decoding of %s failed: %s", &tx, err)
+		}
+		if rx.Cmp(&tx) != 0 {
+			t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
+		}
+	}
+}
+
+// Sending a nil Int pointer (inside a slice) on a round trip through gob should yield a zero.
+// TODO: top-level nils.
+func TestGobEncodingNilIntInSlice(t *testing.T) {
+	buf := new(bytes.Buffer)
+	enc := gob.NewEncoder(buf)
+	dec := gob.NewDecoder(buf)
+
+	var in = make([]*Int, 1)
+	err := enc.Encode(&in)
+	if err != nil {
+		t.Errorf("gob encode failed: %q", err)
+	}
+	var out []*Int
+	err = dec.Decode(&out)
+	if err != nil {
+		t.Fatalf("gob decode failed: %q", err)
+	}
+	if len(out) != 1 {
+		t.Fatalf("wrong len; want 1 got %d", len(out))
+	}
+	var zero Int
+	if out[0].Cmp(&zero) != 0 {
+		t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
+	}
+}
+
+func TestIntJSONEncoding(t *testing.T) {
+	for _, test := range encodingTests {
+		var tx Int
+		tx.SetString(test, 10)
+		b, err := json.Marshal(&tx)
+		if err != nil {
+			t.Errorf("marshaling of %s failed: %s", &tx, err)
+		}
+		var rx Int
+		if err := json.Unmarshal(b, &rx); err != nil {
+			t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+		}
+		if rx.Cmp(&tx) != 0 {
+			t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+		}
+	}
+}
+
+var intVals = []string{
+	"-141592653589793238462643383279502884197169399375105820974944592307816406286",
+	"-1415926535897932384626433832795028841971",
+	"-141592653589793",
+	"-1",
+	"0",
+	"1",
+	"141592653589793",
+	"1415926535897932384626433832795028841971",
+	"141592653589793238462643383279502884197169399375105820974944592307816406286",
+}
+
+func TestIntJSONEncodingTextMarshaller(t *testing.T) {
+	for _, num := range intVals {
+		var tx Int
+		tx.SetString(num, 0)
+		b, err := json.Marshal(&tx)
+		if err != nil {
+			t.Errorf("marshaling of %s failed: %s", &tx, err)
+			continue
+		}
+		var rx Int
+		if err := json.Unmarshal(b, &rx); err != nil {
+			t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+			continue
+		}
+		if rx.Cmp(&tx) != 0 {
+			t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+		}
+	}
+}
+
+func TestIntXMLEncodingTextMarshaller(t *testing.T) {
+	for _, num := range intVals {
+		var tx Int
+		tx.SetString(num, 0)
+		b, err := xml.Marshal(&tx)
+		if err != nil {
+			t.Errorf("marshaling of %s failed: %s", &tx, err)
+			continue
+		}
+		var rx Int
+		if err := xml.Unmarshal(b, &rx); err != nil {
+			t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+			continue
+		}
+		if rx.Cmp(&tx) != 0 {
+			t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+		}
+	}
+}
+
+func TestIssue2607(t *testing.T) {
+	// This code sequence used to hang.
+	n := NewInt(10)
+	n.Rand(rand.New(rand.NewSource(9)), n)
+}
diff --git a/third_party/gofrontend/libgo/go/math/big/nat.go b/third_party/gofrontend/libgo/go/math/big/nat.go
new file mode 100644
index 0000000..16a87f5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/nat.go
@@ -0,0 +1,1508 @@
+// 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 big implements multi-precision arithmetic (big numbers).
+// The following numeric types are supported:
+//
+//	- Int	signed integers
+//	- Rat	rational numbers
+//
+// Methods are typically of the form:
+//
+//	func (z *Int) Op(x, y *Int) *Int	(similar for *Rat)
+//
+// and implement operations z = x Op y with the result as receiver; if it
+// is one of the operands it may be overwritten (and its memory reused).
+// To enable chaining of operations, the result is also returned. Methods
+// returning a result other than *Int or *Rat take one of the operands as
+// the receiver.
+//
+package big
+
+// This file contains operations on unsigned multi-precision integers.
+// These are the building blocks for the operations on signed integers
+// and rationals.
+
+import (
+	"errors"
+	"io"
+	"math"
+	"math/rand"
+	"sync"
+)
+
+// An unsigned integer x of the form
+//
+//   x = x[n-1]*_B^(n-1) + x[n-2]*_B^(n-2) + ... + x[1]*_B + x[0]
+//
+// with 0 <= x[i] < _B and 0 <= i < n is stored in a slice of length n,
+// with the digits x[i] as the slice elements.
+//
+// A number is normalized if the slice contains no leading 0 digits.
+// During arithmetic operations, denormalized values may occur but are
+// always normalized before returning the final result. The normalized
+// representation of 0 is the empty or nil slice (length = 0).
+//
+type nat []Word
+
+var (
+	natOne = nat{1}
+	natTwo = nat{2}
+	natTen = nat{10}
+)
+
+func (z nat) clear() {
+	for i := range z {
+		z[i] = 0
+	}
+}
+
+func (z nat) norm() nat {
+	i := len(z)
+	for i > 0 && z[i-1] == 0 {
+		i--
+	}
+	return z[0:i]
+}
+
+func (z nat) make(n int) nat {
+	if n <= cap(z) {
+		return z[0:n] // reuse z
+	}
+	// Choosing a good value for e has significant performance impact
+	// because it increases the chance that a value can be reused.
+	const e = 4 // extra capacity
+	return make(nat, n, n+e)
+}
+
+func (z nat) setWord(x Word) nat {
+	if x == 0 {
+		return z.make(0)
+	}
+	z = z.make(1)
+	z[0] = x
+	return z
+}
+
+func (z nat) setUint64(x uint64) nat {
+	// single-digit values
+	if w := Word(x); uint64(w) == x {
+		return z.setWord(w)
+	}
+
+	// compute number of words n required to represent x
+	n := 0
+	for t := x; t > 0; t >>= _W {
+		n++
+	}
+
+	// split x into n words
+	z = z.make(n)
+	for i := range z {
+		z[i] = Word(x & _M)
+		x >>= _W
+	}
+
+	return z
+}
+
+func (z nat) set(x nat) nat {
+	z = z.make(len(x))
+	copy(z, x)
+	return z
+}
+
+func (z nat) add(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+
+	switch {
+	case m < n:
+		return z.add(y, x)
+	case m == 0:
+		// n == 0 because m >= n; result is 0
+		return z.make(0)
+	case n == 0:
+		// result is x
+		return z.set(x)
+	}
+	// m > 0
+
+	z = z.make(m + 1)
+	c := addVV(z[0:n], x, y)
+	if m > n {
+		c = addVW(z[n:m], x[n:], c)
+	}
+	z[m] = c
+
+	return z.norm()
+}
+
+func (z nat) sub(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+
+	switch {
+	case m < n:
+		panic("underflow")
+	case m == 0:
+		// n == 0 because m >= n; result is 0
+		return z.make(0)
+	case n == 0:
+		// result is x
+		return z.set(x)
+	}
+	// m > 0
+
+	z = z.make(m)
+	c := subVV(z[0:n], x, y)
+	if m > n {
+		c = subVW(z[n:], x[n:], c)
+	}
+	if c != 0 {
+		panic("underflow")
+	}
+
+	return z.norm()
+}
+
+func (x nat) cmp(y nat) (r int) {
+	m := len(x)
+	n := len(y)
+	if m != n || m == 0 {
+		switch {
+		case m < n:
+			r = -1
+		case m > n:
+			r = 1
+		}
+		return
+	}
+
+	i := m - 1
+	for i > 0 && x[i] == y[i] {
+		i--
+	}
+
+	switch {
+	case x[i] < y[i]:
+		r = -1
+	case x[i] > y[i]:
+		r = 1
+	}
+	return
+}
+
+func (z nat) mulAddWW(x nat, y, r Word) nat {
+	m := len(x)
+	if m == 0 || y == 0 {
+		return z.setWord(r) // result is r
+	}
+	// m > 0
+
+	z = z.make(m + 1)
+	z[m] = mulAddVWW(z[0:m], x, y, r)
+
+	return z.norm()
+}
+
+// basicMul multiplies x and y and leaves the result in z.
+// The (non-normalized) result is placed in z[0 : len(x) + len(y)].
+func basicMul(z, x, y nat) {
+	z[0 : len(x)+len(y)].clear() // initialize z
+	for i, d := range y {
+		if d != 0 {
+			z[len(x)+i] = addMulVVW(z[i:i+len(x)], x, d)
+		}
+	}
+}
+
+// Fast version of z[0:n+n>>1].add(z[0:n+n>>1], x[0:n]) w/o bounds checks.
+// Factored out for readability - do not use outside karatsuba.
+func karatsubaAdd(z, x nat, n int) {
+	if c := addVV(z[0:n], z, x); c != 0 {
+		addVW(z[n:n+n>>1], z[n:], c)
+	}
+}
+
+// Like karatsubaAdd, but does subtract.
+func karatsubaSub(z, x nat, n int) {
+	if c := subVV(z[0:n], z, x); c != 0 {
+		subVW(z[n:n+n>>1], z[n:], c)
+	}
+}
+
+// Operands that are shorter than karatsubaThreshold are multiplied using
+// "grade school" multiplication; for longer operands the Karatsuba algorithm
+// is used.
+var karatsubaThreshold int = 40 // computed by calibrate.go
+
+// karatsuba multiplies x and y and leaves the result in z.
+// Both x and y must have the same length n and n must be a
+// power of 2. The result vector z must have len(z) >= 6*n.
+// The (non-normalized) result is placed in z[0 : 2*n].
+func karatsuba(z, x, y nat) {
+	n := len(y)
+
+	// Switch to basic multiplication if numbers are odd or small.
+	// (n is always even if karatsubaThreshold is even, but be
+	// conservative)
+	if n&1 != 0 || n < karatsubaThreshold || n < 2 {
+		basicMul(z, x, y)
+		return
+	}
+	// n&1 == 0 && n >= karatsubaThreshold && n >= 2
+
+	// Karatsuba multiplication is based on the observation that
+	// for two numbers x and y with:
+	//
+	//   x = x1*b + x0
+	//   y = y1*b + y0
+	//
+	// the product x*y can be obtained with 3 products z2, z1, z0
+	// instead of 4:
+	//
+	//   x*y = x1*y1*b*b + (x1*y0 + x0*y1)*b + x0*y0
+	//       =    z2*b*b +              z1*b +    z0
+	//
+	// with:
+	//
+	//   xd = x1 - x0
+	//   yd = y0 - y1
+	//
+	//   z1 =      xd*yd                    + z2 + z0
+	//      = (x1-x0)*(y0 - y1)             + z2 + z0
+	//      = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z2 + z0
+	//      = x1*y0 -    z2 -    z0 + x0*y1 + z2 + z0
+	//      = x1*y0                 + x0*y1
+
+	// split x, y into "digits"
+	n2 := n >> 1              // n2 >= 1
+	x1, x0 := x[n2:], x[0:n2] // x = x1*b + y0
+	y1, y0 := y[n2:], y[0:n2] // y = y1*b + y0
+
+	// z is used for the result and temporary storage:
+	//
+	//   6*n     5*n     4*n     3*n     2*n     1*n     0*n
+	// z = [z2 copy|z0 copy| xd*yd | yd:xd | x1*y1 | x0*y0 ]
+	//
+	// For each recursive call of karatsuba, an unused slice of
+	// z is passed in that has (at least) half the length of the
+	// caller's z.
+
+	// compute z0 and z2 with the result "in place" in z
+	karatsuba(z, x0, y0)     // z0 = x0*y0
+	karatsuba(z[n:], x1, y1) // z2 = x1*y1
+
+	// compute xd (or the negative value if underflow occurs)
+	s := 1 // sign of product xd*yd
+	xd := z[2*n : 2*n+n2]
+	if subVV(xd, x1, x0) != 0 { // x1-x0
+		s = -s
+		subVV(xd, x0, x1) // x0-x1
+	}
+
+	// compute yd (or the negative value if underflow occurs)
+	yd := z[2*n+n2 : 3*n]
+	if subVV(yd, y0, y1) != 0 { // y0-y1
+		s = -s
+		subVV(yd, y1, y0) // y1-y0
+	}
+
+	// p = (x1-x0)*(y0-y1) == x1*y0 - x1*y1 - x0*y0 + x0*y1 for s > 0
+	// p = (x0-x1)*(y0-y1) == x0*y0 - x0*y1 - x1*y0 + x1*y1 for s < 0
+	p := z[n*3:]
+	karatsuba(p, xd, yd)
+
+	// save original z2:z0
+	// (ok to use upper half of z since we're done recursing)
+	r := z[n*4:]
+	copy(r, z[:n*2])
+
+	// add up all partial products
+	//
+	//   2*n     n     0
+	// z = [ z2  | z0  ]
+	//   +    [ z0  ]
+	//   +    [ z2  ]
+	//   +    [  p  ]
+	//
+	karatsubaAdd(z[n2:], r, n)
+	karatsubaAdd(z[n2:], r[n:], n)
+	if s > 0 {
+		karatsubaAdd(z[n2:], p, n)
+	} else {
+		karatsubaSub(z[n2:], p, n)
+	}
+}
+
+// alias returns true if x and y share the same base array.
+func alias(x, y nat) bool {
+	return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
+}
+
+// addAt implements z += x<<(_W*i); z must be long enough.
+// (we don't use nat.add because we need z to stay the same
+// slice, and we don't need to normalize z after each addition)
+func addAt(z, x nat, i int) {
+	if n := len(x); n > 0 {
+		if c := addVV(z[i:i+n], z[i:], x); c != 0 {
+			j := i + n
+			if j < len(z) {
+				addVW(z[j:], z[j:], c)
+			}
+		}
+	}
+}
+
+func max(x, y int) int {
+	if x > y {
+		return x
+	}
+	return y
+}
+
+// karatsubaLen computes an approximation to the maximum k <= n such that
+// k = p<<i for a number p <= karatsubaThreshold and an i >= 0. Thus, the
+// result is the largest number that can be divided repeatedly by 2 before
+// becoming about the value of karatsubaThreshold.
+func karatsubaLen(n int) int {
+	i := uint(0)
+	for n > karatsubaThreshold {
+		n >>= 1
+		i++
+	}
+	return n << i
+}
+
+func (z nat) mul(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+
+	switch {
+	case m < n:
+		return z.mul(y, x)
+	case m == 0 || n == 0:
+		return z.make(0)
+	case n == 1:
+		return z.mulAddWW(x, y[0], 0)
+	}
+	// m >= n > 1
+
+	// determine if z can be reused
+	if alias(z, x) || alias(z, y) {
+		z = nil // z is an alias for x or y - cannot reuse
+	}
+
+	// use basic multiplication if the numbers are small
+	if n < karatsubaThreshold {
+		z = z.make(m + n)
+		basicMul(z, x, y)
+		return z.norm()
+	}
+	// m >= n && n >= karatsubaThreshold && n >= 2
+
+	// determine Karatsuba length k such that
+	//
+	//   x = xh*b + x0  (0 <= x0 < b)
+	//   y = yh*b + y0  (0 <= y0 < b)
+	//   b = 1<<(_W*k)  ("base" of digits xi, yi)
+	//
+	k := karatsubaLen(n)
+	// k <= n
+
+	// multiply x0 and y0 via Karatsuba
+	x0 := x[0:k]              // x0 is not normalized
+	y0 := y[0:k]              // y0 is not normalized
+	z = z.make(max(6*k, m+n)) // enough space for karatsuba of x0*y0 and full result of x*y
+	karatsuba(z, x0, y0)
+	z = z[0 : m+n]  // z has final length but may be incomplete
+	z[2*k:].clear() // upper portion of z is garbage (and 2*k <= m+n since k <= n <= m)
+
+	// If xh != 0 or yh != 0, add the missing terms to z. For
+	//
+	//   xh = xi*b^i + ... + x2*b^2 + x1*b (0 <= xi < b)
+	//   yh =                         y1*b (0 <= y1 < b)
+	//
+	// the missing terms are
+	//
+	//   x0*y1*b and xi*y0*b^i, xi*y1*b^(i+1) for i > 0
+	//
+	// since all the yi for i > 1 are 0 by choice of k: If any of them
+	// were > 0, then yh >= b^2 and thus y >= b^2. Then k' = k*2 would
+	// be a larger valid threshold contradicting the assumption about k.
+	//
+	if k < n || m != n {
+		var t nat
+
+		// add x0*y1*b
+		x0 := x0.norm()
+		y1 := y[k:]       // y1 is normalized because y is
+		t = t.mul(x0, y1) // update t so we don't lose t's underlying array
+		addAt(z, t, k)
+
+		// add xi*y0<<i, xi*y1*b<<(i+k)
+		y0 := y0.norm()
+		for i := k; i < len(x); i += k {
+			xi := x[i:]
+			if len(xi) > k {
+				xi = xi[:k]
+			}
+			xi = xi.norm()
+			t = t.mul(xi, y0)
+			addAt(z, t, i)
+			t = t.mul(xi, y1)
+			addAt(z, t, i+k)
+		}
+	}
+
+	return z.norm()
+}
+
+// mulRange computes the product of all the unsigned integers in the
+// range [a, b] inclusively. If a > b (empty range), the result is 1.
+func (z nat) mulRange(a, b uint64) nat {
+	switch {
+	case a == 0:
+		// cut long ranges short (optimization)
+		return z.setUint64(0)
+	case a > b:
+		return z.setUint64(1)
+	case a == b:
+		return z.setUint64(a)
+	case a+1 == b:
+		return z.mul(nat(nil).setUint64(a), nat(nil).setUint64(b))
+	}
+	m := (a + b) / 2
+	return z.mul(nat(nil).mulRange(a, m), nat(nil).mulRange(m+1, b))
+}
+
+// q = (x-r)/y, with 0 <= r < y
+func (z nat) divW(x nat, y Word) (q nat, r Word) {
+	m := len(x)
+	switch {
+	case y == 0:
+		panic("division by zero")
+	case y == 1:
+		q = z.set(x) // result is x
+		return
+	case m == 0:
+		q = z.make(0) // result is 0
+		return
+	}
+	// m > 0
+	z = z.make(m)
+	r = divWVW(z, 0, x, y)
+	q = z.norm()
+	return
+}
+
+func (z nat) div(z2, u, v nat) (q, r nat) {
+	if len(v) == 0 {
+		panic("division by zero")
+	}
+
+	if u.cmp(v) < 0 {
+		q = z.make(0)
+		r = z2.set(u)
+		return
+	}
+
+	if len(v) == 1 {
+		var r2 Word
+		q, r2 = z.divW(u, v[0])
+		r = z2.setWord(r2)
+		return
+	}
+
+	q, r = z.divLarge(z2, u, v)
+	return
+}
+
+// q = (uIn-r)/v, with 0 <= r < y
+// Uses z as storage for q, and u as storage for r if possible.
+// See Knuth, Volume 2, section 4.3.1, Algorithm D.
+// Preconditions:
+//    len(v) >= 2
+//    len(uIn) >= len(v)
+func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
+	n := len(v)
+	m := len(uIn) - n
+
+	// determine if z can be reused
+	// TODO(gri) should find a better solution - this if statement
+	//           is very costly (see e.g. time pidigits -s -n 10000)
+	if alias(z, uIn) || alias(z, v) {
+		z = nil // z is an alias for uIn or v - cannot reuse
+	}
+	q = z.make(m + 1)
+
+	qhatv := make(nat, n+1)
+	if alias(u, uIn) || alias(u, v) {
+		u = nil // u is an alias for uIn or v - cannot reuse
+	}
+	u = u.make(len(uIn) + 1)
+	u.clear()
+
+	// D1.
+	shift := leadingZeros(v[n-1])
+	if shift > 0 {
+		// do not modify v, it may be used by another goroutine simultaneously
+		v1 := make(nat, n)
+		shlVU(v1, v, shift)
+		v = v1
+	}
+	u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift)
+
+	// D2.
+	for j := m; j >= 0; j-- {
+		// D3.
+		qhat := Word(_M)
+		if u[j+n] != v[n-1] {
+			var rhat Word
+			qhat, rhat = divWW(u[j+n], u[j+n-1], v[n-1])
+
+			// x1 | x2 = q̂v_{n-2}
+			x1, x2 := mulWW(qhat, v[n-2])
+			// test if q̂v_{n-2} > br̂ + u_{j+n-2}
+			for greaterThan(x1, x2, rhat, u[j+n-2]) {
+				qhat--
+				prevRhat := rhat
+				rhat += v[n-1]
+				// v[n-1] >= 0, so this tests for overflow.
+				if rhat < prevRhat {
+					break
+				}
+				x1, x2 = mulWW(qhat, v[n-2])
+			}
+		}
+
+		// D4.
+		qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0)
+
+		c := subVV(u[j:j+len(qhatv)], u[j:], qhatv)
+		if c != 0 {
+			c := addVV(u[j:j+n], u[j:], v)
+			u[j+n] += c
+			qhat--
+		}
+
+		q[j] = qhat
+	}
+
+	q = q.norm()
+	shrVU(u, u, shift)
+	r = u.norm()
+
+	return q, r
+}
+
+// Length of x in bits. x must be normalized.
+func (x nat) bitLen() int {
+	if i := len(x) - 1; i >= 0 {
+		return i*_W + bitLen(x[i])
+	}
+	return 0
+}
+
+// MaxBase is the largest number base accepted for string conversions.
+const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1
+
+func hexValue(ch rune) Word {
+	d := int(MaxBase + 1) // illegal base
+	switch {
+	case '0' <= ch && ch <= '9':
+		d = int(ch - '0')
+	case 'a' <= ch && ch <= 'z':
+		d = int(ch - 'a' + 10)
+	case 'A' <= ch && ch <= 'Z':
+		d = int(ch - 'A' + 10)
+	}
+	return Word(d)
+}
+
+// scan sets z to the natural number corresponding to the longest possible prefix
+// read from r representing an unsigned integer in a given conversion base.
+// It returns z, the actual conversion base used, and an error, if any. In the
+// error case, the value of z is undefined. The syntax follows the syntax of
+// unsigned integer literals in Go.
+//
+// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// is 0, the string prefix determines the actual conversion base. A prefix of
+// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
+// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
+//
+func (z nat) scan(r io.RuneScanner, base int) (nat, int, error) {
+	// reject illegal bases
+	if base < 0 || base == 1 || MaxBase < base {
+		return z, 0, errors.New("illegal number base")
+	}
+
+	// one char look-ahead
+	ch, _, err := r.ReadRune()
+	if err != nil {
+		return z, 0, err
+	}
+
+	// determine base if necessary
+	b := Word(base)
+	if base == 0 {
+		b = 10
+		if ch == '0' {
+			switch ch, _, err = r.ReadRune(); err {
+			case nil:
+				b = 8
+				switch ch {
+				case 'x', 'X':
+					b = 16
+				case 'b', 'B':
+					b = 2
+				}
+				if b == 2 || b == 16 {
+					if ch, _, err = r.ReadRune(); err != nil {
+						return z, 0, err
+					}
+				}
+			case io.EOF:
+				return z.make(0), 10, nil
+			default:
+				return z, 10, err
+			}
+		}
+	}
+
+	// convert string
+	// - group as many digits d as possible together into a "super-digit" dd with "super-base" bb
+	// - only when bb does not fit into a word anymore, do a full number mulAddWW using bb and dd
+	z = z.make(0)
+	bb := Word(1)
+	dd := Word(0)
+	for max := _M / b; ; {
+		d := hexValue(ch)
+		if d >= b {
+			r.UnreadRune() // ch does not belong to number anymore
+			break
+		}
+
+		if bb <= max {
+			bb *= b
+			dd = dd*b + d
+		} else {
+			// bb * b would overflow
+			z = z.mulAddWW(z, bb, dd)
+			bb = b
+			dd = d
+		}
+
+		if ch, _, err = r.ReadRune(); err != nil {
+			if err != io.EOF {
+				return z, int(b), err
+			}
+			break
+		}
+	}
+
+	switch {
+	case bb > 1:
+		// there was at least one mantissa digit
+		z = z.mulAddWW(z, bb, dd)
+	case base == 0 && b == 8:
+		// there was only the octal prefix 0 (possibly followed by digits > 7);
+		// return base 10, not 8
+		return z, 10, nil
+	case base != 0 || b != 8:
+		// there was neither a mantissa digit nor the octal prefix 0
+		return z, int(b), errors.New("syntax error scanning number")
+	}
+
+	return z.norm(), int(b), nil
+}
+
+// Character sets for string conversion.
+const (
+	lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
+	uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+)
+
+// decimalString returns a decimal representation of x.
+// It calls x.string with the charset "0123456789".
+func (x nat) decimalString() string {
+	return x.string(lowercaseDigits[0:10])
+}
+
+// string converts x to a string using digits from a charset; a digit with
+// value d is represented by charset[d]. The conversion base is determined
+// by len(charset), which must be >= 2 and <= 256.
+func (x nat) string(charset string) string {
+	b := Word(len(charset))
+
+	// special cases
+	switch {
+	case b < 2 || MaxBase > 256:
+		panic("illegal base")
+	case len(x) == 0:
+		return string(charset[0])
+	}
+
+	// allocate buffer for conversion
+	i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
+	s := make([]byte, i)
+
+	// convert power of two and non power of two bases separately
+	if b == b&-b {
+		// shift is base-b digit size in bits
+		shift := trailingZeroBits(b) // shift > 0 because b >= 2
+		mask := Word(1)<<shift - 1
+		w := x[0]
+		nbits := uint(_W) // number of unprocessed bits in w
+
+		// convert less-significant words
+		for k := 1; k < len(x); k++ {
+			// convert full digits
+			for nbits >= shift {
+				i--
+				s[i] = charset[w&mask]
+				w >>= shift
+				nbits -= shift
+			}
+
+			// convert any partial leading digit and advance to next word
+			if nbits == 0 {
+				// no partial digit remaining, just advance
+				w = x[k]
+				nbits = _W
+			} else {
+				// partial digit in current (k-1) and next (k) word
+				w |= x[k] << nbits
+				i--
+				s[i] = charset[w&mask]
+
+				// advance
+				w = x[k] >> (shift - nbits)
+				nbits = _W - (shift - nbits)
+			}
+		}
+
+		// convert digits of most-significant word (omit leading zeros)
+		for nbits >= 0 && w != 0 {
+			i--
+			s[i] = charset[w&mask]
+			w >>= shift
+			nbits -= shift
+		}
+
+	} else {
+		// determine "big base"; i.e., the largest possible value bb
+		// that is a power of base b and still fits into a Word
+		// (as in 10^19 for 19 decimal digits in a 64bit Word)
+		bb := b      // big base is b**ndigits
+		ndigits := 1 // number of base b digits
+		for max := Word(_M / b); bb <= max; bb *= b {
+			ndigits++ // maximize ndigits where bb = b**ndigits, bb <= _M
+		}
+
+		// construct table of successive squares of bb*leafSize to use in subdivisions
+		// result (table != nil) <=> (len(x) > leafSize > 0)
+		table := divisors(len(x), b, ndigits, bb)
+
+		// preserve x, create local copy for use by convertWords
+		q := nat(nil).set(x)
+
+		// convert q to string s in base b
+		q.convertWords(s, charset, b, ndigits, bb, table)
+
+		// strip leading zeros
+		// (x != 0; thus s must contain at least one non-zero digit
+		// and the loop will terminate)
+		i = 0
+		for zero := charset[0]; s[i] == zero; {
+			i++
+		}
+	}
+
+	return string(s[i:])
+}
+
+// Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
+// by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
+// repeated nat/Word division.
+//
+// The iterative method processes n Words by n divW() calls, each of which visits every Word in the
+// incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s.
+// Recursive conversion divides q by its approximate square root, yielding two parts, each half
+// the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
+// plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
+// is made better by splitting the subblocks recursively. Best is to split blocks until one more
+// split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the
+// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
+// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
+// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
+// specific hardware.
+//
+func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
+	// split larger blocks recursively
+	if table != nil {
+		// len(q) > leafSize > 0
+		var r nat
+		index := len(table) - 1
+		for len(q) > leafSize {
+			// find divisor close to sqrt(q) if possible, but in any case < q
+			maxLength := q.bitLen()     // ~= log2 q, or at of least largest possible q of this bit length
+			minLength := maxLength >> 1 // ~= log2 sqrt(q)
+			for index > 0 && table[index-1].nbits > minLength {
+				index-- // desired
+			}
+			if table[index].nbits >= maxLength && table[index].bbb.cmp(q) >= 0 {
+				index--
+				if index < 0 {
+					panic("internal inconsistency")
+				}
+			}
+
+			// split q into the two digit number (q'*bbb + r) to form independent subblocks
+			q, r = q.div(r, q, table[index].bbb)
+
+			// convert subblocks and collect results in s[:h] and s[h:]
+			h := len(s) - table[index].ndigits
+			r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
+			s = s[:h] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1])
+		}
+	}
+
+	// having split any large blocks now process the remaining (small) block iteratively
+	i := len(s)
+	var r Word
+	if b == 10 {
+		// hard-coding for 10 here speeds this up by 1.25x (allows for / and % by constants)
+		for len(q) > 0 {
+			// extract least significant, base bb "digit"
+			q, r = q.divW(q, bb)
+			for j := 0; j < ndigits && i > 0; j++ {
+				i--
+				// avoid % computation since r%10 == r - int(r/10)*10;
+				// this appears to be faster for BenchmarkString10000Base10
+				// and smaller strings (but a bit slower for larger ones)
+				t := r / 10
+				s[i] = charset[r-t<<3-t-t] // TODO(gri) replace w/ t*10 once compiler produces better code
+				r = t
+			}
+		}
+	} else {
+		for len(q) > 0 {
+			// extract least significant, base bb "digit"
+			q, r = q.divW(q, bb)
+			for j := 0; j < ndigits && i > 0; j++ {
+				i--
+				s[i] = charset[r%b]
+				r /= b
+			}
+		}
+	}
+
+	// prepend high-order zeroes
+	zero := charset[0]
+	for i > 0 { // while need more leading zeroes
+		i--
+		s[i] = zero
+	}
+}
+
+// Split blocks greater than leafSize Words (or set to 0 to disable recursive conversion)
+// Benchmark and configure leafSize using: go test -bench="Leaf"
+//   8 and 16 effective on 3.0 GHz Xeon "Clovertown" CPU (128 byte cache lines)
+//   8 and 16 effective on 2.66 GHz Core 2 Duo "Penryn" CPU
+var leafSize int = 8 // number of Word-size binary values treat as a monolithic block
+
+type divisor struct {
+	bbb     nat // divisor
+	nbits   int // bit length of divisor (discounting leading zeroes) ~= log2(bbb)
+	ndigits int // digit length of divisor in terms of output base digits
+}
+
+var cacheBase10 struct {
+	sync.Mutex
+	table [64]divisor // cached divisors for base 10
+}
+
+// expWW computes x**y
+func (z nat) expWW(x, y Word) nat {
+	return z.expNN(nat(nil).setWord(x), nat(nil).setWord(y), nil)
+}
+
+// construct table of powers of bb*leafSize to use in subdivisions
+func divisors(m int, b Word, ndigits int, bb Word) []divisor {
+	// only compute table when recursive conversion is enabled and x is large
+	if leafSize == 0 || m <= leafSize {
+		return nil
+	}
+
+	// determine k where (bb**leafSize)**(2**k) >= sqrt(x)
+	k := 1
+	for words := leafSize; words < m>>1 && k < len(cacheBase10.table); words <<= 1 {
+		k++
+	}
+
+	// reuse and extend existing table of divisors or create new table as appropriate
+	var table []divisor // for b == 10, table overlaps with cacheBase10.table
+	if b == 10 {
+		cacheBase10.Lock()
+		table = cacheBase10.table[0:k] // reuse old table for this conversion
+	} else {
+		table = make([]divisor, k) // create new table for this conversion
+	}
+
+	// extend table
+	if table[k-1].ndigits == 0 {
+		// add new entries as needed
+		var larger nat
+		for i := 0; i < k; i++ {
+			if table[i].ndigits == 0 {
+				if i == 0 {
+					table[0].bbb = nat(nil).expWW(bb, Word(leafSize))
+					table[0].ndigits = ndigits * leafSize
+				} else {
+					table[i].bbb = nat(nil).mul(table[i-1].bbb, table[i-1].bbb)
+					table[i].ndigits = 2 * table[i-1].ndigits
+				}
+
+				// optimization: exploit aggregated extra bits in macro blocks
+				larger = nat(nil).set(table[i].bbb)
+				for mulAddVWW(larger, larger, b, 0) == 0 {
+					table[i].bbb = table[i].bbb.set(larger)
+					table[i].ndigits++
+				}
+
+				table[i].nbits = table[i].bbb.bitLen()
+			}
+		}
+	}
+
+	if b == 10 {
+		cacheBase10.Unlock()
+	}
+
+	return table
+}
+
+const deBruijn32 = 0x077CB531
+
+var deBruijn32Lookup = []byte{
+	0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
+	31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9,
+}
+
+const deBruijn64 = 0x03f79d71b4ca8b09
+
+var deBruijn64Lookup = []byte{
+	0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
+	62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
+	63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
+	54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
+}
+
+// trailingZeroBits returns the number of consecutive least significant zero
+// bits of x.
+func trailingZeroBits(x Word) uint {
+	// x & -x leaves only the right-most bit set in the word. Let k be the
+	// index of that bit. Since only a single bit is set, the value is two
+	// to the power of k. Multiplying by a power of two is equivalent to
+	// left shifting, in this case by k bits.  The de Bruijn constant is
+	// such that all six bit, consecutive substrings are distinct.
+	// Therefore, if we have a left shifted version of this constant we can
+	// find by how many bits it was shifted by looking at which six bit
+	// substring ended up at the top of the word.
+	// (Knuth, volume 4, section 7.3.1)
+	switch _W {
+	case 32:
+		return uint(deBruijn32Lookup[((x&-x)*deBruijn32)>>27])
+	case 64:
+		return uint(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58])
+	default:
+		panic("unknown word size")
+	}
+}
+
+// trailingZeroBits returns the number of consecutive least significant zero
+// bits of x.
+func (x nat) trailingZeroBits() uint {
+	if len(x) == 0 {
+		return 0
+	}
+	var i uint
+	for x[i] == 0 {
+		i++
+	}
+	// x[i] != 0
+	return i*_W + trailingZeroBits(x[i])
+}
+
+// z = x << s
+func (z nat) shl(x nat, s uint) nat {
+	m := len(x)
+	if m == 0 {
+		return z.make(0)
+	}
+	// m > 0
+
+	n := m + int(s/_W)
+	z = z.make(n + 1)
+	z[n] = shlVU(z[n-m:n], x, s%_W)
+	z[0 : n-m].clear()
+
+	return z.norm()
+}
+
+// z = x >> s
+func (z nat) shr(x nat, s uint) nat {
+	m := len(x)
+	n := m - int(s/_W)
+	if n <= 0 {
+		return z.make(0)
+	}
+	// n > 0
+
+	z = z.make(n)
+	shrVU(z, x[m-n:], s%_W)
+
+	return z.norm()
+}
+
+func (z nat) setBit(x nat, i uint, b uint) nat {
+	j := int(i / _W)
+	m := Word(1) << (i % _W)
+	n := len(x)
+	switch b {
+	case 0:
+		z = z.make(n)
+		copy(z, x)
+		if j >= n {
+			// no need to grow
+			return z
+		}
+		z[j] &^= m
+		return z.norm()
+	case 1:
+		if j >= n {
+			z = z.make(j + 1)
+			z[n:].clear()
+		} else {
+			z = z.make(n)
+		}
+		copy(z, x)
+		z[j] |= m
+		// no need to normalize
+		return z
+	}
+	panic("set bit is not 0 or 1")
+}
+
+func (z nat) bit(i uint) uint {
+	j := int(i / _W)
+	if j >= len(z) {
+		return 0
+	}
+	return uint(z[j] >> (i % _W) & 1)
+}
+
+func (z nat) and(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+	if m > n {
+		m = n
+	}
+	// m <= n
+
+	z = z.make(m)
+	for i := 0; i < m; i++ {
+		z[i] = x[i] & y[i]
+	}
+
+	return z.norm()
+}
+
+func (z nat) andNot(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+	if n > m {
+		n = m
+	}
+	// m >= n
+
+	z = z.make(m)
+	for i := 0; i < n; i++ {
+		z[i] = x[i] &^ y[i]
+	}
+	copy(z[n:m], x[n:m])
+
+	return z.norm()
+}
+
+func (z nat) or(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+	s := x
+	if m < n {
+		n, m = m, n
+		s = y
+	}
+	// m >= n
+
+	z = z.make(m)
+	for i := 0; i < n; i++ {
+		z[i] = x[i] | y[i]
+	}
+	copy(z[n:m], s[n:m])
+
+	return z.norm()
+}
+
+func (z nat) xor(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+	s := x
+	if m < n {
+		n, m = m, n
+		s = y
+	}
+	// m >= n
+
+	z = z.make(m)
+	for i := 0; i < n; i++ {
+		z[i] = x[i] ^ y[i]
+	}
+	copy(z[n:m], s[n:m])
+
+	return z.norm()
+}
+
+// greaterThan returns true iff (x1<<_W + x2) > (y1<<_W + y2)
+func greaterThan(x1, x2, y1, y2 Word) bool {
+	return x1 > y1 || x1 == y1 && x2 > y2
+}
+
+// modW returns x % d.
+func (x nat) modW(d Word) (r Word) {
+	// TODO(agl): we don't actually need to store the q value.
+	var q nat
+	q = q.make(len(x))
+	return divWVW(q, 0, x, d)
+}
+
+// random creates a random integer in [0..limit), using the space in z if
+// possible. n is the bit length of limit.
+func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
+	if alias(z, limit) {
+		z = nil // z is an alias for limit - cannot reuse
+	}
+	z = z.make(len(limit))
+
+	bitLengthOfMSW := uint(n % _W)
+	if bitLengthOfMSW == 0 {
+		bitLengthOfMSW = _W
+	}
+	mask := Word((1 << bitLengthOfMSW) - 1)
+
+	for {
+		switch _W {
+		case 32:
+			for i := range z {
+				z[i] = Word(rand.Uint32())
+			}
+		case 64:
+			for i := range z {
+				z[i] = Word(rand.Uint32()) | Word(rand.Uint32())<<32
+			}
+		default:
+			panic("unknown word size")
+		}
+		z[len(limit)-1] &= mask
+		if z.cmp(limit) < 0 {
+			break
+		}
+	}
+
+	return z.norm()
+}
+
+// If m != 0 (i.e., len(m) != 0), expNN sets z to x**y mod m;
+// otherwise it sets z to x**y. The result is the value of z.
+func (z nat) expNN(x, y, m nat) nat {
+	if alias(z, x) || alias(z, y) {
+		// We cannot allow in-place modification of x or y.
+		z = nil
+	}
+
+	// x**y mod 1 == 0
+	if len(m) == 1 && m[0] == 1 {
+		return z.setWord(0)
+	}
+	// m == 0 || m > 1
+
+	// x**0 == 1
+	if len(y) == 0 {
+		return z.setWord(1)
+	}
+	// y > 0
+
+	if len(m) != 0 {
+		// We likely end up being as long as the modulus.
+		z = z.make(len(m))
+	}
+	z = z.set(x)
+
+	// If the base is non-trivial and the exponent is large, we use
+	// 4-bit, windowed exponentiation. This involves precomputing 14 values
+	// (x^2...x^15) but then reduces the number of multiply-reduces by a
+	// third. Even for a 32-bit exponent, this reduces the number of
+	// operations.
+	if len(x) > 1 && len(y) > 1 && len(m) > 0 {
+		return z.expNNWindowed(x, y, m)
+	}
+
+	v := y[len(y)-1] // v > 0 because y is normalized and y > 0
+	shift := leadingZeros(v) + 1
+	v <<= shift
+	var q nat
+
+	const mask = 1 << (_W - 1)
+
+	// We walk through the bits of the exponent one by one. Each time we
+	// see a bit, we square, thus doubling the power. If the bit is a one,
+	// we also multiply by x, thus adding one to the power.
+
+	w := _W - int(shift)
+	// zz and r are used to avoid allocating in mul and div as
+	// otherwise the arguments would alias.
+	var zz, r nat
+	for j := 0; j < w; j++ {
+		zz = zz.mul(z, z)
+		zz, z = z, zz
+
+		if v&mask != 0 {
+			zz = zz.mul(z, x)
+			zz, z = z, zz
+		}
+
+		if len(m) != 0 {
+			zz, r = zz.div(r, z, m)
+			zz, r, q, z = q, z, zz, r
+		}
+
+		v <<= 1
+	}
+
+	for i := len(y) - 2; i >= 0; i-- {
+		v = y[i]
+
+		for j := 0; j < _W; j++ {
+			zz = zz.mul(z, z)
+			zz, z = z, zz
+
+			if v&mask != 0 {
+				zz = zz.mul(z, x)
+				zz, z = z, zz
+			}
+
+			if len(m) != 0 {
+				zz, r = zz.div(r, z, m)
+				zz, r, q, z = q, z, zz, r
+			}
+
+			v <<= 1
+		}
+	}
+
+	return z.norm()
+}
+
+// expNNWindowed calculates x**y mod m using a fixed, 4-bit window.
+func (z nat) expNNWindowed(x, y, m nat) nat {
+	// zz and r are used to avoid allocating in mul and div as otherwise
+	// the arguments would alias.
+	var zz, r nat
+
+	const n = 4
+	// powers[i] contains x^i.
+	var powers [1 << n]nat
+	powers[0] = natOne
+	powers[1] = x
+	for i := 2; i < 1<<n; i += 2 {
+		p2, p, p1 := &powers[i/2], &powers[i], &powers[i+1]
+		*p = p.mul(*p2, *p2)
+		zz, r = zz.div(r, *p, m)
+		*p, r = r, *p
+		*p1 = p1.mul(*p, x)
+		zz, r = zz.div(r, *p1, m)
+		*p1, r = r, *p1
+	}
+
+	z = z.setWord(1)
+
+	for i := len(y) - 1; i >= 0; i-- {
+		yi := y[i]
+		for j := 0; j < _W; j += n {
+			if i != len(y)-1 || j != 0 {
+				// Unrolled loop for significant performance
+				// gain.  Use go test -bench=".*" in crypto/rsa
+				// to check performance before making changes.
+				zz = zz.mul(z, z)
+				zz, z = z, zz
+				zz, r = zz.div(r, z, m)
+				z, r = r, z
+
+				zz = zz.mul(z, z)
+				zz, z = z, zz
+				zz, r = zz.div(r, z, m)
+				z, r = r, z
+
+				zz = zz.mul(z, z)
+				zz, z = z, zz
+				zz, r = zz.div(r, z, m)
+				z, r = r, z
+
+				zz = zz.mul(z, z)
+				zz, z = z, zz
+				zz, r = zz.div(r, z, m)
+				z, r = r, z
+			}
+
+			zz = zz.mul(z, powers[yi>>(_W-n)])
+			zz, z = z, zz
+			zz, r = zz.div(r, z, m)
+			z, r = r, z
+
+			yi <<= n
+		}
+	}
+
+	return z.norm()
+}
+
+// probablyPrime performs reps Miller-Rabin tests to check whether n is prime.
+// If it returns true, n is prime with probability 1 - 1/4^reps.
+// If it returns false, n is not prime.
+func (n nat) probablyPrime(reps int) bool {
+	if len(n) == 0 {
+		return false
+	}
+
+	if len(n) == 1 {
+		if n[0] < 2 {
+			return false
+		}
+
+		if n[0]%2 == 0 {
+			return n[0] == 2
+		}
+
+		// We have to exclude these cases because we reject all
+		// multiples of these numbers below.
+		switch n[0] {
+		case 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53:
+			return true
+		}
+	}
+
+	const primesProduct32 = 0xC0CFD797         // Π {p ∈ primes, 2 < p <= 29}
+	const primesProduct64 = 0xE221F97C30E94E1D // Π {p ∈ primes, 2 < p <= 53}
+
+	var r Word
+	switch _W {
+	case 32:
+		r = n.modW(primesProduct32)
+	case 64:
+		r = n.modW(primesProduct64 & _M)
+	default:
+		panic("Unknown word size")
+	}
+
+	if r%3 == 0 || r%5 == 0 || r%7 == 0 || r%11 == 0 ||
+		r%13 == 0 || r%17 == 0 || r%19 == 0 || r%23 == 0 || r%29 == 0 {
+		return false
+	}
+
+	if _W == 64 && (r%31 == 0 || r%37 == 0 || r%41 == 0 ||
+		r%43 == 0 || r%47 == 0 || r%53 == 0) {
+		return false
+	}
+
+	nm1 := nat(nil).sub(n, natOne)
+	// determine q, k such that nm1 = q << k
+	k := nm1.trailingZeroBits()
+	q := nat(nil).shr(nm1, k)
+
+	nm3 := nat(nil).sub(nm1, natTwo)
+	rand := rand.New(rand.NewSource(int64(n[0])))
+
+	var x, y, quotient nat
+	nm3Len := nm3.bitLen()
+
+NextRandom:
+	for i := 0; i < reps; i++ {
+		x = x.random(rand, nm3, nm3Len)
+		x = x.add(x, natTwo)
+		y = y.expNN(x, q, n)
+		if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 {
+			continue
+		}
+		for j := uint(1); j < k; j++ {
+			y = y.mul(y, y)
+			quotient, y = quotient.div(y, y, n)
+			if y.cmp(nm1) == 0 {
+				continue NextRandom
+			}
+			if y.cmp(natOne) == 0 {
+				return false
+			}
+		}
+		return false
+	}
+
+	return true
+}
+
+// bytes writes the value of z into buf using big-endian encoding.
+// len(buf) must be >= len(z)*_S. The value of z is encoded in the
+// slice buf[i:]. The number i of unused bytes at the beginning of
+// buf is returned as result.
+func (z nat) bytes(buf []byte) (i int) {
+	i = len(buf)
+	for _, d := range z {
+		for j := 0; j < _S; j++ {
+			i--
+			buf[i] = byte(d)
+			d >>= 8
+		}
+	}
+
+	for i < len(buf) && buf[i] == 0 {
+		i++
+	}
+
+	return
+}
+
+// setBytes interprets buf as the bytes of a big-endian unsigned
+// integer, sets z to that value, and returns z.
+func (z nat) setBytes(buf []byte) nat {
+	z = z.make((len(buf) + _S - 1) / _S)
+
+	k := 0
+	s := uint(0)
+	var d Word
+	for i := len(buf); i > 0; i-- {
+		d |= Word(buf[i-1]) << s
+		if s += 8; s == _S*8 {
+			z[k] = d
+			k++
+			s = 0
+			d = 0
+		}
+	}
+	if k < len(z) {
+		z[k] = d
+	}
+
+	return z.norm()
+}
diff --git a/third_party/gofrontend/libgo/go/math/big/nat_test.go b/third_party/gofrontend/libgo/go/math/big/nat_test.go
new file mode 100644
index 0000000..a2ae533
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/nat_test.go
@@ -0,0 +1,771 @@
+// 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 big
+
+import (
+	"io"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+var cmpTests = []struct {
+	x, y nat
+	r    int
+}{
+	{nil, nil, 0},
+	{nil, nat(nil), 0},
+	{nat(nil), nil, 0},
+	{nat(nil), nat(nil), 0},
+	{nat{0}, nat{0}, 0},
+	{nat{0}, nat{1}, -1},
+	{nat{1}, nat{0}, 1},
+	{nat{1}, nat{1}, 0},
+	{nat{0, _M}, nat{1}, 1},
+	{nat{1}, nat{0, _M}, -1},
+	{nat{1, _M}, nat{0, _M}, 1},
+	{nat{0, _M}, nat{1, _M}, -1},
+	{nat{16, 571956, 8794, 68}, nat{837, 9146, 1, 754489}, -1},
+	{nat{34986, 41, 105, 1957}, nat{56, 7458, 104, 1957}, 1},
+}
+
+func TestCmp(t *testing.T) {
+	for i, a := range cmpTests {
+		r := a.x.cmp(a.y)
+		if r != a.r {
+			t.Errorf("#%d got r = %v; want %v", i, r, a.r)
+		}
+	}
+}
+
+type funNN func(z, x, y nat) nat
+type argNN struct {
+	z, x, y nat
+}
+
+var sumNN = []argNN{
+	{},
+	{nat{1}, nil, nat{1}},
+	{nat{1111111110}, nat{123456789}, nat{987654321}},
+	{nat{0, 0, 0, 1}, nil, nat{0, 0, 0, 1}},
+	{nat{0, 0, 0, 1111111110}, nat{0, 0, 0, 123456789}, nat{0, 0, 0, 987654321}},
+	{nat{0, 0, 0, 1}, nat{0, 0, _M}, nat{0, 0, 1}},
+}
+
+var prodNN = []argNN{
+	{},
+	{nil, nil, nil},
+	{nil, nat{991}, nil},
+	{nat{991}, nat{991}, nat{1}},
+	{nat{991 * 991}, nat{991}, nat{991}},
+	{nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}},
+	{nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}},
+	{nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}},
+	// 3^100 * 3^28 = 3^128
+	{
+		natFromString("11790184577738583171520872861412518665678211592275841109096961"),
+		natFromString("515377520732011331036461129765621272702107522001"),
+		natFromString("22876792454961"),
+	},
+	// z = 111....1 (70000 digits)
+	// x = 10^(99*700) + ... + 10^1400 + 10^700 + 1
+	// y = 111....1 (700 digits, larger than Karatsuba threshold on 32-bit and 64-bit)
+	{
+		natFromString(strings.Repeat("1", 70000)),
+		natFromString("1" + strings.Repeat(strings.Repeat("0", 699)+"1", 99)),
+		natFromString(strings.Repeat("1", 700)),
+	},
+	// z = 111....1 (20000 digits)
+	// x = 10^10000 + 1
+	// y = 111....1 (10000 digits)
+	{
+		natFromString(strings.Repeat("1", 20000)),
+		natFromString("1" + strings.Repeat("0", 9999) + "1"),
+		natFromString(strings.Repeat("1", 10000)),
+	},
+}
+
+func natFromString(s string) nat {
+	x, _, err := nat(nil).scan(strings.NewReader(s), 0)
+	if err != nil {
+		panic(err)
+	}
+	return x
+}
+
+func TestSet(t *testing.T) {
+	for _, a := range sumNN {
+		z := nat(nil).set(a.z)
+		if z.cmp(a.z) != 0 {
+			t.Errorf("got z = %v; want %v", z, a.z)
+		}
+	}
+}
+
+func testFunNN(t *testing.T, msg string, f funNN, a argNN) {
+	z := f(nil, a.x, a.y)
+	if z.cmp(a.z) != 0 {
+		t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z)
+	}
+}
+
+func TestFunNN(t *testing.T) {
+	for _, a := range sumNN {
+		arg := a
+		testFunNN(t, "add", nat.add, arg)
+
+		arg = argNN{a.z, a.y, a.x}
+		testFunNN(t, "add symmetric", nat.add, arg)
+
+		arg = argNN{a.x, a.z, a.y}
+		testFunNN(t, "sub", nat.sub, arg)
+
+		arg = argNN{a.y, a.z, a.x}
+		testFunNN(t, "sub symmetric", nat.sub, arg)
+	}
+
+	for _, a := range prodNN {
+		arg := a
+		testFunNN(t, "mul", nat.mul, arg)
+
+		arg = argNN{a.z, a.y, a.x}
+		testFunNN(t, "mul symmetric", nat.mul, arg)
+	}
+}
+
+var mulRangesN = []struct {
+	a, b uint64
+	prod string
+}{
+	{0, 0, "0"},
+	{1, 1, "1"},
+	{1, 2, "2"},
+	{1, 3, "6"},
+	{10, 10, "10"},
+	{0, 100, "0"},
+	{0, 1e9, "0"},
+	{1, 0, "1"},                    // empty range
+	{100, 1, "1"},                  // empty range
+	{1, 10, "3628800"},             // 10!
+	{1, 20, "2432902008176640000"}, // 20!
+	{1, 100,
+		"933262154439441526816992388562667004907159682643816214685929" +
+			"638952175999932299156089414639761565182862536979208272237582" +
+			"51185210916864000000000000000000000000", // 100!
+	},
+}
+
+func TestMulRangeN(t *testing.T) {
+	for i, r := range mulRangesN {
+		prod := nat(nil).mulRange(r.a, r.b).decimalString()
+		if prod != r.prod {
+			t.Errorf("#%d: got %s; want %s", i, prod, r.prod)
+		}
+	}
+}
+
+// allocBytes returns the number of bytes allocated by invoking f.
+func allocBytes(f func()) uint64 {
+	var stats runtime.MemStats
+	runtime.ReadMemStats(&stats)
+	t := stats.TotalAlloc
+	f()
+	runtime.ReadMemStats(&stats)
+	return stats.TotalAlloc - t
+}
+
+// TestMulUnbalanced tests that multiplying numbers of different lengths
+// does not cause deep recursion and in turn allocate too much memory.
+// Test case for issue 3807.
+func TestMulUnbalanced(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
+	x := rndNat(50000)
+	y := rndNat(40)
+	allocSize := allocBytes(func() {
+		nat(nil).mul(x, y)
+	})
+	inputSize := uint64(len(x)+len(y)) * _S
+	if ratio := allocSize / uint64(inputSize); ratio > 10 {
+		t.Errorf("multiplication uses too much memory (%d > %d times the size of inputs)", allocSize, ratio)
+	}
+}
+
+func rndNat(n int) nat {
+	return nat(rndV(n)).norm()
+}
+
+func BenchmarkMul(b *testing.B) {
+	mulx := rndNat(1e4)
+	muly := rndNat(1e4)
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		var z nat
+		z.mul(mulx, muly)
+	}
+}
+
+func toString(x nat, charset string) string {
+	base := len(charset)
+
+	// special cases
+	switch {
+	case base < 2:
+		panic("illegal base")
+	case len(x) == 0:
+		return string(charset[0])
+	}
+
+	// allocate buffer for conversion
+	i := x.bitLen()/log2(Word(base)) + 1 // +1: round up
+	s := make([]byte, i)
+
+	// don't destroy x
+	q := nat(nil).set(x)
+
+	// convert
+	for len(q) > 0 {
+		i--
+		var r Word
+		q, r = q.divW(q, Word(base))
+		s[i] = charset[r]
+	}
+
+	return string(s[i:])
+}
+
+var strTests = []struct {
+	x nat    // nat value to be converted
+	c string // conversion charset
+	s string // expected result
+}{
+	{nil, "01", "0"},
+	{nat{1}, "01", "1"},
+	{nat{0xc5}, "01", "11000101"},
+	{nat{03271}, lowercaseDigits[0:8], "3271"},
+	{nat{10}, lowercaseDigits[0:10], "10"},
+	{nat{1234567890}, uppercaseDigits[0:10], "1234567890"},
+	{nat{0xdeadbeef}, lowercaseDigits[0:16], "deadbeef"},
+	{nat{0xdeadbeef}, uppercaseDigits[0:16], "DEADBEEF"},
+	{nat{0x229be7}, lowercaseDigits[0:17], "1a2b3c"},
+	{nat{0x309663e6}, uppercaseDigits[0:32], "O9COV6"},
+}
+
+func TestString(t *testing.T) {
+	for _, a := range strTests {
+		s := a.x.string(a.c)
+		if s != a.s {
+			t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
+		}
+
+		x, b, err := nat(nil).scan(strings.NewReader(a.s), len(a.c))
+		if x.cmp(a.x) != 0 {
+			t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
+		}
+		if b != len(a.c) {
+			t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c))
+		}
+		if err != nil {
+			t.Errorf("scan%+v\n\tgot error = %s", a, err)
+		}
+	}
+}
+
+var natScanTests = []struct {
+	s    string // string to be scanned
+	base int    // input base
+	x    nat    // expected nat
+	b    int    // expected base
+	ok   bool   // expected success
+	next rune   // next character (or 0, if at EOF)
+}{
+	// error: illegal base
+	{base: -1},
+	{base: 1},
+	{base: 37},
+
+	// error: no mantissa
+	{},
+	{s: "?"},
+	{base: 10},
+	{base: 36},
+	{s: "?", base: 10},
+	{s: "0x"},
+	{s: "345", base: 2},
+
+	// no errors
+	{"0", 0, nil, 10, true, 0},
+	{"0", 10, nil, 10, true, 0},
+	{"0", 36, nil, 36, true, 0},
+	{"1", 0, nat{1}, 10, true, 0},
+	{"1", 10, nat{1}, 10, true, 0},
+	{"0 ", 0, nil, 10, true, ' '},
+	{"08", 0, nil, 10, true, '8'},
+	{"018", 0, nat{1}, 8, true, '8'},
+	{"0b1", 0, nat{1}, 2, true, 0},
+	{"0b11000101", 0, nat{0xc5}, 2, true, 0},
+	{"03271", 0, nat{03271}, 8, true, 0},
+	{"10ab", 0, nat{10}, 10, true, 'a'},
+	{"1234567890", 0, nat{1234567890}, 10, true, 0},
+	{"xyz", 36, nat{(33*36+34)*36 + 35}, 36, true, 0},
+	{"xyz?", 36, nat{(33*36+34)*36 + 35}, 36, true, '?'},
+	{"0x", 16, nil, 16, true, 'x'},
+	{"0xdeadbeef", 0, nat{0xdeadbeef}, 16, true, 0},
+	{"0XDEADBEEF", 0, nat{0xdeadbeef}, 16, true, 0},
+}
+
+func TestScanBase(t *testing.T) {
+	for _, a := range natScanTests {
+		r := strings.NewReader(a.s)
+		x, b, err := nat(nil).scan(r, a.base)
+		if err == nil && !a.ok {
+			t.Errorf("scan%+v\n\texpected error", a)
+		}
+		if err != nil {
+			if a.ok {
+				t.Errorf("scan%+v\n\tgot error = %s", a, err)
+			}
+			continue
+		}
+		if x.cmp(a.x) != 0 {
+			t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
+		}
+		if b != a.b {
+			t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base)
+		}
+		next, _, err := r.ReadRune()
+		if err == io.EOF {
+			next = 0
+			err = nil
+		}
+		if err == nil && next != a.next {
+			t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next)
+		}
+	}
+}
+
+var pi = "3" +
+	"14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" +
+	"32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" +
+	"28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" +
+	"96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" +
+	"31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" +
+	"60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" +
+	"22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" +
+	"29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" +
+	"81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" +
+	"21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" +
+	"55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" +
+	"63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" +
+	"75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" +
+	"45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" +
+	"34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" +
+	"16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" +
+	"04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" +
+	"26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" +
+	"99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" +
+	"53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" +
+	"68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" +
+	"13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" +
+	"88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" +
+	"79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" +
+	"68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" +
+	"21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" +
+	"06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" +
+	"14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" +
+	"21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" +
+	"05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" +
+	"23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" +
+	"90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" +
+	"31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" +
+	"20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" +
+	"97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" +
+	"44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" +
+	"44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" +
+	"85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" +
+	"58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" +
+	"27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" +
+	"09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" +
+	"79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" +
+	"06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" +
+	"91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" +
+	"94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" +
+	"78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" +
+	"24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" +
+	"59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" +
+	"34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" +
+	"88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" +
+	"94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337"
+
+// Test case for BenchmarkScanPi.
+func TestScanPi(t *testing.T) {
+	var x nat
+	z, _, err := x.scan(strings.NewReader(pi), 10)
+	if err != nil {
+		t.Errorf("scanning pi: %s", err)
+	}
+	if s := z.decimalString(); s != pi {
+		t.Errorf("scanning pi: got %s", s)
+	}
+}
+
+func TestScanPiParallel(t *testing.T) {
+	const n = 2
+	c := make(chan int)
+	for i := 0; i < n; i++ {
+		go func() {
+			TestScanPi(t)
+			c <- 0
+		}()
+	}
+	for i := 0; i < n; i++ {
+		<-c
+	}
+}
+
+func BenchmarkScanPi(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		var x nat
+		x.scan(strings.NewReader(pi), 10)
+	}
+}
+
+func BenchmarkStringPiParallel(b *testing.B) {
+	var x nat
+	x, _, _ = x.scan(strings.NewReader(pi), 0)
+	if x.decimalString() != pi {
+		panic("benchmark incorrect: conversion failed")
+	}
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			x.decimalString()
+		}
+	})
+}
+
+func BenchmarkScan10Base2(b *testing.B)     { ScanHelper(b, 2, 10, 10) }
+func BenchmarkScan100Base2(b *testing.B)    { ScanHelper(b, 2, 10, 100) }
+func BenchmarkScan1000Base2(b *testing.B)   { ScanHelper(b, 2, 10, 1000) }
+func BenchmarkScan10000Base2(b *testing.B)  { ScanHelper(b, 2, 10, 10000) }
+func BenchmarkScan100000Base2(b *testing.B) { ScanHelper(b, 2, 10, 100000) }
+
+func BenchmarkScan10Base8(b *testing.B)     { ScanHelper(b, 8, 10, 10) }
+func BenchmarkScan100Base8(b *testing.B)    { ScanHelper(b, 8, 10, 100) }
+func BenchmarkScan1000Base8(b *testing.B)   { ScanHelper(b, 8, 10, 1000) }
+func BenchmarkScan10000Base8(b *testing.B)  { ScanHelper(b, 8, 10, 10000) }
+func BenchmarkScan100000Base8(b *testing.B) { ScanHelper(b, 8, 10, 100000) }
+
+func BenchmarkScan10Base10(b *testing.B)     { ScanHelper(b, 10, 10, 10) }
+func BenchmarkScan100Base10(b *testing.B)    { ScanHelper(b, 10, 10, 100) }
+func BenchmarkScan1000Base10(b *testing.B)   { ScanHelper(b, 10, 10, 1000) }
+func BenchmarkScan10000Base10(b *testing.B)  { ScanHelper(b, 10, 10, 10000) }
+func BenchmarkScan100000Base10(b *testing.B) { ScanHelper(b, 10, 10, 100000) }
+
+func BenchmarkScan10Base16(b *testing.B)     { ScanHelper(b, 16, 10, 10) }
+func BenchmarkScan100Base16(b *testing.B)    { ScanHelper(b, 16, 10, 100) }
+func BenchmarkScan1000Base16(b *testing.B)   { ScanHelper(b, 16, 10, 1000) }
+func BenchmarkScan10000Base16(b *testing.B)  { ScanHelper(b, 16, 10, 10000) }
+func BenchmarkScan100000Base16(b *testing.B) { ScanHelper(b, 16, 10, 100000) }
+
+func ScanHelper(b *testing.B, base int, x, y Word) {
+	b.StopTimer()
+	var z nat
+	z = z.expWW(x, y)
+
+	var s string
+	s = z.string(lowercaseDigits[0:base])
+	if t := toString(z, lowercaseDigits[0:base]); t != s {
+		b.Fatalf("scanning: got %s; want %s", s, t)
+	}
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		z.scan(strings.NewReader(s), base)
+	}
+}
+
+func BenchmarkString10Base2(b *testing.B)     { StringHelper(b, 2, 10, 10) }
+func BenchmarkString100Base2(b *testing.B)    { StringHelper(b, 2, 10, 100) }
+func BenchmarkString1000Base2(b *testing.B)   { StringHelper(b, 2, 10, 1000) }
+func BenchmarkString10000Base2(b *testing.B)  { StringHelper(b, 2, 10, 10000) }
+func BenchmarkString100000Base2(b *testing.B) { StringHelper(b, 2, 10, 100000) }
+
+func BenchmarkString10Base8(b *testing.B)     { StringHelper(b, 8, 10, 10) }
+func BenchmarkString100Base8(b *testing.B)    { StringHelper(b, 8, 10, 100) }
+func BenchmarkString1000Base8(b *testing.B)   { StringHelper(b, 8, 10, 1000) }
+func BenchmarkString10000Base8(b *testing.B)  { StringHelper(b, 8, 10, 10000) }
+func BenchmarkString100000Base8(b *testing.B) { StringHelper(b, 8, 10, 100000) }
+
+func BenchmarkString10Base10(b *testing.B)     { StringHelper(b, 10, 10, 10) }
+func BenchmarkString100Base10(b *testing.B)    { StringHelper(b, 10, 10, 100) }
+func BenchmarkString1000Base10(b *testing.B)   { StringHelper(b, 10, 10, 1000) }
+func BenchmarkString10000Base10(b *testing.B)  { StringHelper(b, 10, 10, 10000) }
+func BenchmarkString100000Base10(b *testing.B) { StringHelper(b, 10, 10, 100000) }
+
+func BenchmarkString10Base16(b *testing.B)     { StringHelper(b, 16, 10, 10) }
+func BenchmarkString100Base16(b *testing.B)    { StringHelper(b, 16, 10, 100) }
+func BenchmarkString1000Base16(b *testing.B)   { StringHelper(b, 16, 10, 1000) }
+func BenchmarkString10000Base16(b *testing.B)  { StringHelper(b, 16, 10, 10000) }
+func BenchmarkString100000Base16(b *testing.B) { StringHelper(b, 16, 10, 100000) }
+
+func StringHelper(b *testing.B, base int, x, y Word) {
+	b.StopTimer()
+	var z nat
+	z = z.expWW(x, y)
+	z.string(lowercaseDigits[0:base]) // warm divisor cache
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		_ = z.string(lowercaseDigits[0:base])
+	}
+}
+
+func BenchmarkLeafSize0(b *testing.B)  { LeafSizeHelper(b, 10, 0) } // test without splitting
+func BenchmarkLeafSize1(b *testing.B)  { LeafSizeHelper(b, 10, 1) }
+func BenchmarkLeafSize2(b *testing.B)  { LeafSizeHelper(b, 10, 2) }
+func BenchmarkLeafSize3(b *testing.B)  { LeafSizeHelper(b, 10, 3) }
+func BenchmarkLeafSize4(b *testing.B)  { LeafSizeHelper(b, 10, 4) }
+func BenchmarkLeafSize5(b *testing.B)  { LeafSizeHelper(b, 10, 5) }
+func BenchmarkLeafSize6(b *testing.B)  { LeafSizeHelper(b, 10, 6) }
+func BenchmarkLeafSize7(b *testing.B)  { LeafSizeHelper(b, 10, 7) }
+func BenchmarkLeafSize8(b *testing.B)  { LeafSizeHelper(b, 10, 8) }
+func BenchmarkLeafSize9(b *testing.B)  { LeafSizeHelper(b, 10, 9) }
+func BenchmarkLeafSize10(b *testing.B) { LeafSizeHelper(b, 10, 10) }
+func BenchmarkLeafSize11(b *testing.B) { LeafSizeHelper(b, 10, 11) }
+func BenchmarkLeafSize12(b *testing.B) { LeafSizeHelper(b, 10, 12) }
+func BenchmarkLeafSize13(b *testing.B) { LeafSizeHelper(b, 10, 13) }
+func BenchmarkLeafSize14(b *testing.B) { LeafSizeHelper(b, 10, 14) }
+func BenchmarkLeafSize15(b *testing.B) { LeafSizeHelper(b, 10, 15) }
+func BenchmarkLeafSize16(b *testing.B) { LeafSizeHelper(b, 10, 16) }
+func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths
+func BenchmarkLeafSize64(b *testing.B) { LeafSizeHelper(b, 10, 64) }
+
+func LeafSizeHelper(b *testing.B, base Word, size int) {
+	b.StopTimer()
+	originalLeafSize := leafSize
+	resetTable(cacheBase10.table[:])
+	leafSize = size
+	b.StartTimer()
+
+	for d := 1; d <= 10000; d *= 10 {
+		b.StopTimer()
+		var z nat
+		z = z.expWW(base, Word(d))            // build target number
+		_ = z.string(lowercaseDigits[0:base]) // warm divisor cache
+		b.StartTimer()
+
+		for i := 0; i < b.N; i++ {
+			_ = z.string(lowercaseDigits[0:base])
+		}
+	}
+
+	b.StopTimer()
+	resetTable(cacheBase10.table[:])
+	leafSize = originalLeafSize
+	b.StartTimer()
+}
+
+func resetTable(table []divisor) {
+	if table != nil && table[0].bbb != nil {
+		for i := 0; i < len(table); i++ {
+			table[i].bbb = nil
+			table[i].nbits = 0
+			table[i].ndigits = 0
+		}
+	}
+}
+
+func TestStringPowers(t *testing.T) {
+	var b, p Word
+	for b = 2; b <= 16; b++ {
+		for p = 0; p <= 512; p++ {
+			x := nat(nil).expWW(b, p)
+			xs := x.string(lowercaseDigits[0:b])
+			xs2 := toString(x, lowercaseDigits[0:b])
+			if xs != xs2 {
+				t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
+			}
+		}
+		if b >= 3 && testing.Short() {
+			break
+		}
+	}
+}
+
+func TestLeadingZeros(t *testing.T) {
+	var x Word = _B >> 1
+	for i := 0; i <= _W; i++ {
+		if int(leadingZeros(x)) != i {
+			t.Errorf("failed at %x: got %d want %d", x, leadingZeros(x), i)
+		}
+		x >>= 1
+	}
+}
+
+type shiftTest struct {
+	in    nat
+	shift uint
+	out   nat
+}
+
+var leftShiftTests = []shiftTest{
+	{nil, 0, nil},
+	{nil, 1, nil},
+	{natOne, 0, natOne},
+	{natOne, 1, natTwo},
+	{nat{1 << (_W - 1)}, 1, nat{0}},
+	{nat{1 << (_W - 1), 0}, 1, nat{0, 1}},
+}
+
+func TestShiftLeft(t *testing.T) {
+	for i, test := range leftShiftTests {
+		var z nat
+		z = z.shl(test.in, test.shift)
+		for j, d := range test.out {
+			if j >= len(z) || z[j] != d {
+				t.Errorf("#%d: got: %v want: %v", i, z, test.out)
+				break
+			}
+		}
+	}
+}
+
+var rightShiftTests = []shiftTest{
+	{nil, 0, nil},
+	{nil, 1, nil},
+	{natOne, 0, natOne},
+	{natOne, 1, nil},
+	{natTwo, 1, natOne},
+	{nat{0, 1}, 1, nat{1 << (_W - 1)}},
+	{nat{2, 1, 1}, 1, nat{1<<(_W-1) + 1, 1 << (_W - 1)}},
+}
+
+func TestShiftRight(t *testing.T) {
+	for i, test := range rightShiftTests {
+		var z nat
+		z = z.shr(test.in, test.shift)
+		for j, d := range test.out {
+			if j >= len(z) || z[j] != d {
+				t.Errorf("#%d: got: %v want: %v", i, z, test.out)
+				break
+			}
+		}
+	}
+}
+
+type modWTest struct {
+	in       string
+	dividend string
+	out      string
+}
+
+var modWTests32 = []modWTest{
+	{"23492635982634928349238759823742", "252341", "220170"},
+}
+
+var modWTests64 = []modWTest{
+	{"6527895462947293856291561095690465243862946", "524326975699234", "375066989628668"},
+}
+
+func runModWTests(t *testing.T, tests []modWTest) {
+	for i, test := range tests {
+		in, _ := new(Int).SetString(test.in, 10)
+		d, _ := new(Int).SetString(test.dividend, 10)
+		out, _ := new(Int).SetString(test.out, 10)
+
+		r := in.abs.modW(d.abs[0])
+		if r != out.abs[0] {
+			t.Errorf("#%d failed: got %d want %s", i, r, out)
+		}
+	}
+}
+
+func TestModW(t *testing.T) {
+	if _W >= 32 {
+		runModWTests(t, modWTests32)
+	}
+	if _W >= 64 {
+		runModWTests(t, modWTests64)
+	}
+}
+
+func TestTrailingZeroBits(t *testing.T) {
+	x := Word(1)
+	for i := uint(0); i <= _W; i++ {
+		n := trailingZeroBits(x)
+		if n != i%_W {
+			t.Errorf("got trailingZeroBits(%#x) = %d; want %d", x, n, i%_W)
+		}
+		x <<= 1
+	}
+
+	y := nat(nil).set(natOne)
+	for i := uint(0); i <= 3*_W; i++ {
+		n := y.trailingZeroBits()
+		if n != i {
+			t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.string(lowercaseDigits[0:16]), n, i)
+		}
+		y = y.shl(y, 1)
+	}
+}
+
+var expNNTests = []struct {
+	x, y, m string
+	out     string
+}{
+	{"0", "0", "0", "1"},
+	{"0", "0", "1", "0"},
+	{"1", "1", "1", "0"},
+	{"2", "1", "1", "0"},
+	{"2", "2", "1", "0"},
+	{"10", "100000000000", "1", "0"},
+	{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"},
+	{"0x8000000000000000", "2", "6719", "4944"},
+	{"0x8000000000000000", "3", "6719", "5447"},
+	{"0x8000000000000000", "1000", "6719", "1603"},
+	{"0x8000000000000000", "1000000", "6719", "3199"},
+	{
+		"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
+		"298472983472983471903246121093472394872319615612417471234712061",
+		"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
+		"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
+	},
+}
+
+func TestExpNN(t *testing.T) {
+	for i, test := range expNNTests {
+		x, _, _ := nat(nil).scan(strings.NewReader(test.x), 0)
+		y, _, _ := nat(nil).scan(strings.NewReader(test.y), 0)
+		out, _, _ := nat(nil).scan(strings.NewReader(test.out), 0)
+
+		var m nat
+
+		if len(test.m) > 0 {
+			m, _, _ = nat(nil).scan(strings.NewReader(test.m), 0)
+		}
+
+		z := nat(nil).expNN(x, y, m)
+		if z.cmp(out) != 0 {
+			t.Errorf("#%d got %s want %s", i, z.decimalString(), out.decimalString())
+		}
+	}
+}
+
+func ExpHelper(b *testing.B, x, y Word) {
+	var z nat
+	for i := 0; i < b.N; i++ {
+		z.expWW(x, y)
+	}
+}
+
+func BenchmarkExp3Power0x10(b *testing.B)     { ExpHelper(b, 3, 0x10) }
+func BenchmarkExp3Power0x40(b *testing.B)     { ExpHelper(b, 3, 0x40) }
+func BenchmarkExp3Power0x100(b *testing.B)    { ExpHelper(b, 3, 0x100) }
+func BenchmarkExp3Power0x400(b *testing.B)    { ExpHelper(b, 3, 0x400) }
+func BenchmarkExp3Power0x1000(b *testing.B)   { ExpHelper(b, 3, 0x1000) }
+func BenchmarkExp3Power0x4000(b *testing.B)   { ExpHelper(b, 3, 0x4000) }
+func BenchmarkExp3Power0x10000(b *testing.B)  { ExpHelper(b, 3, 0x10000) }
+func BenchmarkExp3Power0x40000(b *testing.B)  { ExpHelper(b, 3, 0x40000) }
+func BenchmarkExp3Power0x100000(b *testing.B) { ExpHelper(b, 3, 0x100000) }
+func BenchmarkExp3Power0x400000(b *testing.B) { ExpHelper(b, 3, 0x400000) }
diff --git a/third_party/gofrontend/libgo/go/math/big/rat.go b/third_party/gofrontend/libgo/go/math/big/rat.go
new file mode 100644
index 0000000..f0973b3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/rat.go
@@ -0,0 +1,600 @@
+// Copyright 2010 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.
+
+// This file implements multi-precision rational numbers.
+
+package big
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"math"
+	"strings"
+)
+
+// A Rat represents a quotient a/b of arbitrary precision.
+// The zero value for a Rat represents the value 0.
+type Rat struct {
+	// To make zero values for Rat work w/o initialization,
+	// a zero value of b (len(b) == 0) acts like b == 1.
+	// a.neg determines the sign of the Rat, b.neg is ignored.
+	a, b Int
+}
+
+// NewRat creates a new Rat with numerator a and denominator b.
+func NewRat(a, b int64) *Rat {
+	return new(Rat).SetFrac64(a, b)
+}
+
+// SetFloat64 sets z to exactly f and returns z.
+// If f is not finite, SetFloat returns nil.
+func (z *Rat) SetFloat64(f float64) *Rat {
+	const expMask = 1<<11 - 1
+	bits := math.Float64bits(f)
+	mantissa := bits & (1<<52 - 1)
+	exp := int((bits >> 52) & expMask)
+	switch exp {
+	case expMask: // non-finite
+		return nil
+	case 0: // denormal
+		exp -= 1022
+	default: // normal
+		mantissa |= 1 << 52
+		exp -= 1023
+	}
+
+	shift := 52 - exp
+
+	// Optimization (?): partially pre-normalise.
+	for mantissa&1 == 0 && shift > 0 {
+		mantissa >>= 1
+		shift--
+	}
+
+	z.a.SetUint64(mantissa)
+	z.a.neg = f < 0
+	z.b.Set(intOne)
+	if shift > 0 {
+		z.b.Lsh(&z.b, uint(shift))
+	} else {
+		z.a.Lsh(&z.a, uint(-shift))
+	}
+	return z.norm()
+}
+
+// isFinite reports whether f represents a finite rational value.
+// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
+func isFinite(f float64) bool {
+	return math.Abs(f) <= math.MaxFloat64
+}
+
+// low64 returns the least significant 64 bits of natural number z.
+func low64(z nat) uint64 {
+	if len(z) == 0 {
+		return 0
+	}
+	if _W == 32 && len(z) > 1 {
+		return uint64(z[1])<<32 | uint64(z[0])
+	}
+	return uint64(z[0])
+}
+
+// quotToFloat returns the non-negative IEEE 754 double-precision
+// value nearest to the quotient a/b, using round-to-even in halfway
+// cases.  It does not mutate its arguments.
+// Preconditions: b is non-zero; a and b have no common factors.
+func quotToFloat(a, b nat) (f float64, exact bool) {
+	// TODO(adonovan): specialize common degenerate cases: 1.0, integers.
+	alen := a.bitLen()
+	if alen == 0 {
+		return 0, true
+	}
+	blen := b.bitLen()
+	if blen == 0 {
+		panic("division by zero")
+	}
+
+	// 1. Left-shift A or B such that quotient A/B is in [1<<53, 1<<55).
+	// (54 bits if A<B when they are left-aligned, 55 bits if A>=B.)
+	// This is 2 or 3 more than the float64 mantissa field width of 52:
+	// - the optional extra bit is shifted away in step 3 below.
+	// - the high-order 1 is omitted in float64 "normal" representation;
+	// - the low-order 1 will be used during rounding then discarded.
+	exp := alen - blen
+	var a2, b2 nat
+	a2 = a2.set(a)
+	b2 = b2.set(b)
+	if shift := 54 - exp; shift > 0 {
+		a2 = a2.shl(a2, uint(shift))
+	} else if shift < 0 {
+		b2 = b2.shl(b2, uint(-shift))
+	}
+
+	// 2. Compute quotient and remainder (q, r).  NB: due to the
+	// extra shift, the low-order bit of q is logically the
+	// high-order bit of r.
+	var q nat
+	q, r := q.div(a2, a2, b2) // (recycle a2)
+	mantissa := low64(q)
+	haveRem := len(r) > 0 // mantissa&1 && !haveRem => remainder is exactly half
+
+	// 3. If quotient didn't fit in 54 bits, re-do division by b2<<1
+	// (in effect---we accomplish this incrementally).
+	if mantissa>>54 == 1 {
+		if mantissa&1 == 1 {
+			haveRem = true
+		}
+		mantissa >>= 1
+		exp++
+	}
+	if mantissa>>53 != 1 {
+		panic("expected exactly 54 bits of result")
+	}
+
+	// 4. Rounding.
+	if -1022-52 <= exp && exp <= -1022 {
+		// Denormal case; lose 'shift' bits of precision.
+		shift := uint64(-1022 - (exp - 1)) // [1..53)
+		lostbits := mantissa & (1<<shift - 1)
+		haveRem = haveRem || lostbits != 0
+		mantissa >>= shift
+		exp = -1023 + 2
+	}
+	// Round q using round-half-to-even.
+	exact = !haveRem
+	if mantissa&1 != 0 {
+		exact = false
+		if haveRem || mantissa&2 != 0 {
+			if mantissa++; mantissa >= 1<<54 {
+				// Complete rollover 11...1 => 100...0, so shift is safe
+				mantissa >>= 1
+				exp++
+			}
+		}
+	}
+	mantissa >>= 1 // discard rounding bit.  Mantissa now scaled by 2^53.
+
+	f = math.Ldexp(float64(mantissa), exp-53)
+	if math.IsInf(f, 0) {
+		exact = false
+	}
+	return
+}
+
+// Float64 returns the nearest float64 value for x and a bool indicating
+// whether f represents x exactly. If the magnitude of x is too large to
+// be represented by a float64, f is an infinity and exact is false.
+// The sign of f always matches the sign of x, even if f == 0.
+func (x *Rat) Float64() (f float64, exact bool) {
+	b := x.b.abs
+	if len(b) == 0 {
+		b = b.set(natOne) // materialize denominator
+	}
+	f, exact = quotToFloat(x.a.abs, b)
+	if x.a.neg {
+		f = -f
+	}
+	return
+}
+
+// SetFrac sets z to a/b and returns z.
+func (z *Rat) SetFrac(a, b *Int) *Rat {
+	z.a.neg = a.neg != b.neg
+	babs := b.abs
+	if len(babs) == 0 {
+		panic("division by zero")
+	}
+	if &z.a == b || alias(z.a.abs, babs) {
+		babs = nat(nil).set(babs) // make a copy
+	}
+	z.a.abs = z.a.abs.set(a.abs)
+	z.b.abs = z.b.abs.set(babs)
+	return z.norm()
+}
+
+// SetFrac64 sets z to a/b and returns z.
+func (z *Rat) SetFrac64(a, b int64) *Rat {
+	z.a.SetInt64(a)
+	if b == 0 {
+		panic("division by zero")
+	}
+	if b < 0 {
+		b = -b
+		z.a.neg = !z.a.neg
+	}
+	z.b.abs = z.b.abs.setUint64(uint64(b))
+	return z.norm()
+}
+
+// SetInt sets z to x (by making a copy of x) and returns z.
+func (z *Rat) SetInt(x *Int) *Rat {
+	z.a.Set(x)
+	z.b.abs = z.b.abs.make(0)
+	return z
+}
+
+// SetInt64 sets z to x and returns z.
+func (z *Rat) SetInt64(x int64) *Rat {
+	z.a.SetInt64(x)
+	z.b.abs = z.b.abs.make(0)
+	return z
+}
+
+// Set sets z to x (by making a copy of x) and returns z.
+func (z *Rat) Set(x *Rat) *Rat {
+	if z != x {
+		z.a.Set(&x.a)
+		z.b.Set(&x.b)
+	}
+	return z
+}
+
+// Abs sets z to |x| (the absolute value of x) and returns z.
+func (z *Rat) Abs(x *Rat) *Rat {
+	z.Set(x)
+	z.a.neg = false
+	return z
+}
+
+// Neg sets z to -x and returns z.
+func (z *Rat) Neg(x *Rat) *Rat {
+	z.Set(x)
+	z.a.neg = len(z.a.abs) > 0 && !z.a.neg // 0 has no sign
+	return z
+}
+
+// Inv sets z to 1/x and returns z.
+func (z *Rat) Inv(x *Rat) *Rat {
+	if len(x.a.abs) == 0 {
+		panic("division by zero")
+	}
+	z.Set(x)
+	a := z.b.abs
+	if len(a) == 0 {
+		a = a.set(natOne) // materialize numerator
+	}
+	b := z.a.abs
+	if b.cmp(natOne) == 0 {
+		b = b.make(0) // normalize denominator
+	}
+	z.a.abs, z.b.abs = a, b // sign doesn't change
+	return z
+}
+
+// Sign returns:
+//
+//	-1 if x <  0
+//	 0 if x == 0
+//	+1 if x >  0
+//
+func (x *Rat) Sign() int {
+	return x.a.Sign()
+}
+
+// IsInt returns true if the denominator of x is 1.
+func (x *Rat) IsInt() bool {
+	return len(x.b.abs) == 0 || x.b.abs.cmp(natOne) == 0
+}
+
+// Num returns the numerator of x; it may be <= 0.
+// The result is a reference to x's numerator; it
+// may change if a new value is assigned to x, and vice versa.
+// The sign of the numerator corresponds to the sign of x.
+func (x *Rat) Num() *Int {
+	return &x.a
+}
+
+// Denom returns the denominator of x; it is always > 0.
+// The result is a reference to x's denominator; it
+// may change if a new value is assigned to x, and vice versa.
+func (x *Rat) Denom() *Int {
+	x.b.neg = false // the result is always >= 0
+	if len(x.b.abs) == 0 {
+		x.b.abs = x.b.abs.set(natOne) // materialize denominator
+	}
+	return &x.b
+}
+
+func (z *Rat) norm() *Rat {
+	switch {
+	case len(z.a.abs) == 0:
+		// z == 0 - normalize sign and denominator
+		z.a.neg = false
+		z.b.abs = z.b.abs.make(0)
+	case len(z.b.abs) == 0:
+		// z is normalized int - nothing to do
+	case z.b.abs.cmp(natOne) == 0:
+		// z is int - normalize denominator
+		z.b.abs = z.b.abs.make(0)
+	default:
+		neg := z.a.neg
+		z.a.neg = false
+		z.b.neg = false
+		if f := NewInt(0).binaryGCD(&z.a, &z.b); f.Cmp(intOne) != 0 {
+			z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f.abs)
+			z.b.abs, _ = z.b.abs.div(nil, z.b.abs, f.abs)
+			if z.b.abs.cmp(natOne) == 0 {
+				// z is int - normalize denominator
+				z.b.abs = z.b.abs.make(0)
+			}
+		}
+		z.a.neg = neg
+	}
+	return z
+}
+
+// mulDenom sets z to the denominator product x*y (by taking into
+// account that 0 values for x or y must be interpreted as 1) and
+// returns z.
+func mulDenom(z, x, y nat) nat {
+	switch {
+	case len(x) == 0:
+		return z.set(y)
+	case len(y) == 0:
+		return z.set(x)
+	}
+	return z.mul(x, y)
+}
+
+// scaleDenom computes x*f.
+// If f == 0 (zero value of denominator), the result is (a copy of) x.
+func scaleDenom(x *Int, f nat) *Int {
+	var z Int
+	if len(f) == 0 {
+		return z.Set(x)
+	}
+	z.abs = z.abs.mul(x.abs, f)
+	z.neg = x.neg
+	return &z
+}
+
+// Cmp compares x and y and returns:
+//
+//   -1 if x <  y
+//    0 if x == y
+//   +1 if x >  y
+//
+func (x *Rat) Cmp(y *Rat) int {
+	return scaleDenom(&x.a, y.b.abs).Cmp(scaleDenom(&y.a, x.b.abs))
+}
+
+// Add sets z to the sum x+y and returns z.
+func (z *Rat) Add(x, y *Rat) *Rat {
+	a1 := scaleDenom(&x.a, y.b.abs)
+	a2 := scaleDenom(&y.a, x.b.abs)
+	z.a.Add(a1, a2)
+	z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
+	return z.norm()
+}
+
+// Sub sets z to the difference x-y and returns z.
+func (z *Rat) Sub(x, y *Rat) *Rat {
+	a1 := scaleDenom(&x.a, y.b.abs)
+	a2 := scaleDenom(&y.a, x.b.abs)
+	z.a.Sub(a1, a2)
+	z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
+	return z.norm()
+}
+
+// Mul sets z to the product x*y and returns z.
+func (z *Rat) Mul(x, y *Rat) *Rat {
+	z.a.Mul(&x.a, &y.a)
+	z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
+	return z.norm()
+}
+
+// Quo sets z to the quotient x/y and returns z.
+// If y == 0, a division-by-zero run-time panic occurs.
+func (z *Rat) Quo(x, y *Rat) *Rat {
+	if len(y.a.abs) == 0 {
+		panic("division by zero")
+	}
+	a := scaleDenom(&x.a, y.b.abs)
+	b := scaleDenom(&y.a, x.b.abs)
+	z.a.abs = a.abs
+	z.b.abs = b.abs
+	z.a.neg = a.neg != b.neg
+	return z.norm()
+}
+
+func ratTok(ch rune) bool {
+	return strings.IndexRune("+-/0123456789.eE", ch) >= 0
+}
+
+// Scan is a support routine for fmt.Scanner. It accepts the formats
+// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
+func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
+	tok, err := s.Token(true, ratTok)
+	if err != nil {
+		return err
+	}
+	if strings.IndexRune("efgEFGv", ch) < 0 {
+		return errors.New("Rat.Scan: invalid verb")
+	}
+	if _, ok := z.SetString(string(tok)); !ok {
+		return errors.New("Rat.Scan: invalid syntax")
+	}
+	return nil
+}
+
+// SetString sets z to the value of s and returns z and a boolean indicating
+// success. s can be given as a fraction "a/b" or as a floating-point number
+// optionally followed by an exponent. If the operation failed, the value of
+// z is undefined but the returned value is nil.
+func (z *Rat) SetString(s string) (*Rat, bool) {
+	if len(s) == 0 {
+		return nil, false
+	}
+
+	// check for a quotient
+	sep := strings.Index(s, "/")
+	if sep >= 0 {
+		if _, ok := z.a.SetString(s[0:sep], 10); !ok {
+			return nil, false
+		}
+		s = s[sep+1:]
+		var err error
+		if z.b.abs, _, err = z.b.abs.scan(strings.NewReader(s), 10); err != nil {
+			return nil, false
+		}
+		return z.norm(), true
+	}
+
+	// check for a decimal point
+	sep = strings.Index(s, ".")
+	// check for an exponent
+	e := strings.IndexAny(s, "eE")
+	var exp Int
+	if e >= 0 {
+		if e < sep {
+			// The E must come after the decimal point.
+			return nil, false
+		}
+		if _, ok := exp.SetString(s[e+1:], 10); !ok {
+			return nil, false
+		}
+		s = s[0:e]
+	}
+	if sep >= 0 {
+		s = s[0:sep] + s[sep+1:]
+		exp.Sub(&exp, NewInt(int64(len(s)-sep)))
+	}
+
+	if _, ok := z.a.SetString(s, 10); !ok {
+		return nil, false
+	}
+	powTen := nat(nil).expNN(natTen, exp.abs, nil)
+	if exp.neg {
+		z.b.abs = powTen
+		z.norm()
+	} else {
+		z.a.abs = z.a.abs.mul(z.a.abs, powTen)
+		z.b.abs = z.b.abs.make(0)
+	}
+
+	return z, true
+}
+
+// String returns a string representation of x in the form "a/b" (even if b == 1).
+func (x *Rat) String() string {
+	s := "/1"
+	if len(x.b.abs) != 0 {
+		s = "/" + x.b.abs.decimalString()
+	}
+	return x.a.String() + s
+}
+
+// RatString returns a string representation of x in the form "a/b" if b != 1,
+// and in the form "a" if b == 1.
+func (x *Rat) RatString() string {
+	if x.IsInt() {
+		return x.a.String()
+	}
+	return x.String()
+}
+
+// FloatString returns a string representation of x in decimal form with prec
+// digits of precision after the decimal point and the last digit rounded.
+func (x *Rat) FloatString(prec int) string {
+	if x.IsInt() {
+		s := x.a.String()
+		if prec > 0 {
+			s += "." + strings.Repeat("0", prec)
+		}
+		return s
+	}
+	// x.b.abs != 0
+
+	q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
+
+	p := natOne
+	if prec > 0 {
+		p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
+	}
+
+	r = r.mul(r, p)
+	r, r2 := r.div(nat(nil), r, x.b.abs)
+
+	// see if we need to round up
+	r2 = r2.add(r2, r2)
+	if x.b.abs.cmp(r2) <= 0 {
+		r = r.add(r, natOne)
+		if r.cmp(p) >= 0 {
+			q = nat(nil).add(q, natOne)
+			r = nat(nil).sub(r, p)
+		}
+	}
+
+	s := q.decimalString()
+	if x.a.neg {
+		s = "-" + s
+	}
+
+	if prec > 0 {
+		rs := r.decimalString()
+		leadingZeros := prec - len(rs)
+		s += "." + strings.Repeat("0", leadingZeros) + rs
+	}
+
+	return s
+}
+
+// Gob codec version. Permits backward-compatible changes to the encoding.
+const ratGobVersion byte = 1
+
+// GobEncode implements the gob.GobEncoder interface.
+func (x *Rat) GobEncode() ([]byte, error) {
+	if x == nil {
+		return nil, nil
+	}
+	buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
+	i := x.b.abs.bytes(buf)
+	j := x.a.abs.bytes(buf[0:i])
+	n := i - j
+	if int(uint32(n)) != n {
+		// this should never happen
+		return nil, errors.New("Rat.GobEncode: numerator too large")
+	}
+	binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
+	j -= 1 + 4
+	b := ratGobVersion << 1 // make space for sign bit
+	if x.a.neg {
+		b |= 1
+	}
+	buf[j] = b
+	return buf[j:], nil
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (z *Rat) GobDecode(buf []byte) error {
+	if len(buf) == 0 {
+		// Other side sent a nil or default value.
+		*z = Rat{}
+		return nil
+	}
+	b := buf[0]
+	if b>>1 != ratGobVersion {
+		return errors.New(fmt.Sprintf("Rat.GobDecode: encoding version %d not supported", b>>1))
+	}
+	const j = 1 + 4
+	i := j + binary.BigEndian.Uint32(buf[j-4:j])
+	z.a.neg = b&1 != 0
+	z.a.abs = z.a.abs.setBytes(buf[j:i])
+	z.b.abs = z.b.abs.setBytes(buf[i:])
+	return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface
+func (r *Rat) MarshalText() (text []byte, err error) {
+	return []byte(r.RatString()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface
+func (r *Rat) UnmarshalText(text []byte) error {
+	if _, ok := r.SetString(string(text)); !ok {
+		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text)
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/math/big/rat_test.go b/third_party/gofrontend/libgo/go/math/big/rat_test.go
new file mode 100644
index 0000000..414a67d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/big/rat_test.go
@@ -0,0 +1,994 @@
+// Copyright 2010 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 big
+
+import (
+	"bytes"
+	"encoding/gob"
+	"encoding/json"
+	"encoding/xml"
+	"fmt"
+	"math"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func TestZeroRat(t *testing.T) {
+	var x, y, z Rat
+	y.SetFrac64(0, 42)
+
+	if x.Cmp(&y) != 0 {
+		t.Errorf("x and y should be both equal and zero")
+	}
+
+	if s := x.String(); s != "0/1" {
+		t.Errorf("got x = %s, want 0/1", s)
+	}
+
+	if s := x.RatString(); s != "0" {
+		t.Errorf("got x = %s, want 0", s)
+	}
+
+	z.Add(&x, &y)
+	if s := z.RatString(); s != "0" {
+		t.Errorf("got x+y = %s, want 0", s)
+	}
+
+	z.Sub(&x, &y)
+	if s := z.RatString(); s != "0" {
+		t.Errorf("got x-y = %s, want 0", s)
+	}
+
+	z.Mul(&x, &y)
+	if s := z.RatString(); s != "0" {
+		t.Errorf("got x*y = %s, want 0", s)
+	}
+
+	// check for division by zero
+	defer func() {
+		if s := recover(); s == nil || s.(string) != "division by zero" {
+			panic(s)
+		}
+	}()
+	z.Quo(&x, &y)
+}
+
+var setStringTests = []struct {
+	in, out string
+	ok      bool
+}{
+	{"0", "0", true},
+	{"-0", "0", true},
+	{"1", "1", true},
+	{"-1", "-1", true},
+	{"1.", "1", true},
+	{"1e0", "1", true},
+	{"1.e1", "10", true},
+	{in: "1e", ok: false},
+	{in: "1.e", ok: false},
+	{in: "1e+14e-5", ok: false},
+	{in: "1e4.5", ok: false},
+	{in: "r", ok: false},
+	{in: "a/b", ok: false},
+	{in: "a.b", ok: false},
+	{"-0.1", "-1/10", true},
+	{"-.1", "-1/10", true},
+	{"2/4", "1/2", true},
+	{".25", "1/4", true},
+	{"-1/5", "-1/5", true},
+	{"8129567.7690E14", "812956776900000000000", true},
+	{"78189e+4", "781890000", true},
+	{"553019.8935e+8", "55301989350000", true},
+	{"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
+	{"9877861857500000E-7", "3951144743/4", true},
+	{"2169378.417e-3", "2169378417/1000000", true},
+	{"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
+	{"53/70893980658822810696", "53/70893980658822810696", true},
+	{"106/141787961317645621392", "53/70893980658822810696", true},
+	{"204211327800791583.81095", "4084226556015831676219/20000", true},
+}
+
+func TestRatSetString(t *testing.T) {
+	for i, test := range setStringTests {
+		x, ok := new(Rat).SetString(test.in)
+
+		if ok {
+			if !test.ok {
+				t.Errorf("#%d SetString(%q) expected failure", i, test.in)
+			} else if x.RatString() != test.out {
+				t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
+			}
+		} else if x != nil {
+			t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
+		}
+	}
+}
+
+func TestRatScan(t *testing.T) {
+	var buf bytes.Buffer
+	for i, test := range setStringTests {
+		x := new(Rat)
+		buf.Reset()
+		buf.WriteString(test.in)
+
+		_, err := fmt.Fscanf(&buf, "%v", x)
+		if err == nil != test.ok {
+			if test.ok {
+				t.Errorf("#%d error: %s", i, err)
+			} else {
+				t.Errorf("#%d expected error", i)
+			}
+			continue
+		}
+		if err == nil && x.RatString() != test.out {
+			t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
+		}
+	}
+}
+
+var floatStringTests = []struct {
+	in   string
+	prec int
+	out  string
+}{
+	{"0", 0, "0"},
+	{"0", 4, "0.0000"},
+	{"1", 0, "1"},
+	{"1", 2, "1.00"},
+	{"-1", 0, "-1"},
+	{".25", 2, "0.25"},
+	{".25", 1, "0.3"},
+	{".25", 3, "0.250"},
+	{"-1/3", 3, "-0.333"},
+	{"-2/3", 4, "-0.6667"},
+	{"0.96", 1, "1.0"},
+	{"0.999", 2, "1.00"},
+	{"0.9", 0, "1"},
+	{".25", -1, "0"},
+	{".55", -1, "1"},
+}
+
+func TestFloatString(t *testing.T) {
+	for i, test := range floatStringTests {
+		x, _ := new(Rat).SetString(test.in)
+
+		if x.FloatString(test.prec) != test.out {
+			t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
+		}
+	}
+}
+
+func TestRatSign(t *testing.T) {
+	zero := NewRat(0, 1)
+	for _, a := range setStringTests {
+		x, ok := new(Rat).SetString(a.in)
+		if !ok {
+			continue
+		}
+		s := x.Sign()
+		e := x.Cmp(zero)
+		if s != e {
+			t.Errorf("got %d; want %d for z = %v", s, e, &x)
+		}
+	}
+}
+
+var ratCmpTests = []struct {
+	rat1, rat2 string
+	out        int
+}{
+	{"0", "0/1", 0},
+	{"1/1", "1", 0},
+	{"-1", "-2/2", 0},
+	{"1", "0", 1},
+	{"0/1", "1/1", -1},
+	{"-5/1434770811533343057144", "-5/1434770811533343057145", -1},
+	{"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1},
+	{"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1},
+	{"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0},
+}
+
+func TestRatCmp(t *testing.T) {
+	for i, test := range ratCmpTests {
+		x, _ := new(Rat).SetString(test.rat1)
+		y, _ := new(Rat).SetString(test.rat2)
+
+		out := x.Cmp(y)
+		if out != test.out {
+			t.Errorf("#%d got out = %v; want %v", i, out, test.out)
+		}
+	}
+}
+
+func TestIsInt(t *testing.T) {
+	one := NewInt(1)
+	for _, a := range setStringTests {
+		x, ok := new(Rat).SetString(a.in)
+		if !ok {
+			continue
+		}
+		i := x.IsInt()
+		e := x.Denom().Cmp(one) == 0
+		if i != e {
+			t.Errorf("got IsInt(%v) == %v; want %v", x, i, e)
+		}
+	}
+}
+
+func TestRatAbs(t *testing.T) {
+	zero := new(Rat)
+	for _, a := range setStringTests {
+		x, ok := new(Rat).SetString(a.in)
+		if !ok {
+			continue
+		}
+		e := new(Rat).Set(x)
+		if e.Cmp(zero) < 0 {
+			e.Sub(zero, e)
+		}
+		z := new(Rat).Abs(x)
+		if z.Cmp(e) != 0 {
+			t.Errorf("got Abs(%v) = %v; want %v", x, z, e)
+		}
+	}
+}
+
+func TestRatNeg(t *testing.T) {
+	zero := new(Rat)
+	for _, a := range setStringTests {
+		x, ok := new(Rat).SetString(a.in)
+		if !ok {
+			continue
+		}
+		e := new(Rat).Sub(zero, x)
+		z := new(Rat).Neg(x)
+		if z.Cmp(e) != 0 {
+			t.Errorf("got Neg(%v) = %v; want %v", x, z, e)
+		}
+	}
+}
+
+func TestRatInv(t *testing.T) {
+	zero := new(Rat)
+	for _, a := range setStringTests {
+		x, ok := new(Rat).SetString(a.in)
+		if !ok {
+			continue
+		}
+		if x.Cmp(zero) == 0 {
+			continue // avoid division by zero
+		}
+		e := new(Rat).SetFrac(x.Denom(), x.Num())
+		z := new(Rat).Inv(x)
+		if z.Cmp(e) != 0 {
+			t.Errorf("got Inv(%v) = %v; want %v", x, z, e)
+		}
+	}
+}
+
+type ratBinFun func(z, x, y *Rat) *Rat
+type ratBinArg struct {
+	x, y, z string
+}
+
+func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) {
+	x, _ := new(Rat).SetString(a.x)
+	y, _ := new(Rat).SetString(a.y)
+	z, _ := new(Rat).SetString(a.z)
+	out := f(new(Rat), x, y)
+
+	if out.Cmp(z) != 0 {
+		t.Errorf("%s #%d got %s want %s", name, i, out, z)
+	}
+}
+
+var ratBinTests = []struct {
+	x, y      string
+	sum, prod string
+}{
+	{"0", "0", "0", "0"},
+	{"0", "1", "1", "0"},
+	{"-1", "0", "-1", "0"},
+	{"-1", "1", "0", "-1"},
+	{"1", "1", "2", "1"},
+	{"1/2", "1/2", "1", "1/4"},
+	{"1/4", "1/3", "7/12", "1/12"},
+	{"2/5", "-14/3", "-64/15", "-28/15"},
+	{"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"},
+	{"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"},
+	{"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"},
+	{"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"},
+	{"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"},
+	{"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"},
+	{"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"},
+	{"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"},
+	{"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"},
+	{"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"},
+}
+
+func TestRatBin(t *testing.T) {
+	for i, test := range ratBinTests {
+		arg := ratBinArg{test.x, test.y, test.sum}
+		testRatBin(t, i, "Add", (*Rat).Add, arg)
+
+		arg = ratBinArg{test.y, test.x, test.sum}
+		testRatBin(t, i, "Add symmetric", (*Rat).Add, arg)
+
+		arg = ratBinArg{test.sum, test.x, test.y}
+		testRatBin(t, i, "Sub", (*Rat).Sub, arg)
+
+		arg = ratBinArg{test.sum, test.y, test.x}
+		testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg)
+
+		arg = ratBinArg{test.x, test.y, test.prod}
+		testRatBin(t, i, "Mul", (*Rat).Mul, arg)
+
+		arg = ratBinArg{test.y, test.x, test.prod}
+		testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg)
+
+		if test.x != "0" {
+			arg = ratBinArg{test.prod, test.x, test.y}
+			testRatBin(t, i, "Quo", (*Rat).Quo, arg)
+		}
+
+		if test.y != "0" {
+			arg = ratBinArg{test.prod, test.y, test.x}
+			testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg)
+		}
+	}
+}
+
+func TestIssue820(t *testing.T) {
+	x := NewRat(3, 1)
+	y := NewRat(2, 1)
+	z := y.Quo(x, y)
+	q := NewRat(3, 2)
+	if z.Cmp(q) != 0 {
+		t.Errorf("got %s want %s", z, q)
+	}
+
+	y = NewRat(3, 1)
+	x = NewRat(2, 1)
+	z = y.Quo(x, y)
+	q = NewRat(2, 3)
+	if z.Cmp(q) != 0 {
+		t.Errorf("got %s want %s", z, q)
+	}
+
+	x = NewRat(3, 1)
+	z = x.Quo(x, x)
+	q = NewRat(3, 3)
+	if z.Cmp(q) != 0 {
+		t.Errorf("got %s want %s", z, q)
+	}
+}
+
+var setFrac64Tests = []struct {
+	a, b int64
+	out  string
+}{
+	{0, 1, "0"},
+	{0, -1, "0"},
+	{1, 1, "1"},
+	{-1, 1, "-1"},
+	{1, -1, "-1"},
+	{-1, -1, "1"},
+	{-9223372036854775808, -9223372036854775808, "1"},
+}
+
+func TestRatSetFrac64Rat(t *testing.T) {
+	for i, test := range setFrac64Tests {
+		x := new(Rat).SetFrac64(test.a, test.b)
+		if x.RatString() != test.out {
+			t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
+		}
+	}
+}
+
+func TestRatGobEncoding(t *testing.T) {
+	var medium bytes.Buffer
+	enc := gob.NewEncoder(&medium)
+	dec := gob.NewDecoder(&medium)
+	for _, test := range encodingTests {
+		medium.Reset() // empty buffer for each test case (in case of failures)
+		var tx Rat
+		tx.SetString(test + ".14159265")
+		if err := enc.Encode(&tx); err != nil {
+			t.Errorf("encoding of %s failed: %s", &tx, err)
+		}
+		var rx Rat
+		if err := dec.Decode(&rx); err != nil {
+			t.Errorf("decoding of %s failed: %s", &tx, err)
+		}
+		if rx.Cmp(&tx) != 0 {
+			t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
+		}
+	}
+}
+
+// Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero.
+// TODO: top-level nils.
+func TestGobEncodingNilRatInSlice(t *testing.T) {
+	buf := new(bytes.Buffer)
+	enc := gob.NewEncoder(buf)
+	dec := gob.NewDecoder(buf)
+
+	var in = make([]*Rat, 1)
+	err := enc.Encode(&in)
+	if err != nil {
+		t.Errorf("gob encode failed: %q", err)
+	}
+	var out []*Rat
+	err = dec.Decode(&out)
+	if err != nil {
+		t.Fatalf("gob decode failed: %q", err)
+	}
+	if len(out) != 1 {
+		t.Fatalf("wrong len; want 1 got %d", len(out))
+	}
+	var zero Rat
+	if out[0].Cmp(&zero) != 0 {
+		t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
+	}
+}
+
+var ratNums = []string{
+	"-141592653589793238462643383279502884197169399375105820974944592307816406286",
+	"-1415926535897932384626433832795028841971",
+	"-141592653589793",
+	"-1",
+	"0",
+	"1",
+	"141592653589793",
+	"1415926535897932384626433832795028841971",
+	"141592653589793238462643383279502884197169399375105820974944592307816406286",
+}
+
+var ratDenoms = []string{
+	"1",
+	"718281828459045",
+	"7182818284590452353602874713526624977572",
+	"718281828459045235360287471352662497757247093699959574966967627724076630353",
+}
+
+func TestRatJSONEncoding(t *testing.T) {
+	for _, num := range ratNums {
+		for _, denom := range ratDenoms {
+			var tx Rat
+			tx.SetString(num + "/" + denom)
+			b, err := json.Marshal(&tx)
+			if err != nil {
+				t.Errorf("marshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			var rx Rat
+			if err := json.Unmarshal(b, &rx); err != nil {
+				t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			if rx.Cmp(&tx) != 0 {
+				t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+			}
+		}
+	}
+}
+
+func TestRatXMLEncoding(t *testing.T) {
+	for _, num := range ratNums {
+		for _, denom := range ratDenoms {
+			var tx Rat
+			tx.SetString(num + "/" + denom)
+			b, err := xml.Marshal(&tx)
+			if err != nil {
+				t.Errorf("marshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			var rx Rat
+			if err := xml.Unmarshal(b, &rx); err != nil {
+				t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			if rx.Cmp(&tx) != 0 {
+				t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+			}
+		}
+	}
+}
+
+func TestIssue2379(t *testing.T) {
+	// 1) no aliasing
+	q := NewRat(3, 2)
+	x := new(Rat)
+	x.SetFrac(NewInt(3), NewInt(2))
+	if x.Cmp(q) != 0 {
+		t.Errorf("1) got %s want %s", x, q)
+	}
+
+	// 2) aliasing of numerator
+	x = NewRat(2, 3)
+	x.SetFrac(NewInt(3), x.Num())
+	if x.Cmp(q) != 0 {
+		t.Errorf("2) got %s want %s", x, q)
+	}
+
+	// 3) aliasing of denominator
+	x = NewRat(2, 3)
+	x.SetFrac(x.Denom(), NewInt(2))
+	if x.Cmp(q) != 0 {
+		t.Errorf("3) got %s want %s", x, q)
+	}
+
+	// 4) aliasing of numerator and denominator
+	x = NewRat(2, 3)
+	x.SetFrac(x.Denom(), x.Num())
+	if x.Cmp(q) != 0 {
+		t.Errorf("4) got %s want %s", x, q)
+	}
+
+	// 5) numerator and denominator are the same
+	q = NewRat(1, 1)
+	x = new(Rat)
+	n := NewInt(7)
+	x.SetFrac(n, n)
+	if x.Cmp(q) != 0 {
+		t.Errorf("5) got %s want %s", x, q)
+	}
+}
+
+func TestIssue3521(t *testing.T) {
+	a := new(Int)
+	b := new(Int)
+	a.SetString("64375784358435883458348587", 0)
+	b.SetString("4789759874531", 0)
+
+	// 0) a raw zero value has 1 as denominator
+	zero := new(Rat)
+	one := NewInt(1)
+	if zero.Denom().Cmp(one) != 0 {
+		t.Errorf("0) got %s want %s", zero.Denom(), one)
+	}
+
+	// 1a) a zero value remains zero independent of denominator
+	x := new(Rat)
+	x.Denom().Set(new(Int).Neg(b))
+	if x.Cmp(zero) != 0 {
+		t.Errorf("1a) got %s want %s", x, zero)
+	}
+
+	// 1b) a zero value may have a denominator != 0 and != 1
+	x.Num().Set(a)
+	qab := new(Rat).SetFrac(a, b)
+	if x.Cmp(qab) != 0 {
+		t.Errorf("1b) got %s want %s", x, qab)
+	}
+
+	// 2a) an integral value becomes a fraction depending on denominator
+	x.SetFrac64(10, 2)
+	x.Denom().SetInt64(3)
+	q53 := NewRat(5, 3)
+	if x.Cmp(q53) != 0 {
+		t.Errorf("2a) got %s want %s", x, q53)
+	}
+
+	// 2b) an integral value becomes a fraction depending on denominator
+	x = NewRat(10, 2)
+	x.Denom().SetInt64(3)
+	if x.Cmp(q53) != 0 {
+		t.Errorf("2b) got %s want %s", x, q53)
+	}
+
+	// 3) changing the numerator/denominator of a Rat changes the Rat
+	x.SetFrac(a, b)
+	a = x.Num()
+	b = x.Denom()
+	a.SetInt64(5)
+	b.SetInt64(3)
+	if x.Cmp(q53) != 0 {
+		t.Errorf("3) got %s want %s", x, q53)
+	}
+}
+
+// Test inputs to Rat.SetString.  The prefix "long:" causes the test
+// to be skipped in --test.short mode.  (The threshold is about 500us.)
+var float64inputs = []string{
+	// Constants plundered from strconv/testfp.txt.
+
+	// Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
+	"5e+125",
+	"69e+267",
+	"999e-026",
+	"7861e-034",
+	"75569e-254",
+	"928609e-261",
+	"9210917e+080",
+	"84863171e+114",
+	"653777767e+273",
+	"5232604057e-298",
+	"27235667517e-109",
+	"653532977297e-123",
+	"3142213164987e-294",
+	"46202199371337e-072",
+	"231010996856685e-073",
+	"9324754620109615e+212",
+	"78459735791271921e+049",
+	"272104041512242479e+200",
+	"6802601037806061975e+198",
+	"20505426358836677347e-221",
+	"836168422905420598437e-234",
+	"4891559871276714924261e+222",
+
+	// Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
+	"9e-265",
+	"85e-037",
+	"623e+100",
+	"3571e+263",
+	"81661e+153",
+	"920657e-023",
+	"4603285e-024",
+	"87575437e-309",
+	"245540327e+122",
+	"6138508175e+120",
+	"83356057653e+193",
+	"619534293513e+124",
+	"2335141086879e+218",
+	"36167929443327e-159",
+	"609610927149051e-255",
+	"3743626360493413e-165",
+	"94080055902682397e-242",
+	"899810892172646163e+283",
+	"7120190517612959703e+120",
+	"25188282901709339043e-252",
+	"308984926168550152811e-052",
+	"6372891218502368041059e+064",
+
+	// Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
+	"5e-20",
+	"67e+14",
+	"985e+15",
+	"7693e-42",
+	"55895e-16",
+	"996622e-44",
+	"7038531e-32",
+	"60419369e-46",
+	"702990899e-20",
+	"6930161142e-48",
+	"25933168707e+13",
+	"596428896559e+20",
+
+	// Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
+	"3e-23",
+	"57e+18",
+	"789e-35",
+	"2539e-18",
+	"76173e+28",
+	"887745e-11",
+	"5382571e-37",
+	"82381273e-35",
+	"750486563e-38",
+	"3752432815e-39",
+	"75224575729e-45",
+	"459926601011e+15",
+
+	// Constants plundered from strconv/atof_test.go.
+
+	"0",
+	"1",
+	"+1",
+	"1e23",
+	"1E23",
+	"100000000000000000000000",
+	"1e-100",
+	"123456700",
+	"99999999999999974834176",
+	"100000000000000000000001",
+	"100000000000000008388608",
+	"100000000000000016777215",
+	"100000000000000016777216",
+	"-1",
+	"-0.1",
+	"-0", // NB: exception made for this input
+	"1e-20",
+	"625e-3",
+
+	// largest float64
+	"1.7976931348623157e308",
+	"-1.7976931348623157e308",
+	// next float64 - too large
+	"1.7976931348623159e308",
+	"-1.7976931348623159e308",
+	// the border is ...158079
+	// borderline - okay
+	"1.7976931348623158e308",
+	"-1.7976931348623158e308",
+	// borderline - too large
+	"1.797693134862315808e308",
+	"-1.797693134862315808e308",
+
+	// a little too large
+	"1e308",
+	"2e308",
+	"1e309",
+
+	// way too large
+	"1e310",
+	"-1e310",
+	"1e400",
+	"-1e400",
+	"long:1e400000",
+	"long:-1e400000",
+
+	// denormalized
+	"1e-305",
+	"1e-306",
+	"1e-307",
+	"1e-308",
+	"1e-309",
+	"1e-310",
+	"1e-322",
+	// smallest denormal
+	"5e-324",
+	"4e-324",
+	"3e-324",
+	// too small
+	"2e-324",
+	// way too small
+	"1e-350",
+	"long:1e-400000",
+	// way too small, negative
+	"-1e-350",
+	"long:-1e-400000",
+
+	// try to overflow exponent
+	// [Disabled: too slow and memory-hungry with rationals.]
+	// "1e-4294967296",
+	// "1e+4294967296",
+	// "1e-18446744073709551616",
+	// "1e+18446744073709551616",
+
+	// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
+	"2.2250738585072012e-308",
+	// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
+
+	"2.2250738585072011e-308",
+
+	// A very large number (initially wrongly parsed by the fast algorithm).
+	"4.630813248087435e+307",
+
+	// A different kind of very large number.
+	"22.222222222222222",
+	"long:2." + strings.Repeat("2", 4000) + "e+1",
+
+	// Exactly halfway between 1 and math.Nextafter(1, 2).
+	// Round to even (down).
+	"1.00000000000000011102230246251565404236316680908203125",
+	// Slightly lower; still round down.
+	"1.00000000000000011102230246251565404236316680908203124",
+	// Slightly higher; round up.
+	"1.00000000000000011102230246251565404236316680908203126",
+	// Slightly higher, but you have to read all the way to the end.
+	"long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
+
+	// Smallest denormal, 2^(-1022-52)
+	"4.940656458412465441765687928682213723651e-324",
+	// Half of smallest denormal, 2^(-1022-53)
+	"2.470328229206232720882843964341106861825e-324",
+	// A little more than the exact half of smallest denormal
+	// 2^-1075 + 2^-1100.  (Rounds to 1p-1074.)
+	"2.470328302827751011111470718709768633275e-324",
+	// The exact halfway between smallest normal and largest denormal:
+	// 2^-1022 - 2^-1075.  (Rounds to 2^-1022.)
+	"2.225073858507201136057409796709131975935e-308",
+
+	"1152921504606846975",  //   1<<60 - 1
+	"-1152921504606846975", // -(1<<60 - 1)
+	"1152921504606846977",  //   1<<60 + 1
+	"-1152921504606846977", // -(1<<60 + 1)
+
+	"1/3",
+}
+
+func TestFloat64SpecialCases(t *testing.T) {
+	for _, input := range float64inputs {
+		if strings.HasPrefix(input, "long:") {
+			if testing.Short() {
+				continue
+			}
+			input = input[len("long:"):]
+		}
+
+		r, ok := new(Rat).SetString(input)
+		if !ok {
+			t.Errorf("Rat.SetString(%q) failed", input)
+			continue
+		}
+		f, exact := r.Float64()
+
+		// 1. Check string -> Rat -> float64 conversions are
+		// consistent with strconv.ParseFloat.
+		// Skip this check if the input uses "a/b" rational syntax.
+		if !strings.Contains(input, "/") {
+			e, _ := strconv.ParseFloat(input, 64)
+
+			// Careful: negative Rats too small for
+			// float64 become -0, but Rat obviously cannot
+			// preserve the sign from SetString("-0").
+			switch {
+			case math.Float64bits(e) == math.Float64bits(f):
+				// Ok: bitwise equal.
+			case f == 0 && r.Num().BitLen() == 0:
+				// Ok: Rat(0) is equivalent to both +/- float64(0).
+			default:
+				t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
+			}
+		}
+
+		if !isFinite(f) {
+			continue
+		}
+
+		// 2. Check f is best approximation to r.
+		if !checkIsBestApprox(t, f, r) {
+			// Append context information.
+			t.Errorf("(input was %q)", input)
+		}
+
+		// 3. Check f->R->f roundtrip is non-lossy.
+		checkNonLossyRoundtrip(t, f)
+
+		// 4. Check exactness using slow algorithm.
+		if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
+			t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
+		}
+	}
+}
+
+func TestFloat64Distribution(t *testing.T) {
+	// Generate a distribution of (sign, mantissa, exp) values
+	// broader than the float64 range, and check Rat.Float64()
+	// always picks the closest float64 approximation.
+	var add = []int64{
+		0,
+		1,
+		3,
+		5,
+		7,
+		9,
+		11,
+	}
+	var winc, einc = uint64(1), int(1) // soak test (~75s on x86-64)
+	if testing.Short() {
+		winc, einc = 10, 500 // quick test (~12ms on x86-64)
+	}
+
+	for _, sign := range "+-" {
+		for _, a := range add {
+			for wid := uint64(0); wid < 60; wid += winc {
+				b := int64(1<<wid + a)
+				if sign == '-' {
+					b = -b
+				}
+				for exp := -1100; exp < 1100; exp += einc {
+					num, den := NewInt(b), NewInt(1)
+					if exp > 0 {
+						num.Lsh(num, uint(exp))
+					} else {
+						den.Lsh(den, uint(-exp))
+					}
+					r := new(Rat).SetFrac(num, den)
+					f, _ := r.Float64()
+
+					if !checkIsBestApprox(t, f, r) {
+						// Append context information.
+						t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)",
+							b, exp, f, f, math.Ldexp(float64(b), exp), r)
+					}
+
+					checkNonLossyRoundtrip(t, f)
+				}
+			}
+		}
+	}
+}
+
+// TestFloat64NonFinite checks that SetFloat64 of a non-finite value
+// returns nil.
+func TestSetFloat64NonFinite(t *testing.T) {
+	for _, f := range []float64{math.NaN(), math.Inf(+1), math.Inf(-1)} {
+		var r Rat
+		if r2 := r.SetFloat64(f); r2 != nil {
+			t.Errorf("SetFloat64(%g) was %v, want nil", f, r2)
+		}
+	}
+}
+
+// checkNonLossyRoundtrip checks that a float->Rat->float roundtrip is
+// non-lossy for finite f.
+func checkNonLossyRoundtrip(t *testing.T, f float64) {
+	if !isFinite(f) {
+		return
+	}
+	r := new(Rat).SetFloat64(f)
+	if r == nil {
+		t.Errorf("Rat.SetFloat64(%g (%b)) == nil", f, f)
+		return
+	}
+	f2, exact := r.Float64()
+	if f != f2 || !exact {
+		t.Errorf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta = %b",
+			f, f2, f2, exact, f, f, true, f2-f)
+	}
+}
+
+// delta returns the absolute difference between r and f.
+func delta(r *Rat, f float64) *Rat {
+	d := new(Rat).Sub(r, new(Rat).SetFloat64(f))
+	return d.Abs(d)
+}
+
+// checkIsBestApprox checks that f is the best possible float64
+// approximation of r.
+// Returns true on success.
+func checkIsBestApprox(t *testing.T, f float64, r *Rat) bool {
+	if math.Abs(f) >= math.MaxFloat64 {
+		// Cannot check +Inf, -Inf, nor the float next to them (MaxFloat64).
+		// But we have tests for these special cases.
+		return true
+	}
+
+	// r must be strictly between f0 and f1, the floats bracketing f.
+	f0 := math.Nextafter(f, math.Inf(-1))
+	f1 := math.Nextafter(f, math.Inf(+1))
+
+	// For f to be correct, r must be closer to f than to f0 or f1.
+	df := delta(r, f)
+	df0 := delta(r, f0)
+	df1 := delta(r, f1)
+	if df.Cmp(df0) > 0 {
+		t.Errorf("Rat(%v).Float64() = %g (%b), but previous float64 %g (%b) is closer", r, f, f, f0, f0)
+		return false
+	}
+	if df.Cmp(df1) > 0 {
+		t.Errorf("Rat(%v).Float64() = %g (%b), but next float64 %g (%b) is closer", r, f, f, f1, f1)
+		return false
+	}
+	if df.Cmp(df0) == 0 && !isEven(f) {
+		t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0)
+		return false
+	}
+	if df.Cmp(df1) == 0 && !isEven(f) {
+		t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1)
+		return false
+	}
+	return true
+}
+
+func isEven(f float64) bool { return math.Float64bits(f)&1 == 0 }
+
+func TestIsFinite(t *testing.T) {
+	finites := []float64{
+		1.0 / 3,
+		4891559871276714924261e+222,
+		math.MaxFloat64,
+		math.SmallestNonzeroFloat64,
+		-math.MaxFloat64,
+		-math.SmallestNonzeroFloat64,
+	}
+	for _, f := range finites {
+		if !isFinite(f) {
+			t.Errorf("!IsFinite(%g (%b))", f, f)
+		}
+	}
+	nonfinites := []float64{
+		math.NaN(),
+		math.Inf(-1),
+		math.Inf(+1),
+	}
+	for _, f := range nonfinites {
+		if isFinite(f) {
+			t.Errorf("IsFinite(%g, (%b))", f, f)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/math/bits.go b/third_party/gofrontend/libgo/go/math/bits.go
new file mode 100644
index 0000000..d85ee9c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/bits.go
@@ -0,0 +1,59 @@
+// 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 math
+
+const (
+	uvnan    = 0x7FF8000000000001
+	uvinf    = 0x7FF0000000000000
+	uvneginf = 0xFFF0000000000000
+	mask     = 0x7FF
+	shift    = 64 - 11 - 1
+	bias     = 1023
+)
+
+// Inf returns positive infinity if sign >= 0, negative infinity if sign < 0.
+func Inf(sign int) float64 {
+	var v uint64
+	if sign >= 0 {
+		v = uvinf
+	} else {
+		v = uvneginf
+	}
+	return Float64frombits(v)
+}
+
+// NaN returns an IEEE 754 ``not-a-number'' value.
+func NaN() float64 { return Float64frombits(uvnan) }
+
+// IsNaN reports whether f is an IEEE 754 ``not-a-number'' value.
+func IsNaN(f float64) (is bool) {
+	// IEEE 754 says that only NaNs satisfy f != f.
+	// To avoid the floating-point hardware, could use:
+	//	x := Float64bits(f);
+	//	return uint32(x>>shift)&mask == mask && x != uvinf && x != uvneginf
+	return f != f
+}
+
+// IsInf reports whether f is an infinity, according to sign.
+// If sign > 0, IsInf reports whether f is positive infinity.
+// If sign < 0, IsInf reports whether f is negative infinity.
+// If sign == 0, IsInf reports whether f is either infinity.
+func IsInf(f float64, sign int) bool {
+	// Test for infinity by comparing against maximum float.
+	// To avoid the floating-point hardware, could use:
+	//	x := Float64bits(f);
+	//	return sign >= 0 && x == uvinf || sign <= 0 && x == uvneginf;
+	return sign >= 0 && f > MaxFloat64 || sign <= 0 && f < -MaxFloat64
+}
+
+// normalize returns a normal number y and exponent exp
+// satisfying x == y × 2**exp. It assumes x is finite and non-zero.
+func normalize(x float64) (y float64, exp int) {
+	const SmallestNormal = 2.2250738585072014e-308 // 2**-1022
+	if Abs(x) < SmallestNormal {
+		return x * (1 << 52), -52
+	}
+	return x, 0
+}
diff --git a/third_party/gofrontend/libgo/go/math/cbrt.go b/third_party/gofrontend/libgo/go/math/cbrt.go
new file mode 100644
index 0000000..272e309
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cbrt.go
@@ -0,0 +1,76 @@
+// 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 math
+
+/*
+	The algorithm is based in part on "Optimal Partitioning of
+	Newton's Method for Calculating Roots", by Gunter Meinardus
+	and G. D. Taylor, Mathematics of Computation © 1980 American
+	Mathematical Society.
+	(http://www.jstor.org/stable/2006387?seq=9, accessed 11-Feb-2010)
+*/
+
+// Cbrt returns the cube root of x.
+//
+// Special cases are:
+//	Cbrt(±0) = ±0
+//	Cbrt(±Inf) = ±Inf
+//	Cbrt(NaN) = NaN
+func Cbrt(x float64) float64 {
+	const (
+		A1 = 1.662848358e-01
+		A2 = 1.096040958e+00
+		A3 = 4.105032829e-01
+		A4 = 5.649335816e-01
+		B1 = 2.639607233e-01
+		B2 = 8.699282849e-01
+		B3 = 1.629083358e-01
+		B4 = 2.824667908e-01
+		C1 = 4.190115298e-01
+		C2 = 6.904625373e-01
+		C3 = 6.46502159e-02
+		C4 = 1.412333954e-01
+	)
+	// special cases
+	switch {
+	case x == 0 || IsNaN(x) || IsInf(x, 0):
+		return x
+	}
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+	// Reduce argument and estimate cube root
+	f, e := Frexp(x) // 0.5 <= f < 1.0
+	m := e % 3
+	if m > 0 {
+		m -= 3
+		e -= m // e is multiple of 3
+	}
+	switch m {
+	case 0: // 0.5 <= f < 1.0
+		f = A1*f + A2 - A3/(A4+f)
+	case -1:
+		f *= 0.5 // 0.25 <= f < 0.5
+		f = B1*f + B2 - B3/(B4+f)
+	default: // m == -2
+		f *= 0.25 // 0.125 <= f < 0.25
+		f = C1*f + C2 - C3/(C4+f)
+	}
+	y := Ldexp(f, e/3) // e/3 = exponent of cube root
+
+	// Iterate
+	s := y * y * y
+	t := s + x
+	y *= (t + x) / (s + t)
+	// Reiterate
+	s = (y*y*y - x) / x
+	y -= y * (((14.0/81.0)*s-(2.0/9.0))*s + (1.0 / 3.0)) * s
+	if sign {
+		y = -y
+	}
+	return y
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/abs.go b/third_party/gofrontend/libgo/go/math/cmplx/abs.go
new file mode 100644
index 0000000..f3cd107
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/abs.go
@@ -0,0 +1,12 @@
+// Copyright 2010 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 cmplx provides basic constants and mathematical functions for
+// complex numbers.
+package cmplx
+
+import "math"
+
+// Abs returns the absolute value (also called the modulus) of x.
+func Abs(x complex128) float64 { return math.Hypot(real(x), imag(x)) }
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/asin.go b/third_party/gofrontend/libgo/go/math/cmplx/asin.go
new file mode 100644
index 0000000..61880a2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/asin.go
@@ -0,0 +1,170 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+// Complex circular arc sine
+//
+// DESCRIPTION:
+//
+// Inverse complex sine:
+//                               2
+// w = -i clog( iz + csqrt( 1 - z ) ).
+//
+// casin(z) = -i casinh(iz)
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10     10100       2.1e-15     3.4e-16
+//    IEEE      -10,+10     30000       2.2e-14     2.7e-15
+// Larger relative error can be observed for z near zero.
+// Also tested by csin(casin(z)) = z.
+
+// Asin returns the inverse sine of x.
+func Asin(x complex128) complex128 {
+	if imag(x) == 0 {
+		if math.Abs(real(x)) > 1 {
+			return complex(math.Pi/2, 0) // DOMAIN error
+		}
+		return complex(math.Asin(real(x)), 0)
+	}
+	ct := complex(-imag(x), real(x)) // i * x
+	xx := x * x
+	x1 := complex(1-real(xx), -imag(xx)) // 1 - x*x
+	x2 := Sqrt(x1)                       // x2 = sqrt(1 - x*x)
+	w := Log(ct + x2)
+	return complex(imag(w), -real(w)) // -i * w
+}
+
+// Asinh returns the inverse hyperbolic sine of x.
+func Asinh(x complex128) complex128 {
+	// TODO check range
+	if imag(x) == 0 {
+		if math.Abs(real(x)) > 1 {
+			return complex(math.Pi/2, 0) // DOMAIN error
+		}
+		return complex(math.Asinh(real(x)), 0)
+	}
+	xx := x * x
+	x1 := complex(1+real(xx), imag(xx)) // 1 + x*x
+	return Log(x + Sqrt(x1))            // log(x + sqrt(1 + x*x))
+}
+
+// Complex circular arc cosine
+//
+// DESCRIPTION:
+//
+// w = arccos z  =  PI/2 - arcsin z.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      5200      1.6e-15      2.8e-16
+//    IEEE      -10,+10     30000      1.8e-14      2.2e-15
+
+// Acos returns the inverse cosine of x.
+func Acos(x complex128) complex128 {
+	w := Asin(x)
+	return complex(math.Pi/2-real(w), -imag(w))
+}
+
+// Acosh returns the inverse hyperbolic cosine of x.
+func Acosh(x complex128) complex128 {
+	w := Acos(x)
+	if imag(w) <= 0 {
+		return complex(-imag(w), real(w)) // i * w
+	}
+	return complex(imag(w), -real(w)) // -i * w
+}
+
+// Complex circular arc tangent
+//
+// DESCRIPTION:
+//
+// If
+//     z = x + iy,
+//
+// then
+//          1       (    2x     )
+// Re w  =  - arctan(-----------)  +  k PI
+//          2       (     2    2)
+//                  (1 - x  - y )
+//
+//               ( 2         2)
+//          1    (x  +  (y+1) )
+// Im w  =  - log(------------)
+//          4    ( 2         2)
+//               (x  +  (y-1) )
+//
+// Where k is an arbitrary integer.
+//
+// catan(z) = -i catanh(iz).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      5900       1.3e-16     7.8e-18
+//    IEEE      -10,+10     30000       2.3e-15     8.5e-17
+// The check catan( ctan(z) )  =  z, with |x| and |y| < PI/2,
+// had peak relative error 1.5e-16, rms relative error
+// 2.9e-17.  See also clog().
+
+// Atan returns the inverse tangent of x.
+func Atan(x complex128) complex128 {
+	if real(x) == 0 && imag(x) > 1 {
+		return NaN()
+	}
+
+	x2 := real(x) * real(x)
+	a := 1 - x2 - imag(x)*imag(x)
+	if a == 0 {
+		return NaN()
+	}
+	t := 0.5 * math.Atan2(2*real(x), a)
+	w := reducePi(t)
+
+	t = imag(x) - 1
+	b := x2 + t*t
+	if b == 0 {
+		return NaN()
+	}
+	t = imag(x) + 1
+	c := (x2 + t*t) / b
+	return complex(w, 0.25*math.Log(c))
+}
+
+// Atanh returns the inverse hyperbolic tangent of x.
+func Atanh(x complex128) complex128 {
+	z := complex(-imag(x), real(x)) // z = i * x
+	z = Atan(z)
+	return complex(imag(z), -real(z)) // z = -i * z
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/cmath_test.go b/third_party/gofrontend/libgo/go/math/cmplx/cmath_test.go
new file mode 100644
index 0000000..f285646
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/cmath_test.go
@@ -0,0 +1,866 @@
+// Copyright 2010 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 cmplx
+
+import (
+	"math"
+	"testing"
+)
+
+var vc26 = []complex128{
+	(4.97901192488367350108546816 + 7.73887247457810456552351752i),
+	(7.73887247457810456552351752 - 0.27688005719200159404635997i),
+	(-0.27688005719200159404635997 - 5.01060361827107492160848778i),
+	(-5.01060361827107492160848778 + 9.63629370719841737980004837i),
+	(9.63629370719841737980004837 + 2.92637723924396464525443662i),
+	(2.92637723924396464525443662 + 5.22908343145930665230025625i),
+	(5.22908343145930665230025625 + 2.72793991043601025126008608i),
+	(2.72793991043601025126008608 + 1.82530809168085506044576505i),
+	(1.82530809168085506044576505 - 8.68592476857560136238589621i),
+	(-8.68592476857560136238589621 + 4.97901192488367350108546816i),
+}
+var vc = []complex128{
+	(4.9790119248836735e+00 + 7.7388724745781045e+00i),
+	(7.7388724745781045e+00 - 2.7688005719200159e-01i),
+	(-2.7688005719200159e-01 - 5.0106036182710749e+00i),
+	(-5.0106036182710749e+00 + 9.6362937071984173e+00i),
+	(9.6362937071984173e+00 + 2.9263772392439646e+00i),
+	(2.9263772392439646e+00 + 5.2290834314593066e+00i),
+	(5.2290834314593066e+00 + 2.7279399104360102e+00i),
+	(2.7279399104360102e+00 + 1.8253080916808550e+00i),
+	(1.8253080916808550e+00 - 8.6859247685756013e+00i),
+	(-8.6859247685756013e+00 + 4.9790119248836735e+00i),
+}
+
+// The expected results below were computed by the high precision calculators
+// at http://keisan.casio.com/.  More exact input values (array vc[], above)
+// were obtained by printing them with "%.26f".  The answers were calculated
+// to 26 digits (by using the "Digit number" drop-down control of each
+// calculator).
+
+var abs = []float64{
+	9.2022120669932650313380972e+00,
+	7.7438239742296106616261394e+00,
+	5.0182478202557746902556648e+00,
+	1.0861137372799545160704002e+01,
+	1.0070841084922199607011905e+01,
+	5.9922447613166942183705192e+00,
+	5.8978784056736762299945176e+00,
+	3.2822866700678709020367184e+00,
+	8.8756430028990417290744307e+00,
+	1.0011785496777731986390856e+01,
+}
+
+var acos = []complex128{
+	(1.0017679804707456328694569 - 2.9138232718554953784519807i),
+	(0.03606427612041407369636057 + 2.7358584434576260925091256i),
+	(1.6249365462333796703711823 + 2.3159537454335901187730929i),
+	(2.0485650849650740120660391 - 3.0795576791204117911123886i),
+	(0.29621132089073067282488147 - 3.0007392508200622519398814i),
+	(1.0664555914934156601503632 - 2.4872865024796011364747111i),
+	(0.48681307452231387690013905 - 2.463655912283054555225301i),
+	(0.6116977071277574248407752 - 1.8734458851737055262693056i),
+	(1.3649311280370181331184214 + 2.8793528632328795424123832i),
+	(2.6189310485682988308904501 - 2.9956543302898767795858704i),
+}
+var acosh = []complex128{
+	(2.9138232718554953784519807 + 1.0017679804707456328694569i),
+	(2.7358584434576260925091256 - 0.03606427612041407369636057i),
+	(2.3159537454335901187730929 - 1.6249365462333796703711823i),
+	(3.0795576791204117911123886 + 2.0485650849650740120660391i),
+	(3.0007392508200622519398814 + 0.29621132089073067282488147i),
+	(2.4872865024796011364747111 + 1.0664555914934156601503632i),
+	(2.463655912283054555225301 + 0.48681307452231387690013905i),
+	(1.8734458851737055262693056 + 0.6116977071277574248407752i),
+	(2.8793528632328795424123832 - 1.3649311280370181331184214i),
+	(2.9956543302898767795858704 + 2.6189310485682988308904501i),
+}
+var asin = []complex128{
+	(0.56902834632415098636186476 + 2.9138232718554953784519807i),
+	(1.5347320506744825455349611 - 2.7358584434576260925091256i),
+	(-0.054140219438483051139860579 - 2.3159537454335901187730929i),
+	(-0.47776875817017739283471738 + 3.0795576791204117911123886i),
+	(1.2745850059041659464064402 + 3.0007392508200622519398814i),
+	(0.50434073530148095908095852 + 2.4872865024796011364747111i),
+	(1.0839832522725827423311826 + 2.463655912283054555225301i),
+	(0.9590986196671391943905465 + 1.8734458851737055262693056i),
+	(0.20586519875787848611290031 - 2.8793528632328795424123832i),
+	(-1.0481347217734022116591284 + 2.9956543302898767795858704i),
+}
+var asinh = []complex128{
+	(2.9113760469415295679342185 + 0.99639459545704326759805893i),
+	(2.7441755423994259061579029 - 0.035468308789000500601119392i),
+	(-2.2962136462520690506126678 - 1.5144663565690151885726707i),
+	(-3.0771233459295725965402455 + 1.0895577967194013849422294i),
+	(3.0048366100923647417557027 + 0.29346979169819220036454168i),
+	(2.4800059370795363157364643 + 1.0545868606049165710424232i),
+	(2.4718773838309585611141821 + 0.47502344364250803363708842i),
+	(1.8910743588080159144378396 + 0.56882925572563602341139174i),
+	(2.8735426423367341878069406 - 1.362376149648891420997548i),
+	(-2.9981750586172477217567878 + 0.5183571985225367505624207i),
+}
+var atan = []complex128{
+	(1.5115747079332741358607654 + 0.091324403603954494382276776i),
+	(1.4424504323482602560806727 - 0.0045416132642803911503770933i),
+	(-1.5593488703630532674484026 - 0.20163295409248362456446431i),
+	(-1.5280619472445889867794105 + 0.081721556230672003746956324i),
+	(1.4759909163240799678221039 + 0.028602969320691644358773586i),
+	(1.4877353772046548932715555 + 0.14566877153207281663773599i),
+	(1.4206983927779191889826 + 0.076830486127880702249439993i),
+	(1.3162236060498933364869556 + 0.16031313000467530644933363i),
+	(1.5473450684303703578810093 - 0.11064907507939082484935782i),
+	(-1.4841462340185253987375812 + 0.049341850305024399493142411i),
+}
+var atanh = []complex128{
+	(0.058375027938968509064640438 + 1.4793488495105334458167782i),
+	(0.12977343497790381229915667 - 1.5661009410463561327262499i),
+	(-0.010576456067347252072200088 - 1.3743698658402284549750563i),
+	(-0.042218595678688358882784918 + 1.4891433968166405606692604i),
+	(0.095218997991316722061828397 + 1.5416884098777110330499698i),
+	(0.079965459366890323857556487 + 1.4252510353873192700350435i),
+	(0.15051245471980726221708301 + 1.4907432533016303804884461i),
+	(0.25082072933993987714470373 + 1.392057665392187516442986i),
+	(0.022896108815797135846276662 - 1.4609224989282864208963021i),
+	(-0.08665624101841876130537396 + 1.5207902036935093480142159i),
+}
+var conj = []complex128{
+	(4.9790119248836735e+00 - 7.7388724745781045e+00i),
+	(7.7388724745781045e+00 + 2.7688005719200159e-01i),
+	(-2.7688005719200159e-01 + 5.0106036182710749e+00i),
+	(-5.0106036182710749e+00 - 9.6362937071984173e+00i),
+	(9.6362937071984173e+00 - 2.9263772392439646e+00i),
+	(2.9263772392439646e+00 - 5.2290834314593066e+00i),
+	(5.2290834314593066e+00 - 2.7279399104360102e+00i),
+	(2.7279399104360102e+00 - 1.8253080916808550e+00i),
+	(1.8253080916808550e+00 + 8.6859247685756013e+00i),
+	(-8.6859247685756013e+00 - 4.9790119248836735e+00i),
+}
+var cos = []complex128{
+	(3.024540920601483938336569e+02 + 1.1073797572517071650045357e+03i),
+	(1.192858682649064973252758e-01 + 2.7857554122333065540970207e-01i),
+	(7.2144394304528306603857962e+01 - 2.0500129667076044169954205e+01i),
+	(2.24921952538403984190541e+03 - 7.317363745602773587049329e+03i),
+	(-9.148222970032421760015498e+00 + 1.953124661113563541862227e+00i),
+	(-9.116081175857732248227078e+01 - 1.992669213569952232487371e+01i),
+	(3.795639179042704640002918e+00 + 6.623513350981458399309662e+00i),
+	(-2.9144840732498869560679084e+00 - 1.214620271628002917638748e+00i),
+	(-7.45123482501299743872481e+02 + 2.8641692314488080814066734e+03i),
+	(-5.371977967039319076416747e+01 + 4.893348341339375830564624e+01i),
+}
+var cosh = []complex128{
+	(8.34638383523018249366948e+00 + 7.2181057886425846415112064e+01i),
+	(1.10421967379919366952251e+03 - 3.1379638689277575379469861e+02i),
+	(3.051485206773701584738512e-01 - 2.6805384730105297848044485e-01i),
+	(-7.33294728684187933370938e+01 + 1.574445942284918251038144e+01i),
+	(-7.478643293945957535757355e+03 + 1.6348382209913353929473321e+03i),
+	(4.622316522966235701630926e+00 - 8.088695185566375256093098e+00i),
+	(-8.544333183278877406197712e+01 + 3.7505836120128166455231717e+01i),
+	(-1.934457815021493925115198e+00 + 7.3725859611767228178358673e+00i),
+	(-2.352958770061749348353548e+00 - 2.034982010440878358915409e+00i),
+	(7.79756457532134748165069e+02 + 2.8549350716819176560377717e+03i),
+}
+var exp = []complex128{
+	(1.669197736864670815125146e+01 + 1.4436895109507663689174096e+02i),
+	(2.2084389286252583447276212e+03 - 6.2759289284909211238261917e+02i),
+	(2.227538273122775173434327e-01 + 7.2468284028334191250470034e-01i),
+	(-6.5182985958153548997881627e-03 - 1.39965837915193860879044e-03i),
+	(-1.4957286524084015746110777e+04 + 3.269676455931135688988042e+03i),
+	(9.218158701983105935659273e+00 - 1.6223985291084956009304582e+01i),
+	(-1.7088175716853040841444505e+02 + 7.501382609870410713795546e+01i),
+	(-3.852461315830959613132505e+00 + 1.4808420423156073221970892e+01i),
+	(-4.586775503301407379786695e+00 - 4.178501081246873415144744e+00i),
+	(4.451337963005453491095747e-05 - 1.62977574205442915935263e-04i),
+}
+var log = []complex128{
+	(2.2194438972179194425697051e+00 + 9.9909115046919291062461269e-01i),
+	(2.0468956191154167256337289e+00 - 3.5762575021856971295156489e-02i),
+	(1.6130808329853860438751244e+00 - 1.6259990074019058442232221e+00i),
+	(2.3851910394823008710032651e+00 + 2.0502936359659111755031062e+00i),
+	(2.3096442270679923004800651e+00 + 2.9483213155446756211881774e-01i),
+	(1.7904660933974656106951860e+00 + 1.0605860367252556281902109e+00i),
+	(1.7745926939841751666177512e+00 + 4.8084556083358307819310911e-01i),
+	(1.1885403350045342425648780e+00 + 5.8969634164776659423195222e-01i),
+	(2.1833107837679082586772505e+00 - 1.3636647724582455028314573e+00i),
+	(2.3037629487273259170991671e+00 + 2.6210913895386013290915234e+00i),
+}
+var log10 = []complex128{
+	(9.6389223745559042474184943e-01 + 4.338997735671419492599631e-01i),
+	(8.8895547241376579493490892e-01 - 1.5531488990643548254864806e-02i),
+	(7.0055210462945412305244578e-01 - 7.0616239649481243222248404e-01i),
+	(1.0358753067322445311676952e+00 + 8.9043121238134980156490909e-01i),
+	(1.003065742975330237172029e+00 + 1.2804396782187887479857811e-01i),
+	(7.7758954439739162532085157e-01 + 4.6060666333341810869055108e-01i),
+	(7.7069581462315327037689152e-01 + 2.0882857371769952195512475e-01i),
+	(5.1617650901191156135137239e-01 + 2.5610186717615977620363299e-01i),
+	(9.4819982567026639742663212e-01 - 5.9223208584446952284914289e-01i),
+	(1.0005115362454417135973429e+00 + 1.1383255270407412817250921e+00i),
+}
+
+type ff struct {
+	r, theta float64
+}
+
+var polar = []ff{
+	{9.2022120669932650313380972e+00, 9.9909115046919291062461269e-01},
+	{7.7438239742296106616261394e+00, -3.5762575021856971295156489e-02},
+	{5.0182478202557746902556648e+00, -1.6259990074019058442232221e+00},
+	{1.0861137372799545160704002e+01, 2.0502936359659111755031062e+00},
+	{1.0070841084922199607011905e+01, 2.9483213155446756211881774e-01},
+	{5.9922447613166942183705192e+00, 1.0605860367252556281902109e+00},
+	{5.8978784056736762299945176e+00, 4.8084556083358307819310911e-01},
+	{3.2822866700678709020367184e+00, 5.8969634164776659423195222e-01},
+	{8.8756430028990417290744307e+00, -1.3636647724582455028314573e+00},
+	{1.0011785496777731986390856e+01, 2.6210913895386013290915234e+00},
+}
+var pow = []complex128{
+	(-2.499956739197529585028819e+00 + 1.759751724335650228957144e+00i),
+	(7.357094338218116311191939e+04 - 5.089973412479151648145882e+04i),
+	(1.320777296067768517259592e+01 - 3.165621914333901498921986e+01i),
+	(-3.123287828297300934072149e-07 - 1.9849567521490553032502223E-7i),
+	(8.0622651468477229614813e+04 - 7.80028727944573092944363e+04i),
+	(-1.0268824572103165858577141e+00 - 4.716844738244989776610672e-01i),
+	(-4.35953819012244175753187e+01 + 2.2036445974645306917648585e+02i),
+	(8.3556092283250594950239e-01 - 1.2261571947167240272593282e+01i),
+	(1.582292972120769306069625e+03 + 1.273564263524278244782512e+04i),
+	(6.592208301642122149025369e-08 + 2.584887236651661903526389e-08i),
+}
+var sin = []complex128{
+	(-1.1073801774240233539648544e+03 + 3.024539773002502192425231e+02i),
+	(1.0317037521400759359744682e+00 - 3.2208979799929570242818e-02i),
+	(-2.0501952097271429804261058e+01 - 7.2137981348240798841800967e+01i),
+	(7.3173638080346338642193078e+03 + 2.249219506193664342566248e+03i),
+	(-1.964375633631808177565226e+00 - 9.0958264713870404464159683e+00i),
+	(1.992783647158514838337674e+01 - 9.11555769410191350416942e+01i),
+	(-6.680335650741921444300349e+00 + 3.763353833142432513086117e+00i),
+	(1.2794028166657459148245993e+00 - 2.7669092099795781155109602e+00i),
+	(2.8641693949535259594188879e+03 + 7.451234399649871202841615e+02i),
+	(-4.893811726244659135553033e+01 - 5.371469305562194635957655e+01i),
+}
+var sinh = []complex128{
+	(8.34559353341652565758198e+00 + 7.2187893208650790476628899e+01i),
+	(1.1042192548260646752051112e+03 - 3.1379650595631635858792056e+02i),
+	(-8.239469336509264113041849e-02 + 9.9273668758439489098514519e-01i),
+	(7.332295456982297798219401e+01 - 1.574585908122833444899023e+01i),
+	(-7.4786432301380582103534216e+03 + 1.63483823493980029604071e+03i),
+	(4.595842179016870234028347e+00 - 8.135290105518580753211484e+00i),
+	(-8.543842533574163435246793e+01 + 3.750798997857594068272375e+01i),
+	(-1.918003500809465688017307e+00 + 7.4358344619793504041350251e+00i),
+	(-2.233816733239658031433147e+00 - 2.143519070805995056229335e+00i),
+	(-7.797564130187551181105341e+02 - 2.8549352346594918614806877e+03i),
+}
+var sqrt = []complex128{
+	(2.6628203086086130543813948e+00 + 1.4531345674282185229796902e+00i),
+	(2.7823278427251986247149295e+00 - 4.9756907317005224529115567e-02i),
+	(1.5397025302089642757361015e+00 - 1.6271336573016637535695727e+00i),
+	(1.7103411581506875260277898e+00 + 2.8170677122737589676157029e+00i),
+	(3.1390392472953103383607947e+00 + 4.6612625849858653248980849e-01i),
+	(2.1117080764822417640789287e+00 + 1.2381170223514273234967850e+00i),
+	(2.3587032281672256703926939e+00 + 5.7827111903257349935720172e-01i),
+	(1.7335262588873410476661577e+00 + 5.2647258220721269141550382e-01i),
+	(2.3131094974708716531499282e+00 - 1.8775429304303785570775490e+00i),
+	(8.1420535745048086240947359e-01 + 3.0575897587277248522656113e+00i),
+}
+var tan = []complex128{
+	(-1.928757919086441129134525e-07 + 1.0000003267499169073251826e+00i),
+	(1.242412685364183792138948e+00 - 3.17149693883133370106696e+00i),
+	(-4.6745126251587795225571826e-05 - 9.9992439225263959286114298e-01i),
+	(4.792363401193648192887116e-09 + 1.0000000070589333451557723e+00i),
+	(2.345740824080089140287315e-03 + 9.947733046570988661022763e-01i),
+	(-2.396030789494815566088809e-05 + 9.9994781345418591429826779e-01i),
+	(-7.370204836644931340905303e-03 + 1.0043553413417138987717748e+00i),
+	(-3.691803847992048527007457e-02 + 9.6475071993469548066328894e-01i),
+	(-2.781955256713729368401878e-08 - 1.000000049848910609006646e+00i),
+	(9.4281590064030478879791249e-05 + 9.9999119340863718183758545e-01i),
+}
+var tanh = []complex128{
+	(1.0000921981225144748819918e+00 + 2.160986245871518020231507e-05i),
+	(9.9999967727531993209562591e-01 - 1.9953763222959658873657676e-07i),
+	(-1.765485739548037260789686e+00 + 1.7024216325552852445168471e+00i),
+	(-9.999189442732736452807108e-01 + 3.64906070494473701938098e-05i),
+	(9.9999999224622333738729767e-01 - 3.560088949517914774813046e-09i),
+	(1.0029324933367326862499343e+00 - 4.948790309797102353137528e-03i),
+	(9.9996113064788012488693567e-01 - 4.226995742097032481451259e-05i),
+	(1.0074784189316340029873945e+00 - 4.194050814891697808029407e-03i),
+	(9.9385534229718327109131502e-01 + 5.144217985914355502713437e-02i),
+	(-1.0000000491604982429364892e+00 - 2.901873195374433112227349e-08i),
+}
+
+// special cases
+var vcAbsSC = []complex128{
+	NaN(),
+}
+var absSC = []float64{
+	math.NaN(),
+}
+var vcAcosSC = []complex128{
+	NaN(),
+}
+var acosSC = []complex128{
+	NaN(),
+}
+var vcAcoshSC = []complex128{
+	NaN(),
+}
+var acoshSC = []complex128{
+	NaN(),
+}
+var vcAsinSC = []complex128{
+	NaN(),
+}
+var asinSC = []complex128{
+	NaN(),
+}
+var vcAsinhSC = []complex128{
+	NaN(),
+}
+var asinhSC = []complex128{
+	NaN(),
+}
+var vcAtanSC = []complex128{
+	NaN(),
+}
+var atanSC = []complex128{
+	NaN(),
+}
+var vcAtanhSC = []complex128{
+	NaN(),
+}
+var atanhSC = []complex128{
+	NaN(),
+}
+var vcConjSC = []complex128{
+	NaN(),
+}
+var conjSC = []complex128{
+	NaN(),
+}
+var vcCosSC = []complex128{
+	NaN(),
+}
+var cosSC = []complex128{
+	NaN(),
+}
+var vcCoshSC = []complex128{
+	NaN(),
+}
+var coshSC = []complex128{
+	NaN(),
+}
+var vcExpSC = []complex128{
+	NaN(),
+}
+var expSC = []complex128{
+	NaN(),
+}
+var vcIsNaNSC = []complex128{
+	complex(math.Inf(-1), math.Inf(-1)),
+	complex(math.Inf(-1), math.NaN()),
+	complex(math.NaN(), math.Inf(-1)),
+	complex(0, math.NaN()),
+	complex(math.NaN(), 0),
+	complex(math.Inf(1), math.Inf(1)),
+	complex(math.Inf(1), math.NaN()),
+	complex(math.NaN(), math.Inf(1)),
+	complex(math.NaN(), math.NaN()),
+}
+var isNaNSC = []bool{
+	false,
+	false,
+	false,
+	true,
+	true,
+	false,
+	false,
+	false,
+	true,
+}
+var vcLogSC = []complex128{
+	NaN(),
+}
+var logSC = []complex128{
+	NaN(),
+}
+var vcLog10SC = []complex128{
+	NaN(),
+}
+var log10SC = []complex128{
+	NaN(),
+}
+var vcPolarSC = []complex128{
+	NaN(),
+}
+var polarSC = []ff{
+	{math.NaN(), math.NaN()},
+}
+var vcPowSC = [][2]complex128{
+	{NaN(), NaN()},
+}
+var powSC = []complex128{
+	NaN(),
+}
+var vcSinSC = []complex128{
+	NaN(),
+}
+var sinSC = []complex128{
+	NaN(),
+}
+var vcSinhSC = []complex128{
+	NaN(),
+}
+var sinhSC = []complex128{
+	NaN(),
+}
+var vcSqrtSC = []complex128{
+	NaN(),
+}
+var sqrtSC = []complex128{
+	NaN(),
+}
+var vcTanSC = []complex128{
+	NaN(),
+}
+var tanSC = []complex128{
+	NaN(),
+}
+var vcTanhSC = []complex128{
+	NaN(),
+}
+var tanhSC = []complex128{
+	NaN(),
+}
+
+// functions borrowed from pkg/math/all_test.go
+func tolerance(a, b, e float64) bool {
+	d := a - b
+	if d < 0 {
+		d = -d
+	}
+
+	if a != 0 {
+		e = e * a
+		if e < 0 {
+			e = -e
+		}
+	}
+	return d < e
+}
+func soclose(a, b, e float64) bool { return tolerance(a, b, e) }
+func veryclose(a, b float64) bool  { return tolerance(a, b, 4e-16) }
+func alike(a, b float64) bool {
+	switch {
+	case a != a && b != b: // math.IsNaN(a) && math.IsNaN(b):
+		return true
+	case a == b:
+		return math.Signbit(a) == math.Signbit(b)
+	}
+	return false
+}
+
+func cTolerance(a, b complex128, e float64) bool {
+	d := Abs(a - b)
+	if a != 0 {
+		e = e * Abs(a)
+		if e < 0 {
+			e = -e
+		}
+	}
+	return d < e
+}
+func cSoclose(a, b complex128, e float64) bool { return cTolerance(a, b, e) }
+func cVeryclose(a, b complex128) bool          { return cTolerance(a, b, 4e-16) }
+func cAlike(a, b complex128) bool {
+	switch {
+	case IsNaN(a) && IsNaN(b):
+		return true
+	case a == b:
+		return math.Signbit(real(a)) == math.Signbit(real(b)) && math.Signbit(imag(a)) == math.Signbit(imag(b))
+	}
+	return false
+}
+
+func TestAbs(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Abs(vc[i]); !veryclose(abs[i], f) {
+			t.Errorf("Abs(%g) = %g, want %g", vc[i], f, abs[i])
+		}
+	}
+	for i := 0; i < len(vcAbsSC); i++ {
+		if f := Abs(vcAbsSC[i]); !alike(absSC[i], f) {
+			t.Errorf("Abs(%g) = %g, want %g", vcAbsSC[i], f, absSC[i])
+		}
+	}
+}
+func TestAcos(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Acos(vc[i]); !cSoclose(acos[i], f, 1e-14) {
+			t.Errorf("Acos(%g) = %g, want %g", vc[i], f, acos[i])
+		}
+	}
+	for i := 0; i < len(vcAcosSC); i++ {
+		if f := Acos(vcAcosSC[i]); !cAlike(acosSC[i], f) {
+			t.Errorf("Acos(%g) = %g, want %g", vcAcosSC[i], f, acosSC[i])
+		}
+	}
+}
+func TestAcosh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Acosh(vc[i]); !cSoclose(acosh[i], f, 1e-14) {
+			t.Errorf("Acosh(%g) = %g, want %g", vc[i], f, acosh[i])
+		}
+	}
+	for i := 0; i < len(vcAcoshSC); i++ {
+		if f := Acosh(vcAcoshSC[i]); !cAlike(acoshSC[i], f) {
+			t.Errorf("Acosh(%g) = %g, want %g", vcAcoshSC[i], f, acoshSC[i])
+		}
+	}
+}
+func TestAsin(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Asin(vc[i]); !cSoclose(asin[i], f, 1e-14) {
+			t.Errorf("Asin(%g) = %g, want %g", vc[i], f, asin[i])
+		}
+	}
+	for i := 0; i < len(vcAsinSC); i++ {
+		if f := Asin(vcAsinSC[i]); !cAlike(asinSC[i], f) {
+			t.Errorf("Asin(%g) = %g, want %g", vcAsinSC[i], f, asinSC[i])
+		}
+	}
+}
+func TestAsinh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Asinh(vc[i]); !cSoclose(asinh[i], f, 4e-15) {
+			t.Errorf("Asinh(%g) = %g, want %g", vc[i], f, asinh[i])
+		}
+	}
+	for i := 0; i < len(vcAsinhSC); i++ {
+		if f := Asinh(vcAsinhSC[i]); !cAlike(asinhSC[i], f) {
+			t.Errorf("Asinh(%g) = %g, want %g", vcAsinhSC[i], f, asinhSC[i])
+		}
+	}
+}
+func TestAtan(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Atan(vc[i]); !cVeryclose(atan[i], f) {
+			t.Errorf("Atan(%g) = %g, want %g", vc[i], f, atan[i])
+		}
+	}
+	for i := 0; i < len(vcAtanSC); i++ {
+		if f := Atan(vcAtanSC[i]); !cAlike(atanSC[i], f) {
+			t.Errorf("Atan(%g) = %g, want %g", vcAtanSC[i], f, atanSC[i])
+		}
+	}
+}
+func TestAtanh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Atanh(vc[i]); !cVeryclose(atanh[i], f) {
+			t.Errorf("Atanh(%g) = %g, want %g", vc[i], f, atanh[i])
+		}
+	}
+	for i := 0; i < len(vcAtanhSC); i++ {
+		if f := Atanh(vcAtanhSC[i]); !cAlike(atanhSC[i], f) {
+			t.Errorf("Atanh(%g) = %g, want %g", vcAtanhSC[i], f, atanhSC[i])
+		}
+	}
+}
+func TestConj(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Conj(vc[i]); !cVeryclose(conj[i], f) {
+			t.Errorf("Conj(%g) = %g, want %g", vc[i], f, conj[i])
+		}
+	}
+	for i := 0; i < len(vcConjSC); i++ {
+		if f := Conj(vcConjSC[i]); !cAlike(conjSC[i], f) {
+			t.Errorf("Conj(%g) = %g, want %g", vcConjSC[i], f, conjSC[i])
+		}
+	}
+}
+func TestCos(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Cos(vc[i]); !cSoclose(cos[i], f, 3e-15) {
+			t.Errorf("Cos(%g) = %g, want %g", vc[i], f, cos[i])
+		}
+	}
+	for i := 0; i < len(vcCosSC); i++ {
+		if f := Cos(vcCosSC[i]); !cAlike(cosSC[i], f) {
+			t.Errorf("Cos(%g) = %g, want %g", vcCosSC[i], f, cosSC[i])
+		}
+	}
+}
+func TestCosh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Cosh(vc[i]); !cSoclose(cosh[i], f, 2e-15) {
+			t.Errorf("Cosh(%g) = %g, want %g", vc[i], f, cosh[i])
+		}
+	}
+	for i := 0; i < len(vcCoshSC); i++ {
+		if f := Cosh(vcCoshSC[i]); !cAlike(coshSC[i], f) {
+			t.Errorf("Cosh(%g) = %g, want %g", vcCoshSC[i], f, coshSC[i])
+		}
+	}
+}
+func TestExp(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Exp(vc[i]); !cSoclose(exp[i], f, 1e-15) {
+			t.Errorf("Exp(%g) = %g, want %g", vc[i], f, exp[i])
+		}
+	}
+	for i := 0; i < len(vcExpSC); i++ {
+		if f := Exp(vcExpSC[i]); !cAlike(expSC[i], f) {
+			t.Errorf("Exp(%g) = %g, want %g", vcExpSC[i], f, expSC[i])
+		}
+	}
+}
+func TestIsNaN(t *testing.T) {
+	for i := 0; i < len(vcIsNaNSC); i++ {
+		if f := IsNaN(vcIsNaNSC[i]); isNaNSC[i] != f {
+			t.Errorf("IsNaN(%v) = %v, want %v", vcIsNaNSC[i], f, isNaNSC[i])
+		}
+	}
+}
+func TestLog(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Log(vc[i]); !cVeryclose(log[i], f) {
+			t.Errorf("Log(%g) = %g, want %g", vc[i], f, log[i])
+		}
+	}
+	for i := 0; i < len(vcLogSC); i++ {
+		if f := Log(vcLogSC[i]); !cAlike(logSC[i], f) {
+			t.Errorf("Log(%g) = %g, want %g", vcLogSC[i], f, logSC[i])
+		}
+	}
+}
+func TestLog10(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Log10(vc[i]); !cVeryclose(log10[i], f) {
+			t.Errorf("Log10(%g) = %g, want %g", vc[i], f, log10[i])
+		}
+	}
+	for i := 0; i < len(vcLog10SC); i++ {
+		if f := Log10(vcLog10SC[i]); !cAlike(log10SC[i], f) {
+			t.Errorf("Log10(%g) = %g, want %g", vcLog10SC[i], f, log10SC[i])
+		}
+	}
+}
+func TestPolar(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if r, theta := Polar(vc[i]); !veryclose(polar[i].r, r) && !veryclose(polar[i].theta, theta) {
+			t.Errorf("Polar(%g) = %g, %g want %g, %g", vc[i], r, theta, polar[i].r, polar[i].theta)
+		}
+	}
+	for i := 0; i < len(vcPolarSC); i++ {
+		if r, theta := Polar(vcPolarSC[i]); !alike(polarSC[i].r, r) && !alike(polarSC[i].theta, theta) {
+			t.Errorf("Polar(%g) = %g, %g, want %g, %g", vcPolarSC[i], r, theta, polarSC[i].r, polarSC[i].theta)
+		}
+	}
+}
+func TestPow(t *testing.T) {
+	// Special cases for Pow(0, c).
+	var zero = complex(0, 0)
+	zeroPowers := [][2]complex128{
+		{0, 1 + 0i},
+		{1.5, 0 + 0i},
+		{-1.5, complex(math.Inf(0), 0)},
+		{-1.5 + 1.5i, Inf()},
+	}
+	for _, zp := range zeroPowers {
+		if f := Pow(zero, zp[0]); f != zp[1] {
+			t.Errorf("Pow(%g, %g) = %g, want %g", zero, zp[0], f, zp[1])
+		}
+	}
+	var a = complex(3.0, 3.0)
+	for i := 0; i < len(vc); i++ {
+		if f := Pow(a, vc[i]); !cSoclose(pow[i], f, 4e-15) {
+			t.Errorf("Pow(%g, %g) = %g, want %g", a, vc[i], f, pow[i])
+		}
+	}
+	for i := 0; i < len(vcPowSC); i++ {
+		if f := Pow(vcPowSC[i][0], vcPowSC[i][0]); !cAlike(powSC[i], f) {
+			t.Errorf("Pow(%g, %g) = %g, want %g", vcPowSC[i][0], vcPowSC[i][0], f, powSC[i])
+		}
+	}
+}
+func TestRect(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Rect(polar[i].r, polar[i].theta); !cVeryclose(vc[i], f) {
+			t.Errorf("Rect(%g, %g) = %g want %g", polar[i].r, polar[i].theta, f, vc[i])
+		}
+	}
+	for i := 0; i < len(vcPolarSC); i++ {
+		if f := Rect(polarSC[i].r, polarSC[i].theta); !cAlike(vcPolarSC[i], f) {
+			t.Errorf("Rect(%g, %g) = %g, want %g", polarSC[i].r, polarSC[i].theta, f, vcPolarSC[i])
+		}
+	}
+}
+func TestSin(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Sin(vc[i]); !cSoclose(sin[i], f, 2e-15) {
+			t.Errorf("Sin(%g) = %g, want %g", vc[i], f, sin[i])
+		}
+	}
+	for i := 0; i < len(vcSinSC); i++ {
+		if f := Sin(vcSinSC[i]); !cAlike(sinSC[i], f) {
+			t.Errorf("Sin(%g) = %g, want %g", vcSinSC[i], f, sinSC[i])
+		}
+	}
+}
+func TestSinh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Sinh(vc[i]); !cSoclose(sinh[i], f, 2e-15) {
+			t.Errorf("Sinh(%g) = %g, want %g", vc[i], f, sinh[i])
+		}
+	}
+	for i := 0; i < len(vcSinhSC); i++ {
+		if f := Sinh(vcSinhSC[i]); !cAlike(sinhSC[i], f) {
+			t.Errorf("Sinh(%g) = %g, want %g", vcSinhSC[i], f, sinhSC[i])
+		}
+	}
+}
+func TestSqrt(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Sqrt(vc[i]); !cVeryclose(sqrt[i], f) {
+			t.Errorf("Sqrt(%g) = %g, want %g", vc[i], f, sqrt[i])
+		}
+	}
+	for i := 0; i < len(vcSqrtSC); i++ {
+		if f := Sqrt(vcSqrtSC[i]); !cAlike(sqrtSC[i], f) {
+			t.Errorf("Sqrt(%g) = %g, want %g", vcSqrtSC[i], f, sqrtSC[i])
+		}
+	}
+}
+func TestTan(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Tan(vc[i]); !cSoclose(tan[i], f, 3e-15) {
+			t.Errorf("Tan(%g) = %g, want %g", vc[i], f, tan[i])
+		}
+	}
+	for i := 0; i < len(vcTanSC); i++ {
+		if f := Tan(vcTanSC[i]); !cAlike(tanSC[i], f) {
+			t.Errorf("Tan(%g) = %g, want %g", vcTanSC[i], f, tanSC[i])
+		}
+	}
+}
+func TestTanh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Tanh(vc[i]); !cSoclose(tanh[i], f, 2e-15) {
+			t.Errorf("Tanh(%g) = %g, want %g", vc[i], f, tanh[i])
+		}
+	}
+	for i := 0; i < len(vcTanhSC); i++ {
+		if f := Tanh(vcTanhSC[i]); !cAlike(tanhSC[i], f) {
+			t.Errorf("Tanh(%g) = %g, want %g", vcTanhSC[i], f, tanhSC[i])
+		}
+	}
+}
+
+func BenchmarkAbs(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Abs(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAcos(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Acos(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAcosh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Acosh(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAsin(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Asin(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAsinh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Asinh(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAtan(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Atan(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAtanh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Atanh(complex(2.5, 3.5))
+	}
+}
+func BenchmarkConj(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Conj(complex(2.5, 3.5))
+	}
+}
+func BenchmarkCos(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Cos(complex(2.5, 3.5))
+	}
+}
+func BenchmarkCosh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Cosh(complex(2.5, 3.5))
+	}
+}
+func BenchmarkExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Exp(complex(2.5, 3.5))
+	}
+}
+func BenchmarkLog(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Log(complex(2.5, 3.5))
+	}
+}
+func BenchmarkLog10(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Log10(complex(2.5, 3.5))
+	}
+}
+func BenchmarkPhase(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Phase(complex(2.5, 3.5))
+	}
+}
+func BenchmarkPolar(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Polar(complex(2.5, 3.5))
+	}
+}
+func BenchmarkPow(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Pow(complex(2.5, 3.5), complex(2.5, 3.5))
+	}
+}
+func BenchmarkRect(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Rect(2.5, 1.5)
+	}
+}
+func BenchmarkSin(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sin(complex(2.5, 3.5))
+	}
+}
+func BenchmarkSinh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sinh(complex(2.5, 3.5))
+	}
+}
+func BenchmarkSqrt(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sqrt(complex(2.5, 3.5))
+	}
+}
+func BenchmarkTan(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Tan(complex(2.5, 3.5))
+	}
+}
+func BenchmarkTanh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Tanh(complex(2.5, 3.5))
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/conj.go b/third_party/gofrontend/libgo/go/math/cmplx/conj.go
new file mode 100644
index 0000000..34a4277
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/conj.go
@@ -0,0 +1,8 @@
+// Copyright 2010 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 cmplx
+
+// Conj returns the complex conjugate of x.
+func Conj(x complex128) complex128 { return complex(real(x), -imag(x)) }
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/exp.go b/third_party/gofrontend/libgo/go/math/cmplx/exp.go
new file mode 100644
index 0000000..485ed2c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/exp.go
@@ -0,0 +1,55 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+// Complex exponential function
+//
+// DESCRIPTION:
+//
+// Returns the complex exponential of the complex argument z.
+//
+// If
+//     z = x + iy,
+//     r = exp(x),
+// then
+//     w = r cos y + i r sin y.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      8700       3.7e-17     1.1e-17
+//    IEEE      -10,+10     30000       3.0e-16     8.7e-17
+
+// Exp returns e**x, the base-e exponential of x.
+func Exp(x complex128) complex128 {
+	r := math.Exp(real(x))
+	s, c := math.Sincos(imag(x))
+	return complex(r*c, r*s)
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/isinf.go b/third_party/gofrontend/libgo/go/math/cmplx/isinf.go
new file mode 100644
index 0000000..d5a65b4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/isinf.go
@@ -0,0 +1,21 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// IsInf returns true if either real(x) or imag(x) is an infinity.
+func IsInf(x complex128) bool {
+	if math.IsInf(real(x), 0) || math.IsInf(imag(x), 0) {
+		return true
+	}
+	return false
+}
+
+// Inf returns a complex infinity, complex(+Inf, +Inf).
+func Inf() complex128 {
+	inf := math.Inf(1)
+	return complex(inf, inf)
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/isnan.go b/third_party/gofrontend/libgo/go/math/cmplx/isnan.go
new file mode 100644
index 0000000..05d0cce
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/isnan.go
@@ -0,0 +1,25 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// IsNaN returns true if either real(x) or imag(x) is NaN
+// and neither is an infinity.
+func IsNaN(x complex128) bool {
+	switch {
+	case math.IsInf(real(x), 0) || math.IsInf(imag(x), 0):
+		return false
+	case math.IsNaN(real(x)) || math.IsNaN(imag(x)):
+		return true
+	}
+	return false
+}
+
+// NaN returns a complex ``not-a-number'' value.
+func NaN() complex128 {
+	nan := math.NaN()
+	return complex(nan, nan)
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/log.go b/third_party/gofrontend/libgo/go/math/cmplx/log.go
new file mode 100644
index 0000000..881a064
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/log.go
@@ -0,0 +1,64 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+// Complex natural logarithm
+//
+// DESCRIPTION:
+//
+// Returns complex logarithm to the base e (2.718...) of
+// the complex argument z.
+//
+// If
+//       z = x + iy, r = sqrt( x**2 + y**2 ),
+// then
+//       w = log(r) + i arctan(y/x).
+//
+// The arctangent ranges from -PI to +PI.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      7000       8.5e-17     1.9e-17
+//    IEEE      -10,+10     30000       5.0e-15     1.1e-16
+//
+// Larger relative error can be observed for z near 1 +i0.
+// In IEEE arithmetic the peak absolute error is 5.2e-16, rms
+// absolute error 1.0e-16.
+
+// Log returns the natural logarithm of x.
+func Log(x complex128) complex128 {
+	return complex(math.Log(Abs(x)), Phase(x))
+}
+
+// Log10 returns the decimal logarithm of x.
+func Log10(x complex128) complex128 {
+	return math.Log10E * Log(x)
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/phase.go b/third_party/gofrontend/libgo/go/math/cmplx/phase.go
new file mode 100644
index 0000000..03cece8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/phase.go
@@ -0,0 +1,11 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// Phase returns the phase (also called the argument) of x.
+// The returned value is in the range [-Pi, Pi].
+func Phase(x complex128) float64 { return math.Atan2(imag(x), real(x)) }
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/polar.go b/third_party/gofrontend/libgo/go/math/cmplx/polar.go
new file mode 100644
index 0000000..9b192bc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/polar.go
@@ -0,0 +1,12 @@
+// Copyright 2010 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 cmplx
+
+// Polar returns the absolute value r and phase θ of x,
+// such that x = r * e**θi.
+// The phase is in the range [-Pi, Pi].
+func Polar(x complex128) (r, θ float64) {
+	return Abs(x), Phase(x)
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/pow.go b/third_party/gofrontend/libgo/go/math/cmplx/pow.go
new file mode 100644
index 0000000..1630b87
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/pow.go
@@ -0,0 +1,78 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+// Complex power function
+//
+// DESCRIPTION:
+//
+// Raises complex A to the complex Zth power.
+// Definition is per AMS55 # 4.2.8,
+// analytically equivalent to cpow(a,z) = cexp(z clog(a)).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    IEEE      -10,+10     30000       9.4e-15     1.5e-15
+
+// Pow returns x**y, the base-x exponential of y.
+// For generalized compatibility with math.Pow:
+//	Pow(0, ±0) returns 1+0i
+//	Pow(0, c) for real(c)<0 returns Inf+0i if imag(c) is zero, otherwise Inf+Inf i.
+func Pow(x, y complex128) complex128 {
+	if x == 0 { // Guaranteed also true for x == -0.
+		r, i := real(y), imag(y)
+		switch {
+		case r == 0:
+			return 1
+		case r < 0:
+			if i == 0 {
+				return complex(math.Inf(1), 0)
+			}
+			return Inf()
+		case r > 0:
+			return 0
+		}
+		panic("not reached")
+	}
+	modulus := Abs(x)
+	if modulus == 0 {
+		return complex(0, 0)
+	}
+	r := math.Pow(modulus, real(y))
+	arg := Phase(x)
+	theta := real(y) * arg
+	if imag(y) != 0 {
+		r *= math.Exp(-imag(y) * arg)
+		theta += imag(y) * math.Log(modulus)
+	}
+	s, c := math.Sincos(theta)
+	return complex(r*c, r*s)
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/rect.go b/third_party/gofrontend/libgo/go/math/cmplx/rect.go
new file mode 100644
index 0000000..bf94d78
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/rect.go
@@ -0,0 +1,13 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// Rect returns the complex number x with polar coordinates r, θ.
+func Rect(r, θ float64) complex128 {
+	s, c := math.Sincos(θ)
+	return complex(r*c, r*s)
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/sin.go b/third_party/gofrontend/libgo/go/math/cmplx/sin.go
new file mode 100644
index 0000000..2c57536
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/sin.go
@@ -0,0 +1,132 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+// Complex circular sine
+//
+// DESCRIPTION:
+//
+// If
+//     z = x + iy,
+//
+// then
+//
+//     w = sin x  cosh y  +  i cos x sinh y.
+//
+// csin(z) = -i csinh(iz).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      8400       5.3e-17     1.3e-17
+//    IEEE      -10,+10     30000       3.8e-16     1.0e-16
+// Also tested by csin(casin(z)) = z.
+
+// Sin returns the sine of x.
+func Sin(x complex128) complex128 {
+	s, c := math.Sincos(real(x))
+	sh, ch := sinhcosh(imag(x))
+	return complex(s*ch, c*sh)
+}
+
+// Complex hyperbolic sine
+//
+// DESCRIPTION:
+//
+// csinh z = (cexp(z) - cexp(-z))/2
+//         = sinh x * cos y  +  i cosh x * sin y .
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    IEEE      -10,+10     30000       3.1e-16     8.2e-17
+
+// Sinh returns the hyperbolic sine of x.
+func Sinh(x complex128) complex128 {
+	s, c := math.Sincos(imag(x))
+	sh, ch := sinhcosh(real(x))
+	return complex(c*sh, s*ch)
+}
+
+// Complex circular cosine
+//
+// DESCRIPTION:
+//
+// If
+//     z = x + iy,
+//
+// then
+//
+//     w = cos x  cosh y  -  i sin x sinh y.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      8400       4.5e-17     1.3e-17
+//    IEEE      -10,+10     30000       3.8e-16     1.0e-16
+
+// Cos returns the cosine of x.
+func Cos(x complex128) complex128 {
+	s, c := math.Sincos(real(x))
+	sh, ch := sinhcosh(imag(x))
+	return complex(c*ch, -s*sh)
+}
+
+// Complex hyperbolic cosine
+//
+// DESCRIPTION:
+//
+// ccosh(z) = cosh x  cos y + i sinh x sin y .
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    IEEE      -10,+10     30000       2.9e-16     8.1e-17
+
+// Cosh returns the hyperbolic cosine of x.
+func Cosh(x complex128) complex128 {
+	s, c := math.Sincos(imag(x))
+	sh, ch := sinhcosh(real(x))
+	return complex(c*ch, s*sh)
+}
+
+// calculate sinh and cosh
+func sinhcosh(x float64) (sh, ch float64) {
+	if math.Abs(x) <= 0.5 {
+		return math.Sinh(x), math.Cosh(x)
+	}
+	e := math.Exp(x)
+	ei := 0.5 / e
+	e *= 0.5
+	return e - ei, e + ei
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/sqrt.go b/third_party/gofrontend/libgo/go/math/cmplx/sqrt.go
new file mode 100644
index 0000000..4ef6807
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/sqrt.go
@@ -0,0 +1,104 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+// Complex square root
+//
+// DESCRIPTION:
+//
+// If z = x + iy,  r = |z|, then
+//
+//                       1/2
+// Re w  =  [ (r + x)/2 ]   ,
+//
+//                       1/2
+// Im w  =  [ (r - x)/2 ]   .
+//
+// Cancellation error in r-x or r+x is avoided by using the
+// identity  2 Re w Im w  =  y.
+//
+// Note that -w is also a square root of z.  The root chosen
+// is always in the right half plane and Im w has the same sign as y.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10     25000       3.2e-17     9.6e-18
+//    IEEE      -10,+10   1,000,000     2.9e-16     6.1e-17
+
+// Sqrt returns the square root of x.
+// The result r is chosen so that real(r) ≥ 0 and imag(r) has the same sign as imag(x).
+func Sqrt(x complex128) complex128 {
+	if imag(x) == 0 {
+		if real(x) == 0 {
+			return complex(0, 0)
+		}
+		if real(x) < 0 {
+			return complex(0, math.Sqrt(-real(x)))
+		}
+		return complex(math.Sqrt(real(x)), 0)
+	}
+	if real(x) == 0 {
+		if imag(x) < 0 {
+			r := math.Sqrt(-0.5 * imag(x))
+			return complex(r, -r)
+		}
+		r := math.Sqrt(0.5 * imag(x))
+		return complex(r, r)
+	}
+	a := real(x)
+	b := imag(x)
+	var scale float64
+	// Rescale to avoid internal overflow or underflow.
+	if math.Abs(a) > 4 || math.Abs(b) > 4 {
+		a *= 0.25
+		b *= 0.25
+		scale = 2
+	} else {
+		a *= 1.8014398509481984e16 // 2**54
+		b *= 1.8014398509481984e16
+		scale = 7.450580596923828125e-9 // 2**-27
+	}
+	r := math.Hypot(a, b)
+	var t float64
+	if a > 0 {
+		t = math.Sqrt(0.5*r + 0.5*a)
+		r = scale * math.Abs((0.5*b)/t)
+		t *= scale
+	} else {
+		r = math.Sqrt(0.5*r - 0.5*a)
+		t = scale * math.Abs((0.5*b)/r)
+		r *= scale
+	}
+	if b < 0 {
+		return complex(t, -r)
+	}
+	return complex(t, r)
+}
diff --git a/third_party/gofrontend/libgo/go/math/cmplx/tan.go b/third_party/gofrontend/libgo/go/math/cmplx/tan.go
new file mode 100644
index 0000000..9485315
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/cmplx/tan.go
@@ -0,0 +1,184 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+// Complex circular tangent
+//
+// DESCRIPTION:
+//
+// If
+//     z = x + iy,
+//
+// then
+//
+//           sin 2x  +  i sinh 2y
+//     w  =  --------------------.
+//            cos 2x  +  cosh 2y
+//
+// On the real axis the denominator is zero at odd multiples
+// of PI/2.  The denominator is evaluated by its Taylor
+// series near these points.
+//
+// ctan(z) = -i ctanh(iz).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      5200       7.1e-17     1.6e-17
+//    IEEE      -10,+10     30000       7.2e-16     1.2e-16
+// Also tested by ctan * ccot = 1 and catan(ctan(z))  =  z.
+
+// Tan returns the tangent of x.
+func Tan(x complex128) complex128 {
+	d := math.Cos(2*real(x)) + math.Cosh(2*imag(x))
+	if math.Abs(d) < 0.25 {
+		d = tanSeries(x)
+	}
+	if d == 0 {
+		return Inf()
+	}
+	return complex(math.Sin(2*real(x))/d, math.Sinh(2*imag(x))/d)
+}
+
+// Complex hyperbolic tangent
+//
+// DESCRIPTION:
+//
+// tanh z = (sinh 2x  +  i sin 2y) / (cosh 2x + cos 2y) .
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    IEEE      -10,+10     30000       1.7e-14     2.4e-16
+
+// Tanh returns the hyperbolic tangent of x.
+func Tanh(x complex128) complex128 {
+	d := math.Cosh(2*real(x)) + math.Cos(2*imag(x))
+	if d == 0 {
+		return Inf()
+	}
+	return complex(math.Sinh(2*real(x))/d, math.Sin(2*imag(x))/d)
+}
+
+// Program to subtract nearest integer multiple of PI
+func reducePi(x float64) float64 {
+	const (
+		// extended precision value of PI:
+		DP1 = 3.14159265160560607910E0   // ?? 0x400921fb54000000
+		DP2 = 1.98418714791870343106E-9  // ?? 0x3e210b4610000000
+		DP3 = 1.14423774522196636802E-17 // ?? 0x3c6a62633145c06e
+	)
+	t := x / math.Pi
+	if t >= 0 {
+		t += 0.5
+	} else {
+		t -= 0.5
+	}
+	t = float64(int64(t)) // int64(t) = the multiple
+	return ((x - t*DP1) - t*DP2) - t*DP3
+}
+
+// Taylor series expansion for cosh(2y) - cos(2x)
+func tanSeries(z complex128) float64 {
+	const MACHEP = 1.0 / (1 << 53)
+	x := math.Abs(2 * real(z))
+	y := math.Abs(2 * imag(z))
+	x = reducePi(x)
+	x = x * x
+	y = y * y
+	x2 := 1.0
+	y2 := 1.0
+	f := 1.0
+	rn := 0.0
+	d := 0.0
+	for {
+		rn += 1
+		f *= rn
+		rn += 1
+		f *= rn
+		x2 *= x
+		y2 *= y
+		t := y2 + x2
+		t /= f
+		d += t
+
+		rn += 1
+		f *= rn
+		rn += 1
+		f *= rn
+		x2 *= x
+		y2 *= y
+		t = y2 - x2
+		t /= f
+		d += t
+		if math.Abs(t/d) <= MACHEP {
+			break
+		}
+	}
+	return d
+}
+
+// Complex circular cotangent
+//
+// DESCRIPTION:
+//
+// If
+//     z = x + iy,
+//
+// then
+//
+//           sin 2x  -  i sinh 2y
+//     w  =  --------------------.
+//            cosh 2y  -  cos 2x
+//
+// On the real axis, the denominator has zeros at even
+// multiples of PI/2.  Near these points it is evaluated
+// by a Taylor series.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      3000       6.5e-17     1.6e-17
+//    IEEE      -10,+10     30000       9.2e-16     1.2e-16
+// Also tested by ctan * ccot = 1 + i0.
+
+// Cot returns the cotangent of x.
+func Cot(x complex128) complex128 {
+	d := math.Cosh(2*imag(x)) - math.Cos(2*real(x))
+	if math.Abs(d) < 0.25 {
+		d = tanSeries(x)
+	}
+	if d == 0 {
+		return Inf()
+	}
+	return complex(math.Sin(2*real(x))/d, -math.Sinh(2*imag(x))/d)
+}
diff --git a/third_party/gofrontend/libgo/go/math/const.go b/third_party/gofrontend/libgo/go/math/const.go
new file mode 100644
index 0000000..f1247c3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/const.go
@@ -0,0 +1,51 @@
+// 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 math provides basic constants and mathematical functions.
+package math
+
+// Mathematical constants.
+// Reference: http://oeis.org/Axxxxxx
+const (
+	E   = 2.71828182845904523536028747135266249775724709369995957496696763 // A001113
+	Pi  = 3.14159265358979323846264338327950288419716939937510582097494459 // A000796
+	Phi = 1.61803398874989484820458683436563811772030917980576286213544862 // A001622
+
+	Sqrt2   = 1.41421356237309504880168872420969807856967187537694807317667974 // A002193
+	SqrtE   = 1.64872127070012814684865078781416357165377610071014801157507931 // A019774
+	SqrtPi  = 1.77245385090551602729816748334114518279754945612238712821380779 // A002161
+	SqrtPhi = 1.27201964951406896425242246173749149171560804184009624861664038 // A139339
+
+	Ln2    = 0.693147180559945309417232121458176568075500134360255254120680009 // A002162
+	Log2E  = 1 / Ln2
+	Ln10   = 2.30258509299404568401799145468436420760110148862877297603332790 // A002392
+	Log10E = 1 / Ln10
+)
+
+// Floating-point limit values.
+// Max is the largest finite value representable by the type.
+// SmallestNonzero is the smallest positive, non-zero value representable by the type.
+const (
+	MaxFloat32             = 3.40282346638528859811704183484516925440e+38  // 2**127 * (2**24 - 1) / 2**23
+	SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23)
+
+	MaxFloat64             = 1.797693134862315708145274237317043567981e+308 // 2**1023 * (2**53 - 1) / 2**52
+	SmallestNonzeroFloat64 = 4.940656458412465441765687928682213723651e-324 // 1 / 2**(1023 - 1 + 52)
+)
+
+// Integer limit values.
+const (
+	MaxInt8   = 1<<7 - 1
+	MinInt8   = -1 << 7
+	MaxInt16  = 1<<15 - 1
+	MinInt16  = -1 << 15
+	MaxInt32  = 1<<31 - 1
+	MinInt32  = -1 << 31
+	MaxInt64  = 1<<63 - 1
+	MinInt64  = -1 << 63
+	MaxUint8  = 1<<8 - 1
+	MaxUint16 = 1<<16 - 1
+	MaxUint32 = 1<<32 - 1
+	MaxUint64 = 1<<64 - 1
+)
diff --git a/third_party/gofrontend/libgo/go/math/copysign.go b/third_party/gofrontend/libgo/go/math/copysign.go
new file mode 100644
index 0000000..719c64b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/copysign.go
@@ -0,0 +1,12 @@
+// Copyright 2010 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 math
+
+// Copysign returns a value with the magnitude
+// of x and the sign of y.
+func Copysign(x, y float64) float64 {
+	const sign = 1 << 63
+	return Float64frombits(Float64bits(x)&^sign | Float64bits(y)&sign)
+}
diff --git a/third_party/gofrontend/libgo/go/math/dim.go b/third_party/gofrontend/libgo/go/math/dim.go
new file mode 100644
index 0000000..37ab538
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/dim.go
@@ -0,0 +1,78 @@
+// Copyright 2010 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 math
+
+// Dim returns the maximum of x-y or 0.
+//
+// Special cases are:
+//	Dim(+Inf, +Inf) = NaN
+//	Dim(-Inf, -Inf) = NaN
+//	Dim(x, NaN) = Dim(NaN, x) = NaN
+func Dim(x, y float64) float64 {
+	return dim(x, y)
+}
+
+func dim(x, y float64) float64 {
+	return max(x-y, 0)
+}
+
+// Max returns the larger of x or y.
+//
+// Special cases are:
+//	Max(x, +Inf) = Max(+Inf, x) = +Inf
+//	Max(x, NaN) = Max(NaN, x) = NaN
+//	Max(+0, ±0) = Max(±0, +0) = +0
+//	Max(-0, -0) = -0
+func Max(x, y float64) float64 {
+	return max(x, y)
+}
+
+func max(x, y float64) float64 {
+	// special cases
+	switch {
+	case IsInf(x, 1) || IsInf(y, 1):
+		return Inf(1)
+	case IsNaN(x) || IsNaN(y):
+		return NaN()
+	case x == 0 && x == y:
+		if Signbit(x) {
+			return y
+		}
+		return x
+	}
+	if x > y {
+		return x
+	}
+	return y
+}
+
+// Min returns the smaller of x or y.
+//
+// Special cases are:
+//	Min(x, -Inf) = Min(-Inf, x) = -Inf
+//	Min(x, NaN) = Min(NaN, x) = NaN
+//	Min(-0, ±0) = Min(±0, -0) = -0
+func Min(x, y float64) float64 {
+	return min(x, y)
+}
+
+func min(x, y float64) float64 {
+	// special cases
+	switch {
+	case IsInf(x, -1) || IsInf(y, -1):
+		return Inf(-1)
+	case IsNaN(x) || IsNaN(y):
+		return NaN()
+	case x == 0 && x == y:
+		if Signbit(x) {
+			return x
+		}
+		return y
+	}
+	if x < y {
+		return x
+	}
+	return y
+}
diff --git a/third_party/gofrontend/libgo/go/math/erf.go b/third_party/gofrontend/libgo/go/math/erf.go
new file mode 100644
index 0000000..4cd80f8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/erf.go
@@ -0,0 +1,335 @@
+// Copyright 2010 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 math
+
+/*
+	Floating-point error function and complementary error function.
+*/
+
+// The original C code and the long comment below are
+// from FreeBSD's /usr/src/lib/msun/src/s_erf.c and
+// came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+//
+// double erf(double x)
+// double erfc(double x)
+//                           x
+//                    2      |\
+//     erf(x)  =  ---------  | exp(-t*t)dt
+//                 sqrt(pi) \|
+//                           0
+//
+//     erfc(x) =  1-erf(x)
+//  Note that
+//              erf(-x) = -erf(x)
+//              erfc(-x) = 2 - erfc(x)
+//
+// Method:
+//      1. For |x| in [0, 0.84375]
+//          erf(x)  = x + x*R(x**2)
+//          erfc(x) = 1 - erf(x)           if x in [-.84375,0.25]
+//                  = 0.5 + ((0.5-x)-x*R)  if x in [0.25,0.84375]
+//         where R = P/Q where P is an odd poly of degree 8 and
+//         Q is an odd poly of degree 10.
+//                                               -57.90
+//                      | R - (erf(x)-x)/x | <= 2
+//
+//
+//         Remark. The formula is derived by noting
+//          erf(x) = (2/sqrt(pi))*(x - x**3/3 + x**5/10 - x**7/42 + ....)
+//         and that
+//          2/sqrt(pi) = 1.128379167095512573896158903121545171688
+//         is close to one. The interval is chosen because the fix
+//         point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
+//         near 0.6174), and by some experiment, 0.84375 is chosen to
+//         guarantee the error is less than one ulp for erf.
+//
+//      2. For |x| in [0.84375,1.25], let s = |x| - 1, and
+//         c = 0.84506291151 rounded to single (24 bits)
+//              erf(x)  = sign(x) * (c  + P1(s)/Q1(s))
+//              erfc(x) = (1-c)  - P1(s)/Q1(s) if x > 0
+//                        1+(c+P1(s)/Q1(s))    if x < 0
+//              |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06
+//         Remark: here we use the taylor series expansion at x=1.
+//              erf(1+s) = erf(1) + s*Poly(s)
+//                       = 0.845.. + P1(s)/Q1(s)
+//         That is, we use rational approximation to approximate
+//                      erf(1+s) - (c = (single)0.84506291151)
+//         Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+//         where
+//              P1(s) = degree 6 poly in s
+//              Q1(s) = degree 6 poly in s
+//
+//      3. For x in [1.25,1/0.35(~2.857143)],
+//              erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
+//              erf(x)  = 1 - erfc(x)
+//         where
+//              R1(z) = degree 7 poly in z, (z=1/x**2)
+//              S1(z) = degree 8 poly in z
+//
+//      4. For x in [1/0.35,28]
+//              erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
+//                      = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0
+//                      = 2.0 - tiny            (if x <= -6)
+//              erf(x)  = sign(x)*(1.0 - erfc(x)) if x < 6, else
+//              erf(x)  = sign(x)*(1.0 - tiny)
+//         where
+//              R2(z) = degree 6 poly in z, (z=1/x**2)
+//              S2(z) = degree 7 poly in z
+//
+//      Note1:
+//         To compute exp(-x*x-0.5625+R/S), let s be a single
+//         precision number and s := x; then
+//              -x*x = -s*s + (s-x)*(s+x)
+//              exp(-x*x-0.5626+R/S) =
+//                      exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+//      Note2:
+//         Here 4 and 5 make use of the asymptotic series
+//                        exp(-x*x)
+//              erfc(x) ~ ---------- * ( 1 + Poly(1/x**2) )
+//                        x*sqrt(pi)
+//         We use rational approximation to approximate
+//              g(s)=f(1/x**2) = log(erfc(x)*x) - x*x + 0.5625
+//         Here is the error bound for R1/S1 and R2/S2
+//              |R1/S1 - f(x)|  < 2**(-62.57)
+//              |R2/S2 - f(x)|  < 2**(-61.52)
+//
+//      5. For inf > x >= 28
+//              erf(x)  = sign(x) *(1 - tiny)  (raise inexact)
+//              erfc(x) = tiny*tiny (raise underflow) if x > 0
+//                      = 2 - tiny if x<0
+//
+//      7. Special case:
+//              erf(0)  = 0, erf(inf)  = 1, erf(-inf) = -1,
+//              erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+//              erfc/erf(NaN) is NaN
+
+const (
+	erx = 8.45062911510467529297e-01 // 0x3FEB0AC160000000
+	// Coefficients for approximation to  erf in [0, 0.84375]
+	efx  = 1.28379167095512586316e-01  // 0x3FC06EBA8214DB69
+	efx8 = 1.02703333676410069053e+00  // 0x3FF06EBA8214DB69
+	pp0  = 1.28379167095512558561e-01  // 0x3FC06EBA8214DB68
+	pp1  = -3.25042107247001499370e-01 // 0xBFD4CD7D691CB913
+	pp2  = -2.84817495755985104766e-02 // 0xBF9D2A51DBD7194F
+	pp3  = -5.77027029648944159157e-03 // 0xBF77A291236668E4
+	pp4  = -2.37630166566501626084e-05 // 0xBEF8EAD6120016AC
+	qq1  = 3.97917223959155352819e-01  // 0x3FD97779CDDADC09
+	qq2  = 6.50222499887672944485e-02  // 0x3FB0A54C5536CEBA
+	qq3  = 5.08130628187576562776e-03  // 0x3F74D022C4D36B0F
+	qq4  = 1.32494738004321644526e-04  // 0x3F215DC9221C1A10
+	qq5  = -3.96022827877536812320e-06 // 0xBED09C4342A26120
+	// Coefficients for approximation to  erf  in [0.84375, 1.25]
+	pa0 = -2.36211856075265944077e-03 // 0xBF6359B8BEF77538
+	pa1 = 4.14856118683748331666e-01  // 0x3FDA8D00AD92B34D
+	pa2 = -3.72207876035701323847e-01 // 0xBFD7D240FBB8C3F1
+	pa3 = 3.18346619901161753674e-01  // 0x3FD45FCA805120E4
+	pa4 = -1.10894694282396677476e-01 // 0xBFBC63983D3E28EC
+	pa5 = 3.54783043256182359371e-02  // 0x3FA22A36599795EB
+	pa6 = -2.16637559486879084300e-03 // 0xBF61BF380A96073F
+	qa1 = 1.06420880400844228286e-01  // 0x3FBB3E6618EEE323
+	qa2 = 5.40397917702171048937e-01  // 0x3FE14AF092EB6F33
+	qa3 = 7.18286544141962662868e-02  // 0x3FB2635CD99FE9A7
+	qa4 = 1.26171219808761642112e-01  // 0x3FC02660E763351F
+	qa5 = 1.36370839120290507362e-02  // 0x3F8BEDC26B51DD1C
+	qa6 = 1.19844998467991074170e-02  // 0x3F888B545735151D
+	// Coefficients for approximation to  erfc in [1.25, 1/0.35]
+	ra0 = -9.86494403484714822705e-03 // 0xBF843412600D6435
+	ra1 = -6.93858572707181764372e-01 // 0xBFE63416E4BA7360
+	ra2 = -1.05586262253232909814e+01 // 0xC0251E0441B0E726
+	ra3 = -6.23753324503260060396e+01 // 0xC04F300AE4CBA38D
+	ra4 = -1.62396669462573470355e+02 // 0xC0644CB184282266
+	ra5 = -1.84605092906711035994e+02 // 0xC067135CEBCCABB2
+	ra6 = -8.12874355063065934246e+01 // 0xC054526557E4D2F2
+	ra7 = -9.81432934416914548592e+00 // 0xC023A0EFC69AC25C
+	sa1 = 1.96512716674392571292e+01  // 0x4033A6B9BD707687
+	sa2 = 1.37657754143519042600e+02  // 0x4061350C526AE721
+	sa3 = 4.34565877475229228821e+02  // 0x407B290DD58A1A71
+	sa4 = 6.45387271733267880336e+02  // 0x40842B1921EC2868
+	sa5 = 4.29008140027567833386e+02  // 0x407AD02157700314
+	sa6 = 1.08635005541779435134e+02  // 0x405B28A3EE48AE2C
+	sa7 = 6.57024977031928170135e+00  // 0x401A47EF8E484A93
+	sa8 = -6.04244152148580987438e-02 // 0xBFAEEFF2EE749A62
+	// Coefficients for approximation to  erfc in [1/.35, 28]
+	rb0 = -9.86494292470009928597e-03 // 0xBF84341239E86F4A
+	rb1 = -7.99283237680523006574e-01 // 0xBFE993BA70C285DE
+	rb2 = -1.77579549177547519889e+01 // 0xC031C209555F995A
+	rb3 = -1.60636384855821916062e+02 // 0xC064145D43C5ED98
+	rb4 = -6.37566443368389627722e+02 // 0xC083EC881375F228
+	rb5 = -1.02509513161107724954e+03 // 0xC09004616A2E5992
+	rb6 = -4.83519191608651397019e+02 // 0xC07E384E9BDC383F
+	sb1 = 3.03380607434824582924e+01  // 0x403E568B261D5190
+	sb2 = 3.25792512996573918826e+02  // 0x40745CAE221B9F0A
+	sb3 = 1.53672958608443695994e+03  // 0x409802EB189D5118
+	sb4 = 3.19985821950859553908e+03  // 0x40A8FFB7688C246A
+	sb5 = 2.55305040643316442583e+03  // 0x40A3F219CEDF3BE6
+	sb6 = 4.74528541206955367215e+02  // 0x407DA874E79FE763
+	sb7 = -2.24409524465858183362e+01 // 0xC03670E242712D62
+)
+
+// Erf returns the error function of x.
+//
+// Special cases are:
+//	Erf(+Inf) = 1
+//	Erf(-Inf) = -1
+//	Erf(NaN) = NaN
+func Erf(x float64) float64 {
+	const (
+		VeryTiny = 2.848094538889218e-306 // 0x0080000000000000
+		Small    = 1.0 / (1 << 28)        // 2**-28
+	)
+	// special cases
+	switch {
+	case IsNaN(x):
+		return NaN()
+	case IsInf(x, 1):
+		return 1
+	case IsInf(x, -1):
+		return -1
+	}
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+	if x < 0.84375 { // |x| < 0.84375
+		var temp float64
+		if x < Small { // |x| < 2**-28
+			if x < VeryTiny {
+				temp = 0.125 * (8.0*x + efx8*x) // avoid underflow
+			} else {
+				temp = x + efx*x
+			}
+		} else {
+			z := x * x
+			r := pp0 + z*(pp1+z*(pp2+z*(pp3+z*pp4)))
+			s := 1 + z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))))
+			y := r / s
+			temp = x + x*y
+		}
+		if sign {
+			return -temp
+		}
+		return temp
+	}
+	if x < 1.25 { // 0.84375 <= |x| < 1.25
+		s := x - 1
+		P := pa0 + s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))))
+		Q := 1 + s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))))
+		if sign {
+			return -erx - P/Q
+		}
+		return erx + P/Q
+	}
+	if x >= 6 { // inf > |x| >= 6
+		if sign {
+			return -1
+		}
+		return 1
+	}
+	s := 1 / (x * x)
+	var R, S float64
+	if x < 1/0.35 { // |x| < 1 / 0.35  ~ 2.857143
+		R = ra0 + s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*ra7))))))
+		S = 1 + s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+s*sa8)))))))
+	} else { // |x| >= 1 / 0.35  ~ 2.857143
+		R = rb0 + s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6)))))
+		S = 1 + s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))))
+	}
+	z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precision x
+	r := Exp(-z*z-0.5625) * Exp((z-x)*(z+x)+R/S)
+	if sign {
+		return r/x - 1
+	}
+	return 1 - r/x
+}
+
+// Erfc returns the complementary error function of x.
+//
+// Special cases are:
+//	Erfc(+Inf) = 0
+//	Erfc(-Inf) = 2
+//	Erfc(NaN) = NaN
+func Erfc(x float64) float64 {
+	const Tiny = 1.0 / (1 << 56) // 2**-56
+	// special cases
+	switch {
+	case IsNaN(x):
+		return NaN()
+	case IsInf(x, 1):
+		return 0
+	case IsInf(x, -1):
+		return 2
+	}
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+	if x < 0.84375 { // |x| < 0.84375
+		var temp float64
+		if x < Tiny { // |x| < 2**-56
+			temp = x
+		} else {
+			z := x * x
+			r := pp0 + z*(pp1+z*(pp2+z*(pp3+z*pp4)))
+			s := 1 + z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))))
+			y := r / s
+			if x < 0.25 { // |x| < 1/4
+				temp = x + x*y
+			} else {
+				temp = 0.5 + (x*y + (x - 0.5))
+			}
+		}
+		if sign {
+			return 1 + temp
+		}
+		return 1 - temp
+	}
+	if x < 1.25 { // 0.84375 <= |x| < 1.25
+		s := x - 1
+		P := pa0 + s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))))
+		Q := 1 + s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))))
+		if sign {
+			return 1 + erx + P/Q
+		}
+		return 1 - erx - P/Q
+
+	}
+	if x < 28 { // |x| < 28
+		s := 1 / (x * x)
+		var R, S float64
+		if x < 1/0.35 { // |x| < 1 / 0.35 ~ 2.857143
+			R = ra0 + s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*ra7))))))
+			S = 1 + s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+s*sa8)))))))
+		} else { // |x| >= 1 / 0.35 ~ 2.857143
+			if sign && x > 6 {
+				return 2 // x < -6
+			}
+			R = rb0 + s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6)))))
+			S = 1 + s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))))
+		}
+		z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precision x
+		r := Exp(-z*z-0.5625) * Exp((z-x)*(z+x)+R/S)
+		if sign {
+			return 2 - r/x
+		}
+		return r / x
+	}
+	if sign {
+		return 2
+	}
+	return 0
+}
diff --git a/third_party/gofrontend/libgo/go/math/exp.go b/third_party/gofrontend/libgo/go/math/exp.go
new file mode 100644
index 0000000..51330c2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/exp.go
@@ -0,0 +1,199 @@
+// 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 math
+
+// Exp returns e**x, the base-e exponential of x.
+//
+// Special cases are:
+//	Exp(+Inf) = +Inf
+//	Exp(NaN) = NaN
+// Very large values overflow to 0 or +Inf.
+// Very small values underflow to 1.
+
+//extern exp
+func libc_exp(float64) float64
+
+func Exp(x float64) float64 {
+	return libc_exp(x)
+}
+
+// The original C code, the long comment, and the constants
+// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c
+// and came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+//
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+//
+// exp(x)
+// Returns the exponential of x.
+//
+// Method
+//   1. Argument reduction:
+//      Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+//      Given x, find r and integer k such that
+//
+//               x = k*ln2 + r,  |r| <= 0.5*ln2.
+//
+//      Here r will be represented as r = hi-lo for better
+//      accuracy.
+//
+//   2. Approximation of exp(r) by a special rational function on
+//      the interval [0,0.34658]:
+//      Write
+//          R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+//      We use a special Remes algorithm on [0,0.34658] to generate
+//      a polynomial of degree 5 to approximate R. The maximum error
+//      of this polynomial approximation is bounded by 2**-59. In
+//      other words,
+//          R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+//      (where z=r*r, and the values of P1 to P5 are listed below)
+//      and
+//          |                  5          |     -59
+//          | 2.0+P1*z+...+P5*z   -  R(z) | <= 2
+//          |                             |
+//      The computation of exp(r) thus becomes
+//                             2*r
+//              exp(r) = 1 + -------
+//                            R - r
+//                                 r*R1(r)
+//                     = 1 + r + ----------- (for better accuracy)
+//                                2 - R1(r)
+//      where
+//                               2       4             10
+//              R1(r) = r - (P1*r  + P2*r  + ... + P5*r   ).
+//
+//   3. Scale back to obtain exp(x):
+//      From step 1, we have
+//         exp(x) = 2**k * exp(r)
+//
+// Special cases:
+//      exp(INF) is INF, exp(NaN) is NaN;
+//      exp(-INF) is 0, and
+//      for finite argument, only exp(0)=1 is exact.
+//
+// Accuracy:
+//      according to an error analysis, the error is always less than
+//      1 ulp (unit in the last place).
+//
+// Misc. info.
+//      For IEEE double
+//          if x >  7.09782712893383973096e+02 then exp(x) overflow
+//          if x < -7.45133219101941108420e+02 then exp(x) underflow
+//
+// Constants:
+// The hexadecimal values are the intended ones for the following
+// constants. The decimal values may be used, provided that the
+// compiler will convert from decimal to binary accurately enough
+// to produce the hexadecimal values shown.
+
+func exp(x float64) float64 {
+	const (
+		Ln2Hi = 6.93147180369123816490e-01
+		Ln2Lo = 1.90821492927058770002e-10
+		Log2e = 1.44269504088896338700e+00
+
+		Overflow  = 7.09782712893383973096e+02
+		Underflow = -7.45133219101941108420e+02
+		NearZero  = 1.0 / (1 << 28) // 2**-28
+	)
+
+	// special cases
+	switch {
+	case IsNaN(x) || IsInf(x, 1):
+		return x
+	case IsInf(x, -1):
+		return 0
+	case x > Overflow:
+		return Inf(1)
+	case x < Underflow:
+		return 0
+	case -NearZero < x && x < NearZero:
+		return 1 + x
+	}
+
+	// reduce; computed as r = hi - lo for extra precision.
+	var k int
+	switch {
+	case x < 0:
+		k = int(Log2e*x - 0.5)
+	case x > 0:
+		k = int(Log2e*x + 0.5)
+	}
+	hi := x - float64(k)*Ln2Hi
+	lo := float64(k) * Ln2Lo
+
+	// compute
+	return expmulti(hi, lo, k)
+}
+
+// Exp2 returns 2**x, the base-2 exponential of x.
+//
+// Special cases are the same as Exp.
+func Exp2(x float64) float64 {
+	return exp2(x)
+}
+
+func exp2(x float64) float64 {
+	const (
+		Ln2Hi = 6.93147180369123816490e-01
+		Ln2Lo = 1.90821492927058770002e-10
+
+		Overflow  = 1.0239999999999999e+03
+		Underflow = -1.0740e+03
+	)
+
+	// special cases
+	switch {
+	case IsNaN(x) || IsInf(x, 1):
+		return x
+	case IsInf(x, -1):
+		return 0
+	case x > Overflow:
+		return Inf(1)
+	case x < Underflow:
+		return 0
+	}
+
+	// argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2.
+	// computed as r = hi - lo for extra precision.
+	var k int
+	switch {
+	case x > 0:
+		k = int(x + 0.5)
+	case x < 0:
+		k = int(x - 0.5)
+	}
+	t := x - float64(k)
+	hi := t * Ln2Hi
+	lo := -t * Ln2Lo
+
+	// compute
+	return expmulti(hi, lo, k)
+}
+
+// exp1 returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2.
+func expmulti(hi, lo float64, k int) float64 {
+	const (
+		P1 = 1.66666666666666019037e-01  /* 0x3FC55555; 0x5555553E */
+		P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */
+		P3 = 6.61375632143793436117e-05  /* 0x3F11566A; 0xAF25DE2C */
+		P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */
+		P5 = 4.13813679705723846039e-08  /* 0x3E663769; 0x72BEA4D0 */
+	)
+
+	r := hi - lo
+	t := r * r
+	c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
+	y := 1 - ((lo - (r*c)/(2-c)) - hi)
+	// TODO(rsc): make sure Ldexp can handle boundary k
+	return Ldexp(y, k)
+}
diff --git a/third_party/gofrontend/libgo/go/math/expm1.go b/third_party/gofrontend/libgo/go/math/expm1.go
new file mode 100644
index 0000000..f7e15db
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/expm1.go
@@ -0,0 +1,243 @@
+// Copyright 2010 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 math
+
+// The original C code, the long comment, and the constants
+// below are from FreeBSD's /usr/src/lib/msun/src/s_expm1.c
+// and came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// expm1(x)
+// Returns exp(x)-1, the exponential of x minus 1.
+//
+// Method
+//   1. Argument reduction:
+//      Given x, find r and integer k such that
+//
+//               x = k*ln2 + r,  |r| <= 0.5*ln2 ~ 0.34658
+//
+//      Here a correction term c will be computed to compensate
+//      the error in r when rounded to a floating-point number.
+//
+//   2. Approximating expm1(r) by a special rational function on
+//      the interval [0,0.34658]:
+//      Since
+//          r*(exp(r)+1)/(exp(r)-1) = 2+ r**2/6 - r**4/360 + ...
+//      we define R1(r*r) by
+//          r*(exp(r)+1)/(exp(r)-1) = 2+ r**2/6 * R1(r*r)
+//      That is,
+//          R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
+//                   = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
+//                   = 1 - r**2/60 + r**4/2520 - r**6/100800 + ...
+//      We use a special Reme algorithm on [0,0.347] to generate
+//      a polynomial of degree 5 in r*r to approximate R1. The
+//      maximum error of this polynomial approximation is bounded
+//      by 2**-61. In other words,
+//          R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
+//      where   Q1  =  -1.6666666666666567384E-2,
+//              Q2  =   3.9682539681370365873E-4,
+//              Q3  =  -9.9206344733435987357E-6,
+//              Q4  =   2.5051361420808517002E-7,
+//              Q5  =  -6.2843505682382617102E-9;
+//      (where z=r*r, and the values of Q1 to Q5 are listed below)
+//      with error bounded by
+//          |                  5           |     -61
+//          | 1.0+Q1*z+...+Q5*z   -  R1(z) | <= 2
+//          |                              |
+//
+//      expm1(r) = exp(r)-1 is then computed by the following
+//      specific way which minimize the accumulation rounding error:
+//                             2     3
+//                            r     r    [ 3 - (R1 + R1*r/2)  ]
+//            expm1(r) = r + --- + --- * [--------------------]
+//                            2     2    [ 6 - r*(3 - R1*r/2) ]
+//
+//      To compensate the error in the argument reduction, we use
+//              expm1(r+c) = expm1(r) + c + expm1(r)*c
+//                         ~ expm1(r) + c + r*c
+//      Thus c+r*c will be added in as the correction terms for
+//      expm1(r+c). Now rearrange the term to avoid optimization
+//      screw up:
+//                      (      2                                    2 )
+//                      ({  ( r    [ R1 -  (3 - R1*r/2) ]  )  }    r  )
+//       expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
+//                      ({  ( 2    [ 6 - r*(3 - R1*r/2) ]  )  }    2  )
+//                      (                                             )
+//
+//                 = r - E
+//   3. Scale back to obtain expm1(x):
+//      From step 1, we have
+//         expm1(x) = either 2**k*[expm1(r)+1] - 1
+//                  = or     2**k*[expm1(r) + (1-2**-k)]
+//   4. Implementation notes:
+//      (A). To save one multiplication, we scale the coefficient Qi
+//           to Qi*2**i, and replace z by (x**2)/2.
+//      (B). To achieve maximum accuracy, we compute expm1(x) by
+//        (i)   if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
+//        (ii)  if k=0, return r-E
+//        (iii) if k=-1, return 0.5*(r-E)-0.5
+//        (iv)  if k=1 if r < -0.25, return 2*((r+0.5)- E)
+//                     else          return  1.0+2.0*(r-E);
+//        (v)   if (k<-2||k>56) return 2**k(1-(E-r)) - 1 (or exp(x)-1)
+//        (vi)  if k <= 20, return 2**k((1-2**-k)-(E-r)), else
+//        (vii) return 2**k(1-((E+2**-k)-r))
+//
+// Special cases:
+//      expm1(INF) is INF, expm1(NaN) is NaN;
+//      expm1(-INF) is -1, and
+//      for finite argument, only expm1(0)=0 is exact.
+//
+// Accuracy:
+//      according to an error analysis, the error is always less than
+//      1 ulp (unit in the last place).
+//
+// Misc. info.
+//      For IEEE double
+//          if x >  7.09782712893383973096e+02 then expm1(x) overflow
+//
+// Constants:
+// The hexadecimal values are the intended ones for the following
+// constants. The decimal values may be used, provided that the
+// compiler will convert from decimal to binary accurately enough
+// to produce the hexadecimal values shown.
+//
+
+// Expm1 returns e**x - 1, the base-e exponential of x minus 1.
+// It is more accurate than Exp(x) - 1 when x is near zero.
+//
+// Special cases are:
+//	Expm1(+Inf) = +Inf
+//	Expm1(-Inf) = -1
+//	Expm1(NaN) = NaN
+// Very large values overflow to -1 or +Inf.
+
+//extern expm1
+func libc_expm1(float64) float64
+
+func Expm1(x float64) float64 {
+	return libc_expm1(x)
+}
+
+func expm1(x float64) float64 {
+	const (
+		Othreshold = 7.09782712893383973096e+02 // 0x40862E42FEFA39EF
+		Ln2X56     = 3.88162421113569373274e+01 // 0x4043687a9f1af2b1
+		Ln2HalfX3  = 1.03972077083991796413e+00 // 0x3ff0a2b23f3bab73
+		Ln2Half    = 3.46573590279972654709e-01 // 0x3fd62e42fefa39ef
+		Ln2Hi      = 6.93147180369123816490e-01 // 0x3fe62e42fee00000
+		Ln2Lo      = 1.90821492927058770002e-10 // 0x3dea39ef35793c76
+		InvLn2     = 1.44269504088896338700e+00 // 0x3ff71547652b82fe
+		Tiny       = 1.0 / (1 << 54)            // 2**-54 = 0x3c90000000000000
+		// scaled coefficients related to expm1
+		Q1 = -3.33333333333331316428e-02 // 0xBFA11111111110F4
+		Q2 = 1.58730158725481460165e-03  // 0x3F5A01A019FE5585
+		Q3 = -7.93650757867487942473e-05 // 0xBF14CE199EAADBB7
+		Q4 = 4.00821782732936239552e-06  // 0x3ED0CFCA86E65239
+		Q5 = -2.01099218183624371326e-07 // 0xBE8AFDB76E09C32D
+	)
+
+	// special cases
+	switch {
+	case IsInf(x, 1) || IsNaN(x):
+		return x
+	case IsInf(x, -1):
+		return -1
+	}
+
+	absx := x
+	sign := false
+	if x < 0 {
+		absx = -absx
+		sign = true
+	}
+
+	// filter out huge argument
+	if absx >= Ln2X56 { // if |x| >= 56 * ln2
+		if absx >= Othreshold { // if |x| >= 709.78...
+			return Inf(1) // overflow
+		}
+		if sign {
+			return -1 // x < -56*ln2, return -1.0
+		}
+	}
+
+	// argument reduction
+	var c float64
+	var k int
+	if absx > Ln2Half { // if  |x| > 0.5 * ln2
+		var hi, lo float64
+		if absx < Ln2HalfX3 { // and |x| < 1.5 * ln2
+			if !sign {
+				hi = x - Ln2Hi
+				lo = Ln2Lo
+				k = 1
+			} else {
+				hi = x + Ln2Hi
+				lo = -Ln2Lo
+				k = -1
+			}
+		} else {
+			if !sign {
+				k = int(InvLn2*x + 0.5)
+			} else {
+				k = int(InvLn2*x - 0.5)
+			}
+			t := float64(k)
+			hi = x - t*Ln2Hi // t * Ln2Hi is exact here
+			lo = t * Ln2Lo
+		}
+		x = hi - lo
+		c = (hi - x) - lo
+	} else if absx < Tiny { // when |x| < 2**-54, return x
+		return x
+	} else {
+		k = 0
+	}
+
+	// x is now in primary range
+	hfx := 0.5 * x
+	hxs := x * hfx
+	r1 := 1 + hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))))
+	t := 3 - r1*hfx
+	e := hxs * ((r1 - t) / (6.0 - x*t))
+	if k != 0 {
+		e = (x*(e-c) - c)
+		e -= hxs
+		switch {
+		case k == -1:
+			return 0.5*(x-e) - 0.5
+		case k == 1:
+			if x < -0.25 {
+				return -2 * (e - (x + 0.5))
+			}
+			return 1 + 2*(x-e)
+		case k <= -2 || k > 56: // suffice to return exp(x)-1
+			y := 1 - (e - x)
+			y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent
+			return y - 1
+		}
+		if k < 20 {
+			t := Float64frombits(0x3ff0000000000000 - (0x20000000000000 >> uint(k))) // t=1-2**-k
+			y := t - (e - x)
+			y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent
+			return y
+		}
+		t := Float64frombits(uint64((0x3ff - k) << 52)) // 2**-k
+		y := x - (e + t)
+		y += 1
+		y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent
+		return y
+	}
+	return x - (x*e - hxs) // c is 0
+}
diff --git a/third_party/gofrontend/libgo/go/math/export_test.go b/third_party/gofrontend/libgo/go/math/export_test.go
new file mode 100644
index 0000000..02992d7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/export_test.go
@@ -0,0 +1,11 @@
+// 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.
+
+package math
+
+// Export internal functions for testing.
+var ExpGo = exp
+var Exp2Go = exp2
+var HypotGo = hypot
+var SqrtGo = sqrt
diff --git a/third_party/gofrontend/libgo/go/math/floor.go b/third_party/gofrontend/libgo/go/math/floor.go
new file mode 100644
index 0000000..c40be41
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/floor.go
@@ -0,0 +1,71 @@
+// Copyright 2009-2010 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 math
+
+// Floor returns the greatest integer value less than or equal to x.
+//
+// Special cases are:
+//	Floor(±0) = ±0
+//	Floor(±Inf) = ±Inf
+//	Floor(NaN) = NaN
+
+//extern floor
+func libc_floor(float64) float64
+
+func Floor(x float64) float64 {
+	return libc_floor(x)
+}
+
+func floor(x float64) float64 {
+	if x == 0 || IsNaN(x) || IsInf(x, 0) {
+		return x
+	}
+	if x < 0 {
+		d, fract := Modf(-x)
+		if fract != 0.0 {
+			d = d + 1
+		}
+		return -d
+	}
+	d, _ := Modf(x)
+	return d
+}
+
+// Ceil returns the least integer value greater than or equal to x.
+//
+// Special cases are:
+//	Ceil(±0) = ±0
+//	Ceil(±Inf) = ±Inf
+//	Ceil(NaN) = NaN
+
+//extern ceil
+func libc_ceil(float64) float64
+
+func Ceil(x float64) float64 {
+	return libc_ceil(x)
+}
+
+func ceil(x float64) float64 {
+	return -Floor(-x)
+}
+
+// Trunc returns the integer value of x.
+//
+// Special cases are:
+//	Trunc(±0) = ±0
+//	Trunc(±Inf) = ±Inf
+//	Trunc(NaN) = NaN
+
+func Trunc(x float64) float64 {
+	return trunc(x)
+}
+
+func trunc(x float64) float64 {
+	if x == 0 || IsNaN(x) || IsInf(x, 0) {
+		return x
+	}
+	d, _ := Modf(x)
+	return d
+}
diff --git a/third_party/gofrontend/libgo/go/math/frexp.go b/third_party/gofrontend/libgo/go/math/frexp.go
new file mode 100644
index 0000000..4ad0aee
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/frexp.go
@@ -0,0 +1,35 @@
+// 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 math
+
+// Frexp breaks f into a normalized fraction
+// and an integral power of two.
+// It returns frac and exp satisfying f == frac × 2**exp,
+// with the absolute value of frac in the interval [½, 1).
+//
+// Special cases are:
+//	Frexp(±0) = ±0, 0
+//	Frexp(±Inf) = ±Inf, 0
+//	Frexp(NaN) = NaN, 0
+func Frexp(f float64) (frac float64, exp int) {
+	return frexp(f)
+}
+
+func frexp(f float64) (frac float64, exp int) {
+	// special cases
+	switch {
+	case f == 0:
+		return f, 0 // correctly return -0
+	case IsInf(f, 0) || IsNaN(f):
+		return f, 0
+	}
+	f, exp = normalize(f)
+	x := Float64bits(f)
+	exp += int((x>>shift)&mask) - bias + 1
+	x &^= mask << shift
+	x |= (-1 + bias) << shift
+	frac = Float64frombits(x)
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/math/gamma.go b/third_party/gofrontend/libgo/go/math/gamma.go
new file mode 100644
index 0000000..164f54f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/gamma.go
@@ -0,0 +1,202 @@
+// Copyright 2010 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 math
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/cprob/gamma.c.
+// The go code is a simplified version of the original C.
+//
+//      tgamma.c
+//
+//      Gamma function
+//
+// SYNOPSIS:
+//
+// double x, y, tgamma();
+// extern int signgam;
+//
+// y = tgamma( x );
+//
+// DESCRIPTION:
+//
+// Returns gamma function of the argument.  The result is
+// correctly signed, and the sign (+1 or -1) is also
+// returned in a global (extern) variable named signgam.
+// This variable is also filled in by the logarithmic gamma
+// function lgamma().
+//
+// Arguments |x| <= 34 are reduced by recurrence and the function
+// approximated by a rational function of degree 6/7 in the
+// interval (2,3).  Large arguments are handled by Stirling's
+// formula. Large negative arguments are made positive using
+// a reflection formula.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC      -34, 34      10000       1.3e-16     2.5e-17
+//    IEEE    -170,-33      20000       2.3e-15     3.3e-16
+//    IEEE     -33,  33     20000       9.4e-16     2.2e-16
+//    IEEE      33, 171.6   20000       2.3e-15     3.2e-16
+//
+// Error for arguments outside the test range will be larger
+// owing to error amplification by the exponential function.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+var _gamP = [...]float64{
+	1.60119522476751861407e-04,
+	1.19135147006586384913e-03,
+	1.04213797561761569935e-02,
+	4.76367800457137231464e-02,
+	2.07448227648435975150e-01,
+	4.94214826801497100753e-01,
+	9.99999999999999996796e-01,
+}
+var _gamQ = [...]float64{
+	-2.31581873324120129819e-05,
+	5.39605580493303397842e-04,
+	-4.45641913851797240494e-03,
+	1.18139785222060435552e-02,
+	3.58236398605498653373e-02,
+	-2.34591795718243348568e-01,
+	7.14304917030273074085e-02,
+	1.00000000000000000320e+00,
+}
+var _gamS = [...]float64{
+	7.87311395793093628397e-04,
+	-2.29549961613378126380e-04,
+	-2.68132617805781232825e-03,
+	3.47222221605458667310e-03,
+	8.33333333333482257126e-02,
+}
+
+// Gamma function computed by Stirling's formula.
+// The polynomial is valid for 33 <= x <= 172.
+func stirling(x float64) float64 {
+	const (
+		SqrtTwoPi   = 2.506628274631000502417
+		MaxStirling = 143.01608
+	)
+	w := 1 / x
+	w = 1 + w*((((_gamS[0]*w+_gamS[1])*w+_gamS[2])*w+_gamS[3])*w+_gamS[4])
+	y := Exp(x)
+	if x > MaxStirling { // avoid Pow() overflow
+		v := Pow(x, 0.5*x-0.25)
+		y = v * (v / y)
+	} else {
+		y = Pow(x, x-0.5) / y
+	}
+	y = SqrtTwoPi * y * w
+	return y
+}
+
+// Gamma returns the Gamma function of x.
+//
+// Special cases are:
+//	Gamma(+Inf) = +Inf
+//	Gamma(+0) = +Inf
+//	Gamma(-0) = -Inf
+//	Gamma(x) = NaN for integer x < 0
+//	Gamma(-Inf) = NaN
+//	Gamma(NaN) = NaN
+func Gamma(x float64) float64 {
+	const Euler = 0.57721566490153286060651209008240243104215933593992 // A001620
+	// special cases
+	switch {
+	case isNegInt(x) || IsInf(x, -1) || IsNaN(x):
+		return NaN()
+	case x == 0:
+		if Signbit(x) {
+			return Inf(-1)
+		}
+		return Inf(1)
+	case x < -170.5674972726612 || x > 171.61447887182298:
+		return Inf(1)
+	}
+	q := Abs(x)
+	p := Floor(q)
+	if q > 33 {
+		if x >= 0 {
+			return stirling(x)
+		}
+		signgam := 1
+		if ip := int(p); ip&1 == 0 {
+			signgam = -1
+		}
+		z := q - p
+		if z > 0.5 {
+			p = p + 1
+			z = q - p
+		}
+		z = q * Sin(Pi*z)
+		if z == 0 {
+			return Inf(signgam)
+		}
+		z = Pi / (Abs(z) * stirling(q))
+		return float64(signgam) * z
+	}
+
+	// Reduce argument
+	z := 1.0
+	for x >= 3 {
+		x = x - 1
+		z = z * x
+	}
+	for x < 0 {
+		if x > -1e-09 {
+			goto small
+		}
+		z = z / x
+		x = x + 1
+	}
+	for x < 2 {
+		if x < 1e-09 {
+			goto small
+		}
+		z = z / x
+		x = x + 1
+	}
+
+	if x == 2 {
+		return z
+	}
+
+	x = x - 2
+	p = (((((x*_gamP[0]+_gamP[1])*x+_gamP[2])*x+_gamP[3])*x+_gamP[4])*x+_gamP[5])*x + _gamP[6]
+	q = ((((((x*_gamQ[0]+_gamQ[1])*x+_gamQ[2])*x+_gamQ[3])*x+_gamQ[4])*x+_gamQ[5])*x+_gamQ[6])*x + _gamQ[7]
+	return z * p / q
+
+small:
+	if x == 0 {
+		return Inf(1)
+	}
+	return z / ((1 + Euler*x) * x)
+}
+
+func isNegInt(x float64) bool {
+	if x < 0 {
+		_, xf := Modf(x)
+		return xf == 0
+	}
+	return false
+}
diff --git a/third_party/gofrontend/libgo/go/math/hypot.go b/third_party/gofrontend/libgo/go/math/hypot.go
new file mode 100644
index 0000000..59b9c74
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/hypot.go
@@ -0,0 +1,45 @@
+// Copyright 2010 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 math
+
+/*
+	Hypot -- sqrt(p*p + q*q), but overflows only if the result does.
+*/
+
+// Hypot returns Sqrt(p*p + q*q), taking care to avoid
+// unnecessary overflow and underflow.
+//
+// Special cases are:
+//	Hypot(±Inf, q) = +Inf
+//	Hypot(p, ±Inf) = +Inf
+//	Hypot(NaN, q) = NaN
+//	Hypot(p, NaN) = NaN
+func Hypot(p, q float64) float64 {
+	return hypot(p, q)
+}
+
+func hypot(p, q float64) float64 {
+	// special cases
+	switch {
+	case IsInf(p, 0) || IsInf(q, 0):
+		return Inf(1)
+	case IsNaN(p) || IsNaN(q):
+		return NaN()
+	}
+	if p < 0 {
+		p = -p
+	}
+	if q < 0 {
+		q = -q
+	}
+	if p < q {
+		p, q = q, p
+	}
+	if p == 0 {
+		return 0
+	}
+	q = q / p
+	return p * Sqrt(1+q*q)
+}
diff --git a/third_party/gofrontend/libgo/go/math/j0.go b/third_party/gofrontend/libgo/go/math/j0.go
new file mode 100644
index 0000000..c20a9b2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/j0.go
@@ -0,0 +1,429 @@
+// Copyright 2010 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 math
+
+/*
+	Bessel function of the first and second kinds of order zero.
+*/
+
+// The original C code and the long comment below are
+// from FreeBSD's /usr/src/lib/msun/src/e_j0.c and
+// came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// __ieee754_j0(x), __ieee754_y0(x)
+// Bessel function of the first and second kinds of order zero.
+// Method -- j0(x):
+//      1. For tiny x, we use j0(x) = 1 - x**2/4 + x**4/64 - ...
+//      2. Reduce x to |x| since j0(x)=j0(-x),  and
+//         for x in (0,2)
+//              j0(x) = 1-z/4+ z**2*R0/S0,  where z = x*x;
+//         (precision:  |j0-1+z/4-z**2R0/S0 |<2**-63.67 )
+//         for x in (2,inf)
+//              j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0))
+//         where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
+//         as follow:
+//              cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+//                      = 1/sqrt(2) * (cos(x) + sin(x))
+//              sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4)
+//                      = 1/sqrt(2) * (sin(x) - cos(x))
+//         (To avoid cancellation, use
+//              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+//         to compute the worse one.)
+//
+//      3 Special cases
+//              j0(nan)= nan
+//              j0(0) = 1
+//              j0(inf) = 0
+//
+// Method -- y0(x):
+//      1. For x<2.
+//         Since
+//              y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x**2/4 - ...)
+//         therefore y0(x)-2/pi*j0(x)*ln(x) is an even function.
+//         We use the following function to approximate y0,
+//              y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x**2
+//         where
+//              U(z) = u00 + u01*z + ... + u06*z**6
+//              V(z) = 1  + v01*z + ... + v04*z**4
+//         with absolute approximation error bounded by 2**-72.
+//         Note: For tiny x, U/V = u0 and j0(x)~1, hence
+//              y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27)
+//      2. For x>=2.
+//              y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0))
+//         where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
+//         by the method mentioned above.
+//      3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0.
+//
+
+// J0 returns the order-zero Bessel function of the first kind.
+//
+// Special cases are:
+//	J0(±Inf) = 0
+//	J0(0) = 1
+//	J0(NaN) = NaN
+func J0(x float64) float64 {
+	const (
+		Huge   = 1e300
+		TwoM27 = 1.0 / (1 << 27) // 2**-27 0x3e40000000000000
+		TwoM13 = 1.0 / (1 << 13) // 2**-13 0x3f20000000000000
+		Two129 = 1 << 129        // 2**129 0x4800000000000000
+		// R0/S0 on [0, 2]
+		R02 = 1.56249999999999947958e-02  // 0x3F8FFFFFFFFFFFFD
+		R03 = -1.89979294238854721751e-04 // 0xBF28E6A5B61AC6E9
+		R04 = 1.82954049532700665670e-06  // 0x3EBEB1D10C503919
+		R05 = -4.61832688532103189199e-09 // 0xBE33D5E773D63FCE
+		S01 = 1.56191029464890010492e-02  // 0x3F8FFCE882C8C2A4
+		S02 = 1.16926784663337450260e-04  // 0x3F1EA6D2DD57DBF4
+		S03 = 5.13546550207318111446e-07  // 0x3EA13B54CE84D5A9
+		S04 = 1.16614003333790000205e-09  // 0x3E1408BCF4745D8F
+	)
+	// special cases
+	switch {
+	case IsNaN(x):
+		return x
+	case IsInf(x, 0):
+		return 0
+	case x == 0:
+		return 1
+	}
+
+	if x < 0 {
+		x = -x
+	}
+	if x >= 2 {
+		s, c := Sincos(x)
+		ss := s - c
+		cc := s + c
+
+		// make sure x+x does not overflow
+		if x < MaxFloat64/2 {
+			z := -Cos(x + x)
+			if s*c < 0 {
+				cc = z / ss
+			} else {
+				ss = z / cc
+			}
+		}
+
+		// j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+		// y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+
+		var z float64
+		if x > Two129 { // |x| > ~6.8056e+38
+			z = (1 / SqrtPi) * cc / Sqrt(x)
+		} else {
+			u := pzero(x)
+			v := qzero(x)
+			z = (1 / SqrtPi) * (u*cc - v*ss) / Sqrt(x)
+		}
+		return z // |x| >= 2.0
+	}
+	if x < TwoM13 { // |x| < ~1.2207e-4
+		if x < TwoM27 {
+			return 1 // |x| < ~7.4506e-9
+		}
+		return 1 - 0.25*x*x // ~7.4506e-9 < |x| < ~1.2207e-4
+	}
+	z := x * x
+	r := z * (R02 + z*(R03+z*(R04+z*R05)))
+	s := 1 + z*(S01+z*(S02+z*(S03+z*S04)))
+	if x < 1 {
+		return 1 + z*(-0.25+(r/s)) // |x| < 1.00
+	}
+	u := 0.5 * x
+	return (1+u)*(1-u) + z*(r/s) // 1.0 < |x| < 2.0
+}
+
+// Y0 returns the order-zero Bessel function of the second kind.
+//
+// Special cases are:
+//	Y0(+Inf) = 0
+//	Y0(0) = -Inf
+//	Y0(x < 0) = NaN
+//	Y0(NaN) = NaN
+func Y0(x float64) float64 {
+	const (
+		TwoM27 = 1.0 / (1 << 27)             // 2**-27 0x3e40000000000000
+		Two129 = 1 << 129                    // 2**129 0x4800000000000000
+		U00    = -7.38042951086872317523e-02 // 0xBFB2E4D699CBD01F
+		U01    = 1.76666452509181115538e-01  // 0x3FC69D019DE9E3FC
+		U02    = -1.38185671945596898896e-02 // 0xBF8C4CE8B16CFA97
+		U03    = 3.47453432093683650238e-04  // 0x3F36C54D20B29B6B
+		U04    = -3.81407053724364161125e-06 // 0xBECFFEA773D25CAD
+		U05    = 1.95590137035022920206e-08  // 0x3E5500573B4EABD4
+		U06    = -3.98205194132103398453e-11 // 0xBDC5E43D693FB3C8
+		V01    = 1.27304834834123699328e-02  // 0x3F8A127091C9C71A
+		V02    = 7.60068627350353253702e-05  // 0x3F13ECBBF578C6C1
+		V03    = 2.59150851840457805467e-07  // 0x3E91642D7FF202FD
+		V04    = 4.41110311332675467403e-10  // 0x3DFE50183BD6D9EF
+	)
+	// special cases
+	switch {
+	case x < 0 || IsNaN(x):
+		return NaN()
+	case IsInf(x, 1):
+		return 0
+	case x == 0:
+		return Inf(-1)
+	}
+
+	if x >= 2 { // |x| >= 2.0
+
+		// y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
+		//     where x0 = x-pi/4
+		// Better formula:
+		//     cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+		//             =  1/sqrt(2) * (sin(x) + cos(x))
+		//     sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+		//             =  1/sqrt(2) * (sin(x) - cos(x))
+		// To avoid cancellation, use
+		//     sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+		// to compute the worse one.
+
+		s, c := Sincos(x)
+		ss := s - c
+		cc := s + c
+
+		// j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+		// y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+
+		// make sure x+x does not overflow
+		if x < MaxFloat64/2 {
+			z := -Cos(x + x)
+			if s*c < 0 {
+				cc = z / ss
+			} else {
+				ss = z / cc
+			}
+		}
+		var z float64
+		if x > Two129 { // |x| > ~6.8056e+38
+			z = (1 / SqrtPi) * ss / Sqrt(x)
+		} else {
+			u := pzero(x)
+			v := qzero(x)
+			z = (1 / SqrtPi) * (u*ss + v*cc) / Sqrt(x)
+		}
+		return z // |x| >= 2.0
+	}
+	if x <= TwoM27 {
+		return U00 + (2/Pi)*Log(x) // |x| < ~7.4506e-9
+	}
+	z := x * x
+	u := U00 + z*(U01+z*(U02+z*(U03+z*(U04+z*(U05+z*U06)))))
+	v := 1 + z*(V01+z*(V02+z*(V03+z*V04)))
+	return u/v + (2/Pi)*J0(x)*Log(x) // ~7.4506e-9 < |x| < 2.0
+}
+
+// The asymptotic expansions of pzero is
+//      1 - 9/128 s**2 + 11025/98304 s**4 - ..., where s = 1/x.
+// For x >= 2, We approximate pzero by
+// 	pzero(x) = 1 + (R/S)
+// where  R = pR0 + pR1*s**2 + pR2*s**4 + ... + pR5*s**10
+// 	  S = 1 + pS0*s**2 + ... + pS4*s**10
+// and
+//      | pzero(x)-1-R/S | <= 2  ** ( -60.26)
+
+// for x in [inf, 8]=1/[0,0.125]
+var p0R8 = [6]float64{
+	0.00000000000000000000e+00,  // 0x0000000000000000
+	-7.03124999999900357484e-02, // 0xBFB1FFFFFFFFFD32
+	-8.08167041275349795626e+00, // 0xC02029D0B44FA779
+	-2.57063105679704847262e+02, // 0xC07011027B19E863
+	-2.48521641009428822144e+03, // 0xC0A36A6ECD4DCAFC
+	-5.25304380490729545272e+03, // 0xC0B4850B36CC643D
+}
+var p0S8 = [5]float64{
+	1.16534364619668181717e+02, // 0x405D223307A96751
+	3.83374475364121826715e+03, // 0x40ADF37D50596938
+	4.05978572648472545552e+04, // 0x40E3D2BB6EB6B05F
+	1.16752972564375915681e+05, // 0x40FC810F8F9FA9BD
+	4.76277284146730962675e+04, // 0x40E741774F2C49DC
+}
+
+// for x in [8,4.5454]=1/[0.125,0.22001]
+var p0R5 = [6]float64{
+	-1.14125464691894502584e-11, // 0xBDA918B147E495CC
+	-7.03124940873599280078e-02, // 0xBFB1FFFFE69AFBC6
+	-4.15961064470587782438e+00, // 0xC010A370F90C6BBF
+	-6.76747652265167261021e+01, // 0xC050EB2F5A7D1783
+	-3.31231299649172967747e+02, // 0xC074B3B36742CC63
+	-3.46433388365604912451e+02, // 0xC075A6EF28A38BD7
+}
+var p0S5 = [5]float64{
+	6.07539382692300335975e+01, // 0x404E60810C98C5DE
+	1.05125230595704579173e+03, // 0x40906D025C7E2864
+	5.97897094333855784498e+03, // 0x40B75AF88FBE1D60
+	9.62544514357774460223e+03, // 0x40C2CCB8FA76FA38
+	2.40605815922939109441e+03, // 0x40A2CC1DC70BE864
+}
+
+// for x in [4.547,2.8571]=1/[0.2199,0.35001]
+var p0R3 = [6]float64{
+	-2.54704601771951915620e-09, // 0xBE25E1036FE1AA86
+	-7.03119616381481654654e-02, // 0xBFB1FFF6F7C0E24B
+	-2.40903221549529611423e+00, // 0xC00345B2AEA48074
+	-2.19659774734883086467e+01, // 0xC035F74A4CB94E14
+	-5.80791704701737572236e+01, // 0xC04D0A22420A1A45
+	-3.14479470594888503854e+01, // 0xC03F72ACA892D80F
+}
+var p0S3 = [5]float64{
+	3.58560338055209726349e+01, // 0x4041ED9284077DD3
+	3.61513983050303863820e+02, // 0x40769839464A7C0E
+	1.19360783792111533330e+03, // 0x4092A66E6D1061D6
+	1.12799679856907414432e+03, // 0x40919FFCB8C39B7E
+	1.73580930813335754692e+02, // 0x4065B296FC379081
+}
+
+// for x in [2.8570,2]=1/[0.3499,0.5]
+var p0R2 = [6]float64{
+	-8.87534333032526411254e-08, // 0xBE77D316E927026D
+	-7.03030995483624743247e-02, // 0xBFB1FF62495E1E42
+	-1.45073846780952986357e+00, // 0xBFF736398A24A843
+	-7.63569613823527770791e+00, // 0xC01E8AF3EDAFA7F3
+	-1.11931668860356747786e+01, // 0xC02662E6C5246303
+	-3.23364579351335335033e+00, // 0xC009DE81AF8FE70F
+}
+var p0S2 = [5]float64{
+	2.22202997532088808441e+01, // 0x40363865908B5959
+	1.36206794218215208048e+02, // 0x4061069E0EE8878F
+	2.70470278658083486789e+02, // 0x4070E78642EA079B
+	1.53875394208320329881e+02, // 0x40633C033AB6FAFF
+	1.46576176948256193810e+01, // 0x402D50B344391809
+}
+
+func pzero(x float64) float64 {
+	var p [6]float64
+	var q [5]float64
+	if x >= 8 {
+		p = p0R8
+		q = p0S8
+	} else if x >= 4.5454 {
+		p = p0R5
+		q = p0S5
+	} else if x >= 2.8571 {
+		p = p0R3
+		q = p0S3
+	} else if x >= 2 {
+		p = p0R2
+		q = p0S2
+	}
+	z := 1 / (x * x)
+	r := p[0] + z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))))
+	s := 1 + z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))))
+	return 1 + r/s
+}
+
+// For x >= 8, the asymptotic expansions of qzero is
+//      -1/8 s + 75/1024 s**3 - ..., where s = 1/x.
+// We approximate pzero by
+//      qzero(x) = s*(-1.25 + (R/S))
+// where R = qR0 + qR1*s**2 + qR2*s**4 + ... + qR5*s**10
+//       S = 1 + qS0*s**2 + ... + qS5*s**12
+// and
+//      | qzero(x)/s +1.25-R/S | <= 2**(-61.22)
+
+// for x in [inf, 8]=1/[0,0.125]
+var q0R8 = [6]float64{
+	0.00000000000000000000e+00, // 0x0000000000000000
+	7.32421874999935051953e-02, // 0x3FB2BFFFFFFFFE2C
+	1.17682064682252693899e+01, // 0x402789525BB334D6
+	5.57673380256401856059e+02, // 0x40816D6315301825
+	8.85919720756468632317e+03, // 0x40C14D993E18F46D
+	3.70146267776887834771e+04, // 0x40E212D40E901566
+}
+var q0S8 = [6]float64{
+	1.63776026895689824414e+02,  // 0x406478D5365B39BC
+	8.09834494656449805916e+03,  // 0x40BFA2584E6B0563
+	1.42538291419120476348e+05,  // 0x4101665254D38C3F
+	8.03309257119514397345e+05,  // 0x412883DA83A52B43
+	8.40501579819060512818e+05,  // 0x4129A66B28DE0B3D
+	-3.43899293537866615225e+05, // 0xC114FD6D2C9530C5
+}
+
+// for x in [8,4.5454]=1/[0.125,0.22001]
+var q0R5 = [6]float64{
+	1.84085963594515531381e-11, // 0x3DB43D8F29CC8CD9
+	7.32421766612684765896e-02, // 0x3FB2BFFFD172B04C
+	5.83563508962056953777e+00, // 0x401757B0B9953DD3
+	1.35111577286449829671e+02, // 0x4060E3920A8788E9
+	1.02724376596164097464e+03, // 0x40900CF99DC8C481
+	1.98997785864605384631e+03, // 0x409F17E953C6E3A6
+}
+var q0S5 = [6]float64{
+	8.27766102236537761883e+01,  // 0x4054B1B3FB5E1543
+	2.07781416421392987104e+03,  // 0x40A03BA0DA21C0CE
+	1.88472887785718085070e+04,  // 0x40D267D27B591E6D
+	5.67511122894947329769e+04,  // 0x40EBB5E397E02372
+	3.59767538425114471465e+04,  // 0x40E191181F7A54A0
+	-5.35434275601944773371e+03, // 0xC0B4EA57BEDBC609
+}
+
+// for x in [4.547,2.8571]=1/[0.2199,0.35001]
+var q0R3 = [6]float64{
+	4.37741014089738620906e-09, // 0x3E32CD036ADECB82
+	7.32411180042911447163e-02, // 0x3FB2BFEE0E8D0842
+	3.34423137516170720929e+00, // 0x400AC0FC61149CF5
+	4.26218440745412650017e+01, // 0x40454F98962DAEDD
+	1.70808091340565596283e+02, // 0x406559DBE25EFD1F
+	1.66733948696651168575e+02, // 0x4064D77C81FA21E0
+}
+var q0S3 = [6]float64{
+	4.87588729724587182091e+01,  // 0x40486122BFE343A6
+	7.09689221056606015736e+02,  // 0x40862D8386544EB3
+	3.70414822620111362994e+03,  // 0x40ACF04BE44DFC63
+	6.46042516752568917582e+03,  // 0x40B93C6CD7C76A28
+	2.51633368920368957333e+03,  // 0x40A3A8AAD94FB1C0
+	-1.49247451836156386662e+02, // 0xC062A7EB201CF40F
+}
+
+// for x in [2.8570,2]=1/[0.3499,0.5]
+var q0R2 = [6]float64{
+	1.50444444886983272379e-07, // 0x3E84313B54F76BDB
+	7.32234265963079278272e-02, // 0x3FB2BEC53E883E34
+	1.99819174093815998816e+00, // 0x3FFFF897E727779C
+	1.44956029347885735348e+01, // 0x402CFDBFAAF96FE5
+	3.16662317504781540833e+01, // 0x403FAA8E29FBDC4A
+	1.62527075710929267416e+01, // 0x403040B171814BB4
+}
+var q0S2 = [6]float64{
+	3.03655848355219184498e+01,  // 0x403E5D96F7C07AED
+	2.69348118608049844624e+02,  // 0x4070D591E4D14B40
+	8.44783757595320139444e+02,  // 0x408A664522B3BF22
+	8.82935845112488550512e+02,  // 0x408B977C9C5CC214
+	2.12666388511798828631e+02,  // 0x406A95530E001365
+	-5.31095493882666946917e+00, // 0xC0153E6AF8B32931
+}
+
+func qzero(x float64) float64 {
+	var p, q [6]float64
+	if x >= 8 {
+		p = q0R8
+		q = q0S8
+	} else if x >= 4.5454 {
+		p = q0R5
+		q = q0S5
+	} else if x >= 2.8571 {
+		p = q0R3
+		q = q0S3
+	} else if x >= 2 {
+		p = q0R2
+		q = q0S2
+	}
+	z := 1 / (x * x)
+	r := p[0] + z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))))
+	s := 1 + z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))))
+	return (-0.125 + r/s) / x
+}
diff --git a/third_party/gofrontend/libgo/go/math/j1.go b/third_party/gofrontend/libgo/go/math/j1.go
new file mode 100644
index 0000000..7ac186b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/j1.go
@@ -0,0 +1,422 @@
+// Copyright 2010 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 math
+
+/*
+	Bessel function of the first and second kinds of order one.
+*/
+
+// The original C code and the long comment below are
+// from FreeBSD's /usr/src/lib/msun/src/e_j1.c and
+// came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// __ieee754_j1(x), __ieee754_y1(x)
+// Bessel function of the first and second kinds of order one.
+// Method -- j1(x):
+//      1. For tiny x, we use j1(x) = x/2 - x**3/16 + x**5/384 - ...
+//      2. Reduce x to |x| since j1(x)=-j1(-x),  and
+//         for x in (0,2)
+//              j1(x) = x/2 + x*z*R0/S0,  where z = x*x;
+//         (precision:  |j1/x - 1/2 - R0/S0 |<2**-61.51 )
+//         for x in (2,inf)
+//              j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1))
+//              y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
+//         where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
+//         as follow:
+//              cos(x1) =  cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+//                      =  1/sqrt(2) * (sin(x) - cos(x))
+//              sin(x1) =  sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+//                      = -1/sqrt(2) * (sin(x) + cos(x))
+//         (To avoid cancellation, use
+//              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+//         to compute the worse one.)
+//
+//      3 Special cases
+//              j1(nan)= nan
+//              j1(0) = 0
+//              j1(inf) = 0
+//
+// Method -- y1(x):
+//      1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN
+//      2. For x<2.
+//         Since
+//              y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x**3-...)
+//         therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function.
+//         We use the following function to approximate y1,
+//              y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x**2
+//         where for x in [0,2] (abs err less than 2**-65.89)
+//              U(z) = U0[0] + U0[1]*z + ... + U0[4]*z**4
+//              V(z) = 1  + v0[0]*z + ... + v0[4]*z**5
+//         Note: For tiny x, 1/x dominate y1 and hence
+//              y1(tiny) = -2/pi/tiny, (choose tiny<2**-54)
+//      3. For x>=2.
+//               y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
+//         where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
+//         by method mentioned above.
+
+// J1 returns the order-one Bessel function of the first kind.
+//
+// Special cases are:
+//	J1(±Inf) = 0
+//	J1(NaN) = NaN
+func J1(x float64) float64 {
+	const (
+		TwoM27 = 1.0 / (1 << 27) // 2**-27 0x3e40000000000000
+		Two129 = 1 << 129        // 2**129 0x4800000000000000
+		// R0/S0 on [0, 2]
+		R00 = -6.25000000000000000000e-02 // 0xBFB0000000000000
+		R01 = 1.40705666955189706048e-03  // 0x3F570D9F98472C61
+		R02 = -1.59955631084035597520e-05 // 0xBEF0C5C6BA169668
+		R03 = 4.96727999609584448412e-08  // 0x3E6AAAFA46CA0BD9
+		S01 = 1.91537599538363460805e-02  // 0x3F939D0B12637E53
+		S02 = 1.85946785588630915560e-04  // 0x3F285F56B9CDF664
+		S03 = 1.17718464042623683263e-06  // 0x3EB3BFF8333F8498
+		S04 = 5.04636257076217042715e-09  // 0x3E35AC88C97DFF2C
+		S05 = 1.23542274426137913908e-11  // 0x3DAB2ACFCFB97ED8
+	)
+	// special cases
+	switch {
+	case IsNaN(x):
+		return x
+	case IsInf(x, 0) || x == 0:
+		return 0
+	}
+
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+	if x >= 2 {
+		s, c := Sincos(x)
+		ss := -s - c
+		cc := s - c
+
+		// make sure x+x does not overflow
+		if x < MaxFloat64/2 {
+			z := Cos(x + x)
+			if s*c > 0 {
+				cc = z / ss
+			} else {
+				ss = z / cc
+			}
+		}
+
+		// j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
+		// y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
+
+		var z float64
+		if x > Two129 {
+			z = (1 / SqrtPi) * cc / Sqrt(x)
+		} else {
+			u := pone(x)
+			v := qone(x)
+			z = (1 / SqrtPi) * (u*cc - v*ss) / Sqrt(x)
+		}
+		if sign {
+			return -z
+		}
+		return z
+	}
+	if x < TwoM27 { // |x|<2**-27
+		return 0.5 * x // inexact if x!=0 necessary
+	}
+	z := x * x
+	r := z * (R00 + z*(R01+z*(R02+z*R03)))
+	s := 1.0 + z*(S01+z*(S02+z*(S03+z*(S04+z*S05))))
+	r *= x
+	z = 0.5*x + r/s
+	if sign {
+		return -z
+	}
+	return z
+}
+
+// Y1 returns the order-one Bessel function of the second kind.
+//
+// Special cases are:
+//	Y1(+Inf) = 0
+//	Y1(0) = -Inf
+//	Y1(x < 0) = NaN
+//	Y1(NaN) = NaN
+func Y1(x float64) float64 {
+	const (
+		TwoM54 = 1.0 / (1 << 54)             // 2**-54 0x3c90000000000000
+		Two129 = 1 << 129                    // 2**129 0x4800000000000000
+		U00    = -1.96057090646238940668e-01 // 0xBFC91866143CBC8A
+		U01    = 5.04438716639811282616e-02  // 0x3FA9D3C776292CD1
+		U02    = -1.91256895875763547298e-03 // 0xBF5F55E54844F50F
+		U03    = 2.35252600561610495928e-05  // 0x3EF8AB038FA6B88E
+		U04    = -9.19099158039878874504e-08 // 0xBE78AC00569105B8
+		V00    = 1.99167318236649903973e-02  // 0x3F94650D3F4DA9F0
+		V01    = 2.02552581025135171496e-04  // 0x3F2A8C896C257764
+		V02    = 1.35608801097516229404e-06  // 0x3EB6C05A894E8CA6
+		V03    = 6.22741452364621501295e-09  // 0x3E3ABF1D5BA69A86
+		V04    = 1.66559246207992079114e-11  // 0x3DB25039DACA772A
+	)
+	// special cases
+	switch {
+	case x < 0 || IsNaN(x):
+		return NaN()
+	case IsInf(x, 1):
+		return 0
+	case x == 0:
+		return Inf(-1)
+	}
+
+	if x >= 2 {
+		s, c := Sincos(x)
+		ss := -s - c
+		cc := s - c
+
+		// make sure x+x does not overflow
+		if x < MaxFloat64/2 {
+			z := Cos(x + x)
+			if s*c > 0 {
+				cc = z / ss
+			} else {
+				ss = z / cc
+			}
+		}
+		// y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
+		// where x0 = x-3pi/4
+		//     Better formula:
+		//         cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+		//                 =  1/sqrt(2) * (sin(x) - cos(x))
+		//         sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+		//                 = -1/sqrt(2) * (cos(x) + sin(x))
+		// To avoid cancellation, use
+		//     sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+		// to compute the worse one.
+
+		var z float64
+		if x > Two129 {
+			z = (1 / SqrtPi) * ss / Sqrt(x)
+		} else {
+			u := pone(x)
+			v := qone(x)
+			z = (1 / SqrtPi) * (u*ss + v*cc) / Sqrt(x)
+		}
+		return z
+	}
+	if x <= TwoM54 { // x < 2**-54
+		return -(2 / Pi) / x
+	}
+	z := x * x
+	u := U00 + z*(U01+z*(U02+z*(U03+z*U04)))
+	v := 1 + z*(V00+z*(V01+z*(V02+z*(V03+z*V04))))
+	return x*(u/v) + (2/Pi)*(J1(x)*Log(x)-1/x)
+}
+
+// For x >= 8, the asymptotic expansions of pone is
+//      1 + 15/128 s**2 - 4725/2**15 s**4 - ..., where s = 1/x.
+// We approximate pone by
+//      pone(x) = 1 + (R/S)
+// where R = pr0 + pr1*s**2 + pr2*s**4 + ... + pr5*s**10
+//       S = 1 + ps0*s**2 + ... + ps4*s**10
+// and
+//      | pone(x)-1-R/S | <= 2**(-60.06)
+
+// for x in [inf, 8]=1/[0,0.125]
+var p1R8 = [6]float64{
+	0.00000000000000000000e+00, // 0x0000000000000000
+	1.17187499999988647970e-01, // 0x3FBDFFFFFFFFFCCE
+	1.32394806593073575129e+01, // 0x402A7A9D357F7FCE
+	4.12051854307378562225e+02, // 0x4079C0D4652EA590
+	3.87474538913960532227e+03, // 0x40AE457DA3A532CC
+	7.91447954031891731574e+03, // 0x40BEEA7AC32782DD
+}
+var p1S8 = [5]float64{
+	1.14207370375678408436e+02, // 0x405C8D458E656CAC
+	3.65093083420853463394e+03, // 0x40AC85DC964D274F
+	3.69562060269033463555e+04, // 0x40E20B8697C5BB7F
+	9.76027935934950801311e+04, // 0x40F7D42CB28F17BB
+	3.08042720627888811578e+04, // 0x40DE1511697A0B2D
+}
+
+// for x in [8,4.5454] = 1/[0.125,0.22001]
+var p1R5 = [6]float64{
+	1.31990519556243522749e-11, // 0x3DAD0667DAE1CA7D
+	1.17187493190614097638e-01, // 0x3FBDFFFFE2C10043
+	6.80275127868432871736e+00, // 0x401B36046E6315E3
+	1.08308182990189109773e+02, // 0x405B13B9452602ED
+	5.17636139533199752805e+02, // 0x40802D16D052D649
+	5.28715201363337541807e+02, // 0x408085B8BB7E0CB7
+}
+var p1S5 = [5]float64{
+	5.92805987221131331921e+01, // 0x404DA3EAA8AF633D
+	9.91401418733614377743e+02, // 0x408EFB361B066701
+	5.35326695291487976647e+03, // 0x40B4E9445706B6FB
+	7.84469031749551231769e+03, // 0x40BEA4B0B8A5BB15
+	1.50404688810361062679e+03, // 0x40978030036F5E51
+}
+
+// for x in[4.5453,2.8571] = 1/[0.2199,0.35001]
+var p1R3 = [6]float64{
+	3.02503916137373618024e-09, // 0x3E29FC21A7AD9EDD
+	1.17186865567253592491e-01, // 0x3FBDFFF55B21D17B
+	3.93297750033315640650e+00, // 0x400F76BCE85EAD8A
+	3.51194035591636932736e+01, // 0x40418F489DA6D129
+	9.10550110750781271918e+01, // 0x4056C3854D2C1837
+	4.85590685197364919645e+01, // 0x4048478F8EA83EE5
+}
+var p1S3 = [5]float64{
+	3.47913095001251519989e+01, // 0x40416549A134069C
+	3.36762458747825746741e+02, // 0x40750C3307F1A75F
+	1.04687139975775130551e+03, // 0x40905B7C5037D523
+	8.90811346398256432622e+02, // 0x408BD67DA32E31E9
+	1.03787932439639277504e+02, // 0x4059F26D7C2EED53
+}
+
+// for x in [2.8570,2] = 1/[0.3499,0.5]
+var p1R2 = [6]float64{
+	1.07710830106873743082e-07, // 0x3E7CE9D4F65544F4
+	1.17176219462683348094e-01, // 0x3FBDFF42BE760D83
+	2.36851496667608785174e+00, // 0x4002F2B7F98FAEC0
+	1.22426109148261232917e+01, // 0x40287C377F71A964
+	1.76939711271687727390e+01, // 0x4031B1A8177F8EE2
+	5.07352312588818499250e+00, // 0x40144B49A574C1FE
+}
+var p1S2 = [5]float64{
+	2.14364859363821409488e+01, // 0x40356FBD8AD5ECDC
+	1.25290227168402751090e+02, // 0x405F529314F92CD5
+	2.32276469057162813669e+02, // 0x406D08D8D5A2DBD9
+	1.17679373287147100768e+02, // 0x405D6B7ADA1884A9
+	8.36463893371618283368e+00, // 0x4020BAB1F44E5192
+}
+
+func pone(x float64) float64 {
+	var p [6]float64
+	var q [5]float64
+	if x >= 8 {
+		p = p1R8
+		q = p1S8
+	} else if x >= 4.5454 {
+		p = p1R5
+		q = p1S5
+	} else if x >= 2.8571 {
+		p = p1R3
+		q = p1S3
+	} else if x >= 2 {
+		p = p1R2
+		q = p1S2
+	}
+	z := 1 / (x * x)
+	r := p[0] + z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))))
+	s := 1.0 + z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))))
+	return 1 + r/s
+}
+
+// For x >= 8, the asymptotic expansions of qone is
+//      3/8 s - 105/1024 s**3 - ..., where s = 1/x.
+// We approximate qone by
+//      qone(x) = s*(0.375 + (R/S))
+// where R = qr1*s**2 + qr2*s**4 + ... + qr5*s**10
+//       S = 1 + qs1*s**2 + ... + qs6*s**12
+// and
+//      | qone(x)/s -0.375-R/S | <= 2**(-61.13)
+
+// for x in [inf, 8] = 1/[0,0.125]
+var q1R8 = [6]float64{
+	0.00000000000000000000e+00,  // 0x0000000000000000
+	-1.02539062499992714161e-01, // 0xBFBA3FFFFFFFFDF3
+	-1.62717534544589987888e+01, // 0xC0304591A26779F7
+	-7.59601722513950107896e+02, // 0xC087BCD053E4B576
+	-1.18498066702429587167e+04, // 0xC0C724E740F87415
+	-4.84385124285750353010e+04, // 0xC0E7A6D065D09C6A
+}
+var q1S8 = [6]float64{
+	1.61395369700722909556e+02,  // 0x40642CA6DE5BCDE5
+	7.82538599923348465381e+03,  // 0x40BE9162D0D88419
+	1.33875336287249578163e+05,  // 0x4100579AB0B75E98
+	7.19657723683240939863e+05,  // 0x4125F65372869C19
+	6.66601232617776375264e+05,  // 0x412457D27719AD5C
+	-2.94490264303834643215e+05, // 0xC111F9690EA5AA18
+}
+
+// for x in [8,4.5454] = 1/[0.125,0.22001]
+var q1R5 = [6]float64{
+	-2.08979931141764104297e-11, // 0xBDB6FA431AA1A098
+	-1.02539050241375426231e-01, // 0xBFBA3FFFCB597FEF
+	-8.05644828123936029840e+00, // 0xC0201CE6CA03AD4B
+	-1.83669607474888380239e+02, // 0xC066F56D6CA7B9B0
+	-1.37319376065508163265e+03, // 0xC09574C66931734F
+	-2.61244440453215656817e+03, // 0xC0A468E388FDA79D
+}
+var q1S5 = [6]float64{
+	8.12765501384335777857e+01,  // 0x405451B2FF5A11B2
+	1.99179873460485964642e+03,  // 0x409F1F31E77BF839
+	1.74684851924908907677e+04,  // 0x40D10F1F0D64CE29
+	4.98514270910352279316e+04,  // 0x40E8576DAABAD197
+	2.79480751638918118260e+04,  // 0x40DB4B04CF7C364B
+	-4.71918354795128470869e+03, // 0xC0B26F2EFCFFA004
+}
+
+// for x in [4.5454,2.8571] = 1/[0.2199,0.35001] ???
+var q1R3 = [6]float64{
+	-5.07831226461766561369e-09, // 0xBE35CFA9D38FC84F
+	-1.02537829820837089745e-01, // 0xBFBA3FEB51AEED54
+	-4.61011581139473403113e+00, // 0xC01270C23302D9FF
+	-5.78472216562783643212e+01, // 0xC04CEC71C25D16DA
+	-2.28244540737631695038e+02, // 0xC06C87D34718D55F
+	-2.19210128478909325622e+02, // 0xC06B66B95F5C1BF6
+}
+var q1S3 = [6]float64{
+	4.76651550323729509273e+01,  // 0x4047D523CCD367E4
+	6.73865112676699709482e+02,  // 0x40850EEBC031EE3E
+	3.38015286679526343505e+03,  // 0x40AA684E448E7C9A
+	5.54772909720722782367e+03,  // 0x40B5ABBAA61D54A6
+	1.90311919338810798763e+03,  // 0x409DBC7A0DD4DF4B
+	-1.35201191444307340817e+02, // 0xC060E670290A311F
+}
+
+// for x in [2.8570,2] = 1/[0.3499,0.5]
+var q1R2 = [6]float64{
+	-1.78381727510958865572e-07, // 0xBE87F12644C626D2
+	-1.02517042607985553460e-01, // 0xBFBA3E8E9148B010
+	-2.75220568278187460720e+00, // 0xC006048469BB4EDA
+	-1.96636162643703720221e+01, // 0xC033A9E2C168907F
+	-4.23253133372830490089e+01, // 0xC04529A3DE104AAA
+	-2.13719211703704061733e+01, // 0xC0355F3639CF6E52
+}
+var q1S2 = [6]float64{
+	2.95333629060523854548e+01,  // 0x403D888A78AE64FF
+	2.52981549982190529136e+02,  // 0x406F9F68DB821CBA
+	7.57502834868645436472e+02,  // 0x4087AC05CE49A0F7
+	7.39393205320467245656e+02,  // 0x40871B2548D4C029
+	1.55949003336666123687e+02,  // 0x40637E5E3C3ED8D4
+	-4.95949898822628210127e+00, // 0xC013D686E71BE86B
+}
+
+func qone(x float64) float64 {
+	var p, q [6]float64
+	if x >= 8 {
+		p = q1R8
+		q = q1S8
+	} else if x >= 4.5454 {
+		p = q1R5
+		q = q1S5
+	} else if x >= 2.8571 {
+		p = q1R3
+		q = q1S3
+	} else if x >= 2 {
+		p = q1R2
+		q = q1S2
+	}
+	z := 1 / (x * x)
+	r := p[0] + z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))))
+	s := 1 + z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))))
+	return (0.375 + r/s) / x
+}
diff --git a/third_party/gofrontend/libgo/go/math/jn.go b/third_party/gofrontend/libgo/go/math/jn.go
new file mode 100644
index 0000000..a7909eb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/jn.go
@@ -0,0 +1,306 @@
+// Copyright 2010 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 math
+
+/*
+	Bessel function of the first and second kinds of order n.
+*/
+
+// The original C code and the long comment below are
+// from FreeBSD's /usr/src/lib/msun/src/e_jn.c and
+// came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// __ieee754_jn(n, x), __ieee754_yn(n, x)
+// floating point Bessel's function of the 1st and 2nd kind
+// of order n
+//
+// Special cases:
+//      y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;
+//      y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
+// Note 2. About jn(n,x), yn(n,x)
+//      For n=0, j0(x) is called,
+//      for n=1, j1(x) is called,
+//      for n<x, forward recursion is used starting
+//      from values of j0(x) and j1(x).
+//      for n>x, a continued fraction approximation to
+//      j(n,x)/j(n-1,x) is evaluated and then backward
+//      recursion is used starting from a supposed value
+//      for j(n,x). The resulting value of j(0,x) is
+//      compared with the actual value to correct the
+//      supposed value of j(n,x).
+//
+//      yn(n,x) is similar in all respects, except
+//      that forward recursion is used for all
+//      values of n>1.
+
+// Jn returns the order-n Bessel function of the first kind.
+//
+// Special cases are:
+//	Jn(n, ±Inf) = 0
+//	Jn(n, NaN) = NaN
+func Jn(n int, x float64) float64 {
+	const (
+		TwoM29 = 1.0 / (1 << 29) // 2**-29 0x3e10000000000000
+		Two302 = 1 << 302        // 2**302 0x52D0000000000000
+	)
+	// special cases
+	switch {
+	case IsNaN(x):
+		return x
+	case IsInf(x, 0):
+		return 0
+	}
+	// J(-n, x) = (-1)**n * J(n, x), J(n, -x) = (-1)**n * J(n, x)
+	// Thus, J(-n, x) = J(n, -x)
+
+	if n == 0 {
+		return J0(x)
+	}
+	if x == 0 {
+		return 0
+	}
+	if n < 0 {
+		n, x = -n, -x
+	}
+	if n == 1 {
+		return J1(x)
+	}
+	sign := false
+	if x < 0 {
+		x = -x
+		if n&1 == 1 {
+			sign = true // odd n and negative x
+		}
+	}
+	var b float64
+	if float64(n) <= x {
+		// Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x)
+		if x >= Two302 { // x > 2**302
+
+			// (x >> n**2)
+			//          Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+			//          Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+			//          Let s=sin(x), c=cos(x),
+			//              xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+			//
+			//                 n    sin(xn)*sqt2    cos(xn)*sqt2
+			//              ----------------------------------
+			//                 0     s-c             c+s
+			//                 1    -s-c            -c+s
+			//                 2    -s+c            -c-s
+			//                 3     s+c             c-s
+
+			var temp float64
+			switch n & 3 {
+			case 0:
+				temp = Cos(x) + Sin(x)
+			case 1:
+				temp = -Cos(x) + Sin(x)
+			case 2:
+				temp = -Cos(x) - Sin(x)
+			case 3:
+				temp = Cos(x) - Sin(x)
+			}
+			b = (1 / SqrtPi) * temp / Sqrt(x)
+		} else {
+			b = J1(x)
+			for i, a := 1, J0(x); i < n; i++ {
+				a, b = b, b*(float64(i+i)/x)-a // avoid underflow
+			}
+		}
+	} else {
+		if x < TwoM29 { // x < 2**-29
+			// x is tiny, return the first Taylor expansion of J(n,x)
+			// J(n,x) = 1/n!*(x/2)**n  - ...
+
+			if n > 33 { // underflow
+				b = 0
+			} else {
+				temp := x * 0.5
+				b = temp
+				a := 1.0
+				for i := 2; i <= n; i++ {
+					a *= float64(i) // a = n!
+					b *= temp       // b = (x/2)**n
+				}
+				b /= a
+			}
+		} else {
+			// use backward recurrence
+			//                      x      x**2      x**2
+			//  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
+			//                      2n  - 2(n+1) - 2(n+2)
+			//
+			//                      1      1        1
+			//  (for large x)   =  ----  ------   ------   .....
+			//                      2n   2(n+1)   2(n+2)
+			//                      -- - ------ - ------ -
+			//                       x     x         x
+			//
+			// Let w = 2n/x and h=2/x, then the above quotient
+			// is equal to the continued fraction:
+			//                  1
+			//      = -----------------------
+			//                     1
+			//         w - -----------------
+			//                        1
+			//              w+h - ---------
+			//                     w+2h - ...
+			//
+			// To determine how many terms needed, let
+			// Q(0) = w, Q(1) = w(w+h) - 1,
+			// Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
+			// When Q(k) > 1e4	good for single
+			// When Q(k) > 1e9	good for double
+			// When Q(k) > 1e17	good for quadruple
+
+			// determine k
+			w := float64(n+n) / x
+			h := 2 / x
+			q0 := w
+			z := w + h
+			q1 := w*z - 1
+			k := 1
+			for q1 < 1e9 {
+				k += 1
+				z += h
+				q0, q1 = q1, z*q1-q0
+			}
+			m := n + n
+			t := 0.0
+			for i := 2 * (n + k); i >= m; i -= 2 {
+				t = 1 / (float64(i)/x - t)
+			}
+			a := t
+			b = 1
+			//  estimate log((2/x)**n*n!) = n*log(2/x)+n*ln(n)
+			//  Hence, if n*(log(2n/x)) > ...
+			//  single 8.8722839355e+01
+			//  double 7.09782712893383973096e+02
+			//  long double 1.1356523406294143949491931077970765006170e+04
+			//  then recurrent value may overflow and the result is
+			//  likely underflow to zero
+
+			tmp := float64(n)
+			v := 2 / x
+			tmp = tmp * Log(Abs(v*tmp))
+			if tmp < 7.09782712893383973096e+02 {
+				for i := n - 1; i > 0; i-- {
+					di := float64(i + i)
+					a, b = b, b*di/x-a
+					di -= 2
+				}
+			} else {
+				for i := n - 1; i > 0; i-- {
+					di := float64(i + i)
+					a, b = b, b*di/x-a
+					di -= 2
+					// scale b to avoid spurious overflow
+					if b > 1e100 {
+						a /= b
+						t /= b
+						b = 1
+					}
+				}
+			}
+			b = t * J0(x) / b
+		}
+	}
+	if sign {
+		return -b
+	}
+	return b
+}
+
+// Yn returns the order-n Bessel function of the second kind.
+//
+// Special cases are:
+//	Yn(n, +Inf) = 0
+//	Yn(n > 0, 0) = -Inf
+//	Yn(n < 0, 0) = +Inf if n is odd, -Inf if n is even
+//	Y1(n, x < 0) = NaN
+//	Y1(n, NaN) = NaN
+func Yn(n int, x float64) float64 {
+	const Two302 = 1 << 302 // 2**302 0x52D0000000000000
+	// special cases
+	switch {
+	case x < 0 || IsNaN(x):
+		return NaN()
+	case IsInf(x, 1):
+		return 0
+	}
+
+	if n == 0 {
+		return Y0(x)
+	}
+	if x == 0 {
+		if n < 0 && n&1 == 1 {
+			return Inf(1)
+		}
+		return Inf(-1)
+	}
+	sign := false
+	if n < 0 {
+		n = -n
+		if n&1 == 1 {
+			sign = true // sign true if n < 0 && |n| odd
+		}
+	}
+	if n == 1 {
+		if sign {
+			return -Y1(x)
+		}
+		return Y1(x)
+	}
+	var b float64
+	if x >= Two302 { // x > 2**302
+		// (x >> n**2)
+		//	    Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+		//	    Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+		//	    Let s=sin(x), c=cos(x),
+		//		xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+		//
+		//		   n	sin(xn)*sqt2	cos(xn)*sqt2
+		//		----------------------------------
+		//		   0	 s-c		 c+s
+		//		   1	-s-c 		-c+s
+		//		   2	-s+c		-c-s
+		//		   3	 s+c		 c-s
+
+		var temp float64
+		switch n & 3 {
+		case 0:
+			temp = Sin(x) - Cos(x)
+		case 1:
+			temp = -Sin(x) - Cos(x)
+		case 2:
+			temp = -Sin(x) + Cos(x)
+		case 3:
+			temp = Sin(x) + Cos(x)
+		}
+		b = (1 / SqrtPi) * temp / Sqrt(x)
+	} else {
+		a := Y0(x)
+		b = Y1(x)
+		// quit if b is -inf
+		for i := 1; i < n && !IsInf(b, -1); i++ {
+			a, b = b, (float64(i+i)/x)*b-a
+		}
+	}
+	if sign {
+		return -b
+	}
+	return b
+}
diff --git a/third_party/gofrontend/libgo/go/math/ldexp.go b/third_party/gofrontend/libgo/go/math/ldexp.go
new file mode 100644
index 0000000..2898f5d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/ldexp.go
@@ -0,0 +1,52 @@
+// 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 math
+
+// Ldexp is the inverse of Frexp.
+// It returns frac × 2**exp.
+//
+// Special cases are:
+//	Ldexp(±0, exp) = ±0
+//	Ldexp(±Inf, exp) = ±Inf
+//	Ldexp(NaN, exp) = NaN
+
+//extern ldexp
+func libc_ldexp(float64, int) float64
+
+func Ldexp(frac float64, exp int) float64 {
+	r := libc_ldexp(frac, exp)
+	return r
+}
+
+func ldexp(frac float64, exp int) float64 {
+	// special cases
+	switch {
+	case frac == 0:
+		return frac // correctly return -0
+	case IsInf(frac, 0) || IsNaN(frac):
+		return frac
+	}
+	frac, e := normalize(frac)
+	exp += e
+	x := Float64bits(frac)
+	exp += int(x>>shift)&mask - bias
+	if exp < -1074 {
+		return Copysign(0, frac) // underflow
+	}
+	if exp > 1023 { // overflow
+		if frac < 0 {
+			return Inf(-1)
+		}
+		return Inf(1)
+	}
+	var m float64 = 1
+	if exp < -1022 { // denormal
+		exp += 52
+		m = 1.0 / (1 << 52) // 2**-52
+	}
+	x &^= mask << shift
+	x |= uint64(exp+bias) << shift
+	return m * Float64frombits(x)
+}
diff --git a/third_party/gofrontend/libgo/go/math/lgamma.go b/third_party/gofrontend/libgo/go/math/lgamma.go
new file mode 100644
index 0000000..6a02c41
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/lgamma.go
@@ -0,0 +1,365 @@
+// Copyright 2010 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 math
+
+/*
+	Floating-point logarithm of the Gamma function.
+*/
+
+// The original C code and the long comment below are
+// from FreeBSD's /usr/src/lib/msun/src/e_lgamma_r.c and
+// came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// __ieee754_lgamma_r(x, signgamp)
+// Reentrant version of the logarithm of the Gamma function
+// with user provided pointer for the sign of Gamma(x).
+//
+// Method:
+//   1. Argument Reduction for 0 < x <= 8
+//      Since gamma(1+s)=s*gamma(s), for x in [0,8], we may
+//      reduce x to a number in [1.5,2.5] by
+//              lgamma(1+s) = log(s) + lgamma(s)
+//      for example,
+//              lgamma(7.3) = log(6.3) + lgamma(6.3)
+//                          = log(6.3*5.3) + lgamma(5.3)
+//                          = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3)
+//   2. Polynomial approximation of lgamma around its
+//      minimum (ymin=1.461632144968362245) to maintain monotonicity.
+//      On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use
+//              Let z = x-ymin;
+//              lgamma(x) = -1.214862905358496078218 + z**2*poly(z)
+//              poly(z) is a 14 degree polynomial.
+//   2. Rational approximation in the primary interval [2,3]
+//      We use the following approximation:
+//              s = x-2.0;
+//              lgamma(x) = 0.5*s + s*P(s)/Q(s)
+//      with accuracy
+//              |P/Q - (lgamma(x)-0.5s)| < 2**-61.71
+//      Our algorithms are based on the following observation
+//
+//                             zeta(2)-1    2    zeta(3)-1    3
+// lgamma(2+s) = s*(1-Euler) + --------- * s  -  --------- * s  + ...
+//                                 2                 3
+//
+//      where Euler = 0.5772156649... is the Euler constant, which
+//      is very close to 0.5.
+//
+//   3. For x>=8, we have
+//      lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+....
+//      (better formula:
+//         lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...)
+//      Let z = 1/x, then we approximation
+//              f(z) = lgamma(x) - (x-0.5)(log(x)-1)
+//      by
+//                                  3       5             11
+//              w = w0 + w1*z + w2*z  + w3*z  + ... + w6*z
+//      where
+//              |w - f(z)| < 2**-58.74
+//
+//   4. For negative x, since (G is gamma function)
+//              -x*G(-x)*G(x) = pi/sin(pi*x),
+//      we have
+//              G(x) = pi/(sin(pi*x)*(-x)*G(-x))
+//      since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0
+//      Hence, for x<0, signgam = sign(sin(pi*x)) and
+//              lgamma(x) = log(|Gamma(x)|)
+//                        = log(pi/(|x*sin(pi*x)|)) - lgamma(-x);
+//      Note: one should avoid computing pi*(-x) directly in the
+//            computation of sin(pi*(-x)).
+//
+//   5. Special Cases
+//              lgamma(2+s) ~ s*(1-Euler) for tiny s
+//              lgamma(1)=lgamma(2)=0
+//              lgamma(x) ~ -log(x) for tiny x
+//              lgamma(0) = lgamma(inf) = inf
+//              lgamma(-integer) = +-inf
+//
+//
+
+var _lgamA = [...]float64{
+	7.72156649015328655494e-02, // 0x3FB3C467E37DB0C8
+	3.22467033424113591611e-01, // 0x3FD4A34CC4A60FAD
+	6.73523010531292681824e-02, // 0x3FB13E001A5562A7
+	2.05808084325167332806e-02, // 0x3F951322AC92547B
+	7.38555086081402883957e-03, // 0x3F7E404FB68FEFE8
+	2.89051383673415629091e-03, // 0x3F67ADD8CCB7926B
+	1.19270763183362067845e-03, // 0x3F538A94116F3F5D
+	5.10069792153511336608e-04, // 0x3F40B6C689B99C00
+	2.20862790713908385557e-04, // 0x3F2CF2ECED10E54D
+	1.08011567247583939954e-04, // 0x3F1C5088987DFB07
+	2.52144565451257326939e-05, // 0x3EFA7074428CFA52
+	4.48640949618915160150e-05, // 0x3F07858E90A45837
+}
+var _lgamR = [...]float64{
+	1.0, // placeholder
+	1.39200533467621045958e+00, // 0x3FF645A762C4AB74
+	7.21935547567138069525e-01, // 0x3FE71A1893D3DCDC
+	1.71933865632803078993e-01, // 0x3FC601EDCCFBDF27
+	1.86459191715652901344e-02, // 0x3F9317EA742ED475
+	7.77942496381893596434e-04, // 0x3F497DDACA41A95B
+	7.32668430744625636189e-06, // 0x3EDEBAF7A5B38140
+}
+var _lgamS = [...]float64{
+	-7.72156649015328655494e-02, // 0xBFB3C467E37DB0C8
+	2.14982415960608852501e-01,  // 0x3FCB848B36E20878
+	3.25778796408930981787e-01,  // 0x3FD4D98F4F139F59
+	1.46350472652464452805e-01,  // 0x3FC2BB9CBEE5F2F7
+	2.66422703033638609560e-02,  // 0x3F9B481C7E939961
+	1.84028451407337715652e-03,  // 0x3F5E26B67368F239
+	3.19475326584100867617e-05,  // 0x3F00BFECDD17E945
+}
+var _lgamT = [...]float64{
+	4.83836122723810047042e-01,  // 0x3FDEF72BC8EE38A2
+	-1.47587722994593911752e-01, // 0xBFC2E4278DC6C509
+	6.46249402391333854778e-02,  // 0x3FB08B4294D5419B
+	-3.27885410759859649565e-02, // 0xBFA0C9A8DF35B713
+	1.79706750811820387126e-02,  // 0x3F9266E7970AF9EC
+	-1.03142241298341437450e-02, // 0xBF851F9FBA91EC6A
+	6.10053870246291332635e-03,  // 0x3F78FCE0E370E344
+	-3.68452016781138256760e-03, // 0xBF6E2EFFB3E914D7
+	2.25964780900612472250e-03,  // 0x3F6282D32E15C915
+	-1.40346469989232843813e-03, // 0xBF56FE8EBF2D1AF1
+	8.81081882437654011382e-04,  // 0x3F4CDF0CEF61A8E9
+	-5.38595305356740546715e-04, // 0xBF41A6109C73E0EC
+	3.15632070903625950361e-04,  // 0x3F34AF6D6C0EBBF7
+	-3.12754168375120860518e-04, // 0xBF347F24ECC38C38
+	3.35529192635519073543e-04,  // 0x3F35FD3EE8C2D3F4
+}
+var _lgamU = [...]float64{
+	-7.72156649015328655494e-02, // 0xBFB3C467E37DB0C8
+	6.32827064025093366517e-01,  // 0x3FE4401E8B005DFF
+	1.45492250137234768737e+00,  // 0x3FF7475CD119BD6F
+	9.77717527963372745603e-01,  // 0x3FEF497644EA8450
+	2.28963728064692451092e-01,  // 0x3FCD4EAEF6010924
+	1.33810918536787660377e-02,  // 0x3F8B678BBF2BAB09
+}
+var _lgamV = [...]float64{
+	1.0,
+	2.45597793713041134822e+00, // 0x4003A5D7C2BD619C
+	2.12848976379893395361e+00, // 0x40010725A42B18F5
+	7.69285150456672783825e-01, // 0x3FE89DFBE45050AF
+	1.04222645593369134254e-01, // 0x3FBAAE55D6537C88
+	3.21709242282423911810e-03, // 0x3F6A5ABB57D0CF61
+}
+var _lgamW = [...]float64{
+	4.18938533204672725052e-01,  // 0x3FDACFE390C97D69
+	8.33333333333329678849e-02,  // 0x3FB555555555553B
+	-2.77777777728775536470e-03, // 0xBF66C16C16B02E5C
+	7.93650558643019558500e-04,  // 0x3F4A019F98CF38B6
+	-5.95187557450339963135e-04, // 0xBF4380CB8C0FE741
+	8.36339918996282139126e-04,  // 0x3F4B67BA4CDAD5D1
+	-1.63092934096575273989e-03, // 0xBF5AB89D0B9E43E4
+}
+
+// Lgamma returns the natural logarithm and sign (-1 or +1) of Gamma(x).
+//
+// Special cases are:
+//	Lgamma(+Inf) = +Inf
+//	Lgamma(0) = +Inf
+//	Lgamma(-integer) = +Inf
+//	Lgamma(-Inf) = -Inf
+//	Lgamma(NaN) = NaN
+func Lgamma(x float64) (lgamma float64, sign int) {
+	const (
+		Ymin  = 1.461632144968362245
+		Two52 = 1 << 52                     // 0x4330000000000000 ~4.5036e+15
+		Two53 = 1 << 53                     // 0x4340000000000000 ~9.0072e+15
+		Two58 = 1 << 58                     // 0x4390000000000000 ~2.8823e+17
+		Tiny  = 1.0 / (1 << 70)             // 0x3b90000000000000 ~8.47033e-22
+		Tc    = 1.46163214496836224576e+00  // 0x3FF762D86356BE3F
+		Tf    = -1.21486290535849611461e-01 // 0xBFBF19B9BCC38A42
+		// Tt = -(tail of Tf)
+		Tt = -3.63867699703950536541e-18 // 0xBC50C7CAA48A971F
+	)
+	// special cases
+	sign = 1
+	switch {
+	case IsNaN(x):
+		lgamma = x
+		return
+	case IsInf(x, 0):
+		lgamma = x
+		return
+	case x == 0:
+		lgamma = Inf(1)
+		return
+	}
+
+	neg := false
+	if x < 0 {
+		x = -x
+		neg = true
+	}
+
+	if x < Tiny { // if |x| < 2**-70, return -log(|x|)
+		if neg {
+			sign = -1
+		}
+		lgamma = -Log(x)
+		return
+	}
+	var nadj float64
+	if neg {
+		if x >= Two52 { // |x| >= 2**52, must be -integer
+			lgamma = Inf(1)
+			return
+		}
+		t := sinPi(x)
+		if t == 0 {
+			lgamma = Inf(1) // -integer
+			return
+		}
+		nadj = Log(Pi / Abs(t*x))
+		if t < 0 {
+			sign = -1
+		}
+	}
+
+	switch {
+	case x == 1 || x == 2: // purge off 1 and 2
+		lgamma = 0
+		return
+	case x < 2: // use lgamma(x) = lgamma(x+1) - log(x)
+		var y float64
+		var i int
+		if x <= 0.9 {
+			lgamma = -Log(x)
+			switch {
+			case x >= (Ymin - 1 + 0.27): // 0.7316 <= x <=  0.9
+				y = 1 - x
+				i = 0
+			case x >= (Ymin - 1 - 0.27): // 0.2316 <= x < 0.7316
+				y = x - (Tc - 1)
+				i = 1
+			default: // 0 < x < 0.2316
+				y = x
+				i = 2
+			}
+		} else {
+			lgamma = 0
+			switch {
+			case x >= (Ymin + 0.27): // 1.7316 <= x < 2
+				y = 2 - x
+				i = 0
+			case x >= (Ymin - 0.27): // 1.2316 <= x < 1.7316
+				y = x - Tc
+				i = 1
+			default: // 0.9 < x < 1.2316
+				y = x - 1
+				i = 2
+			}
+		}
+		switch i {
+		case 0:
+			z := y * y
+			p1 := _lgamA[0] + z*(_lgamA[2]+z*(_lgamA[4]+z*(_lgamA[6]+z*(_lgamA[8]+z*_lgamA[10]))))
+			p2 := z * (_lgamA[1] + z*(+_lgamA[3]+z*(_lgamA[5]+z*(_lgamA[7]+z*(_lgamA[9]+z*_lgamA[11])))))
+			p := y*p1 + p2
+			lgamma += (p - 0.5*y)
+		case 1:
+			z := y * y
+			w := z * y
+			p1 := _lgamT[0] + w*(_lgamT[3]+w*(_lgamT[6]+w*(_lgamT[9]+w*_lgamT[12]))) // parallel comp
+			p2 := _lgamT[1] + w*(_lgamT[4]+w*(_lgamT[7]+w*(_lgamT[10]+w*_lgamT[13])))
+			p3 := _lgamT[2] + w*(_lgamT[5]+w*(_lgamT[8]+w*(_lgamT[11]+w*_lgamT[14])))
+			p := z*p1 - (Tt - w*(p2+y*p3))
+			lgamma += (Tf + p)
+		case 2:
+			p1 := y * (_lgamU[0] + y*(_lgamU[1]+y*(_lgamU[2]+y*(_lgamU[3]+y*(_lgamU[4]+y*_lgamU[5])))))
+			p2 := 1 + y*(_lgamV[1]+y*(_lgamV[2]+y*(_lgamV[3]+y*(_lgamV[4]+y*_lgamV[5]))))
+			lgamma += (-0.5*y + p1/p2)
+		}
+	case x < 8: // 2 <= x < 8
+		i := int(x)
+		y := x - float64(i)
+		p := y * (_lgamS[0] + y*(_lgamS[1]+y*(_lgamS[2]+y*(_lgamS[3]+y*(_lgamS[4]+y*(_lgamS[5]+y*_lgamS[6]))))))
+		q := 1 + y*(_lgamR[1]+y*(_lgamR[2]+y*(_lgamR[3]+y*(_lgamR[4]+y*(_lgamR[5]+y*_lgamR[6])))))
+		lgamma = 0.5*y + p/q
+		z := 1.0 // Lgamma(1+s) = Log(s) + Lgamma(s)
+		switch i {
+		case 7:
+			z *= (y + 6)
+			fallthrough
+		case 6:
+			z *= (y + 5)
+			fallthrough
+		case 5:
+			z *= (y + 4)
+			fallthrough
+		case 4:
+			z *= (y + 3)
+			fallthrough
+		case 3:
+			z *= (y + 2)
+			lgamma += Log(z)
+		}
+	case x < Two58: // 8 <= x < 2**58
+		t := Log(x)
+		z := 1 / x
+		y := z * z
+		w := _lgamW[0] + z*(_lgamW[1]+y*(_lgamW[2]+y*(_lgamW[3]+y*(_lgamW[4]+y*(_lgamW[5]+y*_lgamW[6])))))
+		lgamma = (x-0.5)*(t-1) + w
+	default: // 2**58 <= x <= Inf
+		lgamma = x * (Log(x) - 1)
+	}
+	if neg {
+		lgamma = nadj - lgamma
+	}
+	return
+}
+
+// sinPi(x) is a helper function for negative x
+func sinPi(x float64) float64 {
+	const (
+		Two52 = 1 << 52 // 0x4330000000000000 ~4.5036e+15
+		Two53 = 1 << 53 // 0x4340000000000000 ~9.0072e+15
+	)
+	if x < 0.25 {
+		return -Sin(Pi * x)
+	}
+
+	// argument reduction
+	z := Floor(x)
+	var n int
+	if z != x { // inexact
+		x = Mod(x, 2)
+		n = int(x * 4)
+	} else {
+		if x >= Two53 { // x must be even
+			x = 0
+			n = 0
+		} else {
+			if x < Two52 {
+				z = x + Two52 // exact
+			}
+			n = int(1 & Float64bits(z))
+			x = float64(n)
+			n <<= 2
+		}
+	}
+	switch n {
+	case 0:
+		x = Sin(Pi * x)
+	case 1, 2:
+		x = Cos(Pi * (0.5 - x))
+	case 3, 4:
+		x = Sin(Pi * (1 - x))
+	case 5, 6:
+		x = -Cos(Pi * (x - 1.5))
+	default:
+		x = Sin(Pi * (x - 2))
+	}
+	return -x
+}
diff --git a/third_party/gofrontend/libgo/go/math/log.go b/third_party/gofrontend/libgo/go/math/log.go
new file mode 100644
index 0000000..60b5755
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/log.go
@@ -0,0 +1,129 @@
+// 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 math
+
+/*
+	Floating-point logarithm.
+*/
+
+// The original C code, the long comment, and the constants
+// below are from FreeBSD's /usr/src/lib/msun/src/e_log.c
+// and came with this notice.  The go code is a simpler
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// __ieee754_log(x)
+// Return the logarithm of x
+//
+// Method :
+//   1. Argument Reduction: find k and f such that
+//			x = 2**k * (1+f),
+//	   where  sqrt(2)/2 < 1+f < sqrt(2) .
+//
+//   2. Approximation of log(1+f).
+//	Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+//		 = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+//	     	 = 2s + s*R
+//      We use a special Reme algorithm on [0,0.1716] to generate
+//	a polynomial of degree 14 to approximate R.  The maximum error
+//	of this polynomial approximation is bounded by 2**-58.45. In
+//	other words,
+//		        2      4      6      8      10      12      14
+//	    R(z) ~ L1*s +L2*s +L3*s +L4*s +L5*s  +L6*s  +L7*s
+//	(the values of L1 to L7 are listed in the program) and
+//	    |      2          14          |     -58.45
+//	    | L1*s +...+L7*s    -  R(z) | <= 2
+//	    |                             |
+//	Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+//	In order to guarantee error in log below 1ulp, we compute log by
+//		log(1+f) = f - s*(f - R)		(if f is not too large)
+//		log(1+f) = f - (hfsq - s*(hfsq+R)).	(better accuracy)
+//
+//	3. Finally,  log(x) = k*Ln2 + log(1+f).
+//			    = k*Ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*Ln2_lo)))
+//	   Here Ln2 is split into two floating point number:
+//			Ln2_hi + Ln2_lo,
+//	   where n*Ln2_hi is always exact for |n| < 2000.
+//
+// Special cases:
+//	log(x) is NaN with signal if x < 0 (including -INF) ;
+//	log(+INF) is +INF; log(0) is -INF with signal;
+//	log(NaN) is that NaN with no signal.
+//
+// Accuracy:
+//	according to an error analysis, the error is always less than
+//	1 ulp (unit in the last place).
+//
+// Constants:
+// The hexadecimal values are the intended ones for the following
+// constants. The decimal values may be used, provided that the
+// compiler will convert from decimal to binary accurately enough
+// to produce the hexadecimal values shown.
+
+// Log returns the natural logarithm of x.
+//
+// Special cases are:
+//	Log(+Inf) = +Inf
+//	Log(0) = -Inf
+//	Log(x < 0) = NaN
+//	Log(NaN) = NaN
+
+//extern log
+func libc_log(float64) float64
+
+func Log(x float64) float64 {
+	return libc_log(x)
+}
+
+func log(x float64) float64 {
+	const (
+		Ln2Hi = 6.93147180369123816490e-01 /* 3fe62e42 fee00000 */
+		Ln2Lo = 1.90821492927058770002e-10 /* 3dea39ef 35793c76 */
+		L1    = 6.666666666666735130e-01   /* 3FE55555 55555593 */
+		L2    = 3.999999999940941908e-01   /* 3FD99999 9997FA04 */
+		L3    = 2.857142874366239149e-01   /* 3FD24924 94229359 */
+		L4    = 2.222219843214978396e-01   /* 3FCC71C5 1D8E78AF */
+		L5    = 1.818357216161805012e-01   /* 3FC74664 96CB03DE */
+		L6    = 1.531383769920937332e-01   /* 3FC39A09 D078C69F */
+		L7    = 1.479819860511658591e-01   /* 3FC2F112 DF3E5244 */
+	)
+
+	// special cases
+	switch {
+	case IsNaN(x) || IsInf(x, 1):
+		return x
+	case x < 0:
+		return NaN()
+	case x == 0:
+		return Inf(-1)
+	}
+
+	// reduce
+	f1, ki := Frexp(x)
+	if f1 < Sqrt2/2 {
+		f1 *= 2
+		ki--
+	}
+	f := f1 - 1
+	k := float64(ki)
+
+	// compute
+	s := f / (2 + f)
+	s2 := s * s
+	s4 := s2 * s2
+	t1 := s2 * (L1 + s4*(L3+s4*(L5+s4*L7)))
+	t2 := s4 * (L2 + s4*(L4+s4*L6))
+	R := t1 + t2
+	hfsq := 0.5 * f * f
+	return k*Ln2Hi - ((hfsq - (s*(hfsq+R) + k*Ln2Lo)) - f)
+}
diff --git a/third_party/gofrontend/libgo/go/math/log10.go b/third_party/gofrontend/libgo/go/math/log10.go
new file mode 100644
index 0000000..d880ec2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/log10.go
@@ -0,0 +1,31 @@
+// 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 math
+
+// Log10 returns the decimal logarithm of x.
+// The special cases are the same as for Log.
+
+//extern log10
+func libc_log10(float64) float64
+
+func Log10(x float64) float64 {
+	return libc_log10(x)
+}
+
+func log10(x float64) float64 {
+	return Log(x) * (1 / Ln10)
+}
+
+// Log2 returns the binary logarithm of x.
+// The special cases are the same as for Log.
+
+func Log2(x float64) float64 {
+	return log2(x)
+}
+
+func log2(x float64) float64 {
+	frac, exp := Frexp(x)
+	return Log(frac)*(1/Ln2) + float64(exp)
+}
diff --git a/third_party/gofrontend/libgo/go/math/log1p.go b/third_party/gofrontend/libgo/go/math/log1p.go
new file mode 100644
index 0000000..c8daaaa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/log1p.go
@@ -0,0 +1,206 @@
+// Copyright 2010 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 math
+
+// The original C code, the long comment, and the constants
+// below are from FreeBSD's /usr/src/lib/msun/src/s_log1p.c
+// and came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+//
+// double log1p(double x)
+//
+// Method :
+//   1. Argument Reduction: find k and f such that
+//                      1+x = 2**k * (1+f),
+//         where  sqrt(2)/2 < 1+f < sqrt(2) .
+//
+//      Note. If k=0, then f=x is exact. However, if k!=0, then f
+//      may not be representable exactly. In that case, a correction
+//      term is need. Let u=1+x rounded. Let c = (1+x)-u, then
+//      log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
+//      and add back the correction term c/u.
+//      (Note: when x > 2**53, one can simply return log(x))
+//
+//   2. Approximation of log1p(f).
+//      Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+//               = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+//               = 2s + s*R
+//      We use a special Reme algorithm on [0,0.1716] to generate
+//      a polynomial of degree 14 to approximate R The maximum error
+//      of this polynomial approximation is bounded by 2**-58.45. In
+//      other words,
+//                      2      4      6      8      10      12      14
+//          R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s  +Lp6*s  +Lp7*s
+//      (the values of Lp1 to Lp7 are listed in the program)
+//      and
+//          |      2          14          |     -58.45
+//          | Lp1*s +...+Lp7*s    -  R(z) | <= 2
+//          |                             |
+//      Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+//      In order to guarantee error in log below 1ulp, we compute log
+//      by
+//              log1p(f) = f - (hfsq - s*(hfsq+R)).
+//
+//   3. Finally, log1p(x) = k*ln2 + log1p(f).
+//                        = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+//      Here ln2 is split into two floating point number:
+//                   ln2_hi + ln2_lo,
+//      where n*ln2_hi is always exact for |n| < 2000.
+//
+// Special cases:
+//      log1p(x) is NaN with signal if x < -1 (including -INF) ;
+//      log1p(+INF) is +INF; log1p(-1) is -INF with signal;
+//      log1p(NaN) is that NaN with no signal.
+//
+// Accuracy:
+//      according to an error analysis, the error is always less than
+//      1 ulp (unit in the last place).
+//
+// Constants:
+// The hexadecimal values are the intended ones for the following
+// constants. The decimal values may be used, provided that the
+// compiler will convert from decimal to binary accurately enough
+// to produce the hexadecimal values shown.
+//
+// Note: Assuming log() return accurate answer, the following
+//       algorithm can be used to compute log1p(x) to within a few ULP:
+//
+//              u = 1+x;
+//              if(u==1.0) return x ; else
+//                         return log(u)*(x/(u-1.0));
+//
+//       See HP-15C Advanced Functions Handbook, p.193.
+
+// Log1p returns the natural logarithm of 1 plus its argument x.
+// It is more accurate than Log(1 + x) when x is near zero.
+//
+// Special cases are:
+//	Log1p(+Inf) = +Inf
+//	Log1p(±0) = ±0
+//	Log1p(-1) = -Inf
+//	Log1p(x < -1) = NaN
+//	Log1p(NaN) = NaN
+
+//extern log1p
+func libc_log1p(float64) float64
+
+func Log1p(x float64) float64 {
+	return libc_log1p(x)
+}
+
+func log1p(x float64) float64 {
+	const (
+		Sqrt2M1     = 4.142135623730950488017e-01  // Sqrt(2)-1 = 0x3fda827999fcef34
+		Sqrt2HalfM1 = -2.928932188134524755992e-01 // Sqrt(2)/2-1 = 0xbfd2bec333018866
+		Small       = 1.0 / (1 << 29)              // 2**-29 = 0x3e20000000000000
+		Tiny        = 1.0 / (1 << 54)              // 2**-54
+		Two53       = 1 << 53                      // 2**53
+		Ln2Hi       = 6.93147180369123816490e-01   // 3fe62e42fee00000
+		Ln2Lo       = 1.90821492927058770002e-10   // 3dea39ef35793c76
+		Lp1         = 6.666666666666735130e-01     // 3FE5555555555593
+		Lp2         = 3.999999999940941908e-01     // 3FD999999997FA04
+		Lp3         = 2.857142874366239149e-01     // 3FD2492494229359
+		Lp4         = 2.222219843214978396e-01     // 3FCC71C51D8E78AF
+		Lp5         = 1.818357216161805012e-01     // 3FC7466496CB03DE
+		Lp6         = 1.531383769920937332e-01     // 3FC39A09D078C69F
+		Lp7         = 1.479819860511658591e-01     // 3FC2F112DF3E5244
+	)
+
+	// special cases
+	switch {
+	case x < -1 || IsNaN(x): // includes -Inf
+		return NaN()
+	case x == -1:
+		return Inf(-1)
+	case IsInf(x, 1):
+		return Inf(1)
+	}
+
+	absx := x
+	if absx < 0 {
+		absx = -absx
+	}
+
+	var f float64
+	var iu uint64
+	k := 1
+	if absx < Sqrt2M1 { //  |x| < Sqrt(2)-1
+		if absx < Small { // |x| < 2**-29
+			if absx < Tiny { // |x| < 2**-54
+				return x
+			}
+			return x - x*x*0.5
+		}
+		if x > Sqrt2HalfM1 { // Sqrt(2)/2-1 < x
+			// (Sqrt(2)/2-1) < x < (Sqrt(2)-1)
+			k = 0
+			f = x
+			iu = 1
+		}
+	}
+	var c float64
+	if k != 0 {
+		var u float64
+		if absx < Two53 { // 1<<53
+			u = 1.0 + x
+			iu = Float64bits(u)
+			k = int((iu >> 52) - 1023)
+			if k > 0 {
+				c = 1.0 - (u - x)
+			} else {
+				c = x - (u - 1.0) // correction term
+				c /= u
+			}
+		} else {
+			u = x
+			iu = Float64bits(u)
+			k = int((iu >> 52) - 1023)
+			c = 0
+		}
+		iu &= 0x000fffffffffffff
+		if iu < 0x0006a09e667f3bcd { // mantissa of Sqrt(2)
+			u = Float64frombits(iu | 0x3ff0000000000000) // normalize u
+		} else {
+			k += 1
+			u = Float64frombits(iu | 0x3fe0000000000000) // normalize u/2
+			iu = (0x0010000000000000 - iu) >> 2
+		}
+		f = u - 1.0 // Sqrt(2)/2 < u < Sqrt(2)
+	}
+	hfsq := 0.5 * f * f
+	var s, R, z float64
+	if iu == 0 { // |f| < 2**-20
+		if f == 0 {
+			if k == 0 {
+				return 0
+			} else {
+				c += float64(k) * Ln2Lo
+				return float64(k)*Ln2Hi + c
+			}
+		}
+		R = hfsq * (1.0 - 0.66666666666666666*f) // avoid division
+		if k == 0 {
+			return f - R
+		}
+		return float64(k)*Ln2Hi - ((R - (float64(k)*Ln2Lo + c)) - f)
+	}
+	s = f / (2.0 + f)
+	z = s * s
+	R = z * (Lp1 + z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))))
+	if k == 0 {
+		return f - (hfsq - s*(hfsq+R))
+	}
+	return float64(k)*Ln2Hi - ((hfsq - (s*(hfsq+R) + (float64(k)*Ln2Lo + c))) - f)
+}
diff --git a/third_party/gofrontend/libgo/go/math/logb.go b/third_party/gofrontend/libgo/go/math/logb.go
new file mode 100644
index 0000000..f2769d4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/logb.go
@@ -0,0 +1,50 @@
+// Copyright 2010 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 math
+
+// Logb returns the binary exponent of x.
+//
+// Special cases are:
+//	Logb(±Inf) = +Inf
+//	Logb(0) = -Inf
+//	Logb(NaN) = NaN
+func Logb(x float64) float64 {
+	// special cases
+	switch {
+	case x == 0:
+		return Inf(-1)
+	case IsInf(x, 0):
+		return Inf(1)
+	case IsNaN(x):
+		return x
+	}
+	return float64(ilogb(x))
+}
+
+// Ilogb returns the binary exponent of x as an integer.
+//
+// Special cases are:
+//	Ilogb(±Inf) = MaxInt32
+//	Ilogb(0) = MinInt32
+//	Ilogb(NaN) = MaxInt32
+func Ilogb(x float64) int {
+	// special cases
+	switch {
+	case x == 0:
+		return MinInt32
+	case IsNaN(x):
+		return MaxInt32
+	case IsInf(x, 0):
+		return MaxInt32
+	}
+	return ilogb(x)
+}
+
+// logb returns the binary exponent of x. It assumes x is finite and
+// non-zero.
+func ilogb(x float64) int {
+	x, exp := normalize(x)
+	return int((Float64bits(x)>>shift)&mask) - bias + exp
+}
diff --git a/third_party/gofrontend/libgo/go/math/mod.go b/third_party/gofrontend/libgo/go/math/mod.go
new file mode 100644
index 0000000..0b208f4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/mod.go
@@ -0,0 +1,56 @@
+// Copyright 2009-2010 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 math
+
+/*
+	Floating-point mod function.
+*/
+
+// Mod returns the floating-point remainder of x/y.
+// The magnitude of the result is less than y and its
+// sign agrees with that of x.
+//
+// Special cases are:
+//	Mod(±Inf, y) = NaN
+//	Mod(NaN, y) = NaN
+//	Mod(x, 0) = NaN
+//	Mod(x, ±Inf) = x
+//	Mod(x, NaN) = NaN
+
+//extern fmod
+func libc_fmod(float64, float64) float64
+
+func Mod(x, y float64) float64 {
+	return libc_fmod(x, y)
+}
+
+func mod(x, y float64) float64 {
+	if y == 0 || IsInf(x, 0) || IsNaN(x) || IsNaN(y) {
+		return NaN()
+	}
+	if y < 0 {
+		y = -y
+	}
+
+	yfr, yexp := Frexp(y)
+	sign := false
+	r := x
+	if x < 0 {
+		r = -x
+		sign = true
+	}
+
+	for r >= y {
+		rfr, rexp := Frexp(r)
+		if rfr < yfr {
+			rexp = rexp - 1
+		}
+		r = r - Ldexp(y, rexp-yexp)
+	}
+	if sign {
+		r = -r
+	}
+	return r
+}
diff --git a/third_party/gofrontend/libgo/go/math/modf.go b/third_party/gofrontend/libgo/go/math/modf.go
new file mode 100644
index 0000000..ecec4b7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/modf.go
@@ -0,0 +1,36 @@
+// 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 math
+
+// Modf returns integer and fractional floating-point numbers
+// that sum to f.  Both values have the same sign as f.
+//
+// Special cases are:
+//	Modf(±Inf) = ±Inf, NaN
+//	Modf(NaN) = NaN, NaN
+func Modf(f float64) (int float64, frac float64) {
+	return modf(f)
+}
+
+func modf(f float64) (int float64, frac float64) {
+	if f < 1 {
+		if f < 0 {
+			int, frac = Modf(-f)
+			return -int, -frac
+		}
+		return 0, f
+	}
+
+	x := Float64bits(f)
+	e := uint(x>>shift)&mask - bias
+
+	// Keep the top 12+e bits, the integer part; clear the rest.
+	if e < 64-12 {
+		x &^= 1<<(64-12-e) - 1
+	}
+	int = Float64frombits(x)
+	frac = f - int
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/math/nextafter.go b/third_party/gofrontend/libgo/go/math/nextafter.go
new file mode 100644
index 0000000..7c4b5bc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/nextafter.go
@@ -0,0 +1,27 @@
+// Copyright 2010 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 math
+
+// Nextafter returns the next representable value after x towards y.
+// If x == y, then x is returned.
+//
+// Special cases are:
+//      Nextafter(NaN, y) = NaN
+//      Nextafter(x, NaN) = NaN
+func Nextafter(x, y float64) (r float64) {
+	switch {
+	case IsNaN(x) || IsNaN(y): // special case
+		r = NaN()
+	case x == y:
+		r = x
+	case x == 0:
+		r = Copysign(Float64frombits(1), y)
+	case (y > x) == (x > 0):
+		r = Float64frombits(Float64bits(x) + 1)
+	default:
+		r = Float64frombits(Float64bits(x) - 1)
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/math/pow.go b/third_party/gofrontend/libgo/go/math/pow.go
new file mode 100644
index 0000000..77af256
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/pow.go
@@ -0,0 +1,137 @@
+// 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 math
+
+func isOddInt(x float64) bool {
+	xi, xf := Modf(x)
+	return xf == 0 && int64(xi)&1 == 1
+}
+
+// Special cases taken from FreeBSD's /usr/src/lib/msun/src/e_pow.c
+// updated by IEEE Std. 754-2008 "Section 9.2.1 Special values".
+
+// Pow returns x**y, the base-x exponential of y.
+//
+// Special cases are (in order):
+//	Pow(x, ±0) = 1 for any x
+//	Pow(1, y) = 1 for any y
+//	Pow(x, 1) = x for any x
+//	Pow(NaN, y) = NaN
+//	Pow(x, NaN) = NaN
+//	Pow(±0, y) = ±Inf for y an odd integer < 0
+//	Pow(±0, -Inf) = +Inf
+//	Pow(±0, +Inf) = +0
+//	Pow(±0, y) = +Inf for finite y < 0 and not an odd integer
+//	Pow(±0, y) = ±0 for y an odd integer > 0
+//	Pow(±0, y) = +0 for finite y > 0 and not an odd integer
+//	Pow(-1, ±Inf) = 1
+//	Pow(x, +Inf) = +Inf for |x| > 1
+//	Pow(x, -Inf) = +0 for |x| > 1
+//	Pow(x, +Inf) = +0 for |x| < 1
+//	Pow(x, -Inf) = +Inf for |x| < 1
+//	Pow(+Inf, y) = +Inf for y > 0
+//	Pow(+Inf, y) = +0 for y < 0
+//	Pow(-Inf, y) = Pow(-0, -y)
+//	Pow(x, y) = NaN for finite x < 0 and finite non-integer y
+func Pow(x, y float64) float64 {
+	switch {
+	case y == 0 || x == 1:
+		return 1
+	case y == 1:
+		return x
+	case y == 0.5:
+		return Sqrt(x)
+	case y == -0.5:
+		return 1 / Sqrt(x)
+	case IsNaN(x) || IsNaN(y):
+		return NaN()
+	case x == 0:
+		switch {
+		case y < 0:
+			if isOddInt(y) {
+				return Copysign(Inf(1), x)
+			}
+			return Inf(1)
+		case y > 0:
+			if isOddInt(y) {
+				return x
+			}
+			return 0
+		}
+	case IsInf(y, 0):
+		switch {
+		case x == -1:
+			return 1
+		case (Abs(x) < 1) == IsInf(y, 1):
+			return 0
+		default:
+			return Inf(1)
+		}
+	case IsInf(x, 0):
+		if IsInf(x, -1) {
+			return Pow(1/x, -y) // Pow(-0, -y)
+		}
+		switch {
+		case y < 0:
+			return 0
+		case y > 0:
+			return Inf(1)
+		}
+	}
+
+	absy := y
+	flip := false
+	if absy < 0 {
+		absy = -absy
+		flip = true
+	}
+	yi, yf := Modf(absy)
+	if yf != 0 && x < 0 {
+		return NaN()
+	}
+	if yi >= 1<<63 {
+		return Exp(y * Log(x))
+	}
+
+	// ans = a1 * 2**ae (= 1 for now).
+	a1 := 1.0
+	ae := 0
+
+	// ans *= x**yf
+	if yf != 0 {
+		if yf > 0.5 {
+			yf--
+			yi++
+		}
+		a1 = Exp(yf * Log(x))
+	}
+
+	// ans *= x**yi
+	// by multiplying in successive squarings
+	// of x according to bits of yi.
+	// accumulate powers of two into exp.
+	x1, xe := Frexp(x)
+	for i := int64(yi); i != 0; i >>= 1 {
+		if i&1 == 1 {
+			a1 *= x1
+			ae += xe
+		}
+		x1 *= x1
+		xe <<= 1
+		if x1 < .5 {
+			x1 += x1
+			xe--
+		}
+	}
+
+	// ans = a1*2**ae
+	// if flip { ans = 1 / ans }
+	// but in the opposite order
+	if flip {
+		a1 = 1 / a1
+		ae = -ae
+	}
+	return Ldexp(a1, ae)
+}
diff --git a/third_party/gofrontend/libgo/go/math/pow10.go b/third_party/gofrontend/libgo/go/math/pow10.go
new file mode 100644
index 0000000..f5ad28b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/pow10.go
@@ -0,0 +1,40 @@
+// 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 math
+
+// This table might overflow 127-bit exponent representations.
+// In that case, truncate it after 1.0e38.
+var pow10tab [70]float64
+
+// Pow10 returns 10**e, the base-10 exponential of e.
+//
+// Special cases are:
+//	Pow10(e) = +Inf for e > 309
+//	Pow10(e) = 0 for e < -324
+func Pow10(e int) float64 {
+	if e <= -325 {
+		return 0
+	} else if e > 309 {
+		return Inf(1)
+	}
+
+	if e < 0 {
+		return 1 / Pow10(-e)
+	}
+	if e < len(pow10tab) {
+		return pow10tab[e]
+	}
+	m := e / 2
+	return Pow10(m) * Pow10(e-m)
+}
+
+func init() {
+	pow10tab[0] = 1.0e0
+	pow10tab[1] = 1.0e1
+	for i := 2; i < len(pow10tab); i++ {
+		m := i / 2
+		pow10tab[i] = pow10tab[m] * pow10tab[i-m]
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/math/rand/exp.go b/third_party/gofrontend/libgo/go/math/rand/exp.go
new file mode 100644
index 0000000..4bc110f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/rand/exp.go
@@ -0,0 +1,222 @@
+// 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 rand
+
+import (
+	"math"
+)
+
+/*
+ * Exponential distribution
+ *
+ * See "The Ziggurat Method for Generating Random Variables"
+ * (Marsaglia & Tsang, 2000)
+ * http://www.jstatsoft.org/v05/i08/paper [pdf]
+ */
+
+const (
+	re = 7.69711747013104972
+)
+
+// ExpFloat64 returns an exponentially distributed float64 in the range
+// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
+// (lambda) is 1 and whose mean is 1/lambda (1).
+// To produce a distribution with a different rate parameter,
+// callers can adjust the output using:
+//
+//  sample = ExpFloat64() / desiredRateParameter
+//
+func (r *Rand) ExpFloat64() float64 {
+	for {
+		j := r.Uint32()
+		i := j & 0xFF
+		x := float64(j) * float64(we[i])
+		if j < ke[i] {
+			return x
+		}
+		if i == 0 {
+			return re - math.Log(r.Float64())
+		}
+		if fe[i]+float32(r.Float64())*(fe[i-1]-fe[i]) < float32(math.Exp(-x)) {
+			return x
+		}
+	}
+}
+
+var ke = [256]uint32{
+	0xe290a139, 0x0, 0x9beadebc, 0xc377ac71, 0xd4ddb990,
+	0xde893fb8, 0xe4a8e87c, 0xe8dff16a, 0xebf2deab, 0xee49a6e8,
+	0xf0204efd, 0xf19bdb8e, 0xf2d458bb, 0xf3da104b, 0xf4b86d78,
+	0xf577ad8a, 0xf61de83d, 0xf6afb784, 0xf730a573, 0xf7a37651,
+	0xf80a5bb6, 0xf867189d, 0xf8bb1b4f, 0xf9079062, 0xf94d70ca,
+	0xf98d8c7d, 0xf9c8928a, 0xf9ff175b, 0xfa319996, 0xfa6085f8,
+	0xfa8c3a62, 0xfab5084e, 0xfadb36c8, 0xfaff0410, 0xfb20a6ea,
+	0xfb404fb4, 0xfb5e2951, 0xfb7a59e9, 0xfb95038c, 0xfbae44ba,
+	0xfbc638d8, 0xfbdcf892, 0xfbf29a30, 0xfc0731df, 0xfc1ad1ed,
+	0xfc2d8b02, 0xfc3f6c4d, 0xfc5083ac, 0xfc60ddd1, 0xfc708662,
+	0xfc7f8810, 0xfc8decb4, 0xfc9bbd62, 0xfca9027c, 0xfcb5c3c3,
+	0xfcc20864, 0xfccdd70a, 0xfcd935e3, 0xfce42ab0, 0xfceebace,
+	0xfcf8eb3b, 0xfd02c0a0, 0xfd0c3f59, 0xfd156b7b, 0xfd1e48d6,
+	0xfd26daff, 0xfd2f2552, 0xfd372af7, 0xfd3eeee5, 0xfd4673e7,
+	0xfd4dbc9e, 0xfd54cb85, 0xfd5ba2f2, 0xfd62451b, 0xfd68b415,
+	0xfd6ef1da, 0xfd750047, 0xfd7ae120, 0xfd809612, 0xfd8620b4,
+	0xfd8b8285, 0xfd90bcf5, 0xfd95d15e, 0xfd9ac10b, 0xfd9f8d36,
+	0xfda43708, 0xfda8bf9e, 0xfdad2806, 0xfdb17141, 0xfdb59c46,
+	0xfdb9a9fd, 0xfdbd9b46, 0xfdc170f6, 0xfdc52bd8, 0xfdc8ccac,
+	0xfdcc542d, 0xfdcfc30b, 0xfdd319ef, 0xfdd6597a, 0xfdd98245,
+	0xfddc94e5, 0xfddf91e6, 0xfde279ce, 0xfde54d1f, 0xfde80c52,
+	0xfdeab7de, 0xfded5034, 0xfdefd5be, 0xfdf248e3, 0xfdf4aa06,
+	0xfdf6f984, 0xfdf937b6, 0xfdfb64f4, 0xfdfd818d, 0xfdff8dd0,
+	0xfe018a08, 0xfe03767a, 0xfe05536c, 0xfe07211c, 0xfe08dfc9,
+	0xfe0a8fab, 0xfe0c30fb, 0xfe0dc3ec, 0xfe0f48b1, 0xfe10bf76,
+	0xfe122869, 0xfe1383b4, 0xfe14d17c, 0xfe1611e7, 0xfe174516,
+	0xfe186b2a, 0xfe19843e, 0xfe1a9070, 0xfe1b8fd6, 0xfe1c8289,
+	0xfe1d689b, 0xfe1e4220, 0xfe1f0f26, 0xfe1fcfbc, 0xfe2083ed,
+	0xfe212bc3, 0xfe21c745, 0xfe225678, 0xfe22d95f, 0xfe234ffb,
+	0xfe23ba4a, 0xfe241849, 0xfe2469f2, 0xfe24af3c, 0xfe24e81e,
+	0xfe25148b, 0xfe253474, 0xfe2547c7, 0xfe254e70, 0xfe25485a,
+	0xfe25356a, 0xfe251586, 0xfe24e88f, 0xfe24ae64, 0xfe2466e1,
+	0xfe2411df, 0xfe23af34, 0xfe233eb4, 0xfe22c02c, 0xfe22336b,
+	0xfe219838, 0xfe20ee58, 0xfe20358c, 0xfe1f6d92, 0xfe1e9621,
+	0xfe1daef0, 0xfe1cb7ac, 0xfe1bb002, 0xfe1a9798, 0xfe196e0d,
+	0xfe1832fd, 0xfe16e5fe, 0xfe15869d, 0xfe141464, 0xfe128ed3,
+	0xfe10f565, 0xfe0f478c, 0xfe0d84b1, 0xfe0bac36, 0xfe09bd73,
+	0xfe07b7b5, 0xfe059a40, 0xfe03644c, 0xfe011504, 0xfdfeab88,
+	0xfdfc26e9, 0xfdf98629, 0xfdf6c83b, 0xfdf3ec01, 0xfdf0f04a,
+	0xfdedd3d1, 0xfdea953d, 0xfde7331e, 0xfde3abe9, 0xfddffdfb,
+	0xfddc2791, 0xfdd826cd, 0xfdd3f9a8, 0xfdcf9dfc, 0xfdcb1176,
+	0xfdc65198, 0xfdc15bb3, 0xfdbc2ce2, 0xfdb6c206, 0xfdb117be,
+	0xfdab2a63, 0xfda4f5fd, 0xfd9e7640, 0xfd97a67a, 0xfd908192,
+	0xfd8901f2, 0xfd812182, 0xfd78d98e, 0xfd7022bb, 0xfd66f4ed,
+	0xfd5d4732, 0xfd530f9c, 0xfd48432b, 0xfd3cd59a, 0xfd30b936,
+	0xfd23dea4, 0xfd16349e, 0xfd07a7a3, 0xfcf8219b, 0xfce7895b,
+	0xfcd5c220, 0xfcc2aadb, 0xfcae1d5e, 0xfc97ed4e, 0xfc7fe6d4,
+	0xfc65ccf3, 0xfc495762, 0xfc2a2fc8, 0xfc07ee19, 0xfbe213c1,
+	0xfbb8051a, 0xfb890078, 0xfb5411a5, 0xfb180005, 0xfad33482,
+	0xfa839276, 0xfa263b32, 0xf9b72d1c, 0xf930a1a2, 0xf889f023,
+	0xf7b577d2, 0xf69c650c, 0xf51530f0, 0xf2cb0e3c, 0xeeefb15d,
+	0xe6da6ecf,
+}
+var we = [256]float32{
+	2.0249555e-09, 1.486674e-11, 2.4409617e-11, 3.1968806e-11,
+	3.844677e-11, 4.4228204e-11, 4.9516443e-11, 5.443359e-11,
+	5.905944e-11, 6.344942e-11, 6.7643814e-11, 7.1672945e-11,
+	7.556032e-11, 7.932458e-11, 8.298079e-11, 8.654132e-11,
+	9.0016515e-11, 9.3415074e-11, 9.674443e-11, 1.0001099e-10,
+	1.03220314e-10, 1.06377254e-10, 1.09486115e-10, 1.1255068e-10,
+	1.1557435e-10, 1.1856015e-10, 1.2151083e-10, 1.2442886e-10,
+	1.2731648e-10, 1.3017575e-10, 1.3300853e-10, 1.3581657e-10,
+	1.3860142e-10, 1.4136457e-10, 1.4410738e-10, 1.4683108e-10,
+	1.4953687e-10, 1.5222583e-10, 1.54899e-10, 1.5755733e-10,
+	1.6020171e-10, 1.6283301e-10, 1.6545203e-10, 1.6805951e-10,
+	1.7065617e-10, 1.732427e-10, 1.7581973e-10, 1.7838787e-10,
+	1.8094774e-10, 1.8349985e-10, 1.8604476e-10, 1.8858298e-10,
+	1.9111498e-10, 1.9364126e-10, 1.9616223e-10, 1.9867835e-10,
+	2.0119004e-10, 2.0369768e-10, 2.0620168e-10, 2.087024e-10,
+	2.1120022e-10, 2.136955e-10, 2.1618855e-10, 2.1867974e-10,
+	2.2116936e-10, 2.2365775e-10, 2.261452e-10, 2.2863202e-10,
+	2.311185e-10, 2.3360494e-10, 2.360916e-10, 2.3857874e-10,
+	2.4106667e-10, 2.4355562e-10, 2.4604588e-10, 2.485377e-10,
+	2.5103128e-10, 2.5352695e-10, 2.560249e-10, 2.585254e-10,
+	2.6102867e-10, 2.6353494e-10, 2.6604446e-10, 2.6855745e-10,
+	2.7107416e-10, 2.7359479e-10, 2.761196e-10, 2.7864877e-10,
+	2.8118255e-10, 2.8372119e-10, 2.8626485e-10, 2.888138e-10,
+	2.9136826e-10, 2.939284e-10, 2.9649452e-10, 2.9906677e-10,
+	3.016454e-10, 3.0423064e-10, 3.0682268e-10, 3.0942177e-10,
+	3.1202813e-10, 3.1464195e-10, 3.1726352e-10, 3.19893e-10,
+	3.2253064e-10, 3.251767e-10, 3.2783135e-10, 3.3049485e-10,
+	3.3316744e-10, 3.3584938e-10, 3.3854083e-10, 3.4124212e-10,
+	3.4395342e-10, 3.46675e-10, 3.4940711e-10, 3.5215003e-10,
+	3.5490397e-10, 3.5766917e-10, 3.6044595e-10, 3.6323455e-10,
+	3.660352e-10, 3.6884823e-10, 3.7167386e-10, 3.745124e-10,
+	3.773641e-10, 3.802293e-10, 3.8310827e-10, 3.860013e-10,
+	3.8890866e-10, 3.918307e-10, 3.9476775e-10, 3.9772008e-10,
+	4.0068804e-10, 4.0367196e-10, 4.0667217e-10, 4.09689e-10,
+	4.1272286e-10, 4.1577405e-10, 4.1884296e-10, 4.2192994e-10,
+	4.250354e-10, 4.281597e-10, 4.313033e-10, 4.3446652e-10,
+	4.3764986e-10, 4.408537e-10, 4.4407847e-10, 4.4732465e-10,
+	4.5059267e-10, 4.5388301e-10, 4.571962e-10, 4.6053267e-10,
+	4.6389292e-10, 4.6727755e-10, 4.70687e-10, 4.741219e-10,
+	4.7758275e-10, 4.810702e-10, 4.845848e-10, 4.8812715e-10,
+	4.9169796e-10, 4.9529775e-10, 4.989273e-10, 5.0258725e-10,
+	5.0627835e-10, 5.100013e-10, 5.1375687e-10, 5.1754584e-10,
+	5.21369e-10, 5.2522725e-10, 5.2912136e-10, 5.330522e-10,
+	5.370208e-10, 5.4102806e-10, 5.45075e-10, 5.491625e-10,
+	5.532918e-10, 5.5746385e-10, 5.616799e-10, 5.6594107e-10,
+	5.7024857e-10, 5.746037e-10, 5.7900773e-10, 5.834621e-10,
+	5.8796823e-10, 5.925276e-10, 5.971417e-10, 6.018122e-10,
+	6.065408e-10, 6.113292e-10, 6.1617933e-10, 6.2109295e-10,
+	6.260722e-10, 6.3111916e-10, 6.3623595e-10, 6.4142497e-10,
+	6.4668854e-10, 6.5202926e-10, 6.5744976e-10, 6.6295286e-10,
+	6.6854156e-10, 6.742188e-10, 6.79988e-10, 6.858526e-10,
+	6.9181616e-10, 6.978826e-10, 7.04056e-10, 7.103407e-10,
+	7.167412e-10, 7.2326256e-10, 7.2990985e-10, 7.366886e-10,
+	7.4360473e-10, 7.5066453e-10, 7.5787476e-10, 7.6524265e-10,
+	7.7277595e-10, 7.80483e-10, 7.883728e-10, 7.9645507e-10,
+	8.047402e-10, 8.1323964e-10, 8.219657e-10, 8.309319e-10,
+	8.401528e-10, 8.496445e-10, 8.594247e-10, 8.6951274e-10,
+	8.799301e-10, 8.9070046e-10, 9.018503e-10, 9.134092e-10,
+	9.254101e-10, 9.378904e-10, 9.508923e-10, 9.644638e-10,
+	9.786603e-10, 9.935448e-10, 1.0091913e-09, 1.025686e-09,
+	1.0431306e-09, 1.0616465e-09, 1.08138e-09, 1.1025096e-09,
+	1.1252564e-09, 1.1498986e-09, 1.1767932e-09, 1.206409e-09,
+	1.2393786e-09, 1.276585e-09, 1.3193139e-09, 1.3695435e-09,
+	1.4305498e-09, 1.508365e-09, 1.6160854e-09, 1.7921248e-09,
+}
+var fe = [256]float32{
+	1, 0.9381437, 0.90046996, 0.87170434, 0.8477855, 0.8269933,
+	0.8084217, 0.7915276, 0.77595687, 0.7614634, 0.7478686,
+	0.7350381, 0.72286767, 0.71127474, 0.70019263, 0.6895665,
+	0.67935055, 0.6695063, 0.66000086, 0.65080583, 0.6418967,
+	0.63325197, 0.6248527, 0.6166822, 0.60872537, 0.60096896,
+	0.5934009, 0.58601034, 0.5787874, 0.57172304, 0.5648092,
+	0.5580383, 0.5514034, 0.5448982, 0.5385169, 0.53225386,
+	0.5261042, 0.52006316, 0.5141264, 0.50828975, 0.5025495,
+	0.496902, 0.49134386, 0.485872, 0.48048335, 0.4751752,
+	0.46994483, 0.46478975, 0.45970762, 0.45469615, 0.44975325,
+	0.44487688, 0.44006512, 0.43531612, 0.43062815, 0.42599955,
+	0.42142874, 0.4169142, 0.41245446, 0.40804818, 0.403694,
+	0.3993907, 0.39513698, 0.39093173, 0.38677382, 0.38266218,
+	0.37859577, 0.37457356, 0.37059465, 0.3666581, 0.362763,
+	0.35890847, 0.35509375, 0.351318, 0.3475805, 0.34388044,
+	0.34021714, 0.3365899, 0.33299807, 0.32944095, 0.32591796,
+	0.3224285, 0.3189719, 0.31554767, 0.31215525, 0.30879408,
+	0.3054636, 0.3021634, 0.29889292, 0.2956517, 0.29243928,
+	0.28925523, 0.28609908, 0.28297043, 0.27986884, 0.27679393,
+	0.2737453, 0.2707226, 0.2677254, 0.26475343, 0.26180625,
+	0.25888354, 0.25598502, 0.2531103, 0.25025907, 0.24743107,
+	0.24462597, 0.24184346, 0.23908329, 0.23634516, 0.23362878,
+	0.23093392, 0.2282603, 0.22560766, 0.22297576, 0.22036438,
+	0.21777324, 0.21520215, 0.21265087, 0.21011916, 0.20760682,
+	0.20511365, 0.20263945, 0.20018397, 0.19774707, 0.19532852,
+	0.19292815, 0.19054577, 0.1881812, 0.18583426, 0.18350479,
+	0.1811926, 0.17889754, 0.17661946, 0.17435817, 0.17211354,
+	0.1698854, 0.16767362, 0.16547804, 0.16329853, 0.16113494,
+	0.15898713, 0.15685499, 0.15473837, 0.15263714, 0.15055119,
+	0.14848037, 0.14642459, 0.14438373, 0.14235765, 0.14034624,
+	0.13834943, 0.13636707, 0.13439907, 0.13244532, 0.13050574,
+	0.1285802, 0.12666863, 0.12477092, 0.12288698, 0.12101672,
+	0.119160056, 0.1173169, 0.115487166, 0.11367077, 0.11186763,
+	0.11007768, 0.10830083, 0.10653701, 0.10478614, 0.10304816,
+	0.101323, 0.09961058, 0.09791085, 0.09622374, 0.09454919,
+	0.09288713, 0.091237515, 0.08960028, 0.087975375, 0.08636274,
+	0.08476233, 0.083174095, 0.081597984, 0.08003395, 0.07848195,
+	0.076941945, 0.07541389, 0.07389775, 0.072393484, 0.07090106,
+	0.069420435, 0.06795159, 0.066494495, 0.06504912, 0.063615434,
+	0.062193416, 0.060783047, 0.059384305, 0.057997175,
+	0.05662164, 0.05525769, 0.053905312, 0.052564494, 0.051235236,
+	0.049917534, 0.048611384, 0.047316793, 0.046033762, 0.0447623,
+	0.043502413, 0.042254124, 0.041017443, 0.039792392,
+	0.038578995, 0.037377283, 0.036187284, 0.035009038,
+	0.033842582, 0.032687962, 0.031545233, 0.030414443, 0.02929566,
+	0.02818895, 0.027094385, 0.026012046, 0.024942026, 0.023884421,
+	0.022839336, 0.021806888, 0.020787204, 0.019780423, 0.0187867,
+	0.0178062, 0.016839107, 0.015885621, 0.014945968, 0.014020392,
+	0.013109165, 0.012212592, 0.011331013, 0.01046481, 0.009614414,
+	0.008780315, 0.007963077, 0.0071633533, 0.006381906,
+	0.0056196423, 0.0048776558, 0.004157295, 0.0034602648,
+	0.0027887989, 0.0021459677, 0.0015362998, 0.0009672693,
+	0.00045413437,
+}
diff --git a/third_party/gofrontend/libgo/go/math/rand/normal.go b/third_party/gofrontend/libgo/go/math/rand/normal.go
new file mode 100644
index 0000000..ba4ea54
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/rand/normal.go
@@ -0,0 +1,157 @@
+// 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 rand
+
+import (
+	"math"
+)
+
+/*
+ * Normal distribution
+ *
+ * See "The Ziggurat Method for Generating Random Variables"
+ * (Marsaglia & Tsang, 2000)
+ * http://www.jstatsoft.org/v05/i08/paper [pdf]
+ */
+
+const (
+	rn = 3.442619855899
+)
+
+func absInt32(i int32) uint32 {
+	if i < 0 {
+		return uint32(-i)
+	}
+	return uint32(i)
+}
+
+// NormFloat64 returns a normally distributed float64 in the range
+// [-math.MaxFloat64, +math.MaxFloat64] with
+// standard normal distribution (mean = 0, stddev = 1).
+// To produce a different normal distribution, callers can
+// adjust the output using:
+//
+//  sample = NormFloat64() * desiredStdDev + desiredMean
+//
+func (r *Rand) NormFloat64() float64 {
+	for {
+		j := int32(r.Uint32()) // Possibly negative
+		i := j & 0x7F
+		x := float64(j) * float64(wn[i])
+		if absInt32(j) < kn[i] {
+			// This case should be hit better than 99% of the time.
+			return x
+		}
+
+		if i == 0 {
+			// This extra work is only required for the base strip.
+			for {
+				x = -math.Log(r.Float64()) * (1.0 / rn)
+				y := -math.Log(r.Float64())
+				if y+y >= x*x {
+					break
+				}
+			}
+			if j > 0 {
+				return rn + x
+			}
+			return -rn - x
+		}
+		if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) {
+			return x
+		}
+	}
+}
+
+var kn = [128]uint32{
+	0x76ad2212, 0x0, 0x600f1b53, 0x6ce447a6, 0x725b46a2,
+	0x7560051d, 0x774921eb, 0x789a25bd, 0x799045c3, 0x7a4bce5d,
+	0x7adf629f, 0x7b5682a6, 0x7bb8a8c6, 0x7c0ae722, 0x7c50cce7,
+	0x7c8cec5b, 0x7cc12cd6, 0x7ceefed2, 0x7d177e0b, 0x7d3b8883,
+	0x7d5bce6c, 0x7d78dd64, 0x7d932886, 0x7dab0e57, 0x7dc0dd30,
+	0x7dd4d688, 0x7de73185, 0x7df81cea, 0x7e07c0a3, 0x7e163efa,
+	0x7e23b587, 0x7e303dfd, 0x7e3beec2, 0x7e46db77, 0x7e51155d,
+	0x7e5aabb3, 0x7e63abf7, 0x7e6c222c, 0x7e741906, 0x7e7b9a18,
+	0x7e82adfa, 0x7e895c63, 0x7e8fac4b, 0x7e95a3fb, 0x7e9b4924,
+	0x7ea0a0ef, 0x7ea5b00d, 0x7eaa7ac3, 0x7eaf04f3, 0x7eb3522a,
+	0x7eb765a5, 0x7ebb4259, 0x7ebeeafd, 0x7ec2620a, 0x7ec5a9c4,
+	0x7ec8c441, 0x7ecbb365, 0x7ece78ed, 0x7ed11671, 0x7ed38d62,
+	0x7ed5df12, 0x7ed80cb4, 0x7eda175c, 0x7edc0005, 0x7eddc78e,
+	0x7edf6ebf, 0x7ee0f647, 0x7ee25ebe, 0x7ee3a8a9, 0x7ee4d473,
+	0x7ee5e276, 0x7ee6d2f5, 0x7ee7a620, 0x7ee85c10, 0x7ee8f4cd,
+	0x7ee97047, 0x7ee9ce59, 0x7eea0eca, 0x7eea3147, 0x7eea3568,
+	0x7eea1aab, 0x7ee9e071, 0x7ee98602, 0x7ee90a88, 0x7ee86d08,
+	0x7ee7ac6a, 0x7ee6c769, 0x7ee5bc9c, 0x7ee48a67, 0x7ee32efc,
+	0x7ee1a857, 0x7edff42f, 0x7ede0ffa, 0x7edbf8d9, 0x7ed9ab94,
+	0x7ed7248d, 0x7ed45fae, 0x7ed1585c, 0x7ece095f, 0x7eca6ccb,
+	0x7ec67be2, 0x7ec22eee, 0x7ebd7d1a, 0x7eb85c35, 0x7eb2c075,
+	0x7eac9c20, 0x7ea5df27, 0x7e9e769f, 0x7e964c16, 0x7e8d44ba,
+	0x7e834033, 0x7e781728, 0x7e6b9933, 0x7e5d8a1a, 0x7e4d9ded,
+	0x7e3b737a, 0x7e268c2f, 0x7e0e3ff5, 0x7df1aa5d, 0x7dcf8c72,
+	0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a,
+	0x7ba90bdc, 0x7a722176, 0x77d664e5,
+}
+var wn = [128]float32{
+	1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10,
+	2.2232431e-10, 2.4244937e-10, 2.601613e-10, 2.7611988e-10,
+	2.9073963e-10, 3.042997e-10, 3.1699796e-10, 3.289802e-10,
+	3.4035738e-10, 3.5121603e-10, 3.616251e-10, 3.7164058e-10,
+	3.8130857e-10, 3.9066758e-10, 3.9975012e-10, 4.08584e-10,
+	4.1719309e-10, 4.2559822e-10, 4.338176e-10, 4.418672e-10,
+	4.497613e-10, 4.5751258e-10, 4.651324e-10, 4.7263105e-10,
+	4.8001775e-10, 4.87301e-10, 4.944885e-10, 5.015873e-10,
+	5.0860405e-10, 5.155446e-10, 5.2241467e-10, 5.2921934e-10,
+	5.359635e-10, 5.426517e-10, 5.4928817e-10, 5.5587696e-10,
+	5.624219e-10, 5.6892646e-10, 5.753941e-10, 5.818282e-10,
+	5.882317e-10, 5.946077e-10, 6.00959e-10, 6.072884e-10,
+	6.135985e-10, 6.19892e-10, 6.2617134e-10, 6.3243905e-10,
+	6.386974e-10, 6.449488e-10, 6.511956e-10, 6.5744005e-10,
+	6.6368433e-10, 6.699307e-10, 6.7618144e-10, 6.824387e-10,
+	6.8870465e-10, 6.949815e-10, 7.012715e-10, 7.075768e-10,
+	7.1389966e-10, 7.202424e-10, 7.266073e-10, 7.329966e-10,
+	7.394128e-10, 7.4585826e-10, 7.5233547e-10, 7.58847e-10,
+	7.653954e-10, 7.719835e-10, 7.7861395e-10, 7.852897e-10,
+	7.920138e-10, 7.987892e-10, 8.0561924e-10, 8.125073e-10,
+	8.194569e-10, 8.2647167e-10, 8.3355556e-10, 8.407127e-10,
+	8.479473e-10, 8.55264e-10, 8.6266755e-10, 8.7016316e-10,
+	8.777562e-10, 8.8545243e-10, 8.932582e-10, 9.0117996e-10,
+	9.09225e-10, 9.174008e-10, 9.2571584e-10, 9.341788e-10,
+	9.427997e-10, 9.515889e-10, 9.605579e-10, 9.697193e-10,
+	9.790869e-10, 9.88676e-10, 9.985036e-10, 1.0085882e-09,
+	1.0189509e-09, 1.0296151e-09, 1.0406069e-09, 1.0519566e-09,
+	1.063698e-09, 1.0758702e-09, 1.0885183e-09, 1.1016947e-09,
+	1.1154611e-09, 1.1298902e-09, 1.1450696e-09, 1.1611052e-09,
+	1.1781276e-09, 1.1962995e-09, 1.2158287e-09, 1.2369856e-09,
+	1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09,
+	1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09,
+}
+var fn = [128]float32{
+	1, 0.9635997, 0.9362827, 0.9130436, 0.89228165, 0.87324303,
+	0.8555006, 0.8387836, 0.8229072, 0.8077383, 0.793177,
+	0.7791461, 0.7655842, 0.7524416, 0.73967725, 0.7272569,
+	0.7151515, 0.7033361, 0.69178915, 0.68049186, 0.6694277,
+	0.658582, 0.6479418, 0.63749546, 0.6272325, 0.6171434,
+	0.6072195, 0.5974532, 0.58783704, 0.5783647, 0.56903,
+	0.5598274, 0.5507518, 0.54179835, 0.5329627, 0.52424055,
+	0.5156282, 0.50712204, 0.49871865, 0.49041483, 0.48220766,
+	0.4740943, 0.46607214, 0.4581387, 0.45029163, 0.44252872,
+	0.43484783, 0.427247, 0.41972435, 0.41227803, 0.40490642,
+	0.39760786, 0.3903808, 0.3832238, 0.37613547, 0.36911446,
+	0.3621595, 0.35526937, 0.34844297, 0.34167916, 0.33497685,
+	0.3283351, 0.3217529, 0.3152294, 0.30876362, 0.30235484,
+	0.29600215, 0.28970486, 0.2834622, 0.2772735, 0.27113807,
+	0.2650553, 0.25902456, 0.2530453, 0.24711695, 0.241239,
+	0.23541094, 0.22963232, 0.2239027, 0.21822165, 0.21258877,
+	0.20700371, 0.20146611, 0.19597565, 0.19053204, 0.18513499,
+	0.17978427, 0.17447963, 0.1692209, 0.16400786, 0.15884037,
+	0.15371831, 0.14864157, 0.14361008, 0.13862377, 0.13368265,
+	0.12878671, 0.12393598, 0.119130544, 0.11437051, 0.10965602,
+	0.104987256, 0.10036444, 0.095787846, 0.0912578, 0.08677467,
+	0.0823389, 0.077950984, 0.073611505, 0.06932112, 0.06508058,
+	0.06089077, 0.056752663, 0.0526674, 0.048636295, 0.044660863,
+	0.040742867, 0.03688439, 0.033087887, 0.029356318,
+	0.025693292, 0.022103304, 0.018592102, 0.015167298,
+	0.011839478, 0.008624485, 0.005548995, 0.0026696292,
+}
diff --git a/third_party/gofrontend/libgo/go/math/rand/rand.go b/third_party/gofrontend/libgo/go/math/rand/rand.go
new file mode 100644
index 0000000..3ffb5c4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/rand/rand.go
@@ -0,0 +1,246 @@
+// 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 rand implements pseudo-random number generators.
+//
+// Random numbers are generated by a Source. Top-level functions, such as
+// Float64 and Int, use a default shared Source that produces a deterministic
+// sequence of values each time a program is run. Use the Seed function to
+// initialize the default Source if different behavior is required for each run.
+// The default Source is safe for concurrent use by multiple goroutines.
+package rand
+
+import "sync"
+
+// A Source represents a source of uniformly-distributed
+// pseudo-random int64 values in the range [0, 1<<63).
+type Source interface {
+	Int63() int64
+	Seed(seed int64)
+}
+
+// NewSource returns a new pseudo-random Source seeded with the given value.
+func NewSource(seed int64) Source {
+	var rng rngSource
+	rng.Seed(seed)
+	return &rng
+}
+
+// A Rand is a source of random numbers.
+type Rand struct {
+	src Source
+}
+
+// New returns a new Rand that uses random values from src
+// to generate other random values.
+func New(src Source) *Rand { return &Rand{src} }
+
+// Seed uses the provided seed value to initialize the generator to a deterministic state.
+func (r *Rand) Seed(seed int64) { r.src.Seed(seed) }
+
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
+func (r *Rand) Int63() int64 { return r.src.Int63() }
+
+// Uint32 returns a pseudo-random 32-bit value as a uint32.
+func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }
+
+// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
+func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
+
+// Int returns a non-negative pseudo-random int.
+func (r *Rand) Int() int {
+	u := uint(r.Int63())
+	return int(u << 1 >> 1) // clear sign bit if int == int32
+}
+
+// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
+// It panics if n <= 0.
+func (r *Rand) Int63n(n int64) int64 {
+	if n <= 0 {
+		panic("invalid argument to Int63n")
+	}
+	if n&(n-1) == 0 { // n is power of two, can mask
+		return r.Int63() & (n - 1)
+	}
+	max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
+	v := r.Int63()
+	for v > max {
+		v = r.Int63()
+	}
+	return v % n
+}
+
+// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
+// It panics if n <= 0.
+func (r *Rand) Int31n(n int32) int32 {
+	if n <= 0 {
+		panic("invalid argument to Int31n")
+	}
+	if n&(n-1) == 0 { // n is power of two, can mask
+		return r.Int31() & (n - 1)
+	}
+	max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
+	v := r.Int31()
+	for v > max {
+		v = r.Int31()
+	}
+	return v % n
+}
+
+// Intn returns, as an int, a non-negative pseudo-random number in [0,n).
+// It panics if n <= 0.
+func (r *Rand) Intn(n int) int {
+	if n <= 0 {
+		panic("invalid argument to Intn")
+	}
+	if n <= 1<<31-1 {
+		return int(r.Int31n(int32(n)))
+	}
+	return int(r.Int63n(int64(n)))
+}
+
+// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
+func (r *Rand) Float64() float64 {
+	// A clearer, simpler implementation would be:
+	//	return float64(r.Int63n(1<<53)) / (1<<53)
+	// However, Go 1 shipped with
+	//	return float64(r.Int63()) / (1 << 63)
+	// and we want to preserve that value stream.
+	//
+	// There is one bug in the value stream: r.Int63() may be so close
+	// to 1<<63 that the division rounds up to 1.0, and we've guaranteed
+	// that the result is always less than 1.0. To fix that, we treat the
+	// range as cyclic and map 1 back to 0. This is justified by observing
+	// that while some of the values rounded down to 0, nothing was
+	// rounding up to 0, so 0 was underrepresented in the results.
+	// Mapping 1 back to zero restores some balance.
+	// (The balance is not perfect because the implementation
+	// returns denormalized numbers for very small r.Int63(),
+	// and those steal from what would normally be 0 results.)
+	// The remapping only happens 1/2⁵³ of the time, so most clients
+	// will not observe it anyway.
+	f := float64(r.Int63()) / (1 << 63)
+	if f == 1 {
+		f = 0
+	}
+	return f
+}
+
+// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
+func (r *Rand) Float32() float32 {
+	// Same rationale as in Float64: we want to preserve the Go 1 value
+	// stream except we want to fix it not to return 1.0
+	// There is a double rounding going on here, but the argument for
+	// mapping 1 to 0 still applies: 0 was underrepresented before,
+	// so mapping 1 to 0 doesn't cause too many 0s.
+	// This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64).
+	f := float32(r.Float64())
+	if f == 1 {
+		f = 0
+	}
+	return f
+}
+
+// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
+func (r *Rand) Perm(n int) []int {
+	m := make([]int, n)
+	for i := 0; i < n; i++ {
+		j := r.Intn(i + 1)
+		m[i] = m[j]
+		m[j] = i
+	}
+	return m
+}
+
+/*
+ * Top-level convenience functions
+ */
+
+var globalRand = New(&lockedSource{src: NewSource(1)})
+
+// Seed uses the provided seed value to initialize the default Source to a
+// deterministic state. If Seed is not called, the generator behaves as
+// if seeded by Seed(1).
+func Seed(seed int64) { globalRand.Seed(seed) }
+
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
+// from the default Source.
+func Int63() int64 { return globalRand.Int63() }
+
+// Uint32 returns a pseudo-random 32-bit value as a uint32
+// from the default Source.
+func Uint32() uint32 { return globalRand.Uint32() }
+
+// Int31 returns a non-negative pseudo-random 31-bit integer as an int32
+// from the default Source.
+func Int31() int32 { return globalRand.Int31() }
+
+// Int returns a non-negative pseudo-random int from the default Source.
+func Int() int { return globalRand.Int() }
+
+// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n)
+// from the default Source.
+// It panics if n <= 0.
+func Int63n(n int64) int64 { return globalRand.Int63n(n) }
+
+// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n)
+// from the default Source.
+// It panics if n <= 0.
+func Int31n(n int32) int32 { return globalRand.Int31n(n) }
+
+// Intn returns, as an int, a non-negative pseudo-random number in [0,n)
+// from the default Source.
+// It panics if n <= 0.
+func Intn(n int) int { return globalRand.Intn(n) }
+
+// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0)
+// from the default Source.
+func Float64() float64 { return globalRand.Float64() }
+
+// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0)
+// from the default Source.
+func Float32() float32 { return globalRand.Float32() }
+
+// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n)
+// from the default Source.
+func Perm(n int) []int { return globalRand.Perm(n) }
+
+// NormFloat64 returns a normally distributed float64 in the range
+// [-math.MaxFloat64, +math.MaxFloat64] with
+// standard normal distribution (mean = 0, stddev = 1)
+// from the default Source.
+// To produce a different normal distribution, callers can
+// adjust the output using:
+//
+//  sample = NormFloat64() * desiredStdDev + desiredMean
+//
+func NormFloat64() float64 { return globalRand.NormFloat64() }
+
+// ExpFloat64 returns an exponentially distributed float64 in the range
+// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
+// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.
+// To produce a distribution with a different rate parameter,
+// callers can adjust the output using:
+//
+//  sample = ExpFloat64() / desiredRateParameter
+//
+func ExpFloat64() float64 { return globalRand.ExpFloat64() }
+
+type lockedSource struct {
+	lk  sync.Mutex
+	src Source
+}
+
+func (r *lockedSource) Int63() (n int64) {
+	r.lk.Lock()
+	n = r.src.Int63()
+	r.lk.Unlock()
+	return
+}
+
+func (r *lockedSource) Seed(seed int64) {
+	r.lk.Lock()
+	r.src.Seed(seed)
+	r.lk.Unlock()
+}
diff --git a/third_party/gofrontend/libgo/go/math/rand/rand_test.go b/third_party/gofrontend/libgo/go/math/rand/rand_test.go
new file mode 100644
index 0000000..ab0dc49
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/rand/rand_test.go
@@ -0,0 +1,398 @@
+// 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 rand
+
+import (
+	"errors"
+	"fmt"
+	"math"
+	"testing"
+)
+
+const (
+	numTestSamples = 10000
+)
+
+type statsResults struct {
+	mean        float64
+	stddev      float64
+	closeEnough float64
+	maxError    float64
+}
+
+func max(a, b float64) float64 {
+	if a > b {
+		return a
+	}
+	return b
+}
+
+func nearEqual(a, b, closeEnough, maxError float64) bool {
+	absDiff := math.Abs(a - b)
+	if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero.
+		return true
+	}
+	return absDiff/max(math.Abs(a), math.Abs(b)) < maxError
+}
+
+var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961}
+
+// checkSimilarDistribution returns success if the mean and stddev of the
+// two statsResults are similar.
+func (this *statsResults) checkSimilarDistribution(expected *statsResults) error {
+	if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) {
+		s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError)
+		fmt.Println(s)
+		return errors.New(s)
+	}
+	if !nearEqual(this.stddev, expected.stddev, 0, expected.maxError) {
+		s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError)
+		fmt.Println(s)
+		return errors.New(s)
+	}
+	return nil
+}
+
+func getStatsResults(samples []float64) *statsResults {
+	res := new(statsResults)
+	var sum, squaresum float64
+	for _, s := range samples {
+		sum += s
+		squaresum += s * s
+	}
+	res.mean = sum / float64(len(samples))
+	res.stddev = math.Sqrt(squaresum/float64(len(samples)) - res.mean*res.mean)
+	return res
+}
+
+func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) {
+	actual := getStatsResults(samples)
+	err := actual.checkSimilarDistribution(expected)
+	if err != nil {
+		t.Errorf(err.Error())
+	}
+}
+
+func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) {
+	chunk := len(samples) / nslices
+	for i := 0; i < nslices; i++ {
+		low := i * chunk
+		var high int
+		if i == nslices-1 {
+			high = len(samples) - 1
+		} else {
+			high = (i + 1) * chunk
+		}
+		checkSampleDistribution(t, samples[low:high], expected)
+	}
+}
+
+//
+// Normal distribution tests
+//
+
+func generateNormalSamples(nsamples int, mean, stddev float64, seed int64) []float64 {
+	r := New(NewSource(seed))
+	samples := make([]float64, nsamples)
+	for i := range samples {
+		samples[i] = r.NormFloat64()*stddev + mean
+	}
+	return samples
+}
+
+func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed int64) {
+	//fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed);
+
+	samples := generateNormalSamples(nsamples, mean, stddev, seed)
+	errorScale := max(1.0, stddev) // Error scales with stddev
+	expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale}
+
+	// Make sure that the entire set matches the expected distribution.
+	checkSampleDistribution(t, samples, expected)
+
+	// Make sure that each half of the set matches the expected distribution.
+	checkSampleSliceDistributions(t, samples, 2, expected)
+
+	// Make sure that each 7th of the set matches the expected distribution.
+	checkSampleSliceDistributions(t, samples, 7, expected)
+}
+
+// Actual tests
+
+func TestStandardNormalValues(t *testing.T) {
+	for _, seed := range testSeeds {
+		testNormalDistribution(t, numTestSamples, 0, 1, seed)
+	}
+}
+
+func TestNonStandardNormalValues(t *testing.T) {
+	sdmax := 1000.0
+	mmax := 1000.0
+	if testing.Short() {
+		sdmax = 5
+		mmax = 5
+	}
+	for sd := 0.5; sd < sdmax; sd *= 2 {
+		for m := 0.5; m < mmax; m *= 2 {
+			for _, seed := range testSeeds {
+				testNormalDistribution(t, numTestSamples, m, sd, seed)
+				if testing.Short() {
+					break
+				}
+			}
+		}
+	}
+}
+
+//
+// Exponential distribution tests
+//
+
+func generateExponentialSamples(nsamples int, rate float64, seed int64) []float64 {
+	r := New(NewSource(seed))
+	samples := make([]float64, nsamples)
+	for i := range samples {
+		samples[i] = r.ExpFloat64() / rate
+	}
+	return samples
+}
+
+func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed int64) {
+	//fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed);
+
+	mean := 1 / rate
+	stddev := mean
+
+	samples := generateExponentialSamples(nsamples, rate, seed)
+	errorScale := max(1.0, 1/rate) // Error scales with the inverse of the rate
+	expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale}
+
+	// Make sure that the entire set matches the expected distribution.
+	checkSampleDistribution(t, samples, expected)
+
+	// Make sure that each half of the set matches the expected distribution.
+	checkSampleSliceDistributions(t, samples, 2, expected)
+
+	// Make sure that each 7th of the set matches the expected distribution.
+	checkSampleSliceDistributions(t, samples, 7, expected)
+}
+
+// Actual tests
+
+func TestStandardExponentialValues(t *testing.T) {
+	for _, seed := range testSeeds {
+		testExponentialDistribution(t, numTestSamples, 1, seed)
+	}
+}
+
+func TestNonStandardExponentialValues(t *testing.T) {
+	for rate := 0.05; rate < 10; rate *= 2 {
+		for _, seed := range testSeeds {
+			testExponentialDistribution(t, numTestSamples, rate, seed)
+			if testing.Short() {
+				break
+			}
+		}
+	}
+}
+
+//
+// Table generation tests
+//
+
+func initNorm() (testKn []uint32, testWn, testFn []float32) {
+	const m1 = 1 << 31
+	var (
+		dn float64 = rn
+		tn         = dn
+		vn float64 = 9.91256303526217e-3
+	)
+
+	testKn = make([]uint32, 128)
+	testWn = make([]float32, 128)
+	testFn = make([]float32, 128)
+
+	q := vn / math.Exp(-0.5*dn*dn)
+	testKn[0] = uint32((dn / q) * m1)
+	testKn[1] = 0
+	testWn[0] = float32(q / m1)
+	testWn[127] = float32(dn / m1)
+	testFn[0] = 1.0
+	testFn[127] = float32(math.Exp(-0.5 * dn * dn))
+	for i := 126; i >= 1; i-- {
+		dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn)))
+		testKn[i+1] = uint32((dn / tn) * m1)
+		tn = dn
+		testFn[i] = float32(math.Exp(-0.5 * dn * dn))
+		testWn[i] = float32(dn / m1)
+	}
+	return
+}
+
+func initExp() (testKe []uint32, testWe, testFe []float32) {
+	const m2 = 1 << 32
+	var (
+		de float64 = re
+		te         = de
+		ve float64 = 3.9496598225815571993e-3
+	)
+
+	testKe = make([]uint32, 256)
+	testWe = make([]float32, 256)
+	testFe = make([]float32, 256)
+
+	q := ve / math.Exp(-de)
+	testKe[0] = uint32((de / q) * m2)
+	testKe[1] = 0
+	testWe[0] = float32(q / m2)
+	testWe[255] = float32(de / m2)
+	testFe[0] = 1.0
+	testFe[255] = float32(math.Exp(-de))
+	for i := 254; i >= 1; i-- {
+		de = -math.Log(ve/de + math.Exp(-de))
+		testKe[i+1] = uint32((de / te) * m2)
+		te = de
+		testFe[i] = float32(math.Exp(-de))
+		testWe[i] = float32(de / m2)
+	}
+	return
+}
+
+// compareUint32Slices returns the first index where the two slices
+// disagree, or <0 if the lengths are the same and all elements
+// are identical.
+func compareUint32Slices(s1, s2 []uint32) int {
+	if len(s1) != len(s2) {
+		if len(s1) > len(s2) {
+			return len(s2) + 1
+		}
+		return len(s1) + 1
+	}
+	for i := range s1 {
+		if s1[i] != s2[i] {
+			return i
+		}
+	}
+	return -1
+}
+
+// compareFloat32Slices returns the first index where the two slices
+// disagree, or <0 if the lengths are the same and all elements
+// are identical.
+func compareFloat32Slices(s1, s2 []float32) int {
+	if len(s1) != len(s2) {
+		if len(s1) > len(s2) {
+			return len(s2) + 1
+		}
+		return len(s1) + 1
+	}
+	for i := range s1 {
+		if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) {
+			return i
+		}
+	}
+	return -1
+}
+
+func TestNormTables(t *testing.T) {
+	testKn, testWn, testFn := initNorm()
+	if i := compareUint32Slices(kn[0:], testKn); i >= 0 {
+		t.Errorf("kn disagrees at index %v; %v != %v", i, kn[i], testKn[i])
+	}
+	if i := compareFloat32Slices(wn[0:], testWn); i >= 0 {
+		t.Errorf("wn disagrees at index %v; %v != %v", i, wn[i], testWn[i])
+	}
+	if i := compareFloat32Slices(fn[0:], testFn); i >= 0 {
+		t.Errorf("fn disagrees at index %v; %v != %v", i, fn[i], testFn[i])
+	}
+}
+
+func TestExpTables(t *testing.T) {
+	testKe, testWe, testFe := initExp()
+	if i := compareUint32Slices(ke[0:], testKe); i >= 0 {
+		t.Errorf("ke disagrees at index %v; %v != %v", i, ke[i], testKe[i])
+	}
+	if i := compareFloat32Slices(we[0:], testWe); i >= 0 {
+		t.Errorf("we disagrees at index %v; %v != %v", i, we[i], testWe[i])
+	}
+	if i := compareFloat32Slices(fe[0:], testFe); i >= 0 {
+		t.Errorf("fe disagrees at index %v; %v != %v", i, fe[i], testFe[i])
+	}
+}
+
+// For issue 6721, the problem came after 7533753 calls, so check 10e6.
+func TestFloat32(t *testing.T) {
+	r := New(NewSource(1))
+	for ct := 0; ct < 10e6; ct++ {
+		f := r.Float32()
+		if f >= 1 {
+			t.Fatal("Float32() should be in range [0,1). ct:", ct, "f:", f)
+		}
+	}
+}
+
+// Benchmarks
+
+func BenchmarkInt63Threadsafe(b *testing.B) {
+	for n := b.N; n > 0; n-- {
+		Int63()
+	}
+}
+
+func BenchmarkInt63Unthreadsafe(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Int63()
+	}
+}
+
+func BenchmarkIntn1000(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Intn(1000)
+	}
+}
+
+func BenchmarkInt63n1000(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Int63n(1000)
+	}
+}
+
+func BenchmarkInt31n1000(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Int31n(1000)
+	}
+}
+
+func BenchmarkFloat32(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Float32()
+	}
+}
+
+func BenchmarkFloat64(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Float64()
+	}
+}
+
+func BenchmarkPerm3(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Perm(3)
+	}
+}
+
+func BenchmarkPerm30(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Perm(30)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/math/rand/regress_test.go b/third_party/gofrontend/libgo/go/math/rand/regress_test.go
new file mode 100644
index 0000000..2b012af
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/rand/regress_test.go
@@ -0,0 +1,355 @@
+// Copyright 2014 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.
+
+// Test that random number sequences generated by a specific seed
+// do not change from version to version.
+//
+// Do NOT make changes to the golden outputs. If bugs need to be fixed
+// in the underlying code, find ways to fix them that do not affect the
+// outputs.
+
+package rand_test
+
+import (
+	"flag"
+	"fmt"
+	. "math/rand"
+	"reflect"
+	"testing"
+)
+
+var printgolden = flag.Bool("printgolden", false, "print golden results for regression test")
+
+func TestRegress(t *testing.T) {
+	var int32s = []int32{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1}
+	var int64s = []int64{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1, 1000000000000000000, 1 << 60, 1<<63 - 2, 1<<63 - 1}
+	var permSizes = []int{0, 1, 5, 8, 9, 10, 16}
+	r := New(NewSource(0))
+
+	rv := reflect.ValueOf(r)
+	n := rv.NumMethod()
+	p := 0
+	if *printgolden {
+		fmt.Printf("var regressGolden = []interface{}{\n")
+	}
+	for i := 0; i < n; i++ {
+		m := rv.Type().Method(i)
+		mv := rv.Method(i)
+		mt := mv.Type()
+		if mt.NumOut() == 0 {
+			continue
+		}
+		if mt.NumOut() != 1 {
+			t.Fatalf("unexpected result count for r.%s", m.Name)
+		}
+		r.Seed(0)
+		for repeat := 0; repeat < 20; repeat++ {
+			var args []reflect.Value
+			var argstr string
+			if mt.NumIn() == 1 {
+				var x interface{}
+				switch mt.In(0).Kind() {
+				default:
+					t.Fatalf("unexpected argument type for r.%s", m.Name)
+
+				case reflect.Int:
+					if m.Name == "Perm" {
+						x = permSizes[repeat%len(permSizes)]
+						break
+					}
+					big := int64s[repeat%len(int64s)]
+					if int64(int(big)) != big {
+						r.Int63n(big) // what would happen on 64-bit machine, to keep stream in sync
+						if *printgolden {
+							fmt.Printf("\tskipped, // must run printgolden on 64-bit machine\n")
+						}
+						p++
+						continue
+					}
+					x = int(big)
+
+				case reflect.Int32:
+					x = int32s[repeat%len(int32s)]
+
+				case reflect.Int64:
+					x = int64s[repeat%len(int64s)]
+				}
+				argstr = fmt.Sprint(x)
+				args = append(args, reflect.ValueOf(x))
+			}
+			out := mv.Call(args)[0].Interface()
+			if m.Name == "Int" || m.Name == "Intn" {
+				out = int64(out.(int))
+			}
+			if *printgolden {
+				var val string
+				big := int64(1 << 60)
+				if int64(int(big)) != big && (m.Name == "Int" || m.Name == "Intn") {
+					// 32-bit machine cannot print 64-bit results
+					val = "truncated"
+				} else if reflect.TypeOf(out).Kind() == reflect.Slice {
+					val = fmt.Sprintf("%#v", out)
+				} else {
+					val = fmt.Sprintf("%T(%v)", out, out)
+				}
+				fmt.Printf("\t%s, // %s(%s)\n", val, m.Name, argstr)
+			} else {
+				want := regressGolden[p]
+				if m.Name == "Int" {
+					want = int64(int(uint(want.(int64)) << 1 >> 1))
+				}
+				if !reflect.DeepEqual(out, want) {
+					t.Errorf("r.%s(%s) = %v, want %v", m.Name, argstr, out, want)
+				}
+			}
+			p++
+		}
+	}
+	if *printgolden {
+		fmt.Printf("}\n")
+	}
+}
+
+var regressGolden = []interface{}{
+	float64(4.668112973579268),    // ExpFloat64()
+	float64(0.1601593871172866),   // ExpFloat64()
+	float64(3.0465834105636),      // ExpFloat64()
+	float64(0.06385839451671879),  // ExpFloat64()
+	float64(1.8578917487258961),   // ExpFloat64()
+	float64(0.784676123472182),    // ExpFloat64()
+	float64(0.11225477361256932),  // ExpFloat64()
+	float64(0.20173283329802255),  // ExpFloat64()
+	float64(0.3468619496201105),   // ExpFloat64()
+	float64(0.35601103454384536),  // ExpFloat64()
+	float64(0.888376329507869),    // ExpFloat64()
+	float64(1.4081362450365698),   // ExpFloat64()
+	float64(1.0077753823151994),   // ExpFloat64()
+	float64(0.23594100766227588),  // ExpFloat64()
+	float64(2.777245612300007),    // ExpFloat64()
+	float64(0.5202997830662377),   // ExpFloat64()
+	float64(1.2842705247770294),   // ExpFloat64()
+	float64(0.030307408362776206), // ExpFloat64()
+	float64(2.204156824853721),    // ExpFloat64()
+	float64(2.09891923895058),     // ExpFloat64()
+	float32(0.94519615),           // Float32()
+	float32(0.24496509),           // Float32()
+	float32(0.65595627),           // Float32()
+	float32(0.05434384),           // Float32()
+	float32(0.3675872),            // Float32()
+	float32(0.28948045),           // Float32()
+	float32(0.1924386),            // Float32()
+	float32(0.65533215),           // Float32()
+	float32(0.8971697),            // Float32()
+	float32(0.16735445),           // Float32()
+	float32(0.28858566),           // Float32()
+	float32(0.9026048),            // Float32()
+	float32(0.84978026),           // Float32()
+	float32(0.2730468),            // Float32()
+	float32(0.6090802),            // Float32()
+	float32(0.253656),             // Float32()
+	float32(0.7746542),            // Float32()
+	float32(0.017480763),          // Float32()
+	float32(0.78707397),           // Float32()
+	float32(0.7993937),            // Float32()
+	float64(0.9451961492941164),   // Float64()
+	float64(0.24496508529377975),  // Float64()
+	float64(0.6559562651954052),   // Float64()
+	float64(0.05434383959970039),  // Float64()
+	float64(0.36758720663245853),  // Float64()
+	float64(0.2894804331565928),   // Float64()
+	float64(0.19243860967493215),  // Float64()
+	float64(0.6553321508148324),   // Float64()
+	float64(0.897169713149801),    // Float64()
+	float64(0.16735444255905835),  // Float64()
+	float64(0.2885856518054551),   // Float64()
+	float64(0.9026048462705047),   // Float64()
+	float64(0.8497802817628735),   // Float64()
+	float64(0.2730468047134829),   // Float64()
+	float64(0.6090801919903561),   // Float64()
+	float64(0.25365600644283687),  // Float64()
+	float64(0.7746542391859803),   // Float64()
+	float64(0.017480762156647272), // Float64()
+	float64(0.7870739563039942),   // Float64()
+	float64(0.7993936979594545),   // Float64()
+	int64(8717895732742165505),    // Int()
+	int64(2259404117704393152),    // Int()
+	int64(6050128673802995827),    // Int()
+	int64(501233450539197794),     // Int()
+	int64(3390393562759376202),    // Int()
+	int64(2669985732393126063),    // Int()
+	int64(1774932891286980153),    // Int()
+	int64(6044372234677422456),    // Int()
+	int64(8274930044578894929),    // Int()
+	int64(1543572285742637646),    // Int()
+	int64(2661732831099943416),    // Int()
+	int64(8325060299420976708),    // Int()
+	int64(7837839688282259259),    // Int()
+	int64(2518412263346885298),    // Int()
+	int64(5617773211005988520),    // Int()
+	int64(2339563716805116249),    // Int()
+	int64(7144924247938981575),    // Int()
+	int64(161231572858529631),     // Int()
+	int64(7259475919510918339),    // Int()
+	int64(7373105480197164748),    // Int()
+	int32(2029793274),             // Int31()
+	int32(526058514),              // Int31()
+	int32(1408655353),             // Int31()
+	int32(116702506),              // Int31()
+	int32(789387515),              // Int31()
+	int32(621654496),              // Int31()
+	int32(413258767),              // Int31()
+	int32(1407315077),             // Int31()
+	int32(1926657288),             // Int31()
+	int32(359390928),              // Int31()
+	int32(619732968),              // Int31()
+	int32(1938329147),             // Int31()
+	int32(1824889259),             // Int31()
+	int32(586363548),              // Int31()
+	int32(1307989752),             // Int31()
+	int32(544722126),              // Int31()
+	int32(1663557311),             // Int31()
+	int32(37539650),               // Int31()
+	int32(1690228450),             // Int31()
+	int32(1716684894),             // Int31()
+	int32(0),                      // Int31n(1)
+	int32(4),                      // Int31n(10)
+	int32(25),                     // Int31n(32)
+	int32(310570),                 // Int31n(1048576)
+	int32(857611),                 // Int31n(1048577)
+	int32(621654496),              // Int31n(1000000000)
+	int32(413258767),              // Int31n(1073741824)
+	int32(1407315077),             // Int31n(2147483646)
+	int32(1926657288),             // Int31n(2147483647)
+	int32(0),                      // Int31n(1)
+	int32(8),                      // Int31n(10)
+	int32(27),                     // Int31n(32)
+	int32(367019),                 // Int31n(1048576)
+	int32(209005),                 // Int31n(1048577)
+	int32(307989752),              // Int31n(1000000000)
+	int32(544722126),              // Int31n(1073741824)
+	int32(1663557311),             // Int31n(2147483646)
+	int32(37539650),               // Int31n(2147483647)
+	int32(0),                      // Int31n(1)
+	int32(4),                      // Int31n(10)
+	int64(8717895732742165505),    // Int63()
+	int64(2259404117704393152),    // Int63()
+	int64(6050128673802995827),    // Int63()
+	int64(501233450539197794),     // Int63()
+	int64(3390393562759376202),    // Int63()
+	int64(2669985732393126063),    // Int63()
+	int64(1774932891286980153),    // Int63()
+	int64(6044372234677422456),    // Int63()
+	int64(8274930044578894929),    // Int63()
+	int64(1543572285742637646),    // Int63()
+	int64(2661732831099943416),    // Int63()
+	int64(8325060299420976708),    // Int63()
+	int64(7837839688282259259),    // Int63()
+	int64(2518412263346885298),    // Int63()
+	int64(5617773211005988520),    // Int63()
+	int64(2339563716805116249),    // Int63()
+	int64(7144924247938981575),    // Int63()
+	int64(161231572858529631),     // Int63()
+	int64(7259475919510918339),    // Int63()
+	int64(7373105480197164748),    // Int63()
+	int64(0),                      // Int63n(1)
+	int64(2),                      // Int63n(10)
+	int64(19),                     // Int63n(32)
+	int64(959842),                 // Int63n(1048576)
+	int64(688912),                 // Int63n(1048577)
+	int64(393126063),              // Int63n(1000000000)
+	int64(89212473),               // Int63n(1073741824)
+	int64(834026388),              // Int63n(2147483646)
+	int64(1577188963),             // Int63n(2147483647)
+	int64(543572285742637646),     // Int63n(1000000000000000000)
+	int64(355889821886249464),     // Int63n(1152921504606846976)
+	int64(8325060299420976708),    // Int63n(9223372036854775806)
+	int64(7837839688282259259),    // Int63n(9223372036854775807)
+	int64(0),                      // Int63n(1)
+	int64(0),                      // Int63n(10)
+	int64(25),                     // Int63n(32)
+	int64(679623),                 // Int63n(1048576)
+	int64(882178),                 // Int63n(1048577)
+	int64(510918339),              // Int63n(1000000000)
+	int64(782454476),              // Int63n(1073741824)
+	int64(0),                      // Intn(1)
+	int64(4),                      // Intn(10)
+	int64(25),                     // Intn(32)
+	int64(310570),                 // Intn(1048576)
+	int64(857611),                 // Intn(1048577)
+	int64(621654496),              // Intn(1000000000)
+	int64(413258767),              // Intn(1073741824)
+	int64(1407315077),             // Intn(2147483646)
+	int64(1926657288),             // Intn(2147483647)
+	int64(543572285742637646),     // Intn(1000000000000000000)
+	int64(355889821886249464),     // Intn(1152921504606846976)
+	int64(8325060299420976708),    // Intn(9223372036854775806)
+	int64(7837839688282259259),    // Intn(9223372036854775807)
+	int64(0),                      // Intn(1)
+	int64(2),                      // Intn(10)
+	int64(14),                     // Intn(32)
+	int64(515775),                 // Intn(1048576)
+	int64(839455),                 // Intn(1048577)
+	int64(690228450),              // Intn(1000000000)
+	int64(642943070),              // Intn(1073741824)
+	float64(-0.28158587086436215), // NormFloat64()
+	float64(0.570933095808067),    // NormFloat64()
+	float64(-1.6920196326157044),  // NormFloat64()
+	float64(0.1996229111693099),   // NormFloat64()
+	float64(1.9195199291234621),   // NormFloat64()
+	float64(0.8954838794918353),   // NormFloat64()
+	float64(0.41457072128813166),  // NormFloat64()
+	float64(-0.48700161491544713), // NormFloat64()
+	float64(-0.1684059662402393),  // NormFloat64()
+	float64(0.37056410998929545),  // NormFloat64()
+	float64(1.0156889027029008),   // NormFloat64()
+	float64(-0.5174422210625114),  // NormFloat64()
+	float64(-0.5565834214413804),  // NormFloat64()
+	float64(0.778320596648391),    // NormFloat64()
+	float64(-1.8970718197702225),  // NormFloat64()
+	float64(0.5229525761688676),   // NormFloat64()
+	float64(-1.5515595563231523),  // NormFloat64()
+	float64(0.0182029289376123),   // NormFloat64()
+	float64(-0.6820951356608795),  // NormFloat64()
+	float64(-0.5987943422687668),  // NormFloat64()
+	[]int{},                                                     // Perm(0)
+	[]int{0},                                                    // Perm(1)
+	[]int{0, 4, 1, 3, 2},                                        // Perm(5)
+	[]int{3, 1, 0, 4, 7, 5, 2, 6},                               // Perm(8)
+	[]int{5, 0, 3, 6, 7, 4, 2, 1, 8},                            // Perm(9)
+	[]int{4, 5, 0, 2, 6, 9, 3, 1, 8, 7},                         // Perm(10)
+	[]int{14, 2, 0, 8, 3, 5, 13, 12, 1, 4, 6, 7, 11, 9, 15, 10}, // Perm(16)
+	[]int{},                                                     // Perm(0)
+	[]int{0},                                                    // Perm(1)
+	[]int{3, 0, 1, 2, 4},                                        // Perm(5)
+	[]int{5, 1, 2, 0, 4, 7, 3, 6},                               // Perm(8)
+	[]int{4, 0, 6, 8, 1, 5, 2, 7, 3},                            // Perm(9)
+	[]int{8, 6, 1, 7, 5, 4, 3, 2, 9, 0},                         // Perm(10)
+	[]int{0, 3, 13, 2, 15, 4, 10, 1, 8, 14, 7, 6, 12, 9, 5, 11}, // Perm(16)
+	[]int{},                             // Perm(0)
+	[]int{0},                            // Perm(1)
+	[]int{0, 4, 2, 1, 3},                // Perm(5)
+	[]int{2, 1, 7, 0, 6, 3, 4, 5},       // Perm(8)
+	[]int{8, 7, 5, 3, 4, 6, 0, 1, 2},    // Perm(9)
+	[]int{1, 0, 2, 5, 7, 6, 9, 8, 3, 4}, // Perm(10)
+	uint32(4059586549),                  // Uint32()
+	uint32(1052117029),                  // Uint32()
+	uint32(2817310706),                  // Uint32()
+	uint32(233405013),                   // Uint32()
+	uint32(1578775030),                  // Uint32()
+	uint32(1243308993),                  // Uint32()
+	uint32(826517535),                   // Uint32()
+	uint32(2814630155),                  // Uint32()
+	uint32(3853314576),                  // Uint32()
+	uint32(718781857),                   // Uint32()
+	uint32(1239465936),                  // Uint32()
+	uint32(3876658295),                  // Uint32()
+	uint32(3649778518),                  // Uint32()
+	uint32(1172727096),                  // Uint32()
+	uint32(2615979505),                  // Uint32()
+	uint32(1089444252),                  // Uint32()
+	uint32(3327114623),                  // Uint32()
+	uint32(75079301),                    // Uint32()
+	uint32(3380456901),                  // Uint32()
+	uint32(3433369789),                  // Uint32()
+}
diff --git a/third_party/gofrontend/libgo/go/math/rand/rng.go b/third_party/gofrontend/libgo/go/math/rand/rng.go
new file mode 100644
index 0000000..947c49f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/rand/rng.go
@@ -0,0 +1,246 @@
+// 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 rand
+
+/*
+ * Uniform distribution
+ *
+ * algorithm by
+ * DP Mitchell and JA Reeds
+ */
+
+const (
+	_LEN  = 607
+	_TAP  = 273
+	_MAX  = 1 << 63
+	_MASK = _MAX - 1
+	_A    = 48271
+	_M    = (1 << 31) - 1
+	_Q    = 44488
+	_R    = 3399
+)
+
+var (
+	// cooked random numbers
+	// the state of the rng
+	// after 780e10 iterations
+	rng_cooked [_LEN]int64 = [...]int64{
+		5041579894721019882, 4646389086726545243, 1395769623340756751, 5333664234075297259,
+		2875692520355975054, 9033628115061424579, 7143218595135194537, 4812947590706362721,
+		7937252194349799378, 5307299880338848416, 8209348851763925077, 2115741599318814044,
+		4593015457530856296, 8140875735541888011, 3319429241265089026, 8619815648190321034,
+		1727074043483619500, 113108499721038619, 4569519971459345583, 5062833859075314731,
+		2387618771259064424, 2716131344356686112, 6559392774825876886, 7650093201692370310,
+		7684323884043752161, 257867835996031390, 6593456519409015164, 271327514973697897,
+		2789386447340118284, 1065192797246149621, 3344507881999356393, 4459797941780066633,
+		7465081662728599889, 1014950805555097187, 4449440729345990775, 3481109366438502643,
+		2418672789110888383, 5796562887576294778, 4484266064449540171, 3738982361971787048,
+		4523597184512354423, 10530508058128498, 8633833783282346118, 2625309929628791628,
+		8660405965245884302, 10162832508971942, 6540714680961817391, 7031802312784620857,
+		6240911277345944669, 831864355460801054, 8004434137542152891, 2116287251661052151,
+		2202309800992166967, 9161020366945053561, 4069299552407763864, 4936383537992622449,
+		457351505131524928, 342195045928179354, 2847771682816600509, 2068020115986376518,
+		4368649989588021065, 887231587095185257, 5563591506886576496, 6816225200251950296,
+		5616972787034086048, 8471809303394836566, 1686575021641186857, 4045484338074262002,
+		4244156215201778923, 7848217333783577387, 5632136521049761902, 833283142057835272,
+		9029726508369077193, 3243583134664087292, 4316371101804477087, 8937849979965997980,
+		6446940406810434101, 1679342092332374735, 6050638460742422078, 6993520719509581582,
+		7640877852514293609, 5881353426285907985, 812786550756860885, 4541845584483343330,
+		2725470216277009086, 4980675660146853729, 5210769080603236061, 8894283318990530821,
+		6326442804750084282, 1495812843684243920, 7069751578799128019, 7370257291860230865,
+		6756929275356942261, 4706794511633873654, 7824520467827898663, 8549875090542453214,
+		33650829478596156, 1328918435751322643, 7297902601803624459, 1011190183918857495,
+		2238025036817854944, 5147159997473910359, 896512091560522982, 2659470849286379941,
+		6097729358393448602, 1731725986304753684, 4106255841983812711, 8327155210721535508,
+		8477511620686074402, 5803876044675762232, 8435417780860221662, 5988852856651071244,
+		4715837297103951910, 7566171971264485114, 505808562678895611, 5070098180695063370,
+		842110666775871513, 572156825025677802, 1791881013492340891, 3393267094866038768,
+		3778721850472236509, 2352769483186201278, 1292459583847367458, 8897907043675088419,
+		5781809037144163536, 2733958794029492513, 5092019688680754699, 8996124554772526841,
+		4234737173186232084, 5027558287275472836, 4635198586344772304, 8687338893267139351,
+		5907508150730407386, 784756255473944452, 972392927514829904, 5422057694808175112,
+		5158420642969283891, 9048531678558643225, 2407211146698877100, 7583282216521099569,
+		3940796514530962282, 3341174631045206375, 3095313889586102949, 7405321895688238710,
+		5832080132947175283, 7890064875145919662, 8184139210799583195, 1149859861409226130,
+		1464597243840211302, 4641648007187991873, 3516491885471466898, 956288521791657692,
+		6657089965014657519, 5220884358887979358, 1796677326474620641, 5340761970648932916,
+		1147977171614181568, 5066037465548252321, 2574765911837859848, 1085848279845204775,
+		3350107529868390359, 6116438694366558490, 2107701075971293812, 1803294065921269267,
+		2469478054175558874, 7368243281019965984, 3791908367843677526, 185046971116456637,
+		2257095756513439648, 7217693971077460129, 909049953079504259, 7196649268545224266,
+		5637660345400869599, 3955544945427965183, 8057528650917418961, 4139268440301127643,
+		6621926588513568059, 1373361136802681441, 6527366231383600011, 3507654575162700890,
+		9202058512774729859, 1954818376891585542, 6640380907130175705, 8299563319178235687,
+		3901867355218954373, 7046310742295574065, 6847195391333990232, 1572638100518868053,
+		8850422670118399721, 3631909142291992901, 5158881091950831288, 2882958317343121593,
+		4763258931815816403, 6280052734341785344, 4243789408204964850, 2043464728020827976,
+		6545300466022085465, 4562580375758598164, 5495451168795427352, 1738312861590151095,
+		553004618757816492, 6895160632757959823, 8233623922264685171, 7139506338801360852,
+		8550891222387991669, 5535668688139305547, 2430933853350256242, 5401941257863201076,
+		8159640039107728799, 6157493831600770366, 7632066283658143750, 6308328381617103346,
+		3681878764086140361, 3289686137190109749, 6587997200611086848, 244714774258135476,
+		4079788377417136100, 8090302575944624335, 2945117363431356361, 864324395848741045,
+		3009039260312620700, 8430027460082534031, 401084700045993341, 7254622446438694921,
+		4707864159563588614, 5640248530963493951, 5982507712689997893, 3315098242282210105,
+		5503847578771918426, 3941971367175193882, 8118566580304798074, 3839261274019871296,
+		7062410411742090847, 741381002980207668, 6027994129690250817, 2497829994150063930,
+		6251390334426228834, 1368930247903518833, 8809096399316380241, 6492004350391900708,
+		2462145737463489636, 404828418920299174, 4153026434231690595, 261785715255475940,
+		5464715384600071357, 592710404378763017, 6764129236657751224, 8513655718539357449,
+		5820343663801914208, 385298524683789911, 5224135003438199467, 6303131641338802145,
+		7150122561309371392, 368107899140673753, 3115186834558311558, 2915636353584281051,
+		4782583894627718279, 6718292300699989587, 8387085186914375220, 3387513132024756289,
+		4654329375432538231, 8930667561363381602, 5374373436876319273, 7623042350483453954,
+		7725442901813263321, 9186225467561587250, 4091027289597503355, 2357631606492579800,
+		2530936820058611833, 1636551876240043639, 5564664674334965799, 1452244145334316253,
+		2061642381019690829, 1279580266495294036, 9108481583171221009, 6023278686734049809,
+		5007630032676973346, 2153168792952589781, 6720334534964750538, 6041546491134794105,
+		3433922409283786309, 2285479922797300912, 3110614940896576130, 6366559590722842893,
+		5418791419666136509, 7163298419643543757, 4891138053923696990, 580618510277907015,
+		1684034065251686769, 4429514767357295841, 330346578555450005, 1119637995812174675,
+		7177515271653460134, 4589042248470800257, 7693288629059004563, 143607045258444228,
+		246994305896273627, 866417324803099287, 6473547110565816071, 3092379936208876896,
+		2058427839513754051, 5133784708526867938, 8785882556301281247, 6149332666841167611,
+		8585842181454472135, 6137678347805511274, 2070447184436970006, 5708223427705576541,
+		5999657892458244504, 4358391411789012426, 325123008708389849, 6837621693887290924,
+		4843721905315627004, 6010651222149276415, 5398352198963874652, 4602025990114250980,
+		1044646352569048800, 9106614159853161675, 829256115228593269, 4919284369102997000,
+		2681532557646850893, 3681559472488511871, 5307999518958214035, 6334130388442829274,
+		2658708232916537604, 1163313865052186287, 581945337509520675, 3648778920718647903,
+		4423673246306544414, 1620799783996955743, 220828013409515943, 8150384699999389761,
+		4287360518296753003, 4590000184845883843, 5513660857261085186, 6964829100392774275,
+		478991688350776035, 8746140185685648781, 228500091334420247, 1356187007457302238,
+		3019253992034194581, 3152601605678500003, 430152752706002213, 5559581553696971176,
+		4916432985369275664, 663574931734554391, 3420773838927732076, 2868348622579915573,
+		1999319134044418520, 3328689518636282723, 2587672709781371173, 1517255313529399333,
+		3092343956317362483, 3662252519007064108, 972445599196498113, 7664865435875959367,
+		1708913533482282562, 6917817162668868494, 3217629022545312900, 2570043027221707107,
+		8739788839543624613, 2488075924621352812, 4694002395387436668, 4559628481798514356,
+		2997203966153298104, 1282559373026354493, 240113143146674385, 8665713329246516443,
+		628141331766346752, 4571950817186770476, 1472811188152235408, 7596648026010355826,
+		6091219417754424743, 7834161864828164065, 7103445518877254909, 4390861237357459201,
+		4442653864240571734, 8903482404847331368, 622261699494173647, 6037261250297213248,
+		504404948065709118, 7275215526217113061, 1011176780856001400, 2194750105623461063,
+		2623071828615234808, 5157313728073836108, 3738405111966602044, 2539767524076729570,
+		2467284396349269342, 5256026990536851868, 7841086888628396109, 6640857538655893162,
+		1202087339038317498, 2113514992440715978, 7534350895342931403, 4925284734898484745,
+		5145623771477493805, 8225140880134972332, 2719520354384050532, 9132346697815513771,
+		4332154495710163773, 7137789594094346916, 6994721091344268833, 6667228574869048934,
+		655440045726677499, 59934747298466858, 6124974028078036405, 8957774780655365418,
+		2332206071942466437, 1701056712286369627, 3154897383618636503, 1637766181387607527,
+		2460521277767576533, 197309393502684135, 643677854385267315, 2543179307861934850,
+		4350769010207485119, 4754652089410667672, 2015595502641514512, 7999059458976458608,
+		4287946071480840813, 8362686366770308971, 6486469209321732151, 3617727845841796026,
+		7554353525834302244, 4450022655153542367, 1605195740213535749, 5327014565305508387,
+		4626575813550328320, 2692222020597705149, 241045573717249868, 5098046974627094010,
+		7916882295460730264, 884817090297530579, 5329160409530630596, 7790979528857726136,
+		4955070238059373407, 4918537275422674302, 3008076183950404629, 3007769226071157901,
+		2470346235617803020, 8928702772696731736, 7856187920214445904, 4474874585391974885,
+		7900176660600710914, 2140571127916226672, 2425445057265199971, 2486055153341847830,
+		4186670094382025798, 1883939007446035042, 8808666044074867985, 3734134241178479257,
+		4065968871360089196, 6953124200385847784, 1305686814738899057, 1637739099014457647,
+		3656125660947993209, 3966759634633167020, 3106378204088556331, 6328899822778449810,
+		4565385105440252958, 1979884289539493806, 2331793186920865425, 3783206694208922581,
+		8464961209802336085, 2843963751609577687, 3030678195484896323, 4793717574095772604,
+		4459239494808162889, 402587895800087237, 8057891408711167515, 4541888170938985079,
+		1042662272908816815, 5557303057122568958, 2647678726283249984, 2144477441549833761,
+		5806352215355387087, 7117771003473903623, 5916597177708541638, 462597715452321361,
+		8833658097025758785, 5970273481425315300, 563813119381731307, 2768349550652697015,
+		1598828206250873866, 5206393647403558110, 6235043485709261823, 3152217402014639496,
+		8469693267274066490, 125672920241807416, 5311079624024060938, 6663754932310491587,
+		8736848295048751716, 4488039774992061878, 5923302823487327109, 140891791083103236,
+		7414942793393574290, 7990420780896957397, 4317817392807076702, 3625184369705367340,
+		2740722765288122703, 5743100009702758344, 5997898640509039159, 8854493341352484163,
+		5242208035432907801, 701338899890987198, 7609280429197514109, 3020985755112334161,
+		6651322707055512866, 2635195723621160615, 5144520864246028816, 1035086515727829828,
+		1567242097116389047, 8172389260191636581, 6337820351429292273, 2163012566996458925,
+		2743190902890262681, 1906367633221323427, 6011544915663598137, 5932255307352610768,
+		2241128460406315459, 895504896216695588, 3094483003111372717, 4583857460292963101,
+		9079887171656594975, 8839289181930711403, 5762740387243057873, 4225072055348026230,
+		1838220598389033063, 3801620336801580414, 8823526620080073856, 1776617605585100335,
+		7899055018877642622, 5421679761463003041, 5521102963086275121, 4248279443559365898,
+		8735487530905098534, 1760527091573692978, 7142485049657745894, 8222656872927218123,
+		4969531564923704323, 3394475942196872480, 6424174453260338141, 359248545074932887,
+		3273651282831730598, 6797106199797138596, 3030918217665093212, 145600834617314036,
+		6036575856065626233, 740416251634527158, 7080427635449935582, 6951781370868335478,
+		399922722363687927, 294902314447253185, 7844950936339178523, 880320858634709042,
+		6192655680808675579, 411604686384710388, 9026808440365124461, 6440783557497587732,
+		4615674634722404292, 539897290441580544, 2096238225866883852, 8751955639408182687,
+		1907224908052289603, 7381039757301768559, 6157238513393239656, 7749994231914157575,
+		8629571604380892756, 5280433031239081479, 7101611890139813254, 2479018537985767835,
+		7169176924412769570, 7942066497793203302, 1357759729055557688, 2278447439451174845,
+		3625338785743880657, 6477479539006708521, 8976185375579272206, 5511371554711836120,
+		1326024180520890843, 7537449876596048829, 5464680203499696154, 3189671183162196045,
+		6346751753565857109, 241159987320630307, 3095793449658682053, 8978332846736310159,
+		2902794662273147216, 7208698530190629697, 7276901792339343736, 1732385229314443140,
+		4133292154170828382, 2918308698224194548, 1519461397937144458, 5293934712616591764,
+		4922828954023452664, 2879211533496425641, 5896236396443472108, 8465043815351752425,
+		7329020396871624740, 8915471717014488588, 2944902635677463047, 7052079073493465134,
+		8382142935188824023, 9103922860780351547, 4152330101494654406,
+	}
+)
+
+type rngSource struct {
+	tap  int         // index into vec
+	feed int         // index into vec
+	vec  [_LEN]int64 // current feedback register
+}
+
+// seed rng x[n+1] = 48271 * x[n] mod (2**31 - 1)
+func seedrand(x int32) int32 {
+	hi := x / _Q
+	lo := x % _Q
+	x = _A*lo - _R*hi
+	if x < 0 {
+		x += _M
+	}
+	return x
+}
+
+// Seed uses the provided seed value to initialize the generator to a deterministic state.
+func (rng *rngSource) Seed(seed int64) {
+	rng.tap = 0
+	rng.feed = _LEN - _TAP
+
+	seed = seed % _M
+	if seed < 0 {
+		seed += _M
+	}
+	if seed == 0 {
+		seed = 89482311
+	}
+
+	x := int32(seed)
+	for i := -20; i < _LEN; i++ {
+		x = seedrand(x)
+		if i >= 0 {
+			var u int64
+			u = int64(x) << 40
+			x = seedrand(x)
+			u ^= int64(x) << 20
+			x = seedrand(x)
+			u ^= int64(x)
+			u ^= rng_cooked[i]
+			rng.vec[i] = u & _MASK
+		}
+	}
+}
+
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
+func (rng *rngSource) Int63() int64 {
+	rng.tap--
+	if rng.tap < 0 {
+		rng.tap += _LEN
+	}
+
+	rng.feed--
+	if rng.feed < 0 {
+		rng.feed += _LEN
+	}
+
+	x := (rng.vec[rng.feed] + rng.vec[rng.tap]) & _MASK
+	rng.vec[rng.feed] = x
+	return x
+}
diff --git a/third_party/gofrontend/libgo/go/math/rand/zipf.go b/third_party/gofrontend/libgo/go/math/rand/zipf.go
new file mode 100644
index 0000000..8db2c6f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/rand/zipf.go
@@ -0,0 +1,75 @@
+// 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.
+
+// W.Hormann, G.Derflinger:
+// "Rejection-Inversion to Generate Variates
+// from Monotone Discrete Distributions"
+// http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz
+
+package rand
+
+import "math"
+
+// A Zipf generates Zipf distributed variates.
+type Zipf struct {
+	r            *Rand
+	imax         float64
+	v            float64
+	q            float64
+	s            float64
+	oneminusQ    float64
+	oneminusQinv float64
+	hxm          float64
+	hx0minusHxm  float64
+}
+
+func (z *Zipf) h(x float64) float64 {
+	return math.Exp(z.oneminusQ*math.Log(z.v+x)) * z.oneminusQinv
+}
+
+func (z *Zipf) hinv(x float64) float64 {
+	return math.Exp(z.oneminusQinv*math.Log(z.oneminusQ*x)) - z.v
+}
+
+// NewZipf returns a Zipf generating variates p(k) on [0, imax]
+// proportional to (v+k)**(-s) where s>1 and k>=0, and v>=1.
+func NewZipf(r *Rand, s float64, v float64, imax uint64) *Zipf {
+	z := new(Zipf)
+	if s <= 1.0 || v < 1 {
+		return nil
+	}
+	z.r = r
+	z.imax = float64(imax)
+	z.v = v
+	z.q = s
+	z.oneminusQ = 1.0 - z.q
+	z.oneminusQinv = 1.0 / z.oneminusQ
+	z.hxm = z.h(z.imax + 0.5)
+	z.hx0minusHxm = z.h(0.5) - math.Exp(math.Log(z.v)*(-z.q)) - z.hxm
+	z.s = 1 - z.hinv(z.h(1.5)-math.Exp(-z.q*math.Log(z.v+1.0)))
+	return z
+}
+
+// Uint64 returns a value drawn from the Zipf distribution described
+// by the Zipf object.
+func (z *Zipf) Uint64() uint64 {
+	if z == nil {
+		panic("rand: nil Zipf")
+	}
+	k := 0.0
+
+	for {
+		r := z.r.Float64() // r on [0,1]
+		ur := z.hxm + r*z.hx0minusHxm
+		x := z.hinv(ur)
+		k = math.Floor(x + 0.5)
+		if k-x <= z.s {
+			break
+		}
+		if ur >= z.h(k+0.5)-math.Exp(-math.Log(k+z.v)*z.q) {
+			break
+		}
+	}
+	return uint64(k)
+}
diff --git a/third_party/gofrontend/libgo/go/math/remainder.go b/third_party/gofrontend/libgo/go/math/remainder.go
new file mode 100644
index 0000000..98bb04d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/remainder.go
@@ -0,0 +1,87 @@
+// Copyright 2010 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 math
+
+// The original C code and the comment below are from
+// FreeBSD's /usr/src/lib/msun/src/e_remainder.c and came
+// with this notice.  The go code is a simplified version of
+// the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// __ieee754_remainder(x,y)
+// Return :
+//      returns  x REM y  =  x - [x/y]*y  as if in infinite
+//      precision arithmetic, where [x/y] is the (infinite bit)
+//      integer nearest x/y (in half way cases, choose the even one).
+// Method :
+//      Based on Mod() returning  x - [x/y]chopped * y  exactly.
+
+// Remainder returns the IEEE 754 floating-point remainder of x/y.
+//
+// Special cases are:
+//	Remainder(±Inf, y) = NaN
+//	Remainder(NaN, y) = NaN
+//	Remainder(x, 0) = NaN
+//	Remainder(x, ±Inf) = x
+//	Remainder(x, NaN) = NaN
+func Remainder(x, y float64) float64 {
+	return remainder(x, y)
+}
+
+func remainder(x, y float64) float64 {
+	const (
+		Tiny    = 4.45014771701440276618e-308 // 0x0020000000000000
+		HalfMax = MaxFloat64 / 2
+	)
+	// special cases
+	switch {
+	case IsNaN(x) || IsNaN(y) || IsInf(x, 0) || y == 0:
+		return NaN()
+	case IsInf(y, 0):
+		return x
+	}
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+	if y < 0 {
+		y = -y
+	}
+	if x == y {
+		return 0
+	}
+	if y <= HalfMax {
+		x = Mod(x, y+y) // now x < 2y
+	}
+	if y < Tiny {
+		if x+x > y {
+			x -= y
+			if x+x >= y {
+				x -= y
+			}
+		}
+	} else {
+		yHalf := 0.5 * y
+		if x > yHalf {
+			x -= y
+			if x >= yHalf {
+				x -= y
+			}
+		}
+	}
+	if sign {
+		x = -x
+	}
+	return x
+}
diff --git a/third_party/gofrontend/libgo/go/math/signbit.go b/third_party/gofrontend/libgo/go/math/signbit.go
new file mode 100644
index 0000000..670cc1a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/signbit.go
@@ -0,0 +1,10 @@
+// Copyright 2010 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 math
+
+// Signbit returns true if x is negative or negative zero.
+func Signbit(x float64) bool {
+	return Float64bits(x)&(1<<63) != 0
+}
diff --git a/third_party/gofrontend/libgo/go/math/sin.go b/third_party/gofrontend/libgo/go/math/sin.go
new file mode 100644
index 0000000..1c5491f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/sin.go
@@ -0,0 +1,236 @@
+// 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.
+
+package math
+
+/*
+	Floating-point sine and cosine.
+*/
+
+// The original C code, the long comment, and the constants
+// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
+// available from http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a simplified version of the original C.
+//
+//      sin.c
+//
+//      Circular sine
+//
+// SYNOPSIS:
+//
+// double x, y, sin();
+// y = sin( x );
+//
+// DESCRIPTION:
+//
+// Range reduction is into intervals of pi/4.  The reduction error is nearly
+// eliminated by contriving an extended precision modular arithmetic.
+//
+// Two polynomial approximating functions are employed.
+// Between 0 and pi/4 the sine is approximated by
+//      x  +  x**3 P(x**2).
+// Between pi/4 and pi/2 the cosine is represented as
+//      1  -  x**2 Q(x**2).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain      # trials      peak         rms
+//    DEC       0, 10       150000       3.0e-17     7.8e-18
+//    IEEE -1.07e9,+1.07e9  130000       2.1e-16     5.4e-17
+//
+// Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9.  The loss
+// is not gradual, but jumps suddenly to about 1 part in 10e7.  Results may
+// be meaningless for x > 2**49 = 5.6e14.
+//
+//      cos.c
+//
+//      Circular cosine
+//
+// SYNOPSIS:
+//
+// double x, y, cos();
+// y = cos( x );
+//
+// DESCRIPTION:
+//
+// Range reduction is into intervals of pi/4.  The reduction error is nearly
+// eliminated by contriving an extended precision modular arithmetic.
+//
+// Two polynomial approximating functions are employed.
+// Between 0 and pi/4 the cosine is approximated by
+//      1  -  x**2 Q(x**2).
+// Between pi/4 and pi/2 the sine is represented as
+//      x  +  x**3 P(x**2).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain      # trials      peak         rms
+//    IEEE -1.07e9,+1.07e9  130000       2.1e-16     5.4e-17
+//    DEC        0,+1.07e9   17000       3.0e-17     7.2e-18
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+// sin coefficients
+var _sin = [...]float64{
+	1.58962301576546568060E-10, // 0x3de5d8fd1fd19ccd
+	-2.50507477628578072866E-8, // 0xbe5ae5e5a9291f5d
+	2.75573136213857245213E-6,  // 0x3ec71de3567d48a1
+	-1.98412698295895385996E-4, // 0xbf2a01a019bfdf03
+	8.33333333332211858878E-3,  // 0x3f8111111110f7d0
+	-1.66666666666666307295E-1, // 0xbfc5555555555548
+}
+
+// cos coefficients
+var _cos = [...]float64{
+	-1.13585365213876817300E-11, // 0xbda8fa49a0861a9b
+	2.08757008419747316778E-9,   // 0x3e21ee9d7b4e3f05
+	-2.75573141792967388112E-7,  // 0xbe927e4f7eac4bc6
+	2.48015872888517045348E-5,   // 0x3efa01a019c844f5
+	-1.38888888888730564116E-3,  // 0xbf56c16c16c14f91
+	4.16666666666665929218E-2,   // 0x3fa555555555554b
+}
+
+// Cos returns the cosine of the radian argument x.
+//
+// Special cases are:
+//	Cos(±Inf) = NaN
+//	Cos(NaN) = NaN
+
+//extern cos
+func libc_cos(float64) float64
+
+func Cos(x float64) float64 {
+	return libc_cos(x)
+}
+
+func cos(x float64) float64 {
+	const (
+		PI4A = 7.85398125648498535156E-1                             // 0x3fe921fb40000000, Pi/4 split into three parts
+		PI4B = 3.77489470793079817668E-8                             // 0x3e64442d00000000,
+		PI4C = 2.69515142907905952645E-15                            // 0x3ce8469898cc5170,
+		M4PI = 1.273239544735162542821171882678754627704620361328125 // 4/pi
+	)
+	// special cases
+	switch {
+	case IsNaN(x) || IsInf(x, 0):
+		return NaN()
+	}
+
+	// make argument positive
+	sign := false
+	if x < 0 {
+		x = -x
+	}
+
+	j := int64(x * M4PI) // integer part of x/(Pi/4), as integer for tests on the phase angle
+	y := float64(j)      // integer part of x/(Pi/4), as float
+
+	// map zeros to origin
+	if j&1 == 1 {
+		j += 1
+		y += 1
+	}
+	j &= 7 // octant modulo 2Pi radians (360 degrees)
+	if j > 3 {
+		j -= 4
+		sign = !sign
+	}
+	if j > 1 {
+		sign = !sign
+	}
+
+	z := ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
+	zz := z * z
+	if j == 1 || j == 2 {
+		y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
+	} else {
+		y = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
+	}
+	if sign {
+		y = -y
+	}
+	return y
+}
+
+// Sin returns the sine of the radian argument x.
+//
+// Special cases are:
+//	Sin(±0) = ±0
+//	Sin(±Inf) = NaN
+//	Sin(NaN) = NaN
+
+//extern sin
+func libc_sin(float64) float64
+
+func Sin(x float64) float64 {
+	return libc_sin(x)
+}
+
+func sin(x float64) float64 {
+	const (
+		PI4A = 7.85398125648498535156E-1                             // 0x3fe921fb40000000, Pi/4 split into three parts
+		PI4B = 3.77489470793079817668E-8                             // 0x3e64442d00000000,
+		PI4C = 2.69515142907905952645E-15                            // 0x3ce8469898cc5170,
+		M4PI = 1.273239544735162542821171882678754627704620361328125 // 4/pi
+	)
+	// special cases
+	switch {
+	case x == 0 || IsNaN(x):
+		return x // return ±0 || NaN()
+	case IsInf(x, 0):
+		return NaN()
+	}
+
+	// make argument positive but save the sign
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+
+	j := int64(x * M4PI) // integer part of x/(Pi/4), as integer for tests on the phase angle
+	y := float64(j)      // integer part of x/(Pi/4), as float
+
+	// map zeros to origin
+	if j&1 == 1 {
+		j += 1
+		y += 1
+	}
+	j &= 7 // octant modulo 2Pi radians (360 degrees)
+	// reflect in x axis
+	if j > 3 {
+		sign = !sign
+		j -= 4
+	}
+
+	z := ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
+	zz := z * z
+	if j == 1 || j == 2 {
+		y = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
+	} else {
+		y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
+	}
+	if sign {
+		y = -y
+	}
+	return y
+}
diff --git a/third_party/gofrontend/libgo/go/math/sincos.go b/third_party/gofrontend/libgo/go/math/sincos.go
new file mode 100644
index 0000000..b3a2f8a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/sincos.go
@@ -0,0 +1,71 @@
+// Copyright 2010 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 math
+
+// Coefficients _sin[] and _cos[] are found in pkg/math/sin.go.
+
+// Sincos returns Sin(x), Cos(x).
+//
+// Special cases are:
+//	Sincos(±0) = ±0, 1
+//	Sincos(±Inf) = NaN, NaN
+//	Sincos(NaN) = NaN, NaN
+func Sincos(x float64) (sin, cos float64) {
+	return sincos(x)
+}
+
+func sincos(x float64) (sin, cos float64) {
+	const (
+		PI4A = 7.85398125648498535156E-1                             // 0x3fe921fb40000000, Pi/4 split into three parts
+		PI4B = 3.77489470793079817668E-8                             // 0x3e64442d00000000,
+		PI4C = 2.69515142907905952645E-15                            // 0x3ce8469898cc5170,
+		M4PI = 1.273239544735162542821171882678754627704620361328125 // 4/pi
+	)
+	// special cases
+	switch {
+	case x == 0:
+		return x, 1 // return ±0.0, 1.0
+	case IsNaN(x) || IsInf(x, 0):
+		return NaN(), NaN()
+	}
+
+	// make argument positive
+	sinSign, cosSign := false, false
+	if x < 0 {
+		x = -x
+		sinSign = true
+	}
+
+	j := int64(x * M4PI) // integer part of x/(Pi/4), as integer for tests on the phase angle
+	y := float64(j)      // integer part of x/(Pi/4), as float
+
+	if j&1 == 1 { // map zeros to origin
+		j += 1
+		y += 1
+	}
+	j &= 7     // octant modulo 2Pi radians (360 degrees)
+	if j > 3 { // reflect in x axis
+		j -= 4
+		sinSign, cosSign = !sinSign, !cosSign
+	}
+	if j > 1 {
+		cosSign = !cosSign
+	}
+
+	z := ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
+	zz := z * z
+	cos = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
+	sin = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
+	if j == 1 || j == 2 {
+		sin, cos = cos, sin
+	}
+	if cosSign {
+		cos = -cos
+	}
+	if sinSign {
+		sin = -sin
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/math/sinh.go b/third_party/gofrontend/libgo/go/math/sinh.go
new file mode 100644
index 0000000..139b911
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/sinh.go
@@ -0,0 +1,77 @@
+// 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 math
+
+/*
+	Floating-point hyperbolic sine and cosine.
+
+	The exponential func is called for arguments
+	greater in magnitude than 0.5.
+
+	A series is used for arguments smaller in magnitude than 0.5.
+
+	Cosh(x) is computed from the exponential func for
+	all arguments.
+*/
+
+// Sinh returns the hyperbolic sine of x.
+//
+// Special cases are:
+//	Sinh(±0) = ±0
+//	Sinh(±Inf) = ±Inf
+//	Sinh(NaN) = NaN
+func Sinh(x float64) float64 {
+	// The coefficients are #2029 from Hart & Cheney. (20.36D)
+	const (
+		P0 = -0.6307673640497716991184787251e+6
+		P1 = -0.8991272022039509355398013511e+5
+		P2 = -0.2894211355989563807284660366e+4
+		P3 = -0.2630563213397497062819489e+2
+		Q0 = -0.6307673640497716991212077277e+6
+		Q1 = 0.1521517378790019070696485176e+5
+		Q2 = -0.173678953558233699533450911e+3
+	)
+
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+
+	var temp float64
+	switch true {
+	case x > 21:
+		temp = Exp(x) / 2
+
+	case x > 0.5:
+		temp = (Exp(x) - Exp(-x)) / 2
+
+	default:
+		sq := x * x
+		temp = (((P3*sq+P2)*sq+P1)*sq + P0) * x
+		temp = temp / (((sq+Q2)*sq+Q1)*sq + Q0)
+	}
+
+	if sign {
+		temp = -temp
+	}
+	return temp
+}
+
+// Cosh returns the hyperbolic cosine of x.
+//
+// Special cases are:
+//	Cosh(±0) = 1
+//	Cosh(±Inf) = +Inf
+//	Cosh(NaN) = NaN
+func Cosh(x float64) float64 {
+	if x < 0 {
+		x = -x
+	}
+	if x > 21 {
+		return Exp(x) / 2
+	}
+	return (Exp(x) + Exp(-x)) / 2
+}
diff --git a/third_party/gofrontend/libgo/go/math/sqrt.go b/third_party/gofrontend/libgo/go/math/sqrt.go
new file mode 100644
index 0000000..7847597
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/sqrt.go
@@ -0,0 +1,148 @@
+// 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 math
+
+//extern sqrt
+func libc_sqrt(float64) float64
+
+func Sqrt(x float64) float64 {
+	return libc_sqrt(x)
+}
+
+// The original C code and the long comment below are
+// from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and
+// came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// __ieee754_sqrt(x)
+// Return correctly rounded sqrt.
+//           -----------------------------------------
+//           | Use the hardware sqrt if you have one |
+//           -----------------------------------------
+// Method:
+//   Bit by bit method using integer arithmetic. (Slow, but portable)
+//   1. Normalization
+//      Scale x to y in [1,4) with even powers of 2:
+//      find an integer k such that  1 <= (y=x*2**(2k)) < 4, then
+//              sqrt(x) = 2**k * sqrt(y)
+//   2. Bit by bit computation
+//      Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
+//           i                                                   0
+//                                     i+1         2
+//          s  = 2*q , and      y  =  2   * ( y - q  ).          (1)
+//           i      i            i                 i
+//
+//      To compute q    from q , one checks whether
+//                  i+1       i
+//
+//                            -(i+1) 2
+//                      (q + 2      )  <= y.                     (2)
+//                        i
+//                                                            -(i+1)
+//      If (2) is false, then q   = q ; otherwise q   = q  + 2      .
+//                             i+1   i             i+1   i
+//
+//      With some algebraic manipulation, it is not difficult to see
+//      that (2) is equivalent to
+//                             -(i+1)
+//                      s  +  2       <= y                       (3)
+//                       i                i
+//
+//      The advantage of (3) is that s  and y  can be computed by
+//                                    i      i
+//      the following recurrence formula:
+//          if (3) is false
+//
+//          s     =  s  ,       y    = y   ;                     (4)
+//           i+1      i          i+1    i
+//
+//      otherwise,
+//                         -i                      -(i+1)
+//          s     =  s  + 2  ,  y    = y  -  s  - 2              (5)
+//           i+1      i          i+1    i     i
+//
+//      One may easily use induction to prove (4) and (5).
+//      Note. Since the left hand side of (3) contain only i+2 bits,
+//            it does not necessary to do a full (53-bit) comparison
+//            in (3).
+//   3. Final rounding
+//      After generating the 53 bits result, we compute one more bit.
+//      Together with the remainder, we can decide whether the
+//      result is exact, bigger than 1/2ulp, or less than 1/2ulp
+//      (it will never equal to 1/2ulp).
+//      The rounding mode can be detected by checking whether
+//      huge + tiny is equal to huge, and whether huge - tiny is
+//      equal to huge for some floating point number "huge" and "tiny".
+//
+//
+// Notes:  Rounding mode detection omitted.  The constants "mask", "shift",
+// and "bias" are found in src/pkg/math/bits.go
+
+// Sqrt returns the square root of x.
+//
+// Special cases are:
+//	Sqrt(+Inf) = +Inf
+//	Sqrt(±0) = ±0
+//	Sqrt(x < 0) = NaN
+//	Sqrt(NaN) = NaN
+func sqrt(x float64) float64 {
+	// special cases
+	switch {
+	case x == 0 || IsNaN(x) || IsInf(x, 1):
+		return x
+	case x < 0:
+		return NaN()
+	}
+	ix := Float64bits(x)
+	// normalize x
+	exp := int((ix >> shift) & mask)
+	if exp == 0 { // subnormal x
+		for ix&1<<shift == 0 {
+			ix <<= 1
+			exp--
+		}
+		exp++
+	}
+	exp -= bias // unbias exponent
+	ix &^= mask << shift
+	ix |= 1 << shift
+	if exp&1 == 1 { // odd exp, double x to make it even
+		ix <<= 1
+	}
+	exp >>= 1 // exp = exp/2, exponent of square root
+	// generate sqrt(x) bit by bit
+	ix <<= 1
+	var q, s uint64               // q = sqrt(x)
+	r := uint64(1 << (shift + 1)) // r = moving bit from MSB to LSB
+	for r != 0 {
+		t := s + r
+		if t <= ix {
+			s = t + r
+			ix -= t
+			q += r
+		}
+		ix <<= 1
+		r >>= 1
+	}
+	// final rounding
+	if ix != 0 { // remainder, result not exact
+		q += q & 1 // round according to extra bit
+	}
+	ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent
+	return Float64frombits(ix)
+}
+
+func sqrtC(f float64, r *float64) {
+	*r = sqrt(f)
+}
diff --git a/third_party/gofrontend/libgo/go/math/tan.go b/third_party/gofrontend/libgo/go/math/tan.go
new file mode 100644
index 0000000..e544b27
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/tan.go
@@ -0,0 +1,136 @@
+// 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.
+
+package math
+
+/*
+	Floating-point tangent.
+*/
+
+// The original C code, the long comment, and the constants
+// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
+// available from http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a simplified version of the original C.
+//
+//      tan.c
+//
+//      Circular tangent
+//
+// SYNOPSIS:
+//
+// double x, y, tan();
+// y = tan( x );
+//
+// DESCRIPTION:
+//
+// Returns the circular tangent of the radian argument x.
+//
+// Range reduction is modulo pi/4.  A rational function
+//       x + x**3 P(x**2)/Q(x**2)
+// is employed in the basic interval [0, pi/4].
+//
+// ACCURACY:
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC      +-1.07e9      44000      4.1e-17     1.0e-17
+//    IEEE     +-1.07e9      30000      2.9e-16     8.1e-17
+//
+// Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9.  The loss
+// is not gradual, but jumps suddenly to about 1 part in 10e7.  Results may
+// be meaningless for x > 2**49 = 5.6e14.
+// [Accuracy loss statement from sin.go comments.]
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+
+// tan coefficients
+var _tanP = [...]float64{
+	-1.30936939181383777646E4, // 0xc0c992d8d24f3f38
+	1.15351664838587416140E6,  // 0x413199eca5fc9ddd
+	-1.79565251976484877988E7, // 0xc1711fead3299176
+}
+var _tanQ = [...]float64{
+	1.00000000000000000000E0,
+	1.36812963470692954678E4,  //0x40cab8a5eeb36572
+	-1.32089234440210967447E6, //0xc13427bc582abc96
+	2.50083801823357915839E7,  //0x4177d98fc2ead8ef
+	-5.38695755929454629881E7, //0xc189afe03cbe5a31
+}
+
+// Tan returns the tangent of the radian argument x.
+//
+// Special cases are:
+//	Tan(±0) = ±0
+//	Tan(±Inf) = NaN
+//	Tan(NaN) = NaN
+
+//extern tan
+func libc_tan(float64) float64
+
+func Tan(x float64) float64 {
+	return libc_tan(x)
+}
+
+func tan(x float64) float64 {
+	const (
+		PI4A = 7.85398125648498535156E-1                             // 0x3fe921fb40000000, Pi/4 split into three parts
+		PI4B = 3.77489470793079817668E-8                             // 0x3e64442d00000000,
+		PI4C = 2.69515142907905952645E-15                            // 0x3ce8469898cc5170,
+		M4PI = 1.273239544735162542821171882678754627704620361328125 // 4/pi
+	)
+	// special cases
+	switch {
+	case x == 0 || IsNaN(x):
+		return x // return ±0 || NaN()
+	case IsInf(x, 0):
+		return NaN()
+	}
+
+	// make argument positive but save the sign
+	sign := false
+	if x < 0 {
+		x = -x
+		sign = true
+	}
+
+	j := int64(x * M4PI) // integer part of x/(Pi/4), as integer for tests on the phase angle
+	y := float64(j)      // integer part of x/(Pi/4), as float
+
+	/* map zeros and singularities to origin */
+	if j&1 == 1 {
+		j += 1
+		y += 1
+	}
+
+	z := ((x - y*PI4A) - y*PI4B) - y*PI4C
+	zz := z * z
+
+	if zz > 1e-14 {
+		y = z + z*(zz*(((_tanP[0]*zz)+_tanP[1])*zz+_tanP[2])/((((zz+_tanQ[1])*zz+_tanQ[2])*zz+_tanQ[3])*zz+_tanQ[4]))
+	} else {
+		y = z
+	}
+	if j&2 == 2 {
+		y = -1 / y
+	}
+	if sign {
+		y = -y
+	}
+	return y
+}
diff --git a/third_party/gofrontend/libgo/go/math/tanh.go b/third_party/gofrontend/libgo/go/math/tanh.go
new file mode 100644
index 0000000..cf0ffa1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/tanh.go
@@ -0,0 +1,97 @@
+// 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 math
+
+// The original C code, the long comment, and the constants
+// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
+// available from http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a simplified version of the original C.
+//      tanh.c
+//
+//      Hyperbolic tangent
+//
+// SYNOPSIS:
+//
+// double x, y, tanh();
+//
+// y = tanh( x );
+//
+// DESCRIPTION:
+//
+// Returns hyperbolic tangent of argument in the range MINLOG to MAXLOG.
+//      MAXLOG = 8.8029691931113054295988e+01 = log(2**127)
+//      MINLOG = -8.872283911167299960540e+01 = log(2**-128)
+//
+// A rational function is used for |x| < 0.625.  The form
+// x + x**3 P(x)/Q(x) of Cody & Waite is employed.
+// Otherwise,
+//      tanh(x) = sinh(x)/cosh(x) = 1  -  2/(exp(2x) + 1).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    IEEE      -2,2        30000       2.5e-16     5.8e-17
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier@na-net.ornl.gov
+//
+
+var tanhP = [...]float64{
+	-9.64399179425052238628E-1,
+	-9.92877231001918586564E1,
+	-1.61468768441708447952E3,
+}
+var tanhQ = [...]float64{
+	1.12811678491632931402E2,
+	2.23548839060100448583E3,
+	4.84406305325125486048E3,
+}
+
+// Tanh returns the hyperbolic tangent of x.
+//
+// Special cases are:
+//	Tanh(±0) = ±0
+//	Tanh(±Inf) = ±1
+//	Tanh(NaN) = NaN
+func Tanh(x float64) float64 {
+	const MAXLOG = 8.8029691931113054295988e+01 // log(2**127)
+	z := Abs(x)
+	switch {
+	case z > 0.5*MAXLOG:
+		if x < 0 {
+			return -1
+		}
+		return 1
+	case z >= 0.625:
+		s := Exp(2 * z)
+		z = 1 - 2/(s+1)
+		if x < 0 {
+			z = -z
+		}
+	default:
+		if x == 0 {
+			return x
+		}
+		s := x * x
+		z = x + x*s*((tanhP[0]*s+tanhP[1])*s+tanhP[2])/(((s+tanhQ[0])*s+tanhQ[1])*s+tanhQ[2])
+	}
+	return z
+}
diff --git a/third_party/gofrontend/libgo/go/math/unsafe.go b/third_party/gofrontend/libgo/go/math/unsafe.go
new file mode 100644
index 0000000..5ae6742
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/math/unsafe.go
@@ -0,0 +1,21 @@
+// 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 math
+
+import "unsafe"
+
+// Float32bits returns the IEEE 754 binary representation of f.
+func Float32bits(f float32) uint32 { return *(*uint32)(unsafe.Pointer(&f)) }
+
+// Float32frombits returns the floating point number corresponding
+// to the IEEE 754 binary representation b.
+func Float32frombits(b uint32) float32 { return *(*float32)(unsafe.Pointer(&b)) }
+
+// Float64bits returns the IEEE 754 binary representation of f.
+func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) }
+
+// Float64frombits returns the floating point number corresponding
+// the IEEE 754 binary representation b.
+func Float64frombits(b uint64) float64 { return *(*float64)(unsafe.Pointer(&b)) }
diff --git a/third_party/gofrontend/libgo/go/mime/grammar.go b/third_party/gofrontend/libgo/go/mime/grammar.go
new file mode 100644
index 0000000..2347324
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/grammar.go
@@ -0,0 +1,32 @@
+// Copyright 2010 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 mime
+
+import (
+	"strings"
+)
+
+// isTSpecial returns true if rune is in 'tspecials' as defined by RFC
+// 1521 and RFC 2045.
+func isTSpecial(r rune) bool {
+	return strings.IndexRune(`()<>@,;:\"/[]?=`, r) != -1
+}
+
+// isTokenChar returns true if rune is in 'token' as defined by RFC
+// 1521 and RFC 2045.
+func isTokenChar(r rune) bool {
+	// token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
+	//             or tspecials>
+	return r > 0x20 && r < 0x7f && !isTSpecial(r)
+}
+
+// isToken returns true if s is a 'token' as defined by RFC 1521
+// and RFC 2045.
+func isToken(s string) bool {
+	if s == "" {
+		return false
+	}
+	return strings.IndexFunc(s, isNotTokenChar) < 0
+}
diff --git a/third_party/gofrontend/libgo/go/mime/mediatype.go b/third_party/gofrontend/libgo/go/mime/mediatype.go
new file mode 100644
index 0000000..ad63f9b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/mediatype.go
@@ -0,0 +1,358 @@
+// Copyright 2010 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 mime
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"sort"
+	"strings"
+	"unicode"
+)
+
+// FormatMediaType serializes mediatype t and the parameters
+// param as a media type conforming to RFC 2045 and RFC 2616.
+// The type and parameter names are written in lower-case.
+// When any of the arguments result in a standard violation then
+// FormatMediaType returns the empty string.
+func FormatMediaType(t string, param map[string]string) string {
+	slash := strings.Index(t, "/")
+	if slash == -1 {
+		return ""
+	}
+	major, sub := t[:slash], t[slash+1:]
+	if !isToken(major) || !isToken(sub) {
+		return ""
+	}
+	var b bytes.Buffer
+	b.WriteString(strings.ToLower(major))
+	b.WriteByte('/')
+	b.WriteString(strings.ToLower(sub))
+
+	attrs := make([]string, 0, len(param))
+	for a := range param {
+		attrs = append(attrs, a)
+	}
+	sort.Strings(attrs)
+
+	for _, attribute := range attrs {
+		value := param[attribute]
+		b.WriteByte(';')
+		b.WriteByte(' ')
+		if !isToken(attribute) {
+			return ""
+		}
+		b.WriteString(strings.ToLower(attribute))
+		b.WriteByte('=')
+		if isToken(value) {
+			b.WriteString(value)
+			continue
+		}
+
+		b.WriteByte('"')
+		offset := 0
+		for index, character := range value {
+			if character == '"' || character == '\\' {
+				b.WriteString(value[offset:index])
+				offset = index
+				b.WriteByte('\\')
+			}
+			if character&0x80 != 0 {
+				return ""
+			}
+		}
+		b.WriteString(value[offset:])
+		b.WriteByte('"')
+	}
+	return b.String()
+}
+
+func checkMediaTypeDisposition(s string) error {
+	typ, rest := consumeToken(s)
+	if typ == "" {
+		return errors.New("mime: no media type")
+	}
+	if rest == "" {
+		return nil
+	}
+	if !strings.HasPrefix(rest, "/") {
+		return errors.New("mime: expected slash after first token")
+	}
+	subtype, rest := consumeToken(rest[1:])
+	if subtype == "" {
+		return errors.New("mime: expected token after slash")
+	}
+	if rest != "" {
+		return errors.New("mime: unexpected content after media subtype")
+	}
+	return nil
+}
+
+// ParseMediaType parses a media type value and any optional
+// parameters, per RFC 1521.  Media types are the values in
+// Content-Type and Content-Disposition headers (RFC 2183).
+// On success, ParseMediaType returns the media type converted
+// to lowercase and trimmed of white space and a non-nil map.
+// The returned map, params, maps from the lowercase
+// attribute to the attribute value with its case preserved.
+func ParseMediaType(v string) (mediatype string, params map[string]string, err error) {
+	i := strings.Index(v, ";")
+	if i == -1 {
+		i = len(v)
+	}
+	mediatype = strings.TrimSpace(strings.ToLower(v[0:i]))
+
+	err = checkMediaTypeDisposition(mediatype)
+	if err != nil {
+		return "", nil, err
+	}
+
+	params = make(map[string]string)
+
+	// Map of base parameter name -> parameter name -> value
+	// for parameters containing a '*' character.
+	// Lazily initialized.
+	var continuation map[string]map[string]string
+
+	v = v[i:]
+	for len(v) > 0 {
+		v = strings.TrimLeftFunc(v, unicode.IsSpace)
+		if len(v) == 0 {
+			break
+		}
+		key, value, rest := consumeMediaParam(v)
+		if key == "" {
+			if strings.TrimSpace(rest) == ";" {
+				// Ignore trailing semicolons.
+				// Not an error.
+				return
+			}
+			// Parse error.
+			return "", nil, errors.New("mime: invalid media parameter")
+		}
+
+		pmap := params
+		if idx := strings.Index(key, "*"); idx != -1 {
+			baseName := key[:idx]
+			if continuation == nil {
+				continuation = make(map[string]map[string]string)
+			}
+			var ok bool
+			if pmap, ok = continuation[baseName]; !ok {
+				continuation[baseName] = make(map[string]string)
+				pmap = continuation[baseName]
+			}
+		}
+		if _, exists := pmap[key]; exists {
+			// Duplicate parameter name is bogus.
+			return "", nil, errors.New("mime: duplicate parameter name")
+		}
+		pmap[key] = value
+		v = rest
+	}
+
+	// Stitch together any continuations or things with stars
+	// (i.e. RFC 2231 things with stars: "foo*0" or "foo*")
+	var buf bytes.Buffer
+	for key, pieceMap := range continuation {
+		singlePartKey := key + "*"
+		if v, ok := pieceMap[singlePartKey]; ok {
+			decv := decode2231Enc(v)
+			params[key] = decv
+			continue
+		}
+
+		buf.Reset()
+		valid := false
+		for n := 0; ; n++ {
+			simplePart := fmt.Sprintf("%s*%d", key, n)
+			if v, ok := pieceMap[simplePart]; ok {
+				valid = true
+				buf.WriteString(v)
+				continue
+			}
+			encodedPart := simplePart + "*"
+			if v, ok := pieceMap[encodedPart]; ok {
+				valid = true
+				if n == 0 {
+					buf.WriteString(decode2231Enc(v))
+				} else {
+					decv, _ := percentHexUnescape(v)
+					buf.WriteString(decv)
+				}
+			} else {
+				break
+			}
+		}
+		if valid {
+			params[key] = buf.String()
+		}
+	}
+
+	return
+}
+
+func decode2231Enc(v string) string {
+	sv := strings.SplitN(v, "'", 3)
+	if len(sv) != 3 {
+		return ""
+	}
+	// TODO: ignoring lang in sv[1] for now. If anybody needs it we'll
+	// need to decide how to expose it in the API. But I'm not sure
+	// anybody uses it in practice.
+	charset := strings.ToLower(sv[0])
+	if charset != "us-ascii" && charset != "utf-8" {
+		// TODO: unsupported encoding
+		return ""
+	}
+	encv, _ := percentHexUnescape(sv[2])
+	return encv
+}
+
+func isNotTokenChar(r rune) bool {
+	return !isTokenChar(r)
+}
+
+// consumeToken consumes a token from the beginning of provided
+// string, per RFC 2045 section 5.1 (referenced from 2183), and return
+// the token consumed and the rest of the string.  Returns ("", v) on
+// failure to consume at least one character.
+func consumeToken(v string) (token, rest string) {
+	notPos := strings.IndexFunc(v, isNotTokenChar)
+	if notPos == -1 {
+		return v, ""
+	}
+	if notPos == 0 {
+		return "", v
+	}
+	return v[0:notPos], v[notPos:]
+}
+
+// consumeValue consumes a "value" per RFC 2045, where a value is
+// either a 'token' or a 'quoted-string'.  On success, consumeValue
+// returns the value consumed (and de-quoted/escaped, if a
+// quoted-string) and the rest of the string.  On failure, returns
+// ("", v).
+func consumeValue(v string) (value, rest string) {
+	if !strings.HasPrefix(v, `"`) && !strings.HasPrefix(v, `'`) {
+		return consumeToken(v)
+	}
+
+	leadQuote := rune(v[0])
+
+	// parse a quoted-string
+	rest = v[1:] // consume the leading quote
+	buffer := new(bytes.Buffer)
+	var idx int
+	var r rune
+	var nextIsLiteral bool
+	for idx, r = range rest {
+		switch {
+		case nextIsLiteral:
+			buffer.WriteRune(r)
+			nextIsLiteral = false
+		case r == leadQuote:
+			return buffer.String(), rest[idx+1:]
+		case r == '\\':
+			nextIsLiteral = true
+		case r != '\r' && r != '\n':
+			buffer.WriteRune(r)
+		default:
+			return "", v
+		}
+	}
+	return "", v
+}
+
+func consumeMediaParam(v string) (param, value, rest string) {
+	rest = strings.TrimLeftFunc(v, unicode.IsSpace)
+	if !strings.HasPrefix(rest, ";") {
+		return "", "", v
+	}
+
+	rest = rest[1:] // consume semicolon
+	rest = strings.TrimLeftFunc(rest, unicode.IsSpace)
+	param, rest = consumeToken(rest)
+	param = strings.ToLower(param)
+	if param == "" {
+		return "", "", v
+	}
+
+	rest = strings.TrimLeftFunc(rest, unicode.IsSpace)
+	if !strings.HasPrefix(rest, "=") {
+		return "", "", v
+	}
+	rest = rest[1:] // consume equals sign
+	rest = strings.TrimLeftFunc(rest, unicode.IsSpace)
+	value, rest = consumeValue(rest)
+	if value == "" {
+		return "", "", v
+	}
+	return param, value, rest
+}
+
+func percentHexUnescape(s string) (string, error) {
+	// Count %, check that they're well-formed.
+	percents := 0
+	for i := 0; i < len(s); {
+		if s[i] != '%' {
+			i++
+			continue
+		}
+		percents++
+		if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
+			s = s[i:]
+			if len(s) > 3 {
+				s = s[0:3]
+			}
+			return "", fmt.Errorf("mime: bogus characters after %%: %q", s)
+		}
+		i += 3
+	}
+	if percents == 0 {
+		return s, nil
+	}
+
+	t := make([]byte, len(s)-2*percents)
+	j := 0
+	for i := 0; i < len(s); {
+		switch s[i] {
+		case '%':
+			t[j] = unhex(s[i+1])<<4 | unhex(s[i+2])
+			j++
+			i += 3
+		default:
+			t[j] = s[i]
+			j++
+			i++
+		}
+	}
+	return string(t), nil
+}
+
+func ishex(c byte) bool {
+	switch {
+	case '0' <= c && c <= '9':
+		return true
+	case 'a' <= c && c <= 'f':
+		return true
+	case 'A' <= c && c <= 'F':
+		return true
+	}
+	return false
+}
+
+func unhex(c byte) byte {
+	switch {
+	case '0' <= c && c <= '9':
+		return c - '0'
+	case 'a' <= c && c <= 'f':
+		return c - 'a' + 10
+	case 'A' <= c && c <= 'F':
+		return c - 'A' + 10
+	}
+	return 0
+}
diff --git a/third_party/gofrontend/libgo/go/mime/mediatype_test.go b/third_party/gofrontend/libgo/go/mime/mediatype_test.go
new file mode 100644
index 0000000..026bfa4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/mediatype_test.go
@@ -0,0 +1,306 @@
+// Copyright 2010 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 mime
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestConsumeToken(t *testing.T) {
+	tests := [...][3]string{
+		{"foo bar", "foo", " bar"},
+		{"bar", "bar", ""},
+		{"", "", ""},
+		{" foo", "", " foo"},
+	}
+	for _, test := range tests {
+		token, rest := consumeToken(test[0])
+		expectedToken := test[1]
+		expectedRest := test[2]
+		if token != expectedToken {
+			t.Errorf("expected to consume token '%s', not '%s' from '%s'",
+				expectedToken, token, test[0])
+		} else if rest != expectedRest {
+			t.Errorf("expected to have left '%s', not '%s' after reading token '%s' from '%s'",
+				expectedRest, rest, token, test[0])
+		}
+	}
+}
+
+func TestConsumeValue(t *testing.T) {
+	tests := [...][3]string{
+		{"foo bar", "foo", " bar"},
+		{"bar", "bar", ""},
+		{" bar ", "", " bar "},
+		{`"My value"end`, "My value", "end"},
+		{`"My value" end`, "My value", " end"},
+		{`"\\" rest`, "\\", " rest"},
+		{`"My \" value"end`, "My \" value", "end"},
+		{`"\" rest`, "", `"\" rest`},
+	}
+	for _, test := range tests {
+		value, rest := consumeValue(test[0])
+		expectedValue := test[1]
+		expectedRest := test[2]
+		if value != expectedValue {
+			t.Errorf("expected to consume value [%s], not [%s] from [%s]",
+				expectedValue, value, test[0])
+		} else if rest != expectedRest {
+			t.Errorf("expected to have left [%s], not [%s] after reading value [%s] from [%s]",
+				expectedRest, rest, value, test[0])
+		}
+	}
+}
+
+func TestConsumeMediaParam(t *testing.T) {
+	tests := [...][4]string{
+		{" ; foo=bar", "foo", "bar", ""},
+		{"; foo=bar", "foo", "bar", ""},
+		{";foo=bar", "foo", "bar", ""},
+		{";FOO=bar", "foo", "bar", ""},
+		{`;foo="bar"`, "foo", "bar", ""},
+		{`;foo="bar"; `, "foo", "bar", "; "},
+		{`;foo="bar"; foo=baz`, "foo", "bar", "; foo=baz"},
+		{` ; boundary=----CUT;`, "boundary", "----CUT", ";"},
+		{` ; key=value;  blah="value";name="foo" `, "key", "value", `;  blah="value";name="foo" `},
+		{`;  blah="value";name="foo" `, "blah", "value", `;name="foo" `},
+		{`;name="foo" `, "name", "foo", ` `},
+	}
+	for _, test := range tests {
+		param, value, rest := consumeMediaParam(test[0])
+		expectedParam := test[1]
+		expectedValue := test[2]
+		expectedRest := test[3]
+		if param != expectedParam {
+			t.Errorf("expected to consume param [%s], not [%s] from [%s]",
+				expectedParam, param, test[0])
+		} else if value != expectedValue {
+			t.Errorf("expected to consume value [%s], not [%s] from [%s]",
+				expectedValue, value, test[0])
+		} else if rest != expectedRest {
+			t.Errorf("expected to have left [%s], not [%s] after reading [%s/%s] from [%s]",
+				expectedRest, rest, param, value, test[0])
+		}
+	}
+}
+
+type mediaTypeTest struct {
+	in string
+	t  string
+	p  map[string]string
+}
+
+func TestParseMediaType(t *testing.T) {
+	// Convenience map initializer
+	m := func(s ...string) map[string]string {
+		sm := make(map[string]string)
+		for i := 0; i < len(s); i += 2 {
+			sm[s[i]] = s[i+1]
+		}
+		return sm
+	}
+
+	nameFoo := map[string]string{"name": "foo"}
+	tests := []mediaTypeTest{
+		{`form-data; name="foo"`, "form-data", nameFoo},
+		{` form-data ; name=foo`, "form-data", nameFoo},
+		{`FORM-DATA;name="foo"`, "form-data", nameFoo},
+		{` FORM-DATA ; name="foo"`, "form-data", nameFoo},
+		{` FORM-DATA ; name="foo"`, "form-data", nameFoo},
+
+		{`form-data; key=value;  blah="value";name="foo" `,
+			"form-data",
+			m("key", "value", "blah", "value", "name", "foo")},
+
+		{`foo; key=val1; key=the-key-appears-again-which-is-bogus`,
+			"", m()},
+
+		// From RFC 2231:
+		{`application/x-stuff; title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A`,
+			"application/x-stuff",
+			m("title", "This is ***fun***")},
+
+		{`message/external-body; access-type=URL; ` +
+			`URL*0="ftp://";` +
+			`URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"`,
+			"message/external-body",
+			m("access-type", "URL",
+				"url", "ftp://cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar")},
+
+		{`application/x-stuff; ` +
+			`title*0*=us-ascii'en'This%20is%20even%20more%20; ` +
+			`title*1*=%2A%2A%2Afun%2A%2A%2A%20; ` +
+			`title*2="isn't it!"`,
+			"application/x-stuff",
+			m("title", "This is even more ***fun*** isn't it!")},
+
+		// Tests from http://greenbytes.de/tech/tc2231/
+		// TODO(bradfitz): add the rest of the tests from that site.
+		{`attachment; filename="f\oo.html"`,
+			"attachment",
+			m("filename", "foo.html")},
+		{`attachment; filename="\"quoting\" tested.html"`,
+			"attachment",
+			m("filename", `"quoting" tested.html`)},
+		{`attachment; filename="Here's a semicolon;.html"`,
+			"attachment",
+			m("filename", "Here's a semicolon;.html")},
+		{`attachment; foo="\"\\";filename="foo.html"`,
+			"attachment",
+			m("foo", "\"\\", "filename", "foo.html")},
+		{`attachment; filename=foo.html`,
+			"attachment",
+			m("filename", "foo.html")},
+		{`attachment; filename=foo.html ;`,
+			"attachment",
+			m("filename", "foo.html")},
+		{`attachment; filename='foo.html'`,
+			"attachment",
+			m("filename", "foo.html")},
+		{`attachment; filename="foo-%41.html"`,
+			"attachment",
+			m("filename", "foo-%41.html")},
+		{`attachment; filename="foo-%\41.html"`,
+			"attachment",
+			m("filename", "foo-%41.html")},
+		{`filename=foo.html`,
+			"", m()},
+		{`x=y; filename=foo.html`,
+			"", m()},
+		{`"foo; filename=bar;baz"; filename=qux`,
+			"", m()},
+		{`inline; attachment; filename=foo.html`,
+			"", m()},
+		{`attachment; filename="foo.html".txt`,
+			"", m()},
+		{`attachment; filename="bar`,
+			"", m()},
+		{`attachment; creation-date="Wed, 12 Feb 1997 16:29:51 -0500"`,
+			"attachment",
+			m("creation-date", "Wed, 12 Feb 1997 16:29:51 -0500")},
+		{`foobar`, "foobar", m()},
+		{`attachment; filename* =UTF-8''foo-%c3%a4.html`,
+			"attachment",
+			m("filename", "foo-ä.html")},
+		{`attachment; filename*=UTF-8''A-%2541.html`,
+			"attachment",
+			m("filename", "A-%41.html")},
+		{`attachment; filename*0="foo."; filename*1="html"`,
+			"attachment",
+			m("filename", "foo.html")},
+		{`attachment; filename*0*=UTF-8''foo-%c3%a4; filename*1=".html"`,
+			"attachment",
+			m("filename", "foo-ä.html")},
+		{`attachment; filename*0="foo"; filename*01="bar"`,
+			"attachment",
+			m("filename", "foo")},
+		{`attachment; filename*0="foo"; filename*2="bar"`,
+			"attachment",
+			m("filename", "foo")},
+		{`attachment; filename*1="foo"; filename*2="bar"`,
+			"attachment", m()},
+		{`attachment; filename*1="bar"; filename*0="foo"`,
+			"attachment",
+			m("filename", "foobar")},
+		{`attachment; filename="foo-ae.html"; filename*=UTF-8''foo-%c3%a4.html`,
+			"attachment",
+			m("filename", "foo-ä.html")},
+		{`attachment; filename*=UTF-8''foo-%c3%a4.html; filename="foo-ae.html"`,
+			"attachment",
+			m("filename", "foo-ä.html")},
+
+		// Browsers also just send UTF-8 directly without RFC 2231,
+		// at least when the source page is served with UTF-8.
+		{`form-data; firstname="Брэд"; lastname="Фицпатрик"`,
+			"form-data",
+			m("firstname", "Брэд", "lastname", "Фицпатрик")},
+	}
+	for _, test := range tests {
+		mt, params, err := ParseMediaType(test.in)
+		if err != nil {
+			if test.t != "" {
+				t.Errorf("for input %q, unexpected error: %v", test.in, err)
+				continue
+			}
+			continue
+		}
+		if g, e := mt, test.t; g != e {
+			t.Errorf("for input %q, expected type %q, got %q",
+				test.in, e, g)
+			continue
+		}
+		if len(params) == 0 && len(test.p) == 0 {
+			continue
+		}
+		if !reflect.DeepEqual(params, test.p) {
+			t.Errorf("for input %q, wrong params.\n"+
+				"expected: %#v\n"+
+				"     got: %#v",
+				test.in, test.p, params)
+		}
+	}
+}
+
+type badMediaTypeTest struct {
+	in  string
+	err string
+}
+
+var badMediaTypeTests = []badMediaTypeTest{
+	{"bogus ;=========", "mime: invalid media parameter"},
+	{"bogus/<script>alert</script>", "mime: expected token after slash"},
+	{"bogus/bogus<script>alert</script>", "mime: unexpected content after media subtype"},
+}
+
+func TestParseMediaTypeBogus(t *testing.T) {
+	for _, tt := range badMediaTypeTests {
+		mt, params, err := ParseMediaType(tt.in)
+		if err == nil {
+			t.Errorf("ParseMediaType(%q) = nil error; want parse error", tt.in)
+			continue
+		}
+		if err.Error() != tt.err {
+			t.Errorf("ParseMediaType(%q) = err %q; want %q", tt.in, err.Error(), tt.err)
+		}
+		if params != nil {
+			t.Errorf("ParseMediaType(%q): got non-nil params on error", tt.in)
+		}
+		if mt != "" {
+			t.Errorf("ParseMediaType(%q): got non-empty media type string on error", tt.in)
+		}
+	}
+}
+
+type formatTest struct {
+	typ    string
+	params map[string]string
+	want   string
+}
+
+var formatTests = []formatTest{
+	{"noslash", nil, ""},
+	{"foo bar/baz", nil, ""},
+	{"foo/bar baz", nil, ""},
+	{"foo/BAR", nil, "foo/bar"},
+	{"foo/BAR", map[string]string{"X": "Y"}, "foo/bar; x=Y"},
+	{"foo/BAR", map[string]string{"space": "With space"}, `foo/bar; space="With space"`},
+	{"foo/BAR", map[string]string{"quote": `With "quote`}, `foo/bar; quote="With \"quote"`},
+	{"foo/BAR", map[string]string{"bslash": `With \backslash`}, `foo/bar; bslash="With \\backslash"`},
+	{"foo/BAR", map[string]string{"both": `With \backslash and "quote`}, `foo/bar; both="With \\backslash and \"quote"`},
+	{"foo/BAR", map[string]string{"": "empty attribute"}, ""},
+	{"foo/BAR", map[string]string{"bad attribute": "baz"}, ""},
+	{"foo/BAR", map[string]string{"nonascii": "not an ascii character: ä"}, ""},
+	{"foo/bar", map[string]string{"a": "av", "b": "bv", "c": "cv"}, "foo/bar; a=av; b=bv; c=cv"},
+}
+
+func TestFormatMediaType(t *testing.T) {
+	for i, tt := range formatTests {
+		got := FormatMediaType(tt.typ, tt.params)
+		if got != tt.want {
+			t.Errorf("%d. FormatMediaType(%q, %v) = %q; want %q", i, tt.typ, tt.params, got, tt.want)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/mime/multipart/formdata.go b/third_party/gofrontend/libgo/go/mime/multipart/formdata.go
new file mode 100644
index 0000000..eee53fc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/multipart/formdata.go
@@ -0,0 +1,157 @@
+// 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.
+
+package multipart
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"io/ioutil"
+	"net/textproto"
+	"os"
+)
+
+// TODO(adg,bradfitz): find a way to unify the DoS-prevention strategy here
+// with that of the http package's ParseForm.
+
+// ReadForm parses an entire multipart message whose parts have
+// a Content-Disposition of "form-data".
+// It stores up to maxMemory bytes of the file parts in memory
+// and the remainder on disk in temporary files.
+func (r *Reader) ReadForm(maxMemory int64) (f *Form, err error) {
+	form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
+	defer func() {
+		if err != nil {
+			form.RemoveAll()
+		}
+	}()
+
+	maxValueBytes := int64(10 << 20) // 10 MB is a lot of text.
+	for {
+		p, err := r.NextPart()
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return nil, err
+		}
+
+		name := p.FormName()
+		if name == "" {
+			continue
+		}
+		filename := p.FileName()
+
+		var b bytes.Buffer
+
+		if filename == "" {
+			// value, store as string in memory
+			n, err := io.CopyN(&b, p, maxValueBytes)
+			if err != nil && err != io.EOF {
+				return nil, err
+			}
+			maxValueBytes -= n
+			if maxValueBytes == 0 {
+				return nil, errors.New("multipart: message too large")
+			}
+			form.Value[name] = append(form.Value[name], b.String())
+			continue
+		}
+
+		// file, store in memory or on disk
+		fh := &FileHeader{
+			Filename: filename,
+			Header:   p.Header,
+		}
+		n, err := io.CopyN(&b, p, maxMemory+1)
+		if err != nil && err != io.EOF {
+			return nil, err
+		}
+		if n > maxMemory {
+			// too big, write to disk and flush buffer
+			file, err := ioutil.TempFile("", "multipart-")
+			if err != nil {
+				return nil, err
+			}
+			defer file.Close()
+			_, err = io.Copy(file, io.MultiReader(&b, p))
+			if err != nil {
+				os.Remove(file.Name())
+				return nil, err
+			}
+			fh.tmpfile = file.Name()
+		} else {
+			fh.content = b.Bytes()
+			maxMemory -= n
+		}
+		form.File[name] = append(form.File[name], fh)
+	}
+
+	return form, nil
+}
+
+// Form is a parsed multipart form.
+// Its File parts are stored either in memory or on disk,
+// and are accessible via the *FileHeader's Open method.
+// Its Value parts are stored as strings.
+// Both are keyed by field name.
+type Form struct {
+	Value map[string][]string
+	File  map[string][]*FileHeader
+}
+
+// RemoveAll removes any temporary files associated with a Form.
+func (f *Form) RemoveAll() error {
+	var err error
+	for _, fhs := range f.File {
+		for _, fh := range fhs {
+			if fh.tmpfile != "" {
+				e := os.Remove(fh.tmpfile)
+				if e != nil && err == nil {
+					err = e
+				}
+			}
+		}
+	}
+	return err
+}
+
+// A FileHeader describes a file part of a multipart request.
+type FileHeader struct {
+	Filename string
+	Header   textproto.MIMEHeader
+
+	content []byte
+	tmpfile string
+}
+
+// Open opens and returns the FileHeader's associated File.
+func (fh *FileHeader) Open() (File, error) {
+	if b := fh.content; b != nil {
+		r := io.NewSectionReader(bytes.NewReader(b), 0, int64(len(b)))
+		return sectionReadCloser{r}, nil
+	}
+	return os.Open(fh.tmpfile)
+}
+
+// File is an interface to access the file part of a multipart message.
+// Its contents may be either stored in memory or on disk.
+// If stored on disk, the File's underlying concrete type will be an *os.File.
+type File interface {
+	io.Reader
+	io.ReaderAt
+	io.Seeker
+	io.Closer
+}
+
+// helper types to turn a []byte into a File
+
+type sectionReadCloser struct {
+	*io.SectionReader
+}
+
+func (rc sectionReadCloser) Close() error {
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/mime/multipart/formdata_test.go b/third_party/gofrontend/libgo/go/mime/multipart/formdata_test.go
new file mode 100644
index 0000000..6e2388b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/multipart/formdata_test.go
@@ -0,0 +1,90 @@
+// 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.
+
+package multipart
+
+import (
+	"bytes"
+	"io"
+	"os"
+	"regexp"
+	"strings"
+	"testing"
+)
+
+func TestReadForm(t *testing.T) {
+	testBody := regexp.MustCompile("\n").ReplaceAllString(message, "\r\n")
+	b := strings.NewReader(testBody)
+	r := NewReader(b, boundary)
+	f, err := r.ReadForm(25)
+	if err != nil {
+		t.Fatal("ReadForm:", err)
+	}
+	defer f.RemoveAll()
+	if g, e := f.Value["texta"][0], textaValue; g != e {
+		t.Errorf("texta value = %q, want %q", g, e)
+	}
+	if g, e := f.Value["textb"][0], textbValue; g != e {
+		t.Errorf("texta value = %q, want %q", g, e)
+	}
+	fd := testFile(t, f.File["filea"][0], "filea.txt", fileaContents)
+	if _, ok := fd.(*os.File); ok {
+		t.Error("file is *os.File, should not be")
+	}
+	fd.Close()
+	fd = testFile(t, f.File["fileb"][0], "fileb.txt", filebContents)
+	if _, ok := fd.(*os.File); !ok {
+		t.Errorf("file has unexpected underlying type %T", fd)
+	}
+	fd.Close()
+}
+
+func testFile(t *testing.T, fh *FileHeader, efn, econtent string) File {
+	if fh.Filename != efn {
+		t.Errorf("filename = %q, want %q", fh.Filename, efn)
+	}
+	f, err := fh.Open()
+	if err != nil {
+		t.Fatal("opening file:", err)
+	}
+	b := new(bytes.Buffer)
+	_, err = io.Copy(b, f)
+	if err != nil {
+		t.Fatal("copying contents:", err)
+	}
+	if g := b.String(); g != econtent {
+		t.Errorf("contents = %q, want %q", g, econtent)
+	}
+	return f
+}
+
+const (
+	fileaContents = "This is a test file."
+	filebContents = "Another test file."
+	textaValue    = "foo"
+	textbValue    = "bar"
+	boundary      = `MyBoundary`
+)
+
+const message = `
+--MyBoundary
+Content-Disposition: form-data; name="filea"; filename="filea.txt"
+Content-Type: text/plain
+
+` + fileaContents + `
+--MyBoundary
+Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
+Content-Type: text/plain
+
+` + filebContents + `
+--MyBoundary
+Content-Disposition: form-data; name="texta"
+
+` + textaValue + `
+--MyBoundary
+Content-Disposition: form-data; name="textb"
+
+` + textbValue + `
+--MyBoundary--
+`
diff --git a/third_party/gofrontend/libgo/go/mime/multipart/multipart.go b/third_party/gofrontend/libgo/go/mime/multipart/multipart.go
new file mode 100644
index 0000000..7382efa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/multipart/multipart.go
@@ -0,0 +1,349 @@
+// Copyright 2010 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 multipart implements MIME multipart parsing, as defined in RFC
+2046.
+
+The implementation is sufficient for HTTP (RFC 2388) and the multipart
+bodies generated by popular browsers.
+*/
+package multipart
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"mime"
+	"net/textproto"
+)
+
+var emptyParams = make(map[string]string)
+
+// A Part represents a single part in a multipart body.
+type Part struct {
+	// The headers of the body, if any, with the keys canonicalized
+	// in the same fashion that the Go http.Request headers are.
+	// For example, "foo-bar" changes case to "Foo-Bar"
+	//
+	// As a special case, if the "Content-Transfer-Encoding" header
+	// has a value of "quoted-printable", that header is instead
+	// hidden from this map and the body is transparently decoded
+	// during Read calls.
+	Header textproto.MIMEHeader
+
+	buffer    *bytes.Buffer
+	mr        *Reader
+	bytesRead int
+
+	disposition       string
+	dispositionParams map[string]string
+
+	// r is either a reader directly reading from mr, or it's a
+	// wrapper around such a reader, decoding the
+	// Content-Transfer-Encoding
+	r io.Reader
+}
+
+// FormName returns the name parameter if p has a Content-Disposition
+// of type "form-data".  Otherwise it returns the empty string.
+func (p *Part) FormName() string {
+	// See http://tools.ietf.org/html/rfc2183 section 2 for EBNF
+	// of Content-Disposition value format.
+	if p.dispositionParams == nil {
+		p.parseContentDisposition()
+	}
+	if p.disposition != "form-data" {
+		return ""
+	}
+	return p.dispositionParams["name"]
+}
+
+// FileName returns the filename parameter of the Part's
+// Content-Disposition header.
+func (p *Part) FileName() string {
+	if p.dispositionParams == nil {
+		p.parseContentDisposition()
+	}
+	return p.dispositionParams["filename"]
+}
+
+func (p *Part) parseContentDisposition() {
+	v := p.Header.Get("Content-Disposition")
+	var err error
+	p.disposition, p.dispositionParams, err = mime.ParseMediaType(v)
+	if err != nil {
+		p.dispositionParams = emptyParams
+	}
+}
+
+// NewReader creates a new multipart Reader reading from r using the
+// given MIME boundary.
+//
+// The boundary is usually obtained from the "boundary" parameter of
+// the message's "Content-Type" header. Use mime.ParseMediaType to
+// parse such headers.
+func NewReader(r io.Reader, boundary string) *Reader {
+	b := []byte("\r\n--" + boundary + "--")
+	return &Reader{
+		bufReader: bufio.NewReader(r),
+
+		nl:               b[:2],
+		nlDashBoundary:   b[:len(b)-2],
+		dashBoundaryDash: b[2:],
+		dashBoundary:     b[2 : len(b)-2],
+	}
+}
+
+func newPart(mr *Reader) (*Part, error) {
+	bp := &Part{
+		Header: make(map[string][]string),
+		mr:     mr,
+		buffer: new(bytes.Buffer),
+	}
+	if err := bp.populateHeaders(); err != nil {
+		return nil, err
+	}
+	bp.r = partReader{bp}
+	const cte = "Content-Transfer-Encoding"
+	if bp.Header.Get(cte) == "quoted-printable" {
+		bp.Header.Del(cte)
+		bp.r = newQuotedPrintableReader(bp.r)
+	}
+	return bp, nil
+}
+
+func (bp *Part) populateHeaders() error {
+	r := textproto.NewReader(bp.mr.bufReader)
+	header, err := r.ReadMIMEHeader()
+	if err == nil {
+		bp.Header = header
+	}
+	return err
+}
+
+// Read reads the body of a part, after its headers and before the
+// next part (if any) begins.
+func (p *Part) Read(d []byte) (n int, err error) {
+	return p.r.Read(d)
+}
+
+// partReader implements io.Reader by reading raw bytes directly from the
+// wrapped *Part, without doing any Transfer-Encoding decoding.
+type partReader struct {
+	p *Part
+}
+
+func (pr partReader) Read(d []byte) (n int, err error) {
+	p := pr.p
+	defer func() {
+		p.bytesRead += n
+	}()
+	if p.buffer.Len() >= len(d) {
+		// Internal buffer of unconsumed data is large enough for
+		// the read request.  No need to parse more at the moment.
+		return p.buffer.Read(d)
+	}
+	peek, err := p.mr.bufReader.Peek(4096) // TODO(bradfitz): add buffer size accessor
+
+	// Look for an immediate empty part without a leading \r\n
+	// before the boundary separator.  Some MIME code makes empty
+	// parts like this. Most browsers, however, write the \r\n
+	// before the subsequent boundary even for empty parts and
+	// won't hit this path.
+	if p.bytesRead == 0 && p.mr.peekBufferIsEmptyPart(peek) {
+		return 0, io.EOF
+	}
+	unexpectedEOF := err == io.EOF
+	if err != nil && !unexpectedEOF {
+		return 0, fmt.Errorf("multipart: Part Read: %v", err)
+	}
+	if peek == nil {
+		panic("nil peek buf")
+	}
+
+	// Search the peek buffer for "\r\n--boundary". If found,
+	// consume everything up to the boundary. If not, consume only
+	// as much of the peek buffer as cannot hold the boundary
+	// string.
+	nCopy := 0
+	foundBoundary := false
+	if idx := bytes.Index(peek, p.mr.nlDashBoundary); idx != -1 {
+		nCopy = idx
+		foundBoundary = true
+	} else if safeCount := len(peek) - len(p.mr.nlDashBoundary); safeCount > 0 {
+		nCopy = safeCount
+	} else if unexpectedEOF {
+		// If we've run out of peek buffer and the boundary
+		// wasn't found (and can't possibly fit), we must have
+		// hit the end of the file unexpectedly.
+		return 0, io.ErrUnexpectedEOF
+	}
+	if nCopy > 0 {
+		if _, err := io.CopyN(p.buffer, p.mr.bufReader, int64(nCopy)); err != nil {
+			return 0, err
+		}
+	}
+	n, err = p.buffer.Read(d)
+	if err == io.EOF && !foundBoundary {
+		// If the boundary hasn't been reached there's more to
+		// read, so don't pass through an EOF from the buffer
+		err = nil
+	}
+	return
+}
+
+func (p *Part) Close() error {
+	io.Copy(ioutil.Discard, p)
+	return nil
+}
+
+// Reader is an iterator over parts in a MIME multipart body.
+// Reader's underlying parser consumes its input as needed.  Seeking
+// isn't supported.
+type Reader struct {
+	bufReader *bufio.Reader
+
+	currentPart *Part
+	partsRead   int
+
+	nl               []byte // "\r\n" or "\n" (set after seeing first boundary line)
+	nlDashBoundary   []byte // nl + "--boundary"
+	dashBoundaryDash []byte // "--boundary--"
+	dashBoundary     []byte // "--boundary"
+}
+
+// NextPart returns the next part in the multipart or an error.
+// When there are no more parts, the error io.EOF is returned.
+func (r *Reader) NextPart() (*Part, error) {
+	if r.currentPart != nil {
+		r.currentPart.Close()
+	}
+
+	expectNewPart := false
+	for {
+		line, err := r.bufReader.ReadSlice('\n')
+		if err == io.EOF && r.isFinalBoundary(line) {
+			// If the buffer ends in "--boundary--" without the
+			// trailing "\r\n", ReadSlice will return an error
+			// (since it's missing the '\n'), but this is a valid
+			// multipart EOF so we need to return io.EOF instead of
+			// a fmt-wrapped one.
+			return nil, io.EOF
+		}
+		if err != nil {
+			return nil, fmt.Errorf("multipart: NextPart: %v", err)
+		}
+
+		if r.isBoundaryDelimiterLine(line) {
+			r.partsRead++
+			bp, err := newPart(r)
+			if err != nil {
+				return nil, err
+			}
+			r.currentPart = bp
+			return bp, nil
+		}
+
+		if r.isFinalBoundary(line) {
+			// Expected EOF
+			return nil, io.EOF
+		}
+
+		if expectNewPart {
+			return nil, fmt.Errorf("multipart: expecting a new Part; got line %q", string(line))
+		}
+
+		if r.partsRead == 0 {
+			// skip line
+			continue
+		}
+
+		// Consume the "\n" or "\r\n" separator between the
+		// body of the previous part and the boundary line we
+		// now expect will follow. (either a new part or the
+		// end boundary)
+		if bytes.Equal(line, r.nl) {
+			expectNewPart = true
+			continue
+		}
+
+		return nil, fmt.Errorf("multipart: unexpected line in Next(): %q", line)
+	}
+}
+
+// isFinalBoundary reports whether line is the final boundary line
+// indicating that all parts are over.
+// It matches `^--boundary--[ \t]*(\r\n)?$`
+func (mr *Reader) isFinalBoundary(line []byte) bool {
+	if !bytes.HasPrefix(line, mr.dashBoundaryDash) {
+		return false
+	}
+	rest := line[len(mr.dashBoundaryDash):]
+	rest = skipLWSPChar(rest)
+	return len(rest) == 0 || bytes.Equal(rest, mr.nl)
+}
+
+func (mr *Reader) isBoundaryDelimiterLine(line []byte) (ret bool) {
+	// http://tools.ietf.org/html/rfc2046#section-5.1
+	//   The boundary delimiter line is then defined as a line
+	//   consisting entirely of two hyphen characters ("-",
+	//   decimal value 45) followed by the boundary parameter
+	//   value from the Content-Type header field, optional linear
+	//   whitespace, and a terminating CRLF.
+	if !bytes.HasPrefix(line, mr.dashBoundary) {
+		return false
+	}
+	rest := line[len(mr.dashBoundary):]
+	rest = skipLWSPChar(rest)
+
+	// On the first part, see our lines are ending in \n instead of \r\n
+	// and switch into that mode if so.  This is a violation of the spec,
+	// but occurs in practice.
+	if mr.partsRead == 0 && len(rest) == 1 && rest[0] == '\n' {
+		mr.nl = mr.nl[1:]
+		mr.nlDashBoundary = mr.nlDashBoundary[1:]
+	}
+	return bytes.Equal(rest, mr.nl)
+}
+
+// peekBufferIsEmptyPart reports whether the provided peek-ahead
+// buffer represents an empty part. It is called only if we've not
+// already read any bytes in this part and checks for the case of MIME
+// software not writing the \r\n on empty parts. Some does, some
+// doesn't.
+//
+// This checks that what follows the "--boundary" is actually the end
+// ("--boundary--" with optional whitespace) or optional whitespace
+// and then a newline, so we don't catch "--boundaryFAKE", in which
+// case the whole line is part of the data.
+func (mr *Reader) peekBufferIsEmptyPart(peek []byte) bool {
+	// End of parts case.
+	// Test whether peek matches `^--boundary--[ \t]*(?:\r\n|$)`
+	if bytes.HasPrefix(peek, mr.dashBoundaryDash) {
+		rest := peek[len(mr.dashBoundaryDash):]
+		rest = skipLWSPChar(rest)
+		return bytes.HasPrefix(rest, mr.nl) || len(rest) == 0
+	}
+	if !bytes.HasPrefix(peek, mr.dashBoundary) {
+		return false
+	}
+	// Test whether rest matches `^[ \t]*\r\n`)
+	rest := peek[len(mr.dashBoundary):]
+	rest = skipLWSPChar(rest)
+	return bytes.HasPrefix(rest, mr.nl)
+}
+
+// skipLWSPChar returns b with leading spaces and tabs removed.
+// RFC 822 defines:
+//    LWSP-char = SPACE / HTAB
+func skipLWSPChar(b []byte) []byte {
+	for len(b) > 0 && (b[0] == ' ' || b[0] == '\t') {
+		b = b[1:]
+	}
+	return b
+}
diff --git a/third_party/gofrontend/libgo/go/mime/multipart/multipart_test.go b/third_party/gofrontend/libgo/go/mime/multipart/multipart_test.go
new file mode 100644
index 0000000..d662e83
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/multipart/multipart_test.go
@@ -0,0 +1,634 @@
+// Copyright 2010 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 multipart
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/textproto"
+	"os"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func TestBoundaryLine(t *testing.T) {
+	mr := NewReader(strings.NewReader(""), "myBoundary")
+	if !mr.isBoundaryDelimiterLine([]byte("--myBoundary\r\n")) {
+		t.Error("expected")
+	}
+	if !mr.isBoundaryDelimiterLine([]byte("--myBoundary \r\n")) {
+		t.Error("expected")
+	}
+	if !mr.isBoundaryDelimiterLine([]byte("--myBoundary \n")) {
+		t.Error("expected")
+	}
+	if mr.isBoundaryDelimiterLine([]byte("--myBoundary bogus \n")) {
+		t.Error("expected fail")
+	}
+	if mr.isBoundaryDelimiterLine([]byte("--myBoundary bogus--")) {
+		t.Error("expected fail")
+	}
+}
+
+func escapeString(v string) string {
+	bytes, _ := json.Marshal(v)
+	return string(bytes)
+}
+
+func expectEq(t *testing.T, expected, actual, what string) {
+	if expected == actual {
+		return
+	}
+	t.Errorf("Unexpected value for %s; got %s (len %d) but expected: %s (len %d)",
+		what, escapeString(actual), len(actual), escapeString(expected), len(expected))
+}
+
+func TestNameAccessors(t *testing.T) {
+	tests := [...][3]string{
+		{`form-data; name="foo"`, "foo", ""},
+		{` form-data ; name=foo`, "foo", ""},
+		{`FORM-DATA;name="foo"`, "foo", ""},
+		{` FORM-DATA ; name="foo"`, "foo", ""},
+		{` FORM-DATA ; name="foo"`, "foo", ""},
+		{` FORM-DATA ; name=foo`, "foo", ""},
+		{` FORM-DATA ; filename="foo.txt"; name=foo; baz=quux`, "foo", "foo.txt"},
+		{` not-form-data ; filename="bar.txt"; name=foo; baz=quux`, "", "bar.txt"},
+	}
+	for i, test := range tests {
+		p := &Part{Header: make(map[string][]string)}
+		p.Header.Set("Content-Disposition", test[0])
+		if g, e := p.FormName(), test[1]; g != e {
+			t.Errorf("test %d: FormName() = %q; want %q", i, g, e)
+		}
+		if g, e := p.FileName(), test[2]; g != e {
+			t.Errorf("test %d: FileName() = %q; want %q", i, g, e)
+		}
+	}
+}
+
+var longLine = strings.Repeat("\n\n\r\r\r\n\r\000", (1<<20)/8)
+
+func testMultipartBody(sep string) string {
+	testBody := `
+This is a multi-part message.  This line is ignored.
+--MyBoundary
+Header1: value1
+HEADER2: value2
+foo-bar: baz
+
+My value
+The end.
+--MyBoundary
+name: bigsection
+
+[longline]
+--MyBoundary
+Header1: value1b
+HEADER2: value2b
+foo-bar: bazb
+
+Line 1
+Line 2
+Line 3 ends in a newline, but just one.
+
+--MyBoundary
+
+never read data
+--MyBoundary--
+
+
+useless trailer
+`
+	testBody = strings.Replace(testBody, "\n", sep, -1)
+	return strings.Replace(testBody, "[longline]", longLine, 1)
+}
+
+func TestMultipart(t *testing.T) {
+	bodyReader := strings.NewReader(testMultipartBody("\r\n"))
+	testMultipart(t, bodyReader, false)
+}
+
+func TestMultipartOnlyNewlines(t *testing.T) {
+	bodyReader := strings.NewReader(testMultipartBody("\n"))
+	testMultipart(t, bodyReader, true)
+}
+
+func TestMultipartSlowInput(t *testing.T) {
+	bodyReader := strings.NewReader(testMultipartBody("\r\n"))
+	testMultipart(t, &slowReader{bodyReader}, false)
+}
+
+func testMultipart(t *testing.T, r io.Reader, onlyNewlines bool) {
+	reader := NewReader(r, "MyBoundary")
+	buf := new(bytes.Buffer)
+
+	// Part1
+	part, err := reader.NextPart()
+	if part == nil || err != nil {
+		t.Error("Expected part1")
+		return
+	}
+	if x := part.Header.Get("Header1"); x != "value1" {
+		t.Errorf("part.Header.Get(%q) = %q, want %q", "Header1", x, "value1")
+	}
+	if x := part.Header.Get("foo-bar"); x != "baz" {
+		t.Errorf("part.Header.Get(%q) = %q, want %q", "foo-bar", x, "baz")
+	}
+	if x := part.Header.Get("Foo-Bar"); x != "baz" {
+		t.Errorf("part.Header.Get(%q) = %q, want %q", "Foo-Bar", x, "baz")
+	}
+	buf.Reset()
+	if _, err := io.Copy(buf, part); err != nil {
+		t.Errorf("part 1 copy: %v", err)
+	}
+
+	adjustNewlines := func(s string) string {
+		if onlyNewlines {
+			return strings.Replace(s, "\r\n", "\n", -1)
+		}
+		return s
+	}
+
+	expectEq(t, adjustNewlines("My value\r\nThe end."), buf.String(), "Value of first part")
+
+	// Part2
+	part, err = reader.NextPart()
+	if err != nil {
+		t.Fatalf("Expected part2; got: %v", err)
+		return
+	}
+	if e, g := "bigsection", part.Header.Get("name"); e != g {
+		t.Errorf("part2's name header: expected %q, got %q", e, g)
+	}
+	buf.Reset()
+	if _, err := io.Copy(buf, part); err != nil {
+		t.Errorf("part 2 copy: %v", err)
+	}
+	s := buf.String()
+	if len(s) != len(longLine) {
+		t.Errorf("part2 body expected long line of length %d; got length %d",
+			len(longLine), len(s))
+	}
+	if s != longLine {
+		t.Errorf("part2 long body didn't match")
+	}
+
+	// Part3
+	part, err = reader.NextPart()
+	if part == nil || err != nil {
+		t.Error("Expected part3")
+		return
+	}
+	if part.Header.Get("foo-bar") != "bazb" {
+		t.Error("Expected foo-bar: bazb")
+	}
+	buf.Reset()
+	if _, err := io.Copy(buf, part); err != nil {
+		t.Errorf("part 3 copy: %v", err)
+	}
+	expectEq(t, adjustNewlines("Line 1\r\nLine 2\r\nLine 3 ends in a newline, but just one.\r\n"),
+		buf.String(), "body of part 3")
+
+	// Part4
+	part, err = reader.NextPart()
+	if part == nil || err != nil {
+		t.Error("Expected part 4 without errors")
+		return
+	}
+
+	// Non-existent part5
+	part, err = reader.NextPart()
+	if part != nil {
+		t.Error("Didn't expect a fifth part.")
+	}
+	if err != io.EOF {
+		t.Errorf("On fifth part expected io.EOF; got %v", err)
+	}
+}
+
+func TestVariousTextLineEndings(t *testing.T) {
+	tests := [...]string{
+		"Foo\nBar",
+		"Foo\nBar\n",
+		"Foo\r\nBar",
+		"Foo\r\nBar\r\n",
+		"Foo\rBar",
+		"Foo\rBar\r",
+		"\x00\x01\x02\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10",
+	}
+
+	for testNum, expectedBody := range tests {
+		body := "--BOUNDARY\r\n" +
+			"Content-Disposition: form-data; name=\"value\"\r\n" +
+			"\r\n" +
+			expectedBody +
+			"\r\n--BOUNDARY--\r\n"
+		bodyReader := strings.NewReader(body)
+
+		reader := NewReader(bodyReader, "BOUNDARY")
+		buf := new(bytes.Buffer)
+		part, err := reader.NextPart()
+		if part == nil {
+			t.Errorf("Expected a body part on text %d", testNum)
+			continue
+		}
+		if err != nil {
+			t.Errorf("Unexpected error on text %d: %v", testNum, err)
+			continue
+		}
+		written, err := io.Copy(buf, part)
+		expectEq(t, expectedBody, buf.String(), fmt.Sprintf("test %d", testNum))
+		if err != nil {
+			t.Errorf("Error copying multipart; bytes=%v, error=%v", written, err)
+		}
+
+		part, err = reader.NextPart()
+		if part != nil {
+			t.Errorf("Unexpected part in test %d", testNum)
+		}
+		if err != io.EOF {
+			t.Errorf("On test %d expected io.EOF; got %v", testNum, err)
+		}
+
+	}
+}
+
+type maliciousReader struct {
+	t *testing.T
+	n int
+}
+
+const maxReadThreshold = 1 << 20
+
+func (mr *maliciousReader) Read(b []byte) (n int, err error) {
+	mr.n += len(b)
+	if mr.n >= maxReadThreshold {
+		mr.t.Fatal("too much was read")
+		return 0, io.EOF
+	}
+	return len(b), nil
+}
+
+func TestLineLimit(t *testing.T) {
+	mr := &maliciousReader{t: t}
+	r := NewReader(mr, "fooBoundary")
+	part, err := r.NextPart()
+	if part != nil {
+		t.Errorf("unexpected part read")
+	}
+	if err == nil {
+		t.Errorf("expected an error")
+	}
+	if mr.n >= maxReadThreshold {
+		t.Errorf("expected to read < %d bytes; read %d", maxReadThreshold, mr.n)
+	}
+}
+
+func TestMultipartTruncated(t *testing.T) {
+	testBody := `
+This is a multi-part message.  This line is ignored.
+--MyBoundary
+foo-bar: baz
+
+Oh no, premature EOF!
+`
+	body := strings.Replace(testBody, "\n", "\r\n", -1)
+	bodyReader := strings.NewReader(body)
+	r := NewReader(bodyReader, "MyBoundary")
+
+	part, err := r.NextPart()
+	if err != nil {
+		t.Fatalf("didn't get a part")
+	}
+	_, err = io.Copy(ioutil.Discard, part)
+	if err != io.ErrUnexpectedEOF {
+		t.Fatalf("expected error io.ErrUnexpectedEOF; got %v", err)
+	}
+}
+
+type slowReader struct {
+	r io.Reader
+}
+
+func (s *slowReader) Read(p []byte) (int, error) {
+	if len(p) == 0 {
+		return s.r.Read(p)
+	}
+	return s.r.Read(p[:1])
+}
+
+func TestLineContinuation(t *testing.T) {
+	// This body, extracted from an email, contains headers that span multiple
+	// lines.
+
+	// TODO: The original mail ended with a double-newline before the
+	// final delimiter; this was manually edited to use a CRLF.
+	testBody :=
+		"\n--Apple-Mail-2-292336769\nContent-Transfer-Encoding: 7bit\nContent-Type: text/plain;\n\tcharset=US-ASCII;\n\tdelsp=yes;\n\tformat=flowed\n\nI'm finding the same thing happening on my system (10.4.1).\n\n\n--Apple-Mail-2-292336769\nContent-Transfer-Encoding: quoted-printable\nContent-Type: text/html;\n\tcharset=ISO-8859-1\n\n<HTML><BODY>I'm finding the same thing =\nhappening on my system (10.4.1).=A0 But I built it with XCode =\n2.0.</BODY></=\nHTML>=\n\r\n--Apple-Mail-2-292336769--\n"
+
+	r := NewReader(strings.NewReader(testBody), "Apple-Mail-2-292336769")
+
+	for i := 0; i < 2; i++ {
+		part, err := r.NextPart()
+		if err != nil {
+			t.Fatalf("didn't get a part")
+		}
+		var buf bytes.Buffer
+		n, err := io.Copy(&buf, part)
+		if err != nil {
+			t.Errorf("error reading part: %v\nread so far: %q", err, buf.String())
+		}
+		if n <= 0 {
+			t.Errorf("read %d bytes; expected >0", n)
+		}
+	}
+}
+
+func TestQuotedPrintableEncoding(t *testing.T) {
+	// From http://golang.org/issue/4411
+	body := "--0016e68ee29c5d515f04cedf6733\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=text\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nwords words words words words words words words words words words words wor=\r\nds words words words words words words words words words words words words =\r\nwords words words words words words words words words words words words wor=\r\nds words words words words words words words words words words words words =\r\nwords words words words words words words words words\r\n--0016e68ee29c5d515f04cedf6733\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=submit\r\n\r\nSubmit\r\n--0016e68ee29c5d515f04cedf6733--"
+	r := NewReader(strings.NewReader(body), "0016e68ee29c5d515f04cedf6733")
+	part, err := r.NextPart()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if te, ok := part.Header["Content-Transfer-Encoding"]; ok {
+		t.Errorf("unexpected Content-Transfer-Encoding of %q", te)
+	}
+	var buf bytes.Buffer
+	_, err = io.Copy(&buf, part)
+	if err != nil {
+		t.Error(err)
+	}
+	got := buf.String()
+	want := "words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words"
+	if got != want {
+		t.Errorf("wrong part value:\n got: %q\nwant: %q", got, want)
+	}
+}
+
+// Test parsing an image attachment from gmail, which previously failed.
+func TestNested(t *testing.T) {
+	// nested-mime is the body part of a multipart/mixed email
+	// with boundary e89a8ff1c1e83553e304be640612
+	f, err := os.Open("testdata/nested-mime")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer f.Close()
+	mr := NewReader(f, "e89a8ff1c1e83553e304be640612")
+	p, err := mr.NextPart()
+	if err != nil {
+		t.Fatalf("error reading first section (alternative): %v", err)
+	}
+
+	// Read the inner text/plain and text/html sections of the multipart/alternative.
+	mr2 := NewReader(p, "e89a8ff1c1e83553e004be640610")
+	p, err = mr2.NextPart()
+	if err != nil {
+		t.Fatalf("reading text/plain part: %v", err)
+	}
+	if b, err := ioutil.ReadAll(p); string(b) != "*body*\r\n" || err != nil {
+		t.Fatalf("reading text/plain part: got %q, %v", b, err)
+	}
+	p, err = mr2.NextPart()
+	if err != nil {
+		t.Fatalf("reading text/html part: %v", err)
+	}
+	if b, err := ioutil.ReadAll(p); string(b) != "<b>body</b>\r\n" || err != nil {
+		t.Fatalf("reading text/html part: got %q, %v", b, err)
+	}
+
+	p, err = mr2.NextPart()
+	if err != io.EOF {
+		t.Fatalf("final inner NextPart = %v; want io.EOF", err)
+	}
+
+	// Back to the outer multipart/mixed, reading the image attachment.
+	_, err = mr.NextPart()
+	if err != nil {
+		t.Fatalf("error reading the image attachment at the end: %v", err)
+	}
+
+	_, err = mr.NextPart()
+	if err != io.EOF {
+		t.Fatalf("final outer NextPart = %v; want io.EOF", err)
+	}
+}
+
+type headerBody struct {
+	header textproto.MIMEHeader
+	body   string
+}
+
+func formData(key, value string) headerBody {
+	return headerBody{
+		textproto.MIMEHeader{
+			"Content-Type":        {"text/plain; charset=ISO-8859-1"},
+			"Content-Disposition": {"form-data; name=" + key},
+		},
+		value,
+	}
+}
+
+type parseTest struct {
+	name    string
+	in, sep string
+	want    []headerBody
+}
+
+var parseTests = []parseTest{
+	// Actual body from App Engine on a blob upload. The final part (the
+	// Content-Type: message/external-body) is what App Engine replaces
+	// the uploaded file with.  The other form fields (prefixed with
+	// "other" in their form-data name) are unchanged.  A bug was
+	// reported with blob uploads failing when the other fields were
+	// empty. This was the MIME POST body that previously failed.
+	{
+		name: "App Engine post",
+		sep:  "00151757727e9583fd04bfbca4c6",
+		in:   "--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherEmpty1\r\n\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherFoo1\r\n\r\nfoo\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherFoo2\r\n\r\nfoo\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherEmpty2\r\n\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherRepeatFoo\r\n\r\nfoo\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherRepeatFoo\r\n\r\nfoo\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherRepeatEmpty\r\n\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherRepeatEmpty\r\n\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=submit\r\n\r\nSubmit\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: message/external-body; charset=ISO-8859-1; blob-key=AHAZQqG84qllx7HUqO_oou5EvdYQNS3Mbbkb0RjjBoM_Kc1UqEN2ygDxWiyCPulIhpHRPx-VbpB6RX4MrsqhWAi_ZxJ48O9P2cTIACbvATHvg7IgbvZytyGMpL7xO1tlIvgwcM47JNfv_tGhy1XwyEUO8oldjPqg5Q\r\nContent-Disposition: form-data; name=file; filename=\"fall.png\"\r\n\r\nContent-Type: image/png\r\nContent-Length: 232303\r\nX-AppEngine-Upload-Creation: 2012-05-10 23:14:02.715173\r\nContent-MD5: MzRjODU1ZDZhZGU1NmRlOWEwZmMwMDdlODBmZTA0NzA=\r\nContent-Disposition: form-data; name=file; filename=\"fall.png\"\r\n\r\n\r\n--00151757727e9583fd04bfbca4c6--",
+		want: []headerBody{
+			formData("otherEmpty1", ""),
+			formData("otherFoo1", "foo"),
+			formData("otherFoo2", "foo"),
+			formData("otherEmpty2", ""),
+			formData("otherRepeatFoo", "foo"),
+			formData("otherRepeatFoo", "foo"),
+			formData("otherRepeatEmpty", ""),
+			formData("otherRepeatEmpty", ""),
+			formData("submit", "Submit"),
+			{textproto.MIMEHeader{
+				"Content-Type":        {"message/external-body; charset=ISO-8859-1; blob-key=AHAZQqG84qllx7HUqO_oou5EvdYQNS3Mbbkb0RjjBoM_Kc1UqEN2ygDxWiyCPulIhpHRPx-VbpB6RX4MrsqhWAi_ZxJ48O9P2cTIACbvATHvg7IgbvZytyGMpL7xO1tlIvgwcM47JNfv_tGhy1XwyEUO8oldjPqg5Q"},
+				"Content-Disposition": {"form-data; name=file; filename=\"fall.png\""},
+			}, "Content-Type: image/png\r\nContent-Length: 232303\r\nX-AppEngine-Upload-Creation: 2012-05-10 23:14:02.715173\r\nContent-MD5: MzRjODU1ZDZhZGU1NmRlOWEwZmMwMDdlODBmZTA0NzA=\r\nContent-Disposition: form-data; name=file; filename=\"fall.png\"\r\n\r\n"},
+		},
+	},
+
+	// Single empty part, ended with --boundary immediately after headers.
+	{
+		name: "single empty part, --boundary",
+		sep:  "abc",
+		in:   "--abc\r\nFoo: bar\r\n\r\n--abc--",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+		},
+	},
+
+	// Single empty part, ended with \r\n--boundary immediately after headers.
+	{
+		name: "single empty part, \r\n--boundary",
+		sep:  "abc",
+		in:   "--abc\r\nFoo: bar\r\n\r\n\r\n--abc--",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+		},
+	},
+
+	// Final part empty.
+	{
+		name: "final part empty",
+		sep:  "abc",
+		in:   "--abc\r\nFoo: bar\r\n\r\n--abc\r\nFoo2: bar2\r\n\r\n--abc--",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+			{textproto.MIMEHeader{"Foo2": {"bar2"}}, ""},
+		},
+	},
+
+	// Final part empty with newlines after final separator.
+	{
+		name: "final part empty then crlf",
+		sep:  "abc",
+		in:   "--abc\r\nFoo: bar\r\n\r\n--abc--\r\n",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+		},
+	},
+
+	// Final part empty with lwsp-chars after final separator.
+	{
+		name: "final part empty then lwsp",
+		sep:  "abc",
+		in:   "--abc\r\nFoo: bar\r\n\r\n--abc-- \t",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+		},
+	},
+
+	// No parts (empty form as submitted by Chrome)
+	{
+		name: "no parts",
+		sep:  "----WebKitFormBoundaryQfEAfzFOiSemeHfA",
+		in:   "------WebKitFormBoundaryQfEAfzFOiSemeHfA--\r\n",
+		want: []headerBody{},
+	},
+
+	// Part containing data starting with the boundary, but with additional suffix.
+	{
+		name: "fake separator as data",
+		sep:  "sep",
+		in:   "--sep\r\nFoo: bar\r\n\r\n--sepFAKE\r\n--sep--",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, "--sepFAKE"},
+		},
+	},
+
+	// Part containing a boundary with whitespace following it.
+	{
+		name: "boundary with whitespace",
+		sep:  "sep",
+		in:   "--sep \r\nFoo: bar\r\n\r\ntext\r\n--sep--",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, "text"},
+		},
+	},
+
+	// With ignored leading line.
+	{
+		name: "leading line",
+		sep:  "MyBoundary",
+		in: strings.Replace(`This is a multi-part message.  This line is ignored.
+--MyBoundary
+foo: bar
+
+
+--MyBoundary--`, "\n", "\r\n", -1),
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+		},
+	},
+
+	roundTripParseTest(),
+}
+
+func TestParse(t *testing.T) {
+Cases:
+	for _, tt := range parseTests {
+		r := NewReader(strings.NewReader(tt.in), tt.sep)
+		got := []headerBody{}
+		for {
+			p, err := r.NextPart()
+			if err == io.EOF {
+				break
+			}
+			if err != nil {
+				t.Errorf("in test %q, NextPart: %v", tt.name, err)
+				continue Cases
+			}
+			pbody, err := ioutil.ReadAll(p)
+			if err != nil {
+				t.Errorf("in test %q, error reading part: %v", tt.name, err)
+				continue Cases
+			}
+			got = append(got, headerBody{p.Header, string(pbody)})
+		}
+		if !reflect.DeepEqual(tt.want, got) {
+			t.Errorf("test %q:\n got: %v\nwant: %v", tt.name, got, tt.want)
+			if len(tt.want) != len(got) {
+				t.Errorf("test %q: got %d parts, want %d", tt.name, len(got), len(tt.want))
+			} else if len(got) > 1 {
+				for pi, wantPart := range tt.want {
+					if !reflect.DeepEqual(wantPart, got[pi]) {
+						t.Errorf("test %q, part %d:\n got: %v\nwant: %v", tt.name, pi, got[pi], wantPart)
+					}
+				}
+			}
+		}
+	}
+}
+
+func roundTripParseTest() parseTest {
+	t := parseTest{
+		name: "round trip",
+		want: []headerBody{
+			formData("empty", ""),
+			formData("lf", "\n"),
+			formData("cr", "\r"),
+			formData("crlf", "\r\n"),
+			formData("foo", "bar"),
+		},
+	}
+	var buf bytes.Buffer
+	w := NewWriter(&buf)
+	for _, p := range t.want {
+		pw, err := w.CreatePart(p.header)
+		if err != nil {
+			panic(err)
+		}
+		_, err = pw.Write([]byte(p.body))
+		if err != nil {
+			panic(err)
+		}
+	}
+	w.Close()
+	t.in = buf.String()
+	t.sep = w.Boundary()
+	return t
+}
diff --git a/third_party/gofrontend/libgo/go/mime/multipart/quotedprintable.go b/third_party/gofrontend/libgo/go/mime/multipart/quotedprintable.go
new file mode 100644
index 0000000..9ff4ee7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/multipart/quotedprintable.go
@@ -0,0 +1,118 @@
+// 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.
+
+// The file define a quoted-printable decoder, as specified in RFC 2045.
+// Deviations:
+// 1. in addition to "=\r\n", "=\n" is also treated as soft line break.
+// 2. it will pass through a '\r' or '\n' not preceded by '=', consistent
+//    with other broken QP encoders & decoders.
+
+package multipart
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+)
+
+type qpReader struct {
+	br   *bufio.Reader
+	rerr error  // last read error
+	line []byte // to be consumed before more of br
+}
+
+func newQuotedPrintableReader(r io.Reader) io.Reader {
+	return &qpReader{
+		br: bufio.NewReader(r),
+	}
+}
+
+func fromHex(b byte) (byte, error) {
+	switch {
+	case b >= '0' && b <= '9':
+		return b - '0', nil
+	case b >= 'A' && b <= 'F':
+		return b - 'A' + 10, nil
+	}
+	return 0, fmt.Errorf("multipart: invalid quoted-printable hex byte 0x%02x", b)
+}
+
+func (q *qpReader) readHexByte(v []byte) (b byte, err error) {
+	if len(v) < 2 {
+		return 0, io.ErrUnexpectedEOF
+	}
+	var hb, lb byte
+	if hb, err = fromHex(v[0]); err != nil {
+		return 0, err
+	}
+	if lb, err = fromHex(v[1]); err != nil {
+		return 0, err
+	}
+	return hb<<4 | lb, nil
+}
+
+func isQPDiscardWhitespace(r rune) bool {
+	switch r {
+	case '\n', '\r', ' ', '\t':
+		return true
+	}
+	return false
+}
+
+var (
+	crlf       = []byte("\r\n")
+	lf         = []byte("\n")
+	softSuffix = []byte("=")
+)
+
+func (q *qpReader) Read(p []byte) (n int, err error) {
+	for len(p) > 0 {
+		if len(q.line) == 0 {
+			if q.rerr != nil {
+				return n, q.rerr
+			}
+			q.line, q.rerr = q.br.ReadSlice('\n')
+
+			// Does the line end in CRLF instead of just LF?
+			hasLF := bytes.HasSuffix(q.line, lf)
+			hasCR := bytes.HasSuffix(q.line, crlf)
+			wholeLine := q.line
+			q.line = bytes.TrimRightFunc(wholeLine, isQPDiscardWhitespace)
+			if bytes.HasSuffix(q.line, softSuffix) {
+				rightStripped := wholeLine[len(q.line):]
+				q.line = q.line[:len(q.line)-1]
+				if !bytes.HasPrefix(rightStripped, lf) && !bytes.HasPrefix(rightStripped, crlf) {
+					q.rerr = fmt.Errorf("multipart: invalid bytes after =: %q", rightStripped)
+				}
+			} else if hasLF {
+				if hasCR {
+					q.line = append(q.line, '\r', '\n')
+				} else {
+					q.line = append(q.line, '\n')
+				}
+			}
+			continue
+		}
+		b := q.line[0]
+
+		switch {
+		case b == '=':
+			b, err = q.readHexByte(q.line[1:])
+			if err != nil {
+				return n, err
+			}
+			q.line = q.line[2:] // 2 of the 3; other 1 is done below
+		case b == '\t' || b == '\r' || b == '\n':
+			break
+		case b < ' ' || b > '~':
+			return n, fmt.Errorf("multipart: invalid unescaped byte 0x%02x in quoted-printable body", b)
+		}
+		p[0] = b
+		p = p[1:]
+		q.line = q.line[1:]
+		n++
+	}
+	return n, nil
+}
diff --git a/third_party/gofrontend/libgo/go/mime/multipart/quotedprintable_test.go b/third_party/gofrontend/libgo/go/mime/multipart/quotedprintable_test.go
new file mode 100644
index 0000000..c4de3eb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/multipart/quotedprintable_test.go
@@ -0,0 +1,204 @@
+// 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 multipart
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"os/exec"
+	"regexp"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+)
+
+func TestQuotedPrintable(t *testing.T) {
+	tests := []struct {
+		in, want string
+		err      interface{}
+	}{
+		{in: "", want: ""},
+		{in: "foo bar", want: "foo bar"},
+		{in: "foo bar=3D", want: "foo bar="},
+		{in: "foo bar=\n", want: "foo bar"},
+		{in: "foo bar\n", want: "foo bar\n"}, // somewhat lax.
+		{in: "foo bar=0", want: "foo bar", err: io.ErrUnexpectedEOF},
+		{in: "foo bar=ab", want: "foo bar", err: "multipart: invalid quoted-printable hex byte 0x61"},
+		{in: "foo bar=0D=0A", want: "foo bar\r\n"},
+		{in: " A B        \r\n C ", want: " A B\r\n C"},
+		{in: " A B =\r\n C ", want: " A B  C"},
+		{in: " A B =\n C ", want: " A B  C"}, // lax. treating LF as CRLF
+		{in: "foo=\nbar", want: "foobar"},
+		{in: "foo\x00bar", want: "foo", err: "multipart: invalid unescaped byte 0x00 in quoted-printable body"},
+		{in: "foo bar\xff", want: "foo bar", err: "multipart: invalid unescaped byte 0xff in quoted-printable body"},
+
+		// Equal sign.
+		{in: "=3D30\n", want: "=30\n"},
+		{in: "=00=FF0=\n", want: "\x00\xff0"},
+
+		// Trailing whitespace
+		{in: "foo  \n", want: "foo\n"},
+		{in: "foo  \n\nfoo =\n\nfoo=20\n\n", want: "foo\n\nfoo \nfoo \n\n"},
+
+		// Tests that we allow bare \n and \r through, despite it being strictly
+		// not permitted per RFC 2045, Section 6.7 Page 22 bullet (4).
+		{in: "foo\nbar", want: "foo\nbar"},
+		{in: "foo\rbar", want: "foo\rbar"},
+		{in: "foo\r\nbar", want: "foo\r\nbar"},
+
+		// Different types of soft line-breaks.
+		{in: "foo=\r\nbar", want: "foobar"},
+		{in: "foo=\nbar", want: "foobar"},
+		{in: "foo=\rbar", want: "foo", err: "multipart: invalid quoted-printable hex byte 0x0d"},
+		{in: "foo=\r\r\r \nbar", want: "foo", err: `multipart: invalid bytes after =: "\r\r\r \n"`},
+
+		// Example from RFC 2045:
+		{in: "Now's the time =\n" + "for all folk to come=\n" + " to the aid of their country.",
+			want: "Now's the time for all folk to come to the aid of their country."},
+	}
+	for _, tt := range tests {
+		var buf bytes.Buffer
+		_, err := io.Copy(&buf, newQuotedPrintableReader(strings.NewReader(tt.in)))
+		if got := buf.String(); got != tt.want {
+			t.Errorf("for %q, got %q; want %q", tt.in, got, tt.want)
+		}
+		switch verr := tt.err.(type) {
+		case nil:
+			if err != nil {
+				t.Errorf("for %q, got unexpected error: %v", tt.in, err)
+			}
+		case string:
+			if got := fmt.Sprint(err); got != verr {
+				t.Errorf("for %q, got error %q; want %q", tt.in, got, verr)
+			}
+		case error:
+			if err != verr {
+				t.Errorf("for %q, got error %q; want %q", tt.in, err, verr)
+			}
+		}
+	}
+
+}
+
+func everySequence(base, alpha string, length int, fn func(string)) {
+	if len(base) == length {
+		fn(base)
+		return
+	}
+	for i := 0; i < len(alpha); i++ {
+		everySequence(base+alpha[i:i+1], alpha, length, fn)
+	}
+}
+
+var useQprint = flag.Bool("qprint", false, "Compare against the 'qprint' program.")
+
+var badSoftRx = regexp.MustCompile(`=([^\r\n]+?\n)|([^\r\n]+$)|(\r$)|(\r[^\n]+\n)|( \r\n)`)
+
+func TestQPExhaustive(t *testing.T) {
+	if *useQprint {
+		_, err := exec.LookPath("qprint")
+		if err != nil {
+			t.Fatalf("Error looking for qprint: %v", err)
+		}
+	}
+
+	var buf bytes.Buffer
+	res := make(map[string]int)
+	everySequence("", "0A \r\n=", 6, func(s string) {
+		if strings.HasSuffix(s, "=") || strings.Contains(s, "==") {
+			return
+		}
+		buf.Reset()
+		_, err := io.Copy(&buf, newQuotedPrintableReader(strings.NewReader(s)))
+		if err != nil {
+			errStr := err.Error()
+			if strings.Contains(errStr, "invalid bytes after =:") {
+				errStr = "invalid bytes after ="
+			}
+			res[errStr]++
+			if strings.Contains(errStr, "invalid quoted-printable hex byte ") {
+				if strings.HasSuffix(errStr, "0x20") && (strings.Contains(s, "=0 ") || strings.Contains(s, "=A ") || strings.Contains(s, "= ")) {
+					return
+				}
+				if strings.HasSuffix(errStr, "0x3d") && (strings.Contains(s, "=0=") || strings.Contains(s, "=A=")) {
+					return
+				}
+				if strings.HasSuffix(errStr, "0x0a") || strings.HasSuffix(errStr, "0x0d") {
+					// bunch of cases; since whitespace at the end of a line before \n is removed.
+					return
+				}
+			}
+			if strings.Contains(errStr, "unexpected EOF") {
+				return
+			}
+			if errStr == "invalid bytes after =" && badSoftRx.MatchString(s) {
+				return
+			}
+			t.Errorf("decode(%q) = %v", s, err)
+			return
+		}
+		if *useQprint {
+			cmd := exec.Command("qprint", "-d")
+			cmd.Stdin = strings.NewReader(s)
+			stderr, err := cmd.StderrPipe()
+			if err != nil {
+				panic(err)
+			}
+			qpres := make(chan interface{}, 2)
+			go func() {
+				br := bufio.NewReader(stderr)
+				s, _ := br.ReadString('\n')
+				if s != "" {
+					qpres <- errors.New(s)
+					if cmd.Process != nil {
+						// It can get stuck on invalid input, like:
+						// echo -n "0000= " | qprint -d
+						cmd.Process.Kill()
+					}
+				}
+			}()
+			go func() {
+				want, err := cmd.Output()
+				if err == nil {
+					qpres <- want
+				}
+			}()
+			select {
+			case got := <-qpres:
+				if want, ok := got.([]byte); ok {
+					if string(want) != buf.String() {
+						t.Errorf("go decode(%q) = %q; qprint = %q", s, want, buf.String())
+					}
+				} else {
+					t.Logf("qprint -d(%q) = %v", s, got)
+				}
+			case <-time.After(5 * time.Second):
+				t.Logf("qprint timeout on %q", s)
+			}
+		}
+		res["OK"]++
+	})
+	var outcomes []string
+	for k, v := range res {
+		outcomes = append(outcomes, fmt.Sprintf("%v: %d", k, v))
+	}
+	sort.Strings(outcomes)
+	got := strings.Join(outcomes, "\n")
+	want := `OK: 21576
+invalid bytes after =: 3397
+multipart: invalid quoted-printable hex byte 0x0a: 1400
+multipart: invalid quoted-printable hex byte 0x0d: 2700
+multipart: invalid quoted-printable hex byte 0x20: 2490
+multipart: invalid quoted-printable hex byte 0x3d: 440
+unexpected EOF: 3122`
+	if got != want {
+		t.Errorf("Got:\n%s\nWant:\n%s", got, want)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/mime/multipart/testdata/nested-mime b/third_party/gofrontend/libgo/go/mime/multipart/testdata/nested-mime
new file mode 100644
index 0000000..71c238e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/multipart/testdata/nested-mime
@@ -0,0 +1,29 @@
+--e89a8ff1c1e83553e304be640612

+Content-Type: multipart/alternative; boundary=e89a8ff1c1e83553e004be640610

+

+--e89a8ff1c1e83553e004be640610

+Content-Type: text/plain; charset=UTF-8

+

+*body*

+

+--e89a8ff1c1e83553e004be640610

+Content-Type: text/html; charset=UTF-8

+

+<b>body</b>

+

+--e89a8ff1c1e83553e004be640610--

+--e89a8ff1c1e83553e304be640612

+Content-Type: image/png; name="x.png"

+Content-Disposition: attachment; 

+	filename="x.png"

+Content-Transfer-Encoding: base64

+X-Attachment-Id: f_h1edgigu0

+

+iVBORw0KGgoAAAANSUhEUgAAAagAAADrCAIAAACza5XhAAAKMWlDQ1BJQ0MgUHJvZmlsZQAASImd

+lndUU9kWh8+9N71QkhCKlNBraFICSA29SJEuKjEJEErAkAAiNkRUcERRkaYIMijggKNDkbEiioUB

+8b2kqeGaj4aTNftesu5mob4pr07ecMywRwLBvDCJOksqlUyldAZD7g9fxIZRWWPMvXRNJROJRBIG

+Y7Vx0mva1HAwYqibdKONXye3dW4iUonhWFJnqK7OaanU1gGkErFYEgaj0cg8wK+zVPh2ziwnHy07

+U8lYTNapezSzOuevRwLB7CFkqQQCwaJDiBQIBIJFhwh8AoFg0SHUqQUCASRJKkwkhMy/JfODWPEJ

+BIJFhwh8AoFg0TFnQqQ55GtPFopcJsN97e1nYtNuIBYeGBgYCmYrmE3jZ05iaGAoMX0xzxkWz6Hv

+yO7WvrlwzA0uLzrD+VkKqViwl9IfTBVNFMyc/x9alloiPPlqhQAAAABJRU5ErkJggg==

+--e89a8ff1c1e83553e304be640612--

diff --git a/third_party/gofrontend/libgo/go/mime/multipart/writer.go b/third_party/gofrontend/libgo/go/mime/multipart/writer.go
new file mode 100644
index 0000000..e13a956
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/multipart/writer.go
@@ -0,0 +1,184 @@
+// 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.
+
+package multipart
+
+import (
+	"bytes"
+	"crypto/rand"
+	"errors"
+	"fmt"
+	"io"
+	"net/textproto"
+	"strings"
+)
+
+// A Writer generates multipart messages.
+type Writer struct {
+	w        io.Writer
+	boundary string
+	lastpart *part
+}
+
+// NewWriter returns a new multipart Writer with a random boundary,
+// writing to w.
+func NewWriter(w io.Writer) *Writer {
+	return &Writer{
+		w:        w,
+		boundary: randomBoundary(),
+	}
+}
+
+// Boundary returns the Writer's boundary.
+func (w *Writer) Boundary() string {
+	return w.boundary
+}
+
+// SetBoundary overrides the Writer's default randomly-generated
+// boundary separator with an explicit value.
+//
+// SetBoundary must be called before any parts are created, may only
+// contain certain ASCII characters, and must be 1-69 bytes long.
+func (w *Writer) SetBoundary(boundary string) error {
+	if w.lastpart != nil {
+		return errors.New("mime: SetBoundary called after write")
+	}
+	// rfc2046#section-5.1.1
+	if len(boundary) < 1 || len(boundary) > 69 {
+		return errors.New("mime: invalid boundary length")
+	}
+	for _, b := range boundary {
+		if 'A' <= b && b <= 'Z' || 'a' <= b && b <= 'z' || '0' <= b && b <= '9' {
+			continue
+		}
+		switch b {
+		case '\'', '(', ')', '+', '_', ',', '-', '.', '/', ':', '=', '?':
+			continue
+		}
+		return errors.New("mime: invalid boundary character")
+	}
+	w.boundary = boundary
+	return nil
+}
+
+// FormDataContentType returns the Content-Type for an HTTP
+// multipart/form-data with this Writer's Boundary.
+func (w *Writer) FormDataContentType() string {
+	return "multipart/form-data; boundary=" + w.boundary
+}
+
+func randomBoundary() string {
+	var buf [30]byte
+	_, err := io.ReadFull(rand.Reader, buf[:])
+	if err != nil {
+		panic(err)
+	}
+	return fmt.Sprintf("%x", buf[:])
+}
+
+// CreatePart creates a new multipart section with the provided
+// header. The body of the part should be written to the returned
+// Writer. After calling CreatePart, any previous part may no longer
+// be written to.
+func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, error) {
+	if w.lastpart != nil {
+		if err := w.lastpart.close(); err != nil {
+			return nil, err
+		}
+	}
+	var b bytes.Buffer
+	if w.lastpart != nil {
+		fmt.Fprintf(&b, "\r\n--%s\r\n", w.boundary)
+	} else {
+		fmt.Fprintf(&b, "--%s\r\n", w.boundary)
+	}
+	// TODO(bradfitz): move this to textproto.MimeHeader.Write(w), have it sort
+	// and clean, like http.Header.Write(w) does.
+	for k, vv := range header {
+		for _, v := range vv {
+			fmt.Fprintf(&b, "%s: %s\r\n", k, v)
+		}
+	}
+	fmt.Fprintf(&b, "\r\n")
+	_, err := io.Copy(w.w, &b)
+	if err != nil {
+		return nil, err
+	}
+	p := &part{
+		mw: w,
+	}
+	w.lastpart = p
+	return p, nil
+}
+
+var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
+
+func escapeQuotes(s string) string {
+	return quoteEscaper.Replace(s)
+}
+
+// CreateFormFile is a convenience wrapper around CreatePart. It creates
+// a new form-data header with the provided field name and file name.
+func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error) {
+	h := make(textproto.MIMEHeader)
+	h.Set("Content-Disposition",
+		fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
+			escapeQuotes(fieldname), escapeQuotes(filename)))
+	h.Set("Content-Type", "application/octet-stream")
+	return w.CreatePart(h)
+}
+
+// CreateFormField calls CreatePart with a header using the
+// given field name.
+func (w *Writer) CreateFormField(fieldname string) (io.Writer, error) {
+	h := make(textproto.MIMEHeader)
+	h.Set("Content-Disposition",
+		fmt.Sprintf(`form-data; name="%s"`, escapeQuotes(fieldname)))
+	return w.CreatePart(h)
+}
+
+// WriteField calls CreateFormField and then writes the given value.
+func (w *Writer) WriteField(fieldname, value string) error {
+	p, err := w.CreateFormField(fieldname)
+	if err != nil {
+		return err
+	}
+	_, err = p.Write([]byte(value))
+	return err
+}
+
+// Close finishes the multipart message and writes the trailing
+// boundary end line to the output.
+func (w *Writer) Close() error {
+	if w.lastpart != nil {
+		if err := w.lastpart.close(); err != nil {
+			return err
+		}
+		w.lastpart = nil
+	}
+	_, err := fmt.Fprintf(w.w, "\r\n--%s--\r\n", w.boundary)
+	return err
+}
+
+type part struct {
+	mw     *Writer
+	closed bool
+	we     error // last error that occurred writing
+}
+
+func (p *part) close() error {
+	p.closed = true
+	return p.we
+}
+
+func (p *part) Write(d []byte) (n int, err error) {
+	if p.closed {
+		return 0, errors.New("multipart: can't write to finished part")
+	}
+	n, err = p.mw.w.Write(d)
+	if err != nil {
+		p.we = err
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/mime/multipart/writer_test.go b/third_party/gofrontend/libgo/go/mime/multipart/writer_test.go
new file mode 100644
index 0000000..52d68bc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/multipart/writer_test.go
@@ -0,0 +1,113 @@
+// 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.
+
+package multipart
+
+import (
+	"bytes"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+func TestWriter(t *testing.T) {
+	fileContents := []byte("my file contents")
+
+	var b bytes.Buffer
+	w := NewWriter(&b)
+	{
+		part, err := w.CreateFormFile("myfile", "my-file.txt")
+		if err != nil {
+			t.Fatalf("CreateFormFile: %v", err)
+		}
+		part.Write(fileContents)
+		err = w.WriteField("key", "val")
+		if err != nil {
+			t.Fatalf("WriteField: %v", err)
+		}
+		part.Write([]byte("val"))
+		err = w.Close()
+		if err != nil {
+			t.Fatalf("Close: %v", err)
+		}
+		s := b.String()
+		if len(s) == 0 {
+			t.Fatal("String: unexpected empty result")
+		}
+		if s[0] == '\r' || s[0] == '\n' {
+			t.Fatal("String: unexpected newline")
+		}
+	}
+
+	r := NewReader(&b, w.Boundary())
+
+	part, err := r.NextPart()
+	if err != nil {
+		t.Fatalf("part 1: %v", err)
+	}
+	if g, e := part.FormName(), "myfile"; g != e {
+		t.Errorf("part 1: want form name %q, got %q", e, g)
+	}
+	slurp, err := ioutil.ReadAll(part)
+	if err != nil {
+		t.Fatalf("part 1: ReadAll: %v", err)
+	}
+	if e, g := string(fileContents), string(slurp); e != g {
+		t.Errorf("part 1: want contents %q, got %q", e, g)
+	}
+
+	part, err = r.NextPart()
+	if err != nil {
+		t.Fatalf("part 2: %v", err)
+	}
+	if g, e := part.FormName(), "key"; g != e {
+		t.Errorf("part 2: want form name %q, got %q", e, g)
+	}
+	slurp, err = ioutil.ReadAll(part)
+	if err != nil {
+		t.Fatalf("part 2: ReadAll: %v", err)
+	}
+	if e, g := "val", string(slurp); e != g {
+		t.Errorf("part 2: want contents %q, got %q", e, g)
+	}
+
+	part, err = r.NextPart()
+	if part != nil || err == nil {
+		t.Fatalf("expected end of parts; got %v, %v", part, err)
+	}
+}
+
+func TestWriterSetBoundary(t *testing.T) {
+	var b bytes.Buffer
+	w := NewWriter(&b)
+	tests := []struct {
+		b  string
+		ok bool
+	}{
+		{"abc", true},
+		{"", false},
+		{"ungültig", false},
+		{"!", false},
+		{strings.Repeat("x", 69), true},
+		{strings.Repeat("x", 70), false},
+		{"bad!ascii!", false},
+		{"my-separator", true},
+	}
+	for i, tt := range tests {
+		err := w.SetBoundary(tt.b)
+		got := err == nil
+		if got != tt.ok {
+			t.Errorf("%d. boundary %q = %v (%v); want %v", i, tt.b, got, err, tt.ok)
+		} else if tt.ok {
+			got := w.Boundary()
+			if got != tt.b {
+				t.Errorf("boundary = %q; want %q", got, tt.b)
+			}
+		}
+	}
+	w.Close()
+	if got := b.String(); !strings.Contains(got, "\r\n--my-separator--\r\n") {
+		t.Errorf("expected my-separator in output. got: %q", got)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/mime/test.types b/third_party/gofrontend/libgo/go/mime/test.types
new file mode 100644
index 0000000..9b040ed
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/test.types
@@ -0,0 +1,8 @@
+# Copyright 2010 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.
+
+
+ # mime package test
+application/test	t1	# Simple test
+text/test		t2	# Text test
diff --git a/third_party/gofrontend/libgo/go/mime/testdata/test.types b/third_party/gofrontend/libgo/go/mime/testdata/test.types
new file mode 100644
index 0000000..9b040ed
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/testdata/test.types
@@ -0,0 +1,8 @@
+# Copyright 2010 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.
+
+
+ # mime package test
+application/test	t1	# Simple test
+text/test		t2	# Text test
diff --git a/third_party/gofrontend/libgo/go/mime/type.go b/third_party/gofrontend/libgo/go/mime/type.go
new file mode 100644
index 0000000..00cff26
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/type.go
@@ -0,0 +1,77 @@
+// Copyright 2010 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 mime implements parts of the MIME spec.
+package mime
+
+import (
+	"fmt"
+	"strings"
+	"sync"
+)
+
+var mimeTypes = map[string]string{
+	".css":  "text/css; charset=utf-8",
+	".gif":  "image/gif",
+	".htm":  "text/html; charset=utf-8",
+	".html": "text/html; charset=utf-8",
+	".jpg":  "image/jpeg",
+	".js":   "application/x-javascript",
+	".pdf":  "application/pdf",
+	".png":  "image/png",
+	".xml":  "text/xml; charset=utf-8",
+}
+
+var mimeLock sync.RWMutex
+
+var once sync.Once
+
+// TypeByExtension returns the MIME type associated with the file extension ext.
+// The extension ext should begin with a leading dot, as in ".html".
+// When ext has no associated type, TypeByExtension returns "".
+//
+// The built-in table is small but on unix it is augmented by the local
+// system's mime.types file(s) if available under one or more of these
+// names:
+//
+//   /etc/mime.types
+//   /etc/apache2/mime.types
+//   /etc/apache/mime.types
+//
+// Windows system mime types are extracted from registry.
+//
+// Text types have the charset parameter set to "utf-8" by default.
+func TypeByExtension(ext string) string {
+	once.Do(initMime)
+	mimeLock.RLock()
+	typename := mimeTypes[ext]
+	mimeLock.RUnlock()
+	return typename
+}
+
+// AddExtensionType sets the MIME type associated with
+// the extension ext to typ.  The extension should begin with
+// a leading dot, as in ".html".
+func AddExtensionType(ext, typ string) error {
+	if ext == "" || ext[0] != '.' {
+		return fmt.Errorf(`mime: extension "%s" misses dot`, ext)
+	}
+	once.Do(initMime)
+	return setExtensionType(ext, typ)
+}
+
+func setExtensionType(extension, mimeType string) error {
+	_, param, err := ParseMediaType(mimeType)
+	if err != nil {
+		return err
+	}
+	if strings.HasPrefix(mimeType, "text/") && param["charset"] == "" {
+		param["charset"] = "utf-8"
+		mimeType = FormatMediaType(mimeType, param)
+	}
+	mimeLock.Lock()
+	mimeTypes[extension] = mimeType
+	mimeLock.Unlock()
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/mime/type_plan9.go b/third_party/gofrontend/libgo/go/mime/type_plan9.go
new file mode 100644
index 0000000..b8f0511
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/type_plan9.go
@@ -0,0 +1,53 @@
+// Copyright 2013 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 mime
+
+import (
+	"bufio"
+	"os"
+	"strings"
+)
+
+var typeFiles = []string{
+	"/sys/lib/mimetypes",
+}
+
+func loadMimeFile(filename string) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return
+	}
+	defer f.Close()
+
+	scanner := bufio.NewScanner(f)
+	for scanner.Scan() {
+		fields := strings.Fields(scanner.Text())
+		if len(fields) <= 2 || fields[0][0] != '.' {
+			continue
+		}
+		if fields[1] == "-" || fields[2] == "-" {
+			continue
+		}
+		setExtensionType(fields[0], fields[1]+"/"+fields[2])
+	}
+	if err := scanner.Err(); err != nil {
+		panic(err)
+	}
+}
+
+func initMime() {
+	for _, filename := range typeFiles {
+		loadMimeFile(filename)
+	}
+}
+
+func initMimeForTests() map[string]string {
+	typeFiles = []string{"testdata/test.types.plan9"}
+	return map[string]string{
+		".t1":  "application/test",
+		".t2":  "text/test; charset=utf-8",
+		".png": "image/png",
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/mime/type_test.go b/third_party/gofrontend/libgo/go/mime/type_test.go
new file mode 100644
index 0000000..07e1cd5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/type_test.go
@@ -0,0 +1,29 @@
+// Copyright 2010 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 mime
+
+import "testing"
+
+var typeTests = initMimeForTests()
+
+func TestTypeByExtension(t *testing.T) {
+	for ext, want := range typeTests {
+		val := TypeByExtension(ext)
+		if val != want {
+			t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want)
+		}
+
+	}
+}
+
+func TestCustomExtension(t *testing.T) {
+	custom := "text/xml; charset=iso-8859-1"
+	if error := AddExtensionType(".xml", custom); error != nil {
+		t.Fatalf("error %s for AddExtension(%s)", error, custom)
+	}
+	if registered := TypeByExtension(".xml"); registered != custom {
+		t.Fatalf("registered %s instead of %s", registered, custom)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/mime/type_unix.go b/third_party/gofrontend/libgo/go/mime/type_unix.go
new file mode 100644
index 0000000..1d39431
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/type_unix.go
@@ -0,0 +1,60 @@
+// Copyright 2010 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package mime
+
+import (
+	"bufio"
+	"os"
+	"strings"
+)
+
+var typeFiles = []string{
+	"/etc/mime.types",
+	"/etc/apache2/mime.types",
+	"/etc/apache/mime.types",
+}
+
+func loadMimeFile(filename string) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return
+	}
+	defer f.Close()
+
+	scanner := bufio.NewScanner(f)
+	for scanner.Scan() {
+		fields := strings.Fields(scanner.Text())
+		if len(fields) <= 1 || fields[0][0] == '#' {
+			continue
+		}
+		mimeType := fields[0]
+		for _, ext := range fields[1:] {
+			if ext[0] == '#' {
+				break
+			}
+			setExtensionType("."+ext, mimeType)
+		}
+	}
+	if err := scanner.Err(); err != nil {
+		panic(err)
+	}
+}
+
+func initMime() {
+	for _, filename := range typeFiles {
+		loadMimeFile(filename)
+	}
+}
+
+func initMimeForTests() map[string]string {
+	typeFiles = []string{"testdata/test.types"}
+	return map[string]string{
+		".t1":  "application/test",
+		".t2":  "text/test; charset=utf-8",
+		".png": "image/png",
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/mime/type_windows.go b/third_party/gofrontend/libgo/go/mime/type_windows.go
new file mode 100644
index 0000000..180f948
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/mime/type_windows.go
@@ -0,0 +1,63 @@
+// Copyright 2010 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 mime
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+func initMime() {
+	var root syscall.Handle
+	rootpathp, _ := syscall.UTF16PtrFromString(`\`)
+	if syscall.RegOpenKeyEx(syscall.HKEY_CLASSES_ROOT, rootpathp,
+		0, syscall.KEY_READ, &root) != nil {
+		return
+	}
+	defer syscall.RegCloseKey(root)
+	var count uint32
+	if syscall.RegQueryInfoKey(root, nil, nil, nil, &count, nil, nil, nil, nil, nil, nil, nil) != nil {
+		return
+	}
+	var buf [1 << 10]uint16
+	for i := uint32(0); i < count; i++ {
+		n := uint32(len(buf))
+		if syscall.RegEnumKeyEx(root, i, &buf[0], &n, nil, nil, nil, nil) != nil {
+			continue
+		}
+		ext := syscall.UTF16ToString(buf[:])
+		if len(ext) < 2 || ext[0] != '.' { // looking for extensions only
+			continue
+		}
+		var h syscall.Handle
+		extpathp, _ := syscall.UTF16PtrFromString(`\` + ext)
+		if syscall.RegOpenKeyEx(
+			syscall.HKEY_CLASSES_ROOT, extpathp,
+			0, syscall.KEY_READ, &h) != nil {
+			continue
+		}
+		var typ uint32
+		n = uint32(len(buf) * 2) // api expects array of bytes, not uint16
+		contenttypep, _ := syscall.UTF16PtrFromString("Content Type")
+		if syscall.RegQueryValueEx(
+			h, contenttypep,
+			nil, &typ, (*byte)(unsafe.Pointer(&buf[0])), &n) != nil {
+			syscall.RegCloseKey(h)
+			continue
+		}
+		syscall.RegCloseKey(h)
+		if typ != syscall.REG_SZ { // null terminated strings only
+			continue
+		}
+		mimeType := syscall.UTF16ToString(buf[:])
+		setExtensionType(ext, mimeType)
+	}
+}
+
+func initMimeForTests() map[string]string {
+	return map[string]string{
+		".png": "image/png",
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/cgo_bsd.go b/third_party/gofrontend/libgo/go/net/cgo_bsd.go
new file mode 100644
index 0000000..ce46f2e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/cgo_bsd.go
@@ -0,0 +1,18 @@
+// 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.
+
+// +build !netgo
+// +build darwin dragonfly freebsd solaris
+
+package net
+
+/*
+#include <netdb.h>
+*/
+
+import "syscall"
+
+func cgoAddrInfoFlags() int {
+	return (syscall.AI_CANONNAME | syscall.AI_V4MAPPED | syscall.AI_ALL) & syscall.AI_MASK
+}
diff --git a/third_party/gofrontend/libgo/go/net/cgo_linux.go b/third_party/gofrontend/libgo/go/net/cgo_linux.go
new file mode 100644
index 0000000..77522f9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/cgo_linux.go
@@ -0,0 +1,23 @@
+// 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.
+
+// +build cgo,!netgo
+
+package net
+
+/*
+#include <netdb.h>
+*/
+
+import "syscall"
+
+func cgoAddrInfoFlags() int {
+	// NOTE(rsc): In theory there are approximately balanced
+	// arguments for and against including AI_ADDRCONFIG
+	// in the flags (it includes IPv4 results only on IPv4 systems,
+	// and similarly for IPv6), but in practice setting it causes
+	// getaddrinfo to return the wrong canonical name on Linux.
+	// So definitely leave it out.
+	return syscall.AI_CANONNAME | syscall.AI_V4MAPPED | syscall.AI_ALL
+}
diff --git a/third_party/gofrontend/libgo/go/net/cgo_netbsd.go b/third_party/gofrontend/libgo/go/net/cgo_netbsd.go
new file mode 100644
index 0000000..3c13103
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/cgo_netbsd.go
@@ -0,0 +1,16 @@
+// 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.
+
+// +build cgo,!netgo
+
+package net
+
+/*
+#include <netdb.h>
+*/
+import "C"
+
+func cgoAddrInfoFlags() int {
+	return C.AI_CANONNAME
+}
diff --git a/third_party/gofrontend/libgo/go/net/cgo_openbsd.go b/third_party/gofrontend/libgo/go/net/cgo_openbsd.go
new file mode 100644
index 0000000..09c5ad2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/cgo_openbsd.go
@@ -0,0 +1,16 @@
+// 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.
+
+// +build cgo,!netgo
+
+package net
+
+/*
+#include <netdb.h>
+*/
+import "C"
+
+func cgoAddrInfoFlags() C.int {
+	return C.AI_CANONNAME
+}
diff --git a/third_party/gofrontend/libgo/go/net/cgo_stub.go b/third_party/gofrontend/libgo/go/net/cgo_stub.go
new file mode 100644
index 0000000..f533c14
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/cgo_stub.go
@@ -0,0 +1,25 @@
+// 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.
+
+// +build !cgo netgo
+
+// Stub cgo routines for systems that do not use cgo to do network lookups.
+
+package net
+
+func cgoLookupHost(name string) (addrs []string, err error, completed bool) {
+	return nil, nil, false
+}
+
+func cgoLookupPort(network, service string) (port int, err error, completed bool) {
+	return 0, nil, false
+}
+
+func cgoLookupIP(name string) (addrs []IP, err error, completed bool) {
+	return nil, nil, false
+}
+
+func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
+	return "", nil, false
+}
diff --git a/third_party/gofrontend/libgo/go/net/cgo_unix.go b/third_party/gofrontend/libgo/go/net/cgo_unix.go
new file mode 100644
index 0000000..0abf434
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/cgo_unix.go
@@ -0,0 +1,187 @@
+// 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.
+
+// +build !netgo
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package net
+
+/*
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+*/
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+//extern getaddrinfo
+func libc_getaddrinfo(node *byte, service *byte, hints *syscall.Addrinfo, res **syscall.Addrinfo) int
+
+//extern freeaddrinfo
+func libc_freeaddrinfo(res *syscall.Addrinfo)
+
+//extern gai_strerror
+func libc_gai_strerror(errcode int) *byte
+
+// bytePtrToString takes a NUL-terminated array of bytes and convert
+// it to a Go string.
+func bytePtrToString(p *byte) string {
+	a := (*[10000]byte)(unsafe.Pointer(p))
+	i := 0
+	for a[i] != 0 {
+		i++
+	}
+	return string(a[:i])
+}
+
+func cgoLookupHost(name string) (addrs []string, err error, completed bool) {
+	ip, err, completed := cgoLookupIP(name)
+	for _, p := range ip {
+		addrs = append(addrs, p.String())
+	}
+	return
+}
+
+func cgoLookupPort(net, service string) (port int, err error, completed bool) {
+	acquireThread()
+	defer releaseThread()
+
+	var res *syscall.Addrinfo
+	var hints syscall.Addrinfo
+
+	switch net {
+	case "":
+		// no hints
+	case "tcp", "tcp4", "tcp6":
+		hints.Ai_socktype = syscall.SOCK_STREAM
+		hints.Ai_protocol = syscall.IPPROTO_TCP
+	case "udp", "udp4", "udp6":
+		hints.Ai_socktype = syscall.SOCK_DGRAM
+		hints.Ai_protocol = syscall.IPPROTO_UDP
+	default:
+		return 0, UnknownNetworkError(net), true
+	}
+	if len(net) >= 4 {
+		switch net[3] {
+		case '4':
+			hints.Ai_family = syscall.AF_INET
+		case '6':
+			hints.Ai_family = syscall.AF_INET6
+		}
+	}
+
+	s := syscall.StringBytePtr(service)
+	syscall.Entersyscall()
+	gerrno := libc_getaddrinfo(nil, s, &hints, &res)
+	syscall.Exitsyscall()
+	if gerrno == 0 {
+		defer libc_freeaddrinfo(res)
+		for r := res; r != nil; r = r.Ai_next {
+			switch r.Ai_family {
+			default:
+				continue
+			case syscall.AF_INET:
+				sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.Ai_addr))
+				p := (*[2]byte)(unsafe.Pointer(&sa.Port))
+				return int(p[0])<<8 | int(p[1]), nil, true
+			case syscall.AF_INET6:
+				sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.Ai_addr))
+				p := (*[2]byte)(unsafe.Pointer(&sa.Port))
+				return int(p[0])<<8 | int(p[1]), nil, true
+			}
+		}
+	}
+	return 0, &AddrError{"unknown port", net + "/" + service}, true
+}
+
+func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, completed bool) {
+	acquireThread()
+	defer releaseThread()
+
+	var res *syscall.Addrinfo
+	var hints syscall.Addrinfo
+
+	hints.Ai_flags = int32(cgoAddrInfoFlags())
+	hints.Ai_socktype = syscall.SOCK_STREAM
+
+	h := syscall.StringBytePtr(name)
+	syscall.Entersyscall()
+	gerrno := libc_getaddrinfo(h, nil, &hints, &res)
+	syscall.Exitsyscall()
+	if gerrno != 0 {
+		var str string
+		if gerrno == syscall.EAI_NONAME {
+			str = noSuchHost
+		} else if gerrno == syscall.EAI_SYSTEM {
+			errno := syscall.GetErrno()
+			if errno == 0 {
+				// err should not be nil, but sometimes getaddrinfo returns
+				// gerrno == C.EAI_SYSTEM with err == nil on Linux.
+				// The report claims that it happens when we have too many
+				// open files, so use syscall.EMFILE (too many open files in system).
+				// Most system calls would return ENFILE (too many open files),
+				// so at the least EMFILE should be easy to recognize if this
+				// comes up again. golang.org/issue/6232.
+				errno = syscall.EMFILE
+			}
+			str = errno.Error()
+		} else {
+			str = bytePtrToString(libc_gai_strerror(gerrno))
+		}
+		return nil, "", &DNSError{Err: str, Name: name}, true
+	}
+	defer libc_freeaddrinfo(res)
+	if res != nil {
+		cname = bytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
+		if cname == "" {
+			cname = name
+		}
+		if len(cname) > 0 && cname[len(cname)-1] != '.' {
+			cname += "."
+		}
+	}
+	for r := res; r != nil; r = r.Ai_next {
+		// We only asked for SOCK_STREAM, but check anyhow.
+		if r.Ai_socktype != syscall.SOCK_STREAM {
+			continue
+		}
+		switch r.Ai_family {
+		default:
+			continue
+		case syscall.AF_INET:
+			sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.Ai_addr))
+			addrs = append(addrs, copyIP(sa.Addr[:]))
+		case syscall.AF_INET6:
+			sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.Ai_addr))
+			addrs = append(addrs, copyIP(sa.Addr[:]))
+		}
+	}
+	return addrs, cname, nil, true
+}
+
+func cgoLookupIP(name string) (addrs []IP, err error, completed bool) {
+	addrs, _, err, completed = cgoLookupIPCNAME(name)
+	return
+}
+
+func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
+	_, cname, err, completed = cgoLookupIPCNAME(name)
+	return
+}
+
+func copyIP(x IP) IP {
+	if len(x) < 16 {
+		return x.To16()
+	}
+	y := make(IP, len(x))
+	copy(y, x)
+	return y
+}
diff --git a/third_party/gofrontend/libgo/go/net/cgo_unix_test.go b/third_party/gofrontend/libgo/go/net/cgo_unix_test.go
new file mode 100644
index 0000000..33566ce
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/cgo_unix_test.go
@@ -0,0 +1,24 @@
+// Copyright 2013 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.
+
+// +build cgo,!netgo
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package net
+
+import "testing"
+
+func TestCgoLookupIP(t *testing.T) {
+	host := "localhost"
+	_, err, ok := cgoLookupIP(host)
+	if !ok {
+		t.Errorf("cgoLookupIP must not be a placeholder")
+	}
+	if err != nil {
+		t.Errorf("cgoLookupIP failed: %v", err)
+	}
+	if _, err := goLookupIP(host); err != nil {
+		t.Errorf("goLookupIP failed: %v", err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/conn_test.go b/third_party/gofrontend/libgo/go/net/conn_test.go
new file mode 100644
index 0000000..37bb4e2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/conn_test.go
@@ -0,0 +1,124 @@
+// 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.
+
+// This file implements API tests across platforms and will never have a build
+// tag.
+
+package net
+
+import (
+	"os"
+	"runtime"
+	"testing"
+	"time"
+)
+
+var connTests = []struct {
+	net  string
+	addr string
+}{
+	{"tcp", "127.0.0.1:0"},
+	{"unix", testUnixAddr()},
+	{"unixpacket", testUnixAddr()},
+}
+
+// someTimeout is used just to test that net.Conn implementations
+// don't explode when their SetFooDeadline methods are called.
+// It isn't actually used for testing timeouts.
+const someTimeout = 10 * time.Second
+
+func TestConnAndListener(t *testing.T) {
+	for _, tt := range connTests {
+		switch tt.net {
+		case "unix":
+			switch runtime.GOOS {
+			case "nacl", "plan9", "windows":
+				continue
+			}
+		case "unixpacket":
+			switch runtime.GOOS {
+			case "darwin", "nacl", "openbsd", "plan9", "windows":
+				continue
+			case "freebsd": // FreeBSD 8 doesn't support unixpacket
+				continue
+			}
+		}
+
+		ln, err := Listen(tt.net, tt.addr)
+		if err != nil {
+			t.Fatalf("Listen failed: %v", err)
+		}
+		defer func(ln Listener, net, addr string) {
+			ln.Close()
+			switch net {
+			case "unix", "unixpacket":
+				os.Remove(addr)
+			}
+		}(ln, tt.net, tt.addr)
+		if ln.Addr().Network() != tt.net {
+			t.Fatalf("got %v; expected %v", ln.Addr().Network(), tt.net)
+		}
+
+		done := make(chan int)
+		go transponder(t, ln, done)
+
+		c, err := Dial(tt.net, ln.Addr().String())
+		if err != nil {
+			t.Fatalf("Dial failed: %v", err)
+		}
+		defer c.Close()
+		if c.LocalAddr().Network() != tt.net || c.LocalAddr().Network() != tt.net {
+			t.Fatalf("got %v->%v; expected %v->%v", c.LocalAddr().Network(), c.RemoteAddr().Network(), tt.net, tt.net)
+		}
+		c.SetDeadline(time.Now().Add(someTimeout))
+		c.SetReadDeadline(time.Now().Add(someTimeout))
+		c.SetWriteDeadline(time.Now().Add(someTimeout))
+
+		if _, err := c.Write([]byte("CONN TEST")); err != nil {
+			t.Fatalf("Conn.Write failed: %v", err)
+		}
+		rb := make([]byte, 128)
+		if _, err := c.Read(rb); err != nil {
+			t.Fatalf("Conn.Read failed: %v", err)
+		}
+
+		<-done
+	}
+}
+
+func transponder(t *testing.T, ln Listener, done chan<- int) {
+	defer func() { done <- 1 }()
+
+	switch ln := ln.(type) {
+	case *TCPListener:
+		ln.SetDeadline(time.Now().Add(someTimeout))
+	case *UnixListener:
+		ln.SetDeadline(time.Now().Add(someTimeout))
+	}
+	c, err := ln.Accept()
+	if err != nil {
+		t.Errorf("Listener.Accept failed: %v", err)
+		return
+	}
+	defer c.Close()
+	network := ln.Addr().Network()
+	if c.LocalAddr().Network() != network || c.LocalAddr().Network() != network {
+		t.Errorf("got %v->%v; expected %v->%v", c.LocalAddr().Network(), c.RemoteAddr().Network(), network, network)
+		return
+	}
+	c.SetDeadline(time.Now().Add(someTimeout))
+	c.SetReadDeadline(time.Now().Add(someTimeout))
+	c.SetWriteDeadline(time.Now().Add(someTimeout))
+
+	b := make([]byte, 128)
+	n, err := c.Read(b)
+	if err != nil {
+		t.Errorf("Conn.Read failed: %v", err)
+		return
+	}
+	if _, err := c.Write(b[:n]); err != nil {
+		t.Errorf("Conn.Write failed: %v", err)
+		return
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/dial.go b/third_party/gofrontend/libgo/go/net/dial.go
new file mode 100644
index 0000000..93569c2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dial.go
@@ -0,0 +1,305 @@
+// Copyright 2010 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 net
+
+import (
+	"errors"
+	"time"
+)
+
+// A Dialer contains options for connecting to an address.
+//
+// The zero value for each field is equivalent to dialing
+// without that option. Dialing with the zero value of Dialer
+// is therefore equivalent to just calling the Dial function.
+type Dialer struct {
+	// Timeout is the maximum amount of time a dial will wait for
+	// a connect to complete. If Deadline is also set, it may fail
+	// earlier.
+	//
+	// The default is no timeout.
+	//
+	// With or without a timeout, the operating system may impose
+	// its own earlier timeout. For instance, TCP timeouts are
+	// often around 3 minutes.
+	Timeout time.Duration
+
+	// Deadline is the absolute point in time after which dials
+	// will fail. If Timeout is set, it may fail earlier.
+	// Zero means no deadline, or dependent on the operating system
+	// as with the Timeout option.
+	Deadline time.Time
+
+	// LocalAddr is the local address to use when dialing an
+	// address. The address must be of a compatible type for the
+	// network being dialed.
+	// If nil, a local address is automatically chosen.
+	LocalAddr Addr
+
+	// DualStack allows a single dial to attempt to establish
+	// multiple IPv4 and IPv6 connections and to return the first
+	// established connection when the network is "tcp" and the
+	// destination is a host name that has multiple address family
+	// DNS records.
+	DualStack bool
+
+	// KeepAlive specifies the keep-alive period for an active
+	// network connection.
+	// If zero, keep-alives are not enabled. Network protocols
+	// that do not support keep-alives ignore this field.
+	KeepAlive time.Duration
+}
+
+// Return either now+Timeout or Deadline, whichever comes first.
+// Or zero, if neither is set.
+func (d *Dialer) deadline() time.Time {
+	if d.Timeout == 0 {
+		return d.Deadline
+	}
+	timeoutDeadline := time.Now().Add(d.Timeout)
+	if d.Deadline.IsZero() || timeoutDeadline.Before(d.Deadline) {
+		return timeoutDeadline
+	} else {
+		return d.Deadline
+	}
+}
+
+func parseNetwork(net string) (afnet string, proto int, err error) {
+	i := last(net, ':')
+	if i < 0 { // no colon
+		switch net {
+		case "tcp", "tcp4", "tcp6":
+		case "udp", "udp4", "udp6":
+		case "ip", "ip4", "ip6":
+		case "unix", "unixgram", "unixpacket":
+		default:
+			return "", 0, UnknownNetworkError(net)
+		}
+		return net, 0, nil
+	}
+	afnet = net[:i]
+	switch afnet {
+	case "ip", "ip4", "ip6":
+		protostr := net[i+1:]
+		proto, i, ok := dtoi(protostr, 0)
+		if !ok || i != len(protostr) {
+			proto, err = lookupProtocol(protostr)
+			if err != nil {
+				return "", 0, err
+			}
+		}
+		return afnet, proto, nil
+	}
+	return "", 0, UnknownNetworkError(net)
+}
+
+func resolveAddr(op, net, addr string, deadline time.Time) (netaddr, error) {
+	afnet, _, err := parseNetwork(net)
+	if err != nil {
+		return nil, err
+	}
+	if op == "dial" && addr == "" {
+		return nil, errMissingAddress
+	}
+	switch afnet {
+	case "unix", "unixgram", "unixpacket":
+		return ResolveUnixAddr(afnet, addr)
+	}
+	return resolveInternetAddr(afnet, addr, deadline)
+}
+
+// Dial connects to the address on the named network.
+//
+// Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
+// "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
+// (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and
+// "unixpacket".
+//
+// For TCP and UDP networks, addresses have the form host:port.
+// If host is a literal IPv6 address or host name, it must be enclosed
+// in square brackets as in "[::1]:80", "[ipv6-host]:http" or
+// "[ipv6-host%zone]:80".
+// The functions JoinHostPort and SplitHostPort manipulate addresses
+// in this form.
+//
+// Examples:
+//	Dial("tcp", "12.34.56.78:80")
+//	Dial("tcp", "google.com:http")
+//	Dial("tcp", "[2001:db8::1]:http")
+//	Dial("tcp", "[fe80::1%lo0]:80")
+//
+// For IP networks, the network must be "ip", "ip4" or "ip6" followed
+// by a colon and a protocol number or name and the addr must be a
+// literal IP address.
+//
+// Examples:
+//	Dial("ip4:1", "127.0.0.1")
+//	Dial("ip6:ospf", "::1")
+//
+// For Unix networks, the address must be a file system path.
+func Dial(network, address string) (Conn, error) {
+	var d Dialer
+	return d.Dial(network, address)
+}
+
+// DialTimeout acts like Dial but takes a timeout.
+// The timeout includes name resolution, if required.
+func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {
+	d := Dialer{Timeout: timeout}
+	return d.Dial(network, address)
+}
+
+// Dial connects to the address on the named network.
+//
+// See func Dial for a description of the network and address
+// parameters.
+func (d *Dialer) Dial(network, address string) (Conn, error) {
+	ra, err := resolveAddr("dial", network, address, d.deadline())
+	if err != nil {
+		return nil, &OpError{Op: "dial", Net: network, Addr: nil, Err: err}
+	}
+	dialer := func(deadline time.Time) (Conn, error) {
+		return dialSingle(network, address, d.LocalAddr, ra.toAddr(), deadline)
+	}
+	if ras, ok := ra.(addrList); ok && d.DualStack && network == "tcp" {
+		dialer = func(deadline time.Time) (Conn, error) {
+			return dialMulti(network, address, d.LocalAddr, ras, deadline)
+		}
+	}
+	c, err := dial(network, ra.toAddr(), dialer, d.deadline())
+	if d.KeepAlive > 0 && err == nil {
+		if tc, ok := c.(*TCPConn); ok {
+			tc.SetKeepAlive(true)
+			tc.SetKeepAlivePeriod(d.KeepAlive)
+			testHookSetKeepAlive()
+		}
+	}
+	return c, err
+}
+
+var testHookSetKeepAlive = func() {} // changed by dial_test.go
+
+// dialMulti attempts to establish connections to each destination of
+// the list of addresses. It will return the first established
+// connection and close the other connections. Otherwise it returns
+// error on the last attempt.
+func dialMulti(net, addr string, la Addr, ras addrList, deadline time.Time) (Conn, error) {
+	type racer struct {
+		Conn
+		error
+	}
+	// Sig controls the flow of dial results on lane. It passes a
+	// token to the next racer and also indicates the end of flow
+	// by using closed channel.
+	sig := make(chan bool, 1)
+	lane := make(chan racer, 1)
+	for _, ra := range ras {
+		go func(ra Addr) {
+			c, err := dialSingle(net, addr, la, ra, deadline)
+			if _, ok := <-sig; ok {
+				lane <- racer{c, err}
+			} else if err == nil {
+				// We have to return the resources
+				// that belong to the other
+				// connections here for avoiding
+				// unnecessary resource starvation.
+				c.Close()
+			}
+		}(ra.toAddr())
+	}
+	defer close(sig)
+	lastErr := errTimeout
+	nracers := len(ras)
+	for nracers > 0 {
+		sig <- true
+		select {
+		case racer := <-lane:
+			if racer.error == nil {
+				return racer.Conn, nil
+			}
+			lastErr = racer.error
+			nracers--
+		}
+	}
+	return nil, lastErr
+}
+
+// dialSingle attempts to establish and returns a single connection to
+// the destination address.
+func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
+	if la != nil && la.Network() != ra.Network() {
+		return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
+	}
+	switch ra := ra.(type) {
+	case *TCPAddr:
+		la, _ := la.(*TCPAddr)
+		c, err = dialTCP(net, la, ra, deadline)
+	case *UDPAddr:
+		la, _ := la.(*UDPAddr)
+		c, err = dialUDP(net, la, ra, deadline)
+	case *IPAddr:
+		la, _ := la.(*IPAddr)
+		c, err = dialIP(net, la, ra, deadline)
+	case *UnixAddr:
+		la, _ := la.(*UnixAddr)
+		c, err = dialUnix(net, la, ra, deadline)
+	default:
+		return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: addr}}
+	}
+	if err != nil {
+		return nil, err // c is non-nil interface containing nil pointer
+	}
+	return c, nil
+}
+
+// Listen announces on the local network address laddr.
+// The network net must be a stream-oriented network: "tcp", "tcp4",
+// "tcp6", "unix" or "unixpacket".
+// See Dial for the syntax of laddr.
+func Listen(net, laddr string) (Listener, error) {
+	la, err := resolveAddr("listen", net, laddr, noDeadline)
+	if err != nil {
+		return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
+	}
+	var l Listener
+	switch la := la.toAddr().(type) {
+	case *TCPAddr:
+		l, err = ListenTCP(net, la)
+	case *UnixAddr:
+		l, err = ListenUnix(net, la)
+	default:
+		return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
+	}
+	if err != nil {
+		return nil, err // l is non-nil interface containing nil pointer
+	}
+	return l, nil
+}
+
+// ListenPacket announces on the local network address laddr.
+// The network net must be a packet-oriented network: "udp", "udp4",
+// "udp6", "ip", "ip4", "ip6" or "unixgram".
+// See Dial for the syntax of laddr.
+func ListenPacket(net, laddr string) (PacketConn, error) {
+	la, err := resolveAddr("listen", net, laddr, noDeadline)
+	if err != nil {
+		return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
+	}
+	var l PacketConn
+	switch la := la.toAddr().(type) {
+	case *UDPAddr:
+		l, err = ListenUDP(net, la)
+	case *IPAddr:
+		l, err = ListenIP(net, la)
+	case *UnixAddr:
+		l, err = ListenUnixgram(net, la)
+	default:
+		return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
+	}
+	if err != nil {
+		return nil, err // l is non-nil interface containing nil pointer
+	}
+	return l, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/dial_gen.go b/third_party/gofrontend/libgo/go/net/dial_gen.go
new file mode 100644
index 0000000..ada6233
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dial_gen.go
@@ -0,0 +1,46 @@
+// 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.
+
+// +build windows plan9
+
+package net
+
+import (
+	"time"
+)
+
+var testingIssue5349 bool // used during tests
+
+// dialChannel is the simple pure-Go implementation of dial, still
+// used on operating systems where the deadline hasn't been pushed
+// down into the pollserver. (Plan 9 and some old versions of Windows)
+func dialChannel(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
+	var timeout time.Duration
+	if !deadline.IsZero() {
+		timeout = deadline.Sub(time.Now())
+	}
+	if timeout <= 0 {
+		return dialer(noDeadline)
+	}
+	t := time.NewTimer(timeout)
+	defer t.Stop()
+	type racer struct {
+		Conn
+		error
+	}
+	ch := make(chan racer, 1)
+	go func() {
+		if testingIssue5349 {
+			time.Sleep(time.Millisecond)
+		}
+		c, err := dialer(noDeadline)
+		ch <- racer{c, err}
+	}()
+	select {
+	case <-t.C:
+		return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errTimeout}
+	case racer := <-ch:
+		return racer.Conn, racer.error
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/dial_test.go b/third_party/gofrontend/libgo/go/net/dial_test.go
new file mode 100644
index 0000000..f9260fd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dial_test.go
@@ -0,0 +1,536 @@
+// 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.
+
+package net
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"os/exec"
+	"reflect"
+	"regexp"
+	"runtime"
+	"strconv"
+	"sync"
+	"testing"
+	"time"
+)
+
+func newLocalListener(t *testing.T) Listener {
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		ln, err = Listen("tcp6", "[::1]:0")
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+	return ln
+}
+
+func TestDialTimeout(t *testing.T) {
+	origBacklog := listenerBacklog
+	defer func() {
+		listenerBacklog = origBacklog
+	}()
+	listenerBacklog = 1
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	errc := make(chan error)
+
+	numConns := listenerBacklog + 100
+
+	// TODO(bradfitz): It's hard to test this in a portable
+	// way. This is unfortunate, but works for now.
+	switch runtime.GOOS {
+	case "linux":
+		// The kernel will start accepting TCP connections before userspace
+		// gets a chance to not accept them, so fire off a bunch to fill up
+		// the kernel's backlog.  Then we test we get a failure after that.
+		for i := 0; i < numConns; i++ {
+			go func() {
+				_, err := DialTimeout("tcp", ln.Addr().String(), 200*time.Millisecond)
+				errc <- err
+			}()
+		}
+	case "darwin", "plan9", "windows":
+		// At least OS X 10.7 seems to accept any number of
+		// connections, ignoring listen's backlog, so resort
+		// to connecting to a hopefully-dead 127/8 address.
+		// Same for windows.
+		//
+		// Use an IANA reserved port (49151) instead of 80, because
+		// on our 386 builder, this Dial succeeds, connecting
+		// to an IIS web server somewhere.  The data center
+		// or VM or firewall must be stealing the TCP connection.
+		//
+		// IANA Service Name and Transport Protocol Port Number Registry
+		// <http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml>
+		go func() {
+			c, err := DialTimeout("tcp", "127.0.71.111:49151", 200*time.Millisecond)
+			if err == nil {
+				err = fmt.Errorf("unexpected: connected to %s!", c.RemoteAddr())
+				c.Close()
+			}
+			errc <- err
+		}()
+	default:
+		// TODO(bradfitz):
+		// OpenBSD may have a reject route to 127/8 except 127.0.0.1/32
+		// by default. FreeBSD likely works, but is untested.
+		// TODO(rsc):
+		// The timeout never happens on Windows.  Why?  Issue 3016.
+		t.Skipf("skipping test on %q; untested.", runtime.GOOS)
+	}
+
+	connected := 0
+	for {
+		select {
+		case <-time.After(15 * time.Second):
+			t.Fatal("too slow")
+		case err := <-errc:
+			if err == nil {
+				connected++
+				if connected == numConns {
+					t.Fatal("all connections connected; expected some to time out")
+				}
+			} else {
+				terr, ok := err.(timeout)
+				if !ok {
+					t.Fatalf("got error %q; want error with timeout interface", err)
+				}
+				if !terr.Timeout() {
+					t.Fatalf("got error %q; not a timeout", err)
+				}
+				// Pass. We saw a timeout error.
+				return
+			}
+		}
+	}
+}
+
+func TestSelfConnect(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		// TODO(brainman): do not know why it hangs.
+		t.Skip("skipping known-broken test on windows")
+	}
+	// Test that Dial does not honor self-connects.
+	// See the comment in DialTCP.
+
+	// Find a port that would be used as a local address.
+	l, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	c, err := Dial("tcp", l.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	addr := c.LocalAddr().String()
+	c.Close()
+	l.Close()
+
+	// Try to connect to that address repeatedly.
+	n := 100000
+	if testing.Short() {
+		n = 1000
+	}
+	switch runtime.GOOS {
+	case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd", "plan9", "solaris", "windows":
+		// Non-Linux systems take a long time to figure
+		// out that there is nothing listening on localhost.
+		n = 100
+	}
+	for i := 0; i < n; i++ {
+		c, err := DialTimeout("tcp", addr, time.Millisecond)
+		if err == nil {
+			c.Close()
+			t.Errorf("#%d: Dial %q succeeded", i, addr)
+		}
+	}
+}
+
+var runErrorTest = flag.Bool("run_error_test", false, "let TestDialError check for dns errors")
+
+type DialErrorTest struct {
+	Net     string
+	Raddr   string
+	Pattern string
+}
+
+var dialErrorTests = []DialErrorTest{
+	{
+		"datakit", "mh/astro/r70",
+		"dial datakit mh/astro/r70: unknown network datakit",
+	},
+	{
+		"tcp", "127.0.0.1:☺",
+		"dial tcp 127.0.0.1:☺: unknown port tcp/☺",
+	},
+	{
+		"tcp", "no-such-name.google.com.:80",
+		"dial tcp no-such-name.google.com.:80: lookup no-such-name.google.com.( on .*)?: no (.*)",
+	},
+	{
+		"tcp", "no-such-name.no-such-top-level-domain.:80",
+		"dial tcp no-such-name.no-such-top-level-domain.:80: lookup no-such-name.no-such-top-level-domain.( on .*)?: no (.*)",
+	},
+	{
+		"tcp", "no-such-name:80",
+		`dial tcp no-such-name:80: lookup no-such-name\.(.*\.)?( on .*)?: no (.*)`,
+	},
+	{
+		"tcp", "mh/astro/r70:http",
+		"dial tcp mh/astro/r70:http: lookup mh/astro/r70: invalid domain name",
+	},
+	{
+		"unix", "/etc/file-not-found",
+		"dial unix /etc/file-not-found: no such file or directory",
+	},
+	{
+		"unix", "/etc/",
+		"dial unix /etc/: (permission denied|socket operation on non-socket|connection refused)",
+	},
+	{
+		"unixpacket", "/etc/file-not-found",
+		"dial unixpacket /etc/file-not-found: no such file or directory",
+	},
+	{
+		"unixpacket", "/etc/",
+		"dial unixpacket /etc/: (permission denied|socket operation on non-socket|connection refused)",
+	},
+}
+
+var duplicateErrorPattern = `dial (.*) dial (.*)`
+
+func TestDialError(t *testing.T) {
+	if !*runErrorTest {
+		t.Logf("test disabled; use -run_error_test to enable")
+		return
+	}
+	for i, tt := range dialErrorTests {
+		c, err := Dial(tt.Net, tt.Raddr)
+		if c != nil {
+			c.Close()
+		}
+		if err == nil {
+			t.Errorf("#%d: nil error, want match for %#q", i, tt.Pattern)
+			continue
+		}
+		s := err.Error()
+		match, _ := regexp.MatchString(tt.Pattern, s)
+		if !match {
+			t.Errorf("#%d: %q, want match for %#q", i, s, tt.Pattern)
+		}
+		match, _ = regexp.MatchString(duplicateErrorPattern, s)
+		if match {
+			t.Errorf("#%d: %q, duplicate error return from Dial", i, s)
+		}
+	}
+}
+
+var invalidDialAndListenArgTests = []struct {
+	net  string
+	addr string
+	err  error
+}{
+	{"foo", "bar", &OpError{Op: "dial", Net: "foo", Addr: nil, Err: UnknownNetworkError("foo")}},
+	{"baz", "", &OpError{Op: "listen", Net: "baz", Addr: nil, Err: UnknownNetworkError("baz")}},
+	{"tcp", "", &OpError{Op: "dial", Net: "tcp", Addr: nil, Err: errMissingAddress}},
+}
+
+func TestInvalidDialAndListenArgs(t *testing.T) {
+	for _, tt := range invalidDialAndListenArgTests {
+		var err error
+		switch tt.err.(*OpError).Op {
+		case "dial":
+			_, err = Dial(tt.net, tt.addr)
+		case "listen":
+			_, err = Listen(tt.net, tt.addr)
+		}
+		if !reflect.DeepEqual(tt.err, err) {
+			t.Fatalf("got %#v; expected %#v", err, tt.err)
+		}
+	}
+}
+
+func TestDialTimeoutFDLeak(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		// TODO(bradfitz): test on other platforms
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	type connErr struct {
+		conn Conn
+		err  error
+	}
+	dials := listenerBacklog + 100
+	// used to be listenerBacklog + 5, but was found to be unreliable, issue 4384.
+	maxGoodConnect := listenerBacklog + runtime.NumCPU()*10
+	resc := make(chan connErr)
+	for i := 0; i < dials; i++ {
+		go func() {
+			conn, err := DialTimeout("tcp", ln.Addr().String(), 500*time.Millisecond)
+			resc <- connErr{conn, err}
+		}()
+	}
+
+	var firstErr string
+	var ngood int
+	var toClose []io.Closer
+	for i := 0; i < dials; i++ {
+		ce := <-resc
+		if ce.err == nil {
+			ngood++
+			if ngood > maxGoodConnect {
+				t.Errorf("%d good connects; expected at most %d", ngood, maxGoodConnect)
+			}
+			toClose = append(toClose, ce.conn)
+			continue
+		}
+		err := ce.err
+		if firstErr == "" {
+			firstErr = err.Error()
+		} else if err.Error() != firstErr {
+			t.Fatalf("inconsistent error messages: first was %q, then later %q", firstErr, err)
+		}
+	}
+	for _, c := range toClose {
+		c.Close()
+	}
+	for i := 0; i < 100; i++ {
+		if got := numFD(); got < dials {
+			// Test passes.
+			return
+		}
+		time.Sleep(10 * time.Millisecond)
+	}
+	if got := numFD(); got >= dials {
+		t.Errorf("num fds after %d timeouts = %d; want <%d", dials, got, dials)
+	}
+}
+
+func numTCP() (ntcp, nopen, nclose int, err error) {
+	lsof, err := exec.Command("lsof", "-n", "-p", strconv.Itoa(os.Getpid())).Output()
+	if err != nil {
+		return 0, 0, 0, err
+	}
+	ntcp += bytes.Count(lsof, []byte("TCP"))
+	for _, state := range []string{"LISTEN", "SYN_SENT", "SYN_RECEIVED", "ESTABLISHED"} {
+		nopen += bytes.Count(lsof, []byte(state))
+	}
+	for _, state := range []string{"CLOSED", "CLOSE_WAIT", "LAST_ACK", "FIN_WAIT_1", "FIN_WAIT_2", "CLOSING", "TIME_WAIT"} {
+		nclose += bytes.Count(lsof, []byte(state))
+	}
+	return ntcp, nopen, nclose, nil
+}
+
+func TestDialMultiFDLeak(t *testing.T) {
+	if !supportsIPv4 || !supportsIPv6 {
+		t.Skip("neither ipv4 nor ipv6 is supported")
+	}
+
+	halfDeadServer := func(dss *dualStackServer, ln Listener) {
+		for {
+			if c, err := ln.Accept(); err != nil {
+				return
+			} else {
+				// It just keeps established
+				// connections like a half-dead server
+				// does.
+				dss.putConn(c)
+			}
+		}
+	}
+	dss, err := newDualStackServer([]streamListener{
+		{net: "tcp4", addr: "127.0.0.1"},
+		{net: "tcp6", addr: "[::1]"},
+	})
+	if err != nil {
+		t.Fatalf("newDualStackServer failed: %v", err)
+	}
+	defer dss.teardown()
+	if err := dss.buildup(halfDeadServer); err != nil {
+		t.Fatalf("dualStackServer.buildup failed: %v", err)
+	}
+
+	_, before, _, err := numTCP()
+	if err != nil {
+		t.Skipf("skipping test; error finding or running lsof: %v", err)
+	}
+
+	var wg sync.WaitGroup
+	portnum, _, _ := dtoi(dss.port, 0)
+	ras := addrList{
+		// Losers that will fail to connect, see RFC 6890.
+		&TCPAddr{IP: IPv4(198, 18, 0, 254), Port: portnum},
+		&TCPAddr{IP: ParseIP("2001:2::254"), Port: portnum},
+
+		// Winner candidates of this race.
+		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: portnum},
+		&TCPAddr{IP: IPv6loopback, Port: portnum},
+
+		// Losers that will have established connections.
+		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: portnum},
+		&TCPAddr{IP: IPv6loopback, Port: portnum},
+	}
+	const T1 = 10 * time.Millisecond
+	const T2 = 2 * T1
+	const N = 10
+	for i := 0; i < N; i++ {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			if c, err := dialMulti("tcp", "fast failover test", nil, ras, time.Now().Add(T1)); err == nil {
+				c.Close()
+			}
+		}()
+	}
+	wg.Wait()
+	time.Sleep(T2)
+
+	ntcp, after, nclose, err := numTCP()
+	if err != nil {
+		t.Skipf("skipping test; error finding or running lsof: %v", err)
+	}
+	t.Logf("tcp sessions: %v, open sessions: %v, closing sessions: %v", ntcp, after, nclose)
+
+	if after != before {
+		t.Fatalf("got %v open sessions; expected %v", after, before)
+	}
+}
+
+func numFD() int {
+	if runtime.GOOS == "linux" {
+		f, err := os.Open("/proc/self/fd")
+		if err != nil {
+			panic(err)
+		}
+		defer f.Close()
+		names, err := f.Readdirnames(0)
+		if err != nil {
+			panic(err)
+		}
+		return len(names)
+	}
+	// All tests using this should be skipped anyway, but:
+	panic("numFDs not implemented on " + runtime.GOOS)
+}
+
+func TestDialer(t *testing.T) {
+	ln, err := Listen("tcp4", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+	}
+	defer ln.Close()
+	ch := make(chan error, 1)
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			ch <- fmt.Errorf("Accept failed: %v", err)
+			return
+		}
+		defer c.Close()
+		ch <- nil
+	}()
+
+	laddr, err := ResolveTCPAddr("tcp4", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ResolveTCPAddr failed: %v", err)
+	}
+	d := &Dialer{LocalAddr: laddr}
+	c, err := d.Dial("tcp4", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial failed: %v", err)
+	}
+	defer c.Close()
+	c.Read(make([]byte, 1))
+	err = <-ch
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func TestDialDualStackLocalhost(t *testing.T) {
+	if ips, err := LookupIP("localhost"); err != nil {
+		t.Fatalf("LookupIP failed: %v", err)
+	} else if len(ips) < 2 || !supportsIPv4 || !supportsIPv6 {
+		t.Skip("localhost doesn't have a pair of different address family IP addresses")
+	}
+
+	touchAndByeServer := func(dss *dualStackServer, ln Listener) {
+		for {
+			if c, err := ln.Accept(); err != nil {
+				return
+			} else {
+				c.Close()
+			}
+		}
+	}
+	dss, err := newDualStackServer([]streamListener{
+		{net: "tcp4", addr: "127.0.0.1"},
+		{net: "tcp6", addr: "[::1]"},
+	})
+	if err != nil {
+		t.Fatalf("newDualStackServer failed: %v", err)
+	}
+	defer dss.teardown()
+	if err := dss.buildup(touchAndByeServer); err != nil {
+		t.Fatalf("dualStackServer.buildup failed: %v", err)
+	}
+
+	d := &Dialer{DualStack: true}
+	for _ = range dss.lns {
+		if c, err := d.Dial("tcp", "localhost:"+dss.port); err != nil {
+			t.Errorf("Dial failed: %v", err)
+		} else {
+			if addr := c.LocalAddr().(*TCPAddr); addr.IP.To4() != nil {
+				dss.teardownNetwork("tcp4")
+			} else if addr.IP.To16() != nil && addr.IP.To4() == nil {
+				dss.teardownNetwork("tcp6")
+			}
+			c.Close()
+		}
+	}
+}
+
+func TestDialerKeepAlive(t *testing.T) {
+	ln := newLocalListener(t)
+	defer ln.Close()
+	defer func() {
+		testHookSetKeepAlive = func() {}
+	}()
+	go func() {
+		for {
+			c, err := ln.Accept()
+			if err != nil {
+				return
+			}
+			c.Close()
+		}
+	}()
+	for _, keepAlive := range []bool{false, true} {
+		got := false
+		testHookSetKeepAlive = func() { got = true }
+		var d Dialer
+		if keepAlive {
+			d.KeepAlive = 30 * time.Second
+		}
+		c, err := d.Dial("tcp", ln.Addr().String())
+		if err != nil {
+			t.Fatal(err)
+		}
+		c.Close()
+		if got != keepAlive {
+			t.Errorf("Dialer.KeepAlive = %v: SetKeepAlive called = %v, want %v", d.KeepAlive, got, !got)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/dialgoogle_test.go b/third_party/gofrontend/libgo/go/net/dialgoogle_test.go
new file mode 100644
index 0000000..df5895a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dialgoogle_test.go
@@ -0,0 +1,209 @@
+// 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 net
+
+import (
+	"flag"
+	"fmt"
+	"io"
+	"strings"
+	"syscall"
+	"testing"
+)
+
+// If an IPv6 tunnel is running, we can try dialing a real IPv6 address.
+var testIPv6 = flag.Bool("ipv6", false, "assume ipv6 tunnel is present")
+
+func TestResolveGoogle(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	for _, network := range []string{"tcp", "tcp4", "tcp6"} {
+		addr, err := ResolveTCPAddr(network, "www.google.com:http")
+		if err != nil {
+			if (network == "tcp" || network == "tcp4") && !supportsIPv4 {
+				t.Logf("ipv4 is not supported: %v", err)
+			} else if network == "tcp6" && !supportsIPv6 {
+				t.Logf("ipv6 is not supported: %v", err)
+			} else {
+				t.Errorf("ResolveTCPAddr failed: %v", err)
+			}
+			continue
+		}
+		if (network == "tcp" || network == "tcp4") && addr.IP.To4() == nil {
+			t.Errorf("got %v; expected an IPv4 address on %v", addr, network)
+		} else if network == "tcp6" && (addr.IP.To16() == nil || addr.IP.To4() != nil) {
+			t.Errorf("got %v; expected an IPv6 address on %v", addr, network)
+		}
+	}
+}
+
+func TestDialGoogle(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	d := &Dialer{DualStack: true}
+	for _, network := range []string{"tcp", "tcp4", "tcp6"} {
+		if network == "tcp" && !supportsIPv4 && !supportsIPv6 {
+			t.Logf("skipping test; both ipv4 and ipv6 are not supported")
+			continue
+		} else if network == "tcp4" && !supportsIPv4 {
+			t.Logf("skipping test; ipv4 is not supported")
+			continue
+		} else if network == "tcp6" && !supportsIPv6 {
+			t.Logf("skipping test; ipv6 is not supported")
+			continue
+		} else if network == "tcp6" && !*testIPv6 {
+			t.Logf("test disabled; use -ipv6 to enable")
+			continue
+		}
+		if c, err := d.Dial(network, "www.google.com:http"); err != nil {
+			t.Errorf("Dial failed: %v", err)
+		} else {
+			c.Close()
+		}
+	}
+}
+
+// fd is already connected to the destination, port 80.
+// Run an HTTP request to fetch the appropriate page.
+func fetchGoogle(t *testing.T, fd Conn, network, addr string) {
+	req := []byte("GET /robots.txt HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
+	n, err := fd.Write(req)
+
+	buf := make([]byte, 1000)
+	n, err = io.ReadFull(fd, buf)
+
+	if n < 1000 {
+		t.Errorf("fetchGoogle: short HTTP read from %s %s - %v", network, addr, err)
+		return
+	}
+}
+
+func doDial(t *testing.T, network, addr string) {
+	fd, err := Dial(network, addr)
+	if err != nil {
+		t.Errorf("Dial(%q, %q, %q) = _, %v", network, "", addr, err)
+		return
+	}
+	fetchGoogle(t, fd, network, addr)
+	fd.Close()
+}
+
+var googleaddrsipv4 = []string{
+	"%d.%d.%d.%d:80",
+	"www.google.com:80",
+	"%d.%d.%d.%d:http",
+	"www.google.com:http",
+	"%03d.%03d.%03d.%03d:0080",
+	"[::ffff:%d.%d.%d.%d]:80",
+	"[::ffff:%02x%02x:%02x%02x]:80",
+	"[0:0:0:0:0000:ffff:%d.%d.%d.%d]:80",
+	"[0:0:0:0:000000:ffff:%d.%d.%d.%d]:80",
+	"[0:0:0:0::ffff:%d.%d.%d.%d]:80",
+}
+
+func TestDialGoogleIPv4(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	// Insert an actual IPv4 address for google.com
+	// into the table.
+	addrs, err := LookupIP("www.google.com")
+	if err != nil {
+		t.Fatalf("lookup www.google.com: %v", err)
+	}
+	var ip IP
+	for _, addr := range addrs {
+		if x := addr.To4(); x != nil {
+			ip = x
+			break
+		}
+	}
+	if ip == nil {
+		t.Fatalf("no IPv4 addresses for www.google.com")
+	}
+
+	for i, s := range googleaddrsipv4 {
+		if strings.Contains(s, "%") {
+			googleaddrsipv4[i] = fmt.Sprintf(s, ip[0], ip[1], ip[2], ip[3])
+		}
+	}
+
+	for i := 0; i < len(googleaddrsipv4); i++ {
+		addr := googleaddrsipv4[i]
+		if addr == "" {
+			continue
+		}
+		t.Logf("-- %s --", addr)
+		doDial(t, "tcp", addr)
+		if addr[0] != '[' {
+			doDial(t, "tcp4", addr)
+			if supportsIPv6 {
+				// make sure syscall.SocketDisableIPv6 flag works.
+				syscall.SocketDisableIPv6 = true
+				doDial(t, "tcp", addr)
+				doDial(t, "tcp4", addr)
+				syscall.SocketDisableIPv6 = false
+			}
+		}
+	}
+}
+
+var googleaddrsipv6 = []string{
+	"[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:80",
+	"ipv6.google.com:80",
+	"[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:http",
+	"ipv6.google.com:http",
+}
+
+func TestDialGoogleIPv6(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+	// Only run tcp6 if the kernel will take it.
+	if !supportsIPv6 {
+		t.Skip("skipping test; ipv6 is not supported")
+	}
+	if !*testIPv6 {
+		t.Skip("test disabled; use -ipv6 to enable")
+	}
+
+	// Insert an actual IPv6 address for ipv6.google.com
+	// into the table.
+	addrs, err := LookupIP("ipv6.google.com")
+	if err != nil {
+		t.Fatalf("lookup ipv6.google.com: %v", err)
+	}
+	var ip IP
+	for _, addr := range addrs {
+		if x := addr.To16(); x != nil {
+			ip = x
+			break
+		}
+	}
+	if ip == nil {
+		t.Fatalf("no IPv6 addresses for ipv6.google.com")
+	}
+
+	for i, s := range googleaddrsipv6 {
+		if strings.Contains(s, "%") {
+			googleaddrsipv6[i] = fmt.Sprintf(s, ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15])
+		}
+	}
+
+	for i := 0; i < len(googleaddrsipv6); i++ {
+		addr := googleaddrsipv6[i]
+		if addr == "" {
+			continue
+		}
+		t.Logf("-- %s --", addr)
+		doDial(t, "tcp", addr)
+		doDial(t, "tcp6", addr)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/dnsclient.go b/third_party/gofrontend/libgo/go/net/dnsclient.go
new file mode 100644
index 0000000..9bffa11
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dnsclient.go
@@ -0,0 +1,251 @@
+// 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 net
+
+import (
+	"math/rand"
+	"sort"
+)
+
+// DNSError represents a DNS lookup error.
+type DNSError struct {
+	Err       string // description of the error
+	Name      string // name looked for
+	Server    string // server used
+	IsTimeout bool
+}
+
+func (e *DNSError) Error() string {
+	if e == nil {
+		return "<nil>"
+	}
+	s := "lookup " + e.Name
+	if e.Server != "" {
+		s += " on " + e.Server
+	}
+	s += ": " + e.Err
+	return s
+}
+
+func (e *DNSError) Timeout() bool   { return e.IsTimeout }
+func (e *DNSError) Temporary() bool { return e.IsTimeout }
+
+const noSuchHost = "no such host"
+
+// reverseaddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
+// address addr suitable for rDNS (PTR) record lookup or an error if it fails
+// to parse the IP address.
+func reverseaddr(addr string) (arpa string, err error) {
+	ip := ParseIP(addr)
+	if ip == nil {
+		return "", &DNSError{Err: "unrecognized address", Name: addr}
+	}
+	if ip.To4() != nil {
+		return itoa(int(ip[15])) + "." + itoa(int(ip[14])) + "." + itoa(int(ip[13])) + "." +
+			itoa(int(ip[12])) + ".in-addr.arpa.", nil
+	}
+	// Must be IPv6
+	buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
+	// Add it, in reverse, to the buffer
+	for i := len(ip) - 1; i >= 0; i-- {
+		v := ip[i]
+		buf = append(buf, hexDigit[v&0xF])
+		buf = append(buf, '.')
+		buf = append(buf, hexDigit[v>>4])
+		buf = append(buf, '.')
+	}
+	// Append "ip6.arpa." and return (buf already has the final .)
+	buf = append(buf, "ip6.arpa."...)
+	return string(buf), nil
+}
+
+// Find answer for name in dns message.
+// On return, if err == nil, addrs != nil.
+func answer(name, server string, dns *dnsMsg, qtype uint16) (cname string, addrs []dnsRR, err error) {
+	addrs = make([]dnsRR, 0, len(dns.answer))
+
+	if dns.rcode == dnsRcodeNameError && dns.recursion_available {
+		return "", nil, &DNSError{Err: noSuchHost, Name: name}
+	}
+	if dns.rcode != dnsRcodeSuccess {
+		// None of the error codes make sense
+		// for the query we sent.  If we didn't get
+		// a name error and we didn't get success,
+		// the server is behaving incorrectly.
+		return "", nil, &DNSError{Err: "server misbehaving", Name: name, Server: server}
+	}
+
+	// Look for the name.
+	// Presotto says it's okay to assume that servers listed in
+	// /etc/resolv.conf are recursive resolvers.
+	// We asked for recursion, so it should have included
+	// all the answers we need in this one packet.
+Cname:
+	for cnameloop := 0; cnameloop < 10; cnameloop++ {
+		addrs = addrs[0:0]
+		for _, rr := range dns.answer {
+			if _, justHeader := rr.(*dnsRR_Header); justHeader {
+				// Corrupt record: we only have a
+				// header. That header might say it's
+				// of type qtype, but we don't
+				// actually have it. Skip.
+				continue
+			}
+			h := rr.Header()
+			if h.Class == dnsClassINET && h.Name == name {
+				switch h.Rrtype {
+				case qtype:
+					addrs = append(addrs, rr)
+				case dnsTypeCNAME:
+					// redirect to cname
+					name = rr.(*dnsRR_CNAME).Cname
+					continue Cname
+				}
+			}
+		}
+		if len(addrs) == 0 {
+			return "", nil, &DNSError{Err: noSuchHost, Name: name, Server: server}
+		}
+		return name, addrs, nil
+	}
+
+	return "", nil, &DNSError{Err: "too many redirects", Name: name, Server: server}
+}
+
+func isDomainName(s string) bool {
+	// See RFC 1035, RFC 3696.
+	if len(s) == 0 {
+		return false
+	}
+	if len(s) > 255 {
+		return false
+	}
+
+	last := byte('.')
+	ok := false // Ok once we've seen a letter.
+	partlen := 0
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		switch {
+		default:
+			return false
+		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_':
+			ok = true
+			partlen++
+		case '0' <= c && c <= '9':
+			// fine
+			partlen++
+		case c == '-':
+			// Byte before dash cannot be dot.
+			if last == '.' {
+				return false
+			}
+			partlen++
+		case c == '.':
+			// Byte before dot cannot be dot, dash.
+			if last == '.' || last == '-' {
+				return false
+			}
+			if partlen > 63 || partlen == 0 {
+				return false
+			}
+			partlen = 0
+		}
+		last = c
+	}
+	if last == '-' || partlen > 63 {
+		return false
+	}
+
+	return ok
+}
+
+// An SRV represents a single DNS SRV record.
+type SRV struct {
+	Target   string
+	Port     uint16
+	Priority uint16
+	Weight   uint16
+}
+
+// byPriorityWeight sorts SRV records by ascending priority and weight.
+type byPriorityWeight []*SRV
+
+func (s byPriorityWeight) Len() int { return len(s) }
+
+func (s byPriorityWeight) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+func (s byPriorityWeight) Less(i, j int) bool {
+	return s[i].Priority < s[j].Priority ||
+		(s[i].Priority == s[j].Priority && s[i].Weight < s[j].Weight)
+}
+
+// shuffleByWeight shuffles SRV records by weight using the algorithm
+// described in RFC 2782.
+func (addrs byPriorityWeight) shuffleByWeight() {
+	sum := 0
+	for _, addr := range addrs {
+		sum += int(addr.Weight)
+	}
+	for sum > 0 && len(addrs) > 1 {
+		s := 0
+		n := rand.Intn(sum)
+		for i := range addrs {
+			s += int(addrs[i].Weight)
+			if s > n {
+				if i > 0 {
+					t := addrs[i]
+					copy(addrs[1:i+1], addrs[0:i])
+					addrs[0] = t
+				}
+				break
+			}
+		}
+		sum -= int(addrs[0].Weight)
+		addrs = addrs[1:]
+	}
+}
+
+// sort reorders SRV records as specified in RFC 2782.
+func (addrs byPriorityWeight) sort() {
+	sort.Sort(addrs)
+	i := 0
+	for j := 1; j < len(addrs); j++ {
+		if addrs[i].Priority != addrs[j].Priority {
+			addrs[i:j].shuffleByWeight()
+			i = j
+		}
+	}
+	addrs[i:].shuffleByWeight()
+}
+
+// An MX represents a single DNS MX record.
+type MX struct {
+	Host string
+	Pref uint16
+}
+
+// byPref implements sort.Interface to sort MX records by preference
+type byPref []*MX
+
+func (s byPref) Len() int { return len(s) }
+
+func (s byPref) Less(i, j int) bool { return s[i].Pref < s[j].Pref }
+
+func (s byPref) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// sort reorders MX records as specified in RFC 5321.
+func (s byPref) sort() {
+	for i := range s {
+		j := rand.Intn(i + 1)
+		s[i], s[j] = s[j], s[i]
+	}
+	sort.Sort(s)
+}
+
+// An NS represents a single DNS NS record.
+type NS struct {
+	Host string
+}
diff --git a/third_party/gofrontend/libgo/go/net/dnsclient_test.go b/third_party/gofrontend/libgo/go/net/dnsclient_test.go
new file mode 100644
index 0000000..435eb35
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dnsclient_test.go
@@ -0,0 +1,69 @@
+// Copyright 2014 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 net
+
+import (
+	"math/rand"
+	"testing"
+)
+
+func checkDistribution(t *testing.T, data []*SRV, margin float64) {
+	sum := 0
+	for _, srv := range data {
+		sum += int(srv.Weight)
+	}
+
+	results := make(map[string]int)
+
+	count := 1000
+	for j := 0; j < count; j++ {
+		d := make([]*SRV, len(data))
+		copy(d, data)
+		byPriorityWeight(d).shuffleByWeight()
+		key := d[0].Target
+		results[key] = results[key] + 1
+	}
+
+	actual := results[data[0].Target]
+	expected := float64(count) * float64(data[0].Weight) / float64(sum)
+	diff := float64(actual) - expected
+	t.Logf("actual: %v diff: %v e: %v m: %v", actual, diff, expected, margin)
+	if diff < 0 {
+		diff = -diff
+	}
+	if diff > (expected * margin) {
+		t.Errorf("missed target weight: expected %v, %v", expected, actual)
+	}
+}
+
+func testUniformity(t *testing.T, size int, margin float64) {
+	rand.Seed(1)
+	data := make([]*SRV, size)
+	for i := 0; i < size; i++ {
+		data[i] = &SRV{Target: string('a' + i), Weight: 1}
+	}
+	checkDistribution(t, data, margin)
+}
+
+func TestUniformity(t *testing.T) {
+	testUniformity(t, 2, 0.05)
+	testUniformity(t, 3, 0.10)
+	testUniformity(t, 10, 0.20)
+	testWeighting(t, 0.05)
+}
+
+func testWeighting(t *testing.T, margin float64) {
+	rand.Seed(1)
+	data := []*SRV{
+		{Target: "a", Weight: 60},
+		{Target: "b", Weight: 30},
+		{Target: "c", Weight: 10},
+	}
+	checkDistribution(t, data, margin)
+}
+
+func TestWeighting(t *testing.T) {
+	testWeighting(t, 0.05)
+}
diff --git a/third_party/gofrontend/libgo/go/net/dnsclient_unix.go b/third_party/gofrontend/libgo/go/net/dnsclient_unix.go
new file mode 100644
index 0000000..3713efd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dnsclient_unix.go
@@ -0,0 +1,364 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+// DNS client: see RFC 1035.
+// Has to be linked into package net for Dial.
+
+// TODO(rsc):
+//	Could potentially handle many outstanding lookups faster.
+//	Could have a small cache.
+//	Random UDP source port (net.Dial should do that for us).
+//	Random request IDs.
+
+package net
+
+import (
+	"io"
+	"math/rand"
+	"os"
+	"sync"
+	"time"
+)
+
+// Send a request on the connection and hope for a reply.
+// Up to cfg.attempts attempts.
+func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error) {
+	_, useTCP := c.(*TCPConn)
+	if len(name) >= 256 {
+		return nil, &DNSError{Err: "name too long", Name: name}
+	}
+	out := new(dnsMsg)
+	out.id = uint16(rand.Int()) ^ uint16(time.Now().UnixNano())
+	out.question = []dnsQuestion{
+		{name, qtype, dnsClassINET},
+	}
+	out.recursion_desired = true
+	msg, ok := out.Pack()
+	if !ok {
+		return nil, &DNSError{Err: "internal error - cannot pack message", Name: name}
+	}
+	if useTCP {
+		mlen := uint16(len(msg))
+		msg = append([]byte{byte(mlen >> 8), byte(mlen)}, msg...)
+	}
+	for attempt := 0; attempt < cfg.attempts; attempt++ {
+		n, err := c.Write(msg)
+		if err != nil {
+			return nil, err
+		}
+
+		if cfg.timeout == 0 {
+			c.SetReadDeadline(noDeadline)
+		} else {
+			c.SetReadDeadline(time.Now().Add(time.Duration(cfg.timeout) * time.Second))
+		}
+		buf := make([]byte, 2000)
+		if useTCP {
+			n, err = io.ReadFull(c, buf[:2])
+			if err != nil {
+				if e, ok := err.(Error); ok && e.Timeout() {
+					continue
+				}
+			}
+			mlen := int(buf[0])<<8 | int(buf[1])
+			if mlen > len(buf) {
+				buf = make([]byte, mlen)
+			}
+			n, err = io.ReadFull(c, buf[:mlen])
+		} else {
+			n, err = c.Read(buf)
+		}
+		if err != nil {
+			if e, ok := err.(Error); ok && e.Timeout() {
+				continue
+			}
+			return nil, err
+		}
+		buf = buf[:n]
+		in := new(dnsMsg)
+		if !in.Unpack(buf) || in.id != out.id {
+			continue
+		}
+		return in, nil
+	}
+	var server string
+	if a := c.RemoteAddr(); a != nil {
+		server = a.String()
+	}
+	return nil, &DNSError{Err: "no answer from server", Name: name, Server: server, IsTimeout: true}
+}
+
+// Do a lookup for a single name, which must be rooted
+// (otherwise answer will not find the answers).
+func tryOneName(cfg *dnsConfig, name string, qtype uint16) (cname string, addrs []dnsRR, err error) {
+	if len(cfg.servers) == 0 {
+		return "", nil, &DNSError{Err: "no DNS servers", Name: name}
+	}
+	for i := 0; i < len(cfg.servers); i++ {
+		// Calling Dial here is scary -- we have to be sure
+		// not to dial a name that will require a DNS lookup,
+		// or Dial will call back here to translate it.
+		// The DNS config parser has already checked that
+		// all the cfg.servers[i] are IP addresses, which
+		// Dial will use without a DNS lookup.
+		server := cfg.servers[i] + ":53"
+		c, cerr := Dial("udp", server)
+		if cerr != nil {
+			err = cerr
+			continue
+		}
+		msg, merr := exchange(cfg, c, name, qtype)
+		c.Close()
+		if merr != nil {
+			err = merr
+			continue
+		}
+		if msg.truncated { // see RFC 5966
+			c, cerr = Dial("tcp", server)
+			if cerr != nil {
+				err = cerr
+				continue
+			}
+			msg, merr = exchange(cfg, c, name, qtype)
+			c.Close()
+			if merr != nil {
+				err = merr
+				continue
+			}
+		}
+		cname, addrs, err = answer(name, server, msg, qtype)
+		if err == nil || err.(*DNSError).Err == noSuchHost {
+			break
+		}
+	}
+	return
+}
+
+func convertRR_A(records []dnsRR) []IP {
+	addrs := make([]IP, len(records))
+	for i, rr := range records {
+		a := rr.(*dnsRR_A).A
+		addrs[i] = IPv4(byte(a>>24), byte(a>>16), byte(a>>8), byte(a))
+	}
+	return addrs
+}
+
+func convertRR_AAAA(records []dnsRR) []IP {
+	addrs := make([]IP, len(records))
+	for i, rr := range records {
+		a := make(IP, IPv6len)
+		copy(a, rr.(*dnsRR_AAAA).AAAA[:])
+		addrs[i] = a
+	}
+	return addrs
+}
+
+var cfg struct {
+	ch        chan struct{}
+	mu        sync.RWMutex // protects dnsConfig and dnserr
+	dnsConfig *dnsConfig
+	dnserr    error
+}
+var onceLoadConfig sync.Once
+
+// Assume dns config file is /etc/resolv.conf here
+func loadDefaultConfig() {
+	loadConfig("/etc/resolv.conf", 5*time.Second, nil)
+}
+
+func loadConfig(resolvConfPath string, reloadTime time.Duration, quit <-chan chan struct{}) {
+	var mtime time.Time
+	cfg.ch = make(chan struct{}, 1)
+	if fi, err := os.Stat(resolvConfPath); err != nil {
+		cfg.dnserr = err
+	} else {
+		mtime = fi.ModTime()
+		cfg.dnsConfig, cfg.dnserr = dnsReadConfig(resolvConfPath)
+	}
+	go func() {
+		for {
+			time.Sleep(reloadTime)
+			select {
+			case qresp := <-quit:
+				qresp <- struct{}{}
+				return
+			case <-cfg.ch:
+			}
+
+			// In case of error, we keep the previous config
+			fi, err := os.Stat(resolvConfPath)
+			if err != nil {
+				continue
+			}
+			// If the resolv.conf mtime didn't change, do not reload
+			m := fi.ModTime()
+			if m.Equal(mtime) {
+				continue
+			}
+			mtime = m
+			// In case of error, we keep the previous config
+			ncfg, err := dnsReadConfig(resolvConfPath)
+			if err != nil || len(ncfg.servers) == 0 {
+				continue
+			}
+			cfg.mu.Lock()
+			cfg.dnsConfig = ncfg
+			cfg.dnserr = nil
+			cfg.mu.Unlock()
+		}
+	}()
+}
+
+func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err error) {
+	if !isDomainName(name) {
+		return name, nil, &DNSError{Err: "invalid domain name", Name: name}
+	}
+	onceLoadConfig.Do(loadDefaultConfig)
+
+	select {
+	case cfg.ch <- struct{}{}:
+	default:
+	}
+
+	cfg.mu.RLock()
+	defer cfg.mu.RUnlock()
+
+	if cfg.dnserr != nil || cfg.dnsConfig == nil {
+		err = cfg.dnserr
+		return
+	}
+	// If name is rooted (trailing dot) or has enough dots,
+	// try it by itself first.
+	rooted := len(name) > 0 && name[len(name)-1] == '.'
+	if rooted || count(name, '.') >= cfg.dnsConfig.ndots {
+		rname := name
+		if !rooted {
+			rname += "."
+		}
+		// Can try as ordinary name.
+		cname, addrs, err = tryOneName(cfg.dnsConfig, rname, qtype)
+		if err == nil {
+			return
+		}
+	}
+	if rooted {
+		return
+	}
+
+	// Otherwise, try suffixes.
+	for i := 0; i < len(cfg.dnsConfig.search); i++ {
+		rname := name + "." + cfg.dnsConfig.search[i]
+		if rname[len(rname)-1] != '.' {
+			rname += "."
+		}
+		cname, addrs, err = tryOneName(cfg.dnsConfig, rname, qtype)
+		if err == nil {
+			return
+		}
+	}
+
+	// Last ditch effort: try unsuffixed.
+	rname := name
+	if !rooted {
+		rname += "."
+	}
+	cname, addrs, err = tryOneName(cfg.dnsConfig, rname, qtype)
+	if err == nil {
+		return
+	}
+	if e, ok := err.(*DNSError); ok {
+		// Show original name passed to lookup, not suffixed one.
+		// In general we might have tried many suffixes; showing
+		// just one is misleading. See also golang.org/issue/6324.
+		e.Name = name
+	}
+	return
+}
+
+// goLookupHost is the native Go implementation of LookupHost.
+// Used only if cgoLookupHost refuses to handle the request
+// (that is, only if cgoLookupHost is the stub in cgo_stub.go).
+// Normally we let cgo use the C library resolver instead of
+// depending on our lookup code, so that Go and C get the same
+// answers.
+func goLookupHost(name string) (addrs []string, err error) {
+	// Use entries from /etc/hosts if they match.
+	addrs = lookupStaticHost(name)
+	if len(addrs) > 0 {
+		return
+	}
+	ips, err := goLookupIP(name)
+	if err != nil {
+		return
+	}
+	addrs = make([]string, 0, len(ips))
+	for _, ip := range ips {
+		addrs = append(addrs, ip.String())
+	}
+	return
+}
+
+// goLookupIP is the native Go implementation of LookupIP.
+// Used only if cgoLookupIP refuses to handle the request
+// (that is, only if cgoLookupIP is the stub in cgo_stub.go).
+// Normally we let cgo use the C library resolver instead of
+// depending on our lookup code, so that Go and C get the same
+// answers.
+func goLookupIP(name string) (addrs []IP, err error) {
+	// Use entries from /etc/hosts if possible.
+	haddrs := lookupStaticHost(name)
+	if len(haddrs) > 0 {
+		for _, haddr := range haddrs {
+			if ip := ParseIP(haddr); ip != nil {
+				addrs = append(addrs, ip)
+			}
+		}
+		if len(addrs) > 0 {
+			return
+		}
+	}
+	var records []dnsRR
+	var cname string
+	var err4, err6 error
+	cname, records, err4 = lookup(name, dnsTypeA)
+	addrs = convertRR_A(records)
+	if cname != "" {
+		name = cname
+	}
+	_, records, err6 = lookup(name, dnsTypeAAAA)
+	if err4 != nil && err6 == nil {
+		// Ignore A error because AAAA lookup succeeded.
+		err4 = nil
+	}
+	if err6 != nil && len(addrs) > 0 {
+		// Ignore AAAA error because A lookup succeeded.
+		err6 = nil
+	}
+	if err4 != nil {
+		return nil, err4
+	}
+	if err6 != nil {
+		return nil, err6
+	}
+
+	addrs = append(addrs, convertRR_AAAA(records)...)
+	return addrs, nil
+}
+
+// goLookupCNAME is the native Go implementation of LookupCNAME.
+// Used only if cgoLookupCNAME refuses to handle the request
+// (that is, only if cgoLookupCNAME is the stub in cgo_stub.go).
+// Normally we let cgo use the C library resolver instead of
+// depending on our lookup code, so that Go and C get the same
+// answers.
+func goLookupCNAME(name string) (cname string, err error) {
+	_, rr, err := lookup(name, dnsTypeCNAME)
+	if err != nil {
+		return
+	}
+	cname = rr[0].(*dnsRR_CNAME).Cname
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/net/dnsclient_unix_test.go b/third_party/gofrontend/libgo/go/net/dnsclient_unix_test.go
new file mode 100644
index 0000000..2350142
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dnsclient_unix_test.go
@@ -0,0 +1,159 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package net
+
+import (
+	"io"
+	"io/ioutil"
+	"os"
+	"path"
+	"reflect"
+	"testing"
+	"time"
+)
+
+func TestTCPLookup(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+	c, err := Dial("tcp", "8.8.8.8:53")
+	if err != nil {
+		t.Fatalf("Dial failed: %v", err)
+	}
+	defer c.Close()
+	cfg := &dnsConfig{timeout: 10, attempts: 3}
+	_, err = exchange(cfg, c, "com.", dnsTypeALL)
+	if err != nil {
+		t.Fatalf("exchange failed: %v", err)
+	}
+}
+
+type resolvConfTest struct {
+	*testing.T
+	dir     string
+	path    string
+	started bool
+	quitc   chan chan struct{}
+}
+
+func newResolvConfTest(t *testing.T) *resolvConfTest {
+	dir, err := ioutil.TempDir("", "resolvConfTest")
+	if err != nil {
+		t.Fatalf("could not create temp dir: %v", err)
+	}
+
+	// Disable the default loadConfig
+	onceLoadConfig.Do(func() {})
+
+	r := &resolvConfTest{
+		T:     t,
+		dir:   dir,
+		path:  path.Join(dir, "resolv.conf"),
+		quitc: make(chan chan struct{}),
+	}
+
+	return r
+}
+
+func (r *resolvConfTest) Start() {
+	loadConfig(r.path, 100*time.Millisecond, r.quitc)
+	r.started = true
+}
+
+func (r *resolvConfTest) SetConf(s string) {
+	// Make sure the file mtime will be different once we're done here,
+	// even on systems with coarse (1s) mtime resolution.
+	time.Sleep(time.Second)
+
+	f, err := os.OpenFile(r.path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
+	if err != nil {
+		r.Fatalf("failed to create temp file %s: %v", r.path, err)
+	}
+	if _, err := io.WriteString(f, s); err != nil {
+		f.Close()
+		r.Fatalf("failed to write temp file: %v", err)
+	}
+	f.Close()
+
+	if r.started {
+		cfg.ch <- struct{}{} // fill buffer
+		cfg.ch <- struct{}{} // wait for reload to begin
+		cfg.ch <- struct{}{} // wait for reload to complete
+	}
+}
+
+func (r *resolvConfTest) WantServers(want []string) {
+	cfg.mu.RLock()
+	defer cfg.mu.RUnlock()
+	if got := cfg.dnsConfig.servers; !reflect.DeepEqual(got, want) {
+		r.Fatalf("Unexpected dns server loaded, got %v want %v", got, want)
+	}
+}
+
+func (r *resolvConfTest) Close() {
+	resp := make(chan struct{})
+	r.quitc <- resp
+	<-resp
+	if err := os.RemoveAll(r.dir); err != nil {
+		r.Logf("failed to remove temp dir %s: %v", r.dir, err)
+	}
+}
+
+func TestReloadResolvConfFail(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	r := newResolvConfTest(t)
+	defer r.Close()
+
+	// resolv.conf.tmp does not exist yet
+	r.Start()
+	if _, err := goLookupIP("golang.org"); err == nil {
+		t.Fatal("goLookupIP(missing) succeeded")
+	}
+
+	r.SetConf("nameserver 8.8.8.8")
+	if _, err := goLookupIP("golang.org"); err != nil {
+		t.Fatalf("goLookupIP(missing; good) failed: %v", err)
+	}
+
+	// Using a bad resolv.conf while we had a good
+	// one before should not update the config
+	r.SetConf("")
+	if _, err := goLookupIP("golang.org"); err != nil {
+		t.Fatalf("goLookupIP(missing; good; bad) failed: %v", err)
+	}
+}
+
+func TestReloadResolvConfChange(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	r := newResolvConfTest(t)
+	defer r.Close()
+
+	r.SetConf("nameserver 8.8.8.8")
+	r.Start()
+
+	if _, err := goLookupIP("golang.org"); err != nil {
+		t.Fatalf("goLookupIP(good) failed: %v", err)
+	}
+	r.WantServers([]string{"[8.8.8.8]"})
+
+	// Using a bad resolv.conf when we had a good one
+	// before should not update the config
+	r.SetConf("")
+	if _, err := goLookupIP("golang.org"); err != nil {
+		t.Fatalf("goLookupIP(good; bad) failed: %v", err)
+	}
+
+	// A new good config should get picked up
+	r.SetConf("nameserver 8.8.4.4")
+	r.WantServers([]string{"[8.8.4.4]"})
+}
diff --git a/third_party/gofrontend/libgo/go/net/dnsconfig_unix.go b/third_party/gofrontend/libgo/go/net/dnsconfig_unix.go
new file mode 100644
index 0000000..db45716
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dnsconfig_unix.go
@@ -0,0 +1,109 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+// Read system DNS config from /etc/resolv.conf
+
+package net
+
+type dnsConfig struct {
+	servers  []string // servers to use
+	search   []string // suffixes to append to local name
+	ndots    int      // number of dots in name to trigger absolute lookup
+	timeout  int      // seconds before giving up on packet
+	attempts int      // lost packets before giving up on server
+	rotate   bool     // round robin among servers
+}
+
+// See resolv.conf(5) on a Linux machine.
+// TODO(rsc): Supposed to call uname() and chop the beginning
+// of the host name to get the default search domain.
+func dnsReadConfig(filename string) (*dnsConfig, error) {
+	file, err := open(filename)
+	if err != nil {
+		return nil, &DNSConfigError{err}
+	}
+	conf := new(dnsConfig)
+	conf.servers = make([]string, 0, 3) // small, but the standard limit
+	conf.search = make([]string, 0)
+	conf.ndots = 1
+	conf.timeout = 5
+	conf.attempts = 2
+	conf.rotate = false
+	for line, ok := file.readLine(); ok; line, ok = file.readLine() {
+		f := getFields(line)
+		if len(f) < 1 {
+			continue
+		}
+		switch f[0] {
+		case "nameserver": // add one name server
+			a := conf.servers
+			n := len(a)
+			if len(f) > 1 && n < cap(a) {
+				// One more check: make sure server name is
+				// just an IP address.  Otherwise we need DNS
+				// to look it up.
+				name := f[1]
+				switch len(ParseIP(name)) {
+				case 16:
+					name = "[" + name + "]"
+					fallthrough
+				case 4:
+					a = a[0 : n+1]
+					a[n] = name
+					conf.servers = a
+				}
+			}
+
+		case "domain": // set search path to just this domain
+			if len(f) > 1 {
+				conf.search = make([]string, 1)
+				conf.search[0] = f[1]
+			} else {
+				conf.search = make([]string, 0)
+			}
+
+		case "search": // set search path to given servers
+			conf.search = make([]string, len(f)-1)
+			for i := 0; i < len(conf.search); i++ {
+				conf.search[i] = f[i+1]
+			}
+
+		case "options": // magic options
+			for i := 1; i < len(f); i++ {
+				s := f[i]
+				switch {
+				case hasPrefix(s, "ndots:"):
+					n, _, _ := dtoi(s, 6)
+					if n < 1 {
+						n = 1
+					}
+					conf.ndots = n
+				case hasPrefix(s, "timeout:"):
+					n, _, _ := dtoi(s, 8)
+					if n < 1 {
+						n = 1
+					}
+					conf.timeout = n
+				case hasPrefix(s, "attempts:"):
+					n, _, _ := dtoi(s, 9)
+					if n < 1 {
+						n = 1
+					}
+					conf.attempts = n
+				case s == "rotate":
+					conf.rotate = true
+				}
+			}
+		}
+	}
+	file.close()
+
+	return conf, nil
+}
+
+func hasPrefix(s, prefix string) bool {
+	return len(s) >= len(prefix) && s[:len(prefix)] == prefix
+}
diff --git a/third_party/gofrontend/libgo/go/net/dnsconfig_unix_test.go b/third_party/gofrontend/libgo/go/net/dnsconfig_unix_test.go
new file mode 100644
index 0000000..37ed493
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dnsconfig_unix_test.go
@@ -0,0 +1,46 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package net
+
+import "testing"
+
+func TestDNSReadConfig(t *testing.T) {
+	dnsConfig, err := dnsReadConfig("testdata/resolv.conf")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if len(dnsConfig.servers) != 1 {
+		t.Errorf("len(dnsConfig.servers) = %d; want %d", len(dnsConfig.servers), 1)
+	}
+	if dnsConfig.servers[0] != "[192.168.1.1]" {
+		t.Errorf("dnsConfig.servers[0] = %s; want %s", dnsConfig.servers[0], "[192.168.1.1]")
+	}
+
+	if len(dnsConfig.search) != 1 {
+		t.Errorf("len(dnsConfig.search) = %d; want %d", len(dnsConfig.search), 1)
+	}
+	if dnsConfig.search[0] != "Home" {
+		t.Errorf("dnsConfig.search[0] = %s; want %s", dnsConfig.search[0], "Home")
+	}
+
+	if dnsConfig.ndots != 5 {
+		t.Errorf("dnsConfig.ndots = %d; want %d", dnsConfig.ndots, 5)
+	}
+
+	if dnsConfig.timeout != 10 {
+		t.Errorf("dnsConfig.timeout = %d; want %d", dnsConfig.timeout, 10)
+	}
+
+	if dnsConfig.attempts != 3 {
+		t.Errorf("dnsConfig.attempts = %d; want %d", dnsConfig.attempts, 3)
+	}
+
+	if dnsConfig.rotate != true {
+		t.Errorf("dnsConfig.rotate = %t; want %t", dnsConfig.rotate, true)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/dnsmsg.go b/third_party/gofrontend/libgo/go/net/dnsmsg.go
new file mode 100644
index 0000000..161afb2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dnsmsg.go
@@ -0,0 +1,887 @@
+// 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.
+
+// DNS packet assembly.  See RFC 1035.
+//
+// This is intended to support name resolution during Dial.
+// It doesn't have to be blazing fast.
+//
+// Each message structure has a Walk method that is used by
+// a generic pack/unpack routine. Thus, if in the future we need
+// to define new message structs, no new pack/unpack/printing code
+// needs to be written.
+//
+// The first half of this file defines the DNS message formats.
+// The second half implements the conversion to and from wire format.
+// A few of the structure elements have string tags to aid the
+// generic pack/unpack routines.
+//
+// TODO(rsc):  There are enough names defined in this file that they're all
+// prefixed with dns.  Perhaps put this in its own package later.
+
+package net
+
+// Packet formats
+
+// Wire constants.
+const (
+	// valid dnsRR_Header.Rrtype and dnsQuestion.qtype
+	dnsTypeA     = 1
+	dnsTypeNS    = 2
+	dnsTypeMD    = 3
+	dnsTypeMF    = 4
+	dnsTypeCNAME = 5
+	dnsTypeSOA   = 6
+	dnsTypeMB    = 7
+	dnsTypeMG    = 8
+	dnsTypeMR    = 9
+	dnsTypeNULL  = 10
+	dnsTypeWKS   = 11
+	dnsTypePTR   = 12
+	dnsTypeHINFO = 13
+	dnsTypeMINFO = 14
+	dnsTypeMX    = 15
+	dnsTypeTXT   = 16
+	dnsTypeAAAA  = 28
+	dnsTypeSRV   = 33
+
+	// valid dnsQuestion.qtype only
+	dnsTypeAXFR  = 252
+	dnsTypeMAILB = 253
+	dnsTypeMAILA = 254
+	dnsTypeALL   = 255
+
+	// valid dnsQuestion.qclass
+	dnsClassINET   = 1
+	dnsClassCSNET  = 2
+	dnsClassCHAOS  = 3
+	dnsClassHESIOD = 4
+	dnsClassANY    = 255
+
+	// dnsMsg.rcode
+	dnsRcodeSuccess        = 0
+	dnsRcodeFormatError    = 1
+	dnsRcodeServerFailure  = 2
+	dnsRcodeNameError      = 3
+	dnsRcodeNotImplemented = 4
+	dnsRcodeRefused        = 5
+)
+
+// A dnsStruct describes how to iterate over its fields to emulate
+// reflective marshalling.
+type dnsStruct interface {
+	// Walk iterates over fields of a structure and calls f
+	// with a reference to that field, the name of the field
+	// and a tag ("", "domain", "ipv4", "ipv6") specifying
+	// particular encodings. Possible concrete types
+	// for v are *uint16, *uint32, *string, or []byte, and
+	// *int, *bool in the case of dnsMsgHdr.
+	// Whenever f returns false, Walk must stop and return
+	// false, and otherwise return true.
+	Walk(f func(v interface{}, name, tag string) (ok bool)) (ok bool)
+}
+
+// The wire format for the DNS packet header.
+type dnsHeader struct {
+	Id                                 uint16
+	Bits                               uint16
+	Qdcount, Ancount, Nscount, Arcount uint16
+}
+
+func (h *dnsHeader) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return f(&h.Id, "Id", "") &&
+		f(&h.Bits, "Bits", "") &&
+		f(&h.Qdcount, "Qdcount", "") &&
+		f(&h.Ancount, "Ancount", "") &&
+		f(&h.Nscount, "Nscount", "") &&
+		f(&h.Arcount, "Arcount", "")
+}
+
+const (
+	// dnsHeader.Bits
+	_QR = 1 << 15 // query/response (response=1)
+	_AA = 1 << 10 // authoritative
+	_TC = 1 << 9  // truncated
+	_RD = 1 << 8  // recursion desired
+	_RA = 1 << 7  // recursion available
+)
+
+// DNS queries.
+type dnsQuestion struct {
+	Name   string `net:"domain-name"` // `net:"domain-name"` specifies encoding; see packers below
+	Qtype  uint16
+	Qclass uint16
+}
+
+func (q *dnsQuestion) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return f(&q.Name, "Name", "domain") &&
+		f(&q.Qtype, "Qtype", "") &&
+		f(&q.Qclass, "Qclass", "")
+}
+
+// DNS responses (resource records).
+// There are many types of messages,
+// but they all share the same header.
+type dnsRR_Header struct {
+	Name     string `net:"domain-name"`
+	Rrtype   uint16
+	Class    uint16
+	Ttl      uint32
+	Rdlength uint16 // length of data after header
+}
+
+func (h *dnsRR_Header) Header() *dnsRR_Header {
+	return h
+}
+
+func (h *dnsRR_Header) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return f(&h.Name, "Name", "domain") &&
+		f(&h.Rrtype, "Rrtype", "") &&
+		f(&h.Class, "Class", "") &&
+		f(&h.Ttl, "Ttl", "") &&
+		f(&h.Rdlength, "Rdlength", "")
+}
+
+type dnsRR interface {
+	dnsStruct
+	Header() *dnsRR_Header
+}
+
+// Specific DNS RR formats for each query type.
+
+type dnsRR_CNAME struct {
+	Hdr   dnsRR_Header
+	Cname string `net:"domain-name"`
+}
+
+func (rr *dnsRR_CNAME) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_CNAME) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.Cname, "Cname", "domain")
+}
+
+type dnsRR_HINFO struct {
+	Hdr dnsRR_Header
+	Cpu string
+	Os  string
+}
+
+func (rr *dnsRR_HINFO) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_HINFO) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.Cpu, "Cpu", "") && f(&rr.Os, "Os", "")
+}
+
+type dnsRR_MB struct {
+	Hdr dnsRR_Header
+	Mb  string `net:"domain-name"`
+}
+
+func (rr *dnsRR_MB) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_MB) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.Mb, "Mb", "domain")
+}
+
+type dnsRR_MG struct {
+	Hdr dnsRR_Header
+	Mg  string `net:"domain-name"`
+}
+
+func (rr *dnsRR_MG) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_MG) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.Mg, "Mg", "domain")
+}
+
+type dnsRR_MINFO struct {
+	Hdr   dnsRR_Header
+	Rmail string `net:"domain-name"`
+	Email string `net:"domain-name"`
+}
+
+func (rr *dnsRR_MINFO) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_MINFO) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.Rmail, "Rmail", "domain") && f(&rr.Email, "Email", "domain")
+}
+
+type dnsRR_MR struct {
+	Hdr dnsRR_Header
+	Mr  string `net:"domain-name"`
+}
+
+func (rr *dnsRR_MR) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_MR) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.Mr, "Mr", "domain")
+}
+
+type dnsRR_MX struct {
+	Hdr  dnsRR_Header
+	Pref uint16
+	Mx   string `net:"domain-name"`
+}
+
+func (rr *dnsRR_MX) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_MX) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.Pref, "Pref", "") && f(&rr.Mx, "Mx", "domain")
+}
+
+type dnsRR_NS struct {
+	Hdr dnsRR_Header
+	Ns  string `net:"domain-name"`
+}
+
+func (rr *dnsRR_NS) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_NS) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.Ns, "Ns", "domain")
+}
+
+type dnsRR_PTR struct {
+	Hdr dnsRR_Header
+	Ptr string `net:"domain-name"`
+}
+
+func (rr *dnsRR_PTR) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_PTR) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.Ptr, "Ptr", "domain")
+}
+
+type dnsRR_SOA struct {
+	Hdr     dnsRR_Header
+	Ns      string `net:"domain-name"`
+	Mbox    string `net:"domain-name"`
+	Serial  uint32
+	Refresh uint32
+	Retry   uint32
+	Expire  uint32
+	Minttl  uint32
+}
+
+func (rr *dnsRR_SOA) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_SOA) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) &&
+		f(&rr.Ns, "Ns", "domain") &&
+		f(&rr.Mbox, "Mbox", "domain") &&
+		f(&rr.Serial, "Serial", "") &&
+		f(&rr.Refresh, "Refresh", "") &&
+		f(&rr.Retry, "Retry", "") &&
+		f(&rr.Expire, "Expire", "") &&
+		f(&rr.Minttl, "Minttl", "")
+}
+
+type dnsRR_TXT struct {
+	Hdr dnsRR_Header
+	Txt string // not domain name
+}
+
+func (rr *dnsRR_TXT) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_TXT) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.Txt, "Txt", "")
+}
+
+type dnsRR_SRV struct {
+	Hdr      dnsRR_Header
+	Priority uint16
+	Weight   uint16
+	Port     uint16
+	Target   string `net:"domain-name"`
+}
+
+func (rr *dnsRR_SRV) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_SRV) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) &&
+		f(&rr.Priority, "Priority", "") &&
+		f(&rr.Weight, "Weight", "") &&
+		f(&rr.Port, "Port", "") &&
+		f(&rr.Target, "Target", "domain")
+}
+
+type dnsRR_A struct {
+	Hdr dnsRR_Header
+	A   uint32 `net:"ipv4"`
+}
+
+func (rr *dnsRR_A) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_A) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(&rr.A, "A", "ipv4")
+}
+
+type dnsRR_AAAA struct {
+	Hdr  dnsRR_Header
+	AAAA [16]byte `net:"ipv6"`
+}
+
+func (rr *dnsRR_AAAA) Header() *dnsRR_Header {
+	return &rr.Hdr
+}
+
+func (rr *dnsRR_AAAA) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return rr.Hdr.Walk(f) && f(rr.AAAA[:], "AAAA", "ipv6")
+}
+
+// Packing and unpacking.
+//
+// All the packers and unpackers take a (msg []byte, off int)
+// and return (off1 int, ok bool).  If they return ok==false, they
+// also return off1==len(msg), so that the next unpacker will
+// also fail.  This lets us avoid checks of ok until the end of a
+// packing sequence.
+
+// Map of constructors for each RR wire type.
+var rr_mk = map[int]func() dnsRR{
+	dnsTypeCNAME: func() dnsRR { return new(dnsRR_CNAME) },
+	dnsTypeHINFO: func() dnsRR { return new(dnsRR_HINFO) },
+	dnsTypeMB:    func() dnsRR { return new(dnsRR_MB) },
+	dnsTypeMG:    func() dnsRR { return new(dnsRR_MG) },
+	dnsTypeMINFO: func() dnsRR { return new(dnsRR_MINFO) },
+	dnsTypeMR:    func() dnsRR { return new(dnsRR_MR) },
+	dnsTypeMX:    func() dnsRR { return new(dnsRR_MX) },
+	dnsTypeNS:    func() dnsRR { return new(dnsRR_NS) },
+	dnsTypePTR:   func() dnsRR { return new(dnsRR_PTR) },
+	dnsTypeSOA:   func() dnsRR { return new(dnsRR_SOA) },
+	dnsTypeTXT:   func() dnsRR { return new(dnsRR_TXT) },
+	dnsTypeSRV:   func() dnsRR { return new(dnsRR_SRV) },
+	dnsTypeA:     func() dnsRR { return new(dnsRR_A) },
+	dnsTypeAAAA:  func() dnsRR { return new(dnsRR_AAAA) },
+}
+
+// Pack a domain name s into msg[off:].
+// Domain names are a sequence of counted strings
+// split at the dots.  They end with a zero-length string.
+func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
+	// Add trailing dot to canonicalize name.
+	if n := len(s); n == 0 || s[n-1] != '.' {
+		s += "."
+	}
+
+	// Each dot ends a segment of the name.
+	// We trade each dot byte for a length byte.
+	// There is also a trailing zero.
+	// Check that we have all the space we need.
+	tot := len(s) + 1
+	if off+tot > len(msg) {
+		return len(msg), false
+	}
+
+	// Emit sequence of counted strings, chopping at dots.
+	begin := 0
+	for i := 0; i < len(s); i++ {
+		if s[i] == '.' {
+			if i-begin >= 1<<6 { // top two bits of length must be clear
+				return len(msg), false
+			}
+			msg[off] = byte(i - begin)
+			off++
+			for j := begin; j < i; j++ {
+				msg[off] = s[j]
+				off++
+			}
+			begin = i + 1
+		}
+	}
+	msg[off] = 0
+	off++
+	return off, true
+}
+
+// Unpack a domain name.
+// In addition to the simple sequences of counted strings above,
+// domain names are allowed to refer to strings elsewhere in the
+// packet, to avoid repeating common suffixes when returning
+// many entries in a single domain.  The pointers are marked
+// by a length byte with the top two bits set.  Ignoring those
+// two bits, that byte and the next give a 14 bit offset from msg[0]
+// where we should pick up the trail.
+// Note that if we jump elsewhere in the packet,
+// we return off1 == the offset after the first pointer we found,
+// which is where the next record will start.
+// In theory, the pointers are only allowed to jump backward.
+// We let them jump anywhere and stop jumping after a while.
+func unpackDomainName(msg []byte, off int) (s string, off1 int, ok bool) {
+	s = ""
+	ptr := 0 // number of pointers followed
+Loop:
+	for {
+		if off >= len(msg) {
+			return "", len(msg), false
+		}
+		c := int(msg[off])
+		off++
+		switch c & 0xC0 {
+		case 0x00:
+			if c == 0x00 {
+				// end of name
+				break Loop
+			}
+			// literal string
+			if off+c > len(msg) {
+				return "", len(msg), false
+			}
+			s += string(msg[off:off+c]) + "."
+			off += c
+		case 0xC0:
+			// pointer to somewhere else in msg.
+			// remember location after first ptr,
+			// since that's how many bytes we consumed.
+			// also, don't follow too many pointers --
+			// maybe there's a loop.
+			if off >= len(msg) {
+				return "", len(msg), false
+			}
+			c1 := msg[off]
+			off++
+			if ptr == 0 {
+				off1 = off
+			}
+			if ptr++; ptr > 10 {
+				return "", len(msg), false
+			}
+			off = (c^0xC0)<<8 | int(c1)
+		default:
+			// 0x80 and 0x40 are reserved
+			return "", len(msg), false
+		}
+	}
+	if ptr == 0 {
+		off1 = off
+	}
+	return s, off1, true
+}
+
+// packStruct packs a structure into msg at specified offset off, and
+// returns off1 such that msg[off:off1] is the encoded data.
+func packStruct(any dnsStruct, msg []byte, off int) (off1 int, ok bool) {
+	ok = any.Walk(func(field interface{}, name, tag string) bool {
+		switch fv := field.(type) {
+		default:
+			println("net: dns: unknown packing type")
+			return false
+		case *uint16:
+			i := *fv
+			if off+2 > len(msg) {
+				return false
+			}
+			msg[off] = byte(i >> 8)
+			msg[off+1] = byte(i)
+			off += 2
+		case *uint32:
+			i := *fv
+			msg[off] = byte(i >> 24)
+			msg[off+1] = byte(i >> 16)
+			msg[off+2] = byte(i >> 8)
+			msg[off+3] = byte(i)
+			off += 4
+		case []byte:
+			n := len(fv)
+			if off+n > len(msg) {
+				return false
+			}
+			copy(msg[off:off+n], fv)
+			off += n
+		case *string:
+			s := *fv
+			switch tag {
+			default:
+				println("net: dns: unknown string tag", tag)
+				return false
+			case "domain":
+				off, ok = packDomainName(s, msg, off)
+				if !ok {
+					return false
+				}
+			case "":
+				// Counted string: 1 byte length.
+				if len(s) > 255 || off+1+len(s) > len(msg) {
+					return false
+				}
+				msg[off] = byte(len(s))
+				off++
+				off += copy(msg[off:], s)
+			}
+		}
+		return true
+	})
+	if !ok {
+		return len(msg), false
+	}
+	return off, true
+}
+
+// unpackStruct decodes msg[off:] into the given structure, and
+// returns off1 such that msg[off:off1] is the encoded data.
+func unpackStruct(any dnsStruct, msg []byte, off int) (off1 int, ok bool) {
+	ok = any.Walk(func(field interface{}, name, tag string) bool {
+		switch fv := field.(type) {
+		default:
+			println("net: dns: unknown packing type")
+			return false
+		case *uint16:
+			if off+2 > len(msg) {
+				return false
+			}
+			*fv = uint16(msg[off])<<8 | uint16(msg[off+1])
+			off += 2
+		case *uint32:
+			if off+4 > len(msg) {
+				return false
+			}
+			*fv = uint32(msg[off])<<24 | uint32(msg[off+1])<<16 |
+				uint32(msg[off+2])<<8 | uint32(msg[off+3])
+			off += 4
+		case []byte:
+			n := len(fv)
+			if off+n > len(msg) {
+				return false
+			}
+			copy(fv, msg[off:off+n])
+			off += n
+		case *string:
+			var s string
+			switch tag {
+			default:
+				println("net: dns: unknown string tag", tag)
+				return false
+			case "domain":
+				s, off, ok = unpackDomainName(msg, off)
+				if !ok {
+					return false
+				}
+			case "":
+				if off >= len(msg) || off+1+int(msg[off]) > len(msg) {
+					return false
+				}
+				n := int(msg[off])
+				off++
+				b := make([]byte, n)
+				for i := 0; i < n; i++ {
+					b[i] = msg[off+i]
+				}
+				off += n
+				s = string(b)
+			}
+			*fv = s
+		}
+		return true
+	})
+	if !ok {
+		return len(msg), false
+	}
+	return off, true
+}
+
+// Generic struct printer. Prints fields with tag "ipv4" or "ipv6"
+// as IP addresses.
+func printStruct(any dnsStruct) string {
+	s := "{"
+	i := 0
+	any.Walk(func(val interface{}, name, tag string) bool {
+		i++
+		if i > 1 {
+			s += ", "
+		}
+		s += name + "="
+		switch tag {
+		case "ipv4":
+			i := *val.(*uint32)
+			s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String()
+		case "ipv6":
+			i := val.([]byte)
+			s += IP(i).String()
+		default:
+			var i int64
+			switch v := val.(type) {
+			default:
+				// can't really happen.
+				s += "<unknown type>"
+				return true
+			case *string:
+				s += *v
+				return true
+			case []byte:
+				s += string(v)
+				return true
+			case *bool:
+				if *v {
+					s += "true"
+				} else {
+					s += "false"
+				}
+				return true
+			case *int:
+				i = int64(*v)
+			case *uint:
+				i = int64(*v)
+			case *uint8:
+				i = int64(*v)
+			case *uint16:
+				i = int64(*v)
+			case *uint32:
+				i = int64(*v)
+			case *uint64:
+				i = int64(*v)
+			case *uintptr:
+				i = int64(*v)
+			}
+			s += itoa(int(i))
+		}
+		return true
+	})
+	s += "}"
+	return s
+}
+
+// Resource record packer.
+func packRR(rr dnsRR, msg []byte, off int) (off2 int, ok bool) {
+	var off1 int
+	// pack twice, once to find end of header
+	// and again to find end of packet.
+	// a bit inefficient but this doesn't need to be fast.
+	// off1 is end of header
+	// off2 is end of rr
+	off1, ok = packStruct(rr.Header(), msg, off)
+	off2, ok = packStruct(rr, msg, off)
+	if !ok {
+		return len(msg), false
+	}
+	// pack a third time; redo header with correct data length
+	rr.Header().Rdlength = uint16(off2 - off1)
+	packStruct(rr.Header(), msg, off)
+	return off2, true
+}
+
+// Resource record unpacker.
+func unpackRR(msg []byte, off int) (rr dnsRR, off1 int, ok bool) {
+	// unpack just the header, to find the rr type and length
+	var h dnsRR_Header
+	off0 := off
+	if off, ok = unpackStruct(&h, msg, off); !ok {
+		return nil, len(msg), false
+	}
+	end := off + int(h.Rdlength)
+
+	// make an rr of that type and re-unpack.
+	// again inefficient but doesn't need to be fast.
+	mk, known := rr_mk[int(h.Rrtype)]
+	if !known {
+		return &h, end, true
+	}
+	rr = mk()
+	off, ok = unpackStruct(rr, msg, off0)
+	if off != end {
+		return &h, end, true
+	}
+	return rr, off, ok
+}
+
+// Usable representation of a DNS packet.
+
+// A manually-unpacked version of (id, bits).
+// This is in its own struct for easy printing.
+type dnsMsgHdr struct {
+	id                  uint16
+	response            bool
+	opcode              int
+	authoritative       bool
+	truncated           bool
+	recursion_desired   bool
+	recursion_available bool
+	rcode               int
+}
+
+func (h *dnsMsgHdr) Walk(f func(v interface{}, name, tag string) bool) bool {
+	return f(&h.id, "id", "") &&
+		f(&h.response, "response", "") &&
+		f(&h.opcode, "opcode", "") &&
+		f(&h.authoritative, "authoritative", "") &&
+		f(&h.truncated, "truncated", "") &&
+		f(&h.recursion_desired, "recursion_desired", "") &&
+		f(&h.recursion_available, "recursion_available", "") &&
+		f(&h.rcode, "rcode", "")
+}
+
+type dnsMsg struct {
+	dnsMsgHdr
+	question []dnsQuestion
+	answer   []dnsRR
+	ns       []dnsRR
+	extra    []dnsRR
+}
+
+func (dns *dnsMsg) Pack() (msg []byte, ok bool) {
+	var dh dnsHeader
+
+	// Convert convenient dnsMsg into wire-like dnsHeader.
+	dh.Id = dns.id
+	dh.Bits = uint16(dns.opcode)<<11 | uint16(dns.rcode)
+	if dns.recursion_available {
+		dh.Bits |= _RA
+	}
+	if dns.recursion_desired {
+		dh.Bits |= _RD
+	}
+	if dns.truncated {
+		dh.Bits |= _TC
+	}
+	if dns.authoritative {
+		dh.Bits |= _AA
+	}
+	if dns.response {
+		dh.Bits |= _QR
+	}
+
+	// Prepare variable sized arrays.
+	question := dns.question
+	answer := dns.answer
+	ns := dns.ns
+	extra := dns.extra
+
+	dh.Qdcount = uint16(len(question))
+	dh.Ancount = uint16(len(answer))
+	dh.Nscount = uint16(len(ns))
+	dh.Arcount = uint16(len(extra))
+
+	// Could work harder to calculate message size,
+	// but this is far more than we need and not
+	// big enough to hurt the allocator.
+	msg = make([]byte, 2000)
+
+	// Pack it in: header and then the pieces.
+	off := 0
+	off, ok = packStruct(&dh, msg, off)
+	for i := 0; i < len(question); i++ {
+		off, ok = packStruct(&question[i], msg, off)
+	}
+	for i := 0; i < len(answer); i++ {
+		off, ok = packRR(answer[i], msg, off)
+	}
+	for i := 0; i < len(ns); i++ {
+		off, ok = packRR(ns[i], msg, off)
+	}
+	for i := 0; i < len(extra); i++ {
+		off, ok = packRR(extra[i], msg, off)
+	}
+	if !ok {
+		return nil, false
+	}
+	return msg[0:off], true
+}
+
+func (dns *dnsMsg) Unpack(msg []byte) bool {
+	// Header.
+	var dh dnsHeader
+	off := 0
+	var ok bool
+	if off, ok = unpackStruct(&dh, msg, off); !ok {
+		return false
+	}
+	dns.id = dh.Id
+	dns.response = (dh.Bits & _QR) != 0
+	dns.opcode = int(dh.Bits>>11) & 0xF
+	dns.authoritative = (dh.Bits & _AA) != 0
+	dns.truncated = (dh.Bits & _TC) != 0
+	dns.recursion_desired = (dh.Bits & _RD) != 0
+	dns.recursion_available = (dh.Bits & _RA) != 0
+	dns.rcode = int(dh.Bits & 0xF)
+
+	// Arrays.
+	dns.question = make([]dnsQuestion, dh.Qdcount)
+	dns.answer = make([]dnsRR, 0, dh.Ancount)
+	dns.ns = make([]dnsRR, 0, dh.Nscount)
+	dns.extra = make([]dnsRR, 0, dh.Arcount)
+
+	var rec dnsRR
+
+	for i := 0; i < len(dns.question); i++ {
+		off, ok = unpackStruct(&dns.question[i], msg, off)
+	}
+	for i := 0; i < int(dh.Ancount); i++ {
+		rec, off, ok = unpackRR(msg, off)
+		if !ok {
+			return false
+		}
+		dns.answer = append(dns.answer, rec)
+	}
+	for i := 0; i < int(dh.Nscount); i++ {
+		rec, off, ok = unpackRR(msg, off)
+		if !ok {
+			return false
+		}
+		dns.ns = append(dns.ns, rec)
+	}
+	for i := 0; i < int(dh.Arcount); i++ {
+		rec, off, ok = unpackRR(msg, off)
+		if !ok {
+			return false
+		}
+		dns.extra = append(dns.extra, rec)
+	}
+	//	if off != len(msg) {
+	//		println("extra bytes in dns packet", off, "<", len(msg));
+	//	}
+	return true
+}
+
+func (dns *dnsMsg) String() string {
+	s := "DNS: " + printStruct(&dns.dnsMsgHdr) + "\n"
+	if len(dns.question) > 0 {
+		s += "-- Questions\n"
+		for i := 0; i < len(dns.question); i++ {
+			s += printStruct(&dns.question[i]) + "\n"
+		}
+	}
+	if len(dns.answer) > 0 {
+		s += "-- Answers\n"
+		for i := 0; i < len(dns.answer); i++ {
+			s += printStruct(dns.answer[i]) + "\n"
+		}
+	}
+	if len(dns.ns) > 0 {
+		s += "-- Name servers\n"
+		for i := 0; i < len(dns.ns); i++ {
+			s += printStruct(dns.ns[i]) + "\n"
+		}
+	}
+	if len(dns.extra) > 0 {
+		s += "-- Extra\n"
+		for i := 0; i < len(dns.extra); i++ {
+			s += printStruct(dns.extra[i]) + "\n"
+		}
+	}
+	return s
+}
diff --git a/third_party/gofrontend/libgo/go/net/dnsmsg_test.go b/third_party/gofrontend/libgo/go/net/dnsmsg_test.go
new file mode 100644
index 0000000..c39dbdb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dnsmsg_test.go
@@ -0,0 +1,113 @@
+// 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.
+
+package net
+
+import (
+	"encoding/hex"
+	"reflect"
+	"testing"
+)
+
+func TestDNSParseSRVReply(t *testing.T) {
+	data, err := hex.DecodeString(dnsSRVReply)
+	if err != nil {
+		t.Fatal(err)
+	}
+	msg := new(dnsMsg)
+	ok := msg.Unpack(data)
+	if !ok {
+		t.Fatalf("unpacking packet failed")
+	}
+	msg.String() // exercise this code path
+	if g, e := len(msg.answer), 5; g != e {
+		t.Errorf("len(msg.answer) = %d; want %d", g, e)
+	}
+	for idx, rr := range msg.answer {
+		if g, e := rr.Header().Rrtype, uint16(dnsTypeSRV); g != e {
+			t.Errorf("rr[%d].Header().Rrtype = %d; want %d", idx, g, e)
+		}
+		if _, ok := rr.(*dnsRR_SRV); !ok {
+			t.Errorf("answer[%d] = %T; want *dnsRR_SRV", idx, rr)
+		}
+	}
+	_, addrs, err := answer("_xmpp-server._tcp.google.com.", "foo:53", msg, uint16(dnsTypeSRV))
+	if err != nil {
+		t.Fatalf("answer: %v", err)
+	}
+	if g, e := len(addrs), 5; g != e {
+		t.Errorf("len(addrs) = %d; want %d", g, e)
+		t.Logf("addrs = %#v", addrs)
+	}
+	// repack and unpack.
+	data2, ok := msg.Pack()
+	msg2 := new(dnsMsg)
+	msg2.Unpack(data2)
+	switch {
+	case !ok:
+		t.Errorf("failed to repack message")
+	case !reflect.DeepEqual(msg, msg2):
+		t.Errorf("repacked message differs from original")
+	}
+}
+
+func TestDNSParseCorruptSRVReply(t *testing.T) {
+	data, err := hex.DecodeString(dnsSRVCorruptReply)
+	if err != nil {
+		t.Fatal(err)
+	}
+	msg := new(dnsMsg)
+	ok := msg.Unpack(data)
+	if !ok {
+		t.Fatalf("unpacking packet failed")
+	}
+	msg.String() // exercise this code path
+	if g, e := len(msg.answer), 5; g != e {
+		t.Errorf("len(msg.answer) = %d; want %d", g, e)
+	}
+	for idx, rr := range msg.answer {
+		if g, e := rr.Header().Rrtype, uint16(dnsTypeSRV); g != e {
+			t.Errorf("rr[%d].Header().Rrtype = %d; want %d", idx, g, e)
+		}
+		if idx == 4 {
+			if _, ok := rr.(*dnsRR_Header); !ok {
+				t.Errorf("answer[%d] = %T; want *dnsRR_Header", idx, rr)
+			}
+		} else {
+			if _, ok := rr.(*dnsRR_SRV); !ok {
+				t.Errorf("answer[%d] = %T; want *dnsRR_SRV", idx, rr)
+			}
+		}
+	}
+	_, addrs, err := answer("_xmpp-server._tcp.google.com.", "foo:53", msg, uint16(dnsTypeSRV))
+	if err != nil {
+		t.Fatalf("answer: %v", err)
+	}
+	if g, e := len(addrs), 4; g != e {
+		t.Errorf("len(addrs) = %d; want %d", g, e)
+		t.Logf("addrs = %#v", addrs)
+	}
+}
+
+// Valid DNS SRV reply
+const dnsSRVReply = "0901818000010005000000000c5f786d70702d736572766572045f74637006676f6f67" +
+	"6c6503636f6d0000210001c00c002100010000012c00210014000014950c786d70702d" +
+	"73657276657234016c06676f6f676c6503636f6d00c00c002100010000012c00210014" +
+	"000014950c786d70702d73657276657232016c06676f6f676c6503636f6d00c00c0021" +
+	"00010000012c00210014000014950c786d70702d73657276657233016c06676f6f676c" +
+	"6503636f6d00c00c002100010000012c00200005000014950b786d70702d7365727665" +
+	"72016c06676f6f676c6503636f6d00c00c002100010000012c00210014000014950c78" +
+	"6d70702d73657276657231016c06676f6f676c6503636f6d00"
+
+// Corrupt DNS SRV reply, with its final RR having a bogus length
+// (perhaps it was truncated, or it's malicious) The mutation is the
+// capital "FF" below, instead of the proper "21".
+const dnsSRVCorruptReply = "0901818000010005000000000c5f786d70702d736572766572045f74637006676f6f67" +
+	"6c6503636f6d0000210001c00c002100010000012c00210014000014950c786d70702d" +
+	"73657276657234016c06676f6f676c6503636f6d00c00c002100010000012c00210014" +
+	"000014950c786d70702d73657276657232016c06676f6f676c6503636f6d00c00c0021" +
+	"00010000012c00210014000014950c786d70702d73657276657233016c06676f6f676c" +
+	"6503636f6d00c00c002100010000012c00200005000014950b786d70702d7365727665" +
+	"72016c06676f6f676c6503636f6d00c00c002100010000012c00FF0014000014950c78" +
+	"6d70702d73657276657231016c06676f6f676c6503636f6d00"
diff --git a/third_party/gofrontend/libgo/go/net/dnsname_test.go b/third_party/gofrontend/libgo/go/net/dnsname_test.go
new file mode 100644
index 0000000..57dd25f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/dnsname_test.go
@@ -0,0 +1,83 @@
+// 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 net
+
+import (
+	"strings"
+	"testing"
+)
+
+type testCase struct {
+	name   string
+	result bool
+}
+
+var tests = []testCase{
+	// RFC2181, section 11.
+	{"_xmpp-server._tcp.google.com", true},
+	{"foo.com", true},
+	{"1foo.com", true},
+	{"26.0.0.73.com", true},
+	{"fo-o.com", true},
+	{"fo1o.com", true},
+	{"foo1.com", true},
+	{"a.b..com", false},
+	{"a.b-.com", false},
+	{"a.b.com-", false},
+	{"a.b..", false},
+	{"b.com.", true},
+}
+
+func getTestCases(ch chan<- testCase) {
+	defer close(ch)
+	var char59 = ""
+	var char63 = ""
+	var char64 = ""
+	for i := 0; i < 59; i++ {
+		char59 += "a"
+	}
+	char63 = char59 + "aaaa"
+	char64 = char63 + "a"
+
+	for _, tc := range tests {
+		ch <- tc
+	}
+
+	ch <- testCase{char63 + ".com", true}
+	ch <- testCase{char64 + ".com", false}
+	// 255 char name is fine:
+	ch <- testCase{char59 + "." + char63 + "." + char63 + "." +
+		char63 + ".com",
+		true}
+	// 256 char name is bad:
+	ch <- testCase{char59 + "a." + char63 + "." + char63 + "." +
+		char63 + ".com",
+		false}
+}
+
+func TestDNSNames(t *testing.T) {
+	ch := make(chan testCase)
+	go getTestCases(ch)
+	for tc := range ch {
+		if isDomainName(tc.name) != tc.result {
+			t.Errorf("isDomainName(%v) failed: Should be %v",
+				tc.name, tc.result)
+		}
+	}
+}
+
+func BenchmarkDNSNames(b *testing.B) {
+	benchmarks := append(tests, []testCase{
+		{strings.Repeat("a", 63), true},
+		{strings.Repeat("a", 64), false},
+	}...)
+	for n := 0; n < b.N; n++ {
+		for _, tc := range benchmarks {
+			if isDomainName(tc.name) != tc.result {
+				b.Errorf("isDomainName(%q) = %v; want %v", tc.name, !tc.result, tc.result)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/fd_mutex.go b/third_party/gofrontend/libgo/go/net/fd_mutex.go
new file mode 100644
index 0000000..6d5509d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/fd_mutex.go
@@ -0,0 +1,184 @@
+// Copyright 2013 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 net
+
+import "sync/atomic"
+
+// fdMutex is a specialized synchronization primitive
+// that manages lifetime of an fd and serializes access
+// to Read and Write methods on netFD.
+type fdMutex struct {
+	state uint64
+	rsema uint32
+	wsema uint32
+}
+
+// fdMutex.state is organized as follows:
+// 1 bit - whether netFD is closed, if set all subsequent lock operations will fail.
+// 1 bit - lock for read operations.
+// 1 bit - lock for write operations.
+// 20 bits - total number of references (read+write+misc).
+// 20 bits - number of outstanding read waiters.
+// 20 bits - number of outstanding write waiters.
+const (
+	mutexClosed  = 1 << 0
+	mutexRLock   = 1 << 1
+	mutexWLock   = 1 << 2
+	mutexRef     = 1 << 3
+	mutexRefMask = (1<<20 - 1) << 3
+	mutexRWait   = 1 << 23
+	mutexRMask   = (1<<20 - 1) << 23
+	mutexWWait   = 1 << 43
+	mutexWMask   = (1<<20 - 1) << 43
+)
+
+// Read operations must do RWLock(true)/RWUnlock(true).
+// Write operations must do RWLock(false)/RWUnlock(false).
+// Misc operations must do Incref/Decref. Misc operations include functions like
+// setsockopt and setDeadline. They need to use Incref/Decref to ensure that
+// they operate on the correct fd in presence of a concurrent Close call
+// (otherwise fd can be closed under their feet).
+// Close operation must do IncrefAndClose/Decref.
+
+// RWLock/Incref return whether fd is open.
+// RWUnlock/Decref return whether fd is closed and there are no remaining references.
+
+func (mu *fdMutex) Incref() bool {
+	for {
+		old := atomic.LoadUint64(&mu.state)
+		if old&mutexClosed != 0 {
+			return false
+		}
+		new := old + mutexRef
+		if new&mutexRefMask == 0 {
+			panic("net: inconsistent fdMutex")
+		}
+		if atomic.CompareAndSwapUint64(&mu.state, old, new) {
+			return true
+		}
+	}
+}
+
+func (mu *fdMutex) IncrefAndClose() bool {
+	for {
+		old := atomic.LoadUint64(&mu.state)
+		if old&mutexClosed != 0 {
+			return false
+		}
+		// Mark as closed and acquire a reference.
+		new := (old | mutexClosed) + mutexRef
+		if new&mutexRefMask == 0 {
+			panic("net: inconsistent fdMutex")
+		}
+		// Remove all read and write waiters.
+		new &^= mutexRMask | mutexWMask
+		if atomic.CompareAndSwapUint64(&mu.state, old, new) {
+			// Wake all read and write waiters,
+			// they will observe closed flag after wakeup.
+			for old&mutexRMask != 0 {
+				old -= mutexRWait
+				runtime_Semrelease(&mu.rsema)
+			}
+			for old&mutexWMask != 0 {
+				old -= mutexWWait
+				runtime_Semrelease(&mu.wsema)
+			}
+			return true
+		}
+	}
+}
+
+func (mu *fdMutex) Decref() bool {
+	for {
+		old := atomic.LoadUint64(&mu.state)
+		if old&mutexRefMask == 0 {
+			panic("net: inconsistent fdMutex")
+		}
+		new := old - mutexRef
+		if atomic.CompareAndSwapUint64(&mu.state, old, new) {
+			return new&(mutexClosed|mutexRefMask) == mutexClosed
+		}
+	}
+}
+
+func (mu *fdMutex) RWLock(read bool) bool {
+	var mutexBit, mutexWait, mutexMask uint64
+	var mutexSema *uint32
+	if read {
+		mutexBit = mutexRLock
+		mutexWait = mutexRWait
+		mutexMask = mutexRMask
+		mutexSema = &mu.rsema
+	} else {
+		mutexBit = mutexWLock
+		mutexWait = mutexWWait
+		mutexMask = mutexWMask
+		mutexSema = &mu.wsema
+	}
+	for {
+		old := atomic.LoadUint64(&mu.state)
+		if old&mutexClosed != 0 {
+			return false
+		}
+		var new uint64
+		if old&mutexBit == 0 {
+			// Lock is free, acquire it.
+			new = (old | mutexBit) + mutexRef
+			if new&mutexRefMask == 0 {
+				panic("net: inconsistent fdMutex")
+			}
+		} else {
+			// Wait for lock.
+			new = old + mutexWait
+			if new&mutexMask == 0 {
+				panic("net: inconsistent fdMutex")
+			}
+		}
+		if atomic.CompareAndSwapUint64(&mu.state, old, new) {
+			if old&mutexBit == 0 {
+				return true
+			}
+			runtime_Semacquire(mutexSema)
+			// The signaller has subtracted mutexWait.
+		}
+	}
+}
+
+func (mu *fdMutex) RWUnlock(read bool) bool {
+	var mutexBit, mutexWait, mutexMask uint64
+	var mutexSema *uint32
+	if read {
+		mutexBit = mutexRLock
+		mutexWait = mutexRWait
+		mutexMask = mutexRMask
+		mutexSema = &mu.rsema
+	} else {
+		mutexBit = mutexWLock
+		mutexWait = mutexWWait
+		mutexMask = mutexWMask
+		mutexSema = &mu.wsema
+	}
+	for {
+		old := atomic.LoadUint64(&mu.state)
+		if old&mutexBit == 0 || old&mutexRefMask == 0 {
+			panic("net: inconsistent fdMutex")
+		}
+		// Drop lock, drop reference and wake read waiter if present.
+		new := (old &^ mutexBit) - mutexRef
+		if old&mutexMask != 0 {
+			new -= mutexWait
+		}
+		if atomic.CompareAndSwapUint64(&mu.state, old, new) {
+			if old&mutexMask != 0 {
+				runtime_Semrelease(mutexSema)
+			}
+			return new&(mutexClosed|mutexRefMask) == mutexClosed
+		}
+	}
+}
+
+// Implemented in runtime package.
+func runtime_Semacquire(sema *uint32)
+func runtime_Semrelease(sema *uint32)
diff --git a/third_party/gofrontend/libgo/go/net/fd_mutex_test.go b/third_party/gofrontend/libgo/go/net/fd_mutex_test.go
new file mode 100644
index 0000000..c34ec59
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/fd_mutex_test.go
@@ -0,0 +1,195 @@
+// Copyright 2013 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 net
+
+import (
+	"math/rand"
+	"runtime"
+	"testing"
+	"time"
+)
+
+func TestMutexLock(t *testing.T) {
+	var mu fdMutex
+
+	if !mu.Incref() {
+		t.Fatal("broken")
+	}
+	if mu.Decref() {
+		t.Fatal("broken")
+	}
+
+	if !mu.RWLock(true) {
+		t.Fatal("broken")
+	}
+	if mu.RWUnlock(true) {
+		t.Fatal("broken")
+	}
+
+	if !mu.RWLock(false) {
+		t.Fatal("broken")
+	}
+	if mu.RWUnlock(false) {
+		t.Fatal("broken")
+	}
+}
+
+func TestMutexClose(t *testing.T) {
+	var mu fdMutex
+	if !mu.IncrefAndClose() {
+		t.Fatal("broken")
+	}
+
+	if mu.Incref() {
+		t.Fatal("broken")
+	}
+	if mu.RWLock(true) {
+		t.Fatal("broken")
+	}
+	if mu.RWLock(false) {
+		t.Fatal("broken")
+	}
+	if mu.IncrefAndClose() {
+		t.Fatal("broken")
+	}
+}
+
+func TestMutexCloseUnblock(t *testing.T) {
+	c := make(chan bool)
+	var mu fdMutex
+	mu.RWLock(true)
+	for i := 0; i < 4; i++ {
+		go func() {
+			if mu.RWLock(true) {
+				t.Error("broken")
+				return
+			}
+			c <- true
+		}()
+	}
+	// Concurrent goroutines must not be able to read lock the mutex.
+	time.Sleep(time.Millisecond)
+	select {
+	case <-c:
+		t.Fatal("broken")
+	default:
+	}
+	mu.IncrefAndClose() // Must unblock the readers.
+	for i := 0; i < 4; i++ {
+		select {
+		case <-c:
+		case <-time.After(10 * time.Second):
+			t.Fatal("broken")
+		}
+	}
+	if mu.Decref() {
+		t.Fatal("broken")
+	}
+	if !mu.RWUnlock(true) {
+		t.Fatal("broken")
+	}
+}
+
+func TestMutexPanic(t *testing.T) {
+	ensurePanics := func(f func()) {
+		defer func() {
+			if recover() == nil {
+				t.Fatal("does not panic")
+			}
+		}()
+		f()
+	}
+
+	var mu fdMutex
+	ensurePanics(func() { mu.Decref() })
+	ensurePanics(func() { mu.RWUnlock(true) })
+	ensurePanics(func() { mu.RWUnlock(false) })
+
+	ensurePanics(func() { mu.Incref(); mu.Decref(); mu.Decref() })
+	ensurePanics(func() { mu.RWLock(true); mu.RWUnlock(true); mu.RWUnlock(true) })
+	ensurePanics(func() { mu.RWLock(false); mu.RWUnlock(false); mu.RWUnlock(false) })
+
+	// ensure that it's still not broken
+	mu.Incref()
+	mu.Decref()
+	mu.RWLock(true)
+	mu.RWUnlock(true)
+	mu.RWLock(false)
+	mu.RWUnlock(false)
+}
+
+func TestMutexStress(t *testing.T) {
+	P := 8
+	N := int(1e6)
+	if testing.Short() {
+		P = 4
+		N = 1e4
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
+	done := make(chan bool)
+	var mu fdMutex
+	var readState [2]uint64
+	var writeState [2]uint64
+	for p := 0; p < P; p++ {
+		go func() {
+			r := rand.New(rand.NewSource(rand.Int63()))
+			for i := 0; i < N; i++ {
+				switch r.Intn(3) {
+				case 0:
+					if !mu.Incref() {
+						t.Error("broken")
+						return
+					}
+					if mu.Decref() {
+						t.Error("broken")
+						return
+					}
+				case 1:
+					if !mu.RWLock(true) {
+						t.Error("broken")
+						return
+					}
+					// Ensure that it provides mutual exclusion for readers.
+					if readState[0] != readState[1] {
+						t.Error("broken")
+						return
+					}
+					readState[0]++
+					readState[1]++
+					if mu.RWUnlock(true) {
+						t.Error("broken")
+						return
+					}
+				case 2:
+					if !mu.RWLock(false) {
+						t.Error("broken")
+						return
+					}
+					// Ensure that it provides mutual exclusion for writers.
+					if writeState[0] != writeState[1] {
+						t.Error("broken")
+						return
+					}
+					writeState[0]++
+					writeState[1]++
+					if mu.RWUnlock(false) {
+						t.Error("broken")
+						return
+					}
+				}
+			}
+			done <- true
+		}()
+	}
+	for p := 0; p < P; p++ {
+		<-done
+	}
+	if !mu.IncrefAndClose() {
+		t.Fatal("broken")
+	}
+	if !mu.Decref() {
+		t.Fatal("broken")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/fd_plan9.go b/third_party/gofrontend/libgo/go/net/fd_plan9.go
new file mode 100644
index 0000000..5fe8eff
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/fd_plan9.go
@@ -0,0 +1,232 @@
+// 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 net
+
+import (
+	"io"
+	"os"
+	"syscall"
+	"time"
+)
+
+// Network file descritor.
+type netFD struct {
+	// locking/lifetime of sysfd + serialize access to Read and Write methods
+	fdmu fdMutex
+
+	// immutable until Close
+	proto        string
+	n            string
+	dir          string
+	ctl, data    *os.File
+	laddr, raddr Addr
+}
+
+var (
+	netdir string // default network
+)
+
+func sysInit() {
+	netdir = "/net"
+}
+
+func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
+	// On plan9, use the relatively inefficient
+	// goroutine-racing implementation.
+	return dialChannel(net, ra, dialer, deadline)
+}
+
+func newFD(proto, name string, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) {
+	return &netFD{proto: proto, n: name, dir: netdir + "/" + proto + "/" + name, ctl: ctl, data: data, laddr: laddr, raddr: raddr}, nil
+}
+
+func (fd *netFD) init() error {
+	// stub for future fd.pd.Init(fd)
+	return nil
+}
+
+func (fd *netFD) name() string {
+	var ls, rs string
+	if fd.laddr != nil {
+		ls = fd.laddr.String()
+	}
+	if fd.raddr != nil {
+		rs = fd.raddr.String()
+	}
+	return fd.proto + ":" + ls + "->" + rs
+}
+
+func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil }
+
+func (fd *netFD) destroy() {
+	if !fd.ok() {
+		return
+	}
+	err := fd.ctl.Close()
+	if fd.data != nil {
+		if err1 := fd.data.Close(); err1 != nil && err == nil {
+			err = err1
+		}
+	}
+	fd.ctl = nil
+	fd.data = nil
+}
+
+// Add a reference to this fd.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) incref() error {
+	if !fd.fdmu.Incref() {
+		return errClosing
+	}
+	return nil
+}
+
+// Remove a reference to this FD and close if we've been asked to do so
+// (and there are no references left).
+func (fd *netFD) decref() {
+	if fd.fdmu.Decref() {
+		fd.destroy()
+	}
+}
+
+// Add a reference to this fd and lock for reading.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) readLock() error {
+	if !fd.fdmu.RWLock(true) {
+		return errClosing
+	}
+	return nil
+}
+
+// Unlock for reading and remove a reference to this FD.
+func (fd *netFD) readUnlock() {
+	if fd.fdmu.RWUnlock(true) {
+		fd.destroy()
+	}
+}
+
+// Add a reference to this fd and lock for writing.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) writeLock() error {
+	if !fd.fdmu.RWLock(false) {
+		return errClosing
+	}
+	return nil
+}
+
+// Unlock for writing and remove a reference to this FD.
+func (fd *netFD) writeUnlock() {
+	if fd.fdmu.RWUnlock(false) {
+		fd.destroy()
+	}
+}
+
+func (fd *netFD) Read(b []byte) (n int, err error) {
+	if !fd.ok() || fd.data == nil {
+		return 0, syscall.EINVAL
+	}
+	if err := fd.readLock(); err != nil {
+		return 0, err
+	}
+	defer fd.readUnlock()
+	n, err = fd.data.Read(b)
+	if fd.proto == "udp" && err == io.EOF {
+		n = 0
+		err = nil
+	}
+	return
+}
+
+func (fd *netFD) Write(b []byte) (n int, err error) {
+	if !fd.ok() || fd.data == nil {
+		return 0, syscall.EINVAL
+	}
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+	return fd.data.Write(b)
+}
+
+func (fd *netFD) closeRead() error {
+	if !fd.ok() {
+		return syscall.EINVAL
+	}
+	return syscall.EPLAN9
+}
+
+func (fd *netFD) closeWrite() error {
+	if !fd.ok() {
+		return syscall.EINVAL
+	}
+	return syscall.EPLAN9
+}
+
+func (fd *netFD) Close() error {
+	if !fd.fdmu.IncrefAndClose() {
+		return errClosing
+	}
+	if !fd.ok() {
+		return syscall.EINVAL
+	}
+	err := fd.ctl.Close()
+	if fd.data != nil {
+		if err1 := fd.data.Close(); err1 != nil && err == nil {
+			err = err1
+		}
+	}
+	fd.ctl = nil
+	fd.data = nil
+	return err
+}
+
+// This method is only called via Conn.
+func (fd *netFD) dup() (*os.File, error) {
+	if !fd.ok() || fd.data == nil {
+		return nil, syscall.EINVAL
+	}
+	return fd.file(fd.data, fd.dir+"/data")
+}
+
+func (l *TCPListener) dup() (*os.File, error) {
+	if !l.fd.ok() {
+		return nil, syscall.EINVAL
+	}
+	return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl")
+}
+
+func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
+	syscall.ForkLock.RLock()
+	dfd, err := syscall.Dup(int(f.Fd()), -1)
+	syscall.ForkLock.RUnlock()
+	if err != nil {
+		return nil, &OpError{"dup", s, fd.laddr, err}
+	}
+	return os.NewFile(uintptr(dfd), s), nil
+}
+
+func (fd *netFD) setDeadline(t time.Time) error {
+	return syscall.EPLAN9
+}
+
+func (fd *netFD) setReadDeadline(t time.Time) error {
+	return syscall.EPLAN9
+}
+
+func (fd *netFD) setWriteDeadline(t time.Time) error {
+	return syscall.EPLAN9
+}
+
+func setReadBuffer(fd *netFD, bytes int) error {
+	return syscall.EPLAN9
+}
+
+func setWriteBuffer(fd *netFD, bytes int) error {
+	return syscall.EPLAN9
+}
+
+func skipRawSocketTests() (skip bool, skipmsg string, err error) {
+	return true, "skipping test on plan9", nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/fd_poll_nacl.go b/third_party/gofrontend/libgo/go/net/fd_poll_nacl.go
new file mode 100644
index 0000000..a3701f8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/fd_poll_nacl.go
@@ -0,0 +1,94 @@
+// Copyright 2013 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 net
+
+import (
+	"syscall"
+	"time"
+)
+
+type pollDesc struct {
+	fd      *netFD
+	closing bool
+}
+
+func (pd *pollDesc) Init(fd *netFD) error { pd.fd = fd; return nil }
+
+func (pd *pollDesc) Close() {}
+
+func (pd *pollDesc) Lock() {}
+
+func (pd *pollDesc) Unlock() {}
+
+func (pd *pollDesc) Wakeup() {}
+
+func (pd *pollDesc) Evict() bool {
+	pd.closing = true
+	if pd.fd != nil {
+		syscall.StopIO(pd.fd.sysfd)
+	}
+	return false
+}
+
+func (pd *pollDesc) Prepare(mode int) error {
+	if pd.closing {
+		return errClosing
+	}
+	return nil
+}
+
+func (pd *pollDesc) PrepareRead() error { return pd.Prepare('r') }
+
+func (pd *pollDesc) PrepareWrite() error { return pd.Prepare('w') }
+
+func (pd *pollDesc) Wait(mode int) error {
+	if pd.closing {
+		return errClosing
+	}
+	return errTimeout
+}
+
+func (pd *pollDesc) WaitRead() error { return pd.Wait('r') }
+
+func (pd *pollDesc) WaitWrite() error { return pd.Wait('w') }
+
+func (pd *pollDesc) WaitCanceled(mode int) {}
+
+func (pd *pollDesc) WaitCanceledRead() {}
+
+func (pd *pollDesc) WaitCanceledWrite() {}
+
+func (fd *netFD) setDeadline(t time.Time) error {
+	return setDeadlineImpl(fd, t, 'r'+'w')
+}
+
+func (fd *netFD) setReadDeadline(t time.Time) error {
+	return setDeadlineImpl(fd, t, 'r')
+}
+
+func (fd *netFD) setWriteDeadline(t time.Time) error {
+	return setDeadlineImpl(fd, t, 'w')
+}
+
+func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
+	d := t.UnixNano()
+	if t.IsZero() {
+		d = 0
+	}
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	switch mode {
+	case 'r':
+		syscall.SetReadDeadline(fd.sysfd, d)
+	case 'w':
+		syscall.SetWriteDeadline(fd.sysfd, d)
+	case 'r' + 'w':
+		syscall.SetReadDeadline(fd.sysfd, d)
+		syscall.SetWriteDeadline(fd.sysfd, d)
+	}
+	fd.decref()
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/fd_poll_runtime.go b/third_party/gofrontend/libgo/go/net/fd_poll_runtime.go
new file mode 100644
index 0000000..2bddc83
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/fd_poll_runtime.go
@@ -0,0 +1,144 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd windows solaris
+
+package net
+
+import (
+	"sync"
+	"syscall"
+	"time"
+)
+
+// runtimeNano returns the current value of the runtime clock in nanoseconds.
+func runtimeNano() int64
+
+func runtime_pollServerInit()
+func runtime_pollOpen(fd uintptr) (uintptr, int)
+func runtime_pollClose(ctx uintptr)
+func runtime_pollWait(ctx uintptr, mode int) int
+func runtime_pollWaitCanceled(ctx uintptr, mode int) int
+func runtime_pollReset(ctx uintptr, mode int) int
+func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
+func runtime_pollUnblock(ctx uintptr)
+
+type pollDesc struct {
+	runtimeCtx uintptr
+}
+
+var serverInit sync.Once
+
+func (pd *pollDesc) Init(fd *netFD) error {
+	serverInit.Do(runtime_pollServerInit)
+	ctx, errno := runtime_pollOpen(uintptr(fd.sysfd))
+	if errno != 0 {
+		return syscall.Errno(errno)
+	}
+	pd.runtimeCtx = ctx
+	return nil
+}
+
+func (pd *pollDesc) Close() {
+	if pd.runtimeCtx == 0 {
+		return
+	}
+	runtime_pollClose(pd.runtimeCtx)
+	pd.runtimeCtx = 0
+}
+
+func (pd *pollDesc) Lock() {
+}
+
+func (pd *pollDesc) Unlock() {
+}
+
+func (pd *pollDesc) Wakeup() {
+}
+
+// Evict evicts fd from the pending list, unblocking any I/O running on fd.
+// Return value is whether the pollServer should be woken up.
+func (pd *pollDesc) Evict() bool {
+	if pd.runtimeCtx == 0 {
+		return false
+	}
+	runtime_pollUnblock(pd.runtimeCtx)
+	return false
+}
+
+func (pd *pollDesc) Prepare(mode int) error {
+	res := runtime_pollReset(pd.runtimeCtx, mode)
+	return convertErr(res)
+}
+
+func (pd *pollDesc) PrepareRead() error {
+	return pd.Prepare('r')
+}
+
+func (pd *pollDesc) PrepareWrite() error {
+	return pd.Prepare('w')
+}
+
+func (pd *pollDesc) Wait(mode int) error {
+	res := runtime_pollWait(pd.runtimeCtx, mode)
+	return convertErr(res)
+}
+
+func (pd *pollDesc) WaitRead() error {
+	return pd.Wait('r')
+}
+
+func (pd *pollDesc) WaitWrite() error {
+	return pd.Wait('w')
+}
+
+func (pd *pollDesc) WaitCanceled(mode int) {
+	runtime_pollWaitCanceled(pd.runtimeCtx, mode)
+}
+
+func (pd *pollDesc) WaitCanceledRead() {
+	pd.WaitCanceled('r')
+}
+
+func (pd *pollDesc) WaitCanceledWrite() {
+	pd.WaitCanceled('w')
+}
+
+func convertErr(res int) error {
+	switch res {
+	case 0:
+		return nil
+	case 1:
+		return errClosing
+	case 2:
+		return errTimeout
+	}
+	println("unreachable: ", res)
+	panic("unreachable")
+}
+
+func (fd *netFD) setDeadline(t time.Time) error {
+	return setDeadlineImpl(fd, t, 'r'+'w')
+}
+
+func (fd *netFD) setReadDeadline(t time.Time) error {
+	return setDeadlineImpl(fd, t, 'r')
+}
+
+func (fd *netFD) setWriteDeadline(t time.Time) error {
+	return setDeadlineImpl(fd, t, 'w')
+}
+
+func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
+	d := runtimeNano() + int64(t.Sub(time.Now()))
+	if t.IsZero() {
+		d = 0
+	}
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
+	fd.decref()
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/fd_select.go b/third_party/gofrontend/libgo/go/net/fd_select.go
new file mode 100644
index 0000000..4103c57
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/fd_select.go
@@ -0,0 +1,182 @@
+// Copyright 2010 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.
+
+// Waiting for FDs via select(2).
+
+package net
+
+import (
+	"errors"
+	"os"
+	"syscall"
+)
+
+type pollster struct {
+	readFds, writeFds, repeatFds *syscall.FdSet
+	maxFd                        int
+	readyReadFds, readyWriteFds  *syscall.FdSet
+	nReady                       int
+	lastFd                       int
+	closed                       bool
+}
+
+func newpollster() (p *pollster, err error) {
+	p = new(pollster)
+	p.readFds = new(syscall.FdSet)
+	p.writeFds = new(syscall.FdSet)
+	p.repeatFds = new(syscall.FdSet)
+	p.readyReadFds = new(syscall.FdSet)
+	p.readyWriteFds = new(syscall.FdSet)
+	p.maxFd = -1
+	p.nReady = 0
+	p.lastFd = 0
+	return p, nil
+}
+
+func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
+	// pollServer is locked.
+
+	if p.closed {
+		return false, errors.New("pollster closed")
+	}
+
+	if mode == 'r' {
+		syscall.FDSet(fd, p.readFds)
+	} else {
+		syscall.FDSet(fd, p.writeFds)
+	}
+
+	if repeat {
+		syscall.FDSet(fd, p.repeatFds)
+	}
+
+	if fd > p.maxFd {
+		p.maxFd = fd
+	}
+
+	return true, nil
+}
+
+func (p *pollster) DelFD(fd int, mode int) bool {
+	// pollServer is locked.
+
+	if p.closed {
+		return false
+	}
+
+	if mode == 'r' {
+		if !syscall.FDIsSet(fd, p.readFds) {
+			print("Select unexpected fd=", fd, " for read\n")
+			return false
+		}
+		syscall.FDClr(fd, p.readFds)
+	} else {
+		if !syscall.FDIsSet(fd, p.writeFds) {
+			print("Select unexpected fd=", fd, " for write\n")
+			return false
+		}
+		syscall.FDClr(fd, p.writeFds)
+	}
+
+	// Doesn't matter if not already present.
+	syscall.FDClr(fd, p.repeatFds)
+
+	// We don't worry about maxFd here.
+
+	return true
+}
+
+func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
+	if p.nReady == 0 {
+		var timeout *syscall.Timeval
+		var tv syscall.Timeval
+		timeout = nil
+		if nsec > 0 {
+			tv = syscall.NsecToTimeval(nsec)
+			timeout = &tv
+		}
+
+		var n int
+		var e error
+		var tmpReadFds, tmpWriteFds syscall.FdSet
+		for {
+			if p.closed {
+				return -1, 0, errors.New("pollster closed")
+			}
+
+			// Temporary syscall.FdSet's into which the values are copied
+			// because select mutates the values.
+			tmpReadFds = *p.readFds
+			tmpWriteFds = *p.writeFds
+
+			s.Unlock()
+			n, e = syscall.Select(p.maxFd+1, &tmpReadFds, &tmpWriteFds, nil, timeout)
+			s.Lock()
+
+			if e != syscall.EINTR {
+				break
+			}
+		}
+		if e == syscall.EBADF {
+			// Some file descriptor has been closed.
+			tmpReadFds = syscall.FdSet{}
+			tmpWriteFds = syscall.FdSet{}
+			n = 0
+			for i := 0; i < p.maxFd+1; i++ {
+				if syscall.FDIsSet(i, p.readFds) {
+					var s syscall.Stat_t
+					if syscall.Fstat(i, &s) == syscall.EBADF {
+						syscall.FDSet(i, &tmpReadFds)
+						n++
+					}
+				} else if syscall.FDIsSet(i, p.writeFds) {
+					var s syscall.Stat_t
+					if syscall.Fstat(i, &s) == syscall.EBADF {
+						syscall.FDSet(i, &tmpWriteFds)
+						n++
+					}
+				}
+			}
+		} else if e != nil {
+			return -1, 0, os.NewSyscallError("select", e)
+		}
+		if n == 0 {
+			return -1, 0, nil
+		}
+
+		p.nReady = n
+		*p.readyReadFds = tmpReadFds
+		*p.readyWriteFds = tmpWriteFds
+		p.lastFd = 0
+	}
+
+	flag := false
+	for i := p.lastFd; i < p.maxFd+1; i++ {
+		if syscall.FDIsSet(i, p.readyReadFds) {
+			flag = true
+			mode = 'r'
+			syscall.FDClr(i, p.readyReadFds)
+		} else if syscall.FDIsSet(i, p.readyWriteFds) {
+			flag = true
+			mode = 'w'
+			syscall.FDClr(i, p.readyWriteFds)
+		}
+		if flag {
+			if !syscall.FDIsSet(i, p.repeatFds) {
+				p.DelFD(i, mode)
+			}
+			p.nReady--
+			p.lastFd = i
+			return i, mode, nil
+		}
+	}
+
+	// Will not reach here.  Just to shut up the compiler.
+	return -1, 0, nil
+}
+
+func (p *pollster) Close() error {
+	p.closed = true
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/fd_unix.go b/third_party/gofrontend/libgo/go/net/fd_unix.go
new file mode 100644
index 0000000..7c73ddc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/fd_unix.go
@@ -0,0 +1,518 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package net
+
+import (
+	"io"
+	"os"
+	"runtime"
+	"sync/atomic"
+	"syscall"
+	"time"
+)
+
+// Network file descriptor.
+type netFD struct {
+	// locking/lifetime of sysfd + serialize access to Read and Write methods
+	fdmu fdMutex
+
+	// immutable until Close
+	sysfd       int
+	family      int
+	sotype      int
+	isConnected bool
+	net         string
+	laddr       Addr
+	raddr       Addr
+
+	// wait server
+	pd pollDesc
+}
+
+func sysInit() {
+}
+
+func dial(network string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
+	return dialer(deadline)
+}
+
+func newFD(sysfd, family, sotype int, net string) (*netFD, error) {
+	return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil
+}
+
+func (fd *netFD) init() error {
+	if err := fd.pd.Init(fd); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (fd *netFD) setAddr(laddr, raddr Addr) {
+	fd.laddr = laddr
+	fd.raddr = raddr
+	runtime.SetFinalizer(fd, (*netFD).Close)
+}
+
+func (fd *netFD) name() string {
+	var ls, rs string
+	if fd.laddr != nil {
+		ls = fd.laddr.String()
+	}
+	if fd.raddr != nil {
+		rs = fd.raddr.String()
+	}
+	return fd.net + ":" + ls + "->" + rs
+}
+
+func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
+	// Do not need to call fd.writeLock here,
+	// because fd is not yet accessible to user,
+	// so no concurrent operations are possible.
+	switch err := syscall.Connect(fd.sysfd, ra); err {
+	case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
+	case nil, syscall.EISCONN:
+		if !deadline.IsZero() && deadline.Before(time.Now()) {
+			return errTimeout
+		}
+		if err := fd.init(); err != nil {
+			return err
+		}
+		return nil
+	case syscall.EINVAL:
+		// On Solaris we can see EINVAL if the socket has
+		// already been accepted and closed by the server.
+		// Treat this as a successful connection--writes to
+		// the socket will see EOF.  For details and a test
+		// case in C see http://golang.org/issue/6828.
+		if runtime.GOOS == "solaris" {
+			return nil
+		}
+		fallthrough
+	default:
+		return err
+	}
+	if err := fd.init(); err != nil {
+		return err
+	}
+	if !deadline.IsZero() {
+		fd.setWriteDeadline(deadline)
+		defer fd.setWriteDeadline(noDeadline)
+	}
+	for {
+		// Performing multiple connect system calls on a
+		// non-blocking socket under Unix variants does not
+		// necessarily result in earlier errors being
+		// returned. Instead, once runtime-integrated network
+		// poller tells us that the socket is ready, get the
+		// SO_ERROR socket option to see if the connection
+		// succeeded or failed. See issue 7474 for further
+		// details.
+		if err := fd.pd.WaitWrite(); err != nil {
+			return err
+		}
+		nerr, err := syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
+		if err != nil {
+			return err
+		}
+		switch err := syscall.Errno(nerr); err {
+		case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
+		case syscall.Errno(0), syscall.EISCONN:
+			return nil
+		default:
+			return err
+		}
+	}
+}
+
+func (fd *netFD) destroy() {
+	// Poller may want to unregister fd in readiness notification mechanism,
+	// so this must be executed before closesocket.
+	fd.pd.Close()
+	closesocket(fd.sysfd)
+	fd.sysfd = -1
+	runtime.SetFinalizer(fd, nil)
+}
+
+// Add a reference to this fd.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) incref() error {
+	if !fd.fdmu.Incref() {
+		return errClosing
+	}
+	return nil
+}
+
+// Remove a reference to this FD and close if we've been asked to do so
+// (and there are no references left).
+func (fd *netFD) decref() {
+	if fd.fdmu.Decref() {
+		fd.destroy()
+	}
+}
+
+// Add a reference to this fd and lock for reading.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) readLock() error {
+	if !fd.fdmu.RWLock(true) {
+		return errClosing
+	}
+	return nil
+}
+
+// Unlock for reading and remove a reference to this FD.
+func (fd *netFD) readUnlock() {
+	if fd.fdmu.RWUnlock(true) {
+		fd.destroy()
+	}
+}
+
+// Add a reference to this fd and lock for writing.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) writeLock() error {
+	if !fd.fdmu.RWLock(false) {
+		return errClosing
+	}
+	return nil
+}
+
+// Unlock for writing and remove a reference to this FD.
+func (fd *netFD) writeUnlock() {
+	if fd.fdmu.RWUnlock(false) {
+		fd.destroy()
+	}
+}
+
+func (fd *netFD) Close() error {
+	fd.pd.Lock() // needed for both fd.incref(true) and pollDesc.Evict
+	if !fd.fdmu.IncrefAndClose() {
+		fd.pd.Unlock()
+		return errClosing
+	}
+	// Unblock any I/O.  Once it all unblocks and returns,
+	// so that it cannot be referring to fd.sysfd anymore,
+	// the final decref will close fd.sysfd.  This should happen
+	// fairly quickly, since all the I/O is non-blocking, and any
+	// attempts to block in the pollDesc will return errClosing.
+	doWakeup := fd.pd.Evict()
+	fd.pd.Unlock()
+	fd.decref()
+	if doWakeup {
+		fd.pd.Wakeup()
+	}
+	return nil
+}
+
+func (fd *netFD) shutdown(how int) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	err := syscall.Shutdown(fd.sysfd, how)
+	if err != nil {
+		return &OpError{"shutdown", fd.net, fd.laddr, err}
+	}
+	return nil
+}
+
+func (fd *netFD) closeRead() error {
+	return fd.shutdown(syscall.SHUT_RD)
+}
+
+func (fd *netFD) closeWrite() error {
+	return fd.shutdown(syscall.SHUT_WR)
+}
+
+func (fd *netFD) Read(p []byte) (n int, err error) {
+	if err := fd.readLock(); err != nil {
+		return 0, err
+	}
+	defer fd.readUnlock()
+	if err := fd.pd.PrepareRead(); err != nil {
+		return 0, &OpError{"read", fd.net, fd.raddr, err}
+	}
+	for {
+		n, err = syscall.Read(int(fd.sysfd), p)
+		if err != nil {
+			n = 0
+			if err == syscall.EAGAIN {
+				if err = fd.pd.WaitRead(); err == nil {
+					continue
+				}
+			}
+		}
+		err = chkReadErr(n, err, fd)
+		break
+	}
+	if err != nil && err != io.EOF {
+		err = &OpError{"read", fd.net, fd.raddr, err}
+	}
+	return
+}
+
+func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
+	if err := fd.readLock(); err != nil {
+		return 0, nil, err
+	}
+	defer fd.readUnlock()
+	if err := fd.pd.PrepareRead(); err != nil {
+		return 0, nil, &OpError{"read", fd.net, fd.laddr, err}
+	}
+	for {
+		n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
+		if err != nil {
+			n = 0
+			if err == syscall.EAGAIN {
+				if err = fd.pd.WaitRead(); err == nil {
+					continue
+				}
+			}
+		}
+		err = chkReadErr(n, err, fd)
+		break
+	}
+	if err != nil && err != io.EOF {
+		err = &OpError{"read", fd.net, fd.laddr, err}
+	}
+	return
+}
+
+func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
+	if err := fd.readLock(); err != nil {
+		return 0, 0, 0, nil, err
+	}
+	defer fd.readUnlock()
+	if err := fd.pd.PrepareRead(); err != nil {
+		return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err}
+	}
+	for {
+		n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
+		if err != nil {
+			// TODO(dfc) should n and oobn be set to 0
+			if err == syscall.EAGAIN {
+				if err = fd.pd.WaitRead(); err == nil {
+					continue
+				}
+			}
+		}
+		err = chkReadErr(n, err, fd)
+		break
+	}
+	if err != nil && err != io.EOF {
+		err = &OpError{"read", fd.net, fd.laddr, err}
+	}
+	return
+}
+
+func chkReadErr(n int, err error, fd *netFD) error {
+	if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM && fd.sotype != syscall.SOCK_RAW {
+		return io.EOF
+	}
+	return err
+}
+
+func (fd *netFD) Write(p []byte) (nn int, err error) {
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+	if err := fd.pd.PrepareWrite(); err != nil {
+		return 0, &OpError{"write", fd.net, fd.raddr, err}
+	}
+	for {
+		var n int
+		n, err = syscall.Write(int(fd.sysfd), p[nn:])
+		if n > 0 {
+			nn += n
+		}
+		if nn == len(p) {
+			break
+		}
+		if err == syscall.EAGAIN {
+			if err = fd.pd.WaitWrite(); err == nil {
+				continue
+			}
+		}
+		if err != nil {
+			n = 0
+			break
+		}
+		if n == 0 {
+			err = io.ErrUnexpectedEOF
+			break
+		}
+	}
+	if err != nil {
+		err = &OpError{"write", fd.net, fd.raddr, err}
+	}
+	return nn, err
+}
+
+func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+	if err := fd.pd.PrepareWrite(); err != nil {
+		return 0, &OpError{"write", fd.net, fd.raddr, err}
+	}
+	for {
+		err = syscall.Sendto(fd.sysfd, p, 0, sa)
+		if err == syscall.EAGAIN {
+			if err = fd.pd.WaitWrite(); err == nil {
+				continue
+			}
+		}
+		break
+	}
+	if err == nil {
+		n = len(p)
+	} else {
+		err = &OpError{"write", fd.net, fd.raddr, err}
+	}
+	return
+}
+
+func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
+	if err := fd.writeLock(); err != nil {
+		return 0, 0, err
+	}
+	defer fd.writeUnlock()
+	if err := fd.pd.PrepareWrite(); err != nil {
+		return 0, 0, &OpError{"write", fd.net, fd.raddr, err}
+	}
+	for {
+		n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0)
+		if err == syscall.EAGAIN {
+			if err = fd.pd.WaitWrite(); err == nil {
+				continue
+			}
+		}
+		break
+	}
+	if err == nil {
+		oobn = len(oob)
+	} else {
+		err = &OpError{"write", fd.net, fd.raddr, err}
+	}
+	return
+}
+
+func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
+	if err := fd.readLock(); err != nil {
+		return nil, err
+	}
+	defer fd.readUnlock()
+
+	var s int
+	var rsa syscall.Sockaddr
+	if err = fd.pd.PrepareRead(); err != nil {
+		return nil, &OpError{"accept", fd.net, fd.laddr, err}
+	}
+	for {
+		s, rsa, err = accept(fd.sysfd)
+		if err != nil {
+			if err == syscall.EAGAIN {
+				if err = fd.pd.WaitRead(); err == nil {
+					continue
+				}
+			} else if err == syscall.ECONNABORTED {
+				// This means that a socket on the listen queue was closed
+				// before we Accept()ed it; it's a silly error, so try again.
+				continue
+			}
+			return nil, &OpError{"accept", fd.net, fd.laddr, err}
+		}
+		break
+	}
+
+	if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
+		closesocket(s)
+		return nil, err
+	}
+	if err = netfd.init(); err != nil {
+		fd.Close()
+		return nil, err
+	}
+	lsa, _ := syscall.Getsockname(netfd.sysfd)
+	netfd.setAddr(toAddr(lsa), toAddr(rsa))
+	return netfd, nil
+}
+
+// tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used.
+// If the kernel doesn't support it, this is set to 0.
+var tryDupCloexec = int32(1)
+
+func dupCloseOnExec(fd int) (newfd int, err error) {
+	if atomic.LoadInt32(&tryDupCloexec) == 1 && syscall.F_DUPFD_CLOEXEC != 0 {
+		r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0)
+		if runtime.GOOS == "darwin" && e1 == syscall.EBADF {
+			// On OS X 10.6 and below (but we only support
+			// >= 10.6), F_DUPFD_CLOEXEC is unsupported
+			// and fcntl there falls back (undocumented)
+			// to doing an ioctl instead, returning EBADF
+			// in this case because fd is not of the
+			// expected device fd type.  Treat it as
+			// EINVAL instead, so we fall back to the
+			// normal dup path.
+			// TODO: only do this on 10.6 if we can detect 10.6
+			// cheaply.
+			e1 = syscall.EINVAL
+		}
+		switch e1 {
+		case 0:
+			return int(r0), nil
+		case syscall.EINVAL:
+			// Old kernel. Fall back to the portable way
+			// from now on.
+			atomic.StoreInt32(&tryDupCloexec, 0)
+		default:
+			return -1, e1
+		}
+	}
+	return dupCloseOnExecOld(fd)
+}
+
+// dupCloseOnExecUnixOld is the traditional way to dup an fd and
+// set its O_CLOEXEC bit, using two system calls.
+func dupCloseOnExecOld(fd int) (newfd int, err error) {
+	syscall.ForkLock.RLock()
+	defer syscall.ForkLock.RUnlock()
+	newfd, err = syscall.Dup(fd)
+	if err != nil {
+		return -1, err
+	}
+	syscall.CloseOnExec(newfd)
+	return
+}
+
+func (fd *netFD) dup() (f *os.File, err error) {
+	ns, err := dupCloseOnExec(fd.sysfd)
+	if err != nil {
+		return nil, &OpError{"dup", fd.net, fd.laddr, err}
+	}
+
+	// We want blocking mode for the new fd, hence the double negative.
+	// This also puts the old fd into blocking mode, meaning that
+	// I/O will block the thread instead of letting us use the epoll server.
+	// Everything will still work, just with more threads.
+	if err = syscall.SetNonblock(ns, false); err != nil {
+		return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
+	}
+
+	return os.NewFile(uintptr(ns), fd.name()), nil
+}
+
+func closesocket(s int) error {
+	return syscall.Close(s)
+}
+
+func skipRawSocketTests() (skip bool, skipmsg string, err error) {
+	if os.Getuid() != 0 {
+		return true, "skipping test; must be root", nil
+	}
+	return false, "", nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/fd_unix_test.go b/third_party/gofrontend/libgo/go/net/fd_unix_test.go
new file mode 100644
index 0000000..fe8e8ff
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/fd_unix_test.go
@@ -0,0 +1,58 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package net
+
+import (
+	"io"
+	"syscall"
+	"testing"
+)
+
+var chkReadErrTests = []struct {
+	n        int
+	err      error
+	fd       *netFD
+	expected error
+}{
+
+	{100, nil, &netFD{sotype: syscall.SOCK_STREAM}, nil},
+	{100, io.EOF, &netFD{sotype: syscall.SOCK_STREAM}, io.EOF},
+	{100, errClosing, &netFD{sotype: syscall.SOCK_STREAM}, errClosing},
+	{0, nil, &netFD{sotype: syscall.SOCK_STREAM}, io.EOF},
+	{0, io.EOF, &netFD{sotype: syscall.SOCK_STREAM}, io.EOF},
+	{0, errClosing, &netFD{sotype: syscall.SOCK_STREAM}, errClosing},
+
+	{100, nil, &netFD{sotype: syscall.SOCK_DGRAM}, nil},
+	{100, io.EOF, &netFD{sotype: syscall.SOCK_DGRAM}, io.EOF},
+	{100, errClosing, &netFD{sotype: syscall.SOCK_DGRAM}, errClosing},
+	{0, nil, &netFD{sotype: syscall.SOCK_DGRAM}, nil},
+	{0, io.EOF, &netFD{sotype: syscall.SOCK_DGRAM}, io.EOF},
+	{0, errClosing, &netFD{sotype: syscall.SOCK_DGRAM}, errClosing},
+
+	{100, nil, &netFD{sotype: syscall.SOCK_SEQPACKET}, nil},
+	{100, io.EOF, &netFD{sotype: syscall.SOCK_SEQPACKET}, io.EOF},
+	{100, errClosing, &netFD{sotype: syscall.SOCK_SEQPACKET}, errClosing},
+	{0, nil, &netFD{sotype: syscall.SOCK_SEQPACKET}, io.EOF},
+	{0, io.EOF, &netFD{sotype: syscall.SOCK_SEQPACKET}, io.EOF},
+	{0, errClosing, &netFD{sotype: syscall.SOCK_SEQPACKET}, errClosing},
+
+	{100, nil, &netFD{sotype: syscall.SOCK_RAW}, nil},
+	{100, io.EOF, &netFD{sotype: syscall.SOCK_RAW}, io.EOF},
+	{100, errClosing, &netFD{sotype: syscall.SOCK_RAW}, errClosing},
+	{0, nil, &netFD{sotype: syscall.SOCK_RAW}, nil},
+	{0, io.EOF, &netFD{sotype: syscall.SOCK_RAW}, io.EOF},
+	{0, errClosing, &netFD{sotype: syscall.SOCK_RAW}, errClosing},
+}
+
+func TestChkReadErr(t *testing.T) {
+	for _, tt := range chkReadErrTests {
+		actual := chkReadErr(tt.n, tt.err, tt.fd)
+		if actual != tt.expected {
+			t.Errorf("chkReadError(%v, %v, %v): expected %v, actual %v", tt.n, tt.err, tt.fd.sotype, tt.expected, actual)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/fd_windows.go b/third_party/gofrontend/libgo/go/net/fd_windows.go
new file mode 100644
index 0000000..d1129dc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/fd_windows.go
@@ -0,0 +1,644 @@
+// Copyright 2010 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 net
+
+import (
+	"errors"
+	"io"
+	"os"
+	"runtime"
+	"sync"
+	"syscall"
+	"time"
+	"unsafe"
+)
+
+var (
+	initErr error
+	ioSync  uint64
+)
+
+// CancelIo Windows API cancels all outstanding IO for a particular
+// socket on current thread. To overcome that limitation, we run
+// special goroutine, locked to OS single thread, that both starts
+// and cancels IO. It means, there are 2 unavoidable thread switches
+// for every IO.
+// Some newer versions of Windows has new CancelIoEx API, that does
+// not have that limitation and can be used from any thread. This
+// package uses CancelIoEx API, if present, otherwise it fallback
+// to CancelIo.
+
+var (
+	canCancelIO                               bool // determines if CancelIoEx API is present
+	skipSyncNotif                             bool
+	hasLoadSetFileCompletionNotificationModes bool
+)
+
+func sysInit() {
+	var d syscall.WSAData
+	e := syscall.WSAStartup(uint32(0x202), &d)
+	if e != nil {
+		initErr = os.NewSyscallError("WSAStartup", e)
+	}
+	canCancelIO = syscall.LoadCancelIoEx() == nil
+	if syscall.LoadGetAddrInfo() == nil {
+		lookupPort = newLookupPort
+		lookupIP = newLookupIP
+	}
+
+	hasLoadSetFileCompletionNotificationModes = syscall.LoadSetFileCompletionNotificationModes() == nil
+	if hasLoadSetFileCompletionNotificationModes {
+		// It's not safe to use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS if non IFS providers are installed:
+		// http://support.microsoft.com/kb/2568167
+		skipSyncNotif = true
+		protos := [2]int32{syscall.IPPROTO_TCP, 0}
+		var buf [32]syscall.WSAProtocolInfo
+		len := uint32(unsafe.Sizeof(buf))
+		n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
+		if err != nil {
+			skipSyncNotif = false
+		} else {
+			for i := int32(0); i < n; i++ {
+				if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
+					skipSyncNotif = false
+					break
+				}
+			}
+		}
+	}
+}
+
+func closesocket(s syscall.Handle) error {
+	return syscall.Closesocket(s)
+}
+
+func canUseConnectEx(net string) bool {
+	switch net {
+	case "udp", "udp4", "udp6", "ip", "ip4", "ip6":
+		// ConnectEx windows API does not support connectionless sockets.
+		return false
+	}
+	return syscall.LoadConnectEx() == nil
+}
+
+func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
+	if !canUseConnectEx(net) {
+		// Use the relatively inefficient goroutine-racing
+		// implementation of DialTimeout.
+		return dialChannel(net, ra, dialer, deadline)
+	}
+	return dialer(deadline)
+}
+
+// operation contains superset of data necessary to perform all async IO.
+type operation struct {
+	// Used by IOCP interface, it must be first field
+	// of the struct, as our code rely on it.
+	o syscall.Overlapped
+
+	// fields used by runtime.netpoll
+	runtimeCtx uintptr
+	mode       int32
+	errno      int32
+	qty        uint32
+
+	// fields used only by net package
+	fd     *netFD
+	errc   chan error
+	buf    syscall.WSABuf
+	sa     syscall.Sockaddr
+	rsa    *syscall.RawSockaddrAny
+	rsan   int32
+	handle syscall.Handle
+	flags  uint32
+}
+
+func (o *operation) InitBuf(buf []byte) {
+	o.buf.Len = uint32(len(buf))
+	o.buf.Buf = nil
+	if len(buf) != 0 {
+		o.buf.Buf = &buf[0]
+	}
+}
+
+// ioSrv executes net IO requests.
+type ioSrv struct {
+	req chan ioSrvReq
+}
+
+type ioSrvReq struct {
+	o      *operation
+	submit func(o *operation) error // if nil, cancel the operation
+}
+
+// ProcessRemoteIO will execute submit IO requests on behalf
+// of other goroutines, all on a single os thread, so it can
+// cancel them later. Results of all operations will be sent
+// back to their requesters via channel supplied in request.
+// It is used only when the CancelIoEx API is unavailable.
+func (s *ioSrv) ProcessRemoteIO() {
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+	for r := range s.req {
+		if r.submit != nil {
+			r.o.errc <- r.submit(r.o)
+		} else {
+			r.o.errc <- syscall.CancelIo(r.o.fd.sysfd)
+		}
+	}
+}
+
+// ExecIO executes a single IO operation o. It submits and cancels
+// IO in the current thread for systems where Windows CancelIoEx API
+// is available. Alternatively, it passes the request onto
+// runtime netpoll and waits for completion or cancels request.
+func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) error) (int, error) {
+	fd := o.fd
+	// Notify runtime netpoll about starting IO.
+	err := fd.pd.Prepare(int(o.mode))
+	if err != nil {
+		return 0, &OpError{name, fd.net, fd.laddr, err}
+	}
+	// Start IO.
+	if canCancelIO {
+		err = submit(o)
+	} else {
+		// Send request to a special dedicated thread,
+		// so it can stop the IO with CancelIO later.
+		s.req <- ioSrvReq{o, submit}
+		err = <-o.errc
+	}
+	switch err {
+	case nil:
+		// IO completed immediately
+		if o.fd.skipSyncNotif {
+			// No completion message will follow, so return immediately.
+			return int(o.qty), nil
+		}
+		// Need to get our completion message anyway.
+	case syscall.ERROR_IO_PENDING:
+		// IO started, and we have to wait for its completion.
+		err = nil
+	default:
+		return 0, &OpError{name, fd.net, fd.laddr, err}
+	}
+	// Wait for our request to complete.
+	err = fd.pd.Wait(int(o.mode))
+	if err == nil {
+		// All is good. Extract our IO results and return.
+		if o.errno != 0 {
+			err = syscall.Errno(o.errno)
+			return 0, &OpError{name, fd.net, fd.laddr, err}
+		}
+		return int(o.qty), nil
+	}
+	// IO is interrupted by "close" or "timeout"
+	netpollErr := err
+	switch netpollErr {
+	case errClosing, errTimeout:
+		// will deal with those.
+	default:
+		panic("net: unexpected runtime.netpoll error: " + netpollErr.Error())
+	}
+	// Cancel our request.
+	if canCancelIO {
+		err := syscall.CancelIoEx(fd.sysfd, &o.o)
+		// Assuming ERROR_NOT_FOUND is returned, if IO is completed.
+		if err != nil && err != syscall.ERROR_NOT_FOUND {
+			// TODO(brainman): maybe do something else, but panic.
+			panic(err)
+		}
+	} else {
+		s.req <- ioSrvReq{o, nil}
+		<-o.errc
+	}
+	// Wait for cancellation to complete.
+	fd.pd.WaitCanceled(int(o.mode))
+	if o.errno != 0 {
+		err = syscall.Errno(o.errno)
+		if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
+			err = netpollErr
+		}
+		return 0, &OpError{name, fd.net, fd.laddr, err}
+	}
+	// We issued cancellation request. But, it seems, IO operation succeeded
+	// before cancellation request run. We need to treat IO operation as
+	// succeeded (the bytes are actually sent/recv from network).
+	return int(o.qty), nil
+}
+
+// Start helper goroutines.
+var rsrv, wsrv *ioSrv
+var onceStartServer sync.Once
+
+func startServer() {
+	rsrv = new(ioSrv)
+	wsrv = new(ioSrv)
+	if !canCancelIO {
+		// Only CancelIo API is available. Lets start two special goroutines
+		// locked to an OS thread, that both starts and cancels IO. One will
+		// process read requests, while other will do writes.
+		rsrv.req = make(chan ioSrvReq)
+		go rsrv.ProcessRemoteIO()
+		wsrv.req = make(chan ioSrvReq)
+		go wsrv.ProcessRemoteIO()
+	}
+}
+
+// Network file descriptor.
+type netFD struct {
+	// locking/lifetime of sysfd + serialize access to Read and Write methods
+	fdmu fdMutex
+
+	// immutable until Close
+	sysfd         syscall.Handle
+	family        int
+	sotype        int
+	isConnected   bool
+	skipSyncNotif bool
+	net           string
+	laddr         Addr
+	raddr         Addr
+
+	rop operation // read operation
+	wop operation // write operation
+
+	// wait server
+	pd pollDesc
+}
+
+func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
+	if initErr != nil {
+		return nil, initErr
+	}
+	onceStartServer.Do(startServer)
+	return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil
+}
+
+func (fd *netFD) init() error {
+	if err := fd.pd.Init(fd); err != nil {
+		return err
+	}
+	if hasLoadSetFileCompletionNotificationModes {
+		// We do not use events, so we can skip them always.
+		flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
+		// It's not safe to skip completion notifications for UDP:
+		// http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
+		if skipSyncNotif && fd.net == "tcp" {
+			flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
+		}
+		err := syscall.SetFileCompletionNotificationModes(fd.sysfd, flags)
+		if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 {
+			fd.skipSyncNotif = true
+		}
+	}
+	fd.rop.mode = 'r'
+	fd.wop.mode = 'w'
+	fd.rop.fd = fd
+	fd.wop.fd = fd
+	fd.rop.runtimeCtx = fd.pd.runtimeCtx
+	fd.wop.runtimeCtx = fd.pd.runtimeCtx
+	if !canCancelIO {
+		fd.rop.errc = make(chan error)
+		fd.wop.errc = make(chan error)
+	}
+	return nil
+}
+
+func (fd *netFD) setAddr(laddr, raddr Addr) {
+	fd.laddr = laddr
+	fd.raddr = raddr
+	runtime.SetFinalizer(fd, (*netFD).Close)
+}
+
+func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
+	// Do not need to call fd.writeLock here,
+	// because fd is not yet accessible to user,
+	// so no concurrent operations are possible.
+	if err := fd.init(); err != nil {
+		return err
+	}
+	if !deadline.IsZero() {
+		fd.setWriteDeadline(deadline)
+		defer fd.setWriteDeadline(noDeadline)
+	}
+	if !canUseConnectEx(fd.net) {
+		return syscall.Connect(fd.sysfd, ra)
+	}
+	// ConnectEx windows API requires an unconnected, previously bound socket.
+	if la == nil {
+		switch ra.(type) {
+		case *syscall.SockaddrInet4:
+			la = &syscall.SockaddrInet4{}
+		case *syscall.SockaddrInet6:
+			la = &syscall.SockaddrInet6{}
+		default:
+			panic("unexpected type in connect")
+		}
+		if err := syscall.Bind(fd.sysfd, la); err != nil {
+			return err
+		}
+	}
+	// Call ConnectEx API.
+	o := &fd.wop
+	o.sa = ra
+	_, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
+		return syscall.ConnectEx(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
+	})
+	if err != nil {
+		return err
+	}
+	// Refresh socket properties.
+	return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
+}
+
+func (fd *netFD) destroy() {
+	if fd.sysfd == syscall.InvalidHandle {
+		return
+	}
+	// Poller may want to unregister fd in readiness notification mechanism,
+	// so this must be executed before closesocket.
+	fd.pd.Close()
+	closesocket(fd.sysfd)
+	fd.sysfd = syscall.InvalidHandle
+	// no need for a finalizer anymore
+	runtime.SetFinalizer(fd, nil)
+}
+
+// Add a reference to this fd.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) incref() error {
+	if !fd.fdmu.Incref() {
+		return errClosing
+	}
+	return nil
+}
+
+// Remove a reference to this FD and close if we've been asked to do so
+// (and there are no references left).
+func (fd *netFD) decref() {
+	if fd.fdmu.Decref() {
+		fd.destroy()
+	}
+}
+
+// Add a reference to this fd and lock for reading.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) readLock() error {
+	if !fd.fdmu.RWLock(true) {
+		return errClosing
+	}
+	return nil
+}
+
+// Unlock for reading and remove a reference to this FD.
+func (fd *netFD) readUnlock() {
+	if fd.fdmu.RWUnlock(true) {
+		fd.destroy()
+	}
+}
+
+// Add a reference to this fd and lock for writing.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) writeLock() error {
+	if !fd.fdmu.RWLock(false) {
+		return errClosing
+	}
+	return nil
+}
+
+// Unlock for writing and remove a reference to this FD.
+func (fd *netFD) writeUnlock() {
+	if fd.fdmu.RWUnlock(false) {
+		fd.destroy()
+	}
+}
+
+func (fd *netFD) Close() error {
+	if !fd.fdmu.IncrefAndClose() {
+		return errClosing
+	}
+	// unblock pending reader and writer
+	fd.pd.Evict()
+	fd.decref()
+	return nil
+}
+
+func (fd *netFD) shutdown(how int) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	err := syscall.Shutdown(fd.sysfd, how)
+	if err != nil {
+		return &OpError{"shutdown", fd.net, fd.laddr, err}
+	}
+	return nil
+}
+
+func (fd *netFD) closeRead() error {
+	return fd.shutdown(syscall.SHUT_RD)
+}
+
+func (fd *netFD) closeWrite() error {
+	return fd.shutdown(syscall.SHUT_WR)
+}
+
+func (fd *netFD) Read(buf []byte) (int, error) {
+	if err := fd.readLock(); err != nil {
+		return 0, err
+	}
+	defer fd.readUnlock()
+	o := &fd.rop
+	o.InitBuf(buf)
+	n, err := rsrv.ExecIO(o, "WSARecv", func(o *operation) error {
+		return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
+	})
+	if err == nil && n == 0 {
+		err = io.EOF
+	}
+	if raceenabled {
+		raceAcquire(unsafe.Pointer(&ioSync))
+	}
+	return n, err
+}
+
+func (fd *netFD) readFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
+	if len(buf) == 0 {
+		return 0, nil, nil
+	}
+	if err := fd.readLock(); err != nil {
+		return 0, nil, err
+	}
+	defer fd.readUnlock()
+	o := &fd.rop
+	o.InitBuf(buf)
+	n, err = rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error {
+		if o.rsa == nil {
+			o.rsa = new(syscall.RawSockaddrAny)
+		}
+		o.rsan = int32(unsafe.Sizeof(*o.rsa))
+		return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
+	})
+	if err != nil {
+		return 0, nil, err
+	}
+	sa, _ = o.rsa.Sockaddr()
+	return
+}
+
+func (fd *netFD) Write(buf []byte) (int, error) {
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+	if raceenabled {
+		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	}
+	o := &fd.wop
+	o.InitBuf(buf)
+	return wsrv.ExecIO(o, "WSASend", func(o *operation) error {
+		return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
+	})
+}
+
+func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
+	if len(buf) == 0 {
+		return 0, nil
+	}
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+	o := &fd.wop
+	o.InitBuf(buf)
+	o.sa = sa
+	return wsrv.ExecIO(o, "WSASendto", func(o *operation) error {
+		return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
+	})
+}
+
+func (fd *netFD) acceptOne(toAddr func(syscall.Sockaddr) Addr, rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) {
+	// Get new socket.
+	s, err := sysSocket(fd.family, fd.sotype, 0)
+	if err != nil {
+		return nil, &OpError{"socket", fd.net, fd.laddr, err}
+	}
+
+	// Associate our new socket with IOCP.
+	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
+	if err != nil {
+		closesocket(s)
+		return nil, &OpError{"accept", fd.net, fd.laddr, err}
+	}
+	if err := netfd.init(); err != nil {
+		fd.Close()
+		return nil, err
+	}
+
+	// Submit accept request.
+	o.handle = s
+	o.rsan = int32(unsafe.Sizeof(rawsa[0]))
+	_, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error {
+		return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
+	})
+	if err != nil {
+		netfd.Close()
+		return nil, err
+	}
+
+	// Inherit properties of the listening socket.
+	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
+	if err != nil {
+		netfd.Close()
+		return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
+	}
+
+	return netfd, nil
+}
+
+func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
+	if err := fd.readLock(); err != nil {
+		return nil, err
+	}
+	defer fd.readUnlock()
+
+	o := &fd.rop
+	var netfd *netFD
+	var err error
+	var rawsa [2]syscall.RawSockaddrAny
+	for {
+		netfd, err = fd.acceptOne(toAddr, rawsa[:], o)
+		if err == nil {
+			break
+		}
+		// Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
+		// returned here. These happen if connection reset is received
+		// before AcceptEx could complete. These errors relate to new
+		// connection, not to AcceptEx, so ignore broken connection and
+		// try AcceptEx again for more connections.
+		operr, ok := err.(*OpError)
+		if !ok {
+			return nil, err
+		}
+		errno, ok := operr.Err.(syscall.Errno)
+		if !ok {
+			return nil, err
+		}
+		switch errno {
+		case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
+			// ignore these and try again
+		default:
+			return nil, err
+		}
+	}
+
+	// Get local and peer addr out of AcceptEx buffer.
+	var lrsa, rrsa *syscall.RawSockaddrAny
+	var llen, rlen int32
+	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
+		0, uint32(o.rsan), uint32(o.rsan), &lrsa, &llen, &rrsa, &rlen)
+	lsa, _ := lrsa.Sockaddr()
+	rsa, _ := rrsa.Sockaddr()
+
+	netfd.setAddr(toAddr(lsa), toAddr(rsa))
+	return netfd, nil
+}
+
+func skipRawSocketTests() (skip bool, skipmsg string, err error) {
+	// From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx:
+	// Note: To use a socket of type SOCK_RAW requires administrative privileges.
+	// Users running Winsock applications that use raw sockets must be a member of
+	// the Administrators group on the local computer, otherwise raw socket calls
+	// will fail with an error code of WSAEACCES. On Windows Vista and later, access
+	// for raw sockets is enforced at socket creation. In earlier versions of Windows,
+	// access for raw sockets is enforced during other socket operations.
+	s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0)
+	if err == syscall.WSAEACCES {
+		return true, "skipping test; no access to raw socket allowed", nil
+	}
+	if err != nil {
+		return true, "", err
+	}
+	defer syscall.Closesocket(s)
+	return false, "", nil
+}
+
+// Unimplemented functions.
+
+func (fd *netFD) dup() (*os.File, error) {
+	// TODO: Implement this
+	return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
+}
+
+var errNoSupport = errors.New("address family not supported")
+
+func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
+	return 0, 0, 0, nil, errNoSupport
+}
+
+func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
+	return 0, 0, errNoSupport
+}
diff --git a/third_party/gofrontend/libgo/go/net/file_plan9.go b/third_party/gofrontend/libgo/go/net/file_plan9.go
new file mode 100644
index 0000000..068f088
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/file_plan9.go
@@ -0,0 +1,157 @@
+// 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.
+
+package net
+
+import (
+	"errors"
+	"io"
+	"os"
+	"syscall"
+)
+
+func (fd *netFD) status(ln int) (string, error) {
+	if !fd.ok() {
+		return "", syscall.EINVAL
+	}
+
+	status, err := os.Open(fd.dir + "/status")
+	if err != nil {
+		return "", err
+	}
+	defer status.Close()
+	buf := make([]byte, ln)
+	n, err := io.ReadFull(status, buf[:])
+	if err != nil {
+		return "", err
+	}
+	return string(buf[:n]), nil
+}
+
+func newFileFD(f *os.File) (net *netFD, err error) {
+	var ctl *os.File
+	close := func(fd int) {
+		if err != nil {
+			syscall.Close(fd)
+		}
+	}
+
+	path, err := syscall.Fd2path(int(f.Fd()))
+	if err != nil {
+		return nil, os.NewSyscallError("fd2path", err)
+	}
+	comp := splitAtBytes(path, "/")
+	n := len(comp)
+	if n < 3 || comp[0][0:3] != "net" {
+		return nil, syscall.EPLAN9
+	}
+
+	name := comp[2]
+	switch file := comp[n-1]; file {
+	case "ctl", "clone":
+		syscall.ForkLock.RLock()
+		fd, err := syscall.Dup(int(f.Fd()), -1)
+		syscall.ForkLock.RUnlock()
+		if err != nil {
+			return nil, os.NewSyscallError("dup", err)
+		}
+		defer close(fd)
+
+		dir := netdir + "/" + comp[n-2]
+		ctl = os.NewFile(uintptr(fd), dir+"/"+file)
+		ctl.Seek(0, 0)
+		var buf [16]byte
+		n, err := ctl.Read(buf[:])
+		if err != nil {
+			return nil, err
+		}
+		name = string(buf[:n])
+	default:
+		if len(comp) < 4 {
+			return nil, errors.New("could not find control file for connection")
+		}
+		dir := netdir + "/" + comp[1] + "/" + name
+		ctl, err = os.OpenFile(dir+"/ctl", os.O_RDWR, 0)
+		if err != nil {
+			return nil, err
+		}
+		defer close(int(ctl.Fd()))
+	}
+	dir := netdir + "/" + comp[1] + "/" + name
+	laddr, err := readPlan9Addr(comp[1], dir+"/local")
+	if err != nil {
+		return nil, err
+	}
+	return newFD(comp[1], name, ctl, nil, laddr, nil)
+}
+
+func newFileConn(f *os.File) (c Conn, err error) {
+	fd, err := newFileFD(f)
+	if err != nil {
+		return nil, err
+	}
+	if !fd.ok() {
+		return nil, syscall.EINVAL
+	}
+
+	fd.data, err = os.OpenFile(fd.dir+"/data", os.O_RDWR, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	switch fd.laddr.(type) {
+	case *TCPAddr:
+		return newTCPConn(fd), nil
+	case *UDPAddr:
+		return newUDPConn(fd), nil
+	}
+	return nil, syscall.EPLAN9
+}
+
+func newFileListener(f *os.File) (l Listener, err error) {
+	fd, err := newFileFD(f)
+	if err != nil {
+		return nil, err
+	}
+	switch fd.laddr.(type) {
+	case *TCPAddr:
+	default:
+		return nil, syscall.EPLAN9
+	}
+
+	// check that file corresponds to a listener
+	s, err := fd.status(len("Listen"))
+	if err != nil {
+		return nil, err
+	}
+	if s != "Listen" {
+		return nil, errors.New("file does not represent a listener")
+	}
+
+	return &TCPListener{fd}, nil
+}
+
+// FileConn returns a copy of the network connection corresponding to
+// the open file f.  It is the caller's responsibility to close f when
+// finished.  Closing c does not affect f, and closing f does not
+// affect c.
+func FileConn(f *os.File) (c Conn, err error) {
+	return newFileConn(f)
+}
+
+// FileListener returns a copy of the network listener corresponding
+// to the open file f.  It is the caller's responsibility to close l
+// when finished.  Closing l does not affect f, and closing f does not
+// affect l.
+func FileListener(f *os.File) (l Listener, err error) {
+	return newFileListener(f)
+}
+
+// FilePacketConn returns a copy of the packet network connection
+// corresponding to the open file f.  It is the caller's
+// responsibility to close f when finished.  Closing c does not affect
+// f, and closing f does not affect c.
+func FilePacketConn(f *os.File) (c PacketConn, err error) {
+	return nil, syscall.EPLAN9
+}
diff --git a/third_party/gofrontend/libgo/go/net/file_test.go b/third_party/gofrontend/libgo/go/net/file_test.go
new file mode 100644
index 0000000..d81bca7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/file_test.go
@@ -0,0 +1,205 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"reflect"
+	"runtime"
+	"testing"
+)
+
+type listenerFile interface {
+	Listener
+	File() (f *os.File, err error)
+}
+
+type packetConnFile interface {
+	PacketConn
+	File() (f *os.File, err error)
+}
+
+type connFile interface {
+	Conn
+	File() (f *os.File, err error)
+}
+
+func testFileListener(t *testing.T, net, laddr string) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+		laddr += ":0" // any available port
+	}
+	l, err := Listen(net, laddr)
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+	}
+	defer l.Close()
+	lf := l.(listenerFile)
+	f, err := lf.File()
+	if err != nil {
+		t.Fatalf("File failed: %v", err)
+	}
+	c, err := FileListener(f)
+	if err != nil {
+		t.Fatalf("FileListener failed: %v", err)
+	}
+	if !reflect.DeepEqual(l.Addr(), c.Addr()) {
+		t.Fatalf("Addrs not equal: %#v != %#v", l.Addr(), c.Addr())
+	}
+	if err := c.Close(); err != nil {
+		t.Fatalf("Close failed: %v", err)
+	}
+	if err := f.Close(); err != nil {
+		t.Fatalf("Close failed: %v", err)
+	}
+}
+
+var fileListenerTests = []struct {
+	net   string
+	laddr string
+	ipv6  bool // test with underlying AF_INET6 socket
+	linux bool // test with abstract unix domain socket, a Linux-ism
+}{
+	{net: "tcp", laddr: ""},
+	{net: "tcp", laddr: "0.0.0.0"},
+	{net: "tcp", laddr: "[::ffff:0.0.0.0]"},
+	{net: "tcp", laddr: "[::]", ipv6: true},
+
+	{net: "tcp", laddr: "127.0.0.1"},
+	{net: "tcp", laddr: "[::ffff:127.0.0.1]"},
+	{net: "tcp", laddr: "[::1]", ipv6: true},
+
+	{net: "tcp4", laddr: ""},
+	{net: "tcp4", laddr: "0.0.0.0"},
+	{net: "tcp4", laddr: "[::ffff:0.0.0.0]"},
+
+	{net: "tcp4", laddr: "127.0.0.1"},
+	{net: "tcp4", laddr: "[::ffff:127.0.0.1]"},
+
+	{net: "tcp6", laddr: "", ipv6: true},
+	{net: "tcp6", laddr: "[::]", ipv6: true},
+
+	{net: "tcp6", laddr: "[::1]", ipv6: true},
+
+	{net: "unix", laddr: "@gotest/net", linux: true},
+	{net: "unixpacket", laddr: "@gotest/net", linux: true},
+}
+
+func TestFileListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	for _, tt := range fileListenerTests {
+		if skipServerTest(tt.net, "unix", tt.laddr, tt.ipv6, false, tt.linux) {
+			continue
+		}
+		if skipServerTest(tt.net, "unixpacket", tt.laddr, tt.ipv6, false, tt.linux) {
+			continue
+		}
+		testFileListener(t, tt.net, tt.laddr)
+	}
+}
+
+func testFilePacketConn(t *testing.T, pcf packetConnFile, listen bool) {
+	f, err := pcf.File()
+	if err != nil {
+		t.Fatalf("File failed: %v", err)
+	}
+	c, err := FilePacketConn(f)
+	if err != nil {
+		t.Fatalf("FilePacketConn failed: %v", err)
+	}
+	if !reflect.DeepEqual(pcf.LocalAddr(), c.LocalAddr()) {
+		t.Fatalf("LocalAddrs not equal: %#v != %#v", pcf.LocalAddr(), c.LocalAddr())
+	}
+	if listen {
+		if _, err := c.WriteTo([]byte{}, c.LocalAddr()); err != nil {
+			t.Fatalf("WriteTo failed: %v", err)
+		}
+	}
+	if err := c.Close(); err != nil {
+		t.Fatalf("Close failed: %v", err)
+	}
+	if err := f.Close(); err != nil {
+		t.Fatalf("Close failed: %v", err)
+	}
+}
+
+func testFilePacketConnListen(t *testing.T, net, laddr string) {
+	switch net {
+	case "udp", "udp4", "udp6":
+		laddr += ":0" // any available port
+	}
+	l, err := ListenPacket(net, laddr)
+	if err != nil {
+		t.Fatalf("ListenPacket failed: %v", err)
+	}
+	testFilePacketConn(t, l.(packetConnFile), true)
+	if err := l.Close(); err != nil {
+		t.Fatalf("Close failed: %v", err)
+	}
+}
+
+func testFilePacketConnDial(t *testing.T, net, raddr string) {
+	switch net {
+	case "udp", "udp4", "udp6":
+		raddr += ":12345"
+	}
+	c, err := Dial(net, raddr)
+	if err != nil {
+		t.Fatalf("Dial failed: %v", err)
+	}
+	testFilePacketConn(t, c.(packetConnFile), false)
+	if err := c.Close(); err != nil {
+		t.Fatalf("Close failed: %v", err)
+	}
+}
+
+var filePacketConnTests = []struct {
+	net   string
+	addr  string
+	ipv6  bool // test with underlying AF_INET6 socket
+	linux bool // test with abstract unix domain socket, a Linux-ism
+}{
+	{net: "udp", addr: "127.0.0.1"},
+	{net: "udp", addr: "[::ffff:127.0.0.1]"},
+	{net: "udp", addr: "[::1]", ipv6: true},
+
+	{net: "udp4", addr: "127.0.0.1"},
+	{net: "udp4", addr: "[::ffff:127.0.0.1]"},
+
+	{net: "udp6", addr: "[::1]", ipv6: true},
+
+	{net: "ip4:icmp", addr: "127.0.0.1"},
+
+	{net: "unixgram", addr: "@gotest3/net", linux: true},
+}
+
+func TestFilePacketConn(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	for _, tt := range filePacketConnTests {
+		if skipServerTest(tt.net, "unixgram", tt.addr, tt.ipv6, false, tt.linux) {
+			continue
+		}
+		if os.Getuid() != 0 && tt.net == "ip4:icmp" {
+			t.Log("skipping test; must be root")
+			continue
+		}
+		testFilePacketConnListen(t, tt.net, tt.addr)
+		switch tt.addr {
+		case "", "0.0.0.0", "[::ffff:0.0.0.0]", "[::]":
+		default:
+			if tt.net != "unixgram" {
+				testFilePacketConnDial(t, tt.net, tt.addr)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/file_unix.go b/third_party/gofrontend/libgo/go/net/file_unix.go
new file mode 100644
index 0000000..07b3ecf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/file_unix.go
@@ -0,0 +1,139 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func newFileFD(f *os.File) (*netFD, error) {
+	fd, err := dupCloseOnExec(int(f.Fd()))
+	if err != nil {
+		return nil, os.NewSyscallError("dup", err)
+	}
+
+	if err = syscall.SetNonblock(fd, true); err != nil {
+		closesocket(fd)
+		return nil, err
+	}
+
+	sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
+	if err != nil {
+		closesocket(fd)
+		return nil, os.NewSyscallError("getsockopt", err)
+	}
+
+	family := syscall.AF_UNSPEC
+	toAddr := sockaddrToTCP
+	lsa, _ := syscall.Getsockname(fd)
+	switch lsa.(type) {
+	default:
+		closesocket(fd)
+		return nil, syscall.EINVAL
+	case *syscall.SockaddrInet4:
+		family = syscall.AF_INET
+		if sotype == syscall.SOCK_DGRAM {
+			toAddr = sockaddrToUDP
+		} else if sotype == syscall.SOCK_RAW {
+			toAddr = sockaddrToIP
+		}
+	case *syscall.SockaddrInet6:
+		family = syscall.AF_INET6
+		if sotype == syscall.SOCK_DGRAM {
+			toAddr = sockaddrToUDP
+		} else if sotype == syscall.SOCK_RAW {
+			toAddr = sockaddrToIP
+		}
+	case *syscall.SockaddrUnix:
+		family = syscall.AF_UNIX
+		toAddr = sockaddrToUnix
+		if sotype == syscall.SOCK_DGRAM {
+			toAddr = sockaddrToUnixgram
+		} else if sotype == syscall.SOCK_SEQPACKET {
+			toAddr = sockaddrToUnixpacket
+		}
+	}
+	laddr := toAddr(lsa)
+	rsa, _ := syscall.Getpeername(fd)
+	raddr := toAddr(rsa)
+
+	netfd, err := newFD(fd, family, sotype, laddr.Network())
+	if err != nil {
+		closesocket(fd)
+		return nil, err
+	}
+	if err := netfd.init(); err != nil {
+		netfd.Close()
+		return nil, err
+	}
+	netfd.setAddr(laddr, raddr)
+	return netfd, nil
+}
+
+// FileConn returns a copy of the network connection corresponding to
+// the open file f.  It is the caller's responsibility to close f when
+// finished.  Closing c does not affect f, and closing f does not
+// affect c.
+func FileConn(f *os.File) (c Conn, err error) {
+	fd, err := newFileFD(f)
+	if err != nil {
+		return nil, err
+	}
+	switch fd.laddr.(type) {
+	case *TCPAddr:
+		return newTCPConn(fd), nil
+	case *UDPAddr:
+		return newUDPConn(fd), nil
+	case *IPAddr:
+		return newIPConn(fd), nil
+	case *UnixAddr:
+		return newUnixConn(fd), nil
+	}
+	fd.Close()
+	return nil, syscall.EINVAL
+}
+
+// FileListener returns a copy of the network listener corresponding
+// to the open file f.  It is the caller's responsibility to close l
+// when finished.  Closing l does not affect f, and closing f does not
+// affect l.
+func FileListener(f *os.File) (l Listener, err error) {
+	fd, err := newFileFD(f)
+	if err != nil {
+		return nil, err
+	}
+	switch laddr := fd.laddr.(type) {
+	case *TCPAddr:
+		return &TCPListener{fd}, nil
+	case *UnixAddr:
+		return &UnixListener{fd, laddr.Name}, nil
+	}
+	fd.Close()
+	return nil, syscall.EINVAL
+}
+
+// FilePacketConn returns a copy of the packet network connection
+// corresponding to the open file f.  It is the caller's
+// responsibility to close f when finished.  Closing c does not affect
+// f, and closing f does not affect c.
+func FilePacketConn(f *os.File) (c PacketConn, err error) {
+	fd, err := newFileFD(f)
+	if err != nil {
+		return nil, err
+	}
+	switch fd.laddr.(type) {
+	case *UDPAddr:
+		return newUDPConn(fd), nil
+	case *IPAddr:
+		return newIPConn(fd), nil
+	case *UnixAddr:
+		return newUnixConn(fd), nil
+	}
+	fd.Close()
+	return nil, syscall.EINVAL
+}
diff --git a/third_party/gofrontend/libgo/go/net/file_windows.go b/third_party/gofrontend/libgo/go/net/file_windows.go
new file mode 100644
index 0000000..ca2b9b2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/file_windows.go
@@ -0,0 +1,37 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+// FileConn returns a copy of the network connection corresponding to
+// the open file f.  It is the caller's responsibility to close f when
+// finished.  Closing c does not affect f, and closing f does not
+// affect c.
+func FileConn(f *os.File) (c Conn, err error) {
+	// TODO: Implement this
+	return nil, os.NewSyscallError("FileConn", syscall.EWINDOWS)
+}
+
+// FileListener returns a copy of the network listener corresponding
+// to the open file f.  It is the caller's responsibility to close l
+// when finished.  Closing l does not affect f, and closing f does not
+// affect l.
+func FileListener(f *os.File) (l Listener, err error) {
+	// TODO: Implement this
+	return nil, os.NewSyscallError("FileListener", syscall.EWINDOWS)
+}
+
+// FilePacketConn returns a copy of the packet network connection
+// corresponding to the open file f.  It is the caller's
+// responsibility to close f when finished.  Closing c does not affect
+// f, and closing f does not affect c.
+func FilePacketConn(f *os.File) (c PacketConn, err error) {
+	// TODO: Implement this
+	return nil, os.NewSyscallError("FilePacketConn", syscall.EWINDOWS)
+}
diff --git a/third_party/gofrontend/libgo/go/net/hosts.go b/third_party/gofrontend/libgo/go/net/hosts.go
new file mode 100644
index 0000000..e6674ba
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/hosts.go
@@ -0,0 +1,86 @@
+// 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.
+
+// Read static host/IP entries from /etc/hosts.
+
+package net
+
+import (
+	"sync"
+	"time"
+)
+
+const cacheMaxAge = 5 * time.Minute
+
+// hostsPath points to the file with static IP/address entries.
+var hostsPath = "/etc/hosts"
+
+// Simple cache.
+var hosts struct {
+	sync.Mutex
+	byName map[string][]string
+	byAddr map[string][]string
+	expire time.Time
+	path   string
+}
+
+func readHosts() {
+	now := time.Now()
+	hp := hostsPath
+	if len(hosts.byName) == 0 || now.After(hosts.expire) || hosts.path != hp {
+		hs := make(map[string][]string)
+		is := make(map[string][]string)
+		var file *file
+		if file, _ = open(hp); file == nil {
+			return
+		}
+		for line, ok := file.readLine(); ok; line, ok = file.readLine() {
+			if i := byteIndex(line, '#'); i >= 0 {
+				// Discard comments.
+				line = line[0:i]
+			}
+			f := getFields(line)
+			if len(f) < 2 || ParseIP(f[0]) == nil {
+				continue
+			}
+			for i := 1; i < len(f); i++ {
+				h := f[i]
+				hs[h] = append(hs[h], f[0])
+				is[f[0]] = append(is[f[0]], h)
+			}
+		}
+		// Update the data cache.
+		hosts.expire = time.Now().Add(cacheMaxAge)
+		hosts.path = hp
+		hosts.byName = hs
+		hosts.byAddr = is
+		file.close()
+	}
+}
+
+// lookupStaticHost looks up the addresses for the given host from /etc/hosts.
+func lookupStaticHost(host string) []string {
+	hosts.Lock()
+	defer hosts.Unlock()
+	readHosts()
+	if len(hosts.byName) != 0 {
+		if ips, ok := hosts.byName[host]; ok {
+			return ips
+		}
+	}
+	return nil
+}
+
+// lookupStaticAddr looks up the hosts for the given address from /etc/hosts.
+func lookupStaticAddr(addr string) []string {
+	hosts.Lock()
+	defer hosts.Unlock()
+	readHosts()
+	if len(hosts.byAddr) != 0 {
+		if hosts, ok := hosts.byAddr[addr]; ok {
+			return hosts
+		}
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/hosts_test.go b/third_party/gofrontend/libgo/go/net/hosts_test.go
new file mode 100644
index 0000000..2fe358e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/hosts_test.go
@@ -0,0 +1,81 @@
+// 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 net
+
+import (
+	"sort"
+	"testing"
+)
+
+type hostTest struct {
+	host string
+	ips  []IP
+}
+
+var hosttests = []hostTest{
+	{"odin", []IP{
+		IPv4(127, 0, 0, 2),
+		IPv4(127, 0, 0, 3),
+		ParseIP("::2"),
+	}},
+	{"thor", []IP{
+		IPv4(127, 1, 1, 1),
+	}},
+	{"loki", []IP{}},
+	{"ullr", []IP{
+		IPv4(127, 1, 1, 2),
+	}},
+	{"ullrhost", []IP{
+		IPv4(127, 1, 1, 2),
+	}},
+}
+
+func TestLookupStaticHost(t *testing.T) {
+	p := hostsPath
+	hostsPath = "testdata/hosts"
+	for i := 0; i < len(hosttests); i++ {
+		tt := hosttests[i]
+		ips := lookupStaticHost(tt.host)
+		if len(ips) != len(tt.ips) {
+			t.Errorf("# of hosts = %v; want %v",
+				len(ips), len(tt.ips))
+			continue
+		}
+		for k, v := range ips {
+			if tt.ips[k].String() != v {
+				t.Errorf("lookupStaticHost(%q) = %v; want %v",
+					tt.host, v, tt.ips[k])
+			}
+		}
+	}
+	hostsPath = p
+}
+
+// https://code.google.com/p/go/issues/detail?id=6646
+func TestSingleLineHostsFile(t *testing.T) {
+	p := hostsPath
+	hostsPath = "testdata/hosts_singleline"
+
+	ips := lookupStaticHost("odin")
+	if len(ips) != 1 || ips[0] != "127.0.0.2" {
+		t.Errorf("lookupStaticHost = %v, want %v", ips, []string{"127.0.0.2"})
+	}
+
+	hostsPath = p
+}
+
+func TestLookupHost(t *testing.T) {
+	// Can't depend on this to return anything in particular,
+	// but if it does return something, make sure it doesn't
+	// duplicate addresses (a common bug due to the way
+	// getaddrinfo works).
+	addrs, _ := LookupHost("localhost")
+	sort.Strings(addrs)
+	for i := 0; i+1 < len(addrs); i++ {
+		if addrs[i] == addrs[i+1] {
+			t.Fatalf("LookupHost(\"localhost\") = %v, has duplicate addresses", addrs)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/hosts_testdata b/third_party/gofrontend/libgo/go/net/hosts_testdata
new file mode 100644
index 0000000..b601763
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/hosts_testdata
@@ -0,0 +1,12 @@
+255.255.255.255	broadcasthost
+127.0.0.2	odin
+127.0.0.3	odin  # inline comment 
+::2             odin
+127.1.1.1	thor
+# aliases
+127.1.1.2	ullr ullrhost
+# Bogus entries that must be ignored.
+123.123.123	loki
+321.321.321.321
+# TODO(yvesj): Should we be able to parse this? From a Darwin system.
+fe80::1%lo0	localhost
diff --git a/third_party/gofrontend/libgo/go/net/http/cgi/child.go b/third_party/gofrontend/libgo/go/net/http/cgi/child.go
new file mode 100644
index 0000000..45fc2e5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cgi/child.go
@@ -0,0 +1,206 @@
+// 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.
+
+// This file implements CGI from the perspective of a child
+// process.
+
+package cgi
+
+import (
+	"bufio"
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"net/url"
+	"os"
+	"strconv"
+	"strings"
+)
+
+// Request returns the HTTP request as represented in the current
+// environment. This assumes the current program is being run
+// by a web server in a CGI environment.
+// The returned Request's Body is populated, if applicable.
+func Request() (*http.Request, error) {
+	r, err := RequestFromMap(envMap(os.Environ()))
+	if err != nil {
+		return nil, err
+	}
+	if r.ContentLength > 0 {
+		r.Body = ioutil.NopCloser(io.LimitReader(os.Stdin, r.ContentLength))
+	}
+	return r, nil
+}
+
+func envMap(env []string) map[string]string {
+	m := make(map[string]string)
+	for _, kv := range env {
+		if idx := strings.Index(kv, "="); idx != -1 {
+			m[kv[:idx]] = kv[idx+1:]
+		}
+	}
+	return m
+}
+
+// RequestFromMap creates an http.Request from CGI variables.
+// The returned Request's Body field is not populated.
+func RequestFromMap(params map[string]string) (*http.Request, error) {
+	r := new(http.Request)
+	r.Method = params["REQUEST_METHOD"]
+	if r.Method == "" {
+		return nil, errors.New("cgi: no REQUEST_METHOD in environment")
+	}
+
+	r.Proto = params["SERVER_PROTOCOL"]
+	var ok bool
+	r.ProtoMajor, r.ProtoMinor, ok = http.ParseHTTPVersion(r.Proto)
+	if !ok {
+		return nil, errors.New("cgi: invalid SERVER_PROTOCOL version")
+	}
+
+	r.Close = true
+	r.Trailer = http.Header{}
+	r.Header = http.Header{}
+
+	r.Host = params["HTTP_HOST"]
+
+	if lenstr := params["CONTENT_LENGTH"]; lenstr != "" {
+		clen, err := strconv.ParseInt(lenstr, 10, 64)
+		if err != nil {
+			return nil, errors.New("cgi: bad CONTENT_LENGTH in environment: " + lenstr)
+		}
+		r.ContentLength = clen
+	}
+
+	if ct := params["CONTENT_TYPE"]; ct != "" {
+		r.Header.Set("Content-Type", ct)
+	}
+
+	// Copy "HTTP_FOO_BAR" variables to "Foo-Bar" Headers
+	for k, v := range params {
+		if !strings.HasPrefix(k, "HTTP_") || k == "HTTP_HOST" {
+			continue
+		}
+		r.Header.Add(strings.Replace(k[5:], "_", "-", -1), v)
+	}
+
+	// TODO: cookies.  parsing them isn't exported, though.
+
+	uriStr := params["REQUEST_URI"]
+	if uriStr == "" {
+		// Fallback to SCRIPT_NAME, PATH_INFO and QUERY_STRING.
+		uriStr = params["SCRIPT_NAME"] + params["PATH_INFO"]
+		s := params["QUERY_STRING"]
+		if s != "" {
+			uriStr += "?" + s
+		}
+	}
+
+	// There's apparently a de-facto standard for this.
+	// http://docstore.mik.ua/orelly/linux/cgi/ch03_02.htm#ch03-35636
+	if s := params["HTTPS"]; s == "on" || s == "ON" || s == "1" {
+		r.TLS = &tls.ConnectionState{HandshakeComplete: true}
+	}
+
+	if r.Host != "" {
+		// Hostname is provided, so we can reasonably construct a URL.
+		rawurl := r.Host + uriStr
+		if r.TLS == nil {
+			rawurl = "http://" + rawurl
+		} else {
+			rawurl = "https://" + rawurl
+		}
+		url, err := url.Parse(rawurl)
+		if err != nil {
+			return nil, errors.New("cgi: failed to parse host and REQUEST_URI into a URL: " + rawurl)
+		}
+		r.URL = url
+	}
+	// Fallback logic if we don't have a Host header or the URL
+	// failed to parse
+	if r.URL == nil {
+		url, err := url.Parse(uriStr)
+		if err != nil {
+			return nil, errors.New("cgi: failed to parse REQUEST_URI into a URL: " + uriStr)
+		}
+		r.URL = url
+	}
+
+	// Request.RemoteAddr has its port set by Go's standard http
+	// server, so we do here too. We don't have one, though, so we
+	// use a dummy one.
+	r.RemoteAddr = net.JoinHostPort(params["REMOTE_ADDR"], "0")
+
+	return r, nil
+}
+
+// Serve executes the provided Handler on the currently active CGI
+// request, if any. If there's no current CGI environment
+// an error is returned. The provided handler may be nil to use
+// http.DefaultServeMux.
+func Serve(handler http.Handler) error {
+	req, err := Request()
+	if err != nil {
+		return err
+	}
+	if handler == nil {
+		handler = http.DefaultServeMux
+	}
+	rw := &response{
+		req:    req,
+		header: make(http.Header),
+		bufw:   bufio.NewWriter(os.Stdout),
+	}
+	handler.ServeHTTP(rw, req)
+	rw.Write(nil) // make sure a response is sent
+	if err = rw.bufw.Flush(); err != nil {
+		return err
+	}
+	return nil
+}
+
+type response struct {
+	req        *http.Request
+	header     http.Header
+	bufw       *bufio.Writer
+	headerSent bool
+}
+
+func (r *response) Flush() {
+	r.bufw.Flush()
+}
+
+func (r *response) Header() http.Header {
+	return r.header
+}
+
+func (r *response) Write(p []byte) (n int, err error) {
+	if !r.headerSent {
+		r.WriteHeader(http.StatusOK)
+	}
+	return r.bufw.Write(p)
+}
+
+func (r *response) WriteHeader(code int) {
+	if r.headerSent {
+		// Note: explicitly using Stderr, as Stdout is our HTTP output.
+		fmt.Fprintf(os.Stderr, "CGI attempted to write header twice on request for %s", r.req.URL)
+		return
+	}
+	r.headerSent = true
+	fmt.Fprintf(r.bufw, "Status: %d %s\r\n", code, http.StatusText(code))
+
+	// Set a default Content-Type
+	if _, hasType := r.header["Content-Type"]; !hasType {
+		r.header.Add("Content-Type", "text/html; charset=utf-8")
+	}
+
+	r.header.Write(r.bufw)
+	r.bufw.WriteString("\r\n")
+	r.bufw.Flush()
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cgi/child_test.go b/third_party/gofrontend/libgo/go/net/http/cgi/child_test.go
new file mode 100644
index 0000000..075d841
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cgi/child_test.go
@@ -0,0 +1,131 @@
+// 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.
+
+// Tests for CGI (the child process perspective)
+
+package cgi
+
+import (
+	"testing"
+)
+
+func TestRequest(t *testing.T) {
+	env := map[string]string{
+		"SERVER_PROTOCOL": "HTTP/1.1",
+		"REQUEST_METHOD":  "GET",
+		"HTTP_HOST":       "example.com",
+		"HTTP_REFERER":    "elsewhere",
+		"HTTP_USER_AGENT": "goclient",
+		"HTTP_FOO_BAR":    "baz",
+		"REQUEST_URI":     "/path?a=b",
+		"CONTENT_LENGTH":  "123",
+		"CONTENT_TYPE":    "text/xml",
+		"REMOTE_ADDR":     "5.6.7.8",
+	}
+	req, err := RequestFromMap(env)
+	if err != nil {
+		t.Fatalf("RequestFromMap: %v", err)
+	}
+	if g, e := req.UserAgent(), "goclient"; e != g {
+		t.Errorf("expected UserAgent %q; got %q", e, g)
+	}
+	if g, e := req.Method, "GET"; e != g {
+		t.Errorf("expected Method %q; got %q", e, g)
+	}
+	if g, e := req.Header.Get("Content-Type"), "text/xml"; e != g {
+		t.Errorf("expected Content-Type %q; got %q", e, g)
+	}
+	if g, e := req.ContentLength, int64(123); e != g {
+		t.Errorf("expected ContentLength %d; got %d", e, g)
+	}
+	if g, e := req.Referer(), "elsewhere"; e != g {
+		t.Errorf("expected Referer %q; got %q", e, g)
+	}
+	if req.Header == nil {
+		t.Fatalf("unexpected nil Header")
+	}
+	if g, e := req.Header.Get("Foo-Bar"), "baz"; e != g {
+		t.Errorf("expected Foo-Bar %q; got %q", e, g)
+	}
+	if g, e := req.URL.String(), "http://example.com/path?a=b"; e != g {
+		t.Errorf("expected URL %q; got %q", e, g)
+	}
+	if g, e := req.FormValue("a"), "b"; e != g {
+		t.Errorf("expected FormValue(a) %q; got %q", e, g)
+	}
+	if req.Trailer == nil {
+		t.Errorf("unexpected nil Trailer")
+	}
+	if req.TLS != nil {
+		t.Errorf("expected nil TLS")
+	}
+	if e, g := "5.6.7.8:0", req.RemoteAddr; e != g {
+		t.Errorf("RemoteAddr: got %q; want %q", g, e)
+	}
+}
+
+func TestRequestWithTLS(t *testing.T) {
+	env := map[string]string{
+		"SERVER_PROTOCOL": "HTTP/1.1",
+		"REQUEST_METHOD":  "GET",
+		"HTTP_HOST":       "example.com",
+		"HTTP_REFERER":    "elsewhere",
+		"REQUEST_URI":     "/path?a=b",
+		"CONTENT_TYPE":    "text/xml",
+		"HTTPS":           "1",
+		"REMOTE_ADDR":     "5.6.7.8",
+	}
+	req, err := RequestFromMap(env)
+	if err != nil {
+		t.Fatalf("RequestFromMap: %v", err)
+	}
+	if g, e := req.URL.String(), "https://example.com/path?a=b"; e != g {
+		t.Errorf("expected URL %q; got %q", e, g)
+	}
+	if req.TLS == nil {
+		t.Errorf("expected non-nil TLS")
+	}
+}
+
+func TestRequestWithoutHost(t *testing.T) {
+	env := map[string]string{
+		"SERVER_PROTOCOL": "HTTP/1.1",
+		"HTTP_HOST":       "",
+		"REQUEST_METHOD":  "GET",
+		"REQUEST_URI":     "/path?a=b",
+		"CONTENT_LENGTH":  "123",
+	}
+	req, err := RequestFromMap(env)
+	if err != nil {
+		t.Fatalf("RequestFromMap: %v", err)
+	}
+	if req.URL == nil {
+		t.Fatalf("unexpected nil URL")
+	}
+	if g, e := req.URL.String(), "/path?a=b"; e != g {
+		t.Errorf("URL = %q; want %q", g, e)
+	}
+}
+
+func TestRequestWithoutRequestURI(t *testing.T) {
+	env := map[string]string{
+		"SERVER_PROTOCOL": "HTTP/1.1",
+		"HTTP_HOST":       "example.com",
+		"REQUEST_METHOD":  "GET",
+		"SCRIPT_NAME":     "/dir/scriptname",
+		"PATH_INFO":       "/p1/p2",
+		"QUERY_STRING":    "a=1&b=2",
+		"CONTENT_LENGTH":  "123",
+	}
+	req, err := RequestFromMap(env)
+	if err != nil {
+		t.Fatalf("RequestFromMap: %v", err)
+	}
+	if req.URL == nil {
+		t.Fatalf("unexpected nil URL")
+	}
+	if g, e := req.URL.String(), "http://example.com/dir/scriptname/p1/p2?a=1&b=2"; e != g {
+		t.Errorf("URL = %q; want %q", g, e)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cgi/host.go b/third_party/gofrontend/libgo/go/net/http/cgi/host.go
new file mode 100644
index 0000000..ec95a97
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cgi/host.go
@@ -0,0 +1,377 @@
+// 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.
+
+// This file implements the host side of CGI (being the webserver
+// parent process).
+
+// Package cgi implements CGI (Common Gateway Interface) as specified
+// in RFC 3875.
+//
+// Note that using CGI means starting a new process to handle each
+// request, which is typically less efficient than using a
+// long-running server.  This package is intended primarily for
+// compatibility with existing systems.
+package cgi
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+)
+
+var trailingPort = regexp.MustCompile(`:([0-9]+)$`)
+
+var osDefaultInheritEnv = map[string][]string{
+	"darwin":  {"DYLD_LIBRARY_PATH"},
+	"freebsd": {"LD_LIBRARY_PATH"},
+	"hpux":    {"LD_LIBRARY_PATH", "SHLIB_PATH"},
+	"irix":    {"LD_LIBRARY_PATH", "LD_LIBRARYN32_PATH", "LD_LIBRARY64_PATH"},
+	"linux":   {"LD_LIBRARY_PATH"},
+	"openbsd": {"LD_LIBRARY_PATH"},
+	"solaris": {"LD_LIBRARY_PATH", "LD_LIBRARY_PATH_32", "LD_LIBRARY_PATH_64"},
+	"windows": {"SystemRoot", "COMSPEC", "PATHEXT", "WINDIR"},
+}
+
+// Handler runs an executable in a subprocess with a CGI environment.
+type Handler struct {
+	Path string // path to the CGI executable
+	Root string // root URI prefix of handler or empty for "/"
+
+	// Dir specifies the CGI executable's working directory.
+	// If Dir is empty, the base directory of Path is used.
+	// If Path has no base directory, the current working
+	// directory is used.
+	Dir string
+
+	Env        []string    // extra environment variables to set, if any, as "key=value"
+	InheritEnv []string    // environment variables to inherit from host, as "key"
+	Logger     *log.Logger // optional log for errors or nil to use log.Print
+	Args       []string    // optional arguments to pass to child process
+
+	// PathLocationHandler specifies the root http Handler that
+	// should handle internal redirects when the CGI process
+	// returns a Location header value starting with a "/", as
+	// specified in RFC 3875 § 6.3.2. This will likely be
+	// http.DefaultServeMux.
+	//
+	// If nil, a CGI response with a local URI path is instead sent
+	// back to the client and not redirected internally.
+	PathLocationHandler http.Handler
+}
+
+// removeLeadingDuplicates remove leading duplicate in environments.
+// It's possible to override environment like following.
+//    cgi.Handler{
+//      ...
+//      Env: []string{"SCRIPT_FILENAME=foo.php"},
+//    }
+func removeLeadingDuplicates(env []string) (ret []string) {
+	n := len(env)
+	for i := 0; i < n; i++ {
+		e := env[i]
+		s := strings.SplitN(e, "=", 2)[0]
+		found := false
+		for j := i + 1; j < n; j++ {
+			if s == strings.SplitN(env[j], "=", 2)[0] {
+				found = true
+				break
+			}
+		}
+		if !found {
+			ret = append(ret, e)
+		}
+	}
+	return
+}
+
+func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+	root := h.Root
+	if root == "" {
+		root = "/"
+	}
+
+	if len(req.TransferEncoding) > 0 && req.TransferEncoding[0] == "chunked" {
+		rw.WriteHeader(http.StatusBadRequest)
+		rw.Write([]byte("Chunked request bodies are not supported by CGI."))
+		return
+	}
+
+	pathInfo := req.URL.Path
+	if root != "/" && strings.HasPrefix(pathInfo, root) {
+		pathInfo = pathInfo[len(root):]
+	}
+
+	port := "80"
+	if matches := trailingPort.FindStringSubmatch(req.Host); len(matches) != 0 {
+		port = matches[1]
+	}
+
+	env := []string{
+		"SERVER_SOFTWARE=go",
+		"SERVER_NAME=" + req.Host,
+		"SERVER_PROTOCOL=HTTP/1.1",
+		"HTTP_HOST=" + req.Host,
+		"GATEWAY_INTERFACE=CGI/1.1",
+		"REQUEST_METHOD=" + req.Method,
+		"QUERY_STRING=" + req.URL.RawQuery,
+		"REQUEST_URI=" + req.URL.RequestURI(),
+		"PATH_INFO=" + pathInfo,
+		"SCRIPT_NAME=" + root,
+		"SCRIPT_FILENAME=" + h.Path,
+		"REMOTE_ADDR=" + req.RemoteAddr,
+		"REMOTE_HOST=" + req.RemoteAddr,
+		"SERVER_PORT=" + port,
+	}
+
+	if req.TLS != nil {
+		env = append(env, "HTTPS=on")
+	}
+
+	for k, v := range req.Header {
+		k = strings.Map(upperCaseAndUnderscore, k)
+		joinStr := ", "
+		if k == "COOKIE" {
+			joinStr = "; "
+		}
+		env = append(env, "HTTP_"+k+"="+strings.Join(v, joinStr))
+	}
+
+	if req.ContentLength > 0 {
+		env = append(env, fmt.Sprintf("CONTENT_LENGTH=%d", req.ContentLength))
+	}
+	if ctype := req.Header.Get("Content-Type"); ctype != "" {
+		env = append(env, "CONTENT_TYPE="+ctype)
+	}
+
+	if h.Env != nil {
+		env = append(env, h.Env...)
+	}
+
+	envPath := os.Getenv("PATH")
+	if envPath == "" {
+		envPath = "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
+	}
+	env = append(env, "PATH="+envPath)
+
+	for _, e := range h.InheritEnv {
+		if v := os.Getenv(e); v != "" {
+			env = append(env, e+"="+v)
+		}
+	}
+
+	for _, e := range osDefaultInheritEnv[runtime.GOOS] {
+		if v := os.Getenv(e); v != "" {
+			env = append(env, e+"="+v)
+		}
+	}
+
+	env = removeLeadingDuplicates(env)
+
+	var cwd, path string
+	if h.Dir != "" {
+		path = h.Path
+		cwd = h.Dir
+	} else {
+		cwd, path = filepath.Split(h.Path)
+	}
+	if cwd == "" {
+		cwd = "."
+	}
+
+	internalError := func(err error) {
+		rw.WriteHeader(http.StatusInternalServerError)
+		h.printf("CGI error: %v", err)
+	}
+
+	cmd := &exec.Cmd{
+		Path:   path,
+		Args:   append([]string{h.Path}, h.Args...),
+		Dir:    cwd,
+		Env:    env,
+		Stderr: os.Stderr, // for now
+	}
+	if req.ContentLength != 0 {
+		cmd.Stdin = req.Body
+	}
+	stdoutRead, err := cmd.StdoutPipe()
+	if err != nil {
+		internalError(err)
+		return
+	}
+
+	err = cmd.Start()
+	if err != nil {
+		internalError(err)
+		return
+	}
+	if hook := testHookStartProcess; hook != nil {
+		hook(cmd.Process)
+	}
+	defer cmd.Wait()
+	defer stdoutRead.Close()
+
+	linebody := bufio.NewReaderSize(stdoutRead, 1024)
+	headers := make(http.Header)
+	statusCode := 0
+	headerLines := 0
+	sawBlankLine := false
+	for {
+		line, isPrefix, err := linebody.ReadLine()
+		if isPrefix {
+			rw.WriteHeader(http.StatusInternalServerError)
+			h.printf("cgi: long header line from subprocess.")
+			return
+		}
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			rw.WriteHeader(http.StatusInternalServerError)
+			h.printf("cgi: error reading headers: %v", err)
+			return
+		}
+		if len(line) == 0 {
+			sawBlankLine = true
+			break
+		}
+		headerLines++
+		parts := strings.SplitN(string(line), ":", 2)
+		if len(parts) < 2 {
+			h.printf("cgi: bogus header line: %s", string(line))
+			continue
+		}
+		header, val := parts[0], parts[1]
+		header = strings.TrimSpace(header)
+		val = strings.TrimSpace(val)
+		switch {
+		case header == "Status":
+			if len(val) < 3 {
+				h.printf("cgi: bogus status (short): %q", val)
+				return
+			}
+			code, err := strconv.Atoi(val[0:3])
+			if err != nil {
+				h.printf("cgi: bogus status: %q", val)
+				h.printf("cgi: line was %q", line)
+				return
+			}
+			statusCode = code
+		default:
+			headers.Add(header, val)
+		}
+	}
+	if headerLines == 0 || !sawBlankLine {
+		rw.WriteHeader(http.StatusInternalServerError)
+		h.printf("cgi: no headers")
+		return
+	}
+
+	if loc := headers.Get("Location"); loc != "" {
+		if strings.HasPrefix(loc, "/") && h.PathLocationHandler != nil {
+			h.handleInternalRedirect(rw, req, loc)
+			return
+		}
+		if statusCode == 0 {
+			statusCode = http.StatusFound
+		}
+	}
+
+	if statusCode == 0 && headers.Get("Content-Type") == "" {
+		rw.WriteHeader(http.StatusInternalServerError)
+		h.printf("cgi: missing required Content-Type in headers")
+		return
+	}
+
+	if statusCode == 0 {
+		statusCode = http.StatusOK
+	}
+
+	// Copy headers to rw's headers, after we've decided not to
+	// go into handleInternalRedirect, which won't want its rw
+	// headers to have been touched.
+	for k, vv := range headers {
+		for _, v := range vv {
+			rw.Header().Add(k, v)
+		}
+	}
+
+	rw.WriteHeader(statusCode)
+
+	_, err = io.Copy(rw, linebody)
+	if err != nil {
+		h.printf("cgi: copy error: %v", err)
+		// And kill the child CGI process so we don't hang on
+		// the deferred cmd.Wait above if the error was just
+		// the client (rw) going away. If it was a read error
+		// (because the child died itself), then the extra
+		// kill of an already-dead process is harmless (the PID
+		// won't be reused until the Wait above).
+		cmd.Process.Kill()
+	}
+}
+
+func (h *Handler) printf(format string, v ...interface{}) {
+	if h.Logger != nil {
+		h.Logger.Printf(format, v...)
+	} else {
+		log.Printf(format, v...)
+	}
+}
+
+func (h *Handler) handleInternalRedirect(rw http.ResponseWriter, req *http.Request, path string) {
+	url, err := req.URL.Parse(path)
+	if err != nil {
+		rw.WriteHeader(http.StatusInternalServerError)
+		h.printf("cgi: error resolving local URI path %q: %v", path, err)
+		return
+	}
+	// TODO: RFC 3875 isn't clear if only GET is supported, but it
+	// suggests so: "Note that any message-body attached to the
+	// request (such as for a POST request) may not be available
+	// to the resource that is the target of the redirect."  We
+	// should do some tests against Apache to see how it handles
+	// POST, HEAD, etc. Does the internal redirect get the same
+	// method or just GET? What about incoming headers?
+	// (e.g. Cookies) Which headers, if any, are copied into the
+	// second request?
+	newReq := &http.Request{
+		Method:     "GET",
+		URL:        url,
+		Proto:      "HTTP/1.1",
+		ProtoMajor: 1,
+		ProtoMinor: 1,
+		Header:     make(http.Header),
+		Host:       url.Host,
+		RemoteAddr: req.RemoteAddr,
+		TLS:        req.TLS,
+	}
+	h.PathLocationHandler.ServeHTTP(rw, newReq)
+}
+
+func upperCaseAndUnderscore(r rune) rune {
+	switch {
+	case r >= 'a' && r <= 'z':
+		return r - ('a' - 'A')
+	case r == '-':
+		return '_'
+	case r == '=':
+		// Maybe not part of the CGI 'spec' but would mess up
+		// the environment in any case, as Go represents the
+		// environment as a slice of "key=value" strings.
+		return '_'
+	}
+	// TODO: other transformations in spec or practice?
+	return r
+}
+
+var testHookStartProcess func(*os.Process) // nil except for some tests
diff --git a/third_party/gofrontend/libgo/go/net/http/cgi/host_test.go b/third_party/gofrontend/libgo/go/net/http/cgi/host_test.go
new file mode 100644
index 0000000..b514e10
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cgi/host_test.go
@@ -0,0 +1,462 @@
+// 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.
+
+// Tests for package cgi
+
+package cgi
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"net"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+)
+
+func newRequest(httpreq string) *http.Request {
+	buf := bufio.NewReader(strings.NewReader(httpreq))
+	req, err := http.ReadRequest(buf)
+	if err != nil {
+		panic("cgi: bogus http request in test: " + httpreq)
+	}
+	req.RemoteAddr = "1.2.3.4"
+	return req
+}
+
+func runCgiTest(t *testing.T, h *Handler, httpreq string, expectedMap map[string]string) *httptest.ResponseRecorder {
+	rw := httptest.NewRecorder()
+	req := newRequest(httpreq)
+	h.ServeHTTP(rw, req)
+
+	// Make a map to hold the test map that the CGI returns.
+	m := make(map[string]string)
+	m["_body"] = rw.Body.String()
+	linesRead := 0
+readlines:
+	for {
+		line, err := rw.Body.ReadString('\n')
+		switch {
+		case err == io.EOF:
+			break readlines
+		case err != nil:
+			t.Fatalf("unexpected error reading from CGI: %v", err)
+		}
+		linesRead++
+		trimmedLine := strings.TrimRight(line, "\r\n")
+		split := strings.SplitN(trimmedLine, "=", 2)
+		if len(split) != 2 {
+			t.Fatalf("Unexpected %d parts from invalid line number %v: %q; existing map=%v",
+				len(split), linesRead, line, m)
+		}
+		m[split[0]] = split[1]
+	}
+
+	for key, expected := range expectedMap {
+		got := m[key]
+		if key == "cwd" {
+			// For Windows. golang.org/issue/4645.
+			fi1, _ := os.Stat(got)
+			fi2, _ := os.Stat(expected)
+			if os.SameFile(fi1, fi2) {
+				got = expected
+			}
+		}
+		if got != expected {
+			t.Errorf("for key %q got %q; expected %q", key, got, expected)
+		}
+	}
+	return rw
+}
+
+var cgiTested, cgiWorks bool
+
+func check(t *testing.T) {
+	if !cgiTested {
+		cgiTested = true
+		cgiWorks = exec.Command("./testdata/test.cgi").Run() == nil
+	}
+	if !cgiWorks {
+		// No Perl on Windows, needed by test.cgi
+		// TODO: make the child process be Go, not Perl.
+		t.Skip("Skipping test: test.cgi failed.")
+	}
+}
+
+func TestCGIBasicGet(t *testing.T) {
+	check(t)
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap := map[string]string{
+		"test":                  "Hello CGI",
+		"param-a":               "b",
+		"param-foo":             "bar",
+		"env-GATEWAY_INTERFACE": "CGI/1.1",
+		"env-HTTP_HOST":         "example.com",
+		"env-PATH_INFO":         "",
+		"env-QUERY_STRING":      "foo=bar&a=b",
+		"env-REMOTE_ADDR":       "1.2.3.4",
+		"env-REMOTE_HOST":       "1.2.3.4",
+		"env-REQUEST_METHOD":    "GET",
+		"env-REQUEST_URI":       "/test.cgi?foo=bar&a=b",
+		"env-SCRIPT_FILENAME":   "testdata/test.cgi",
+		"env-SCRIPT_NAME":       "/test.cgi",
+		"env-SERVER_NAME":       "example.com",
+		"env-SERVER_PORT":       "80",
+		"env-SERVER_SOFTWARE":   "go",
+	}
+	replay := runCgiTest(t, h, "GET /test.cgi?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+
+	if expected, got := "text/html", replay.Header().Get("Content-Type"); got != expected {
+		t.Errorf("got a Content-Type of %q; expected %q", got, expected)
+	}
+	if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
+		t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
+	}
+}
+
+func TestCGIBasicGetAbsPath(t *testing.T) {
+	check(t)
+	pwd, err := os.Getwd()
+	if err != nil {
+		t.Fatalf("getwd error: %v", err)
+	}
+	h := &Handler{
+		Path: pwd + "/testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap := map[string]string{
+		"env-REQUEST_URI":     "/test.cgi?foo=bar&a=b",
+		"env-SCRIPT_FILENAME": pwd + "/testdata/test.cgi",
+		"env-SCRIPT_NAME":     "/test.cgi",
+	}
+	runCgiTest(t, h, "GET /test.cgi?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestPathInfo(t *testing.T) {
+	check(t)
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap := map[string]string{
+		"param-a":             "b",
+		"env-PATH_INFO":       "/extrapath",
+		"env-QUERY_STRING":    "a=b",
+		"env-REQUEST_URI":     "/test.cgi/extrapath?a=b",
+		"env-SCRIPT_FILENAME": "testdata/test.cgi",
+		"env-SCRIPT_NAME":     "/test.cgi",
+	}
+	runCgiTest(t, h, "GET /test.cgi/extrapath?a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestPathInfoDirRoot(t *testing.T) {
+	check(t)
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/myscript/",
+	}
+	expectedMap := map[string]string{
+		"env-PATH_INFO":       "bar",
+		"env-QUERY_STRING":    "a=b",
+		"env-REQUEST_URI":     "/myscript/bar?a=b",
+		"env-SCRIPT_FILENAME": "testdata/test.cgi",
+		"env-SCRIPT_NAME":     "/myscript/",
+	}
+	runCgiTest(t, h, "GET /myscript/bar?a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestDupHeaders(t *testing.T) {
+	check(t)
+	h := &Handler{
+		Path: "testdata/test.cgi",
+	}
+	expectedMap := map[string]string{
+		"env-REQUEST_URI":     "/myscript/bar?a=b",
+		"env-SCRIPT_FILENAME": "testdata/test.cgi",
+		"env-HTTP_COOKIE":     "nom=NOM; yum=YUM",
+		"env-HTTP_X_FOO":      "val1, val2",
+	}
+	runCgiTest(t, h, "GET /myscript/bar?a=b HTTP/1.0\n"+
+		"Cookie: nom=NOM\n"+
+		"Cookie: yum=YUM\n"+
+		"X-Foo: val1\n"+
+		"X-Foo: val2\n"+
+		"Host: example.com\n\n",
+		expectedMap)
+}
+
+func TestPathInfoNoRoot(t *testing.T) {
+	check(t)
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "",
+	}
+	expectedMap := map[string]string{
+		"env-PATH_INFO":       "/bar",
+		"env-QUERY_STRING":    "a=b",
+		"env-REQUEST_URI":     "/bar?a=b",
+		"env-SCRIPT_FILENAME": "testdata/test.cgi",
+		"env-SCRIPT_NAME":     "/",
+	}
+	runCgiTest(t, h, "GET /bar?a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestCGIBasicPost(t *testing.T) {
+	check(t)
+	postReq := `POST /test.cgi?a=b HTTP/1.0
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+Content-Length: 15
+
+postfoo=postbar`
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap := map[string]string{
+		"test":               "Hello CGI",
+		"param-postfoo":      "postbar",
+		"env-REQUEST_METHOD": "POST",
+		"env-CONTENT_LENGTH": "15",
+		"env-REQUEST_URI":    "/test.cgi?a=b",
+	}
+	runCgiTest(t, h, postReq, expectedMap)
+}
+
+func chunk(s string) string {
+	return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
+}
+
+// The CGI spec doesn't allow chunked requests.
+func TestCGIPostChunked(t *testing.T) {
+	check(t)
+	postReq := `POST /test.cgi?a=b HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+Transfer-Encoding: chunked
+
+` + chunk("postfoo") + chunk("=") + chunk("postbar") + chunk("")
+
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap := map[string]string{}
+	resp := runCgiTest(t, h, postReq, expectedMap)
+	if got, expected := resp.Code, http.StatusBadRequest; got != expected {
+		t.Fatalf("Expected %v response code from chunked request body; got %d",
+			expected, got)
+	}
+}
+
+func TestRedirect(t *testing.T) {
+	check(t)
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	rec := runCgiTest(t, h, "GET /test.cgi?loc=http://foo.com/ HTTP/1.0\nHost: example.com\n\n", nil)
+	if e, g := 302, rec.Code; e != g {
+		t.Errorf("expected status code %d; got %d", e, g)
+	}
+	if e, g := "http://foo.com/", rec.Header().Get("Location"); e != g {
+		t.Errorf("expected Location header of %q; got %q", e, g)
+	}
+}
+
+func TestInternalRedirect(t *testing.T) {
+	check(t)
+	baseHandler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
+		fmt.Fprintf(rw, "basepath=%s\n", req.URL.Path)
+		fmt.Fprintf(rw, "remoteaddr=%s\n", req.RemoteAddr)
+	})
+	h := &Handler{
+		Path:                "testdata/test.cgi",
+		Root:                "/test.cgi",
+		PathLocationHandler: baseHandler,
+	}
+	expectedMap := map[string]string{
+		"basepath":   "/foo",
+		"remoteaddr": "1.2.3.4",
+	}
+	runCgiTest(t, h, "GET /test.cgi?loc=/foo HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+// TestCopyError tests that we kill the process if there's an error copying
+// its output. (for example, from the client having gone away)
+func TestCopyError(t *testing.T) {
+	check(t)
+	if runtime.GOOS == "windows" {
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	ts := httptest.NewServer(h)
+	defer ts.Close()
+
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	req, _ := http.NewRequest("GET", "http://example.com/test.cgi?bigresponse=1", nil)
+	err = req.Write(conn)
+	if err != nil {
+		t.Fatalf("Write: %v", err)
+	}
+
+	res, err := http.ReadResponse(bufio.NewReader(conn), req)
+	if err != nil {
+		t.Fatalf("ReadResponse: %v", err)
+	}
+
+	pidstr := res.Header.Get("X-CGI-Pid")
+	if pidstr == "" {
+		t.Fatalf("expected an X-CGI-Pid header in response")
+	}
+	pid, err := strconv.Atoi(pidstr)
+	if err != nil {
+		t.Fatalf("invalid X-CGI-Pid value")
+	}
+
+	var buf [5000]byte
+	n, err := io.ReadFull(res.Body, buf[:])
+	if err != nil {
+		t.Fatalf("ReadFull: %d bytes, %v", n, err)
+	}
+
+	childRunning := func() bool {
+		return isProcessRunning(t, pid)
+	}
+
+	if !childRunning() {
+		t.Fatalf("pre-conn.Close, expected child to be running")
+	}
+	conn.Close()
+
+	tries := 0
+	for tries < 25 && childRunning() {
+		time.Sleep(50 * time.Millisecond * time.Duration(tries))
+		tries++
+	}
+	if childRunning() {
+		t.Fatalf("post-conn.Close, expected child to be gone")
+	}
+}
+
+func TestDirUnix(t *testing.T) {
+	check(t)
+	if runtime.GOOS == "windows" {
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	cwd, _ := os.Getwd()
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+		Dir:  cwd,
+	}
+	expectedMap := map[string]string{
+		"cwd": cwd,
+	}
+	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+
+	cwd, _ = os.Getwd()
+	cwd = filepath.Join(cwd, "testdata")
+	h = &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	abswd, _ := filepath.EvalSymlinks(cwd)
+	expectedMap = map[string]string{
+		"cwd": abswd,
+	}
+	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestDirWindows(t *testing.T) {
+	if runtime.GOOS != "windows" {
+		t.Skip("Skipping windows specific test.")
+	}
+
+	cgifile, _ := filepath.Abs("testdata/test.cgi")
+
+	var perl string
+	var err error
+	perl, err = exec.LookPath("perl")
+	if err != nil {
+		t.Skip("Skipping test: perl not found.")
+	}
+	perl, _ = filepath.Abs(perl)
+
+	cwd, _ := os.Getwd()
+	h := &Handler{
+		Path: perl,
+		Root: "/test.cgi",
+		Dir:  cwd,
+		Args: []string{cgifile},
+		Env:  []string{"SCRIPT_FILENAME=" + cgifile},
+	}
+	expectedMap := map[string]string{
+		"cwd": cwd,
+	}
+	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+
+	// If not specify Dir on windows, working directory should be
+	// base directory of perl.
+	cwd, _ = filepath.Split(perl)
+	if cwd != "" && cwd[len(cwd)-1] == filepath.Separator {
+		cwd = cwd[:len(cwd)-1]
+	}
+	h = &Handler{
+		Path: perl,
+		Root: "/test.cgi",
+		Args: []string{cgifile},
+		Env:  []string{"SCRIPT_FILENAME=" + cgifile},
+	}
+	expectedMap = map[string]string{
+		"cwd": cwd,
+	}
+	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestEnvOverride(t *testing.T) {
+	cgifile, _ := filepath.Abs("testdata/test.cgi")
+
+	var perl string
+	var err error
+	perl, err = exec.LookPath("perl")
+	if err != nil {
+		t.Skipf("Skipping test: perl not found.")
+	}
+	perl, _ = filepath.Abs(perl)
+
+	cwd, _ := os.Getwd()
+	h := &Handler{
+		Path: perl,
+		Root: "/test.cgi",
+		Dir:  cwd,
+		Args: []string{cgifile},
+		Env: []string{
+			"SCRIPT_FILENAME=" + cgifile,
+			"REQUEST_URI=/foo/bar"},
+	}
+	expectedMap := map[string]string{
+		"cwd": cwd,
+		"env-SCRIPT_FILENAME": cgifile,
+		"env-REQUEST_URI":     "/foo/bar",
+	}
+	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cgi/matryoshka_test.go b/third_party/gofrontend/libgo/go/net/http/cgi/matryoshka_test.go
new file mode 100644
index 0000000..18c4803
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cgi/matryoshka_test.go
@@ -0,0 +1,228 @@
+// 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.
+
+// Tests a Go CGI program running under a Go CGI host process.
+// Further, the two programs are the same binary, just checking
+// their environment to figure out what mode to run in.
+
+package cgi
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"runtime"
+	"testing"
+	"time"
+)
+
+// This test is a CGI host (testing host.go) that runs its own binary
+// as a child process testing the other half of CGI (child.go).
+func TestHostingOurselves(t *testing.T) {
+	if runtime.GOOS == "nacl" {
+		t.Skip("skipping on nacl")
+	}
+
+	h := &Handler{
+		Path: os.Args[0],
+		Root: "/test.go",
+		Args: []string{"-test.run=TestBeChildCGIProcess"},
+	}
+	expectedMap := map[string]string{
+		"test":                  "Hello CGI-in-CGI",
+		"param-a":               "b",
+		"param-foo":             "bar",
+		"env-GATEWAY_INTERFACE": "CGI/1.1",
+		"env-HTTP_HOST":         "example.com",
+		"env-PATH_INFO":         "",
+		"env-QUERY_STRING":      "foo=bar&a=b",
+		"env-REMOTE_ADDR":       "1.2.3.4",
+		"env-REMOTE_HOST":       "1.2.3.4",
+		"env-REQUEST_METHOD":    "GET",
+		"env-REQUEST_URI":       "/test.go?foo=bar&a=b",
+		"env-SCRIPT_FILENAME":   os.Args[0],
+		"env-SCRIPT_NAME":       "/test.go",
+		"env-SERVER_NAME":       "example.com",
+		"env-SERVER_PORT":       "80",
+		"env-SERVER_SOFTWARE":   "go",
+	}
+	replay := runCgiTest(t, h, "GET /test.go?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+
+	if expected, got := "text/html; charset=utf-8", replay.Header().Get("Content-Type"); got != expected {
+		t.Errorf("got a Content-Type of %q; expected %q", got, expected)
+	}
+	if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
+		t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
+	}
+}
+
+type customWriterRecorder struct {
+	w io.Writer
+	*httptest.ResponseRecorder
+}
+
+func (r *customWriterRecorder) Write(p []byte) (n int, err error) {
+	return r.w.Write(p)
+}
+
+type limitWriter struct {
+	w io.Writer
+	n int
+}
+
+func (w *limitWriter) Write(p []byte) (n int, err error) {
+	if len(p) > w.n {
+		p = p[:w.n]
+	}
+	if len(p) > 0 {
+		n, err = w.w.Write(p)
+		w.n -= n
+	}
+	if w.n == 0 {
+		err = errors.New("past write limit")
+	}
+	return
+}
+
+// If there's an error copying the child's output to the parent, test
+// that we kill the child.
+func TestKillChildAfterCopyError(t *testing.T) {
+	if runtime.GOOS == "nacl" {
+		t.Skip("skipping on nacl")
+	}
+
+	defer func() { testHookStartProcess = nil }()
+	proc := make(chan *os.Process, 1)
+	testHookStartProcess = func(p *os.Process) {
+		proc <- p
+	}
+
+	h := &Handler{
+		Path: os.Args[0],
+		Root: "/test.go",
+		Args: []string{"-test.run=TestBeChildCGIProcess"},
+	}
+	req, _ := http.NewRequest("GET", "http://example.com/test.cgi?write-forever=1", nil)
+	rec := httptest.NewRecorder()
+	var out bytes.Buffer
+	const writeLen = 50 << 10
+	rw := &customWriterRecorder{&limitWriter{&out, writeLen}, rec}
+
+	donec := make(chan bool, 1)
+	go func() {
+		h.ServeHTTP(rw, req)
+		donec <- true
+	}()
+
+	select {
+	case <-donec:
+		if out.Len() != writeLen || out.Bytes()[0] != 'a' {
+			t.Errorf("unexpected output: %q", out.Bytes())
+		}
+	case <-time.After(5 * time.Second):
+		t.Errorf("timeout. ServeHTTP hung and didn't kill the child process?")
+		select {
+		case p := <-proc:
+			p.Kill()
+			t.Logf("killed process")
+		default:
+			t.Logf("didn't kill process")
+		}
+	}
+}
+
+// Test that a child handler writing only headers works.
+// golang.org/issue/7196
+func TestChildOnlyHeaders(t *testing.T) {
+	if runtime.GOOS == "nacl" {
+		t.Skip("skipping on nacl")
+	}
+
+	h := &Handler{
+		Path: os.Args[0],
+		Root: "/test.go",
+		Args: []string{"-test.run=TestBeChildCGIProcess"},
+	}
+	expectedMap := map[string]string{
+		"_body": "",
+	}
+	replay := runCgiTest(t, h, "GET /test.go?no-body=1 HTTP/1.0\nHost: example.com\n\n", expectedMap)
+	if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
+		t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
+	}
+}
+
+// golang.org/issue/7198
+func Test500WithNoHeaders(t *testing.T)     { want500Test(t, "/immediate-disconnect") }
+func Test500WithNoContentType(t *testing.T) { want500Test(t, "/no-content-type") }
+func Test500WithEmptyHeaders(t *testing.T)  { want500Test(t, "/empty-headers") }
+
+func want500Test(t *testing.T, path string) {
+	h := &Handler{
+		Path: os.Args[0],
+		Root: "/test.go",
+		Args: []string{"-test.run=TestBeChildCGIProcess"},
+	}
+	expectedMap := map[string]string{
+		"_body": "",
+	}
+	replay := runCgiTest(t, h, "GET "+path+" HTTP/1.0\nHost: example.com\n\n", expectedMap)
+	if replay.Code != 500 {
+		t.Errorf("Got code %d; want 500", replay.Code)
+	}
+}
+
+type neverEnding byte
+
+func (b neverEnding) Read(p []byte) (n int, err error) {
+	for i := range p {
+		p[i] = byte(b)
+	}
+	return len(p), nil
+}
+
+// Note: not actually a test.
+func TestBeChildCGIProcess(t *testing.T) {
+	if os.Getenv("REQUEST_METHOD") == "" {
+		// Not in a CGI environment; skipping test.
+		return
+	}
+	switch os.Getenv("REQUEST_URI") {
+	case "/immediate-disconnect":
+		os.Exit(0)
+	case "/no-content-type":
+		fmt.Printf("Content-Length: 6\n\nHello\n")
+		os.Exit(0)
+	case "/empty-headers":
+		fmt.Printf("\nHello")
+		os.Exit(0)
+	}
+	Serve(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
+		rw.Header().Set("X-Test-Header", "X-Test-Value")
+		req.ParseForm()
+		if req.FormValue("no-body") == "1" {
+			return
+		}
+		if req.FormValue("write-forever") == "1" {
+			io.Copy(rw, neverEnding('a'))
+			for {
+				time.Sleep(5 * time.Second) // hang forever, until killed
+			}
+		}
+		fmt.Fprintf(rw, "test=Hello CGI-in-CGI\n")
+		for k, vv := range req.Form {
+			for _, v := range vv {
+				fmt.Fprintf(rw, "param-%s=%s\n", k, v)
+			}
+		}
+		for _, kv := range os.Environ() {
+			fmt.Fprintf(rw, "env-%s\n", kv)
+		}
+	}))
+	os.Exit(0)
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cgi/posix_test.go b/third_party/gofrontend/libgo/go/net/http/cgi/posix_test.go
new file mode 100644
index 0000000..5ff9e7d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cgi/posix_test.go
@@ -0,0 +1,21 @@
+// Copyright 2013 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.
+
+// +build !plan9
+
+package cgi
+
+import (
+	"os"
+	"syscall"
+	"testing"
+)
+
+func isProcessRunning(t *testing.T, pid int) bool {
+	p, err := os.FindProcess(pid)
+	if err != nil {
+		return false
+	}
+	return p.Signal(syscall.Signal(0)) == nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cgi/testdata/test.cgi b/third_party/gofrontend/libgo/go/net/http/cgi/testdata/test.cgi
new file mode 100755
index 0000000..3214df6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cgi/testdata/test.cgi
@@ -0,0 +1,91 @@
+#!/usr/bin/perl
+# 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.
+#
+# Test script run as a child process under cgi_test.go
+
+use strict;
+use Cwd;
+
+binmode STDOUT;
+
+my $q = MiniCGI->new;
+my $params = $q->Vars;
+
+if ($params->{"loc"}) {
+    print "Location: $params->{loc}\r\n\r\n";
+    exit(0);
+}
+
+print "Content-Type: text/html\r\n";
+print "X-CGI-Pid: $$\r\n";
+print "X-Test-Header: X-Test-Value\r\n";
+print "\r\n";
+
+if ($params->{"bigresponse"}) {
+    # 17 MB, for OS X: golang.org/issue/4958
+    for (1..(17 * 1024)) {
+        print "A" x 1024, "\r\n";
+    }
+    exit 0;
+}
+
+print "test=Hello CGI\r\n";
+
+foreach my $k (sort keys %$params) {
+    print "param-$k=$params->{$k}\r\n";
+}
+
+foreach my $k (sort keys %ENV) {
+    my $clean_env = $ENV{$k};
+    $clean_env =~ s/[\n\r]//g;
+    print "env-$k=$clean_env\r\n";
+}
+
+# NOTE: msys perl returns /c/go/src/... not C:\go\....
+my $dir = getcwd();
+if ($^O eq 'MSWin32' || $^O eq 'msys') {
+    if ($dir =~ /^.:/) {
+        $dir =~ s!/!\\!g;
+    } else {
+        my $cmd = $ENV{'COMSPEC'} || 'c:\\windows\\system32\\cmd.exe';
+        $cmd =~ s!\\!/!g;
+        $dir = `$cmd /c cd`;
+        chomp $dir;
+    }
+}
+print "cwd=$dir\r\n";
+
+# A minimal version of CGI.pm, for people without the perl-modules
+# package installed.  (CGI.pm used to be part of the Perl core, but
+# some distros now bundle perl-base and perl-modules separately...)
+package MiniCGI;
+
+sub new {
+    my $class = shift;
+    return bless {}, $class;
+}
+
+sub Vars {
+    my $self = shift;
+    my $pairs;
+    if ($ENV{CONTENT_LENGTH}) {
+        $pairs = do { local $/; <STDIN> };
+    } else {
+        $pairs = $ENV{QUERY_STRING};
+    }
+    my $vars = {};
+    foreach my $kv (split(/&/, $pairs)) {
+        my ($k, $v) = split(/=/, $kv, 2);
+        $vars->{_urldecode($k)} = _urldecode($v);
+    }
+    return $vars;
+}
+
+sub _urldecode {
+    my $v = shift;
+    $v =~ tr/+/ /;
+    $v =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+    return $v;
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/chunked.go b/third_party/gofrontend/libgo/go/net/http/chunked.go
new file mode 100644
index 0000000..749f29d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/chunked.go
@@ -0,0 +1,203 @@
+// 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.
+
+// The wire protocol for HTTP's "chunked" Transfer-Encoding.
+
+// This code is duplicated in net/http and net/http/httputil.
+// Please make any changes in both files.
+
+package http
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+)
+
+const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
+
+var ErrLineTooLong = errors.New("header line too long")
+
+// newChunkedReader returns a new chunkedReader that translates the data read from r
+// out of HTTP "chunked" format before returning it.
+// The chunkedReader returns io.EOF when the final 0-length chunk is read.
+//
+// newChunkedReader is not needed by normal applications. The http package
+// automatically decodes chunking when reading response bodies.
+func newChunkedReader(r io.Reader) io.Reader {
+	br, ok := r.(*bufio.Reader)
+	if !ok {
+		br = bufio.NewReader(r)
+	}
+	return &chunkedReader{r: br}
+}
+
+type chunkedReader struct {
+	r   *bufio.Reader
+	n   uint64 // unread bytes in chunk
+	err error
+	buf [2]byte
+}
+
+func (cr *chunkedReader) beginChunk() {
+	// chunk-size CRLF
+	var line []byte
+	line, cr.err = readLine(cr.r)
+	if cr.err != nil {
+		return
+	}
+	cr.n, cr.err = parseHexUint(line)
+	if cr.err != nil {
+		return
+	}
+	if cr.n == 0 {
+		cr.err = io.EOF
+	}
+}
+
+func (cr *chunkedReader) chunkHeaderAvailable() bool {
+	n := cr.r.Buffered()
+	if n > 0 {
+		peek, _ := cr.r.Peek(n)
+		return bytes.IndexByte(peek, '\n') >= 0
+	}
+	return false
+}
+
+func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
+	for cr.err == nil {
+		if cr.n == 0 {
+			if n > 0 && !cr.chunkHeaderAvailable() {
+				// We've read enough. Don't potentially block
+				// reading a new chunk header.
+				break
+			}
+			cr.beginChunk()
+			continue
+		}
+		if len(b) == 0 {
+			break
+		}
+		rbuf := b
+		if uint64(len(rbuf)) > cr.n {
+			rbuf = rbuf[:cr.n]
+		}
+		var n0 int
+		n0, cr.err = cr.r.Read(rbuf)
+		n += n0
+		b = b[n0:]
+		cr.n -= uint64(n0)
+		// If we're at the end of a chunk, read the next two
+		// bytes to verify they are "\r\n".
+		if cr.n == 0 && cr.err == nil {
+			if _, cr.err = io.ReadFull(cr.r, cr.buf[:2]); cr.err == nil {
+				if cr.buf[0] != '\r' || cr.buf[1] != '\n' {
+					cr.err = errors.New("malformed chunked encoding")
+				}
+			}
+		}
+	}
+	return n, cr.err
+}
+
+// Read a line of bytes (up to \n) from b.
+// Give up if the line exceeds maxLineLength.
+// The returned bytes are a pointer into storage in
+// the bufio, so they are only valid until the next bufio read.
+func readLine(b *bufio.Reader) (p []byte, err error) {
+	if p, err = b.ReadSlice('\n'); err != nil {
+		// We always know when EOF is coming.
+		// If the caller asked for a line, there should be a line.
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		} else if err == bufio.ErrBufferFull {
+			err = ErrLineTooLong
+		}
+		return nil, err
+	}
+	if len(p) >= maxLineLength {
+		return nil, ErrLineTooLong
+	}
+	return trimTrailingWhitespace(p), nil
+}
+
+func trimTrailingWhitespace(b []byte) []byte {
+	for len(b) > 0 && isASCIISpace(b[len(b)-1]) {
+		b = b[:len(b)-1]
+	}
+	return b
+}
+
+func isASCIISpace(b byte) bool {
+	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
+}
+
+// newChunkedWriter returns a new chunkedWriter that translates writes into HTTP
+// "chunked" format before writing them to w. Closing the returned chunkedWriter
+// sends the final 0-length chunk that marks the end of the stream.
+//
+// newChunkedWriter is not needed by normal applications. The http
+// package adds chunking automatically if handlers don't set a
+// Content-Length header. Using newChunkedWriter inside a handler
+// would result in double chunking or chunking with a Content-Length
+// length, both of which are wrong.
+func newChunkedWriter(w io.Writer) io.WriteCloser {
+	return &chunkedWriter{w}
+}
+
+// Writing to chunkedWriter translates to writing in HTTP chunked Transfer
+// Encoding wire format to the underlying Wire chunkedWriter.
+type chunkedWriter struct {
+	Wire io.Writer
+}
+
+// Write the contents of data as one chunk to Wire.
+// NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has
+// a bug since it does not check for success of io.WriteString
+func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
+
+	// Don't send 0-length data. It looks like EOF for chunked encoding.
+	if len(data) == 0 {
+		return 0, nil
+	}
+
+	if _, err = fmt.Fprintf(cw.Wire, "%x\r\n", len(data)); err != nil {
+		return 0, err
+	}
+	if n, err = cw.Wire.Write(data); err != nil {
+		return
+	}
+	if n != len(data) {
+		err = io.ErrShortWrite
+		return
+	}
+	_, err = io.WriteString(cw.Wire, "\r\n")
+
+	return
+}
+
+func (cw *chunkedWriter) Close() error {
+	_, err := io.WriteString(cw.Wire, "0\r\n")
+	return err
+}
+
+func parseHexUint(v []byte) (n uint64, err error) {
+	for _, b := range v {
+		n <<= 4
+		switch {
+		case '0' <= b && b <= '9':
+			b = b - '0'
+		case 'a' <= b && b <= 'f':
+			b = b - 'a' + 10
+		case 'A' <= b && b <= 'F':
+			b = b - 'A' + 10
+		default:
+			return 0, errors.New("invalid byte in chunk length")
+		}
+		n |= uint64(b)
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/chunked_test.go b/third_party/gofrontend/libgo/go/net/http/chunked_test.go
new file mode 100644
index 0000000..3454479
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/chunked_test.go
@@ -0,0 +1,159 @@
+// 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.
+
+// This code is duplicated in net/http and net/http/httputil.
+// Please make any changes in both files.
+
+package http
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+func TestChunk(t *testing.T) {
+	var b bytes.Buffer
+
+	w := newChunkedWriter(&b)
+	const chunk1 = "hello, "
+	const chunk2 = "world! 0123456789abcdef"
+	w.Write([]byte(chunk1))
+	w.Write([]byte(chunk2))
+	w.Close()
+
+	if g, e := b.String(), "7\r\nhello, \r\n17\r\nworld! 0123456789abcdef\r\n0\r\n"; g != e {
+		t.Fatalf("chunk writer wrote %q; want %q", g, e)
+	}
+
+	r := newChunkedReader(&b)
+	data, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Logf(`data: "%s"`, data)
+		t.Fatalf("ReadAll from reader: %v", err)
+	}
+	if g, e := string(data), chunk1+chunk2; g != e {
+		t.Errorf("chunk reader read %q; want %q", g, e)
+	}
+}
+
+func TestChunkReadMultiple(t *testing.T) {
+	// Bunch of small chunks, all read together.
+	{
+		var b bytes.Buffer
+		w := newChunkedWriter(&b)
+		w.Write([]byte("foo"))
+		w.Write([]byte("bar"))
+		w.Close()
+
+		r := newChunkedReader(&b)
+		buf := make([]byte, 10)
+		n, err := r.Read(buf)
+		if n != 6 || err != io.EOF {
+			t.Errorf("Read = %d, %v; want 6, EOF", n, err)
+		}
+		buf = buf[:n]
+		if string(buf) != "foobar" {
+			t.Errorf("Read = %q; want %q", buf, "foobar")
+		}
+	}
+
+	// One big chunk followed by a little chunk, but the small bufio.Reader size
+	// should prevent the second chunk header from being read.
+	{
+		var b bytes.Buffer
+		w := newChunkedWriter(&b)
+		// fillBufChunk is 11 bytes + 3 bytes header + 2 bytes footer = 16 bytes,
+		// the same as the bufio ReaderSize below (the minimum), so even
+		// though we're going to try to Read with a buffer larger enough to also
+		// receive "foo", the second chunk header won't be read yet.
+		const fillBufChunk = "0123456789a"
+		const shortChunk = "foo"
+		w.Write([]byte(fillBufChunk))
+		w.Write([]byte(shortChunk))
+		w.Close()
+
+		r := newChunkedReader(bufio.NewReaderSize(&b, 16))
+		buf := make([]byte, len(fillBufChunk)+len(shortChunk))
+		n, err := r.Read(buf)
+		if n != len(fillBufChunk) || err != nil {
+			t.Errorf("Read = %d, %v; want %d, nil", n, err, len(fillBufChunk))
+		}
+		buf = buf[:n]
+		if string(buf) != fillBufChunk {
+			t.Errorf("Read = %q; want %q", buf, fillBufChunk)
+		}
+
+		n, err = r.Read(buf)
+		if n != len(shortChunk) || err != io.EOF {
+			t.Errorf("Read = %d, %v; want %d, EOF", n, err, len(shortChunk))
+		}
+	}
+
+	// And test that we see an EOF chunk, even though our buffer is already full:
+	{
+		r := newChunkedReader(bufio.NewReader(strings.NewReader("3\r\nfoo\r\n0\r\n")))
+		buf := make([]byte, 3)
+		n, err := r.Read(buf)
+		if n != 3 || err != io.EOF {
+			t.Errorf("Read = %d, %v; want 3, EOF", n, err)
+		}
+		if string(buf) != "foo" {
+			t.Errorf("buf = %q; want foo", buf)
+		}
+	}
+}
+
+func TestChunkReaderAllocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	var buf bytes.Buffer
+	w := newChunkedWriter(&buf)
+	a, b, c := []byte("aaaaaa"), []byte("bbbbbbbbbbbb"), []byte("cccccccccccccccccccccccc")
+	w.Write(a)
+	w.Write(b)
+	w.Write(c)
+	w.Close()
+
+	readBuf := make([]byte, len(a)+len(b)+len(c)+1)
+	byter := bytes.NewReader(buf.Bytes())
+	bufr := bufio.NewReader(byter)
+	mallocs := testing.AllocsPerRun(100, func() {
+		byter.Seek(0, 0)
+		bufr.Reset(byter)
+		r := newChunkedReader(bufr)
+		n, err := io.ReadFull(r, readBuf)
+		if n != len(readBuf)-1 {
+			t.Fatalf("read %d bytes; want %d", n, len(readBuf)-1)
+		}
+		if err != io.ErrUnexpectedEOF {
+			t.Fatalf("read error = %v; want ErrUnexpectedEOF", err)
+		}
+	})
+	if mallocs > 1.5 {
+		t.Errorf("mallocs = %v; want 1", mallocs)
+	}
+}
+
+func TestParseHexUint(t *testing.T) {
+	for i := uint64(0); i <= 1234; i++ {
+		line := []byte(fmt.Sprintf("%x", i))
+		got, err := parseHexUint(line)
+		if err != nil {
+			t.Fatalf("on %d: %v", i, err)
+		}
+		if got != i {
+			t.Errorf("for input %q = %d; want %d", line, got, i)
+		}
+	}
+	_, err := parseHexUint([]byte("bogus"))
+	if err == nil {
+		t.Error("expected error on bogus input")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/client.go b/third_party/gofrontend/libgo/go/net/http/client.go
new file mode 100644
index 0000000..a5a3abe
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/client.go
@@ -0,0 +1,487 @@
+// 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.
+
+// HTTP client. See RFC 2616.
+//
+// This is the high-level Client interface.
+// The low-level implementation is in transport.go.
+
+package http
+
+import (
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/url"
+	"strings"
+	"sync"
+	"time"
+)
+
+// A Client is an HTTP client. Its zero value (DefaultClient) is a
+// usable client that uses DefaultTransport.
+//
+// The Client's Transport typically has internal state (cached TCP
+// connections), so Clients should be reused instead of created as
+// needed. Clients are safe for concurrent use by multiple goroutines.
+//
+// A Client is higher-level than a RoundTripper (such as Transport)
+// and additionally handles HTTP details such as cookies and
+// redirects.
+type Client struct {
+	// Transport specifies the mechanism by which individual
+	// HTTP requests are made.
+	// If nil, DefaultTransport is used.
+	Transport RoundTripper
+
+	// CheckRedirect specifies the policy for handling redirects.
+	// If CheckRedirect is not nil, the client calls it before
+	// following an HTTP redirect. The arguments req and via are
+	// the upcoming request and the requests made already, oldest
+	// first. If CheckRedirect returns an error, the Client's Get
+	// method returns both the previous Response and
+	// CheckRedirect's error (wrapped in a url.Error) instead of
+	// issuing the Request req.
+	//
+	// If CheckRedirect is nil, the Client uses its default policy,
+	// which is to stop after 10 consecutive requests.
+	CheckRedirect func(req *Request, via []*Request) error
+
+	// Jar specifies the cookie jar.
+	// If Jar is nil, cookies are not sent in requests and ignored
+	// in responses.
+	Jar CookieJar
+
+	// Timeout specifies a time limit for requests made by this
+	// Client. The timeout includes connection time, any
+	// redirects, and reading the response body. The timer remains
+	// running after Get, Head, Post, or Do return and will
+	// interrupt reading of the Response.Body.
+	//
+	// A Timeout of zero means no timeout.
+	//
+	// The Client's Transport must support the CancelRequest
+	// method or Client will return errors when attempting to make
+	// a request with Get, Head, Post, or Do. Client's default
+	// Transport (DefaultTransport) supports CancelRequest.
+	Timeout time.Duration
+}
+
+// DefaultClient is the default Client and is used by Get, Head, and Post.
+var DefaultClient = &Client{}
+
+// RoundTripper is an interface representing the ability to execute a
+// single HTTP transaction, obtaining the Response for a given Request.
+//
+// A RoundTripper must be safe for concurrent use by multiple
+// goroutines.
+type RoundTripper interface {
+	// RoundTrip executes a single HTTP transaction, returning
+	// the Response for the request req.  RoundTrip should not
+	// attempt to interpret the response.  In particular,
+	// RoundTrip must return err == nil if it obtained a response,
+	// regardless of the response's HTTP status code.  A non-nil
+	// err should be reserved for failure to obtain a response.
+	// Similarly, RoundTrip should not attempt to handle
+	// higher-level protocol details such as redirects,
+	// authentication, or cookies.
+	//
+	// RoundTrip should not modify the request, except for
+	// consuming and closing the Body, including on errors. The
+	// request's URL and Header fields are guaranteed to be
+	// initialized.
+	RoundTrip(*Request) (*Response, error)
+}
+
+// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
+// return true if the string includes a port.
+func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
+
+// Used in Send to implement io.ReadCloser by bundling together the
+// bufio.Reader through which we read the response, and the underlying
+// network connection.
+type readClose struct {
+	io.Reader
+	io.Closer
+}
+
+func (c *Client) send(req *Request) (*Response, error) {
+	if c.Jar != nil {
+		for _, cookie := range c.Jar.Cookies(req.URL) {
+			req.AddCookie(cookie)
+		}
+	}
+	resp, err := send(req, c.transport())
+	if err != nil {
+		return nil, err
+	}
+	if c.Jar != nil {
+		if rc := resp.Cookies(); len(rc) > 0 {
+			c.Jar.SetCookies(req.URL, rc)
+		}
+	}
+	return resp, err
+}
+
+// Do sends an HTTP request and returns an HTTP response, following
+// policy (e.g. redirects, cookies, auth) as configured on the client.
+//
+// An error is returned if caused by client policy (such as
+// CheckRedirect), or if there was an HTTP protocol error.
+// A non-2xx response doesn't cause an error.
+//
+// When err is nil, resp always contains a non-nil resp.Body.
+//
+// Callers should close resp.Body when done reading from it. If
+// resp.Body is not closed, the Client's underlying RoundTripper
+// (typically Transport) may not be able to re-use a persistent TCP
+// connection to the server for a subsequent "keep-alive" request.
+//
+// The request Body, if non-nil, will be closed by the underlying
+// Transport, even on errors.
+//
+// Generally Get, Post, or PostForm will be used instead of Do.
+func (c *Client) Do(req *Request) (resp *Response, err error) {
+	if req.Method == "GET" || req.Method == "HEAD" {
+		return c.doFollowingRedirects(req, shouldRedirectGet)
+	}
+	if req.Method == "POST" || req.Method == "PUT" {
+		return c.doFollowingRedirects(req, shouldRedirectPost)
+	}
+	return c.send(req)
+}
+
+func (c *Client) transport() RoundTripper {
+	if c.Transport != nil {
+		return c.Transport
+	}
+	return DefaultTransport
+}
+
+// send issues an HTTP request.
+// Caller should close resp.Body when done reading from it.
+func send(req *Request, t RoundTripper) (resp *Response, err error) {
+	if t == nil {
+		req.closeBody()
+		return nil, errors.New("http: no Client.Transport or DefaultTransport")
+	}
+
+	if req.URL == nil {
+		req.closeBody()
+		return nil, errors.New("http: nil Request.URL")
+	}
+
+	if req.RequestURI != "" {
+		req.closeBody()
+		return nil, errors.New("http: Request.RequestURI can't be set in client requests.")
+	}
+
+	// Most the callers of send (Get, Post, et al) don't need
+	// Headers, leaving it uninitialized.  We guarantee to the
+	// Transport that this has been initialized, though.
+	if req.Header == nil {
+		req.Header = make(Header)
+	}
+
+	if u := req.URL.User; u != nil {
+		username := u.Username()
+		password, _ := u.Password()
+		req.Header.Set("Authorization", "Basic "+basicAuth(username, password))
+	}
+	resp, err = t.RoundTrip(req)
+	if err != nil {
+		if resp != nil {
+			log.Printf("RoundTripper returned a response & error; ignoring response")
+		}
+		return nil, err
+	}
+	return resp, nil
+}
+
+// See 2 (end of page 4) http://www.ietf.org/rfc/rfc2617.txt
+// "To receive authorization, the client sends the userid and password,
+// separated by a single colon (":") character, within a base64
+// encoded string in the credentials."
+// It is not meant to be urlencoded.
+func basicAuth(username, password string) string {
+	auth := username + ":" + password
+	return base64.StdEncoding.EncodeToString([]byte(auth))
+}
+
+// True if the specified HTTP status code is one for which the Get utility should
+// automatically redirect.
+func shouldRedirectGet(statusCode int) bool {
+	switch statusCode {
+	case StatusMovedPermanently, StatusFound, StatusSeeOther, StatusTemporaryRedirect:
+		return true
+	}
+	return false
+}
+
+// True if the specified HTTP status code is one for which the Post utility should
+// automatically redirect.
+func shouldRedirectPost(statusCode int) bool {
+	switch statusCode {
+	case StatusFound, StatusSeeOther:
+		return true
+	}
+	return false
+}
+
+// Get issues a GET to the specified URL.  If the response is one of the following
+// redirect codes, Get follows the redirect, up to a maximum of 10 redirects:
+//
+//    301 (Moved Permanently)
+//    302 (Found)
+//    303 (See Other)
+//    307 (Temporary Redirect)
+//
+// An error is returned if there were too many redirects or if there
+// was an HTTP protocol error. A non-2xx response doesn't cause an
+// error.
+//
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
+//
+// Get is a wrapper around DefaultClient.Get.
+func Get(url string) (resp *Response, err error) {
+	return DefaultClient.Get(url)
+}
+
+// Get issues a GET to the specified URL.  If the response is one of the
+// following redirect codes, Get follows the redirect after calling the
+// Client's CheckRedirect function.
+//
+//    301 (Moved Permanently)
+//    302 (Found)
+//    303 (See Other)
+//    307 (Temporary Redirect)
+//
+// An error is returned if the Client's CheckRedirect function fails
+// or if there was an HTTP protocol error. A non-2xx response doesn't
+// cause an error.
+//
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
+func (c *Client) Get(url string) (resp *Response, err error) {
+	req, err := NewRequest("GET", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	return c.doFollowingRedirects(req, shouldRedirectGet)
+}
+
+func (c *Client) doFollowingRedirects(ireq *Request, shouldRedirect func(int) bool) (resp *Response, err error) {
+	var base *url.URL
+	redirectChecker := c.CheckRedirect
+	if redirectChecker == nil {
+		redirectChecker = defaultCheckRedirect
+	}
+	var via []*Request
+
+	if ireq.URL == nil {
+		ireq.closeBody()
+		return nil, errors.New("http: nil Request.URL")
+	}
+
+	var reqmu sync.Mutex // guards req
+	req := ireq
+
+	var timer *time.Timer
+	if c.Timeout > 0 {
+		type canceler interface {
+			CancelRequest(*Request)
+		}
+		tr, ok := c.transport().(canceler)
+		if !ok {
+			return nil, fmt.Errorf("net/http: Client Transport of type %T doesn't support CancelRequest; Timeout not supported", c.transport())
+		}
+		timer = time.AfterFunc(c.Timeout, func() {
+			reqmu.Lock()
+			defer reqmu.Unlock()
+			tr.CancelRequest(req)
+		})
+	}
+
+	urlStr := "" // next relative or absolute URL to fetch (after first request)
+	redirectFailed := false
+	for redirect := 0; ; redirect++ {
+		if redirect != 0 {
+			nreq := new(Request)
+			nreq.Method = ireq.Method
+			if ireq.Method == "POST" || ireq.Method == "PUT" {
+				nreq.Method = "GET"
+			}
+			nreq.Header = make(Header)
+			nreq.URL, err = base.Parse(urlStr)
+			if err != nil {
+				break
+			}
+			if len(via) > 0 {
+				// Add the Referer header.
+				lastReq := via[len(via)-1]
+				if lastReq.URL.Scheme != "https" {
+					nreq.Header.Set("Referer", lastReq.URL.String())
+				}
+
+				err = redirectChecker(nreq, via)
+				if err != nil {
+					redirectFailed = true
+					break
+				}
+			}
+			reqmu.Lock()
+			req = nreq
+			reqmu.Unlock()
+		}
+
+		urlStr = req.URL.String()
+		if resp, err = c.send(req); err != nil {
+			break
+		}
+
+		if shouldRedirect(resp.StatusCode) {
+			// Read the body if small so underlying TCP connection will be re-used.
+			// No need to check for errors: if it fails, Transport won't reuse it anyway.
+			const maxBodySlurpSize = 2 << 10
+			if resp.ContentLength == -1 || resp.ContentLength <= maxBodySlurpSize {
+				io.CopyN(ioutil.Discard, resp.Body, maxBodySlurpSize)
+			}
+			resp.Body.Close()
+			if urlStr = resp.Header.Get("Location"); urlStr == "" {
+				err = errors.New(fmt.Sprintf("%d response missing Location header", resp.StatusCode))
+				break
+			}
+			base = req.URL
+			via = append(via, req)
+			continue
+		}
+		if timer != nil {
+			resp.Body = &cancelTimerBody{timer, resp.Body}
+		}
+		return resp, nil
+	}
+
+	method := ireq.Method
+	urlErr := &url.Error{
+		Op:  method[0:1] + strings.ToLower(method[1:]),
+		URL: urlStr,
+		Err: err,
+	}
+
+	if redirectFailed {
+		// Special case for Go 1 compatibility: return both the response
+		// and an error if the CheckRedirect function failed.
+		// See http://golang.org/issue/3795
+		return resp, urlErr
+	}
+
+	if resp != nil {
+		resp.Body.Close()
+	}
+	return nil, urlErr
+}
+
+func defaultCheckRedirect(req *Request, via []*Request) error {
+	if len(via) >= 10 {
+		return errors.New("stopped after 10 redirects")
+	}
+	return nil
+}
+
+// Post issues a POST to the specified URL.
+//
+// Caller should close resp.Body when done reading from it.
+//
+// Post is a wrapper around DefaultClient.Post
+func Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
+	return DefaultClient.Post(url, bodyType, body)
+}
+
+// Post issues a POST to the specified URL.
+//
+// Caller should close resp.Body when done reading from it.
+//
+// If the provided body is also an io.Closer, it is closed after the
+// request.
+func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
+	req, err := NewRequest("POST", url, body)
+	if err != nil {
+		return nil, err
+	}
+	req.Header.Set("Content-Type", bodyType)
+	return c.doFollowingRedirects(req, shouldRedirectPost)
+}
+
+// PostForm issues a POST to the specified URL, with data's keys and
+// values URL-encoded as the request body.
+//
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
+//
+// PostForm is a wrapper around DefaultClient.PostForm
+func PostForm(url string, data url.Values) (resp *Response, err error) {
+	return DefaultClient.PostForm(url, data)
+}
+
+// PostForm issues a POST to the specified URL,
+// with data's keys and values urlencoded as the request body.
+//
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
+func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) {
+	return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
+
+// Head issues a HEAD to the specified URL.  If the response is one of the
+// following redirect codes, Head follows the redirect after calling the
+// Client's CheckRedirect function.
+//
+//    301 (Moved Permanently)
+//    302 (Found)
+//    303 (See Other)
+//    307 (Temporary Redirect)
+//
+// Head is a wrapper around DefaultClient.Head
+func Head(url string) (resp *Response, err error) {
+	return DefaultClient.Head(url)
+}
+
+// Head issues a HEAD to the specified URL.  If the response is one of the
+// following redirect codes, Head follows the redirect after calling the
+// Client's CheckRedirect function.
+//
+//    301 (Moved Permanently)
+//    302 (Found)
+//    303 (See Other)
+//    307 (Temporary Redirect)
+func (c *Client) Head(url string) (resp *Response, err error) {
+	req, err := NewRequest("HEAD", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	return c.doFollowingRedirects(req, shouldRedirectGet)
+}
+
+type cancelTimerBody struct {
+	t  *time.Timer
+	rc io.ReadCloser
+}
+
+func (b *cancelTimerBody) Read(p []byte) (n int, err error) {
+	n, err = b.rc.Read(p)
+	if err == io.EOF {
+		b.t.Stop()
+	}
+	return
+}
+
+func (b *cancelTimerBody) Close() error {
+	err := b.rc.Close()
+	b.t.Stop()
+	return err
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/client_test.go b/third_party/gofrontend/libgo/go/net/http/client_test.go
new file mode 100644
index 0000000..6392c1b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/client_test.go
@@ -0,0 +1,1038 @@
+// 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.
+
+// Tests for client.go
+
+package http_test
+
+import (
+	"bytes"
+	"crypto/tls"
+	"crypto/x509"
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	. "net/http"
+	"net/http/httptest"
+	"net/url"
+	"reflect"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"testing"
+	"time"
+)
+
+var robotsTxtHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
+	w.Header().Set("Last-Modified", "sometime")
+	fmt.Fprintf(w, "User-agent: go\nDisallow: /something/")
+})
+
+// pedanticReadAll works like ioutil.ReadAll but additionally
+// verifies that r obeys the documented io.Reader contract.
+func pedanticReadAll(r io.Reader) (b []byte, err error) {
+	var bufa [64]byte
+	buf := bufa[:]
+	for {
+		n, err := r.Read(buf)
+		if n == 0 && err == nil {
+			return nil, fmt.Errorf("Read: n=0 with err=nil")
+		}
+		b = append(b, buf[:n]...)
+		if err == io.EOF {
+			n, err := r.Read(buf)
+			if n != 0 || err != io.EOF {
+				return nil, fmt.Errorf("Read: n=%d err=%#v after EOF", n, err)
+			}
+			return b, nil
+		}
+		if err != nil {
+			return b, err
+		}
+	}
+}
+
+type chanWriter chan string
+
+func (w chanWriter) Write(p []byte) (n int, err error) {
+	w <- string(p)
+	return len(p), nil
+}
+
+func TestClient(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(robotsTxtHandler)
+	defer ts.Close()
+
+	r, err := Get(ts.URL)
+	var b []byte
+	if err == nil {
+		b, err = pedanticReadAll(r.Body)
+		r.Body.Close()
+	}
+	if err != nil {
+		t.Error(err)
+	} else if s := string(b); !strings.HasPrefix(s, "User-agent:") {
+		t.Errorf("Incorrect page body (did not begin with User-agent): %q", s)
+	}
+}
+
+func TestClientHead(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(robotsTxtHandler)
+	defer ts.Close()
+
+	r, err := Head(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if _, ok := r.Header["Last-Modified"]; !ok {
+		t.Error("Last-Modified header not found.")
+	}
+}
+
+type recordingTransport struct {
+	req *Request
+}
+
+func (t *recordingTransport) RoundTrip(req *Request) (resp *Response, err error) {
+	t.req = req
+	return nil, errors.New("dummy impl")
+}
+
+func TestGetRequestFormat(t *testing.T) {
+	defer afterTest(t)
+	tr := &recordingTransport{}
+	client := &Client{Transport: tr}
+	url := "http://dummy.faketld/"
+	client.Get(url) // Note: doesn't hit network
+	if tr.req.Method != "GET" {
+		t.Errorf("expected method %q; got %q", "GET", tr.req.Method)
+	}
+	if tr.req.URL.String() != url {
+		t.Errorf("expected URL %q; got %q", url, tr.req.URL.String())
+	}
+	if tr.req.Header == nil {
+		t.Errorf("expected non-nil request Header")
+	}
+}
+
+func TestPostRequestFormat(t *testing.T) {
+	defer afterTest(t)
+	tr := &recordingTransport{}
+	client := &Client{Transport: tr}
+
+	url := "http://dummy.faketld/"
+	json := `{"key":"value"}`
+	b := strings.NewReader(json)
+	client.Post(url, "application/json", b) // Note: doesn't hit network
+
+	if tr.req.Method != "POST" {
+		t.Errorf("got method %q, want %q", tr.req.Method, "POST")
+	}
+	if tr.req.URL.String() != url {
+		t.Errorf("got URL %q, want %q", tr.req.URL.String(), url)
+	}
+	if tr.req.Header == nil {
+		t.Fatalf("expected non-nil request Header")
+	}
+	if tr.req.Close {
+		t.Error("got Close true, want false")
+	}
+	if g, e := tr.req.ContentLength, int64(len(json)); g != e {
+		t.Errorf("got ContentLength %d, want %d", g, e)
+	}
+}
+
+func TestPostFormRequestFormat(t *testing.T) {
+	defer afterTest(t)
+	tr := &recordingTransport{}
+	client := &Client{Transport: tr}
+
+	urlStr := "http://dummy.faketld/"
+	form := make(url.Values)
+	form.Set("foo", "bar")
+	form.Add("foo", "bar2")
+	form.Set("bar", "baz")
+	client.PostForm(urlStr, form) // Note: doesn't hit network
+
+	if tr.req.Method != "POST" {
+		t.Errorf("got method %q, want %q", tr.req.Method, "POST")
+	}
+	if tr.req.URL.String() != urlStr {
+		t.Errorf("got URL %q, want %q", tr.req.URL.String(), urlStr)
+	}
+	if tr.req.Header == nil {
+		t.Fatalf("expected non-nil request Header")
+	}
+	if g, e := tr.req.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; g != e {
+		t.Errorf("got Content-Type %q, want %q", g, e)
+	}
+	if tr.req.Close {
+		t.Error("got Close true, want false")
+	}
+	// Depending on map iteration, body can be either of these.
+	expectedBody := "foo=bar&foo=bar2&bar=baz"
+	expectedBody1 := "bar=baz&foo=bar&foo=bar2"
+	if g, e := tr.req.ContentLength, int64(len(expectedBody)); g != e {
+		t.Errorf("got ContentLength %d, want %d", g, e)
+	}
+	bodyb, err := ioutil.ReadAll(tr.req.Body)
+	if err != nil {
+		t.Fatalf("ReadAll on req.Body: %v", err)
+	}
+	if g := string(bodyb); g != expectedBody && g != expectedBody1 {
+		t.Errorf("got body %q, want %q or %q", g, expectedBody, expectedBody1)
+	}
+}
+
+func TestClientRedirects(t *testing.T) {
+	defer afterTest(t)
+	var ts *httptest.Server
+	ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		n, _ := strconv.Atoi(r.FormValue("n"))
+		// Test Referer header. (7 is arbitrary position to test at)
+		if n == 7 {
+			if g, e := r.Referer(), ts.URL+"/?n=6"; e != g {
+				t.Errorf("on request ?n=7, expected referer of %q; got %q", e, g)
+			}
+		}
+		if n < 15 {
+			Redirect(w, r, fmt.Sprintf("/?n=%d", n+1), StatusFound)
+			return
+		}
+		fmt.Fprintf(w, "n=%d", n)
+	}))
+	defer ts.Close()
+
+	c := &Client{}
+	_, err := c.Get(ts.URL)
+	if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with default client Get, expected error %q, got %q", e, g)
+	}
+
+	// HEAD request should also have the ability to follow redirects.
+	_, err = c.Head(ts.URL)
+	if e, g := "Head /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with default client Head, expected error %q, got %q", e, g)
+	}
+
+	// Do should also follow redirects.
+	greq, _ := NewRequest("GET", ts.URL, nil)
+	_, err = c.Do(greq)
+	if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with default client Do, expected error %q, got %q", e, g)
+	}
+
+	var checkErr error
+	var lastVia []*Request
+	c = &Client{CheckRedirect: func(_ *Request, via []*Request) error {
+		lastVia = via
+		return checkErr
+	}}
+	res, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get error: %v", err)
+	}
+	res.Body.Close()
+	finalUrl := res.Request.URL.String()
+	if e, g := "<nil>", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with custom client, expected error %q, got %q", e, g)
+	}
+	if !strings.HasSuffix(finalUrl, "/?n=15") {
+		t.Errorf("expected final url to end in /?n=15; got url %q", finalUrl)
+	}
+	if e, g := 15, len(lastVia); e != g {
+		t.Errorf("expected lastVia to have contained %d elements; got %d", e, g)
+	}
+
+	checkErr = errors.New("no redirects allowed")
+	res, err = c.Get(ts.URL)
+	if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr {
+		t.Errorf("with redirects forbidden, expected a *url.Error with our 'no redirects allowed' error inside; got %#v (%q)", err, err)
+	}
+	if res == nil {
+		t.Fatalf("Expected a non-nil Response on CheckRedirect failure (http://golang.org/issue/3795)")
+	}
+	res.Body.Close()
+	if res.Header.Get("Location") == "" {
+		t.Errorf("no Location header in Response")
+	}
+}
+
+func TestPostRedirects(t *testing.T) {
+	defer afterTest(t)
+	var log struct {
+		sync.Mutex
+		bytes.Buffer
+	}
+	var ts *httptest.Server
+	ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		log.Lock()
+		fmt.Fprintf(&log.Buffer, "%s %s ", r.Method, r.RequestURI)
+		log.Unlock()
+		if v := r.URL.Query().Get("code"); v != "" {
+			code, _ := strconv.Atoi(v)
+			if code/100 == 3 {
+				w.Header().Set("Location", ts.URL)
+			}
+			w.WriteHeader(code)
+		}
+	}))
+	defer ts.Close()
+	tests := []struct {
+		suffix string
+		want   int // response code
+	}{
+		{"/", 200},
+		{"/?code=301", 301},
+		{"/?code=302", 200},
+		{"/?code=303", 200},
+		{"/?code=404", 404},
+	}
+	for _, tt := range tests {
+		res, err := Post(ts.URL+tt.suffix, "text/plain", strings.NewReader("Some content"))
+		if err != nil {
+			t.Fatal(err)
+		}
+		if res.StatusCode != tt.want {
+			t.Errorf("POST %s: status code = %d; want %d", tt.suffix, res.StatusCode, tt.want)
+		}
+	}
+	log.Lock()
+	got := log.String()
+	log.Unlock()
+	want := "POST / POST /?code=301 POST /?code=302 GET / POST /?code=303 GET / POST /?code=404 "
+	if got != want {
+		t.Errorf("Log differs.\n Got: %q\nWant: %q", got, want)
+	}
+}
+
+var expectedCookies = []*Cookie{
+	{Name: "ChocolateChip", Value: "tasty"},
+	{Name: "First", Value: "Hit"},
+	{Name: "Second", Value: "Hit"},
+}
+
+var echoCookiesRedirectHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
+	for _, cookie := range r.Cookies() {
+		SetCookie(w, cookie)
+	}
+	if r.URL.Path == "/" {
+		SetCookie(w, expectedCookies[1])
+		Redirect(w, r, "/second", StatusMovedPermanently)
+	} else {
+		SetCookie(w, expectedCookies[2])
+		w.Write([]byte("hello"))
+	}
+})
+
+func TestClientSendsCookieFromJar(t *testing.T) {
+	tr := &recordingTransport{}
+	client := &Client{Transport: tr}
+	client.Jar = &TestJar{perURL: make(map[string][]*Cookie)}
+	us := "http://dummy.faketld/"
+	u, _ := url.Parse(us)
+	client.Jar.SetCookies(u, expectedCookies)
+
+	client.Get(us) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+
+	client.Head(us) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+
+	client.Post(us, "text/plain", strings.NewReader("body")) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+
+	client.PostForm(us, url.Values{}) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+
+	req, _ := NewRequest("GET", us, nil)
+	client.Do(req) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+
+	req, _ = NewRequest("POST", us, nil)
+	client.Do(req) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+}
+
+// Just enough correctness for our redirect tests. Uses the URL.Host as the
+// scope of all cookies.
+type TestJar struct {
+	m      sync.Mutex
+	perURL map[string][]*Cookie
+}
+
+func (j *TestJar) SetCookies(u *url.URL, cookies []*Cookie) {
+	j.m.Lock()
+	defer j.m.Unlock()
+	if j.perURL == nil {
+		j.perURL = make(map[string][]*Cookie)
+	}
+	j.perURL[u.Host] = cookies
+}
+
+func (j *TestJar) Cookies(u *url.URL) []*Cookie {
+	j.m.Lock()
+	defer j.m.Unlock()
+	return j.perURL[u.Host]
+}
+
+func TestRedirectCookiesJar(t *testing.T) {
+	defer afterTest(t)
+	var ts *httptest.Server
+	ts = httptest.NewServer(echoCookiesRedirectHandler)
+	defer ts.Close()
+	c := &Client{
+		Jar: new(TestJar),
+	}
+	u, _ := url.Parse(ts.URL)
+	c.Jar.SetCookies(u, []*Cookie{expectedCookies[0]})
+	resp, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	resp.Body.Close()
+	matchReturnedCookies(t, expectedCookies, resp.Cookies())
+}
+
+func matchReturnedCookies(t *testing.T, expected, given []*Cookie) {
+	if len(given) != len(expected) {
+		t.Logf("Received cookies: %v", given)
+		t.Errorf("Expected %d cookies, got %d", len(expected), len(given))
+	}
+	for _, ec := range expected {
+		foundC := false
+		for _, c := range given {
+			if ec.Name == c.Name && ec.Value == c.Value {
+				foundC = true
+				break
+			}
+		}
+		if !foundC {
+			t.Errorf("Missing cookie %v", ec)
+		}
+	}
+}
+
+func TestJarCalls(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		pathSuffix := r.RequestURI[1:]
+		if r.RequestURI == "/nosetcookie" {
+			return // dont set cookies for this path
+		}
+		SetCookie(w, &Cookie{Name: "name" + pathSuffix, Value: "val" + pathSuffix})
+		if r.RequestURI == "/" {
+			Redirect(w, r, "http://secondhost.fake/secondpath", 302)
+		}
+	}))
+	defer ts.Close()
+	jar := new(RecordingJar)
+	c := &Client{
+		Jar: jar,
+		Transport: &Transport{
+			Dial: func(_ string, _ string) (net.Conn, error) {
+				return net.Dial("tcp", ts.Listener.Addr().String())
+			},
+		},
+	}
+	_, err := c.Get("http://firsthost.fake/")
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = c.Get("http://firsthost.fake/nosetcookie")
+	if err != nil {
+		t.Fatal(err)
+	}
+	got := jar.log.String()
+	want := `Cookies("http://firsthost.fake/")
+SetCookie("http://firsthost.fake/", [name=val])
+Cookies("http://secondhost.fake/secondpath")
+SetCookie("http://secondhost.fake/secondpath", [namesecondpath=valsecondpath])
+Cookies("http://firsthost.fake/nosetcookie")
+`
+	if got != want {
+		t.Errorf("Got Jar calls:\n%s\nWant:\n%s", got, want)
+	}
+}
+
+// RecordingJar keeps a log of calls made to it, without
+// tracking any cookies.
+type RecordingJar struct {
+	mu  sync.Mutex
+	log bytes.Buffer
+}
+
+func (j *RecordingJar) SetCookies(u *url.URL, cookies []*Cookie) {
+	j.logf("SetCookie(%q, %v)\n", u, cookies)
+}
+
+func (j *RecordingJar) Cookies(u *url.URL) []*Cookie {
+	j.logf("Cookies(%q)\n", u)
+	return nil
+}
+
+func (j *RecordingJar) logf(format string, args ...interface{}) {
+	j.mu.Lock()
+	defer j.mu.Unlock()
+	fmt.Fprintf(&j.log, format, args...)
+}
+
+func TestStreamingGet(t *testing.T) {
+	defer afterTest(t)
+	say := make(chan string)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.(Flusher).Flush()
+		for str := range say {
+			w.Write([]byte(str))
+			w.(Flusher).Flush()
+		}
+	}))
+	defer ts.Close()
+
+	c := &Client{}
+	res, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	var buf [10]byte
+	for _, str := range []string{"i", "am", "also", "known", "as", "comet"} {
+		say <- str
+		n, err := io.ReadFull(res.Body, buf[0:len(str)])
+		if err != nil {
+			t.Fatalf("ReadFull on %q: %v", str, err)
+		}
+		if n != len(str) {
+			t.Fatalf("Receiving %q, only read %d bytes", str, n)
+		}
+		got := string(buf[0:n])
+		if got != str {
+			t.Fatalf("Expected %q, got %q", str, got)
+		}
+	}
+	close(say)
+	_, err = io.ReadFull(res.Body, buf[0:1])
+	if err != io.EOF {
+		t.Fatalf("at end expected EOF, got %v", err)
+	}
+}
+
+type writeCountingConn struct {
+	net.Conn
+	count *int
+}
+
+func (c *writeCountingConn) Write(p []byte) (int, error) {
+	*c.count++
+	return c.Conn.Write(p)
+}
+
+// TestClientWrites verifies that client requests are buffered and we
+// don't send a TCP packet per line of the http request + body.
+func TestClientWrites(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	}))
+	defer ts.Close()
+
+	writes := 0
+	dialer := func(netz string, addr string) (net.Conn, error) {
+		c, err := net.Dial(netz, addr)
+		if err == nil {
+			c = &writeCountingConn{c, &writes}
+		}
+		return c, err
+	}
+	c := &Client{Transport: &Transport{Dial: dialer}}
+
+	_, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if writes != 1 {
+		t.Errorf("Get request did %d Write calls, want 1", writes)
+	}
+
+	writes = 0
+	_, err = c.PostForm(ts.URL, url.Values{"foo": {"bar"}})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if writes != 1 {
+		t.Errorf("Post request did %d Write calls, want 1", writes)
+	}
+}
+
+func TestClientInsecureTransport(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Write([]byte("Hello"))
+	}))
+	errc := make(chanWriter, 10) // but only expecting 1
+	ts.Config.ErrorLog = log.New(errc, "", 0)
+	defer ts.Close()
+
+	// TODO(bradfitz): add tests for skipping hostname checks too?
+	// would require a new cert for testing, and probably
+	// redundant with these tests.
+	for _, insecure := range []bool{true, false} {
+		tr := &Transport{
+			TLSClientConfig: &tls.Config{
+				InsecureSkipVerify: insecure,
+			},
+		}
+		defer tr.CloseIdleConnections()
+		c := &Client{Transport: tr}
+		res, err := c.Get(ts.URL)
+		if (err == nil) != insecure {
+			t.Errorf("insecure=%v: got unexpected err=%v", insecure, err)
+		}
+		if res != nil {
+			res.Body.Close()
+		}
+	}
+
+	select {
+	case v := <-errc:
+		if !strings.Contains(v, "TLS handshake error") {
+			t.Errorf("expected an error log message containing 'TLS handshake error'; got %q", v)
+		}
+	case <-time.After(5 * time.Second):
+		t.Errorf("timeout waiting for logged error")
+	}
+
+}
+
+func TestClientErrorWithRequestURI(t *testing.T) {
+	defer afterTest(t)
+	req, _ := NewRequest("GET", "http://localhost:1234/", nil)
+	req.RequestURI = "/this/field/is/illegal/and/should/error/"
+	_, err := DefaultClient.Do(req)
+	if err == nil {
+		t.Fatalf("expected an error")
+	}
+	if !strings.Contains(err.Error(), "RequestURI") {
+		t.Errorf("wanted error mentioning RequestURI; got error: %v", err)
+	}
+}
+
+func newTLSTransport(t *testing.T, ts *httptest.Server) *Transport {
+	certs := x509.NewCertPool()
+	for _, c := range ts.TLS.Certificates {
+		roots, err := x509.ParseCertificates(c.Certificate[len(c.Certificate)-1])
+		if err != nil {
+			t.Fatalf("error parsing server's root cert: %v", err)
+		}
+		for _, root := range roots {
+			certs.AddCert(root)
+		}
+	}
+	return &Transport{
+		TLSClientConfig: &tls.Config{RootCAs: certs},
+	}
+}
+
+func TestClientWithCorrectTLSServerName(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.TLS.ServerName != "127.0.0.1" {
+			t.Errorf("expected client to set ServerName 127.0.0.1, got: %q", r.TLS.ServerName)
+		}
+	}))
+	defer ts.Close()
+
+	c := &Client{Transport: newTLSTransport(t, ts)}
+	if _, err := c.Get(ts.URL); err != nil {
+		t.Fatalf("expected successful TLS connection, got error: %v", err)
+	}
+}
+
+func TestClientWithIncorrectTLSServerName(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+	defer ts.Close()
+	errc := make(chanWriter, 10) // but only expecting 1
+	ts.Config.ErrorLog = log.New(errc, "", 0)
+
+	trans := newTLSTransport(t, ts)
+	trans.TLSClientConfig.ServerName = "badserver"
+	c := &Client{Transport: trans}
+	_, err := c.Get(ts.URL)
+	if err == nil {
+		t.Fatalf("expected an error")
+	}
+	if !strings.Contains(err.Error(), "127.0.0.1") || !strings.Contains(err.Error(), "badserver") {
+		t.Errorf("wanted error mentioning 127.0.0.1 and badserver; got error: %v", err)
+	}
+	select {
+	case v := <-errc:
+		if !strings.Contains(v, "TLS handshake error") {
+			t.Errorf("expected an error log message containing 'TLS handshake error'; got %q", v)
+		}
+	case <-time.After(5 * time.Second):
+		t.Errorf("timeout waiting for logged error")
+	}
+}
+
+// Test for golang.org/issue/5829; the Transport should respect TLSClientConfig.ServerName
+// when not empty.
+//
+// tls.Config.ServerName (non-empty, set to "example.com") takes
+// precedence over "some-other-host.tld" which previously incorrectly
+// took precedence. We don't actually connect to (or even resolve)
+// "some-other-host.tld", though, because of the Transport.Dial hook.
+//
+// The httptest.Server has a cert with "example.com" as its name.
+func TestTransportUsesTLSConfigServerName(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Write([]byte("Hello"))
+	}))
+	defer ts.Close()
+
+	tr := newTLSTransport(t, ts)
+	tr.TLSClientConfig.ServerName = "example.com" // one of httptest's Server cert names
+	tr.Dial = func(netw, addr string) (net.Conn, error) {
+		return net.Dial(netw, ts.Listener.Addr().String())
+	}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+	res, err := c.Get("https://some-other-host.tld/")
+	if err != nil {
+		t.Fatal(err)
+	}
+	res.Body.Close()
+}
+
+func TestResponseSetsTLSConnectionState(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Write([]byte("Hello"))
+	}))
+	defer ts.Close()
+
+	tr := newTLSTransport(t, ts)
+	tr.TLSClientConfig.CipherSuites = []uint16{tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA}
+	tr.Dial = func(netw, addr string) (net.Conn, error) {
+		return net.Dial(netw, ts.Listener.Addr().String())
+	}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+	res, err := c.Get("https://example.com/")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer res.Body.Close()
+	if res.TLS == nil {
+		t.Fatal("Response didn't set TLS Connection State.")
+	}
+	if got, want := res.TLS.CipherSuite, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA; got != want {
+		t.Errorf("TLS Cipher Suite = %d; want %d", got, want)
+	}
+}
+
+// Verify Response.ContentLength is populated. http://golang.org/issue/4126
+func TestClientHeadContentLength(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if v := r.FormValue("cl"); v != "" {
+			w.Header().Set("Content-Length", v)
+		}
+	}))
+	defer ts.Close()
+	tests := []struct {
+		suffix string
+		want   int64
+	}{
+		{"/?cl=1234", 1234},
+		{"/?cl=0", 0},
+		{"", -1},
+	}
+	for _, tt := range tests {
+		req, _ := NewRequest("HEAD", ts.URL+tt.suffix, nil)
+		res, err := DefaultClient.Do(req)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if res.ContentLength != tt.want {
+			t.Errorf("Content-Length = %d; want %d", res.ContentLength, tt.want)
+		}
+		bs, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if len(bs) != 0 {
+			t.Errorf("Unexpected content: %q", bs)
+		}
+	}
+}
+
+func TestEmptyPasswordAuth(t *testing.T) {
+	defer afterTest(t)
+	gopher := "gopher"
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		auth := r.Header.Get("Authorization")
+		if strings.HasPrefix(auth, "Basic ") {
+			encoded := auth[6:]
+			decoded, err := base64.StdEncoding.DecodeString(encoded)
+			if err != nil {
+				t.Fatal(err)
+			}
+			expected := gopher + ":"
+			s := string(decoded)
+			if expected != s {
+				t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected)
+			}
+		} else {
+			t.Errorf("Invalid auth %q", auth)
+		}
+	}))
+	defer ts.Close()
+	c := &Client{}
+	req, err := NewRequest("GET", ts.URL, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	req.URL.User = url.User(gopher)
+	resp, err := c.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer resp.Body.Close()
+}
+
+func TestBasicAuth(t *testing.T) {
+	defer afterTest(t)
+	tr := &recordingTransport{}
+	client := &Client{Transport: tr}
+
+	url := "http://My%20User:My%20Pass@dummy.faketld/"
+	expected := "My User:My Pass"
+	client.Get(url)
+
+	if tr.req.Method != "GET" {
+		t.Errorf("got method %q, want %q", tr.req.Method, "GET")
+	}
+	if tr.req.URL.String() != url {
+		t.Errorf("got URL %q, want %q", tr.req.URL.String(), url)
+	}
+	if tr.req.Header == nil {
+		t.Fatalf("expected non-nil request Header")
+	}
+	auth := tr.req.Header.Get("Authorization")
+	if strings.HasPrefix(auth, "Basic ") {
+		encoded := auth[6:]
+		decoded, err := base64.StdEncoding.DecodeString(encoded)
+		if err != nil {
+			t.Fatal(err)
+		}
+		s := string(decoded)
+		if expected != s {
+			t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected)
+		}
+	} else {
+		t.Errorf("Invalid auth %q", auth)
+	}
+}
+
+func TestClientTimeout(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	defer afterTest(t)
+	sawRoot := make(chan bool, 1)
+	sawSlow := make(chan bool, 1)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.URL.Path == "/" {
+			sawRoot <- true
+			Redirect(w, r, "/slow", StatusFound)
+			return
+		}
+		if r.URL.Path == "/slow" {
+			w.Write([]byte("Hello"))
+			w.(Flusher).Flush()
+			sawSlow <- true
+			time.Sleep(2 * time.Second)
+			return
+		}
+	}))
+	defer ts.Close()
+	const timeout = 500 * time.Millisecond
+	c := &Client{
+		Timeout: timeout,
+	}
+
+	res, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	select {
+	case <-sawRoot:
+		// good.
+	default:
+		t.Fatal("handler never got / request")
+	}
+
+	select {
+	case <-sawSlow:
+		// good.
+	default:
+		t.Fatal("handler never got /slow request")
+	}
+
+	errc := make(chan error, 1)
+	go func() {
+		_, err := ioutil.ReadAll(res.Body)
+		errc <- err
+		res.Body.Close()
+	}()
+
+	const failTime = timeout * 2
+	select {
+	case err := <-errc:
+		if err == nil {
+			t.Error("expected error from ReadAll")
+		}
+		// Expected error.
+	case <-time.After(failTime):
+		t.Errorf("timeout after %v waiting for timeout of %v", failTime, timeout)
+	}
+}
+
+func TestClientRedirectEatsBody(t *testing.T) {
+	defer afterTest(t)
+	saw := make(chan string, 2)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		saw <- r.RemoteAddr
+		if r.URL.Path == "/" {
+			Redirect(w, r, "/foo", StatusFound) // which includes a body
+		}
+	}))
+	defer ts.Close()
+
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	res.Body.Close()
+
+	var first string
+	select {
+	case first = <-saw:
+	default:
+		t.Fatal("server didn't see a request")
+	}
+
+	var second string
+	select {
+	case second = <-saw:
+	default:
+		t.Fatal("server didn't see a second request")
+	}
+
+	if first != second {
+		t.Fatal("server saw different client ports before & after the redirect")
+	}
+}
+
+// eofReaderFunc is an io.Reader that runs itself, and then returns io.EOF.
+type eofReaderFunc func()
+
+func (f eofReaderFunc) Read(p []byte) (n int, err error) {
+	f()
+	return 0, io.EOF
+}
+
+func TestClientTrailers(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Connection", "close")
+		w.Header().Set("Trailer", "Server-Trailer-A, Server-Trailer-B")
+		w.Header().Add("Trailer", "Server-Trailer-C")
+
+		var decl []string
+		for k := range r.Trailer {
+			decl = append(decl, k)
+		}
+		sort.Strings(decl)
+
+		slurp, err := ioutil.ReadAll(r.Body)
+		if err != nil {
+			t.Errorf("Server reading request body: %v", err)
+		}
+		if string(slurp) != "foo" {
+			t.Errorf("Server read request body %q; want foo", slurp)
+		}
+		if r.Trailer == nil {
+			io.WriteString(w, "nil Trailer")
+		} else {
+			fmt.Fprintf(w, "decl: %v, vals: %s, %s",
+				decl,
+				r.Trailer.Get("Client-Trailer-A"),
+				r.Trailer.Get("Client-Trailer-B"))
+		}
+
+		// TODO: golang.org/issue/7759: there's no way yet for
+		// the server to set trailers without hijacking, so do
+		// that for now, just to test the client.  Later, in
+		// Go 1.4, it should be implicit that any mutations
+		// to w.Header() after the initial write are the
+		// trailers to be sent, if and only if they were
+		// previously declared with w.Header().Set("Trailer",
+		// ..keys..)
+		w.(Flusher).Flush()
+		conn, buf, _ := w.(Hijacker).Hijack()
+		t := Header{}
+		t.Set("Server-Trailer-A", "valuea")
+		t.Set("Server-Trailer-C", "valuec") // skipping B
+		buf.WriteString("0\r\n")            // eof
+		t.Write(buf)
+		buf.WriteString("\r\n") // end of trailers
+		buf.Flush()
+		conn.Close()
+	}))
+	defer ts.Close()
+
+	var req *Request
+	req, _ = NewRequest("POST", ts.URL, io.MultiReader(
+		eofReaderFunc(func() {
+			req.Trailer["Client-Trailer-A"] = []string{"valuea"}
+		}),
+		strings.NewReader("foo"),
+		eofReaderFunc(func() {
+			req.Trailer["Client-Trailer-B"] = []string{"valueb"}
+		}),
+	))
+	req.Trailer = Header{
+		"Client-Trailer-A": nil, //  to be set later
+		"Client-Trailer-B": nil, //  to be set later
+	}
+	req.ContentLength = -1
+	res, err := DefaultClient.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := wantBody(res, err, "decl: [Client-Trailer-A Client-Trailer-B], vals: valuea, valueb"); err != nil {
+		t.Error(err)
+	}
+	want := Header{
+		"Server-Trailer-A": []string{"valuea"},
+		"Server-Trailer-B": nil,
+		"Server-Trailer-C": []string{"valuec"},
+	}
+	if !reflect.DeepEqual(res.Trailer, want) {
+		t.Errorf("Response trailers = %#v; want %#v", res.Trailer, want)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cookie.go b/third_party/gofrontend/libgo/go/net/http/cookie.go
new file mode 100644
index 0000000..dc60ba8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cookie.go
@@ -0,0 +1,363 @@
+// 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 http
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"net"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// This implementation is done according to RFC 6265:
+//
+//    http://tools.ietf.org/html/rfc6265
+
+// A Cookie represents an HTTP cookie as sent in the Set-Cookie header of an
+// HTTP response or the Cookie header of an HTTP request.
+type Cookie struct {
+	Name       string
+	Value      string
+	Path       string
+	Domain     string
+	Expires    time.Time
+	RawExpires string
+
+	// MaxAge=0 means no 'Max-Age' attribute specified.
+	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
+	// MaxAge>0 means Max-Age attribute present and given in seconds
+	MaxAge   int
+	Secure   bool
+	HttpOnly bool
+	Raw      string
+	Unparsed []string // Raw text of unparsed attribute-value pairs
+}
+
+// readSetCookies parses all "Set-Cookie" values from
+// the header h and returns the successfully parsed Cookies.
+func readSetCookies(h Header) []*Cookie {
+	cookies := []*Cookie{}
+	for _, line := range h["Set-Cookie"] {
+		parts := strings.Split(strings.TrimSpace(line), ";")
+		if len(parts) == 1 && parts[0] == "" {
+			continue
+		}
+		parts[0] = strings.TrimSpace(parts[0])
+		j := strings.Index(parts[0], "=")
+		if j < 0 {
+			continue
+		}
+		name, value := parts[0][:j], parts[0][j+1:]
+		if !isCookieNameValid(name) {
+			continue
+		}
+		value, success := parseCookieValue(value)
+		if !success {
+			continue
+		}
+		c := &Cookie{
+			Name:  name,
+			Value: value,
+			Raw:   line,
+		}
+		for i := 1; i < len(parts); i++ {
+			parts[i] = strings.TrimSpace(parts[i])
+			if len(parts[i]) == 0 {
+				continue
+			}
+
+			attr, val := parts[i], ""
+			if j := strings.Index(attr, "="); j >= 0 {
+				attr, val = attr[:j], attr[j+1:]
+			}
+			lowerAttr := strings.ToLower(attr)
+			val, success = parseCookieValue(val)
+			if !success {
+				c.Unparsed = append(c.Unparsed, parts[i])
+				continue
+			}
+			switch lowerAttr {
+			case "secure":
+				c.Secure = true
+				continue
+			case "httponly":
+				c.HttpOnly = true
+				continue
+			case "domain":
+				c.Domain = val
+				continue
+			case "max-age":
+				secs, err := strconv.Atoi(val)
+				if err != nil || secs != 0 && val[0] == '0' {
+					break
+				}
+				if secs <= 0 {
+					c.MaxAge = -1
+				} else {
+					c.MaxAge = secs
+				}
+				continue
+			case "expires":
+				c.RawExpires = val
+				exptime, err := time.Parse(time.RFC1123, val)
+				if err != nil {
+					exptime, err = time.Parse("Mon, 02-Jan-2006 15:04:05 MST", val)
+					if err != nil {
+						c.Expires = time.Time{}
+						break
+					}
+				}
+				c.Expires = exptime.UTC()
+				continue
+			case "path":
+				c.Path = val
+				continue
+			}
+			c.Unparsed = append(c.Unparsed, parts[i])
+		}
+		cookies = append(cookies, c)
+	}
+	return cookies
+}
+
+// SetCookie adds a Set-Cookie header to the provided ResponseWriter's headers.
+func SetCookie(w ResponseWriter, cookie *Cookie) {
+	w.Header().Add("Set-Cookie", cookie.String())
+}
+
+// String returns the serialization of the cookie for use in a Cookie
+// header (if only Name and Value are set) or a Set-Cookie response
+// header (if other fields are set).
+func (c *Cookie) String() string {
+	var b bytes.Buffer
+	fmt.Fprintf(&b, "%s=%s", sanitizeCookieName(c.Name), sanitizeCookieValue(c.Value))
+	if len(c.Path) > 0 {
+		fmt.Fprintf(&b, "; Path=%s", sanitizeCookiePath(c.Path))
+	}
+	if len(c.Domain) > 0 {
+		if validCookieDomain(c.Domain) {
+			// A c.Domain containing illegal characters is not
+			// sanitized but simply dropped which turns the cookie
+			// into a host-only cookie. A leading dot is okay
+			// but won't be sent.
+			d := c.Domain
+			if d[0] == '.' {
+				d = d[1:]
+			}
+			fmt.Fprintf(&b, "; Domain=%s", d)
+		} else {
+			log.Printf("net/http: invalid Cookie.Domain %q; dropping domain attribute",
+				c.Domain)
+		}
+	}
+	if c.Expires.Unix() > 0 {
+		fmt.Fprintf(&b, "; Expires=%s", c.Expires.UTC().Format(time.RFC1123))
+	}
+	if c.MaxAge > 0 {
+		fmt.Fprintf(&b, "; Max-Age=%d", c.MaxAge)
+	} else if c.MaxAge < 0 {
+		fmt.Fprintf(&b, "; Max-Age=0")
+	}
+	if c.HttpOnly {
+		fmt.Fprintf(&b, "; HttpOnly")
+	}
+	if c.Secure {
+		fmt.Fprintf(&b, "; Secure")
+	}
+	return b.String()
+}
+
+// readCookies parses all "Cookie" values from the header h and
+// returns the successfully parsed Cookies.
+//
+// if filter isn't empty, only cookies of that name are returned
+func readCookies(h Header, filter string) []*Cookie {
+	cookies := []*Cookie{}
+	lines, ok := h["Cookie"]
+	if !ok {
+		return cookies
+	}
+
+	for _, line := range lines {
+		parts := strings.Split(strings.TrimSpace(line), ";")
+		if len(parts) == 1 && parts[0] == "" {
+			continue
+		}
+		// Per-line attributes
+		parsedPairs := 0
+		for i := 0; i < len(parts); i++ {
+			parts[i] = strings.TrimSpace(parts[i])
+			if len(parts[i]) == 0 {
+				continue
+			}
+			name, val := parts[i], ""
+			if j := strings.Index(name, "="); j >= 0 {
+				name, val = name[:j], name[j+1:]
+			}
+			if !isCookieNameValid(name) {
+				continue
+			}
+			if filter != "" && filter != name {
+				continue
+			}
+			val, success := parseCookieValue(val)
+			if !success {
+				continue
+			}
+			cookies = append(cookies, &Cookie{Name: name, Value: val})
+			parsedPairs++
+		}
+	}
+	return cookies
+}
+
+// validCookieDomain returns wheter v is a valid cookie domain-value.
+func validCookieDomain(v string) bool {
+	if isCookieDomainName(v) {
+		return true
+	}
+	if net.ParseIP(v) != nil && !strings.Contains(v, ":") {
+		return true
+	}
+	return false
+}
+
+// isCookieDomainName returns whether s is a valid domain name or a valid
+// domain name with a leading dot '.'.  It is almost a direct copy of
+// package net's isDomainName.
+func isCookieDomainName(s string) bool {
+	if len(s) == 0 {
+		return false
+	}
+	if len(s) > 255 {
+		return false
+	}
+
+	if s[0] == '.' {
+		// A cookie a domain attribute may start with a leading dot.
+		s = s[1:]
+	}
+	last := byte('.')
+	ok := false // Ok once we've seen a letter.
+	partlen := 0
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		switch {
+		default:
+			return false
+		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
+			// No '_' allowed here (in contrast to package net).
+			ok = true
+			partlen++
+		case '0' <= c && c <= '9':
+			// fine
+			partlen++
+		case c == '-':
+			// Byte before dash cannot be dot.
+			if last == '.' {
+				return false
+			}
+			partlen++
+		case c == '.':
+			// Byte before dot cannot be dot, dash.
+			if last == '.' || last == '-' {
+				return false
+			}
+			if partlen > 63 || partlen == 0 {
+				return false
+			}
+			partlen = 0
+		}
+		last = c
+	}
+	if last == '-' || partlen > 63 {
+		return false
+	}
+
+	return ok
+}
+
+var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")
+
+func sanitizeCookieName(n string) string {
+	return cookieNameSanitizer.Replace(n)
+}
+
+// http://tools.ietf.org/html/rfc6265#section-4.1.1
+// cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
+// cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
+//           ; US-ASCII characters excluding CTLs,
+//           ; whitespace DQUOTE, comma, semicolon,
+//           ; and backslash
+// We loosen this as spaces and commas are common in cookie values
+// but we produce a quoted cookie-value in when value starts or ends
+// with a comma or space.
+// See http://golang.org/issue/7243 for the discussion.
+func sanitizeCookieValue(v string) string {
+	v = sanitizeOrWarn("Cookie.Value", validCookieValueByte, v)
+	if len(v) == 0 {
+		return v
+	}
+	if v[0] == ' ' || v[0] == ',' || v[len(v)-1] == ' ' || v[len(v)-1] == ',' {
+		return `"` + v + `"`
+	}
+	return v
+}
+
+func validCookieValueByte(b byte) bool {
+	return 0x20 <= b && b < 0x7f && b != '"' && b != ';' && b != '\\'
+}
+
+// path-av           = "Path=" path-value
+// path-value        = <any CHAR except CTLs or ";">
+func sanitizeCookiePath(v string) string {
+	return sanitizeOrWarn("Cookie.Path", validCookiePathByte, v)
+}
+
+func validCookiePathByte(b byte) bool {
+	return 0x20 <= b && b < 0x7f && b != ';'
+}
+
+func sanitizeOrWarn(fieldName string, valid func(byte) bool, v string) string {
+	ok := true
+	for i := 0; i < len(v); i++ {
+		if valid(v[i]) {
+			continue
+		}
+		log.Printf("net/http: invalid byte %q in %s; dropping invalid bytes", v[i], fieldName)
+		ok = false
+		break
+	}
+	if ok {
+		return v
+	}
+	buf := make([]byte, 0, len(v))
+	for i := 0; i < len(v); i++ {
+		if b := v[i]; valid(b) {
+			buf = append(buf, b)
+		}
+	}
+	return string(buf)
+}
+
+func parseCookieValue(raw string) (string, bool) {
+	// Strip the quotes, if present.
+	if len(raw) > 1 && raw[0] == '"' && raw[len(raw)-1] == '"' {
+		raw = raw[1 : len(raw)-1]
+	}
+	for i := 0; i < len(raw); i++ {
+		if !validCookieValueByte(raw[i]) {
+			return "", false
+		}
+	}
+	return raw, true
+}
+
+func isCookieNameValid(raw string) bool {
+	return strings.IndexFunc(raw, isNotToken) < 0
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cookie_test.go b/third_party/gofrontend/libgo/go/net/http/cookie_test.go
new file mode 100644
index 0000000..f78f372
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cookie_test.go
@@ -0,0 +1,380 @@
+// Copyright 2010 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 http
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"log"
+	"os"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+)
+
+var writeSetCookiesTests = []struct {
+	Cookie *Cookie
+	Raw    string
+}{
+	{
+		&Cookie{Name: "cookie-1", Value: "v$1"},
+		"cookie-1=v$1",
+	},
+	{
+		&Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600},
+		"cookie-2=two; Max-Age=3600",
+	},
+	{
+		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
+		"cookie-3=three; Domain=example.com",
+	},
+	{
+		&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},
+		"cookie-4=four; Path=/restricted/",
+	},
+	{
+		&Cookie{Name: "cookie-5", Value: "five", Domain: "wrong;bad.abc"},
+		"cookie-5=five",
+	},
+	{
+		&Cookie{Name: "cookie-6", Value: "six", Domain: "bad-.abc"},
+		"cookie-6=six",
+	},
+	{
+		&Cookie{Name: "cookie-7", Value: "seven", Domain: "127.0.0.1"},
+		"cookie-7=seven; Domain=127.0.0.1",
+	},
+	{
+		&Cookie{Name: "cookie-8", Value: "eight", Domain: "::1"},
+		"cookie-8=eight",
+	},
+	// The "special" cookies have values containing commas or spaces which
+	// are disallowed by RFC 6265 but are common in the wild.
+	{
+		&Cookie{Name: "special-1", Value: "a z"},
+		`special-1=a z`,
+	},
+	{
+		&Cookie{Name: "special-2", Value: " z"},
+		`special-2=" z"`,
+	},
+	{
+		&Cookie{Name: "special-3", Value: "a "},
+		`special-3="a "`,
+	},
+	{
+		&Cookie{Name: "special-4", Value: " "},
+		`special-4=" "`,
+	},
+	{
+		&Cookie{Name: "special-5", Value: "a,z"},
+		`special-5=a,z`,
+	},
+	{
+		&Cookie{Name: "special-6", Value: ",z"},
+		`special-6=",z"`,
+	},
+	{
+		&Cookie{Name: "special-7", Value: "a,"},
+		`special-7="a,"`,
+	},
+	{
+		&Cookie{Name: "special-8", Value: ","},
+		`special-8=","`,
+	},
+	{
+		&Cookie{Name: "empty-value", Value: ""},
+		`empty-value=`,
+	},
+}
+
+func TestWriteSetCookies(t *testing.T) {
+	defer log.SetOutput(os.Stderr)
+	var logbuf bytes.Buffer
+	log.SetOutput(&logbuf)
+
+	for i, tt := range writeSetCookiesTests {
+		if g, e := tt.Cookie.String(), tt.Raw; g != e {
+			t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, e, g)
+			continue
+		}
+	}
+
+	if got, sub := logbuf.String(), "dropping domain attribute"; !strings.Contains(got, sub) {
+		t.Errorf("Expected substring %q in log output. Got:\n%s", sub, got)
+	}
+}
+
+type headerOnlyResponseWriter Header
+
+func (ho headerOnlyResponseWriter) Header() Header {
+	return Header(ho)
+}
+
+func (ho headerOnlyResponseWriter) Write([]byte) (int, error) {
+	panic("NOIMPL")
+}
+
+func (ho headerOnlyResponseWriter) WriteHeader(int) {
+	panic("NOIMPL")
+}
+
+func TestSetCookie(t *testing.T) {
+	m := make(Header)
+	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-1", Value: "one", Path: "/restricted/"})
+	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600})
+	if l := len(m["Set-Cookie"]); l != 2 {
+		t.Fatalf("expected %d cookies, got %d", 2, l)
+	}
+	if g, e := m["Set-Cookie"][0], "cookie-1=one; Path=/restricted/"; g != e {
+		t.Errorf("cookie #1: want %q, got %q", e, g)
+	}
+	if g, e := m["Set-Cookie"][1], "cookie-2=two; Max-Age=3600"; g != e {
+		t.Errorf("cookie #2: want %q, got %q", e, g)
+	}
+}
+
+var addCookieTests = []struct {
+	Cookies []*Cookie
+	Raw     string
+}{
+	{
+		[]*Cookie{},
+		"",
+	},
+	{
+		[]*Cookie{{Name: "cookie-1", Value: "v$1"}},
+		"cookie-1=v$1",
+	},
+	{
+		[]*Cookie{
+			{Name: "cookie-1", Value: "v$1"},
+			{Name: "cookie-2", Value: "v$2"},
+			{Name: "cookie-3", Value: "v$3"},
+		},
+		"cookie-1=v$1; cookie-2=v$2; cookie-3=v$3",
+	},
+}
+
+func TestAddCookie(t *testing.T) {
+	for i, tt := range addCookieTests {
+		req, _ := NewRequest("GET", "http://example.com/", nil)
+		for _, c := range tt.Cookies {
+			req.AddCookie(c)
+		}
+		if g := req.Header.Get("Cookie"); g != tt.Raw {
+			t.Errorf("Test %d:\nwant: %s\n got: %s\n", i, tt.Raw, g)
+			continue
+		}
+	}
+}
+
+var readSetCookiesTests = []struct {
+	Header  Header
+	Cookies []*Cookie
+}{
+	{
+		Header{"Set-Cookie": {"Cookie-1=v$1"}},
+		[]*Cookie{{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
+	},
+	{
+		Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}},
+		[]*Cookie{{
+			Name:       "NID",
+			Value:      "99=YsDT5i3E-CXax-",
+			Path:       "/",
+			Domain:     ".google.ch",
+			HttpOnly:   true,
+			Expires:    time.Date(2011, 11, 23, 1, 5, 3, 0, time.UTC),
+			RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
+			Raw:        "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
+		}},
+	},
+	{
+		Header{"Set-Cookie": {".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}},
+		[]*Cookie{{
+			Name:       ".ASPXAUTH",
+			Value:      "7E3AA",
+			Path:       "/",
+			Expires:    time.Date(2012, 3, 7, 14, 25, 6, 0, time.UTC),
+			RawExpires: "Wed, 07-Mar-2012 14:25:06 GMT",
+			HttpOnly:   true,
+			Raw:        ".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly",
+		}},
+	},
+	{
+		Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly"}},
+		[]*Cookie{{
+			Name:     "ASP.NET_SessionId",
+			Value:    "foo",
+			Path:     "/",
+			HttpOnly: true,
+			Raw:      "ASP.NET_SessionId=foo; path=/; HttpOnly",
+		}},
+	},
+	// Make sure we can properly read back the Set-Cookie headers we create
+	// for values containing spaces or commas:
+	{
+		Header{"Set-Cookie": {`special-1=a z`}},
+		[]*Cookie{{Name: "special-1", Value: "a z", Raw: `special-1=a z`}},
+	},
+	{
+		Header{"Set-Cookie": {`special-2=" z"`}},
+		[]*Cookie{{Name: "special-2", Value: " z", Raw: `special-2=" z"`}},
+	},
+	{
+		Header{"Set-Cookie": {`special-3="a "`}},
+		[]*Cookie{{Name: "special-3", Value: "a ", Raw: `special-3="a "`}},
+	},
+	{
+		Header{"Set-Cookie": {`special-4=" "`}},
+		[]*Cookie{{Name: "special-4", Value: " ", Raw: `special-4=" "`}},
+	},
+	{
+		Header{"Set-Cookie": {`special-5=a,z`}},
+		[]*Cookie{{Name: "special-5", Value: "a,z", Raw: `special-5=a,z`}},
+	},
+	{
+		Header{"Set-Cookie": {`special-6=",z"`}},
+		[]*Cookie{{Name: "special-6", Value: ",z", Raw: `special-6=",z"`}},
+	},
+	{
+		Header{"Set-Cookie": {`special-7=a,`}},
+		[]*Cookie{{Name: "special-7", Value: "a,", Raw: `special-7=a,`}},
+	},
+	{
+		Header{"Set-Cookie": {`special-8=","`}},
+		[]*Cookie{{Name: "special-8", Value: ",", Raw: `special-8=","`}},
+	},
+
+	// TODO(bradfitz): users have reported seeing this in the
+	// wild, but do browsers handle it? RFC 6265 just says "don't
+	// do that" (section 3) and then never mentions header folding
+	// again.
+	// Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly, .ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}},
+}
+
+func toJSON(v interface{}) string {
+	b, err := json.Marshal(v)
+	if err != nil {
+		return fmt.Sprintf("%#v", v)
+	}
+	return string(b)
+}
+
+func TestReadSetCookies(t *testing.T) {
+	for i, tt := range readSetCookiesTests {
+		for n := 0; n < 2; n++ { // to verify readSetCookies doesn't mutate its input
+			c := readSetCookies(tt.Header)
+			if !reflect.DeepEqual(c, tt.Cookies) {
+				t.Errorf("#%d readSetCookies: have\n%s\nwant\n%s\n", i, toJSON(c), toJSON(tt.Cookies))
+				continue
+			}
+		}
+	}
+}
+
+var readCookiesTests = []struct {
+	Header  Header
+	Filter  string
+	Cookies []*Cookie
+}{
+	{
+		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
+		"",
+		[]*Cookie{
+			{Name: "Cookie-1", Value: "v$1"},
+			{Name: "c2", Value: "v2"},
+		},
+	},
+	{
+		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
+		"c2",
+		[]*Cookie{
+			{Name: "c2", Value: "v2"},
+		},
+	},
+	{
+		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
+		"",
+		[]*Cookie{
+			{Name: "Cookie-1", Value: "v$1"},
+			{Name: "c2", Value: "v2"},
+		},
+	},
+	{
+		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
+		"c2",
+		[]*Cookie{
+			{Name: "c2", Value: "v2"},
+		},
+	},
+}
+
+func TestReadCookies(t *testing.T) {
+	for i, tt := range readCookiesTests {
+		for n := 0; n < 2; n++ { // to verify readCookies doesn't mutate its input
+			c := readCookies(tt.Header, tt.Filter)
+			if !reflect.DeepEqual(c, tt.Cookies) {
+				t.Errorf("#%d readCookies:\nhave: %s\nwant: %s\n", i, toJSON(c), toJSON(tt.Cookies))
+				continue
+			}
+		}
+	}
+}
+
+func TestCookieSanitizeValue(t *testing.T) {
+	defer log.SetOutput(os.Stderr)
+	var logbuf bytes.Buffer
+	log.SetOutput(&logbuf)
+
+	tests := []struct {
+		in, want string
+	}{
+		{"foo", "foo"},
+		{"foo;bar", "foobar"},
+		{"foo\\bar", "foobar"},
+		{"foo\"bar", "foobar"},
+		{"\x00\x7e\x7f\x80", "\x7e"},
+		{`"withquotes"`, "withquotes"},
+		{"a z", "a z"},
+		{" z", `" z"`},
+		{"a ", `"a "`},
+	}
+	for _, tt := range tests {
+		if got := sanitizeCookieValue(tt.in); got != tt.want {
+			t.Errorf("sanitizeCookieValue(%q) = %q; want %q", tt.in, got, tt.want)
+		}
+	}
+
+	if got, sub := logbuf.String(), "dropping invalid bytes"; !strings.Contains(got, sub) {
+		t.Errorf("Expected substring %q in log output. Got:\n%s", sub, got)
+	}
+}
+
+func TestCookieSanitizePath(t *testing.T) {
+	defer log.SetOutput(os.Stderr)
+	var logbuf bytes.Buffer
+	log.SetOutput(&logbuf)
+
+	tests := []struct {
+		in, want string
+	}{
+		{"/path", "/path"},
+		{"/path with space/", "/path with space/"},
+		{"/just;no;semicolon\x00orstuff/", "/justnosemicolonorstuff/"},
+	}
+	for _, tt := range tests {
+		if got := sanitizeCookiePath(tt.in); got != tt.want {
+			t.Errorf("sanitizeCookiePath(%q) = %q; want %q", tt.in, got, tt.want)
+		}
+	}
+
+	if got, sub := logbuf.String(), "dropping invalid bytes"; !strings.Contains(got, sub) {
+		t.Errorf("Expected substring %q in log output. Got:\n%s", sub, got)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cookiejar/jar.go b/third_party/gofrontend/libgo/go/net/http/cookiejar/jar.go
new file mode 100644
index 0000000..389ab58
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cookiejar/jar.go
@@ -0,0 +1,497 @@
+// 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 cookiejar implements an in-memory RFC 6265-compliant http.CookieJar.
+package cookiejar
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"net/http"
+	"net/url"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+)
+
+// PublicSuffixList provides the public suffix of a domain. For example:
+//      - the public suffix of "example.com" is "com",
+//      - the public suffix of "foo1.foo2.foo3.co.uk" is "co.uk", and
+//      - the public suffix of "bar.pvt.k12.ma.us" is "pvt.k12.ma.us".
+//
+// Implementations of PublicSuffixList must be safe for concurrent use by
+// multiple goroutines.
+//
+// An implementation that always returns "" is valid and may be useful for
+// testing but it is not secure: it means that the HTTP server for foo.com can
+// set a cookie for bar.com.
+//
+// A public suffix list implementation is in the package
+// code.google.com/p/go.net/publicsuffix.
+type PublicSuffixList interface {
+	// PublicSuffix returns the public suffix of domain.
+	//
+	// TODO: specify which of the caller and callee is responsible for IP
+	// addresses, for leading and trailing dots, for case sensitivity, and
+	// for IDN/Punycode.
+	PublicSuffix(domain string) string
+
+	// String returns a description of the source of this public suffix
+	// list. The description will typically contain something like a time
+	// stamp or version number.
+	String() string
+}
+
+// Options are the options for creating a new Jar.
+type Options struct {
+	// PublicSuffixList is the public suffix list that determines whether
+	// an HTTP server can set a cookie for a domain.
+	//
+	// A nil value is valid and may be useful for testing but it is not
+	// secure: it means that the HTTP server for foo.co.uk can set a cookie
+	// for bar.co.uk.
+	PublicSuffixList PublicSuffixList
+}
+
+// Jar implements the http.CookieJar interface from the net/http package.
+type Jar struct {
+	psList PublicSuffixList
+
+	// mu locks the remaining fields.
+	mu sync.Mutex
+
+	// entries is a set of entries, keyed by their eTLD+1 and subkeyed by
+	// their name/domain/path.
+	entries map[string]map[string]entry
+
+	// nextSeqNum is the next sequence number assigned to a new cookie
+	// created SetCookies.
+	nextSeqNum uint64
+}
+
+// New returns a new cookie jar. A nil *Options is equivalent to a zero
+// Options.
+func New(o *Options) (*Jar, error) {
+	jar := &Jar{
+		entries: make(map[string]map[string]entry),
+	}
+	if o != nil {
+		jar.psList = o.PublicSuffixList
+	}
+	return jar, nil
+}
+
+// entry is the internal representation of a cookie.
+//
+// This struct type is not used outside of this package per se, but the exported
+// fields are those of RFC 6265.
+type entry struct {
+	Name       string
+	Value      string
+	Domain     string
+	Path       string
+	Secure     bool
+	HttpOnly   bool
+	Persistent bool
+	HostOnly   bool
+	Expires    time.Time
+	Creation   time.Time
+	LastAccess time.Time
+
+	// seqNum is a sequence number so that Cookies returns cookies in a
+	// deterministic order, even for cookies that have equal Path length and
+	// equal Creation time. This simplifies testing.
+	seqNum uint64
+}
+
+// Id returns the domain;path;name triple of e as an id.
+func (e *entry) id() string {
+	return fmt.Sprintf("%s;%s;%s", e.Domain, e.Path, e.Name)
+}
+
+// shouldSend determines whether e's cookie qualifies to be included in a
+// request to host/path. It is the caller's responsibility to check if the
+// cookie is expired.
+func (e *entry) shouldSend(https bool, host, path string) bool {
+	return e.domainMatch(host) && e.pathMatch(path) && (https || !e.Secure)
+}
+
+// domainMatch implements "domain-match" of RFC 6265 section 5.1.3.
+func (e *entry) domainMatch(host string) bool {
+	if e.Domain == host {
+		return true
+	}
+	return !e.HostOnly && hasDotSuffix(host, e.Domain)
+}
+
+// pathMatch implements "path-match" according to RFC 6265 section 5.1.4.
+func (e *entry) pathMatch(requestPath string) bool {
+	if requestPath == e.Path {
+		return true
+	}
+	if strings.HasPrefix(requestPath, e.Path) {
+		if e.Path[len(e.Path)-1] == '/' {
+			return true // The "/any/" matches "/any/path" case.
+		} else if requestPath[len(e.Path)] == '/' {
+			return true // The "/any" matches "/any/path" case.
+		}
+	}
+	return false
+}
+
+// hasDotSuffix reports whether s ends in "."+suffix.
+func hasDotSuffix(s, suffix string) bool {
+	return len(s) > len(suffix) && s[len(s)-len(suffix)-1] == '.' && s[len(s)-len(suffix):] == suffix
+}
+
+// byPathLength is a []entry sort.Interface that sorts according to RFC 6265
+// section 5.4 point 2: by longest path and then by earliest creation time.
+type byPathLength []entry
+
+func (s byPathLength) Len() int { return len(s) }
+
+func (s byPathLength) Less(i, j int) bool {
+	if len(s[i].Path) != len(s[j].Path) {
+		return len(s[i].Path) > len(s[j].Path)
+	}
+	if !s[i].Creation.Equal(s[j].Creation) {
+		return s[i].Creation.Before(s[j].Creation)
+	}
+	return s[i].seqNum < s[j].seqNum
+}
+
+func (s byPathLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// Cookies implements the Cookies method of the http.CookieJar interface.
+//
+// It returns an empty slice if the URL's scheme is not HTTP or HTTPS.
+func (j *Jar) Cookies(u *url.URL) (cookies []*http.Cookie) {
+	return j.cookies(u, time.Now())
+}
+
+// cookies is like Cookies but takes the current time as a parameter.
+func (j *Jar) cookies(u *url.URL, now time.Time) (cookies []*http.Cookie) {
+	if u.Scheme != "http" && u.Scheme != "https" {
+		return cookies
+	}
+	host, err := canonicalHost(u.Host)
+	if err != nil {
+		return cookies
+	}
+	key := jarKey(host, j.psList)
+
+	j.mu.Lock()
+	defer j.mu.Unlock()
+
+	submap := j.entries[key]
+	if submap == nil {
+		return cookies
+	}
+
+	https := u.Scheme == "https"
+	path := u.Path
+	if path == "" {
+		path = "/"
+	}
+
+	modified := false
+	var selected []entry
+	for id, e := range submap {
+		if e.Persistent && !e.Expires.After(now) {
+			delete(submap, id)
+			modified = true
+			continue
+		}
+		if !e.shouldSend(https, host, path) {
+			continue
+		}
+		e.LastAccess = now
+		submap[id] = e
+		selected = append(selected, e)
+		modified = true
+	}
+	if modified {
+		if len(submap) == 0 {
+			delete(j.entries, key)
+		} else {
+			j.entries[key] = submap
+		}
+	}
+
+	sort.Sort(byPathLength(selected))
+	for _, e := range selected {
+		cookies = append(cookies, &http.Cookie{Name: e.Name, Value: e.Value})
+	}
+
+	return cookies
+}
+
+// SetCookies implements the SetCookies method of the http.CookieJar interface.
+//
+// It does nothing if the URL's scheme is not HTTP or HTTPS.
+func (j *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
+	j.setCookies(u, cookies, time.Now())
+}
+
+// setCookies is like SetCookies but takes the current time as parameter.
+func (j *Jar) setCookies(u *url.URL, cookies []*http.Cookie, now time.Time) {
+	if len(cookies) == 0 {
+		return
+	}
+	if u.Scheme != "http" && u.Scheme != "https" {
+		return
+	}
+	host, err := canonicalHost(u.Host)
+	if err != nil {
+		return
+	}
+	key := jarKey(host, j.psList)
+	defPath := defaultPath(u.Path)
+
+	j.mu.Lock()
+	defer j.mu.Unlock()
+
+	submap := j.entries[key]
+
+	modified := false
+	for _, cookie := range cookies {
+		e, remove, err := j.newEntry(cookie, now, defPath, host)
+		if err != nil {
+			continue
+		}
+		id := e.id()
+		if remove {
+			if submap != nil {
+				if _, ok := submap[id]; ok {
+					delete(submap, id)
+					modified = true
+				}
+			}
+			continue
+		}
+		if submap == nil {
+			submap = make(map[string]entry)
+		}
+
+		if old, ok := submap[id]; ok {
+			e.Creation = old.Creation
+			e.seqNum = old.seqNum
+		} else {
+			e.Creation = now
+			e.seqNum = j.nextSeqNum
+			j.nextSeqNum++
+		}
+		e.LastAccess = now
+		submap[id] = e
+		modified = true
+	}
+
+	if modified {
+		if len(submap) == 0 {
+			delete(j.entries, key)
+		} else {
+			j.entries[key] = submap
+		}
+	}
+}
+
+// canonicalHost strips port from host if present and returns the canonicalized
+// host name.
+func canonicalHost(host string) (string, error) {
+	var err error
+	host = strings.ToLower(host)
+	if hasPort(host) {
+		host, _, err = net.SplitHostPort(host)
+		if err != nil {
+			return "", err
+		}
+	}
+	if strings.HasSuffix(host, ".") {
+		// Strip trailing dot from fully qualified domain names.
+		host = host[:len(host)-1]
+	}
+	return toASCII(host)
+}
+
+// hasPort reports whether host contains a port number. host may be a host
+// name, an IPv4 or an IPv6 address.
+func hasPort(host string) bool {
+	colons := strings.Count(host, ":")
+	if colons == 0 {
+		return false
+	}
+	if colons == 1 {
+		return true
+	}
+	return host[0] == '[' && strings.Contains(host, "]:")
+}
+
+// jarKey returns the key to use for a jar.
+func jarKey(host string, psl PublicSuffixList) string {
+	if isIP(host) {
+		return host
+	}
+
+	var i int
+	if psl == nil {
+		i = strings.LastIndex(host, ".")
+		if i == -1 {
+			return host
+		}
+	} else {
+		suffix := psl.PublicSuffix(host)
+		if suffix == host {
+			return host
+		}
+		i = len(host) - len(suffix)
+		if i <= 0 || host[i-1] != '.' {
+			// The provided public suffix list psl is broken.
+			// Storing cookies under host is a safe stopgap.
+			return host
+		}
+	}
+	prevDot := strings.LastIndex(host[:i-1], ".")
+	return host[prevDot+1:]
+}
+
+// isIP reports whether host is an IP address.
+func isIP(host string) bool {
+	return net.ParseIP(host) != nil
+}
+
+// defaultPath returns the directory part of an URL's path according to
+// RFC 6265 section 5.1.4.
+func defaultPath(path string) string {
+	if len(path) == 0 || path[0] != '/' {
+		return "/" // Path is empty or malformed.
+	}
+
+	i := strings.LastIndex(path, "/") // Path starts with "/", so i != -1.
+	if i == 0 {
+		return "/" // Path has the form "/abc".
+	}
+	return path[:i] // Path is either of form "/abc/xyz" or "/abc/xyz/".
+}
+
+// newEntry creates an entry from a http.Cookie c. now is the current time and
+// is compared to c.Expires to determine deletion of c. defPath and host are the
+// default-path and the canonical host name of the URL c was received from.
+//
+// remove records whether the jar should delete this cookie, as it has already
+// expired with respect to now. In this case, e may be incomplete, but it will
+// be valid to call e.id (which depends on e's Name, Domain and Path).
+//
+// A malformed c.Domain will result in an error.
+func (j *Jar) newEntry(c *http.Cookie, now time.Time, defPath, host string) (e entry, remove bool, err error) {
+	e.Name = c.Name
+
+	if c.Path == "" || c.Path[0] != '/' {
+		e.Path = defPath
+	} else {
+		e.Path = c.Path
+	}
+
+	e.Domain, e.HostOnly, err = j.domainAndType(host, c.Domain)
+	if err != nil {
+		return e, false, err
+	}
+
+	// MaxAge takes precedence over Expires.
+	if c.MaxAge < 0 {
+		return e, true, nil
+	} else if c.MaxAge > 0 {
+		e.Expires = now.Add(time.Duration(c.MaxAge) * time.Second)
+		e.Persistent = true
+	} else {
+		if c.Expires.IsZero() {
+			e.Expires = endOfTime
+			e.Persistent = false
+		} else {
+			if !c.Expires.After(now) {
+				return e, true, nil
+			}
+			e.Expires = c.Expires
+			e.Persistent = true
+		}
+	}
+
+	e.Value = c.Value
+	e.Secure = c.Secure
+	e.HttpOnly = c.HttpOnly
+
+	return e, false, nil
+}
+
+var (
+	errIllegalDomain   = errors.New("cookiejar: illegal cookie domain attribute")
+	errMalformedDomain = errors.New("cookiejar: malformed cookie domain attribute")
+	errNoHostname      = errors.New("cookiejar: no host name available (IP only)")
+)
+
+// endOfTime is the time when session (non-persistent) cookies expire.
+// This instant is representable in most date/time formats (not just
+// Go's time.Time) and should be far enough in the future.
+var endOfTime = time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC)
+
+// domainAndType determines the cookie's domain and hostOnly attribute.
+func (j *Jar) domainAndType(host, domain string) (string, bool, error) {
+	if domain == "" {
+		// No domain attribute in the SetCookie header indicates a
+		// host cookie.
+		return host, true, nil
+	}
+
+	if isIP(host) {
+		// According to RFC 6265 domain-matching includes not being
+		// an IP address.
+		// TODO: This might be relaxed as in common browsers.
+		return "", false, errNoHostname
+	}
+
+	// From here on: If the cookie is valid, it is a domain cookie (with
+	// the one exception of a public suffix below).
+	// See RFC 6265 section 5.2.3.
+	if domain[0] == '.' {
+		domain = domain[1:]
+	}
+
+	if len(domain) == 0 || domain[0] == '.' {
+		// Received either "Domain=." or "Domain=..some.thing",
+		// both are illegal.
+		return "", false, errMalformedDomain
+	}
+	domain = strings.ToLower(domain)
+
+	if domain[len(domain)-1] == '.' {
+		// We received stuff like "Domain=www.example.com.".
+		// Browsers do handle such stuff (actually differently) but
+		// RFC 6265 seems to be clear here (e.g. section 4.1.2.3) in
+		// requiring a reject.  4.1.2.3 is not normative, but
+		// "Domain Matching" (5.1.3) and "Canonicalized Host Names"
+		// (5.1.2) are.
+		return "", false, errMalformedDomain
+	}
+
+	// See RFC 6265 section 5.3 #5.
+	if j.psList != nil {
+		if ps := j.psList.PublicSuffix(domain); ps != "" && !hasDotSuffix(domain, ps) {
+			if host == domain {
+				// This is the one exception in which a cookie
+				// with a domain attribute is a host cookie.
+				return host, true, nil
+			}
+			return "", false, errIllegalDomain
+		}
+	}
+
+	// The domain must domain-match host: www.mycompany.com cannot
+	// set cookies for .ourcompetitors.com.
+	if host != domain && !hasDotSuffix(host, domain) {
+		return "", false, errIllegalDomain
+	}
+
+	return domain, false, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cookiejar/jar_test.go b/third_party/gofrontend/libgo/go/net/http/cookiejar/jar_test.go
new file mode 100644
index 0000000..3aa6015
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cookiejar/jar_test.go
@@ -0,0 +1,1267 @@
+// Copyright 2013 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 cookiejar
+
+import (
+	"fmt"
+	"net/http"
+	"net/url"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+)
+
+// tNow is the synthetic current time used as now during testing.
+var tNow = time.Date(2013, 1, 1, 12, 0, 0, 0, time.UTC)
+
+// testPSL implements PublicSuffixList with just two rules: "co.uk"
+// and the default rule "*".
+type testPSL struct{}
+
+func (testPSL) String() string {
+	return "testPSL"
+}
+func (testPSL) PublicSuffix(d string) string {
+	if d == "co.uk" || strings.HasSuffix(d, ".co.uk") {
+		return "co.uk"
+	}
+	return d[strings.LastIndex(d, ".")+1:]
+}
+
+// newTestJar creates an empty Jar with testPSL as the public suffix list.
+func newTestJar() *Jar {
+	jar, err := New(&Options{PublicSuffixList: testPSL{}})
+	if err != nil {
+		panic(err)
+	}
+	return jar
+}
+
+var hasDotSuffixTests = [...]struct {
+	s, suffix string
+}{
+	{"", ""},
+	{"", "."},
+	{"", "x"},
+	{".", ""},
+	{".", "."},
+	{".", ".."},
+	{".", "x"},
+	{".", "x."},
+	{".", ".x"},
+	{".", ".x."},
+	{"x", ""},
+	{"x", "."},
+	{"x", ".."},
+	{"x", "x"},
+	{"x", "x."},
+	{"x", ".x"},
+	{"x", ".x."},
+	{".x", ""},
+	{".x", "."},
+	{".x", ".."},
+	{".x", "x"},
+	{".x", "x."},
+	{".x", ".x"},
+	{".x", ".x."},
+	{"x.", ""},
+	{"x.", "."},
+	{"x.", ".."},
+	{"x.", "x"},
+	{"x.", "x."},
+	{"x.", ".x"},
+	{"x.", ".x."},
+	{"com", ""},
+	{"com", "m"},
+	{"com", "om"},
+	{"com", "com"},
+	{"com", ".com"},
+	{"com", "x.com"},
+	{"com", "xcom"},
+	{"com", "xorg"},
+	{"com", "org"},
+	{"com", "rg"},
+	{"foo.com", ""},
+	{"foo.com", "m"},
+	{"foo.com", "om"},
+	{"foo.com", "com"},
+	{"foo.com", ".com"},
+	{"foo.com", "o.com"},
+	{"foo.com", "oo.com"},
+	{"foo.com", "foo.com"},
+	{"foo.com", ".foo.com"},
+	{"foo.com", "x.foo.com"},
+	{"foo.com", "xfoo.com"},
+	{"foo.com", "xfoo.org"},
+	{"foo.com", "foo.org"},
+	{"foo.com", "oo.org"},
+	{"foo.com", "o.org"},
+	{"foo.com", ".org"},
+	{"foo.com", "org"},
+	{"foo.com", "rg"},
+}
+
+func TestHasDotSuffix(t *testing.T) {
+	for _, tc := range hasDotSuffixTests {
+		got := hasDotSuffix(tc.s, tc.suffix)
+		want := strings.HasSuffix(tc.s, "."+tc.suffix)
+		if got != want {
+			t.Errorf("s=%q, suffix=%q: got %v, want %v", tc.s, tc.suffix, got, want)
+		}
+	}
+}
+
+var canonicalHostTests = map[string]string{
+	"www.example.com":         "www.example.com",
+	"WWW.EXAMPLE.COM":         "www.example.com",
+	"wWw.eXAmple.CoM":         "www.example.com",
+	"www.example.com:80":      "www.example.com",
+	"192.168.0.10":            "192.168.0.10",
+	"192.168.0.5:8080":        "192.168.0.5",
+	"2001:4860:0:2001::68":    "2001:4860:0:2001::68",
+	"[2001:4860:0:::68]:8080": "2001:4860:0:::68",
+	"www.bücher.de":           "www.xn--bcher-kva.de",
+	"www.example.com.":        "www.example.com",
+	"[bad.unmatched.bracket:": "error",
+}
+
+func TestCanonicalHost(t *testing.T) {
+	for h, want := range canonicalHostTests {
+		got, err := canonicalHost(h)
+		if want == "error" {
+			if err == nil {
+				t.Errorf("%q: got nil error, want non-nil", h)
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("%q: %v", h, err)
+			continue
+		}
+		if got != want {
+			t.Errorf("%q: got %q, want %q", h, got, want)
+			continue
+		}
+	}
+}
+
+var hasPortTests = map[string]bool{
+	"www.example.com":      false,
+	"www.example.com:80":   true,
+	"127.0.0.1":            false,
+	"127.0.0.1:8080":       true,
+	"2001:4860:0:2001::68": false,
+	"[2001::0:::68]:80":    true,
+}
+
+func TestHasPort(t *testing.T) {
+	for host, want := range hasPortTests {
+		if got := hasPort(host); got != want {
+			t.Errorf("%q: got %t, want %t", host, got, want)
+		}
+	}
+}
+
+var jarKeyTests = map[string]string{
+	"foo.www.example.com": "example.com",
+	"www.example.com":     "example.com",
+	"example.com":         "example.com",
+	"com":                 "com",
+	"foo.www.bbc.co.uk":   "bbc.co.uk",
+	"www.bbc.co.uk":       "bbc.co.uk",
+	"bbc.co.uk":           "bbc.co.uk",
+	"co.uk":               "co.uk",
+	"uk":                  "uk",
+	"192.168.0.5":         "192.168.0.5",
+}
+
+func TestJarKey(t *testing.T) {
+	for host, want := range jarKeyTests {
+		if got := jarKey(host, testPSL{}); got != want {
+			t.Errorf("%q: got %q, want %q", host, got, want)
+		}
+	}
+}
+
+var jarKeyNilPSLTests = map[string]string{
+	"foo.www.example.com": "example.com",
+	"www.example.com":     "example.com",
+	"example.com":         "example.com",
+	"com":                 "com",
+	"foo.www.bbc.co.uk":   "co.uk",
+	"www.bbc.co.uk":       "co.uk",
+	"bbc.co.uk":           "co.uk",
+	"co.uk":               "co.uk",
+	"uk":                  "uk",
+	"192.168.0.5":         "192.168.0.5",
+}
+
+func TestJarKeyNilPSL(t *testing.T) {
+	for host, want := range jarKeyNilPSLTests {
+		if got := jarKey(host, nil); got != want {
+			t.Errorf("%q: got %q, want %q", host, got, want)
+		}
+	}
+}
+
+var isIPTests = map[string]bool{
+	"127.0.0.1":            true,
+	"1.2.3.4":              true,
+	"2001:4860:0:2001::68": true,
+	"example.com":          false,
+	"1.1.1.300":            false,
+	"www.foo.bar.net":      false,
+	"123.foo.bar.net":      false,
+}
+
+func TestIsIP(t *testing.T) {
+	for host, want := range isIPTests {
+		if got := isIP(host); got != want {
+			t.Errorf("%q: got %t, want %t", host, got, want)
+		}
+	}
+}
+
+var defaultPathTests = map[string]string{
+	"/":           "/",
+	"/abc":        "/",
+	"/abc/":       "/abc",
+	"/abc/xyz":    "/abc",
+	"/abc/xyz/":   "/abc/xyz",
+	"/a/b/c.html": "/a/b",
+	"":            "/",
+	"strange":     "/",
+	"//":          "/",
+	"/a//b":       "/a/",
+	"/a/./b":      "/a/.",
+	"/a/../b":     "/a/..",
+}
+
+func TestDefaultPath(t *testing.T) {
+	for path, want := range defaultPathTests {
+		if got := defaultPath(path); got != want {
+			t.Errorf("%q: got %q, want %q", path, got, want)
+		}
+	}
+}
+
+var domainAndTypeTests = [...]struct {
+	host         string // host Set-Cookie header was received from
+	domain       string // domain attribute in Set-Cookie header
+	wantDomain   string // expected domain of cookie
+	wantHostOnly bool   // expected host-cookie flag
+	wantErr      error  // expected error
+}{
+	{"www.example.com", "", "www.example.com", true, nil},
+	{"127.0.0.1", "", "127.0.0.1", true, nil},
+	{"2001:4860:0:2001::68", "", "2001:4860:0:2001::68", true, nil},
+	{"www.example.com", "example.com", "example.com", false, nil},
+	{"www.example.com", ".example.com", "example.com", false, nil},
+	{"www.example.com", "www.example.com", "www.example.com", false, nil},
+	{"www.example.com", ".www.example.com", "www.example.com", false, nil},
+	{"foo.sso.example.com", "sso.example.com", "sso.example.com", false, nil},
+	{"bar.co.uk", "bar.co.uk", "bar.co.uk", false, nil},
+	{"foo.bar.co.uk", ".bar.co.uk", "bar.co.uk", false, nil},
+	{"127.0.0.1", "127.0.0.1", "", false, errNoHostname},
+	{"2001:4860:0:2001::68", "2001:4860:0:2001::68", "2001:4860:0:2001::68", false, errNoHostname},
+	{"www.example.com", ".", "", false, errMalformedDomain},
+	{"www.example.com", "..", "", false, errMalformedDomain},
+	{"www.example.com", "other.com", "", false, errIllegalDomain},
+	{"www.example.com", "com", "", false, errIllegalDomain},
+	{"www.example.com", ".com", "", false, errIllegalDomain},
+	{"foo.bar.co.uk", ".co.uk", "", false, errIllegalDomain},
+	{"127.www.0.0.1", "127.0.0.1", "", false, errIllegalDomain},
+	{"com", "", "com", true, nil},
+	{"com", "com", "com", true, nil},
+	{"com", ".com", "com", true, nil},
+	{"co.uk", "", "co.uk", true, nil},
+	{"co.uk", "co.uk", "co.uk", true, nil},
+	{"co.uk", ".co.uk", "co.uk", true, nil},
+}
+
+func TestDomainAndType(t *testing.T) {
+	jar := newTestJar()
+	for _, tc := range domainAndTypeTests {
+		domain, hostOnly, err := jar.domainAndType(tc.host, tc.domain)
+		if err != tc.wantErr {
+			t.Errorf("%q/%q: got %q error, want %q",
+				tc.host, tc.domain, err, tc.wantErr)
+			continue
+		}
+		if err != nil {
+			continue
+		}
+		if domain != tc.wantDomain || hostOnly != tc.wantHostOnly {
+			t.Errorf("%q/%q: got %q/%t want %q/%t",
+				tc.host, tc.domain, domain, hostOnly,
+				tc.wantDomain, tc.wantHostOnly)
+		}
+	}
+}
+
+// expiresIn creates an expires attribute delta seconds from tNow.
+func expiresIn(delta int) string {
+	t := tNow.Add(time.Duration(delta) * time.Second)
+	return "expires=" + t.Format(time.RFC1123)
+}
+
+// mustParseURL parses s to an URL and panics on error.
+func mustParseURL(s string) *url.URL {
+	u, err := url.Parse(s)
+	if err != nil || u.Scheme == "" || u.Host == "" {
+		panic(fmt.Sprintf("Unable to parse URL %s.", s))
+	}
+	return u
+}
+
+// jarTest encapsulates the following actions on a jar:
+//   1. Perform SetCookies with fromURL and the cookies from setCookies.
+//      (Done at time tNow + 0 ms.)
+//   2. Check that the entries in the jar matches content.
+//      (Done at time tNow + 1001 ms.)
+//   3. For each query in tests: Check that Cookies with toURL yields the
+//      cookies in want.
+//      (Query n done at tNow + (n+2)*1001 ms.)
+type jarTest struct {
+	description string   // The description of what this test is supposed to test
+	fromURL     string   // The full URL of the request from which Set-Cookie headers where received
+	setCookies  []string // All the cookies received from fromURL
+	content     string   // The whole (non-expired) content of the jar
+	queries     []query  // Queries to test the Jar.Cookies method
+}
+
+// query contains one test of the cookies returned from Jar.Cookies.
+type query struct {
+	toURL string // the URL in the Cookies call
+	want  string // the expected list of cookies (order matters)
+}
+
+// run runs the jarTest.
+func (test jarTest) run(t *testing.T, jar *Jar) {
+	now := tNow
+
+	// Populate jar with cookies.
+	setCookies := make([]*http.Cookie, len(test.setCookies))
+	for i, cs := range test.setCookies {
+		cookies := (&http.Response{Header: http.Header{"Set-Cookie": {cs}}}).Cookies()
+		if len(cookies) != 1 {
+			panic(fmt.Sprintf("Wrong cookie line %q: %#v", cs, cookies))
+		}
+		setCookies[i] = cookies[0]
+	}
+	jar.setCookies(mustParseURL(test.fromURL), setCookies, now)
+	now = now.Add(1001 * time.Millisecond)
+
+	// Serialize non-expired entries in the form "name1=val1 name2=val2".
+	var cs []string
+	for _, submap := range jar.entries {
+		for _, cookie := range submap {
+			if !cookie.Expires.After(now) {
+				continue
+			}
+			cs = append(cs, cookie.Name+"="+cookie.Value)
+		}
+	}
+	sort.Strings(cs)
+	got := strings.Join(cs, " ")
+
+	// Make sure jar content matches our expectations.
+	if got != test.content {
+		t.Errorf("Test %q Content\ngot  %q\nwant %q",
+			test.description, got, test.content)
+	}
+
+	// Test different calls to Cookies.
+	for i, query := range test.queries {
+		now = now.Add(1001 * time.Millisecond)
+		var s []string
+		for _, c := range jar.cookies(mustParseURL(query.toURL), now) {
+			s = append(s, c.Name+"="+c.Value)
+		}
+		if got := strings.Join(s, " "); got != query.want {
+			t.Errorf("Test %q #%d\ngot  %q\nwant %q", test.description, i, got, query.want)
+		}
+	}
+}
+
+// basicsTests contains fundamental tests. Each jarTest has to be performed on
+// a fresh, empty Jar.
+var basicsTests = [...]jarTest{
+	{
+		"Retrieval of a plain host cookie.",
+		"http://www.host.test/",
+		[]string{"A=a"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", "A=a"},
+			{"http://www.host.test/", "A=a"},
+			{"http://www.host.test/some/path", "A=a"},
+			{"https://www.host.test", "A=a"},
+			{"https://www.host.test/", "A=a"},
+			{"https://www.host.test/some/path", "A=a"},
+			{"ftp://www.host.test", ""},
+			{"ftp://www.host.test/", ""},
+			{"ftp://www.host.test/some/path", ""},
+			{"http://www.other.org", ""},
+			{"http://sibling.host.test", ""},
+			{"http://deep.www.host.test", ""},
+		},
+	},
+	{
+		"Secure cookies are not returned to http.",
+		"http://www.host.test/",
+		[]string{"A=a; secure"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", ""},
+			{"http://www.host.test/", ""},
+			{"http://www.host.test/some/path", ""},
+			{"https://www.host.test", "A=a"},
+			{"https://www.host.test/", "A=a"},
+			{"https://www.host.test/some/path", "A=a"},
+		},
+	},
+	{
+		"Explicit path.",
+		"http://www.host.test/",
+		[]string{"A=a; path=/some/path"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", ""},
+			{"http://www.host.test/", ""},
+			{"http://www.host.test/some", ""},
+			{"http://www.host.test/some/", ""},
+			{"http://www.host.test/some/path", "A=a"},
+			{"http://www.host.test/some/paths", ""},
+			{"http://www.host.test/some/path/foo", "A=a"},
+			{"http://www.host.test/some/path/foo/", "A=a"},
+		},
+	},
+	{
+		"Implicit path #1: path is a directory.",
+		"http://www.host.test/some/path/",
+		[]string{"A=a"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", ""},
+			{"http://www.host.test/", ""},
+			{"http://www.host.test/some", ""},
+			{"http://www.host.test/some/", ""},
+			{"http://www.host.test/some/path", "A=a"},
+			{"http://www.host.test/some/paths", ""},
+			{"http://www.host.test/some/path/foo", "A=a"},
+			{"http://www.host.test/some/path/foo/", "A=a"},
+		},
+	},
+	{
+		"Implicit path #2: path is not a directory.",
+		"http://www.host.test/some/path/index.html",
+		[]string{"A=a"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", ""},
+			{"http://www.host.test/", ""},
+			{"http://www.host.test/some", ""},
+			{"http://www.host.test/some/", ""},
+			{"http://www.host.test/some/path", "A=a"},
+			{"http://www.host.test/some/paths", ""},
+			{"http://www.host.test/some/path/foo", "A=a"},
+			{"http://www.host.test/some/path/foo/", "A=a"},
+		},
+	},
+	{
+		"Implicit path #3: no path in URL at all.",
+		"http://www.host.test",
+		[]string{"A=a"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", "A=a"},
+			{"http://www.host.test/", "A=a"},
+			{"http://www.host.test/some/path", "A=a"},
+		},
+	},
+	{
+		"Cookies are sorted by path length.",
+		"http://www.host.test/",
+		[]string{
+			"A=a; path=/foo/bar",
+			"B=b; path=/foo/bar/baz/qux",
+			"C=c; path=/foo/bar/baz",
+			"D=d; path=/foo"},
+		"A=a B=b C=c D=d",
+		[]query{
+			{"http://www.host.test/foo/bar/baz/qux", "B=b C=c A=a D=d"},
+			{"http://www.host.test/foo/bar/baz/", "C=c A=a D=d"},
+			{"http://www.host.test/foo/bar", "A=a D=d"},
+		},
+	},
+	{
+		"Creation time determines sorting on same length paths.",
+		"http://www.host.test/",
+		[]string{
+			"A=a; path=/foo/bar",
+			"X=x; path=/foo/bar",
+			"Y=y; path=/foo/bar/baz/qux",
+			"B=b; path=/foo/bar/baz/qux",
+			"C=c; path=/foo/bar/baz",
+			"W=w; path=/foo/bar/baz",
+			"Z=z; path=/foo",
+			"D=d; path=/foo"},
+		"A=a B=b C=c D=d W=w X=x Y=y Z=z",
+		[]query{
+			{"http://www.host.test/foo/bar/baz/qux", "Y=y B=b C=c W=w A=a X=x Z=z D=d"},
+			{"http://www.host.test/foo/bar/baz/", "C=c W=w A=a X=x Z=z D=d"},
+			{"http://www.host.test/foo/bar", "A=a X=x Z=z D=d"},
+		},
+	},
+	{
+		"Sorting of same-name cookies.",
+		"http://www.host.test/",
+		[]string{
+			"A=1; path=/",
+			"A=2; path=/path",
+			"A=3; path=/quux",
+			"A=4; path=/path/foo",
+			"A=5; domain=.host.test; path=/path",
+			"A=6; domain=.host.test; path=/quux",
+			"A=7; domain=.host.test; path=/path/foo",
+		},
+		"A=1 A=2 A=3 A=4 A=5 A=6 A=7",
+		[]query{
+			{"http://www.host.test/path", "A=2 A=5 A=1"},
+			{"http://www.host.test/path/foo", "A=4 A=7 A=2 A=5 A=1"},
+		},
+	},
+	{
+		"Disallow domain cookie on public suffix.",
+		"http://www.bbc.co.uk",
+		[]string{
+			"a=1",
+			"b=2; domain=co.uk",
+		},
+		"a=1",
+		[]query{{"http://www.bbc.co.uk", "a=1"}},
+	},
+	{
+		"Host cookie on IP.",
+		"http://192.168.0.10",
+		[]string{"a=1"},
+		"a=1",
+		[]query{{"http://192.168.0.10", "a=1"}},
+	},
+	{
+		"Port is ignored #1.",
+		"http://www.host.test/",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://www.host.test", "a=1"},
+			{"http://www.host.test:8080/", "a=1"},
+		},
+	},
+	{
+		"Port is ignored #2.",
+		"http://www.host.test:8080/",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://www.host.test", "a=1"},
+			{"http://www.host.test:8080/", "a=1"},
+			{"http://www.host.test:1234/", "a=1"},
+		},
+	},
+}
+
+func TestBasics(t *testing.T) {
+	for _, test := range basicsTests {
+		jar := newTestJar()
+		test.run(t, jar)
+	}
+}
+
+// updateAndDeleteTests contains jarTests which must be performed on the same
+// Jar.
+var updateAndDeleteTests = [...]jarTest{
+	{
+		"Set initial cookies.",
+		"http://www.host.test",
+		[]string{
+			"a=1",
+			"b=2; secure",
+			"c=3; httponly",
+			"d=4; secure; httponly"},
+		"a=1 b=2 c=3 d=4",
+		[]query{
+			{"http://www.host.test", "a=1 c=3"},
+			{"https://www.host.test", "a=1 b=2 c=3 d=4"},
+		},
+	},
+	{
+		"Update value via http.",
+		"http://www.host.test",
+		[]string{
+			"a=w",
+			"b=x; secure",
+			"c=y; httponly",
+			"d=z; secure; httponly"},
+		"a=w b=x c=y d=z",
+		[]query{
+			{"http://www.host.test", "a=w c=y"},
+			{"https://www.host.test", "a=w b=x c=y d=z"},
+		},
+	},
+	{
+		"Clear Secure flag from a http.",
+		"http://www.host.test/",
+		[]string{
+			"b=xx",
+			"d=zz; httponly"},
+		"a=w b=xx c=y d=zz",
+		[]query{{"http://www.host.test", "a=w b=xx c=y d=zz"}},
+	},
+	{
+		"Delete all.",
+		"http://www.host.test/",
+		[]string{
+			"a=1; max-Age=-1",                    // delete via MaxAge
+			"b=2; " + expiresIn(-10),             // delete via Expires
+			"c=2; max-age=-1; " + expiresIn(-10), // delete via both
+			"d=4; max-age=-1; " + expiresIn(10)}, // MaxAge takes precedence
+		"",
+		[]query{{"http://www.host.test", ""}},
+	},
+	{
+		"Refill #1.",
+		"http://www.host.test",
+		[]string{
+			"A=1",
+			"A=2; path=/foo",
+			"A=3; domain=.host.test",
+			"A=4; path=/foo; domain=.host.test"},
+		"A=1 A=2 A=3 A=4",
+		[]query{{"http://www.host.test/foo", "A=2 A=4 A=1 A=3"}},
+	},
+	{
+		"Refill #2.",
+		"http://www.google.com",
+		[]string{
+			"A=6",
+			"A=7; path=/foo",
+			"A=8; domain=.google.com",
+			"A=9; path=/foo; domain=.google.com"},
+		"A=1 A=2 A=3 A=4 A=6 A=7 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=4 A=1 A=3"},
+			{"http://www.google.com/foo", "A=7 A=9 A=6 A=8"},
+		},
+	},
+	{
+		"Delete A7.",
+		"http://www.google.com",
+		[]string{"A=; path=/foo; max-age=-1"},
+		"A=1 A=2 A=3 A=4 A=6 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=4 A=1 A=3"},
+			{"http://www.google.com/foo", "A=9 A=6 A=8"},
+		},
+	},
+	{
+		"Delete A4.",
+		"http://www.host.test",
+		[]string{"A=; path=/foo; domain=host.test; max-age=-1"},
+		"A=1 A=2 A=3 A=6 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=1 A=3"},
+			{"http://www.google.com/foo", "A=9 A=6 A=8"},
+		},
+	},
+	{
+		"Delete A6.",
+		"http://www.google.com",
+		[]string{"A=; max-age=-1"},
+		"A=1 A=2 A=3 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=1 A=3"},
+			{"http://www.google.com/foo", "A=9 A=8"},
+		},
+	},
+	{
+		"Delete A3.",
+		"http://www.host.test",
+		[]string{"A=; domain=host.test; max-age=-1"},
+		"A=1 A=2 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=1"},
+			{"http://www.google.com/foo", "A=9 A=8"},
+		},
+	},
+	{
+		"No cross-domain delete.",
+		"http://www.host.test",
+		[]string{
+			"A=; domain=google.com; max-age=-1",
+			"A=; path=/foo; domain=google.com; max-age=-1"},
+		"A=1 A=2 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=1"},
+			{"http://www.google.com/foo", "A=9 A=8"},
+		},
+	},
+	{
+		"Delete A8 and A9.",
+		"http://www.google.com",
+		[]string{
+			"A=; domain=google.com; max-age=-1",
+			"A=; path=/foo; domain=google.com; max-age=-1"},
+		"A=1 A=2",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=1"},
+			{"http://www.google.com/foo", ""},
+		},
+	},
+}
+
+func TestUpdateAndDelete(t *testing.T) {
+	jar := newTestJar()
+	for _, test := range updateAndDeleteTests {
+		test.run(t, jar)
+	}
+}
+
+func TestExpiration(t *testing.T) {
+	jar := newTestJar()
+	jarTest{
+		"Expiration.",
+		"http://www.host.test",
+		[]string{
+			"a=1",
+			"b=2; max-age=3",
+			"c=3; " + expiresIn(3),
+			"d=4; max-age=5",
+			"e=5; " + expiresIn(5),
+			"f=6; max-age=100",
+		},
+		"a=1 b=2 c=3 d=4 e=5 f=6", // executed at t0 + 1001 ms
+		[]query{
+			{"http://www.host.test", "a=1 b=2 c=3 d=4 e=5 f=6"}, // t0 + 2002 ms
+			{"http://www.host.test", "a=1 d=4 e=5 f=6"},         // t0 + 3003 ms
+			{"http://www.host.test", "a=1 d=4 e=5 f=6"},         // t0 + 4004 ms
+			{"http://www.host.test", "a=1 f=6"},                 // t0 + 5005 ms
+			{"http://www.host.test", "a=1 f=6"},                 // t0 + 6006 ms
+		},
+	}.run(t, jar)
+}
+
+//
+// Tests derived from Chromium's cookie_store_unittest.h.
+//
+
+// See http://src.chromium.org/viewvc/chrome/trunk/src/net/cookies/cookie_store_unittest.h?revision=159685&content-type=text/plain
+// Some of the original tests are in a bad condition (e.g.
+// DomainWithTrailingDotTest) or are not RFC 6265 conforming (e.g.
+// TestNonDottedAndTLD #1 and #6) and have not been ported.
+
+// chromiumBasicsTests contains fundamental tests. Each jarTest has to be
+// performed on a fresh, empty Jar.
+var chromiumBasicsTests = [...]jarTest{
+	{
+		"DomainWithTrailingDotTest.",
+		"http://www.google.com/",
+		[]string{
+			"a=1; domain=.www.google.com.",
+			"b=2; domain=.www.google.com.."},
+		"",
+		[]query{
+			{"http://www.google.com", ""},
+		},
+	},
+	{
+		"ValidSubdomainTest #1.",
+		"http://a.b.c.d.com",
+		[]string{
+			"a=1; domain=.a.b.c.d.com",
+			"b=2; domain=.b.c.d.com",
+			"c=3; domain=.c.d.com",
+			"d=4; domain=.d.com"},
+		"a=1 b=2 c=3 d=4",
+		[]query{
+			{"http://a.b.c.d.com", "a=1 b=2 c=3 d=4"},
+			{"http://b.c.d.com", "b=2 c=3 d=4"},
+			{"http://c.d.com", "c=3 d=4"},
+			{"http://d.com", "d=4"},
+		},
+	},
+	{
+		"ValidSubdomainTest #2.",
+		"http://a.b.c.d.com",
+		[]string{
+			"a=1; domain=.a.b.c.d.com",
+			"b=2; domain=.b.c.d.com",
+			"c=3; domain=.c.d.com",
+			"d=4; domain=.d.com",
+			"X=bcd; domain=.b.c.d.com",
+			"X=cd; domain=.c.d.com"},
+		"X=bcd X=cd a=1 b=2 c=3 d=4",
+		[]query{
+			{"http://b.c.d.com", "b=2 c=3 d=4 X=bcd X=cd"},
+			{"http://c.d.com", "c=3 d=4 X=cd"},
+		},
+	},
+	{
+		"InvalidDomainTest #1.",
+		"http://foo.bar.com",
+		[]string{
+			"a=1; domain=.yo.foo.bar.com",
+			"b=2; domain=.foo.com",
+			"c=3; domain=.bar.foo.com",
+			"d=4; domain=.foo.bar.com.net",
+			"e=5; domain=ar.com",
+			"f=6; domain=.",
+			"g=7; domain=/",
+			"h=8; domain=http://foo.bar.com",
+			"i=9; domain=..foo.bar.com",
+			"j=10; domain=..bar.com",
+			"k=11; domain=.foo.bar.com?blah",
+			"l=12; domain=.foo.bar.com/blah",
+			"m=12; domain=.foo.bar.com:80",
+			"n=14; domain=.foo.bar.com:",
+			"o=15; domain=.foo.bar.com#sup",
+		},
+		"", // Jar is empty.
+		[]query{{"http://foo.bar.com", ""}},
+	},
+	{
+		"InvalidDomainTest #2.",
+		"http://foo.com.com",
+		[]string{"a=1; domain=.foo.com.com.com"},
+		"",
+		[]query{{"http://foo.bar.com", ""}},
+	},
+	{
+		"DomainWithoutLeadingDotTest #1.",
+		"http://manage.hosted.filefront.com",
+		[]string{"a=1; domain=filefront.com"},
+		"a=1",
+		[]query{{"http://www.filefront.com", "a=1"}},
+	},
+	{
+		"DomainWithoutLeadingDotTest #2.",
+		"http://www.google.com",
+		[]string{"a=1; domain=www.google.com"},
+		"a=1",
+		[]query{
+			{"http://www.google.com", "a=1"},
+			{"http://sub.www.google.com", "a=1"},
+			{"http://something-else.com", ""},
+		},
+	},
+	{
+		"CaseInsensitiveDomainTest.",
+		"http://www.google.com",
+		[]string{
+			"a=1; domain=.GOOGLE.COM",
+			"b=2; domain=.www.gOOgLE.coM"},
+		"a=1 b=2",
+		[]query{{"http://www.google.com", "a=1 b=2"}},
+	},
+	{
+		"TestIpAddress #1.",
+		"http://1.2.3.4/foo",
+		[]string{"a=1; path=/"},
+		"a=1",
+		[]query{{"http://1.2.3.4/foo", "a=1"}},
+	},
+	{
+		"TestIpAddress #2.",
+		"http://1.2.3.4/foo",
+		[]string{
+			"a=1; domain=.1.2.3.4",
+			"b=2; domain=.3.4"},
+		"",
+		[]query{{"http://1.2.3.4/foo", ""}},
+	},
+	{
+		"TestIpAddress #3.",
+		"http://1.2.3.4/foo",
+		[]string{"a=1; domain=1.2.3.4"},
+		"",
+		[]query{{"http://1.2.3.4/foo", ""}},
+	},
+	{
+		"TestNonDottedAndTLD #2.",
+		"http://com./index.html",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://com./index.html", "a=1"},
+			{"http://no-cookies.com./index.html", ""},
+		},
+	},
+	{
+		"TestNonDottedAndTLD #3.",
+		"http://a.b",
+		[]string{
+			"a=1; domain=.b",
+			"b=2; domain=b"},
+		"",
+		[]query{{"http://bar.foo", ""}},
+	},
+	{
+		"TestNonDottedAndTLD #4.",
+		"http://google.com",
+		[]string{
+			"a=1; domain=.com",
+			"b=2; domain=com"},
+		"",
+		[]query{{"http://google.com", ""}},
+	},
+	{
+		"TestNonDottedAndTLD #5.",
+		"http://google.co.uk",
+		[]string{
+			"a=1; domain=.co.uk",
+			"b=2; domain=.uk"},
+		"",
+		[]query{
+			{"http://google.co.uk", ""},
+			{"http://else.co.com", ""},
+			{"http://else.uk", ""},
+		},
+	},
+	{
+		"TestHostEndsWithDot.",
+		"http://www.google.com",
+		[]string{
+			"a=1",
+			"b=2; domain=.www.google.com."},
+		"a=1",
+		[]query{{"http://www.google.com", "a=1"}},
+	},
+	{
+		"PathTest",
+		"http://www.google.izzle",
+		[]string{"a=1; path=/wee"},
+		"a=1",
+		[]query{
+			{"http://www.google.izzle/wee", "a=1"},
+			{"http://www.google.izzle/wee/", "a=1"},
+			{"http://www.google.izzle/wee/war", "a=1"},
+			{"http://www.google.izzle/wee/war/more/more", "a=1"},
+			{"http://www.google.izzle/weehee", ""},
+			{"http://www.google.izzle/", ""},
+		},
+	},
+}
+
+func TestChromiumBasics(t *testing.T) {
+	for _, test := range chromiumBasicsTests {
+		jar := newTestJar()
+		test.run(t, jar)
+	}
+}
+
+// chromiumDomainTests contains jarTests which must be executed all on the
+// same Jar.
+var chromiumDomainTests = [...]jarTest{
+	{
+		"Fill #1.",
+		"http://www.google.izzle",
+		[]string{"A=B"},
+		"A=B",
+		[]query{{"http://www.google.izzle", "A=B"}},
+	},
+	{
+		"Fill #2.",
+		"http://www.google.izzle",
+		[]string{"C=D; domain=.google.izzle"},
+		"A=B C=D",
+		[]query{{"http://www.google.izzle", "A=B C=D"}},
+	},
+	{
+		"Verify A is a host cookie and not accessible from subdomain.",
+		"http://unused.nil",
+		[]string{},
+		"A=B C=D",
+		[]query{{"http://foo.www.google.izzle", "C=D"}},
+	},
+	{
+		"Verify domain cookies are found on proper domain.",
+		"http://www.google.izzle",
+		[]string{"E=F; domain=.www.google.izzle"},
+		"A=B C=D E=F",
+		[]query{{"http://www.google.izzle", "A=B C=D E=F"}},
+	},
+	{
+		"Leading dots in domain attributes are optional.",
+		"http://www.google.izzle",
+		[]string{"G=H; domain=www.google.izzle"},
+		"A=B C=D E=F G=H",
+		[]query{{"http://www.google.izzle", "A=B C=D E=F G=H"}},
+	},
+	{
+		"Verify domain enforcement works #1.",
+		"http://www.google.izzle",
+		[]string{"K=L; domain=.bar.www.google.izzle"},
+		"A=B C=D E=F G=H",
+		[]query{{"http://bar.www.google.izzle", "C=D E=F G=H"}},
+	},
+	{
+		"Verify domain enforcement works #2.",
+		"http://unused.nil",
+		[]string{},
+		"A=B C=D E=F G=H",
+		[]query{{"http://www.google.izzle", "A=B C=D E=F G=H"}},
+	},
+}
+
+func TestChromiumDomain(t *testing.T) {
+	jar := newTestJar()
+	for _, test := range chromiumDomainTests {
+		test.run(t, jar)
+	}
+
+}
+
+// chromiumDeletionTests must be performed all on the same Jar.
+var chromiumDeletionTests = [...]jarTest{
+	{
+		"Create session cookie a1.",
+		"http://www.google.com",
+		[]string{"a=1"},
+		"a=1",
+		[]query{{"http://www.google.com", "a=1"}},
+	},
+	{
+		"Delete sc a1 via MaxAge.",
+		"http://www.google.com",
+		[]string{"a=1; max-age=-1"},
+		"",
+		[]query{{"http://www.google.com", ""}},
+	},
+	{
+		"Create session cookie b2.",
+		"http://www.google.com",
+		[]string{"b=2"},
+		"b=2",
+		[]query{{"http://www.google.com", "b=2"}},
+	},
+	{
+		"Delete sc b2 via Expires.",
+		"http://www.google.com",
+		[]string{"b=2; " + expiresIn(-10)},
+		"",
+		[]query{{"http://www.google.com", ""}},
+	},
+	{
+		"Create persistent cookie c3.",
+		"http://www.google.com",
+		[]string{"c=3; max-age=3600"},
+		"c=3",
+		[]query{{"http://www.google.com", "c=3"}},
+	},
+	{
+		"Delete pc c3 via MaxAge.",
+		"http://www.google.com",
+		[]string{"c=3; max-age=-1"},
+		"",
+		[]query{{"http://www.google.com", ""}},
+	},
+	{
+		"Create persistent cookie d4.",
+		"http://www.google.com",
+		[]string{"d=4; max-age=3600"},
+		"d=4",
+		[]query{{"http://www.google.com", "d=4"}},
+	},
+	{
+		"Delete pc d4 via Expires.",
+		"http://www.google.com",
+		[]string{"d=4; " + expiresIn(-10)},
+		"",
+		[]query{{"http://www.google.com", ""}},
+	},
+}
+
+func TestChromiumDeletion(t *testing.T) {
+	jar := newTestJar()
+	for _, test := range chromiumDeletionTests {
+		test.run(t, jar)
+	}
+}
+
+// domainHandlingTests tests and documents the rules for domain handling.
+// Each test must be performed on an empty new Jar.
+var domainHandlingTests = [...]jarTest{
+	{
+		"Host cookie",
+		"http://www.host.test",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://www.host.test", "a=1"},
+			{"http://host.test", ""},
+			{"http://bar.host.test", ""},
+			{"http://foo.www.host.test", ""},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Domain cookie #1",
+		"http://www.host.test",
+		[]string{"a=1; domain=host.test"},
+		"a=1",
+		[]query{
+			{"http://www.host.test", "a=1"},
+			{"http://host.test", "a=1"},
+			{"http://bar.host.test", "a=1"},
+			{"http://foo.www.host.test", "a=1"},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Domain cookie #2",
+		"http://www.host.test",
+		[]string{"a=1; domain=.host.test"},
+		"a=1",
+		[]query{
+			{"http://www.host.test", "a=1"},
+			{"http://host.test", "a=1"},
+			{"http://bar.host.test", "a=1"},
+			{"http://foo.www.host.test", "a=1"},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Host cookie on IDNA domain #1",
+		"http://www.bücher.test",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://www.bücher.test", "a=1"},
+			{"http://www.xn--bcher-kva.test", "a=1"},
+			{"http://bücher.test", ""},
+			{"http://xn--bcher-kva.test", ""},
+			{"http://bar.bücher.test", ""},
+			{"http://bar.xn--bcher-kva.test", ""},
+			{"http://foo.www.bücher.test", ""},
+			{"http://foo.www.xn--bcher-kva.test", ""},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Host cookie on IDNA domain #2",
+		"http://www.xn--bcher-kva.test",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://www.bücher.test", "a=1"},
+			{"http://www.xn--bcher-kva.test", "a=1"},
+			{"http://bücher.test", ""},
+			{"http://xn--bcher-kva.test", ""},
+			{"http://bar.bücher.test", ""},
+			{"http://bar.xn--bcher-kva.test", ""},
+			{"http://foo.www.bücher.test", ""},
+			{"http://foo.www.xn--bcher-kva.test", ""},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Domain cookie on IDNA domain #1",
+		"http://www.bücher.test",
+		[]string{"a=1; domain=xn--bcher-kva.test"},
+		"a=1",
+		[]query{
+			{"http://www.bücher.test", "a=1"},
+			{"http://www.xn--bcher-kva.test", "a=1"},
+			{"http://bücher.test", "a=1"},
+			{"http://xn--bcher-kva.test", "a=1"},
+			{"http://bar.bücher.test", "a=1"},
+			{"http://bar.xn--bcher-kva.test", "a=1"},
+			{"http://foo.www.bücher.test", "a=1"},
+			{"http://foo.www.xn--bcher-kva.test", "a=1"},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Domain cookie on IDNA domain #2",
+		"http://www.xn--bcher-kva.test",
+		[]string{"a=1; domain=xn--bcher-kva.test"},
+		"a=1",
+		[]query{
+			{"http://www.bücher.test", "a=1"},
+			{"http://www.xn--bcher-kva.test", "a=1"},
+			{"http://bücher.test", "a=1"},
+			{"http://xn--bcher-kva.test", "a=1"},
+			{"http://bar.bücher.test", "a=1"},
+			{"http://bar.xn--bcher-kva.test", "a=1"},
+			{"http://foo.www.bücher.test", "a=1"},
+			{"http://foo.www.xn--bcher-kva.test", "a=1"},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Host cookie on TLD.",
+		"http://com",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://com", "a=1"},
+			{"http://any.com", ""},
+			{"http://any.test", ""},
+		},
+	},
+	{
+		"Domain cookie on TLD becomes a host cookie.",
+		"http://com",
+		[]string{"a=1; domain=com"},
+		"a=1",
+		[]query{
+			{"http://com", "a=1"},
+			{"http://any.com", ""},
+			{"http://any.test", ""},
+		},
+	},
+	{
+		"Host cookie on public suffix.",
+		"http://co.uk",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://co.uk", "a=1"},
+			{"http://uk", ""},
+			{"http://some.co.uk", ""},
+			{"http://foo.some.co.uk", ""},
+			{"http://any.uk", ""},
+		},
+	},
+	{
+		"Domain cookie on public suffix is ignored.",
+		"http://some.co.uk",
+		[]string{"a=1; domain=co.uk"},
+		"",
+		[]query{
+			{"http://co.uk", ""},
+			{"http://uk", ""},
+			{"http://some.co.uk", ""},
+			{"http://foo.some.co.uk", ""},
+			{"http://any.uk", ""},
+		},
+	},
+}
+
+func TestDomainHandling(t *testing.T) {
+	for _, test := range domainHandlingTests {
+		jar := newTestJar()
+		test.run(t, jar)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cookiejar/punycode.go b/third_party/gofrontend/libgo/go/net/http/cookiejar/punycode.go
new file mode 100644
index 0000000..ea7ceb5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cookiejar/punycode.go
@@ -0,0 +1,159 @@
+// 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 cookiejar
+
+// This file implements the Punycode algorithm from RFC 3492.
+
+import (
+	"fmt"
+	"strings"
+	"unicode/utf8"
+)
+
+// These parameter values are specified in section 5.
+//
+// All computation is done with int32s, so that overflow behavior is identical
+// regardless of whether int is 32-bit or 64-bit.
+const (
+	base        int32 = 36
+	damp        int32 = 700
+	initialBias int32 = 72
+	initialN    int32 = 128
+	skew        int32 = 38
+	tmax        int32 = 26
+	tmin        int32 = 1
+)
+
+// encode encodes a string as specified in section 6.3 and prepends prefix to
+// the result.
+//
+// The "while h < length(input)" line in the specification becomes "for
+// remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes.
+func encode(prefix, s string) (string, error) {
+	output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
+	copy(output, prefix)
+	delta, n, bias := int32(0), initialN, initialBias
+	b, remaining := int32(0), int32(0)
+	for _, r := range s {
+		if r < 0x80 {
+			b++
+			output = append(output, byte(r))
+		} else {
+			remaining++
+		}
+	}
+	h := b
+	if b > 0 {
+		output = append(output, '-')
+	}
+	for remaining != 0 {
+		m := int32(0x7fffffff)
+		for _, r := range s {
+			if m > r && r >= n {
+				m = r
+			}
+		}
+		delta += (m - n) * (h + 1)
+		if delta < 0 {
+			return "", fmt.Errorf("cookiejar: invalid label %q", s)
+		}
+		n = m
+		for _, r := range s {
+			if r < n {
+				delta++
+				if delta < 0 {
+					return "", fmt.Errorf("cookiejar: invalid label %q", s)
+				}
+				continue
+			}
+			if r > n {
+				continue
+			}
+			q := delta
+			for k := base; ; k += base {
+				t := k - bias
+				if t < tmin {
+					t = tmin
+				} else if t > tmax {
+					t = tmax
+				}
+				if q < t {
+					break
+				}
+				output = append(output, encodeDigit(t+(q-t)%(base-t)))
+				q = (q - t) / (base - t)
+			}
+			output = append(output, encodeDigit(q))
+			bias = adapt(delta, h+1, h == b)
+			delta = 0
+			h++
+			remaining--
+		}
+		delta++
+		n++
+	}
+	return string(output), nil
+}
+
+func encodeDigit(digit int32) byte {
+	switch {
+	case 0 <= digit && digit < 26:
+		return byte(digit + 'a')
+	case 26 <= digit && digit < 36:
+		return byte(digit + ('0' - 26))
+	}
+	panic("cookiejar: internal error in punycode encoding")
+}
+
+// adapt is the bias adaptation function specified in section 6.1.
+func adapt(delta, numPoints int32, firstTime bool) int32 {
+	if firstTime {
+		delta /= damp
+	} else {
+		delta /= 2
+	}
+	delta += delta / numPoints
+	k := int32(0)
+	for delta > ((base-tmin)*tmax)/2 {
+		delta /= base - tmin
+		k += base
+	}
+	return k + (base-tmin+1)*delta/(delta+skew)
+}
+
+// Strictly speaking, the remaining code below deals with IDNA (RFC 5890 and
+// friends) and not Punycode (RFC 3492) per se.
+
+// acePrefix is the ASCII Compatible Encoding prefix.
+const acePrefix = "xn--"
+
+// toASCII converts a domain or domain label to its ASCII form. For example,
+// toASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
+// toASCII("golang") is "golang".
+func toASCII(s string) (string, error) {
+	if ascii(s) {
+		return s, nil
+	}
+	labels := strings.Split(s, ".")
+	for i, label := range labels {
+		if !ascii(label) {
+			a, err := encode(acePrefix, label)
+			if err != nil {
+				return "", err
+			}
+			labels[i] = a
+		}
+	}
+	return strings.Join(labels, "."), nil
+}
+
+func ascii(s string) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] >= utf8.RuneSelf {
+			return false
+		}
+	}
+	return true
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/cookiejar/punycode_test.go b/third_party/gofrontend/libgo/go/net/http/cookiejar/punycode_test.go
new file mode 100644
index 0000000..0301de1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/cookiejar/punycode_test.go
@@ -0,0 +1,161 @@
+// 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 cookiejar
+
+import (
+	"testing"
+)
+
+var punycodeTestCases = [...]struct {
+	s, encoded string
+}{
+	{"", ""},
+	{"-", "--"},
+	{"-a", "-a-"},
+	{"-a-", "-a--"},
+	{"a", "a-"},
+	{"a-", "a--"},
+	{"a-b", "a-b-"},
+	{"books", "books-"},
+	{"bücher", "bcher-kva"},
+	{"Hello世界", "Hello-ck1hg65u"},
+	{"ü", "tda"},
+	{"üý", "tdac"},
+
+	// The test cases below come from RFC 3492 section 7.1 with Errata 3026.
+	{
+		// (A) Arabic (Egyptian).
+		"\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" +
+			"\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F",
+		"egbpdaj6bu4bxfgehfvwxn",
+	},
+	{
+		// (B) Chinese (simplified).
+		"\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587",
+		"ihqwcrb4cv8a8dqg056pqjye",
+	},
+	{
+		// (C) Chinese (traditional).
+		"\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587",
+		"ihqwctvzc91f659drss3x8bo0yb",
+	},
+	{
+		// (D) Czech.
+		"\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" +
+			"\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" +
+			"\u0065\u0073\u006B\u0079",
+		"Proprostnemluvesky-uyb24dma41a",
+	},
+	{
+		// (E) Hebrew.
+		"\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" +
+			"\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" +
+			"\u05D1\u05E8\u05D9\u05EA",
+		"4dbcagdahymbxekheh6e0a7fei0b",
+	},
+	{
+		// (F) Hindi (Devanagari).
+		"\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" +
+			"\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" +
+			"\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" +
+			"\u0939\u0948\u0902",
+		"i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd",
+	},
+	{
+		// (G) Japanese (kanji and hiragana).
+		"\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" +
+			"\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B",
+		"n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa",
+	},
+	{
+		// (H) Korean (Hangul syllables).
+		"\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" +
+			"\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" +
+			"\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C",
+		"989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5j" +
+			"psd879ccm6fea98c",
+	},
+	{
+		// (I) Russian (Cyrillic).
+		"\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" +
+			"\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" +
+			"\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" +
+			"\u0438",
+		"b1abfaaepdrnnbgefbadotcwatmq2g4l",
+	},
+	{
+		// (J) Spanish.
+		"\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" +
+			"\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" +
+			"\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" +
+			"\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" +
+			"\u0061\u00F1\u006F\u006C",
+		"PorqunopuedensimplementehablarenEspaol-fmd56a",
+	},
+	{
+		// (K) Vietnamese.
+		"\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" +
+			"\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" +
+			"\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" +
+			"\u0056\u0069\u1EC7\u0074",
+		"TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g",
+	},
+	{
+		// (L) 3<nen>B<gumi><kinpachi><sensei>.
+		"\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F",
+		"3B-ww4c5e180e575a65lsy2b",
+	},
+	{
+		// (M) <amuro><namie>-with-SUPER-MONKEYS.
+		"\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" +
+			"\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" +
+			"\u004F\u004E\u004B\u0045\u0059\u0053",
+		"-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n",
+	},
+	{
+		// (N) Hello-Another-Way-<sorezore><no><basho>.
+		"\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" +
+			"\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" +
+			"\u305D\u308C\u305E\u308C\u306E\u5834\u6240",
+		"Hello-Another-Way--fc4qua05auwb3674vfr0b",
+	},
+	{
+		// (O) <hitotsu><yane><no><shita>2.
+		"\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032",
+		"2-u9tlzr9756bt3uc0v",
+	},
+	{
+		// (P) Maji<de>Koi<suru>5<byou><mae>
+		"\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" +
+			"\u308B\u0035\u79D2\u524D",
+		"MajiKoi5-783gue6qz075azm5e",
+	},
+	{
+		// (Q) <pafii>de<runba>
+		"\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0",
+		"de-jg4avhby1noc0d",
+	},
+	{
+		// (R) <sono><supiido><de>
+		"\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067",
+		"d9juau41awczczp",
+	},
+	{
+		// (S) -> $1.00 <-
+		"\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" +
+			"\u003C\u002D",
+		"-> $1.00 <--",
+	},
+}
+
+func TestPunycode(t *testing.T) {
+	for _, tc := range punycodeTestCases {
+		if got, err := encode("", tc.s); err != nil {
+			t.Errorf(`encode("", %q): %v`, tc.s, err)
+		} else if got != tc.encoded {
+			t.Errorf(`encode("", %q): got %q, want %q`, tc.s, got, tc.encoded)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/doc.go b/third_party/gofrontend/libgo/go/net/http/doc.go
new file mode 100644
index 0000000..b1216e8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/doc.go
@@ -0,0 +1,80 @@
+// 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.
+
+/*
+Package http provides HTTP client and server implementations.
+
+Get, Head, Post, and PostForm make HTTP (or HTTPS) requests:
+
+	resp, err := http.Get("http://example.com/")
+	...
+	resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf)
+	...
+	resp, err := http.PostForm("http://example.com/form",
+		url.Values{"key": {"Value"}, "id": {"123"}})
+
+The client must close the response body when finished with it:
+
+	resp, err := http.Get("http://example.com/")
+	if err != nil {
+		// handle error
+	}
+	defer resp.Body.Close()
+	body, err := ioutil.ReadAll(resp.Body)
+	// ...
+
+For control over HTTP client headers, redirect policy, and other
+settings, create a Client:
+
+	client := &http.Client{
+		CheckRedirect: redirectPolicyFunc,
+	}
+
+	resp, err := client.Get("http://example.com")
+	// ...
+
+	req, err := http.NewRequest("GET", "http://example.com", nil)
+	// ...
+	req.Header.Add("If-None-Match", `W/"wyzzy"`)
+	resp, err := client.Do(req)
+	// ...
+
+For control over proxies, TLS configuration, keep-alives,
+compression, and other settings, create a Transport:
+
+	tr := &http.Transport{
+		TLSClientConfig:    &tls.Config{RootCAs: pool},
+		DisableCompression: true,
+	}
+	client := &http.Client{Transport: tr}
+	resp, err := client.Get("https://example.com")
+
+Clients and Transports are safe for concurrent use by multiple
+goroutines and for efficiency should only be created once and re-used.
+
+ListenAndServe starts an HTTP server with a given address and handler.
+The handler is usually nil, which means to use DefaultServeMux.
+Handle and HandleFunc add handlers to DefaultServeMux:
+
+	http.Handle("/foo", fooHandler)
+
+	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
+		fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
+	})
+
+	log.Fatal(http.ListenAndServe(":8080", nil))
+
+More control over the server's behavior is available by creating a
+custom Server:
+
+	s := &http.Server{
+		Addr:           ":8080",
+		Handler:        myHandler,
+		ReadTimeout:    10 * time.Second,
+		WriteTimeout:   10 * time.Second,
+		MaxHeaderBytes: 1 << 20,
+	}
+	log.Fatal(s.ListenAndServe())
+*/
+package http
diff --git a/third_party/gofrontend/libgo/go/net/http/example_test.go b/third_party/gofrontend/libgo/go/net/http/example_test.go
new file mode 100644
index 0000000..88b97d9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/example_test.go
@@ -0,0 +1,88 @@
+// 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 http_test
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"net/http"
+)
+
+func ExampleHijacker() {
+	http.HandleFunc("/hijack", func(w http.ResponseWriter, r *http.Request) {
+		hj, ok := w.(http.Hijacker)
+		if !ok {
+			http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
+			return
+		}
+		conn, bufrw, err := hj.Hijack()
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+		// Don't forget to close the connection:
+		defer conn.Close()
+		bufrw.WriteString("Now we're speaking raw TCP. Say hi: ")
+		bufrw.Flush()
+		s, err := bufrw.ReadString('\n')
+		if err != nil {
+			log.Printf("error reading string: %v", err)
+			return
+		}
+		fmt.Fprintf(bufrw, "You said: %q\nBye.\n", s)
+		bufrw.Flush()
+	})
+}
+
+func ExampleGet() {
+	res, err := http.Get("http://www.google.com/robots.txt")
+	if err != nil {
+		log.Fatal(err)
+	}
+	robots, err := ioutil.ReadAll(res.Body)
+	res.Body.Close()
+	if err != nil {
+		log.Fatal(err)
+	}
+	fmt.Printf("%s", robots)
+}
+
+func ExampleFileServer() {
+	// Simple static webserver:
+	log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("/usr/share/doc"))))
+}
+
+func ExampleFileServer_stripPrefix() {
+	// To serve a directory on disk (/tmp) under an alternate URL
+	// path (/tmpfiles/), use StripPrefix to modify the request
+	// URL's path before the FileServer sees it:
+	http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
+}
+
+func ExampleStripPrefix() {
+	// To serve a directory on disk (/tmp) under an alternate URL
+	// path (/tmpfiles/), use StripPrefix to modify the request
+	// URL's path before the FileServer sees it:
+	http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
+}
+
+type apiHandler struct{}
+
+func (apiHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}
+
+func ExampleServeMux_Handle() {
+	mux := http.NewServeMux()
+	mux.Handle("/api/", apiHandler{})
+	mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
+		// The "/" pattern matches everything, so we need to check
+		// that we're at the root here.
+		if req.URL.Path != "/" {
+			http.NotFound(w, req)
+			return
+		}
+		fmt.Fprintf(w, "Welcome to the home page!")
+	})
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/export_test.go b/third_party/gofrontend/libgo/go/net/http/export_test.go
new file mode 100644
index 0000000..960563b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/export_test.go
@@ -0,0 +1,72 @@
+// 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.
+
+// Bridge package to expose http internals to tests in the http_test
+// package.
+
+package http
+
+import (
+	"net"
+	"time"
+)
+
+func NewLoggingConn(baseName string, c net.Conn) net.Conn {
+	return newLoggingConn(baseName, c)
+}
+
+var ExportAppendTime = appendTime
+
+func (t *Transport) NumPendingRequestsForTesting() int {
+	t.reqMu.Lock()
+	defer t.reqMu.Unlock()
+	return len(t.reqCanceler)
+}
+
+func (t *Transport) IdleConnKeysForTesting() (keys []string) {
+	keys = make([]string, 0)
+	t.idleMu.Lock()
+	defer t.idleMu.Unlock()
+	if t.idleConn == nil {
+		return
+	}
+	for key := range t.idleConn {
+		keys = append(keys, key.String())
+	}
+	return
+}
+
+func (t *Transport) IdleConnCountForTesting(cacheKey string) int {
+	t.idleMu.Lock()
+	defer t.idleMu.Unlock()
+	if t.idleConn == nil {
+		return 0
+	}
+	for k, conns := range t.idleConn {
+		if k.String() == cacheKey {
+			return len(conns)
+		}
+	}
+	return 0
+}
+
+func (t *Transport) IdleConnChMapSizeForTesting() int {
+	t.idleMu.Lock()
+	defer t.idleMu.Unlock()
+	return len(t.idleConnCh)
+}
+
+func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
+	f := func() <-chan time.Time {
+		return ch
+	}
+	return &timeoutHandler{handler, f, ""}
+}
+
+func ResetCachedEnvironment() {
+	httpProxyEnv.reset()
+	noProxyEnv.reset()
+}
+
+var DefaultUserAgent = defaultUserAgent
diff --git a/third_party/gofrontend/libgo/go/net/http/fcgi/child.go b/third_party/gofrontend/libgo/go/net/http/fcgi/child.go
new file mode 100644
index 0000000..a3beaa3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/fcgi/child.go
@@ -0,0 +1,305 @@
+// 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.
+
+package fcgi
+
+// This file implements FastCGI from the perspective of a child process.
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"net/http/cgi"
+	"os"
+	"strings"
+	"sync"
+	"time"
+)
+
+// request holds the state for an in-progress request. As soon as it's complete,
+// it's converted to an http.Request.
+type request struct {
+	pw        *io.PipeWriter
+	reqId     uint16
+	params    map[string]string
+	buf       [1024]byte
+	rawParams []byte
+	keepConn  bool
+}
+
+func newRequest(reqId uint16, flags uint8) *request {
+	r := &request{
+		reqId:    reqId,
+		params:   map[string]string{},
+		keepConn: flags&flagKeepConn != 0,
+	}
+	r.rawParams = r.buf[:0]
+	return r
+}
+
+// parseParams reads an encoded []byte into Params.
+func (r *request) parseParams() {
+	text := r.rawParams
+	r.rawParams = nil
+	for len(text) > 0 {
+		keyLen, n := readSize(text)
+		if n == 0 {
+			return
+		}
+		text = text[n:]
+		valLen, n := readSize(text)
+		if n == 0 {
+			return
+		}
+		text = text[n:]
+		key := readString(text, keyLen)
+		text = text[keyLen:]
+		val := readString(text, valLen)
+		text = text[valLen:]
+		r.params[key] = val
+	}
+}
+
+// response implements http.ResponseWriter.
+type response struct {
+	req         *request
+	header      http.Header
+	w           *bufWriter
+	wroteHeader bool
+}
+
+func newResponse(c *child, req *request) *response {
+	return &response{
+		req:    req,
+		header: http.Header{},
+		w:      newWriter(c.conn, typeStdout, req.reqId),
+	}
+}
+
+func (r *response) Header() http.Header {
+	return r.header
+}
+
+func (r *response) Write(data []byte) (int, error) {
+	if !r.wroteHeader {
+		r.WriteHeader(http.StatusOK)
+	}
+	return r.w.Write(data)
+}
+
+func (r *response) WriteHeader(code int) {
+	if r.wroteHeader {
+		return
+	}
+	r.wroteHeader = true
+	if code == http.StatusNotModified {
+		// Must not have body.
+		r.header.Del("Content-Type")
+		r.header.Del("Content-Length")
+		r.header.Del("Transfer-Encoding")
+	} else if r.header.Get("Content-Type") == "" {
+		r.header.Set("Content-Type", "text/html; charset=utf-8")
+	}
+
+	if r.header.Get("Date") == "" {
+		r.header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
+	}
+
+	fmt.Fprintf(r.w, "Status: %d %s\r\n", code, http.StatusText(code))
+	r.header.Write(r.w)
+	r.w.WriteString("\r\n")
+}
+
+func (r *response) Flush() {
+	if !r.wroteHeader {
+		r.WriteHeader(http.StatusOK)
+	}
+	r.w.Flush()
+}
+
+func (r *response) Close() error {
+	r.Flush()
+	return r.w.Close()
+}
+
+type child struct {
+	conn    *conn
+	handler http.Handler
+
+	mu       sync.Mutex          // protects requests:
+	requests map[uint16]*request // keyed by request ID
+}
+
+func newChild(rwc io.ReadWriteCloser, handler http.Handler) *child {
+	return &child{
+		conn:     newConn(rwc),
+		handler:  handler,
+		requests: make(map[uint16]*request),
+	}
+}
+
+func (c *child) serve() {
+	defer c.conn.Close()
+	var rec record
+	for {
+		if err := rec.read(c.conn.rwc); err != nil {
+			return
+		}
+		if err := c.handleRecord(&rec); err != nil {
+			return
+		}
+	}
+}
+
+var errCloseConn = errors.New("fcgi: connection should be closed")
+
+var emptyBody = ioutil.NopCloser(strings.NewReader(""))
+
+func (c *child) handleRecord(rec *record) error {
+	c.mu.Lock()
+	req, ok := c.requests[rec.h.Id]
+	c.mu.Unlock()
+	if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues {
+		// The spec says to ignore unknown request IDs.
+		return nil
+	}
+
+	switch rec.h.Type {
+	case typeBeginRequest:
+		if req != nil {
+			// The server is trying to begin a request with the same ID
+			// as an in-progress request. This is an error.
+			return errors.New("fcgi: received ID that is already in-flight")
+		}
+
+		var br beginRequest
+		if err := br.read(rec.content()); err != nil {
+			return err
+		}
+		if br.role != roleResponder {
+			c.conn.writeEndRequest(rec.h.Id, 0, statusUnknownRole)
+			return nil
+		}
+		req = newRequest(rec.h.Id, br.flags)
+		c.mu.Lock()
+		c.requests[rec.h.Id] = req
+		c.mu.Unlock()
+		return nil
+	case typeParams:
+		// NOTE(eds): Technically a key-value pair can straddle the boundary
+		// between two packets. We buffer until we've received all parameters.
+		if len(rec.content()) > 0 {
+			req.rawParams = append(req.rawParams, rec.content()...)
+			return nil
+		}
+		req.parseParams()
+		return nil
+	case typeStdin:
+		content := rec.content()
+		if req.pw == nil {
+			var body io.ReadCloser
+			if len(content) > 0 {
+				// body could be an io.LimitReader, but it shouldn't matter
+				// as long as both sides are behaving.
+				body, req.pw = io.Pipe()
+			} else {
+				body = emptyBody
+			}
+			go c.serveRequest(req, body)
+		}
+		if len(content) > 0 {
+			// TODO(eds): This blocks until the handler reads from the pipe.
+			// If the handler takes a long time, it might be a problem.
+			req.pw.Write(content)
+		} else if req.pw != nil {
+			req.pw.Close()
+		}
+		return nil
+	case typeGetValues:
+		values := map[string]string{"FCGI_MPXS_CONNS": "1"}
+		c.conn.writePairs(typeGetValuesResult, 0, values)
+		return nil
+	case typeData:
+		// If the filter role is implemented, read the data stream here.
+		return nil
+	case typeAbortRequest:
+		println("abort")
+		c.mu.Lock()
+		delete(c.requests, rec.h.Id)
+		c.mu.Unlock()
+		c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
+		if !req.keepConn {
+			// connection will close upon return
+			return errCloseConn
+		}
+		return nil
+	default:
+		b := make([]byte, 8)
+		b[0] = byte(rec.h.Type)
+		c.conn.writeRecord(typeUnknownType, 0, b)
+		return nil
+	}
+}
+
+func (c *child) serveRequest(req *request, body io.ReadCloser) {
+	r := newResponse(c, req)
+	httpReq, err := cgi.RequestFromMap(req.params)
+	if err != nil {
+		// there was an error reading the request
+		r.WriteHeader(http.StatusInternalServerError)
+		c.conn.writeRecord(typeStderr, req.reqId, []byte(err.Error()))
+	} else {
+		httpReq.Body = body
+		c.handler.ServeHTTP(r, httpReq)
+	}
+	r.Close()
+	c.mu.Lock()
+	delete(c.requests, req.reqId)
+	c.mu.Unlock()
+	c.conn.writeEndRequest(req.reqId, 0, statusRequestComplete)
+
+	// Consume the entire body, so the host isn't still writing to
+	// us when we close the socket below in the !keepConn case,
+	// otherwise we'd send a RST. (golang.org/issue/4183)
+	// TODO(bradfitz): also bound this copy in time. Or send
+	// some sort of abort request to the host, so the host
+	// can properly cut off the client sending all the data.
+	// For now just bound it a little and
+	io.CopyN(ioutil.Discard, body, 100<<20)
+	body.Close()
+
+	if !req.keepConn {
+		c.conn.Close()
+	}
+}
+
+// Serve accepts incoming FastCGI connections on the listener l, creating a new
+// goroutine for each. The goroutine reads requests and then calls handler
+// to reply to them.
+// If l is nil, Serve accepts connections from os.Stdin.
+// If handler is nil, http.DefaultServeMux is used.
+func Serve(l net.Listener, handler http.Handler) error {
+	if l == nil {
+		var err error
+		l, err = net.FileListener(os.Stdin)
+		if err != nil {
+			return err
+		}
+		defer l.Close()
+	}
+	if handler == nil {
+		handler = http.DefaultServeMux
+	}
+	for {
+		rw, err := l.Accept()
+		if err != nil {
+			return err
+		}
+		c := newChild(rw, handler)
+		go c.serve()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/fcgi/fcgi.go b/third_party/gofrontend/libgo/go/net/http/fcgi/fcgi.go
new file mode 100644
index 0000000..06bba04
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/fcgi/fcgi.go
@@ -0,0 +1,274 @@
+// 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.
+
+// Package fcgi implements the FastCGI protocol.
+// Currently only the responder role is supported.
+// The protocol is defined at http://www.fastcgi.com/drupal/node/6?q=node/22
+package fcgi
+
+// This file defines the raw protocol and some utilities used by the child and
+// the host.
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"io"
+	"sync"
+)
+
+// recType is a record type, as defined by
+// http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S8
+type recType uint8
+
+const (
+	typeBeginRequest    recType = 1
+	typeAbortRequest    recType = 2
+	typeEndRequest      recType = 3
+	typeParams          recType = 4
+	typeStdin           recType = 5
+	typeStdout          recType = 6
+	typeStderr          recType = 7
+	typeData            recType = 8
+	typeGetValues       recType = 9
+	typeGetValuesResult recType = 10
+	typeUnknownType     recType = 11
+)
+
+// keep the connection between web-server and responder open after request
+const flagKeepConn = 1
+
+const (
+	maxWrite = 65535 // maximum record body
+	maxPad   = 255
+)
+
+const (
+	roleResponder = iota + 1 // only Responders are implemented.
+	roleAuthorizer
+	roleFilter
+)
+
+const (
+	statusRequestComplete = iota
+	statusCantMultiplex
+	statusOverloaded
+	statusUnknownRole
+)
+
+const headerLen = 8
+
+type header struct {
+	Version       uint8
+	Type          recType
+	Id            uint16
+	ContentLength uint16
+	PaddingLength uint8
+	Reserved      uint8
+}
+
+type beginRequest struct {
+	role     uint16
+	flags    uint8
+	reserved [5]uint8
+}
+
+func (br *beginRequest) read(content []byte) error {
+	if len(content) != 8 {
+		return errors.New("fcgi: invalid begin request record")
+	}
+	br.role = binary.BigEndian.Uint16(content)
+	br.flags = content[2]
+	return nil
+}
+
+// for padding so we don't have to allocate all the time
+// not synchronized because we don't care what the contents are
+var pad [maxPad]byte
+
+func (h *header) init(recType recType, reqId uint16, contentLength int) {
+	h.Version = 1
+	h.Type = recType
+	h.Id = reqId
+	h.ContentLength = uint16(contentLength)
+	h.PaddingLength = uint8(-contentLength & 7)
+}
+
+// conn sends records over rwc
+type conn struct {
+	mutex sync.Mutex
+	rwc   io.ReadWriteCloser
+
+	// to avoid allocations
+	buf bytes.Buffer
+	h   header
+}
+
+func newConn(rwc io.ReadWriteCloser) *conn {
+	return &conn{rwc: rwc}
+}
+
+func (c *conn) Close() error {
+	c.mutex.Lock()
+	defer c.mutex.Unlock()
+	return c.rwc.Close()
+}
+
+type record struct {
+	h   header
+	buf [maxWrite + maxPad]byte
+}
+
+func (rec *record) read(r io.Reader) (err error) {
+	if err = binary.Read(r, binary.BigEndian, &rec.h); err != nil {
+		return err
+	}
+	if rec.h.Version != 1 {
+		return errors.New("fcgi: invalid header version")
+	}
+	n := int(rec.h.ContentLength) + int(rec.h.PaddingLength)
+	if _, err = io.ReadFull(r, rec.buf[:n]); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *record) content() []byte {
+	return r.buf[:r.h.ContentLength]
+}
+
+// writeRecord writes and sends a single record.
+func (c *conn) writeRecord(recType recType, reqId uint16, b []byte) error {
+	c.mutex.Lock()
+	defer c.mutex.Unlock()
+	c.buf.Reset()
+	c.h.init(recType, reqId, len(b))
+	if err := binary.Write(&c.buf, binary.BigEndian, c.h); err != nil {
+		return err
+	}
+	if _, err := c.buf.Write(b); err != nil {
+		return err
+	}
+	if _, err := c.buf.Write(pad[:c.h.PaddingLength]); err != nil {
+		return err
+	}
+	_, err := c.rwc.Write(c.buf.Bytes())
+	return err
+}
+
+func (c *conn) writeBeginRequest(reqId uint16, role uint16, flags uint8) error {
+	b := [8]byte{byte(role >> 8), byte(role), flags}
+	return c.writeRecord(typeBeginRequest, reqId, b[:])
+}
+
+func (c *conn) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) error {
+	b := make([]byte, 8)
+	binary.BigEndian.PutUint32(b, uint32(appStatus))
+	b[4] = protocolStatus
+	return c.writeRecord(typeEndRequest, reqId, b)
+}
+
+func (c *conn) writePairs(recType recType, reqId uint16, pairs map[string]string) error {
+	w := newWriter(c, recType, reqId)
+	b := make([]byte, 8)
+	for k, v := range pairs {
+		n := encodeSize(b, uint32(len(k)))
+		n += encodeSize(b[n:], uint32(len(v)))
+		if _, err := w.Write(b[:n]); err != nil {
+			return err
+		}
+		if _, err := w.WriteString(k); err != nil {
+			return err
+		}
+		if _, err := w.WriteString(v); err != nil {
+			return err
+		}
+	}
+	w.Close()
+	return nil
+}
+
+func readSize(s []byte) (uint32, int) {
+	if len(s) == 0 {
+		return 0, 0
+	}
+	size, n := uint32(s[0]), 1
+	if size&(1<<7) != 0 {
+		if len(s) < 4 {
+			return 0, 0
+		}
+		n = 4
+		size = binary.BigEndian.Uint32(s)
+		size &^= 1 << 31
+	}
+	return size, n
+}
+
+func readString(s []byte, size uint32) string {
+	if size > uint32(len(s)) {
+		return ""
+	}
+	return string(s[:size])
+}
+
+func encodeSize(b []byte, size uint32) int {
+	if size > 127 {
+		size |= 1 << 31
+		binary.BigEndian.PutUint32(b, size)
+		return 4
+	}
+	b[0] = byte(size)
+	return 1
+}
+
+// bufWriter encapsulates bufio.Writer but also closes the underlying stream when
+// Closed.
+type bufWriter struct {
+	closer io.Closer
+	*bufio.Writer
+}
+
+func (w *bufWriter) Close() error {
+	if err := w.Writer.Flush(); err != nil {
+		w.closer.Close()
+		return err
+	}
+	return w.closer.Close()
+}
+
+func newWriter(c *conn, recType recType, reqId uint16) *bufWriter {
+	s := &streamWriter{c: c, recType: recType, reqId: reqId}
+	w := bufio.NewWriterSize(s, maxWrite)
+	return &bufWriter{s, w}
+}
+
+// streamWriter abstracts out the separation of a stream into discrete records.
+// It only writes maxWrite bytes at a time.
+type streamWriter struct {
+	c       *conn
+	recType recType
+	reqId   uint16
+}
+
+func (w *streamWriter) Write(p []byte) (int, error) {
+	nn := 0
+	for len(p) > 0 {
+		n := len(p)
+		if n > maxWrite {
+			n = maxWrite
+		}
+		if err := w.c.writeRecord(w.recType, w.reqId, p[:n]); err != nil {
+			return nn, err
+		}
+		nn += n
+		p = p[n:]
+	}
+	return nn, nil
+}
+
+func (w *streamWriter) Close() error {
+	// send empty record to close the stream
+	return w.c.writeRecord(w.recType, w.reqId, nil)
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/fcgi/fcgi_test.go b/third_party/gofrontend/libgo/go/net/http/fcgi/fcgi_test.go
new file mode 100644
index 0000000..6c7e1a9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/fcgi/fcgi_test.go
@@ -0,0 +1,150 @@
+// 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.
+
+package fcgi
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"testing"
+)
+
+var sizeTests = []struct {
+	size  uint32
+	bytes []byte
+}{
+	{0, []byte{0x00}},
+	{127, []byte{0x7F}},
+	{128, []byte{0x80, 0x00, 0x00, 0x80}},
+	{1000, []byte{0x80, 0x00, 0x03, 0xE8}},
+	{33554431, []byte{0x81, 0xFF, 0xFF, 0xFF}},
+}
+
+func TestSize(t *testing.T) {
+	b := make([]byte, 4)
+	for i, test := range sizeTests {
+		n := encodeSize(b, test.size)
+		if !bytes.Equal(b[:n], test.bytes) {
+			t.Errorf("%d expected %x, encoded %x", i, test.bytes, b)
+		}
+		size, n := readSize(test.bytes)
+		if size != test.size {
+			t.Errorf("%d expected %d, read %d", i, test.size, size)
+		}
+		if len(test.bytes) != n {
+			t.Errorf("%d did not consume all the bytes", i)
+		}
+	}
+}
+
+var streamTests = []struct {
+	desc    string
+	recType recType
+	reqId   uint16
+	content []byte
+	raw     []byte
+}{
+	{"single record", typeStdout, 1, nil,
+		[]byte{1, byte(typeStdout), 0, 1, 0, 0, 0, 0},
+	},
+	// this data will have to be split into two records
+	{"two records", typeStdin, 300, make([]byte, 66000),
+		bytes.Join([][]byte{
+			// header for the first record
+			{1, byte(typeStdin), 0x01, 0x2C, 0xFF, 0xFF, 1, 0},
+			make([]byte, 65536),
+			// header for the second
+			{1, byte(typeStdin), 0x01, 0x2C, 0x01, 0xD1, 7, 0},
+			make([]byte, 472),
+			// header for the empty record
+			{1, byte(typeStdin), 0x01, 0x2C, 0, 0, 0, 0},
+		},
+			nil),
+	},
+}
+
+type nilCloser struct {
+	io.ReadWriter
+}
+
+func (c *nilCloser) Close() error { return nil }
+
+func TestStreams(t *testing.T) {
+	var rec record
+outer:
+	for _, test := range streamTests {
+		buf := bytes.NewBuffer(test.raw)
+		var content []byte
+		for buf.Len() > 0 {
+			if err := rec.read(buf); err != nil {
+				t.Errorf("%s: error reading record: %v", test.desc, err)
+				continue outer
+			}
+			content = append(content, rec.content()...)
+		}
+		if rec.h.Type != test.recType {
+			t.Errorf("%s: got type %d expected %d", test.desc, rec.h.Type, test.recType)
+			continue
+		}
+		if rec.h.Id != test.reqId {
+			t.Errorf("%s: got request ID %d expected %d", test.desc, rec.h.Id, test.reqId)
+			continue
+		}
+		if !bytes.Equal(content, test.content) {
+			t.Errorf("%s: read wrong content", test.desc)
+			continue
+		}
+		buf.Reset()
+		c := newConn(&nilCloser{buf})
+		w := newWriter(c, test.recType, test.reqId)
+		if _, err := w.Write(test.content); err != nil {
+			t.Errorf("%s: error writing record: %v", test.desc, err)
+			continue
+		}
+		if err := w.Close(); err != nil {
+			t.Errorf("%s: error closing stream: %v", test.desc, err)
+			continue
+		}
+		if !bytes.Equal(buf.Bytes(), test.raw) {
+			t.Errorf("%s: wrote wrong content", test.desc)
+		}
+	}
+}
+
+type writeOnlyConn struct {
+	buf []byte
+}
+
+func (c *writeOnlyConn) Write(p []byte) (int, error) {
+	c.buf = append(c.buf, p...)
+	return len(p), nil
+}
+
+func (c *writeOnlyConn) Read(p []byte) (int, error) {
+	return 0, errors.New("conn is write-only")
+}
+
+func (c *writeOnlyConn) Close() error {
+	return nil
+}
+
+func TestGetValues(t *testing.T) {
+	var rec record
+	rec.h.Type = typeGetValues
+
+	wc := new(writeOnlyConn)
+	c := newChild(wc, nil)
+	err := c.handleRecord(&rec)
+	if err != nil {
+		t.Fatalf("handleRecord: %v", err)
+	}
+
+	const want = "\x01\n\x00\x00\x00\x12\x06\x00" +
+		"\x0f\x01FCGI_MPXS_CONNS1" +
+		"\x00\x00\x00\x00\x00\x00\x01\n\x00\x00\x00\x00\x00\x00"
+	if got := string(wc.buf); got != want {
+		t.Errorf(" got: %q\nwant: %q\n", got, want)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/filetransport.go b/third_party/gofrontend/libgo/go/net/http/filetransport.go
new file mode 100644
index 0000000..821787e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/filetransport.go
@@ -0,0 +1,123 @@
+// 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.
+
+package http
+
+import (
+	"fmt"
+	"io"
+)
+
+// fileTransport implements RoundTripper for the 'file' protocol.
+type fileTransport struct {
+	fh fileHandler
+}
+
+// NewFileTransport returns a new RoundTripper, serving the provided
+// FileSystem. The returned RoundTripper ignores the URL host in its
+// incoming requests, as well as most other properties of the
+// request.
+//
+// The typical use case for NewFileTransport is to register the "file"
+// protocol with a Transport, as in:
+//
+//   t := &http.Transport{}
+//   t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
+//   c := &http.Client{Transport: t}
+//   res, err := c.Get("file:///etc/passwd")
+//   ...
+func NewFileTransport(fs FileSystem) RoundTripper {
+	return fileTransport{fileHandler{fs}}
+}
+
+func (t fileTransport) RoundTrip(req *Request) (resp *Response, err error) {
+	// We start ServeHTTP in a goroutine, which may take a long
+	// time if the file is large.  The newPopulateResponseWriter
+	// call returns a channel which either ServeHTTP or finish()
+	// sends our *Response on, once the *Response itself has been
+	// populated (even if the body itself is still being
+	// written to the res.Body, a pipe)
+	rw, resc := newPopulateResponseWriter()
+	go func() {
+		t.fh.ServeHTTP(rw, req)
+		rw.finish()
+	}()
+	return <-resc, nil
+}
+
+func newPopulateResponseWriter() (*populateResponse, <-chan *Response) {
+	pr, pw := io.Pipe()
+	rw := &populateResponse{
+		ch: make(chan *Response),
+		pw: pw,
+		res: &Response{
+			Proto:      "HTTP/1.0",
+			ProtoMajor: 1,
+			Header:     make(Header),
+			Close:      true,
+			Body:       pr,
+		},
+	}
+	return rw, rw.ch
+}
+
+// populateResponse is a ResponseWriter that populates the *Response
+// in res, and writes its body to a pipe connected to the response
+// body. Once writes begin or finish() is called, the response is sent
+// on ch.
+type populateResponse struct {
+	res          *Response
+	ch           chan *Response
+	wroteHeader  bool
+	hasContent   bool
+	sentResponse bool
+	pw           *io.PipeWriter
+}
+
+func (pr *populateResponse) finish() {
+	if !pr.wroteHeader {
+		pr.WriteHeader(500)
+	}
+	if !pr.sentResponse {
+		pr.sendResponse()
+	}
+	pr.pw.Close()
+}
+
+func (pr *populateResponse) sendResponse() {
+	if pr.sentResponse {
+		return
+	}
+	pr.sentResponse = true
+
+	if pr.hasContent {
+		pr.res.ContentLength = -1
+	}
+	pr.ch <- pr.res
+}
+
+func (pr *populateResponse) Header() Header {
+	return pr.res.Header
+}
+
+func (pr *populateResponse) WriteHeader(code int) {
+	if pr.wroteHeader {
+		return
+	}
+	pr.wroteHeader = true
+
+	pr.res.StatusCode = code
+	pr.res.Status = fmt.Sprintf("%d %s", code, StatusText(code))
+}
+
+func (pr *populateResponse) Write(p []byte) (n int, err error) {
+	if !pr.wroteHeader {
+		pr.WriteHeader(StatusOK)
+	}
+	pr.hasContent = true
+	if !pr.sentResponse {
+		pr.sendResponse()
+	}
+	return pr.pw.Write(p)
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/filetransport_test.go b/third_party/gofrontend/libgo/go/net/http/filetransport_test.go
new file mode 100644
index 0000000..6f1a537
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/filetransport_test.go
@@ -0,0 +1,65 @@
+// 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.
+
+package http
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"testing"
+)
+
+func checker(t *testing.T) func(string, error) {
+	return func(call string, err error) {
+		if err == nil {
+			return
+		}
+		t.Fatalf("%s: %v", call, err)
+	}
+}
+
+func TestFileTransport(t *testing.T) {
+	check := checker(t)
+
+	dname, err := ioutil.TempDir("", "")
+	check("TempDir", err)
+	fname := filepath.Join(dname, "foo.txt")
+	err = ioutil.WriteFile(fname, []byte("Bar"), 0644)
+	check("WriteFile", err)
+	defer os.Remove(dname)
+	defer os.Remove(fname)
+
+	tr := &Transport{}
+	tr.RegisterProtocol("file", NewFileTransport(Dir(dname)))
+	c := &Client{Transport: tr}
+
+	fooURLs := []string{"file:///foo.txt", "file://../foo.txt"}
+	for _, urlstr := range fooURLs {
+		res, err := c.Get(urlstr)
+		check("Get "+urlstr, err)
+		if res.StatusCode != 200 {
+			t.Errorf("for %s, StatusCode = %d, want 200", urlstr, res.StatusCode)
+		}
+		if res.ContentLength != -1 {
+			t.Errorf("for %s, ContentLength = %d, want -1", urlstr, res.ContentLength)
+		}
+		if res.Body == nil {
+			t.Fatalf("for %s, nil Body", urlstr)
+		}
+		slurp, err := ioutil.ReadAll(res.Body)
+		check("ReadAll "+urlstr, err)
+		if string(slurp) != "Bar" {
+			t.Errorf("for %s, got content %q, want %q", urlstr, string(slurp), "Bar")
+		}
+	}
+
+	const badURL = "file://../no-exist.txt"
+	res, err := c.Get(badURL)
+	check("Get "+badURL, err)
+	if res.StatusCode != 404 {
+		t.Errorf("for %s, StatusCode = %d, want 404", badURL, res.StatusCode)
+	}
+	res.Body.Close()
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/fs.go b/third_party/gofrontend/libgo/go/net/http/fs.go
new file mode 100644
index 0000000..8576cf8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/fs.go
@@ -0,0 +1,549 @@
+// 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.
+
+// HTTP file system request handler
+
+package http
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"mime"
+	"mime/multipart"
+	"net/textproto"
+	"net/url"
+	"os"
+	"path"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// A Dir implements http.FileSystem using the native file
+// system restricted to a specific directory tree.
+//
+// An empty Dir is treated as ".".
+type Dir string
+
+func (d Dir) Open(name string) (File, error) {
+	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
+		strings.Contains(name, "\x00") {
+		return nil, errors.New("http: invalid character in file path")
+	}
+	dir := string(d)
+	if dir == "" {
+		dir = "."
+	}
+	f, err := os.Open(filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))))
+	if err != nil {
+		return nil, err
+	}
+	return f, nil
+}
+
+// A FileSystem implements access to a collection of named files.
+// The elements in a file path are separated by slash ('/', U+002F)
+// characters, regardless of host operating system convention.
+type FileSystem interface {
+	Open(name string) (File, error)
+}
+
+// A File is returned by a FileSystem's Open method and can be
+// served by the FileServer implementation.
+//
+// The methods should behave the same as those on an *os.File.
+type File interface {
+	io.Closer
+	io.Reader
+	Readdir(count int) ([]os.FileInfo, error)
+	Seek(offset int64, whence int) (int64, error)
+	Stat() (os.FileInfo, error)
+}
+
+func dirList(w ResponseWriter, f File) {
+	w.Header().Set("Content-Type", "text/html; charset=utf-8")
+	fmt.Fprintf(w, "<pre>\n")
+	for {
+		dirs, err := f.Readdir(100)
+		if err != nil || len(dirs) == 0 {
+			break
+		}
+		for _, d := range dirs {
+			name := d.Name()
+			if d.IsDir() {
+				name += "/"
+			}
+			// name may contain '?' or '#', which must be escaped to remain
+			// part of the URL path, and not indicate the start of a query
+			// string or fragment.
+			url := url.URL{Path: name}
+			fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", url.String(), htmlReplacer.Replace(name))
+		}
+	}
+	fmt.Fprintf(w, "</pre>\n")
+}
+
+// ServeContent replies to the request using the content in the
+// provided ReadSeeker.  The main benefit of ServeContent over io.Copy
+// is that it handles Range requests properly, sets the MIME type, and
+// handles If-Modified-Since requests.
+//
+// If the response's Content-Type header is not set, ServeContent
+// first tries to deduce the type from name's file extension and,
+// if that fails, falls back to reading the first block of the content
+// and passing it to DetectContentType.
+// The name is otherwise unused; in particular it can be empty and is
+// never sent in the response.
+//
+// If modtime is not the zero time, ServeContent includes it in a
+// Last-Modified header in the response.  If the request includes an
+// If-Modified-Since header, ServeContent uses modtime to decide
+// whether the content needs to be sent at all.
+//
+// The content's Seek method must work: ServeContent uses
+// a seek to the end of the content to determine its size.
+//
+// If the caller has set w's ETag header, ServeContent uses it to
+// handle requests using If-Range and If-None-Match.
+//
+// Note that *os.File implements the io.ReadSeeker interface.
+func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker) {
+	sizeFunc := func() (int64, error) {
+		size, err := content.Seek(0, os.SEEK_END)
+		if err != nil {
+			return 0, errSeeker
+		}
+		_, err = content.Seek(0, os.SEEK_SET)
+		if err != nil {
+			return 0, errSeeker
+		}
+		return size, nil
+	}
+	serveContent(w, req, name, modtime, sizeFunc, content)
+}
+
+// errSeeker is returned by ServeContent's sizeFunc when the content
+// doesn't seek properly. The underlying Seeker's error text isn't
+// included in the sizeFunc reply so it's not sent over HTTP to end
+// users.
+var errSeeker = errors.New("seeker can't seek")
+
+// if name is empty, filename is unknown. (used for mime type, before sniffing)
+// if modtime.IsZero(), modtime is unknown.
+// content must be seeked to the beginning of the file.
+// The sizeFunc is called at most once. Its error, if any, is sent in the HTTP response.
+func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time, sizeFunc func() (int64, error), content io.ReadSeeker) {
+	if checkLastModified(w, r, modtime) {
+		return
+	}
+	rangeReq, done := checkETag(w, r)
+	if done {
+		return
+	}
+
+	code := StatusOK
+
+	// If Content-Type isn't set, use the file's extension to find it, but
+	// if the Content-Type is unset explicitly, do not sniff the type.
+	ctypes, haveType := w.Header()["Content-Type"]
+	var ctype string
+	if !haveType {
+		ctype = mime.TypeByExtension(filepath.Ext(name))
+		if ctype == "" {
+			// read a chunk to decide between utf-8 text and binary
+			var buf [sniffLen]byte
+			n, _ := io.ReadFull(content, buf[:])
+			ctype = DetectContentType(buf[:n])
+			_, err := content.Seek(0, os.SEEK_SET) // rewind to output whole file
+			if err != nil {
+				Error(w, "seeker can't seek", StatusInternalServerError)
+				return
+			}
+		}
+		w.Header().Set("Content-Type", ctype)
+	} else if len(ctypes) > 0 {
+		ctype = ctypes[0]
+	}
+
+	size, err := sizeFunc()
+	if err != nil {
+		Error(w, err.Error(), StatusInternalServerError)
+		return
+	}
+
+	// handle Content-Range header.
+	sendSize := size
+	var sendContent io.Reader = content
+	if size >= 0 {
+		ranges, err := parseRange(rangeReq, size)
+		if err != nil {
+			Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
+			return
+		}
+		if sumRangesSize(ranges) > size {
+			// The total number of bytes in all the ranges
+			// is larger than the size of the file by
+			// itself, so this is probably an attack, or a
+			// dumb client.  Ignore the range request.
+			ranges = nil
+		}
+		switch {
+		case len(ranges) == 1:
+			// RFC 2616, Section 14.16:
+			// "When an HTTP message includes the content of a single
+			// range (for example, a response to a request for a
+			// single range, or to a request for a set of ranges
+			// that overlap without any holes), this content is
+			// transmitted with a Content-Range header, and a
+			// Content-Length header showing the number of bytes
+			// actually transferred.
+			// ...
+			// A response to a request for a single range MUST NOT
+			// be sent using the multipart/byteranges media type."
+			ra := ranges[0]
+			if _, err := content.Seek(ra.start, os.SEEK_SET); err != nil {
+				Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
+				return
+			}
+			sendSize = ra.length
+			code = StatusPartialContent
+			w.Header().Set("Content-Range", ra.contentRange(size))
+		case len(ranges) > 1:
+			for _, ra := range ranges {
+				if ra.start > size {
+					Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
+					return
+				}
+			}
+			sendSize = rangesMIMESize(ranges, ctype, size)
+			code = StatusPartialContent
+
+			pr, pw := io.Pipe()
+			mw := multipart.NewWriter(pw)
+			w.Header().Set("Content-Type", "multipart/byteranges; boundary="+mw.Boundary())
+			sendContent = pr
+			defer pr.Close() // cause writing goroutine to fail and exit if CopyN doesn't finish.
+			go func() {
+				for _, ra := range ranges {
+					part, err := mw.CreatePart(ra.mimeHeader(ctype, size))
+					if err != nil {
+						pw.CloseWithError(err)
+						return
+					}
+					if _, err := content.Seek(ra.start, os.SEEK_SET); err != nil {
+						pw.CloseWithError(err)
+						return
+					}
+					if _, err := io.CopyN(part, content, ra.length); err != nil {
+						pw.CloseWithError(err)
+						return
+					}
+				}
+				mw.Close()
+				pw.Close()
+			}()
+		}
+
+		w.Header().Set("Accept-Ranges", "bytes")
+		if w.Header().Get("Content-Encoding") == "" {
+			w.Header().Set("Content-Length", strconv.FormatInt(sendSize, 10))
+		}
+	}
+
+	w.WriteHeader(code)
+
+	if r.Method != "HEAD" {
+		io.CopyN(w, sendContent, sendSize)
+	}
+}
+
+// modtime is the modification time of the resource to be served, or IsZero().
+// return value is whether this request is now complete.
+func checkLastModified(w ResponseWriter, r *Request, modtime time.Time) bool {
+	if modtime.IsZero() {
+		return false
+	}
+
+	// The Date-Modified header truncates sub-second precision, so
+	// use mtime < t+1s instead of mtime <= t to check for unmodified.
+	if t, err := time.Parse(TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modtime.Before(t.Add(1*time.Second)) {
+		h := w.Header()
+		delete(h, "Content-Type")
+		delete(h, "Content-Length")
+		w.WriteHeader(StatusNotModified)
+		return true
+	}
+	w.Header().Set("Last-Modified", modtime.UTC().Format(TimeFormat))
+	return false
+}
+
+// checkETag implements If-None-Match and If-Range checks.
+// The ETag must have been previously set in the ResponseWriter's headers.
+//
+// The return value is the effective request "Range" header to use and
+// whether this request is now considered done.
+func checkETag(w ResponseWriter, r *Request) (rangeReq string, done bool) {
+	etag := w.Header().get("Etag")
+	rangeReq = r.Header.get("Range")
+
+	// Invalidate the range request if the entity doesn't match the one
+	// the client was expecting.
+	// "If-Range: version" means "ignore the Range: header unless version matches the
+	// current file."
+	// We only support ETag versions.
+	// The caller must have set the ETag on the response already.
+	if ir := r.Header.get("If-Range"); ir != "" && ir != etag {
+		// TODO(bradfitz): handle If-Range requests with Last-Modified
+		// times instead of ETags? I'd rather not, at least for
+		// now. That seems like a bug/compromise in the RFC 2616, and
+		// I've never heard of anybody caring about that (yet).
+		rangeReq = ""
+	}
+
+	if inm := r.Header.get("If-None-Match"); inm != "" {
+		// Must know ETag.
+		if etag == "" {
+			return rangeReq, false
+		}
+
+		// TODO(bradfitz): non-GET/HEAD requests require more work:
+		// sending a different status code on matches, and
+		// also can't use weak cache validators (those with a "W/
+		// prefix).  But most users of ServeContent will be using
+		// it on GET or HEAD, so only support those for now.
+		if r.Method != "GET" && r.Method != "HEAD" {
+			return rangeReq, false
+		}
+
+		// TODO(bradfitz): deal with comma-separated or multiple-valued
+		// list of If-None-match values.  For now just handle the common
+		// case of a single item.
+		if inm == etag || inm == "*" {
+			h := w.Header()
+			delete(h, "Content-Type")
+			delete(h, "Content-Length")
+			w.WriteHeader(StatusNotModified)
+			return "", true
+		}
+	}
+	return rangeReq, false
+}
+
+// name is '/'-separated, not filepath.Separator.
+func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {
+	const indexPage = "/index.html"
+
+	// redirect .../index.html to .../
+	// can't use Redirect() because that would make the path absolute,
+	// which would be a problem running under StripPrefix
+	if strings.HasSuffix(r.URL.Path, indexPage) {
+		localRedirect(w, r, "./")
+		return
+	}
+
+	f, err := fs.Open(name)
+	if err != nil {
+		// TODO expose actual error?
+		NotFound(w, r)
+		return
+	}
+	defer f.Close()
+
+	d, err1 := f.Stat()
+	if err1 != nil {
+		// TODO expose actual error?
+		NotFound(w, r)
+		return
+	}
+
+	if redirect {
+		// redirect to canonical path: / at end of directory url
+		// r.URL.Path always begins with /
+		url := r.URL.Path
+		if d.IsDir() {
+			if url[len(url)-1] != '/' {
+				localRedirect(w, r, path.Base(url)+"/")
+				return
+			}
+		} else {
+			if url[len(url)-1] == '/' {
+				localRedirect(w, r, "../"+path.Base(url))
+				return
+			}
+		}
+	}
+
+	// use contents of index.html for directory, if present
+	if d.IsDir() {
+		index := name + indexPage
+		ff, err := fs.Open(index)
+		if err == nil {
+			defer ff.Close()
+			dd, err := ff.Stat()
+			if err == nil {
+				name = index
+				d = dd
+				f = ff
+			}
+		}
+	}
+
+	// Still a directory? (we didn't find an index.html file)
+	if d.IsDir() {
+		if checkLastModified(w, r, d.ModTime()) {
+			return
+		}
+		dirList(w, f)
+		return
+	}
+
+	// serverContent will check modification time
+	sizeFunc := func() (int64, error) { return d.Size(), nil }
+	serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f)
+}
+
+// localRedirect gives a Moved Permanently response.
+// It does not convert relative paths to absolute paths like Redirect does.
+func localRedirect(w ResponseWriter, r *Request, newPath string) {
+	if q := r.URL.RawQuery; q != "" {
+		newPath += "?" + q
+	}
+	w.Header().Set("Location", newPath)
+	w.WriteHeader(StatusMovedPermanently)
+}
+
+// ServeFile replies to the request with the contents of the named file or directory.
+func ServeFile(w ResponseWriter, r *Request, name string) {
+	dir, file := filepath.Split(name)
+	serveFile(w, r, Dir(dir), file, false)
+}
+
+type fileHandler struct {
+	root FileSystem
+}
+
+// FileServer returns a handler that serves HTTP requests
+// with the contents of the file system rooted at root.
+//
+// To use the operating system's file system implementation,
+// use http.Dir:
+//
+//     http.Handle("/", http.FileServer(http.Dir("/tmp")))
+func FileServer(root FileSystem) Handler {
+	return &fileHandler{root}
+}
+
+func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	upath := r.URL.Path
+	if !strings.HasPrefix(upath, "/") {
+		upath = "/" + upath
+		r.URL.Path = upath
+	}
+	serveFile(w, r, f.root, path.Clean(upath), true)
+}
+
+// httpRange specifies the byte range to be sent to the client.
+type httpRange struct {
+	start, length int64
+}
+
+func (r httpRange) contentRange(size int64) string {
+	return fmt.Sprintf("bytes %d-%d/%d", r.start, r.start+r.length-1, size)
+}
+
+func (r httpRange) mimeHeader(contentType string, size int64) textproto.MIMEHeader {
+	return textproto.MIMEHeader{
+		"Content-Range": {r.contentRange(size)},
+		"Content-Type":  {contentType},
+	}
+}
+
+// parseRange parses a Range header string as per RFC 2616.
+func parseRange(s string, size int64) ([]httpRange, error) {
+	if s == "" {
+		return nil, nil // header not present
+	}
+	const b = "bytes="
+	if !strings.HasPrefix(s, b) {
+		return nil, errors.New("invalid range")
+	}
+	var ranges []httpRange
+	for _, ra := range strings.Split(s[len(b):], ",") {
+		ra = strings.TrimSpace(ra)
+		if ra == "" {
+			continue
+		}
+		i := strings.Index(ra, "-")
+		if i < 0 {
+			return nil, errors.New("invalid range")
+		}
+		start, end := strings.TrimSpace(ra[:i]), strings.TrimSpace(ra[i+1:])
+		var r httpRange
+		if start == "" {
+			// If no start is specified, end specifies the
+			// range start relative to the end of the file.
+			i, err := strconv.ParseInt(end, 10, 64)
+			if err != nil {
+				return nil, errors.New("invalid range")
+			}
+			if i > size {
+				i = size
+			}
+			r.start = size - i
+			r.length = size - r.start
+		} else {
+			i, err := strconv.ParseInt(start, 10, 64)
+			if err != nil || i > size || i < 0 {
+				return nil, errors.New("invalid range")
+			}
+			r.start = i
+			if end == "" {
+				// If no end is specified, range extends to end of the file.
+				r.length = size - r.start
+			} else {
+				i, err := strconv.ParseInt(end, 10, 64)
+				if err != nil || r.start > i {
+					return nil, errors.New("invalid range")
+				}
+				if i >= size {
+					i = size - 1
+				}
+				r.length = i - r.start + 1
+			}
+		}
+		ranges = append(ranges, r)
+	}
+	return ranges, nil
+}
+
+// countingWriter counts how many bytes have been written to it.
+type countingWriter int64
+
+func (w *countingWriter) Write(p []byte) (n int, err error) {
+	*w += countingWriter(len(p))
+	return len(p), nil
+}
+
+// rangesMIMESize returns the number of bytes it takes to encode the
+// provided ranges as a multipart response.
+func rangesMIMESize(ranges []httpRange, contentType string, contentSize int64) (encSize int64) {
+	var w countingWriter
+	mw := multipart.NewWriter(&w)
+	for _, ra := range ranges {
+		mw.CreatePart(ra.mimeHeader(contentType, contentSize))
+		encSize += ra.length
+	}
+	mw.Close()
+	encSize += int64(w)
+	return
+}
+
+func sumRangesSize(ranges []httpRange) (size int64) {
+	for _, ra := range ranges {
+		size += ra.length
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/fs_test.go b/third_party/gofrontend/libgo/go/net/http/fs_test.go
new file mode 100644
index 0000000..c9a77c9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/fs_test.go
@@ -0,0 +1,863 @@
+// Copyright 2010 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 http_test
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"mime"
+	"mime/multipart"
+	"net"
+	. "net/http"
+	"net/http/httptest"
+	"net/url"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"reflect"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+)
+
+const (
+	testFile    = "testdata/file"
+	testFileLen = 11
+)
+
+type wantRange struct {
+	start, end int64 // range [start,end)
+}
+
+var itoa = strconv.Itoa
+
+var ServeFileRangeTests = []struct {
+	r      string
+	code   int
+	ranges []wantRange
+}{
+	{r: "", code: StatusOK},
+	{r: "bytes=0-4", code: StatusPartialContent, ranges: []wantRange{{0, 5}}},
+	{r: "bytes=2-", code: StatusPartialContent, ranges: []wantRange{{2, testFileLen}}},
+	{r: "bytes=-5", code: StatusPartialContent, ranges: []wantRange{{testFileLen - 5, testFileLen}}},
+	{r: "bytes=3-7", code: StatusPartialContent, ranges: []wantRange{{3, 8}}},
+	{r: "bytes=20-", code: StatusRequestedRangeNotSatisfiable},
+	{r: "bytes=0-0,-2", code: StatusPartialContent, ranges: []wantRange{{0, 1}, {testFileLen - 2, testFileLen}}},
+	{r: "bytes=0-1,5-8", code: StatusPartialContent, ranges: []wantRange{{0, 2}, {5, 9}}},
+	{r: "bytes=0-1,5-", code: StatusPartialContent, ranges: []wantRange{{0, 2}, {5, testFileLen}}},
+	{r: "bytes=5-1000", code: StatusPartialContent, ranges: []wantRange{{5, testFileLen}}},
+	{r: "bytes=0-,1-,2-,3-,4-", code: StatusOK}, // ignore wasteful range request
+	{r: "bytes=0-" + itoa(testFileLen-2), code: StatusPartialContent, ranges: []wantRange{{0, testFileLen - 1}}},
+	{r: "bytes=0-" + itoa(testFileLen-1), code: StatusPartialContent, ranges: []wantRange{{0, testFileLen}}},
+	{r: "bytes=0-" + itoa(testFileLen), code: StatusPartialContent, ranges: []wantRange{{0, testFileLen}}},
+}
+
+func TestServeFile(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		ServeFile(w, r, "testdata/file")
+	}))
+	defer ts.Close()
+
+	var err error
+
+	file, err := ioutil.ReadFile(testFile)
+	if err != nil {
+		t.Fatal("reading file:", err)
+	}
+
+	// set up the Request (re-used for all tests)
+	var req Request
+	req.Header = make(Header)
+	if req.URL, err = url.Parse(ts.URL); err != nil {
+		t.Fatal("ParseURL:", err)
+	}
+	req.Method = "GET"
+
+	// straight GET
+	_, body := getBody(t, "straight get", req)
+	if !bytes.Equal(body, file) {
+		t.Fatalf("body mismatch: got %q, want %q", body, file)
+	}
+
+	// Range tests
+Cases:
+	for _, rt := range ServeFileRangeTests {
+		if rt.r != "" {
+			req.Header.Set("Range", rt.r)
+		}
+		resp, body := getBody(t, fmt.Sprintf("range test %q", rt.r), req)
+		if resp.StatusCode != rt.code {
+			t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, resp.StatusCode, rt.code)
+		}
+		if rt.code == StatusRequestedRangeNotSatisfiable {
+			continue
+		}
+		wantContentRange := ""
+		if len(rt.ranges) == 1 {
+			rng := rt.ranges[0]
+			wantContentRange = fmt.Sprintf("bytes %d-%d/%d", rng.start, rng.end-1, testFileLen)
+		}
+		cr := resp.Header.Get("Content-Range")
+		if cr != wantContentRange {
+			t.Errorf("range=%q: Content-Range = %q, want %q", rt.r, cr, wantContentRange)
+		}
+		ct := resp.Header.Get("Content-Type")
+		if len(rt.ranges) == 1 {
+			rng := rt.ranges[0]
+			wantBody := file[rng.start:rng.end]
+			if !bytes.Equal(body, wantBody) {
+				t.Errorf("range=%q: body = %q, want %q", rt.r, body, wantBody)
+			}
+			if strings.HasPrefix(ct, "multipart/byteranges") {
+				t.Errorf("range=%q content-type = %q; unexpected multipart/byteranges", rt.r, ct)
+			}
+		}
+		if len(rt.ranges) > 1 {
+			typ, params, err := mime.ParseMediaType(ct)
+			if err != nil {
+				t.Errorf("range=%q content-type = %q; %v", rt.r, ct, err)
+				continue
+			}
+			if typ != "multipart/byteranges" {
+				t.Errorf("range=%q content-type = %q; want multipart/byteranges", rt.r, typ)
+				continue
+			}
+			if params["boundary"] == "" {
+				t.Errorf("range=%q content-type = %q; lacks boundary", rt.r, ct)
+				continue
+			}
+			if g, w := resp.ContentLength, int64(len(body)); g != w {
+				t.Errorf("range=%q Content-Length = %d; want %d", rt.r, g, w)
+				continue
+			}
+			mr := multipart.NewReader(bytes.NewReader(body), params["boundary"])
+			for ri, rng := range rt.ranges {
+				part, err := mr.NextPart()
+				if err != nil {
+					t.Errorf("range=%q, reading part index %d: %v", rt.r, ri, err)
+					continue Cases
+				}
+				wantContentRange = fmt.Sprintf("bytes %d-%d/%d", rng.start, rng.end-1, testFileLen)
+				if g, w := part.Header.Get("Content-Range"), wantContentRange; g != w {
+					t.Errorf("range=%q: part Content-Range = %q; want %q", rt.r, g, w)
+				}
+				body, err := ioutil.ReadAll(part)
+				if err != nil {
+					t.Errorf("range=%q, reading part index %d body: %v", rt.r, ri, err)
+					continue Cases
+				}
+				wantBody := file[rng.start:rng.end]
+				if !bytes.Equal(body, wantBody) {
+					t.Errorf("range=%q: body = %q, want %q", rt.r, body, wantBody)
+				}
+			}
+			_, err = mr.NextPart()
+			if err != io.EOF {
+				t.Errorf("range=%q; expected final error io.EOF; got %v", rt.r, err)
+			}
+		}
+	}
+}
+
+var fsRedirectTestData = []struct {
+	original, redirect string
+}{
+	{"/test/index.html", "/test/"},
+	{"/test/testdata", "/test/testdata/"},
+	{"/test/testdata/file/", "/test/testdata/file"},
+}
+
+func TestFSRedirect(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(StripPrefix("/test", FileServer(Dir("."))))
+	defer ts.Close()
+
+	for _, data := range fsRedirectTestData {
+		res, err := Get(ts.URL + data.original)
+		if err != nil {
+			t.Fatal(err)
+		}
+		res.Body.Close()
+		if g, e := res.Request.URL.Path, data.redirect; g != e {
+			t.Errorf("redirect from %s: got %s, want %s", data.original, g, e)
+		}
+	}
+}
+
+type testFileSystem struct {
+	open func(name string) (File, error)
+}
+
+func (fs *testFileSystem) Open(name string) (File, error) {
+	return fs.open(name)
+}
+
+func TestFileServerCleans(t *testing.T) {
+	defer afterTest(t)
+	ch := make(chan string, 1)
+	fs := FileServer(&testFileSystem{func(name string) (File, error) {
+		ch <- name
+		return nil, errors.New("file does not exist")
+	}})
+	tests := []struct {
+		reqPath, openArg string
+	}{
+		{"/foo.txt", "/foo.txt"},
+		{"//foo.txt", "/foo.txt"},
+		{"/../foo.txt", "/foo.txt"},
+	}
+	req, _ := NewRequest("GET", "http://example.com", nil)
+	for n, test := range tests {
+		rec := httptest.NewRecorder()
+		req.URL.Path = test.reqPath
+		fs.ServeHTTP(rec, req)
+		if got := <-ch; got != test.openArg {
+			t.Errorf("test %d: got %q, want %q", n, got, test.openArg)
+		}
+	}
+}
+
+func TestFileServerEscapesNames(t *testing.T) {
+	defer afterTest(t)
+	const dirListPrefix = "<pre>\n"
+	const dirListSuffix = "\n</pre>\n"
+	tests := []struct {
+		name, escaped string
+	}{
+		{`simple_name`, `<a href="simple_name">simple_name</a>`},
+		{`"'<>&`, `<a href="%22%27%3C%3E&">&#34;&#39;&lt;&gt;&amp;</a>`},
+		{`?foo=bar#baz`, `<a href="%3Ffoo=bar%23baz">?foo=bar#baz</a>`},
+		{`<combo>?foo`, `<a href="%3Ccombo%3E%3Ffoo">&lt;combo&gt;?foo</a>`},
+	}
+
+	// We put each test file in its own directory in the fakeFS so we can look at it in isolation.
+	fs := make(fakeFS)
+	for i, test := range tests {
+		testFile := &fakeFileInfo{basename: test.name}
+		fs[fmt.Sprintf("/%d", i)] = &fakeFileInfo{
+			dir:     true,
+			modtime: time.Unix(1000000000, 0).UTC(),
+			ents:    []*fakeFileInfo{testFile},
+		}
+		fs[fmt.Sprintf("/%d/%s", i, test.name)] = testFile
+	}
+
+	ts := httptest.NewServer(FileServer(&fs))
+	defer ts.Close()
+	for i, test := range tests {
+		url := fmt.Sprintf("%s/%d", ts.URL, i)
+		res, err := Get(url)
+		if err != nil {
+			t.Fatalf("test %q: Get: %v", test.name, err)
+		}
+		b, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatalf("test %q: read Body: %v", test.name, err)
+		}
+		s := string(b)
+		if !strings.HasPrefix(s, dirListPrefix) || !strings.HasSuffix(s, dirListSuffix) {
+			t.Errorf("test %q: listing dir, full output is %q, want prefix %q and suffix %q", test.name, s, dirListPrefix, dirListSuffix)
+		}
+		if trimmed := strings.TrimSuffix(strings.TrimPrefix(s, dirListPrefix), dirListSuffix); trimmed != test.escaped {
+			t.Errorf("test %q: listing dir, filename escaped to %q, want %q", test.name, trimmed, test.escaped)
+		}
+		res.Body.Close()
+	}
+}
+
+func mustRemoveAll(dir string) {
+	err := os.RemoveAll(dir)
+	if err != nil {
+		panic(err)
+	}
+}
+
+func TestFileServerImplicitLeadingSlash(t *testing.T) {
+	defer afterTest(t)
+	tempDir, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Fatalf("TempDir: %v", err)
+	}
+	defer mustRemoveAll(tempDir)
+	if err := ioutil.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil {
+		t.Fatalf("WriteFile: %v", err)
+	}
+	ts := httptest.NewServer(StripPrefix("/bar/", FileServer(Dir(tempDir))))
+	defer ts.Close()
+	get := func(suffix string) string {
+		res, err := Get(ts.URL + suffix)
+		if err != nil {
+			t.Fatalf("Get %s: %v", suffix, err)
+		}
+		b, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatalf("ReadAll %s: %v", suffix, err)
+		}
+		res.Body.Close()
+		return string(b)
+	}
+	if s := get("/bar/"); !strings.Contains(s, ">foo.txt<") {
+		t.Logf("expected a directory listing with foo.txt, got %q", s)
+	}
+	if s := get("/bar/foo.txt"); s != "Hello world" {
+		t.Logf("expected %q, got %q", "Hello world", s)
+	}
+}
+
+func TestDirJoin(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		t.Skip("skipping test on windows")
+	}
+	wfi, err := os.Stat("/etc/hosts")
+	if err != nil {
+		t.Skip("skipping test; no /etc/hosts file")
+	}
+	test := func(d Dir, name string) {
+		f, err := d.Open(name)
+		if err != nil {
+			t.Fatalf("open of %s: %v", name, err)
+		}
+		defer f.Close()
+		gfi, err := f.Stat()
+		if err != nil {
+			t.Fatalf("stat of %s: %v", name, err)
+		}
+		if !os.SameFile(gfi, wfi) {
+			t.Errorf("%s got different file", name)
+		}
+	}
+	test(Dir("/etc/"), "/hosts")
+	test(Dir("/etc/"), "hosts")
+	test(Dir("/etc/"), "../../../../hosts")
+	test(Dir("/etc"), "/hosts")
+	test(Dir("/etc"), "hosts")
+	test(Dir("/etc"), "../../../../hosts")
+
+	// Not really directories, but since we use this trick in
+	// ServeFile, test it:
+	test(Dir("/etc/hosts"), "")
+	test(Dir("/etc/hosts"), "/")
+	test(Dir("/etc/hosts"), "../")
+}
+
+func TestEmptyDirOpenCWD(t *testing.T) {
+	test := func(d Dir) {
+		name := "fs_test.go"
+		f, err := d.Open(name)
+		if err != nil {
+			t.Fatalf("open of %s: %v", name, err)
+		}
+		defer f.Close()
+	}
+	test(Dir(""))
+	test(Dir("."))
+	test(Dir("./"))
+}
+
+func TestServeFileContentType(t *testing.T) {
+	defer afterTest(t)
+	const ctype = "icecream/chocolate"
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		switch r.FormValue("override") {
+		case "1":
+			w.Header().Set("Content-Type", ctype)
+		case "2":
+			// Explicitly inhibit sniffing.
+			w.Header()["Content-Type"] = []string{}
+		}
+		ServeFile(w, r, "testdata/file")
+	}))
+	defer ts.Close()
+	get := func(override string, want []string) {
+		resp, err := Get(ts.URL + "?override=" + override)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if h := resp.Header["Content-Type"]; !reflect.DeepEqual(h, want) {
+			t.Errorf("Content-Type mismatch: got %v, want %v", h, want)
+		}
+		resp.Body.Close()
+	}
+	get("0", []string{"text/plain; charset=utf-8"})
+	get("1", []string{ctype})
+	get("2", nil)
+}
+
+func TestServeFileMimeType(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		ServeFile(w, r, "testdata/style.css")
+	}))
+	defer ts.Close()
+	resp, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	resp.Body.Close()
+	want := "text/css; charset=utf-8"
+	if h := resp.Header.Get("Content-Type"); h != want {
+		t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
+	}
+}
+
+func TestServeFileFromCWD(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		ServeFile(w, r, "fs_test.go")
+	}))
+	defer ts.Close()
+	r, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	r.Body.Close()
+	if r.StatusCode != 200 {
+		t.Fatalf("expected 200 OK, got %s", r.Status)
+	}
+}
+
+func TestServeFileWithContentEncoding(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Encoding", "foo")
+		ServeFile(w, r, "testdata/file")
+	}))
+	defer ts.Close()
+	resp, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	resp.Body.Close()
+	if g, e := resp.ContentLength, int64(-1); g != e {
+		t.Errorf("Content-Length mismatch: got %d, want %d", g, e)
+	}
+}
+
+func TestServeIndexHtml(t *testing.T) {
+	defer afterTest(t)
+	const want = "index.html says hello\n"
+	ts := httptest.NewServer(FileServer(Dir(".")))
+	defer ts.Close()
+
+	for _, path := range []string{"/testdata/", "/testdata/index.html"} {
+		res, err := Get(ts.URL + path)
+		if err != nil {
+			t.Fatal(err)
+		}
+		b, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal("reading Body:", err)
+		}
+		if s := string(b); s != want {
+			t.Errorf("for path %q got %q, want %q", path, s, want)
+		}
+		res.Body.Close()
+	}
+}
+
+func TestFileServerZeroByte(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(FileServer(Dir(".")))
+	defer ts.Close()
+
+	res, err := Get(ts.URL + "/..\x00")
+	if err != nil {
+		t.Fatal(err)
+	}
+	b, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal("reading Body:", err)
+	}
+	if res.StatusCode == 200 {
+		t.Errorf("got status 200; want an error. Body is:\n%s", string(b))
+	}
+}
+
+type fakeFileInfo struct {
+	dir      bool
+	basename string
+	modtime  time.Time
+	ents     []*fakeFileInfo
+	contents string
+}
+
+func (f *fakeFileInfo) Name() string       { return f.basename }
+func (f *fakeFileInfo) Sys() interface{}   { return nil }
+func (f *fakeFileInfo) ModTime() time.Time { return f.modtime }
+func (f *fakeFileInfo) IsDir() bool        { return f.dir }
+func (f *fakeFileInfo) Size() int64        { return int64(len(f.contents)) }
+func (f *fakeFileInfo) Mode() os.FileMode {
+	if f.dir {
+		return 0755 | os.ModeDir
+	}
+	return 0644
+}
+
+type fakeFile struct {
+	io.ReadSeeker
+	fi     *fakeFileInfo
+	path   string // as opened
+	entpos int
+}
+
+func (f *fakeFile) Close() error               { return nil }
+func (f *fakeFile) Stat() (os.FileInfo, error) { return f.fi, nil }
+func (f *fakeFile) Readdir(count int) ([]os.FileInfo, error) {
+	if !f.fi.dir {
+		return nil, os.ErrInvalid
+	}
+	var fis []os.FileInfo
+
+	limit := f.entpos + count
+	if count <= 0 || limit > len(f.fi.ents) {
+		limit = len(f.fi.ents)
+	}
+	for ; f.entpos < limit; f.entpos++ {
+		fis = append(fis, f.fi.ents[f.entpos])
+	}
+
+	if len(fis) == 0 && count > 0 {
+		return fis, io.EOF
+	} else {
+		return fis, nil
+	}
+}
+
+type fakeFS map[string]*fakeFileInfo
+
+func (fs fakeFS) Open(name string) (File, error) {
+	name = path.Clean(name)
+	f, ok := fs[name]
+	if !ok {
+		return nil, os.ErrNotExist
+	}
+	return &fakeFile{ReadSeeker: strings.NewReader(f.contents), fi: f, path: name}, nil
+}
+
+func TestDirectoryIfNotModified(t *testing.T) {
+	defer afterTest(t)
+	const indexContents = "I am a fake index.html file"
+	fileMod := time.Unix(1000000000, 0).UTC()
+	fileModStr := fileMod.Format(TimeFormat)
+	dirMod := time.Unix(123, 0).UTC()
+	indexFile := &fakeFileInfo{
+		basename: "index.html",
+		modtime:  fileMod,
+		contents: indexContents,
+	}
+	fs := fakeFS{
+		"/": &fakeFileInfo{
+			dir:     true,
+			modtime: dirMod,
+			ents:    []*fakeFileInfo{indexFile},
+		},
+		"/index.html": indexFile,
+	}
+
+	ts := httptest.NewServer(FileServer(fs))
+	defer ts.Close()
+
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	b, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(b) != indexContents {
+		t.Fatalf("Got body %q; want %q", b, indexContents)
+	}
+	res.Body.Close()
+
+	lastMod := res.Header.Get("Last-Modified")
+	if lastMod != fileModStr {
+		t.Fatalf("initial Last-Modified = %q; want %q", lastMod, fileModStr)
+	}
+
+	req, _ := NewRequest("GET", ts.URL, nil)
+	req.Header.Set("If-Modified-Since", lastMod)
+
+	res, err = DefaultClient.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != 304 {
+		t.Fatalf("Code after If-Modified-Since request = %v; want 304", res.StatusCode)
+	}
+	res.Body.Close()
+
+	// Advance the index.html file's modtime, but not the directory's.
+	indexFile.modtime = indexFile.modtime.Add(1 * time.Hour)
+
+	res, err = DefaultClient.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != 200 {
+		t.Fatalf("Code after second If-Modified-Since request = %v; want 200; res is %#v", res.StatusCode, res)
+	}
+	res.Body.Close()
+}
+
+func mustStat(t *testing.T, fileName string) os.FileInfo {
+	fi, err := os.Stat(fileName)
+	if err != nil {
+		t.Fatal(err)
+	}
+	return fi
+}
+
+func TestServeContent(t *testing.T) {
+	defer afterTest(t)
+	type serveParam struct {
+		name        string
+		modtime     time.Time
+		content     io.ReadSeeker
+		contentType string
+		etag        string
+	}
+	servec := make(chan serveParam, 1)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		p := <-servec
+		if p.etag != "" {
+			w.Header().Set("ETag", p.etag)
+		}
+		if p.contentType != "" {
+			w.Header().Set("Content-Type", p.contentType)
+		}
+		ServeContent(w, r, p.name, p.modtime, p.content)
+	}))
+	defer ts.Close()
+
+	type testCase struct {
+		// One of file or content must be set:
+		file    string
+		content io.ReadSeeker
+
+		modtime          time.Time
+		serveETag        string // optional
+		serveContentType string // optional
+		reqHeader        map[string]string
+		wantLastMod      string
+		wantContentType  string
+		wantStatus       int
+	}
+	htmlModTime := mustStat(t, "testdata/index.html").ModTime()
+	tests := map[string]testCase{
+		"no_last_modified": {
+			file:            "testdata/style.css",
+			wantContentType: "text/css; charset=utf-8",
+			wantStatus:      200,
+		},
+		"with_last_modified": {
+			file:            "testdata/index.html",
+			wantContentType: "text/html; charset=utf-8",
+			modtime:         htmlModTime,
+			wantLastMod:     htmlModTime.UTC().Format(TimeFormat),
+			wantStatus:      200,
+		},
+		"not_modified_modtime": {
+			file:    "testdata/style.css",
+			modtime: htmlModTime,
+			reqHeader: map[string]string{
+				"If-Modified-Since": htmlModTime.UTC().Format(TimeFormat),
+			},
+			wantStatus: 304,
+		},
+		"not_modified_modtime_with_contenttype": {
+			file:             "testdata/style.css",
+			serveContentType: "text/css", // explicit content type
+			modtime:          htmlModTime,
+			reqHeader: map[string]string{
+				"If-Modified-Since": htmlModTime.UTC().Format(TimeFormat),
+			},
+			wantStatus: 304,
+		},
+		"not_modified_etag": {
+			file:      "testdata/style.css",
+			serveETag: `"foo"`,
+			reqHeader: map[string]string{
+				"If-None-Match": `"foo"`,
+			},
+			wantStatus: 304,
+		},
+		"not_modified_etag_no_seek": {
+			content:   panicOnSeek{nil}, // should never be called
+			serveETag: `"foo"`,
+			reqHeader: map[string]string{
+				"If-None-Match": `"foo"`,
+			},
+			wantStatus: 304,
+		},
+		"range_good": {
+			file:      "testdata/style.css",
+			serveETag: `"A"`,
+			reqHeader: map[string]string{
+				"Range": "bytes=0-4",
+			},
+			wantStatus:      StatusPartialContent,
+			wantContentType: "text/css; charset=utf-8",
+		},
+		// An If-Range resource for entity "A", but entity "B" is now current.
+		// The Range request should be ignored.
+		"range_no_match": {
+			file:      "testdata/style.css",
+			serveETag: `"A"`,
+			reqHeader: map[string]string{
+				"Range":    "bytes=0-4",
+				"If-Range": `"B"`,
+			},
+			wantStatus:      200,
+			wantContentType: "text/css; charset=utf-8",
+		},
+	}
+	for testName, tt := range tests {
+		var content io.ReadSeeker
+		if tt.file != "" {
+			f, err := os.Open(tt.file)
+			if err != nil {
+				t.Fatalf("test %q: %v", testName, err)
+			}
+			defer f.Close()
+			content = f
+		} else {
+			content = tt.content
+		}
+
+		servec <- serveParam{
+			name:        filepath.Base(tt.file),
+			content:     content,
+			modtime:     tt.modtime,
+			etag:        tt.serveETag,
+			contentType: tt.serveContentType,
+		}
+		req, err := NewRequest("GET", ts.URL, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		for k, v := range tt.reqHeader {
+			req.Header.Set(k, v)
+		}
+		res, err := DefaultClient.Do(req)
+		if err != nil {
+			t.Fatal(err)
+		}
+		io.Copy(ioutil.Discard, res.Body)
+		res.Body.Close()
+		if res.StatusCode != tt.wantStatus {
+			t.Errorf("test %q: status = %d; want %d", testName, res.StatusCode, tt.wantStatus)
+		}
+		if g, e := res.Header.Get("Content-Type"), tt.wantContentType; g != e {
+			t.Errorf("test %q: content-type = %q, want %q", testName, g, e)
+		}
+		if g, e := res.Header.Get("Last-Modified"), tt.wantLastMod; g != e {
+			t.Errorf("test %q: last-modified = %q, want %q", testName, g, e)
+		}
+	}
+}
+
+// verifies that sendfile is being used on Linux
+func TestLinuxSendfile(t *testing.T) {
+	defer afterTest(t)
+	if runtime.GOOS != "linux" {
+		t.Skip("skipping; linux-only test")
+	}
+	if _, err := exec.LookPath("strace"); err != nil {
+		t.Skip("skipping; strace not found in path")
+	}
+
+	ln, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	lnf, err := ln.(*net.TCPListener).File()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln.Close()
+
+	trace := "trace=sendfile"
+	if runtime.GOARCH != "alpha" {
+		trace = trace + ",sendfile64"
+	}
+
+	var buf bytes.Buffer
+	child := exec.Command("strace", "-f", "-q", "-e", trace, os.Args[0], "-test.run=TestLinuxSendfileChild")
+	child.ExtraFiles = append(child.ExtraFiles, lnf)
+	child.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
+	child.Stdout = &buf
+	child.Stderr = &buf
+	if err := child.Start(); err != nil {
+		t.Skipf("skipping; failed to start straced child: %v", err)
+	}
+
+	res, err := Get(fmt.Sprintf("http://%s/", ln.Addr()))
+	if err != nil {
+		t.Fatalf("http client error: %v", err)
+	}
+	_, err = io.Copy(ioutil.Discard, res.Body)
+	if err != nil {
+		t.Fatalf("client body read error: %v", err)
+	}
+	res.Body.Close()
+
+	// Force child to exit cleanly.
+	Get(fmt.Sprintf("http://%s/quit", ln.Addr()))
+	child.Wait()
+
+	rx := regexp.MustCompile(`sendfile(64)?\(\d+,\s*\d+,\s*NULL,\s*\d+\)\s*=\s*\d+\s*\n`)
+	rxResume := regexp.MustCompile(`<\.\.\. sendfile(64)? resumed> \)\s*=\s*\d+\s*\n`)
+	out := buf.String()
+	if !rx.MatchString(out) && !rxResume.MatchString(out) {
+		t.Errorf("no sendfile system call found in:\n%s", out)
+	}
+}
+
+func getBody(t *testing.T, testName string, req Request) (*Response, []byte) {
+	r, err := DefaultClient.Do(&req)
+	if err != nil {
+		t.Fatalf("%s: for URL %q, send error: %v", testName, req.URL.String(), err)
+	}
+	b, err := ioutil.ReadAll(r.Body)
+	if err != nil {
+		t.Fatalf("%s: for URL %q, reading body: %v", testName, req.URL.String(), err)
+	}
+	return r, b
+}
+
+// TestLinuxSendfileChild isn't a real test. It's used as a helper process
+// for TestLinuxSendfile.
+func TestLinuxSendfileChild(*testing.T) {
+	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
+		return
+	}
+	defer os.Exit(0)
+	fd3 := os.NewFile(3, "ephemeral-port-listener")
+	ln, err := net.FileListener(fd3)
+	if err != nil {
+		panic(err)
+	}
+	mux := NewServeMux()
+	mux.Handle("/", FileServer(Dir("testdata")))
+	mux.HandleFunc("/quit", func(ResponseWriter, *Request) {
+		os.Exit(0)
+	})
+	s := &Server{Handler: mux}
+	err = s.Serve(ln)
+	if err != nil {
+		panic(err)
+	}
+}
+
+type panicOnSeek struct{ io.ReadSeeker }
diff --git a/third_party/gofrontend/libgo/go/net/http/header.go b/third_party/gofrontend/libgo/go/net/http/header.go
new file mode 100644
index 0000000..153b943
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/header.go
@@ -0,0 +1,211 @@
+// Copyright 2010 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 http
+
+import (
+	"io"
+	"net/textproto"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+)
+
+var raceEnabled = false // set by race.go
+
+// A Header represents the key-value pairs in an HTTP header.
+type Header map[string][]string
+
+// Add adds the key, value pair to the header.
+// It appends to any existing values associated with key.
+func (h Header) Add(key, value string) {
+	textproto.MIMEHeader(h).Add(key, value)
+}
+
+// Set sets the header entries associated with key to
+// the single element value.  It replaces any existing
+// values associated with key.
+func (h Header) Set(key, value string) {
+	textproto.MIMEHeader(h).Set(key, value)
+}
+
+// Get gets the first value associated with the given key.
+// If there are no values associated with the key, Get returns "".
+// To access multiple values of a key, access the map directly
+// with CanonicalHeaderKey.
+func (h Header) Get(key string) string {
+	return textproto.MIMEHeader(h).Get(key)
+}
+
+// get is like Get, but key must already be in CanonicalHeaderKey form.
+func (h Header) get(key string) string {
+	if v := h[key]; len(v) > 0 {
+		return v[0]
+	}
+	return ""
+}
+
+// Del deletes the values associated with key.
+func (h Header) Del(key string) {
+	textproto.MIMEHeader(h).Del(key)
+}
+
+// Write writes a header in wire format.
+func (h Header) Write(w io.Writer) error {
+	return h.WriteSubset(w, nil)
+}
+
+func (h Header) clone() Header {
+	h2 := make(Header, len(h))
+	for k, vv := range h {
+		vv2 := make([]string, len(vv))
+		copy(vv2, vv)
+		h2[k] = vv2
+	}
+	return h2
+}
+
+var timeFormats = []string{
+	TimeFormat,
+	time.RFC850,
+	time.ANSIC,
+}
+
+// ParseTime parses a time header (such as the Date: header),
+// trying each of the three formats allowed by HTTP/1.1:
+// TimeFormat, time.RFC850, and time.ANSIC.
+func ParseTime(text string) (t time.Time, err error) {
+	for _, layout := range timeFormats {
+		t, err = time.Parse(layout, text)
+		if err == nil {
+			return
+		}
+	}
+	return
+}
+
+var headerNewlineToSpace = strings.NewReplacer("\n", " ", "\r", " ")
+
+type writeStringer interface {
+	WriteString(string) (int, error)
+}
+
+// stringWriter implements WriteString on a Writer.
+type stringWriter struct {
+	w io.Writer
+}
+
+func (w stringWriter) WriteString(s string) (n int, err error) {
+	return w.w.Write([]byte(s))
+}
+
+type keyValues struct {
+	key    string
+	values []string
+}
+
+// A headerSorter implements sort.Interface by sorting a []keyValues
+// by key. It's used as a pointer, so it can fit in a sort.Interface
+// interface value without allocation.
+type headerSorter struct {
+	kvs []keyValues
+}
+
+func (s *headerSorter) Len() int           { return len(s.kvs) }
+func (s *headerSorter) Swap(i, j int)      { s.kvs[i], s.kvs[j] = s.kvs[j], s.kvs[i] }
+func (s *headerSorter) Less(i, j int) bool { return s.kvs[i].key < s.kvs[j].key }
+
+var headerSorterPool = sync.Pool{
+	New: func() interface{} { return new(headerSorter) },
+}
+
+// sortedKeyValues returns h's keys sorted in the returned kvs
+// slice. The headerSorter used to sort is also returned, for possible
+// return to headerSorterCache.
+func (h Header) sortedKeyValues(exclude map[string]bool) (kvs []keyValues, hs *headerSorter) {
+	hs = headerSorterPool.Get().(*headerSorter)
+	if cap(hs.kvs) < len(h) {
+		hs.kvs = make([]keyValues, 0, len(h))
+	}
+	kvs = hs.kvs[:0]
+	for k, vv := range h {
+		if !exclude[k] {
+			kvs = append(kvs, keyValues{k, vv})
+		}
+	}
+	hs.kvs = kvs
+	sort.Sort(hs)
+	return kvs, hs
+}
+
+// WriteSubset writes a header in wire format.
+// If exclude is not nil, keys where exclude[key] == true are not written.
+func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
+	ws, ok := w.(writeStringer)
+	if !ok {
+		ws = stringWriter{w}
+	}
+	kvs, sorter := h.sortedKeyValues(exclude)
+	for _, kv := range kvs {
+		for _, v := range kv.values {
+			v = headerNewlineToSpace.Replace(v)
+			v = textproto.TrimString(v)
+			for _, s := range []string{kv.key, ": ", v, "\r\n"} {
+				if _, err := ws.WriteString(s); err != nil {
+					return err
+				}
+			}
+		}
+	}
+	headerSorterPool.Put(sorter)
+	return nil
+}
+
+// CanonicalHeaderKey returns the canonical format of the
+// header key s.  The canonicalization converts the first
+// letter and any letter following a hyphen to upper case;
+// the rest are converted to lowercase.  For example, the
+// canonical key for "accept-encoding" is "Accept-Encoding".
+func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
+
+// hasToken reports whether token appears with v, ASCII
+// case-insensitive, with space or comma boundaries.
+// token must be all lowercase.
+// v may contain mixed cased.
+func hasToken(v, token string) bool {
+	if len(token) > len(v) || token == "" {
+		return false
+	}
+	if v == token {
+		return true
+	}
+	for sp := 0; sp <= len(v)-len(token); sp++ {
+		// Check that first character is good.
+		// The token is ASCII, so checking only a single byte
+		// is sufficient.  We skip this potential starting
+		// position if both the first byte and its potential
+		// ASCII uppercase equivalent (b|0x20) don't match.
+		// False positives ('^' => '~') are caught by EqualFold.
+		if b := v[sp]; b != token[0] && b|0x20 != token[0] {
+			continue
+		}
+		// Check that start pos is on a valid token boundary.
+		if sp > 0 && !isTokenBoundary(v[sp-1]) {
+			continue
+		}
+		// Check that end pos is on a valid token boundary.
+		if endPos := sp + len(token); endPos != len(v) && !isTokenBoundary(v[endPos]) {
+			continue
+		}
+		if strings.EqualFold(v[sp:sp+len(token)], token) {
+			return true
+		}
+	}
+	return false
+}
+
+func isTokenBoundary(b byte) bool {
+	return b == ' ' || b == ',' || b == '\t'
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/header_test.go b/third_party/gofrontend/libgo/go/net/http/header_test.go
new file mode 100644
index 0000000..299576b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/header_test.go
@@ -0,0 +1,213 @@
+// 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.
+
+package http
+
+import (
+	"bytes"
+	"runtime"
+	"testing"
+	"time"
+)
+
+var headerWriteTests = []struct {
+	h        Header
+	exclude  map[string]bool
+	expected string
+}{
+	{Header{}, nil, ""},
+	{
+		Header{
+			"Content-Type":   {"text/html; charset=UTF-8"},
+			"Content-Length": {"0"},
+		},
+		nil,
+		"Content-Length: 0\r\nContent-Type: text/html; charset=UTF-8\r\n",
+	},
+	{
+		Header{
+			"Content-Length": {"0", "1", "2"},
+		},
+		nil,
+		"Content-Length: 0\r\nContent-Length: 1\r\nContent-Length: 2\r\n",
+	},
+	{
+		Header{
+			"Expires":          {"-1"},
+			"Content-Length":   {"0"},
+			"Content-Encoding": {"gzip"},
+		},
+		map[string]bool{"Content-Length": true},
+		"Content-Encoding: gzip\r\nExpires: -1\r\n",
+	},
+	{
+		Header{
+			"Expires":          {"-1"},
+			"Content-Length":   {"0", "1", "2"},
+			"Content-Encoding": {"gzip"},
+		},
+		map[string]bool{"Content-Length": true},
+		"Content-Encoding: gzip\r\nExpires: -1\r\n",
+	},
+	{
+		Header{
+			"Expires":          {"-1"},
+			"Content-Length":   {"0"},
+			"Content-Encoding": {"gzip"},
+		},
+		map[string]bool{"Content-Length": true, "Expires": true, "Content-Encoding": true},
+		"",
+	},
+	{
+		Header{
+			"Nil":          nil,
+			"Empty":        {},
+			"Blank":        {""},
+			"Double-Blank": {"", ""},
+		},
+		nil,
+		"Blank: \r\nDouble-Blank: \r\nDouble-Blank: \r\n",
+	},
+	// Tests header sorting when over the insertion sort threshold side:
+	{
+		Header{
+			"k1": {"1a", "1b"},
+			"k2": {"2a", "2b"},
+			"k3": {"3a", "3b"},
+			"k4": {"4a", "4b"},
+			"k5": {"5a", "5b"},
+			"k6": {"6a", "6b"},
+			"k7": {"7a", "7b"},
+			"k8": {"8a", "8b"},
+			"k9": {"9a", "9b"},
+		},
+		map[string]bool{"k5": true},
+		"k1: 1a\r\nk1: 1b\r\nk2: 2a\r\nk2: 2b\r\nk3: 3a\r\nk3: 3b\r\n" +
+			"k4: 4a\r\nk4: 4b\r\nk6: 6a\r\nk6: 6b\r\n" +
+			"k7: 7a\r\nk7: 7b\r\nk8: 8a\r\nk8: 8b\r\nk9: 9a\r\nk9: 9b\r\n",
+	},
+}
+
+func TestHeaderWrite(t *testing.T) {
+	var buf bytes.Buffer
+	for i, test := range headerWriteTests {
+		test.h.WriteSubset(&buf, test.exclude)
+		if buf.String() != test.expected {
+			t.Errorf("#%d:\n got: %q\nwant: %q", i, buf.String(), test.expected)
+		}
+		buf.Reset()
+	}
+}
+
+var parseTimeTests = []struct {
+	h   Header
+	err bool
+}{
+	{Header{"Date": {""}}, true},
+	{Header{"Date": {"invalid"}}, true},
+	{Header{"Date": {"1994-11-06T08:49:37Z00:00"}}, true},
+	{Header{"Date": {"Sun, 06 Nov 1994 08:49:37 GMT"}}, false},
+	{Header{"Date": {"Sunday, 06-Nov-94 08:49:37 GMT"}}, false},
+	{Header{"Date": {"Sun Nov  6 08:49:37 1994"}}, false},
+}
+
+func TestParseTime(t *testing.T) {
+	expect := time.Date(1994, 11, 6, 8, 49, 37, 0, time.UTC)
+	for i, test := range parseTimeTests {
+		d, err := ParseTime(test.h.Get("Date"))
+		if err != nil {
+			if !test.err {
+				t.Errorf("#%d:\n got err: %v", i, err)
+			}
+			continue
+		}
+		if test.err {
+			t.Errorf("#%d:\n  should err", i)
+			continue
+		}
+		if !expect.Equal(d) {
+			t.Errorf("#%d:\n got: %v\nwant: %v", i, d, expect)
+		}
+	}
+}
+
+type hasTokenTest struct {
+	header string
+	token  string
+	want   bool
+}
+
+var hasTokenTests = []hasTokenTest{
+	{"", "", false},
+	{"", "foo", false},
+	{"foo", "foo", true},
+	{"foo ", "foo", true},
+	{" foo", "foo", true},
+	{" foo ", "foo", true},
+	{"foo,bar", "foo", true},
+	{"bar,foo", "foo", true},
+	{"bar, foo", "foo", true},
+	{"bar,foo, baz", "foo", true},
+	{"bar, foo,baz", "foo", true},
+	{"bar,foo, baz", "foo", true},
+	{"bar, foo, baz", "foo", true},
+	{"FOO", "foo", true},
+	{"FOO ", "foo", true},
+	{" FOO", "foo", true},
+	{" FOO ", "foo", true},
+	{"FOO,BAR", "foo", true},
+	{"BAR,FOO", "foo", true},
+	{"BAR, FOO", "foo", true},
+	{"BAR,FOO, baz", "foo", true},
+	{"BAR, FOO,BAZ", "foo", true},
+	{"BAR,FOO, BAZ", "foo", true},
+	{"BAR, FOO, BAZ", "foo", true},
+	{"foobar", "foo", false},
+	{"barfoo ", "foo", false},
+}
+
+func TestHasToken(t *testing.T) {
+	for _, tt := range hasTokenTests {
+		if hasToken(tt.header, tt.token) != tt.want {
+			t.Errorf("hasToken(%q, %q) = %v; want %v", tt.header, tt.token, !tt.want, tt.want)
+		}
+	}
+}
+
+var testHeader = Header{
+	"Content-Length": {"123"},
+	"Content-Type":   {"text/plain"},
+	"Date":           {"some date at some time Z"},
+	"Server":         {DefaultUserAgent},
+}
+
+var buf bytes.Buffer
+
+func BenchmarkHeaderWriteSubset(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		buf.Reset()
+		testHeader.WriteSubset(&buf, nil)
+	}
+}
+
+func TestHeaderWriteSubsetAllocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping alloc test in short mode")
+	}
+	if raceEnabled {
+		t.Skip("skipping test under race detector")
+	}
+	t.Skip("Skipping alloc count test on gccgo")
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Skip("skipping; GOMAXPROCS>1")
+	}
+	n := testing.AllocsPerRun(100, func() {
+		buf.Reset()
+		testHeader.WriteSubset(&buf, nil)
+	})
+	if n > 0 {
+		t.Errorf("allocs = %g; want 0", n)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/httptest/recorder.go b/third_party/gofrontend/libgo/go/net/http/httptest/recorder.go
new file mode 100644
index 0000000..5451f54
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httptest/recorder.go
@@ -0,0 +1,72 @@
+// 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.
+
+// Package httptest provides utilities for HTTP testing.
+package httptest
+
+import (
+	"bytes"
+	"net/http"
+)
+
+// ResponseRecorder is an implementation of http.ResponseWriter that
+// records its mutations for later inspection in tests.
+type ResponseRecorder struct {
+	Code      int           // the HTTP response code from WriteHeader
+	HeaderMap http.Header   // the HTTP response headers
+	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
+	Flushed   bool
+
+	wroteHeader bool
+}
+
+// NewRecorder returns an initialized ResponseRecorder.
+func NewRecorder() *ResponseRecorder {
+	return &ResponseRecorder{
+		HeaderMap: make(http.Header),
+		Body:      new(bytes.Buffer),
+		Code:      200,
+	}
+}
+
+// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
+// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
+const DefaultRemoteAddr = "1.2.3.4"
+
+// Header returns the response headers.
+func (rw *ResponseRecorder) Header() http.Header {
+	m := rw.HeaderMap
+	if m == nil {
+		m = make(http.Header)
+		rw.HeaderMap = m
+	}
+	return m
+}
+
+// Write always succeeds and writes to rw.Body, if not nil.
+func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
+	if !rw.wroteHeader {
+		rw.WriteHeader(200)
+	}
+	if rw.Body != nil {
+		rw.Body.Write(buf)
+	}
+	return len(buf), nil
+}
+
+// WriteHeader sets rw.Code.
+func (rw *ResponseRecorder) WriteHeader(code int) {
+	if !rw.wroteHeader {
+		rw.Code = code
+	}
+	rw.wroteHeader = true
+}
+
+// Flush sets rw.Flushed to true.
+func (rw *ResponseRecorder) Flush() {
+	if !rw.wroteHeader {
+		rw.WriteHeader(200)
+	}
+	rw.Flushed = true
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/httptest/recorder_test.go b/third_party/gofrontend/libgo/go/net/http/httptest/recorder_test.go
new file mode 100644
index 0000000..2b56326
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httptest/recorder_test.go
@@ -0,0 +1,90 @@
+// 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 httptest
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+)
+
+func TestRecorder(t *testing.T) {
+	type checkFunc func(*ResponseRecorder) error
+	check := func(fns ...checkFunc) []checkFunc { return fns }
+
+	hasStatus := func(wantCode int) checkFunc {
+		return func(rec *ResponseRecorder) error {
+			if rec.Code != wantCode {
+				return fmt.Errorf("Status = %d; want %d", rec.Code, wantCode)
+			}
+			return nil
+		}
+	}
+	hasContents := func(want string) checkFunc {
+		return func(rec *ResponseRecorder) error {
+			if rec.Body.String() != want {
+				return fmt.Errorf("wrote = %q; want %q", rec.Body.String(), want)
+			}
+			return nil
+		}
+	}
+	hasFlush := func(want bool) checkFunc {
+		return func(rec *ResponseRecorder) error {
+			if rec.Flushed != want {
+				return fmt.Errorf("Flushed = %v; want %v", rec.Flushed, want)
+			}
+			return nil
+		}
+	}
+
+	tests := []struct {
+		name   string
+		h      func(w http.ResponseWriter, r *http.Request)
+		checks []checkFunc
+	}{
+		{
+			"200 default",
+			func(w http.ResponseWriter, r *http.Request) {},
+			check(hasStatus(200), hasContents("")),
+		},
+		{
+			"first code only",
+			func(w http.ResponseWriter, r *http.Request) {
+				w.WriteHeader(201)
+				w.WriteHeader(202)
+				w.Write([]byte("hi"))
+			},
+			check(hasStatus(201), hasContents("hi")),
+		},
+		{
+			"write sends 200",
+			func(w http.ResponseWriter, r *http.Request) {
+				w.Write([]byte("hi first"))
+				w.WriteHeader(201)
+				w.WriteHeader(202)
+			},
+			check(hasStatus(200), hasContents("hi first"), hasFlush(false)),
+		},
+		{
+			"flush",
+			func(w http.ResponseWriter, r *http.Request) {
+				w.(http.Flusher).Flush() // also sends a 200
+				w.WriteHeader(201)
+			},
+			check(hasStatus(200), hasFlush(true)),
+		},
+	}
+	r, _ := http.NewRequest("GET", "http://foo.com/", nil)
+	for _, tt := range tests {
+		h := http.HandlerFunc(tt.h)
+		rec := NewRecorder()
+		h.ServeHTTP(rec, r)
+		for _, check := range tt.checks {
+			if err := check(rec); err != nil {
+				t.Errorf("%s: %v", tt.name, err)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/httptest/server.go b/third_party/gofrontend/libgo/go/net/http/httptest/server.go
new file mode 100644
index 0000000..7f26555
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httptest/server.go
@@ -0,0 +1,228 @@
+// 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.
+
+// Implementation of Server
+
+package httptest
+
+import (
+	"crypto/tls"
+	"flag"
+	"fmt"
+	"net"
+	"net/http"
+	"os"
+	"sync"
+)
+
+// A Server is an HTTP server listening on a system-chosen port on the
+// local loopback interface, for use in end-to-end HTTP tests.
+type Server struct {
+	URL      string // base URL of form http://ipaddr:port with no trailing slash
+	Listener net.Listener
+
+	// TLS is the optional TLS configuration, populated with a new config
+	// after TLS is started. If set on an unstarted server before StartTLS
+	// is called, existing fields are copied into the new config.
+	TLS *tls.Config
+
+	// Config may be changed after calling NewUnstartedServer and
+	// before Start or StartTLS.
+	Config *http.Server
+
+	// wg counts the number of outstanding HTTP requests on this server.
+	// Close blocks until all requests are finished.
+	wg sync.WaitGroup
+}
+
+// historyListener keeps track of all connections that it's ever
+// accepted.
+type historyListener struct {
+	net.Listener
+	sync.Mutex // protects history
+	history    []net.Conn
+}
+
+func (hs *historyListener) Accept() (c net.Conn, err error) {
+	c, err = hs.Listener.Accept()
+	if err == nil {
+		hs.Lock()
+		hs.history = append(hs.history, c)
+		hs.Unlock()
+	}
+	return
+}
+
+func newLocalListener() net.Listener {
+	if *serve != "" {
+		l, err := net.Listen("tcp", *serve)
+		if err != nil {
+			panic(fmt.Sprintf("httptest: failed to listen on %v: %v", *serve, err))
+		}
+		return l
+	}
+	l, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
+			panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
+		}
+	}
+	return l
+}
+
+// When debugging a particular http server-based test,
+// this flag lets you run
+//	go test -run=BrokenTest -httptest.serve=127.0.0.1:8000
+// to start the broken server so you can interact with it manually.
+var serve = flag.String("httptest.serve", "", "if non-empty, httptest.NewServer serves on this address and blocks")
+
+// NewServer starts and returns a new Server.
+// The caller should call Close when finished, to shut it down.
+func NewServer(handler http.Handler) *Server {
+	ts := NewUnstartedServer(handler)
+	ts.Start()
+	return ts
+}
+
+// NewUnstartedServer returns a new Server but doesn't start it.
+//
+// After changing its configuration, the caller should call Start or
+// StartTLS.
+//
+// The caller should call Close when finished, to shut it down.
+func NewUnstartedServer(handler http.Handler) *Server {
+	return &Server{
+		Listener: newLocalListener(),
+		Config:   &http.Server{Handler: handler},
+	}
+}
+
+// Start starts a server from NewUnstartedServer.
+func (s *Server) Start() {
+	if s.URL != "" {
+		panic("Server already started")
+	}
+	s.Listener = &historyListener{Listener: s.Listener}
+	s.URL = "http://" + s.Listener.Addr().String()
+	s.wrapHandler()
+	go s.Config.Serve(s.Listener)
+	if *serve != "" {
+		fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL)
+		select {}
+	}
+}
+
+// StartTLS starts TLS on a server from NewUnstartedServer.
+func (s *Server) StartTLS() {
+	if s.URL != "" {
+		panic("Server already started")
+	}
+	cert, err := tls.X509KeyPair(localhostCert, localhostKey)
+	if err != nil {
+		panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
+	}
+
+	existingConfig := s.TLS
+	s.TLS = new(tls.Config)
+	if existingConfig != nil {
+		*s.TLS = *existingConfig
+	}
+	if s.TLS.NextProtos == nil {
+		s.TLS.NextProtos = []string{"http/1.1"}
+	}
+	if len(s.TLS.Certificates) == 0 {
+		s.TLS.Certificates = []tls.Certificate{cert}
+	}
+	tlsListener := tls.NewListener(s.Listener, s.TLS)
+
+	s.Listener = &historyListener{Listener: tlsListener}
+	s.URL = "https://" + s.Listener.Addr().String()
+	s.wrapHandler()
+	go s.Config.Serve(s.Listener)
+}
+
+func (s *Server) wrapHandler() {
+	h := s.Config.Handler
+	if h == nil {
+		h = http.DefaultServeMux
+	}
+	s.Config.Handler = &waitGroupHandler{
+		s: s,
+		h: h,
+	}
+}
+
+// NewTLSServer starts and returns a new Server using TLS.
+// The caller should call Close when finished, to shut it down.
+func NewTLSServer(handler http.Handler) *Server {
+	ts := NewUnstartedServer(handler)
+	ts.StartTLS()
+	return ts
+}
+
+// Close shuts down the server and blocks until all outstanding
+// requests on this server have completed.
+func (s *Server) Close() {
+	s.Listener.Close()
+	s.wg.Wait()
+	s.CloseClientConnections()
+	if t, ok := http.DefaultTransport.(*http.Transport); ok {
+		t.CloseIdleConnections()
+	}
+}
+
+// CloseClientConnections closes any currently open HTTP connections
+// to the test Server.
+func (s *Server) CloseClientConnections() {
+	hl, ok := s.Listener.(*historyListener)
+	if !ok {
+		return
+	}
+	hl.Lock()
+	for _, conn := range hl.history {
+		conn.Close()
+	}
+	hl.Unlock()
+}
+
+// waitGroupHandler wraps a handler, incrementing and decrementing a
+// sync.WaitGroup on each request, to enable Server.Close to block
+// until outstanding requests are finished.
+type waitGroupHandler struct {
+	s *Server
+	h http.Handler // non-nil
+}
+
+func (h *waitGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	h.s.wg.Add(1)
+	defer h.s.wg.Done() // a defer, in case ServeHTTP below panics
+	h.h.ServeHTTP(w, r)
+}
+
+// localhostCert is a PEM-encoded TLS cert with SAN IPs
+// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
+// of ASN.1 time).
+// generated from src/pkg/crypto/tls:
+// go run generate_cert.go  --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
+var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
+bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
+bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
+IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
+AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
+EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
+AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
+Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
+-----END CERTIFICATE-----`)
+
+// localhostKey is the private key for localhostCert.
+var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
+0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
+NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
+AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
+MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
+EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
+1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
+-----END RSA PRIVATE KEY-----`)
diff --git a/third_party/gofrontend/libgo/go/net/http/httptest/server_test.go b/third_party/gofrontend/libgo/go/net/http/httptest/server_test.go
new file mode 100644
index 0000000..4fc4c70
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httptest/server_test.go
@@ -0,0 +1,53 @@
+// 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 httptest
+
+import (
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+)
+
+func TestServer(t *testing.T) {
+	ts := NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Write([]byte("hello"))
+	}))
+	defer ts.Close()
+	res, err := http.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	got, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(got) != "hello" {
+		t.Errorf("got %q, want hello", string(got))
+	}
+}
+
+func TestIssue7264(t *testing.T) {
+	t.Skip("broken test - removed at tip")
+	for i := 0; i < 1000; i++ {
+		func() {
+			inHandler := make(chan bool, 1)
+			ts := NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+				inHandler <- true
+			}))
+			defer ts.Close()
+			tr := &http.Transport{
+				ResponseHeaderTimeout: time.Nanosecond,
+			}
+			defer tr.CloseIdleConnections()
+			c := &http.Client{Transport: tr}
+			res, err := c.Get(ts.URL)
+			<-inHandler
+			if err == nil {
+				res.Body.Close()
+			}
+		}()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/httputil/chunked.go b/third_party/gofrontend/libgo/go/net/http/httputil/chunked.go
new file mode 100644
index 0000000..9632bfd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httputil/chunked.go
@@ -0,0 +1,203 @@
+// 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.
+
+// The wire protocol for HTTP's "chunked" Transfer-Encoding.
+
+// This code is duplicated in net/http and net/http/httputil.
+// Please make any changes in both files.
+
+package httputil
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+)
+
+const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
+
+var ErrLineTooLong = errors.New("header line too long")
+
+// newChunkedReader returns a new chunkedReader that translates the data read from r
+// out of HTTP "chunked" format before returning it.
+// The chunkedReader returns io.EOF when the final 0-length chunk is read.
+//
+// newChunkedReader is not needed by normal applications. The http package
+// automatically decodes chunking when reading response bodies.
+func newChunkedReader(r io.Reader) io.Reader {
+	br, ok := r.(*bufio.Reader)
+	if !ok {
+		br = bufio.NewReader(r)
+	}
+	return &chunkedReader{r: br}
+}
+
+type chunkedReader struct {
+	r   *bufio.Reader
+	n   uint64 // unread bytes in chunk
+	err error
+	buf [2]byte
+}
+
+func (cr *chunkedReader) beginChunk() {
+	// chunk-size CRLF
+	var line []byte
+	line, cr.err = readLine(cr.r)
+	if cr.err != nil {
+		return
+	}
+	cr.n, cr.err = parseHexUint(line)
+	if cr.err != nil {
+		return
+	}
+	if cr.n == 0 {
+		cr.err = io.EOF
+	}
+}
+
+func (cr *chunkedReader) chunkHeaderAvailable() bool {
+	n := cr.r.Buffered()
+	if n > 0 {
+		peek, _ := cr.r.Peek(n)
+		return bytes.IndexByte(peek, '\n') >= 0
+	}
+	return false
+}
+
+func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
+	for cr.err == nil {
+		if cr.n == 0 {
+			if n > 0 && !cr.chunkHeaderAvailable() {
+				// We've read enough. Don't potentially block
+				// reading a new chunk header.
+				break
+			}
+			cr.beginChunk()
+			continue
+		}
+		if len(b) == 0 {
+			break
+		}
+		rbuf := b
+		if uint64(len(rbuf)) > cr.n {
+			rbuf = rbuf[:cr.n]
+		}
+		var n0 int
+		n0, cr.err = cr.r.Read(rbuf)
+		n += n0
+		b = b[n0:]
+		cr.n -= uint64(n0)
+		// If we're at the end of a chunk, read the next two
+		// bytes to verify they are "\r\n".
+		if cr.n == 0 && cr.err == nil {
+			if _, cr.err = io.ReadFull(cr.r, cr.buf[:2]); cr.err == nil {
+				if cr.buf[0] != '\r' || cr.buf[1] != '\n' {
+					cr.err = errors.New("malformed chunked encoding")
+				}
+			}
+		}
+	}
+	return n, cr.err
+}
+
+// Read a line of bytes (up to \n) from b.
+// Give up if the line exceeds maxLineLength.
+// The returned bytes are a pointer into storage in
+// the bufio, so they are only valid until the next bufio read.
+func readLine(b *bufio.Reader) (p []byte, err error) {
+	if p, err = b.ReadSlice('\n'); err != nil {
+		// We always know when EOF is coming.
+		// If the caller asked for a line, there should be a line.
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		} else if err == bufio.ErrBufferFull {
+			err = ErrLineTooLong
+		}
+		return nil, err
+	}
+	if len(p) >= maxLineLength {
+		return nil, ErrLineTooLong
+	}
+	return trimTrailingWhitespace(p), nil
+}
+
+func trimTrailingWhitespace(b []byte) []byte {
+	for len(b) > 0 && isASCIISpace(b[len(b)-1]) {
+		b = b[:len(b)-1]
+	}
+	return b
+}
+
+func isASCIISpace(b byte) bool {
+	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
+}
+
+// newChunkedWriter returns a new chunkedWriter that translates writes into HTTP
+// "chunked" format before writing them to w. Closing the returned chunkedWriter
+// sends the final 0-length chunk that marks the end of the stream.
+//
+// newChunkedWriter is not needed by normal applications. The http
+// package adds chunking automatically if handlers don't set a
+// Content-Length header. Using newChunkedWriter inside a handler
+// would result in double chunking or chunking with a Content-Length
+// length, both of which are wrong.
+func newChunkedWriter(w io.Writer) io.WriteCloser {
+	return &chunkedWriter{w}
+}
+
+// Writing to chunkedWriter translates to writing in HTTP chunked Transfer
+// Encoding wire format to the underlying Wire chunkedWriter.
+type chunkedWriter struct {
+	Wire io.Writer
+}
+
+// Write the contents of data as one chunk to Wire.
+// NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has
+// a bug since it does not check for success of io.WriteString
+func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
+
+	// Don't send 0-length data. It looks like EOF for chunked encoding.
+	if len(data) == 0 {
+		return 0, nil
+	}
+
+	if _, err = fmt.Fprintf(cw.Wire, "%x\r\n", len(data)); err != nil {
+		return 0, err
+	}
+	if n, err = cw.Wire.Write(data); err != nil {
+		return
+	}
+	if n != len(data) {
+		err = io.ErrShortWrite
+		return
+	}
+	_, err = io.WriteString(cw.Wire, "\r\n")
+
+	return
+}
+
+func (cw *chunkedWriter) Close() error {
+	_, err := io.WriteString(cw.Wire, "0\r\n")
+	return err
+}
+
+func parseHexUint(v []byte) (n uint64, err error) {
+	for _, b := range v {
+		n <<= 4
+		switch {
+		case '0' <= b && b <= '9':
+			b = b - '0'
+		case 'a' <= b && b <= 'f':
+			b = b - 'a' + 10
+		case 'A' <= b && b <= 'F':
+			b = b - 'A' + 10
+		default:
+			return 0, errors.New("invalid byte in chunk length")
+		}
+		n |= uint64(b)
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/httputil/chunked_test.go b/third_party/gofrontend/libgo/go/net/http/httputil/chunked_test.go
new file mode 100644
index 0000000..a7a5774
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httputil/chunked_test.go
@@ -0,0 +1,159 @@
+// 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.
+
+// This code is duplicated in net/http and net/http/httputil.
+// Please make any changes in both files.
+
+package httputil
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+func TestChunk(t *testing.T) {
+	var b bytes.Buffer
+
+	w := newChunkedWriter(&b)
+	const chunk1 = "hello, "
+	const chunk2 = "world! 0123456789abcdef"
+	w.Write([]byte(chunk1))
+	w.Write([]byte(chunk2))
+	w.Close()
+
+	if g, e := b.String(), "7\r\nhello, \r\n17\r\nworld! 0123456789abcdef\r\n0\r\n"; g != e {
+		t.Fatalf("chunk writer wrote %q; want %q", g, e)
+	}
+
+	r := newChunkedReader(&b)
+	data, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Logf(`data: "%s"`, data)
+		t.Fatalf("ReadAll from reader: %v", err)
+	}
+	if g, e := string(data), chunk1+chunk2; g != e {
+		t.Errorf("chunk reader read %q; want %q", g, e)
+	}
+}
+
+func TestChunkReadMultiple(t *testing.T) {
+	// Bunch of small chunks, all read together.
+	{
+		var b bytes.Buffer
+		w := newChunkedWriter(&b)
+		w.Write([]byte("foo"))
+		w.Write([]byte("bar"))
+		w.Close()
+
+		r := newChunkedReader(&b)
+		buf := make([]byte, 10)
+		n, err := r.Read(buf)
+		if n != 6 || err != io.EOF {
+			t.Errorf("Read = %d, %v; want 6, EOF", n, err)
+		}
+		buf = buf[:n]
+		if string(buf) != "foobar" {
+			t.Errorf("Read = %q; want %q", buf, "foobar")
+		}
+	}
+
+	// One big chunk followed by a little chunk, but the small bufio.Reader size
+	// should prevent the second chunk header from being read.
+	{
+		var b bytes.Buffer
+		w := newChunkedWriter(&b)
+		// fillBufChunk is 11 bytes + 3 bytes header + 2 bytes footer = 16 bytes,
+		// the same as the bufio ReaderSize below (the minimum), so even
+		// though we're going to try to Read with a buffer larger enough to also
+		// receive "foo", the second chunk header won't be read yet.
+		const fillBufChunk = "0123456789a"
+		const shortChunk = "foo"
+		w.Write([]byte(fillBufChunk))
+		w.Write([]byte(shortChunk))
+		w.Close()
+
+		r := newChunkedReader(bufio.NewReaderSize(&b, 16))
+		buf := make([]byte, len(fillBufChunk)+len(shortChunk))
+		n, err := r.Read(buf)
+		if n != len(fillBufChunk) || err != nil {
+			t.Errorf("Read = %d, %v; want %d, nil", n, err, len(fillBufChunk))
+		}
+		buf = buf[:n]
+		if string(buf) != fillBufChunk {
+			t.Errorf("Read = %q; want %q", buf, fillBufChunk)
+		}
+
+		n, err = r.Read(buf)
+		if n != len(shortChunk) || err != io.EOF {
+			t.Errorf("Read = %d, %v; want %d, EOF", n, err, len(shortChunk))
+		}
+	}
+
+	// And test that we see an EOF chunk, even though our buffer is already full:
+	{
+		r := newChunkedReader(bufio.NewReader(strings.NewReader("3\r\nfoo\r\n0\r\n")))
+		buf := make([]byte, 3)
+		n, err := r.Read(buf)
+		if n != 3 || err != io.EOF {
+			t.Errorf("Read = %d, %v; want 3, EOF", n, err)
+		}
+		if string(buf) != "foo" {
+			t.Errorf("buf = %q; want foo", buf)
+		}
+	}
+}
+
+func TestChunkReaderAllocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	var buf bytes.Buffer
+	w := newChunkedWriter(&buf)
+	a, b, c := []byte("aaaaaa"), []byte("bbbbbbbbbbbb"), []byte("cccccccccccccccccccccccc")
+	w.Write(a)
+	w.Write(b)
+	w.Write(c)
+	w.Close()
+
+	readBuf := make([]byte, len(a)+len(b)+len(c)+1)
+	byter := bytes.NewReader(buf.Bytes())
+	bufr := bufio.NewReader(byter)
+	mallocs := testing.AllocsPerRun(100, func() {
+		byter.Seek(0, 0)
+		bufr.Reset(byter)
+		r := newChunkedReader(bufr)
+		n, err := io.ReadFull(r, readBuf)
+		if n != len(readBuf)-1 {
+			t.Fatalf("read %d bytes; want %d", n, len(readBuf)-1)
+		}
+		if err != io.ErrUnexpectedEOF {
+			t.Fatalf("read error = %v; want ErrUnexpectedEOF", err)
+		}
+	})
+	if mallocs > 1.5 {
+		t.Errorf("mallocs = %v; want 1", mallocs)
+	}
+}
+
+func TestParseHexUint(t *testing.T) {
+	for i := uint64(0); i <= 1234; i++ {
+		line := []byte(fmt.Sprintf("%x", i))
+		got, err := parseHexUint(line)
+		if err != nil {
+			t.Fatalf("on %d: %v", i, err)
+		}
+		if got != i {
+			t.Errorf("for input %q = %d; want %d", line, got, i)
+		}
+	}
+	_, err := parseHexUint([]byte("bogus"))
+	if err == nil {
+		t.Error("expected error on bogus input")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/httputil/dump.go b/third_party/gofrontend/libgo/go/net/http/httputil/dump.go
new file mode 100644
index 0000000..2a7a413
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httputil/dump.go
@@ -0,0 +1,276 @@
+// 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 httputil
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"net/url"
+	"strings"
+	"time"
+)
+
+// One of the copies, say from b to r2, could be avoided by using a more
+// elaborate trick where the other copy is made during Request/Response.Write.
+// This would complicate things too much, given that these functions are for
+// debugging only.
+func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) {
+	var buf bytes.Buffer
+	if _, err = buf.ReadFrom(b); err != nil {
+		return nil, nil, err
+	}
+	if err = b.Close(); err != nil {
+		return nil, nil, err
+	}
+	return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
+}
+
+// dumpConn is a net.Conn which writes to Writer and reads from Reader
+type dumpConn struct {
+	io.Writer
+	io.Reader
+}
+
+func (c *dumpConn) Close() error                       { return nil }
+func (c *dumpConn) LocalAddr() net.Addr                { return nil }
+func (c *dumpConn) RemoteAddr() net.Addr               { return nil }
+func (c *dumpConn) SetDeadline(t time.Time) error      { return nil }
+func (c *dumpConn) SetReadDeadline(t time.Time) error  { return nil }
+func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
+
+type neverEnding byte
+
+func (b neverEnding) Read(p []byte) (n int, err error) {
+	for i := range p {
+		p[i] = byte(b)
+	}
+	return len(p), nil
+}
+
+// DumpRequestOut is like DumpRequest but includes
+// headers that the standard http.Transport adds,
+// such as User-Agent.
+func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
+	save := req.Body
+	dummyBody := false
+	if !body || req.Body == nil {
+		req.Body = nil
+		if req.ContentLength != 0 {
+			req.Body = ioutil.NopCloser(io.LimitReader(neverEnding('x'), req.ContentLength))
+			dummyBody = true
+		}
+	} else {
+		var err error
+		save, req.Body, err = drainBody(req.Body)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	// Since we're using the actual Transport code to write the request,
+	// switch to http so the Transport doesn't try to do an SSL
+	// negotiation with our dumpConn and its bytes.Buffer & pipe.
+	// The wire format for https and http are the same, anyway.
+	reqSend := req
+	if req.URL.Scheme == "https" {
+		reqSend = new(http.Request)
+		*reqSend = *req
+		reqSend.URL = new(url.URL)
+		*reqSend.URL = *req.URL
+		reqSend.URL.Scheme = "http"
+	}
+
+	// Use the actual Transport code to record what we would send
+	// on the wire, but not using TCP.  Use a Transport with a
+	// custom dialer that returns a fake net.Conn that waits
+	// for the full input (and recording it), and then responds
+	// with a dummy response.
+	var buf bytes.Buffer // records the output
+	pr, pw := io.Pipe()
+	dr := &delegateReader{c: make(chan io.Reader)}
+	// Wait for the request before replying with a dummy response:
+	go func() {
+		http.ReadRequest(bufio.NewReader(pr))
+		dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\n\r\n")
+	}()
+
+	t := &http.Transport{
+		Dial: func(net, addr string) (net.Conn, error) {
+			return &dumpConn{io.MultiWriter(&buf, pw), dr}, nil
+		},
+	}
+	defer t.CloseIdleConnections()
+
+	_, err := t.RoundTrip(reqSend)
+
+	req.Body = save
+	if err != nil {
+		return nil, err
+	}
+	dump := buf.Bytes()
+
+	// If we used a dummy body above, remove it now.
+	// TODO: if the req.ContentLength is large, we allocate memory
+	// unnecessarily just to slice it off here.  But this is just
+	// a debug function, so this is acceptable for now. We could
+	// discard the body earlier if this matters.
+	if dummyBody {
+		if i := bytes.Index(dump, []byte("\r\n\r\n")); i >= 0 {
+			dump = dump[:i+4]
+		}
+	}
+	return dump, nil
+}
+
+// delegateReader is a reader that delegates to another reader,
+// once it arrives on a channel.
+type delegateReader struct {
+	c chan io.Reader
+	r io.Reader // nil until received from c
+}
+
+func (r *delegateReader) Read(p []byte) (int, error) {
+	if r.r == nil {
+		r.r = <-r.c
+	}
+	return r.r.Read(p)
+}
+
+// Return value if nonempty, def otherwise.
+func valueOrDefault(value, def string) string {
+	if value != "" {
+		return value
+	}
+	return def
+}
+
+var reqWriteExcludeHeaderDump = map[string]bool{
+	"Host":              true, // not in Header map anyway
+	"Content-Length":    true,
+	"Transfer-Encoding": true,
+	"Trailer":           true,
+}
+
+// dumpAsReceived writes req to w in the form as it was received, or
+// at least as accurately as possible from the information retained in
+// the request.
+func dumpAsReceived(req *http.Request, w io.Writer) error {
+	return nil
+}
+
+// DumpRequest returns the as-received wire representation of req,
+// optionally including the request body, for debugging.
+// DumpRequest is semantically a no-op, but in order to
+// dump the body, it reads the body data into memory and
+// changes req.Body to refer to the in-memory copy.
+// The documentation for http.Request.Write details which fields
+// of req are used.
+func DumpRequest(req *http.Request, body bool) (dump []byte, err error) {
+	save := req.Body
+	if !body || req.Body == nil {
+		req.Body = nil
+	} else {
+		save, req.Body, err = drainBody(req.Body)
+		if err != nil {
+			return
+		}
+	}
+
+	var b bytes.Buffer
+
+	fmt.Fprintf(&b, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"),
+		req.URL.RequestURI(), req.ProtoMajor, req.ProtoMinor)
+
+	host := req.Host
+	if host == "" && req.URL != nil {
+		host = req.URL.Host
+	}
+	if host != "" {
+		fmt.Fprintf(&b, "Host: %s\r\n", host)
+	}
+
+	chunked := len(req.TransferEncoding) > 0 && req.TransferEncoding[0] == "chunked"
+	if len(req.TransferEncoding) > 0 {
+		fmt.Fprintf(&b, "Transfer-Encoding: %s\r\n", strings.Join(req.TransferEncoding, ","))
+	}
+	if req.Close {
+		fmt.Fprintf(&b, "Connection: close\r\n")
+	}
+
+	err = req.Header.WriteSubset(&b, reqWriteExcludeHeaderDump)
+	if err != nil {
+		return
+	}
+
+	io.WriteString(&b, "\r\n")
+
+	if req.Body != nil {
+		var dest io.Writer = &b
+		if chunked {
+			dest = NewChunkedWriter(dest)
+		}
+		_, err = io.Copy(dest, req.Body)
+		if chunked {
+			dest.(io.Closer).Close()
+			io.WriteString(&b, "\r\n")
+		}
+	}
+
+	req.Body = save
+	if err != nil {
+		return
+	}
+	dump = b.Bytes()
+	return
+}
+
+// errNoBody is a sentinel error value used by failureToReadBody so we can detect
+// that the lack of body was intentional.
+var errNoBody = errors.New("sentinel error value")
+
+// failureToReadBody is a io.ReadCloser that just returns errNoBody on
+// Read.  It's swapped in when we don't actually want to consume the
+// body, but need a non-nil one, and want to distinguish the error
+// from reading the dummy body.
+type failureToReadBody struct{}
+
+func (failureToReadBody) Read([]byte) (int, error) { return 0, errNoBody }
+func (failureToReadBody) Close() error             { return nil }
+
+var emptyBody = ioutil.NopCloser(strings.NewReader(""))
+
+// DumpResponse is like DumpRequest but dumps a response.
+func DumpResponse(resp *http.Response, body bool) (dump []byte, err error) {
+	var b bytes.Buffer
+	save := resp.Body
+	savecl := resp.ContentLength
+
+	if !body {
+		resp.Body = failureToReadBody{}
+	} else if resp.Body == nil {
+		resp.Body = emptyBody
+	} else {
+		save, resp.Body, err = drainBody(resp.Body)
+		if err != nil {
+			return
+		}
+	}
+	err = resp.Write(&b)
+	if err == errNoBody {
+		err = nil
+	}
+	resp.Body = save
+	resp.ContentLength = savecl
+	if err != nil {
+		return nil, err
+	}
+	return b.Bytes(), nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/httputil/dump_test.go b/third_party/gofrontend/libgo/go/net/http/httputil/dump_test.go
new file mode 100644
index 0000000..e1ffb39
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httputil/dump_test.go
@@ -0,0 +1,263 @@
+// 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.
+
+package httputil
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+type dumpTest struct {
+	Req  http.Request
+	Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body
+
+	WantDump    string
+	WantDumpOut string
+	NoBody      bool // if true, set DumpRequest{,Out} body to false
+}
+
+var dumpTests = []dumpTest{
+
+	// HTTP/1.1 => chunked coding; body; empty trailer
+	{
+		Req: http.Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Path:   "/search",
+			},
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			TransferEncoding: []string{"chunked"},
+		},
+
+		Body: []byte("abcdef"),
+
+		WantDump: "GET /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("abcdef") + chunk(""),
+	},
+
+	// Verify that DumpRequest preserves the HTTP version number, doesn't add a Host,
+	// and doesn't add a User-Agent.
+	{
+		Req: http.Request{
+			Method:     "GET",
+			URL:        mustParseURL("/foo"),
+			ProtoMajor: 1,
+			ProtoMinor: 0,
+			Header: http.Header{
+				"X-Foo": []string{"X-Bar"},
+			},
+		},
+
+		WantDump: "GET /foo HTTP/1.0\r\n" +
+			"X-Foo: X-Bar\r\n\r\n",
+	},
+
+	{
+		Req: *mustNewRequest("GET", "http://example.com/foo", nil),
+
+		WantDumpOut: "GET /foo HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Accept-Encoding: gzip\r\n\r\n",
+	},
+
+	// Test that an https URL doesn't try to do an SSL negotiation
+	// with a bytes.Buffer and hang with all goroutines not
+	// runnable.
+	{
+		Req: *mustNewRequest("GET", "https://example.com/foo", nil),
+
+		WantDumpOut: "GET /foo HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Accept-Encoding: gzip\r\n\r\n",
+	},
+
+	// Request with Body, but Dump requested without it.
+	{
+		Req: http.Request{
+			Method: "POST",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "post.tld",
+				Path:   "/",
+			},
+			ContentLength: 6,
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+		},
+
+		Body: []byte("abcdef"),
+
+		WantDumpOut: "POST / HTTP/1.1\r\n" +
+			"Host: post.tld\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Content-Length: 6\r\n" +
+			"Accept-Encoding: gzip\r\n\r\n",
+
+		NoBody: true,
+	},
+}
+
+func TestDumpRequest(t *testing.T) {
+	numg0 := runtime.NumGoroutine()
+	for i, tt := range dumpTests {
+		setBody := func() {
+			if tt.Body == nil {
+				return
+			}
+			switch b := tt.Body.(type) {
+			case []byte:
+				tt.Req.Body = ioutil.NopCloser(bytes.NewReader(b))
+			case func() io.ReadCloser:
+				tt.Req.Body = b()
+			}
+		}
+		setBody()
+		if tt.Req.Header == nil {
+			tt.Req.Header = make(http.Header)
+		}
+
+		if tt.WantDump != "" {
+			setBody()
+			dump, err := DumpRequest(&tt.Req, !tt.NoBody)
+			if err != nil {
+				t.Errorf("DumpRequest #%d: %s", i, err)
+				continue
+			}
+			if string(dump) != tt.WantDump {
+				t.Errorf("DumpRequest %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantDump, string(dump))
+				continue
+			}
+		}
+
+		if tt.WantDumpOut != "" {
+			setBody()
+			dump, err := DumpRequestOut(&tt.Req, !tt.NoBody)
+			if err != nil {
+				t.Errorf("DumpRequestOut #%d: %s", i, err)
+				continue
+			}
+			if string(dump) != tt.WantDumpOut {
+				t.Errorf("DumpRequestOut %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantDumpOut, string(dump))
+				continue
+			}
+		}
+	}
+	if dg := runtime.NumGoroutine() - numg0; dg > 4 {
+		t.Errorf("Unexpectedly large number of new goroutines: %d new", dg)
+	}
+}
+
+func chunk(s string) string {
+	return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
+}
+
+func mustParseURL(s string) *url.URL {
+	u, err := url.Parse(s)
+	if err != nil {
+		panic(fmt.Sprintf("Error parsing URL %q: %v", s, err))
+	}
+	return u
+}
+
+func mustNewRequest(method, url string, body io.Reader) *http.Request {
+	req, err := http.NewRequest(method, url, body)
+	if err != nil {
+		panic(fmt.Sprintf("NewRequest(%q, %q, %p) err = %v", method, url, body, err))
+	}
+	return req
+}
+
+var dumpResTests = []struct {
+	res  *http.Response
+	body bool
+	want string
+}{
+	{
+		res: &http.Response{
+			Status:        "200 OK",
+			StatusCode:    200,
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 50,
+			Header: http.Header{
+				"Foo": []string{"Bar"},
+			},
+			Body: ioutil.NopCloser(strings.NewReader("foo")), // shouldn't be used
+		},
+		body: false, // to verify we see 50, not empty or 3.
+		want: `HTTP/1.1 200 OK
+Content-Length: 50
+Foo: Bar`,
+	},
+
+	{
+		res: &http.Response{
+			Status:        "200 OK",
+			StatusCode:    200,
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 3,
+			Body:          ioutil.NopCloser(strings.NewReader("foo")),
+		},
+		body: true,
+		want: `HTTP/1.1 200 OK
+Content-Length: 3
+
+foo`,
+	},
+
+	{
+		res: &http.Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.1",
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			ContentLength:    -1,
+			Body:             ioutil.NopCloser(strings.NewReader("foo")),
+			TransferEncoding: []string{"chunked"},
+		},
+		body: true,
+		want: `HTTP/1.1 200 OK
+Transfer-Encoding: chunked
+
+3
+foo
+0`,
+	},
+}
+
+func TestDumpResponse(t *testing.T) {
+	for i, tt := range dumpResTests {
+		gotb, err := DumpResponse(tt.res, tt.body)
+		if err != nil {
+			t.Errorf("%d. DumpResponse = %v", i, err)
+			continue
+		}
+		got := string(gotb)
+		got = strings.TrimSpace(got)
+		got = strings.Replace(got, "\r", "", -1)
+
+		if got != tt.want {
+			t.Errorf("%d.\nDumpResponse got:\n%s\n\nWant:\n%s\n", i, got, tt.want)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/httputil/httputil.go b/third_party/gofrontend/libgo/go/net/http/httputil/httputil.go
new file mode 100644
index 0000000..74fb6c6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httputil/httputil.go
@@ -0,0 +1,32 @@
+// Copyright 2014 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 httputil provides HTTP utility functions, complementing the
+// more common ones in the net/http package.
+package httputil
+
+import "io"
+
+// NewChunkedReader returns a new chunkedReader that translates the data read from r
+// out of HTTP "chunked" format before returning it.
+// The chunkedReader returns io.EOF when the final 0-length chunk is read.
+//
+// NewChunkedReader is not needed by normal applications. The http package
+// automatically decodes chunking when reading response bodies.
+func NewChunkedReader(r io.Reader) io.Reader {
+	return newChunkedReader(r)
+}
+
+// NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP
+// "chunked" format before writing them to w. Closing the returned chunkedWriter
+// sends the final 0-length chunk that marks the end of the stream.
+//
+// NewChunkedWriter is not needed by normal applications. The http
+// package adds chunking automatically if handlers don't set a
+// Content-Length header. Using NewChunkedWriter inside a handler
+// would result in double chunking or chunking with a Content-Length
+// length, both of which are wrong.
+func NewChunkedWriter(w io.Writer) io.WriteCloser {
+	return newChunkedWriter(w)
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/httputil/persist.go b/third_party/gofrontend/libgo/go/net/http/httputil/persist.go
new file mode 100644
index 0000000..987bcc9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httputil/persist.go
@@ -0,0 +1,429 @@
+// 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 httputil
+
+import (
+	"bufio"
+	"errors"
+	"io"
+	"net"
+	"net/http"
+	"net/textproto"
+	"sync"
+)
+
+var (
+	ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"}
+	ErrClosed     = &http.ProtocolError{ErrorString: "connection closed by user"}
+	ErrPipeline   = &http.ProtocolError{ErrorString: "pipeline error"}
+)
+
+// This is an API usage error - the local side is closed.
+// ErrPersistEOF (above) reports that the remote side is closed.
+var errClosed = errors.New("i/o operation on closed connection")
+
+// A ServerConn reads requests and sends responses over an underlying
+// connection, until the HTTP keepalive logic commands an end. ServerConn
+// also allows hijacking the underlying connection by calling Hijack
+// to regain control over the connection. ServerConn supports pipe-lining,
+// i.e. requests can be read out of sync (but in the same order) while the
+// respective responses are sent.
+//
+// ServerConn is low-level and old. Applications should instead use Server
+// in the net/http package.
+type ServerConn struct {
+	lk              sync.Mutex // read-write protects the following fields
+	c               net.Conn
+	r               *bufio.Reader
+	re, we          error // read/write errors
+	lastbody        io.ReadCloser
+	nread, nwritten int
+	pipereq         map[*http.Request]uint
+
+	pipe textproto.Pipeline
+}
+
+// NewServerConn returns a new ServerConn reading and writing c. If r is not
+// nil, it is the buffer to use when reading c.
+//
+// ServerConn is low-level and old. Applications should instead use Server
+// in the net/http package.
+func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
+	if r == nil {
+		r = bufio.NewReader(c)
+	}
+	return &ServerConn{c: c, r: r, pipereq: make(map[*http.Request]uint)}
+}
+
+// Hijack detaches the ServerConn and returns the underlying connection as well
+// as the read-side bufio which may have some left over data. Hijack may be
+// called before Read has signaled the end of the keep-alive logic. The user
+// should not call Hijack while Read or Write is in progress.
+func (sc *ServerConn) Hijack() (c net.Conn, r *bufio.Reader) {
+	sc.lk.Lock()
+	defer sc.lk.Unlock()
+	c = sc.c
+	r = sc.r
+	sc.c = nil
+	sc.r = nil
+	return
+}
+
+// Close calls Hijack and then also closes the underlying connection
+func (sc *ServerConn) Close() error {
+	c, _ := sc.Hijack()
+	if c != nil {
+		return c.Close()
+	}
+	return nil
+}
+
+// Read returns the next request on the wire. An ErrPersistEOF is returned if
+// it is gracefully determined that there are no more requests (e.g. after the
+// first request on an HTTP/1.0 connection, or after a Connection:close on a
+// HTTP/1.1 connection).
+func (sc *ServerConn) Read() (req *http.Request, err error) {
+
+	// Ensure ordered execution of Reads and Writes
+	id := sc.pipe.Next()
+	sc.pipe.StartRequest(id)
+	defer func() {
+		sc.pipe.EndRequest(id)
+		if req == nil {
+			sc.pipe.StartResponse(id)
+			sc.pipe.EndResponse(id)
+		} else {
+			// Remember the pipeline id of this request
+			sc.lk.Lock()
+			sc.pipereq[req] = id
+			sc.lk.Unlock()
+		}
+	}()
+
+	sc.lk.Lock()
+	if sc.we != nil { // no point receiving if write-side broken or closed
+		defer sc.lk.Unlock()
+		return nil, sc.we
+	}
+	if sc.re != nil {
+		defer sc.lk.Unlock()
+		return nil, sc.re
+	}
+	if sc.r == nil { // connection closed by user in the meantime
+		defer sc.lk.Unlock()
+		return nil, errClosed
+	}
+	r := sc.r
+	lastbody := sc.lastbody
+	sc.lastbody = nil
+	sc.lk.Unlock()
+
+	// Make sure body is fully consumed, even if user does not call body.Close
+	if lastbody != nil {
+		// body.Close is assumed to be idempotent and multiple calls to
+		// it should return the error that its first invocation
+		// returned.
+		err = lastbody.Close()
+		if err != nil {
+			sc.lk.Lock()
+			defer sc.lk.Unlock()
+			sc.re = err
+			return nil, err
+		}
+	}
+
+	req, err = http.ReadRequest(r)
+	sc.lk.Lock()
+	defer sc.lk.Unlock()
+	if err != nil {
+		if err == io.ErrUnexpectedEOF {
+			// A close from the opposing client is treated as a
+			// graceful close, even if there was some unparse-able
+			// data before the close.
+			sc.re = ErrPersistEOF
+			return nil, sc.re
+		} else {
+			sc.re = err
+			return req, err
+		}
+	}
+	sc.lastbody = req.Body
+	sc.nread++
+	if req.Close {
+		sc.re = ErrPersistEOF
+		return req, sc.re
+	}
+	return req, err
+}
+
+// Pending returns the number of unanswered requests
+// that have been received on the connection.
+func (sc *ServerConn) Pending() int {
+	sc.lk.Lock()
+	defer sc.lk.Unlock()
+	return sc.nread - sc.nwritten
+}
+
+// Write writes resp in response to req. To close the connection gracefully, set the
+// Response.Close field to true. Write should be considered operational until
+// it returns an error, regardless of any errors returned on the Read side.
+func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error {
+
+	// Retrieve the pipeline ID of this request/response pair
+	sc.lk.Lock()
+	id, ok := sc.pipereq[req]
+	delete(sc.pipereq, req)
+	if !ok {
+		sc.lk.Unlock()
+		return ErrPipeline
+	}
+	sc.lk.Unlock()
+
+	// Ensure pipeline order
+	sc.pipe.StartResponse(id)
+	defer sc.pipe.EndResponse(id)
+
+	sc.lk.Lock()
+	if sc.we != nil {
+		defer sc.lk.Unlock()
+		return sc.we
+	}
+	if sc.c == nil { // connection closed by user in the meantime
+		defer sc.lk.Unlock()
+		return ErrClosed
+	}
+	c := sc.c
+	if sc.nread <= sc.nwritten {
+		defer sc.lk.Unlock()
+		return errors.New("persist server pipe count")
+	}
+	if resp.Close {
+		// After signaling a keep-alive close, any pipelined unread
+		// requests will be lost. It is up to the user to drain them
+		// before signaling.
+		sc.re = ErrPersistEOF
+	}
+	sc.lk.Unlock()
+
+	err := resp.Write(c)
+	sc.lk.Lock()
+	defer sc.lk.Unlock()
+	if err != nil {
+		sc.we = err
+		return err
+	}
+	sc.nwritten++
+
+	return nil
+}
+
+// A ClientConn sends request and receives headers over an underlying
+// connection, while respecting the HTTP keepalive logic. ClientConn
+// supports hijacking the connection calling Hijack to
+// regain control of the underlying net.Conn and deal with it as desired.
+//
+// ClientConn is low-level and old. Applications should instead use
+// Client or Transport in the net/http package.
+type ClientConn struct {
+	lk              sync.Mutex // read-write protects the following fields
+	c               net.Conn
+	r               *bufio.Reader
+	re, we          error // read/write errors
+	lastbody        io.ReadCloser
+	nread, nwritten int
+	pipereq         map[*http.Request]uint
+
+	pipe     textproto.Pipeline
+	writeReq func(*http.Request, io.Writer) error
+}
+
+// NewClientConn returns a new ClientConn reading and writing c.  If r is not
+// nil, it is the buffer to use when reading c.
+//
+// ClientConn is low-level and old. Applications should use Client or
+// Transport in the net/http package.
+func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
+	if r == nil {
+		r = bufio.NewReader(c)
+	}
+	return &ClientConn{
+		c:        c,
+		r:        r,
+		pipereq:  make(map[*http.Request]uint),
+		writeReq: (*http.Request).Write,
+	}
+}
+
+// NewProxyClientConn works like NewClientConn but writes Requests
+// using Request's WriteProxy method.
+//
+// New code should not use NewProxyClientConn. See Client or
+// Transport in the net/http package instead.
+func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
+	cc := NewClientConn(c, r)
+	cc.writeReq = (*http.Request).WriteProxy
+	return cc
+}
+
+// Hijack detaches the ClientConn and returns the underlying connection as well
+// as the read-side bufio which may have some left over data. Hijack may be
+// called before the user or Read have signaled the end of the keep-alive
+// logic. The user should not call Hijack while Read or Write is in progress.
+func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
+	cc.lk.Lock()
+	defer cc.lk.Unlock()
+	c = cc.c
+	r = cc.r
+	cc.c = nil
+	cc.r = nil
+	return
+}
+
+// Close calls Hijack and then also closes the underlying connection
+func (cc *ClientConn) Close() error {
+	c, _ := cc.Hijack()
+	if c != nil {
+		return c.Close()
+	}
+	return nil
+}
+
+// Write writes a request. An ErrPersistEOF error is returned if the connection
+// has been closed in an HTTP keepalive sense. If req.Close equals true, the
+// keepalive connection is logically closed after this request and the opposing
+// server is informed. An ErrUnexpectedEOF indicates the remote closed the
+// underlying TCP connection, which is usually considered as graceful close.
+func (cc *ClientConn) Write(req *http.Request) (err error) {
+
+	// Ensure ordered execution of Writes
+	id := cc.pipe.Next()
+	cc.pipe.StartRequest(id)
+	defer func() {
+		cc.pipe.EndRequest(id)
+		if err != nil {
+			cc.pipe.StartResponse(id)
+			cc.pipe.EndResponse(id)
+		} else {
+			// Remember the pipeline id of this request
+			cc.lk.Lock()
+			cc.pipereq[req] = id
+			cc.lk.Unlock()
+		}
+	}()
+
+	cc.lk.Lock()
+	if cc.re != nil { // no point sending if read-side closed or broken
+		defer cc.lk.Unlock()
+		return cc.re
+	}
+	if cc.we != nil {
+		defer cc.lk.Unlock()
+		return cc.we
+	}
+	if cc.c == nil { // connection closed by user in the meantime
+		defer cc.lk.Unlock()
+		return errClosed
+	}
+	c := cc.c
+	if req.Close {
+		// We write the EOF to the write-side error, because there
+		// still might be some pipelined reads
+		cc.we = ErrPersistEOF
+	}
+	cc.lk.Unlock()
+
+	err = cc.writeReq(req, c)
+	cc.lk.Lock()
+	defer cc.lk.Unlock()
+	if err != nil {
+		cc.we = err
+		return err
+	}
+	cc.nwritten++
+
+	return nil
+}
+
+// Pending returns the number of unanswered requests
+// that have been sent on the connection.
+func (cc *ClientConn) Pending() int {
+	cc.lk.Lock()
+	defer cc.lk.Unlock()
+	return cc.nwritten - cc.nread
+}
+
+// Read reads the next response from the wire. A valid response might be
+// returned together with an ErrPersistEOF, which means that the remote
+// requested that this be the last request serviced. Read can be called
+// concurrently with Write, but not with another Read.
+func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error) {
+	// Retrieve the pipeline ID of this request/response pair
+	cc.lk.Lock()
+	id, ok := cc.pipereq[req]
+	delete(cc.pipereq, req)
+	if !ok {
+		cc.lk.Unlock()
+		return nil, ErrPipeline
+	}
+	cc.lk.Unlock()
+
+	// Ensure pipeline order
+	cc.pipe.StartResponse(id)
+	defer cc.pipe.EndResponse(id)
+
+	cc.lk.Lock()
+	if cc.re != nil {
+		defer cc.lk.Unlock()
+		return nil, cc.re
+	}
+	if cc.r == nil { // connection closed by user in the meantime
+		defer cc.lk.Unlock()
+		return nil, errClosed
+	}
+	r := cc.r
+	lastbody := cc.lastbody
+	cc.lastbody = nil
+	cc.lk.Unlock()
+
+	// Make sure body is fully consumed, even if user does not call body.Close
+	if lastbody != nil {
+		// body.Close is assumed to be idempotent and multiple calls to
+		// it should return the error that its first invocation
+		// returned.
+		err = lastbody.Close()
+		if err != nil {
+			cc.lk.Lock()
+			defer cc.lk.Unlock()
+			cc.re = err
+			return nil, err
+		}
+	}
+
+	resp, err = http.ReadResponse(r, req)
+	cc.lk.Lock()
+	defer cc.lk.Unlock()
+	if err != nil {
+		cc.re = err
+		return resp, err
+	}
+	cc.lastbody = resp.Body
+
+	cc.nread++
+
+	if resp.Close {
+		cc.re = ErrPersistEOF // don't send any more requests
+		return resp, cc.re
+	}
+	return resp, err
+}
+
+// Do is convenience method that writes a request and reads a response.
+func (cc *ClientConn) Do(req *http.Request) (resp *http.Response, err error) {
+	err = cc.Write(req)
+	if err != nil {
+		return
+	}
+	return cc.Read(req)
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/httputil/reverseproxy.go b/third_party/gofrontend/libgo/go/net/http/httputil/reverseproxy.go
new file mode 100644
index 0000000..48ada5f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httputil/reverseproxy.go
@@ -0,0 +1,211 @@
+// 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.
+
+// HTTP reverse proxy handler
+
+package httputil
+
+import (
+	"io"
+	"log"
+	"net"
+	"net/http"
+	"net/url"
+	"strings"
+	"sync"
+	"time"
+)
+
+// onExitFlushLoop is a callback set by tests to detect the state of the
+// flushLoop() goroutine.
+var onExitFlushLoop func()
+
+// ReverseProxy is an HTTP Handler that takes an incoming request and
+// sends it to another server, proxying the response back to the
+// client.
+type ReverseProxy struct {
+	// Director must be a function which modifies
+	// the request into a new request to be sent
+	// using Transport. Its response is then copied
+	// back to the original client unmodified.
+	Director func(*http.Request)
+
+	// The transport used to perform proxy requests.
+	// If nil, http.DefaultTransport is used.
+	Transport http.RoundTripper
+
+	// FlushInterval specifies the flush interval
+	// to flush to the client while copying the
+	// response body.
+	// If zero, no periodic flushing is done.
+	FlushInterval time.Duration
+}
+
+func singleJoiningSlash(a, b string) string {
+	aslash := strings.HasSuffix(a, "/")
+	bslash := strings.HasPrefix(b, "/")
+	switch {
+	case aslash && bslash:
+		return a + b[1:]
+	case !aslash && !bslash:
+		return a + "/" + b
+	}
+	return a + b
+}
+
+// NewSingleHostReverseProxy returns a new ReverseProxy that rewrites
+// URLs to the scheme, host, and base path provided in target. If the
+// target's path is "/base" and the incoming request was for "/dir",
+// the target request will be for /base/dir.
+func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
+	targetQuery := target.RawQuery
+	director := func(req *http.Request) {
+		req.URL.Scheme = target.Scheme
+		req.URL.Host = target.Host
+		req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
+		if targetQuery == "" || req.URL.RawQuery == "" {
+			req.URL.RawQuery = targetQuery + req.URL.RawQuery
+		} else {
+			req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
+		}
+	}
+	return &ReverseProxy{Director: director}
+}
+
+func copyHeader(dst, src http.Header) {
+	for k, vv := range src {
+		for _, v := range vv {
+			dst.Add(k, v)
+		}
+	}
+}
+
+// Hop-by-hop headers. These are removed when sent to the backend.
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
+var hopHeaders = []string{
+	"Connection",
+	"Keep-Alive",
+	"Proxy-Authenticate",
+	"Proxy-Authorization",
+	"Te", // canonicalized version of "TE"
+	"Trailers",
+	"Transfer-Encoding",
+	"Upgrade",
+}
+
+func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+	transport := p.Transport
+	if transport == nil {
+		transport = http.DefaultTransport
+	}
+
+	outreq := new(http.Request)
+	*outreq = *req // includes shallow copies of maps, but okay
+
+	p.Director(outreq)
+	outreq.Proto = "HTTP/1.1"
+	outreq.ProtoMajor = 1
+	outreq.ProtoMinor = 1
+	outreq.Close = false
+
+	// Remove hop-by-hop headers to the backend.  Especially
+	// important is "Connection" because we want a persistent
+	// connection, regardless of what the client sent to us.  This
+	// is modifying the same underlying map from req (shallow
+	// copied above) so we only copy it if necessary.
+	copiedHeaders := false
+	for _, h := range hopHeaders {
+		if outreq.Header.Get(h) != "" {
+			if !copiedHeaders {
+				outreq.Header = make(http.Header)
+				copyHeader(outreq.Header, req.Header)
+				copiedHeaders = true
+			}
+			outreq.Header.Del(h)
+		}
+	}
+
+	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
+		// If we aren't the first proxy retain prior
+		// X-Forwarded-For information as a comma+space
+		// separated list and fold multiple headers into one.
+		if prior, ok := outreq.Header["X-Forwarded-For"]; ok {
+			clientIP = strings.Join(prior, ", ") + ", " + clientIP
+		}
+		outreq.Header.Set("X-Forwarded-For", clientIP)
+	}
+
+	res, err := transport.RoundTrip(outreq)
+	if err != nil {
+		log.Printf("http: proxy error: %v", err)
+		rw.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+	defer res.Body.Close()
+
+	for _, h := range hopHeaders {
+		res.Header.Del(h)
+	}
+
+	copyHeader(rw.Header(), res.Header)
+
+	rw.WriteHeader(res.StatusCode)
+	p.copyResponse(rw, res.Body)
+}
+
+func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader) {
+	if p.FlushInterval != 0 {
+		if wf, ok := dst.(writeFlusher); ok {
+			mlw := &maxLatencyWriter{
+				dst:     wf,
+				latency: p.FlushInterval,
+				done:    make(chan bool),
+			}
+			go mlw.flushLoop()
+			defer mlw.stop()
+			dst = mlw
+		}
+	}
+
+	io.Copy(dst, src)
+}
+
+type writeFlusher interface {
+	io.Writer
+	http.Flusher
+}
+
+type maxLatencyWriter struct {
+	dst     writeFlusher
+	latency time.Duration
+
+	lk   sync.Mutex // protects Write + Flush
+	done chan bool
+}
+
+func (m *maxLatencyWriter) Write(p []byte) (int, error) {
+	m.lk.Lock()
+	defer m.lk.Unlock()
+	return m.dst.Write(p)
+}
+
+func (m *maxLatencyWriter) flushLoop() {
+	t := time.NewTicker(m.latency)
+	defer t.Stop()
+	for {
+		select {
+		case <-m.done:
+			if onExitFlushLoop != nil {
+				onExitFlushLoop()
+			}
+			return
+		case <-t.C:
+			m.lk.Lock()
+			m.dst.Flush()
+			m.lk.Unlock()
+		}
+	}
+}
+
+func (m *maxLatencyWriter) stop() { m.done <- true }
diff --git a/third_party/gofrontend/libgo/go/net/http/httputil/reverseproxy_test.go b/third_party/gofrontend/libgo/go/net/http/httputil/reverseproxy_test.go
new file mode 100644
index 0000000..e9539b4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/httputil/reverseproxy_test.go
@@ -0,0 +1,213 @@
+// 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.
+
+// Reverse proxy tests.
+
+package httputil
+
+import (
+	"io/ioutil"
+	"net/http"
+	"net/http/httptest"
+	"net/url"
+	"strings"
+	"testing"
+	"time"
+)
+
+const fakeHopHeader = "X-Fake-Hop-Header-For-Test"
+
+func init() {
+	hopHeaders = append(hopHeaders, fakeHopHeader)
+}
+
+func TestReverseProxy(t *testing.T) {
+	const backendResponse = "I am the backend"
+	const backendStatus = 404
+	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if len(r.TransferEncoding) > 0 {
+			t.Errorf("backend got unexpected TransferEncoding: %v", r.TransferEncoding)
+		}
+		if r.Header.Get("X-Forwarded-For") == "" {
+			t.Errorf("didn't get X-Forwarded-For header")
+		}
+		if c := r.Header.Get("Connection"); c != "" {
+			t.Errorf("handler got Connection header value %q", c)
+		}
+		if c := r.Header.Get("Upgrade"); c != "" {
+			t.Errorf("handler got Upgrade header value %q", c)
+		}
+		if g, e := r.Host, "some-name"; g != e {
+			t.Errorf("backend got Host header %q, want %q", g, e)
+		}
+		w.Header().Set("X-Foo", "bar")
+		w.Header().Set("Upgrade", "foo")
+		w.Header().Set(fakeHopHeader, "foo")
+		w.Header().Add("X-Multi-Value", "foo")
+		w.Header().Add("X-Multi-Value", "bar")
+		http.SetCookie(w, &http.Cookie{Name: "flavor", Value: "chocolateChip"})
+		w.WriteHeader(backendStatus)
+		w.Write([]byte(backendResponse))
+	}))
+	defer backend.Close()
+	backendURL, err := url.Parse(backend.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	proxyHandler := NewSingleHostReverseProxy(backendURL)
+	frontend := httptest.NewServer(proxyHandler)
+	defer frontend.Close()
+
+	getReq, _ := http.NewRequest("GET", frontend.URL, nil)
+	getReq.Host = "some-name"
+	getReq.Header.Set("Connection", "close")
+	getReq.Header.Set("Upgrade", "foo")
+	getReq.Close = true
+	res, err := http.DefaultClient.Do(getReq)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	if g, e := res.StatusCode, backendStatus; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	if g, e := res.Header.Get("X-Foo"), "bar"; g != e {
+		t.Errorf("got X-Foo %q; expected %q", g, e)
+	}
+	if c := res.Header.Get(fakeHopHeader); c != "" {
+		t.Errorf("got %s header value %q", fakeHopHeader, c)
+	}
+	if g, e := len(res.Header["X-Multi-Value"]), 2; g != e {
+		t.Errorf("got %d X-Multi-Value header values; expected %d", g, e)
+	}
+	if g, e := len(res.Header["Set-Cookie"]), 1; g != e {
+		t.Fatalf("got %d SetCookies, want %d", g, e)
+	}
+	if cookie := res.Cookies()[0]; cookie.Name != "flavor" {
+		t.Errorf("unexpected cookie %q", cookie.Name)
+	}
+	bodyBytes, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(bodyBytes), backendResponse; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+}
+
+func TestXForwardedFor(t *testing.T) {
+	const prevForwardedFor = "client ip"
+	const backendResponse = "I am the backend"
+	const backendStatus = 404
+	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.Header.Get("X-Forwarded-For") == "" {
+			t.Errorf("didn't get X-Forwarded-For header")
+		}
+		if !strings.Contains(r.Header.Get("X-Forwarded-For"), prevForwardedFor) {
+			t.Errorf("X-Forwarded-For didn't contain prior data")
+		}
+		w.WriteHeader(backendStatus)
+		w.Write([]byte(backendResponse))
+	}))
+	defer backend.Close()
+	backendURL, err := url.Parse(backend.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	proxyHandler := NewSingleHostReverseProxy(backendURL)
+	frontend := httptest.NewServer(proxyHandler)
+	defer frontend.Close()
+
+	getReq, _ := http.NewRequest("GET", frontend.URL, nil)
+	getReq.Host = "some-name"
+	getReq.Header.Set("Connection", "close")
+	getReq.Header.Set("X-Forwarded-For", prevForwardedFor)
+	getReq.Close = true
+	res, err := http.DefaultClient.Do(getReq)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	if g, e := res.StatusCode, backendStatus; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	bodyBytes, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(bodyBytes), backendResponse; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+}
+
+var proxyQueryTests = []struct {
+	baseSuffix string // suffix to add to backend URL
+	reqSuffix  string // suffix to add to frontend's request URL
+	want       string // what backend should see for final request URL (without ?)
+}{
+	{"", "", ""},
+	{"?sta=tic", "?us=er", "sta=tic&us=er"},
+	{"", "?us=er", "us=er"},
+	{"?sta=tic", "", "sta=tic"},
+}
+
+func TestReverseProxyQuery(t *testing.T) {
+	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("X-Got-Query", r.URL.RawQuery)
+		w.Write([]byte("hi"))
+	}))
+	defer backend.Close()
+
+	for i, tt := range proxyQueryTests {
+		backendURL, err := url.Parse(backend.URL + tt.baseSuffix)
+		if err != nil {
+			t.Fatal(err)
+		}
+		frontend := httptest.NewServer(NewSingleHostReverseProxy(backendURL))
+		req, _ := http.NewRequest("GET", frontend.URL+tt.reqSuffix, nil)
+		req.Close = true
+		res, err := http.DefaultClient.Do(req)
+		if err != nil {
+			t.Fatalf("%d. Get: %v", i, err)
+		}
+		if g, e := res.Header.Get("X-Got-Query"), tt.want; g != e {
+			t.Errorf("%d. got query %q; expected %q", i, g, e)
+		}
+		res.Body.Close()
+		frontend.Close()
+	}
+}
+
+func TestReverseProxyFlushInterval(t *testing.T) {
+	const expected = "hi"
+	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Write([]byte(expected))
+	}))
+	defer backend.Close()
+
+	backendURL, err := url.Parse(backend.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	proxyHandler := NewSingleHostReverseProxy(backendURL)
+	proxyHandler.FlushInterval = time.Microsecond
+
+	done := make(chan bool)
+	onExitFlushLoop = func() { done <- true }
+	defer func() { onExitFlushLoop = nil }()
+
+	frontend := httptest.NewServer(proxyHandler)
+	defer frontend.Close()
+
+	req, _ := http.NewRequest("GET", frontend.URL, nil)
+	req.Close = true
+	res, err := http.DefaultClient.Do(req)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	defer res.Body.Close()
+	if bodyBytes, _ := ioutil.ReadAll(res.Body); string(bodyBytes) != expected {
+		t.Errorf("got body %q; expected %q", bodyBytes, expected)
+	}
+
+	select {
+	case <-done:
+		// OK
+	case <-time.After(5 * time.Second):
+		t.Error("maxLatencyWriter flushLoop() never exited")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/jar.go b/third_party/gofrontend/libgo/go/net/http/jar.go
new file mode 100644
index 0000000..5c3de0d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/jar.go
@@ -0,0 +1,27 @@
+// 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.
+
+package http
+
+import (
+	"net/url"
+)
+
+// A CookieJar manages storage and use of cookies in HTTP requests.
+//
+// Implementations of CookieJar must be safe for concurrent use by multiple
+// goroutines.
+//
+// The net/http/cookiejar package provides a CookieJar implementation.
+type CookieJar interface {
+	// SetCookies handles the receipt of the cookies in a reply for the
+	// given URL.  It may or may not choose to save the cookies, depending
+	// on the jar's policy and implementation.
+	SetCookies(u *url.URL, cookies []*Cookie)
+
+	// Cookies returns the cookies to send in a request for the given URL.
+	// It is up to the implementation to honor the standard cookie use
+	// restrictions such as in RFC 6265.
+	Cookies(u *url.URL) []*Cookie
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/lex.go b/third_party/gofrontend/libgo/go/net/http/lex.go
new file mode 100644
index 0000000..cb33318
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/lex.go
@@ -0,0 +1,96 @@
+// 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 http
+
+// This file deals with lexical matters of HTTP
+
+var isTokenTable = [127]bool{
+	'!':  true,
+	'#':  true,
+	'$':  true,
+	'%':  true,
+	'&':  true,
+	'\'': true,
+	'*':  true,
+	'+':  true,
+	'-':  true,
+	'.':  true,
+	'0':  true,
+	'1':  true,
+	'2':  true,
+	'3':  true,
+	'4':  true,
+	'5':  true,
+	'6':  true,
+	'7':  true,
+	'8':  true,
+	'9':  true,
+	'A':  true,
+	'B':  true,
+	'C':  true,
+	'D':  true,
+	'E':  true,
+	'F':  true,
+	'G':  true,
+	'H':  true,
+	'I':  true,
+	'J':  true,
+	'K':  true,
+	'L':  true,
+	'M':  true,
+	'N':  true,
+	'O':  true,
+	'P':  true,
+	'Q':  true,
+	'R':  true,
+	'S':  true,
+	'T':  true,
+	'U':  true,
+	'W':  true,
+	'V':  true,
+	'X':  true,
+	'Y':  true,
+	'Z':  true,
+	'^':  true,
+	'_':  true,
+	'`':  true,
+	'a':  true,
+	'b':  true,
+	'c':  true,
+	'd':  true,
+	'e':  true,
+	'f':  true,
+	'g':  true,
+	'h':  true,
+	'i':  true,
+	'j':  true,
+	'k':  true,
+	'l':  true,
+	'm':  true,
+	'n':  true,
+	'o':  true,
+	'p':  true,
+	'q':  true,
+	'r':  true,
+	's':  true,
+	't':  true,
+	'u':  true,
+	'v':  true,
+	'w':  true,
+	'x':  true,
+	'y':  true,
+	'z':  true,
+	'|':  true,
+	'~':  true,
+}
+
+func isToken(r rune) bool {
+	i := int(r)
+	return i < len(isTokenTable) && isTokenTable[i]
+}
+
+func isNotToken(r rune) bool {
+	return !isToken(r)
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/lex_test.go b/third_party/gofrontend/libgo/go/net/http/lex_test.go
new file mode 100644
index 0000000..6d9d294
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/lex_test.go
@@ -0,0 +1,31 @@
+// 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 http
+
+import (
+	"testing"
+)
+
+func isChar(c rune) bool { return c <= 127 }
+
+func isCtl(c rune) bool { return c <= 31 || c == 127 }
+
+func isSeparator(c rune) bool {
+	switch c {
+	case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
+		return true
+	}
+	return false
+}
+
+func TestIsToken(t *testing.T) {
+	for i := 0; i <= 130; i++ {
+		r := rune(i)
+		expected := isChar(r) && !isCtl(r) && !isSeparator(r)
+		if isToken(r) != expected {
+			t.Errorf("isToken(0x%x) = %v", r, !expected)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/npn_test.go b/third_party/gofrontend/libgo/go/net/http/npn_test.go
new file mode 100644
index 0000000..98b8930
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/npn_test.go
@@ -0,0 +1,118 @@
+// Copyright 2013 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 http_test
+
+import (
+	"bufio"
+	"crypto/tls"
+	"fmt"
+	"io"
+	"io/ioutil"
+	. "net/http"
+	"net/http/httptest"
+	"strings"
+	"testing"
+)
+
+func TestNextProtoUpgrade(t *testing.T) {
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "path=%s,proto=", r.URL.Path)
+		if r.TLS != nil {
+			w.Write([]byte(r.TLS.NegotiatedProtocol))
+		}
+		if r.RemoteAddr == "" {
+			t.Error("request with no RemoteAddr")
+		}
+		if r.Body == nil {
+			t.Errorf("request with nil Body")
+		}
+	}))
+	ts.TLS = &tls.Config{
+		NextProtos: []string{"unhandled-proto", "tls-0.9"},
+	}
+	ts.Config.TLSNextProto = map[string]func(*Server, *tls.Conn, Handler){
+		"tls-0.9": handleTLSProtocol09,
+	}
+	ts.StartTLS()
+	defer ts.Close()
+
+	tr := newTLSTransport(t, ts)
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	// Normal request, without NPN.
+	{
+		res, err := c.Get(ts.URL)
+		if err != nil {
+			t.Fatal(err)
+		}
+		body, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if want := "path=/,proto="; string(body) != want {
+			t.Errorf("plain request = %q; want %q", body, want)
+		}
+	}
+
+	// Request to an advertised but unhandled NPN protocol.
+	// Server will hang up.
+	{
+		tr.CloseIdleConnections()
+		tr.TLSClientConfig.NextProtos = []string{"unhandled-proto"}
+		_, err := c.Get(ts.URL)
+		if err == nil {
+			t.Errorf("expected error on unhandled-proto request")
+		}
+	}
+
+	// Request using the "tls-0.9" protocol, which we register here.
+	// It is HTTP/0.9 over TLS.
+	{
+		tlsConfig := newTLSTransport(t, ts).TLSClientConfig
+		tlsConfig.NextProtos = []string{"tls-0.9"}
+		conn, err := tls.Dial("tcp", ts.Listener.Addr().String(), tlsConfig)
+		if err != nil {
+			t.Fatal(err)
+		}
+		conn.Write([]byte("GET /foo\n"))
+		body, err := ioutil.ReadAll(conn)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if want := "path=/foo,proto=tls-0.9"; string(body) != want {
+			t.Errorf("plain request = %q; want %q", body, want)
+		}
+	}
+}
+
+// handleTLSProtocol09 implements the HTTP/0.9 protocol over TLS, for the
+// TestNextProtoUpgrade test.
+func handleTLSProtocol09(srv *Server, conn *tls.Conn, h Handler) {
+	br := bufio.NewReader(conn)
+	line, err := br.ReadString('\n')
+	if err != nil {
+		return
+	}
+	line = strings.TrimSpace(line)
+	path := strings.TrimPrefix(line, "GET ")
+	if path == line {
+		return
+	}
+	req, _ := NewRequest("GET", path, nil)
+	req.Proto = "HTTP/0.9"
+	req.ProtoMajor = 0
+	req.ProtoMinor = 9
+	rw := &http09Writer{conn, make(Header)}
+	h.ServeHTTP(rw, req)
+}
+
+type http09Writer struct {
+	io.Writer
+	h Header
+}
+
+func (w http09Writer) Header() Header  { return w.h }
+func (w http09Writer) WriteHeader(int) {} // no headers
diff --git a/third_party/gofrontend/libgo/go/net/http/pprof/pprof.go b/third_party/gofrontend/libgo/go/net/http/pprof/pprof.go
new file mode 100644
index 0000000..0c7548e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/pprof/pprof.go
@@ -0,0 +1,205 @@
+// Copyright 2010 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 pprof serves via its HTTP server runtime profiling data
+// in the format expected by the pprof visualization tool.
+// For more information about pprof, see
+// http://code.google.com/p/google-perftools/.
+//
+// The package is typically only imported for the side effect of
+// registering its HTTP handlers.
+// The handled paths all begin with /debug/pprof/.
+//
+// To use pprof, link this package into your program:
+//	import _ "net/http/pprof"
+//
+// If your application is not already running an http server, you
+// need to start one.  Add "net/http" and "log" to your imports and
+// the following code to your main function:
+//
+// 	go func() {
+// 		log.Println(http.ListenAndServe("localhost:6060", nil))
+// 	}()
+//
+// Then use the pprof tool to look at the heap profile:
+//
+//	go tool pprof http://localhost:6060/debug/pprof/heap
+//
+// Or to look at a 30-second CPU profile:
+//
+//	go tool pprof http://localhost:6060/debug/pprof/profile
+//
+// Or to look at the goroutine blocking profile:
+//
+//	go tool pprof http://localhost:6060/debug/pprof/block
+//
+// To view all available profiles, open http://localhost:6060/debug/pprof/
+// in your browser.
+//
+// For a study of the facility in action, visit
+//
+//	http://blog.golang.org/2011/06/profiling-go-programs.html
+//
+package pprof
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"html/template"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	"runtime"
+	"runtime/pprof"
+	"strconv"
+	"strings"
+	"time"
+)
+
+func init() {
+	http.Handle("/debug/pprof/", http.HandlerFunc(Index))
+	http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
+	http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
+	http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
+}
+
+// Cmdline responds with the running program's
+// command line, with arguments separated by NUL bytes.
+// The package initialization registers it as /debug/pprof/cmdline.
+func Cmdline(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	fmt.Fprintf(w, strings.Join(os.Args, "\x00"))
+}
+
+// Profile responds with the pprof-formatted cpu profile.
+// The package initialization registers it as /debug/pprof/profile.
+func Profile(w http.ResponseWriter, r *http.Request) {
+	sec, _ := strconv.ParseInt(r.FormValue("seconds"), 10, 64)
+	if sec == 0 {
+		sec = 30
+	}
+
+	// Set Content Type assuming StartCPUProfile will work,
+	// because if it does it starts writing.
+	w.Header().Set("Content-Type", "application/octet-stream")
+	if err := pprof.StartCPUProfile(w); err != nil {
+		// StartCPUProfile failed, so no writes yet.
+		// Can change header back to text content
+		// and send error code.
+		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+		w.WriteHeader(http.StatusInternalServerError)
+		fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err)
+		return
+	}
+	time.Sleep(time.Duration(sec) * time.Second)
+	pprof.StopCPUProfile()
+}
+
+// Symbol looks up the program counters listed in the request,
+// responding with a table mapping program counters to function names.
+// The package initialization registers it as /debug/pprof/symbol.
+func Symbol(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+
+	// We have to read the whole POST body before
+	// writing any output.  Buffer the output here.
+	var buf bytes.Buffer
+
+	// We don't know how many symbols we have, but we
+	// do have symbol information.  Pprof only cares whether
+	// this number is 0 (no symbols available) or > 0.
+	fmt.Fprintf(&buf, "num_symbols: 1\n")
+
+	var b *bufio.Reader
+	if r.Method == "POST" {
+		b = bufio.NewReader(r.Body)
+	} else {
+		b = bufio.NewReader(strings.NewReader(r.URL.RawQuery))
+	}
+
+	for {
+		word, err := b.ReadSlice('+')
+		if err == nil {
+			word = word[0 : len(word)-1] // trim +
+		}
+		pc, _ := strconv.ParseUint(string(word), 0, 64)
+		if pc != 0 {
+			f := runtime.FuncForPC(uintptr(pc))
+			if f != nil {
+				fmt.Fprintf(&buf, "%#x %s\n", pc, f.Name())
+			}
+		}
+
+		// Wait until here to check for err; the last
+		// symbol will have an err because it doesn't end in +.
+		if err != nil {
+			if err != io.EOF {
+				fmt.Fprintf(&buf, "reading request: %v\n", err)
+			}
+			break
+		}
+	}
+
+	w.Write(buf.Bytes())
+}
+
+// Handler returns an HTTP handler that serves the named profile.
+func Handler(name string) http.Handler {
+	return handler(name)
+}
+
+type handler string
+
+func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	debug, _ := strconv.Atoi(r.FormValue("debug"))
+	p := pprof.Lookup(string(name))
+	if p == nil {
+		w.WriteHeader(404)
+		fmt.Fprintf(w, "Unknown profile: %s\n", name)
+		return
+	}
+	p.WriteTo(w, debug)
+	return
+}
+
+// Index responds with the pprof-formatted profile named by the request.
+// For example, "/debug/pprof/heap" serves the "heap" profile.
+// Index responds to a request for "/debug/pprof/" with an HTML page
+// listing the available profiles.
+func Index(w http.ResponseWriter, r *http.Request) {
+	if strings.HasPrefix(r.URL.Path, "/debug/pprof/") {
+		name := strings.TrimPrefix(r.URL.Path, "/debug/pprof/")
+		if name != "" {
+			handler(name).ServeHTTP(w, r)
+			return
+		}
+	}
+
+	profiles := pprof.Profiles()
+	if err := indexTmpl.Execute(w, profiles); err != nil {
+		log.Print(err)
+	}
+}
+
+var indexTmpl = template.Must(template.New("index").Parse(`<html>
+<head>
+<title>/debug/pprof/</title>
+</head>
+/debug/pprof/<br>
+<br>
+<body>
+profiles:<br>
+<table>
+{{range .}}
+<tr><td align=right>{{.Count}}<td><a href="/debug/pprof/{{.Name}}?debug=1">{{.Name}}</a>
+{{end}}
+</table>
+<br>
+<a href="/debug/pprof/goroutine?debug=2">full goroutine stack dump</a><br>
+</body>
+</html>
+`))
diff --git a/third_party/gofrontend/libgo/go/net/http/proxy_test.go b/third_party/gofrontend/libgo/go/net/http/proxy_test.go
new file mode 100644
index 0000000..b6aed37
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/proxy_test.go
@@ -0,0 +1,81 @@
+// 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 http
+
+import (
+	"net/url"
+	"os"
+	"testing"
+)
+
+// TODO(mattn):
+//	test ProxyAuth
+
+var UseProxyTests = []struct {
+	host  string
+	match bool
+}{
+	// Never proxy localhost:
+	{"localhost:80", false},
+	{"127.0.0.1", false},
+	{"127.0.0.2", false},
+	{"[::1]", false},
+	{"[::2]", true}, // not a loopback address
+
+	{"barbaz.net", false},     // match as .barbaz.net
+	{"foobar.com", false},     // have a port but match
+	{"foofoobar.com", true},   // not match as a part of foobar.com
+	{"baz.com", true},         // not match as a part of barbaz.com
+	{"localhost.net", true},   // not match as suffix of address
+	{"local.localhost", true}, // not match as prefix as address
+	{"barbarbaz.net", true},   // not match because NO_PROXY have a '.'
+	{"www.foobar.com", false}, // match because NO_PROXY includes "foobar.com"
+}
+
+func TestUseProxy(t *testing.T) {
+	ResetProxyEnv()
+	os.Setenv("NO_PROXY", "foobar.com, .barbaz.net")
+	for _, test := range UseProxyTests {
+		if useProxy(test.host+":80") != test.match {
+			t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
+		}
+	}
+}
+
+var cacheKeysTests = []struct {
+	proxy  string
+	scheme string
+	addr   string
+	key    string
+}{
+	{"", "http", "foo.com", "|http|foo.com"},
+	{"", "https", "foo.com", "|https|foo.com"},
+	{"http://foo.com", "http", "foo.com", "http://foo.com|http|"},
+	{"http://foo.com", "https", "foo.com", "http://foo.com|https|foo.com"},
+}
+
+func TestCacheKeys(t *testing.T) {
+	for _, tt := range cacheKeysTests {
+		var proxy *url.URL
+		if tt.proxy != "" {
+			u, err := url.Parse(tt.proxy)
+			if err != nil {
+				t.Fatal(err)
+			}
+			proxy = u
+		}
+		cm := connectMethod{proxy, tt.scheme, tt.addr}
+		if got := cm.key().String(); got != tt.key {
+			t.Fatalf("{%q, %q, %q} cache key = %q; want %q", tt.proxy, tt.scheme, tt.addr, got, tt.key)
+		}
+	}
+}
+
+func ResetProxyEnv() {
+	for _, v := range []string{"HTTP_PROXY", "http_proxy", "NO_PROXY", "no_proxy"} {
+		os.Setenv(v, "")
+	}
+	ResetCachedEnvironment()
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/race.go b/third_party/gofrontend/libgo/go/net/http/race.go
new file mode 100644
index 0000000..7665039
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/race.go
@@ -0,0 +1,11 @@
+// Copyright 2014 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.
+
+// +build race
+
+package http
+
+func init() {
+	raceEnabled = true
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/range_test.go b/third_party/gofrontend/libgo/go/net/http/range_test.go
new file mode 100644
index 0000000..ef911af
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/range_test.go
@@ -0,0 +1,79 @@
+// 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.
+
+package http
+
+import (
+	"testing"
+)
+
+var ParseRangeTests = []struct {
+	s      string
+	length int64
+	r      []httpRange
+}{
+	{"", 0, nil},
+	{"", 1000, nil},
+	{"foo", 0, nil},
+	{"bytes=", 0, nil},
+	{"bytes=7", 10, nil},
+	{"bytes= 7 ", 10, nil},
+	{"bytes=1-", 0, nil},
+	{"bytes=5-4", 10, nil},
+	{"bytes=0-2,5-4", 10, nil},
+	{"bytes=2-5,4-3", 10, nil},
+	{"bytes=--5,4--3", 10, nil},
+	{"bytes=A-", 10, nil},
+	{"bytes=A- ", 10, nil},
+	{"bytes=A-Z", 10, nil},
+	{"bytes= -Z", 10, nil},
+	{"bytes=5-Z", 10, nil},
+	{"bytes=Ran-dom, garbage", 10, nil},
+	{"bytes=0x01-0x02", 10, nil},
+	{"bytes=         ", 10, nil},
+	{"bytes= , , ,   ", 10, nil},
+
+	{"bytes=0-9", 10, []httpRange{{0, 10}}},
+	{"bytes=0-", 10, []httpRange{{0, 10}}},
+	{"bytes=5-", 10, []httpRange{{5, 5}}},
+	{"bytes=0-20", 10, []httpRange{{0, 10}}},
+	{"bytes=15-,0-5", 10, nil},
+	{"bytes=1-2,5-", 10, []httpRange{{1, 2}, {5, 5}}},
+	{"bytes=-2 , 7-", 11, []httpRange{{9, 2}, {7, 4}}},
+	{"bytes=0-0 ,2-2, 7-", 11, []httpRange{{0, 1}, {2, 1}, {7, 4}}},
+	{"bytes=-5", 10, []httpRange{{5, 5}}},
+	{"bytes=-15", 10, []httpRange{{0, 10}}},
+	{"bytes=0-499", 10000, []httpRange{{0, 500}}},
+	{"bytes=500-999", 10000, []httpRange{{500, 500}}},
+	{"bytes=-500", 10000, []httpRange{{9500, 500}}},
+	{"bytes=9500-", 10000, []httpRange{{9500, 500}}},
+	{"bytes=0-0,-1", 10000, []httpRange{{0, 1}, {9999, 1}}},
+	{"bytes=500-600,601-999", 10000, []httpRange{{500, 101}, {601, 399}}},
+	{"bytes=500-700,601-999", 10000, []httpRange{{500, 201}, {601, 399}}},
+
+	// Match Apache laxity:
+	{"bytes=   1 -2   ,  4- 5, 7 - 8 , ,,", 11, []httpRange{{1, 2}, {4, 2}, {7, 2}}},
+}
+
+func TestParseRange(t *testing.T) {
+	for _, test := range ParseRangeTests {
+		r := test.r
+		ranges, err := parseRange(test.s, test.length)
+		if err != nil && r != nil {
+			t.Errorf("parseRange(%q) returned error %q", test.s, err)
+		}
+		if len(ranges) != len(r) {
+			t.Errorf("len(parseRange(%q)) = %d, want %d", test.s, len(ranges), len(r))
+			continue
+		}
+		for i := range r {
+			if ranges[i].start != r[i].start {
+				t.Errorf("parseRange(%q)[%d].start = %d, want %d", test.s, i, ranges[i].start, r[i].start)
+			}
+			if ranges[i].length != r[i].length {
+				t.Errorf("parseRange(%q)[%d].length = %d, want %d", test.s, i, ranges[i].length, r[i].length)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/readrequest_test.go b/third_party/gofrontend/libgo/go/net/http/readrequest_test.go
new file mode 100644
index 0000000..ffdd6a8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/readrequest_test.go
@@ -0,0 +1,331 @@
+// Copyright 2010 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 http
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"net/url"
+	"reflect"
+	"testing"
+)
+
+type reqTest struct {
+	Raw     string
+	Req     *Request
+	Body    string
+	Trailer Header
+	Error   string
+}
+
+var noError = ""
+var noBody = ""
+var noTrailer Header = nil
+
+var reqTests = []reqTest{
+	// Baseline test; All Request fields included for template use
+	{
+		"GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
+			"Host: www.techcrunch.com\r\n" +
+			"User-Agent: Fake\r\n" +
+			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
+			"Accept-Language: en-us,en;q=0.5\r\n" +
+			"Accept-Encoding: gzip,deflate\r\n" +
+			"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
+			"Keep-Alive: 300\r\n" +
+			"Content-Length: 7\r\n" +
+			"Proxy-Connection: keep-alive\r\n\r\n" +
+			"abcdef\n???",
+
+		&Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.techcrunch.com",
+				Path:   "/",
+			},
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"Accept":           {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
+				"Accept-Language":  {"en-us,en;q=0.5"},
+				"Accept-Encoding":  {"gzip,deflate"},
+				"Accept-Charset":   {"ISO-8859-1,utf-8;q=0.7,*;q=0.7"},
+				"Keep-Alive":       {"300"},
+				"Proxy-Connection": {"keep-alive"},
+				"Content-Length":   {"7"},
+				"User-Agent":       {"Fake"},
+			},
+			Close:         false,
+			ContentLength: 7,
+			Host:          "www.techcrunch.com",
+			RequestURI:    "http://www.techcrunch.com/",
+		},
+
+		"abcdef\n",
+
+		noTrailer,
+		noError,
+	},
+
+	// GET request with no body (the normal case)
+	{
+		"GET / HTTP/1.1\r\n" +
+			"Host: foo.com\r\n\r\n",
+
+		&Request{
+			Method: "GET",
+			URL: &url.URL{
+				Path: "/",
+			},
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         false,
+			ContentLength: 0,
+			Host:          "foo.com",
+			RequestURI:    "/",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// Tests that we don't parse a path that looks like a
+	// scheme-relative URI as a scheme-relative URI.
+	{
+		"GET //user@host/is/actually/a/path/ HTTP/1.1\r\n" +
+			"Host: test\r\n\r\n",
+
+		&Request{
+			Method: "GET",
+			URL: &url.URL{
+				Path: "//user@host/is/actually/a/path/",
+			},
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         false,
+			ContentLength: 0,
+			Host:          "test",
+			RequestURI:    "//user@host/is/actually/a/path/",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// Tests a bogus abs_path on the Request-Line (RFC 2616 section 5.1.2)
+	{
+		"GET ../../../../etc/passwd HTTP/1.1\r\n" +
+			"Host: test\r\n\r\n",
+		nil,
+		noBody,
+		noTrailer,
+		"parse ../../../../etc/passwd: invalid URI for request",
+	},
+
+	// Tests missing URL:
+	{
+		"GET  HTTP/1.1\r\n" +
+			"Host: test\r\n\r\n",
+		nil,
+		noBody,
+		noTrailer,
+		"parse : empty url",
+	},
+
+	// Tests chunked body with trailer:
+	{
+		"POST / HTTP/1.1\r\n" +
+			"Host: foo.com\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			"3\r\nfoo\r\n" +
+			"3\r\nbar\r\n" +
+			"0\r\n" +
+			"Trailer-Key: Trailer-Value\r\n" +
+			"\r\n",
+		&Request{
+			Method: "POST",
+			URL: &url.URL{
+				Path: "/",
+			},
+			TransferEncoding: []string{"chunked"},
+			Proto:            "HTTP/1.1",
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Header:           Header{},
+			ContentLength:    -1,
+			Host:             "foo.com",
+			RequestURI:       "/",
+		},
+
+		"foobar",
+		Header{
+			"Trailer-Key": {"Trailer-Value"},
+		},
+		noError,
+	},
+
+	// CONNECT request with domain name:
+	{
+		"CONNECT www.google.com:443 HTTP/1.1\r\n\r\n",
+
+		&Request{
+			Method: "CONNECT",
+			URL: &url.URL{
+				Host: "www.google.com:443",
+			},
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         false,
+			ContentLength: 0,
+			Host:          "www.google.com:443",
+			RequestURI:    "www.google.com:443",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// CONNECT request with IP address:
+	{
+		"CONNECT 127.0.0.1:6060 HTTP/1.1\r\n\r\n",
+
+		&Request{
+			Method: "CONNECT",
+			URL: &url.URL{
+				Host: "127.0.0.1:6060",
+			},
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         false,
+			ContentLength: 0,
+			Host:          "127.0.0.1:6060",
+			RequestURI:    "127.0.0.1:6060",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// CONNECT request for RPC:
+	{
+		"CONNECT /_goRPC_ HTTP/1.1\r\n\r\n",
+
+		&Request{
+			Method: "CONNECT",
+			URL: &url.URL{
+				Path: "/_goRPC_",
+			},
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         false,
+			ContentLength: 0,
+			Host:          "",
+			RequestURI:    "/_goRPC_",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// SSDP Notify request. golang.org/issue/3692
+	{
+		"NOTIFY * HTTP/1.1\r\nServer: foo\r\n\r\n",
+		&Request{
+			Method: "NOTIFY",
+			URL: &url.URL{
+				Path: "*",
+			},
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"Server": []string{"foo"},
+			},
+			Close:         false,
+			ContentLength: 0,
+			RequestURI:    "*",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// OPTIONS request. Similar to golang.org/issue/3692
+	{
+		"OPTIONS * HTTP/1.1\r\nServer: foo\r\n\r\n",
+		&Request{
+			Method: "OPTIONS",
+			URL: &url.URL{
+				Path: "*",
+			},
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"Server": []string{"foo"},
+			},
+			Close:         false,
+			ContentLength: 0,
+			RequestURI:    "*",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+}
+
+func TestReadRequest(t *testing.T) {
+	for i := range reqTests {
+		tt := &reqTests[i]
+		var braw bytes.Buffer
+		braw.WriteString(tt.Raw)
+		req, err := ReadRequest(bufio.NewReader(&braw))
+		if err != nil {
+			if err.Error() != tt.Error {
+				t.Errorf("#%d: error %q, want error %q", i, err.Error(), tt.Error)
+			}
+			continue
+		}
+		rbody := req.Body
+		req.Body = nil
+		diff(t, fmt.Sprintf("#%d Request", i), req, tt.Req)
+		var bout bytes.Buffer
+		if rbody != nil {
+			_, err := io.Copy(&bout, rbody)
+			if err != nil {
+				t.Fatalf("#%d. copying body: %v", i, err)
+			}
+			rbody.Close()
+		}
+		body := bout.String()
+		if body != tt.Body {
+			t.Errorf("#%d: Body = %q want %q", i, body, tt.Body)
+		}
+		if !reflect.DeepEqual(tt.Trailer, req.Trailer) {
+			t.Errorf("#%d. Trailers differ.\n got: %v\nwant: %v", i, req.Trailer, tt.Trailer)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/request.go b/third_party/gofrontend/libgo/go/net/http/request.go
new file mode 100644
index 0000000..a670920
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/request.go
@@ -0,0 +1,875 @@
+// 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.
+
+// HTTP Request reading and parsing.
+
+package http
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"mime"
+	"mime/multipart"
+	"net/textproto"
+	"net/url"
+	"strconv"
+	"strings"
+	"sync"
+)
+
+const (
+	maxValueLength   = 4096
+	maxHeaderLines   = 1024
+	chunkSize        = 4 << 10  // 4 KB chunks
+	defaultMaxMemory = 32 << 20 // 32 MB
+)
+
+// ErrMissingFile is returned by FormFile when the provided file field name
+// is either not present in the request or not a file field.
+var ErrMissingFile = errors.New("http: no such file")
+
+// HTTP request parsing errors.
+type ProtocolError struct {
+	ErrorString string
+}
+
+func (err *ProtocolError) Error() string { return err.ErrorString }
+
+var (
+	ErrHeaderTooLong        = &ProtocolError{"header too long"}
+	ErrShortBody            = &ProtocolError{"entity body too short"}
+	ErrNotSupported         = &ProtocolError{"feature not supported"}
+	ErrUnexpectedTrailer    = &ProtocolError{"trailer header without chunked transfer encoding"}
+	ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"}
+	ErrNotMultipart         = &ProtocolError{"request Content-Type isn't multipart/form-data"}
+	ErrMissingBoundary      = &ProtocolError{"no multipart boundary param in Content-Type"}
+)
+
+type badStringError struct {
+	what string
+	str  string
+}
+
+func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
+
+// Headers that Request.Write handles itself and should be skipped.
+var reqWriteExcludeHeader = map[string]bool{
+	"Host":              true, // not in Header map anyway
+	"User-Agent":        true,
+	"Content-Length":    true,
+	"Transfer-Encoding": true,
+	"Trailer":           true,
+}
+
+// A Request represents an HTTP request received by a server
+// or to be sent by a client.
+//
+// The field semantics differ slightly between client and server
+// usage. In addition to the notes on the fields below, see the
+// documentation for Request.Write and RoundTripper.
+type Request struct {
+	// Method specifies the HTTP method (GET, POST, PUT, etc.).
+	// For client requests an empty string means GET.
+	Method string
+
+	// URL specifies either the URI being requested (for server
+	// requests) or the URL to access (for client requests).
+	//
+	// For server requests the URL is parsed from the URI
+	// supplied on the Request-Line as stored in RequestURI.  For
+	// most requests, fields other than Path and RawQuery will be
+	// empty. (See RFC 2616, Section 5.1.2)
+	//
+	// For client requests, the URL's Host specifies the server to
+	// connect to, while the Request's Host field optionally
+	// specifies the Host header value to send in the HTTP
+	// request.
+	URL *url.URL
+
+	// The protocol version for incoming requests.
+	// Client requests always use HTTP/1.1.
+	Proto      string // "HTTP/1.0"
+	ProtoMajor int    // 1
+	ProtoMinor int    // 0
+
+	// A header maps request lines to their values.
+	// If the header says
+	//
+	//	accept-encoding: gzip, deflate
+	//	Accept-Language: en-us
+	//	Connection: keep-alive
+	//
+	// then
+	//
+	//	Header = map[string][]string{
+	//		"Accept-Encoding": {"gzip, deflate"},
+	//		"Accept-Language": {"en-us"},
+	//		"Connection": {"keep-alive"},
+	//	}
+	//
+	// HTTP defines that header names are case-insensitive.
+	// The request parser implements this by canonicalizing the
+	// name, making the first character and any characters
+	// following a hyphen uppercase and the rest lowercase.
+	//
+	// For client requests certain headers are automatically
+	// added and may override values in Header.
+	//
+	// See the documentation for the Request.Write method.
+	Header Header
+
+	// Body is the request's body.
+	//
+	// For client requests a nil body means the request has no
+	// body, such as a GET request. The HTTP Client's Transport
+	// is responsible for calling the Close method.
+	//
+	// For server requests the Request Body is always non-nil
+	// but will return EOF immediately when no body is present.
+	// The Server will close the request body. The ServeHTTP
+	// Handler does not need to.
+	Body io.ReadCloser
+
+	// ContentLength records the length of the associated content.
+	// The value -1 indicates that the length is unknown.
+	// Values >= 0 indicate that the given number of bytes may
+	// be read from Body.
+	// For client requests, a value of 0 means unknown if Body is not nil.
+	ContentLength int64
+
+	// TransferEncoding lists the transfer encodings from outermost to
+	// innermost. An empty list denotes the "identity" encoding.
+	// TransferEncoding can usually be ignored; chunked encoding is
+	// automatically added and removed as necessary when sending and
+	// receiving requests.
+	TransferEncoding []string
+
+	// Close indicates whether to close the connection after
+	// replying to this request (for servers) or after sending
+	// the request (for clients).
+	Close bool
+
+	// For server requests Host specifies the host on which the
+	// URL is sought. Per RFC 2616, this is either the value of
+	// the "Host" header or the host name given in the URL itself.
+	// It may be of the form "host:port".
+	//
+	// For client requests Host optionally overrides the Host
+	// header to send. If empty, the Request.Write method uses
+	// the value of URL.Host.
+	Host string
+
+	// Form contains the parsed form data, including both the URL
+	// field's query parameters and the POST or PUT form data.
+	// This field is only available after ParseForm is called.
+	// The HTTP client ignores Form and uses Body instead.
+	Form url.Values
+
+	// PostForm contains the parsed form data from POST or PUT
+	// body parameters.
+	// This field is only available after ParseForm is called.
+	// The HTTP client ignores PostForm and uses Body instead.
+	PostForm url.Values
+
+	// MultipartForm is the parsed multipart form, including file uploads.
+	// This field is only available after ParseMultipartForm is called.
+	// The HTTP client ignores MultipartForm and uses Body instead.
+	MultipartForm *multipart.Form
+
+	// Trailer specifies additional headers that are sent after the request
+	// body.
+	//
+	// For server requests the Trailer map initially contains only the
+	// trailer keys, with nil values. (The client declares which trailers it
+	// will later send.)  While the handler is reading from Body, it must
+	// not reference Trailer. After reading from Body returns EOF, Trailer
+	// can be read again and will contain non-nil values, if they were sent
+	// by the client.
+	//
+	// For client requests Trailer must be initialized to a map containing
+	// the trailer keys to later send. The values may be nil or their final
+	// values. The ContentLength must be 0 or -1, to send a chunked request.
+	// After the HTTP request is sent the map values can be updated while
+	// the request body is read. Once the body returns EOF, the caller must
+	// not mutate Trailer.
+	//
+	// Few HTTP clients, servers, or proxies support HTTP trailers.
+	Trailer Header
+
+	// RemoteAddr allows HTTP servers and other software to record
+	// the network address that sent the request, usually for
+	// logging. This field is not filled in by ReadRequest and
+	// has no defined format. The HTTP server in this package
+	// sets RemoteAddr to an "IP:port" address before invoking a
+	// handler.
+	// This field is ignored by the HTTP client.
+	RemoteAddr string
+
+	// RequestURI is the unmodified Request-URI of the
+	// Request-Line (RFC 2616, Section 5.1) as sent by the client
+	// to a server. Usually the URL field should be used instead.
+	// It is an error to set this field in an HTTP client request.
+	RequestURI string
+
+	// TLS allows HTTP servers and other software to record
+	// information about the TLS connection on which the request
+	// was received. This field is not filled in by ReadRequest.
+	// The HTTP server in this package sets the field for
+	// TLS-enabled connections before invoking a handler;
+	// otherwise it leaves the field nil.
+	// This field is ignored by the HTTP client.
+	TLS *tls.ConnectionState
+}
+
+// ProtoAtLeast reports whether the HTTP protocol used
+// in the request is at least major.minor.
+func (r *Request) ProtoAtLeast(major, minor int) bool {
+	return r.ProtoMajor > major ||
+		r.ProtoMajor == major && r.ProtoMinor >= minor
+}
+
+// UserAgent returns the client's User-Agent, if sent in the request.
+func (r *Request) UserAgent() string {
+	return r.Header.Get("User-Agent")
+}
+
+// Cookies parses and returns the HTTP cookies sent with the request.
+func (r *Request) Cookies() []*Cookie {
+	return readCookies(r.Header, "")
+}
+
+var ErrNoCookie = errors.New("http: named cookie not present")
+
+// Cookie returns the named cookie provided in the request or
+// ErrNoCookie if not found.
+func (r *Request) Cookie(name string) (*Cookie, error) {
+	for _, c := range readCookies(r.Header, name) {
+		return c, nil
+	}
+	return nil, ErrNoCookie
+}
+
+// AddCookie adds a cookie to the request.  Per RFC 6265 section 5.4,
+// AddCookie does not attach more than one Cookie header field.  That
+// means all cookies, if any, are written into the same line,
+// separated by semicolon.
+func (r *Request) AddCookie(c *Cookie) {
+	s := fmt.Sprintf("%s=%s", sanitizeCookieName(c.Name), sanitizeCookieValue(c.Value))
+	if c := r.Header.Get("Cookie"); c != "" {
+		r.Header.Set("Cookie", c+"; "+s)
+	} else {
+		r.Header.Set("Cookie", s)
+	}
+}
+
+// Referer returns the referring URL, if sent in the request.
+//
+// Referer is misspelled as in the request itself, a mistake from the
+// earliest days of HTTP.  This value can also be fetched from the
+// Header map as Header["Referer"]; the benefit of making it available
+// as a method is that the compiler can diagnose programs that use the
+// alternate (correct English) spelling req.Referrer() but cannot
+// diagnose programs that use Header["Referrer"].
+func (r *Request) Referer() string {
+	return r.Header.Get("Referer")
+}
+
+// multipartByReader is a sentinel value.
+// Its presence in Request.MultipartForm indicates that parsing of the request
+// body has been handed off to a MultipartReader instead of ParseMultipartFrom.
+var multipartByReader = &multipart.Form{
+	Value: make(map[string][]string),
+	File:  make(map[string][]*multipart.FileHeader),
+}
+
+// MultipartReader returns a MIME multipart reader if this is a
+// multipart/form-data POST request, else returns nil and an error.
+// Use this function instead of ParseMultipartForm to
+// process the request body as a stream.
+func (r *Request) MultipartReader() (*multipart.Reader, error) {
+	if r.MultipartForm == multipartByReader {
+		return nil, errors.New("http: MultipartReader called twice")
+	}
+	if r.MultipartForm != nil {
+		return nil, errors.New("http: multipart handled by ParseMultipartForm")
+	}
+	r.MultipartForm = multipartByReader
+	return r.multipartReader()
+}
+
+func (r *Request) multipartReader() (*multipart.Reader, error) {
+	v := r.Header.Get("Content-Type")
+	if v == "" {
+		return nil, ErrNotMultipart
+	}
+	d, params, err := mime.ParseMediaType(v)
+	if err != nil || d != "multipart/form-data" {
+		return nil, ErrNotMultipart
+	}
+	boundary, ok := params["boundary"]
+	if !ok {
+		return nil, ErrMissingBoundary
+	}
+	return multipart.NewReader(r.Body, boundary), nil
+}
+
+// Return value if nonempty, def otherwise.
+func valueOrDefault(value, def string) string {
+	if value != "" {
+		return value
+	}
+	return def
+}
+
+// NOTE: This is not intended to reflect the actual Go version being used.
+// It was changed from "Go http package" to "Go 1.1 package http" at the
+// time of the Go 1.1 release because the former User-Agent had ended up
+// on a blacklist for some intrusion detection systems.
+// See https://codereview.appspot.com/7532043.
+const defaultUserAgent = "Go 1.1 package http"
+
+// Write writes an HTTP/1.1 request -- header and body -- in wire format.
+// This method consults the following fields of the request:
+//	Host
+//	URL
+//	Method (defaults to "GET")
+//	Header
+//	ContentLength
+//	TransferEncoding
+//	Body
+//
+// If Body is present, Content-Length is <= 0 and TransferEncoding
+// hasn't been set to "identity", Write adds "Transfer-Encoding:
+// chunked" to the header. Body is closed after it is sent.
+func (r *Request) Write(w io.Writer) error {
+	return r.write(w, false, nil)
+}
+
+// WriteProxy is like Write but writes the request in the form
+// expected by an HTTP proxy.  In particular, WriteProxy writes the
+// initial Request-URI line of the request with an absolute URI, per
+// section 5.1.2 of RFC 2616, including the scheme and host.
+// In either case, WriteProxy also writes a Host header, using
+// either r.Host or r.URL.Host.
+func (r *Request) WriteProxy(w io.Writer) error {
+	return r.write(w, true, nil)
+}
+
+// extraHeaders may be nil
+func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) error {
+	host := req.Host
+	if host == "" {
+		if req.URL == nil {
+			return errors.New("http: Request.Write on Request with no Host or URL set")
+		}
+		host = req.URL.Host
+	}
+
+	ruri := req.URL.RequestURI()
+	if usingProxy && req.URL.Scheme != "" && req.URL.Opaque == "" {
+		ruri = req.URL.Scheme + "://" + host + ruri
+	} else if req.Method == "CONNECT" && req.URL.Path == "" {
+		// CONNECT requests normally give just the host and port, not a full URL.
+		ruri = host
+	}
+	// TODO(bradfitz): escape at least newlines in ruri?
+
+	// Wrap the writer in a bufio Writer if it's not already buffered.
+	// Don't always call NewWriter, as that forces a bytes.Buffer
+	// and other small bufio Writers to have a minimum 4k buffer
+	// size.
+	var bw *bufio.Writer
+	if _, ok := w.(io.ByteWriter); !ok {
+		bw = bufio.NewWriter(w)
+		w = bw
+	}
+
+	fmt.Fprintf(w, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), ruri)
+
+	// Header lines
+	fmt.Fprintf(w, "Host: %s\r\n", host)
+
+	// Use the defaultUserAgent unless the Header contains one, which
+	// may be blank to not send the header.
+	userAgent := defaultUserAgent
+	if req.Header != nil {
+		if ua := req.Header["User-Agent"]; len(ua) > 0 {
+			userAgent = ua[0]
+		}
+	}
+	if userAgent != "" {
+		fmt.Fprintf(w, "User-Agent: %s\r\n", userAgent)
+	}
+
+	// Process Body,ContentLength,Close,Trailer
+	tw, err := newTransferWriter(req)
+	if err != nil {
+		return err
+	}
+	err = tw.WriteHeader(w)
+	if err != nil {
+		return err
+	}
+
+	err = req.Header.WriteSubset(w, reqWriteExcludeHeader)
+	if err != nil {
+		return err
+	}
+
+	if extraHeaders != nil {
+		err = extraHeaders.Write(w)
+		if err != nil {
+			return err
+		}
+	}
+
+	io.WriteString(w, "\r\n")
+
+	// Write body and trailer
+	err = tw.WriteBody(w)
+	if err != nil {
+		return err
+	}
+
+	if bw != nil {
+		return bw.Flush()
+	}
+	return nil
+}
+
+// ParseHTTPVersion parses a HTTP version string.
+// "HTTP/1.0" returns (1, 0, true).
+func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
+	const Big = 1000000 // arbitrary upper bound
+	switch vers {
+	case "HTTP/1.1":
+		return 1, 1, true
+	case "HTTP/1.0":
+		return 1, 0, true
+	}
+	if !strings.HasPrefix(vers, "HTTP/") {
+		return 0, 0, false
+	}
+	dot := strings.Index(vers, ".")
+	if dot < 0 {
+		return 0, 0, false
+	}
+	major, err := strconv.Atoi(vers[5:dot])
+	if err != nil || major < 0 || major > Big {
+		return 0, 0, false
+	}
+	minor, err = strconv.Atoi(vers[dot+1:])
+	if err != nil || minor < 0 || minor > Big {
+		return 0, 0, false
+	}
+	return major, minor, true
+}
+
+// NewRequest returns a new Request given a method, URL, and optional body.
+//
+// If the provided body is also an io.Closer, the returned
+// Request.Body is set to body and will be closed by the Client
+// methods Do, Post, and PostForm, and Transport.RoundTrip.
+func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
+	u, err := url.Parse(urlStr)
+	if err != nil {
+		return nil, err
+	}
+	rc, ok := body.(io.ReadCloser)
+	if !ok && body != nil {
+		rc = ioutil.NopCloser(body)
+	}
+	req := &Request{
+		Method:     method,
+		URL:        u,
+		Proto:      "HTTP/1.1",
+		ProtoMajor: 1,
+		ProtoMinor: 1,
+		Header:     make(Header),
+		Body:       rc,
+		Host:       u.Host,
+	}
+	if body != nil {
+		switch v := body.(type) {
+		case *bytes.Buffer:
+			req.ContentLength = int64(v.Len())
+		case *bytes.Reader:
+			req.ContentLength = int64(v.Len())
+		case *strings.Reader:
+			req.ContentLength = int64(v.Len())
+		}
+	}
+
+	return req, nil
+}
+
+// SetBasicAuth sets the request's Authorization header to use HTTP
+// Basic Authentication with the provided username and password.
+//
+// With HTTP Basic Authentication the provided username and password
+// are not encrypted.
+func (r *Request) SetBasicAuth(username, password string) {
+	r.Header.Set("Authorization", "Basic "+basicAuth(username, password))
+}
+
+// parseRequestLine parses "GET /foo HTTP/1.1" into its three parts.
+func parseRequestLine(line string) (method, requestURI, proto string, ok bool) {
+	s1 := strings.Index(line, " ")
+	s2 := strings.Index(line[s1+1:], " ")
+	if s1 < 0 || s2 < 0 {
+		return
+	}
+	s2 += s1 + 1
+	return line[:s1], line[s1+1 : s2], line[s2+1:], true
+}
+
+var textprotoReaderPool sync.Pool
+
+func newTextprotoReader(br *bufio.Reader) *textproto.Reader {
+	if v := textprotoReaderPool.Get(); v != nil {
+		tr := v.(*textproto.Reader)
+		tr.R = br
+		return tr
+	}
+	return textproto.NewReader(br)
+}
+
+func putTextprotoReader(r *textproto.Reader) {
+	r.R = nil
+	textprotoReaderPool.Put(r)
+}
+
+// ReadRequest reads and parses a request from b.
+func ReadRequest(b *bufio.Reader) (req *Request, err error) {
+
+	tp := newTextprotoReader(b)
+	req = new(Request)
+
+	// First line: GET /index.html HTTP/1.0
+	var s string
+	if s, err = tp.ReadLine(); err != nil {
+		return nil, err
+	}
+	defer func() {
+		putTextprotoReader(tp)
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+	}()
+
+	var ok bool
+	req.Method, req.RequestURI, req.Proto, ok = parseRequestLine(s)
+	if !ok {
+		return nil, &badStringError{"malformed HTTP request", s}
+	}
+	rawurl := req.RequestURI
+	if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
+		return nil, &badStringError{"malformed HTTP version", req.Proto}
+	}
+
+	// CONNECT requests are used two different ways, and neither uses a full URL:
+	// The standard use is to tunnel HTTPS through an HTTP proxy.
+	// It looks like "CONNECT www.google.com:443 HTTP/1.1", and the parameter is
+	// just the authority section of a URL. This information should go in req.URL.Host.
+	//
+	// The net/rpc package also uses CONNECT, but there the parameter is a path
+	// that starts with a slash. It can be parsed with the regular URL parser,
+	// and the path will end up in req.URL.Path, where it needs to be in order for
+	// RPC to work.
+	justAuthority := req.Method == "CONNECT" && !strings.HasPrefix(rawurl, "/")
+	if justAuthority {
+		rawurl = "http://" + rawurl
+	}
+
+	if req.URL, err = url.ParseRequestURI(rawurl); err != nil {
+		return nil, err
+	}
+
+	if justAuthority {
+		// Strip the bogus "http://" back off.
+		req.URL.Scheme = ""
+	}
+
+	// Subsequent lines: Key: value.
+	mimeHeader, err := tp.ReadMIMEHeader()
+	if err != nil {
+		return nil, err
+	}
+	req.Header = Header(mimeHeader)
+
+	// RFC2616: Must treat
+	//	GET /index.html HTTP/1.1
+	//	Host: www.google.com
+	// and
+	//	GET http://www.google.com/index.html HTTP/1.1
+	//	Host: doesntmatter
+	// the same.  In the second case, any Host line is ignored.
+	req.Host = req.URL.Host
+	if req.Host == "" {
+		req.Host = req.Header.get("Host")
+	}
+	delete(req.Header, "Host")
+
+	fixPragmaCacheControl(req.Header)
+
+	err = readTransfer(req, b)
+	if err != nil {
+		return nil, err
+	}
+
+	return req, nil
+}
+
+// MaxBytesReader is similar to io.LimitReader but is intended for
+// limiting the size of incoming request bodies. In contrast to
+// io.LimitReader, MaxBytesReader's result is a ReadCloser, returns a
+// non-EOF error for a Read beyond the limit, and Closes the
+// underlying reader when its Close method is called.
+//
+// MaxBytesReader prevents clients from accidentally or maliciously
+// sending a large request and wasting server resources.
+func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser {
+	return &maxBytesReader{w: w, r: r, n: n}
+}
+
+type maxBytesReader struct {
+	w       ResponseWriter
+	r       io.ReadCloser // underlying reader
+	n       int64         // max bytes remaining
+	stopped bool
+}
+
+func (l *maxBytesReader) Read(p []byte) (n int, err error) {
+	if l.n <= 0 {
+		if !l.stopped {
+			l.stopped = true
+			if res, ok := l.w.(*response); ok {
+				res.requestTooLarge()
+			}
+		}
+		return 0, errors.New("http: request body too large")
+	}
+	if int64(len(p)) > l.n {
+		p = p[:l.n]
+	}
+	n, err = l.r.Read(p)
+	l.n -= int64(n)
+	return
+}
+
+func (l *maxBytesReader) Close() error {
+	return l.r.Close()
+}
+
+func copyValues(dst, src url.Values) {
+	for k, vs := range src {
+		for _, value := range vs {
+			dst.Add(k, value)
+		}
+	}
+}
+
+func parsePostForm(r *Request) (vs url.Values, err error) {
+	if r.Body == nil {
+		err = errors.New("missing form body")
+		return
+	}
+	ct := r.Header.Get("Content-Type")
+	// RFC 2616, section 7.2.1 - empty type
+	//   SHOULD be treated as application/octet-stream
+	if ct == "" {
+		ct = "application/octet-stream"
+	}
+	ct, _, err = mime.ParseMediaType(ct)
+	switch {
+	case ct == "application/x-www-form-urlencoded":
+		var reader io.Reader = r.Body
+		maxFormSize := int64(1<<63 - 1)
+		if _, ok := r.Body.(*maxBytesReader); !ok {
+			maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
+			reader = io.LimitReader(r.Body, maxFormSize+1)
+		}
+		b, e := ioutil.ReadAll(reader)
+		if e != nil {
+			if err == nil {
+				err = e
+			}
+			break
+		}
+		if int64(len(b)) > maxFormSize {
+			err = errors.New("http: POST too large")
+			return
+		}
+		vs, e = url.ParseQuery(string(b))
+		if err == nil {
+			err = e
+		}
+	case ct == "multipart/form-data":
+		// handled by ParseMultipartForm (which is calling us, or should be)
+		// TODO(bradfitz): there are too many possible
+		// orders to call too many functions here.
+		// Clean this up and write more tests.
+		// request_test.go contains the start of this,
+		// in TestParseMultipartFormOrder and others.
+	}
+	return
+}
+
+// ParseForm parses the raw query from the URL and updates r.Form.
+//
+// For POST or PUT requests, it also parses the request body as a form and
+// put the results into both r.PostForm and r.Form.
+// POST and PUT body parameters take precedence over URL query string values
+// in r.Form.
+//
+// If the request Body's size has not already been limited by MaxBytesReader,
+// the size is capped at 10MB.
+//
+// ParseMultipartForm calls ParseForm automatically.
+// It is idempotent.
+func (r *Request) ParseForm() error {
+	var err error
+	if r.PostForm == nil {
+		if r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH" {
+			r.PostForm, err = parsePostForm(r)
+		}
+		if r.PostForm == nil {
+			r.PostForm = make(url.Values)
+		}
+	}
+	if r.Form == nil {
+		if len(r.PostForm) > 0 {
+			r.Form = make(url.Values)
+			copyValues(r.Form, r.PostForm)
+		}
+		var newValues url.Values
+		if r.URL != nil {
+			var e error
+			newValues, e = url.ParseQuery(r.URL.RawQuery)
+			if err == nil {
+				err = e
+			}
+		}
+		if newValues == nil {
+			newValues = make(url.Values)
+		}
+		if r.Form == nil {
+			r.Form = newValues
+		} else {
+			copyValues(r.Form, newValues)
+		}
+	}
+	return err
+}
+
+// ParseMultipartForm parses a request body as multipart/form-data.
+// The whole request body is parsed and up to a total of maxMemory bytes of
+// its file parts are stored in memory, with the remainder stored on
+// disk in temporary files.
+// ParseMultipartForm calls ParseForm if necessary.
+// After one call to ParseMultipartForm, subsequent calls have no effect.
+func (r *Request) ParseMultipartForm(maxMemory int64) error {
+	if r.MultipartForm == multipartByReader {
+		return errors.New("http: multipart handled by MultipartReader")
+	}
+	if r.Form == nil {
+		err := r.ParseForm()
+		if err != nil {
+			return err
+		}
+	}
+	if r.MultipartForm != nil {
+		return nil
+	}
+
+	mr, err := r.multipartReader()
+	if err != nil {
+		return err
+	}
+
+	f, err := mr.ReadForm(maxMemory)
+	if err != nil {
+		return err
+	}
+	for k, v := range f.Value {
+		r.Form[k] = append(r.Form[k], v...)
+	}
+	r.MultipartForm = f
+
+	return nil
+}
+
+// FormValue returns the first value for the named component of the query.
+// POST and PUT body parameters take precedence over URL query string values.
+// FormValue calls ParseMultipartForm and ParseForm if necessary.
+// To access multiple values of the same key use ParseForm.
+func (r *Request) FormValue(key string) string {
+	if r.Form == nil {
+		r.ParseMultipartForm(defaultMaxMemory)
+	}
+	if vs := r.Form[key]; len(vs) > 0 {
+		return vs[0]
+	}
+	return ""
+}
+
+// PostFormValue returns the first value for the named component of the POST
+// or PUT request body. URL query parameters are ignored.
+// PostFormValue calls ParseMultipartForm and ParseForm if necessary.
+func (r *Request) PostFormValue(key string) string {
+	if r.PostForm == nil {
+		r.ParseMultipartForm(defaultMaxMemory)
+	}
+	if vs := r.PostForm[key]; len(vs) > 0 {
+		return vs[0]
+	}
+	return ""
+}
+
+// FormFile returns the first file for the provided form key.
+// FormFile calls ParseMultipartForm and ParseForm if necessary.
+func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error) {
+	if r.MultipartForm == multipartByReader {
+		return nil, nil, errors.New("http: multipart handled by MultipartReader")
+	}
+	if r.MultipartForm == nil {
+		err := r.ParseMultipartForm(defaultMaxMemory)
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+	if r.MultipartForm != nil && r.MultipartForm.File != nil {
+		if fhs := r.MultipartForm.File[key]; len(fhs) > 0 {
+			f, err := fhs[0].Open()
+			return f, fhs[0], err
+		}
+	}
+	return nil, nil, ErrMissingFile
+}
+
+func (r *Request) expectsContinue() bool {
+	return hasToken(r.Header.get("Expect"), "100-continue")
+}
+
+func (r *Request) wantsHttp10KeepAlive() bool {
+	if r.ProtoMajor != 1 || r.ProtoMinor != 0 {
+		return false
+	}
+	return hasToken(r.Header.get("Connection"), "keep-alive")
+}
+
+func (r *Request) wantsClose() bool {
+	return hasToken(r.Header.get("Connection"), "close")
+}
+
+func (r *Request) closeBody() {
+	if r.Body != nil {
+		r.Body.Close()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/request_test.go b/third_party/gofrontend/libgo/go/net/http/request_test.go
new file mode 100644
index 0000000..b9fa3c2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/request_test.go
@@ -0,0 +1,610 @@
+// 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 http_test
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"mime/multipart"
+	. "net/http"
+	"net/http/httptest"
+	"net/url"
+	"os"
+	"reflect"
+	"regexp"
+	"strings"
+	"testing"
+)
+
+func TestQuery(t *testing.T) {
+	req := &Request{Method: "GET"}
+	req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
+	if q := req.FormValue("q"); q != "foo" {
+		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
+	}
+}
+
+func TestPostQuery(t *testing.T) {
+	req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&empty=not",
+		strings.NewReader("z=post&both=y&prio=2&empty="))
+	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
+
+	if q := req.FormValue("q"); q != "foo" {
+		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
+	}
+	if z := req.FormValue("z"); z != "post" {
+		t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
+	}
+	if bq, found := req.PostForm["q"]; found {
+		t.Errorf(`req.PostForm["q"] = %q, want no entry in map`, bq)
+	}
+	if bz := req.PostFormValue("z"); bz != "post" {
+		t.Errorf(`req.PostFormValue("z") = %q, want "post"`, bz)
+	}
+	if qs := req.Form["q"]; !reflect.DeepEqual(qs, []string{"foo", "bar"}) {
+		t.Errorf(`req.Form["q"] = %q, want ["foo", "bar"]`, qs)
+	}
+	if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"y", "x"}) {
+		t.Errorf(`req.Form["both"] = %q, want ["y", "x"]`, both)
+	}
+	if prio := req.FormValue("prio"); prio != "2" {
+		t.Errorf(`req.FormValue("prio") = %q, want "2" (from body)`, prio)
+	}
+	if empty := req.FormValue("empty"); empty != "" {
+		t.Errorf(`req.FormValue("empty") = %q, want "" (from body)`, empty)
+	}
+}
+
+func TestPatchQuery(t *testing.T) {
+	req, _ := NewRequest("PATCH", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&empty=not",
+		strings.NewReader("z=post&both=y&prio=2&empty="))
+	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
+
+	if q := req.FormValue("q"); q != "foo" {
+		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
+	}
+	if z := req.FormValue("z"); z != "post" {
+		t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
+	}
+	if bq, found := req.PostForm["q"]; found {
+		t.Errorf(`req.PostForm["q"] = %q, want no entry in map`, bq)
+	}
+	if bz := req.PostFormValue("z"); bz != "post" {
+		t.Errorf(`req.PostFormValue("z") = %q, want "post"`, bz)
+	}
+	if qs := req.Form["q"]; !reflect.DeepEqual(qs, []string{"foo", "bar"}) {
+		t.Errorf(`req.Form["q"] = %q, want ["foo", "bar"]`, qs)
+	}
+	if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"y", "x"}) {
+		t.Errorf(`req.Form["both"] = %q, want ["y", "x"]`, both)
+	}
+	if prio := req.FormValue("prio"); prio != "2" {
+		t.Errorf(`req.FormValue("prio") = %q, want "2" (from body)`, prio)
+	}
+	if empty := req.FormValue("empty"); empty != "" {
+		t.Errorf(`req.FormValue("empty") = %q, want "" (from body)`, empty)
+	}
+}
+
+type stringMap map[string][]string
+type parseContentTypeTest struct {
+	shouldError bool
+	contentType stringMap
+}
+
+var parseContentTypeTests = []parseContentTypeTest{
+	{false, stringMap{"Content-Type": {"text/plain"}}},
+	// Empty content type is legal - shoult be treated as
+	// application/octet-stream (RFC 2616, section 7.2.1)
+	{false, stringMap{}},
+	{true, stringMap{"Content-Type": {"text/plain; boundary="}}},
+	{false, stringMap{"Content-Type": {"application/unknown"}}},
+}
+
+func TestParseFormUnknownContentType(t *testing.T) {
+	for i, test := range parseContentTypeTests {
+		req := &Request{
+			Method: "POST",
+			Header: Header(test.contentType),
+			Body:   ioutil.NopCloser(strings.NewReader("body")),
+		}
+		err := req.ParseForm()
+		switch {
+		case err == nil && test.shouldError:
+			t.Errorf("test %d should have returned error", i)
+		case err != nil && !test.shouldError:
+			t.Errorf("test %d should not have returned error, got %v", i, err)
+		}
+	}
+}
+
+func TestParseFormInitializeOnError(t *testing.T) {
+	nilBody, _ := NewRequest("POST", "http://www.google.com/search?q=foo", nil)
+	tests := []*Request{
+		nilBody,
+		{Method: "GET", URL: nil},
+	}
+	for i, req := range tests {
+		err := req.ParseForm()
+		if req.Form == nil {
+			t.Errorf("%d. Form not initialized, error %v", i, err)
+		}
+		if req.PostForm == nil {
+			t.Errorf("%d. PostForm not initialized, error %v", i, err)
+		}
+	}
+}
+
+func TestMultipartReader(t *testing.T) {
+	req := &Request{
+		Method: "POST",
+		Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
+		Body:   ioutil.NopCloser(new(bytes.Buffer)),
+	}
+	multipart, err := req.MultipartReader()
+	if multipart == nil {
+		t.Errorf("expected multipart; error: %v", err)
+	}
+
+	req.Header = Header{"Content-Type": {"text/plain"}}
+	multipart, err = req.MultipartReader()
+	if multipart != nil {
+		t.Error("unexpected multipart for text/plain")
+	}
+}
+
+func TestParseMultipartForm(t *testing.T) {
+	req := &Request{
+		Method: "POST",
+		Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
+		Body:   ioutil.NopCloser(new(bytes.Buffer)),
+	}
+	err := req.ParseMultipartForm(25)
+	if err == nil {
+		t.Error("expected multipart EOF, got nil")
+	}
+
+	req.Header = Header{"Content-Type": {"text/plain"}}
+	err = req.ParseMultipartForm(25)
+	if err != ErrNotMultipart {
+		t.Error("expected ErrNotMultipart for text/plain")
+	}
+}
+
+func TestRedirect(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		switch r.URL.Path {
+		case "/":
+			w.Header().Set("Location", "/foo/")
+			w.WriteHeader(StatusSeeOther)
+		case "/foo/":
+			fmt.Fprintf(w, "foo")
+		default:
+			w.WriteHeader(StatusBadRequest)
+		}
+	}))
+	defer ts.Close()
+
+	var end = regexp.MustCompile("/foo/$")
+	r, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	r.Body.Close()
+	url := r.Request.URL.String()
+	if r.StatusCode != 200 || !end.MatchString(url) {
+		t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url)
+	}
+}
+
+func TestSetBasicAuth(t *testing.T) {
+	r, _ := NewRequest("GET", "http://example.com/", nil)
+	r.SetBasicAuth("Aladdin", "open sesame")
+	if g, e := r.Header.Get("Authorization"), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; g != e {
+		t.Errorf("got header %q, want %q", g, e)
+	}
+}
+
+func TestMultipartRequest(t *testing.T) {
+	// Test that we can read the values and files of a
+	// multipart request with FormValue and FormFile,
+	// and that ParseMultipartForm can be called multiple times.
+	req := newTestMultipartRequest(t)
+	if err := req.ParseMultipartForm(25); err != nil {
+		t.Fatal("ParseMultipartForm first call:", err)
+	}
+	defer req.MultipartForm.RemoveAll()
+	validateTestMultipartContents(t, req, false)
+	if err := req.ParseMultipartForm(25); err != nil {
+		t.Fatal("ParseMultipartForm second call:", err)
+	}
+	validateTestMultipartContents(t, req, false)
+}
+
+func TestMultipartRequestAuto(t *testing.T) {
+	// Test that FormValue and FormFile automatically invoke
+	// ParseMultipartForm and return the right values.
+	req := newTestMultipartRequest(t)
+	defer func() {
+		if req.MultipartForm != nil {
+			req.MultipartForm.RemoveAll()
+		}
+	}()
+	validateTestMultipartContents(t, req, true)
+}
+
+func TestMissingFileMultipartRequest(t *testing.T) {
+	// Test that FormFile returns an error if
+	// the named file is missing.
+	req := newTestMultipartRequest(t)
+	testMissingFile(t, req)
+}
+
+// Test that FormValue invokes ParseMultipartForm.
+func TestFormValueCallsParseMultipartForm(t *testing.T) {
+	req, _ := NewRequest("POST", "http://www.google.com/", strings.NewReader("z=post"))
+	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
+	if req.Form != nil {
+		t.Fatal("Unexpected request Form, want nil")
+	}
+	req.FormValue("z")
+	if req.Form == nil {
+		t.Fatal("ParseMultipartForm not called by FormValue")
+	}
+}
+
+// Test that FormFile invokes ParseMultipartForm.
+func TestFormFileCallsParseMultipartForm(t *testing.T) {
+	req := newTestMultipartRequest(t)
+	if req.Form != nil {
+		t.Fatal("Unexpected request Form, want nil")
+	}
+	req.FormFile("")
+	if req.Form == nil {
+		t.Fatal("ParseMultipartForm not called by FormFile")
+	}
+}
+
+// Test that ParseMultipartForm errors if called
+// after MultipartReader on the same request.
+func TestParseMultipartFormOrder(t *testing.T) {
+	req := newTestMultipartRequest(t)
+	if _, err := req.MultipartReader(); err != nil {
+		t.Fatalf("MultipartReader: %v", err)
+	}
+	if err := req.ParseMultipartForm(1024); err == nil {
+		t.Fatal("expected an error from ParseMultipartForm after call to MultipartReader")
+	}
+}
+
+// Test that MultipartReader errors if called
+// after ParseMultipartForm on the same request.
+func TestMultipartReaderOrder(t *testing.T) {
+	req := newTestMultipartRequest(t)
+	if err := req.ParseMultipartForm(25); err != nil {
+		t.Fatalf("ParseMultipartForm: %v", err)
+	}
+	defer req.MultipartForm.RemoveAll()
+	if _, err := req.MultipartReader(); err == nil {
+		t.Fatal("expected an error from MultipartReader after call to ParseMultipartForm")
+	}
+}
+
+// Test that FormFile errors if called after
+// MultipartReader on the same request.
+func TestFormFileOrder(t *testing.T) {
+	req := newTestMultipartRequest(t)
+	if _, err := req.MultipartReader(); err != nil {
+		t.Fatalf("MultipartReader: %v", err)
+	}
+	if _, _, err := req.FormFile(""); err == nil {
+		t.Fatal("expected an error from FormFile after call to MultipartReader")
+	}
+}
+
+var readRequestErrorTests = []struct {
+	in  string
+	err error
+}{
+	{"GET / HTTP/1.1\r\nheader:foo\r\n\r\n", nil},
+	{"GET / HTTP/1.1\r\nheader:foo\r\n", io.ErrUnexpectedEOF},
+	{"", io.EOF},
+}
+
+func TestReadRequestErrors(t *testing.T) {
+	for i, tt := range readRequestErrorTests {
+		_, err := ReadRequest(bufio.NewReader(strings.NewReader(tt.in)))
+		if err != tt.err {
+			t.Errorf("%d. got error = %v; want %v", i, err, tt.err)
+		}
+	}
+}
+
+func TestNewRequestHost(t *testing.T) {
+	req, err := NewRequest("GET", "http://localhost:1234/", nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if req.Host != "localhost:1234" {
+		t.Errorf("Host = %q; want localhost:1234", req.Host)
+	}
+}
+
+func TestNewRequestContentLength(t *testing.T) {
+	readByte := func(r io.Reader) io.Reader {
+		var b [1]byte
+		r.Read(b[:])
+		return r
+	}
+	tests := []struct {
+		r    io.Reader
+		want int64
+	}{
+		{bytes.NewReader([]byte("123")), 3},
+		{bytes.NewBuffer([]byte("1234")), 4},
+		{strings.NewReader("12345"), 5},
+		// Not detected:
+		{struct{ io.Reader }{strings.NewReader("xyz")}, 0},
+		{io.NewSectionReader(strings.NewReader("x"), 0, 6), 0},
+		{readByte(io.NewSectionReader(strings.NewReader("xy"), 0, 6)), 0},
+	}
+	for _, tt := range tests {
+		req, err := NewRequest("POST", "http://localhost/", tt.r)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if req.ContentLength != tt.want {
+			t.Errorf("ContentLength(%T) = %d; want %d", tt.r, req.ContentLength, tt.want)
+		}
+	}
+}
+
+var parseHTTPVersionTests = []struct {
+	vers         string
+	major, minor int
+	ok           bool
+}{
+	{"HTTP/0.9", 0, 9, true},
+	{"HTTP/1.0", 1, 0, true},
+	{"HTTP/1.1", 1, 1, true},
+	{"HTTP/3.14", 3, 14, true},
+
+	{"HTTP", 0, 0, false},
+	{"HTTP/one.one", 0, 0, false},
+	{"HTTP/1.1/", 0, 0, false},
+	{"HTTP/-1,0", 0, 0, false},
+	{"HTTP/0,-1", 0, 0, false},
+	{"HTTP/", 0, 0, false},
+	{"HTTP/1,1", 0, 0, false},
+}
+
+func TestParseHTTPVersion(t *testing.T) {
+	for _, tt := range parseHTTPVersionTests {
+		major, minor, ok := ParseHTTPVersion(tt.vers)
+		if ok != tt.ok || major != tt.major || minor != tt.minor {
+			type version struct {
+				major, minor int
+				ok           bool
+			}
+			t.Errorf("failed to parse %q, expected: %#v, got %#v", tt.vers, version{tt.major, tt.minor, tt.ok}, version{major, minor, ok})
+		}
+	}
+}
+
+type logWrites struct {
+	t   *testing.T
+	dst *[]string
+}
+
+func (l logWrites) WriteByte(c byte) error {
+	l.t.Fatalf("unexpected WriteByte call")
+	return nil
+}
+
+func (l logWrites) Write(p []byte) (n int, err error) {
+	*l.dst = append(*l.dst, string(p))
+	return len(p), nil
+}
+
+func TestRequestWriteBufferedWriter(t *testing.T) {
+	got := []string{}
+	req, _ := NewRequest("GET", "http://foo.com/", nil)
+	req.Write(logWrites{t, &got})
+	want := []string{
+		"GET / HTTP/1.1\r\n",
+		"Host: foo.com\r\n",
+		"User-Agent: " + DefaultUserAgent + "\r\n",
+		"\r\n",
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Writes = %q\n  Want = %q", got, want)
+	}
+}
+
+func testMissingFile(t *testing.T, req *Request) {
+	f, fh, err := req.FormFile("missing")
+	if f != nil {
+		t.Errorf("FormFile file = %v, want nil", f)
+	}
+	if fh != nil {
+		t.Errorf("FormFile file header = %q, want nil", fh)
+	}
+	if err != ErrMissingFile {
+		t.Errorf("FormFile err = %q, want ErrMissingFile", err)
+	}
+}
+
+func newTestMultipartRequest(t *testing.T) *Request {
+	b := strings.NewReader(strings.Replace(message, "\n", "\r\n", -1))
+	req, err := NewRequest("POST", "/", b)
+	if err != nil {
+		t.Fatal("NewRequest:", err)
+	}
+	ctype := fmt.Sprintf(`multipart/form-data; boundary="%s"`, boundary)
+	req.Header.Set("Content-type", ctype)
+	return req
+}
+
+func validateTestMultipartContents(t *testing.T, req *Request, allMem bool) {
+	if g, e := req.FormValue("texta"), textaValue; g != e {
+		t.Errorf("texta value = %q, want %q", g, e)
+	}
+	if g, e := req.FormValue("textb"), textbValue; g != e {
+		t.Errorf("textb value = %q, want %q", g, e)
+	}
+	if g := req.FormValue("missing"); g != "" {
+		t.Errorf("missing value = %q, want empty string", g)
+	}
+
+	assertMem := func(n string, fd multipart.File) {
+		if _, ok := fd.(*os.File); ok {
+			t.Error(n, " is *os.File, should not be")
+		}
+	}
+	fda := testMultipartFile(t, req, "filea", "filea.txt", fileaContents)
+	defer fda.Close()
+	assertMem("filea", fda)
+	fdb := testMultipartFile(t, req, "fileb", "fileb.txt", filebContents)
+	defer fdb.Close()
+	if allMem {
+		assertMem("fileb", fdb)
+	} else {
+		if _, ok := fdb.(*os.File); !ok {
+			t.Errorf("fileb has unexpected underlying type %T", fdb)
+		}
+	}
+
+	testMissingFile(t, req)
+}
+
+func testMultipartFile(t *testing.T, req *Request, key, expectFilename, expectContent string) multipart.File {
+	f, fh, err := req.FormFile(key)
+	if err != nil {
+		t.Fatalf("FormFile(%q): %q", key, err)
+	}
+	if fh.Filename != expectFilename {
+		t.Errorf("filename = %q, want %q", fh.Filename, expectFilename)
+	}
+	var b bytes.Buffer
+	_, err = io.Copy(&b, f)
+	if err != nil {
+		t.Fatal("copying contents:", err)
+	}
+	if g := b.String(); g != expectContent {
+		t.Errorf("contents = %q, want %q", g, expectContent)
+	}
+	return f
+}
+
+const (
+	fileaContents = "This is a test file."
+	filebContents = "Another test file."
+	textaValue    = "foo"
+	textbValue    = "bar"
+	boundary      = `MyBoundary`
+)
+
+const message = `
+--MyBoundary
+Content-Disposition: form-data; name="filea"; filename="filea.txt"
+Content-Type: text/plain
+
+` + fileaContents + `
+--MyBoundary
+Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
+Content-Type: text/plain
+
+` + filebContents + `
+--MyBoundary
+Content-Disposition: form-data; name="texta"
+
+` + textaValue + `
+--MyBoundary
+Content-Disposition: form-data; name="textb"
+
+` + textbValue + `
+--MyBoundary--
+`
+
+func benchmarkReadRequest(b *testing.B, request string) {
+	request = request + "\n"                             // final \n
+	request = strings.Replace(request, "\n", "\r\n", -1) // expand \n to \r\n
+	b.SetBytes(int64(len(request)))
+	r := bufio.NewReader(&infiniteReader{buf: []byte(request)})
+	b.ReportAllocs()
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, err := ReadRequest(r)
+		if err != nil {
+			b.Fatalf("failed to read request: %v", err)
+		}
+	}
+}
+
+// infiniteReader satisfies Read requests as if the contents of buf
+// loop indefinitely.
+type infiniteReader struct {
+	buf    []byte
+	offset int
+}
+
+func (r *infiniteReader) Read(b []byte) (int, error) {
+	n := copy(b, r.buf[r.offset:])
+	r.offset = (r.offset + n) % len(r.buf)
+	return n, nil
+}
+
+func BenchmarkReadRequestChrome(b *testing.B) {
+	// https://github.com/felixge/node-http-perf/blob/master/fixtures/get.http
+	benchmarkReadRequest(b, `GET / HTTP/1.1
+Host: localhost:8080
+Connection: keep-alive
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
+Accept-Encoding: gzip,deflate,sdch
+Accept-Language: en-US,en;q=0.8
+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
+Cookie: __utma=1.1978842379.1323102373.1323102373.1323102373.1; EPi:NumberOfVisits=1,2012-02-28T13:42:18; CrmSession=5b707226b9563e1bc69084d07a107c98; plushContainerWidth=100%25; plushNoTopMenu=0; hudson_auto_refresh=false
+`)
+}
+
+func BenchmarkReadRequestCurl(b *testing.B) {
+	// curl http://localhost:8080/
+	benchmarkReadRequest(b, `GET / HTTP/1.1
+User-Agent: curl/7.27.0
+Host: localhost:8080
+Accept: */*
+`)
+}
+
+func BenchmarkReadRequestApachebench(b *testing.B) {
+	// ab -n 1 -c 1 http://localhost:8080/
+	benchmarkReadRequest(b, `GET / HTTP/1.0
+Host: localhost:8080
+User-Agent: ApacheBench/2.3
+Accept: */*
+`)
+}
+
+func BenchmarkReadRequestSiege(b *testing.B) {
+	// siege -r 1 -c 1 http://localhost:8080/
+	benchmarkReadRequest(b, `GET / HTTP/1.1
+Host: localhost:8080
+Accept: */*
+Accept-Encoding: gzip
+User-Agent: JoeDog/1.00 [en] (X11; I; Siege 2.70)
+Connection: keep-alive
+`)
+}
+
+func BenchmarkReadRequestWrk(b *testing.B) {
+	// wrk -t 1 -r 1 -c 1 http://localhost:8080/
+	benchmarkReadRequest(b, `GET / HTTP/1.1
+Host: localhost:8080
+`)
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/requestwrite_test.go b/third_party/gofrontend/libgo/go/net/http/requestwrite_test.go
new file mode 100644
index 0000000..dc0e204
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/requestwrite_test.go
@@ -0,0 +1,565 @@
+// Copyright 2010 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 http
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/url"
+	"strings"
+	"testing"
+)
+
+type reqWriteTest struct {
+	Req  Request
+	Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body
+
+	// Any of these three may be empty to skip that test.
+	WantWrite string // Request.Write
+	WantProxy string // Request.WriteProxy
+
+	WantError error // wanted error from Request.Write
+}
+
+var reqWriteTests = []reqWriteTest{
+	// HTTP/1.1 => chunked coding; no body; no trailer
+	{
+		Req: Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.techcrunch.com",
+				Path:   "/",
+			},
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"Accept":           {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
+				"Accept-Charset":   {"ISO-8859-1,utf-8;q=0.7,*;q=0.7"},
+				"Accept-Encoding":  {"gzip,deflate"},
+				"Accept-Language":  {"en-us,en;q=0.5"},
+				"Keep-Alive":       {"300"},
+				"Proxy-Connection": {"keep-alive"},
+				"User-Agent":       {"Fake"},
+			},
+			Body:  nil,
+			Close: false,
+			Host:  "www.techcrunch.com",
+			Form:  map[string][]string{},
+		},
+
+		WantWrite: "GET / HTTP/1.1\r\n" +
+			"Host: www.techcrunch.com\r\n" +
+			"User-Agent: Fake\r\n" +
+			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
+			"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
+			"Accept-Encoding: gzip,deflate\r\n" +
+			"Accept-Language: en-us,en;q=0.5\r\n" +
+			"Keep-Alive: 300\r\n" +
+			"Proxy-Connection: keep-alive\r\n\r\n",
+
+		WantProxy: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
+			"Host: www.techcrunch.com\r\n" +
+			"User-Agent: Fake\r\n" +
+			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
+			"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
+			"Accept-Encoding: gzip,deflate\r\n" +
+			"Accept-Language: en-us,en;q=0.5\r\n" +
+			"Keep-Alive: 300\r\n" +
+			"Proxy-Connection: keep-alive\r\n\r\n",
+	},
+	// HTTP/1.1 => chunked coding; body; empty trailer
+	{
+		Req: Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Path:   "/search",
+			},
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Header:           Header{},
+			TransferEncoding: []string{"chunked"},
+		},
+
+		Body: []byte("abcdef"),
+
+		WantWrite: "GET /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("abcdef") + chunk(""),
+
+		WantProxy: "GET http://www.google.com/search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("abcdef") + chunk(""),
+	},
+	// HTTP/1.1 POST => chunked coding; body; empty trailer
+	{
+		Req: Request{
+			Method: "POST",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Path:   "/search",
+			},
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Header:           Header{},
+			Close:            true,
+			TransferEncoding: []string{"chunked"},
+		},
+
+		Body: []byte("abcdef"),
+
+		WantWrite: "POST /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Connection: close\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("abcdef") + chunk(""),
+
+		WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Connection: close\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("abcdef") + chunk(""),
+	},
+
+	// HTTP/1.1 POST with Content-Length, no chunking
+	{
+		Req: Request{
+			Method: "POST",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Path:   "/search",
+			},
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         true,
+			ContentLength: 6,
+		},
+
+		Body: []byte("abcdef"),
+
+		WantWrite: "POST /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Connection: close\r\n" +
+			"Content-Length: 6\r\n" +
+			"\r\n" +
+			"abcdef",
+
+		WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Connection: close\r\n" +
+			"Content-Length: 6\r\n" +
+			"\r\n" +
+			"abcdef",
+	},
+
+	// HTTP/1.1 POST with Content-Length in headers
+	{
+		Req: Request{
+			Method: "POST",
+			URL:    mustParseURL("http://example.com/"),
+			Host:   "example.com",
+			Header: Header{
+				"Content-Length": []string{"10"}, // ignored
+			},
+			ContentLength: 6,
+		},
+
+		Body: []byte("abcdef"),
+
+		WantWrite: "POST / HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Content-Length: 6\r\n" +
+			"\r\n" +
+			"abcdef",
+
+		WantProxy: "POST http://example.com/ HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Content-Length: 6\r\n" +
+			"\r\n" +
+			"abcdef",
+	},
+
+	// default to HTTP/1.1
+	{
+		Req: Request{
+			Method: "GET",
+			URL:    mustParseURL("/search"),
+			Host:   "www.google.com",
+		},
+
+		WantWrite: "GET /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"\r\n",
+	},
+
+	// Request with a 0 ContentLength and a 0 byte body.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 0, // as if unset by user
+		},
+
+		Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
+
+		// RFC 2616 Section 14.13 says Content-Length should be specified
+		// unless body is prohibited by the request method.
+		// Also, nginx expects it for POST and PUT.
+		WantWrite: "POST / HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Content-Length: 0\r\n" +
+			"\r\n",
+
+		WantProxy: "POST / HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Content-Length: 0\r\n" +
+			"\r\n",
+	},
+
+	// Request with a 0 ContentLength and a 1 byte body.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 0, // as if unset by user
+		},
+
+		Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) },
+
+		WantWrite: "POST / HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("x") + chunk(""),
+
+		WantProxy: "POST / HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("x") + chunk(""),
+	},
+
+	// Request with a ContentLength of 10 but a 5 byte body.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 10, // but we're going to send only 5 bytes
+		},
+		Body:      []byte("12345"),
+		WantError: errors.New("http: Request.ContentLength=10 with Body length 5"),
+	},
+
+	// Request with a ContentLength of 4 but an 8 byte body.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 4, // but we're going to try to send 8 bytes
+		},
+		Body:      []byte("12345678"),
+		WantError: errors.New("http: Request.ContentLength=4 with Body length 8"),
+	},
+
+	// Request with a 5 ContentLength and nil body.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 5, // but we'll omit the body
+		},
+		WantError: errors.New("http: Request.ContentLength=5 with nil Body"),
+	},
+
+	// Request with a 0 ContentLength and a body with 1 byte content and an error.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 0, // as if unset by user
+		},
+
+		Body: func() io.ReadCloser {
+			err := errors.New("Custom reader error")
+			errReader := &errorReader{err}
+			return ioutil.NopCloser(io.MultiReader(strings.NewReader("x"), errReader))
+		},
+
+		WantError: errors.New("Custom reader error"),
+	},
+
+	// Request with a 0 ContentLength and a body without content and an error.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 0, // as if unset by user
+		},
+
+		Body: func() io.ReadCloser {
+			err := errors.New("Custom reader error")
+			errReader := &errorReader{err}
+			return ioutil.NopCloser(errReader)
+		},
+
+		WantError: errors.New("Custom reader error"),
+	},
+
+	// Verify that DumpRequest preserves the HTTP version number, doesn't add a Host,
+	// and doesn't add a User-Agent.
+	{
+		Req: Request{
+			Method:     "GET",
+			URL:        mustParseURL("/foo"),
+			ProtoMajor: 1,
+			ProtoMinor: 0,
+			Header: Header{
+				"X-Foo": []string{"X-Bar"},
+			},
+		},
+
+		WantWrite: "GET /foo HTTP/1.1\r\n" +
+			"Host: \r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"X-Foo: X-Bar\r\n\r\n",
+	},
+
+	// If no Request.Host and no Request.URL.Host, we send
+	// an empty Host header, and don't use
+	// Request.Header["Host"]. This is just testing that
+	// we don't change Go 1.0 behavior.
+	{
+		Req: Request{
+			Method: "GET",
+			Host:   "",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "",
+				Path:   "/search",
+			},
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"Host": []string{"bad.example.com"},
+			},
+		},
+
+		WantWrite: "GET /search HTTP/1.1\r\n" +
+			"Host: \r\n" +
+			"User-Agent: Go 1.1 package http\r\n\r\n",
+	},
+
+	// Opaque test #1 from golang.org/issue/4860
+	{
+		Req: Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Opaque: "/%2F/%2F/",
+			},
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header:     Header{},
+		},
+
+		WantWrite: "GET /%2F/%2F/ HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n\r\n",
+	},
+
+	// Opaque test #2 from golang.org/issue/4860
+	{
+		Req: Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "x.google.com",
+				Opaque: "//y.google.com/%2F/%2F/",
+			},
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header:     Header{},
+		},
+
+		WantWrite: "GET http://y.google.com/%2F/%2F/ HTTP/1.1\r\n" +
+			"Host: x.google.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n\r\n",
+	},
+
+	// Testing custom case in header keys. Issue 5022.
+	{
+		Req: Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Path:   "/",
+			},
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"ALL-CAPS": {"x"},
+			},
+		},
+
+		WantWrite: "GET / HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go 1.1 package http\r\n" +
+			"ALL-CAPS: x\r\n" +
+			"\r\n",
+	},
+}
+
+func TestRequestWrite(t *testing.T) {
+	for i := range reqWriteTests {
+		tt := &reqWriteTests[i]
+
+		setBody := func() {
+			if tt.Body == nil {
+				return
+			}
+			switch b := tt.Body.(type) {
+			case []byte:
+				tt.Req.Body = ioutil.NopCloser(bytes.NewReader(b))
+			case func() io.ReadCloser:
+				tt.Req.Body = b()
+			}
+		}
+		setBody()
+		if tt.Req.Header == nil {
+			tt.Req.Header = make(Header)
+		}
+
+		var braw bytes.Buffer
+		err := tt.Req.Write(&braw)
+		if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.WantError); g != e {
+			t.Errorf("writing #%d, err = %q, want %q", i, g, e)
+			continue
+		}
+		if err != nil {
+			continue
+		}
+
+		if tt.WantWrite != "" {
+			sraw := braw.String()
+			if sraw != tt.WantWrite {
+				t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantWrite, sraw)
+				continue
+			}
+		}
+
+		if tt.WantProxy != "" {
+			setBody()
+			var praw bytes.Buffer
+			err = tt.Req.WriteProxy(&praw)
+			if err != nil {
+				t.Errorf("WriteProxy #%d: %s", i, err)
+				continue
+			}
+			sraw := praw.String()
+			if sraw != tt.WantProxy {
+				t.Errorf("Test Proxy %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantProxy, sraw)
+				continue
+			}
+		}
+	}
+}
+
+type closeChecker struct {
+	io.Reader
+	closed bool
+}
+
+func (rc *closeChecker) Close() error {
+	rc.closed = true
+	return nil
+}
+
+// TestRequestWriteClosesBody tests that Request.Write does close its request.Body.
+// It also indirectly tests NewRequest and that it doesn't wrap an existing Closer
+// inside a NopCloser, and that it serializes it correctly.
+func TestRequestWriteClosesBody(t *testing.T) {
+	rc := &closeChecker{Reader: strings.NewReader("my body")}
+	req, _ := NewRequest("POST", "http://foo.com/", rc)
+	if req.ContentLength != 0 {
+		t.Errorf("got req.ContentLength %d, want 0", req.ContentLength)
+	}
+	buf := new(bytes.Buffer)
+	req.Write(buf)
+	if !rc.closed {
+		t.Error("body not closed after write")
+	}
+	expected := "POST / HTTP/1.1\r\n" +
+		"Host: foo.com\r\n" +
+		"User-Agent: Go 1.1 package http\r\n" +
+		"Transfer-Encoding: chunked\r\n\r\n" +
+		// TODO: currently we don't buffer before chunking, so we get a
+		// single "m" chunk before the other chunks, as this was the 1-byte
+		// read from our MultiReader where we stiched the Body back together
+		// after sniffing whether the Body was 0 bytes or not.
+		chunk("m") +
+		chunk("y body") +
+		chunk("")
+	if buf.String() != expected {
+		t.Errorf("write:\n got: %s\nwant: %s", buf.String(), expected)
+	}
+}
+
+func chunk(s string) string {
+	return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
+}
+
+func mustParseURL(s string) *url.URL {
+	u, err := url.Parse(s)
+	if err != nil {
+		panic(fmt.Sprintf("Error parsing URL %q: %v", s, err))
+	}
+	return u
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/response.go b/third_party/gofrontend/libgo/go/net/http/response.go
new file mode 100644
index 0000000..5d2c390
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/response.go
@@ -0,0 +1,291 @@
+// 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.
+
+// HTTP Response reading and parsing.
+
+package http
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/tls"
+	"errors"
+	"io"
+	"net/textproto"
+	"net/url"
+	"strconv"
+	"strings"
+)
+
+var respExcludeHeader = map[string]bool{
+	"Content-Length":    true,
+	"Transfer-Encoding": true,
+	"Trailer":           true,
+}
+
+// Response represents the response from an HTTP request.
+//
+type Response struct {
+	Status     string // e.g. "200 OK"
+	StatusCode int    // e.g. 200
+	Proto      string // e.g. "HTTP/1.0"
+	ProtoMajor int    // e.g. 1
+	ProtoMinor int    // e.g. 0
+
+	// Header maps header keys to values.  If the response had multiple
+	// headers with the same key, they may be concatenated, with comma
+	// delimiters.  (Section 4.2 of RFC 2616 requires that multiple headers
+	// be semantically equivalent to a comma-delimited sequence.) Values
+	// duplicated by other fields in this struct (e.g., ContentLength) are
+	// omitted from Header.
+	//
+	// Keys in the map are canonicalized (see CanonicalHeaderKey).
+	Header Header
+
+	// Body represents the response body.
+	//
+	// The http Client and Transport guarantee that Body is always
+	// non-nil, even on responses without a body or responses with
+	// a zero-length body. It is the caller's responsibility to
+	// close Body.
+	//
+	// The Body is automatically dechunked if the server replied
+	// with a "chunked" Transfer-Encoding.
+	Body io.ReadCloser
+
+	// ContentLength records the length of the associated content.  The
+	// value -1 indicates that the length is unknown.  Unless Request.Method
+	// is "HEAD", values >= 0 indicate that the given number of bytes may
+	// be read from Body.
+	ContentLength int64
+
+	// Contains transfer encodings from outer-most to inner-most. Value is
+	// nil, means that "identity" encoding is used.
+	TransferEncoding []string
+
+	// Close records whether the header directed that the connection be
+	// closed after reading Body.  The value is advice for clients: neither
+	// ReadResponse nor Response.Write ever closes a connection.
+	Close bool
+
+	// Trailer maps trailer keys to values, in the same
+	// format as the header.
+	Trailer Header
+
+	// The Request that was sent to obtain this Response.
+	// Request's Body is nil (having already been consumed).
+	// This is only populated for Client requests.
+	Request *Request
+
+	// TLS contains information about the TLS connection on which the
+	// response was received. It is nil for unencrypted responses.
+	// The pointer is shared between responses and should not be
+	// modified.
+	TLS *tls.ConnectionState
+}
+
+// Cookies parses and returns the cookies set in the Set-Cookie headers.
+func (r *Response) Cookies() []*Cookie {
+	return readSetCookies(r.Header)
+}
+
+var ErrNoLocation = errors.New("http: no Location header in response")
+
+// Location returns the URL of the response's "Location" header,
+// if present.  Relative redirects are resolved relative to
+// the Response's Request.  ErrNoLocation is returned if no
+// Location header is present.
+func (r *Response) Location() (*url.URL, error) {
+	lv := r.Header.Get("Location")
+	if lv == "" {
+		return nil, ErrNoLocation
+	}
+	if r.Request != nil && r.Request.URL != nil {
+		return r.Request.URL.Parse(lv)
+	}
+	return url.Parse(lv)
+}
+
+// ReadResponse reads and returns an HTTP response from r.
+// The req parameter optionally specifies the Request that corresponds
+// to this Response. If nil, a GET request is assumed.
+// Clients must call resp.Body.Close when finished reading resp.Body.
+// After that call, clients can inspect resp.Trailer to find key/value
+// pairs included in the response trailer.
+func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) {
+	tp := textproto.NewReader(r)
+	resp := &Response{
+		Request: req,
+	}
+
+	// Parse the first line of the response.
+	line, err := tp.ReadLine()
+	if err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		return nil, err
+	}
+	f := strings.SplitN(line, " ", 3)
+	if len(f) < 2 {
+		return nil, &badStringError{"malformed HTTP response", line}
+	}
+	reasonPhrase := ""
+	if len(f) > 2 {
+		reasonPhrase = f[2]
+	}
+	resp.Status = f[1] + " " + reasonPhrase
+	resp.StatusCode, err = strconv.Atoi(f[1])
+	if err != nil {
+		return nil, &badStringError{"malformed HTTP status code", f[1]}
+	}
+
+	resp.Proto = f[0]
+	var ok bool
+	if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok {
+		return nil, &badStringError{"malformed HTTP version", resp.Proto}
+	}
+
+	// Parse the response headers.
+	mimeHeader, err := tp.ReadMIMEHeader()
+	if err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		return nil, err
+	}
+	resp.Header = Header(mimeHeader)
+
+	fixPragmaCacheControl(resp.Header)
+
+	err = readTransfer(resp, r)
+	if err != nil {
+		return nil, err
+	}
+
+	return resp, nil
+}
+
+// RFC2616: Should treat
+//	Pragma: no-cache
+// like
+//	Cache-Control: no-cache
+func fixPragmaCacheControl(header Header) {
+	if hp, ok := header["Pragma"]; ok && len(hp) > 0 && hp[0] == "no-cache" {
+		if _, presentcc := header["Cache-Control"]; !presentcc {
+			header["Cache-Control"] = []string{"no-cache"}
+		}
+	}
+}
+
+// ProtoAtLeast reports whether the HTTP protocol used
+// in the response is at least major.minor.
+func (r *Response) ProtoAtLeast(major, minor int) bool {
+	return r.ProtoMajor > major ||
+		r.ProtoMajor == major && r.ProtoMinor >= minor
+}
+
+// Writes the response (header, body and trailer) in wire format. This method
+// consults the following fields of the response:
+//
+//  StatusCode
+//  ProtoMajor
+//  ProtoMinor
+//  Request.Method
+//  TransferEncoding
+//  Trailer
+//  Body
+//  ContentLength
+//  Header, values for non-canonical keys will have unpredictable behavior
+//
+// Body is closed after it is sent.
+func (r *Response) Write(w io.Writer) error {
+	// Status line
+	text := r.Status
+	if text == "" {
+		var ok bool
+		text, ok = statusText[r.StatusCode]
+		if !ok {
+			text = "status code " + strconv.Itoa(r.StatusCode)
+		}
+	}
+	protoMajor, protoMinor := strconv.Itoa(r.ProtoMajor), strconv.Itoa(r.ProtoMinor)
+	statusCode := strconv.Itoa(r.StatusCode) + " "
+	text = strings.TrimPrefix(text, statusCode)
+	if _, err := io.WriteString(w, "HTTP/"+protoMajor+"."+protoMinor+" "+statusCode+text+"\r\n"); err != nil {
+		return err
+	}
+
+	// Clone it, so we can modify r1 as needed.
+	r1 := new(Response)
+	*r1 = *r
+	if r1.ContentLength == 0 && r1.Body != nil {
+		// Is it actually 0 length? Or just unknown?
+		var buf [1]byte
+		n, err := r1.Body.Read(buf[:])
+		if err != nil && err != io.EOF {
+			return err
+		}
+		if n == 0 {
+			// Reset it to a known zero reader, in case underlying one
+			// is unhappy being read repeatedly.
+			r1.Body = eofReader
+		} else {
+			r1.ContentLength = -1
+			r1.Body = struct {
+				io.Reader
+				io.Closer
+			}{
+				io.MultiReader(bytes.NewReader(buf[:1]), r.Body),
+				r.Body,
+			}
+		}
+	}
+	// If we're sending a non-chunked HTTP/1.1 response without a
+	// content-length, the only way to do that is the old HTTP/1.0
+	// way, by noting the EOF with a connection close, so we need
+	// to set Close.
+	if r1.ContentLength == -1 && !r1.Close && r1.ProtoAtLeast(1, 1) && !chunked(r1.TransferEncoding) {
+		r1.Close = true
+	}
+
+	// Process Body,ContentLength,Close,Trailer
+	tw, err := newTransferWriter(r1)
+	if err != nil {
+		return err
+	}
+	err = tw.WriteHeader(w)
+	if err != nil {
+		return err
+	}
+
+	// Rest of header
+	err = r.Header.WriteSubset(w, respExcludeHeader)
+	if err != nil {
+		return err
+	}
+
+	// contentLengthAlreadySent may have been already sent for
+	// POST/PUT requests, even if zero length. See Issue 8180.
+	contentLengthAlreadySent := tw.shouldSendContentLength()
+	if r1.ContentLength == 0 && !chunked(r1.TransferEncoding) && !contentLengthAlreadySent {
+		if _, err := io.WriteString(w, "Content-Length: 0\r\n"); err != nil {
+			return err
+		}
+	}
+
+	// End-of-header
+	if _, err := io.WriteString(w, "\r\n"); err != nil {
+		return err
+	}
+
+	// Write body and trailer
+	err = tw.WriteBody(w)
+	if err != nil {
+		return err
+	}
+
+	// Success
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/response_test.go b/third_party/gofrontend/libgo/go/net/http/response_test.go
new file mode 100644
index 0000000..4b8946f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/response_test.go
@@ -0,0 +1,645 @@
+// Copyright 2010 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 http
+
+import (
+	"bufio"
+	"bytes"
+	"compress/gzip"
+	"crypto/rand"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/url"
+	"reflect"
+	"regexp"
+	"strings"
+	"testing"
+)
+
+type respTest struct {
+	Raw  string
+	Resp Response
+	Body string
+}
+
+func dummyReq(method string) *Request {
+	return &Request{Method: method}
+}
+
+func dummyReq11(method string) *Request {
+	return &Request{Method: method, Proto: "HTTP/1.1", ProtoMajor: 1, ProtoMinor: 1}
+}
+
+var respTests = []respTest{
+	// Unchunked response without Content-Length.
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Connection: close\r\n" +
+			"\r\n" +
+			"Body here\n",
+
+		Response{
+			Status:     "200 OK",
+			StatusCode: 200,
+			Proto:      "HTTP/1.0",
+			ProtoMajor: 1,
+			ProtoMinor: 0,
+			Request:    dummyReq("GET"),
+			Header: Header{
+				"Connection": {"close"}, // TODO(rsc): Delete?
+			},
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"Body here\n",
+	},
+
+	// Unchunked HTTP/1.1 response without Content-Length or
+	// Connection headers.
+	{
+		"HTTP/1.1 200 OK\r\n" +
+			"\r\n" +
+			"Body here\n",
+
+		Response{
+			Status:        "200 OK",
+			StatusCode:    200,
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Request:       dummyReq("GET"),
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"Body here\n",
+	},
+
+	// Unchunked HTTP/1.1 204 response without Content-Length.
+	{
+		"HTTP/1.1 204 No Content\r\n" +
+			"\r\n" +
+			"Body should not be read!\n",
+
+		Response{
+			Status:        "204 No Content",
+			StatusCode:    204,
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Request:       dummyReq("GET"),
+			Close:         false,
+			ContentLength: 0,
+		},
+
+		"",
+	},
+
+	// Unchunked response with Content-Length.
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Content-Length: 10\r\n" +
+			"Connection: close\r\n" +
+			"\r\n" +
+			"Body here\n",
+
+		Response{
+			Status:     "200 OK",
+			StatusCode: 200,
+			Proto:      "HTTP/1.0",
+			ProtoMajor: 1,
+			ProtoMinor: 0,
+			Request:    dummyReq("GET"),
+			Header: Header{
+				"Connection":     {"close"},
+				"Content-Length": {"10"},
+			},
+			Close:         true,
+			ContentLength: 10,
+		},
+
+		"Body here\n",
+	},
+
+	// Chunked response without Content-Length.
+	{
+		"HTTP/1.1 200 OK\r\n" +
+			"Transfer-Encoding: chunked\r\n" +
+			"\r\n" +
+			"0a\r\n" +
+			"Body here\n\r\n" +
+			"09\r\n" +
+			"continued\r\n" +
+			"0\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.1",
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Request:          dummyReq("GET"),
+			Header:           Header{},
+			Close:            false,
+			ContentLength:    -1,
+			TransferEncoding: []string{"chunked"},
+		},
+
+		"Body here\ncontinued",
+	},
+
+	// Chunked response with Content-Length.
+	{
+		"HTTP/1.1 200 OK\r\n" +
+			"Transfer-Encoding: chunked\r\n" +
+			"Content-Length: 10\r\n" +
+			"\r\n" +
+			"0a\r\n" +
+			"Body here\n\r\n" +
+			"0\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.1",
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Request:          dummyReq("GET"),
+			Header:           Header{},
+			Close:            false,
+			ContentLength:    -1,
+			TransferEncoding: []string{"chunked"},
+		},
+
+		"Body here\n",
+	},
+
+	// Chunked response in response to a HEAD request
+	{
+		"HTTP/1.1 200 OK\r\n" +
+			"Transfer-Encoding: chunked\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.1",
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Request:          dummyReq("HEAD"),
+			Header:           Header{},
+			TransferEncoding: []string{"chunked"},
+			Close:            false,
+			ContentLength:    -1,
+		},
+
+		"",
+	},
+
+	// Content-Length in response to a HEAD request
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Content-Length: 256\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.0",
+			ProtoMajor:       1,
+			ProtoMinor:       0,
+			Request:          dummyReq("HEAD"),
+			Header:           Header{"Content-Length": {"256"}},
+			TransferEncoding: nil,
+			Close:            true,
+			ContentLength:    256,
+		},
+
+		"",
+	},
+
+	// Content-Length in response to a HEAD request with HTTP/1.1
+	{
+		"HTTP/1.1 200 OK\r\n" +
+			"Content-Length: 256\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.1",
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Request:          dummyReq("HEAD"),
+			Header:           Header{"Content-Length": {"256"}},
+			TransferEncoding: nil,
+			Close:            false,
+			ContentLength:    256,
+		},
+
+		"",
+	},
+
+	// No Content-Length or Chunked in response to a HEAD request
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.0",
+			ProtoMajor:       1,
+			ProtoMinor:       0,
+			Request:          dummyReq("HEAD"),
+			Header:           Header{},
+			TransferEncoding: nil,
+			Close:            true,
+			ContentLength:    -1,
+		},
+
+		"",
+	},
+
+	// explicit Content-Length of 0.
+	{
+		"HTTP/1.1 200 OK\r\n" +
+			"Content-Length: 0\r\n" +
+			"\r\n",
+
+		Response{
+			Status:     "200 OK",
+			StatusCode: 200,
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Request:    dummyReq("GET"),
+			Header: Header{
+				"Content-Length": {"0"},
+			},
+			Close:         false,
+			ContentLength: 0,
+		},
+
+		"",
+	},
+
+	// Status line without a Reason-Phrase, but trailing space.
+	// (permitted by RFC 2616)
+	{
+		"HTTP/1.0 303 \r\n\r\n",
+		Response{
+			Status:        "303 ",
+			StatusCode:    303,
+			Proto:         "HTTP/1.0",
+			ProtoMajor:    1,
+			ProtoMinor:    0,
+			Request:       dummyReq("GET"),
+			Header:        Header{},
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"",
+	},
+
+	// Status line without a Reason-Phrase, and no trailing space.
+	// (not permitted by RFC 2616, but we'll accept it anyway)
+	{
+		"HTTP/1.0 303\r\n\r\n",
+		Response{
+			Status:        "303 ",
+			StatusCode:    303,
+			Proto:         "HTTP/1.0",
+			ProtoMajor:    1,
+			ProtoMinor:    0,
+			Request:       dummyReq("GET"),
+			Header:        Header{},
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"",
+	},
+
+	// golang.org/issue/4767: don't special-case multipart/byteranges responses
+	{
+		`HTTP/1.1 206 Partial Content
+Connection: close
+Content-Type: multipart/byteranges; boundary=18a75608c8f47cef
+
+some body`,
+		Response{
+			Status:     "206 Partial Content",
+			StatusCode: 206,
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Request:    dummyReq("GET"),
+			Header: Header{
+				"Content-Type": []string{"multipart/byteranges; boundary=18a75608c8f47cef"},
+			},
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"some body",
+	},
+
+	// Unchunked response without Content-Length, Request is nil
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Connection: close\r\n" +
+			"\r\n" +
+			"Body here\n",
+
+		Response{
+			Status:     "200 OK",
+			StatusCode: 200,
+			Proto:      "HTTP/1.0",
+			ProtoMajor: 1,
+			ProtoMinor: 0,
+			Header: Header{
+				"Connection": {"close"}, // TODO(rsc): Delete?
+			},
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"Body here\n",
+	},
+}
+
+func TestReadResponse(t *testing.T) {
+	for i, tt := range respTests {
+		resp, err := ReadResponse(bufio.NewReader(strings.NewReader(tt.Raw)), tt.Resp.Request)
+		if err != nil {
+			t.Errorf("#%d: %v", i, err)
+			continue
+		}
+		rbody := resp.Body
+		resp.Body = nil
+		diff(t, fmt.Sprintf("#%d Response", i), resp, &tt.Resp)
+		var bout bytes.Buffer
+		if rbody != nil {
+			_, err = io.Copy(&bout, rbody)
+			if err != nil {
+				t.Errorf("#%d: %v", i, err)
+				continue
+			}
+			rbody.Close()
+		}
+		body := bout.String()
+		if body != tt.Body {
+			t.Errorf("#%d: Body = %q want %q", i, body, tt.Body)
+		}
+	}
+}
+
+func TestWriteResponse(t *testing.T) {
+	for i, tt := range respTests {
+		resp, err := ReadResponse(bufio.NewReader(strings.NewReader(tt.Raw)), tt.Resp.Request)
+		if err != nil {
+			t.Errorf("#%d: %v", i, err)
+			continue
+		}
+		err = resp.Write(ioutil.Discard)
+		if err != nil {
+			t.Errorf("#%d: %v", i, err)
+			continue
+		}
+	}
+}
+
+var readResponseCloseInMiddleTests = []struct {
+	chunked, compressed bool
+}{
+	{false, false},
+	{true, false},
+	{true, true},
+}
+
+// TestReadResponseCloseInMiddle tests that closing a body after
+// reading only part of its contents advances the read to the end of
+// the request, right up until the next request.
+func TestReadResponseCloseInMiddle(t *testing.T) {
+	for _, test := range readResponseCloseInMiddleTests {
+		fatalf := func(format string, args ...interface{}) {
+			args = append([]interface{}{test.chunked, test.compressed}, args...)
+			t.Fatalf("on test chunked=%v, compressed=%v: "+format, args...)
+		}
+		checkErr := func(err error, msg string) {
+			if err == nil {
+				return
+			}
+			fatalf(msg+": %v", err)
+		}
+		var buf bytes.Buffer
+		buf.WriteString("HTTP/1.1 200 OK\r\n")
+		if test.chunked {
+			buf.WriteString("Transfer-Encoding: chunked\r\n")
+		} else {
+			buf.WriteString("Content-Length: 1000000\r\n")
+		}
+		var wr io.Writer = &buf
+		if test.chunked {
+			wr = newChunkedWriter(wr)
+		}
+		if test.compressed {
+			buf.WriteString("Content-Encoding: gzip\r\n")
+			wr = gzip.NewWriter(wr)
+		}
+		buf.WriteString("\r\n")
+
+		chunk := bytes.Repeat([]byte{'x'}, 1000)
+		for i := 0; i < 1000; i++ {
+			if test.compressed {
+				// Otherwise this compresses too well.
+				_, err := io.ReadFull(rand.Reader, chunk)
+				checkErr(err, "rand.Reader ReadFull")
+			}
+			wr.Write(chunk)
+		}
+		if test.compressed {
+			err := wr.(*gzip.Writer).Close()
+			checkErr(err, "compressor close")
+		}
+		if test.chunked {
+			buf.WriteString("0\r\n\r\n")
+		}
+		buf.WriteString("Next Request Here")
+
+		bufr := bufio.NewReader(&buf)
+		resp, err := ReadResponse(bufr, dummyReq("GET"))
+		checkErr(err, "ReadResponse")
+		expectedLength := int64(-1)
+		if !test.chunked {
+			expectedLength = 1000000
+		}
+		if resp.ContentLength != expectedLength {
+			fatalf("expected response length %d, got %d", expectedLength, resp.ContentLength)
+		}
+		if resp.Body == nil {
+			fatalf("nil body")
+		}
+		if test.compressed {
+			gzReader, err := gzip.NewReader(resp.Body)
+			checkErr(err, "gzip.NewReader")
+			resp.Body = &readerAndCloser{gzReader, resp.Body}
+		}
+
+		rbuf := make([]byte, 2500)
+		n, err := io.ReadFull(resp.Body, rbuf)
+		checkErr(err, "2500 byte ReadFull")
+		if n != 2500 {
+			fatalf("ReadFull only read %d bytes", n)
+		}
+		if test.compressed == false && !bytes.Equal(bytes.Repeat([]byte{'x'}, 2500), rbuf) {
+			fatalf("ReadFull didn't read 2500 'x'; got %q", string(rbuf))
+		}
+		resp.Body.Close()
+
+		rest, err := ioutil.ReadAll(bufr)
+		checkErr(err, "ReadAll on remainder")
+		if e, g := "Next Request Here", string(rest); e != g {
+			g = regexp.MustCompile(`(xx+)`).ReplaceAllStringFunc(g, func(match string) string {
+				return fmt.Sprintf("x(repeated x%d)", len(match))
+			})
+			fatalf("remainder = %q, expected %q", g, e)
+		}
+	}
+}
+
+func diff(t *testing.T, prefix string, have, want interface{}) {
+	hv := reflect.ValueOf(have).Elem()
+	wv := reflect.ValueOf(want).Elem()
+	if hv.Type() != wv.Type() {
+		t.Errorf("%s: type mismatch %v want %v", prefix, hv.Type(), wv.Type())
+	}
+	for i := 0; i < hv.NumField(); i++ {
+		hf := hv.Field(i).Interface()
+		wf := wv.Field(i).Interface()
+		if !reflect.DeepEqual(hf, wf) {
+			t.Errorf("%s: %s = %v want %v", prefix, hv.Type().Field(i).Name, hf, wf)
+		}
+	}
+}
+
+type responseLocationTest struct {
+	location string // Response's Location header or ""
+	requrl   string // Response.Request.URL or ""
+	want     string
+	wantErr  error
+}
+
+var responseLocationTests = []responseLocationTest{
+	{"/foo", "http://bar.com/baz", "http://bar.com/foo", nil},
+	{"http://foo.com/", "http://bar.com/baz", "http://foo.com/", nil},
+	{"", "http://bar.com/baz", "", ErrNoLocation},
+}
+
+func TestLocationResponse(t *testing.T) {
+	for i, tt := range responseLocationTests {
+		res := new(Response)
+		res.Header = make(Header)
+		res.Header.Set("Location", tt.location)
+		if tt.requrl != "" {
+			res.Request = &Request{}
+			var err error
+			res.Request.URL, err = url.Parse(tt.requrl)
+			if err != nil {
+				t.Fatalf("bad test URL %q: %v", tt.requrl, err)
+			}
+		}
+
+		got, err := res.Location()
+		if tt.wantErr != nil {
+			if err == nil {
+				t.Errorf("%d. err=nil; want %q", i, tt.wantErr)
+				continue
+			}
+			if g, e := err.Error(), tt.wantErr.Error(); g != e {
+				t.Errorf("%d. err=%q; want %q", i, g, e)
+				continue
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("%d. err=%q", i, err)
+			continue
+		}
+		if g, e := got.String(), tt.want; g != e {
+			t.Errorf("%d. Location=%q; want %q", i, g, e)
+		}
+	}
+}
+
+func TestResponseStatusStutter(t *testing.T) {
+	r := &Response{
+		Status:     "123 some status",
+		StatusCode: 123,
+		ProtoMajor: 1,
+		ProtoMinor: 3,
+	}
+	var buf bytes.Buffer
+	r.Write(&buf)
+	if strings.Contains(buf.String(), "123 123") {
+		t.Errorf("stutter in status: %s", buf.String())
+	}
+}
+
+func TestResponseContentLengthShortBody(t *testing.T) {
+	const shortBody = "Short body, not 123 bytes."
+	br := bufio.NewReader(strings.NewReader("HTTP/1.1 200 OK\r\n" +
+		"Content-Length: 123\r\n" +
+		"\r\n" +
+		shortBody))
+	res, err := ReadResponse(br, &Request{Method: "GET"})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.ContentLength != 123 {
+		t.Fatalf("Content-Length = %d; want 123", res.ContentLength)
+	}
+	var buf bytes.Buffer
+	n, err := io.Copy(&buf, res.Body)
+	if n != int64(len(shortBody)) {
+		t.Errorf("Copied %d bytes; want %d, len(%q)", n, len(shortBody), shortBody)
+	}
+	if buf.String() != shortBody {
+		t.Errorf("Read body %q; want %q", buf.String(), shortBody)
+	}
+	if err != io.ErrUnexpectedEOF {
+		t.Errorf("io.Copy error = %#v; want io.ErrUnexpectedEOF", err)
+	}
+}
+
+func TestReadResponseUnexpectedEOF(t *testing.T) {
+	br := bufio.NewReader(strings.NewReader("HTTP/1.1 301 Moved Permanently\r\n" +
+		"Location: http://example.com"))
+	_, err := ReadResponse(br, nil)
+	if err != io.ErrUnexpectedEOF {
+		t.Errorf("ReadResponse = %v; want io.ErrUnexpectedEOF", err)
+	}
+}
+
+func TestNeedsSniff(t *testing.T) {
+	// needsSniff returns true with an empty response.
+	r := &response{}
+	if got, want := r.needsSniff(), true; got != want {
+		t.Errorf("needsSniff = %t; want %t", got, want)
+	}
+	// needsSniff returns false when Content-Type = nil.
+	r.handlerHeader = Header{"Content-Type": nil}
+	if got, want := r.needsSniff(), false; got != want {
+		t.Errorf("needsSniff empty Content-Type = %t; want %t", got, want)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/responsewrite_test.go b/third_party/gofrontend/libgo/go/net/http/responsewrite_test.go
new file mode 100644
index 0000000..585b13b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/responsewrite_test.go
@@ -0,0 +1,226 @@
+// Copyright 2010 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 http
+
+import (
+	"bytes"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+type respWriteTest struct {
+	Resp Response
+	Raw  string
+}
+
+func TestResponseWrite(t *testing.T) {
+	respWriteTests := []respWriteTest{
+		// HTTP/1.0, identity coding; no trailer
+		{
+			Response{
+				StatusCode:    503,
+				ProtoMajor:    1,
+				ProtoMinor:    0,
+				Request:       dummyReq("GET"),
+				Header:        Header{},
+				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
+				ContentLength: 6,
+			},
+
+			"HTTP/1.0 503 Service Unavailable\r\n" +
+				"Content-Length: 6\r\n\r\n" +
+				"abcdef",
+		},
+		// Unchunked response without Content-Length.
+		{
+			Response{
+				StatusCode:    200,
+				ProtoMajor:    1,
+				ProtoMinor:    0,
+				Request:       dummyReq("GET"),
+				Header:        Header{},
+				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
+				ContentLength: -1,
+			},
+			"HTTP/1.0 200 OK\r\n" +
+				"\r\n" +
+				"abcdef",
+		},
+		// HTTP/1.1 response with unknown length and Connection: close
+		{
+			Response{
+				StatusCode:    200,
+				ProtoMajor:    1,
+				ProtoMinor:    1,
+				Request:       dummyReq("GET"),
+				Header:        Header{},
+				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
+				ContentLength: -1,
+				Close:         true,
+			},
+			"HTTP/1.1 200 OK\r\n" +
+				"Connection: close\r\n" +
+				"\r\n" +
+				"abcdef",
+		},
+		// HTTP/1.1 response with unknown length and not setting connection: close
+		{
+			Response{
+				StatusCode:    200,
+				ProtoMajor:    1,
+				ProtoMinor:    1,
+				Request:       dummyReq11("GET"),
+				Header:        Header{},
+				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
+				ContentLength: -1,
+				Close:         false,
+			},
+			"HTTP/1.1 200 OK\r\n" +
+				"Connection: close\r\n" +
+				"\r\n" +
+				"abcdef",
+		},
+		// HTTP/1.1 response with unknown length and not setting connection: close, but
+		// setting chunked.
+		{
+			Response{
+				StatusCode:       200,
+				ProtoMajor:       1,
+				ProtoMinor:       1,
+				Request:          dummyReq11("GET"),
+				Header:           Header{},
+				Body:             ioutil.NopCloser(strings.NewReader("abcdef")),
+				ContentLength:    -1,
+				TransferEncoding: []string{"chunked"},
+				Close:            false,
+			},
+			"HTTP/1.1 200 OK\r\n" +
+				"Transfer-Encoding: chunked\r\n\r\n" +
+				"6\r\nabcdef\r\n0\r\n\r\n",
+		},
+		// HTTP/1.1 response 0 content-length, and nil body
+		{
+			Response{
+				StatusCode:    200,
+				ProtoMajor:    1,
+				ProtoMinor:    1,
+				Request:       dummyReq11("GET"),
+				Header:        Header{},
+				Body:          nil,
+				ContentLength: 0,
+				Close:         false,
+			},
+			"HTTP/1.1 200 OK\r\n" +
+				"Content-Length: 0\r\n" +
+				"\r\n",
+		},
+		// HTTP/1.1 response 0 content-length, and non-nil empty body
+		{
+			Response{
+				StatusCode:    200,
+				ProtoMajor:    1,
+				ProtoMinor:    1,
+				Request:       dummyReq11("GET"),
+				Header:        Header{},
+				Body:          ioutil.NopCloser(strings.NewReader("")),
+				ContentLength: 0,
+				Close:         false,
+			},
+			"HTTP/1.1 200 OK\r\n" +
+				"Content-Length: 0\r\n" +
+				"\r\n",
+		},
+		// HTTP/1.1 response 0 content-length, and non-nil non-empty body
+		{
+			Response{
+				StatusCode:    200,
+				ProtoMajor:    1,
+				ProtoMinor:    1,
+				Request:       dummyReq11("GET"),
+				Header:        Header{},
+				Body:          ioutil.NopCloser(strings.NewReader("foo")),
+				ContentLength: 0,
+				Close:         false,
+			},
+			"HTTP/1.1 200 OK\r\n" +
+				"Connection: close\r\n" +
+				"\r\nfoo",
+		},
+		// HTTP/1.1, chunked coding; empty trailer; close
+		{
+			Response{
+				StatusCode:       200,
+				ProtoMajor:       1,
+				ProtoMinor:       1,
+				Request:          dummyReq("GET"),
+				Header:           Header{},
+				Body:             ioutil.NopCloser(strings.NewReader("abcdef")),
+				ContentLength:    6,
+				TransferEncoding: []string{"chunked"},
+				Close:            true,
+			},
+
+			"HTTP/1.1 200 OK\r\n" +
+				"Connection: close\r\n" +
+				"Transfer-Encoding: chunked\r\n\r\n" +
+				"6\r\nabcdef\r\n0\r\n\r\n",
+		},
+
+		// Header value with a newline character (Issue 914).
+		// Also tests removal of leading and trailing whitespace.
+		{
+			Response{
+				StatusCode: 204,
+				ProtoMajor: 1,
+				ProtoMinor: 1,
+				Request:    dummyReq("GET"),
+				Header: Header{
+					"Foo": []string{" Bar\nBaz "},
+				},
+				Body:             nil,
+				ContentLength:    0,
+				TransferEncoding: []string{"chunked"},
+				Close:            true,
+			},
+
+			"HTTP/1.1 204 No Content\r\n" +
+				"Connection: close\r\n" +
+				"Foo: Bar Baz\r\n" +
+				"\r\n",
+		},
+
+		// Want a single Content-Length header. Fixing issue 8180 where
+		// there were two.
+		{
+			Response{
+				StatusCode:       StatusOK,
+				ProtoMajor:       1,
+				ProtoMinor:       1,
+				Request:          &Request{Method: "POST"},
+				Header:           Header{},
+				ContentLength:    0,
+				TransferEncoding: nil,
+				Body:             nil,
+			},
+			"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n",
+		},
+	}
+
+	for i := range respWriteTests {
+		tt := &respWriteTests[i]
+		var braw bytes.Buffer
+		err := tt.Resp.Write(&braw)
+		if err != nil {
+			t.Errorf("error writing #%d: %s", i, err)
+			continue
+		}
+		sraw := braw.String()
+		if sraw != tt.Raw {
+			t.Errorf("Test %d, expecting:\n%q\nGot:\n%q\n", i, tt.Raw, sraw)
+			continue
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/serve_test.go b/third_party/gofrontend/libgo/go/net/http/serve_test.go
new file mode 100644
index 0000000..8371dd8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/serve_test.go
@@ -0,0 +1,2849 @@
+// Copyright 2010 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.
+
+// End-to-end serving tests
+
+package http_test
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	. "net/http"
+	"net/http/httptest"
+	"net/http/httputil"
+	"net/url"
+	"os"
+	"os/exec"
+	"reflect"
+	"runtime"
+	"strconv"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"syscall"
+	"testing"
+	"time"
+)
+
+type dummyAddr string
+type oneConnListener struct {
+	conn net.Conn
+}
+
+func (l *oneConnListener) Accept() (c net.Conn, err error) {
+	c = l.conn
+	if c == nil {
+		err = io.EOF
+		return
+	}
+	err = nil
+	l.conn = nil
+	return
+}
+
+func (l *oneConnListener) Close() error {
+	return nil
+}
+
+func (l *oneConnListener) Addr() net.Addr {
+	return dummyAddr("test-address")
+}
+
+func (a dummyAddr) Network() string {
+	return string(a)
+}
+
+func (a dummyAddr) String() string {
+	return string(a)
+}
+
+type noopConn struct{}
+
+func (noopConn) LocalAddr() net.Addr                { return dummyAddr("local-addr") }
+func (noopConn) RemoteAddr() net.Addr               { return dummyAddr("remote-addr") }
+func (noopConn) SetDeadline(t time.Time) error      { return nil }
+func (noopConn) SetReadDeadline(t time.Time) error  { return nil }
+func (noopConn) SetWriteDeadline(t time.Time) error { return nil }
+
+type rwTestConn struct {
+	io.Reader
+	io.Writer
+	noopConn
+
+	closeFunc func() error // called if non-nil
+	closec    chan bool    // else, if non-nil, send value to it on close
+}
+
+func (c *rwTestConn) Close() error {
+	if c.closeFunc != nil {
+		return c.closeFunc()
+	}
+	select {
+	case c.closec <- true:
+	default:
+	}
+	return nil
+}
+
+type testConn struct {
+	readBuf  bytes.Buffer
+	writeBuf bytes.Buffer
+	closec   chan bool // if non-nil, send value to it on close
+	noopConn
+}
+
+func (c *testConn) Read(b []byte) (int, error) {
+	return c.readBuf.Read(b)
+}
+
+func (c *testConn) Write(b []byte) (int, error) {
+	return c.writeBuf.Write(b)
+}
+
+func (c *testConn) Close() error {
+	select {
+	case c.closec <- true:
+	default:
+	}
+	return nil
+}
+
+// reqBytes treats req as a request (with \n delimiters) and returns it with \r\n delimiters,
+// ending in \r\n\r\n
+func reqBytes(req string) []byte {
+	return []byte(strings.Replace(strings.TrimSpace(req), "\n", "\r\n", -1) + "\r\n\r\n")
+}
+
+type handlerTest struct {
+	handler Handler
+}
+
+func newHandlerTest(h Handler) handlerTest {
+	return handlerTest{h}
+}
+
+func (ht handlerTest) rawResponse(req string) string {
+	reqb := reqBytes(req)
+	var output bytes.Buffer
+	conn := &rwTestConn{
+		Reader: bytes.NewReader(reqb),
+		Writer: &output,
+		closec: make(chan bool, 1),
+	}
+	ln := &oneConnListener{conn: conn}
+	go Serve(ln, ht.handler)
+	<-conn.closec
+	return output.String()
+}
+
+func TestConsumingBodyOnNextConn(t *testing.T) {
+	conn := new(testConn)
+	for i := 0; i < 2; i++ {
+		conn.readBuf.Write([]byte(
+			"POST / HTTP/1.1\r\n" +
+				"Host: test\r\n" +
+				"Content-Length: 11\r\n" +
+				"\r\n" +
+				"foo=1&bar=1"))
+	}
+
+	reqNum := 0
+	ch := make(chan *Request)
+	servech := make(chan error)
+	listener := &oneConnListener{conn}
+	handler := func(res ResponseWriter, req *Request) {
+		reqNum++
+		ch <- req
+	}
+
+	go func() {
+		servech <- Serve(listener, HandlerFunc(handler))
+	}()
+
+	var req *Request
+	req = <-ch
+	if req == nil {
+		t.Fatal("Got nil first request.")
+	}
+	if req.Method != "POST" {
+		t.Errorf("For request #1's method, got %q; expected %q",
+			req.Method, "POST")
+	}
+
+	req = <-ch
+	if req == nil {
+		t.Fatal("Got nil first request.")
+	}
+	if req.Method != "POST" {
+		t.Errorf("For request #2's method, got %q; expected %q",
+			req.Method, "POST")
+	}
+
+	if serveerr := <-servech; serveerr != io.EOF {
+		t.Errorf("Serve returned %q; expected EOF", serveerr)
+	}
+}
+
+type stringHandler string
+
+func (s stringHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	w.Header().Set("Result", string(s))
+}
+
+var handlers = []struct {
+	pattern string
+	msg     string
+}{
+	{"/", "Default"},
+	{"/someDir/", "someDir"},
+	{"someHost.com/someDir/", "someHost.com/someDir"},
+}
+
+var vtests = []struct {
+	url      string
+	expected string
+}{
+	{"http://localhost/someDir/apage", "someDir"},
+	{"http://localhost/otherDir/apage", "Default"},
+	{"http://someHost.com/someDir/apage", "someHost.com/someDir"},
+	{"http://otherHost.com/someDir/apage", "someDir"},
+	{"http://otherHost.com/aDir/apage", "Default"},
+	// redirections for trees
+	{"http://localhost/someDir", "/someDir/"},
+	{"http://someHost.com/someDir", "/someDir/"},
+}
+
+func TestHostHandlers(t *testing.T) {
+	defer afterTest(t)
+	mux := NewServeMux()
+	for _, h := range handlers {
+		mux.Handle(h.pattern, stringHandler(h.msg))
+	}
+	ts := httptest.NewServer(mux)
+	defer ts.Close()
+
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer conn.Close()
+	cc := httputil.NewClientConn(conn, nil)
+	for _, vt := range vtests {
+		var r *Response
+		var req Request
+		if req.URL, err = url.Parse(vt.url); err != nil {
+			t.Errorf("cannot parse url: %v", err)
+			continue
+		}
+		if err := cc.Write(&req); err != nil {
+			t.Errorf("writing request: %v", err)
+			continue
+		}
+		r, err := cc.Read(&req)
+		if err != nil {
+			t.Errorf("reading response: %v", err)
+			continue
+		}
+		switch r.StatusCode {
+		case StatusOK:
+			s := r.Header.Get("Result")
+			if s != vt.expected {
+				t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
+			}
+		case StatusMovedPermanently:
+			s := r.Header.Get("Location")
+			if s != vt.expected {
+				t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
+			}
+		default:
+			t.Errorf("Get(%q) unhandled status code %d", vt.url, r.StatusCode)
+		}
+	}
+}
+
+var serveMuxRegister = []struct {
+	pattern string
+	h       Handler
+}{
+	{"/dir/", serve(200)},
+	{"/search", serve(201)},
+	{"codesearch.google.com/search", serve(202)},
+	{"codesearch.google.com/", serve(203)},
+	{"example.com/", HandlerFunc(checkQueryStringHandler)},
+}
+
+// serve returns a handler that sends a response with the given code.
+func serve(code int) HandlerFunc {
+	return func(w ResponseWriter, r *Request) {
+		w.WriteHeader(code)
+	}
+}
+
+// checkQueryStringHandler checks if r.URL.RawQuery has the same value
+// as the URL excluding the scheme and the query string and sends 200
+// response code if it is, 500 otherwise.
+func checkQueryStringHandler(w ResponseWriter, r *Request) {
+	u := *r.URL
+	u.Scheme = "http"
+	u.Host = r.Host
+	u.RawQuery = ""
+	if "http://"+r.URL.RawQuery == u.String() {
+		w.WriteHeader(200)
+	} else {
+		w.WriteHeader(500)
+	}
+}
+
+var serveMuxTests = []struct {
+	method  string
+	host    string
+	path    string
+	code    int
+	pattern string
+}{
+	{"GET", "google.com", "/", 404, ""},
+	{"GET", "google.com", "/dir", 301, "/dir/"},
+	{"GET", "google.com", "/dir/", 200, "/dir/"},
+	{"GET", "google.com", "/dir/file", 200, "/dir/"},
+	{"GET", "google.com", "/search", 201, "/search"},
+	{"GET", "google.com", "/search/", 404, ""},
+	{"GET", "google.com", "/search/foo", 404, ""},
+	{"GET", "codesearch.google.com", "/search", 202, "codesearch.google.com/search"},
+	{"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"},
+	{"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"},
+	{"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"},
+	{"GET", "images.google.com", "/search", 201, "/search"},
+	{"GET", "images.google.com", "/search/", 404, ""},
+	{"GET", "images.google.com", "/search/foo", 404, ""},
+	{"GET", "google.com", "/../search", 301, "/search"},
+	{"GET", "google.com", "/dir/..", 301, ""},
+	{"GET", "google.com", "/dir/..", 301, ""},
+	{"GET", "google.com", "/dir/./file", 301, "/dir/"},
+
+	// The /foo -> /foo/ redirect applies to CONNECT requests
+	// but the path canonicalization does not.
+	{"CONNECT", "google.com", "/dir", 301, "/dir/"},
+	{"CONNECT", "google.com", "/../search", 404, ""},
+	{"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
+	{"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
+	{"CONNECT", "google.com", "/dir/./file", 200, "/dir/"},
+}
+
+func TestServeMuxHandler(t *testing.T) {
+	mux := NewServeMux()
+	for _, e := range serveMuxRegister {
+		mux.Handle(e.pattern, e.h)
+	}
+
+	for _, tt := range serveMuxTests {
+		r := &Request{
+			Method: tt.method,
+			Host:   tt.host,
+			URL: &url.URL{
+				Path: tt.path,
+			},
+		}
+		h, pattern := mux.Handler(r)
+		rr := httptest.NewRecorder()
+		h.ServeHTTP(rr, r)
+		if pattern != tt.pattern || rr.Code != tt.code {
+			t.Errorf("%s %s %s = %d, %q, want %d, %q", tt.method, tt.host, tt.path, rr.Code, pattern, tt.code, tt.pattern)
+		}
+	}
+}
+
+var serveMuxTests2 = []struct {
+	method  string
+	host    string
+	url     string
+	code    int
+	redirOk bool
+}{
+	{"GET", "google.com", "/", 404, false},
+	{"GET", "example.com", "/test/?example.com/test/", 200, false},
+	{"GET", "example.com", "test/?example.com/test/", 200, true},
+}
+
+// TestServeMuxHandlerRedirects tests that automatic redirects generated by
+// mux.Handler() shouldn't clear the request's query string.
+func TestServeMuxHandlerRedirects(t *testing.T) {
+	mux := NewServeMux()
+	for _, e := range serveMuxRegister {
+		mux.Handle(e.pattern, e.h)
+	}
+
+	for _, tt := range serveMuxTests2 {
+		tries := 1
+		turl := tt.url
+		for tries > 0 {
+			u, e := url.Parse(turl)
+			if e != nil {
+				t.Fatal(e)
+			}
+			r := &Request{
+				Method: tt.method,
+				Host:   tt.host,
+				URL:    u,
+			}
+			h, _ := mux.Handler(r)
+			rr := httptest.NewRecorder()
+			h.ServeHTTP(rr, r)
+			if rr.Code != 301 {
+				if rr.Code != tt.code {
+					t.Errorf("%s %s %s = %d, want %d", tt.method, tt.host, tt.url, rr.Code, tt.code)
+				}
+				break
+			}
+			if !tt.redirOk {
+				t.Errorf("%s %s %s, unexpected redirect", tt.method, tt.host, tt.url)
+				break
+			}
+			turl = rr.HeaderMap.Get("Location")
+			tries--
+		}
+		if tries < 0 {
+			t.Errorf("%s %s %s, too many redirects", tt.method, tt.host, tt.url)
+		}
+	}
+}
+
+// Tests for http://code.google.com/p/go/issues/detail?id=900
+func TestMuxRedirectLeadingSlashes(t *testing.T) {
+	paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"}
+	for _, path := range paths {
+		req, err := ReadRequest(bufio.NewReader(strings.NewReader("GET " + path + " HTTP/1.1\r\nHost: test\r\n\r\n")))
+		if err != nil {
+			t.Errorf("%s", err)
+		}
+		mux := NewServeMux()
+		resp := httptest.NewRecorder()
+
+		mux.ServeHTTP(resp, req)
+
+		if loc, expected := resp.Header().Get("Location"), "/foo.txt"; loc != expected {
+			t.Errorf("Expected Location header set to %q; got %q", expected, loc)
+			return
+		}
+
+		if code, expected := resp.Code, StatusMovedPermanently; code != expected {
+			t.Errorf("Expected response code of StatusMovedPermanently; got %d", code)
+			return
+		}
+	}
+}
+
+func TestServerTimeouts(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping test; see http://golang.org/issue/7237")
+	}
+	defer afterTest(t)
+	reqNum := 0
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(res ResponseWriter, req *Request) {
+		reqNum++
+		fmt.Fprintf(res, "req=%d", reqNum)
+	}))
+	ts.Config.ReadTimeout = 250 * time.Millisecond
+	ts.Config.WriteTimeout = 250 * time.Millisecond
+	ts.Start()
+	defer ts.Close()
+
+	// Hit the HTTP server successfully.
+	tr := &Transport{DisableKeepAlives: true} // they interfere with this test
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+	r, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatalf("http Get #1: %v", err)
+	}
+	got, _ := ioutil.ReadAll(r.Body)
+	expected := "req=1"
+	if string(got) != expected {
+		t.Errorf("Unexpected response for request #1; got %q; expected %q",
+			string(got), expected)
+	}
+
+	// Slow client that should timeout.
+	t1 := time.Now()
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	buf := make([]byte, 1)
+	n, err := conn.Read(buf)
+	latency := time.Since(t1)
+	if n != 0 || err != io.EOF {
+		t.Errorf("Read = %v, %v, wanted %v, %v", n, err, 0, io.EOF)
+	}
+	if latency < 200*time.Millisecond /* fudge from 250 ms above */ {
+		t.Errorf("got EOF after %s, want >= %s", latency, 200*time.Millisecond)
+	}
+
+	// Hit the HTTP server successfully again, verifying that the
+	// previous slow connection didn't run our handler.  (that we
+	// get "req=2", not "req=3")
+	r, err = Get(ts.URL)
+	if err != nil {
+		t.Fatalf("http Get #2: %v", err)
+	}
+	got, _ = ioutil.ReadAll(r.Body)
+	expected = "req=2"
+	if string(got) != expected {
+		t.Errorf("Get #2 got %q, want %q", string(got), expected)
+	}
+
+	if !testing.Short() {
+		conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatalf("Dial: %v", err)
+		}
+		defer conn.Close()
+		go io.Copy(ioutil.Discard, conn)
+		for i := 0; i < 5; i++ {
+			_, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"))
+			if err != nil {
+				t.Fatalf("on write %d: %v", i, err)
+			}
+			time.Sleep(ts.Config.ReadTimeout / 2)
+		}
+	}
+}
+
+// golang.org/issue/4741 -- setting only a write timeout that triggers
+// shouldn't cause a handler to block forever on reads (next HTTP
+// request) that will never happen.
+func TestOnlyWriteTimeout(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping test; see http://golang.org/issue/7237")
+	}
+	defer afterTest(t)
+	var conn net.Conn
+	var afterTimeoutErrc = make(chan error, 1)
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, req *Request) {
+		buf := make([]byte, 512<<10)
+		_, err := w.Write(buf)
+		if err != nil {
+			t.Errorf("handler Write error: %v", err)
+			return
+		}
+		conn.SetWriteDeadline(time.Now().Add(-30 * time.Second))
+		_, err = w.Write(buf)
+		afterTimeoutErrc <- err
+	}))
+	ts.Listener = trackLastConnListener{ts.Listener, &conn}
+	ts.Start()
+	defer ts.Close()
+
+	tr := &Transport{DisableKeepAlives: false}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	errc := make(chan error)
+	go func() {
+		res, err := c.Get(ts.URL)
+		if err != nil {
+			errc <- err
+			return
+		}
+		_, err = io.Copy(ioutil.Discard, res.Body)
+		errc <- err
+	}()
+	select {
+	case err := <-errc:
+		if err == nil {
+			t.Errorf("expected an error from Get request")
+		}
+	case <-time.After(5 * time.Second):
+		t.Fatal("timeout waiting for Get error")
+	}
+	if err := <-afterTimeoutErrc; err == nil {
+		t.Error("expected write error after timeout")
+	}
+}
+
+// trackLastConnListener tracks the last net.Conn that was accepted.
+type trackLastConnListener struct {
+	net.Listener
+	last *net.Conn // destination
+}
+
+func (l trackLastConnListener) Accept() (c net.Conn, err error) {
+	c, err = l.Listener.Accept()
+	*l.last = c
+	return
+}
+
+// TestIdentityResponse verifies that a handler can unset
+func TestIdentityResponse(t *testing.T) {
+	defer afterTest(t)
+	handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
+		rw.Header().Set("Content-Length", "3")
+		rw.Header().Set("Transfer-Encoding", req.FormValue("te"))
+		switch {
+		case req.FormValue("overwrite") == "1":
+			_, err := rw.Write([]byte("foo TOO LONG"))
+			if err != ErrContentLength {
+				t.Errorf("expected ErrContentLength; got %v", err)
+			}
+		case req.FormValue("underwrite") == "1":
+			rw.Header().Set("Content-Length", "500")
+			rw.Write([]byte("too short"))
+		default:
+			rw.Write([]byte("foo"))
+		}
+	})
+
+	ts := httptest.NewServer(handler)
+	defer ts.Close()
+
+	// Note: this relies on the assumption (which is true) that
+	// Get sends HTTP/1.1 or greater requests.  Otherwise the
+	// server wouldn't have the choice to send back chunked
+	// responses.
+	for _, te := range []string{"", "identity"} {
+		url := ts.URL + "/?te=" + te
+		res, err := Get(url)
+		if err != nil {
+			t.Fatalf("error with Get of %s: %v", url, err)
+		}
+		if cl, expected := res.ContentLength, int64(3); cl != expected {
+			t.Errorf("for %s expected res.ContentLength of %d; got %d", url, expected, cl)
+		}
+		if cl, expected := res.Header.Get("Content-Length"), "3"; cl != expected {
+			t.Errorf("for %s expected Content-Length header of %q; got %q", url, expected, cl)
+		}
+		if tl, expected := len(res.TransferEncoding), 0; tl != expected {
+			t.Errorf("for %s expected len(res.TransferEncoding) of %d; got %d (%v)",
+				url, expected, tl, res.TransferEncoding)
+		}
+		res.Body.Close()
+	}
+
+	// Verify that ErrContentLength is returned
+	url := ts.URL + "/?overwrite=1"
+	res, err := Get(url)
+	if err != nil {
+		t.Fatalf("error with Get of %s: %v", url, err)
+	}
+	res.Body.Close()
+
+	// Verify that the connection is closed when the declared Content-Length
+	// is larger than what the handler wrote.
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("error dialing: %v", err)
+	}
+	_, err = conn.Write([]byte("GET /?underwrite=1 HTTP/1.1\r\nHost: foo\r\n\r\n"))
+	if err != nil {
+		t.Fatalf("error writing: %v", err)
+	}
+
+	// The ReadAll will hang for a failing test, so use a Timer to
+	// fail explicitly.
+	goTimeout(t, 2*time.Second, func() {
+		got, _ := ioutil.ReadAll(conn)
+		expectedSuffix := "\r\n\r\ntoo short"
+		if !strings.HasSuffix(string(got), expectedSuffix) {
+			t.Errorf("Expected output to end with %q; got response body %q",
+				expectedSuffix, string(got))
+		}
+	})
+}
+
+func testTCPConnectionCloses(t *testing.T, req string, h Handler) {
+	defer afterTest(t)
+	s := httptest.NewServer(h)
+	defer s.Close()
+
+	conn, err := net.Dial("tcp", s.Listener.Addr().String())
+	if err != nil {
+		t.Fatal("dial error:", err)
+	}
+	defer conn.Close()
+
+	_, err = fmt.Fprint(conn, req)
+	if err != nil {
+		t.Fatal("print error:", err)
+	}
+
+	r := bufio.NewReader(conn)
+	res, err := ReadResponse(r, &Request{Method: "GET"})
+	if err != nil {
+		t.Fatal("ReadResponse error:", err)
+	}
+
+	didReadAll := make(chan bool, 1)
+	go func() {
+		select {
+		case <-time.After(5 * time.Second):
+			t.Error("body not closed after 5s")
+			return
+		case <-didReadAll:
+		}
+	}()
+
+	_, err = ioutil.ReadAll(r)
+	if err != nil {
+		t.Fatal("read error:", err)
+	}
+	didReadAll <- true
+
+	if !res.Close {
+		t.Errorf("Response.Close = false; want true")
+	}
+}
+
+// TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive.
+func TestServeHTTP10Close(t *testing.T) {
+	testTCPConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+		ServeFile(w, r, "testdata/file")
+	}))
+}
+
+// TestClientCanClose verifies that clients can also force a connection to close.
+func TestClientCanClose(t *testing.T) {
+	testTCPConnectionCloses(t, "GET / HTTP/1.1\r\nConnection: close\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+		// Nothing.
+	}))
+}
+
+// TestHandlersCanSetConnectionClose verifies that handlers can force a connection to close,
+// even for HTTP/1.1 requests.
+func TestHandlersCanSetConnectionClose11(t *testing.T) {
+	testTCPConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Connection", "close")
+	}))
+}
+
+func TestHandlersCanSetConnectionClose10(t *testing.T) {
+	testTCPConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Connection", "close")
+	}))
+}
+
+func TestSetsRemoteAddr(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "%s", r.RemoteAddr)
+	}))
+	defer ts.Close()
+
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get error: %v", err)
+	}
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatalf("ReadAll error: %v", err)
+	}
+	ip := string(body)
+	if !strings.HasPrefix(ip, "127.0.0.1:") && !strings.HasPrefix(ip, "[::1]:") {
+		t.Fatalf("Expected local addr; got %q", ip)
+	}
+}
+
+func TestChunkedResponseHeaders(t *testing.T) {
+	defer afterTest(t)
+	log.SetOutput(ioutil.Discard) // is noisy otherwise
+	defer log.SetOutput(os.Stderr)
+
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted
+		w.(Flusher).Flush()
+		fmt.Fprintf(w, "I am a chunked response.")
+	}))
+	defer ts.Close()
+
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get error: %v", err)
+	}
+	defer res.Body.Close()
+	if g, e := res.ContentLength, int64(-1); g != e {
+		t.Errorf("expected ContentLength of %d; got %d", e, g)
+	}
+	if g, e := res.TransferEncoding, []string{"chunked"}; !reflect.DeepEqual(g, e) {
+		t.Errorf("expected TransferEncoding of %v; got %v", e, g)
+	}
+	if _, haveCL := res.Header["Content-Length"]; haveCL {
+		t.Errorf("Unexpected Content-Length")
+	}
+}
+
+// Test304Responses verifies that 304s don't declare that they're
+// chunking in their response headers and aren't allowed to produce
+// output.
+func Test304Responses(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.WriteHeader(StatusNotModified)
+		_, err := w.Write([]byte("illegal body"))
+		if err != ErrBodyNotAllowed {
+			t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
+		}
+	}))
+	defer ts.Close()
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if len(res.TransferEncoding) > 0 {
+		t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
+	}
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Error(err)
+	}
+	if len(body) > 0 {
+		t.Errorf("got unexpected body %q", string(body))
+	}
+}
+
+// TestHeadResponses verifies that all MIME type sniffing and Content-Length
+// counting of GET requests also happens on HEAD requests.
+func TestHeadResponses(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		_, err := w.Write([]byte("<html>"))
+		if err != nil {
+			t.Errorf("ResponseWriter.Write: %v", err)
+		}
+
+		// Also exercise the ReaderFrom path
+		_, err = io.Copy(w, strings.NewReader("789a"))
+		if err != nil {
+			t.Errorf("Copy(ResponseWriter, ...): %v", err)
+		}
+	}))
+	defer ts.Close()
+	res, err := Head(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if len(res.TransferEncoding) > 0 {
+		t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
+	}
+	if ct := res.Header.Get("Content-Type"); ct != "text/html; charset=utf-8" {
+		t.Errorf("Content-Type: %q; want text/html; charset=utf-8", ct)
+	}
+	if v := res.ContentLength; v != 10 {
+		t.Errorf("Content-Length: %d; want 10", v)
+	}
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Error(err)
+	}
+	if len(body) > 0 {
+		t.Errorf("got unexpected body %q", string(body))
+	}
+}
+
+func TestTLSHandshakeTimeout(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping test; see http://golang.org/issue/7237")
+	}
+	defer afterTest(t)
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+	errc := make(chanWriter, 10) // but only expecting 1
+	ts.Config.ReadTimeout = 250 * time.Millisecond
+	ts.Config.ErrorLog = log.New(errc, "", 0)
+	ts.StartTLS()
+	defer ts.Close()
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer conn.Close()
+	goTimeout(t, 10*time.Second, func() {
+		var buf [1]byte
+		n, err := conn.Read(buf[:])
+		if err == nil || n != 0 {
+			t.Errorf("Read = %d, %v; want an error and no bytes", n, err)
+		}
+	})
+	select {
+	case v := <-errc:
+		if !strings.Contains(v, "timeout") && !strings.Contains(v, "TLS handshake") {
+			t.Errorf("expected a TLS handshake timeout error; got %q", v)
+		}
+	case <-time.After(5 * time.Second):
+		t.Errorf("timeout waiting for logged error")
+	}
+}
+
+func TestTLSServer(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.TLS != nil {
+			w.Header().Set("X-TLS-Set", "true")
+			if r.TLS.HandshakeComplete {
+				w.Header().Set("X-TLS-HandshakeComplete", "true")
+			}
+		}
+	}))
+	ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0)
+	defer ts.Close()
+
+	// Connect an idle TCP connection to this server before we run
+	// our real tests.  This idle connection used to block forever
+	// in the TLS handshake, preventing future connections from
+	// being accepted. It may prevent future accidental blocking
+	// in newConn.
+	idleConn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer idleConn.Close()
+	goTimeout(t, 10*time.Second, func() {
+		if !strings.HasPrefix(ts.URL, "https://") {
+			t.Errorf("expected test TLS server to start with https://, got %q", ts.URL)
+			return
+		}
+		noVerifyTransport := &Transport{
+			TLSClientConfig: &tls.Config{
+				InsecureSkipVerify: true,
+			},
+		}
+		client := &Client{Transport: noVerifyTransport}
+		res, err := client.Get(ts.URL)
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		if res == nil {
+			t.Errorf("got nil Response")
+			return
+		}
+		defer res.Body.Close()
+		if res.Header.Get("X-TLS-Set") != "true" {
+			t.Errorf("expected X-TLS-Set response header")
+			return
+		}
+		if res.Header.Get("X-TLS-HandshakeComplete") != "true" {
+			t.Errorf("expected X-TLS-HandshakeComplete header")
+		}
+	})
+}
+
+type serverExpectTest struct {
+	contentLength    int // of request body
+	chunked          bool
+	expectation      string // e.g. "100-continue"
+	readBody         bool   // whether handler should read the body (if false, sends StatusUnauthorized)
+	expectedResponse string // expected substring in first line of http response
+}
+
+func expectTest(contentLength int, expectation string, readBody bool, expectedResponse string) serverExpectTest {
+	return serverExpectTest{
+		contentLength:    contentLength,
+		expectation:      expectation,
+		readBody:         readBody,
+		expectedResponse: expectedResponse,
+	}
+}
+
+var serverExpectTests = []serverExpectTest{
+	// Normal 100-continues, case-insensitive.
+	expectTest(100, "100-continue", true, "100 Continue"),
+	expectTest(100, "100-cOntInUE", true, "100 Continue"),
+
+	// No 100-continue.
+	expectTest(100, "", true, "200 OK"),
+
+	// 100-continue but requesting client to deny us,
+	// so it never reads the body.
+	expectTest(100, "100-continue", false, "401 Unauthorized"),
+	// Likewise without 100-continue:
+	expectTest(100, "", false, "401 Unauthorized"),
+
+	// Non-standard expectations are failures
+	expectTest(0, "a-pony", false, "417 Expectation Failed"),
+
+	// Expect-100 requested but no body (is apparently okay: Issue 7625)
+	expectTest(0, "100-continue", true, "200 OK"),
+	// Expect-100 requested but handler doesn't read the body
+	expectTest(0, "100-continue", false, "401 Unauthorized"),
+	// Expect-100 continue with no body, but a chunked body.
+	{
+		expectation:      "100-continue",
+		readBody:         true,
+		chunked:          true,
+		expectedResponse: "100 Continue",
+	},
+}
+
+// Tests that the server responds to the "Expect" request header
+// correctly.
+func TestServerExpect(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		// Note using r.FormValue("readbody") because for POST
+		// requests that would read from r.Body, which we only
+		// conditionally want to do.
+		if strings.Contains(r.URL.RawQuery, "readbody=true") {
+			ioutil.ReadAll(r.Body)
+			w.Write([]byte("Hi"))
+		} else {
+			w.WriteHeader(StatusUnauthorized)
+		}
+	}))
+	defer ts.Close()
+
+	runTest := func(test serverExpectTest) {
+		conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatalf("Dial: %v", err)
+		}
+		defer conn.Close()
+
+		// Only send the body immediately if we're acting like an HTTP client
+		// that doesn't send 100-continue expectations.
+		writeBody := test.contentLength != 0 && strings.ToLower(test.expectation) != "100-continue"
+
+		go func() {
+			contentLen := fmt.Sprintf("Content-Length: %d", test.contentLength)
+			if test.chunked {
+				contentLen = "Transfer-Encoding: chunked"
+			}
+			_, err := fmt.Fprintf(conn, "POST /?readbody=%v HTTP/1.1\r\n"+
+				"Connection: close\r\n"+
+				"%s\r\n"+
+				"Expect: %s\r\nHost: foo\r\n\r\n",
+				test.readBody, contentLen, test.expectation)
+			if err != nil {
+				t.Errorf("On test %#v, error writing request headers: %v", test, err)
+				return
+			}
+			if writeBody {
+				var targ io.WriteCloser = struct {
+					io.Writer
+					io.Closer
+				}{
+					conn,
+					ioutil.NopCloser(nil),
+				}
+				if test.chunked {
+					targ = httputil.NewChunkedWriter(conn)
+				}
+				body := strings.Repeat("A", test.contentLength)
+				_, err = fmt.Fprint(targ, body)
+				if err == nil {
+					err = targ.Close()
+				}
+				if err != nil {
+					if !test.readBody {
+						// Server likely already hung up on us.
+						// See larger comment below.
+						t.Logf("On test %#v, acceptable error writing request body: %v", test, err)
+						return
+					}
+					t.Errorf("On test %#v, error writing request body: %v", test, err)
+				}
+			}
+		}()
+		bufr := bufio.NewReader(conn)
+		line, err := bufr.ReadString('\n')
+		if err != nil {
+			if writeBody && !test.readBody {
+				// This is an acceptable failure due to a possible TCP race:
+				// We were still writing data and the server hung up on us. A TCP
+				// implementation may send a RST if our request body data was known
+				// to be lost, which may trigger our reads to fail.
+				// See RFC 1122 page 88.
+				t.Logf("On test %#v, acceptable error from ReadString: %v", test, err)
+				return
+			}
+			t.Fatalf("On test %#v, ReadString: %v", test, err)
+		}
+		if !strings.Contains(line, test.expectedResponse) {
+			t.Errorf("On test %#v, got first line = %q; want %q", test, line, test.expectedResponse)
+		}
+	}
+
+	for _, test := range serverExpectTests {
+		runTest(test)
+	}
+}
+
+// Under a ~256KB (maxPostHandlerReadBytes) threshold, the server
+// should consume client request bodies that a handler didn't read.
+func TestServerUnreadRequestBodyLittle(t *testing.T) {
+	conn := new(testConn)
+	body := strings.Repeat("x", 100<<10)
+	conn.readBuf.Write([]byte(fmt.Sprintf(
+		"POST / HTTP/1.1\r\n"+
+			"Host: test\r\n"+
+			"Content-Length: %d\r\n"+
+			"\r\n", len(body))))
+	conn.readBuf.Write([]byte(body))
+
+	done := make(chan bool)
+
+	ls := &oneConnListener{conn}
+	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
+		defer close(done)
+		if conn.readBuf.Len() < len(body)/2 {
+			t.Errorf("on request, read buffer length is %d; expected about 100 KB", conn.readBuf.Len())
+		}
+		rw.WriteHeader(200)
+		rw.(Flusher).Flush()
+		if g, e := conn.readBuf.Len(), 0; g != e {
+			t.Errorf("after WriteHeader, read buffer length is %d; want %d", g, e)
+		}
+		if c := rw.Header().Get("Connection"); c != "" {
+			t.Errorf(`Connection header = %q; want ""`, c)
+		}
+	}))
+	<-done
+}
+
+// Over a ~256KB (maxPostHandlerReadBytes) threshold, the server
+// should ignore client request bodies that a handler didn't read
+// and close the connection.
+func TestServerUnreadRequestBodyLarge(t *testing.T) {
+	conn := new(testConn)
+	body := strings.Repeat("x", 1<<20)
+	conn.readBuf.Write([]byte(fmt.Sprintf(
+		"POST / HTTP/1.1\r\n"+
+			"Host: test\r\n"+
+			"Content-Length: %d\r\n"+
+			"\r\n", len(body))))
+	conn.readBuf.Write([]byte(body))
+	conn.closec = make(chan bool, 1)
+
+	ls := &oneConnListener{conn}
+	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
+		if conn.readBuf.Len() < len(body)/2 {
+			t.Errorf("on request, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
+		}
+		rw.WriteHeader(200)
+		rw.(Flusher).Flush()
+		if conn.readBuf.Len() < len(body)/2 {
+			t.Errorf("post-WriteHeader, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
+		}
+	}))
+	<-conn.closec
+
+	if res := conn.writeBuf.String(); !strings.Contains(res, "Connection: close") {
+		t.Errorf("Expected a Connection: close header; got response: %s", res)
+	}
+}
+
+func TestTimeoutHandler(t *testing.T) {
+	defer afterTest(t)
+	sendHi := make(chan bool, 1)
+	writeErrors := make(chan error, 1)
+	sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
+		<-sendHi
+		_, werr := w.Write([]byte("hi"))
+		writeErrors <- werr
+	})
+	timeout := make(chan time.Time, 1) // write to this to force timeouts
+	ts := httptest.NewServer(NewTestTimeoutHandler(sayHi, timeout))
+	defer ts.Close()
+
+	// Succeed without timing out:
+	sendHi <- true
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if g, e := res.StatusCode, StatusOK; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	body, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(body), "hi"; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+	if g := <-writeErrors; g != nil {
+		t.Errorf("got unexpected Write error on first request: %v", g)
+	}
+
+	// Times out:
+	timeout <- time.Time{}
+	res, err = Get(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	body, _ = ioutil.ReadAll(res.Body)
+	if !strings.Contains(string(body), "<title>Timeout</title>") {
+		t.Errorf("expected timeout body; got %q", string(body))
+	}
+
+	// Now make the previously-timed out handler speak again,
+	// which verifies the panic is handled:
+	sendHi <- true
+	if g, e := <-writeErrors, ErrHandlerTimeout; g != e {
+		t.Errorf("expected Write error of %v; got %v", e, g)
+	}
+}
+
+// Verifies we don't path.Clean() on the wrong parts in redirects.
+func TestRedirectMunging(t *testing.T) {
+	req, _ := NewRequest("GET", "http://example.com/", nil)
+
+	resp := httptest.NewRecorder()
+	Redirect(resp, req, "/foo?next=http://bar.com/", 302)
+	if g, e := resp.Header().Get("Location"), "/foo?next=http://bar.com/"; g != e {
+		t.Errorf("Location header was %q; want %q", g, e)
+	}
+
+	resp = httptest.NewRecorder()
+	Redirect(resp, req, "http://localhost:8080/_ah/login?continue=http://localhost:8080/", 302)
+	if g, e := resp.Header().Get("Location"), "http://localhost:8080/_ah/login?continue=http://localhost:8080/"; g != e {
+		t.Errorf("Location header was %q; want %q", g, e)
+	}
+}
+
+func TestRedirectBadPath(t *testing.T) {
+	// This used to crash. It's not valid input (bad path), but it
+	// shouldn't crash.
+	rr := httptest.NewRecorder()
+	req := &Request{
+		Method: "GET",
+		URL: &url.URL{
+			Scheme: "http",
+			Path:   "not-empty-but-no-leading-slash", // bogus
+		},
+	}
+	Redirect(rr, req, "", 304)
+	if rr.Code != 304 {
+		t.Errorf("Code = %d; want 304", rr.Code)
+	}
+}
+
+// TestZeroLengthPostAndResponse exercises an optimization done by the Transport:
+// when there is no body (either because the method doesn't permit a body, or an
+// explicit Content-Length of zero is present), then the transport can re-use the
+// connection immediately. But when it re-uses the connection, it typically closes
+// the previous request's body, which is not optimal for zero-lengthed bodies,
+// as the client would then see http.ErrBodyReadAfterClose and not 0, io.EOF.
+func TestZeroLengthPostAndResponse(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+		all, err := ioutil.ReadAll(r.Body)
+		if err != nil {
+			t.Fatalf("handler ReadAll: %v", err)
+		}
+		if len(all) != 0 {
+			t.Errorf("handler got %d bytes; expected 0", len(all))
+		}
+		rw.Header().Set("Content-Length", "0")
+	}))
+	defer ts.Close()
+
+	req, err := NewRequest("POST", ts.URL, strings.NewReader(""))
+	if err != nil {
+		t.Fatal(err)
+	}
+	req.ContentLength = 0
+
+	var resp [5]*Response
+	for i := range resp {
+		resp[i], err = DefaultClient.Do(req)
+		if err != nil {
+			t.Fatalf("client post #%d: %v", i, err)
+		}
+	}
+
+	for i := range resp {
+		all, err := ioutil.ReadAll(resp[i].Body)
+		if err != nil {
+			t.Fatalf("req #%d: client ReadAll: %v", i, err)
+		}
+		if len(all) != 0 {
+			t.Errorf("req #%d: client got %d bytes; expected 0", i, len(all))
+		}
+	}
+}
+
+func TestHandlerPanicNil(t *testing.T) {
+	testHandlerPanic(t, false, nil)
+}
+
+func TestHandlerPanic(t *testing.T) {
+	testHandlerPanic(t, false, "intentional death for testing")
+}
+
+func TestHandlerPanicWithHijack(t *testing.T) {
+	testHandlerPanic(t, true, "intentional death for testing")
+}
+
+func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
+	defer afterTest(t)
+	// Unlike the other tests that set the log output to ioutil.Discard
+	// to quiet the output, this test uses a pipe.  The pipe serves three
+	// purposes:
+	//
+	//   1) The log.Print from the http server (generated by the caught
+	//      panic) will go to the pipe instead of stderr, making the
+	//      output quiet.
+	//
+	//   2) We read from the pipe to verify that the handler
+	//      actually caught the panic and logged something.
+	//
+	//   3) The blocking Read call prevents this TestHandlerPanic
+	//      function from exiting before the HTTP server handler
+	//      finishes crashing. If this text function exited too
+	//      early (and its defer log.SetOutput(os.Stderr) ran),
+	//      then the crash output could spill into the next test.
+	pr, pw := io.Pipe()
+	log.SetOutput(pw)
+	defer log.SetOutput(os.Stderr)
+	defer pw.Close()
+
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if withHijack {
+			rwc, _, err := w.(Hijacker).Hijack()
+			if err != nil {
+				t.Logf("unexpected error: %v", err)
+			}
+			defer rwc.Close()
+		}
+		panic(panicValue)
+	}))
+	defer ts.Close()
+
+	// Do a blocking read on the log output pipe so its logging
+	// doesn't bleed into the next test.  But wait only 5 seconds
+	// for it.
+	done := make(chan bool, 1)
+	go func() {
+		buf := make([]byte, 4<<10)
+		_, err := pr.Read(buf)
+		pr.Close()
+		if err != nil && err != io.EOF {
+			t.Error(err)
+		}
+		done <- true
+	}()
+
+	_, err := Get(ts.URL)
+	if err == nil {
+		t.Logf("expected an error")
+	}
+
+	if panicValue == nil {
+		return
+	}
+
+	select {
+	case <-done:
+		return
+	case <-time.After(5 * time.Second):
+		t.Fatal("expected server handler to log an error")
+	}
+}
+
+func TestNoDate(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header()["Date"] = nil
+	}))
+	defer ts.Close()
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, present := res.Header["Date"]
+	if present {
+		t.Fatalf("Expected no Date header; got %v", res.Header["Date"])
+	}
+}
+
+func TestStripPrefix(t *testing.T) {
+	defer afterTest(t)
+	h := HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("X-Path", r.URL.Path)
+	})
+	ts := httptest.NewServer(StripPrefix("/foo", h))
+	defer ts.Close()
+
+	res, err := Get(ts.URL + "/foo/bar")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, e := res.Header.Get("X-Path"), "/bar"; g != e {
+		t.Errorf("test 1: got %s, want %s", g, e)
+	}
+	res.Body.Close()
+
+	res, err = Get(ts.URL + "/bar")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, e := res.StatusCode, 404; g != e {
+		t.Errorf("test 2: got status %v, want %v", g, e)
+	}
+	res.Body.Close()
+}
+
+func TestRequestLimit(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		t.Fatalf("didn't expect to get request in Handler")
+	}))
+	defer ts.Close()
+	req, _ := NewRequest("GET", ts.URL, nil)
+	var bytesPerHeader = len("header12345: val12345\r\n")
+	for i := 0; i < ((DefaultMaxHeaderBytes+4096)/bytesPerHeader)+1; i++ {
+		req.Header.Set(fmt.Sprintf("header%05d", i), fmt.Sprintf("val%05d", i))
+	}
+	res, err := DefaultClient.Do(req)
+	if err != nil {
+		// Some HTTP clients may fail on this undefined behavior (server replying and
+		// closing the connection while the request is still being written), but
+		// we do support it (at least currently), so we expect a response below.
+		t.Fatalf("Do: %v", err)
+	}
+	defer res.Body.Close()
+	if res.StatusCode != 413 {
+		t.Fatalf("expected 413 response status; got: %d %s", res.StatusCode, res.Status)
+	}
+}
+
+type neverEnding byte
+
+func (b neverEnding) Read(p []byte) (n int, err error) {
+	for i := range p {
+		p[i] = byte(b)
+	}
+	return len(p), nil
+}
+
+type countReader struct {
+	r io.Reader
+	n *int64
+}
+
+func (cr countReader) Read(p []byte) (n int, err error) {
+	n, err = cr.r.Read(p)
+	atomic.AddInt64(cr.n, int64(n))
+	return
+}
+
+func TestRequestBodyLimit(t *testing.T) {
+	defer afterTest(t)
+	const limit = 1 << 20
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		r.Body = MaxBytesReader(w, r.Body, limit)
+		n, err := io.Copy(ioutil.Discard, r.Body)
+		if err == nil {
+			t.Errorf("expected error from io.Copy")
+		}
+		if n != limit {
+			t.Errorf("io.Copy = %d, want %d", n, limit)
+		}
+	}))
+	defer ts.Close()
+
+	nWritten := new(int64)
+	req, _ := NewRequest("POST", ts.URL, io.LimitReader(countReader{neverEnding('a'), nWritten}, limit*200))
+
+	// Send the POST, but don't care it succeeds or not.  The
+	// remote side is going to reply and then close the TCP
+	// connection, and HTTP doesn't really define if that's
+	// allowed or not.  Some HTTP clients will get the response
+	// and some (like ours, currently) will complain that the
+	// request write failed, without reading the response.
+	//
+	// But that's okay, since what we're really testing is that
+	// the remote side hung up on us before we wrote too much.
+	_, _ = DefaultClient.Do(req)
+
+	if atomic.LoadInt64(nWritten) > limit*100 {
+		t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d",
+			limit, nWritten)
+	}
+}
+
+// TestClientWriteShutdown tests that if the client shuts down the write
+// side of their TCP connection, the server doesn't send a 400 Bad Request.
+func TestClientWriteShutdown(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping test; see http://golang.org/issue/7237")
+	}
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+	defer ts.Close()
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	err = conn.(*net.TCPConn).CloseWrite()
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	donec := make(chan bool)
+	go func() {
+		defer close(donec)
+		bs, err := ioutil.ReadAll(conn)
+		if err != nil {
+			t.Fatalf("ReadAll: %v", err)
+		}
+		got := string(bs)
+		if got != "" {
+			t.Errorf("read %q from server; want nothing", got)
+		}
+	}()
+	select {
+	case <-donec:
+	case <-time.After(10 * time.Second):
+		t.Fatalf("timeout")
+	}
+}
+
+// Tests that chunked server responses that write 1 byte at a time are
+// buffered before chunk headers are added, not after chunk headers.
+func TestServerBufferedChunking(t *testing.T) {
+	conn := new(testConn)
+	conn.readBuf.Write([]byte("GET / HTTP/1.1\r\n\r\n"))
+	conn.closec = make(chan bool, 1)
+	ls := &oneConnListener{conn}
+	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
+		rw.(Flusher).Flush() // force the Header to be sent, in chunking mode, not counting the length
+		rw.Write([]byte{'x'})
+		rw.Write([]byte{'y'})
+		rw.Write([]byte{'z'})
+	}))
+	<-conn.closec
+	if !bytes.HasSuffix(conn.writeBuf.Bytes(), []byte("\r\n\r\n3\r\nxyz\r\n0\r\n\r\n")) {
+		t.Errorf("response didn't end with a single 3 byte 'xyz' chunk; got:\n%q",
+			conn.writeBuf.Bytes())
+	}
+}
+
+// Tests that the server flushes its response headers out when it's
+// ignoring the response body and waits a bit before forcefully
+// closing the TCP connection, causing the client to get a RST.
+// See http://golang.org/issue/3595
+func TestServerGracefulClose(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		Error(w, "bye", StatusUnauthorized)
+	}))
+	defer ts.Close()
+
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer conn.Close()
+	const bodySize = 5 << 20
+	req := []byte(fmt.Sprintf("POST / HTTP/1.1\r\nHost: foo.com\r\nContent-Length: %d\r\n\r\n", bodySize))
+	for i := 0; i < bodySize; i++ {
+		req = append(req, 'x')
+	}
+	writeErr := make(chan error)
+	go func() {
+		_, err := conn.Write(req)
+		writeErr <- err
+	}()
+	br := bufio.NewReader(conn)
+	lineNum := 0
+	for {
+		line, err := br.ReadString('\n')
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			t.Fatalf("ReadLine: %v", err)
+		}
+		lineNum++
+		if lineNum == 1 && !strings.Contains(line, "401 Unauthorized") {
+			t.Errorf("Response line = %q; want a 401", line)
+		}
+	}
+	// Wait for write to finish. This is a broken pipe on both
+	// Darwin and Linux, but checking this isn't the point of
+	// the test.
+	<-writeErr
+}
+
+func TestCaseSensitiveMethod(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.Method != "get" {
+			t.Errorf(`Got method %q; want "get"`, r.Method)
+		}
+	}))
+	defer ts.Close()
+	req, _ := NewRequest("get", ts.URL, nil)
+	res, err := DefaultClient.Do(req)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	res.Body.Close()
+}
+
+// TestContentLengthZero tests that for both an HTTP/1.0 and HTTP/1.1
+// request (both keep-alive), when a Handler never writes any
+// response, the net/http package adds a "Content-Length: 0" response
+// header.
+func TestContentLengthZero(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {}))
+	defer ts.Close()
+
+	for _, version := range []string{"HTTP/1.0", "HTTP/1.1"} {
+		conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatalf("error dialing: %v", err)
+		}
+		_, err = fmt.Fprintf(conn, "GET / %v\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n", version)
+		if err != nil {
+			t.Fatalf("error writing: %v", err)
+		}
+		req, _ := NewRequest("GET", "/", nil)
+		res, err := ReadResponse(bufio.NewReader(conn), req)
+		if err != nil {
+			t.Fatalf("error reading response: %v", err)
+		}
+		if te := res.TransferEncoding; len(te) > 0 {
+			t.Errorf("For version %q, Transfer-Encoding = %q; want none", version, te)
+		}
+		if cl := res.ContentLength; cl != 0 {
+			t.Errorf("For version %q, Content-Length = %v; want 0", version, cl)
+		}
+		conn.Close()
+	}
+}
+
+func TestCloseNotifier(t *testing.T) {
+	defer afterTest(t)
+	gotReq := make(chan bool, 1)
+	sawClose := make(chan bool, 1)
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		gotReq <- true
+		cc := rw.(CloseNotifier).CloseNotify()
+		<-cc
+		sawClose <- true
+	}))
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("error dialing: %v", err)
+	}
+	diec := make(chan bool)
+	go func() {
+		_, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n")
+		if err != nil {
+			t.Fatal(err)
+		}
+		<-diec
+		conn.Close()
+	}()
+For:
+	for {
+		select {
+		case <-gotReq:
+			diec <- true
+		case <-sawClose:
+			break For
+		case <-time.After(5 * time.Second):
+			t.Fatal("timeout")
+		}
+	}
+	ts.Close()
+}
+
+func TestCloseNotifierChanLeak(t *testing.T) {
+	defer afterTest(t)
+	req := reqBytes("GET / HTTP/1.0\nHost: golang.org")
+	for i := 0; i < 20; i++ {
+		var output bytes.Buffer
+		conn := &rwTestConn{
+			Reader: bytes.NewReader(req),
+			Writer: &output,
+			closec: make(chan bool, 1),
+		}
+		ln := &oneConnListener{conn: conn}
+		handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+			// Ignore the return value and never read from
+			// it, testing that we don't leak goroutines
+			// on the sending side:
+			_ = rw.(CloseNotifier).CloseNotify()
+		})
+		go Serve(ln, handler)
+		<-conn.closec
+	}
+}
+
+func TestOptions(t *testing.T) {
+	uric := make(chan string, 2) // only expect 1, but leave space for 2
+	mux := NewServeMux()
+	mux.HandleFunc("/", func(w ResponseWriter, r *Request) {
+		uric <- r.RequestURI
+	})
+	ts := httptest.NewServer(mux)
+	defer ts.Close()
+
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer conn.Close()
+
+	// An OPTIONS * request should succeed.
+	_, err = conn.Write([]byte("OPTIONS * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	br := bufio.NewReader(conn)
+	res, err := ReadResponse(br, &Request{Method: "OPTIONS"})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != 200 {
+		t.Errorf("Got non-200 response to OPTIONS *: %#v", res)
+	}
+
+	// A GET * request on a ServeMux should fail.
+	_, err = conn.Write([]byte("GET * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	res, err = ReadResponse(br, &Request{Method: "GET"})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != 400 {
+		t.Errorf("Got non-400 response to GET *: %#v", res)
+	}
+
+	res, err = Get(ts.URL + "/second")
+	if err != nil {
+		t.Fatal(err)
+	}
+	res.Body.Close()
+	if got := <-uric; got != "/second" {
+		t.Errorf("Handler saw request for %q; want /second", got)
+	}
+}
+
+// Tests regarding the ordering of Write, WriteHeader, Header, and
+// Flush calls.  In Go 1.0, rw.WriteHeader immediately flushed the
+// (*response).header to the wire. In Go 1.1, the actual wire flush is
+// delayed, so we could maybe tack on a Content-Length and better
+// Content-Type after we see more (or all) of the output. To preserve
+// compatibility with Go 1, we need to be careful to track which
+// headers were live at the time of WriteHeader, so we write the same
+// ones, even if the handler modifies them (~erroneously) after the
+// first Write.
+func TestHeaderToWire(t *testing.T) {
+	tests := []struct {
+		name    string
+		handler func(ResponseWriter, *Request)
+		check   func(output string) error
+	}{
+		{
+			name: "write without Header",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Write([]byte("hello world"))
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Content-Length:") {
+					return errors.New("no content-length")
+				}
+				if !strings.Contains(got, "Content-Type: text/plain") {
+					return errors.New("no content-length")
+				}
+				return nil
+			},
+		},
+		{
+			name: "Header mutation before write",
+			handler: func(rw ResponseWriter, r *Request) {
+				h := rw.Header()
+				h.Set("Content-Type", "some/type")
+				rw.Write([]byte("hello world"))
+				h.Set("Too-Late", "bogus")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Content-Length:") {
+					return errors.New("no content-length")
+				}
+				if !strings.Contains(got, "Content-Type: some/type") {
+					return errors.New("wrong content-type")
+				}
+				if strings.Contains(got, "Too-Late") {
+					return errors.New("don't want too-late header")
+				}
+				return nil
+			},
+		},
+		{
+			name: "write then useless Header mutation",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Write([]byte("hello world"))
+				rw.Header().Set("Too-Late", "Write already wrote headers")
+			},
+			check: func(got string) error {
+				if strings.Contains(got, "Too-Late") {
+					return errors.New("header appeared from after WriteHeader")
+				}
+				return nil
+			},
+		},
+		{
+			name: "flush then write",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.(Flusher).Flush()
+				rw.Write([]byte("post-flush"))
+				rw.Header().Set("Too-Late", "Write already wrote headers")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Transfer-Encoding: chunked") {
+					return errors.New("not chunked")
+				}
+				if strings.Contains(got, "Too-Late") {
+					return errors.New("header appeared from after WriteHeader")
+				}
+				return nil
+			},
+		},
+		{
+			name: "header then flush",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Header().Set("Content-Type", "some/type")
+				rw.(Flusher).Flush()
+				rw.Write([]byte("post-flush"))
+				rw.Header().Set("Too-Late", "Write already wrote headers")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Transfer-Encoding: chunked") {
+					return errors.New("not chunked")
+				}
+				if strings.Contains(got, "Too-Late") {
+					return errors.New("header appeared from after WriteHeader")
+				}
+				if !strings.Contains(got, "Content-Type: some/type") {
+					return errors.New("wrong content-length")
+				}
+				return nil
+			},
+		},
+		{
+			name: "sniff-on-first-write content-type",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Write([]byte("<html><head></head><body>some html</body></html>"))
+				rw.Header().Set("Content-Type", "x/wrong")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Content-Type: text/html") {
+					return errors.New("wrong content-length; want html")
+				}
+				return nil
+			},
+		},
+		{
+			name: "explicit content-type wins",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Header().Set("Content-Type", "some/type")
+				rw.Write([]byte("<html><head></head><body>some html</body></html>"))
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Content-Type: some/type") {
+					return errors.New("wrong content-length; want html")
+				}
+				return nil
+			},
+		},
+		{
+			name: "empty handler",
+			handler: func(rw ResponseWriter, r *Request) {
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Content-Type: text/plain") {
+					return errors.New("wrong content-length; want text/plain")
+				}
+				if !strings.Contains(got, "Content-Length: 0") {
+					return errors.New("want 0 content-length")
+				}
+				return nil
+			},
+		},
+		{
+			name: "only Header, no write",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.Header().Set("Some-Header", "some-value")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "Some-Header") {
+					return errors.New("didn't get header")
+				}
+				return nil
+			},
+		},
+		{
+			name: "WriteHeader call",
+			handler: func(rw ResponseWriter, r *Request) {
+				rw.WriteHeader(404)
+				rw.Header().Set("Too-Late", "some-value")
+			},
+			check: func(got string) error {
+				if !strings.Contains(got, "404") {
+					return errors.New("wrong status")
+				}
+				if strings.Contains(got, "Some-Header") {
+					return errors.New("shouldn't have seen Too-Late")
+				}
+				return nil
+			},
+		},
+	}
+	for _, tc := range tests {
+		ht := newHandlerTest(HandlerFunc(tc.handler))
+		got := ht.rawResponse("GET / HTTP/1.1\nHost: golang.org")
+		if err := tc.check(got); err != nil {
+			t.Errorf("%s: %v\nGot response:\n%s", tc.name, err, got)
+		}
+	}
+}
+
+// goTimeout runs f, failing t if f takes more than ns to complete.
+func goTimeout(t *testing.T, d time.Duration, f func()) {
+	ch := make(chan bool, 2)
+	timer := time.AfterFunc(d, func() {
+		t.Errorf("Timeout expired after %v", d)
+		ch <- true
+	})
+	defer timer.Stop()
+	go func() {
+		defer func() { ch <- true }()
+		f()
+	}()
+	<-ch
+}
+
+type errorListener struct {
+	errs []error
+}
+
+func (l *errorListener) Accept() (c net.Conn, err error) {
+	if len(l.errs) == 0 {
+		return nil, io.EOF
+	}
+	err = l.errs[0]
+	l.errs = l.errs[1:]
+	return
+}
+
+func (l *errorListener) Close() error {
+	return nil
+}
+
+func (l *errorListener) Addr() net.Addr {
+	return dummyAddr("test-address")
+}
+
+func TestAcceptMaxFds(t *testing.T) {
+	log.SetOutput(ioutil.Discard) // is noisy otherwise
+	defer log.SetOutput(os.Stderr)
+
+	ln := &errorListener{[]error{
+		&net.OpError{
+			Op:  "accept",
+			Err: syscall.EMFILE,
+		}}}
+	err := Serve(ln, HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})))
+	if err != io.EOF {
+		t.Errorf("got error %v, want EOF", err)
+	}
+}
+
+func TestWriteAfterHijack(t *testing.T) {
+	req := reqBytes("GET / HTTP/1.1\nHost: golang.org")
+	var buf bytes.Buffer
+	wrotec := make(chan bool, 1)
+	conn := &rwTestConn{
+		Reader: bytes.NewReader(req),
+		Writer: &buf,
+		closec: make(chan bool, 1),
+	}
+	handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+		conn, bufrw, err := rw.(Hijacker).Hijack()
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		go func() {
+			bufrw.Write([]byte("[hijack-to-bufw]"))
+			bufrw.Flush()
+			conn.Write([]byte("[hijack-to-conn]"))
+			conn.Close()
+			wrotec <- true
+		}()
+	})
+	ln := &oneConnListener{conn: conn}
+	go Serve(ln, handler)
+	<-conn.closec
+	<-wrotec
+	if g, w := buf.String(), "[hijack-to-bufw][hijack-to-conn]"; g != w {
+		t.Errorf("wrote %q; want %q", g, w)
+	}
+}
+
+func TestDoubleHijack(t *testing.T) {
+	req := reqBytes("GET / HTTP/1.1\nHost: golang.org")
+	var buf bytes.Buffer
+	conn := &rwTestConn{
+		Reader: bytes.NewReader(req),
+		Writer: &buf,
+		closec: make(chan bool, 1),
+	}
+	handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+		conn, _, err := rw.(Hijacker).Hijack()
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		_, _, err = rw.(Hijacker).Hijack()
+		if err == nil {
+			t.Errorf("got err = nil;  want err != nil")
+		}
+		conn.Close()
+	})
+	ln := &oneConnListener{conn: conn}
+	go Serve(ln, handler)
+	<-conn.closec
+}
+
+// http://code.google.com/p/go/issues/detail?id=5955
+// Note that this does not test the "request too large"
+// exit path from the http server. This is intentional;
+// not sending Connection: close is just a minor wire
+// optimization and is pointless if dealing with a
+// badly behaved client.
+func TestHTTP10ConnectionHeader(t *testing.T) {
+	defer afterTest(t)
+
+	mux := NewServeMux()
+	mux.Handle("/", HandlerFunc(func(resp ResponseWriter, req *Request) {}))
+	ts := httptest.NewServer(mux)
+	defer ts.Close()
+
+	// net/http uses HTTP/1.1 for requests, so write requests manually
+	tests := []struct {
+		req    string   // raw http request
+		expect []string // expected Connection header(s)
+	}{
+		{
+			req:    "GET / HTTP/1.0\r\n\r\n",
+			expect: nil,
+		},
+		{
+			req:    "OPTIONS * HTTP/1.0\r\n\r\n",
+			expect: nil,
+		},
+		{
+			req:    "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n",
+			expect: []string{"keep-alive"},
+		},
+	}
+
+	for _, tt := range tests {
+		conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatal("dial err:", err)
+		}
+
+		_, err = fmt.Fprint(conn, tt.req)
+		if err != nil {
+			t.Fatal("conn write err:", err)
+		}
+
+		resp, err := ReadResponse(bufio.NewReader(conn), &Request{Method: "GET"})
+		if err != nil {
+			t.Fatal("ReadResponse err:", err)
+		}
+		conn.Close()
+		resp.Body.Close()
+
+		got := resp.Header["Connection"]
+		if !reflect.DeepEqual(got, tt.expect) {
+			t.Errorf("wrong Connection headers for request %q. Got %q expect %q", tt.req, got, tt.expect)
+		}
+	}
+}
+
+// See golang.org/issue/5660
+func TestServerReaderFromOrder(t *testing.T) {
+	defer afterTest(t)
+	pr, pw := io.Pipe()
+	const size = 3 << 20
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		rw.Header().Set("Content-Type", "text/plain") // prevent sniffing path
+		done := make(chan bool)
+		go func() {
+			io.Copy(rw, pr)
+			close(done)
+		}()
+		time.Sleep(25 * time.Millisecond) // give Copy a chance to break things
+		n, err := io.Copy(ioutil.Discard, req.Body)
+		if err != nil {
+			t.Errorf("handler Copy: %v", err)
+			return
+		}
+		if n != size {
+			t.Errorf("handler Copy = %d; want %d", n, size)
+		}
+		pw.Write([]byte("hi"))
+		pw.Close()
+		<-done
+	}))
+	defer ts.Close()
+
+	req, err := NewRequest("POST", ts.URL, io.LimitReader(neverEnding('a'), size))
+	if err != nil {
+		t.Fatal(err)
+	}
+	res, err := DefaultClient.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	all, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	res.Body.Close()
+	if string(all) != "hi" {
+		t.Errorf("Body = %q; want hi", all)
+	}
+}
+
+// Issue 6157, Issue 6685
+func TestCodesPreventingContentTypeAndBody(t *testing.T) {
+	for _, code := range []int{StatusNotModified, StatusNoContent, StatusContinue} {
+		ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
+			if r.URL.Path == "/header" {
+				w.Header().Set("Content-Length", "123")
+			}
+			w.WriteHeader(code)
+			if r.URL.Path == "/more" {
+				w.Write([]byte("stuff"))
+			}
+		}))
+		for _, req := range []string{
+			"GET / HTTP/1.0",
+			"GET /header HTTP/1.0",
+			"GET /more HTTP/1.0",
+			"GET / HTTP/1.1",
+			"GET /header HTTP/1.1",
+			"GET /more HTTP/1.1",
+		} {
+			got := ht.rawResponse(req)
+			wantStatus := fmt.Sprintf("%d %s", code, StatusText(code))
+			if !strings.Contains(got, wantStatus) {
+				t.Errorf("Code %d: Wanted %q Modified for %q: %s", code, wantStatus, req, got)
+			} else if strings.Contains(got, "Content-Length") {
+				t.Errorf("Code %d: Got a Content-Length from %q: %s", code, req, got)
+			} else if strings.Contains(got, "stuff") {
+				t.Errorf("Code %d: Response contains a body from %q: %s", code, req, got)
+			}
+		}
+	}
+}
+
+func TestContentTypeOkayOn204(t *testing.T) {
+	ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Length", "123") // suppressed
+		w.Header().Set("Content-Type", "foo/bar")
+		w.WriteHeader(204)
+	}))
+	got := ht.rawResponse("GET / HTTP/1.1")
+	if !strings.Contains(got, "Content-Type: foo/bar") {
+		t.Errorf("Response = %q; want Content-Type: foo/bar", got)
+	}
+	if strings.Contains(got, "Content-Length: 123") {
+		t.Errorf("Response = %q; don't want a Content-Length", got)
+	}
+}
+
+// Issue 6995
+// A server Handler can receive a Request, and then turn around and
+// give a copy of that Request.Body out to the Transport (e.g. any
+// proxy).  So then two people own that Request.Body (both the server
+// and the http client), and both think they can close it on failure.
+// Therefore, all incoming server requests Bodies need to be thread-safe.
+func TestTransportAndServerSharedBodyRace(t *testing.T) {
+	defer afterTest(t)
+
+	const bodySize = 1 << 20
+
+	unblockBackend := make(chan bool)
+	backend := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		io.CopyN(rw, req.Body, bodySize/2)
+		<-unblockBackend
+	}))
+	defer backend.Close()
+
+	backendRespc := make(chan *Response, 1)
+	proxy := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		if req.RequestURI == "/foo" {
+			rw.Write([]byte("bar"))
+			return
+		}
+		req2, _ := NewRequest("POST", backend.URL, req.Body)
+		req2.ContentLength = bodySize
+
+		bresp, err := DefaultClient.Do(req2)
+		if err != nil {
+			t.Errorf("Proxy outbound request: %v", err)
+			return
+		}
+		_, err = io.CopyN(ioutil.Discard, bresp.Body, bodySize/4)
+		if err != nil {
+			t.Errorf("Proxy copy error: %v", err)
+			return
+		}
+		backendRespc <- bresp // to close later
+
+		// Try to cause a race: Both the DefaultTransport and the proxy handler's Server
+		// will try to read/close req.Body (aka req2.Body)
+		DefaultTransport.(*Transport).CancelRequest(req2)
+		rw.Write([]byte("OK"))
+	}))
+	defer proxy.Close()
+
+	req, _ := NewRequest("POST", proxy.URL, io.LimitReader(neverEnding('a'), bodySize))
+	res, err := DefaultClient.Do(req)
+	if err != nil {
+		t.Fatalf("Original request: %v", err)
+	}
+
+	// Cleanup, so we don't leak goroutines.
+	res.Body.Close()
+	close(unblockBackend)
+	(<-backendRespc).Body.Close()
+}
+
+// Test that a hanging Request.Body.Read from another goroutine can't
+// cause the Handler goroutine's Request.Body.Close to block.
+func TestRequestBodyCloseDoesntBlock(t *testing.T) {
+	t.Skipf("Skipping known issue; see golang.org/issue/7121")
+	if testing.Short() {
+		t.Skip("skipping in -short mode")
+	}
+	defer afterTest(t)
+
+	readErrCh := make(chan error, 1)
+	errCh := make(chan error, 2)
+
+	server := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		go func(body io.Reader) {
+			_, err := body.Read(make([]byte, 100))
+			readErrCh <- err
+		}(req.Body)
+		time.Sleep(500 * time.Millisecond)
+	}))
+	defer server.Close()
+
+	closeConn := make(chan bool)
+	defer close(closeConn)
+	go func() {
+		conn, err := net.Dial("tcp", server.Listener.Addr().String())
+		if err != nil {
+			errCh <- err
+			return
+		}
+		defer conn.Close()
+		_, err = conn.Write([]byte("POST / HTTP/1.1\r\nConnection: close\r\nHost: foo\r\nContent-Length: 100000\r\n\r\n"))
+		if err != nil {
+			errCh <- err
+			return
+		}
+		// And now just block, making the server block on our
+		// 100000 bytes of body that will never arrive.
+		<-closeConn
+	}()
+	select {
+	case err := <-readErrCh:
+		if err == nil {
+			t.Error("Read was nil. Expected error.")
+		}
+	case err := <-errCh:
+		t.Error(err)
+	case <-time.After(5 * time.Second):
+		t.Error("timeout")
+	}
+}
+
+func TestResponseWriterWriteStringAllocs(t *testing.T) {
+	t.Skip("allocs test unreliable with gccgo")
+	ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.URL.Path == "/s" {
+			io.WriteString(w, "Hello world")
+		} else {
+			w.Write([]byte("Hello world"))
+		}
+	}))
+	before := testing.AllocsPerRun(50, func() { ht.rawResponse("GET / HTTP/1.0") })
+	after := testing.AllocsPerRun(50, func() { ht.rawResponse("GET /s HTTP/1.0") })
+	if int(after) >= int(before) {
+		t.Errorf("WriteString allocs of %v >= Write allocs of %v", after, before)
+	}
+}
+
+func TestAppendTime(t *testing.T) {
+	var b [len(TimeFormat)]byte
+	t1 := time.Date(2013, 9, 21, 15, 41, 0, 0, time.FixedZone("CEST", 2*60*60))
+	res := ExportAppendTime(b[:0], t1)
+	t2, err := ParseTime(string(res))
+	if err != nil {
+		t.Fatalf("Error parsing time: %s", err)
+	}
+	if !t1.Equal(t2) {
+		t.Fatalf("Times differ; expected: %v, got %v (%s)", t1, t2, string(res))
+	}
+}
+
+func TestServerConnState(t *testing.T) {
+	defer afterTest(t)
+	handler := map[string]func(w ResponseWriter, r *Request){
+		"/": func(w ResponseWriter, r *Request) {
+			fmt.Fprintf(w, "Hello.")
+		},
+		"/close": func(w ResponseWriter, r *Request) {
+			w.Header().Set("Connection", "close")
+			fmt.Fprintf(w, "Hello.")
+		},
+		"/hijack": func(w ResponseWriter, r *Request) {
+			c, _, _ := w.(Hijacker).Hijack()
+			c.Write([]byte("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nHello."))
+			c.Close()
+		},
+		"/hijack-panic": func(w ResponseWriter, r *Request) {
+			c, _, _ := w.(Hijacker).Hijack()
+			c.Write([]byte("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nHello."))
+			c.Close()
+			panic("intentional panic")
+		},
+	}
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		handler[r.URL.Path](w, r)
+	}))
+	defer ts.Close()
+
+	var mu sync.Mutex // guard stateLog and connID
+	var stateLog = map[int][]ConnState{}
+	var connID = map[net.Conn]int{}
+
+	ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0)
+	ts.Config.ConnState = func(c net.Conn, state ConnState) {
+		if c == nil {
+			t.Errorf("nil conn seen in state %s", state)
+			return
+		}
+		mu.Lock()
+		defer mu.Unlock()
+		id, ok := connID[c]
+		if !ok {
+			id = len(connID) + 1
+			connID[c] = id
+		}
+		stateLog[id] = append(stateLog[id], state)
+	}
+	ts.Start()
+
+	mustGet(t, ts.URL+"/")
+	mustGet(t, ts.URL+"/close")
+
+	mustGet(t, ts.URL+"/")
+	mustGet(t, ts.URL+"/", "Connection", "close")
+
+	mustGet(t, ts.URL+"/hijack")
+	mustGet(t, ts.URL+"/hijack-panic")
+
+	// New->Closed
+	{
+		c, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatal(err)
+		}
+		c.Close()
+	}
+
+	// New->Active->Closed
+	{
+		c, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatal(err)
+		}
+		if _, err := io.WriteString(c, "BOGUS REQUEST\r\n\r\n"); err != nil {
+			t.Fatal(err)
+		}
+		c.Close()
+	}
+
+	// New->Idle->Closed
+	{
+		c, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatal(err)
+		}
+		if _, err := io.WriteString(c, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n"); err != nil {
+			t.Fatal(err)
+		}
+		res, err := ReadResponse(bufio.NewReader(c), nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
+			t.Fatal(err)
+		}
+		c.Close()
+	}
+
+	want := map[int][]ConnState{
+		1: []ConnState{StateNew, StateActive, StateIdle, StateActive, StateClosed},
+		2: []ConnState{StateNew, StateActive, StateIdle, StateActive, StateClosed},
+		3: []ConnState{StateNew, StateActive, StateHijacked},
+		4: []ConnState{StateNew, StateActive, StateHijacked},
+		5: []ConnState{StateNew, StateClosed},
+		6: []ConnState{StateNew, StateActive, StateClosed},
+		7: []ConnState{StateNew, StateActive, StateIdle, StateClosed},
+	}
+	logString := func(m map[int][]ConnState) string {
+		var b bytes.Buffer
+		for id, l := range m {
+			fmt.Fprintf(&b, "Conn %d: ", id)
+			for _, s := range l {
+				fmt.Fprintf(&b, "%s ", s)
+			}
+			b.WriteString("\n")
+		}
+		return b.String()
+	}
+
+	for i := 0; i < 5; i++ {
+		time.Sleep(time.Duration(i) * 50 * time.Millisecond)
+		mu.Lock()
+		match := reflect.DeepEqual(stateLog, want)
+		mu.Unlock()
+		if match {
+			return
+		}
+	}
+
+	mu.Lock()
+	t.Errorf("Unexpected events.\nGot log: %s\n   Want: %s\n", logString(stateLog), logString(want))
+	mu.Unlock()
+}
+
+func mustGet(t *testing.T, url string, headers ...string) {
+	req, err := NewRequest("GET", url, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for len(headers) > 0 {
+		req.Header.Add(headers[0], headers[1])
+		headers = headers[2:]
+	}
+	res, err := DefaultClient.Do(req)
+	if err != nil {
+		t.Errorf("Error fetching %s: %v", url, err)
+		return
+	}
+	_, err = ioutil.ReadAll(res.Body)
+	defer res.Body.Close()
+	if err != nil {
+		t.Errorf("Error reading %s: %v", url, err)
+	}
+}
+
+func TestServerKeepAlivesEnabled(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+	ts.Config.SetKeepAlivesEnabled(false)
+	ts.Start()
+	defer ts.Close()
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer res.Body.Close()
+	if !res.Close {
+		t.Errorf("Body.Close == false; want true")
+	}
+}
+
+// golang.org/issue/7856
+func TestServerEmptyBodyRace(t *testing.T) {
+	defer afterTest(t)
+	var n int32
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		atomic.AddInt32(&n, 1)
+	}))
+	defer ts.Close()
+	var wg sync.WaitGroup
+	const reqs = 20
+	for i := 0; i < reqs; i++ {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			res, err := Get(ts.URL)
+			if err != nil {
+				t.Error(err)
+				return
+			}
+			defer res.Body.Close()
+			_, err = io.Copy(ioutil.Discard, res.Body)
+			if err != nil {
+				t.Error(err)
+				return
+			}
+		}()
+	}
+	wg.Wait()
+	if got := atomic.LoadInt32(&n); got != reqs {
+		t.Errorf("handler ran %d times; want %d", got, reqs)
+	}
+}
+
+func TestServerConnStateNew(t *testing.T) {
+	sawNew := false // if the test is buggy, we'll race on this variable.
+	srv := &Server{
+		ConnState: func(c net.Conn, state ConnState) {
+			if state == StateNew {
+				sawNew = true // testing that this write isn't racy
+			}
+		},
+		Handler: HandlerFunc(func(w ResponseWriter, r *Request) {}), // irrelevant
+	}
+	srv.Serve(&oneConnListener{
+		conn: &rwTestConn{
+			Reader: strings.NewReader("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"),
+			Writer: ioutil.Discard,
+		},
+	})
+	if !sawNew { // testing that this read isn't racy
+		t.Error("StateNew not seen")
+	}
+}
+
+func BenchmarkClientServer(b *testing.B) {
+	b.ReportAllocs()
+	b.StopTimer()
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+		fmt.Fprintf(rw, "Hello world.\n")
+	}))
+	defer ts.Close()
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		res, err := Get(ts.URL)
+		if err != nil {
+			b.Fatal("Get:", err)
+		}
+		all, err := ioutil.ReadAll(res.Body)
+		res.Body.Close()
+		if err != nil {
+			b.Fatal("ReadAll:", err)
+		}
+		body := string(all)
+		if body != "Hello world.\n" {
+			b.Fatal("Got body:", body)
+		}
+	}
+
+	b.StopTimer()
+}
+
+func BenchmarkClientServerParallel4(b *testing.B) {
+	benchmarkClientServerParallel(b, 4)
+}
+
+func BenchmarkClientServerParallel64(b *testing.B) {
+	benchmarkClientServerParallel(b, 64)
+}
+
+func benchmarkClientServerParallel(b *testing.B, parallelism int) {
+	b.ReportAllocs()
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+		fmt.Fprintf(rw, "Hello world.\n")
+	}))
+	defer ts.Close()
+	b.ResetTimer()
+	b.SetParallelism(parallelism)
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			res, err := Get(ts.URL)
+			if err != nil {
+				b.Logf("Get: %v", err)
+				continue
+			}
+			all, err := ioutil.ReadAll(res.Body)
+			res.Body.Close()
+			if err != nil {
+				b.Logf("ReadAll: %v", err)
+				continue
+			}
+			body := string(all)
+			if body != "Hello world.\n" {
+				panic("Got body: " + body)
+			}
+		}
+	})
+}
+
+// A benchmark for profiling the server without the HTTP client code.
+// The client code runs in a subprocess.
+//
+// For use like:
+//   $ go test -c
+//   $ ./http.test -test.run=XX -test.bench=BenchmarkServer -test.benchtime=15s -test.cpuprofile=http.prof
+//   $ go tool pprof http.test http.prof
+//   (pprof) web
+func BenchmarkServer(b *testing.B) {
+	b.ReportAllocs()
+	// Child process mode;
+	if url := os.Getenv("TEST_BENCH_SERVER_URL"); url != "" {
+		n, err := strconv.Atoi(os.Getenv("TEST_BENCH_CLIENT_N"))
+		if err != nil {
+			panic(err)
+		}
+		for i := 0; i < n; i++ {
+			res, err := Get(url)
+			if err != nil {
+				log.Panicf("Get: %v", err)
+			}
+			all, err := ioutil.ReadAll(res.Body)
+			res.Body.Close()
+			if err != nil {
+				log.Panicf("ReadAll: %v", err)
+			}
+			body := string(all)
+			if body != "Hello world.\n" {
+				log.Panicf("Got body: %q", body)
+			}
+		}
+		os.Exit(0)
+		return
+	}
+
+	var res = []byte("Hello world.\n")
+	b.StopTimer()
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+		rw.Header().Set("Content-Type", "text/html; charset=utf-8")
+		rw.Write(res)
+	}))
+	defer ts.Close()
+	b.StartTimer()
+
+	cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkServer")
+	cmd.Env = append([]string{
+		fmt.Sprintf("TEST_BENCH_CLIENT_N=%d", b.N),
+		fmt.Sprintf("TEST_BENCH_SERVER_URL=%s", ts.URL),
+	}, os.Environ()...)
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		b.Errorf("Test failure: %v, with output: %s", err, out)
+	}
+}
+
+func BenchmarkServerFakeConnNoKeepAlive(b *testing.B) {
+	b.ReportAllocs()
+	req := reqBytes(`GET / HTTP/1.0
+Host: golang.org
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
+Accept-Encoding: gzip,deflate,sdch
+Accept-Language: en-US,en;q=0.8
+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
+`)
+	res := []byte("Hello world!\n")
+
+	conn := &testConn{
+		// testConn.Close will not push into the channel
+		// if it's full.
+		closec: make(chan bool, 1),
+	}
+	handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+		rw.Header().Set("Content-Type", "text/html; charset=utf-8")
+		rw.Write(res)
+	})
+	ln := new(oneConnListener)
+	for i := 0; i < b.N; i++ {
+		conn.readBuf.Reset()
+		conn.writeBuf.Reset()
+		conn.readBuf.Write(req)
+		ln.conn = conn
+		Serve(ln, handler)
+		<-conn.closec
+	}
+}
+
+// repeatReader reads content count times, then EOFs.
+type repeatReader struct {
+	content []byte
+	count   int
+	off     int
+}
+
+func (r *repeatReader) Read(p []byte) (n int, err error) {
+	if r.count <= 0 {
+		return 0, io.EOF
+	}
+	n = copy(p, r.content[r.off:])
+	r.off += n
+	if r.off == len(r.content) {
+		r.count--
+		r.off = 0
+	}
+	return
+}
+
+func BenchmarkServerFakeConnWithKeepAlive(b *testing.B) {
+	b.ReportAllocs()
+
+	req := reqBytes(`GET / HTTP/1.1
+Host: golang.org
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
+Accept-Encoding: gzip,deflate,sdch
+Accept-Language: en-US,en;q=0.8
+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
+`)
+	res := []byte("Hello world!\n")
+
+	conn := &rwTestConn{
+		Reader: &repeatReader{content: req, count: b.N},
+		Writer: ioutil.Discard,
+		closec: make(chan bool, 1),
+	}
+	handled := 0
+	handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+		handled++
+		rw.Header().Set("Content-Type", "text/html; charset=utf-8")
+		rw.Write(res)
+	})
+	ln := &oneConnListener{conn: conn}
+	go Serve(ln, handler)
+	<-conn.closec
+	if b.N != handled {
+		b.Errorf("b.N=%d but handled %d", b.N, handled)
+	}
+}
+
+// same as above, but representing the most simple possible request
+// and handler. Notably: the handler does not call rw.Header().
+func BenchmarkServerFakeConnWithKeepAliveLite(b *testing.B) {
+	b.ReportAllocs()
+
+	req := reqBytes(`GET / HTTP/1.1
+Host: golang.org
+`)
+	res := []byte("Hello world!\n")
+
+	conn := &rwTestConn{
+		Reader: &repeatReader{content: req, count: b.N},
+		Writer: ioutil.Discard,
+		closec: make(chan bool, 1),
+	}
+	handled := 0
+	handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+		handled++
+		rw.Write(res)
+	})
+	ln := &oneConnListener{conn: conn}
+	go Serve(ln, handler)
+	<-conn.closec
+	if b.N != handled {
+		b.Errorf("b.N=%d but handled %d", b.N, handled)
+	}
+}
+
+const someResponse = "<html>some response</html>"
+
+// A Response that's just no bigger than 2KB, the buffer-before-chunking threshold.
+var response = bytes.Repeat([]byte(someResponse), 2<<10/len(someResponse))
+
+// Both Content-Type and Content-Length set. Should be no buffering.
+func BenchmarkServerHandlerTypeLen(b *testing.B) {
+	benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Type", "text/html")
+		w.Header().Set("Content-Length", strconv.Itoa(len(response)))
+		w.Write(response)
+	}))
+}
+
+// A Content-Type is set, but no length. No sniffing, but will count the Content-Length.
+func BenchmarkServerHandlerNoLen(b *testing.B) {
+	benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Type", "text/html")
+		w.Write(response)
+	}))
+}
+
+// A Content-Length is set, but the Content-Type will be sniffed.
+func BenchmarkServerHandlerNoType(b *testing.B) {
+	benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Length", strconv.Itoa(len(response)))
+		w.Write(response)
+	}))
+}
+
+// Neither a Content-Type or Content-Length, so sniffed and counted.
+func BenchmarkServerHandlerNoHeader(b *testing.B) {
+	benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Write(response)
+	}))
+}
+
+func benchmarkHandler(b *testing.B, h Handler) {
+	b.ReportAllocs()
+	req := reqBytes(`GET / HTTP/1.1
+Host: golang.org
+`)
+	conn := &rwTestConn{
+		Reader: &repeatReader{content: req, count: b.N},
+		Writer: ioutil.Discard,
+		closec: make(chan bool, 1),
+	}
+	handled := 0
+	handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+		handled++
+		h.ServeHTTP(rw, r)
+	})
+	ln := &oneConnListener{conn: conn}
+	go Serve(ln, handler)
+	<-conn.closec
+	if b.N != handled {
+		b.Errorf("b.N=%d but handled %d", b.N, handled)
+	}
+}
+
+func BenchmarkServerHijack(b *testing.B) {
+	b.ReportAllocs()
+	req := reqBytes(`GET / HTTP/1.1
+Host: golang.org
+`)
+	h := HandlerFunc(func(w ResponseWriter, r *Request) {
+		conn, _, err := w.(Hijacker).Hijack()
+		if err != nil {
+			panic(err)
+		}
+		conn.Close()
+	})
+	conn := &rwTestConn{
+		Writer: ioutil.Discard,
+		closec: make(chan bool, 1),
+	}
+	ln := &oneConnListener{conn: conn}
+	for i := 0; i < b.N; i++ {
+		conn.Reader = bytes.NewReader(req)
+		ln.conn = conn
+		Serve(ln, h)
+		<-conn.closec
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/server.go b/third_party/gofrontend/libgo/go/net/http/server.go
new file mode 100644
index 0000000..eae097e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/server.go
@@ -0,0 +1,2052 @@
+// 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.
+
+// HTTP server.  See RFC 2616.
+
+package http
+
+import (
+	"bufio"
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/url"
+	"os"
+	"path"
+	"runtime"
+	"strconv"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"time"
+)
+
+// Errors introduced by the HTTP server.
+var (
+	ErrWriteAfterFlush = errors.New("Conn.Write called after Flush")
+	ErrBodyNotAllowed  = errors.New("http: request method or response status code does not allow body")
+	ErrHijacked        = errors.New("Conn has been hijacked")
+	ErrContentLength   = errors.New("Conn.Write wrote more than the declared Content-Length")
+)
+
+// Objects implementing the Handler interface can be
+// registered to serve a particular path or subtree
+// in the HTTP server.
+//
+// ServeHTTP should write reply headers and data to the ResponseWriter
+// and then return.  Returning signals that the request is finished
+// and that the HTTP server can move on to the next request on
+// the connection.
+type Handler interface {
+	ServeHTTP(ResponseWriter, *Request)
+}
+
+// A ResponseWriter interface is used by an HTTP handler to
+// construct an HTTP response.
+type ResponseWriter interface {
+	// Header returns the header map that will be sent by WriteHeader.
+	// Changing the header after a call to WriteHeader (or Write) has
+	// no effect.
+	Header() Header
+
+	// Write writes the data to the connection as part of an HTTP reply.
+	// If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
+	// before writing the data.  If the Header does not contain a
+	// Content-Type line, Write adds a Content-Type set to the result of passing
+	// the initial 512 bytes of written data to DetectContentType.
+	Write([]byte) (int, error)
+
+	// WriteHeader sends an HTTP response header with status code.
+	// If WriteHeader is not called explicitly, the first call to Write
+	// will trigger an implicit WriteHeader(http.StatusOK).
+	// Thus explicit calls to WriteHeader are mainly used to
+	// send error codes.
+	WriteHeader(int)
+}
+
+// The Flusher interface is implemented by ResponseWriters that allow
+// an HTTP handler to flush buffered data to the client.
+//
+// Note that even for ResponseWriters that support Flush,
+// if the client is connected through an HTTP proxy,
+// the buffered data may not reach the client until the response
+// completes.
+type Flusher interface {
+	// Flush sends any buffered data to the client.
+	Flush()
+}
+
+// The Hijacker interface is implemented by ResponseWriters that allow
+// an HTTP handler to take over the connection.
+type Hijacker interface {
+	// Hijack lets the caller take over the connection.
+	// After a call to Hijack(), the HTTP server library
+	// will not do anything else with the connection.
+	// It becomes the caller's responsibility to manage
+	// and close the connection.
+	Hijack() (net.Conn, *bufio.ReadWriter, error)
+}
+
+// The CloseNotifier interface is implemented by ResponseWriters which
+// allow detecting when the underlying connection has gone away.
+//
+// This mechanism can be used to cancel long operations on the server
+// if the client has disconnected before the response is ready.
+type CloseNotifier interface {
+	// CloseNotify returns a channel that receives a single value
+	// when the client connection has gone away.
+	CloseNotify() <-chan bool
+}
+
+// A conn represents the server side of an HTTP connection.
+type conn struct {
+	remoteAddr string               // network address of remote side
+	server     *Server              // the Server on which the connection arrived
+	rwc        net.Conn             // i/o connection
+	sr         liveSwitchReader     // where the LimitReader reads from; usually the rwc
+	lr         *io.LimitedReader    // io.LimitReader(sr)
+	buf        *bufio.ReadWriter    // buffered(lr,rwc), reading from bufio->limitReader->sr->rwc
+	tlsState   *tls.ConnectionState // or nil when not using TLS
+
+	mu           sync.Mutex // guards the following
+	clientGone   bool       // if client has disconnected mid-request
+	closeNotifyc chan bool  // made lazily
+	hijackedv    bool       // connection has been hijacked by handler
+}
+
+func (c *conn) hijacked() bool {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	return c.hijackedv
+}
+
+func (c *conn) hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.hijackedv {
+		return nil, nil, ErrHijacked
+	}
+	if c.closeNotifyc != nil {
+		return nil, nil, errors.New("http: Hijack is incompatible with use of CloseNotifier")
+	}
+	c.hijackedv = true
+	rwc = c.rwc
+	buf = c.buf
+	c.rwc = nil
+	c.buf = nil
+	c.setState(rwc, StateHijacked)
+	return
+}
+
+func (c *conn) closeNotify() <-chan bool {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.closeNotifyc == nil {
+		c.closeNotifyc = make(chan bool, 1)
+		if c.hijackedv {
+			// to obey the function signature, even though
+			// it'll never receive a value.
+			return c.closeNotifyc
+		}
+		pr, pw := io.Pipe()
+
+		readSource := c.sr.r
+		c.sr.Lock()
+		c.sr.r = pr
+		c.sr.Unlock()
+		go func() {
+			_, err := io.Copy(pw, readSource)
+			if err == nil {
+				err = io.EOF
+			}
+			pw.CloseWithError(err)
+			c.noteClientGone()
+		}()
+	}
+	return c.closeNotifyc
+}
+
+func (c *conn) noteClientGone() {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.closeNotifyc != nil && !c.clientGone {
+		c.closeNotifyc <- true
+	}
+	c.clientGone = true
+}
+
+// A switchReader can have its Reader changed at runtime.
+// It's not safe for concurrent Reads and switches.
+type switchReader struct {
+	io.Reader
+}
+
+// A switchWriter can have its Writer changed at runtime.
+// It's not safe for concurrent Writes and switches.
+type switchWriter struct {
+	io.Writer
+}
+
+// A liveSwitchReader is a switchReader that's safe for concurrent
+// reads and switches, if its mutex is held.
+type liveSwitchReader struct {
+	sync.Mutex
+	r io.Reader
+}
+
+func (sr *liveSwitchReader) Read(p []byte) (n int, err error) {
+	sr.Lock()
+	r := sr.r
+	sr.Unlock()
+	return r.Read(p)
+}
+
+// This should be >= 512 bytes for DetectContentType,
+// but otherwise it's somewhat arbitrary.
+const bufferBeforeChunkingSize = 2048
+
+// chunkWriter writes to a response's conn buffer, and is the writer
+// wrapped by the response.bufw buffered writer.
+//
+// chunkWriter also is responsible for finalizing the Header, including
+// conditionally setting the Content-Type and setting a Content-Length
+// in cases where the handler's final output is smaller than the buffer
+// size. It also conditionally adds chunk headers, when in chunking mode.
+//
+// See the comment above (*response).Write for the entire write flow.
+type chunkWriter struct {
+	res *response
+
+	// header is either nil or a deep clone of res.handlerHeader
+	// at the time of res.WriteHeader, if res.WriteHeader is
+	// called and extra buffering is being done to calculate
+	// Content-Type and/or Content-Length.
+	header Header
+
+	// wroteHeader tells whether the header's been written to "the
+	// wire" (or rather: w.conn.buf). this is unlike
+	// (*response).wroteHeader, which tells only whether it was
+	// logically written.
+	wroteHeader bool
+
+	// set by the writeHeader method:
+	chunking bool // using chunked transfer encoding for reply body
+}
+
+var (
+	crlf       = []byte("\r\n")
+	colonSpace = []byte(": ")
+)
+
+func (cw *chunkWriter) Write(p []byte) (n int, err error) {
+	if !cw.wroteHeader {
+		cw.writeHeader(p)
+	}
+	if cw.res.req.Method == "HEAD" {
+		// Eat writes.
+		return len(p), nil
+	}
+	if cw.chunking {
+		_, err = fmt.Fprintf(cw.res.conn.buf, "%x\r\n", len(p))
+		if err != nil {
+			cw.res.conn.rwc.Close()
+			return
+		}
+	}
+	n, err = cw.res.conn.buf.Write(p)
+	if cw.chunking && err == nil {
+		_, err = cw.res.conn.buf.Write(crlf)
+	}
+	if err != nil {
+		cw.res.conn.rwc.Close()
+	}
+	return
+}
+
+func (cw *chunkWriter) flush() {
+	if !cw.wroteHeader {
+		cw.writeHeader(nil)
+	}
+	cw.res.conn.buf.Flush()
+}
+
+func (cw *chunkWriter) close() {
+	if !cw.wroteHeader {
+		cw.writeHeader(nil)
+	}
+	if cw.chunking {
+		// zero EOF chunk, trailer key/value pairs (currently
+		// unsupported in Go's server), followed by a blank
+		// line.
+		cw.res.conn.buf.WriteString("0\r\n\r\n")
+	}
+}
+
+// A response represents the server side of an HTTP response.
+type response struct {
+	conn          *conn
+	req           *Request // request for this response
+	wroteHeader   bool     // reply header has been (logically) written
+	wroteContinue bool     // 100 Continue response was written
+
+	w  *bufio.Writer // buffers output in chunks to chunkWriter
+	cw chunkWriter
+	sw *switchWriter // of the bufio.Writer, for return to putBufioWriter
+
+	// handlerHeader is the Header that Handlers get access to,
+	// which may be retained and mutated even after WriteHeader.
+	// handlerHeader is copied into cw.header at WriteHeader
+	// time, and privately mutated thereafter.
+	handlerHeader Header
+	calledHeader  bool // handler accessed handlerHeader via Header
+
+	written       int64 // number of bytes written in body
+	contentLength int64 // explicitly-declared Content-Length; or -1
+	status        int   // status code passed to WriteHeader
+
+	// close connection after this reply.  set on request and
+	// updated after response from handler if there's a
+	// "Connection: keep-alive" response header and a
+	// Content-Length.
+	closeAfterReply bool
+
+	// requestBodyLimitHit is set by requestTooLarge when
+	// maxBytesReader hits its max size. It is checked in
+	// WriteHeader, to make sure we don't consume the
+	// remaining request body to try to advance to the next HTTP
+	// request. Instead, when this is set, we stop reading
+	// subsequent requests on this connection and stop reading
+	// input from it.
+	requestBodyLimitHit bool
+
+	handlerDone bool // set true when the handler exits
+
+	// Buffers for Date and Content-Length
+	dateBuf [len(TimeFormat)]byte
+	clenBuf [10]byte
+}
+
+// requestTooLarge is called by maxBytesReader when too much input has
+// been read from the client.
+func (w *response) requestTooLarge() {
+	w.closeAfterReply = true
+	w.requestBodyLimitHit = true
+	if !w.wroteHeader {
+		w.Header().Set("Connection", "close")
+	}
+}
+
+// needsSniff reports whether a Content-Type still needs to be sniffed.
+func (w *response) needsSniff() bool {
+	_, haveType := w.handlerHeader["Content-Type"]
+	return !w.cw.wroteHeader && !haveType && w.written < sniffLen
+}
+
+// writerOnly hides an io.Writer value's optional ReadFrom method
+// from io.Copy.
+type writerOnly struct {
+	io.Writer
+}
+
+func srcIsRegularFile(src io.Reader) (isRegular bool, err error) {
+	switch v := src.(type) {
+	case *os.File:
+		fi, err := v.Stat()
+		if err != nil {
+			return false, err
+		}
+		return fi.Mode().IsRegular(), nil
+	case *io.LimitedReader:
+		return srcIsRegularFile(v.R)
+	default:
+		return
+	}
+}
+
+// ReadFrom is here to optimize copying from an *os.File regular file
+// to a *net.TCPConn with sendfile.
+func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
+	// Our underlying w.conn.rwc is usually a *TCPConn (with its
+	// own ReadFrom method). If not, or if our src isn't a regular
+	// file, just fall back to the normal copy method.
+	rf, ok := w.conn.rwc.(io.ReaderFrom)
+	regFile, err := srcIsRegularFile(src)
+	if err != nil {
+		return 0, err
+	}
+	if !ok || !regFile {
+		return io.Copy(writerOnly{w}, src)
+	}
+
+	// sendfile path:
+
+	if !w.wroteHeader {
+		w.WriteHeader(StatusOK)
+	}
+
+	if w.needsSniff() {
+		n0, err := io.Copy(writerOnly{w}, io.LimitReader(src, sniffLen))
+		n += n0
+		if err != nil {
+			return n, err
+		}
+	}
+
+	w.w.Flush()  // get rid of any previous writes
+	w.cw.flush() // make sure Header is written; flush data to rwc
+
+	// Now that cw has been flushed, its chunking field is guaranteed initialized.
+	if !w.cw.chunking && w.bodyAllowed() {
+		n0, err := rf.ReadFrom(src)
+		n += n0
+		w.written += n0
+		return n, err
+	}
+
+	n0, err := io.Copy(writerOnly{w}, src)
+	n += n0
+	return n, err
+}
+
+// noLimit is an effective infinite upper bound for io.LimitedReader
+const noLimit int64 = (1 << 63) - 1
+
+// debugServerConnections controls whether all server connections are wrapped
+// with a verbose logging wrapper.
+const debugServerConnections = false
+
+// Create new connection from rwc.
+func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
+	c = new(conn)
+	c.remoteAddr = rwc.RemoteAddr().String()
+	c.server = srv
+	c.rwc = rwc
+	if debugServerConnections {
+		c.rwc = newLoggingConn("server", c.rwc)
+	}
+	c.sr = liveSwitchReader{r: c.rwc}
+	c.lr = io.LimitReader(&c.sr, noLimit).(*io.LimitedReader)
+	br := newBufioReader(c.lr)
+	bw := newBufioWriterSize(c.rwc, 4<<10)
+	c.buf = bufio.NewReadWriter(br, bw)
+	return c, nil
+}
+
+var (
+	bufioReaderPool   sync.Pool
+	bufioWriter2kPool sync.Pool
+	bufioWriter4kPool sync.Pool
+)
+
+func bufioWriterPool(size int) *sync.Pool {
+	switch size {
+	case 2 << 10:
+		return &bufioWriter2kPool
+	case 4 << 10:
+		return &bufioWriter4kPool
+	}
+	return nil
+}
+
+func newBufioReader(r io.Reader) *bufio.Reader {
+	if v := bufioReaderPool.Get(); v != nil {
+		br := v.(*bufio.Reader)
+		br.Reset(r)
+		return br
+	}
+	return bufio.NewReader(r)
+}
+
+func putBufioReader(br *bufio.Reader) {
+	br.Reset(nil)
+	bufioReaderPool.Put(br)
+}
+
+func newBufioWriterSize(w io.Writer, size int) *bufio.Writer {
+	pool := bufioWriterPool(size)
+	if pool != nil {
+		if v := pool.Get(); v != nil {
+			bw := v.(*bufio.Writer)
+			bw.Reset(w)
+			return bw
+		}
+	}
+	return bufio.NewWriterSize(w, size)
+}
+
+func putBufioWriter(bw *bufio.Writer) {
+	bw.Reset(nil)
+	if pool := bufioWriterPool(bw.Available()); pool != nil {
+		pool.Put(bw)
+	}
+}
+
+// DefaultMaxHeaderBytes is the maximum permitted size of the headers
+// in an HTTP request.
+// This can be overridden by setting Server.MaxHeaderBytes.
+const DefaultMaxHeaderBytes = 1 << 20 // 1 MB
+
+func (srv *Server) maxHeaderBytes() int {
+	if srv.MaxHeaderBytes > 0 {
+		return srv.MaxHeaderBytes
+	}
+	return DefaultMaxHeaderBytes
+}
+
+func (srv *Server) initialLimitedReaderSize() int64 {
+	return int64(srv.maxHeaderBytes()) + 4096 // bufio slop
+}
+
+// wrapper around io.ReaderCloser which on first read, sends an
+// HTTP/1.1 100 Continue header
+type expectContinueReader struct {
+	resp       *response
+	readCloser io.ReadCloser
+	closed     bool
+}
+
+func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
+	if ecr.closed {
+		return 0, ErrBodyReadAfterClose
+	}
+	if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked() {
+		ecr.resp.wroteContinue = true
+		ecr.resp.conn.buf.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
+		ecr.resp.conn.buf.Flush()
+	}
+	return ecr.readCloser.Read(p)
+}
+
+func (ecr *expectContinueReader) Close() error {
+	ecr.closed = true
+	return ecr.readCloser.Close()
+}
+
+// TimeFormat is the time format to use with
+// time.Parse and time.Time.Format when parsing
+// or generating times in HTTP headers.
+// It is like time.RFC1123 but hard codes GMT as the time zone.
+const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
+
+// appendTime is a non-allocating version of []byte(t.UTC().Format(TimeFormat))
+func appendTime(b []byte, t time.Time) []byte {
+	const days = "SunMonTueWedThuFriSat"
+	const months = "JanFebMarAprMayJunJulAugSepOctNovDec"
+
+	t = t.UTC()
+	yy, mm, dd := t.Date()
+	hh, mn, ss := t.Clock()
+	day := days[3*t.Weekday():]
+	mon := months[3*(mm-1):]
+
+	return append(b,
+		day[0], day[1], day[2], ',', ' ',
+		byte('0'+dd/10), byte('0'+dd%10), ' ',
+		mon[0], mon[1], mon[2], ' ',
+		byte('0'+yy/1000), byte('0'+(yy/100)%10), byte('0'+(yy/10)%10), byte('0'+yy%10), ' ',
+		byte('0'+hh/10), byte('0'+hh%10), ':',
+		byte('0'+mn/10), byte('0'+mn%10), ':',
+		byte('0'+ss/10), byte('0'+ss%10), ' ',
+		'G', 'M', 'T')
+}
+
+var errTooLarge = errors.New("http: request too large")
+
+// Read next request from connection.
+func (c *conn) readRequest() (w *response, err error) {
+	if c.hijacked() {
+		return nil, ErrHijacked
+	}
+
+	if d := c.server.ReadTimeout; d != 0 {
+		c.rwc.SetReadDeadline(time.Now().Add(d))
+	}
+	if d := c.server.WriteTimeout; d != 0 {
+		defer func() {
+			c.rwc.SetWriteDeadline(time.Now().Add(d))
+		}()
+	}
+
+	c.lr.N = c.server.initialLimitedReaderSize()
+	var req *Request
+	if req, err = ReadRequest(c.buf.Reader); err != nil {
+		if c.lr.N == 0 {
+			return nil, errTooLarge
+		}
+		return nil, err
+	}
+	c.lr.N = noLimit
+
+	req.RemoteAddr = c.remoteAddr
+	req.TLS = c.tlsState
+
+	w = &response{
+		conn:          c,
+		req:           req,
+		handlerHeader: make(Header),
+		contentLength: -1,
+	}
+	w.cw.res = w
+	w.w = newBufioWriterSize(&w.cw, bufferBeforeChunkingSize)
+	return w, nil
+}
+
+func (w *response) Header() Header {
+	if w.cw.header == nil && w.wroteHeader && !w.cw.wroteHeader {
+		// Accessing the header between logically writing it
+		// and physically writing it means we need to allocate
+		// a clone to snapshot the logically written state.
+		w.cw.header = w.handlerHeader.clone()
+	}
+	w.calledHeader = true
+	return w.handlerHeader
+}
+
+// maxPostHandlerReadBytes is the max number of Request.Body bytes not
+// consumed by a handler that the server will read from the client
+// in order to keep a connection alive.  If there are more bytes than
+// this then the server to be paranoid instead sends a "Connection:
+// close" response.
+//
+// This number is approximately what a typical machine's TCP buffer
+// size is anyway.  (if we have the bytes on the machine, we might as
+// well read them)
+const maxPostHandlerReadBytes = 256 << 10
+
+func (w *response) WriteHeader(code int) {
+	if w.conn.hijacked() {
+		w.conn.server.logf("http: response.WriteHeader on hijacked connection")
+		return
+	}
+	if w.wroteHeader {
+		w.conn.server.logf("http: multiple response.WriteHeader calls")
+		return
+	}
+	w.wroteHeader = true
+	w.status = code
+
+	if w.calledHeader && w.cw.header == nil {
+		w.cw.header = w.handlerHeader.clone()
+	}
+
+	if cl := w.handlerHeader.get("Content-Length"); cl != "" {
+		v, err := strconv.ParseInt(cl, 10, 64)
+		if err == nil && v >= 0 {
+			w.contentLength = v
+		} else {
+			w.conn.server.logf("http: invalid Content-Length of %q", cl)
+			w.handlerHeader.Del("Content-Length")
+		}
+	}
+}
+
+// extraHeader is the set of headers sometimes added by chunkWriter.writeHeader.
+// This type is used to avoid extra allocations from cloning and/or populating
+// the response Header map and all its 1-element slices.
+type extraHeader struct {
+	contentType      string
+	connection       string
+	transferEncoding string
+	date             []byte // written if not nil
+	contentLength    []byte // written if not nil
+}
+
+// Sorted the same as extraHeader.Write's loop.
+var extraHeaderKeys = [][]byte{
+	[]byte("Content-Type"),
+	[]byte("Connection"),
+	[]byte("Transfer-Encoding"),
+}
+
+var (
+	headerContentLength = []byte("Content-Length: ")
+	headerDate          = []byte("Date: ")
+)
+
+// Write writes the headers described in h to w.
+//
+// This method has a value receiver, despite the somewhat large size
+// of h, because it prevents an allocation. The escape analysis isn't
+// smart enough to realize this function doesn't mutate h.
+func (h extraHeader) Write(w *bufio.Writer) {
+	if h.date != nil {
+		w.Write(headerDate)
+		w.Write(h.date)
+		w.Write(crlf)
+	}
+	if h.contentLength != nil {
+		w.Write(headerContentLength)
+		w.Write(h.contentLength)
+		w.Write(crlf)
+	}
+	for i, v := range []string{h.contentType, h.connection, h.transferEncoding} {
+		if v != "" {
+			w.Write(extraHeaderKeys[i])
+			w.Write(colonSpace)
+			w.WriteString(v)
+			w.Write(crlf)
+		}
+	}
+}
+
+// writeHeader finalizes the header sent to the client and writes it
+// to cw.res.conn.buf.
+//
+// p is not written by writeHeader, but is the first chunk of the body
+// that will be written.  It is sniffed for a Content-Type if none is
+// set explicitly.  It's also used to set the Content-Length, if the
+// total body size was small and the handler has already finished
+// running.
+func (cw *chunkWriter) writeHeader(p []byte) {
+	if cw.wroteHeader {
+		return
+	}
+	cw.wroteHeader = true
+
+	w := cw.res
+	keepAlivesEnabled := w.conn.server.doKeepAlives()
+	isHEAD := w.req.Method == "HEAD"
+
+	// header is written out to w.conn.buf below. Depending on the
+	// state of the handler, we either own the map or not. If we
+	// don't own it, the exclude map is created lazily for
+	// WriteSubset to remove headers. The setHeader struct holds
+	// headers we need to add.
+	header := cw.header
+	owned := header != nil
+	if !owned {
+		header = w.handlerHeader
+	}
+	var excludeHeader map[string]bool
+	delHeader := func(key string) {
+		if owned {
+			header.Del(key)
+			return
+		}
+		if _, ok := header[key]; !ok {
+			return
+		}
+		if excludeHeader == nil {
+			excludeHeader = make(map[string]bool)
+		}
+		excludeHeader[key] = true
+	}
+	var setHeader extraHeader
+
+	// If the handler is done but never sent a Content-Length
+	// response header and this is our first (and last) write, set
+	// it, even to zero. This helps HTTP/1.0 clients keep their
+	// "keep-alive" connections alive.
+	// Exceptions: 304/204/1xx responses never get Content-Length, and if
+	// it was a HEAD request, we don't know the difference between
+	// 0 actual bytes and 0 bytes because the handler noticed it
+	// was a HEAD request and chose not to write anything.  So for
+	// HEAD, the handler should either write the Content-Length or
+	// write non-zero bytes.  If it's actually 0 bytes and the
+	// handler never looked at the Request.Method, we just don't
+	// send a Content-Length header.
+	if w.handlerDone && bodyAllowedForStatus(w.status) && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) {
+		w.contentLength = int64(len(p))
+		setHeader.contentLength = strconv.AppendInt(cw.res.clenBuf[:0], int64(len(p)), 10)
+	}
+
+	// If this was an HTTP/1.0 request with keep-alive and we sent a
+	// Content-Length back, we can make this a keep-alive response ...
+	if w.req.wantsHttp10KeepAlive() && keepAlivesEnabled {
+		sentLength := header.get("Content-Length") != ""
+		if sentLength && header.get("Connection") == "keep-alive" {
+			w.closeAfterReply = false
+		}
+	}
+
+	// Check for a explicit (and valid) Content-Length header.
+	hasCL := w.contentLength != -1
+
+	if w.req.wantsHttp10KeepAlive() && (isHEAD || hasCL) {
+		_, connectionHeaderSet := header["Connection"]
+		if !connectionHeaderSet {
+			setHeader.connection = "keep-alive"
+		}
+	} else if !w.req.ProtoAtLeast(1, 1) || w.req.wantsClose() {
+		w.closeAfterReply = true
+	}
+
+	if header.get("Connection") == "close" || !keepAlivesEnabled {
+		w.closeAfterReply = true
+	}
+
+	// Per RFC 2616, we should consume the request body before
+	// replying, if the handler hasn't already done so.  But we
+	// don't want to do an unbounded amount of reading here for
+	// DoS reasons, so we only try up to a threshold.
+	if w.req.ContentLength != 0 && !w.closeAfterReply {
+		ecr, isExpecter := w.req.Body.(*expectContinueReader)
+		if !isExpecter || ecr.resp.wroteContinue {
+			n, _ := io.CopyN(ioutil.Discard, w.req.Body, maxPostHandlerReadBytes+1)
+			if n >= maxPostHandlerReadBytes {
+				w.requestTooLarge()
+				delHeader("Connection")
+				setHeader.connection = "close"
+			} else {
+				w.req.Body.Close()
+			}
+		}
+	}
+
+	code := w.status
+	if bodyAllowedForStatus(code) {
+		// If no content type, apply sniffing algorithm to body.
+		_, haveType := header["Content-Type"]
+		if !haveType {
+			setHeader.contentType = DetectContentType(p)
+		}
+	} else {
+		for _, k := range suppressedHeaders(code) {
+			delHeader(k)
+		}
+	}
+
+	if _, ok := header["Date"]; !ok {
+		setHeader.date = appendTime(cw.res.dateBuf[:0], time.Now())
+	}
+
+	te := header.get("Transfer-Encoding")
+	hasTE := te != ""
+	if hasCL && hasTE && te != "identity" {
+		// TODO: return an error if WriteHeader gets a return parameter
+		// For now just ignore the Content-Length.
+		w.conn.server.logf("http: WriteHeader called with both Transfer-Encoding of %q and a Content-Length of %d",
+			te, w.contentLength)
+		delHeader("Content-Length")
+		hasCL = false
+	}
+
+	if w.req.Method == "HEAD" || !bodyAllowedForStatus(code) {
+		// do nothing
+	} else if code == StatusNoContent {
+		delHeader("Transfer-Encoding")
+	} else if hasCL {
+		delHeader("Transfer-Encoding")
+	} else if w.req.ProtoAtLeast(1, 1) {
+		// HTTP/1.1 or greater: use chunked transfer encoding
+		// to avoid closing the connection at EOF.
+		// TODO: this blows away any custom or stacked Transfer-Encoding they
+		// might have set.  Deal with that as need arises once we have a valid
+		// use case.
+		cw.chunking = true
+		setHeader.transferEncoding = "chunked"
+	} else {
+		// HTTP version < 1.1: cannot do chunked transfer
+		// encoding and we don't know the Content-Length so
+		// signal EOF by closing connection.
+		w.closeAfterReply = true
+		delHeader("Transfer-Encoding") // in case already set
+	}
+
+	// Cannot use Content-Length with non-identity Transfer-Encoding.
+	if cw.chunking {
+		delHeader("Content-Length")
+	}
+	if !w.req.ProtoAtLeast(1, 0) {
+		return
+	}
+
+	if w.closeAfterReply && (!keepAlivesEnabled || !hasToken(cw.header.get("Connection"), "close")) {
+		delHeader("Connection")
+		if w.req.ProtoAtLeast(1, 1) {
+			setHeader.connection = "close"
+		}
+	}
+
+	w.conn.buf.WriteString(statusLine(w.req, code))
+	cw.header.WriteSubset(w.conn.buf, excludeHeader)
+	setHeader.Write(w.conn.buf.Writer)
+	w.conn.buf.Write(crlf)
+}
+
+// statusLines is a cache of Status-Line strings, keyed by code (for
+// HTTP/1.1) or negative code (for HTTP/1.0). This is faster than a
+// map keyed by struct of two fields. This map's max size is bounded
+// by 2*len(statusText), two protocol types for each known official
+// status code in the statusText map.
+var (
+	statusMu    sync.RWMutex
+	statusLines = make(map[int]string)
+)
+
+// statusLine returns a response Status-Line (RFC 2616 Section 6.1)
+// for the given request and response status code.
+func statusLine(req *Request, code int) string {
+	// Fast path:
+	key := code
+	proto11 := req.ProtoAtLeast(1, 1)
+	if !proto11 {
+		key = -key
+	}
+	statusMu.RLock()
+	line, ok := statusLines[key]
+	statusMu.RUnlock()
+	if ok {
+		return line
+	}
+
+	// Slow path:
+	proto := "HTTP/1.0"
+	if proto11 {
+		proto = "HTTP/1.1"
+	}
+	codestring := strconv.Itoa(code)
+	text, ok := statusText[code]
+	if !ok {
+		text = "status code " + codestring
+	}
+	line = proto + " " + codestring + " " + text + "\r\n"
+	if ok {
+		statusMu.Lock()
+		defer statusMu.Unlock()
+		statusLines[key] = line
+	}
+	return line
+}
+
+// bodyAllowed returns true if a Write is allowed for this response type.
+// It's illegal to call this before the header has been flushed.
+func (w *response) bodyAllowed() bool {
+	if !w.wroteHeader {
+		panic("")
+	}
+	return bodyAllowedForStatus(w.status)
+}
+
+// The Life Of A Write is like this:
+//
+// Handler starts. No header has been sent. The handler can either
+// write a header, or just start writing.  Writing before sending a header
+// sends an implicitly empty 200 OK header.
+//
+// If the handler didn't declare a Content-Length up front, we either
+// go into chunking mode or, if the handler finishes running before
+// the chunking buffer size, we compute a Content-Length and send that
+// in the header instead.
+//
+// Likewise, if the handler didn't set a Content-Type, we sniff that
+// from the initial chunk of output.
+//
+// The Writers are wired together like:
+//
+// 1. *response (the ResponseWriter) ->
+// 2. (*response).w, a *bufio.Writer of bufferBeforeChunkingSize bytes
+// 3. chunkWriter.Writer (whose writeHeader finalizes Content-Length/Type)
+//    and which writes the chunk headers, if needed.
+// 4. conn.buf, a bufio.Writer of default (4kB) bytes
+// 5. the rwc, the net.Conn.
+//
+// TODO(bradfitz): short-circuit some of the buffering when the
+// initial header contains both a Content-Type and Content-Length.
+// Also short-circuit in (1) when the header's been sent and not in
+// chunking mode, writing directly to (4) instead, if (2) has no
+// buffered data.  More generally, we could short-circuit from (1) to
+// (3) even in chunking mode if the write size from (1) is over some
+// threshold and nothing is in (2).  The answer might be mostly making
+// bufferBeforeChunkingSize smaller and having bufio's fast-paths deal
+// with this instead.
+func (w *response) Write(data []byte) (n int, err error) {
+	return w.write(len(data), data, "")
+}
+
+func (w *response) WriteString(data string) (n int, err error) {
+	return w.write(len(data), nil, data)
+}
+
+// either dataB or dataS is non-zero.
+func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {
+	if w.conn.hijacked() {
+		w.conn.server.logf("http: response.Write on hijacked connection")
+		return 0, ErrHijacked
+	}
+	if !w.wroteHeader {
+		w.WriteHeader(StatusOK)
+	}
+	if lenData == 0 {
+		return 0, nil
+	}
+	if !w.bodyAllowed() {
+		return 0, ErrBodyNotAllowed
+	}
+
+	w.written += int64(lenData) // ignoring errors, for errorKludge
+	if w.contentLength != -1 && w.written > w.contentLength {
+		return 0, ErrContentLength
+	}
+	if dataB != nil {
+		return w.w.Write(dataB)
+	} else {
+		return w.w.WriteString(dataS)
+	}
+}
+
+func (w *response) finishRequest() {
+	w.handlerDone = true
+
+	if !w.wroteHeader {
+		w.WriteHeader(StatusOK)
+	}
+
+	w.w.Flush()
+	putBufioWriter(w.w)
+	w.cw.close()
+	w.conn.buf.Flush()
+
+	// Close the body (regardless of w.closeAfterReply) so we can
+	// re-use its bufio.Reader later safely.
+	w.req.Body.Close()
+
+	if w.req.MultipartForm != nil {
+		w.req.MultipartForm.RemoveAll()
+	}
+
+	if w.req.Method != "HEAD" && w.contentLength != -1 && w.bodyAllowed() && w.contentLength != w.written {
+		// Did not write enough. Avoid getting out of sync.
+		w.closeAfterReply = true
+	}
+}
+
+func (w *response) Flush() {
+	if !w.wroteHeader {
+		w.WriteHeader(StatusOK)
+	}
+	w.w.Flush()
+	w.cw.flush()
+}
+
+func (c *conn) finalFlush() {
+	if c.buf != nil {
+		c.buf.Flush()
+
+		// Steal the bufio.Reader (~4KB worth of memory) and its associated
+		// reader for a future connection.
+		putBufioReader(c.buf.Reader)
+
+		// Steal the bufio.Writer (~4KB worth of memory) and its associated
+		// writer for a future connection.
+		putBufioWriter(c.buf.Writer)
+
+		c.buf = nil
+	}
+}
+
+// Close the connection.
+func (c *conn) close() {
+	c.finalFlush()
+	if c.rwc != nil {
+		c.rwc.Close()
+		c.rwc = nil
+	}
+}
+
+// rstAvoidanceDelay is the amount of time we sleep after closing the
+// write side of a TCP connection before closing the entire socket.
+// By sleeping, we increase the chances that the client sees our FIN
+// and processes its final data before they process the subsequent RST
+// from closing a connection with known unread data.
+// This RST seems to occur mostly on BSD systems. (And Windows?)
+// This timeout is somewhat arbitrary (~latency around the planet).
+const rstAvoidanceDelay = 500 * time.Millisecond
+
+// closeWrite flushes any outstanding data and sends a FIN packet (if
+// client is connected via TCP), signalling that we're done.  We then
+// pause for a bit, hoping the client processes it before `any
+// subsequent RST.
+//
+// See http://golang.org/issue/3595
+func (c *conn) closeWriteAndWait() {
+	c.finalFlush()
+	if tcp, ok := c.rwc.(*net.TCPConn); ok {
+		tcp.CloseWrite()
+	}
+	time.Sleep(rstAvoidanceDelay)
+}
+
+// validNPN reports whether the proto is not a blacklisted Next
+// Protocol Negotiation protocol.  Empty and built-in protocol types
+// are blacklisted and can't be overridden with alternate
+// implementations.
+func validNPN(proto string) bool {
+	switch proto {
+	case "", "http/1.1", "http/1.0":
+		return false
+	}
+	return true
+}
+
+func (c *conn) setState(nc net.Conn, state ConnState) {
+	if hook := c.server.ConnState; hook != nil {
+		hook(nc, state)
+	}
+}
+
+// Serve a new connection.
+func (c *conn) serve() {
+	origConn := c.rwc // copy it before it's set nil on Close or Hijack
+	defer func() {
+		if err := recover(); err != nil {
+			const size = 64 << 10
+			buf := make([]byte, size)
+			buf = buf[:runtime.Stack(buf, false)]
+			c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
+		}
+		if !c.hijacked() {
+			c.close()
+			c.setState(origConn, StateClosed)
+		}
+	}()
+
+	if tlsConn, ok := c.rwc.(*tls.Conn); ok {
+		if d := c.server.ReadTimeout; d != 0 {
+			c.rwc.SetReadDeadline(time.Now().Add(d))
+		}
+		if d := c.server.WriteTimeout; d != 0 {
+			c.rwc.SetWriteDeadline(time.Now().Add(d))
+		}
+		if err := tlsConn.Handshake(); err != nil {
+			c.server.logf("http: TLS handshake error from %s: %v", c.rwc.RemoteAddr(), err)
+			return
+		}
+		c.tlsState = new(tls.ConnectionState)
+		*c.tlsState = tlsConn.ConnectionState()
+		if proto := c.tlsState.NegotiatedProtocol; validNPN(proto) {
+			if fn := c.server.TLSNextProto[proto]; fn != nil {
+				h := initNPNRequest{tlsConn, serverHandler{c.server}}
+				fn(c.server, tlsConn, h)
+			}
+			return
+		}
+	}
+
+	for {
+		w, err := c.readRequest()
+		if c.lr.N != c.server.initialLimitedReaderSize() {
+			// If we read any bytes off the wire, we're active.
+			c.setState(c.rwc, StateActive)
+		}
+		if err != nil {
+			if err == errTooLarge {
+				// Their HTTP client may or may not be
+				// able to read this if we're
+				// responding to them and hanging up
+				// while they're still writing their
+				// request.  Undefined behavior.
+				io.WriteString(c.rwc, "HTTP/1.1 413 Request Entity Too Large\r\n\r\n")
+				c.closeWriteAndWait()
+				break
+			} else if err == io.EOF {
+				break // Don't reply
+			} else if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
+				break // Don't reply
+			}
+			io.WriteString(c.rwc, "HTTP/1.1 400 Bad Request\r\n\r\n")
+			break
+		}
+
+		// Expect 100 Continue support
+		req := w.req
+		if req.expectsContinue() {
+			if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
+				// Wrap the Body reader with one that replies on the connection
+				req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
+			}
+			req.Header.Del("Expect")
+		} else if req.Header.get("Expect") != "" {
+			w.sendExpectationFailed()
+			break
+		}
+
+		// HTTP cannot have multiple simultaneous active requests.[*]
+		// Until the server replies to this request, it can't read another,
+		// so we might as well run the handler in this goroutine.
+		// [*] Not strictly true: HTTP pipelining.  We could let them all process
+		// in parallel even if their responses need to be serialized.
+		serverHandler{c.server}.ServeHTTP(w, w.req)
+		if c.hijacked() {
+			return
+		}
+		w.finishRequest()
+		if w.closeAfterReply {
+			if w.requestBodyLimitHit {
+				c.closeWriteAndWait()
+			}
+			break
+		}
+		c.setState(c.rwc, StateIdle)
+	}
+}
+
+func (w *response) sendExpectationFailed() {
+	// TODO(bradfitz): let ServeHTTP handlers handle
+	// requests with non-standard expectation[s]? Seems
+	// theoretical at best, and doesn't fit into the
+	// current ServeHTTP model anyway.  We'd need to
+	// make the ResponseWriter an optional
+	// "ExpectReplier" interface or something.
+	//
+	// For now we'll just obey RFC 2616 14.20 which says
+	// "If a server receives a request containing an
+	// Expect field that includes an expectation-
+	// extension that it does not support, it MUST
+	// respond with a 417 (Expectation Failed) status."
+	w.Header().Set("Connection", "close")
+	w.WriteHeader(StatusExpectationFailed)
+	w.finishRequest()
+}
+
+// Hijack implements the Hijacker.Hijack method. Our response is both a ResponseWriter
+// and a Hijacker.
+func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
+	if w.wroteHeader {
+		w.cw.flush()
+	}
+	// Release the bufioWriter that writes to the chunk writer, it is not
+	// used after a connection has been hijacked.
+	rwc, buf, err = w.conn.hijack()
+	if err == nil {
+		putBufioWriter(w.w)
+		w.w = nil
+	}
+	return rwc, buf, err
+}
+
+func (w *response) CloseNotify() <-chan bool {
+	return w.conn.closeNotify()
+}
+
+// The HandlerFunc type is an adapter to allow the use of
+// ordinary functions as HTTP handlers.  If f is a function
+// with the appropriate signature, HandlerFunc(f) is a
+// Handler object that calls f.
+type HandlerFunc func(ResponseWriter, *Request)
+
+// ServeHTTP calls f(w, r).
+func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
+	f(w, r)
+}
+
+// Helper handlers
+
+// Error replies to the request with the specified error message and HTTP code.
+// The error message should be plain text.
+func Error(w ResponseWriter, error string, code int) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	w.WriteHeader(code)
+	fmt.Fprintln(w, error)
+}
+
+// NotFound replies to the request with an HTTP 404 not found error.
+func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }
+
+// NotFoundHandler returns a simple request handler
+// that replies to each request with a ``404 page not found'' reply.
+func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
+
+// StripPrefix returns a handler that serves HTTP requests
+// by removing the given prefix from the request URL's Path
+// and invoking the handler h. StripPrefix handles a
+// request for a path that doesn't begin with prefix by
+// replying with an HTTP 404 not found error.
+func StripPrefix(prefix string, h Handler) Handler {
+	if prefix == "" {
+		return h
+	}
+	return HandlerFunc(func(w ResponseWriter, r *Request) {
+		if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {
+			r.URL.Path = p
+			h.ServeHTTP(w, r)
+		} else {
+			NotFound(w, r)
+		}
+	})
+}
+
+// Redirect replies to the request with a redirect to url,
+// which may be a path relative to the request path.
+func Redirect(w ResponseWriter, r *Request, urlStr string, code int) {
+	if u, err := url.Parse(urlStr); err == nil {
+		// If url was relative, make absolute by
+		// combining with request path.
+		// The browser would probably do this for us,
+		// but doing it ourselves is more reliable.
+
+		// NOTE(rsc): RFC 2616 says that the Location
+		// line must be an absolute URI, like
+		// "http://www.google.com/redirect/",
+		// not a path like "/redirect/".
+		// Unfortunately, we don't know what to
+		// put in the host name section to get the
+		// client to connect to us again, so we can't
+		// know the right absolute URI to send back.
+		// Because of this problem, no one pays attention
+		// to the RFC; they all send back just a new path.
+		// So do we.
+		oldpath := r.URL.Path
+		if oldpath == "" { // should not happen, but avoid a crash if it does
+			oldpath = "/"
+		}
+		if u.Scheme == "" {
+			// no leading http://server
+			if urlStr == "" || urlStr[0] != '/' {
+				// make relative path absolute
+				olddir, _ := path.Split(oldpath)
+				urlStr = olddir + urlStr
+			}
+
+			var query string
+			if i := strings.Index(urlStr, "?"); i != -1 {
+				urlStr, query = urlStr[:i], urlStr[i:]
+			}
+
+			// clean up but preserve trailing slash
+			trailing := strings.HasSuffix(urlStr, "/")
+			urlStr = path.Clean(urlStr)
+			if trailing && !strings.HasSuffix(urlStr, "/") {
+				urlStr += "/"
+			}
+			urlStr += query
+		}
+	}
+
+	w.Header().Set("Location", urlStr)
+	w.WriteHeader(code)
+
+	// RFC2616 recommends that a short note "SHOULD" be included in the
+	// response because older user agents may not understand 301/307.
+	// Shouldn't send the response for POST or HEAD; that leaves GET.
+	if r.Method == "GET" {
+		note := "<a href=\"" + htmlEscape(urlStr) + "\">" + statusText[code] + "</a>.\n"
+		fmt.Fprintln(w, note)
+	}
+}
+
+var htmlReplacer = strings.NewReplacer(
+	"&", "&amp;",
+	"<", "&lt;",
+	">", "&gt;",
+	// "&#34;" is shorter than "&quot;".
+	`"`, "&#34;",
+	// "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
+	"'", "&#39;",
+)
+
+func htmlEscape(s string) string {
+	return htmlReplacer.Replace(s)
+}
+
+// Redirect to a fixed URL
+type redirectHandler struct {
+	url  string
+	code int
+}
+
+func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	Redirect(w, r, rh.url, rh.code)
+}
+
+// RedirectHandler returns a request handler that redirects
+// each request it receives to the given url using the given
+// status code.
+func RedirectHandler(url string, code int) Handler {
+	return &redirectHandler{url, code}
+}
+
+// ServeMux is an HTTP request multiplexer.
+// It matches the URL of each incoming request against a list of registered
+// patterns and calls the handler for the pattern that
+// most closely matches the URL.
+//
+// Patterns name fixed, rooted paths, like "/favicon.ico",
+// or rooted subtrees, like "/images/" (note the trailing slash).
+// Longer patterns take precedence over shorter ones, so that
+// if there are handlers registered for both "/images/"
+// and "/images/thumbnails/", the latter handler will be
+// called for paths beginning "/images/thumbnails/" and the
+// former will receive requests for any other paths in the
+// "/images/" subtree.
+//
+// Note that since a pattern ending in a slash names a rooted subtree,
+// the pattern "/" matches all paths not matched by other registered
+// patterns, not just the URL with Path == "/".
+//
+// Patterns may optionally begin with a host name, restricting matches to
+// URLs on that host only.  Host-specific patterns take precedence over
+// general patterns, so that a handler might register for the two patterns
+// "/codesearch" and "codesearch.google.com/" without also taking over
+// requests for "http://www.google.com/".
+//
+// ServeMux also takes care of sanitizing the URL request path,
+// redirecting any request containing . or .. elements to an
+// equivalent .- and ..-free URL.
+type ServeMux struct {
+	mu    sync.RWMutex
+	m     map[string]muxEntry
+	hosts bool // whether any patterns contain hostnames
+}
+
+type muxEntry struct {
+	explicit bool
+	h        Handler
+	pattern  string
+}
+
+// NewServeMux allocates and returns a new ServeMux.
+func NewServeMux() *ServeMux { return &ServeMux{m: make(map[string]muxEntry)} }
+
+// DefaultServeMux is the default ServeMux used by Serve.
+var DefaultServeMux = NewServeMux()
+
+// Does path match pattern?
+func pathMatch(pattern, path string) bool {
+	if len(pattern) == 0 {
+		// should not happen
+		return false
+	}
+	n := len(pattern)
+	if pattern[n-1] != '/' {
+		return pattern == path
+	}
+	return len(path) >= n && path[0:n] == pattern
+}
+
+// Return the canonical path for p, eliminating . and .. elements.
+func cleanPath(p string) string {
+	if p == "" {
+		return "/"
+	}
+	if p[0] != '/' {
+		p = "/" + p
+	}
+	np := path.Clean(p)
+	// path.Clean removes trailing slash except for root;
+	// put the trailing slash back if necessary.
+	if p[len(p)-1] == '/' && np != "/" {
+		np += "/"
+	}
+	return np
+}
+
+// Find a handler on a handler map given a path string
+// Most-specific (longest) pattern wins
+func (mux *ServeMux) match(path string) (h Handler, pattern string) {
+	var n = 0
+	for k, v := range mux.m {
+		if !pathMatch(k, path) {
+			continue
+		}
+		if h == nil || len(k) > n {
+			n = len(k)
+			h = v.h
+			pattern = v.pattern
+		}
+	}
+	return
+}
+
+// Handler returns the handler to use for the given request,
+// consulting r.Method, r.Host, and r.URL.Path. It always returns
+// a non-nil handler. If the path is not in its canonical form, the
+// handler will be an internally-generated handler that redirects
+// to the canonical path.
+//
+// Handler also returns the registered pattern that matches the
+// request or, in the case of internally-generated redirects,
+// the pattern that will match after following the redirect.
+//
+// If there is no registered handler that applies to the request,
+// Handler returns a ``page not found'' handler and an empty pattern.
+func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
+	if r.Method != "CONNECT" {
+		if p := cleanPath(r.URL.Path); p != r.URL.Path {
+			_, pattern = mux.handler(r.Host, p)
+			url := *r.URL
+			url.Path = p
+			return RedirectHandler(url.String(), StatusMovedPermanently), pattern
+		}
+	}
+
+	return mux.handler(r.Host, r.URL.Path)
+}
+
+// handler is the main implementation of Handler.
+// The path is known to be in canonical form, except for CONNECT methods.
+func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
+	mux.mu.RLock()
+	defer mux.mu.RUnlock()
+
+	// Host-specific pattern takes precedence over generic ones
+	if mux.hosts {
+		h, pattern = mux.match(host + path)
+	}
+	if h == nil {
+		h, pattern = mux.match(path)
+	}
+	if h == nil {
+		h, pattern = NotFoundHandler(), ""
+	}
+	return
+}
+
+// ServeHTTP dispatches the request to the handler whose
+// pattern most closely matches the request URL.
+func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
+	if r.RequestURI == "*" {
+		if r.ProtoAtLeast(1, 1) {
+			w.Header().Set("Connection", "close")
+		}
+		w.WriteHeader(StatusBadRequest)
+		return
+	}
+	h, _ := mux.Handler(r)
+	h.ServeHTTP(w, r)
+}
+
+// Handle registers the handler for the given pattern.
+// If a handler already exists for pattern, Handle panics.
+func (mux *ServeMux) Handle(pattern string, handler Handler) {
+	mux.mu.Lock()
+	defer mux.mu.Unlock()
+
+	if pattern == "" {
+		panic("http: invalid pattern " + pattern)
+	}
+	if handler == nil {
+		panic("http: nil handler")
+	}
+	if mux.m[pattern].explicit {
+		panic("http: multiple registrations for " + pattern)
+	}
+
+	mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}
+
+	if pattern[0] != '/' {
+		mux.hosts = true
+	}
+
+	// Helpful behavior:
+	// If pattern is /tree/, insert an implicit permanent redirect for /tree.
+	// It can be overridden by an explicit registration.
+	n := len(pattern)
+	if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {
+		// If pattern contains a host name, strip it and use remaining
+		// path for redirect.
+		path := pattern
+		if pattern[0] != '/' {
+			// In pattern, at least the last character is a '/', so
+			// strings.Index can't be -1.
+			path = pattern[strings.Index(pattern, "/"):]
+		}
+		mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(path, StatusMovedPermanently), pattern: pattern}
+	}
+}
+
+// HandleFunc registers the handler function for the given pattern.
+func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
+	mux.Handle(pattern, HandlerFunc(handler))
+}
+
+// Handle registers the handler for the given pattern
+// in the DefaultServeMux.
+// The documentation for ServeMux explains how patterns are matched.
+func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
+
+// HandleFunc registers the handler function for the given pattern
+// in the DefaultServeMux.
+// The documentation for ServeMux explains how patterns are matched.
+func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
+	DefaultServeMux.HandleFunc(pattern, handler)
+}
+
+// Serve accepts incoming HTTP connections on the listener l,
+// creating a new service goroutine for each.  The service goroutines
+// read requests and then call handler to reply to them.
+// Handler is typically nil, in which case the DefaultServeMux is used.
+func Serve(l net.Listener, handler Handler) error {
+	srv := &Server{Handler: handler}
+	return srv.Serve(l)
+}
+
+// A Server defines parameters for running an HTTP server.
+// The zero value for Server is a valid configuration.
+type Server struct {
+	Addr           string        // TCP address to listen on, ":http" if empty
+	Handler        Handler       // handler to invoke, http.DefaultServeMux if nil
+	ReadTimeout    time.Duration // maximum duration before timing out read of the request
+	WriteTimeout   time.Duration // maximum duration before timing out write of the response
+	MaxHeaderBytes int           // maximum size of request headers, DefaultMaxHeaderBytes if 0
+	TLSConfig      *tls.Config   // optional TLS config, used by ListenAndServeTLS
+
+	// TLSNextProto optionally specifies a function to take over
+	// ownership of the provided TLS connection when an NPN
+	// protocol upgrade has occurred.  The map key is the protocol
+	// name negotiated. The Handler argument should be used to
+	// handle HTTP requests and will initialize the Request's TLS
+	// and RemoteAddr if not already set.  The connection is
+	// automatically closed when the function returns.
+	TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
+
+	// ConnState specifies an optional callback function that is
+	// called when a client connection changes state. See the
+	// ConnState type and associated constants for details.
+	ConnState func(net.Conn, ConnState)
+
+	// ErrorLog specifies an optional logger for errors accepting
+	// connections and unexpected behavior from handlers.
+	// If nil, logging goes to os.Stderr via the log package's
+	// standard logger.
+	ErrorLog *log.Logger
+
+	disableKeepAlives int32 // accessed atomically.
+}
+
+// A ConnState represents the state of a client connection to a server.
+// It's used by the optional Server.ConnState hook.
+type ConnState int
+
+const (
+	// StateNew represents a new connection that is expected to
+	// send a request immediately. Connections begin at this
+	// state and then transition to either StateActive or
+	// StateClosed.
+	StateNew ConnState = iota
+
+	// StateActive represents a connection that has read 1 or more
+	// bytes of a request. The Server.ConnState hook for
+	// StateActive fires before the request has entered a handler
+	// and doesn't fire again until the request has been
+	// handled. After the request is handled, the state
+	// transitions to StateClosed, StateHijacked, or StateIdle.
+	StateActive
+
+	// StateIdle represents a connection that has finished
+	// handling a request and is in the keep-alive state, waiting
+	// for a new request. Connections transition from StateIdle
+	// to either StateActive or StateClosed.
+	StateIdle
+
+	// StateHijacked represents a hijacked connection.
+	// This is a terminal state. It does not transition to StateClosed.
+	StateHijacked
+
+	// StateClosed represents a closed connection.
+	// This is a terminal state. Hijacked connections do not
+	// transition to StateClosed.
+	StateClosed
+)
+
+var stateName = map[ConnState]string{
+	StateNew:      "new",
+	StateActive:   "active",
+	StateIdle:     "idle",
+	StateHijacked: "hijacked",
+	StateClosed:   "closed",
+}
+
+func (c ConnState) String() string {
+	return stateName[c]
+}
+
+// serverHandler delegates to either the server's Handler or
+// DefaultServeMux and also handles "OPTIONS *" requests.
+type serverHandler struct {
+	srv *Server
+}
+
+func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
+	handler := sh.srv.Handler
+	if handler == nil {
+		handler = DefaultServeMux
+	}
+	if req.RequestURI == "*" && req.Method == "OPTIONS" {
+		handler = globalOptionsHandler{}
+	}
+	handler.ServeHTTP(rw, req)
+}
+
+// ListenAndServe listens on the TCP network address srv.Addr and then
+// calls Serve to handle requests on incoming connections.  If
+// srv.Addr is blank, ":http" is used.
+func (srv *Server) ListenAndServe() error {
+	addr := srv.Addr
+	if addr == "" {
+		addr = ":http"
+	}
+	ln, err := net.Listen("tcp", addr)
+	if err != nil {
+		return err
+	}
+	return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
+}
+
+// Serve accepts incoming connections on the Listener l, creating a
+// new service goroutine for each.  The service goroutines read requests and
+// then call srv.Handler to reply to them.
+func (srv *Server) Serve(l net.Listener) error {
+	defer l.Close()
+	var tempDelay time.Duration // how long to sleep on accept failure
+	for {
+		rw, e := l.Accept()
+		if e != nil {
+			if ne, ok := e.(net.Error); ok && ne.Temporary() {
+				if tempDelay == 0 {
+					tempDelay = 5 * time.Millisecond
+				} else {
+					tempDelay *= 2
+				}
+				if max := 1 * time.Second; tempDelay > max {
+					tempDelay = max
+				}
+				srv.logf("http: Accept error: %v; retrying in %v", e, tempDelay)
+				time.Sleep(tempDelay)
+				continue
+			}
+			return e
+		}
+		tempDelay = 0
+		c, err := srv.newConn(rw)
+		if err != nil {
+			continue
+		}
+		c.setState(c.rwc, StateNew) // before Serve can return
+		go c.serve()
+	}
+}
+
+func (s *Server) doKeepAlives() bool {
+	return atomic.LoadInt32(&s.disableKeepAlives) == 0
+}
+
+// SetKeepAlivesEnabled controls whether HTTP keep-alives are enabled.
+// By default, keep-alives are always enabled. Only very
+// resource-constrained environments or servers in the process of
+// shutting down should disable them.
+func (s *Server) SetKeepAlivesEnabled(v bool) {
+	if v {
+		atomic.StoreInt32(&s.disableKeepAlives, 0)
+	} else {
+		atomic.StoreInt32(&s.disableKeepAlives, 1)
+	}
+}
+
+func (s *Server) logf(format string, args ...interface{}) {
+	if s.ErrorLog != nil {
+		s.ErrorLog.Printf(format, args...)
+	} else {
+		log.Printf(format, args...)
+	}
+}
+
+// ListenAndServe listens on the TCP network address addr
+// and then calls Serve with handler to handle requests
+// on incoming connections.  Handler is typically nil,
+// in which case the DefaultServeMux is used.
+//
+// A trivial example server is:
+//
+//	package main
+//
+//	import (
+//		"io"
+//		"net/http"
+//		"log"
+//	)
+//
+//	// hello world, the web server
+//	func HelloServer(w http.ResponseWriter, req *http.Request) {
+//		io.WriteString(w, "hello, world!\n")
+//	}
+//
+//	func main() {
+//		http.HandleFunc("/hello", HelloServer)
+//		err := http.ListenAndServe(":12345", nil)
+//		if err != nil {
+//			log.Fatal("ListenAndServe: ", err)
+//		}
+//	}
+func ListenAndServe(addr string, handler Handler) error {
+	server := &Server{Addr: addr, Handler: handler}
+	return server.ListenAndServe()
+}
+
+// ListenAndServeTLS acts identically to ListenAndServe, except that it
+// expects HTTPS connections. Additionally, files containing a certificate and
+// matching private key for the server must be provided. If the certificate
+// is signed by a certificate authority, the certFile should be the concatenation
+// of the server's certificate followed by the CA's certificate.
+//
+// A trivial example server is:
+//
+//	import (
+//		"log"
+//		"net/http"
+//	)
+//
+//	func handler(w http.ResponseWriter, req *http.Request) {
+//		w.Header().Set("Content-Type", "text/plain")
+//		w.Write([]byte("This is an example server.\n"))
+//	}
+//
+//	func main() {
+//		http.HandleFunc("/", handler)
+//		log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
+//		err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
+//		if err != nil {
+//			log.Fatal(err)
+//		}
+//	}
+//
+// One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
+func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error {
+	server := &Server{Addr: addr, Handler: handler}
+	return server.ListenAndServeTLS(certFile, keyFile)
+}
+
+// ListenAndServeTLS listens on the TCP network address srv.Addr and
+// then calls Serve to handle requests on incoming TLS connections.
+//
+// Filenames containing a certificate and matching private key for
+// the server must be provided. If the certificate is signed by a
+// certificate authority, the certFile should be the concatenation
+// of the server's certificate followed by the CA's certificate.
+//
+// If srv.Addr is blank, ":https" is used.
+func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
+	addr := srv.Addr
+	if addr == "" {
+		addr = ":https"
+	}
+	config := &tls.Config{}
+	if srv.TLSConfig != nil {
+		*config = *srv.TLSConfig
+	}
+	if config.NextProtos == nil {
+		config.NextProtos = []string{"http/1.1"}
+	}
+
+	var err error
+	config.Certificates = make([]tls.Certificate, 1)
+	config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
+	if err != nil {
+		return err
+	}
+
+	ln, err := net.Listen("tcp", addr)
+	if err != nil {
+		return err
+	}
+
+	tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
+	return srv.Serve(tlsListener)
+}
+
+// TimeoutHandler returns a Handler that runs h with the given time limit.
+//
+// The new Handler calls h.ServeHTTP to handle each request, but if a
+// call runs for longer than its time limit, the handler responds with
+// a 503 Service Unavailable error and the given message in its body.
+// (If msg is empty, a suitable default message will be sent.)
+// After such a timeout, writes by h to its ResponseWriter will return
+// ErrHandlerTimeout.
+func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler {
+	f := func() <-chan time.Time {
+		return time.After(dt)
+	}
+	return &timeoutHandler{h, f, msg}
+}
+
+// ErrHandlerTimeout is returned on ResponseWriter Write calls
+// in handlers which have timed out.
+var ErrHandlerTimeout = errors.New("http: Handler timeout")
+
+type timeoutHandler struct {
+	handler Handler
+	timeout func() <-chan time.Time // returns channel producing a timeout
+	body    string
+}
+
+func (h *timeoutHandler) errorBody() string {
+	if h.body != "" {
+		return h.body
+	}
+	return "<html><head><title>Timeout</title></head><body><h1>Timeout</h1></body></html>"
+}
+
+func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	done := make(chan bool, 1)
+	tw := &timeoutWriter{w: w}
+	go func() {
+		h.handler.ServeHTTP(tw, r)
+		done <- true
+	}()
+	select {
+	case <-done:
+		return
+	case <-h.timeout():
+		tw.mu.Lock()
+		defer tw.mu.Unlock()
+		if !tw.wroteHeader {
+			tw.w.WriteHeader(StatusServiceUnavailable)
+			tw.w.Write([]byte(h.errorBody()))
+		}
+		tw.timedOut = true
+	}
+}
+
+type timeoutWriter struct {
+	w ResponseWriter
+
+	mu          sync.Mutex
+	timedOut    bool
+	wroteHeader bool
+}
+
+func (tw *timeoutWriter) Header() Header {
+	return tw.w.Header()
+}
+
+func (tw *timeoutWriter) Write(p []byte) (int, error) {
+	tw.mu.Lock()
+	timedOut := tw.timedOut
+	tw.mu.Unlock()
+	if timedOut {
+		return 0, ErrHandlerTimeout
+	}
+	return tw.w.Write(p)
+}
+
+func (tw *timeoutWriter) WriteHeader(code int) {
+	tw.mu.Lock()
+	if tw.timedOut || tw.wroteHeader {
+		tw.mu.Unlock()
+		return
+	}
+	tw.wroteHeader = true
+	tw.mu.Unlock()
+	tw.w.WriteHeader(code)
+}
+
+// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
+// connections. It's used by ListenAndServe and ListenAndServeTLS so
+// dead TCP connections (e.g. closing laptop mid-download) eventually
+// go away.
+type tcpKeepAliveListener struct {
+	*net.TCPListener
+}
+
+func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
+	tc, err := ln.AcceptTCP()
+	if err != nil {
+		return
+	}
+	tc.SetKeepAlive(true)
+	tc.SetKeepAlivePeriod(3 * time.Minute)
+	return tc, nil
+}
+
+// globalOptionsHandler responds to "OPTIONS *" requests.
+type globalOptionsHandler struct{}
+
+func (globalOptionsHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	w.Header().Set("Content-Length", "0")
+	if r.ContentLength != 0 {
+		// Read up to 4KB of OPTIONS body (as mentioned in the
+		// spec as being reserved for future use), but anything
+		// over that is considered a waste of server resources
+		// (or an attack) and we abort and close the connection,
+		// courtesy of MaxBytesReader's EOF behavior.
+		mb := MaxBytesReader(w, r.Body, 4<<10)
+		io.Copy(ioutil.Discard, mb)
+	}
+}
+
+type eofReaderWithWriteTo struct{}
+
+func (eofReaderWithWriteTo) WriteTo(io.Writer) (int64, error) { return 0, nil }
+func (eofReaderWithWriteTo) Read([]byte) (int, error)         { return 0, io.EOF }
+
+// eofReader is a non-nil io.ReadCloser that always returns EOF.
+// It has a WriteTo method so io.Copy won't need a buffer.
+var eofReader = &struct {
+	eofReaderWithWriteTo
+	io.Closer
+}{
+	eofReaderWithWriteTo{},
+	ioutil.NopCloser(nil),
+}
+
+// Verify that an io.Copy from an eofReader won't require a buffer.
+var _ io.WriterTo = eofReader
+
+// initNPNRequest is an HTTP handler that initializes certain
+// uninitialized fields in its *Request. Such partially-initialized
+// Requests come from NPN protocol handlers.
+type initNPNRequest struct {
+	c *tls.Conn
+	h serverHandler
+}
+
+func (h initNPNRequest) ServeHTTP(rw ResponseWriter, req *Request) {
+	if req.TLS == nil {
+		req.TLS = &tls.ConnectionState{}
+		*req.TLS = h.c.ConnectionState()
+	}
+	if req.Body == nil {
+		req.Body = eofReader
+	}
+	if req.RemoteAddr == "" {
+		req.RemoteAddr = h.c.RemoteAddr().String()
+	}
+	h.h.ServeHTTP(rw, req)
+}
+
+// loggingConn is used for debugging.
+type loggingConn struct {
+	name string
+	net.Conn
+}
+
+var (
+	uniqNameMu   sync.Mutex
+	uniqNameNext = make(map[string]int)
+)
+
+func newLoggingConn(baseName string, c net.Conn) net.Conn {
+	uniqNameMu.Lock()
+	defer uniqNameMu.Unlock()
+	uniqNameNext[baseName]++
+	return &loggingConn{
+		name: fmt.Sprintf("%s-%d", baseName, uniqNameNext[baseName]),
+		Conn: c,
+	}
+}
+
+func (c *loggingConn) Write(p []byte) (n int, err error) {
+	log.Printf("%s.Write(%d) = ....", c.name, len(p))
+	n, err = c.Conn.Write(p)
+	log.Printf("%s.Write(%d) = %d, %v", c.name, len(p), n, err)
+	return
+}
+
+func (c *loggingConn) Read(p []byte) (n int, err error) {
+	log.Printf("%s.Read(%d) = ....", c.name, len(p))
+	n, err = c.Conn.Read(p)
+	log.Printf("%s.Read(%d) = %d, %v", c.name, len(p), n, err)
+	return
+}
+
+func (c *loggingConn) Close() (err error) {
+	log.Printf("%s.Close() = ...", c.name)
+	err = c.Conn.Close()
+	log.Printf("%s.Close() = %v", c.name, err)
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/sniff.go b/third_party/gofrontend/libgo/go/net/http/sniff.go
new file mode 100644
index 0000000..68f519b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/sniff.go
@@ -0,0 +1,214 @@
+// 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.
+
+package http
+
+import (
+	"bytes"
+	"encoding/binary"
+)
+
+// The algorithm uses at most sniffLen bytes to make its decision.
+const sniffLen = 512
+
+// DetectContentType implements the algorithm described
+// at http://mimesniff.spec.whatwg.org/ to determine the
+// Content-Type of the given data.  It considers at most the
+// first 512 bytes of data.  DetectContentType always returns
+// a valid MIME type: if it cannot determine a more specific one, it
+// returns "application/octet-stream".
+func DetectContentType(data []byte) string {
+	if len(data) > sniffLen {
+		data = data[:sniffLen]
+	}
+
+	// Index of the first non-whitespace byte in data.
+	firstNonWS := 0
+	for ; firstNonWS < len(data) && isWS(data[firstNonWS]); firstNonWS++ {
+	}
+
+	for _, sig := range sniffSignatures {
+		if ct := sig.match(data, firstNonWS); ct != "" {
+			return ct
+		}
+	}
+
+	return "application/octet-stream" // fallback
+}
+
+func isWS(b byte) bool {
+	return bytes.IndexByte([]byte("\t\n\x0C\r "), b) != -1
+}
+
+type sniffSig interface {
+	// match returns the MIME type of the data, or "" if unknown.
+	match(data []byte, firstNonWS int) string
+}
+
+// Data matching the table in section 6.
+var sniffSignatures = []sniffSig{
+	htmlSig("<!DOCTYPE HTML"),
+	htmlSig("<HTML"),
+	htmlSig("<HEAD"),
+	htmlSig("<SCRIPT"),
+	htmlSig("<IFRAME"),
+	htmlSig("<H1"),
+	htmlSig("<DIV"),
+	htmlSig("<FONT"),
+	htmlSig("<TABLE"),
+	htmlSig("<A"),
+	htmlSig("<STYLE"),
+	htmlSig("<TITLE"),
+	htmlSig("<B"),
+	htmlSig("<BODY"),
+	htmlSig("<BR"),
+	htmlSig("<P"),
+	htmlSig("<!--"),
+
+	&maskedSig{mask: []byte("\xFF\xFF\xFF\xFF\xFF"), pat: []byte("<?xml"), skipWS: true, ct: "text/xml; charset=utf-8"},
+
+	&exactSig{[]byte("%PDF-"), "application/pdf"},
+	&exactSig{[]byte("%!PS-Adobe-"), "application/postscript"},
+
+	// UTF BOMs.
+	&maskedSig{mask: []byte("\xFF\xFF\x00\x00"), pat: []byte("\xFE\xFF\x00\x00"), ct: "text/plain; charset=utf-16be"},
+	&maskedSig{mask: []byte("\xFF\xFF\x00\x00"), pat: []byte("\xFF\xFE\x00\x00"), ct: "text/plain; charset=utf-16le"},
+	&maskedSig{mask: []byte("\xFF\xFF\xFF\x00"), pat: []byte("\xEF\xBB\xBF\x00"), ct: "text/plain; charset=utf-8"},
+
+	&exactSig{[]byte("GIF87a"), "image/gif"},
+	&exactSig{[]byte("GIF89a"), "image/gif"},
+	&exactSig{[]byte("\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"), "image/png"},
+	&exactSig{[]byte("\xFF\xD8\xFF"), "image/jpeg"},
+	&exactSig{[]byte("BM"), "image/bmp"},
+	&maskedSig{
+		mask: []byte("\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"),
+		pat:  []byte("RIFF\x00\x00\x00\x00WEBPVP"),
+		ct:   "image/webp",
+	},
+	&exactSig{[]byte("\x00\x00\x01\x00"), "image/vnd.microsoft.icon"},
+	&exactSig{[]byte("\x4F\x67\x67\x53\x00"), "application/ogg"},
+	&maskedSig{
+		mask: []byte("\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF"),
+		pat:  []byte("RIFF\x00\x00\x00\x00WAVE"),
+		ct:   "audio/wave",
+	},
+	&exactSig{[]byte("\x1A\x45\xDF\xA3"), "video/webm"},
+	&exactSig{[]byte("\x52\x61\x72\x20\x1A\x07\x00"), "application/x-rar-compressed"},
+	&exactSig{[]byte("\x50\x4B\x03\x04"), "application/zip"},
+	&exactSig{[]byte("\x1F\x8B\x08"), "application/x-gzip"},
+
+	// TODO(dsymonds): Re-enable this when the spec is sorted w.r.t. MP4.
+	//mp4Sig(0),
+
+	textSig(0), // should be last
+}
+
+type exactSig struct {
+	sig []byte
+	ct  string
+}
+
+func (e *exactSig) match(data []byte, firstNonWS int) string {
+	if bytes.HasPrefix(data, e.sig) {
+		return e.ct
+	}
+	return ""
+}
+
+type maskedSig struct {
+	mask, pat []byte
+	skipWS    bool
+	ct        string
+}
+
+func (m *maskedSig) match(data []byte, firstNonWS int) string {
+	if m.skipWS {
+		data = data[firstNonWS:]
+	}
+	if len(data) < len(m.mask) {
+		return ""
+	}
+	for i, mask := range m.mask {
+		db := data[i] & mask
+		if db != m.pat[i] {
+			return ""
+		}
+	}
+	return m.ct
+}
+
+type htmlSig []byte
+
+func (h htmlSig) match(data []byte, firstNonWS int) string {
+	data = data[firstNonWS:]
+	if len(data) < len(h)+1 {
+		return ""
+	}
+	for i, b := range h {
+		db := data[i]
+		if 'A' <= b && b <= 'Z' {
+			db &= 0xDF
+		}
+		if b != db {
+			return ""
+		}
+	}
+	// Next byte must be space or right angle bracket.
+	if db := data[len(h)]; db != ' ' && db != '>' {
+		return ""
+	}
+	return "text/html; charset=utf-8"
+}
+
+type mp4Sig int
+
+func (mp4Sig) match(data []byte, firstNonWS int) string {
+	// c.f. section 6.1.
+	if len(data) < 8 {
+		return ""
+	}
+	boxSize := int(binary.BigEndian.Uint32(data[:4]))
+	if boxSize%4 != 0 || len(data) < boxSize {
+		return ""
+	}
+	if !bytes.Equal(data[4:8], []byte("ftyp")) {
+		return ""
+	}
+	for st := 8; st < boxSize; st += 4 {
+		if st == 12 {
+			// minor version number
+			continue
+		}
+		seg := string(data[st : st+3])
+		switch seg {
+		case "mp4", "iso", "M4V", "M4P", "M4B":
+			return "video/mp4"
+			/* The remainder are not in the spec.
+			case "M4A":
+				return "audio/mp4"
+			case "3gp":
+				return "video/3gpp"
+			case "jp2":
+				return "image/jp2" // JPEG 2000
+			*/
+		}
+	}
+	return ""
+}
+
+type textSig int
+
+func (textSig) match(data []byte, firstNonWS int) string {
+	// c.f. section 5, step 4.
+	for _, b := range data[firstNonWS:] {
+		switch {
+		case 0x00 <= b && b <= 0x08,
+			b == 0x0B,
+			0x0E <= b && b <= 0x1A,
+			0x1C <= b && b <= 0x1F:
+			return ""
+		}
+	}
+	return "text/plain; charset=utf-8"
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/sniff_test.go b/third_party/gofrontend/libgo/go/net/http/sniff_test.go
new file mode 100644
index 0000000..24ca27a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/sniff_test.go
@@ -0,0 +1,171 @@
+// 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.
+
+package http_test
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	. "net/http"
+	"net/http/httptest"
+	"reflect"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+var sniffTests = []struct {
+	desc        string
+	data        []byte
+	contentType string
+}{
+	// Some nonsense.
+	{"Empty", []byte{}, "text/plain; charset=utf-8"},
+	{"Binary", []byte{1, 2, 3}, "application/octet-stream"},
+
+	{"HTML document #1", []byte(`<HtMl><bOdY>blah blah blah</body></html>`), "text/html; charset=utf-8"},
+	{"HTML document #2", []byte(`<HTML></HTML>`), "text/html; charset=utf-8"},
+	{"HTML document #3 (leading whitespace)", []byte(`   <!DOCTYPE HTML>...`), "text/html; charset=utf-8"},
+	{"HTML document #4 (leading CRLF)", []byte("\r\n<html>..."), "text/html; charset=utf-8"},
+
+	{"Plain text", []byte(`This is not HTML. It has ☃ though.`), "text/plain; charset=utf-8"},
+
+	{"XML", []byte("\n<?xml!"), "text/xml; charset=utf-8"},
+
+	// Image types.
+	{"GIF 87a", []byte(`GIF87a`), "image/gif"},
+	{"GIF 89a", []byte(`GIF89a...`), "image/gif"},
+
+	// TODO(dsymonds): Re-enable this when the spec is sorted w.r.t. MP4.
+	//{"MP4 video", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"},
+	//{"MP4 audio", []byte("\x00\x00\x00\x20ftypM4A \x00\x00\x00\x00M4A mp42isom\x00\x00\x00\x00"), "audio/mp4"},
+}
+
+func TestDetectContentType(t *testing.T) {
+	for _, tt := range sniffTests {
+		ct := DetectContentType(tt.data)
+		if ct != tt.contentType {
+			t.Errorf("%v: DetectContentType = %q, want %q", tt.desc, ct, tt.contentType)
+		}
+	}
+}
+
+func TestServerContentType(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		i, _ := strconv.Atoi(r.FormValue("i"))
+		tt := sniffTests[i]
+		n, err := w.Write(tt.data)
+		if n != len(tt.data) || err != nil {
+			log.Fatalf("%v: Write(%q) = %v, %v want %d, nil", tt.desc, tt.data, n, err, len(tt.data))
+		}
+	}))
+	defer ts.Close()
+
+	for i, tt := range sniffTests {
+		resp, err := Get(ts.URL + "/?i=" + strconv.Itoa(i))
+		if err != nil {
+			t.Errorf("%v: %v", tt.desc, err)
+			continue
+		}
+		if ct := resp.Header.Get("Content-Type"); ct != tt.contentType {
+			t.Errorf("%v: Content-Type = %q, want %q", tt.desc, ct, tt.contentType)
+		}
+		data, err := ioutil.ReadAll(resp.Body)
+		if err != nil {
+			t.Errorf("%v: reading body: %v", tt.desc, err)
+		} else if !bytes.Equal(data, tt.data) {
+			t.Errorf("%v: data is %q, want %q", tt.desc, data, tt.data)
+		}
+		resp.Body.Close()
+	}
+}
+
+// Issue 5953: shouldn't sniff if the handler set a Content-Type header,
+// even if it's the empty string.
+func TestServerIssue5953(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header()["Content-Type"] = []string{""}
+		fmt.Fprintf(w, "<html><head></head><body>hi</body></html>")
+	}))
+	defer ts.Close()
+
+	resp, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	got := resp.Header["Content-Type"]
+	want := []string{""}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Content-Type = %q; want %q", got, want)
+	}
+	resp.Body.Close()
+}
+
+func TestContentTypeWithCopy(t *testing.T) {
+	defer afterTest(t)
+
+	const (
+		input    = "\n<html>\n\t<head>\n"
+		expected = "text/html; charset=utf-8"
+	)
+
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		// Use io.Copy from a bytes.Buffer to trigger ReadFrom.
+		buf := bytes.NewBuffer([]byte(input))
+		n, err := io.Copy(w, buf)
+		if int(n) != len(input) || err != nil {
+			t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
+		}
+	}))
+	defer ts.Close()
+
+	resp, err := Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	if ct := resp.Header.Get("Content-Type"); ct != expected {
+		t.Errorf("Content-Type = %q, want %q", ct, expected)
+	}
+	data, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		t.Errorf("reading body: %v", err)
+	} else if !bytes.Equal(data, []byte(input)) {
+		t.Errorf("data is %q, want %q", data, input)
+	}
+	resp.Body.Close()
+}
+
+func TestSniffWriteSize(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		size, _ := strconv.Atoi(r.FormValue("size"))
+		written, err := io.WriteString(w, strings.Repeat("a", size))
+		if err != nil {
+			t.Errorf("write of %d bytes: %v", size, err)
+			return
+		}
+		if written != size {
+			t.Errorf("write of %d bytes wrote %d bytes", size, written)
+		}
+	}))
+	defer ts.Close()
+	for _, size := range []int{0, 1, 200, 600, 999, 1000, 1023, 1024, 512 << 10, 1 << 20} {
+		res, err := Get(fmt.Sprintf("%s/?size=%d", ts.URL, size))
+		if err != nil {
+			t.Fatalf("size %d: %v", size, err)
+		}
+		if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
+			t.Fatalf("size %d: io.Copy of body = %v", size, err)
+		}
+		if err := res.Body.Close(); err != nil {
+			t.Fatalf("size %d: body Close = %v", size, err)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/status.go b/third_party/gofrontend/libgo/go/net/http/status.go
new file mode 100644
index 0000000..d253bd5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/status.go
@@ -0,0 +1,120 @@
+// 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 http
+
+// HTTP status codes, defined in RFC 2616.
+const (
+	StatusContinue           = 100
+	StatusSwitchingProtocols = 101
+
+	StatusOK                   = 200
+	StatusCreated              = 201
+	StatusAccepted             = 202
+	StatusNonAuthoritativeInfo = 203
+	StatusNoContent            = 204
+	StatusResetContent         = 205
+	StatusPartialContent       = 206
+
+	StatusMultipleChoices   = 300
+	StatusMovedPermanently  = 301
+	StatusFound             = 302
+	StatusSeeOther          = 303
+	StatusNotModified       = 304
+	StatusUseProxy          = 305
+	StatusTemporaryRedirect = 307
+
+	StatusBadRequest                   = 400
+	StatusUnauthorized                 = 401
+	StatusPaymentRequired              = 402
+	StatusForbidden                    = 403
+	StatusNotFound                     = 404
+	StatusMethodNotAllowed             = 405
+	StatusNotAcceptable                = 406
+	StatusProxyAuthRequired            = 407
+	StatusRequestTimeout               = 408
+	StatusConflict                     = 409
+	StatusGone                         = 410
+	StatusLengthRequired               = 411
+	StatusPreconditionFailed           = 412
+	StatusRequestEntityTooLarge        = 413
+	StatusRequestURITooLong            = 414
+	StatusUnsupportedMediaType         = 415
+	StatusRequestedRangeNotSatisfiable = 416
+	StatusExpectationFailed            = 417
+	StatusTeapot                       = 418
+
+	StatusInternalServerError     = 500
+	StatusNotImplemented          = 501
+	StatusBadGateway              = 502
+	StatusServiceUnavailable      = 503
+	StatusGatewayTimeout          = 504
+	StatusHTTPVersionNotSupported = 505
+
+	// New HTTP status codes from RFC 6585. Not exported yet in Go 1.1.
+	// See discussion at https://codereview.appspot.com/7678043/
+	statusPreconditionRequired          = 428
+	statusTooManyRequests               = 429
+	statusRequestHeaderFieldsTooLarge   = 431
+	statusNetworkAuthenticationRequired = 511
+)
+
+var statusText = map[int]string{
+	StatusContinue:           "Continue",
+	StatusSwitchingProtocols: "Switching Protocols",
+
+	StatusOK:                   "OK",
+	StatusCreated:              "Created",
+	StatusAccepted:             "Accepted",
+	StatusNonAuthoritativeInfo: "Non-Authoritative Information",
+	StatusNoContent:            "No Content",
+	StatusResetContent:         "Reset Content",
+	StatusPartialContent:       "Partial Content",
+
+	StatusMultipleChoices:   "Multiple Choices",
+	StatusMovedPermanently:  "Moved Permanently",
+	StatusFound:             "Found",
+	StatusSeeOther:          "See Other",
+	StatusNotModified:       "Not Modified",
+	StatusUseProxy:          "Use Proxy",
+	StatusTemporaryRedirect: "Temporary Redirect",
+
+	StatusBadRequest:                   "Bad Request",
+	StatusUnauthorized:                 "Unauthorized",
+	StatusPaymentRequired:              "Payment Required",
+	StatusForbidden:                    "Forbidden",
+	StatusNotFound:                     "Not Found",
+	StatusMethodNotAllowed:             "Method Not Allowed",
+	StatusNotAcceptable:                "Not Acceptable",
+	StatusProxyAuthRequired:            "Proxy Authentication Required",
+	StatusRequestTimeout:               "Request Timeout",
+	StatusConflict:                     "Conflict",
+	StatusGone:                         "Gone",
+	StatusLengthRequired:               "Length Required",
+	StatusPreconditionFailed:           "Precondition Failed",
+	StatusRequestEntityTooLarge:        "Request Entity Too Large",
+	StatusRequestURITooLong:            "Request URI Too Long",
+	StatusUnsupportedMediaType:         "Unsupported Media Type",
+	StatusRequestedRangeNotSatisfiable: "Requested Range Not Satisfiable",
+	StatusExpectationFailed:            "Expectation Failed",
+	StatusTeapot:                       "I'm a teapot",
+
+	StatusInternalServerError:     "Internal Server Error",
+	StatusNotImplemented:          "Not Implemented",
+	StatusBadGateway:              "Bad Gateway",
+	StatusServiceUnavailable:      "Service Unavailable",
+	StatusGatewayTimeout:          "Gateway Timeout",
+	StatusHTTPVersionNotSupported: "HTTP Version Not Supported",
+
+	statusPreconditionRequired:          "Precondition Required",
+	statusTooManyRequests:               "Too Many Requests",
+	statusRequestHeaderFieldsTooLarge:   "Request Header Fields Too Large",
+	statusNetworkAuthenticationRequired: "Network Authentication Required",
+}
+
+// StatusText returns a text for the HTTP status code. It returns the empty
+// string if the code is unknown.
+func StatusText(code int) string {
+	return statusText[code]
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/testdata/file b/third_party/gofrontend/libgo/go/net/http/testdata/file
new file mode 100644
index 0000000..11f11f9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/testdata/file
@@ -0,0 +1 @@
+0123456789
diff --git a/third_party/gofrontend/libgo/go/net/http/testdata/index.html b/third_party/gofrontend/libgo/go/net/http/testdata/index.html
new file mode 100644
index 0000000..da8e1e9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/testdata/index.html
@@ -0,0 +1 @@
+index.html says hello
diff --git a/third_party/gofrontend/libgo/go/net/http/testdata/style.css b/third_party/gofrontend/libgo/go/net/http/testdata/style.css
new file mode 100644
index 0000000..208d16d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/testdata/style.css
@@ -0,0 +1 @@
+body {}
diff --git a/third_party/gofrontend/libgo/go/net/http/transfer.go b/third_party/gofrontend/libgo/go/net/http/transfer.go
new file mode 100644
index 0000000..7f63686
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/transfer.go
@@ -0,0 +1,730 @@
+// 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 http
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/textproto"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+)
+
+type errorReader struct {
+	err error
+}
+
+func (r *errorReader) Read(p []byte) (n int, err error) {
+	return 0, r.err
+}
+
+// transferWriter inspects the fields of a user-supplied Request or Response,
+// sanitizes them without changing the user object and provides methods for
+// writing the respective header, body and trailer in wire format.
+type transferWriter struct {
+	Method           string
+	Body             io.Reader
+	BodyCloser       io.Closer
+	ResponseToHEAD   bool
+	ContentLength    int64 // -1 means unknown, 0 means exactly none
+	Close            bool
+	TransferEncoding []string
+	Trailer          Header
+}
+
+func newTransferWriter(r interface{}) (t *transferWriter, err error) {
+	t = &transferWriter{}
+
+	// Extract relevant fields
+	atLeastHTTP11 := false
+	switch rr := r.(type) {
+	case *Request:
+		if rr.ContentLength != 0 && rr.Body == nil {
+			return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
+		}
+		t.Method = rr.Method
+		t.Body = rr.Body
+		t.BodyCloser = rr.Body
+		t.ContentLength = rr.ContentLength
+		t.Close = rr.Close
+		t.TransferEncoding = rr.TransferEncoding
+		t.Trailer = rr.Trailer
+		atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
+		if t.Body != nil && len(t.TransferEncoding) == 0 && atLeastHTTP11 {
+			if t.ContentLength == 0 {
+				// Test to see if it's actually zero or just unset.
+				var buf [1]byte
+				n, rerr := io.ReadFull(t.Body, buf[:])
+				if rerr != nil && rerr != io.EOF {
+					t.ContentLength = -1
+					t.Body = &errorReader{rerr}
+				} else if n == 1 {
+					// Oh, guess there is data in this Body Reader after all.
+					// The ContentLength field just wasn't set.
+					// Stich the Body back together again, re-attaching our
+					// consumed byte.
+					t.ContentLength = -1
+					t.Body = io.MultiReader(bytes.NewReader(buf[:]), t.Body)
+				} else {
+					// Body is actually empty.
+					t.Body = nil
+					t.BodyCloser = nil
+				}
+			}
+			if t.ContentLength < 0 {
+				t.TransferEncoding = []string{"chunked"}
+			}
+		}
+	case *Response:
+		if rr.Request != nil {
+			t.Method = rr.Request.Method
+		}
+		t.Body = rr.Body
+		t.BodyCloser = rr.Body
+		t.ContentLength = rr.ContentLength
+		t.Close = rr.Close
+		t.TransferEncoding = rr.TransferEncoding
+		t.Trailer = rr.Trailer
+		atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
+		t.ResponseToHEAD = noBodyExpected(t.Method)
+	}
+
+	// Sanitize Body,ContentLength,TransferEncoding
+	if t.ResponseToHEAD {
+		t.Body = nil
+		if chunked(t.TransferEncoding) {
+			t.ContentLength = -1
+		}
+	} else {
+		if !atLeastHTTP11 || t.Body == nil {
+			t.TransferEncoding = nil
+		}
+		if chunked(t.TransferEncoding) {
+			t.ContentLength = -1
+		} else if t.Body == nil { // no chunking, no body
+			t.ContentLength = 0
+		}
+	}
+
+	// Sanitize Trailer
+	if !chunked(t.TransferEncoding) {
+		t.Trailer = nil
+	}
+
+	return t, nil
+}
+
+func noBodyExpected(requestMethod string) bool {
+	return requestMethod == "HEAD"
+}
+
+func (t *transferWriter) shouldSendContentLength() bool {
+	if chunked(t.TransferEncoding) {
+		return false
+	}
+	if t.ContentLength > 0 {
+		return true
+	}
+	// Many servers expect a Content-Length for these methods
+	if t.Method == "POST" || t.Method == "PUT" {
+		return true
+	}
+	if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
+		return true
+	}
+
+	return false
+}
+
+func (t *transferWriter) WriteHeader(w io.Writer) error {
+	if t.Close {
+		if _, err := io.WriteString(w, "Connection: close\r\n"); err != nil {
+			return err
+		}
+	}
+
+	// Write Content-Length and/or Transfer-Encoding whose values are a
+	// function of the sanitized field triple (Body, ContentLength,
+	// TransferEncoding)
+	if t.shouldSendContentLength() {
+		if _, err := io.WriteString(w, "Content-Length: "); err != nil {
+			return err
+		}
+		if _, err := io.WriteString(w, strconv.FormatInt(t.ContentLength, 10)+"\r\n"); err != nil {
+			return err
+		}
+	} else if chunked(t.TransferEncoding) {
+		if _, err := io.WriteString(w, "Transfer-Encoding: chunked\r\n"); err != nil {
+			return err
+		}
+	}
+
+	// Write Trailer header
+	if t.Trailer != nil {
+		keys := make([]string, 0, len(t.Trailer))
+		for k := range t.Trailer {
+			k = CanonicalHeaderKey(k)
+			switch k {
+			case "Transfer-Encoding", "Trailer", "Content-Length":
+				return &badStringError{"invalid Trailer key", k}
+			}
+			keys = append(keys, k)
+		}
+		if len(keys) > 0 {
+			sort.Strings(keys)
+			// TODO: could do better allocation-wise here, but trailers are rare,
+			// so being lazy for now.
+			if _, err := io.WriteString(w, "Trailer: "+strings.Join(keys, ",")+"\r\n"); err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func (t *transferWriter) WriteBody(w io.Writer) error {
+	var err error
+	var ncopy int64
+
+	// Write body
+	if t.Body != nil {
+		if chunked(t.TransferEncoding) {
+			cw := newChunkedWriter(w)
+			_, err = io.Copy(cw, t.Body)
+			if err == nil {
+				err = cw.Close()
+			}
+		} else if t.ContentLength == -1 {
+			ncopy, err = io.Copy(w, t.Body)
+		} else {
+			ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
+			if err != nil {
+				return err
+			}
+			var nextra int64
+			nextra, err = io.Copy(ioutil.Discard, t.Body)
+			ncopy += nextra
+		}
+		if err != nil {
+			return err
+		}
+		if err = t.BodyCloser.Close(); err != nil {
+			return err
+		}
+	}
+
+	if !t.ResponseToHEAD && t.ContentLength != -1 && t.ContentLength != ncopy {
+		return fmt.Errorf("http: Request.ContentLength=%d with Body length %d",
+			t.ContentLength, ncopy)
+	}
+
+	// TODO(petar): Place trailer writer code here.
+	if chunked(t.TransferEncoding) {
+		// Write Trailer header
+		if t.Trailer != nil {
+			if err := t.Trailer.Write(w); err != nil {
+				return err
+			}
+		}
+		// Last chunk, empty trailer
+		_, err = io.WriteString(w, "\r\n")
+	}
+	return err
+}
+
+type transferReader struct {
+	// Input
+	Header        Header
+	StatusCode    int
+	RequestMethod string
+	ProtoMajor    int
+	ProtoMinor    int
+	// Output
+	Body             io.ReadCloser
+	ContentLength    int64
+	TransferEncoding []string
+	Close            bool
+	Trailer          Header
+}
+
+// bodyAllowedForStatus reports whether a given response status code
+// permits a body.  See RFC2616, section 4.4.
+func bodyAllowedForStatus(status int) bool {
+	switch {
+	case status >= 100 && status <= 199:
+		return false
+	case status == 204:
+		return false
+	case status == 304:
+		return false
+	}
+	return true
+}
+
+var (
+	suppressedHeaders304    = []string{"Content-Type", "Content-Length", "Transfer-Encoding"}
+	suppressedHeadersNoBody = []string{"Content-Length", "Transfer-Encoding"}
+)
+
+func suppressedHeaders(status int) []string {
+	switch {
+	case status == 304:
+		// RFC 2616 section 10.3.5: "the response MUST NOT include other entity-headers"
+		return suppressedHeaders304
+	case !bodyAllowedForStatus(status):
+		return suppressedHeadersNoBody
+	}
+	return nil
+}
+
+// msg is *Request or *Response.
+func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
+	t := &transferReader{RequestMethod: "GET"}
+
+	// Unify input
+	isResponse := false
+	switch rr := msg.(type) {
+	case *Response:
+		t.Header = rr.Header
+		t.StatusCode = rr.StatusCode
+		t.ProtoMajor = rr.ProtoMajor
+		t.ProtoMinor = rr.ProtoMinor
+		t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header)
+		isResponse = true
+		if rr.Request != nil {
+			t.RequestMethod = rr.Request.Method
+		}
+	case *Request:
+		t.Header = rr.Header
+		t.ProtoMajor = rr.ProtoMajor
+		t.ProtoMinor = rr.ProtoMinor
+		// Transfer semantics for Requests are exactly like those for
+		// Responses with status code 200, responding to a GET method
+		t.StatusCode = 200
+	default:
+		panic("unexpected type")
+	}
+
+	// Default to HTTP/1.1
+	if t.ProtoMajor == 0 && t.ProtoMinor == 0 {
+		t.ProtoMajor, t.ProtoMinor = 1, 1
+	}
+
+	// Transfer encoding, content length
+	t.TransferEncoding, err = fixTransferEncoding(t.RequestMethod, t.Header)
+	if err != nil {
+		return err
+	}
+
+	realLength, err := fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
+	if err != nil {
+		return err
+	}
+	if isResponse && t.RequestMethod == "HEAD" {
+		if n, err := parseContentLength(t.Header.get("Content-Length")); err != nil {
+			return err
+		} else {
+			t.ContentLength = n
+		}
+	} else {
+		t.ContentLength = realLength
+	}
+
+	// Trailer
+	t.Trailer, err = fixTrailer(t.Header, t.TransferEncoding)
+	if err != nil {
+		return err
+	}
+
+	// If there is no Content-Length or chunked Transfer-Encoding on a *Response
+	// and the status is not 1xx, 204 or 304, then the body is unbounded.
+	// See RFC2616, section 4.4.
+	switch msg.(type) {
+	case *Response:
+		if realLength == -1 &&
+			!chunked(t.TransferEncoding) &&
+			bodyAllowedForStatus(t.StatusCode) {
+			// Unbounded body.
+			t.Close = true
+		}
+	}
+
+	// Prepare body reader.  ContentLength < 0 means chunked encoding
+	// or close connection when finished, since multipart is not supported yet
+	switch {
+	case chunked(t.TransferEncoding):
+		if noBodyExpected(t.RequestMethod) {
+			t.Body = eofReader
+		} else {
+			t.Body = &body{src: newChunkedReader(r), hdr: msg, r: r, closing: t.Close}
+		}
+	case realLength == 0:
+		t.Body = eofReader
+	case realLength > 0:
+		t.Body = &body{src: io.LimitReader(r, realLength), closing: t.Close}
+	default:
+		// realLength < 0, i.e. "Content-Length" not mentioned in header
+		if t.Close {
+			// Close semantics (i.e. HTTP/1.0)
+			t.Body = &body{src: r, closing: t.Close}
+		} else {
+			// Persistent connection (i.e. HTTP/1.1)
+			t.Body = eofReader
+		}
+	}
+
+	// Unify output
+	switch rr := msg.(type) {
+	case *Request:
+		rr.Body = t.Body
+		rr.ContentLength = t.ContentLength
+		rr.TransferEncoding = t.TransferEncoding
+		rr.Close = t.Close
+		rr.Trailer = t.Trailer
+	case *Response:
+		rr.Body = t.Body
+		rr.ContentLength = t.ContentLength
+		rr.TransferEncoding = t.TransferEncoding
+		rr.Close = t.Close
+		rr.Trailer = t.Trailer
+	}
+
+	return nil
+}
+
+// Checks whether chunked is part of the encodings stack
+func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
+
+// Checks whether the encoding is explicitly "identity".
+func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
+
+// Sanitize transfer encoding
+func fixTransferEncoding(requestMethod string, header Header) ([]string, error) {
+	raw, present := header["Transfer-Encoding"]
+	if !present {
+		return nil, nil
+	}
+
+	delete(header, "Transfer-Encoding")
+
+	encodings := strings.Split(raw[0], ",")
+	te := make([]string, 0, len(encodings))
+	// TODO: Even though we only support "identity" and "chunked"
+	// encodings, the loop below is designed with foresight. One
+	// invariant that must be maintained is that, if present,
+	// chunked encoding must always come first.
+	for _, encoding := range encodings {
+		encoding = strings.ToLower(strings.TrimSpace(encoding))
+		// "identity" encoding is not recorded
+		if encoding == "identity" {
+			break
+		}
+		if encoding != "chunked" {
+			return nil, &badStringError{"unsupported transfer encoding", encoding}
+		}
+		te = te[0 : len(te)+1]
+		te[len(te)-1] = encoding
+	}
+	if len(te) > 1 {
+		return nil, &badStringError{"too many transfer encodings", strings.Join(te, ",")}
+	}
+	if len(te) > 0 {
+		// Chunked encoding trumps Content-Length. See RFC 2616
+		// Section 4.4. Currently len(te) > 0 implies chunked
+		// encoding.
+		delete(header, "Content-Length")
+		return te, nil
+	}
+
+	return nil, nil
+}
+
+// Determine the expected body length, using RFC 2616 Section 4.4. This
+// function is not a method, because ultimately it should be shared by
+// ReadResponse and ReadRequest.
+func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, error) {
+
+	// Logic based on response type or status
+	if noBodyExpected(requestMethod) {
+		return 0, nil
+	}
+	if status/100 == 1 {
+		return 0, nil
+	}
+	switch status {
+	case 204, 304:
+		return 0, nil
+	}
+
+	// Logic based on Transfer-Encoding
+	if chunked(te) {
+		return -1, nil
+	}
+
+	// Logic based on Content-Length
+	cl := strings.TrimSpace(header.get("Content-Length"))
+	if cl != "" {
+		n, err := parseContentLength(cl)
+		if err != nil {
+			return -1, err
+		}
+		return n, nil
+	} else {
+		header.Del("Content-Length")
+	}
+
+	if !isResponse && requestMethod == "GET" {
+		// RFC 2616 doesn't explicitly permit nor forbid an
+		// entity-body on a GET request so we permit one if
+		// declared, but we default to 0 here (not -1 below)
+		// if there's no mention of a body.
+		return 0, nil
+	}
+
+	// Body-EOF logic based on other methods (like closing, or chunked coding)
+	return -1, nil
+}
+
+// Determine whether to hang up after sending a request and body, or
+// receiving a response and body
+// 'header' is the request headers
+func shouldClose(major, minor int, header Header) bool {
+	if major < 1 {
+		return true
+	} else if major == 1 && minor == 0 {
+		if !strings.Contains(strings.ToLower(header.get("Connection")), "keep-alive") {
+			return true
+		}
+		return false
+	} else {
+		// TODO: Should split on commas, toss surrounding white space,
+		// and check each field.
+		if strings.ToLower(header.get("Connection")) == "close" {
+			header.Del("Connection")
+			return true
+		}
+	}
+	return false
+}
+
+// Parse the trailer header
+func fixTrailer(header Header, te []string) (Header, error) {
+	raw := header.get("Trailer")
+	if raw == "" {
+		return nil, nil
+	}
+
+	header.Del("Trailer")
+	trailer := make(Header)
+	keys := strings.Split(raw, ",")
+	for _, key := range keys {
+		key = CanonicalHeaderKey(strings.TrimSpace(key))
+		switch key {
+		case "Transfer-Encoding", "Trailer", "Content-Length":
+			return nil, &badStringError{"bad trailer key", key}
+		}
+		trailer[key] = nil
+	}
+	if len(trailer) == 0 {
+		return nil, nil
+	}
+	if !chunked(te) {
+		// Trailer and no chunking
+		return nil, ErrUnexpectedTrailer
+	}
+	return trailer, nil
+}
+
+// body turns a Reader into a ReadCloser.
+// Close ensures that the body has been fully read
+// and then reads the trailer if necessary.
+type body struct {
+	src     io.Reader
+	hdr     interface{}   // non-nil (Response or Request) value means read trailer
+	r       *bufio.Reader // underlying wire-format reader for the trailer
+	closing bool          // is the connection to be closed after reading body?
+
+	mu     sync.Mutex // guards closed, and calls to Read and Close
+	closed bool
+}
+
+// ErrBodyReadAfterClose is returned when reading a Request or Response
+// Body after the body has been closed. This typically happens when the body is
+// read after an HTTP Handler calls WriteHeader or Write on its
+// ResponseWriter.
+var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
+
+func (b *body) Read(p []byte) (n int, err error) {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+	if b.closed {
+		return 0, ErrBodyReadAfterClose
+	}
+	return b.readLocked(p)
+}
+
+// Must hold b.mu.
+func (b *body) readLocked(p []byte) (n int, err error) {
+	n, err = b.src.Read(p)
+
+	if err == io.EOF {
+		// Chunked case. Read the trailer.
+		if b.hdr != nil {
+			if e := b.readTrailer(); e != nil {
+				err = e
+			}
+			b.hdr = nil
+		} else {
+			// If the server declared the Content-Length, our body is a LimitedReader
+			// and we need to check whether this EOF arrived early.
+			if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > 0 {
+				err = io.ErrUnexpectedEOF
+			}
+		}
+	}
+
+	// If we can return an EOF here along with the read data, do
+	// so. This is optional per the io.Reader contract, but doing
+	// so helps the HTTP transport code recycle its connection
+	// earlier (since it will see this EOF itself), even if the
+	// client doesn't do future reads or Close.
+	if err == nil && n > 0 {
+		if lr, ok := b.src.(*io.LimitedReader); ok && lr.N == 0 {
+			err = io.EOF
+		}
+	}
+
+	return n, err
+}
+
+var (
+	singleCRLF = []byte("\r\n")
+	doubleCRLF = []byte("\r\n\r\n")
+)
+
+func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
+	for peekSize := 4; ; peekSize++ {
+		// This loop stops when Peek returns an error,
+		// which it does when r's buffer has been filled.
+		buf, err := r.Peek(peekSize)
+		if bytes.HasSuffix(buf, doubleCRLF) {
+			return true
+		}
+		if err != nil {
+			break
+		}
+	}
+	return false
+}
+
+var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
+
+func (b *body) readTrailer() error {
+	// The common case, since nobody uses trailers.
+	buf, err := b.r.Peek(2)
+	if bytes.Equal(buf, singleCRLF) {
+		b.r.ReadByte()
+		b.r.ReadByte()
+		return nil
+	}
+	if len(buf) < 2 {
+		return errTrailerEOF
+	}
+	if err != nil {
+		return err
+	}
+
+	// Make sure there's a header terminator coming up, to prevent
+	// a DoS with an unbounded size Trailer.  It's not easy to
+	// slip in a LimitReader here, as textproto.NewReader requires
+	// a concrete *bufio.Reader.  Also, we can't get all the way
+	// back up to our conn's LimitedReader that *might* be backing
+	// this bufio.Reader.  Instead, a hack: we iteratively Peek up
+	// to the bufio.Reader's max size, looking for a double CRLF.
+	// This limits the trailer to the underlying buffer size, typically 4kB.
+	if !seeUpcomingDoubleCRLF(b.r) {
+		return errors.New("http: suspiciously long trailer after chunked body")
+	}
+
+	hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
+	if err != nil {
+		if err == io.EOF {
+			return errTrailerEOF
+		}
+		return err
+	}
+	switch rr := b.hdr.(type) {
+	case *Request:
+		mergeSetHeader(&rr.Trailer, Header(hdr))
+	case *Response:
+		mergeSetHeader(&rr.Trailer, Header(hdr))
+	}
+	return nil
+}
+
+func mergeSetHeader(dst *Header, src Header) {
+	if *dst == nil {
+		*dst = src
+		return
+	}
+	for k, vv := range src {
+		(*dst)[k] = vv
+	}
+}
+
+func (b *body) Close() error {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+	if b.closed {
+		return nil
+	}
+	var err error
+	switch {
+	case b.hdr == nil && b.closing:
+		// no trailer and closing the connection next.
+		// no point in reading to EOF.
+	default:
+		// Fully consume the body, which will also lead to us reading
+		// the trailer headers after the body, if present.
+		_, err = io.Copy(ioutil.Discard, bodyLocked{b})
+	}
+	b.closed = true
+	return err
+}
+
+// bodyLocked is a io.Reader reading from a *body when its mutex is
+// already held.
+type bodyLocked struct {
+	b *body
+}
+
+func (bl bodyLocked) Read(p []byte) (n int, err error) {
+	if bl.b.closed {
+		return 0, ErrBodyReadAfterClose
+	}
+	return bl.b.readLocked(p)
+}
+
+// parseContentLength trims whitespace from s and returns -1 if no value
+// is set, or the value if it's >= 0.
+func parseContentLength(cl string) (int64, error) {
+	cl = strings.TrimSpace(cl)
+	if cl == "" {
+		return -1, nil
+	}
+	n, err := strconv.ParseInt(cl, 10, 64)
+	if err != nil || n < 0 {
+		return 0, &badStringError{"bad Content-Length", cl}
+	}
+	return n, nil
+
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/transfer_test.go b/third_party/gofrontend/libgo/go/net/http/transfer_test.go
new file mode 100644
index 0000000..48cd540
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/transfer_test.go
@@ -0,0 +1,64 @@
+// 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 http
+
+import (
+	"bufio"
+	"io"
+	"strings"
+	"testing"
+)
+
+func TestBodyReadBadTrailer(t *testing.T) {
+	b := &body{
+		src: strings.NewReader("foobar"),
+		hdr: true, // force reading the trailer
+		r:   bufio.NewReader(strings.NewReader("")),
+	}
+	buf := make([]byte, 7)
+	n, err := b.Read(buf[:3])
+	got := string(buf[:n])
+	if got != "foo" || err != nil {
+		t.Fatalf(`first Read = %d (%q), %v; want 3 ("foo")`, n, got, err)
+	}
+
+	n, err = b.Read(buf[:])
+	got = string(buf[:n])
+	if got != "bar" || err != nil {
+		t.Fatalf(`second Read = %d (%q), %v; want 3 ("bar")`, n, got, err)
+	}
+
+	n, err = b.Read(buf[:])
+	got = string(buf[:n])
+	if err == nil {
+		t.Errorf("final Read was successful (%q), expected error from trailer read", got)
+	}
+}
+
+func TestFinalChunkedBodyReadEOF(t *testing.T) {
+	res, err := ReadResponse(bufio.NewReader(strings.NewReader(
+		"HTTP/1.1 200 OK\r\n"+
+			"Transfer-Encoding: chunked\r\n"+
+			"\r\n"+
+			"0a\r\n"+
+			"Body here\n\r\n"+
+			"09\r\n"+
+			"continued\r\n"+
+			"0\r\n"+
+			"\r\n")), nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	want := "Body here\ncontinued"
+	buf := make([]byte, len(want))
+	n, err := res.Body.Read(buf)
+	if n != len(want) || err != io.EOF {
+		t.Logf("body = %#v", res.Body)
+		t.Errorf("Read = %v, %v; want %d, EOF", n, err, len(want))
+	}
+	if string(buf) != want {
+		t.Errorf("buf = %q; want %q", buf, want)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/transport.go b/third_party/gofrontend/libgo/go/net/http/transport.go
new file mode 100644
index 0000000..b1cc632
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/transport.go
@@ -0,0 +1,1208 @@
+// 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.
+
+// HTTP client implementation. See RFC 2616.
+//
+// This is the low-level Transport implementation of RoundTripper.
+// The high-level interface is in client.go.
+
+package http
+
+import (
+	"bufio"
+	"compress/gzip"
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"net"
+	"net/url"
+	"os"
+	"strings"
+	"sync"
+	"time"
+)
+
+// DefaultTransport is the default implementation of Transport and is
+// used by DefaultClient. It establishes network connections as needed
+// and caches them for reuse by subsequent calls. It uses HTTP proxies
+// as directed by the $HTTP_PROXY and $NO_PROXY (or $http_proxy and
+// $no_proxy) environment variables.
+var DefaultTransport RoundTripper = &Transport{
+	Proxy: ProxyFromEnvironment,
+	Dial: (&net.Dialer{
+		Timeout:   30 * time.Second,
+		KeepAlive: 30 * time.Second,
+	}).Dial,
+	TLSHandshakeTimeout: 10 * time.Second,
+}
+
+// DefaultMaxIdleConnsPerHost is the default value of Transport's
+// MaxIdleConnsPerHost.
+const DefaultMaxIdleConnsPerHost = 2
+
+// Transport is an implementation of RoundTripper that supports http,
+// https, and http proxies (for either http or https with CONNECT).
+// Transport can also cache connections for future re-use.
+type Transport struct {
+	idleMu      sync.Mutex
+	idleConn    map[connectMethodKey][]*persistConn
+	idleConnCh  map[connectMethodKey]chan *persistConn
+	reqMu       sync.Mutex
+	reqCanceler map[*Request]func()
+	altMu       sync.RWMutex
+	altProto    map[string]RoundTripper // nil or map of URI scheme => RoundTripper
+
+	// Proxy specifies a function to return a proxy for a given
+	// Request. If the function returns a non-nil error, the
+	// request is aborted with the provided error.
+	// If Proxy is nil or returns a nil *URL, no proxy is used.
+	Proxy func(*Request) (*url.URL, error)
+
+	// Dial specifies the dial function for creating TCP
+	// connections.
+	// If Dial is nil, net.Dial is used.
+	Dial func(network, addr string) (net.Conn, error)
+
+	// TLSClientConfig specifies the TLS configuration to use with
+	// tls.Client. If nil, the default configuration is used.
+	TLSClientConfig *tls.Config
+
+	// TLSHandshakeTimeout specifies the maximum amount of time waiting to
+	// wait for a TLS handshake. Zero means no timeout.
+	TLSHandshakeTimeout time.Duration
+
+	// DisableKeepAlives, if true, prevents re-use of TCP connections
+	// between different HTTP requests.
+	DisableKeepAlives bool
+
+	// DisableCompression, if true, prevents the Transport from
+	// requesting compression with an "Accept-Encoding: gzip"
+	// request header when the Request contains no existing
+	// Accept-Encoding value. If the Transport requests gzip on
+	// its own and gets a gzipped response, it's transparently
+	// decoded in the Response.Body. However, if the user
+	// explicitly requested gzip it is not automatically
+	// uncompressed.
+	DisableCompression bool
+
+	// MaxIdleConnsPerHost, if non-zero, controls the maximum idle
+	// (keep-alive) to keep per-host.  If zero,
+	// DefaultMaxIdleConnsPerHost is used.
+	MaxIdleConnsPerHost int
+
+	// ResponseHeaderTimeout, if non-zero, specifies the amount of
+	// time to wait for a server's response headers after fully
+	// writing the request (including its body, if any). This
+	// time does not include the time to read the response body.
+	ResponseHeaderTimeout time.Duration
+
+	// TODO: tunable on global max cached connections
+	// TODO: tunable on timeout on cached connections
+}
+
+// ProxyFromEnvironment returns the URL of the proxy to use for a
+// given request, as indicated by the environment variables
+// $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy).
+// An error is returned if the proxy environment is invalid.
+// A nil URL and nil error are returned if no proxy is defined in the
+// environment, or a proxy should not be used for the given request.
+//
+// As a special case, if req.URL.Host is "localhost" (with or without
+// a port number), then a nil URL and nil error will be returned.
+func ProxyFromEnvironment(req *Request) (*url.URL, error) {
+	proxy := httpProxyEnv.Get()
+	if proxy == "" {
+		return nil, nil
+	}
+	if !useProxy(canonicalAddr(req.URL)) {
+		return nil, nil
+	}
+	proxyURL, err := url.Parse(proxy)
+	if err != nil || !strings.HasPrefix(proxyURL.Scheme, "http") {
+		// proxy was bogus. Try prepending "http://" to it and
+		// see if that parses correctly. If not, we fall
+		// through and complain about the original one.
+		if proxyURL, err := url.Parse("http://" + proxy); err == nil {
+			return proxyURL, nil
+		}
+	}
+	if err != nil {
+		return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
+	}
+	return proxyURL, nil
+}
+
+// ProxyURL returns a proxy function (for use in a Transport)
+// that always returns the same URL.
+func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, error) {
+	return func(*Request) (*url.URL, error) {
+		return fixedURL, nil
+	}
+}
+
+// transportRequest is a wrapper around a *Request that adds
+// optional extra headers to write.
+type transportRequest struct {
+	*Request        // original request, not to be mutated
+	extra    Header // extra headers to write, or nil
+}
+
+func (tr *transportRequest) extraHeaders() Header {
+	if tr.extra == nil {
+		tr.extra = make(Header)
+	}
+	return tr.extra
+}
+
+// RoundTrip implements the RoundTripper interface.
+//
+// For higher-level HTTP client support (such as handling of cookies
+// and redirects), see Get, Post, and the Client type.
+func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) {
+	if req.URL == nil {
+		req.closeBody()
+		return nil, errors.New("http: nil Request.URL")
+	}
+	if req.Header == nil {
+		req.closeBody()
+		return nil, errors.New("http: nil Request.Header")
+	}
+	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
+		t.altMu.RLock()
+		var rt RoundTripper
+		if t.altProto != nil {
+			rt = t.altProto[req.URL.Scheme]
+		}
+		t.altMu.RUnlock()
+		if rt == nil {
+			req.closeBody()
+			return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
+		}
+		return rt.RoundTrip(req)
+	}
+	if req.URL.Host == "" {
+		req.closeBody()
+		return nil, errors.New("http: no Host in request URL")
+	}
+	treq := &transportRequest{Request: req}
+	cm, err := t.connectMethodForRequest(treq)
+	if err != nil {
+		req.closeBody()
+		return nil, err
+	}
+
+	// Get the cached or newly-created connection to either the
+	// host (for http or https), the http proxy, or the http proxy
+	// pre-CONNECTed to https server.  In any case, we'll be ready
+	// to send it requests.
+	pconn, err := t.getConn(req, cm)
+	if err != nil {
+		t.setReqCanceler(req, nil)
+		req.closeBody()
+		return nil, err
+	}
+
+	return pconn.roundTrip(treq)
+}
+
+// RegisterProtocol registers a new protocol with scheme.
+// The Transport will pass requests using the given scheme to rt.
+// It is rt's responsibility to simulate HTTP request semantics.
+//
+// RegisterProtocol can be used by other packages to provide
+// implementations of protocol schemes like "ftp" or "file".
+func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
+	if scheme == "http" || scheme == "https" {
+		panic("protocol " + scheme + " already registered")
+	}
+	t.altMu.Lock()
+	defer t.altMu.Unlock()
+	if t.altProto == nil {
+		t.altProto = make(map[string]RoundTripper)
+	}
+	if _, exists := t.altProto[scheme]; exists {
+		panic("protocol " + scheme + " already registered")
+	}
+	t.altProto[scheme] = rt
+}
+
+// CloseIdleConnections closes any connections which were previously
+// connected from previous requests but are now sitting idle in
+// a "keep-alive" state. It does not interrupt any connections currently
+// in use.
+func (t *Transport) CloseIdleConnections() {
+	t.idleMu.Lock()
+	m := t.idleConn
+	t.idleConn = nil
+	t.idleConnCh = nil
+	t.idleMu.Unlock()
+	for _, conns := range m {
+		for _, pconn := range conns {
+			pconn.close()
+		}
+	}
+}
+
+// CancelRequest cancels an in-flight request by closing its
+// connection.
+func (t *Transport) CancelRequest(req *Request) {
+	t.reqMu.Lock()
+	cancel := t.reqCanceler[req]
+	t.reqMu.Unlock()
+	if cancel != nil {
+		cancel()
+	}
+}
+
+//
+// Private implementation past this point.
+//
+
+var (
+	httpProxyEnv = &envOnce{
+		names: []string{"HTTP_PROXY", "http_proxy"},
+	}
+	noProxyEnv = &envOnce{
+		names: []string{"NO_PROXY", "no_proxy"},
+	}
+)
+
+// envOnce looks up an environment variable (optionally by multiple
+// names) once. It mitigates expensive lookups on some platforms
+// (e.g. Windows).
+type envOnce struct {
+	names []string
+	once  sync.Once
+	val   string
+}
+
+func (e *envOnce) Get() string {
+	e.once.Do(e.init)
+	return e.val
+}
+
+func (e *envOnce) init() {
+	for _, n := range e.names {
+		e.val = os.Getenv(n)
+		if e.val != "" {
+			return
+		}
+	}
+}
+
+// reset is used by tests
+func (e *envOnce) reset() {
+	e.once = sync.Once{}
+	e.val = ""
+}
+
+func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectMethod, err error) {
+	cm.targetScheme = treq.URL.Scheme
+	cm.targetAddr = canonicalAddr(treq.URL)
+	if t.Proxy != nil {
+		cm.proxyURL, err = t.Proxy(treq.Request)
+	}
+	return cm, nil
+}
+
+// proxyAuth returns the Proxy-Authorization header to set
+// on requests, if applicable.
+func (cm *connectMethod) proxyAuth() string {
+	if cm.proxyURL == nil {
+		return ""
+	}
+	if u := cm.proxyURL.User; u != nil {
+		username := u.Username()
+		password, _ := u.Password()
+		return "Basic " + basicAuth(username, password)
+	}
+	return ""
+}
+
+// putIdleConn adds pconn to the list of idle persistent connections awaiting
+// a new request.
+// If pconn is no longer needed or not in a good state, putIdleConn
+// returns false.
+func (t *Transport) putIdleConn(pconn *persistConn) bool {
+	if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
+		pconn.close()
+		return false
+	}
+	if pconn.isBroken() {
+		return false
+	}
+	key := pconn.cacheKey
+	max := t.MaxIdleConnsPerHost
+	if max == 0 {
+		max = DefaultMaxIdleConnsPerHost
+	}
+	t.idleMu.Lock()
+
+	waitingDialer := t.idleConnCh[key]
+	select {
+	case waitingDialer <- pconn:
+		// We're done with this pconn and somebody else is
+		// currently waiting for a conn of this type (they're
+		// actively dialing, but this conn is ready
+		// first). Chrome calls this socket late binding.  See
+		// https://insouciant.org/tech/connection-management-in-chromium/
+		t.idleMu.Unlock()
+		return true
+	default:
+		if waitingDialer != nil {
+			// They had populated this, but their dial won
+			// first, so we can clean up this map entry.
+			delete(t.idleConnCh, key)
+		}
+	}
+	if t.idleConn == nil {
+		t.idleConn = make(map[connectMethodKey][]*persistConn)
+	}
+	if len(t.idleConn[key]) >= max {
+		t.idleMu.Unlock()
+		pconn.close()
+		return false
+	}
+	for _, exist := range t.idleConn[key] {
+		if exist == pconn {
+			log.Fatalf("dup idle pconn %p in freelist", pconn)
+		}
+	}
+	t.idleConn[key] = append(t.idleConn[key], pconn)
+	t.idleMu.Unlock()
+	return true
+}
+
+// getIdleConnCh returns a channel to receive and return idle
+// persistent connection for the given connectMethod.
+// It may return nil, if persistent connections are not being used.
+func (t *Transport) getIdleConnCh(cm connectMethod) chan *persistConn {
+	if t.DisableKeepAlives {
+		return nil
+	}
+	key := cm.key()
+	t.idleMu.Lock()
+	defer t.idleMu.Unlock()
+	if t.idleConnCh == nil {
+		t.idleConnCh = make(map[connectMethodKey]chan *persistConn)
+	}
+	ch, ok := t.idleConnCh[key]
+	if !ok {
+		ch = make(chan *persistConn)
+		t.idleConnCh[key] = ch
+	}
+	return ch
+}
+
+func (t *Transport) getIdleConn(cm connectMethod) (pconn *persistConn) {
+	key := cm.key()
+	t.idleMu.Lock()
+	defer t.idleMu.Unlock()
+	if t.idleConn == nil {
+		return nil
+	}
+	for {
+		pconns, ok := t.idleConn[key]
+		if !ok {
+			return nil
+		}
+		if len(pconns) == 1 {
+			pconn = pconns[0]
+			delete(t.idleConn, key)
+		} else {
+			// 2 or more cached connections; pop last
+			// TODO: queue?
+			pconn = pconns[len(pconns)-1]
+			t.idleConn[key] = pconns[:len(pconns)-1]
+		}
+		if !pconn.isBroken() {
+			return
+		}
+	}
+}
+
+func (t *Transport) setReqCanceler(r *Request, fn func()) {
+	t.reqMu.Lock()
+	defer t.reqMu.Unlock()
+	if t.reqCanceler == nil {
+		t.reqCanceler = make(map[*Request]func())
+	}
+	if fn != nil {
+		t.reqCanceler[r] = fn
+	} else {
+		delete(t.reqCanceler, r)
+	}
+}
+
+func (t *Transport) dial(network, addr string) (c net.Conn, err error) {
+	if t.Dial != nil {
+		return t.Dial(network, addr)
+	}
+	return net.Dial(network, addr)
+}
+
+// getConn dials and creates a new persistConn to the target as
+// specified in the connectMethod.  This includes doing a proxy CONNECT
+// and/or setting up TLS.  If this doesn't return an error, the persistConn
+// is ready to write requests to.
+func (t *Transport) getConn(req *Request, cm connectMethod) (*persistConn, error) {
+	if pc := t.getIdleConn(cm); pc != nil {
+		return pc, nil
+	}
+
+	type dialRes struct {
+		pc  *persistConn
+		err error
+	}
+	dialc := make(chan dialRes)
+
+	handlePendingDial := func() {
+		if v := <-dialc; v.err == nil {
+			t.putIdleConn(v.pc)
+		}
+	}
+
+	cancelc := make(chan struct{})
+	t.setReqCanceler(req, func() { close(cancelc) })
+
+	go func() {
+		pc, err := t.dialConn(cm)
+		dialc <- dialRes{pc, err}
+	}()
+
+	idleConnCh := t.getIdleConnCh(cm)
+	select {
+	case v := <-dialc:
+		// Our dial finished.
+		return v.pc, v.err
+	case pc := <-idleConnCh:
+		// Another request finished first and its net.Conn
+		// became available before our dial. Or somebody
+		// else's dial that they didn't use.
+		// But our dial is still going, so give it away
+		// when it finishes:
+		go handlePendingDial()
+		return pc, nil
+	case <-cancelc:
+		go handlePendingDial()
+		return nil, errors.New("net/http: request canceled while waiting for connection")
+	}
+}
+
+func (t *Transport) dialConn(cm connectMethod) (*persistConn, error) {
+	conn, err := t.dial("tcp", cm.addr())
+	if err != nil {
+		if cm.proxyURL != nil {
+			err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err)
+		}
+		return nil, err
+	}
+
+	pa := cm.proxyAuth()
+
+	pconn := &persistConn{
+		t:          t,
+		cacheKey:   cm.key(),
+		conn:       conn,
+		reqch:      make(chan requestAndChan, 1),
+		writech:    make(chan writeRequest, 1),
+		closech:    make(chan struct{}),
+		writeErrCh: make(chan error, 1),
+	}
+
+	switch {
+	case cm.proxyURL == nil:
+		// Do nothing.
+	case cm.targetScheme == "http":
+		pconn.isProxy = true
+		if pa != "" {
+			pconn.mutateHeaderFunc = func(h Header) {
+				h.Set("Proxy-Authorization", pa)
+			}
+		}
+	case cm.targetScheme == "https":
+		connectReq := &Request{
+			Method: "CONNECT",
+			URL:    &url.URL{Opaque: cm.targetAddr},
+			Host:   cm.targetAddr,
+			Header: make(Header),
+		}
+		if pa != "" {
+			connectReq.Header.Set("Proxy-Authorization", pa)
+		}
+		connectReq.Write(conn)
+
+		// Read response.
+		// Okay to use and discard buffered reader here, because
+		// TLS server will not speak until spoken to.
+		br := bufio.NewReader(conn)
+		resp, err := ReadResponse(br, connectReq)
+		if err != nil {
+			conn.Close()
+			return nil, err
+		}
+		if resp.StatusCode != 200 {
+			f := strings.SplitN(resp.Status, " ", 2)
+			conn.Close()
+			return nil, errors.New(f[1])
+		}
+	}
+
+	if cm.targetScheme == "https" {
+		// Initiate TLS and check remote host name against certificate.
+		cfg := t.TLSClientConfig
+		if cfg == nil || cfg.ServerName == "" {
+			host := cm.tlsHost()
+			if cfg == nil {
+				cfg = &tls.Config{ServerName: host}
+			} else {
+				clone := *cfg // shallow clone
+				clone.ServerName = host
+				cfg = &clone
+			}
+		}
+		plainConn := conn
+		tlsConn := tls.Client(plainConn, cfg)
+		errc := make(chan error, 2)
+		var timer *time.Timer // for canceling TLS handshake
+		if d := t.TLSHandshakeTimeout; d != 0 {
+			timer = time.AfterFunc(d, func() {
+				errc <- tlsHandshakeTimeoutError{}
+			})
+		}
+		go func() {
+			err := tlsConn.Handshake()
+			if timer != nil {
+				timer.Stop()
+			}
+			errc <- err
+		}()
+		if err := <-errc; err != nil {
+			plainConn.Close()
+			return nil, err
+		}
+		if !cfg.InsecureSkipVerify {
+			if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
+				plainConn.Close()
+				return nil, err
+			}
+		}
+		cs := tlsConn.ConnectionState()
+		pconn.tlsState = &cs
+		pconn.conn = tlsConn
+	}
+
+	pconn.br = bufio.NewReader(noteEOFReader{pconn.conn, &pconn.sawEOF})
+	pconn.bw = bufio.NewWriter(pconn.conn)
+	go pconn.readLoop()
+	go pconn.writeLoop()
+	return pconn, nil
+}
+
+// useProxy returns true if requests to addr should use a proxy,
+// according to the NO_PROXY or no_proxy environment variable.
+// addr is always a canonicalAddr with a host and port.
+func useProxy(addr string) bool {
+	if len(addr) == 0 {
+		return true
+	}
+	host, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		return false
+	}
+	if host == "localhost" {
+		return false
+	}
+	if ip := net.ParseIP(host); ip != nil {
+		if ip.IsLoopback() {
+			return false
+		}
+	}
+
+	no_proxy := noProxyEnv.Get()
+	if no_proxy == "*" {
+		return false
+	}
+
+	addr = strings.ToLower(strings.TrimSpace(addr))
+	if hasPort(addr) {
+		addr = addr[:strings.LastIndex(addr, ":")]
+	}
+
+	for _, p := range strings.Split(no_proxy, ",") {
+		p = strings.ToLower(strings.TrimSpace(p))
+		if len(p) == 0 {
+			continue
+		}
+		if hasPort(p) {
+			p = p[:strings.LastIndex(p, ":")]
+		}
+		if addr == p {
+			return false
+		}
+		if p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:]) {
+			// no_proxy ".foo.com" matches "bar.foo.com" or "foo.com"
+			return false
+		}
+		if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' {
+			// no_proxy "foo.com" matches "bar.foo.com"
+			return false
+		}
+	}
+	return true
+}
+
+// connectMethod is the map key (in its String form) for keeping persistent
+// TCP connections alive for subsequent HTTP requests.
+//
+// A connect method may be of the following types:
+//
+// Cache key form                Description
+// -----------------             -------------------------
+// |http|foo.com                 http directly to server, no proxy
+// |https|foo.com                https directly to server, no proxy
+// http://proxy.com|https|foo.com  http to proxy, then CONNECT to foo.com
+// http://proxy.com|http           http to proxy, http to anywhere after that
+//
+// Note: no support to https to the proxy yet.
+//
+type connectMethod struct {
+	proxyURL     *url.URL // nil for no proxy, else full proxy URL
+	targetScheme string   // "http" or "https"
+	targetAddr   string   // Not used if proxy + http targetScheme (4th example in table)
+}
+
+func (cm *connectMethod) key() connectMethodKey {
+	proxyStr := ""
+	targetAddr := cm.targetAddr
+	if cm.proxyURL != nil {
+		proxyStr = cm.proxyURL.String()
+		if cm.targetScheme == "http" {
+			targetAddr = ""
+		}
+	}
+	return connectMethodKey{
+		proxy:  proxyStr,
+		scheme: cm.targetScheme,
+		addr:   targetAddr,
+	}
+}
+
+// addr returns the first hop "host:port" to which we need to TCP connect.
+func (cm *connectMethod) addr() string {
+	if cm.proxyURL != nil {
+		return canonicalAddr(cm.proxyURL)
+	}
+	return cm.targetAddr
+}
+
+// tlsHost returns the host name to match against the peer's
+// TLS certificate.
+func (cm *connectMethod) tlsHost() string {
+	h := cm.targetAddr
+	if hasPort(h) {
+		h = h[:strings.LastIndex(h, ":")]
+	}
+	return h
+}
+
+// connectMethodKey is the map key version of connectMethod, with a
+// stringified proxy URL (or the empty string) instead of a pointer to
+// a URL.
+type connectMethodKey struct {
+	proxy, scheme, addr string
+}
+
+func (k connectMethodKey) String() string {
+	// Only used by tests.
+	return fmt.Sprintf("%s|%s|%s", k.proxy, k.scheme, k.addr)
+}
+
+// persistConn wraps a connection, usually a persistent one
+// (but may be used for non-keep-alive requests as well)
+type persistConn struct {
+	t        *Transport
+	cacheKey connectMethodKey
+	conn     net.Conn
+	tlsState *tls.ConnectionState
+	br       *bufio.Reader       // from conn
+	sawEOF   bool                // whether we've seen EOF from conn; owned by readLoop
+	bw       *bufio.Writer       // to conn
+	reqch    chan requestAndChan // written by roundTrip; read by readLoop
+	writech  chan writeRequest   // written by roundTrip; read by writeLoop
+	closech  chan struct{}       // closed when conn closed
+	isProxy  bool
+	// writeErrCh passes the request write error (usually nil)
+	// from the writeLoop goroutine to the readLoop which passes
+	// it off to the res.Body reader, which then uses it to decide
+	// whether or not a connection can be reused. Issue 7569.
+	writeErrCh chan error
+
+	lk                   sync.Mutex // guards following fields
+	numExpectedResponses int
+	closed               bool // whether conn has been closed
+	broken               bool // an error has happened on this connection; marked broken so it's not reused.
+	// mutateHeaderFunc is an optional func to modify extra
+	// headers on each outbound request before it's written. (the
+	// original Request given to RoundTrip is not modified)
+	mutateHeaderFunc func(Header)
+}
+
+// isBroken reports whether this connection is in a known broken state.
+func (pc *persistConn) isBroken() bool {
+	pc.lk.Lock()
+	b := pc.broken
+	pc.lk.Unlock()
+	return b
+}
+
+func (pc *persistConn) cancelRequest() {
+	pc.conn.Close()
+}
+
+var remoteSideClosedFunc func(error) bool // or nil to use default
+
+func remoteSideClosed(err error) bool {
+	if err == io.EOF {
+		return true
+	}
+	if remoteSideClosedFunc != nil {
+		return remoteSideClosedFunc(err)
+	}
+	return false
+}
+
+func (pc *persistConn) readLoop() {
+	alive := true
+
+	for alive {
+		pb, err := pc.br.Peek(1)
+
+		pc.lk.Lock()
+		if pc.numExpectedResponses == 0 {
+			if !pc.closed {
+				pc.closeLocked()
+				if len(pb) > 0 {
+					log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
+						string(pb), err)
+				}
+			}
+			pc.lk.Unlock()
+			return
+		}
+		pc.lk.Unlock()
+
+		rc := <-pc.reqch
+
+		var resp *Response
+		if err == nil {
+			resp, err = ReadResponse(pc.br, rc.req)
+			if err == nil && resp.StatusCode == 100 {
+				// Skip any 100-continue for now.
+				// TODO(bradfitz): if rc.req had "Expect: 100-continue",
+				// actually block the request body write and signal the
+				// writeLoop now to begin sending it. (Issue 2184) For now we
+				// eat it, since we're never expecting one.
+				resp, err = ReadResponse(pc.br, rc.req)
+			}
+		}
+
+		if resp != nil {
+			resp.TLS = pc.tlsState
+		}
+
+		hasBody := resp != nil && rc.req.Method != "HEAD" && resp.ContentLength != 0
+
+		if err != nil {
+			pc.close()
+		} else {
+			if rc.addedGzip && hasBody && resp.Header.Get("Content-Encoding") == "gzip" {
+				resp.Header.Del("Content-Encoding")
+				resp.Header.Del("Content-Length")
+				resp.ContentLength = -1
+				resp.Body = &gzipReader{body: resp.Body}
+			}
+			resp.Body = &bodyEOFSignal{body: resp.Body}
+		}
+
+		if err != nil || resp.Close || rc.req.Close || resp.StatusCode <= 199 {
+			// Don't do keep-alive on error if either party requested a close
+			// or we get an unexpected informational (1xx) response.
+			// StatusCode 100 is already handled above.
+			alive = false
+		}
+
+		var waitForBodyRead chan bool
+		if hasBody {
+			waitForBodyRead = make(chan bool, 2)
+			resp.Body.(*bodyEOFSignal).earlyCloseFn = func() error {
+				// Sending false here sets alive to
+				// false and closes the connection
+				// below.
+				waitForBodyRead <- false
+				return nil
+			}
+			resp.Body.(*bodyEOFSignal).fn = func(err error) {
+				waitForBodyRead <- alive &&
+					err == nil &&
+					!pc.sawEOF &&
+					pc.wroteRequest() &&
+					pc.t.putIdleConn(pc)
+			}
+		}
+
+		if alive && !hasBody {
+			alive = !pc.sawEOF &&
+				pc.wroteRequest() &&
+				pc.t.putIdleConn(pc)
+		}
+
+		rc.ch <- responseAndError{resp, err}
+
+		// Wait for the just-returned response body to be fully consumed
+		// before we race and peek on the underlying bufio reader.
+		if waitForBodyRead != nil {
+			select {
+			case alive = <-waitForBodyRead:
+			case <-pc.closech:
+				alive = false
+			}
+		}
+
+		pc.t.setReqCanceler(rc.req, nil)
+
+		if !alive {
+			pc.close()
+		}
+	}
+}
+
+func (pc *persistConn) writeLoop() {
+	for {
+		select {
+		case wr := <-pc.writech:
+			if pc.isBroken() {
+				wr.ch <- errors.New("http: can't write HTTP request on broken connection")
+				continue
+			}
+			err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra)
+			if err == nil {
+				err = pc.bw.Flush()
+			}
+			if err != nil {
+				pc.markBroken()
+				wr.req.Request.closeBody()
+			}
+			pc.writeErrCh <- err // to the body reader, which might recycle us
+			wr.ch <- err         // to the roundTrip function
+		case <-pc.closech:
+			return
+		}
+	}
+}
+
+// wroteRequest is a check before recycling a connection that the previous write
+// (from writeLoop above) happened and was successful.
+func (pc *persistConn) wroteRequest() bool {
+	select {
+	case err := <-pc.writeErrCh:
+		// Common case: the write happened well before the response, so
+		// avoid creating a timer.
+		return err == nil
+	default:
+		// Rare case: the request was written in writeLoop above but
+		// before it could send to pc.writeErrCh, the reader read it
+		// all, processed it, and called us here. In this case, give the
+		// write goroutine a bit of time to finish its send.
+		//
+		// Less rare case: We also get here in the legitimate case of
+		// Issue 7569, where the writer is still writing (or stalled),
+		// but the server has already replied. In this case, we don't
+		// want to wait too long, and we want to return false so this
+		// connection isn't re-used.
+		select {
+		case err := <-pc.writeErrCh:
+			return err == nil
+		case <-time.After(50 * time.Millisecond):
+			return false
+		}
+	}
+}
+
+type responseAndError struct {
+	res *Response
+	err error
+}
+
+type requestAndChan struct {
+	req *Request
+	ch  chan responseAndError
+
+	// did the Transport (as opposed to the client code) add an
+	// Accept-Encoding gzip header? only if it we set it do
+	// we transparently decode the gzip.
+	addedGzip bool
+}
+
+// A writeRequest is sent by the readLoop's goroutine to the
+// writeLoop's goroutine to write a request while the read loop
+// concurrently waits on both the write response and the server's
+// reply.
+type writeRequest struct {
+	req *transportRequest
+	ch  chan<- error
+}
+
+type httpError struct {
+	err     string
+	timeout bool
+}
+
+func (e *httpError) Error() string   { return e.err }
+func (e *httpError) Timeout() bool   { return e.timeout }
+func (e *httpError) Temporary() bool { return true }
+
+var errTimeout error = &httpError{err: "net/http: timeout awaiting response headers", timeout: true}
+var errClosed error = &httpError{err: "net/http: transport closed before response was received"}
+
+func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) {
+	pc.t.setReqCanceler(req.Request, pc.cancelRequest)
+	pc.lk.Lock()
+	pc.numExpectedResponses++
+	headerFn := pc.mutateHeaderFunc
+	pc.lk.Unlock()
+
+	if headerFn != nil {
+		headerFn(req.extraHeaders())
+	}
+
+	// Ask for a compressed version if the caller didn't set their
+	// own value for Accept-Encoding. We only attempted to
+	// uncompress the gzip stream if we were the layer that
+	// requested it.
+	requestedGzip := false
+	if !pc.t.DisableCompression && req.Header.Get("Accept-Encoding") == "" && req.Method != "HEAD" {
+		// Request gzip only, not deflate. Deflate is ambiguous and
+		// not as universally supported anyway.
+		// See: http://www.gzip.org/zlib/zlib_faq.html#faq38
+		//
+		// Note that we don't request this for HEAD requests,
+		// due to a bug in nginx:
+		//   http://trac.nginx.org/nginx/ticket/358
+		//   http://golang.org/issue/5522
+		requestedGzip = true
+		req.extraHeaders().Set("Accept-Encoding", "gzip")
+	}
+
+	// Write the request concurrently with waiting for a response,
+	// in case the server decides to reply before reading our full
+	// request body.
+	writeErrCh := make(chan error, 1)
+	pc.writech <- writeRequest{req, writeErrCh}
+
+	resc := make(chan responseAndError, 1)
+	pc.reqch <- requestAndChan{req.Request, resc, requestedGzip}
+
+	var re responseAndError
+	var pconnDeadCh = pc.closech
+	var failTicker <-chan time.Time
+	var respHeaderTimer <-chan time.Time
+WaitResponse:
+	for {
+		select {
+		case err := <-writeErrCh:
+			if err != nil {
+				re = responseAndError{nil, err}
+				pc.close()
+				break WaitResponse
+			}
+			if d := pc.t.ResponseHeaderTimeout; d > 0 {
+				respHeaderTimer = time.After(d)
+			}
+		case <-pconnDeadCh:
+			// The persist connection is dead. This shouldn't
+			// usually happen (only with Connection: close responses
+			// with no response bodies), but if it does happen it
+			// means either a) the remote server hung up on us
+			// prematurely, or b) the readLoop sent us a response &
+			// closed its closech at roughly the same time, and we
+			// selected this case first, in which case a response
+			// might still be coming soon.
+			//
+			// We can't avoid the select race in b) by using a unbuffered
+			// resc channel instead, because then goroutines can
+			// leak if we exit due to other errors.
+			pconnDeadCh = nil                               // avoid spinning
+			failTicker = time.After(100 * time.Millisecond) // arbitrary time to wait for resc
+		case <-failTicker:
+			re = responseAndError{err: errClosed}
+			break WaitResponse
+		case <-respHeaderTimer:
+			pc.close()
+			re = responseAndError{err: errTimeout}
+			break WaitResponse
+		case re = <-resc:
+			break WaitResponse
+		}
+	}
+
+	pc.lk.Lock()
+	pc.numExpectedResponses--
+	pc.lk.Unlock()
+
+	if re.err != nil {
+		pc.t.setReqCanceler(req.Request, nil)
+	}
+	return re.res, re.err
+}
+
+// markBroken marks a connection as broken (so it's not reused).
+// It differs from close in that it doesn't close the underlying
+// connection for use when it's still being read.
+func (pc *persistConn) markBroken() {
+	pc.lk.Lock()
+	defer pc.lk.Unlock()
+	pc.broken = true
+}
+
+func (pc *persistConn) close() {
+	pc.lk.Lock()
+	defer pc.lk.Unlock()
+	pc.closeLocked()
+}
+
+func (pc *persistConn) closeLocked() {
+	pc.broken = true
+	if !pc.closed {
+		pc.conn.Close()
+		pc.closed = true
+		close(pc.closech)
+	}
+	pc.mutateHeaderFunc = nil
+}
+
+var portMap = map[string]string{
+	"http":  "80",
+	"https": "443",
+}
+
+// canonicalAddr returns url.Host but always with a ":port" suffix
+func canonicalAddr(url *url.URL) string {
+	addr := url.Host
+	if !hasPort(addr) {
+		return addr + ":" + portMap[url.Scheme]
+	}
+	return addr
+}
+
+// bodyEOFSignal wraps a ReadCloser but runs fn (if non-nil) at most
+// once, right before its final (error-producing) Read or Close call
+// returns. If earlyCloseFn is non-nil and Close is called before
+// io.EOF is seen, earlyCloseFn is called instead of fn, and its
+// return value is the return value from Close.
+type bodyEOFSignal struct {
+	body         io.ReadCloser
+	mu           sync.Mutex   // guards following 4 fields
+	closed       bool         // whether Close has been called
+	rerr         error        // sticky Read error
+	fn           func(error)  // error will be nil on Read io.EOF
+	earlyCloseFn func() error // optional alt Close func used if io.EOF not seen
+}
+
+func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
+	es.mu.Lock()
+	closed, rerr := es.closed, es.rerr
+	es.mu.Unlock()
+	if closed {
+		return 0, errors.New("http: read on closed response body")
+	}
+	if rerr != nil {
+		return 0, rerr
+	}
+
+	n, err = es.body.Read(p)
+	if err != nil {
+		es.mu.Lock()
+		defer es.mu.Unlock()
+		if es.rerr == nil {
+			es.rerr = err
+		}
+		es.condfn(err)
+	}
+	return
+}
+
+func (es *bodyEOFSignal) Close() error {
+	es.mu.Lock()
+	defer es.mu.Unlock()
+	if es.closed {
+		return nil
+	}
+	es.closed = true
+	if es.earlyCloseFn != nil && es.rerr != io.EOF {
+		return es.earlyCloseFn()
+	}
+	err := es.body.Close()
+	es.condfn(err)
+	return err
+}
+
+// caller must hold es.mu.
+func (es *bodyEOFSignal) condfn(err error) {
+	if es.fn == nil {
+		return
+	}
+	if err == io.EOF {
+		err = nil
+	}
+	es.fn(err)
+	es.fn = nil
+}
+
+// gzipReader wraps a response body so it can lazily
+// call gzip.NewReader on the first call to Read
+type gzipReader struct {
+	body io.ReadCloser // underlying Response.Body
+	zr   io.Reader     // lazily-initialized gzip reader
+}
+
+func (gz *gzipReader) Read(p []byte) (n int, err error) {
+	if gz.zr == nil {
+		gz.zr, err = gzip.NewReader(gz.body)
+		if err != nil {
+			return 0, err
+		}
+	}
+	return gz.zr.Read(p)
+}
+
+func (gz *gzipReader) Close() error {
+	return gz.body.Close()
+}
+
+type readerAndCloser struct {
+	io.Reader
+	io.Closer
+}
+
+type tlsHandshakeTimeoutError struct{}
+
+func (tlsHandshakeTimeoutError) Timeout() bool   { return true }
+func (tlsHandshakeTimeoutError) Temporary() bool { return true }
+func (tlsHandshakeTimeoutError) Error() string   { return "net/http: TLS handshake timeout" }
+
+type noteEOFReader struct {
+	r      io.Reader
+	sawEOF *bool
+}
+
+func (nr noteEOFReader) Read(p []byte) (n int, err error) {
+	n, err = nr.r.Read(p)
+	if err == io.EOF {
+		*nr.sawEOF = true
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/transport_test.go b/third_party/gofrontend/libgo/go/net/http/transport_test.go
new file mode 100644
index 0000000..964ca0f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/transport_test.go
@@ -0,0 +1,2173 @@
+// 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.
+
+// Tests for transport.go
+
+package http_test
+
+import (
+	"bufio"
+	"bytes"
+	"compress/gzip"
+	"crypto/rand"
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/http"
+	. "net/http"
+	"net/http/httptest"
+	"net/url"
+	"os"
+	"runtime"
+	"strconv"
+	"strings"
+	"sync"
+	"testing"
+	"time"
+)
+
+// TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close
+//       and then verify that the final 2 responses get errors back.
+
+// hostPortHandler writes back the client's "host:port".
+var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
+	if r.FormValue("close") == "true" {
+		w.Header().Set("Connection", "close")
+	}
+	w.Write([]byte(r.RemoteAddr))
+})
+
+// testCloseConn is a net.Conn tracked by a testConnSet.
+type testCloseConn struct {
+	net.Conn
+	set *testConnSet
+}
+
+func (c *testCloseConn) Close() error {
+	c.set.remove(c)
+	return c.Conn.Close()
+}
+
+// testConnSet tracks a set of TCP connections and whether they've
+// been closed.
+type testConnSet struct {
+	t      *testing.T
+	mu     sync.Mutex // guards closed and list
+	closed map[net.Conn]bool
+	list   []net.Conn // in order created
+}
+
+func (tcs *testConnSet) insert(c net.Conn) {
+	tcs.mu.Lock()
+	defer tcs.mu.Unlock()
+	tcs.closed[c] = false
+	tcs.list = append(tcs.list, c)
+}
+
+func (tcs *testConnSet) remove(c net.Conn) {
+	tcs.mu.Lock()
+	defer tcs.mu.Unlock()
+	tcs.closed[c] = true
+}
+
+// some tests use this to manage raw tcp connections for later inspection
+func makeTestDial(t *testing.T) (*testConnSet, func(n, addr string) (net.Conn, error)) {
+	connSet := &testConnSet{
+		t:      t,
+		closed: make(map[net.Conn]bool),
+	}
+	dial := func(n, addr string) (net.Conn, error) {
+		c, err := net.Dial(n, addr)
+		if err != nil {
+			return nil, err
+		}
+		tc := &testCloseConn{c, connSet}
+		connSet.insert(tc)
+		return tc, nil
+	}
+	return connSet, dial
+}
+
+func (tcs *testConnSet) check(t *testing.T) {
+	tcs.mu.Lock()
+	defer tcs.mu.Unlock()
+	for i := 4; i >= 0; i-- {
+		for i, c := range tcs.list {
+			if tcs.closed[c] {
+				continue
+			}
+			if i != 0 {
+				tcs.mu.Unlock()
+				time.Sleep(50 * time.Millisecond)
+				tcs.mu.Lock()
+				continue
+			}
+			t.Errorf("TCP connection #%d, %p (of %d total) was not closed", i+1, c, len(tcs.list))
+		}
+	}
+}
+
+// Two subsequent requests and verify their response is the same.
+// The response from the server is our own IP:port
+func TestTransportKeepAlives(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(hostPortHandler)
+	defer ts.Close()
+
+	for _, disableKeepAlive := range []bool{false, true} {
+		tr := &Transport{DisableKeepAlives: disableKeepAlive}
+		defer tr.CloseIdleConnections()
+		c := &Client{Transport: tr}
+
+		fetch := func(n int) string {
+			res, err := c.Get(ts.URL)
+			if err != nil {
+				t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err)
+			}
+			body, err := ioutil.ReadAll(res.Body)
+			if err != nil {
+				t.Fatalf("error in disableKeepAlive=%v, req #%d, ReadAll: %v", disableKeepAlive, n, err)
+			}
+			return string(body)
+		}
+
+		body1 := fetch(1)
+		body2 := fetch(2)
+
+		bodiesDiffer := body1 != body2
+		if bodiesDiffer != disableKeepAlive {
+			t.Errorf("error in disableKeepAlive=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
+				disableKeepAlive, bodiesDiffer, body1, body2)
+		}
+	}
+}
+
+func TestTransportConnectionCloseOnResponse(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(hostPortHandler)
+	defer ts.Close()
+
+	connSet, testDial := makeTestDial(t)
+
+	for _, connectionClose := range []bool{false, true} {
+		tr := &Transport{
+			Dial: testDial,
+		}
+		c := &Client{Transport: tr}
+
+		fetch := func(n int) string {
+			req := new(Request)
+			var err error
+			req.URL, err = url.Parse(ts.URL + fmt.Sprintf("/?close=%v", connectionClose))
+			if err != nil {
+				t.Fatalf("URL parse error: %v", err)
+			}
+			req.Method = "GET"
+			req.Proto = "HTTP/1.1"
+			req.ProtoMajor = 1
+			req.ProtoMinor = 1
+
+			res, err := c.Do(req)
+			if err != nil {
+				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
+			}
+			defer res.Body.Close()
+			body, err := ioutil.ReadAll(res.Body)
+			if err != nil {
+				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
+			}
+			return string(body)
+		}
+
+		body1 := fetch(1)
+		body2 := fetch(2)
+		bodiesDiffer := body1 != body2
+		if bodiesDiffer != connectionClose {
+			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
+				connectionClose, bodiesDiffer, body1, body2)
+		}
+
+		tr.CloseIdleConnections()
+	}
+
+	connSet.check(t)
+}
+
+func TestTransportConnectionCloseOnRequest(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(hostPortHandler)
+	defer ts.Close()
+
+	connSet, testDial := makeTestDial(t)
+
+	for _, connectionClose := range []bool{false, true} {
+		tr := &Transport{
+			Dial: testDial,
+		}
+		c := &Client{Transport: tr}
+
+		fetch := func(n int) string {
+			req := new(Request)
+			var err error
+			req.URL, err = url.Parse(ts.URL)
+			if err != nil {
+				t.Fatalf("URL parse error: %v", err)
+			}
+			req.Method = "GET"
+			req.Proto = "HTTP/1.1"
+			req.ProtoMajor = 1
+			req.ProtoMinor = 1
+			req.Close = connectionClose
+
+			res, err := c.Do(req)
+			if err != nil {
+				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
+			}
+			body, err := ioutil.ReadAll(res.Body)
+			if err != nil {
+				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
+			}
+			return string(body)
+		}
+
+		body1 := fetch(1)
+		body2 := fetch(2)
+		bodiesDiffer := body1 != body2
+		if bodiesDiffer != connectionClose {
+			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
+				connectionClose, bodiesDiffer, body1, body2)
+		}
+
+		tr.CloseIdleConnections()
+	}
+
+	connSet.check(t)
+}
+
+func TestTransportIdleCacheKeys(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(hostPortHandler)
+	defer ts.Close()
+
+	tr := &Transport{DisableKeepAlives: false}
+	c := &Client{Transport: tr}
+
+	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
+		t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
+	}
+
+	resp, err := c.Get(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	ioutil.ReadAll(resp.Body)
+
+	keys := tr.IdleConnKeysForTesting()
+	if e, g := 1, len(keys); e != g {
+		t.Fatalf("After Get expected %d idle conn cache keys; got %d", e, g)
+	}
+
+	if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e {
+		t.Errorf("Expected idle cache key %q; got %q", e, keys[0])
+	}
+
+	tr.CloseIdleConnections()
+	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
+		t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
+	}
+}
+
+// Tests that the HTTP transport re-uses connections when a client
+// reads to the end of a response Body without closing it.
+func TestTransportReadToEndReusesConn(t *testing.T) {
+	defer afterTest(t)
+	const msg = "foobar"
+
+	var addrSeen map[string]int
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		addrSeen[r.RemoteAddr]++
+		if r.URL.Path == "/chunked/" {
+			w.WriteHeader(200)
+			w.(http.Flusher).Flush()
+		} else {
+			w.Header().Set("Content-Type", strconv.Itoa(len(msg)))
+			w.WriteHeader(200)
+		}
+		w.Write([]byte(msg))
+	}))
+	defer ts.Close()
+
+	buf := make([]byte, len(msg))
+
+	for pi, path := range []string{"/content-length/", "/chunked/"} {
+		wantLen := []int{len(msg), -1}[pi]
+		addrSeen = make(map[string]int)
+		for i := 0; i < 3; i++ {
+			res, err := http.Get(ts.URL + path)
+			if err != nil {
+				t.Errorf("Get %s: %v", path, err)
+				continue
+			}
+			// We want to close this body eventually (before the
+			// defer afterTest at top runs), but not before the
+			// len(addrSeen) check at the bottom of this test,
+			// since Closing this early in the loop would risk
+			// making connections be re-used for the wrong reason.
+			defer res.Body.Close()
+
+			if res.ContentLength != int64(wantLen) {
+				t.Errorf("%s res.ContentLength = %d; want %d", path, res.ContentLength, wantLen)
+			}
+			n, err := res.Body.Read(buf)
+			if n != len(msg) || err != io.EOF {
+				t.Errorf("%s Read = %v, %v; want %d, EOF", path, n, err, len(msg))
+			}
+		}
+		if len(addrSeen) != 1 {
+			t.Errorf("for %s, server saw %d distinct client addresses; want 1", path, len(addrSeen))
+		}
+	}
+}
+
+func TestTransportMaxPerHostIdleConns(t *testing.T) {
+	defer afterTest(t)
+	resch := make(chan string)
+	gotReq := make(chan bool)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		gotReq <- true
+		msg := <-resch
+		_, err := w.Write([]byte(msg))
+		if err != nil {
+			t.Fatalf("Write: %v", err)
+		}
+	}))
+	defer ts.Close()
+	maxIdleConns := 2
+	tr := &Transport{DisableKeepAlives: false, MaxIdleConnsPerHost: maxIdleConns}
+	c := &Client{Transport: tr}
+
+	// Start 3 outstanding requests and wait for the server to get them.
+	// Their responses will hang until we write to resch, though.
+	donech := make(chan bool)
+	doReq := func() {
+		resp, err := c.Get(ts.URL)
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		if _, err := ioutil.ReadAll(resp.Body); err != nil {
+			t.Errorf("ReadAll: %v", err)
+			return
+		}
+		donech <- true
+	}
+	go doReq()
+	<-gotReq
+	go doReq()
+	<-gotReq
+	go doReq()
+	<-gotReq
+
+	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
+		t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g)
+	}
+
+	resch <- "res1"
+	<-donech
+	keys := tr.IdleConnKeysForTesting()
+	if e, g := 1, len(keys); e != g {
+		t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g)
+	}
+	cacheKey := "|http|" + ts.Listener.Addr().String()
+	if keys[0] != cacheKey {
+		t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0])
+	}
+	if e, g := 1, tr.IdleConnCountForTesting(cacheKey); e != g {
+		t.Errorf("after first response, expected %d idle conns; got %d", e, g)
+	}
+
+	resch <- "res2"
+	<-donech
+	if e, g := 2, tr.IdleConnCountForTesting(cacheKey); e != g {
+		t.Errorf("after second response, expected %d idle conns; got %d", e, g)
+	}
+
+	resch <- "res3"
+	<-donech
+	if e, g := maxIdleConns, tr.IdleConnCountForTesting(cacheKey); e != g {
+		t.Errorf("after third response, still expected %d idle conns; got %d", e, g)
+	}
+}
+
+func TestTransportServerClosingUnexpectedly(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(hostPortHandler)
+	defer ts.Close()
+
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+
+	fetch := func(n, retries int) string {
+		condFatalf := func(format string, arg ...interface{}) {
+			if retries <= 0 {
+				t.Fatalf(format, arg...)
+			}
+			t.Logf("retrying shortly after expected error: "+format, arg...)
+			time.Sleep(time.Second / time.Duration(retries))
+		}
+		for retries >= 0 {
+			retries--
+			res, err := c.Get(ts.URL)
+			if err != nil {
+				condFatalf("error in req #%d, GET: %v", n, err)
+				continue
+			}
+			body, err := ioutil.ReadAll(res.Body)
+			if err != nil {
+				condFatalf("error in req #%d, ReadAll: %v", n, err)
+				continue
+			}
+			res.Body.Close()
+			return string(body)
+		}
+		panic("unreachable")
+	}
+
+	body1 := fetch(1, 0)
+	body2 := fetch(2, 0)
+
+	ts.CloseClientConnections() // surprise!
+
+	// This test has an expected race. Sleeping for 25 ms prevents
+	// it on most fast machines, causing the next fetch() call to
+	// succeed quickly.  But if we do get errors, fetch() will retry 5
+	// times with some delays between.
+	time.Sleep(25 * time.Millisecond)
+
+	body3 := fetch(3, 5)
+
+	if body1 != body2 {
+		t.Errorf("expected body1 and body2 to be equal")
+	}
+	if body2 == body3 {
+		t.Errorf("expected body2 and body3 to be different")
+	}
+}
+
+// Test for http://golang.org/issue/2616 (appropriate issue number)
+// This fails pretty reliably with GOMAXPROCS=100 or something high.
+func TestStressSurpriseServerCloses(t *testing.T) {
+	defer afterTest(t)
+	if testing.Short() {
+		t.Skip("skipping test in short mode")
+	}
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Length", "5")
+		w.Header().Set("Content-Type", "text/plain")
+		w.Write([]byte("Hello"))
+		w.(Flusher).Flush()
+		conn, buf, _ := w.(Hijacker).Hijack()
+		buf.Flush()
+		conn.Close()
+	}))
+	defer ts.Close()
+
+	tr := &Transport{DisableKeepAlives: false}
+	c := &Client{Transport: tr}
+
+	// Do a bunch of traffic from different goroutines. Send to activityc
+	// after each request completes, regardless of whether it failed.
+	const (
+		numClients    = 50
+		reqsPerClient = 250
+	)
+	activityc := make(chan bool)
+	for i := 0; i < numClients; i++ {
+		go func() {
+			for i := 0; i < reqsPerClient; i++ {
+				res, err := c.Get(ts.URL)
+				if err == nil {
+					// We expect errors since the server is
+					// hanging up on us after telling us to
+					// send more requests, so we don't
+					// actually care what the error is.
+					// But we want to close the body in cases
+					// where we won the race.
+					res.Body.Close()
+				}
+				activityc <- true
+			}
+		}()
+	}
+
+	// Make sure all the request come back, one way or another.
+	for i := 0; i < numClients*reqsPerClient; i++ {
+		select {
+		case <-activityc:
+		case <-time.After(5 * time.Second):
+			t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile")
+		}
+	}
+}
+
+// TestTransportHeadResponses verifies that we deal with Content-Lengths
+// with no bodies properly
+func TestTransportHeadResponses(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.Method != "HEAD" {
+			panic("expected HEAD; got " + r.Method)
+		}
+		w.Header().Set("Content-Length", "123")
+		w.WriteHeader(200)
+	}))
+	defer ts.Close()
+
+	tr := &Transport{DisableKeepAlives: false}
+	c := &Client{Transport: tr}
+	for i := 0; i < 2; i++ {
+		res, err := c.Head(ts.URL)
+		if err != nil {
+			t.Errorf("error on loop %d: %v", i, err)
+			continue
+		}
+		if e, g := "123", res.Header.Get("Content-Length"); e != g {
+			t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g)
+		}
+		if e, g := int64(123), res.ContentLength; e != g {
+			t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g)
+		}
+		if all, err := ioutil.ReadAll(res.Body); err != nil {
+			t.Errorf("loop %d: Body ReadAll: %v", i, err)
+		} else if len(all) != 0 {
+			t.Errorf("Bogus body %q", all)
+		}
+	}
+}
+
+// TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
+// on responses to HEAD requests.
+func TestTransportHeadChunkedResponse(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.Method != "HEAD" {
+			panic("expected HEAD; got " + r.Method)
+		}
+		w.Header().Set("Transfer-Encoding", "chunked") // client should ignore
+		w.Header().Set("x-client-ipport", r.RemoteAddr)
+		w.WriteHeader(200)
+	}))
+	defer ts.Close()
+
+	tr := &Transport{DisableKeepAlives: false}
+	c := &Client{Transport: tr}
+
+	res1, err := c.Head(ts.URL)
+	if err != nil {
+		t.Fatalf("request 1 error: %v", err)
+	}
+	res2, err := c.Head(ts.URL)
+	if err != nil {
+		t.Fatalf("request 2 error: %v", err)
+	}
+	if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 {
+		t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2)
+	}
+}
+
+var roundTripTests = []struct {
+	accept       string
+	expectAccept string
+	compressed   bool
+}{
+	// Requests with no accept-encoding header use transparent compression
+	{"", "gzip", false},
+	// Requests with other accept-encoding should pass through unmodified
+	{"foo", "foo", false},
+	// Requests with accept-encoding == gzip should be passed through
+	{"gzip", "gzip", true},
+}
+
+// Test that the modification made to the Request by the RoundTripper is cleaned up
+func TestRoundTripGzip(t *testing.T) {
+	defer afterTest(t)
+	const responseBody = "test response body"
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		accept := req.Header.Get("Accept-Encoding")
+		if expect := req.FormValue("expect_accept"); accept != expect {
+			t.Errorf("in handler, test %v: Accept-Encoding = %q, want %q",
+				req.FormValue("testnum"), accept, expect)
+		}
+		if accept == "gzip" {
+			rw.Header().Set("Content-Encoding", "gzip")
+			gz := gzip.NewWriter(rw)
+			gz.Write([]byte(responseBody))
+			gz.Close()
+		} else {
+			rw.Header().Set("Content-Encoding", accept)
+			rw.Write([]byte(responseBody))
+		}
+	}))
+	defer ts.Close()
+
+	for i, test := range roundTripTests {
+		// Test basic request (no accept-encoding)
+		req, _ := NewRequest("GET", fmt.Sprintf("%s/?testnum=%d&expect_accept=%s", ts.URL, i, test.expectAccept), nil)
+		if test.accept != "" {
+			req.Header.Set("Accept-Encoding", test.accept)
+		}
+		res, err := DefaultTransport.RoundTrip(req)
+		var body []byte
+		if test.compressed {
+			var r *gzip.Reader
+			r, err = gzip.NewReader(res.Body)
+			if err != nil {
+				t.Errorf("%d. gzip NewReader: %v", i, err)
+				continue
+			}
+			body, err = ioutil.ReadAll(r)
+			res.Body.Close()
+		} else {
+			body, err = ioutil.ReadAll(res.Body)
+		}
+		if err != nil {
+			t.Errorf("%d. Error: %q", i, err)
+			continue
+		}
+		if g, e := string(body), responseBody; g != e {
+			t.Errorf("%d. body = %q; want %q", i, g, e)
+		}
+		if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e {
+			t.Errorf("%d. Accept-Encoding = %q; want %q (it was mutated, in violation of RoundTrip contract)", i, g, e)
+		}
+		if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e {
+			t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e)
+		}
+	}
+
+}
+
+func TestTransportGzip(t *testing.T) {
+	defer afterTest(t)
+	const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+	const nRandBytes = 1024 * 1024
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		if req.Method == "HEAD" {
+			if g := req.Header.Get("Accept-Encoding"); g != "" {
+				t.Errorf("HEAD request sent with Accept-Encoding of %q; want none", g)
+			}
+			return
+		}
+		if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e {
+			t.Errorf("Accept-Encoding = %q, want %q", g, e)
+		}
+		rw.Header().Set("Content-Encoding", "gzip")
+
+		var w io.Writer = rw
+		var buf bytes.Buffer
+		if req.FormValue("chunked") == "0" {
+			w = &buf
+			defer io.Copy(rw, &buf)
+			defer func() {
+				rw.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
+			}()
+		}
+		gz := gzip.NewWriter(w)
+		gz.Write([]byte(testString))
+		if req.FormValue("body") == "large" {
+			io.CopyN(gz, rand.Reader, nRandBytes)
+		}
+		gz.Close()
+	}))
+	defer ts.Close()
+
+	for _, chunked := range []string{"1", "0"} {
+		c := &Client{Transport: &Transport{}}
+
+		// First fetch something large, but only read some of it.
+		res, err := c.Get(ts.URL + "/?body=large&chunked=" + chunked)
+		if err != nil {
+			t.Fatalf("large get: %v", err)
+		}
+		buf := make([]byte, len(testString))
+		n, err := io.ReadFull(res.Body, buf)
+		if err != nil {
+			t.Fatalf("partial read of large response: size=%d, %v", n, err)
+		}
+		if e, g := testString, string(buf); e != g {
+			t.Errorf("partial read got %q, expected %q", g, e)
+		}
+		res.Body.Close()
+		// Read on the body, even though it's closed
+		n, err = res.Body.Read(buf)
+		if n != 0 || err == nil {
+			t.Errorf("expected error post-closed large Read; got = %d, %v", n, err)
+		}
+
+		// Then something small.
+		res, err = c.Get(ts.URL + "/?chunked=" + chunked)
+		if err != nil {
+			t.Fatal(err)
+		}
+		body, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if g, e := string(body), testString; g != e {
+			t.Fatalf("body = %q; want %q", g, e)
+		}
+		if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
+			t.Fatalf("Content-Encoding = %q; want %q", g, e)
+		}
+
+		// Read on the body after it's been fully read:
+		n, err = res.Body.Read(buf)
+		if n != 0 || err == nil {
+			t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err)
+		}
+		res.Body.Close()
+		n, err = res.Body.Read(buf)
+		if n != 0 || err == nil {
+			t.Errorf("expected Read error after Close; got %d, %v", n, err)
+		}
+	}
+
+	// And a HEAD request too, because they're always weird.
+	c := &Client{Transport: &Transport{}}
+	res, err := c.Head(ts.URL)
+	if err != nil {
+		t.Fatalf("Head: %v", err)
+	}
+	if res.StatusCode != 200 {
+		t.Errorf("Head status=%d; want=200", res.StatusCode)
+	}
+}
+
+func TestTransportProxy(t *testing.T) {
+	defer afterTest(t)
+	ch := make(chan string, 1)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		ch <- "real server"
+	}))
+	defer ts.Close()
+	proxy := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		ch <- "proxy for " + r.URL.String()
+	}))
+	defer proxy.Close()
+
+	pu, err := url.Parse(proxy.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	c := &Client{Transport: &Transport{Proxy: ProxyURL(pu)}}
+	c.Head(ts.URL)
+	got := <-ch
+	want := "proxy for " + ts.URL + "/"
+	if got != want {
+		t.Errorf("want %q, got %q", want, got)
+	}
+}
+
+// TestTransportGzipRecursive sends a gzip quine and checks that the
+// client gets the same value back. This is more cute than anything,
+// but checks that we don't recurse forever, and checks that
+// Content-Encoding is removed.
+func TestTransportGzipRecursive(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Encoding", "gzip")
+		w.Write(rgz)
+	}))
+	defer ts.Close()
+
+	c := &Client{Transport: &Transport{}}
+	res, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !bytes.Equal(body, rgz) {
+		t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x",
+			body, rgz)
+	}
+	if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
+		t.Fatalf("Content-Encoding = %q; want %q", g, e)
+	}
+}
+
+// golang.org/issue/7750: request fails when server replies with
+// a short gzip body
+func TestTransportGzipShort(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Encoding", "gzip")
+		w.Write([]byte{0x1f, 0x8b})
+	}))
+	defer ts.Close()
+
+	tr := &Transport{}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+	res, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer res.Body.Close()
+	_, err = ioutil.ReadAll(res.Body)
+	if err == nil {
+		t.Fatal("Expect an error from reading a body.")
+	}
+	if err != io.ErrUnexpectedEOF {
+		t.Errorf("ReadAll error = %v; want io.ErrUnexpectedEOF", err)
+	}
+}
+
+// tests that persistent goroutine connections shut down when no longer desired.
+func TestTransportPersistConnLeak(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping test; see http://golang.org/issue/7237")
+	}
+	defer afterTest(t)
+	gotReqCh := make(chan bool)
+	unblockCh := make(chan bool)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		gotReqCh <- true
+		<-unblockCh
+		w.Header().Set("Content-Length", "0")
+		w.WriteHeader(204)
+	}))
+	defer ts.Close()
+
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+
+	n0 := runtime.NumGoroutine()
+
+	const numReq = 25
+	didReqCh := make(chan bool)
+	for i := 0; i < numReq; i++ {
+		go func() {
+			res, err := c.Get(ts.URL)
+			didReqCh <- true
+			if err != nil {
+				t.Errorf("client fetch error: %v", err)
+				return
+			}
+			res.Body.Close()
+		}()
+	}
+
+	// Wait for all goroutines to be stuck in the Handler.
+	for i := 0; i < numReq; i++ {
+		<-gotReqCh
+	}
+
+	nhigh := runtime.NumGoroutine()
+
+	// Tell all handlers to unblock and reply.
+	for i := 0; i < numReq; i++ {
+		unblockCh <- true
+	}
+
+	// Wait for all HTTP clients to be done.
+	for i := 0; i < numReq; i++ {
+		<-didReqCh
+	}
+
+	tr.CloseIdleConnections()
+	time.Sleep(100 * time.Millisecond)
+	runtime.GC()
+	runtime.GC() // even more.
+	nfinal := runtime.NumGoroutine()
+
+	growth := nfinal - n0
+
+	// We expect 0 or 1 extra goroutine, empirically.  Allow up to 5.
+	// Previously we were leaking one per numReq.
+	if int(growth) > 5 {
+		t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth)
+		t.Error("too many new goroutines")
+	}
+}
+
+// golang.org/issue/4531: Transport leaks goroutines when
+// request.ContentLength is explicitly short
+func TestTransportPersistConnLeakShortBody(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping test; see http://golang.org/issue/7237")
+	}
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	}))
+	defer ts.Close()
+
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+
+	n0 := runtime.NumGoroutine()
+	body := []byte("Hello")
+	for i := 0; i < 20; i++ {
+		req, err := NewRequest("POST", ts.URL, bytes.NewReader(body))
+		if err != nil {
+			t.Fatal(err)
+		}
+		req.ContentLength = int64(len(body) - 2) // explicitly short
+		_, err = c.Do(req)
+		if err == nil {
+			t.Fatal("Expect an error from writing too long of a body.")
+		}
+	}
+	nhigh := runtime.NumGoroutine()
+	tr.CloseIdleConnections()
+	time.Sleep(400 * time.Millisecond)
+	runtime.GC()
+	nfinal := runtime.NumGoroutine()
+
+	growth := nfinal - n0
+
+	// We expect 0 or 1 extra goroutine, empirically.  Allow up to 5.
+	// Previously we were leaking one per numReq.
+	t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth)
+	if int(growth) > 5 {
+		t.Error("too many new goroutines")
+	}
+}
+
+// This used to crash; http://golang.org/issue/3266
+func TestTransportIdleConnCrash(t *testing.T) {
+	defer afterTest(t)
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+
+	unblockCh := make(chan bool, 1)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		<-unblockCh
+		tr.CloseIdleConnections()
+	}))
+	defer ts.Close()
+
+	didreq := make(chan bool)
+	go func() {
+		res, err := c.Get(ts.URL)
+		if err != nil {
+			t.Error(err)
+		} else {
+			res.Body.Close() // returns idle conn
+		}
+		didreq <- true
+	}()
+	unblockCh <- true
+	<-didreq
+}
+
+// Test that the transport doesn't close the TCP connection early,
+// before the response body has been read.  This was a regression
+// which sadly lacked a triggering test.  The large response body made
+// the old race easier to trigger.
+func TestIssue3644(t *testing.T) {
+	defer afterTest(t)
+	const numFoos = 5000
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Connection", "close")
+		for i := 0; i < numFoos; i++ {
+			w.Write([]byte("foo "))
+		}
+	}))
+	defer ts.Close()
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+	res, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer res.Body.Close()
+	bs, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(bs) != numFoos*len("foo ") {
+		t.Errorf("unexpected response length")
+	}
+}
+
+// Test that a client receives a server's reply, even if the server doesn't read
+// the entire request body.
+func TestIssue3595(t *testing.T) {
+	defer afterTest(t)
+	const deniedMsg = "sorry, denied."
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		Error(w, deniedMsg, StatusUnauthorized)
+	}))
+	defer ts.Close()
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+	res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a'))
+	if err != nil {
+		t.Errorf("Post: %v", err)
+		return
+	}
+	got, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatalf("Body ReadAll: %v", err)
+	}
+	if !strings.Contains(string(got), deniedMsg) {
+		t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg)
+	}
+}
+
+// From http://golang.org/issue/4454 ,
+// "client fails to handle requests with no body and chunked encoding"
+func TestChunkedNoContent(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.WriteHeader(StatusNoContent)
+	}))
+	defer ts.Close()
+
+	for _, closeBody := range []bool{true, false} {
+		c := &Client{Transport: &Transport{}}
+		const n = 4
+		for i := 1; i <= n; i++ {
+			res, err := c.Get(ts.URL)
+			if err != nil {
+				t.Errorf("closingBody=%v, req %d/%d: %v", closeBody, i, n, err)
+			} else {
+				if closeBody {
+					res.Body.Close()
+				}
+			}
+		}
+	}
+}
+
+func TestTransportConcurrency(t *testing.T) {
+	defer afterTest(t)
+	maxProcs, numReqs := 16, 500
+	if testing.Short() {
+		maxProcs, numReqs = 4, 50
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "%v", r.FormValue("echo"))
+	}))
+	defer ts.Close()
+
+	var wg sync.WaitGroup
+	wg.Add(numReqs)
+
+	tr := &Transport{
+		Dial: func(netw, addr string) (c net.Conn, err error) {
+			// Due to the Transport's "socket late
+			// binding" (see idleConnCh in transport.go),
+			// the numReqs HTTP requests below can finish
+			// with a dial still outstanding.  So count
+			// our dials as work too so the leak checker
+			// doesn't complain at us.
+			wg.Add(1)
+			defer wg.Done()
+			return net.Dial(netw, addr)
+		},
+	}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+	reqs := make(chan string)
+	defer close(reqs)
+
+	for i := 0; i < maxProcs*2; i++ {
+		go func() {
+			for req := range reqs {
+				res, err := c.Get(ts.URL + "/?echo=" + req)
+				if err != nil {
+					t.Errorf("error on req %s: %v", req, err)
+					wg.Done()
+					continue
+				}
+				all, err := ioutil.ReadAll(res.Body)
+				if err != nil {
+					t.Errorf("read error on req %s: %v", req, err)
+					wg.Done()
+					continue
+				}
+				if string(all) != req {
+					t.Errorf("body of req %s = %q; want %q", req, all, req)
+				}
+				res.Body.Close()
+				wg.Done()
+			}
+		}()
+	}
+	for i := 0; i < numReqs; i++ {
+		reqs <- fmt.Sprintf("request-%d", i)
+	}
+	wg.Wait()
+}
+
+func TestIssue4191_InfiniteGetTimeout(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping test; see http://golang.org/issue/7237")
+	}
+	defer afterTest(t)
+	const debug = false
+	mux := NewServeMux()
+	mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
+		io.Copy(w, neverEnding('a'))
+	})
+	ts := httptest.NewServer(mux)
+	timeout := 100 * time.Millisecond
+
+	client := &Client{
+		Transport: &Transport{
+			Dial: func(n, addr string) (net.Conn, error) {
+				conn, err := net.Dial(n, addr)
+				if err != nil {
+					return nil, err
+				}
+				conn.SetDeadline(time.Now().Add(timeout))
+				if debug {
+					conn = NewLoggingConn("client", conn)
+				}
+				return conn, nil
+			},
+			DisableKeepAlives: true,
+		},
+	}
+
+	getFailed := false
+	nRuns := 5
+	if testing.Short() {
+		nRuns = 1
+	}
+	for i := 0; i < nRuns; i++ {
+		if debug {
+			println("run", i+1, "of", nRuns)
+		}
+		sres, err := client.Get(ts.URL + "/get")
+		if err != nil {
+			if !getFailed {
+				// Make the timeout longer, once.
+				getFailed = true
+				t.Logf("increasing timeout")
+				i--
+				timeout *= 10
+				continue
+			}
+			t.Errorf("Error issuing GET: %v", err)
+			break
+		}
+		_, err = io.Copy(ioutil.Discard, sres.Body)
+		if err == nil {
+			t.Errorf("Unexpected successful copy")
+			break
+		}
+	}
+	if debug {
+		println("tests complete; waiting for handlers to finish")
+	}
+	ts.Close()
+}
+
+func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping test; see http://golang.org/issue/7237")
+	}
+	defer afterTest(t)
+	const debug = false
+	mux := NewServeMux()
+	mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
+		io.Copy(w, neverEnding('a'))
+	})
+	mux.HandleFunc("/put", func(w ResponseWriter, r *Request) {
+		defer r.Body.Close()
+		io.Copy(ioutil.Discard, r.Body)
+	})
+	ts := httptest.NewServer(mux)
+	timeout := 100 * time.Millisecond
+
+	client := &Client{
+		Transport: &Transport{
+			Dial: func(n, addr string) (net.Conn, error) {
+				conn, err := net.Dial(n, addr)
+				if err != nil {
+					return nil, err
+				}
+				conn.SetDeadline(time.Now().Add(timeout))
+				if debug {
+					conn = NewLoggingConn("client", conn)
+				}
+				return conn, nil
+			},
+			DisableKeepAlives: true,
+		},
+	}
+
+	getFailed := false
+	nRuns := 5
+	if testing.Short() {
+		nRuns = 1
+	}
+	for i := 0; i < nRuns; i++ {
+		if debug {
+			println("run", i+1, "of", nRuns)
+		}
+		sres, err := client.Get(ts.URL + "/get")
+		if err != nil {
+			if !getFailed {
+				// Make the timeout longer, once.
+				getFailed = true
+				t.Logf("increasing timeout")
+				i--
+				timeout *= 10
+				continue
+			}
+			t.Errorf("Error issuing GET: %v", err)
+			break
+		}
+		req, _ := NewRequest("PUT", ts.URL+"/put", sres.Body)
+		_, err = client.Do(req)
+		if err == nil {
+			sres.Body.Close()
+			t.Errorf("Unexpected successful PUT")
+			break
+		}
+		sres.Body.Close()
+	}
+	if debug {
+		println("tests complete; waiting for handlers to finish")
+	}
+	ts.Close()
+}
+
+func TestTransportResponseHeaderTimeout(t *testing.T) {
+	defer afterTest(t)
+	if testing.Short() {
+		t.Skip("skipping timeout test in -short mode")
+	}
+	inHandler := make(chan bool, 1)
+	mux := NewServeMux()
+	mux.HandleFunc("/fast", func(w ResponseWriter, r *Request) {
+		inHandler <- true
+	})
+	mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) {
+		inHandler <- true
+		time.Sleep(2 * time.Second)
+	})
+	ts := httptest.NewServer(mux)
+	defer ts.Close()
+
+	tr := &Transport{
+		ResponseHeaderTimeout: 500 * time.Millisecond,
+	}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	tests := []struct {
+		path    string
+		want    int
+		wantErr string
+	}{
+		{path: "/fast", want: 200},
+		{path: "/slow", wantErr: "timeout awaiting response headers"},
+		{path: "/fast", want: 200},
+	}
+	for i, tt := range tests {
+		res, err := c.Get(ts.URL + tt.path)
+		select {
+		case <-inHandler:
+		case <-time.After(5 * time.Second):
+			t.Errorf("never entered handler for test index %d, %s", i, tt.path)
+			continue
+		}
+		if err != nil {
+			uerr, ok := err.(*url.Error)
+			if !ok {
+				t.Errorf("error is not an url.Error; got: %#v", err)
+				continue
+			}
+			nerr, ok := uerr.Err.(net.Error)
+			if !ok {
+				t.Errorf("error does not satisfy net.Error interface; got: %#v", err)
+				continue
+			}
+			if !nerr.Timeout() {
+				t.Errorf("want timeout error; got: %q", nerr)
+				continue
+			}
+			if strings.Contains(err.Error(), tt.wantErr) {
+				continue
+			}
+			t.Errorf("%d. unexpected error: %v", i, err)
+			continue
+		}
+		if tt.wantErr != "" {
+			t.Errorf("%d. no error. expected error: %v", i, tt.wantErr)
+			continue
+		}
+		if res.StatusCode != tt.want {
+			t.Errorf("%d for path %q status = %d; want %d", i, tt.path, res.StatusCode, tt.want)
+		}
+	}
+}
+
+func TestTransportCancelRequest(t *testing.T) {
+	defer afterTest(t)
+	if testing.Short() {
+		t.Skip("skipping test in -short mode")
+	}
+	unblockc := make(chan bool)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "Hello")
+		w.(Flusher).Flush() // send headers and some body
+		<-unblockc
+	}))
+	defer ts.Close()
+	defer close(unblockc)
+
+	tr := &Transport{}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	req, _ := NewRequest("GET", ts.URL, nil)
+	res, err := c.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	go func() {
+		time.Sleep(1 * time.Second)
+		tr.CancelRequest(req)
+	}()
+	t0 := time.Now()
+	body, err := ioutil.ReadAll(res.Body)
+	d := time.Since(t0)
+
+	if err == nil {
+		t.Error("expected an error reading the body")
+	}
+	if string(body) != "Hello" {
+		t.Errorf("Body = %q; want Hello", body)
+	}
+	if d < 500*time.Millisecond {
+		t.Errorf("expected ~1 second delay; got %v", d)
+	}
+	// Verify no outstanding requests after readLoop/writeLoop
+	// goroutines shut down.
+	for tries := 3; tries > 0; tries-- {
+		n := tr.NumPendingRequestsForTesting()
+		if n == 0 {
+			break
+		}
+		time.Sleep(100 * time.Millisecond)
+		if tries == 1 {
+			t.Errorf("pending requests = %d; want 0", n)
+		}
+	}
+}
+
+func TestTransportCancelRequestInDial(t *testing.T) {
+	defer afterTest(t)
+	if testing.Short() {
+		t.Skip("skipping test in -short mode")
+	}
+	var logbuf bytes.Buffer
+	eventLog := log.New(&logbuf, "", 0)
+
+	unblockDial := make(chan bool)
+	defer close(unblockDial)
+
+	inDial := make(chan bool)
+	tr := &Transport{
+		Dial: func(network, addr string) (net.Conn, error) {
+			eventLog.Println("dial: blocking")
+			inDial <- true
+			<-unblockDial
+			return nil, errors.New("nope")
+		},
+	}
+	cl := &Client{Transport: tr}
+	gotres := make(chan bool)
+	req, _ := NewRequest("GET", "http://something.no-network.tld/", nil)
+	go func() {
+		_, err := cl.Do(req)
+		eventLog.Printf("Get = %v", err)
+		gotres <- true
+	}()
+
+	select {
+	case <-inDial:
+	case <-time.After(5 * time.Second):
+		t.Fatal("timeout; never saw blocking dial")
+	}
+
+	eventLog.Printf("canceling")
+	tr.CancelRequest(req)
+
+	select {
+	case <-gotres:
+	case <-time.After(5 * time.Second):
+		panic("hang. events are: " + logbuf.String())
+	}
+
+	got := logbuf.String()
+	want := `dial: blocking
+canceling
+Get = Get http://something.no-network.tld/: net/http: request canceled while waiting for connection
+`
+	if got != want {
+		t.Errorf("Got events:\n%s\nWant:\n%s", got, want)
+	}
+}
+
+// golang.org/issue/3672 -- Client can't close HTTP stream
+// Calling Close on a Response.Body used to just read until EOF.
+// Now it actually closes the TCP connection.
+func TestTransportCloseResponseBody(t *testing.T) {
+	defer afterTest(t)
+	writeErr := make(chan error, 1)
+	msg := []byte("young\n")
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		for {
+			_, err := w.Write(msg)
+			if err != nil {
+				writeErr <- err
+				return
+			}
+			w.(Flusher).Flush()
+		}
+	}))
+	defer ts.Close()
+
+	tr := &Transport{}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	req, _ := NewRequest("GET", ts.URL, nil)
+	defer tr.CancelRequest(req)
+
+	res, err := c.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	const repeats = 3
+	buf := make([]byte, len(msg)*repeats)
+	want := bytes.Repeat(msg, repeats)
+
+	_, err = io.ReadFull(res.Body, buf)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !bytes.Equal(buf, want) {
+		t.Fatalf("read %q; want %q", buf, want)
+	}
+	didClose := make(chan error, 1)
+	go func() {
+		didClose <- res.Body.Close()
+	}()
+	select {
+	case err := <-didClose:
+		if err != nil {
+			t.Errorf("Close = %v", err)
+		}
+	case <-time.After(10 * time.Second):
+		t.Fatal("too long waiting for close")
+	}
+	select {
+	case err := <-writeErr:
+		if err == nil {
+			t.Errorf("expected non-nil write error")
+		}
+	case <-time.After(10 * time.Second):
+		t.Fatal("too long waiting for write error")
+	}
+}
+
+type fooProto struct{}
+
+func (fooProto) RoundTrip(req *Request) (*Response, error) {
+	res := &Response{
+		Status:     "200 OK",
+		StatusCode: 200,
+		Header:     make(Header),
+		Body:       ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())),
+	}
+	return res, nil
+}
+
+func TestTransportAltProto(t *testing.T) {
+	defer afterTest(t)
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+	tr.RegisterProtocol("foo", fooProto{})
+	res, err := c.Get("foo://bar.com/path")
+	if err != nil {
+		t.Fatal(err)
+	}
+	bodyb, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	body := string(bodyb)
+	if e := "You wanted foo://bar.com/path"; body != e {
+		t.Errorf("got response %q, want %q", body, e)
+	}
+}
+
+func TestTransportNoHost(t *testing.T) {
+	defer afterTest(t)
+	tr := &Transport{}
+	_, err := tr.RoundTrip(&Request{
+		Header: make(Header),
+		URL: &url.URL{
+			Scheme: "http",
+		},
+	})
+	want := "http: no Host in request URL"
+	if got := fmt.Sprint(err); got != want {
+		t.Errorf("error = %v; want %q", err, want)
+	}
+}
+
+func TestTransportSocketLateBinding(t *testing.T) {
+	defer afterTest(t)
+
+	mux := NewServeMux()
+	fooGate := make(chan bool, 1)
+	mux.HandleFunc("/foo", func(w ResponseWriter, r *Request) {
+		w.Header().Set("foo-ipport", r.RemoteAddr)
+		w.(Flusher).Flush()
+		<-fooGate
+	})
+	mux.HandleFunc("/bar", func(w ResponseWriter, r *Request) {
+		w.Header().Set("bar-ipport", r.RemoteAddr)
+	})
+	ts := httptest.NewServer(mux)
+	defer ts.Close()
+
+	dialGate := make(chan bool, 1)
+	tr := &Transport{
+		Dial: func(n, addr string) (net.Conn, error) {
+			if <-dialGate {
+				return net.Dial(n, addr)
+			}
+			return nil, errors.New("manually closed")
+		},
+		DisableKeepAlives: false,
+	}
+	defer tr.CloseIdleConnections()
+	c := &Client{
+		Transport: tr,
+	}
+
+	dialGate <- true // only allow one dial
+	fooRes, err := c.Get(ts.URL + "/foo")
+	if err != nil {
+		t.Fatal(err)
+	}
+	fooAddr := fooRes.Header.Get("foo-ipport")
+	if fooAddr == "" {
+		t.Fatal("No addr on /foo request")
+	}
+	time.AfterFunc(200*time.Millisecond, func() {
+		// let the foo response finish so we can use its
+		// connection for /bar
+		fooGate <- true
+		io.Copy(ioutil.Discard, fooRes.Body)
+		fooRes.Body.Close()
+	})
+
+	barRes, err := c.Get(ts.URL + "/bar")
+	if err != nil {
+		t.Fatal(err)
+	}
+	barAddr := barRes.Header.Get("bar-ipport")
+	if barAddr != fooAddr {
+		t.Fatalf("/foo came from conn %q; /bar came from %q instead", fooAddr, barAddr)
+	}
+	barRes.Body.Close()
+	dialGate <- false
+}
+
+// Issue 2184
+func TestTransportReading100Continue(t *testing.T) {
+	defer afterTest(t)
+
+	const numReqs = 5
+	reqBody := func(n int) string { return fmt.Sprintf("request body %d", n) }
+	reqID := func(n int) string { return fmt.Sprintf("REQ-ID-%d", n) }
+
+	send100Response := func(w *io.PipeWriter, r *io.PipeReader) {
+		defer w.Close()
+		defer r.Close()
+		br := bufio.NewReader(r)
+		n := 0
+		for {
+			n++
+			req, err := ReadRequest(br)
+			if err == io.EOF {
+				return
+			}
+			if err != nil {
+				t.Error(err)
+				return
+			}
+			slurp, err := ioutil.ReadAll(req.Body)
+			if err != nil {
+				t.Errorf("Server request body slurp: %v", err)
+				return
+			}
+			id := req.Header.Get("Request-Id")
+			resCode := req.Header.Get("X-Want-Response-Code")
+			if resCode == "" {
+				resCode = "100 Continue"
+				if string(slurp) != reqBody(n) {
+					t.Errorf("Server got %q, %v; want %q", slurp, err, reqBody(n))
+				}
+			}
+			body := fmt.Sprintf("Response number %d", n)
+			v := []byte(strings.Replace(fmt.Sprintf(`HTTP/1.1 %s
+Date: Thu, 28 Feb 2013 17:55:41 GMT
+
+HTTP/1.1 200 OK
+Content-Type: text/html
+Echo-Request-Id: %s
+Content-Length: %d
+
+%s`, resCode, id, len(body), body), "\n", "\r\n", -1))
+			w.Write(v)
+			if id == reqID(numReqs) {
+				return
+			}
+		}
+
+	}
+
+	tr := &Transport{
+		Dial: func(n, addr string) (net.Conn, error) {
+			sr, sw := io.Pipe() // server read/write
+			cr, cw := io.Pipe() // client read/write
+			conn := &rwTestConn{
+				Reader: cr,
+				Writer: sw,
+				closeFunc: func() error {
+					sw.Close()
+					cw.Close()
+					return nil
+				},
+			}
+			go send100Response(cw, sr)
+			return conn, nil
+		},
+		DisableKeepAlives: false,
+	}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	testResponse := func(req *Request, name string, wantCode int) {
+		res, err := c.Do(req)
+		if err != nil {
+			t.Fatalf("%s: Do: %v", name, err)
+		}
+		if res.StatusCode != wantCode {
+			t.Fatalf("%s: Response Statuscode=%d; want %d", name, res.StatusCode, wantCode)
+		}
+		if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack {
+			t.Errorf("%s: response id %q != request id %q", name, idBack, id)
+		}
+		_, err = ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatalf("%s: Slurp error: %v", name, err)
+		}
+	}
+
+	// Few 100 responses, making sure we're not off-by-one.
+	for i := 1; i <= numReqs; i++ {
+		req, _ := NewRequest("POST", "http://dummy.tld/", strings.NewReader(reqBody(i)))
+		req.Header.Set("Request-Id", reqID(i))
+		testResponse(req, fmt.Sprintf("100, %d/%d", i, numReqs), 200)
+	}
+
+	// And some other informational 1xx but non-100 responses, to test
+	// we return them but don't re-use the connection.
+	for i := 1; i <= numReqs; i++ {
+		req, _ := NewRequest("POST", "http://other.tld/", strings.NewReader(reqBody(i)))
+		req.Header.Set("X-Want-Response-Code", "123 Sesame Street")
+		testResponse(req, fmt.Sprintf("123, %d/%d", i, numReqs), 123)
+	}
+}
+
+type proxyFromEnvTest struct {
+	req     string // URL to fetch; blank means "http://example.com"
+	env     string
+	noenv   string
+	want    string
+	wanterr error
+}
+
+func (t proxyFromEnvTest) String() string {
+	var buf bytes.Buffer
+	if t.env != "" {
+		fmt.Fprintf(&buf, "http_proxy=%q", t.env)
+	}
+	if t.noenv != "" {
+		fmt.Fprintf(&buf, " no_proxy=%q", t.noenv)
+	}
+	req := "http://example.com"
+	if t.req != "" {
+		req = t.req
+	}
+	fmt.Fprintf(&buf, " req=%q", req)
+	return strings.TrimSpace(buf.String())
+}
+
+var proxyFromEnvTests = []proxyFromEnvTest{
+	{env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"},
+	{env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"},
+	{env: "cache.corp.example.com", want: "http://cache.corp.example.com"},
+	{env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"},
+	{env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"},
+	{env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"},
+	{want: "<nil>"},
+	{noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
+	{noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
+	{noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
+	{noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"},
+	{noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
+}
+
+func TestProxyFromEnvironment(t *testing.T) {
+	ResetProxyEnv()
+	for _, tt := range proxyFromEnvTests {
+		os.Setenv("HTTP_PROXY", tt.env)
+		os.Setenv("NO_PROXY", tt.noenv)
+		ResetCachedEnvironment()
+		reqURL := tt.req
+		if reqURL == "" {
+			reqURL = "http://example.com"
+		}
+		req, _ := NewRequest("GET", reqURL, nil)
+		url, err := ProxyFromEnvironment(req)
+		if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
+			t.Errorf("%v: got error = %q, want %q", tt, g, e)
+			continue
+		}
+		if got := fmt.Sprintf("%s", url); got != tt.want {
+			t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
+		}
+	}
+}
+
+func TestIdleConnChannelLeak(t *testing.T) {
+	var mu sync.Mutex
+	var n int
+
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		mu.Lock()
+		n++
+		mu.Unlock()
+	}))
+	defer ts.Close()
+
+	tr := &Transport{
+		Dial: func(netw, addr string) (net.Conn, error) {
+			return net.Dial(netw, ts.Listener.Addr().String())
+		},
+	}
+	defer tr.CloseIdleConnections()
+
+	c := &Client{Transport: tr}
+
+	// First, without keep-alives.
+	for _, disableKeep := range []bool{true, false} {
+		tr.DisableKeepAlives = disableKeep
+		for i := 0; i < 5; i++ {
+			_, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i))
+			if err != nil {
+				t.Fatal(err)
+			}
+		}
+		if got := tr.IdleConnChMapSizeForTesting(); got != 0 {
+			t.Fatalf("ForDisableKeepAlives = %v, map size = %d; want 0", disableKeep, got)
+		}
+	}
+}
+
+// Verify the status quo: that the Client.Post function coerces its
+// body into a ReadCloser if it's a Closer, and that the Transport
+// then closes it.
+func TestTransportClosesRequestBody(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(http.HandlerFunc(func(w ResponseWriter, r *Request) {
+		io.Copy(ioutil.Discard, r.Body)
+	}))
+	defer ts.Close()
+
+	tr := &Transport{}
+	defer tr.CloseIdleConnections()
+	cl := &Client{Transport: tr}
+
+	closes := 0
+
+	res, err := cl.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")})
+	if err != nil {
+		t.Fatal(err)
+	}
+	res.Body.Close()
+	if closes != 1 {
+		t.Errorf("closes = %d; want 1", closes)
+	}
+}
+
+func TestTransportTLSHandshakeTimeout(t *testing.T) {
+	defer afterTest(t)
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	ln := newLocalListener(t)
+	defer ln.Close()
+	testdonec := make(chan struct{})
+	defer close(testdonec)
+
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		<-testdonec
+		c.Close()
+	}()
+
+	getdonec := make(chan struct{})
+	go func() {
+		defer close(getdonec)
+		tr := &Transport{
+			Dial: func(_, _ string) (net.Conn, error) {
+				return net.Dial("tcp", ln.Addr().String())
+			},
+			TLSHandshakeTimeout: 250 * time.Millisecond,
+		}
+		cl := &Client{Transport: tr}
+		_, err := cl.Get("https://dummy.tld/")
+		if err == nil {
+			t.Error("expected error")
+			return
+		}
+		ue, ok := err.(*url.Error)
+		if !ok {
+			t.Errorf("expected url.Error; got %#v", err)
+			return
+		}
+		ne, ok := ue.Err.(net.Error)
+		if !ok {
+			t.Errorf("expected net.Error; got %#v", err)
+			return
+		}
+		if !ne.Timeout() {
+			t.Errorf("expected timeout error; got %v", err)
+		}
+		if !strings.Contains(err.Error(), "handshake timeout") {
+			t.Errorf("expected 'handshake timeout' in error; got %v", err)
+		}
+	}()
+	select {
+	case <-getdonec:
+	case <-time.After(5 * time.Second):
+		t.Error("test timeout; TLS handshake hung?")
+	}
+}
+
+// Trying to repro golang.org/issue/3514
+func TestTLSServerClosesConnection(t *testing.T) {
+	defer afterTest(t)
+	if runtime.GOOS == "windows" {
+		t.Skip("skipping flaky test on Windows; golang.org/issue/7634")
+	}
+	closedc := make(chan bool, 1)
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if strings.Contains(r.URL.Path, "/keep-alive-then-die") {
+			conn, _, _ := w.(Hijacker).Hijack()
+			conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo"))
+			conn.Close()
+			closedc <- true
+			return
+		}
+		fmt.Fprintf(w, "hello")
+	}))
+	defer ts.Close()
+	tr := &Transport{
+		TLSClientConfig: &tls.Config{
+			InsecureSkipVerify: true,
+		},
+	}
+	defer tr.CloseIdleConnections()
+	client := &Client{Transport: tr}
+
+	var nSuccess = 0
+	var errs []error
+	const trials = 20
+	for i := 0; i < trials; i++ {
+		tr.CloseIdleConnections()
+		res, err := client.Get(ts.URL + "/keep-alive-then-die")
+		if err != nil {
+			t.Fatal(err)
+		}
+		<-closedc
+		slurp, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if string(slurp) != "foo" {
+			t.Errorf("Got %q, want foo", slurp)
+		}
+
+		// Now try again and see if we successfully
+		// pick a new connection.
+		res, err = client.Get(ts.URL + "/")
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+		slurp, err = ioutil.ReadAll(res.Body)
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+		nSuccess++
+	}
+	if nSuccess > 0 {
+		t.Logf("successes = %d of %d", nSuccess, trials)
+	} else {
+		t.Errorf("All runs failed:")
+	}
+	for _, err := range errs {
+		t.Logf("  err: %v", err)
+	}
+}
+
+// byteFromChanReader is an io.Reader that reads a single byte at a
+// time from the channel.  When the channel is closed, the reader
+// returns io.EOF.
+type byteFromChanReader chan byte
+
+func (c byteFromChanReader) Read(p []byte) (n int, err error) {
+	if len(p) == 0 {
+		return
+	}
+	b, ok := <-c
+	if !ok {
+		return 0, io.EOF
+	}
+	p[0] = b
+	return 1, nil
+}
+
+// Verifies that the Transport doesn't reuse a connection in the case
+// where the server replies before the request has been fully
+// written. We still honor that reply (see TestIssue3595), but don't
+// send future requests on the connection because it's then in a
+// questionable state.
+// golang.org/issue/7569
+func TestTransportNoReuseAfterEarlyResponse(t *testing.T) {
+	defer afterTest(t)
+	var sconn struct {
+		sync.Mutex
+		c net.Conn
+	}
+	var getOkay bool
+	closeConn := func() {
+		sconn.Lock()
+		defer sconn.Unlock()
+		if sconn.c != nil {
+			sconn.c.Close()
+			sconn.c = nil
+			if !getOkay {
+				t.Logf("Closed server connection")
+			}
+		}
+	}
+	defer closeConn()
+
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.Method == "GET" {
+			io.WriteString(w, "bar")
+			return
+		}
+		conn, _, _ := w.(Hijacker).Hijack()
+		sconn.Lock()
+		sconn.c = conn
+		sconn.Unlock()
+		conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) // keep-alive
+		go io.Copy(ioutil.Discard, conn)
+	}))
+	defer ts.Close()
+	tr := &Transport{}
+	defer tr.CloseIdleConnections()
+	client := &Client{Transport: tr}
+
+	const bodySize = 256 << 10
+	finalBit := make(byteFromChanReader, 1)
+	req, _ := NewRequest("POST", ts.URL, io.MultiReader(io.LimitReader(neverEnding('x'), bodySize-1), finalBit))
+	req.ContentLength = bodySize
+	res, err := client.Do(req)
+	if err := wantBody(res, err, "foo"); err != nil {
+		t.Errorf("POST response: %v", err)
+	}
+	donec := make(chan bool)
+	go func() {
+		defer close(donec)
+		res, err = client.Get(ts.URL)
+		if err := wantBody(res, err, "bar"); err != nil {
+			t.Errorf("GET response: %v", err)
+			return
+		}
+		getOkay = true // suppress test noise
+	}()
+	time.AfterFunc(5*time.Second, closeConn)
+	select {
+	case <-donec:
+		finalBit <- 'x' // unblock the writeloop of the first Post
+		close(finalBit)
+	case <-time.After(7 * time.Second):
+		t.Fatal("timeout waiting for GET request to finish")
+	}
+}
+
+type errorReader struct {
+	err error
+}
+
+func (e errorReader) Read(p []byte) (int, error) { return 0, e.err }
+
+type closerFunc func() error
+
+func (f closerFunc) Close() error { return f() }
+
+// Issue 6981
+func TestTransportClosesBodyOnError(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping test; see http://golang.org/issue/7782")
+	}
+	defer afterTest(t)
+	readBody := make(chan error, 1)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		_, err := ioutil.ReadAll(r.Body)
+		readBody <- err
+	}))
+	defer ts.Close()
+	fakeErr := errors.New("fake error")
+	didClose := make(chan bool, 1)
+	req, _ := NewRequest("POST", ts.URL, struct {
+		io.Reader
+		io.Closer
+	}{
+		io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), errorReader{fakeErr}),
+		closerFunc(func() error {
+			select {
+			case didClose <- true:
+			default:
+			}
+			return nil
+		}),
+	})
+	res, err := DefaultClient.Do(req)
+	if res != nil {
+		defer res.Body.Close()
+	}
+	if err == nil || !strings.Contains(err.Error(), fakeErr.Error()) {
+		t.Fatalf("Do error = %v; want something containing %q", err, fakeErr.Error())
+	}
+	select {
+	case err := <-readBody:
+		if err == nil {
+			t.Errorf("Unexpected success reading request body from handler; want 'unexpected EOF reading trailer'")
+		}
+	case <-time.After(5 * time.Second):
+		t.Error("timeout waiting for server handler to complete")
+	}
+	select {
+	case <-didClose:
+	default:
+		t.Errorf("didn't see Body.Close")
+	}
+}
+
+func wantBody(res *http.Response, err error, want string) error {
+	if err != nil {
+		return err
+	}
+	slurp, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		return fmt.Errorf("error reading body: %v", err)
+	}
+	if string(slurp) != want {
+		return fmt.Errorf("body = %q; want %q", slurp, want)
+	}
+	if err := res.Body.Close(); err != nil {
+		return fmt.Errorf("body Close = %v", err)
+	}
+	return nil
+}
+
+func newLocalListener(t *testing.T) net.Listener {
+	ln, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		ln, err = net.Listen("tcp6", "[::1]:0")
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+	return ln
+}
+
+type countCloseReader struct {
+	n *int
+	io.Reader
+}
+
+func (cr countCloseReader) Close() error {
+	(*cr.n)++
+	return nil
+}
+
+// rgz is a gzip quine that uncompresses to itself.
+var rgz = []byte{
+	0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73,
+	0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0,
+	0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2,
+	0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17,
+	0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60,
+	0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2,
+	0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00,
+	0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00,
+	0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16,
+	0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05,
+	0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff,
+	0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00,
+	0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00,
+	0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
+	0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88,
+	0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff,
+	0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00,
+	0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00,
+	0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
+	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
+	0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff,
+	0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00,
+	0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
+	0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16,
+	0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08,
+	0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa,
+	0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06,
+	0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00,
+	0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
+	0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
+	0x00, 0x00,
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/triv.go b/third_party/gofrontend/libgo/go/net/http/triv.go
new file mode 100644
index 0000000..232d650
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/triv.go
@@ -0,0 +1,141 @@
+// 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.
+
+// +build ignore
+
+package main
+
+import (
+	"bytes"
+	"expvar"
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	"os/exec"
+	"strconv"
+	"sync"
+)
+
+// hello world, the web server
+var helloRequests = expvar.NewInt("hello-requests")
+
+func HelloServer(w http.ResponseWriter, req *http.Request) {
+	helloRequests.Add(1)
+	io.WriteString(w, "hello, world!\n")
+}
+
+// Simple counter server. POSTing to it will set the value.
+type Counter struct {
+	mu sync.Mutex // protects n
+	n  int
+}
+
+// This makes Counter satisfy the expvar.Var interface, so we can export
+// it directly.
+func (ctr *Counter) String() string {
+	ctr.mu.Lock()
+	defer ctr.mu.Unlock()
+	return fmt.Sprintf("%d", ctr.n)
+}
+
+func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	ctr.mu.Lock()
+	defer ctr.mu.Unlock()
+	switch req.Method {
+	case "GET":
+		ctr.n++
+	case "POST":
+		buf := new(bytes.Buffer)
+		io.Copy(buf, req.Body)
+		body := buf.String()
+		if n, err := strconv.Atoi(body); err != nil {
+			fmt.Fprintf(w, "bad POST: %v\nbody: [%v]\n", err, body)
+		} else {
+			ctr.n = n
+			fmt.Fprint(w, "counter reset\n")
+		}
+	}
+	fmt.Fprintf(w, "counter = %d\n", ctr.n)
+}
+
+// simple flag server
+var booleanflag = flag.Bool("boolean", true, "another flag for testing")
+
+func FlagServer(w http.ResponseWriter, req *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	fmt.Fprint(w, "Flags:\n")
+	flag.VisitAll(func(f *flag.Flag) {
+		if f.Value.String() != f.DefValue {
+			fmt.Fprintf(w, "%s = %s [default = %s]\n", f.Name, f.Value.String(), f.DefValue)
+		} else {
+			fmt.Fprintf(w, "%s = %s\n", f.Name, f.Value.String())
+		}
+	})
+}
+
+// simple argument server
+func ArgServer(w http.ResponseWriter, req *http.Request) {
+	for _, s := range os.Args {
+		fmt.Fprint(w, s, " ")
+	}
+}
+
+// a channel (just for the fun of it)
+type Chan chan int
+
+func ChanCreate() Chan {
+	c := make(Chan)
+	go func(c Chan) {
+		for x := 0; ; x++ {
+			c <- x
+		}
+	}(c)
+	return c
+}
+
+func (ch Chan) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	io.WriteString(w, fmt.Sprintf("channel send #%d\n", <-ch))
+}
+
+// exec a program, redirecting output
+func DateServer(rw http.ResponseWriter, req *http.Request) {
+	rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
+
+	date, err := exec.Command("/bin/date").Output()
+	if err != nil {
+		http.Error(rw, err.Error(), 500)
+		return
+	}
+	rw.Write(date)
+}
+
+func Logger(w http.ResponseWriter, req *http.Request) {
+	log.Print(req.URL)
+	http.Error(w, "oops", 404)
+}
+
+var webroot = flag.String("root", os.Getenv("HOME"), "web root directory")
+
+func main() {
+	flag.Parse()
+
+	// The counter is published as a variable directly.
+	ctr := new(Counter)
+	expvar.Publish("counter", ctr)
+	http.Handle("/counter", ctr)
+	http.Handle("/", http.HandlerFunc(Logger))
+	http.Handle("/go/", http.StripPrefix("/go/", http.FileServer(http.Dir(*webroot))))
+	http.Handle("/chan", ChanCreate())
+	http.HandleFunc("/flags", FlagServer)
+	http.HandleFunc("/args", ArgServer)
+	http.HandleFunc("/go/hello", HelloServer)
+	http.HandleFunc("/date", DateServer)
+	err := http.ListenAndServe(":12345", nil)
+	if err != nil {
+		log.Panicln("ListenAndServe:", err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/http/z_last_test.go b/third_party/gofrontend/libgo/go/net/http/z_last_test.go
new file mode 100644
index 0000000..5a0cc11
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/http/z_last_test.go
@@ -0,0 +1,97 @@
+// Copyright 2013 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 http_test
+
+import (
+	"net/http"
+	"runtime"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+)
+
+func interestingGoroutines() (gs []string) {
+	buf := make([]byte, 2<<20)
+	buf = buf[:runtime.Stack(buf, true)]
+	for _, g := range strings.Split(string(buf), "\n\n") {
+		sl := strings.SplitN(g, "\n", 2)
+		if len(sl) != 2 {
+			continue
+		}
+		stack := strings.TrimSpace(sl[1])
+		if stack == "" ||
+			strings.Contains(stack, "created by net.startServer") ||
+			strings.Contains(stack, "created by testing.RunTests") ||
+			strings.Contains(stack, "closeWriteAndWait") ||
+			strings.Contains(stack, "testing.Main(") ||
+			// These only show up with GOTRACEBACK=2; Issue 5005 (comment 28)
+			strings.Contains(stack, "runtime.goexit") ||
+			strings.Contains(stack, "created by runtime.gc") ||
+			strings.Contains(stack, "runtime.MHeap_Scavenger") {
+			continue
+		}
+		gs = append(gs, stack)
+	}
+	sort.Strings(gs)
+	return
+}
+
+// Verify the other tests didn't leave any goroutines running.
+// This is in a file named z_last_test.go so it sorts at the end.
+func TestGoroutinesRunning(t *testing.T) {
+	if testing.Short() {
+		t.Skip("not counting goroutines for leakage in -short mode")
+	}
+	gs := interestingGoroutines()
+
+	n := 0
+	stackCount := make(map[string]int)
+	for _, g := range gs {
+		stackCount[g]++
+		n++
+	}
+
+	t.Logf("num goroutines = %d", n)
+	if n > 0 {
+		t.Error("Too many goroutines.")
+		for stack, count := range stackCount {
+			t.Logf("%d instances of:\n%s", count, stack)
+		}
+	}
+}
+
+func afterTest(t *testing.T) {
+	http.DefaultTransport.(*http.Transport).CloseIdleConnections()
+	if testing.Short() {
+		return
+	}
+	var bad string
+	badSubstring := map[string]string{
+		").readLoop(":                                  "a Transport",
+		").writeLoop(":                                 "a Transport",
+		"created by net/http/httptest.(*Server).Start": "an httptest.Server",
+		"timeoutHandler":                               "a TimeoutHandler",
+		"net.(*netFD).connect(":                        "a timing out dial",
+		").noteClientGone(":                            "a closenotifier sender",
+	}
+	var stacks string
+	for i := 0; i < 4; i++ {
+		bad = ""
+		stacks = strings.Join(interestingGoroutines(), "\n\n")
+		for substr, what := range badSubstring {
+			if strings.Contains(stacks, substr) {
+				bad = what
+			}
+		}
+		if bad == "" {
+			return
+		}
+		// Bad stuff found, but goroutines might just still be
+		// shutting down, so give it some time.
+		time.Sleep(250 * time.Millisecond)
+	}
+	t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks)
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface.go b/third_party/gofrontend/libgo/go/net/interface.go
new file mode 100644
index 0000000..2e9f1eb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface.go
@@ -0,0 +1,126 @@
+// 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.
+
+package net
+
+import "errors"
+
+var (
+	errInvalidInterface         = errors.New("invalid network interface")
+	errInvalidInterfaceIndex    = errors.New("invalid network interface index")
+	errInvalidInterfaceName     = errors.New("invalid network interface name")
+	errNoSuchInterface          = errors.New("no such network interface")
+	errNoSuchMulticastInterface = errors.New("no such multicast network interface")
+)
+
+// Interface represents a mapping between network interface name
+// and index.  It also represents network interface facility
+// information.
+type Interface struct {
+	Index        int          // positive integer that starts at one, zero is never used
+	MTU          int          // maximum transmission unit
+	Name         string       // e.g., "en0", "lo0", "eth0.100"
+	HardwareAddr HardwareAddr // IEEE MAC-48, EUI-48 and EUI-64 form
+	Flags        Flags        // e.g., FlagUp, FlagLoopback, FlagMulticast
+}
+
+type Flags uint
+
+const (
+	FlagUp           Flags = 1 << iota // interface is up
+	FlagBroadcast                      // interface supports broadcast access capability
+	FlagLoopback                       // interface is a loopback interface
+	FlagPointToPoint                   // interface belongs to a point-to-point link
+	FlagMulticast                      // interface supports multicast access capability
+)
+
+var flagNames = []string{
+	"up",
+	"broadcast",
+	"loopback",
+	"pointtopoint",
+	"multicast",
+}
+
+func (f Flags) String() string {
+	s := ""
+	for i, name := range flagNames {
+		if f&(1<<uint(i)) != 0 {
+			if s != "" {
+				s += "|"
+			}
+			s += name
+		}
+	}
+	if s == "" {
+		s = "0"
+	}
+	return s
+}
+
+// Addrs returns interface addresses for a specific interface.
+func (ifi *Interface) Addrs() ([]Addr, error) {
+	if ifi == nil {
+		return nil, errInvalidInterface
+	}
+	return interfaceAddrTable(ifi)
+}
+
+// MulticastAddrs returns multicast, joined group addresses for
+// a specific interface.
+func (ifi *Interface) MulticastAddrs() ([]Addr, error) {
+	if ifi == nil {
+		return nil, errInvalidInterface
+	}
+	return interfaceMulticastAddrTable(ifi)
+}
+
+// Interfaces returns a list of the system's network interfaces.
+func Interfaces() ([]Interface, error) {
+	return interfaceTable(0)
+}
+
+// InterfaceAddrs returns a list of the system's network interface
+// addresses.
+func InterfaceAddrs() ([]Addr, error) {
+	return interfaceAddrTable(nil)
+}
+
+// InterfaceByIndex returns the interface specified by index.
+func InterfaceByIndex(index int) (*Interface, error) {
+	if index <= 0 {
+		return nil, errInvalidInterfaceIndex
+	}
+	ift, err := interfaceTable(index)
+	if err != nil {
+		return nil, err
+	}
+	return interfaceByIndex(ift, index)
+}
+
+func interfaceByIndex(ift []Interface, index int) (*Interface, error) {
+	for _, ifi := range ift {
+		if index == ifi.Index {
+			return &ifi, nil
+		}
+	}
+	return nil, errNoSuchInterface
+}
+
+// InterfaceByName returns the interface specified by name.
+func InterfaceByName(name string) (*Interface, error) {
+	if name == "" {
+		return nil, errInvalidInterfaceName
+	}
+	ift, err := interfaceTable(0)
+	if err != nil {
+		return nil, err
+	}
+	for _, ifi := range ift {
+		if name == ifi.Name {
+			return &ifi, nil
+		}
+	}
+	return nil, errNoSuchInterface
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface_bsd.go b/third_party/gofrontend/libgo/go/net/interface_bsd.go
new file mode 100644
index 0000000..1677557
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface_bsd.go
@@ -0,0 +1,182 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"unsafe"
+)
+
+// If the ifindex is zero, interfaceTable returns mappings of all
+// network interfaces.  Otherwise it returns a mapping of a specific
+// interface.
+func interfaceTable(ifindex int) ([]Interface, error) {
+	tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
+	if err != nil {
+		return nil, os.NewSyscallError("route rib", err)
+	}
+	msgs, err := syscall.ParseRoutingMessage(tab)
+	if err != nil {
+		return nil, os.NewSyscallError("route message", err)
+	}
+	return parseInterfaceTable(ifindex, msgs)
+}
+
+func parseInterfaceTable(ifindex int, msgs []syscall.RoutingMessage) ([]Interface, error) {
+	var ift []Interface
+loop:
+	for _, m := range msgs {
+		switch m := m.(type) {
+		case *syscall.InterfaceMessage:
+			if ifindex == 0 || ifindex == int(m.Header.Index) {
+				ifi, err := newLink(m)
+				if err != nil {
+					return nil, err
+				}
+				ift = append(ift, *ifi)
+				if ifindex == int(m.Header.Index) {
+					break loop
+				}
+			}
+		}
+	}
+	return ift, nil
+}
+
+func newLink(m *syscall.InterfaceMessage) (*Interface, error) {
+	sas, err := syscall.ParseRoutingSockaddr(m)
+	if err != nil {
+		return nil, os.NewSyscallError("route sockaddr", err)
+	}
+	ifi := &Interface{Index: int(m.Header.Index), Flags: linkFlags(m.Header.Flags)}
+	for _, sa := range sas {
+		switch sa := sa.(type) {
+		case *syscall.SockaddrDatalink:
+			// NOTE: SockaddrDatalink.Data is minimum work area,
+			// can be larger.
+			m.Data = m.Data[unsafe.Offsetof(sa.Data):]
+			var name [syscall.IFNAMSIZ]byte
+			for i := 0; i < int(sa.Nlen); i++ {
+				name[i] = byte(m.Data[i])
+			}
+			ifi.Name = string(name[:sa.Nlen])
+			ifi.MTU = int(m.Header.Data.Mtu)
+			addr := make([]byte, sa.Alen)
+			for i := 0; i < int(sa.Alen); i++ {
+				addr[i] = byte(m.Data[int(sa.Nlen)+i])
+			}
+			ifi.HardwareAddr = addr[:sa.Alen]
+		}
+	}
+	return ifi, nil
+}
+
+func linkFlags(rawFlags int32) Flags {
+	var f Flags
+	if rawFlags&syscall.IFF_UP != 0 {
+		f |= FlagUp
+	}
+	if rawFlags&syscall.IFF_BROADCAST != 0 {
+		f |= FlagBroadcast
+	}
+	if rawFlags&syscall.IFF_LOOPBACK != 0 {
+		f |= FlagLoopback
+	}
+	if rawFlags&syscall.IFF_POINTOPOINT != 0 {
+		f |= FlagPointToPoint
+	}
+	if rawFlags&syscall.IFF_MULTICAST != 0 {
+		f |= FlagMulticast
+	}
+	return f
+}
+
+// If the ifi is nil, interfaceAddrTable returns addresses for all
+// network interfaces.  Otherwise it returns addresses for a specific
+// interface.
+func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
+	index := 0
+	if ifi != nil {
+		index = ifi.Index
+	}
+	tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, index)
+	if err != nil {
+		return nil, os.NewSyscallError("route rib", err)
+	}
+	msgs, err := syscall.ParseRoutingMessage(tab)
+	if err != nil {
+		return nil, os.NewSyscallError("route message", err)
+	}
+	var ift []Interface
+	if index == 0 {
+		ift, err = parseInterfaceTable(index, msgs)
+		if err != nil {
+			return nil, err
+		}
+	}
+	var ifat []Addr
+	for _, m := range msgs {
+		switch m := m.(type) {
+		case *syscall.InterfaceAddrMessage:
+			if index == 0 || index == int(m.Header.Index) {
+				if index == 0 {
+					var err error
+					ifi, err = interfaceByIndex(ift, int(m.Header.Index))
+					if err != nil {
+						return nil, err
+					}
+				}
+				ifa, err := newAddr(ifi, m)
+				if err != nil {
+					return nil, err
+				}
+				if ifa != nil {
+					ifat = append(ifat, ifa)
+				}
+			}
+		}
+	}
+	return ifat, nil
+}
+
+func newAddr(ifi *Interface, m *syscall.InterfaceAddrMessage) (Addr, error) {
+	sas, err := syscall.ParseRoutingSockaddr(m)
+	if err != nil {
+		return nil, os.NewSyscallError("route sockaddr", err)
+	}
+	ifa := &IPNet{}
+	for i, sa := range sas {
+		switch sa := sa.(type) {
+		case *syscall.SockaddrInet4:
+			switch i {
+			case 0:
+				ifa.Mask = IPv4Mask(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
+			case 1:
+				ifa.IP = IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
+			}
+		case *syscall.SockaddrInet6:
+			switch i {
+			case 0:
+				ifa.Mask = make(IPMask, IPv6len)
+				copy(ifa.Mask, sa.Addr[:])
+			case 1:
+				ifa.IP = make(IP, IPv6len)
+				copy(ifa.IP, sa.Addr[:])
+				// NOTE: KAME based IPv6 protcol stack usually embeds
+				// the interface index in the interface-local or link-
+				// local address as the kernel-internal form.
+				if ifa.IP.IsLinkLocalUnicast() {
+					ifa.IP[2], ifa.IP[3] = 0, 0
+				}
+			}
+		default: // Sockaddrs contain syscall.SockaddrDatalink on NetBSD
+			return nil, nil
+		}
+	}
+	return ifa, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface_darwin.go b/third_party/gofrontend/libgo/go/net/interface_darwin.go
new file mode 100644
index 0000000..ad0937d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface_darwin.go
@@ -0,0 +1,63 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifi.Index)
+	if err != nil {
+		return nil, os.NewSyscallError("route rib", err)
+	}
+	msgs, err := syscall.ParseRoutingMessage(tab)
+	if err != nil {
+		return nil, os.NewSyscallError("route message", err)
+	}
+	var ifmat []Addr
+	for _, m := range msgs {
+		switch m := m.(type) {
+		case *syscall.InterfaceMulticastAddrMessage:
+			if ifi.Index == int(m.Header.Index) {
+				ifma, err := newMulticastAddr(ifi, m)
+				if err != nil {
+					return nil, err
+				}
+				ifmat = append(ifmat, ifma...)
+			}
+		}
+	}
+	return ifmat, nil
+}
+
+func newMulticastAddr(ifi *Interface, m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) {
+	sas, err := syscall.ParseRoutingSockaddr(m)
+	if err != nil {
+		return nil, os.NewSyscallError("route sockaddr", err)
+	}
+	var ifmat []Addr
+	for _, sa := range sas {
+		switch sa := sa.(type) {
+		case *syscall.SockaddrInet4:
+			ifma := &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])}
+			ifmat = append(ifmat, ifma.toAddr())
+		case *syscall.SockaddrInet6:
+			ifma := &IPAddr{IP: make(IP, IPv6len)}
+			copy(ifma.IP, sa.Addr[:])
+			// NOTE: KAME based IPv6 protocol stack usually embeds
+			// the interface index in the interface-local or link-
+			// local address as the kernel-internal form.
+			if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
+				ifma.IP[2], ifma.IP[3] = 0, 0
+			}
+			ifmat = append(ifmat, ifma.toAddr())
+		}
+	}
+	return ifmat, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface_dragonfly.go b/third_party/gofrontend/libgo/go/net/interface_dragonfly.go
new file mode 100644
index 0000000..c9ce5a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface_dragonfly.go
@@ -0,0 +1,12 @@
+// 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.
+
+package net
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	// TODO(mikio): Implement this like other platforms.
+	return nil, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface_freebsd.go b/third_party/gofrontend/libgo/go/net/interface_freebsd.go
new file mode 100644
index 0000000..5df7679
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface_freebsd.go
@@ -0,0 +1,63 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	tab, err := syscall.RouteRIB(syscall.NET_RT_IFMALIST, ifi.Index)
+	if err != nil {
+		return nil, os.NewSyscallError("route rib", err)
+	}
+	msgs, err := syscall.ParseRoutingMessage(tab)
+	if err != nil {
+		return nil, os.NewSyscallError("route message", err)
+	}
+	var ifmat []Addr
+	for _, m := range msgs {
+		switch m := m.(type) {
+		case *syscall.InterfaceMulticastAddrMessage:
+			if ifi.Index == int(m.Header.Index) {
+				ifma, err := newMulticastAddr(ifi, m)
+				if err != nil {
+					return nil, err
+				}
+				ifmat = append(ifmat, ifma...)
+			}
+		}
+	}
+	return ifmat, nil
+}
+
+func newMulticastAddr(ifi *Interface, m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) {
+	sas, err := syscall.ParseRoutingSockaddr(m)
+	if err != nil {
+		return nil, os.NewSyscallError("route sockaddr", err)
+	}
+	var ifmat []Addr
+	for _, sa := range sas {
+		switch sa := sa.(type) {
+		case *syscall.SockaddrInet4:
+			ifma := &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])}
+			ifmat = append(ifmat, ifma.toAddr())
+		case *syscall.SockaddrInet6:
+			ifma := &IPAddr{IP: make(IP, IPv6len)}
+			copy(ifma.IP, sa.Addr[:])
+			// NOTE: KAME based IPv6 protocol stack usually embeds
+			// the interface index in the interface-local or link-
+			// local address as the kernel-internal form.
+			if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
+				ifma.IP[2], ifma.IP[3] = 0, 0
+			}
+			ifmat = append(ifmat, ifma.toAddr())
+		}
+	}
+	return ifmat, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface_linux.go b/third_party/gofrontend/libgo/go/net/interface_linux.go
new file mode 100644
index 0000000..1115d0f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface_linux.go
@@ -0,0 +1,271 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"unsafe"
+)
+
+// If the ifindex is zero, interfaceTable returns mappings of all
+// network interfaces.  Otherwise it returns a mapping of a specific
+// interface.
+func interfaceTable(ifindex int) ([]Interface, error) {
+	tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
+	if err != nil {
+		return nil, os.NewSyscallError("netlink rib", err)
+	}
+	msgs, err := syscall.ParseNetlinkMessage(tab)
+	if err != nil {
+		return nil, os.NewSyscallError("netlink message", err)
+	}
+	var ift []Interface
+loop:
+	for _, m := range msgs {
+		switch m.Header.Type {
+		case syscall.NLMSG_DONE:
+			break loop
+		case syscall.RTM_NEWLINK:
+			ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
+			if ifindex == 0 || ifindex == int(ifim.Index) {
+				attrs, err := syscall.ParseNetlinkRouteAttr(&m)
+				if err != nil {
+					return nil, os.NewSyscallError("netlink routeattr", err)
+				}
+				ift = append(ift, *newLink(ifim, attrs))
+				if ifindex == int(ifim.Index) {
+					break loop
+				}
+			}
+		}
+	}
+	return ift, nil
+}
+
+const (
+	// See linux/if_arp.h.
+	// Note that Linux doesn't support IPv4 over IPv6 tunneling.
+	sysARPHardwareIPv4IPv4 = 768 // IPv4 over IPv4 tunneling
+	sysARPHardwareIPv6IPv6 = 769 // IPv6 over IPv6 tunneling
+	sysARPHardwareIPv6IPv4 = 776 // IPv6 over IPv4 tunneling
+	sysARPHardwareGREIPv4  = 778 // any over GRE over IPv4 tunneling
+	sysARPHardwareGREIPv6  = 823 // any over GRE over IPv6 tunneling
+)
+
+func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) *Interface {
+	ifi := &Interface{Index: int(ifim.Index), Flags: linkFlags(ifim.Flags)}
+	for _, a := range attrs {
+		switch a.Attr.Type {
+		case syscall.IFLA_ADDRESS:
+			// We never return any /32 or /128 IP address
+			// prefix on any IP tunnel interface as the
+			// hardware address.
+			switch len(a.Value) {
+			case IPv4len:
+				switch ifim.Type {
+				case sysARPHardwareIPv4IPv4, sysARPHardwareGREIPv4, sysARPHardwareIPv6IPv4:
+					continue
+				}
+			case IPv6len:
+				switch ifim.Type {
+				case sysARPHardwareIPv6IPv6, sysARPHardwareGREIPv6:
+					continue
+				}
+			}
+			var nonzero bool
+			for _, b := range a.Value {
+				if b != 0 {
+					nonzero = true
+					break
+				}
+			}
+			if nonzero {
+				ifi.HardwareAddr = a.Value[:]
+			}
+		case syscall.IFLA_IFNAME:
+			ifi.Name = string(a.Value[:len(a.Value)-1])
+		case syscall.IFLA_MTU:
+			ifi.MTU = int(*(*uint32)(unsafe.Pointer(&a.Value[:4][0])))
+		}
+	}
+	return ifi
+}
+
+func linkFlags(rawFlags uint32) Flags {
+	var f Flags
+	if rawFlags&syscall.IFF_UP != 0 {
+		f |= FlagUp
+	}
+	if rawFlags&syscall.IFF_BROADCAST != 0 {
+		f |= FlagBroadcast
+	}
+	if rawFlags&syscall.IFF_LOOPBACK != 0 {
+		f |= FlagLoopback
+	}
+	if rawFlags&syscall.IFF_POINTOPOINT != 0 {
+		f |= FlagPointToPoint
+	}
+	if rawFlags&syscall.IFF_MULTICAST != 0 {
+		f |= FlagMulticast
+	}
+	return f
+}
+
+// If the ifi is nil, interfaceAddrTable returns addresses for all
+// network interfaces.  Otherwise it returns addresses for a specific
+// interface.
+func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
+	tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
+	if err != nil {
+		return nil, os.NewSyscallError("netlink rib", err)
+	}
+	msgs, err := syscall.ParseNetlinkMessage(tab)
+	if err != nil {
+		return nil, os.NewSyscallError("netlink message", err)
+	}
+	var ift []Interface
+	if ifi == nil {
+		var err error
+		ift, err = interfaceTable(0)
+		if err != nil {
+			return nil, err
+		}
+	}
+	ifat, err := addrTable(ift, ifi, msgs)
+	if err != nil {
+		return nil, err
+	}
+	return ifat, nil
+}
+
+func addrTable(ift []Interface, ifi *Interface, msgs []syscall.NetlinkMessage) ([]Addr, error) {
+	var ifat []Addr
+loop:
+	for _, m := range msgs {
+		switch m.Header.Type {
+		case syscall.NLMSG_DONE:
+			break loop
+		case syscall.RTM_NEWADDR:
+			ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
+			if len(ift) != 0 || ifi.Index == int(ifam.Index) {
+				if len(ift) != 0 {
+					var err error
+					ifi, err = interfaceByIndex(ift, int(ifam.Index))
+					if err != nil {
+						return nil, err
+					}
+				}
+				attrs, err := syscall.ParseNetlinkRouteAttr(&m)
+				if err != nil {
+					return nil, os.NewSyscallError("netlink routeattr", err)
+				}
+				ifa := newAddr(ifi, ifam, attrs)
+				if ifa != nil {
+					ifat = append(ifat, ifa)
+				}
+			}
+		}
+	}
+	return ifat, nil
+}
+
+func newAddr(ifi *Interface, ifam *syscall.IfAddrmsg, attrs []syscall.NetlinkRouteAttr) Addr {
+	var ipPointToPoint bool
+	// Seems like we need to make sure whether the IP interface
+	// stack consists of IP point-to-point numbered or unnumbered
+	// addressing over point-to-point link encapsulation.
+	if ifi.Flags&FlagPointToPoint != 0 {
+		for _, a := range attrs {
+			if a.Attr.Type == syscall.IFA_LOCAL {
+				ipPointToPoint = true
+				break
+			}
+		}
+	}
+	for _, a := range attrs {
+		if ipPointToPoint && a.Attr.Type == syscall.IFA_ADDRESS || !ipPointToPoint && a.Attr.Type == syscall.IFA_LOCAL {
+			continue
+		}
+		switch ifam.Family {
+		case syscall.AF_INET:
+			return &IPNet{IP: IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3]), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv4len)}
+		case syscall.AF_INET6:
+			ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv6len)}
+			copy(ifa.IP, a.Value[:])
+			return ifa
+		}
+	}
+	return nil
+}
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	ifmat4 := parseProcNetIGMP("/proc/net/igmp", ifi)
+	ifmat6 := parseProcNetIGMP6("/proc/net/igmp6", ifi)
+	return append(ifmat4, ifmat6...), nil
+}
+
+func parseProcNetIGMP(path string, ifi *Interface) []Addr {
+	fd, err := open(path)
+	if err != nil {
+		return nil
+	}
+	defer fd.close()
+	var (
+		ifmat []Addr
+		name  string
+	)
+	fd.readLine() // skip first line
+	b := make([]byte, IPv4len)
+	for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
+		f := splitAtBytes(l, " :\r\t\n")
+		if len(f) < 4 {
+			continue
+		}
+		switch {
+		case l[0] != ' ' && l[0] != '\t': // new interface line
+			name = f[1]
+		case len(f[0]) == 8:
+			if ifi == nil || name == ifi.Name {
+				// The Linux kernel puts the IP
+				// address in /proc/net/igmp in native
+				// endianness.
+				for i := 0; i+1 < len(f[0]); i += 2 {
+					b[i/2], _ = xtoi2(f[0][i:i+2], 0)
+				}
+				i := *(*uint32)(unsafe.Pointer(&b[:4][0]))
+				ifma := IPAddr{IP: IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i))}
+				ifmat = append(ifmat, ifma.toAddr())
+			}
+		}
+	}
+	return ifmat
+}
+
+func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
+	fd, err := open(path)
+	if err != nil {
+		return nil
+	}
+	defer fd.close()
+	var ifmat []Addr
+	b := make([]byte, IPv6len)
+	for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
+		f := splitAtBytes(l, " \r\t\n")
+		if len(f) < 6 {
+			continue
+		}
+		if ifi == nil || f[1] == ifi.Name {
+			for i := 0; i+1 < len(f[2]); i += 2 {
+				b[i/2], _ = xtoi2(f[2][i:i+2], 0)
+			}
+			ifma := IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}}
+			ifmat = append(ifmat, ifma.toAddr())
+		}
+	}
+	return ifmat
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface_netbsd.go b/third_party/gofrontend/libgo/go/net/interface_netbsd.go
new file mode 100644
index 0000000..c9ce5a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface_netbsd.go
@@ -0,0 +1,12 @@
+// 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.
+
+package net
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	// TODO(mikio): Implement this like other platforms.
+	return nil, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface_openbsd.go b/third_party/gofrontend/libgo/go/net/interface_openbsd.go
new file mode 100644
index 0000000..c9ce5a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface_openbsd.go
@@ -0,0 +1,12 @@
+// 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.
+
+package net
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	// TODO(mikio): Implement this like other platforms.
+	return nil, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface_stub.go b/third_party/gofrontend/libgo/go/net/interface_stub.go
new file mode 100644
index 0000000..c38fb7f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface_stub.go
@@ -0,0 +1,27 @@
+// 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.
+
+// +build nacl plan9 solaris
+
+package net
+
+// If the ifindex is zero, interfaceTable returns mappings of all
+// network interfaces.  Otherwise it returns a mapping of a specific
+// interface.
+func interfaceTable(ifindex int) ([]Interface, error) {
+	return nil, nil
+}
+
+// If the ifi is nil, interfaceAddrTable returns addresses for all
+// network interfaces.  Otherwise it returns addresses for a specific
+// interface.
+func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
+	return nil, nil
+}
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	return nil, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface_test.go b/third_party/gofrontend/libgo/go/net/interface_test.go
new file mode 100644
index 0000000..efabb5f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface_test.go
@@ -0,0 +1,211 @@
+// 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.
+
+package net
+
+import (
+	"reflect"
+	"testing"
+)
+
+// loopbackInterface returns an available logical network interface
+// for loopback tests.  It returns nil if no suitable interface is
+// found.
+func loopbackInterface() *Interface {
+	ift, err := Interfaces()
+	if err != nil {
+		return nil
+	}
+	for _, ifi := range ift {
+		if ifi.Flags&FlagLoopback != 0 && ifi.Flags&FlagUp != 0 {
+			return &ifi
+		}
+	}
+	return nil
+}
+
+// ipv6LinkLocalUnicastAddr returns an IPv6 link-local unicast address
+// on the given network interface for tests. It returns "" if no
+// suitable address is found.
+func ipv6LinkLocalUnicastAddr(ifi *Interface) string {
+	if ifi == nil {
+		return ""
+	}
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		return ""
+	}
+	for _, ifa := range ifat {
+		switch ifa := ifa.(type) {
+		case *IPAddr:
+			if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() {
+				return ifa.IP.String()
+			}
+		case *IPNet:
+			if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() {
+				return ifa.IP.String()
+			}
+		}
+	}
+	return ""
+}
+
+func TestInterfaces(t *testing.T) {
+	ift, err := Interfaces()
+	if err != nil {
+		t.Fatalf("Interfaces failed: %v", err)
+	}
+	t.Logf("table: len/cap = %v/%v", len(ift), cap(ift))
+
+	for _, ifi := range ift {
+		ifxi, err := InterfaceByIndex(ifi.Index)
+		if err != nil {
+			t.Fatalf("InterfaceByIndex(%v) failed: %v", ifi.Index, err)
+		}
+		if !reflect.DeepEqual(ifxi, &ifi) {
+			t.Fatalf("InterfaceByIndex(%v) = %v, want %v", ifi.Index, ifxi, ifi)
+		}
+		ifxn, err := InterfaceByName(ifi.Name)
+		if err != nil {
+			t.Fatalf("InterfaceByName(%q) failed: %v", ifi.Name, err)
+		}
+		if !reflect.DeepEqual(ifxn, &ifi) {
+			t.Fatalf("InterfaceByName(%q) = %v, want %v", ifi.Name, ifxn, ifi)
+		}
+		t.Logf("%q: flags %q, ifindex %v, mtu %v", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
+		t.Logf("\thardware address %q", ifi.HardwareAddr.String())
+		testInterfaceAddrs(t, &ifi)
+		testInterfaceMulticastAddrs(t, &ifi)
+	}
+}
+
+func TestInterfaceAddrs(t *testing.T) {
+	ifat, err := InterfaceAddrs()
+	if err != nil {
+		t.Fatalf("InterfaceAddrs failed: %v", err)
+	}
+	t.Logf("table: len/cap = %v/%v", len(ifat), cap(ifat))
+	testAddrs(t, ifat)
+}
+
+func testInterfaceAddrs(t *testing.T, ifi *Interface) {
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		t.Fatalf("Interface.Addrs failed: %v", err)
+	}
+	testAddrs(t, ifat)
+}
+
+func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) {
+	ifmat, err := ifi.MulticastAddrs()
+	if err != nil {
+		t.Fatalf("Interface.MulticastAddrs failed: %v", err)
+	}
+	testMulticastAddrs(t, ifmat)
+}
+
+func testAddrs(t *testing.T, ifat []Addr) {
+	for _, ifa := range ifat {
+		switch ifa := ifa.(type) {
+		case *IPAddr:
+			if ifa == nil || ifa.IP == nil {
+				t.Errorf("\tunexpected value: %v, %v", ifa, ifa.IP)
+			} else {
+				t.Logf("\tinterface address %q", ifa.String())
+			}
+		case *IPNet:
+			if ifa == nil || ifa.IP == nil || ifa.Mask == nil {
+				t.Errorf("\tunexpected value: %v, %v, %v", ifa, ifa.IP, ifa.Mask)
+			} else {
+				_, prefixLen := ifa.Mask.Size()
+				if ifa.IP.To4() != nil && prefixLen != 8*IPv4len || ifa.IP.To16() != nil && ifa.IP.To4() == nil && prefixLen != 8*IPv6len {
+					t.Errorf("\tunexpected value: %v, %v, %v, %v", ifa, ifa.IP, ifa.Mask, prefixLen)
+				} else {
+					t.Logf("\tinterface address %q", ifa.String())
+				}
+			}
+		default:
+			t.Errorf("\tunexpected type: %T", ifa)
+		}
+	}
+}
+
+func testMulticastAddrs(t *testing.T, ifmat []Addr) {
+	for _, ifma := range ifmat {
+		switch ifma := ifma.(type) {
+		case *IPAddr:
+			if ifma == nil {
+				t.Errorf("\tunexpected value: %v", ifma)
+			} else {
+				t.Logf("\tjoined group address %q", ifma.String())
+			}
+		default:
+			t.Errorf("\tunexpected type: %T", ifma)
+		}
+	}
+}
+
+func BenchmarkInterfaces(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		if _, err := Interfaces(); err != nil {
+			b.Fatalf("Interfaces failed: %v", err)
+		}
+	}
+}
+
+func BenchmarkInterfaceByIndex(b *testing.B) {
+	ifi := loopbackInterface()
+	if ifi == nil {
+		b.Skip("loopback interface not found")
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := InterfaceByIndex(ifi.Index); err != nil {
+			b.Fatalf("InterfaceByIndex failed: %v", err)
+		}
+	}
+}
+
+func BenchmarkInterfaceByName(b *testing.B) {
+	ifi := loopbackInterface()
+	if ifi == nil {
+		b.Skip("loopback interface not found")
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := InterfaceByName(ifi.Name); err != nil {
+			b.Fatalf("InterfaceByName failed: %v", err)
+		}
+	}
+}
+
+func BenchmarkInterfaceAddrs(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		if _, err := InterfaceAddrs(); err != nil {
+			b.Fatalf("InterfaceAddrs failed: %v", err)
+		}
+	}
+}
+
+func BenchmarkInterfacesAndAddrs(b *testing.B) {
+	ifi := loopbackInterface()
+	if ifi == nil {
+		b.Skip("loopback interface not found")
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := ifi.Addrs(); err != nil {
+			b.Fatalf("Interface.Addrs failed: %v", err)
+		}
+	}
+}
+
+func BenchmarkInterfacesAndMulticastAddrs(b *testing.B) {
+	ifi := loopbackInterface()
+	if ifi == nil {
+		b.Skip("loopback interface not found")
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := ifi.MulticastAddrs(); err != nil {
+			b.Fatalf("Interface.MulticastAddrs failed: %v", err)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/interface_windows.go b/third_party/gofrontend/libgo/go/net/interface_windows.go
new file mode 100644
index 0000000..0759dc2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/interface_windows.go
@@ -0,0 +1,158 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"unsafe"
+)
+
+func bytePtrToString(p *uint8) string {
+	a := (*[10000]uint8)(unsafe.Pointer(p))
+	i := 0
+	for a[i] != 0 {
+		i++
+	}
+	return string(a[:i])
+}
+
+func getAdapterList() (*syscall.IpAdapterInfo, error) {
+	b := make([]byte, 1000)
+	l := uint32(len(b))
+	a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
+	// TODO(mikio): GetAdaptersInfo returns IP_ADAPTER_INFO that
+	// contains IPv4 address list only. We should use another API
+	// for fetching IPv6 stuff from the kernel.
+	err := syscall.GetAdaptersInfo(a, &l)
+	if err == syscall.ERROR_BUFFER_OVERFLOW {
+		b = make([]byte, l)
+		a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
+		err = syscall.GetAdaptersInfo(a, &l)
+	}
+	if err != nil {
+		return nil, os.NewSyscallError("GetAdaptersInfo", err)
+	}
+	return a, nil
+}
+
+func getInterfaceList() ([]syscall.InterfaceInfo, error) {
+	s, err := sysSocket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
+	if err != nil {
+		return nil, os.NewSyscallError("Socket", err)
+	}
+	defer syscall.Closesocket(s)
+
+	ii := [20]syscall.InterfaceInfo{}
+	ret := uint32(0)
+	size := uint32(unsafe.Sizeof(ii))
+	err = syscall.WSAIoctl(s, syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&ii[0])), size, &ret, nil, 0)
+	if err != nil {
+		return nil, os.NewSyscallError("WSAIoctl", err)
+	}
+	c := ret / uint32(unsafe.Sizeof(ii[0]))
+	return ii[:c-1], nil
+}
+
+// If the ifindex is zero, interfaceTable returns mappings of all
+// network interfaces.  Otherwise it returns a mapping of a specific
+// interface.
+func interfaceTable(ifindex int) ([]Interface, error) {
+	ai, err := getAdapterList()
+	if err != nil {
+		return nil, err
+	}
+
+	ii, err := getInterfaceList()
+	if err != nil {
+		return nil, err
+	}
+
+	var ift []Interface
+	for ; ai != nil; ai = ai.Next {
+		index := ai.Index
+		if ifindex == 0 || ifindex == int(index) {
+			var flags Flags
+
+			row := syscall.MibIfRow{Index: index}
+			e := syscall.GetIfEntry(&row)
+			if e != nil {
+				return nil, os.NewSyscallError("GetIfEntry", e)
+			}
+
+			for _, ii := range ii {
+				ip := (*syscall.RawSockaddrInet4)(unsafe.Pointer(&ii.Address)).Addr
+				ipv4 := IPv4(ip[0], ip[1], ip[2], ip[3])
+				ipl := &ai.IpAddressList
+				for ipl != nil {
+					ips := bytePtrToString(&ipl.IpAddress.String[0])
+					if ipv4.Equal(parseIPv4(ips)) {
+						break
+					}
+					ipl = ipl.Next
+				}
+				if ipl == nil {
+					continue
+				}
+				if ii.Flags&syscall.IFF_UP != 0 {
+					flags |= FlagUp
+				}
+				if ii.Flags&syscall.IFF_LOOPBACK != 0 {
+					flags |= FlagLoopback
+				}
+				if ii.Flags&syscall.IFF_BROADCAST != 0 {
+					flags |= FlagBroadcast
+				}
+				if ii.Flags&syscall.IFF_POINTTOPOINT != 0 {
+					flags |= FlagPointToPoint
+				}
+				if ii.Flags&syscall.IFF_MULTICAST != 0 {
+					flags |= FlagMulticast
+				}
+			}
+
+			name := bytePtrToString(&ai.AdapterName[0])
+
+			ifi := Interface{
+				Index:        int(index),
+				MTU:          int(row.Mtu),
+				Name:         name,
+				HardwareAddr: HardwareAddr(row.PhysAddr[:row.PhysAddrLen]),
+				Flags:        flags}
+			ift = append(ift, ifi)
+		}
+	}
+	return ift, nil
+}
+
+// If the ifi is nil, interfaceAddrTable returns addresses for all
+// network interfaces.  Otherwise it returns addresses for a specific
+// interface.
+func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
+	ai, err := getAdapterList()
+	if err != nil {
+		return nil, err
+	}
+
+	var ifat []Addr
+	for ; ai != nil; ai = ai.Next {
+		index := ai.Index
+		if ifi == nil || ifi.Index == int(index) {
+			ipl := &ai.IpAddressList
+			for ; ipl != nil; ipl = ipl.Next {
+				ifa := IPAddr{IP: parseIPv4(bytePtrToString(&ipl.IpAddress.String[0]))}
+				ifat = append(ifat, ifa.toAddr())
+			}
+		}
+	}
+	return ifat, nil
+}
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	// TODO(mikio): Implement this like other platforms.
+	return nil, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/ip.go b/third_party/gofrontend/libgo/go/net/ip.go
new file mode 100644
index 0000000..0582009
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/ip.go
@@ -0,0 +1,681 @@
+// 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.
+
+// IP address manipulations
+//
+// IPv4 addresses are 4 bytes; IPv6 addresses are 16 bytes.
+// An IPv4 address can be converted to an IPv6 address by
+// adding a canonical prefix (10 zeros, 2 0xFFs).
+// This library accepts either size of byte slice but always
+// returns 16-byte addresses.
+
+package net
+
+import "errors"
+
+// IP address lengths (bytes).
+const (
+	IPv4len = 4
+	IPv6len = 16
+)
+
+// An IP is a single IP address, a slice of bytes.
+// Functions in this package accept either 4-byte (IPv4)
+// or 16-byte (IPv6) slices as input.
+//
+// Note that in this documentation, referring to an
+// IP address as an IPv4 address or an IPv6 address
+// is a semantic property of the address, not just the
+// length of the byte slice: a 16-byte slice can still
+// be an IPv4 address.
+type IP []byte
+
+// An IP mask is an IP address.
+type IPMask []byte
+
+// An IPNet represents an IP network.
+type IPNet struct {
+	IP   IP     // network number
+	Mask IPMask // network mask
+}
+
+// IPv4 returns the IP address (in 16-byte form) of the
+// IPv4 address a.b.c.d.
+func IPv4(a, b, c, d byte) IP {
+	p := make(IP, IPv6len)
+	copy(p, v4InV6Prefix)
+	p[12] = a
+	p[13] = b
+	p[14] = c
+	p[15] = d
+	return p
+}
+
+var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
+
+// IPv4Mask returns the IP mask (in 4-byte form) of the
+// IPv4 mask a.b.c.d.
+func IPv4Mask(a, b, c, d byte) IPMask {
+	p := make(IPMask, IPv4len)
+	p[0] = a
+	p[1] = b
+	p[2] = c
+	p[3] = d
+	return p
+}
+
+// CIDRMask returns an IPMask consisting of `ones' 1 bits
+// followed by 0s up to a total length of `bits' bits.
+// For a mask of this form, CIDRMask is the inverse of IPMask.Size.
+func CIDRMask(ones, bits int) IPMask {
+	if bits != 8*IPv4len && bits != 8*IPv6len {
+		return nil
+	}
+	if ones < 0 || ones > bits {
+		return nil
+	}
+	l := bits / 8
+	m := make(IPMask, l)
+	n := uint(ones)
+	for i := 0; i < l; i++ {
+		if n >= 8 {
+			m[i] = 0xff
+			n -= 8
+			continue
+		}
+		m[i] = ^byte(0xff >> n)
+		n = 0
+	}
+	return m
+}
+
+// Well-known IPv4 addresses
+var (
+	IPv4bcast     = IPv4(255, 255, 255, 255) // broadcast
+	IPv4allsys    = IPv4(224, 0, 0, 1)       // all systems
+	IPv4allrouter = IPv4(224, 0, 0, 2)       // all routers
+	IPv4zero      = IPv4(0, 0, 0, 0)         // all zeros
+)
+
+// Well-known IPv6 addresses
+var (
+	IPv6zero                   = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	IPv6unspecified            = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	IPv6loopback               = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
+	IPv6interfacelocalallnodes = IP{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
+	IPv6linklocalallnodes      = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
+	IPv6linklocalallrouters    = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}
+)
+
+// IsUnspecified returns true if ip is an unspecified address.
+func (ip IP) IsUnspecified() bool {
+	if ip.Equal(IPv4zero) || ip.Equal(IPv6unspecified) {
+		return true
+	}
+	return false
+}
+
+// IsLoopback returns true if ip is a loopback address.
+func (ip IP) IsLoopback() bool {
+	if ip4 := ip.To4(); ip4 != nil && ip4[0] == 127 {
+		return true
+	}
+	return ip.Equal(IPv6loopback)
+}
+
+// IsMulticast returns true if ip is a multicast address.
+func (ip IP) IsMulticast() bool {
+	if ip4 := ip.To4(); ip4 != nil && ip4[0]&0xf0 == 0xe0 {
+		return true
+	}
+	return ip[0] == 0xff
+}
+
+// IsInterfaceLinkLocalMulticast returns true if ip is
+// an interface-local multicast address.
+func (ip IP) IsInterfaceLocalMulticast() bool {
+	return len(ip) == IPv6len && ip[0] == 0xff && ip[1]&0x0f == 0x01
+}
+
+// IsLinkLocalMulticast returns true if ip is a link-local
+// multicast address.
+func (ip IP) IsLinkLocalMulticast() bool {
+	if ip4 := ip.To4(); ip4 != nil && ip4[0] == 224 && ip4[1] == 0 && ip4[2] == 0 {
+		return true
+	}
+	return ip[0] == 0xff && ip[1]&0x0f == 0x02
+}
+
+// IsLinkLocalUnicast returns true if ip is a link-local
+// unicast address.
+func (ip IP) IsLinkLocalUnicast() bool {
+	if ip4 := ip.To4(); ip4 != nil && ip4[0] == 169 && ip4[1] == 254 {
+		return true
+	}
+	return ip[0] == 0xfe && ip[1]&0xc0 == 0x80
+}
+
+// IsGlobalUnicast returns true if ip is a global unicast
+// address.
+func (ip IP) IsGlobalUnicast() bool {
+	return !ip.IsUnspecified() &&
+		!ip.IsLoopback() &&
+		!ip.IsMulticast() &&
+		!ip.IsLinkLocalUnicast()
+}
+
+// Is p all zeros?
+func isZeros(p IP) bool {
+	for i := 0; i < len(p); i++ {
+		if p[i] != 0 {
+			return false
+		}
+	}
+	return true
+}
+
+// To4 converts the IPv4 address ip to a 4-byte representation.
+// If ip is not an IPv4 address, To4 returns nil.
+func (ip IP) To4() IP {
+	if len(ip) == IPv4len {
+		return ip
+	}
+	if len(ip) == IPv6len &&
+		isZeros(ip[0:10]) &&
+		ip[10] == 0xff &&
+		ip[11] == 0xff {
+		return ip[12:16]
+	}
+	return nil
+}
+
+// To16 converts the IP address ip to a 16-byte representation.
+// If ip is not an IP address (it is the wrong length), To16 returns nil.
+func (ip IP) To16() IP {
+	if len(ip) == IPv4len {
+		return IPv4(ip[0], ip[1], ip[2], ip[3])
+	}
+	if len(ip) == IPv6len {
+		return ip
+	}
+	return nil
+}
+
+// Default route masks for IPv4.
+var (
+	classAMask = IPv4Mask(0xff, 0, 0, 0)
+	classBMask = IPv4Mask(0xff, 0xff, 0, 0)
+	classCMask = IPv4Mask(0xff, 0xff, 0xff, 0)
+)
+
+// DefaultMask returns the default IP mask for the IP address ip.
+// Only IPv4 addresses have default masks; DefaultMask returns
+// nil if ip is not a valid IPv4 address.
+func (ip IP) DefaultMask() IPMask {
+	if ip = ip.To4(); ip == nil {
+		return nil
+	}
+	switch true {
+	case ip[0] < 0x80:
+		return classAMask
+	case ip[0] < 0xC0:
+		return classBMask
+	default:
+		return classCMask
+	}
+}
+
+func allFF(b []byte) bool {
+	for _, c := range b {
+		if c != 0xff {
+			return false
+		}
+	}
+	return true
+}
+
+// Mask returns the result of masking the IP address ip with mask.
+func (ip IP) Mask(mask IPMask) IP {
+	if len(mask) == IPv6len && len(ip) == IPv4len && allFF(mask[:12]) {
+		mask = mask[12:]
+	}
+	if len(mask) == IPv4len && len(ip) == IPv6len && bytesEqual(ip[:12], v4InV6Prefix) {
+		ip = ip[12:]
+	}
+	n := len(ip)
+	if n != len(mask) {
+		return nil
+	}
+	out := make(IP, n)
+	for i := 0; i < n; i++ {
+		out[i] = ip[i] & mask[i]
+	}
+	return out
+}
+
+// String returns the string form of the IP address ip.
+// If the address is an IPv4 address, the string representation
+// is dotted decimal ("74.125.19.99").  Otherwise the representation
+// is IPv6 ("2001:4860:0:2001::68").
+func (ip IP) String() string {
+	p := ip
+
+	if len(ip) == 0 {
+		return "<nil>"
+	}
+
+	// If IPv4, use dotted notation.
+	if p4 := p.To4(); len(p4) == IPv4len {
+		return itod(uint(p4[0])) + "." +
+			itod(uint(p4[1])) + "." +
+			itod(uint(p4[2])) + "." +
+			itod(uint(p4[3]))
+	}
+	if len(p) != IPv6len {
+		return "?"
+	}
+
+	// Find longest run of zeros.
+	e0 := -1
+	e1 := -1
+	for i := 0; i < IPv6len; i += 2 {
+		j := i
+		for j < IPv6len && p[j] == 0 && p[j+1] == 0 {
+			j += 2
+		}
+		if j > i && j-i > e1-e0 {
+			e0 = i
+			e1 = j
+		}
+	}
+	// The symbol "::" MUST NOT be used to shorten just one 16 bit 0 field.
+	if e1-e0 <= 2 {
+		e0 = -1
+		e1 = -1
+	}
+
+	// Print with possible :: in place of run of zeros
+	var s string
+	for i := 0; i < IPv6len; i += 2 {
+		if i == e0 {
+			s += "::"
+			i = e1
+			if i >= IPv6len {
+				break
+			}
+		} else if i > 0 {
+			s += ":"
+		}
+		s += itox((uint(p[i])<<8)|uint(p[i+1]), 1)
+	}
+	return s
+}
+
+// ipEmptyString is like ip.String except that it returns
+// an empty string when ip is unset.
+func ipEmptyString(ip IP) string {
+	if len(ip) == 0 {
+		return ""
+	}
+	return ip.String()
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+// The encoding is the same as returned by String.
+func (ip IP) MarshalText() ([]byte, error) {
+	if len(ip) == 0 {
+		return []byte(""), nil
+	}
+	if len(ip) != IPv4len && len(ip) != IPv6len {
+		return nil, errors.New("invalid IP address")
+	}
+	return []byte(ip.String()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+// The IP address is expected in a form accepted by ParseIP.
+func (ip *IP) UnmarshalText(text []byte) error {
+	if len(text) == 0 {
+		*ip = nil
+		return nil
+	}
+	s := string(text)
+	x := ParseIP(s)
+	if x == nil {
+		return &ParseError{"IP address", s}
+	}
+	*ip = x
+	return nil
+}
+
+// Equal returns true if ip and x are the same IP address.
+// An IPv4 address and that same address in IPv6 form are
+// considered to be equal.
+func (ip IP) Equal(x IP) bool {
+	if len(ip) == len(x) {
+		return bytesEqual(ip, x)
+	}
+	if len(ip) == IPv4len && len(x) == IPv6len {
+		return bytesEqual(x[0:12], v4InV6Prefix) && bytesEqual(ip, x[12:])
+	}
+	if len(ip) == IPv6len && len(x) == IPv4len {
+		return bytesEqual(ip[0:12], v4InV6Prefix) && bytesEqual(ip[12:], x)
+	}
+	return false
+}
+
+func bytesEqual(x, y []byte) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, b := range x {
+		if y[i] != b {
+			return false
+		}
+	}
+	return true
+}
+
+// If mask is a sequence of 1 bits followed by 0 bits,
+// return the number of 1 bits.
+func simpleMaskLength(mask IPMask) int {
+	var n int
+	for i, v := range mask {
+		if v == 0xff {
+			n += 8
+			continue
+		}
+		// found non-ff byte
+		// count 1 bits
+		for v&0x80 != 0 {
+			n++
+			v <<= 1
+		}
+		// rest must be 0 bits
+		if v != 0 {
+			return -1
+		}
+		for i++; i < len(mask); i++ {
+			if mask[i] != 0 {
+				return -1
+			}
+		}
+		break
+	}
+	return n
+}
+
+// Size returns the number of leading ones and total bits in the mask.
+// If the mask is not in the canonical form--ones followed by zeros--then
+// Size returns 0, 0.
+func (m IPMask) Size() (ones, bits int) {
+	ones, bits = simpleMaskLength(m), len(m)*8
+	if ones == -1 {
+		return 0, 0
+	}
+	return
+}
+
+// String returns the hexadecimal form of m, with no punctuation.
+func (m IPMask) String() string {
+	s := ""
+	for _, b := range m {
+		s += itox(uint(b), 2)
+	}
+	if len(s) == 0 {
+		return "<nil>"
+	}
+	return s
+}
+
+func networkNumberAndMask(n *IPNet) (ip IP, m IPMask) {
+	if ip = n.IP.To4(); ip == nil {
+		ip = n.IP
+		if len(ip) != IPv6len {
+			return nil, nil
+		}
+	}
+	m = n.Mask
+	switch len(m) {
+	case IPv4len:
+		if len(ip) != IPv4len {
+			return nil, nil
+		}
+	case IPv6len:
+		if len(ip) == IPv4len {
+			m = m[12:]
+		}
+	default:
+		return nil, nil
+	}
+	return
+}
+
+// Contains reports whether the network includes ip.
+func (n *IPNet) Contains(ip IP) bool {
+	nn, m := networkNumberAndMask(n)
+	if x := ip.To4(); x != nil {
+		ip = x
+	}
+	l := len(ip)
+	if l != len(nn) {
+		return false
+	}
+	for i := 0; i < l; i++ {
+		if nn[i]&m[i] != ip[i]&m[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// Network returns the address's network name, "ip+net".
+func (n *IPNet) Network() string { return "ip+net" }
+
+// String returns the CIDR notation of n like "192.168.100.1/24"
+// or "2001:DB8::/48" as defined in RFC 4632 and RFC 4291.
+// If the mask is not in the canonical form, it returns the
+// string which consists of an IP address, followed by a slash
+// character and a mask expressed as hexadecimal form with no
+// punctuation like "192.168.100.1/c000ff00".
+func (n *IPNet) String() string {
+	nn, m := networkNumberAndMask(n)
+	if nn == nil || m == nil {
+		return "<nil>"
+	}
+	l := simpleMaskLength(m)
+	if l == -1 {
+		return nn.String() + "/" + m.String()
+	}
+	return nn.String() + "/" + itod(uint(l))
+}
+
+// Parse IPv4 address (d.d.d.d).
+func parseIPv4(s string) IP {
+	var p [IPv4len]byte
+	i := 0
+	for j := 0; j < IPv4len; j++ {
+		if i >= len(s) {
+			// Missing octets.
+			return nil
+		}
+		if j > 0 {
+			if s[i] != '.' {
+				return nil
+			}
+			i++
+		}
+		var (
+			n  int
+			ok bool
+		)
+		n, i, ok = dtoi(s, i)
+		if !ok || n > 0xFF {
+			return nil
+		}
+		p[j] = byte(n)
+	}
+	if i != len(s) {
+		return nil
+	}
+	return IPv4(p[0], p[1], p[2], p[3])
+}
+
+// parseIPv6 parses s as a literal IPv6 address described in RFC 4291
+// and RFC 5952.  It can also parse a literal scoped IPv6 address with
+// zone identifier which is described in RFC 4007 when zoneAllowed is
+// true.
+func parseIPv6(s string, zoneAllowed bool) (ip IP, zone string) {
+	ip = make(IP, IPv6len)
+	ellipsis := -1 // position of ellipsis in p
+	i := 0         // index in string s
+
+	if zoneAllowed {
+		s, zone = splitHostZone(s)
+	}
+
+	// Might have leading ellipsis
+	if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
+		ellipsis = 0
+		i = 2
+		// Might be only ellipsis
+		if i == len(s) {
+			return ip, zone
+		}
+	}
+
+	// Loop, parsing hex numbers followed by colon.
+	j := 0
+	for j < IPv6len {
+		// Hex number.
+		n, i1, ok := xtoi(s, i)
+		if !ok || n > 0xFFFF {
+			return nil, zone
+		}
+
+		// If followed by dot, might be in trailing IPv4.
+		if i1 < len(s) && s[i1] == '.' {
+			if ellipsis < 0 && j != IPv6len-IPv4len {
+				// Not the right place.
+				return nil, zone
+			}
+			if j+IPv4len > IPv6len {
+				// Not enough room.
+				return nil, zone
+			}
+			ip4 := parseIPv4(s[i:])
+			if ip4 == nil {
+				return nil, zone
+			}
+			ip[j] = ip4[12]
+			ip[j+1] = ip4[13]
+			ip[j+2] = ip4[14]
+			ip[j+3] = ip4[15]
+			i = len(s)
+			j += IPv4len
+			break
+		}
+
+		// Save this 16-bit chunk.
+		ip[j] = byte(n >> 8)
+		ip[j+1] = byte(n)
+		j += 2
+
+		// Stop at end of string.
+		i = i1
+		if i == len(s) {
+			break
+		}
+
+		// Otherwise must be followed by colon and more.
+		if s[i] != ':' || i+1 == len(s) {
+			return nil, zone
+		}
+		i++
+
+		// Look for ellipsis.
+		if s[i] == ':' {
+			if ellipsis >= 0 { // already have one
+				return nil, zone
+			}
+			ellipsis = j
+			if i++; i == len(s) { // can be at end
+				break
+			}
+		}
+	}
+
+	// Must have used entire string.
+	if i != len(s) {
+		return nil, zone
+	}
+
+	// If didn't parse enough, expand ellipsis.
+	if j < IPv6len {
+		if ellipsis < 0 {
+			return nil, zone
+		}
+		n := IPv6len - j
+		for k := j - 1; k >= ellipsis; k-- {
+			ip[k+n] = ip[k]
+		}
+		for k := ellipsis + n - 1; k >= ellipsis; k-- {
+			ip[k] = 0
+		}
+	} else if ellipsis >= 0 {
+		// Ellipsis must represent at least one 0 group.
+		return nil, zone
+	}
+	return ip, zone
+}
+
+// A ParseError represents a malformed text string and the type of string that was expected.
+type ParseError struct {
+	Type string
+	Text string
+}
+
+func (e *ParseError) Error() string {
+	return "invalid " + e.Type + ": " + e.Text
+}
+
+// ParseIP parses s as an IP address, returning the result.
+// The string s can be in dotted decimal ("74.125.19.99")
+// or IPv6 ("2001:4860:0:2001::68") form.
+// If s is not a valid textual representation of an IP address,
+// ParseIP returns nil.
+func ParseIP(s string) IP {
+	if ip := parseIPv4(s); ip != nil {
+		return ip
+	}
+	ip, _ := parseIPv6(s, false)
+	return ip
+}
+
+// ParseCIDR parses s as a CIDR notation IP address and mask,
+// like "192.168.100.1/24" or "2001:DB8::/48", as defined in
+// RFC 4632 and RFC 4291.
+//
+// It returns the IP address and the network implied by the IP
+// and mask.  For example, ParseCIDR("192.168.100.1/16") returns
+// the IP address 192.168.100.1 and the network 192.168.0.0/16.
+func ParseCIDR(s string) (IP, *IPNet, error) {
+	i := byteIndex(s, '/')
+	if i < 0 {
+		return nil, nil, &ParseError{"CIDR address", s}
+	}
+	addr, mask := s[:i], s[i+1:]
+	iplen := IPv4len
+	ip := parseIPv4(addr)
+	if ip == nil {
+		iplen = IPv6len
+		ip, _ = parseIPv6(addr, false)
+	}
+	n, i, ok := dtoi(mask, 0)
+	if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen {
+		return nil, nil, &ParseError{"CIDR address", s}
+	}
+	m := CIDRMask(n, 8*iplen)
+	return ip, &IPNet{IP: ip.Mask(m), Mask: m}, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/ip_test.go b/third_party/gofrontend/libgo/go/net/ip_test.go
new file mode 100644
index 0000000..ffeb9d3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/ip_test.go
@@ -0,0 +1,439 @@
+// 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 net
+
+import (
+	"reflect"
+	"runtime"
+	"testing"
+)
+
+var parseIPTests = []struct {
+	in  string
+	out IP
+}{
+	{"127.0.1.2", IPv4(127, 0, 1, 2)},
+	{"127.0.0.1", IPv4(127, 0, 0, 1)},
+	{"127.0.0.256", nil},
+	{"abc", nil},
+	{"123:", nil},
+	{"::ffff:127.0.0.1", IPv4(127, 0, 0, 1)},
+	{"2001:4860:0:2001::68", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}},
+	{"::ffff:4a7d:1363", IPv4(74, 125, 19, 99)},
+	{"fe80::1%lo0", nil},
+	{"fe80::1%911", nil},
+	{"", nil},
+	{"a1:a2:a3:a4::b1:b2:b3:b4", nil}, // Issue 6628
+}
+
+func TestParseIP(t *testing.T) {
+	for _, tt := range parseIPTests {
+		if out := ParseIP(tt.in); !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("ParseIP(%q) = %v, want %v", tt.in, out, tt.out)
+		}
+		if tt.in == "" {
+			// Tested in TestMarshalEmptyIP below.
+			continue
+		}
+		var out IP
+		if err := out.UnmarshalText([]byte(tt.in)); !reflect.DeepEqual(out, tt.out) || (tt.out == nil) != (err != nil) {
+			t.Errorf("IP.UnmarshalText(%q) = %v, %v, want %v", tt.in, out, err, tt.out)
+		}
+	}
+}
+
+// Issue 6339
+func TestMarshalEmptyIP(t *testing.T) {
+	for _, in := range [][]byte{nil, []byte("")} {
+		var out = IP{1, 2, 3, 4}
+		if err := out.UnmarshalText(in); err != nil || out != nil {
+			t.Errorf("UnmarshalText(%v) = %v, %v; want nil, nil", in, out, err)
+		}
+	}
+	var ip IP
+	got, err := ip.MarshalText()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !reflect.DeepEqual(got, []byte("")) {
+		t.Errorf(`got %#v, want []byte("")`, got)
+	}
+}
+
+var ipStringTests = []struct {
+	in  IP
+	out string // see RFC 5952
+}{
+	{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}, "2001:db8::123:12:1"},
+	{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1}, "2001:db8::1"},
+	{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1}, "2001:db8:0:1:0:1:0:1"},
+	{IP{0x20, 0x1, 0xd, 0xb8, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0}, "2001:db8:1:0:1:0:1:0"},
+	{IP{0x20, 0x1, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1}, "2001::1:0:0:1"},
+	{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0}, "2001:db8:0:0:1::"},
+	{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1}, "2001:db8::1:0:0:1"},
+	{IP{0x20, 0x1, 0xD, 0xB8, 0, 0, 0, 0, 0, 0xA, 0, 0xB, 0, 0xC, 0, 0xD}, "2001:db8::a:b:c:d"},
+	{IPv4(192, 168, 0, 1), "192.168.0.1"},
+	{nil, ""},
+}
+
+func TestIPString(t *testing.T) {
+	for _, tt := range ipStringTests {
+		if tt.in != nil {
+			if out := tt.in.String(); out != tt.out {
+				t.Errorf("IP.String(%v) = %q, want %q", tt.in, out, tt.out)
+			}
+		}
+		if out, err := tt.in.MarshalText(); string(out) != tt.out || err != nil {
+			t.Errorf("IP.MarshalText(%v) = %q, %v, want %q, nil", tt.in, out, err, tt.out)
+		}
+	}
+}
+
+var ipMaskTests = []struct {
+	in   IP
+	mask IPMask
+	out  IP
+}{
+	{IPv4(192, 168, 1, 127), IPv4Mask(255, 255, 255, 128), IPv4(192, 168, 1, 0)},
+	{IPv4(192, 168, 1, 127), IPMask(ParseIP("255.255.255.192")), IPv4(192, 168, 1, 64)},
+	{IPv4(192, 168, 1, 127), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0")), IPv4(192, 168, 1, 96)},
+	{IPv4(192, 168, 1, 127), IPv4Mask(255, 0, 255, 0), IPv4(192, 0, 1, 0)},
+	{ParseIP("2001:db8::1"), IPMask(ParseIP("ffff:ff80::")), ParseIP("2001:d80::")},
+	{ParseIP("2001:db8::1"), IPMask(ParseIP("f0f0:0f0f::")), ParseIP("2000:d08::")},
+}
+
+func TestIPMask(t *testing.T) {
+	for _, tt := range ipMaskTests {
+		if out := tt.in.Mask(tt.mask); out == nil || !tt.out.Equal(out) {
+			t.Errorf("IP(%v).Mask(%v) = %v, want %v", tt.in, tt.mask, out, tt.out)
+		}
+	}
+}
+
+var ipMaskStringTests = []struct {
+	in  IPMask
+	out string
+}{
+	{IPv4Mask(255, 255, 255, 240), "fffffff0"},
+	{IPv4Mask(255, 0, 128, 0), "ff008000"},
+	{IPMask(ParseIP("ffff:ff80::")), "ffffff80000000000000000000000000"},
+	{IPMask(ParseIP("ef00:ff80::cafe:0")), "ef00ff800000000000000000cafe0000"},
+	{nil, "<nil>"},
+}
+
+func TestIPMaskString(t *testing.T) {
+	for _, tt := range ipMaskStringTests {
+		if out := tt.in.String(); out != tt.out {
+			t.Errorf("IPMask.String(%v) = %q, want %q", tt.in, out, tt.out)
+		}
+	}
+}
+
+var parseCIDRTests = []struct {
+	in  string
+	ip  IP
+	net *IPNet
+	err error
+}{
+	{"135.104.0.0/32", IPv4(135, 104, 0, 0), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 255)}, nil},
+	{"0.0.0.0/24", IPv4(0, 0, 0, 0), &IPNet{IP: IPv4(0, 0, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
+	{"135.104.0.0/24", IPv4(135, 104, 0, 0), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
+	{"135.104.0.1/32", IPv4(135, 104, 0, 1), &IPNet{IP: IPv4(135, 104, 0, 1), Mask: IPv4Mask(255, 255, 255, 255)}, nil},
+	{"135.104.0.1/24", IPv4(135, 104, 0, 1), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
+	{"::1/128", ParseIP("::1"), &IPNet{IP: ParseIP("::1"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))}, nil},
+	{"abcd:2345::/127", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"))}, nil},
+	{"abcd:2345::/65", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:8000::"))}, nil},
+	{"abcd:2345::/64", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff::"))}, nil},
+	{"abcd:2345::/63", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:fffe::"))}, nil},
+	{"abcd:2345::/33", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:8000::"))}, nil},
+	{"abcd:2345::/32", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff::"))}, nil},
+	{"abcd:2344::/31", ParseIP("abcd:2344::"), &IPNet{IP: ParseIP("abcd:2344::"), Mask: IPMask(ParseIP("ffff:fffe::"))}, nil},
+	{"abcd:2300::/24", ParseIP("abcd:2300::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil},
+	{"abcd:2345::/24", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil},
+	{"2001:DB8::/48", ParseIP("2001:DB8::"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
+	{"2001:DB8::1/48", ParseIP("2001:DB8::1"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
+	{"192.168.1.1/255.255.255.0", nil, nil, &ParseError{"CIDR address", "192.168.1.1/255.255.255.0"}},
+	{"192.168.1.1/35", nil, nil, &ParseError{"CIDR address", "192.168.1.1/35"}},
+	{"2001:db8::1/-1", nil, nil, &ParseError{"CIDR address", "2001:db8::1/-1"}},
+	{"", nil, nil, &ParseError{"CIDR address", ""}},
+}
+
+func TestParseCIDR(t *testing.T) {
+	for _, tt := range parseCIDRTests {
+		ip, net, err := ParseCIDR(tt.in)
+		if !reflect.DeepEqual(err, tt.err) {
+			t.Errorf("ParseCIDR(%q) = %v, %v; want %v, %v", tt.in, ip, net, tt.ip, tt.net)
+		}
+		if err == nil && (!tt.ip.Equal(ip) || !tt.net.IP.Equal(net.IP) || !reflect.DeepEqual(net.Mask, tt.net.Mask)) {
+			t.Errorf("ParseCIDR(%q) = %v, {%v, %v}; want %v, {%v, %v}", tt.in, ip, net.IP, net.Mask, tt.ip, tt.net.IP, tt.net.Mask)
+		}
+	}
+}
+
+var ipNetContainsTests = []struct {
+	ip  IP
+	net *IPNet
+	ok  bool
+}{
+	{IPv4(172, 16, 1, 1), &IPNet{IP: IPv4(172, 16, 0, 0), Mask: CIDRMask(12, 32)}, true},
+	{IPv4(172, 24, 0, 1), &IPNet{IP: IPv4(172, 16, 0, 0), Mask: CIDRMask(13, 32)}, false},
+	{IPv4(192, 168, 0, 3), &IPNet{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(0, 0, 255, 252)}, true},
+	{IPv4(192, 168, 0, 4), &IPNet{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(0, 255, 0, 252)}, false},
+	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: CIDRMask(47, 128)}, true},
+	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:2::"), Mask: CIDRMask(47, 128)}, false},
+	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: IPMask(ParseIP("ffff:0:ffff::"))}, true},
+	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: IPMask(ParseIP("0:0:0:ffff::"))}, false},
+}
+
+func TestIPNetContains(t *testing.T) {
+	for _, tt := range ipNetContainsTests {
+		if ok := tt.net.Contains(tt.ip); ok != tt.ok {
+			t.Errorf("IPNet(%v).Contains(%v) = %v, want %v", tt.net, tt.ip, ok, tt.ok)
+		}
+	}
+}
+
+var ipNetStringTests = []struct {
+	in  *IPNet
+	out string
+}{
+	{&IPNet{IP: IPv4(192, 168, 1, 0), Mask: CIDRMask(26, 32)}, "192.168.1.0/26"},
+	{&IPNet{IP: IPv4(192, 168, 1, 0), Mask: IPv4Mask(255, 0, 255, 0)}, "192.168.1.0/ff00ff00"},
+	{&IPNet{IP: ParseIP("2001:db8::"), Mask: CIDRMask(55, 128)}, "2001:db8::/55"},
+	{&IPNet{IP: ParseIP("2001:db8::"), Mask: IPMask(ParseIP("8000:f123:0:cafe::"))}, "2001:db8::/8000f1230000cafe0000000000000000"},
+}
+
+func TestIPNetString(t *testing.T) {
+	for _, tt := range ipNetStringTests {
+		if out := tt.in.String(); out != tt.out {
+			t.Errorf("IPNet.String(%v) = %q, want %q", tt.in, out, tt.out)
+		}
+	}
+}
+
+var cidrMaskTests = []struct {
+	ones int
+	bits int
+	out  IPMask
+}{
+	{0, 32, IPv4Mask(0, 0, 0, 0)},
+	{12, 32, IPv4Mask(255, 240, 0, 0)},
+	{24, 32, IPv4Mask(255, 255, 255, 0)},
+	{32, 32, IPv4Mask(255, 255, 255, 255)},
+	{0, 128, IPMask{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+	{4, 128, IPMask{0xf0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+	{48, 128, IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+	{128, 128, IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
+	{33, 32, nil},
+	{32, 33, nil},
+	{-1, 128, nil},
+	{128, -1, nil},
+}
+
+func TestCIDRMask(t *testing.T) {
+	for _, tt := range cidrMaskTests {
+		if out := CIDRMask(tt.ones, tt.bits); !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("CIDRMask(%v, %v) = %v, want %v", tt.ones, tt.bits, out, tt.out)
+		}
+	}
+}
+
+var (
+	v4addr         = IP{192, 168, 0, 1}
+	v4mappedv6addr = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 0, 1}
+	v6addr         = IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}
+	v4mask         = IPMask{255, 255, 255, 0}
+	v4mappedv6mask = IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 255, 255, 255, 0}
+	v6mask         = IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}
+	badaddr        = IP{192, 168, 0}
+	badmask        = IPMask{255, 255, 0}
+	v4maskzero     = IPMask{0, 0, 0, 0}
+)
+
+var networkNumberAndMaskTests = []struct {
+	in  IPNet
+	out IPNet
+}{
+	{IPNet{IP: v4addr, Mask: v4mask}, IPNet{IP: v4addr, Mask: v4mask}},
+	{IPNet{IP: v4addr, Mask: v4mappedv6mask}, IPNet{IP: v4addr, Mask: v4mask}},
+	{IPNet{IP: v4mappedv6addr, Mask: v4mappedv6mask}, IPNet{IP: v4addr, Mask: v4mask}},
+	{IPNet{IP: v4mappedv6addr, Mask: v6mask}, IPNet{IP: v4addr, Mask: v4maskzero}},
+	{IPNet{IP: v4addr, Mask: v6mask}, IPNet{IP: v4addr, Mask: v4maskzero}},
+	{IPNet{IP: v6addr, Mask: v6mask}, IPNet{IP: v6addr, Mask: v6mask}},
+	{IPNet{IP: v6addr, Mask: v4mappedv6mask}, IPNet{IP: v6addr, Mask: v4mappedv6mask}},
+	{in: IPNet{IP: v6addr, Mask: v4mask}},
+	{in: IPNet{IP: v4addr, Mask: badmask}},
+	{in: IPNet{IP: v4mappedv6addr, Mask: badmask}},
+	{in: IPNet{IP: v6addr, Mask: badmask}},
+	{in: IPNet{IP: badaddr, Mask: v4mask}},
+	{in: IPNet{IP: badaddr, Mask: v4mappedv6mask}},
+	{in: IPNet{IP: badaddr, Mask: v6mask}},
+	{in: IPNet{IP: badaddr, Mask: badmask}},
+}
+
+func TestNetworkNumberAndMask(t *testing.T) {
+	for _, tt := range networkNumberAndMaskTests {
+		ip, m := networkNumberAndMask(&tt.in)
+		out := &IPNet{IP: ip, Mask: m}
+		if !reflect.DeepEqual(&tt.out, out) {
+			t.Errorf("networkNumberAndMask(%v) = %v, want %v", tt.in, out, &tt.out)
+		}
+	}
+}
+
+var splitJoinTests = []struct {
+	host string
+	port string
+	join string
+}{
+	{"www.google.com", "80", "www.google.com:80"},
+	{"127.0.0.1", "1234", "127.0.0.1:1234"},
+	{"::1", "80", "[::1]:80"},
+	{"fe80::1%lo0", "80", "[fe80::1%lo0]:80"},
+	{"localhost%lo0", "80", "[localhost%lo0]:80"},
+	{"", "0", ":0"},
+
+	{"google.com", "https%foo", "google.com:https%foo"}, // Go 1.0 behavior
+	{"127.0.0.1", "", "127.0.0.1:"},                     // Go 1.0 behaviour
+	{"www.google.com", "", "www.google.com:"},           // Go 1.0 behaviour
+}
+
+var splitFailureTests = []struct {
+	hostPort string
+	err      string
+}{
+	{"www.google.com", "missing port in address"},
+	{"127.0.0.1", "missing port in address"},
+	{"[::1]", "missing port in address"},
+	{"[fe80::1%lo0]", "missing port in address"},
+	{"[localhost%lo0]", "missing port in address"},
+	{"localhost%lo0", "missing port in address"},
+
+	{"::1", "too many colons in address"},
+	{"fe80::1%lo0", "too many colons in address"},
+	{"fe80::1%lo0:80", "too many colons in address"},
+
+	{"localhost%lo0:80", "missing brackets in address"},
+
+	// Test cases that didn't fail in Go 1.0
+
+	{"[foo:bar]", "missing port in address"},
+	{"[foo:bar]baz", "missing port in address"},
+	{"[foo]bar:baz", "missing port in address"},
+
+	{"[foo]:[bar]:baz", "too many colons in address"},
+
+	{"[foo]:[bar]baz", "unexpected '[' in address"},
+	{"foo[bar]:baz", "unexpected '[' in address"},
+
+	{"foo]bar:baz", "unexpected ']' in address"},
+}
+
+func TestSplitHostPort(t *testing.T) {
+	for _, tt := range splitJoinTests {
+		if host, port, err := SplitHostPort(tt.join); host != tt.host || port != tt.port || err != nil {
+			t.Errorf("SplitHostPort(%q) = %q, %q, %v; want %q, %q, nil", tt.join, host, port, err, tt.host, tt.port)
+		}
+	}
+	for _, tt := range splitFailureTests {
+		if _, _, err := SplitHostPort(tt.hostPort); err == nil {
+			t.Errorf("SplitHostPort(%q) should have failed", tt.hostPort)
+		} else {
+			e := err.(*AddrError)
+			if e.Err != tt.err {
+				t.Errorf("SplitHostPort(%q) = _, _, %q; want %q", tt.hostPort, e.Err, tt.err)
+			}
+		}
+	}
+}
+
+func TestJoinHostPort(t *testing.T) {
+	for _, tt := range splitJoinTests {
+		if join := JoinHostPort(tt.host, tt.port); join != tt.join {
+			t.Errorf("JoinHostPort(%q, %q) = %q; want %q", tt.host, tt.port, join, tt.join)
+		}
+	}
+}
+
+var ipAddrFamilyTests = []struct {
+	in  IP
+	af4 bool
+	af6 bool
+}{
+	{IPv4bcast, true, false},
+	{IPv4allsys, true, false},
+	{IPv4allrouter, true, false},
+	{IPv4zero, true, false},
+	{IPv4(224, 0, 0, 1), true, false},
+	{IPv4(127, 0, 0, 1), true, false},
+	{IPv4(240, 0, 0, 1), true, false},
+	{IPv6unspecified, false, true},
+	{IPv6loopback, false, true},
+	{IPv6interfacelocalallnodes, false, true},
+	{IPv6linklocalallnodes, false, true},
+	{IPv6linklocalallrouters, false, true},
+	{ParseIP("ff05::a:b:c:d"), false, true},
+	{ParseIP("fe80::1:2:3:4"), false, true},
+	{ParseIP("2001:db8::123:12:1"), false, true},
+}
+
+func TestIPAddrFamily(t *testing.T) {
+	for _, tt := range ipAddrFamilyTests {
+		if af := tt.in.To4() != nil; af != tt.af4 {
+			t.Errorf("verifying IPv4 address family for %q = %v, want %v", tt.in, af, tt.af4)
+		}
+		if af := len(tt.in) == IPv6len && tt.in.To4() == nil; af != tt.af6 {
+			t.Errorf("verifying IPv6 address family for %q = %v, want %v", tt.in, af, tt.af6)
+		}
+	}
+}
+
+var ipAddrScopeTests = []struct {
+	scope func(IP) bool
+	in    IP
+	ok    bool
+}{
+	{IP.IsUnspecified, IPv4zero, true},
+	{IP.IsUnspecified, IPv4(127, 0, 0, 1), false},
+	{IP.IsUnspecified, IPv6unspecified, true},
+	{IP.IsUnspecified, IPv6interfacelocalallnodes, false},
+	{IP.IsLoopback, IPv4(127, 0, 0, 1), true},
+	{IP.IsLoopback, IPv4(127, 255, 255, 254), true},
+	{IP.IsLoopback, IPv4(128, 1, 2, 3), false},
+	{IP.IsLoopback, IPv6loopback, true},
+	{IP.IsLoopback, IPv6linklocalallrouters, false},
+	{IP.IsMulticast, IPv4(224, 0, 0, 0), true},
+	{IP.IsMulticast, IPv4(239, 0, 0, 0), true},
+	{IP.IsMulticast, IPv4(240, 0, 0, 0), false},
+	{IP.IsMulticast, IPv6linklocalallnodes, true},
+	{IP.IsMulticast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true},
+	{IP.IsMulticast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
+	{IP.IsLinkLocalMulticast, IPv4(224, 0, 0, 0), true},
+	{IP.IsLinkLocalMulticast, IPv4(239, 0, 0, 0), false},
+	{IP.IsLinkLocalMulticast, IPv6linklocalallrouters, true},
+	{IP.IsLinkLocalMulticast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
+	{IP.IsLinkLocalUnicast, IPv4(169, 254, 0, 0), true},
+	{IP.IsLinkLocalUnicast, IPv4(169, 255, 0, 0), false},
+	{IP.IsLinkLocalUnicast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true},
+	{IP.IsLinkLocalUnicast, IP{0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
+	{IP.IsGlobalUnicast, IPv4(240, 0, 0, 0), true},
+	{IP.IsGlobalUnicast, IPv4(232, 0, 0, 0), false},
+	{IP.IsGlobalUnicast, IPv4(169, 254, 0, 0), false},
+	{IP.IsGlobalUnicast, IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}, true},
+	{IP.IsGlobalUnicast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
+	{IP.IsGlobalUnicast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
+}
+
+func name(f interface{}) string {
+	return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
+}
+
+func TestIPAddrScope(t *testing.T) {
+	for _, tt := range ipAddrScopeTests {
+		if ok := tt.scope(tt.in); ok != tt.ok {
+			t.Errorf("%s(%q) = %v, want %v", name(tt.scope), tt.in, ok, tt.ok)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/ipraw_test.go b/third_party/gofrontend/libgo/go/net/ipraw_test.go
new file mode 100644
index 0000000..0632daf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/ipraw_test.go
@@ -0,0 +1,289 @@
+// 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 net
+
+import (
+	"bytes"
+	"fmt"
+	"os"
+	"reflect"
+	"runtime"
+	"testing"
+	"time"
+)
+
+type resolveIPAddrTest struct {
+	net           string
+	litAddrOrName string
+	addr          *IPAddr
+	err           error
+}
+
+var resolveIPAddrTests = []resolveIPAddrTest{
+	{"ip", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+	{"ip4", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+	{"ip4:icmp", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+
+	{"ip", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
+	{"ip6", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
+	{"ip6:ipv6-icmp", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
+	{"ip6:IPv6-ICMP", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
+
+	{"ip", "::1%en0", &IPAddr{IP: ParseIP("::1"), Zone: "en0"}, nil},
+	{"ip6", "::1%911", &IPAddr{IP: ParseIP("::1"), Zone: "911"}, nil},
+
+	{"", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil}, // Go 1.0 behavior
+	{"", "::1", &IPAddr{IP: ParseIP("::1")}, nil},           // Go 1.0 behavior
+
+	{"l2tp", "127.0.0.1", nil, UnknownNetworkError("l2tp")},
+	{"l2tp:gre", "127.0.0.1", nil, UnknownNetworkError("l2tp:gre")},
+	{"tcp", "1.2.3.4:123", nil, UnknownNetworkError("tcp")},
+}
+
+func init() {
+	if ifi := loopbackInterface(); ifi != nil {
+		index := fmt.Sprintf("%v", ifi.Index)
+		resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
+			{"ip6", "fe80::1%" + ifi.Name, &IPAddr{IP: ParseIP("fe80::1"), Zone: zoneToString(ifi.Index)}, nil},
+			{"ip6", "fe80::1%" + index, &IPAddr{IP: ParseIP("fe80::1"), Zone: index}, nil},
+		}...)
+	}
+	if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
+		resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
+			{"ip", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+			{"ip4", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+			{"ip6", "localhost", &IPAddr{IP: IPv6loopback}, nil},
+		}...)
+	}
+}
+
+func skipRawSocketTest(t *testing.T) (skip bool, skipmsg string) {
+	skip, skipmsg, err := skipRawSocketTests()
+	if err != nil {
+		t.Fatal(err)
+	}
+	return skip, skipmsg
+}
+
+func TestResolveIPAddr(t *testing.T) {
+	for _, tt := range resolveIPAddrTests {
+		addr, err := ResolveIPAddr(tt.net, tt.litAddrOrName)
+		if err != tt.err {
+			t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddrOrName, err)
+		} else if !reflect.DeepEqual(addr, tt.addr) {
+			t.Fatalf("got %#v; expected %#v", addr, tt.addr)
+		}
+	}
+}
+
+var icmpEchoTests = []struct {
+	net   string
+	laddr string
+	raddr string
+}{
+	{"ip4:icmp", "0.0.0.0", "127.0.0.1"},
+	{"ip6:ipv6-icmp", "::", "::1"},
+}
+
+func TestConnICMPEcho(t *testing.T) {
+	if skip, skipmsg := skipRawSocketTest(t); skip {
+		t.Skip(skipmsg)
+	}
+
+	for i, tt := range icmpEchoTests {
+		net, _, err := parseNetwork(tt.net)
+		if err != nil {
+			t.Fatalf("parseNetwork failed: %v", err)
+		}
+		if net == "ip6" && !supportsIPv6 {
+			continue
+		}
+
+		c, err := Dial(tt.net, tt.raddr)
+		if err != nil {
+			t.Fatalf("Dial failed: %v", err)
+		}
+		c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		defer c.Close()
+
+		typ := icmpv4EchoRequest
+		if net == "ip6" {
+			typ = icmpv6EchoRequest
+		}
+		xid, xseq := os.Getpid()&0xffff, i+1
+		wb, err := (&icmpMessage{
+			Type: typ, Code: 0,
+			Body: &icmpEcho{
+				ID: xid, Seq: xseq,
+				Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
+			},
+		}).Marshal()
+		if err != nil {
+			t.Fatalf("icmpMessage.Marshal failed: %v", err)
+		}
+		if _, err := c.Write(wb); err != nil {
+			t.Fatalf("Conn.Write failed: %v", err)
+		}
+		var m *icmpMessage
+		rb := make([]byte, 20+len(wb))
+		for {
+			if _, err := c.Read(rb); err != nil {
+				t.Fatalf("Conn.Read failed: %v", err)
+			}
+			if net == "ip4" {
+				rb = ipv4Payload(rb)
+			}
+			if m, err = parseICMPMessage(rb); err != nil {
+				t.Fatalf("parseICMPMessage failed: %v", err)
+			}
+			switch m.Type {
+			case icmpv4EchoRequest, icmpv6EchoRequest:
+				continue
+			}
+			break
+		}
+		switch p := m.Body.(type) {
+		case *icmpEcho:
+			if p.ID != xid || p.Seq != xseq {
+				t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
+			}
+		default:
+			t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
+		}
+	}
+}
+
+func TestPacketConnICMPEcho(t *testing.T) {
+	if skip, skipmsg := skipRawSocketTest(t); skip {
+		t.Skip(skipmsg)
+	}
+
+	for i, tt := range icmpEchoTests {
+		net, _, err := parseNetwork(tt.net)
+		if err != nil {
+			t.Fatalf("parseNetwork failed: %v", err)
+		}
+		if net == "ip6" && !supportsIPv6 {
+			continue
+		}
+
+		c, err := ListenPacket(tt.net, tt.laddr)
+		if err != nil {
+			t.Fatalf("ListenPacket failed: %v", err)
+		}
+		c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		defer c.Close()
+
+		ra, err := ResolveIPAddr(tt.net, tt.raddr)
+		if err != nil {
+			t.Fatalf("ResolveIPAddr failed: %v", err)
+		}
+		typ := icmpv4EchoRequest
+		if net == "ip6" {
+			typ = icmpv6EchoRequest
+		}
+		xid, xseq := os.Getpid()&0xffff, i+1
+		wb, err := (&icmpMessage{
+			Type: typ, Code: 0,
+			Body: &icmpEcho{
+				ID: xid, Seq: xseq,
+				Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
+			},
+		}).Marshal()
+		if err != nil {
+			t.Fatalf("icmpMessage.Marshal failed: %v", err)
+		}
+		if _, err := c.WriteTo(wb, ra); err != nil {
+			t.Fatalf("PacketConn.WriteTo failed: %v", err)
+		}
+		var m *icmpMessage
+		rb := make([]byte, 20+len(wb))
+		for {
+			if _, _, err := c.ReadFrom(rb); err != nil {
+				t.Fatalf("PacketConn.ReadFrom failed: %v", err)
+			}
+			// See BUG section.
+			//if net == "ip4" {
+			//	rb = ipv4Payload(rb)
+			//}
+			if m, err = parseICMPMessage(rb); err != nil {
+				t.Fatalf("parseICMPMessage failed: %v", err)
+			}
+			switch m.Type {
+			case icmpv4EchoRequest, icmpv6EchoRequest:
+				continue
+			}
+			break
+		}
+		switch p := m.Body.(type) {
+		case *icmpEcho:
+			if p.ID != xid || p.Seq != xseq {
+				t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
+			}
+		default:
+			t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
+		}
+	}
+}
+
+func ipv4Payload(b []byte) []byte {
+	if len(b) < 20 {
+		return b
+	}
+	hdrlen := int(b[0]&0x0f) << 2
+	return b[hdrlen:]
+}
+
+var ipConnLocalNameTests = []struct {
+	net   string
+	laddr *IPAddr
+}{
+	{"ip4:icmp", &IPAddr{IP: IPv4(127, 0, 0, 1)}},
+	{"ip4:icmp", &IPAddr{}},
+	{"ip4:icmp", nil},
+}
+
+func TestIPConnLocalName(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	default:
+		if os.Getuid() != 0 {
+			t.Skip("skipping test; must be root")
+		}
+	}
+
+	for _, tt := range ipConnLocalNameTests {
+		c, err := ListenIP(tt.net, tt.laddr)
+		if err != nil {
+			t.Fatalf("ListenIP failed: %v", err)
+		}
+		defer c.Close()
+		if la := c.LocalAddr(); la == nil {
+			t.Fatal("IPConn.LocalAddr failed")
+		}
+	}
+}
+
+func TestIPConnRemoteName(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	default:
+		if os.Getuid() != 0 {
+			t.Skip("skipping test; must be root")
+		}
+	}
+
+	raddr := &IPAddr{IP: IPv4(127, 0, 0, 1).To4()}
+	c, err := DialIP("ip:tcp", &IPAddr{IP: IPv4(127, 0, 0, 1)}, raddr)
+	if err != nil {
+		t.Fatalf("DialIP failed: %v", err)
+	}
+	defer c.Close()
+	if !reflect.DeepEqual(raddr, c.RemoteAddr()) {
+		t.Fatalf("got %#v, expected %#v", c.RemoteAddr(), raddr)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/iprawsock.go b/third_party/gofrontend/libgo/go/net/iprawsock.go
new file mode 100644
index 0000000..5cc3613
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/iprawsock.go
@@ -0,0 +1,54 @@
+// Copyright 2010 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 net
+
+// IPAddr represents the address of an IP end point.
+type IPAddr struct {
+	IP   IP
+	Zone string // IPv6 scoped addressing zone
+}
+
+// Network returns the address's network name, "ip".
+func (a *IPAddr) Network() string { return "ip" }
+
+func (a *IPAddr) String() string {
+	if a == nil {
+		return "<nil>"
+	}
+	if a.Zone != "" {
+		return a.IP.String() + "%" + a.Zone
+	}
+	return a.IP.String()
+}
+
+func (a *IPAddr) toAddr() Addr {
+	if a == nil {
+		return nil
+	}
+	return a
+}
+
+// ResolveIPAddr parses addr as an IP address of the form "host" or
+// "ipv6-host%zone" and resolves the domain name on the network net,
+// which must be "ip", "ip4" or "ip6".
+func ResolveIPAddr(net, addr string) (*IPAddr, error) {
+	if net == "" { // a hint wildcard for Go 1.0 undocumented behavior
+		net = "ip"
+	}
+	afnet, _, err := parseNetwork(net)
+	if err != nil {
+		return nil, err
+	}
+	switch afnet {
+	case "ip", "ip4", "ip6":
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	a, err := resolveInternetAddr(afnet, addr, noDeadline)
+	if err != nil {
+		return nil, err
+	}
+	return a.toAddr().(*IPAddr), nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/iprawsock_plan9.go b/third_party/gofrontend/libgo/go/net/iprawsock_plan9.go
new file mode 100644
index 0000000..e62d116
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/iprawsock_plan9.go
@@ -0,0 +1,82 @@
+// Copyright 2010 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 net
+
+import (
+	"syscall"
+	"time"
+)
+
+// IPConn is the implementation of the Conn and PacketConn interfaces
+// for IP network connections.
+type IPConn struct {
+	conn
+}
+
+// ReadFromIP reads an IP packet from c, copying the payload into b.
+// It returns the number of bytes copied into b and the return address
+// that was on the packet.
+//
+// ReadFromIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
+	return 0, nil, syscall.EPLAN9
+}
+
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
+	return 0, nil, syscall.EPLAN9
+}
+
+// ReadMsgIP reads a packet from c, copying the payload into b and the
+// associated out-of-band data into oob.  It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet and the source address of the packet.
+func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
+	return 0, 0, 0, nil, syscall.EPLAN9
+}
+
+// WriteToIP writes an IP packet to addr via c, copying the payload
+// from b.
+//
+// WriteToIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
+func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
+	return 0, syscall.EPLAN9
+}
+
+// WriteTo implements the PacketConn WriteTo method.
+func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
+	return 0, syscall.EPLAN9
+}
+
+// WriteMsgIP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob.  It returns the
+// number of payload and out-of-band bytes written.
+func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
+	return 0, 0, syscall.EPLAN9
+}
+
+// DialIP connects to the remote address raddr on the network protocol
+// netProto, which must be "ip", "ip4", or "ip6" followed by a colon
+// and a protocol number or name.
+func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
+	return dialIP(netProto, laddr, raddr, noDeadline)
+}
+
+func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
+	return nil, syscall.EPLAN9
+}
+
+// ListenIP listens for incoming IP packets addressed to the local
+// address laddr.  The returned connection's ReadFrom and WriteTo
+// methods can be used to receive and send IP packets with per-packet
+// addressing.
+func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
+	return nil, syscall.EPLAN9
+}
diff --git a/third_party/gofrontend/libgo/go/net/iprawsock_posix.go b/third_party/gofrontend/libgo/go/net/iprawsock_posix.go
new file mode 100644
index 0000000..bbb3f3e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/iprawsock_posix.go
@@ -0,0 +1,227 @@
+// Copyright 2010 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package net
+
+import (
+	"syscall"
+	"time"
+)
+
+// BUG(mikio): On every POSIX platform, reads from the "ip4" network
+// using the ReadFrom or ReadFromIP method might not return a complete
+// IPv4 packet, including its header, even if there is space
+// available. This can occur even in cases where Read or ReadMsgIP
+// could return a complete packet. For this reason, it is recommended
+// that you do not uses these methods if it is important to receive a
+// full packet.
+//
+// The Go 1 compatibility guidelines make it impossible for us to
+// change the behavior of these methods; use Read or ReadMsgIP
+// instead.
+
+func sockaddrToIP(sa syscall.Sockaddr) Addr {
+	switch sa := sa.(type) {
+	case *syscall.SockaddrInet4:
+		return &IPAddr{IP: sa.Addr[0:]}
+	case *syscall.SockaddrInet6:
+		return &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
+	}
+	return nil
+}
+
+func (a *IPAddr) family() int {
+	if a == nil || len(a.IP) <= IPv4len {
+		return syscall.AF_INET
+	}
+	if a.IP.To4() != nil {
+		return syscall.AF_INET
+	}
+	return syscall.AF_INET6
+}
+
+func (a *IPAddr) isWildcard() bool {
+	if a == nil || a.IP == nil {
+		return true
+	}
+	return a.IP.IsUnspecified()
+}
+
+func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
+	if a == nil {
+		return nil, nil
+	}
+	return ipToSockaddr(family, a.IP, 0, a.Zone)
+}
+
+// IPConn is the implementation of the Conn and PacketConn interfaces
+// for IP network connections.
+type IPConn struct {
+	conn
+}
+
+func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
+
+// ReadFromIP reads an IP packet from c, copying the payload into b.
+// It returns the number of bytes copied into b and the return address
+// that was on the packet.
+//
+// ReadFromIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
+	if !c.ok() {
+		return 0, nil, syscall.EINVAL
+	}
+	// TODO(cw,rsc): consider using readv if we know the family
+	// type to avoid the header trim/copy
+	var addr *IPAddr
+	n, sa, err := c.fd.readFrom(b)
+	switch sa := sa.(type) {
+	case *syscall.SockaddrInet4:
+		addr = &IPAddr{IP: sa.Addr[0:]}
+		if len(b) >= IPv4len { // discard ipv4 header
+			hsize := (int(b[0]) & 0xf) * 4
+			copy(b, b[hsize:])
+			n -= hsize
+		}
+	case *syscall.SockaddrInet6:
+		addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
+	}
+	return n, addr, err
+}
+
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
+	if !c.ok() {
+		return 0, nil, syscall.EINVAL
+	}
+	n, addr, err := c.ReadFromIP(b)
+	return n, addr.toAddr(), err
+}
+
+// ReadMsgIP reads a packet from c, copying the payload into b and the
+// associated out-of-band data into oob.  It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet and the source address of the packet.
+func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
+	if !c.ok() {
+		return 0, 0, 0, nil, syscall.EINVAL
+	}
+	var sa syscall.Sockaddr
+	n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
+	switch sa := sa.(type) {
+	case *syscall.SockaddrInet4:
+		addr = &IPAddr{IP: sa.Addr[0:]}
+	case *syscall.SockaddrInet6:
+		addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
+	}
+	return
+}
+
+// WriteToIP writes an IP packet to addr via c, copying the payload
+// from b.
+//
+// WriteToIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
+func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	if c.fd.isConnected {
+		return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
+	}
+	if addr == nil {
+		return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+	}
+	sa, err := addr.sockaddr(c.fd.family)
+	if err != nil {
+		return 0, &OpError{"write", c.fd.net, addr, err}
+	}
+	return c.fd.writeTo(b, sa)
+}
+
+// WriteTo implements the PacketConn WriteTo method.
+func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	a, ok := addr.(*IPAddr)
+	if !ok {
+		return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL}
+	}
+	return c.WriteToIP(b, a)
+}
+
+// WriteMsgIP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob.  It returns the
+// number of payload and out-of-band bytes written.
+func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
+	if !c.ok() {
+		return 0, 0, syscall.EINVAL
+	}
+	if c.fd.isConnected {
+		return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
+	}
+	if addr == nil {
+		return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+	}
+	sa, err := addr.sockaddr(c.fd.family)
+	if err != nil {
+		return 0, 0, &OpError{"write", c.fd.net, addr, err}
+	}
+	return c.fd.writeMsg(b, oob, sa)
+}
+
+// DialIP connects to the remote address raddr on the network protocol
+// netProto, which must be "ip", "ip4", or "ip6" followed by a colon
+// and a protocol number or name.
+func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
+	return dialIP(netProto, laddr, raddr, noDeadline)
+}
+
+func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
+	net, proto, err := parseNetwork(netProto)
+	if err != nil {
+		return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err}
+	}
+	switch net {
+	case "ip", "ip4", "ip6":
+	default:
+		return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: UnknownNetworkError(netProto)}
+	}
+	if raddr == nil {
+		return nil, &OpError{Op: "dial", Net: netProto, Addr: nil, Err: errMissingAddress}
+	}
+	fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
+	if err != nil {
+		return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err}
+	}
+	return newIPConn(fd), nil
+}
+
+// ListenIP listens for incoming IP packets addressed to the local
+// address laddr.  The returned connection's ReadFrom and WriteTo
+// methods can be used to receive and send IP packets with per-packet
+// addressing.
+func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
+	net, proto, err := parseNetwork(netProto)
+	if err != nil {
+		return nil, &OpError{Op: "dial", Net: netProto, Addr: laddr, Err: err}
+	}
+	switch net {
+	case "ip", "ip4", "ip6":
+	default:
+		return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: UnknownNetworkError(netProto)}
+	}
+	fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
+	if err != nil {
+		return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: err}
+	}
+	return newIPConn(fd), nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/ipsock.go b/third_party/gofrontend/libgo/go/net/ipsock.go
new file mode 100644
index 0000000..dda8578
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/ipsock.go
@@ -0,0 +1,318 @@
+// 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.
+
+// Internet protocol family sockets
+
+package net
+
+import (
+	"errors"
+	"time"
+)
+
+var (
+	// supportsIPv4 reports whether the platform supports IPv4
+	// networking functionality.
+	supportsIPv4 bool
+
+	// supportsIPv6 reports whether the platform supports IPv6
+	// networking functionality.
+	supportsIPv6 bool
+
+	// supportsIPv4map reports whether the platform supports
+	// mapping an IPv4 address inside an IPv6 address at transport
+	// layer protocols.  See RFC 4291, RFC 4038 and RFC 3493.
+	supportsIPv4map bool
+)
+
+func init() {
+	sysInit()
+	supportsIPv4 = probeIPv4Stack()
+	supportsIPv6, supportsIPv4map = probeIPv6Stack()
+}
+
+// A netaddr represents a network endpoint address or a list of
+// network endpoint addresses.
+type netaddr interface {
+	// toAddr returns the address represented in Addr interface.
+	// It returns a nil interface when the address is nil.
+	toAddr() Addr
+}
+
+// An addrList represents a list of network endpoint addresses.
+type addrList []netaddr
+
+func (al addrList) toAddr() Addr {
+	switch len(al) {
+	case 0:
+		return nil
+	case 1:
+		return al[0].toAddr()
+	default:
+		// For now, we'll roughly pick first one without
+		// considering dealing with any preferences such as
+		// DNS TTL, transport path quality, network routing
+		// information.
+		return al[0].toAddr()
+	}
+}
+
+var errNoSuitableAddress = errors.New("no suitable address found")
+
+// firstFavoriteAddr returns an address or a list of addresses that
+// implement the netaddr interface. Known filters are nil, ipv4only
+// and ipv6only. It returns any address when filter is nil. The result
+// contains at least one address when error is nil.
+func firstFavoriteAddr(filter func(IP) IP, ips []IP, inetaddr func(IP) netaddr) (netaddr, error) {
+	if filter != nil {
+		return firstSupportedAddr(filter, ips, inetaddr)
+	}
+	var (
+		ipv4, ipv6, swap bool
+		list             addrList
+	)
+	for _, ip := range ips {
+		// We'll take any IP address, but since the dialing
+		// code does not yet try multiple addresses
+		// effectively, prefer to use an IPv4 address if
+		// possible. This is especially relevant if localhost
+		// resolves to [ipv6-localhost, ipv4-localhost]. Too
+		// much code assumes localhost == ipv4-localhost.
+		if ip4 := ipv4only(ip); ip4 != nil && !ipv4 {
+			list = append(list, inetaddr(ip4))
+			ipv4 = true
+			if ipv6 {
+				swap = true
+			}
+		} else if ip6 := ipv6only(ip); ip6 != nil && !ipv6 {
+			list = append(list, inetaddr(ip6))
+			ipv6 = true
+		}
+		if ipv4 && ipv6 {
+			if swap {
+				list[0], list[1] = list[1], list[0]
+			}
+			break
+		}
+	}
+	switch len(list) {
+	case 0:
+		return nil, errNoSuitableAddress
+	case 1:
+		return list[0], nil
+	default:
+		return list, nil
+	}
+}
+
+func firstSupportedAddr(filter func(IP) IP, ips []IP, inetaddr func(IP) netaddr) (netaddr, error) {
+	for _, ip := range ips {
+		if ip := filter(ip); ip != nil {
+			return inetaddr(ip), nil
+		}
+	}
+	return nil, errNoSuitableAddress
+}
+
+// ipv4only returns IPv4 addresses that we can use with the kernel's
+// IPv4 addressing modes. If ip is an IPv4 address, ipv4only returns ip.
+// Otherwise it returns nil.
+func ipv4only(ip IP) IP {
+	if supportsIPv4 && ip.To4() != nil {
+		return ip
+	}
+	return nil
+}
+
+// ipv6only returns IPv6 addresses that we can use with the kernel's
+// IPv6 addressing modes.  It returns IPv4-mapped IPv6 addresses as
+// nils and returns other IPv6 address types as IPv6 addresses.
+func ipv6only(ip IP) IP {
+	if supportsIPv6 && len(ip) == IPv6len && ip.To4() == nil {
+		return ip
+	}
+	return nil
+}
+
+// SplitHostPort splits a network address of the form "host:port",
+// "[host]:port" or "[ipv6-host%zone]:port" into host or
+// ipv6-host%zone and port.  A literal address or host name for IPv6
+// must be enclosed in square brackets, as in "[::1]:80",
+// "[ipv6-host]:http" or "[ipv6-host%zone]:80".
+func SplitHostPort(hostport string) (host, port string, err error) {
+	j, k := 0, 0
+
+	// The port starts after the last colon.
+	i := last(hostport, ':')
+	if i < 0 {
+		goto missingPort
+	}
+
+	if hostport[0] == '[' {
+		// Expect the first ']' just before the last ':'.
+		end := byteIndex(hostport, ']')
+		if end < 0 {
+			err = &AddrError{"missing ']' in address", hostport}
+			return
+		}
+		switch end + 1 {
+		case len(hostport):
+			// There can't be a ':' behind the ']' now.
+			goto missingPort
+		case i:
+			// The expected result.
+		default:
+			// Either ']' isn't followed by a colon, or it is
+			// followed by a colon that is not the last one.
+			if hostport[end+1] == ':' {
+				goto tooManyColons
+			}
+			goto missingPort
+		}
+		host = hostport[1:end]
+		j, k = 1, end+1 // there can't be a '[' resp. ']' before these positions
+	} else {
+		host = hostport[:i]
+		if byteIndex(host, ':') >= 0 {
+			goto tooManyColons
+		}
+		if byteIndex(host, '%') >= 0 {
+			goto missingBrackets
+		}
+	}
+	if byteIndex(hostport[j:], '[') >= 0 {
+		err = &AddrError{"unexpected '[' in address", hostport}
+		return
+	}
+	if byteIndex(hostport[k:], ']') >= 0 {
+		err = &AddrError{"unexpected ']' in address", hostport}
+		return
+	}
+
+	port = hostport[i+1:]
+	return
+
+missingPort:
+	err = &AddrError{"missing port in address", hostport}
+	return
+
+tooManyColons:
+	err = &AddrError{"too many colons in address", hostport}
+	return
+
+missingBrackets:
+	err = &AddrError{"missing brackets in address", hostport}
+	return
+}
+
+func splitHostZone(s string) (host, zone string) {
+	// The IPv6 scoped addressing zone identifier starts after the
+	// last percent sign.
+	if i := last(s, '%'); i > 0 {
+		host, zone = s[:i], s[i+1:]
+	} else {
+		host = s
+	}
+	return
+}
+
+// JoinHostPort combines host and port into a network address of the
+// form "host:port" or, if host contains a colon or a percent sign,
+// "[host]:port".
+func JoinHostPort(host, port string) string {
+	// If host has colons or a percent sign, have to bracket it.
+	if byteIndex(host, ':') >= 0 || byteIndex(host, '%') >= 0 {
+		return "[" + host + "]:" + port
+	}
+	return host + ":" + port
+}
+
+// resolveInternetAddr resolves addr that is either a literal IP
+// address or a DNS name and returns an internet protocol family
+// address. It returns a list that contains a pair of different
+// address family addresses when addr is a DNS name and the name has
+// multiple address family records. The result contains at least one
+// address when error is nil.
+func resolveInternetAddr(net, addr string, deadline time.Time) (netaddr, error) {
+	var (
+		err              error
+		host, port, zone string
+		portnum          int
+	)
+	switch net {
+	case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
+		if addr != "" {
+			if host, port, err = SplitHostPort(addr); err != nil {
+				return nil, err
+			}
+			if portnum, err = parsePort(net, port); err != nil {
+				return nil, err
+			}
+		}
+	case "ip", "ip4", "ip6":
+		if addr != "" {
+			host = addr
+		}
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	inetaddr := func(ip IP) netaddr {
+		switch net {
+		case "tcp", "tcp4", "tcp6":
+			return &TCPAddr{IP: ip, Port: portnum, Zone: zone}
+		case "udp", "udp4", "udp6":
+			return &UDPAddr{IP: ip, Port: portnum, Zone: zone}
+		case "ip", "ip4", "ip6":
+			return &IPAddr{IP: ip, Zone: zone}
+		default:
+			panic("unexpected network: " + net)
+		}
+	}
+	if host == "" {
+		return inetaddr(nil), nil
+	}
+	// Try as a literal IP address.
+	var ip IP
+	if ip = parseIPv4(host); ip != nil {
+		return inetaddr(ip), nil
+	}
+	if ip, zone = parseIPv6(host, true); ip != nil {
+		return inetaddr(ip), nil
+	}
+	// Try as a DNS name.
+	host, zone = splitHostZone(host)
+	ips, err := lookupIPDeadline(host, deadline)
+	if err != nil {
+		return nil, err
+	}
+	var filter func(IP) IP
+	if net != "" && net[len(net)-1] == '4' {
+		filter = ipv4only
+	}
+	if net != "" && net[len(net)-1] == '6' || zone != "" {
+		filter = ipv6only
+	}
+	return firstFavoriteAddr(filter, ips, inetaddr)
+}
+
+func zoneToString(zone int) string {
+	if zone == 0 {
+		return ""
+	}
+	if ifi, err := InterfaceByIndex(zone); err == nil {
+		return ifi.Name
+	}
+	return itod(uint(zone))
+}
+
+func zoneToInt(zone string) int {
+	if zone == "" {
+		return 0
+	}
+	if ifi, err := InterfaceByName(zone); err == nil {
+		return ifi.Index
+	}
+	n, _, _ := dtoi(zone, 0)
+	return n
+}
diff --git a/third_party/gofrontend/libgo/go/net/ipsock_plan9.go b/third_party/gofrontend/libgo/go/net/ipsock_plan9.go
new file mode 100644
index 0000000..94ceea3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/ipsock_plan9.go
@@ -0,0 +1,228 @@
+// 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.
+
+// Internet protocol family sockets for Plan 9
+
+package net
+
+import (
+	"errors"
+	"os"
+	"syscall"
+)
+
+func probe(filename, query string) bool {
+	var file *file
+	var err error
+	if file, err = open(filename); err != nil {
+		return false
+	}
+
+	r := false
+	for line, ok := file.readLine(); ok && !r; line, ok = file.readLine() {
+		f := getFields(line)
+		if len(f) < 3 {
+			continue
+		}
+		for i := 0; i < len(f); i++ {
+			if query == f[i] {
+				r = true
+				break
+			}
+		}
+	}
+	file.close()
+	return r
+}
+
+func probeIPv4Stack() bool {
+	return probe(netdir+"/iproute", "4i")
+}
+
+// probeIPv6Stack returns two boolean values.  If the first boolean
+// value is true, kernel supports basic IPv6 functionality.  If the
+// second boolean value is true, kernel supports IPv6 IPv4-mapping.
+func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
+	// Plan 9 uses IPv6 natively, see ip(3).
+	r := probe(netdir+"/iproute", "6i")
+	v := false
+	if r {
+		v = probe(netdir+"/iproute", "4i")
+	}
+	return r, v
+}
+
+// parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80).
+func parsePlan9Addr(s string) (ip IP, iport int, err error) {
+	addr := IPv4zero // address contains port only
+	i := byteIndex(s, '!')
+	if i >= 0 {
+		addr = ParseIP(s[:i])
+		if addr == nil {
+			return nil, 0, errors.New("parsing IP failed")
+		}
+	}
+	p, _, ok := dtoi(s[i+1:], 0)
+	if !ok {
+		return nil, 0, errors.New("parsing port failed")
+	}
+	if p < 0 || p > 0xFFFF {
+		return nil, 0, &AddrError{"invalid port", string(p)}
+	}
+	return addr, p, nil
+}
+
+func readPlan9Addr(proto, filename string) (addr Addr, err error) {
+	var buf [128]byte
+
+	f, err := os.Open(filename)
+	if err != nil {
+		return
+	}
+	defer f.Close()
+	n, err := f.Read(buf[:])
+	if err != nil {
+		return
+	}
+	ip, port, err := parsePlan9Addr(string(buf[:n]))
+	if err != nil {
+		return
+	}
+	switch proto {
+	case "tcp":
+		addr = &TCPAddr{IP: ip, Port: port}
+	case "udp":
+		addr = &UDPAddr{IP: ip, Port: port}
+	default:
+		return nil, errors.New("unknown protocol " + proto)
+	}
+	return addr, nil
+}
+
+func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err error) {
+	var (
+		ip   IP
+		port int
+	)
+	switch a := addr.(type) {
+	case *TCPAddr:
+		proto = "tcp"
+		ip = a.IP
+		port = a.Port
+	case *UDPAddr:
+		proto = "udp"
+		ip = a.IP
+		port = a.Port
+	default:
+		err = UnknownNetworkError(net)
+		return
+	}
+
+	clone, dest, err := queryCS1(proto, ip, port)
+	if err != nil {
+		return
+	}
+	f, err := os.OpenFile(clone, os.O_RDWR, 0)
+	if err != nil {
+		return
+	}
+	var buf [16]byte
+	n, err := f.Read(buf[:])
+	if err != nil {
+		f.Close()
+		return
+	}
+	return f, dest, proto, string(buf[:n]), nil
+}
+
+func netErr(e error) {
+	oe, ok := e.(*OpError)
+	if !ok {
+		return
+	}
+	if pe, ok := oe.Err.(*os.PathError); ok {
+		if _, ok = pe.Err.(syscall.ErrorString); ok {
+			oe.Err = pe.Err
+		}
+	}
+}
+
+func dialPlan9(net string, laddr, raddr Addr) (fd *netFD, err error) {
+	defer func() { netErr(err) }()
+	f, dest, proto, name, err := startPlan9(net, raddr)
+	if err != nil {
+		return nil, &OpError{"dial", net, raddr, err}
+	}
+	_, err = f.WriteString("connect " + dest)
+	if err != nil {
+		f.Close()
+		return nil, &OpError{"dial", f.Name(), raddr, err}
+	}
+	data, err := os.OpenFile(netdir+"/"+proto+"/"+name+"/data", os.O_RDWR, 0)
+	if err != nil {
+		f.Close()
+		return nil, &OpError{"dial", net, raddr, err}
+	}
+	laddr, err = readPlan9Addr(proto, netdir+"/"+proto+"/"+name+"/local")
+	if err != nil {
+		data.Close()
+		f.Close()
+		return nil, &OpError{"dial", proto, raddr, err}
+	}
+	return newFD(proto, name, f, data, laddr, raddr)
+}
+
+func listenPlan9(net string, laddr Addr) (fd *netFD, err error) {
+	defer func() { netErr(err) }()
+	f, dest, proto, name, err := startPlan9(net, laddr)
+	if err != nil {
+		return nil, &OpError{"listen", net, laddr, err}
+	}
+	_, err = f.WriteString("announce " + dest)
+	if err != nil {
+		f.Close()
+		return nil, &OpError{"announce", proto, laddr, err}
+	}
+	laddr, err = readPlan9Addr(proto, netdir+"/"+proto+"/"+name+"/local")
+	if err != nil {
+		f.Close()
+		return nil, &OpError{Op: "listen", Net: net, Err: err}
+	}
+	return newFD(proto, name, f, nil, laddr, nil)
+}
+
+func (l *netFD) netFD() (*netFD, error) {
+	return newFD(l.proto, l.n, l.ctl, l.data, l.laddr, l.raddr)
+}
+
+func (l *netFD) acceptPlan9() (fd *netFD, err error) {
+	defer func() { netErr(err) }()
+	if err := l.readLock(); err != nil {
+		return nil, err
+	}
+	defer l.readUnlock()
+	f, err := os.Open(l.dir + "/listen")
+	if err != nil {
+		return nil, &OpError{"accept", l.dir + "/listen", l.laddr, err}
+	}
+	var buf [16]byte
+	n, err := f.Read(buf[:])
+	if err != nil {
+		f.Close()
+		return nil, &OpError{"accept", l.dir + "/listen", l.laddr, err}
+	}
+	name := string(buf[:n])
+	data, err := os.OpenFile(netdir+"/"+l.proto+"/"+name+"/data", os.O_RDWR, 0)
+	if err != nil {
+		f.Close()
+		return nil, &OpError{"accept", l.proto, l.laddr, err}
+	}
+	raddr, err := readPlan9Addr(l.proto, netdir+"/"+l.proto+"/"+name+"/remote")
+	if err != nil {
+		data.Close()
+		f.Close()
+		return nil, &OpError{"accept", l.proto, l.laddr, err}
+	}
+	return newFD(l.proto, name, f, data, l.laddr, raddr)
+}
diff --git a/third_party/gofrontend/libgo/go/net/ipsock_posix.go b/third_party/gofrontend/libgo/go/net/ipsock_posix.go
new file mode 100644
index 0000000..2ba4c8e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/ipsock_posix.go
@@ -0,0 +1,177 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+// Internet protocol family sockets for POSIX
+
+package net
+
+import (
+	"syscall"
+	"time"
+)
+
+func probeIPv4Stack() bool {
+	s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
+	switch err {
+	case syscall.EAFNOSUPPORT, syscall.EPROTONOSUPPORT:
+		return false
+	case nil:
+		closesocket(s)
+	}
+	return true
+}
+
+// Should we try to use the IPv4 socket interface if we're
+// only dealing with IPv4 sockets?  As long as the host system
+// understands IPv6, it's okay to pass IPv4 addresses to the IPv6
+// interface.  That simplifies our code and is most general.
+// Unfortunately, we need to run on kernels built without IPv6
+// support too.  So probe the kernel to figure it out.
+//
+// probeIPv6Stack probes both basic IPv6 capability and IPv6 IPv4-
+// mapping capability which is controlled by IPV6_V6ONLY socket
+// option and/or kernel state "net.inet6.ip6.v6only".
+// It returns two boolean values.  If the first boolean value is
+// true, kernel supports basic IPv6 functionality.  If the second
+// boolean value is true, kernel supports IPv6 IPv4-mapping.
+func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
+	var probes = []struct {
+		laddr TCPAddr
+		value int
+		ok    bool
+	}{
+		// IPv6 communication capability
+		{laddr: TCPAddr{IP: ParseIP("::1")}, value: 1},
+		// IPv6 IPv4-mapped address communication capability
+		{laddr: TCPAddr{IP: IPv4(127, 0, 0, 1)}, value: 0},
+	}
+
+	for i := range probes {
+		s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
+		if err != nil {
+			continue
+		}
+		defer closesocket(s)
+		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, probes[i].value)
+		sa, err := probes[i].laddr.sockaddr(syscall.AF_INET6)
+		if err != nil {
+			continue
+		}
+		if err := syscall.Bind(s, sa); err != nil {
+			continue
+		}
+		probes[i].ok = true
+	}
+
+	return probes[0].ok, probes[1].ok
+}
+
+// favoriteAddrFamily returns the appropriate address family to
+// the given net, laddr, raddr and mode.  At first it figures
+// address family out from the net.  If mode indicates "listen"
+// and laddr is a wildcard, it assumes that the user wants to
+// make a passive connection with a wildcard address family, both
+// AF_INET and AF_INET6, and a wildcard address like following:
+//
+//	1. A wild-wild listen, "tcp" + ""
+//	If the platform supports both IPv6 and IPv6 IPv4-mapping
+//	capabilities, we assume that the user want to listen on
+//	both IPv4 and IPv6 wildcard address over an AF_INET6
+//	socket with IPV6_V6ONLY=0.  Otherwise we prefer an IPv4
+//	wildcard address listen over an AF_INET socket.
+//
+//	2. A wild-ipv4wild listen, "tcp" + "0.0.0.0"
+//	Same as 1.
+//
+//	3. A wild-ipv6wild listen, "tcp" + "[::]"
+//	Almost same as 1 but we prefer an IPv6 wildcard address
+//	listen over an AF_INET6 socket with IPV6_V6ONLY=0 when
+//	the platform supports IPv6 capability but not IPv6 IPv4-
+//	mapping capability.
+//
+//	4. A ipv4-ipv4wild listen, "tcp4" + "" or "0.0.0.0"
+//	We use an IPv4 (AF_INET) wildcard address listen.
+//
+//	5. A ipv6-ipv6wild listen, "tcp6" + "" or "[::]"
+//	We use an IPv6 (AF_INET6, IPV6_V6ONLY=1) wildcard address
+//	listen.
+//
+// Otherwise guess: if the addresses are IPv4 then returns AF_INET,
+// or else returns AF_INET6.  It also returns a boolean value what
+// designates IPV6_V6ONLY option.
+//
+// Note that OpenBSD allows neither "net.inet6.ip6.v6only=1" change
+// nor IPPROTO_IPV6 level IPV6_V6ONLY socket option setting.
+func favoriteAddrFamily(net string, laddr, raddr sockaddr, mode string) (family int, ipv6only bool) {
+	switch net[len(net)-1] {
+	case '4':
+		return syscall.AF_INET, false
+	case '6':
+		return syscall.AF_INET6, true
+	}
+
+	if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
+		if supportsIPv4map {
+			return syscall.AF_INET6, false
+		}
+		if laddr == nil {
+			return syscall.AF_INET, false
+		}
+		return laddr.family(), false
+	}
+
+	if (laddr == nil || laddr.family() == syscall.AF_INET) &&
+		(raddr == nil || raddr.family() == syscall.AF_INET) {
+		return syscall.AF_INET, false
+	}
+	return syscall.AF_INET6, false
+}
+
+// Internet sockets (TCP, UDP, IP)
+
+func internetSocket(net string, laddr, raddr sockaddr, deadline time.Time, sotype, proto int, mode string, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
+	family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
+	return socket(net, family, sotype, proto, ipv6only, laddr, raddr, deadline, toAddr)
+}
+
+func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
+	switch family {
+	case syscall.AF_INET:
+		if len(ip) == 0 {
+			ip = IPv4zero
+		}
+		if ip = ip.To4(); ip == nil {
+			return nil, InvalidAddrError("non-IPv4 address")
+		}
+		sa := new(syscall.SockaddrInet4)
+		for i := 0; i < IPv4len; i++ {
+			sa.Addr[i] = ip[i]
+		}
+		sa.Port = port
+		return sa, nil
+	case syscall.AF_INET6:
+		if len(ip) == 0 {
+			ip = IPv6zero
+		}
+		// IPv4 callers use 0.0.0.0 to mean "announce on any available address".
+		// In IPv6 mode, Linux treats that as meaning "announce on 0.0.0.0",
+		// which it refuses to do.  Rewrite to the IPv6 unspecified address.
+		if ip.Equal(IPv4zero) {
+			ip = IPv6zero
+		}
+		if ip = ip.To16(); ip == nil {
+			return nil, InvalidAddrError("non-IPv6 address")
+		}
+		sa := new(syscall.SockaddrInet6)
+		for i := 0; i < IPv6len; i++ {
+			sa.Addr[i] = ip[i]
+		}
+		sa.Port = port
+		sa.ZoneId = uint32(zoneToInt(zone))
+		return sa, nil
+	}
+	return nil, InvalidAddrError("unexpected socket family")
+}
diff --git a/third_party/gofrontend/libgo/go/net/ipsock_test.go b/third_party/gofrontend/libgo/go/net/ipsock_test.go
new file mode 100644
index 0000000..9ecaaec
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/ipsock_test.go
@@ -0,0 +1,193 @@
+// Copyright 2013 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 net
+
+import (
+	"reflect"
+	"testing"
+)
+
+var testInetaddr = func(ip IP) netaddr { return &TCPAddr{IP: ip, Port: 5682} }
+
+var firstFavoriteAddrTests = []struct {
+	filter   func(IP) IP
+	ips      []IP
+	inetaddr func(IP) netaddr
+	addr     netaddr
+	err      error
+}{
+	{
+		nil,
+		[]IP{
+			IPv4(127, 0, 0, 1),
+			IPv6loopback,
+		},
+		testInetaddr,
+		addrList{
+			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+			&TCPAddr{IP: IPv6loopback, Port: 5682},
+		},
+		nil,
+	},
+	{
+		nil,
+		[]IP{
+			IPv6loopback,
+			IPv4(127, 0, 0, 1),
+		},
+		testInetaddr,
+		addrList{
+			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+			&TCPAddr{IP: IPv6loopback, Port: 5682},
+		},
+		nil,
+	},
+	{
+		nil,
+		[]IP{
+			IPv4(127, 0, 0, 1),
+			IPv4(192, 168, 0, 1),
+		},
+		testInetaddr,
+		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+		nil,
+	},
+	{
+		nil,
+		[]IP{
+			IPv6loopback,
+			ParseIP("fe80::1"),
+		},
+		testInetaddr,
+		&TCPAddr{IP: IPv6loopback, Port: 5682},
+		nil,
+	},
+	{
+		nil,
+		[]IP{
+			IPv4(127, 0, 0, 1),
+			IPv4(192, 168, 0, 1),
+			IPv6loopback,
+			ParseIP("fe80::1"),
+		},
+		testInetaddr,
+		addrList{
+			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+			&TCPAddr{IP: IPv6loopback, Port: 5682},
+		},
+		nil,
+	},
+	{
+		nil,
+		[]IP{
+			IPv6loopback,
+			ParseIP("fe80::1"),
+			IPv4(127, 0, 0, 1),
+			IPv4(192, 168, 0, 1),
+		},
+		testInetaddr,
+		addrList{
+			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+			&TCPAddr{IP: IPv6loopback, Port: 5682},
+		},
+		nil,
+	},
+	{
+		nil,
+		[]IP{
+			IPv4(127, 0, 0, 1),
+			IPv6loopback,
+			IPv4(192, 168, 0, 1),
+			ParseIP("fe80::1"),
+		},
+		testInetaddr,
+		addrList{
+			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+			&TCPAddr{IP: IPv6loopback, Port: 5682},
+		},
+		nil,
+	},
+	{
+		nil,
+		[]IP{
+			IPv6loopback,
+			IPv4(127, 0, 0, 1),
+			ParseIP("fe80::1"),
+			IPv4(192, 168, 0, 1),
+		},
+		testInetaddr,
+		addrList{
+			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+			&TCPAddr{IP: IPv6loopback, Port: 5682},
+		},
+		nil,
+	},
+
+	{
+		ipv4only,
+		[]IP{
+			IPv4(127, 0, 0, 1),
+			IPv6loopback,
+		},
+		testInetaddr,
+		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+		nil,
+	},
+	{
+		ipv4only,
+		[]IP{
+			IPv6loopback,
+			IPv4(127, 0, 0, 1),
+		},
+		testInetaddr,
+		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+		nil,
+	},
+
+	{
+		ipv6only,
+		[]IP{
+			IPv4(127, 0, 0, 1),
+			IPv6loopback,
+		},
+		testInetaddr,
+		&TCPAddr{IP: IPv6loopback, Port: 5682},
+		nil,
+	},
+	{
+		ipv6only,
+		[]IP{
+			IPv6loopback,
+			IPv4(127, 0, 0, 1),
+		},
+		testInetaddr,
+		&TCPAddr{IP: IPv6loopback, Port: 5682},
+		nil,
+	},
+
+	{nil, nil, testInetaddr, nil, errNoSuitableAddress},
+
+	{ipv4only, nil, testInetaddr, nil, errNoSuitableAddress},
+	{ipv4only, []IP{IPv6loopback}, testInetaddr, nil, errNoSuitableAddress},
+
+	{ipv6only, nil, testInetaddr, nil, errNoSuitableAddress},
+	{ipv6only, []IP{IPv4(127, 0, 0, 1)}, testInetaddr, nil, errNoSuitableAddress},
+}
+
+func TestFirstFavoriteAddr(t *testing.T) {
+	if !supportsIPv4 || !supportsIPv6 {
+		t.Skip("ipv4 or ipv6 is not supported")
+	}
+
+	for i, tt := range firstFavoriteAddrTests {
+		addr, err := firstFavoriteAddr(tt.filter, tt.ips, tt.inetaddr)
+		if err != tt.err {
+			t.Errorf("#%v: got %v; expected %v", i, err, tt.err)
+		}
+		if !reflect.DeepEqual(addr, tt.addr) {
+			t.Errorf("#%v: got %v; expected %v", i, addr, tt.addr)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/lookup.go b/third_party/gofrontend/libgo/go/net/lookup.go
new file mode 100644
index 0000000..20f2057
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/lookup.go
@@ -0,0 +1,137 @@
+// 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 net
+
+import "time"
+
+// protocols contains minimal mappings between internet protocol
+// names and numbers for platforms that don't have a complete list of
+// protocol numbers.
+//
+// See http://www.iana.org/assignments/protocol-numbers
+var protocols = map[string]int{
+	"icmp": 1, "ICMP": 1,
+	"igmp": 2, "IGMP": 2,
+	"tcp": 6, "TCP": 6,
+	"udp": 17, "UDP": 17,
+	"ipv6-icmp": 58, "IPV6-ICMP": 58, "IPv6-ICMP": 58,
+}
+
+// LookupHost looks up the given host using the local resolver.
+// It returns an array of that host's addresses.
+func LookupHost(host string) (addrs []string, err error) {
+	return lookupHost(host)
+}
+
+// LookupIP looks up host using the local resolver.
+// It returns an array of that host's IPv4 and IPv6 addresses.
+func LookupIP(host string) (addrs []IP, err error) {
+	return lookupIPMerge(host)
+}
+
+var lookupGroup singleflight
+
+// lookupIPMerge wraps lookupIP, but makes sure that for any given
+// host, only one lookup is in-flight at a time. The returned memory
+// is always owned by the caller.
+func lookupIPMerge(host string) (addrs []IP, err error) {
+	addrsi, err, shared := lookupGroup.Do(host, func() (interface{}, error) {
+		return lookupIP(host)
+	})
+	if err != nil {
+		return nil, err
+	}
+	addrs = addrsi.([]IP)
+	if shared {
+		clone := make([]IP, len(addrs))
+		copy(clone, addrs)
+		addrs = clone
+	}
+	return addrs, nil
+}
+
+func lookupIPDeadline(host string, deadline time.Time) (addrs []IP, err error) {
+	if deadline.IsZero() {
+		return lookupIPMerge(host)
+	}
+
+	// TODO(bradfitz): consider pushing the deadline down into the
+	// name resolution functions. But that involves fixing it for
+	// the native Go resolver, cgo, Windows, etc.
+	//
+	// In the meantime, just use a goroutine. Most users affected
+	// by http://golang.org/issue/2631 are due to TCP connections
+	// to unresponsive hosts, not DNS.
+	timeout := deadline.Sub(time.Now())
+	if timeout <= 0 {
+		err = errTimeout
+		return
+	}
+	t := time.NewTimer(timeout)
+	defer t.Stop()
+	type res struct {
+		addrs []IP
+		err   error
+	}
+	resc := make(chan res, 1)
+	go func() {
+		a, err := lookupIPMerge(host)
+		resc <- res{a, err}
+	}()
+	select {
+	case <-t.C:
+		err = errTimeout
+	case r := <-resc:
+		addrs, err = r.addrs, r.err
+	}
+	return
+}
+
+// LookupPort looks up the port for the given network and service.
+func LookupPort(network, service string) (port int, err error) {
+	return lookupPort(network, service)
+}
+
+// LookupCNAME returns the canonical DNS host for the given name.
+// Callers that do not care about the canonical name can call
+// LookupHost or LookupIP directly; both take care of resolving
+// the canonical name as part of the lookup.
+func LookupCNAME(name string) (cname string, err error) {
+	return lookupCNAME(name)
+}
+
+// LookupSRV tries to resolve an SRV query of the given service,
+// protocol, and domain name.  The proto is "tcp" or "udp".
+// The returned records are sorted by priority and randomized
+// by weight within a priority.
+//
+// LookupSRV constructs the DNS name to look up following RFC 2782.
+// That is, it looks up _service._proto.name.  To accommodate services
+// publishing SRV records under non-standard names, if both service
+// and proto are empty strings, LookupSRV looks up name directly.
+func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+	return lookupSRV(service, proto, name)
+}
+
+// LookupMX returns the DNS MX records for the given domain name sorted by preference.
+func LookupMX(name string) (mx []*MX, err error) {
+	return lookupMX(name)
+}
+
+// LookupNS returns the DNS NS records for the given domain name.
+func LookupNS(name string) (ns []*NS, err error) {
+	return lookupNS(name)
+}
+
+// LookupTXT returns the DNS TXT records for the given domain name.
+func LookupTXT(name string) (txt []string, err error) {
+	return lookupTXT(name)
+}
+
+// LookupAddr performs a reverse lookup for the given address, returning a list
+// of names mapping to that address.
+func LookupAddr(addr string) (name []string, err error) {
+	return lookupAddr(addr)
+}
diff --git a/third_party/gofrontend/libgo/go/net/lookup_plan9.go b/third_party/gofrontend/libgo/go/net/lookup_plan9.go
new file mode 100644
index 0000000..b80ac10
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/lookup_plan9.go
@@ -0,0 +1,297 @@
+// 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.
+
+package net
+
+import (
+	"errors"
+	"os"
+)
+
+func query(filename, query string, bufSize int) (res []string, err error) {
+	file, err := os.OpenFile(filename, os.O_RDWR, 0)
+	if err != nil {
+		return
+	}
+	defer file.Close()
+
+	_, err = file.Seek(0, 0)
+	if err != nil {
+		return
+	}
+	_, err = file.WriteString(query)
+	if err != nil {
+		return
+	}
+	_, err = file.Seek(0, 0)
+	if err != nil {
+		return
+	}
+	buf := make([]byte, bufSize)
+	for {
+		n, _ := file.Read(buf)
+		if n <= 0 {
+			break
+		}
+		res = append(res, string(buf[:n]))
+	}
+	return
+}
+
+func queryCS(net, host, service string) (res []string, err error) {
+	switch net {
+	case "tcp4", "tcp6":
+		net = "tcp"
+	case "udp4", "udp6":
+		net = "udp"
+	}
+	if host == "" {
+		host = "*"
+	}
+	return query(netdir+"/cs", net+"!"+host+"!"+service, 128)
+}
+
+func queryCS1(net string, ip IP, port int) (clone, dest string, err error) {
+	ips := "*"
+	if len(ip) != 0 && !ip.IsUnspecified() {
+		ips = ip.String()
+	}
+	lines, err := queryCS(net, ips, itoa(port))
+	if err != nil {
+		return
+	}
+	f := getFields(lines[0])
+	if len(f) < 2 {
+		return "", "", errors.New("bad response from ndb/cs")
+	}
+	clone, dest = f[0], f[1]
+	return
+}
+
+func queryDNS(addr string, typ string) (res []string, err error) {
+	return query(netdir+"/dns", addr+" "+typ, 1024)
+}
+
+// toLower returns a lower-case version of in. Restricting us to
+// ASCII is sufficient to handle the IP protocol names and allow
+// us to not depend on the strings and unicode packages.
+func toLower(in string) string {
+	for _, c := range in {
+		if 'A' <= c && c <= 'Z' {
+			// Has upper case; need to fix.
+			out := []byte(in)
+			for i := 0; i < len(in); i++ {
+				c := in[i]
+				if 'A' <= c && c <= 'Z' {
+					c += 'a' - 'A'
+				}
+				out[i] = c
+			}
+			return string(out)
+		}
+	}
+	return in
+}
+
+// lookupProtocol looks up IP protocol name and returns
+// the corresponding protocol number.
+func lookupProtocol(name string) (proto int, err error) {
+	lines, err := query(netdir+"/cs", "!protocol="+toLower(name), 128)
+	if err != nil {
+		return 0, err
+	}
+	unknownProtoError := errors.New("unknown IP protocol specified: " + name)
+	if len(lines) == 0 {
+		return 0, unknownProtoError
+	}
+	f := getFields(lines[0])
+	if len(f) < 2 {
+		return 0, unknownProtoError
+	}
+	s := f[1]
+	if n, _, ok := dtoi(s, byteIndex(s, '=')+1); ok {
+		return n, nil
+	}
+	return 0, unknownProtoError
+}
+
+func lookupHost(host string) (addrs []string, err error) {
+	// Use netdir/cs instead of netdir/dns because cs knows about
+	// host names in local network (e.g. from /lib/ndb/local)
+	lines, err := queryCS("net", host, "1")
+	if err != nil {
+		return
+	}
+loop:
+	for _, line := range lines {
+		f := getFields(line)
+		if len(f) < 2 {
+			continue
+		}
+		addr := f[1]
+		if i := byteIndex(addr, '!'); i >= 0 {
+			addr = addr[:i] // remove port
+		}
+		if ParseIP(addr) == nil {
+			continue
+		}
+		// only return unique addresses
+		for _, a := range addrs {
+			if a == addr {
+				continue loop
+			}
+		}
+		addrs = append(addrs, addr)
+	}
+	return
+}
+
+func lookupIP(host string) (ips []IP, err error) {
+	addrs, err := LookupHost(host)
+	if err != nil {
+		return
+	}
+	for _, addr := range addrs {
+		if ip := ParseIP(addr); ip != nil {
+			ips = append(ips, ip)
+		}
+	}
+	return
+}
+
+func lookupPort(network, service string) (port int, err error) {
+	switch network {
+	case "tcp4", "tcp6":
+		network = "tcp"
+	case "udp4", "udp6":
+		network = "udp"
+	}
+	lines, err := queryCS(network, "127.0.0.1", service)
+	if err != nil {
+		return
+	}
+	unknownPortError := &AddrError{"unknown port", network + "/" + service}
+	if len(lines) == 0 {
+		return 0, unknownPortError
+	}
+	f := getFields(lines[0])
+	if len(f) < 2 {
+		return 0, unknownPortError
+	}
+	s := f[1]
+	if i := byteIndex(s, '!'); i >= 0 {
+		s = s[i+1:] // remove address
+	}
+	if n, _, ok := dtoi(s, 0); ok {
+		return n, nil
+	}
+	return 0, unknownPortError
+}
+
+func lookupCNAME(name string) (cname string, err error) {
+	lines, err := queryDNS(name, "cname")
+	if err != nil {
+		return
+	}
+	if len(lines) > 0 {
+		if f := getFields(lines[0]); len(f) >= 3 {
+			return f[2] + ".", nil
+		}
+	}
+	return "", errors.New("bad response from ndb/dns")
+}
+
+func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+	var target string
+	if service == "" && proto == "" {
+		target = name
+	} else {
+		target = "_" + service + "._" + proto + "." + name
+	}
+	lines, err := queryDNS(target, "srv")
+	if err != nil {
+		return
+	}
+	for _, line := range lines {
+		f := getFields(line)
+		if len(f) < 6 {
+			continue
+		}
+		port, _, portOk := dtoi(f[4], 0)
+		priority, _, priorityOk := dtoi(f[3], 0)
+		weight, _, weightOk := dtoi(f[2], 0)
+		if !(portOk && priorityOk && weightOk) {
+			continue
+		}
+		addrs = append(addrs, &SRV{f[5], uint16(port), uint16(priority), uint16(weight)})
+		cname = f[0]
+	}
+	byPriorityWeight(addrs).sort()
+	return
+}
+
+func lookupMX(name string) (mx []*MX, err error) {
+	lines, err := queryDNS(name, "mx")
+	if err != nil {
+		return
+	}
+	for _, line := range lines {
+		f := getFields(line)
+		if len(f) < 4 {
+			continue
+		}
+		if pref, _, ok := dtoi(f[2], 0); ok {
+			mx = append(mx, &MX{f[3], uint16(pref)})
+		}
+	}
+	byPref(mx).sort()
+	return
+}
+
+func lookupNS(name string) (ns []*NS, err error) {
+	lines, err := queryDNS(name, "ns")
+	if err != nil {
+		return
+	}
+	for _, line := range lines {
+		f := getFields(line)
+		if len(f) < 3 {
+			continue
+		}
+		ns = append(ns, &NS{f[2]})
+	}
+	return
+}
+
+func lookupTXT(name string) (txt []string, err error) {
+	lines, err := queryDNS(name, "txt")
+	if err != nil {
+		return
+	}
+	for _, line := range lines {
+		if i := byteIndex(line, '\t'); i >= 0 {
+			txt = append(txt, line[i+1:])
+		}
+	}
+	return
+}
+
+func lookupAddr(addr string) (name []string, err error) {
+	arpa, err := reverseaddr(addr)
+	if err != nil {
+		return
+	}
+	lines, err := queryDNS(arpa, "ptr")
+	if err != nil {
+		return
+	}
+	for _, line := range lines {
+		f := getFields(line)
+		if len(f) < 3 {
+			continue
+		}
+		name = append(name, f[2])
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/net/lookup_test.go b/third_party/gofrontend/libgo/go/net/lookup_test.go
new file mode 100644
index 0000000..3355e46
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/lookup_test.go
@@ -0,0 +1,137 @@
+// 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.
+
+// TODO It would be nice to use a mock DNS server, to eliminate
+// external dependencies.
+
+package net
+
+import (
+	"flag"
+	"strings"
+	"testing"
+)
+
+var testExternal = flag.Bool("external", true, "allow use of external networks during long test")
+
+func TestGoogleSRV(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+	_, addrs, err := LookupSRV("xmpp-server", "tcp", "google.com")
+	if err != nil {
+		t.Errorf("failed: %s", err)
+	}
+	if len(addrs) == 0 {
+		t.Errorf("no results")
+	}
+
+	// Non-standard back door.
+	_, addrs, err = LookupSRV("", "", "_xmpp-server._tcp.google.com")
+	if err != nil {
+		t.Errorf("back door failed: %s", err)
+	}
+	if len(addrs) == 0 {
+		t.Errorf("back door no results")
+	}
+}
+
+func TestGmailMX(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+	mx, err := LookupMX("gmail.com")
+	if err != nil {
+		t.Errorf("failed: %s", err)
+	}
+	if len(mx) == 0 {
+		t.Errorf("no results")
+	}
+}
+
+func TestGmailNS(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+	ns, err := LookupNS("gmail.com")
+	if err != nil {
+		t.Errorf("failed: %s", err)
+	}
+	if len(ns) == 0 {
+		t.Errorf("no results")
+	}
+}
+
+func TestGmailTXT(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+	txt, err := LookupTXT("gmail.com")
+	if err != nil {
+		t.Errorf("failed: %s", err)
+	}
+	if len(txt) == 0 || len(txt[0]) == 0 {
+		t.Errorf("no results")
+	}
+}
+
+func TestGoogleDNSAddr(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+	names, err := LookupAddr("8.8.8.8")
+	if err != nil {
+		t.Errorf("failed: %s", err)
+	}
+	if len(names) == 0 {
+		t.Errorf("no results")
+	}
+}
+
+func TestLookupIANACNAME(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+	cname, err := LookupCNAME("www.iana.org")
+	if !strings.HasSuffix(cname, ".icann.org.") || err != nil {
+		t.Errorf(`LookupCNAME("www.iana.org.") = %q, %v, want "*.icann.org.", nil`, cname, err)
+	}
+}
+
+var revAddrTests = []struct {
+	Addr      string
+	Reverse   string
+	ErrPrefix string
+}{
+	{"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
+	{"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
+	{"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
+	{"::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", ""},
+	{"1::", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.ip6.arpa.", ""},
+	{"1234:567::89a:bcde", "e.d.c.b.a.9.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.7.6.5.0.4.3.2.1.ip6.arpa.", ""},
+	{"1234:567:fefe:bcbc:adad:9e4a:89a:bcde", "e.d.c.b.a.9.8.0.a.4.e.9.d.a.d.a.c.b.c.b.e.f.e.f.7.6.5.0.4.3.2.1.ip6.arpa.", ""},
+	{"1.2.3", "", "unrecognized address"},
+	{"1.2.3.4.5", "", "unrecognized address"},
+	{"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
+	{"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
+}
+
+func TestReverseAddress(t *testing.T) {
+	for i, tt := range revAddrTests {
+		a, err := reverseaddr(tt.Addr)
+		if len(tt.ErrPrefix) > 0 && err == nil {
+			t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
+			continue
+		}
+		if len(tt.ErrPrefix) == 0 && err != nil {
+			t.Errorf("#%d: expected <nil>, got %q (error)", i, err)
+		}
+		if err != nil && err.(*DNSError).Err != tt.ErrPrefix {
+			t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err)
+		}
+		if a != tt.Reverse {
+			t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/lookup_unix.go b/third_party/gofrontend/libgo/go/net/lookup_unix.go
new file mode 100644
index 0000000..b1d2f8f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/lookup_unix.go
@@ -0,0 +1,168 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package net
+
+import (
+	"errors"
+	"sync"
+)
+
+var onceReadProtocols sync.Once
+
+// readProtocols loads contents of /etc/protocols into protocols map
+// for quick access.
+func readProtocols() {
+	if file, err := open("/etc/protocols"); err == nil {
+		for line, ok := file.readLine(); ok; line, ok = file.readLine() {
+			// tcp    6   TCP    # transmission control protocol
+			if i := byteIndex(line, '#'); i >= 0 {
+				line = line[0:i]
+			}
+			f := getFields(line)
+			if len(f) < 2 {
+				continue
+			}
+			if proto, _, ok := dtoi(f[1], 0); ok {
+				if _, ok := protocols[f[0]]; !ok {
+					protocols[f[0]] = proto
+				}
+				for _, alias := range f[2:] {
+					if _, ok := protocols[alias]; !ok {
+						protocols[alias] = proto
+					}
+				}
+			}
+		}
+		file.close()
+	}
+}
+
+// lookupProtocol looks up IP protocol name in /etc/protocols and
+// returns correspondent protocol number.
+func lookupProtocol(name string) (proto int, err error) {
+	onceReadProtocols.Do(readProtocols)
+	proto, found := protocols[name]
+	if !found {
+		return 0, errors.New("unknown IP protocol specified: " + name)
+	}
+	return
+}
+
+func lookupHost(host string) (addrs []string, err error) {
+	addrs, err, ok := cgoLookupHost(host)
+	if !ok {
+		addrs, err = goLookupHost(host)
+	}
+	return
+}
+
+func lookupIP(host string) (addrs []IP, err error) {
+	addrs, err, ok := cgoLookupIP(host)
+	if !ok {
+		addrs, err = goLookupIP(host)
+	}
+	return
+}
+
+func lookupPort(network, service string) (port int, err error) {
+	port, err, ok := cgoLookupPort(network, service)
+	if !ok {
+		port, err = goLookupPort(network, service)
+	}
+	return
+}
+
+func lookupCNAME(name string) (cname string, err error) {
+	cname, err, ok := cgoLookupCNAME(name)
+	if !ok {
+		cname, err = goLookupCNAME(name)
+	}
+	return
+}
+
+func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+	var target string
+	if service == "" && proto == "" {
+		target = name
+	} else {
+		target = "_" + service + "._" + proto + "." + name
+	}
+	var records []dnsRR
+	cname, records, err = lookup(target, dnsTypeSRV)
+	if err != nil {
+		return
+	}
+	addrs = make([]*SRV, len(records))
+	for i, rr := range records {
+		r := rr.(*dnsRR_SRV)
+		addrs[i] = &SRV{r.Target, r.Port, r.Priority, r.Weight}
+	}
+	byPriorityWeight(addrs).sort()
+	return
+}
+
+func lookupMX(name string) (mx []*MX, err error) {
+	_, records, err := lookup(name, dnsTypeMX)
+	if err != nil {
+		return
+	}
+	mx = make([]*MX, len(records))
+	for i, rr := range records {
+		r := rr.(*dnsRR_MX)
+		mx[i] = &MX{r.Mx, r.Pref}
+	}
+	byPref(mx).sort()
+	return
+}
+
+func lookupNS(name string) (ns []*NS, err error) {
+	_, records, err := lookup(name, dnsTypeNS)
+	if err != nil {
+		return
+	}
+	ns = make([]*NS, len(records))
+	for i, r := range records {
+		r := r.(*dnsRR_NS)
+		ns[i] = &NS{r.Ns}
+	}
+	return
+}
+
+func lookupTXT(name string) (txt []string, err error) {
+	_, records, err := lookup(name, dnsTypeTXT)
+	if err != nil {
+		return
+	}
+	txt = make([]string, len(records))
+	for i, r := range records {
+		txt[i] = r.(*dnsRR_TXT).Txt
+	}
+	return
+}
+
+func lookupAddr(addr string) (name []string, err error) {
+	name = lookupStaticAddr(addr)
+	if len(name) > 0 {
+		return
+	}
+	var arpa string
+	arpa, err = reverseaddr(addr)
+	if err != nil {
+		return
+	}
+	var records []dnsRR
+	_, records, err = lookup(arpa, dnsTypePTR)
+	if err != nil {
+		return
+	}
+	name = make([]string, len(records))
+	for i := range records {
+		r := records[i].(*dnsRR_PTR)
+		name[i] = r.Ptr
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/net/lookup_windows.go b/third_party/gofrontend/libgo/go/net/lookup_windows.go
new file mode 100644
index 0000000..1303642
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/lookup_windows.go
@@ -0,0 +1,322 @@
+// 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 net
+
+import (
+	"os"
+	"runtime"
+	"syscall"
+	"unsafe"
+)
+
+var (
+	lookupPort = oldLookupPort
+	lookupIP   = oldLookupIP
+)
+
+func getprotobyname(name string) (proto int, err error) {
+	p, err := syscall.GetProtoByName(name)
+	if err != nil {
+		return 0, os.NewSyscallError("GetProtoByName", err)
+	}
+	return int(p.Proto), nil
+}
+
+// lookupProtocol looks up IP protocol name and returns correspondent protocol number.
+func lookupProtocol(name string) (proto int, err error) {
+	// GetProtoByName return value is stored in thread local storage.
+	// Start new os thread before the call to prevent races.
+	type result struct {
+		proto int
+		err   error
+	}
+	ch := make(chan result)
+	go func() {
+		acquireThread()
+		defer releaseThread()
+		runtime.LockOSThread()
+		defer runtime.UnlockOSThread()
+		proto, err := getprotobyname(name)
+		ch <- result{proto: proto, err: err}
+	}()
+	r := <-ch
+	if r.err != nil {
+		if proto, ok := protocols[name]; ok {
+			return proto, nil
+		}
+	}
+	return r.proto, r.err
+}
+
+func lookupHost(name string) (addrs []string, err error) {
+	ips, err := LookupIP(name)
+	if err != nil {
+		return
+	}
+	addrs = make([]string, 0, len(ips))
+	for _, ip := range ips {
+		addrs = append(addrs, ip.String())
+	}
+	return
+}
+
+func gethostbyname(name string) (addrs []IP, err error) {
+	// caller already acquired thread
+	h, err := syscall.GetHostByName(name)
+	if err != nil {
+		return nil, os.NewSyscallError("GetHostByName", err)
+	}
+	switch h.AddrType {
+	case syscall.AF_INET:
+		i := 0
+		addrs = make([]IP, 100) // plenty of room to grow
+		for p := (*[100](*[4]byte))(unsafe.Pointer(h.AddrList)); i < cap(addrs) && p[i] != nil; i++ {
+			addrs[i] = IPv4(p[i][0], p[i][1], p[i][2], p[i][3])
+		}
+		addrs = addrs[0:i]
+	default: // TODO(vcc): Implement non IPv4 address lookups.
+		return nil, os.NewSyscallError("LookupIP", syscall.EWINDOWS)
+	}
+	return addrs, nil
+}
+
+func oldLookupIP(name string) (addrs []IP, err error) {
+	// GetHostByName return value is stored in thread local storage.
+	// Start new os thread before the call to prevent races.
+	type result struct {
+		addrs []IP
+		err   error
+	}
+	ch := make(chan result)
+	go func() {
+		acquireThread()
+		defer releaseThread()
+		runtime.LockOSThread()
+		defer runtime.UnlockOSThread()
+		addrs, err := gethostbyname(name)
+		ch <- result{addrs: addrs, err: err}
+	}()
+	r := <-ch
+	return r.addrs, r.err
+}
+
+func newLookupIP(name string) (addrs []IP, err error) {
+	acquireThread()
+	defer releaseThread()
+	hints := syscall.AddrinfoW{
+		Family:   syscall.AF_UNSPEC,
+		Socktype: syscall.SOCK_STREAM,
+		Protocol: syscall.IPPROTO_IP,
+	}
+	var result *syscall.AddrinfoW
+	e := syscall.GetAddrInfoW(syscall.StringToUTF16Ptr(name), nil, &hints, &result)
+	if e != nil {
+		return nil, os.NewSyscallError("GetAddrInfoW", e)
+	}
+	defer syscall.FreeAddrInfoW(result)
+	addrs = make([]IP, 0, 5)
+	for ; result != nil; result = result.Next {
+		addr := unsafe.Pointer(result.Addr)
+		switch result.Family {
+		case syscall.AF_INET:
+			a := (*syscall.RawSockaddrInet4)(addr).Addr
+			addrs = append(addrs, IPv4(a[0], a[1], a[2], a[3]))
+		case syscall.AF_INET6:
+			a := (*syscall.RawSockaddrInet6)(addr).Addr
+			addrs = append(addrs, IP{a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]})
+		default:
+			return nil, os.NewSyscallError("LookupIP", syscall.EWINDOWS)
+		}
+	}
+	return addrs, nil
+}
+
+func getservbyname(network, service string) (port int, err error) {
+	acquireThread()
+	defer releaseThread()
+	switch network {
+	case "tcp4", "tcp6":
+		network = "tcp"
+	case "udp4", "udp6":
+		network = "udp"
+	}
+	s, err := syscall.GetServByName(service, network)
+	if err != nil {
+		return 0, os.NewSyscallError("GetServByName", err)
+	}
+	return int(syscall.Ntohs(s.Port)), nil
+}
+
+func oldLookupPort(network, service string) (port int, err error) {
+	// GetServByName return value is stored in thread local storage.
+	// Start new os thread before the call to prevent races.
+	type result struct {
+		port int
+		err  error
+	}
+	ch := make(chan result)
+	go func() {
+		acquireThread()
+		defer releaseThread()
+		runtime.LockOSThread()
+		defer runtime.UnlockOSThread()
+		port, err := getservbyname(network, service)
+		ch <- result{port: port, err: err}
+	}()
+	r := <-ch
+	return r.port, r.err
+}
+
+func newLookupPort(network, service string) (port int, err error) {
+	acquireThread()
+	defer releaseThread()
+	var stype int32
+	switch network {
+	case "tcp4", "tcp6":
+		stype = syscall.SOCK_STREAM
+	case "udp4", "udp6":
+		stype = syscall.SOCK_DGRAM
+	}
+	hints := syscall.AddrinfoW{
+		Family:   syscall.AF_UNSPEC,
+		Socktype: stype,
+		Protocol: syscall.IPPROTO_IP,
+	}
+	var result *syscall.AddrinfoW
+	e := syscall.GetAddrInfoW(nil, syscall.StringToUTF16Ptr(service), &hints, &result)
+	if e != nil {
+		return 0, os.NewSyscallError("GetAddrInfoW", e)
+	}
+	defer syscall.FreeAddrInfoW(result)
+	if result == nil {
+		return 0, os.NewSyscallError("LookupPort", syscall.EINVAL)
+	}
+	addr := unsafe.Pointer(result.Addr)
+	switch result.Family {
+	case syscall.AF_INET:
+		a := (*syscall.RawSockaddrInet4)(addr)
+		return int(syscall.Ntohs(a.Port)), nil
+	case syscall.AF_INET6:
+		a := (*syscall.RawSockaddrInet6)(addr)
+		return int(syscall.Ntohs(a.Port)), nil
+	}
+	return 0, os.NewSyscallError("LookupPort", syscall.EINVAL)
+}
+
+func lookupCNAME(name string) (cname string, err error) {
+	acquireThread()
+	defer releaseThread()
+	var r *syscall.DNSRecord
+	e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
+	if e != nil {
+		return "", os.NewSyscallError("LookupCNAME", e)
+	}
+	defer syscall.DnsRecordListFree(r, 1)
+	if r != nil && r.Type == syscall.DNS_TYPE_CNAME {
+		v := (*syscall.DNSPTRData)(unsafe.Pointer(&r.Data[0]))
+		cname = syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]) + "."
+	}
+	return
+}
+
+func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+	acquireThread()
+	defer releaseThread()
+	var target string
+	if service == "" && proto == "" {
+		target = name
+	} else {
+		target = "_" + service + "._" + proto + "." + name
+	}
+	var r *syscall.DNSRecord
+	e := syscall.DnsQuery(target, syscall.DNS_TYPE_SRV, 0, nil, &r, nil)
+	if e != nil {
+		return "", nil, os.NewSyscallError("LookupSRV", e)
+	}
+	defer syscall.DnsRecordListFree(r, 1)
+	addrs = make([]*SRV, 0, 10)
+	for p := r; p != nil && p.Type == syscall.DNS_TYPE_SRV; p = p.Next {
+		v := (*syscall.DNSSRVData)(unsafe.Pointer(&p.Data[0]))
+		addrs = append(addrs, &SRV{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:]), v.Port, v.Priority, v.Weight})
+	}
+	byPriorityWeight(addrs).sort()
+	return name, addrs, nil
+}
+
+func lookupMX(name string) (mx []*MX, err error) {
+	acquireThread()
+	defer releaseThread()
+	var r *syscall.DNSRecord
+	e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil)
+	if e != nil {
+		return nil, os.NewSyscallError("LookupMX", e)
+	}
+	defer syscall.DnsRecordListFree(r, 1)
+	mx = make([]*MX, 0, 10)
+	for p := r; p != nil && p.Type == syscall.DNS_TYPE_MX; p = p.Next {
+		v := (*syscall.DNSMXData)(unsafe.Pointer(&p.Data[0]))
+		mx = append(mx, &MX{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.NameExchange))[:]) + ".", v.Preference})
+	}
+	byPref(mx).sort()
+	return mx, nil
+}
+
+func lookupNS(name string) (ns []*NS, err error) {
+	acquireThread()
+	defer releaseThread()
+	var r *syscall.DNSRecord
+	e := syscall.DnsQuery(name, syscall.DNS_TYPE_NS, 0, nil, &r, nil)
+	if e != nil {
+		return nil, os.NewSyscallError("LookupNS", e)
+	}
+	defer syscall.DnsRecordListFree(r, 1)
+	ns = make([]*NS, 0, 10)
+	for p := r; p != nil && p.Type == syscall.DNS_TYPE_NS; p = p.Next {
+		v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
+		ns = append(ns, &NS{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]) + "."})
+	}
+	return ns, nil
+}
+
+func lookupTXT(name string) (txt []string, err error) {
+	acquireThread()
+	defer releaseThread()
+	var r *syscall.DNSRecord
+	e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil)
+	if e != nil {
+		return nil, os.NewSyscallError("LookupTXT", e)
+	}
+	defer syscall.DnsRecordListFree(r, 1)
+	txt = make([]string, 0, 10)
+	if r != nil && r.Type == syscall.DNS_TYPE_TEXT {
+		d := (*syscall.DNSTXTData)(unsafe.Pointer(&r.Data[0]))
+		for _, v := range (*[1 << 10]*uint16)(unsafe.Pointer(&(d.StringArray[0])))[:d.StringCount] {
+			s := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(v))[:])
+			txt = append(txt, s)
+		}
+	}
+	return
+}
+
+func lookupAddr(addr string) (name []string, err error) {
+	acquireThread()
+	defer releaseThread()
+	arpa, err := reverseaddr(addr)
+	if err != nil {
+		return nil, err
+	}
+	var r *syscall.DNSRecord
+	e := syscall.DnsQuery(arpa, syscall.DNS_TYPE_PTR, 0, nil, &r, nil)
+	if e != nil {
+		return nil, os.NewSyscallError("LookupAddr", e)
+	}
+	defer syscall.DnsRecordListFree(r, 1)
+	name = make([]string, 0, 10)
+	for p := r; p != nil && p.Type == syscall.DNS_TYPE_PTR; p = p.Next {
+		v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
+		name = append(name, syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]))
+	}
+	return name, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/mac.go b/third_party/gofrontend/libgo/go/net/mac.go
new file mode 100644
index 0000000..d616b1f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/mac.go
@@ -0,0 +1,86 @@
+// 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.
+
+// MAC address manipulations
+
+package net
+
+import "errors"
+
+const hexDigit = "0123456789abcdef"
+
+// A HardwareAddr represents a physical hardware address.
+type HardwareAddr []byte
+
+func (a HardwareAddr) String() string {
+	if len(a) == 0 {
+		return ""
+	}
+	buf := make([]byte, 0, len(a)*3-1)
+	for i, b := range a {
+		if i > 0 {
+			buf = append(buf, ':')
+		}
+		buf = append(buf, hexDigit[b>>4])
+		buf = append(buf, hexDigit[b&0xF])
+	}
+	return string(buf)
+}
+
+// ParseMAC parses s as an IEEE 802 MAC-48, EUI-48, or EUI-64 using one of the
+// following formats:
+//   01:23:45:67:89:ab
+//   01:23:45:67:89:ab:cd:ef
+//   01-23-45-67-89-ab
+//   01-23-45-67-89-ab-cd-ef
+//   0123.4567.89ab
+//   0123.4567.89ab.cdef
+func ParseMAC(s string) (hw HardwareAddr, err error) {
+	if len(s) < 14 {
+		goto error
+	}
+
+	if s[2] == ':' || s[2] == '-' {
+		if (len(s)+1)%3 != 0 {
+			goto error
+		}
+		n := (len(s) + 1) / 3
+		if n != 6 && n != 8 {
+			goto error
+		}
+		hw = make(HardwareAddr, n)
+		for x, i := 0, 0; i < n; i++ {
+			var ok bool
+			if hw[i], ok = xtoi2(s[x:], s[2]); !ok {
+				goto error
+			}
+			x += 3
+		}
+	} else if s[4] == '.' {
+		if (len(s)+1)%5 != 0 {
+			goto error
+		}
+		n := 2 * (len(s) + 1) / 5
+		if n != 6 && n != 8 {
+			goto error
+		}
+		hw = make(HardwareAddr, n)
+		for x, i := 0, 0; i < n; i += 2 {
+			var ok bool
+			if hw[i], ok = xtoi2(s[x:x+2], 0); !ok {
+				goto error
+			}
+			if hw[i+1], ok = xtoi2(s[x+2:], s[4]); !ok {
+				goto error
+			}
+			x += 5
+		}
+	} else {
+		goto error
+	}
+	return hw, nil
+
+error:
+	return nil, errors.New("invalid MAC address: " + s)
+}
diff --git a/third_party/gofrontend/libgo/go/net/mac_test.go b/third_party/gofrontend/libgo/go/net/mac_test.go
new file mode 100644
index 0000000..8f9dc66
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/mac_test.go
@@ -0,0 +1,66 @@
+// 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.
+
+package net
+
+import (
+	"reflect"
+	"strings"
+	"testing"
+)
+
+var mactests = []struct {
+	in  string
+	out HardwareAddr
+	err string
+}{
+	{"01:23:45:67:89:AB", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab}, ""},
+	{"01-23-45-67-89-AB", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab}, ""},
+	{"0123.4567.89AB", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab}, ""},
+	{"ab:cd:ef:AB:CD:EF", HardwareAddr{0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef}, ""},
+	{"01.02.03.04.05.06", nil, "invalid MAC address"},
+	{"01:02:03:04:05:06:", nil, "invalid MAC address"},
+	{"x1:02:03:04:05:06", nil, "invalid MAC address"},
+	{"01002:03:04:05:06", nil, "invalid MAC address"},
+	{"01:02003:04:05:06", nil, "invalid MAC address"},
+	{"01:02:03004:05:06", nil, "invalid MAC address"},
+	{"01:02:03:04005:06", nil, "invalid MAC address"},
+	{"01:02:03:04:05006", nil, "invalid MAC address"},
+	{"01-02:03:04:05:06", nil, "invalid MAC address"},
+	{"01:02-03-04-05-06", nil, "invalid MAC address"},
+	{"0123:4567:89AF", nil, "invalid MAC address"},
+	{"0123-4567-89AF", nil, "invalid MAC address"},
+	{"01:23:45:67:89:AB:CD:EF", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, ""},
+	{"01-23-45-67-89-AB-CD-EF", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, ""},
+	{"0123.4567.89AB.CDEF", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, ""},
+}
+
+func match(err error, s string) bool {
+	if s == "" {
+		return err == nil
+	}
+	return err != nil && strings.Contains(err.Error(), s)
+}
+
+func TestMACParseString(t *testing.T) {
+	for i, tt := range mactests {
+		out, err := ParseMAC(tt.in)
+		if !reflect.DeepEqual(out, tt.out) || !match(err, tt.err) {
+			t.Errorf("ParseMAC(%q) = %v, %v, want %v, %v", tt.in, out, err, tt.out,
+				tt.err)
+		}
+		if tt.err == "" {
+			// Verify that serialization works too, and that it round-trips.
+			s := out.String()
+			out2, err := ParseMAC(s)
+			if err != nil {
+				t.Errorf("%d. ParseMAC(%q) = %v", i, s, err)
+				continue
+			}
+			if !reflect.DeepEqual(out2, out) {
+				t.Errorf("%d. ParseMAC(%q) = %v, want %v", i, s, out2, out)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/mail/message.go b/third_party/gofrontend/libgo/go/net/mail/message.go
new file mode 100644
index 0000000..ba0778c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/mail/message.go
@@ -0,0 +1,545 @@
+// 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.
+
+/*
+Package mail implements parsing of mail messages.
+
+For the most part, this package follows the syntax as specified by RFC 5322.
+Notable divergences:
+	* Obsolete address formats are not parsed, including addresses with
+	  embedded route information.
+	* Group addresses are not parsed.
+	* The full range of spacing (the CFWS syntax element) is not supported,
+	  such as breaking addresses across lines.
+*/
+package mail
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/textproto"
+	"strconv"
+	"strings"
+	"time"
+)
+
+var debug = debugT(false)
+
+type debugT bool
+
+func (d debugT) Printf(format string, args ...interface{}) {
+	if d {
+		log.Printf(format, args...)
+	}
+}
+
+// A Message represents a parsed mail message.
+type Message struct {
+	Header Header
+	Body   io.Reader
+}
+
+// ReadMessage reads a message from r.
+// The headers are parsed, and the body of the message will be available
+// for reading from r.
+func ReadMessage(r io.Reader) (msg *Message, err error) {
+	tp := textproto.NewReader(bufio.NewReader(r))
+
+	hdr, err := tp.ReadMIMEHeader()
+	if err != nil {
+		return nil, err
+	}
+
+	return &Message{
+		Header: Header(hdr),
+		Body:   tp.R,
+	}, nil
+}
+
+// Layouts suitable for passing to time.Parse.
+// These are tried in order.
+var dateLayouts []string
+
+func init() {
+	// Generate layouts based on RFC 5322, section 3.3.
+
+	dows := [...]string{"", "Mon, "}   // day-of-week
+	days := [...]string{"2", "02"}     // day = 1*2DIGIT
+	years := [...]string{"2006", "06"} // year = 4*DIGIT / 2*DIGIT
+	seconds := [...]string{":05", ""}  // second
+	// "-0700 (MST)" is not in RFC 5322, but is common.
+	zones := [...]string{"-0700", "MST", "-0700 (MST)"} // zone = (("+" / "-") 4DIGIT) / "GMT" / ...
+
+	for _, dow := range dows {
+		for _, day := range days {
+			for _, year := range years {
+				for _, second := range seconds {
+					for _, zone := range zones {
+						s := dow + day + " Jan " + year + " 15:04" + second + " " + zone
+						dateLayouts = append(dateLayouts, s)
+					}
+				}
+			}
+		}
+	}
+}
+
+func parseDate(date string) (time.Time, error) {
+	for _, layout := range dateLayouts {
+		t, err := time.Parse(layout, date)
+		if err == nil {
+			return t, nil
+		}
+	}
+	return time.Time{}, errors.New("mail: header could not be parsed")
+}
+
+// A Header represents the key-value pairs in a mail message header.
+type Header map[string][]string
+
+// Get gets the first value associated with the given key.
+// If there are no values associated with the key, Get returns "".
+func (h Header) Get(key string) string {
+	return textproto.MIMEHeader(h).Get(key)
+}
+
+var ErrHeaderNotPresent = errors.New("mail: header not in message")
+
+// Date parses the Date header field.
+func (h Header) Date() (time.Time, error) {
+	hdr := h.Get("Date")
+	if hdr == "" {
+		return time.Time{}, ErrHeaderNotPresent
+	}
+	return parseDate(hdr)
+}
+
+// AddressList parses the named header field as a list of addresses.
+func (h Header) AddressList(key string) ([]*Address, error) {
+	hdr := h.Get(key)
+	if hdr == "" {
+		return nil, ErrHeaderNotPresent
+	}
+	return ParseAddressList(hdr)
+}
+
+// Address represents a single mail address.
+// An address such as "Barry Gibbs <bg@example.com>" is represented
+// as Address{Name: "Barry Gibbs", Address: "bg@example.com"}.
+type Address struct {
+	Name    string // Proper name; may be empty.
+	Address string // user@domain
+}
+
+// Parses a single RFC 5322 address, e.g. "Barry Gibbs <bg@example.com>"
+func ParseAddress(address string) (*Address, error) {
+	return newAddrParser(address).parseAddress()
+}
+
+// ParseAddressList parses the given string as a list of addresses.
+func ParseAddressList(list string) ([]*Address, error) {
+	return newAddrParser(list).parseAddressList()
+}
+
+// String formats the address as a valid RFC 5322 address.
+// If the address's name contains non-ASCII characters
+// the name will be rendered according to RFC 2047.
+func (a *Address) String() string {
+	s := "<" + a.Address + ">"
+	if a.Name == "" {
+		return s
+	}
+	// If every character is printable ASCII, quoting is simple.
+	allPrintable := true
+	for i := 0; i < len(a.Name); i++ {
+		// isWSP here should actually be isFWS,
+		// but we don't support folding yet.
+		if !isVchar(a.Name[i]) && !isWSP(a.Name[i]) {
+			allPrintable = false
+			break
+		}
+	}
+	if allPrintable {
+		b := bytes.NewBufferString(`"`)
+		for i := 0; i < len(a.Name); i++ {
+			if !isQtext(a.Name[i]) && !isWSP(a.Name[i]) {
+				b.WriteByte('\\')
+			}
+			b.WriteByte(a.Name[i])
+		}
+		b.WriteString(`" `)
+		b.WriteString(s)
+		return b.String()
+	}
+
+	// UTF-8 "Q" encoding
+	b := bytes.NewBufferString("=?utf-8?q?")
+	for i := 0; i < len(a.Name); i++ {
+		switch c := a.Name[i]; {
+		case c == ' ':
+			b.WriteByte('_')
+		case isVchar(c) && c != '=' && c != '?' && c != '_':
+			b.WriteByte(c)
+		default:
+			fmt.Fprintf(b, "=%02X", c)
+		}
+	}
+	b.WriteString("?= ")
+	b.WriteString(s)
+	return b.String()
+}
+
+type addrParser []byte
+
+func newAddrParser(s string) *addrParser {
+	p := addrParser(s)
+	return &p
+}
+
+func (p *addrParser) parseAddressList() ([]*Address, error) {
+	var list []*Address
+	for {
+		p.skipSpace()
+		addr, err := p.parseAddress()
+		if err != nil {
+			return nil, err
+		}
+		list = append(list, addr)
+
+		p.skipSpace()
+		if p.empty() {
+			break
+		}
+		if !p.consume(',') {
+			return nil, errors.New("mail: expected comma")
+		}
+	}
+	return list, nil
+}
+
+// parseAddress parses a single RFC 5322 address at the start of p.
+func (p *addrParser) parseAddress() (addr *Address, err error) {
+	debug.Printf("parseAddress: %q", *p)
+	p.skipSpace()
+	if p.empty() {
+		return nil, errors.New("mail: no address")
+	}
+
+	// address = name-addr / addr-spec
+	// TODO(dsymonds): Support parsing group address.
+
+	// addr-spec has a more restricted grammar than name-addr,
+	// so try parsing it first, and fallback to name-addr.
+	// TODO(dsymonds): Is this really correct?
+	spec, err := p.consumeAddrSpec()
+	if err == nil {
+		return &Address{
+			Address: spec,
+		}, err
+	}
+	debug.Printf("parseAddress: not an addr-spec: %v", err)
+	debug.Printf("parseAddress: state is now %q", *p)
+
+	// display-name
+	var displayName string
+	if p.peek() != '<' {
+		displayName, err = p.consumePhrase()
+		if err != nil {
+			return nil, err
+		}
+	}
+	debug.Printf("parseAddress: displayName=%q", displayName)
+
+	// angle-addr = "<" addr-spec ">"
+	p.skipSpace()
+	if !p.consume('<') {
+		return nil, errors.New("mail: no angle-addr")
+	}
+	spec, err = p.consumeAddrSpec()
+	if err != nil {
+		return nil, err
+	}
+	if !p.consume('>') {
+		return nil, errors.New("mail: unclosed angle-addr")
+	}
+	debug.Printf("parseAddress: spec=%q", spec)
+
+	return &Address{
+		Name:    displayName,
+		Address: spec,
+	}, nil
+}
+
+// consumeAddrSpec parses a single RFC 5322 addr-spec at the start of p.
+func (p *addrParser) consumeAddrSpec() (spec string, err error) {
+	debug.Printf("consumeAddrSpec: %q", *p)
+
+	orig := *p
+	defer func() {
+		if err != nil {
+			*p = orig
+		}
+	}()
+
+	// local-part = dot-atom / quoted-string
+	var localPart string
+	p.skipSpace()
+	if p.empty() {
+		return "", errors.New("mail: no addr-spec")
+	}
+	if p.peek() == '"' {
+		// quoted-string
+		debug.Printf("consumeAddrSpec: parsing quoted-string")
+		localPart, err = p.consumeQuotedString()
+	} else {
+		// dot-atom
+		debug.Printf("consumeAddrSpec: parsing dot-atom")
+		localPart, err = p.consumeAtom(true)
+	}
+	if err != nil {
+		debug.Printf("consumeAddrSpec: failed: %v", err)
+		return "", err
+	}
+
+	if !p.consume('@') {
+		return "", errors.New("mail: missing @ in addr-spec")
+	}
+
+	// domain = dot-atom / domain-literal
+	var domain string
+	p.skipSpace()
+	if p.empty() {
+		return "", errors.New("mail: no domain in addr-spec")
+	}
+	// TODO(dsymonds): Handle domain-literal
+	domain, err = p.consumeAtom(true)
+	if err != nil {
+		return "", err
+	}
+
+	return localPart + "@" + domain, nil
+}
+
+// consumePhrase parses the RFC 5322 phrase at the start of p.
+func (p *addrParser) consumePhrase() (phrase string, err error) {
+	debug.Printf("consumePhrase: [%s]", *p)
+	// phrase = 1*word
+	var words []string
+	for {
+		// word = atom / quoted-string
+		var word string
+		p.skipSpace()
+		if p.empty() {
+			return "", errors.New("mail: missing phrase")
+		}
+		if p.peek() == '"' {
+			// quoted-string
+			word, err = p.consumeQuotedString()
+		} else {
+			// atom
+			// We actually parse dot-atom here to be more permissive
+			// than what RFC 5322 specifies.
+			word, err = p.consumeAtom(true)
+		}
+
+		// RFC 2047 encoded-word starts with =?, ends with ?=, and has two other ?s.
+		if err == nil && strings.HasPrefix(word, "=?") && strings.HasSuffix(word, "?=") && strings.Count(word, "?") == 4 {
+			word, err = decodeRFC2047Word(word)
+		}
+
+		if err != nil {
+			break
+		}
+		debug.Printf("consumePhrase: consumed %q", word)
+		words = append(words, word)
+	}
+	// Ignore any error if we got at least one word.
+	if err != nil && len(words) == 0 {
+		debug.Printf("consumePhrase: hit err: %v", err)
+		return "", fmt.Errorf("mail: missing word in phrase: %v", err)
+	}
+	phrase = strings.Join(words, " ")
+	return phrase, nil
+}
+
+// consumeQuotedString parses the quoted string at the start of p.
+func (p *addrParser) consumeQuotedString() (qs string, err error) {
+	// Assume first byte is '"'.
+	i := 1
+	qsb := make([]byte, 0, 10)
+Loop:
+	for {
+		if i >= p.len() {
+			return "", errors.New("mail: unclosed quoted-string")
+		}
+		switch c := (*p)[i]; {
+		case c == '"':
+			break Loop
+		case c == '\\':
+			if i+1 == p.len() {
+				return "", errors.New("mail: unclosed quoted-string")
+			}
+			qsb = append(qsb, (*p)[i+1])
+			i += 2
+		case isQtext(c), c == ' ' || c == '\t':
+			// qtext (printable US-ASCII excluding " and \), or
+			// FWS (almost; we're ignoring CRLF)
+			qsb = append(qsb, c)
+			i++
+		default:
+			return "", fmt.Errorf("mail: bad character in quoted-string: %q", c)
+		}
+	}
+	*p = (*p)[i+1:]
+	return string(qsb), nil
+}
+
+// consumeAtom parses an RFC 5322 atom at the start of p.
+// If dot is true, consumeAtom parses an RFC 5322 dot-atom instead.
+func (p *addrParser) consumeAtom(dot bool) (atom string, err error) {
+	if !isAtext(p.peek(), false) {
+		return "", errors.New("mail: invalid string")
+	}
+	i := 1
+	for ; i < p.len() && isAtext((*p)[i], dot); i++ {
+	}
+	atom, *p = string((*p)[:i]), (*p)[i:]
+	return atom, nil
+}
+
+func (p *addrParser) consume(c byte) bool {
+	if p.empty() || p.peek() != c {
+		return false
+	}
+	*p = (*p)[1:]
+	return true
+}
+
+// skipSpace skips the leading space and tab characters.
+func (p *addrParser) skipSpace() {
+	*p = bytes.TrimLeft(*p, " \t")
+}
+
+func (p *addrParser) peek() byte {
+	return (*p)[0]
+}
+
+func (p *addrParser) empty() bool {
+	return p.len() == 0
+}
+
+func (p *addrParser) len() int {
+	return len(*p)
+}
+
+func decodeRFC2047Word(s string) (string, error) {
+	fields := strings.Split(s, "?")
+	if len(fields) != 5 || fields[0] != "=" || fields[4] != "=" {
+		return "", errors.New("address not RFC 2047 encoded")
+	}
+	charset, enc := strings.ToLower(fields[1]), strings.ToLower(fields[2])
+	if charset != "iso-8859-1" && charset != "utf-8" {
+		return "", fmt.Errorf("charset not supported: %q", charset)
+	}
+
+	in := bytes.NewBufferString(fields[3])
+	var r io.Reader
+	switch enc {
+	case "b":
+		r = base64.NewDecoder(base64.StdEncoding, in)
+	case "q":
+		r = qDecoder{r: in}
+	default:
+		return "", fmt.Errorf("RFC 2047 encoding not supported: %q", enc)
+	}
+
+	dec, err := ioutil.ReadAll(r)
+	if err != nil {
+		return "", err
+	}
+
+	switch charset {
+	case "iso-8859-1":
+		b := new(bytes.Buffer)
+		for _, c := range dec {
+			b.WriteRune(rune(c))
+		}
+		return b.String(), nil
+	case "utf-8":
+		return string(dec), nil
+	}
+	panic("unreachable")
+}
+
+type qDecoder struct {
+	r       io.Reader
+	scratch [2]byte
+}
+
+func (qd qDecoder) Read(p []byte) (n int, err error) {
+	// This method writes at most one byte into p.
+	if len(p) == 0 {
+		return 0, nil
+	}
+	if _, err := qd.r.Read(qd.scratch[:1]); err != nil {
+		return 0, err
+	}
+	switch c := qd.scratch[0]; {
+	case c == '=':
+		if _, err := io.ReadFull(qd.r, qd.scratch[:2]); err != nil {
+			return 0, err
+		}
+		x, err := strconv.ParseInt(string(qd.scratch[:2]), 16, 64)
+		if err != nil {
+			return 0, fmt.Errorf("mail: invalid RFC 2047 encoding: %q", qd.scratch[:2])
+		}
+		p[0] = byte(x)
+	case c == '_':
+		p[0] = ' '
+	default:
+		p[0] = c
+	}
+	return 1, nil
+}
+
+var atextChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+	"abcdefghijklmnopqrstuvwxyz" +
+	"0123456789" +
+	"!#$%&'*+-/=?^_`{|}~")
+
+// isAtext returns true if c is an RFC 5322 atext character.
+// If dot is true, period is included.
+func isAtext(c byte, dot bool) bool {
+	if dot && c == '.' {
+		return true
+	}
+	return bytes.IndexByte(atextChars, c) >= 0
+}
+
+// isQtext returns true if c is an RFC 5322 qtext character.
+func isQtext(c byte) bool {
+	// Printable US-ASCII, excluding backslash or quote.
+	if c == '\\' || c == '"' {
+		return false
+	}
+	return '!' <= c && c <= '~'
+}
+
+// isVchar returns true if c is an RFC 5322 VCHAR character.
+func isVchar(c byte) bool {
+	// Visible (printing) characters.
+	return '!' <= c && c <= '~'
+}
+
+// isWSP returns true if c is a WSP (white space).
+// WSP is a space or horizontal tab (RFC5234 Appendix B).
+func isWSP(c byte) bool {
+	return c == ' ' || c == '\t'
+}
diff --git a/third_party/gofrontend/libgo/go/net/mail/message_test.go b/third_party/gofrontend/libgo/go/net/mail/message_test.go
new file mode 100644
index 0000000..eb9c8cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/mail/message_test.go
@@ -0,0 +1,304 @@
+// 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.
+
+package mail
+
+import (
+	"bytes"
+	"io/ioutil"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+)
+
+var parseTests = []struct {
+	in     string
+	header Header
+	body   string
+}{
+	{
+		// RFC 5322, Appendix A.1.1
+		in: `From: John Doe <jdoe@machine.example>
+To: Mary Smith <mary@example.net>
+Subject: Saying Hello
+Date: Fri, 21 Nov 1997 09:55:06 -0600
+Message-ID: <1234@local.machine.example>
+
+This is a message just to say hello.
+So, "Hello".
+`,
+		header: Header{
+			"From":       []string{"John Doe <jdoe@machine.example>"},
+			"To":         []string{"Mary Smith <mary@example.net>"},
+			"Subject":    []string{"Saying Hello"},
+			"Date":       []string{"Fri, 21 Nov 1997 09:55:06 -0600"},
+			"Message-Id": []string{"<1234@local.machine.example>"},
+		},
+		body: "This is a message just to say hello.\nSo, \"Hello\".\n",
+	},
+}
+
+func TestParsing(t *testing.T) {
+	for i, test := range parseTests {
+		msg, err := ReadMessage(bytes.NewBuffer([]byte(test.in)))
+		if err != nil {
+			t.Errorf("test #%d: Failed parsing message: %v", i, err)
+			continue
+		}
+		if !headerEq(msg.Header, test.header) {
+			t.Errorf("test #%d: Incorrectly parsed message header.\nGot:\n%+v\nWant:\n%+v",
+				i, msg.Header, test.header)
+		}
+		body, err := ioutil.ReadAll(msg.Body)
+		if err != nil {
+			t.Errorf("test #%d: Failed reading body: %v", i, err)
+			continue
+		}
+		bodyStr := string(body)
+		if bodyStr != test.body {
+			t.Errorf("test #%d: Incorrectly parsed message body.\nGot:\n%+v\nWant:\n%+v",
+				i, bodyStr, test.body)
+		}
+	}
+}
+
+func headerEq(a, b Header) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for k, as := range a {
+		bs, ok := b[k]
+		if !ok {
+			return false
+		}
+		if !reflect.DeepEqual(as, bs) {
+			return false
+		}
+	}
+	return true
+}
+
+func TestDateParsing(t *testing.T) {
+	tests := []struct {
+		dateStr string
+		exp     time.Time
+	}{
+		// RFC 5322, Appendix A.1.1
+		{
+			"Fri, 21 Nov 1997 09:55:06 -0600",
+			time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", -6*60*60)),
+		},
+		// RFC5322, Appendix A.6.2
+		// Obsolete date.
+		{
+			"21 Nov 97 09:55:06 GMT",
+			time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("GMT", 0)),
+		},
+		// Commonly found format not specified by RFC 5322.
+		{
+			"Fri, 21 Nov 1997 09:55:06 -0600 (MDT)",
+			time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", -6*60*60)),
+		},
+	}
+	for _, test := range tests {
+		hdr := Header{
+			"Date": []string{test.dateStr},
+		}
+		date, err := hdr.Date()
+		if err != nil {
+			t.Errorf("Failed parsing %q: %v", test.dateStr, err)
+			continue
+		}
+		if !date.Equal(test.exp) {
+			t.Errorf("Parse of %q: got %+v, want %+v", test.dateStr, date, test.exp)
+		}
+	}
+}
+
+func TestAddressParsingError(t *testing.T) {
+	const txt = "=?iso-8859-2?Q?Bogl=E1rka_Tak=E1cs?= <unknown@gmail.com>"
+	_, err := ParseAddress(txt)
+	if err == nil || !strings.Contains(err.Error(), "charset not supported") {
+		t.Errorf(`mail.ParseAddress(%q) err: %q, want ".*charset not supported.*"`, txt, err)
+	}
+}
+
+func TestAddressParsing(t *testing.T) {
+	tests := []struct {
+		addrsStr string
+		exp      []*Address
+	}{
+		// Bare address
+		{
+			`jdoe@machine.example`,
+			[]*Address{{
+				Address: "jdoe@machine.example",
+			}},
+		},
+		// RFC 5322, Appendix A.1.1
+		{
+			`John Doe <jdoe@machine.example>`,
+			[]*Address{{
+				Name:    "John Doe",
+				Address: "jdoe@machine.example",
+			}},
+		},
+		// RFC 5322, Appendix A.1.2
+		{
+			`"Joe Q. Public" <john.q.public@example.com>`,
+			[]*Address{{
+				Name:    "Joe Q. Public",
+				Address: "john.q.public@example.com",
+			}},
+		},
+		{
+			`Mary Smith <mary@x.test>, jdoe@example.org, Who? <one@y.test>`,
+			[]*Address{
+				{
+					Name:    "Mary Smith",
+					Address: "mary@x.test",
+				},
+				{
+					Address: "jdoe@example.org",
+				},
+				{
+					Name:    "Who?",
+					Address: "one@y.test",
+				},
+			},
+		},
+		{
+			`<boss@nil.test>, "Giant; \"Big\" Box" <sysservices@example.net>`,
+			[]*Address{
+				{
+					Address: "boss@nil.test",
+				},
+				{
+					Name:    `Giant; "Big" Box`,
+					Address: "sysservices@example.net",
+				},
+			},
+		},
+		// RFC 5322, Appendix A.1.3
+		// TODO(dsymonds): Group addresses.
+
+		// RFC 2047 "Q"-encoded ISO-8859-1 address.
+		{
+			`=?iso-8859-1?q?J=F6rg_Doe?= <joerg@example.com>`,
+			[]*Address{
+				{
+					Name:    `Jörg Doe`,
+					Address: "joerg@example.com",
+				},
+			},
+		},
+		// RFC 2047 "Q"-encoded UTF-8 address.
+		{
+			`=?utf-8?q?J=C3=B6rg_Doe?= <joerg@example.com>`,
+			[]*Address{
+				{
+					Name:    `Jörg Doe`,
+					Address: "joerg@example.com",
+				},
+			},
+		},
+		// RFC 2047, Section 8.
+		{
+			`=?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>`,
+			[]*Address{
+				{
+					Name:    `André Pirard`,
+					Address: "PIRARD@vm1.ulg.ac.be",
+				},
+			},
+		},
+		// Custom example of RFC 2047 "B"-encoded ISO-8859-1 address.
+		{
+			`=?ISO-8859-1?B?SvZyZw==?= <joerg@example.com>`,
+			[]*Address{
+				{
+					Name:    `Jörg`,
+					Address: "joerg@example.com",
+				},
+			},
+		},
+		// Custom example of RFC 2047 "B"-encoded UTF-8 address.
+		{
+			`=?UTF-8?B?SsO2cmc=?= <joerg@example.com>`,
+			[]*Address{
+				{
+					Name:    `Jörg`,
+					Address: "joerg@example.com",
+				},
+			},
+		},
+		// Custom example with "." in name. For issue 4938
+		{
+			`Asem H. <noreply@example.com>`,
+			[]*Address{
+				{
+					Name:    `Asem H.`,
+					Address: "noreply@example.com",
+				},
+			},
+		},
+	}
+	for _, test := range tests {
+		if len(test.exp) == 1 {
+			addr, err := ParseAddress(test.addrsStr)
+			if err != nil {
+				t.Errorf("Failed parsing (single) %q: %v", test.addrsStr, err)
+				continue
+			}
+			if !reflect.DeepEqual([]*Address{addr}, test.exp) {
+				t.Errorf("Parse (single) of %q: got %+v, want %+v", test.addrsStr, addr, test.exp)
+			}
+		}
+
+		addrs, err := ParseAddressList(test.addrsStr)
+		if err != nil {
+			t.Errorf("Failed parsing (list) %q: %v", test.addrsStr, err)
+			continue
+		}
+		if !reflect.DeepEqual(addrs, test.exp) {
+			t.Errorf("Parse (list) of %q: got %+v, want %+v", test.addrsStr, addrs, test.exp)
+		}
+	}
+}
+
+func TestAddressFormatting(t *testing.T) {
+	tests := []struct {
+		addr *Address
+		exp  string
+	}{
+		{
+			&Address{Address: "bob@example.com"},
+			"<bob@example.com>",
+		},
+		{
+			&Address{Name: "Bob", Address: "bob@example.com"},
+			`"Bob" <bob@example.com>`,
+		},
+		{
+			// note the ö (o with an umlaut)
+			&Address{Name: "Böb", Address: "bob@example.com"},
+			`=?utf-8?q?B=C3=B6b?= <bob@example.com>`,
+		},
+		{
+			&Address{Name: "Bob Jane", Address: "bob@example.com"},
+			`"Bob Jane" <bob@example.com>`,
+		},
+		{
+			&Address{Name: "Böb Jacöb", Address: "bob@example.com"},
+			`=?utf-8?q?B=C3=B6b_Jac=C3=B6b?= <bob@example.com>`,
+		},
+	}
+	for _, test := range tests {
+		s := test.addr.String()
+		if s != test.exp {
+			t.Errorf("Address%+v.String() = %v, want %v", *test.addr, s, test.exp)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/mockicmp_test.go b/third_party/gofrontend/libgo/go/net/mockicmp_test.go
new file mode 100644
index 0000000..e742365
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/mockicmp_test.go
@@ -0,0 +1,116 @@
+// 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 net
+
+import "errors"
+
+const (
+	icmpv4EchoRequest = 8
+	icmpv4EchoReply   = 0
+	icmpv6EchoRequest = 128
+	icmpv6EchoReply   = 129
+)
+
+// icmpMessage represents an ICMP message.
+type icmpMessage struct {
+	Type     int             // type
+	Code     int             // code
+	Checksum int             // checksum
+	Body     icmpMessageBody // body
+}
+
+// icmpMessageBody represents an ICMP message body.
+type icmpMessageBody interface {
+	Len() int
+	Marshal() ([]byte, error)
+}
+
+// Marshal returns the binary enconding of the ICMP echo request or
+// reply message m.
+func (m *icmpMessage) Marshal() ([]byte, error) {
+	b := []byte{byte(m.Type), byte(m.Code), 0, 0}
+	if m.Body != nil && m.Body.Len() != 0 {
+		mb, err := m.Body.Marshal()
+		if err != nil {
+			return nil, err
+		}
+		b = append(b, mb...)
+	}
+	switch m.Type {
+	case icmpv6EchoRequest, icmpv6EchoReply:
+		return b, nil
+	}
+	csumcv := len(b) - 1 // checksum coverage
+	s := uint32(0)
+	for i := 0; i < csumcv; i += 2 {
+		s += uint32(b[i+1])<<8 | uint32(b[i])
+	}
+	if csumcv&1 == 0 {
+		s += uint32(b[csumcv])
+	}
+	s = s>>16 + s&0xffff
+	s = s + s>>16
+	// Place checksum back in header; using ^= avoids the
+	// assumption the checksum bytes are zero.
+	b[2] ^= byte(^s)
+	b[3] ^= byte(^s >> 8)
+	return b, nil
+}
+
+// parseICMPMessage parses b as an ICMP message.
+func parseICMPMessage(b []byte) (*icmpMessage, error) {
+	msglen := len(b)
+	if msglen < 4 {
+		return nil, errors.New("message too short")
+	}
+	m := &icmpMessage{Type: int(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
+	if msglen > 4 {
+		var err error
+		switch m.Type {
+		case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply:
+			m.Body, err = parseICMPEcho(b[4:])
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+	return m, nil
+}
+
+// imcpEcho represenets an ICMP echo request or reply message body.
+type icmpEcho struct {
+	ID   int    // identifier
+	Seq  int    // sequence number
+	Data []byte // data
+}
+
+func (p *icmpEcho) Len() int {
+	if p == nil {
+		return 0
+	}
+	return 4 + len(p.Data)
+}
+
+// Marshal returns the binary enconding of the ICMP echo request or
+// reply message body p.
+func (p *icmpEcho) Marshal() ([]byte, error) {
+	b := make([]byte, 4+len(p.Data))
+	b[0], b[1] = byte(p.ID>>8), byte(p.ID)
+	b[2], b[3] = byte(p.Seq>>8), byte(p.Seq)
+	copy(b[4:], p.Data)
+	return b, nil
+}
+
+// parseICMPEcho parses b as an ICMP echo request or reply message
+// body.
+func parseICMPEcho(b []byte) (*icmpEcho, error) {
+	bodylen := len(b)
+	p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
+	if bodylen > 4 {
+		p.Data = make([]byte, bodylen-4)
+		copy(p.Data, b[4:])
+	}
+	return p, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/mockserver_test.go b/third_party/gofrontend/libgo/go/net/mockserver_test.go
new file mode 100644
index 0000000..68ded5d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/mockserver_test.go
@@ -0,0 +1,82 @@
+// Copyright 2013 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 net
+
+import "sync"
+
+type streamListener struct {
+	net, addr string
+	ln        Listener
+}
+
+type dualStackServer struct {
+	lnmu sync.RWMutex
+	lns  []streamListener
+	port string
+
+	cmu sync.RWMutex
+	cs  []Conn // established connections at the passive open side
+}
+
+func (dss *dualStackServer) buildup(server func(*dualStackServer, Listener)) error {
+	for i := range dss.lns {
+		go server(dss, dss.lns[i].ln)
+	}
+	return nil
+}
+
+func (dss *dualStackServer) putConn(c Conn) error {
+	dss.cmu.Lock()
+	dss.cs = append(dss.cs, c)
+	dss.cmu.Unlock()
+	return nil
+}
+
+func (dss *dualStackServer) teardownNetwork(net string) error {
+	dss.lnmu.Lock()
+	for i := range dss.lns {
+		if net == dss.lns[i].net && dss.lns[i].ln != nil {
+			dss.lns[i].ln.Close()
+			dss.lns[i].ln = nil
+		}
+	}
+	dss.lnmu.Unlock()
+	return nil
+}
+
+func (dss *dualStackServer) teardown() error {
+	dss.lnmu.Lock()
+	for i := range dss.lns {
+		if dss.lns[i].ln != nil {
+			dss.lns[i].ln.Close()
+		}
+	}
+	dss.lnmu.Unlock()
+	dss.cmu.Lock()
+	for _, c := range dss.cs {
+		c.Close()
+	}
+	dss.cmu.Unlock()
+	return nil
+}
+
+func newDualStackServer(lns []streamListener) (*dualStackServer, error) {
+	dss := &dualStackServer{lns: lns, port: "0"}
+	for i := range dss.lns {
+		ln, err := Listen(dss.lns[i].net, dss.lns[i].addr+":"+dss.port)
+		if err != nil {
+			dss.teardown()
+			return nil, err
+		}
+		dss.lns[i].ln = ln
+		if dss.port == "0" {
+			if _, dss.port, err = SplitHostPort(ln.Addr().String()); err != nil {
+				dss.teardown()
+				return nil, err
+			}
+		}
+	}
+	return dss, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/multicast_test.go b/third_party/gofrontend/libgo/go/net/multicast_test.go
new file mode 100644
index 0000000..63dbce8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/multicast_test.go
@@ -0,0 +1,188 @@
+// 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.
+
+package net
+
+import (
+	"fmt"
+	"os"
+	"runtime"
+	"testing"
+)
+
+var ipv4MulticastListenerTests = []struct {
+	net   string
+	gaddr *UDPAddr // see RFC 4727
+}{
+	{"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
+
+	{"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
+}
+
+// TestIPv4MulticastListener tests both single and double listen to a
+// test listener with same address family, same group address and same
+// port.
+func TestIPv4MulticastListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	case "solaris":
+		t.Skipf("skipping test on solaris, see issue 7399")
+	}
+
+	closer := func(cs []*UDPConn) {
+		for _, c := range cs {
+			if c != nil {
+				c.Close()
+			}
+		}
+	}
+
+	for _, ifi := range []*Interface{loopbackInterface(), nil} {
+		// Note that multicast interface assignment by system
+		// is not recommended because it usually relies on
+		// routing stuff for finding out an appropriate
+		// nexthop containing both network and link layer
+		// adjacencies.
+		if ifi == nil && !*testExternal {
+			continue
+		}
+		for _, tt := range ipv4MulticastListenerTests {
+			var err error
+			cs := make([]*UDPConn, 2)
+			if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
+				t.Fatalf("First ListenMulticastUDP on %v failed: %v", ifi, err)
+			}
+			if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
+				closer(cs)
+				t.Fatal(err)
+			}
+			if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
+				closer(cs)
+				t.Fatalf("Second ListenMulticastUDP on %v failed: %v", ifi, err)
+			}
+			if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
+				closer(cs)
+				t.Fatal(err)
+			}
+			closer(cs)
+		}
+	}
+}
+
+var ipv6MulticastListenerTests = []struct {
+	net   string
+	gaddr *UDPAddr // see RFC 4727
+}{
+	{"udp", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
+	{"udp", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
+	{"udp", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
+	{"udp", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
+	{"udp", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
+	{"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
+
+	{"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
+	{"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
+	{"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
+	{"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
+	{"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
+	{"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
+}
+
+// TestIPv6MulticastListener tests both single and double listen to a
+// test listener with same address family, same group address and same
+// port.
+func TestIPv6MulticastListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	case "solaris":
+		t.Skipf("skipping test on solaris, see issue 7399")
+	}
+	if !supportsIPv6 {
+		t.Skip("ipv6 is not supported")
+	}
+	if os.Getuid() != 0 {
+		t.Skip("skipping test; must be root")
+	}
+
+	closer := func(cs []*UDPConn) {
+		for _, c := range cs {
+			if c != nil {
+				c.Close()
+			}
+		}
+	}
+
+	for _, ifi := range []*Interface{loopbackInterface(), nil} {
+		// Note that multicast interface assignment by system
+		// is not recommended because it usually relies on
+		// routing stuff for finding out an appropriate
+		// nexthop containing both network and link layer
+		// adjacencies.
+		if ifi == nil && (!*testExternal || !*testIPv6) {
+			continue
+		}
+		for _, tt := range ipv6MulticastListenerTests {
+			var err error
+			cs := make([]*UDPConn, 2)
+			if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
+				t.Fatalf("First ListenMulticastUDP on %v failed: %v", ifi, err)
+			}
+			if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
+				closer(cs)
+				t.Fatal(err)
+			}
+			if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
+				closer(cs)
+				t.Fatalf("Second ListenMulticastUDP on %v failed: %v", ifi, err)
+			}
+			if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
+				closer(cs)
+				t.Fatal(err)
+			}
+			closer(cs)
+		}
+	}
+}
+
+func checkMulticastListener(c *UDPConn, ip IP) error {
+	if ok, err := multicastRIBContains(ip); err != nil {
+		return err
+	} else if !ok {
+		return fmt.Errorf("%q not found in multicast RIB", ip.String())
+	}
+	la := c.LocalAddr()
+	if la, ok := la.(*UDPAddr); !ok || la.Port == 0 {
+		return fmt.Errorf("got %v; expected a proper address with non-zero port number", la)
+	}
+	return nil
+}
+
+func multicastRIBContains(ip IP) (bool, error) {
+	switch runtime.GOOS {
+	case "dragonfly", "netbsd", "openbsd", "plan9", "solaris", "windows":
+		return true, nil // not implemented yet
+	case "linux":
+		if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
+			return true, nil // not implemented yet
+		}
+	}
+	ift, err := Interfaces()
+	if err != nil {
+		return false, err
+	}
+	for _, ifi := range ift {
+		ifmat, err := ifi.MulticastAddrs()
+		if err != nil {
+			return false, err
+		}
+		for _, ifma := range ifmat {
+			if ifma.(*IPAddr).IP.Equal(ip) {
+				return true, nil
+			}
+		}
+	}
+	return false, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/net.go b/third_party/gofrontend/libgo/go/net/net.go
new file mode 100644
index 0000000..ca56af5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/net.go
@@ -0,0 +1,426 @@
+// 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 net provides a portable interface for network I/O, including
+TCP/IP, UDP, domain name resolution, and Unix domain sockets.
+
+Although the package provides access to low-level networking
+primitives, most clients will need only the basic interface provided
+by the Dial, Listen, and Accept functions and the associated
+Conn and Listener interfaces. The crypto/tls package uses
+the same interfaces and similar Dial and Listen functions.
+
+The Dial function connects to a server:
+
+	conn, err := net.Dial("tcp", "google.com:80")
+	if err != nil {
+		// handle error
+	}
+	fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n")
+	status, err := bufio.NewReader(conn).ReadString('\n')
+	// ...
+
+The Listen function creates servers:
+
+	ln, err := net.Listen("tcp", ":8080")
+	if err != nil {
+		// handle error
+	}
+	for {
+		conn, err := ln.Accept()
+		if err != nil {
+			// handle error
+			continue
+		}
+		go handleConnection(conn)
+	}
+*/
+package net
+
+// TODO(rsc):
+//	support for raw ethernet sockets
+
+import (
+	"errors"
+	"io"
+	"os"
+	"syscall"
+	"time"
+)
+
+// Addr represents a network end point address.
+type Addr interface {
+	Network() string // name of the network
+	String() string  // string form of address
+}
+
+// Conn is a generic stream-oriented network connection.
+//
+// Multiple goroutines may invoke methods on a Conn simultaneously.
+type Conn interface {
+	// Read reads data from the connection.
+	// Read can be made to time out and return a Error with Timeout() == true
+	// after a fixed time limit; see SetDeadline and SetReadDeadline.
+	Read(b []byte) (n int, err error)
+
+	// Write writes data to the connection.
+	// Write can be made to time out and return a Error with Timeout() == true
+	// after a fixed time limit; see SetDeadline and SetWriteDeadline.
+	Write(b []byte) (n int, err error)
+
+	// Close closes the connection.
+	// Any blocked Read or Write operations will be unblocked and return errors.
+	Close() error
+
+	// LocalAddr returns the local network address.
+	LocalAddr() Addr
+
+	// RemoteAddr returns the remote network address.
+	RemoteAddr() Addr
+
+	// SetDeadline sets the read and write deadlines associated
+	// with the connection. It is equivalent to calling both
+	// SetReadDeadline and SetWriteDeadline.
+	//
+	// A deadline is an absolute time after which I/O operations
+	// fail with a timeout (see type Error) instead of
+	// blocking. The deadline applies to all future I/O, not just
+	// the immediately following call to Read or Write.
+	//
+	// An idle timeout can be implemented by repeatedly extending
+	// the deadline after successful Read or Write calls.
+	//
+	// A zero value for t means I/O operations will not time out.
+	SetDeadline(t time.Time) error
+
+	// SetReadDeadline sets the deadline for future Read calls.
+	// A zero value for t means Read will not time out.
+	SetReadDeadline(t time.Time) error
+
+	// SetWriteDeadline sets the deadline for future Write calls.
+	// Even if write times out, it may return n > 0, indicating that
+	// some of the data was successfully written.
+	// A zero value for t means Write will not time out.
+	SetWriteDeadline(t time.Time) error
+}
+
+type conn struct {
+	fd *netFD
+}
+
+func (c *conn) ok() bool { return c != nil && c.fd != nil }
+
+// Implementation of the Conn interface.
+
+// Read implements the Conn Read method.
+func (c *conn) Read(b []byte) (int, error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	return c.fd.Read(b)
+}
+
+// Write implements the Conn Write method.
+func (c *conn) Write(b []byte) (int, error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	return c.fd.Write(b)
+}
+
+// Close closes the connection.
+func (c *conn) Close() error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.Close()
+}
+
+// LocalAddr returns the local network address.
+func (c *conn) LocalAddr() Addr {
+	if !c.ok() {
+		return nil
+	}
+	return c.fd.laddr
+}
+
+// RemoteAddr returns the remote network address.
+func (c *conn) RemoteAddr() Addr {
+	if !c.ok() {
+		return nil
+	}
+	return c.fd.raddr
+}
+
+// SetDeadline implements the Conn SetDeadline method.
+func (c *conn) SetDeadline(t time.Time) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.setDeadline(t)
+}
+
+// SetReadDeadline implements the Conn SetReadDeadline method.
+func (c *conn) SetReadDeadline(t time.Time) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.setReadDeadline(t)
+}
+
+// SetWriteDeadline implements the Conn SetWriteDeadline method.
+func (c *conn) SetWriteDeadline(t time.Time) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.setWriteDeadline(t)
+}
+
+// SetReadBuffer sets the size of the operating system's
+// receive buffer associated with the connection.
+func (c *conn) SetReadBuffer(bytes int) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setReadBuffer(c.fd, bytes)
+}
+
+// SetWriteBuffer sets the size of the operating system's
+// transmit buffer associated with the connection.
+func (c *conn) SetWriteBuffer(bytes int) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setWriteBuffer(c.fd, bytes)
+}
+
+// File sets the underlying os.File to blocking mode and returns a copy.
+// It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+//
+// The returned os.File's file descriptor is different from the connection's.
+// Attempting to change properties of the original using this duplicate
+// may or may not have the desired effect.
+func (c *conn) File() (f *os.File, err error) { return c.fd.dup() }
+
+// An Error represents a network error.
+type Error interface {
+	error
+	Timeout() bool   // Is the error a timeout?
+	Temporary() bool // Is the error temporary?
+}
+
+// PacketConn is a generic packet-oriented network connection.
+//
+// Multiple goroutines may invoke methods on a PacketConn simultaneously.
+type PacketConn interface {
+	// ReadFrom reads a packet from the connection,
+	// copying the payload into b.  It returns the number of
+	// bytes copied into b and the return address that
+	// was on the packet.
+	// ReadFrom can be made to time out and return
+	// an error with Timeout() == true after a fixed time limit;
+	// see SetDeadline and SetReadDeadline.
+	ReadFrom(b []byte) (n int, addr Addr, err error)
+
+	// WriteTo writes a packet with payload b to addr.
+	// WriteTo can be made to time out and return
+	// an error with Timeout() == true after a fixed time limit;
+	// see SetDeadline and SetWriteDeadline.
+	// On packet-oriented connections, write timeouts are rare.
+	WriteTo(b []byte, addr Addr) (n int, err error)
+
+	// Close closes the connection.
+	// Any blocked ReadFrom or WriteTo operations will be unblocked and return errors.
+	Close() error
+
+	// LocalAddr returns the local network address.
+	LocalAddr() Addr
+
+	// SetDeadline sets the read and write deadlines associated
+	// with the connection.
+	SetDeadline(t time.Time) error
+
+	// SetReadDeadline sets the deadline for future Read calls.
+	// If the deadline is reached, Read will fail with a timeout
+	// (see type Error) instead of blocking.
+	// A zero value for t means Read will not time out.
+	SetReadDeadline(t time.Time) error
+
+	// SetWriteDeadline sets the deadline for future Write calls.
+	// If the deadline is reached, Write will fail with a timeout
+	// (see type Error) instead of blocking.
+	// A zero value for t means Write will not time out.
+	// Even if write times out, it may return n > 0, indicating that
+	// some of the data was successfully written.
+	SetWriteDeadline(t time.Time) error
+}
+
+var listenerBacklog = maxListenerBacklog()
+
+// A Listener is a generic network listener for stream-oriented protocols.
+//
+// Multiple goroutines may invoke methods on a Listener simultaneously.
+type Listener interface {
+	// Accept waits for and returns the next connection to the listener.
+	Accept() (c Conn, err error)
+
+	// Close closes the listener.
+	// Any blocked Accept operations will be unblocked and return errors.
+	Close() error
+
+	// Addr returns the listener's network address.
+	Addr() Addr
+}
+
+// Various errors contained in OpError.
+var (
+	// For connection setup and write operations.
+	errMissingAddress = errors.New("missing address")
+
+	// For both read and write operations.
+	errTimeout          error = &timeoutError{}
+	errClosing                = errors.New("use of closed network connection")
+	ErrWriteToConnected       = errors.New("use of WriteTo with pre-connected connection")
+)
+
+// OpError is the error type usually returned by functions in the net
+// package. It describes the operation, network type, and address of
+// an error.
+type OpError struct {
+	// Op is the operation which caused the error, such as
+	// "read" or "write".
+	Op string
+
+	// Net is the network type on which this error occurred,
+	// such as "tcp" or "udp6".
+	Net string
+
+	// Addr is the network address on which this error occurred.
+	Addr Addr
+
+	// Err is the error that occurred during the operation.
+	Err error
+}
+
+func (e *OpError) Error() string {
+	if e == nil {
+		return "<nil>"
+	}
+	s := e.Op
+	if e.Net != "" {
+		s += " " + e.Net
+	}
+	if e.Addr != nil {
+		s += " " + e.Addr.String()
+	}
+	s += ": " + e.Err.Error()
+	return s
+}
+
+type temporary interface {
+	Temporary() bool
+}
+
+func (e *OpError) Temporary() bool {
+	t, ok := e.Err.(temporary)
+	return ok && t.Temporary()
+}
+
+var noDeadline = time.Time{}
+
+type timeout interface {
+	Timeout() bool
+}
+
+func (e *OpError) Timeout() bool {
+	t, ok := e.Err.(timeout)
+	return ok && t.Timeout()
+}
+
+type timeoutError struct{}
+
+func (e *timeoutError) Error() string   { return "i/o timeout" }
+func (e *timeoutError) Timeout() bool   { return true }
+func (e *timeoutError) Temporary() bool { return true }
+
+type AddrError struct {
+	Err  string
+	Addr string
+}
+
+func (e *AddrError) Error() string {
+	if e == nil {
+		return "<nil>"
+	}
+	s := e.Err
+	if e.Addr != "" {
+		s += " " + e.Addr
+	}
+	return s
+}
+
+func (e *AddrError) Temporary() bool {
+	return false
+}
+
+func (e *AddrError) Timeout() bool {
+	return false
+}
+
+type UnknownNetworkError string
+
+func (e UnknownNetworkError) Error() string   { return "unknown network " + string(e) }
+func (e UnknownNetworkError) Temporary() bool { return false }
+func (e UnknownNetworkError) Timeout() bool   { return false }
+
+type InvalidAddrError string
+
+func (e InvalidAddrError) Error() string   { return string(e) }
+func (e InvalidAddrError) Timeout() bool   { return false }
+func (e InvalidAddrError) Temporary() bool { return false }
+
+// DNSConfigError represents an error reading the machine's DNS configuration.
+type DNSConfigError struct {
+	Err error
+}
+
+func (e *DNSConfigError) Error() string {
+	return "error reading DNS config: " + e.Err.Error()
+}
+
+func (e *DNSConfigError) Timeout() bool   { return false }
+func (e *DNSConfigError) Temporary() bool { return false }
+
+type writerOnly struct {
+	io.Writer
+}
+
+// Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
+// applicable.
+func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) {
+	// Use wrapper to hide existing r.ReadFrom from io.Copy.
+	return io.Copy(writerOnly{w}, r)
+}
+
+// Limit the number of concurrent cgo-using goroutines, because
+// each will block an entire operating system thread. The usual culprit
+// is resolving many DNS names in separate goroutines but the DNS
+// server is not responding. Then the many lookups each use a different
+// thread, and the system or the program runs out of threads.
+
+var threadLimit = make(chan struct{}, 500)
+
+// Using send for acquire is fine here because we are not using this
+// to protect any memory. All we care about is the number of goroutines
+// making calls at a time.
+
+func acquireThread() {
+	threadLimit <- struct{}{}
+}
+
+func releaseThread() {
+	<-threadLimit
+}
diff --git a/third_party/gofrontend/libgo/go/net/net_test.go b/third_party/gofrontend/libgo/go/net/net_test.go
new file mode 100644
index 0000000..bfed4d6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/net_test.go
@@ -0,0 +1,263 @@
+// 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 net
+
+import (
+	"io"
+	"io/ioutil"
+	"os"
+	"runtime"
+	"testing"
+	"time"
+)
+
+func TestShutdown(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		if ln, err = Listen("tcp6", "[::1]:0"); err != nil {
+			t.Fatalf("ListenTCP on :0: %v", err)
+		}
+	}
+
+	go func() {
+		defer ln.Close()
+		c, err := ln.Accept()
+		if err != nil {
+			t.Errorf("Accept: %v", err)
+			return
+		}
+		var buf [10]byte
+		n, err := c.Read(buf[:])
+		if n != 0 || err != io.EOF {
+			t.Errorf("server Read = %d, %v; want 0, io.EOF", n, err)
+			return
+		}
+		c.Write([]byte("response"))
+		c.Close()
+	}()
+
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+
+	err = c.(*TCPConn).CloseWrite()
+	if err != nil {
+		t.Fatalf("CloseWrite: %v", err)
+	}
+	var buf [10]byte
+	n, err := c.Read(buf[:])
+	if err != nil {
+		t.Fatalf("client Read: %d, %v", n, err)
+	}
+	got := string(buf[:n])
+	if got != "response" {
+		t.Errorf("read = %q, want \"response\"", got)
+	}
+}
+
+func TestShutdownUnix(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	f, err := ioutil.TempFile("", "go_net_unixtest")
+	if err != nil {
+		t.Fatalf("TempFile: %s", err)
+	}
+	f.Close()
+	tmpname := f.Name()
+	os.Remove(tmpname)
+	ln, err := Listen("unix", tmpname)
+	if err != nil {
+		t.Fatalf("ListenUnix on %s: %s", tmpname, err)
+	}
+	defer func() {
+		ln.Close()
+		os.Remove(tmpname)
+	}()
+
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Errorf("Accept: %v", err)
+			return
+		}
+		var buf [10]byte
+		n, err := c.Read(buf[:])
+		if n != 0 || err != io.EOF {
+			t.Errorf("server Read = %d, %v; want 0, io.EOF", n, err)
+			return
+		}
+		c.Write([]byte("response"))
+		c.Close()
+	}()
+
+	c, err := Dial("unix", tmpname)
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+
+	err = c.(*UnixConn).CloseWrite()
+	if err != nil {
+		t.Fatalf("CloseWrite: %v", err)
+	}
+	var buf [10]byte
+	n, err := c.Read(buf[:])
+	if err != nil {
+		t.Fatalf("client Read: %d, %v", n, err)
+	}
+	got := string(buf[:n])
+	if got != "response" {
+		t.Errorf("read = %q, want \"response\"", got)
+	}
+}
+
+func TestTCPListenClose(t *testing.T) {
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+	}
+
+	done := make(chan bool, 1)
+	go func() {
+		time.Sleep(100 * time.Millisecond)
+		ln.Close()
+	}()
+	go func() {
+		c, err := ln.Accept()
+		if err == nil {
+			c.Close()
+			t.Error("Accept succeeded")
+		} else {
+			t.Logf("Accept timeout error: %s (any error is fine)", err)
+		}
+		done <- true
+	}()
+	select {
+	case <-done:
+	case <-time.After(2 * time.Second):
+		t.Fatal("timeout waiting for TCP close")
+	}
+}
+
+func TestUDPListenClose(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	ln, err := ListenPacket("udp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+	}
+
+	buf := make([]byte, 1000)
+	done := make(chan bool, 1)
+	go func() {
+		time.Sleep(100 * time.Millisecond)
+		ln.Close()
+	}()
+	go func() {
+		_, _, err = ln.ReadFrom(buf)
+		if err == nil {
+			t.Error("ReadFrom succeeded")
+		} else {
+			t.Logf("ReadFrom timeout error: %s (any error is fine)", err)
+		}
+		done <- true
+	}()
+	select {
+	case <-done:
+	case <-time.After(2 * time.Second):
+		t.Fatal("timeout waiting for UDP close")
+	}
+}
+
+func TestTCPClose(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	l, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer l.Close()
+
+	read := func(r io.Reader) error {
+		var m [1]byte
+		_, err := r.Read(m[:])
+		return err
+	}
+
+	go func() {
+		c, err := Dial("tcp", l.Addr().String())
+		if err != nil {
+			t.Errorf("Dial: %v", err)
+			return
+		}
+
+		go read(c)
+
+		time.Sleep(10 * time.Millisecond)
+		c.Close()
+	}()
+
+	c, err := l.Accept()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer c.Close()
+
+	for err == nil {
+		err = read(c)
+	}
+	if err != nil && err != io.EOF {
+		t.Fatal(err)
+	}
+}
+
+func TestErrorNil(t *testing.T) {
+	c, err := Dial("tcp", "127.0.0.1:65535")
+	if err == nil {
+		t.Fatal("Dial 127.0.0.1:65535 succeeded")
+	}
+	if c != nil {
+		t.Fatalf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
+	}
+
+	// Make Listen fail by relistening on the same address.
+	l, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen 127.0.0.1:0: %v", err)
+	}
+	defer l.Close()
+	l1, err := Listen("tcp", l.Addr().String())
+	if err == nil {
+		t.Fatalf("second Listen %v: %v", l.Addr(), err)
+	}
+	if l1 != nil {
+		t.Fatalf("Listen returned non-nil interface %T(%v) with err != nil", l1, l1)
+	}
+
+	// Make ListenPacket fail by relistening on the same address.
+	lp, err := ListenPacket("udp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen 127.0.0.1:0: %v", err)
+	}
+	defer lp.Close()
+	lp1, err := ListenPacket("udp", lp.LocalAddr().String())
+	if err == nil {
+		t.Fatalf("second Listen %v: %v", lp.LocalAddr(), err)
+	}
+	if lp1 != nil {
+		t.Fatalf("ListenPacket returned non-nil interface %T(%v) with err != nil", lp1, lp1)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/newpollserver_rtems.go b/third_party/gofrontend/libgo/go/net/newpollserver_rtems.go
new file mode 100644
index 0000000..410f932
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/newpollserver_rtems.go
@@ -0,0 +1,78 @@
+// Copyright 2010 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 net
+
+import (
+	"os"
+	"syscall"
+)
+
+func selfConnectedTCPSocket() (pr, pw *os.File, err error) {
+	// See ../syscall/exec.go for description of ForkLock.
+	syscall.ForkLock.RLock()
+	sockfd, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)
+	if e != 0 {
+		syscall.ForkLock.RUnlock()
+		return nil, nil, os.Errno(e)
+	}
+	syscall.CloseOnExec(sockfd)
+	syscall.ForkLock.RUnlock()
+
+	// Allow reuse of recently-used addresses.
+	syscall.SetsockoptInt(sockfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+
+	var laTCP *TCPAddr
+	var la syscall.Sockaddr
+	if laTCP, err = ResolveTCPAddr("127.0.0.1:0"); err != nil {
+	Error:
+		return nil, nil, err
+	}
+	if la, err = laTCP.sockaddr(syscall.AF_INET); err != nil {
+		goto Error
+	}
+	e = syscall.Bind(sockfd, la)
+	if e != 0 {
+	Errno:
+		syscall.Close(sockfd)
+		return nil, nil, os.Errno(e)
+	}
+
+	laddr, _ := syscall.Getsockname(sockfd)
+	e = syscall.Connect(sockfd, laddr)
+	if e != 0 {
+		goto Errno
+	}
+
+	fd := os.NewFile(sockfd, "wakeupSocket")
+	return fd, fd, nil
+}
+
+func newPollServer() (s *pollServer, err error) {
+	s = new(pollServer)
+	s.cr = make(chan *netFD, 1)
+	s.cw = make(chan *netFD, 1)
+	// s.pr and s.pw are indistinguishable.
+	if s.pr, s.pw, err = selfConnectedTCPSocket(); err != nil {
+		return nil, err
+	}
+	var e int
+	if e = syscall.SetNonblock(s.pr.Fd(), true); e != 0 {
+	Errno:
+		err = &os.PathError{"setnonblock", s.pr.Name(), os.Errno(e)}
+	Error:
+		s.pr.Close()
+		return nil, err
+	}
+	if s.poll, err = newpollster(); err != nil {
+		goto Error
+	}
+	if _, err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
+		s.poll.Close()
+		goto Error
+	}
+	s.pending = make(map[int]*netFD)
+	go s.Run()
+	return s, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/packetconn_test.go b/third_party/gofrontend/libgo/go/net/packetconn_test.go
new file mode 100644
index 0000000..b6e4e76
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/packetconn_test.go
@@ -0,0 +1,186 @@
+// 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.
+
+// This file implements API tests across platforms and will never have a build
+// tag.
+
+package net
+
+import (
+	"os"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+func packetConnTestData(t *testing.T, net string, i int) ([]byte, func()) {
+	switch net {
+	case "udp":
+		return []byte("UDP PACKETCONN TEST"), nil
+	case "ip":
+		if skip, skipmsg := skipRawSocketTest(t); skip {
+			return nil, func() {
+				t.Logf(skipmsg)
+			}
+		}
+		b, err := (&icmpMessage{
+			Type: icmpv4EchoRequest, Code: 0,
+			Body: &icmpEcho{
+				ID: os.Getpid() & 0xffff, Seq: i + 1,
+				Data: []byte("IP PACKETCONN TEST"),
+			},
+		}).Marshal()
+		if err != nil {
+			return nil, func() {
+				t.Fatalf("icmpMessage.Marshal failed: %v", err)
+			}
+		}
+		return b, nil
+	case "unixgram":
+		switch runtime.GOOS {
+		case "nacl", "plan9", "windows":
+			return nil, func() {
+				t.Logf("skipping %q test on %q", net, runtime.GOOS)
+			}
+		default:
+			return []byte("UNIXGRAM PACKETCONN TEST"), nil
+		}
+	default:
+		return nil, func() {
+			t.Logf("skipping %q test", net)
+		}
+	}
+}
+
+var packetConnTests = []struct {
+	net   string
+	addr1 string
+	addr2 string
+}{
+	{"udp", "127.0.0.1:0", "127.0.0.1:0"},
+	{"ip:icmp", "127.0.0.1", "127.0.0.1"},
+	{"unixgram", testUnixAddr(), testUnixAddr()},
+}
+
+func TestPacketConn(t *testing.T) {
+	closer := func(c PacketConn, net, addr1, addr2 string) {
+		c.Close()
+		switch net {
+		case "unixgram":
+			os.Remove(addr1)
+			os.Remove(addr2)
+		}
+	}
+
+	for i, tt := range packetConnTests {
+		netstr := strings.Split(tt.net, ":")
+		wb, skipOrFatalFn := packetConnTestData(t, netstr[0], i)
+		if skipOrFatalFn != nil {
+			skipOrFatalFn()
+			continue
+		}
+
+		c1, err := ListenPacket(tt.net, tt.addr1)
+		if err != nil {
+			t.Fatalf("ListenPacket failed: %v", err)
+		}
+		defer closer(c1, netstr[0], tt.addr1, tt.addr2)
+		c1.LocalAddr()
+		c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+
+		c2, err := ListenPacket(tt.net, tt.addr2)
+		if err != nil {
+			t.Fatalf("ListenPacket failed: %v", err)
+		}
+		defer closer(c2, netstr[0], tt.addr1, tt.addr2)
+		c2.LocalAddr()
+		c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+
+		if _, err := c1.WriteTo(wb, c2.LocalAddr()); err != nil {
+			t.Fatalf("PacketConn.WriteTo failed: %v", err)
+		}
+		rb2 := make([]byte, 128)
+		if _, _, err := c2.ReadFrom(rb2); err != nil {
+			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
+		}
+		if _, err := c2.WriteTo(wb, c1.LocalAddr()); err != nil {
+			t.Fatalf("PacketConn.WriteTo failed: %v", err)
+		}
+		rb1 := make([]byte, 128)
+		if _, _, err := c1.ReadFrom(rb1); err != nil {
+			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
+		}
+	}
+}
+
+func TestConnAndPacketConn(t *testing.T) {
+	closer := func(c PacketConn, net, addr1, addr2 string) {
+		c.Close()
+		switch net {
+		case "unixgram":
+			os.Remove(addr1)
+			os.Remove(addr2)
+		}
+	}
+
+	for i, tt := range packetConnTests {
+		var wb []byte
+		netstr := strings.Split(tt.net, ":")
+		wb, skipOrFatalFn := packetConnTestData(t, netstr[0], i)
+		if skipOrFatalFn != nil {
+			skipOrFatalFn()
+			continue
+		}
+
+		c1, err := ListenPacket(tt.net, tt.addr1)
+		if err != nil {
+			t.Fatalf("ListenPacket failed: %v", err)
+		}
+		defer closer(c1, netstr[0], tt.addr1, tt.addr2)
+		c1.LocalAddr()
+		c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+
+		c2, err := Dial(tt.net, c1.LocalAddr().String())
+		if err != nil {
+			t.Fatalf("Dial failed: %v", err)
+		}
+		defer c2.Close()
+		c2.LocalAddr()
+		c2.RemoteAddr()
+		c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+
+		if _, err := c2.Write(wb); err != nil {
+			t.Fatalf("Conn.Write failed: %v", err)
+		}
+		rb1 := make([]byte, 128)
+		if _, _, err := c1.ReadFrom(rb1); err != nil {
+			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
+		}
+		var dst Addr
+		switch netstr[0] {
+		case "ip":
+			dst = &IPAddr{IP: IPv4(127, 0, 0, 1)}
+		case "unixgram":
+			continue
+		default:
+			dst = c2.LocalAddr()
+		}
+		if _, err := c1.WriteTo(wb, dst); err != nil {
+			t.Fatalf("PacketConn.WriteTo failed: %v", err)
+		}
+		rb2 := make([]byte, 128)
+		if _, err := c2.Read(rb2); err != nil {
+			t.Fatalf("Conn.Read failed: %v", err)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/parse.go b/third_party/gofrontend/libgo/go/net/parse.go
new file mode 100644
index 0000000..ee6e7e9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/parse.go
@@ -0,0 +1,247 @@
+// 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.
+
+// Simple file i/o and string manipulation, to avoid
+// depending on strconv and bufio and strings.
+
+package net
+
+import (
+	"io"
+	"os"
+)
+
+type file struct {
+	file  *os.File
+	data  []byte
+	atEOF bool
+}
+
+func (f *file) close() { f.file.Close() }
+
+func (f *file) getLineFromData() (s string, ok bool) {
+	data := f.data
+	i := 0
+	for i = 0; i < len(data); i++ {
+		if data[i] == '\n' {
+			s = string(data[0:i])
+			ok = true
+			// move data
+			i++
+			n := len(data) - i
+			copy(data[0:], data[i:])
+			f.data = data[0:n]
+			return
+		}
+	}
+	if f.atEOF && len(f.data) > 0 {
+		// EOF, return all we have
+		s = string(data)
+		f.data = f.data[0:0]
+		ok = true
+	}
+	return
+}
+
+func (f *file) readLine() (s string, ok bool) {
+	if s, ok = f.getLineFromData(); ok {
+		return
+	}
+	if len(f.data) < cap(f.data) {
+		ln := len(f.data)
+		n, err := io.ReadFull(f.file, f.data[ln:cap(f.data)])
+		if n >= 0 {
+			f.data = f.data[0 : ln+n]
+		}
+		if err == io.EOF || err == io.ErrUnexpectedEOF {
+			f.atEOF = true
+		}
+	}
+	s, ok = f.getLineFromData()
+	return
+}
+
+func open(name string) (*file, error) {
+	fd, err := os.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	return &file{fd, make([]byte, 0, os.Getpagesize()), false}, nil
+}
+
+func byteIndex(s string, c byte) int {
+	for i := 0; i < len(s); i++ {
+		if s[i] == c {
+			return i
+		}
+	}
+	return -1
+}
+
+// Count occurrences in s of any bytes in t.
+func countAnyByte(s string, t string) int {
+	n := 0
+	for i := 0; i < len(s); i++ {
+		if byteIndex(t, s[i]) >= 0 {
+			n++
+		}
+	}
+	return n
+}
+
+// Split s at any bytes in t.
+func splitAtBytes(s string, t string) []string {
+	a := make([]string, 1+countAnyByte(s, t))
+	n := 0
+	last := 0
+	for i := 0; i < len(s); i++ {
+		if byteIndex(t, s[i]) >= 0 {
+			if last < i {
+				a[n] = string(s[last:i])
+				n++
+			}
+			last = i + 1
+		}
+	}
+	if last < len(s) {
+		a[n] = string(s[last:])
+		n++
+	}
+	return a[0:n]
+}
+
+func getFields(s string) []string { return splitAtBytes(s, " \r\t\n") }
+
+// Bigger than we need, not too big to worry about overflow
+const big = 0xFFFFFF
+
+// Decimal to integer starting at &s[i0].
+// Returns number, new offset, success.
+func dtoi(s string, i0 int) (n int, i int, ok bool) {
+	n = 0
+	for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
+		n = n*10 + int(s[i]-'0')
+		if n >= big {
+			return 0, i, false
+		}
+	}
+	if i == i0 {
+		return 0, i, false
+	}
+	return n, i, true
+}
+
+// Hexadecimal to integer starting at &s[i0].
+// Returns number, new offset, success.
+func xtoi(s string, i0 int) (n int, i int, ok bool) {
+	n = 0
+	for i = i0; i < len(s); i++ {
+		if '0' <= s[i] && s[i] <= '9' {
+			n *= 16
+			n += int(s[i] - '0')
+		} else if 'a' <= s[i] && s[i] <= 'f' {
+			n *= 16
+			n += int(s[i]-'a') + 10
+		} else if 'A' <= s[i] && s[i] <= 'F' {
+			n *= 16
+			n += int(s[i]-'A') + 10
+		} else {
+			break
+		}
+		if n >= big {
+			return 0, i, false
+		}
+	}
+	if i == i0 {
+		return 0, i, false
+	}
+	return n, i, true
+}
+
+// xtoi2 converts the next two hex digits of s into a byte.
+// If s is longer than 2 bytes then the third byte must be e.
+// If the first two bytes of s are not hex digits or the third byte
+// does not match e, false is returned.
+func xtoi2(s string, e byte) (byte, bool) {
+	if len(s) > 2 && s[2] != e {
+		return 0, false
+	}
+	n, ei, ok := xtoi(s[:2], 0)
+	return byte(n), ok && ei == 2
+}
+
+// Integer to decimal.
+func itoa(i int) string {
+	var buf [30]byte
+	n := len(buf)
+	neg := false
+	if i < 0 {
+		i = -i
+		neg = true
+	}
+	ui := uint(i)
+	for ui > 0 || n == len(buf) {
+		n--
+		buf[n] = byte('0' + ui%10)
+		ui /= 10
+	}
+	if neg {
+		n--
+		buf[n] = '-'
+	}
+	return string(buf[n:])
+}
+
+// Convert i to decimal string.
+func itod(i uint) string {
+	if i == 0 {
+		return "0"
+	}
+
+	// Assemble decimal in reverse order.
+	var b [32]byte
+	bp := len(b)
+	for ; i > 0; i /= 10 {
+		bp--
+		b[bp] = byte(i%10) + '0'
+	}
+
+	return string(b[bp:])
+}
+
+// Convert i to hexadecimal string.
+func itox(i uint, min int) string {
+	// Assemble hexadecimal in reverse order.
+	var b [32]byte
+	bp := len(b)
+	for ; i > 0 || min > 0; i /= 16 {
+		bp--
+		b[bp] = "0123456789abcdef"[byte(i%16)]
+		min--
+	}
+
+	return string(b[bp:])
+}
+
+// Number of occurrences of b in s.
+func count(s string, b byte) int {
+	n := 0
+	for i := 0; i < len(s); i++ {
+		if s[i] == b {
+			n++
+		}
+	}
+	return n
+}
+
+// Index of rightmost occurrence of b in s.
+func last(s string, b byte) int {
+	i := len(s)
+	for i--; i >= 0; i-- {
+		if s[i] == b {
+			break
+		}
+	}
+	return i
+}
diff --git a/third_party/gofrontend/libgo/go/net/parse_test.go b/third_party/gofrontend/libgo/go/net/parse_test.go
new file mode 100644
index 0000000..b86bc32
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/parse_test.go
@@ -0,0 +1,53 @@
+// 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 net
+
+import (
+	"bufio"
+	"os"
+	"runtime"
+	"testing"
+)
+
+func TestReadLine(t *testing.T) {
+	// /etc/services file does not exist on windows and Plan 9.
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	filename := "/etc/services" // a nice big file
+
+	fd, err := os.Open(filename)
+	if err != nil {
+		t.Fatalf("open %s: %v", filename, err)
+	}
+	defer fd.Close()
+	br := bufio.NewReader(fd)
+
+	file, err := open(filename)
+	if file == nil {
+		t.Fatalf("net.open(%s) = nil", filename)
+	}
+	defer file.close()
+
+	lineno := 1
+	byteno := 0
+	for {
+		bline, berr := br.ReadString('\n')
+		if n := len(bline); n > 0 {
+			bline = bline[0 : n-1]
+		}
+		line, ok := file.readLine()
+		if (berr != nil) != !ok || bline != line {
+			t.Fatalf("%s:%d (#%d)\nbufio => %q, %v\nnet => %q, %v",
+				filename, lineno, byteno, bline, berr, line, ok)
+		}
+		if !ok {
+			break
+		}
+		lineno++
+		byteno += len(line) + 1
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/pipe.go b/third_party/gofrontend/libgo/go/net/pipe.go
new file mode 100644
index 0000000..f1a2eca
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/pipe.go
@@ -0,0 +1,67 @@
+// Copyright 2010 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 net
+
+import (
+	"errors"
+	"io"
+	"time"
+)
+
+// Pipe creates a synchronous, in-memory, full duplex
+// network connection; both ends implement the Conn interface.
+// Reads on one end are matched with writes on the other,
+// copying data directly between the two; there is no internal
+// buffering.
+func Pipe() (Conn, Conn) {
+	r1, w1 := io.Pipe()
+	r2, w2 := io.Pipe()
+
+	return &pipe{r1, w2}, &pipe{r2, w1}
+}
+
+type pipe struct {
+	*io.PipeReader
+	*io.PipeWriter
+}
+
+type pipeAddr int
+
+func (pipeAddr) Network() string {
+	return "pipe"
+}
+
+func (pipeAddr) String() string {
+	return "pipe"
+}
+
+func (p *pipe) Close() error {
+	err := p.PipeReader.Close()
+	err1 := p.PipeWriter.Close()
+	if err == nil {
+		err = err1
+	}
+	return err
+}
+
+func (p *pipe) LocalAddr() Addr {
+	return pipeAddr(0)
+}
+
+func (p *pipe) RemoteAddr() Addr {
+	return pipeAddr(0)
+}
+
+func (p *pipe) SetDeadline(t time.Time) error {
+	return errors.New("net.Pipe does not support deadlines")
+}
+
+func (p *pipe) SetReadDeadline(t time.Time) error {
+	return errors.New("net.Pipe does not support deadlines")
+}
+
+func (p *pipe) SetWriteDeadline(t time.Time) error {
+	return errors.New("net.Pipe does not support deadlines")
+}
diff --git a/third_party/gofrontend/libgo/go/net/pipe_test.go b/third_party/gofrontend/libgo/go/net/pipe_test.go
new file mode 100644
index 0000000..afe4f24
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/pipe_test.go
@@ -0,0 +1,56 @@
+// Copyright 2010 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 net
+
+import (
+	"bytes"
+	"io"
+	"testing"
+)
+
+func checkWrite(t *testing.T, w io.Writer, data []byte, c chan int) {
+	n, err := w.Write(data)
+	if err != nil {
+		t.Errorf("write: %v", err)
+	}
+	if n != len(data) {
+		t.Errorf("short write: %d != %d", n, len(data))
+	}
+	c <- 0
+}
+
+func checkRead(t *testing.T, r io.Reader, data []byte, wantErr error) {
+	buf := make([]byte, len(data)+10)
+	n, err := r.Read(buf)
+	if err != wantErr {
+		t.Errorf("read: %v", err)
+		return
+	}
+	if n != len(data) || !bytes.Equal(buf[0:n], data) {
+		t.Errorf("bad read: got %q", buf[0:n])
+		return
+	}
+}
+
+// Test a simple read/write/close sequence.
+// Assumes that the underlying io.Pipe implementation
+// is solid and we're just testing the net wrapping.
+
+func TestPipe(t *testing.T) {
+	c := make(chan int)
+	cli, srv := Pipe()
+	go checkWrite(t, cli, []byte("hello, world"), c)
+	checkRead(t, srv, []byte("hello, world"), nil)
+	<-c
+	go checkWrite(t, srv, []byte("line 2"), c)
+	checkRead(t, cli, []byte("line 2"), nil)
+	<-c
+	go checkWrite(t, cli, []byte("a third line"), c)
+	checkRead(t, srv, []byte("a third line"), nil)
+	<-c
+	go srv.Close()
+	checkRead(t, cli, nil, io.EOF)
+	cli.Close()
+}
diff --git a/third_party/gofrontend/libgo/go/net/port.go b/third_party/gofrontend/libgo/go/net/port.go
new file mode 100644
index 0000000..c24f4ed
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/port.go
@@ -0,0 +1,24 @@
+// 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.
+
+// Network service port manipulations
+
+package net
+
+// parsePort parses port as a network service port number for both
+// TCP and UDP.
+func parsePort(net, port string) (int, error) {
+	p, i, ok := dtoi(port, 0)
+	if !ok || i != len(port) {
+		var err error
+		p, err = LookupPort(net, port)
+		if err != nil {
+			return 0, err
+		}
+	}
+	if p < 0 || p > 0xFFFF {
+		return 0, &AddrError{"invalid port", port}
+	}
+	return p, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/port_test.go b/third_party/gofrontend/libgo/go/net/port_test.go
new file mode 100644
index 0000000..9e8968f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/port_test.go
@@ -0,0 +1,53 @@
+// 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 net
+
+import (
+	"testing"
+)
+
+type portTest struct {
+	netw string
+	name string
+	port int
+	ok   bool
+}
+
+var porttests = []portTest{
+	{"tcp", "echo", 7, true},
+	{"tcp", "discard", 9, true},
+	{"tcp", "systat", 11, true},
+	{"tcp", "daytime", 13, true},
+	{"tcp", "chargen", 19, true},
+	{"tcp", "ftp-data", 20, true},
+	{"tcp", "ftp", 21, true},
+	{"tcp", "telnet", 23, true},
+	{"tcp", "smtp", 25, true},
+	{"tcp", "time", 37, true},
+	{"tcp", "domain", 53, true},
+	{"tcp", "finger", 79, true},
+
+	{"udp", "echo", 7, true},
+	{"udp", "tftp", 69, true},
+	{"udp", "bootpc", 68, true},
+	{"udp", "bootps", 67, true},
+	{"udp", "domain", 53, true},
+	{"udp", "ntp", 123, true},
+	{"udp", "snmp", 161, true},
+	{"udp", "syslog", 514, true},
+
+	{"--badnet--", "zzz", 0, false},
+	{"tcp", "--badport--", 0, false},
+}
+
+func TestLookupPort(t *testing.T) {
+	for i := 0; i < len(porttests); i++ {
+		tt := porttests[i]
+		if port, err := LookupPort(tt.netw, tt.name); port != tt.port || (err == nil) != tt.ok {
+			t.Errorf("LookupPort(%q, %q) = %v, %v; want %v",
+				tt.netw, tt.name, port, err, tt.port)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/port_unix.go b/third_party/gofrontend/libgo/go/net/port_unix.go
new file mode 100644
index 0000000..89558c1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/port_unix.go
@@ -0,0 +1,73 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+// Read system port mappings from /etc/services
+
+package net
+
+import "sync"
+
+// services contains minimal mappings between services names and port
+// numbers for platforms that don't have a complete list of port numbers
+// (some Solaris distros).
+var services = map[string]map[string]int{
+	"tcp": {"http": 80},
+}
+var servicesError error
+var onceReadServices sync.Once
+
+func readServices() {
+	var file *file
+	if file, servicesError = open("/etc/services"); servicesError != nil {
+		return
+	}
+	for line, ok := file.readLine(); ok; line, ok = file.readLine() {
+		// "http 80/tcp www www-http # World Wide Web HTTP"
+		if i := byteIndex(line, '#'); i >= 0 {
+			line = line[0:i]
+		}
+		f := getFields(line)
+		if len(f) < 2 {
+			continue
+		}
+		portnet := f[1] // "80/tcp"
+		port, j, ok := dtoi(portnet, 0)
+		if !ok || port <= 0 || j >= len(portnet) || portnet[j] != '/' {
+			continue
+		}
+		netw := portnet[j+1:] // "tcp"
+		m, ok1 := services[netw]
+		if !ok1 {
+			m = make(map[string]int)
+			services[netw] = m
+		}
+		for i := 0; i < len(f); i++ {
+			if i != 1 { // f[1] was port/net
+				m[f[i]] = port
+			}
+		}
+	}
+	file.close()
+}
+
+// goLookupPort is the native Go implementation of LookupPort.
+func goLookupPort(network, service string) (port int, err error) {
+	onceReadServices.Do(readServices)
+
+	switch network {
+	case "tcp4", "tcp6":
+		network = "tcp"
+	case "udp4", "udp6":
+		network = "udp"
+	}
+
+	if m, ok := services[network]; ok {
+		if port, ok = m[service]; ok {
+			return
+		}
+	}
+	return 0, &AddrError{"unknown port", network + "/" + service}
+}
diff --git a/third_party/gofrontend/libgo/go/net/protoconn_test.go b/third_party/gofrontend/libgo/go/net/protoconn_test.go
new file mode 100644
index 0000000..12856b6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/protoconn_test.go
@@ -0,0 +1,386 @@
+// 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.
+
+// This file implements API tests across platforms and will never have a build
+// tag.
+
+package net
+
+import (
+	"io/ioutil"
+	"os"
+	"runtime"
+	"testing"
+	"time"
+)
+
+// testUnixAddr uses ioutil.TempFile to get a name that is unique. It
+// also uses /tmp directory in case it is prohibited to create UNIX
+// sockets in TMPDIR.
+func testUnixAddr() string {
+	f, err := ioutil.TempFile("", "nettest")
+	if err != nil {
+		panic(err)
+	}
+	addr := f.Name()
+	f.Close()
+	os.Remove(addr)
+	return addr
+}
+
+var condFatalf = func() func(*testing.T, string, ...interface{}) {
+	// A few APIs are not implemented yet on both Plan 9 and Windows.
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		return (*testing.T).Logf
+	}
+	return (*testing.T).Fatalf
+}()
+
+func TestTCPListenerSpecificMethods(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	la, err := ResolveTCPAddr("tcp4", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ResolveTCPAddr failed: %v", err)
+	}
+	ln, err := ListenTCP("tcp4", la)
+	if err != nil {
+		t.Fatalf("ListenTCP failed: %v", err)
+	}
+	defer ln.Close()
+	ln.Addr()
+	ln.SetDeadline(time.Now().Add(30 * time.Nanosecond))
+
+	if c, err := ln.Accept(); err != nil {
+		if !err.(Error).Timeout() {
+			t.Fatalf("TCPListener.Accept failed: %v", err)
+		}
+	} else {
+		c.Close()
+	}
+	if c, err := ln.AcceptTCP(); err != nil {
+		if !err.(Error).Timeout() {
+			t.Fatalf("TCPListener.AcceptTCP failed: %v", err)
+		}
+	} else {
+		c.Close()
+	}
+
+	if f, err := ln.File(); err != nil {
+		condFatalf(t, "TCPListener.File failed: %v", err)
+	} else {
+		f.Close()
+	}
+}
+
+func TestTCPConnSpecificMethods(t *testing.T) {
+	la, err := ResolveTCPAddr("tcp4", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ResolveTCPAddr failed: %v", err)
+	}
+	ln, err := ListenTCP("tcp4", la)
+	if err != nil {
+		t.Fatalf("ListenTCP failed: %v", err)
+	}
+	defer ln.Close()
+	ln.Addr()
+
+	done := make(chan int)
+	go transponder(t, ln, done)
+
+	ra, err := ResolveTCPAddr("tcp4", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("ResolveTCPAddr failed: %v", err)
+	}
+	c, err := DialTCP("tcp4", nil, ra)
+	if err != nil {
+		t.Fatalf("DialTCP failed: %v", err)
+	}
+	defer c.Close()
+	c.SetKeepAlive(false)
+	c.SetKeepAlivePeriod(3 * time.Second)
+	c.SetLinger(0)
+	c.SetNoDelay(false)
+	c.LocalAddr()
+	c.RemoteAddr()
+	c.SetDeadline(time.Now().Add(someTimeout))
+	c.SetReadDeadline(time.Now().Add(someTimeout))
+	c.SetWriteDeadline(time.Now().Add(someTimeout))
+
+	if _, err := c.Write([]byte("TCPCONN TEST")); err != nil {
+		t.Fatalf("TCPConn.Write failed: %v", err)
+	}
+	rb := make([]byte, 128)
+	if _, err := c.Read(rb); err != nil {
+		t.Fatalf("TCPConn.Read failed: %v", err)
+	}
+
+	<-done
+}
+
+func TestUDPConnSpecificMethods(t *testing.T) {
+	la, err := ResolveUDPAddr("udp4", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ResolveUDPAddr failed: %v", err)
+	}
+	c, err := ListenUDP("udp4", la)
+	if err != nil {
+		t.Fatalf("ListenUDP failed: %v", err)
+	}
+	defer c.Close()
+	c.LocalAddr()
+	c.RemoteAddr()
+	c.SetDeadline(time.Now().Add(someTimeout))
+	c.SetReadDeadline(time.Now().Add(someTimeout))
+	c.SetWriteDeadline(time.Now().Add(someTimeout))
+	c.SetReadBuffer(2048)
+	c.SetWriteBuffer(2048)
+
+	wb := []byte("UDPCONN TEST")
+	rb := make([]byte, 128)
+	if _, err := c.WriteToUDP(wb, c.LocalAddr().(*UDPAddr)); err != nil {
+		t.Fatalf("UDPConn.WriteToUDP failed: %v", err)
+	}
+	if _, _, err := c.ReadFromUDP(rb); err != nil {
+		t.Fatalf("UDPConn.ReadFromUDP failed: %v", err)
+	}
+	if _, _, err := c.WriteMsgUDP(wb, nil, c.LocalAddr().(*UDPAddr)); err != nil {
+		condFatalf(t, "UDPConn.WriteMsgUDP failed: %v", err)
+	}
+	if _, _, _, _, err := c.ReadMsgUDP(rb, nil); err != nil {
+		condFatalf(t, "UDPConn.ReadMsgUDP failed: %v", err)
+	}
+
+	if f, err := c.File(); err != nil {
+		condFatalf(t, "UDPConn.File failed: %v", err)
+	} else {
+		f.Close()
+	}
+
+	defer func() {
+		if p := recover(); p != nil {
+			t.Fatalf("UDPConn.WriteToUDP or WriteMsgUDP panicked: %v", p)
+		}
+	}()
+
+	c.WriteToUDP(wb, nil)
+	c.WriteMsgUDP(wb, nil, nil)
+}
+
+func TestIPConnSpecificMethods(t *testing.T) {
+	if skip, skipmsg := skipRawSocketTest(t); skip {
+		t.Skip(skipmsg)
+	}
+
+	la, err := ResolveIPAddr("ip4", "127.0.0.1")
+	if err != nil {
+		t.Fatalf("ResolveIPAddr failed: %v", err)
+	}
+	c, err := ListenIP("ip4:icmp", la)
+	if err != nil {
+		t.Fatalf("ListenIP failed: %v", err)
+	}
+	defer c.Close()
+	c.LocalAddr()
+	c.RemoteAddr()
+	c.SetDeadline(time.Now().Add(someTimeout))
+	c.SetReadDeadline(time.Now().Add(someTimeout))
+	c.SetWriteDeadline(time.Now().Add(someTimeout))
+	c.SetReadBuffer(2048)
+	c.SetWriteBuffer(2048)
+
+	wb, err := (&icmpMessage{
+		Type: icmpv4EchoRequest, Code: 0,
+		Body: &icmpEcho{
+			ID: os.Getpid() & 0xffff, Seq: 1,
+			Data: []byte("IPCONN TEST "),
+		},
+	}).Marshal()
+	if err != nil {
+		t.Fatalf("icmpMessage.Marshal failed: %v", err)
+	}
+	rb := make([]byte, 20+len(wb))
+	if _, err := c.WriteToIP(wb, c.LocalAddr().(*IPAddr)); err != nil {
+		t.Fatalf("IPConn.WriteToIP failed: %v", err)
+	}
+	if _, _, err := c.ReadFromIP(rb); err != nil {
+		t.Fatalf("IPConn.ReadFromIP failed: %v", err)
+	}
+	if _, _, err := c.WriteMsgIP(wb, nil, c.LocalAddr().(*IPAddr)); err != nil {
+		condFatalf(t, "IPConn.WriteMsgIP failed: %v", err)
+	}
+	if _, _, _, _, err := c.ReadMsgIP(rb, nil); err != nil {
+		condFatalf(t, "IPConn.ReadMsgIP failed: %v", err)
+	}
+
+	if f, err := c.File(); err != nil {
+		condFatalf(t, "IPConn.File failed: %v", err)
+	} else {
+		f.Close()
+	}
+
+	defer func() {
+		if p := recover(); p != nil {
+			t.Fatalf("IPConn.WriteToIP or WriteMsgIP panicked: %v", p)
+		}
+	}()
+
+	c.WriteToIP(wb, nil)
+	c.WriteMsgIP(wb, nil, nil)
+}
+
+func TestUnixListenerSpecificMethods(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	addr := testUnixAddr()
+	la, err := ResolveUnixAddr("unix", addr)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	ln, err := ListenUnix("unix", la)
+	if err != nil {
+		t.Fatalf("ListenUnix failed: %v", err)
+	}
+	defer ln.Close()
+	defer os.Remove(addr)
+	ln.Addr()
+	ln.SetDeadline(time.Now().Add(30 * time.Nanosecond))
+
+	if c, err := ln.Accept(); err != nil {
+		if !err.(Error).Timeout() {
+			t.Fatalf("UnixListener.Accept failed: %v", err)
+		}
+	} else {
+		c.Close()
+	}
+	if c, err := ln.AcceptUnix(); err != nil {
+		if !err.(Error).Timeout() {
+			t.Fatalf("UnixListener.AcceptUnix failed: %v", err)
+		}
+	} else {
+		c.Close()
+	}
+
+	if f, err := ln.File(); err != nil {
+		t.Fatalf("UnixListener.File failed: %v", err)
+	} else {
+		f.Close()
+	}
+}
+
+func TestUnixConnSpecificMethods(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	addr1, addr2, addr3 := testUnixAddr(), testUnixAddr(), testUnixAddr()
+
+	a1, err := ResolveUnixAddr("unixgram", addr1)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c1, err := DialUnix("unixgram", a1, nil)
+	if err != nil {
+		t.Fatalf("DialUnix failed: %v", err)
+	}
+	defer c1.Close()
+	defer os.Remove(addr1)
+	c1.LocalAddr()
+	c1.RemoteAddr()
+	c1.SetDeadline(time.Now().Add(someTimeout))
+	c1.SetReadDeadline(time.Now().Add(someTimeout))
+	c1.SetWriteDeadline(time.Now().Add(someTimeout))
+	c1.SetReadBuffer(2048)
+	c1.SetWriteBuffer(2048)
+
+	a2, err := ResolveUnixAddr("unixgram", addr2)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c2, err := DialUnix("unixgram", a2, nil)
+	if err != nil {
+		t.Fatalf("DialUnix failed: %v", err)
+	}
+	defer c2.Close()
+	defer os.Remove(addr2)
+	c2.LocalAddr()
+	c2.RemoteAddr()
+	c2.SetDeadline(time.Now().Add(someTimeout))
+	c2.SetReadDeadline(time.Now().Add(someTimeout))
+	c2.SetWriteDeadline(time.Now().Add(someTimeout))
+	c2.SetReadBuffer(2048)
+	c2.SetWriteBuffer(2048)
+
+	a3, err := ResolveUnixAddr("unixgram", addr3)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c3, err := ListenUnixgram("unixgram", a3)
+	if err != nil {
+		t.Fatalf("ListenUnixgram failed: %v", err)
+	}
+	defer c3.Close()
+	defer os.Remove(addr3)
+	c3.LocalAddr()
+	c3.RemoteAddr()
+	c3.SetDeadline(time.Now().Add(someTimeout))
+	c3.SetReadDeadline(time.Now().Add(someTimeout))
+	c3.SetWriteDeadline(time.Now().Add(someTimeout))
+	c3.SetReadBuffer(2048)
+	c3.SetWriteBuffer(2048)
+
+	wb := []byte("UNIXCONN TEST")
+	rb1 := make([]byte, 128)
+	rb2 := make([]byte, 128)
+	rb3 := make([]byte, 128)
+	if _, _, err := c1.WriteMsgUnix(wb, nil, a2); err != nil {
+		t.Fatalf("UnixConn.WriteMsgUnix failed: %v", err)
+	}
+	if _, _, _, _, err := c2.ReadMsgUnix(rb2, nil); err != nil {
+		t.Fatalf("UnixConn.ReadMsgUnix failed: %v", err)
+	}
+	if _, err := c2.WriteToUnix(wb, a1); err != nil {
+		t.Fatalf("UnixConn.WriteToUnix failed: %v", err)
+	}
+	if _, _, err := c1.ReadFromUnix(rb1); err != nil {
+		t.Fatalf("UnixConn.ReadFromUnix failed: %v", err)
+	}
+	if _, err := c3.WriteToUnix(wb, a1); err != nil {
+		t.Fatalf("UnixConn.WriteToUnix failed: %v", err)
+	}
+	if _, _, err := c1.ReadFromUnix(rb1); err != nil {
+		t.Fatalf("UnixConn.ReadFromUnix failed: %v", err)
+	}
+	if _, err := c2.WriteToUnix(wb, a3); err != nil {
+		t.Fatalf("UnixConn.WriteToUnix failed: %v", err)
+	}
+	if _, _, err := c3.ReadFromUnix(rb3); err != nil {
+		t.Fatalf("UnixConn.ReadFromUnix failed: %v", err)
+	}
+
+	if f, err := c1.File(); err != nil {
+		t.Fatalf("UnixConn.File failed: %v", err)
+	} else {
+		f.Close()
+	}
+
+	defer func() {
+		if p := recover(); p != nil {
+			t.Fatalf("UnixConn.WriteToUnix or WriteMsgUnix panicked: %v", p)
+		}
+	}()
+
+	c1.WriteToUnix(wb, nil)
+	c1.WriteMsgUnix(wb, nil, nil)
+	c3.WriteToUnix(wb, nil)
+	c3.WriteMsgUnix(wb, nil, nil)
+}
diff --git a/third_party/gofrontend/libgo/go/net/race.go b/third_party/gofrontend/libgo/go/net/race.go
new file mode 100644
index 0000000..2f02a6c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/race.go
@@ -0,0 +1,31 @@
+// Copyright 2013 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.
+
+// +build race
+// +build windows
+
+package net
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+const raceenabled = true
+
+func raceAcquire(addr unsafe.Pointer) {
+	runtime.RaceAcquire(addr)
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+	runtime.RaceReleaseMerge(addr)
+}
+
+func raceReadRange(addr unsafe.Pointer, len int) {
+	runtime.RaceReadRange(addr, len)
+}
+
+func raceWriteRange(addr unsafe.Pointer, len int) {
+	runtime.RaceWriteRange(addr, len)
+}
diff --git a/third_party/gofrontend/libgo/go/net/race0.go b/third_party/gofrontend/libgo/go/net/race0.go
new file mode 100644
index 0000000..f504297
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/race0.go
@@ -0,0 +1,26 @@
+// Copyright 2013 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.
+
+// +build !race
+// +build windows
+
+package net
+
+import (
+	"unsafe"
+)
+
+const raceenabled = false
+
+func raceAcquire(addr unsafe.Pointer) {
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+}
+
+func raceReadRange(addr unsafe.Pointer, len int) {
+}
+
+func raceWriteRange(addr unsafe.Pointer, len int) {
+}
diff --git a/third_party/gofrontend/libgo/go/net/rpc/client.go b/third_party/gofrontend/libgo/go/net/rpc/client.go
new file mode 100644
index 0000000..21f79b0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/rpc/client.go
@@ -0,0 +1,317 @@
+// 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 rpc
+
+import (
+	"bufio"
+	"encoding/gob"
+	"errors"
+	"io"
+	"log"
+	"net"
+	"net/http"
+	"sync"
+)
+
+// ServerError represents an error that has been returned from
+// the remote side of the RPC connection.
+type ServerError string
+
+func (e ServerError) Error() string {
+	return string(e)
+}
+
+var ErrShutdown = errors.New("connection is shut down")
+
+// Call represents an active RPC.
+type Call struct {
+	ServiceMethod string      // The name of the service and method to call.
+	Args          interface{} // The argument to the function (*struct).
+	Reply         interface{} // The reply from the function (*struct).
+	Error         error       // After completion, the error status.
+	Done          chan *Call  // Strobes when call is complete.
+}
+
+// Client represents an RPC Client.
+// There may be multiple outstanding Calls associated
+// with a single Client, and a Client may be used by
+// multiple goroutines simultaneously.
+type Client struct {
+	codec ClientCodec
+
+	sending sync.Mutex
+
+	mutex    sync.Mutex // protects following
+	request  Request
+	seq      uint64
+	pending  map[uint64]*Call
+	closing  bool // user has called Close
+	shutdown bool // server has told us to stop
+}
+
+// A ClientCodec implements writing of RPC requests and
+// reading of RPC responses for the client side of an RPC session.
+// The client calls WriteRequest to write a request to the connection
+// and calls ReadResponseHeader and ReadResponseBody in pairs
+// to read responses.  The client calls Close when finished with the
+// connection. ReadResponseBody may be called with a nil
+// argument to force the body of the response to be read and then
+// discarded.
+type ClientCodec interface {
+	// WriteRequest must be safe for concurrent use by multiple goroutines.
+	WriteRequest(*Request, interface{}) error
+	ReadResponseHeader(*Response) error
+	ReadResponseBody(interface{}) error
+
+	Close() error
+}
+
+func (client *Client) send(call *Call) {
+	client.sending.Lock()
+	defer client.sending.Unlock()
+
+	// Register this call.
+	client.mutex.Lock()
+	if client.shutdown || client.closing {
+		call.Error = ErrShutdown
+		client.mutex.Unlock()
+		call.done()
+		return
+	}
+	seq := client.seq
+	client.seq++
+	client.pending[seq] = call
+	client.mutex.Unlock()
+
+	// Encode and send the request.
+	client.request.Seq = seq
+	client.request.ServiceMethod = call.ServiceMethod
+	err := client.codec.WriteRequest(&client.request, call.Args)
+	if err != nil {
+		client.mutex.Lock()
+		call = client.pending[seq]
+		delete(client.pending, seq)
+		client.mutex.Unlock()
+		if call != nil {
+			call.Error = err
+			call.done()
+		}
+	}
+}
+
+func (client *Client) input() {
+	var err error
+	var response Response
+	for err == nil {
+		response = Response{}
+		err = client.codec.ReadResponseHeader(&response)
+		if err != nil {
+			break
+		}
+		seq := response.Seq
+		client.mutex.Lock()
+		call := client.pending[seq]
+		delete(client.pending, seq)
+		client.mutex.Unlock()
+
+		switch {
+		case call == nil:
+			// We've got no pending call. That usually means that
+			// WriteRequest partially failed, and call was already
+			// removed; response is a server telling us about an
+			// error reading request body. We should still attempt
+			// to read error body, but there's no one to give it to.
+			err = client.codec.ReadResponseBody(nil)
+			if err != nil {
+				err = errors.New("reading error body: " + err.Error())
+			}
+		case response.Error != "":
+			// We've got an error response. Give this to the request;
+			// any subsequent requests will get the ReadResponseBody
+			// error if there is one.
+			call.Error = ServerError(response.Error)
+			err = client.codec.ReadResponseBody(nil)
+			if err != nil {
+				err = errors.New("reading error body: " + err.Error())
+			}
+			call.done()
+		default:
+			err = client.codec.ReadResponseBody(call.Reply)
+			if err != nil {
+				call.Error = errors.New("reading body " + err.Error())
+			}
+			call.done()
+		}
+	}
+	// Terminate pending calls.
+	client.sending.Lock()
+	client.mutex.Lock()
+	client.shutdown = true
+	closing := client.closing
+	if err == io.EOF {
+		if closing {
+			err = ErrShutdown
+		} else {
+			err = io.ErrUnexpectedEOF
+		}
+	}
+	for _, call := range client.pending {
+		call.Error = err
+		call.done()
+	}
+	client.mutex.Unlock()
+	client.sending.Unlock()
+	if debugLog && err != io.EOF && !closing {
+		log.Println("rpc: client protocol error:", err)
+	}
+}
+
+func (call *Call) done() {
+	select {
+	case call.Done <- call:
+		// ok
+	default:
+		// We don't want to block here.  It is the caller's responsibility to make
+		// sure the channel has enough buffer space. See comment in Go().
+		if debugLog {
+			log.Println("rpc: discarding Call reply due to insufficient Done chan capacity")
+		}
+	}
+}
+
+// NewClient returns a new Client to handle requests to the
+// set of services at the other end of the connection.
+// It adds a buffer to the write side of the connection so
+// the header and payload are sent as a unit.
+func NewClient(conn io.ReadWriteCloser) *Client {
+	encBuf := bufio.NewWriter(conn)
+	client := &gobClientCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(encBuf), encBuf}
+	return NewClientWithCodec(client)
+}
+
+// NewClientWithCodec is like NewClient but uses the specified
+// codec to encode requests and decode responses.
+func NewClientWithCodec(codec ClientCodec) *Client {
+	client := &Client{
+		codec:   codec,
+		pending: make(map[uint64]*Call),
+	}
+	go client.input()
+	return client
+}
+
+type gobClientCodec struct {
+	rwc    io.ReadWriteCloser
+	dec    *gob.Decoder
+	enc    *gob.Encoder
+	encBuf *bufio.Writer
+}
+
+func (c *gobClientCodec) WriteRequest(r *Request, body interface{}) (err error) {
+	if err = c.enc.Encode(r); err != nil {
+		return
+	}
+	if err = c.enc.Encode(body); err != nil {
+		return
+	}
+	return c.encBuf.Flush()
+}
+
+func (c *gobClientCodec) ReadResponseHeader(r *Response) error {
+	return c.dec.Decode(r)
+}
+
+func (c *gobClientCodec) ReadResponseBody(body interface{}) error {
+	return c.dec.Decode(body)
+}
+
+func (c *gobClientCodec) Close() error {
+	return c.rwc.Close()
+}
+
+// DialHTTP connects to an HTTP RPC server at the specified network address
+// listening on the default HTTP RPC path.
+func DialHTTP(network, address string) (*Client, error) {
+	return DialHTTPPath(network, address, DefaultRPCPath)
+}
+
+// DialHTTPPath connects to an HTTP RPC server
+// at the specified network address and path.
+func DialHTTPPath(network, address, path string) (*Client, error) {
+	var err error
+	conn, err := net.Dial(network, address)
+	if err != nil {
+		return nil, err
+	}
+	io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n")
+
+	// Require successful HTTP response
+	// before switching to RPC protocol.
+	resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
+	if err == nil && resp.Status == connected {
+		return NewClient(conn), nil
+	}
+	if err == nil {
+		err = errors.New("unexpected HTTP response: " + resp.Status)
+	}
+	conn.Close()
+	return nil, &net.OpError{
+		Op:   "dial-http",
+		Net:  network + " " + address,
+		Addr: nil,
+		Err:  err,
+	}
+}
+
+// Dial connects to an RPC server at the specified network address.
+func Dial(network, address string) (*Client, error) {
+	conn, err := net.Dial(network, address)
+	if err != nil {
+		return nil, err
+	}
+	return NewClient(conn), nil
+}
+
+func (client *Client) Close() error {
+	client.mutex.Lock()
+	if client.closing {
+		client.mutex.Unlock()
+		return ErrShutdown
+	}
+	client.closing = true
+	client.mutex.Unlock()
+	return client.codec.Close()
+}
+
+// Go invokes the function asynchronously.  It returns the Call structure representing
+// the invocation.  The done channel will signal when the call is complete by returning
+// the same Call object.  If done is nil, Go will allocate a new channel.
+// If non-nil, done must be buffered or Go will deliberately crash.
+func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
+	call := new(Call)
+	call.ServiceMethod = serviceMethod
+	call.Args = args
+	call.Reply = reply
+	if done == nil {
+		done = make(chan *Call, 10) // buffered.
+	} else {
+		// If caller passes done != nil, it must arrange that
+		// done has enough buffer for the number of simultaneous
+		// RPCs that will be using that channel.  If the channel
+		// is totally unbuffered, it's best not to run at all.
+		if cap(done) == 0 {
+			log.Panic("rpc: done channel is unbuffered")
+		}
+	}
+	call.Done = done
+	client.send(call)
+	return call
+}
+
+// Call invokes the named function, waits for it to complete, and returns its error status.
+func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error {
+	call := <-client.Go(serviceMethod, args, reply, make(chan *Call, 1)).Done
+	return call.Error
+}
diff --git a/third_party/gofrontend/libgo/go/net/rpc/client_test.go b/third_party/gofrontend/libgo/go/net/rpc/client_test.go
new file mode 100644
index 0000000..bbfc1ec
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/rpc/client_test.go
@@ -0,0 +1,36 @@
+// Copyright 2014 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 rpc
+
+import (
+	"errors"
+	"testing"
+)
+
+type shutdownCodec struct {
+	responded chan int
+	closed    bool
+}
+
+func (c *shutdownCodec) WriteRequest(*Request, interface{}) error { return nil }
+func (c *shutdownCodec) ReadResponseBody(interface{}) error       { return nil }
+func (c *shutdownCodec) ReadResponseHeader(*Response) error {
+	c.responded <- 1
+	return errors.New("shutdownCodec ReadResponseHeader")
+}
+func (c *shutdownCodec) Close() error {
+	c.closed = true
+	return nil
+}
+
+func TestCloseCodec(t *testing.T) {
+	codec := &shutdownCodec{responded: make(chan int)}
+	client := NewClientWithCodec(codec)
+	<-codec.responded
+	client.Close()
+	if !codec.closed {
+		t.Error("client.Close did not close codec")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/rpc/debug.go b/third_party/gofrontend/libgo/go/net/rpc/debug.go
new file mode 100644
index 0000000..926466d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/rpc/debug.go
@@ -0,0 +1,93 @@
+// 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 rpc
+
+/*
+	Some HTML presented at http://machine:port/debug/rpc
+	Lists services, their methods, and some statistics, still rudimentary.
+*/
+
+import (
+	"fmt"
+	"net/http"
+	"sort"
+	"text/template"
+)
+
+const debugText = `<html>
+	<body>
+	<title>Services</title>
+	{{range .}}
+	<hr>
+	Service {{.Name}}
+	<hr>
+		<table>
+		<th align=center>Method</th><th align=center>Calls</th>
+		{{range .Method}}
+			<tr>
+			<td align=left font=fixed>{{.Name}}({{.Type.ArgType}}, {{.Type.ReplyType}}) error</td>
+			<td align=center>{{.Type.NumCalls}}</td>
+			</tr>
+		{{end}}
+		</table>
+	{{end}}
+	</body>
+	</html>`
+
+var debug = template.Must(template.New("RPC debug").Parse(debugText))
+
+// If set, print log statements for internal and I/O errors.
+var debugLog = false
+
+type debugMethod struct {
+	Type *methodType
+	Name string
+}
+
+type methodArray []debugMethod
+
+type debugService struct {
+	Service *service
+	Name    string
+	Method  methodArray
+}
+
+type serviceArray []debugService
+
+func (s serviceArray) Len() int           { return len(s) }
+func (s serviceArray) Less(i, j int) bool { return s[i].Name < s[j].Name }
+func (s serviceArray) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+
+func (m methodArray) Len() int           { return len(m) }
+func (m methodArray) Less(i, j int) bool { return m[i].Name < m[j].Name }
+func (m methodArray) Swap(i, j int)      { m[i], m[j] = m[j], m[i] }
+
+type debugHTTP struct {
+	*Server
+}
+
+// Runs at /debug/rpc
+func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	// Build a sorted version of the data.
+	var services = make(serviceArray, len(server.serviceMap))
+	i := 0
+	server.mu.Lock()
+	for sname, service := range server.serviceMap {
+		services[i] = debugService{service, sname, make(methodArray, len(service.method))}
+		j := 0
+		for mname, method := range service.method {
+			services[i].Method[j] = debugMethod{method, mname}
+			j++
+		}
+		sort.Sort(services[i].Method)
+		i++
+	}
+	server.mu.Unlock()
+	sort.Sort(services)
+	err := debug.Execute(w, services)
+	if err != nil {
+		fmt.Fprintln(w, "rpc: error executing template:", err.Error())
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/rpc/jsonrpc/all_test.go b/third_party/gofrontend/libgo/go/net/rpc/jsonrpc/all_test.go
new file mode 100644
index 0000000..a433a36
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/rpc/jsonrpc/all_test.go
@@ -0,0 +1,296 @@
+// Copyright 2010 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 jsonrpc
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/rpc"
+	"strings"
+	"testing"
+)
+
+type Args struct {
+	A, B int
+}
+
+type Reply struct {
+	C int
+}
+
+type Arith int
+
+type ArithAddResp struct {
+	Id     interface{} `json:"id"`
+	Result Reply       `json:"result"`
+	Error  interface{} `json:"error"`
+}
+
+func (t *Arith) Add(args *Args, reply *Reply) error {
+	reply.C = args.A + args.B
+	return nil
+}
+
+func (t *Arith) Mul(args *Args, reply *Reply) error {
+	reply.C = args.A * args.B
+	return nil
+}
+
+func (t *Arith) Div(args *Args, reply *Reply) error {
+	if args.B == 0 {
+		return errors.New("divide by zero")
+	}
+	reply.C = args.A / args.B
+	return nil
+}
+
+func (t *Arith) Error(args *Args, reply *Reply) error {
+	panic("ERROR")
+}
+
+func init() {
+	rpc.Register(new(Arith))
+}
+
+func TestServerNoParams(t *testing.T) {
+	cli, srv := net.Pipe()
+	defer cli.Close()
+	go ServeConn(srv)
+	dec := json.NewDecoder(cli)
+
+	fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "123"}`)
+	var resp ArithAddResp
+	if err := dec.Decode(&resp); err != nil {
+		t.Fatalf("Decode after no params: %s", err)
+	}
+	if resp.Error == nil {
+		t.Fatalf("Expected error, got nil")
+	}
+}
+
+func TestServerEmptyMessage(t *testing.T) {
+	cli, srv := net.Pipe()
+	defer cli.Close()
+	go ServeConn(srv)
+	dec := json.NewDecoder(cli)
+
+	fmt.Fprintf(cli, "{}")
+	var resp ArithAddResp
+	if err := dec.Decode(&resp); err != nil {
+		t.Fatalf("Decode after empty: %s", err)
+	}
+	if resp.Error == nil {
+		t.Fatalf("Expected error, got nil")
+	}
+}
+
+func TestServer(t *testing.T) {
+	cli, srv := net.Pipe()
+	defer cli.Close()
+	go ServeConn(srv)
+	dec := json.NewDecoder(cli)
+
+	// Send hand-coded requests to server, parse responses.
+	for i := 0; i < 10; i++ {
+		fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "\u%04d", "params": [{"A": %d, "B": %d}]}`, i, i, i+1)
+		var resp ArithAddResp
+		err := dec.Decode(&resp)
+		if err != nil {
+			t.Fatalf("Decode: %s", err)
+		}
+		if resp.Error != nil {
+			t.Fatalf("resp.Error: %s", resp.Error)
+		}
+		if resp.Id.(string) != string(i) {
+			t.Fatalf("resp: bad id %q want %q", resp.Id.(string), string(i))
+		}
+		if resp.Result.C != 2*i+1 {
+			t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C)
+		}
+	}
+}
+
+func TestClient(t *testing.T) {
+	// Assume server is okay (TestServer is above).
+	// Test client against server.
+	cli, srv := net.Pipe()
+	go ServeConn(srv)
+
+	client := NewClient(cli)
+	defer client.Close()
+
+	// Synchronous calls
+	args := &Args{7, 8}
+	reply := new(Reply)
+	err := client.Call("Arith.Add", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: got %d expected %d", reply.C, args.A+args.B)
+	}
+
+	args = &Args{7, 8}
+	reply = new(Reply)
+	err = client.Call("Arith.Mul", args, reply)
+	if err != nil {
+		t.Errorf("Mul: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A*args.B {
+		t.Errorf("Mul: got %d expected %d", reply.C, args.A*args.B)
+	}
+
+	// Out of order.
+	args = &Args{7, 8}
+	mulReply := new(Reply)
+	mulCall := client.Go("Arith.Mul", args, mulReply, nil)
+	addReply := new(Reply)
+	addCall := client.Go("Arith.Add", args, addReply, nil)
+
+	addCall = <-addCall.Done
+	if addCall.Error != nil {
+		t.Errorf("Add: expected no error but got string %q", addCall.Error.Error())
+	}
+	if addReply.C != args.A+args.B {
+		t.Errorf("Add: got %d expected %d", addReply.C, args.A+args.B)
+	}
+
+	mulCall = <-mulCall.Done
+	if mulCall.Error != nil {
+		t.Errorf("Mul: expected no error but got string %q", mulCall.Error.Error())
+	}
+	if mulReply.C != args.A*args.B {
+		t.Errorf("Mul: got %d expected %d", mulReply.C, args.A*args.B)
+	}
+
+	// Error test
+	args = &Args{7, 0}
+	reply = new(Reply)
+	err = client.Call("Arith.Div", args, reply)
+	// expect an error: zero divide
+	if err == nil {
+		t.Error("Div: expected error")
+	} else if err.Error() != "divide by zero" {
+		t.Error("Div: expected divide by zero error; got", err)
+	}
+}
+
+func TestMalformedInput(t *testing.T) {
+	cli, srv := net.Pipe()
+	go cli.Write([]byte(`{id:1}`)) // invalid json
+	ServeConn(srv)                 // must return, not loop
+}
+
+func TestMalformedOutput(t *testing.T) {
+	cli, srv := net.Pipe()
+	go srv.Write([]byte(`{"id":0,"result":null,"error":null}`))
+	go ioutil.ReadAll(srv)
+
+	client := NewClient(cli)
+	defer client.Close()
+
+	args := &Args{7, 8}
+	reply := new(Reply)
+	err := client.Call("Arith.Add", args, reply)
+	if err == nil {
+		t.Error("expected error")
+	}
+}
+
+func TestServerErrorHasNullResult(t *testing.T) {
+	var out bytes.Buffer
+	sc := NewServerCodec(struct {
+		io.Reader
+		io.Writer
+		io.Closer
+	}{
+		Reader: strings.NewReader(`{"method": "Arith.Add", "id": "123", "params": []}`),
+		Writer: &out,
+		Closer: ioutil.NopCloser(nil),
+	})
+	r := new(rpc.Request)
+	if err := sc.ReadRequestHeader(r); err != nil {
+		t.Fatal(err)
+	}
+	const valueText = "the value we don't want to see"
+	const errorText = "some error"
+	err := sc.WriteResponse(&rpc.Response{
+		ServiceMethod: "Method",
+		Seq:           1,
+		Error:         errorText,
+	}, valueText)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !strings.Contains(out.String(), errorText) {
+		t.Fatalf("Response didn't contain expected error %q: %s", errorText, &out)
+	}
+	if strings.Contains(out.String(), valueText) {
+		t.Errorf("Response contains both an error and value: %s", &out)
+	}
+}
+
+func TestUnexpectedError(t *testing.T) {
+	cli, srv := myPipe()
+	go cli.PipeWriter.CloseWithError(errors.New("unexpected error!")) // reader will get this error
+	ServeConn(srv)                                                    // must return, not loop
+}
+
+// Copied from package net.
+func myPipe() (*pipe, *pipe) {
+	r1, w1 := io.Pipe()
+	r2, w2 := io.Pipe()
+
+	return &pipe{r1, w2}, &pipe{r2, w1}
+}
+
+type pipe struct {
+	*io.PipeReader
+	*io.PipeWriter
+}
+
+type pipeAddr int
+
+func (pipeAddr) Network() string {
+	return "pipe"
+}
+
+func (pipeAddr) String() string {
+	return "pipe"
+}
+
+func (p *pipe) Close() error {
+	err := p.PipeReader.Close()
+	err1 := p.PipeWriter.Close()
+	if err == nil {
+		err = err1
+	}
+	return err
+}
+
+func (p *pipe) LocalAddr() net.Addr {
+	return pipeAddr(0)
+}
+
+func (p *pipe) RemoteAddr() net.Addr {
+	return pipeAddr(0)
+}
+
+func (p *pipe) SetTimeout(nsec int64) error {
+	return errors.New("net.Pipe does not support timeouts")
+}
+
+func (p *pipe) SetReadTimeout(nsec int64) error {
+	return errors.New("net.Pipe does not support timeouts")
+}
+
+func (p *pipe) SetWriteTimeout(nsec int64) error {
+	return errors.New("net.Pipe does not support timeouts")
+}
diff --git a/third_party/gofrontend/libgo/go/net/rpc/jsonrpc/client.go b/third_party/gofrontend/libgo/go/net/rpc/jsonrpc/client.go
new file mode 100644
index 0000000..2194f21
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/rpc/jsonrpc/client.go
@@ -0,0 +1,123 @@
+// Copyright 2010 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 jsonrpc implements a JSON-RPC ClientCodec and ServerCodec
+// for the rpc package.
+package jsonrpc
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"net"
+	"net/rpc"
+	"sync"
+)
+
+type clientCodec struct {
+	dec *json.Decoder // for reading JSON values
+	enc *json.Encoder // for writing JSON values
+	c   io.Closer
+
+	// temporary work space
+	req  clientRequest
+	resp clientResponse
+
+	// JSON-RPC responses include the request id but not the request method.
+	// Package rpc expects both.
+	// We save the request method in pending when sending a request
+	// and then look it up by request ID when filling out the rpc Response.
+	mutex   sync.Mutex        // protects pending
+	pending map[uint64]string // map request id to method name
+}
+
+// NewClientCodec returns a new rpc.ClientCodec using JSON-RPC on conn.
+func NewClientCodec(conn io.ReadWriteCloser) rpc.ClientCodec {
+	return &clientCodec{
+		dec:     json.NewDecoder(conn),
+		enc:     json.NewEncoder(conn),
+		c:       conn,
+		pending: make(map[uint64]string),
+	}
+}
+
+type clientRequest struct {
+	Method string         `json:"method"`
+	Params [1]interface{} `json:"params"`
+	Id     uint64         `json:"id"`
+}
+
+func (c *clientCodec) WriteRequest(r *rpc.Request, param interface{}) error {
+	c.mutex.Lock()
+	c.pending[r.Seq] = r.ServiceMethod
+	c.mutex.Unlock()
+	c.req.Method = r.ServiceMethod
+	c.req.Params[0] = param
+	c.req.Id = r.Seq
+	return c.enc.Encode(&c.req)
+}
+
+type clientResponse struct {
+	Id     uint64           `json:"id"`
+	Result *json.RawMessage `json:"result"`
+	Error  interface{}      `json:"error"`
+}
+
+func (r *clientResponse) reset() {
+	r.Id = 0
+	r.Result = nil
+	r.Error = nil
+}
+
+func (c *clientCodec) ReadResponseHeader(r *rpc.Response) error {
+	c.resp.reset()
+	if err := c.dec.Decode(&c.resp); err != nil {
+		return err
+	}
+
+	c.mutex.Lock()
+	r.ServiceMethod = c.pending[c.resp.Id]
+	delete(c.pending, c.resp.Id)
+	c.mutex.Unlock()
+
+	r.Error = ""
+	r.Seq = c.resp.Id
+	if c.resp.Error != nil || c.resp.Result == nil {
+		x, ok := c.resp.Error.(string)
+		if !ok {
+			return fmt.Errorf("invalid error %v", c.resp.Error)
+		}
+		if x == "" {
+			x = "unspecified error"
+		}
+		r.Error = x
+	}
+	return nil
+}
+
+func (c *clientCodec) ReadResponseBody(x interface{}) error {
+	if x == nil {
+		return nil
+	}
+	return json.Unmarshal(*c.resp.Result, x)
+}
+
+func (c *clientCodec) Close() error {
+	return c.c.Close()
+}
+
+// NewClient returns a new rpc.Client to handle requests to the
+// set of services at the other end of the connection.
+func NewClient(conn io.ReadWriteCloser) *rpc.Client {
+	return rpc.NewClientWithCodec(NewClientCodec(conn))
+}
+
+// Dial connects to a JSON-RPC server at the specified network address.
+func Dial(network, address string) (*rpc.Client, error) {
+	conn, err := net.Dial(network, address)
+	if err != nil {
+		return nil, err
+	}
+	return NewClient(conn), err
+}
diff --git a/third_party/gofrontend/libgo/go/net/rpc/jsonrpc/server.go b/third_party/gofrontend/libgo/go/net/rpc/jsonrpc/server.go
new file mode 100644
index 0000000..e6d37cf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/rpc/jsonrpc/server.go
@@ -0,0 +1,134 @@
+// Copyright 2010 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 jsonrpc
+
+import (
+	"encoding/json"
+	"errors"
+	"io"
+	"net/rpc"
+	"sync"
+)
+
+var errMissingParams = errors.New("jsonrpc: request body missing params")
+
+type serverCodec struct {
+	dec *json.Decoder // for reading JSON values
+	enc *json.Encoder // for writing JSON values
+	c   io.Closer
+
+	// temporary work space
+	req serverRequest
+
+	// JSON-RPC clients can use arbitrary json values as request IDs.
+	// Package rpc expects uint64 request IDs.
+	// We assign uint64 sequence numbers to incoming requests
+	// but save the original request ID in the pending map.
+	// When rpc responds, we use the sequence number in
+	// the response to find the original request ID.
+	mutex   sync.Mutex // protects seq, pending
+	seq     uint64
+	pending map[uint64]*json.RawMessage
+}
+
+// NewServerCodec returns a new rpc.ServerCodec using JSON-RPC on conn.
+func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec {
+	return &serverCodec{
+		dec:     json.NewDecoder(conn),
+		enc:     json.NewEncoder(conn),
+		c:       conn,
+		pending: make(map[uint64]*json.RawMessage),
+	}
+}
+
+type serverRequest struct {
+	Method string           `json:"method"`
+	Params *json.RawMessage `json:"params"`
+	Id     *json.RawMessage `json:"id"`
+}
+
+func (r *serverRequest) reset() {
+	r.Method = ""
+	r.Params = nil
+	r.Id = nil
+}
+
+type serverResponse struct {
+	Id     *json.RawMessage `json:"id"`
+	Result interface{}      `json:"result"`
+	Error  interface{}      `json:"error"`
+}
+
+func (c *serverCodec) ReadRequestHeader(r *rpc.Request) error {
+	c.req.reset()
+	if err := c.dec.Decode(&c.req); err != nil {
+		return err
+	}
+	r.ServiceMethod = c.req.Method
+
+	// JSON request id can be any JSON value;
+	// RPC package expects uint64.  Translate to
+	// internal uint64 and save JSON on the side.
+	c.mutex.Lock()
+	c.seq++
+	c.pending[c.seq] = c.req.Id
+	c.req.Id = nil
+	r.Seq = c.seq
+	c.mutex.Unlock()
+
+	return nil
+}
+
+func (c *serverCodec) ReadRequestBody(x interface{}) error {
+	if x == nil {
+		return nil
+	}
+	if c.req.Params == nil {
+		return errMissingParams
+	}
+	// JSON params is array value.
+	// RPC params is struct.
+	// Unmarshal into array containing struct for now.
+	// Should think about making RPC more general.
+	var params [1]interface{}
+	params[0] = x
+	return json.Unmarshal(*c.req.Params, &params)
+}
+
+var null = json.RawMessage([]byte("null"))
+
+func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) error {
+	c.mutex.Lock()
+	b, ok := c.pending[r.Seq]
+	if !ok {
+		c.mutex.Unlock()
+		return errors.New("invalid sequence number in response")
+	}
+	delete(c.pending, r.Seq)
+	c.mutex.Unlock()
+
+	if b == nil {
+		// Invalid request so no id.  Use JSON null.
+		b = &null
+	}
+	resp := serverResponse{Id: b}
+	if r.Error == "" {
+		resp.Result = x
+	} else {
+		resp.Error = r.Error
+	}
+	return c.enc.Encode(resp)
+}
+
+func (c *serverCodec) Close() error {
+	return c.c.Close()
+}
+
+// ServeConn runs the JSON-RPC server on a single connection.
+// ServeConn blocks, serving the connection until the client hangs up.
+// The caller typically invokes ServeConn in a go statement.
+func ServeConn(conn io.ReadWriteCloser) {
+	rpc.ServeCodec(NewServerCodec(conn))
+}
diff --git a/third_party/gofrontend/libgo/go/net/rpc/server.go b/third_party/gofrontend/libgo/go/net/rpc/server.go
new file mode 100644
index 0000000..6b264b4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/rpc/server.go
@@ -0,0 +1,686 @@
+// 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 rpc provides access to the exported methods of an object across a
+	network or other I/O connection.  A server registers an object, making it visible
+	as a service with the name of the type of the object.  After registration, exported
+	methods of the object will be accessible remotely.  A server may register multiple
+	objects (services) of different types but it is an error to register multiple
+	objects of the same type.
+
+	Only methods that satisfy these criteria will be made available for remote access;
+	other methods will be ignored:
+
+		- the method is exported.
+		- the method has two arguments, both exported (or builtin) types.
+		- the method's second argument is a pointer.
+		- the method has return type error.
+
+	In effect, the method must look schematically like
+
+		func (t *T) MethodName(argType T1, replyType *T2) error
+
+	where T, T1 and T2 can be marshaled by encoding/gob.
+	These requirements apply even if a different codec is used.
+	(In the future, these requirements may soften for custom codecs.)
+
+	The method's first argument represents the arguments provided by the caller; the
+	second argument represents the result parameters to be returned to the caller.
+	The method's return value, if non-nil, is passed back as a string that the client
+	sees as if created by errors.New.  If an error is returned, the reply parameter
+	will not be sent back to the client.
+
+	The server may handle requests on a single connection by calling ServeConn.  More
+	typically it will create a network listener and call Accept or, for an HTTP
+	listener, HandleHTTP and http.Serve.
+
+	A client wishing to use the service establishes a connection and then invokes
+	NewClient on the connection.  The convenience function Dial (DialHTTP) performs
+	both steps for a raw network connection (an HTTP connection).  The resulting
+	Client object has two methods, Call and Go, that specify the service and method to
+	call, a pointer containing the arguments, and a pointer to receive the result
+	parameters.
+
+	The Call method waits for the remote call to complete while the Go method
+	launches the call asynchronously and signals completion using the Call
+	structure's Done channel.
+
+	Unless an explicit codec is set up, package encoding/gob is used to
+	transport the data.
+
+	Here is a simple example.  A server wishes to export an object of type Arith:
+
+		package server
+
+		type Args struct {
+			A, B int
+		}
+
+		type Quotient struct {
+			Quo, Rem int
+		}
+
+		type Arith int
+
+		func (t *Arith) Multiply(args *Args, reply *int) error {
+			*reply = args.A * args.B
+			return nil
+		}
+
+		func (t *Arith) Divide(args *Args, quo *Quotient) error {
+			if args.B == 0 {
+				return errors.New("divide by zero")
+			}
+			quo.Quo = args.A / args.B
+			quo.Rem = args.A % args.B
+			return nil
+		}
+
+	The server calls (for HTTP service):
+
+		arith := new(Arith)
+		rpc.Register(arith)
+		rpc.HandleHTTP()
+		l, e := net.Listen("tcp", ":1234")
+		if e != nil {
+			log.Fatal("listen error:", e)
+		}
+		go http.Serve(l, nil)
+
+	At this point, clients can see a service "Arith" with methods "Arith.Multiply" and
+	"Arith.Divide".  To invoke one, a client first dials the server:
+
+		client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
+		if err != nil {
+			log.Fatal("dialing:", err)
+		}
+
+	Then it can make a remote call:
+
+		// Synchronous call
+		args := &server.Args{7,8}
+		var reply int
+		err = client.Call("Arith.Multiply", args, &reply)
+		if err != nil {
+			log.Fatal("arith error:", err)
+		}
+		fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)
+
+	or
+
+		// Asynchronous call
+		quotient := new(Quotient)
+		divCall := client.Go("Arith.Divide", args, quotient, nil)
+		replyCall := <-divCall.Done	// will be equal to divCall
+		// check errors, print, etc.
+
+	A server implementation will often provide a simple, type-safe wrapper for the
+	client.
+*/
+package rpc
+
+import (
+	"bufio"
+	"encoding/gob"
+	"errors"
+	"io"
+	"log"
+	"net"
+	"net/http"
+	"reflect"
+	"strings"
+	"sync"
+	"unicode"
+	"unicode/utf8"
+)
+
+const (
+	// Defaults used by HandleHTTP
+	DefaultRPCPath   = "/_goRPC_"
+	DefaultDebugPath = "/debug/rpc"
+)
+
+// Precompute the reflect type for error.  Can't use error directly
+// because Typeof takes an empty interface value.  This is annoying.
+var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
+
+type methodType struct {
+	sync.Mutex // protects counters
+	method     reflect.Method
+	ArgType    reflect.Type
+	ReplyType  reflect.Type
+	numCalls   uint
+}
+
+type service struct {
+	name   string                 // name of service
+	rcvr   reflect.Value          // receiver of methods for the service
+	typ    reflect.Type           // type of the receiver
+	method map[string]*methodType // registered methods
+}
+
+// Request is a header written before every RPC call.  It is used internally
+// but documented here as an aid to debugging, such as when analyzing
+// network traffic.
+type Request struct {
+	ServiceMethod string   // format: "Service.Method"
+	Seq           uint64   // sequence number chosen by client
+	next          *Request // for free list in Server
+}
+
+// Response is a header written before every RPC return.  It is used internally
+// but documented here as an aid to debugging, such as when analyzing
+// network traffic.
+type Response struct {
+	ServiceMethod string    // echoes that of the Request
+	Seq           uint64    // echoes that of the request
+	Error         string    // error, if any.
+	next          *Response // for free list in Server
+}
+
+// Server represents an RPC Server.
+type Server struct {
+	mu         sync.RWMutex // protects the serviceMap
+	serviceMap map[string]*service
+	reqLock    sync.Mutex // protects freeReq
+	freeReq    *Request
+	respLock   sync.Mutex // protects freeResp
+	freeResp   *Response
+}
+
+// NewServer returns a new Server.
+func NewServer() *Server {
+	return &Server{serviceMap: make(map[string]*service)}
+}
+
+// DefaultServer is the default instance of *Server.
+var DefaultServer = NewServer()
+
+// Is this an exported - upper case - name?
+func isExported(name string) bool {
+	rune, _ := utf8.DecodeRuneInString(name)
+	return unicode.IsUpper(rune)
+}
+
+// Is this type exported or a builtin?
+func isExportedOrBuiltinType(t reflect.Type) bool {
+	for t.Kind() == reflect.Ptr {
+		t = t.Elem()
+	}
+	// PkgPath will be non-empty even for an exported type,
+	// so we need to check the type name as well.
+	return isExported(t.Name()) || t.PkgPath() == ""
+}
+
+// Register publishes in the server the set of methods of the
+// receiver value that satisfy the following conditions:
+//	- exported method
+//	- two arguments, both of exported type
+//	- the second argument is a pointer
+//	- one return value, of type error
+// It returns an error if the receiver is not an exported type or has
+// no suitable methods. It also logs the error using package log.
+// The client accesses each method using a string of the form "Type.Method",
+// where Type is the receiver's concrete type.
+func (server *Server) Register(rcvr interface{}) error {
+	return server.register(rcvr, "", false)
+}
+
+// RegisterName is like Register but uses the provided name for the type
+// instead of the receiver's concrete type.
+func (server *Server) RegisterName(name string, rcvr interface{}) error {
+	return server.register(rcvr, name, true)
+}
+
+func (server *Server) register(rcvr interface{}, name string, useName bool) error {
+	server.mu.Lock()
+	defer server.mu.Unlock()
+	if server.serviceMap == nil {
+		server.serviceMap = make(map[string]*service)
+	}
+	s := new(service)
+	s.typ = reflect.TypeOf(rcvr)
+	s.rcvr = reflect.ValueOf(rcvr)
+	sname := reflect.Indirect(s.rcvr).Type().Name()
+	if useName {
+		sname = name
+	}
+	if sname == "" {
+		s := "rpc.Register: no service name for type " + s.typ.String()
+		log.Print(s)
+		return errors.New(s)
+	}
+	if !isExported(sname) && !useName {
+		s := "rpc.Register: type " + sname + " is not exported"
+		log.Print(s)
+		return errors.New(s)
+	}
+	if _, present := server.serviceMap[sname]; present {
+		return errors.New("rpc: service already defined: " + sname)
+	}
+	s.name = sname
+
+	// Install the methods
+	s.method = suitableMethods(s.typ, true)
+
+	if len(s.method) == 0 {
+		str := ""
+
+		// To help the user, see if a pointer receiver would work.
+		method := suitableMethods(reflect.PtrTo(s.typ), false)
+		if len(method) != 0 {
+			str = "rpc.Register: type " + sname + " has no exported methods of suitable type (hint: pass a pointer to value of that type)"
+		} else {
+			str = "rpc.Register: type " + sname + " has no exported methods of suitable type"
+		}
+		log.Print(str)
+		return errors.New(str)
+	}
+	server.serviceMap[s.name] = s
+	return nil
+}
+
+// suitableMethods returns suitable Rpc methods of typ, it will report
+// error using log if reportErr is true.
+func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
+	methods := make(map[string]*methodType)
+	for m := 0; m < typ.NumMethod(); m++ {
+		method := typ.Method(m)
+		mtype := method.Type
+		mname := method.Name
+		// Method must be exported.
+		if method.PkgPath != "" {
+			continue
+		}
+		// Method needs three ins: receiver, *args, *reply.
+		if mtype.NumIn() != 3 {
+			if reportErr {
+				log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
+			}
+			continue
+		}
+		// First arg need not be a pointer.
+		argType := mtype.In(1)
+		if !isExportedOrBuiltinType(argType) {
+			if reportErr {
+				log.Println(mname, "argument type not exported:", argType)
+			}
+			continue
+		}
+		// Second arg must be a pointer.
+		replyType := mtype.In(2)
+		if replyType.Kind() != reflect.Ptr {
+			if reportErr {
+				log.Println("method", mname, "reply type not a pointer:", replyType)
+			}
+			continue
+		}
+		// Reply type must be exported.
+		if !isExportedOrBuiltinType(replyType) {
+			if reportErr {
+				log.Println("method", mname, "reply type not exported:", replyType)
+			}
+			continue
+		}
+		// Method needs one out.
+		if mtype.NumOut() != 1 {
+			if reportErr {
+				log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
+			}
+			continue
+		}
+		// The return type of the method must be error.
+		if returnType := mtype.Out(0); returnType != typeOfError {
+			if reportErr {
+				log.Println("method", mname, "returns", returnType.String(), "not error")
+			}
+			continue
+		}
+		methods[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
+	}
+	return methods
+}
+
+// A value sent as a placeholder for the server's response value when the server
+// receives an invalid request. It is never decoded by the client since the Response
+// contains an error when it is used.
+var invalidRequest = struct{}{}
+
+func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg string) {
+	resp := server.getResponse()
+	// Encode the response header
+	resp.ServiceMethod = req.ServiceMethod
+	if errmsg != "" {
+		resp.Error = errmsg
+		reply = invalidRequest
+	}
+	resp.Seq = req.Seq
+	sending.Lock()
+	err := codec.WriteResponse(resp, reply)
+	if debugLog && err != nil {
+		log.Println("rpc: writing response:", err)
+	}
+	sending.Unlock()
+	server.freeResponse(resp)
+}
+
+func (m *methodType) NumCalls() (n uint) {
+	m.Lock()
+	n = m.numCalls
+	m.Unlock()
+	return n
+}
+
+func (s *service) call(server *Server, sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, codec ServerCodec) {
+	mtype.Lock()
+	mtype.numCalls++
+	mtype.Unlock()
+	function := mtype.method.Func
+	// Invoke the method, providing a new value for the reply.
+	returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv})
+	// The return value for the method is an error.
+	errInter := returnValues[0].Interface()
+	errmsg := ""
+	if errInter != nil {
+		errmsg = errInter.(error).Error()
+	}
+	server.sendResponse(sending, req, replyv.Interface(), codec, errmsg)
+	server.freeRequest(req)
+}
+
+type gobServerCodec struct {
+	rwc    io.ReadWriteCloser
+	dec    *gob.Decoder
+	enc    *gob.Encoder
+	encBuf *bufio.Writer
+}
+
+func (c *gobServerCodec) ReadRequestHeader(r *Request) error {
+	return c.dec.Decode(r)
+}
+
+func (c *gobServerCodec) ReadRequestBody(body interface{}) error {
+	return c.dec.Decode(body)
+}
+
+func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err error) {
+	if err = c.enc.Encode(r); err != nil {
+		return
+	}
+	if err = c.enc.Encode(body); err != nil {
+		return
+	}
+	return c.encBuf.Flush()
+}
+
+func (c *gobServerCodec) Close() error {
+	return c.rwc.Close()
+}
+
+// ServeConn runs the server on a single connection.
+// ServeConn blocks, serving the connection until the client hangs up.
+// The caller typically invokes ServeConn in a go statement.
+// ServeConn uses the gob wire format (see package gob) on the
+// connection.  To use an alternate codec, use ServeCodec.
+func (server *Server) ServeConn(conn io.ReadWriteCloser) {
+	buf := bufio.NewWriter(conn)
+	srv := &gobServerCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(buf), buf}
+	server.ServeCodec(srv)
+}
+
+// ServeCodec is like ServeConn but uses the specified codec to
+// decode requests and encode responses.
+func (server *Server) ServeCodec(codec ServerCodec) {
+	sending := new(sync.Mutex)
+	for {
+		service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
+		if err != nil {
+			if debugLog && err != io.EOF {
+				log.Println("rpc:", err)
+			}
+			if !keepReading {
+				break
+			}
+			// send a response if we actually managed to read a header.
+			if req != nil {
+				server.sendResponse(sending, req, invalidRequest, codec, err.Error())
+				server.freeRequest(req)
+			}
+			continue
+		}
+		go service.call(server, sending, mtype, req, argv, replyv, codec)
+	}
+	codec.Close()
+}
+
+// ServeRequest is like ServeCodec but synchronously serves a single request.
+// It does not close the codec upon completion.
+func (server *Server) ServeRequest(codec ServerCodec) error {
+	sending := new(sync.Mutex)
+	service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
+	if err != nil {
+		if !keepReading {
+			return err
+		}
+		// send a response if we actually managed to read a header.
+		if req != nil {
+			server.sendResponse(sending, req, invalidRequest, codec, err.Error())
+			server.freeRequest(req)
+		}
+		return err
+	}
+	service.call(server, sending, mtype, req, argv, replyv, codec)
+	return nil
+}
+
+func (server *Server) getRequest() *Request {
+	server.reqLock.Lock()
+	req := server.freeReq
+	if req == nil {
+		req = new(Request)
+	} else {
+		server.freeReq = req.next
+		*req = Request{}
+	}
+	server.reqLock.Unlock()
+	return req
+}
+
+func (server *Server) freeRequest(req *Request) {
+	server.reqLock.Lock()
+	req.next = server.freeReq
+	server.freeReq = req
+	server.reqLock.Unlock()
+}
+
+func (server *Server) getResponse() *Response {
+	server.respLock.Lock()
+	resp := server.freeResp
+	if resp == nil {
+		resp = new(Response)
+	} else {
+		server.freeResp = resp.next
+		*resp = Response{}
+	}
+	server.respLock.Unlock()
+	return resp
+}
+
+func (server *Server) freeResponse(resp *Response) {
+	server.respLock.Lock()
+	resp.next = server.freeResp
+	server.freeResp = resp
+	server.respLock.Unlock()
+}
+
+func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *methodType, req *Request, argv, replyv reflect.Value, keepReading bool, err error) {
+	service, mtype, req, keepReading, err = server.readRequestHeader(codec)
+	if err != nil {
+		if !keepReading {
+			return
+		}
+		// discard body
+		codec.ReadRequestBody(nil)
+		return
+	}
+
+	// Decode the argument value.
+	argIsValue := false // if true, need to indirect before calling.
+	if mtype.ArgType.Kind() == reflect.Ptr {
+		argv = reflect.New(mtype.ArgType.Elem())
+	} else {
+		argv = reflect.New(mtype.ArgType)
+		argIsValue = true
+	}
+	// argv guaranteed to be a pointer now.
+	if err = codec.ReadRequestBody(argv.Interface()); err != nil {
+		return
+	}
+	if argIsValue {
+		argv = argv.Elem()
+	}
+
+	replyv = reflect.New(mtype.ReplyType.Elem())
+	return
+}
+
+func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mtype *methodType, req *Request, keepReading bool, err error) {
+	// Grab the request header.
+	req = server.getRequest()
+	err = codec.ReadRequestHeader(req)
+	if err != nil {
+		req = nil
+		if err == io.EOF || err == io.ErrUnexpectedEOF {
+			return
+		}
+		err = errors.New("rpc: server cannot decode request: " + err.Error())
+		return
+	}
+
+	// We read the header successfully.  If we see an error now,
+	// we can still recover and move on to the next request.
+	keepReading = true
+
+	dot := strings.LastIndex(req.ServiceMethod, ".")
+	if dot < 0 {
+		err = errors.New("rpc: service/method request ill-formed: " + req.ServiceMethod)
+		return
+	}
+	serviceName := req.ServiceMethod[:dot]
+	methodName := req.ServiceMethod[dot+1:]
+
+	// Look up the request.
+	server.mu.RLock()
+	service = server.serviceMap[serviceName]
+	server.mu.RUnlock()
+	if service == nil {
+		err = errors.New("rpc: can't find service " + req.ServiceMethod)
+		return
+	}
+	mtype = service.method[methodName]
+	if mtype == nil {
+		err = errors.New("rpc: can't find method " + req.ServiceMethod)
+	}
+	return
+}
+
+// Accept accepts connections on the listener and serves requests
+// for each incoming connection.  Accept blocks; the caller typically
+// invokes it in a go statement.
+func (server *Server) Accept(lis net.Listener) {
+	for {
+		conn, err := lis.Accept()
+		if err != nil {
+			log.Fatal("rpc.Serve: accept:", err.Error()) // TODO(r): exit?
+		}
+		go server.ServeConn(conn)
+	}
+}
+
+// Register publishes the receiver's methods in the DefaultServer.
+func Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) }
+
+// RegisterName is like Register but uses the provided name for the type
+// instead of the receiver's concrete type.
+func RegisterName(name string, rcvr interface{}) error {
+	return DefaultServer.RegisterName(name, rcvr)
+}
+
+// A ServerCodec implements reading of RPC requests and writing of
+// RPC responses for the server side of an RPC session.
+// The server calls ReadRequestHeader and ReadRequestBody in pairs
+// to read requests from the connection, and it calls WriteResponse to
+// write a response back.  The server calls Close when finished with the
+// connection. ReadRequestBody may be called with a nil
+// argument to force the body of the request to be read and discarded.
+type ServerCodec interface {
+	ReadRequestHeader(*Request) error
+	ReadRequestBody(interface{}) error
+	// WriteResponse must be safe for concurrent use by multiple goroutines.
+	WriteResponse(*Response, interface{}) error
+
+	Close() error
+}
+
+// ServeConn runs the DefaultServer on a single connection.
+// ServeConn blocks, serving the connection until the client hangs up.
+// The caller typically invokes ServeConn in a go statement.
+// ServeConn uses the gob wire format (see package gob) on the
+// connection.  To use an alternate codec, use ServeCodec.
+func ServeConn(conn io.ReadWriteCloser) {
+	DefaultServer.ServeConn(conn)
+}
+
+// ServeCodec is like ServeConn but uses the specified codec to
+// decode requests and encode responses.
+func ServeCodec(codec ServerCodec) {
+	DefaultServer.ServeCodec(codec)
+}
+
+// ServeRequest is like ServeCodec but synchronously serves a single request.
+// It does not close the codec upon completion.
+func ServeRequest(codec ServerCodec) error {
+	return DefaultServer.ServeRequest(codec)
+}
+
+// Accept accepts connections on the listener and serves requests
+// to DefaultServer for each incoming connection.
+// Accept blocks; the caller typically invokes it in a go statement.
+func Accept(lis net.Listener) { DefaultServer.Accept(lis) }
+
+// Can connect to RPC service using HTTP CONNECT to rpcPath.
+var connected = "200 Connected to Go RPC"
+
+// ServeHTTP implements an http.Handler that answers RPC requests.
+func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	if req.Method != "CONNECT" {
+		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+		w.WriteHeader(http.StatusMethodNotAllowed)
+		io.WriteString(w, "405 must CONNECT\n")
+		return
+	}
+	conn, _, err := w.(http.Hijacker).Hijack()
+	if err != nil {
+		log.Print("rpc hijacking ", req.RemoteAddr, ": ", err.Error())
+		return
+	}
+	io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
+	server.ServeConn(conn)
+}
+
+// HandleHTTP registers an HTTP handler for RPC messages on rpcPath,
+// and a debugging handler on debugPath.
+// It is still necessary to invoke http.Serve(), typically in a go statement.
+func (server *Server) HandleHTTP(rpcPath, debugPath string) {
+	http.Handle(rpcPath, server)
+	http.Handle(debugPath, debugHTTP{server})
+}
+
+// HandleHTTP registers an HTTP handler for RPC messages to DefaultServer
+// on DefaultRPCPath and a debugging handler on DefaultDebugPath.
+// It is still necessary to invoke http.Serve(), typically in a go statement.
+func HandleHTTP() {
+	DefaultServer.HandleHTTP(DefaultRPCPath, DefaultDebugPath)
+}
diff --git a/third_party/gofrontend/libgo/go/net/rpc/server_test.go b/third_party/gofrontend/libgo/go/net/rpc/server_test.go
new file mode 100644
index 0000000..0dc4ddc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/rpc/server_test.go
@@ -0,0 +1,683 @@
+// 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 rpc
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"net"
+	"net/http/httptest"
+	"runtime"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"testing"
+	"time"
+)
+
+var (
+	newServer                 *Server
+	serverAddr, newServerAddr string
+	httpServerAddr            string
+	once, newOnce, httpOnce   sync.Once
+)
+
+const (
+	newHttpPath = "/foo"
+)
+
+type Args struct {
+	A, B int
+}
+
+type Reply struct {
+	C int
+}
+
+type Arith int
+
+// Some of Arith's methods have value args, some have pointer args. That's deliberate.
+
+func (t *Arith) Add(args Args, reply *Reply) error {
+	reply.C = args.A + args.B
+	return nil
+}
+
+func (t *Arith) Mul(args *Args, reply *Reply) error {
+	reply.C = args.A * args.B
+	return nil
+}
+
+func (t *Arith) Div(args Args, reply *Reply) error {
+	if args.B == 0 {
+		return errors.New("divide by zero")
+	}
+	reply.C = args.A / args.B
+	return nil
+}
+
+func (t *Arith) String(args *Args, reply *string) error {
+	*reply = fmt.Sprintf("%d+%d=%d", args.A, args.B, args.A+args.B)
+	return nil
+}
+
+func (t *Arith) Scan(args string, reply *Reply) (err error) {
+	_, err = fmt.Sscan(args, &reply.C)
+	return
+}
+
+func (t *Arith) Error(args *Args, reply *Reply) error {
+	panic("ERROR")
+}
+
+func listenTCP() (net.Listener, string) {
+	l, e := net.Listen("tcp", "127.0.0.1:0") // any available address
+	if e != nil {
+		log.Fatalf("net.Listen tcp :0: %v", e)
+	}
+	return l, l.Addr().String()
+}
+
+func startServer() {
+	Register(new(Arith))
+	RegisterName("net.rpc.Arith", new(Arith))
+
+	var l net.Listener
+	l, serverAddr = listenTCP()
+	log.Println("Test RPC server listening on", serverAddr)
+	go Accept(l)
+
+	HandleHTTP()
+	httpOnce.Do(startHttpServer)
+}
+
+func startNewServer() {
+	newServer = NewServer()
+	newServer.Register(new(Arith))
+	newServer.RegisterName("net.rpc.Arith", new(Arith))
+	newServer.RegisterName("newServer.Arith", new(Arith))
+
+	var l net.Listener
+	l, newServerAddr = listenTCP()
+	log.Println("NewServer test RPC server listening on", newServerAddr)
+	go newServer.Accept(l)
+
+	newServer.HandleHTTP(newHttpPath, "/bar")
+	httpOnce.Do(startHttpServer)
+}
+
+func startHttpServer() {
+	server := httptest.NewServer(nil)
+	httpServerAddr = server.Listener.Addr().String()
+	log.Println("Test HTTP RPC server listening on", httpServerAddr)
+}
+
+func TestRPC(t *testing.T) {
+	once.Do(startServer)
+	testRPC(t, serverAddr)
+	newOnce.Do(startNewServer)
+	testRPC(t, newServerAddr)
+	testNewServerRPC(t, newServerAddr)
+}
+
+func testRPC(t *testing.T, addr string) {
+	client, err := Dial("tcp", addr)
+	if err != nil {
+		t.Fatal("dialing", err)
+	}
+	defer client.Close()
+
+	// Synchronous calls
+	args := &Args{7, 8}
+	reply := new(Reply)
+	err = client.Call("Arith.Add", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+	}
+
+	// Nonexistent method
+	args = &Args{7, 0}
+	reply = new(Reply)
+	err = client.Call("Arith.BadOperation", args, reply)
+	// expect an error
+	if err == nil {
+		t.Error("BadOperation: expected error")
+	} else if !strings.HasPrefix(err.Error(), "rpc: can't find method ") {
+		t.Errorf("BadOperation: expected can't find method error; got %q", err)
+	}
+
+	// Unknown service
+	args = &Args{7, 8}
+	reply = new(Reply)
+	err = client.Call("Arith.Unknown", args, reply)
+	if err == nil {
+		t.Error("expected error calling unknown service")
+	} else if strings.Index(err.Error(), "method") < 0 {
+		t.Error("expected error about method; got", err)
+	}
+
+	// Out of order.
+	args = &Args{7, 8}
+	mulReply := new(Reply)
+	mulCall := client.Go("Arith.Mul", args, mulReply, nil)
+	addReply := new(Reply)
+	addCall := client.Go("Arith.Add", args, addReply, nil)
+
+	addCall = <-addCall.Done
+	if addCall.Error != nil {
+		t.Errorf("Add: expected no error but got string %q", addCall.Error.Error())
+	}
+	if addReply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
+	}
+
+	mulCall = <-mulCall.Done
+	if mulCall.Error != nil {
+		t.Errorf("Mul: expected no error but got string %q", mulCall.Error.Error())
+	}
+	if mulReply.C != args.A*args.B {
+		t.Errorf("Mul: expected %d got %d", mulReply.C, args.A*args.B)
+	}
+
+	// Error test
+	args = &Args{7, 0}
+	reply = new(Reply)
+	err = client.Call("Arith.Div", args, reply)
+	// expect an error: zero divide
+	if err == nil {
+		t.Error("Div: expected error")
+	} else if err.Error() != "divide by zero" {
+		t.Error("Div: expected divide by zero error; got", err)
+	}
+
+	// Bad type.
+	reply = new(Reply)
+	err = client.Call("Arith.Add", reply, reply) // args, reply would be the correct thing to use
+	if err == nil {
+		t.Error("expected error calling Arith.Add with wrong arg type")
+	} else if strings.Index(err.Error(), "type") < 0 {
+		t.Error("expected error about type; got", err)
+	}
+
+	// Non-struct argument
+	const Val = 12345
+	str := fmt.Sprint(Val)
+	reply = new(Reply)
+	err = client.Call("Arith.Scan", &str, reply)
+	if err != nil {
+		t.Errorf("Scan: expected no error but got string %q", err.Error())
+	} else if reply.C != Val {
+		t.Errorf("Scan: expected %d got %d", Val, reply.C)
+	}
+
+	// Non-struct reply
+	args = &Args{27, 35}
+	str = ""
+	err = client.Call("Arith.String", args, &str)
+	if err != nil {
+		t.Errorf("String: expected no error but got string %q", err.Error())
+	}
+	expect := fmt.Sprintf("%d+%d=%d", args.A, args.B, args.A+args.B)
+	if str != expect {
+		t.Errorf("String: expected %s got %s", expect, str)
+	}
+
+	args = &Args{7, 8}
+	reply = new(Reply)
+	err = client.Call("Arith.Mul", args, reply)
+	if err != nil {
+		t.Errorf("Mul: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A*args.B {
+		t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
+	}
+
+	// ServiceName contain "." character
+	args = &Args{7, 8}
+	reply = new(Reply)
+	err = client.Call("net.rpc.Arith.Add", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+	}
+}
+
+func testNewServerRPC(t *testing.T, addr string) {
+	client, err := Dial("tcp", addr)
+	if err != nil {
+		t.Fatal("dialing", err)
+	}
+	defer client.Close()
+
+	// Synchronous calls
+	args := &Args{7, 8}
+	reply := new(Reply)
+	err = client.Call("newServer.Arith.Add", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+	}
+}
+
+func TestHTTP(t *testing.T) {
+	once.Do(startServer)
+	testHTTPRPC(t, "")
+	newOnce.Do(startNewServer)
+	testHTTPRPC(t, newHttpPath)
+}
+
+func testHTTPRPC(t *testing.T, path string) {
+	var client *Client
+	var err error
+	if path == "" {
+		client, err = DialHTTP("tcp", httpServerAddr)
+	} else {
+		client, err = DialHTTPPath("tcp", httpServerAddr, path)
+	}
+	if err != nil {
+		t.Fatal("dialing", err)
+	}
+	defer client.Close()
+
+	// Synchronous calls
+	args := &Args{7, 8}
+	reply := new(Reply)
+	err = client.Call("Arith.Add", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+	}
+}
+
+// CodecEmulator provides a client-like api and a ServerCodec interface.
+// Can be used to test ServeRequest.
+type CodecEmulator struct {
+	server        *Server
+	serviceMethod string
+	args          *Args
+	reply         *Reply
+	err           error
+}
+
+func (codec *CodecEmulator) Call(serviceMethod string, args *Args, reply *Reply) error {
+	codec.serviceMethod = serviceMethod
+	codec.args = args
+	codec.reply = reply
+	codec.err = nil
+	var serverError error
+	if codec.server == nil {
+		serverError = ServeRequest(codec)
+	} else {
+		serverError = codec.server.ServeRequest(codec)
+	}
+	if codec.err == nil && serverError != nil {
+		codec.err = serverError
+	}
+	return codec.err
+}
+
+func (codec *CodecEmulator) ReadRequestHeader(req *Request) error {
+	req.ServiceMethod = codec.serviceMethod
+	req.Seq = 0
+	return nil
+}
+
+func (codec *CodecEmulator) ReadRequestBody(argv interface{}) error {
+	if codec.args == nil {
+		return io.ErrUnexpectedEOF
+	}
+	*(argv.(*Args)) = *codec.args
+	return nil
+}
+
+func (codec *CodecEmulator) WriteResponse(resp *Response, reply interface{}) error {
+	if resp.Error != "" {
+		codec.err = errors.New(resp.Error)
+	} else {
+		*codec.reply = *(reply.(*Reply))
+	}
+	return nil
+}
+
+func (codec *CodecEmulator) Close() error {
+	return nil
+}
+
+func TestServeRequest(t *testing.T) {
+	once.Do(startServer)
+	testServeRequest(t, nil)
+	newOnce.Do(startNewServer)
+	testServeRequest(t, newServer)
+}
+
+func testServeRequest(t *testing.T, server *Server) {
+	client := CodecEmulator{server: server}
+	defer client.Close()
+
+	args := &Args{7, 8}
+	reply := new(Reply)
+	err := client.Call("Arith.Add", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+	}
+
+	err = client.Call("Arith.Add", nil, reply)
+	if err == nil {
+		t.Errorf("expected error calling Arith.Add with nil arg")
+	}
+}
+
+type ReplyNotPointer int
+type ArgNotPublic int
+type ReplyNotPublic int
+type NeedsPtrType int
+type local struct{}
+
+func (t *ReplyNotPointer) ReplyNotPointer(args *Args, reply Reply) error {
+	return nil
+}
+
+func (t *ArgNotPublic) ArgNotPublic(args *local, reply *Reply) error {
+	return nil
+}
+
+func (t *ReplyNotPublic) ReplyNotPublic(args *Args, reply *local) error {
+	return nil
+}
+
+func (t *NeedsPtrType) NeedsPtrType(args *Args, reply *Reply) error {
+	return nil
+}
+
+// Check that registration handles lots of bad methods and a type with no suitable methods.
+func TestRegistrationError(t *testing.T) {
+	err := Register(new(ReplyNotPointer))
+	if err == nil {
+		t.Error("expected error registering ReplyNotPointer")
+	}
+	err = Register(new(ArgNotPublic))
+	if err == nil {
+		t.Error("expected error registering ArgNotPublic")
+	}
+	err = Register(new(ReplyNotPublic))
+	if err == nil {
+		t.Error("expected error registering ReplyNotPublic")
+	}
+	err = Register(NeedsPtrType(0))
+	if err == nil {
+		t.Error("expected error registering NeedsPtrType")
+	} else if !strings.Contains(err.Error(), "pointer") {
+		t.Error("expected hint when registering NeedsPtrType")
+	}
+}
+
+type WriteFailCodec int
+
+func (WriteFailCodec) WriteRequest(*Request, interface{}) error {
+	// the panic caused by this error used to not unlock a lock.
+	return errors.New("fail")
+}
+
+func (WriteFailCodec) ReadResponseHeader(*Response) error {
+	select {}
+}
+
+func (WriteFailCodec) ReadResponseBody(interface{}) error {
+	select {}
+}
+
+func (WriteFailCodec) Close() error {
+	return nil
+}
+
+func TestSendDeadlock(t *testing.T) {
+	client := NewClientWithCodec(WriteFailCodec(0))
+	defer client.Close()
+
+	done := make(chan bool)
+	go func() {
+		testSendDeadlock(client)
+		testSendDeadlock(client)
+		done <- true
+	}()
+	select {
+	case <-done:
+		return
+	case <-time.After(5 * time.Second):
+		t.Fatal("deadlock")
+	}
+}
+
+func testSendDeadlock(client *Client) {
+	defer func() {
+		recover()
+	}()
+	args := &Args{7, 8}
+	reply := new(Reply)
+	client.Call("Arith.Add", args, reply)
+}
+
+func dialDirect() (*Client, error) {
+	return Dial("tcp", serverAddr)
+}
+
+func dialHTTP() (*Client, error) {
+	return DialHTTP("tcp", httpServerAddr)
+}
+
+func countMallocs(dial func() (*Client, error), t *testing.T) float64 {
+	once.Do(startServer)
+	client, err := dial()
+	if err != nil {
+		t.Fatal("error dialing", err)
+	}
+	defer client.Close()
+
+	args := &Args{7, 8}
+	reply := new(Reply)
+	return testing.AllocsPerRun(100, func() {
+		err := client.Call("Arith.Add", args, reply)
+		if err != nil {
+			t.Errorf("Add: expected no error but got string %q", err.Error())
+		}
+		if reply.C != args.A+args.B {
+			t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+		}
+	})
+}
+
+func TestCountMallocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Skip("skipping; GOMAXPROCS>1")
+	}
+	fmt.Printf("mallocs per rpc round trip: %v\n", countMallocs(dialDirect, t))
+}
+
+func TestCountMallocsOverHTTP(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Skip("skipping; GOMAXPROCS>1")
+	}
+	fmt.Printf("mallocs per HTTP rpc round trip: %v\n", countMallocs(dialHTTP, t))
+}
+
+type writeCrasher struct {
+	done chan bool
+}
+
+func (writeCrasher) Close() error {
+	return nil
+}
+
+func (w *writeCrasher) Read(p []byte) (int, error) {
+	<-w.done
+	return 0, io.EOF
+}
+
+func (writeCrasher) Write(p []byte) (int, error) {
+	return 0, errors.New("fake write failure")
+}
+
+func TestClientWriteError(t *testing.T) {
+	w := &writeCrasher{done: make(chan bool)}
+	c := NewClient(w)
+	defer c.Close()
+
+	res := false
+	err := c.Call("foo", 1, &res)
+	if err == nil {
+		t.Fatal("expected error")
+	}
+	if err.Error() != "fake write failure" {
+		t.Error("unexpected value of error:", err)
+	}
+	w.done <- true
+}
+
+func TestTCPClose(t *testing.T) {
+	once.Do(startServer)
+
+	client, err := dialHTTP()
+	if err != nil {
+		t.Fatalf("dialing: %v", err)
+	}
+	defer client.Close()
+
+	args := Args{17, 8}
+	var reply Reply
+	err = client.Call("Arith.Mul", args, &reply)
+	if err != nil {
+		t.Fatal("arith error:", err)
+	}
+	t.Logf("Arith: %d*%d=%d\n", args.A, args.B, reply)
+	if reply.C != args.A*args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A*args.B)
+	}
+}
+
+func TestErrorAfterClientClose(t *testing.T) {
+	once.Do(startServer)
+
+	client, err := dialHTTP()
+	if err != nil {
+		t.Fatalf("dialing: %v", err)
+	}
+	err = client.Close()
+	if err != nil {
+		t.Fatal("close error:", err)
+	}
+	err = client.Call("Arith.Add", &Args{7, 9}, new(Reply))
+	if err != ErrShutdown {
+		t.Errorf("Forever: expected ErrShutdown got %v", err)
+	}
+}
+
+func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
+	once.Do(startServer)
+	client, err := dial()
+	if err != nil {
+		b.Fatal("error dialing:", err)
+	}
+	defer client.Close()
+
+	// Synchronous calls
+	args := &Args{7, 8}
+	b.ResetTimer()
+
+	b.RunParallel(func(pb *testing.PB) {
+		reply := new(Reply)
+		for pb.Next() {
+			err := client.Call("Arith.Add", args, reply)
+			if err != nil {
+				b.Fatalf("rpc error: Add: expected no error but got string %q", err.Error())
+			}
+			if reply.C != args.A+args.B {
+				b.Fatalf("rpc error: Add: expected %d got %d", reply.C, args.A+args.B)
+			}
+		}
+	})
+}
+
+func benchmarkEndToEndAsync(dial func() (*Client, error), b *testing.B) {
+	const MaxConcurrentCalls = 100
+	once.Do(startServer)
+	client, err := dial()
+	if err != nil {
+		b.Fatal("error dialing:", err)
+	}
+	defer client.Close()
+
+	// Asynchronous calls
+	args := &Args{7, 8}
+	procs := 4 * runtime.GOMAXPROCS(-1)
+	send := int32(b.N)
+	recv := int32(b.N)
+	var wg sync.WaitGroup
+	wg.Add(procs)
+	gate := make(chan bool, MaxConcurrentCalls)
+	res := make(chan *Call, MaxConcurrentCalls)
+	b.ResetTimer()
+
+	for p := 0; p < procs; p++ {
+		go func() {
+			for atomic.AddInt32(&send, -1) >= 0 {
+				gate <- true
+				reply := new(Reply)
+				client.Go("Arith.Add", args, reply, res)
+			}
+		}()
+		go func() {
+			for call := range res {
+				A := call.Args.(*Args).A
+				B := call.Args.(*Args).B
+				C := call.Reply.(*Reply).C
+				if A+B != C {
+					b.Fatalf("incorrect reply: Add: expected %d got %d", A+B, C)
+				}
+				<-gate
+				if atomic.AddInt32(&recv, -1) == 0 {
+					close(res)
+				}
+			}
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+
+func BenchmarkEndToEnd(b *testing.B) {
+	benchmarkEndToEnd(dialDirect, b)
+}
+
+func BenchmarkEndToEndHTTP(b *testing.B) {
+	benchmarkEndToEnd(dialHTTP, b)
+}
+
+func BenchmarkEndToEndAsync(b *testing.B) {
+	benchmarkEndToEndAsync(dialDirect, b)
+}
+
+func BenchmarkEndToEndAsyncHTTP(b *testing.B) {
+	benchmarkEndToEndAsync(dialHTTP, b)
+}
diff --git a/third_party/gofrontend/libgo/go/net/sendfile_dragonfly.go b/third_party/gofrontend/libgo/go/net/sendfile_dragonfly.go
new file mode 100644
index 0000000..bc88fd3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sendfile_dragonfly.go
@@ -0,0 +1,103 @@
+// 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.
+
+package net
+
+import (
+	"io"
+	"os"
+	"syscall"
+)
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// sendFile copies the contents of r to c using the sendfile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
+	// DragonFly uses 0 as the "until EOF" value. If you pass in more bytes than the
+	// file contains, it will loop back to the beginning ad nauseam until it's sent
+	// exactly the number of bytes told to. As such, we need to know exactly how many
+	// bytes to send.
+	var remain int64 = 0
+
+	lr, ok := r.(*io.LimitedReader)
+	if ok {
+		remain, r = lr.N, lr.R
+		if remain <= 0 {
+			return 0, nil, true
+		}
+	}
+	f, ok := r.(*os.File)
+	if !ok {
+		return 0, nil, false
+	}
+
+	if remain == 0 {
+		fi, err := f.Stat()
+		if err != nil {
+			return 0, err, false
+		}
+
+		remain = fi.Size()
+	}
+
+	// The other quirk with DragonFly's sendfile implementation is that it doesn't
+	// use the current position of the file -- if you pass it offset 0, it starts
+	// from offset 0. There's no way to tell it "start from current position", so
+	// we have to manage that explicitly.
+	pos, err := f.Seek(0, os.SEEK_CUR)
+	if err != nil {
+		return 0, err, false
+	}
+
+	if err := c.writeLock(); err != nil {
+		return 0, err, true
+	}
+	defer c.writeUnlock()
+
+	dst := c.sysfd
+	src := int(f.Fd())
+	for remain > 0 {
+		n := maxSendfileSize
+		if int64(n) > remain {
+			n = int(remain)
+		}
+		pos1 := pos
+		n, err1 := syscall.Sendfile(dst, src, &pos1, n)
+		if n > 0 {
+			pos += int64(n)
+			written += int64(n)
+			remain -= int64(n)
+		}
+		if n == 0 && err1 == nil {
+			break
+		}
+		if err1 == syscall.EAGAIN {
+			if err1 = c.pd.WaitWrite(); err1 == nil {
+				continue
+			}
+		}
+		if err1 == syscall.EINTR {
+			continue
+		}
+		if err1 != nil {
+			// This includes syscall.ENOSYS (no kernel
+			// support) and syscall.EINVAL (fd types which
+			// don't implement sendfile together)
+			err = &OpError{"sendfile", c.net, c.raddr, err1}
+			break
+		}
+	}
+	if lr != nil {
+		lr.N = remain
+	}
+	return written, err, written > 0
+}
diff --git a/third_party/gofrontend/libgo/go/net/sendfile_freebsd.go b/third_party/gofrontend/libgo/go/net/sendfile_freebsd.go
new file mode 100644
index 0000000..ffc1472
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sendfile_freebsd.go
@@ -0,0 +1,103 @@
+// 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.
+
+package net
+
+import (
+	"io"
+	"os"
+	"syscall"
+)
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// sendFile copies the contents of r to c using the sendfile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
+	// FreeBSD uses 0 as the "until EOF" value. If you pass in more bytes than the
+	// file contains, it will loop back to the beginning ad nauseam until it's sent
+	// exactly the number of bytes told to. As such, we need to know exactly how many
+	// bytes to send.
+	var remain int64 = 0
+
+	lr, ok := r.(*io.LimitedReader)
+	if ok {
+		remain, r = lr.N, lr.R
+		if remain <= 0 {
+			return 0, nil, true
+		}
+	}
+	f, ok := r.(*os.File)
+	if !ok {
+		return 0, nil, false
+	}
+
+	if remain == 0 {
+		fi, err := f.Stat()
+		if err != nil {
+			return 0, err, false
+		}
+
+		remain = fi.Size()
+	}
+
+	// The other quirk with FreeBSD's sendfile implementation is that it doesn't
+	// use the current position of the file -- if you pass it offset 0, it starts
+	// from offset 0. There's no way to tell it "start from current position", so
+	// we have to manage that explicitly.
+	pos, err := f.Seek(0, os.SEEK_CUR)
+	if err != nil {
+		return 0, err, false
+	}
+
+	if err := c.writeLock(); err != nil {
+		return 0, err, true
+	}
+	defer c.writeUnlock()
+
+	dst := c.sysfd
+	src := int(f.Fd())
+	for remain > 0 {
+		n := maxSendfileSize
+		if int64(n) > remain {
+			n = int(remain)
+		}
+		pos1 := pos
+		n, err1 := syscall.Sendfile(dst, src, &pos1, n)
+		if n > 0 {
+			pos += int64(n)
+			written += int64(n)
+			remain -= int64(n)
+		}
+		if n == 0 && err1 == nil {
+			break
+		}
+		if err1 == syscall.EAGAIN {
+			if err1 = c.pd.WaitWrite(); err1 == nil {
+				continue
+			}
+		}
+		if err1 == syscall.EINTR {
+			continue
+		}
+		if err1 != nil {
+			// This includes syscall.ENOSYS (no kernel
+			// support) and syscall.EINVAL (fd types which
+			// don't implement sendfile together)
+			err = &OpError{"sendfile", c.net, c.raddr, err1}
+			break
+		}
+	}
+	if lr != nil {
+		lr.N = remain
+	}
+	return written, err, written > 0
+}
diff --git a/third_party/gofrontend/libgo/go/net/sendfile_linux.go b/third_party/gofrontend/libgo/go/net/sendfile_linux.go
new file mode 100644
index 0000000..5e11763
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sendfile_linux.go
@@ -0,0 +1,76 @@
+// 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.
+
+package net
+
+import (
+	"io"
+	"os"
+	"syscall"
+)
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// sendFile copies the contents of r to c using the sendfile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
+	var remain int64 = 1 << 62 // by default, copy until EOF
+
+	lr, ok := r.(*io.LimitedReader)
+	if ok {
+		remain, r = lr.N, lr.R
+		if remain <= 0 {
+			return 0, nil, true
+		}
+	}
+	f, ok := r.(*os.File)
+	if !ok {
+		return 0, nil, false
+	}
+
+	if err := c.writeLock(); err != nil {
+		return 0, err, true
+	}
+	defer c.writeUnlock()
+
+	dst := c.sysfd
+	src := int(f.Fd())
+	for remain > 0 {
+		n := maxSendfileSize
+		if int64(n) > remain {
+			n = int(remain)
+		}
+		n, err1 := syscall.Sendfile(dst, src, nil, n)
+		if n > 0 {
+			written += int64(n)
+			remain -= int64(n)
+		}
+		if n == 0 && err1 == nil {
+			break
+		}
+		if err1 == syscall.EAGAIN {
+			if err1 = c.pd.WaitWrite(); err1 == nil {
+				continue
+			}
+		}
+		if err1 != nil {
+			// This includes syscall.ENOSYS (no kernel
+			// support) and syscall.EINVAL (fd types which
+			// don't implement sendfile together)
+			err = &OpError{"sendfile", c.net, c.raddr, err1}
+			break
+		}
+	}
+	if lr != nil {
+		lr.N = remain
+	}
+	return written, err, written > 0
+}
diff --git a/third_party/gofrontend/libgo/go/net/sendfile_stub.go b/third_party/gofrontend/libgo/go/net/sendfile_stub.go
new file mode 100644
index 0000000..03426ef
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sendfile_stub.go
@@ -0,0 +1,13 @@
+// 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.
+
+// +build darwin nacl netbsd openbsd solaris
+
+package net
+
+import "io"
+
+func sendFile(c *netFD, r io.Reader) (n int64, err error, handled bool) {
+	return 0, nil, false
+}
diff --git a/third_party/gofrontend/libgo/go/net/sendfile_windows.go b/third_party/gofrontend/libgo/go/net/sendfile_windows.go
new file mode 100644
index 0000000..b128ba2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sendfile_windows.go
@@ -0,0 +1,55 @@
+// 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.
+
+package net
+
+import (
+	"io"
+	"os"
+	"syscall"
+)
+
+// sendFile copies the contents of r to c using the TransmitFile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+//
+// Note that sendfile for windows does not suppport >2GB file.
+func sendFile(fd *netFD, r io.Reader) (written int64, err error, handled bool) {
+	var n int64 = 0 // by default, copy until EOF
+
+	lr, ok := r.(*io.LimitedReader)
+	if ok {
+		n, r = lr.N, lr.R
+		if n <= 0 {
+			return 0, nil, true
+		}
+	}
+	f, ok := r.(*os.File)
+	if !ok {
+		return 0, nil, false
+	}
+
+	if err := fd.writeLock(); err != nil {
+		return 0, err, true
+	}
+	defer fd.writeUnlock()
+
+	o := &fd.wop
+	o.qty = uint32(n)
+	o.handle = syscall.Handle(f.Fd())
+	done, err := wsrv.ExecIO(o, "TransmitFile", func(o *operation) error {
+		return syscall.TransmitFile(o.fd.sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
+	})
+	if err != nil {
+		return 0, err, false
+	}
+	if lr != nil {
+		lr.N -= int64(done)
+	}
+	return int64(done), nil, true
+}
diff --git a/third_party/gofrontend/libgo/go/net/server_test.go b/third_party/gofrontend/libgo/go/net/server_test.go
new file mode 100644
index 0000000..6a2bb92
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/server_test.go
@@ -0,0 +1,461 @@
+// 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 net
+
+import (
+	"flag"
+	"io"
+	"os"
+	"runtime"
+	"testing"
+	"time"
+)
+
+func skipServerTest(net, unixsotype, addr string, ipv6, ipv4map, linuxOnly bool) bool {
+	switch runtime.GOOS {
+	case "linux":
+	case "nacl", "plan9", "windows":
+		// "unix" sockets are not supported on Windows and Plan 9.
+		if net == unixsotype {
+			return true
+		}
+	default:
+		if net == unixsotype && linuxOnly {
+			return true
+		}
+	}
+	switch addr {
+	case "", "0.0.0.0", "[::ffff:0.0.0.0]", "[::]":
+		if testing.Short() || !*testExternal {
+			return true
+		}
+	}
+	if ipv6 && !supportsIPv6 {
+		return true
+	}
+	if ipv4map && !supportsIPv4map {
+		return true
+	}
+	return false
+}
+
+var streamConnServerTests = []struct {
+	snet      string // server side
+	saddr     string
+	cnet      string // client side
+	caddr     string
+	ipv6      bool // test with underlying AF_INET6 socket
+	ipv4map   bool // test with IPv6 IPv4-mapping functionality
+	empty     bool // test with empty data
+	linuxOnly bool // test with abstract unix domain socket, a Linux-ism
+}{
+	{snet: "tcp", saddr: "", cnet: "tcp", caddr: "127.0.0.1"},
+	{snet: "tcp", saddr: "0.0.0.0", cnet: "tcp", caddr: "127.0.0.1"},
+	{snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp", caddr: "127.0.0.1"},
+	{snet: "tcp", saddr: "[::]", cnet: "tcp", caddr: "[::1]", ipv6: true},
+
+	{snet: "tcp", saddr: "", cnet: "tcp", caddr: "[::1]", ipv4map: true},
+	{snet: "tcp", saddr: "0.0.0.0", cnet: "tcp", caddr: "[::1]", ipv4map: true},
+	{snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp", caddr: "[::1]", ipv4map: true},
+	{snet: "tcp", saddr: "[::]", cnet: "tcp", caddr: "127.0.0.1", ipv4map: true},
+
+	{snet: "tcp", saddr: "", cnet: "tcp4", caddr: "127.0.0.1"},
+	{snet: "tcp", saddr: "0.0.0.0", cnet: "tcp4", caddr: "127.0.0.1"},
+	{snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp4", caddr: "127.0.0.1"},
+	{snet: "tcp", saddr: "[::]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
+
+	{snet: "tcp", saddr: "", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
+	{snet: "tcp", saddr: "0.0.0.0", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
+	{snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
+	{snet: "tcp", saddr: "[::]", cnet: "tcp4", caddr: "127.0.0.1", ipv4map: true},
+
+	{snet: "tcp", saddr: "127.0.0.1", cnet: "tcp", caddr: "127.0.0.1"},
+	{snet: "tcp", saddr: "[::ffff:127.0.0.1]", cnet: "tcp", caddr: "127.0.0.1"},
+	{snet: "tcp", saddr: "[::1]", cnet: "tcp", caddr: "[::1]", ipv6: true},
+
+	{snet: "tcp4", saddr: "", cnet: "tcp4", caddr: "127.0.0.1"},
+	{snet: "tcp4", saddr: "0.0.0.0", cnet: "tcp4", caddr: "127.0.0.1"},
+	{snet: "tcp4", saddr: "[::ffff:0.0.0.0]", cnet: "tcp4", caddr: "127.0.0.1"},
+
+	{snet: "tcp4", saddr: "127.0.0.1", cnet: "tcp4", caddr: "127.0.0.1"},
+
+	{snet: "tcp6", saddr: "", cnet: "tcp6", caddr: "[::1]", ipv6: true},
+	{snet: "tcp6", saddr: "[::]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
+
+	{snet: "tcp6", saddr: "[::1]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
+
+	{snet: "unix", saddr: testUnixAddr(), cnet: "unix", caddr: testUnixAddr()},
+	{snet: "unix", saddr: "@gotest2/net", cnet: "unix", caddr: "@gotest2/net.local", linuxOnly: true},
+}
+
+func TestStreamConnServer(t *testing.T) {
+	for _, tt := range streamConnServerTests {
+		if skipServerTest(tt.snet, "unix", tt.saddr, tt.ipv6, tt.ipv4map, tt.linuxOnly) {
+			continue
+		}
+
+		listening := make(chan string)
+		done := make(chan int)
+		switch tt.snet {
+		case "tcp", "tcp4", "tcp6":
+			tt.saddr += ":0"
+		case "unix":
+			os.Remove(tt.saddr)
+			os.Remove(tt.caddr)
+		}
+
+		go runStreamConnServer(t, tt.snet, tt.saddr, listening, done)
+		taddr := <-listening // wait for server to start
+
+		switch tt.cnet {
+		case "tcp", "tcp4", "tcp6":
+			_, port, err := SplitHostPort(taddr)
+			if err != nil {
+				t.Fatalf("SplitHostPort(%q) failed: %v", taddr, err)
+			}
+			taddr = tt.caddr + ":" + port
+		}
+
+		runStreamConnClient(t, tt.cnet, taddr, tt.empty)
+		<-done // make sure server stopped
+
+		switch tt.snet {
+		case "unix":
+			os.Remove(tt.saddr)
+			os.Remove(tt.caddr)
+		}
+	}
+}
+
+var seqpacketConnServerTests = []struct {
+	net       string
+	saddr     string // server address
+	caddr     string // client address
+	empty     bool   // test with empty data
+	linuxOnly bool   // test with abstract unix domain socket, a Linux-ism
+}{
+	{net: "unixpacket", saddr: testUnixAddr(), caddr: testUnixAddr()},
+	{net: "unixpacket", saddr: "@gotest4/net", caddr: "@gotest4/net.local", linuxOnly: true},
+}
+
+func TestSeqpacketConnServer(t *testing.T) {
+	switch runtime.GOOS {
+	case "darwin", "nacl", "openbsd", "plan9", "windows":
+		fallthrough
+	case "freebsd": // FreeBSD 8 doesn't support unixpacket
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	for _, tt := range seqpacketConnServerTests {
+		if runtime.GOOS != "linux" && tt.linuxOnly {
+			continue
+		}
+		listening := make(chan string)
+		done := make(chan int)
+		switch tt.net {
+		case "unixpacket":
+			os.Remove(tt.saddr)
+			os.Remove(tt.caddr)
+		}
+
+		go runStreamConnServer(t, tt.net, tt.saddr, listening, done)
+		taddr := <-listening // wait for server to start
+
+		runStreamConnClient(t, tt.net, taddr, tt.empty)
+		<-done // make sure server stopped
+
+		switch tt.net {
+		case "unixpacket":
+			os.Remove(tt.saddr)
+			os.Remove(tt.caddr)
+		}
+	}
+}
+
+func runStreamConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
+	defer close(done)
+	l, err := Listen(net, laddr)
+	if err != nil {
+		t.Errorf("Listen(%q, %q) failed: %v", net, laddr, err)
+		listening <- "<nil>"
+		return
+	}
+	defer l.Close()
+	listening <- l.Addr().String()
+
+	echo := func(rw io.ReadWriter, done chan<- int) {
+		buf := make([]byte, 1024)
+		for {
+			n, err := rw.Read(buf[0:])
+			if err != nil || n == 0 || string(buf[:n]) == "END" {
+				break
+			}
+			rw.Write(buf[0:n])
+		}
+		close(done)
+	}
+
+run:
+	for {
+		c, err := l.Accept()
+		if err != nil {
+			t.Logf("Accept failed: %v", err)
+			continue run
+		}
+		echodone := make(chan int)
+		go echo(c, echodone)
+		<-echodone // make sure echo stopped
+		c.Close()
+		break run
+	}
+}
+
+func runStreamConnClient(t *testing.T, net, taddr string, isEmpty bool) {
+	c, err := Dial(net, taddr)
+	if err != nil {
+		t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
+	}
+	defer c.Close()
+	c.SetReadDeadline(time.Now().Add(1 * time.Second))
+
+	var wb []byte
+	if !isEmpty {
+		wb = []byte("StreamConnClient by Dial\n")
+	}
+	if n, err := c.Write(wb); err != nil || n != len(wb) {
+		t.Fatalf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
+	}
+
+	rb := make([]byte, 1024)
+	if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
+		t.Fatalf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
+	}
+
+	// Send explicit ending for unixpacket.
+	// Older Linux kernels do not stop reads on close.
+	switch net {
+	case "unixpacket":
+		c.Write([]byte("END"))
+	}
+}
+
+// Do not test empty datagrams by default.
+// It causes unexplained timeouts on some systems,
+// including Snow Leopard.  I think that the kernel
+// doesn't quite expect them.
+var testDatagram = flag.Bool("datagram", false, "whether to test udp and unixgram")
+
+var datagramPacketConnServerTests = []struct {
+	snet      string // server side
+	saddr     string
+	cnet      string // client side
+	caddr     string
+	ipv6      bool // test with underlying AF_INET6 socket
+	ipv4map   bool // test with IPv6 IPv4-mapping functionality
+	dial      bool // test with Dial or DialUnix
+	empty     bool // test with empty data
+	linuxOnly bool // test with abstract unix domain socket, a Linux-ism
+}{
+	{snet: "udp", saddr: "", cnet: "udp", caddr: "127.0.0.1"},
+	{snet: "udp", saddr: "0.0.0.0", cnet: "udp", caddr: "127.0.0.1"},
+	{snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp", caddr: "127.0.0.1"},
+	{snet: "udp", saddr: "[::]", cnet: "udp", caddr: "[::1]", ipv6: true},
+
+	{snet: "udp", saddr: "", cnet: "udp", caddr: "[::1]", ipv4map: true},
+	{snet: "udp", saddr: "0.0.0.0", cnet: "udp", caddr: "[::1]", ipv4map: true},
+	{snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp", caddr: "[::1]", ipv4map: true},
+	{snet: "udp", saddr: "[::]", cnet: "udp", caddr: "127.0.0.1", ipv4map: true},
+
+	{snet: "udp", saddr: "", cnet: "udp4", caddr: "127.0.0.1"},
+	{snet: "udp", saddr: "0.0.0.0", cnet: "udp4", caddr: "127.0.0.1"},
+	{snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp4", caddr: "127.0.0.1"},
+	{snet: "udp", saddr: "[::]", cnet: "udp6", caddr: "[::1]", ipv6: true},
+
+	{snet: "udp", saddr: "", cnet: "udp6", caddr: "[::1]", ipv4map: true},
+	{snet: "udp", saddr: "0.0.0.0", cnet: "udp6", caddr: "[::1]", ipv4map: true},
+	{snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp6", caddr: "[::1]", ipv4map: true},
+	{snet: "udp", saddr: "[::]", cnet: "udp4", caddr: "127.0.0.1", ipv4map: true},
+
+	{snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1"},
+	{snet: "udp", saddr: "[::ffff:127.0.0.1]", cnet: "udp", caddr: "127.0.0.1"},
+	{snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true},
+
+	{snet: "udp4", saddr: "", cnet: "udp4", caddr: "127.0.0.1"},
+	{snet: "udp4", saddr: "0.0.0.0", cnet: "udp4", caddr: "127.0.0.1"},
+	{snet: "udp4", saddr: "[::ffff:0.0.0.0]", cnet: "udp4", caddr: "127.0.0.1"},
+
+	{snet: "udp4", saddr: "127.0.0.1", cnet: "udp4", caddr: "127.0.0.1"},
+
+	{snet: "udp6", saddr: "", cnet: "udp6", caddr: "[::1]", ipv6: true},
+	{snet: "udp6", saddr: "[::]", cnet: "udp6", caddr: "[::1]", ipv6: true},
+
+	{snet: "udp6", saddr: "[::1]", cnet: "udp6", caddr: "[::1]", ipv6: true},
+
+	{snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", dial: true},
+	{snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", empty: true},
+	{snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", dial: true, empty: true},
+
+	{snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, dial: true},
+	{snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, empty: true},
+	{snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, dial: true, empty: true},
+
+	{snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr()},
+	{snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), dial: true},
+	{snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), empty: true},
+	{snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), dial: true, empty: true},
+
+	{snet: "unixgram", saddr: "@gotest6/net", cnet: "unixgram", caddr: "@gotest6/net.local", linuxOnly: true},
+}
+
+func TestDatagramPacketConnServer(t *testing.T) {
+	if !*testDatagram {
+		return
+	}
+
+	for _, tt := range datagramPacketConnServerTests {
+		if skipServerTest(tt.snet, "unixgram", tt.saddr, tt.ipv6, tt.ipv4map, tt.linuxOnly) {
+			continue
+		}
+
+		listening := make(chan string)
+		done := make(chan int)
+		switch tt.snet {
+		case "udp", "udp4", "udp6":
+			tt.saddr += ":0"
+		case "unixgram":
+			os.Remove(tt.saddr)
+			os.Remove(tt.caddr)
+		}
+
+		go runDatagramPacketConnServer(t, tt.snet, tt.saddr, listening, done)
+		taddr := <-listening // wait for server to start
+
+		switch tt.cnet {
+		case "udp", "udp4", "udp6":
+			_, port, err := SplitHostPort(taddr)
+			if err != nil {
+				t.Fatalf("SplitHostPort(%q) failed: %v", taddr, err)
+			}
+			taddr = tt.caddr + ":" + port
+			tt.caddr += ":0"
+		}
+		if tt.dial {
+			runDatagramConnClient(t, tt.cnet, tt.caddr, taddr, tt.empty)
+		} else {
+			runDatagramPacketConnClient(t, tt.cnet, tt.caddr, taddr, tt.empty)
+		}
+		<-done // tell server to stop
+		<-done // make sure server stopped
+
+		switch tt.snet {
+		case "unixgram":
+			os.Remove(tt.saddr)
+			os.Remove(tt.caddr)
+		}
+	}
+}
+
+func runDatagramPacketConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
+	c, err := ListenPacket(net, laddr)
+	if err != nil {
+		t.Errorf("ListenPacket(%q, %q) failed: %v", net, laddr, err)
+		listening <- "<nil>"
+		done <- 1
+		return
+	}
+	defer c.Close()
+	listening <- c.LocalAddr().String()
+
+	buf := make([]byte, 1024)
+run:
+	for {
+		c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
+		n, ra, err := c.ReadFrom(buf[0:])
+		if nerr, ok := err.(Error); ok && nerr.Timeout() {
+			select {
+			case done <- 1:
+				break run
+			default:
+				continue run
+			}
+		}
+		if err != nil {
+			break run
+		}
+		if _, err = c.WriteTo(buf[0:n], ra); err != nil {
+			t.Errorf("WriteTo(%v) failed: %v", ra, err)
+			break run
+		}
+	}
+	done <- 1
+}
+
+func runDatagramConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool) {
+	var c Conn
+	var err error
+	switch net {
+	case "udp", "udp4", "udp6":
+		c, err = Dial(net, taddr)
+		if err != nil {
+			t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
+		}
+	case "unixgram":
+		c, err = DialUnix(net, &UnixAddr{Name: laddr, Net: net}, &UnixAddr{Name: taddr, Net: net})
+		if err != nil {
+			t.Fatalf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err)
+		}
+	}
+	defer c.Close()
+	c.SetReadDeadline(time.Now().Add(1 * time.Second))
+
+	var wb []byte
+	if !isEmpty {
+		wb = []byte("DatagramConnClient by Dial\n")
+	}
+	if n, err := c.Write(wb[0:]); err != nil || n != len(wb) {
+		t.Fatalf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
+	}
+
+	rb := make([]byte, 1024)
+	if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
+		t.Fatalf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
+	}
+}
+
+func runDatagramPacketConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool) {
+	var ra Addr
+	var err error
+	switch net {
+	case "udp", "udp4", "udp6":
+		ra, err = ResolveUDPAddr(net, taddr)
+		if err != nil {
+			t.Fatalf("ResolveUDPAddr(%q, %q) failed: %v", net, taddr, err)
+		}
+	case "unixgram":
+		ra, err = ResolveUnixAddr(net, taddr)
+		if err != nil {
+			t.Fatalf("ResolveUxixAddr(%q, %q) failed: %v", net, taddr, err)
+		}
+	}
+	c, err := ListenPacket(net, laddr)
+	if err != nil {
+		t.Fatalf("ListenPacket(%q, %q) faild: %v", net, laddr, err)
+	}
+	defer c.Close()
+	c.SetReadDeadline(time.Now().Add(1 * time.Second))
+
+	var wb []byte
+	if !isEmpty {
+		wb = []byte("DatagramPacketConnClient by ListenPacket\n")
+	}
+	if n, err := c.WriteTo(wb[0:], ra); err != nil || n != len(wb) {
+		t.Fatalf("WriteTo(%v) failed: %v, %v; want %v, <nil>", ra, n, err, len(wb))
+	}
+
+	rb := make([]byte, 1024)
+	if n, _, err := c.ReadFrom(rb[0:]); err != nil || n != len(wb) {
+		t.Fatalf("ReadFrom failed: %v, %v; want %v, <nil>", n, err, len(wb))
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/singleflight.go b/third_party/gofrontend/libgo/go/net/singleflight.go
new file mode 100644
index 0000000..dc58aff
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/singleflight.go
@@ -0,0 +1,53 @@
+// Copyright 2013 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 net
+
+import "sync"
+
+// call is an in-flight or completed singleflight.Do call
+type call struct {
+	wg   sync.WaitGroup
+	val  interface{}
+	err  error
+	dups int
+}
+
+// singleflight represents a class of work and forms a namespace in
+// which units of work can be executed with duplicate suppression.
+type singleflight struct {
+	mu sync.Mutex       // protects m
+	m  map[string]*call // lazily initialized
+}
+
+// Do executes and returns the results of the given function, making
+// sure that only one execution is in-flight for a given key at a
+// time. If a duplicate comes in, the duplicate caller waits for the
+// original to complete and receives the same results.
+// The return value shared indicates whether v was given to multiple callers.
+func (g *singleflight) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {
+	g.mu.Lock()
+	if g.m == nil {
+		g.m = make(map[string]*call)
+	}
+	if c, ok := g.m[key]; ok {
+		c.dups++
+		g.mu.Unlock()
+		c.wg.Wait()
+		return c.val, c.err, true
+	}
+	c := new(call)
+	c.wg.Add(1)
+	g.m[key] = c
+	g.mu.Unlock()
+
+	c.val, c.err = fn()
+	c.wg.Done()
+
+	g.mu.Lock()
+	delete(g.m, key)
+	g.mu.Unlock()
+
+	return c.val, c.err, c.dups > 0
+}
diff --git a/third_party/gofrontend/libgo/go/net/smtp/auth.go b/third_party/gofrontend/libgo/go/net/smtp/auth.go
new file mode 100644
index 0000000..3f1339e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/smtp/auth.go
@@ -0,0 +1,107 @@
+// Copyright 2010 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 smtp
+
+import (
+	"crypto/hmac"
+	"crypto/md5"
+	"errors"
+	"fmt"
+)
+
+// Auth is implemented by an SMTP authentication mechanism.
+type Auth interface {
+	// Start begins an authentication with a server.
+	// It returns the name of the authentication protocol
+	// and optionally data to include in the initial AUTH message
+	// sent to the server. It can return proto == "" to indicate
+	// that the authentication should be skipped.
+	// If it returns a non-nil error, the SMTP client aborts
+	// the authentication attempt and closes the connection.
+	Start(server *ServerInfo) (proto string, toServer []byte, err error)
+
+	// Next continues the authentication. The server has just sent
+	// the fromServer data. If more is true, the server expects a
+	// response, which Next should return as toServer; otherwise
+	// Next should return toServer == nil.
+	// If Next returns a non-nil error, the SMTP client aborts
+	// the authentication attempt and closes the connection.
+	Next(fromServer []byte, more bool) (toServer []byte, err error)
+}
+
+// ServerInfo records information about an SMTP server.
+type ServerInfo struct {
+	Name string   // SMTP server name
+	TLS  bool     // using TLS, with valid certificate for Name
+	Auth []string // advertised authentication mechanisms
+}
+
+type plainAuth struct {
+	identity, username, password string
+	host                         string
+}
+
+// PlainAuth returns an Auth that implements the PLAIN authentication
+// mechanism as defined in RFC 4616.
+// The returned Auth uses the given username and password to authenticate
+// on TLS connections to host and act as identity. Usually identity will be
+// left blank to act as username.
+func PlainAuth(identity, username, password, host string) Auth {
+	return &plainAuth{identity, username, password, host}
+}
+
+func (a *plainAuth) Start(server *ServerInfo) (string, []byte, error) {
+	if !server.TLS {
+		advertised := false
+		for _, mechanism := range server.Auth {
+			if mechanism == "PLAIN" {
+				advertised = true
+				break
+			}
+		}
+		if !advertised {
+			return "", nil, errors.New("unencrypted connection")
+		}
+	}
+	if server.Name != a.host {
+		return "", nil, errors.New("wrong host name")
+	}
+	resp := []byte(a.identity + "\x00" + a.username + "\x00" + a.password)
+	return "PLAIN", resp, nil
+}
+
+func (a *plainAuth) Next(fromServer []byte, more bool) ([]byte, error) {
+	if more {
+		// We've already sent everything.
+		return nil, errors.New("unexpected server challenge")
+	}
+	return nil, nil
+}
+
+type cramMD5Auth struct {
+	username, secret string
+}
+
+// CRAMMD5Auth returns an Auth that implements the CRAM-MD5 authentication
+// mechanism as defined in RFC 2195.
+// The returned Auth uses the given username and secret to authenticate
+// to the server using the challenge-response mechanism.
+func CRAMMD5Auth(username, secret string) Auth {
+	return &cramMD5Auth{username, secret}
+}
+
+func (a *cramMD5Auth) Start(server *ServerInfo) (string, []byte, error) {
+	return "CRAM-MD5", nil, nil
+}
+
+func (a *cramMD5Auth) Next(fromServer []byte, more bool) ([]byte, error) {
+	if more {
+		d := hmac.New(md5.New, []byte(a.secret))
+		d.Write(fromServer)
+		s := make([]byte, 0, d.Size())
+		return []byte(fmt.Sprintf("%s %x", a.username, d.Sum(s))), nil
+	}
+	return nil, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/smtp/smtp.go b/third_party/gofrontend/libgo/go/net/smtp/smtp.go
new file mode 100644
index 0000000..87dea44
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/smtp/smtp.go
@@ -0,0 +1,357 @@
+// Copyright 2010 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 smtp implements the Simple Mail Transfer Protocol as defined in RFC 5321.
+// It also implements the following extensions:
+//	8BITMIME  RFC 1652
+//	AUTH      RFC 2554
+//	STARTTLS  RFC 3207
+// Additional extensions may be handled by clients.
+package smtp
+
+import (
+	"crypto/tls"
+	"encoding/base64"
+	"errors"
+	"io"
+	"net"
+	"net/textproto"
+	"strings"
+)
+
+// A Client represents a client connection to an SMTP server.
+type Client struct {
+	// Text is the textproto.Conn used by the Client. It is exported to allow for
+	// clients to add extensions.
+	Text *textproto.Conn
+	// keep a reference to the connection so it can be used to create a TLS
+	// connection later
+	conn net.Conn
+	// whether the Client is using TLS
+	tls        bool
+	serverName string
+	// map of supported extensions
+	ext map[string]string
+	// supported auth mechanisms
+	auth       []string
+	localName  string // the name to use in HELO/EHLO
+	didHello   bool   // whether we've said HELO/EHLO
+	helloError error  // the error from the hello
+}
+
+// Dial returns a new Client connected to an SMTP server at addr.
+// The addr must include a port number.
+func Dial(addr string) (*Client, error) {
+	conn, err := net.Dial("tcp", addr)
+	if err != nil {
+		return nil, err
+	}
+	host, _, _ := net.SplitHostPort(addr)
+	return NewClient(conn, host)
+}
+
+// NewClient returns a new Client using an existing connection and host as a
+// server name to be used when authenticating.
+func NewClient(conn net.Conn, host string) (*Client, error) {
+	text := textproto.NewConn(conn)
+	_, _, err := text.ReadResponse(220)
+	if err != nil {
+		text.Close()
+		return nil, err
+	}
+	c := &Client{Text: text, conn: conn, serverName: host, localName: "localhost"}
+	return c, nil
+}
+
+// Close closes the connection.
+func (c *Client) Close() error {
+	return c.Text.Close()
+}
+
+// hello runs a hello exchange if needed.
+func (c *Client) hello() error {
+	if !c.didHello {
+		c.didHello = true
+		err := c.ehlo()
+		if err != nil {
+			c.helloError = c.helo()
+		}
+	}
+	return c.helloError
+}
+
+// Hello sends a HELO or EHLO to the server as the given host name.
+// Calling this method is only necessary if the client needs control
+// over the host name used.  The client will introduce itself as "localhost"
+// automatically otherwise.  If Hello is called, it must be called before
+// any of the other methods.
+func (c *Client) Hello(localName string) error {
+	if c.didHello {
+		return errors.New("smtp: Hello called after other methods")
+	}
+	c.localName = localName
+	return c.hello()
+}
+
+// cmd is a convenience function that sends a command and returns the response
+func (c *Client) cmd(expectCode int, format string, args ...interface{}) (int, string, error) {
+	id, err := c.Text.Cmd(format, args...)
+	if err != nil {
+		return 0, "", err
+	}
+	c.Text.StartResponse(id)
+	defer c.Text.EndResponse(id)
+	code, msg, err := c.Text.ReadResponse(expectCode)
+	return code, msg, err
+}
+
+// helo sends the HELO greeting to the server. It should be used only when the
+// server does not support ehlo.
+func (c *Client) helo() error {
+	c.ext = nil
+	_, _, err := c.cmd(250, "HELO %s", c.localName)
+	return err
+}
+
+// ehlo sends the EHLO (extended hello) greeting to the server. It
+// should be the preferred greeting for servers that support it.
+func (c *Client) ehlo() error {
+	_, msg, err := c.cmd(250, "EHLO %s", c.localName)
+	if err != nil {
+		return err
+	}
+	ext := make(map[string]string)
+	extList := strings.Split(msg, "\n")
+	if len(extList) > 1 {
+		extList = extList[1:]
+		for _, line := range extList {
+			args := strings.SplitN(line, " ", 2)
+			if len(args) > 1 {
+				ext[args[0]] = args[1]
+			} else {
+				ext[args[0]] = ""
+			}
+		}
+	}
+	if mechs, ok := ext["AUTH"]; ok {
+		c.auth = strings.Split(mechs, " ")
+	}
+	c.ext = ext
+	return err
+}
+
+// StartTLS sends the STARTTLS command and encrypts all further communication.
+// Only servers that advertise the STARTTLS extension support this function.
+func (c *Client) StartTLS(config *tls.Config) error {
+	if err := c.hello(); err != nil {
+		return err
+	}
+	_, _, err := c.cmd(220, "STARTTLS")
+	if err != nil {
+		return err
+	}
+	c.conn = tls.Client(c.conn, config)
+	c.Text = textproto.NewConn(c.conn)
+	c.tls = true
+	return c.ehlo()
+}
+
+// Verify checks the validity of an email address on the server.
+// If Verify returns nil, the address is valid. A non-nil return
+// does not necessarily indicate an invalid address. Many servers
+// will not verify addresses for security reasons.
+func (c *Client) Verify(addr string) error {
+	if err := c.hello(); err != nil {
+		return err
+	}
+	_, _, err := c.cmd(250, "VRFY %s", addr)
+	return err
+}
+
+// Auth authenticates a client using the provided authentication mechanism.
+// A failed authentication closes the connection.
+// Only servers that advertise the AUTH extension support this function.
+func (c *Client) Auth(a Auth) error {
+	if err := c.hello(); err != nil {
+		return err
+	}
+	encoding := base64.StdEncoding
+	mech, resp, err := a.Start(&ServerInfo{c.serverName, c.tls, c.auth})
+	if err != nil {
+		c.Quit()
+		return err
+	}
+	resp64 := make([]byte, encoding.EncodedLen(len(resp)))
+	encoding.Encode(resp64, resp)
+	code, msg64, err := c.cmd(0, "AUTH %s %s", mech, resp64)
+	for err == nil {
+		var msg []byte
+		switch code {
+		case 334:
+			msg, err = encoding.DecodeString(msg64)
+		case 235:
+			// the last message isn't base64 because it isn't a challenge
+			msg = []byte(msg64)
+		default:
+			err = &textproto.Error{Code: code, Msg: msg64}
+		}
+		if err == nil {
+			resp, err = a.Next(msg, code == 334)
+		}
+		if err != nil {
+			// abort the AUTH
+			c.cmd(501, "*")
+			c.Quit()
+			break
+		}
+		if resp == nil {
+			break
+		}
+		resp64 = make([]byte, encoding.EncodedLen(len(resp)))
+		encoding.Encode(resp64, resp)
+		code, msg64, err = c.cmd(0, string(resp64))
+	}
+	return err
+}
+
+// Mail issues a MAIL command to the server using the provided email address.
+// If the server supports the 8BITMIME extension, Mail adds the BODY=8BITMIME
+// parameter.
+// This initiates a mail transaction and is followed by one or more Rcpt calls.
+func (c *Client) Mail(from string) error {
+	if err := c.hello(); err != nil {
+		return err
+	}
+	cmdStr := "MAIL FROM:<%s>"
+	if c.ext != nil {
+		if _, ok := c.ext["8BITMIME"]; ok {
+			cmdStr += " BODY=8BITMIME"
+		}
+	}
+	_, _, err := c.cmd(250, cmdStr, from)
+	return err
+}
+
+// Rcpt issues a RCPT command to the server using the provided email address.
+// A call to Rcpt must be preceded by a call to Mail and may be followed by
+// a Data call or another Rcpt call.
+func (c *Client) Rcpt(to string) error {
+	_, _, err := c.cmd(25, "RCPT TO:<%s>", to)
+	return err
+}
+
+type dataCloser struct {
+	c *Client
+	io.WriteCloser
+}
+
+func (d *dataCloser) Close() error {
+	d.WriteCloser.Close()
+	_, _, err := d.c.Text.ReadResponse(250)
+	return err
+}
+
+// Data issues a DATA command to the server and returns a writer that
+// can be used to write the data. The caller should close the writer
+// before calling any more methods on c.
+// A call to Data must be preceded by one or more calls to Rcpt.
+func (c *Client) Data() (io.WriteCloser, error) {
+	_, _, err := c.cmd(354, "DATA")
+	if err != nil {
+		return nil, err
+	}
+	return &dataCloser{c, c.Text.DotWriter()}, nil
+}
+
+var testHookStartTLS func(*tls.Config) // nil, except for tests
+
+// SendMail connects to the server at addr, switches to TLS if
+// possible, authenticates with the optional mechanism a if possible,
+// and then sends an email from address from, to addresses to, with
+// message msg.
+func SendMail(addr string, a Auth, from string, to []string, msg []byte) error {
+	c, err := Dial(addr)
+	if err != nil {
+		return err
+	}
+	defer c.Close()
+	if err = c.hello(); err != nil {
+		return err
+	}
+	if ok, _ := c.Extension("STARTTLS"); ok {
+		config := &tls.Config{ServerName: c.serverName}
+		if testHookStartTLS != nil {
+			testHookStartTLS(config)
+		}
+		if err = c.StartTLS(config); err != nil {
+			return err
+		}
+	}
+	if a != nil && c.ext != nil {
+		if _, ok := c.ext["AUTH"]; ok {
+			if err = c.Auth(a); err != nil {
+				return err
+			}
+		}
+	}
+	if err = c.Mail(from); err != nil {
+		return err
+	}
+	for _, addr := range to {
+		if err = c.Rcpt(addr); err != nil {
+			return err
+		}
+	}
+	w, err := c.Data()
+	if err != nil {
+		return err
+	}
+	_, err = w.Write(msg)
+	if err != nil {
+		return err
+	}
+	err = w.Close()
+	if err != nil {
+		return err
+	}
+	return c.Quit()
+}
+
+// Extension reports whether an extension is support by the server.
+// The extension name is case-insensitive. If the extension is supported,
+// Extension also returns a string that contains any parameters the
+// server specifies for the extension.
+func (c *Client) Extension(ext string) (bool, string) {
+	if err := c.hello(); err != nil {
+		return false, ""
+	}
+	if c.ext == nil {
+		return false, ""
+	}
+	ext = strings.ToUpper(ext)
+	param, ok := c.ext[ext]
+	return ok, param
+}
+
+// Reset sends the RSET command to the server, aborting the current mail
+// transaction.
+func (c *Client) Reset() error {
+	if err := c.hello(); err != nil {
+		return err
+	}
+	_, _, err := c.cmd(250, "RSET")
+	return err
+}
+
+// Quit sends the QUIT command and closes the connection to the server.
+func (c *Client) Quit() error {
+	if err := c.hello(); err != nil {
+		return err
+	}
+	_, _, err := c.cmd(221, "QUIT")
+	if err != nil {
+		return err
+	}
+	return c.Text.Close()
+}
diff --git a/third_party/gofrontend/libgo/go/net/smtp/smtp_test.go b/third_party/gofrontend/libgo/go/net/smtp/smtp_test.go
new file mode 100644
index 0000000..3fba1ea
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/smtp/smtp_test.go
@@ -0,0 +1,694 @@
+// Copyright 2010 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 smtp
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/tls"
+	"crypto/x509"
+	"io"
+	"net"
+	"net/textproto"
+	"strings"
+	"testing"
+	"time"
+)
+
+type authTest struct {
+	auth       Auth
+	challenges []string
+	name       string
+	responses  []string
+}
+
+var authTests = []authTest{
+	{PlainAuth("", "user", "pass", "testserver"), []string{}, "PLAIN", []string{"\x00user\x00pass"}},
+	{PlainAuth("foo", "bar", "baz", "testserver"), []string{}, "PLAIN", []string{"foo\x00bar\x00baz"}},
+	{CRAMMD5Auth("user", "pass"), []string{"<123456.1322876914@testserver>"}, "CRAM-MD5", []string{"", "user 287eb355114cf5c471c26a875f1ca4ae"}},
+}
+
+func TestAuth(t *testing.T) {
+testLoop:
+	for i, test := range authTests {
+		name, resp, err := test.auth.Start(&ServerInfo{"testserver", true, nil})
+		if name != test.name {
+			t.Errorf("#%d got name %s, expected %s", i, name, test.name)
+		}
+		if !bytes.Equal(resp, []byte(test.responses[0])) {
+			t.Errorf("#%d got response %s, expected %s", i, resp, test.responses[0])
+		}
+		if err != nil {
+			t.Errorf("#%d error: %s", i, err)
+		}
+		for j := range test.challenges {
+			challenge := []byte(test.challenges[j])
+			expected := []byte(test.responses[j+1])
+			resp, err := test.auth.Next(challenge, true)
+			if err != nil {
+				t.Errorf("#%d error: %s", i, err)
+				continue testLoop
+			}
+			if !bytes.Equal(resp, expected) {
+				t.Errorf("#%d got %s, expected %s", i, resp, expected)
+				continue testLoop
+			}
+		}
+	}
+}
+
+func TestAuthPlain(t *testing.T) {
+	auth := PlainAuth("foo", "bar", "baz", "servername")
+
+	tests := []struct {
+		server *ServerInfo
+		err    string
+	}{
+		{
+			server: &ServerInfo{Name: "servername", TLS: true},
+		},
+		{
+			// Okay; explicitly advertised by server.
+			server: &ServerInfo{Name: "servername", Auth: []string{"PLAIN"}},
+		},
+		{
+			server: &ServerInfo{Name: "servername", Auth: []string{"CRAM-MD5"}},
+			err:    "unencrypted connection",
+		},
+		{
+			server: &ServerInfo{Name: "attacker", TLS: true},
+			err:    "wrong host name",
+		},
+	}
+	for i, tt := range tests {
+		_, _, err := auth.Start(tt.server)
+		got := ""
+		if err != nil {
+			got = err.Error()
+		}
+		if got != tt.err {
+			t.Errorf("%d. got error = %q; want %q", i, got, tt.err)
+		}
+	}
+}
+
+type faker struct {
+	io.ReadWriter
+}
+
+func (f faker) Close() error                     { return nil }
+func (f faker) LocalAddr() net.Addr              { return nil }
+func (f faker) RemoteAddr() net.Addr             { return nil }
+func (f faker) SetDeadline(time.Time) error      { return nil }
+func (f faker) SetReadDeadline(time.Time) error  { return nil }
+func (f faker) SetWriteDeadline(time.Time) error { return nil }
+
+func TestBasic(t *testing.T) {
+	server := strings.Join(strings.Split(basicServer, "\n"), "\r\n")
+	client := strings.Join(strings.Split(basicClient, "\n"), "\r\n")
+
+	var cmdbuf bytes.Buffer
+	bcmdbuf := bufio.NewWriter(&cmdbuf)
+	var fake faker
+	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
+	c := &Client{Text: textproto.NewConn(fake), localName: "localhost"}
+
+	if err := c.helo(); err != nil {
+		t.Fatalf("HELO failed: %s", err)
+	}
+	if err := c.ehlo(); err == nil {
+		t.Fatalf("Expected first EHLO to fail")
+	}
+	if err := c.ehlo(); err != nil {
+		t.Fatalf("Second EHLO failed: %s", err)
+	}
+
+	c.didHello = true
+	if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" {
+		t.Fatalf("Expected AUTH supported")
+	}
+	if ok, _ := c.Extension("DSN"); ok {
+		t.Fatalf("Shouldn't support DSN")
+	}
+
+	if err := c.Mail("user@gmail.com"); err == nil {
+		t.Fatalf("MAIL should require authentication")
+	}
+
+	if err := c.Verify("user1@gmail.com"); err == nil {
+		t.Fatalf("First VRFY: expected no verification")
+	}
+	if err := c.Verify("user2@gmail.com"); err != nil {
+		t.Fatalf("Second VRFY: expected verification, got %s", err)
+	}
+
+	// fake TLS so authentication won't complain
+	c.tls = true
+	c.serverName = "smtp.google.com"
+	if err := c.Auth(PlainAuth("", "user", "pass", "smtp.google.com")); err != nil {
+		t.Fatalf("AUTH failed: %s", err)
+	}
+
+	if err := c.Mail("user@gmail.com"); err != nil {
+		t.Fatalf("MAIL failed: %s", err)
+	}
+	if err := c.Rcpt("golang-nuts@googlegroups.com"); err != nil {
+		t.Fatalf("RCPT failed: %s", err)
+	}
+	msg := `From: user@gmail.com
+To: golang-nuts@googlegroups.com
+Subject: Hooray for Go
+
+Line 1
+.Leading dot line .
+Goodbye.`
+	w, err := c.Data()
+	if err != nil {
+		t.Fatalf("DATA failed: %s", err)
+	}
+	if _, err := w.Write([]byte(msg)); err != nil {
+		t.Fatalf("Data write failed: %s", err)
+	}
+	if err := w.Close(); err != nil {
+		t.Fatalf("Bad data response: %s", err)
+	}
+
+	if err := c.Quit(); err != nil {
+		t.Fatalf("QUIT failed: %s", err)
+	}
+
+	bcmdbuf.Flush()
+	actualcmds := cmdbuf.String()
+	if client != actualcmds {
+		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client)
+	}
+}
+
+var basicServer = `250 mx.google.com at your service
+502 Unrecognized command.
+250-mx.google.com at your service
+250-SIZE 35651584
+250-AUTH LOGIN PLAIN
+250 8BITMIME
+530 Authentication required
+252 Send some mail, I'll try my best
+250 User is valid
+235 Accepted
+250 Sender OK
+250 Receiver OK
+354 Go ahead
+250 Data OK
+221 OK
+`
+
+var basicClient = `HELO localhost
+EHLO localhost
+EHLO localhost
+MAIL FROM:<user@gmail.com> BODY=8BITMIME
+VRFY user1@gmail.com
+VRFY user2@gmail.com
+AUTH PLAIN AHVzZXIAcGFzcw==
+MAIL FROM:<user@gmail.com> BODY=8BITMIME
+RCPT TO:<golang-nuts@googlegroups.com>
+DATA
+From: user@gmail.com
+To: golang-nuts@googlegroups.com
+Subject: Hooray for Go
+
+Line 1
+..Leading dot line .
+Goodbye.
+.
+QUIT
+`
+
+func TestNewClient(t *testing.T) {
+	server := strings.Join(strings.Split(newClientServer, "\n"), "\r\n")
+	client := strings.Join(strings.Split(newClientClient, "\n"), "\r\n")
+
+	var cmdbuf bytes.Buffer
+	bcmdbuf := bufio.NewWriter(&cmdbuf)
+	out := func() string {
+		bcmdbuf.Flush()
+		return cmdbuf.String()
+	}
+	var fake faker
+	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
+	c, err := NewClient(fake, "fake.host")
+	if err != nil {
+		t.Fatalf("NewClient: %v\n(after %v)", err, out())
+	}
+	defer c.Close()
+	if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" {
+		t.Fatalf("Expected AUTH supported")
+	}
+	if ok, _ := c.Extension("DSN"); ok {
+		t.Fatalf("Shouldn't support DSN")
+	}
+	if err := c.Quit(); err != nil {
+		t.Fatalf("QUIT failed: %s", err)
+	}
+
+	actualcmds := out()
+	if client != actualcmds {
+		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client)
+	}
+}
+
+var newClientServer = `220 hello world
+250-mx.google.com at your service
+250-SIZE 35651584
+250-AUTH LOGIN PLAIN
+250 8BITMIME
+221 OK
+`
+
+var newClientClient = `EHLO localhost
+QUIT
+`
+
+func TestNewClient2(t *testing.T) {
+	server := strings.Join(strings.Split(newClient2Server, "\n"), "\r\n")
+	client := strings.Join(strings.Split(newClient2Client, "\n"), "\r\n")
+
+	var cmdbuf bytes.Buffer
+	bcmdbuf := bufio.NewWriter(&cmdbuf)
+	var fake faker
+	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
+	c, err := NewClient(fake, "fake.host")
+	if err != nil {
+		t.Fatalf("NewClient: %v", err)
+	}
+	defer c.Close()
+	if ok, _ := c.Extension("DSN"); ok {
+		t.Fatalf("Shouldn't support DSN")
+	}
+	if err := c.Quit(); err != nil {
+		t.Fatalf("QUIT failed: %s", err)
+	}
+
+	bcmdbuf.Flush()
+	actualcmds := cmdbuf.String()
+	if client != actualcmds {
+		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client)
+	}
+}
+
+var newClient2Server = `220 hello world
+502 EH?
+250-mx.google.com at your service
+250-SIZE 35651584
+250-AUTH LOGIN PLAIN
+250 8BITMIME
+221 OK
+`
+
+var newClient2Client = `EHLO localhost
+HELO localhost
+QUIT
+`
+
+func TestHello(t *testing.T) {
+
+	if len(helloServer) != len(helloClient) {
+		t.Fatalf("Hello server and client size mismatch")
+	}
+
+	for i := 0; i < len(helloServer); i++ {
+		server := strings.Join(strings.Split(baseHelloServer+helloServer[i], "\n"), "\r\n")
+		client := strings.Join(strings.Split(baseHelloClient+helloClient[i], "\n"), "\r\n")
+		var cmdbuf bytes.Buffer
+		bcmdbuf := bufio.NewWriter(&cmdbuf)
+		var fake faker
+		fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
+		c, err := NewClient(fake, "fake.host")
+		if err != nil {
+			t.Fatalf("NewClient: %v", err)
+		}
+		defer c.Close()
+		c.localName = "customhost"
+		err = nil
+
+		switch i {
+		case 0:
+			err = c.Hello("customhost")
+		case 1:
+			err = c.StartTLS(nil)
+			if err.Error() == "502 Not implemented" {
+				err = nil
+			}
+		case 2:
+			err = c.Verify("test@example.com")
+		case 3:
+			c.tls = true
+			c.serverName = "smtp.google.com"
+			err = c.Auth(PlainAuth("", "user", "pass", "smtp.google.com"))
+		case 4:
+			err = c.Mail("test@example.com")
+		case 5:
+			ok, _ := c.Extension("feature")
+			if ok {
+				t.Errorf("Expected FEATURE not to be supported")
+			}
+		case 6:
+			err = c.Reset()
+		case 7:
+			err = c.Quit()
+		case 8:
+			err = c.Verify("test@example.com")
+			if err != nil {
+				err = c.Hello("customhost")
+				if err != nil {
+					t.Errorf("Want error, got none")
+				}
+			}
+		default:
+			t.Fatalf("Unhandled command")
+		}
+
+		if err != nil {
+			t.Errorf("Command %d failed: %v", i, err)
+		}
+
+		bcmdbuf.Flush()
+		actualcmds := cmdbuf.String()
+		if client != actualcmds {
+			t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client)
+		}
+	}
+}
+
+var baseHelloServer = `220 hello world
+502 EH?
+250-mx.google.com at your service
+250 FEATURE
+`
+
+var helloServer = []string{
+	"",
+	"502 Not implemented\n",
+	"250 User is valid\n",
+	"235 Accepted\n",
+	"250 Sender ok\n",
+	"",
+	"250 Reset ok\n",
+	"221 Goodbye\n",
+	"250 Sender ok\n",
+}
+
+var baseHelloClient = `EHLO customhost
+HELO customhost
+`
+
+var helloClient = []string{
+	"",
+	"STARTTLS\n",
+	"VRFY test@example.com\n",
+	"AUTH PLAIN AHVzZXIAcGFzcw==\n",
+	"MAIL FROM:<test@example.com>\n",
+	"",
+	"RSET\n",
+	"QUIT\n",
+	"VRFY test@example.com\n",
+}
+
+func TestSendMail(t *testing.T) {
+	server := strings.Join(strings.Split(sendMailServer, "\n"), "\r\n")
+	client := strings.Join(strings.Split(sendMailClient, "\n"), "\r\n")
+	var cmdbuf bytes.Buffer
+	bcmdbuf := bufio.NewWriter(&cmdbuf)
+	l, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Unable to to create listener: %v", err)
+	}
+	defer l.Close()
+
+	// prevent data race on bcmdbuf
+	var done = make(chan struct{})
+	go func(data []string) {
+
+		defer close(done)
+
+		conn, err := l.Accept()
+		if err != nil {
+			t.Errorf("Accept error: %v", err)
+			return
+		}
+		defer conn.Close()
+
+		tc := textproto.NewConn(conn)
+		for i := 0; i < len(data) && data[i] != ""; i++ {
+			tc.PrintfLine(data[i])
+			for len(data[i]) >= 4 && data[i][3] == '-' {
+				i++
+				tc.PrintfLine(data[i])
+			}
+			if data[i] == "221 Goodbye" {
+				return
+			}
+			read := false
+			for !read || data[i] == "354 Go ahead" {
+				msg, err := tc.ReadLine()
+				bcmdbuf.Write([]byte(msg + "\r\n"))
+				read = true
+				if err != nil {
+					t.Errorf("Read error: %v", err)
+					return
+				}
+				if data[i] == "354 Go ahead" && msg == "." {
+					break
+				}
+			}
+		}
+	}(strings.Split(server, "\r\n"))
+
+	err = SendMail(l.Addr().String(), nil, "test@example.com", []string{"other@example.com"}, []byte(strings.Replace(`From: test@example.com
+To: other@example.com
+Subject: SendMail test
+
+SendMail is working for me.
+`, "\n", "\r\n", -1)))
+
+	if err != nil {
+		t.Errorf("%v", err)
+	}
+
+	<-done
+	bcmdbuf.Flush()
+	actualcmds := cmdbuf.String()
+	if client != actualcmds {
+		t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client)
+	}
+}
+
+var sendMailServer = `220 hello world
+502 EH?
+250 mx.google.com at your service
+250 Sender ok
+250 Receiver ok
+354 Go ahead
+250 Data ok
+221 Goodbye
+`
+
+var sendMailClient = `EHLO localhost
+HELO localhost
+MAIL FROM:<test@example.com>
+RCPT TO:<other@example.com>
+DATA
+From: test@example.com
+To: other@example.com
+Subject: SendMail test
+
+SendMail is working for me.
+.
+QUIT
+`
+
+func TestAuthFailed(t *testing.T) {
+	server := strings.Join(strings.Split(authFailedServer, "\n"), "\r\n")
+	client := strings.Join(strings.Split(authFailedClient, "\n"), "\r\n")
+	var cmdbuf bytes.Buffer
+	bcmdbuf := bufio.NewWriter(&cmdbuf)
+	var fake faker
+	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
+	c, err := NewClient(fake, "fake.host")
+	if err != nil {
+		t.Fatalf("NewClient: %v", err)
+	}
+	defer c.Close()
+
+	c.tls = true
+	c.serverName = "smtp.google.com"
+	err = c.Auth(PlainAuth("", "user", "pass", "smtp.google.com"))
+
+	if err == nil {
+		t.Error("Auth: expected error; got none")
+	} else if err.Error() != "535 Invalid credentials\nplease see www.example.com" {
+		t.Errorf("Auth: got error: %v, want: %s", err, "535 Invalid credentials\nplease see www.example.com")
+	}
+
+	bcmdbuf.Flush()
+	actualcmds := cmdbuf.String()
+	if client != actualcmds {
+		t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client)
+	}
+}
+
+var authFailedServer = `220 hello world
+250-mx.google.com at your service
+250 AUTH LOGIN PLAIN
+535-Invalid credentials
+535 please see www.example.com
+221 Goodbye
+`
+
+var authFailedClient = `EHLO localhost
+AUTH PLAIN AHVzZXIAcGFzcw==
+*
+QUIT
+`
+
+func TestTLSClient(t *testing.T) {
+	ln := newLocalListener(t)
+	defer ln.Close()
+	errc := make(chan error)
+	go func() {
+		errc <- sendMail(ln.Addr().String())
+	}()
+	conn, err := ln.Accept()
+	if err != nil {
+		t.Fatalf("failed to accept connection: %v", err)
+	}
+	defer conn.Close()
+	if err := serverHandle(conn, t); err != nil {
+		t.Fatalf("failed to handle connection: %v", err)
+	}
+	if err := <-errc; err != nil {
+		t.Fatalf("client error: %v", err)
+	}
+}
+
+func newLocalListener(t *testing.T) net.Listener {
+	ln, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		ln, err = net.Listen("tcp6", "[::1]:0")
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+	return ln
+}
+
+type smtpSender struct {
+	w io.Writer
+}
+
+func (s smtpSender) send(f string) {
+	s.w.Write([]byte(f + "\r\n"))
+}
+
+// smtp server, finely tailored to deal with our own client only!
+func serverHandle(c net.Conn, t *testing.T) error {
+	send := smtpSender{c}.send
+	send("220 127.0.0.1 ESMTP service ready")
+	s := bufio.NewScanner(c)
+	for s.Scan() {
+		switch s.Text() {
+		case "EHLO localhost":
+			send("250-127.0.0.1 ESMTP offers a warm hug of welcome")
+			send("250-STARTTLS")
+			send("250 Ok")
+		case "STARTTLS":
+			send("220 Go ahead")
+			keypair, err := tls.X509KeyPair(localhostCert, localhostKey)
+			if err != nil {
+				return err
+			}
+			config := &tls.Config{Certificates: []tls.Certificate{keypair}}
+			c = tls.Server(c, config)
+			defer c.Close()
+			return serverHandleTLS(c, t)
+		default:
+			t.Fatalf("unrecognized command: %q", s.Text())
+		}
+	}
+	return s.Err()
+}
+
+func serverHandleTLS(c net.Conn, t *testing.T) error {
+	send := smtpSender{c}.send
+	s := bufio.NewScanner(c)
+	for s.Scan() {
+		switch s.Text() {
+		case "EHLO localhost":
+			send("250 Ok")
+		case "MAIL FROM:<joe1@example.com>":
+			send("250 Ok")
+		case "RCPT TO:<joe2@example.com>":
+			send("250 Ok")
+		case "DATA":
+			send("354 send the mail data, end with .")
+			send("250 Ok")
+		case "Subject: test":
+		case "":
+		case "howdy!":
+		case ".":
+		case "QUIT":
+			send("221 127.0.0.1 Service closing transmission channel")
+			return nil
+		default:
+			t.Fatalf("unrecognized command during TLS: %q", s.Text())
+		}
+	}
+	return s.Err()
+}
+
+func init() {
+	testRootCAs := x509.NewCertPool()
+	testRootCAs.AppendCertsFromPEM(localhostCert)
+	testHookStartTLS = func(config *tls.Config) {
+		config.RootCAs = testRootCAs
+	}
+}
+
+func sendMail(hostPort string) error {
+	host, _, err := net.SplitHostPort(hostPort)
+	if err != nil {
+		return err
+	}
+	auth := PlainAuth("", "", "", host)
+	from := "joe1@example.com"
+	to := []string{"joe2@example.com"}
+	return SendMail(hostPort, auth, from, to, []byte("Subject: test\n\nhowdy!"))
+}
+
+// (copied from net/http/httptest)
+// localhostCert is a PEM-encoded TLS cert with SAN IPs
+// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
+// of ASN.1 time).
+// generated from src/pkg/crypto/tls:
+// go run generate_cert.go  --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
+var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
+bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
+bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
+IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
+AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
+EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
+AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
+Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
+-----END CERTIFICATE-----`)
+
+// localhostKey is the private key for localhostCert.
+var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
+0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
+NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
+AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
+MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
+EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
+1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
+-----END RSA PRIVATE KEY-----`)
diff --git a/third_party/gofrontend/libgo/go/net/sock_bsd.go b/third_party/gofrontend/libgo/go/net/sock_bsd.go
new file mode 100644
index 0000000..48fb785
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sock_bsd.go
@@ -0,0 +1,37 @@
+// 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.
+
+// +build darwin dragonfly freebsd nacl netbsd openbsd
+
+package net
+
+import (
+	"runtime"
+	"syscall"
+)
+
+func maxListenerBacklog() int {
+	var (
+		n   uint32
+		err error
+	)
+	switch runtime.GOOS {
+	case "darwin", "freebsd":
+		n, err = syscall.SysctlUint32("kern.ipc.somaxconn")
+	case "netbsd":
+		// NOTE: NetBSD has no somaxconn-like kernel state so far
+	case "openbsd":
+		n, err = syscall.SysctlUint32("kern.somaxconn")
+	}
+	if n == 0 || err != nil {
+		return syscall.SOMAXCONN
+	}
+	// FreeBSD stores the backlog in a uint16, as does Linux.
+	// Assume the other BSDs do too. Truncate number to avoid wrapping.
+	// See issue 5030.
+	if n > 1<<16-1 {
+		n = 1<<16 - 1
+	}
+	return int(n)
+}
diff --git a/third_party/gofrontend/libgo/go/net/sock_cloexec.go b/third_party/gofrontend/libgo/go/net/sock_cloexec.go
new file mode 100644
index 0000000..dec8185
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sock_cloexec.go
@@ -0,0 +1,78 @@
+// Copyright 2013 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.
+
+// This file implements sysSocket and accept for platforms that
+// provide a fast path for setting SetNonblock and CloseOnExec.
+
+// +build freebsd linux
+
+package net
+
+import "syscall"
+
+// Wrapper around the socket system call that marks the returned file
+// descriptor as nonblocking and close-on-exec.
+func sysSocket(family, sotype, proto int) (int, error) {
+	s, err := syscall.Socket(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto)
+	// On Linux the SOCK_NONBLOCK and SOCK_CLOEXEC flags were
+	// introduced in 2.6.27 kernel and on FreeBSD both flags were
+	// introduced in 10 kernel. If we get an EINVAL error on Linux
+	// or EPROTONOSUPPORT error on FreeBSD, fall back to using
+	// socket without them.
+	if err == nil || (err != syscall.EPROTONOSUPPORT && err != syscall.EINVAL) {
+		return s, err
+	}
+
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	syscall.ForkLock.RLock()
+	s, err = syscall.Socket(family, sotype, proto)
+	if err == nil {
+		syscall.CloseOnExec(s)
+	}
+	syscall.ForkLock.RUnlock()
+	if err != nil {
+		return -1, err
+	}
+	if err = syscall.SetNonblock(s, true); err != nil {
+		syscall.Close(s)
+		return -1, err
+	}
+	return s, nil
+}
+
+// Wrapper around the accept system call that marks the returned file
+// descriptor as nonblocking and close-on-exec.
+func accept(s int) (int, syscall.Sockaddr, error) {
+	ns, sa, err := syscall.Accept4(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
+	// On Linux the accept4 system call was introduced in 2.6.28
+	// kernel and on FreeBSD it was introduced in 10 kernel. If we
+	// get an ENOSYS error on both Linux and FreeBSD, or EINVAL
+	// error on Linux, fall back to using accept.
+	switch err {
+	default: // nil and errors other than the ones listed
+		return ns, sa, err
+	case syscall.ENOSYS: // syscall missing
+	case syscall.EINVAL: // some Linux use this instead of ENOSYS
+	case syscall.EACCES: // some Linux use this instead of ENOSYS
+	case syscall.EFAULT: // some Linux use this instead of ENOSYS
+	}
+
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	// It is probably okay to hold the lock across syscall.Accept
+	// because we have put fd.sysfd into non-blocking mode.
+	// However, a call to the File method will put it back into
+	// blocking mode. We can't take that risk, so no use of ForkLock here.
+	ns, sa, err = syscall.Accept(s)
+	if err == nil {
+		syscall.CloseOnExec(ns)
+	}
+	if err != nil {
+		return -1, nil, err
+	}
+	if err = syscall.SetNonblock(ns, true); err != nil {
+		syscall.Close(ns)
+		return -1, nil, err
+	}
+	return ns, sa, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/sock_linux.go b/third_party/gofrontend/libgo/go/net/sock_linux.go
new file mode 100644
index 0000000..cc5ce15
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sock_linux.go
@@ -0,0 +1,31 @@
+// 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 net
+
+import "syscall"
+
+func maxListenerBacklog() int {
+	fd, err := open("/proc/sys/net/core/somaxconn")
+	if err != nil {
+		return syscall.SOMAXCONN
+	}
+	defer fd.close()
+	l, ok := fd.readLine()
+	if !ok {
+		return syscall.SOMAXCONN
+	}
+	f := getFields(l)
+	n, _, ok := dtoi(f[0], 0)
+	if n == 0 || !ok {
+		return syscall.SOMAXCONN
+	}
+	// Linux stores the backlog in a uint16.
+	// Truncate number to avoid wrapping.
+	// See issue 5030.
+	if n > 1<<16-1 {
+		n = 1<<16 - 1
+	}
+	return n
+}
diff --git a/third_party/gofrontend/libgo/go/net/sock_plan9.go b/third_party/gofrontend/libgo/go/net/sock_plan9.go
new file mode 100644
index 0000000..88d9ed1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sock_plan9.go
@@ -0,0 +1,10 @@
+// Copyright 2013 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 net
+
+func maxListenerBacklog() int {
+	// /sys/include/ape/sys/socket.h:/SOMAXCONN
+	return 5
+}
diff --git a/third_party/gofrontend/libgo/go/net/sock_posix.go b/third_party/gofrontend/libgo/go/net/sock_posix.go
new file mode 100644
index 0000000..c80c7d6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sock_posix.go
@@ -0,0 +1,192 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"time"
+)
+
+// A sockaddr represents a TCP, UDP, IP or Unix network endpoint
+// address that can be converted into a syscall.Sockaddr.
+type sockaddr interface {
+	Addr
+
+	netaddr
+
+	// family returns the platform-dependent address family
+	// identifier.
+	family() int
+
+	// isWildcard reports whether the address is a wildcard
+	// address.
+	isWildcard() bool
+
+	// sockaddr returns the address converted into a syscall
+	// sockaddr type that implements syscall.Sockaddr
+	// interface. It returns a nil interface when the address is
+	// nil.
+	sockaddr(family int) (syscall.Sockaddr, error)
+}
+
+// socket returns a network file descriptor that is ready for
+// asynchronous I/O using the network poller.
+func socket(net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
+	s, err := sysSocket(family, sotype, proto)
+	if err != nil {
+		return nil, err
+	}
+	if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
+		closesocket(s)
+		return nil, err
+	}
+	if fd, err = newFD(s, family, sotype, net); err != nil {
+		closesocket(s)
+		return nil, err
+	}
+
+	// This function makes a network file descriptor for the
+	// following applications:
+	//
+	// - An endpoint holder that opens a passive stream
+	//   connenction, known as a stream listener
+	//
+	// - An endpoint holder that opens a destination-unspecific
+	//   datagram connection, known as a datagram listener
+	//
+	// - An endpoint holder that opens an active stream or a
+	//   destination-specific datagram connection, known as a
+	//   dialer
+	//
+	// - An endpoint holder that opens the other connection, such
+	//   as talking to the protocol stack inside the kernel
+	//
+	// For stream and datagram listeners, they will only require
+	// named sockets, so we can assume that it's just a request
+	// from stream or datagram listeners when laddr is not nil but
+	// raddr is nil. Otherwise we assume it's just for dialers or
+	// the other connection holders.
+
+	if laddr != nil && raddr == nil {
+		switch sotype {
+		case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET:
+			if err := fd.listenStream(laddr, listenerBacklog, toAddr); err != nil {
+				fd.Close()
+				return nil, err
+			}
+			return fd, nil
+		case syscall.SOCK_DGRAM:
+			if err := fd.listenDatagram(laddr, toAddr); err != nil {
+				fd.Close()
+				return nil, err
+			}
+			return fd, nil
+		}
+	}
+	if err := fd.dial(laddr, raddr, deadline, toAddr); err != nil {
+		fd.Close()
+		return nil, err
+	}
+	return fd, nil
+}
+
+func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) error {
+	var err error
+	var lsa syscall.Sockaddr
+	if laddr != nil {
+		if lsa, err = laddr.sockaddr(fd.family); err != nil {
+			return err
+		} else if lsa != nil {
+			if err := syscall.Bind(fd.sysfd, lsa); err != nil {
+				return os.NewSyscallError("bind", err)
+			}
+		}
+	}
+	var rsa syscall.Sockaddr
+	if raddr != nil {
+		if rsa, err = raddr.sockaddr(fd.family); err != nil {
+			return err
+		}
+		if err := fd.connect(lsa, rsa, deadline); err != nil {
+			return err
+		}
+		fd.isConnected = true
+	} else {
+		if err := fd.init(); err != nil {
+			return err
+		}
+	}
+	lsa, _ = syscall.Getsockname(fd.sysfd)
+	if rsa, _ = syscall.Getpeername(fd.sysfd); rsa != nil {
+		fd.setAddr(toAddr(lsa), toAddr(rsa))
+	} else {
+		fd.setAddr(toAddr(lsa), raddr)
+	}
+	return nil
+}
+
+func (fd *netFD) listenStream(laddr sockaddr, backlog int, toAddr func(syscall.Sockaddr) Addr) error {
+	if err := setDefaultListenerSockopts(fd.sysfd); err != nil {
+		return err
+	}
+	if lsa, err := laddr.sockaddr(fd.family); err != nil {
+		return err
+	} else if lsa != nil {
+		if err := syscall.Bind(fd.sysfd, lsa); err != nil {
+			return os.NewSyscallError("bind", err)
+		}
+	}
+	if err := syscall.Listen(fd.sysfd, backlog); err != nil {
+		return os.NewSyscallError("listen", err)
+	}
+	if err := fd.init(); err != nil {
+		return err
+	}
+	lsa, _ := syscall.Getsockname(fd.sysfd)
+	fd.setAddr(toAddr(lsa), nil)
+	return nil
+}
+
+func (fd *netFD) listenDatagram(laddr sockaddr, toAddr func(syscall.Sockaddr) Addr) error {
+	switch addr := laddr.(type) {
+	case *UDPAddr:
+		// We provide a socket that listens to a wildcard
+		// address with reusable UDP port when the given laddr
+		// is an appropriate UDP multicast address prefix.
+		// This makes it possible for a single UDP listener to
+		// join multiple different group addresses, for
+		// multiple UDP listeners that listen on the same UDP
+		// port to join the same group address.
+		if addr.IP != nil && addr.IP.IsMulticast() {
+			if err := setDefaultMulticastSockopts(fd.sysfd); err != nil {
+				return err
+			}
+			addr := *addr
+			switch fd.family {
+			case syscall.AF_INET:
+				addr.IP = IPv4zero
+			case syscall.AF_INET6:
+				addr.IP = IPv6unspecified
+			}
+			laddr = &addr
+		}
+	}
+	if lsa, err := laddr.sockaddr(fd.family); err != nil {
+		return err
+	} else if lsa != nil {
+		if err := syscall.Bind(fd.sysfd, lsa); err != nil {
+			return os.NewSyscallError("bind", err)
+		}
+	}
+	if err := fd.init(); err != nil {
+		return err
+	}
+	lsa, _ := syscall.Getsockname(fd.sysfd)
+	fd.setAddr(toAddr(lsa), nil)
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/sock_solaris.go b/third_party/gofrontend/libgo/go/net/sock_solaris.go
new file mode 100644
index 0000000..90fe9de
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sock_solaris.go
@@ -0,0 +1,13 @@
+// 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 net
+
+import "syscall"
+
+func maxListenerBacklog() int {
+	// TODO: Implement this
+	// NOTE: Never return a number bigger than 1<<16 - 1. See issue 5030.
+	return syscall.SOMAXCONN
+}
diff --git a/third_party/gofrontend/libgo/go/net/sock_windows.go b/third_party/gofrontend/libgo/go/net/sock_windows.go
new file mode 100644
index 0000000..6ccde3a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sock_windows.go
@@ -0,0 +1,24 @@
+// 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 net
+
+import "syscall"
+
+func maxListenerBacklog() int {
+	// TODO: Implement this
+	// NOTE: Never return a number bigger than 1<<16 - 1. See issue 5030.
+	return syscall.SOMAXCONN
+}
+
+func sysSocket(f, t, p int) (syscall.Handle, error) {
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	syscall.ForkLock.RLock()
+	s, err := syscall.Socket(f, t, p)
+	if err == nil {
+		syscall.CloseOnExec(s)
+	}
+	syscall.ForkLock.RUnlock()
+	return s, err
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockopt_bsd.go b/third_party/gofrontend/libgo/go/net/sockopt_bsd.go
new file mode 100644
index 0000000..2fa3b6f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockopt_bsd.go
@@ -0,0 +1,57 @@
+// 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.
+
+// +build darwin dragonfly freebsd nacl netbsd openbsd
+
+package net
+
+import (
+	"os"
+	"runtime"
+	"syscall"
+)
+
+func setDefaultSockopts(s, family, sotype int, ipv6only bool) error {
+	if runtime.GOOS == "dragonfly" && sotype != syscall.SOCK_RAW {
+		// On DragonFly BSD, we adjust the ephemeral port
+		// range because unlike other BSD systems its default
+		// port range doesn't conform to IANA recommendation
+		// as described in RFC 6355 and is pretty narrow.
+		switch family {
+		case syscall.AF_INET:
+			syscall.SetsockoptInt(s, syscall.IPPROTO_IP, syscall.IP_PORTRANGE, syscall.IP_PORTRANGE_HIGH)
+		case syscall.AF_INET6:
+			syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_PORTRANGE, syscall.IPV6_PORTRANGE_HIGH)
+		}
+	}
+	if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW {
+		// Allow both IP versions even if the OS default
+		// is otherwise.  Note that some operating systems
+		// never admit this option.
+		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
+	}
+	// Allow broadcast.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1))
+}
+
+func setDefaultListenerSockopts(s int) error {
+	// Allow reuse of recently-used addresses.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
+}
+
+func setDefaultMulticastSockopts(s int) error {
+	// Allow multicast UDP and raw IP datagram sockets to listen
+	// concurrently across multiple listeners.
+	if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	// Allow reuse of recently-used ports.
+	// This option is supported only in descendants of 4.4BSD,
+	// to make an effective multicast application that requires
+	// quick draw possible.
+	if syscall.SO_REUSEPORT != 0 {
+		return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1))
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockopt_linux.go b/third_party/gofrontend/libgo/go/net/sockopt_linux.go
new file mode 100644
index 0000000..54c20b1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockopt_linux.go
@@ -0,0 +1,32 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func setDefaultSockopts(s, family, sotype int, ipv6only bool) error {
+	if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW {
+		// Allow both IP versions even if the OS default
+		// is otherwise.  Note that some operating systems
+		// never admit this option.
+		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
+	}
+	// Allow broadcast.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1))
+}
+
+func setDefaultListenerSockopts(s int) error {
+	// Allow reuse of recently-used addresses.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
+}
+
+func setDefaultMulticastSockopts(s int) error {
+	// Allow multicast UDP and raw IP datagram sockets to listen
+	// concurrently across multiple listeners.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockopt_plan9.go b/third_party/gofrontend/libgo/go/net/sockopt_plan9.go
new file mode 100644
index 0000000..8bc689b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockopt_plan9.go
@@ -0,0 +1,13 @@
+// Copyright 2014 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 net
+
+func setKeepAlive(fd *netFD, keepalive bool) error {
+	if keepalive {
+		_, e := fd.ctl.WriteAt([]byte("keepalive"), 0)
+		return e
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockopt_posix.go b/third_party/gofrontend/libgo/go/net/sockopt_posix.go
new file mode 100644
index 0000000..921918c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockopt_posix.go
@@ -0,0 +1,141 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+// Boolean to int.
+func boolint(b bool) int {
+	if b {
+		return 1
+	}
+	return 0
+}
+
+func ipv4AddrToInterface(ip IP) (*Interface, error) {
+	ift, err := Interfaces()
+	if err != nil {
+		return nil, err
+	}
+	for _, ifi := range ift {
+		ifat, err := ifi.Addrs()
+		if err != nil {
+			return nil, err
+		}
+		for _, ifa := range ifat {
+			switch v := ifa.(type) {
+			case *IPAddr:
+				if ip.Equal(v.IP) {
+					return &ifi, nil
+				}
+			case *IPNet:
+				if ip.Equal(v.IP) {
+					return &ifi, nil
+				}
+			}
+		}
+	}
+	if ip.Equal(IPv4zero) {
+		return nil, nil
+	}
+	return nil, errNoSuchInterface
+}
+
+func interfaceToIPv4Addr(ifi *Interface) (IP, error) {
+	if ifi == nil {
+		return IPv4zero, nil
+	}
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		return nil, err
+	}
+	for _, ifa := range ifat {
+		switch v := ifa.(type) {
+		case *IPAddr:
+			if v.IP.To4() != nil {
+				return v.IP, nil
+			}
+		case *IPNet:
+			if v.IP.To4() != nil {
+				return v.IP, nil
+			}
+		}
+	}
+	return nil, errNoSuchInterface
+}
+
+func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error {
+	if ifi == nil {
+		return nil
+	}
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		return err
+	}
+	for _, ifa := range ifat {
+		switch v := ifa.(type) {
+		case *IPAddr:
+			if a := v.IP.To4(); a != nil {
+				copy(mreq.Interface[:], a)
+				goto done
+			}
+		case *IPNet:
+			if a := v.IP.To4(); a != nil {
+				copy(mreq.Interface[:], a)
+				goto done
+			}
+		}
+	}
+done:
+	if bytesEqual(mreq.Multiaddr[:], IPv4zero.To4()) {
+		return errNoSuchMulticastInterface
+	}
+	return nil
+}
+
+func setReadBuffer(fd *netFD, bytes int) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes))
+}
+
+func setWriteBuffer(fd *netFD, bytes int) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
+}
+
+func setKeepAlive(fd *netFD, keepalive bool) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive)))
+}
+
+func setLinger(fd *netFD, sec int) error {
+	var l syscall.Linger
+	if sec >= 0 {
+		l.Onoff = 1
+		l.Linger = int32(sec)
+	} else {
+		l.Onoff = 0
+		l.Linger = 0
+	}
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l))
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockopt_solaris.go b/third_party/gofrontend/libgo/go/net/sockopt_solaris.go
new file mode 100644
index 0000000..54c20b1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockopt_solaris.go
@@ -0,0 +1,32 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func setDefaultSockopts(s, family, sotype int, ipv6only bool) error {
+	if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW {
+		// Allow both IP versions even if the OS default
+		// is otherwise.  Note that some operating systems
+		// never admit this option.
+		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
+	}
+	// Allow broadcast.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1))
+}
+
+func setDefaultListenerSockopts(s int) error {
+	// Allow reuse of recently-used addresses.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
+}
+
+func setDefaultMulticastSockopts(s int) error {
+	// Allow multicast UDP and raw IP datagram sockets to listen
+	// concurrently across multiple listeners.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockopt_windows.go b/third_party/gofrontend/libgo/go/net/sockopt_windows.go
new file mode 100644
index 0000000..cb64a40
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockopt_windows.go
@@ -0,0 +1,38 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func setDefaultSockopts(s syscall.Handle, family, sotype int, ipv6only bool) error {
+	if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW {
+		// Allow both IP versions even if the OS default
+		// is otherwise.  Note that some operating systems
+		// never admit this option.
+		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
+	}
+	// Allow broadcast.
+	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
+	return nil
+}
+
+func setDefaultListenerSockopts(s syscall.Handle) error {
+	// Windows will reuse recently-used addresses by default.
+	// SO_REUSEADDR should not be used here, as it allows
+	// a socket to forcibly bind to a port in use by another socket.
+	// This could lead to a non-deterministic behavior, where
+	// connection requests over the port cannot be guaranteed
+	// to be handled by the correct socket.
+	return nil
+}
+
+func setDefaultMulticastSockopts(s syscall.Handle) error {
+	// Allow multicast UDP and raw IP datagram sockets to listen
+	// concurrently across multiple listeners.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockoptip_bsd.go b/third_party/gofrontend/libgo/go/net/sockoptip_bsd.go
new file mode 100644
index 0000000..87132f0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockoptip_bsd.go
@@ -0,0 +1,34 @@
+// 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.
+
+// +build darwin dragonfly freebsd nacl netbsd openbsd
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+	ip, err := interfaceToIPv4Addr(ifi)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	var a [4]byte
+	copy(a[:], ip.To4())
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, a))
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v))))
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockoptip_linux.go b/third_party/gofrontend/libgo/go/net/sockoptip_linux.go
new file mode 100644
index 0000000..a69b778
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockoptip_linux.go
@@ -0,0 +1,31 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+	var v int32
+	if ifi != nil {
+		v = int32(ifi.Index)
+	}
+	mreq := &syscall.IPMreqn{Ifindex: v}
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq))
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)))
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockoptip_posix.go b/third_party/gofrontend/libgo/go/net/sockoptip_posix.go
new file mode 100644
index 0000000..b5c80e4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockoptip_posix.go
@@ -0,0 +1,57 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd windows
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
+	mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+	if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
+		return err
+	}
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
+}
+
+func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
+	var v int
+	if ifi != nil {
+		v = ifi.Index
+	}
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v))
+}
+
+func setIPv6MulticastLoopback(fd *netFD, v bool) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v)))
+}
+
+func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
+	mreq := &syscall.IPv6Mreq{}
+	copy(mreq.Multiaddr[:], ip)
+	if ifi != nil {
+		mreq.Interface = uint32(ifi.Index)
+	}
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq))
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockoptip_stub.go b/third_party/gofrontend/libgo/go/net/sockoptip_stub.go
new file mode 100644
index 0000000..dcd3a22
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockoptip_stub.go
@@ -0,0 +1,39 @@
+// 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.
+
+// +build solaris
+
+package net
+
+import "syscall"
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+	// See golang.org/issue/7399.
+	return syscall.EINVAL
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+	// See golang.org/issue/7399.
+	return syscall.EINVAL
+}
+
+func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
+	// See golang.org/issue/7399.
+	return syscall.EINVAL
+}
+
+func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
+	// See golang.org/issue/7399.
+	return syscall.EINVAL
+}
+
+func setIPv6MulticastLoopback(fd *netFD, v bool) error {
+	// See golang.org/issue/7399.
+	return syscall.EINVAL
+}
+
+func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
+	// See golang.org/issue/7399.
+	return syscall.EINVAL
+}
diff --git a/third_party/gofrontend/libgo/go/net/sockoptip_windows.go b/third_party/gofrontend/libgo/go/net/sockoptip_windows.go
new file mode 100644
index 0000000..7b11f20
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sockoptip_windows.go
@@ -0,0 +1,33 @@
+// 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"unsafe"
+)
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+	ip, err := interfaceToIPv4Addr(ifi)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	var a [4]byte
+	copy(a[:], ip.To4())
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, (*byte)(unsafe.Pointer(&a[0])), 4))
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)))
+}
diff --git a/third_party/gofrontend/libgo/go/net/sys_cloexec.go b/third_party/gofrontend/libgo/go/net/sys_cloexec.go
new file mode 100644
index 0000000..898fb7c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/sys_cloexec.go
@@ -0,0 +1,54 @@
+// Copyright 2013 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.
+
+// This file implements sysSocket and accept for platforms that do not
+// provide a fast path for setting SetNonblock and CloseOnExec.
+
+// +build darwin dragonfly nacl netbsd openbsd solaris
+
+package net
+
+import "syscall"
+
+// Wrapper around the socket system call that marks the returned file
+// descriptor as nonblocking and close-on-exec.
+func sysSocket(family, sotype, proto int) (int, error) {
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	syscall.ForkLock.RLock()
+	s, err := syscall.Socket(family, sotype, proto)
+	if err == nil {
+		syscall.CloseOnExec(s)
+	}
+	syscall.ForkLock.RUnlock()
+	if err != nil {
+		return -1, err
+	}
+	if err = syscall.SetNonblock(s, true); err != nil {
+		syscall.Close(s)
+		return -1, err
+	}
+	return s, nil
+}
+
+// Wrapper around the accept system call that marks the returned file
+// descriptor as nonblocking and close-on-exec.
+func accept(s int) (int, syscall.Sockaddr, error) {
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	// It is probably okay to hold the lock across syscall.Accept
+	// because we have put fd.sysfd into non-blocking mode.
+	// However, a call to the File method will put it back into
+	// blocking mode. We can't take that risk, so no use of ForkLock here.
+	ns, sa, err := syscall.Accept(s)
+	if err == nil {
+		syscall.CloseOnExec(ns)
+	}
+	if err != nil {
+		return -1, nil, err
+	}
+	if err = syscall.SetNonblock(ns, true); err != nil {
+		syscall.Close(ns)
+		return -1, nil, err
+	}
+	return ns, sa, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcp_test.go b/third_party/gofrontend/libgo/go/net/tcp_test.go
new file mode 100644
index 0000000..c04198e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcp_test.go
@@ -0,0 +1,611 @@
+// 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 net
+
+import (
+	"fmt"
+	"io"
+	"reflect"
+	"runtime"
+	"sync"
+	"testing"
+	"time"
+)
+
+func BenchmarkTCP4OneShot(b *testing.B) {
+	benchmarkTCP(b, false, false, "127.0.0.1:0")
+}
+
+func BenchmarkTCP4OneShotTimeout(b *testing.B) {
+	benchmarkTCP(b, false, true, "127.0.0.1:0")
+}
+
+func BenchmarkTCP4Persistent(b *testing.B) {
+	benchmarkTCP(b, true, false, "127.0.0.1:0")
+}
+
+func BenchmarkTCP4PersistentTimeout(b *testing.B) {
+	benchmarkTCP(b, true, true, "127.0.0.1:0")
+}
+
+func BenchmarkTCP6OneShot(b *testing.B) {
+	if !supportsIPv6 {
+		b.Skip("ipv6 is not supported")
+	}
+	benchmarkTCP(b, false, false, "[::1]:0")
+}
+
+func BenchmarkTCP6OneShotTimeout(b *testing.B) {
+	if !supportsIPv6 {
+		b.Skip("ipv6 is not supported")
+	}
+	benchmarkTCP(b, false, true, "[::1]:0")
+}
+
+func BenchmarkTCP6Persistent(b *testing.B) {
+	if !supportsIPv6 {
+		b.Skip("ipv6 is not supported")
+	}
+	benchmarkTCP(b, true, false, "[::1]:0")
+}
+
+func BenchmarkTCP6PersistentTimeout(b *testing.B) {
+	if !supportsIPv6 {
+		b.Skip("ipv6 is not supported")
+	}
+	benchmarkTCP(b, true, true, "[::1]:0")
+}
+
+func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
+	const msgLen = 512
+	conns := b.N
+	numConcurrent := runtime.GOMAXPROCS(-1) * 2
+	msgs := 1
+	if persistent {
+		conns = numConcurrent
+		msgs = b.N / conns
+		if msgs == 0 {
+			msgs = 1
+		}
+		if conns > b.N {
+			conns = b.N
+		}
+	}
+	sendMsg := func(c Conn, buf []byte) bool {
+		n, err := c.Write(buf)
+		if n != len(buf) || err != nil {
+			b.Logf("Write failed: %v", err)
+			return false
+		}
+		return true
+	}
+	recvMsg := func(c Conn, buf []byte) bool {
+		for read := 0; read != len(buf); {
+			n, err := c.Read(buf)
+			read += n
+			if err != nil {
+				b.Logf("Read failed: %v", err)
+				return false
+			}
+		}
+		return true
+	}
+	ln, err := Listen("tcp", laddr)
+	if err != nil {
+		b.Fatalf("Listen failed: %v", err)
+	}
+	defer ln.Close()
+	serverSem := make(chan bool, numConcurrent)
+	// Acceptor.
+	go func() {
+		for {
+			c, err := ln.Accept()
+			if err != nil {
+				break
+			}
+			serverSem <- true
+			// Server connection.
+			go func(c Conn) {
+				defer func() {
+					c.Close()
+					<-serverSem
+				}()
+				if timeout {
+					c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
+				}
+				var buf [msgLen]byte
+				for m := 0; m < msgs; m++ {
+					if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
+						break
+					}
+				}
+			}(c)
+		}
+	}()
+	clientSem := make(chan bool, numConcurrent)
+	for i := 0; i < conns; i++ {
+		clientSem <- true
+		// Client connection.
+		go func() {
+			defer func() {
+				<-clientSem
+			}()
+			c, err := Dial("tcp", ln.Addr().String())
+			if err != nil {
+				b.Logf("Dial failed: %v", err)
+				return
+			}
+			defer c.Close()
+			if timeout {
+				c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
+			}
+			var buf [msgLen]byte
+			for m := 0; m < msgs; m++ {
+				if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
+					break
+				}
+			}
+		}()
+	}
+	for i := 0; i < numConcurrent; i++ {
+		clientSem <- true
+		serverSem <- true
+	}
+}
+
+func BenchmarkTCP4ConcurrentReadWrite(b *testing.B) {
+	benchmarkTCPConcurrentReadWrite(b, "127.0.0.1:0")
+}
+
+func BenchmarkTCP6ConcurrentReadWrite(b *testing.B) {
+	if !supportsIPv6 {
+		b.Skip("ipv6 is not supported")
+	}
+	benchmarkTCPConcurrentReadWrite(b, "[::1]:0")
+}
+
+func benchmarkTCPConcurrentReadWrite(b *testing.B, laddr string) {
+	// The benchmark creates GOMAXPROCS client/server pairs.
+	// Each pair creates 4 goroutines: client reader/writer and server reader/writer.
+	// The benchmark stresses concurrent reading and writing to the same connection.
+	// Such pattern is used in net/http and net/rpc.
+
+	b.StopTimer()
+
+	P := runtime.GOMAXPROCS(0)
+	N := b.N / P
+	W := 1000
+
+	// Setup P client/server connections.
+	clients := make([]Conn, P)
+	servers := make([]Conn, P)
+	ln, err := Listen("tcp", laddr)
+	if err != nil {
+		b.Fatalf("Listen failed: %v", err)
+	}
+	defer ln.Close()
+	done := make(chan bool)
+	go func() {
+		for p := 0; p < P; p++ {
+			s, err := ln.Accept()
+			if err != nil {
+				b.Errorf("Accept failed: %v", err)
+				return
+			}
+			servers[p] = s
+		}
+		done <- true
+	}()
+	for p := 0; p < P; p++ {
+		c, err := Dial("tcp", ln.Addr().String())
+		if err != nil {
+			b.Fatalf("Dial failed: %v", err)
+		}
+		clients[p] = c
+	}
+	<-done
+
+	b.StartTimer()
+
+	var wg sync.WaitGroup
+	wg.Add(4 * P)
+	for p := 0; p < P; p++ {
+		// Client writer.
+		go func(c Conn) {
+			defer wg.Done()
+			var buf [1]byte
+			for i := 0; i < N; i++ {
+				v := byte(i)
+				for w := 0; w < W; w++ {
+					v *= v
+				}
+				buf[0] = v
+				_, err := c.Write(buf[:])
+				if err != nil {
+					b.Errorf("Write failed: %v", err)
+					return
+				}
+			}
+		}(clients[p])
+
+		// Pipe between server reader and server writer.
+		pipe := make(chan byte, 128)
+
+		// Server reader.
+		go func(s Conn) {
+			defer wg.Done()
+			var buf [1]byte
+			for i := 0; i < N; i++ {
+				_, err := s.Read(buf[:])
+				if err != nil {
+					b.Errorf("Read failed: %v", err)
+					return
+				}
+				pipe <- buf[0]
+			}
+		}(servers[p])
+
+		// Server writer.
+		go func(s Conn) {
+			defer wg.Done()
+			var buf [1]byte
+			for i := 0; i < N; i++ {
+				v := <-pipe
+				for w := 0; w < W; w++ {
+					v *= v
+				}
+				buf[0] = v
+				_, err := s.Write(buf[:])
+				if err != nil {
+					b.Errorf("Write failed: %v", err)
+					return
+				}
+			}
+			s.Close()
+		}(servers[p])
+
+		// Client reader.
+		go func(c Conn) {
+			defer wg.Done()
+			var buf [1]byte
+			for i := 0; i < N; i++ {
+				_, err := c.Read(buf[:])
+				if err != nil {
+					b.Errorf("Read failed: %v", err)
+					return
+				}
+			}
+			c.Close()
+		}(clients[p])
+	}
+	wg.Wait()
+}
+
+type resolveTCPAddrTest struct {
+	net           string
+	litAddrOrName string
+	addr          *TCPAddr
+	err           error
+}
+
+var resolveTCPAddrTests = []resolveTCPAddrTest{
+	{"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
+	{"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
+
+	{"tcp", "[::1]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1}, nil},
+	{"tcp6", "[::1]:65534", &TCPAddr{IP: ParseIP("::1"), Port: 65534}, nil},
+
+	{"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
+	{"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
+
+	{"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
+	{"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior
+
+	{"tcp", ":12345", &TCPAddr{Port: 12345}, nil},
+
+	{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
+}
+
+func init() {
+	if ifi := loopbackInterface(); ifi != nil {
+		index := fmt.Sprintf("%v", ifi.Index)
+		resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
+			{"tcp6", "[fe80::1%" + ifi.Name + "]:3", &TCPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: zoneToString(ifi.Index)}, nil},
+			{"tcp6", "[fe80::1%" + index + "]:4", &TCPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: index}, nil},
+		}...)
+	}
+	if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
+		resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
+			{"tcp", "localhost:5", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5}, nil},
+			{"tcp4", "localhost:6", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 6}, nil},
+			{"tcp6", "localhost:7", &TCPAddr{IP: IPv6loopback, Port: 7}, nil},
+		}...)
+	}
+}
+
+func TestResolveTCPAddr(t *testing.T) {
+	for _, tt := range resolveTCPAddrTests {
+		addr, err := ResolveTCPAddr(tt.net, tt.litAddrOrName)
+		if err != tt.err {
+			t.Fatalf("ResolveTCPAddr(%q, %q) failed: %v", tt.net, tt.litAddrOrName, err)
+		}
+		if !reflect.DeepEqual(addr, tt.addr) {
+			t.Fatalf("ResolveTCPAddr(%q, %q) = %#v, want %#v", tt.net, tt.litAddrOrName, addr, tt.addr)
+		}
+		if err == nil {
+			str := addr.String()
+			addr1, err := ResolveTCPAddr(tt.net, str)
+			if err != nil {
+				t.Fatalf("ResolveTCPAddr(%q, %q) [from %q]: %v", tt.net, str, tt.litAddrOrName, err)
+			}
+			if !reflect.DeepEqual(addr1, addr) {
+				t.Fatalf("ResolveTCPAddr(%q, %q) [from %q] = %#v, want %#v", tt.net, str, tt.litAddrOrName, addr1, addr)
+			}
+		}
+	}
+}
+
+var tcpListenerNameTests = []struct {
+	net   string
+	laddr *TCPAddr
+}{
+	{"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}},
+	{"tcp4", &TCPAddr{}},
+	{"tcp4", nil},
+}
+
+func TestTCPListenerName(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	for _, tt := range tcpListenerNameTests {
+		ln, err := ListenTCP(tt.net, tt.laddr)
+		if err != nil {
+			t.Fatalf("ListenTCP failed: %v", err)
+		}
+		defer ln.Close()
+		la := ln.Addr()
+		if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
+			t.Fatalf("got %v; expected a proper address with non-zero port number", la)
+		}
+	}
+}
+
+func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+	if !supportsIPv6 {
+		t.Skip("ipv6 is not supported")
+	}
+	ifi := loopbackInterface()
+	if ifi == nil {
+		t.Skip("loopback interface not found")
+	}
+	laddr := ipv6LinkLocalUnicastAddr(ifi)
+	if laddr == "" {
+		t.Skip("ipv6 unicast address on loopback not found")
+	}
+
+	type test struct {
+		net, addr  string
+		nameLookup bool
+	}
+	var tests = []test{
+		{"tcp", "[" + laddr + "%" + ifi.Name + "]:0", false},
+		{"tcp6", "[" + laddr + "%" + ifi.Name + "]:0", false},
+	}
+	switch runtime.GOOS {
+	case "darwin", "freebsd", "openbsd", "netbsd":
+		tests = append(tests, []test{
+			{"tcp", "[localhost%" + ifi.Name + "]:0", true},
+			{"tcp6", "[localhost%" + ifi.Name + "]:0", true},
+		}...)
+	case "linux":
+		tests = append(tests, []test{
+			{"tcp", "[ip6-localhost%" + ifi.Name + "]:0", true},
+			{"tcp6", "[ip6-localhost%" + ifi.Name + "]:0", true},
+		}...)
+	}
+	for _, tt := range tests {
+		ln, err := Listen(tt.net, tt.addr)
+		if err != nil {
+			// It might return "LookupHost returned no
+			// suitable address" error on some platforms.
+			t.Logf("Listen failed: %v", err)
+			continue
+		}
+		defer ln.Close()
+		if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
+			t.Fatalf("got %v; expected a proper address with zone identifier", la)
+		}
+
+		done := make(chan int)
+		go transponder(t, ln, done)
+
+		c, err := Dial(tt.net, ln.Addr().String())
+		if err != nil {
+			t.Fatalf("Dial failed: %v", err)
+		}
+		defer c.Close()
+		if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
+			t.Fatalf("got %v; expected a proper address with zone identifier", la)
+		}
+		if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
+			t.Fatalf("got %v; expected a proper address with zone identifier", ra)
+		}
+
+		if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err != nil {
+			t.Fatalf("Conn.Write failed: %v", err)
+		}
+		b := make([]byte, 32)
+		if _, err := c.Read(b); err != nil {
+			t.Fatalf("Conn.Read failed: %v", err)
+		}
+
+		<-done
+	}
+}
+
+func TestTCPConcurrentAccept(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+	}
+	const N = 10
+	var wg sync.WaitGroup
+	wg.Add(N)
+	for i := 0; i < N; i++ {
+		go func() {
+			for {
+				c, err := ln.Accept()
+				if err != nil {
+					break
+				}
+				c.Close()
+			}
+			wg.Done()
+		}()
+	}
+	attempts := 10 * N
+	fails := 0
+	d := &Dialer{Timeout: 200 * time.Millisecond}
+	for i := 0; i < attempts; i++ {
+		c, err := d.Dial("tcp", ln.Addr().String())
+		if err != nil {
+			fails++
+		} else {
+			c.Close()
+		}
+	}
+	ln.Close()
+	wg.Wait()
+	if fails > attempts/9 { // see issues 7400 and 7541
+		t.Fatalf("too many Dial failed: %v", fails)
+	}
+	if fails > 0 {
+		t.Logf("# of failed Dials: %v", fails)
+	}
+}
+
+func TestTCPReadWriteMallocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+	}
+	defer ln.Close()
+	var server Conn
+	errc := make(chan error)
+	go func() {
+		var err error
+		server, err = ln.Accept()
+		errc <- err
+	}()
+	client, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial failed: %v", err)
+	}
+	if err := <-errc; err != nil {
+		t.Fatalf("Accept failed: %v", err)
+	}
+	defer server.Close()
+	var buf [128]byte
+	mallocs := testing.AllocsPerRun(1000, func() {
+		_, err := server.Write(buf[:])
+		if err != nil {
+			t.Fatalf("Write failed: %v", err)
+		}
+		_, err = io.ReadFull(client, buf[:])
+		if err != nil {
+			t.Fatalf("Read failed: %v", err)
+		}
+	})
+	if mallocs > 0 {
+		t.Fatalf("Got %v allocs, want 0", mallocs)
+	}
+}
+
+func TestTCPStress(t *testing.T) {
+	const conns = 2
+	const msgLen = 512
+	msgs := int(1e4)
+	if testing.Short() {
+		msgs = 1e2
+	}
+
+	sendMsg := func(c Conn, buf []byte) bool {
+		n, err := c.Write(buf)
+		if n != len(buf) || err != nil {
+			t.Logf("Write failed: %v", err)
+			return false
+		}
+		return true
+	}
+	recvMsg := func(c Conn, buf []byte) bool {
+		for read := 0; read != len(buf); {
+			n, err := c.Read(buf)
+			read += n
+			if err != nil {
+				t.Logf("Read failed: %v", err)
+				return false
+			}
+		}
+		return true
+	}
+
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+	}
+	defer ln.Close()
+	// Acceptor.
+	go func() {
+		for {
+			c, err := ln.Accept()
+			if err != nil {
+				break
+			}
+			// Server connection.
+			go func(c Conn) {
+				defer c.Close()
+				var buf [msgLen]byte
+				for m := 0; m < msgs; m++ {
+					if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
+						break
+					}
+				}
+			}(c)
+		}
+	}()
+	done := make(chan bool)
+	for i := 0; i < conns; i++ {
+		// Client connection.
+		go func() {
+			defer func() {
+				done <- true
+			}()
+			c, err := Dial("tcp", ln.Addr().String())
+			if err != nil {
+				t.Logf("Dial failed: %v", err)
+				return
+			}
+			defer c.Close()
+			var buf [msgLen]byte
+			for m := 0; m < msgs; m++ {
+				if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
+					break
+				}
+			}
+		}()
+	}
+	for i := 0; i < conns; i++ {
+		<-done
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsock.go b/third_party/gofrontend/libgo/go/net/tcpsock.go
new file mode 100644
index 0000000..f3dfbd2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsock.go
@@ -0,0 +1,54 @@
+// 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 net
+
+// TCPAddr represents the address of a TCP end point.
+type TCPAddr struct {
+	IP   IP
+	Port int
+	Zone string // IPv6 scoped addressing zone
+}
+
+// Network returns the address's network name, "tcp".
+func (a *TCPAddr) Network() string { return "tcp" }
+
+func (a *TCPAddr) String() string {
+	if a == nil {
+		return "<nil>"
+	}
+	ip := ipEmptyString(a.IP)
+	if a.Zone != "" {
+		return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port))
+	}
+	return JoinHostPort(ip, itoa(a.Port))
+}
+
+func (a *TCPAddr) toAddr() Addr {
+	if a == nil {
+		return nil
+	}
+	return a
+}
+
+// ResolveTCPAddr parses addr as a TCP address of the form "host:port"
+// or "[ipv6-host%zone]:port" and resolves a pair of domain name and
+// port name on the network net, which must be "tcp", "tcp4" or
+// "tcp6".  A literal address or host name for IPv6 must be enclosed
+// in square brackets, as in "[::1]:80", "[ipv6-host]:http" or
+// "[ipv6-host%zone]:80".
+func ResolveTCPAddr(net, addr string) (*TCPAddr, error) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+	case "": // a hint wildcard for Go 1.0 undocumented behavior
+		net = "tcp"
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	a, err := resolveInternetAddr(net, addr, noDeadline)
+	if err != nil {
+		return nil, err
+	}
+	return a.toAddr().(*TCPAddr), nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsock_plan9.go b/third_party/gofrontend/libgo/go/net/tcpsock_plan9.go
new file mode 100644
index 0000000..52019d7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsock_plan9.go
@@ -0,0 +1,198 @@
+// 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 net
+
+import (
+	"io"
+	"os"
+	"syscall"
+	"time"
+)
+
+// TCPConn is an implementation of the Conn interface for TCP network
+// connections.
+type TCPConn struct {
+	conn
+}
+
+func newTCPConn(fd *netFD) *TCPConn {
+	return &TCPConn{conn{fd}}
+}
+
+// ReadFrom implements the io.ReaderFrom ReadFrom method.
+func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
+	return genericReadFrom(c, r)
+}
+
+// CloseRead shuts down the reading side of the TCP connection.
+// Most callers should just use Close.
+func (c *TCPConn) CloseRead() error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.closeRead()
+}
+
+// CloseWrite shuts down the writing side of the TCP connection.
+// Most callers should just use Close.
+func (c *TCPConn) CloseWrite() error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.closeWrite()
+}
+
+// SetLinger sets the behavior of Close on a connection which still
+// has data waiting to be sent or to be acknowledged.
+//
+// If sec < 0 (the default), the operating system finishes sending the
+// data in the background.
+//
+// If sec == 0, the operating system discards any unsent or
+// unacknowledged data.
+//
+// If sec > 0, the data is sent in the background as with sec < 0. On
+// some operating systems after sec seconds have elapsed any remaining
+// unsent data may be discarded.
+func (c *TCPConn) SetLinger(sec int) error {
+	return syscall.EPLAN9
+}
+
+// SetKeepAlive sets whether the operating system should send
+// keepalive messages on the connection.
+func (c *TCPConn) SetKeepAlive(keepalive bool) error {
+	if !c.ok() {
+		return syscall.EPLAN9
+	}
+	return setKeepAlive(c.fd, keepalive)
+}
+
+// SetKeepAlivePeriod sets period between keep alives.
+func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
+	if !c.ok() {
+		return syscall.EPLAN9
+	}
+	return setKeepAlivePeriod(c.fd, d)
+}
+
+// SetNoDelay controls whether the operating system should delay
+// packet transmission in hopes of sending fewer packets (Nagle's
+// algorithm).  The default is true (no delay), meaning that data is
+// sent as soon as possible after a Write.
+func (c *TCPConn) SetNoDelay(noDelay bool) error {
+	return syscall.EPLAN9
+}
+
+// DialTCP connects to the remote address raddr on the network net,
+// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is
+// used as the local address for the connection.
+func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
+	return dialTCP(net, laddr, raddr, noDeadline)
+}
+
+func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
+	if !deadline.IsZero() {
+		panic("net.dialTCP: deadline not implemented on Plan 9")
+	}
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+	default:
+		return nil, &OpError{"dial", net, raddr, UnknownNetworkError(net)}
+	}
+	if raddr == nil {
+		return nil, &OpError{"dial", net, nil, errMissingAddress}
+	}
+	fd, err := dialPlan9(net, laddr, raddr)
+	if err != nil {
+		return nil, err
+	}
+	return newTCPConn(fd), nil
+}
+
+// TCPListener is a TCP network listener.  Clients should typically
+// use variables of type Listener instead of assuming TCP.
+type TCPListener struct {
+	fd *netFD
+}
+
+// AcceptTCP accepts the next incoming call and returns the new
+// connection.
+func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
+	if l == nil || l.fd == nil || l.fd.ctl == nil {
+		return nil, syscall.EINVAL
+	}
+	fd, err := l.fd.acceptPlan9()
+	if err != nil {
+		return nil, err
+	}
+	return newTCPConn(fd), nil
+}
+
+// Accept implements the Accept method in the Listener interface; it
+// waits for the next call and returns a generic Conn.
+func (l *TCPListener) Accept() (Conn, error) {
+	if l == nil || l.fd == nil || l.fd.ctl == nil {
+		return nil, syscall.EINVAL
+	}
+	c, err := l.AcceptTCP()
+	if err != nil {
+		return nil, err
+	}
+	return c, nil
+}
+
+// Close stops listening on the TCP address.
+// Already Accepted connections are not closed.
+func (l *TCPListener) Close() error {
+	if l == nil || l.fd == nil || l.fd.ctl == nil {
+		return syscall.EINVAL
+	}
+	if _, err := l.fd.ctl.WriteString("hangup"); err != nil {
+		l.fd.ctl.Close()
+		return &OpError{"close", l.fd.ctl.Name(), l.fd.laddr, err}
+	}
+	return l.fd.ctl.Close()
+}
+
+// Addr returns the listener's network address, a *TCPAddr.
+func (l *TCPListener) Addr() Addr { return l.fd.laddr }
+
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *TCPListener) SetDeadline(t time.Time) error {
+	if l == nil || l.fd == nil || l.fd.ctl == nil {
+		return syscall.EINVAL
+	}
+	return l.fd.setDeadline(t)
+}
+
+// File returns a copy of the underlying os.File, set to blocking
+// mode.  It is the caller's responsibility to close f when finished.
+// Closing l does not affect f, and closing f does not affect l.
+//
+// The returned os.File's file descriptor is different from the
+// connection's.  Attempting to change properties of the original
+// using this duplicate may or may not have the desired effect.
+func (l *TCPListener) File() (f *os.File, err error) { return l.dup() }
+
+// ListenTCP announces on the TCP address laddr and returns a TCP
+// listener.  Net must be "tcp", "tcp4", or "tcp6".  If laddr has a
+// port of 0, ListenTCP will choose an available port.  The caller can
+// use the Addr method of TCPListener to retrieve the chosen address.
+func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+	default:
+		return nil, &OpError{"listen", net, laddr, UnknownNetworkError(net)}
+	}
+	if laddr == nil {
+		laddr = &TCPAddr{}
+	}
+	fd, err := listenPlan9(net, laddr)
+	if err != nil {
+		return nil, err
+	}
+	return &TCPListener{fd}, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsock_posix.go b/third_party/gofrontend/libgo/go/net/tcpsock_posix.go
new file mode 100644
index 0000000..b79b115
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsock_posix.go
@@ -0,0 +1,299 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package net
+
+import (
+	"io"
+	"os"
+	"syscall"
+	"time"
+)
+
+// BUG(rsc): On OpenBSD, listening on the "tcp" network does not listen for
+// both IPv4 and IPv6 connections. This is due to the fact that IPv4 traffic
+// will not be routed to an IPv6 socket - two separate sockets are required
+// if both AFs are to be supported. See inet6(4) on OpenBSD for details.
+
+func sockaddrToTCP(sa syscall.Sockaddr) Addr {
+	switch sa := sa.(type) {
+	case *syscall.SockaddrInet4:
+		return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port}
+	case *syscall.SockaddrInet6:
+		return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
+	}
+	return nil
+}
+
+func (a *TCPAddr) family() int {
+	if a == nil || len(a.IP) <= IPv4len {
+		return syscall.AF_INET
+	}
+	if a.IP.To4() != nil {
+		return syscall.AF_INET
+	}
+	return syscall.AF_INET6
+}
+
+func (a *TCPAddr) isWildcard() bool {
+	if a == nil || a.IP == nil {
+		return true
+	}
+	return a.IP.IsUnspecified()
+}
+
+func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
+	if a == nil {
+		return nil, nil
+	}
+	return ipToSockaddr(family, a.IP, a.Port, a.Zone)
+}
+
+// TCPConn is an implementation of the Conn interface for TCP network
+// connections.
+type TCPConn struct {
+	conn
+}
+
+func newTCPConn(fd *netFD) *TCPConn {
+	c := &TCPConn{conn{fd}}
+	c.SetNoDelay(true)
+	return c
+}
+
+// ReadFrom implements the io.ReaderFrom ReadFrom method.
+func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
+	if n, err, handled := sendFile(c.fd, r); handled {
+		return n, err
+	}
+	return genericReadFrom(c, r)
+}
+
+// CloseRead shuts down the reading side of the TCP connection.
+// Most callers should just use Close.
+func (c *TCPConn) CloseRead() error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.closeRead()
+}
+
+// CloseWrite shuts down the writing side of the TCP connection.
+// Most callers should just use Close.
+func (c *TCPConn) CloseWrite() error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.closeWrite()
+}
+
+// SetLinger sets the behavior of Close on a connection which still
+// has data waiting to be sent or to be acknowledged.
+//
+// If sec < 0 (the default), the operating system finishes sending the
+// data in the background.
+//
+// If sec == 0, the operating system discards any unsent or
+// unacknowledged data.
+//
+// If sec > 0, the data is sent in the background as with sec < 0. On
+// some operating systems after sec seconds have elapsed any remaining
+// unsent data may be discarded.
+func (c *TCPConn) SetLinger(sec int) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setLinger(c.fd, sec)
+}
+
+// SetKeepAlive sets whether the operating system should send
+// keepalive messages on the connection.
+func (c *TCPConn) SetKeepAlive(keepalive bool) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setKeepAlive(c.fd, keepalive)
+}
+
+// SetKeepAlivePeriod sets period between keep alives.
+func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setKeepAlivePeriod(c.fd, d)
+}
+
+// SetNoDelay controls whether the operating system should delay
+// packet transmission in hopes of sending fewer packets (Nagle's
+// algorithm).  The default is true (no delay), meaning that data is
+// sent as soon as possible after a Write.
+func (c *TCPConn) SetNoDelay(noDelay bool) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setNoDelay(c.fd, noDelay)
+}
+
+// DialTCP connects to the remote address raddr on the network net,
+// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is
+// used as the local address for the connection.
+func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+	default:
+		return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
+	}
+	if raddr == nil {
+		return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: errMissingAddress}
+	}
+	return dialTCP(net, laddr, raddr, noDeadline)
+}
+
+func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
+	fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
+
+	// TCP has a rarely used mechanism called a 'simultaneous connection' in
+	// which Dial("tcp", addr1, addr2) run on the machine at addr1 can
+	// connect to a simultaneous Dial("tcp", addr2, addr1) run on the machine
+	// at addr2, without either machine executing Listen.  If laddr == nil,
+	// it means we want the kernel to pick an appropriate originating local
+	// address.  Some Linux kernels cycle blindly through a fixed range of
+	// local ports, regardless of destination port.  If a kernel happens to
+	// pick local port 50001 as the source for a Dial("tcp", "", "localhost:50001"),
+	// then the Dial will succeed, having simultaneously connected to itself.
+	// This can only happen when we are letting the kernel pick a port (laddr == nil)
+	// and when there is no listener for the destination address.
+	// It's hard to argue this is anything other than a kernel bug.  If we
+	// see this happen, rather than expose the buggy effect to users, we
+	// close the fd and try again.  If it happens twice more, we relent and
+	// use the result.  See also:
+	//	http://golang.org/issue/2690
+	//	http://stackoverflow.com/questions/4949858/
+	//
+	// The opposite can also happen: if we ask the kernel to pick an appropriate
+	// originating local address, sometimes it picks one that is already in use.
+	// So if the error is EADDRNOTAVAIL, we have to try again too, just for
+	// a different reason.
+	//
+	// The kernel socket code is no doubt enjoying watching us squirm.
+	for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(fd, err) || spuriousENOTAVAIL(err)); i++ {
+		if err == nil {
+			fd.Close()
+		}
+		fd, err = internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
+	}
+
+	if err != nil {
+		return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
+	}
+	return newTCPConn(fd), nil
+}
+
+func selfConnect(fd *netFD, err error) bool {
+	// If the connect failed, we clearly didn't connect to ourselves.
+	if err != nil {
+		return false
+	}
+
+	// The socket constructor can return an fd with raddr nil under certain
+	// unknown conditions. The errors in the calls there to Getpeername
+	// are discarded, but we can't catch the problem there because those
+	// calls are sometimes legally erroneous with a "socket not connected".
+	// Since this code (selfConnect) is already trying to work around
+	// a problem, we make sure if this happens we recognize trouble and
+	// ask the DialTCP routine to try again.
+	// TODO: try to understand what's really going on.
+	if fd.laddr == nil || fd.raddr == nil {
+		return true
+	}
+	l := fd.laddr.(*TCPAddr)
+	r := fd.raddr.(*TCPAddr)
+	return l.Port == r.Port && l.IP.Equal(r.IP)
+}
+
+func spuriousENOTAVAIL(err error) bool {
+	e, ok := err.(*OpError)
+	return ok && e.Err == syscall.EADDRNOTAVAIL
+}
+
+// TCPListener is a TCP network listener.  Clients should typically
+// use variables of type Listener instead of assuming TCP.
+type TCPListener struct {
+	fd *netFD
+}
+
+// AcceptTCP accepts the next incoming call and returns the new
+// connection.
+func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
+	if l == nil || l.fd == nil {
+		return nil, syscall.EINVAL
+	}
+	fd, err := l.fd.accept(sockaddrToTCP)
+	if err != nil {
+		return nil, err
+	}
+	return newTCPConn(fd), nil
+}
+
+// Accept implements the Accept method in the Listener interface; it
+// waits for the next call and returns a generic Conn.
+func (l *TCPListener) Accept() (Conn, error) {
+	c, err := l.AcceptTCP()
+	if err != nil {
+		return nil, err
+	}
+	return c, nil
+}
+
+// Close stops listening on the TCP address.
+// Already Accepted connections are not closed.
+func (l *TCPListener) Close() error {
+	if l == nil || l.fd == nil {
+		return syscall.EINVAL
+	}
+	return l.fd.Close()
+}
+
+// Addr returns the listener's network address, a *TCPAddr.
+func (l *TCPListener) Addr() Addr { return l.fd.laddr }
+
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *TCPListener) SetDeadline(t time.Time) error {
+	if l == nil || l.fd == nil {
+		return syscall.EINVAL
+	}
+	return l.fd.setDeadline(t)
+}
+
+// File returns a copy of the underlying os.File, set to blocking
+// mode.  It is the caller's responsibility to close f when finished.
+// Closing l does not affect f, and closing f does not affect l.
+//
+// The returned os.File's file descriptor is different from the
+// connection's.  Attempting to change properties of the original
+// using this duplicate may or may not have the desired effect.
+func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }
+
+// ListenTCP announces on the TCP address laddr and returns a TCP
+// listener.  Net must be "tcp", "tcp4", or "tcp6".  If laddr has a
+// port of 0, ListenTCP will choose an available port.  The caller can
+// use the Addr method of TCPListener to retrieve the chosen address.
+func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+	default:
+		return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
+	}
+	if laddr == nil {
+		laddr = &TCPAddr{}
+	}
+	fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP)
+	if err != nil {
+		return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
+	}
+	return &TCPListener{fd}, nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsockopt_darwin.go b/third_party/gofrontend/libgo/go/net/tcpsockopt_darwin.go
new file mode 100644
index 0000000..3314084
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsockopt_darwin.go
@@ -0,0 +1,27 @@
+// 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.
+
+// TCP socket options for darwin
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+
+	// The kernel expects seconds so round to next highest second.
+	d += (time.Second - time.Nanosecond)
+	secs := int(d.Seconds())
+
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs))
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsockopt_dragonfly.go b/third_party/gofrontend/libgo/go/net/tcpsockopt_dragonfly.go
new file mode 100644
index 0000000..d10a777
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsockopt_dragonfly.go
@@ -0,0 +1,29 @@
+// 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 net
+
+import (
+	"os"
+	"syscall"
+	"time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+
+	// The kernel expects milliseconds so round to next highest millisecond.
+	d += (time.Millisecond - time.Nanosecond)
+	msecs := int(time.Duration(d.Nanoseconds()) / time.Millisecond)
+
+	err := os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, msecs))
+	if err != nil {
+		return err
+	}
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, msecs))
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsockopt_openbsd.go b/third_party/gofrontend/libgo/go/net/tcpsockopt_openbsd.go
new file mode 100644
index 0000000..3480f93
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsockopt_openbsd.go
@@ -0,0 +1,27 @@
+// 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.
+
+// TCP socket options for openbsd
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+
+	// The kernel expects seconds so round to next highest second.
+	d += (time.Second - time.Nanosecond)
+	secs := int(d.Seconds())
+
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.SO_KEEPALIVE, secs))
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsockopt_plan9.go b/third_party/gofrontend/libgo/go/net/tcpsockopt_plan9.go
new file mode 100644
index 0000000..0e7a664
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsockopt_plan9.go
@@ -0,0 +1,18 @@
+// Copyright 2014 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.
+
+// TCP socket options for plan9
+
+package net
+
+import (
+	"time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+	cmd := "keepalive " + string(int64(d/time.Millisecond))
+	_, e := fd.ctl.WriteAt([]byte(cmd), 0)
+	return e
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsockopt_posix.go b/third_party/gofrontend/libgo/go/net/tcpsockopt_posix.go
new file mode 100644
index 0000000..6484bad
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsockopt_posix.go
@@ -0,0 +1,20 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func setNoDelay(fd *netFD, noDelay bool) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay)))
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsockopt_solaris.go b/third_party/gofrontend/libgo/go/net/tcpsockopt_solaris.go
new file mode 100644
index 0000000..eaab6b6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsockopt_solaris.go
@@ -0,0 +1,27 @@
+// Copyright 2013 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.
+
+// TCP socket options for solaris
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+
+	// The kernel expects seconds so round to next highest second.
+	d += (time.Second - time.Nanosecond)
+	secs := int(d.Seconds())
+
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.SO_KEEPALIVE, secs))
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsockopt_unix.go b/third_party/gofrontend/libgo/go/net/tcpsockopt_unix.go
new file mode 100644
index 0000000..2693a54
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsockopt_unix.go
@@ -0,0 +1,31 @@
+// 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.
+
+// +build freebsd linux nacl netbsd
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+
+	// The kernel expects seconds so round to next highest second.
+	d += (time.Second - time.Nanosecond)
+	secs := int(d.Seconds())
+
+	err := os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs))
+	if err != nil {
+		return err
+	}
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs))
+}
diff --git a/third_party/gofrontend/libgo/go/net/tcpsockopt_windows.go b/third_party/gofrontend/libgo/go/net/tcpsockopt_windows.go
new file mode 100644
index 0000000..8ef1407
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/tcpsockopt_windows.go
@@ -0,0 +1,34 @@
+// 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.
+
+// TCP socket options for windows
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"time"
+	"unsafe"
+)
+
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+
+	// Windows expects milliseconds so round to next highest millisecond.
+	d += (time.Millisecond - time.Nanosecond)
+	millis := uint32(d / time.Millisecond)
+	ka := syscall.TCPKeepalive{
+		OnOff:    1,
+		Time:     millis,
+		Interval: millis,
+	}
+	ret := uint32(0)
+	size := uint32(unsafe.Sizeof(ka))
+	err := syscall.WSAIoctl(fd.sysfd, syscall.SIO_KEEPALIVE_VALS, (*byte)(unsafe.Pointer(&ka)), size, nil, 0, &ret, nil, 0)
+	return os.NewSyscallError("WSAIoctl", err)
+}
diff --git a/third_party/gofrontend/libgo/go/net/testdata/hosts b/third_party/gofrontend/libgo/go/net/testdata/hosts
new file mode 100644
index 0000000..b601763
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/testdata/hosts
@@ -0,0 +1,12 @@
+255.255.255.255	broadcasthost
+127.0.0.2	odin
+127.0.0.3	odin  # inline comment 
+::2             odin
+127.1.1.1	thor
+# aliases
+127.1.1.2	ullr ullrhost
+# Bogus entries that must be ignored.
+123.123.123	loki
+321.321.321.321
+# TODO(yvesj): Should we be able to parse this? From a Darwin system.
+fe80::1%lo0	localhost
diff --git a/third_party/gofrontend/libgo/go/net/testdata/hosts_singleline b/third_party/gofrontend/libgo/go/net/testdata/hosts_singleline
new file mode 100644
index 0000000..5f5f74a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/testdata/hosts_singleline
@@ -0,0 +1 @@
+127.0.0.2	odin
\ No newline at end of file
diff --git a/third_party/gofrontend/libgo/go/net/testdata/igmp b/third_party/gofrontend/libgo/go/net/testdata/igmp
new file mode 100644
index 0000000..5f380a2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/testdata/igmp
@@ -0,0 +1,24 @@
+Idx	Device    : Count Querier	Group    Users Timer	Reporter
+1	lo        :     1      V3
+				010000E0     1 0:00000000		0
+2	eth0      :     2      V2
+				FB0000E0     1 0:00000000		1
+				010000E0     1 0:00000000		0
+3	eth1      :     1      V3
+				010000E0     1 0:00000000		0
+4	eth2      :     1      V3
+				010000E0     1 0:00000000		0
+5	eth0.100  :     2      V3
+				FB0000E0     1 0:00000000		0
+				010000E0     1 0:00000000		0
+6	eth0.101  :     2      V3
+				FB0000E0     1 0:00000000		0
+				010000E0     1 0:00000000		0
+7	eth0.102  :     2      V3
+				FB0000E0     1 0:00000000		0
+				010000E0     1 0:00000000		0
+8	eth0.103  :     2      V3
+				FB0000E0     1 0:00000000		0
+				010000E0     1 0:00000000		0
+9	device1tap2:     1      V3
+				010000E0     1 0:00000000		0
diff --git a/third_party/gofrontend/libgo/go/net/testdata/igmp6 b/third_party/gofrontend/libgo/go/net/testdata/igmp6
new file mode 100644
index 0000000..6cd5a2d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/testdata/igmp6
@@ -0,0 +1,18 @@
+1    lo              ff020000000000000000000000000001     1 0000000C 0
+2    eth0            ff0200000000000000000001ffac891e     1 00000006 0
+2    eth0            ff020000000000000000000000000001     1 0000000C 0
+3    eth1            ff0200000000000000000001ffac8928     2 00000006 0
+3    eth1            ff020000000000000000000000000001     1 0000000C 0
+4    eth2            ff0200000000000000000001ffac8932     2 00000006 0
+4    eth2            ff020000000000000000000000000001     1 0000000C 0
+5    eth0.100        ff0200000000000000000001ffac891e     1 00000004 0
+5    eth0.100        ff020000000000000000000000000001     1 0000000C 0
+6    pan0            ff020000000000000000000000000001     1 0000000C 0
+7    eth0.101        ff0200000000000000000001ffac891e     1 00000004 0
+7    eth0.101        ff020000000000000000000000000001     1 0000000C 0
+8    eth0.102        ff0200000000000000000001ffac891e     1 00000004 0
+8    eth0.102        ff020000000000000000000000000001     1 0000000C 0
+9    eth0.103        ff0200000000000000000001ffac891e     1 00000004 0
+9    eth0.103        ff020000000000000000000000000001     1 0000000C 0
+10   device1tap2     ff0200000000000000000001ff4cc3a3     1 00000004 0
+10   device1tap2     ff020000000000000000000000000001     1 0000000C 0
diff --git a/third_party/gofrontend/libgo/go/net/testdata/resolv.conf b/third_party/gofrontend/libgo/go/net/testdata/resolv.conf
new file mode 100644
index 0000000..3841bbf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/testdata/resolv.conf
@@ -0,0 +1,6 @@
+# /etc/resolv.conf
+
+domain Home
+nameserver 192.168.1.1
+options ndots:5 timeout:10 attempts:3 rotate
+options attempts 3
diff --git a/third_party/gofrontend/libgo/go/net/textproto/header.go b/third_party/gofrontend/libgo/go/net/textproto/header.go
new file mode 100644
index 0000000..7fb32f8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/textproto/header.go
@@ -0,0 +1,43 @@
+// Copyright 2010 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 textproto
+
+// A MIMEHeader represents a MIME-style header mapping
+// keys to sets of values.
+type MIMEHeader map[string][]string
+
+// Add adds the key, value pair to the header.
+// It appends to any existing values associated with key.
+func (h MIMEHeader) Add(key, value string) {
+	key = CanonicalMIMEHeaderKey(key)
+	h[key] = append(h[key], value)
+}
+
+// Set sets the header entries associated with key to
+// the single element value.  It replaces any existing
+// values associated with key.
+func (h MIMEHeader) Set(key, value string) {
+	h[CanonicalMIMEHeaderKey(key)] = []string{value}
+}
+
+// Get gets the first value associated with the given key.
+// If there are no values associated with the key, Get returns "".
+// Get is a convenience method.  For more complex queries,
+// access the map directly.
+func (h MIMEHeader) Get(key string) string {
+	if h == nil {
+		return ""
+	}
+	v := h[CanonicalMIMEHeaderKey(key)]
+	if len(v) == 0 {
+		return ""
+	}
+	return v[0]
+}
+
+// Del deletes the values associated with key.
+func (h MIMEHeader) Del(key string) {
+	delete(h, CanonicalMIMEHeaderKey(key))
+}
diff --git a/third_party/gofrontend/libgo/go/net/textproto/pipeline.go b/third_party/gofrontend/libgo/go/net/textproto/pipeline.go
new file mode 100644
index 0000000..ca50edd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/textproto/pipeline.go
@@ -0,0 +1,117 @@
+// Copyright 2010 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 textproto
+
+import (
+	"sync"
+)
+
+// A Pipeline manages a pipelined in-order request/response sequence.
+//
+// To use a Pipeline p to manage multiple clients on a connection,
+// each client should run:
+//
+//	id := p.Next()	// take a number
+//
+//	p.StartRequest(id)	// wait for turn to send request
+//	«send request»
+//	p.EndRequest(id)	// notify Pipeline that request is sent
+//
+//	p.StartResponse(id)	// wait for turn to read response
+//	«read response»
+//	p.EndResponse(id)	// notify Pipeline that response is read
+//
+// A pipelined server can use the same calls to ensure that
+// responses computed in parallel are written in the correct order.
+type Pipeline struct {
+	mu       sync.Mutex
+	id       uint
+	request  sequencer
+	response sequencer
+}
+
+// Next returns the next id for a request/response pair.
+func (p *Pipeline) Next() uint {
+	p.mu.Lock()
+	id := p.id
+	p.id++
+	p.mu.Unlock()
+	return id
+}
+
+// StartRequest blocks until it is time to send (or, if this is a server, receive)
+// the request with the given id.
+func (p *Pipeline) StartRequest(id uint) {
+	p.request.Start(id)
+}
+
+// EndRequest notifies p that the request with the given id has been sent
+// (or, if this is a server, received).
+func (p *Pipeline) EndRequest(id uint) {
+	p.request.End(id)
+}
+
+// StartResponse blocks until it is time to receive (or, if this is a server, send)
+// the request with the given id.
+func (p *Pipeline) StartResponse(id uint) {
+	p.response.Start(id)
+}
+
+// EndResponse notifies p that the response with the given id has been received
+// (or, if this is a server, sent).
+func (p *Pipeline) EndResponse(id uint) {
+	p.response.End(id)
+}
+
+// A sequencer schedules a sequence of numbered events that must
+// happen in order, one after the other.  The event numbering must start
+// at 0 and increment without skipping.  The event number wraps around
+// safely as long as there are not 2^32 simultaneous events pending.
+type sequencer struct {
+	mu   sync.Mutex
+	id   uint
+	wait map[uint]chan uint
+}
+
+// Start waits until it is time for the event numbered id to begin.
+// That is, except for the first event, it waits until End(id-1) has
+// been called.
+func (s *sequencer) Start(id uint) {
+	s.mu.Lock()
+	if s.id == id {
+		s.mu.Unlock()
+		return
+	}
+	c := make(chan uint)
+	if s.wait == nil {
+		s.wait = make(map[uint]chan uint)
+	}
+	s.wait[id] = c
+	s.mu.Unlock()
+	<-c
+}
+
+// End notifies the sequencer that the event numbered id has completed,
+// allowing it to schedule the event numbered id+1.  It is a run-time error
+// to call End with an id that is not the number of the active event.
+func (s *sequencer) End(id uint) {
+	s.mu.Lock()
+	if s.id != id {
+		panic("out of sync")
+	}
+	id++
+	s.id = id
+	if s.wait == nil {
+		s.wait = make(map[uint]chan uint)
+	}
+	c, ok := s.wait[id]
+	if ok {
+		delete(s.wait, id)
+	}
+	s.mu.Unlock()
+	if ok {
+		c <- 1
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/textproto/reader.go b/third_party/gofrontend/libgo/go/net/textproto/reader.go
new file mode 100644
index 0000000..eea9207
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/textproto/reader.go
@@ -0,0 +1,637 @@
+// Copyright 2010 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 textproto
+
+import (
+	"bufio"
+	"bytes"
+	"io"
+	"io/ioutil"
+	"strconv"
+	"strings"
+)
+
+// BUG(rsc): To let callers manage exposure to denial of service
+// attacks, Reader should allow them to set and reset a limit on
+// the number of bytes read from the connection.
+
+// A Reader implements convenience methods for reading requests
+// or responses from a text protocol network connection.
+type Reader struct {
+	R   *bufio.Reader
+	dot *dotReader
+	buf []byte // a re-usable buffer for readContinuedLineSlice
+}
+
+// NewReader returns a new Reader reading from r.
+func NewReader(r *bufio.Reader) *Reader {
+	return &Reader{R: r}
+}
+
+// ReadLine reads a single line from r,
+// eliding the final \n or \r\n from the returned string.
+func (r *Reader) ReadLine() (string, error) {
+	line, err := r.readLineSlice()
+	return string(line), err
+}
+
+// ReadLineBytes is like ReadLine but returns a []byte instead of a string.
+func (r *Reader) ReadLineBytes() ([]byte, error) {
+	line, err := r.readLineSlice()
+	if line != nil {
+		buf := make([]byte, len(line))
+		copy(buf, line)
+		line = buf
+	}
+	return line, err
+}
+
+func (r *Reader) readLineSlice() ([]byte, error) {
+	r.closeDot()
+	var line []byte
+	for {
+		l, more, err := r.R.ReadLine()
+		if err != nil {
+			return nil, err
+		}
+		// Avoid the copy if the first call produced a full line.
+		if line == nil && !more {
+			return l, nil
+		}
+		line = append(line, l...)
+		if !more {
+			break
+		}
+	}
+	return line, nil
+}
+
+// ReadContinuedLine reads a possibly continued line from r,
+// eliding the final trailing ASCII white space.
+// Lines after the first are considered continuations if they
+// begin with a space or tab character.  In the returned data,
+// continuation lines are separated from the previous line
+// only by a single space: the newline and leading white space
+// are removed.
+//
+// For example, consider this input:
+//
+//	Line 1
+//	  continued...
+//	Line 2
+//
+// The first call to ReadContinuedLine will return "Line 1 continued..."
+// and the second will return "Line 2".
+//
+// A line consisting of only white space is never continued.
+//
+func (r *Reader) ReadContinuedLine() (string, error) {
+	line, err := r.readContinuedLineSlice()
+	return string(line), err
+}
+
+// trim returns s with leading and trailing spaces and tabs removed.
+// It does not assume Unicode or UTF-8.
+func trim(s []byte) []byte {
+	i := 0
+	for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
+		i++
+	}
+	n := len(s)
+	for n > i && (s[n-1] == ' ' || s[n-1] == '\t') {
+		n--
+	}
+	return s[i:n]
+}
+
+// ReadContinuedLineBytes is like ReadContinuedLine but
+// returns a []byte instead of a string.
+func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
+	line, err := r.readContinuedLineSlice()
+	if line != nil {
+		buf := make([]byte, len(line))
+		copy(buf, line)
+		line = buf
+	}
+	return line, err
+}
+
+func (r *Reader) readContinuedLineSlice() ([]byte, error) {
+	// Read the first line.
+	line, err := r.readLineSlice()
+	if err != nil {
+		return nil, err
+	}
+	if len(line) == 0 { // blank line - no continuation
+		return line, nil
+	}
+
+	// Optimistically assume that we have started to buffer the next line
+	// and it starts with an ASCII letter (the next header key), so we can
+	// avoid copying that buffered data around in memory and skipping over
+	// non-existent whitespace.
+	if r.R.Buffered() > 1 {
+		peek, err := r.R.Peek(1)
+		if err == nil && isASCIILetter(peek[0]) {
+			return trim(line), nil
+		}
+	}
+
+	// ReadByte or the next readLineSlice will flush the read buffer;
+	// copy the slice into buf.
+	r.buf = append(r.buf[:0], trim(line)...)
+
+	// Read continuation lines.
+	for r.skipSpace() > 0 {
+		line, err := r.readLineSlice()
+		if err != nil {
+			break
+		}
+		r.buf = append(r.buf, ' ')
+		r.buf = append(r.buf, line...)
+	}
+	return r.buf, nil
+}
+
+// skipSpace skips R over all spaces and returns the number of bytes skipped.
+func (r *Reader) skipSpace() int {
+	n := 0
+	for {
+		c, err := r.R.ReadByte()
+		if err != nil {
+			// Bufio will keep err until next read.
+			break
+		}
+		if c != ' ' && c != '\t' {
+			r.R.UnreadByte()
+			break
+		}
+		n++
+	}
+	return n
+}
+
+func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message string, err error) {
+	line, err := r.ReadLine()
+	if err != nil {
+		return
+	}
+	return parseCodeLine(line, expectCode)
+}
+
+func parseCodeLine(line string, expectCode int) (code int, continued bool, message string, err error) {
+	if len(line) < 4 || line[3] != ' ' && line[3] != '-' {
+		err = ProtocolError("short response: " + line)
+		return
+	}
+	continued = line[3] == '-'
+	code, err = strconv.Atoi(line[0:3])
+	if err != nil || code < 100 {
+		err = ProtocolError("invalid response code: " + line)
+		return
+	}
+	message = line[4:]
+	if 1 <= expectCode && expectCode < 10 && code/100 != expectCode ||
+		10 <= expectCode && expectCode < 100 && code/10 != expectCode ||
+		100 <= expectCode && expectCode < 1000 && code != expectCode {
+		err = &Error{code, message}
+	}
+	return
+}
+
+// ReadCodeLine reads a response code line of the form
+//	code message
+// where code is a three-digit status code and the message
+// extends to the rest of the line.  An example of such a line is:
+//	220 plan9.bell-labs.com ESMTP
+//
+// If the prefix of the status does not match the digits in expectCode,
+// ReadCodeLine returns with err set to &Error{code, message}.
+// For example, if expectCode is 31, an error will be returned if
+// the status is not in the range [310,319].
+//
+// If the response is multi-line, ReadCodeLine returns an error.
+//
+// An expectCode <= 0 disables the check of the status code.
+//
+func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err error) {
+	code, continued, message, err := r.readCodeLine(expectCode)
+	if err == nil && continued {
+		err = ProtocolError("unexpected multi-line response: " + message)
+	}
+	return
+}
+
+// ReadResponse reads a multi-line response of the form:
+//
+//	code-message line 1
+//	code-message line 2
+//	...
+//	code message line n
+//
+// where code is a three-digit status code. The first line starts with the
+// code and a hyphen. The response is terminated by a line that starts
+// with the same code followed by a space. Each line in message is
+// separated by a newline (\n).
+//
+// See page 36 of RFC 959 (http://www.ietf.org/rfc/rfc959.txt) for
+// details.
+//
+// If the prefix of the status does not match the digits in expectCode,
+// ReadResponse returns with err set to &Error{code, message}.
+// For example, if expectCode is 31, an error will be returned if
+// the status is not in the range [310,319].
+//
+// An expectCode <= 0 disables the check of the status code.
+//
+func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) {
+	code, continued, message, err := r.readCodeLine(expectCode)
+	for err == nil && continued {
+		line, err := r.ReadLine()
+		if err != nil {
+			return 0, "", err
+		}
+
+		var code2 int
+		var moreMessage string
+		code2, continued, moreMessage, err = parseCodeLine(line, expectCode)
+		if err != nil || code2 != code {
+			message += "\n" + strings.TrimRight(line, "\r\n")
+			continued = true
+			continue
+		}
+		message += "\n" + moreMessage
+	}
+	return
+}
+
+// DotReader returns a new Reader that satisfies Reads using the
+// decoded text of a dot-encoded block read from r.
+// The returned Reader is only valid until the next call
+// to a method on r.
+//
+// Dot encoding is a common framing used for data blocks
+// in text protocols such as SMTP.  The data consists of a sequence
+// of lines, each of which ends in "\r\n".  The sequence itself
+// ends at a line containing just a dot: ".\r\n".  Lines beginning
+// with a dot are escaped with an additional dot to avoid
+// looking like the end of the sequence.
+//
+// The decoded form returned by the Reader's Read method
+// rewrites the "\r\n" line endings into the simpler "\n",
+// removes leading dot escapes if present, and stops with error io.EOF
+// after consuming (and discarding) the end-of-sequence line.
+func (r *Reader) DotReader() io.Reader {
+	r.closeDot()
+	r.dot = &dotReader{r: r}
+	return r.dot
+}
+
+type dotReader struct {
+	r     *Reader
+	state int
+}
+
+// Read satisfies reads by decoding dot-encoded data read from d.r.
+func (d *dotReader) Read(b []byte) (n int, err error) {
+	// Run data through a simple state machine to
+	// elide leading dots, rewrite trailing \r\n into \n,
+	// and detect ending .\r\n line.
+	const (
+		stateBeginLine = iota // beginning of line; initial state; must be zero
+		stateDot              // read . at beginning of line
+		stateDotCR            // read .\r at beginning of line
+		stateCR               // read \r (possibly at end of line)
+		stateData             // reading data in middle of line
+		stateEOF              // reached .\r\n end marker line
+	)
+	br := d.r.R
+	for n < len(b) && d.state != stateEOF {
+		var c byte
+		c, err = br.ReadByte()
+		if err != nil {
+			if err == io.EOF {
+				err = io.ErrUnexpectedEOF
+			}
+			break
+		}
+		switch d.state {
+		case stateBeginLine:
+			if c == '.' {
+				d.state = stateDot
+				continue
+			}
+			if c == '\r' {
+				d.state = stateCR
+				continue
+			}
+			d.state = stateData
+
+		case stateDot:
+			if c == '\r' {
+				d.state = stateDotCR
+				continue
+			}
+			if c == '\n' {
+				d.state = stateEOF
+				continue
+			}
+			d.state = stateData
+
+		case stateDotCR:
+			if c == '\n' {
+				d.state = stateEOF
+				continue
+			}
+			// Not part of .\r\n.
+			// Consume leading dot and emit saved \r.
+			br.UnreadByte()
+			c = '\r'
+			d.state = stateData
+
+		case stateCR:
+			if c == '\n' {
+				d.state = stateBeginLine
+				break
+			}
+			// Not part of \r\n.  Emit saved \r
+			br.UnreadByte()
+			c = '\r'
+			d.state = stateData
+
+		case stateData:
+			if c == '\r' {
+				d.state = stateCR
+				continue
+			}
+			if c == '\n' {
+				d.state = stateBeginLine
+			}
+		}
+		b[n] = c
+		n++
+	}
+	if err == nil && d.state == stateEOF {
+		err = io.EOF
+	}
+	if err != nil && d.r.dot == d {
+		d.r.dot = nil
+	}
+	return
+}
+
+// closeDot drains the current DotReader if any,
+// making sure that it reads until the ending dot line.
+func (r *Reader) closeDot() {
+	if r.dot == nil {
+		return
+	}
+	buf := make([]byte, 128)
+	for r.dot != nil {
+		// When Read reaches EOF or an error,
+		// it will set r.dot == nil.
+		r.dot.Read(buf)
+	}
+}
+
+// ReadDotBytes reads a dot-encoding and returns the decoded data.
+//
+// See the documentation for the DotReader method for details about dot-encoding.
+func (r *Reader) ReadDotBytes() ([]byte, error) {
+	return ioutil.ReadAll(r.DotReader())
+}
+
+// ReadDotLines reads a dot-encoding and returns a slice
+// containing the decoded lines, with the final \r\n or \n elided from each.
+//
+// See the documentation for the DotReader method for details about dot-encoding.
+func (r *Reader) ReadDotLines() ([]string, error) {
+	// We could use ReadDotBytes and then Split it,
+	// but reading a line at a time avoids needing a
+	// large contiguous block of memory and is simpler.
+	var v []string
+	var err error
+	for {
+		var line string
+		line, err = r.ReadLine()
+		if err != nil {
+			if err == io.EOF {
+				err = io.ErrUnexpectedEOF
+			}
+			break
+		}
+
+		// Dot by itself marks end; otherwise cut one dot.
+		if len(line) > 0 && line[0] == '.' {
+			if len(line) == 1 {
+				break
+			}
+			line = line[1:]
+		}
+		v = append(v, line)
+	}
+	return v, err
+}
+
+// ReadMIMEHeader reads a MIME-style header from r.
+// The header is a sequence of possibly continued Key: Value lines
+// ending in a blank line.
+// The returned map m maps CanonicalMIMEHeaderKey(key) to a
+// sequence of values in the same order encountered in the input.
+//
+// For example, consider this input:
+//
+//	My-Key: Value 1
+//	Long-Key: Even
+//	       Longer Value
+//	My-Key: Value 2
+//
+// Given that input, ReadMIMEHeader returns the map:
+//
+//	map[string][]string{
+//		"My-Key": {"Value 1", "Value 2"},
+//		"Long-Key": {"Even Longer Value"},
+//	}
+//
+func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
+	// Avoid lots of small slice allocations later by allocating one
+	// large one ahead of time which we'll cut up into smaller
+	// slices. If this isn't big enough later, we allocate small ones.
+	var strs []string
+	hint := r.upcomingHeaderNewlines()
+	if hint > 0 {
+		strs = make([]string, hint)
+	}
+
+	m := make(MIMEHeader, hint)
+	for {
+		kv, err := r.readContinuedLineSlice()
+		if len(kv) == 0 {
+			return m, err
+		}
+
+		// Key ends at first colon; should not have spaces but
+		// they appear in the wild, violating specs, so we
+		// remove them if present.
+		i := bytes.IndexByte(kv, ':')
+		if i < 0 {
+			return m, ProtocolError("malformed MIME header line: " + string(kv))
+		}
+		endKey := i
+		for endKey > 0 && kv[endKey-1] == ' ' {
+			endKey--
+		}
+		key := canonicalMIMEHeaderKey(kv[:endKey])
+
+		// Skip initial spaces in value.
+		i++ // skip colon
+		for i < len(kv) && (kv[i] == ' ' || kv[i] == '\t') {
+			i++
+		}
+		value := string(kv[i:])
+
+		vv := m[key]
+		if vv == nil && len(strs) > 0 {
+			// More than likely this will be a single-element key.
+			// Most headers aren't multi-valued.
+			// Set the capacity on strs[0] to 1, so any future append
+			// won't extend the slice into the other strings.
+			vv, strs = strs[:1:1], strs[1:]
+			vv[0] = value
+			m[key] = vv
+		} else {
+			m[key] = append(vv, value)
+		}
+
+		if err != nil {
+			return m, err
+		}
+	}
+}
+
+// upcomingHeaderNewlines returns an approximation of the number of newlines
+// that will be in this header. If it gets confused, it returns 0.
+func (r *Reader) upcomingHeaderNewlines() (n int) {
+	// Try to determine the 'hint' size.
+	r.R.Peek(1) // force a buffer load if empty
+	s := r.R.Buffered()
+	if s == 0 {
+		return
+	}
+	peek, _ := r.R.Peek(s)
+	for len(peek) > 0 {
+		i := bytes.IndexByte(peek, '\n')
+		if i < 3 {
+			// Not present (-1) or found within the next few bytes,
+			// implying we're at the end ("\r\n\r\n" or "\n\n")
+			return
+		}
+		n++
+		peek = peek[i+1:]
+	}
+	return
+}
+
+// CanonicalMIMEHeaderKey returns the canonical format of the
+// MIME header key s.  The canonicalization converts the first
+// letter and any letter following a hyphen to upper case;
+// the rest are converted to lowercase.  For example, the
+// canonical key for "accept-encoding" is "Accept-Encoding".
+// MIME header keys are assumed to be ASCII only.
+func CanonicalMIMEHeaderKey(s string) string {
+	// Quick check for canonical encoding.
+	upper := true
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		if upper && 'a' <= c && c <= 'z' {
+			return canonicalMIMEHeaderKey([]byte(s))
+		}
+		if !upper && 'A' <= c && c <= 'Z' {
+			return canonicalMIMEHeaderKey([]byte(s))
+		}
+		upper = c == '-'
+	}
+	return s
+}
+
+const toLower = 'a' - 'A'
+
+// canonicalMIMEHeaderKey is like CanonicalMIMEHeaderKey but is
+// allowed to mutate the provided byte slice before returning the
+// string.
+func canonicalMIMEHeaderKey(a []byte) string {
+	upper := true
+	for i, c := range a {
+		// Canonicalize: first letter upper case
+		// and upper case after each dash.
+		// (Host, User-Agent, If-Modified-Since).
+		// MIME headers are ASCII only, so no Unicode issues.
+		if c == ' ' {
+			c = '-'
+		} else if upper && 'a' <= c && c <= 'z' {
+			c -= toLower
+		} else if !upper && 'A' <= c && c <= 'Z' {
+			c += toLower
+		}
+		a[i] = c
+		upper = c == '-' // for next time
+	}
+	// The compiler recognizes m[string(byteSlice)] as a special
+	// case, so a copy of a's bytes into a new string does not
+	// happen in this map lookup:
+	if v := commonHeader[string(a)]; v != "" {
+		return v
+	}
+	return string(a)
+}
+
+// commonHeader interns common header strings.
+var commonHeader = make(map[string]string)
+
+func init() {
+	for _, v := range []string{
+		"Accept",
+		"Accept-Charset",
+		"Accept-Encoding",
+		"Accept-Language",
+		"Accept-Ranges",
+		"Cache-Control",
+		"Cc",
+		"Connection",
+		"Content-Id",
+		"Content-Language",
+		"Content-Length",
+		"Content-Transfer-Encoding",
+		"Content-Type",
+		"Cookie",
+		"Date",
+		"Dkim-Signature",
+		"Etag",
+		"Expires",
+		"From",
+		"Host",
+		"If-Modified-Since",
+		"If-None-Match",
+		"In-Reply-To",
+		"Last-Modified",
+		"Location",
+		"Message-Id",
+		"Mime-Version",
+		"Pragma",
+		"Received",
+		"Return-Path",
+		"Server",
+		"Set-Cookie",
+		"Subject",
+		"To",
+		"User-Agent",
+		"Via",
+		"X-Forwarded-For",
+		"X-Imforwards",
+		"X-Powered-By",
+	} {
+		commonHeader[v] = v
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/textproto/reader_test.go b/third_party/gofrontend/libgo/go/net/textproto/reader_test.go
new file mode 100644
index 0000000..c895666
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/textproto/reader_test.go
@@ -0,0 +1,338 @@
+// Copyright 2010 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 textproto
+
+import (
+	"bufio"
+	"bytes"
+	"io"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+type canonicalHeaderKeyTest struct {
+	in, out string
+}
+
+var canonicalHeaderKeyTests = []canonicalHeaderKeyTest{
+	{"a-b-c", "A-B-C"},
+	{"a-1-c", "A-1-C"},
+	{"User-Agent", "User-Agent"},
+	{"uSER-aGENT", "User-Agent"},
+	{"user-agent", "User-Agent"},
+	{"USER-AGENT", "User-Agent"},
+	{"üser-agenT", "üser-Agent"}, // non-ASCII unchanged
+
+	// This caused a panic due to mishandling of a space:
+	{"C Ontent-Transfer-Encoding", "C-Ontent-Transfer-Encoding"},
+	{"foo bar", "Foo-Bar"},
+}
+
+func TestCanonicalMIMEHeaderKey(t *testing.T) {
+	for _, tt := range canonicalHeaderKeyTests {
+		if s := CanonicalMIMEHeaderKey(tt.in); s != tt.out {
+			t.Errorf("CanonicalMIMEHeaderKey(%q) = %q, want %q", tt.in, s, tt.out)
+		}
+	}
+}
+
+func reader(s string) *Reader {
+	return NewReader(bufio.NewReader(strings.NewReader(s)))
+}
+
+func TestReadLine(t *testing.T) {
+	r := reader("line1\nline2\n")
+	s, err := r.ReadLine()
+	if s != "line1" || err != nil {
+		t.Fatalf("Line 1: %s, %v", s, err)
+	}
+	s, err = r.ReadLine()
+	if s != "line2" || err != nil {
+		t.Fatalf("Line 2: %s, %v", s, err)
+	}
+	s, err = r.ReadLine()
+	if s != "" || err != io.EOF {
+		t.Fatalf("EOF: %s, %v", s, err)
+	}
+}
+
+func TestReadContinuedLine(t *testing.T) {
+	r := reader("line1\nline\n 2\nline3\n")
+	s, err := r.ReadContinuedLine()
+	if s != "line1" || err != nil {
+		t.Fatalf("Line 1: %s, %v", s, err)
+	}
+	s, err = r.ReadContinuedLine()
+	if s != "line 2" || err != nil {
+		t.Fatalf("Line 2: %s, %v", s, err)
+	}
+	s, err = r.ReadContinuedLine()
+	if s != "line3" || err != nil {
+		t.Fatalf("Line 3: %s, %v", s, err)
+	}
+	s, err = r.ReadContinuedLine()
+	if s != "" || err != io.EOF {
+		t.Fatalf("EOF: %s, %v", s, err)
+	}
+}
+
+func TestReadCodeLine(t *testing.T) {
+	r := reader("123 hi\n234 bye\n345 no way\n")
+	code, msg, err := r.ReadCodeLine(0)
+	if code != 123 || msg != "hi" || err != nil {
+		t.Fatalf("Line 1: %d, %s, %v", code, msg, err)
+	}
+	code, msg, err = r.ReadCodeLine(23)
+	if code != 234 || msg != "bye" || err != nil {
+		t.Fatalf("Line 2: %d, %s, %v", code, msg, err)
+	}
+	code, msg, err = r.ReadCodeLine(346)
+	if code != 345 || msg != "no way" || err == nil {
+		t.Fatalf("Line 3: %d, %s, %v", code, msg, err)
+	}
+	if e, ok := err.(*Error); !ok || e.Code != code || e.Msg != msg {
+		t.Fatalf("Line 3: wrong error %v\n", err)
+	}
+	code, msg, err = r.ReadCodeLine(1)
+	if code != 0 || msg != "" || err != io.EOF {
+		t.Fatalf("EOF: %d, %s, %v", code, msg, err)
+	}
+}
+
+func TestReadDotLines(t *testing.T) {
+	r := reader("dotlines\r\n.foo\r\n..bar\n...baz\nquux\r\n\r\n.\r\nanother\n")
+	s, err := r.ReadDotLines()
+	want := []string{"dotlines", "foo", ".bar", "..baz", "quux", ""}
+	if !reflect.DeepEqual(s, want) || err != nil {
+		t.Fatalf("ReadDotLines: %v, %v", s, err)
+	}
+
+	s, err = r.ReadDotLines()
+	want = []string{"another"}
+	if !reflect.DeepEqual(s, want) || err != io.ErrUnexpectedEOF {
+		t.Fatalf("ReadDotLines2: %v, %v", s, err)
+	}
+}
+
+func TestReadDotBytes(t *testing.T) {
+	r := reader("dotlines\r\n.foo\r\n..bar\n...baz\nquux\r\n\r\n.\r\nanot.her\r\n")
+	b, err := r.ReadDotBytes()
+	want := []byte("dotlines\nfoo\n.bar\n..baz\nquux\n\n")
+	if !reflect.DeepEqual(b, want) || err != nil {
+		t.Fatalf("ReadDotBytes: %q, %v", b, err)
+	}
+
+	b, err = r.ReadDotBytes()
+	want = []byte("anot.her\n")
+	if !reflect.DeepEqual(b, want) || err != io.ErrUnexpectedEOF {
+		t.Fatalf("ReadDotBytes2: %q, %v", b, err)
+	}
+}
+
+func TestReadMIMEHeader(t *testing.T) {
+	r := reader("my-key: Value 1  \r\nLong-key: Even \n Longer Value\r\nmy-Key: Value 2\r\n\n")
+	m, err := r.ReadMIMEHeader()
+	want := MIMEHeader{
+		"My-Key":   {"Value 1", "Value 2"},
+		"Long-Key": {"Even Longer Value"},
+	}
+	if !reflect.DeepEqual(m, want) || err != nil {
+		t.Fatalf("ReadMIMEHeader: %v, %v; want %v", m, err, want)
+	}
+}
+
+func TestReadMIMEHeaderSingle(t *testing.T) {
+	r := reader("Foo: bar\n\n")
+	m, err := r.ReadMIMEHeader()
+	want := MIMEHeader{"Foo": {"bar"}}
+	if !reflect.DeepEqual(m, want) || err != nil {
+		t.Fatalf("ReadMIMEHeader: %v, %v; want %v", m, err, want)
+	}
+}
+
+func TestLargeReadMIMEHeader(t *testing.T) {
+	data := make([]byte, 16*1024)
+	for i := 0; i < len(data); i++ {
+		data[i] = 'x'
+	}
+	sdata := string(data)
+	r := reader("Cookie: " + sdata + "\r\n\n")
+	m, err := r.ReadMIMEHeader()
+	if err != nil {
+		t.Fatalf("ReadMIMEHeader: %v", err)
+	}
+	cookie := m.Get("Cookie")
+	if cookie != sdata {
+		t.Fatalf("ReadMIMEHeader: %v bytes, want %v bytes", len(cookie), len(sdata))
+	}
+}
+
+// Test that we read slightly-bogus MIME headers seen in the wild,
+// with spaces before colons, and spaces in keys.
+func TestReadMIMEHeaderNonCompliant(t *testing.T) {
+	// Invalid HTTP response header as sent by an Axis security
+	// camera: (this is handled by IE, Firefox, Chrome, curl, etc.)
+	r := reader("Foo: bar\r\n" +
+		"Content-Language: en\r\n" +
+		"SID : 0\r\n" +
+		"Audio Mode : None\r\n" +
+		"Privilege : 127\r\n\r\n")
+	m, err := r.ReadMIMEHeader()
+	want := MIMEHeader{
+		"Foo":              {"bar"},
+		"Content-Language": {"en"},
+		"Sid":              {"0"},
+		"Audio-Mode":       {"None"},
+		"Privilege":        {"127"},
+	}
+	if !reflect.DeepEqual(m, want) || err != nil {
+		t.Fatalf("ReadMIMEHeader =\n%v, %v; want:\n%v", m, err, want)
+	}
+}
+
+type readResponseTest struct {
+	in       string
+	inCode   int
+	wantCode int
+	wantMsg  string
+}
+
+var readResponseTests = []readResponseTest{
+	{"230-Anonymous access granted, restrictions apply\n" +
+		"Read the file README.txt,\n" +
+		"230  please",
+		23,
+		230,
+		"Anonymous access granted, restrictions apply\nRead the file README.txt,\n please",
+	},
+
+	{"230 Anonymous access granted, restrictions apply\n",
+		23,
+		230,
+		"Anonymous access granted, restrictions apply",
+	},
+
+	{"400-A\n400-B\n400 C",
+		4,
+		400,
+		"A\nB\nC",
+	},
+
+	{"400-A\r\n400-B\r\n400 C\r\n",
+		4,
+		400,
+		"A\nB\nC",
+	},
+}
+
+// See http://www.ietf.org/rfc/rfc959.txt page 36.
+func TestRFC959Lines(t *testing.T) {
+	for i, tt := range readResponseTests {
+		r := reader(tt.in + "\nFOLLOWING DATA")
+		code, msg, err := r.ReadResponse(tt.inCode)
+		if err != nil {
+			t.Errorf("#%d: ReadResponse: %v", i, err)
+			continue
+		}
+		if code != tt.wantCode {
+			t.Errorf("#%d: code=%d, want %d", i, code, tt.wantCode)
+		}
+		if msg != tt.wantMsg {
+			t.Errorf("#%d: msg=%q, want %q", i, msg, tt.wantMsg)
+		}
+	}
+}
+
+func TestCommonHeaders(t *testing.T) {
+	for h := range commonHeader {
+		if h != CanonicalMIMEHeaderKey(h) {
+			t.Errorf("Non-canonical header %q in commonHeader", h)
+		}
+	}
+	t.Skip("gccgo escape analysis")
+	b := []byte("content-Length")
+	want := "Content-Length"
+	n := testing.AllocsPerRun(200, func() {
+		if x := canonicalMIMEHeaderKey(b); x != want {
+			t.Fatalf("canonicalMIMEHeaderKey(%q) = %q; want %q", b, x, want)
+		}
+	})
+	if n > 0 {
+		t.Errorf("canonicalMIMEHeaderKey allocs = %v; want 0", n)
+	}
+}
+
+var clientHeaders = strings.Replace(`Host: golang.org
+Connection: keep-alive
+Cache-Control: max-age=0
+Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
+User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3
+Accept-Encoding: gzip,deflate,sdch
+Accept-Language: en-US,en;q=0.8,fr-CH;q=0.6
+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
+COOKIE: __utma=000000000.0000000000.0000000000.0000000000.0000000000.00; __utmb=000000000.0.00.0000000000; __utmc=000000000; __utmz=000000000.0000000000.00.0.utmcsr=code.google.com|utmccn=(referral)|utmcmd=referral|utmcct=/p/go/issues/detail
+Non-Interned: test
+
+`, "\n", "\r\n", -1)
+
+var serverHeaders = strings.Replace(`Content-Type: text/html; charset=utf-8
+Content-Encoding: gzip
+Date: Thu, 27 Sep 2012 09:03:33 GMT
+Server: Google Frontend
+Cache-Control: private
+Content-Length: 2298
+VIA: 1.1 proxy.example.com:80 (XXX/n.n.n-nnn)
+Connection: Close
+Non-Interned: test
+
+`, "\n", "\r\n", -1)
+
+func BenchmarkReadMIMEHeader(b *testing.B) {
+	b.ReportAllocs()
+	var buf bytes.Buffer
+	br := bufio.NewReader(&buf)
+	r := NewReader(br)
+	for i := 0; i < b.N; i++ {
+		var want int
+		var find string
+		if (i & 1) == 1 {
+			buf.WriteString(clientHeaders)
+			want = 10
+			find = "Cookie"
+		} else {
+			buf.WriteString(serverHeaders)
+			want = 9
+			find = "Via"
+		}
+		h, err := r.ReadMIMEHeader()
+		if err != nil {
+			b.Fatal(err)
+		}
+		if len(h) != want {
+			b.Fatalf("wrong number of headers: got %d, want %d", len(h), want)
+		}
+		if _, ok := h[find]; !ok {
+			b.Fatalf("did not find key %s", find)
+		}
+	}
+}
+
+func BenchmarkUncommon(b *testing.B) {
+	b.ReportAllocs()
+	var buf bytes.Buffer
+	br := bufio.NewReader(&buf)
+	r := NewReader(br)
+	for i := 0; i < b.N; i++ {
+		buf.WriteString("uncommon-header-for-benchmark: foo\r\n\r\n")
+		h, err := r.ReadMIMEHeader()
+		if err != nil {
+			b.Fatal(err)
+		}
+		if _, ok := h["Uncommon-Header-For-Benchmark"]; !ok {
+			b.Fatal("Missing result header.")
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/textproto/textproto.go b/third_party/gofrontend/libgo/go/net/textproto/textproto.go
new file mode 100644
index 0000000..026eb02
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/textproto/textproto.go
@@ -0,0 +1,154 @@
+// Copyright 2010 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 textproto implements generic support for text-based request/response
+// protocols in the style of HTTP, NNTP, and SMTP.
+//
+// The package provides:
+//
+// Error, which represents a numeric error response from
+// a server.
+//
+// Pipeline, to manage pipelined requests and responses
+// in a client.
+//
+// Reader, to read numeric response code lines,
+// key: value headers, lines wrapped with leading spaces
+// on continuation lines, and whole text blocks ending
+// with a dot on a line by itself.
+//
+// Writer, to write dot-encoded text blocks.
+//
+// Conn, a convenient packaging of Reader, Writer, and Pipeline for use
+// with a single network connection.
+//
+package textproto
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"net"
+)
+
+// An Error represents a numeric error response from a server.
+type Error struct {
+	Code int
+	Msg  string
+}
+
+func (e *Error) Error() string {
+	return fmt.Sprintf("%03d %s", e.Code, e.Msg)
+}
+
+// A ProtocolError describes a protocol violation such
+// as an invalid response or a hung-up connection.
+type ProtocolError string
+
+func (p ProtocolError) Error() string {
+	return string(p)
+}
+
+// A Conn represents a textual network protocol connection.
+// It consists of a Reader and Writer to manage I/O
+// and a Pipeline to sequence concurrent requests on the connection.
+// These embedded types carry methods with them;
+// see the documentation of those types for details.
+type Conn struct {
+	Reader
+	Writer
+	Pipeline
+	conn io.ReadWriteCloser
+}
+
+// NewConn returns a new Conn using conn for I/O.
+func NewConn(conn io.ReadWriteCloser) *Conn {
+	return &Conn{
+		Reader: Reader{R: bufio.NewReader(conn)},
+		Writer: Writer{W: bufio.NewWriter(conn)},
+		conn:   conn,
+	}
+}
+
+// Close closes the connection.
+func (c *Conn) Close() error {
+	return c.conn.Close()
+}
+
+// Dial connects to the given address on the given network using net.Dial
+// and then returns a new Conn for the connection.
+func Dial(network, addr string) (*Conn, error) {
+	c, err := net.Dial(network, addr)
+	if err != nil {
+		return nil, err
+	}
+	return NewConn(c), nil
+}
+
+// Cmd is a convenience method that sends a command after
+// waiting its turn in the pipeline.  The command text is the
+// result of formatting format with args and appending \r\n.
+// Cmd returns the id of the command, for use with StartResponse and EndResponse.
+//
+// For example, a client might run a HELP command that returns a dot-body
+// by using:
+//
+//	id, err := c.Cmd("HELP")
+//	if err != nil {
+//		return nil, err
+//	}
+//
+//	c.StartResponse(id)
+//	defer c.EndResponse(id)
+//
+//	if _, _, err = c.ReadCodeLine(110); err != nil {
+//		return nil, err
+//	}
+//	text, err := c.ReadDotBytes()
+//	if err != nil {
+//		return nil, err
+//	}
+//	return c.ReadCodeLine(250)
+//
+func (c *Conn) Cmd(format string, args ...interface{}) (id uint, err error) {
+	id = c.Next()
+	c.StartRequest(id)
+	err = c.PrintfLine(format, args...)
+	c.EndRequest(id)
+	if err != nil {
+		return 0, err
+	}
+	return id, nil
+}
+
+// TrimString returns s without leading and trailing ASCII space.
+func TrimString(s string) string {
+	for len(s) > 0 && isASCIISpace(s[0]) {
+		s = s[1:]
+	}
+	for len(s) > 0 && isASCIISpace(s[len(s)-1]) {
+		s = s[:len(s)-1]
+	}
+	return s
+}
+
+// TrimBytes returns b without leading and trailing ASCII space.
+func TrimBytes(b []byte) []byte {
+	for len(b) > 0 && isASCIISpace(b[0]) {
+		b = b[1:]
+	}
+	for len(b) > 0 && isASCIISpace(b[len(b)-1]) {
+		b = b[:len(b)-1]
+	}
+	return b
+}
+
+func isASCIISpace(b byte) bool {
+	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
+}
+
+func isASCIILetter(b byte) bool {
+	b |= 0x20 // make lower case
+	return 'a' <= b && b <= 'z'
+}
diff --git a/third_party/gofrontend/libgo/go/net/textproto/writer.go b/third_party/gofrontend/libgo/go/net/textproto/writer.go
new file mode 100644
index 0000000..03e2fd6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/textproto/writer.go
@@ -0,0 +1,118 @@
+// Copyright 2010 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 textproto
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+)
+
+// A Writer implements convenience methods for writing
+// requests or responses to a text protocol network connection.
+type Writer struct {
+	W   *bufio.Writer
+	dot *dotWriter
+}
+
+// NewWriter returns a new Writer writing to w.
+func NewWriter(w *bufio.Writer) *Writer {
+	return &Writer{W: w}
+}
+
+var crnl = []byte{'\r', '\n'}
+var dotcrnl = []byte{'.', '\r', '\n'}
+
+// PrintfLine writes the formatted output followed by \r\n.
+func (w *Writer) PrintfLine(format string, args ...interface{}) error {
+	w.closeDot()
+	fmt.Fprintf(w.W, format, args...)
+	w.W.Write(crnl)
+	return w.W.Flush()
+}
+
+// DotWriter returns a writer that can be used to write a dot-encoding to w.
+// It takes care of inserting leading dots when necessary,
+// translating line-ending \n into \r\n, and adding the final .\r\n line
+// when the DotWriter is closed.  The caller should close the
+// DotWriter before the next call to a method on w.
+//
+// See the documentation for Reader's DotReader method for details about dot-encoding.
+func (w *Writer) DotWriter() io.WriteCloser {
+	w.closeDot()
+	w.dot = &dotWriter{w: w}
+	return w.dot
+}
+
+func (w *Writer) closeDot() {
+	if w.dot != nil {
+		w.dot.Close() // sets w.dot = nil
+	}
+}
+
+type dotWriter struct {
+	w     *Writer
+	state int
+}
+
+const (
+	wstateBeginLine = iota // beginning of line; initial state; must be zero
+	wstateCR               // wrote \r (possibly at end of line)
+	wstateData             // writing data in middle of line
+)
+
+func (d *dotWriter) Write(b []byte) (n int, err error) {
+	bw := d.w.W
+	for n < len(b) {
+		c := b[n]
+		switch d.state {
+		case wstateBeginLine:
+			d.state = wstateData
+			if c == '.' {
+				// escape leading dot
+				bw.WriteByte('.')
+			}
+			fallthrough
+
+		case wstateData:
+			if c == '\r' {
+				d.state = wstateCR
+			}
+			if c == '\n' {
+				bw.WriteByte('\r')
+				d.state = wstateBeginLine
+			}
+
+		case wstateCR:
+			d.state = wstateData
+			if c == '\n' {
+				d.state = wstateBeginLine
+			}
+		}
+		if err = bw.WriteByte(c); err != nil {
+			break
+		}
+		n++
+	}
+	return
+}
+
+func (d *dotWriter) Close() error {
+	if d.w.dot == d {
+		d.w.dot = nil
+	}
+	bw := d.w.W
+	switch d.state {
+	default:
+		bw.WriteByte('\r')
+		fallthrough
+	case wstateCR:
+		bw.WriteByte('\n')
+		fallthrough
+	case wstateBeginLine:
+		bw.Write(dotcrnl)
+	}
+	return bw.Flush()
+}
diff --git a/third_party/gofrontend/libgo/go/net/textproto/writer_test.go b/third_party/gofrontend/libgo/go/net/textproto/writer_test.go
new file mode 100644
index 0000000..e03ab5e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/textproto/writer_test.go
@@ -0,0 +1,35 @@
+// Copyright 2010 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 textproto
+
+import (
+	"bufio"
+	"bytes"
+	"testing"
+)
+
+func TestPrintfLine(t *testing.T) {
+	var buf bytes.Buffer
+	w := NewWriter(bufio.NewWriter(&buf))
+	err := w.PrintfLine("foo %d", 123)
+	if s := buf.String(); s != "foo 123\r\n" || err != nil {
+		t.Fatalf("s=%q; err=%s", s, err)
+	}
+}
+
+func TestDotWriter(t *testing.T) {
+	var buf bytes.Buffer
+	w := NewWriter(bufio.NewWriter(&buf))
+	d := w.DotWriter()
+	n, err := d.Write([]byte("abc\n.def\n..ghi\n.jkl\n."))
+	if n != 21 || err != nil {
+		t.Fatalf("Write: %d, %s", n, err)
+	}
+	d.Close()
+	want := "abc\r\n..def\r\n...ghi\r\n..jkl\r\n..\r\n.\r\n"
+	if s := buf.String(); s != want {
+		t.Fatalf("wrote %q", s)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/timeout_test.go b/third_party/gofrontend/libgo/go/net/timeout_test.go
new file mode 100644
index 0000000..9ef0c4d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/timeout_test.go
@@ -0,0 +1,747 @@
+// 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 net
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"runtime"
+	"testing"
+	"time"
+)
+
+func isTimeout(err error) bool {
+	e, ok := err.(Error)
+	return ok && e.Timeout()
+}
+
+type copyRes struct {
+	n   int64
+	err error
+	d   time.Duration
+}
+
+func TestAcceptTimeout(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t).(*TCPListener)
+	defer ln.Close()
+	ln.SetDeadline(time.Now().Add(-1 * time.Second))
+	if _, err := ln.Accept(); !isTimeout(err) {
+		t.Fatalf("Accept: expected err %v, got %v", errTimeout, err)
+	}
+	if _, err := ln.Accept(); !isTimeout(err) {
+		t.Fatalf("Accept: expected err %v, got %v", errTimeout, err)
+	}
+	ln.SetDeadline(time.Now().Add(100 * time.Millisecond))
+	if _, err := ln.Accept(); !isTimeout(err) {
+		t.Fatalf("Accept: expected err %v, got %v", errTimeout, err)
+	}
+	if _, err := ln.Accept(); !isTimeout(err) {
+		t.Fatalf("Accept: expected err %v, got %v", errTimeout, err)
+	}
+	ln.SetDeadline(noDeadline)
+	errc := make(chan error)
+	go func() {
+		_, err := ln.Accept()
+		errc <- err
+	}()
+	time.Sleep(100 * time.Millisecond)
+	select {
+	case err := <-errc:
+		t.Fatalf("Expected Accept() to not return, but it returned with %v\n", err)
+	default:
+	}
+	ln.Close()
+	switch nerr := <-errc; err := nerr.(type) {
+	case *OpError:
+		if err.Err != errClosing {
+			t.Fatalf("Accept: expected err %v, got %v", errClosing, err)
+		}
+	default:
+		if err != errClosing {
+			t.Fatalf("Accept: expected err %v, got %v", errClosing, err)
+		}
+	}
+}
+
+func TestReadTimeout(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+	c, err := DialTCP("tcp", nil, ln.Addr().(*TCPAddr))
+	if err != nil {
+		t.Fatalf("Connect: %v", err)
+	}
+	defer c.Close()
+	c.SetDeadline(time.Now().Add(time.Hour))
+	c.SetReadDeadline(time.Now().Add(-1 * time.Second))
+	buf := make([]byte, 1)
+	if _, err = c.Read(buf); !isTimeout(err) {
+		t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
+	}
+	if _, err = c.Read(buf); !isTimeout(err) {
+		t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
+	}
+	c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+	if _, err = c.Read(buf); !isTimeout(err) {
+		t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
+	}
+	if _, err = c.Read(buf); !isTimeout(err) {
+		t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
+	}
+	c.SetReadDeadline(noDeadline)
+	c.SetWriteDeadline(time.Now().Add(-1 * time.Second))
+	errc := make(chan error)
+	go func() {
+		_, err := c.Read(buf)
+		errc <- err
+	}()
+	time.Sleep(100 * time.Millisecond)
+	select {
+	case err := <-errc:
+		t.Fatalf("Expected Read() to not return, but it returned with %v\n", err)
+	default:
+	}
+	c.Close()
+	switch nerr := <-errc; err := nerr.(type) {
+	case *OpError:
+		if err.Err != errClosing {
+			t.Fatalf("Read: expected err %v, got %v", errClosing, err)
+		}
+	default:
+		if err == io.EOF && runtime.GOOS == "nacl" { // close enough; golang.org/issue/8044
+			break
+		}
+		if err != errClosing {
+			t.Fatalf("Read: expected err %v, got %v", errClosing, err)
+		}
+	}
+}
+
+func TestWriteTimeout(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+	c, err := DialTCP("tcp", nil, ln.Addr().(*TCPAddr))
+	if err != nil {
+		t.Fatalf("Connect: %v", err)
+	}
+	defer c.Close()
+	c.SetDeadline(time.Now().Add(time.Hour))
+	c.SetWriteDeadline(time.Now().Add(-1 * time.Second))
+	buf := make([]byte, 4096)
+	writeUntilTimeout := func() {
+		for {
+			_, err := c.Write(buf)
+			if err != nil {
+				if isTimeout(err) {
+					return
+				}
+				t.Fatalf("Write: expected err %v, got %v", errTimeout, err)
+			}
+		}
+	}
+	writeUntilTimeout()
+	c.SetDeadline(time.Now().Add(10 * time.Millisecond))
+	writeUntilTimeout()
+	writeUntilTimeout()
+	c.SetWriteDeadline(noDeadline)
+	c.SetReadDeadline(time.Now().Add(-1 * time.Second))
+	errc := make(chan error)
+	go func() {
+		for {
+			_, err := c.Write(buf)
+			if err != nil {
+				errc <- err
+			}
+		}
+	}()
+	time.Sleep(100 * time.Millisecond)
+	select {
+	case err := <-errc:
+		t.Fatalf("Expected Write() to not return, but it returned with %v\n", err)
+	default:
+	}
+	c.Close()
+	switch nerr := <-errc; err := nerr.(type) {
+	case *OpError:
+		if err.Err != errClosing {
+			t.Fatalf("Write: expected err %v, got %v", errClosing, err)
+		}
+	default:
+		if err != errClosing {
+			t.Fatalf("Write: expected err %v, got %v", errClosing, err)
+		}
+	}
+}
+
+func testTimeout(t *testing.T, net, addr string, readFrom bool) {
+	c, err := Dial(net, addr)
+	if err != nil {
+		t.Errorf("Dial(%q, %q) failed: %v", net, addr, err)
+		return
+	}
+	defer c.Close()
+	what := "Read"
+	if readFrom {
+		what = "ReadFrom"
+	}
+
+	errc := make(chan error, 1)
+	go func() {
+		t0 := time.Now()
+		c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		var b [100]byte
+		var n int
+		var err error
+		if readFrom {
+			n, _, err = c.(PacketConn).ReadFrom(b[0:])
+		} else {
+			n, err = c.Read(b[0:])
+		}
+		t1 := time.Now()
+		if n != 0 || err == nil || !err.(Error).Timeout() {
+			errc <- fmt.Errorf("%s(%q, %q) did not return 0, timeout: %v, %v", what, net, addr, n, err)
+			return
+		}
+		if dt := t1.Sub(t0); dt < 50*time.Millisecond || !testing.Short() && dt > 250*time.Millisecond {
+			errc <- fmt.Errorf("%s(%q, %q) took %s, expected 0.1s", what, net, addr, dt)
+			return
+		}
+		errc <- nil
+	}()
+	select {
+	case err := <-errc:
+		if err != nil {
+			t.Error(err)
+		}
+	case <-time.After(1 * time.Second):
+		t.Errorf("%s(%q, %q) took over 1 second, expected 0.1s", what, net, addr)
+	}
+}
+
+func TestTimeoutUDP(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	// set up a listener that won't talk back
+	listening := make(chan string)
+	done := make(chan int)
+	go runDatagramPacketConnServer(t, "udp", "127.0.0.1:0", listening, done)
+	addr := <-listening
+
+	testTimeout(t, "udp", addr, false)
+	testTimeout(t, "udp", addr, true)
+	<-done
+}
+
+func TestTimeoutTCP(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	// set up a listener that won't talk back
+	listening := make(chan string)
+	done := make(chan int)
+	go runStreamConnServer(t, "tcp", "127.0.0.1:0", listening, done)
+	addr := <-listening
+
+	testTimeout(t, "tcp", addr, false)
+	<-done
+}
+
+func TestDeadlineReset(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln.Close()
+	tl := ln.(*TCPListener)
+	tl.SetDeadline(time.Now().Add(1 * time.Minute))
+	tl.SetDeadline(noDeadline) // reset it
+	errc := make(chan error, 1)
+	go func() {
+		_, err := ln.Accept()
+		errc <- err
+	}()
+	select {
+	case <-time.After(50 * time.Millisecond):
+		// Pass.
+	case err := <-errc:
+		// Accept should never return; we never
+		// connected to it.
+		t.Errorf("unexpected return from Accept; err=%v", err)
+	}
+}
+
+func TestTimeoutAccept(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln.Close()
+	tl := ln.(*TCPListener)
+	tl.SetDeadline(time.Now().Add(100 * time.Millisecond))
+	errc := make(chan error, 1)
+	go func() {
+		_, err := ln.Accept()
+		errc <- err
+	}()
+	select {
+	case <-time.After(1 * time.Second):
+		// Accept shouldn't block indefinitely
+		t.Errorf("Accept didn't return in an expected time")
+	case <-errc:
+		// Pass.
+	}
+}
+
+func TestReadWriteDeadline(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	const (
+		readTimeout  = 50 * time.Millisecond
+		writeTimeout = 250 * time.Millisecond
+	)
+	checkTimeout := func(command string, start time.Time, should time.Duration) {
+		is := time.Now().Sub(start)
+		d := is - should
+		if d < -30*time.Millisecond || !testing.Short() && 150*time.Millisecond < d {
+			t.Errorf("%s timeout test failed: is=%v should=%v\n", command, is, should)
+		}
+	}
+
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ListenTCP on :0: %v", err)
+	}
+	defer ln.Close()
+
+	lnquit := make(chan bool)
+
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Errorf("Accept: %v", err)
+			return
+		}
+		defer c.Close()
+		lnquit <- true
+	}()
+
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+
+	start := time.Now()
+	err = c.SetReadDeadline(start.Add(readTimeout))
+	if err != nil {
+		t.Fatalf("SetReadDeadline: %v", err)
+	}
+	err = c.SetWriteDeadline(start.Add(writeTimeout))
+	if err != nil {
+		t.Fatalf("SetWriteDeadline: %v", err)
+	}
+
+	quit := make(chan bool)
+
+	go func() {
+		var buf [10]byte
+		_, err := c.Read(buf[:])
+		if err == nil {
+			t.Errorf("Read should not succeed")
+		}
+		checkTimeout("Read", start, readTimeout)
+		quit <- true
+	}()
+
+	go func() {
+		var buf [10000]byte
+		for {
+			_, err := c.Write(buf[:])
+			if err != nil {
+				break
+			}
+		}
+		checkTimeout("Write", start, writeTimeout)
+		quit <- true
+	}()
+
+	<-quit
+	<-quit
+	<-lnquit
+}
+
+type neverEnding byte
+
+func (b neverEnding) Read(p []byte) (n int, err error) {
+	for i := range p {
+		p[i] = byte(b)
+	}
+	return len(p), nil
+}
+
+func TestVariousDeadlines1Proc(t *testing.T) {
+	testVariousDeadlines(t, 1)
+}
+
+func TestVariousDeadlines4Proc(t *testing.T) {
+	testVariousDeadlines(t, 4)
+}
+
+func testVariousDeadlines(t *testing.T, maxProcs int) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
+	ln := newLocalListener(t)
+	defer ln.Close()
+	acceptc := make(chan error, 1)
+
+	// The server, with no timeouts of its own, sending bytes to clients
+	// as fast as it can.
+	servec := make(chan copyRes)
+	go func() {
+		for {
+			c, err := ln.Accept()
+			if err != nil {
+				acceptc <- err
+				return
+			}
+			go func() {
+				t0 := time.Now()
+				n, err := io.Copy(c, neverEnding('a'))
+				d := time.Since(t0)
+				c.Close()
+				servec <- copyRes{n, err, d}
+			}()
+		}
+	}()
+
+	for _, timeout := range []time.Duration{
+		1 * time.Nanosecond,
+		2 * time.Nanosecond,
+		5 * time.Nanosecond,
+		50 * time.Nanosecond,
+		100 * time.Nanosecond,
+		200 * time.Nanosecond,
+		500 * time.Nanosecond,
+		750 * time.Nanosecond,
+		1 * time.Microsecond,
+		5 * time.Microsecond,
+		25 * time.Microsecond,
+		250 * time.Microsecond,
+		500 * time.Microsecond,
+		1 * time.Millisecond,
+		5 * time.Millisecond,
+		100 * time.Millisecond,
+		250 * time.Millisecond,
+		500 * time.Millisecond,
+		1 * time.Second,
+	} {
+		numRuns := 3
+		if testing.Short() {
+			numRuns = 1
+			if timeout > 500*time.Microsecond {
+				continue
+			}
+		}
+		for run := 0; run < numRuns; run++ {
+			name := fmt.Sprintf("%v run %d/%d", timeout, run+1, numRuns)
+			t.Log(name)
+
+			c, err := Dial("tcp", ln.Addr().String())
+			if err != nil {
+				t.Fatalf("Dial: %v", err)
+			}
+			clientc := make(chan copyRes)
+			go func() {
+				t0 := time.Now()
+				c.SetDeadline(t0.Add(timeout))
+				n, err := io.Copy(ioutil.Discard, c)
+				d := time.Since(t0)
+				c.Close()
+				clientc <- copyRes{n, err, d}
+			}()
+
+			tooLong := 5 * time.Second
+			select {
+			case res := <-clientc:
+				if isTimeout(res.err) {
+					t.Logf("for %v, good client timeout after %v, reading %d bytes", name, res.d, res.n)
+				} else {
+					t.Fatalf("for %v: client Copy = %d, %v (want timeout)", name, res.n, res.err)
+				}
+			case <-time.After(tooLong):
+				t.Fatalf("for %v: timeout (%v) waiting for client to timeout (%v) reading", name, tooLong, timeout)
+			}
+
+			select {
+			case res := <-servec:
+				t.Logf("for %v: server in %v wrote %d, %v", name, res.d, res.n, res.err)
+			case err := <-acceptc:
+				t.Fatalf("for %v: server Accept = %v", name, err)
+			case <-time.After(tooLong):
+				t.Fatalf("for %v, timeout waiting for server to finish writing", name)
+			}
+		}
+	}
+}
+
+// TestReadDeadlineDataAvailable tests that read deadlines work, even
+// if there's data ready to be read.
+func TestReadDeadlineDataAvailable(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	servec := make(chan copyRes)
+	const msg = "data client shouldn't read, even though it'll be waiting"
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Errorf("Accept: %v", err)
+			return
+		}
+		defer c.Close()
+		n, err := c.Write([]byte(msg))
+		servec <- copyRes{n: int64(n), err: err}
+	}()
+
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+	if res := <-servec; res.err != nil || res.n != int64(len(msg)) {
+		t.Fatalf("unexpected server Write: n=%d, err=%v; want n=%d, err=nil", res.n, res.err, len(msg))
+	}
+	c.SetReadDeadline(time.Now().Add(-5 * time.Second)) // in the psat.
+	buf := make([]byte, len(msg)/2)
+	n, err := c.Read(buf)
+	if n > 0 || !isTimeout(err) {
+		t.Fatalf("client read = %d (%q) err=%v; want 0, timeout", n, buf[:n], err)
+	}
+}
+
+// TestWriteDeadlineBufferAvailable tests that write deadlines work, even
+// if there's buffer space available to write.
+func TestWriteDeadlineBufferAvailable(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	servec := make(chan copyRes)
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Errorf("Accept: %v", err)
+			return
+		}
+		defer c.Close()
+		c.SetWriteDeadline(time.Now().Add(-5 * time.Second)) // in the past
+		n, err := c.Write([]byte{'x'})
+		servec <- copyRes{n: int64(n), err: err}
+	}()
+
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+	res := <-servec
+	if res.n != 0 {
+		t.Errorf("Write = %d; want 0", res.n)
+	}
+	if !isTimeout(res.err) {
+		t.Errorf("Write error = %v; want timeout", res.err)
+	}
+}
+
+// TestAcceptDeadlineConnectionAvailable tests that accept deadlines work, even
+// if there's incoming connections available.
+func TestAcceptDeadlineConnectionAvailable(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t).(*TCPListener)
+	defer ln.Close()
+
+	go func() {
+		c, err := Dial("tcp", ln.Addr().String())
+		if err != nil {
+			t.Errorf("Dial: %v", err)
+			return
+		}
+		defer c.Close()
+		var buf [1]byte
+		c.Read(buf[:]) // block until the connection or listener is closed
+	}()
+	time.Sleep(10 * time.Millisecond)
+	ln.SetDeadline(time.Now().Add(-5 * time.Second)) // in the past
+	c, err := ln.Accept()
+	if err == nil {
+		defer c.Close()
+	}
+	if !isTimeout(err) {
+		t.Fatalf("Accept: got %v; want timeout", err)
+	}
+}
+
+// TestConnectDeadlineInThePast tests that connect deadlines work, even
+// if the connection can be established w/o blocking.
+func TestConnectDeadlineInThePast(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t).(*TCPListener)
+	defer ln.Close()
+
+	go func() {
+		c, err := ln.Accept()
+		if err == nil {
+			defer c.Close()
+		}
+	}()
+	time.Sleep(10 * time.Millisecond)
+	c, err := DialTimeout("tcp", ln.Addr().String(), -5*time.Second) // in the past
+	if err == nil {
+		defer c.Close()
+	}
+	if !isTimeout(err) {
+		t.Fatalf("DialTimeout: got %v; want timeout", err)
+	}
+}
+
+// TestProlongTimeout tests concurrent deadline modification.
+// Known to cause data races in the past.
+func TestProlongTimeout(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+	connected := make(chan bool)
+	go func() {
+		s, err := ln.Accept()
+		connected <- true
+		if err != nil {
+			t.Errorf("ln.Accept: %v", err)
+			return
+		}
+		defer s.Close()
+		s.SetDeadline(time.Now().Add(time.Hour))
+		go func() {
+			var buf [4096]byte
+			for {
+				_, err := s.Write(buf[:])
+				if err != nil {
+					break
+				}
+				s.SetDeadline(time.Now().Add(time.Hour))
+			}
+		}()
+		buf := make([]byte, 1)
+		for {
+			_, err := s.Read(buf)
+			if err != nil {
+				break
+			}
+			s.SetDeadline(time.Now().Add(time.Hour))
+		}
+	}()
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("DialTCP: %v", err)
+	}
+	defer c.Close()
+	<-connected
+	for i := 0; i < 1024; i++ {
+		var buf [1]byte
+		c.Write(buf[:])
+	}
+}
+
+func TestDeadlineRace(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	N := 1000
+	if testing.Short() {
+		N = 50
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	ln := newLocalListener(t)
+	defer ln.Close()
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+	done := make(chan bool)
+	go func() {
+		t := time.NewTicker(2 * time.Microsecond).C
+		for i := 0; i < N; i++ {
+			if err := c.SetDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
+				break
+			}
+			<-t
+		}
+		done <- true
+	}()
+	var buf [1]byte
+	for i := 0; i < N; i++ {
+		c.Read(buf[:]) // ignore possible timeout errors
+	}
+	c.Close()
+	<-done
+}
diff --git a/third_party/gofrontend/libgo/go/net/udp_test.go b/third_party/gofrontend/libgo/go/net/udp_test.go
new file mode 100644
index 0000000..e177877
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/udp_test.go
@@ -0,0 +1,257 @@
+// 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 net
+
+import (
+	"reflect"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+func TestResolveUDPAddr(t *testing.T) {
+	for _, tt := range resolveTCPAddrTests {
+		net := strings.Replace(tt.net, "tcp", "udp", -1)
+		addr, err := ResolveUDPAddr(net, tt.litAddrOrName)
+		if err != tt.err {
+			t.Fatalf("ResolveUDPAddr(%q, %q) failed: %v", net, tt.litAddrOrName, err)
+		}
+		if !reflect.DeepEqual(addr, (*UDPAddr)(tt.addr)) {
+			t.Fatalf("ResolveUDPAddr(%q, %q) = %#v, want %#v", net, tt.litAddrOrName, addr, tt.addr)
+		}
+		if err == nil {
+			str := addr.String()
+			addr1, err := ResolveUDPAddr(net, str)
+			if err != nil {
+				t.Fatalf("ResolveUDPAddr(%q, %q) [from %q]: %v", net, str, tt.litAddrOrName, err)
+			}
+			if !reflect.DeepEqual(addr1, addr) {
+				t.Fatalf("ResolveUDPAddr(%q, %q) [from %q] = %#v, want %#v", net, str, tt.litAddrOrName, addr1, addr)
+			}
+		}
+	}
+}
+
+func TestWriteToUDP(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	l, err := ListenPacket("udp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+	}
+	defer l.Close()
+
+	testWriteToConn(t, l.LocalAddr().String())
+	testWriteToPacketConn(t, l.LocalAddr().String())
+}
+
+func testWriteToConn(t *testing.T, raddr string) {
+	c, err := Dial("udp", raddr)
+	if err != nil {
+		t.Fatalf("Dial failed: %v", err)
+	}
+	defer c.Close()
+
+	ra, err := ResolveUDPAddr("udp", raddr)
+	if err != nil {
+		t.Fatalf("ResolveUDPAddr failed: %v", err)
+	}
+
+	_, err = c.(*UDPConn).WriteToUDP([]byte("Connection-oriented mode socket"), ra)
+	if err == nil {
+		t.Fatal("WriteToUDP should fail")
+	}
+	if err != nil && err.(*OpError).Err != ErrWriteToConnected {
+		t.Fatalf("WriteToUDP should fail as ErrWriteToConnected: %v", err)
+	}
+
+	_, err = c.(*UDPConn).WriteTo([]byte("Connection-oriented mode socket"), ra)
+	if err == nil {
+		t.Fatal("WriteTo should fail")
+	}
+	if err != nil && err.(*OpError).Err != ErrWriteToConnected {
+		t.Fatalf("WriteTo should fail as ErrWriteToConnected: %v", err)
+	}
+
+	_, err = c.Write([]byte("Connection-oriented mode socket"))
+	if err != nil {
+		t.Fatalf("Write failed: %v", err)
+	}
+}
+
+func testWriteToPacketConn(t *testing.T, raddr string) {
+	c, err := ListenPacket("udp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ListenPacket failed: %v", err)
+	}
+	defer c.Close()
+
+	ra, err := ResolveUDPAddr("udp", raddr)
+	if err != nil {
+		t.Fatalf("ResolveUDPAddr failed: %v", err)
+	}
+
+	_, err = c.(*UDPConn).WriteToUDP([]byte("Connection-less mode socket"), ra)
+	if err != nil {
+		t.Fatalf("WriteToUDP failed: %v", err)
+	}
+
+	_, err = c.WriteTo([]byte("Connection-less mode socket"), ra)
+	if err != nil {
+		t.Fatalf("WriteTo failed: %v", err)
+	}
+
+	_, err = c.(*UDPConn).Write([]byte("Connection-less mode socket"))
+	if err == nil {
+		t.Fatal("Write should fail")
+	}
+}
+
+var udpConnLocalNameTests = []struct {
+	net   string
+	laddr *UDPAddr
+}{
+	{"udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}},
+	{"udp4", &UDPAddr{}},
+	{"udp4", nil},
+}
+
+func TestUDPConnLocalName(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	for _, tt := range udpConnLocalNameTests {
+		c, err := ListenUDP(tt.net, tt.laddr)
+		if err != nil {
+			t.Fatalf("ListenUDP failed: %v", err)
+		}
+		defer c.Close()
+		la := c.LocalAddr()
+		if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
+			t.Fatalf("got %v; expected a proper address with non-zero port number", la)
+		}
+	}
+}
+
+func TestUDPConnLocalAndRemoteNames(t *testing.T) {
+	for _, laddr := range []string{"", "127.0.0.1:0"} {
+		c1, err := ListenPacket("udp", "127.0.0.1:0")
+		if err != nil {
+			t.Fatalf("ListenUDP failed: %v", err)
+		}
+		defer c1.Close()
+
+		var la *UDPAddr
+		if laddr != "" {
+			var err error
+			if la, err = ResolveUDPAddr("udp", laddr); err != nil {
+				t.Fatalf("ResolveUDPAddr failed: %v", err)
+			}
+		}
+		c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr))
+		if err != nil {
+			t.Fatalf("DialUDP failed: %v", err)
+		}
+		defer c2.Close()
+
+		var connAddrs = [4]struct {
+			got Addr
+			ok  bool
+		}{
+			{c1.LocalAddr(), true},
+			{c1.(*UDPConn).RemoteAddr(), false},
+			{c2.LocalAddr(), true},
+			{c2.RemoteAddr(), true},
+		}
+		for _, ca := range connAddrs {
+			if a, ok := ca.got.(*UDPAddr); ok != ca.ok || ok && a.Port == 0 {
+				t.Fatalf("got %v; expected a proper address with non-zero port number", ca.got)
+			}
+		}
+	}
+}
+
+func TestIPv6LinkLocalUnicastUDP(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+	if !supportsIPv6 {
+		t.Skip("ipv6 is not supported")
+	}
+	ifi := loopbackInterface()
+	if ifi == nil {
+		t.Skip("loopback interface not found")
+	}
+	laddr := ipv6LinkLocalUnicastAddr(ifi)
+	if laddr == "" {
+		t.Skip("ipv6 unicast address on loopback not found")
+	}
+
+	type test struct {
+		net, addr  string
+		nameLookup bool
+	}
+	var tests = []test{
+		{"udp", "[" + laddr + "%" + ifi.Name + "]:0", false},
+		{"udp6", "[" + laddr + "%" + ifi.Name + "]:0", false},
+	}
+	// The first udp test fails on DragonFly - see issue 7473.
+	if runtime.GOOS == "dragonfly" {
+		tests = tests[1:]
+	}
+	switch runtime.GOOS {
+	case "darwin", "dragonfly", "freebsd", "openbsd", "netbsd":
+		tests = append(tests, []test{
+			{"udp", "[localhost%" + ifi.Name + "]:0", true},
+			{"udp6", "[localhost%" + ifi.Name + "]:0", true},
+		}...)
+	case "linux":
+		tests = append(tests, []test{
+			{"udp", "[ip6-localhost%" + ifi.Name + "]:0", true},
+			{"udp6", "[ip6-localhost%" + ifi.Name + "]:0", true},
+		}...)
+	}
+	for _, tt := range tests {
+		c1, err := ListenPacket(tt.net, tt.addr)
+		if err != nil {
+			// It might return "LookupHost returned no
+			// suitable address" error on some platforms.
+			t.Logf("ListenPacket failed: %v", err)
+			continue
+		}
+		defer c1.Close()
+		if la, ok := c1.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" {
+			t.Fatalf("got %v; expected a proper address with zone identifier", la)
+		}
+
+		c2, err := Dial(tt.net, c1.LocalAddr().String())
+		if err != nil {
+			t.Fatalf("Dial failed: %v", err)
+		}
+		defer c2.Close()
+		if la, ok := c2.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" {
+			t.Fatalf("got %v; expected a proper address with zone identifier", la)
+		}
+		if ra, ok := c2.RemoteAddr().(*UDPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
+			t.Fatalf("got %v; expected a proper address with zone identifier", ra)
+		}
+
+		if _, err := c2.Write([]byte("UDP OVER IPV6 LINKLOCAL TEST")); err != nil {
+			t.Fatalf("Conn.Write failed: %v", err)
+		}
+		b := make([]byte, 32)
+		if _, from, err := c1.ReadFrom(b); err != nil {
+			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
+		} else {
+			if ra, ok := from.(*UDPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
+				t.Fatalf("got %v; expected a proper address with zone identifier", ra)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/udpsock.go b/third_party/gofrontend/libgo/go/net/udpsock.go
new file mode 100644
index 0000000..4c99ae4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/udpsock.go
@@ -0,0 +1,54 @@
+// 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 net
+
+// UDPAddr represents the address of a UDP end point.
+type UDPAddr struct {
+	IP   IP
+	Port int
+	Zone string // IPv6 scoped addressing zone
+}
+
+// Network returns the address's network name, "udp".
+func (a *UDPAddr) Network() string { return "udp" }
+
+func (a *UDPAddr) String() string {
+	if a == nil {
+		return "<nil>"
+	}
+	ip := ipEmptyString(a.IP)
+	if a.Zone != "" {
+		return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port))
+	}
+	return JoinHostPort(ip, itoa(a.Port))
+}
+
+func (a *UDPAddr) toAddr() Addr {
+	if a == nil {
+		return nil
+	}
+	return a
+}
+
+// ResolveUDPAddr parses addr as a UDP address of the form "host:port"
+// or "[ipv6-host%zone]:port" and resolves a pair of domain name and
+// port name on the network net, which must be "udp", "udp4" or
+// "udp6".  A literal address or host name for IPv6 must be enclosed
+// in square brackets, as in "[::1]:80", "[ipv6-host]:http" or
+// "[ipv6-host%zone]:80".
+func ResolveUDPAddr(net, addr string) (*UDPAddr, error) {
+	switch net {
+	case "udp", "udp4", "udp6":
+	case "": // a hint wildcard for Go 1.0 undocumented behavior
+		net = "udp"
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	a, err := resolveInternetAddr(net, addr, noDeadline)
+	if err != nil {
+		return nil, err
+	}
+	return a.toAddr().(*UDPAddr), nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/udpsock_plan9.go b/third_party/gofrontend/libgo/go/net/udpsock_plan9.go
new file mode 100644
index 0000000..510ac5e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/udpsock_plan9.go
@@ -0,0 +1,203 @@
+// 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 net
+
+import (
+	"errors"
+	"os"
+	"syscall"
+	"time"
+)
+
+// UDPConn is the implementation of the Conn and PacketConn interfaces
+// for UDP network connections.
+type UDPConn struct {
+	conn
+}
+
+func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
+
+// ReadFromUDP reads a UDP packet from c, copying the payload into b.
+// It returns the number of bytes copied into b and the return address
+// that was on the packet.
+//
+// ReadFromUDP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
+	if !c.ok() || c.fd.data == nil {
+		return 0, nil, syscall.EINVAL
+	}
+	buf := make([]byte, udpHeaderSize+len(b))
+	m, err := c.fd.data.Read(buf)
+	if err != nil {
+		return
+	}
+	if m < udpHeaderSize {
+		return 0, nil, errors.New("short read reading UDP header")
+	}
+	buf = buf[:m]
+
+	h, buf := unmarshalUDPHeader(buf)
+	n = copy(b, buf)
+	return n, &UDPAddr{IP: h.raddr, Port: int(h.rport)}, nil
+}
+
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
+	if !c.ok() {
+		return 0, nil, syscall.EINVAL
+	}
+	return c.ReadFromUDP(b)
+}
+
+// ReadMsgUDP reads a packet from c, copying the payload into b and
+// the associated out-of-band data into oob.  It returns the number
+// of bytes copied into b, the number of bytes copied into oob, the
+// flags that were set on the packet and the source address of the
+// packet.
+func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
+	return 0, 0, 0, nil, syscall.EPLAN9
+}
+
+// WriteToUDP writes a UDP packet to addr via c, copying the payload
+// from b.
+//
+// WriteToUDP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
+func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
+	if !c.ok() || c.fd.data == nil {
+		return 0, syscall.EINVAL
+	}
+	if addr == nil {
+		return 0, &OpError{Op: "write", Net: c.fd.dir, Addr: nil, Err: errMissingAddress}
+	}
+	h := new(udpHeader)
+	h.raddr = addr.IP.To16()
+	h.laddr = c.fd.laddr.(*UDPAddr).IP.To16()
+	h.ifcaddr = IPv6zero // ignored (receive only)
+	h.rport = uint16(addr.Port)
+	h.lport = uint16(c.fd.laddr.(*UDPAddr).Port)
+
+	buf := make([]byte, udpHeaderSize+len(b))
+	i := copy(buf, h.Bytes())
+	copy(buf[i:], b)
+	return c.fd.data.Write(buf)
+}
+
+// WriteTo implements the PacketConn WriteTo method.
+func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	a, ok := addr.(*UDPAddr)
+	if !ok {
+		return 0, &OpError{"write", c.fd.dir, addr, syscall.EINVAL}
+	}
+	return c.WriteToUDP(b, a)
+}
+
+// WriteMsgUDP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob.  It returns the
+// number of payload and out-of-band bytes written.
+func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
+	return 0, 0, syscall.EPLAN9
+}
+
+// DialUDP connects to the remote address raddr on the network net,
+// which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is
+// used as the local address for the connection.
+func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
+	return dialUDP(net, laddr, raddr, noDeadline)
+}
+
+func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
+	if !deadline.IsZero() {
+		panic("net.dialUDP: deadline not implemented on Plan 9")
+	}
+	switch net {
+	case "udp", "udp4", "udp6":
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	if raddr == nil {
+		return nil, &OpError{"dial", net, nil, errMissingAddress}
+	}
+	fd, err := dialPlan9(net, laddr, raddr)
+	if err != nil {
+		return nil, err
+	}
+	return newUDPConn(fd), nil
+}
+
+const udpHeaderSize = 16*3 + 2*2
+
+type udpHeader struct {
+	raddr, laddr, ifcaddr IP
+	rport, lport          uint16
+}
+
+func (h *udpHeader) Bytes() []byte {
+	b := make([]byte, udpHeaderSize)
+	i := 0
+	i += copy(b[i:i+16], h.raddr)
+	i += copy(b[i:i+16], h.laddr)
+	i += copy(b[i:i+16], h.ifcaddr)
+	b[i], b[i+1], i = byte(h.rport>>8), byte(h.rport), i+2
+	b[i], b[i+1], i = byte(h.lport>>8), byte(h.lport), i+2
+	return b
+}
+
+func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {
+	h := new(udpHeader)
+	h.raddr, b = IP(b[:16]), b[16:]
+	h.laddr, b = IP(b[:16]), b[16:]
+	h.ifcaddr, b = IP(b[:16]), b[16:]
+	h.rport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
+	h.lport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
+	return h, b
+}
+
+// ListenUDP listens for incoming UDP packets addressed to the local
+// address laddr.  Net must be "udp", "udp4", or "udp6".  If laddr has
+// a port of 0, ListenUDP will choose an available port.
+// The LocalAddr method of the returned UDPConn can be used to
+// discover the port.  The returned connection's ReadFrom and WriteTo
+// methods can be used to receive and send UDP packets with per-packet
+// addressing.
+func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
+	switch net {
+	case "udp", "udp4", "udp6":
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	if laddr == nil {
+		laddr = &UDPAddr{}
+	}
+	l, err := listenPlan9(net, laddr)
+	if err != nil {
+		return nil, err
+	}
+	_, err = l.ctl.WriteString("headers")
+	if err != nil {
+		return nil, err
+	}
+	l.data, err = os.OpenFile(l.dir+"/data", os.O_RDWR, 0)
+	if err != nil {
+		return nil, err
+	}
+	fd, err := l.netFD()
+	return newUDPConn(fd), err
+}
+
+// ListenMulticastUDP listens for incoming multicast UDP packets
+// addressed to the group address gaddr on ifi, which specifies the
+// interface to join.  ListenMulticastUDP uses default multicast
+// interface if ifi is nil.
+func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
+	return nil, syscall.EPLAN9
+}
diff --git a/third_party/gofrontend/libgo/go/net/udpsock_posix.go b/third_party/gofrontend/libgo/go/net/udpsock_posix.go
new file mode 100644
index 0000000..5dfba94
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/udpsock_posix.go
@@ -0,0 +1,268 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package net
+
+import (
+	"syscall"
+	"time"
+)
+
+func sockaddrToUDP(sa syscall.Sockaddr) Addr {
+	switch sa := sa.(type) {
+	case *syscall.SockaddrInet4:
+		return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
+	case *syscall.SockaddrInet6:
+		return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
+	}
+	return nil
+}
+
+func (a *UDPAddr) family() int {
+	if a == nil || len(a.IP) <= IPv4len {
+		return syscall.AF_INET
+	}
+	if a.IP.To4() != nil {
+		return syscall.AF_INET
+	}
+	return syscall.AF_INET6
+}
+
+func (a *UDPAddr) isWildcard() bool {
+	if a == nil || a.IP == nil {
+		return true
+	}
+	return a.IP.IsUnspecified()
+}
+
+func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
+	if a == nil {
+		return nil, nil
+	}
+	return ipToSockaddr(family, a.IP, a.Port, a.Zone)
+}
+
+// UDPConn is the implementation of the Conn and PacketConn interfaces
+// for UDP network connections.
+type UDPConn struct {
+	conn
+}
+
+func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
+
+// ReadFromUDP reads a UDP packet from c, copying the payload into b.
+// It returns the number of bytes copied into b and the return address
+// that was on the packet.
+//
+// ReadFromUDP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
+	if !c.ok() {
+		return 0, nil, syscall.EINVAL
+	}
+	n, sa, err := c.fd.readFrom(b)
+	switch sa := sa.(type) {
+	case *syscall.SockaddrInet4:
+		addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
+	case *syscall.SockaddrInet6:
+		addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
+	}
+	return
+}
+
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
+	if !c.ok() {
+		return 0, nil, syscall.EINVAL
+	}
+	n, addr, err := c.ReadFromUDP(b)
+	return n, addr.toAddr(), err
+}
+
+// ReadMsgUDP reads a packet from c, copying the payload into b and
+// the associated out-of-band data into oob.  It returns the number
+// of bytes copied into b, the number of bytes copied into oob, the
+// flags that were set on the packet and the source address of the
+// packet.
+func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
+	if !c.ok() {
+		return 0, 0, 0, nil, syscall.EINVAL
+	}
+	var sa syscall.Sockaddr
+	n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
+	switch sa := sa.(type) {
+	case *syscall.SockaddrInet4:
+		addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
+	case *syscall.SockaddrInet6:
+		addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
+	}
+	return
+}
+
+// WriteToUDP writes a UDP packet to addr via c, copying the payload
+// from b.
+//
+// WriteToUDP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
+func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	if c.fd.isConnected {
+		return 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
+	}
+	if addr == nil {
+		return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+	}
+	sa, err := addr.sockaddr(c.fd.family)
+	if err != nil {
+		return 0, &OpError{"write", c.fd.net, addr, err}
+	}
+	return c.fd.writeTo(b, sa)
+}
+
+// WriteTo implements the PacketConn WriteTo method.
+func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	a, ok := addr.(*UDPAddr)
+	if !ok {
+		return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL}
+	}
+	return c.WriteToUDP(b, a)
+}
+
+// WriteMsgUDP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob.  It returns the
+// number of payload and out-of-band bytes written.
+func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
+	if !c.ok() {
+		return 0, 0, syscall.EINVAL
+	}
+	if c.fd.isConnected {
+		return 0, 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
+	}
+	if addr == nil {
+		return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+	}
+	sa, err := addr.sockaddr(c.fd.family)
+	if err != nil {
+		return 0, 0, &OpError{"write", c.fd.net, addr, err}
+	}
+	return c.fd.writeMsg(b, oob, sa)
+}
+
+// DialUDP connects to the remote address raddr on the network net,
+// which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is
+// used as the local address for the connection.
+func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
+	switch net {
+	case "udp", "udp4", "udp6":
+	default:
+		return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
+	}
+	if raddr == nil {
+		return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: errMissingAddress}
+	}
+	return dialUDP(net, laddr, raddr, noDeadline)
+}
+
+func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
+	fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
+	if err != nil {
+		return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
+	}
+	return newUDPConn(fd), nil
+}
+
+// ListenUDP listens for incoming UDP packets addressed to the local
+// address laddr.  Net must be "udp", "udp4", or "udp6".  If laddr has
+// a port of 0, ListenUDP will choose an available port.
+// The LocalAddr method of the returned UDPConn can be used to
+// discover the port.  The returned connection's ReadFrom and WriteTo
+// methods can be used to receive and send UDP packets with per-packet
+// addressing.
+func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
+	switch net {
+	case "udp", "udp4", "udp6":
+	default:
+		return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
+	}
+	if laddr == nil {
+		laddr = &UDPAddr{}
+	}
+	fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
+	if err != nil {
+		return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
+	}
+	return newUDPConn(fd), nil
+}
+
+// ListenMulticastUDP listens for incoming multicast UDP packets
+// addressed to the group address gaddr on ifi, which specifies the
+// interface to join.  ListenMulticastUDP uses default multicast
+// interface if ifi is nil.
+func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
+	switch net {
+	case "udp", "udp4", "udp6":
+	default:
+		return nil, &OpError{Op: "listen", Net: net, Addr: gaddr, Err: UnknownNetworkError(net)}
+	}
+	if gaddr == nil || gaddr.IP == nil {
+		return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
+	}
+	fd, err := internetSocket(net, gaddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
+	if err != nil {
+		return nil, &OpError{Op: "listen", Net: net, Addr: gaddr, Err: err}
+	}
+	c := newUDPConn(fd)
+	if ip4 := gaddr.IP.To4(); ip4 != nil {
+		if err := listenIPv4MulticastUDP(c, ifi, ip4); err != nil {
+			c.Close()
+			return nil, &OpError{Op: "listen", Net: net, Addr: &IPAddr{IP: ip4}, Err: err}
+		}
+	} else {
+		if err := listenIPv6MulticastUDP(c, ifi, gaddr.IP); err != nil {
+			c.Close()
+			return nil, &OpError{Op: "listen", Net: net, Addr: &IPAddr{IP: gaddr.IP}, Err: err}
+		}
+	}
+	return c, nil
+}
+
+func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
+	if ifi != nil {
+		if err := setIPv4MulticastInterface(c.fd, ifi); err != nil {
+			return err
+		}
+	}
+	if err := setIPv4MulticastLoopback(c.fd, false); err != nil {
+		return err
+	}
+	if err := joinIPv4Group(c.fd, ifi, ip); err != nil {
+		return err
+	}
+	return nil
+}
+
+func listenIPv6MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
+	if ifi != nil {
+		if err := setIPv6MulticastInterface(c.fd, ifi); err != nil {
+			return err
+		}
+	}
+	if err := setIPv6MulticastLoopback(c.fd, false); err != nil {
+		return err
+	}
+	if err := joinIPv6Group(c.fd, ifi, ip); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/unicast_posix_test.go b/third_party/gofrontend/libgo/go/net/unicast_posix_test.go
new file mode 100644
index 0000000..452ac92
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/unicast_posix_test.go
@@ -0,0 +1,466 @@
+// 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.
+
+// +build !plan9
+
+package net
+
+import (
+	"runtime"
+	"syscall"
+	"testing"
+)
+
+var listenerTests = []struct {
+	net      string
+	laddr    string
+	ipv6     bool // test with underlying AF_INET6 socket
+	wildcard bool // test with wildcard address
+}{
+	{net: "tcp", laddr: "", wildcard: true},
+	{net: "tcp", laddr: "0.0.0.0", wildcard: true},
+	{net: "tcp", laddr: "[::ffff:0.0.0.0]", wildcard: true},
+	{net: "tcp", laddr: "[::]", ipv6: true, wildcard: true},
+
+	{net: "tcp", laddr: "127.0.0.1"},
+	{net: "tcp", laddr: "[::ffff:127.0.0.1]"},
+	{net: "tcp", laddr: "[::1]", ipv6: true},
+
+	{net: "tcp4", laddr: "", wildcard: true},
+	{net: "tcp4", laddr: "0.0.0.0", wildcard: true},
+	{net: "tcp4", laddr: "[::ffff:0.0.0.0]", wildcard: true},
+
+	{net: "tcp4", laddr: "127.0.0.1"},
+	{net: "tcp4", laddr: "[::ffff:127.0.0.1]"},
+
+	{net: "tcp6", laddr: "", ipv6: true, wildcard: true},
+	{net: "tcp6", laddr: "[::]", ipv6: true, wildcard: true},
+
+	{net: "tcp6", laddr: "[::1]", ipv6: true},
+}
+
+// TestTCPListener tests both single and double listen to a test
+// listener with same address family, same listening address and
+// same port.
+func TestTCPListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	for _, tt := range listenerTests {
+		if tt.wildcard && (testing.Short() || !*testExternal) {
+			continue
+		}
+		if tt.ipv6 && !supportsIPv6 {
+			continue
+		}
+		l1, port := usableListenPort(t, tt.net, tt.laddr)
+		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
+		l2, err := Listen(tt.net, tt.laddr+":"+port)
+		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
+		l1.Close()
+	}
+}
+
+// TestUDPListener tests both single and double listen to a test
+// listener with same address family, same listening address and
+// same port.
+func TestUDPListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	toudpnet := func(net string) string {
+		switch net {
+		case "tcp":
+			return "udp"
+		case "tcp4":
+			return "udp4"
+		case "tcp6":
+			return "udp6"
+		}
+		return "<nil>"
+	}
+
+	for _, tt := range listenerTests {
+		if tt.wildcard && (testing.Short() || !*testExternal) {
+			continue
+		}
+		if tt.ipv6 && !supportsIPv6 {
+			continue
+		}
+		tt.net = toudpnet(tt.net)
+		l1, port := usableListenPacketPort(t, tt.net, tt.laddr)
+		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
+		l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
+		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
+		l1.Close()
+	}
+}
+
+var dualStackListenerTests = []struct {
+	net1     string // first listener
+	laddr1   string
+	net2     string // second listener
+	laddr2   string
+	wildcard bool  // test with wildcard address
+	xerr     error // expected error value, nil or other
+}{
+	// Test cases and expected results for the attemping 2nd listen on the same port
+	// 1st listen                2nd listen                 darwin  freebsd  linux  openbsd
+	// ------------------------------------------------------------------------------------
+	// "tcp"  ""                 "tcp"  ""                    -        -       -       -
+	// "tcp"  ""                 "tcp"  "0.0.0.0"             -        -       -       -
+	// "tcp"  "0.0.0.0"          "tcp"  ""                    -        -       -       -
+	// ------------------------------------------------------------------------------------
+	// "tcp"  ""                 "tcp"  "[::]"                -        -       -       ok
+	// "tcp"  "[::]"             "tcp"  ""                    -        -       -       ok
+	// "tcp"  "0.0.0.0"          "tcp"  "[::]"                -        -       -       ok
+	// "tcp"  "[::]"             "tcp"  "0.0.0.0"             -        -       -       ok
+	// "tcp"  "[::ffff:0.0.0.0]" "tcp"  "[::]"                -        -       -       ok
+	// "tcp"  "[::]"             "tcp"  "[::ffff:0.0.0.0]"    -        -       -       ok
+	// ------------------------------------------------------------------------------------
+	// "tcp4" ""                 "tcp6" ""                    ok       ok      ok      ok
+	// "tcp6" ""                 "tcp4" ""                    ok       ok      ok      ok
+	// "tcp4" "0.0.0.0"          "tcp6" "[::]"                ok       ok      ok      ok
+	// "tcp6" "[::]"             "tcp4" "0.0.0.0"             ok       ok      ok      ok
+	// ------------------------------------------------------------------------------------
+	// "tcp"  "127.0.0.1"        "tcp"  "[::1]"               ok       ok      ok      ok
+	// "tcp"  "[::1]"            "tcp"  "127.0.0.1"           ok       ok      ok      ok
+	// "tcp4" "127.0.0.1"        "tcp6" "[::1]"               ok       ok      ok      ok
+	// "tcp6" "[::1]"            "tcp4" "127.0.0.1"           ok       ok      ok      ok
+	//
+	// Platform default configurations:
+	// darwin, kernel version 11.3.0
+	//	net.inet6.ip6.v6only=0 (overridable by sysctl or IPV6_V6ONLY option)
+	// freebsd, kernel version 8.2
+	//	net.inet6.ip6.v6only=1 (overridable by sysctl or IPV6_V6ONLY option)
+	// linux, kernel version 3.0.0
+	//	net.ipv6.bindv6only=0 (overridable by sysctl or IPV6_V6ONLY option)
+	// openbsd, kernel version 5.0
+	//	net.inet6.ip6.v6only=1 (overriding is prohibited)
+
+	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "0.0.0.0", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "0.0.0.0", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
+
+	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "0.0.0.0", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "0.0.0.0", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "[::ffff:0.0.0.0]", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "[::ffff:0.0.0.0]", wildcard: true, xerr: syscall.EADDRINUSE},
+
+	{net1: "tcp4", laddr1: "", net2: "tcp6", laddr2: "", wildcard: true},
+	{net1: "tcp6", laddr1: "", net2: "tcp4", laddr2: "", wildcard: true},
+	{net1: "tcp4", laddr1: "0.0.0.0", net2: "tcp6", laddr2: "[::]", wildcard: true},
+	{net1: "tcp6", laddr1: "[::]", net2: "tcp4", laddr2: "0.0.0.0", wildcard: true},
+
+	{net1: "tcp", laddr1: "127.0.0.1", net2: "tcp", laddr2: "[::1]"},
+	{net1: "tcp", laddr1: "[::1]", net2: "tcp", laddr2: "127.0.0.1"},
+	{net1: "tcp4", laddr1: "127.0.0.1", net2: "tcp6", laddr2: "[::1]"},
+	{net1: "tcp6", laddr1: "[::1]", net2: "tcp4", laddr2: "127.0.0.1"},
+}
+
+// TestDualStackTCPListener tests both single and double listen
+// to a test listener with various address families, different
+// listening address and same port.
+func TestDualStackTCPListener(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in -short mode, see issue 5001")
+	}
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	if !supportsIPv6 {
+		t.Skip("ipv6 is not supported")
+	}
+
+	for _, tt := range dualStackListenerTests {
+		if tt.wildcard && !*testExternal {
+			continue
+		}
+		switch runtime.GOOS {
+		case "openbsd":
+			if tt.wildcard && differentWildcardAddr(tt.laddr1, tt.laddr2) {
+				tt.xerr = nil
+			}
+		}
+		l1, port := usableListenPort(t, tt.net1, tt.laddr1)
+		laddr := tt.laddr1 + ":" + port
+		checkFirstListener(t, tt.net1, laddr, l1)
+		laddr = tt.laddr2 + ":" + port
+		l2, err := Listen(tt.net2, laddr)
+		checkDualStackSecondListener(t, tt.net2, laddr, tt.xerr, err, l2)
+		l1.Close()
+	}
+}
+
+// TestDualStackUDPListener tests both single and double listen
+// to a test listener with various address families, differnet
+// listening address and same port.
+func TestDualStackUDPListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	if !supportsIPv6 {
+		t.Skip("ipv6 is not supported")
+	}
+
+	toudpnet := func(net string) string {
+		switch net {
+		case "tcp":
+			return "udp"
+		case "tcp4":
+			return "udp4"
+		case "tcp6":
+			return "udp6"
+		}
+		return "<nil>"
+	}
+
+	for _, tt := range dualStackListenerTests {
+		if tt.wildcard && (testing.Short() || !*testExternal) {
+			continue
+		}
+		tt.net1 = toudpnet(tt.net1)
+		tt.net2 = toudpnet(tt.net2)
+		switch runtime.GOOS {
+		case "openbsd":
+			if tt.wildcard && differentWildcardAddr(tt.laddr1, tt.laddr2) {
+				tt.xerr = nil
+			}
+		}
+		l1, port := usableListenPacketPort(t, tt.net1, tt.laddr1)
+		laddr := tt.laddr1 + ":" + port
+		checkFirstListener(t, tt.net1, laddr, l1)
+		laddr = tt.laddr2 + ":" + port
+		l2, err := ListenPacket(tt.net2, laddr)
+		checkDualStackSecondListener(t, tt.net2, laddr, tt.xerr, err, l2)
+		l1.Close()
+	}
+}
+
+func usableListenPort(t *testing.T, net, laddr string) (l Listener, port string) {
+	var nladdr string
+	var err error
+	switch net {
+	default:
+		panic("usableListenPort net=" + net)
+	case "tcp", "tcp4", "tcp6":
+		l, err = Listen(net, laddr+":0")
+		if err != nil {
+			t.Fatalf("Probe Listen(%q, %q) failed: %v", net, laddr, err)
+		}
+		nladdr = l.(*TCPListener).Addr().String()
+	}
+	_, port, err = SplitHostPort(nladdr)
+	if err != nil {
+		t.Fatalf("SplitHostPort failed: %v", err)
+	}
+	return l, port
+}
+
+func usableListenPacketPort(t *testing.T, net, laddr string) (l PacketConn, port string) {
+	var nladdr string
+	var err error
+	switch net {
+	default:
+		panic("usableListenPacketPort net=" + net)
+	case "udp", "udp4", "udp6":
+		l, err = ListenPacket(net, laddr+":0")
+		if err != nil {
+			t.Fatalf("Probe ListenPacket(%q, %q) failed: %v", net, laddr, err)
+		}
+		nladdr = l.(*UDPConn).LocalAddr().String()
+	}
+	_, port, err = SplitHostPort(nladdr)
+	if err != nil {
+		t.Fatalf("SplitHostPort failed: %v", err)
+	}
+	return l, port
+}
+
+func differentWildcardAddr(i, j string) bool {
+	if (i == "" || i == "0.0.0.0" || i == "::ffff:0.0.0.0") && (j == "" || j == "0.0.0.0" || j == "::ffff:0.0.0.0") {
+		return false
+	}
+	if i == "[::]" && j == "[::]" {
+		return false
+	}
+	return true
+}
+
+func checkFirstListener(t *testing.T, net, laddr string, l interface{}) {
+	switch net {
+	case "tcp":
+		fd := l.(*TCPListener).fd
+		checkDualStackAddrFamily(t, net, laddr, fd)
+	case "tcp4":
+		fd := l.(*TCPListener).fd
+		if fd.family != syscall.AF_INET {
+			t.Fatalf("First Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET)
+		}
+	case "tcp6":
+		fd := l.(*TCPListener).fd
+		if fd.family != syscall.AF_INET6 {
+			t.Fatalf("First Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
+		}
+	case "udp":
+		fd := l.(*UDPConn).fd
+		checkDualStackAddrFamily(t, net, laddr, fd)
+	case "udp4":
+		fd := l.(*UDPConn).fd
+		if fd.family != syscall.AF_INET {
+			t.Fatalf("First ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET)
+		}
+	case "udp6":
+		fd := l.(*UDPConn).fd
+		if fd.family != syscall.AF_INET6 {
+			t.Fatalf("First ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
+		}
+	default:
+		t.Fatalf("Unexpected network: %q", net)
+	}
+}
+
+func checkSecondListener(t *testing.T, net, laddr string, err error, l interface{}) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+		if err == nil {
+			l.(*TCPListener).Close()
+			t.Fatalf("Second Listen(%q, %q) should fail", net, laddr)
+		}
+	case "udp", "udp4", "udp6":
+		if err == nil {
+			l.(*UDPConn).Close()
+			t.Fatalf("Second ListenPacket(%q, %q) should fail", net, laddr)
+		}
+	default:
+		t.Fatalf("Unexpected network: %q", net)
+	}
+}
+
+func checkDualStackSecondListener(t *testing.T, net, laddr string, xerr, err error, l interface{}) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+		if xerr == nil && err != nil || xerr != nil && err == nil {
+			t.Fatalf("Second Listen(%q, %q) returns %v, expected %v", net, laddr, err, xerr)
+		}
+		if err == nil {
+			l.(*TCPListener).Close()
+		}
+	case "udp", "udp4", "udp6":
+		if xerr == nil && err != nil || xerr != nil && err == nil {
+			t.Fatalf("Second ListenPacket(%q, %q) returns %v, expected %v", net, laddr, err, xerr)
+		}
+		if err == nil {
+			l.(*UDPConn).Close()
+		}
+	default:
+		t.Fatalf("Unexpected network: %q", net)
+	}
+}
+
+func checkDualStackAddrFamily(t *testing.T, net, laddr string, fd *netFD) {
+	switch a := fd.laddr.(type) {
+	case *TCPAddr:
+		// If a node under test supports both IPv6 capability
+		// and IPv6 IPv4-mapping capability, we can assume
+		// that the node listens on a wildcard address with an
+		// AF_INET6 socket.
+		if supportsIPv4map && fd.laddr.(*TCPAddr).isWildcard() {
+			if fd.family != syscall.AF_INET6 {
+				t.Fatalf("Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
+			}
+		} else {
+			if fd.family != a.family() {
+				t.Fatalf("Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, a.family())
+			}
+		}
+	case *UDPAddr:
+		// If a node under test supports both IPv6 capability
+		// and IPv6 IPv4-mapping capability, we can assume
+		// that the node listens on a wildcard address with an
+		// AF_INET6 socket.
+		if supportsIPv4map && fd.laddr.(*UDPAddr).isWildcard() {
+			if fd.family != syscall.AF_INET6 {
+				t.Fatalf("ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
+			}
+		} else {
+			if fd.family != a.family() {
+				t.Fatalf("ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, a.family())
+			}
+		}
+	default:
+		t.Fatalf("Unexpected protocol address type: %T", a)
+	}
+}
+
+var prohibitionaryDialArgTests = []struct {
+	net  string
+	addr string
+}{
+	{"tcp6", "127.0.0.1"},
+	{"tcp6", "[::ffff:127.0.0.1]"},
+}
+
+func TestProhibitionaryDialArgs(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	// This test requires both IPv6 and IPv6 IPv4-mapping functionality.
+	if !supportsIPv4map || testing.Short() || !*testExternal {
+		return
+	}
+
+	l, port := usableListenPort(t, "tcp", "[::]")
+	defer l.Close()
+
+	for _, tt := range prohibitionaryDialArgTests {
+		c, err := Dial(tt.net, tt.addr+":"+port)
+		if err == nil {
+			c.Close()
+			t.Fatalf("Dial(%q, %q) should fail", tt.net, tt.addr)
+		}
+	}
+}
+
+func TestWildWildcardListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	defer func() {
+		if p := recover(); p != nil {
+			t.Fatalf("Listen, ListenPacket or protocol-specific Listen panicked: %v", p)
+		}
+	}()
+
+	if ln, err := Listen("tcp", ""); err == nil {
+		ln.Close()
+	}
+	if ln, err := ListenPacket("udp", ""); err == nil {
+		ln.Close()
+	}
+	if ln, err := ListenTCP("tcp", nil); err == nil {
+		ln.Close()
+	}
+	if ln, err := ListenUDP("udp", nil); err == nil {
+		ln.Close()
+	}
+	if ln, err := ListenIP("ip:icmp", nil); err == nil {
+		ln.Close()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/unix_test.go b/third_party/gofrontend/libgo/go/net/unix_test.go
new file mode 100644
index 0000000..05643dd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/unix_test.go
@@ -0,0 +1,326 @@
+// Copyright 2013 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.
+
+// +build !nacl,!plan9,!windows
+
+package net
+
+import (
+	"bytes"
+	"os"
+	"reflect"
+	"runtime"
+	"syscall"
+	"testing"
+	"time"
+)
+
+func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
+	addr := testUnixAddr()
+	la, err := ResolveUnixAddr("unixgram", addr)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c, err := ListenUnixgram("unixgram", la)
+	if err != nil {
+		t.Fatalf("ListenUnixgram failed: %v", err)
+	}
+	defer func() {
+		c.Close()
+		os.Remove(addr)
+	}()
+
+	off := make(chan bool)
+	data := [5]byte{1, 2, 3, 4, 5}
+	go func() {
+		defer func() { off <- true }()
+		s, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
+		if err != nil {
+			t.Errorf("syscall.Socket failed: %v", err)
+			return
+		}
+		defer syscall.Close(s)
+		rsa := &syscall.SockaddrUnix{Name: addr}
+		if err := syscall.Sendto(s, data[:], 0, rsa); err != nil {
+			t.Errorf("syscall.Sendto failed: %v", err)
+			return
+		}
+	}()
+
+	<-off
+	b := make([]byte, 64)
+	c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+	n, from, err := c.ReadFrom(b)
+	if err != nil {
+		t.Fatalf("UnixConn.ReadFrom failed: %v", err)
+	}
+	if from != nil {
+		t.Fatalf("neighbor address is %v", from)
+	}
+	if !bytes.Equal(b[:n], data[:]) {
+		t.Fatalf("got %v, want %v", b[:n], data[:])
+	}
+}
+
+func TestReadUnixgramWithZeroBytesBuffer(t *testing.T) {
+	// issue 4352: Recvfrom failed with "address family not
+	// supported by protocol family" if zero-length buffer provided
+
+	addr := testUnixAddr()
+	la, err := ResolveUnixAddr("unixgram", addr)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c, err := ListenUnixgram("unixgram", la)
+	if err != nil {
+		t.Fatalf("ListenUnixgram failed: %v", err)
+	}
+	defer func() {
+		c.Close()
+		os.Remove(addr)
+	}()
+
+	off := make(chan bool)
+	go func() {
+		defer func() { off <- true }()
+		c, err := DialUnix("unixgram", nil, la)
+		if err != nil {
+			t.Errorf("DialUnix failed: %v", err)
+			return
+		}
+		defer c.Close()
+		if _, err := c.Write([]byte{1, 2, 3, 4, 5}); err != nil {
+			t.Errorf("UnixConn.Write failed: %v", err)
+			return
+		}
+	}()
+
+	<-off
+	c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+	_, from, err := c.ReadFrom(nil)
+	if err != nil {
+		t.Fatalf("UnixConn.ReadFrom failed: %v", err)
+	}
+	if from != nil {
+		t.Fatalf("neighbor address is %v", from)
+	}
+}
+
+func TestUnixgramAutobind(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("skipping: autobind is linux only")
+	}
+
+	laddr := &UnixAddr{Name: "", Net: "unixgram"}
+	c1, err := ListenUnixgram("unixgram", laddr)
+	if err != nil {
+		t.Fatalf("ListenUnixgram failed: %v", err)
+	}
+	defer c1.Close()
+
+	// retrieve the autobind address
+	autoAddr := c1.LocalAddr().(*UnixAddr)
+	if len(autoAddr.Name) <= 1 {
+		t.Fatalf("invalid autobind address: %v", autoAddr)
+	}
+	if autoAddr.Name[0] != '@' {
+		t.Fatalf("invalid autobind address: %v", autoAddr)
+	}
+
+	c2, err := DialUnix("unixgram", nil, autoAddr)
+	if err != nil {
+		t.Fatalf("DialUnix failed: %v", err)
+	}
+	defer c2.Close()
+
+	if !reflect.DeepEqual(c1.LocalAddr(), c2.RemoteAddr()) {
+		t.Fatalf("expected autobind address %v, got %v", c1.LocalAddr(), c2.RemoteAddr())
+	}
+}
+
+func TestUnixAutobindClose(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("skipping: autobind is linux only")
+	}
+	laddr := &UnixAddr{Name: "", Net: "unix"}
+	ln, err := ListenUnix("unix", laddr)
+	if err != nil {
+		t.Fatalf("ListenUnix failed: %v", err)
+	}
+	ln.Close()
+}
+
+func TestUnixgramWrite(t *testing.T) {
+	addr := testUnixAddr()
+	laddr, err := ResolveUnixAddr("unixgram", addr)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c, err := ListenPacket("unixgram", addr)
+	if err != nil {
+		t.Fatalf("ListenPacket failed: %v", err)
+	}
+	defer os.Remove(addr)
+	defer c.Close()
+
+	testUnixgramWriteConn(t, laddr)
+	testUnixgramWritePacketConn(t, laddr)
+}
+
+func testUnixgramWriteConn(t *testing.T, raddr *UnixAddr) {
+	c, err := Dial("unixgram", raddr.String())
+	if err != nil {
+		t.Fatalf("Dial failed: %v", err)
+	}
+	defer c.Close()
+
+	if _, err := c.(*UnixConn).WriteToUnix([]byte("Connection-oriented mode socket"), raddr); err == nil {
+		t.Fatal("WriteToUnix should fail")
+	} else if err.(*OpError).Err != ErrWriteToConnected {
+		t.Fatalf("WriteToUnix should fail as ErrWriteToConnected: %v", err)
+	}
+	if _, err = c.(*UnixConn).WriteTo([]byte("Connection-oriented mode socket"), raddr); err == nil {
+		t.Fatal("WriteTo should fail")
+	} else if err.(*OpError).Err != ErrWriteToConnected {
+		t.Fatalf("WriteTo should fail as ErrWriteToConnected: %v", err)
+	}
+	if _, _, err = c.(*UnixConn).WriteMsgUnix([]byte("Connection-oriented mode socket"), nil, raddr); err == nil {
+		t.Fatal("WriteTo should fail")
+	} else if err.(*OpError).Err != ErrWriteToConnected {
+		t.Fatalf("WriteMsgUnix should fail as ErrWriteToConnected: %v", err)
+	}
+	if _, err := c.Write([]byte("Connection-oriented mode socket")); err != nil {
+		t.Fatalf("Write failed: %v", err)
+	}
+}
+
+func testUnixgramWritePacketConn(t *testing.T, raddr *UnixAddr) {
+	addr := testUnixAddr()
+	c, err := ListenPacket("unixgram", addr)
+	if err != nil {
+		t.Fatalf("ListenPacket failed: %v", err)
+	}
+	defer os.Remove(addr)
+	defer c.Close()
+
+	if _, err := c.(*UnixConn).WriteToUnix([]byte("Connectionless mode socket"), raddr); err != nil {
+		t.Fatalf("WriteToUnix failed: %v", err)
+	}
+	if _, err := c.WriteTo([]byte("Connectionless mode socket"), raddr); err != nil {
+		t.Fatalf("WriteTo failed: %v", err)
+	}
+	if _, _, err := c.(*UnixConn).WriteMsgUnix([]byte("Connectionless mode socket"), nil, raddr); err != nil {
+		t.Fatalf("WriteMsgUnix failed: %v", err)
+	}
+	if _, err := c.(*UnixConn).Write([]byte("Connectionless mode socket")); err == nil {
+		t.Fatal("Write should fail")
+	}
+}
+
+func TestUnixConnLocalAndRemoteNames(t *testing.T) {
+	for _, laddr := range []string{"", testUnixAddr()} {
+		laddr := laddr
+		taddr := testUnixAddr()
+		ta, err := ResolveUnixAddr("unix", taddr)
+		if err != nil {
+			t.Fatalf("ResolveUnixAddr failed: %v", err)
+		}
+		ln, err := ListenUnix("unix", ta)
+		if err != nil {
+			t.Fatalf("ListenUnix failed: %v", err)
+		}
+		defer func() {
+			ln.Close()
+			os.Remove(taddr)
+		}()
+
+		done := make(chan int)
+		go transponder(t, ln, done)
+
+		la, err := ResolveUnixAddr("unix", laddr)
+		if err != nil {
+			t.Fatalf("ResolveUnixAddr failed: %v", err)
+		}
+		c, err := DialUnix("unix", la, ta)
+		if err != nil {
+			t.Fatalf("DialUnix failed: %v", err)
+		}
+		defer func() {
+			c.Close()
+			if la != nil {
+				defer os.Remove(laddr)
+			}
+		}()
+		if _, err := c.Write([]byte("UNIXCONN LOCAL AND REMOTE NAME TEST")); err != nil {
+			t.Fatalf("UnixConn.Write failed: %v", err)
+		}
+
+		if runtime.GOOS == "linux" && laddr == "" {
+			laddr = "@" // autobind feature
+		}
+		var connAddrs = [3]struct{ got, want Addr }{
+			{ln.Addr(), ta},
+			{c.LocalAddr(), &UnixAddr{Name: laddr, Net: "unix"}},
+			{c.RemoteAddr(), ta},
+		}
+		for _, ca := range connAddrs {
+			if !reflect.DeepEqual(ca.got, ca.want) {
+				t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
+			}
+		}
+
+		<-done
+	}
+}
+
+func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
+	for _, laddr := range []string{"", testUnixAddr()} {
+		laddr := laddr
+		taddr := testUnixAddr()
+		ta, err := ResolveUnixAddr("unixgram", taddr)
+		if err != nil {
+			t.Fatalf("ResolveUnixAddr failed: %v", err)
+		}
+		c1, err := ListenUnixgram("unixgram", ta)
+		if err != nil {
+			t.Fatalf("ListenUnixgram failed: %v", err)
+		}
+		defer func() {
+			c1.Close()
+			os.Remove(taddr)
+		}()
+
+		var la *UnixAddr
+		if laddr != "" {
+			if la, err = ResolveUnixAddr("unixgram", laddr); err != nil {
+				t.Fatalf("ResolveUnixAddr failed: %v", err)
+			}
+		}
+		c2, err := DialUnix("unixgram", la, ta)
+		if err != nil {
+			t.Fatalf("DialUnix failed: %v", err)
+		}
+		defer func() {
+			c2.Close()
+			if la != nil {
+				defer os.Remove(laddr)
+			}
+		}()
+
+		if runtime.GOOS == "linux" && laddr == "" {
+			laddr = "@" // autobind feature
+		}
+		var connAddrs = [4]struct{ got, want Addr }{
+			{c1.LocalAddr(), ta},
+			{c1.RemoteAddr(), nil},
+			{c2.LocalAddr(), &UnixAddr{Name: laddr, Net: "unixgram"}},
+			{c2.RemoteAddr(), ta},
+		}
+		for _, ca := range connAddrs {
+			if !reflect.DeepEqual(ca.got, ca.want) {
+				t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/unixsock.go b/third_party/gofrontend/libgo/go/net/unixsock.go
new file mode 100644
index 0000000..8595584
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/unixsock.go
@@ -0,0 +1,43 @@
+// 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 net
+
+// UnixAddr represents the address of a Unix domain socket end point.
+type UnixAddr struct {
+	Name string
+	Net  string
+}
+
+// Network returns the address's network name, "unix", "unixgram" or
+// "unixpacket".
+func (a *UnixAddr) Network() string {
+	return a.Net
+}
+
+func (a *UnixAddr) String() string {
+	if a == nil {
+		return "<nil>"
+	}
+	return a.Name
+}
+
+func (a *UnixAddr) toAddr() Addr {
+	if a == nil {
+		return nil
+	}
+	return a
+}
+
+// ResolveUnixAddr parses addr as a Unix domain socket address.
+// The string net gives the network name, "unix", "unixgram" or
+// "unixpacket".
+func ResolveUnixAddr(net, addr string) (*UnixAddr, error) {
+	switch net {
+	case "unix", "unixgram", "unixpacket":
+		return &UnixAddr{Name: addr, Net: net}, nil
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/unixsock_plan9.go b/third_party/gofrontend/libgo/go/net/unixsock_plan9.go
new file mode 100644
index 0000000..c60c1d8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/unixsock_plan9.go
@@ -0,0 +1,143 @@
+// 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 net
+
+import (
+	"os"
+	"syscall"
+	"time"
+)
+
+// UnixConn is an implementation of the Conn interface for connections
+// to Unix domain sockets.
+type UnixConn struct {
+	conn
+}
+
+// ReadFromUnix reads a packet from c, copying the payload into b.  It
+// returns the number of bytes copied into b and the source address of
+// the packet.
+//
+// ReadFromUnix can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
+	return 0, nil, syscall.EPLAN9
+}
+
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
+	return 0, nil, syscall.EPLAN9
+}
+
+// ReadMsgUnix reads a packet from c, copying the payload into b and
+// the associated out-of-band data into oob.  It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet, and the source address of the packet.
+func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
+	return 0, 0, 0, nil, syscall.EPLAN9
+}
+
+// WriteToUnix writes a packet to addr via c, copying the payload from b.
+//
+// WriteToUnix can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
+func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
+	return 0, syscall.EPLAN9
+}
+
+// WriteTo implements the PacketConn WriteTo method.
+func (c *UnixConn) WriteTo(b []byte, addr Addr) (int, error) {
+	return 0, syscall.EPLAN9
+}
+
+// WriteMsgUnix writes a packet to addr via c, copying the payload
+// from b and the associated out-of-band data from oob.  It returns
+// the number of payload and out-of-band bytes written.
+func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
+	return 0, 0, syscall.EPLAN9
+}
+
+// CloseRead shuts down the reading side of the Unix domain connection.
+// Most callers should just use Close.
+func (c *UnixConn) CloseRead() error {
+	return syscall.EPLAN9
+}
+
+// CloseWrite shuts down the writing side of the Unix domain connection.
+// Most callers should just use Close.
+func (c *UnixConn) CloseWrite() error {
+	return syscall.EPLAN9
+}
+
+// DialUnix connects to the remote address raddr on the network net,
+// which must be "unix", "unixgram" or "unixpacket".  If laddr is not
+// nil, it is used as the local address for the connection.
+func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
+	return dialUnix(net, laddr, raddr, noDeadline)
+}
+
+func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
+	return nil, syscall.EPLAN9
+}
+
+// UnixListener is a Unix domain socket listener.  Clients should
+// typically use variables of type Listener instead of assuming Unix
+// domain sockets.
+type UnixListener struct{}
+
+// ListenUnix announces on the Unix domain socket laddr and returns a
+// Unix listener.  The network net must be "unix" or "unixpacket".
+func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
+	return nil, syscall.EPLAN9
+}
+
+// AcceptUnix accepts the next incoming call and returns the new
+// connection.
+func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
+	return nil, syscall.EPLAN9
+}
+
+// Accept implements the Accept method in the Listener interface; it
+// waits for the next call and returns a generic Conn.
+func (l *UnixListener) Accept() (Conn, error) {
+	return nil, syscall.EPLAN9
+}
+
+// Close stops listening on the Unix address.  Already accepted
+// connections are not closed.
+func (l *UnixListener) Close() error {
+	return syscall.EPLAN9
+}
+
+// Addr returns the listener's network address.
+func (l *UnixListener) Addr() Addr { return nil }
+
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *UnixListener) SetDeadline(t time.Time) error {
+	return syscall.EPLAN9
+}
+
+// File returns a copy of the underlying os.File, set to blocking
+// mode.  It is the caller's responsibility to close f when finished.
+// Closing l does not affect f, and closing f does not affect l.
+//
+// The returned os.File's file descriptor is different from the
+// connection's.  Attempting to change properties of the original
+// using this duplicate may or may not have the desired effect.
+func (l *UnixListener) File() (*os.File, error) {
+	return nil, syscall.EPLAN9
+}
+
+// ListenUnixgram listens for incoming Unix datagram packets addressed
+// to the local address laddr.  The network net must be "unixgram".
+// The returned connection's ReadFrom and WriteTo methods can be used
+// to receive and send packets with per-packet addressing.
+func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
+	return nil, syscall.EPLAN9
+}
diff --git a/third_party/gofrontend/libgo/go/net/unixsock_posix.go b/third_party/gofrontend/libgo/go/net/unixsock_posix.go
new file mode 100644
index 0000000..2610779
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/unixsock_posix.go
@@ -0,0 +1,373 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package net
+
+import (
+	"errors"
+	"os"
+	"syscall"
+	"time"
+)
+
+func unixSocket(net string, laddr, raddr sockaddr, mode string, deadline time.Time) (*netFD, error) {
+	var sotype int
+	switch net {
+	case "unix":
+		sotype = syscall.SOCK_STREAM
+	case "unixgram":
+		sotype = syscall.SOCK_DGRAM
+	case "unixpacket":
+		sotype = syscall.SOCK_SEQPACKET
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+
+	switch mode {
+	case "dial":
+		if laddr != nil && laddr.isWildcard() {
+			laddr = nil
+		}
+		if raddr != nil && raddr.isWildcard() {
+			raddr = nil
+		}
+		if raddr == nil && (sotype != syscall.SOCK_DGRAM || laddr == nil) {
+			return nil, errMissingAddress
+		}
+	case "listen":
+	default:
+		return nil, errors.New("unknown mode: " + mode)
+	}
+
+	f := sockaddrToUnix
+	if sotype == syscall.SOCK_DGRAM {
+		f = sockaddrToUnixgram
+	} else if sotype == syscall.SOCK_SEQPACKET {
+		f = sockaddrToUnixpacket
+	}
+
+	fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, laddr, raddr, deadline, f)
+	if err != nil {
+		return nil, err
+	}
+	return fd, nil
+}
+
+func sockaddrToUnix(sa syscall.Sockaddr) Addr {
+	if s, ok := sa.(*syscall.SockaddrUnix); ok {
+		return &UnixAddr{Name: s.Name, Net: "unix"}
+	}
+	return nil
+}
+
+func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
+	if s, ok := sa.(*syscall.SockaddrUnix); ok {
+		return &UnixAddr{Name: s.Name, Net: "unixgram"}
+	}
+	return nil
+}
+
+func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
+	if s, ok := sa.(*syscall.SockaddrUnix); ok {
+		return &UnixAddr{Name: s.Name, Net: "unixpacket"}
+	}
+	return nil
+}
+
+func sotypeToNet(sotype int) string {
+	switch sotype {
+	case syscall.SOCK_STREAM:
+		return "unix"
+	case syscall.SOCK_DGRAM:
+		return "unixgram"
+	case syscall.SOCK_SEQPACKET:
+		return "unixpacket"
+	default:
+		panic("sotypeToNet unknown socket type")
+	}
+}
+
+func (a *UnixAddr) family() int {
+	return syscall.AF_UNIX
+}
+
+func (a *UnixAddr) isWildcard() bool {
+	return a == nil || a.Name == ""
+}
+
+func (a *UnixAddr) sockaddr(family int) (syscall.Sockaddr, error) {
+	if a == nil {
+		return nil, nil
+	}
+	return &syscall.SockaddrUnix{Name: a.Name}, nil
+}
+
+// UnixConn is an implementation of the Conn interface for connections
+// to Unix domain sockets.
+type UnixConn struct {
+	conn
+}
+
+func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
+
+// ReadFromUnix reads a packet from c, copying the payload into b.  It
+// returns the number of bytes copied into b and the source address of
+// the packet.
+//
+// ReadFromUnix can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
+	if !c.ok() {
+		return 0, nil, syscall.EINVAL
+	}
+	n, sa, err := c.fd.readFrom(b)
+	switch sa := sa.(type) {
+	case *syscall.SockaddrUnix:
+		if sa.Name != "" {
+			addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
+		}
+	}
+	return
+}
+
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
+	if !c.ok() {
+		return 0, nil, syscall.EINVAL
+	}
+	n, addr, err := c.ReadFromUnix(b)
+	return n, addr.toAddr(), err
+}
+
+// ReadMsgUnix reads a packet from c, copying the payload into b and
+// the associated out-of-band data into oob.  It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet, and the source address of the packet.
+func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
+	if !c.ok() {
+		return 0, 0, 0, nil, syscall.EINVAL
+	}
+	n, oobn, flags, sa, err := c.fd.readMsg(b, oob)
+	switch sa := sa.(type) {
+	case *syscall.SockaddrUnix:
+		if sa.Name != "" {
+			addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
+		}
+	}
+	return
+}
+
+// WriteToUnix writes a packet to addr via c, copying the payload from b.
+//
+// WriteToUnix can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
+func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	if c.fd.isConnected {
+		return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
+	}
+	if addr == nil {
+		return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+	}
+	if addr.Net != sotypeToNet(c.fd.sotype) {
+		return 0, syscall.EAFNOSUPPORT
+	}
+	sa := &syscall.SockaddrUnix{Name: addr.Name}
+	return c.fd.writeTo(b, sa)
+}
+
+// WriteTo implements the PacketConn WriteTo method.
+func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	a, ok := addr.(*UnixAddr)
+	if !ok {
+		return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL}
+	}
+	return c.WriteToUnix(b, a)
+}
+
+// WriteMsgUnix writes a packet to addr via c, copying the payload
+// from b and the associated out-of-band data from oob.  It returns
+// the number of payload and out-of-band bytes written.
+func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
+	if !c.ok() {
+		return 0, 0, syscall.EINVAL
+	}
+	if c.fd.sotype == syscall.SOCK_DGRAM && c.fd.isConnected {
+		return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
+	}
+	if addr != nil {
+		if addr.Net != sotypeToNet(c.fd.sotype) {
+			return 0, 0, syscall.EAFNOSUPPORT
+		}
+		sa := &syscall.SockaddrUnix{Name: addr.Name}
+		return c.fd.writeMsg(b, oob, sa)
+	}
+	return c.fd.writeMsg(b, oob, nil)
+}
+
+// CloseRead shuts down the reading side of the Unix domain connection.
+// Most callers should just use Close.
+func (c *UnixConn) CloseRead() error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.closeRead()
+}
+
+// CloseWrite shuts down the writing side of the Unix domain connection.
+// Most callers should just use Close.
+func (c *UnixConn) CloseWrite() error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.closeWrite()
+}
+
+// DialUnix connects to the remote address raddr on the network net,
+// which must be "unix", "unixgram" or "unixpacket".  If laddr is not
+// nil, it is used as the local address for the connection.
+func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
+	switch net {
+	case "unix", "unixgram", "unixpacket":
+	default:
+		return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
+	}
+	return dialUnix(net, laddr, raddr, noDeadline)
+}
+
+func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
+	fd, err := unixSocket(net, laddr, raddr, "dial", deadline)
+	if err != nil {
+		return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
+	}
+	return newUnixConn(fd), nil
+}
+
+// UnixListener is a Unix domain socket listener.  Clients should
+// typically use variables of type Listener instead of assuming Unix
+// domain sockets.
+type UnixListener struct {
+	fd   *netFD
+	path string
+}
+
+// ListenUnix announces on the Unix domain socket laddr and returns a
+// Unix listener.  The network net must be "unix" or "unixpacket".
+func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
+	switch net {
+	case "unix", "unixpacket":
+	default:
+		return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
+	}
+	if laddr == nil {
+		return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
+	}
+	fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
+	if err != nil {
+		return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
+	}
+	return &UnixListener{fd, fd.laddr.String()}, nil
+}
+
+// AcceptUnix accepts the next incoming call and returns the new
+// connection.
+func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
+	if l == nil || l.fd == nil {
+		return nil, syscall.EINVAL
+	}
+	toAddr := sockaddrToUnix
+	if l.fd.sotype == syscall.SOCK_SEQPACKET {
+		toAddr = sockaddrToUnixpacket
+	}
+	fd, err := l.fd.accept(toAddr)
+	if err != nil {
+		return nil, err
+	}
+	c := newUnixConn(fd)
+	return c, nil
+}
+
+// Accept implements the Accept method in the Listener interface; it
+// waits for the next call and returns a generic Conn.
+func (l *UnixListener) Accept() (c Conn, err error) {
+	c1, err := l.AcceptUnix()
+	if err != nil {
+		return nil, err
+	}
+	return c1, nil
+}
+
+// Close stops listening on the Unix address.  Already accepted
+// connections are not closed.
+func (l *UnixListener) Close() error {
+	if l == nil || l.fd == nil {
+		return syscall.EINVAL
+	}
+
+	// The operating system doesn't clean up
+	// the file that announcing created, so
+	// we have to clean it up ourselves.
+	// There's a race here--we can't know for
+	// sure whether someone else has come along
+	// and replaced our socket name already--
+	// but this sequence (remove then close)
+	// is at least compatible with the auto-remove
+	// sequence in ListenUnix.  It's only non-Go
+	// programs that can mess us up.
+	if l.path[0] != '@' {
+		syscall.Unlink(l.path)
+	}
+	return l.fd.Close()
+}
+
+// Addr returns the listener's network address.
+func (l *UnixListener) Addr() Addr { return l.fd.laddr }
+
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *UnixListener) SetDeadline(t time.Time) (err error) {
+	if l == nil || l.fd == nil {
+		return syscall.EINVAL
+	}
+	return l.fd.setDeadline(t)
+}
+
+// File returns a copy of the underlying os.File, set to blocking
+// mode.  It is the caller's responsibility to close f when finished.
+// Closing l does not affect f, and closing f does not affect l.
+//
+// The returned os.File's file descriptor is different from the
+// connection's.  Attempting to change properties of the original
+// using this duplicate may or may not have the desired effect.
+func (l *UnixListener) File() (f *os.File, err error) { return l.fd.dup() }
+
+// ListenUnixgram listens for incoming Unix datagram packets addressed
+// to the local address laddr.  The network net must be "unixgram".
+// The returned connection's ReadFrom and WriteTo methods can be used
+// to receive and send packets with per-packet addressing.
+func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
+	switch net {
+	case "unixgram":
+	default:
+		return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
+	}
+	if laddr == nil {
+		return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
+	}
+	fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
+	if err != nil {
+		return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
+	}
+	return newUnixConn(fd), nil
+}
diff --git a/third_party/gofrontend/libgo/go/net/url/url.go b/third_party/gofrontend/libgo/go/net/url/url.go
new file mode 100644
index 0000000..75f650a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/url/url.go
@@ -0,0 +1,700 @@
+// 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 url parses URLs and implements query escaping.
+// See RFC 3986.
+package url
+
+import (
+	"bytes"
+	"errors"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+// Error reports an error and the operation and URL that caused it.
+type Error struct {
+	Op  string
+	URL string
+	Err error
+}
+
+func (e *Error) Error() string { return e.Op + " " + e.URL + ": " + e.Err.Error() }
+
+func ishex(c byte) bool {
+	switch {
+	case '0' <= c && c <= '9':
+		return true
+	case 'a' <= c && c <= 'f':
+		return true
+	case 'A' <= c && c <= 'F':
+		return true
+	}
+	return false
+}
+
+func unhex(c byte) byte {
+	switch {
+	case '0' <= c && c <= '9':
+		return c - '0'
+	case 'a' <= c && c <= 'f':
+		return c - 'a' + 10
+	case 'A' <= c && c <= 'F':
+		return c - 'A' + 10
+	}
+	return 0
+}
+
+type encoding int
+
+const (
+	encodePath encoding = 1 + iota
+	encodeUserPassword
+	encodeQueryComponent
+	encodeFragment
+)
+
+type EscapeError string
+
+func (e EscapeError) Error() string {
+	return "invalid URL escape " + strconv.Quote(string(e))
+}
+
+// Return true if the specified character should be escaped when
+// appearing in a URL string, according to RFC 3986.
+// When 'all' is true the full range of reserved characters are matched.
+func shouldEscape(c byte, mode encoding) bool {
+	// §2.3 Unreserved characters (alphanum)
+	if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' {
+		return false
+	}
+
+	switch c {
+	case '-', '_', '.', '~': // §2.3 Unreserved characters (mark)
+		return false
+
+	case '$', '&', '+', ',', '/', ':', ';', '=', '?', '@': // §2.2 Reserved characters (reserved)
+		// Different sections of the URL allow a few of
+		// the reserved characters to appear unescaped.
+		switch mode {
+		case encodePath: // §3.3
+			// The RFC allows : @ & = + $ but saves / ; , for assigning
+			// meaning to individual path segments. This package
+			// only manipulates the path as a whole, so we allow those
+			// last two as well. That leaves only ? to escape.
+			return c == '?'
+
+		case encodeUserPassword: // §3.2.2
+			// The RFC allows ; : & = + $ , in userinfo, so we must escape only @ and /.
+			// The parsing of userinfo treats : as special so we must escape that too.
+			return c == '@' || c == '/' || c == ':'
+
+		case encodeQueryComponent: // §3.4
+			// The RFC reserves (so we must escape) everything.
+			return true
+
+		case encodeFragment: // §4.1
+			// The RFC text is silent but the grammar allows
+			// everything, so escape nothing.
+			return false
+		}
+	}
+
+	// Everything else must be escaped.
+	return true
+}
+
+// QueryUnescape does the inverse transformation of QueryEscape, converting
+// %AB into the byte 0xAB and '+' into ' ' (space). It returns an error if
+// any % is not followed by two hexadecimal digits.
+func QueryUnescape(s string) (string, error) {
+	return unescape(s, encodeQueryComponent)
+}
+
+// unescape unescapes a string; the mode specifies
+// which section of the URL string is being unescaped.
+func unescape(s string, mode encoding) (string, error) {
+	// Count %, check that they're well-formed.
+	n := 0
+	hasPlus := false
+	for i := 0; i < len(s); {
+		switch s[i] {
+		case '%':
+			n++
+			if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
+				s = s[i:]
+				if len(s) > 3 {
+					s = s[0:3]
+				}
+				return "", EscapeError(s)
+			}
+			i += 3
+		case '+':
+			hasPlus = mode == encodeQueryComponent
+			i++
+		default:
+			i++
+		}
+	}
+
+	if n == 0 && !hasPlus {
+		return s, nil
+	}
+
+	t := make([]byte, len(s)-2*n)
+	j := 0
+	for i := 0; i < len(s); {
+		switch s[i] {
+		case '%':
+			t[j] = unhex(s[i+1])<<4 | unhex(s[i+2])
+			j++
+			i += 3
+		case '+':
+			if mode == encodeQueryComponent {
+				t[j] = ' '
+			} else {
+				t[j] = '+'
+			}
+			j++
+			i++
+		default:
+			t[j] = s[i]
+			j++
+			i++
+		}
+	}
+	return string(t), nil
+}
+
+// QueryEscape escapes the string so it can be safely placed
+// inside a URL query.
+func QueryEscape(s string) string {
+	return escape(s, encodeQueryComponent)
+}
+
+func escape(s string, mode encoding) string {
+	spaceCount, hexCount := 0, 0
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		if shouldEscape(c, mode) {
+			if c == ' ' && mode == encodeQueryComponent {
+				spaceCount++
+			} else {
+				hexCount++
+			}
+		}
+	}
+
+	if spaceCount == 0 && hexCount == 0 {
+		return s
+	}
+
+	t := make([]byte, len(s)+2*hexCount)
+	j := 0
+	for i := 0; i < len(s); i++ {
+		switch c := s[i]; {
+		case c == ' ' && mode == encodeQueryComponent:
+			t[j] = '+'
+			j++
+		case shouldEscape(c, mode):
+			t[j] = '%'
+			t[j+1] = "0123456789ABCDEF"[c>>4]
+			t[j+2] = "0123456789ABCDEF"[c&15]
+			j += 3
+		default:
+			t[j] = s[i]
+			j++
+		}
+	}
+	return string(t)
+}
+
+// A URL represents a parsed URL (technically, a URI reference).
+// The general form represented is:
+//
+//	scheme://[userinfo@]host/path[?query][#fragment]
+//
+// URLs that do not start with a slash after the scheme are interpreted as:
+//
+//	scheme:opaque[?query][#fragment]
+//
+// Note that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.
+// A consequence is that it is impossible to tell which slashes in the Path were
+// slashes in the raw URL and which were %2f. This distinction is rarely important,
+// but when it is a client must use other routines to parse the raw URL or construct
+// the parsed URL. For example, an HTTP server can consult req.RequestURI, and
+// an HTTP client can use URL{Host: "example.com", Opaque: "//example.com/Go%2f"}
+// instead of URL{Host: "example.com", Path: "/Go/"}.
+type URL struct {
+	Scheme   string
+	Opaque   string    // encoded opaque data
+	User     *Userinfo // username and password information
+	Host     string    // host or host:port
+	Path     string
+	RawQuery string // encoded query values, without '?'
+	Fragment string // fragment for references, without '#'
+}
+
+// User returns a Userinfo containing the provided username
+// and no password set.
+func User(username string) *Userinfo {
+	return &Userinfo{username, "", false}
+}
+
+// UserPassword returns a Userinfo containing the provided username
+// and password.
+// This functionality should only be used with legacy web sites.
+// RFC 2396 warns that interpreting Userinfo this way
+// ``is NOT RECOMMENDED, because the passing of authentication
+// information in clear text (such as URI) has proven to be a
+// security risk in almost every case where it has been used.''
+func UserPassword(username, password string) *Userinfo {
+	return &Userinfo{username, password, true}
+}
+
+// The Userinfo type is an immutable encapsulation of username and
+// password details for a URL. An existing Userinfo value is guaranteed
+// to have a username set (potentially empty, as allowed by RFC 2396),
+// and optionally a password.
+type Userinfo struct {
+	username    string
+	password    string
+	passwordSet bool
+}
+
+// Username returns the username.
+func (u *Userinfo) Username() string {
+	return u.username
+}
+
+// Password returns the password in case it is set, and whether it is set.
+func (u *Userinfo) Password() (string, bool) {
+	if u.passwordSet {
+		return u.password, true
+	}
+	return "", false
+}
+
+// String returns the encoded userinfo information in the standard form
+// of "username[:password]".
+func (u *Userinfo) String() string {
+	s := escape(u.username, encodeUserPassword)
+	if u.passwordSet {
+		s += ":" + escape(u.password, encodeUserPassword)
+	}
+	return s
+}
+
+// Maybe rawurl is of the form scheme:path.
+// (Scheme must be [a-zA-Z][a-zA-Z0-9+-.]*)
+// If so, return scheme, path; else return "", rawurl.
+func getscheme(rawurl string) (scheme, path string, err error) {
+	for i := 0; i < len(rawurl); i++ {
+		c := rawurl[i]
+		switch {
+		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
+		// do nothing
+		case '0' <= c && c <= '9' || c == '+' || c == '-' || c == '.':
+			if i == 0 {
+				return "", rawurl, nil
+			}
+		case c == ':':
+			if i == 0 {
+				return "", "", errors.New("missing protocol scheme")
+			}
+			return rawurl[0:i], rawurl[i+1:], nil
+		default:
+			// we have encountered an invalid character,
+			// so there is no valid scheme
+			return "", rawurl, nil
+		}
+	}
+	return "", rawurl, nil
+}
+
+// Maybe s is of the form t c u.
+// If so, return t, c u (or t, u if cutc == true).
+// If not, return s, "".
+func split(s string, c string, cutc bool) (string, string) {
+	i := strings.Index(s, c)
+	if i < 0 {
+		return s, ""
+	}
+	if cutc {
+		return s[0:i], s[i+len(c):]
+	}
+	return s[0:i], s[i:]
+}
+
+// Parse parses rawurl into a URL structure.
+// The rawurl may be relative or absolute.
+func Parse(rawurl string) (url *URL, err error) {
+	// Cut off #frag
+	u, frag := split(rawurl, "#", true)
+	if url, err = parse(u, false); err != nil {
+		return nil, err
+	}
+	if frag == "" {
+		return url, nil
+	}
+	if url.Fragment, err = unescape(frag, encodeFragment); err != nil {
+		return nil, &Error{"parse", rawurl, err}
+	}
+	return url, nil
+}
+
+// ParseRequestURI parses rawurl into a URL structure.  It assumes that
+// rawurl was received in an HTTP request, so the rawurl is interpreted
+// only as an absolute URI or an absolute path.
+// The string rawurl is assumed not to have a #fragment suffix.
+// (Web browsers strip #fragment before sending the URL to a web server.)
+func ParseRequestURI(rawurl string) (url *URL, err error) {
+	return parse(rawurl, true)
+}
+
+// parse parses a URL from a string in one of two contexts.  If
+// viaRequest is true, the URL is assumed to have arrived via an HTTP request,
+// in which case only absolute URLs or path-absolute relative URLs are allowed.
+// If viaRequest is false, all forms of relative URLs are allowed.
+func parse(rawurl string, viaRequest bool) (url *URL, err error) {
+	var rest string
+
+	if rawurl == "" && viaRequest {
+		err = errors.New("empty url")
+		goto Error
+	}
+	url = new(URL)
+
+	if rawurl == "*" {
+		url.Path = "*"
+		return
+	}
+
+	// Split off possible leading "http:", "mailto:", etc.
+	// Cannot contain escaped characters.
+	if url.Scheme, rest, err = getscheme(rawurl); err != nil {
+		goto Error
+	}
+	url.Scheme = strings.ToLower(url.Scheme)
+
+	rest, url.RawQuery = split(rest, "?", true)
+
+	if !strings.HasPrefix(rest, "/") {
+		if url.Scheme != "" {
+			// We consider rootless paths per RFC 3986 as opaque.
+			url.Opaque = rest
+			return url, nil
+		}
+		if viaRequest {
+			err = errors.New("invalid URI for request")
+			goto Error
+		}
+	}
+
+	if (url.Scheme != "" || !viaRequest && !strings.HasPrefix(rest, "///")) && strings.HasPrefix(rest, "//") {
+		var authority string
+		authority, rest = split(rest[2:], "/", false)
+		url.User, url.Host, err = parseAuthority(authority)
+		if err != nil {
+			goto Error
+		}
+		if strings.Contains(url.Host, "%") {
+			err = errors.New("hexadecimal escape in host")
+			goto Error
+		}
+	}
+	if url.Path, err = unescape(rest, encodePath); err != nil {
+		goto Error
+	}
+	return url, nil
+
+Error:
+	return nil, &Error{"parse", rawurl, err}
+}
+
+func parseAuthority(authority string) (user *Userinfo, host string, err error) {
+	i := strings.LastIndex(authority, "@")
+	if i < 0 {
+		host = authority
+		return
+	}
+	userinfo, host := authority[:i], authority[i+1:]
+	if strings.Index(userinfo, ":") < 0 {
+		if userinfo, err = unescape(userinfo, encodeUserPassword); err != nil {
+			return
+		}
+		user = User(userinfo)
+	} else {
+		username, password := split(userinfo, ":", true)
+		if username, err = unescape(username, encodeUserPassword); err != nil {
+			return
+		}
+		if password, err = unescape(password, encodeUserPassword); err != nil {
+			return
+		}
+		user = UserPassword(username, password)
+	}
+	return
+}
+
+// String reassembles the URL into a valid URL string.
+func (u *URL) String() string {
+	var buf bytes.Buffer
+	if u.Scheme != "" {
+		buf.WriteString(u.Scheme)
+		buf.WriteByte(':')
+	}
+	if u.Opaque != "" {
+		buf.WriteString(u.Opaque)
+	} else {
+		if u.Scheme != "" || u.Host != "" || u.User != nil {
+			buf.WriteString("//")
+			if ui := u.User; ui != nil {
+				buf.WriteString(ui.String())
+				buf.WriteByte('@')
+			}
+			if h := u.Host; h != "" {
+				buf.WriteString(h)
+			}
+		}
+		if u.Path != "" && u.Path[0] != '/' && u.Host != "" {
+			buf.WriteByte('/')
+		}
+		buf.WriteString(escape(u.Path, encodePath))
+	}
+	if u.RawQuery != "" {
+		buf.WriteByte('?')
+		buf.WriteString(u.RawQuery)
+	}
+	if u.Fragment != "" {
+		buf.WriteByte('#')
+		buf.WriteString(escape(u.Fragment, encodeFragment))
+	}
+	return buf.String()
+}
+
+// Values maps a string key to a list of values.
+// It is typically used for query parameters and form values.
+// Unlike in the http.Header map, the keys in a Values map
+// are case-sensitive.
+type Values map[string][]string
+
+// Get gets the first value associated with the given key.
+// If there are no values associated with the key, Get returns
+// the empty string. To access multiple values, use the map
+// directly.
+func (v Values) Get(key string) string {
+	if v == nil {
+		return ""
+	}
+	vs, ok := v[key]
+	if !ok || len(vs) == 0 {
+		return ""
+	}
+	return vs[0]
+}
+
+// Set sets the key to value. It replaces any existing
+// values.
+func (v Values) Set(key, value string) {
+	v[key] = []string{value}
+}
+
+// Add adds the value to key. It appends to any existing
+// values associated with key.
+func (v Values) Add(key, value string) {
+	v[key] = append(v[key], value)
+}
+
+// Del deletes the values associated with key.
+func (v Values) Del(key string) {
+	delete(v, key)
+}
+
+// ParseQuery parses the URL-encoded query string and returns
+// a map listing the values specified for each key.
+// ParseQuery always returns a non-nil map containing all the
+// valid query parameters found; err describes the first decoding error
+// encountered, if any.
+func ParseQuery(query string) (m Values, err error) {
+	m = make(Values)
+	err = parseQuery(m, query)
+	return
+}
+
+func parseQuery(m Values, query string) (err error) {
+	for query != "" {
+		key := query
+		if i := strings.IndexAny(key, "&;"); i >= 0 {
+			key, query = key[:i], key[i+1:]
+		} else {
+			query = ""
+		}
+		if key == "" {
+			continue
+		}
+		value := ""
+		if i := strings.Index(key, "="); i >= 0 {
+			key, value = key[:i], key[i+1:]
+		}
+		key, err1 := QueryUnescape(key)
+		if err1 != nil {
+			if err == nil {
+				err = err1
+			}
+			continue
+		}
+		value, err1 = QueryUnescape(value)
+		if err1 != nil {
+			if err == nil {
+				err = err1
+			}
+			continue
+		}
+		m[key] = append(m[key], value)
+	}
+	return err
+}
+
+// Encode encodes the values into ``URL encoded'' form
+// ("bar=baz&foo=quux") sorted by key.
+func (v Values) Encode() string {
+	if v == nil {
+		return ""
+	}
+	var buf bytes.Buffer
+	keys := make([]string, 0, len(v))
+	for k := range v {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+	for _, k := range keys {
+		vs := v[k]
+		prefix := QueryEscape(k) + "="
+		for _, v := range vs {
+			if buf.Len() > 0 {
+				buf.WriteByte('&')
+			}
+			buf.WriteString(prefix)
+			buf.WriteString(QueryEscape(v))
+		}
+	}
+	return buf.String()
+}
+
+// resolvePath applies special path segments from refs and applies
+// them to base, per RFC 3986.
+func resolvePath(base, ref string) string {
+	var full string
+	if ref == "" {
+		full = base
+	} else if ref[0] != '/' {
+		i := strings.LastIndex(base, "/")
+		full = base[:i+1] + ref
+	} else {
+		full = ref
+	}
+	if full == "" {
+		return ""
+	}
+	var dst []string
+	src := strings.Split(full, "/")
+	for _, elem := range src {
+		switch elem {
+		case ".":
+			// drop
+		case "..":
+			if len(dst) > 0 {
+				dst = dst[:len(dst)-1]
+			}
+		default:
+			dst = append(dst, elem)
+		}
+	}
+	if last := src[len(src)-1]; last == "." || last == ".." {
+		// Add final slash to the joined path.
+		dst = append(dst, "")
+	}
+	return "/" + strings.TrimLeft(strings.Join(dst, "/"), "/")
+}
+
+// IsAbs returns true if the URL is absolute.
+func (u *URL) IsAbs() bool {
+	return u.Scheme != ""
+}
+
+// Parse parses a URL in the context of the receiver.  The provided URL
+// may be relative or absolute.  Parse returns nil, err on parse
+// failure, otherwise its return value is the same as ResolveReference.
+func (u *URL) Parse(ref string) (*URL, error) {
+	refurl, err := Parse(ref)
+	if err != nil {
+		return nil, err
+	}
+	return u.ResolveReference(refurl), nil
+}
+
+// ResolveReference resolves a URI reference to an absolute URI from
+// an absolute base URI, per RFC 3986 Section 5.2.  The URI reference
+// may be relative or absolute.  ResolveReference always returns a new
+// URL instance, even if the returned URL is identical to either the
+// base or reference. If ref is an absolute URL, then ResolveReference
+// ignores base and returns a copy of ref.
+func (u *URL) ResolveReference(ref *URL) *URL {
+	url := *ref
+	if ref.Scheme == "" {
+		url.Scheme = u.Scheme
+	}
+	if ref.Scheme != "" || ref.Host != "" || ref.User != nil {
+		// The "absoluteURI" or "net_path" cases.
+		url.Path = resolvePath(ref.Path, "")
+		return &url
+	}
+	if ref.Opaque != "" {
+		url.User = nil
+		url.Host = ""
+		url.Path = ""
+		return &url
+	}
+	if ref.Path == "" {
+		if ref.RawQuery == "" {
+			url.RawQuery = u.RawQuery
+			if ref.Fragment == "" {
+				url.Fragment = u.Fragment
+			}
+		}
+	}
+	// The "abs_path" or "rel_path" cases.
+	url.Host = u.Host
+	url.User = u.User
+	url.Path = resolvePath(u.Path, ref.Path)
+	return &url
+}
+
+// Query parses RawQuery and returns the corresponding values.
+func (u *URL) Query() Values {
+	v, _ := ParseQuery(u.RawQuery)
+	return v
+}
+
+// RequestURI returns the encoded path?query or opaque?query
+// string that would be used in an HTTP request for u.
+func (u *URL) RequestURI() string {
+	result := u.Opaque
+	if result == "" {
+		result = escape(u.Path, encodePath)
+		if result == "" {
+			result = "/"
+		}
+	} else {
+		if strings.HasPrefix(result, "//") {
+			result = u.Scheme + ":" + result
+		}
+	}
+	if u.RawQuery != "" {
+		result += "?" + u.RawQuery
+	}
+	return result
+}
diff --git a/third_party/gofrontend/libgo/go/net/url/url_test.go b/third_party/gofrontend/libgo/go/net/url/url_test.go
new file mode 100644
index 0000000..cad758f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/url/url_test.go
@@ -0,0 +1,905 @@
+// 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 url
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+type URLTest struct {
+	in        string
+	out       *URL
+	roundtrip string // expected result of reserializing the URL; empty means same as "in".
+}
+
+var urltests = []URLTest{
+	// no path
+	{
+		"http://www.google.com",
+		&URL{
+			Scheme: "http",
+			Host:   "www.google.com",
+		},
+		"",
+	},
+	// path
+	{
+		"http://www.google.com/",
+		&URL{
+			Scheme: "http",
+			Host:   "www.google.com",
+			Path:   "/",
+		},
+		"",
+	},
+	// path with hex escaping
+	{
+		"http://www.google.com/file%20one%26two",
+		&URL{
+			Scheme: "http",
+			Host:   "www.google.com",
+			Path:   "/file one&two",
+		},
+		"http://www.google.com/file%20one&two",
+	},
+	// user
+	{
+		"ftp://webmaster@www.google.com/",
+		&URL{
+			Scheme: "ftp",
+			User:   User("webmaster"),
+			Host:   "www.google.com",
+			Path:   "/",
+		},
+		"",
+	},
+	// escape sequence in username
+	{
+		"ftp://john%20doe@www.google.com/",
+		&URL{
+			Scheme: "ftp",
+			User:   User("john doe"),
+			Host:   "www.google.com",
+			Path:   "/",
+		},
+		"ftp://john%20doe@www.google.com/",
+	},
+	// query
+	{
+		"http://www.google.com/?q=go+language",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/",
+			RawQuery: "q=go+language",
+		},
+		"",
+	},
+	// query with hex escaping: NOT parsed
+	{
+		"http://www.google.com/?q=go%20language",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/",
+			RawQuery: "q=go%20language",
+		},
+		"",
+	},
+	// %20 outside query
+	{
+		"http://www.google.com/a%20b?q=c+d",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/a b",
+			RawQuery: "q=c+d",
+		},
+		"",
+	},
+	// path without leading /, so no parsing
+	{
+		"http:www.google.com/?q=go+language",
+		&URL{
+			Scheme:   "http",
+			Opaque:   "www.google.com/",
+			RawQuery: "q=go+language",
+		},
+		"http:www.google.com/?q=go+language",
+	},
+	// path without leading /, so no parsing
+	{
+		"http:%2f%2fwww.google.com/?q=go+language",
+		&URL{
+			Scheme:   "http",
+			Opaque:   "%2f%2fwww.google.com/",
+			RawQuery: "q=go+language",
+		},
+		"http:%2f%2fwww.google.com/?q=go+language",
+	},
+	// non-authority with path
+	{
+		"mailto:/webmaster@golang.org",
+		&URL{
+			Scheme: "mailto",
+			Path:   "/webmaster@golang.org",
+		},
+		"mailto:///webmaster@golang.org", // unfortunate compromise
+	},
+	// non-authority
+	{
+		"mailto:webmaster@golang.org",
+		&URL{
+			Scheme: "mailto",
+			Opaque: "webmaster@golang.org",
+		},
+		"",
+	},
+	// unescaped :// in query should not create a scheme
+	{
+		"/foo?query=http://bad",
+		&URL{
+			Path:     "/foo",
+			RawQuery: "query=http://bad",
+		},
+		"",
+	},
+	// leading // without scheme should create an authority
+	{
+		"//foo",
+		&URL{
+			Host: "foo",
+		},
+		"",
+	},
+	// leading // without scheme, with userinfo, path, and query
+	{
+		"//user@foo/path?a=b",
+		&URL{
+			User:     User("user"),
+			Host:     "foo",
+			Path:     "/path",
+			RawQuery: "a=b",
+		},
+		"",
+	},
+	// Three leading slashes isn't an authority, but doesn't return an error.
+	// (We can't return an error, as this code is also used via
+	// ServeHTTP -> ReadRequest -> Parse, which is arguably a
+	// different URL parsing context, but currently shares the
+	// same codepath)
+	{
+		"///threeslashes",
+		&URL{
+			Path: "///threeslashes",
+		},
+		"",
+	},
+	{
+		"http://user:password@google.com",
+		&URL{
+			Scheme: "http",
+			User:   UserPassword("user", "password"),
+			Host:   "google.com",
+		},
+		"http://user:password@google.com",
+	},
+	// unescaped @ in username should not confuse host
+	{
+		"http://j@ne:password@google.com",
+		&URL{
+			Scheme: "http",
+			User:   UserPassword("j@ne", "password"),
+			Host:   "google.com",
+		},
+		"http://j%40ne:password@google.com",
+	},
+	// unescaped @ in password should not confuse host
+	{
+		"http://jane:p@ssword@google.com",
+		&URL{
+			Scheme: "http",
+			User:   UserPassword("jane", "p@ssword"),
+			Host:   "google.com",
+		},
+		"http://jane:p%40ssword@google.com",
+	},
+	{
+		"http://j@ne:password@google.com/p@th?q=@go",
+		&URL{
+			Scheme:   "http",
+			User:     UserPassword("j@ne", "password"),
+			Host:     "google.com",
+			Path:     "/p@th",
+			RawQuery: "q=@go",
+		},
+		"http://j%40ne:password@google.com/p@th?q=@go",
+	},
+	{
+		"http://www.google.com/?q=go+language#foo",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/",
+			RawQuery: "q=go+language",
+			Fragment: "foo",
+		},
+		"",
+	},
+	{
+		"http://www.google.com/?q=go+language#foo%26bar",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/",
+			RawQuery: "q=go+language",
+			Fragment: "foo&bar",
+		},
+		"http://www.google.com/?q=go+language#foo&bar",
+	},
+	{
+		"file:///home/adg/rabbits",
+		&URL{
+			Scheme: "file",
+			Host:   "",
+			Path:   "/home/adg/rabbits",
+		},
+		"file:///home/adg/rabbits",
+	},
+	// "Windows" paths are no exception to the rule.
+	// See golang.org/issue/6027, especially comment #9.
+	{
+		"file:///C:/FooBar/Baz.txt",
+		&URL{
+			Scheme: "file",
+			Host:   "",
+			Path:   "/C:/FooBar/Baz.txt",
+		},
+		"file:///C:/FooBar/Baz.txt",
+	},
+	// case-insensitive scheme
+	{
+		"MaIlTo:webmaster@golang.org",
+		&URL{
+			Scheme: "mailto",
+			Opaque: "webmaster@golang.org",
+		},
+		"mailto:webmaster@golang.org",
+	},
+	// Relative path
+	{
+		"a/b/c",
+		&URL{
+			Path: "a/b/c",
+		},
+		"a/b/c",
+	},
+}
+
+// more useful string for debugging than fmt's struct printer
+func ufmt(u *URL) string {
+	var user, pass interface{}
+	if u.User != nil {
+		user = u.User.Username()
+		if p, ok := u.User.Password(); ok {
+			pass = p
+		}
+	}
+	return fmt.Sprintf("opaque=%q, scheme=%q, user=%#v, pass=%#v, host=%q, path=%q, rawq=%q, frag=%q",
+		u.Opaque, u.Scheme, user, pass, u.Host, u.Path, u.RawQuery, u.Fragment)
+}
+
+func DoTest(t *testing.T, parse func(string) (*URL, error), name string, tests []URLTest) {
+	for _, tt := range tests {
+		u, err := parse(tt.in)
+		if err != nil {
+			t.Errorf("%s(%q) returned error %s", name, tt.in, err)
+			continue
+		}
+		if !reflect.DeepEqual(u, tt.out) {
+			t.Errorf("%s(%q):\n\thave %v\n\twant %v\n",
+				name, tt.in, ufmt(u), ufmt(tt.out))
+		}
+	}
+}
+
+func BenchmarkString(b *testing.B) {
+	b.StopTimer()
+	b.ReportAllocs()
+	for _, tt := range urltests {
+		u, err := Parse(tt.in)
+		if err != nil {
+			b.Errorf("Parse(%q) returned error %s", tt.in, err)
+			continue
+		}
+		if tt.roundtrip == "" {
+			continue
+		}
+		b.StartTimer()
+		var g string
+		for i := 0; i < b.N; i++ {
+			g = u.String()
+		}
+		b.StopTimer()
+		if w := tt.roundtrip; g != w {
+			b.Errorf("Parse(%q).String() == %q, want %q", tt.in, g, w)
+		}
+	}
+}
+
+func TestParse(t *testing.T) {
+	DoTest(t, Parse, "Parse", urltests)
+}
+
+const pathThatLooksSchemeRelative = "//not.a.user@not.a.host/just/a/path"
+
+var parseRequestURLTests = []struct {
+	url           string
+	expectedValid bool
+}{
+	{"http://foo.com", true},
+	{"http://foo.com/", true},
+	{"http://foo.com/path", true},
+	{"/", true},
+	{pathThatLooksSchemeRelative, true},
+	{"//not.a.user@%66%6f%6f.com/just/a/path/also", true},
+	{"foo.html", false},
+	{"../dir/", false},
+	{"*", true},
+}
+
+func TestParseRequestURI(t *testing.T) {
+	for _, test := range parseRequestURLTests {
+		_, err := ParseRequestURI(test.url)
+		valid := err == nil
+		if valid != test.expectedValid {
+			t.Errorf("Expected valid=%v for %q; got %v", test.expectedValid, test.url, valid)
+		}
+	}
+
+	url, err := ParseRequestURI(pathThatLooksSchemeRelative)
+	if err != nil {
+		t.Fatalf("Unexpected error %v", err)
+	}
+	if url.Path != pathThatLooksSchemeRelative {
+		t.Errorf("Expected path %q; got %q", pathThatLooksSchemeRelative, url.Path)
+	}
+}
+
+func DoTestString(t *testing.T, parse func(string) (*URL, error), name string, tests []URLTest) {
+	for _, tt := range tests {
+		u, err := parse(tt.in)
+		if err != nil {
+			t.Errorf("%s(%q) returned error %s", name, tt.in, err)
+			continue
+		}
+		expected := tt.in
+		if len(tt.roundtrip) > 0 {
+			expected = tt.roundtrip
+		}
+		s := u.String()
+		if s != expected {
+			t.Errorf("%s(%q).String() == %q (expected %q)", name, tt.in, s, expected)
+		}
+	}
+}
+
+func TestURLString(t *testing.T) {
+	DoTestString(t, Parse, "Parse", urltests)
+
+	// no leading slash on path should prepend
+	// slash on String() call
+	noslash := URLTest{
+		"http://www.google.com/search",
+		&URL{
+			Scheme: "http",
+			Host:   "www.google.com",
+			Path:   "search",
+		},
+		"",
+	}
+	s := noslash.out.String()
+	if s != noslash.in {
+		t.Errorf("Expected %s; go %s", noslash.in, s)
+	}
+}
+
+type EscapeTest struct {
+	in  string
+	out string
+	err error
+}
+
+var unescapeTests = []EscapeTest{
+	{
+		"",
+		"",
+		nil,
+	},
+	{
+		"abc",
+		"abc",
+		nil,
+	},
+	{
+		"1%41",
+		"1A",
+		nil,
+	},
+	{
+		"1%41%42%43",
+		"1ABC",
+		nil,
+	},
+	{
+		"%4a",
+		"J",
+		nil,
+	},
+	{
+		"%6F",
+		"o",
+		nil,
+	},
+	{
+		"%", // not enough characters after %
+		"",
+		EscapeError("%"),
+	},
+	{
+		"%a", // not enough characters after %
+		"",
+		EscapeError("%a"),
+	},
+	{
+		"%1", // not enough characters after %
+		"",
+		EscapeError("%1"),
+	},
+	{
+		"123%45%6", // not enough characters after %
+		"",
+		EscapeError("%6"),
+	},
+	{
+		"%zzzzz", // invalid hex digits
+		"",
+		EscapeError("%zz"),
+	},
+}
+
+func TestUnescape(t *testing.T) {
+	for _, tt := range unescapeTests {
+		actual, err := QueryUnescape(tt.in)
+		if actual != tt.out || (err != nil) != (tt.err != nil) {
+			t.Errorf("QueryUnescape(%q) = %q, %s; want %q, %s", tt.in, actual, err, tt.out, tt.err)
+		}
+	}
+}
+
+var escapeTests = []EscapeTest{
+	{
+		"",
+		"",
+		nil,
+	},
+	{
+		"abc",
+		"abc",
+		nil,
+	},
+	{
+		"one two",
+		"one+two",
+		nil,
+	},
+	{
+		"10%",
+		"10%25",
+		nil,
+	},
+	{
+		" ?&=#+%!<>#\"{}|\\^[]`☺\t:/@$'()*,;",
+		"+%3F%26%3D%23%2B%25%21%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09%3A%2F%40%24%27%28%29%2A%2C%3B",
+		nil,
+	},
+}
+
+func TestEscape(t *testing.T) {
+	for _, tt := range escapeTests {
+		actual := QueryEscape(tt.in)
+		if tt.out != actual {
+			t.Errorf("QueryEscape(%q) = %q, want %q", tt.in, actual, tt.out)
+		}
+
+		// for bonus points, verify that escape:unescape is an identity.
+		roundtrip, err := QueryUnescape(actual)
+		if roundtrip != tt.in || err != nil {
+			t.Errorf("QueryUnescape(%q) = %q, %s; want %q, %s", actual, roundtrip, err, tt.in, "[no error]")
+		}
+	}
+}
+
+//var userinfoTests = []UserinfoTest{
+//	{"user", "password", "user:password"},
+//	{"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./",
+//		"foo%3Abar:~!%40%23$%25%5E&*()_+%7B%7D%7C%5B%5D%5C-=%60%3A;'%22%3C%3E?,.%2F"},
+//}
+
+type EncodeQueryTest struct {
+	m        Values
+	expected string
+}
+
+var encodeQueryTests = []EncodeQueryTest{
+	{nil, ""},
+	{Values{"q": {"puppies"}, "oe": {"utf8"}}, "oe=utf8&q=puppies"},
+	{Values{"q": {"dogs", "&", "7"}}, "q=dogs&q=%26&q=7"},
+	{Values{
+		"a": {"a1", "a2", "a3"},
+		"b": {"b1", "b2", "b3"},
+		"c": {"c1", "c2", "c3"},
+	}, "a=a1&a=a2&a=a3&b=b1&b=b2&b=b3&c=c1&c=c2&c=c3"},
+}
+
+func TestEncodeQuery(t *testing.T) {
+	for _, tt := range encodeQueryTests {
+		if q := tt.m.Encode(); q != tt.expected {
+			t.Errorf(`EncodeQuery(%+v) = %q, want %q`, tt.m, q, tt.expected)
+		}
+	}
+}
+
+var resolvePathTests = []struct {
+	base, ref, expected string
+}{
+	{"a/b", ".", "/a/"},
+	{"a/b", "c", "/a/c"},
+	{"a/b", "..", "/"},
+	{"a/", "..", "/"},
+	{"a/", "../..", "/"},
+	{"a/b/c", "..", "/a/"},
+	{"a/b/c", "../d", "/a/d"},
+	{"a/b/c", ".././d", "/a/d"},
+	{"a/b", "./..", "/"},
+	{"a/./b", ".", "/a/"},
+	{"a/../", ".", "/"},
+	{"a/.././b", "c", "/c"},
+}
+
+func TestResolvePath(t *testing.T) {
+	for _, test := range resolvePathTests {
+		got := resolvePath(test.base, test.ref)
+		if got != test.expected {
+			t.Errorf("For %q + %q got %q; expected %q", test.base, test.ref, got, test.expected)
+		}
+	}
+}
+
+var resolveReferenceTests = []struct {
+	base, rel, expected string
+}{
+	// Absolute URL references
+	{"http://foo.com?a=b", "https://bar.com/", "https://bar.com/"},
+	{"http://foo.com/", "https://bar.com/?a=b", "https://bar.com/?a=b"},
+	{"http://foo.com/bar", "mailto:foo@example.com", "mailto:foo@example.com"},
+
+	// Path-absolute references
+	{"http://foo.com/bar", "/baz", "http://foo.com/baz"},
+	{"http://foo.com/bar?a=b#f", "/baz", "http://foo.com/baz"},
+	{"http://foo.com/bar?a=b", "/baz?c=d", "http://foo.com/baz?c=d"},
+
+	// Scheme-relative
+	{"https://foo.com/bar?a=b", "//bar.com/quux", "https://bar.com/quux"},
+
+	// Path-relative references:
+
+	// ... current directory
+	{"http://foo.com", ".", "http://foo.com/"},
+	{"http://foo.com/bar", ".", "http://foo.com/"},
+	{"http://foo.com/bar/", ".", "http://foo.com/bar/"},
+
+	// ... going down
+	{"http://foo.com", "bar", "http://foo.com/bar"},
+	{"http://foo.com/", "bar", "http://foo.com/bar"},
+	{"http://foo.com/bar/baz", "quux", "http://foo.com/bar/quux"},
+
+	// ... going up
+	{"http://foo.com/bar/baz", "../quux", "http://foo.com/quux"},
+	{"http://foo.com/bar/baz", "../../../../../quux", "http://foo.com/quux"},
+	{"http://foo.com/bar", "..", "http://foo.com/"},
+	{"http://foo.com/bar/baz", "./..", "http://foo.com/"},
+	// ".." in the middle (issue 3560)
+	{"http://foo.com/bar/baz", "quux/dotdot/../tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/../tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/.././tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/./../tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/dotdot/././../../tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/dotdot/./.././../tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/dotdot/dotdot/./../../.././././tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/../dotdot/../dot/./tail/..", "http://foo.com/bar/quux/dot/"},
+
+	// Remove any dot-segments prior to forming the target URI.
+	// http://tools.ietf.org/html/rfc3986#section-5.2.4
+	{"http://foo.com/dot/./dotdot/../foo/bar", "../baz", "http://foo.com/dot/baz"},
+
+	// Triple dot isn't special
+	{"http://foo.com/bar", "...", "http://foo.com/..."},
+
+	// Fragment
+	{"http://foo.com/bar", ".#frag", "http://foo.com/#frag"},
+
+	// RFC 3986: Normal Examples
+	// http://tools.ietf.org/html/rfc3986#section-5.4.1
+	{"http://a/b/c/d;p?q", "g:h", "g:h"},
+	{"http://a/b/c/d;p?q", "g", "http://a/b/c/g"},
+	{"http://a/b/c/d;p?q", "./g", "http://a/b/c/g"},
+	{"http://a/b/c/d;p?q", "g/", "http://a/b/c/g/"},
+	{"http://a/b/c/d;p?q", "/g", "http://a/g"},
+	{"http://a/b/c/d;p?q", "//g", "http://g"},
+	{"http://a/b/c/d;p?q", "?y", "http://a/b/c/d;p?y"},
+	{"http://a/b/c/d;p?q", "g?y", "http://a/b/c/g?y"},
+	{"http://a/b/c/d;p?q", "#s", "http://a/b/c/d;p?q#s"},
+	{"http://a/b/c/d;p?q", "g#s", "http://a/b/c/g#s"},
+	{"http://a/b/c/d;p?q", "g?y#s", "http://a/b/c/g?y#s"},
+	{"http://a/b/c/d;p?q", ";x", "http://a/b/c/;x"},
+	{"http://a/b/c/d;p?q", "g;x", "http://a/b/c/g;x"},
+	{"http://a/b/c/d;p?q", "g;x?y#s", "http://a/b/c/g;x?y#s"},
+	{"http://a/b/c/d;p?q", "", "http://a/b/c/d;p?q"},
+	{"http://a/b/c/d;p?q", ".", "http://a/b/c/"},
+	{"http://a/b/c/d;p?q", "./", "http://a/b/c/"},
+	{"http://a/b/c/d;p?q", "..", "http://a/b/"},
+	{"http://a/b/c/d;p?q", "../", "http://a/b/"},
+	{"http://a/b/c/d;p?q", "../g", "http://a/b/g"},
+	{"http://a/b/c/d;p?q", "../..", "http://a/"},
+	{"http://a/b/c/d;p?q", "../../", "http://a/"},
+	{"http://a/b/c/d;p?q", "../../g", "http://a/g"},
+
+	// RFC 3986: Abnormal Examples
+	// http://tools.ietf.org/html/rfc3986#section-5.4.2
+	{"http://a/b/c/d;p?q", "../../../g", "http://a/g"},
+	{"http://a/b/c/d;p?q", "../../../../g", "http://a/g"},
+	{"http://a/b/c/d;p?q", "/./g", "http://a/g"},
+	{"http://a/b/c/d;p?q", "/../g", "http://a/g"},
+	{"http://a/b/c/d;p?q", "g.", "http://a/b/c/g."},
+	{"http://a/b/c/d;p?q", ".g", "http://a/b/c/.g"},
+	{"http://a/b/c/d;p?q", "g..", "http://a/b/c/g.."},
+	{"http://a/b/c/d;p?q", "..g", "http://a/b/c/..g"},
+	{"http://a/b/c/d;p?q", "./../g", "http://a/b/g"},
+	{"http://a/b/c/d;p?q", "./g/.", "http://a/b/c/g/"},
+	{"http://a/b/c/d;p?q", "g/./h", "http://a/b/c/g/h"},
+	{"http://a/b/c/d;p?q", "g/../h", "http://a/b/c/h"},
+	{"http://a/b/c/d;p?q", "g;x=1/./y", "http://a/b/c/g;x=1/y"},
+	{"http://a/b/c/d;p?q", "g;x=1/../y", "http://a/b/c/y"},
+	{"http://a/b/c/d;p?q", "g?y/./x", "http://a/b/c/g?y/./x"},
+	{"http://a/b/c/d;p?q", "g?y/../x", "http://a/b/c/g?y/../x"},
+	{"http://a/b/c/d;p?q", "g#s/./x", "http://a/b/c/g#s/./x"},
+	{"http://a/b/c/d;p?q", "g#s/../x", "http://a/b/c/g#s/../x"},
+
+	// Extras.
+	{"https://a/b/c/d;p?q", "//g?q", "https://g?q"},
+	{"https://a/b/c/d;p?q", "//g#s", "https://g#s"},
+	{"https://a/b/c/d;p?q", "//g/d/e/f?y#s", "https://g/d/e/f?y#s"},
+	{"https://a/b/c/d;p#s", "?y", "https://a/b/c/d;p?y"},
+	{"https://a/b/c/d;p?q#s", "?y", "https://a/b/c/d;p?y"},
+}
+
+func TestResolveReference(t *testing.T) {
+	mustParse := func(url string) *URL {
+		u, err := Parse(url)
+		if err != nil {
+			t.Fatalf("Expected URL to parse: %q, got error: %v", url, err)
+		}
+		return u
+	}
+	opaque := &URL{Scheme: "scheme", Opaque: "opaque"}
+	for _, test := range resolveReferenceTests {
+		base := mustParse(test.base)
+		rel := mustParse(test.rel)
+		url := base.ResolveReference(rel)
+		if url.String() != test.expected {
+			t.Errorf("URL(%q).ResolveReference(%q) == %q, got %q", test.base, test.rel, test.expected, url.String())
+		}
+		// Ensure that new instances are returned.
+		if base == url {
+			t.Errorf("Expected URL.ResolveReference to return new URL instance.")
+		}
+		// Test the convenience wrapper too.
+		url, err := base.Parse(test.rel)
+		if err != nil {
+			t.Errorf("URL(%q).Parse(%q) failed: %v", test.base, test.rel, err)
+		} else if url.String() != test.expected {
+			t.Errorf("URL(%q).Parse(%q) == %q, got %q", test.base, test.rel, test.expected, url.String())
+		} else if base == url {
+			// Ensure that new instances are returned for the wrapper too.
+			t.Errorf("Expected URL.Parse to return new URL instance.")
+		}
+		// Ensure Opaque resets the URL.
+		url = base.ResolveReference(opaque)
+		if *url != *opaque {
+			t.Errorf("ResolveReference failed to resolve opaque URL: want %#v, got %#v", url, opaque)
+		}
+		// Test the convenience wrapper with an opaque URL too.
+		url, err = base.Parse("scheme:opaque")
+		if err != nil {
+			t.Errorf(`URL(%q).Parse("scheme:opaque") failed: %v`, test.base, err)
+		} else if *url != *opaque {
+			t.Errorf("Parse failed to resolve opaque URL: want %#v, got %#v", url, opaque)
+		} else if base == url {
+			// Ensure that new instances are returned, again.
+			t.Errorf("Expected URL.Parse to return new URL instance.")
+		}
+	}
+}
+
+func TestQueryValues(t *testing.T) {
+	u, _ := Parse("http://x.com?foo=bar&bar=1&bar=2")
+	v := u.Query()
+	if len(v) != 2 {
+		t.Errorf("got %d keys in Query values, want 2", len(v))
+	}
+	if g, e := v.Get("foo"), "bar"; g != e {
+		t.Errorf("Get(foo) = %q, want %q", g, e)
+	}
+	// Case sensitive:
+	if g, e := v.Get("Foo"), ""; g != e {
+		t.Errorf("Get(Foo) = %q, want %q", g, e)
+	}
+	if g, e := v.Get("bar"), "1"; g != e {
+		t.Errorf("Get(bar) = %q, want %q", g, e)
+	}
+	if g, e := v.Get("baz"), ""; g != e {
+		t.Errorf("Get(baz) = %q, want %q", g, e)
+	}
+	v.Del("bar")
+	if g, e := v.Get("bar"), ""; g != e {
+		t.Errorf("second Get(bar) = %q, want %q", g, e)
+	}
+}
+
+type parseTest struct {
+	query string
+	out   Values
+}
+
+var parseTests = []parseTest{
+	{
+		query: "a=1&b=2",
+		out:   Values{"a": []string{"1"}, "b": []string{"2"}},
+	},
+	{
+		query: "a=1&a=2&a=banana",
+		out:   Values{"a": []string{"1", "2", "banana"}},
+	},
+	{
+		query: "ascii=%3Ckey%3A+0x90%3E",
+		out:   Values{"ascii": []string{"<key: 0x90>"}},
+	},
+	{
+		query: "a=1;b=2",
+		out:   Values{"a": []string{"1"}, "b": []string{"2"}},
+	},
+	{
+		query: "a=1&a=2;a=banana",
+		out:   Values{"a": []string{"1", "2", "banana"}},
+	},
+}
+
+func TestParseQuery(t *testing.T) {
+	for i, test := range parseTests {
+		form, err := ParseQuery(test.query)
+		if err != nil {
+			t.Errorf("test %d: Unexpected error: %v", i, err)
+			continue
+		}
+		if len(form) != len(test.out) {
+			t.Errorf("test %d: len(form) = %d, want %d", i, len(form), len(test.out))
+		}
+		for k, evs := range test.out {
+			vs, ok := form[k]
+			if !ok {
+				t.Errorf("test %d: Missing key %q", i, k)
+				continue
+			}
+			if len(vs) != len(evs) {
+				t.Errorf("test %d: len(form[%q]) = %d, want %d", i, k, len(vs), len(evs))
+				continue
+			}
+			for j, ev := range evs {
+				if v := vs[j]; v != ev {
+					t.Errorf("test %d: form[%q][%d] = %q, want %q", i, k, j, v, ev)
+				}
+			}
+		}
+	}
+}
+
+type RequestURITest struct {
+	url *URL
+	out string
+}
+
+var requritests = []RequestURITest{
+	{
+		&URL{
+			Scheme: "http",
+			Host:   "example.com",
+			Path:   "",
+		},
+		"/",
+	},
+	{
+		&URL{
+			Scheme: "http",
+			Host:   "example.com",
+			Path:   "/a b",
+		},
+		"/a%20b",
+	},
+	// golang.org/issue/4860 variant 1
+	{
+		&URL{
+			Scheme: "http",
+			Host:   "example.com",
+			Opaque: "/%2F/%2F/",
+		},
+		"/%2F/%2F/",
+	},
+	// golang.org/issue/4860 variant 2
+	{
+		&URL{
+			Scheme: "http",
+			Host:   "example.com",
+			Opaque: "//other.example.com/%2F/%2F/",
+		},
+		"http://other.example.com/%2F/%2F/",
+	},
+	{
+		&URL{
+			Scheme:   "http",
+			Host:     "example.com",
+			Path:     "/a b",
+			RawQuery: "q=go+language",
+		},
+		"/a%20b?q=go+language",
+	},
+	{
+		&URL{
+			Scheme: "myschema",
+			Opaque: "opaque",
+		},
+		"opaque",
+	},
+	{
+		&URL{
+			Scheme:   "myschema",
+			Opaque:   "opaque",
+			RawQuery: "q=go+language",
+		},
+		"opaque?q=go+language",
+	},
+}
+
+func TestRequestURI(t *testing.T) {
+	for _, tt := range requritests {
+		s := tt.url.RequestURI()
+		if s != tt.out {
+			t.Errorf("%#v.RequestURI() == %q (expected %q)", tt.url, s, tt.out)
+		}
+	}
+}
+
+func TestParseFailure(t *testing.T) {
+	// Test that the first parse error is returned.
+	const url = "%gh&%ij"
+	_, err := ParseQuery(url)
+	errStr := fmt.Sprint(err)
+	if !strings.Contains(errStr, "%gh") {
+		t.Errorf(`ParseQuery(%q) returned error %q, want something containing %q"`, url, errStr, "%gh")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/net/z_last_test.go b/third_party/gofrontend/libgo/go/net/z_last_test.go
new file mode 100644
index 0000000..4f6a54a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/net/z_last_test.go
@@ -0,0 +1,37 @@
+// 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 net
+
+import (
+	"flag"
+	"fmt"
+	"testing"
+)
+
+var testDNSFlood = flag.Bool("dnsflood", false, "whether to test dns query flooding")
+
+func TestDNSThreadLimit(t *testing.T) {
+	if !*testDNSFlood {
+		t.Skip("test disabled; use -dnsflood to enable")
+	}
+
+	const N = 10000
+	c := make(chan int, N)
+	for i := 0; i < N; i++ {
+		go func(i int) {
+			LookupIP(fmt.Sprintf("%d.net-test.golang.org", i))
+			c <- 1
+		}(i)
+	}
+	// Don't bother waiting for the stragglers; stop at 0.9 N.
+	for i := 0; i < N*9/10; i++ {
+		if i%100 == 0 {
+			//println("TestDNSThreadLimit:", i)
+		}
+		<-c
+	}
+
+	// If we're still here, it worked.
+}
diff --git a/third_party/gofrontend/libgo/go/old/regexp/all_test.go b/third_party/gofrontend/libgo/go/old/regexp/all_test.go
new file mode 100644
index 0000000..180dac4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/old/regexp/all_test.go
@@ -0,0 +1,421 @@
+// 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 regexp
+
+import (
+	"strings"
+	"testing"
+)
+
+var good_re = []string{
+	``,
+	`.`,
+	`^.$`,
+	`a`,
+	`a*`,
+	`a+`,
+	`a?`,
+	`a|b`,
+	`a*|b*`,
+	`(a*|b)(c*|d)`,
+	`[a-z]`,
+	`[a-abc-c\-\]\[]`,
+	`[a-z]+`,
+	`[]`,
+	`[abc]`,
+	`[^1234]`,
+	`[^\n]`,
+	`\!\\`,
+}
+
+type stringError struct {
+	re  string
+	err error
+}
+
+var bad_re = []stringError{
+	{`*`, ErrBareClosure},
+	{`+`, ErrBareClosure},
+	{`?`, ErrBareClosure},
+	{`(abc`, ErrUnmatchedLpar},
+	{`abc)`, ErrUnmatchedRpar},
+	{`x[a-z`, ErrUnmatchedLbkt},
+	{`abc]`, ErrUnmatchedRbkt},
+	{`[z-a]`, ErrBadRange},
+	{`abc\`, ErrExtraneousBackslash},
+	{`a**`, ErrBadClosure},
+	{`a*+`, ErrBadClosure},
+	{`a??`, ErrBadClosure},
+	{`\x`, ErrBadBackslash},
+}
+
+func compileTest(t *testing.T, expr string, error error) *Regexp {
+	re, err := Compile(expr)
+	if err != error {
+		t.Error("compiling `", expr, "`; unexpected error: ", err.Error())
+	}
+	return re
+}
+
+func TestGoodCompile(t *testing.T) {
+	for i := 0; i < len(good_re); i++ {
+		compileTest(t, good_re[i], nil)
+	}
+}
+
+func TestBadCompile(t *testing.T) {
+	for i := 0; i < len(bad_re); i++ {
+		compileTest(t, bad_re[i].re, bad_re[i].err)
+	}
+}
+
+func matchTest(t *testing.T, test *FindTest) {
+	re := compileTest(t, test.pat, nil)
+	if re == nil {
+		return
+	}
+	m := re.MatchString(test.text)
+	if m != (len(test.matches) > 0) {
+		t.Errorf("MatchString failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+	}
+	// now try bytes
+	m = re.Match([]byte(test.text))
+	if m != (len(test.matches) > 0) {
+		t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+	}
+}
+
+func TestMatch(t *testing.T) {
+	for _, test := range findTests {
+		matchTest(t, &test)
+	}
+}
+
+func matchFunctionTest(t *testing.T, test *FindTest) {
+	m, err := MatchString(test.pat, test.text)
+	if err == nil {
+		return
+	}
+	if m != (len(test.matches) > 0) {
+		t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+	}
+}
+
+func TestMatchFunction(t *testing.T) {
+	for _, test := range findTests {
+		matchFunctionTest(t, &test)
+	}
+}
+
+type ReplaceTest struct {
+	pattern, replacement, input, output string
+}
+
+var replaceTests = []ReplaceTest{
+	// Test empty input and/or replacement, with pattern that matches the empty string.
+	{"", "", "", ""},
+	{"", "x", "", "x"},
+	{"", "", "abc", "abc"},
+	{"", "x", "abc", "xaxbxcx"},
+
+	// Test empty input and/or replacement, with pattern that does not match the empty string.
+	{"b", "", "", ""},
+	{"b", "x", "", ""},
+	{"b", "", "abc", "ac"},
+	{"b", "x", "abc", "axc"},
+	{"y", "", "", ""},
+	{"y", "x", "", ""},
+	{"y", "", "abc", "abc"},
+	{"y", "x", "abc", "abc"},
+
+	// Multibyte characters -- verify that we don't try to match in the middle
+	// of a character.
+	{"[a-c]*", "x", "\u65e5", "x\u65e5x"},
+	{"[^\u65e5]", "x", "abc\u65e5def", "xxx\u65e5xxx"},
+
+	// Start and end of a string.
+	{"^[a-c]*", "x", "abcdabc", "xdabc"},
+	{"[a-c]*$", "x", "abcdabc", "abcdx"},
+	{"^[a-c]*$", "x", "abcdabc", "abcdabc"},
+	{"^[a-c]*", "x", "abc", "x"},
+	{"[a-c]*$", "x", "abc", "x"},
+	{"^[a-c]*$", "x", "abc", "x"},
+	{"^[a-c]*", "x", "dabce", "xdabce"},
+	{"[a-c]*$", "x", "dabce", "dabcex"},
+	{"^[a-c]*$", "x", "dabce", "dabce"},
+	{"^[a-c]*", "x", "", "x"},
+	{"[a-c]*$", "x", "", "x"},
+	{"^[a-c]*$", "x", "", "x"},
+
+	{"^[a-c]+", "x", "abcdabc", "xdabc"},
+	{"[a-c]+$", "x", "abcdabc", "abcdx"},
+	{"^[a-c]+$", "x", "abcdabc", "abcdabc"},
+	{"^[a-c]+", "x", "abc", "x"},
+	{"[a-c]+$", "x", "abc", "x"},
+	{"^[a-c]+$", "x", "abc", "x"},
+	{"^[a-c]+", "x", "dabce", "dabce"},
+	{"[a-c]+$", "x", "dabce", "dabce"},
+	{"^[a-c]+$", "x", "dabce", "dabce"},
+	{"^[a-c]+", "x", "", ""},
+	{"[a-c]+$", "x", "", ""},
+	{"^[a-c]+$", "x", "", ""},
+
+	// Other cases.
+	{"abc", "def", "abcdefg", "defdefg"},
+	{"bc", "BC", "abcbcdcdedef", "aBCBCdcdedef"},
+	{"abc", "", "abcdabc", "d"},
+	{"x", "xXx", "xxxXxxx", "xXxxXxxXxXxXxxXxxXx"},
+	{"abc", "d", "", ""},
+	{"abc", "d", "abc", "d"},
+	{".+", "x", "abc", "x"},
+	{"[a-c]*", "x", "def", "xdxexfx"},
+	{"[a-c]+", "x", "abcbcdcdedef", "xdxdedef"},
+	{"[a-c]*", "x", "abcbcdcdedef", "xdxdxexdxexfx"},
+}
+
+type ReplaceFuncTest struct {
+	pattern       string
+	replacement   func(string) string
+	input, output string
+}
+
+var replaceFuncTests = []ReplaceFuncTest{
+	{"[a-c]", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxayxbyxcydef"},
+	{"[a-c]+", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxabcydef"},
+	{"[a-c]*", func(s string) string { return "x" + s + "y" }, "defabcdef", "xydxyexyfxabcydxyexyfxy"},
+}
+
+func TestReplaceAll(t *testing.T) {
+	for _, tc := range replaceTests {
+		re, err := Compile(tc.pattern)
+		if err != nil {
+			t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
+			continue
+		}
+		actual := re.ReplaceAllString(tc.input, tc.replacement)
+		if actual != tc.output {
+			t.Errorf("%q.Replace(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+		// now try bytes
+		actual = string(re.ReplaceAll([]byte(tc.input), []byte(tc.replacement)))
+		if actual != tc.output {
+			t.Errorf("%q.Replace(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+	}
+}
+
+func TestReplaceAllFunc(t *testing.T) {
+	for _, tc := range replaceFuncTests {
+		re, err := Compile(tc.pattern)
+		if err != nil {
+			t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
+			continue
+		}
+		actual := re.ReplaceAllStringFunc(tc.input, tc.replacement)
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+		// now try bytes
+		actual = string(re.ReplaceAllFunc([]byte(tc.input), func(s []byte) []byte { return []byte(tc.replacement(string(s))) }))
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+	}
+}
+
+type MetaTest struct {
+	pattern, output, literal string
+	isLiteral                bool
+}
+
+var metaTests = []MetaTest{
+	{``, ``, ``, true},
+	{`foo`, `foo`, `foo`, true},
+	{`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
+	{`foo.\$`, `foo\.\\\$`, `foo`, false},     // has escaped operators and real operators
+	{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]}\\\|,<\.>/\?~`, `!@#`, false},
+}
+
+func TestQuoteMeta(t *testing.T) {
+	for _, tc := range metaTests {
+		// Verify that QuoteMeta returns the expected string.
+		quoted := QuoteMeta(tc.pattern)
+		if quoted != tc.output {
+			t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`",
+				tc.pattern, quoted, tc.output)
+			continue
+		}
+
+		// Verify that the quoted string is in fact treated as expected
+		// by Compile -- i.e. that it matches the original, unquoted string.
+		if tc.pattern != "" {
+			re, err := Compile(quoted)
+			if err != nil {
+				t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err)
+				continue
+			}
+			src := "abc" + tc.pattern + "def"
+			repl := "xyz"
+			replaced := re.ReplaceAllString(src, repl)
+			expected := "abcxyzdef"
+			if replaced != expected {
+				t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`",
+					tc.pattern, src, repl, replaced, expected)
+			}
+		}
+	}
+}
+
+func TestLiteralPrefix(t *testing.T) {
+	for _, tc := range metaTests {
+		// Literal method needs to scan the pattern.
+		re := MustCompile(tc.pattern)
+		str, complete := re.LiteralPrefix()
+		if complete != tc.isLiteral {
+			t.Errorf("LiteralPrefix(`%s`) = %t; want %t", tc.pattern, complete, tc.isLiteral)
+		}
+		if str != tc.literal {
+			t.Errorf("LiteralPrefix(`%s`) = `%s`; want `%s`", tc.pattern, str, tc.literal)
+		}
+	}
+}
+
+type numSubexpCase struct {
+	input    string
+	expected int
+}
+
+var numSubexpCases = []numSubexpCase{
+	{``, 0},
+	{`.*`, 0},
+	{`abba`, 0},
+	{`ab(b)a`, 1},
+	{`ab(.*)a`, 1},
+	{`(.*)ab(.*)a`, 2},
+	{`(.*)(ab)(.*)a`, 3},
+	{`(.*)((a)b)(.*)a`, 4},
+	{`(.*)(\(ab)(.*)a`, 3},
+	{`(.*)(\(a\)b)(.*)a`, 3},
+}
+
+func TestNumSubexp(t *testing.T) {
+	for _, c := range numSubexpCases {
+		re := MustCompile(c.input)
+		n := re.NumSubexp()
+		if n != c.expected {
+			t.Errorf("NumSubexp for %q returned %d, expected %d", c.input, n, c.expected)
+		}
+	}
+}
+
+func BenchmarkLiteral(b *testing.B) {
+	x := strings.Repeat("x", 50) + "y"
+	b.StopTimer()
+	re := MustCompile("y")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatal("no match!")
+		}
+	}
+}
+
+func BenchmarkNotLiteral(b *testing.B) {
+	x := strings.Repeat("x", 50) + "y"
+	b.StopTimer()
+	re := MustCompile(".y")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatal("no match!")
+		}
+	}
+}
+
+func BenchmarkMatchClass(b *testing.B) {
+	b.StopTimer()
+	x := strings.Repeat("xxxx", 20) + "w"
+	re := MustCompile("[abcdw]")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatal("no match!")
+		}
+	}
+}
+
+func BenchmarkMatchClass_InRange(b *testing.B) {
+	b.StopTimer()
+	// 'b' is between 'a' and 'c', so the charclass
+	// range checking is no help here.
+	x := strings.Repeat("bbbb", 20) + "c"
+	re := MustCompile("[ac]")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatal("no match!")
+		}
+	}
+}
+
+func BenchmarkReplaceAll(b *testing.B) {
+	x := "abcdefghijklmnopqrstuvwxyz"
+	b.StopTimer()
+	re := MustCompile("[cjrw]")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.ReplaceAllString(x, "")
+	}
+}
+
+func BenchmarkAnchoredLiteralShortNonMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	re := MustCompile("^zbc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkAnchoredLiteralLongNonMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	for i := 0; i < 15; i++ {
+		x = append(x, x...)
+	}
+	re := MustCompile("^zbc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkAnchoredShortMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	re := MustCompile("^.bc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkAnchoredLongMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	for i := 0; i < 15; i++ {
+		x = append(x, x...)
+	}
+	re := MustCompile("^.bc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/old/regexp/find_test.go b/third_party/gofrontend/libgo/go/old/regexp/find_test.go
new file mode 100644
index 0000000..83b249e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/old/regexp/find_test.go
@@ -0,0 +1,472 @@
+// Copyright 2010 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 regexp
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+)
+
+// For each pattern/text pair, what is the expected output of each function?
+// We can derive the textual results from the indexed results, the non-submatch
+// results from the submatched results, the single results from the 'all' results,
+// and the byte results from the string results. Therefore the table includes
+// only the FindAllStringSubmatchIndex result.
+type FindTest struct {
+	pat     string
+	text    string
+	matches [][]int
+}
+
+func (t FindTest) String() string {
+	return fmt.Sprintf("pat: %#q text: %#q", t.pat, t.text)
+}
+
+var findTests = []FindTest{
+	{``, ``, build(1, 0, 0)},
+	{`^abcdefg`, "abcdefg", build(1, 0, 7)},
+	{`a+`, "baaab", build(1, 1, 4)},
+	{"abcd..", "abcdef", build(1, 0, 6)},
+	{`a`, "a", build(1, 0, 1)},
+	{`x`, "y", nil},
+	{`b`, "abc", build(1, 1, 2)},
+	{`.`, "a", build(1, 0, 1)},
+	{`.*`, "abcdef", build(1, 0, 6)},
+	{`^`, "abcde", build(1, 0, 0)},
+	{`$`, "abcde", build(1, 5, 5)},
+	{`^abcd$`, "abcd", build(1, 0, 4)},
+	{`^bcd'`, "abcdef", nil},
+	{`^abcd$`, "abcde", nil},
+	{`a+`, "baaab", build(1, 1, 4)},
+	{`a*`, "baaab", build(3, 0, 0, 1, 4, 5, 5)},
+	{`[a-z]+`, "abcd", build(1, 0, 4)},
+	{`[^a-z]+`, "ab1234cd", build(1, 2, 6)},
+	{`[a\-\]z]+`, "az]-bcz", build(2, 0, 4, 6, 7)},
+	{`[^\n]+`, "abcd\n", build(1, 0, 4)},
+	{`[日本語]+`, "日本語日本語", build(1, 0, 18)},
+	{`日本語+`, "日本語", build(1, 0, 9)},
+	{`日本語+`, "日本語語語語", build(1, 0, 18)},
+	{`()`, "", build(1, 0, 0, 0, 0)},
+	{`(a)`, "a", build(1, 0, 1, 0, 1)},
+	{`(.)(.)`, "日a", build(1, 0, 4, 0, 3, 3, 4)},
+	{`(.*)`, "", build(1, 0, 0, 0, 0)},
+	{`(.*)`, "abcd", build(1, 0, 4, 0, 4)},
+	{`(..)(..)`, "abcd", build(1, 0, 4, 0, 2, 2, 4)},
+	{`(([^xyz]*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 3, 4)},
+	{`((a|b|c)*(d))`, "abcd", build(1, 0, 4, 0, 4, 2, 3, 3, 4)},
+	{`(((a|b|c)*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)},
+	{`\a\b\f\n\r\t\v`, "\a\b\f\n\r\t\v", build(1, 0, 7)},
+	{`[\a\b\f\n\r\t\v]+`, "\a\b\f\n\r\t\v", build(1, 0, 7)},
+
+	{`a*(|(b))c*`, "aacc", build(1, 0, 4, 2, 2, -1, -1)},
+	{`(.*).*`, "ab", build(1, 0, 2, 0, 2)},
+	{`[.]`, ".", build(1, 0, 1)},
+	{`/$`, "/abc/", build(1, 4, 5)},
+	{`/$`, "/abc", nil},
+
+	// multiple matches
+	{`.`, "abc", build(3, 0, 1, 1, 2, 2, 3)},
+	{`(.)`, "abc", build(3, 0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 2, 3)},
+	{`.(.)`, "abcd", build(2, 0, 2, 1, 2, 2, 4, 3, 4)},
+	{`ab*`, "abbaab", build(3, 0, 3, 3, 4, 4, 6)},
+	{`a(b*)`, "abbaab", build(3, 0, 3, 1, 3, 3, 4, 4, 4, 4, 6, 5, 6)},
+
+	// fixed bugs
+	{`ab$`, "cab", build(1, 1, 3)},
+	{`axxb$`, "axxcb", nil},
+	{`data`, "daXY data", build(1, 5, 9)},
+	{`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)},
+	{`zx+`, "zzx", build(1, 1, 3)},
+
+	// can backslash-escape any punctuation
+	{`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
+		`!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
+	{`[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~]+`,
+		`!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
+	{"\\`", "`", build(1, 0, 1)},
+	{"[\\`]+", "`", build(1, 0, 1)},
+
+	// long set of matches (longer than startSize)
+	{
+		".",
+		"qwertyuiopasdfghjklzxcvbnm1234567890",
+		build(36, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
+			10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
+			20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30,
+			30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36),
+	},
+}
+
+// build is a helper to construct a [][]int by extracting n sequences from x.
+// This represents n matches with len(x)/n submatches each.
+func build(n int, x ...int) [][]int {
+	ret := make([][]int, n)
+	runLength := len(x) / n
+	j := 0
+	for i := range ret {
+		ret[i] = make([]int, runLength)
+		copy(ret[i], x[j:])
+		j += runLength
+		if j > len(x) {
+			panic("invalid build entry")
+		}
+	}
+	return ret
+}
+
+// First the simple cases.
+
+func TestFind(t *testing.T) {
+	for _, test := range findTests {
+		re := MustCompile(test.pat)
+		if re.String() != test.pat {
+			t.Errorf("String() = `%s`; should be `%s`", re.String(), test.pat)
+		}
+		result := re.Find([]byte(test.text))
+		switch {
+		case len(test.matches) == 0 && len(result) == 0:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case test.matches != nil && result != nil:
+			expect := test.text[test.matches[0][0]:test.matches[0][1]]
+			if expect != string(result) {
+				t.Errorf("expected %q got %q: %s", expect, result, test)
+			}
+		}
+	}
+}
+
+func TestFindString(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindString(test.text)
+		switch {
+		case len(test.matches) == 0 && len(result) == 0:
+			// ok
+		case test.matches == nil && result != "":
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == "":
+			// Tricky because an empty result has two meanings: no match or empty match.
+			if test.matches[0][0] != test.matches[0][1] {
+				t.Errorf("expected match; got none: %s", test)
+			}
+		case test.matches != nil && result != "":
+			expect := test.text[test.matches[0][0]:test.matches[0][1]]
+			if expect != result {
+				t.Errorf("expected %q got %q: %s", expect, result, test)
+			}
+		}
+	}
+}
+
+func testFindIndex(test *FindTest, result []int, t *testing.T) {
+	switch {
+	case len(test.matches) == 0 && len(result) == 0:
+		// ok
+	case test.matches == nil && result != nil:
+		t.Errorf("expected no match; got one: %s", test)
+	case test.matches != nil && result == nil:
+		t.Errorf("expected match; got none: %s", test)
+	case test.matches != nil && result != nil:
+		expect := test.matches[0]
+		if expect[0] != result[0] || expect[1] != result[1] {
+			t.Errorf("expected %v got %v: %s", expect, result, test)
+		}
+	}
+}
+
+func TestFindIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindIndex(&test, MustCompile(test.pat).FindIndex([]byte(test.text)), t)
+	}
+}
+
+func TestFindStringIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindIndex(&test, MustCompile(test.pat).FindStringIndex(test.text), t)
+	}
+}
+
+func TestFindReaderIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindIndex(&test, MustCompile(test.pat).FindReaderIndex(strings.NewReader(test.text)), t)
+	}
+}
+
+// Now come the simple All cases.
+
+func TestFindAll(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindAll([]byte(test.text), -1)
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case test.matches != nil && result != nil:
+			if len(test.matches) != len(result) {
+				t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+				continue
+			}
+			for k, e := range test.matches {
+				expect := test.text[e[0]:e[1]]
+				if expect != string(result[k]) {
+					t.Errorf("match %d: expected %q got %q: %s", k, expect, result[k], test)
+				}
+			}
+		}
+	}
+}
+
+func TestFindAllString(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindAllString(test.text, -1)
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case test.matches != nil && result != nil:
+			if len(test.matches) != len(result) {
+				t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+				continue
+			}
+			for k, e := range test.matches {
+				expect := test.text[e[0]:e[1]]
+				if expect != result[k] {
+					t.Errorf("expected %q got %q: %s", expect, result, test)
+				}
+			}
+		}
+	}
+}
+
+func testFindAllIndex(test *FindTest, result [][]int, t *testing.T) {
+	switch {
+	case test.matches == nil && result == nil:
+		// ok
+	case test.matches == nil && result != nil:
+		t.Errorf("expected no match; got one: %s", test)
+	case test.matches != nil && result == nil:
+		t.Errorf("expected match; got none: %s", test)
+	case test.matches != nil && result != nil:
+		if len(test.matches) != len(result) {
+			t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+			return
+		}
+		for k, e := range test.matches {
+			if e[0] != result[k][0] || e[1] != result[k][1] {
+				t.Errorf("match %d: expected %v got %v: %s", k, e, result[k], test)
+			}
+		}
+	}
+}
+
+func TestFindAllIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindAllIndex(&test, MustCompile(test.pat).FindAllIndex([]byte(test.text), -1), t)
+	}
+}
+
+func TestFindAllStringIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindAllIndex(&test, MustCompile(test.pat).FindAllStringIndex(test.text, -1), t)
+	}
+}
+
+// Now come the Submatch cases.
+
+func testSubmatchBytes(test *FindTest, n int, submatches []int, result [][]byte, t *testing.T) {
+	if len(submatches) != len(result)*2 {
+		t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
+		return
+	}
+	for k := 0; k < len(submatches); k += 2 {
+		if submatches[k] == -1 {
+			if result[k/2] != nil {
+				t.Errorf("match %d: expected nil got %q: %s", n, result, test)
+			}
+			continue
+		}
+		expect := test.text[submatches[k]:submatches[k+1]]
+		if expect != string(result[k/2]) {
+			t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
+			return
+		}
+	}
+}
+
+func TestFindSubmatch(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindSubmatch([]byte(test.text))
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case test.matches != nil && result != nil:
+			testSubmatchBytes(&test, 0, test.matches[0], result, t)
+		}
+	}
+}
+
+func testSubmatchString(test *FindTest, n int, submatches []int, result []string, t *testing.T) {
+	if len(submatches) != len(result)*2 {
+		t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
+		return
+	}
+	for k := 0; k < len(submatches); k += 2 {
+		if submatches[k] == -1 {
+			if result[k/2] != "" {
+				t.Errorf("match %d: expected nil got %q: %s", n, result, test)
+			}
+			continue
+		}
+		expect := test.text[submatches[k]:submatches[k+1]]
+		if expect != result[k/2] {
+			t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
+			return
+		}
+	}
+}
+
+func TestFindStringSubmatch(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindStringSubmatch(test.text)
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case test.matches != nil && result != nil:
+			testSubmatchString(&test, 0, test.matches[0], result, t)
+		}
+	}
+}
+
+func testSubmatchIndices(test *FindTest, n int, expect, result []int, t *testing.T) {
+	if len(expect) != len(result) {
+		t.Errorf("match %d: expected %d matches; got %d: %s", n, len(expect)/2, len(result)/2, test)
+		return
+	}
+	for k, e := range expect {
+		if e != result[k] {
+			t.Errorf("match %d: submatch error: expected %v got %v: %s", n, expect, result, test)
+		}
+	}
+}
+
+func testFindSubmatchIndex(test *FindTest, result []int, t *testing.T) {
+	switch {
+	case test.matches == nil && result == nil:
+		// ok
+	case test.matches == nil && result != nil:
+		t.Errorf("expected no match; got one: %s", test)
+	case test.matches != nil && result == nil:
+		t.Errorf("expected match; got none: %s", test)
+	case test.matches != nil && result != nil:
+		testSubmatchIndices(test, 0, test.matches[0], result, t)
+	}
+}
+
+func TestFindSubmatchIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindSubmatchIndex(&test, MustCompile(test.pat).FindSubmatchIndex([]byte(test.text)), t)
+	}
+}
+
+func TestFindStringSubmatchIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindSubmatchIndex(&test, MustCompile(test.pat).FindStringSubmatchIndex(test.text), t)
+	}
+}
+
+func TestFindReaderSubmatchIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindSubmatchIndex(&test, MustCompile(test.pat).FindReaderSubmatchIndex(strings.NewReader(test.text)), t)
+	}
+}
+
+// Now come the monster AllSubmatch cases.
+
+func TestFindAllSubmatch(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindAllSubmatch([]byte(test.text), -1)
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case len(test.matches) != len(result):
+			t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+		case test.matches != nil && result != nil:
+			for k, match := range test.matches {
+				testSubmatchBytes(&test, k, match, result[k], t)
+			}
+		}
+	}
+}
+
+func TestFindAllStringSubmatch(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindAllStringSubmatch(test.text, -1)
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case len(test.matches) != len(result):
+			t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+		case test.matches != nil && result != nil:
+			for k, match := range test.matches {
+				testSubmatchString(&test, k, match, result[k], t)
+			}
+		}
+	}
+}
+
+func testFindAllSubmatchIndex(test *FindTest, result [][]int, t *testing.T) {
+	switch {
+	case test.matches == nil && result == nil:
+		// ok
+	case test.matches == nil && result != nil:
+		t.Errorf("expected no match; got one: %s", test)
+	case test.matches != nil && result == nil:
+		t.Errorf("expected match; got none: %s", test)
+	case len(test.matches) != len(result):
+		t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+	case test.matches != nil && result != nil:
+		for k, match := range test.matches {
+			testSubmatchIndices(test, k, match, result[k], t)
+		}
+	}
+}
+
+func TestFindAllSubmatchIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllSubmatchIndex([]byte(test.text), -1), t)
+	}
+}
+
+func TestFindAllStringSubmatchIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllStringSubmatchIndex(test.text, -1), t)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/old/regexp/regexp.go b/third_party/gofrontend/libgo/go/old/regexp/regexp.go
new file mode 100644
index 0000000..d3044d0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/old/regexp/regexp.go
@@ -0,0 +1,1488 @@
+// Copyright 2010 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 regexp implements a simple regular expression library.
+//
+// The syntax of the regular expressions accepted is:
+//
+//	regexp:
+//		concatenation { '|' concatenation }
+//	concatenation:
+//		{ closure }
+//	closure:
+//		term [ '*' | '+' | '?' ]
+//	term:
+//		'^'
+//		'$'
+//		'.'
+//		character
+//		'[' [ '^' ] { character-range } ']'
+//		'(' regexp ')'
+//	character-range:
+//		character [ '-' character ]
+//
+// All characters are UTF-8-encoded code points.  Backslashes escape special
+// characters, including inside character classes.  The standard Go character
+// escapes are also recognized: \a \b \f \n \r \t \v.
+//
+// There are 16 methods of Regexp that match a regular expression and identify
+// the matched text.  Their names are matched by this regular expression:
+//
+//	Find(All)?(String)?(Submatch)?(Index)?
+//
+// If 'All' is present, the routine matches successive non-overlapping
+// matches of the entire expression.  Empty matches abutting a preceding
+// match are ignored.  The return value is a slice containing the successive
+// return values of the corresponding non-'All' routine.  These routines take
+// an extra integer argument, n; if n >= 0, the function returns at most n
+// matches/submatches.
+//
+// If 'String' is present, the argument is a string; otherwise it is a slice
+// of bytes; return values are adjusted as appropriate.
+//
+// If 'Submatch' is present, the return value is a slice identifying the
+// successive submatches of the expression.  Submatches are matches of
+// parenthesized subexpressions within the regular expression, numbered from
+// left to right in order of opening parenthesis.  Submatch 0 is the match of
+// the entire expression, submatch 1 the match of the first parenthesized
+// subexpression, and so on.
+//
+// If 'Index' is present, matches and submatches are identified by byte index
+// pairs within the input string: result[2*n:2*n+1] identifies the indexes of
+// the nth submatch.  The pair for n==0 identifies the match of the entire
+// expression.  If 'Index' is not present, the match is identified by the
+// text of the match/submatch.  If an index is negative, it means that
+// subexpression did not match any string in the input.
+//
+// There is also a subset of the methods that can be applied to text read
+// from a RuneReader:
+//
+//	MatchReader, FindReaderIndex, FindReaderSubmatchIndex
+//
+// This set may grow.  Note that regular expression matches may need to
+// examine text beyond the text returned by a match, so the methods that
+// match text from a RuneReader may read arbitrarily far into the input
+// before returning.
+//
+// (There are a few other methods that do not match this pattern.)
+//
+package regexp
+
+import (
+	"bytes"
+	"io"
+	"strings"
+	"unicode/utf8"
+)
+
+var debug = false
+
+// Error is the local type for a parsing error.
+type Error string
+
+func (e Error) Error() string {
+	return string(e)
+}
+
+// Error codes returned by failures to parse an expression.
+var (
+	ErrInternal            = Error("regexp: internal error")
+	ErrUnmatchedLpar       = Error("regexp: unmatched '('")
+	ErrUnmatchedRpar       = Error("regexp: unmatched ')'")
+	ErrUnmatchedLbkt       = Error("regexp: unmatched '['")
+	ErrUnmatchedRbkt       = Error("regexp: unmatched ']'")
+	ErrBadRange            = Error("regexp: bad range in character class")
+	ErrExtraneousBackslash = Error("regexp: extraneous backslash")
+	ErrBadClosure          = Error("regexp: repeated closure (**, ++, etc.)")
+	ErrBareClosure         = Error("regexp: closure applies to nothing")
+	ErrBadBackslash        = Error("regexp: illegal backslash escape")
+)
+
+const (
+	iStart     = iota // beginning of program
+	iEnd              // end of program: success
+	iBOT              // '^' beginning of text
+	iEOT              // '$' end of text
+	iChar             // 'a' regular character
+	iCharClass        // [a-z] character class
+	iAny              // '.' any character including newline
+	iNotNL            // [^\n] special case: any character but newline
+	iBra              // '(' parenthesized expression: 2*braNum for left, 2*braNum+1 for right
+	iAlt              // '|' alternation
+	iNop              // do nothing; makes it easy to link without patching
+)
+
+// An instruction executed by the NFA
+type instr struct {
+	kind  int    // the type of this instruction: iChar, iAny, etc.
+	index int    // used only in debugging; could be eliminated
+	next  *instr // the instruction to execute after this one
+	// Special fields valid only for some items.
+	char   rune       // iChar
+	braNum int        // iBra, iEbra
+	cclass *charClass // iCharClass
+	left   *instr     // iAlt, other branch
+}
+
+func (i *instr) print() {
+	switch i.kind {
+	case iStart:
+		print("start")
+	case iEnd:
+		print("end")
+	case iBOT:
+		print("bot")
+	case iEOT:
+		print("eot")
+	case iChar:
+		print("char ", string(i.char))
+	case iCharClass:
+		i.cclass.print()
+	case iAny:
+		print("any")
+	case iNotNL:
+		print("notnl")
+	case iBra:
+		if i.braNum&1 == 0 {
+			print("bra", i.braNum/2)
+		} else {
+			print("ebra", i.braNum/2)
+		}
+	case iAlt:
+		print("alt(", i.left.index, ")")
+	case iNop:
+		print("nop")
+	}
+}
+
+// Regexp is the representation of a compiled regular expression.
+// The public interface is entirely through methods.
+// A Regexp is safe for concurrent use by multiple goroutines.
+type Regexp struct {
+	expr        string // the original expression
+	prefix      string // initial plain text string
+	prefixBytes []byte // initial plain text bytes
+	inst        []*instr
+	start       *instr // first instruction of machine
+	prefixStart *instr // where to start if there is a prefix
+	nbra        int    // number of brackets in expression, for subexpressions
+}
+
+type charClass struct {
+	negate bool // is character class negated? ([^a-z])
+	// slice of int, stored pairwise: [a-z] is (a,z); x is (x,x):
+	ranges     []rune
+	cmin, cmax rune
+}
+
+func (cclass *charClass) print() {
+	print("charclass")
+	if cclass.negate {
+		print(" (negated)")
+	}
+	for i := 0; i < len(cclass.ranges); i += 2 {
+		l := cclass.ranges[i]
+		r := cclass.ranges[i+1]
+		if l == r {
+			print(" [", string(l), "]")
+		} else {
+			print(" [", string(l), "-", string(r), "]")
+		}
+	}
+}
+
+func (cclass *charClass) addRange(a, b rune) {
+	// range is a through b inclusive
+	cclass.ranges = append(cclass.ranges, a, b)
+	if a < cclass.cmin {
+		cclass.cmin = a
+	}
+	if b > cclass.cmax {
+		cclass.cmax = b
+	}
+}
+
+func (cclass *charClass) matches(c rune) bool {
+	if c < cclass.cmin || c > cclass.cmax {
+		return cclass.negate
+	}
+	ranges := cclass.ranges
+	for i := 0; i < len(ranges); i = i + 2 {
+		if ranges[i] <= c && c <= ranges[i+1] {
+			return !cclass.negate
+		}
+	}
+	return cclass.negate
+}
+
+func newCharClass() *instr {
+	i := &instr{kind: iCharClass}
+	i.cclass = new(charClass)
+	i.cclass.ranges = make([]rune, 0, 4)
+	i.cclass.cmin = 0x10FFFF + 1 // MaxRune + 1
+	i.cclass.cmax = -1
+	return i
+}
+
+func (re *Regexp) add(i *instr) *instr {
+	i.index = len(re.inst)
+	re.inst = append(re.inst, i)
+	return i
+}
+
+type parser struct {
+	re    *Regexp
+	nlpar int // number of unclosed lpars
+	pos   int
+	ch    rune
+}
+
+func (p *parser) error(err Error) {
+	panic(err)
+}
+
+const endOfText = -1
+
+func (p *parser) c() rune { return p.ch }
+
+func (p *parser) nextc() rune {
+	if p.pos >= len(p.re.expr) {
+		p.ch = endOfText
+	} else {
+		c, w := utf8.DecodeRuneInString(p.re.expr[p.pos:])
+		p.ch = c
+		p.pos += w
+	}
+	return p.ch
+}
+
+func newParser(re *Regexp) *parser {
+	p := new(parser)
+	p.re = re
+	p.nextc() // load p.ch
+	return p
+}
+
+func special(c rune) bool {
+	for _, r := range `\.+*?()|[]^$` {
+		if c == r {
+			return true
+		}
+	}
+	return false
+}
+
+func ispunct(c rune) bool {
+	for _, r := range "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" {
+		if c == r {
+			return true
+		}
+	}
+	return false
+}
+
+var escapes = []byte("abfnrtv")
+var escaped = []byte("\a\b\f\n\r\t\v")
+
+func escape(c rune) int {
+	for i, b := range escapes {
+		if rune(b) == c {
+			return i
+		}
+	}
+	return -1
+}
+
+func (p *parser) checkBackslash() rune {
+	c := p.c()
+	if c == '\\' {
+		c = p.nextc()
+		switch {
+		case c == endOfText:
+			p.error(ErrExtraneousBackslash)
+		case ispunct(c):
+			// c is as delivered
+		case escape(c) >= 0:
+			c = rune(escaped[escape(c)])
+		default:
+			p.error(ErrBadBackslash)
+		}
+	}
+	return c
+}
+
+func (p *parser) charClass() *instr {
+	i := newCharClass()
+	cc := i.cclass
+	if p.c() == '^' {
+		cc.negate = true
+		p.nextc()
+	}
+	left := rune(-1)
+	for {
+		switch c := p.c(); c {
+		case ']', endOfText:
+			if left >= 0 {
+				p.error(ErrBadRange)
+			}
+			// Is it [^\n]?
+			if cc.negate && len(cc.ranges) == 2 &&
+				cc.ranges[0] == '\n' && cc.ranges[1] == '\n' {
+				nl := &instr{kind: iNotNL}
+				p.re.add(nl)
+				return nl
+			}
+			// Special common case: "[a]" -> "a"
+			if !cc.negate && len(cc.ranges) == 2 && cc.ranges[0] == cc.ranges[1] {
+				c := &instr{kind: iChar, char: cc.ranges[0]}
+				p.re.add(c)
+				return c
+			}
+			p.re.add(i)
+			return i
+		case '-': // do this before backslash processing
+			p.error(ErrBadRange)
+		default:
+			c = p.checkBackslash()
+			p.nextc()
+			switch {
+			case left < 0: // first of pair
+				if p.c() == '-' { // range
+					p.nextc()
+					left = c
+				} else { // single char
+					cc.addRange(c, c)
+				}
+			case left <= c: // second of pair
+				cc.addRange(left, c)
+				left = -1
+			default:
+				p.error(ErrBadRange)
+			}
+		}
+	}
+	panic("unreachable")
+}
+
+func (p *parser) term() (start, end *instr) {
+	switch c := p.c(); c {
+	case '|', endOfText:
+		return nil, nil
+	case '*', '+', '?':
+		p.error(ErrBareClosure)
+	case ')':
+		if p.nlpar == 0 {
+			p.error(ErrUnmatchedRpar)
+		}
+		return nil, nil
+	case ']':
+		p.error(ErrUnmatchedRbkt)
+	case '^':
+		p.nextc()
+		start = p.re.add(&instr{kind: iBOT})
+		return start, start
+	case '$':
+		p.nextc()
+		start = p.re.add(&instr{kind: iEOT})
+		return start, start
+	case '.':
+		p.nextc()
+		start = p.re.add(&instr{kind: iAny})
+		return start, start
+	case '[':
+		p.nextc()
+		start = p.charClass()
+		if p.c() != ']' {
+			p.error(ErrUnmatchedLbkt)
+		}
+		p.nextc()
+		return start, start
+	case '(':
+		p.nextc()
+		p.nlpar++
+		p.re.nbra++ // increment first so first subexpr is \1
+		nbra := p.re.nbra
+		start, end = p.regexp()
+		if p.c() != ')' {
+			p.error(ErrUnmatchedLpar)
+		}
+		p.nlpar--
+		p.nextc()
+		bra := &instr{kind: iBra, braNum: 2 * nbra}
+		p.re.add(bra)
+		ebra := &instr{kind: iBra, braNum: 2*nbra + 1}
+		p.re.add(ebra)
+		if start == nil {
+			if end == nil {
+				p.error(ErrInternal)
+				return
+			}
+			start = ebra
+		} else {
+			end.next = ebra
+		}
+		bra.next = start
+		return bra, ebra
+	default:
+		c = p.checkBackslash()
+		p.nextc()
+		start = &instr{kind: iChar, char: c}
+		p.re.add(start)
+		return start, start
+	}
+	panic("unreachable")
+}
+
+func (p *parser) closure() (start, end *instr) {
+	start, end = p.term()
+	if start == nil {
+		return
+	}
+	switch p.c() {
+	case '*':
+		// (start,end)*:
+		alt := &instr{kind: iAlt}
+		p.re.add(alt)
+		end.next = alt   // after end, do alt
+		alt.left = start // alternate brach: return to start
+		start = alt      // alt becomes new (start, end)
+		end = alt
+	case '+':
+		// (start,end)+:
+		alt := &instr{kind: iAlt}
+		p.re.add(alt)
+		end.next = alt   // after end, do alt
+		alt.left = start // alternate brach: return to start
+		end = alt        // start is unchanged; end is alt
+	case '?':
+		// (start,end)?:
+		alt := &instr{kind: iAlt}
+		p.re.add(alt)
+		nop := &instr{kind: iNop}
+		p.re.add(nop)
+		alt.left = start // alternate branch is start
+		alt.next = nop   // follow on to nop
+		end.next = nop   // after end, go to nop
+		start = alt      // start is now alt
+		end = nop        // end is nop pointed to by both branches
+	default:
+		return
+	}
+	switch p.nextc() {
+	case '*', '+', '?':
+		p.error(ErrBadClosure)
+	}
+	return
+}
+
+func (p *parser) concatenation() (start, end *instr) {
+	for {
+		nstart, nend := p.closure()
+		switch {
+		case nstart == nil: // end of this concatenation
+			if start == nil { // this is the empty string
+				nop := p.re.add(&instr{kind: iNop})
+				return nop, nop
+			}
+			return
+		case start == nil: // this is first element of concatenation
+			start, end = nstart, nend
+		default:
+			end.next = nstart
+			end = nend
+		}
+	}
+	panic("unreachable")
+}
+
+func (p *parser) regexp() (start, end *instr) {
+	start, end = p.concatenation()
+	for {
+		switch p.c() {
+		default:
+			return
+		case '|':
+			p.nextc()
+			nstart, nend := p.concatenation()
+			alt := &instr{kind: iAlt}
+			p.re.add(alt)
+			alt.left = start
+			alt.next = nstart
+			nop := &instr{kind: iNop}
+			p.re.add(nop)
+			end.next = nop
+			nend.next = nop
+			start, end = alt, nop
+		}
+	}
+	panic("unreachable")
+}
+
+func unNop(i *instr) *instr {
+	for i.kind == iNop {
+		i = i.next
+	}
+	return i
+}
+
+func (re *Regexp) eliminateNops() {
+	for _, inst := range re.inst {
+		if inst.kind == iEnd {
+			continue
+		}
+		inst.next = unNop(inst.next)
+		if inst.kind == iAlt {
+			inst.left = unNop(inst.left)
+		}
+	}
+}
+
+func (re *Regexp) dump() {
+	print("prefix <", re.prefix, ">\n")
+	for _, inst := range re.inst {
+		print(inst.index, ": ")
+		inst.print()
+		if inst.kind != iEnd {
+			print(" -> ", inst.next.index)
+		}
+		print("\n")
+	}
+}
+
+func (re *Regexp) doParse() {
+	p := newParser(re)
+	start := &instr{kind: iStart}
+	re.add(start)
+	s, e := p.regexp()
+	start.next = s
+	re.start = start
+	e.next = re.add(&instr{kind: iEnd})
+
+	if debug {
+		re.dump()
+		println()
+	}
+
+	re.eliminateNops()
+	if debug {
+		re.dump()
+		println()
+	}
+	re.setPrefix()
+	if debug {
+		re.dump()
+		println()
+	}
+}
+
+// Extract regular text from the beginning of the pattern,
+// possibly after a leading iBOT.
+// That text can be used by doExecute to speed up matching.
+func (re *Regexp) setPrefix() {
+	var b []byte
+	var utf = make([]byte, utf8.UTFMax)
+	var inst *instr
+	// First instruction is start; skip that.  Also skip any initial iBOT.
+	inst = re.inst[0].next
+	for inst.kind == iBOT {
+		inst = inst.next
+	}
+Loop:
+	for ; inst.kind != iEnd; inst = inst.next {
+		// stop if this is not a char
+		if inst.kind != iChar {
+			break
+		}
+		// stop if this char can be followed by a match for an empty string,
+		// which includes closures, ^, and $.
+		switch inst.next.kind {
+		case iBOT, iEOT, iAlt:
+			break Loop
+		}
+		n := utf8.EncodeRune(utf, inst.char)
+		b = append(b, utf[0:n]...)
+	}
+	// point prefixStart instruction to first non-CHAR after prefix
+	re.prefixStart = inst
+	re.prefixBytes = b
+	re.prefix = string(b)
+}
+
+// String returns the source text used to compile the regular expression.
+func (re *Regexp) String() string {
+	return re.expr
+}
+
+// Compile parses a regular expression and returns, if successful, a Regexp
+// object that can be used to match against text.
+func Compile(str string) (regexp *Regexp, error error) {
+	regexp = new(Regexp)
+	// doParse will panic if there is a parse error.
+	defer func() {
+		if e := recover(); e != nil {
+			regexp = nil
+			error = e.(Error) // Will re-panic if error was not an Error, e.g. nil-pointer exception
+		}
+	}()
+	regexp.expr = str
+	regexp.inst = make([]*instr, 0, 10)
+	regexp.doParse()
+	return
+}
+
+// MustCompile is like Compile but panics if the expression cannot be parsed.
+// It simplifies safe initialization of global variables holding compiled regular
+// expressions.
+func MustCompile(str string) *Regexp {
+	regexp, error := Compile(str)
+	if error != nil {
+		panic(`regexp: compiling "` + str + `": ` + error.Error())
+	}
+	return regexp
+}
+
+// NumSubexp returns the number of parenthesized subexpressions in this Regexp.
+func (re *Regexp) NumSubexp() int { return re.nbra }
+
+// The match arena allows us to reduce the garbage generated by tossing
+// match vectors away as we execute.  Matches are ref counted and returned
+// to a free list when no longer active.  Increases a simple benchmark by 22X.
+type matchArena struct {
+	head  *matchVec
+	len   int // length of match vector
+	pos   int
+	atBOT bool // whether we're at beginning of text
+	atEOT bool // whether we're at end of text
+}
+
+type matchVec struct {
+	m    []int // pairs of bracketing submatches. 0th is start,end
+	ref  int
+	next *matchVec
+}
+
+func (a *matchArena) new() *matchVec {
+	if a.head == nil {
+		const N = 10
+		block := make([]matchVec, N)
+		for i := 0; i < N; i++ {
+			b := &block[i]
+			b.next = a.head
+			a.head = b
+		}
+	}
+	m := a.head
+	a.head = m.next
+	m.ref = 0
+	if m.m == nil {
+		m.m = make([]int, a.len)
+	}
+	return m
+}
+
+func (a *matchArena) free(m *matchVec) {
+	m.ref--
+	if m.ref == 0 {
+		m.next = a.head
+		a.head = m
+	}
+}
+
+func (a *matchArena) copy(m *matchVec) *matchVec {
+	m1 := a.new()
+	copy(m1.m, m.m)
+	return m1
+}
+
+func (a *matchArena) noMatch() *matchVec {
+	m := a.new()
+	for i := range m.m {
+		m.m[i] = -1 // no match seen; catches cases like "a(b)?c" on "ac"
+	}
+	m.ref = 1
+	return m
+}
+
+type state struct {
+	inst     *instr // next instruction to execute
+	prefixed bool   // this match began with a fixed prefix
+	match    *matchVec
+}
+
+// Append new state to to-do list.  Leftmost-longest wins so avoid
+// adding a state that's already active.  The matchVec will be inc-ref'ed
+// if it is assigned to a state.
+func (a *matchArena) addState(s []state, inst *instr, prefixed bool, match *matchVec) []state {
+	switch inst.kind {
+	case iBOT:
+		if a.atBOT {
+			s = a.addState(s, inst.next, prefixed, match)
+		}
+		return s
+	case iEOT:
+		if a.atEOT {
+			s = a.addState(s, inst.next, prefixed, match)
+		}
+		return s
+	case iBra:
+		match.m[inst.braNum] = a.pos
+		s = a.addState(s, inst.next, prefixed, match)
+		return s
+	}
+	l := len(s)
+	// States are inserted in order so it's sufficient to see if we have the same
+	// instruction; no need to see if existing match is earlier (it is).
+	for i := 0; i < l; i++ {
+		if s[i].inst == inst {
+			return s
+		}
+	}
+	s = append(s, state{inst, prefixed, match})
+	match.ref++
+	if inst.kind == iAlt {
+		s = a.addState(s, inst.left, prefixed, a.copy(match))
+		// give other branch a copy of this match vector
+		s = a.addState(s, inst.next, prefixed, a.copy(match))
+	}
+	return s
+}
+
+// input abstracts different representations of the input text. It provides
+// one-character lookahead.
+type input interface {
+	step(pos int) (r rune, width int) // advance one rune
+	canCheckPrefix() bool             // can we look ahead without losing info?
+	hasPrefix(re *Regexp) bool
+	index(re *Regexp, pos int) int
+}
+
+// inputString scans a string.
+type inputString struct {
+	str string
+}
+
+func newInputString(str string) *inputString {
+	return &inputString{str: str}
+}
+
+func (i *inputString) step(pos int) (rune, int) {
+	if pos < len(i.str) {
+		return utf8.DecodeRuneInString(i.str[pos:len(i.str)])
+	}
+	return endOfText, 0
+}
+
+func (i *inputString) canCheckPrefix() bool {
+	return true
+}
+
+func (i *inputString) hasPrefix(re *Regexp) bool {
+	return strings.HasPrefix(i.str, re.prefix)
+}
+
+func (i *inputString) index(re *Regexp, pos int) int {
+	return strings.Index(i.str[pos:], re.prefix)
+}
+
+// inputBytes scans a byte slice.
+type inputBytes struct {
+	str []byte
+}
+
+func newInputBytes(str []byte) *inputBytes {
+	return &inputBytes{str: str}
+}
+
+func (i *inputBytes) step(pos int) (rune, int) {
+	if pos < len(i.str) {
+		return utf8.DecodeRune(i.str[pos:len(i.str)])
+	}
+	return endOfText, 0
+}
+
+func (i *inputBytes) canCheckPrefix() bool {
+	return true
+}
+
+func (i *inputBytes) hasPrefix(re *Regexp) bool {
+	return bytes.HasPrefix(i.str, re.prefixBytes)
+}
+
+func (i *inputBytes) index(re *Regexp, pos int) int {
+	return bytes.Index(i.str[pos:], re.prefixBytes)
+}
+
+// inputReader scans a RuneReader.
+type inputReader struct {
+	r     io.RuneReader
+	atEOT bool
+	pos   int
+}
+
+func newInputReader(r io.RuneReader) *inputReader {
+	return &inputReader{r: r}
+}
+
+func (i *inputReader) step(pos int) (rune, int) {
+	if !i.atEOT && pos != i.pos {
+		return endOfText, 0
+
+	}
+	r, w, err := i.r.ReadRune()
+	if err != nil {
+		i.atEOT = true
+		return endOfText, 0
+	}
+	i.pos += w
+	return r, w
+}
+
+func (i *inputReader) canCheckPrefix() bool {
+	return false
+}
+
+func (i *inputReader) hasPrefix(re *Regexp) bool {
+	return false
+}
+
+func (i *inputReader) index(re *Regexp, pos int) int {
+	return -1
+}
+
+// Search match starting from pos bytes into the input.
+func (re *Regexp) doExecute(i input, pos int) []int {
+	var s [2][]state
+	s[0] = make([]state, 0, 10)
+	s[1] = make([]state, 0, 10)
+	in, out := 0, 1
+	var final state
+	found := false
+	anchored := re.inst[0].next.kind == iBOT
+	if anchored && pos > 0 {
+		return nil
+	}
+	// fast check for initial plain substring
+	if i.canCheckPrefix() && re.prefix != "" {
+		advance := 0
+		if anchored {
+			if !i.hasPrefix(re) {
+				return nil
+			}
+		} else {
+			advance = i.index(re, pos)
+			if advance == -1 {
+				return nil
+			}
+		}
+		pos += advance
+	}
+	// We look one character ahead so we can match $, which checks whether
+	// we are at EOT.
+	nextChar, nextWidth := i.step(pos)
+	arena := &matchArena{
+		len:   2 * (re.nbra + 1),
+		pos:   pos,
+		atBOT: pos == 0,
+		atEOT: nextChar == endOfText,
+	}
+	for c, startPos := rune(0), pos; c != endOfText; {
+		if !found && (pos == startPos || !anchored) {
+			// prime the pump if we haven't seen a match yet
+			match := arena.noMatch()
+			match.m[0] = pos
+			s[out] = arena.addState(s[out], re.start.next, false, match)
+			arena.free(match) // if addState saved it, ref was incremented
+		} else if len(s[out]) == 0 {
+			// machine has completed
+			break
+		}
+		in, out = out, in // old out state is new in state
+		// clear out old state
+		old := s[out]
+		for _, state := range old {
+			arena.free(state.match)
+		}
+		s[out] = old[0:0] // truncate state vector
+		c = nextChar
+		thisPos := pos
+		pos += nextWidth
+		nextChar, nextWidth = i.step(pos)
+		arena.atEOT = nextChar == endOfText
+		arena.atBOT = false
+		arena.pos = pos
+		for _, st := range s[in] {
+			switch st.inst.kind {
+			case iBOT:
+			case iEOT:
+			case iChar:
+				if c == st.inst.char {
+					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+				}
+			case iCharClass:
+				if st.inst.cclass.matches(c) {
+					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+				}
+			case iAny:
+				if c != endOfText {
+					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+				}
+			case iNotNL:
+				if c != endOfText && c != '\n' {
+					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+				}
+			case iBra:
+			case iAlt:
+			case iEnd:
+				// choose leftmost longest
+				if !found || // first
+					st.match.m[0] < final.match.m[0] || // leftmost
+					(st.match.m[0] == final.match.m[0] && thisPos > final.match.m[1]) { // longest
+					if final.match != nil {
+						arena.free(final.match)
+					}
+					final = st
+					final.match.ref++
+					final.match.m[1] = thisPos
+				}
+				found = true
+			default:
+				st.inst.print()
+				panic("unknown instruction in execute")
+			}
+		}
+	}
+	if final.match == nil {
+		return nil
+	}
+	// if match found, back up start of match by width of prefix.
+	if final.prefixed && len(final.match.m) > 0 {
+		final.match.m[0] -= len(re.prefix)
+	}
+	return final.match.m
+}
+
+// LiteralPrefix returns a literal string that must begin any match
+// of the regular expression re.  It returns the boolean true if the
+// literal string comprises the entire regular expression.
+func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
+	c := make([]rune, len(re.inst)-2) // minus start and end.
+	// First instruction is start; skip that.
+	i := 0
+	for inst := re.inst[0].next; inst.kind != iEnd; inst = inst.next {
+		// stop if this is not a char
+		if inst.kind != iChar {
+			return string(c[:i]), false
+		}
+		c[i] = inst.char
+		i++
+	}
+	return string(c[:i]), true
+}
+
+// MatchReader returns whether the Regexp matches the text read by the
+// RuneReader.  The return value is a boolean: true for match, false for no
+// match.
+func (re *Regexp) MatchReader(r io.RuneReader) bool {
+	return len(re.doExecute(newInputReader(r), 0)) > 0
+}
+
+// MatchString returns whether the Regexp matches the string s.
+// The return value is a boolean: true for match, false for no match.
+func (re *Regexp) MatchString(s string) bool { return len(re.doExecute(newInputString(s), 0)) > 0 }
+
+// Match returns whether the Regexp matches the byte slice b.
+// The return value is a boolean: true for match, false for no match.
+func (re *Regexp) Match(b []byte) bool { return len(re.doExecute(newInputBytes(b), 0)) > 0 }
+
+// MatchReader checks whether a textual regular expression matches the text
+// read by the RuneReader.  More complicated queries need to use Compile and
+// the full Regexp interface.
+func MatchReader(pattern string, r io.RuneReader) (matched bool, error error) {
+	re, err := Compile(pattern)
+	if err != nil {
+		return false, err
+	}
+	return re.MatchReader(r), nil
+}
+
+// MatchString checks whether a textual regular expression
+// matches a string.  More complicated queries need
+// to use Compile and the full Regexp interface.
+func MatchString(pattern string, s string) (matched bool, error error) {
+	re, err := Compile(pattern)
+	if err != nil {
+		return false, err
+	}
+	return re.MatchString(s), nil
+}
+
+// Match checks whether a textual regular expression
+// matches a byte slice.  More complicated queries need
+// to use Compile and the full Regexp interface.
+func Match(pattern string, b []byte) (matched bool, error error) {
+	re, err := Compile(pattern)
+	if err != nil {
+		return false, err
+	}
+	return re.Match(b), nil
+}
+
+// ReplaceAllString returns a copy of src in which all matches for the Regexp
+// have been replaced by repl.  No support is provided for expressions
+// (e.g. \1 or $1) in the replacement string.
+func (re *Regexp) ReplaceAllString(src, repl string) string {
+	return re.ReplaceAllStringFunc(src, func(string) string { return repl })
+}
+
+// ReplaceAllStringFunc returns a copy of src in which all matches for the
+// Regexp have been replaced by the return value of of function repl (whose
+// first argument is the matched string).  No support is provided for
+// expressions (e.g. \1 or $1) in the replacement string.
+func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
+	lastMatchEnd := 0 // end position of the most recent match
+	searchPos := 0    // position where we next look for a match
+	buf := new(bytes.Buffer)
+	for searchPos <= len(src) {
+		a := re.doExecute(newInputString(src), searchPos)
+		if len(a) == 0 {
+			break // no more matches
+		}
+
+		// Copy the unmatched characters before this match.
+		io.WriteString(buf, src[lastMatchEnd:a[0]])
+
+		// Now insert a copy of the replacement string, but not for a
+		// match of the empty string immediately after another match.
+		// (Otherwise, we get double replacement for patterns that
+		// match both empty and nonempty strings.)
+		if a[1] > lastMatchEnd || a[0] == 0 {
+			io.WriteString(buf, repl(src[a[0]:a[1]]))
+		}
+		lastMatchEnd = a[1]
+
+		// Advance past this match; always advance at least one character.
+		_, width := utf8.DecodeRuneInString(src[searchPos:])
+		if searchPos+width > a[1] {
+			searchPos += width
+		} else if searchPos+1 > a[1] {
+			// This clause is only needed at the end of the input
+			// string.  In that case, DecodeRuneInString returns width=0.
+			searchPos++
+		} else {
+			searchPos = a[1]
+		}
+	}
+
+	// Copy the unmatched characters after the last match.
+	io.WriteString(buf, src[lastMatchEnd:])
+
+	return buf.String()
+}
+
+// ReplaceAll returns a copy of src in which all matches for the Regexp
+// have been replaced by repl.  No support is provided for expressions
+// (e.g. \1 or $1) in the replacement text.
+func (re *Regexp) ReplaceAll(src, repl []byte) []byte {
+	return re.ReplaceAllFunc(src, func([]byte) []byte { return repl })
+}
+
+// ReplaceAllFunc returns a copy of src in which all matches for the
+// Regexp have been replaced by the return value of of function repl (whose
+// first argument is the matched []byte).  No support is provided for
+// expressions (e.g. \1 or $1) in the replacement string.
+func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
+	lastMatchEnd := 0 // end position of the most recent match
+	searchPos := 0    // position where we next look for a match
+	buf := new(bytes.Buffer)
+	for searchPos <= len(src) {
+		a := re.doExecute(newInputBytes(src), searchPos)
+		if len(a) == 0 {
+			break // no more matches
+		}
+
+		// Copy the unmatched characters before this match.
+		buf.Write(src[lastMatchEnd:a[0]])
+
+		// Now insert a copy of the replacement string, but not for a
+		// match of the empty string immediately after another match.
+		// (Otherwise, we get double replacement for patterns that
+		// match both empty and nonempty strings.)
+		if a[1] > lastMatchEnd || a[0] == 0 {
+			buf.Write(repl(src[a[0]:a[1]]))
+		}
+		lastMatchEnd = a[1]
+
+		// Advance past this match; always advance at least one character.
+		_, width := utf8.DecodeRune(src[searchPos:])
+		if searchPos+width > a[1] {
+			searchPos += width
+		} else if searchPos+1 > a[1] {
+			// This clause is only needed at the end of the input
+			// string.  In that case, DecodeRuneInString returns width=0.
+			searchPos++
+		} else {
+			searchPos = a[1]
+		}
+	}
+
+	// Copy the unmatched characters after the last match.
+	buf.Write(src[lastMatchEnd:])
+
+	return buf.Bytes()
+}
+
+// QuoteMeta returns a string that quotes all regular expression metacharacters
+// inside the argument text; the returned string is a regular expression matching
+// the literal text.  For example, QuoteMeta(`[foo]`) returns `\[foo\]`.
+func QuoteMeta(s string) string {
+	b := make([]byte, 2*len(s))
+
+	// A byte loop is correct because all metacharacters are ASCII.
+	j := 0
+	for i := 0; i < len(s); i++ {
+		if special(rune(s[i])) {
+			b[j] = '\\'
+			j++
+		}
+		b[j] = s[i]
+		j++
+	}
+	return string(b[0:j])
+}
+
+// Find matches in slice b if b is non-nil, otherwise find matches in string s.
+func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
+	var end int
+	if b == nil {
+		end = len(s)
+	} else {
+		end = len(b)
+	}
+
+	for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; {
+		var in input
+		if b == nil {
+			in = newInputString(s)
+		} else {
+			in = newInputBytes(b)
+		}
+		matches := re.doExecute(in, pos)
+		if len(matches) == 0 {
+			break
+		}
+
+		accept := true
+		if matches[1] == pos {
+			// We've found an empty match.
+			if matches[0] == prevMatchEnd {
+				// We don't allow an empty match right
+				// after a previous match, so ignore it.
+				accept = false
+			}
+			var width int
+			// TODO: use step()
+			if b == nil {
+				_, width = utf8.DecodeRuneInString(s[pos:end])
+			} else {
+				_, width = utf8.DecodeRune(b[pos:end])
+			}
+			if width > 0 {
+				pos += width
+			} else {
+				pos = end + 1
+			}
+		} else {
+			pos = matches[1]
+		}
+		prevMatchEnd = matches[1]
+
+		if accept {
+			deliver(matches)
+			i++
+		}
+	}
+}
+
+// Find returns a slice holding the text of the leftmost match in b of the regular expression.
+// A return value of nil indicates no match.
+func (re *Regexp) Find(b []byte) []byte {
+	a := re.doExecute(newInputBytes(b), 0)
+	if a == nil {
+		return nil
+	}
+	return b[a[0]:a[1]]
+}
+
+// FindIndex returns a two-element slice of integers defining the location of
+// the leftmost match in b of the regular expression.  The match itself is at
+// b[loc[0]:loc[1]].
+// A return value of nil indicates no match.
+func (re *Regexp) FindIndex(b []byte) (loc []int) {
+	a := re.doExecute(newInputBytes(b), 0)
+	if a == nil {
+		return nil
+	}
+	return a[0:2]
+}
+
+// FindString returns a string holding the text of the leftmost match in s of the regular
+// expression.  If there is no match, the return value is an empty string,
+// but it will also be empty if the regular expression successfully matches
+// an empty string.  Use FindStringIndex or FindStringSubmatch if it is
+// necessary to distinguish these cases.
+func (re *Regexp) FindString(s string) string {
+	a := re.doExecute(newInputString(s), 0)
+	if a == nil {
+		return ""
+	}
+	return s[a[0]:a[1]]
+}
+
+// FindStringIndex returns a two-element slice of integers defining the
+// location of the leftmost match in s of the regular expression.  The match
+// itself is at s[loc[0]:loc[1]].
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringIndex(s string) []int {
+	a := re.doExecute(newInputString(s), 0)
+	if a == nil {
+		return nil
+	}
+	return a[0:2]
+}
+
+// FindReaderIndex returns a two-element slice of integers defining the
+// location of the leftmost match of the regular expression in text read from
+// the RuneReader.  The match itself is at s[loc[0]:loc[1]].  A return
+// value of nil indicates no match.
+func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
+	a := re.doExecute(newInputReader(r), 0)
+	if a == nil {
+		return nil
+	}
+	return a[0:2]
+}
+
+// FindSubmatch returns a slice of slices holding the text of the leftmost
+// match of the regular expression in b and the matches, if any, of its
+// subexpressions, as defined by the 'Submatch' descriptions in the package
+// comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindSubmatch(b []byte) [][]byte {
+	a := re.doExecute(newInputBytes(b), 0)
+	if a == nil {
+		return nil
+	}
+	ret := make([][]byte, len(a)/2)
+	for i := range ret {
+		if a[2*i] >= 0 {
+			ret[i] = b[a[2*i]:a[2*i+1]]
+		}
+	}
+	return ret
+}
+
+// FindSubmatchIndex returns a slice holding the index pairs identifying the
+// leftmost match of the regular expression in b and the matches, if any, of
+// its subexpressions, as defined by the 'Submatch' and 'Index' descriptions
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindSubmatchIndex(b []byte) []int {
+	return re.doExecute(newInputBytes(b), 0)
+}
+
+// FindStringSubmatch returns a slice of strings holding the text of the
+// leftmost match of the regular expression in s and the matches, if any, of
+// its subexpressions, as defined by the 'Submatch' description in the
+// package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringSubmatch(s string) []string {
+	a := re.doExecute(newInputString(s), 0)
+	if a == nil {
+		return nil
+	}
+	ret := make([]string, len(a)/2)
+	for i := range ret {
+		if a[2*i] >= 0 {
+			ret[i] = s[a[2*i]:a[2*i+1]]
+		}
+	}
+	return ret
+}
+
+// FindStringSubmatchIndex returns a slice holding the index pairs
+// identifying the leftmost match of the regular expression in s and the
+// matches, if any, of its subexpressions, as defined by the 'Submatch' and
+// 'Index' descriptions in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringSubmatchIndex(s string) []int {
+	return re.doExecute(newInputString(s), 0)
+}
+
+// FindReaderSubmatchIndex returns a slice holding the index pairs
+// identifying the leftmost match of the regular expression of text read by
+// the RuneReader, and the matches, if any, of its subexpressions, as defined
+// by the 'Submatch' and 'Index' descriptions in the package comment.  A
+// return value of nil indicates no match.
+func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int {
+	return re.doExecute(newInputReader(r), 0)
+}
+
+const startSize = 10 // The size at which to start a slice in the 'All' routines.
+
+// FindAll is the 'All' version of Find; it returns a slice of all successive
+// matches of the expression, as defined by the 'All' description in the
+// package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAll(b []byte, n int) [][]byte {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][]byte, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		result = append(result, b[match[0]:match[1]])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllIndex is the 'All' version of FindIndex; it returns a slice of all
+// successive matches of the expression, as defined by the 'All' description
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllIndex(b []byte, n int) [][]int {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		result = append(result, match[0:2])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllString is the 'All' version of FindString; it returns a slice of all
+// successive matches of the expression, as defined by the 'All' description
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllString(s string, n int) []string {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([]string, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		result = append(result, s[match[0]:match[1]])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllStringIndex is the 'All' version of FindStringIndex; it returns a
+// slice of all successive matches of the expression, as defined by the 'All'
+// description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringIndex(s string, n int) [][]int {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		result = append(result, match[0:2])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllSubmatch is the 'All' version of FindSubmatch; it returns a slice
+// of all successive matches of the expression, as defined by the 'All'
+// description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][][]byte, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		slice := make([][]byte, len(match)/2)
+		for j := range slice {
+			if match[2*j] >= 0 {
+				slice[j] = b[match[2*j]:match[2*j+1]]
+			}
+		}
+		result = append(result, slice)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllSubmatchIndex is the 'All' version of FindSubmatchIndex; it returns
+// a slice of all successive matches of the expression, as defined by the
+// 'All' description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		result = append(result, match)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllStringSubmatch is the 'All' version of FindStringSubmatch; it
+// returns a slice of all successive matches of the expression, as defined by
+// the 'All' description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([][]string, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		slice := make([]string, len(match)/2)
+		for j := range slice {
+			if match[2*j] >= 0 {
+				slice[j] = s[match[2*j]:match[2*j+1]]
+			}
+		}
+		result = append(result, slice)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllStringSubmatchIndex is the 'All' version of
+// FindStringSubmatchIndex; it returns a slice of all successive matches of
+// the expression, as defined by the 'All' description in the package
+// comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		result = append(result, match)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
diff --git a/third_party/gofrontend/libgo/go/old/template/doc.go b/third_party/gofrontend/libgo/go/old/template/doc.go
new file mode 100644
index 0000000..e778d80
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/old/template/doc.go
@@ -0,0 +1,91 @@
+// 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 template implements data-driven templates for generating textual
+	output such as HTML.
+
+	Templates are executed by applying them to a data structure.
+	Annotations in the template refer to elements of the data
+	structure (typically a field of a struct or a key in a map)
+	to control execution and derive values to be displayed.
+	The template walks the structure as it executes and the
+	"cursor" @ represents the value at the current location
+	in the structure.
+
+	Data items may be values or pointers; the interface hides the
+	indirection.
+
+	In the following, 'Field' is one of several things, according to the data.
+
+		- The name of a field of a struct (result = data.Field),
+		- The value stored in a map under that key (result = data["Field"]), or
+		- The result of invoking a niladic single-valued method with that name
+		  (result = data.Field())
+
+	If Field is a struct field or method name, it must be an exported
+	(capitalized) name.
+
+	Major constructs ({} are the default delimiters for template actions;
+	[] are the notation in this comment for optional elements):
+
+		{# comment }
+
+	A one-line comment.
+
+		{.section field} XXX [ {.or} YYY ] {.end}
+
+	Set @ to the value of the field.  It may be an explicit @
+	to stay at the same point in the data. If the field is nil
+	or empty, execute YYY; otherwise execute XXX.
+
+		{.repeated section field} XXX [ {.alternates with} ZZZ ] [ {.or} YYY ] {.end}
+
+	Like .section, but field must be an array or slice.  XXX
+	is executed for each element.  If the array is nil or empty,
+	YYY is executed instead.  If the {.alternates with} marker
+	is present, ZZZ is executed between iterations of XXX.
+
+		{field}
+		{field1 field2 ...}
+		{field|formatter}
+		{field1 field2...|formatter}
+		{field|formatter1|formatter2}
+
+	Insert the value of the fields into the output. Each field is
+	first looked for in the cursor, as in .section and .repeated.
+	If it is not found, the search continues in outer sections
+	until the top level is reached.
+
+	If the field value is a pointer, leading asterisks indicate
+	that the value to be inserted should be evaluated through the
+	pointer.  For example, if x.p is of type *int, {x.p} will
+	insert the value of the pointer but {*x.p} will insert the
+	value of the underlying integer.  If the value is nil or not a
+	pointer, asterisks have no effect.
+
+	If a formatter is specified, it must be named in the formatter
+	map passed to the template set up routines or in the default
+	set ("html","str","") and is used to process the data for
+	output.  The formatter function has signature
+		func(wr io.Writer, formatter string, data ...interface{})
+	where wr is the destination for output, data holds the field
+	values at the instantiation, and formatter is its name at
+	the invocation site.  The default formatter just concatenates
+	the string representations of the fields.
+
+	Multiple formatters separated by the pipeline character | are
+	executed sequentially, with each formatter receiving the bytes
+	emitted by the one to its left.
+
+	As well as field names, one may use literals with Go syntax.
+	Integer, floating-point, and string literals are supported.
+	Raw strings may not span newlines.
+
+	The delimiter strings get their default value, "{" and "}", from
+	JSON-template.  They may be set to any non-empty, space-free
+	string using the SetDelims method.  Their value can be printed
+	in the output using {.meta-left} and {.meta-right}.
+*/
+package template
diff --git a/third_party/gofrontend/libgo/go/old/template/execute.go b/third_party/gofrontend/libgo/go/old/template/execute.go
new file mode 100644
index 0000000..464b620
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/old/template/execute.go
@@ -0,0 +1,346 @@
+// 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.
+
+// Code to execute a parsed template.
+
+package template
+
+import (
+	"bytes"
+	"io"
+	"reflect"
+	"strings"
+)
+
+// Internal state for executing a Template.  As we evaluate the struct,
+// the data item descends into the fields associated with sections, etc.
+// Parent is used to walk upwards to find variables higher in the tree.
+type state struct {
+	parent *state          // parent in hierarchy
+	data   reflect.Value   // the driver data for this section etc.
+	wr     io.Writer       // where to send output
+	buf    [2]bytes.Buffer // alternating buffers used when chaining formatters
+}
+
+func (parent *state) clone(data reflect.Value) *state {
+	return &state{parent: parent, data: data, wr: parent.wr}
+}
+
+// Evaluate interfaces and pointers looking for a value that can look up the name, via a
+// struct field, method, or map key, and return the result of the lookup.
+func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value {
+	for v.IsValid() {
+		typ := v.Type()
+		if n := v.Type().NumMethod(); n > 0 {
+			for i := 0; i < n; i++ {
+				m := typ.Method(i)
+				mtyp := m.Type
+				if m.Name == name && mtyp.NumIn() == 1 && mtyp.NumOut() == 1 {
+					if !isExported(name) {
+						t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type())
+					}
+					return v.Method(i).Call(nil)[0]
+				}
+			}
+		}
+		switch av := v; av.Kind() {
+		case reflect.Ptr:
+			v = av.Elem()
+		case reflect.Interface:
+			v = av.Elem()
+		case reflect.Struct:
+			if !isExported(name) {
+				t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type())
+			}
+			return av.FieldByName(name)
+		case reflect.Map:
+			if v := av.MapIndex(reflect.ValueOf(name)); v.IsValid() {
+				return v
+			}
+			return reflect.Zero(typ.Elem())
+		default:
+			return reflect.Value{}
+		}
+	}
+	return v
+}
+
+// indirectPtr returns the item numLevels levels of indirection below the value.
+// It is forgiving: if the value is not a pointer, it returns it rather than giving
+// an error.  If the pointer is nil, it is returned as is.
+func indirectPtr(v reflect.Value, numLevels int) reflect.Value {
+	for i := numLevels; v.IsValid() && i > 0; i++ {
+		if p := v; p.Kind() == reflect.Ptr {
+			if p.IsNil() {
+				return v
+			}
+			v = p.Elem()
+		} else {
+			break
+		}
+	}
+	return v
+}
+
+// Walk v through pointers and interfaces, extracting the elements within.
+func indirect(v reflect.Value) reflect.Value {
+loop:
+	for v.IsValid() {
+		switch av := v; av.Kind() {
+		case reflect.Ptr:
+			v = av.Elem()
+		case reflect.Interface:
+			v = av.Elem()
+		default:
+			break loop
+		}
+	}
+	return v
+}
+
+// If the data for this template is a struct, find the named variable.
+// Names of the form a.b.c are walked down the data tree.
+// The special name "@" (the "cursor") denotes the current data.
+// The value coming in (st.data) might need indirecting to reach
+// a struct while the return value is not indirected - that is,
+// it represents the actual named field. Leading stars indicate
+// levels of indirection to be applied to the value.
+func (t *Template) findVar(st *state, s string) reflect.Value {
+	data := st.data
+	flattenedName := strings.TrimLeft(s, "*")
+	numStars := len(s) - len(flattenedName)
+	s = flattenedName
+	if s == "@" {
+		return indirectPtr(data, numStars)
+	}
+	for _, elem := range strings.Split(s, ".") {
+		// Look up field; data must be a struct or map.
+		data = t.lookup(st, data, elem)
+		if !data.IsValid() {
+			return reflect.Value{}
+		}
+	}
+	return indirectPtr(data, numStars)
+}
+
+// Is there no data to look at?
+func empty(v reflect.Value) bool {
+	v = indirect(v)
+	if !v.IsValid() {
+		return true
+	}
+	switch v.Kind() {
+	case reflect.Bool:
+		return v.Bool() == false
+	case reflect.String:
+		return v.String() == ""
+	case reflect.Struct:
+		return false
+	case reflect.Map:
+		return false
+	case reflect.Array:
+		return v.Len() == 0
+	case reflect.Slice:
+		return v.Len() == 0
+	}
+	return false
+}
+
+// Look up a variable or method, up through the parent if necessary.
+func (t *Template) varValue(name string, st *state) reflect.Value {
+	field := t.findVar(st, name)
+	if !field.IsValid() {
+		if st.parent == nil {
+			t.execError(st, t.linenum, "name not found: %s in type %s", name, st.data.Type())
+		}
+		return t.varValue(name, st.parent)
+	}
+	return field
+}
+
+func (t *Template) format(wr io.Writer, fmt string, val []interface{}, v *variableElement, st *state) {
+	fn := t.formatter(fmt)
+	if fn == nil {
+		t.execError(st, v.linenum, "missing formatter %s for variable", fmt)
+	}
+	fn(wr, fmt, val...)
+}
+
+// Evaluate a variable, looking up through the parent if necessary.
+// If it has a formatter attached ({var|formatter}) run that too.
+func (t *Template) writeVariable(v *variableElement, st *state) {
+	// Resolve field names
+	val := make([]interface{}, len(v.args))
+	for i, arg := range v.args {
+		if name, ok := arg.(fieldName); ok {
+			val[i] = t.varValue(string(name), st).Interface()
+		} else {
+			val[i] = arg
+		}
+	}
+	for i, fmt := range v.fmts[:len(v.fmts)-1] {
+		b := &st.buf[i&1]
+		b.Reset()
+		t.format(b, fmt, val, v, st)
+		val = val[0:1]
+		val[0] = b.Bytes()
+	}
+	t.format(st.wr, v.fmts[len(v.fmts)-1], val, v, st)
+}
+
+// Execute element i.  Return next index to execute.
+func (t *Template) executeElement(i int, st *state) int {
+	switch elem := t.elems[i].(type) {
+	case *textElement:
+		st.wr.Write(elem.text)
+		return i + 1
+	case *literalElement:
+		st.wr.Write(elem.text)
+		return i + 1
+	case *variableElement:
+		t.writeVariable(elem, st)
+		return i + 1
+	case *sectionElement:
+		t.executeSection(elem, st)
+		return elem.end
+	case *repeatedElement:
+		t.executeRepeated(elem, st)
+		return elem.end
+	}
+	e := t.elems[i]
+	t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.ValueOf(e).Interface(), e)
+	return 0
+}
+
+// Execute the template.
+func (t *Template) execute(start, end int, st *state) {
+	for i := start; i < end; {
+		i = t.executeElement(i, st)
+	}
+}
+
+// Execute a .section
+func (t *Template) executeSection(s *sectionElement, st *state) {
+	// Find driver data for this section.  It must be in the current struct.
+	field := t.varValue(s.field, st)
+	if !field.IsValid() {
+		t.execError(st, s.linenum, ".section: cannot find field %s in %s", s.field, st.data.Type())
+	}
+	st = st.clone(field)
+	start, end := s.start, s.or
+	if !empty(field) {
+		// Execute the normal block.
+		if end < 0 {
+			end = s.end
+		}
+	} else {
+		// Execute the .or block.  If it's missing, do nothing.
+		start, end = s.or, s.end
+		if start < 0 {
+			return
+		}
+	}
+	for i := start; i < end; {
+		i = t.executeElement(i, st)
+	}
+}
+
+// Return the result of calling the Iter method on v, or nil.
+func iter(v reflect.Value) reflect.Value {
+	for j := 0; j < v.Type().NumMethod(); j++ {
+		mth := v.Type().Method(j)
+		fv := v.Method(j)
+		ft := fv.Type()
+		// TODO(rsc): NumIn() should return 0 here, because ft is from a curried FuncValue.
+		if mth.Name != "Iter" || ft.NumIn() != 1 || ft.NumOut() != 1 {
+			continue
+		}
+		ct := ft.Out(0)
+		if ct.Kind() != reflect.Chan ||
+			ct.ChanDir()&reflect.RecvDir == 0 {
+			continue
+		}
+		return fv.Call(nil)[0]
+	}
+	return reflect.Value{}
+}
+
+// Execute a .repeated section
+func (t *Template) executeRepeated(r *repeatedElement, st *state) {
+	// Find driver data for this section.  It must be in the current struct.
+	field := t.varValue(r.field, st)
+	if !field.IsValid() {
+		t.execError(st, r.linenum, ".repeated: cannot find field %s in %s", r.field, st.data.Type())
+	}
+	field = indirect(field)
+
+	start, end := r.start, r.or
+	if end < 0 {
+		end = r.end
+	}
+	if r.altstart >= 0 {
+		end = r.altstart
+	}
+	first := true
+
+	// Code common to all the loops.
+	loopBody := func(newst *state) {
+		// .alternates between elements
+		if !first && r.altstart >= 0 {
+			for i := r.altstart; i < r.altend; {
+				i = t.executeElement(i, newst)
+			}
+		}
+		first = false
+		for i := start; i < end; {
+			i = t.executeElement(i, newst)
+		}
+	}
+
+	if array := field; array.Kind() == reflect.Array || array.Kind() == reflect.Slice {
+		for j := 0; j < array.Len(); j++ {
+			loopBody(st.clone(array.Index(j)))
+		}
+	} else if m := field; m.Kind() == reflect.Map {
+		for _, key := range m.MapKeys() {
+			loopBody(st.clone(m.MapIndex(key)))
+		}
+	} else if ch := iter(field); ch.IsValid() {
+		for {
+			e, ok := ch.Recv()
+			if !ok {
+				break
+			}
+			loopBody(st.clone(e))
+		}
+	} else {
+		t.execError(st, r.linenum, ".repeated: cannot repeat %s (type %s)",
+			r.field, field.Type())
+	}
+
+	if first {
+		// Empty. Execute the .or block, once.  If it's missing, do nothing.
+		start, end := r.or, r.end
+		if start >= 0 {
+			newst := st.clone(field)
+			for i := start; i < end; {
+				i = t.executeElement(i, newst)
+			}
+		}
+		return
+	}
+}
+
+// A valid delimiter must contain no space and be non-empty.
+func validDelim(d []byte) bool {
+	if len(d) == 0 {
+		return false
+	}
+	for _, c := range d {
+		if isSpace(c) {
+			return false
+		}
+	}
+	return true
+}
diff --git a/third_party/gofrontend/libgo/go/old/template/format.go b/third_party/gofrontend/libgo/go/old/template/format.go
new file mode 100644
index 0000000..9156b08
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/old/template/format.go
@@ -0,0 +1,77 @@
+// 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.
+
+// Template library: default formatters
+
+package template
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+)
+
+// StringFormatter formats into the default string representation.
+// It is stored under the name "str" and is the default formatter.
+// You can override the default formatter by storing your default
+// under the name "" in your custom formatter map.
+func StringFormatter(w io.Writer, format string, value ...interface{}) {
+	if len(value) == 1 {
+		if b, ok := value[0].([]byte); ok {
+			w.Write(b)
+			return
+		}
+	}
+	fmt.Fprint(w, value...)
+}
+
+var (
+	esc_quot = []byte("&#34;") // shorter than "&quot;"
+	esc_apos = []byte("&#39;") // shorter than "&apos;"
+	esc_amp  = []byte("&amp;")
+	esc_lt   = []byte("&lt;")
+	esc_gt   = []byte("&gt;")
+)
+
+// HTMLEscape writes to w the properly escaped HTML equivalent
+// of the plain text data s.
+func HTMLEscape(w io.Writer, s []byte) {
+	var esc []byte
+	last := 0
+	for i, c := range s {
+		switch c {
+		case '"':
+			esc = esc_quot
+		case '\'':
+			esc = esc_apos
+		case '&':
+			esc = esc_amp
+		case '<':
+			esc = esc_lt
+		case '>':
+			esc = esc_gt
+		default:
+			continue
+		}
+		w.Write(s[last:i])
+		w.Write(esc)
+		last = i + 1
+	}
+	w.Write(s[last:])
+}
+
+// HTMLFormatter formats arbitrary values for HTML
+func HTMLFormatter(w io.Writer, format string, value ...interface{}) {
+	ok := false
+	var b []byte
+	if len(value) == 1 {
+		b, ok = value[0].([]byte)
+	}
+	if !ok {
+		var buf bytes.Buffer
+		fmt.Fprint(&buf, value...)
+		b = buf.Bytes()
+	}
+	HTMLEscape(w, b)
+}
diff --git a/third_party/gofrontend/libgo/go/old/template/parse.go b/third_party/gofrontend/libgo/go/old/template/parse.go
new file mode 100644
index 0000000..e1bfa47
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/old/template/parse.go
@@ -0,0 +1,742 @@
+// 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.
+
+// Code to parse a template.
+
+package template
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"reflect"
+	"strconv"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// Errors returned during parsing and execution.  Users may extract the information and reformat
+// if they desire.
+type Error struct {
+	Line int
+	Msg  string
+}
+
+func (e *Error) Error() string { return fmt.Sprintf("line %d: %s", e.Line, e.Msg) }
+
+// checkError is a deferred function to turn a panic with type *Error into a plain error return.
+// Other panics are unexpected and so are re-enabled.
+func checkError(error *error) {
+	if v := recover(); v != nil {
+		if e, ok := v.(*Error); ok {
+			*error = e
+		} else {
+			// runtime errors should crash
+			panic(v)
+		}
+	}
+}
+
+// Most of the literals are aces.
+var lbrace = []byte{'{'}
+var rbrace = []byte{'}'}
+var space = []byte{' '}
+var tab = []byte{'\t'}
+
+// The various types of "tokens", which are plain text or (usually) brace-delimited descriptors
+const (
+	tokAlternates = iota
+	tokComment
+	tokEnd
+	tokLiteral
+	tokOr
+	tokRepeated
+	tokSection
+	tokText
+	tokVariable
+)
+
+// FormatterMap is the type describing the mapping from formatter
+// names to the functions that implement them.
+type FormatterMap map[string]func(io.Writer, string, ...interface{})
+
+// Built-in formatters.
+var builtins = FormatterMap{
+	"html": HTMLFormatter,
+	"str":  StringFormatter,
+	"":     StringFormatter,
+}
+
+// The parsed state of a template is a vector of xxxElement structs.
+// Sections have line numbers so errors can be reported better during execution.
+
+// Plain text.
+type textElement struct {
+	text []byte
+}
+
+// A literal such as .meta-left or .meta-right
+type literalElement struct {
+	text []byte
+}
+
+// A variable invocation to be evaluated
+type variableElement struct {
+	linenum int
+	args    []interface{} // The fields and literals in the invocation.
+	fmts    []string      // Names of formatters to apply. len(fmts) > 0
+}
+
+// A variableElement arg to be evaluated as a field name
+type fieldName string
+
+// A .section block, possibly with a .or
+type sectionElement struct {
+	linenum int    // of .section itself
+	field   string // cursor field for this block
+	start   int    // first element
+	or      int    // first element of .or block
+	end     int    // one beyond last element
+}
+
+// A .repeated block, possibly with a .or and a .alternates
+type repeatedElement struct {
+	sectionElement     // It has the same structure...
+	altstart       int // ... except for alternates
+	altend         int
+}
+
+// Template is the type that represents a template definition.
+// It is unchanged after parsing.
+type Template struct {
+	fmap FormatterMap // formatters for variables
+	// Used during parsing:
+	ldelim, rdelim []byte // delimiters; default {}
+	buf            []byte // input text to process
+	p              int    // position in buf
+	linenum        int    // position in input
+	// Parsed results:
+	elems []interface{}
+}
+
+// New creates a new template with the specified formatter map (which
+// may be nil) to define auxiliary functions for formatting variables.
+func New(fmap FormatterMap) *Template {
+	t := new(Template)
+	t.fmap = fmap
+	t.ldelim = lbrace
+	t.rdelim = rbrace
+	t.elems = make([]interface{}, 0, 16)
+	return t
+}
+
+// Report error and stop executing.  The line number must be provided explicitly.
+func (t *Template) execError(st *state, line int, err string, args ...interface{}) {
+	panic(&Error{line, fmt.Sprintf(err, args...)})
+}
+
+// Report error, panic to terminate parsing.
+// The line number comes from the template state.
+func (t *Template) parseError(err string, args ...interface{}) {
+	panic(&Error{t.linenum, fmt.Sprintf(err, args...)})
+}
+
+// Is this an exported - upper case - name?
+func isExported(name string) bool {
+	r, _ := utf8.DecodeRuneInString(name)
+	return unicode.IsUpper(r)
+}
+
+// -- Lexical analysis
+
+// Is c a space character?
+func isSpace(c uint8) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' }
+
+// Safely, does s[n:n+len(t)] == t?
+func equal(s []byte, n int, t []byte) bool {
+	b := s[n:]
+	if len(t) > len(b) { // not enough space left for a match.
+		return false
+	}
+	for i, c := range t {
+		if c != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// isQuote returns true if c is a string- or character-delimiting quote character.
+func isQuote(c byte) bool {
+	return c == '"' || c == '`' || c == '\''
+}
+
+// endQuote returns the end quote index for the quoted string that
+// starts at n, or -1 if no matching end quote is found before the end
+// of the line.
+func endQuote(s []byte, n int) int {
+	quote := s[n]
+	for n++; n < len(s); n++ {
+		switch s[n] {
+		case '\\':
+			if quote == '"' || quote == '\'' {
+				n++
+			}
+		case '\n':
+			return -1
+		case quote:
+			return n
+		}
+	}
+	return -1
+}
+
+// nextItem returns the next item from the input buffer.  If the returned
+// item is empty, we are at EOF.  The item will be either a
+// delimited string or a non-empty string between delimited
+// strings. Tokens stop at (but include, if plain text) a newline.
+// Action tokens on a line by themselves drop any space on
+// either side, up to and including the newline.
+func (t *Template) nextItem() []byte {
+	startOfLine := t.p == 0 || t.buf[t.p-1] == '\n'
+	start := t.p
+	var i int
+	newline := func() {
+		t.linenum++
+		i++
+	}
+	// Leading space up to but not including newline
+	for i = start; i < len(t.buf); i++ {
+		if t.buf[i] == '\n' || !isSpace(t.buf[i]) {
+			break
+		}
+	}
+	leadingSpace := i > start
+	// What's left is nothing, newline, delimited string, or plain text
+	switch {
+	case i == len(t.buf):
+		// EOF; nothing to do
+	case t.buf[i] == '\n':
+		newline()
+	case equal(t.buf, i, t.ldelim):
+		left := i         // Start of left delimiter.
+		right := -1       // Will be (immediately after) right delimiter.
+		haveText := false // Delimiters contain text.
+		i += len(t.ldelim)
+		// Find the end of the action.
+		for ; i < len(t.buf); i++ {
+			if t.buf[i] == '\n' {
+				break
+			}
+			if isQuote(t.buf[i]) {
+				i = endQuote(t.buf, i)
+				if i == -1 {
+					t.parseError("unmatched quote")
+					return nil
+				}
+				continue
+			}
+			if equal(t.buf, i, t.rdelim) {
+				i += len(t.rdelim)
+				right = i
+				break
+			}
+			haveText = true
+		}
+		if right < 0 {
+			t.parseError("unmatched opening delimiter")
+			return nil
+		}
+		// Is this a special action (starts with '.' or '#') and the only thing on the line?
+		if startOfLine && haveText {
+			firstChar := t.buf[left+len(t.ldelim)]
+			if firstChar == '.' || firstChar == '#' {
+				// It's special and the first thing on the line. Is it the last?
+				for j := right; j < len(t.buf) && isSpace(t.buf[j]); j++ {
+					if t.buf[j] == '\n' {
+						// Yes it is. Drop the surrounding space and return the {.foo}
+						t.linenum++
+						t.p = j + 1
+						return t.buf[left:right]
+					}
+				}
+			}
+		}
+		// No it's not. If there's leading space, return that.
+		if leadingSpace {
+			// not trimming space: return leading space if there is some.
+			t.p = left
+			return t.buf[start:left]
+		}
+		// Return the word, leave the trailing space.
+		start = left
+		break
+	default:
+		for ; i < len(t.buf); i++ {
+			if t.buf[i] == '\n' {
+				newline()
+				break
+			}
+			if equal(t.buf, i, t.ldelim) {
+				break
+			}
+		}
+	}
+	item := t.buf[start:i]
+	t.p = i
+	return item
+}
+
+// Turn a byte array into a space-split array of strings,
+// taking into account quoted strings.
+func words(buf []byte) []string {
+	s := make([]string, 0, 5)
+	for i := 0; i < len(buf); {
+		// One word per loop
+		for i < len(buf) && isSpace(buf[i]) {
+			i++
+		}
+		if i == len(buf) {
+			break
+		}
+		// Got a word
+		start := i
+		if isQuote(buf[i]) {
+			i = endQuote(buf, i)
+			if i < 0 {
+				i = len(buf)
+			} else {
+				i++
+			}
+		}
+		// Even with quotes, break on space only.  This handles input
+		// such as {""|} and catches quoting mistakes.
+		for i < len(buf) && !isSpace(buf[i]) {
+			i++
+		}
+		s = append(s, string(buf[start:i]))
+	}
+	return s
+}
+
+// Analyze an item and return its token type and, if it's an action item, an array of
+// its constituent words.
+func (t *Template) analyze(item []byte) (tok int, w []string) {
+	// item is known to be non-empty
+	if !equal(item, 0, t.ldelim) { // doesn't start with left delimiter
+		tok = tokText
+		return
+	}
+	if !equal(item, len(item)-len(t.rdelim), t.rdelim) { // doesn't end with right delimiter
+		t.parseError("internal error: unmatched opening delimiter") // lexing should prevent this
+		return
+	}
+	if len(item) <= len(t.ldelim)+len(t.rdelim) { // no contents
+		t.parseError("empty directive")
+		return
+	}
+	// Comment
+	if item[len(t.ldelim)] == '#' {
+		tok = tokComment
+		return
+	}
+	// Split into words
+	w = words(item[len(t.ldelim) : len(item)-len(t.rdelim)]) // drop final delimiter
+	if len(w) == 0 {
+		t.parseError("empty directive")
+		return
+	}
+	first := w[0]
+	if first[0] != '.' {
+		tok = tokVariable
+		return
+	}
+	if len(first) > 1 && first[1] >= '0' && first[1] <= '9' {
+		// Must be a float.
+		tok = tokVariable
+		return
+	}
+	switch first {
+	case ".meta-left", ".meta-right", ".space", ".tab":
+		tok = tokLiteral
+		return
+	case ".or":
+		tok = tokOr
+		return
+	case ".end":
+		tok = tokEnd
+		return
+	case ".section":
+		if len(w) != 2 {
+			t.parseError("incorrect fields for .section: %s", item)
+			return
+		}
+		tok = tokSection
+		return
+	case ".repeated":
+		if len(w) != 3 || w[1] != "section" {
+			t.parseError("incorrect fields for .repeated: %s", item)
+			return
+		}
+		tok = tokRepeated
+		return
+	case ".alternates":
+		if len(w) != 2 || w[1] != "with" {
+			t.parseError("incorrect fields for .alternates: %s", item)
+			return
+		}
+		tok = tokAlternates
+		return
+	}
+	t.parseError("bad directive: %s", item)
+	return
+}
+
+// formatter returns the Formatter with the given name in the Template, or nil if none exists.
+func (t *Template) formatter(name string) func(io.Writer, string, ...interface{}) {
+	if t.fmap != nil {
+		if fn := t.fmap[name]; fn != nil {
+			return fn
+		}
+	}
+	return builtins[name]
+}
+
+// -- Parsing
+
+// newVariable allocates a new variable-evaluation element.
+func (t *Template) newVariable(words []string) *variableElement {
+	formatters := extractFormatters(words)
+	args := make([]interface{}, len(words))
+
+	// Build argument list, processing any literals
+	for i, word := range words {
+		var lerr error
+		switch word[0] {
+		case '"', '`', '\'':
+			v, err := strconv.Unquote(word)
+			if err == nil && word[0] == '\'' {
+				args[i], _ = utf8.DecodeRuneInString(v)
+			} else {
+				args[i], lerr = v, err
+			}
+
+		case '.', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			v, err := strconv.ParseInt(word, 0, 64)
+			if err == nil {
+				args[i] = v
+			} else {
+				v, err := strconv.ParseFloat(word, 64)
+				args[i], lerr = v, err
+			}
+
+		default:
+			args[i] = fieldName(word)
+		}
+		if lerr != nil {
+			t.parseError("invalid literal: %q: %s", word, lerr)
+		}
+	}
+
+	// We could remember the function address here and avoid the lookup later,
+	// but it's more dynamic to let the user change the map contents underfoot.
+	// We do require the name to be present, though.
+
+	// Is it in user-supplied map?
+	for _, f := range formatters {
+		if t.formatter(f) == nil {
+			t.parseError("unknown formatter: %q", f)
+		}
+	}
+
+	return &variableElement{t.linenum, args, formatters}
+}
+
+// extractFormatters extracts a list of formatters from words.
+// After the final space-separated argument in a variable, formatters may be
+// specified separated by pipe symbols. For example: {a b c|d|e}
+// The words parameter still has the formatters joined by '|' in the last word.
+// extractFormatters splits formatters, replaces the last word with the content
+// found before the first '|' within it, and returns the formatters obtained.
+// If no formatters are found in words, the default formatter is returned.
+func extractFormatters(words []string) (formatters []string) {
+	// "" is the default formatter.
+	formatters = []string{""}
+	if len(words) == 0 {
+		return
+	}
+	var bar int
+	lastWord := words[len(words)-1]
+	if isQuote(lastWord[0]) {
+		end := endQuote([]byte(lastWord), 0)
+		if end < 0 || end+1 == len(lastWord) || lastWord[end+1] != '|' {
+			return
+		}
+		bar = end + 1
+	} else {
+		bar = strings.IndexRune(lastWord, '|')
+		if bar < 0 {
+			return
+		}
+	}
+	words[len(words)-1] = lastWord[0:bar]
+	formatters = strings.Split(lastWord[bar+1:], "|")
+	return
+}
+
+// Grab the next item.  If it's simple, just append it to the template.
+// Otherwise return its details.
+func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) {
+	tok, w = t.analyze(item)
+	done = true // assume for simplicity
+	switch tok {
+	case tokComment:
+		return
+	case tokText:
+		t.elems = append(t.elems, &textElement{item})
+		return
+	case tokLiteral:
+		switch w[0] {
+		case ".meta-left":
+			t.elems = append(t.elems, &literalElement{t.ldelim})
+		case ".meta-right":
+			t.elems = append(t.elems, &literalElement{t.rdelim})
+		case ".space":
+			t.elems = append(t.elems, &literalElement{space})
+		case ".tab":
+			t.elems = append(t.elems, &literalElement{tab})
+		default:
+			t.parseError("internal error: unknown literal: %s", w[0])
+		}
+		return
+	case tokVariable:
+		t.elems = append(t.elems, t.newVariable(w))
+		return
+	}
+	return false, tok, w
+}
+
+// parseRepeated and parseSection are mutually recursive
+
+func (t *Template) parseRepeated(words []string) *repeatedElement {
+	r := new(repeatedElement)
+	t.elems = append(t.elems, r)
+	r.linenum = t.linenum
+	r.field = words[2]
+	// Scan section, collecting true and false (.or) blocks.
+	r.start = len(t.elems)
+	r.or = -1
+	r.altstart = -1
+	r.altend = -1
+Loop:
+	for {
+		item := t.nextItem()
+		if len(item) == 0 {
+			t.parseError("missing .end for .repeated section")
+			break
+		}
+		done, tok, w := t.parseSimple(item)
+		if done {
+			continue
+		}
+		switch tok {
+		case tokEnd:
+			break Loop
+		case tokOr:
+			if r.or >= 0 {
+				t.parseError("extra .or in .repeated section")
+				break Loop
+			}
+			r.altend = len(t.elems)
+			r.or = len(t.elems)
+		case tokSection:
+			t.parseSection(w)
+		case tokRepeated:
+			t.parseRepeated(w)
+		case tokAlternates:
+			if r.altstart >= 0 {
+				t.parseError("extra .alternates in .repeated section")
+				break Loop
+			}
+			if r.or >= 0 {
+				t.parseError(".alternates inside .or block in .repeated section")
+				break Loop
+			}
+			r.altstart = len(t.elems)
+		default:
+			t.parseError("internal error: unknown repeated section item: %s", item)
+			break Loop
+		}
+	}
+	if r.altend < 0 {
+		r.altend = len(t.elems)
+	}
+	r.end = len(t.elems)
+	return r
+}
+
+func (t *Template) parseSection(words []string) *sectionElement {
+	s := new(sectionElement)
+	t.elems = append(t.elems, s)
+	s.linenum = t.linenum
+	s.field = words[1]
+	// Scan section, collecting true and false (.or) blocks.
+	s.start = len(t.elems)
+	s.or = -1
+Loop:
+	for {
+		item := t.nextItem()
+		if len(item) == 0 {
+			t.parseError("missing .end for .section")
+			break
+		}
+		done, tok, w := t.parseSimple(item)
+		if done {
+			continue
+		}
+		switch tok {
+		case tokEnd:
+			break Loop
+		case tokOr:
+			if s.or >= 0 {
+				t.parseError("extra .or in .section")
+				break Loop
+			}
+			s.or = len(t.elems)
+		case tokSection:
+			t.parseSection(w)
+		case tokRepeated:
+			t.parseRepeated(w)
+		case tokAlternates:
+			t.parseError(".alternates not in .repeated")
+		default:
+			t.parseError("internal error: unknown section item: %s", item)
+		}
+	}
+	s.end = len(t.elems)
+	return s
+}
+
+func (t *Template) parse() {
+	for {
+		item := t.nextItem()
+		if len(item) == 0 {
+			break
+		}
+		done, tok, w := t.parseSimple(item)
+		if done {
+			continue
+		}
+		switch tok {
+		case tokOr, tokEnd, tokAlternates:
+			t.parseError("unexpected %s", w[0])
+		case tokSection:
+			t.parseSection(w)
+		case tokRepeated:
+			t.parseRepeated(w)
+		default:
+			t.parseError("internal error: bad directive in parse: %s", item)
+		}
+	}
+}
+
+// -- Execution
+
+// -- Public interface
+
+// Parse initializes a Template by parsing its definition.  The string
+// s contains the template text.  If any errors occur, Parse returns
+// the error.
+func (t *Template) Parse(s string) (err error) {
+	if t.elems == nil {
+		return &Error{1, "template not allocated with New"}
+	}
+	if !validDelim(t.ldelim) || !validDelim(t.rdelim) {
+		return &Error{1, fmt.Sprintf("bad delimiter strings %q %q", t.ldelim, t.rdelim)}
+	}
+	defer checkError(&err)
+	t.buf = []byte(s)
+	t.p = 0
+	t.linenum = 1
+	t.parse()
+	return nil
+}
+
+// ParseFile is like Parse but reads the template definition from the
+// named file.
+func (t *Template) ParseFile(filename string) (err error) {
+	b, err := ioutil.ReadFile(filename)
+	if err != nil {
+		return err
+	}
+	return t.Parse(string(b))
+}
+
+// Execute applies a parsed template to the specified data object,
+// generating output to wr.
+func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
+	// Extract the driver data.
+	val := reflect.ValueOf(data)
+	defer checkError(&err)
+	t.p = 0
+	t.execute(0, len(t.elems), &state{parent: nil, data: val, wr: wr})
+	return nil
+}
+
+// SetDelims sets the left and right delimiters for operations in the
+// template.  They are validated during parsing.  They could be
+// validated here but it's better to keep the routine simple.  The
+// delimiters are very rarely invalid and Parse has the necessary
+// error-handling interface already.
+func (t *Template) SetDelims(left, right string) {
+	t.ldelim = []byte(left)
+	t.rdelim = []byte(right)
+}
+
+// Parse creates a Template with default parameters (such as {} for
+// metacharacters).  The string s contains the template text while
+// the formatter map fmap, which may be nil, defines auxiliary functions
+// for formatting variables.  The template is returned. If any errors
+// occur, err will be non-nil.
+func Parse(s string, fmap FormatterMap) (t *Template, err error) {
+	t = New(fmap)
+	err = t.Parse(s)
+	if err != nil {
+		t = nil
+	}
+	return
+}
+
+// ParseFile is a wrapper function that creates a Template with default
+// parameters (such as {} for metacharacters).  The filename identifies
+// a file containing the template text, while the formatter map fmap, which
+// may be nil, defines auxiliary functions for formatting variables.
+// The template is returned. If any errors occur, err will be non-nil.
+func ParseFile(filename string, fmap FormatterMap) (t *Template, err error) {
+	b, err := ioutil.ReadFile(filename)
+	if err != nil {
+		return nil, err
+	}
+	return Parse(string(b), fmap)
+}
+
+// MustParse is like Parse but panics if the template cannot be parsed.
+func MustParse(s string, fmap FormatterMap) *Template {
+	t, err := Parse(s, fmap)
+	if err != nil {
+		panic("template.MustParse error: " + err.Error())
+	}
+	return t
+}
+
+// MustParseFile is like ParseFile but panics if the file cannot be read
+// or the template cannot be parsed.
+func MustParseFile(filename string, fmap FormatterMap) *Template {
+	b, err := ioutil.ReadFile(filename)
+	if err != nil {
+		panic("template.MustParseFile error: " + err.Error())
+	}
+	return MustParse(string(b), fmap)
+}
diff --git a/third_party/gofrontend/libgo/go/old/template/template_test.go b/third_party/gofrontend/libgo/go/old/template/template_test.go
new file mode 100644
index 0000000..854a548
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/old/template/template_test.go
@@ -0,0 +1,810 @@
+// 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 template
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"strings"
+	"testing"
+)
+
+type Test struct {
+	in, out, err string
+}
+
+type T struct {
+	Item  string
+	Value string
+}
+
+type U struct {
+	Mp map[string]int
+}
+
+type S struct {
+	Header        string
+	HeaderPtr     *string
+	Integer       int
+	IntegerPtr    *int
+	NilPtr        *int
+	InnerT        T
+	InnerPointerT *T
+	Data          []T
+	Pdata         []*T
+	Empty         []*T
+	Emptystring   string
+	Null          []*T
+	Vec           []interface{}
+	True          bool
+	False         bool
+	Mp            map[string]string
+	JSON          interface{}
+	Innermap      U
+	Stringmap     map[string]string
+	Ptrmap        map[string]*string
+	Iface         interface{}
+	Ifaceptr      interface{}
+}
+
+func (s *S) PointerMethod() string { return "ptrmethod!" }
+
+func (s S) ValueMethod() string { return "valmethod!" }
+
+var t1 = T{"ItemNumber1", "ValueNumber1"}
+var t2 = T{"ItemNumber2", "ValueNumber2"}
+
+func uppercase(v interface{}) string {
+	s := v.(string)
+	t := ""
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		if 'a' <= c && c <= 'z' {
+			c = c + 'A' - 'a'
+		}
+		t += string(c)
+	}
+	return t
+}
+
+func plus1(v interface{}) string {
+	i := v.(int)
+	return fmt.Sprint(i + 1)
+}
+
+func writer(f func(interface{}) string) func(io.Writer, string, ...interface{}) {
+	return func(w io.Writer, format string, v ...interface{}) {
+		if len(v) != 1 {
+			panic("test writer expected one arg")
+		}
+		io.WriteString(w, f(v[0]))
+	}
+}
+
+func multiword(w io.Writer, format string, value ...interface{}) {
+	for _, v := range value {
+		fmt.Fprintf(w, "<%v>", v)
+	}
+}
+
+func printf(w io.Writer, format string, v ...interface{}) {
+	io.WriteString(w, fmt.Sprintf(v[0].(string), v[1:]...))
+}
+
+var formatters = FormatterMap{
+	"uppercase": writer(uppercase),
+	"+1":        writer(plus1),
+	"multiword": multiword,
+	"printf":    printf,
+}
+
+var tests = []*Test{
+	// Simple
+	{"", "", ""},
+	{"abc", "abc", ""},
+	{"abc\ndef\n", "abc\ndef\n", ""},
+	{" {.meta-left}   \n", "{", ""},
+	{" {.meta-right}   \n", "}", ""},
+	{" {.space}   \n", " ", ""},
+	{" {.tab}   \n", "\t", ""},
+	{"     {#comment}   \n", "", ""},
+	{"\tSome Text\t\n", "\tSome Text\t\n", ""},
+	{" {.meta-right} {.meta-right} {.meta-right} \n", " } } } \n", ""},
+
+	// Variables at top level
+	{
+		in: "{Header}={Integer}\n",
+
+		out: "Header=77\n",
+	},
+
+	{
+		in: "Pointers: {*HeaderPtr}={*IntegerPtr}\n",
+
+		out: "Pointers: Header=77\n",
+	},
+
+	{
+		in: "Stars but not pointers: {*Header}={*Integer}\n",
+
+		out: "Stars but not pointers: Header=77\n",
+	},
+
+	{
+		in: "nil pointer: {*NilPtr}={*Integer}\n",
+
+		out: "nil pointer: <nil>=77\n",
+	},
+
+	{
+		in: `{"Strings" ":"} {""} {"|"} {"\t\u0123 \x23\\"} {"\"}{\\"}`,
+
+		out: "Strings:  | \t\u0123 \x23\\ \"}{\\",
+	},
+
+	{
+		in: "{`Raw strings` `:`} {``} {`|`} {`\\t\\u0123 \\x23\\`} {`}{\\`}",
+
+		out: "Raw strings:  | \\t\\u0123 \\x23\\ }{\\",
+	},
+
+	{
+		in: "Characters: {'a'} {'\\u0123'} {' '} {'{'} {'|'} {'}'}",
+
+		out: "Characters: 97 291 32 123 124 125",
+	},
+
+	{
+		in: "Integers: {1} {-2} {+42} {0777} {0x0a}",
+
+		out: "Integers: 1 -2 42 511 10",
+	},
+
+	{
+		in: "Floats: {.5} {-.5} {1.1} {-2.2} {+42.1} {1e10} {1.2e-3} {1.2e3} {-1.2e3}",
+
+		out: "Floats: 0.5 -0.5 1.1 -2.2 42.1 1e+10 0.0012 1200 -1200",
+	},
+
+	// Method at top level
+	{
+		in: "ptrmethod={PointerMethod}\n",
+
+		out: "ptrmethod=ptrmethod!\n",
+	},
+
+	{
+		in: "valmethod={ValueMethod}\n",
+
+		out: "valmethod=valmethod!\n",
+	},
+
+	// Section
+	{
+		in: "{.section Data }\n" +
+			"some text for the section\n" +
+			"{.end}\n",
+
+		out: "some text for the section\n",
+	},
+	{
+		in: "{.section Data }\n" +
+			"{Header}={Integer}\n" +
+			"{.end}\n",
+
+		out: "Header=77\n",
+	},
+	{
+		in: "{.section Pdata }\n" +
+			"{Header}={Integer}\n" +
+			"{.end}\n",
+
+		out: "Header=77\n",
+	},
+	{
+		in: "{.section Pdata }\n" +
+			"data present\n" +
+			"{.or}\n" +
+			"data not present\n" +
+			"{.end}\n",
+
+		out: "data present\n",
+	},
+	{
+		in: "{.section Empty }\n" +
+			"data present\n" +
+			"{.or}\n" +
+			"data not present\n" +
+			"{.end}\n",
+
+		out: "data not present\n",
+	},
+	{
+		in: "{.section Null }\n" +
+			"data present\n" +
+			"{.or}\n" +
+			"data not present\n" +
+			"{.end}\n",
+
+		out: "data not present\n",
+	},
+	{
+		in: "{.section Pdata }\n" +
+			"{Header}={Integer}\n" +
+			"{.section @ }\n" +
+			"{Header}={Integer}\n" +
+			"{.end}\n" +
+			"{.end}\n",
+
+		out: "Header=77\n" +
+			"Header=77\n",
+	},
+
+	{
+		in: "{.section Data}{.end} {Header}\n",
+
+		out: " Header\n",
+	},
+
+	{
+		in: "{.section Integer}{@}{.end}",
+
+		out: "77",
+	},
+
+	// Repeated
+	{
+		in: "{.section Pdata }\n" +
+			"{.repeated section @ }\n" +
+			"{Item}={Value}\n" +
+			"{.end}\n" +
+			"{.end}\n",
+
+		out: "ItemNumber1=ValueNumber1\n" +
+			"ItemNumber2=ValueNumber2\n",
+	},
+	{
+		in: "{.section Pdata }\n" +
+			"{.repeated section @ }\n" +
+			"{Item}={Value}\n" +
+			"{.or}\n" +
+			"this should not appear\n" +
+			"{.end}\n" +
+			"{.end}\n",
+
+		out: "ItemNumber1=ValueNumber1\n" +
+			"ItemNumber2=ValueNumber2\n",
+	},
+	{
+		in: "{.section @ }\n" +
+			"{.repeated section Empty }\n" +
+			"{Item}={Value}\n" +
+			"{.or}\n" +
+			"this should appear: empty field\n" +
+			"{.end}\n" +
+			"{.end}\n",
+
+		out: "this should appear: empty field\n",
+	},
+	{
+		in: "{.repeated section Pdata }\n" +
+			"{Item}\n" +
+			"{.alternates with}\n" +
+			"is\nover\nmultiple\nlines\n" +
+			"{.end}\n",
+
+		out: "ItemNumber1\n" +
+			"is\nover\nmultiple\nlines\n" +
+			"ItemNumber2\n",
+	},
+	{
+		in: "{.repeated section Pdata }\n" +
+			"{Item}\n" +
+			"{.alternates with}\n" +
+			"is\nover\nmultiple\nlines\n" +
+			" {.end}\n",
+
+		out: "ItemNumber1\n" +
+			"is\nover\nmultiple\nlines\n" +
+			"ItemNumber2\n",
+	},
+	{
+		in: "{.section Pdata }\n" +
+			"{.repeated section @ }\n" +
+			"{Item}={Value}\n" +
+			"{.alternates with}DIVIDER\n" +
+			"{.or}\n" +
+			"this should not appear\n" +
+			"{.end}\n" +
+			"{.end}\n",
+
+		out: "ItemNumber1=ValueNumber1\n" +
+			"DIVIDER\n" +
+			"ItemNumber2=ValueNumber2\n",
+	},
+	{
+		in: "{.repeated section Vec }\n" +
+			"{@}\n" +
+			"{.end}\n",
+
+		out: "elt1\n" +
+			"elt2\n",
+	},
+	// Same but with a space before {.end}: was a bug.
+	{
+		in: "{.repeated section Vec }\n" +
+			"{@} {.end}\n",
+
+		out: "elt1 elt2 \n",
+	},
+	{
+		in: "{.repeated section Integer}{.end}",
+
+		err: "line 1: .repeated: cannot repeat Integer (type int)",
+	},
+
+	// Nested names
+	{
+		in: "{.section @ }\n" +
+			"{InnerT.Item}={InnerT.Value}\n" +
+			"{.end}",
+
+		out: "ItemNumber1=ValueNumber1\n",
+	},
+	{
+		in: "{.section @ }\n" +
+			"{InnerT.Item}={.section InnerT}{.section Value}{@}{.end}{.end}\n" +
+			"{.end}",
+
+		out: "ItemNumber1=ValueNumber1\n",
+	},
+
+	{
+		in: "{.section Emptystring}emptystring{.end}\n" +
+			"{.section Header}header{.end}\n",
+
+		out: "\nheader\n",
+	},
+
+	{
+		in: "{.section True}1{.or}2{.end}\n" +
+			"{.section False}3{.or}4{.end}\n",
+
+		out: "1\n4\n",
+	},
+
+	// Maps
+
+	{
+		in: "{Mp.mapkey}\n",
+
+		out: "Ahoy!\n",
+	},
+	{
+		in: "{Innermap.Mp.innerkey}\n",
+
+		out: "55\n",
+	},
+	{
+		in: "{.section Innermap}{.section Mp}{innerkey}{.end}{.end}\n",
+
+		out: "55\n",
+	},
+	{
+		in: "{.section JSON}{.repeated section maps}{a}{b}{.end}{.end}\n",
+
+		out: "1234\n",
+	},
+	{
+		in: "{Stringmap.stringkey1}\n",
+
+		out: "stringresult\n",
+	},
+	{
+		in: "{.repeated section Stringmap}\n" +
+			"{@}\n" +
+			"{.end}",
+
+		out: "stringresult\n" +
+			"stringresult\n",
+	},
+	{
+		in: "{.repeated section Stringmap}\n" +
+			"\t{@}\n" +
+			"{.end}",
+
+		out: "\tstringresult\n" +
+			"\tstringresult\n",
+	},
+	{
+		in: "{*Ptrmap.stringkey1}\n",
+
+		out: "pointedToString\n",
+	},
+	{
+		in: "{.repeated section Ptrmap}\n" +
+			"{*@}\n" +
+			"{.end}",
+
+		out: "pointedToString\n" +
+			"pointedToString\n",
+	},
+
+	// Interface values
+
+	{
+		in: "{Iface}",
+
+		out: "[1 2 3]",
+	},
+	{
+		in: "{.repeated section Iface}{@}{.alternates with} {.end}",
+
+		out: "1 2 3",
+	},
+	{
+		in: "{.section Iface}{@}{.end}",
+
+		out: "[1 2 3]",
+	},
+	{
+		in: "{.section Ifaceptr}{Item} {Value}{.end}",
+
+		out: "Item Value",
+	},
+}
+
+func TestAll(t *testing.T) {
+	// Parse
+	testAll(t, func(test *Test) (*Template, error) { return Parse(test.in, formatters) })
+	// ParseFile
+	f, err := ioutil.TempFile("", "template-test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		name := f.Name()
+		f.Close()
+		os.Remove(name)
+	}()
+	testAll(t, func(test *Test) (*Template, error) {
+		err := ioutil.WriteFile(f.Name(), []byte(test.in), 0600)
+		if err != nil {
+			t.Error("unexpected write error:", err)
+			return nil, err
+		}
+		return ParseFile(f.Name(), formatters)
+	})
+	// tmpl.ParseFile
+	testAll(t, func(test *Test) (*Template, error) {
+		err := ioutil.WriteFile(f.Name(), []byte(test.in), 0600)
+		if err != nil {
+			t.Error("unexpected write error:", err)
+			return nil, err
+		}
+		tmpl := New(formatters)
+		return tmpl, tmpl.ParseFile(f.Name())
+	})
+}
+
+func testAll(t *testing.T, parseFunc func(*Test) (*Template, error)) {
+	s := new(S)
+	// initialized by hand for clarity.
+	s.Header = "Header"
+	s.HeaderPtr = &s.Header
+	s.Integer = 77
+	s.IntegerPtr = &s.Integer
+	s.InnerT = t1
+	s.Data = []T{t1, t2}
+	s.Pdata = []*T{&t1, &t2}
+	s.Empty = []*T{}
+	s.Null = nil
+	s.Vec = []interface{}{"elt1", "elt2"}
+	s.True = true
+	s.False = false
+	s.Mp = make(map[string]string)
+	s.Mp["mapkey"] = "Ahoy!"
+	json.Unmarshal([]byte(`{"maps":[{"a":1,"b":2},{"a":3,"b":4}]}`), &s.JSON)
+	s.Innermap.Mp = make(map[string]int)
+	s.Innermap.Mp["innerkey"] = 55
+	s.Stringmap = make(map[string]string)
+	s.Stringmap["stringkey1"] = "stringresult" // the same value so repeated section is order-independent
+	s.Stringmap["stringkey2"] = "stringresult"
+	s.Ptrmap = make(map[string]*string)
+	x := "pointedToString"
+	s.Ptrmap["stringkey1"] = &x // the same value so repeated section is order-independent
+	s.Ptrmap["stringkey2"] = &x
+	s.Iface = []int{1, 2, 3}
+	s.Ifaceptr = &T{"Item", "Value"}
+
+	var buf bytes.Buffer
+	for _, test := range tests {
+		buf.Reset()
+		tmpl, err := parseFunc(test)
+		if err != nil {
+			t.Error("unexpected parse error: ", err)
+			continue
+		}
+		err = tmpl.Execute(&buf, s)
+		if test.err == "" {
+			if err != nil {
+				t.Error("unexpected execute error:", err)
+			}
+		} else {
+			if err == nil {
+				t.Errorf("expected execute error %q, got nil", test.err)
+			} else if err.Error() != test.err {
+				t.Errorf("expected execute error %q, got %q", test.err, err.Error())
+			}
+		}
+		if buf.String() != test.out {
+			t.Errorf("for %q: expected %q got %q", test.in, test.out, buf.String())
+		}
+	}
+}
+
+func TestMapDriverType(t *testing.T) {
+	mp := map[string]string{"footer": "Ahoy!"}
+	tmpl, err := Parse("template: {footer}", nil)
+	if err != nil {
+		t.Error("unexpected parse error:", err)
+	}
+	var b bytes.Buffer
+	err = tmpl.Execute(&b, mp)
+	if err != nil {
+		t.Error("unexpected execute error:", err)
+	}
+	s := b.String()
+	expect := "template: Ahoy!"
+	if s != expect {
+		t.Errorf("failed passing string as data: expected %q got %q", expect, s)
+	}
+}
+
+func TestMapNoEntry(t *testing.T) {
+	mp := make(map[string]int)
+	tmpl, err := Parse("template: {notthere}!", nil)
+	if err != nil {
+		t.Error("unexpected parse error:", err)
+	}
+	var b bytes.Buffer
+	err = tmpl.Execute(&b, mp)
+	if err != nil {
+		t.Error("unexpected execute error:", err)
+	}
+	s := b.String()
+	expect := "template: 0!"
+	if s != expect {
+		t.Errorf("failed passing string as data: expected %q got %q", expect, s)
+	}
+}
+
+func TestStringDriverType(t *testing.T) {
+	tmpl, err := Parse("template: {@}", nil)
+	if err != nil {
+		t.Error("unexpected parse error:", err)
+	}
+	var b bytes.Buffer
+	err = tmpl.Execute(&b, "hello")
+	if err != nil {
+		t.Error("unexpected execute error:", err)
+	}
+	s := b.String()
+	expect := "template: hello"
+	if s != expect {
+		t.Errorf("failed passing string as data: expected %q got %q", expect, s)
+	}
+}
+
+func TestTwice(t *testing.T) {
+	tmpl, err := Parse("template: {@}", nil)
+	if err != nil {
+		t.Error("unexpected parse error:", err)
+	}
+	var b bytes.Buffer
+	err = tmpl.Execute(&b, "hello")
+	if err != nil {
+		t.Error("unexpected parse error:", err)
+	}
+	s := b.String()
+	expect := "template: hello"
+	if s != expect {
+		t.Errorf("failed passing string as data: expected %q got %q", expect, s)
+	}
+	err = tmpl.Execute(&b, "hello")
+	if err != nil {
+		t.Error("unexpected parse error:", err)
+	}
+	s = b.String()
+	expect += expect
+	if s != expect {
+		t.Errorf("failed passing string as data: expected %q got %q", expect, s)
+	}
+}
+
+func TestCustomDelims(t *testing.T) {
+	// try various lengths.  zero should catch error.
+	for i := 0; i < 7; i++ {
+		for j := 0; j < 7; j++ {
+			tmpl := New(nil)
+			// first two chars deliberately the same to test equal left and right delims
+			ldelim := "$!#$%^&"[0:i]
+			rdelim := "$*&^%$!"[0:j]
+			tmpl.SetDelims(ldelim, rdelim)
+			// if braces, this would be template: {@}{.meta-left}{.meta-right}
+			text := "template: " +
+				ldelim + "@" + rdelim +
+				ldelim + ".meta-left" + rdelim +
+				ldelim + ".meta-right" + rdelim
+			err := tmpl.Parse(text)
+			if err != nil {
+				if i == 0 || j == 0 { // expected
+					continue
+				}
+				t.Error("unexpected parse error:", err)
+			} else if i == 0 || j == 0 {
+				t.Errorf("expected parse error for empty delimiter: %d %d %q %q", i, j, ldelim, rdelim)
+				continue
+			}
+			var b bytes.Buffer
+			err = tmpl.Execute(&b, "hello")
+			s := b.String()
+			if s != "template: hello"+ldelim+rdelim {
+				t.Errorf("failed delim check(%q %q) %q got %q", ldelim, rdelim, text, s)
+			}
+		}
+	}
+}
+
+// Test that a variable evaluates to the field itself and does not further indirection
+func TestVarIndirection(t *testing.T) {
+	s := new(S)
+	// initialized by hand for clarity.
+	s.InnerPointerT = &t1
+
+	var buf bytes.Buffer
+	input := "{.section @}{InnerPointerT}{.end}"
+	tmpl, err := Parse(input, nil)
+	if err != nil {
+		t.Fatal("unexpected parse error:", err)
+	}
+	err = tmpl.Execute(&buf, s)
+	if err != nil {
+		t.Fatal("unexpected execute error:", err)
+	}
+	expect := fmt.Sprintf("%v", &t1) // output should be hex address of t1
+	if buf.String() != expect {
+		t.Errorf("for %q: expected %q got %q", input, expect, buf.String())
+	}
+}
+
+func TestHTMLFormatterWithByte(t *testing.T) {
+	s := "Test string."
+	b := []byte(s)
+	var buf bytes.Buffer
+	HTMLFormatter(&buf, "", b)
+	bs := buf.String()
+	if bs != s {
+		t.Errorf("munged []byte, expected: %s got: %s", s, bs)
+	}
+}
+
+type UF struct {
+	I int
+	s string
+}
+
+func TestReferenceToUnexported(t *testing.T) {
+	u := &UF{3, "hello"}
+	var buf bytes.Buffer
+	input := "{.section @}{I}{s}{.end}"
+	tmpl, err := Parse(input, nil)
+	if err != nil {
+		t.Fatal("unexpected parse error:", err)
+	}
+	err = tmpl.Execute(&buf, u)
+	if err == nil {
+		t.Fatal("expected execute error, got none")
+	}
+	if strings.Index(err.Error(), "not exported") < 0 {
+		t.Fatal("expected unexported error; got", err)
+	}
+}
+
+var formatterTests = []Test{
+	{
+		in: "{Header|uppercase}={Integer|+1}\n" +
+			"{Header|html}={Integer|str}\n",
+
+		out: "HEADER=78\n" +
+			"Header=77\n",
+	},
+
+	{
+		in: "{Header|uppercase}={Integer Header|multiword}\n" +
+			"{Header|html}={Header Integer|multiword}\n" +
+			"{Header|html}={Header Integer}\n",
+
+		out: "HEADER=<77><Header>\n" +
+			"Header=<Header><77>\n" +
+			"Header=Header77\n",
+	},
+	{
+		in: "{Raw}\n" +
+			"{Raw|html}\n",
+
+		out: "a <&> b\n" +
+			"a &lt;&amp;&gt; b\n",
+	},
+	{
+		in:  "{Bytes}",
+		out: "hello",
+	},
+	{
+		in:  "{Raw|uppercase|html|html}",
+		out: "A &amp;lt;&amp;amp;&amp;gt; B",
+	},
+	{
+		in:  "{Header Integer|multiword|html}",
+		out: "&lt;Header&gt;&lt;77&gt;",
+	},
+	{
+		in:  "{Integer|no_formatter|html}",
+		err: `unknown formatter: "no_formatter"`,
+	},
+	{
+		in:  "{Integer|||||}", // empty string is a valid formatter
+		out: "77",
+	},
+	{
+		in:  `{"%.02f 0x%02X" 1.1 10|printf}`,
+		out: "1.10 0x0A",
+	},
+	{
+		in:  `{""|}{""||}{""|printf}`, // Issue #1896.
+		out: "",
+	},
+}
+
+func TestFormatters(t *testing.T) {
+	data := map[string]interface{}{
+		"Header":  "Header",
+		"Integer": 77,
+		"Raw":     "a <&> b",
+		"Bytes":   []byte("hello"),
+	}
+	for _, c := range formatterTests {
+		tmpl, err := Parse(c.in, formatters)
+		if err != nil {
+			if c.err == "" {
+				t.Error("unexpected parse error:", err)
+				continue
+			}
+			if strings.Index(err.Error(), c.err) < 0 {
+				t.Errorf("unexpected error: expected %q, got %q", c.err, err.Error())
+				continue
+			}
+		} else {
+			if c.err != "" {
+				t.Errorf("For %q, expected error, got none.", c.in)
+				continue
+			}
+			var buf bytes.Buffer
+			err = tmpl.Execute(&buf, data)
+			if err != nil {
+				t.Error("unexpected Execute error: ", err)
+				continue
+			}
+			actual := buf.String()
+			if actual != c.out {
+				t.Errorf("for %q: expected %q but got %q.", c.in, c.out, actual)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/dir.go b/third_party/gofrontend/libgo/go/os/dir.go
new file mode 100644
index 0000000..d811c9f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/dir.go
@@ -0,0 +1,102 @@
+// 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 os
+
+import (
+	"io"
+	"sync/atomic"
+	"syscall"
+	"unsafe"
+)
+
+//extern opendir
+func libc_opendir(*byte) *syscall.DIR
+
+//extern closedir
+func libc_closedir(*syscall.DIR) int
+
+// FIXME: pathconf returns long, not int.
+//extern pathconf
+func libc_pathconf(*byte, int) int
+
+func clen(n []byte) int {
+	for i := 0; i < len(n); i++ {
+		if n[i] == 0 {
+			return i
+		}
+	}
+	return len(n)
+}
+
+var nameMax int32
+
+func (file *File) readdirnames(n int) (names []string, err error) {
+	if file.dirinfo == nil {
+		p, err := syscall.BytePtrFromString(file.name)
+		if err != nil {
+			return nil, err
+		}
+
+		elen := int(atomic.LoadInt32(&nameMax))
+		if elen == 0 {
+			syscall.Entersyscall()
+			plen := libc_pathconf(p, syscall.PC_NAME_MAX)
+			syscall.Exitsyscall()
+			if plen < 1024 {
+				plen = 1024
+			}
+			var dummy syscall.Dirent
+			elen = int(unsafe.Offsetof(dummy.Name)) + plen + 1
+			atomic.StoreInt32(&nameMax, int32(elen))
+		}
+
+		syscall.Entersyscall()
+		r := libc_opendir(p)
+		errno := syscall.GetErrno()
+		syscall.Exitsyscall()
+		if r == nil {
+			return nil, &PathError{"opendir", file.name, errno}
+		}
+
+		file.dirinfo = new(dirInfo)
+		file.dirinfo.buf = make([]byte, elen)
+		file.dirinfo.dir = r
+	}
+
+	entryDirent := (*syscall.Dirent)(unsafe.Pointer(&file.dirinfo.buf[0]))
+
+	size := n
+	if size <= 0 {
+		size = 100
+		n = -1
+	}
+
+	names = make([]string, 0, size) // Empty with room to grow.
+
+	for n != 0 {
+		var dirent *syscall.Dirent
+		pr := &dirent
+		syscall.Entersyscall()
+		i := libc_readdir_r(file.dirinfo.dir, entryDirent, pr)
+		syscall.Exitsyscall()
+		if i != 0 {
+			return names, NewSyscallError("readdir_r", i)
+		}
+		if dirent == nil {
+			break // EOF
+		}
+		bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
+		var name = string(bytes[0:clen(bytes[:])])
+		if name == "." || name == ".." { // Useless names
+			continue
+		}
+		names = append(names, name)
+		n--
+	}
+	if n >= 0 && len(names) == 0 {
+		return names, io.EOF
+	}
+	return names, nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/dir_largefile.go b/third_party/gofrontend/libgo/go/os/dir_largefile.go
new file mode 100644
index 0000000..2555c7b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/dir_largefile.go
@@ -0,0 +1,13 @@
+// dir_largefile.go -- For systems which use the large file interface for
+// readdir_r.
+
+// 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.
+
+package os
+
+import "syscall"
+
+//extern readdir64_r
+func libc_readdir_r(*syscall.DIR, *syscall.Dirent, **syscall.Dirent) syscall.Errno
diff --git a/third_party/gofrontend/libgo/go/os/dir_plan9.go b/third_party/gofrontend/libgo/go/os/dir_plan9.go
new file mode 100644
index 0000000..8195c02
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/dir_plan9.go
@@ -0,0 +1,73 @@
+// 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 os
+
+import (
+	"io"
+	"syscall"
+)
+
+func (file *File) readdir(n int) ([]FileInfo, error) {
+	// If this file has no dirinfo, create one.
+	if file.dirinfo == nil {
+		file.dirinfo = new(dirInfo)
+	}
+	d := file.dirinfo
+	size := n
+	if size <= 0 {
+		size = 100
+		n = -1
+	}
+	fi := make([]FileInfo, 0, size) // Empty with room to grow.
+	for n != 0 {
+		// Refill the buffer if necessary.
+		if d.bufp >= d.nbuf {
+			nb, err := file.Read(d.buf[:])
+
+			// Update the buffer state before checking for errors.
+			d.bufp, d.nbuf = 0, nb
+
+			if err != nil {
+				if err == io.EOF {
+					break
+				}
+				return fi, &PathError{"readdir", file.name, err}
+			}
+			if nb < syscall.STATFIXLEN {
+				return fi, &PathError{"readdir", file.name, syscall.ErrShortStat}
+			}
+		}
+
+		// Get a record from the buffer.
+		b := d.buf[d.bufp:]
+		m := int(uint16(b[0])|uint16(b[1])<<8) + 2
+		if m < syscall.STATFIXLEN {
+			return fi, &PathError{"readdir", file.name, syscall.ErrShortStat}
+		}
+
+		dir, err := syscall.UnmarshalDir(b[:m])
+		if err != nil {
+			return fi, &PathError{"readdir", file.name, err}
+		}
+		fi = append(fi, fileInfoFromStat(dir))
+
+		d.bufp += m
+		n--
+	}
+
+	if n >= 0 && len(fi) == 0 {
+		return fi, io.EOF
+	}
+	return fi, nil
+}
+
+func (file *File) readdirnames(n int) (names []string, err error) {
+	fi, err := file.Readdir(n)
+	names = make([]string, len(fi))
+	for i := range fi {
+		names[i] = fi[i].Name()
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/os/dir_regfile.go b/third_party/gofrontend/libgo/go/os/dir_regfile.go
new file mode 100644
index 0000000..e5f7c57
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/dir_regfile.go
@@ -0,0 +1,13 @@
+// dir_regfile.go -- For systems which do not use the large file interface
+// for readdir_r.
+
+// 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.
+
+package os
+
+import "syscall"
+
+//extern readdir_r
+func libc_readdir_r(*syscall.DIR, *syscall.Dirent, **syscall.Dirent) syscall.Errno
diff --git a/third_party/gofrontend/libgo/go/os/dir_unix.go b/third_party/gofrontend/libgo/go/os/dir_unix.go
new file mode 100644
index 0000000..d353e40
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/dir_unix.go
@@ -0,0 +1,58 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package os
+
+import (
+	"io"
+	"syscall"
+)
+
+const (
+	blockSize = 4096
+)
+
+func (f *File) readdirnames(n int) (names []string, err error) {
+	// If this file has no dirinfo, create one.
+	if f.dirinfo == nil {
+		f.dirinfo = new(dirInfo)
+		// The buffer must be at least a block long.
+		f.dirinfo.buf = make([]byte, blockSize)
+	}
+	d := f.dirinfo
+
+	size := n
+	if size <= 0 {
+		size = 100
+		n = -1
+	}
+
+	names = make([]string, 0, size) // Empty with room to grow.
+	for n != 0 {
+		// Refill the buffer if necessary
+		if d.bufp >= d.nbuf {
+			d.bufp = 0
+			var errno error
+			d.nbuf, errno = syscall.ReadDirent(f.fd, d.buf)
+			if errno != nil {
+				return names, NewSyscallError("readdirent", errno)
+			}
+			if d.nbuf <= 0 {
+				break // EOF
+			}
+		}
+
+		// Drain the buffer
+		var nb, nc int
+		nb, nc, names = syscall.ParseDirent(d.buf[d.bufp:d.nbuf], n, names)
+		d.bufp += nb
+		n -= nc
+	}
+	if n >= 0 && len(names) == 0 {
+		return names, io.EOF
+	}
+	return names, nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/doc.go b/third_party/gofrontend/libgo/go/os/doc.go
new file mode 100644
index 0000000..389a8eb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/doc.go
@@ -0,0 +1,135 @@
+// 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 os
+
+import "time"
+
+// FindProcess looks for a running process by its pid.
+// The Process it returns can be used to obtain information
+// about the underlying operating system process.
+func FindProcess(pid int) (p *Process, err error) {
+	return findProcess(pid)
+}
+
+// StartProcess starts a new process with the program, arguments and attributes
+// specified by name, argv and attr.
+//
+// StartProcess is a low-level interface. The os/exec package provides
+// higher-level interfaces.
+//
+// If there is an error, it will be of type *PathError.
+func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
+	return startProcess(name, argv, attr)
+}
+
+// Release releases any resources associated with the Process p,
+// rendering it unusable in the future.
+// Release only needs to be called if Wait is not.
+func (p *Process) Release() error {
+	return p.release()
+}
+
+// Kill causes the Process to exit immediately.
+func (p *Process) Kill() error {
+	return p.kill()
+}
+
+// Wait waits for the Process to exit, and then returns a
+// ProcessState describing its status and an error, if any.
+// Wait releases any resources associated with the Process.
+// On most operating systems, the Process must be a child
+// of the current process or an error will be returned.
+func (p *Process) Wait() (*ProcessState, error) {
+	return p.wait()
+}
+
+// Signal sends a signal to the Process.
+// Sending Interrupt on Windows is not implemented.
+func (p *Process) Signal(sig Signal) error {
+	return p.signal(sig)
+}
+
+// UserTime returns the user CPU time of the exited process and its children.
+func (p *ProcessState) UserTime() time.Duration {
+	return p.userTime()
+}
+
+// SystemTime returns the system CPU time of the exited process and its children.
+func (p *ProcessState) SystemTime() time.Duration {
+	return p.systemTime()
+}
+
+// Exited reports whether the program has exited.
+func (p *ProcessState) Exited() bool {
+	return p.exited()
+}
+
+// Success reports whether the program exited successfully,
+// such as with exit status 0 on Unix.
+func (p *ProcessState) Success() bool {
+	return p.success()
+}
+
+// Sys returns system-dependent exit information about
+// the process.  Convert it to the appropriate underlying
+// type, such as syscall.WaitStatus on Unix, to access its contents.
+func (p *ProcessState) Sys() interface{} {
+	return p.sys()
+}
+
+// SysUsage returns system-dependent resource usage information about
+// the exited process.  Convert it to the appropriate underlying
+// type, such as *syscall.Rusage on Unix, to access its contents.
+// (On Unix, *syscall.Rusage matches struct rusage as defined in the
+// getrusage(2) manual page.)
+func (p *ProcessState) SysUsage() interface{} {
+	return p.sysUsage()
+}
+
+// Hostname returns the host name reported by the kernel.
+func Hostname() (name string, err error) {
+	return hostname()
+}
+
+// Readdir reads the contents of the directory associated with file and
+// returns a slice of up to n FileInfo values, as would be returned
+// by Lstat, in directory order. Subsequent calls on the same file will yield
+// further FileInfos.
+//
+// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
+// Readdir returns an empty slice, it will return a non-nil error
+// explaining why. At the end of a directory, the error is io.EOF.
+//
+// If n <= 0, Readdir returns all the FileInfo from the directory in
+// a single slice. In this case, if Readdir succeeds (reads all
+// the way to the end of the directory), it returns the slice and a
+// nil error. If it encounters an error before the end of the
+// directory, Readdir returns the FileInfo read until that point
+// and a non-nil error.
+func (f *File) Readdir(n int) (fi []FileInfo, err error) {
+	if f == nil {
+		return nil, ErrInvalid
+	}
+	return f.readdir(n)
+}
+
+// Readdirnames reads and returns a slice of names from the directory f.
+//
+// If n > 0, Readdirnames returns at most n names. In this case, if
+// Readdirnames returns an empty slice, it will return a non-nil error
+// explaining why. At the end of a directory, the error is io.EOF.
+//
+// If n <= 0, Readdirnames returns all the names from the directory in
+// a single slice. In this case, if Readdirnames succeeds (reads all
+// the way to the end of the directory), it returns the slice and a
+// nil error. If it encounters an error before the end of the
+// directory, Readdirnames returns the names read until that point and
+// a non-nil error.
+func (f *File) Readdirnames(n int) (names []string, err error) {
+	if f == nil {
+		return nil, ErrInvalid
+	}
+	return f.readdirnames(n)
+}
diff --git a/third_party/gofrontend/libgo/go/os/env.go b/third_party/gofrontend/libgo/go/os/env.go
new file mode 100644
index 0000000..db7fc72
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/env.go
@@ -0,0 +1,103 @@
+// Copyright 2010 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.
+
+// General environment variables.
+
+package os
+
+import "syscall"
+
+// Expand replaces ${var} or $var in the string based on the mapping function.
+// For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv).
+func Expand(s string, mapping func(string) string) string {
+	buf := make([]byte, 0, 2*len(s))
+	// ${} is all ASCII, so bytes are fine for this operation.
+	i := 0
+	for j := 0; j < len(s); j++ {
+		if s[j] == '$' && j+1 < len(s) {
+			buf = append(buf, s[i:j]...)
+			name, w := getShellName(s[j+1:])
+			buf = append(buf, mapping(name)...)
+			j += w
+			i = j + 1
+		}
+	}
+	return string(buf) + s[i:]
+}
+
+// ExpandEnv replaces ${var} or $var in the string according to the values
+// of the current environment variables.  References to undefined
+// variables are replaced by the empty string.
+func ExpandEnv(s string) string {
+	return Expand(s, Getenv)
+}
+
+// isSpellSpecialVar reports whether the character identifies a special
+// shell variable such as $*.
+func isShellSpecialVar(c uint8) bool {
+	switch c {
+	case '*', '#', '$', '@', '!', '?', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+		return true
+	}
+	return false
+}
+
+// isAlphaNum reports whether the byte is an ASCII letter, number, or underscore
+func isAlphaNum(c uint8) bool {
+	return c == '_' || '0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
+}
+
+// getName returns the name that begins the string and the number of bytes
+// consumed to extract it.  If the name is enclosed in {}, it's part of a ${}
+// expansion and two more bytes are needed than the length of the name.
+func getShellName(s string) (string, int) {
+	switch {
+	case s[0] == '{':
+		if len(s) > 2 && isShellSpecialVar(s[1]) && s[2] == '}' {
+			return s[1:2], 3
+		}
+		// Scan to closing brace
+		for i := 1; i < len(s); i++ {
+			if s[i] == '}' {
+				return s[1:i], i + 1
+			}
+		}
+		return "", 1 // Bad syntax; just eat the brace.
+	case isShellSpecialVar(s[0]):
+		return s[0:1], 1
+	}
+	// Scan alphanumerics.
+	var i int
+	for i = 0; i < len(s) && isAlphaNum(s[i]); i++ {
+	}
+	return s[:i], i
+}
+
+// Getenv retrieves the value of the environment variable named by the key.
+// It returns the value, which will be empty if the variable is not present.
+func Getenv(key string) string {
+	v, _ := syscall.Getenv(key)
+	return v
+}
+
+// Setenv sets the value of the environment variable named by the key.
+// It returns an error, if any.
+func Setenv(key, value string) error {
+	err := syscall.Setenv(key, value)
+	if err != nil {
+		return NewSyscallError("setenv", err)
+	}
+	return nil
+}
+
+// Clearenv deletes all environment variables.
+func Clearenv() {
+	syscall.Clearenv()
+}
+
+// Environ returns a copy of strings representing the environment,
+// in the form "key=value".
+func Environ() []string {
+	return syscall.Environ()
+}
diff --git a/third_party/gofrontend/libgo/go/os/env_test.go b/third_party/gofrontend/libgo/go/os/env_test.go
new file mode 100644
index 0000000..991fa4d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/env_test.go
@@ -0,0 +1,70 @@
+// Copyright 2010 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 os_test
+
+import (
+	. "os"
+	"reflect"
+	"testing"
+)
+
+// testGetenv gives us a controlled set of variables for testing Expand.
+func testGetenv(s string) string {
+	switch s {
+	case "*":
+		return "all the args"
+	case "#":
+		return "NARGS"
+	case "$":
+		return "PID"
+	case "1":
+		return "ARGUMENT1"
+	case "HOME":
+		return "/usr/gopher"
+	case "H":
+		return "(Value of H)"
+	case "home_1":
+		return "/usr/foo"
+	case "_":
+		return "underscore"
+	}
+	return ""
+}
+
+var expandTests = []struct {
+	in, out string
+}{
+	{"", ""},
+	{"$*", "all the args"},
+	{"$$", "PID"},
+	{"${*}", "all the args"},
+	{"$1", "ARGUMENT1"},
+	{"${1}", "ARGUMENT1"},
+	{"now is the time", "now is the time"},
+	{"$HOME", "/usr/gopher"},
+	{"$home_1", "/usr/foo"},
+	{"${HOME}", "/usr/gopher"},
+	{"${H}OME", "(Value of H)OME"},
+	{"A$$$#$1$H$home_1*B", "APIDNARGSARGUMENT1(Value of H)/usr/foo*B"},
+}
+
+func TestExpand(t *testing.T) {
+	for _, test := range expandTests {
+		result := Expand(test.in, testGetenv)
+		if result != test.out {
+			t.Errorf("Expand(%q)=%q; expected %q", test.in, result, test.out)
+		}
+	}
+}
+
+func TestConsistentEnviron(t *testing.T) {
+	e0 := Environ()
+	for i := 0; i < 10; i++ {
+		e1 := Environ()
+		if !reflect.DeepEqual(e0, e1) {
+			t.Fatalf("environment changed")
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/env_unix_test.go b/third_party/gofrontend/libgo/go/os/env_unix_test.go
new file mode 100644
index 0000000..5ec07ee
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/env_unix_test.go
@@ -0,0 +1,30 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package os_test
+
+import (
+	. "os"
+	"testing"
+)
+
+var setenvEinvalTests = []struct {
+	k, v string
+}{
+	{"", ""},      // empty key
+	{"k=v", ""},   // '=' in key
+	{"\x00", ""},  // '\x00' in key
+	{"k", "\x00"}, // '\x00' in value
+}
+
+func TestSetenvUnixEinval(t *testing.T) {
+	for _, tt := range setenvEinvalTests {
+		err := Setenv(tt.k, tt.v)
+		if err == nil {
+			t.Errorf(`Setenv(%q, %q) == nil, want error`, tt.k, tt.v)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/error.go b/third_party/gofrontend/libgo/go/os/error.go
new file mode 100644
index 0000000..8810e69
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/error.go
@@ -0,0 +1,65 @@
+// 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 os
+
+import (
+	"errors"
+)
+
+// Portable analogs of some common system call errors.
+var (
+	ErrInvalid    = errors.New("invalid argument")
+	ErrPermission = errors.New("permission denied")
+	ErrExist      = errors.New("file already exists")
+	ErrNotExist   = errors.New("file does not exist")
+)
+
+// PathError records an error and the operation and file path that caused it.
+type PathError struct {
+	Op   string
+	Path string
+	Err  error
+}
+
+func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+	Syscall string
+	Err     error
+}
+
+func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() }
+
+// NewSyscallError returns, as an error, a new SyscallError
+// with the given system call name and error details.
+// As a convenience, if err is nil, NewSyscallError returns nil.
+func NewSyscallError(syscall string, err error) error {
+	if err == nil {
+		return nil
+	}
+	return &SyscallError{syscall, err}
+}
+
+// IsExist returns a boolean indicating whether the error is known to report
+// that a file or directory already exists. It is satisfied by ErrExist as
+// well as some syscall errors.
+func IsExist(err error) bool {
+	return isExist(err)
+}
+
+// IsNotExist returns a boolean indicating whether the error is known to
+// report that a file or directory does not exist. It is satisfied by
+// ErrNotExist as well as some syscall errors.
+func IsNotExist(err error) bool {
+	return isNotExist(err)
+}
+
+// IsPermission returns a boolean indicating whether the error is known to
+// report that permission is denied. It is satisfied by ErrPermission as well
+// as some syscall errors.
+func IsPermission(err error) bool {
+	return isPermission(err)
+}
diff --git a/third_party/gofrontend/libgo/go/os/error_plan9.go b/third_party/gofrontend/libgo/go/os/error_plan9.go
new file mode 100644
index 0000000..85260c8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/error_plan9.go
@@ -0,0 +1,53 @@
+// 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.
+
+package os
+
+func isExist(err error) bool {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
+		err = pe.Err
+	}
+	return contains(err.Error(), " exists")
+}
+
+func isNotExist(err error) bool {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
+		err = pe.Err
+	}
+	return contains(err.Error(), "does not exist")
+}
+
+func isPermission(err error) bool {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
+		err = pe.Err
+	}
+	return contains(err.Error(), "permission denied")
+}
+
+// contains is a local version of strings.Contains. It knows len(sep) > 1.
+func contains(s, sep string) bool {
+	n := len(sep)
+	c := sep[0]
+	for i := 0; i+n <= len(s); i++ {
+		if s[i] == c && s[i:i+n] == sep {
+			return true
+		}
+	}
+	return false
+}
diff --git a/third_party/gofrontend/libgo/go/os/error_test.go b/third_party/gofrontend/libgo/go/os/error_test.go
new file mode 100644
index 0000000..02ed235
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/error_test.go
@@ -0,0 +1,132 @@
+// 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 os_test
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"testing"
+)
+
+func TestErrIsExist(t *testing.T) {
+	f, err := ioutil.TempFile("", "_Go_ErrIsExist")
+	if err != nil {
+		t.Fatalf("open ErrIsExist tempfile: %s", err)
+		return
+	}
+	defer os.Remove(f.Name())
+	defer f.Close()
+	f2, err := os.OpenFile(f.Name(), os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
+	if err == nil {
+		f2.Close()
+		t.Fatal("Open should have failed")
+		return
+	}
+	if s := checkErrorPredicate("os.IsExist", os.IsExist, err); s != "" {
+		t.Fatal(s)
+		return
+	}
+}
+
+func testErrNotExist(name string) string {
+	f, err := os.Open(name)
+	if err == nil {
+		f.Close()
+		return "Open should have failed"
+	}
+	if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err); s != "" {
+		return s
+	}
+
+	err = os.Chdir(name)
+	if err == nil {
+		return "Chdir should have failed"
+	}
+	if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err); s != "" {
+		return s
+	}
+	return ""
+}
+
+func TestErrIsNotExist(t *testing.T) {
+	tmpDir, err := ioutil.TempDir("", "_Go_ErrIsNotExist")
+	if err != nil {
+		t.Fatalf("create ErrIsNotExist tempdir: %s", err)
+		return
+	}
+	defer os.RemoveAll(tmpDir)
+
+	name := filepath.Join(tmpDir, "NotExists")
+	if s := testErrNotExist(name); s != "" {
+		t.Fatal(s)
+		return
+	}
+
+	name = filepath.Join(name, "NotExists2")
+	if s := testErrNotExist(name); s != "" {
+		t.Fatal(s)
+		return
+	}
+}
+
+func checkErrorPredicate(predName string, pred func(error) bool, err error) string {
+	if !pred(err) {
+		return fmt.Sprintf("%s does not work as expected for %#v", predName, err)
+	}
+	return ""
+}
+
+var isExistTests = []struct {
+	err   error
+	is    bool
+	isnot bool
+}{
+	{&os.PathError{Err: os.ErrInvalid}, false, false},
+	{&os.PathError{Err: os.ErrPermission}, false, false},
+	{&os.PathError{Err: os.ErrExist}, true, false},
+	{&os.PathError{Err: os.ErrNotExist}, false, true},
+	{&os.LinkError{Err: os.ErrInvalid}, false, false},
+	{&os.LinkError{Err: os.ErrPermission}, false, false},
+	{&os.LinkError{Err: os.ErrExist}, true, false},
+	{&os.LinkError{Err: os.ErrNotExist}, false, true},
+	{nil, false, false},
+}
+
+func TestIsExist(t *testing.T) {
+	for _, tt := range isExistTests {
+		if is := os.IsExist(tt.err); is != tt.is {
+			t.Errorf("os.IsExist(%T %v) = %v, want %v", tt.err, tt.err, is, tt.is)
+		}
+		if isnot := os.IsNotExist(tt.err); isnot != tt.isnot {
+			t.Errorf("os.IsNotExist(%T %v) = %v, want %v", tt.err, tt.err, isnot, tt.isnot)
+		}
+	}
+}
+
+func TestErrPathNUL(t *testing.T) {
+	f, err := ioutil.TempFile("", "_Go_ErrPathNUL\x00")
+	if err == nil {
+		f.Close()
+		t.Fatal("TempFile should have failed")
+	}
+	f, err = ioutil.TempFile("", "_Go_ErrPathNUL")
+	if err != nil {
+		t.Fatalf("open ErrPathNUL tempfile: %s", err)
+	}
+	defer os.Remove(f.Name())
+	defer f.Close()
+	f2, err := os.OpenFile(f.Name(), os.O_RDWR, 0600)
+	if err != nil {
+		t.Fatalf("open ErrPathNUL: %s", err)
+	}
+	f2.Close()
+	f2, err = os.OpenFile(f.Name()+"\x00", os.O_RDWR, 0600)
+	if err == nil {
+		f2.Close()
+		t.Fatal("Open should have failed")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/error_unix.go b/third_party/gofrontend/libgo/go/os/error_unix.go
new file mode 100644
index 0000000..f2aabbb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/error_unix.go
@@ -0,0 +1,45 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package os
+
+import "syscall"
+
+func isExist(err error) bool {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
+		err = pe.Err
+	}
+	return err == syscall.EEXIST || err == ErrExist
+}
+
+func isNotExist(err error) bool {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
+		err = pe.Err
+	}
+	return err == syscall.ENOENT || err == ErrNotExist
+}
+
+func isPermission(err error) bool {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
+		err = pe.Err
+	}
+	return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission
+}
diff --git a/third_party/gofrontend/libgo/go/os/error_windows.go b/third_party/gofrontend/libgo/go/os/error_windows.go
new file mode 100644
index 0000000..83db6c0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/error_windows.go
@@ -0,0 +1,45 @@
+// 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 os
+
+import "syscall"
+
+func isExist(err error) bool {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
+		err = pe.Err
+	}
+	return err == syscall.ERROR_ALREADY_EXISTS ||
+		err == syscall.ERROR_FILE_EXISTS || err == ErrExist
+}
+
+func isNotExist(err error) bool {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
+		err = pe.Err
+	}
+	return err == syscall.ERROR_FILE_NOT_FOUND ||
+		err == syscall.ERROR_PATH_NOT_FOUND || err == ErrNotExist
+}
+
+func isPermission(err error) bool {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
+		err = pe.Err
+	}
+	return err == syscall.ERROR_ACCESS_DENIED || err == ErrPermission
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec.go b/third_party/gofrontend/libgo/go/os/exec.go
new file mode 100644
index 0000000..5aea309
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec.go
@@ -0,0 +1,70 @@
+// 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 os
+
+import (
+	"runtime"
+	"sync/atomic"
+	"syscall"
+)
+
+// Process stores the information about a process created by StartProcess.
+type Process struct {
+	Pid    int
+	handle uintptr
+	isdone uint32 // process has been successfully waited on, non zero if true
+}
+
+func newProcess(pid int, handle uintptr) *Process {
+	p := &Process{Pid: pid, handle: handle}
+	runtime.SetFinalizer(p, (*Process).Release)
+	return p
+}
+
+func (p *Process) setDone() {
+	atomic.StoreUint32(&p.isdone, 1)
+}
+
+func (p *Process) done() bool {
+	return atomic.LoadUint32(&p.isdone) > 0
+}
+
+// ProcAttr holds the attributes that will be applied to a new process
+// started by StartProcess.
+type ProcAttr struct {
+	// If Dir is non-empty, the child changes into the directory before
+	// creating the process.
+	Dir string
+	// If Env is non-nil, it gives the environment variables for the
+	// new process in the form returned by Environ.
+	// If it is nil, the result of Environ will be used.
+	Env []string
+	// Files specifies the open files inherited by the new process.  The
+	// first three entries correspond to standard input, standard output, and
+	// standard error.  An implementation may support additional entries,
+	// depending on the underlying operating system.  A nil entry corresponds
+	// to that file being closed when the process starts.
+	Files []*File
+
+	// Operating system-specific process creation attributes.
+	// Note that setting this field means that your program
+	// may not execute properly or even compile on some
+	// operating systems.
+	Sys *syscall.SysProcAttr
+}
+
+// A Signal represents an operating system signal.
+// The usual underlying implementation is operating system-dependent:
+// on Unix it is syscall.Signal.
+type Signal interface {
+	String() string
+	Signal() // to distinguish from other Stringers
+}
+
+// Getpid returns the process id of the caller.
+func Getpid() int { return syscall.Getpid() }
+
+// Getppid returns the process id of the caller's parent.
+func Getppid() int { return syscall.Getppid() }
diff --git a/third_party/gofrontend/libgo/go/os/exec/exec.go b/third_party/gofrontend/libgo/go/os/exec/exec.go
new file mode 100644
index 0000000..a70ed0d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec/exec.go
@@ -0,0 +1,493 @@
+// 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 exec runs external commands. It wraps os.StartProcess to make it
+// easier to remap stdin and stdout, connect I/O with pipes, and do other
+// adjustments.
+package exec
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"strings"
+	"sync"
+	"syscall"
+)
+
+// Error records the name of a binary that failed to be executed
+// and the reason it failed.
+type Error struct {
+	Name string
+	Err  error
+}
+
+func (e *Error) Error() string {
+	return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error()
+}
+
+// Cmd represents an external command being prepared or run.
+type Cmd struct {
+	// Path is the path of the command to run.
+	//
+	// This is the only field that must be set to a non-zero
+	// value. If Path is relative, it is evaluated relative
+	// to Dir.
+	Path string
+
+	// Args holds command line arguments, including the command as Args[0].
+	// If the Args field is empty or nil, Run uses {Path}.
+	//
+	// In typical use, both Path and Args are set by calling Command.
+	Args []string
+
+	// Env specifies the environment of the process.
+	// If Env is nil, Run uses the current process's environment.
+	Env []string
+
+	// Dir specifies the working directory of the command.
+	// If Dir is the empty string, Run runs the command in the
+	// calling process's current directory.
+	Dir string
+
+	// Stdin specifies the process's standard input. If Stdin is
+	// nil, the process reads from the null device (os.DevNull).
+	Stdin io.Reader
+
+	// Stdout and Stderr specify the process's standard output and error.
+	//
+	// If either is nil, Run connects the corresponding file descriptor
+	// to the null device (os.DevNull).
+	//
+	// If Stdout and Stderr are the same writer, at most one
+	// goroutine at a time will call Write.
+	Stdout io.Writer
+	Stderr io.Writer
+
+	// ExtraFiles specifies additional open files to be inherited by the
+	// new process. It does not include standard input, standard output, or
+	// standard error. If non-nil, entry i becomes file descriptor 3+i.
+	//
+	// BUG: on OS X 10.6, child processes may sometimes inherit unwanted fds.
+	// http://golang.org/issue/2603
+	ExtraFiles []*os.File
+
+	// SysProcAttr holds optional, operating system-specific attributes.
+	// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
+	SysProcAttr *syscall.SysProcAttr
+
+	// Process is the underlying process, once started.
+	Process *os.Process
+
+	// ProcessState contains information about an exited process,
+	// available after a call to Wait or Run.
+	ProcessState *os.ProcessState
+
+	lookPathErr     error // LookPath error, if any.
+	finished        bool  // when Wait was called
+	childFiles      []*os.File
+	closeAfterStart []io.Closer
+	closeAfterWait  []io.Closer
+	goroutine       []func() error
+	errch           chan error // one send per goroutine
+}
+
+// Command returns the Cmd struct to execute the named program with
+// the given arguments.
+//
+// It sets only the Path and Args in the returned structure.
+//
+// If name contains no path separators, Command uses LookPath to
+// resolve the path to a complete name if possible. Otherwise it uses
+// name directly.
+//
+// The returned Cmd's Args field is constructed from the command name
+// followed by the elements of arg, so arg should not include the
+// command name itself. For example, Command("echo", "hello")
+func Command(name string, arg ...string) *Cmd {
+	cmd := &Cmd{
+		Path: name,
+		Args: append([]string{name}, arg...),
+	}
+	if filepath.Base(name) == name {
+		if lp, err := LookPath(name); err != nil {
+			cmd.lookPathErr = err
+		} else {
+			cmd.Path = lp
+		}
+	}
+	return cmd
+}
+
+// interfaceEqual protects against panics from doing equality tests on
+// two interfaces with non-comparable underlying types.
+func interfaceEqual(a, b interface{}) bool {
+	defer func() {
+		recover()
+	}()
+	return a == b
+}
+
+func (c *Cmd) envv() []string {
+	if c.Env != nil {
+		return c.Env
+	}
+	return os.Environ()
+}
+
+func (c *Cmd) argv() []string {
+	if len(c.Args) > 0 {
+		return c.Args
+	}
+	return []string{c.Path}
+}
+
+func (c *Cmd) stdin() (f *os.File, err error) {
+	if c.Stdin == nil {
+		f, err = os.Open(os.DevNull)
+		if err != nil {
+			return
+		}
+		c.closeAfterStart = append(c.closeAfterStart, f)
+		return
+	}
+
+	if f, ok := c.Stdin.(*os.File); ok {
+		return f, nil
+	}
+
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return
+	}
+
+	c.closeAfterStart = append(c.closeAfterStart, pr)
+	c.closeAfterWait = append(c.closeAfterWait, pw)
+	c.goroutine = append(c.goroutine, func() error {
+		_, err := io.Copy(pw, c.Stdin)
+		if err1 := pw.Close(); err == nil {
+			err = err1
+		}
+		return err
+	})
+	return pr, nil
+}
+
+func (c *Cmd) stdout() (f *os.File, err error) {
+	return c.writerDescriptor(c.Stdout)
+}
+
+func (c *Cmd) stderr() (f *os.File, err error) {
+	if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
+		return c.childFiles[1], nil
+	}
+	return c.writerDescriptor(c.Stderr)
+}
+
+func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) {
+	if w == nil {
+		f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
+		if err != nil {
+			return
+		}
+		c.closeAfterStart = append(c.closeAfterStart, f)
+		return
+	}
+
+	if f, ok := w.(*os.File); ok {
+		return f, nil
+	}
+
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return
+	}
+
+	c.closeAfterStart = append(c.closeAfterStart, pw)
+	c.closeAfterWait = append(c.closeAfterWait, pr)
+	c.goroutine = append(c.goroutine, func() error {
+		_, err := io.Copy(w, pr)
+		return err
+	})
+	return pw, nil
+}
+
+func (c *Cmd) closeDescriptors(closers []io.Closer) {
+	for _, fd := range closers {
+		fd.Close()
+	}
+}
+
+// Run starts the specified command and waits for it to complete.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the command fails to run or doesn't complete successfully, the
+// error is of type *ExitError. Other error types may be
+// returned for I/O problems.
+func (c *Cmd) Run() error {
+	if err := c.Start(); err != nil {
+		return err
+	}
+	return c.Wait()
+}
+
+// lookExtensions finds windows executable by its dir and path.
+// It uses LookPath to try appropriate extensions.
+// lookExtensions does not search PATH, instead it converts `prog` into `.\prog`.
+func lookExtensions(path, dir string) (string, error) {
+	if filepath.Base(path) == path {
+		path = filepath.Join(".", path)
+	}
+	if dir == "" {
+		return LookPath(path)
+	}
+	if filepath.VolumeName(path) != "" {
+		return LookPath(path)
+	}
+	if len(path) > 1 && os.IsPathSeparator(path[0]) {
+		return LookPath(path)
+	}
+	dirandpath := filepath.Join(dir, path)
+	// We assume that LookPath will only add file extension.
+	lp, err := LookPath(dirandpath)
+	if err != nil {
+		return "", err
+	}
+	ext := strings.TrimPrefix(lp, dirandpath)
+	return path + ext, nil
+}
+
+// Start starts the specified command but does not wait for it to complete.
+//
+// The Wait method will return the exit code and release associated resources
+// once the command exits.
+func (c *Cmd) Start() error {
+	if c.lookPathErr != nil {
+		c.closeDescriptors(c.closeAfterStart)
+		c.closeDescriptors(c.closeAfterWait)
+		return c.lookPathErr
+	}
+	if runtime.GOOS == "windows" {
+		lp, err := lookExtensions(c.Path, c.Dir)
+		if err != nil {
+			c.closeDescriptors(c.closeAfterStart)
+			c.closeDescriptors(c.closeAfterWait)
+			return err
+		}
+		c.Path = lp
+	}
+	if c.Process != nil {
+		return errors.New("exec: already started")
+	}
+
+	type F func(*Cmd) (*os.File, error)
+	for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
+		fd, err := setupFd(c)
+		if err != nil {
+			c.closeDescriptors(c.closeAfterStart)
+			c.closeDescriptors(c.closeAfterWait)
+			return err
+		}
+		c.childFiles = append(c.childFiles, fd)
+	}
+	c.childFiles = append(c.childFiles, c.ExtraFiles...)
+
+	var err error
+	c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
+		Dir:   c.Dir,
+		Files: c.childFiles,
+		Env:   c.envv(),
+		Sys:   c.SysProcAttr,
+	})
+	if err != nil {
+		c.closeDescriptors(c.closeAfterStart)
+		c.closeDescriptors(c.closeAfterWait)
+		return err
+	}
+
+	c.closeDescriptors(c.closeAfterStart)
+
+	c.errch = make(chan error, len(c.goroutine))
+	for _, fn := range c.goroutine {
+		go func(fn func() error) {
+			c.errch <- fn()
+		}(fn)
+	}
+
+	return nil
+}
+
+// An ExitError reports an unsuccessful exit by a command.
+type ExitError struct {
+	*os.ProcessState
+}
+
+func (e *ExitError) Error() string {
+	return e.ProcessState.String()
+}
+
+// Wait waits for the command to exit.
+// It must have been started by Start.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the command fails to run or doesn't complete successfully, the
+// error is of type *ExitError. Other error types may be
+// returned for I/O problems.
+//
+// Wait releases any resources associated with the Cmd.
+func (c *Cmd) Wait() error {
+	if c.Process == nil {
+		return errors.New("exec: not started")
+	}
+	if c.finished {
+		return errors.New("exec: Wait was already called")
+	}
+	c.finished = true
+	state, err := c.Process.Wait()
+	c.ProcessState = state
+
+	var copyError error
+	for _ = range c.goroutine {
+		if err := <-c.errch; err != nil && copyError == nil {
+			copyError = err
+		}
+	}
+
+	c.closeDescriptors(c.closeAfterWait)
+
+	if err != nil {
+		return err
+	} else if !state.Success() {
+		return &ExitError{state}
+	}
+
+	return copyError
+}
+
+// Output runs the command and returns its standard output.
+func (c *Cmd) Output() ([]byte, error) {
+	if c.Stdout != nil {
+		return nil, errors.New("exec: Stdout already set")
+	}
+	var b bytes.Buffer
+	c.Stdout = &b
+	err := c.Run()
+	return b.Bytes(), err
+}
+
+// CombinedOutput runs the command and returns its combined standard
+// output and standard error.
+func (c *Cmd) CombinedOutput() ([]byte, error) {
+	if c.Stdout != nil {
+		return nil, errors.New("exec: Stdout already set")
+	}
+	if c.Stderr != nil {
+		return nil, errors.New("exec: Stderr already set")
+	}
+	var b bytes.Buffer
+	c.Stdout = &b
+	c.Stderr = &b
+	err := c.Run()
+	return b.Bytes(), err
+}
+
+// StdinPipe returns a pipe that will be connected to the command's
+// standard input when the command starts.
+// The pipe will be closed automatically after Wait sees the command exit.
+// A caller need only call Close to force the pipe to close sooner.
+// For example, if the command being run will not exit until standard input
+// is closed, the caller must close the pipe.
+func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
+	if c.Stdin != nil {
+		return nil, errors.New("exec: Stdin already set")
+	}
+	if c.Process != nil {
+		return nil, errors.New("exec: StdinPipe after process started")
+	}
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return nil, err
+	}
+	c.Stdin = pr
+	c.closeAfterStart = append(c.closeAfterStart, pr)
+	wc := &closeOnce{File: pw}
+	c.closeAfterWait = append(c.closeAfterWait, wc)
+	return wc, nil
+}
+
+type closeOnce struct {
+	*os.File
+
+	once sync.Once
+	err  error
+}
+
+func (c *closeOnce) Close() error {
+	c.once.Do(c.close)
+	return c.err
+}
+
+func (c *closeOnce) close() {
+	c.err = c.File.Close()
+}
+
+// StdoutPipe returns a pipe that will be connected to the command's
+// standard output when the command starts.
+//
+// Wait will close the pipe after seeing the command exit, so most callers
+// need not close the pipe themselves; however, an implication is that
+// it is incorrect to call Wait before all reads from the pipe have completed.
+// For the same reason, it is incorrect to call Run when using StdoutPipe.
+// See the example for idiomatic usage.
+func (c *Cmd) StdoutPipe() (io.ReadCloser, error) {
+	if c.Stdout != nil {
+		return nil, errors.New("exec: Stdout already set")
+	}
+	if c.Process != nil {
+		return nil, errors.New("exec: StdoutPipe after process started")
+	}
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return nil, err
+	}
+	c.Stdout = pw
+	c.closeAfterStart = append(c.closeAfterStart, pw)
+	c.closeAfterWait = append(c.closeAfterWait, pr)
+	return pr, nil
+}
+
+// StderrPipe returns a pipe that will be connected to the command's
+// standard error when the command starts.
+//
+// Wait will close the pipe after seeing the command exit, so most callers
+// need not close the pipe themselves; however, an implication is that
+// it is incorrect to call Wait before all reads from the pipe have completed.
+// For the same reason, it is incorrect to use Run when using StderrPipe.
+// See the StdoutPipe example for idiomatic usage.
+func (c *Cmd) StderrPipe() (io.ReadCloser, error) {
+	if c.Stderr != nil {
+		return nil, errors.New("exec: Stderr already set")
+	}
+	if c.Process != nil {
+		return nil, errors.New("exec: StderrPipe after process started")
+	}
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return nil, err
+	}
+	c.Stderr = pw
+	c.closeAfterStart = append(c.closeAfterStart, pw)
+	c.closeAfterWait = append(c.closeAfterWait, pr)
+	return pr, nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec/exec_test.go b/third_party/gofrontend/libgo/go/os/exec/exec_test.go
new file mode 100644
index 0000000..8521bfd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec/exec_test.go
@@ -0,0 +1,730 @@
+// 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.
+
+// Use an external test to avoid os/exec -> net/http -> crypto/x509 -> os/exec
+// circular dependency on non-cgo darwin.
+
+package exec_test
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+)
+
+func helperCommand(t *testing.T, s ...string) *exec.Cmd {
+	if runtime.GOOS == "nacl" {
+		t.Skip("skipping on nacl")
+	}
+	cs := []string{"-test.run=TestHelperProcess", "--"}
+	cs = append(cs, s...)
+	cmd := exec.Command(os.Args[0], cs...)
+	cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
+	path := os.Getenv("LD_LIBRARY_PATH")
+	if path != "" {
+		cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+path)
+	}
+	return cmd
+}
+
+func TestEcho(t *testing.T) {
+	bs, err := helperCommand(t, "echo", "foo bar", "baz").Output()
+	if err != nil {
+		t.Errorf("echo: %v", err)
+	}
+	if g, e := string(bs), "foo bar baz\n"; g != e {
+		t.Errorf("echo: want %q, got %q", e, g)
+	}
+}
+
+func TestCommandRelativeName(t *testing.T) {
+	// Run our own binary as a relative path
+	// (e.g. "_test/exec.test") our parent directory.
+	base := filepath.Base(os.Args[0]) // "exec.test"
+	dir := filepath.Dir(os.Args[0])   // "/tmp/go-buildNNNN/os/exec/_test"
+	if dir == "." {
+		t.Skip("skipping; running test at root somehow")
+	}
+	parentDir := filepath.Dir(dir) // "/tmp/go-buildNNNN/os/exec"
+	dirBase := filepath.Base(dir)  // "_test"
+	if dirBase == "." {
+		t.Skipf("skipping; unexpected shallow dir of %q", dir)
+	}
+
+	cmd := exec.Command(filepath.Join(dirBase, base), "-test.run=TestHelperProcess", "--", "echo", "foo")
+	cmd.Dir = parentDir
+	cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
+
+	out, err := cmd.Output()
+	if err != nil {
+		t.Errorf("echo: %v", err)
+	}
+	if g, e := string(out), "foo\n"; g != e {
+		t.Errorf("echo: want %q, got %q", e, g)
+	}
+}
+
+func TestCatStdin(t *testing.T) {
+	// Cat, testing stdin and stdout.
+	input := "Input string\nLine 2"
+	p := helperCommand(t, "cat")
+	p.Stdin = strings.NewReader(input)
+	bs, err := p.Output()
+	if err != nil {
+		t.Errorf("cat: %v", err)
+	}
+	s := string(bs)
+	if s != input {
+		t.Errorf("cat: want %q, got %q", input, s)
+	}
+}
+
+func TestCatGoodAndBadFile(t *testing.T) {
+	// Testing combined output and error values.
+	bs, err := helperCommand(t, "cat", "/bogus/file.foo", "exec_test.go").CombinedOutput()
+	if _, ok := err.(*exec.ExitError); !ok {
+		t.Errorf("expected *exec.ExitError from cat combined; got %T: %v", err, err)
+	}
+	s := string(bs)
+	sp := strings.SplitN(s, "\n", 2)
+	if len(sp) != 2 {
+		t.Fatalf("expected two lines from cat; got %q", s)
+	}
+	errLine, body := sp[0], sp[1]
+	if !strings.HasPrefix(errLine, "Error: open /bogus/file.foo") {
+		t.Errorf("expected stderr to complain about file; got %q", errLine)
+	}
+	if !strings.Contains(body, "func TestHelperProcess(t *testing.T)") {
+		t.Errorf("expected test code; got %q (len %d)", body, len(body))
+	}
+}
+
+func TestNoExistBinary(t *testing.T) {
+	// Can't run a non-existent binary
+	err := exec.Command("/no-exist-binary").Run()
+	if err == nil {
+		t.Error("expected error from /no-exist-binary")
+	}
+}
+
+func TestExitStatus(t *testing.T) {
+	// Test that exit values are returned correctly
+	cmd := helperCommand(t, "exit", "42")
+	err := cmd.Run()
+	want := "exit status 42"
+	switch runtime.GOOS {
+	case "plan9":
+		want = fmt.Sprintf("exit status: '%s %d: 42'", filepath.Base(cmd.Path), cmd.ProcessState.Pid())
+	}
+	if werr, ok := err.(*exec.ExitError); ok {
+		if s := werr.Error(); s != want {
+			t.Errorf("from exit 42 got exit %q, want %q", s, want)
+		}
+	} else {
+		t.Fatalf("expected *exec.ExitError from exit 42; got %T: %v", err, err)
+	}
+}
+
+func TestPipes(t *testing.T) {
+	check := func(what string, err error) {
+		if err != nil {
+			t.Fatalf("%s: %v", what, err)
+		}
+	}
+	// Cat, testing stdin and stdout.
+	c := helperCommand(t, "pipetest")
+	stdin, err := c.StdinPipe()
+	check("StdinPipe", err)
+	stdout, err := c.StdoutPipe()
+	check("StdoutPipe", err)
+	stderr, err := c.StderrPipe()
+	check("StderrPipe", err)
+
+	outbr := bufio.NewReader(stdout)
+	errbr := bufio.NewReader(stderr)
+	line := func(what string, br *bufio.Reader) string {
+		line, _, err := br.ReadLine()
+		if err != nil {
+			t.Fatalf("%s: %v", what, err)
+		}
+		return string(line)
+	}
+
+	err = c.Start()
+	check("Start", err)
+
+	_, err = stdin.Write([]byte("O:I am output\n"))
+	check("first stdin Write", err)
+	if g, e := line("first output line", outbr), "O:I am output"; g != e {
+		t.Errorf("got %q, want %q", g, e)
+	}
+
+	_, err = stdin.Write([]byte("E:I am error\n"))
+	check("second stdin Write", err)
+	if g, e := line("first error line", errbr), "E:I am error"; g != e {
+		t.Errorf("got %q, want %q", g, e)
+	}
+
+	_, err = stdin.Write([]byte("O:I am output2\n"))
+	check("third stdin Write 3", err)
+	if g, e := line("second output line", outbr), "O:I am output2"; g != e {
+		t.Errorf("got %q, want %q", g, e)
+	}
+
+	stdin.Close()
+	err = c.Wait()
+	check("Wait", err)
+}
+
+const stdinCloseTestString = "Some test string."
+
+// Issue 6270.
+func TestStdinClose(t *testing.T) {
+	check := func(what string, err error) {
+		if err != nil {
+			t.Fatalf("%s: %v", what, err)
+		}
+	}
+	cmd := helperCommand(t, "stdinClose")
+	stdin, err := cmd.StdinPipe()
+	check("StdinPipe", err)
+	// Check that we can access methods of the underlying os.File.`
+	if _, ok := stdin.(interface {
+		Fd() uintptr
+	}); !ok {
+		t.Error("can't access methods of underlying *os.File")
+	}
+	check("Start", cmd.Start())
+	go func() {
+		_, err := io.Copy(stdin, strings.NewReader(stdinCloseTestString))
+		check("Copy", err)
+		// Before the fix, this next line would race with cmd.Wait.
+		check("Close", stdin.Close())
+	}()
+	check("Wait", cmd.Wait())
+}
+
+// Issue 5071
+func TestPipeLookPathLeak(t *testing.T) {
+	fd0, lsof0 := numOpenFDS(t)
+	for i := 0; i < 4; i++ {
+		cmd := exec.Command("something-that-does-not-exist-binary")
+		cmd.StdoutPipe()
+		cmd.StderrPipe()
+		cmd.StdinPipe()
+		if err := cmd.Run(); err == nil {
+			t.Fatal("unexpected success")
+		}
+	}
+	for triesLeft := 3; triesLeft >= 0; triesLeft-- {
+		open, lsof := numOpenFDS(t)
+		fdGrowth := open - fd0
+		if fdGrowth > 2 {
+			if triesLeft > 0 {
+				// Work around what appears to be a race with Linux's
+				// proc filesystem (as used by lsof). It seems to only
+				// be eventually consistent. Give it awhile to settle.
+				// See golang.org/issue/7808
+				time.Sleep(100 * time.Millisecond)
+				continue
+			}
+			t.Errorf("leaked %d fds; want ~0; have:\n%s\noriginally:\n%s", fdGrowth, lsof, lsof0)
+		}
+		break
+	}
+}
+
+func numOpenFDS(t *testing.T) (n int, lsof []byte) {
+	lsof, err := exec.Command("lsof", "-n", "-p", strconv.Itoa(os.Getpid())).Output()
+	if err != nil {
+		t.Skip("skipping test; error finding or running lsof")
+	}
+	return bytes.Count(lsof, []byte("\n")), lsof
+}
+
+var testedAlreadyLeaked = false
+
+// basefds returns the number of expected file descriptors
+// to be present in a process at start.
+func basefds() uintptr {
+	n := os.Stderr.Fd() + 1
+
+	// Go runtime for 32-bit Plan 9 requires that /dev/bintime
+	// be kept open.
+	// See ../../runtime/time_plan9_386.c:/^runtime·nanotime
+	if runtime.GOOS == "plan9" && runtime.GOARCH == "386" {
+		n++
+	}
+	return n
+}
+
+func closeUnexpectedFds(t *testing.T, m string) {
+	for fd := basefds(); fd <= 101; fd++ {
+		err := os.NewFile(fd, "").Close()
+		if err == nil {
+			t.Logf("%s: Something already leaked - closed fd %d", m, fd)
+		}
+	}
+}
+
+func TestExtraFilesFDShuffle(t *testing.T) {
+	t.Skip("flaky test; see http://golang.org/issue/5780")
+	switch runtime.GOOS {
+	case "darwin":
+		// TODO(cnicolaou): http://golang.org/issue/2603
+		// leads to leaked file descriptors in this test when it's
+		// run from a builder.
+		closeUnexpectedFds(t, "TestExtraFilesFDShuffle")
+	case "netbsd":
+		// http://golang.org/issue/3955
+		closeUnexpectedFds(t, "TestExtraFilesFDShuffle")
+	case "windows":
+		t.Skip("no operating system support; skipping")
+	}
+
+	// syscall.StartProcess maps all the FDs passed to it in
+	// ProcAttr.Files (the concatenation of stdin,stdout,stderr and
+	// ExtraFiles) into consecutive FDs in the child, that is:
+	// Files{11, 12, 6, 7, 9, 3} should result in the file
+	// represented by FD 11 in the parent being made available as 0
+	// in the child, 12 as 1, etc.
+	//
+	// We want to test that FDs in the child do not get overwritten
+	// by one another as this shuffle occurs. The original implementation
+	// was buggy in that in some data dependent cases it would ovewrite
+	// stderr in the child with one of the ExtraFile members.
+	// Testing for this case is difficult because it relies on using
+	// the same FD values as that case. In particular, an FD of 3
+	// must be at an index of 4 or higher in ProcAttr.Files and
+	// the FD of the write end of the Stderr pipe (as obtained by
+	// StderrPipe()) must be the same as the size of ProcAttr.Files;
+	// therefore we test that the read end of this pipe (which is what
+	// is returned to the parent by StderrPipe() being one less than
+	// the size of ProcAttr.Files, i.e. 3+len(cmd.ExtraFiles).
+	//
+	// Moving this test case around within the overall tests may
+	// affect the FDs obtained and hence the checks to catch these cases.
+	npipes := 2
+	c := helperCommand(t, "extraFilesAndPipes", strconv.Itoa(npipes+1))
+	rd, wr, _ := os.Pipe()
+	defer rd.Close()
+	if rd.Fd() != 3 {
+		t.Errorf("bad test value for test pipe: fd %d", rd.Fd())
+	}
+	stderr, _ := c.StderrPipe()
+	wr.WriteString("_LAST")
+	wr.Close()
+
+	pipes := make([]struct {
+		r, w *os.File
+	}, npipes)
+	data := []string{"a", "b"}
+
+	for i := 0; i < npipes; i++ {
+		r, w, err := os.Pipe()
+		if err != nil {
+			t.Fatalf("unexpected error creating pipe: %s", err)
+		}
+		pipes[i].r = r
+		pipes[i].w = w
+		w.WriteString(data[i])
+		c.ExtraFiles = append(c.ExtraFiles, pipes[i].r)
+		defer func() {
+			r.Close()
+			w.Close()
+		}()
+	}
+	// Put fd 3 at the end.
+	c.ExtraFiles = append(c.ExtraFiles, rd)
+
+	stderrFd := int(stderr.(*os.File).Fd())
+	if stderrFd != ((len(c.ExtraFiles) + 3) - 1) {
+		t.Errorf("bad test value for stderr pipe")
+	}
+
+	expected := "child: " + strings.Join(data, "") + "_LAST"
+
+	err := c.Start()
+	if err != nil {
+		t.Fatalf("Run: %v", err)
+	}
+	ch := make(chan string, 1)
+	go func(ch chan string) {
+		buf := make([]byte, 512)
+		n, err := stderr.Read(buf)
+		if err != nil {
+			t.Fatalf("Read: %s", err)
+			ch <- err.Error()
+		} else {
+			ch <- string(buf[:n])
+		}
+		close(ch)
+	}(ch)
+	select {
+	case m := <-ch:
+		if m != expected {
+			t.Errorf("Read: '%s' not '%s'", m, expected)
+		}
+	case <-time.After(5 * time.Second):
+		t.Errorf("Read timedout")
+	}
+	c.Wait()
+}
+
+func TestExtraFiles(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		t.Skip("no operating system support; skipping")
+	}
+
+	// Ensure that file descriptors have not already been leaked into
+	// our environment.
+	if !testedAlreadyLeaked {
+		testedAlreadyLeaked = true
+		closeUnexpectedFds(t, "TestExtraFiles")
+	}
+
+	// Force network usage, to verify the epoll (or whatever) fd
+	// doesn't leak to the child,
+	ln, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln.Close()
+
+	// Make sure duplicated fds don't leak to the child.
+	f, err := ln.(*net.TCPListener).File()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer f.Close()
+	ln2, err := net.FileListener(f)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln2.Close()
+
+	// Force TLS root certs to be loaded (which might involve
+	// cgo), to make sure none of that potential C code leaks fds.
+	ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
+	// quiet expected TLS handshake error "remote error: bad certificate"
+	ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0)
+	ts.StartTLS()
+	defer ts.Close()
+	_, err = http.Get(ts.URL)
+	if err == nil {
+		t.Errorf("success trying to fetch %s; want an error", ts.URL)
+	}
+
+	tf, err := ioutil.TempFile("", "")
+	if err != nil {
+		t.Fatalf("TempFile: %v", err)
+	}
+	defer os.Remove(tf.Name())
+	defer tf.Close()
+
+	const text = "Hello, fd 3!"
+	_, err = tf.Write([]byte(text))
+	if err != nil {
+		t.Fatalf("Write: %v", err)
+	}
+	_, err = tf.Seek(0, os.SEEK_SET)
+	if err != nil {
+		t.Fatalf("Seek: %v", err)
+	}
+
+	c := helperCommand(t, "read3")
+	var stdout, stderr bytes.Buffer
+	c.Stdout = &stdout
+	c.Stderr = &stderr
+	c.ExtraFiles = []*os.File{tf}
+	err = c.Run()
+	if err != nil {
+		t.Fatalf("Run: %v; stdout %q, stderr %q", err, stdout.Bytes(), stderr.Bytes())
+	}
+	if stdout.String() != text {
+		t.Errorf("got stdout %q, stderr %q; want %q on stdout", stdout.String(), stderr.String(), text)
+	}
+}
+
+func TestExtraFilesRace(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		t.Skip("no operating system support; skipping")
+	}
+	listen := func() net.Listener {
+		ln, err := net.Listen("tcp", "127.0.0.1:0")
+		if err != nil {
+			t.Fatal(err)
+		}
+		return ln
+	}
+	listenerFile := func(ln net.Listener) *os.File {
+		f, err := ln.(*net.TCPListener).File()
+		if err != nil {
+			t.Fatal(err)
+		}
+		return f
+	}
+	runCommand := func(c *exec.Cmd, out chan<- string) {
+		bout, err := c.CombinedOutput()
+		if err != nil {
+			out <- "ERROR:" + err.Error()
+		} else {
+			out <- string(bout)
+		}
+	}
+
+	for i := 0; i < 10; i++ {
+		la := listen()
+		ca := helperCommand(t, "describefiles")
+		ca.ExtraFiles = []*os.File{listenerFile(la)}
+		lb := listen()
+		cb := helperCommand(t, "describefiles")
+		cb.ExtraFiles = []*os.File{listenerFile(lb)}
+		ares := make(chan string)
+		bres := make(chan string)
+		go runCommand(ca, ares)
+		go runCommand(cb, bres)
+		if got, want := <-ares, fmt.Sprintf("fd3: listener %s\n", la.Addr()); got != want {
+			t.Errorf("iteration %d, process A got:\n%s\nwant:\n%s\n", i, got, want)
+		}
+		if got, want := <-bres, fmt.Sprintf("fd3: listener %s\n", lb.Addr()); got != want {
+			t.Errorf("iteration %d, process B got:\n%s\nwant:\n%s\n", i, got, want)
+		}
+		la.Close()
+		lb.Close()
+		for _, f := range ca.ExtraFiles {
+			f.Close()
+		}
+		for _, f := range cb.ExtraFiles {
+			f.Close()
+		}
+
+	}
+}
+
+// TestHelperProcess isn't a real test. It's used as a helper process
+// for TestParameterRun.
+func TestHelperProcess(*testing.T) {
+	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
+		return
+	}
+	defer os.Exit(0)
+
+	// Determine which command to use to display open files.
+	ofcmd := "lsof"
+	switch runtime.GOOS {
+	case "dragonfly", "freebsd", "netbsd", "openbsd":
+		ofcmd = "fstat"
+	case "plan9":
+		ofcmd = "/bin/cat"
+	}
+
+	args := os.Args
+	for len(args) > 0 {
+		if args[0] == "--" {
+			args = args[1:]
+			break
+		}
+		args = args[1:]
+	}
+	if len(args) == 0 {
+		fmt.Fprintf(os.Stderr, "No command\n")
+		os.Exit(2)
+	}
+
+	cmd, args := args[0], args[1:]
+	switch cmd {
+	case "echo":
+		iargs := []interface{}{}
+		for _, s := range args {
+			iargs = append(iargs, s)
+		}
+		fmt.Println(iargs...)
+	case "cat":
+		if len(args) == 0 {
+			io.Copy(os.Stdout, os.Stdin)
+			return
+		}
+		exit := 0
+		for _, fn := range args {
+			f, err := os.Open(fn)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+				exit = 2
+			} else {
+				defer f.Close()
+				io.Copy(os.Stdout, f)
+			}
+		}
+		os.Exit(exit)
+	case "pipetest":
+		bufr := bufio.NewReader(os.Stdin)
+		for {
+			line, _, err := bufr.ReadLine()
+			if err == io.EOF {
+				break
+			} else if err != nil {
+				os.Exit(1)
+			}
+			if bytes.HasPrefix(line, []byte("O:")) {
+				os.Stdout.Write(line)
+				os.Stdout.Write([]byte{'\n'})
+			} else if bytes.HasPrefix(line, []byte("E:")) {
+				os.Stderr.Write(line)
+				os.Stderr.Write([]byte{'\n'})
+			} else {
+				os.Exit(1)
+			}
+		}
+	case "stdinClose":
+		b, err := ioutil.ReadAll(os.Stdin)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+			os.Exit(1)
+		}
+		if s := string(b); s != stdinCloseTestString {
+			fmt.Fprintf(os.Stderr, "Error: Read %q, want %q", s, stdinCloseTestString)
+			os.Exit(1)
+		}
+		os.Exit(0)
+	case "read3": // read fd 3
+		fd3 := os.NewFile(3, "fd3")
+		bs, err := ioutil.ReadAll(fd3)
+		if err != nil {
+			fmt.Printf("ReadAll from fd 3: %v", err)
+			os.Exit(1)
+		}
+		switch runtime.GOOS {
+		case "dragonfly":
+			// TODO(jsing): Determine why DragonFly is leaking
+			// file descriptors...
+		case "darwin":
+			// TODO(bradfitz): broken? Sometimes.
+			// http://golang.org/issue/2603
+			// Skip this additional part of the test for now.
+		case "netbsd":
+			// TODO(jsing): This currently fails on NetBSD due to
+			// the cloned file descriptors that result from opening
+			// /dev/urandom.
+			// http://golang.org/issue/3955
+		case "plan9":
+			// TODO(0intro): Determine why Plan 9 is leaking
+			// file descriptors.
+			// http://golang.org/issue/7118
+		case "solaris":
+			// TODO(aram): This fails on Solaris because libc opens
+			// its own files, as it sees fit. Darwin does the same,
+			// see: http://golang.org/issue/2603
+		default:
+			// Now verify that there are no other open fds.
+			var files []*os.File
+			for wantfd := basefds() + 1; wantfd <= 100; wantfd++ {
+				f, err := os.Open(os.Args[0])
+				if err != nil {
+					fmt.Printf("error opening file with expected fd %d: %v", wantfd, err)
+					os.Exit(1)
+				}
+				if got := f.Fd(); got != wantfd {
+					fmt.Printf("leaked parent file. fd = %d; want %d\n", got, wantfd)
+					var args []string
+					switch runtime.GOOS {
+					case "plan9":
+						args = []string{fmt.Sprintf("/proc/%d/fd", os.Getpid())}
+					default:
+						args = []string{"-p", fmt.Sprint(os.Getpid())}
+					}
+					out, _ := exec.Command(ofcmd, args...).CombinedOutput()
+					fmt.Print(string(out))
+					os.Exit(1)
+				}
+				files = append(files, f)
+			}
+			for _, f := range files {
+				f.Close()
+			}
+		}
+		// Referring to fd3 here ensures that it is not
+		// garbage collected, and therefore closed, while
+		// executing the wantfd loop above.  It doesn't matter
+		// what we do with fd3 as long as we refer to it;
+		// closing it is the easy choice.
+		fd3.Close()
+		os.Stdout.Write(bs)
+	case "exit":
+		n, _ := strconv.Atoi(args[0])
+		os.Exit(n)
+	case "describefiles":
+		f := os.NewFile(3, fmt.Sprintf("fd3"))
+		ln, err := net.FileListener(f)
+		if err == nil {
+			fmt.Printf("fd3: listener %s\n", ln.Addr())
+			ln.Close()
+		}
+		os.Exit(0)
+	case "extraFilesAndPipes":
+		n, _ := strconv.Atoi(args[0])
+		pipes := make([]*os.File, n)
+		for i := 0; i < n; i++ {
+			pipes[i] = os.NewFile(uintptr(3+i), strconv.Itoa(i))
+		}
+		response := ""
+		for i, r := range pipes {
+			ch := make(chan string, 1)
+			go func(c chan string) {
+				buf := make([]byte, 10)
+				n, err := r.Read(buf)
+				if err != nil {
+					fmt.Fprintf(os.Stderr, "Child: read error: %v on pipe %d\n", err, i)
+					os.Exit(1)
+				}
+				c <- string(buf[:n])
+				close(c)
+			}(ch)
+			select {
+			case m := <-ch:
+				response = response + m
+			case <-time.After(5 * time.Second):
+				fmt.Fprintf(os.Stderr, "Child: Timeout reading from pipe: %d\n", i)
+				os.Exit(1)
+			}
+		}
+		fmt.Fprintf(os.Stderr, "child: %s", response)
+		os.Exit(0)
+	case "exec":
+		cmd := exec.Command(args[1])
+		cmd.Dir = args[0]
+		output, err := cmd.CombinedOutput()
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Child: %s %s", err, string(output))
+			os.Exit(1)
+		}
+		fmt.Printf("%s", string(output))
+		os.Exit(0)
+	case "lookpath":
+		p, err := exec.LookPath(args[0])
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "LookPath failed: %v\n", err)
+			os.Exit(1)
+		}
+		fmt.Print(p)
+		os.Exit(0)
+	default:
+		fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
+		os.Exit(2)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec/lp_plan9.go b/third_party/gofrontend/libgo/go/os/exec/lp_plan9.go
new file mode 100644
index 0000000..5aa8a54
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec/lp_plan9.go
@@ -0,0 +1,53 @@
+// 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.
+
+package exec
+
+import (
+	"errors"
+	"os"
+	"strings"
+)
+
+// ErrNotFound is the error resulting if a path search failed to find an executable file.
+var ErrNotFound = errors.New("executable file not found in $path")
+
+func findExecutable(file string) error {
+	d, err := os.Stat(file)
+	if err != nil {
+		return err
+	}
+	if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
+		return nil
+	}
+	return os.ErrPermission
+}
+
+// LookPath searches for an executable binary named file
+// in the directories named by the path environment variable.
+// If file begins with "/", "#", "./", or "../", it is tried
+// directly and the path is not consulted.
+// The result may be an absolute path or a path relative to the current directory.
+func LookPath(file string) (string, error) {
+	// skip the path lookup for these prefixes
+	skip := []string{"/", "#", "./", "../"}
+
+	for _, p := range skip {
+		if strings.HasPrefix(file, p) {
+			err := findExecutable(file)
+			if err == nil {
+				return file, nil
+			}
+			return "", &Error{file, err}
+		}
+	}
+
+	path := os.Getenv("path")
+	for _, dir := range strings.Split(path, "\000") {
+		if err := findExecutable(dir + "/" + file); err == nil {
+			return dir + "/" + file, nil
+		}
+	}
+	return "", &Error{file, ErrNotFound}
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec/lp_test.go b/third_party/gofrontend/libgo/go/os/exec/lp_test.go
new file mode 100644
index 0000000..77d8e84
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec/lp_test.go
@@ -0,0 +1,33 @@
+// 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.
+
+package exec
+
+import (
+	"testing"
+)
+
+var nonExistentPaths = []string{
+	"some-non-existent-path",
+	"non-existent-path/slashed",
+}
+
+func TestLookPathNotFound(t *testing.T) {
+	for _, name := range nonExistentPaths {
+		path, err := LookPath(name)
+		if err == nil {
+			t.Fatalf("LookPath found %q in $PATH", name)
+		}
+		if path != "" {
+			t.Fatalf("LookPath path == %q when err != nil", path)
+		}
+		perr, ok := err.(*Error)
+		if !ok {
+			t.Fatal("LookPath error is not an exec.Error")
+		}
+		if perr.Name != name {
+			t.Fatalf("want Error name %q, got %q", name, perr.Name)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec/lp_unix.go b/third_party/gofrontend/libgo/go/os/exec/lp_unix.go
new file mode 100644
index 0000000..3f895d5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec/lp_unix.go
@@ -0,0 +1,60 @@
+// Copyright 2010 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package exec
+
+import (
+	"errors"
+	"os"
+	"strings"
+)
+
+// ErrNotFound is the error resulting if a path search failed to find an executable file.
+var ErrNotFound = errors.New("executable file not found in $PATH")
+
+func findExecutable(file string) error {
+	d, err := os.Stat(file)
+	if err != nil {
+		return err
+	}
+	if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
+		return nil
+	}
+	return os.ErrPermission
+}
+
+// LookPath searches for an executable binary named file
+// in the directories named by the PATH environment variable.
+// If file contains a slash, it is tried directly and the PATH is not consulted.
+// The result may be an absolute path or a path relative to the current directory.
+func LookPath(file string) (string, error) {
+	// NOTE(rsc): I wish we could use the Plan 9 behavior here
+	// (only bypass the path if file begins with / or ./ or ../)
+	// but that would not match all the Unix shells.
+
+	if strings.Contains(file, "/") {
+		err := findExecutable(file)
+		if err == nil {
+			return file, nil
+		}
+		return "", &Error{file, err}
+	}
+	pathenv := os.Getenv("PATH")
+	if pathenv == "" {
+		return "", &Error{file, ErrNotFound}
+	}
+	for _, dir := range strings.Split(pathenv, ":") {
+		if dir == "" {
+			// Unix shell semantics: path element "" means "."
+			dir = "."
+		}
+		path := dir + "/" + file
+		if err := findExecutable(path); err == nil {
+			return path, nil
+		}
+	}
+	return "", &Error{file, ErrNotFound}
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec/lp_unix_test.go b/third_party/gofrontend/libgo/go/os/exec/lp_unix_test.go
new file mode 100644
index 0000000..051db66
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec/lp_unix_test.go
@@ -0,0 +1,55 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package exec
+
+import (
+	"io/ioutil"
+	"os"
+	"testing"
+)
+
+func TestLookPathUnixEmptyPath(t *testing.T) {
+	tmp, err := ioutil.TempDir("", "TestLookPathUnixEmptyPath")
+	if err != nil {
+		t.Fatal("TempDir failed: ", err)
+	}
+	defer os.RemoveAll(tmp)
+	wd, err := os.Getwd()
+	if err != nil {
+		t.Fatal("Getwd failed: ", err)
+	}
+	err = os.Chdir(tmp)
+	if err != nil {
+		t.Fatal("Chdir failed: ", err)
+	}
+	defer os.Chdir(wd)
+
+	f, err := os.OpenFile("exec_me", os.O_CREATE|os.O_EXCL, 0700)
+	if err != nil {
+		t.Fatal("OpenFile failed: ", err)
+	}
+	err = f.Close()
+	if err != nil {
+		t.Fatal("Close failed: ", err)
+	}
+
+	pathenv := os.Getenv("PATH")
+	defer os.Setenv("PATH", pathenv)
+
+	err = os.Setenv("PATH", "")
+	if err != nil {
+		t.Fatal("Setenv failed: ", err)
+	}
+
+	path, err := LookPath("exec_me")
+	if err == nil {
+		t.Fatal("LookPath found exec_me in empty $PATH")
+	}
+	if path != "" {
+		t.Fatalf("LookPath path == %q when err != nil", path)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec/lp_windows.go b/third_party/gofrontend/libgo/go/os/exec/lp_windows.go
new file mode 100644
index 0000000..c3efd67
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec/lp_windows.go
@@ -0,0 +1,123 @@
+// Copyright 2010 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 exec
+
+import (
+	"errors"
+	"os"
+	"strings"
+)
+
+// ErrNotFound is the error resulting if a path search failed to find an executable file.
+var ErrNotFound = errors.New("executable file not found in %PATH%")
+
+func chkStat(file string) error {
+	d, err := os.Stat(file)
+	if err != nil {
+		return err
+	}
+	if d.IsDir() {
+		return os.ErrPermission
+	}
+	return nil
+}
+
+func hasExt(file string) bool {
+	i := strings.LastIndex(file, ".")
+	if i < 0 {
+		return false
+	}
+	return strings.LastIndexAny(file, `:\/`) < i
+}
+
+func findExecutable(file string, exts []string) (string, error) {
+	if len(exts) == 0 {
+		return file, chkStat(file)
+	}
+	if hasExt(file) {
+		if chkStat(file) == nil {
+			return file, nil
+		}
+	}
+	for _, e := range exts {
+		if f := file + e; chkStat(f) == nil {
+			return f, nil
+		}
+	}
+	return ``, os.ErrNotExist
+}
+
+// LookPath searches for an executable binary named file
+// in the directories named by the PATH environment variable.
+// If file contains a slash, it is tried directly and the PATH is not consulted.
+// LookPath also uses PATHEXT environment variable to match
+// a suitable candidate.
+// The result may be an absolute path or a path relative to the current directory.
+func LookPath(file string) (f string, err error) {
+	x := os.Getenv(`PATHEXT`)
+	if x == `` {
+		x = `.COM;.EXE;.BAT;.CMD`
+	}
+	exts := []string{}
+	for _, e := range strings.Split(strings.ToLower(x), `;`) {
+		if e == "" {
+			continue
+		}
+		if e[0] != '.' {
+			e = "." + e
+		}
+		exts = append(exts, e)
+	}
+	if strings.IndexAny(file, `:\/`) != -1 {
+		if f, err = findExecutable(file, exts); err == nil {
+			return
+		}
+		return ``, &Error{file, err}
+	}
+	if f, err = findExecutable(`.\`+file, exts); err == nil {
+		return
+	}
+	if pathenv := os.Getenv(`PATH`); pathenv != `` {
+		for _, dir := range splitList(pathenv) {
+			if f, err = findExecutable(dir+`\`+file, exts); err == nil {
+				return
+			}
+		}
+	}
+	return ``, &Error{file, ErrNotFound}
+}
+
+func splitList(path string) []string {
+	// The same implementation is used in SplitList in path/filepath;
+	// consider changing path/filepath when changing this.
+
+	if path == "" {
+		return []string{}
+	}
+
+	// Split path, respecting but preserving quotes.
+	list := []string{}
+	start := 0
+	quo := false
+	for i := 0; i < len(path); i++ {
+		switch c := path[i]; {
+		case c == '"':
+			quo = !quo
+		case c == os.PathListSeparator && !quo:
+			list = append(list, path[start:i])
+			start = i + 1
+		}
+	}
+	list = append(list, path[start:])
+
+	// Remove quotes.
+	for i, s := range list {
+		if strings.Contains(s, `"`) {
+			list[i] = strings.Replace(s, `"`, ``, -1)
+		}
+	}
+
+	return list
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec_plan9.go b/third_party/gofrontend/libgo/go/os/exec_plan9.go
new file mode 100644
index 0000000..676be36
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec_plan9.go
@@ -0,0 +1,137 @@
+// 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 os
+
+import (
+	"errors"
+	"runtime"
+	"syscall"
+	"time"
+)
+
+// The only signal values guaranteed to be present on all systems
+// are Interrupt (send the process an interrupt) and Kill (force
+// the process to exit).
+var (
+	Interrupt Signal = syscall.Note("interrupt")
+	Kill      Signal = syscall.Note("kill")
+)
+
+func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
+	sysattr := &syscall.ProcAttr{
+		Dir: attr.Dir,
+		Env: attr.Env,
+		Sys: attr.Sys,
+	}
+
+	for _, f := range attr.Files {
+		sysattr.Files = append(sysattr.Files, f.Fd())
+	}
+
+	pid, h, e := syscall.StartProcess(name, argv, sysattr)
+	if e != nil {
+		return nil, &PathError{"fork/exec", name, e}
+	}
+
+	return newProcess(pid, h), nil
+}
+
+func (p *Process) writeProcFile(file string, data string) error {
+	f, e := OpenFile("/proc/"+itoa(p.Pid)+"/"+file, O_WRONLY, 0)
+	if e != nil {
+		return e
+	}
+	defer f.Close()
+	_, e = f.Write([]byte(data))
+	return e
+}
+
+func (p *Process) signal(sig Signal) error {
+	if p.done() {
+		return errors.New("os: process already finished")
+	}
+	if e := p.writeProcFile("note", sig.String()); e != nil {
+		return NewSyscallError("signal", e)
+	}
+	return nil
+}
+
+func (p *Process) kill() error {
+	return p.signal(Kill)
+}
+
+func (p *Process) wait() (ps *ProcessState, err error) {
+	var waitmsg syscall.Waitmsg
+
+	if p.Pid == -1 {
+		return nil, ErrInvalid
+	}
+	err = syscall.WaitProcess(p.Pid, &waitmsg)
+	if err != nil {
+		return nil, NewSyscallError("wait", err)
+	}
+
+	p.setDone()
+	ps = &ProcessState{
+		pid:    waitmsg.Pid,
+		status: &waitmsg,
+	}
+	return ps, nil
+}
+
+func (p *Process) release() error {
+	// NOOP for Plan 9.
+	p.Pid = -1
+	// no need for a finalizer anymore
+	runtime.SetFinalizer(p, nil)
+	return nil
+}
+
+func findProcess(pid int) (p *Process, err error) {
+	// NOOP for Plan 9.
+	return newProcess(pid, 0), nil
+}
+
+// ProcessState stores information about a process, as reported by Wait.
+type ProcessState struct {
+	pid    int              // The process's id.
+	status *syscall.Waitmsg // System-dependent status info.
+}
+
+// Pid returns the process id of the exited process.
+func (p *ProcessState) Pid() int {
+	return p.pid
+}
+
+func (p *ProcessState) exited() bool {
+	return p.status.Exited()
+}
+
+func (p *ProcessState) success() bool {
+	return p.status.ExitStatus() == 0
+}
+
+func (p *ProcessState) sys() interface{} {
+	return p.status
+}
+
+func (p *ProcessState) sysUsage() interface{} {
+	return p.status
+}
+
+func (p *ProcessState) userTime() time.Duration {
+	return time.Duration(p.status.Time[0]) * time.Millisecond
+}
+
+func (p *ProcessState) systemTime() time.Duration {
+	return time.Duration(p.status.Time[1]) * time.Millisecond
+}
+
+func (p *ProcessState) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return "exit status: " + p.status.Msg
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec_posix.go b/third_party/gofrontend/libgo/go/os/exec_posix.go
new file mode 100644
index 0000000..fb9d291
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec_posix.go
@@ -0,0 +1,134 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package os
+
+import (
+	"syscall"
+)
+
+// The only signal values guaranteed to be present on all systems
+// are Interrupt (send the process an interrupt) and Kill (force
+// the process to exit).
+var (
+	Interrupt Signal = syscall.SIGINT
+	Kill      Signal = syscall.SIGKILL
+)
+
+func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
+	// If there is no SysProcAttr (ie. no Chroot or changed
+	// UID/GID), double-check existence of the directory we want
+	// to chdir into.  We can make the error clearer this way.
+	if attr != nil && attr.Sys == nil && attr.Dir != "" {
+		if _, err := Stat(attr.Dir); err != nil {
+			pe := err.(*PathError)
+			pe.Op = "chdir"
+			return nil, pe
+		}
+	}
+
+	sysattr := &syscall.ProcAttr{
+		Dir: attr.Dir,
+		Env: attr.Env,
+		Sys: attr.Sys,
+	}
+	if sysattr.Env == nil {
+		sysattr.Env = Environ()
+	}
+	for _, f := range attr.Files {
+		sysattr.Files = append(sysattr.Files, f.Fd())
+	}
+
+	pid, h, e := syscall.StartProcess(name, argv, sysattr)
+	if e != nil {
+		return nil, &PathError{"fork/exec", name, e}
+	}
+	return newProcess(pid, h), nil
+}
+
+func (p *Process) kill() error {
+	return p.Signal(Kill)
+}
+
+// ProcessState stores information about a process, as reported by Wait.
+type ProcessState struct {
+	pid    int                // The process's id.
+	status syscall.WaitStatus // System-dependent status info.
+	rusage *syscall.Rusage
+}
+
+// Pid returns the process id of the exited process.
+func (p *ProcessState) Pid() int {
+	return p.pid
+}
+
+func (p *ProcessState) exited() bool {
+	return p.status.Exited()
+}
+
+func (p *ProcessState) success() bool {
+	return p.status.ExitStatus() == 0
+}
+
+func (p *ProcessState) sys() interface{} {
+	return p.status
+}
+
+func (p *ProcessState) sysUsage() interface{} {
+	return p.rusage
+}
+
+// Convert i to decimal string.
+func itod(i int) string {
+	if i == 0 {
+		return "0"
+	}
+
+	u := uint64(i)
+	if i < 0 {
+		u = -u
+	}
+
+	// Assemble decimal in reverse order.
+	var b [32]byte
+	bp := len(b)
+	for ; u > 0; u /= 10 {
+		bp--
+		b[bp] = byte(u%10) + '0'
+	}
+
+	if i < 0 {
+		bp--
+		b[bp] = '-'
+	}
+
+	return string(b[bp:])
+}
+
+func (p *ProcessState) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	status := p.Sys().(syscall.WaitStatus)
+	res := ""
+	switch {
+	case status.Exited():
+		res = "exit status " + itod(status.ExitStatus())
+	case status.Signaled():
+		res = "signal: " + status.Signal().String()
+	case status.Stopped():
+		res = "stop signal: " + status.StopSignal().String()
+		if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 {
+			res += " (trap " + itod(status.TrapCause()) + ")"
+		}
+	case status.Continued():
+		res = "continued"
+	}
+	if status.CoreDump() {
+		res += " (core dumped)"
+	}
+	return res
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec_unix.go b/third_party/gofrontend/libgo/go/os/exec_unix.go
new file mode 100644
index 0000000..1b1e335
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec_unix.go
@@ -0,0 +1,73 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package os
+
+import (
+	"errors"
+	"runtime"
+	"syscall"
+	"time"
+)
+
+func (p *Process) wait() (ps *ProcessState, err error) {
+	if p.Pid == -1 {
+		return nil, syscall.EINVAL
+	}
+	var status syscall.WaitStatus
+	var rusage syscall.Rusage
+	pid1, e := syscall.Wait4(p.Pid, &status, 0, &rusage)
+	if e != nil {
+		return nil, NewSyscallError("wait", e)
+	}
+	if pid1 != 0 {
+		p.setDone()
+	}
+	ps = &ProcessState{
+		pid:    pid1,
+		status: status,
+		rusage: &rusage,
+	}
+	return ps, nil
+}
+
+func (p *Process) signal(sig Signal) error {
+	if p.done() {
+		return errors.New("os: process already finished")
+	}
+	if p.Pid == -1 {
+		return errors.New("os: process already released")
+	}
+	s, ok := sig.(syscall.Signal)
+	if !ok {
+		return errors.New("os: unsupported signal type")
+	}
+	if e := syscall.Kill(p.Pid, s); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *Process) release() error {
+	// NOOP for unix.
+	p.Pid = -1
+	// no need for a finalizer anymore
+	runtime.SetFinalizer(p, nil)
+	return nil
+}
+
+func findProcess(pid int) (p *Process, err error) {
+	// NOOP for unix.
+	return newProcess(pid, 0), nil
+}
+
+func (p *ProcessState) userTime() time.Duration {
+	return time.Duration(p.rusage.Utime.Nano()) * time.Nanosecond
+}
+
+func (p *ProcessState) systemTime() time.Duration {
+	return time.Duration(p.rusage.Stime.Nano()) * time.Nanosecond
+}
diff --git a/third_party/gofrontend/libgo/go/os/exec_windows.go b/third_party/gofrontend/libgo/go/os/exec_windows.go
new file mode 100644
index 0000000..c4f3d4f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/exec_windows.go
@@ -0,0 +1,115 @@
+// 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 os
+
+import (
+	"errors"
+	"runtime"
+	"syscall"
+	"time"
+	"unsafe"
+)
+
+func (p *Process) wait() (ps *ProcessState, err error) {
+	s, e := syscall.WaitForSingleObject(syscall.Handle(p.handle), syscall.INFINITE)
+	switch s {
+	case syscall.WAIT_OBJECT_0:
+		break
+	case syscall.WAIT_FAILED:
+		return nil, NewSyscallError("WaitForSingleObject", e)
+	default:
+		return nil, errors.New("os: unexpected result from WaitForSingleObject")
+	}
+	var ec uint32
+	e = syscall.GetExitCodeProcess(syscall.Handle(p.handle), &ec)
+	if e != nil {
+		return nil, NewSyscallError("GetExitCodeProcess", e)
+	}
+	var u syscall.Rusage
+	e = syscall.GetProcessTimes(syscall.Handle(p.handle), &u.CreationTime, &u.ExitTime, &u.KernelTime, &u.UserTime)
+	if e != nil {
+		return nil, NewSyscallError("GetProcessTimes", e)
+	}
+	p.setDone()
+	// NOTE(brainman): It seems that sometimes process is not dead
+	// when WaitForSingleObject returns. But we do not know any
+	// other way to wait for it. Sleeping for a while seems to do
+	// the trick sometimes. So we will sleep and smell the roses.
+	defer time.Sleep(5 * time.Millisecond)
+	defer p.Release()
+	return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil
+}
+
+func terminateProcess(pid, exitcode int) error {
+	h, e := syscall.OpenProcess(syscall.PROCESS_TERMINATE, false, uint32(pid))
+	if e != nil {
+		return NewSyscallError("OpenProcess", e)
+	}
+	defer syscall.CloseHandle(h)
+	e = syscall.TerminateProcess(h, uint32(exitcode))
+	return NewSyscallError("TerminateProcess", e)
+}
+
+func (p *Process) signal(sig Signal) error {
+	if p.done() {
+		return errors.New("os: process already finished")
+	}
+	if sig == Kill {
+		return terminateProcess(p.Pid, 1)
+	}
+	// TODO(rsc): Handle Interrupt too?
+	return syscall.Errno(syscall.EWINDOWS)
+}
+
+func (p *Process) release() error {
+	if p.handle == uintptr(syscall.InvalidHandle) {
+		return syscall.EINVAL
+	}
+	e := syscall.CloseHandle(syscall.Handle(p.handle))
+	if e != nil {
+		return NewSyscallError("CloseHandle", e)
+	}
+	p.handle = uintptr(syscall.InvalidHandle)
+	// no need for a finalizer anymore
+	runtime.SetFinalizer(p, nil)
+	return nil
+}
+
+func findProcess(pid int) (p *Process, err error) {
+	const da = syscall.STANDARD_RIGHTS_READ |
+		syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
+	h, e := syscall.OpenProcess(da, false, uint32(pid))
+	if e != nil {
+		return nil, NewSyscallError("OpenProcess", e)
+	}
+	return newProcess(pid, uintptr(h)), nil
+}
+
+func init() {
+	var argc int32
+	cmd := syscall.GetCommandLine()
+	argv, e := syscall.CommandLineToArgv(cmd, &argc)
+	if e != nil {
+		return
+	}
+	defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv))))
+	Args = make([]string, argc)
+	for i, v := range (*argv)[:argc] {
+		Args[i] = string(syscall.UTF16ToString((*v)[:]))
+	}
+}
+
+func ftToDuration(ft *syscall.Filetime) time.Duration {
+	n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) // in 100-nanosecond intervals
+	return time.Duration(n*100) * time.Nanosecond
+}
+
+func (p *ProcessState) userTime() time.Duration {
+	return ftToDuration(&p.rusage.UserTime)
+}
+
+func (p *ProcessState) systemTime() time.Duration {
+	return ftToDuration(&p.rusage.KernelTime)
+}
diff --git a/third_party/gofrontend/libgo/go/os/export_test.go b/third_party/gofrontend/libgo/go/os/export_test.go
new file mode 100644
index 0000000..9fa7936
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/export_test.go
@@ -0,0 +1,10 @@
+// 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.
+
+package os
+
+// Export for testing.
+
+var Atime = atime
+var LstatP = &lstat
diff --git a/third_party/gofrontend/libgo/go/os/file.go b/third_party/gofrontend/libgo/go/os/file.go
new file mode 100644
index 0000000..b4a7458
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/file.go
@@ -0,0 +1,257 @@
+// 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 os provides a platform-independent interface to operating system
+// functionality. The design is Unix-like, although the error handling is
+// Go-like; failing calls return values of type error rather than error numbers.
+// Often, more information is available within the error. For example,
+// if a call that takes a file name fails, such as Open or Stat, the error
+// will include the failing file name when printed and will be of type
+// *PathError, which may be unpacked for more information.
+//
+// The os interface is intended to be uniform across all operating systems.
+// Features not generally available appear in the system-specific package syscall.
+//
+// Here is a simple example, opening a file and reading some of it.
+//
+//	file, err := os.Open("file.go") // For read access.
+//	if err != nil {
+//		log.Fatal(err)
+//	}
+//
+// If the open fails, the error string will be self-explanatory, like
+//
+//	open file.go: no such file or directory
+//
+// The file's data can then be read into a slice of bytes. Read and
+// Write take their byte counts from the length of the argument slice.
+//
+//	data := make([]byte, 100)
+//	count, err := file.Read(data)
+//	if err != nil {
+//		log.Fatal(err)
+//	}
+//	fmt.Printf("read %d bytes: %q\n", count, data[:count])
+//
+package os
+
+import (
+	"io"
+	"syscall"
+)
+
+// Name returns the name of the file as presented to Open.
+func (f *File) Name() string { return f.name }
+
+// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
+// standard output, and standard error file descriptors.
+var (
+	Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
+	Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
+	Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
+)
+
+// Flags to Open wrapping those of the underlying system. Not all flags
+// may be implemented on a given system.
+const (
+	O_RDONLY int = syscall.O_RDONLY // open the file read-only.
+	O_WRONLY int = syscall.O_WRONLY // open the file write-only.
+	O_RDWR   int = syscall.O_RDWR   // open the file read-write.
+	O_APPEND int = syscall.O_APPEND // append data to the file when writing.
+	O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
+	O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist
+	O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
+	O_TRUNC  int = syscall.O_TRUNC  // if possible, truncate file when opened.
+)
+
+// Seek whence values.
+const (
+	SEEK_SET int = 0 // seek relative to the origin of the file
+	SEEK_CUR int = 1 // seek relative to the current offset
+	SEEK_END int = 2 // seek relative to the end
+)
+
+// LinkError records an error during a link or symlink or rename
+// system call and the paths that caused it.
+type LinkError struct {
+	Op  string
+	Old string
+	New string
+	Err error
+}
+
+func (e *LinkError) Error() string {
+	return e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error()
+}
+
+// Read reads up to len(b) bytes from the File.
+// It returns the number of bytes read and an error, if any.
+// EOF is signaled by a zero count with err set to io.EOF.
+func (f *File) Read(b []byte) (n int, err error) {
+	if f == nil {
+		return 0, ErrInvalid
+	}
+	n, e := f.read(b)
+	if n < 0 {
+		n = 0
+	}
+	if n == 0 && len(b) > 0 && e == nil {
+		return 0, io.EOF
+	}
+	if e != nil {
+		err = &PathError{"read", f.name, e}
+	}
+	return n, err
+}
+
+// ReadAt reads len(b) bytes from the File starting at byte offset off.
+// It returns the number of bytes read and the error, if any.
+// ReadAt always returns a non-nil error when n < len(b).
+// At end of file, that error is io.EOF.
+func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
+	if f == nil {
+		return 0, ErrInvalid
+	}
+	for len(b) > 0 {
+		m, e := f.pread(b, off)
+		if m == 0 && e == nil {
+			return n, io.EOF
+		}
+		if e != nil {
+			err = &PathError{"read", f.name, e}
+			break
+		}
+		n += m
+		b = b[m:]
+		off += int64(m)
+	}
+	return
+}
+
+// Write writes len(b) bytes to the File.
+// It returns the number of bytes written and an error, if any.
+// Write returns a non-nil error when n != len(b).
+func (f *File) Write(b []byte) (n int, err error) {
+	if f == nil {
+		return 0, ErrInvalid
+	}
+	n, e := f.write(b)
+	if n < 0 {
+		n = 0
+	}
+	if n != len(b) {
+		err = io.ErrShortWrite
+	}
+
+	epipecheck(f, e)
+
+	if e != nil {
+		err = &PathError{"write", f.name, e}
+	}
+	return n, err
+}
+
+// WriteAt writes len(b) bytes to the File starting at byte offset off.
+// It returns the number of bytes written and an error, if any.
+// WriteAt returns a non-nil error when n != len(b).
+func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
+	if f == nil {
+		return 0, ErrInvalid
+	}
+	for len(b) > 0 {
+		m, e := f.pwrite(b, off)
+		if e != nil {
+			err = &PathError{"write", f.name, e}
+			break
+		}
+		n += m
+		b = b[m:]
+		off += int64(m)
+	}
+	return
+}
+
+// Seek sets the offset for the next Read or Write on file to offset, interpreted
+// according to whence: 0 means relative to the origin of the file, 1 means
+// relative to the current offset, and 2 means relative to the end.
+// It returns the new offset and an error, if any.
+func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
+	if f == nil {
+		return 0, ErrInvalid
+	}
+	r, e := f.seek(offset, whence)
+	if e == nil && f.dirinfo != nil && r != 0 {
+		e = syscall.EISDIR
+	}
+	if e != nil {
+		return 0, &PathError{"seek", f.name, e}
+	}
+	return r, nil
+}
+
+// WriteString is like Write, but writes the contents of string s rather than
+// a slice of bytes.
+func (f *File) WriteString(s string) (ret int, err error) {
+	if f == nil {
+		return 0, ErrInvalid
+	}
+	return f.Write([]byte(s))
+}
+
+// Mkdir creates a new directory with the specified name and permission bits.
+// If there is an error, it will be of type *PathError.
+func Mkdir(name string, perm FileMode) error {
+	e := syscall.Mkdir(name, syscallMode(perm))
+	if e != nil {
+		return &PathError{"mkdir", name, e}
+	}
+	return nil
+}
+
+// Chdir changes the current working directory to the named directory.
+// If there is an error, it will be of type *PathError.
+func Chdir(dir string) error {
+	if e := syscall.Chdir(dir); e != nil {
+		return &PathError{"chdir", dir, e}
+	}
+	return nil
+}
+
+// Chdir changes the current working directory to the file,
+// which must be a directory.
+// If there is an error, it will be of type *PathError.
+func (f *File) Chdir() error {
+	if f == nil {
+		return ErrInvalid
+	}
+	if e := syscall.Fchdir(f.fd); e != nil {
+		return &PathError{"chdir", f.name, e}
+	}
+	return nil
+}
+
+// Open opens the named file for reading.  If successful, methods on
+// the returned file can be used for reading; the associated file
+// descriptor has mode O_RDONLY.
+// If there is an error, it will be of type *PathError.
+func Open(name string) (file *File, err error) {
+	return OpenFile(name, O_RDONLY, 0)
+}
+
+// Create creates the named file mode 0666 (before umask), truncating
+// it if it already exists.  If successful, methods on the returned
+// File can be used for I/O; the associated file descriptor has mode
+// O_RDWR.
+// If there is an error, it will be of type *PathError.
+func Create(name string) (file *File, err error) {
+	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
+}
+
+// lstat is overridden in tests.
+var lstat = Lstat
+
+// Rename renames (moves) a file. OS-specific restrictions might apply.
+func Rename(oldpath, newpath string) error {
+	return rename(oldpath, newpath)
+}
diff --git a/third_party/gofrontend/libgo/go/os/file_plan9.go b/third_party/gofrontend/libgo/go/os/file_plan9.go
new file mode 100644
index 0000000..a804b81
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/file_plan9.go
@@ -0,0 +1,468 @@
+// 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.
+
+package os
+
+import (
+	"runtime"
+	"syscall"
+	"time"
+)
+
+// File represents an open file descriptor.
+type File struct {
+	*file
+}
+
+// file is the real representation of *File.
+// The extra level of indirection ensures that no clients of os
+// can overwrite this data, which could cause the finalizer
+// to close the wrong file descriptor.
+type file struct {
+	fd      int
+	name    string
+	dirinfo *dirInfo // nil unless directory being read
+}
+
+// Fd returns the integer Unix file descriptor referencing the open file.
+func (f *File) Fd() uintptr {
+	if f == nil {
+		return ^(uintptr(0))
+	}
+	return uintptr(f.fd)
+}
+
+// NewFile returns a new File with the given file descriptor and name.
+func NewFile(fd uintptr, name string) *File {
+	fdi := int(fd)
+	if fdi < 0 {
+		return nil
+	}
+	f := &File{&file{fd: fdi, name: name}}
+	runtime.SetFinalizer(f.file, (*file).close)
+	return f
+}
+
+// Auxiliary information if the File describes a directory
+type dirInfo struct {
+	buf  [syscall.STATMAX]byte // buffer for directory I/O
+	nbuf int                   // length of buf; return value from Read
+	bufp int                   // location of next record in buf.
+}
+
+func epipecheck(file *File, e error) {
+}
+
+// DevNull is the name of the operating system's ``null device.''
+// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
+const DevNull = "/dev/null"
+
+// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
+func syscallMode(i FileMode) (o uint32) {
+	o |= uint32(i.Perm())
+	if i&ModeAppend != 0 {
+		o |= syscall.DMAPPEND
+	}
+	if i&ModeExclusive != 0 {
+		o |= syscall.DMEXCL
+	}
+	if i&ModeTemporary != 0 {
+		o |= syscall.DMTMP
+	}
+	return
+}
+
+// OpenFile is the generalized open call; most users will use Open
+// or Create instead.  It opens the named file with specified flag
+// (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
+// methods on the returned File can be used for I/O.
+// If there is an error, it will be of type *PathError.
+func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
+	var (
+		fd     int
+		e      error
+		create bool
+		excl   bool
+		trunc  bool
+		append bool
+	)
+
+	if flag&O_CREATE == O_CREATE {
+		flag = flag & ^O_CREATE
+		create = true
+	}
+	if flag&O_EXCL == O_EXCL {
+		excl = true
+	}
+	if flag&O_TRUNC == O_TRUNC {
+		trunc = true
+	}
+	// O_APPEND is emulated on Plan 9
+	if flag&O_APPEND == O_APPEND {
+		flag = flag &^ O_APPEND
+		append = true
+	}
+
+	if (create && trunc) || excl {
+		fd, e = syscall.Create(name, flag, syscallMode(perm))
+	} else {
+		fd, e = syscall.Open(name, flag)
+		if e != nil && create {
+			var e1 error
+			fd, e1 = syscall.Create(name, flag, syscallMode(perm))
+			if e1 == nil {
+				e = nil
+			}
+		}
+	}
+
+	if e != nil {
+		return nil, &PathError{"open", name, e}
+	}
+
+	if append {
+		if _, e = syscall.Seek(fd, 0, SEEK_END); e != nil {
+			return nil, &PathError{"seek", name, e}
+		}
+	}
+
+	return NewFile(uintptr(fd), name), nil
+}
+
+// Close closes the File, rendering it unusable for I/O.
+// It returns an error, if any.
+func (f *File) Close() error {
+	if f == nil {
+		return ErrInvalid
+	}
+	return f.file.close()
+}
+
+func (file *file) close() error {
+	if file == nil || file.fd < 0 {
+		return ErrInvalid
+	}
+	var err error
+	syscall.ForkLock.RLock()
+	if e := syscall.Close(file.fd); e != nil {
+		err = &PathError{"close", file.name, e}
+	}
+	syscall.ForkLock.RUnlock()
+	file.fd = -1 // so it can't be closed again
+
+	// no need for a finalizer anymore
+	runtime.SetFinalizer(file, nil)
+	return err
+}
+
+// Stat returns the FileInfo structure describing file.
+// If there is an error, it will be of type *PathError.
+func (f *File) Stat() (fi FileInfo, err error) {
+	if f == nil {
+		return nil, ErrInvalid
+	}
+	d, err := dirstat(f)
+	if err != nil {
+		return nil, err
+	}
+	return fileInfoFromStat(d), nil
+}
+
+// Truncate changes the size of the file.
+// It does not change the I/O offset.
+// If there is an error, it will be of type *PathError.
+func (f *File) Truncate(size int64) error {
+	if f == nil {
+		return ErrInvalid
+	}
+
+	var d syscall.Dir
+	d.Null()
+	d.Length = size
+
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"truncate", f.name, err}
+	}
+	if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
+		return &PathError{"truncate", f.name, err}
+	}
+	return nil
+}
+
+const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | ModePerm)
+
+// Chmod changes the mode of the file to mode.
+// If there is an error, it will be of type *PathError.
+func (f *File) Chmod(mode FileMode) error {
+	if f == nil {
+		return ErrInvalid
+	}
+	var d syscall.Dir
+
+	odir, e := dirstat(f)
+	if e != nil {
+		return &PathError{"chmod", f.name, e}
+	}
+	d.Null()
+	d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
+
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"chmod", f.name, err}
+	}
+	if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
+		return &PathError{"chmod", f.name, err}
+	}
+	return nil
+}
+
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (f *File) Sync() (err error) {
+	if f == nil {
+		return ErrInvalid
+	}
+	var d syscall.Dir
+	d.Null()
+
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return NewSyscallError("fsync", err)
+	}
+	if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
+		return NewSyscallError("fsync", err)
+	}
+	return nil
+}
+
+// read reads up to len(b) bytes from the File.
+// It returns the number of bytes read and an error, if any.
+func (f *File) read(b []byte) (n int, err error) {
+	return syscall.Read(f.fd, b)
+}
+
+// pread reads len(b) bytes from the File starting at byte offset off.
+// It returns the number of bytes read and the error, if any.
+// EOF is signaled by a zero count with err set to nil.
+func (f *File) pread(b []byte, off int64) (n int, err error) {
+	return syscall.Pread(f.fd, b, off)
+}
+
+// write writes len(b) bytes to the File.
+// It returns the number of bytes written and an error, if any.
+// Since Plan 9 preserves message boundaries, never allow
+// a zero-byte write.
+func (f *File) write(b []byte) (n int, err error) {
+	if len(b) == 0 {
+		return 0, nil
+	}
+	return syscall.Write(f.fd, b)
+}
+
+// pwrite writes len(b) bytes to the File starting at byte offset off.
+// It returns the number of bytes written and an error, if any.
+// Since Plan 9 preserves message boundaries, never allow
+// a zero-byte write.
+func (f *File) pwrite(b []byte, off int64) (n int, err error) {
+	if len(b) == 0 {
+		return 0, nil
+	}
+	return syscall.Pwrite(f.fd, b, off)
+}
+
+// seek sets the offset for the next Read or Write on file to offset, interpreted
+// according to whence: 0 means relative to the origin of the file, 1 means
+// relative to the current offset, and 2 means relative to the end.
+// It returns the new offset and an error, if any.
+func (f *File) seek(offset int64, whence int) (ret int64, err error) {
+	return syscall.Seek(f.fd, offset, whence)
+}
+
+// Truncate changes the size of the named file.
+// If the file is a symbolic link, it changes the size of the link's target.
+// If there is an error, it will be of type *PathError.
+func Truncate(name string, size int64) error {
+	var d syscall.Dir
+
+	d.Null()
+	d.Length = size
+
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"truncate", name, err}
+	}
+	if err = syscall.Wstat(name, buf[:n]); err != nil {
+		return &PathError{"truncate", name, err}
+	}
+	return nil
+}
+
+// Remove removes the named file or directory.
+// If there is an error, it will be of type *PathError.
+func Remove(name string) error {
+	if e := syscall.Remove(name); e != nil {
+		return &PathError{"remove", name, e}
+	}
+	return nil
+}
+
+// HasPrefix from the strings package.
+func hasPrefix(s, prefix string) bool {
+	return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
+}
+
+// Variant of LastIndex from the strings package.
+func lastIndex(s string, sep byte) int {
+	for i := len(s) - 1; i >= 0; i-- {
+		if s[i] == sep {
+			return i
+		}
+	}
+	return -1
+}
+
+func rename(oldname, newname string) error {
+	dirname := oldname[:lastIndex(oldname, '/')+1]
+	if hasPrefix(newname, dirname) {
+		newname = newname[len(dirname):]
+	} else {
+		return &LinkError{"rename", oldname, newname, ErrInvalid}
+	}
+
+	// If newname still contains slashes after removing the oldname
+	// prefix, the rename is cross-directory and must be rejected.
+	// This case is caught by d.Marshal below.
+
+	var d syscall.Dir
+
+	d.Null()
+	d.Name = newname
+
+	buf := make([]byte, syscall.STATFIXLEN+len(d.Name))
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &LinkError{"rename", oldname, newname, err}
+	}
+	if err = syscall.Wstat(oldname, buf[:n]); err != nil {
+		return &LinkError{"rename", oldname, newname, err}
+	}
+	return nil
+}
+
+// Chmod changes the mode of the named file to mode.
+// If the file is a symbolic link, it changes the mode of the link's target.
+// If there is an error, it will be of type *PathError.
+func Chmod(name string, mode FileMode) error {
+	var d syscall.Dir
+
+	odir, e := dirstat(name)
+	if e != nil {
+		return &PathError{"chmod", name, e}
+	}
+	d.Null()
+	d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
+
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"chmod", name, err}
+	}
+	if err = syscall.Wstat(name, buf[:n]); err != nil {
+		return &PathError{"chmod", name, err}
+	}
+	return nil
+}
+
+// Chtimes changes the access and modification times of the named
+// file, similar to the Unix utime() or utimes() functions.
+//
+// The underlying filesystem may truncate or round the values to a
+// less precise time unit.
+// If there is an error, it will be of type *PathError.
+func Chtimes(name string, atime time.Time, mtime time.Time) error {
+	var d syscall.Dir
+
+	d.Null()
+	d.Atime = uint32(atime.Unix())
+	d.Mtime = uint32(mtime.Unix())
+
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"chtimes", name, err}
+	}
+	if err = syscall.Wstat(name, buf[:n]); err != nil {
+		return &PathError{"chtimes", name, err}
+	}
+	return nil
+}
+
+// Pipe returns a connected pair of Files; reads from r return bytes
+// written to w. It returns the files and an error, if any.
+func Pipe() (r *File, w *File, err error) {
+	var p [2]int
+
+	syscall.ForkLock.RLock()
+	if e := syscall.Pipe(p[0:]); e != nil {
+		syscall.ForkLock.RUnlock()
+		return nil, nil, NewSyscallError("pipe", e)
+	}
+	syscall.ForkLock.RUnlock()
+
+	return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
+}
+
+// not supported on Plan 9
+
+// Link creates newname as a hard link to the oldname file.
+// If there is an error, it will be of type *LinkError.
+func Link(oldname, newname string) error {
+	return &LinkError{"link", oldname, newname, syscall.EPLAN9}
+}
+
+// Symlink creates newname as a symbolic link to oldname.
+// If there is an error, it will be of type *LinkError.
+func Symlink(oldname, newname string) error {
+	return &LinkError{"symlink", oldname, newname, syscall.EPLAN9}
+}
+
+// Readlink returns the destination of the named symbolic link.
+// If there is an error, it will be of type *PathError.
+func Readlink(name string) (string, error) {
+	return "", &PathError{"readlink", name, syscall.EPLAN9}
+}
+
+// Chown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link's target.
+// If there is an error, it will be of type *PathError.
+func Chown(name string, uid, gid int) error {
+	return &PathError{"chown", name, syscall.EPLAN9}
+}
+
+// Lchown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link itself.
+// If there is an error, it will be of type *PathError.
+func Lchown(name string, uid, gid int) error {
+	return &PathError{"lchown", name, syscall.EPLAN9}
+}
+
+// Chown changes the numeric uid and gid of the named file.
+// If there is an error, it will be of type *PathError.
+func (f *File) Chown(uid, gid int) error {
+	if f == nil {
+		return ErrInvalid
+	}
+	return &PathError{"chown", f.name, syscall.EPLAN9}
+}
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+	return "/tmp"
+}
diff --git a/third_party/gofrontend/libgo/go/os/file_posix.go b/third_party/gofrontend/libgo/go/os/file_posix.go
new file mode 100644
index 0000000..b3466b1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/file_posix.go
@@ -0,0 +1,169 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package os
+
+import (
+	"syscall"
+	"time"
+)
+
+func sigpipe() // implemented in package runtime
+
+// Link creates newname as a hard link to the oldname file.
+// If there is an error, it will be of type *LinkError.
+func Link(oldname, newname string) error {
+	e := syscall.Link(oldname, newname)
+	if e != nil {
+		return &LinkError{"link", oldname, newname, e}
+	}
+	return nil
+}
+
+// Symlink creates newname as a symbolic link to oldname.
+// If there is an error, it will be of type *LinkError.
+func Symlink(oldname, newname string) error {
+	e := syscall.Symlink(oldname, newname)
+	if e != nil {
+		return &LinkError{"symlink", oldname, newname, e}
+	}
+	return nil
+}
+
+// Readlink returns the destination of the named symbolic link.
+// If there is an error, it will be of type *PathError.
+func Readlink(name string) (string, error) {
+	for len := 128; ; len *= 2 {
+		b := make([]byte, len)
+		n, e := syscall.Readlink(name, b)
+		if e != nil {
+			return "", &PathError{"readlink", name, e}
+		}
+		if n < len {
+			return string(b[0:n]), nil
+		}
+	}
+}
+
+func rename(oldname, newname string) error {
+	e := syscall.Rename(oldname, newname)
+	if e != nil {
+		return &LinkError{"rename", oldname, newname, e}
+	}
+	return nil
+}
+
+// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
+func syscallMode(i FileMode) (o uint32) {
+	o |= uint32(i.Perm())
+	if i&ModeSetuid != 0 {
+		o |= syscall.S_ISUID
+	}
+	if i&ModeSetgid != 0 {
+		o |= syscall.S_ISGID
+	}
+	if i&ModeSticky != 0 {
+		o |= syscall.S_ISVTX
+	}
+	// No mapping for Go's ModeTemporary (plan9 only).
+	return
+}
+
+// Chmod changes the mode of the named file to mode.
+// If the file is a symbolic link, it changes the mode of the link's target.
+// If there is an error, it will be of type *PathError.
+func Chmod(name string, mode FileMode) error {
+	if e := syscall.Chmod(name, syscallMode(mode)); e != nil {
+		return &PathError{"chmod", name, e}
+	}
+	return nil
+}
+
+// Chmod changes the mode of the file to mode.
+// If there is an error, it will be of type *PathError.
+func (f *File) Chmod(mode FileMode) error {
+	if f == nil {
+		return ErrInvalid
+	}
+	if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil {
+		return &PathError{"chmod", f.name, e}
+	}
+	return nil
+}
+
+// Chown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link's target.
+// If there is an error, it will be of type *PathError.
+func Chown(name string, uid, gid int) error {
+	if e := syscall.Chown(name, uid, gid); e != nil {
+		return &PathError{"chown", name, e}
+	}
+	return nil
+}
+
+// Lchown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link itself.
+// If there is an error, it will be of type *PathError.
+func Lchown(name string, uid, gid int) error {
+	if e := syscall.Lchown(name, uid, gid); e != nil {
+		return &PathError{"lchown", name, e}
+	}
+	return nil
+}
+
+// Chown changes the numeric uid and gid of the named file.
+// If there is an error, it will be of type *PathError.
+func (f *File) Chown(uid, gid int) error {
+	if f == nil {
+		return ErrInvalid
+	}
+	if e := syscall.Fchown(f.fd, uid, gid); e != nil {
+		return &PathError{"chown", f.name, e}
+	}
+	return nil
+}
+
+// Truncate changes the size of the file.
+// It does not change the I/O offset.
+// If there is an error, it will be of type *PathError.
+func (f *File) Truncate(size int64) error {
+	if f == nil {
+		return ErrInvalid
+	}
+	if e := syscall.Ftruncate(f.fd, size); e != nil {
+		return &PathError{"truncate", f.name, e}
+	}
+	return nil
+}
+
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (f *File) Sync() (err error) {
+	if f == nil {
+		return ErrInvalid
+	}
+	if e := syscall.Fsync(f.fd); e != nil {
+		return NewSyscallError("fsync", e)
+	}
+	return nil
+}
+
+// Chtimes changes the access and modification times of the named
+// file, similar to the Unix utime() or utimes() functions.
+//
+// The underlying filesystem may truncate or round the values to a
+// less precise time unit.
+// If there is an error, it will be of type *PathError.
+func Chtimes(name string, atime time.Time, mtime time.Time) error {
+	var utimes [2]syscall.Timespec
+	utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
+	utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())
+	if e := syscall.UtimesNano(name, utimes[0:]); e != nil {
+		return &PathError{"chtimes", name, e}
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/file_unix.go b/third_party/gofrontend/libgo/go/os/file_unix.go
new file mode 100644
index 0000000..7959091
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/file_unix.go
@@ -0,0 +1,325 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package os
+
+import (
+	"runtime"
+	"sync/atomic"
+	"syscall"
+)
+
+// File represents an open file descriptor.
+type File struct {
+	*file
+}
+
+// file is the real representation of *File.
+// The extra level of indirection ensures that no clients of os
+// can overwrite this data, which could cause the finalizer
+// to close the wrong file descriptor.
+type file struct {
+	fd      int
+	name    string
+	dirinfo *dirInfo // nil unless directory being read
+	nepipe  int32    // number of consecutive EPIPE in Write
+}
+
+// Fd returns the integer Unix file descriptor referencing the open file.
+func (f *File) Fd() uintptr {
+	if f == nil {
+		return ^(uintptr(0))
+	}
+	return uintptr(f.fd)
+}
+
+// NewFile returns a new File with the given file descriptor and name.
+func NewFile(fd uintptr, name string) *File {
+	fdi := int(fd)
+	if fdi < 0 {
+		return nil
+	}
+	f := &File{&file{fd: fdi, name: name}}
+	runtime.SetFinalizer(f.file, (*file).close)
+	return f
+}
+
+// Auxiliary information if the File describes a directory
+type dirInfo struct {
+	buf []byte       // buffer for directory I/O
+	dir *syscall.DIR // from opendir
+}
+
+func epipecheck(file *File, e error) {
+	if e == syscall.EPIPE {
+		if atomic.AddInt32(&file.nepipe, 1) >= 10 {
+			sigpipe()
+		}
+	} else {
+		atomic.StoreInt32(&file.nepipe, 0)
+	}
+}
+
+// DevNull is the name of the operating system's ``null device.''
+// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
+const DevNull = "/dev/null"
+
+// OpenFile is the generalized open call; most users will use Open
+// or Create instead.  It opens the named file with specified flag
+// (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
+// methods on the returned File can be used for I/O.
+// If there is an error, it will be of type *PathError.
+func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
+	r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
+	if e != nil {
+		return nil, &PathError{"open", name, e}
+	}
+
+	// There's a race here with fork/exec, which we are
+	// content to live with.  See ../syscall/exec_unix.go.
+	if !supportsCloseOnExec {
+		syscall.CloseOnExec(r)
+	}
+
+	return NewFile(uintptr(r), name), nil
+}
+
+// Close closes the File, rendering it unusable for I/O.
+// It returns an error, if any.
+func (f *File) Close() error {
+	if f == nil {
+		return ErrInvalid
+	}
+	return f.file.close()
+}
+
+func (file *file) close() error {
+	if file == nil || file.fd < 0 {
+		return syscall.EINVAL
+	}
+	var err error
+	if e := syscall.Close(file.fd); e != nil {
+		err = &PathError{"close", file.name, e}
+	}
+
+	if file.dirinfo != nil {
+		syscall.Entersyscall()
+		i := libc_closedir(file.dirinfo.dir)
+		errno := syscall.GetErrno()
+		syscall.Exitsyscall()
+		file.dirinfo = nil
+		if i < 0 && err == nil {
+			err = &PathError{"closedir", file.name, errno}
+		}
+	}
+
+	file.fd = -1 // so it can't be closed again
+
+	// no need for a finalizer anymore
+	runtime.SetFinalizer(file, nil)
+	return err
+}
+
+// Stat returns the FileInfo structure describing file.
+// If there is an error, it will be of type *PathError.
+func (f *File) Stat() (fi FileInfo, err error) {
+	if f == nil {
+		return nil, ErrInvalid
+	}
+	var stat syscall.Stat_t
+	err = syscall.Fstat(f.fd, &stat)
+	if err != nil {
+		return nil, &PathError{"stat", f.name, err}
+	}
+	return fileInfoFromStat(&stat, f.name), nil
+}
+
+// Stat returns a FileInfo describing the named file.
+// If there is an error, it will be of type *PathError.
+func Stat(name string) (fi FileInfo, err error) {
+	var stat syscall.Stat_t
+	err = syscall.Stat(name, &stat)
+	if err != nil {
+		return nil, &PathError{"stat", name, err}
+	}
+	return fileInfoFromStat(&stat, name), nil
+}
+
+// Lstat returns a FileInfo describing the named file.
+// If the file is a symbolic link, the returned FileInfo
+// describes the symbolic link.  Lstat makes no attempt to follow the link.
+// If there is an error, it will be of type *PathError.
+func Lstat(name string) (fi FileInfo, err error) {
+	var stat syscall.Stat_t
+	err = syscall.Lstat(name, &stat)
+	if err != nil {
+		return nil, &PathError{"lstat", name, err}
+	}
+	return fileInfoFromStat(&stat, name), nil
+}
+
+func (f *File) readdir(n int) (fi []FileInfo, err error) {
+	dirname := f.name
+	if dirname == "" {
+		dirname = "."
+	}
+	names, err := f.Readdirnames(n)
+	fi = make([]FileInfo, 0, len(names))
+	for _, filename := range names {
+		fip, lerr := lstat(dirname + "/" + filename)
+		if IsNotExist(lerr) {
+			// File disappeared between readdir + stat.
+			// Just treat it as if it didn't exist.
+			continue
+		}
+		if lerr != nil {
+			return fi, lerr
+		}
+		fi = append(fi, fip)
+	}
+	return fi, err
+}
+
+// Darwin and FreeBSD can't read or write 2GB+ at a time,
+// even on 64-bit systems. See golang.org/issue/7812.
+// Use 1GB instead of, say, 2GB-1, to keep subsequent
+// reads aligned.
+const (
+	needsMaxRW = runtime.GOOS == "darwin" || runtime.GOOS == "freebsd"
+	maxRW      = 1 << 30
+)
+
+// read reads up to len(b) bytes from the File.
+// It returns the number of bytes read and an error, if any.
+func (f *File) read(b []byte) (n int, err error) {
+	if needsMaxRW && len(b) > maxRW {
+		b = b[:maxRW]
+	}
+	return syscall.Read(f.fd, b)
+}
+
+// pread reads len(b) bytes from the File starting at byte offset off.
+// It returns the number of bytes read and the error, if any.
+// EOF is signaled by a zero count with err set to nil.
+func (f *File) pread(b []byte, off int64) (n int, err error) {
+	if needsMaxRW && len(b) > maxRW {
+		b = b[:maxRW]
+	}
+	return syscall.Pread(f.fd, b, off)
+}
+
+// write writes len(b) bytes to the File.
+// It returns the number of bytes written and an error, if any.
+func (f *File) write(b []byte) (n int, err error) {
+	for {
+		bcap := b
+		if needsMaxRW && len(bcap) > maxRW {
+			bcap = bcap[:maxRW]
+		}
+		m, err := syscall.Write(f.fd, bcap)
+		n += m
+
+		// If the syscall wrote some data but not all (short write)
+		// or it returned EINTR, then assume it stopped early for
+		// reasons that are uninteresting to the caller, and try again.
+		if 0 < m && m < len(bcap) || err == syscall.EINTR {
+			b = b[m:]
+			continue
+		}
+
+		if needsMaxRW && len(bcap) != len(b) && err == nil {
+			b = b[m:]
+			continue
+		}
+
+		return n, err
+	}
+}
+
+// pwrite writes len(b) bytes to the File starting at byte offset off.
+// It returns the number of bytes written and an error, if any.
+func (f *File) pwrite(b []byte, off int64) (n int, err error) {
+	if needsMaxRW && len(b) > maxRW {
+		b = b[:maxRW]
+	}
+	return syscall.Pwrite(f.fd, b, off)
+}
+
+// seek sets the offset for the next Read or Write on file to offset, interpreted
+// according to whence: 0 means relative to the origin of the file, 1 means
+// relative to the current offset, and 2 means relative to the end.
+// It returns the new offset and an error, if any.
+func (f *File) seek(offset int64, whence int) (ret int64, err error) {
+	return syscall.Seek(f.fd, offset, whence)
+}
+
+// Truncate changes the size of the named file.
+// If the file is a symbolic link, it changes the size of the link's target.
+// If there is an error, it will be of type *PathError.
+func Truncate(name string, size int64) error {
+	if e := syscall.Truncate(name, size); e != nil {
+		return &PathError{"truncate", name, e}
+	}
+	return nil
+}
+
+// Remove removes the named file or directory.
+// If there is an error, it will be of type *PathError.
+func Remove(name string) error {
+	// System call interface forces us to know
+	// whether name is a file or directory.
+	// Try both: it is cheaper on average than
+	// doing a Stat plus the right one.
+	e := syscall.Unlink(name)
+	if e == nil {
+		return nil
+	}
+	e1 := syscall.Rmdir(name)
+	if e1 == nil {
+		return nil
+	}
+
+	// Both failed: figure out which error to return.
+	// OS X and Linux differ on whether unlink(dir)
+	// returns EISDIR, so can't use that.  However,
+	// both agree that rmdir(file) returns ENOTDIR,
+	// so we can use that to decide which error is real.
+	// Rmdir might also return ENOTDIR if given a bad
+	// file path, like /etc/passwd/foo, but in that case,
+	// both errors will be ENOTDIR, so it's okay to
+	// use the error from unlink.
+	if e1 != syscall.ENOTDIR {
+		e = e1
+	}
+	return &PathError{"remove", name, e}
+}
+
+// basename removes trailing slashes and the leading directory name from path name
+func basename(name string) string {
+	i := len(name) - 1
+	// Remove trailing slashes
+	for ; i > 0 && name[i] == '/'; i-- {
+		name = name[:i]
+	}
+	// Remove leading directory name
+	for i--; i >= 0; i-- {
+		if name[i] == '/' {
+			name = name[i+1:]
+			break
+		}
+	}
+
+	return name
+}
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+	dir := Getenv("TMPDIR")
+	if dir == "" {
+		dir = "/tmp"
+	}
+	return dir
+}
diff --git a/third_party/gofrontend/libgo/go/os/getwd.go b/third_party/gofrontend/libgo/go/os/getwd.go
new file mode 100644
index 0000000..a72edea
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/getwd.go
@@ -0,0 +1,119 @@
+// 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 os
+
+import (
+	"sync"
+	"syscall"
+)
+
+var getwdCache struct {
+	sync.Mutex
+	dir string
+}
+
+// useSyscallwd determines whether to use the return value of
+// syscall.Getwd based on its error.
+var useSyscallwd = func(error) bool { return true }
+
+// Getwd returns a rooted path name corresponding to the
+// current directory.  If the current directory can be
+// reached via multiple paths (due to symbolic links),
+// Getwd may return any one of them.
+func Getwd() (dir string, err error) {
+	// If the operating system provides a Getwd call, use it.
+	if syscall.ImplementsGetwd {
+		s, e := syscall.Getwd()
+		if useSyscallwd(e) {
+			return s, NewSyscallError("getwd", e)
+		}
+	}
+
+	// Otherwise, we're trying to find our way back to ".".
+	dot, err := Stat(".")
+	if err != nil {
+		return "", err
+	}
+
+	// Clumsy but widespread kludge:
+	// if $PWD is set and matches ".", use it.
+	dir = Getenv("PWD")
+	if len(dir) > 0 && dir[0] == '/' {
+		d, err := Stat(dir)
+		if err == nil && SameFile(dot, d) {
+			return dir, nil
+		}
+	}
+
+	// Apply same kludge but to cached dir instead of $PWD.
+	getwdCache.Lock()
+	dir = getwdCache.dir
+	getwdCache.Unlock()
+	if len(dir) > 0 {
+		d, err := Stat(dir)
+		if err == nil && SameFile(dot, d) {
+			return dir, nil
+		}
+	}
+
+	// Root is a special case because it has no parent
+	// and ends in a slash.
+	root, err := Stat("/")
+	if err != nil {
+		// Can't stat root - no hope.
+		return "", err
+	}
+	if SameFile(root, dot) {
+		return "/", nil
+	}
+
+	// General algorithm: find name in parent
+	// and then find name of parent.  Each iteration
+	// adds /name to the beginning of dir.
+	dir = ""
+	for parent := ".."; ; parent = "../" + parent {
+		if len(parent) >= 1024 { // Sanity check
+			return "", syscall.ENAMETOOLONG
+		}
+		fd, err := Open(parent)
+		if err != nil {
+			return "", err
+		}
+
+		for {
+			names, err := fd.Readdirnames(100)
+			if err != nil {
+				fd.Close()
+				return "", err
+			}
+			for _, name := range names {
+				d, _ := Lstat(parent + "/" + name)
+				if SameFile(d, dot) {
+					dir = "/" + name + dir
+					goto Found
+				}
+			}
+		}
+
+	Found:
+		pd, err := fd.Stat()
+		if err != nil {
+			return "", err
+		}
+		fd.Close()
+		if SameFile(pd, root) {
+			break
+		}
+		// Set up for next round.
+		dot = pd
+	}
+
+	// Save answer as hint to avoid the expensive path next time.
+	getwdCache.Lock()
+	getwdCache.dir = dir
+	getwdCache.Unlock()
+
+	return dir, nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/getwd_darwin.go b/third_party/gofrontend/libgo/go/os/getwd_darwin.go
new file mode 100644
index 0000000..e51ffcd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/getwd_darwin.go
@@ -0,0 +1,15 @@
+// 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 os
+
+import "syscall"
+
+func init() {
+	useSyscallwd = useSyscallwdDarwin
+}
+
+func useSyscallwdDarwin(err error) bool {
+	return err != syscall.ENOTSUP
+}
diff --git a/third_party/gofrontend/libgo/go/os/os_test.go b/third_party/gofrontend/libgo/go/os/os_test.go
new file mode 100644
index 0000000..a34e328
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/os_test.go
@@ -0,0 +1,1338 @@
+// 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 os_test
+
+import (
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	. "os"
+	osexec "os/exec"
+	"path/filepath"
+	"reflect"
+	"runtime"
+	"sort"
+	"strings"
+	"syscall"
+	"testing"
+	"text/template"
+	"time"
+)
+
+var dot = []string{
+	"dir_unix.go",
+	"env.go",
+	"error.go",
+	"file.go",
+	"os_test.go",
+	"types.go",
+}
+
+type sysDir struct {
+	name  string
+	files []string
+}
+
+var sysdir = func() (sd *sysDir) {
+	switch runtime.GOOS {
+	case "windows":
+		sd = &sysDir{
+			Getenv("SystemRoot") + "\\system32\\drivers\\etc",
+			[]string{
+				"networks",
+				"protocol",
+				"services",
+			},
+		}
+	case "plan9":
+		sd = &sysDir{
+			"/lib/ndb",
+			[]string{
+				"common",
+				"local",
+			},
+		}
+	default:
+		sd = &sysDir{
+			"/etc",
+			[]string{
+				"group",
+				"hosts",
+				"passwd",
+			},
+		}
+	}
+	return
+}()
+
+func size(name string, t *testing.T) int64 {
+	file, err := Open(name)
+	if err != nil {
+		t.Fatal("open failed:", err)
+	}
+	defer file.Close()
+	var buf [100]byte
+	len := 0
+	for {
+		n, e := file.Read(buf[0:])
+		len += n
+		if e == io.EOF {
+			break
+		}
+		if e != nil {
+			t.Fatal("read failed:", err)
+		}
+	}
+	return int64(len)
+}
+
+func equal(name1, name2 string) (r bool) {
+	switch runtime.GOOS {
+	case "windows":
+		r = strings.ToLower(name1) == strings.ToLower(name2)
+	default:
+		r = name1 == name2
+	}
+	return
+}
+
+func newFile(testName string, t *testing.T) (f *File) {
+	// Use a local file system, not NFS.
+	// On Unix, override $TMPDIR in case the user
+	// has it set to an NFS-mounted directory.
+	dir := ""
+	if runtime.GOOS != "windows" {
+		dir = "/tmp"
+	}
+	f, err := ioutil.TempFile(dir, "_Go_"+testName)
+	if err != nil {
+		t.Fatalf("open %s: %s", testName, err)
+	}
+	return
+}
+
+var sfdir = sysdir.name
+var sfname = sysdir.files[0]
+
+func TestStat(t *testing.T) {
+	path := sfdir + "/" + sfname
+	dir, err := Stat(path)
+	if err != nil {
+		t.Fatal("stat failed:", err)
+	}
+	if !equal(sfname, dir.Name()) {
+		t.Error("name should be ", sfname, "; is", dir.Name())
+	}
+	filesize := size(path, t)
+	if dir.Size() != filesize {
+		t.Error("size should be", filesize, "; is", dir.Size())
+	}
+}
+
+func TestFstat(t *testing.T) {
+	path := sfdir + "/" + sfname
+	file, err1 := Open(path)
+	if err1 != nil {
+		t.Fatal("open failed:", err1)
+	}
+	defer file.Close()
+	dir, err2 := file.Stat()
+	if err2 != nil {
+		t.Fatal("fstat failed:", err2)
+	}
+	if !equal(sfname, dir.Name()) {
+		t.Error("name should be ", sfname, "; is", dir.Name())
+	}
+	filesize := size(path, t)
+	if dir.Size() != filesize {
+		t.Error("size should be", filesize, "; is", dir.Size())
+	}
+}
+
+func TestLstat(t *testing.T) {
+	path := sfdir + "/" + sfname
+	dir, err := Lstat(path)
+	if err != nil {
+		t.Fatal("lstat failed:", err)
+	}
+	if !equal(sfname, dir.Name()) {
+		t.Error("name should be ", sfname, "; is", dir.Name())
+	}
+	filesize := size(path, t)
+	if dir.Size() != filesize {
+		t.Error("size should be", filesize, "; is", dir.Size())
+	}
+}
+
+// Read with length 0 should not return EOF.
+func TestRead0(t *testing.T) {
+	path := sfdir + "/" + sfname
+	f, err := Open(path)
+	if err != nil {
+		t.Fatal("open failed:", err)
+	}
+	defer f.Close()
+
+	b := make([]byte, 0)
+	n, err := f.Read(b)
+	if n != 0 || err != nil {
+		t.Errorf("Read(0) = %d, %v, want 0, nil", n, err)
+	}
+	b = make([]byte, 100)
+	n, err = f.Read(b)
+	if n <= 0 || err != nil {
+		t.Errorf("Read(100) = %d, %v, want >0, nil", n, err)
+	}
+}
+
+func testReaddirnames(dir string, contents []string, t *testing.T) {
+	file, err := Open(dir)
+	if err != nil {
+		t.Fatalf("open %q failed: %v", dir, err)
+	}
+	defer file.Close()
+	s, err2 := file.Readdirnames(-1)
+	if err2 != nil {
+		t.Fatalf("readdirnames %q failed: %v", dir, err2)
+	}
+	for _, m := range contents {
+		found := false
+		for _, n := range s {
+			if n == "." || n == ".." {
+				t.Errorf("got %s in directory", n)
+			}
+			if equal(m, n) {
+				if found {
+					t.Error("present twice:", m)
+				}
+				found = true
+			}
+		}
+		if !found {
+			t.Error("could not find", m)
+		}
+	}
+}
+
+func testReaddir(dir string, contents []string, t *testing.T) {
+	file, err := Open(dir)
+	if err != nil {
+		t.Fatalf("open %q failed: %v", dir, err)
+	}
+	defer file.Close()
+	s, err2 := file.Readdir(-1)
+	if err2 != nil {
+		t.Fatalf("readdir %q failed: %v", dir, err2)
+	}
+	for _, m := range contents {
+		found := false
+		for _, n := range s {
+			if equal(m, n.Name()) {
+				if found {
+					t.Error("present twice:", m)
+				}
+				found = true
+			}
+		}
+		if !found {
+			t.Error("could not find", m)
+		}
+	}
+}
+
+func TestReaddirnames(t *testing.T) {
+	testReaddirnames(".", dot, t)
+	testReaddirnames(sysdir.name, sysdir.files, t)
+}
+
+func TestReaddir(t *testing.T) {
+	testReaddir(".", dot, t)
+	testReaddir(sysdir.name, sysdir.files, t)
+}
+
+// Read the directory one entry at a time.
+func smallReaddirnames(file *File, length int, t *testing.T) []string {
+	names := make([]string, length)
+	count := 0
+	for {
+		d, err := file.Readdirnames(1)
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			t.Fatalf("readdirnames %q failed: %v", file.Name(), err)
+		}
+		if len(d) == 0 {
+			t.Fatalf("readdirnames %q returned empty slice and no error", file.Name())
+		}
+		names[count] = d[0]
+		count++
+	}
+	return names[0:count]
+}
+
+// Check that reading a directory one entry at a time gives the same result
+// as reading it all at once.
+func TestReaddirnamesOneAtATime(t *testing.T) {
+	// big directory that doesn't change often.
+	dir := "/usr/bin"
+	switch runtime.GOOS {
+	case "windows":
+		dir = Getenv("SystemRoot") + "\\system32"
+	case "plan9":
+		dir = "/bin"
+	}
+	file, err := Open(dir)
+	if err != nil {
+		t.Fatalf("open %q failed: %v", dir, err)
+	}
+	defer file.Close()
+	all, err1 := file.Readdirnames(-1)
+	if err1 != nil {
+		t.Fatalf("readdirnames %q failed: %v", dir, err1)
+	}
+	file1, err2 := Open(dir)
+	if err2 != nil {
+		t.Fatalf("open %q failed: %v", dir, err2)
+	}
+	defer file1.Close()
+	small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
+	if len(small) < len(all) {
+		t.Fatalf("len(small) is %d, less than %d", len(small), len(all))
+	}
+	for i, n := range all {
+		if small[i] != n {
+			t.Errorf("small read %q mismatch: %v", small[i], n)
+		}
+	}
+}
+
+func TestReaddirNValues(t *testing.T) {
+	if testing.Short() {
+		t.Skip("test.short; skipping")
+	}
+	dir, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Fatalf("TempDir: %v", err)
+	}
+	defer RemoveAll(dir)
+	for i := 1; i <= 105; i++ {
+		f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i)))
+		if err != nil {
+			t.Fatalf("Create: %v", err)
+		}
+		f.Write([]byte(strings.Repeat("X", i)))
+		f.Close()
+	}
+
+	var d *File
+	openDir := func() {
+		var err error
+		d, err = Open(dir)
+		if err != nil {
+			t.Fatalf("Open directory: %v", err)
+		}
+	}
+
+	readDirExpect := func(n, want int, wantErr error) {
+		fi, err := d.Readdir(n)
+		if err != wantErr {
+			t.Fatalf("Readdir of %d got error %v, want %v", n, err, wantErr)
+		}
+		if g, e := len(fi), want; g != e {
+			t.Errorf("Readdir of %d got %d files, want %d", n, g, e)
+		}
+	}
+
+	readDirNamesExpect := func(n, want int, wantErr error) {
+		fi, err := d.Readdirnames(n)
+		if err != wantErr {
+			t.Fatalf("Readdirnames of %d got error %v, want %v", n, err, wantErr)
+		}
+		if g, e := len(fi), want; g != e {
+			t.Errorf("Readdirnames of %d got %d files, want %d", n, g, e)
+		}
+	}
+
+	for _, fn := range []func(int, int, error){readDirExpect, readDirNamesExpect} {
+		// Test the slurp case
+		openDir()
+		fn(0, 105, nil)
+		fn(0, 0, nil)
+		d.Close()
+
+		// Slurp with -1 instead
+		openDir()
+		fn(-1, 105, nil)
+		fn(-2, 0, nil)
+		fn(0, 0, nil)
+		d.Close()
+
+		// Test the bounded case
+		openDir()
+		fn(1, 1, nil)
+		fn(2, 2, nil)
+		fn(105, 102, nil) // and tests buffer >100 case
+		fn(3, 0, io.EOF)
+		d.Close()
+	}
+}
+
+func touch(t *testing.T, name string) {
+	f, err := Create(name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := f.Close(); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestReaddirStatFailures(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows", "plan9":
+		// Windows and Plan 9 already do this correctly,
+		// but are structured with different syscalls such
+		// that they don't use Lstat, so the hook below for
+		// testing it wouldn't work.
+		t.Skipf("skipping test on %v", runtime.GOOS)
+	}
+	dir, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Fatalf("TempDir: %v", err)
+	}
+	defer RemoveAll(dir)
+	touch(t, filepath.Join(dir, "good1"))
+	touch(t, filepath.Join(dir, "x")) // will disappear or have an error
+	touch(t, filepath.Join(dir, "good2"))
+	defer func() {
+		*LstatP = Lstat
+	}()
+	var xerr error // error to return for x
+	*LstatP = func(path string) (FileInfo, error) {
+		if xerr != nil && strings.HasSuffix(path, "x") {
+			return nil, xerr
+		}
+		return Lstat(path)
+	}
+	readDir := func() ([]FileInfo, error) {
+		d, err := Open(dir)
+		if err != nil {
+			t.Fatal(err)
+		}
+		defer d.Close()
+		return d.Readdir(-1)
+	}
+	mustReadDir := func(testName string) []FileInfo {
+		fis, err := readDir()
+		if err != nil {
+			t.Fatalf("%s: Readdir: %v", testName, err)
+		}
+		return fis
+	}
+	names := func(fis []FileInfo) []string {
+		s := make([]string, len(fis))
+		for i, fi := range fis {
+			s[i] = fi.Name()
+		}
+		sort.Strings(s)
+		return s
+	}
+
+	if got, want := names(mustReadDir("inital readdir")),
+		[]string{"good1", "good2", "x"}; !reflect.DeepEqual(got, want) {
+		t.Errorf("initial readdir got %q; want %q", got, want)
+	}
+
+	xerr = ErrNotExist
+	if got, want := names(mustReadDir("with x disappearing")),
+		[]string{"good1", "good2"}; !reflect.DeepEqual(got, want) {
+		t.Errorf("with x disappearing, got %q; want %q", got, want)
+	}
+
+	xerr = errors.New("some real error")
+	if _, err := readDir(); err != xerr {
+		t.Errorf("with a non-ErrNotExist error, got error %v; want %v", err, xerr)
+	}
+}
+
+func TestHardLink(t *testing.T) {
+	// Hardlinks are not supported under windows or Plan 9.
+	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+		return
+	}
+	from, to := "hardlinktestfrom", "hardlinktestto"
+	Remove(from) // Just in case.
+	file, err := Create(to)
+	if err != nil {
+		t.Fatalf("open %q failed: %v", to, err)
+	}
+	defer Remove(to)
+	if err = file.Close(); err != nil {
+		t.Errorf("close %q failed: %v", to, err)
+	}
+	err = Link(to, from)
+	if err != nil {
+		t.Fatalf("link %q, %q failed: %v", to, from, err)
+	}
+	defer Remove(from)
+	tostat, err := Stat(to)
+	if err != nil {
+		t.Fatalf("stat %q failed: %v", to, err)
+	}
+	fromstat, err := Stat(from)
+	if err != nil {
+		t.Fatalf("stat %q failed: %v", from, err)
+	}
+	if !SameFile(tostat, fromstat) {
+		t.Errorf("link %q, %q did not create hard link", to, from)
+	}
+}
+
+func TestSymlink(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows", "plan9", "nacl":
+		t.Skipf("skipping on %s", runtime.GOOS)
+	}
+	from, to := "symlinktestfrom", "symlinktestto"
+	Remove(from) // Just in case.
+	file, err := Create(to)
+	if err != nil {
+		t.Fatalf("open %q failed: %v", to, err)
+	}
+	defer Remove(to)
+	if err = file.Close(); err != nil {
+		t.Errorf("close %q failed: %v", to, err)
+	}
+	err = Symlink(to, from)
+	if err != nil {
+		t.Fatalf("symlink %q, %q failed: %v", to, from, err)
+	}
+	defer Remove(from)
+	tostat, err := Lstat(to)
+	if err != nil {
+		t.Fatalf("stat %q failed: %v", to, err)
+	}
+	if tostat.Mode()&ModeSymlink != 0 {
+		t.Fatalf("stat %q claims to have found a symlink", to)
+	}
+	fromstat, err := Stat(from)
+	if err != nil {
+		t.Fatalf("stat %q failed: %v", from, err)
+	}
+	if !SameFile(tostat, fromstat) {
+		t.Errorf("symlink %q, %q did not create symlink", to, from)
+	}
+	fromstat, err = Lstat(from)
+	if err != nil {
+		t.Fatalf("lstat %q failed: %v", from, err)
+	}
+	if fromstat.Mode()&ModeSymlink == 0 {
+		t.Fatalf("symlink %q, %q did not create symlink", to, from)
+	}
+	fromstat, err = Stat(from)
+	if err != nil {
+		t.Fatalf("stat %q failed: %v", from, err)
+	}
+	if fromstat.Mode()&ModeSymlink != 0 {
+		t.Fatalf("stat %q did not follow symlink", from)
+	}
+	s, err := Readlink(from)
+	if err != nil {
+		t.Fatalf("readlink %q failed: %v", from, err)
+	}
+	if s != to {
+		t.Fatalf("after symlink %q != %q", s, to)
+	}
+	file, err = Open(from)
+	if err != nil {
+		t.Fatalf("open %q failed: %v", from, err)
+	}
+	file.Close()
+}
+
+func TestLongSymlink(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows", "plan9", "nacl":
+		t.Skipf("skipping on %s", runtime.GOOS)
+	}
+	s := "0123456789abcdef"
+	// Long, but not too long: a common limit is 255.
+	s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s
+	from := "longsymlinktestfrom"
+	Remove(from) // Just in case.
+	err := Symlink(s, from)
+	if err != nil {
+		t.Fatalf("symlink %q, %q failed: %v", s, from, err)
+	}
+	defer Remove(from)
+	r, err := Readlink(from)
+	if err != nil {
+		t.Fatalf("readlink %q failed: %v", from, err)
+	}
+	if r != s {
+		t.Fatalf("after symlink %q != %q", r, s)
+	}
+}
+
+func TestRename(t *testing.T) {
+	from, to := "renamefrom", "renameto"
+	Remove(to) // Just in case.
+	file, err := Create(from)
+	if err != nil {
+		t.Fatalf("open %q failed: %v", to, err)
+	}
+	if err = file.Close(); err != nil {
+		t.Errorf("close %q failed: %v", to, err)
+	}
+	err = Rename(from, to)
+	if err != nil {
+		t.Fatalf("rename %q, %q failed: %v", to, from, err)
+	}
+	defer Remove(to)
+	_, err = Stat(to)
+	if err != nil {
+		t.Errorf("stat %q failed: %v", to, err)
+	}
+}
+
+func exec(t *testing.T, dir, cmd string, args []string, expect string) {
+	r, w, err := Pipe()
+	if err != nil {
+		t.Fatalf("Pipe: %v", err)
+	}
+	defer r.Close()
+	attr := &ProcAttr{Dir: dir, Files: []*File{nil, w, Stderr}}
+	p, err := StartProcess(cmd, args, attr)
+	if err != nil {
+		t.Fatalf("StartProcess: %v", err)
+	}
+	w.Close()
+
+	var b bytes.Buffer
+	io.Copy(&b, r)
+	output := b.String()
+
+	fi1, _ := Stat(strings.TrimSpace(output))
+	fi2, _ := Stat(expect)
+	if !SameFile(fi1, fi2) {
+		t.Errorf("exec %q returned %q wanted %q",
+			strings.Join(append([]string{cmd}, args...), " "), output, expect)
+	}
+	p.Wait()
+}
+
+func TestStartProcess(t *testing.T) {
+	if runtime.GOOS == "nacl" {
+		t.Skip("skipping on nacl")
+	}
+
+	var dir, cmd string
+	var args []string
+	if runtime.GOOS == "windows" {
+		cmd = Getenv("COMSPEC")
+		dir = Getenv("SystemRoot")
+		args = []string{"/c", "cd"}
+	} else {
+		cmd = "/bin/pwd"
+		dir = "/"
+		args = []string{}
+	}
+	cmddir, cmdbase := filepath.Split(cmd)
+	args = append([]string{cmdbase}, args...)
+	// Test absolute executable path.
+	exec(t, dir, cmd, args, dir)
+	// Test relative executable path.
+	exec(t, cmddir, cmdbase, args, cmddir)
+}
+
+func checkMode(t *testing.T, path string, mode FileMode) {
+	dir, err := Stat(path)
+	if err != nil {
+		t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
+	}
+	if dir.Mode()&0777 != mode {
+		t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode(), mode)
+	}
+}
+
+func TestChmod(t *testing.T) {
+	// Chmod is not supported under windows.
+	if runtime.GOOS == "windows" {
+		return
+	}
+	f := newFile("TestChmod", t)
+	defer Remove(f.Name())
+	defer f.Close()
+
+	if err := Chmod(f.Name(), 0456); err != nil {
+		t.Fatalf("chmod %s 0456: %s", f.Name(), err)
+	}
+	checkMode(t, f.Name(), 0456)
+
+	if err := f.Chmod(0123); err != nil {
+		t.Fatalf("chmod %s 0123: %s", f.Name(), err)
+	}
+	checkMode(t, f.Name(), 0123)
+}
+
+func checkSize(t *testing.T, f *File, size int64) {
+	dir, err := f.Stat()
+	if err != nil {
+		t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err)
+	}
+	if dir.Size() != size {
+		t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size)
+	}
+}
+
+func TestFTruncate(t *testing.T) {
+	f := newFile("TestFTruncate", t)
+	defer Remove(f.Name())
+	defer f.Close()
+
+	checkSize(t, f, 0)
+	f.Write([]byte("hello, world\n"))
+	checkSize(t, f, 13)
+	f.Truncate(10)
+	checkSize(t, f, 10)
+	f.Truncate(1024)
+	checkSize(t, f, 1024)
+	f.Truncate(0)
+	checkSize(t, f, 0)
+	_, err := f.Write([]byte("surprise!"))
+	if err == nil {
+		checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
+	}
+}
+
+func TestTruncate(t *testing.T) {
+	f := newFile("TestTruncate", t)
+	defer Remove(f.Name())
+	defer f.Close()
+
+	checkSize(t, f, 0)
+	f.Write([]byte("hello, world\n"))
+	checkSize(t, f, 13)
+	Truncate(f.Name(), 10)
+	checkSize(t, f, 10)
+	Truncate(f.Name(), 1024)
+	checkSize(t, f, 1024)
+	Truncate(f.Name(), 0)
+	checkSize(t, f, 0)
+	_, err := f.Write([]byte("surprise!"))
+	if err == nil {
+		checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
+	}
+}
+
+// Use TempDir() to make sure we're on a local file system,
+// so that timings are not distorted by latency and caching.
+// On NFS, timings can be off due to caching of meta-data on
+// NFS servers (Issue 848).
+func TestChtimes(t *testing.T) {
+	f := newFile("TestChtimes", t)
+	defer Remove(f.Name())
+	defer f.Close()
+
+	f.Write([]byte("hello, world\n"))
+	f.Close()
+
+	st, err := Stat(f.Name())
+	if err != nil {
+		t.Fatalf("Stat %s: %s", f.Name(), err)
+	}
+	preStat := st
+
+	// Move access and modification time back a second
+	at := Atime(preStat)
+	mt := preStat.ModTime()
+	err = Chtimes(f.Name(), at.Add(-time.Second), mt.Add(-time.Second))
+	if err != nil {
+		t.Fatalf("Chtimes %s: %s", f.Name(), err)
+	}
+
+	st, err = Stat(f.Name())
+	if err != nil {
+		t.Fatalf("second Stat %s: %s", f.Name(), err)
+	}
+	postStat := st
+
+	/* Plan 9, NaCl:
+		Mtime is the time of the last change of content.  Similarly, atime is set whenever the
+	    contents are accessed; also, it is set whenever mtime is set.
+	*/
+	pat := Atime(postStat)
+	pmt := postStat.ModTime()
+	if !pat.Before(at) && runtime.GOOS != "plan9" && runtime.GOOS != "nacl" {
+		t.Errorf("AccessTime didn't go backwards; was=%d, after=%d", at, pat)
+	}
+
+	if !pmt.Before(mt) {
+		t.Errorf("ModTime didn't go backwards; was=%d, after=%d", mt, pmt)
+	}
+}
+
+func TestChdirAndGetwd(t *testing.T) {
+	// TODO(brainman): file.Chdir() is not implemented on windows.
+	if runtime.GOOS == "windows" {
+		return
+	}
+	fd, err := Open(".")
+	if err != nil {
+		t.Fatalf("Open .: %s", err)
+	}
+	// These are chosen carefully not to be symlinks on a Mac
+	// (unlike, say, /var, /etc, and /tmp).
+	dirs := []string{"/", "/usr/bin"}
+	// /usr/bin does not usually exist on Plan 9.
+	if runtime.GOOS == "plan9" {
+		dirs = []string{"/", "/usr"}
+	}
+	for mode := 0; mode < 2; mode++ {
+		for _, d := range dirs {
+			if mode == 0 {
+				err = Chdir(d)
+			} else {
+				fd1, err := Open(d)
+				if err != nil {
+					t.Errorf("Open %s: %s", d, err)
+					continue
+				}
+				err = fd1.Chdir()
+				fd1.Close()
+			}
+			pwd, err1 := Getwd()
+			err2 := fd.Chdir()
+			if err2 != nil {
+				// We changed the current directory and cannot go back.
+				// Don't let the tests continue; they'll scribble
+				// all over some other directory.
+				fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2)
+				Exit(1)
+			}
+			if err != nil {
+				fd.Close()
+				t.Fatalf("Chdir %s: %s", d, err)
+			}
+			if err1 != nil {
+				fd.Close()
+				t.Fatalf("Getwd in %s: %s", d, err1)
+			}
+			if pwd != d {
+				fd.Close()
+				t.Fatalf("Getwd returned %q want %q", pwd, d)
+			}
+		}
+	}
+	fd.Close()
+}
+
+func TestSeek(t *testing.T) {
+	f := newFile("TestSeek", t)
+	defer Remove(f.Name())
+	defer f.Close()
+
+	const data = "hello, world\n"
+	io.WriteString(f, data)
+
+	type test struct {
+		in     int64
+		whence int
+		out    int64
+	}
+	var tests = []test{
+		{0, 1, int64(len(data))},
+		{0, 0, 0},
+		{5, 0, 5},
+		{0, 2, int64(len(data))},
+		{0, 0, 0},
+		{-1, 2, int64(len(data)) - 1},
+		{1 << 33, 0, 1 << 33},
+		{1 << 33, 2, 1<<33 + int64(len(data))},
+	}
+	for i, tt := range tests {
+		off, err := f.Seek(tt.in, tt.whence)
+		if off != tt.out || err != nil {
+			if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 {
+				// Reiserfs rejects the big seeks.
+				// http://code.google.com/p/go/issues/detail?id=91
+				break
+			}
+			t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
+		}
+	}
+}
+
+type openErrorTest struct {
+	path  string
+	mode  int
+	error error
+}
+
+var openErrorTests = []openErrorTest{
+	{
+		sfdir + "/no-such-file",
+		O_RDONLY,
+		syscall.ENOENT,
+	},
+	{
+		sfdir,
+		O_WRONLY,
+		syscall.EISDIR,
+	},
+	{
+		sfdir + "/" + sfname + "/no-such-file",
+		O_WRONLY,
+		syscall.ENOTDIR,
+	},
+}
+
+func TestOpenError(t *testing.T) {
+	for _, tt := range openErrorTests {
+		f, err := OpenFile(tt.path, tt.mode, 0)
+		if err == nil {
+			t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode)
+			f.Close()
+			continue
+		}
+		perr, ok := err.(*PathError)
+		if !ok {
+			t.Errorf("Open(%q, %d) returns error of %T type; want *PathError", tt.path, tt.mode, err)
+		}
+		if perr.Err != tt.error {
+			if runtime.GOOS == "plan9" {
+				syscallErrStr := perr.Err.Error()
+				expectedErrStr := strings.Replace(tt.error.Error(), "file ", "", 1)
+				if !strings.HasSuffix(syscallErrStr, expectedErrStr) {
+					t.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt.path, tt.mode, syscallErrStr, expectedErrStr)
+				}
+				continue
+			}
+			if runtime.GOOS == "dragonfly" {
+				// DragonFly incorrectly returns EACCES rather
+				// EISDIR when a directory is opened for write.
+				if tt.error == syscall.EISDIR && perr.Err == syscall.EACCES {
+					continue
+				}
+			}
+			t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Err.Error(), tt.error.Error())
+		}
+	}
+}
+
+func TestOpenNoName(t *testing.T) {
+	f, err := Open("")
+	if err == nil {
+		t.Fatal(`Open("") succeeded`)
+		f.Close()
+	}
+}
+
+func run(t *testing.T, cmd []string) string {
+	// Run /bin/hostname and collect output.
+	r, w, err := Pipe()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer r.Close()
+	p, err := StartProcess("/bin/hostname", []string{"hostname"}, &ProcAttr{Files: []*File{nil, w, Stderr}})
+	if err != nil {
+		t.Fatal(err)
+	}
+	w.Close()
+
+	var b bytes.Buffer
+	io.Copy(&b, r)
+	_, err = p.Wait()
+	if err != nil {
+		t.Fatalf("run hostname Wait: %v", err)
+	}
+	err = p.Kill()
+	if err == nil {
+		t.Errorf("expected an error from Kill running 'hostname'")
+	}
+	output := b.String()
+	if n := len(output); n > 0 && output[n-1] == '\n' {
+		output = output[0 : n-1]
+	}
+	if output == "" {
+		t.Fatalf("%v produced no output", cmd)
+	}
+
+	return output
+}
+
+func TestHostname(t *testing.T) {
+	// There is no other way to fetch hostname on windows, but via winapi.
+	// On Plan 9 it is can be taken from #c/sysname as Hostname() does.
+	switch runtime.GOOS {
+	case "windows", "plan9", "nacl":
+		t.Skipf("skipping on %s", runtime.GOOS)
+	}
+
+	// Check internal Hostname() against the output of /bin/hostname.
+	// Allow that the internal Hostname returns a Fully Qualified Domain Name
+	// and the /bin/hostname only returns the first component
+	hostname, err := Hostname()
+	if err != nil {
+		t.Fatalf("%v", err)
+	}
+	want := run(t, []string{"/bin/hostname"})
+	if hostname != want {
+		i := strings.Index(hostname, ".")
+		if i < 0 || hostname[0:i] != want {
+			t.Errorf("Hostname() = %q, want %q", hostname, want)
+		}
+	}
+}
+
+func TestReadAt(t *testing.T) {
+	f := newFile("TestReadAt", t)
+	defer Remove(f.Name())
+	defer f.Close()
+
+	const data = "hello, world\n"
+	io.WriteString(f, data)
+
+	b := make([]byte, 5)
+	n, err := f.ReadAt(b, 7)
+	if err != nil || n != len(b) {
+		t.Fatalf("ReadAt 7: %d, %v", n, err)
+	}
+	if string(b) != "world" {
+		t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
+	}
+}
+
+func TestWriteAt(t *testing.T) {
+	f := newFile("TestWriteAt", t)
+	defer Remove(f.Name())
+	defer f.Close()
+
+	const data = "hello, world\n"
+	io.WriteString(f, data)
+
+	n, err := f.WriteAt([]byte("WORLD"), 7)
+	if err != nil || n != 5 {
+		t.Fatalf("WriteAt 7: %d, %v", n, err)
+	}
+
+	b, err := ioutil.ReadFile(f.Name())
+	if err != nil {
+		t.Fatalf("ReadFile %s: %v", f.Name(), err)
+	}
+	if string(b) != "hello, WORLD\n" {
+		t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n")
+	}
+}
+
+func writeFile(t *testing.T, fname string, flag int, text string) string {
+	f, err := OpenFile(fname, flag, 0666)
+	if err != nil {
+		t.Fatalf("Open: %v", err)
+	}
+	n, err := io.WriteString(f, text)
+	if err != nil {
+		t.Fatalf("WriteString: %d, %v", n, err)
+	}
+	f.Close()
+	data, err := ioutil.ReadFile(fname)
+	if err != nil {
+		t.Fatalf("ReadFile: %v", err)
+	}
+	return string(data)
+}
+
+func TestAppend(t *testing.T) {
+	const f = "append.txt"
+	defer Remove(f)
+	s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
+	if s != "new" {
+		t.Fatalf("writeFile: have %q want %q", s, "new")
+	}
+	s = writeFile(t, f, O_APPEND|O_RDWR, "|append")
+	if s != "new|append" {
+		t.Fatalf("writeFile: have %q want %q", s, "new|append")
+	}
+	s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "|append")
+	if s != "new|append|append" {
+		t.Fatalf("writeFile: have %q want %q", s, "new|append|append")
+	}
+	err := Remove(f)
+	if err != nil {
+		t.Fatalf("Remove: %v", err)
+	}
+	s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "new&append")
+	if s != "new&append" {
+		t.Fatalf("writeFile: after append have %q want %q", s, "new&append")
+	}
+	s = writeFile(t, f, O_CREATE|O_RDWR, "old")
+	if s != "old&append" {
+		t.Fatalf("writeFile: after create have %q want %q", s, "old&append")
+	}
+	s = writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
+	if s != "new" {
+		t.Fatalf("writeFile: after truncate have %q want %q", s, "new")
+	}
+}
+
+func TestStatDirWithTrailingSlash(t *testing.T) {
+	// Create new temporary directory and arrange to clean it up.
+	path, err := ioutil.TempDir("", "/_TestStatDirWithSlash_")
+	if err != nil {
+		t.Fatalf("TempDir: %s", err)
+	}
+	defer RemoveAll(path)
+
+	// Stat of path should succeed.
+	_, err = Stat(path)
+	if err != nil {
+		t.Fatalf("stat %s failed: %s", path, err)
+	}
+
+	// Stat of path+"/" should succeed too.
+	path += "/"
+	_, err = Stat(path)
+	if err != nil {
+		t.Fatalf("stat %s failed: %s", path, err)
+	}
+}
+
+func TestNilProcessStateString(t *testing.T) {
+	var ps *ProcessState
+	s := ps.String()
+	if s != "<nil>" {
+		t.Errorf("(*ProcessState)(nil).String() = %q, want %q", s, "<nil>")
+	}
+}
+
+func TestSameFile(t *testing.T) {
+	fa, err := Create("a")
+	if err != nil {
+		t.Fatalf("Create(a): %v", err)
+	}
+	defer Remove(fa.Name())
+	fa.Close()
+	fb, err := Create("b")
+	if err != nil {
+		t.Fatalf("Create(b): %v", err)
+	}
+	defer Remove(fb.Name())
+	fb.Close()
+
+	ia1, err := Stat("a")
+	if err != nil {
+		t.Fatalf("Stat(a): %v", err)
+	}
+	ia2, err := Stat("a")
+	if err != nil {
+		t.Fatalf("Stat(a): %v", err)
+	}
+	if !SameFile(ia1, ia2) {
+		t.Errorf("files should be same")
+	}
+
+	ib, err := Stat("b")
+	if err != nil {
+		t.Fatalf("Stat(b): %v", err)
+	}
+	if SameFile(ia1, ib) {
+		t.Errorf("files should be different")
+	}
+}
+
+func TestDevNullFile(t *testing.T) {
+	f, err := Open(DevNull)
+	if err != nil {
+		t.Fatalf("Open(%s): %v", DevNull, err)
+	}
+	defer f.Close()
+	fi, err := f.Stat()
+	if err != nil {
+		t.Fatalf("Stat(%s): %v", DevNull, err)
+	}
+	name := filepath.Base(DevNull)
+	if fi.Name() != name {
+		t.Fatalf("wrong file name have %v want %v", fi.Name(), name)
+	}
+	if fi.Size() != 0 {
+		t.Fatalf("wrong file size have %d want 0", fi.Size())
+	}
+}
+
+var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
+
+func TestLargeWriteToConsole(t *testing.T) {
+	if !*testLargeWrite {
+		t.Skip("skipping console-flooding test; enable with -large_write")
+	}
+	b := make([]byte, 32000)
+	for i := range b {
+		b[i] = '.'
+	}
+	b[len(b)-1] = '\n'
+	n, err := Stdout.Write(b)
+	if err != nil {
+		t.Fatalf("Write to os.Stdout failed: %v", err)
+	}
+	if n != len(b) {
+		t.Errorf("Write to os.Stdout should return %d; got %d", len(b), n)
+	}
+	n, err = Stderr.Write(b)
+	if err != nil {
+		t.Fatalf("Write to os.Stderr failed: %v", err)
+	}
+	if n != len(b) {
+		t.Errorf("Write to os.Stderr should return %d; got %d", len(b), n)
+	}
+}
+
+func TestStatDirModeExec(t *testing.T) {
+	const mode = 0111
+
+	path, err := ioutil.TempDir("", "go-build")
+	if err != nil {
+		t.Fatalf("Failed to create temp directory: %v", err)
+	}
+	defer RemoveAll(path)
+
+	if err := Chmod(path, 0777); err != nil {
+		t.Fatalf("Chmod %q 0777: %v", path, err)
+	}
+
+	dir, err := Stat(path)
+	if err != nil {
+		t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
+	}
+	if dir.Mode()&mode != mode {
+		t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode()&mode, mode)
+	}
+}
+
+func TestReadAtEOF(t *testing.T) {
+	f := newFile("TestReadAtEOF", t)
+	defer Remove(f.Name())
+	defer f.Close()
+
+	_, err := f.ReadAt(make([]byte, 10), 0)
+	switch err {
+	case io.EOF:
+		// all good
+	case nil:
+		t.Fatalf("ReadAt succeeded")
+	default:
+		t.Fatalf("ReadAt failed: %s", err)
+	}
+}
+
+func testKillProcess(t *testing.T, processKiller func(p *Process)) {
+	t.Skip("gccgo does not have a go command")
+	if runtime.GOOS == "nacl" {
+		t.Skip("skipping on nacl")
+	}
+
+	dir, err := ioutil.TempDir("", "go-build")
+	if err != nil {
+		t.Fatalf("Failed to create temp directory: %v", err)
+	}
+	defer RemoveAll(dir)
+
+	src := filepath.Join(dir, "main.go")
+	f, err := Create(src)
+	if err != nil {
+		t.Fatalf("Failed to create %v: %v", src, err)
+	}
+	st := template.Must(template.New("source").Parse(`
+package main
+import "time"
+func main() {
+	time.Sleep(time.Second)
+}
+`))
+	err = st.Execute(f, nil)
+	if err != nil {
+		f.Close()
+		t.Fatalf("Failed to execute template: %v", err)
+	}
+	f.Close()
+
+	exe := filepath.Join(dir, "main.exe")
+	output, err := osexec.Command("go", "build", "-o", exe, src).CombinedOutput()
+	if err != nil {
+		t.Fatalf("Failed to build exe %v: %v %v", exe, err, string(output))
+	}
+
+	cmd := osexec.Command(exe)
+	err = cmd.Start()
+	if err != nil {
+		t.Fatalf("Failed to start test process: %v", err)
+	}
+	go func() {
+		time.Sleep(100 * time.Millisecond)
+		processKiller(cmd.Process)
+	}()
+	err = cmd.Wait()
+	if err == nil {
+		t.Errorf("Test process succeeded, but expected to fail")
+	}
+}
+
+func TestKillStartProcess(t *testing.T) {
+	testKillProcess(t, func(p *Process) {
+		err := p.Kill()
+		if err != nil {
+			t.Fatalf("Failed to kill test process: %v", err)
+		}
+	})
+}
+
+func TestKillFindProcess(t *testing.T) {
+	testKillProcess(t, func(p *Process) {
+		p2, err := FindProcess(p.Pid)
+		if err != nil {
+			t.Fatalf("Failed to find test process: %v", err)
+		}
+		err = p2.Kill()
+		if err != nil {
+			t.Fatalf("Failed to kill test process: %v", err)
+		}
+	})
+}
+
+var nilFileMethodTests = []struct {
+	name string
+	f    func(*File) error
+}{
+	{"Chdir", func(f *File) error { return f.Chdir() }},
+	{"Close", func(f *File) error { return f.Close() }},
+	{"Chmod", func(f *File) error { return f.Chmod(0) }},
+	{"Chown", func(f *File) error { return f.Chown(0, 0) }},
+	{"Read", func(f *File) error { _, err := f.Read(make([]byte, 0)); return err }},
+	{"ReadAt", func(f *File) error { _, err := f.ReadAt(make([]byte, 0), 0); return err }},
+	{"Readdir", func(f *File) error { _, err := f.Readdir(1); return err }},
+	{"Readdirnames", func(f *File) error { _, err := f.Readdirnames(1); return err }},
+	{"Seek", func(f *File) error { _, err := f.Seek(0, 0); return err }},
+	{"Stat", func(f *File) error { _, err := f.Stat(); return err }},
+	{"Sync", func(f *File) error { return f.Sync() }},
+	{"Truncate", func(f *File) error { return f.Truncate(0) }},
+	{"Write", func(f *File) error { _, err := f.Write(make([]byte, 0)); return err }},
+	{"WriteAt", func(f *File) error { _, err := f.WriteAt(make([]byte, 0), 0); return err }},
+	{"WriteString", func(f *File) error { _, err := f.WriteString(""); return err }},
+}
+
+// Test that all File methods give ErrInvalid if the receiver is nil.
+func TestNilFileMethods(t *testing.T) {
+	for _, tt := range nilFileMethodTests {
+		var file *File
+		got := tt.f(file)
+		if got != ErrInvalid {
+			t.Errorf("%v should fail when f is nil; got %v", tt.name, got)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/os_unix_test.go b/third_party/gofrontend/libgo/go/os/os_unix_test.go
new file mode 100644
index 0000000..21d40cc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/os_unix_test.go
@@ -0,0 +1,76 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package os_test
+
+import (
+	. "os"
+	"runtime"
+	"syscall"
+	"testing"
+)
+
+func checkUidGid(t *testing.T, path string, uid, gid int) {
+	dir, err := Stat(path)
+	if err != nil {
+		t.Fatalf("Stat %q (looking for uid/gid %d/%d): %s", path, uid, gid, err)
+	}
+	sys := dir.Sys().(*syscall.Stat_t)
+	if int(sys.Uid) != uid {
+		t.Errorf("Stat %q: uid %d want %d", path, sys.Uid, uid)
+	}
+	if int(sys.Gid) != gid {
+		t.Errorf("Stat %q: gid %d want %d", path, sys.Gid, gid)
+	}
+}
+
+func TestChown(t *testing.T) {
+	// Chown is not supported under windows os Plan 9.
+	// Plan9 provides a native ChownPlan9 version instead.
+	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+		return
+	}
+	// Use TempDir() to make sure we're on a local file system,
+	// so that the group ids returned by Getgroups will be allowed
+	// on the file.  On NFS, the Getgroups groups are
+	// basically useless.
+	f := newFile("TestChown", t)
+	defer Remove(f.Name())
+	defer f.Close()
+	dir, err := f.Stat()
+	if err != nil {
+		t.Fatalf("stat %s: %s", f.Name(), err)
+	}
+
+	// Can't change uid unless root, but can try
+	// changing the group id.  First try our current group.
+	gid := Getgid()
+	t.Log("gid:", gid)
+	if err = Chown(f.Name(), -1, gid); err != nil {
+		t.Fatalf("chown %s -1 %d: %s", f.Name(), gid, err)
+	}
+	sys := dir.Sys().(*syscall.Stat_t)
+	checkUidGid(t, f.Name(), int(sys.Uid), gid)
+
+	// Then try all the auxiliary groups.
+	groups, err := Getgroups()
+	if err != nil {
+		t.Fatalf("getgroups: %s", err)
+	}
+	t.Log("groups: ", groups)
+	for _, g := range groups {
+		if err = Chown(f.Name(), -1, g); err != nil {
+			t.Fatalf("chown %s -1 %d: %s", f.Name(), g, err)
+		}
+		checkUidGid(t, f.Name(), int(sys.Uid), g)
+
+		// change back to gid to test fd.Chown
+		if err = f.Chown(-1, gid); err != nil {
+			t.Fatalf("fchown %s -1 %d: %s", f.Name(), gid, err)
+		}
+		checkUidGid(t, f.Name(), int(sys.Uid), gid)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/path.go b/third_party/gofrontend/libgo/go/os/path.go
new file mode 100644
index 0000000..02a77ec
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/path.go
@@ -0,0 +1,123 @@
+// 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 os
+
+import (
+	"io"
+	"syscall"
+)
+
+// MkdirAll creates a directory named path,
+// along with any necessary parents, and returns nil,
+// or else returns an error.
+// The permission bits perm are used for all
+// directories that MkdirAll creates.
+// If path is already a directory, MkdirAll does nothing
+// and returns nil.
+func MkdirAll(path string, perm FileMode) error {
+	// If path exists, stop with success or error.
+	dir, err := Stat(path)
+	if err == nil {
+		if dir.IsDir() {
+			return nil
+		}
+		return &PathError{"mkdir", path, syscall.ENOTDIR}
+	}
+
+	// Doesn't already exist; make sure parent does.
+	i := len(path)
+	for i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator.
+		i--
+	}
+
+	j := i
+	for j > 0 && !IsPathSeparator(path[j-1]) { // Scan backward over element.
+		j--
+	}
+
+	if j > 1 {
+		// Create parent
+		err = MkdirAll(path[0:j-1], perm)
+		if err != nil {
+			return err
+		}
+	}
+
+	// Now parent exists, try to create.
+	err = Mkdir(path, perm)
+	if err != nil {
+		// Handle arguments like "foo/." by
+		// double-checking that directory doesn't exist.
+		dir, err1 := Lstat(path)
+		if err1 == nil && dir.IsDir() {
+			return nil
+		}
+		return err
+	}
+	return nil
+}
+
+// RemoveAll removes path and any children it contains.
+// It removes everything it can but returns the first error
+// it encounters.  If the path does not exist, RemoveAll
+// returns nil (no error).
+func RemoveAll(path string) error {
+	// Simple case: if Remove works, we're done.
+	err := Remove(path)
+	if err == nil {
+		return nil
+	}
+
+	// Otherwise, is this a directory we need to recurse into?
+	dir, serr := Lstat(path)
+	if serr != nil {
+		if serr, ok := serr.(*PathError); ok && (IsNotExist(serr.Err) || serr.Err == syscall.ENOTDIR) {
+			return nil
+		}
+		return serr
+	}
+	if !dir.IsDir() {
+		// Not a directory; return the error from Remove.
+		return err
+	}
+
+	// Directory.
+	fd, err := Open(path)
+	if err != nil {
+		return err
+	}
+
+	// Remove contents & return first error.
+	err = nil
+	for {
+		names, err1 := fd.Readdirnames(100)
+		for _, name := range names {
+			err1 := RemoveAll(path + string(PathSeparator) + name)
+			if err == nil {
+				err = err1
+			}
+		}
+		if err1 == io.EOF {
+			break
+		}
+		// If Readdirnames returned an error, use it.
+		if err == nil {
+			err = err1
+		}
+		if len(names) == 0 {
+			break
+		}
+	}
+
+	// Close directory, because windows won't remove opened directory.
+	fd.Close()
+
+	// Remove directory.
+	err1 := Remove(path)
+	if err == nil {
+		err = err1
+	}
+	return err
+}
diff --git a/third_party/gofrontend/libgo/go/os/path_plan9.go b/third_party/gofrontend/libgo/go/os/path_plan9.go
new file mode 100644
index 0000000..64bad50
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/path_plan9.go
@@ -0,0 +1,15 @@
+// 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.
+
+package os
+
+const (
+	PathSeparator     = '/'    // OS-specific path separator
+	PathListSeparator = '\000' // OS-specific path list separator
+)
+
+// IsPathSeparator returns true if c is a directory separator character.
+func IsPathSeparator(c uint8) bool {
+	return PathSeparator == c
+}
diff --git a/third_party/gofrontend/libgo/go/os/path_test.go b/third_party/gofrontend/libgo/go/os/path_test.go
new file mode 100644
index 0000000..3af21cd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/path_test.go
@@ -0,0 +1,215 @@
+// 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 os_test
+
+import (
+	"io/ioutil"
+	. "os"
+	"path/filepath"
+	"runtime"
+	"syscall"
+	"testing"
+)
+
+func TestMkdirAll(t *testing.T) {
+	tmpDir := TempDir()
+	path := tmpDir + "/_TestMkdirAll_/dir/./dir2"
+	err := MkdirAll(path, 0777)
+	if err != nil {
+		t.Fatalf("MkdirAll %q: %s", path, err)
+	}
+	defer RemoveAll(tmpDir + "/_TestMkdirAll_")
+
+	// Already exists, should succeed.
+	err = MkdirAll(path, 0777)
+	if err != nil {
+		t.Fatalf("MkdirAll %q (second time): %s", path, err)
+	}
+
+	// Make file.
+	fpath := path + "/file"
+	f, err := Create(fpath)
+	if err != nil {
+		t.Fatalf("create %q: %s", fpath, err)
+	}
+	defer f.Close()
+
+	// Can't make directory named after file.
+	err = MkdirAll(fpath, 0777)
+	if err == nil {
+		t.Fatalf("MkdirAll %q: no error", fpath)
+	}
+	perr, ok := err.(*PathError)
+	if !ok {
+		t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err)
+	}
+	if filepath.Clean(perr.Path) != filepath.Clean(fpath) {
+		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, filepath.Clean(perr.Path), filepath.Clean(fpath))
+	}
+
+	// Can't make subdirectory of file.
+	ffpath := fpath + "/subdir"
+	err = MkdirAll(ffpath, 0777)
+	if err == nil {
+		t.Fatalf("MkdirAll %q: no error", ffpath)
+	}
+	perr, ok = err.(*PathError)
+	if !ok {
+		t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err)
+	}
+	if filepath.Clean(perr.Path) != filepath.Clean(fpath) {
+		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, filepath.Clean(perr.Path), filepath.Clean(fpath))
+	}
+
+	if runtime.GOOS == "windows" {
+		path := tmpDir + `\_TestMkdirAll_\dir\.\dir2\`
+		err := MkdirAll(path, 0777)
+		if err != nil {
+			t.Fatalf("MkdirAll %q: %s", path, err)
+		}
+	}
+}
+
+func TestRemoveAll(t *testing.T) {
+	tmpDir := TempDir()
+	// Work directory.
+	path := tmpDir + "/_TestRemoveAll_"
+	fpath := path + "/file"
+	dpath := path + "/dir"
+
+	// Make directory with 1 file and remove.
+	if err := MkdirAll(path, 0777); err != nil {
+		t.Fatalf("MkdirAll %q: %s", path, err)
+	}
+	fd, err := Create(fpath)
+	if err != nil {
+		t.Fatalf("create %q: %s", fpath, err)
+	}
+	fd.Close()
+	if err = RemoveAll(path); err != nil {
+		t.Fatalf("RemoveAll %q (first): %s", path, err)
+	}
+	if _, err = Lstat(path); err == nil {
+		t.Fatalf("Lstat %q succeeded after RemoveAll (first)", path)
+	}
+
+	// Make directory with file and subdirectory and remove.
+	if err = MkdirAll(dpath, 0777); err != nil {
+		t.Fatalf("MkdirAll %q: %s", dpath, err)
+	}
+	fd, err = Create(fpath)
+	if err != nil {
+		t.Fatalf("create %q: %s", fpath, err)
+	}
+	fd.Close()
+	fd, err = Create(dpath + "/file")
+	if err != nil {
+		t.Fatalf("create %q: %s", fpath, err)
+	}
+	fd.Close()
+	if err = RemoveAll(path); err != nil {
+		t.Fatalf("RemoveAll %q (second): %s", path, err)
+	}
+	if _, err := Lstat(path); err == nil {
+		t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path)
+	}
+
+	// Determine if we should run the following test.
+	testit := true
+	if runtime.GOOS == "windows" {
+		// Chmod is not supported under windows.
+		testit = false
+	} else {
+		// Test fails as root.
+		testit = Getuid() != 0
+	}
+	if testit {
+		// Make directory with file and subdirectory and trigger error.
+		if err = MkdirAll(dpath, 0777); err != nil {
+			t.Fatalf("MkdirAll %q: %s", dpath, err)
+		}
+
+		for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
+			fd, err = Create(s)
+			if err != nil {
+				t.Fatalf("create %q: %s", s, err)
+			}
+			fd.Close()
+		}
+		if err = Chmod(dpath, 0); err != nil {
+			t.Fatalf("Chmod %q 0: %s", dpath, err)
+		}
+
+		// No error checking here: either RemoveAll
+		// will or won't be able to remove dpath;
+		// either way we want to see if it removes fpath
+		// and path/zzz.  Reasons why RemoveAll might
+		// succeed in removing dpath as well include:
+		//	* running as root
+		//	* running on a file system without permissions (FAT)
+		RemoveAll(path)
+		Chmod(dpath, 0777)
+
+		for _, s := range []string{fpath, path + "/zzz"} {
+			if _, err = Lstat(s); err == nil {
+				t.Fatalf("Lstat %q succeeded after partial RemoveAll", s)
+			}
+		}
+	}
+	if err = RemoveAll(path); err != nil {
+		t.Fatalf("RemoveAll %q after partial RemoveAll: %s", path, err)
+	}
+	if _, err = Lstat(path); err == nil {
+		t.Fatalf("Lstat %q succeeded after RemoveAll (final)", path)
+	}
+}
+
+func TestMkdirAllWithSymlink(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9", "windows":
+		t.Skipf("skipping on %s", runtime.GOOS)
+	}
+
+	tmpDir, err := ioutil.TempDir("", "TestMkdirAllWithSymlink-")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer RemoveAll(tmpDir)
+
+	dir := tmpDir + "/dir"
+	err = Mkdir(dir, 0755)
+	if err != nil {
+		t.Fatalf("Mkdir %s: %s", dir, err)
+	}
+
+	link := tmpDir + "/link"
+	err = Symlink("dir", link)
+	if err != nil {
+		t.Fatalf("Symlink %s: %s", link, err)
+	}
+
+	path := link + "/foo"
+	err = MkdirAll(path, 0755)
+	if err != nil {
+		t.Errorf("MkdirAll %q: %s", path, err)
+	}
+}
+
+func TestMkdirAllAtSlash(t *testing.T) {
+	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+		return
+	}
+	RemoveAll("/_go_os_test")
+	err := MkdirAll("/_go_os_test/dir", 0777)
+	if err != nil {
+		pathErr, ok := err.(*PathError)
+		// common for users not to be able to write to /
+		if ok && pathErr.Err == syscall.EACCES {
+			return
+		}
+		t.Fatalf(`MkdirAll "/_go_os_test/dir": %v`, err)
+	}
+	RemoveAll("/_go_os_test")
+}
diff --git a/third_party/gofrontend/libgo/go/os/path_unix.go b/third_party/gofrontend/libgo/go/os/path_unix.go
new file mode 100644
index 0000000..0211107
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/path_unix.go
@@ -0,0 +1,17 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package os
+
+const (
+	PathSeparator     = '/' // OS-specific path separator
+	PathListSeparator = ':' // OS-specific path list separator
+)
+
+// IsPathSeparator returns true if c is a directory separator character.
+func IsPathSeparator(c uint8) bool {
+	return PathSeparator == c
+}
diff --git a/third_party/gofrontend/libgo/go/os/path_windows.go b/third_party/gofrontend/libgo/go/os/path_windows.go
new file mode 100644
index 0000000..61f2ca5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/path_windows.go
@@ -0,0 +1,16 @@
+// 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.
+
+package os
+
+const (
+	PathSeparator     = '\\' // OS-specific path separator
+	PathListSeparator = ';'  // OS-specific path list separator
+)
+
+// IsPathSeparator returns true if c is a directory separator character.
+func IsPathSeparator(c uint8) bool {
+	// NOTE: Windows accept / as path separator.
+	return c == '\\' || c == '/'
+}
diff --git a/third_party/gofrontend/libgo/go/os/pipe_bsd.go b/third_party/gofrontend/libgo/go/os/pipe_bsd.go
new file mode 100644
index 0000000..3b81ed2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/pipe_bsd.go
@@ -0,0 +1,28 @@
+// 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.
+
+// +build darwin dragonfly freebsd nacl netbsd openbsd solaris
+
+package os
+
+import "syscall"
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an error, if any.
+func Pipe() (r *File, w *File, err error) {
+	var p [2]int
+
+	// See ../syscall/exec.go for description of lock.
+	syscall.ForkLock.RLock()
+	e := syscall.Pipe(p[0:])
+	if e != nil {
+		syscall.ForkLock.RUnlock()
+		return nil, nil, NewSyscallError("pipe", e)
+	}
+	syscall.CloseOnExec(p[0])
+	syscall.CloseOnExec(p[1])
+	syscall.ForkLock.RUnlock()
+
+	return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/pipe_linux.go b/third_party/gofrontend/libgo/go/os/pipe_linux.go
new file mode 100644
index 0000000..9bafad8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/pipe_linux.go
@@ -0,0 +1,33 @@
+// Copyright 2013 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 os
+
+import "syscall"
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an error, if any.
+func Pipe() (r *File, w *File, err error) {
+	var p [2]int
+
+	e := syscall.Pipe2(p[0:], syscall.O_CLOEXEC)
+	// pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so it
+	// might not be implemented.
+	if e == syscall.ENOSYS {
+		// See ../syscall/exec.go for description of lock.
+		syscall.ForkLock.RLock()
+		e = syscall.Pipe(p[0:])
+		if e != nil {
+			syscall.ForkLock.RUnlock()
+			return nil, nil, NewSyscallError("pipe", e)
+		}
+		syscall.CloseOnExec(p[0])
+		syscall.CloseOnExec(p[1])
+		syscall.ForkLock.RUnlock()
+	} else if e != nil {
+		return nil, nil, NewSyscallError("pipe2", e)
+	}
+
+	return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/proc.go b/third_party/gofrontend/libgo/go/os/proc.go
new file mode 100644
index 0000000..38c436e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/proc.go
@@ -0,0 +1,36 @@
+// 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.
+
+// Process etc.
+
+package os
+
+import "syscall"
+
+// Args hold the command-line arguments, starting with the program name.
+var Args []string
+
+// Getuid returns the numeric user id of the caller.
+func Getuid() int { return syscall.Getuid() }
+
+// Geteuid returns the numeric effective user id of the caller.
+func Geteuid() int { return syscall.Geteuid() }
+
+// Getgid returns the numeric group id of the caller.
+func Getgid() int { return syscall.Getgid() }
+
+// Getegid returns the numeric effective group id of the caller.
+func Getegid() int { return syscall.Getegid() }
+
+// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
+func Getgroups() ([]int, error) {
+	gids, e := syscall.Getgroups()
+	return gids, NewSyscallError("getgroups", e)
+}
+
+// Exit causes the current program to exit with the given status code.
+// Conventionally, code zero indicates success, non-zero an error.
+// The program terminates immediately; deferred functions are
+// not run.
+func Exit(code int) { syscall.Exit(code) }
diff --git a/third_party/gofrontend/libgo/go/os/signal/signal.go b/third_party/gofrontend/libgo/go/os/signal/signal.go
new file mode 100644
index 0000000..3004275
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/signal/signal.go
@@ -0,0 +1,131 @@
+// 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 signal implements access to incoming signals.
+package signal
+
+// BUG(rsc): This package is not yet implemented on Plan 9.
+
+import (
+	"os"
+	"sync"
+)
+
+var handlers struct {
+	sync.Mutex
+	m   map[chan<- os.Signal]*handler
+	ref [numSig]int64
+}
+
+type handler struct {
+	mask [(numSig + 31) / 32]uint32
+}
+
+func (h *handler) want(sig int) bool {
+	return (h.mask[sig/32]>>uint(sig&31))&1 != 0
+}
+
+func (h *handler) set(sig int) {
+	h.mask[sig/32] |= 1 << uint(sig&31)
+}
+
+// Notify causes package signal to relay incoming signals to c.
+// If no signals are listed, all incoming signals will be relayed to c.
+// Otherwise, just the listed signals will.
+//
+// Package signal will not block sending to c: the caller must ensure
+// that c has sufficient buffer space to keep up with the expected
+// signal rate.  For a channel used for notification of just one signal value,
+// a buffer of size 1 is sufficient.
+//
+// It is allowed to call Notify multiple times with the same channel:
+// each call expands the set of signals sent to that channel.
+// The only way to remove signals from the set is to call Stop.
+//
+// It is allowed to call Notify multiple times with different channels
+// and the same signals: each channel receives copies of incoming
+// signals independently.
+func Notify(c chan<- os.Signal, sig ...os.Signal) {
+	if c == nil {
+		panic("os/signal: Notify using nil channel")
+	}
+
+	handlers.Lock()
+	defer handlers.Unlock()
+
+	h := handlers.m[c]
+	if h == nil {
+		if handlers.m == nil {
+			handlers.m = make(map[chan<- os.Signal]*handler)
+		}
+		h = new(handler)
+		handlers.m[c] = h
+	}
+
+	add := func(n int) {
+		if n < 0 {
+			return
+		}
+		if !h.want(n) {
+			h.set(n)
+			if handlers.ref[n] == 0 {
+				enableSignal(n)
+			}
+			handlers.ref[n]++
+		}
+	}
+
+	if len(sig) == 0 {
+		for n := 0; n < numSig; n++ {
+			add(n)
+		}
+	} else {
+		for _, s := range sig {
+			add(signum(s))
+		}
+	}
+}
+
+// Stop causes package signal to stop relaying incoming signals to c.
+// It undoes the effect of all prior calls to Notify using c.
+// When Stop returns, it is guaranteed that c will receive no more signals.
+func Stop(c chan<- os.Signal) {
+	handlers.Lock()
+	defer handlers.Unlock()
+
+	h := handlers.m[c]
+	if h == nil {
+		return
+	}
+	delete(handlers.m, c)
+
+	for n := 0; n < numSig; n++ {
+		if h.want(n) {
+			handlers.ref[n]--
+			if handlers.ref[n] == 0 {
+				disableSignal(n)
+			}
+		}
+	}
+}
+
+func process(sig os.Signal) {
+	n := signum(sig)
+	if n < 0 {
+		return
+	}
+
+	handlers.Lock()
+	defer handlers.Unlock()
+
+	for c, h := range handlers.m {
+		if h.want(n) {
+			// send but do not block for it
+			select {
+			case c <- sig:
+			default:
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/signal/signal_stub.go b/third_party/gofrontend/libgo/go/os/signal/signal_stub.go
new file mode 100644
index 0000000..d0a6935
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/signal/signal_stub.go
@@ -0,0 +1,17 @@
+// 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.
+
+// +build plan9
+
+package signal
+
+import "os"
+
+const numSig = 0
+
+func signum(sig os.Signal) int { return -1 }
+
+func disableSignal(int) {}
+
+func enableSignal(int) {}
diff --git a/third_party/gofrontend/libgo/go/os/signal/signal_test.go b/third_party/gofrontend/libgo/go/os/signal/signal_test.go
new file mode 100644
index 0000000..076fe3f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/signal/signal_test.go
@@ -0,0 +1,208 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package signal
+
+import (
+	"flag"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"runtime"
+	"strconv"
+	"syscall"
+	"testing"
+	"time"
+)
+
+func waitSig(t *testing.T, c <-chan os.Signal, sig os.Signal) {
+	select {
+	case s := <-c:
+		if s != sig {
+			t.Fatalf("signal was %v, want %v", s, sig)
+		}
+	case <-time.After(1 * time.Second):
+		t.Fatalf("timeout waiting for %v", sig)
+	}
+}
+
+// Test that basic signal handling works.
+func TestSignal(t *testing.T) {
+	// Ask for SIGHUP
+	c := make(chan os.Signal, 1)
+	Notify(c, syscall.SIGHUP)
+	defer Stop(c)
+
+	// Send this process a SIGHUP
+	t.Logf("sighup...")
+	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
+	waitSig(t, c, syscall.SIGHUP)
+
+	// Ask for everything we can get.
+	c1 := make(chan os.Signal, 1)
+	Notify(c1)
+
+	// Send this process a SIGWINCH
+	t.Logf("sigwinch...")
+	syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)
+	waitSig(t, c1, syscall.SIGWINCH)
+
+	// Send two more SIGHUPs, to make sure that
+	// they get delivered on c1 and that not reading
+	// from c does not block everything.
+	t.Logf("sighup...")
+	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
+	waitSig(t, c1, syscall.SIGHUP)
+	t.Logf("sighup...")
+	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
+	waitSig(t, c1, syscall.SIGHUP)
+
+	// The first SIGHUP should be waiting for us on c.
+	waitSig(t, c, syscall.SIGHUP)
+}
+
+func TestStress(t *testing.T) {
+	dur := 3 * time.Second
+	if testing.Short() {
+		dur = 100 * time.Millisecond
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	done := make(chan bool)
+	finished := make(chan bool)
+	go func() {
+		sig := make(chan os.Signal, 1)
+		Notify(sig, syscall.SIGUSR1)
+		defer Stop(sig)
+	Loop:
+		for {
+			select {
+			case <-sig:
+			case <-done:
+				break Loop
+			}
+		}
+		finished <- true
+	}()
+	go func() {
+	Loop:
+		for {
+			select {
+			case <-done:
+				break Loop
+			default:
+				syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
+				runtime.Gosched()
+			}
+		}
+		finished <- true
+	}()
+	time.Sleep(dur)
+	close(done)
+	<-finished
+	<-finished
+	// When run with 'go test -cpu=1,2,4' SIGUSR1 from this test can slip
+	// into subsequent TestSignal() causing failure.
+	// Sleep for a while to reduce the possibility of the failure.
+	time.Sleep(10 * time.Millisecond)
+}
+
+var sendUncaughtSighup = flag.Int("send_uncaught_sighup", 0, "send uncaught SIGHUP during TestStop")
+
+// Test that Stop cancels the channel's registrations.
+func TestStop(t *testing.T) {
+	sigs := []syscall.Signal{
+		syscall.SIGWINCH,
+		syscall.SIGHUP,
+	}
+
+	for _, sig := range sigs {
+		// Send the signal.
+		// If it's SIGWINCH, we should not see it.
+		// If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
+		if sig != syscall.SIGHUP || *sendUncaughtSighup == 1 {
+			syscall.Kill(syscall.Getpid(), sig)
+		}
+		time.Sleep(10 * time.Millisecond)
+
+		// Ask for signal
+		c := make(chan os.Signal, 1)
+		Notify(c, sig)
+		defer Stop(c)
+
+		// Send this process that signal
+		syscall.Kill(syscall.Getpid(), sig)
+		waitSig(t, c, sig)
+
+		Stop(c)
+		select {
+		case s := <-c:
+			t.Fatalf("unexpected signal %v", s)
+		case <-time.After(10 * time.Millisecond):
+			// nothing to read - good
+		}
+
+		// Send the signal.
+		// If it's SIGWINCH, we should not see it.
+		// If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
+		if sig != syscall.SIGHUP || *sendUncaughtSighup == 2 {
+			syscall.Kill(syscall.Getpid(), sig)
+		}
+
+		select {
+		case s := <-c:
+			t.Fatalf("unexpected signal %v", s)
+		case <-time.After(10 * time.Millisecond):
+			// nothing to read - good
+		}
+	}
+}
+
+// Test that when run under nohup, an uncaught SIGHUP does not kill the program,
+// but a
+func TestNohup(t *testing.T) {
+	// Ugly: ask for SIGHUP so that child will not have no-hup set
+	// even if test is running under nohup environment.
+	// We have no intention of reading from c.
+	c := make(chan os.Signal, 1)
+	Notify(c, syscall.SIGHUP)
+
+	// When run without nohup, the test should crash on an uncaught SIGHUP.
+	// When run under nohup, the test should ignore uncaught SIGHUPs,
+	// because the runtime is not supposed to be listening for them.
+	// Either way, TestStop should still be able to catch them when it wants them
+	// and then when it stops wanting them, the original behavior should resume.
+	//
+	// send_uncaught_sighup=1 sends the SIGHUP before starting to listen for SIGHUPs.
+	// send_uncaught_sighup=2 sends the SIGHUP after no longer listening for SIGHUPs.
+	//
+	// Both should fail without nohup and succeed with nohup.
+
+	for i := 1; i <= 2; i++ {
+		out, err := exec.Command(os.Args[0], "-test.run=TestStop", "-send_uncaught_sighup="+strconv.Itoa(i)).CombinedOutput()
+		if err == nil {
+			t.Fatalf("ran test with -send_uncaught_sighup=%d and it succeeded: expected failure.\nOutput:\n%s", i, out)
+		}
+	}
+
+	Stop(c)
+
+	// Again, this time with nohup, assuming we can find it.
+	_, err := os.Stat("/usr/bin/nohup")
+	if err != nil {
+		t.Skip("cannot find nohup; skipping second half of test")
+	}
+
+	for i := 1; i <= 2; i++ {
+		os.Remove("nohup.out")
+		out, err := exec.Command("/usr/bin/nohup", os.Args[0], "-test.run=TestStop", "-send_uncaught_sighup="+strconv.Itoa(i)).CombinedOutput()
+
+		data, _ := ioutil.ReadFile("nohup.out")
+		os.Remove("nohup.out")
+		if err != nil {
+			t.Fatalf("ran test with -send_uncaught_sighup=%d under nohup and it failed: expected success.\nError: %v\nOutput:\n%s%s", i, err, out, data)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/signal/signal_unix.go b/third_party/gofrontend/libgo/go/os/signal/signal_unix.go
new file mode 100644
index 0000000..94b8ab3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/signal/signal_unix.go
@@ -0,0 +1,53 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package signal
+
+import (
+	"os"
+	"syscall"
+)
+
+// In assembly.
+func signal_disable(uint32)
+func signal_enable(uint32)
+func signal_recv() uint32
+
+func loop() {
+	for {
+		process(syscall.Signal(signal_recv()))
+	}
+}
+
+func init() {
+	signal_enable(0) // first call - initialize
+	go loop()
+}
+
+const (
+	numSig = 65 // max across all systems
+)
+
+func signum(sig os.Signal) int {
+	switch sig := sig.(type) {
+	case syscall.Signal:
+		i := int(sig)
+		if i < 0 || i >= numSig {
+			return -1
+		}
+		return i
+	default:
+		return -1
+	}
+}
+
+func enableSignal(sig int) {
+	signal_enable(uint32(sig))
+}
+
+func disableSignal(sig int) {
+	signal_disable(uint32(sig))
+}
diff --git a/third_party/gofrontend/libgo/go/os/stat.go b/third_party/gofrontend/libgo/go/os/stat.go
new file mode 100644
index 0000000..9758d33
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/stat.go
@@ -0,0 +1,56 @@
+// 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 os
+
+import (
+	"syscall"
+	"time"
+)
+
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
+	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
+}
+
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &fileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtim),
+		sys:     st,
+	}
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK, syscall.S_IFCHR:
+		fs.mode |= ModeDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim)
+}
diff --git a/third_party/gofrontend/libgo/go/os/stat_atim.go b/third_party/gofrontend/libgo/go/os/stat_atim.go
new file mode 100644
index 0000000..605c1d9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/stat_atim.go
@@ -0,0 +1,61 @@
+// 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 os
+
+import (
+	"syscall"
+	"time"
+)
+
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
+	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
+}
+
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &fileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtim),
+		sys:     st,
+	}
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim)
+}
diff --git a/third_party/gofrontend/libgo/go/os/stat_atimespec.go b/third_party/gofrontend/libgo/go/os/stat_atimespec.go
new file mode 100644
index 0000000..2ffb60f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/stat_atimespec.go
@@ -0,0 +1,61 @@
+// 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 os
+
+import (
+	"syscall"
+	"time"
+)
+
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
+	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
+}
+
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &fileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtimespec),
+		sys:     st,
+	}
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timespecToTime(fi.Sys().(*syscall.Stat_t).Atimespec)
+}
diff --git a/third_party/gofrontend/libgo/go/os/stat_dragonfly.go b/third_party/gofrontend/libgo/go/os/stat_dragonfly.go
new file mode 100644
index 0000000..605c1d9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/stat_dragonfly.go
@@ -0,0 +1,61 @@
+// 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 os
+
+import (
+	"syscall"
+	"time"
+)
+
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
+	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
+}
+
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &fileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtim),
+		sys:     st,
+	}
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim)
+}
diff --git a/third_party/gofrontend/libgo/go/os/stat_nacl.go b/third_party/gofrontend/libgo/go/os/stat_nacl.go
new file mode 100644
index 0000000..a503b59
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/stat_nacl.go
@@ -0,0 +1,62 @@
+// 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 os
+
+import (
+	"syscall"
+	"time"
+)
+
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
+	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
+}
+
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &fileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtime, st.MtimeNsec),
+		sys:     st,
+	}
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timespecToTime(sec, nsec int64) time.Time {
+	return time.Unix(sec, nsec)
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	st := fi.Sys().(*syscall.Stat_t)
+	return timespecToTime(st.Atime, st.AtimeNsec)
+}
diff --git a/third_party/gofrontend/libgo/go/os/stat_plan9.go b/third_party/gofrontend/libgo/go/os/stat_plan9.go
new file mode 100644
index 0000000..25c9a8c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/stat_plan9.go
@@ -0,0 +1,110 @@
+// 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.
+
+package os
+
+import (
+	"syscall"
+	"time"
+)
+
+func sameFile(fs1, fs2 *fileStat) bool {
+	a := fs1.sys.(*syscall.Dir)
+	b := fs2.sys.(*syscall.Dir)
+	return a.Qid.Path == b.Qid.Path && a.Type == b.Type && a.Dev == b.Dev
+}
+
+func fileInfoFromStat(d *syscall.Dir) FileInfo {
+	fs := &fileStat{
+		name:    d.Name,
+		size:    int64(d.Length),
+		modTime: time.Unix(int64(d.Mtime), 0),
+		sys:     d,
+	}
+	fs.mode = FileMode(d.Mode & 0777)
+	if d.Mode&syscall.DMDIR != 0 {
+		fs.mode |= ModeDir
+	}
+	if d.Mode&syscall.DMAPPEND != 0 {
+		fs.mode |= ModeAppend
+	}
+	if d.Mode&syscall.DMEXCL != 0 {
+		fs.mode |= ModeExclusive
+	}
+	if d.Mode&syscall.DMTMP != 0 {
+		fs.mode |= ModeTemporary
+	}
+	return fs
+}
+
+// arg is an open *File or a path string.
+func dirstat(arg interface{}) (*syscall.Dir, error) {
+	var name string
+
+	// This is big enough for most stat messages
+	// and rounded to a multiple of 128 bytes.
+	size := (syscall.STATFIXLEN + 16*4 + 128) &^ 128
+
+	for i := 0; i < 2; i++ {
+		buf := make([]byte, size)
+
+		var n int
+		var err error
+		switch a := arg.(type) {
+		case *File:
+			name = a.name
+			n, err = syscall.Fstat(a.fd, buf)
+		case string:
+			name = a
+			n, err = syscall.Stat(a, buf)
+		default:
+			panic("phase error in dirstat")
+		}
+		if err != nil {
+			return nil, &PathError{"stat", name, err}
+		}
+		if n < syscall.STATFIXLEN {
+			return nil, &PathError{"stat", name, syscall.ErrShortStat}
+		}
+
+		// Pull the real size out of the stat message.
+		size = int(uint16(buf[0]) | uint16(buf[1])<<8)
+
+		// If the stat message is larger than our buffer we will
+		// go around the loop and allocate one that is big enough.
+		if size > n {
+			continue
+		}
+
+		d, err := syscall.UnmarshalDir(buf[:n])
+		if err != nil {
+			return nil, &PathError{"stat", name, err}
+		}
+		return d, nil
+	}
+	return nil, &PathError{"stat", name, syscall.ErrBadStat}
+}
+
+// Stat returns a FileInfo describing the named file.
+// If there is an error, it will be of type *PathError.
+func Stat(name string) (fi FileInfo, err error) {
+	d, err := dirstat(name)
+	if err != nil {
+		return nil, err
+	}
+	return fileInfoFromStat(d), nil
+}
+
+// Lstat returns a FileInfo describing the named file.
+// If the file is a symbolic link, the returned FileInfo
+// describes the symbolic link.  Lstat makes no attempt to follow the link.
+// If there is an error, it will be of type *PathError.
+func Lstat(name string) (fi FileInfo, err error) {
+	return Stat(name)
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return time.Unix(int64(fi.Sys().(*syscall.Dir).Atime), 0)
+}
diff --git a/third_party/gofrontend/libgo/go/os/stat_solaris.go b/third_party/gofrontend/libgo/go/os/stat_solaris.go
new file mode 100644
index 0000000..3e88bd8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/stat_solaris.go
@@ -0,0 +1,61 @@
+// 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.
+
+package os
+
+import (
+	"syscall"
+	"time"
+)
+
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
+	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
+}
+
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &fileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timestrucToTime(st.Mtim),
+		sys:     st,
+	}
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timestrucToTime(ts syscall.Timestruc) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timestrucToTime(fi.(*fileStat).Sys().(*syscall.Stat_t).Atim)
+}
diff --git a/third_party/gofrontend/libgo/go/os/str.go b/third_party/gofrontend/libgo/go/os/str.go
new file mode 100644
index 0000000..e3606b6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/str.go
@@ -0,0 +1,22 @@
+// 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.
+
+// +build plan9
+
+package os
+
+func itoa(val int) string { // do it here rather than with fmt to avoid dependency
+	if val < 0 {
+		return "-" + itoa(-val)
+	}
+	var buf [32]byte // big enough for int64
+	i := len(buf) - 1
+	for val >= 10 {
+		buf[i] = byte(val%10 + '0')
+		i--
+		val /= 10
+	}
+	buf[i] = byte(val + '0')
+	return string(buf[i:])
+}
diff --git a/third_party/gofrontend/libgo/go/os/sys_bsd.go b/third_party/gofrontend/libgo/go/os/sys_bsd.go
new file mode 100644
index 0000000..8ad5e21
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/sys_bsd.go
@@ -0,0 +1,20 @@
+// 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.
+
+// +build darwin dragonfly freebsd nacl netbsd openbsd
+
+// os code shared between *BSD systems including OS X (Darwin)
+// and FreeBSD.
+
+package os
+
+import "syscall"
+
+func hostname() (name string, err error) {
+	name, err = syscall.Sysctl("kern.hostname")
+	if err != nil {
+		return "", NewSyscallError("sysctl kern.hostname", err)
+	}
+	return name, nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/sys_darwin.go b/third_party/gofrontend/libgo/go/os/sys_darwin.go
new file mode 100644
index 0000000..7a8330a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/sys_darwin.go
@@ -0,0 +1,31 @@
+// Copyright 2014 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 os
+
+import "syscall"
+
+// supportsCloseOnExec reports whether the platform supports the
+// O_CLOEXEC flag.
+var supportsCloseOnExec bool
+
+func init() {
+	// Seems like kern.osreldate is veiled on latest OS X. We use
+	// kern.osrelease instead.
+	osver, err := syscall.Sysctl("kern.osrelease")
+	if err != nil {
+		return
+	}
+	var i int
+	for i = range osver {
+		if osver[i] != '.' {
+			continue
+		}
+	}
+	// The O_CLOEXEC flag was introduced in OS X 10.7 (Darwin
+	// 11.0.0). See http://support.apple.com/kb/HT1633.
+	if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '1' {
+		supportsCloseOnExec = true
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/sys_freebsd.go b/third_party/gofrontend/libgo/go/os/sys_freebsd.go
new file mode 100644
index 0000000..273c2df
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/sys_freebsd.go
@@ -0,0 +1,23 @@
+// Copyright 2014 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 os
+
+import "syscall"
+
+// supportsCloseOnExec reports whether the platform supports the
+// O_CLOEXEC flag.
+var supportsCloseOnExec bool
+
+func init() {
+	osrel, err := syscall.SysctlUint32("kern.osreldate")
+	if err != nil {
+		return
+	}
+	// The O_CLOEXEC flag was introduced in FreeBSD 8.3.
+	// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
+	if osrel >= 803000 {
+		supportsCloseOnExec = true
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/os/sys_linux.go b/third_party/gofrontend/libgo/go/os/sys_linux.go
new file mode 100644
index 0000000..76cdf50
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/sys_linux.go
@@ -0,0 +1,26 @@
+// 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.
+
+// Linux-specific
+
+package os
+
+func hostname() (name string, err error) {
+	f, err := Open("/proc/sys/kernel/hostname")
+	if err != nil {
+		return "", err
+	}
+	defer f.Close()
+
+	var buf [512]byte // Enough for a DNS name.
+	n, err := f.Read(buf[0:])
+	if err != nil {
+		return "", err
+	}
+
+	if n > 0 && buf[n-1] == '\n' {
+		n--
+	}
+	return string(buf[0:n]), nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/sys_nacl.go b/third_party/gofrontend/libgo/go/os/sys_nacl.go
new file mode 100644
index 0000000..07907c8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/sys_nacl.go
@@ -0,0 +1,9 @@
+// Copyright 2014 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 os
+
+// supportsCloseOnExec reports whether the platform supports the
+// O_CLOEXEC flag.
+const supportsCloseOnExec = false
diff --git a/third_party/gofrontend/libgo/go/os/sys_plan9.go b/third_party/gofrontend/libgo/go/os/sys_plan9.go
new file mode 100644
index 0000000..07a7905
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/sys_plan9.go
@@ -0,0 +1,26 @@
+// 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.
+
+// Plan 9-specific
+
+package os
+
+func hostname() (name string, err error) {
+	f, err := Open("#c/sysname")
+	if err != nil {
+		return "", err
+	}
+	defer f.Close()
+
+	var buf [128]byte
+	n, err := f.Read(buf[:len(buf)-1])
+
+	if err != nil {
+		return "", err
+	}
+	if n > 0 {
+		buf[n] = 0
+	}
+	return string(buf[0:n]), nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/sys_uname.go b/third_party/gofrontend/libgo/go/os/sys_uname.go
new file mode 100644
index 0000000..16568b6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/sys_uname.go
@@ -0,0 +1,25 @@
+// 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.
+
+// For systems which only store the hostname in uname (Solaris).
+
+package os
+
+import "syscall"
+
+func hostname() (name string, err error) {
+	var u syscall.Utsname
+	if errno := syscall.Uname(&u); errno != nil {
+		return "", NewSyscallError("uname", errno)
+	}
+	b := make([]byte, len(u.Nodename))
+	i := 0
+	for ; i < len(u.Nodename); i++ {
+		if u.Nodename[i] == 0 {
+			break
+		}
+		b[i] = byte(u.Nodename[i])
+	}
+	return string(b[:i]), nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/sys_unix.go b/third_party/gofrontend/libgo/go/os/sys_unix.go
new file mode 100644
index 0000000..39c20dc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/sys_unix.go
@@ -0,0 +1,11 @@
+// Copyright 2014 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.
+
+// +build dragonfly linux netbsd openbsd solaris
+
+package os
+
+// supportsCloseOnExec reports whether the platform supports the
+// O_CLOEXEC flag.
+const supportsCloseOnExec = true
diff --git a/third_party/gofrontend/libgo/go/os/types.go b/third_party/gofrontend/libgo/go/os/types.go
new file mode 100644
index 0000000..473d431
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/types.go
@@ -0,0 +1,118 @@
+// 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 os
+
+import (
+	"syscall"
+	"time"
+)
+
+// Getpagesize returns the underlying system's memory page size.
+func Getpagesize() int { return syscall.Getpagesize() }
+
+// A FileInfo describes a file and is returned by Stat and Lstat.
+type FileInfo interface {
+	Name() string       // base name of the file
+	Size() int64        // length in bytes for regular files; system-dependent for others
+	Mode() FileMode     // file mode bits
+	ModTime() time.Time // modification time
+	IsDir() bool        // abbreviation for Mode().IsDir()
+	Sys() interface{}   // underlying data source (can return nil)
+}
+
+// A FileMode represents a file's mode and permission bits.
+// The bits have the same definition on all systems, so that
+// information about files can be moved from one system
+// to another portably.  Not all bits apply to all systems.
+// The only required bit is ModeDir for directories.
+type FileMode uint32
+
+// The defined file mode bits are the most significant bits of the FileMode.
+// The nine least-significant bits are the standard Unix rwxrwxrwx permissions.
+// The values of these bits should be considered part of the public API and
+// may be used in wire protocols or disk representations: they must not be
+// changed, although new bits might be added.
+const (
+	// The single letters are the abbreviations
+	// used by the String method's formatting.
+	ModeDir        FileMode = 1 << (32 - 1 - iota) // d: is a directory
+	ModeAppend                                     // a: append-only
+	ModeExclusive                                  // l: exclusive use
+	ModeTemporary                                  // T: temporary file (not backed up)
+	ModeSymlink                                    // L: symbolic link
+	ModeDevice                                     // D: device file
+	ModeNamedPipe                                  // p: named pipe (FIFO)
+	ModeSocket                                     // S: Unix domain socket
+	ModeSetuid                                     // u: setuid
+	ModeSetgid                                     // g: setgid
+	ModeCharDevice                                 // c: Unix character device, when ModeDevice is set
+	ModeSticky                                     // t: sticky
+
+	// Mask for the type bits. For regular files, none will be set.
+	ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
+
+	ModePerm FileMode = 0777 // permission bits
+)
+
+func (m FileMode) String() string {
+	const str = "dalTLDpSugct"
+	var buf [32]byte // Mode is uint32.
+	w := 0
+	for i, c := range str {
+		if m&(1<<uint(32-1-i)) != 0 {
+			buf[w] = byte(c)
+			w++
+		}
+	}
+	if w == 0 {
+		buf[w] = '-'
+		w++
+	}
+	const rwx = "rwxrwxrwx"
+	for i, c := range rwx {
+		if m&(1<<uint(9-1-i)) != 0 {
+			buf[w] = byte(c)
+		} else {
+			buf[w] = '-'
+		}
+		w++
+	}
+	return string(buf[:w])
+}
+
+// IsDir reports whether m describes a directory.
+// That is, it tests for the ModeDir bit being set in m.
+func (m FileMode) IsDir() bool {
+	return m&ModeDir != 0
+}
+
+// IsRegular reports whether m describes a regular file.
+// That is, it tests that no mode type bits are set.
+func (m FileMode) IsRegular() bool {
+	return m&ModeType == 0
+}
+
+// Perm returns the Unix permission bits in m.
+func (m FileMode) Perm() FileMode {
+	return m & ModePerm
+}
+
+func (fs *fileStat) Name() string { return fs.name }
+func (fs *fileStat) IsDir() bool  { return fs.Mode().IsDir() }
+
+// SameFile reports whether fi1 and fi2 describe the same file.
+// For example, on Unix this means that the device and inode fields
+// of the two underlying structures are identical; on other systems
+// the decision may be based on the path names.
+// SameFile only applies to results returned by this package's Stat.
+// It returns false in other cases.
+func SameFile(fi1, fi2 FileInfo) bool {
+	fs1, ok1 := fi1.(*fileStat)
+	fs2, ok2 := fi2.(*fileStat)
+	if !ok1 || !ok2 {
+		return false
+	}
+	return sameFile(fs1, fs2)
+}
diff --git a/third_party/gofrontend/libgo/go/os/types_notwin.go b/third_party/gofrontend/libgo/go/os/types_notwin.go
new file mode 100644
index 0000000..ea1a073
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/types_notwin.go
@@ -0,0 +1,25 @@
+// 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.
+
+// +build !windows
+
+package os
+
+import (
+	"time"
+)
+
+// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
+type fileStat struct {
+	name    string
+	size    int64
+	mode    FileMode
+	modTime time.Time
+	sys     interface{}
+}
+
+func (fs *fileStat) Size() int64        { return fs.size }
+func (fs *fileStat) Mode() FileMode     { return fs.mode }
+func (fs *fileStat) ModTime() time.Time { return fs.modTime }
+func (fs *fileStat) Sys() interface{}   { return fs.sys }
diff --git a/third_party/gofrontend/libgo/go/os/types_windows.go b/third_party/gofrontend/libgo/go/os/types_windows.go
new file mode 100644
index 0000000..3890168
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/types_windows.go
@@ -0,0 +1,104 @@
+// 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 os
+
+import (
+	"sync"
+	"syscall"
+	"time"
+)
+
+// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
+type fileStat struct {
+	name string
+	sys  syscall.Win32FileAttributeData
+
+	// used to implement SameFile
+	sync.Mutex
+	path  string
+	vol   uint32
+	idxhi uint32
+	idxlo uint32
+}
+
+func (fs *fileStat) Size() int64 {
+	return int64(fs.sys.FileSizeHigh)<<32 + int64(fs.sys.FileSizeLow)
+}
+
+func (fs *fileStat) Mode() (m FileMode) {
+	if fs == &devNullStat {
+		return ModeDevice | ModeCharDevice | 0666
+	}
+	if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
+		m |= ModeDir | 0111
+	}
+	if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY != 0 {
+		m |= 0444
+	} else {
+		m |= 0666
+	}
+	return m
+}
+
+func (fs *fileStat) ModTime() time.Time {
+	return time.Unix(0, fs.sys.LastWriteTime.Nanoseconds())
+}
+
+// Sys returns syscall.Win32FileAttributeData for file fs.
+func (fs *fileStat) Sys() interface{} { return &fs.sys }
+
+func (fs *fileStat) loadFileId() error {
+	fs.Lock()
+	defer fs.Unlock()
+	if fs.path == "" {
+		// already done
+		return nil
+	}
+	pathp, err := syscall.UTF16PtrFromString(fs.path)
+	if err != nil {
+		return err
+	}
+	h, err := syscall.CreateFile(pathp, 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
+	if err != nil {
+		return err
+	}
+	defer syscall.CloseHandle(h)
+	var i syscall.ByHandleFileInformation
+	err = syscall.GetFileInformationByHandle(syscall.Handle(h), &i)
+	if err != nil {
+		return err
+	}
+	fs.path = ""
+	fs.vol = i.VolumeSerialNumber
+	fs.idxhi = i.FileIndexHigh
+	fs.idxlo = i.FileIndexLow
+	return nil
+}
+
+// devNullStat is fileStat structure describing DevNull file ("NUL").
+var devNullStat = fileStat{
+	name: DevNull,
+	// hopefully this will work for SameFile
+	vol:   0,
+	idxhi: 0,
+	idxlo: 0,
+}
+
+func sameFile(fs1, fs2 *fileStat) bool {
+	e := fs1.loadFileId()
+	if e != nil {
+		return false
+	}
+	e = fs2.loadFileId()
+	if e != nil {
+		return false
+	}
+	return fs1.vol == fs2.vol && fs1.idxhi == fs2.idxhi && fs1.idxlo == fs2.idxlo
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return time.Unix(0, fi.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
+}
diff --git a/third_party/gofrontend/libgo/go/os/user/decls_solaris.go b/third_party/gofrontend/libgo/go/os/user/decls_solaris.go
new file mode 100644
index 0000000..788a00f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/user/decls_solaris.go
@@ -0,0 +1,18 @@
+// Copyright 2014 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.
+
+// +build solaris
+// +build cgo
+
+package user
+
+import "syscall"
+
+// Declarations for the libc functions on Solaris.
+
+//extern __posix_getpwnam_r
+func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int
+
+//extern __posix_getpwuid_r
+func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int
diff --git a/third_party/gofrontend/libgo/go/os/user/decls_unix.go b/third_party/gofrontend/libgo/go/os/user/decls_unix.go
new file mode 100644
index 0000000..f76e4c9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/user/decls_unix.go
@@ -0,0 +1,18 @@
+// Copyright 2014 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+// +build cgo
+
+package user
+
+import "syscall"
+
+// Declarations for the libc functions on most Unix systems.
+
+//extern getpwnam_r
+func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int
+
+//extern getpwuid_r
+func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int
diff --git a/third_party/gofrontend/libgo/go/os/user/lookup.go b/third_party/gofrontend/libgo/go/os/user/lookup.go
new file mode 100644
index 0000000..09f00c7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/user/lookup.go
@@ -0,0 +1,22 @@
+// 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.
+
+package user
+
+// Current returns the current user.
+func Current() (*User, error) {
+	return current()
+}
+
+// Lookup looks up a user by username. If the user cannot be found, the
+// returned error is of type UnknownUserError.
+func Lookup(username string) (*User, error) {
+	return lookup(username)
+}
+
+// LookupId looks up a user by userid. If the user cannot be found, the
+// returned error is of type UnknownUserIdError.
+func LookupId(uid string) (*User, error) {
+	return lookupId(uid)
+}
diff --git a/third_party/gofrontend/libgo/go/os/user/lookup_plan9.go b/third_party/gofrontend/libgo/go/os/user/lookup_plan9.go
new file mode 100644
index 0000000..f7ef348
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/user/lookup_plan9.go
@@ -0,0 +1,46 @@
+// Copyright 2013 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 user
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	"syscall"
+)
+
+// Partial os/user support on Plan 9.
+// Supports Current(), but not Lookup()/LookupId().
+// The latter two would require parsing /adm/users.
+const (
+	userFile = "/dev/user"
+)
+
+func current() (*User, error) {
+	ubytes, err := ioutil.ReadFile(userFile)
+	if err != nil {
+		return nil, fmt.Errorf("user: %s", err)
+	}
+
+	uname := string(ubytes)
+
+	u := &User{
+		Uid:      uname,
+		Gid:      uname,
+		Username: uname,
+		Name:     uname,
+		HomeDir:  os.Getenv("home"),
+	}
+
+	return u, nil
+}
+
+func lookup(username string) (*User, error) {
+	return nil, syscall.EPLAN9
+}
+
+func lookupId(uid string) (*User, error) {
+	return nil, syscall.EPLAN9
+}
diff --git a/third_party/gofrontend/libgo/go/os/user/lookup_stubs.go b/third_party/gofrontend/libgo/go/os/user/lookup_stubs.go
new file mode 100644
index 0000000..86f0e6e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/user/lookup_stubs.go
@@ -0,0 +1,28 @@
+// 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.
+
+// +build !cgo,!windows,!plan9
+
+package user
+
+import (
+	"fmt"
+	"runtime"
+)
+
+func init() {
+	implemented = false
+}
+
+func current() (*User, error) {
+	return nil, fmt.Errorf("user: Current not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+func lookup(username string) (*User, error) {
+	return nil, fmt.Errorf("user: Lookup not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+func lookupId(uid string) (*User, error) {
+	return nil, fmt.Errorf("user: LookupId not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
diff --git a/third_party/gofrontend/libgo/go/os/user/lookup_unix.go b/third_party/gofrontend/libgo/go/os/user/lookup_unix.go
new file mode 100644
index 0000000..0db0806
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/user/lookup_unix.go
@@ -0,0 +1,109 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build cgo
+
+package user
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+	"syscall"
+	"unsafe"
+)
+
+/*
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdlib.h>
+
+static int mygetpwuid_r(int uid, struct passwd *pwd,
+	char *buf, size_t buflen, struct passwd **result) {
+ return getpwuid_r(uid, pwd, buf, buflen, result);
+}
+*/
+
+// bytePtrToString takes a NUL-terminated array of bytes and convert
+// it to a Go string.
+func bytePtrToString(p *byte) string {
+	a := (*[10000]byte)(unsafe.Pointer(p))
+	i := 0
+	for a[i] != 0 {
+		i++
+	}
+	return string(a[:i])
+}
+
+func current() (*User, error) {
+	return lookupUnix(syscall.Getuid(), "", false)
+}
+
+func lookup(username string) (*User, error) {
+	return lookupUnix(-1, username, true)
+}
+
+func lookupId(uid string) (*User, error) {
+	i, e := strconv.Atoi(uid)
+	if e != nil {
+		return nil, e
+	}
+	return lookupUnix(i, "", false)
+}
+
+func lookupUnix(uid int, username string, lookupByName bool) (*User, error) {
+	var pwd syscall.Passwd
+	var result *syscall.Passwd
+
+	// FIXME: Should let buf grow if necessary.
+	const bufSize = 1024
+	buf := make([]byte, bufSize)
+	if lookupByName {
+		p := syscall.StringBytePtr(username)
+		syscall.Entersyscall()
+		rv := libc_getpwnam_r(p,
+			&pwd,
+			&buf[0],
+			bufSize,
+			&result)
+		syscall.Exitsyscall()
+		if rv != 0 {
+			return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.GetErrno())
+		}
+		if result == nil {
+			return nil, UnknownUserError(username)
+		}
+	} else {
+		syscall.Entersyscall()
+		rv := libc_getpwuid_r(syscall.Uid_t(uid),
+			&pwd,
+			&buf[0],
+			bufSize,
+			&result)
+		syscall.Exitsyscall()
+		if rv != 0 {
+			return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.GetErrno())
+		}
+		if result == nil {
+			return nil, UnknownUserIdError(uid)
+		}
+	}
+	u := &User{
+		Uid:      strconv.Itoa(int(pwd.Pw_uid)),
+		Gid:      strconv.Itoa(int(pwd.Pw_gid)),
+		Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
+		Name:     bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
+		HomeDir:  bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
+	}
+	// The pw_gecos field isn't quite standardized.  Some docs
+	// say: "It is expected to be a comma separated list of
+	// personal data where the first item is the full name of the
+	// user."
+	if i := strings.Index(u.Name, ","); i >= 0 {
+		u.Name = u.Name[:i]
+	}
+	return u, nil
+}
diff --git a/third_party/gofrontend/libgo/go/os/user/lookup_windows.go b/third_party/gofrontend/libgo/go/os/user/lookup_windows.go
new file mode 100644
index 0000000..99c325f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/user/lookup_windows.go
@@ -0,0 +1,149 @@
+// 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 user
+
+import (
+	"fmt"
+	"syscall"
+	"unsafe"
+)
+
+func isDomainJoined() (bool, error) {
+	var domain *uint16
+	var status uint32
+	err := syscall.NetGetJoinInformation(nil, &domain, &status)
+	if err != nil {
+		return false, err
+	}
+	syscall.NetApiBufferFree((*byte)(unsafe.Pointer(domain)))
+	return status == syscall.NetSetupDomainName, nil
+}
+
+func lookupFullNameDomain(domainAndUser string) (string, error) {
+	return syscall.TranslateAccountName(domainAndUser,
+		syscall.NameSamCompatible, syscall.NameDisplay, 50)
+}
+
+func lookupFullNameServer(servername, username string) (string, error) {
+	s, e := syscall.UTF16PtrFromString(servername)
+	if e != nil {
+		return "", e
+	}
+	u, e := syscall.UTF16PtrFromString(username)
+	if e != nil {
+		return "", e
+	}
+	var p *byte
+	e = syscall.NetUserGetInfo(s, u, 10, &p)
+	if e != nil {
+		return "", e
+	}
+	defer syscall.NetApiBufferFree(p)
+	i := (*syscall.UserInfo10)(unsafe.Pointer(p))
+	if i.FullName == nil {
+		return "", nil
+	}
+	name := syscall.UTF16ToString((*[1024]uint16)(unsafe.Pointer(i.FullName))[:])
+	return name, nil
+}
+
+func lookupFullName(domain, username, domainAndUser string) (string, error) {
+	joined, err := isDomainJoined()
+	if err == nil && joined {
+		name, err := lookupFullNameDomain(domainAndUser)
+		if err == nil {
+			return name, nil
+		}
+	}
+	name, err := lookupFullNameServer(domain, username)
+	if err == nil {
+		return name, nil
+	}
+	// domain worked neigher as a domain nor as a server
+	// could be domain server unavailable
+	// pretend username is fullname
+	return username, nil
+}
+
+func newUser(usid *syscall.SID, gid, dir string) (*User, error) {
+	username, domain, t, e := usid.LookupAccount("")
+	if e != nil {
+		return nil, e
+	}
+	if t != syscall.SidTypeUser {
+		return nil, fmt.Errorf("user: should be user account type, not %d", t)
+	}
+	domainAndUser := domain + `\` + username
+	uid, e := usid.String()
+	if e != nil {
+		return nil, e
+	}
+	name, e := lookupFullName(domain, username, domainAndUser)
+	if e != nil {
+		return nil, e
+	}
+	u := &User{
+		Uid:      uid,
+		Gid:      gid,
+		Username: domainAndUser,
+		Name:     name,
+		HomeDir:  dir,
+	}
+	return u, nil
+}
+
+func current() (*User, error) {
+	t, e := syscall.OpenCurrentProcessToken()
+	if e != nil {
+		return nil, e
+	}
+	defer t.Close()
+	u, e := t.GetTokenUser()
+	if e != nil {
+		return nil, e
+	}
+	pg, e := t.GetTokenPrimaryGroup()
+	if e != nil {
+		return nil, e
+	}
+	gid, e := pg.PrimaryGroup.String()
+	if e != nil {
+		return nil, e
+	}
+	dir, e := t.GetUserProfileDirectory()
+	if e != nil {
+		return nil, e
+	}
+	return newUser(u.User.Sid, gid, dir)
+}
+
+// BUG(brainman): Lookup and LookupId functions do not set
+// Gid and HomeDir fields in the User struct returned on windows.
+
+func newUserFromSid(usid *syscall.SID) (*User, error) {
+	// TODO(brainman): do not know where to get gid and dir fields
+	gid := "unknown"
+	dir := "Unknown directory"
+	return newUser(usid, gid, dir)
+}
+
+func lookup(username string) (*User, error) {
+	sid, _, t, e := syscall.LookupSID("", username)
+	if e != nil {
+		return nil, e
+	}
+	if t != syscall.SidTypeUser {
+		return nil, fmt.Errorf("user: should be user account type, not %d", t)
+	}
+	return newUserFromSid(sid)
+}
+
+func lookupId(uid string) (*User, error) {
+	sid, e := syscall.StringToSid(uid)
+	if e != nil {
+		return nil, e
+	}
+	return newUserFromSid(sid)
+}
diff --git a/third_party/gofrontend/libgo/go/os/user/user.go b/third_party/gofrontend/libgo/go/os/user/user.go
new file mode 100644
index 0000000..e8680fe
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/user/user.go
@@ -0,0 +1,43 @@
+// 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.
+
+// Package user allows user account lookups by name or id.
+package user
+
+import (
+	"strconv"
+)
+
+var implemented = true // set to false by lookup_stubs.go's init
+
+// User represents a user account.
+//
+// On posix systems Uid and Gid contain a decimal number
+// representing uid and gid. On windows Uid and Gid
+// contain security identifier (SID) in a string format.
+// On Plan 9, Uid, Gid, Username, and Name will be the
+// contents of /dev/user.
+type User struct {
+	Uid      string // user id
+	Gid      string // primary group id
+	Username string
+	Name     string
+	HomeDir  string
+}
+
+// UnknownUserIdError is returned by LookupId when
+// a user cannot be found.
+type UnknownUserIdError int
+
+func (e UnknownUserIdError) Error() string {
+	return "user: unknown userid " + strconv.Itoa(int(e))
+}
+
+// UnknownUserError is returned by Lookup when
+// a user cannot be found.
+type UnknownUserError string
+
+func (e UnknownUserError) Error() string {
+	return "user: unknown user " + string(e)
+}
diff --git a/third_party/gofrontend/libgo/go/os/user/user_test.go b/third_party/gofrontend/libgo/go/os/user/user_test.go
new file mode 100644
index 0000000..9d9420e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/os/user/user_test.go
@@ -0,0 +1,89 @@
+// 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.
+
+package user
+
+import (
+	"runtime"
+	"testing"
+)
+
+func check(t *testing.T) {
+	if !implemented {
+		t.Skip("user: not implemented; skipping tests")
+	}
+}
+
+func TestCurrent(t *testing.T) {
+	check(t)
+
+	u, err := Current()
+	if err != nil {
+		t.Fatalf("Current: %v", err)
+	}
+	if u.HomeDir == "" {
+		t.Errorf("didn't get a HomeDir")
+	}
+	if u.Username == "" {
+		t.Errorf("didn't get a username")
+	}
+}
+
+func compare(t *testing.T, want, got *User) {
+	if want.Uid != got.Uid {
+		t.Errorf("got Uid=%q; want %q", got.Uid, want.Uid)
+	}
+	if want.Username != got.Username {
+		t.Errorf("got Username=%q; want %q", got.Username, want.Username)
+	}
+	if want.Name != got.Name {
+		t.Errorf("got Name=%q; want %q", got.Name, want.Name)
+	}
+	// TODO(brainman): fix it once we know how.
+	if runtime.GOOS == "windows" {
+		t.Skip("skipping Gid and HomeDir comparisons")
+	}
+	if want.Gid != got.Gid {
+		t.Errorf("got Gid=%q; want %q", got.Gid, want.Gid)
+	}
+	if want.HomeDir != got.HomeDir {
+		t.Errorf("got HomeDir=%q; want %q", got.HomeDir, want.HomeDir)
+	}
+}
+
+func TestLookup(t *testing.T) {
+	check(t)
+
+	if runtime.GOOS == "plan9" {
+		t.Skipf("Lookup not implemented on %q", runtime.GOOS)
+	}
+
+	want, err := Current()
+	if err != nil {
+		t.Fatalf("Current: %v", err)
+	}
+	got, err := Lookup(want.Username)
+	if err != nil {
+		t.Fatalf("Lookup: %v", err)
+	}
+	compare(t, want, got)
+}
+
+func TestLookupId(t *testing.T) {
+	check(t)
+
+	if runtime.GOOS == "plan9" {
+		t.Skipf("LookupId not implemented on %q", runtime.GOOS)
+	}
+
+	want, err := Current()
+	if err != nil {
+		t.Fatalf("Current: %v", err)
+	}
+	got, err := LookupId(want.Uid)
+	if err != nil {
+		t.Fatalf("LookupId: %v", err)
+	}
+	compare(t, want, got)
+}
diff --git a/third_party/gofrontend/libgo/go/path/example_test.go b/third_party/gofrontend/libgo/go/path/example_test.go
new file mode 100644
index 0000000..ca18b32
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/example_test.go
@@ -0,0 +1,67 @@
+// 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 path
+
+/* Commented out until gccgo has example support.
+
+import (
+	"fmt"
+	"path"
+)
+
+func ExampleBase() {
+	fmt.Println(path.Base("/a/b"))
+	// Output: b
+}
+
+func ExampleClean() {
+	paths := []string{
+		"a/c",
+		"a//c",
+		"a/c/.",
+		"a/c/b/..",
+		"/../a/c",
+		"/../a/b/../././/c",
+	}
+
+	for _, p := range paths {
+		fmt.Printf("Clean(%q) = %q\n", p, path.Clean(p))
+	}
+
+	// Output:
+	// Clean("a/c") = "a/c"
+	// Clean("a//c") = "a/c"
+	// Clean("a/c/.") = "a/c"
+	// Clean("a/c/b/..") = "a/c"
+	// Clean("/../a/c") = "/a/c"
+	// Clean("/../a/b/../././/c") = "/a/c"
+}
+
+func ExampleDir() {
+	fmt.Println(path.Dir("/a/b/c"))
+	// Output: /a/b
+}
+
+func ExampleExt() {
+	fmt.Println(path.Ext("/a/b/c/bar.css"))
+	// Output: .css
+}
+
+func ExampleIsAbs() {
+	fmt.Println(path.IsAbs("/dev/null"))
+	// Output: true
+}
+
+func ExampleJoin() {
+	fmt.Println(path.Join("a", "b", "c"))
+	// Output: a/b/c
+}
+
+func ExampleSplit() {
+	fmt.Println(path.Split("static/myfile.css"))
+	// Output: static/ myfile.css
+}
+
+*/
diff --git a/third_party/gofrontend/libgo/go/path/filepath/example_unix_test.go b/third_party/gofrontend/libgo/go/path/filepath/example_unix_test.go
new file mode 100644
index 0000000..f3fe076
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/example_unix_test.go
@@ -0,0 +1,39 @@
+// Copyright 2013 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.
+
+// +build !windows,!plan9
+
+package filepath_test
+
+import (
+	"fmt"
+	"path/filepath"
+)
+
+func ExampleSplitList() {
+	fmt.Println("On Unix:", filepath.SplitList("/a/b/c:/usr/bin"))
+	// Output:
+	// On Unix: [/a/b/c /usr/bin]
+}
+
+func ExampleRel() {
+	paths := []string{
+		"/a/b/c",
+		"/b/c",
+		"./b/c",
+	}
+	base := "/a"
+
+	fmt.Println("On Unix:")
+	for _, p := range paths {
+		rel, err := filepath.Rel(base, p)
+		fmt.Printf("%q: %q %v\n", p, rel, err)
+	}
+
+	// Output:
+	// On Unix:
+	// "/a/b/c": "b/c" <nil>
+	// "/b/c": "../b/c" <nil>
+	// "./b/c": "" Rel: can't make b/c relative to /a
+}
diff --git a/third_party/gofrontend/libgo/go/path/filepath/export_test.go b/third_party/gofrontend/libgo/go/path/filepath/export_test.go
new file mode 100644
index 0000000..0cf9e3b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/export_test.go
@@ -0,0 +1,7 @@
+// Copyright 2013 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 filepath
+
+var LstatP = &lstat
diff --git a/third_party/gofrontend/libgo/go/path/filepath/match.go b/third_party/gofrontend/libgo/go/path/filepath/match.go
new file mode 100644
index 0000000..a9bcc10
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/match.go
@@ -0,0 +1,309 @@
+// Copyright 2010 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 filepath
+
+import (
+	"errors"
+	"os"
+	"runtime"
+	"sort"
+	"strings"
+	"unicode/utf8"
+)
+
+// ErrBadPattern indicates a globbing pattern was malformed.
+var ErrBadPattern = errors.New("syntax error in pattern")
+
+// Match returns true if name matches the shell file name pattern.
+// The pattern syntax is:
+//
+//	pattern:
+//		{ term }
+//	term:
+//		'*'         matches any sequence of non-Separator characters
+//		'?'         matches any single non-Separator character
+//		'[' [ '^' ] { character-range } ']'
+//		            character class (must be non-empty)
+//		c           matches character c (c != '*', '?', '\\', '[')
+//		'\\' c      matches character c
+//
+//	character-range:
+//		c           matches character c (c != '\\', '-', ']')
+//		'\\' c      matches character c
+//		lo '-' hi   matches character c for lo <= c <= hi
+//
+// Match requires pattern to match all of name, not just a substring.
+// The only possible returned error is ErrBadPattern, when pattern
+// is malformed.
+//
+// On Windows, escaping is disabled. Instead, '\\' is treated as
+// path separator.
+//
+func Match(pattern, name string) (matched bool, err error) {
+Pattern:
+	for len(pattern) > 0 {
+		var star bool
+		var chunk string
+		star, chunk, pattern = scanChunk(pattern)
+		if star && chunk == "" {
+			// Trailing * matches rest of string unless it has a /.
+			return strings.Index(name, string(Separator)) < 0, nil
+		}
+		// Look for match at current position.
+		t, ok, err := matchChunk(chunk, name)
+		// if we're the last chunk, make sure we've exhausted the name
+		// otherwise we'll give a false result even if we could still match
+		// using the star
+		if ok && (len(t) == 0 || len(pattern) > 0) {
+			name = t
+			continue
+		}
+		if err != nil {
+			return false, err
+		}
+		if star {
+			// Look for match skipping i+1 bytes.
+			// Cannot skip /.
+			for i := 0; i < len(name) && name[i] != Separator; i++ {
+				t, ok, err := matchChunk(chunk, name[i+1:])
+				if ok {
+					// if we're the last chunk, make sure we exhausted the name
+					if len(pattern) == 0 && len(t) > 0 {
+						continue
+					}
+					name = t
+					continue Pattern
+				}
+				if err != nil {
+					return false, err
+				}
+			}
+		}
+		return false, nil
+	}
+	return len(name) == 0, nil
+}
+
+// scanChunk gets the next segment of pattern, which is a non-star string
+// possibly preceded by a star.
+func scanChunk(pattern string) (star bool, chunk, rest string) {
+	for len(pattern) > 0 && pattern[0] == '*' {
+		pattern = pattern[1:]
+		star = true
+	}
+	inrange := false
+	var i int
+Scan:
+	for i = 0; i < len(pattern); i++ {
+		switch pattern[i] {
+		case '\\':
+			if runtime.GOOS != "windows" {
+				// error check handled in matchChunk: bad pattern.
+				if i+1 < len(pattern) {
+					i++
+				}
+			}
+		case '[':
+			inrange = true
+		case ']':
+			inrange = false
+		case '*':
+			if !inrange {
+				break Scan
+			}
+		}
+	}
+	return star, pattern[0:i], pattern[i:]
+}
+
+// matchChunk checks whether chunk matches the beginning of s.
+// If so, it returns the remainder of s (after the match).
+// Chunk is all single-character operators: literals, char classes, and ?.
+func matchChunk(chunk, s string) (rest string, ok bool, err error) {
+	for len(chunk) > 0 {
+		if len(s) == 0 {
+			return
+		}
+		switch chunk[0] {
+		case '[':
+			// character class
+			r, n := utf8.DecodeRuneInString(s)
+			s = s[n:]
+			chunk = chunk[1:]
+			// We can't end right after '[', we're expecting at least
+			// a closing bracket and possibly a caret.
+			if len(chunk) == 0 {
+				err = ErrBadPattern
+				return
+			}
+			// possibly negated
+			negated := chunk[0] == '^'
+			if negated {
+				chunk = chunk[1:]
+			}
+			// parse all ranges
+			match := false
+			nrange := 0
+			for {
+				if len(chunk) > 0 && chunk[0] == ']' && nrange > 0 {
+					chunk = chunk[1:]
+					break
+				}
+				var lo, hi rune
+				if lo, chunk, err = getEsc(chunk); err != nil {
+					return
+				}
+				hi = lo
+				if chunk[0] == '-' {
+					if hi, chunk, err = getEsc(chunk[1:]); err != nil {
+						return
+					}
+				}
+				if lo <= r && r <= hi {
+					match = true
+				}
+				nrange++
+			}
+			if match == negated {
+				return
+			}
+
+		case '?':
+			if s[0] == Separator {
+				return
+			}
+			_, n := utf8.DecodeRuneInString(s)
+			s = s[n:]
+			chunk = chunk[1:]
+
+		case '\\':
+			if runtime.GOOS != "windows" {
+				chunk = chunk[1:]
+				if len(chunk) == 0 {
+					err = ErrBadPattern
+					return
+				}
+			}
+			fallthrough
+
+		default:
+			if chunk[0] != s[0] {
+				return
+			}
+			s = s[1:]
+			chunk = chunk[1:]
+		}
+	}
+	return s, true, nil
+}
+
+// getEsc gets a possibly-escaped character from chunk, for a character class.
+func getEsc(chunk string) (r rune, nchunk string, err error) {
+	if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' {
+		err = ErrBadPattern
+		return
+	}
+	if chunk[0] == '\\' && runtime.GOOS != "windows" {
+		chunk = chunk[1:]
+		if len(chunk) == 0 {
+			err = ErrBadPattern
+			return
+		}
+	}
+	r, n := utf8.DecodeRuneInString(chunk)
+	if r == utf8.RuneError && n == 1 {
+		err = ErrBadPattern
+	}
+	nchunk = chunk[n:]
+	if len(nchunk) == 0 {
+		err = ErrBadPattern
+	}
+	return
+}
+
+// Glob returns the names of all files matching pattern or nil
+// if there is no matching file. The syntax of patterns is the same
+// as in Match. The pattern may describe hierarchical names such as
+// /usr/*/bin/ed (assuming the Separator is '/').
+//
+func Glob(pattern string) (matches []string, err error) {
+	if !hasMeta(pattern) {
+		if _, err = os.Lstat(pattern); err != nil {
+			return nil, nil
+		}
+		return []string{pattern}, nil
+	}
+
+	dir, file := Split(pattern)
+	switch dir {
+	case "":
+		dir = "."
+	case string(Separator):
+		// nothing
+	default:
+		dir = dir[0 : len(dir)-1] // chop off trailing separator
+	}
+
+	if !hasMeta(dir) {
+		return glob(dir, file, nil)
+	}
+
+	var m []string
+	m, err = Glob(dir)
+	if err != nil {
+		return
+	}
+	for _, d := range m {
+		matches, err = glob(d, file, matches)
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+// glob searches for files matching pattern in the directory dir
+// and appends them to matches. If the directory cannot be
+// opened, it returns the existing matches. New matches are
+// added in lexicographical order.
+func glob(dir, pattern string, matches []string) (m []string, e error) {
+	m = matches
+	fi, err := os.Stat(dir)
+	if err != nil {
+		return
+	}
+	if !fi.IsDir() {
+		return
+	}
+	d, err := os.Open(dir)
+	if err != nil {
+		return
+	}
+	defer d.Close()
+
+	names, err := d.Readdirnames(-1)
+	if err != nil {
+		return
+	}
+	sort.Strings(names)
+
+	for _, n := range names {
+		matched, err := Match(pattern, n)
+		if err != nil {
+			return m, err
+		}
+		if matched {
+			m = append(m, Join(dir, n))
+		}
+	}
+	return
+}
+
+// hasMeta returns true if path contains any of the magic characters
+// recognized by Match.
+func hasMeta(path string) bool {
+	// TODO(niemeyer): Should other magic characters be added here?
+	return strings.IndexAny(path, "*?[") >= 0
+}
diff --git a/third_party/gofrontend/libgo/go/path/filepath/match_test.go b/third_party/gofrontend/libgo/go/path/filepath/match_test.go
new file mode 100644
index 0000000..9886620
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/match_test.go
@@ -0,0 +1,207 @@
+// 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 filepath_test
+
+import (
+	"io/ioutil"
+	"os"
+	. "path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+type MatchTest struct {
+	pattern, s string
+	match      bool
+	err        error
+}
+
+var matchTests = []MatchTest{
+	{"abc", "abc", true, nil},
+	{"*", "abc", true, nil},
+	{"*c", "abc", true, nil},
+	{"a*", "a", true, nil},
+	{"a*", "abc", true, nil},
+	{"a*", "ab/c", false, nil},
+	{"a*/b", "abc/b", true, nil},
+	{"a*/b", "a/c/b", false, nil},
+	{"a*b*c*d*e*/f", "axbxcxdxe/f", true, nil},
+	{"a*b*c*d*e*/f", "axbxcxdxexxx/f", true, nil},
+	{"a*b*c*d*e*/f", "axbxcxdxe/xxx/f", false, nil},
+	{"a*b*c*d*e*/f", "axbxcxdxexxx/fff", false, nil},
+	{"a*b?c*x", "abxbbxdbxebxczzx", true, nil},
+	{"a*b?c*x", "abxbbxdbxebxczzy", false, nil},
+	{"ab[c]", "abc", true, nil},
+	{"ab[b-d]", "abc", true, nil},
+	{"ab[e-g]", "abc", false, nil},
+	{"ab[^c]", "abc", false, nil},
+	{"ab[^b-d]", "abc", false, nil},
+	{"ab[^e-g]", "abc", true, nil},
+	{"a\\*b", "a*b", true, nil},
+	{"a\\*b", "ab", false, nil},
+	{"a?b", "a☺b", true, nil},
+	{"a[^a]b", "a☺b", true, nil},
+	{"a???b", "a☺b", false, nil},
+	{"a[^a][^a][^a]b", "a☺b", false, nil},
+	{"[a-ζ]*", "α", true, nil},
+	{"*[a-ζ]", "A", false, nil},
+	{"a?b", "a/b", false, nil},
+	{"a*b", "a/b", false, nil},
+	{"[\\]a]", "]", true, nil},
+	{"[\\-]", "-", true, nil},
+	{"[x\\-]", "x", true, nil},
+	{"[x\\-]", "-", true, nil},
+	{"[x\\-]", "z", false, nil},
+	{"[\\-x]", "x", true, nil},
+	{"[\\-x]", "-", true, nil},
+	{"[\\-x]", "a", false, nil},
+	{"[]a]", "]", false, ErrBadPattern},
+	{"[-]", "-", false, ErrBadPattern},
+	{"[x-]", "x", false, ErrBadPattern},
+	{"[x-]", "-", false, ErrBadPattern},
+	{"[x-]", "z", false, ErrBadPattern},
+	{"[-x]", "x", false, ErrBadPattern},
+	{"[-x]", "-", false, ErrBadPattern},
+	{"[-x]", "a", false, ErrBadPattern},
+	{"\\", "a", false, ErrBadPattern},
+	{"[a-b-c]", "a", false, ErrBadPattern},
+	{"[", "a", false, ErrBadPattern},
+	{"[^", "a", false, ErrBadPattern},
+	{"[^bc", "a", false, ErrBadPattern},
+	{"a[", "a", false, nil},
+	{"a[", "ab", false, ErrBadPattern},
+	{"*x", "xxx", true, nil},
+}
+
+func errp(e error) string {
+	if e == nil {
+		return "<nil>"
+	}
+	return e.Error()
+}
+
+func TestMatch(t *testing.T) {
+	for _, tt := range matchTests {
+		pattern := tt.pattern
+		s := tt.s
+		if runtime.GOOS == "windows" {
+			if strings.Index(pattern, "\\") >= 0 {
+				// no escape allowed on windows.
+				continue
+			}
+			pattern = Clean(pattern)
+			s = Clean(s)
+		}
+		ok, err := Match(pattern, s)
+		if ok != tt.match || err != tt.err {
+			t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", pattern, s, ok, errp(err), tt.match, errp(tt.err))
+		}
+	}
+}
+
+// contains returns true if vector contains the string s.
+func contains(vector []string, s string) bool {
+	for _, elem := range vector {
+		if elem == s {
+			return true
+		}
+	}
+	return false
+}
+
+var globTests = []struct {
+	pattern, result string
+}{
+	{"match.go", "match.go"},
+	{"mat?h.go", "match.go"},
+	{"*", "match.go"},
+	// Does not work in gccgo test environment.
+	// {"../*/match.go", "../filepath/match.go"},
+}
+
+func TestGlob(t *testing.T) {
+	for _, tt := range globTests {
+		pattern := tt.pattern
+		result := tt.result
+		if runtime.GOOS == "windows" {
+			pattern = Clean(pattern)
+			result = Clean(result)
+		}
+		matches, err := Glob(pattern)
+		if err != nil {
+			t.Errorf("Glob error for %q: %s", pattern, err)
+			continue
+		}
+		if !contains(matches, result) {
+			t.Errorf("Glob(%#q) = %#v want %v", pattern, matches, result)
+		}
+	}
+	for _, pattern := range []string{"no_match", "../*/no_match"} {
+		matches, err := Glob(pattern)
+		if err != nil {
+			t.Errorf("Glob error for %q: %s", pattern, err)
+			continue
+		}
+		if len(matches) != 0 {
+			t.Errorf("Glob(%#q) = %#v want []", pattern, matches)
+		}
+	}
+}
+
+func TestGlobError(t *testing.T) {
+	_, err := Glob("[7]")
+	if err != nil {
+		t.Error("expected error for bad pattern; got none")
+	}
+}
+
+var globSymlinkTests = []struct {
+	path, dest string
+	brokenLink bool
+}{
+	{"test1", "link1", false},
+	{"test2", "link2", true},
+}
+
+func TestGlobSymlink(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9", "windows":
+		t.Skipf("skipping on %s", runtime.GOOS)
+	}
+
+	tmpDir, err := ioutil.TempDir("", "globsymlink")
+	if err != nil {
+		t.Fatal("creating temp dir:", err)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	for _, tt := range globSymlinkTests {
+		path := Join(tmpDir, tt.path)
+		dest := Join(tmpDir, tt.dest)
+		f, err := os.Create(path)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if err := f.Close(); err != nil {
+			t.Fatal(err)
+		}
+		err = os.Symlink(path, dest)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if tt.brokenLink {
+			// Break the symlink.
+			os.Remove(path)
+		}
+		matches, err := Glob(dest)
+		if err != nil {
+			t.Errorf("GlobSymlink error for %q: %s", dest, err)
+		}
+		if !contains(matches, dest) {
+			t.Errorf("Glob(%#q) = %#v want %v", dest, matches, dest)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/path/filepath/path.go b/third_party/gofrontend/libgo/go/path/filepath/path.go
new file mode 100644
index 0000000..71603cc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/path.go
@@ -0,0 +1,467 @@
+// 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 filepath implements utility routines for manipulating filename paths
+// in a way compatible with the target operating system-defined file paths.
+package filepath
+
+import (
+	"errors"
+	"os"
+	"sort"
+	"strings"
+)
+
+// A lazybuf is a lazily constructed path buffer.
+// It supports append, reading previously appended bytes,
+// and retrieving the final string. It does not allocate a buffer
+// to hold the output until that output diverges from s.
+type lazybuf struct {
+	path       string
+	buf        []byte
+	w          int
+	volAndPath string
+	volLen     int
+}
+
+func (b *lazybuf) index(i int) byte {
+	if b.buf != nil {
+		return b.buf[i]
+	}
+	return b.path[i]
+}
+
+func (b *lazybuf) append(c byte) {
+	if b.buf == nil {
+		if b.w < len(b.path) && b.path[b.w] == c {
+			b.w++
+			return
+		}
+		b.buf = make([]byte, len(b.path))
+		copy(b.buf, b.path[:b.w])
+	}
+	b.buf[b.w] = c
+	b.w++
+}
+
+func (b *lazybuf) string() string {
+	if b.buf == nil {
+		return b.volAndPath[:b.volLen+b.w]
+	}
+	return b.volAndPath[:b.volLen] + string(b.buf[:b.w])
+}
+
+const (
+	Separator     = os.PathSeparator
+	ListSeparator = os.PathListSeparator
+)
+
+// Clean returns the shortest path name equivalent to path
+// by purely lexical processing.  It applies the following rules
+// iteratively until no further processing can be done:
+//
+//	1. Replace multiple Separator elements with a single one.
+//	2. Eliminate each . path name element (the current directory).
+//	3. Eliminate each inner .. path name element (the parent directory)
+//	   along with the non-.. element that precedes it.
+//	4. Eliminate .. elements that begin a rooted path:
+//	   that is, replace "/.." by "/" at the beginning of a path,
+//	   assuming Separator is '/'.
+//
+// The returned path ends in a slash only if it represents a root directory,
+// such as "/" on Unix or `C:\` on Windows.
+//
+// If the result of this process is an empty string, Clean
+// returns the string ".".
+//
+// See also Rob Pike, ``Lexical File Names in Plan 9 or
+// Getting Dot-Dot Right,''
+// http://plan9.bell-labs.com/sys/doc/lexnames.html
+func Clean(path string) string {
+	originalPath := path
+	volLen := volumeNameLen(path)
+	path = path[volLen:]
+	if path == "" {
+		if volLen > 1 && originalPath[1] != ':' {
+			// should be UNC
+			return FromSlash(originalPath)
+		}
+		return originalPath + "."
+	}
+	rooted := os.IsPathSeparator(path[0])
+
+	// Invariants:
+	//	reading from path; r is index of next byte to process.
+	//	writing to buf; w is index of next byte to write.
+	//	dotdot is index in buf where .. must stop, either because
+	//		it is the leading slash or it is a leading ../../.. prefix.
+	n := len(path)
+	out := lazybuf{path: path, volAndPath: originalPath, volLen: volLen}
+	r, dotdot := 0, 0
+	if rooted {
+		out.append(Separator)
+		r, dotdot = 1, 1
+	}
+
+	for r < n {
+		switch {
+		case os.IsPathSeparator(path[r]):
+			// empty path element
+			r++
+		case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
+			// . element
+			r++
+		case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
+			// .. element: remove to last separator
+			r += 2
+			switch {
+			case out.w > dotdot:
+				// can backtrack
+				out.w--
+				for out.w > dotdot && !os.IsPathSeparator(out.index(out.w)) {
+					out.w--
+				}
+			case !rooted:
+				// cannot backtrack, but not rooted, so append .. element.
+				if out.w > 0 {
+					out.append(Separator)
+				}
+				out.append('.')
+				out.append('.')
+				dotdot = out.w
+			}
+		default:
+			// real path element.
+			// add slash if needed
+			if rooted && out.w != 1 || !rooted && out.w != 0 {
+				out.append(Separator)
+			}
+			// copy element
+			for ; r < n && !os.IsPathSeparator(path[r]); r++ {
+				out.append(path[r])
+			}
+		}
+	}
+
+	// Turn empty string into "."
+	if out.w == 0 {
+		out.append('.')
+	}
+
+	return FromSlash(out.string())
+}
+
+// ToSlash returns the result of replacing each separator character
+// in path with a slash ('/') character. Multiple separators are
+// replaced by multiple slashes.
+func ToSlash(path string) string {
+	if Separator == '/' {
+		return path
+	}
+	return strings.Replace(path, string(Separator), "/", -1)
+}
+
+// FromSlash returns the result of replacing each slash ('/') character
+// in path with a separator character. Multiple slashes are replaced
+// by multiple separators.
+func FromSlash(path string) string {
+	if Separator == '/' {
+		return path
+	}
+	return strings.Replace(path, "/", string(Separator), -1)
+}
+
+// SplitList splits a list of paths joined by the OS-specific ListSeparator,
+// usually found in PATH or GOPATH environment variables.
+// Unlike strings.Split, SplitList returns an empty slice when passed an empty string.
+func SplitList(path string) []string {
+	return splitList(path)
+}
+
+// Split splits path immediately following the final Separator,
+// separating it into a directory and file name component.
+// If there is no Separator in path, Split returns an empty dir
+// and file set to path.
+// The returned values have the property that path = dir+file.
+func Split(path string) (dir, file string) {
+	vol := VolumeName(path)
+	i := len(path) - 1
+	for i >= len(vol) && !os.IsPathSeparator(path[i]) {
+		i--
+	}
+	return path[:i+1], path[i+1:]
+}
+
+// Join joins any number of path elements into a single path, adding
+// a Separator if necessary. The result is Cleaned, in particular
+// all empty strings are ignored.
+func Join(elem ...string) string {
+	for i, e := range elem {
+		if e != "" {
+			return Clean(strings.Join(elem[i:], string(Separator)))
+		}
+	}
+	return ""
+}
+
+// Ext returns the file name extension used by path.
+// The extension is the suffix beginning at the final dot
+// in the final element of path; it is empty if there is
+// no dot.
+func Ext(path string) string {
+	for i := len(path) - 1; i >= 0 && !os.IsPathSeparator(path[i]); i-- {
+		if path[i] == '.' {
+			return path[i:]
+		}
+	}
+	return ""
+}
+
+// EvalSymlinks returns the path name after the evaluation of any symbolic
+// links.
+// If path is relative the result will be relative to the current directory,
+// unless one of the components is an absolute symbolic link.
+func EvalSymlinks(path string) (string, error) {
+	return evalSymlinks(path)
+}
+
+// Abs returns an absolute representation of path.
+// If the path is not absolute it will be joined with the current
+// working directory to turn it into an absolute path.  The absolute
+// path name for a given file is not guaranteed to be unique.
+func Abs(path string) (string, error) {
+	if IsAbs(path) {
+		return Clean(path), nil
+	}
+	wd, err := os.Getwd()
+	if err != nil {
+		return "", err
+	}
+	return Join(wd, path), nil
+}
+
+// Rel returns a relative path that is lexically equivalent to targpath when
+// joined to basepath with an intervening separator. That is,
+// Join(basepath, Rel(basepath, targpath)) is equivalent to targpath itself.
+// On success, the returned path will always be relative to basepath,
+// even if basepath and targpath share no elements.
+// An error is returned if targpath can't be made relative to basepath or if
+// knowing the current working directory would be necessary to compute it.
+func Rel(basepath, targpath string) (string, error) {
+	baseVol := VolumeName(basepath)
+	targVol := VolumeName(targpath)
+	base := Clean(basepath)
+	targ := Clean(targpath)
+	if targ == base {
+		return ".", nil
+	}
+	base = base[len(baseVol):]
+	targ = targ[len(targVol):]
+	if base == "." {
+		base = ""
+	}
+	// Can't use IsAbs - `\a` and `a` are both relative in Windows.
+	baseSlashed := len(base) > 0 && base[0] == Separator
+	targSlashed := len(targ) > 0 && targ[0] == Separator
+	if baseSlashed != targSlashed || baseVol != targVol {
+		return "", errors.New("Rel: can't make " + targ + " relative to " + base)
+	}
+	// Position base[b0:bi] and targ[t0:ti] at the first differing elements.
+	bl := len(base)
+	tl := len(targ)
+	var b0, bi, t0, ti int
+	for {
+		for bi < bl && base[bi] != Separator {
+			bi++
+		}
+		for ti < tl && targ[ti] != Separator {
+			ti++
+		}
+		if targ[t0:ti] != base[b0:bi] {
+			break
+		}
+		if bi < bl {
+			bi++
+		}
+		if ti < tl {
+			ti++
+		}
+		b0 = bi
+		t0 = ti
+	}
+	if base[b0:bi] == ".." {
+		return "", errors.New("Rel: can't make " + targ + " relative to " + base)
+	}
+	if b0 != bl {
+		// Base elements left. Must go up before going down.
+		seps := strings.Count(base[b0:bl], string(Separator))
+		size := 2 + seps*3
+		if tl != t0 {
+			size += 1 + tl - t0
+		}
+		buf := make([]byte, size)
+		n := copy(buf, "..")
+		for i := 0; i < seps; i++ {
+			buf[n] = Separator
+			copy(buf[n+1:], "..")
+			n += 3
+		}
+		if t0 != tl {
+			buf[n] = Separator
+			copy(buf[n+1:], targ[t0:])
+		}
+		return string(buf), nil
+	}
+	return targ[t0:], nil
+}
+
+// SkipDir is used as a return value from WalkFuncs to indicate that
+// the directory named in the call is to be skipped. It is not returned
+// as an error by any function.
+var SkipDir = errors.New("skip this directory")
+
+// WalkFunc is the type of the function called for each file or directory
+// visited by Walk. The path argument contains the argument to Walk as a
+// prefix; that is, if Walk is called with "dir", which is a directory
+// containing the file "a", the walk function will be called with argument
+// "dir/a". The info argument is the os.FileInfo for the named path.
+//
+// If there was a problem walking to the file or directory named by path, the
+// incoming error will describe the problem and the function can decide how
+// to handle that error (and Walk will not descend into that directory). If
+// an error is returned, processing stops. The sole exception is that if path
+// is a directory and the function returns the special value SkipDir, the
+// contents of the directory are skipped and processing continues as usual on
+// the next file.
+type WalkFunc func(path string, info os.FileInfo, err error) error
+
+var lstat = os.Lstat // for testing
+
+// walk recursively descends path, calling w.
+func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
+	err := walkFn(path, info, nil)
+	if err != nil {
+		if info.IsDir() && err == SkipDir {
+			return nil
+		}
+		return err
+	}
+
+	if !info.IsDir() {
+		return nil
+	}
+
+	names, err := readDirNames(path)
+	if err != nil {
+		return walkFn(path, info, err)
+	}
+
+	for _, name := range names {
+		filename := Join(path, name)
+		fileInfo, err := lstat(filename)
+		if err != nil {
+			if err := walkFn(filename, fileInfo, err); err != nil && err != SkipDir {
+				return err
+			}
+		} else {
+			err = walk(filename, fileInfo, walkFn)
+			if err != nil {
+				if !fileInfo.IsDir() || err != SkipDir {
+					return err
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// Walk walks the file tree rooted at root, calling walkFn for each file or
+// directory in the tree, including root. All errors that arise visiting files
+// and directories are filtered by walkFn. The files are walked in lexical
+// order, which makes the output deterministic but means that for very
+// large directories Walk can be inefficient.
+// Walk does not follow symbolic links.
+func Walk(root string, walkFn WalkFunc) error {
+	info, err := os.Lstat(root)
+	if err != nil {
+		return walkFn(root, nil, err)
+	}
+	return walk(root, info, walkFn)
+}
+
+// readDirNames reads the directory named by dirname and returns
+// a sorted list of directory entries.
+func readDirNames(dirname string) ([]string, error) {
+	f, err := os.Open(dirname)
+	if err != nil {
+		return nil, err
+	}
+	names, err := f.Readdirnames(-1)
+	f.Close()
+	if err != nil {
+		return nil, err
+	}
+	sort.Strings(names)
+	return names, nil
+}
+
+// Base returns the last element of path.
+// Trailing path separators are removed before extracting the last element.
+// If the path is empty, Base returns ".".
+// If the path consists entirely of separators, Base returns a single separator.
+func Base(path string) string {
+	if path == "" {
+		return "."
+	}
+	// Strip trailing slashes.
+	for len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
+		path = path[0 : len(path)-1]
+	}
+	// Throw away volume name
+	path = path[len(VolumeName(path)):]
+	// Find the last element
+	i := len(path) - 1
+	for i >= 0 && !os.IsPathSeparator(path[i]) {
+		i--
+	}
+	if i >= 0 {
+		path = path[i+1:]
+	}
+	// If empty now, it had only slashes.
+	if path == "" {
+		return string(Separator)
+	}
+	return path
+}
+
+// Dir returns all but the last element of path, typically the path's directory.
+// After dropping the final element, the path is Cleaned and trailing
+// slashes are removed.
+// If the path is empty, Dir returns ".".
+// If the path consists entirely of separators, Dir returns a single separator.
+// The returned path does not end in a separator unless it is the root directory.
+func Dir(path string) string {
+	vol := VolumeName(path)
+	i := len(path) - 1
+	for i >= len(vol) && !os.IsPathSeparator(path[i]) {
+		i--
+	}
+	dir := Clean(path[len(vol) : i+1])
+	last := len(dir) - 1
+	if last > 0 && os.IsPathSeparator(dir[last]) {
+		dir = dir[:last]
+	}
+	if dir == "" {
+		dir = "."
+	}
+	return vol + dir
+}
+
+// VolumeName returns leading volume name.
+// Given "C:\foo\bar" it returns "C:" under windows.
+// Given "\\host\share\foo" it returns "\\host\share".
+// On other platforms it returns "".
+func VolumeName(path string) (v string) {
+	return path[:volumeNameLen(path)]
+}
diff --git a/third_party/gofrontend/libgo/go/path/filepath/path_plan9.go b/third_party/gofrontend/libgo/go/path/filepath/path_plan9.go
new file mode 100644
index 0000000..12e85aa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/path_plan9.go
@@ -0,0 +1,30 @@
+// Copyright 2010 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 filepath
+
+import "strings"
+
+// IsAbs returns true if the path is absolute.
+func IsAbs(path string) bool {
+	return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "#")
+}
+
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
+	return 0
+}
+
+// HasPrefix exists for historical compatibility and should not be used.
+func HasPrefix(p, prefix string) bool {
+	return strings.HasPrefix(p, prefix)
+}
+
+func splitList(path string) []string {
+	if path == "" {
+		return []string{}
+	}
+	return strings.Split(path, string(ListSeparator))
+}
diff --git a/third_party/gofrontend/libgo/go/path/filepath/path_test.go b/third_party/gofrontend/libgo/go/path/filepath/path_test.go
new file mode 100644
index 0000000..6d11394
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/path_test.go
@@ -0,0 +1,1025 @@
+// 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 filepath_test
+
+import (
+	"errors"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"reflect"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+type PathTest struct {
+	path, result string
+}
+
+var cleantests = []PathTest{
+	// Already clean
+	{"abc", "abc"},
+	{"abc/def", "abc/def"},
+	{"a/b/c", "a/b/c"},
+	{".", "."},
+	{"..", ".."},
+	{"../..", "../.."},
+	{"../../abc", "../../abc"},
+	{"/abc", "/abc"},
+	{"/", "/"},
+
+	// Empty is current dir
+	{"", "."},
+
+	// Remove trailing slash
+	{"abc/", "abc"},
+	{"abc/def/", "abc/def"},
+	{"a/b/c/", "a/b/c"},
+	{"./", "."},
+	{"../", ".."},
+	{"../../", "../.."},
+	{"/abc/", "/abc"},
+
+	// Remove doubled slash
+	{"abc//def//ghi", "abc/def/ghi"},
+	{"//abc", "/abc"},
+	{"///abc", "/abc"},
+	{"//abc//", "/abc"},
+	{"abc//", "abc"},
+
+	// Remove . elements
+	{"abc/./def", "abc/def"},
+	{"/./abc/def", "/abc/def"},
+	{"abc/.", "abc"},
+
+	// Remove .. elements
+	{"abc/def/ghi/../jkl", "abc/def/jkl"},
+	{"abc/def/../ghi/../jkl", "abc/jkl"},
+	{"abc/def/..", "abc"},
+	{"abc/def/../..", "."},
+	{"/abc/def/../..", "/"},
+	{"abc/def/../../..", ".."},
+	{"/abc/def/../../..", "/"},
+	{"abc/def/../../../ghi/jkl/../../../mno", "../../mno"},
+	{"/../abc", "/abc"},
+
+	// Combinations
+	{"abc/./../def", "def"},
+	{"abc//./../def", "def"},
+	{"abc/../../././../def", "../../def"},
+}
+
+var wincleantests = []PathTest{
+	{`c:`, `c:.`},
+	{`c:\`, `c:\`},
+	{`c:\abc`, `c:\abc`},
+	{`c:abc\..\..\.\.\..\def`, `c:..\..\def`},
+	{`c:\abc\def\..\..`, `c:\`},
+	{`c:\..\abc`, `c:\abc`},
+	{`c:..\abc`, `c:..\abc`},
+	{`\`, `\`},
+	{`/`, `\`},
+	{`\\i\..\c$`, `\c$`},
+	{`\\i\..\i\c$`, `\i\c$`},
+	{`\\i\..\I\c$`, `\I\c$`},
+	{`\\host\share\foo\..\bar`, `\\host\share\bar`},
+	{`//host/share/foo/../baz`, `\\host\share\baz`},
+	{`\\a\b\..\c`, `\\a\b\c`},
+	{`\\a\b`, `\\a\b`},
+}
+
+func TestClean(t *testing.T) {
+	tests := cleantests
+	if runtime.GOOS == "windows" {
+		for i := range tests {
+			tests[i].result = filepath.FromSlash(tests[i].result)
+		}
+		tests = append(tests, wincleantests...)
+	}
+	for _, test := range tests {
+		if s := filepath.Clean(test.path); s != test.result {
+			t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.result)
+		}
+		if s := filepath.Clean(test.result); s != test.result {
+			t.Errorf("Clean(%q) = %q, want %q", test.result, s, test.result)
+		}
+	}
+
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1")
+		return
+	}
+
+	t.Log("Skipping AllocsPerRun for gccgo")
+	return
+
+	for _, test := range tests {
+		allocs := testing.AllocsPerRun(100, func() { filepath.Clean(test.result) })
+		if allocs > 0 {
+			t.Errorf("Clean(%q): %v allocs, want zero", test.result, allocs)
+		}
+	}
+}
+
+const sep = filepath.Separator
+
+var slashtests = []PathTest{
+	{"", ""},
+	{"/", string(sep)},
+	{"/a/b", string([]byte{sep, 'a', sep, 'b'})},
+	{"a//b", string([]byte{'a', sep, sep, 'b'})},
+}
+
+func TestFromAndToSlash(t *testing.T) {
+	for _, test := range slashtests {
+		if s := filepath.FromSlash(test.path); s != test.result {
+			t.Errorf("FromSlash(%q) = %q, want %q", test.path, s, test.result)
+		}
+		if s := filepath.ToSlash(test.result); s != test.path {
+			t.Errorf("ToSlash(%q) = %q, want %q", test.result, s, test.path)
+		}
+	}
+}
+
+type SplitListTest struct {
+	list   string
+	result []string
+}
+
+const lsep = filepath.ListSeparator
+
+var splitlisttests = []SplitListTest{
+	{"", []string{}},
+	{string([]byte{'a', lsep, 'b'}), []string{"a", "b"}},
+	{string([]byte{lsep, 'a', lsep, 'b'}), []string{"", "a", "b"}},
+}
+
+var winsplitlisttests = []SplitListTest{
+	// quoted
+	{`"a"`, []string{`a`}},
+
+	// semicolon
+	{`";"`, []string{`;`}},
+	{`"a;b"`, []string{`a;b`}},
+	{`";";`, []string{`;`, ``}},
+	{`;";"`, []string{``, `;`}},
+
+	// partially quoted
+	{`a";"b`, []string{`a;b`}},
+	{`a; ""b`, []string{`a`, ` b`}},
+	{`"a;b`, []string{`a;b`}},
+	{`""a;b`, []string{`a`, `b`}},
+	{`"""a;b`, []string{`a;b`}},
+	{`""""a;b`, []string{`a`, `b`}},
+	{`a";b`, []string{`a;b`}},
+	{`a;b";c`, []string{`a`, `b;c`}},
+	{`"a";b";c`, []string{`a`, `b;c`}},
+}
+
+func TestSplitList(t *testing.T) {
+	tests := splitlisttests
+	if runtime.GOOS == "windows" {
+		tests = append(tests, winsplitlisttests...)
+	}
+	for _, test := range tests {
+		if l := filepath.SplitList(test.list); !reflect.DeepEqual(l, test.result) {
+			t.Errorf("SplitList(%#q) = %#q, want %#q", test.list, l, test.result)
+		}
+	}
+}
+
+type SplitTest struct {
+	path, dir, file string
+}
+
+var unixsplittests = []SplitTest{
+	{"a/b", "a/", "b"},
+	{"a/b/", "a/b/", ""},
+	{"a/", "a/", ""},
+	{"a", "", "a"},
+	{"/", "/", ""},
+}
+
+var winsplittests = []SplitTest{
+	{`c:`, `c:`, ``},
+	{`c:/`, `c:/`, ``},
+	{`c:/foo`, `c:/`, `foo`},
+	{`c:/foo/bar`, `c:/foo/`, `bar`},
+	{`//host/share`, `//host/share`, ``},
+	{`//host/share/`, `//host/share/`, ``},
+	{`//host/share/foo`, `//host/share/`, `foo`},
+	{`\\host\share`, `\\host\share`, ``},
+	{`\\host\share\`, `\\host\share\`, ``},
+	{`\\host\share\foo`, `\\host\share\`, `foo`},
+}
+
+func TestSplit(t *testing.T) {
+	var splittests []SplitTest
+	splittests = unixsplittests
+	if runtime.GOOS == "windows" {
+		splittests = append(splittests, winsplittests...)
+	}
+	for _, test := range splittests {
+		if d, f := filepath.Split(test.path); d != test.dir || f != test.file {
+			t.Errorf("Split(%q) = %q, %q, want %q, %q", test.path, d, f, test.dir, test.file)
+		}
+	}
+}
+
+type JoinTest struct {
+	elem []string
+	path string
+}
+
+var jointests = []JoinTest{
+	// zero parameters
+	{[]string{}, ""},
+
+	// one parameter
+	{[]string{""}, ""},
+	{[]string{"a"}, "a"},
+
+	// two parameters
+	{[]string{"a", "b"}, "a/b"},
+	{[]string{"a", ""}, "a"},
+	{[]string{"", "b"}, "b"},
+	{[]string{"/", "a"}, "/a"},
+	{[]string{"/", ""}, "/"},
+	{[]string{"a/", "b"}, "a/b"},
+	{[]string{"a/", ""}, "a"},
+	{[]string{"", ""}, ""},
+}
+
+var winjointests = []JoinTest{
+	{[]string{`directory`, `file`}, `directory\file`},
+	{[]string{`C:\Windows\`, `System32`}, `C:\Windows\System32`},
+	{[]string{`C:\Windows\`, ``}, `C:\Windows`},
+	{[]string{`C:\`, `Windows`}, `C:\Windows`},
+	{[]string{`C:`, `Windows`}, `C:\Windows`},
+	{[]string{`\\host\share`, `foo`}, `\\host\share\foo`},
+	{[]string{`//host/share`, `foo/bar`}, `\\host\share\foo\bar`},
+}
+
+// join takes a []string and passes it to Join.
+func join(elem []string, args ...string) string {
+	args = elem
+	return filepath.Join(args...)
+}
+
+func TestJoin(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		jointests = append(jointests, winjointests...)
+	}
+	for _, test := range jointests {
+		if p := join(test.elem); p != filepath.FromSlash(test.path) {
+			t.Errorf("join(%q) = %q, want %q", test.elem, p, test.path)
+		}
+	}
+}
+
+type ExtTest struct {
+	path, ext string
+}
+
+var exttests = []ExtTest{
+	{"path.go", ".go"},
+	{"path.pb.go", ".go"},
+	{"a.dir/b", ""},
+	{"a.dir/b.go", ".go"},
+	{"a.dir/", ""},
+}
+
+func TestExt(t *testing.T) {
+	for _, test := range exttests {
+		if x := filepath.Ext(test.path); x != test.ext {
+			t.Errorf("Ext(%q) = %q, want %q", test.path, x, test.ext)
+		}
+	}
+}
+
+type Node struct {
+	name    string
+	entries []*Node // nil if the entry is a file
+	mark    int
+}
+
+var tree = &Node{
+	"testdata",
+	[]*Node{
+		{"a", nil, 0},
+		{"b", []*Node{}, 0},
+		{"c", nil, 0},
+		{
+			"d",
+			[]*Node{
+				{"x", nil, 0},
+				{"y", []*Node{}, 0},
+				{
+					"z",
+					[]*Node{
+						{"u", nil, 0},
+						{"v", nil, 0},
+					},
+					0,
+				},
+			},
+			0,
+		},
+	},
+	0,
+}
+
+func walkTree(n *Node, path string, f func(path string, n *Node)) {
+	f(path, n)
+	for _, e := range n.entries {
+		walkTree(e, filepath.Join(path, e.name), f)
+	}
+}
+
+func makeTree(t *testing.T) {
+	walkTree(tree, tree.name, func(path string, n *Node) {
+		if n.entries == nil {
+			fd, err := os.Create(path)
+			if err != nil {
+				t.Errorf("makeTree: %v", err)
+				return
+			}
+			fd.Close()
+		} else {
+			os.Mkdir(path, 0770)
+		}
+	})
+}
+
+func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) }
+
+func checkMarks(t *testing.T, report bool) {
+	walkTree(tree, tree.name, func(path string, n *Node) {
+		if n.mark != 1 && report {
+			t.Errorf("node %s mark = %d; expected 1", path, n.mark)
+		}
+		n.mark = 0
+	})
+}
+
+// Assumes that each node name is unique. Good enough for a test.
+// If clear is true, any incoming error is cleared before return. The errors
+// are always accumulated, though.
+func mark(path string, info os.FileInfo, err error, errors *[]error, clear bool) error {
+	if err != nil {
+		*errors = append(*errors, err)
+		if clear {
+			return nil
+		}
+		return err
+	}
+	name := info.Name()
+	walkTree(tree, tree.name, func(path string, n *Node) {
+		if n.name == name {
+			n.mark++
+		}
+	})
+	return nil
+}
+
+func TestWalk(t *testing.T) {
+	makeTree(t)
+	errors := make([]error, 0, 10)
+	clear := true
+	markFn := func(path string, info os.FileInfo, err error) error {
+		return mark(path, info, err, &errors, clear)
+	}
+	// Expect no errors.
+	err := filepath.Walk(tree.name, markFn)
+	if err != nil {
+		t.Fatalf("no error expected, found: %s", err)
+	}
+	if len(errors) != 0 {
+		t.Fatalf("unexpected errors: %s", errors)
+	}
+	checkMarks(t, true)
+	errors = errors[0:0]
+
+	// Test permission errors.  Only possible if we're not root
+	// and only on some file systems (AFS, FAT).  To avoid errors during
+	// all.bash on those file systems, skip during go test -short.
+	if os.Getuid() > 0 && !testing.Short() {
+		// introduce 2 errors: chmod top-level directories to 0
+		os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0)
+		os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0)
+
+		// 3) capture errors, expect two.
+		// mark respective subtrees manually
+		markTree(tree.entries[1])
+		markTree(tree.entries[3])
+		// correct double-marking of directory itself
+		tree.entries[1].mark--
+		tree.entries[3].mark--
+		err := filepath.Walk(tree.name, markFn)
+		if err != nil {
+			t.Fatalf("expected no error return from Walk, got %s", err)
+		}
+		if len(errors) != 2 {
+			t.Errorf("expected 2 errors, got %d: %s", len(errors), errors)
+		}
+		// the inaccessible subtrees were marked manually
+		checkMarks(t, true)
+		errors = errors[0:0]
+
+		// 4) capture errors, stop after first error.
+		// mark respective subtrees manually
+		markTree(tree.entries[1])
+		markTree(tree.entries[3])
+		// correct double-marking of directory itself
+		tree.entries[1].mark--
+		tree.entries[3].mark--
+		clear = false // error will stop processing
+		err = filepath.Walk(tree.name, markFn)
+		if err == nil {
+			t.Fatalf("expected error return from Walk")
+		}
+		if len(errors) != 1 {
+			t.Errorf("expected 1 error, got %d: %s", len(errors), errors)
+		}
+		// the inaccessible subtrees were marked manually
+		checkMarks(t, false)
+		errors = errors[0:0]
+
+		// restore permissions
+		os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770)
+		os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770)
+	}
+
+	// cleanup
+	if err := os.RemoveAll(tree.name); err != nil {
+		t.Errorf("removeTree: %v", err)
+	}
+}
+
+func touch(t *testing.T, name string) {
+	f, err := os.Create(name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := f.Close(); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestWalkFileError(t *testing.T) {
+	td, err := ioutil.TempDir("", "walktest")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(td)
+
+	touch(t, filepath.Join(td, "foo"))
+	touch(t, filepath.Join(td, "bar"))
+	dir := filepath.Join(td, "dir")
+	if err := os.MkdirAll(filepath.Join(td, "dir"), 0755); err != nil {
+		t.Fatal(err)
+	}
+	touch(t, filepath.Join(dir, "baz"))
+	touch(t, filepath.Join(dir, "stat-error"))
+	defer func() {
+		*filepath.LstatP = os.Lstat
+	}()
+	statErr := errors.New("some stat error")
+	*filepath.LstatP = func(path string) (os.FileInfo, error) {
+		if strings.HasSuffix(path, "stat-error") {
+			return nil, statErr
+		}
+		return os.Lstat(path)
+	}
+	got := map[string]error{}
+	err = filepath.Walk(td, func(path string, fi os.FileInfo, err error) error {
+		rel, _ := filepath.Rel(td, path)
+		got[filepath.ToSlash(rel)] = err
+		return nil
+	})
+	if err != nil {
+		t.Errorf("Walk error: %v", err)
+	}
+	want := map[string]error{
+		".":              nil,
+		"foo":            nil,
+		"bar":            nil,
+		"dir":            nil,
+		"dir/baz":        nil,
+		"dir/stat-error": statErr,
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Walked %#v; want %#v", got, want)
+	}
+}
+
+var basetests = []PathTest{
+	{"", "."},
+	{".", "."},
+	{"/.", "."},
+	{"/", "/"},
+	{"////", "/"},
+	{"x/", "x"},
+	{"abc", "abc"},
+	{"abc/def", "def"},
+	{"a/b/.x", ".x"},
+	{"a/b/c.", "c."},
+	{"a/b/c.x", "c.x"},
+}
+
+var winbasetests = []PathTest{
+	{`c:\`, `\`},
+	{`c:.`, `.`},
+	{`c:\a\b`, `b`},
+	{`c:a\b`, `b`},
+	{`c:a\b\c`, `c`},
+	{`\\host\share\`, `\`},
+	{`\\host\share\a`, `a`},
+	{`\\host\share\a\b`, `b`},
+}
+
+func TestBase(t *testing.T) {
+	tests := basetests
+	if runtime.GOOS == "windows" {
+		// make unix tests work on windows
+		for i := range tests {
+			tests[i].result = filepath.Clean(tests[i].result)
+		}
+		// add windows specific tests
+		tests = append(tests, winbasetests...)
+	}
+	for _, test := range tests {
+		if s := filepath.Base(test.path); s != test.result {
+			t.Errorf("Base(%q) = %q, want %q", test.path, s, test.result)
+		}
+	}
+}
+
+var dirtests = []PathTest{
+	{"", "."},
+	{".", "."},
+	{"/.", "/"},
+	{"/", "/"},
+	{"////", "/"},
+	{"/foo", "/"},
+	{"x/", "x"},
+	{"abc", "."},
+	{"abc/def", "abc"},
+	{"a/b/.x", "a/b"},
+	{"a/b/c.", "a/b"},
+	{"a/b/c.x", "a/b"},
+}
+
+var windirtests = []PathTest{
+	{`c:\`, `c:\`},
+	{`c:.`, `c:.`},
+	{`c:\a\b`, `c:\a`},
+	{`c:a\b`, `c:a`},
+	{`c:a\b\c`, `c:a\b`},
+	{`\\host\share\`, `\\host\share\`},
+	{`\\host\share\a`, `\\host\share\`},
+	{`\\host\share\a\b`, `\\host\share\a`},
+}
+
+func TestDir(t *testing.T) {
+	tests := dirtests
+	if runtime.GOOS == "windows" {
+		// make unix tests work on windows
+		for i := range tests {
+			tests[i].result = filepath.Clean(tests[i].result)
+		}
+		// add windows specific tests
+		tests = append(tests, windirtests...)
+	}
+	for _, test := range tests {
+		if s := filepath.Dir(test.path); s != test.result {
+			t.Errorf("Dir(%q) = %q, want %q", test.path, s, test.result)
+		}
+	}
+}
+
+type IsAbsTest struct {
+	path  string
+	isAbs bool
+}
+
+var isabstests = []IsAbsTest{
+	{"", false},
+	{"/", true},
+	{"/usr/bin/gcc", true},
+	{"..", false},
+	{"/a/../bb", true},
+	{".", false},
+	{"./", false},
+	{"lala", false},
+}
+
+var winisabstests = []IsAbsTest{
+	{`C:\`, true},
+	{`c\`, false},
+	{`c::`, false},
+	{`c:`, false},
+	{`/`, false},
+	{`\`, false},
+	{`\Windows`, false},
+	{`c:a\b`, false},
+	{`\\host\share\foo`, true},
+	{`//host/share/foo/bar`, true},
+}
+
+func TestIsAbs(t *testing.T) {
+	var tests []IsAbsTest
+	if runtime.GOOS == "windows" {
+		tests = append(tests, winisabstests...)
+		// All non-windows tests should fail, because they have no volume letter.
+		for _, test := range isabstests {
+			tests = append(tests, IsAbsTest{test.path, false})
+		}
+		// All non-windows test should work as intended if prefixed with volume letter.
+		for _, test := range isabstests {
+			tests = append(tests, IsAbsTest{"c:" + test.path, test.isAbs})
+		}
+	} else {
+		tests = isabstests
+	}
+
+	for _, test := range tests {
+		if r := filepath.IsAbs(test.path); r != test.isAbs {
+			t.Errorf("IsAbs(%q) = %v, want %v", test.path, r, test.isAbs)
+		}
+	}
+}
+
+type EvalSymlinksTest struct {
+	// If dest is empty, the path is created; otherwise the dest is symlinked to the path.
+	path, dest string
+}
+
+var EvalSymlinksTestDirs = []EvalSymlinksTest{
+	{"test", ""},
+	{"test/dir", ""},
+	{"test/dir/link3", "../../"},
+	{"test/link1", "../test"},
+	{"test/link2", "dir"},
+	{"test/linkabs", "/"},
+}
+
+var EvalSymlinksTests = []EvalSymlinksTest{
+	{"test", "test"},
+	{"test/dir", "test/dir"},
+	{"test/dir/../..", "."},
+	{"test/link1", "test"},
+	{"test/link2", "test/dir"},
+	{"test/link1/dir", "test/dir"},
+	{"test/link2/..", "test"},
+	{"test/dir/link3", "."},
+	{"test/link2/link3/test", "test"},
+	{"test/linkabs", "/"},
+}
+
+var EvalSymlinksAbsWindowsTests = []EvalSymlinksTest{
+	{`c:\`, `c:\`},
+}
+
+// simpleJoin builds a file name from the directory and path.
+// It does not use Join because we don't want ".." to be evaluated.
+func simpleJoin(dir, path string) string {
+	return dir + string(filepath.Separator) + path
+}
+
+func TestEvalSymlinks(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9":
+		t.Skipf("skipping on %s", runtime.GOOS)
+	}
+
+	tmpDir, err := ioutil.TempDir("", "evalsymlink")
+	if err != nil {
+		t.Fatal("creating temp dir:", err)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	// /tmp may itself be a symlink! Avoid the confusion, although
+	// it means trusting the thing we're testing.
+	tmpDir, err = filepath.EvalSymlinks(tmpDir)
+	if err != nil {
+		t.Fatal("eval symlink for tmp dir:", err)
+	}
+
+	// Create the symlink farm using relative paths.
+	for _, d := range EvalSymlinksTestDirs {
+		var err error
+		path := simpleJoin(tmpDir, d.path)
+		if d.dest == "" {
+			err = os.Mkdir(path, 0755)
+		} else {
+			if runtime.GOOS != "windows" {
+				err = os.Symlink(d.dest, path)
+			}
+		}
+		if err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	var tests []EvalSymlinksTest
+	if runtime.GOOS == "windows" {
+		for _, d := range EvalSymlinksTests {
+			if d.path == d.dest {
+				// will test only real files and directories
+				tests = append(tests, d)
+				// test "canonical" names
+				d2 := EvalSymlinksTest{
+					path: strings.ToUpper(d.path),
+					dest: d.dest,
+				}
+				tests = append(tests, d2)
+			}
+		}
+	} else {
+		tests = EvalSymlinksTests
+	}
+
+	// Evaluate the symlink farm.
+	for _, d := range tests {
+		path := simpleJoin(tmpDir, d.path)
+		dest := simpleJoin(tmpDir, d.dest)
+		if filepath.IsAbs(d.dest) {
+			dest = d.dest
+		}
+		if p, err := filepath.EvalSymlinks(path); err != nil {
+			t.Errorf("EvalSymlinks(%q) error: %v", d.path, err)
+		} else if filepath.Clean(p) != filepath.Clean(dest) {
+			t.Errorf("Clean(%q)=%q, want %q", path, p, dest)
+		}
+	}
+}
+
+// Test directories relative to temporary directory.
+// The tests are run in absTestDirs[0].
+var absTestDirs = []string{
+	"a",
+	"a/b",
+	"a/b/c",
+}
+
+// Test paths relative to temporary directory. $ expands to the directory.
+// The tests are run in absTestDirs[0].
+// We create absTestDirs first.
+var absTests = []string{
+	".",
+	"b",
+	"../a",
+	"../a/b",
+	"../a/b/./c/../../.././a",
+	"$",
+	"$/.",
+	"$/a/../a/b",
+	"$/a/b/c/../../.././a",
+}
+
+func TestAbs(t *testing.T) {
+	oldwd, err := os.Getwd()
+	if err != nil {
+		t.Fatal("Getwd failed: ", err)
+	}
+	defer os.Chdir(oldwd)
+
+	root, err := ioutil.TempDir("", "TestAbs")
+	if err != nil {
+		t.Fatal("TempDir failed: ", err)
+	}
+	defer os.RemoveAll(root)
+
+	wd, err := os.Getwd()
+	if err != nil {
+		t.Fatal("getwd failed: ", err)
+	}
+	err = os.Chdir(root)
+	if err != nil {
+		t.Fatal("chdir failed: ", err)
+	}
+	defer os.Chdir(wd)
+
+	for _, dir := range absTestDirs {
+		err = os.Mkdir(dir, 0777)
+		if err != nil {
+			t.Fatal("Mkdir failed: ", err)
+		}
+	}
+
+	err = os.Chdir(absTestDirs[0])
+	if err != nil {
+		t.Fatal("chdir failed: ", err)
+	}
+
+	for _, path := range absTests {
+		path = strings.Replace(path, "$", root, -1)
+		info, err := os.Stat(path)
+		if err != nil {
+			t.Errorf("%s: %s", path, err)
+			continue
+		}
+
+		abspath, err := filepath.Abs(path)
+		if err != nil {
+			t.Errorf("Abs(%q) error: %v", path, err)
+			continue
+		}
+		absinfo, err := os.Stat(abspath)
+		if err != nil || !os.SameFile(absinfo, info) {
+			t.Errorf("Abs(%q)=%q, not the same file", path, abspath)
+		}
+		if !filepath.IsAbs(abspath) {
+			t.Errorf("Abs(%q)=%q, not an absolute path", path, abspath)
+		}
+		if filepath.IsAbs(path) && abspath != filepath.Clean(path) {
+			t.Errorf("Abs(%q)=%q, isn't clean", path, abspath)
+		}
+	}
+}
+
+type RelTests struct {
+	root, path, want string
+}
+
+var reltests = []RelTests{
+	{"a/b", "a/b", "."},
+	{"a/b/.", "a/b", "."},
+	{"a/b", "a/b/.", "."},
+	{"./a/b", "a/b", "."},
+	{"a/b", "./a/b", "."},
+	{"ab/cd", "ab/cde", "../cde"},
+	{"ab/cd", "ab/c", "../c"},
+	{"a/b", "a/b/c/d", "c/d"},
+	{"a/b", "a/b/../c", "../c"},
+	{"a/b/../c", "a/b", "../b"},
+	{"a/b/c", "a/c/d", "../../c/d"},
+	{"a/b", "c/d", "../../c/d"},
+	{"a/b/c/d", "a/b", "../.."},
+	{"a/b/c/d", "a/b/", "../.."},
+	{"a/b/c/d/", "a/b", "../.."},
+	{"a/b/c/d/", "a/b/", "../.."},
+	{"../../a/b", "../../a/b/c/d", "c/d"},
+	{"/a/b", "/a/b", "."},
+	{"/a/b/.", "/a/b", "."},
+	{"/a/b", "/a/b/.", "."},
+	{"/ab/cd", "/ab/cde", "../cde"},
+	{"/ab/cd", "/ab/c", "../c"},
+	{"/a/b", "/a/b/c/d", "c/d"},
+	{"/a/b", "/a/b/../c", "../c"},
+	{"/a/b/../c", "/a/b", "../b"},
+	{"/a/b/c", "/a/c/d", "../../c/d"},
+	{"/a/b", "/c/d", "../../c/d"},
+	{"/a/b/c/d", "/a/b", "../.."},
+	{"/a/b/c/d", "/a/b/", "../.."},
+	{"/a/b/c/d/", "/a/b", "../.."},
+	{"/a/b/c/d/", "/a/b/", "../.."},
+	{"/../../a/b", "/../../a/b/c/d", "c/d"},
+	{".", "a/b", "a/b"},
+	{".", "..", ".."},
+
+	// can't do purely lexically
+	{"..", ".", "err"},
+	{"..", "a", "err"},
+	{"../..", "..", "err"},
+	{"a", "/a", "err"},
+	{"/a", "a", "err"},
+}
+
+var winreltests = []RelTests{
+	{`C:a\b\c`, `C:a/b/d`, `..\d`},
+	{`C:\`, `D:\`, `err`},
+	{`C:`, `D:`, `err`},
+}
+
+func TestRel(t *testing.T) {
+	tests := append([]RelTests{}, reltests...)
+	if runtime.GOOS == "windows" {
+		for i := range tests {
+			tests[i].want = filepath.FromSlash(tests[i].want)
+		}
+		tests = append(tests, winreltests...)
+	}
+	for _, test := range tests {
+		got, err := filepath.Rel(test.root, test.path)
+		if test.want == "err" {
+			if err == nil {
+				t.Errorf("Rel(%q, %q)=%q, want error", test.root, test.path, got)
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("Rel(%q, %q): want %q, got error: %s", test.root, test.path, test.want, err)
+		}
+		if got != test.want {
+			t.Errorf("Rel(%q, %q)=%q, want %q", test.root, test.path, got, test.want)
+		}
+	}
+}
+
+type VolumeNameTest struct {
+	path string
+	vol  string
+}
+
+var volumenametests = []VolumeNameTest{
+	{`c:/foo/bar`, `c:`},
+	{`c:`, `c:`},
+	{`2:`, ``},
+	{``, ``},
+	{`\\\host`, ``},
+	{`\\\host\`, ``},
+	{`\\\host\share`, ``},
+	{`\\\host\\share`, ``},
+	{`\\host`, ``},
+	{`//host`, ``},
+	{`\\host\`, ``},
+	{`//host/`, ``},
+	{`\\host\share`, `\\host\share`},
+	{`//host/share`, `//host/share`},
+	{`\\host\share\`, `\\host\share`},
+	{`//host/share/`, `//host/share`},
+	{`\\host\share\foo`, `\\host\share`},
+	{`//host/share/foo`, `//host/share`},
+	{`\\host\share\\foo\\\bar\\\\baz`, `\\host\share`},
+	{`//host/share//foo///bar////baz`, `//host/share`},
+	{`\\host\share\foo\..\bar`, `\\host\share`},
+	{`//host/share/foo/../bar`, `//host/share`},
+}
+
+func TestVolumeName(t *testing.T) {
+	if runtime.GOOS != "windows" {
+		return
+	}
+	for _, v := range volumenametests {
+		if vol := filepath.VolumeName(v.path); vol != v.vol {
+			t.Errorf("VolumeName(%q)=%q, want %q", v.path, vol, v.vol)
+		}
+	}
+}
+
+func TestDriveLetterInEvalSymlinks(t *testing.T) {
+	if runtime.GOOS != "windows" {
+		return
+	}
+	wd, _ := os.Getwd()
+	if len(wd) < 3 {
+		t.Errorf("Current directory path %q is too short", wd)
+	}
+	lp := strings.ToLower(wd)
+	up := strings.ToUpper(wd)
+	flp, err := filepath.EvalSymlinks(lp)
+	if err != nil {
+		t.Fatalf("EvalSymlinks(%q) failed: %q", lp, err)
+	}
+	fup, err := filepath.EvalSymlinks(up)
+	if err != nil {
+		t.Fatalf("EvalSymlinks(%q) failed: %q", up, err)
+	}
+	if flp != fup {
+		t.Errorf("Results of EvalSymlinks do not match: %q and %q", flp, fup)
+	}
+}
+
+/* This test does not work gccgo, since the sources are arranged
+   differently.
+
+func TestBug3486(t *testing.T) { // http://code.google.com/p/go/issues/detail?id=3486
+	root, err := filepath.EvalSymlinks(runtime.GOROOT() + "/test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	bugs := filepath.Join(root, "bugs")
+	ken := filepath.Join(root, "ken")
+	seenBugs := false
+	seenKen := false
+	filepath.Walk(root, func(pth string, info os.FileInfo, err error) error {
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		switch pth {
+		case bugs:
+			seenBugs = true
+			return filepath.SkipDir
+		case ken:
+			if !seenBugs {
+				t.Fatal("filepath.Walk out of order - ken before bugs")
+			}
+			seenKen = true
+		}
+		return nil
+	})
+	if !seenKen {
+		t.Fatalf("%q not seen", ken)
+	}
+}
+
+*/
diff --git a/third_party/gofrontend/libgo/go/path/filepath/path_unix.go b/third_party/gofrontend/libgo/go/path/filepath/path_unix.go
new file mode 100644
index 0000000..7aba0ab
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/path_unix.go
@@ -0,0 +1,32 @@
+// Copyright 2010 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package filepath
+
+import "strings"
+
+// IsAbs returns true if the path is absolute.
+func IsAbs(path string) bool {
+	return strings.HasPrefix(path, "/")
+}
+
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
+	return 0
+}
+
+// HasPrefix exists for historical compatibility and should not be used.
+func HasPrefix(p, prefix string) bool {
+	return strings.HasPrefix(p, prefix)
+}
+
+func splitList(path string) []string {
+	if path == "" {
+		return []string{}
+	}
+	return strings.Split(path, string(ListSeparator))
+}
diff --git a/third_party/gofrontend/libgo/go/path/filepath/path_windows.go b/third_party/gofrontend/libgo/go/path/filepath/path_windows.go
new file mode 100644
index 0000000..e999972
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/path_windows.go
@@ -0,0 +1,105 @@
+// Copyright 2010 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 filepath
+
+import (
+	"strings"
+)
+
+func isSlash(c uint8) bool {
+	return c == '\\' || c == '/'
+}
+
+// IsAbs returns true if the path is absolute.
+func IsAbs(path string) (b bool) {
+	l := volumeNameLen(path)
+	if l == 0 {
+		return false
+	}
+	path = path[l:]
+	if path == "" {
+		return false
+	}
+	return isSlash(path[0])
+}
+
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
+	if len(path) < 2 {
+		return 0
+	}
+	// with drive letter
+	c := path[0]
+	if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
+		return 2
+	}
+	// is it UNC
+	if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&
+		!isSlash(path[2]) && path[2] != '.' {
+		// first, leading `\\` and next shouldn't be `\`. its server name.
+		for n := 3; n < l-1; n++ {
+			// second, next '\' shouldn't be repeated.
+			if isSlash(path[n]) {
+				n++
+				// third, following something characters. its share name.
+				if !isSlash(path[n]) {
+					if path[n] == '.' {
+						break
+					}
+					for ; n < l; n++ {
+						if isSlash(path[n]) {
+							break
+						}
+					}
+					return n
+				}
+				break
+			}
+		}
+	}
+	return 0
+}
+
+// HasPrefix exists for historical compatibility and should not be used.
+func HasPrefix(p, prefix string) bool {
+	if strings.HasPrefix(p, prefix) {
+		return true
+	}
+	return strings.HasPrefix(strings.ToLower(p), strings.ToLower(prefix))
+}
+
+func splitList(path string) []string {
+	// The same implementation is used in LookPath in os/exec;
+	// consider changing os/exec when changing this.
+
+	if path == "" {
+		return []string{}
+	}
+
+	// Split path, respecting but preserving quotes.
+	list := []string{}
+	start := 0
+	quo := false
+	for i := 0; i < len(path); i++ {
+		switch c := path[i]; {
+		case c == '"':
+			quo = !quo
+		case c == ListSeparator && !quo:
+			list = append(list, path[start:i])
+			start = i + 1
+		}
+	}
+	list = append(list, path[start:])
+
+	// Remove quotes.
+	for i, s := range list {
+		if strings.Contains(s, `"`) {
+			list[i] = strings.Replace(s, `"`, ``, -1)
+		}
+	}
+
+	return list
+}
diff --git a/third_party/gofrontend/libgo/go/path/filepath/symlink.go b/third_party/gofrontend/libgo/go/path/filepath/symlink.go
new file mode 100644
index 0000000..307dd0f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/symlink.go
@@ -0,0 +1,67 @@
+// 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.
+
+// +build !windows
+
+package filepath
+
+import (
+	"bytes"
+	"errors"
+	"os"
+	"strings"
+)
+
+func evalSymlinks(path string) (string, error) {
+	const maxIter = 255
+	originalPath := path
+	// consume path by taking each frontmost path element,
+	// expanding it if it's a symlink, and appending it to b
+	var b bytes.Buffer
+	for n := 0; path != ""; n++ {
+		if n > maxIter {
+			return "", errors.New("EvalSymlinks: too many links in " + originalPath)
+		}
+
+		// find next path component, p
+		i := strings.IndexRune(path, Separator)
+		var p string
+		if i == -1 {
+			p, path = path, ""
+		} else {
+			p, path = path[:i], path[i+1:]
+		}
+
+		if p == "" {
+			if b.Len() == 0 {
+				// must be absolute path
+				b.WriteRune(Separator)
+			}
+			continue
+		}
+
+		fi, err := os.Lstat(b.String() + p)
+		if err != nil {
+			return "", err
+		}
+		if fi.Mode()&os.ModeSymlink == 0 {
+			b.WriteString(p)
+			if path != "" {
+				b.WriteRune(Separator)
+			}
+			continue
+		}
+
+		// it's a symlink, put it at the front of path
+		dest, err := os.Readlink(b.String() + p)
+		if err != nil {
+			return "", err
+		}
+		if IsAbs(dest) {
+			b.Reset()
+		}
+		path = dest + string(Separator) + path
+	}
+	return Clean(b.String()), nil
+}
diff --git a/third_party/gofrontend/libgo/go/path/filepath/symlink_windows.go b/third_party/gofrontend/libgo/go/path/filepath/symlink_windows.go
new file mode 100644
index 0000000..9adc8a4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/filepath/symlink_windows.go
@@ -0,0 +1,69 @@
+// 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 filepath
+
+import (
+	"syscall"
+)
+
+func toShort(path string) (string, error) {
+	p, err := syscall.UTF16FromString(path)
+	if err != nil {
+		return "", err
+	}
+	b := p // GetShortPathName says we can reuse buffer
+	n, err := syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
+	if err != nil {
+		return "", err
+	}
+	if n > uint32(len(b)) {
+		b = make([]uint16, n)
+		n, err = syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
+		if err != nil {
+			return "", err
+		}
+	}
+	return syscall.UTF16ToString(b), nil
+}
+
+func toLong(path string) (string, error) {
+	p, err := syscall.UTF16FromString(path)
+	if err != nil {
+		return "", err
+	}
+	b := p // GetLongPathName says we can reuse buffer
+	n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b)))
+	if err != nil {
+		return "", err
+	}
+	if n > uint32(len(b)) {
+		b = make([]uint16, n)
+		n, err = syscall.GetLongPathName(&p[0], &b[0], uint32(len(b)))
+		if err != nil {
+			return "", err
+		}
+	}
+	b = b[:n]
+	return syscall.UTF16ToString(b), nil
+}
+
+func evalSymlinks(path string) (string, error) {
+	p, err := toShort(path)
+	if err != nil {
+		return "", err
+	}
+	p, err = toLong(p)
+	if err != nil {
+		return "", err
+	}
+	// syscall.GetLongPathName does not change the case of the drive letter,
+	// but the result of EvalSymlinks must be unique, so we have
+	// EvalSymlinks(`c:\a`) == EvalSymlinks(`C:\a`).
+	// Make drive letter upper case.
+	if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' {
+		p = string(p[0]+'A'-'a') + p[1:]
+	}
+	return Clean(p), nil
+}
diff --git a/third_party/gofrontend/libgo/go/path/match.go b/third_party/gofrontend/libgo/go/path/match.go
new file mode 100644
index 0000000..8154bf6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/match.go
@@ -0,0 +1,209 @@
+// Copyright 2010 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 path
+
+import (
+	"errors"
+	"strings"
+	"unicode/utf8"
+)
+
+// ErrBadPattern indicates a globbing pattern was malformed.
+var ErrBadPattern = errors.New("syntax error in pattern")
+
+// Match returns true if name matches the shell file name pattern.
+// The pattern syntax is:
+//
+//	pattern:
+//		{ term }
+//	term:
+//		'*'         matches any sequence of non-/ characters
+//		'?'         matches any single non-/ character
+//		'[' [ '^' ] { character-range } ']'
+//		            character class (must be non-empty)
+//		c           matches character c (c != '*', '?', '\\', '[')
+//		'\\' c      matches character c
+//
+//	character-range:
+//		c           matches character c (c != '\\', '-', ']')
+//		'\\' c      matches character c
+//		lo '-' hi   matches character c for lo <= c <= hi
+//
+// Match requires pattern to match all of name, not just a substring.
+// The only possible returned error is ErrBadPattern, when pattern
+// is malformed.
+//
+func Match(pattern, name string) (matched bool, err error) {
+Pattern:
+	for len(pattern) > 0 {
+		var star bool
+		var chunk string
+		star, chunk, pattern = scanChunk(pattern)
+		if star && chunk == "" {
+			// Trailing * matches rest of string unless it has a /.
+			return strings.Index(name, "/") < 0, nil
+		}
+		// Look for match at current position.
+		t, ok, err := matchChunk(chunk, name)
+		// if we're the last chunk, make sure we've exhausted the name
+		// otherwise we'll give a false result even if we could still match
+		// using the star
+		if ok && (len(t) == 0 || len(pattern) > 0) {
+			name = t
+			continue
+		}
+		if err != nil {
+			return false, err
+		}
+		if star {
+			// Look for match skipping i+1 bytes.
+			// Cannot skip /.
+			for i := 0; i < len(name) && name[i] != '/'; i++ {
+				t, ok, err := matchChunk(chunk, name[i+1:])
+				if ok {
+					// if we're the last chunk, make sure we exhausted the name
+					if len(pattern) == 0 && len(t) > 0 {
+						continue
+					}
+					name = t
+					continue Pattern
+				}
+				if err != nil {
+					return false, err
+				}
+			}
+		}
+		return false, nil
+	}
+	return len(name) == 0, nil
+}
+
+// scanChunk gets the next segment of pattern, which is a non-star string
+// possibly preceded by a star.
+func scanChunk(pattern string) (star bool, chunk, rest string) {
+	for len(pattern) > 0 && pattern[0] == '*' {
+		pattern = pattern[1:]
+		star = true
+	}
+	inrange := false
+	var i int
+Scan:
+	for i = 0; i < len(pattern); i++ {
+		switch pattern[i] {
+		case '\\':
+			// error check handled in matchChunk: bad pattern.
+			if i+1 < len(pattern) {
+				i++
+			}
+		case '[':
+			inrange = true
+		case ']':
+			inrange = false
+		case '*':
+			if !inrange {
+				break Scan
+			}
+		}
+	}
+	return star, pattern[0:i], pattern[i:]
+}
+
+// matchChunk checks whether chunk matches the beginning of s.
+// If so, it returns the remainder of s (after the match).
+// Chunk is all single-character operators: literals, char classes, and ?.
+func matchChunk(chunk, s string) (rest string, ok bool, err error) {
+	for len(chunk) > 0 {
+		if len(s) == 0 {
+			return
+		}
+		switch chunk[0] {
+		case '[':
+			// character class
+			r, n := utf8.DecodeRuneInString(s)
+			s = s[n:]
+			chunk = chunk[1:]
+			// possibly negated
+			notNegated := true
+			if len(chunk) > 0 && chunk[0] == '^' {
+				notNegated = false
+				chunk = chunk[1:]
+			}
+			// parse all ranges
+			match := false
+			nrange := 0
+			for {
+				if len(chunk) > 0 && chunk[0] == ']' && nrange > 0 {
+					chunk = chunk[1:]
+					break
+				}
+				var lo, hi rune
+				if lo, chunk, err = getEsc(chunk); err != nil {
+					return
+				}
+				hi = lo
+				if chunk[0] == '-' {
+					if hi, chunk, err = getEsc(chunk[1:]); err != nil {
+						return
+					}
+				}
+				if lo <= r && r <= hi {
+					match = true
+				}
+				nrange++
+			}
+			if match != notNegated {
+				return
+			}
+
+		case '?':
+			if s[0] == '/' {
+				return
+			}
+			_, n := utf8.DecodeRuneInString(s)
+			s = s[n:]
+			chunk = chunk[1:]
+
+		case '\\':
+			chunk = chunk[1:]
+			if len(chunk) == 0 {
+				err = ErrBadPattern
+				return
+			}
+			fallthrough
+
+		default:
+			if chunk[0] != s[0] {
+				return
+			}
+			s = s[1:]
+			chunk = chunk[1:]
+		}
+	}
+	return s, true, nil
+}
+
+// getEsc gets a possibly-escaped character from chunk, for a character class.
+func getEsc(chunk string) (r rune, nchunk string, err error) {
+	if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' {
+		err = ErrBadPattern
+		return
+	}
+	if chunk[0] == '\\' {
+		chunk = chunk[1:]
+		if len(chunk) == 0 {
+			err = ErrBadPattern
+			return
+		}
+	}
+	r, n := utf8.DecodeRuneInString(chunk)
+	if r == utf8.RuneError && n == 1 {
+		err = ErrBadPattern
+	}
+	nchunk = chunk[n:]
+	if len(nchunk) == 0 {
+		err = ErrBadPattern
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/path/match_test.go b/third_party/gofrontend/libgo/go/path/match_test.go
new file mode 100644
index 0000000..6b0676f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/match_test.go
@@ -0,0 +1,79 @@
+// 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 path
+
+import "testing"
+
+type MatchTest struct {
+	pattern, s string
+	match      bool
+	err        error
+}
+
+var matchTests = []MatchTest{
+	{"abc", "abc", true, nil},
+	{"*", "abc", true, nil},
+	{"*c", "abc", true, nil},
+	{"a*", "a", true, nil},
+	{"a*", "abc", true, nil},
+	{"a*", "ab/c", false, nil},
+	{"a*/b", "abc/b", true, nil},
+	{"a*/b", "a/c/b", false, nil},
+	{"a*b*c*d*e*/f", "axbxcxdxe/f", true, nil},
+	{"a*b*c*d*e*/f", "axbxcxdxexxx/f", true, nil},
+	{"a*b*c*d*e*/f", "axbxcxdxe/xxx/f", false, nil},
+	{"a*b*c*d*e*/f", "axbxcxdxexxx/fff", false, nil},
+	{"a*b?c*x", "abxbbxdbxebxczzx", true, nil},
+	{"a*b?c*x", "abxbbxdbxebxczzy", false, nil},
+	{"ab[c]", "abc", true, nil},
+	{"ab[b-d]", "abc", true, nil},
+	{"ab[e-g]", "abc", false, nil},
+	{"ab[^c]", "abc", false, nil},
+	{"ab[^b-d]", "abc", false, nil},
+	{"ab[^e-g]", "abc", true, nil},
+	{"a\\*b", "a*b", true, nil},
+	{"a\\*b", "ab", false, nil},
+	{"a?b", "a☺b", true, nil},
+	{"a[^a]b", "a☺b", true, nil},
+	{"a???b", "a☺b", false, nil},
+	{"a[^a][^a][^a]b", "a☺b", false, nil},
+	{"[a-ζ]*", "α", true, nil},
+	{"*[a-ζ]", "A", false, nil},
+	{"a?b", "a/b", false, nil},
+	{"a*b", "a/b", false, nil},
+	{"[\\]a]", "]", true, nil},
+	{"[\\-]", "-", true, nil},
+	{"[x\\-]", "x", true, nil},
+	{"[x\\-]", "-", true, nil},
+	{"[x\\-]", "z", false, nil},
+	{"[\\-x]", "x", true, nil},
+	{"[\\-x]", "-", true, nil},
+	{"[\\-x]", "a", false, nil},
+	{"[]a]", "]", false, ErrBadPattern},
+	{"[-]", "-", false, ErrBadPattern},
+	{"[x-]", "x", false, ErrBadPattern},
+	{"[x-]", "-", false, ErrBadPattern},
+	{"[x-]", "z", false, ErrBadPattern},
+	{"[-x]", "x", false, ErrBadPattern},
+	{"[-x]", "-", false, ErrBadPattern},
+	{"[-x]", "a", false, ErrBadPattern},
+	{"\\", "a", false, ErrBadPattern},
+	{"[a-b-c]", "a", false, ErrBadPattern},
+	{"[", "a", false, ErrBadPattern},
+	{"[^", "a", false, ErrBadPattern},
+	{"[^bc", "a", false, ErrBadPattern},
+	{"a[", "a", false, nil},
+	{"a[", "ab", false, ErrBadPattern},
+	{"*x", "xxx", true, nil},
+}
+
+func TestMatch(t *testing.T) {
+	for _, tt := range matchTests {
+		ok, err := Match(tt.pattern, tt.s)
+		if ok != tt.match || err != tt.err {
+			t.Errorf("Match(%#q, %#q) = %v, %v want %v, nil", tt.pattern, tt.s, ok, err, tt.match)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/path/path.go b/third_party/gofrontend/libgo/go/path/path.go
new file mode 100644
index 0000000..bdb85c6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/path.go
@@ -0,0 +1,218 @@
+// 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 path implements utility routines for manipulating slash-separated
+// paths.
+package path
+
+import (
+	"strings"
+)
+
+// A lazybuf is a lazily constructed path buffer.
+// It supports append, reading previously appended bytes,
+// and retrieving the final string. It does not allocate a buffer
+// to hold the output until that output diverges from s.
+type lazybuf struct {
+	s   string
+	buf []byte
+	w   int
+}
+
+func (b *lazybuf) index(i int) byte {
+	if b.buf != nil {
+		return b.buf[i]
+	}
+	return b.s[i]
+}
+
+func (b *lazybuf) append(c byte) {
+	if b.buf == nil {
+		if b.w < len(b.s) && b.s[b.w] == c {
+			b.w++
+			return
+		}
+		b.buf = make([]byte, len(b.s))
+		copy(b.buf, b.s[:b.w])
+	}
+	b.buf[b.w] = c
+	b.w++
+}
+
+func (b *lazybuf) string() string {
+	if b.buf == nil {
+		return b.s[:b.w]
+	}
+	return string(b.buf[:b.w])
+}
+
+// Clean returns the shortest path name equivalent to path
+// by purely lexical processing.  It applies the following rules
+// iteratively until no further processing can be done:
+//
+//	1. Replace multiple slashes with a single slash.
+//	2. Eliminate each . path name element (the current directory).
+//	3. Eliminate each inner .. path name element (the parent directory)
+//	   along with the non-.. element that precedes it.
+//	4. Eliminate .. elements that begin a rooted path:
+//	   that is, replace "/.." by "/" at the beginning of a path.
+//
+// The returned path ends in a slash only if it is the root "/".
+//
+// If the result of this process is an empty string, Clean
+// returns the string ".".
+//
+// See also Rob Pike, ``Lexical File Names in Plan 9 or
+// Getting Dot-Dot Right,''
+// http://plan9.bell-labs.com/sys/doc/lexnames.html
+func Clean(path string) string {
+	if path == "" {
+		return "."
+	}
+
+	rooted := path[0] == '/'
+	n := len(path)
+
+	// Invariants:
+	//	reading from path; r is index of next byte to process.
+	//	writing to buf; w is index of next byte to write.
+	//	dotdot is index in buf where .. must stop, either because
+	//		it is the leading slash or it is a leading ../../.. prefix.
+	out := lazybuf{s: path}
+	r, dotdot := 0, 0
+	if rooted {
+		out.append('/')
+		r, dotdot = 1, 1
+	}
+
+	for r < n {
+		switch {
+		case path[r] == '/':
+			// empty path element
+			r++
+		case path[r] == '.' && (r+1 == n || path[r+1] == '/'):
+			// . element
+			r++
+		case path[r] == '.' && path[r+1] == '.' && (r+2 == n || path[r+2] == '/'):
+			// .. element: remove to last /
+			r += 2
+			switch {
+			case out.w > dotdot:
+				// can backtrack
+				out.w--
+				for out.w > dotdot && out.index(out.w) != '/' {
+					out.w--
+				}
+			case !rooted:
+				// cannot backtrack, but not rooted, so append .. element.
+				if out.w > 0 {
+					out.append('/')
+				}
+				out.append('.')
+				out.append('.')
+				dotdot = out.w
+			}
+		default:
+			// real path element.
+			// add slash if needed
+			if rooted && out.w != 1 || !rooted && out.w != 0 {
+				out.append('/')
+			}
+			// copy element
+			for ; r < n && path[r] != '/'; r++ {
+				out.append(path[r])
+			}
+		}
+	}
+
+	// Turn empty string into "."
+	if out.w == 0 {
+		return "."
+	}
+
+	return out.string()
+}
+
+// Split splits path immediately following the final slash.
+// separating it into a directory and file name component.
+// If there is no slash path, Split returns an empty dir and
+// file set to path.
+// The returned values have the property that path = dir+file.
+func Split(path string) (dir, file string) {
+	i := strings.LastIndex(path, "/")
+	return path[:i+1], path[i+1:]
+}
+
+// Join joins any number of path elements into a single path, adding a
+// separating slash if necessary. The result is Cleaned; in particular,
+// all empty strings are ignored.
+func Join(elem ...string) string {
+	for i, e := range elem {
+		if e != "" {
+			return Clean(strings.Join(elem[i:], "/"))
+		}
+	}
+	return ""
+}
+
+// Ext returns the file name extension used by path.
+// The extension is the suffix beginning at the final dot
+// in the final slash-separated element of path;
+// it is empty if there is no dot.
+func Ext(path string) string {
+	for i := len(path) - 1; i >= 0 && path[i] != '/'; i-- {
+		if path[i] == '.' {
+			return path[i:]
+		}
+	}
+	return ""
+}
+
+// Base returns the last element of path.
+// Trailing slashes are removed before extracting the last element.
+// If the path is empty, Base returns ".".
+// If the path consists entirely of slashes, Base returns "/".
+func Base(path string) string {
+	if path == "" {
+		return "."
+	}
+	// Strip trailing slashes.
+	for len(path) > 0 && path[len(path)-1] == '/' {
+		path = path[0 : len(path)-1]
+	}
+	// Find the last element
+	if i := strings.LastIndex(path, "/"); i >= 0 {
+		path = path[i+1:]
+	}
+	// If empty now, it had only slashes.
+	if path == "" {
+		return "/"
+	}
+	return path
+}
+
+// IsAbs returns true if the path is absolute.
+func IsAbs(path string) bool {
+	return len(path) > 0 && path[0] == '/'
+}
+
+// Dir returns all but the last element of path, typically the path's directory.
+// After dropping the final element using Split, the path is Cleaned and trailing
+// slashes are removed.
+// If the path is empty, Dir returns ".".
+// If the path consists entirely of slashes followed by non-slash bytes, Dir
+// returns a single slash. In any other case, the returned path does not end in a
+// slash.
+func Dir(path string) string {
+	dir, _ := Split(path)
+	dir = Clean(dir)
+	last := len(dir) - 1
+	if last > 0 && dir[last] == '/' {
+		dir = dir[:last]
+	}
+	if dir == "" {
+		dir = "."
+	}
+	return dir
+}
diff --git a/third_party/gofrontend/libgo/go/path/path_test.go b/third_party/gofrontend/libgo/go/path/path_test.go
new file mode 100644
index 0000000..512d936
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/path/path_test.go
@@ -0,0 +1,244 @@
+// 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 path
+
+import (
+	"runtime"
+	"testing"
+)
+
+type PathTest struct {
+	path, result string
+}
+
+var cleantests = []PathTest{
+	// Already clean
+	{"", "."},
+	{"abc", "abc"},
+	{"abc/def", "abc/def"},
+	{"a/b/c", "a/b/c"},
+	{".", "."},
+	{"..", ".."},
+	{"../..", "../.."},
+	{"../../abc", "../../abc"},
+	{"/abc", "/abc"},
+	{"/", "/"},
+
+	// Remove trailing slash
+	{"abc/", "abc"},
+	{"abc/def/", "abc/def"},
+	{"a/b/c/", "a/b/c"},
+	{"./", "."},
+	{"../", ".."},
+	{"../../", "../.."},
+	{"/abc/", "/abc"},
+
+	// Remove doubled slash
+	{"abc//def//ghi", "abc/def/ghi"},
+	{"//abc", "/abc"},
+	{"///abc", "/abc"},
+	{"//abc//", "/abc"},
+	{"abc//", "abc"},
+
+	// Remove . elements
+	{"abc/./def", "abc/def"},
+	{"/./abc/def", "/abc/def"},
+	{"abc/.", "abc"},
+
+	// Remove .. elements
+	{"abc/def/ghi/../jkl", "abc/def/jkl"},
+	{"abc/def/../ghi/../jkl", "abc/jkl"},
+	{"abc/def/..", "abc"},
+	{"abc/def/../..", "."},
+	{"/abc/def/../..", "/"},
+	{"abc/def/../../..", ".."},
+	{"/abc/def/../../..", "/"},
+	{"abc/def/../../../ghi/jkl/../../../mno", "../../mno"},
+
+	// Combinations
+	{"abc/./../def", "def"},
+	{"abc//./../def", "def"},
+	{"abc/../../././../def", "../../def"},
+}
+
+func TestClean(t *testing.T) {
+	for _, test := range cleantests {
+		if s := Clean(test.path); s != test.result {
+			t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.result)
+		}
+		if s := Clean(test.result); s != test.result {
+			t.Errorf("Clean(%q) = %q, want %q", test.result, s, test.result)
+		}
+	}
+}
+
+func TestCleanMallocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1")
+		return
+	}
+
+	t.Log("Skipping AllocsPerRun for gccgo")
+	return
+
+	for _, test := range cleantests {
+		allocs := testing.AllocsPerRun(100, func() { Clean(test.result) })
+		if allocs > 0 {
+			t.Errorf("Clean(%q): %v allocs, want zero", test.result, allocs)
+		}
+	}
+}
+
+type SplitTest struct {
+	path, dir, file string
+}
+
+var splittests = []SplitTest{
+	{"a/b", "a/", "b"},
+	{"a/b/", "a/b/", ""},
+	{"a/", "a/", ""},
+	{"a", "", "a"},
+	{"/", "/", ""},
+}
+
+func TestSplit(t *testing.T) {
+	for _, test := range splittests {
+		if d, f := Split(test.path); d != test.dir || f != test.file {
+			t.Errorf("Split(%q) = %q, %q, want %q, %q", test.path, d, f, test.dir, test.file)
+		}
+	}
+}
+
+type JoinTest struct {
+	elem []string
+	path string
+}
+
+var jointests = []JoinTest{
+	// zero parameters
+	{[]string{}, ""},
+
+	// one parameter
+	{[]string{""}, ""},
+	{[]string{"a"}, "a"},
+
+	// two parameters
+	{[]string{"a", "b"}, "a/b"},
+	{[]string{"a", ""}, "a"},
+	{[]string{"", "b"}, "b"},
+	{[]string{"/", "a"}, "/a"},
+	{[]string{"/", ""}, "/"},
+	{[]string{"a/", "b"}, "a/b"},
+	{[]string{"a/", ""}, "a"},
+	{[]string{"", ""}, ""},
+}
+
+// join takes a []string and passes it to Join.
+func join(elem []string, args ...string) string {
+	args = elem
+	return Join(args...)
+}
+
+func TestJoin(t *testing.T) {
+	for _, test := range jointests {
+		if p := join(test.elem); p != test.path {
+			t.Errorf("join(%q) = %q, want %q", test.elem, p, test.path)
+		}
+	}
+}
+
+type ExtTest struct {
+	path, ext string
+}
+
+var exttests = []ExtTest{
+	{"path.go", ".go"},
+	{"path.pb.go", ".go"},
+	{"a.dir/b", ""},
+	{"a.dir/b.go", ".go"},
+	{"a.dir/", ""},
+}
+
+func TestExt(t *testing.T) {
+	for _, test := range exttests {
+		if x := Ext(test.path); x != test.ext {
+			t.Errorf("Ext(%q) = %q, want %q", test.path, x, test.ext)
+		}
+	}
+}
+
+var basetests = []PathTest{
+	// Already clean
+	{"", "."},
+	{".", "."},
+	{"/.", "."},
+	{"/", "/"},
+	{"////", "/"},
+	{"x/", "x"},
+	{"abc", "abc"},
+	{"abc/def", "def"},
+	{"a/b/.x", ".x"},
+	{"a/b/c.", "c."},
+	{"a/b/c.x", "c.x"},
+}
+
+func TestBase(t *testing.T) {
+	for _, test := range basetests {
+		if s := Base(test.path); s != test.result {
+			t.Errorf("Base(%q) = %q, want %q", test.path, s, test.result)
+		}
+	}
+}
+
+var dirtests = []PathTest{
+	{"", "."},
+	{".", "."},
+	{"/.", "/"},
+	{"/", "/"},
+	{"////", "/"},
+	{"/foo", "/"},
+	{"x/", "x"},
+	{"abc", "."},
+	{"abc/def", "abc"},
+	{"abc////def", "abc"},
+	{"a/b/.x", "a/b"},
+	{"a/b/c.", "a/b"},
+	{"a/b/c.x", "a/b"},
+}
+
+func TestDir(t *testing.T) {
+	for _, test := range dirtests {
+		if s := Dir(test.path); s != test.result {
+			t.Errorf("Dir(%q) = %q, want %q", test.path, s, test.result)
+		}
+	}
+}
+
+type IsAbsTest struct {
+	path  string
+	isAbs bool
+}
+
+var isAbsTests = []IsAbsTest{
+	{"", false},
+	{"/", true},
+	{"/usr/bin/gcc", true},
+	{"..", false},
+	{"/a/../bb", true},
+	{".", false},
+	{"./", false},
+	{"lala", false},
+}
+
+func TestIsAbs(t *testing.T) {
+	for _, test := range isAbsTests {
+		if r := IsAbs(test.path); r != test.isAbs {
+			t.Errorf("IsAbs(%q) = %v, want %v", test.path, r, test.isAbs)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/all_test.go b/third_party/gofrontend/libgo/go/reflect/all_test.go
new file mode 100644
index 0000000..3e10779
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/all_test.go
@@ -0,0 +1,3913 @@
+// 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 reflect_test
+
+import (
+	"bytes"
+	"encoding/base64"
+	"flag"
+	"fmt"
+	"io"
+	"math/rand"
+	"os"
+	. "reflect"
+	"runtime"
+	"sort"
+	"strings"
+	"sync"
+	"testing"
+	"time"
+	"unsafe"
+)
+
+func TestBool(t *testing.T) {
+	v := ValueOf(true)
+	if v.Bool() != true {
+		t.Fatal("ValueOf(true).Bool() = false")
+	}
+}
+
+type integer int
+type T struct {
+	a int
+	b float64
+	c string
+	d *int
+}
+
+type pair struct {
+	i interface{}
+	s string
+}
+
+func isDigit(c uint8) bool { return '0' <= c && c <= '9' }
+
+func assert(t *testing.T, s, want string) {
+	if s != want {
+		t.Errorf("have %#q want %#q", s, want)
+	}
+}
+
+func typestring(i interface{}) string { return TypeOf(i).String() }
+
+var typeTests = []pair{
+	{struct{ x int }{}, "int"},
+	{struct{ x int8 }{}, "int8"},
+	{struct{ x int16 }{}, "int16"},
+	{struct{ x int32 }{}, "int32"},
+	{struct{ x int64 }{}, "int64"},
+	{struct{ x uint }{}, "uint"},
+	{struct{ x uint8 }{}, "uint8"},
+	{struct{ x uint16 }{}, "uint16"},
+	{struct{ x uint32 }{}, "uint32"},
+	{struct{ x uint64 }{}, "uint64"},
+	{struct{ x float32 }{}, "float32"},
+	{struct{ x float64 }{}, "float64"},
+	{struct{ x int8 }{}, "int8"},
+	{struct{ x (**int8) }{}, "**int8"},
+	{struct{ x (**integer) }{}, "**reflect_test.integer"},
+	{struct{ x ([32]int32) }{}, "[32]int32"},
+	{struct{ x ([]int8) }{}, "[]int8"},
+	{struct{ x (map[string]int32) }{}, "map[string]int32"},
+	{struct{ x (chan<- string) }{}, "chan<- string"},
+	{struct {
+		x struct {
+			c chan *int32
+			d float32
+		}
+	}{},
+		"struct { c chan *int32; d float32 }",
+	},
+	{struct{ x (func(a int8, b int32)) }{}, "func(int8, int32)"},
+	{struct {
+		x struct {
+			c func(chan *integer, *int8)
+		}
+	}{},
+		"struct { c func(chan *reflect_test.integer, *int8) }",
+	},
+	{struct {
+		x struct {
+			a int8
+			b int32
+		}
+	}{},
+		"struct { a int8; b int32 }",
+	},
+	{struct {
+		x struct {
+			a int8
+			b int8
+			c int32
+		}
+	}{},
+		"struct { a int8; b int8; c int32 }",
+	},
+	{struct {
+		x struct {
+			a int8
+			b int8
+			c int8
+			d int32
+		}
+	}{},
+		"struct { a int8; b int8; c int8; d int32 }",
+	},
+	{struct {
+		x struct {
+			a int8
+			b int8
+			c int8
+			d int8
+			e int32
+		}
+	}{},
+		"struct { a int8; b int8; c int8; d int8; e int32 }",
+	},
+	{struct {
+		x struct {
+			a int8
+			b int8
+			c int8
+			d int8
+			e int8
+			f int32
+		}
+	}{},
+		"struct { a int8; b int8; c int8; d int8; e int8; f int32 }",
+	},
+	{struct {
+		x struct {
+			a int8 `reflect:"hi there"`
+		}
+	}{},
+		`struct { a int8 "reflect:\"hi there\"" }`,
+	},
+	{struct {
+		x struct {
+			a int8 `reflect:"hi \x00there\t\n\"\\"`
+		}
+	}{},
+		`struct { a int8 "reflect:\"hi \\x00there\\t\\n\\\"\\\\\"" }`,
+	},
+	{struct {
+		x struct {
+			f func(args ...int)
+		}
+	}{},
+		"struct { f func(...int) }",
+	},
+	{struct {
+		x (interface {
+			a(func(func(int) int) func(func(int)) int)
+			b()
+		})
+	}{},
+		"interface { reflect_test.a(func(func(int) int) func(func(int)) int); reflect_test.b() }",
+	},
+}
+
+var valueTests = []pair{
+	{new(int), "132"},
+	{new(int8), "8"},
+	{new(int16), "16"},
+	{new(int32), "32"},
+	{new(int64), "64"},
+	{new(uint), "132"},
+	{new(uint8), "8"},
+	{new(uint16), "16"},
+	{new(uint32), "32"},
+	{new(uint64), "64"},
+	{new(float32), "256.25"},
+	{new(float64), "512.125"},
+	{new(complex64), "532.125+10i"},
+	{new(complex128), "564.25+1i"},
+	{new(string), "stringy cheese"},
+	{new(bool), "true"},
+	{new(*int8), "*int8(0)"},
+	{new(**int8), "**int8(0)"},
+	{new([5]int32), "[5]int32{0, 0, 0, 0, 0}"},
+	{new(**integer), "**reflect_test.integer(0)"},
+	{new(map[string]int32), "map[string]int32{<can't iterate on maps>}"},
+	{new(chan<- string), "chan<- string"},
+	{new(func(a int8, b int32)), "func(int8, int32)(0)"},
+	{new(struct {
+		c chan *int32
+		d float32
+	}),
+		"struct { c chan *int32; d float32 }{chan *int32, 0}",
+	},
+	{new(struct{ c func(chan *integer, *int8) }),
+		"struct { c func(chan *reflect_test.integer, *int8) }{func(chan *reflect_test.integer, *int8)(0)}",
+	},
+	{new(struct {
+		a int8
+		b int32
+	}),
+		"struct { a int8; b int32 }{0, 0}",
+	},
+	{new(struct {
+		a int8
+		b int8
+		c int32
+	}),
+		"struct { a int8; b int8; c int32 }{0, 0, 0}",
+	},
+}
+
+func testType(t *testing.T, i int, typ Type, want string) {
+	s := typ.String()
+	if s != want {
+		t.Errorf("#%d: have %#q, want %#q", i, s, want)
+	}
+}
+
+func TestTypes(t *testing.T) {
+	for i, tt := range typeTests {
+		testType(t, i, ValueOf(tt.i).Field(0).Type(), tt.s)
+	}
+}
+
+func TestSet(t *testing.T) {
+	for i, tt := range valueTests {
+		v := ValueOf(tt.i)
+		v = v.Elem()
+		switch v.Kind() {
+		case Int:
+			v.SetInt(132)
+		case Int8:
+			v.SetInt(8)
+		case Int16:
+			v.SetInt(16)
+		case Int32:
+			v.SetInt(32)
+		case Int64:
+			v.SetInt(64)
+		case Uint:
+			v.SetUint(132)
+		case Uint8:
+			v.SetUint(8)
+		case Uint16:
+			v.SetUint(16)
+		case Uint32:
+			v.SetUint(32)
+		case Uint64:
+			v.SetUint(64)
+		case Float32:
+			v.SetFloat(256.25)
+		case Float64:
+			v.SetFloat(512.125)
+		case Complex64:
+			v.SetComplex(532.125 + 10i)
+		case Complex128:
+			v.SetComplex(564.25 + 1i)
+		case String:
+			v.SetString("stringy cheese")
+		case Bool:
+			v.SetBool(true)
+		}
+		s := valueToString(v)
+		if s != tt.s {
+			t.Errorf("#%d: have %#q, want %#q", i, s, tt.s)
+		}
+	}
+}
+
+func TestSetValue(t *testing.T) {
+	for i, tt := range valueTests {
+		v := ValueOf(tt.i).Elem()
+		switch v.Kind() {
+		case Int:
+			v.Set(ValueOf(int(132)))
+		case Int8:
+			v.Set(ValueOf(int8(8)))
+		case Int16:
+			v.Set(ValueOf(int16(16)))
+		case Int32:
+			v.Set(ValueOf(int32(32)))
+		case Int64:
+			v.Set(ValueOf(int64(64)))
+		case Uint:
+			v.Set(ValueOf(uint(132)))
+		case Uint8:
+			v.Set(ValueOf(uint8(8)))
+		case Uint16:
+			v.Set(ValueOf(uint16(16)))
+		case Uint32:
+			v.Set(ValueOf(uint32(32)))
+		case Uint64:
+			v.Set(ValueOf(uint64(64)))
+		case Float32:
+			v.Set(ValueOf(float32(256.25)))
+		case Float64:
+			v.Set(ValueOf(512.125))
+		case Complex64:
+			v.Set(ValueOf(complex64(532.125 + 10i)))
+		case Complex128:
+			v.Set(ValueOf(complex128(564.25 + 1i)))
+		case String:
+			v.Set(ValueOf("stringy cheese"))
+		case Bool:
+			v.Set(ValueOf(true))
+		}
+		s := valueToString(v)
+		if s != tt.s {
+			t.Errorf("#%d: have %#q, want %#q", i, s, tt.s)
+		}
+	}
+}
+
+var _i = 7
+
+var valueToStringTests = []pair{
+	{123, "123"},
+	{123.5, "123.5"},
+	{byte(123), "123"},
+	{"abc", "abc"},
+	{T{123, 456.75, "hello", &_i}, "reflect_test.T{123, 456.75, hello, *int(&7)}"},
+	{new(chan *T), "*chan *reflect_test.T(&chan *reflect_test.T)"},
+	{[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
+	{&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[10]int(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
+	{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
+	{&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[]int(&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
+}
+
+func TestValueToString(t *testing.T) {
+	for i, test := range valueToStringTests {
+		s := valueToString(ValueOf(test.i))
+		if s != test.s {
+			t.Errorf("#%d: have %#q, want %#q", i, s, test.s)
+		}
+	}
+}
+
+func TestArrayElemSet(t *testing.T) {
+	v := ValueOf(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).Elem()
+	v.Index(4).SetInt(123)
+	s := valueToString(v)
+	const want = "[10]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"
+	if s != want {
+		t.Errorf("[10]int: have %#q want %#q", s, want)
+	}
+
+	v = ValueOf([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
+	v.Index(4).SetInt(123)
+	s = valueToString(v)
+	const want1 = "[]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"
+	if s != want1 {
+		t.Errorf("[]int: have %#q want %#q", s, want1)
+	}
+}
+
+func TestPtrPointTo(t *testing.T) {
+	var ip *int32
+	var i int32 = 1234
+	vip := ValueOf(&ip)
+	vi := ValueOf(&i).Elem()
+	vip.Elem().Set(vi.Addr())
+	if *ip != 1234 {
+		t.Errorf("got %d, want 1234", *ip)
+	}
+
+	ip = nil
+	vp := ValueOf(&ip).Elem()
+	vp.Set(Zero(vp.Type()))
+	if ip != nil {
+		t.Errorf("got non-nil (%p), want nil", ip)
+	}
+}
+
+func TestPtrSetNil(t *testing.T) {
+	var i int32 = 1234
+	ip := &i
+	vip := ValueOf(&ip)
+	vip.Elem().Set(Zero(vip.Elem().Type()))
+	if ip != nil {
+		t.Errorf("got non-nil (%d), want nil", *ip)
+	}
+}
+
+func TestMapSetNil(t *testing.T) {
+	m := make(map[string]int)
+	vm := ValueOf(&m)
+	vm.Elem().Set(Zero(vm.Elem().Type()))
+	if m != nil {
+		t.Errorf("got non-nil (%p), want nil", m)
+	}
+}
+
+func TestAll(t *testing.T) {
+	testType(t, 1, TypeOf((int8)(0)), "int8")
+	testType(t, 2, TypeOf((*int8)(nil)).Elem(), "int8")
+
+	typ := TypeOf((*struct {
+		c chan *int32
+		d float32
+	})(nil))
+	testType(t, 3, typ, "*struct { c chan *int32; d float32 }")
+	etyp := typ.Elem()
+	testType(t, 4, etyp, "struct { c chan *int32; d float32 }")
+	styp := etyp
+	f := styp.Field(0)
+	testType(t, 5, f.Type, "chan *int32")
+
+	f, present := styp.FieldByName("d")
+	if !present {
+		t.Errorf("FieldByName says present field is absent")
+	}
+	testType(t, 6, f.Type, "float32")
+
+	f, present = styp.FieldByName("absent")
+	if present {
+		t.Errorf("FieldByName says absent field is present")
+	}
+
+	typ = TypeOf([32]int32{})
+	testType(t, 7, typ, "[32]int32")
+	testType(t, 8, typ.Elem(), "int32")
+
+	typ = TypeOf((map[string]*int32)(nil))
+	testType(t, 9, typ, "map[string]*int32")
+	mtyp := typ
+	testType(t, 10, mtyp.Key(), "string")
+	testType(t, 11, mtyp.Elem(), "*int32")
+
+	typ = TypeOf((chan<- string)(nil))
+	testType(t, 12, typ, "chan<- string")
+	testType(t, 13, typ.Elem(), "string")
+
+	// make sure tag strings are not part of element type
+	typ = TypeOf(struct {
+		d []uint32 `reflect:"TAG"`
+	}{}).Field(0).Type
+	testType(t, 14, typ, "[]uint32")
+}
+
+func TestInterfaceGet(t *testing.T) {
+	var inter struct {
+		E interface{}
+	}
+	inter.E = 123.456
+	v1 := ValueOf(&inter)
+	v2 := v1.Elem().Field(0)
+	assert(t, v2.Type().String(), "interface {}")
+	i2 := v2.Interface()
+	v3 := ValueOf(i2)
+	assert(t, v3.Type().String(), "float64")
+}
+
+func TestInterfaceValue(t *testing.T) {
+	var inter struct {
+		E interface{}
+	}
+	inter.E = 123.456
+	v1 := ValueOf(&inter)
+	v2 := v1.Elem().Field(0)
+	assert(t, v2.Type().String(), "interface {}")
+	v3 := v2.Elem()
+	assert(t, v3.Type().String(), "float64")
+
+	i3 := v2.Interface()
+	if _, ok := i3.(float64); !ok {
+		t.Error("v2.Interface() did not return float64, got ", TypeOf(i3))
+	}
+}
+
+func TestFunctionValue(t *testing.T) {
+	var x interface{} = func() {}
+	v := ValueOf(x)
+	if fmt.Sprint(v.Interface()) != fmt.Sprint(x) {
+		t.Fatalf("TestFunction returned wrong pointer")
+	}
+	assert(t, v.Type().String(), "func()")
+}
+
+var appendTests = []struct {
+	orig, extra []int
+}{
+	{make([]int, 2, 4), []int{22}},
+	{make([]int, 2, 4), []int{22, 33, 44}},
+}
+
+func sameInts(x, y []int) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, xx := range x {
+		if xx != y[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func TestAppend(t *testing.T) {
+	for i, test := range appendTests {
+		origLen, extraLen := len(test.orig), len(test.extra)
+		want := append(test.orig, test.extra...)
+		// Convert extra from []int to []Value.
+		e0 := make([]Value, len(test.extra))
+		for j, e := range test.extra {
+			e0[j] = ValueOf(e)
+		}
+		// Convert extra from []int to *SliceValue.
+		e1 := ValueOf(test.extra)
+		// Test Append.
+		a0 := ValueOf(test.orig)
+		have0 := Append(a0, e0...).Interface().([]int)
+		if !sameInts(have0, want) {
+			t.Errorf("Append #%d: have %v, want %v (%p %p)", i, have0, want, test.orig, have0)
+		}
+		// Check that the orig and extra slices were not modified.
+		if len(test.orig) != origLen {
+			t.Errorf("Append #%d origLen: have %v, want %v", i, len(test.orig), origLen)
+		}
+		if len(test.extra) != extraLen {
+			t.Errorf("Append #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
+		}
+		// Test AppendSlice.
+		a1 := ValueOf(test.orig)
+		have1 := AppendSlice(a1, e1).Interface().([]int)
+		if !sameInts(have1, want) {
+			t.Errorf("AppendSlice #%d: have %v, want %v", i, have1, want)
+		}
+		// Check that the orig and extra slices were not modified.
+		if len(test.orig) != origLen {
+			t.Errorf("AppendSlice #%d origLen: have %v, want %v", i, len(test.orig), origLen)
+		}
+		if len(test.extra) != extraLen {
+			t.Errorf("AppendSlice #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
+		}
+	}
+}
+
+func TestCopy(t *testing.T) {
+	a := []int{1, 2, 3, 4, 10, 9, 8, 7}
+	b := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
+	c := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
+	for i := 0; i < len(b); i++ {
+		if b[i] != c[i] {
+			t.Fatalf("b != c before test")
+		}
+	}
+	a1 := a
+	b1 := b
+	aa := ValueOf(&a1).Elem()
+	ab := ValueOf(&b1).Elem()
+	for tocopy := 1; tocopy <= 7; tocopy++ {
+		aa.SetLen(tocopy)
+		Copy(ab, aa)
+		aa.SetLen(8)
+		for i := 0; i < tocopy; i++ {
+			if a[i] != b[i] {
+				t.Errorf("(i) tocopy=%d a[%d]=%d, b[%d]=%d",
+					tocopy, i, a[i], i, b[i])
+			}
+		}
+		for i := tocopy; i < len(b); i++ {
+			if b[i] != c[i] {
+				if i < len(a) {
+					t.Errorf("(ii) tocopy=%d a[%d]=%d, b[%d]=%d, c[%d]=%d",
+						tocopy, i, a[i], i, b[i], i, c[i])
+				} else {
+					t.Errorf("(iii) tocopy=%d b[%d]=%d, c[%d]=%d",
+						tocopy, i, b[i], i, c[i])
+				}
+			} else {
+				t.Logf("tocopy=%d elem %d is okay\n", tocopy, i)
+			}
+		}
+	}
+}
+
+func TestCopyArray(t *testing.T) {
+	a := [8]int{1, 2, 3, 4, 10, 9, 8, 7}
+	b := [11]int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
+	c := b
+	aa := ValueOf(&a).Elem()
+	ab := ValueOf(&b).Elem()
+	Copy(ab, aa)
+	for i := 0; i < len(a); i++ {
+		if a[i] != b[i] {
+			t.Errorf("(i) a[%d]=%d, b[%d]=%d", i, a[i], i, b[i])
+		}
+	}
+	for i := len(a); i < len(b); i++ {
+		if b[i] != c[i] {
+			t.Errorf("(ii) b[%d]=%d, c[%d]=%d", i, b[i], i, c[i])
+		} else {
+			t.Logf("elem %d is okay\n", i)
+		}
+	}
+}
+
+func TestBigUnnamedStruct(t *testing.T) {
+	b := struct{ a, b, c, d int64 }{1, 2, 3, 4}
+	v := ValueOf(b)
+	b1 := v.Interface().(struct {
+		a, b, c, d int64
+	})
+	if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d {
+		t.Errorf("ValueOf(%v).Interface().(*Big) = %v", b, b1)
+	}
+}
+
+type big struct {
+	a, b, c, d, e int64
+}
+
+func TestBigStruct(t *testing.T) {
+	b := big{1, 2, 3, 4, 5}
+	v := ValueOf(b)
+	b1 := v.Interface().(big)
+	if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d || b1.e != b.e {
+		t.Errorf("ValueOf(%v).Interface().(big) = %v", b, b1)
+	}
+}
+
+type Basic struct {
+	x int
+	y float32
+}
+
+type NotBasic Basic
+
+type DeepEqualTest struct {
+	a, b interface{}
+	eq   bool
+}
+
+// Simple functions for DeepEqual tests.
+var (
+	fn1 func()             // nil.
+	fn2 func()             // nil.
+	fn3 = func() { fn1() } // Not nil.
+)
+
+var deepEqualTests = []DeepEqualTest{
+	// Equalities
+	{nil, nil, true},
+	{1, 1, true},
+	{int32(1), int32(1), true},
+	{0.5, 0.5, true},
+	{float32(0.5), float32(0.5), true},
+	{"hello", "hello", true},
+	{make([]int, 10), make([]int, 10), true},
+	{&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true},
+	{Basic{1, 0.5}, Basic{1, 0.5}, true},
+	{error(nil), error(nil), true},
+	{map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true},
+	{fn1, fn2, true},
+
+	// Inequalities
+	{1, 2, false},
+	{int32(1), int32(2), false},
+	{0.5, 0.6, false},
+	{float32(0.5), float32(0.6), false},
+	{"hello", "hey", false},
+	{make([]int, 10), make([]int, 11), false},
+	{&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false},
+	{Basic{1, 0.5}, Basic{1, 0.6}, false},
+	{Basic{1, 0}, Basic{2, 0}, false},
+	{map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false},
+	{map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false},
+	{map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false},
+	{map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false},
+	{nil, 1, false},
+	{1, nil, false},
+	{fn1, fn3, false},
+	{fn3, fn3, false},
+	{[][]int{[]int{1}}, [][]int{[]int{2}}, false},
+
+	// Nil vs empty: not the same.
+	{[]int{}, []int(nil), false},
+	{[]int{}, []int{}, true},
+	{[]int(nil), []int(nil), true},
+	{map[int]int{}, map[int]int(nil), false},
+	{map[int]int{}, map[int]int{}, true},
+	{map[int]int(nil), map[int]int(nil), true},
+
+	// Mismatched types
+	{1, 1.0, false},
+	{int32(1), int64(1), false},
+	{0.5, "hello", false},
+	{[]int{1, 2, 3}, [3]int{1, 2, 3}, false},
+	{&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false},
+	{Basic{1, 0.5}, NotBasic{1, 0.5}, false},
+	{map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false},
+}
+
+func TestDeepEqual(t *testing.T) {
+	for _, test := range deepEqualTests {
+		if r := DeepEqual(test.a, test.b); r != test.eq {
+			t.Errorf("DeepEqual(%v, %v) = %v, want %v", test.a, test.b, r, test.eq)
+		}
+	}
+}
+
+func TestTypeOf(t *testing.T) {
+	// Special case for nil
+	if typ := TypeOf(nil); typ != nil {
+		t.Errorf("expected nil type for nil value; got %v", typ)
+	}
+	for _, test := range deepEqualTests {
+		v := ValueOf(test.a)
+		if !v.IsValid() {
+			continue
+		}
+		typ := TypeOf(test.a)
+		if typ != v.Type() {
+			t.Errorf("TypeOf(%v) = %v, but ValueOf(%v).Type() = %v", test.a, typ, test.a, v.Type())
+		}
+	}
+}
+
+type Recursive struct {
+	x int
+	r *Recursive
+}
+
+func TestDeepEqualRecursiveStruct(t *testing.T) {
+	a, b := new(Recursive), new(Recursive)
+	*a = Recursive{12, a}
+	*b = Recursive{12, b}
+	if !DeepEqual(a, b) {
+		t.Error("DeepEqual(recursive same) = false, want true")
+	}
+}
+
+type _Complex struct {
+	a int
+	b [3]*_Complex
+	c *string
+	d map[float64]float64
+}
+
+func TestDeepEqualComplexStruct(t *testing.T) {
+	m := make(map[float64]float64)
+	stra, strb := "hello", "hello"
+	a, b := new(_Complex), new(_Complex)
+	*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
+	*b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}
+	if !DeepEqual(a, b) {
+		t.Error("DeepEqual(complex same) = false, want true")
+	}
+}
+
+func TestDeepEqualComplexStructInequality(t *testing.T) {
+	m := make(map[float64]float64)
+	stra, strb := "hello", "helloo" // Difference is here
+	a, b := new(_Complex), new(_Complex)
+	*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
+	*b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}
+	if DeepEqual(a, b) {
+		t.Error("DeepEqual(complex different) = true, want false")
+	}
+}
+
+type UnexpT struct {
+	m map[int]int
+}
+
+func TestDeepEqualUnexportedMap(t *testing.T) {
+	// Check that DeepEqual can look at unexported fields.
+	x1 := UnexpT{map[int]int{1: 2}}
+	x2 := UnexpT{map[int]int{1: 2}}
+	if !DeepEqual(&x1, &x2) {
+		t.Error("DeepEqual(x1, x2) = false, want true")
+	}
+
+	y1 := UnexpT{map[int]int{2: 3}}
+	if DeepEqual(&x1, &y1) {
+		t.Error("DeepEqual(x1, y1) = true, want false")
+	}
+}
+
+func check2ndField(x interface{}, offs uintptr, t *testing.T) {
+	s := ValueOf(x)
+	f := s.Type().Field(1)
+	if f.Offset != offs {
+		t.Error("mismatched offsets in structure alignment:", f.Offset, offs)
+	}
+}
+
+// Check that structure alignment & offsets viewed through reflect agree with those
+// from the compiler itself.
+func TestAlignment(t *testing.T) {
+	type T1inner struct {
+		a int
+	}
+	type T1 struct {
+		T1inner
+		f int
+	}
+	type T2inner struct {
+		a, b int
+	}
+	type T2 struct {
+		T2inner
+		f int
+	}
+
+	x := T1{T1inner{2}, 17}
+	check2ndField(x, uintptr(unsafe.Pointer(&x.f))-uintptr(unsafe.Pointer(&x)), t)
+
+	x1 := T2{T2inner{2, 3}, 17}
+	check2ndField(x1, uintptr(unsafe.Pointer(&x1.f))-uintptr(unsafe.Pointer(&x1)), t)
+}
+
+func Nil(a interface{}, t *testing.T) {
+	n := ValueOf(a).Field(0)
+	if !n.IsNil() {
+		t.Errorf("%v should be nil", a)
+	}
+}
+
+func NotNil(a interface{}, t *testing.T) {
+	n := ValueOf(a).Field(0)
+	if n.IsNil() {
+		t.Errorf("value of type %v should not be nil", ValueOf(a).Type().String())
+	}
+}
+
+func TestIsNil(t *testing.T) {
+	// These implement IsNil.
+	// Wrap in extra struct to hide interface type.
+	doNil := []interface{}{
+		struct{ x *int }{},
+		struct{ x interface{} }{},
+		struct{ x map[string]int }{},
+		struct{ x func() bool }{},
+		struct{ x chan int }{},
+		struct{ x []string }{},
+	}
+	for _, ts := range doNil {
+		ty := TypeOf(ts).Field(0).Type
+		v := Zero(ty)
+		v.IsNil() // panics if not okay to call
+	}
+
+	// Check the implementations
+	var pi struct {
+		x *int
+	}
+	Nil(pi, t)
+	pi.x = new(int)
+	NotNil(pi, t)
+
+	var si struct {
+		x []int
+	}
+	Nil(si, t)
+	si.x = make([]int, 10)
+	NotNil(si, t)
+
+	var ci struct {
+		x chan int
+	}
+	Nil(ci, t)
+	ci.x = make(chan int)
+	NotNil(ci, t)
+
+	var mi struct {
+		x map[int]int
+	}
+	Nil(mi, t)
+	mi.x = make(map[int]int)
+	NotNil(mi, t)
+
+	var ii struct {
+		x interface{}
+	}
+	Nil(ii, t)
+	ii.x = 2
+	NotNil(ii, t)
+
+	var fi struct {
+		x func(t *testing.T)
+	}
+	Nil(fi, t)
+	fi.x = TestIsNil
+	NotNil(fi, t)
+}
+
+func TestInterfaceExtraction(t *testing.T) {
+	var s struct {
+		W io.Writer
+	}
+
+	s.W = os.Stdout
+	v := Indirect(ValueOf(&s)).Field(0).Interface()
+	if v != s.W.(interface{}) {
+		t.Error("Interface() on interface: ", v, s.W)
+	}
+}
+
+func TestNilPtrValueSub(t *testing.T) {
+	var pi *int
+	if pv := ValueOf(pi); pv.Elem().IsValid() {
+		t.Error("ValueOf((*int)(nil)).Elem().IsValid()")
+	}
+}
+
+func TestMap(t *testing.T) {
+	m := map[string]int{"a": 1, "b": 2}
+	mv := ValueOf(m)
+	if n := mv.Len(); n != len(m) {
+		t.Errorf("Len = %d, want %d", n, len(m))
+	}
+	keys := mv.MapKeys()
+	newmap := MakeMap(mv.Type())
+	for k, v := range m {
+		// Check that returned Keys match keys in range.
+		// These aren't required to be in the same order.
+		seen := false
+		for _, kv := range keys {
+			if kv.String() == k {
+				seen = true
+				break
+			}
+		}
+		if !seen {
+			t.Errorf("Missing key %q", k)
+		}
+
+		// Check that value lookup is correct.
+		vv := mv.MapIndex(ValueOf(k))
+		if vi := vv.Int(); vi != int64(v) {
+			t.Errorf("Key %q: have value %d, want %d", k, vi, v)
+		}
+
+		// Copy into new map.
+		newmap.SetMapIndex(ValueOf(k), ValueOf(v))
+	}
+	vv := mv.MapIndex(ValueOf("not-present"))
+	if vv.IsValid() {
+		t.Errorf("Invalid key: got non-nil value %s", valueToString(vv))
+	}
+
+	newm := newmap.Interface().(map[string]int)
+	if len(newm) != len(m) {
+		t.Errorf("length after copy: newm=%d, m=%d", len(newm), len(m))
+	}
+
+	for k, v := range newm {
+		mv, ok := m[k]
+		if mv != v {
+			t.Errorf("newm[%q] = %d, but m[%q] = %d, %v", k, v, k, mv, ok)
+		}
+	}
+
+	newmap.SetMapIndex(ValueOf("a"), Value{})
+	v, ok := newm["a"]
+	if ok {
+		t.Errorf("newm[\"a\"] = %d after delete", v)
+	}
+
+	mv = ValueOf(&m).Elem()
+	mv.Set(Zero(mv.Type()))
+	if m != nil {
+		t.Errorf("mv.Set(nil) failed")
+	}
+}
+
+func TestNilMap(t *testing.T) {
+	var m map[string]int
+	mv := ValueOf(m)
+	keys := mv.MapKeys()
+	if len(keys) != 0 {
+		t.Errorf(">0 keys for nil map: %v", keys)
+	}
+
+	// Check that value for missing key is zero.
+	x := mv.MapIndex(ValueOf("hello"))
+	if x.Kind() != Invalid {
+		t.Errorf("m.MapIndex(\"hello\") for nil map = %v, want Invalid Value", x)
+	}
+
+	// Check big value too.
+	var mbig map[string][10 << 20]byte
+	x = ValueOf(mbig).MapIndex(ValueOf("hello"))
+	if x.Kind() != Invalid {
+		t.Errorf("mbig.MapIndex(\"hello\") for nil map = %v, want Invalid Value", x)
+	}
+
+	// Test that deletes from a nil map succeed.
+	mv.SetMapIndex(ValueOf("hi"), Value{})
+}
+
+func TestChan(t *testing.T) {
+	for loop := 0; loop < 2; loop++ {
+		var c chan int
+		var cv Value
+
+		// check both ways to allocate channels
+		switch loop {
+		case 1:
+			c = make(chan int, 1)
+			cv = ValueOf(c)
+		case 0:
+			cv = MakeChan(TypeOf(c), 1)
+			c = cv.Interface().(chan int)
+		}
+
+		// Send
+		cv.Send(ValueOf(2))
+		if i := <-c; i != 2 {
+			t.Errorf("reflect Send 2, native recv %d", i)
+		}
+
+		// Recv
+		c <- 3
+		if i, ok := cv.Recv(); i.Int() != 3 || !ok {
+			t.Errorf("native send 3, reflect Recv %d, %t", i.Int(), ok)
+		}
+
+		// TryRecv fail
+		val, ok := cv.TryRecv()
+		if val.IsValid() || ok {
+			t.Errorf("TryRecv on empty chan: %s, %t", valueToString(val), ok)
+		}
+
+		// TryRecv success
+		c <- 4
+		val, ok = cv.TryRecv()
+		if !val.IsValid() {
+			t.Errorf("TryRecv on ready chan got nil")
+		} else if i := val.Int(); i != 4 || !ok {
+			t.Errorf("native send 4, TryRecv %d, %t", i, ok)
+		}
+
+		// TrySend fail
+		c <- 100
+		ok = cv.TrySend(ValueOf(5))
+		i := <-c
+		if ok {
+			t.Errorf("TrySend on full chan succeeded: value %d", i)
+		}
+
+		// TrySend success
+		ok = cv.TrySend(ValueOf(6))
+		if !ok {
+			t.Errorf("TrySend on empty chan failed")
+		} else {
+			if i = <-c; i != 6 {
+				t.Errorf("TrySend 6, recv %d", i)
+			}
+		}
+
+		// Close
+		c <- 123
+		cv.Close()
+		if i, ok := cv.Recv(); i.Int() != 123 || !ok {
+			t.Errorf("send 123 then close; Recv %d, %t", i.Int(), ok)
+		}
+		if i, ok := cv.Recv(); i.Int() != 0 || ok {
+			t.Errorf("after close Recv %d, %t", i.Int(), ok)
+		}
+	}
+
+	// check creation of unbuffered channel
+	var c chan int
+	cv := MakeChan(TypeOf(c), 0)
+	c = cv.Interface().(chan int)
+	if cv.TrySend(ValueOf(7)) {
+		t.Errorf("TrySend on sync chan succeeded")
+	}
+	if v, ok := cv.TryRecv(); v.IsValid() || ok {
+		t.Errorf("TryRecv on sync chan succeeded: isvalid=%v ok=%v", v.IsValid(), ok)
+	}
+
+	// len/cap
+	cv = MakeChan(TypeOf(c), 10)
+	c = cv.Interface().(chan int)
+	for i := 0; i < 3; i++ {
+		c <- i
+	}
+	if l, m := cv.Len(), cv.Cap(); l != len(c) || m != cap(c) {
+		t.Errorf("Len/Cap = %d/%d want %d/%d", l, m, len(c), cap(c))
+	}
+}
+
+// caseInfo describes a single case in a select test.
+type caseInfo struct {
+	desc      string
+	canSelect bool
+	recv      Value
+	closed    bool
+	helper    func()
+	panic     bool
+}
+
+var allselect = flag.Bool("allselect", false, "exhaustive select test")
+
+func TestSelect(t *testing.T) {
+	selectWatch.once.Do(func() { go selectWatcher() })
+
+	var x exhaustive
+	nch := 0
+	newop := func(n int, cap int) (ch, val Value) {
+		nch++
+		if nch%101%2 == 1 {
+			c := make(chan int, cap)
+			ch = ValueOf(c)
+			val = ValueOf(n)
+		} else {
+			c := make(chan string, cap)
+			ch = ValueOf(c)
+			val = ValueOf(fmt.Sprint(n))
+		}
+		return
+	}
+
+	for n := 0; x.Next(); n++ {
+		if testing.Short() && n >= 1000 {
+			break
+		}
+		if n >= 100000 && !*allselect {
+			break
+		}
+		if n%100000 == 0 && testing.Verbose() {
+			println("TestSelect", n)
+		}
+		var cases []SelectCase
+		var info []caseInfo
+
+		// Ready send.
+		if x.Maybe() {
+			ch, val := newop(len(cases), 1)
+			cases = append(cases, SelectCase{
+				Dir:  SelectSend,
+				Chan: ch,
+				Send: val,
+			})
+			info = append(info, caseInfo{desc: "ready send", canSelect: true})
+		}
+
+		// Ready recv.
+		if x.Maybe() {
+			ch, val := newop(len(cases), 1)
+			ch.Send(val)
+			cases = append(cases, SelectCase{
+				Dir:  SelectRecv,
+				Chan: ch,
+			})
+			info = append(info, caseInfo{desc: "ready recv", canSelect: true, recv: val})
+		}
+
+		// Blocking send.
+		if x.Maybe() {
+			ch, val := newop(len(cases), 0)
+			cases = append(cases, SelectCase{
+				Dir:  SelectSend,
+				Chan: ch,
+				Send: val,
+			})
+			// Let it execute?
+			if x.Maybe() {
+				f := func() { ch.Recv() }
+				info = append(info, caseInfo{desc: "blocking send", helper: f})
+			} else {
+				info = append(info, caseInfo{desc: "blocking send"})
+			}
+		}
+
+		// Blocking recv.
+		if x.Maybe() {
+			ch, val := newop(len(cases), 0)
+			cases = append(cases, SelectCase{
+				Dir:  SelectRecv,
+				Chan: ch,
+			})
+			// Let it execute?
+			if x.Maybe() {
+				f := func() { ch.Send(val) }
+				info = append(info, caseInfo{desc: "blocking recv", recv: val, helper: f})
+			} else {
+				info = append(info, caseInfo{desc: "blocking recv"})
+			}
+		}
+
+		// Zero Chan send.
+		if x.Maybe() {
+			// Maybe include value to send.
+			var val Value
+			if x.Maybe() {
+				val = ValueOf(100)
+			}
+			cases = append(cases, SelectCase{
+				Dir:  SelectSend,
+				Send: val,
+			})
+			info = append(info, caseInfo{desc: "zero Chan send"})
+		}
+
+		// Zero Chan receive.
+		if x.Maybe() {
+			cases = append(cases, SelectCase{
+				Dir: SelectRecv,
+			})
+			info = append(info, caseInfo{desc: "zero Chan recv"})
+		}
+
+		// nil Chan send.
+		if x.Maybe() {
+			cases = append(cases, SelectCase{
+				Dir:  SelectSend,
+				Chan: ValueOf((chan int)(nil)),
+				Send: ValueOf(101),
+			})
+			info = append(info, caseInfo{desc: "nil Chan send"})
+		}
+
+		// nil Chan recv.
+		if x.Maybe() {
+			cases = append(cases, SelectCase{
+				Dir:  SelectRecv,
+				Chan: ValueOf((chan int)(nil)),
+			})
+			info = append(info, caseInfo{desc: "nil Chan recv"})
+		}
+
+		// closed Chan send.
+		if x.Maybe() {
+			ch := make(chan int)
+			close(ch)
+			cases = append(cases, SelectCase{
+				Dir:  SelectSend,
+				Chan: ValueOf(ch),
+				Send: ValueOf(101),
+			})
+			info = append(info, caseInfo{desc: "closed Chan send", canSelect: true, panic: true})
+		}
+
+		// closed Chan recv.
+		if x.Maybe() {
+			ch, val := newop(len(cases), 0)
+			ch.Close()
+			val = Zero(val.Type())
+			cases = append(cases, SelectCase{
+				Dir:  SelectRecv,
+				Chan: ch,
+			})
+			info = append(info, caseInfo{desc: "closed Chan recv", canSelect: true, closed: true, recv: val})
+		}
+
+		var helper func() // goroutine to help the select complete
+
+		// Add default? Must be last case here, but will permute.
+		// Add the default if the select would otherwise
+		// block forever, and maybe add it anyway.
+		numCanSelect := 0
+		canProceed := false
+		canBlock := true
+		canPanic := false
+		helpers := []int{}
+		for i, c := range info {
+			if c.canSelect {
+				canProceed = true
+				canBlock = false
+				numCanSelect++
+				if c.panic {
+					canPanic = true
+				}
+			} else if c.helper != nil {
+				canProceed = true
+				helpers = append(helpers, i)
+			}
+		}
+		if !canProceed || x.Maybe() {
+			cases = append(cases, SelectCase{
+				Dir: SelectDefault,
+			})
+			info = append(info, caseInfo{desc: "default", canSelect: canBlock})
+			numCanSelect++
+		} else if canBlock {
+			// Select needs to communicate with another goroutine.
+			cas := &info[helpers[x.Choose(len(helpers))]]
+			helper = cas.helper
+			cas.canSelect = true
+			numCanSelect++
+		}
+
+		// Permute cases and case info.
+		// Doing too much here makes the exhaustive loop
+		// too exhausting, so just do two swaps.
+		for loop := 0; loop < 2; loop++ {
+			i := x.Choose(len(cases))
+			j := x.Choose(len(cases))
+			cases[i], cases[j] = cases[j], cases[i]
+			info[i], info[j] = info[j], info[i]
+		}
+
+		if helper != nil {
+			// We wait before kicking off a goroutine to satisfy a blocked select.
+			// The pause needs to be big enough to let the select block before
+			// we run the helper, but if we lose that race once in a while it's okay: the
+			// select will just proceed immediately. Not a big deal.
+			// For short tests we can grow [sic] the timeout a bit without fear of taking too long
+			pause := 10 * time.Microsecond
+			if testing.Short() {
+				pause = 100 * time.Microsecond
+			}
+			time.AfterFunc(pause, helper)
+		}
+
+		// Run select.
+		i, recv, recvOK, panicErr := runSelect(cases, info)
+		if panicErr != nil && !canPanic {
+			t.Fatalf("%s\npanicked unexpectedly: %v", fmtSelect(info), panicErr)
+		}
+		if panicErr == nil && canPanic && numCanSelect == 1 {
+			t.Fatalf("%s\nselected #%d incorrectly (should panic)", fmtSelect(info), i)
+		}
+		if panicErr != nil {
+			continue
+		}
+
+		cas := info[i]
+		if !cas.canSelect {
+			recvStr := ""
+			if recv.IsValid() {
+				recvStr = fmt.Sprintf(", received %v, %v", recv.Interface(), recvOK)
+			}
+			t.Fatalf("%s\nselected #%d incorrectly%s", fmtSelect(info), i, recvStr)
+			continue
+		}
+		if cas.panic {
+			t.Fatalf("%s\nselected #%d incorrectly (case should panic)", fmtSelect(info), i)
+			continue
+		}
+
+		if cases[i].Dir == SelectRecv {
+			if !recv.IsValid() {
+				t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, cas.recv.Interface(), !cas.closed)
+			}
+			if !cas.recv.IsValid() {
+				t.Fatalf("%s\nselected #%d but internal error: missing recv value", fmtSelect(info), i)
+			}
+			if recv.Interface() != cas.recv.Interface() || recvOK != !cas.closed {
+				if recv.Interface() == cas.recv.Interface() && recvOK == !cas.closed {
+					t.Fatalf("%s\nselected #%d, got %#v, %v, and DeepEqual is broken on %T", fmtSelect(info), i, recv.Interface(), recvOK, recv.Interface())
+				}
+				t.Fatalf("%s\nselected #%d but got %#v, %v, want %#v, %v", fmtSelect(info), i, recv.Interface(), recvOK, cas.recv.Interface(), !cas.closed)
+			}
+		} else {
+			if recv.IsValid() || recvOK {
+				t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, Value{}, false)
+			}
+		}
+	}
+}
+
+// selectWatch and the selectWatcher are a watchdog mechanism for running Select.
+// If the selectWatcher notices that the select has been blocked for >1 second, it prints
+// an error describing the select and panics the entire test binary.
+var selectWatch struct {
+	sync.Mutex
+	once sync.Once
+	now  time.Time
+	info []caseInfo
+}
+
+func selectWatcher() {
+	for {
+		time.Sleep(1 * time.Second)
+		selectWatch.Lock()
+		if selectWatch.info != nil && time.Since(selectWatch.now) > 1*time.Second {
+			fmt.Fprintf(os.Stderr, "TestSelect:\n%s blocked indefinitely\n", fmtSelect(selectWatch.info))
+			panic("select stuck")
+		}
+		selectWatch.Unlock()
+	}
+}
+
+// runSelect runs a single select test.
+// It returns the values returned by Select but also returns
+// a panic value if the Select panics.
+func runSelect(cases []SelectCase, info []caseInfo) (chosen int, recv Value, recvOK bool, panicErr interface{}) {
+	defer func() {
+		panicErr = recover()
+
+		selectWatch.Lock()
+		selectWatch.info = nil
+		selectWatch.Unlock()
+	}()
+
+	selectWatch.Lock()
+	selectWatch.now = time.Now()
+	selectWatch.info = info
+	selectWatch.Unlock()
+
+	chosen, recv, recvOK = Select(cases)
+	return
+}
+
+// fmtSelect formats the information about a single select test.
+func fmtSelect(info []caseInfo) string {
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "\nselect {\n")
+	for i, cas := range info {
+		fmt.Fprintf(&buf, "%d: %s", i, cas.desc)
+		if cas.recv.IsValid() {
+			fmt.Fprintf(&buf, " val=%#v", cas.recv.Interface())
+		}
+		if cas.canSelect {
+			fmt.Fprintf(&buf, " canselect")
+		}
+		if cas.panic {
+			fmt.Fprintf(&buf, " panic")
+		}
+		fmt.Fprintf(&buf, "\n")
+	}
+	fmt.Fprintf(&buf, "}")
+	return buf.String()
+}
+
+type two [2]uintptr
+
+// Difficult test for function call because of
+// implicit padding between arguments.
+func dummy(b byte, c int, d byte, e two, f byte, g float32, h byte) (i byte, j int, k byte, l two, m byte, n float32, o byte) {
+	return b, c, d, e, f, g, h
+}
+
+func TestFunc(t *testing.T) {
+	ret := ValueOf(dummy).Call([]Value{
+		ValueOf(byte(10)),
+		ValueOf(20),
+		ValueOf(byte(30)),
+		ValueOf(two{40, 50}),
+		ValueOf(byte(60)),
+		ValueOf(float32(70)),
+		ValueOf(byte(80)),
+	})
+	if len(ret) != 7 {
+		t.Fatalf("Call returned %d values, want 7", len(ret))
+	}
+
+	i := byte(ret[0].Uint())
+	j := int(ret[1].Int())
+	k := byte(ret[2].Uint())
+	l := ret[3].Interface().(two)
+	m := byte(ret[4].Uint())
+	n := float32(ret[5].Float())
+	o := byte(ret[6].Uint())
+
+	if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
+		t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
+	}
+}
+
+type emptyStruct struct{}
+
+type nonEmptyStruct struct {
+	member int
+}
+
+func returnEmpty() emptyStruct {
+	return emptyStruct{}
+}
+
+func takesEmpty(e emptyStruct) {
+}
+
+func returnNonEmpty(i int) nonEmptyStruct {
+	return nonEmptyStruct{member: i}
+}
+
+func takesNonEmpty(n nonEmptyStruct) int {
+	return n.member
+}
+
+func TestCallWithStruct(t *testing.T) {
+	r := ValueOf(returnEmpty).Call(nil)
+	if len(r) != 1 || r[0].Type() != TypeOf(emptyStruct{}) {
+		t.Errorf("returning empty struct returned %#v instead", r)
+	}
+	r = ValueOf(takesEmpty).Call([]Value{ValueOf(emptyStruct{})})
+	if len(r) != 0 {
+		t.Errorf("takesEmpty returned values: %#v", r)
+	}
+	r = ValueOf(returnNonEmpty).Call([]Value{ValueOf(42)})
+	if len(r) != 1 || r[0].Type() != TypeOf(nonEmptyStruct{}) || r[0].Field(0).Int() != 42 {
+		t.Errorf("returnNonEmpty returned %#v", r)
+	}
+	r = ValueOf(takesNonEmpty).Call([]Value{ValueOf(nonEmptyStruct{member: 42})})
+	if len(r) != 1 || r[0].Type() != TypeOf(1) || r[0].Int() != 42 {
+		t.Errorf("takesNonEmpty returned %#v", r)
+	}
+}
+
+func TestMakeFunc(t *testing.T) {
+	f := dummy
+	fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })
+	ValueOf(&f).Elem().Set(fv)
+
+	// Call g with small arguments so that there is
+	// something predictable (and different from the
+	// correct results) in those positions on the stack.
+	g := dummy
+	g(1, 2, 3, two{4, 5}, 6, 7, 8)
+
+	// Call constructed function f.
+	i, j, k, l, m, n, o := f(10, 20, 30, two{40, 50}, 60, 70, 80)
+	if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
+		t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
+	}
+}
+
+func TestMakeFuncInterface(t *testing.T) {
+	fn := func(i int) int { return i }
+	incr := func(in []Value) []Value {
+		return []Value{ValueOf(int(in[0].Int() + 1))}
+	}
+	fv := MakeFunc(TypeOf(fn), incr)
+	ValueOf(&fn).Elem().Set(fv)
+	if r := fn(2); r != 3 {
+		t.Errorf("Call returned %d, want 3", r)
+	}
+	if r := fv.Call([]Value{ValueOf(14)})[0].Int(); r != 15 {
+		t.Errorf("Call returned %d, want 15", r)
+	}
+	if r := fv.Interface().(func(int) int)(26); r != 27 {
+		t.Errorf("Call returned %d, want 27", r)
+	}
+}
+
+func TestMakeFuncVariadic(t *testing.T) {
+	// Test that variadic arguments are packed into a slice and passed as last arg
+	fn := func(_ int, is ...int) []int { return nil }
+	fv := MakeFunc(TypeOf(fn), func(in []Value) []Value { return in[1:2] })
+	ValueOf(&fn).Elem().Set(fv)
+
+	r := fn(1, 2, 3)
+	if r[0] != 2 || r[1] != 3 {
+		t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+	}
+
+	r = fn(1, []int{2, 3}...)
+	if r[0] != 2 || r[1] != 3 {
+		t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+	}
+
+	r = fv.Call([]Value{ValueOf(1), ValueOf(2), ValueOf(3)})[0].Interface().([]int)
+	if r[0] != 2 || r[1] != 3 {
+		t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+	}
+
+	r = fv.CallSlice([]Value{ValueOf(1), ValueOf([]int{2, 3})})[0].Interface().([]int)
+	if r[0] != 2 || r[1] != 3 {
+		t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+	}
+
+	f := fv.Interface().(func(int, ...int) []int)
+
+	r = f(1, 2, 3)
+	if r[0] != 2 || r[1] != 3 {
+		t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+	}
+	r = f(1, []int{2, 3}...)
+	if r[0] != 2 || r[1] != 3 {
+		t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+	}
+}
+
+type Point struct {
+	x, y int
+}
+
+// This will be index 0.
+func (p Point) AnotherMethod(scale int) int {
+	return -1
+}
+
+// This will be index 1.
+func (p Point) Dist(scale int) int {
+	//println("Point.Dist", p.x, p.y, scale)
+	return p.x*p.x*scale + p.y*p.y*scale
+}
+
+// This will be index 2.
+func (p Point) GCMethod(k int) int {
+	runtime.GC()
+	return k + p.x
+}
+
+// This will be index 3.
+func (p Point) TotalDist(points ...Point) int {
+	tot := 0
+	for _, q := range points {
+		dx := q.x - p.x
+		dy := q.y - p.y
+		tot += dx*dx + dy*dy // Should call Sqrt, but it's just a test.
+
+	}
+	return tot
+}
+
+func TestMethod(t *testing.T) {
+	// Non-curried method of type.
+	p := Point{3, 4}
+	i := TypeOf(p).Method(1).Func.Call([]Value{ValueOf(p), ValueOf(10)})[0].Int()
+	if i != 250 {
+		t.Errorf("Type Method returned %d; want 250", i)
+	}
+
+	m, ok := TypeOf(p).MethodByName("Dist")
+	if !ok {
+		t.Fatalf("method by name failed")
+	}
+	i = m.Func.Call([]Value{ValueOf(p), ValueOf(11)})[0].Int()
+	if i != 275 {
+		t.Errorf("Type MethodByName returned %d; want 275", i)
+	}
+
+	i = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(12)})[0].Int()
+	if i != 300 {
+		t.Errorf("Pointer Type Method returned %d; want 300", i)
+	}
+
+	m, ok = TypeOf(&p).MethodByName("Dist")
+	if !ok {
+		t.Fatalf("ptr method by name failed")
+	}
+	i = m.Func.Call([]Value{ValueOf(&p), ValueOf(13)})[0].Int()
+	if i != 325 {
+		t.Errorf("Pointer Type MethodByName returned %d; want 325", i)
+	}
+
+	// Curried method of value.
+	tfunc := TypeOf((func(int) int)(nil))
+	v := ValueOf(p).Method(1)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(14)})[0].Int()
+	if i != 350 {
+		t.Errorf("Value Method returned %d; want 350", i)
+	}
+	v = ValueOf(p).MethodByName("Dist")
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(15)})[0].Int()
+	if i != 375 {
+		t.Errorf("Value MethodByName returned %d; want 375", i)
+	}
+
+	// Curried method of pointer.
+	v = ValueOf(&p).Method(1)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(16)})[0].Int()
+	if i != 400 {
+		t.Errorf("Pointer Value Method returned %d; want 400", i)
+	}
+	v = ValueOf(&p).MethodByName("Dist")
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(17)})[0].Int()
+	if i != 425 {
+		t.Errorf("Pointer Value MethodByName returned %d; want 425", i)
+	}
+
+	// Curried method of interface value.
+	// Have to wrap interface value in a struct to get at it.
+	// Passing it to ValueOf directly would
+	// access the underlying Point, not the interface.
+	var x interface {
+		Dist(int) int
+	} = p
+	pv := ValueOf(&x).Elem()
+	v = pv.Method(0)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(18)})[0].Int()
+	if i != 450 {
+		t.Errorf("Interface Method returned %d; want 450", i)
+	}
+	v = pv.MethodByName("Dist")
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(19)})[0].Int()
+	if i != 475 {
+		t.Errorf("Interface MethodByName returned %d; want 475", i)
+	}
+}
+
+func TestMethodValue(t *testing.T) {
+	p := Point{3, 4}
+	var i int64
+
+	// Curried method of value.
+	tfunc := TypeOf((func(int) int)(nil))
+	v := ValueOf(p).Method(1)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
+	}
+	i = ValueOf(v.Interface()).Call([]Value{ValueOf(10)})[0].Int()
+	if i != 250 {
+		t.Errorf("Value Method returned %d; want 250", i)
+	}
+	v = ValueOf(p).MethodByName("Dist")
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc)
+	}
+	i = ValueOf(v.Interface()).Call([]Value{ValueOf(11)})[0].Int()
+	if i != 275 {
+		t.Errorf("Value MethodByName returned %d; want 275", i)
+	}
+
+	// Curried method of pointer.
+	v = ValueOf(&p).Method(1)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc)
+	}
+	i = ValueOf(v.Interface()).Call([]Value{ValueOf(12)})[0].Int()
+	if i != 300 {
+		t.Errorf("Pointer Value Method returned %d; want 300", i)
+	}
+	v = ValueOf(&p).MethodByName("Dist")
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
+	}
+	i = ValueOf(v.Interface()).Call([]Value{ValueOf(13)})[0].Int()
+	if i != 325 {
+		t.Errorf("Pointer Value MethodByName returned %d; want 325", i)
+	}
+
+	// Curried method of pointer to pointer.
+	pp := &p
+	v = ValueOf(&pp).Elem().Method(1)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Pointer Pointer Value Method Type is %s; want %s", tt, tfunc)
+	}
+	i = ValueOf(v.Interface()).Call([]Value{ValueOf(14)})[0].Int()
+	if i != 350 {
+		t.Errorf("Pointer Pointer Value Method returned %d; want 350", i)
+	}
+	v = ValueOf(&pp).Elem().MethodByName("Dist")
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Pointer Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
+	}
+	i = ValueOf(v.Interface()).Call([]Value{ValueOf(15)})[0].Int()
+	if i != 375 {
+		t.Errorf("Pointer Pointer Value MethodByName returned %d; want 375", i)
+	}
+
+	// Curried method of interface value.
+	// Have to wrap interface value in a struct to get at it.
+	// Passing it to ValueOf directly would
+	// access the underlying Point, not the interface.
+	var s = struct {
+		X interface {
+			Dist(int) int
+		}
+	}{p}
+	pv := ValueOf(s).Field(0)
+	v = pv.Method(0)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
+	}
+	i = ValueOf(v.Interface()).Call([]Value{ValueOf(16)})[0].Int()
+	if i != 400 {
+		t.Errorf("Interface Method returned %d; want 400", i)
+	}
+	v = pv.MethodByName("Dist")
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
+	}
+	i = ValueOf(v.Interface()).Call([]Value{ValueOf(17)})[0].Int()
+	if i != 425 {
+		t.Errorf("Interface MethodByName returned %d; want 425", i)
+	}
+}
+
+func TestVariadicMethodValue(t *testing.T) {
+	p := Point{3, 4}
+	points := []Point{{20, 21}, {22, 23}, {24, 25}}
+	want := int64(p.TotalDist(points[0], points[1], points[2]))
+
+	// Curried method of value.
+	tfunc := TypeOf((func(...Point) int)(nil))
+	v := ValueOf(p).Method(3)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Variadic Method Type is %s; want %s", tt, tfunc)
+	}
+	i := ValueOf(v.Interface()).Call([]Value{ValueOf(points[0]), ValueOf(points[1]), ValueOf(points[2])})[0].Int()
+	if i != want {
+		t.Errorf("Variadic Method returned %d; want %d", i, want)
+	}
+	i = ValueOf(v.Interface()).CallSlice([]Value{ValueOf(points)})[0].Int()
+	if i != want {
+		t.Errorf("Variadic Method CallSlice returned %d; want %d", i, want)
+	}
+
+	f := v.Interface().(func(...Point) int)
+	i = int64(f(points[0], points[1], points[2]))
+	if i != want {
+		t.Errorf("Variadic Method Interface returned %d; want %d", i, want)
+	}
+	i = int64(f(points...))
+	if i != want {
+		t.Errorf("Variadic Method Interface Slice returned %d; want %d", i, want)
+	}
+}
+
+// Reflect version of $GOROOT/test/method5.go
+
+// Concrete types implementing M method.
+// Smaller than a word, word-sized, larger than a word.
+// Value and pointer receivers.
+
+type Tinter interface {
+	M(int, byte) (byte, int)
+}
+
+type Tsmallv byte
+
+func (v Tsmallv) M(x int, b byte) (byte, int) { return b, x + int(v) }
+
+type Tsmallp byte
+
+func (p *Tsmallp) M(x int, b byte) (byte, int) { return b, x + int(*p) }
+
+type Twordv uintptr
+
+func (v Twordv) M(x int, b byte) (byte, int) { return b, x + int(v) }
+
+type Twordp uintptr
+
+func (p *Twordp) M(x int, b byte) (byte, int) { return b, x + int(*p) }
+
+type Tbigv [2]uintptr
+
+func (v Tbigv) M(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) }
+
+type Tbigp [2]uintptr
+
+func (p *Tbigp) M(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }
+
+// Again, with an unexported method.
+
+type tsmallv byte
+
+func (v tsmallv) m(x int, b byte) (byte, int) { return b, x + int(v) }
+
+type tsmallp byte
+
+func (p *tsmallp) m(x int, b byte) (byte, int) { return b, x + int(*p) }
+
+type twordv uintptr
+
+func (v twordv) m(x int, b byte) (byte, int) { return b, x + int(v) }
+
+type twordp uintptr
+
+func (p *twordp) m(x int, b byte) (byte, int) { return b, x + int(*p) }
+
+type tbigv [2]uintptr
+
+func (v tbigv) m(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) }
+
+type tbigp [2]uintptr
+
+func (p *tbigp) m(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }
+
+type tinter interface {
+	m(int, byte) (byte, int)
+}
+
+// Embedding via pointer.
+
+type Tm1 struct {
+	Tm2
+}
+
+type Tm2 struct {
+	*Tm3
+}
+
+type Tm3 struct {
+	*Tm4
+}
+
+type Tm4 struct {
+}
+
+func (t4 Tm4) M(x int, b byte) (byte, int) { return b, x + 40 }
+
+func TestMethod5(t *testing.T) {
+	CheckF := func(name string, f func(int, byte) (byte, int), inc int) {
+		b, x := f(1000, 99)
+		if b != 99 || x != 1000+inc {
+			t.Errorf("%s(1000, 99) = %v, %v, want 99, %v", name, b, x, 1000+inc)
+		}
+	}
+
+	CheckV := func(name string, i Value, inc int) {
+		bx := i.Method(0).Call([]Value{ValueOf(1000), ValueOf(byte(99))})
+		b := bx[0].Interface()
+		x := bx[1].Interface()
+		if b != byte(99) || x != 1000+inc {
+			t.Errorf("direct %s.M(1000, 99) = %v, %v, want 99, %v", name, b, x, 1000+inc)
+		}
+
+		CheckF(name+".M", i.Method(0).Interface().(func(int, byte) (byte, int)), inc)
+	}
+
+	var TinterType = TypeOf(new(Tinter)).Elem()
+	var tinterType = TypeOf(new(tinter)).Elem()
+
+	CheckI := func(name string, i interface{}, inc int) {
+		v := ValueOf(i)
+		CheckV(name, v, inc)
+		CheckV("(i="+name+")", v.Convert(TinterType), inc)
+	}
+
+	sv := Tsmallv(1)
+	CheckI("sv", sv, 1)
+	CheckI("&sv", &sv, 1)
+
+	sp := Tsmallp(2)
+	CheckI("&sp", &sp, 2)
+
+	wv := Twordv(3)
+	CheckI("wv", wv, 3)
+	CheckI("&wv", &wv, 3)
+
+	wp := Twordp(4)
+	CheckI("&wp", &wp, 4)
+
+	bv := Tbigv([2]uintptr{5, 6})
+	CheckI("bv", bv, 11)
+	CheckI("&bv", &bv, 11)
+
+	bp := Tbigp([2]uintptr{7, 8})
+	CheckI("&bp", &bp, 15)
+
+	t4 := Tm4{}
+	t3 := Tm3{&t4}
+	t2 := Tm2{&t3}
+	t1 := Tm1{t2}
+	CheckI("t4", t4, 40)
+	CheckI("&t4", &t4, 40)
+	CheckI("t3", t3, 40)
+	CheckI("&t3", &t3, 40)
+	CheckI("t2", t2, 40)
+	CheckI("&t2", &t2, 40)
+	CheckI("t1", t1, 40)
+	CheckI("&t1", &t1, 40)
+
+	methodShouldPanic := func(name string, i interface{}) {
+		v := ValueOf(i)
+		m := v.Method(0)
+		shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) })
+		shouldPanic(func() { m.Interface() })
+
+		v = v.Convert(tinterType)
+		m = v.Method(0)
+		shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) })
+		shouldPanic(func() { m.Interface() })
+	}
+
+	_sv := tsmallv(1)
+	methodShouldPanic("_sv", _sv)
+	methodShouldPanic("&_sv", &_sv)
+
+	_sp := tsmallp(2)
+	methodShouldPanic("&_sp", &_sp)
+
+	_wv := twordv(3)
+	methodShouldPanic("_wv", _wv)
+	methodShouldPanic("&_wv", &_wv)
+
+	_wp := twordp(4)
+	methodShouldPanic("&_wp", &_wp)
+
+	_bv := tbigv([2]uintptr{5, 6})
+	methodShouldPanic("_bv", _bv)
+	methodShouldPanic("&_bv", &_bv)
+
+	_bp := tbigp([2]uintptr{7, 8})
+	methodShouldPanic("&_bp", &_bp)
+
+	var tnil Tinter
+	vnil := ValueOf(&tnil).Elem()
+	shouldPanic(func() { vnil.Method(0) })
+}
+
+func TestInterfaceSet(t *testing.T) {
+	p := &Point{3, 4}
+
+	var s struct {
+		I interface{}
+		P interface {
+			Dist(int) int
+		}
+	}
+	sv := ValueOf(&s).Elem()
+	sv.Field(0).Set(ValueOf(p))
+	if q := s.I.(*Point); q != p {
+		t.Errorf("i: have %p want %p", q, p)
+	}
+
+	pv := sv.Field(1)
+	pv.Set(ValueOf(p))
+	if q := s.P.(*Point); q != p {
+		t.Errorf("i: have %p want %p", q, p)
+	}
+
+	i := pv.Method(0).Call([]Value{ValueOf(10)})[0].Int()
+	if i != 250 {
+		t.Errorf("Interface Method returned %d; want 250", i)
+	}
+}
+
+type T1 struct {
+	a string
+	int
+}
+
+func TestAnonymousFields(t *testing.T) {
+	var field StructField
+	var ok bool
+	var t1 T1
+	type1 := TypeOf(t1)
+	if field, ok = type1.FieldByName("int"); !ok {
+		t.Fatal("no field 'int'")
+	}
+	if field.Index[0] != 1 {
+		t.Error("field index should be 1; is", field.Index)
+	}
+}
+
+type FTest struct {
+	s     interface{}
+	name  string
+	index []int
+	value int
+}
+
+type D1 struct {
+	d int
+}
+type D2 struct {
+	d int
+}
+
+type S0 struct {
+	A, B, C int
+	D1
+	D2
+}
+
+type S1 struct {
+	B int
+	S0
+}
+
+type S2 struct {
+	A int
+	*S1
+}
+
+type S1x struct {
+	S1
+}
+
+type S1y struct {
+	S1
+}
+
+type S3 struct {
+	S1x
+	S2
+	D, E int
+	*S1y
+}
+
+type S4 struct {
+	*S4
+	A int
+}
+
+// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
+type S5 struct {
+	S6
+	S7
+	S8
+}
+
+type S6 struct {
+	X int
+}
+
+type S7 S6
+
+type S8 struct {
+	S9
+}
+
+type S9 struct {
+	X int
+	Y int
+}
+
+// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
+type S10 struct {
+	S11
+	S12
+	S13
+}
+
+type S11 struct {
+	S6
+}
+
+type S12 struct {
+	S6
+}
+
+type S13 struct {
+	S8
+}
+
+// The X in S15.S11.S1 and S16.S11.S1 annihilate.
+type S14 struct {
+	S15
+	S16
+}
+
+type S15 struct {
+	S11
+}
+
+type S16 struct {
+	S11
+}
+
+var fieldTests = []FTest{
+	{struct{}{}, "", nil, 0},
+	{struct{}{}, "Foo", nil, 0},
+	{S0{A: 'a'}, "A", []int{0}, 'a'},
+	{S0{}, "D", nil, 0},
+	{S1{S0: S0{A: 'a'}}, "A", []int{1, 0}, 'a'},
+	{S1{B: 'b'}, "B", []int{0}, 'b'},
+	{S1{}, "S0", []int{1}, 0},
+	{S1{S0: S0{C: 'c'}}, "C", []int{1, 2}, 'c'},
+	{S2{A: 'a'}, "A", []int{0}, 'a'},
+	{S2{}, "S1", []int{1}, 0},
+	{S2{S1: &S1{B: 'b'}}, "B", []int{1, 0}, 'b'},
+	{S2{S1: &S1{S0: S0{C: 'c'}}}, "C", []int{1, 1, 2}, 'c'},
+	{S2{}, "D", nil, 0},
+	{S3{}, "S1", nil, 0},
+	{S3{S2: S2{A: 'a'}}, "A", []int{1, 0}, 'a'},
+	{S3{}, "B", nil, 0},
+	{S3{D: 'd'}, "D", []int{2}, 0},
+	{S3{E: 'e'}, "E", []int{3}, 'e'},
+	{S4{A: 'a'}, "A", []int{1}, 'a'},
+	{S4{}, "B", nil, 0},
+	{S5{}, "X", nil, 0},
+	{S5{}, "Y", []int{2, 0, 1}, 0},
+	{S10{}, "X", nil, 0},
+	{S10{}, "Y", []int{2, 0, 0, 1}, 0},
+	{S14{}, "X", nil, 0},
+}
+
+func TestFieldByIndex(t *testing.T) {
+	for _, test := range fieldTests {
+		s := TypeOf(test.s)
+		f := s.FieldByIndex(test.index)
+		if f.Name != "" {
+			if test.index != nil {
+				if f.Name != test.name {
+					t.Errorf("%s.%s found; want %s", s.Name(), f.Name, test.name)
+				}
+			} else {
+				t.Errorf("%s.%s found", s.Name(), f.Name)
+			}
+		} else if len(test.index) > 0 {
+			t.Errorf("%s.%s not found", s.Name(), test.name)
+		}
+
+		if test.value != 0 {
+			v := ValueOf(test.s).FieldByIndex(test.index)
+			if v.IsValid() {
+				if x, ok := v.Interface().(int); ok {
+					if x != test.value {
+						t.Errorf("%s%v is %d; want %d", s.Name(), test.index, x, test.value)
+					}
+				} else {
+					t.Errorf("%s%v value not an int", s.Name(), test.index)
+				}
+			} else {
+				t.Errorf("%s%v value not found", s.Name(), test.index)
+			}
+		}
+	}
+}
+
+func TestFieldByName(t *testing.T) {
+	for _, test := range fieldTests {
+		s := TypeOf(test.s)
+		f, found := s.FieldByName(test.name)
+		if found {
+			if test.index != nil {
+				// Verify field depth and index.
+				if len(f.Index) != len(test.index) {
+					t.Errorf("%s.%s depth %d; want %d: %v vs %v", s.Name(), test.name, len(f.Index), len(test.index), f.Index, test.index)
+				} else {
+					for i, x := range f.Index {
+						if x != test.index[i] {
+							t.Errorf("%s.%s.Index[%d] is %d; want %d", s.Name(), test.name, i, x, test.index[i])
+						}
+					}
+				}
+			} else {
+				t.Errorf("%s.%s found", s.Name(), f.Name)
+			}
+		} else if len(test.index) > 0 {
+			t.Errorf("%s.%s not found", s.Name(), test.name)
+		}
+
+		if test.value != 0 {
+			v := ValueOf(test.s).FieldByName(test.name)
+			if v.IsValid() {
+				if x, ok := v.Interface().(int); ok {
+					if x != test.value {
+						t.Errorf("%s.%s is %d; want %d", s.Name(), test.name, x, test.value)
+					}
+				} else {
+					t.Errorf("%s.%s value not an int", s.Name(), test.name)
+				}
+			} else {
+				t.Errorf("%s.%s value not found", s.Name(), test.name)
+			}
+		}
+	}
+}
+
+func TestImportPath(t *testing.T) {
+	tests := []struct {
+		t    Type
+		path string
+	}{
+		{TypeOf(&base64.Encoding{}).Elem(), "encoding/base64"},
+		{TypeOf(int(0)), ""},
+		{TypeOf(int8(0)), ""},
+		{TypeOf(int16(0)), ""},
+		{TypeOf(int32(0)), ""},
+		{TypeOf(int64(0)), ""},
+		{TypeOf(uint(0)), ""},
+		{TypeOf(uint8(0)), ""},
+		{TypeOf(uint16(0)), ""},
+		{TypeOf(uint32(0)), ""},
+		{TypeOf(uint64(0)), ""},
+		{TypeOf(uintptr(0)), ""},
+		{TypeOf(float32(0)), ""},
+		{TypeOf(float64(0)), ""},
+		{TypeOf(complex64(0)), ""},
+		{TypeOf(complex128(0)), ""},
+		{TypeOf(byte(0)), ""},
+		{TypeOf(rune(0)), ""},
+		{TypeOf([]byte(nil)), ""},
+		{TypeOf([]rune(nil)), ""},
+		{TypeOf(string("")), ""},
+		{TypeOf((*interface{})(nil)).Elem(), ""},
+		{TypeOf((*byte)(nil)), ""},
+		{TypeOf((*rune)(nil)), ""},
+		{TypeOf((*int64)(nil)), ""},
+		{TypeOf(map[string]int{}), ""},
+		{TypeOf((*error)(nil)).Elem(), ""},
+	}
+	for _, test := range tests {
+		if path := test.t.PkgPath(); path != test.path {
+			t.Errorf("%v.PkgPath() = %q, want %q", test.t, path, test.path)
+		}
+	}
+}
+
+func TestVariadicType(t *testing.T) {
+	// Test example from Type documentation.
+	var f func(x int, y ...float64)
+	typ := TypeOf(f)
+	if typ.NumIn() == 2 && typ.In(0) == TypeOf(int(0)) {
+		sl := typ.In(1)
+		if sl.Kind() == Slice {
+			if sl.Elem() == TypeOf(0.0) {
+				// ok
+				return
+			}
+		}
+	}
+
+	// Failed
+	t.Errorf("want NumIn() = 2, In(0) = int, In(1) = []float64")
+	s := fmt.Sprintf("have NumIn() = %d", typ.NumIn())
+	for i := 0; i < typ.NumIn(); i++ {
+		s += fmt.Sprintf(", In(%d) = %s", i, typ.In(i))
+	}
+	t.Error(s)
+}
+
+type inner struct {
+	x int
+}
+
+type outer struct {
+	y int
+	inner
+}
+
+func (*inner) m() {}
+func (*outer) m() {}
+
+func TestNestedMethods(t *testing.T) {
+	t.Skip("fails on gccgo due to function wrappers")
+	typ := TypeOf((*outer)(nil))
+	if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).m).Pointer() {
+		t.Errorf("Wrong method table for outer: (m=%p)", (*outer).m)
+		for i := 0; i < typ.NumMethod(); i++ {
+			m := typ.Method(i)
+			t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
+		}
+	}
+}
+
+type InnerInt struct {
+	X int
+}
+
+type OuterInt struct {
+	Y int
+	InnerInt
+}
+
+func (i *InnerInt) M() int {
+	return i.X
+}
+
+func TestEmbeddedMethods(t *testing.T) {
+	/* This part of the test fails on gccgo due to function wrappers.
+	typ := TypeOf((*OuterInt)(nil))
+	if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*OuterInt).M).Pointer() {
+		t.Errorf("Wrong method table for OuterInt: (m=%p)", (*OuterInt).M)
+		for i := 0; i < typ.NumMethod(); i++ {
+			m := typ.Method(i)
+			t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
+		}
+	}
+	*/
+
+	i := &InnerInt{3}
+	if v := ValueOf(i).Method(0).Call(nil)[0].Int(); v != 3 {
+		t.Errorf("i.M() = %d, want 3", v)
+	}
+
+	o := &OuterInt{1, InnerInt{2}}
+	if v := ValueOf(o).Method(0).Call(nil)[0].Int(); v != 2 {
+		t.Errorf("i.M() = %d, want 2", v)
+	}
+
+	f := (*OuterInt).M
+	if v := f(o); v != 2 {
+		t.Errorf("f(o) = %d, want 2", v)
+	}
+}
+
+func TestPtrTo(t *testing.T) {
+	var i int
+
+	typ := TypeOf(i)
+	for i = 0; i < 100; i++ {
+		typ = PtrTo(typ)
+	}
+	for i = 0; i < 100; i++ {
+		typ = typ.Elem()
+	}
+	if typ != TypeOf(i) {
+		t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(i))
+	}
+}
+
+func TestPtrToGC(t *testing.T) {
+	type T *uintptr
+	tt := TypeOf(T(nil))
+	pt := PtrTo(tt)
+	const n = 100
+	var x []interface{}
+	for i := 0; i < n; i++ {
+		v := New(pt)
+		p := new(*uintptr)
+		*p = new(uintptr)
+		**p = uintptr(i)
+		v.Elem().Set(ValueOf(p).Convert(pt))
+		x = append(x, v.Interface())
+	}
+	runtime.GC()
+
+	for i, xi := range x {
+		k := ValueOf(xi).Elem().Elem().Elem().Interface().(uintptr)
+		if k != uintptr(i) {
+			t.Errorf("lost x[%d] = %d, want %d", i, k, i)
+		}
+	}
+}
+
+func TestAddr(t *testing.T) {
+	var p struct {
+		X, Y int
+	}
+
+	v := ValueOf(&p)
+	v = v.Elem()
+	v = v.Addr()
+	v = v.Elem()
+	v = v.Field(0)
+	v.SetInt(2)
+	if p.X != 2 {
+		t.Errorf("Addr.Elem.Set failed to set value")
+	}
+
+	// Again but take address of the ValueOf value.
+	// Exercises generation of PtrTypes not present in the binary.
+	q := &p
+	v = ValueOf(&q).Elem()
+	v = v.Addr()
+	v = v.Elem()
+	v = v.Elem()
+	v = v.Addr()
+	v = v.Elem()
+	v = v.Field(0)
+	v.SetInt(3)
+	if p.X != 3 {
+		t.Errorf("Addr.Elem.Set failed to set value")
+	}
+
+	// Starting without pointer we should get changed value
+	// in interface.
+	qq := p
+	v = ValueOf(&qq).Elem()
+	v0 := v
+	v = v.Addr()
+	v = v.Elem()
+	v = v.Field(0)
+	v.SetInt(4)
+	if p.X != 3 { // should be unchanged from last time
+		t.Errorf("somehow value Set changed original p")
+	}
+	p = v0.Interface().(struct {
+		X, Y int
+	})
+	if p.X != 4 {
+		t.Errorf("Addr.Elem.Set valued to set value in top value")
+	}
+
+	// Verify that taking the address of a type gives us a pointer
+	// which we can convert back using the usual interface
+	// notation.
+	var s struct {
+		B *bool
+	}
+	ps := ValueOf(&s).Elem().Field(0).Addr().Interface()
+	*(ps.(**bool)) = new(bool)
+	if s.B == nil {
+		t.Errorf("Addr.Interface direct assignment failed")
+	}
+}
+
+/* gccgo does do allocations here.
+
+func noAlloc(t *testing.T, n int, f func(int)) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Skip("skipping; GOMAXPROCS>1")
+	}
+	i := -1
+	allocs := testing.AllocsPerRun(n, func() {
+		f(i)
+		i++
+	})
+	if allocs > 0 {
+		t.Errorf("%d iterations: got %v mallocs, want 0", n, allocs)
+	}
+}
+
+func TestAllocations(t *testing.T) {
+	noAlloc(t, 100, func(j int) {
+		var i interface{}
+		var v Value
+		i = 42 + j
+		v = ValueOf(i)
+		if int(v.Int()) != 42+j {
+			panic("wrong int")
+		}
+	})
+}
+
+*/
+
+func TestSmallNegativeInt(t *testing.T) {
+	i := int16(-1)
+	v := ValueOf(i)
+	if v.Int() != -1 {
+		t.Errorf("int16(-1).Int() returned %v", v.Int())
+	}
+}
+
+func TestIndex(t *testing.T) {
+	xs := []byte{1, 2, 3, 4, 5, 6, 7, 8}
+	v := ValueOf(xs).Index(3).Interface().(byte)
+	if v != xs[3] {
+		t.Errorf("xs.Index(3) = %v; expected %v", v, xs[3])
+	}
+	xa := [8]byte{10, 20, 30, 40, 50, 60, 70, 80}
+	v = ValueOf(xa).Index(2).Interface().(byte)
+	if v != xa[2] {
+		t.Errorf("xa.Index(2) = %v; expected %v", v, xa[2])
+	}
+	s := "0123456789"
+	v = ValueOf(s).Index(3).Interface().(byte)
+	if v != s[3] {
+		t.Errorf("s.Index(3) = %v; expected %v", v, s[3])
+	}
+}
+
+func TestSlice(t *testing.T) {
+	xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
+	v := ValueOf(xs).Slice(3, 5).Interface().([]int)
+	if len(v) != 2 {
+		t.Errorf("len(xs.Slice(3, 5)) = %d", len(v))
+	}
+	if cap(v) != 5 {
+		t.Errorf("cap(xs.Slice(3, 5)) = %d", cap(v))
+	}
+	if !DeepEqual(v[0:5], xs[3:]) {
+		t.Errorf("xs.Slice(3, 5)[0:5] = %v", v[0:5])
+	}
+	xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
+	v = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int)
+	if len(v) != 3 {
+		t.Errorf("len(xa.Slice(2, 5)) = %d", len(v))
+	}
+	if cap(v) != 6 {
+		t.Errorf("cap(xa.Slice(2, 5)) = %d", cap(v))
+	}
+	if !DeepEqual(v[0:6], xa[2:]) {
+		t.Errorf("xs.Slice(2, 5)[0:6] = %v", v[0:6])
+	}
+	s := "0123456789"
+	vs := ValueOf(s).Slice(3, 5).Interface().(string)
+	if vs != s[3:5] {
+		t.Errorf("s.Slice(3, 5) = %q; expected %q", vs, s[3:5])
+	}
+}
+
+func TestSlice3(t *testing.T) {
+	xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
+	v := ValueOf(xs).Slice3(3, 5, 7).Interface().([]int)
+	if len(v) != 2 {
+		t.Errorf("len(xs.Slice3(3, 5, 7)) = %d", len(v))
+	}
+	if cap(v) != 4 {
+		t.Errorf("cap(xs.Slice3(3, 5, 7)) = %d", cap(v))
+	}
+	if !DeepEqual(v[0:4], xs[3:7:7]) {
+		t.Errorf("xs.Slice3(3, 5, 7)[0:4] = %v", v[0:4])
+	}
+	rv := ValueOf(&xs).Elem()
+	shouldPanic(func() { rv.Slice3(1, 2, 1) })
+	shouldPanic(func() { rv.Slice3(1, 1, 11) })
+	shouldPanic(func() { rv.Slice3(2, 2, 1) })
+
+	xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
+	v = ValueOf(&xa).Elem().Slice3(2, 5, 6).Interface().([]int)
+	if len(v) != 3 {
+		t.Errorf("len(xa.Slice(2, 5, 6)) = %d", len(v))
+	}
+	if cap(v) != 4 {
+		t.Errorf("cap(xa.Slice(2, 5, 6)) = %d", cap(v))
+	}
+	if !DeepEqual(v[0:4], xa[2:6:6]) {
+		t.Errorf("xs.Slice(2, 5, 6)[0:4] = %v", v[0:4])
+	}
+	rv = ValueOf(&xa).Elem()
+	shouldPanic(func() { rv.Slice3(1, 2, 1) })
+	shouldPanic(func() { rv.Slice3(1, 1, 11) })
+	shouldPanic(func() { rv.Slice3(2, 2, 1) })
+
+	s := "hello world"
+	rv = ValueOf(&s).Elem()
+	shouldPanic(func() { rv.Slice3(1, 2, 3) })
+}
+
+func TestSetLenCap(t *testing.T) {
+	xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
+	xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
+
+	vs := ValueOf(&xs).Elem()
+	shouldPanic(func() { vs.SetLen(10) })
+	shouldPanic(func() { vs.SetCap(10) })
+	shouldPanic(func() { vs.SetLen(-1) })
+	shouldPanic(func() { vs.SetCap(-1) })
+	shouldPanic(func() { vs.SetCap(6) }) // smaller than len
+	vs.SetLen(5)
+	if len(xs) != 5 || cap(xs) != 8 {
+		t.Errorf("after SetLen(5), len, cap = %d, %d, want 5, 8", len(xs), cap(xs))
+	}
+	vs.SetCap(6)
+	if len(xs) != 5 || cap(xs) != 6 {
+		t.Errorf("after SetCap(6), len, cap = %d, %d, want 5, 6", len(xs), cap(xs))
+	}
+	vs.SetCap(5)
+	if len(xs) != 5 || cap(xs) != 5 {
+		t.Errorf("after SetCap(5), len, cap = %d, %d, want 5, 5", len(xs), cap(xs))
+	}
+	shouldPanic(func() { vs.SetCap(4) }) // smaller than len
+	shouldPanic(func() { vs.SetLen(6) }) // bigger than cap
+
+	va := ValueOf(&xa).Elem()
+	shouldPanic(func() { va.SetLen(8) })
+	shouldPanic(func() { va.SetCap(8) })
+}
+
+func TestVariadic(t *testing.T) {
+	var b bytes.Buffer
+	V := ValueOf
+
+	b.Reset()
+	V(fmt.Fprintf).Call([]Value{V(&b), V("%s, %d world"), V("hello"), V(42)})
+	if b.String() != "hello, 42 world" {
+		t.Errorf("after Fprintf Call: %q != %q", b.String(), "hello 42 world")
+	}
+
+	b.Reset()
+	V(fmt.Fprintf).CallSlice([]Value{V(&b), V("%s, %d world"), V([]interface{}{"hello", 42})})
+	if b.String() != "hello, 42 world" {
+		t.Errorf("after Fprintf CallSlice: %q != %q", b.String(), "hello 42 world")
+	}
+}
+
+func TestFuncArg(t *testing.T) {
+	f1 := func(i int, f func(int) int) int { return f(i) }
+	f2 := func(i int) int { return i + 1 }
+	r := ValueOf(f1).Call([]Value{ValueOf(100), ValueOf(f2)})
+	if r[0].Int() != 101 {
+		t.Errorf("function returned %d, want 101", r[0].Int())
+	}
+}
+
+var tagGetTests = []struct {
+	Tag   StructTag
+	Key   string
+	Value string
+}{
+	{`protobuf:"PB(1,2)"`, `protobuf`, `PB(1,2)`},
+	{`protobuf:"PB(1,2)"`, `foo`, ``},
+	{`protobuf:"PB(1,2)"`, `rotobuf`, ``},
+	{`protobuf:"PB(1,2)" json:"name"`, `json`, `name`},
+	{`protobuf:"PB(1,2)" json:"name"`, `protobuf`, `PB(1,2)`},
+}
+
+func TestTagGet(t *testing.T) {
+	for _, tt := range tagGetTests {
+		if v := tt.Tag.Get(tt.Key); v != tt.Value {
+			t.Errorf("StructTag(%#q).Get(%#q) = %#q, want %#q", tt.Tag, tt.Key, v, tt.Value)
+		}
+	}
+}
+
+func TestBytes(t *testing.T) {
+	type B []byte
+	x := B{1, 2, 3, 4}
+	y := ValueOf(x).Bytes()
+	if !bytes.Equal(x, y) {
+		t.Fatalf("ValueOf(%v).Bytes() = %v", x, y)
+	}
+	if &x[0] != &y[0] {
+		t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
+	}
+}
+
+func TestSetBytes(t *testing.T) {
+	type B []byte
+	var x B
+	y := []byte{1, 2, 3, 4}
+	ValueOf(&x).Elem().SetBytes(y)
+	if !bytes.Equal(x, y) {
+		t.Fatalf("ValueOf(%v).Bytes() = %v", x, y)
+	}
+	if &x[0] != &y[0] {
+		t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
+	}
+}
+
+type Private struct {
+	x int
+	y **int
+}
+
+func (p *Private) m() {
+}
+
+type Public struct {
+	X int
+	Y **int
+}
+
+func (p *Public) M() {
+}
+
+func TestUnexported(t *testing.T) {
+	var pub Public
+	v := ValueOf(&pub)
+	isValid(v.Elem().Field(0))
+	isValid(v.Elem().Field(1))
+	isValid(v.Elem().FieldByName("X"))
+	isValid(v.Elem().FieldByName("Y"))
+	isValid(v.Type().Method(0).Func)
+	isNonNil(v.Elem().Field(0).Interface())
+	isNonNil(v.Elem().Field(1).Interface())
+	isNonNil(v.Elem().FieldByName("X").Interface())
+	isNonNil(v.Elem().FieldByName("Y").Interface())
+	isNonNil(v.Type().Method(0).Func.Interface())
+
+	var priv Private
+	v = ValueOf(&priv)
+	isValid(v.Elem().Field(0))
+	isValid(v.Elem().Field(1))
+	isValid(v.Elem().FieldByName("x"))
+	isValid(v.Elem().FieldByName("y"))
+	isValid(v.Type().Method(0).Func)
+	shouldPanic(func() { v.Elem().Field(0).Interface() })
+	shouldPanic(func() { v.Elem().Field(1).Interface() })
+	shouldPanic(func() { v.Elem().FieldByName("x").Interface() })
+	shouldPanic(func() { v.Elem().FieldByName("y").Interface() })
+	shouldPanic(func() { v.Type().Method(0).Func.Interface() })
+}
+
+func shouldPanic(f func()) {
+	defer func() {
+		if recover() == nil {
+			panic("did not panic")
+		}
+	}()
+	f()
+}
+
+func isNonNil(x interface{}) {
+	if x == nil {
+		panic("nil interface")
+	}
+}
+
+func isValid(v Value) {
+	if !v.IsValid() {
+		panic("zero Value")
+	}
+}
+
+func TestAlias(t *testing.T) {
+	x := string("hello")
+	v := ValueOf(&x).Elem()
+	oldvalue := v.Interface()
+	v.SetString("world")
+	newvalue := v.Interface()
+
+	if oldvalue != "hello" || newvalue != "world" {
+		t.Errorf("aliasing: old=%q new=%q, want hello, world", oldvalue, newvalue)
+	}
+}
+
+var V = ValueOf
+
+func EmptyInterfaceV(x interface{}) Value {
+	return ValueOf(&x).Elem()
+}
+
+func ReaderV(x io.Reader) Value {
+	return ValueOf(&x).Elem()
+}
+
+func ReadWriterV(x io.ReadWriter) Value {
+	return ValueOf(&x).Elem()
+}
+
+type Empty struct{}
+type MyString string
+type MyBytes []byte
+type MyRunes []int32
+type MyFunc func()
+type MyByte byte
+
+var convertTests = []struct {
+	in  Value
+	out Value
+}{
+	// numbers
+	/*
+		Edit .+1,/\*\//-1>cat >/tmp/x.go && go run /tmp/x.go
+
+		package main
+
+		import "fmt"
+
+		var numbers = []string{
+			"int8", "uint8", "int16", "uint16",
+			"int32", "uint32", "int64", "uint64",
+			"int", "uint", "uintptr",
+			"float32", "float64",
+		}
+
+		func main() {
+			// all pairs but in an unusual order,
+			// to emit all the int8, uint8 cases
+			// before n grows too big.
+			n := 1
+			for i, f := range numbers {
+				for _, g := range numbers[i:] {
+					fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", f, n, g, n)
+					n++
+					if f != g {
+						fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", g, n, f, n)
+						n++
+					}
+				}
+			}
+		}
+	*/
+	{V(int8(1)), V(int8(1))},
+	{V(int8(2)), V(uint8(2))},
+	{V(uint8(3)), V(int8(3))},
+	{V(int8(4)), V(int16(4))},
+	{V(int16(5)), V(int8(5))},
+	{V(int8(6)), V(uint16(6))},
+	{V(uint16(7)), V(int8(7))},
+	{V(int8(8)), V(int32(8))},
+	{V(int32(9)), V(int8(9))},
+	{V(int8(10)), V(uint32(10))},
+	{V(uint32(11)), V(int8(11))},
+	{V(int8(12)), V(int64(12))},
+	{V(int64(13)), V(int8(13))},
+	{V(int8(14)), V(uint64(14))},
+	{V(uint64(15)), V(int8(15))},
+	{V(int8(16)), V(int(16))},
+	{V(int(17)), V(int8(17))},
+	{V(int8(18)), V(uint(18))},
+	{V(uint(19)), V(int8(19))},
+	{V(int8(20)), V(uintptr(20))},
+	{V(uintptr(21)), V(int8(21))},
+	{V(int8(22)), V(float32(22))},
+	{V(float32(23)), V(int8(23))},
+	{V(int8(24)), V(float64(24))},
+	{V(float64(25)), V(int8(25))},
+	{V(uint8(26)), V(uint8(26))},
+	{V(uint8(27)), V(int16(27))},
+	{V(int16(28)), V(uint8(28))},
+	{V(uint8(29)), V(uint16(29))},
+	{V(uint16(30)), V(uint8(30))},
+	{V(uint8(31)), V(int32(31))},
+	{V(int32(32)), V(uint8(32))},
+	{V(uint8(33)), V(uint32(33))},
+	{V(uint32(34)), V(uint8(34))},
+	{V(uint8(35)), V(int64(35))},
+	{V(int64(36)), V(uint8(36))},
+	{V(uint8(37)), V(uint64(37))},
+	{V(uint64(38)), V(uint8(38))},
+	{V(uint8(39)), V(int(39))},
+	{V(int(40)), V(uint8(40))},
+	{V(uint8(41)), V(uint(41))},
+	{V(uint(42)), V(uint8(42))},
+	{V(uint8(43)), V(uintptr(43))},
+	{V(uintptr(44)), V(uint8(44))},
+	{V(uint8(45)), V(float32(45))},
+	{V(float32(46)), V(uint8(46))},
+	{V(uint8(47)), V(float64(47))},
+	{V(float64(48)), V(uint8(48))},
+	{V(int16(49)), V(int16(49))},
+	{V(int16(50)), V(uint16(50))},
+	{V(uint16(51)), V(int16(51))},
+	{V(int16(52)), V(int32(52))},
+	{V(int32(53)), V(int16(53))},
+	{V(int16(54)), V(uint32(54))},
+	{V(uint32(55)), V(int16(55))},
+	{V(int16(56)), V(int64(56))},
+	{V(int64(57)), V(int16(57))},
+	{V(int16(58)), V(uint64(58))},
+	{V(uint64(59)), V(int16(59))},
+	{V(int16(60)), V(int(60))},
+	{V(int(61)), V(int16(61))},
+	{V(int16(62)), V(uint(62))},
+	{V(uint(63)), V(int16(63))},
+	{V(int16(64)), V(uintptr(64))},
+	{V(uintptr(65)), V(int16(65))},
+	{V(int16(66)), V(float32(66))},
+	{V(float32(67)), V(int16(67))},
+	{V(int16(68)), V(float64(68))},
+	{V(float64(69)), V(int16(69))},
+	{V(uint16(70)), V(uint16(70))},
+	{V(uint16(71)), V(int32(71))},
+	{V(int32(72)), V(uint16(72))},
+	{V(uint16(73)), V(uint32(73))},
+	{V(uint32(74)), V(uint16(74))},
+	{V(uint16(75)), V(int64(75))},
+	{V(int64(76)), V(uint16(76))},
+	{V(uint16(77)), V(uint64(77))},
+	{V(uint64(78)), V(uint16(78))},
+	{V(uint16(79)), V(int(79))},
+	{V(int(80)), V(uint16(80))},
+	{V(uint16(81)), V(uint(81))},
+	{V(uint(82)), V(uint16(82))},
+	{V(uint16(83)), V(uintptr(83))},
+	{V(uintptr(84)), V(uint16(84))},
+	{V(uint16(85)), V(float32(85))},
+	{V(float32(86)), V(uint16(86))},
+	{V(uint16(87)), V(float64(87))},
+	{V(float64(88)), V(uint16(88))},
+	{V(int32(89)), V(int32(89))},
+	{V(int32(90)), V(uint32(90))},
+	{V(uint32(91)), V(int32(91))},
+	{V(int32(92)), V(int64(92))},
+	{V(int64(93)), V(int32(93))},
+	{V(int32(94)), V(uint64(94))},
+	{V(uint64(95)), V(int32(95))},
+	{V(int32(96)), V(int(96))},
+	{V(int(97)), V(int32(97))},
+	{V(int32(98)), V(uint(98))},
+	{V(uint(99)), V(int32(99))},
+	{V(int32(100)), V(uintptr(100))},
+	{V(uintptr(101)), V(int32(101))},
+	{V(int32(102)), V(float32(102))},
+	{V(float32(103)), V(int32(103))},
+	{V(int32(104)), V(float64(104))},
+	{V(float64(105)), V(int32(105))},
+	{V(uint32(106)), V(uint32(106))},
+	{V(uint32(107)), V(int64(107))},
+	{V(int64(108)), V(uint32(108))},
+	{V(uint32(109)), V(uint64(109))},
+	{V(uint64(110)), V(uint32(110))},
+	{V(uint32(111)), V(int(111))},
+	{V(int(112)), V(uint32(112))},
+	{V(uint32(113)), V(uint(113))},
+	{V(uint(114)), V(uint32(114))},
+	{V(uint32(115)), V(uintptr(115))},
+	{V(uintptr(116)), V(uint32(116))},
+	{V(uint32(117)), V(float32(117))},
+	{V(float32(118)), V(uint32(118))},
+	{V(uint32(119)), V(float64(119))},
+	{V(float64(120)), V(uint32(120))},
+	{V(int64(121)), V(int64(121))},
+	{V(int64(122)), V(uint64(122))},
+	{V(uint64(123)), V(int64(123))},
+	{V(int64(124)), V(int(124))},
+	{V(int(125)), V(int64(125))},
+	{V(int64(126)), V(uint(126))},
+	{V(uint(127)), V(int64(127))},
+	{V(int64(128)), V(uintptr(128))},
+	{V(uintptr(129)), V(int64(129))},
+	{V(int64(130)), V(float32(130))},
+	{V(float32(131)), V(int64(131))},
+	{V(int64(132)), V(float64(132))},
+	{V(float64(133)), V(int64(133))},
+	{V(uint64(134)), V(uint64(134))},
+	{V(uint64(135)), V(int(135))},
+	{V(int(136)), V(uint64(136))},
+	{V(uint64(137)), V(uint(137))},
+	{V(uint(138)), V(uint64(138))},
+	{V(uint64(139)), V(uintptr(139))},
+	{V(uintptr(140)), V(uint64(140))},
+	{V(uint64(141)), V(float32(141))},
+	{V(float32(142)), V(uint64(142))},
+	{V(uint64(143)), V(float64(143))},
+	{V(float64(144)), V(uint64(144))},
+	{V(int(145)), V(int(145))},
+	{V(int(146)), V(uint(146))},
+	{V(uint(147)), V(int(147))},
+	{V(int(148)), V(uintptr(148))},
+	{V(uintptr(149)), V(int(149))},
+	{V(int(150)), V(float32(150))},
+	{V(float32(151)), V(int(151))},
+	{V(int(152)), V(float64(152))},
+	{V(float64(153)), V(int(153))},
+	{V(uint(154)), V(uint(154))},
+	{V(uint(155)), V(uintptr(155))},
+	{V(uintptr(156)), V(uint(156))},
+	{V(uint(157)), V(float32(157))},
+	{V(float32(158)), V(uint(158))},
+	{V(uint(159)), V(float64(159))},
+	{V(float64(160)), V(uint(160))},
+	{V(uintptr(161)), V(uintptr(161))},
+	{V(uintptr(162)), V(float32(162))},
+	{V(float32(163)), V(uintptr(163))},
+	{V(uintptr(164)), V(float64(164))},
+	{V(float64(165)), V(uintptr(165))},
+	{V(float32(166)), V(float32(166))},
+	{V(float32(167)), V(float64(167))},
+	{V(float64(168)), V(float32(168))},
+	{V(float64(169)), V(float64(169))},
+
+	// truncation
+	{V(float64(1.5)), V(int(1))},
+
+	// complex
+	{V(complex64(1i)), V(complex64(1i))},
+	{V(complex64(2i)), V(complex128(2i))},
+	{V(complex128(3i)), V(complex64(3i))},
+	{V(complex128(4i)), V(complex128(4i))},
+
+	// string
+	{V(string("hello")), V(string("hello"))},
+	{V(string("bytes1")), V([]byte("bytes1"))},
+	{V([]byte("bytes2")), V(string("bytes2"))},
+	{V([]byte("bytes3")), V([]byte("bytes3"))},
+	{V(string("runes♝")), V([]rune("runes♝"))},
+	{V([]rune("runes♕")), V(string("runes♕"))},
+	{V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
+	{V(int('a')), V(string("a"))},
+	{V(int8('a')), V(string("a"))},
+	{V(int16('a')), V(string("a"))},
+	{V(int32('a')), V(string("a"))},
+	{V(int64('a')), V(string("a"))},
+	{V(uint('a')), V(string("a"))},
+	{V(uint8('a')), V(string("a"))},
+	{V(uint16('a')), V(string("a"))},
+	{V(uint32('a')), V(string("a"))},
+	{V(uint64('a')), V(string("a"))},
+	{V(uintptr('a')), V(string("a"))},
+	{V(int(-1)), V(string("\uFFFD"))},
+	{V(int8(-2)), V(string("\uFFFD"))},
+	{V(int16(-3)), V(string("\uFFFD"))},
+	{V(int32(-4)), V(string("\uFFFD"))},
+	{V(int64(-5)), V(string("\uFFFD"))},
+	{V(uint(0x110001)), V(string("\uFFFD"))},
+	{V(uint32(0x110002)), V(string("\uFFFD"))},
+	{V(uint64(0x110003)), V(string("\uFFFD"))},
+	{V(uintptr(0x110004)), V(string("\uFFFD"))},
+
+	// named string
+	{V(MyString("hello")), V(string("hello"))},
+	{V(string("hello")), V(MyString("hello"))},
+	{V(string("hello")), V(string("hello"))},
+	{V(MyString("hello")), V(MyString("hello"))},
+	{V(MyString("bytes1")), V([]byte("bytes1"))},
+	{V([]byte("bytes2")), V(MyString("bytes2"))},
+	{V([]byte("bytes3")), V([]byte("bytes3"))},
+	{V(MyString("runes♝")), V([]rune("runes♝"))},
+	{V([]rune("runes♕")), V(MyString("runes♕"))},
+	{V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
+	{V([]rune("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
+	{V(MyRunes("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
+	{V(int('a')), V(MyString("a"))},
+	{V(int8('a')), V(MyString("a"))},
+	{V(int16('a')), V(MyString("a"))},
+	{V(int32('a')), V(MyString("a"))},
+	{V(int64('a')), V(MyString("a"))},
+	{V(uint('a')), V(MyString("a"))},
+	{V(uint8('a')), V(MyString("a"))},
+	{V(uint16('a')), V(MyString("a"))},
+	{V(uint32('a')), V(MyString("a"))},
+	{V(uint64('a')), V(MyString("a"))},
+	{V(uintptr('a')), V(MyString("a"))},
+	{V(int(-1)), V(MyString("\uFFFD"))},
+	{V(int8(-2)), V(MyString("\uFFFD"))},
+	{V(int16(-3)), V(MyString("\uFFFD"))},
+	{V(int32(-4)), V(MyString("\uFFFD"))},
+	{V(int64(-5)), V(MyString("\uFFFD"))},
+	{V(uint(0x110001)), V(MyString("\uFFFD"))},
+	{V(uint32(0x110002)), V(MyString("\uFFFD"))},
+	{V(uint64(0x110003)), V(MyString("\uFFFD"))},
+	{V(uintptr(0x110004)), V(MyString("\uFFFD"))},
+
+	// named []byte
+	{V(string("bytes1")), V(MyBytes("bytes1"))},
+	{V(MyBytes("bytes2")), V(string("bytes2"))},
+	{V(MyBytes("bytes3")), V(MyBytes("bytes3"))},
+	{V(MyString("bytes1")), V(MyBytes("bytes1"))},
+	{V(MyBytes("bytes2")), V(MyString("bytes2"))},
+
+	// named []rune
+	{V(string("runes♝")), V(MyRunes("runes♝"))},
+	{V(MyRunes("runes♕")), V(string("runes♕"))},
+	{V(MyRunes("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
+	{V(MyString("runes♝")), V(MyRunes("runes♝"))},
+	{V(MyRunes("runes♕")), V(MyString("runes♕"))},
+
+	// named types and equal underlying types
+	{V(new(int)), V(new(integer))},
+	{V(new(integer)), V(new(int))},
+	{V(Empty{}), V(struct{}{})},
+	{V(new(Empty)), V(new(struct{}))},
+	{V(struct{}{}), V(Empty{})},
+	{V(new(struct{})), V(new(Empty))},
+	{V(Empty{}), V(Empty{})},
+	{V(MyBytes{}), V([]byte{})},
+	{V([]byte{}), V(MyBytes{})},
+	{V((func())(nil)), V(MyFunc(nil))},
+	{V((MyFunc)(nil)), V((func())(nil))},
+
+	// can convert *byte and *MyByte
+	{V((*byte)(nil)), V((*MyByte)(nil))},
+	{V((*MyByte)(nil)), V((*byte)(nil))},
+
+	// cannot convert mismatched array sizes
+	{V([2]byte{}), V([2]byte{})},
+	{V([3]byte{}), V([3]byte{})},
+
+	// cannot convert other instances
+	{V((**byte)(nil)), V((**byte)(nil))},
+	{V((**MyByte)(nil)), V((**MyByte)(nil))},
+	{V((chan byte)(nil)), V((chan byte)(nil))},
+	{V((chan MyByte)(nil)), V((chan MyByte)(nil))},
+	{V(([]byte)(nil)), V(([]byte)(nil))},
+	{V(([]MyByte)(nil)), V(([]MyByte)(nil))},
+	{V((map[int]byte)(nil)), V((map[int]byte)(nil))},
+	{V((map[int]MyByte)(nil)), V((map[int]MyByte)(nil))},
+	{V((map[byte]int)(nil)), V((map[byte]int)(nil))},
+	{V((map[MyByte]int)(nil)), V((map[MyByte]int)(nil))},
+	{V([2]byte{}), V([2]byte{})},
+	{V([2]MyByte{}), V([2]MyByte{})},
+
+	// other
+	{V((***int)(nil)), V((***int)(nil))},
+	{V((***byte)(nil)), V((***byte)(nil))},
+	{V((***int32)(nil)), V((***int32)(nil))},
+	{V((***int64)(nil)), V((***int64)(nil))},
+	{V((chan int)(nil)), V((<-chan int)(nil))},
+	{V((chan int)(nil)), V((chan<- int)(nil))},
+	{V((chan string)(nil)), V((<-chan string)(nil))},
+	{V((chan string)(nil)), V((chan<- string)(nil))},
+	{V((chan byte)(nil)), V((chan byte)(nil))},
+	{V((chan MyByte)(nil)), V((chan MyByte)(nil))},
+	{V((map[int]bool)(nil)), V((map[int]bool)(nil))},
+	{V((map[int]byte)(nil)), V((map[int]byte)(nil))},
+	{V((map[uint]bool)(nil)), V((map[uint]bool)(nil))},
+	{V([]uint(nil)), V([]uint(nil))},
+	{V([]int(nil)), V([]int(nil))},
+	{V(new(interface{})), V(new(interface{}))},
+	{V(new(io.Reader)), V(new(io.Reader))},
+	{V(new(io.Writer)), V(new(io.Writer))},
+
+	// interfaces
+	{V(int(1)), EmptyInterfaceV(int(1))},
+	{V(string("hello")), EmptyInterfaceV(string("hello"))},
+	{V(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))},
+	{ReadWriterV(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))},
+	{V(new(bytes.Buffer)), ReadWriterV(new(bytes.Buffer))},
+}
+
+func TestConvert(t *testing.T) {
+	canConvert := map[[2]Type]bool{}
+	all := map[Type]bool{}
+
+	for _, tt := range convertTests {
+		t1 := tt.in.Type()
+		if !t1.ConvertibleTo(t1) {
+			t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t1)
+			continue
+		}
+
+		t2 := tt.out.Type()
+		if !t1.ConvertibleTo(t2) {
+			t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t2)
+			continue
+		}
+
+		all[t1] = true
+		all[t2] = true
+		canConvert[[2]Type{t1, t2}] = true
+
+		// vout1 represents the in value converted to the in type.
+		v1 := tt.in
+		vout1 := v1.Convert(t1)
+		out1 := vout1.Interface()
+		if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
+			t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t1, out1, tt.in.Interface())
+		}
+
+		// vout2 represents the in value converted to the out type.
+		vout2 := v1.Convert(t2)
+		out2 := vout2.Interface()
+		if vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) {
+			t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t2, out2, tt.out.Interface())
+		}
+
+		// vout3 represents a new value of the out type, set to vout2.  This makes
+		// sure the converted value vout2 is really usable as a regular value.
+		vout3 := New(t2).Elem()
+		vout3.Set(vout2)
+		out3 := vout3.Interface()
+		if vout3.Type() != tt.out.Type() || !DeepEqual(out3, tt.out.Interface()) {
+			t.Errorf("Set(ValueOf(%T(%[1]v)).Convert(%s)) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t2, out3, tt.out.Interface())
+		}
+
+		if IsRO(v1) {
+			t.Errorf("table entry %v is RO, should not be", v1)
+		}
+		if IsRO(vout1) {
+			t.Errorf("self-conversion output %v is RO, should not be", vout1)
+		}
+		if IsRO(vout2) {
+			t.Errorf("conversion output %v is RO, should not be", vout2)
+		}
+		if IsRO(vout3) {
+			t.Errorf("set(conversion output) %v is RO, should not be", vout3)
+		}
+		if !IsRO(MakeRO(v1).Convert(t1)) {
+			t.Errorf("RO self-conversion output %v is not RO, should be", v1)
+		}
+		if !IsRO(MakeRO(v1).Convert(t2)) {
+			t.Errorf("RO conversion output %v is not RO, should be", v1)
+		}
+	}
+
+	// Assume that of all the types we saw during the tests,
+	// if there wasn't an explicit entry for a conversion between
+	// a pair of types, then it's not to be allowed. This checks for
+	// things like 'int64' converting to '*int'.
+	for t1 := range all {
+		for t2 := range all {
+			expectOK := t1 == t2 || canConvert[[2]Type{t1, t2}] || t2.Kind() == Interface && t2.NumMethod() == 0
+			if ok := t1.ConvertibleTo(t2); ok != expectOK {
+				t.Errorf("(%s).ConvertibleTo(%s) = %v, want %v", t1, t2, ok, expectOK)
+			}
+		}
+	}
+}
+
+func TestOverflow(t *testing.T) {
+	if ovf := V(float64(0)).OverflowFloat(1e300); ovf {
+		t.Errorf("%v wrongly overflows float64", 1e300)
+	}
+
+	maxFloat32 := float64((1<<24 - 1) << (127 - 23))
+	if ovf := V(float32(0)).OverflowFloat(maxFloat32); ovf {
+		t.Errorf("%v wrongly overflows float32", maxFloat32)
+	}
+	ovfFloat32 := float64((1<<24-1)<<(127-23) + 1<<(127-52))
+	if ovf := V(float32(0)).OverflowFloat(ovfFloat32); !ovf {
+		t.Errorf("%v should overflow float32", ovfFloat32)
+	}
+	if ovf := V(float32(0)).OverflowFloat(-ovfFloat32); !ovf {
+		t.Errorf("%v should overflow float32", -ovfFloat32)
+	}
+
+	maxInt32 := int64(0x7fffffff)
+	if ovf := V(int32(0)).OverflowInt(maxInt32); ovf {
+		t.Errorf("%v wrongly overflows int32", maxInt32)
+	}
+	if ovf := V(int32(0)).OverflowInt(-1 << 31); ovf {
+		t.Errorf("%v wrongly overflows int32", -int64(1)<<31)
+	}
+	ovfInt32 := int64(1 << 31)
+	if ovf := V(int32(0)).OverflowInt(ovfInt32); !ovf {
+		t.Errorf("%v should overflow int32", ovfInt32)
+	}
+
+	maxUint32 := uint64(0xffffffff)
+	if ovf := V(uint32(0)).OverflowUint(maxUint32); ovf {
+		t.Errorf("%v wrongly overflows uint32", maxUint32)
+	}
+	ovfUint32 := uint64(1 << 32)
+	if ovf := V(uint32(0)).OverflowUint(ovfUint32); !ovf {
+		t.Errorf("%v should overflow uint32", ovfUint32)
+	}
+}
+
+func checkSameType(t *testing.T, x, y interface{}) {
+	if TypeOf(x) != TypeOf(y) {
+		t.Errorf("did not find preexisting type for %s (vs %s)", TypeOf(x), TypeOf(y))
+	}
+}
+
+func TestArrayOf(t *testing.T) {
+	// check construction and use of type not in binary
+	type T int
+	at := ArrayOf(10, TypeOf(T(1)))
+	v := New(at).Elem()
+	for i := 0; i < v.Len(); i++ {
+		v.Index(i).Set(ValueOf(T(i)))
+	}
+	s := fmt.Sprint(v.Interface())
+	want := "[0 1 2 3 4 5 6 7 8 9]"
+	if s != want {
+		t.Errorf("constructed array = %s, want %s", s, want)
+	}
+
+	// check that type already in binary is found
+	checkSameType(t, Zero(ArrayOf(5, TypeOf(T(1)))).Interface(), [5]T{})
+}
+
+func TestSliceOf(t *testing.T) {
+	// check construction and use of type not in binary
+	type T int
+	st := SliceOf(TypeOf(T(1)))
+	v := MakeSlice(st, 10, 10)
+	runtime.GC()
+	for i := 0; i < v.Len(); i++ {
+		v.Index(i).Set(ValueOf(T(i)))
+		runtime.GC()
+	}
+	s := fmt.Sprint(v.Interface())
+	want := "[0 1 2 3 4 5 6 7 8 9]"
+	if s != want {
+		t.Errorf("constructed slice = %s, want %s", s, want)
+	}
+
+	// check that type already in binary is found
+	type T1 int
+	checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{})
+}
+
+func TestSliceOverflow(t *testing.T) {
+	// check that MakeSlice panics when size of slice overflows uint
+	const S = 1e6
+	s := uint(S)
+	l := (1<<(unsafe.Sizeof((*byte)(nil))*8)-1)/s + 1
+	if l*s >= s {
+		t.Fatal("slice size does not overflow")
+	}
+	var x [S]byte
+	st := SliceOf(TypeOf(x))
+	defer func() {
+		err := recover()
+		if err == nil {
+			t.Fatal("slice overflow does not panic")
+		}
+	}()
+	MakeSlice(st, int(l), int(l))
+}
+
+func TestSliceOfGC(t *testing.T) {
+	type T *uintptr
+	tt := TypeOf(T(nil))
+	st := SliceOf(tt)
+	const n = 100
+	var x []interface{}
+	for i := 0; i < n; i++ {
+		v := MakeSlice(st, n, n)
+		for j := 0; j < v.Len(); j++ {
+			p := new(uintptr)
+			*p = uintptr(i*n + j)
+			v.Index(j).Set(ValueOf(p).Convert(tt))
+		}
+		x = append(x, v.Interface())
+	}
+	runtime.GC()
+
+	for i, xi := range x {
+		v := ValueOf(xi)
+		for j := 0; j < v.Len(); j++ {
+			k := v.Index(j).Elem().Interface()
+			if k != uintptr(i*n+j) {
+				t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
+			}
+		}
+	}
+}
+
+func TestChanOf(t *testing.T) {
+	// check construction and use of type not in binary
+	type T string
+	ct := ChanOf(BothDir, TypeOf(T("")))
+	v := MakeChan(ct, 2)
+	runtime.GC()
+	v.Send(ValueOf(T("hello")))
+	runtime.GC()
+	v.Send(ValueOf(T("world")))
+	runtime.GC()
+
+	sv1, _ := v.Recv()
+	sv2, _ := v.Recv()
+	s1 := sv1.String()
+	s2 := sv2.String()
+	if s1 != "hello" || s2 != "world" {
+		t.Errorf("constructed chan: have %q, %q, want %q, %q", s1, s2, "hello", "world")
+	}
+
+	// check that type already in binary is found
+	type T1 int
+	checkSameType(t, Zero(ChanOf(BothDir, TypeOf(T1(1)))).Interface(), (chan T1)(nil))
+}
+
+func TestChanOfGC(t *testing.T) {
+	done := make(chan bool, 1)
+	go func() {
+		select {
+		case <-done:
+		case <-time.After(5 * time.Second):
+			panic("deadlock in TestChanOfGC")
+		}
+	}()
+
+	defer func() {
+		done <- true
+	}()
+
+	type T *uintptr
+	tt := TypeOf(T(nil))
+	ct := ChanOf(BothDir, tt)
+
+	// NOTE: The garbage collector handles allocated channels specially,
+	// so we have to save pointers to channels in x; the pointer code will
+	// use the gc info in the newly constructed chan type.
+	const n = 100
+	var x []interface{}
+	for i := 0; i < n; i++ {
+		v := MakeChan(ct, n)
+		for j := 0; j < n; j++ {
+			p := new(uintptr)
+			*p = uintptr(i*n + j)
+			v.Send(ValueOf(p).Convert(tt))
+		}
+		pv := New(ct)
+		pv.Elem().Set(v)
+		x = append(x, pv.Interface())
+	}
+	runtime.GC()
+
+	for i, xi := range x {
+		v := ValueOf(xi).Elem()
+		for j := 0; j < n; j++ {
+			pv, _ := v.Recv()
+			k := pv.Elem().Interface()
+			if k != uintptr(i*n+j) {
+				t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
+			}
+		}
+	}
+}
+
+func TestMapOf(t *testing.T) {
+	// check construction and use of type not in binary
+	type K string
+	type V float64
+
+	v := MakeMap(MapOf(TypeOf(K("")), TypeOf(V(0))))
+	runtime.GC()
+	v.SetMapIndex(ValueOf(K("a")), ValueOf(V(1)))
+	runtime.GC()
+
+	s := fmt.Sprint(v.Interface())
+	want := "map[a:1]"
+	if s != want {
+		t.Errorf("constructed map = %s, want %s", s, want)
+	}
+
+	// check that type already in binary is found
+	checkSameType(t, Zero(MapOf(TypeOf(V(0)), TypeOf(K("")))).Interface(), map[V]K(nil))
+
+	// check that invalid key type panics
+	shouldPanic(func() { MapOf(TypeOf((func())(nil)), TypeOf(false)) })
+}
+
+func TestMapOfGCKeys(t *testing.T) {
+	type T *uintptr
+	tt := TypeOf(T(nil))
+	mt := MapOf(tt, TypeOf(false))
+
+	// NOTE: The garbage collector handles allocated maps specially,
+	// so we have to save pointers to maps in x; the pointer code will
+	// use the gc info in the newly constructed map type.
+	const n = 100
+	var x []interface{}
+	for i := 0; i < n; i++ {
+		v := MakeMap(mt)
+		for j := 0; j < n; j++ {
+			p := new(uintptr)
+			*p = uintptr(i*n + j)
+			v.SetMapIndex(ValueOf(p).Convert(tt), ValueOf(true))
+		}
+		pv := New(mt)
+		pv.Elem().Set(v)
+		x = append(x, pv.Interface())
+	}
+	runtime.GC()
+
+	for i, xi := range x {
+		v := ValueOf(xi).Elem()
+		var out []int
+		for _, kv := range v.MapKeys() {
+			out = append(out, int(kv.Elem().Interface().(uintptr)))
+		}
+		sort.Ints(out)
+		for j, k := range out {
+			if k != i*n+j {
+				t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
+			}
+		}
+	}
+}
+
+func TestMapOfGCValues(t *testing.T) {
+	type T *uintptr
+	tt := TypeOf(T(nil))
+	mt := MapOf(TypeOf(1), tt)
+
+	// NOTE: The garbage collector handles allocated maps specially,
+	// so we have to save pointers to maps in x; the pointer code will
+	// use the gc info in the newly constructed map type.
+	const n = 100
+	var x []interface{}
+	for i := 0; i < n; i++ {
+		v := MakeMap(mt)
+		for j := 0; j < n; j++ {
+			p := new(uintptr)
+			*p = uintptr(i*n + j)
+			v.SetMapIndex(ValueOf(j), ValueOf(p).Convert(tt))
+		}
+		pv := New(mt)
+		pv.Elem().Set(v)
+		x = append(x, pv.Interface())
+	}
+	runtime.GC()
+
+	for i, xi := range x {
+		v := ValueOf(xi).Elem()
+		for j := 0; j < n; j++ {
+			k := v.MapIndex(ValueOf(j)).Elem().Interface().(uintptr)
+			if k != uintptr(i*n+j) {
+				t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
+			}
+		}
+	}
+}
+
+type B1 struct {
+	X int
+	Y int
+	Z int
+}
+
+func BenchmarkFieldByName1(b *testing.B) {
+	t := TypeOf(B1{})
+	for i := 0; i < b.N; i++ {
+		t.FieldByName("Z")
+	}
+}
+
+func BenchmarkFieldByName2(b *testing.B) {
+	t := TypeOf(S3{})
+	for i := 0; i < b.N; i++ {
+		t.FieldByName("B")
+	}
+}
+
+type R0 struct {
+	*R1
+	*R2
+	*R3
+	*R4
+}
+
+type R1 struct {
+	*R5
+	*R6
+	*R7
+	*R8
+}
+
+type R2 R1
+type R3 R1
+type R4 R1
+
+type R5 struct {
+	*R9
+	*R10
+	*R11
+	*R12
+}
+
+type R6 R5
+type R7 R5
+type R8 R5
+
+type R9 struct {
+	*R13
+	*R14
+	*R15
+	*R16
+}
+
+type R10 R9
+type R11 R9
+type R12 R9
+
+type R13 struct {
+	*R17
+	*R18
+	*R19
+	*R20
+}
+
+type R14 R13
+type R15 R13
+type R16 R13
+
+type R17 struct {
+	*R21
+	*R22
+	*R23
+	*R24
+}
+
+type R18 R17
+type R19 R17
+type R20 R17
+
+type R21 struct {
+	X int
+}
+
+type R22 R21
+type R23 R21
+type R24 R21
+
+func TestEmbed(t *testing.T) {
+	typ := TypeOf(R0{})
+	f, ok := typ.FieldByName("X")
+	if ok {
+		t.Fatalf(`FieldByName("X") should fail, returned %v`, f.Index)
+	}
+}
+
+func BenchmarkFieldByName3(b *testing.B) {
+	t := TypeOf(R0{})
+	for i := 0; i < b.N; i++ {
+		t.FieldByName("X")
+	}
+}
+
+type S struct {
+	i1 int64
+	i2 int64
+}
+
+func BenchmarkInterfaceBig(b *testing.B) {
+	v := ValueOf(S{})
+	for i := 0; i < b.N; i++ {
+		v.Interface()
+	}
+	b.StopTimer()
+}
+
+func TestAllocsInterfaceBig(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	v := ValueOf(S{})
+	if allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {
+		t.Error("allocs:", allocs)
+	}
+}
+
+func BenchmarkInterfaceSmall(b *testing.B) {
+	v := ValueOf(int64(0))
+	for i := 0; i < b.N; i++ {
+		v.Interface()
+	}
+}
+
+func TestAllocsInterfaceSmall(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	v := ValueOf(int64(0))
+	if allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {
+		t.Error("allocs:", allocs)
+	}
+}
+
+// An exhaustive is a mechanism for writing exhaustive or stochastic tests.
+// The basic usage is:
+//
+//	for x.Next() {
+//		... code using x.Maybe() or x.Choice(n) to create test cases ...
+//	}
+//
+// Each iteration of the loop returns a different set of results, until all
+// possible result sets have been explored. It is okay for different code paths
+// to make different method call sequences on x, but there must be no
+// other source of non-determinism in the call sequences.
+//
+// When faced with a new decision, x chooses randomly. Future explorations
+// of that path will choose successive values for the result. Thus, stopping
+// the loop after a fixed number of iterations gives somewhat stochastic
+// testing.
+//
+// Example:
+//
+//	for x.Next() {
+//		v := make([]bool, x.Choose(4))
+//		for i := range v {
+//			v[i] = x.Maybe()
+//		}
+//		fmt.Println(v)
+//	}
+//
+// prints (in some order):
+//
+//	[]
+//	[false]
+//	[true]
+//	[false false]
+//	[false true]
+//	...
+//	[true true]
+//	[false false false]
+//	...
+//	[true true true]
+//	[false false false false]
+//	...
+//	[true true true true]
+//
+type exhaustive struct {
+	r    *rand.Rand
+	pos  int
+	last []choice
+}
+
+type choice struct {
+	off int
+	n   int
+	max int
+}
+
+func (x *exhaustive) Next() bool {
+	if x.r == nil {
+		x.r = rand.New(rand.NewSource(time.Now().UnixNano()))
+	}
+	x.pos = 0
+	if x.last == nil {
+		x.last = []choice{}
+		return true
+	}
+	for i := len(x.last) - 1; i >= 0; i-- {
+		c := &x.last[i]
+		if c.n+1 < c.max {
+			c.n++
+			x.last = x.last[:i+1]
+			return true
+		}
+	}
+	return false
+}
+
+func (x *exhaustive) Choose(max int) int {
+	if x.pos >= len(x.last) {
+		x.last = append(x.last, choice{x.r.Intn(max), 0, max})
+	}
+	c := &x.last[x.pos]
+	x.pos++
+	if c.max != max {
+		panic("inconsistent use of exhaustive tester")
+	}
+	return (c.n + c.off) % max
+}
+
+func (x *exhaustive) Maybe() bool {
+	return x.Choose(2) == 1
+}
+
+func GCFunc(args []Value) []Value {
+	runtime.GC()
+	return []Value{}
+}
+
+func TestReflectFuncTraceback(t *testing.T) {
+	f := MakeFunc(TypeOf(func() {}), GCFunc)
+	f.Call([]Value{})
+}
+
+func TestReflectMethodTraceback(t *testing.T) {
+	p := Point{3, 4}
+	m := ValueOf(p).MethodByName("GCMethod")
+	i := ValueOf(m.Interface()).Call([]Value{ValueOf(5)})[0].Int()
+	if i != 8 {
+		t.Errorf("Call returned %d; want 8", i)
+	}
+}
+
+func TestBigZero(t *testing.T) {
+	const size = 1 << 10
+	var v [size]byte
+	z := Zero(ValueOf(v).Type()).Interface().([size]byte)
+	for i := 0; i < size; i++ {
+		if z[i] != 0 {
+			t.Fatalf("Zero object not all zero, index %d", i)
+		}
+	}
+}
+
+func TestFieldByIndexNil(t *testing.T) {
+	type P struct {
+		F int
+	}
+	type T struct {
+		*P
+	}
+	v := ValueOf(T{})
+
+	v.FieldByName("P") // should be fine
+
+	defer func() {
+		if err := recover(); err == nil {
+			t.Fatalf("no error")
+		} else if !strings.Contains(fmt.Sprint(err), "nil pointer to embedded struct") {
+			t.Fatalf(`err=%q, wanted error containing "nil pointer to embedded struct"`, err)
+		}
+	}()
+	v.FieldByName("F") // should panic
+
+	t.Fatalf("did not panic")
+}
+
+// Given
+//	type Outer struct {
+//		*Inner
+//		...
+//	}
+// the compiler generates the implementation of (*Outer).M dispatching to the embedded Inner.
+// The implementation is logically:
+//	func (p *Outer) M() {
+//		(p.Inner).M()
+//	}
+// but since the only change here is the replacement of one pointer receiver with another,
+// the actual generated code overwrites the original receiver with the p.Inner pointer and
+// then jumps to the M method expecting the *Inner receiver.
+//
+// During reflect.Value.Call, we create an argument frame and the associated data structures
+// to describe it to the garbage collector, populate the frame, call reflect.call to
+// run a function call using that frame, and then copy the results back out of the frame.
+// The reflect.call function does a memmove of the frame structure onto the
+// stack (to set up the inputs), runs the call, and the memmoves the stack back to
+// the frame structure (to preserve the outputs).
+//
+// Originally reflect.call did not distinguish inputs from outputs: both memmoves
+// were for the full stack frame. However, in the case where the called function was
+// one of these wrappers, the rewritten receiver is almost certainly a different type
+// than the original receiver. This is not a problem on the stack, where we use the
+// program counter to determine the type information and understand that
+// during (*Outer).M the receiver is an *Outer while during (*Inner).M the receiver in the same
+// memory word is now an *Inner. But in the statically typed argument frame created
+// by reflect, the receiver is always an *Outer. Copying the modified receiver pointer
+// off the stack into the frame will store an *Inner there, and then if a garbage collection
+// happens to scan that argument frame before it is discarded, it will scan the *Inner
+// memory as if it were an *Outer. If the two have different memory layouts, the
+// collection will intepret the memory incorrectly.
+//
+// One such possible incorrect interpretation is to treat two arbitrary memory words
+// (Inner.P1 and Inner.P2 below) as an interface (Outer.R below). Because interpreting
+// an interface requires dereferencing the itab word, the misinterpretation will try to
+// deference Inner.P1, causing a crash during garbage collection.
+//
+// This came up in a real program in issue 7725.
+
+type Outer struct {
+	*Inner
+	R io.Reader
+}
+
+type Inner struct {
+	X  *Outer
+	P1 uintptr
+	P2 uintptr
+}
+
+func (pi *Inner) M() {
+	// Clear references to pi so that the only way the
+	// garbage collection will find the pointer is in the
+	// argument frame, typed as a *Outer.
+	pi.X.Inner = nil
+
+	// Set up an interface value that will cause a crash.
+	// P1 = 1 is a non-zero, so the interface looks non-nil.
+	// P2 = pi ensures that the data word points into the
+	// allocated heap; if not the collection skips the interface
+	// value as irrelevant, without dereferencing P1.
+	pi.P1 = 1
+	pi.P2 = uintptr(unsafe.Pointer(pi))
+}
+
+func TestCallMethodJump(t *testing.T) {
+	// In reflect.Value.Call, trigger a garbage collection after reflect.call
+	// returns but before the args frame has been discarded.
+	// This is a little clumsy but makes the failure repeatable.
+	*CallGC = true
+
+	p := &Outer{Inner: new(Inner)}
+	p.Inner.X = p
+	ValueOf(p).Method(0).Call(nil)
+
+	// Stop garbage collecting during reflect.call.
+	*CallGC = false
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/deepequal.go b/third_party/gofrontend/libgo/go/reflect/deepequal.go
new file mode 100644
index 0000000..f63715c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/deepequal.go
@@ -0,0 +1,145 @@
+// 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.
+
+// Deep equality test via reflection
+
+package reflect
+
+// During deepValueEqual, must keep track of checks that are
+// in progress.  The comparison algorithm assumes that all
+// checks in progress are true when it reencounters them.
+// Visited comparisons are stored in a map indexed by visit.
+type visit struct {
+	a1  uintptr
+	a2  uintptr
+	typ Type
+}
+
+// Tests for deep equality using reflected types. The map argument tracks
+// comparisons that have already been seen, which allows short circuiting on
+// recursive types.
+func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
+	if !v1.IsValid() || !v2.IsValid() {
+		return v1.IsValid() == v2.IsValid()
+	}
+	if v1.Type() != v2.Type() {
+		return false
+	}
+
+	// if depth > 10 { panic("deepValueEqual") }	// for debugging
+	hard := func(k Kind) bool {
+		switch k {
+		case Array, Map, Slice, Struct:
+			return true
+		}
+		return false
+	}
+
+	if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
+		addr1 := v1.UnsafeAddr()
+		addr2 := v2.UnsafeAddr()
+		if addr1 > addr2 {
+			// Canonicalize order to reduce number of entries in visited.
+			addr1, addr2 = addr2, addr1
+		}
+
+		// Short circuit if references are identical ...
+		if addr1 == addr2 {
+			return true
+		}
+
+		// ... or already seen
+		typ := v1.Type()
+		v := visit{addr1, addr2, typ}
+		if visited[v] {
+			return true
+		}
+
+		// Remember for later.
+		visited[v] = true
+	}
+
+	switch v1.Kind() {
+	case Array:
+		for i := 0; i < v1.Len(); i++ {
+			if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) {
+				return false
+			}
+		}
+		return true
+	case Slice:
+		if v1.IsNil() != v2.IsNil() {
+			return false
+		}
+		if v1.Len() != v2.Len() {
+			return false
+		}
+		if v1.Pointer() == v2.Pointer() {
+			return true
+		}
+		for i := 0; i < v1.Len(); i++ {
+			if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) {
+				return false
+			}
+		}
+		return true
+	case Interface:
+		if v1.IsNil() || v2.IsNil() {
+			return v1.IsNil() == v2.IsNil()
+		}
+		return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1)
+	case Ptr:
+		return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1)
+	case Struct:
+		for i, n := 0, v1.NumField(); i < n; i++ {
+			if !deepValueEqual(v1.Field(i), v2.Field(i), visited, depth+1) {
+				return false
+			}
+		}
+		return true
+	case Map:
+		if v1.IsNil() != v2.IsNil() {
+			return false
+		}
+		if v1.Len() != v2.Len() {
+			return false
+		}
+		if v1.Pointer() == v2.Pointer() {
+			return true
+		}
+		for _, k := range v1.MapKeys() {
+			if !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) {
+				return false
+			}
+		}
+		return true
+	case Func:
+		if v1.IsNil() && v2.IsNil() {
+			return true
+		}
+		// Can't do better than this:
+		return false
+	default:
+		// Normal equality suffices
+		return valueInterface(v1, false) == valueInterface(v2, false)
+	}
+}
+
+// DeepEqual tests for deep equality. It uses normal == equality where
+// possible but will scan elements of arrays, slices, maps, and fields of
+// structs. In maps, keys are compared with == but elements use deep
+// equality. DeepEqual correctly handles recursive types. Functions are equal
+// only if they are both nil.
+// An empty slice is not equal to a nil slice.
+func DeepEqual(a1, a2 interface{}) bool {
+	if a1 == nil || a2 == nil {
+		return a1 == a2
+	}
+	v1 := ValueOf(a1)
+	v2 := ValueOf(a2)
+	if v1.Type() != v2.Type() {
+		return false
+	}
+	return deepValueEqual(v1, v2, make(map[visit]bool), 0)
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/example_test.go b/third_party/gofrontend/libgo/go/reflect/example_test.go
new file mode 100644
index 0000000..cca28ee
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/example_test.go
@@ -0,0 +1,66 @@
+// 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 reflect_test
+
+import (
+	"fmt"
+	"reflect"
+)
+
+func ExampleMakeFunc() {
+	// swap is the implementation passed to MakeFunc.
+	// It must work in terms of reflect.Values so that it is possible
+	// to write code without knowing beforehand what the types
+	// will be.
+	swap := func(in []reflect.Value) []reflect.Value {
+		return []reflect.Value{in[1], in[0]}
+	}
+
+	// makeSwap expects fptr to be a pointer to a nil function.
+	// It sets that pointer to a new function created with MakeFunc.
+	// When the function is invoked, reflect turns the arguments
+	// into Values, calls swap, and then turns swap's result slice
+	// into the values returned by the new function.
+	makeSwap := func(fptr interface{}) {
+		// fptr is a pointer to a function.
+		// Obtain the function value itself (likely nil) as a reflect.Value
+		// so that we can query its type and then set the value.
+		fn := reflect.ValueOf(fptr).Elem()
+
+		// Make a function of the right type.
+		v := reflect.MakeFunc(fn.Type(), swap)
+
+		// Assign it to the value fn represents.
+		fn.Set(v)
+	}
+
+	// Make and call a swap function for ints.
+	var intSwap func(int, int) (int, int)
+	makeSwap(&intSwap)
+	fmt.Println(intSwap(0, 1))
+
+	// Make and call a swap function for float64s.
+	var floatSwap func(float64, float64) (float64, float64)
+	makeSwap(&floatSwap)
+	fmt.Println(floatSwap(2.72, 3.14))
+
+	// Output:
+	// 1 0
+	// 3.14 2.72
+}
+
+func ExampleStructTag() {
+	type S struct {
+		F string `species:"gopher" color:"blue"`
+	}
+
+	s := S{}
+	st := reflect.TypeOf(s)
+	field := st.Field(0)
+	fmt.Println(field.Tag.Get("color"), field.Tag.Get("species"))
+
+	// Output:
+	// blue gopher
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/export_test.go b/third_party/gofrontend/libgo/go/reflect/export_test.go
new file mode 100644
index 0000000..0778ad3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/export_test.go
@@ -0,0 +1,19 @@
+// 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 reflect
+
+// MakeRO returns a copy of v with the read-only flag set.
+func MakeRO(v Value) Value {
+	v.flag |= flagRO
+	return v
+}
+
+// IsRO reports whether v's read-only flag is set.
+func IsRO(v Value) bool {
+	return v.flag&flagRO != 0
+}
+
+var ArrayOf = arrayOf
+var CallGC = &callGC
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc.go b/third_party/gofrontend/libgo/go/reflect/makefunc.go
new file mode 100644
index 0000000..eb4589c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefunc.go
@@ -0,0 +1,193 @@
+// 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.
+
+// MakeFunc implementation.
+
+package reflect
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+// makeFuncImpl is the closure value implementing the function
+// returned by MakeFunc.
+type makeFuncImpl struct {
+	code uintptr
+	typ  *funcType
+	fn   func([]Value) []Value
+
+	// For gccgo we use the same entry point for functions and for
+	// method values.
+	method int
+	rcvr   Value
+
+	// When using FFI, hold onto the FFI closure for the garbage
+	// collector.
+	ffi *ffiData
+}
+
+// MakeFunc returns a new function of the given Type
+// that wraps the function fn. When called, that new function
+// does the following:
+//
+//	- converts its arguments to a slice of Values.
+//	- runs results := fn(args).
+//	- returns the results as a slice of Values, one per formal result.
+//
+// The implementation fn can assume that the argument Value slice
+// has the number and type of arguments given by typ.
+// If typ describes a variadic function, the final Value is itself
+// a slice representing the variadic arguments, as in the
+// body of a variadic function. The result Value slice returned by fn
+// must have the number and type of results given by typ.
+//
+// The Value.Call method allows the caller to invoke a typed function
+// in terms of Values; in contrast, MakeFunc allows the caller to implement
+// a typed function in terms of Values.
+//
+// The Examples section of the documentation includes an illustration
+// of how to use MakeFunc to build a swap function for different types.
+//
+func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
+	if typ.Kind() != Func {
+		panic("reflect: call of MakeFunc with non-Func type")
+	}
+
+	t := typ.common()
+	ftyp := (*funcType)(unsafe.Pointer(t))
+
+	var code uintptr
+	var ffi *ffiData
+	switch runtime.GOARCH {
+	case "amd64", "386", "s390", "s390x":
+		// Indirect Go func value (dummy) to obtain actual
+		// code address. (A Go func value is a pointer to a C
+		// function pointer. http://golang.org/s/go11func.)
+		dummy := makeFuncStub
+		code = **(**uintptr)(unsafe.Pointer(&dummy))
+	default:
+		code, ffi = makeFuncFFI(ftyp, fn)
+	}
+
+	impl := &makeFuncImpl{
+		code:   code,
+		typ:    ftyp,
+		fn:     fn,
+		method: -1,
+		ffi:    ffi,
+	}
+
+	return Value{t, unsafe.Pointer(&impl), flag(Func<<flagKindShift) | flagIndir}
+}
+
+// makeFuncStub is an assembly function that is the code half of
+// the function returned from MakeFunc. It expects a *callReflectFunc
+// as its context register, and its job is to invoke callReflect(ctxt, frame)
+// where ctxt is the context register and frame is a pointer to the first
+// word in the passed-in argument frame.
+func makeFuncStub()
+
+// makeMethodValue converts v from the rcvr+method index representation
+// of a method value to an actual method func value, which is
+// basically the receiver value with a special bit set, into a true
+// func value - a value holding an actual func. The output is
+// semantically equivalent to the input as far as the user of package
+// reflect can tell, but the true func representation can be handled
+// by code like Convert and Interface and Assign.
+func makeMethodValue(op string, v Value) Value {
+	if v.flag&flagMethod == 0 {
+		panic("reflect: internal error: invalid use of makeMethodValue")
+	}
+
+	// Ignoring the flagMethod bit, v describes the receiver, not the method type.
+	fl := v.flag & (flagRO | flagAddr | flagIndir)
+	fl |= flag(v.typ.Kind()) << flagKindShift
+	rcvr := Value{v.typ, v.ptr /* v.scalar, */, fl}
+
+	// v.Type returns the actual type of the method value.
+	ft := v.Type().(*rtype)
+
+	// Cause panic if method is not appropriate.
+	// The panic would still happen during the call if we omit this,
+	// but we want Interface() and other operations to fail early.
+	_, t, _ := methodReceiver(op, rcvr, int(v.flag)>>flagMethodShift)
+
+	ftyp := (*funcType)(unsafe.Pointer(t))
+	method := int(v.flag) >> flagMethodShift
+
+	fv := &makeFuncImpl{
+		typ:    ftyp,
+		method: method,
+		rcvr:   rcvr,
+	}
+
+	switch runtime.GOARCH {
+	case "amd64", "386":
+		// Indirect Go func value (dummy) to obtain actual
+		// code address. (A Go func value is a pointer to a C
+		// function pointer. http://golang.org/s/go11func.)
+		dummy := makeFuncStub
+		fv.code = **(**uintptr)(unsafe.Pointer(&dummy))
+	default:
+		fv.code, fv.ffi = makeFuncFFI(ftyp, fv.call)
+	}
+
+	return Value{ft, unsafe.Pointer(&fv), v.flag&flagRO | flag(Func)<<flagKindShift | flagIndir}
+}
+
+// makeValueMethod takes a method function and returns a function that
+// takes a value receiver and calls the real method with a pointer to
+// it.
+func makeValueMethod(v Value) Value {
+	typ := v.typ
+	if typ.Kind() != Func {
+		panic("reflect: call of makeValueMethod with non-Func type")
+	}
+	if v.flag&flagMethodFn == 0 {
+		panic("reflect: call of makeValueMethod with non-MethodFn")
+	}
+
+	t := typ.common()
+	ftyp := (*funcType)(unsafe.Pointer(t))
+
+	impl := &makeFuncImpl{
+		typ:    ftyp,
+		method: -2,
+		rcvr:   v,
+	}
+
+	switch runtime.GOARCH {
+	case "amd64", "386", "s390", "s390x":
+		// Indirect Go func value (dummy) to obtain actual
+		// code address. (A Go func value is a pointer to a C
+		// function pointer. http://golang.org/s/go11func.)
+		dummy := makeFuncStub
+		impl.code = **(**uintptr)(unsafe.Pointer(&dummy))
+	default:
+		impl.code, impl.ffi = makeFuncFFI(ftyp, impl.call)
+	}
+
+	return Value{t, unsafe.Pointer(&impl), flag(Func<<flagKindShift) | flagIndir}
+}
+
+// Call the function represented by a makeFuncImpl.
+func (c *makeFuncImpl) call(in []Value) []Value {
+	if c.method == -1 {
+		return c.fn(in)
+	} else if c.method == -2 {
+		if c.typ.IsVariadic() {
+			return c.rcvr.CallSlice(in)
+		} else {
+			return c.rcvr.Call(in)
+		}
+	} else {
+		m := c.rcvr.Method(c.method)
+		if c.typ.IsVariadic() {
+			return m.CallSlice(in)
+		} else {
+			return m.Call(in)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_386.S b/third_party/gofrontend/libgo/go/reflect/makefunc_386.S
new file mode 100644
index 0000000..0e2e764
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefunc_386.S
@@ -0,0 +1,230 @@
+/* Copyright 2013 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.
+
+   MakeFunc 386 assembly code.  */
+
+#include "config.h"
+
+	.globl reflect.makeFuncStub
+
+#ifdef __ELF__
+	.type reflect.makeFuncStub,@function
+#endif
+
+reflect.makeFuncStub:
+.LFB1:
+
+	/* Go does not provide any equivalent to the regparm function
+	   attribute, so on Go we do not need to worry about passing
+	   parameters in registers.  We just pass a pointer to the
+	   arguments on the stack.
+	
+	   We do need to pick up the return values, though, so we pass
+	   a pointer to a struct that looks like this.
+	   struct {
+	     esp uint32		// 0x0
+	     eax uint32		// 0x4
+	     st0 float64	// 0x8
+	     sr  bool		// 0x10
+	     sf  bool		// 0x11
+	   }
+	   The sr field is set by the function to a non-zero value if
+	   the function takes a struct hidden pointer that must be
+	   popped off the stack.  */
+
+	pushl	%ebp
+.LCFI0:
+	movl	%esp, %ebp
+.LCFI1:
+	pushl	%ebx		/* In case this is PIC.  */
+	subl	$36, %esp	/* Enough for args and to align stack.  */
+.LCFI2:
+
+#ifdef __PIC__
+	call	__x86.get_pc_thunk.bx
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+#endif
+
+	leal	8(%ebp), %eax	/* Set esp field in struct.  */
+	movl	%eax, -24(%ebp)
+
+	/* For MakeFunc functions that call recover.  */
+	movl	4(%ebp), %eax
+	movl	%eax, (%esp)
+#ifdef __PIC__
+	call	__go_makefunc_can_recover@PLT
+#else
+	call	__go_makefunc_can_recover
+#endif
+
+#ifdef __PIC__
+	call	__go_get_closure@PLT
+#else
+	call	__go_get_closure
+#endif
+
+	movl	%eax, 4(%esp)
+
+	leal	-24(%ebp), %eax
+	movl	%eax, (%esp)
+
+#ifdef __PIC__
+	call	reflect.MakeFuncStubGo@PLT
+#else
+	call	reflect.MakeFuncStubGo
+#endif
+
+	/* MakeFunc functions can no longer call recover.  */
+#ifdef __PIC__
+	call __go_makefunc_returning@PLT
+#else
+	call __go_makefunc_returning
+#endif
+
+	/* Set return registers.  */
+
+	movl	-20(%ebp), %eax
+
+	cmpb	$0, -7(%ebp)
+	je	2f
+
+	fldl	-16(%ebp)
+
+#ifdef __SSE2__
+	/* In case we are compiling with -msseregparm.  This won't work
+	   correctly if only SSE1 is supported, but that seems unlikely.  */
+	movsd	-16(%ebp), %xmm0
+#endif
+
+2:
+	movb	-8(%ebp), %dl
+
+	addl	$36, %esp
+	popl	%ebx
+.LCFI3:
+	popl	%ebp
+.LCFI4:
+
+	testb	%dl,%dl
+	jne	1f
+	ret
+1:
+	ret	$4
+.LFE1:
+#ifdef __ELF__
+	.size	reflect.makeFuncStub, . - reflect.makeFuncStub
+#endif
+
+#ifdef __PIC__
+#ifdef HAVE_AS_COMDAT_GAS
+	.section	.text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+#else
+	/* Sun as needs a different syntax.  */
+	.section	.text.__x86.get_pc_thunk.bx%__x86.get_pc_thunk.bx,"ax",@progbits
+	.group		__x86.get_pc_thunk.bx,.text.__x86.get_pc_thunk.bx%__x86.get_pc_thunk.bx,#comdat
+#endif
+	.globl	__x86.get_pc_thunk.bx
+	.hidden	__x86.get_pc_thunk.bx
+#ifdef __ELF__
+	.type	__x86.get_pc_thunk.bx, @function
+#endif
+__x86.get_pc_thunk.bx:
+.LFB2:
+	movl	(%esp), %ebx
+	ret
+.LFE2:
+#ifdef __ELF__
+	.size	__x86.get_pc_thunk.bx, . - __x86.get_pc_thunk.bx
+#endif
+#endif
+
+#ifdef __ELF__
+#if defined __PIC__
+# if defined __sun__ && defined __svr4__
+/* 32-bit Solaris 2/x86 uses datarel encoding for PIC.  GNU ld before 2.22
+   doesn't correctly sort .eh_frame_hdr with mixed encodings, so match this.  */
+#  define FDE_ENCODING		0x30	/* datarel */
+#  define FDE_ENCODE(X)		X@GOTOFF
+# else
+#  define FDE_ENCODING		0x1b	/* pcrel sdata4 */
+#  if defined HAVE_AS_X86_PCREL
+#   define FDE_ENCODE(X)	X-.
+#  else
+#   define FDE_ENCODE(X)	X@rel
+#  endif
+# endif
+#else
+# define FDE_ENCODING		0	/* absolute */
+# define FDE_ENCODE(X)		X
+#endif
+
+	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
+.LSCIE1:
+	.long	0x0	/* CIE Identifier Tag */
+	.byte	0x1	/* CIE Version */
+	.ascii "zR\0"	/* CIE Augmentation */
+	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
+	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
+	.byte	0x8	/* CIE RA Column */
+	.byte	0x1	/* .uleb128 0x1; Augmentation size */
+	.byte	FDE_ENCODING
+	.byte	0xc	/* DW_CFA_def_cfa */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x88	/* DW_CFA_offset, column 0x8 */
+	.byte	0x1	/* .uleb128 0x1 */
+	.align 4
+.LECIE1:
+.LSFDE1:
+	.long	.LEFDE1-.LASFDE1	/* FDE Length */
+.LASFDE1:
+	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
+	.long	FDE_ENCODE(.LFB1)	/* FDE initial location */
+	.long	.LFE1-.LFB1		/* FDE address range */
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI0-.LFB1
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 */
+	.byte	0x2	/* .uleb128 0x2 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI1-.LCFI0
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0x5	/* .uleb128 0x5 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI2-.LCFI1
+	.byte	0x83	/* .DW_CFA_offset, column 0x3 */
+	.byte	0x3	/* .uleb128 0x3 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI3-.LCFI2
+	.byte	0xc3	/* DW_CFA_restore, column 0x3 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI4-.LCFI3
+	.byte	0xc5	/* DW_CFA_restore, column 0x5 */
+	.byte	0xc	/* DW_CFA_def_cfa */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x4	/* .uleb128 0x4 */
+	.align 4
+.LEFDE1:
+#ifdef __PIC__
+.LSFDE2:
+	.long	.LEFDE2-.LASFDE2	/* FDE Length */
+.LASFDE2:
+	.long	.LASFDE2-.Lframe1	/* FDE CIE offset */
+	.long	FDE_ENCODE(.LFB2)	/* FDE initial location */
+	.long	.LFE2-.LFB2		/* FDE address range */
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+	.align 4
+.LEFDE2:
+#endif /* __PIC__ */
+#endif /* __ELF__ */
+
+#if defined(__ELF__) && defined(__linux__)
+	.section	.note.GNU-stack,"",@progbits
+	.section	.note.GNU-split-stack,"",@progbits
+	.section	.note.GNU-no-split-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_amd64.S b/third_party/gofrontend/libgo/go/reflect/makefunc_amd64.S
new file mode 100644
index 0000000..88302ee
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefunc_amd64.S
@@ -0,0 +1,177 @@
+# Copyright 2013 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.
+
+# MakeFunc amd64 assembly code.
+
+#include "config.h"
+
+	.global	reflect.makeFuncStub
+
+#ifdef __ELF__
+	.type	reflect.makeFuncStub,@function
+#endif
+
+reflect.makeFuncStub:
+.LFB1:
+
+	# Store all the parameter registers in a struct that looks
+	# like:
+	# struct {
+	#   rax uint64		// 0x0
+	#   rdi uint64		// 0x8
+	#   rsi uint64		// 0x10
+	#   rdx uint64		// 0x18
+	#   rcx uint64		// 0x20
+	#   r8 uint64		// 0x28
+	#   r9 uint64		// 0x30
+	#   rsp uint64		// 0x38 Pointer to arguments on stack.
+	#   xmm0 [2]uint64	// 0x40
+	#   xmm1 [2]uint64	// 0x50
+	#   xmm2 [2]uint64	// 0x60
+	#   xmm3 [2]uint64	// 0x70
+	#   xmm4 [2]uint64	// 0x80
+	#   xmm5 [2]uint64	// 0x90
+	#   xmm6 [2]uint64	// 0xa0
+	#   xmm7 [2]uint64	// 0xb0
+	# };
+
+	pushq	%rbp
+.LCFI0:
+	movq	%rsp, %rbp
+.LCFI1:
+
+	subq	$0xc0, %rsp		# Space for struct on stack.
+
+	movq	%rax, 0x0(%rsp)
+	movq	%rdi, 0x8(%rsp)
+	movq	%rsi, 0x10(%rsp)
+	movq	%rdx, 0x18(%rsp)
+	movq	%rcx, 0x20(%rsp)
+	movq	%r8, 0x28(%rsp)
+	movq	%r9, 0x30(%rsp)
+	leaq	16(%rbp), %rax
+	movq	%rax, 0x38(%rsp)
+	movdqa	%xmm0, 0x40(%rsp)
+	movdqa	%xmm1, 0x50(%rsp)
+	movdqa	%xmm2, 0x60(%rsp)
+	movdqa	%xmm3, 0x70(%rsp)
+	movdqa	%xmm4, 0x80(%rsp)
+	movdqa	%xmm5, 0x90(%rsp)
+	movdqa	%xmm6, 0xa0(%rsp)
+	movdqa	%xmm7, 0xb0(%rsp)
+
+	/* For MakeFunc functions that call recover.  */
+	movq	8(%rbp), %rdi
+#ifdef __PIC__
+	call	__go_makefunc_can_recover@PLT
+#else
+	call	__go_makefunc_can_recover
+#endif
+
+	# Get function type.
+#ifdef __PIC__
+	call	__go_get_closure@PLT
+#else
+	call	__go_get_closure
+#endif
+	movq	%rax, %rsi
+
+	movq	%rsp, %rdi
+
+#ifdef __PIC__
+	call	reflect.MakeFuncStubGo@PLT
+#else
+	call	reflect.MakeFuncStubGo
+#endif
+
+	/* MakeFunc functions can no longer call recover.  */
+#ifdef __PIC__
+	call __go_makefunc_returning@PLT
+#else
+	call __go_makefunc_returning
+#endif
+
+	# The structure will be updated with any return values.  Load
+	# all possible return registers before returning to the caller.
+
+	movq	0x0(%rsp), %rax
+	movq	0x18(%rsp), %rdx
+	movq	0x8(%rsp), %rdi
+	movq	0x10(%rsp), %rsi
+	movdqa	0x40(%rsp), %xmm0
+	movdqa	0x50(%rsp), %xmm1
+
+	# long double values are returned on the floating point stack,
+	# but we don't worry about that since Go doesn't have a long
+	# double type.
+
+	leave
+.LCFI2:
+
+	ret
+.LFE1:
+
+#ifdef __ELF__
+	.size	reflect.makeFuncStub, . - reflect.makeFuncStub
+#endif
+
+#ifdef __ELF__
+#ifdef HAVE_AS_X86_64_UNWIND_SECTION_TYPE
+	.section	.eh_frame,"a",@unwind
+#else
+	.section	.eh_frame,"a",@progbits
+#endif
+.Lframe1:
+	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
+.LSCIE1:
+	.long	0x0		/* CIE Identifier Tag */
+	.byte	0x1		/* CIE Version */
+	.ascii "zR\0"		/* CIE Augmentation */
+	.uleb128 1		/* CIE Code Alignment Factor */
+	.sleb128 -8		/* CIE Data Alignment Factor */
+	.byte	0x10		/* CIE RA Column */
+	.uleb128 1		/* Augmentation size */
+	.byte	0x1b		/* FDE Encoding (pcrel sdata4) */
+	.byte	0xc		/* DW_CFA_def_cfa, %rsp offset 8 */
+	.uleb128 7
+	.uleb128 8
+	.byte	0x80+16		/* DW_CFA_offset, %rip offset 1*-8 */
+	.uleb128 1
+	.align 8
+.LECIE1:
+.LSFDE1:
+	.long	.LEFDE1-.LASFDE1	/* FDE Length */
+.LASFDE1:
+	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
+#if HAVE_AS_X86_PCREL
+	.long	.LFB1-.			/* FDE initial location */
+#else
+	.long	.LFB1@rel
+#endif
+	.long	.LFE1-.LFB1		/* FDE address range */
+	.uleb128 0x0			/* Augmentation size */
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.long	.LCFI0-.LFB1
+	.byte	0xe			/* DW_CFA_def_cfa_offset */
+	.uleb128 16
+	.byte	0x86			/* DW_CFA_offset, column 0x6 */
+	.uleb128 2
+	.byte	0x4			/* DW_CFA_advance_loc4 */
+	.long	.LCFI1-.LCFI0
+	.byte	0xd			/* DW_CFA_def_cfa_register */
+	.uleb128 6
+	.byte	0x2			/* DW_CFA_advance_loc1 */
+	.byte	.LCFI2-.LCFI1
+	.byte	0xc			/* DW_CFA_def_cfa */
+	.uleb128 7
+	.uleb128 8
+	.align 8
+.LEFDE1:
+#endif /* __ELF__ */
+
+#if defined(__ELF__) && defined(__linux__)
+	.section	.note.GNU-stack,"",@progbits
+	.section	.note.GNU-split-stack,"",@progbits
+	.section	.note.GNU-no-split-stack,"",@progbits
+#endif
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_dummy.c b/third_party/gofrontend/libgo/go/reflect/makefunc_dummy.c
new file mode 100644
index 0000000..8eff0c1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefunc_dummy.c
@@ -0,0 +1,15 @@
+// Copyright 2013 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 "runtime.h"
+
+/* Dummy function for processors that implement MakeFunc using FFI
+   rather than having builtin support.  */
+
+void makeFuncStub (void) __asm__ ("reflect.makeFuncStub");
+
+void makeFuncStub (void)
+{
+  runtime_throw ("impossible call to makeFuncStub");
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_ffi.go b/third_party/gofrontend/libgo/go/reflect/makefunc_ffi.go
new file mode 100644
index 0000000..a13ef17
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefunc_ffi.go
@@ -0,0 +1,88 @@
+// Copyright 2014 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 reflect
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+// The ffi function, written in C, allocates an FFI closure.  It
+// returns the code and data pointers.  When the code pointer is
+// called, it will call callback.  CIF is an FFI data structure
+// allocated as part of the closure, and is returned to ensure that
+// the GC retains it.
+func ffi(ftyp *funcType, callback func(unsafe.Pointer, unsafe.Pointer)) (code uintptr, data uintptr, cif unsafe.Pointer)
+
+// The ffiFree function, written in C, releases the FFI closure.
+func ffiFree(uintptr)
+
+// An ffiData holds the information needed to preserve an FFI closure
+// for the garbage collector.
+type ffiData struct {
+	code     uintptr
+	data     uintptr
+	cif      unsafe.Pointer
+	callback func(unsafe.Pointer, unsafe.Pointer)
+}
+
+// The makeFuncFFI function uses libffi closures to implement
+// reflect.MakeFunc.  This is used for processors for which we don't
+// have more efficient support.
+func makeFuncFFI(ftyp *funcType, fn func(args []Value) (results []Value)) (uintptr, *ffiData) {
+	callback := func(params, results unsafe.Pointer) {
+		ffiCall(ftyp, fn, params, results)
+	}
+
+	code, data, cif := ffi(ftyp, callback)
+
+	c := &ffiData{code: code, data: data, cif: cif, callback: callback}
+
+	runtime.SetFinalizer(c,
+		func(p *ffiData) {
+			ffiFree(p.data)
+		})
+
+	return code, c
+}
+
+// ffiCall takes pointers to the parameters, calls the function, and
+// stores the results back into memory.
+func ffiCall(ftyp *funcType, fn func([]Value) []Value, params unsafe.Pointer, results unsafe.Pointer) {
+	in := make([]Value, 0, len(ftyp.in))
+	ap := params
+	for _, rt := range ftyp.in {
+		p := unsafe_New(rt)
+		memmove(p, *(*unsafe.Pointer)(ap), rt.size)
+		v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
+		in = append(in, v)
+		ap = (unsafe.Pointer)(uintptr(ap) + ptrSize)
+	}
+
+	out := fn(in)
+
+	off := uintptr(0)
+	for i, typ := range ftyp.out {
+		v := out[i]
+		if v.typ != typ {
+			panic("reflect: function created by MakeFunc using " + funcName(fn) +
+				" returned wrong type: have " +
+				out[i].typ.String() + " for " + typ.String())
+		}
+		if v.flag&flagRO != 0 {
+			panic("reflect: function created by MakeFunc using " + funcName(fn) +
+				" returned value obtained from unexported field")
+		}
+
+		off = align(off, uintptr(typ.fieldAlign))
+		addr := unsafe.Pointer(uintptr(results) + off)
+		if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+			*(*unsafe.Pointer)(addr) = v.ptr
+		} else {
+			memmove(addr, v.ptr, typ.size)
+		}
+		off += typ.size
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_ffi_c.c b/third_party/gofrontend/libgo/go/reflect/makefunc_ffi_c.c
new file mode 100644
index 0000000..a3dfd4a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefunc_ffi_c.c
@@ -0,0 +1,128 @@
+// Copyright 2014 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 "runtime.h"
+#include "go-type.h"
+#include "go-panic.h"
+
+#ifdef USE_LIBFFI
+
+#include "go-ffi.h"
+
+#if FFI_CLOSURES
+#define USE_LIBFFI_CLOSURES
+#endif
+
+#endif /* defined(USE_LIBFFI) */
+
+/* Declare C functions with the names used to call from Go.  */
+
+struct ffi_ret {
+  void *code;
+  void *data;
+  void *cif;
+};
+
+struct ffi_ret ffi(const struct __go_func_type *ftyp, FuncVal *callback)
+  __asm__ (GOSYM_PREFIX "reflect.ffi");
+
+void ffiFree(void *data)
+  __asm__ (GOSYM_PREFIX "reflect.ffiFree");
+
+#ifdef USE_LIBFFI_CLOSURES
+
+/* The function that we pass to ffi_prep_closure_loc.  This calls the
+   Go callback function (passed in user_data) with the pointer to the
+   arguments and the results area.  */
+
+static void ffi_callback (ffi_cif *, void *, void **, void *)
+  __asm__ ("reflect.ffi_callback");
+
+static void
+ffi_callback (ffi_cif* cif __attribute__ ((unused)), void *results,
+	      void **args, void *user_data)
+{
+  Location locs[8];
+  int n;
+  int i;
+  FuncVal *fv;
+  void (*f) (void *, void *);
+
+  /* This function is called from some series of FFI closure functions
+     called by a Go function.  We want to see whether the caller of
+     the closure functions can recover.  Look up the stack and skip
+     the FFI functions.  */
+  n = runtime_callers (1, &locs[0], sizeof locs / sizeof locs[0], true);
+  for (i = 0; i < n; i++)
+    {
+      const byte *name;
+
+      if (locs[i].function.len == 0)
+	continue;
+      if (locs[i].function.len < 4)
+	break;
+      name = locs[i].function.str;
+      if (name[0] != 'f' || name[1] != 'f' || name[2] != 'i' || name[3] != '_')
+	break;
+    }
+  if (i < n)
+    __go_makefunc_ffi_can_recover (locs + i, n - i);
+
+  fv = (FuncVal *) user_data;
+  __go_set_closure (fv);
+  f = (void *) fv->fn;
+  f (args, results);
+
+  if (i < n)
+    __go_makefunc_returning ();
+}
+
+/* Allocate an FFI closure and arrange to call ffi_callback.  */
+
+struct ffi_ret
+ffi (const struct __go_func_type *ftyp, FuncVal *callback)
+{
+  ffi_cif *cif;
+  void *code;
+  void *data;
+  struct ffi_ret ret;
+
+  cif = (ffi_cif *) __go_alloc (sizeof (ffi_cif));
+  __go_func_to_cif (ftyp, 0, 0, cif);
+  data = ffi_closure_alloc (sizeof (ffi_closure), &code);
+  if (data == NULL)
+    runtime_panicstring ("ffi_closure_alloc failed");
+  if (ffi_prep_closure_loc (data, cif, ffi_callback, callback, code)
+      != FFI_OK)
+    runtime_panicstring ("ffi_prep_closure_loc failed");
+  ret.code = code;
+  ret.data = data;
+  ret.cif = cif;
+  return ret;
+}
+
+/* Free the FFI closure.  */
+
+void
+ffiFree (void *data)
+{
+  ffi_closure_free (data);
+}
+
+#else /* !defined(USE_LIBFFI_CLOSURES) */
+
+struct ffi_ret
+ffi(const struct __go_func_type *ftyp, FuncVal *callback)
+{
+  runtime_panicstring ("libgo built without FFI does not support "
+		       "reflect.MakeFunc");
+}
+
+void ffiFree(void *data)
+{
+  runtime_panicstring ("libgo built without FFI does not support "
+		       "reflect.MakeFunc");
+}
+
+#endif
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_s390.c b/third_party/gofrontend/libgo/go/reflect/makefunc_s390.c
new file mode 100644
index 0000000..78a960c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefunc_s390.c
@@ -0,0 +1,86 @@
+// Copyright 2014 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 "runtime.h"
+#include "go-panic.h"
+
+#ifdef __s390x__
+#  define S390_GO_USE_64_BIT_ABI 1
+#  define S390_GO_S390X_ARGS , double f4, double f6
+#  define S390_GO_S390X_FIELDS double f4; double f6;
+   extern void S390xMakeFuncStubGo(void *, void *)
+	asm ("reflect.S390xMakeFuncStubGo");
+#  define S390_GO_MakeFuncStubGo(r, c) S390xMakeFuncStubGo((r), (c))
+#else
+#  define S390_GO_USE_64_BIT_ABI 0
+#  define S390_GO_S390X_ARGS
+#  define S390_GO_S390X_FIELDS
+   extern void S390MakeFuncStubGo(void *, void *)
+	asm ("reflect.S390MakeFuncStubGo");
+#  define S390_GO_MakeFuncStubGo(r, c) S390MakeFuncStubGo((r), (c))
+   /* Needed to make the unused 64 bit abi conditional code compile.  */
+#  define f4 f0
+#  define f6 f2
+#endif
+
+/* Structure to store all registers used for parameter passing.  */
+typedef struct
+{
+	long r2;
+	long r3;
+	long r4;
+	long r5;
+	long r6;
+	/* Pointer to non-register arguments on the stack.  */
+	long stack_args;
+	double f0;
+	double f2;
+	S390_GO_S390X_FIELDS
+} s390Regs;
+
+void
+makeFuncStub(long r2, long r3, long r4, long r5, long r6,
+	unsigned long stack_args, double f0, double f2
+	S390_GO_S390X_ARGS)
+	asm ("reflect.makeFuncStub");
+
+void
+makeFuncStub(long r2, long r3, long r4, long r5, long r6,
+	unsigned long stack_args, double f0, double f2
+	S390_GO_S390X_ARGS)
+{
+	s390Regs regs;
+	void *closure;
+
+	/* Store the registers in a structure that is passed on to the Go stub
+	   function.  */
+	regs.r2 = r2;
+	regs.r3 = r3;
+	regs.r4 = r4;
+	regs.r5 = r5;
+	regs.r6 = r6;
+	regs.stack_args = (long)&stack_args;
+	regs.f0 = f0;
+	regs.f2 = f2;
+	if (S390_GO_USE_64_BIT_ABI) {
+		regs.f4 = f4;
+		regs.f6 = f6;
+	}
+	/* For MakeFunc functions that call recover.  */
+	__go_makefunc_can_recover(__builtin_return_address(0));
+	/* Call the Go stub function.  */
+	closure = __go_get_closure();
+	S390_GO_MakeFuncStubGo(&regs, closure);
+	/* MakeFunc functions can no longer call recover.  */
+	__go_makefunc_returning();
+	/* Restore all possible return registers.  */
+	if (S390_GO_USE_64_BIT_ABI) {
+		asm volatile ("lg\t%%r2,0(%0)" : : "a" (&regs.r2) : "r2" );
+		asm volatile ("ld\t%%f0,0(%0)" : : "a" (&regs.f0) : "f0" );
+	} else {
+		asm volatile ("l\t%%r2,0(%0)" : : "a" (&regs.r2) : "r2" );
+		asm volatile ("l\t%%r3,0(%0)" : : "a" (&regs.r3) : "r3" );
+		asm volatile ("ld\t%%f0,0(%0)" : : "a" (&regs.f0) : "f0" );
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefuncgo_386.go b/third_party/gofrontend/libgo/go/reflect/makefuncgo_386.go
new file mode 100644
index 0000000..7809fb0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefuncgo_386.go
@@ -0,0 +1,142 @@
+// Copyright 2013 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.
+
+// MakeFunc 386 implementation.
+
+package reflect
+
+import "unsafe"
+
+// The assembler stub will pass a pointer to this structure.  We
+// assume that no parameters are passed in registers--that is, we do
+// not support the -mregparm option.  On return we will set the
+// registers that might hold result values.
+type i386Regs struct {
+	esp uint32
+	eax uint32  // Value to return in %eax.
+	st0 float64 // Value to return in %st(0).
+	sr  bool    // Set to true if hidden struct pointer.
+	sf  bool    // Set to true if returning float
+}
+
+// MakeFuncStubGo implements the 386 calling convention for MakeFunc.
+// This should not be called.  It is exported so that assembly code
+// can call it.
+
+func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) {
+	ftyp := c.typ
+
+	// See if the result requires a struct.  If it does, the first
+	// parameter is a pointer to the struct.
+	retStruct := false
+	retEmpty := false
+	switch len(ftyp.out) {
+	case 0:
+		retEmpty = true
+	case 1:
+		if ftyp.out[0].size == 0 {
+			retEmpty = true
+		} else {
+			switch ftyp.out[0].Kind() {
+			case Complex64, Complex128, Array, Interface, Slice, String, Struct:
+				retStruct = true
+			}
+		}
+	default:
+		size := uintptr(0)
+		for _, typ := range ftyp.out {
+			size += typ.size
+		}
+		if size == 0 {
+			retEmpty = true
+		} else {
+			retStruct = true
+		}
+	}
+
+	in := make([]Value, 0, len(ftyp.in))
+	ap := uintptr(regs.esp)
+
+	regs.sr = false
+	regs.sf = false
+	var retPtr unsafe.Pointer
+	if retStruct {
+		retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap))
+		ap += ptrSize
+		regs.sr = true
+	}
+
+	for _, rt := range ftyp.in {
+		ap = align(ap, ptrSize)
+
+		// We have to copy the argument onto the heap in case
+		// the function hangs on the reflect.Value we pass it.
+		p := unsafe_New(rt)
+		memmove(p, unsafe.Pointer(ap), rt.size)
+
+		v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
+		in = append(in, v)
+		ap += rt.size
+	}
+
+	// Call the real function.
+
+	out := c.call(in)
+
+	if len(out) != len(ftyp.out) {
+		panic("reflect: wrong return count from function created by MakeFunc")
+	}
+
+	for i, typ := range ftyp.out {
+		v := out[i]
+		if v.typ != typ {
+			panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
+				" returned wrong type: have " +
+				out[i].typ.String() + " for " + typ.String())
+		}
+		if v.flag&flagRO != 0 {
+			panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
+				" returned value obtained from unexported field")
+		}
+	}
+
+	if retEmpty {
+		return
+	}
+
+	if retStruct {
+		off := uintptr(0)
+		for i, typ := range ftyp.out {
+			v := out[i]
+			off = align(off, uintptr(typ.fieldAlign))
+			addr := unsafe.Pointer(uintptr(retPtr) + off)
+			if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+				*(*unsafe.Pointer)(addr) = v.ptr
+			} else {
+				memmove(addr, v.ptr, typ.size)
+			}
+			off += typ.size
+		}
+		regs.eax = uint32(uintptr(retPtr))
+		return
+	}
+
+	if len(ftyp.out) != 1 {
+		panic("inconsistency")
+	}
+
+	v := out[0]
+	switch v.Kind() {
+	case Ptr, UnsafePointer:
+		regs.eax = uint32(uintptr(v.pointer()))
+	case Float32:
+		regs.st0 = float64(*(*float32)(v.ptr))
+		regs.sf = true
+	case Float64:
+		regs.st0 = *(*float64)(v.ptr)
+		regs.sf = true
+	default:
+		regs.eax = uint32(loadScalar(v.ptr, v.typ.size))
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefuncgo_amd64.go b/third_party/gofrontend/libgo/go/reflect/makefuncgo_amd64.go
new file mode 100644
index 0000000..7118951
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefuncgo_amd64.go
@@ -0,0 +1,495 @@
+// Copyright 2013 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.
+
+// MakeFunc amd64 implementation.
+
+package reflect
+
+import "unsafe"
+
+// The assembler stub will pass a pointer to this structure.
+// This will come in holding all the registers that might hold
+// function parameters.  On return we will set the registers that
+// might hold result values.
+type amd64Regs struct {
+	rax  uint64
+	rdi  uint64
+	rsi  uint64
+	rdx  uint64
+	rcx  uint64
+	r8   uint64
+	r9   uint64
+	rsp  uint64
+	xmm0 [2]uint64
+	xmm1 [2]uint64
+	xmm2 [2]uint64
+	xmm3 [2]uint64
+	xmm4 [2]uint64
+	xmm5 [2]uint64
+	xmm6 [2]uint64
+	xmm7 [2]uint64
+}
+
+// Argument classifications.  The amd64 ELF ABI uses several more, but
+// these are the only ones that arise for Go types.
+type amd64Class int
+
+const (
+	amd64Integer amd64Class = iota
+	amd64SSE
+	amd64NoClass
+	amd64Memory
+)
+
+// amd64Classify returns the one or two register classes needed to
+// pass the value of type.  Go types never need more than two
+// registers.  amd64Memory means the value is stored in memory.
+// amd64NoClass means the register is not used.
+func amd64Classify(typ *rtype) (amd64Class, amd64Class) {
+	switch typ.Kind() {
+	default:
+		panic("internal error--unknown kind in amd64Classify")
+
+	case Bool, Int, Int8, Int16, Int32, Int64,
+		Uint, Uint8, Uint16, Uint32, Uint64,
+		Uintptr, Chan, Func, Map, Ptr, UnsafePointer:
+
+		return amd64Integer, amd64NoClass
+
+	case Float32, Float64, Complex64:
+		return amd64SSE, amd64NoClass
+
+	case Complex128:
+		return amd64SSE, amd64SSE
+
+	case Array:
+		if typ.size == 0 {
+			return amd64NoClass, amd64NoClass
+		} else if typ.size > 16 {
+			return amd64Memory, amd64NoClass
+		}
+		atyp := (*arrayType)(unsafe.Pointer(typ))
+		eclass1, eclass2 := amd64Classify(atyp.elem)
+		if eclass1 == amd64Memory {
+			return amd64Memory, amd64NoClass
+		}
+		if eclass2 == amd64NoClass && typ.size > 8 {
+			eclass2 = eclass1
+		}
+		return eclass1, eclass2
+
+	case Interface:
+		return amd64Integer, amd64Integer
+
+	case Slice:
+		return amd64Memory, amd64NoClass
+
+	case String:
+		return amd64Integer, amd64Integer
+
+	case Struct:
+		if typ.size == 0 {
+			return amd64NoClass, amd64NoClass
+		} else if typ.size > 16 {
+			return amd64Memory, amd64NoClass
+		}
+		var first, second amd64Class
+		f := amd64NoClass
+		onFirst := true
+		styp := (*structType)(unsafe.Pointer(typ))
+		for _, field := range styp.fields {
+			if onFirst && field.offset >= 8 {
+				first = f
+				f = amd64NoClass
+				onFirst = false
+			}
+			fclass1, fclass2 := amd64Classify(field.typ)
+			f = amd64MergeClasses(f, fclass1)
+			if fclass2 != amd64NoClass {
+				if !onFirst {
+					panic("amd64Classify inconsistent")
+				}
+				first = f
+				f = fclass2
+				onFirst = false
+			}
+		}
+		if onFirst {
+			first = f
+			second = amd64NoClass
+		} else {
+			second = f
+		}
+		if first == amd64Memory || second == amd64Memory {
+			return amd64Memory, amd64NoClass
+		}
+		return first, second
+	}
+}
+
+// amd64MergeClasses merges two register classes as described in the
+// amd64 ELF ABI.
+func amd64MergeClasses(c1, c2 amd64Class) amd64Class {
+	switch {
+	case c1 == c2:
+		return c1
+	case c1 == amd64NoClass:
+		return c2
+	case c2 == amd64NoClass:
+		return c1
+	case c1 == amd64Memory || c2 == amd64Memory:
+		return amd64Memory
+	case c1 == amd64Integer || c2 == amd64Integer:
+		return amd64Integer
+	default:
+		return amd64SSE
+	}
+}
+
+// MakeFuncStubGo implements the amd64 calling convention for
+// MakeFunc.  This should not be called.  It is exported so that
+// assembly code can call it.
+
+func MakeFuncStubGo(regs *amd64Regs, c *makeFuncImpl) {
+	ftyp := c.typ
+
+	// See if the result requires a struct.  If it does, the first
+	// parameter is a pointer to the struct.
+	var ret1, ret2 amd64Class
+	switch len(ftyp.out) {
+	case 0:
+		ret1, ret2 = amd64NoClass, amd64NoClass
+	case 1:
+		ret1, ret2 = amd64Classify(ftyp.out[0])
+	default:
+		off := uintptr(0)
+		f := amd64NoClass
+		onFirst := true
+		for _, rt := range ftyp.out {
+			off = align(off, uintptr(rt.fieldAlign))
+
+			if onFirst && off >= 8 {
+				ret1 = f
+				f = amd64NoClass
+				onFirst = false
+			}
+
+			off += rt.size
+			if off > 16 {
+				break
+			}
+
+			fclass1, fclass2 := amd64Classify(rt)
+			f = amd64MergeClasses(f, fclass1)
+			if fclass2 != amd64NoClass {
+				if !onFirst {
+					panic("amd64Classify inconsistent")
+				}
+				ret1 = f
+				f = fclass2
+				onFirst = false
+			}
+		}
+		if off > 16 {
+			ret1, ret2 = amd64Memory, amd64NoClass
+		} else {
+			if onFirst {
+				ret1, ret2 = f, amd64NoClass
+			} else {
+				ret2 = f
+			}
+		}
+		if ret1 == amd64Memory || ret2 == amd64Memory {
+			ret1, ret2 = amd64Memory, amd64NoClass
+		}
+	}
+
+	in := make([]Value, 0, len(ftyp.in))
+	intreg := 0
+	ssereg := 0
+	ap := uintptr(regs.rsp)
+
+	maxIntregs := 6 // When we support Windows, this would be 4.
+	maxSSEregs := 8
+
+	if ret1 == amd64Memory {
+		// We are returning a value in memory, which means
+		// that the first argument is a hidden parameter
+		// pointing to that return area.
+		intreg++
+	}
+
+argloop:
+	for _, rt := range ftyp.in {
+		c1, c2 := amd64Classify(rt)
+
+		fl := flag(rt.Kind()) << flagKindShift
+		if c2 == amd64NoClass {
+
+			// Argument is passed in a single register or
+			// in memory.
+
+			switch c1 {
+			case amd64NoClass:
+				v := Value{rt, nil, fl | flagIndir}
+				in = append(in, v)
+				continue argloop
+			case amd64Integer:
+				if intreg < maxIntregs {
+					reg := amd64IntregVal(regs, intreg)
+					iw := unsafe.Pointer(reg)
+					if k := rt.Kind(); k != Ptr && k != UnsafePointer {
+						iw = unsafe.Pointer(&reg)
+						fl |= flagIndir
+					}
+					v := Value{rt, iw, fl}
+					in = append(in, v)
+					intreg++
+					continue argloop
+				}
+			case amd64SSE:
+				if ssereg < maxSSEregs {
+					reg := amd64SSEregVal(regs, ssereg)
+					v := Value{rt, unsafe.Pointer(&reg), fl | flagIndir}
+					in = append(in, v)
+					ssereg++
+					continue argloop
+				}
+			}
+
+			in, ap = amd64Memarg(in, ap, rt)
+			continue argloop
+		}
+
+		// Argument is passed in two registers.
+
+		nintregs := 0
+		nsseregs := 0
+		switch c1 {
+		case amd64Integer:
+			nintregs++
+		case amd64SSE:
+			nsseregs++
+		default:
+			panic("inconsistent")
+		}
+		switch c2 {
+		case amd64Integer:
+			nintregs++
+		case amd64SSE:
+			nsseregs++
+		default:
+			panic("inconsistent")
+		}
+
+		// If the whole argument does not fit in registers, it
+		// is passed in memory.
+
+		if intreg+nintregs > maxIntregs || ssereg+nsseregs > maxSSEregs {
+			in, ap = amd64Memarg(in, ap, rt)
+			continue argloop
+		}
+
+		var word1, word2 uintptr
+		switch c1 {
+		case amd64Integer:
+			word1 = amd64IntregVal(regs, intreg)
+			intreg++
+		case amd64SSE:
+			word1 = amd64SSEregVal(regs, ssereg)
+			ssereg++
+		}
+		switch c2 {
+		case amd64Integer:
+			word2 = amd64IntregVal(regs, intreg)
+			intreg++
+		case amd64SSE:
+			word2 = amd64SSEregVal(regs, ssereg)
+			ssereg++
+		}
+
+		p := unsafe_New(rt)
+		*(*uintptr)(p) = word1
+		*(*uintptr)(unsafe.Pointer(uintptr(p) + ptrSize)) = word2
+		v := Value{rt, p, fl | flagIndir}
+		in = append(in, v)
+	}
+
+	// All the real arguments have been found and turned into
+	// Value's.  Call the real function.
+
+	out := c.call(in)
+
+	if len(out) != len(ftyp.out) {
+		panic("reflect: wrong return count from function created by MakeFunc")
+	}
+
+	for i, typ := range ftyp.out {
+		v := out[i]
+		if v.typ != typ {
+			panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
+				" returned wrong type: have " +
+				out[i].typ.String() + " for " + typ.String())
+		}
+		if v.flag&flagRO != 0 {
+			panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
+				" returned value obtained from unexported field")
+		}
+	}
+
+	if ret1 == amd64NoClass {
+		return
+	}
+
+	if ret1 == amd64Memory {
+		// The address of the memory area was passed as a
+		// hidden parameter in %rdi.
+		ptr := unsafe.Pointer(uintptr(regs.rdi))
+		off := uintptr(0)
+		for i, typ := range ftyp.out {
+			v := out[i]
+			off = align(off, uintptr(typ.fieldAlign))
+			addr := unsafe.Pointer(uintptr(ptr) + off)
+			if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+				*(*unsafe.Pointer)(addr) = v.ptr
+			} else {
+				memmove(addr, v.ptr, typ.size)
+			}
+			off += typ.size
+		}
+		return
+	}
+
+	if len(out) == 1 && ret2 == amd64NoClass {
+		v := out[0]
+		var w unsafe.Pointer
+		if v.Kind() == Ptr || v.Kind() == UnsafePointer {
+			w = v.pointer()
+		} else {
+			w = unsafe.Pointer(loadScalar(v.ptr, v.typ.size))
+		}
+		switch ret1 {
+		case amd64Integer:
+			regs.rax = uint64(uintptr(w))
+		case amd64SSE:
+			regs.xmm0[0] = uint64(uintptr(w))
+			regs.xmm0[1] = 0
+		default:
+			panic("inconsistency")
+		}
+		return
+	}
+
+	var buf [2]unsafe.Pointer
+	ptr := unsafe.Pointer(&buf[0])
+	off := uintptr(0)
+	for i, typ := range ftyp.out {
+		v := out[i]
+		off = align(off, uintptr(typ.fieldAlign))
+		addr := unsafe.Pointer(uintptr(ptr) + off)
+		if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+			*(*unsafe.Pointer)(addr) = v.ptr
+		} else {
+			memmove(addr, v.ptr, typ.size)
+		}
+		off += uintptr(typ.size)
+	}
+
+	switch ret1 {
+	case amd64Integer:
+		regs.rax = *(*uint64)(unsafe.Pointer(&buf[0]))
+	case amd64SSE:
+		regs.xmm0[0] = *(*uint64)(unsafe.Pointer(&buf[0]))
+		regs.xmm0[1] = 0
+	default:
+		panic("inconsistency")
+	}
+
+	switch ret2 {
+	case amd64Integer:
+		reg := *(*uint64)(unsafe.Pointer(&buf[1]))
+		if ret1 == amd64Integer {
+			regs.rdx = reg
+		} else {
+			regs.rax = reg
+		}
+	case amd64SSE:
+		reg := *(*uint64)(unsafe.Pointer(&buf[1]))
+		if ret1 == amd64Integer {
+			regs.xmm0[0] = reg
+			regs.xmm0[1] = 0
+		} else {
+			regs.xmm1[0] = reg
+			regs.xmm1[1] = 0
+		}
+	case amd64NoClass:
+	default:
+		panic("inconsistency")
+	}
+}
+
+// The amd64Memarg function adds an argument passed in memory.
+func amd64Memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) {
+	ap = align(ap, ptrSize)
+	ap = align(ap, uintptr(rt.align))
+
+	// We have to copy the argument onto the heap in case the
+	// function hangs onto the reflect.Value we pass it.
+	p := unsafe_New(rt)
+	memmove(p, unsafe.Pointer(ap), rt.size)
+
+	v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
+	in = append(in, v)
+	ap += rt.size
+	return in, ap
+}
+
+// The amd64IntregVal function returns the value of integer register i.
+func amd64IntregVal(regs *amd64Regs, i int) uintptr {
+	var r uint64
+	switch i {
+	case 0:
+		r = regs.rdi
+	case 1:
+		r = regs.rsi
+	case 2:
+		r = regs.rdx
+	case 3:
+		r = regs.rcx
+	case 4:
+		r = regs.r8
+	case 5:
+		r = regs.r9
+	default:
+		panic("amd64IntregVal: bad index")
+	}
+	return uintptr(r)
+}
+
+// The amd64SSEregVal function returns the value of SSE register i.
+// Note that although SSE registers can hold two uinptr's, for the
+// types we use in Go we only ever use the least significant one.  The
+// most significant one would only be used for 128 bit types.
+func amd64SSEregVal(regs *amd64Regs, i int) uintptr {
+	var r uint64
+	switch i {
+	case 0:
+		r = regs.xmm0[0]
+	case 1:
+		r = regs.xmm1[0]
+	case 2:
+		r = regs.xmm2[0]
+	case 3:
+		r = regs.xmm3[0]
+	case 4:
+		r = regs.xmm4[0]
+	case 5:
+		r = regs.xmm5[0]
+	case 6:
+		r = regs.xmm6[0]
+	case 7:
+		r = regs.xmm7[0]
+	}
+	return uintptr(r)
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390.go b/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390.go
new file mode 100644
index 0000000..ff22add
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390.go
@@ -0,0 +1,453 @@
+// Copyright 2014 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.
+
+// MakeFunc s390 implementation.
+
+package reflect
+
+import "unsafe"
+
+// Convenience types and constants.
+const s390_arch_stack_slot_align uintptr = 4
+const s390_num_gr = 5
+const s390_num_fr = 2
+
+type s390_arch_gr_t uint32
+type s390_arch_fr_t uint64
+
+// The assembler stub will pass a pointer to this structure.
+// This will come in holding all the registers that might hold
+// function parameters.  On return we will set the registers that
+// might hold result values.
+type s390_regs struct {
+	r2         s390_arch_gr_t
+	r3         s390_arch_gr_t
+	r4         s390_arch_gr_t
+	r5         s390_arch_gr_t
+	r6         s390_arch_gr_t
+	stack_args s390_arch_gr_t
+	f0         s390_arch_fr_t
+	f2         s390_arch_fr_t
+}
+
+// Argument classifications that arise for Go types.
+type s390_arg_t int
+
+const (
+	s390_general_reg s390_arg_t = iota
+	s390_general_reg_pair
+	s390_float_reg
+	// Argument passed as a pointer to an in-memory value.
+	s390_mem_ptr
+	s390_empty
+)
+
+// s390ClassifyParameter returns the register class needed to
+// pass the value of type TYP.  s390_empty means the register is
+// not used.  The second and third return values are the offset of
+// an rtype parameter passed in a register (second) or stack slot
+// (third).
+func s390ClassifyParameter(typ *rtype) (s390_arg_t, uintptr, uintptr) {
+	offset := s390_arch_stack_slot_align - typ.Size()
+	if typ.Size() > s390_arch_stack_slot_align {
+		offset = 0
+	}
+	switch typ.Kind() {
+	default:
+		panic("internal error--unknown kind in s390ClassifyParameter")
+	case Bool, Int, Int8, Int16, Int32, Uint, Uint8, Uint16, Uint32:
+		return s390_general_reg, offset, offset
+	case Int64, Uint64:
+		return s390_general_reg_pair, 0, 0
+	case Uintptr, Chan, Func, Map, Ptr, UnsafePointer:
+		return s390_general_reg, 0, 0
+	case Float32, Float64:
+		return s390_float_reg, 0, offset
+	case Complex64, Complex128:
+		// Complex numbers are passed by reference.
+		return s390_mem_ptr, 0, 0
+	case Array, Struct:
+		var ityp *rtype
+		var length int
+
+		if typ.Size() == 0 {
+			return s390_empty, 0, 0
+		}
+		switch typ.Size() {
+		default:
+			// Pointer to memory.
+			return s390_mem_ptr, 0, 0
+		case 1, 2:
+			// Pass in an integer register.
+			return s390_general_reg, offset, offset
+
+		case 4, 8:
+			// See below.
+		}
+		if typ.Kind() == Array {
+			atyp := (*arrayType)(unsafe.Pointer(typ))
+			length = atyp.Len()
+			ityp = atyp.elem
+		} else {
+			styp := (*structType)(unsafe.Pointer(typ))
+			length = len(styp.fields)
+			ityp = styp.fields[0].typ
+		}
+		if length == 1 {
+			class, off_reg, off_slot := s390ClassifyParameter(ityp)
+			if class == s390_float_reg {
+				// The array (stored in a structure) or struct
+				// is "equivalent to a floating point type" as
+				// defined in the S390 Abi.  Note that this
+				// can only be the case in the case 4 of the
+				// switch above.
+				return s390_float_reg, off_reg, off_slot
+			}
+		}
+		switch typ.Size() {
+		case 4:
+			return s390_general_reg, offset, offset
+		case 8:
+			return s390_general_reg_pair, 0, 0
+		default:
+			return s390_general_reg, 0, 0
+		}
+	case Interface, String:
+		// Structure of size 8.
+		return s390_general_reg_pair, 0, 0
+
+	case Slice:
+		return s390_mem_ptr, 0, 0
+	}
+}
+
+// s390ClassifyReturn returns the register classes needed to
+// return the value of type TYP.  s390_empty means the register is
+// not used.  The second value is the offset of an rtype return
+// parameter if stored in a register.
+func s390ClassifyReturn(typ *rtype) (s390_arg_t, uintptr) {
+	offset := s390_arch_stack_slot_align - typ.Size()
+	if typ.Size() > s390_arch_stack_slot_align {
+		offset = 0
+	}
+	switch typ.Kind() {
+	default:
+		panic("internal error--unknown kind in s390ClassifyReturn")
+	case Bool, Int, Int8, Int16, Int32,
+		Uint, Uint8, Uint16, Uint32, Uintptr:
+
+		return s390_general_reg, offset
+	case Int64, Uint64:
+		return s390_general_reg_pair, 0
+	case Chan, Func, Map, Ptr, UnsafePointer:
+		return s390_general_reg, 0
+	case Float32, Float64:
+		return s390_float_reg, 0
+	case Complex64, Complex128:
+		return s390_mem_ptr, 0
+	case Interface, Slice, String:
+		return s390_mem_ptr, 0
+	case Array, Struct:
+		if typ.size == 0 {
+			return s390_empty, 0
+		}
+		// No optimization is done for returned structures and arrays.
+		return s390_mem_ptr, 0
+	}
+}
+
+// Given a value of type *rtype left aligned in an unsafe.Pointer,
+// reload the value so that it can be stored in a general or
+// floating point register.  For general registers the value is
+// sign extend and right aligned.
+func s390ReloadForRegister(typ *rtype, w uintptr, offset uintptr) uintptr {
+	var do_sign_extend bool = false
+	var gr s390_arch_gr_t
+
+	switch typ.Kind() {
+	case Int, Int8, Int16, Int32:
+		do_sign_extend = true
+	default:
+		// Handle all other cases in the next switch.
+	}
+	switch typ.size {
+	case 1:
+		if do_sign_extend == true {
+			se := int32(*(*int8)(unsafe.Pointer(&w)))
+			gr = *(*s390_arch_gr_t)(unsafe.Pointer(&se))
+		} else {
+			e := int32(*(*uint8)(unsafe.Pointer(&w)))
+			gr = *(*s390_arch_gr_t)(unsafe.Pointer(&e))
+		}
+	case 2:
+		if do_sign_extend == true {
+			se := int32(*(*int16)(unsafe.Pointer(&w)))
+			gr = *(*s390_arch_gr_t)(unsafe.Pointer(&se))
+		} else {
+			e := int32(*(*uint16)(unsafe.Pointer(&w)))
+			gr = *(*s390_arch_gr_t)(unsafe.Pointer(&e))
+		}
+	default:
+		panic("reflect: bad size in s390ReloadForRegister")
+	}
+
+	return *(*uintptr)(unsafe.Pointer(&gr))
+}
+
+// MakeFuncStubGo implements the s390 calling convention for
+// MakeFunc.  This should not be called.  It is exported so that
+// assembly code can call it.
+func S390MakeFuncStubGo(regs *s390_regs, c *makeFuncImpl) {
+	ftyp := c.typ
+	gr := 0
+	fr := 0
+	ap := uintptr(regs.stack_args)
+
+	// See if the result requires a struct.  If it does, the first
+	// parameter is a pointer to the struct.
+	var ret_class s390_arg_t
+	var ret_off_reg uintptr
+	var ret_type *rtype
+
+	switch len(ftyp.out) {
+	case 0:
+		ret_type = nil
+		ret_class, ret_off_reg = s390_empty, 0
+	case 1:
+		ret_type = ftyp.out[0]
+		ret_class, ret_off_reg = s390ClassifyReturn(ret_type)
+	default:
+		ret_type = nil
+		ret_class, ret_off_reg = s390_mem_ptr, 0
+	}
+	in := make([]Value, 0, len(ftyp.in))
+	if ret_class == s390_mem_ptr {
+		// We are returning a value in memory, which means
+		// that the first argument is a hidden parameter
+		// pointing to that return area.
+		gr++
+	}
+
+argloop:
+	for _, rt := range ftyp.in {
+		class, off_reg, off_slot := s390ClassifyParameter(rt)
+		fl := flag(rt.Kind()) << flagKindShift
+		switch class {
+		case s390_empty:
+			v := Value{rt, nil, fl | flagIndir}
+			in = append(in, v)
+			continue argloop
+		case s390_general_reg:
+			// Values stored in a general register are right
+			// aligned.
+			if gr < s390_num_gr {
+				val := s390_general_reg_val(regs, gr)
+				iw := unsafe.Pointer(&val)
+				k := rt.Kind()
+				if k != Ptr && k != UnsafePointer {
+					ix := uintptr(unsafe.Pointer(&val))
+					ix += off_reg
+					iw = unsafe.Pointer(ix)
+					fl |= flagIndir
+				}
+				v := Value{rt, iw, fl}
+				in = append(in, v)
+				gr++
+			} else {
+				in, ap = s390_add_stackreg(
+					in, ap, rt, off_slot)
+			}
+			continue argloop
+		case s390_general_reg_pair:
+			// 64-bit integers and structs are passed in a register
+			// pair.
+			if gr+1 < s390_num_gr {
+				val := uint64(s390_general_reg_val(regs, gr))<<32 + uint64(s390_general_reg_val(regs, gr+1))
+				iw := unsafe.Pointer(&val)
+				v := Value{rt, iw, fl | flagIndir}
+				in = append(in, v)
+				gr += 2
+			} else {
+				in, ap = s390_add_stackreg(in, ap, rt, off_slot)
+				gr = s390_num_gr
+			}
+			continue argloop
+		case s390_float_reg:
+			// In a register, floats are left aligned, but in a
+			// stack slot they are right aligned.
+			if fr < s390_num_fr {
+				val := s390_float_reg_val(regs, fr)
+				ix := uintptr(unsafe.Pointer(&val))
+				v := Value{
+					rt, unsafe.Pointer(unsafe.Pointer(ix)),
+					fl | flagIndir,
+				}
+				in = append(in, v)
+				fr++
+			} else {
+				in, ap = s390_add_stackreg(
+					in, ap, rt, off_slot)
+			}
+			continue argloop
+		case s390_mem_ptr:
+			if gr < s390_num_gr {
+				// Register holding a pointer to memory.
+				val := s390_general_reg_val(regs, gr)
+				v := Value{
+					rt, unsafe.Pointer(uintptr(val)),
+					fl | flagIndir}
+				in = append(in, v)
+				gr++
+			} else {
+				// Stack slot holding a pointer to memory.
+				in, ap = s390_add_memarg(in, ap, rt)
+			}
+			continue argloop
+		}
+		panic("reflect: argtype not handled in MakeFunc:argloop")
+	}
+
+	// All the real arguments have been found and turned into
+	// Values.  Call the real function.
+
+	out := c.call(in)
+
+	if len(out) != len(ftyp.out) {
+		panic("reflect: wrong return count from function created by MakeFunc")
+	}
+
+	for i, typ := range ftyp.out {
+		v := out[i]
+		if v.typ != typ {
+			panic(
+				"reflect: function created by MakeFunc using " +
+					funcName(c.fn) + " returned wrong type: have " +
+					out[i].typ.String() + " for " + typ.String())
+		}
+		if v.flag&flagRO != 0 {
+			panic(
+				"reflect: function created by MakeFunc using " +
+					funcName(c.fn) + " returned value obtained " +
+					"from unexported field")
+		}
+	}
+
+	switch ret_class {
+	case s390_general_reg, s390_float_reg, s390_general_reg_pair:
+		// Single return value in a general or floating point register.
+		v := out[0]
+		var w uintptr
+		if v.Kind() == Ptr || v.Kind() == UnsafePointer {
+			w = uintptr(v.pointer())
+		} else {
+			w = uintptr(loadScalar(v.ptr, v.typ.size))
+			if ret_off_reg != 0 {
+				w = s390ReloadForRegister(
+					ret_type, w, ret_off_reg)
+			}
+		}
+		if ret_class == s390_float_reg {
+			regs.f0 = s390_arch_fr_t(uintptr(w))
+		} else if ret_class == s390_general_reg {
+			regs.r2 = s390_arch_gr_t(uintptr(w))
+		} else {
+			regs.r2 = s390_arch_gr_t(uintptr(w) >> 32)
+			regs.r3 = s390_arch_gr_t(uintptr(w) & 0xffffffff)
+		}
+
+	case s390_mem_ptr:
+		// The address of the memory area was passed as a hidden
+		// parameter in %r2.  Multiple return values are always returned
+		// in an in-memory structure.
+		ptr := unsafe.Pointer(uintptr(regs.r2))
+		off := uintptr(0)
+		for i, typ := range ftyp.out {
+			v := out[i]
+			off = align(off, uintptr(typ.fieldAlign))
+			addr := unsafe.Pointer(uintptr(ptr) + off)
+			if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+				*(*unsafe.Pointer)(addr) = v.ptr
+			} else {
+				memmove(addr, v.ptr, typ.size)
+			}
+			off += typ.size
+		}
+
+	case s390_empty:
+	}
+
+	return
+}
+
+// The s390_add_stackreg function adds an argument passed on the
+// stack that could be passed in a register.
+func s390_add_stackreg(in []Value, ap uintptr, rt *rtype, offset uintptr) ([]Value, uintptr) {
+	// If we're not already at the beginning of a stack slot, round up to
+	// the beginning of the next one.
+	ap = align(ap, s390_arch_stack_slot_align)
+	// If offset is > 0, the data is right aligned on the stack slot.
+	ap += offset
+
+	// We have to copy the argument onto the heap in case the
+	// function hangs onto the reflect.Value we pass it.
+	p := unsafe_New(rt)
+	memmove(p, unsafe.Pointer(ap), rt.size)
+
+	v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
+	in = append(in, v)
+	ap += rt.size
+	ap = align(ap, s390_arch_stack_slot_align)
+
+	return in, ap
+}
+
+// The s390_add_memarg function adds an argument passed in memory.
+func s390_add_memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) {
+	// If we're not already at the beginning of a stack slot,
+	// round up to the beginning of the next one.
+	ap = align(ap, s390_arch_stack_slot_align)
+
+	// We have to copy the argument onto the heap in case the
+	// function hangs onto the reflect.Value we pass it.
+	p := unsafe_New(rt)
+	memmove(p, *(*unsafe.Pointer)(unsafe.Pointer(ap)), rt.size)
+
+	v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
+	in = append(in, v)
+	ap += s390_arch_stack_slot_align
+
+	return in, ap
+}
+
+// The s390_general_reg_val function returns the value of integer register GR.
+func s390_general_reg_val(regs *s390_regs, gr int) s390_arch_gr_t {
+	switch gr {
+	case 0:
+		return regs.r2
+	case 1:
+		return regs.r3
+	case 2:
+		return regs.r4
+	case 3:
+		return regs.r5
+	case 4:
+		return regs.r6
+	default:
+		panic("s390_general_reg_val: bad integer register")
+	}
+}
+
+// The s390_float_reg_val function returns the value of float register FR.
+func s390_float_reg_val(regs *s390_regs, fr int) uintptr {
+	var r s390_arch_fr_t
+	switch fr {
+	case 0:
+		r = regs.f0
+	case 1:
+		r = regs.f2
+	default:
+		panic("s390_float_reg_val: bad floating point register")
+	}
+	return uintptr(r)
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390x.go b/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390x.go
new file mode 100644
index 0000000..a0a5567
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390x.go
@@ -0,0 +1,435 @@
+// Copyright 2014 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.
+
+// MakeFunc s390x implementation.
+
+package reflect
+
+import "unsafe"
+
+// Convenience types and constants.
+const s390x_arch_stack_slot_align uintptr = 8
+const s390x_num_gr = 5
+const s390x_num_fr = 4
+
+type s390x_arch_gr_t uint64
+type s390x_arch_fr_t uint64
+
+// The assembler stub will pass a pointer to this structure.
+// This will come in holding all the registers that might hold
+// function parameters.  On return we will set the registers that
+// might hold result values.
+type s390x_regs struct {
+	r2         s390x_arch_gr_t
+	r3         s390x_arch_gr_t
+	r4         s390x_arch_gr_t
+	r5         s390x_arch_gr_t
+	r6         s390x_arch_gr_t
+	stack_args s390x_arch_gr_t
+	f0         s390x_arch_fr_t
+	f2         s390x_arch_fr_t
+	f4         s390x_arch_fr_t
+	f6         s390x_arch_fr_t
+}
+
+// Argument classifications that arise for Go types.
+type s390x_arg_t int
+
+const (
+	s390x_general_reg s390x_arg_t = iota
+	s390x_float_reg
+	// Argument passed as a pointer to an in-memory value.
+	s390x_mem_ptr
+	s390x_empty
+)
+
+// s390xClassifyParameter returns the register class needed to
+// pass the value of type TYP.  s390x_empty means the register is
+// not used.  The second and third return values are the offset of
+// an rtype parameter passed in a register (second) or stack slot
+// (third).
+func s390xClassifyParameter(typ *rtype) (s390x_arg_t, uintptr, uintptr) {
+	offset := s390x_arch_stack_slot_align - typ.Size()
+	switch typ.Kind() {
+	default:
+		panic("internal error--unknown kind in s390xClassifyParameter")
+	case Bool, Int, Int8, Int16, Int32, Uint, Uint8, Uint16, Uint32:
+		return s390x_general_reg, offset, offset
+	case Int64, Uint64, Uintptr, Chan, Func, Map, Ptr, UnsafePointer:
+		return s390x_general_reg, 0, 0
+	case Float32, Float64:
+		return s390x_float_reg, 0, offset
+	case Complex64, Complex128:
+		// Complex numbers are passed by reference.
+		return s390x_mem_ptr, 0, 0
+	case Array, Struct:
+		var ityp *rtype
+		var length int
+
+		if typ.Size() == 0 {
+			return s390x_empty, 0, 0
+		}
+		switch typ.Size() {
+		default:
+			// Pointer to memory.
+			return s390x_mem_ptr, 0, 0
+		case 1, 2:
+			// Pass in an integer register.
+			return s390x_general_reg, offset, offset
+
+		case 4, 8:
+			// See below.
+		}
+		if typ.Kind() == Array {
+			atyp := (*arrayType)(unsafe.Pointer(typ))
+			length = atyp.Len()
+			ityp = atyp.elem
+		} else {
+			styp := (*structType)(unsafe.Pointer(typ))
+			length = len(styp.fields)
+			ityp = styp.fields[0].typ
+		}
+		if length == 1 {
+			class, off_reg, off_slot := s390xClassifyParameter(ityp)
+			if class == s390x_float_reg {
+				// The array (stored in a structure) or struct
+				// is "equivalent to a floating point type" as
+				// defined in the S390x Abi.  Note that this
+				// can only be the case in the cases 4 and 8 of
+				// the switch above.
+				return s390x_float_reg, off_reg, off_slot
+			}
+		}
+		// Otherwise pass in an integer register.
+		switch typ.Size() {
+		case 4, 8:
+			return s390x_general_reg, offset, offset
+		default:
+			return s390x_general_reg, 0, 0
+		}
+	case Interface, Slice, String:
+		return s390x_mem_ptr, 0, 0
+	}
+}
+
+// s390xClassifyReturn returns the register classes needed to
+// return the value of type TYP.  s390_empty means the register is
+// not used.  The second value is the offset of an rtype return
+// parameter if stored in a register.
+func s390xClassifyReturn(typ *rtype) (s390x_arg_t, uintptr) {
+	offset := s390x_arch_stack_slot_align - typ.Size()
+	switch typ.Kind() {
+	default:
+		panic("internal error--unknown kind in s390xClassifyReturn")
+	case Bool, Int, Int8, Int16, Int32, Int64,
+		Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+
+		return s390x_general_reg, offset
+	case Chan, Func, Map, Ptr, UnsafePointer:
+		return s390x_general_reg, 0
+	case Float32, Float64:
+		return s390x_float_reg, 0
+	case Complex64, Complex128:
+		return s390x_mem_ptr, 0
+	case Interface, Slice, String:
+		return s390x_mem_ptr, 0
+	case Array, Struct:
+		if typ.size == 0 {
+			return s390x_empty, 0
+		}
+		// No optimization is done for returned structures and arrays.
+		return s390x_mem_ptr, 0
+	}
+}
+
+// Given a value of type *rtype left aligned in an unsafe.Pointer,
+// reload the value so that it can be stored in a general or
+// floating point register.  For general registers the value is
+// sign extend and right aligned.
+func s390xReloadForRegister(typ *rtype, w uintptr, offset uintptr) uintptr {
+	var do_sign_extend bool = false
+	var gr s390x_arch_gr_t
+
+	switch typ.Kind() {
+	case Int, Int8, Int16, Int32, Int64:
+		do_sign_extend = true
+	default:
+		// Handle all other cases in the next switch.
+	}
+	switch typ.size {
+	case 1:
+		if do_sign_extend == true {
+			se := int64(*(*int8)(unsafe.Pointer(&w)))
+			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se))
+		} else {
+			e := int64(*(*uint8)(unsafe.Pointer(&w)))
+			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e))
+		}
+	case 2:
+		if do_sign_extend == true {
+			se := int64(*(*int16)(unsafe.Pointer(&w)))
+			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se))
+		} else {
+			e := int64(*(*uint16)(unsafe.Pointer(&w)))
+			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e))
+		}
+	case 4:
+		if do_sign_extend == true {
+			se := int64(*(*int32)(unsafe.Pointer(&w)))
+			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se))
+		} else {
+			e := int64(*(*uint32)(unsafe.Pointer(&w)))
+			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e))
+		}
+	default:
+		panic("reflect: bad size in s390xReloadForRegister")
+	}
+
+	return *(*uintptr)(unsafe.Pointer(&gr))
+}
+
+// MakeFuncStubGo implements the s390x calling convention for
+// MakeFunc.  This should not be called.  It is exported so that
+// assembly code can call it.
+func S390xMakeFuncStubGo(regs *s390x_regs, c *makeFuncImpl) {
+	ftyp := c.typ
+	gr := 0
+	fr := 0
+	ap := uintptr(regs.stack_args)
+
+	// See if the result requires a struct.  If it does, the first
+	// parameter is a pointer to the struct.
+	var ret_class s390x_arg_t
+	var ret_off_reg uintptr
+	var ret_type *rtype
+
+	switch len(ftyp.out) {
+	case 0:
+		ret_type = nil
+		ret_class, ret_off_reg = s390x_empty, 0
+	case 1:
+		ret_type = ftyp.out[0]
+		ret_class, ret_off_reg = s390xClassifyReturn(ret_type)
+	default:
+		ret_type = nil
+		ret_class, ret_off_reg = s390x_mem_ptr, 0
+	}
+	in := make([]Value, 0, len(ftyp.in))
+	if ret_class == s390x_mem_ptr {
+		// We are returning a value in memory, which means
+		// that the first argument is a hidden parameter
+		// pointing to that return area.
+		gr++
+	}
+
+argloop:
+	for _, rt := range ftyp.in {
+		class, off_reg, off_slot := s390xClassifyParameter(rt)
+		fl := flag(rt.Kind()) << flagKindShift
+		switch class {
+		case s390x_empty:
+			v := Value{rt, nil, fl | flagIndir}
+			in = append(in, v)
+			continue argloop
+		case s390x_general_reg:
+			// Values stored in a general register are right
+			// aligned.
+			if gr < s390x_num_gr {
+				val := s390x_general_reg_val(regs, gr)
+				iw := unsafe.Pointer(val)
+				k := rt.Kind()
+				if k != Ptr && k != UnsafePointer {
+					ix := uintptr(unsafe.Pointer(&val))
+					ix += off_reg
+					iw = unsafe.Pointer(ix)
+					fl |= flagIndir
+				}
+				v := Value{rt, iw, fl}
+				in = append(in, v)
+				gr++
+			} else {
+				in, ap = s390x_add_stackreg(
+					in, ap, rt, off_slot)
+			}
+			continue argloop
+		case s390x_float_reg:
+			// In a register, floats are left aligned, but in a
+			// stack slot they are right aligned.
+			if fr < s390x_num_fr {
+				val := s390x_float_reg_val(regs, fr)
+				ix := uintptr(unsafe.Pointer(&val))
+				v := Value{
+					rt, unsafe.Pointer(unsafe.Pointer(ix)),
+					fl | flagIndir,
+				}
+				in = append(in, v)
+				fr++
+			} else {
+				in, ap = s390x_add_stackreg(
+					in, ap, rt, off_slot)
+			}
+			continue argloop
+		case s390x_mem_ptr:
+			if gr < s390x_num_gr {
+				// Register holding a pointer to memory.
+				val := s390x_general_reg_val(regs, gr)
+				v := Value{
+					rt, unsafe.Pointer(val), fl | flagIndir}
+				in = append(in, v)
+				gr++
+			} else {
+				// Stack slot holding a pointer to memory.
+				in, ap = s390x_add_memarg(in, ap, rt)
+			}
+			continue argloop
+		}
+		panic("reflect: argtype not handled in MakeFunc:argloop")
+	}
+
+	// All the real arguments have been found and turned into
+	// Values.  Call the real function.
+
+	out := c.call(in)
+
+	if len(out) != len(ftyp.out) {
+		panic("reflect: wrong return count from function created by MakeFunc")
+	}
+
+	for i, typ := range ftyp.out {
+		v := out[i]
+		if v.typ != typ {
+			panic(
+				"reflect: function created by MakeFunc using " +
+					funcName(c.fn) + " returned wrong type: have " +
+					out[i].typ.String() + " for " + typ.String())
+		}
+		if v.flag&flagRO != 0 {
+			panic(
+				"reflect: function created by MakeFunc using " +
+					funcName(c.fn) + " returned value obtained " +
+					"from unexported field")
+		}
+	}
+
+	switch ret_class {
+	case s390x_general_reg, s390x_float_reg:
+		// Single return value in a general or floating point register.
+		v := out[0]
+		var w uintptr
+		if v.Kind() == Ptr || v.Kind() == UnsafePointer {
+			w = uintptr(v.pointer())
+		} else {
+			w = uintptr(loadScalar(v.ptr, v.typ.size))
+			if ret_off_reg != 0 {
+				w = s390xReloadForRegister(
+					ret_type, w, ret_off_reg)
+			}
+		}
+		if ret_class == s390x_float_reg {
+			regs.f0 = s390x_arch_fr_t(w)
+		} else {
+			regs.r2 = s390x_arch_gr_t(w)
+		}
+
+	case s390x_mem_ptr:
+		// The address of the memory area was passed as a hidden
+		// parameter in %r2.  Multiple return values are always returned
+		// in an in-memory structure.
+		ptr := unsafe.Pointer(uintptr(regs.r2))
+		off := uintptr(0)
+		for i, typ := range ftyp.out {
+			v := out[i]
+			off = align(off, uintptr(typ.fieldAlign))
+			addr := unsafe.Pointer(uintptr(ptr) + off)
+			if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+				*(*unsafe.Pointer)(addr) = v.ptr
+			} else {
+				memmove(addr, v.ptr, typ.size)
+			}
+			off += typ.size
+		}
+
+	case s390x_empty:
+	}
+
+	return
+}
+
+// The s390x_add_stackreg function adds an argument passed on the
+// stack that could be passed in a register.
+func s390x_add_stackreg(in []Value, ap uintptr, rt *rtype, offset uintptr) ([]Value, uintptr) {
+	// If we're not already at the beginning of a stack slot, round up to
+	// the beginning of the next one.
+	ap = align(ap, s390x_arch_stack_slot_align)
+	// If offset is > 0, the data is right aligned on the stack slot.
+	ap += offset
+
+	// We have to copy the argument onto the heap in case the
+	// function hangs onto the reflect.Value we pass it.
+	p := unsafe_New(rt)
+	memmove(p, unsafe.Pointer(ap), rt.size)
+
+	v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
+	in = append(in, v)
+	ap += rt.size
+	ap = align(ap, s390x_arch_stack_slot_align)
+
+	return in, ap
+}
+
+// The s390x_add_memarg function adds an argument passed in memory.
+func s390x_add_memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) {
+	// If we're not already at the beginning of a stack slot,
+	// round up to the beginning of the next one.
+	ap = align(ap, s390x_arch_stack_slot_align)
+
+	// We have to copy the argument onto the heap in case the
+	// function hangs onto the reflect.Value we pass it.
+	p := unsafe_New(rt)
+	memmove(p, *(*unsafe.Pointer)(unsafe.Pointer(ap)), rt.size)
+
+	v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
+	in = append(in, v)
+	ap += s390x_arch_stack_slot_align
+
+	return in, ap
+}
+
+// The s390x_general_reg_val function returns the value of integer register GR.
+func s390x_general_reg_val(regs *s390x_regs, gr int) uintptr {
+	var r s390x_arch_gr_t
+	switch gr {
+	case 0:
+		r = regs.r2
+	case 1:
+		r = regs.r3
+	case 2:
+		r = regs.r4
+	case 3:
+		r = regs.r5
+	case 4:
+		r = regs.r6
+	default:
+		panic("s390x_general_reg_val: bad integer register")
+	}
+	return uintptr(r)
+}
+
+// The s390x_float_reg_val function returns the value of float register FR.
+func s390x_float_reg_val(regs *s390x_regs, fr int) uintptr {
+	var r s390x_arch_fr_t
+	switch fr {
+	case 0:
+		r = regs.f0
+	case 1:
+		r = regs.f2
+	case 2:
+		r = regs.f4
+	case 3:
+		r = regs.f6
+	default:
+		panic("s390x_float_reg_val: bad floating point register")
+	}
+	return uintptr(r)
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/set_test.go b/third_party/gofrontend/libgo/go/reflect/set_test.go
new file mode 100644
index 0000000..85dc55e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/set_test.go
@@ -0,0 +1,211 @@
+// 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.
+
+package reflect_test
+
+import (
+	"bytes"
+	"go/ast"
+	"io"
+	. "reflect"
+	"testing"
+	"unsafe"
+)
+
+type MyBuffer bytes.Buffer
+
+func TestImplicitMapConversion(t *testing.T) {
+	// Test implicit conversions in MapIndex and SetMapIndex.
+	{
+		// direct
+		m := make(map[int]int)
+		mv := ValueOf(m)
+		mv.SetMapIndex(ValueOf(1), ValueOf(2))
+		x, ok := m[1]
+		if x != 2 {
+			t.Errorf("#1 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
+		}
+		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
+			t.Errorf("#1 MapIndex(1) = %d", n)
+		}
+	}
+	{
+		// convert interface key
+		m := make(map[interface{}]int)
+		mv := ValueOf(m)
+		mv.SetMapIndex(ValueOf(1), ValueOf(2))
+		x, ok := m[1]
+		if x != 2 {
+			t.Errorf("#2 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
+		}
+		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
+			t.Errorf("#2 MapIndex(1) = %d", n)
+		}
+	}
+	{
+		// convert interface value
+		m := make(map[int]interface{})
+		mv := ValueOf(m)
+		mv.SetMapIndex(ValueOf(1), ValueOf(2))
+		x, ok := m[1]
+		if x != 2 {
+			t.Errorf("#3 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
+		}
+		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
+			t.Errorf("#3 MapIndex(1) = %d", n)
+		}
+	}
+	{
+		// convert both interface key and interface value
+		m := make(map[interface{}]interface{})
+		mv := ValueOf(m)
+		mv.SetMapIndex(ValueOf(1), ValueOf(2))
+		x, ok := m[1]
+		if x != 2 {
+			t.Errorf("#4 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
+		}
+		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
+			t.Errorf("#4 MapIndex(1) = %d", n)
+		}
+	}
+	{
+		// convert both, with non-empty interfaces
+		m := make(map[io.Reader]io.Writer)
+		mv := ValueOf(m)
+		b1 := new(bytes.Buffer)
+		b2 := new(bytes.Buffer)
+		mv.SetMapIndex(ValueOf(b1), ValueOf(b2))
+		x, ok := m[b1]
+		if x != b2 {
+			t.Errorf("#5 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
+		}
+		if p := mv.MapIndex(ValueOf(b1)).Elem().Pointer(); p != uintptr(unsafe.Pointer(b2)) {
+			t.Errorf("#5 MapIndex(b1) = %#x want %p", p, b2)
+		}
+	}
+	{
+		// convert channel direction
+		m := make(map[<-chan int]chan int)
+		mv := ValueOf(m)
+		c1 := make(chan int)
+		c2 := make(chan int)
+		mv.SetMapIndex(ValueOf(c1), ValueOf(c2))
+		x, ok := m[c1]
+		if x != c2 {
+			t.Errorf("#6 after SetMapIndex(c1, c2): %p (!= %p), %t (map=%v)", x, c2, ok, m)
+		}
+		if p := mv.MapIndex(ValueOf(c1)).Pointer(); p != ValueOf(c2).Pointer() {
+			t.Errorf("#6 MapIndex(c1) = %#x want %p", p, c2)
+		}
+	}
+	{
+		// convert identical underlying types
+		// TODO(rsc): Should be able to define MyBuffer here.
+		// 6l prints very strange messages about .this.Bytes etc
+		// when we do that though, so MyBuffer is defined
+		// at top level.
+		m := make(map[*MyBuffer]*bytes.Buffer)
+		mv := ValueOf(m)
+		b1 := new(MyBuffer)
+		b2 := new(bytes.Buffer)
+		mv.SetMapIndex(ValueOf(b1), ValueOf(b2))
+		x, ok := m[b1]
+		if x != b2 {
+			t.Errorf("#7 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
+		}
+		if p := mv.MapIndex(ValueOf(b1)).Pointer(); p != uintptr(unsafe.Pointer(b2)) {
+			t.Errorf("#7 MapIndex(b1) = %#x want %p", p, b2)
+		}
+	}
+
+}
+
+func TestImplicitSetConversion(t *testing.T) {
+	// Assume TestImplicitMapConversion covered the basics.
+	// Just make sure conversions are being applied at all.
+	var r io.Reader
+	b := new(bytes.Buffer)
+	rv := ValueOf(&r).Elem()
+	rv.Set(ValueOf(b))
+	if r != b {
+		t.Errorf("after Set: r=%T(%v)", r, r)
+	}
+}
+
+func TestImplicitSendConversion(t *testing.T) {
+	c := make(chan io.Reader, 10)
+	b := new(bytes.Buffer)
+	ValueOf(c).Send(ValueOf(b))
+	if bb := <-c; bb != b {
+		t.Errorf("Received %p != %p", bb, b)
+	}
+}
+
+func TestImplicitCallConversion(t *testing.T) {
+	// Arguments must be assignable to parameter types.
+	fv := ValueOf(io.WriteString)
+	b := new(bytes.Buffer)
+	fv.Call([]Value{ValueOf(b), ValueOf("hello world")})
+	if b.String() != "hello world" {
+		t.Errorf("After call: string=%q want %q", b.String(), "hello world")
+	}
+}
+
+func TestImplicitAppendConversion(t *testing.T) {
+	// Arguments must be assignable to the slice's element type.
+	s := []io.Reader{}
+	sv := ValueOf(&s).Elem()
+	b := new(bytes.Buffer)
+	sv.Set(Append(sv, ValueOf(b)))
+	if len(s) != 1 || s[0] != b {
+		t.Errorf("after append: s=%v want [%p]", s, b)
+	}
+}
+
+var implementsTests = []struct {
+	x interface{}
+	t interface{}
+	b bool
+}{
+	{new(*bytes.Buffer), new(io.Reader), true},
+	{new(bytes.Buffer), new(io.Reader), false},
+	{new(*bytes.Buffer), new(io.ReaderAt), false},
+	{new(*ast.Ident), new(ast.Expr), true},
+}
+
+func TestImplements(t *testing.T) {
+	for _, tt := range implementsTests {
+		xv := TypeOf(tt.x).Elem()
+		xt := TypeOf(tt.t).Elem()
+		if b := xv.Implements(xt); b != tt.b {
+			t.Errorf("(%s).Implements(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b)
+		}
+	}
+}
+
+var assignableTests = []struct {
+	x interface{}
+	t interface{}
+	b bool
+}{
+	{new(chan int), new(<-chan int), true},
+	{new(<-chan int), new(chan int), false},
+	{new(*int), new(IntPtr), true},
+	{new(IntPtr), new(*int), true},
+	{new(IntPtr), new(IntPtr1), false},
+	// test runs implementsTests too
+}
+
+type IntPtr *int
+type IntPtr1 *int
+
+func TestAssignableTo(t *testing.T) {
+	for _, tt := range append(assignableTests, implementsTests...) {
+		xv := TypeOf(tt.x).Elem()
+		xt := TypeOf(tt.t).Elem()
+		if b := xv.AssignableTo(xt); b != tt.b {
+			t.Errorf("(%s).AssignableTo(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/tostring_test.go b/third_party/gofrontend/libgo/go/reflect/tostring_test.go
new file mode 100644
index 0000000..e416fd8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/tostring_test.go
@@ -0,0 +1,95 @@
+// 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.
+
+// Formatting of reflection types and values for debugging.
+// Not defined as methods so they do not need to be linked into most binaries;
+// the functions are not used by the library itself, only in tests.
+
+package reflect_test
+
+import (
+	. "reflect"
+	"strconv"
+)
+
+// valueToString returns a textual representation of the reflection value val.
+// For debugging only.
+func valueToString(val Value) string {
+	var str string
+	if !val.IsValid() {
+		return "<zero Value>"
+	}
+	typ := val.Type()
+	switch val.Kind() {
+	case Int, Int8, Int16, Int32, Int64:
+		return strconv.FormatInt(val.Int(), 10)
+	case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+		return strconv.FormatUint(val.Uint(), 10)
+	case Float32, Float64:
+		return strconv.FormatFloat(val.Float(), 'g', -1, 64)
+	case Complex64, Complex128:
+		c := val.Complex()
+		return strconv.FormatFloat(real(c), 'g', -1, 64) + "+" + strconv.FormatFloat(imag(c), 'g', -1, 64) + "i"
+	case String:
+		return val.String()
+	case Bool:
+		if val.Bool() {
+			return "true"
+		} else {
+			return "false"
+		}
+	case Ptr:
+		v := val
+		str = typ.String() + "("
+		if v.IsNil() {
+			str += "0"
+		} else {
+			str += "&" + valueToString(v.Elem())
+		}
+		str += ")"
+		return str
+	case Array, Slice:
+		v := val
+		str += typ.String()
+		str += "{"
+		for i := 0; i < v.Len(); i++ {
+			if i > 0 {
+				str += ", "
+			}
+			str += valueToString(v.Index(i))
+		}
+		str += "}"
+		return str
+	case Map:
+		t := typ
+		str = t.String()
+		str += "{"
+		str += "<can't iterate on maps>"
+		str += "}"
+		return str
+	case Chan:
+		str = typ.String()
+		return str
+	case Struct:
+		t := typ
+		v := val
+		str += t.String()
+		str += "{"
+		for i, n := 0, v.NumField(); i < n; i++ {
+			if i > 0 {
+				str += ", "
+			}
+			str += valueToString(v.Field(i))
+		}
+		str += "}"
+		return str
+	case Interface:
+		return typ.String() + "(" + valueToString(val.Elem()) + ")"
+	case Func:
+		v := val
+		return typ.String() + "(" + strconv.FormatUint(uint64(v.Pointer()), 10) + ")"
+	default:
+		panic("valueToString: can't print type " + typ.String())
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/type.go b/third_party/gofrontend/libgo/go/reflect/type.go
new file mode 100644
index 0000000..91697c4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/type.go
@@ -0,0 +1,1847 @@
+// 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 reflect implements run-time reflection, allowing a program to
+// manipulate objects with arbitrary types.  The typical use is to take a value
+// with static type interface{} and extract its dynamic type information by
+// calling TypeOf, which returns a Type.
+//
+// A call to ValueOf returns a Value representing the run-time data.
+// Zero takes a Type and returns a Value representing a zero value
+// for that type.
+//
+// See "The Laws of Reflection" for an introduction to reflection in Go:
+// http://golang.org/doc/articles/laws_of_reflection.html
+package reflect
+
+import (
+	"runtime"
+	"strconv"
+	"sync"
+	"unsafe"
+)
+
+// Type is the representation of a Go type.
+//
+// Not all methods apply to all kinds of types.  Restrictions,
+// if any, are noted in the documentation for each method.
+// Use the Kind method to find out the kind of type before
+// calling kind-specific methods.  Calling a method
+// inappropriate to the kind of type causes a run-time panic.
+type Type interface {
+	// Methods applicable to all types.
+
+	// Align returns the alignment in bytes of a value of
+	// this type when allocated in memory.
+	Align() int
+
+	// FieldAlign returns the alignment in bytes of a value of
+	// this type when used as a field in a struct.
+	FieldAlign() int
+
+	// Method returns the i'th method in the type's method set.
+	// It panics if i is not in the range [0, NumMethod()).
+	//
+	// For a non-interface type T or *T, the returned Method's Type and Func
+	// fields describe a function whose first argument is the receiver.
+	//
+	// For an interface type, the returned Method's Type field gives the
+	// method signature, without a receiver, and the Func field is nil.
+	Method(int) Method
+
+	// MethodByName returns the method with that name in the type's
+	// method set and a boolean indicating if the method was found.
+	//
+	// For a non-interface type T or *T, the returned Method's Type and Func
+	// fields describe a function whose first argument is the receiver.
+	//
+	// For an interface type, the returned Method's Type field gives the
+	// method signature, without a receiver, and the Func field is nil.
+	MethodByName(string) (Method, bool)
+
+	// NumMethod returns the number of methods in the type's method set.
+	NumMethod() int
+
+	// Name returns the type's name within its package.
+	// It returns an empty string for unnamed types.
+	Name() string
+
+	// PkgPath returns a named type's package path, that is, the import path
+	// that uniquely identifies the package, such as "encoding/base64".
+	// If the type was predeclared (string, error) or unnamed (*T, struct{}, []int),
+	// the package path will be the empty string.
+	PkgPath() string
+
+	// Size returns the number of bytes needed to store
+	// a value of the given type; it is analogous to unsafe.Sizeof.
+	Size() uintptr
+
+	// String returns a string representation of the type.
+	// The string representation may use shortened package names
+	// (e.g., base64 instead of "encoding/base64") and is not
+	// guaranteed to be unique among types.  To test for equality,
+	// compare the Types directly.
+	String() string
+
+	// Used internally by gccgo--the string retaining quoting.
+	rawString() string
+
+	// Kind returns the specific kind of this type.
+	Kind() Kind
+
+	// Implements returns true if the type implements the interface type u.
+	Implements(u Type) bool
+
+	// AssignableTo returns true if a value of the type is assignable to type u.
+	AssignableTo(u Type) bool
+
+	// ConvertibleTo returns true if a value of the type is convertible to type u.
+	ConvertibleTo(u Type) bool
+
+	// Methods applicable only to some types, depending on Kind.
+	// The methods allowed for each kind are:
+	//
+	//	Int*, Uint*, Float*, Complex*: Bits
+	//	Array: Elem, Len
+	//	Chan: ChanDir, Elem
+	//	Func: In, NumIn, Out, NumOut, IsVariadic.
+	//	Map: Key, Elem
+	//	Ptr: Elem
+	//	Slice: Elem
+	//	Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField
+
+	// Bits returns the size of the type in bits.
+	// It panics if the type's Kind is not one of the
+	// sized or unsized Int, Uint, Float, or Complex kinds.
+	Bits() int
+
+	// ChanDir returns a channel type's direction.
+	// It panics if the type's Kind is not Chan.
+	ChanDir() ChanDir
+
+	// IsVariadic returns true if a function type's final input parameter
+	// is a "..." parameter.  If so, t.In(t.NumIn() - 1) returns the parameter's
+	// implicit actual type []T.
+	//
+	// For concreteness, if t represents func(x int, y ... float64), then
+	//
+	//	t.NumIn() == 2
+	//	t.In(0) is the reflect.Type for "int"
+	//	t.In(1) is the reflect.Type for "[]float64"
+	//	t.IsVariadic() == true
+	//
+	// IsVariadic panics if the type's Kind is not Func.
+	IsVariadic() bool
+
+	// Elem returns a type's element type.
+	// It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
+	Elem() Type
+
+	// Field returns a struct type's i'th field.
+	// It panics if the type's Kind is not Struct.
+	// It panics if i is not in the range [0, NumField()).
+	Field(i int) StructField
+
+	// FieldByIndex returns the nested field corresponding
+	// to the index sequence.  It is equivalent to calling Field
+	// successively for each index i.
+	// It panics if the type's Kind is not Struct.
+	FieldByIndex(index []int) StructField
+
+	// FieldByName returns the struct field with the given name
+	// and a boolean indicating if the field was found.
+	FieldByName(name string) (StructField, bool)
+
+	// FieldByNameFunc returns the first struct field with a name
+	// that satisfies the match function and a boolean indicating if
+	// the field was found.
+	FieldByNameFunc(match func(string) bool) (StructField, bool)
+
+	// In returns the type of a function type's i'th input parameter.
+	// It panics if the type's Kind is not Func.
+	// It panics if i is not in the range [0, NumIn()).
+	In(i int) Type
+
+	// Key returns a map type's key type.
+	// It panics if the type's Kind is not Map.
+	Key() Type
+
+	// Len returns an array type's length.
+	// It panics if the type's Kind is not Array.
+	Len() int
+
+	// NumField returns a struct type's field count.
+	// It panics if the type's Kind is not Struct.
+	NumField() int
+
+	// NumIn returns a function type's input parameter count.
+	// It panics if the type's Kind is not Func.
+	NumIn() int
+
+	// NumOut returns a function type's output parameter count.
+	// It panics if the type's Kind is not Func.
+	NumOut() int
+
+	// Out returns the type of a function type's i'th output parameter.
+	// It panics if the type's Kind is not Func.
+	// It panics if i is not in the range [0, NumOut()).
+	Out(i int) Type
+
+	common() *rtype
+	uncommon() *uncommonType
+}
+
+// BUG(rsc): FieldByName and related functions consider struct field names to be equal
+// if the names are equal, even if they are unexported names originating
+// in different packages. The practical effect of this is that the result of
+// t.FieldByName("x") is not well defined if the struct type t contains
+// multiple fields named x (embedded from different packages).
+// FieldByName may return one of the fields named x or may report that there are none.
+// See golang.org/issue/4876 for more details.
+
+/*
+ * These data structures are known to the compiler (../../cmd/gc/reflect.c).
+ * A few are known to ../runtime/type.go to convey to debuggers.
+ * They are also known to ../runtime/type.h.
+ */
+
+// A Kind represents the specific kind of type that a Type represents.
+// The zero Kind is not a valid kind.
+type Kind uint
+
+const (
+	Invalid Kind = iota
+	Bool
+	Int
+	Int8
+	Int16
+	Int32
+	Int64
+	Uint
+	Uint8
+	Uint16
+	Uint32
+	Uint64
+	Uintptr
+	Float32
+	Float64
+	Complex64
+	Complex128
+	Array
+	Chan
+	Func
+	Interface
+	Map
+	Ptr
+	Slice
+	String
+	Struct
+	UnsafePointer
+)
+
+// rtype is the common implementation of most values.
+// It is embedded in other, public struct types, but always
+// with a unique tag like `reflect:"array"` or `reflect:"ptr"`
+// so that code cannot convert from, say, *arrayType to *ptrType.
+type rtype struct {
+	kind       uint8   // enumeration for C
+	align      int8    // alignment of variable with this type
+	fieldAlign uint8   // alignment of struct field with this type
+	_          uint8   // unused/padding
+	size       uintptr // size in bytes
+	hash       uint32  // hash of type; avoids computation in hash tables
+
+	hashfn  uintptr // hash function code
+	equalfn uintptr // equality function code
+
+	gc            unsafe.Pointer // garbage collection data
+	string        *string        // string form; unnecessary  but undeniably useful
+	*uncommonType                // (relatively) uncommon fields
+	ptrToThis     *rtype         // type for pointer to this type, if used in binary or has methods
+	zero          unsafe.Pointer // pointer to zero value
+}
+
+// Method on non-interface type
+type method struct {
+	name    *string        // name of method
+	pkgPath *string        // nil for exported Names; otherwise import path
+	mtyp    *rtype         // method type (without receiver)
+	typ     *rtype         // .(*FuncType) underneath (with receiver)
+	tfn     unsafe.Pointer // fn used for normal method call
+}
+
+// uncommonType is present only for types with names or methods
+// (if T is a named type, the uncommonTypes for T and *T have methods).
+// Using a pointer to this struct reduces the overall size required
+// to describe an unnamed type with no methods.
+type uncommonType struct {
+	name    *string  // name of type
+	pkgPath *string  // import path; nil for built-in types like int, string
+	methods []method // methods associated with type
+}
+
+// ChanDir represents a channel type's direction.
+type ChanDir int
+
+const (
+	RecvDir ChanDir             = 1 << iota // <-chan
+	SendDir                                 // chan<-
+	BothDir = RecvDir | SendDir             // chan
+)
+
+// arrayType represents a fixed array type.
+type arrayType struct {
+	rtype `reflect:"array"`
+	elem  *rtype // array element type
+	slice *rtype // slice type
+	len   uintptr
+}
+
+// chanType represents a channel type.
+type chanType struct {
+	rtype `reflect:"chan"`
+	elem  *rtype  // channel element type
+	dir   uintptr // channel direction (ChanDir)
+}
+
+// funcType represents a function type.
+type funcType struct {
+	rtype     `reflect:"func"`
+	dotdotdot bool     // last input parameter is ...
+	in        []*rtype // input parameter types
+	out       []*rtype // output parameter types
+}
+
+// imethod represents a method on an interface type
+type imethod struct {
+	name    *string // name of method
+	pkgPath *string // nil for exported Names; otherwise import path
+	typ     *rtype  // .(*FuncType) underneath
+}
+
+// interfaceType represents an interface type.
+type interfaceType struct {
+	rtype   `reflect:"interface"`
+	methods []imethod // sorted by hash
+}
+
+// mapType represents a map type.
+type mapType struct {
+	rtype `reflect:"map"`
+	key   *rtype // map key type
+	elem  *rtype // map element (value) type
+	// bucket *rtype // internal bucket structure
+	// hmap   *rtype // internal map header
+}
+
+// ptrType represents a pointer type.
+type ptrType struct {
+	rtype `reflect:"ptr"`
+	elem  *rtype // pointer element (pointed at) type
+}
+
+// sliceType represents a slice type.
+type sliceType struct {
+	rtype `reflect:"slice"`
+	elem  *rtype // slice element type
+}
+
+// Struct field
+type structField struct {
+	name    *string // nil for embedded fields
+	pkgPath *string // nil for exported Names; otherwise import path
+	typ     *rtype  // type of field
+	tag     *string // nil if no tag
+	offset  uintptr // byte offset of field within struct
+}
+
+// structType represents a struct type.
+type structType struct {
+	rtype  `reflect:"struct"`
+	fields []structField // sorted by offset
+}
+
+// NOTE: These are copied from ../runtime/mgc0.h.
+// They must be kept in sync.
+const (
+	_GC_END = iota
+	_GC_PTR
+	_GC_APTR
+	_GC_ARRAY_START
+	_GC_ARRAY_NEXT
+	_GC_CALL
+	_GC_CHAN_PTR
+	_GC_STRING
+	_GC_EFACE
+	_GC_IFACE
+	_GC_SLICE
+	_GC_REGION
+	_GC_NUM_INSTR
+)
+
+/*
+ * The compiler knows the exact layout of all the data structures above.
+ * The compiler does not know about the data structures and methods below.
+ */
+
+// Method represents a single method.
+type Method struct {
+	// Name is the method name.
+	// PkgPath is the package path that qualifies a lower case (unexported)
+	// method name.  It is empty for upper case (exported) method names.
+	// The combination of PkgPath and Name uniquely identifies a method
+	// in a method set.
+	// See http://golang.org/ref/spec#Uniqueness_of_identifiers
+	Name    string
+	PkgPath string
+
+	Type  Type  // method type
+	Func  Value // func with receiver as first argument
+	Index int   // index for Type.Method
+}
+
+// High bit says whether type has
+// embedded pointers,to help garbage collector.
+const (
+	kindMask       = 0x7f
+	kindNoPointers = 0x80
+)
+
+func (k Kind) String() string {
+	if int(k) < len(kindNames) {
+		return kindNames[k]
+	}
+	return "kind" + strconv.Itoa(int(k))
+}
+
+var kindNames = []string{
+	Invalid:       "invalid",
+	Bool:          "bool",
+	Int:           "int",
+	Int8:          "int8",
+	Int16:         "int16",
+	Int32:         "int32",
+	Int64:         "int64",
+	Uint:          "uint",
+	Uint8:         "uint8",
+	Uint16:        "uint16",
+	Uint32:        "uint32",
+	Uint64:        "uint64",
+	Uintptr:       "uintptr",
+	Float32:       "float32",
+	Float64:       "float64",
+	Complex64:     "complex64",
+	Complex128:    "complex128",
+	Array:         "array",
+	Chan:          "chan",
+	Func:          "func",
+	Interface:     "interface",
+	Map:           "map",
+	Ptr:           "ptr",
+	Slice:         "slice",
+	String:        "string",
+	Struct:        "struct",
+	UnsafePointer: "unsafe.Pointer",
+}
+
+func (t *uncommonType) uncommon() *uncommonType {
+	return t
+}
+
+func (t *uncommonType) PkgPath() string {
+	if t == nil || t.pkgPath == nil {
+		return ""
+	}
+	return *t.pkgPath
+}
+
+func (t *uncommonType) Name() string {
+	if t == nil || t.name == nil {
+		return ""
+	}
+	return *t.name
+}
+
+func (t *rtype) rawString() string { return *t.string }
+
+func (t *rtype) String() string {
+	// For gccgo, strip out quoted strings.
+	s := *t.string
+	var q bool
+	r := make([]byte, len(s))
+	j := 0
+	for i := 0; i < len(s); i++ {
+		if s[i] == '\t' {
+			q = !q
+		} else if !q {
+			r[j] = s[i]
+			j++
+		}
+	}
+	return string(r[:j])
+}
+
+func (t *rtype) Size() uintptr { return t.size }
+
+func (t *rtype) Bits() int {
+	if t == nil {
+		panic("reflect: Bits of nil Type")
+	}
+	k := t.Kind()
+	if k < Int || k > Complex128 {
+		panic("reflect: Bits of non-arithmetic Type " + t.String())
+	}
+	return int(t.size) * 8
+}
+
+func (t *rtype) Align() int { return int(t.align) }
+
+func (t *rtype) FieldAlign() int { return int(t.fieldAlign) }
+
+func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
+
+func (t *rtype) pointers() bool { return t.kind&kindNoPointers == 0 }
+
+func (t *rtype) common() *rtype { return t }
+
+func (t *uncommonType) Method(i int) (m Method) {
+	if t == nil || i < 0 || i >= len(t.methods) {
+		panic("reflect: Method index out of range")
+	}
+	p := &t.methods[i]
+	if p.name != nil {
+		m.Name = *p.name
+	}
+	fl := flag(Func) << flagKindShift
+	if p.pkgPath != nil {
+		m.PkgPath = *p.pkgPath
+		fl |= flagRO
+	}
+	mt := p.typ
+	m.Type = toType(mt)
+	x := new(unsafe.Pointer)
+	*x = unsafe.Pointer(&p.tfn)
+	m.Func = Value{mt, unsafe.Pointer(x) /* 0, */, fl | flagIndir | flagMethodFn}
+	m.Index = i
+	return
+}
+
+func (t *uncommonType) NumMethod() int {
+	if t == nil {
+		return 0
+	}
+	return len(t.methods)
+}
+
+func (t *uncommonType) MethodByName(name string) (m Method, ok bool) {
+	if t == nil {
+		return
+	}
+	var p *method
+	for i := range t.methods {
+		p = &t.methods[i]
+		if p.name != nil && *p.name == name {
+			return t.Method(i), true
+		}
+	}
+	return
+}
+
+// TODO(rsc): 6g supplies these, but they are not
+// as efficient as they could be: they have commonType
+// as the receiver instead of *rtype.
+func (t *rtype) NumMethod() int {
+	if t.Kind() == Interface {
+		tt := (*interfaceType)(unsafe.Pointer(t))
+		return tt.NumMethod()
+	}
+	return t.uncommonType.NumMethod()
+}
+
+func (t *rtype) Method(i int) (m Method) {
+	if t.Kind() == Interface {
+		tt := (*interfaceType)(unsafe.Pointer(t))
+		return tt.Method(i)
+	}
+	return t.uncommonType.Method(i)
+}
+
+func (t *rtype) MethodByName(name string) (m Method, ok bool) {
+	if t.Kind() == Interface {
+		tt := (*interfaceType)(unsafe.Pointer(t))
+		return tt.MethodByName(name)
+	}
+	return t.uncommonType.MethodByName(name)
+}
+
+func (t *rtype) PkgPath() string {
+	return t.uncommonType.PkgPath()
+}
+
+func (t *rtype) Name() string {
+	return t.uncommonType.Name()
+}
+
+func (t *rtype) ChanDir() ChanDir {
+	if t.Kind() != Chan {
+		panic("reflect: ChanDir of non-chan type")
+	}
+	tt := (*chanType)(unsafe.Pointer(t))
+	return ChanDir(tt.dir)
+}
+
+func (t *rtype) IsVariadic() bool {
+	if t.Kind() != Func {
+		panic("reflect: IsVariadic of non-func type")
+	}
+	tt := (*funcType)(unsafe.Pointer(t))
+	return tt.dotdotdot
+}
+
+func (t *rtype) Elem() Type {
+	switch t.Kind() {
+	case Array:
+		tt := (*arrayType)(unsafe.Pointer(t))
+		return toType(tt.elem)
+	case Chan:
+		tt := (*chanType)(unsafe.Pointer(t))
+		return toType(tt.elem)
+	case Map:
+		tt := (*mapType)(unsafe.Pointer(t))
+		return toType(tt.elem)
+	case Ptr:
+		tt := (*ptrType)(unsafe.Pointer(t))
+		return toType(tt.elem)
+	case Slice:
+		tt := (*sliceType)(unsafe.Pointer(t))
+		return toType(tt.elem)
+	}
+	panic("reflect: Elem of invalid type")
+}
+
+func (t *rtype) Field(i int) StructField {
+	if t.Kind() != Struct {
+		panic("reflect: Field of non-struct type")
+	}
+	tt := (*structType)(unsafe.Pointer(t))
+	return tt.Field(i)
+}
+
+func (t *rtype) FieldByIndex(index []int) StructField {
+	if t.Kind() != Struct {
+		panic("reflect: FieldByIndex of non-struct type")
+	}
+	tt := (*structType)(unsafe.Pointer(t))
+	return tt.FieldByIndex(index)
+}
+
+func (t *rtype) FieldByName(name string) (StructField, bool) {
+	if t.Kind() != Struct {
+		panic("reflect: FieldByName of non-struct type")
+	}
+	tt := (*structType)(unsafe.Pointer(t))
+	return tt.FieldByName(name)
+}
+
+func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
+	if t.Kind() != Struct {
+		panic("reflect: FieldByNameFunc of non-struct type")
+	}
+	tt := (*structType)(unsafe.Pointer(t))
+	return tt.FieldByNameFunc(match)
+}
+
+func (t *rtype) In(i int) Type {
+	if t.Kind() != Func {
+		panic("reflect: In of non-func type")
+	}
+	tt := (*funcType)(unsafe.Pointer(t))
+	return toType(tt.in[i])
+}
+
+func (t *rtype) Key() Type {
+	if t.Kind() != Map {
+		panic("reflect: Key of non-map type")
+	}
+	tt := (*mapType)(unsafe.Pointer(t))
+	return toType(tt.key)
+}
+
+func (t *rtype) Len() int {
+	if t.Kind() != Array {
+		panic("reflect: Len of non-array type")
+	}
+	tt := (*arrayType)(unsafe.Pointer(t))
+	return int(tt.len)
+}
+
+func (t *rtype) NumField() int {
+	if t.Kind() != Struct {
+		panic("reflect: NumField of non-struct type")
+	}
+	tt := (*structType)(unsafe.Pointer(t))
+	return len(tt.fields)
+}
+
+func (t *rtype) NumIn() int {
+	if t.Kind() != Func {
+		panic("reflect: NumIn of non-func type")
+	}
+	tt := (*funcType)(unsafe.Pointer(t))
+	return len(tt.in)
+}
+
+func (t *rtype) NumOut() int {
+	if t.Kind() != Func {
+		panic("reflect: NumOut of non-func type")
+	}
+	tt := (*funcType)(unsafe.Pointer(t))
+	return len(tt.out)
+}
+
+func (t *rtype) Out(i int) Type {
+	if t.Kind() != Func {
+		panic("reflect: Out of non-func type")
+	}
+	tt := (*funcType)(unsafe.Pointer(t))
+	return toType(tt.out[i])
+}
+
+func (d ChanDir) String() string {
+	switch d {
+	case SendDir:
+		return "chan<-"
+	case RecvDir:
+		return "<-chan"
+	case BothDir:
+		return "chan"
+	}
+	return "ChanDir" + strconv.Itoa(int(d))
+}
+
+// Method returns the i'th method in the type's method set.
+func (t *interfaceType) Method(i int) (m Method) {
+	if i < 0 || i >= len(t.methods) {
+		return
+	}
+	p := &t.methods[i]
+	m.Name = *p.name
+	if p.pkgPath != nil {
+		m.PkgPath = *p.pkgPath
+	}
+	m.Type = toType(p.typ)
+	m.Index = i
+	return
+}
+
+// NumMethod returns the number of interface methods in the type's method set.
+func (t *interfaceType) NumMethod() int { return len(t.methods) }
+
+// MethodByName method with the given name in the type's method set.
+func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
+	if t == nil {
+		return
+	}
+	var p *imethod
+	for i := range t.methods {
+		p = &t.methods[i]
+		if *p.name == name {
+			return t.Method(i), true
+		}
+	}
+	return
+}
+
+// A StructField describes a single field in a struct.
+type StructField struct {
+	// Name is the field name.
+	// PkgPath is the package path that qualifies a lower case (unexported)
+	// field name.  It is empty for upper case (exported) field names.
+	// See http://golang.org/ref/spec#Uniqueness_of_identifiers
+	Name    string
+	PkgPath string
+
+	Type      Type      // field type
+	Tag       StructTag // field tag string
+	Offset    uintptr   // offset within struct, in bytes
+	Index     []int     // index sequence for Type.FieldByIndex
+	Anonymous bool      // is an embedded field
+}
+
+// A StructTag is the tag string in a struct field.
+//
+// By convention, tag strings are a concatenation of
+// optionally space-separated key:"value" pairs.
+// Each key is a non-empty string consisting of non-control
+// characters other than space (U+0020 ' '), quote (U+0022 '"'),
+// and colon (U+003A ':').  Each value is quoted using U+0022 '"'
+// characters and Go string literal syntax.
+type StructTag string
+
+// Get returns the value associated with key in the tag string.
+// If there is no such key in the tag, Get returns the empty string.
+// If the tag does not have the conventional format, the value
+// returned by Get is unspecified.
+func (tag StructTag) Get(key string) string {
+	for tag != "" {
+		// skip leading space
+		i := 0
+		for i < len(tag) && tag[i] == ' ' {
+			i++
+		}
+		tag = tag[i:]
+		if tag == "" {
+			break
+		}
+
+		// scan to colon.
+		// a space or a quote is a syntax error
+		i = 0
+		for i < len(tag) && tag[i] != ' ' && tag[i] != ':' && tag[i] != '"' {
+			i++
+		}
+		if i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
+			break
+		}
+		name := string(tag[:i])
+		tag = tag[i+1:]
+
+		// scan quoted string to find value
+		i = 1
+		for i < len(tag) && tag[i] != '"' {
+			if tag[i] == '\\' {
+				i++
+			}
+			i++
+		}
+		if i >= len(tag) {
+			break
+		}
+		qvalue := string(tag[:i+1])
+		tag = tag[i+1:]
+
+		if key == name {
+			value, _ := strconv.Unquote(qvalue)
+			return value
+		}
+	}
+	return ""
+}
+
+// Field returns the i'th struct field.
+func (t *structType) Field(i int) (f StructField) {
+	if i < 0 || i >= len(t.fields) {
+		return
+	}
+	p := &t.fields[i]
+	f.Type = toType(p.typ)
+	if p.name != nil {
+		f.Name = *p.name
+	} else {
+		t := f.Type
+		if t.Kind() == Ptr {
+			t = t.Elem()
+		}
+		f.Name = t.Name()
+		f.Anonymous = true
+	}
+	if p.pkgPath != nil {
+		f.PkgPath = *p.pkgPath
+	}
+	if p.tag != nil {
+		f.Tag = StructTag(*p.tag)
+	}
+	f.Offset = p.offset
+
+	// NOTE(rsc): This is the only allocation in the interface
+	// presented by a reflect.Type.  It would be nice to avoid,
+	// at least in the common cases, but we need to make sure
+	// that misbehaving clients of reflect cannot affect other
+	// uses of reflect.  One possibility is CL 5371098, but we
+	// postponed that ugliness until there is a demonstrated
+	// need for the performance.  This is issue 2320.
+	f.Index = []int{i}
+	return
+}
+
+// TODO(gri): Should there be an error/bool indicator if the index
+//            is wrong for FieldByIndex?
+
+// FieldByIndex returns the nested field corresponding to index.
+func (t *structType) FieldByIndex(index []int) (f StructField) {
+	f.Type = toType(&t.rtype)
+	for i, x := range index {
+		if i > 0 {
+			ft := f.Type
+			if ft.Kind() == Ptr && ft.Elem().Kind() == Struct {
+				ft = ft.Elem()
+			}
+			f.Type = ft
+		}
+		f = f.Type.Field(x)
+	}
+	return
+}
+
+// A fieldScan represents an item on the fieldByNameFunc scan work list.
+type fieldScan struct {
+	typ   *structType
+	index []int
+}
+
+// FieldByNameFunc returns the struct field with a name that satisfies the
+// match function and a boolean to indicate if the field was found.
+func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
+	// This uses the same condition that the Go language does: there must be a unique instance
+	// of the match at a given depth level. If there are multiple instances of a match at the
+	// same depth, they annihilate each other and inhibit any possible match at a lower level.
+	// The algorithm is breadth first search, one depth level at a time.
+
+	// The current and next slices are work queues:
+	// current lists the fields to visit on this depth level,
+	// and next lists the fields on the next lower level.
+	current := []fieldScan{}
+	next := []fieldScan{{typ: t}}
+
+	// nextCount records the number of times an embedded type has been
+	// encountered and considered for queueing in the 'next' slice.
+	// We only queue the first one, but we increment the count on each.
+	// If a struct type T can be reached more than once at a given depth level,
+	// then it annihilates itself and need not be considered at all when we
+	// process that next depth level.
+	var nextCount map[*structType]int
+
+	// visited records the structs that have been considered already.
+	// Embedded pointer fields can create cycles in the graph of
+	// reachable embedded types; visited avoids following those cycles.
+	// It also avoids duplicated effort: if we didn't find the field in an
+	// embedded type T at level 2, we won't find it in one at level 4 either.
+	visited := map[*structType]bool{}
+
+	for len(next) > 0 {
+		current, next = next, current[:0]
+		count := nextCount
+		nextCount = nil
+
+		// Process all the fields at this depth, now listed in 'current'.
+		// The loop queues embedded fields found in 'next', for processing during the next
+		// iteration. The multiplicity of the 'current' field counts is recorded
+		// in 'count'; the multiplicity of the 'next' field counts is recorded in 'nextCount'.
+		for _, scan := range current {
+			t := scan.typ
+			if visited[t] {
+				// We've looked through this type before, at a higher level.
+				// That higher level would shadow the lower level we're now at,
+				// so this one can't be useful to us. Ignore it.
+				continue
+			}
+			visited[t] = true
+			for i := range t.fields {
+				f := &t.fields[i]
+				// Find name and type for field f.
+				var fname string
+				var ntyp *rtype
+				if f.name != nil {
+					fname = *f.name
+				} else {
+					// Anonymous field of type T or *T.
+					// Name taken from type.
+					ntyp = f.typ
+					if ntyp.Kind() == Ptr {
+						ntyp = ntyp.Elem().common()
+					}
+					fname = ntyp.Name()
+				}
+
+				// Does it match?
+				if match(fname) {
+					// Potential match
+					if count[t] > 1 || ok {
+						// Name appeared multiple times at this level: annihilate.
+						return StructField{}, false
+					}
+					result = t.Field(i)
+					result.Index = nil
+					result.Index = append(result.Index, scan.index...)
+					result.Index = append(result.Index, i)
+					ok = true
+					continue
+				}
+
+				// Queue embedded struct fields for processing with next level,
+				// but only if we haven't seen a match yet at this level and only
+				// if the embedded types haven't already been queued.
+				if ok || ntyp == nil || ntyp.Kind() != Struct {
+					continue
+				}
+				ntyp = toType(ntyp).common()
+				styp := (*structType)(unsafe.Pointer(ntyp))
+				if nextCount[styp] > 0 {
+					nextCount[styp] = 2 // exact multiple doesn't matter
+					continue
+				}
+				if nextCount == nil {
+					nextCount = map[*structType]int{}
+				}
+				nextCount[styp] = 1
+				if count[t] > 1 {
+					nextCount[styp] = 2 // exact multiple doesn't matter
+				}
+				var index []int
+				index = append(index, scan.index...)
+				index = append(index, i)
+				next = append(next, fieldScan{styp, index})
+			}
+		}
+		if ok {
+			break
+		}
+	}
+	return
+}
+
+// FieldByName returns the struct field with the given name
+// and a boolean to indicate if the field was found.
+func (t *structType) FieldByName(name string) (f StructField, present bool) {
+	// Quick check for top-level name, or struct without anonymous fields.
+	hasAnon := false
+	if name != "" {
+		for i := range t.fields {
+			tf := &t.fields[i]
+			if tf.name == nil {
+				hasAnon = true
+				continue
+			}
+			if *tf.name == name {
+				return t.Field(i), true
+			}
+		}
+	}
+	if !hasAnon {
+		return
+	}
+	return t.FieldByNameFunc(func(s string) bool { return s == name })
+}
+
+// TypeOf returns the reflection Type of the value in the interface{}.
+// TypeOf(nil) returns nil.
+func TypeOf(i interface{}) Type {
+	eface := *(*emptyInterface)(unsafe.Pointer(&i))
+	return toType(eface.typ)
+}
+
+// ptrMap is the cache for PtrTo.
+var ptrMap struct {
+	sync.RWMutex
+	m map[*rtype]*ptrType
+}
+
+// garbage collection bytecode program for pointer to memory without pointers.
+// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
+type ptrDataGC struct {
+	width uintptr // sizeof(ptr)
+	op    uintptr // _GC_APTR
+	off   uintptr // 0
+	end   uintptr // _GC_END
+}
+
+var ptrDataGCProg = ptrDataGC{
+	width: unsafe.Sizeof((*byte)(nil)),
+	op:    _GC_APTR,
+	off:   0,
+	end:   _GC_END,
+}
+
+// garbage collection bytecode program for pointer to memory with pointers.
+// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
+type ptrGC struct {
+	width  uintptr        // sizeof(ptr)
+	op     uintptr        // _GC_PTR
+	off    uintptr        // 0
+	elemgc unsafe.Pointer // element gc type
+	end    uintptr        // _GC_END
+}
+
+// PtrTo returns the pointer type with element t.
+// For example, if t represents type Foo, PtrTo(t) represents *Foo.
+func PtrTo(t Type) Type {
+	return t.(*rtype).ptrTo()
+}
+
+func (t *rtype) ptrTo() *rtype {
+	if p := t.ptrToThis; p != nil {
+		return p
+	}
+
+	// Otherwise, synthesize one.
+	// This only happens for pointers with no methods.
+	// We keep the mapping in a map on the side, because
+	// this operation is rare and a separate map lets us keep
+	// the type structures in read-only memory.
+	ptrMap.RLock()
+	if m := ptrMap.m; m != nil {
+		if p := m[t]; p != nil {
+			ptrMap.RUnlock()
+			return &p.rtype
+		}
+	}
+	ptrMap.RUnlock()
+	ptrMap.Lock()
+	if ptrMap.m == nil {
+		ptrMap.m = make(map[*rtype]*ptrType)
+	}
+	p := ptrMap.m[t]
+	if p != nil {
+		// some other goroutine won the race and created it
+		ptrMap.Unlock()
+		return &p.rtype
+	}
+
+	s := "*" + *t.string
+
+	canonicalTypeLock.RLock()
+	r, ok := canonicalType[s]
+	canonicalTypeLock.RUnlock()
+	if ok {
+		ptrMap.m[t] = (*ptrType)(unsafe.Pointer(r.(*rtype)))
+		ptrMap.Unlock()
+		return r.(*rtype)
+	}
+
+	// initialize p using *byte's ptrType as a prototype.
+	p = new(ptrType)
+	var iptr interface{} = (*unsafe.Pointer)(nil)
+	prototype := *(**ptrType)(unsafe.Pointer(&iptr))
+	*p = *prototype
+
+	p.string = &s
+
+	// For the type structures linked into the binary, the
+	// compiler provides a good hash of the string.
+	// Create a good hash for the new string by using
+	// the FNV-1 hash's mixing function to combine the
+	// old hash and the new "*".
+	// p.hash = fnv1(t.hash, '*')
+	// This is the gccgo version.
+	p.hash = (t.hash << 4) + 9
+
+	p.uncommonType = nil
+	p.ptrToThis = nil
+	p.zero = unsafe.Pointer(&make([]byte, p.size)[0])
+	p.elem = t
+
+	if t.kind&kindNoPointers != 0 {
+		p.gc = unsafe.Pointer(&ptrDataGCProg)
+	} else {
+		p.gc = unsafe.Pointer(&ptrGC{
+			width:  p.size,
+			op:     _GC_PTR,
+			off:    0,
+			elemgc: t.gc,
+			end:    _GC_END,
+		})
+	}
+
+	q := canonicalize(&p.rtype)
+	p = (*ptrType)(unsafe.Pointer(q.(*rtype)))
+
+	ptrMap.m[t] = p
+	ptrMap.Unlock()
+	return &p.rtype
+}
+
+// fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function.
+func fnv1(x uint32, list ...byte) uint32 {
+	for _, b := range list {
+		x = x*16777619 ^ uint32(b)
+	}
+	return x
+}
+
+func (t *rtype) Implements(u Type) bool {
+	if u == nil {
+		panic("reflect: nil type passed to Type.Implements")
+	}
+	if u.Kind() != Interface {
+		panic("reflect: non-interface type passed to Type.Implements")
+	}
+	return implements(u.(*rtype), t)
+}
+
+func (t *rtype) AssignableTo(u Type) bool {
+	if u == nil {
+		panic("reflect: nil type passed to Type.AssignableTo")
+	}
+	uu := u.(*rtype)
+	return directlyAssignable(uu, t) || implements(uu, t)
+}
+
+func (t *rtype) ConvertibleTo(u Type) bool {
+	if u == nil {
+		panic("reflect: nil type passed to Type.ConvertibleTo")
+	}
+	uu := u.(*rtype)
+	return convertOp(uu, t) != nil
+}
+
+// implements returns true if the type V implements the interface type T.
+func implements(T, V *rtype) bool {
+	if T.Kind() != Interface {
+		return false
+	}
+	t := (*interfaceType)(unsafe.Pointer(T))
+	if len(t.methods) == 0 {
+		return true
+	}
+
+	// The same algorithm applies in both cases, but the
+	// method tables for an interface type and a concrete type
+	// are different, so the code is duplicated.
+	// In both cases the algorithm is a linear scan over the two
+	// lists - T's methods and V's methods - simultaneously.
+	// Since method tables are stored in a unique sorted order
+	// (alphabetical, with no duplicate method names), the scan
+	// through V's methods must hit a match for each of T's
+	// methods along the way, or else V does not implement T.
+	// This lets us run the scan in overall linear time instead of
+	// the quadratic time  a naive search would require.
+	// See also ../runtime/iface.c.
+	if V.Kind() == Interface {
+		v := (*interfaceType)(unsafe.Pointer(V))
+		i := 0
+		for j := 0; j < len(v.methods); j++ {
+			tm := &t.methods[i]
+			vm := &v.methods[j]
+			if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.typ).common() == toType(tm.typ).common() {
+				if i++; i >= len(t.methods) {
+					return true
+				}
+			}
+		}
+		return false
+	}
+
+	v := V.uncommon()
+	if v == nil {
+		return false
+	}
+	i := 0
+	for j := 0; j < len(v.methods); j++ {
+		tm := &t.methods[i]
+		vm := &v.methods[j]
+		if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.mtyp).common() == toType(tm.typ).common() {
+			if i++; i >= len(t.methods) {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// directlyAssignable returns true if a value x of type V can be directly
+// assigned (using memmove) to a value of type T.
+// http://golang.org/doc/go_spec.html#Assignability
+// Ignoring the interface rules (implemented elsewhere)
+// and the ideal constant rules (no ideal constants at run time).
+func directlyAssignable(T, V *rtype) bool {
+	// x's type V is identical to T?
+	if T == V {
+		return true
+	}
+
+	// Otherwise at least one of T and V must be unnamed
+	// and they must have the same kind.
+	if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() {
+		return false
+	}
+
+	// x's type T and V must  have identical underlying types.
+	return haveIdenticalUnderlyingType(T, V)
+}
+
+func haveIdenticalUnderlyingType(T, V *rtype) bool {
+	if T == V {
+		return true
+	}
+
+	kind := T.Kind()
+	if kind != V.Kind() {
+		return false
+	}
+
+	// Non-composite types of equal kind have same underlying type
+	// (the predefined instance of the type).
+	if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
+		return true
+	}
+
+	// Composite types.
+	switch kind {
+	case Array:
+		return T.Elem() == V.Elem() && T.Len() == V.Len()
+
+	case Chan:
+		// Special case:
+		// x is a bidirectional channel value, T is a channel type,
+		// and x's type V and T have identical element types.
+		if V.ChanDir() == BothDir && T.Elem() == V.Elem() {
+			return true
+		}
+
+		// Otherwise continue test for identical underlying type.
+		return V.ChanDir() == T.ChanDir() && T.Elem() == V.Elem()
+
+	case Func:
+		t := (*funcType)(unsafe.Pointer(T))
+		v := (*funcType)(unsafe.Pointer(V))
+		if t.dotdotdot != v.dotdotdot || len(t.in) != len(v.in) || len(t.out) != len(v.out) {
+			return false
+		}
+		for i, typ := range t.in {
+			if typ != v.in[i] {
+				return false
+			}
+		}
+		for i, typ := range t.out {
+			if typ != v.out[i] {
+				return false
+			}
+		}
+		return true
+
+	case Interface:
+		t := (*interfaceType)(unsafe.Pointer(T))
+		v := (*interfaceType)(unsafe.Pointer(V))
+		if len(t.methods) == 0 && len(v.methods) == 0 {
+			return true
+		}
+		// Might have the same methods but still
+		// need a run time conversion.
+		return false
+
+	case Map:
+		return T.Key() == V.Key() && T.Elem() == V.Elem()
+
+	case Ptr, Slice:
+		return T.Elem() == V.Elem()
+
+	case Struct:
+		t := (*structType)(unsafe.Pointer(T))
+		v := (*structType)(unsafe.Pointer(V))
+		if len(t.fields) != len(v.fields) {
+			return false
+		}
+		for i := range t.fields {
+			tf := &t.fields[i]
+			vf := &v.fields[i]
+			if tf.name != vf.name && (tf.name == nil || vf.name == nil || *tf.name != *vf.name) {
+				return false
+			}
+			if tf.pkgPath != vf.pkgPath && (tf.pkgPath == nil || vf.pkgPath == nil || *tf.pkgPath != *vf.pkgPath) {
+				return false
+			}
+			if tf.typ != vf.typ {
+				return false
+			}
+			if tf.tag != vf.tag && (tf.tag == nil || vf.tag == nil || *tf.tag != *vf.tag) {
+				return false
+			}
+			if tf.offset != vf.offset {
+				return false
+			}
+		}
+		return true
+	}
+
+	return false
+}
+
+// The lookupCache caches ChanOf, MapOf, and SliceOf lookups.
+var lookupCache struct {
+	sync.RWMutex
+	m map[cacheKey]*rtype
+}
+
+// A cacheKey is the key for use in the lookupCache.
+// Four values describe any of the types we are looking for:
+// type kind, one or two subtypes, and an extra integer.
+type cacheKey struct {
+	kind  Kind
+	t1    *rtype
+	t2    *rtype
+	extra uintptr
+}
+
+// cacheGet looks for a type under the key k in the lookupCache.
+// If it finds one, it returns that type.
+// If not, it returns nil with the cache locked.
+// The caller is expected to use cachePut to unlock the cache.
+func cacheGet(k cacheKey) Type {
+	lookupCache.RLock()
+	t := lookupCache.m[k]
+	lookupCache.RUnlock()
+	if t != nil {
+		return t
+	}
+
+	lookupCache.Lock()
+	t = lookupCache.m[k]
+	if t != nil {
+		lookupCache.Unlock()
+		return t
+	}
+
+	if lookupCache.m == nil {
+		lookupCache.m = make(map[cacheKey]*rtype)
+	}
+
+	return nil
+}
+
+// cachePut stores the given type in the cache, unlocks the cache,
+// and returns the type. It is expected that the cache is locked
+// because cacheGet returned nil.
+func cachePut(k cacheKey, t *rtype) Type {
+	t = toType(t).common()
+	lookupCache.m[k] = t
+	lookupCache.Unlock()
+	return t
+}
+
+// garbage collection bytecode program for chan.
+// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
+type chanGC struct {
+	width uintptr // sizeof(map)
+	op    uintptr // _GC_CHAN_PTR
+	off   uintptr // 0
+	typ   *rtype  // map type
+	end   uintptr // _GC_END
+}
+
+type badGC struct {
+	width uintptr
+	end   uintptr
+}
+
+// ChanOf returns the channel type with the given direction and element type.
+// For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int.
+//
+// The gc runtime imposes a limit of 64 kB on channel element types.
+// If t's size is equal to or exceeds this limit, ChanOf panics.
+func ChanOf(dir ChanDir, t Type) Type {
+	typ := t.(*rtype)
+
+	// Look in cache.
+	ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
+	if ch := cacheGet(ckey); ch != nil {
+		return ch
+	}
+
+	// This restriction is imposed by the gc compiler and the runtime.
+	if typ.size >= 1<<16 {
+		lookupCache.Unlock()
+		panic("reflect.ChanOf: element size too large")
+	}
+
+	// Look in known types.
+	// TODO: Precedence when constructing string.
+	var s string
+	switch dir {
+	default:
+		lookupCache.Unlock()
+		panic("reflect.ChanOf: invalid dir")
+	case SendDir:
+		s = "chan<- " + *typ.string
+	case RecvDir:
+		s = "<-chan " + *typ.string
+	case BothDir:
+		s = "chan " + *typ.string
+	}
+
+	// Make a channel type.
+	var ichan interface{} = (chan unsafe.Pointer)(nil)
+	prototype := *(**chanType)(unsafe.Pointer(&ichan))
+	ch := new(chanType)
+	*ch = *prototype
+	ch.string = &s
+
+	// gccgo uses a different hash.
+	// ch.hash = fnv1(typ.hash, 'c', byte(dir))
+	ch.hash = 0
+	if dir&SendDir != 0 {
+		ch.hash += 1
+	}
+	if dir&RecvDir != 0 {
+		ch.hash += 2
+	}
+	ch.hash += typ.hash << 2
+	ch.hash <<= 3
+	ch.hash += 15
+
+	ch.elem = typ
+	ch.uncommonType = nil
+	ch.ptrToThis = nil
+	ch.zero = unsafe.Pointer(&make([]byte, ch.size)[0])
+
+	ch.gc = unsafe.Pointer(&chanGC{
+		width: ch.size,
+		op:    _GC_CHAN_PTR,
+		off:   0,
+		typ:   &ch.rtype,
+		end:   _GC_END,
+	})
+
+	// INCORRECT. Uncomment to check that TestChanOfGC fails when ch.gc is wrong.
+	// ch.gc = unsafe.Pointer(&badGC{width: ch.size, end: _GC_END})
+
+	return cachePut(ckey, &ch.rtype)
+}
+
+func ismapkey(*rtype) bool // implemented in runtime
+
+// MapOf returns the map type with the given key and element types.
+// For example, if k represents int and e represents string,
+// MapOf(k, e) represents map[int]string.
+//
+// If the key type is not a valid map key type (that is, if it does
+// not implement Go's == operator), MapOf panics.
+func MapOf(key, elem Type) Type {
+	ktyp := key.(*rtype)
+	etyp := elem.(*rtype)
+
+	if !ismapkey(ktyp) {
+		panic("reflect.MapOf: invalid key type " + ktyp.String())
+	}
+
+	// Look in cache.
+	ckey := cacheKey{Map, ktyp, etyp, 0}
+	if mt := cacheGet(ckey); mt != nil {
+		return mt
+	}
+
+	// Look in known types.
+	s := "map[" + *ktyp.string + "]" + *etyp.string
+
+	// Make a map type.
+	var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
+	prototype := *(**mapType)(unsafe.Pointer(&imap))
+	mt := new(mapType)
+	*mt = *prototype
+	mt.string = &s
+
+	// gccgo uses a different hash
+	// mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
+	mt.hash = ktyp.hash + etyp.hash + 2 + 14
+
+	mt.key = ktyp
+	mt.elem = etyp
+	// mt.bucket = bucketOf(ktyp, etyp)
+	// mt.hmap = hMapOf(mt.bucket)
+	mt.uncommonType = nil
+	mt.ptrToThis = nil
+	mt.zero = unsafe.Pointer(&make([]byte, mt.size)[0])
+	// mt.gc = unsafe.Pointer(&ptrGC{
+	// 	width:  unsafe.Sizeof(uintptr(0)),
+	// 	op:     _GC_PTR,
+	// 	off:    0,
+	// 	elemgc: nil,
+	// 	end:    _GC_END,
+	// })
+
+	// TODO(cmang): Generate GC data for Map elements.
+	mt.gc = unsafe.Pointer(&ptrDataGCProg)
+
+	// INCORRECT. Uncomment to check that TestMapOfGC and TestMapOfGCValues
+	// fail when mt.gc is wrong.
+	//mt.gc = unsafe.Pointer(&badGC{width: mt.size, end: _GC_END})
+
+	return cachePut(ckey, &mt.rtype)
+}
+
+// Make sure these routines stay in sync with ../../pkg/runtime/hashmap.c!
+// These types exist only for GC, so we only fill out GC relevant info.
+// Currently, that's just size and the GC program.  We also fill in string
+// for possible debugging use.
+const (
+	_BUCKETSIZE = 8
+	_MAXKEYSIZE = 128
+	_MAXVALSIZE = 128
+)
+
+func bucketOf(ktyp, etyp *rtype) *rtype {
+	if ktyp.size > _MAXKEYSIZE {
+		ktyp = PtrTo(ktyp).(*rtype)
+	}
+	if etyp.size > _MAXVALSIZE {
+		etyp = PtrTo(etyp).(*rtype)
+	}
+	ptrsize := unsafe.Sizeof(uintptr(0))
+
+	gc := make([]uintptr, 1)                                       // first entry is size, filled in at the end
+	offset := _BUCKETSIZE * unsafe.Sizeof(uint8(0))                // topbits
+	gc = append(gc, _GC_PTR, offset, 0 /*self pointer set below*/) // overflow
+	offset += ptrsize
+
+	if runtime.GOARCH == "amd64p32" {
+		offset += 4
+	}
+
+	// keys
+	if ktyp.kind&kindNoPointers == 0 {
+		gc = append(gc, _GC_ARRAY_START, offset, _BUCKETSIZE, ktyp.size)
+		gc = appendGCProgram(gc, ktyp)
+		gc = append(gc, _GC_ARRAY_NEXT)
+	}
+	offset += _BUCKETSIZE * ktyp.size
+
+	// values
+	if etyp.kind&kindNoPointers == 0 {
+		gc = append(gc, _GC_ARRAY_START, offset, _BUCKETSIZE, etyp.size)
+		gc = appendGCProgram(gc, etyp)
+		gc = append(gc, _GC_ARRAY_NEXT)
+	}
+	offset += _BUCKETSIZE * etyp.size
+
+	gc = append(gc, _GC_END)
+	gc[0] = offset
+	gc[3] = uintptr(unsafe.Pointer(&gc[0])) // set self pointer
+
+	b := new(rtype)
+	b.size = offset
+	// b.gc = unsafe.Pointer(&gc[0])
+	s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
+	b.string = &s
+	return b
+}
+
+// Take the GC program for "t" and append it to the GC program "gc".
+func appendGCProgram(gc []uintptr, t *rtype) []uintptr {
+	p := t.gc
+	p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0))) // skip size
+loop:
+	for {
+		var argcnt int
+		switch *(*uintptr)(p) {
+		case _GC_END:
+			// Note: _GC_END not included in append
+			break loop
+		case _GC_ARRAY_NEXT:
+			argcnt = 0
+		case _GC_APTR, _GC_STRING, _GC_EFACE, _GC_IFACE:
+			argcnt = 1
+		case _GC_PTR, _GC_CALL, _GC_CHAN_PTR, _GC_SLICE:
+			argcnt = 2
+		case _GC_ARRAY_START, _GC_REGION:
+			argcnt = 3
+		default:
+			panic("unknown GC program op for " + *t.string + ": " + strconv.FormatUint(*(*uint64)(p), 10))
+		}
+		for i := 0; i < argcnt+1; i++ {
+			gc = append(gc, *(*uintptr)(p))
+			p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0)))
+		}
+	}
+	return gc
+}
+func hMapOf(bucket *rtype) *rtype {
+	ptrsize := unsafe.Sizeof(uintptr(0))
+
+	// make gc program & compute hmap size
+	gc := make([]uintptr, 1)           // first entry is size, filled in at the end
+	offset := unsafe.Sizeof(uint(0))   // count
+	offset += unsafe.Sizeof(uint32(0)) // flags
+	offset += unsafe.Sizeof(uint32(0)) // hash0
+	offset += unsafe.Sizeof(uint8(0))  // B
+	offset += unsafe.Sizeof(uint8(0))  // keysize
+	offset += unsafe.Sizeof(uint8(0))  // valuesize
+	offset = (offset + 1) / 2 * 2
+	offset += unsafe.Sizeof(uint16(0)) // bucketsize
+	offset = (offset + ptrsize - 1) / ptrsize * ptrsize
+	// gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // buckets
+	offset += ptrsize
+	// gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // oldbuckets
+	offset += ptrsize
+	offset += ptrsize // nevacuate
+	gc = append(gc, _GC_END)
+	gc[0] = offset
+
+	h := new(rtype)
+	h.size = offset
+	// h.gc = unsafe.Pointer(&gc[0])
+	s := "hmap(" + *bucket.string + ")"
+	h.string = &s
+	return h
+}
+
+// garbage collection bytecode program for slice of non-zero-length values.
+// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
+type sliceGC struct {
+	width  uintptr        // sizeof(slice)
+	op     uintptr        // _GC_SLICE
+	off    uintptr        // 0
+	elemgc unsafe.Pointer // element gc program
+	end    uintptr        // _GC_END
+}
+
+// garbage collection bytecode program for slice of zero-length values.
+// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
+type sliceEmptyGC struct {
+	width uintptr // sizeof(slice)
+	op    uintptr // _GC_APTR
+	off   uintptr // 0
+	end   uintptr // _GC_END
+}
+
+var sliceEmptyGCProg = sliceEmptyGC{
+	width: unsafe.Sizeof([]byte(nil)),
+	op:    _GC_APTR,
+	off:   0,
+	end:   _GC_END,
+}
+
+// SliceOf returns the slice type with element type t.
+// For example, if t represents int, SliceOf(t) represents []int.
+func SliceOf(t Type) Type {
+	typ := t.(*rtype)
+
+	// Look in cache.
+	ckey := cacheKey{Slice, typ, nil, 0}
+	if slice := cacheGet(ckey); slice != nil {
+		return slice
+	}
+
+	// Look in known types.
+	s := "[]" + *typ.string
+
+	// Make a slice type.
+	var islice interface{} = ([]unsafe.Pointer)(nil)
+	prototype := *(**sliceType)(unsafe.Pointer(&islice))
+	slice := new(sliceType)
+	*slice = *prototype
+	slice.string = &s
+
+	// gccgo uses a different hash.
+	// slice.hash = fnv1(typ.hash, '[')
+	slice.hash = typ.hash + 1 + 13
+
+	slice.elem = typ
+	slice.uncommonType = nil
+	slice.ptrToThis = nil
+	slice.zero = unsafe.Pointer(&make([]byte, slice.size)[0])
+
+	if typ.size == 0 {
+		slice.gc = unsafe.Pointer(&sliceEmptyGCProg)
+	} else {
+		slice.gc = unsafe.Pointer(&sliceGC{
+			width:  slice.size,
+			op:     _GC_SLICE,
+			off:    0,
+			elemgc: typ.gc,
+			end:    _GC_END,
+		})
+	}
+
+	// INCORRECT. Uncomment to check that TestSliceOfOfGC fails when slice.gc is wrong.
+	// slice.gc = unsafe.Pointer(&badGC{width: slice.size, end: _GC_END})
+
+	return cachePut(ckey, &slice.rtype)
+}
+
+// ArrayOf returns the array type with the given count and element type.
+// For example, if t represents int, ArrayOf(5, t) represents [5]int.
+//
+// If the resulting type would be larger than the available address space,
+// ArrayOf panics.
+//
+// TODO(rsc): Unexported for now. Export once the alg field is set correctly
+// for the type. This may require significant work.
+func arrayOf(count int, elem Type) Type {
+	typ := elem.(*rtype)
+	slice := SliceOf(elem)
+
+	// Look in cache.
+	ckey := cacheKey{Array, typ, nil, uintptr(count)}
+	if slice := cacheGet(ckey); slice != nil {
+		return slice
+	}
+
+	// Look in known types.
+	s := "[" + strconv.Itoa(count) + "]" + *typ.string
+
+	// Make an array type.
+	var iarray interface{} = [1]unsafe.Pointer{}
+	prototype := *(**arrayType)(unsafe.Pointer(&iarray))
+	array := new(arrayType)
+	*array = *prototype
+	array.string = &s
+
+	// gccgo uses a different hash.
+	// array.hash = fnv1(typ.hash, '[')
+	// for n := uint32(count); n > 0; n >>= 8 {
+	// 	array.hash = fnv1(array.hash, byte(n))
+	// }
+	// array.hash = fnv1(array.hash, ']')
+	array.hash = typ.hash + 1 + 13
+
+	array.elem = typ
+	max := ^uintptr(0) / typ.size
+	if uintptr(count) > max {
+		panic("reflect.ArrayOf: array size would exceed virtual address space")
+	}
+	array.size = typ.size * uintptr(count)
+	array.align = typ.align
+	array.fieldAlign = typ.fieldAlign
+	// TODO: array.alg
+	// TODO: array.gc
+	array.uncommonType = nil
+	array.ptrToThis = nil
+	array.zero = unsafe.Pointer(&make([]byte, array.size)[0])
+	array.len = uintptr(count)
+	array.slice = slice.(*rtype)
+
+	return cachePut(ckey, &array.rtype)
+}
+
+// toType converts from a *rtype to a Type that can be returned
+// to the client of package reflect. In gc, the only concern is that
+// a nil *rtype must be replaced by a nil Type, but in gccgo this
+// function takes care of ensuring that multiple *rtype for the same
+// type are coalesced into a single Type.
+var canonicalType = make(map[string]Type)
+
+var canonicalTypeLock sync.RWMutex
+
+func canonicalize(t Type) Type {
+	if t == nil {
+		return nil
+	}
+	u := t.uncommon()
+	var s string
+	if u == nil || u.PkgPath() == "" {
+		s = t.rawString()
+	} else {
+		s = u.PkgPath() + "." + u.Name()
+	}
+	canonicalTypeLock.RLock()
+	if r, ok := canonicalType[s]; ok {
+		canonicalTypeLock.RUnlock()
+		return r
+	}
+	canonicalTypeLock.RUnlock()
+	canonicalTypeLock.Lock()
+	if r, ok := canonicalType[s]; ok {
+		canonicalTypeLock.Unlock()
+		return r
+	}
+	canonicalType[s] = t
+	canonicalTypeLock.Unlock()
+	return t
+}
+
+func toType(p *rtype) Type {
+	if p == nil {
+		return nil
+	}
+	return canonicalize(p)
+}
diff --git a/third_party/gofrontend/libgo/go/reflect/value.go b/third_party/gofrontend/libgo/go/reflect/value.go
new file mode 100644
index 0000000..c36e995
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/reflect/value.go
@@ -0,0 +1,2596 @@
+// 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 reflect
+
+import (
+	"math"
+	"runtime"
+	"strconv"
+	"unsafe"
+)
+
+const bigEndian = false // can be smarter if we find a big-endian machine
+const ptrSize = unsafe.Sizeof((*byte)(nil))
+const cannotSet = "cannot set value obtained from unexported struct field"
+
+// TODO: This will have to go away when
+// the new gc goes in.
+func memmove(adst, asrc unsafe.Pointer, n uintptr) {
+	dst := uintptr(adst)
+	src := uintptr(asrc)
+	switch {
+	case src < dst && src+n > dst:
+		// byte copy backward
+		// careful: i is unsigned
+		for i := n; i > 0; {
+			i--
+			*(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
+		}
+	case (n|src|dst)&(ptrSize-1) != 0:
+		// byte copy forward
+		for i := uintptr(0); i < n; i++ {
+			*(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
+		}
+	default:
+		// word copy forward
+		for i := uintptr(0); i < n; i += ptrSize {
+			*(*uintptr)(unsafe.Pointer(dst + i)) = *(*uintptr)(unsafe.Pointer(src + i))
+		}
+	}
+}
+
+// Value is the reflection interface to a Go value.
+//
+// Not all methods apply to all kinds of values.  Restrictions,
+// if any, are noted in the documentation for each method.
+// Use the Kind method to find out the kind of value before
+// calling kind-specific methods.  Calling a method
+// inappropriate to the kind of type causes a run time panic.
+//
+// The zero Value represents no value.
+// Its IsValid method returns false, its Kind method returns Invalid,
+// its String method returns "<invalid Value>", and all other methods panic.
+// Most functions and methods never return an invalid value.
+// If one does, its documentation states the conditions explicitly.
+//
+// A Value can be used concurrently by multiple goroutines provided that
+// the underlying Go value can be used concurrently for the equivalent
+// direct operations.
+type Value struct {
+	// typ holds the type of the value represented by a Value.
+	typ *rtype
+
+	// Pointer-valued data or, if flagIndir is set, pointer to data.
+	// Valid when either flagIndir is set or typ.pointers() is true.
+	// Gccgo always uses this field.
+	ptr unsafe.Pointer
+
+	// Non-pointer-valued data.  When the data is smaller
+	// than a word, it begins at the first byte (in the memory
+	// address sense) of this field.
+	// Valid when flagIndir is not set and typ.pointers() is false.
+	// Gccgo never uses this field.
+	// scalar uintptr
+
+	// flag holds metadata about the value.
+	// The lowest bits are flag bits:
+	//	- flagRO: obtained via unexported field, so read-only
+	//	- flagIndir: val holds a pointer to the data
+	//	- flagAddr: v.CanAddr is true (implies flagIndir)
+	//	- flagMethod: v is a method value.
+	// The next five bits give the Kind of the value.
+	// This repeats typ.Kind() except for method values.
+	// The remaining 23+ bits give a method number for method values.
+	// If flag.kind() != Func, code can assume that flagMethod is unset.
+	// If typ.size > ptrSize, code can assume that flagIndir is set.
+	flag
+
+	// A method value represents a curried method invocation
+	// like r.Read for some receiver r.  The typ+val+flag bits describe
+	// the receiver r, but the flag's Kind bits say Func (methods are
+	// functions), and the top bits of the flag give the method number
+	// in r's type's method table.
+}
+
+type flag uintptr
+
+const (
+	flagRO flag = 1 << iota
+	flagIndir
+	flagAddr
+	flagMethod
+	flagMethodFn         // gccgo: first fn parameter is always pointer
+	flagKindShift        = iota
+	flagKindWidth        = 5 // there are 27 kinds
+	flagKindMask    flag = 1<<flagKindWidth - 1
+	flagMethodShift      = flagKindShift + flagKindWidth
+)
+
+func (f flag) kind() Kind {
+	return Kind((f >> flagKindShift) & flagKindMask)
+}
+
+// pointer returns the underlying pointer represented by v.
+// v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer
+func (v Value) pointer() unsafe.Pointer {
+	if v.typ.size != ptrSize || !v.typ.pointers() {
+		panic("can't call pointer on a non-pointer Value")
+	}
+	if v.flag&flagIndir != 0 {
+		return *(*unsafe.Pointer)(v.ptr)
+	}
+	return v.ptr
+}
+
+// packEface converts v to the empty interface.
+func packEface(v Value) interface{} {
+	t := v.typ
+	var i interface{}
+	e := (*emptyInterface)(unsafe.Pointer(&i))
+	// First, fill in the data portion of the interface.
+	switch {
+	case v.Kind() != Ptr && v.Kind() != UnsafePointer:
+		// Value is indirect, and so is the interface we're making.
+		if v.flag&flagIndir == 0 {
+			panic("reflect: missing flagIndir")
+		}
+		ptr := v.ptr
+		if v.flag&flagAddr != 0 {
+			// TODO: pass safe boolean from valueInterface so
+			// we don't need to copy if safe==true?
+			c := unsafe_New(t)
+			memmove(c, ptr, t.size)
+			ptr = c
+		}
+		e.word = iword(ptr)
+	case v.flag&flagIndir != 0:
+		// Value is indirect, but interface is direct.  We need
+		// to load the data at v.ptr into the interface data word.
+		if t.pointers() {
+			e.word = iword(*(*unsafe.Pointer)(v.ptr))
+		} else {
+			e.word = iword(loadScalar(v.ptr, t.size))
+		}
+	default:
+		// Value is direct, and so is the interface.
+		if t.pointers() {
+			e.word = iword(v.ptr)
+		} else {
+			// e.word = iword(v.scalar)
+			panic("reflect: missing flagIndir")
+		}
+	}
+	// Now, fill in the type portion.  We're very careful here not
+	// to have any operation between the e.word and e.typ assignments
+	// that would let the garbage collector observe the partially-built
+	// interface value.
+	e.typ = t
+	return i
+}
+
+// unpackEface converts the empty interface i to a Value.
+func unpackEface(i interface{}) Value {
+	e := (*emptyInterface)(unsafe.Pointer(&i))
+	// NOTE: don't read e.word until we know whether it is really a pointer or not.
+	t := e.typ
+	if t == nil {
+		return Value{}
+	}
+	f := flag(t.Kind()) << flagKindShift
+	if t.Kind() != Ptr && t.Kind() != UnsafePointer {
+		f |= flagIndir
+	}
+	return Value{t, unsafe.Pointer(e.word), f}
+}
+
+// A ValueError occurs when a Value method is invoked on
+// a Value that does not support it.  Such cases are documented
+// in the description of each method.
+type ValueError struct {
+	Method string
+	Kind   Kind
+}
+
+func (e *ValueError) Error() string {
+	if e.Kind == 0 {
+		return "reflect: call of " + e.Method + " on zero Value"
+	}
+	return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
+}
+
+// methodName returns the name of the calling method,
+// assumed to be two stack frames above.
+func methodName() string {
+	pc, _, _, _ := runtime.Caller(2)
+	f := runtime.FuncForPC(pc)
+	if f == nil {
+		return "unknown method"
+	}
+	return f.Name()
+}
+
+// An iword is the word that would be stored in an
+// interface to represent a given value v.  Specifically, if v is
+// bigger than a pointer, its word is a pointer to v's data.
+// Otherwise, its word holds the data stored
+// in its leading bytes (so is not a pointer).
+// This type is very dangerous for the garbage collector because
+// it must be treated conservatively.  We try to never expose it
+// to the GC here so that GC remains precise.
+type iword unsafe.Pointer
+
+// loadScalar loads n bytes at p from memory into a uintptr
+// that forms the second word of an interface.  The data
+// must be non-pointer in nature.
+func loadScalar(p unsafe.Pointer, n uintptr) uintptr {
+	// Run the copy ourselves instead of calling memmove
+	// to avoid moving w to the heap.
+	var w uintptr
+	switch n {
+	default:
+		panic("reflect: internal error: loadScalar of " + strconv.Itoa(int(n)) + "-byte value")
+	case 0:
+	case 1:
+		*(*uint8)(unsafe.Pointer(&w)) = *(*uint8)(p)
+	case 2:
+		*(*uint16)(unsafe.Pointer(&w)) = *(*uint16)(p)
+	case 3:
+		*(*[3]byte)(unsafe.Pointer(&w)) = *(*[3]byte)(p)
+	case 4:
+		*(*uint32)(unsafe.Pointer(&w)) = *(*uint32)(p)
+	case 5:
+		*(*[5]byte)(unsafe.Pointer(&w)) = *(*[5]byte)(p)
+	case 6:
+		*(*[6]byte)(unsafe.Pointer(&w)) = *(*[6]byte)(p)
+	case 7:
+		*(*[7]byte)(unsafe.Pointer(&w)) = *(*[7]byte)(p)
+	case 8:
+		*(*uint64)(unsafe.Pointer(&w)) = *(*uint64)(p)
+	}
+	return w
+}
+
+// storeScalar stores n bytes from w into p.
+func storeScalar(p unsafe.Pointer, w uintptr, n uintptr) {
+	// Run the copy ourselves instead of calling memmove
+	// to avoid moving w to the heap.
+	switch n {
+	default:
+		panic("reflect: internal error: storeScalar of " + strconv.Itoa(int(n)) + "-byte value")
+	case 0:
+	case 1:
+		*(*uint8)(p) = *(*uint8)(unsafe.Pointer(&w))
+	case 2:
+		*(*uint16)(p) = *(*uint16)(unsafe.Pointer(&w))
+	case 3:
+		*(*[3]byte)(p) = *(*[3]byte)(unsafe.Pointer(&w))
+	case 4:
+		*(*uint32)(p) = *(*uint32)(unsafe.Pointer(&w))
+	case 5:
+		*(*[5]byte)(p) = *(*[5]byte)(unsafe.Pointer(&w))
+	case 6:
+		*(*[6]byte)(p) = *(*[6]byte)(unsafe.Pointer(&w))
+	case 7:
+		*(*[7]byte)(p) = *(*[7]byte)(unsafe.Pointer(&w))
+	case 8:
+		*(*uint64)(p) = *(*uint64)(unsafe.Pointer(&w))
+	}
+}
+
+// emptyInterface is the header for an interface{} value.
+type emptyInterface struct {
+	typ  *rtype
+	word iword
+}
+
+// nonEmptyInterface is the header for a interface value with methods.
+type nonEmptyInterface struct {
+	// see ../runtime/iface.c:/Itab
+	itab *struct {
+		typ *rtype                 // dynamic concrete type
+		fun [100000]unsafe.Pointer // method table
+	}
+	word iword
+}
+
+// mustBe panics if f's kind is not expected.
+// Making this a method on flag instead of on Value
+// (and embedding flag in Value) means that we can write
+// the very clear v.mustBe(Bool) and have it compile into
+// v.flag.mustBe(Bool), which will only bother to copy the
+// single important word for the receiver.
+func (f flag) mustBe(expected Kind) {
+	k := f.kind()
+	if k != expected {
+		panic(&ValueError{methodName(), k})
+	}
+}
+
+// mustBeExported panics if f records that the value was obtained using
+// an unexported field.
+func (f flag) mustBeExported() {
+	if f == 0 {
+		panic(&ValueError{methodName(), 0})
+	}
+	if f&flagRO != 0 {
+		panic("reflect: " + methodName() + " using value obtained using unexported field")
+	}
+}
+
+// mustBeAssignable panics if f records that the value is not assignable,
+// which is to say that either it was obtained using an unexported field
+// or it is not addressable.
+func (f flag) mustBeAssignable() {
+	if f == 0 {
+		panic(&ValueError{methodName(), Invalid})
+	}
+	// Assignable if addressable and not read-only.
+	if f&flagRO != 0 {
+		panic("reflect: " + methodName() + " using value obtained using unexported field")
+	}
+	if f&flagAddr == 0 {
+		panic("reflect: " + methodName() + " using unaddressable value")
+	}
+}
+
+// Addr returns a pointer value representing the address of v.
+// It panics if CanAddr() returns false.
+// Addr is typically used to obtain a pointer to a struct field
+// or slice element in order to call a method that requires a
+// pointer receiver.
+func (v Value) Addr() Value {
+	if v.flag&flagAddr == 0 {
+		panic("reflect.Value.Addr of unaddressable value")
+	}
+	return Value{v.typ.ptrTo(), v.ptr /* 0, */, (v.flag & flagRO) | flag(Ptr)<<flagKindShift}
+}
+
+// Bool returns v's underlying value.
+// It panics if v's kind is not Bool.
+func (v Value) Bool() bool {
+	v.mustBe(Bool)
+	if v.flag&flagIndir != 0 {
+		return *(*bool)(v.ptr)
+	}
+	// return *(*bool)(unsafe.Pointer(&v.scalar))
+	panic("reflect: missing flagIndir")
+}
+
+// Bytes returns v's underlying value.
+// It panics if v's underlying value is not a slice of bytes.
+func (v Value) Bytes() []byte {
+	v.mustBe(Slice)
+	if v.typ.Elem().Kind() != Uint8 {
+		panic("reflect.Value.Bytes of non-byte slice")
+	}
+	// Slice is always bigger than a word; assume flagIndir.
+	return *(*[]byte)(v.ptr)
+}
+
+// runes returns v's underlying value.
+// It panics if v's underlying value is not a slice of runes (int32s).
+func (v Value) runes() []rune {
+	v.mustBe(Slice)
+	if v.typ.Elem().Kind() != Int32 {
+		panic("reflect.Value.Bytes of non-rune slice")
+	}
+	// Slice is always bigger than a word; assume flagIndir.
+	return *(*[]rune)(v.ptr)
+}
+
+// CanAddr returns true if the value's address can be obtained with Addr.
+// Such values are called addressable.  A value is addressable if it is
+// an element of a slice, an element of an addressable array,
+// a field of an addressable struct, or the result of dereferencing a pointer.
+// If CanAddr returns false, calling Addr will panic.
+func (v Value) CanAddr() bool {
+	return v.flag&flagAddr != 0
+}
+
+// CanSet returns true if the value of v can be changed.
+// A Value can be changed only if it is addressable and was not
+// obtained by the use of unexported struct fields.
+// If CanSet returns false, calling Set or any type-specific
+// setter (e.g., SetBool, SetInt64) will panic.
+func (v Value) CanSet() bool {
+	return v.flag&(flagAddr|flagRO) == flagAddr
+}
+
+// Call calls the function v with the input arguments in.
+// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]).
+// Call panics if v's Kind is not Func.
+// It returns the output results as Values.
+// As in Go, each input argument must be assignable to the
+// type of the function's corresponding input parameter.
+// If v is a variadic function, Call creates the variadic slice parameter
+// itself, copying in the corresponding values.
+func (v Value) Call(in []Value) []Value {
+	v.mustBe(Func)
+	v.mustBeExported()
+	return v.call("Call", in)
+}
+
+// CallSlice calls the variadic function v with the input arguments in,
+// assigning the slice in[len(in)-1] to v's final variadic argument.
+// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]...).
+// Call panics if v's Kind is not Func or if v is not variadic.
+// It returns the output results as Values.
+// As in Go, each input argument must be assignable to the
+// type of the function's corresponding input parameter.
+func (v Value) CallSlice(in []Value) []Value {
+	v.mustBe(Func)
+	v.mustBeExported()
+	return v.call("CallSlice", in)
+}
+
+var callGC bool // for testing; see TestCallMethodJump
+
+var makeFuncStubFn = makeFuncStub
+var makeFuncStubCode = **(**uintptr)(unsafe.Pointer(&makeFuncStubFn))
+
+func (v Value) call(op string, in []Value) []Value {
+	// Get function pointer, type.
+	t := v.typ
+	var (
+		fn   unsafe.Pointer
+		rcvr Value
+	)
+	if v.flag&flagMethod != 0 {
+		rcvr = v
+		_, t, fn = methodReceiver(op, v, int(v.flag)>>flagMethodShift)
+	} else if v.flag&flagIndir != 0 {
+		fn = *(*unsafe.Pointer)(v.ptr)
+	} else {
+		fn = v.ptr
+	}
+
+	if fn == nil {
+		panic("reflect.Value.Call: call of nil function")
+	}
+
+	isSlice := op == "CallSlice"
+	n := t.NumIn()
+	if isSlice {
+		if !t.IsVariadic() {
+			panic("reflect: CallSlice of non-variadic function")
+		}
+		if len(in) < n {
+			panic("reflect: CallSlice with too few input arguments")
+		}
+		if len(in) > n {
+			panic("reflect: CallSlice with too many input arguments")
+		}
+	} else {
+		if t.IsVariadic() {
+			n--
+		}
+		if len(in) < n {
+			panic("reflect: Call with too few input arguments")
+		}
+		if !t.IsVariadic() && len(in) > n {
+			panic("reflect: Call with too many input arguments")
+		}
+	}
+	for _, x := range in {
+		if x.Kind() == Invalid {
+			panic("reflect: " + op + " using zero Value argument")
+		}
+	}
+	for i := 0; i < n; i++ {
+		if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) {
+			panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String())
+		}
+	}
+	if !isSlice && t.IsVariadic() {
+		// prepare slice for remaining values
+		m := len(in) - n
+		slice := MakeSlice(t.In(n), m, m)
+		elem := t.In(n).Elem()
+		for i := 0; i < m; i++ {
+			x := in[n+i]
+			if xt := x.Type(); !xt.AssignableTo(elem) {
+				panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + op)
+			}
+			slice.Index(i).Set(x)
+		}
+		origIn := in
+		in = make([]Value, n+1)
+		copy(in[:n], origIn)
+		in[n] = slice
+	}
+
+	nin := len(in)
+	if nin != t.NumIn() {
+		panic("reflect.Value.Call: wrong argument count")
+	}
+	nout := t.NumOut()
+
+	// If target is makeFuncStub, short circuit the unpack onto stack /
+	// pack back into []Value for the args and return values.  Just do the
+	// call directly.
+	// We need to do this here because otherwise we have a situation where
+	// reflect.callXX calls makeFuncStub, neither of which knows the
+	// layout of the args.  That's bad for precise gc & stack copying.
+	x := (*makeFuncImpl)(fn)
+	if x.code == makeFuncStubCode {
+		return x.call(in)
+	}
+
+	if v.flag&flagMethod != 0 {
+		nin++
+	}
+	firstPointer := len(in) > 0 && t.In(0).Kind() != Ptr && v.flag&flagMethodFn != 0
+	params := make([]unsafe.Pointer, nin)
+	off := 0
+	if v.flag&flagMethod != 0 {
+		// Hard-wired first argument.
+		p := new(unsafe.Pointer)
+		if rcvr.typ.Kind() == Interface {
+			*p = unsafe.Pointer((*nonEmptyInterface)(v.ptr).word)
+		} else if rcvr.typ.Kind() == Ptr || rcvr.typ.Kind() == UnsafePointer {
+			*p = rcvr.pointer()
+		} else {
+			*p = rcvr.ptr
+		}
+		params[0] = unsafe.Pointer(p)
+		off = 1
+	}
+	for i, pv := range in {
+		pv.mustBeExported()
+		targ := t.In(i).(*rtype)
+		pv = pv.assignTo("reflect.Value.Call", targ, nil)
+		if pv.flag&flagIndir == 0 {
+			p := new(unsafe.Pointer)
+			*p = pv.ptr
+			params[off] = unsafe.Pointer(p)
+		} else {
+			params[off] = pv.ptr
+		}
+		if i == 0 && firstPointer {
+			p := new(unsafe.Pointer)
+			*p = params[off]
+			params[off] = unsafe.Pointer(p)
+		}
+		off++
+	}
+
+	ret := make([]Value, nout)
+	results := make([]unsafe.Pointer, nout)
+	for i := 0; i < nout; i++ {
+		v := New(t.Out(i))
+		results[i] = unsafe.Pointer(v.Pointer())
+		ret[i] = Indirect(v)
+	}
+
+	var pp *unsafe.Pointer
+	if len(params) > 0 {
+		pp = &params[0]
+	}
+	var pr *unsafe.Pointer
+	if len(results) > 0 {
+		pr = &results[0]
+	}
+
+	call(t, fn, v.flag&flagMethod != 0, firstPointer, pp, pr)
+
+	// For testing; see TestCallMethodJump.
+	if callGC {
+		runtime.GC()
+	}
+
+	return ret
+}
+
+// methodReceiver returns information about the receiver
+// described by v. The Value v may or may not have the
+// flagMethod bit set, so the kind cached in v.flag should
+// not be used.
+// The return value rcvrtype gives the method's actual receiver type.
+// The return value t gives the method type signature (without the receiver).
+// The return value fn is a pointer to the method code.
+func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn unsafe.Pointer) {
+	i := methodIndex
+	if v.typ.Kind() == Interface {
+		tt := (*interfaceType)(unsafe.Pointer(v.typ))
+		if i < 0 || i >= len(tt.methods) {
+			panic("reflect: internal error: invalid method index")
+		}
+		m := &tt.methods[i]
+		if m.pkgPath != nil {
+			panic("reflect: " + op + " of unexported method")
+		}
+		iface := (*nonEmptyInterface)(v.ptr)
+		if iface.itab == nil {
+			panic("reflect: " + op + " of method on nil interface value")
+		}
+		rcvrtype = iface.itab.typ
+		fn = unsafe.Pointer(&iface.itab.fun[i])
+		t = m.typ
+	} else {
+		rcvrtype = v.typ
+		ut := v.typ.uncommon()
+		if ut == nil || i < 0 || i >= len(ut.methods) {
+			panic("reflect: internal error: invalid method index")
+		}
+		m := &ut.methods[i]
+		if m.pkgPath != nil {
+			panic("reflect: " + op + " of unexported method")
+		}
+		fn = unsafe.Pointer(&m.tfn)
+		t = m.mtyp
+	}
+	return
+}
+
+// v is a method receiver.  Store at p the word which is used to
+// encode that receiver at the start of the argument list.
+// Reflect uses the "interface" calling convention for
+// methods, which always uses one word to record the receiver.
+func storeRcvr(v Value, p unsafe.Pointer) {
+	t := v.typ
+	if t.Kind() == Interface {
+		// the interface data word becomes the receiver word
+		iface := (*nonEmptyInterface)(v.ptr)
+		*(*unsafe.Pointer)(p) = unsafe.Pointer(iface.word)
+	} else if v.flag&flagIndir != 0 {
+		if t.size > ptrSize {
+			*(*unsafe.Pointer)(p) = v.ptr
+		} else if t.pointers() {
+			*(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
+		} else {
+			*(*uintptr)(p) = loadScalar(v.ptr, t.size)
+		}
+	} else if t.pointers() {
+		*(*unsafe.Pointer)(p) = v.ptr
+	} else {
+		// *(*uintptr)(p) = v.scalar
+		panic("reflect: missing flagIndir")
+	}
+}
+
+// align returns the result of rounding x up to a multiple of n.
+// n must be a power of two.
+func align(x, n uintptr) uintptr {
+	return (x + n - 1) &^ (n - 1)
+}
+
+// funcName returns the name of f, for use in error messages.
+func funcName(f func([]Value) []Value) string {
+	pc := *(*uintptr)(unsafe.Pointer(&f))
+	rf := runtime.FuncForPC(pc)
+	if rf != nil {
+		return rf.Name()
+	}
+	return "closure"
+}
+
+// Cap returns v's capacity.
+// It panics if v's Kind is not Array, Chan, or Slice.
+func (v Value) Cap() int {
+	k := v.kind()
+	switch k {
+	case Array:
+		return v.typ.Len()
+	case Chan:
+		return int(chancap(v.pointer()))
+	case Slice:
+		// Slice is always bigger than a word; assume flagIndir.
+		return (*sliceHeader)(v.ptr).Cap
+	}
+	panic(&ValueError{"reflect.Value.Cap", k})
+}
+
+// Close closes the channel v.
+// It panics if v's Kind is not Chan.
+func (v Value) Close() {
+	v.mustBe(Chan)
+	v.mustBeExported()
+	chanclose(v.pointer())
+}
+
+// Complex returns v's underlying value, as a complex128.
+// It panics if v's Kind is not Complex64 or Complex128
+func (v Value) Complex() complex128 {
+	k := v.kind()
+	switch k {
+	case Complex64:
+		if v.flag&flagIndir != 0 {
+			return complex128(*(*complex64)(v.ptr))
+		}
+		// return complex128(*(*complex64)(unsafe.Pointer(&v.scalar)))
+		panic("reflect: missing flagIndir")
+	case Complex128:
+		// complex128 is always bigger than a word; assume flagIndir.
+		return *(*complex128)(v.ptr)
+	}
+	panic(&ValueError{"reflect.Value.Complex", k})
+}
+
+// Elem returns the value that the interface v contains
+// or that the pointer v points to.
+// It panics if v's Kind is not Interface or Ptr.
+// It returns the zero Value if v is nil.
+func (v Value) Elem() Value {
+	k := v.kind()
+	switch k {
+	case Interface:
+		var eface interface{}
+		if v.typ.NumMethod() == 0 {
+			eface = *(*interface{})(v.ptr)
+		} else {
+			eface = (interface{})(*(*interface {
+				M()
+			})(v.ptr))
+		}
+		x := unpackEface(eface)
+		x.flag |= v.flag & flagRO
+		return x
+	case Ptr:
+		ptr := v.ptr
+		if v.flag&flagIndir != 0 {
+			ptr = *(*unsafe.Pointer)(ptr)
+		}
+		// The returned value's address is v's value.
+		if ptr == nil {
+			return Value{}
+		}
+		tt := (*ptrType)(unsafe.Pointer(v.typ))
+		typ := tt.elem
+		fl := v.flag&flagRO | flagIndir | flagAddr
+		fl |= flag(typ.Kind() << flagKindShift)
+		return Value{typ, ptr /* 0, */, fl}
+	}
+	panic(&ValueError{"reflect.Value.Elem", k})
+}
+
+// Field returns the i'th field of the struct v.
+// It panics if v's Kind is not Struct or i is out of range.
+func (v Value) Field(i int) Value {
+	v.mustBe(Struct)
+	tt := (*structType)(unsafe.Pointer(v.typ))
+	if i < 0 || i >= len(tt.fields) {
+		panic("reflect: Field index out of range")
+	}
+	field := &tt.fields[i]
+	typ := field.typ
+
+	// Inherit permission bits from v.
+	fl := v.flag & (flagRO | flagIndir | flagAddr)
+	// Using an unexported field forces flagRO.
+	if field.pkgPath != nil {
+		fl |= flagRO
+	}
+	fl |= flag(typ.Kind()) << flagKindShift
+
+	var ptr unsafe.Pointer
+	// var scalar uintptr
+	switch {
+	case fl&flagIndir != 0:
+		// Indirect.  Just bump pointer.
+		ptr = unsafe.Pointer(uintptr(v.ptr) + field.offset)
+	case typ.pointers():
+		if field.offset != 0 {
+			panic("field access of ptr value isn't at offset 0")
+		}
+		ptr = v.ptr
+	case bigEndian:
+		// Must be scalar.  Discard leading bytes.
+		// scalar = v.scalar << (field.offset * 8)
+		panic("reflect: missing flagIndir")
+	default:
+		// Must be scalar.  Discard leading bytes.
+		// scalar = v.scalar >> (field.offset * 8)
+		panic("reflect: missing flagIndir")
+	}
+
+	return Value{typ, ptr /* scalar, */, fl}
+}
+
+// FieldByIndex returns the nested field corresponding to index.
+// It panics if v's Kind is not struct.
+func (v Value) FieldByIndex(index []int) Value {
+	v.mustBe(Struct)
+	for i, x := range index {
+		if i > 0 {
+			if v.Kind() == Ptr && v.typ.Elem().Kind() == Struct {
+				if v.IsNil() {
+					panic("reflect: indirection through nil pointer to embedded struct")
+				}
+				v = v.Elem()
+			}
+		}
+		v = v.Field(x)
+	}
+	return v
+}
+
+// FieldByName returns the struct field with the given name.
+// It returns the zero Value if no field was found.
+// It panics if v's Kind is not struct.
+func (v Value) FieldByName(name string) Value {
+	v.mustBe(Struct)
+	if f, ok := v.typ.FieldByName(name); ok {
+		return v.FieldByIndex(f.Index)
+	}
+	return Value{}
+}
+
+// FieldByNameFunc returns the struct field with a name
+// that satisfies the match function.
+// It panics if v's Kind is not struct.
+// It returns the zero Value if no field was found.
+func (v Value) FieldByNameFunc(match func(string) bool) Value {
+	v.mustBe(Struct)
+	if f, ok := v.typ.FieldByNameFunc(match); ok {
+		return v.FieldByIndex(f.Index)
+	}
+	return Value{}
+}
+
+// Float returns v's underlying value, as a float64.
+// It panics if v's Kind is not Float32 or Float64
+func (v Value) Float() float64 {
+	k := v.kind()
+	switch k {
+	case Float32:
+		if v.flag&flagIndir != 0 {
+			return float64(*(*float32)(v.ptr))
+		}
+		// return float64(*(*float32)(unsafe.Pointer(&v.scalar)))
+		panic("reflect: missing flagIndir")
+	case Float64:
+		if v.flag&flagIndir != 0 {
+			return *(*float64)(v.ptr)
+		}
+		// return *(*float64)(unsafe.Pointer(&v.scalar))
+		panic("reflect: missing flagIndir")
+	}
+	panic(&ValueError{"reflect.Value.Float", k})
+}
+
+var uint8Type = TypeOf(uint8(0)).(*rtype)
+
+// Index returns v's i'th element.
+// It panics if v's Kind is not Array, Slice, or String or i is out of range.
+func (v Value) Index(i int) Value {
+	k := v.kind()
+	switch k {
+	case Array:
+		tt := (*arrayType)(unsafe.Pointer(v.typ))
+		if i < 0 || i > int(tt.len) {
+			panic("reflect: array index out of range")
+		}
+		typ := tt.elem
+		fl := v.flag & (flagRO | flagIndir | flagAddr) // bits same as overall array
+		fl |= flag(typ.Kind()) << flagKindShift
+		offset := uintptr(i) * typ.size
+
+		var val unsafe.Pointer
+		switch {
+		case fl&flagIndir != 0:
+			// Indirect.  Just bump pointer.
+			val = unsafe.Pointer(uintptr(v.ptr) + offset)
+		case typ.pointers():
+			if offset != 0 {
+				panic("can't Index(i) with i!=0 on ptrLike value")
+			}
+			val = v.ptr
+		case bigEndian:
+			// Direct.  Discard leading bytes.
+			// scalar = v.scalar << (offset * 8)
+			panic("reflect: missing flagIndir")
+		default:
+			// Direct.  Discard leading bytes.
+			// scalar = v.scalar >> (offset * 8)
+			panic("reflect: missing flagIndir")
+		}
+		return Value{typ, val /* scalar, */, fl}
+
+	case Slice:
+		// Element flag same as Elem of Ptr.
+		// Addressable, indirect, possibly read-only.
+		fl := flagAddr | flagIndir | v.flag&flagRO
+		s := (*sliceHeader)(v.ptr)
+		if i < 0 || i >= s.Len {
+			panic("reflect: slice index out of range")
+		}
+		tt := (*sliceType)(unsafe.Pointer(v.typ))
+		typ := tt.elem
+		fl |= flag(typ.Kind()) << flagKindShift
+		val := unsafe.Pointer(uintptr(s.Data) + uintptr(i)*typ.size)
+		return Value{typ, val /* 0, */, fl}
+
+	case String:
+		fl := v.flag&flagRO | flag(Uint8<<flagKindShift) | flagIndir
+		s := (*StringHeader)(v.ptr)
+		if i < 0 || i >= s.Len {
+			panic("reflect: string index out of range")
+		}
+		b := uintptr(0)
+		*(*byte)(unsafe.Pointer(&b)) = *(*byte)(unsafe.Pointer(uintptr(s.Data) + uintptr(i)))
+		return Value{uint8Type, unsafe.Pointer(&b) /* 0, */, fl | flagIndir}
+	}
+	panic(&ValueError{"reflect.Value.Index", k})
+}
+
+// Int returns v's underlying value, as an int64.
+// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64.
+func (v Value) Int() int64 {
+	k := v.kind()
+	var p unsafe.Pointer
+	if v.flag&flagIndir != 0 {
+		p = v.ptr
+	} else {
+		// The escape analysis is good enough that &v.scalar
+		// does not trigger a heap allocation.
+		// p = unsafe.Pointer(&v.scalar)
+		switch k {
+		case Int, Int8, Int16, Int32, Int64:
+			panic("reflect: missing flagIndir")
+		}
+	}
+	switch k {
+	case Int:
+		return int64(*(*int)(p))
+	case Int8:
+		return int64(*(*int8)(p))
+	case Int16:
+		return int64(*(*int16)(p))
+	case Int32:
+		return int64(*(*int32)(p))
+	case Int64:
+		return int64(*(*int64)(p))
+	}
+	panic(&ValueError{"reflect.Value.Int", k})
+}
+
+// CanInterface returns true if Interface can be used without panicking.
+func (v Value) CanInterface() bool {
+	if v.flag == 0 {
+		panic(&ValueError{"reflect.Value.CanInterface", Invalid})
+	}
+	return v.flag&flagRO == 0
+}
+
+// Interface returns v's current value as an interface{}.
+// It is equivalent to:
+//	var i interface{} = (v's underlying value)
+// It panics if the Value was obtained by accessing
+// unexported struct fields.
+func (v Value) Interface() (i interface{}) {
+	return valueInterface(v, true)
+}
+
+func valueInterface(v Value, safe bool) interface{} {
+	if v.flag == 0 {
+		panic(&ValueError{"reflect.Value.Interface", 0})
+	}
+	if safe && v.flag&flagRO != 0 {
+		// Do not allow access to unexported values via Interface,
+		// because they might be pointers that should not be
+		// writable or methods or function that should not be callable.
+		panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
+	}
+	if v.flag&flagMethod != 0 {
+		v = makeMethodValue("Interface", v)
+	}
+
+	if v.flag&flagMethodFn != 0 {
+		if v.typ.Kind() != Func {
+			panic("reflect: MethodFn of non-Func")
+		}
+		ft := (*funcType)(unsafe.Pointer(v.typ))
+		if ft.in[0].Kind() != Ptr {
+			v = makeValueMethod(v)
+		}
+	}
+
+	if v.kind() == Interface {
+		// Special case: return the element inside the interface.
+		// Empty interface has one layout, all interfaces with
+		// methods have a second layout.
+		if v.NumMethod() == 0 {
+			return *(*interface{})(v.ptr)
+		}
+		return *(*interface {
+			M()
+		})(v.ptr)
+	}
+
+	// TODO: pass safe to packEface so we don't need to copy if safe==true?
+	return packEface(v)
+}
+
+// InterfaceData returns the interface v's value as a uintptr pair.
+// It panics if v's Kind is not Interface.
+func (v Value) InterfaceData() [2]uintptr {
+	// TODO: deprecate this
+	v.mustBe(Interface)
+	// We treat this as a read operation, so we allow
+	// it even for unexported data, because the caller
+	// has to import "unsafe" to turn it into something
+	// that can be abused.
+	// Interface value is always bigger than a word; assume flagIndir.
+	return *(*[2]uintptr)(v.ptr)
+}
+
+// IsNil reports whether its argument v is nil. The argument must be
+// a chan, func, interface, map, pointer, or slice value; if it is
+// not, IsNil panics. Note that IsNil is not always equivalent to a
+// regular comparison with nil in Go. For example, if v was created
+// by calling ValueOf with an uninitialized interface variable i,
+// i==nil will be true but v.IsNil will panic as v will be the zero
+// Value.
+func (v Value) IsNil() bool {
+	k := v.kind()
+	switch k {
+	case Chan, Func, Map, Ptr:
+		if v.flag&flagMethod != 0 {
+			return false
+		}
+		ptr := v.ptr
+		if v.flag&flagIndir != 0 {
+			ptr = *(*unsafe.Pointer)(ptr)
+		}
+		return ptr == nil
+	case Interface, Slice:
+		// Both interface and slice are nil if first word is 0.
+		// Both are always bigger than a word; assume flagIndir.
+		return *(*unsafe.Pointer)(v.ptr) == nil
+	}
+	panic(&ValueError{"reflect.Value.IsNil", k})
+}
+
+// IsValid returns true if v represents a value.
+// It returns false if v is the zero Value.
+// If IsValid returns false, all other methods except String panic.
+// Most functions and methods never return an invalid value.
+// If one does, its documentation states the conditions explicitly.
+func (v Value) IsValid() bool {
+	return v.flag != 0
+}
+
+// Kind returns v's Kind.
+// If v is the zero Value (IsValid returns false), Kind returns Invalid.
+func (v Value) Kind() Kind {
+	return v.kind()
+}
+
+// Len returns v's length.
+// It panics if v's Kind is not Array, Chan, Map, Slice, or String.
+func (v Value) Len() int {
+	k := v.kind()
+	switch k {
+	case Array:
+		tt := (*arrayType)(unsafe.Pointer(v.typ))
+		return int(tt.len)
+	case Chan:
+		return chanlen(v.pointer())
+	case Map:
+		return maplen(v.pointer())
+	case Slice:
+		// Slice is bigger than a word; assume flagIndir.
+		return (*sliceHeader)(v.ptr).Len
+	case String:
+		// String is bigger than a word; assume flagIndir.
+		return (*stringHeader)(v.ptr).Len
+	}
+	panic(&ValueError{"reflect.Value.Len", k})
+}
+
+// MapIndex returns the value associated with key in the map v.
+// It panics if v's Kind is not Map.
+// It returns the zero Value if key is not found in the map or if v represents a nil map.
+// As in Go, the key's value must be assignable to the map's key type.
+func (v Value) MapIndex(key Value) Value {
+	v.mustBe(Map)
+	tt := (*mapType)(unsafe.Pointer(v.typ))
+
+	// Do not require key to be exported, so that DeepEqual
+	// and other programs can use all the keys returned by
+	// MapKeys as arguments to MapIndex.  If either the map
+	// or the key is unexported, though, the result will be
+	// considered unexported.  This is consistent with the
+	// behavior for structs, which allow read but not write
+	// of unexported fields.
+	key = key.assignTo("reflect.Value.MapIndex", tt.key, nil)
+
+	var k unsafe.Pointer
+	if key.flag&flagIndir != 0 {
+		k = key.ptr
+	} else if key.typ.pointers() {
+		k = unsafe.Pointer(&key.ptr)
+	} else {
+		// k = unsafe.Pointer(&key.scalar)
+		panic("reflect: missing flagIndir")
+	}
+	e := mapaccess(v.typ, v.pointer(), k)
+	if e == nil {
+		return Value{}
+	}
+	typ := tt.elem
+	fl := (v.flag | key.flag) & flagRO
+	fl |= flag(typ.Kind()) << flagKindShift
+	if typ.Kind() != Ptr && typ.Kind() != UnsafePointer {
+		// Copy result so future changes to the map
+		// won't change the underlying value.
+		c := unsafe_New(typ)
+		memmove(c, e, typ.size)
+		return Value{typ, c /* 0, */, fl | flagIndir}
+	} else if typ.pointers() {
+		return Value{typ, *(*unsafe.Pointer)(e) /* 0, */, fl}
+	} else {
+		panic("reflect: can't happen")
+	}
+}
+
+// MapKeys returns a slice containing all the keys present in the map,
+// in unspecified order.
+// It panics if v's Kind is not Map.
+// It returns an empty slice if v represents a nil map.
+func (v Value) MapKeys() []Value {
+	v.mustBe(Map)
+	tt := (*mapType)(unsafe.Pointer(v.typ))
+	keyType := tt.key
+
+	fl := v.flag&flagRO | flag(keyType.Kind())<<flagKindShift
+	if keyType.Kind() != Ptr && keyType.Kind() != UnsafePointer {
+		fl |= flagIndir
+	}
+
+	m := v.pointer()
+	mlen := int(0)
+	if m != nil {
+		mlen = maplen(m)
+	}
+	it := mapiterinit(v.typ, m)
+	a := make([]Value, mlen)
+	var i int
+	for i = 0; i < len(a); i++ {
+		key := mapiterkey(it)
+		if key == nil {
+			// Someone deleted an entry from the map since we
+			// called maplen above.  It's a data race, but nothing
+			// we can do about it.
+			break
+		}
+		if keyType.Kind() != Ptr && keyType.Kind() != UnsafePointer {
+			// Copy result so future changes to the map
+			// won't change the underlying value.
+			c := unsafe_New(keyType)
+			memmove(c, key, keyType.size)
+			a[i] = Value{keyType, c /* 0, */, fl | flagIndir}
+		} else if keyType.pointers() {
+			a[i] = Value{keyType, *(*unsafe.Pointer)(key) /* 0, */, fl}
+		} else {
+			panic("reflect: can't happen")
+		}
+		mapiternext(it)
+	}
+	return a[:i]
+}
+
+// Method returns a function value corresponding to v's i'th method.
+// The arguments to a Call on the returned function should not include
+// a receiver; the returned function will always use v as the receiver.
+// Method panics if i is out of range or if v is a nil interface value.
+func (v Value) Method(i int) Value {
+	if v.typ == nil {
+		panic(&ValueError{"reflect.Value.Method", Invalid})
+	}
+	if v.flag&flagMethod != 0 || i < 0 || i >= v.typ.NumMethod() {
+		panic("reflect: Method index out of range")
+	}
+	if v.typ.Kind() == Interface && v.IsNil() {
+		panic("reflect: Method on nil interface value")
+	}
+	fl := v.flag & (flagRO | flagIndir)
+	fl |= flag(Func) << flagKindShift
+	fl |= flag(i)<<flagMethodShift | flagMethod
+	return Value{v.typ, v.ptr /* v.scalar, */, fl}
+}
+
+// NumMethod returns the number of methods in the value's method set.
+func (v Value) NumMethod() int {
+	if v.typ == nil {
+		panic(&ValueError{"reflect.Value.NumMethod", Invalid})
+	}
+	if v.flag&flagMethod != 0 {
+		return 0
+	}
+	return v.typ.NumMethod()
+}
+
+// MethodByName returns a function value corresponding to the method
+// of v with the given name.
+// The arguments to a Call on the returned function should not include
+// a receiver; the returned function will always use v as the receiver.
+// It returns the zero Value if no method was found.
+func (v Value) MethodByName(name string) Value {
+	if v.typ == nil {
+		panic(&ValueError{"reflect.Value.MethodByName", Invalid})
+	}
+	if v.flag&flagMethod != 0 {
+		return Value{}
+	}
+	m, ok := v.typ.MethodByName(name)
+	if !ok {
+		return Value{}
+	}
+	return v.Method(m.Index)
+}
+
+// NumField returns the number of fields in the struct v.
+// It panics if v's Kind is not Struct.
+func (v Value) NumField() int {
+	v.mustBe(Struct)
+	tt := (*structType)(unsafe.Pointer(v.typ))
+	return len(tt.fields)
+}
+
+// OverflowComplex returns true if the complex128 x cannot be represented by v's type.
+// It panics if v's Kind is not Complex64 or Complex128.
+func (v Value) OverflowComplex(x complex128) bool {
+	k := v.kind()
+	switch k {
+	case Complex64:
+		return overflowFloat32(real(x)) || overflowFloat32(imag(x))
+	case Complex128:
+		return false
+	}
+	panic(&ValueError{"reflect.Value.OverflowComplex", k})
+}
+
+// OverflowFloat returns true if the float64 x cannot be represented by v's type.
+// It panics if v's Kind is not Float32 or Float64.
+func (v Value) OverflowFloat(x float64) bool {
+	k := v.kind()
+	switch k {
+	case Float32:
+		return overflowFloat32(x)
+	case Float64:
+		return false
+	}
+	panic(&ValueError{"reflect.Value.OverflowFloat", k})
+}
+
+func overflowFloat32(x float64) bool {
+	if x < 0 {
+		x = -x
+	}
+	return math.MaxFloat32 < x && x <= math.MaxFloat64
+}
+
+// OverflowInt returns true if the int64 x cannot be represented by v's type.
+// It panics if v's Kind is not Int, Int8, int16, Int32, or Int64.
+func (v Value) OverflowInt(x int64) bool {
+	k := v.kind()
+	switch k {
+	case Int, Int8, Int16, Int32, Int64:
+		bitSize := v.typ.size * 8
+		trunc := (x << (64 - bitSize)) >> (64 - bitSize)
+		return x != trunc
+	}
+	panic(&ValueError{"reflect.Value.OverflowInt", k})
+}
+
+// OverflowUint returns true if the uint64 x cannot be represented by v's type.
+// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
+func (v Value) OverflowUint(x uint64) bool {
+	k := v.kind()
+	switch k {
+	case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
+		bitSize := v.typ.size * 8
+		trunc := (x << (64 - bitSize)) >> (64 - bitSize)
+		return x != trunc
+	}
+	panic(&ValueError{"reflect.Value.OverflowUint", k})
+}
+
+// Pointer returns v's value as a uintptr.
+// It returns uintptr instead of unsafe.Pointer so that
+// code using reflect cannot obtain unsafe.Pointers
+// without importing the unsafe package explicitly.
+// It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer.
+//
+// If v's Kind is Func, the returned pointer is an underlying
+// code pointer, but not necessarily enough to identify a
+// single function uniquely. The only guarantee is that the
+// result is zero if and only if v is a nil func Value.
+//
+// If v's Kind is Slice, the returned pointer is to the first
+// element of the slice.  If the slice is nil the returned value
+// is 0.  If the slice is empty but non-nil the return value is non-zero.
+func (v Value) Pointer() uintptr {
+	// TODO: deprecate
+	k := v.kind()
+	switch k {
+	case Chan, Map, Ptr, UnsafePointer:
+		return uintptr(v.pointer())
+	case Func:
+		if v.flag&flagMethod != 0 {
+			// As the doc comment says, the returned pointer is an
+			// underlying code pointer but not necessarily enough to
+			// identify a single function uniquely. All method expressions
+			// created via reflect have the same underlying code pointer,
+			// so their Pointers are equal. The function used here must
+			// match the one used in makeMethodValue.
+			f := makeFuncStub
+			return **(**uintptr)(unsafe.Pointer(&f))
+		}
+		p := v.pointer()
+		// Non-nil func value points at data block.
+		// First word of data block is actual code.
+		if p != nil {
+			p = *(*unsafe.Pointer)(p)
+		}
+		return uintptr(p)
+
+	case Slice:
+		return (*SliceHeader)(v.ptr).Data
+	}
+	panic(&ValueError{"reflect.Value.Pointer", k})
+}
+
+// Recv receives and returns a value from the channel v.
+// It panics if v's Kind is not Chan.
+// The receive blocks until a value is ready.
+// The boolean value ok is true if the value x corresponds to a send
+// on the channel, false if it is a zero value received because the channel is closed.
+func (v Value) Recv() (x Value, ok bool) {
+	v.mustBe(Chan)
+	v.mustBeExported()
+	return v.recv(false)
+}
+
+// internal recv, possibly non-blocking (nb).
+// v is known to be a channel.
+func (v Value) recv(nb bool) (val Value, ok bool) {
+	tt := (*chanType)(unsafe.Pointer(v.typ))
+	if ChanDir(tt.dir)&RecvDir == 0 {
+		panic("reflect: recv on send-only channel")
+	}
+	t := tt.elem
+	val = Value{t, nil /* 0, */, flag(t.Kind()) << flagKindShift}
+	var p unsafe.Pointer
+	if t.Kind() != Ptr && t.Kind() != UnsafePointer {
+		p = unsafe_New(t)
+		val.ptr = p
+		val.flag |= flagIndir
+	} else {
+		p = unsafe.Pointer(&val.ptr)
+	}
+	selected, ok := chanrecv(v.typ, v.pointer(), nb, p)
+	if !selected {
+		val = Value{}
+	}
+	return
+}
+
+// Send sends x on the channel v.
+// It panics if v's kind is not Chan or if x's type is not the same type as v's element type.
+// As in Go, x's value must be assignable to the channel's element type.
+func (v Value) Send(x Value) {
+	v.mustBe(Chan)
+	v.mustBeExported()
+	v.send(x, false)
+}
+
+// internal send, possibly non-blocking.
+// v is known to be a channel.
+func (v Value) send(x Value, nb bool) (selected bool) {
+	tt := (*chanType)(unsafe.Pointer(v.typ))
+	if ChanDir(tt.dir)&SendDir == 0 {
+		panic("reflect: send on recv-only channel")
+	}
+	x.mustBeExported()
+	x = x.assignTo("reflect.Value.Send", tt.elem, nil)
+	var p unsafe.Pointer
+	if x.flag&flagIndir != 0 {
+		p = x.ptr
+	} else if x.typ.pointers() {
+		p = unsafe.Pointer(&x.ptr)
+	} else {
+		// p = unsafe.Pointer(&x.scalar)
+		panic("reflect: missing flagIndir")
+	}
+	return chansend(v.typ, v.pointer(), p, nb)
+}
+
+// Set assigns x to the value v.
+// It panics if CanSet returns false.
+// As in Go, x's value must be assignable to v's type.
+func (v Value) Set(x Value) {
+	v.mustBeAssignable()
+	x.mustBeExported() // do not let unexported x leak
+	var target unsafe.Pointer
+	if v.kind() == Interface {
+		target = v.ptr
+	}
+	x = x.assignTo("reflect.Set", v.typ, target)
+	if x.flag&flagIndir != 0 {
+		memmove(v.ptr, x.ptr, v.typ.size)
+	} else if x.typ.pointers() {
+		*(*unsafe.Pointer)(v.ptr) = x.ptr
+	} else {
+		// memmove(v.ptr, unsafe.Pointer(&x.scalar), v.typ.size)
+		panic("reflect: missing flagIndir")
+	}
+}
+
+// SetBool sets v's underlying value.
+// It panics if v's Kind is not Bool or if CanSet() is false.
+func (v Value) SetBool(x bool) {
+	v.mustBeAssignable()
+	v.mustBe(Bool)
+	*(*bool)(v.ptr) = x
+}
+
+// SetBytes sets v's underlying value.
+// It panics if v's underlying value is not a slice of bytes.
+func (v Value) SetBytes(x []byte) {
+	v.mustBeAssignable()
+	v.mustBe(Slice)
+	if v.typ.Elem().Kind() != Uint8 {
+		panic("reflect.Value.SetBytes of non-byte slice")
+	}
+	*(*[]byte)(v.ptr) = x
+}
+
+// setRunes sets v's underlying value.
+// It panics if v's underlying value is not a slice of runes (int32s).
+func (v Value) setRunes(x []rune) {
+	v.mustBeAssignable()
+	v.mustBe(Slice)
+	if v.typ.Elem().Kind() != Int32 {
+		panic("reflect.Value.setRunes of non-rune slice")
+	}
+	*(*[]rune)(v.ptr) = x
+}
+
+// SetComplex sets v's underlying value to x.
+// It panics if v's Kind is not Complex64 or Complex128, or if CanSet() is false.
+func (v Value) SetComplex(x complex128) {
+	v.mustBeAssignable()
+	switch k := v.kind(); k {
+	default:
+		panic(&ValueError{"reflect.Value.SetComplex", k})
+	case Complex64:
+		*(*complex64)(v.ptr) = complex64(x)
+	case Complex128:
+		*(*complex128)(v.ptr) = x
+	}
+}
+
+// SetFloat sets v's underlying value to x.
+// It panics if v's Kind is not Float32 or Float64, or if CanSet() is false.
+func (v Value) SetFloat(x float64) {
+	v.mustBeAssignable()
+	switch k := v.kind(); k {
+	default:
+		panic(&ValueError{"reflect.Value.SetFloat", k})
+	case Float32:
+		*(*float32)(v.ptr) = float32(x)
+	case Float64:
+		*(*float64)(v.ptr) = x
+	}
+}
+
+// SetInt sets v's underlying value to x.
+// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64, or if CanSet() is false.
+func (v Value) SetInt(x int64) {
+	v.mustBeAssignable()
+	switch k := v.kind(); k {
+	default:
+		panic(&ValueError{"reflect.Value.SetInt", k})
+	case Int:
+		*(*int)(v.ptr) = int(x)
+	case Int8:
+		*(*int8)(v.ptr) = int8(x)
+	case Int16:
+		*(*int16)(v.ptr) = int16(x)
+	case Int32:
+		*(*int32)(v.ptr) = int32(x)
+	case Int64:
+		*(*int64)(v.ptr) = x
+	}
+}
+
+// SetLen sets v's length to n.
+// It panics if v's Kind is not Slice or if n is negative or
+// greater than the capacity of the slice.
+func (v Value) SetLen(n int) {
+	v.mustBeAssignable()
+	v.mustBe(Slice)
+	s := (*sliceHeader)(v.ptr)
+	if n < 0 || n > int(s.Cap) {
+		panic("reflect: slice length out of range in SetLen")
+	}
+	s.Len = n
+}
+
+// SetCap sets v's capacity to n.
+// It panics if v's Kind is not Slice or if n is smaller than the length or
+// greater than the capacity of the slice.
+func (v Value) SetCap(n int) {
+	v.mustBeAssignable()
+	v.mustBe(Slice)
+	s := (*sliceHeader)(v.ptr)
+	if n < int(s.Len) || n > int(s.Cap) {
+		panic("reflect: slice capacity out of range in SetCap")
+	}
+	s.Cap = n
+}
+
+// SetMapIndex sets the value associated with key in the map v to val.
+// It panics if v's Kind is not Map.
+// If val is the zero Value, SetMapIndex deletes the key from the map.
+// Otherwise if v holds a nil map, SetMapIndex will panic.
+// As in Go, key's value must be assignable to the map's key type,
+// and val's value must be assignable to the map's value type.
+func (v Value) SetMapIndex(key, val Value) {
+	v.mustBe(Map)
+	v.mustBeExported()
+	key.mustBeExported()
+	tt := (*mapType)(unsafe.Pointer(v.typ))
+	key = key.assignTo("reflect.Value.SetMapIndex", tt.key, nil)
+	var k unsafe.Pointer
+	if key.flag&flagIndir != 0 {
+		k = key.ptr
+	} else if key.typ.pointers() {
+		k = unsafe.Pointer(&key.ptr)
+	} else {
+		// k = unsafe.Pointer(&key.scalar)
+		panic("reflect: missing flagIndir")
+	}
+	if val.typ == nil {
+		mapdelete(v.typ, v.pointer(), k)
+		return
+	}
+	val.mustBeExported()
+	val = val.assignTo("reflect.Value.SetMapIndex", tt.elem, nil)
+	var e unsafe.Pointer
+	if val.flag&flagIndir != 0 {
+		e = val.ptr
+	} else if val.typ.pointers() {
+		e = unsafe.Pointer(&val.ptr)
+	} else {
+		// e = unsafe.Pointer(&val.scalar)
+		panic("reflect: missing flagIndir")
+	}
+	mapassign(v.typ, v.pointer(), k, e)
+}
+
+// SetUint sets v's underlying value to x.
+// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64, or if CanSet() is false.
+func (v Value) SetUint(x uint64) {
+	v.mustBeAssignable()
+	switch k := v.kind(); k {
+	default:
+		panic(&ValueError{"reflect.Value.SetUint", k})
+	case Uint:
+		*(*uint)(v.ptr) = uint(x)
+	case Uint8:
+		*(*uint8)(v.ptr) = uint8(x)
+	case Uint16:
+		*(*uint16)(v.ptr) = uint16(x)
+	case Uint32:
+		*(*uint32)(v.ptr) = uint32(x)
+	case Uint64:
+		*(*uint64)(v.ptr) = x
+	case Uintptr:
+		*(*uintptr)(v.ptr) = uintptr(x)
+	}
+}
+
+// SetPointer sets the unsafe.Pointer value v to x.
+// It panics if v's Kind is not UnsafePointer.
+func (v Value) SetPointer(x unsafe.Pointer) {
+	v.mustBeAssignable()
+	v.mustBe(UnsafePointer)
+	*(*unsafe.Pointer)(v.ptr) = x
+}
+
+// SetString sets v's underlying value to x.
+// It panics if v's Kind is not String or if CanSet() is false.
+func (v Value) SetString(x string) {
+	v.mustBeAssignable()
+	v.mustBe(String)
+	*(*string)(v.ptr) = x
+}
+
+// Slice returns v[i:j].
+// It panics if v's Kind is not Array, Slice or String, or if v is an unaddressable array,
+// or if the indexes are out of bounds.
+func (v Value) Slice(i, j int) Value {
+	var (
+		cap  int
+		typ  *sliceType
+		base unsafe.Pointer
+	)
+	switch kind := v.kind(); kind {
+	default:
+		panic(&ValueError{"reflect.Value.Slice", kind})
+
+	case Array:
+		if v.flag&flagAddr == 0 {
+			panic("reflect.Value.Slice: slice of unaddressable array")
+		}
+		tt := (*arrayType)(unsafe.Pointer(v.typ))
+		cap = int(tt.len)
+		typ = (*sliceType)(unsafe.Pointer(tt.slice))
+		base = v.ptr
+
+	case Slice:
+		typ = (*sliceType)(unsafe.Pointer(v.typ))
+		s := (*sliceHeader)(v.ptr)
+		base = unsafe.Pointer(s.Data)
+		cap = s.Cap
+
+	case String:
+		s := (*stringHeader)(v.ptr)
+		if i < 0 || j < i || j > s.Len {
+			panic("reflect.Value.Slice: string slice index out of bounds")
+		}
+		t := stringHeader{unsafe.Pointer(uintptr(s.Data) + uintptr(i)), j - i}
+		return Value{v.typ, unsafe.Pointer(&t) /* 0, */, v.flag}
+	}
+
+	if i < 0 || j < i || j > cap {
+		panic("reflect.Value.Slice: slice index out of bounds")
+	}
+
+	// Declare slice so that gc can see the base pointer in it.
+	var x []unsafe.Pointer
+
+	// Reinterpret as *sliceHeader to edit.
+	s := (*sliceHeader)(unsafe.Pointer(&x))
+	s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
+	s.Len = j - i
+	s.Cap = cap - i
+
+	fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
+	return Value{typ.common(), unsafe.Pointer(&x) /* 0, */, fl}
+}
+
+// Slice3 is the 3-index form of the slice operation: it returns v[i:j:k].
+// It panics if v's Kind is not Array or Slice, or if v is an unaddressable array,
+// or if the indexes are out of bounds.
+func (v Value) Slice3(i, j, k int) Value {
+	var (
+		cap  int
+		typ  *sliceType
+		base unsafe.Pointer
+	)
+	switch kind := v.kind(); kind {
+	default:
+		panic(&ValueError{"reflect.Value.Slice3", kind})
+
+	case Array:
+		if v.flag&flagAddr == 0 {
+			panic("reflect.Value.Slice3: slice of unaddressable array")
+		}
+		tt := (*arrayType)(unsafe.Pointer(v.typ))
+		cap = int(tt.len)
+		typ = (*sliceType)(unsafe.Pointer(tt.slice))
+		base = v.ptr
+
+	case Slice:
+		typ = (*sliceType)(unsafe.Pointer(v.typ))
+		s := (*sliceHeader)(v.ptr)
+		base = s.Data
+		cap = s.Cap
+	}
+
+	if i < 0 || j < i || k < j || k > cap {
+		panic("reflect.Value.Slice3: slice index out of bounds")
+	}
+
+	// Declare slice so that the garbage collector
+	// can see the base pointer in it.
+	var x []unsafe.Pointer
+
+	// Reinterpret as *sliceHeader to edit.
+	s := (*sliceHeader)(unsafe.Pointer(&x))
+	s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
+	s.Len = j - i
+	s.Cap = k - i
+
+	fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
+	return Value{typ.common(), unsafe.Pointer(&x) /* 0, */, fl}
+}
+
+// String returns the string v's underlying value, as a string.
+// String is a special case because of Go's String method convention.
+// Unlike the other getters, it does not panic if v's Kind is not String.
+// Instead, it returns a string of the form "<T value>" where T is v's type.
+func (v Value) String() string {
+	switch k := v.kind(); k {
+	case Invalid:
+		return "<invalid Value>"
+	case String:
+		return *(*string)(v.ptr)
+	}
+	// If you call String on a reflect.Value of other type, it's better to
+	// print something than to panic. Useful in debugging.
+	return "<" + v.typ.String() + " Value>"
+}
+
+// TryRecv attempts to receive a value from the channel v but will not block.
+// It panics if v's Kind is not Chan.
+// If the receive delivers a value, x is the transferred value and ok is true.
+// If the receive cannot finish without blocking, x is the zero Value and ok is false.
+// If the channel is closed, x is the zero value for the channel's element type and ok is false.
+func (v Value) TryRecv() (x Value, ok bool) {
+	v.mustBe(Chan)
+	v.mustBeExported()
+	return v.recv(true)
+}
+
+// TrySend attempts to send x on the channel v but will not block.
+// It panics if v's Kind is not Chan.
+// It returns true if the value was sent, false otherwise.
+// As in Go, x's value must be assignable to the channel's element type.
+func (v Value) TrySend(x Value) bool {
+	v.mustBe(Chan)
+	v.mustBeExported()
+	return v.send(x, true)
+}
+
+// Type returns v's type.
+func (v Value) Type() Type {
+	f := v.flag
+	if f == 0 {
+		panic(&ValueError{"reflect.Value.Type", Invalid})
+	}
+	if f&flagMethod == 0 {
+		// Easy case
+		return toType(v.typ)
+	}
+
+	// Method value.
+	// v.typ describes the receiver, not the method type.
+	i := int(v.flag) >> flagMethodShift
+	if v.typ.Kind() == Interface {
+		// Method on interface.
+		tt := (*interfaceType)(unsafe.Pointer(v.typ))
+		if i < 0 || i >= len(tt.methods) {
+			panic("reflect: internal error: invalid method index")
+		}
+		m := &tt.methods[i]
+		return toType(m.typ)
+	}
+	// Method on concrete type.
+	ut := v.typ.uncommon()
+	if ut == nil || i < 0 || i >= len(ut.methods) {
+		panic("reflect: internal error: invalid method index")
+	}
+	m := &ut.methods[i]
+	return toType(m.mtyp)
+}
+
+// Uint returns v's underlying value, as a uint64.
+// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
+func (v Value) Uint() uint64 {
+	k := v.kind()
+	var p unsafe.Pointer
+	if v.flag&flagIndir != 0 {
+		p = v.ptr
+	} else {
+		// The escape analysis is good enough that &v.scalar
+		// does not trigger a heap allocation.
+		// p = unsafe.Pointer(&v.scalar)
+		switch k {
+		case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+			panic("reflect: missing flagIndir")
+		}
+	}
+	switch k {
+	case Uint:
+		return uint64(*(*uint)(p))
+	case Uint8:
+		return uint64(*(*uint8)(p))
+	case Uint16:
+		return uint64(*(*uint16)(p))
+	case Uint32:
+		return uint64(*(*uint32)(p))
+	case Uint64:
+		return uint64(*(*uint64)(p))
+	case Uintptr:
+		return uint64(*(*uintptr)(p))
+	}
+	panic(&ValueError{"reflect.Value.Uint", k})
+}
+
+// UnsafeAddr returns a pointer to v's data.
+// It is for advanced clients that also import the "unsafe" package.
+// It panics if v is not addressable.
+func (v Value) UnsafeAddr() uintptr {
+	// TODO: deprecate
+	if v.typ == nil {
+		panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid})
+	}
+	if v.flag&flagAddr == 0 {
+		panic("reflect.Value.UnsafeAddr of unaddressable value")
+	}
+	return uintptr(v.ptr)
+}
+
+// StringHeader is the runtime representation of a string.
+// It cannot be used safely or portably and its representation may
+// change in a later release.
+// Moreover, the Data field is not sufficient to guarantee the data
+// it references will not be garbage collected, so programs must keep
+// a separate, correctly typed pointer to the underlying data.
+type StringHeader struct {
+	Data uintptr
+	Len  int
+}
+
+// stringHeader is a safe version of StringHeader used within this package.
+type stringHeader struct {
+	Data unsafe.Pointer
+	Len  int
+}
+
+// SliceHeader is the runtime representation of a slice.
+// It cannot be used safely or portably and its representation may
+// change in a later release.
+// Moreover, the Data field is not sufficient to guarantee the data
+// it references will not be garbage collected, so programs must keep
+// a separate, correctly typed pointer to the underlying data.
+type SliceHeader struct {
+	Data uintptr
+	Len  int
+	Cap  int
+}
+
+// sliceHeader is a safe version of SliceHeader used within this package.
+type sliceHeader struct {
+	Data unsafe.Pointer
+	Len  int
+	Cap  int
+}
+
+func typesMustMatch(what string, t1, t2 Type) {
+	if t1 != t2 {
+		panic(what + ": " + t1.String() + " != " + t2.String())
+	}
+}
+
+// grow grows the slice s so that it can hold extra more values, allocating
+// more capacity if needed. It also returns the old and new slice lengths.
+func grow(s Value, extra int) (Value, int, int) {
+	i0 := s.Len()
+	i1 := i0 + extra
+	if i1 < i0 {
+		panic("reflect.Append: slice overflow")
+	}
+	m := s.Cap()
+	if i1 <= m {
+		return s.Slice(0, i1), i0, i1
+	}
+	if m == 0 {
+		m = extra
+	} else {
+		for m < i1 {
+			if i0 < 1024 {
+				m += m
+			} else {
+				m += m / 4
+			}
+		}
+	}
+	t := MakeSlice(s.Type(), i1, m)
+	Copy(t, s)
+	return t, i0, i1
+}
+
+// Append appends the values x to a slice s and returns the resulting slice.
+// As in Go, each x's value must be assignable to the slice's element type.
+func Append(s Value, x ...Value) Value {
+	s.mustBe(Slice)
+	s, i0, i1 := grow(s, len(x))
+	for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
+		s.Index(i).Set(x[j])
+	}
+	return s
+}
+
+// AppendSlice appends a slice t to a slice s and returns the resulting slice.
+// The slices s and t must have the same element type.
+func AppendSlice(s, t Value) Value {
+	s.mustBe(Slice)
+	t.mustBe(Slice)
+	typesMustMatch("reflect.AppendSlice", s.Type().Elem(), t.Type().Elem())
+	s, i0, i1 := grow(s, t.Len())
+	Copy(s.Slice(i0, i1), t)
+	return s
+}
+
+// Copy copies the contents of src into dst until either
+// dst has been filled or src has been exhausted.
+// It returns the number of elements copied.
+// Dst and src each must have kind Slice or Array, and
+// dst and src must have the same element type.
+func Copy(dst, src Value) int {
+	dk := dst.kind()
+	if dk != Array && dk != Slice {
+		panic(&ValueError{"reflect.Copy", dk})
+	}
+	if dk == Array {
+		dst.mustBeAssignable()
+	}
+	dst.mustBeExported()
+
+	sk := src.kind()
+	if sk != Array && sk != Slice {
+		panic(&ValueError{"reflect.Copy", sk})
+	}
+	src.mustBeExported()
+
+	de := dst.typ.Elem()
+	se := src.typ.Elem()
+	typesMustMatch("reflect.Copy", de, se)
+
+	n := dst.Len()
+	if sn := src.Len(); n > sn {
+		n = sn
+	}
+
+	// If sk is an in-line array, cannot take its address.
+	// Instead, copy element by element.
+	// TODO: memmove would be ok for this (sa = unsafe.Pointer(&v.scalar))
+	// if we teach the compiler that ptrs don't escape from memmove.
+	if src.flag&flagIndir == 0 {
+		for i := 0; i < n; i++ {
+			dst.Index(i).Set(src.Index(i))
+		}
+		return n
+	}
+
+	// Copy via memmove.
+	var da, sa unsafe.Pointer
+	if dk == Array {
+		da = dst.ptr
+	} else {
+		da = (*sliceHeader)(dst.ptr).Data
+	}
+	if sk == Array {
+		sa = src.ptr
+	} else {
+		sa = (*sliceHeader)(src.ptr).Data
+	}
+	memmove(da, sa, uintptr(n)*de.Size())
+	return n
+}
+
+// A runtimeSelect is a single case passed to rselect.
+// This must match ../runtime/chan.c:/runtimeSelect
+type runtimeSelect struct {
+	dir uintptr        // 0, SendDir, or RecvDir
+	typ *rtype         // channel type
+	ch  unsafe.Pointer // channel
+	val unsafe.Pointer // ptr to data (SendDir) or ptr to receive buffer (RecvDir)
+}
+
+// rselect runs a select.  It returns the index of the chosen case.
+// If the case was a receive, val is filled in with the received value.
+// The conventional OK bool indicates whether the receive corresponds
+// to a sent value.
+//go:noescape
+func rselect([]runtimeSelect) (chosen int, recvOK bool)
+
+// A SelectDir describes the communication direction of a select case.
+type SelectDir int
+
+// NOTE: These values must match ../runtime/chan.c:/SelectDir.
+
+const (
+	_             SelectDir = iota
+	SelectSend              // case Chan <- Send
+	SelectRecv              // case <-Chan:
+	SelectDefault           // default
+)
+
+// A SelectCase describes a single case in a select operation.
+// The kind of case depends on Dir, the communication direction.
+//
+// If Dir is SelectDefault, the case represents a default case.
+// Chan and Send must be zero Values.
+//
+// If Dir is SelectSend, the case represents a send operation.
+// Normally Chan's underlying value must be a channel, and Send's underlying value must be
+// assignable to the channel's element type. As a special case, if Chan is a zero Value,
+// then the case is ignored, and the field Send will also be ignored and may be either zero
+// or non-zero.
+//
+// If Dir is SelectRecv, the case represents a receive operation.
+// Normally Chan's underlying value must be a channel and Send must be a zero Value.
+// If Chan is a zero Value, then the case is ignored, but Send must still be a zero Value.
+// When a receive operation is selected, the received Value is returned by Select.
+//
+type SelectCase struct {
+	Dir  SelectDir // direction of case
+	Chan Value     // channel to use (for send or receive)
+	Send Value     // value to send (for send)
+}
+
+// Select executes a select operation described by the list of cases.
+// Like the Go select statement, it blocks until at least one of the cases
+// can proceed, makes a uniform pseudo-random choice,
+// and then executes that case. It returns the index of the chosen case
+// and, if that case was a receive operation, the value received and a
+// boolean indicating whether the value corresponds to a send on the channel
+// (as opposed to a zero value received because the channel is closed).
+func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
+	// NOTE: Do not trust that caller is not modifying cases data underfoot.
+	// The range is safe because the caller cannot modify our copy of the len
+	// and each iteration makes its own copy of the value c.
+	runcases := make([]runtimeSelect, len(cases))
+	haveDefault := false
+	for i, c := range cases {
+		rc := &runcases[i]
+		rc.dir = uintptr(c.Dir)
+		switch c.Dir {
+		default:
+			panic("reflect.Select: invalid Dir")
+
+		case SelectDefault: // default
+			if haveDefault {
+				panic("reflect.Select: multiple default cases")
+			}
+			haveDefault = true
+			if c.Chan.IsValid() {
+				panic("reflect.Select: default case has Chan value")
+			}
+			if c.Send.IsValid() {
+				panic("reflect.Select: default case has Send value")
+			}
+
+		case SelectSend:
+			ch := c.Chan
+			if !ch.IsValid() {
+				break
+			}
+			ch.mustBe(Chan)
+			ch.mustBeExported()
+			tt := (*chanType)(unsafe.Pointer(ch.typ))
+			if ChanDir(tt.dir)&SendDir == 0 {
+				panic("reflect.Select: SendDir case using recv-only channel")
+			}
+			rc.ch = ch.pointer()
+			rc.typ = &tt.rtype
+			v := c.Send
+			if !v.IsValid() {
+				panic("reflect.Select: SendDir case missing Send value")
+			}
+			v.mustBeExported()
+			v = v.assignTo("reflect.Select", tt.elem, nil)
+			if v.flag&flagIndir != 0 {
+				rc.val = v.ptr
+			} else if v.typ.pointers() {
+				rc.val = unsafe.Pointer(&v.ptr)
+			} else {
+				// rc.val = unsafe.Pointer(&v.scalar)
+				panic("reflect: missing flagIndir")
+			}
+
+		case SelectRecv:
+			if c.Send.IsValid() {
+				panic("reflect.Select: RecvDir case has Send value")
+			}
+			ch := c.Chan
+			if !ch.IsValid() {
+				break
+			}
+			ch.mustBe(Chan)
+			ch.mustBeExported()
+			tt := (*chanType)(unsafe.Pointer(ch.typ))
+			if ChanDir(tt.dir)&RecvDir == 0 {
+				panic("reflect.Select: RecvDir case using send-only channel")
+			}
+			rc.ch = ch.pointer()
+			rc.typ = &tt.rtype
+			rc.val = unsafe_New(tt.elem)
+		}
+	}
+
+	chosen, recvOK = rselect(runcases)
+	if runcases[chosen].dir == uintptr(SelectRecv) {
+		tt := (*chanType)(unsafe.Pointer(runcases[chosen].typ))
+		t := tt.elem
+		p := runcases[chosen].val
+		fl := flag(t.Kind()) << flagKindShift
+		if t.Kind() != Ptr && t.Kind() != UnsafePointer {
+			recv = Value{t, p /* 0, */, fl | flagIndir}
+		} else {
+			recv = Value{t, *(*unsafe.Pointer)(p) /* 0, */, fl}
+		}
+	}
+	return chosen, recv, recvOK
+}
+
+/*
+ * constructors
+ */
+
+// implemented in package runtime
+func unsafe_New(*rtype) unsafe.Pointer
+func unsafe_NewArray(*rtype, int) unsafe.Pointer
+
+// MakeSlice creates a new zero-initialized slice value
+// for the specified slice type, length, and capacity.
+func MakeSlice(typ Type, len, cap int) Value {
+	if typ.Kind() != Slice {
+		panic("reflect.MakeSlice of non-slice type")
+	}
+	if len < 0 {
+		panic("reflect.MakeSlice: negative len")
+	}
+	if cap < 0 {
+		panic("reflect.MakeSlice: negative cap")
+	}
+	if len > cap {
+		panic("reflect.MakeSlice: len > cap")
+	}
+
+	s := sliceHeader{unsafe_NewArray(typ.Elem().(*rtype), cap), len, cap}
+	return Value{typ.common(), unsafe.Pointer(&s) /* 0, */, flagIndir | flag(Slice)<<flagKindShift}
+}
+
+// MakeChan creates a new channel with the specified type and buffer size.
+func MakeChan(typ Type, buffer int) Value {
+	if typ.Kind() != Chan {
+		panic("reflect.MakeChan of non-chan type")
+	}
+	if buffer < 0 {
+		panic("reflect.MakeChan: negative buffer size")
+	}
+	if typ.ChanDir() != BothDir {
+		panic("reflect.MakeChan: unidirectional channel type")
+	}
+	ch := makechan(typ.(*rtype), uint64(buffer))
+	return Value{typ.common(), unsafe.Pointer(&ch) /* 0, */, flagIndir | (flag(Chan) << flagKindShift)}
+}
+
+// MakeMap creates a new map of the specified type.
+func MakeMap(typ Type) Value {
+	if typ.Kind() != Map {
+		panic("reflect.MakeMap of non-map type")
+	}
+	m := makemap(typ.(*rtype))
+	return Value{typ.common(), unsafe.Pointer(&m) /* 0, */, flagIndir | (flag(Map) << flagKindShift)}
+}
+
+// Indirect returns the value that v points to.
+// If v is a nil pointer, Indirect returns a zero Value.
+// If v is not a pointer, Indirect returns v.
+func Indirect(v Value) Value {
+	if v.Kind() != Ptr {
+		return v
+	}
+	return v.Elem()
+}
+
+// ValueOf returns a new Value initialized to the concrete value
+// stored in the interface i.  ValueOf(nil) returns the zero Value.
+func ValueOf(i interface{}) Value {
+	if i == nil {
+		return Value{}
+	}
+
+	// TODO(rsc): Eliminate this terrible hack.
+	// In the call to unpackEface, i.typ doesn't escape,
+	// and i.word is an integer.  So it looks like
+	// i doesn't escape.  But really it does,
+	// because i.word is actually a pointer.
+	escapes(i)
+
+	return unpackEface(i)
+}
+
+// Zero returns a Value representing the zero value for the specified type.
+// The result is different from the zero value of the Value struct,
+// which represents no value at all.
+// For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0.
+// The returned value is neither addressable nor settable.
+func Zero(typ Type) Value {
+	if typ == nil {
+		panic("reflect: Zero(nil)")
+	}
+	t := typ.common()
+	fl := flag(t.Kind()) << flagKindShift
+	if t.Kind() == Ptr || t.Kind() == UnsafePointer {
+		return Value{t, nil /* 0, */, fl}
+	}
+	return Value{t, unsafe_New(typ.(*rtype)) /* 0, */, fl | flagIndir}
+}
+
+// New returns a Value representing a pointer to a new zero value
+// for the specified type.  That is, the returned Value's Type is PtrTo(typ).
+func New(typ Type) Value {
+	if typ == nil {
+		panic("reflect: New(nil)")
+	}
+	ptr := unsafe_New(typ.(*rtype))
+	fl := flag(Ptr) << flagKindShift
+	return Value{typ.common().ptrTo(), ptr /* 0, */, fl}
+}
+
+// NewAt returns a Value representing a pointer to a value of the
+// specified type, using p as that pointer.
+func NewAt(typ Type, p unsafe.Pointer) Value {
+	fl := flag(Ptr) << flagKindShift
+	return Value{typ.common().ptrTo(), p /* 0, */, fl}
+}
+
+// assignTo returns a value v that can be assigned directly to typ.
+// It panics if v is not assignable to typ.
+// For a conversion to an interface type, target is a suggested scratch space to use.
+func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value {
+	if v.flag&flagMethod != 0 {
+		v = makeMethodValue(context, v)
+	}
+
+	switch {
+	case directlyAssignable(dst, v.typ):
+		// Overwrite type so that they match.
+		// Same memory layout, so no harm done.
+		v.typ = dst
+		fl := v.flag & (flagRO | flagAddr | flagIndir)
+		fl |= flag(dst.Kind()) << flagKindShift
+		return Value{dst, v.ptr /* v.scalar, */, fl}
+
+	case implements(dst, v.typ):
+		if target == nil {
+			target = unsafe_New(dst)
+		}
+		x := valueInterface(v, false)
+		if dst.NumMethod() == 0 {
+			*(*interface{})(target) = x
+		} else {
+			ifaceE2I(dst, x, target)
+		}
+		return Value{dst, target /* 0, */, flagIndir | flag(Interface)<<flagKindShift}
+	}
+
+	// Failed.
+	panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
+}
+
+// Convert returns the value v converted to type t.
+// If the usual Go conversion rules do not allow conversion
+// of the value v to type t, Convert panics.
+func (v Value) Convert(t Type) Value {
+	if v.flag&flagMethod != 0 {
+		v = makeMethodValue("Convert", v)
+	}
+	op := convertOp(t.common(), v.typ)
+	if op == nil {
+		panic("reflect.Value.Convert: value of type " + v.typ.String() + " cannot be converted to type " + t.String())
+	}
+	return op(v, t)
+}
+
+// convertOp returns the function to convert a value of type src
+// to a value of type dst. If the conversion is illegal, convertOp returns nil.
+func convertOp(dst, src *rtype) func(Value, Type) Value {
+	switch src.Kind() {
+	case Int, Int8, Int16, Int32, Int64:
+		switch dst.Kind() {
+		case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+			return cvtInt
+		case Float32, Float64:
+			return cvtIntFloat
+		case String:
+			return cvtIntString
+		}
+
+	case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+		switch dst.Kind() {
+		case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+			return cvtUint
+		case Float32, Float64:
+			return cvtUintFloat
+		case String:
+			return cvtUintString
+		}
+
+	case Float32, Float64:
+		switch dst.Kind() {
+		case Int, Int8, Int16, Int32, Int64:
+			return cvtFloatInt
+		case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+			return cvtFloatUint
+		case Float32, Float64:
+			return cvtFloat
+		}
+
+	case Complex64, Complex128:
+		switch dst.Kind() {
+		case Complex64, Complex128:
+			return cvtComplex
+		}
+
+	case String:
+		if dst.Kind() == Slice && dst.Elem().PkgPath() == "" {
+			switch dst.Elem().Kind() {
+			case Uint8:
+				return cvtStringBytes
+			case Int32:
+				return cvtStringRunes
+			}
+		}
+
+	case Slice:
+		if dst.Kind() == String && src.Elem().PkgPath() == "" {
+			switch src.Elem().Kind() {
+			case Uint8:
+				return cvtBytesString
+			case Int32:
+				return cvtRunesString
+			}
+		}
+	}
+
+	// dst and src have same underlying type.
+	if haveIdenticalUnderlyingType(dst, src) {
+		return cvtDirect
+	}
+
+	// dst and src are unnamed pointer types with same underlying base type.
+	if dst.Kind() == Ptr && dst.Name() == "" &&
+		src.Kind() == Ptr && src.Name() == "" &&
+		haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common()) {
+		return cvtDirect
+	}
+
+	if implements(dst, src) {
+		if src.Kind() == Interface {
+			return cvtI2I
+		}
+		return cvtT2I
+	}
+
+	return nil
+}
+
+// makeInt returns a Value of type t equal to bits (possibly truncated),
+// where t is a signed or unsigned int type.
+func makeInt(f flag, bits uint64, t Type) Value {
+	typ := t.common()
+	if typ.size > ptrSize {
+		// Assume ptrSize >= 4, so this must be uint64.
+		ptr := unsafe_New(typ)
+		*(*uint64)(unsafe.Pointer(ptr)) = bits
+		return Value{typ, ptr /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+	}
+	var s uintptr
+	switch typ.size {
+	case 1:
+		*(*uint8)(unsafe.Pointer(&s)) = uint8(bits)
+	case 2:
+		*(*uint16)(unsafe.Pointer(&s)) = uint16(bits)
+	case 4:
+		*(*uint32)(unsafe.Pointer(&s)) = uint32(bits)
+	case 8:
+		*(*uint64)(unsafe.Pointer(&s)) = uint64(bits)
+	}
+	return Value{typ, unsafe.Pointer(&s) /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+}
+
+// makeFloat returns a Value of type t equal to v (possibly truncated to float32),
+// where t is a float32 or float64 type.
+func makeFloat(f flag, v float64, t Type) Value {
+	typ := t.common()
+	if typ.size > ptrSize {
+		// Assume ptrSize >= 4, so this must be float64.
+		ptr := unsafe_New(typ)
+		*(*float64)(unsafe.Pointer(ptr)) = v
+		return Value{typ, ptr /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+	}
+
+	var s uintptr
+	switch typ.size {
+	case 4:
+		*(*float32)(unsafe.Pointer(&s)) = float32(v)
+	case 8:
+		*(*float64)(unsafe.Pointer(&s)) = v
+	}
+	return Value{typ, unsafe.Pointer(&s) /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+}
+
+// makeComplex returns a Value of type t equal to v (possibly truncated to complex64),
+// where t is a complex64 or complex128 type.
+func makeComplex(f flag, v complex128, t Type) Value {
+	typ := t.common()
+	if typ.size > ptrSize {
+		ptr := unsafe_New(typ)
+		switch typ.size {
+		case 8:
+			*(*complex64)(unsafe.Pointer(ptr)) = complex64(v)
+		case 16:
+			*(*complex128)(unsafe.Pointer(ptr)) = v
+		}
+		return Value{typ, ptr /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+	}
+
+	// Assume ptrSize <= 8 so this must be complex64.
+	var s uintptr
+	*(*complex64)(unsafe.Pointer(&s)) = complex64(v)
+	return Value{typ, unsafe.Pointer(&s) /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+}
+
+func makeString(f flag, v string, t Type) Value {
+	ret := New(t).Elem()
+	ret.SetString(v)
+	ret.flag = ret.flag&^flagAddr | f | flagIndir
+	return ret
+}
+
+func makeBytes(f flag, v []byte, t Type) Value {
+	ret := New(t).Elem()
+	ret.SetBytes(v)
+	ret.flag = ret.flag&^flagAddr | f | flagIndir
+	return ret
+}
+
+func makeRunes(f flag, v []rune, t Type) Value {
+	ret := New(t).Elem()
+	ret.setRunes(v)
+	ret.flag = ret.flag&^flagAddr | f | flagIndir
+	return ret
+}
+
+// These conversion functions are returned by convertOp
+// for classes of conversions. For example, the first function, cvtInt,
+// takes any value v of signed int type and returns the value converted
+// to type t, where t is any signed or unsigned int type.
+
+// convertOp: intXX -> [u]intXX
+func cvtInt(v Value, t Type) Value {
+	return makeInt(v.flag&flagRO, uint64(v.Int()), t)
+}
+
+// convertOp: uintXX -> [u]intXX
+func cvtUint(v Value, t Type) Value {
+	return makeInt(v.flag&flagRO, v.Uint(), t)
+}
+
+// convertOp: floatXX -> intXX
+func cvtFloatInt(v Value, t Type) Value {
+	return makeInt(v.flag&flagRO, uint64(int64(v.Float())), t)
+}
+
+// convertOp: floatXX -> uintXX
+func cvtFloatUint(v Value, t Type) Value {
+	return makeInt(v.flag&flagRO, uint64(v.Float()), t)
+}
+
+// convertOp: intXX -> floatXX
+func cvtIntFloat(v Value, t Type) Value {
+	return makeFloat(v.flag&flagRO, float64(v.Int()), t)
+}
+
+// convertOp: uintXX -> floatXX
+func cvtUintFloat(v Value, t Type) Value {
+	return makeFloat(v.flag&flagRO, float64(v.Uint()), t)
+}
+
+// convertOp: floatXX -> floatXX
+func cvtFloat(v Value, t Type) Value {
+	return makeFloat(v.flag&flagRO, v.Float(), t)
+}
+
+// convertOp: complexXX -> complexXX
+func cvtComplex(v Value, t Type) Value {
+	return makeComplex(v.flag&flagRO, v.Complex(), t)
+}
+
+// convertOp: intXX -> string
+func cvtIntString(v Value, t Type) Value {
+	return makeString(v.flag&flagRO, string(v.Int()), t)
+}
+
+// convertOp: uintXX -> string
+func cvtUintString(v Value, t Type) Value {
+	return makeString(v.flag&flagRO, string(v.Uint()), t)
+}
+
+// convertOp: []byte -> string
+func cvtBytesString(v Value, t Type) Value {
+	return makeString(v.flag&flagRO, string(v.Bytes()), t)
+}
+
+// convertOp: string -> []byte
+func cvtStringBytes(v Value, t Type) Value {
+	return makeBytes(v.flag&flagRO, []byte(v.String()), t)
+}
+
+// convertOp: []rune -> string
+func cvtRunesString(v Value, t Type) Value {
+	return makeString(v.flag&flagRO, string(v.runes()), t)
+}
+
+// convertOp: string -> []rune
+func cvtStringRunes(v Value, t Type) Value {
+	return makeRunes(v.flag&flagRO, []rune(v.String()), t)
+}
+
+// convertOp: direct copy
+func cvtDirect(v Value, typ Type) Value {
+	f := v.flag
+	t := typ.common()
+	ptr := v.ptr
+	if f&flagAddr != 0 {
+		// indirect, mutable word - make a copy
+		c := unsafe_New(t)
+		memmove(c, ptr, t.size)
+		ptr = c
+		f &^= flagAddr
+	}
+	return Value{t, ptr /* v.scalar, */, v.flag&flagRO | f} // v.flag&flagRO|f == f?
+}
+
+// convertOp: concrete -> interface
+func cvtT2I(v Value, typ Type) Value {
+	target := unsafe_New(typ.common())
+	x := valueInterface(v, false)
+	if typ.NumMethod() == 0 {
+		*(*interface{})(target) = x
+	} else {
+		ifaceE2I(typ.(*rtype), x, target)
+	}
+	return Value{typ.common(), target /* 0, */, v.flag&flagRO | flagIndir | flag(Interface)<<flagKindShift}
+}
+
+// convertOp: interface -> interface
+func cvtI2I(v Value, typ Type) Value {
+	if v.IsNil() {
+		ret := Zero(typ)
+		ret.flag |= v.flag & flagRO
+		return ret
+	}
+	return cvtT2I(v.Elem(), typ)
+}
+
+// implemented in ../pkg/runtime
+func chancap(ch unsafe.Pointer) int
+func chanclose(ch unsafe.Pointer)
+func chanlen(ch unsafe.Pointer) int
+
+//go:noescape
+func chanrecv(t *rtype, ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selected, received bool)
+
+//go:noescape
+func chansend(t *rtype, ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool
+
+func makechan(typ *rtype, size uint64) (ch unsafe.Pointer)
+func makemap(t *rtype) (m unsafe.Pointer)
+func mapaccess(t *rtype, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
+func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer)
+func mapdelete(t *rtype, m unsafe.Pointer, key unsafe.Pointer)
+func mapiterinit(t *rtype, m unsafe.Pointer) unsafe.Pointer
+func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer)
+func mapiternext(it unsafe.Pointer)
+func maplen(m unsafe.Pointer) int
+
+func call(typ *rtype, fnaddr unsafe.Pointer, isInterface bool, isMethod bool, params *unsafe.Pointer, results *unsafe.Pointer)
+func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
+
+// Dummy annotation marking that the value x escapes,
+// for use in cases where the reflect code is so clever that
+// the compiler cannot follow.
+func escapes(x interface{}) {
+	if dummy.b {
+		dummy.x = x
+	}
+}
+
+var dummy struct {
+	b bool
+	x interface{}
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/all_test.go b/third_party/gofrontend/libgo/go/regexp/all_test.go
new file mode 100644
index 0000000..301a1df
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/all_test.go
@@ -0,0 +1,645 @@
+// 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 regexp
+
+import (
+	"reflect"
+	"strings"
+	"testing"
+)
+
+var good_re = []string{
+	``,
+	`.`,
+	`^.$`,
+	`a`,
+	`a*`,
+	`a+`,
+	`a?`,
+	`a|b`,
+	`a*|b*`,
+	`(a*|b)(c*|d)`,
+	`[a-z]`,
+	`[a-abc-c\-\]\[]`,
+	`[a-z]+`,
+	`[abc]`,
+	`[^1234]`,
+	`[^\n]`,
+	`\!\\`,
+}
+
+type stringError struct {
+	re  string
+	err string
+}
+
+var bad_re = []stringError{
+	{`*`, "missing argument to repetition operator: `*`"},
+	{`+`, "missing argument to repetition operator: `+`"},
+	{`?`, "missing argument to repetition operator: `?`"},
+	{`(abc`, "missing closing ): `(abc`"},
+	{`abc)`, "unexpected ): `abc)`"},
+	{`x[a-z`, "missing closing ]: `[a-z`"},
+	{`[z-a]`, "invalid character class range: `z-a`"},
+	{`abc\`, "trailing backslash at end of expression"},
+	{`a**`, "invalid nested repetition operator: `**`"},
+	{`a*+`, "invalid nested repetition operator: `*+`"},
+	{`\x`, "invalid escape sequence: `\\x`"},
+}
+
+func compileTest(t *testing.T, expr string, error string) *Regexp {
+	re, err := Compile(expr)
+	if error == "" && err != nil {
+		t.Error("compiling `", expr, "`; unexpected error: ", err.Error())
+	}
+	if error != "" && err == nil {
+		t.Error("compiling `", expr, "`; missing error")
+	} else if error != "" && !strings.Contains(err.Error(), error) {
+		t.Error("compiling `", expr, "`; wrong error: ", err.Error(), "; want ", error)
+	}
+	return re
+}
+
+func TestGoodCompile(t *testing.T) {
+	for i := 0; i < len(good_re); i++ {
+		compileTest(t, good_re[i], "")
+	}
+}
+
+func TestBadCompile(t *testing.T) {
+	for i := 0; i < len(bad_re); i++ {
+		compileTest(t, bad_re[i].re, bad_re[i].err)
+	}
+}
+
+func matchTest(t *testing.T, test *FindTest) {
+	re := compileTest(t, test.pat, "")
+	if re == nil {
+		return
+	}
+	m := re.MatchString(test.text)
+	if m != (len(test.matches) > 0) {
+		t.Errorf("MatchString failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+	}
+	// now try bytes
+	m = re.Match([]byte(test.text))
+	if m != (len(test.matches) > 0) {
+		t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+	}
+}
+
+func TestMatch(t *testing.T) {
+	for _, test := range findTests {
+		matchTest(t, &test)
+	}
+}
+
+func matchFunctionTest(t *testing.T, test *FindTest) {
+	m, err := MatchString(test.pat, test.text)
+	if err == nil {
+		return
+	}
+	if m != (len(test.matches) > 0) {
+		t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+	}
+}
+
+func TestMatchFunction(t *testing.T) {
+	for _, test := range findTests {
+		matchFunctionTest(t, &test)
+	}
+}
+
+type ReplaceTest struct {
+	pattern, replacement, input, output string
+}
+
+var replaceTests = []ReplaceTest{
+	// Test empty input and/or replacement, with pattern that matches the empty string.
+	{"", "", "", ""},
+	{"", "x", "", "x"},
+	{"", "", "abc", "abc"},
+	{"", "x", "abc", "xaxbxcx"},
+
+	// Test empty input and/or replacement, with pattern that does not match the empty string.
+	{"b", "", "", ""},
+	{"b", "x", "", ""},
+	{"b", "", "abc", "ac"},
+	{"b", "x", "abc", "axc"},
+	{"y", "", "", ""},
+	{"y", "x", "", ""},
+	{"y", "", "abc", "abc"},
+	{"y", "x", "abc", "abc"},
+
+	// Multibyte characters -- verify that we don't try to match in the middle
+	// of a character.
+	{"[a-c]*", "x", "\u65e5", "x\u65e5x"},
+	{"[^\u65e5]", "x", "abc\u65e5def", "xxx\u65e5xxx"},
+
+	// Start and end of a string.
+	{"^[a-c]*", "x", "abcdabc", "xdabc"},
+	{"[a-c]*$", "x", "abcdabc", "abcdx"},
+	{"^[a-c]*$", "x", "abcdabc", "abcdabc"},
+	{"^[a-c]*", "x", "abc", "x"},
+	{"[a-c]*$", "x", "abc", "x"},
+	{"^[a-c]*$", "x", "abc", "x"},
+	{"^[a-c]*", "x", "dabce", "xdabce"},
+	{"[a-c]*$", "x", "dabce", "dabcex"},
+	{"^[a-c]*$", "x", "dabce", "dabce"},
+	{"^[a-c]*", "x", "", "x"},
+	{"[a-c]*$", "x", "", "x"},
+	{"^[a-c]*$", "x", "", "x"},
+
+	{"^[a-c]+", "x", "abcdabc", "xdabc"},
+	{"[a-c]+$", "x", "abcdabc", "abcdx"},
+	{"^[a-c]+$", "x", "abcdabc", "abcdabc"},
+	{"^[a-c]+", "x", "abc", "x"},
+	{"[a-c]+$", "x", "abc", "x"},
+	{"^[a-c]+$", "x", "abc", "x"},
+	{"^[a-c]+", "x", "dabce", "dabce"},
+	{"[a-c]+$", "x", "dabce", "dabce"},
+	{"^[a-c]+$", "x", "dabce", "dabce"},
+	{"^[a-c]+", "x", "", ""},
+	{"[a-c]+$", "x", "", ""},
+	{"^[a-c]+$", "x", "", ""},
+
+	// Other cases.
+	{"abc", "def", "abcdefg", "defdefg"},
+	{"bc", "BC", "abcbcdcdedef", "aBCBCdcdedef"},
+	{"abc", "", "abcdabc", "d"},
+	{"x", "xXx", "xxxXxxx", "xXxxXxxXxXxXxxXxxXx"},
+	{"abc", "d", "", ""},
+	{"abc", "d", "abc", "d"},
+	{".+", "x", "abc", "x"},
+	{"[a-c]*", "x", "def", "xdxexfx"},
+	{"[a-c]+", "x", "abcbcdcdedef", "xdxdedef"},
+	{"[a-c]*", "x", "abcbcdcdedef", "xdxdxexdxexfx"},
+
+	// Substitutions
+	{"a+", "($0)", "banana", "b(a)n(a)n(a)"},
+	{"a+", "(${0})", "banana", "b(a)n(a)n(a)"},
+	{"a+", "(${0})$0", "banana", "b(a)an(a)an(a)a"},
+	{"a+", "(${0})$0", "banana", "b(a)an(a)an(a)a"},
+	{"hello, (.+)", "goodbye, ${1}", "hello, world", "goodbye, world"},
+	{"hello, (.+)", "goodbye, $1x", "hello, world", "goodbye, "},
+	{"hello, (.+)", "goodbye, ${1}x", "hello, world", "goodbye, worldx"},
+	{"hello, (.+)", "<$0><$1><$2><$3>", "hello, world", "<hello, world><world><><>"},
+	{"hello, (?P<noun>.+)", "goodbye, $noun!", "hello, world", "goodbye, world!"},
+	{"hello, (?P<noun>.+)", "goodbye, ${noun}", "hello, world", "goodbye, world"},
+	{"(?P<x>hi)|(?P<x>bye)", "$x$x$x", "hi", "hihihi"},
+	{"(?P<x>hi)|(?P<x>bye)", "$x$x$x", "bye", "byebyebye"},
+	{"(?P<x>hi)|(?P<x>bye)", "$xyz", "hi", ""},
+	{"(?P<x>hi)|(?P<x>bye)", "${x}yz", "hi", "hiyz"},
+	{"(?P<x>hi)|(?P<x>bye)", "hello $$x", "hi", "hello $x"},
+	{"a+", "${oops", "aaa", "${oops"},
+	{"a+", "$$", "aaa", "$"},
+	{"a+", "$", "aaa", "$"},
+
+	// Substitution when subexpression isn't found
+	{"(x)?", "$1", "123", "123"},
+	{"abc", "$1", "123", "123"},
+}
+
+var replaceLiteralTests = []ReplaceTest{
+	// Substitutions
+	{"a+", "($0)", "banana", "b($0)n($0)n($0)"},
+	{"a+", "(${0})", "banana", "b(${0})n(${0})n(${0})"},
+	{"a+", "(${0})$0", "banana", "b(${0})$0n(${0})$0n(${0})$0"},
+	{"a+", "(${0})$0", "banana", "b(${0})$0n(${0})$0n(${0})$0"},
+	{"hello, (.+)", "goodbye, ${1}", "hello, world", "goodbye, ${1}"},
+	{"hello, (?P<noun>.+)", "goodbye, $noun!", "hello, world", "goodbye, $noun!"},
+	{"hello, (?P<noun>.+)", "goodbye, ${noun}", "hello, world", "goodbye, ${noun}"},
+	{"(?P<x>hi)|(?P<x>bye)", "$x$x$x", "hi", "$x$x$x"},
+	{"(?P<x>hi)|(?P<x>bye)", "$x$x$x", "bye", "$x$x$x"},
+	{"(?P<x>hi)|(?P<x>bye)", "$xyz", "hi", "$xyz"},
+	{"(?P<x>hi)|(?P<x>bye)", "${x}yz", "hi", "${x}yz"},
+	{"(?P<x>hi)|(?P<x>bye)", "hello $$x", "hi", "hello $$x"},
+	{"a+", "${oops", "aaa", "${oops"},
+	{"a+", "$$", "aaa", "$$"},
+	{"a+", "$", "aaa", "$"},
+}
+
+type ReplaceFuncTest struct {
+	pattern       string
+	replacement   func(string) string
+	input, output string
+}
+
+var replaceFuncTests = []ReplaceFuncTest{
+	{"[a-c]", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxayxbyxcydef"},
+	{"[a-c]+", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxabcydef"},
+	{"[a-c]*", func(s string) string { return "x" + s + "y" }, "defabcdef", "xydxyexyfxabcydxyexyfxy"},
+}
+
+func TestReplaceAll(t *testing.T) {
+	for _, tc := range replaceTests {
+		re, err := Compile(tc.pattern)
+		if err != nil {
+			t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
+			continue
+		}
+		actual := re.ReplaceAllString(tc.input, tc.replacement)
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceAllString(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+		// now try bytes
+		actual = string(re.ReplaceAll([]byte(tc.input), []byte(tc.replacement)))
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceAll(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+	}
+}
+
+func TestReplaceAllLiteral(t *testing.T) {
+	// Run ReplaceAll tests that do not have $ expansions.
+	for _, tc := range replaceTests {
+		if strings.Contains(tc.replacement, "$") {
+			continue
+		}
+		re, err := Compile(tc.pattern)
+		if err != nil {
+			t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
+			continue
+		}
+		actual := re.ReplaceAllLiteralString(tc.input, tc.replacement)
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceAllLiteralString(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+		// now try bytes
+		actual = string(re.ReplaceAllLiteral([]byte(tc.input), []byte(tc.replacement)))
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceAllLiteral(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+	}
+
+	// Run literal-specific tests.
+	for _, tc := range replaceLiteralTests {
+		re, err := Compile(tc.pattern)
+		if err != nil {
+			t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
+			continue
+		}
+		actual := re.ReplaceAllLiteralString(tc.input, tc.replacement)
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceAllLiteralString(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+		// now try bytes
+		actual = string(re.ReplaceAllLiteral([]byte(tc.input), []byte(tc.replacement)))
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceAllLiteral(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+	}
+}
+
+func TestReplaceAllFunc(t *testing.T) {
+	for _, tc := range replaceFuncTests {
+		re, err := Compile(tc.pattern)
+		if err != nil {
+			t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
+			continue
+		}
+		actual := re.ReplaceAllStringFunc(tc.input, tc.replacement)
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceFunc(%q,fn) = %q; want %q",
+				tc.pattern, tc.input, actual, tc.output)
+		}
+		// now try bytes
+		actual = string(re.ReplaceAllFunc([]byte(tc.input), func(s []byte) []byte { return []byte(tc.replacement(string(s))) }))
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceFunc(%q,fn) = %q; want %q",
+				tc.pattern, tc.input, actual, tc.output)
+		}
+	}
+}
+
+type MetaTest struct {
+	pattern, output, literal string
+	isLiteral                bool
+}
+
+var metaTests = []MetaTest{
+	{``, ``, ``, true},
+	{`foo`, `foo`, `foo`, true},
+	{`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
+	{`foo.\$`, `foo\.\\\$`, `foo`, false},     // has escaped operators and real operators
+	{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[\{\]\}\\\|,<\.>/\?~`, `!@#`, false},
+}
+
+func TestQuoteMeta(t *testing.T) {
+	for _, tc := range metaTests {
+		// Verify that QuoteMeta returns the expected string.
+		quoted := QuoteMeta(tc.pattern)
+		if quoted != tc.output {
+			t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`",
+				tc.pattern, quoted, tc.output)
+			continue
+		}
+
+		// Verify that the quoted string is in fact treated as expected
+		// by Compile -- i.e. that it matches the original, unquoted string.
+		if tc.pattern != "" {
+			re, err := Compile(quoted)
+			if err != nil {
+				t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err)
+				continue
+			}
+			src := "abc" + tc.pattern + "def"
+			repl := "xyz"
+			replaced := re.ReplaceAllString(src, repl)
+			expected := "abcxyzdef"
+			if replaced != expected {
+				t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`",
+					tc.pattern, src, repl, replaced, expected)
+			}
+		}
+	}
+}
+
+func TestLiteralPrefix(t *testing.T) {
+	for _, tc := range metaTests {
+		// Literal method needs to scan the pattern.
+		re := MustCompile(tc.pattern)
+		str, complete := re.LiteralPrefix()
+		if complete != tc.isLiteral {
+			t.Errorf("LiteralPrefix(`%s`) = %t; want %t", tc.pattern, complete, tc.isLiteral)
+		}
+		if str != tc.literal {
+			t.Errorf("LiteralPrefix(`%s`) = `%s`; want `%s`", tc.pattern, str, tc.literal)
+		}
+	}
+}
+
+type subexpCase struct {
+	input string
+	num   int
+	names []string
+}
+
+var subexpCases = []subexpCase{
+	{``, 0, nil},
+	{`.*`, 0, nil},
+	{`abba`, 0, nil},
+	{`ab(b)a`, 1, []string{"", ""}},
+	{`ab(.*)a`, 1, []string{"", ""}},
+	{`(.*)ab(.*)a`, 2, []string{"", "", ""}},
+	{`(.*)(ab)(.*)a`, 3, []string{"", "", "", ""}},
+	{`(.*)((a)b)(.*)a`, 4, []string{"", "", "", "", ""}},
+	{`(.*)(\(ab)(.*)a`, 3, []string{"", "", "", ""}},
+	{`(.*)(\(a\)b)(.*)a`, 3, []string{"", "", "", ""}},
+	{`(?P<foo>.*)(?P<bar>(a)b)(?P<foo>.*)a`, 4, []string{"", "foo", "bar", "", "foo"}},
+}
+
+func TestSubexp(t *testing.T) {
+	for _, c := range subexpCases {
+		re := MustCompile(c.input)
+		n := re.NumSubexp()
+		if n != c.num {
+			t.Errorf("%q: NumSubexp = %d, want %d", c.input, n, c.num)
+			continue
+		}
+		names := re.SubexpNames()
+		if len(names) != 1+n {
+			t.Errorf("%q: len(SubexpNames) = %d, want %d", c.input, len(names), n)
+			continue
+		}
+		if c.names != nil {
+			for i := 0; i < 1+n; i++ {
+				if names[i] != c.names[i] {
+					t.Errorf("%q: SubexpNames[%d] = %q, want %q", c.input, i, names[i], c.names[i])
+				}
+			}
+		}
+	}
+}
+
+var splitTests = []struct {
+	s   string
+	r   string
+	n   int
+	out []string
+}{
+	{"foo:and:bar", ":", -1, []string{"foo", "and", "bar"}},
+	{"foo:and:bar", ":", 1, []string{"foo:and:bar"}},
+	{"foo:and:bar", ":", 2, []string{"foo", "and:bar"}},
+	{"foo:and:bar", "foo", -1, []string{"", ":and:bar"}},
+	{"foo:and:bar", "bar", -1, []string{"foo:and:", ""}},
+	{"foo:and:bar", "baz", -1, []string{"foo:and:bar"}},
+	{"baabaab", "a", -1, []string{"b", "", "b", "", "b"}},
+	{"baabaab", "a*", -1, []string{"b", "b", "b"}},
+	{"baabaab", "ba*", -1, []string{"", "", "", ""}},
+	{"foobar", "f*b*", -1, []string{"", "o", "o", "a", "r"}},
+	{"foobar", "f+.*b+", -1, []string{"", "ar"}},
+	{"foobooboar", "o{2}", -1, []string{"f", "b", "boar"}},
+	{"a,b,c,d,e,f", ",", 3, []string{"a", "b", "c,d,e,f"}},
+	{"a,b,c,d,e,f", ",", 0, nil},
+	{",", ",", -1, []string{"", ""}},
+	{",,,", ",", -1, []string{"", "", "", ""}},
+	{"", ",", -1, []string{""}},
+	{"", ".*", -1, []string{""}},
+	{"", ".+", -1, []string{""}},
+	{"", "", -1, []string{}},
+	{"foobar", "", -1, []string{"f", "o", "o", "b", "a", "r"}},
+	{"abaabaccadaaae", "a*", 5, []string{"", "b", "b", "c", "cadaaae"}},
+	{":x:y:z:", ":", -1, []string{"", "x", "y", "z", ""}},
+}
+
+func TestSplit(t *testing.T) {
+	for i, test := range splitTests {
+		re, err := Compile(test.r)
+		if err != nil {
+			t.Errorf("#%d: %q: compile error: %s", i, test.r, err.Error())
+			continue
+		}
+
+		split := re.Split(test.s, test.n)
+		if !reflect.DeepEqual(split, test.out) {
+			t.Errorf("#%d: %q: got %q; want %q", i, test.r, split, test.out)
+		}
+
+		if QuoteMeta(test.r) == test.r {
+			strsplit := strings.SplitN(test.s, test.r, test.n)
+			if !reflect.DeepEqual(split, strsplit) {
+				t.Errorf("#%d: Split(%q, %q, %d): regexp vs strings mismatch\nregexp=%q\nstrings=%q", i, test.s, test.r, test.n, split, strsplit)
+			}
+		}
+	}
+}
+
+// This ran out of stack before issue 7608 was fixed.
+func TestOnePassCutoff(t *testing.T) {
+	MustCompile(`^(?:x{1,1000}){1,1000}$`)
+}
+
+func BenchmarkLiteral(b *testing.B) {
+	x := strings.Repeat("x", 50) + "y"
+	b.StopTimer()
+	re := MustCompile("y")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatalf("no match!")
+		}
+	}
+}
+
+func BenchmarkNotLiteral(b *testing.B) {
+	x := strings.Repeat("x", 50) + "y"
+	b.StopTimer()
+	re := MustCompile(".y")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatalf("no match!")
+		}
+	}
+}
+
+func BenchmarkMatchClass(b *testing.B) {
+	b.StopTimer()
+	x := strings.Repeat("xxxx", 20) + "w"
+	re := MustCompile("[abcdw]")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatalf("no match!")
+		}
+	}
+}
+
+func BenchmarkMatchClass_InRange(b *testing.B) {
+	b.StopTimer()
+	// 'b' is between 'a' and 'c', so the charclass
+	// range checking is no help here.
+	x := strings.Repeat("bbbb", 20) + "c"
+	re := MustCompile("[ac]")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatalf("no match!")
+		}
+	}
+}
+
+func BenchmarkReplaceAll(b *testing.B) {
+	x := "abcdefghijklmnopqrstuvwxyz"
+	b.StopTimer()
+	re := MustCompile("[cjrw]")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.ReplaceAllString(x, "")
+	}
+}
+
+func BenchmarkAnchoredLiteralShortNonMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	re := MustCompile("^zbc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkAnchoredLiteralLongNonMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	for i := 0; i < 15; i++ {
+		x = append(x, x...)
+	}
+	re := MustCompile("^zbc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkAnchoredShortMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	re := MustCompile("^.bc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkAnchoredLongMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	for i := 0; i < 15; i++ {
+		x = append(x, x...)
+	}
+	re := MustCompile("^.bc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkOnePassShortA(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcddddddeeeededd")
+	re := MustCompile("^.bc(d|e)*$")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkNotOnePassShortA(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcddddddeeeededd")
+	re := MustCompile(".bc(d|e)*$")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkOnePassShortB(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcddddddeeeededd")
+	re := MustCompile("^.bc(?:d|e)*$")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkNotOnePassShortB(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcddddddeeeededd")
+	re := MustCompile(".bc(?:d|e)*$")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkOnePassLongPrefix(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	re := MustCompile("^abcdefghijklmnopqrstuvwxyz.*$")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkOnePassLongNotPrefix(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	re := MustCompile("^.bcdefghijklmnopqrstuvwxyz.*$")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/exec.go b/third_party/gofrontend/libgo/go/regexp/exec.go
new file mode 100644
index 0000000..c4cb201
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/exec.go
@@ -0,0 +1,452 @@
+// 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.
+
+package regexp
+
+import (
+	"io"
+	"regexp/syntax"
+)
+
+// A queue is a 'sparse array' holding pending threads of execution.
+// See http://research.swtch.com/2008/03/using-uninitialized-memory-for-fun-and.html
+type queue struct {
+	sparse []uint32
+	dense  []entry
+}
+
+// A entry is an entry on a queue.
+// It holds both the instruction pc and the actual thread.
+// Some queue entries are just place holders so that the machine
+// knows it has considered that pc.  Such entries have t == nil.
+type entry struct {
+	pc uint32
+	t  *thread
+}
+
+// A thread is the state of a single path through the machine:
+// an instruction and a corresponding capture array.
+// See http://swtch.com/~rsc/regexp/regexp2.html
+type thread struct {
+	inst *syntax.Inst
+	cap  []int
+}
+
+// A machine holds all the state during an NFA simulation for p.
+type machine struct {
+	re       *Regexp      // corresponding Regexp
+	p        *syntax.Prog // compiled program
+	op       *onePassProg // compiled onepass program, or notOnePass
+	q0, q1   queue        // two queues for runq, nextq
+	pool     []*thread    // pool of available threads
+	matched  bool         // whether a match was found
+	matchcap []int        // capture information for the match
+
+	// cached inputs, to avoid allocation
+	inputBytes  inputBytes
+	inputString inputString
+	inputReader inputReader
+}
+
+func (m *machine) newInputBytes(b []byte) input {
+	m.inputBytes.str = b
+	return &m.inputBytes
+}
+
+func (m *machine) newInputString(s string) input {
+	m.inputString.str = s
+	return &m.inputString
+}
+
+func (m *machine) newInputReader(r io.RuneReader) input {
+	m.inputReader.r = r
+	m.inputReader.atEOT = false
+	m.inputReader.pos = 0
+	return &m.inputReader
+}
+
+// progMachine returns a new machine running the prog p.
+func progMachine(p *syntax.Prog, op *onePassProg) *machine {
+	m := &machine{p: p, op: op}
+	n := len(m.p.Inst)
+	m.q0 = queue{make([]uint32, n), make([]entry, 0, n)}
+	m.q1 = queue{make([]uint32, n), make([]entry, 0, n)}
+	ncap := p.NumCap
+	if ncap < 2 {
+		ncap = 2
+	}
+	m.matchcap = make([]int, ncap)
+	return m
+}
+
+func (m *machine) init(ncap int) {
+	for _, t := range m.pool {
+		t.cap = t.cap[:ncap]
+	}
+	m.matchcap = m.matchcap[:ncap]
+}
+
+// alloc allocates a new thread with the given instruction.
+// It uses the free pool if possible.
+func (m *machine) alloc(i *syntax.Inst) *thread {
+	var t *thread
+	if n := len(m.pool); n > 0 {
+		t = m.pool[n-1]
+		m.pool = m.pool[:n-1]
+	} else {
+		t = new(thread)
+		t.cap = make([]int, len(m.matchcap), cap(m.matchcap))
+	}
+	t.inst = i
+	return t
+}
+
+// free returns t to the free pool.
+func (m *machine) free(t *thread) {
+	m.inputBytes.str = nil
+	m.inputString.str = ""
+	m.inputReader.r = nil
+	m.pool = append(m.pool, t)
+}
+
+// match runs the machine over the input starting at pos.
+// It reports whether a match was found.
+// If so, m.matchcap holds the submatch information.
+func (m *machine) match(i input, pos int) bool {
+	startCond := m.re.cond
+	if startCond == ^syntax.EmptyOp(0) { // impossible
+		return false
+	}
+	m.matched = false
+	for i := range m.matchcap {
+		m.matchcap[i] = -1
+	}
+	runq, nextq := &m.q0, &m.q1
+	r, r1 := endOfText, endOfText
+	width, width1 := 0, 0
+	r, width = i.step(pos)
+	if r != endOfText {
+		r1, width1 = i.step(pos + width)
+	}
+	var flag syntax.EmptyOp
+	if pos == 0 {
+		flag = syntax.EmptyOpContext(-1, r)
+	} else {
+		flag = i.context(pos)
+	}
+	for {
+		if len(runq.dense) == 0 {
+			if startCond&syntax.EmptyBeginText != 0 && pos != 0 {
+				// Anchored match, past beginning of text.
+				break
+			}
+			if m.matched {
+				// Have match; finished exploring alternatives.
+				break
+			}
+			if len(m.re.prefix) > 0 && r1 != m.re.prefixRune && i.canCheckPrefix() {
+				// Match requires literal prefix; fast search for it.
+				advance := i.index(m.re, pos)
+				if advance < 0 {
+					break
+				}
+				pos += advance
+				r, width = i.step(pos)
+				r1, width1 = i.step(pos + width)
+			}
+		}
+		if !m.matched {
+			if len(m.matchcap) > 0 {
+				m.matchcap[0] = pos
+			}
+			m.add(runq, uint32(m.p.Start), pos, m.matchcap, flag, nil)
+		}
+		flag = syntax.EmptyOpContext(r, r1)
+		m.step(runq, nextq, pos, pos+width, r, flag)
+		if width == 0 {
+			break
+		}
+		if len(m.matchcap) == 0 && m.matched {
+			// Found a match and not paying attention
+			// to where it is, so any match will do.
+			break
+		}
+		pos += width
+		r, width = r1, width1
+		if r != endOfText {
+			r1, width1 = i.step(pos + width)
+		}
+		runq, nextq = nextq, runq
+	}
+	m.clear(nextq)
+	return m.matched
+}
+
+// clear frees all threads on the thread queue.
+func (m *machine) clear(q *queue) {
+	for _, d := range q.dense {
+		if d.t != nil {
+			// m.free(d.t)
+			m.pool = append(m.pool, d.t)
+		}
+	}
+	q.dense = q.dense[:0]
+}
+
+// step executes one step of the machine, running each of the threads
+// on runq and appending new threads to nextq.
+// The step processes the rune c (which may be endOfText),
+// which starts at position pos and ends at nextPos.
+// nextCond gives the setting for the empty-width flags after c.
+func (m *machine) step(runq, nextq *queue, pos, nextPos int, c rune, nextCond syntax.EmptyOp) {
+	longest := m.re.longest
+	for j := 0; j < len(runq.dense); j++ {
+		d := &runq.dense[j]
+		t := d.t
+		if t == nil {
+			continue
+		}
+		if longest && m.matched && len(t.cap) > 0 && m.matchcap[0] < t.cap[0] {
+			// m.free(t)
+			m.pool = append(m.pool, t)
+			continue
+		}
+		i := t.inst
+		add := false
+		switch i.Op {
+		default:
+			panic("bad inst")
+
+		case syntax.InstMatch:
+			if len(t.cap) > 0 && (!longest || !m.matched || m.matchcap[1] < pos) {
+				t.cap[1] = pos
+				copy(m.matchcap, t.cap)
+			}
+			if !longest {
+				// First-match mode: cut off all lower-priority threads.
+				for _, d := range runq.dense[j+1:] {
+					if d.t != nil {
+						// m.free(d.t)
+						m.pool = append(m.pool, d.t)
+					}
+				}
+				runq.dense = runq.dense[:0]
+			}
+			m.matched = true
+
+		case syntax.InstRune:
+			add = i.MatchRune(c)
+		case syntax.InstRune1:
+			add = c == i.Rune[0]
+		case syntax.InstRuneAny:
+			add = true
+		case syntax.InstRuneAnyNotNL:
+			add = c != '\n'
+		}
+		if add {
+			t = m.add(nextq, i.Out, nextPos, t.cap, nextCond, t)
+		}
+		if t != nil {
+			// m.free(t)
+			m.pool = append(m.pool, t)
+		}
+	}
+	runq.dense = runq.dense[:0]
+}
+
+// add adds an entry to q for pc, unless the q already has such an entry.
+// It also recursively adds an entry for all instructions reachable from pc by following
+// empty-width conditions satisfied by cond.  pos gives the current position
+// in the input.
+func (m *machine) add(q *queue, pc uint32, pos int, cap []int, cond syntax.EmptyOp, t *thread) *thread {
+	if pc == 0 {
+		return t
+	}
+	if j := q.sparse[pc]; j < uint32(len(q.dense)) && q.dense[j].pc == pc {
+		return t
+	}
+
+	j := len(q.dense)
+	q.dense = q.dense[:j+1]
+	d := &q.dense[j]
+	d.t = nil
+	d.pc = pc
+	q.sparse[pc] = uint32(j)
+
+	i := &m.p.Inst[pc]
+	switch i.Op {
+	default:
+		panic("unhandled")
+	case syntax.InstFail:
+		// nothing
+	case syntax.InstAlt, syntax.InstAltMatch:
+		t = m.add(q, i.Out, pos, cap, cond, t)
+		t = m.add(q, i.Arg, pos, cap, cond, t)
+	case syntax.InstEmptyWidth:
+		if syntax.EmptyOp(i.Arg)&^cond == 0 {
+			t = m.add(q, i.Out, pos, cap, cond, t)
+		}
+	case syntax.InstNop:
+		t = m.add(q, i.Out, pos, cap, cond, t)
+	case syntax.InstCapture:
+		if int(i.Arg) < len(cap) {
+			opos := cap[i.Arg]
+			cap[i.Arg] = pos
+			m.add(q, i.Out, pos, cap, cond, nil)
+			cap[i.Arg] = opos
+		} else {
+			t = m.add(q, i.Out, pos, cap, cond, t)
+		}
+	case syntax.InstMatch, syntax.InstRune, syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
+		if t == nil {
+			t = m.alloc(i)
+		} else {
+			t.inst = i
+		}
+		if len(cap) > 0 && &t.cap[0] != &cap[0] {
+			copy(t.cap, cap)
+		}
+		d.t = t
+		t = nil
+	}
+	return t
+}
+
+// onepass runs the machine over the input starting at pos.
+// It reports whether a match was found.
+// If so, m.matchcap holds the submatch information.
+func (m *machine) onepass(i input, pos int) bool {
+	startCond := m.re.cond
+	if startCond == ^syntax.EmptyOp(0) { // impossible
+		return false
+	}
+	m.matched = false
+	for i := range m.matchcap {
+		m.matchcap[i] = -1
+	}
+	r, r1 := endOfText, endOfText
+	width, width1 := 0, 0
+	r, width = i.step(pos)
+	if r != endOfText {
+		r1, width1 = i.step(pos + width)
+	}
+	var flag syntax.EmptyOp
+	if pos == 0 {
+		flag = syntax.EmptyOpContext(-1, r)
+	} else {
+		flag = i.context(pos)
+	}
+	pc := m.op.Start
+	inst := m.op.Inst[pc]
+	// If there is a simple literal prefix, skip over it.
+	if pos == 0 && syntax.EmptyOp(inst.Arg)&^flag == 0 &&
+		len(m.re.prefix) > 0 && i.canCheckPrefix() {
+		// Match requires literal prefix; fast search for it.
+		if i.hasPrefix(m.re) {
+			pos += len(m.re.prefix)
+			r, width = i.step(pos)
+			r1, width1 = i.step(pos + width)
+			flag = i.context(pos)
+			pc = int(m.re.prefixEnd)
+		} else {
+			return m.matched
+		}
+	}
+	for {
+		inst = m.op.Inst[pc]
+		pc = int(inst.Out)
+		switch inst.Op {
+		default:
+			panic("bad inst")
+		case syntax.InstMatch:
+			m.matched = true
+			if len(m.matchcap) > 0 {
+				m.matchcap[0] = 0
+				m.matchcap[1] = pos
+			}
+			return m.matched
+		case syntax.InstRune:
+			if !inst.MatchRune(r) {
+				return m.matched
+			}
+		case syntax.InstRune1:
+			if r != inst.Rune[0] {
+				return m.matched
+			}
+		case syntax.InstRuneAny:
+			// Nothing
+		case syntax.InstRuneAnyNotNL:
+			if r == '\n' {
+				return m.matched
+			}
+		// peek at the input rune to see which branch of the Alt to take
+		case syntax.InstAlt, syntax.InstAltMatch:
+			pc = int(onePassNext(&inst, r))
+			continue
+		case syntax.InstFail:
+			return m.matched
+		case syntax.InstNop:
+			continue
+		case syntax.InstEmptyWidth:
+			if syntax.EmptyOp(inst.Arg)&^flag != 0 {
+				return m.matched
+			}
+			continue
+		case syntax.InstCapture:
+			if int(inst.Arg) < len(m.matchcap) {
+				m.matchcap[inst.Arg] = pos
+			}
+			continue
+		}
+		if width == 0 {
+			break
+		}
+		flag = syntax.EmptyOpContext(r, r1)
+		pos += width
+		r, width = r1, width1
+		if r != endOfText {
+			r1, width1 = i.step(pos + width)
+		}
+	}
+	return m.matched
+}
+
+// empty is a non-nil 0-element slice,
+// so doExecute can avoid an allocation
+// when 0 captures are requested from a successful match.
+var empty = make([]int, 0)
+
+// doExecute finds the leftmost match in the input and returns
+// the position of its subexpressions.
+func (re *Regexp) doExecute(r io.RuneReader, b []byte, s string, pos int, ncap int) []int {
+	m := re.get()
+	var i input
+	if r != nil {
+		i = m.newInputReader(r)
+	} else if b != nil {
+		i = m.newInputBytes(b)
+	} else {
+		i = m.newInputString(s)
+	}
+	if m.op != notOnePass {
+		if !m.onepass(i, pos) {
+			re.put(m)
+			return nil
+		}
+	} else {
+		m.init(ncap)
+		if !m.match(i, pos) {
+			re.put(m)
+			return nil
+		}
+	}
+	if ncap == 0 {
+		re.put(m)
+		return empty // empty but not nil
+	}
+	cap := make([]int, len(m.matchcap))
+	copy(cap, m.matchcap)
+	re.put(m)
+	return cap
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/exec2_test.go b/third_party/gofrontend/libgo/go/regexp/exec2_test.go
new file mode 100644
index 0000000..7b86b41
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/exec2_test.go
@@ -0,0 +1,20 @@
+// Copyright 2013 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.
+
+// +build !race
+
+package regexp
+
+import (
+	"testing"
+)
+
+// This test is excluded when running under the race detector because
+// it is a very expensive test and takes too long.
+func TestRE2Exhaustive(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping TestRE2Exhaustive during short test")
+	}
+	testRE2(t, "testdata/re2-exhaustive.txt.bz2")
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/exec_test.go b/third_party/gofrontend/libgo/go/regexp/exec_test.go
new file mode 100644
index 0000000..70d069c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/exec_test.go
@@ -0,0 +1,715 @@
+// Copyright 2010 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 regexp
+
+import (
+	"bufio"
+	"compress/bzip2"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"regexp/syntax"
+	"strconv"
+	"strings"
+	"testing"
+	"unicode/utf8"
+)
+
+// TestRE2 tests this package's regexp API against test cases
+// considered during RE2's exhaustive tests, which run all possible
+// regexps over a given set of atoms and operators, up to a given
+// complexity, over all possible strings over a given alphabet,
+// up to a given size.  Rather than try to link with RE2, we read a
+// log file containing the test cases and the expected matches.
+// The log file, re2.txt, is generated by running 'make exhaustive-log'
+// in the open source RE2 distribution.  http://code.google.com/p/re2/
+//
+// The test file format is a sequence of stanzas like:
+//
+//	strings
+//	"abc"
+//	"123x"
+//	regexps
+//	"[a-z]+"
+//	0-3;0-3
+//	-;-
+//	"([0-9])([0-9])([0-9])"
+//	-;-
+//	-;0-3 0-1 1-2 2-3
+//
+// The stanza begins by defining a set of strings, quoted
+// using Go double-quote syntax, one per line.  Then the
+// regexps section gives a sequence of regexps to run on
+// the strings.  In the block that follows a regexp, each line
+// gives the semicolon-separated match results of running
+// the regexp on the corresponding string.
+// Each match result is either a single -, meaning no match, or a
+// space-separated sequence of pairs giving the match and
+// submatch indices.  An unmatched subexpression formats
+// its pair as a single - (not illustrated above).  For now
+// each regexp run produces two match results, one for a
+// ``full match'' that restricts the regexp to matching the entire
+// string or nothing, and one for a ``partial match'' that gives
+// the leftmost first match found in the string.
+//
+// Lines beginning with # are comments.  Lines beginning with
+// a capital letter are test names printed during RE2's test suite
+// and are echoed into t but otherwise ignored.
+//
+// At time of writing, re2.txt is 32 MB but compresses to 760 kB,
+// so we store re2.txt.gz in the repository and decompress it on the fly.
+//
+func TestRE2Search(t *testing.T) {
+	testRE2(t, "testdata/re2-search.txt")
+}
+
+func testRE2(t *testing.T, file string) {
+	f, err := os.Open(file)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer f.Close()
+	var txt io.Reader
+	if strings.HasSuffix(file, ".bz2") {
+		z := bzip2.NewReader(f)
+		txt = z
+		file = file[:len(file)-len(".bz2")] // for error messages
+	} else {
+		txt = f
+	}
+	lineno := 0
+	scanner := bufio.NewScanner(txt)
+	var (
+		str       []string
+		input     []string
+		inStrings bool
+		re        *Regexp
+		refull    *Regexp
+		nfail     int
+		ncase     int
+	)
+	for lineno := 1; scanner.Scan(); lineno++ {
+		line := scanner.Text()
+		switch {
+		case line == "":
+			t.Fatalf("%s:%d: unexpected blank line", file, lineno)
+		case line[0] == '#':
+			continue
+		case 'A' <= line[0] && line[0] <= 'Z':
+			// Test name.
+			t.Logf("%s\n", line)
+			continue
+		case line == "strings":
+			str = str[:0]
+			inStrings = true
+		case line == "regexps":
+			inStrings = false
+		case line[0] == '"':
+			q, err := strconv.Unquote(line)
+			if err != nil {
+				// Fatal because we'll get out of sync.
+				t.Fatalf("%s:%d: unquote %s: %v", file, lineno, line, err)
+			}
+			if inStrings {
+				str = append(str, q)
+				continue
+			}
+			// Is a regexp.
+			if len(input) != 0 {
+				t.Fatalf("%s:%d: out of sync: have %d strings left before %#q", file, lineno, len(input), q)
+			}
+			re, err = tryCompile(q)
+			if err != nil {
+				if err.Error() == "error parsing regexp: invalid escape sequence: `\\C`" {
+					// We don't and likely never will support \C; keep going.
+					continue
+				}
+				t.Errorf("%s:%d: compile %#q: %v", file, lineno, q, err)
+				if nfail++; nfail >= 100 {
+					t.Fatalf("stopping after %d errors", nfail)
+				}
+				continue
+			}
+			full := `\A(?:` + q + `)\z`
+			refull, err = tryCompile(full)
+			if err != nil {
+				// Fatal because q worked, so this should always work.
+				t.Fatalf("%s:%d: compile full %#q: %v", file, lineno, full, err)
+			}
+			input = str
+		case line[0] == '-' || '0' <= line[0] && line[0] <= '9':
+			// A sequence of match results.
+			ncase++
+			if re == nil {
+				// Failed to compile: skip results.
+				continue
+			}
+			if len(input) == 0 {
+				t.Fatalf("%s:%d: out of sync: no input remaining", file, lineno)
+			}
+			var text string
+			text, input = input[0], input[1:]
+			if !isSingleBytes(text) && strings.Contains(re.String(), `\B`) {
+				// RE2's \B considers every byte position,
+				// so it sees 'not word boundary' in the
+				// middle of UTF-8 sequences.  This package
+				// only considers the positions between runes,
+				// so it disagrees.  Skip those cases.
+				continue
+			}
+			res := strings.Split(line, ";")
+			if len(res) != len(run) {
+				t.Fatalf("%s:%d: have %d test results, want %d", file, lineno, len(res), len(run))
+			}
+			for i := range res {
+				have, suffix := run[i](re, refull, text)
+				want := parseResult(t, file, lineno, res[i])
+				if !same(have, want) {
+					t.Errorf("%s:%d: %#q%s.FindSubmatchIndex(%#q) = %v, want %v", file, lineno, re, suffix, text, have, want)
+					if nfail++; nfail >= 100 {
+						t.Fatalf("stopping after %d errors", nfail)
+					}
+					continue
+				}
+				b, suffix := match[i](re, refull, text)
+				if b != (want != nil) {
+					t.Errorf("%s:%d: %#q%s.MatchString(%#q) = %v, want %v", file, lineno, re, suffix, text, b, !b)
+					if nfail++; nfail >= 100 {
+						t.Fatalf("stopping after %d errors", nfail)
+					}
+					continue
+				}
+			}
+
+		default:
+			t.Fatalf("%s:%d: out of sync: %s\n", file, lineno, line)
+		}
+	}
+	if err := scanner.Err(); err != nil {
+		t.Fatalf("%s:%d: %v", file, lineno, err)
+	}
+	if len(input) != 0 {
+		t.Fatalf("%s:%d: out of sync: have %d strings left at EOF", file, lineno, len(input))
+	}
+	t.Logf("%d cases tested", ncase)
+}
+
+var run = []func(*Regexp, *Regexp, string) ([]int, string){
+	runFull,
+	runPartial,
+	runFullLongest,
+	runPartialLongest,
+}
+
+func runFull(re, refull *Regexp, text string) ([]int, string) {
+	refull.longest = false
+	return refull.FindStringSubmatchIndex(text), "[full]"
+}
+
+func runPartial(re, refull *Regexp, text string) ([]int, string) {
+	re.longest = false
+	return re.FindStringSubmatchIndex(text), ""
+}
+
+func runFullLongest(re, refull *Regexp, text string) ([]int, string) {
+	refull.longest = true
+	return refull.FindStringSubmatchIndex(text), "[full,longest]"
+}
+
+func runPartialLongest(re, refull *Regexp, text string) ([]int, string) {
+	re.longest = true
+	return re.FindStringSubmatchIndex(text), "[longest]"
+}
+
+var match = []func(*Regexp, *Regexp, string) (bool, string){
+	matchFull,
+	matchPartial,
+	matchFullLongest,
+	matchPartialLongest,
+}
+
+func matchFull(re, refull *Regexp, text string) (bool, string) {
+	refull.longest = false
+	return refull.MatchString(text), "[full]"
+}
+
+func matchPartial(re, refull *Regexp, text string) (bool, string) {
+	re.longest = false
+	return re.MatchString(text), ""
+}
+
+func matchFullLongest(re, refull *Regexp, text string) (bool, string) {
+	refull.longest = true
+	return refull.MatchString(text), "[full,longest]"
+}
+
+func matchPartialLongest(re, refull *Regexp, text string) (bool, string) {
+	re.longest = true
+	return re.MatchString(text), "[longest]"
+}
+
+func isSingleBytes(s string) bool {
+	for _, c := range s {
+		if c >= utf8.RuneSelf {
+			return false
+		}
+	}
+	return true
+}
+
+func tryCompile(s string) (re *Regexp, err error) {
+	// Protect against panic during Compile.
+	defer func() {
+		if r := recover(); r != nil {
+			err = fmt.Errorf("panic: %v", r)
+		}
+	}()
+	return Compile(s)
+}
+
+func parseResult(t *testing.T, file string, lineno int, res string) []int {
+	// A single - indicates no match.
+	if res == "-" {
+		return nil
+	}
+	// Otherwise, a space-separated list of pairs.
+	n := 1
+	for j := 0; j < len(res); j++ {
+		if res[j] == ' ' {
+			n++
+		}
+	}
+	out := make([]int, 2*n)
+	i := 0
+	n = 0
+	for j := 0; j <= len(res); j++ {
+		if j == len(res) || res[j] == ' ' {
+			// Process a single pair.  - means no submatch.
+			pair := res[i:j]
+			if pair == "-" {
+				out[n] = -1
+				out[n+1] = -1
+			} else {
+				k := strings.Index(pair, "-")
+				if k < 0 {
+					t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair)
+				}
+				lo, err1 := strconv.Atoi(pair[:k])
+				hi, err2 := strconv.Atoi(pair[k+1:])
+				if err1 != nil || err2 != nil || lo > hi {
+					t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair)
+				}
+				out[n] = lo
+				out[n+1] = hi
+			}
+			n += 2
+			i = j + 1
+		}
+	}
+	return out
+}
+
+func same(x, y []int) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, xi := range x {
+		if xi != y[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// TestFowler runs this package's regexp API against the
+// POSIX regular expression tests collected by Glenn Fowler
+// at http://www2.research.att.com/~gsf/testregex/.
+func TestFowler(t *testing.T) {
+	files, err := filepath.Glob("testdata/*.dat")
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, file := range files {
+		t.Log(file)
+		testFowler(t, file)
+	}
+}
+
+var notab = MustCompilePOSIX(`[^\t]+`)
+
+func testFowler(t *testing.T, file string) {
+	f, err := os.Open(file)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	defer f.Close()
+	b := bufio.NewReader(f)
+	lineno := 0
+	lastRegexp := ""
+Reading:
+	for {
+		lineno++
+		line, err := b.ReadString('\n')
+		if err != nil {
+			if err != io.EOF {
+				t.Errorf("%s:%d: %v", file, lineno, err)
+			}
+			break Reading
+		}
+
+		// http://www2.research.att.com/~gsf/man/man1/testregex.html
+		//
+		// INPUT FORMAT
+		//   Input lines may be blank, a comment beginning with #, or a test
+		//   specification. A specification is five fields separated by one
+		//   or more tabs. NULL denotes the empty string and NIL denotes the
+		//   0 pointer.
+		if line[0] == '#' || line[0] == '\n' {
+			continue Reading
+		}
+		line = line[:len(line)-1]
+		field := notab.FindAllString(line, -1)
+		for i, f := range field {
+			if f == "NULL" {
+				field[i] = ""
+			}
+			if f == "NIL" {
+				t.Logf("%s:%d: skip: %s", file, lineno, line)
+				continue Reading
+			}
+		}
+		if len(field) == 0 {
+			continue Reading
+		}
+
+		//   Field 1: the regex(3) flags to apply, one character per REG_feature
+		//   flag. The test is skipped if REG_feature is not supported by the
+		//   implementation. If the first character is not [BEASKLP] then the
+		//   specification is a global control line. One or more of [BEASKLP] may be
+		//   specified; the test will be repeated for each mode.
+		//
+		//     B 	basic			BRE	(grep, ed, sed)
+		//     E 	REG_EXTENDED		ERE	(egrep)
+		//     A	REG_AUGMENTED		ARE	(egrep with negation)
+		//     S	REG_SHELL		SRE	(sh glob)
+		//     K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)
+		//     L	REG_LITERAL		LRE	(fgrep)
+		//
+		//     a	REG_LEFT|REG_RIGHT	implicit ^...$
+		//     b	REG_NOTBOL		lhs does not match ^
+		//     c	REG_COMMENT		ignore space and #...\n
+		//     d	REG_SHELL_DOT		explicit leading . match
+		//     e	REG_NOTEOL		rhs does not match $
+		//     f	REG_MULTIPLE		multiple \n separated patterns
+		//     g	FNM_LEADING_DIR		testfnmatch only -- match until /
+		//     h	REG_MULTIREF		multiple digit backref
+		//     i	REG_ICASE		ignore case
+		//     j	REG_SPAN		. matches \n
+		//     k	REG_ESCAPE		\ to ecape [...] delimiter
+		//     l	REG_LEFT		implicit ^...
+		//     m	REG_MINIMAL		minimal match
+		//     n	REG_NEWLINE		explicit \n match
+		//     o	REG_ENCLOSED		(|&) magic inside [@|&](...)
+		//     p	REG_SHELL_PATH		explicit / match
+		//     q	REG_DELIMITED		delimited pattern
+		//     r	REG_RIGHT		implicit ...$
+		//     s	REG_SHELL_ESCAPED	\ not special
+		//     t	REG_MUSTDELIM		all delimiters must be specified
+		//     u	standard unspecified behavior -- errors not counted
+		//     v	REG_CLASS_ESCAPE	\ special inside [...]
+		//     w	REG_NOSUB		no subexpression match array
+		//     x	REG_LENIENT		let some errors slide
+		//     y	REG_LEFT		regexec() implicit ^...
+		//     z	REG_NULL		NULL subexpressions ok
+		//     $	                        expand C \c escapes in fields 2 and 3
+		//     /	                        field 2 is a regsubcomp() expression
+		//     =	                        field 3 is a regdecomp() expression
+		//
+		//   Field 1 control lines:
+		//
+		//     C		set LC_COLLATE and LC_CTYPE to locale in field 2
+		//
+		//     ?test ...	output field 5 if passed and != EXPECTED, silent otherwise
+		//     &test ...	output field 5 if current and previous passed
+		//     |test ...	output field 5 if current passed and previous failed
+		//     ; ...	output field 2 if previous failed
+		//     {test ...	skip if failed until }
+		//     }		end of skip
+		//
+		//     : comment		comment copied as output NOTE
+		//     :comment:test	:comment: ignored
+		//     N[OTE] comment	comment copied as output NOTE
+		//     T[EST] comment	comment
+		//
+		//     number		use number for nmatch (20 by default)
+		flag := field[0]
+		switch flag[0] {
+		case '?', '&', '|', ';', '{', '}':
+			// Ignore all the control operators.
+			// Just run everything.
+			flag = flag[1:]
+			if flag == "" {
+				continue Reading
+			}
+		case ':':
+			i := strings.Index(flag[1:], ":")
+			if i < 0 {
+				t.Logf("skip: %s", line)
+				continue Reading
+			}
+			flag = flag[1+i+1:]
+		case 'C', 'N', 'T', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			t.Logf("skip: %s", line)
+			continue Reading
+		}
+
+		// Can check field count now that we've handled the myriad comment formats.
+		if len(field) < 4 {
+			t.Errorf("%s:%d: too few fields: %s", file, lineno, line)
+			continue Reading
+		}
+
+		// Expand C escapes (a.k.a. Go escapes).
+		if strings.Contains(flag, "$") {
+			f := `"` + field[1] + `"`
+			if field[1], err = strconv.Unquote(f); err != nil {
+				t.Errorf("%s:%d: cannot unquote %s", file, lineno, f)
+			}
+			f = `"` + field[2] + `"`
+			if field[2], err = strconv.Unquote(f); err != nil {
+				t.Errorf("%s:%d: cannot unquote %s", file, lineno, f)
+			}
+		}
+
+		//   Field 2: the regular expression pattern; SAME uses the pattern from
+		//     the previous specification.
+		//
+		if field[1] == "SAME" {
+			field[1] = lastRegexp
+		}
+		lastRegexp = field[1]
+
+		//   Field 3: the string to match.
+		text := field[2]
+
+		//   Field 4: the test outcome...
+		ok, shouldCompile, shouldMatch, pos := parseFowlerResult(field[3])
+		if !ok {
+			t.Errorf("%s:%d: cannot parse result %#q", file, lineno, field[3])
+			continue Reading
+		}
+
+		//   Field 5: optional comment appended to the report.
+
+	Testing:
+		// Run test once for each specified capital letter mode that we support.
+		for _, c := range flag {
+			pattern := field[1]
+			syn := syntax.POSIX | syntax.ClassNL
+			switch c {
+			default:
+				continue Testing
+			case 'E':
+				// extended regexp (what we support)
+			case 'L':
+				// literal
+				pattern = QuoteMeta(pattern)
+			}
+
+			for _, c := range flag {
+				switch c {
+				case 'i':
+					syn |= syntax.FoldCase
+				}
+			}
+
+			re, err := compile(pattern, syn, true)
+			if err != nil {
+				if shouldCompile {
+					t.Errorf("%s:%d: %#q did not compile", file, lineno, pattern)
+				}
+				continue Testing
+			}
+			if !shouldCompile {
+				t.Errorf("%s:%d: %#q should not compile", file, lineno, pattern)
+				continue Testing
+			}
+			match := re.MatchString(text)
+			if match != shouldMatch {
+				t.Errorf("%s:%d: %#q.Match(%#q) = %v, want %v", file, lineno, pattern, text, match, shouldMatch)
+				continue Testing
+			}
+			have := re.FindStringSubmatchIndex(text)
+			if (len(have) > 0) != match {
+				t.Errorf("%s:%d: %#q.Match(%#q) = %v, but %#q.FindSubmatchIndex(%#q) = %v", file, lineno, pattern, text, match, pattern, text, have)
+				continue Testing
+			}
+			if len(have) > len(pos) {
+				have = have[:len(pos)]
+			}
+			if !same(have, pos) {
+				t.Errorf("%s:%d: %#q.FindSubmatchIndex(%#q) = %v, want %v", file, lineno, pattern, text, have, pos)
+			}
+		}
+	}
+}
+
+func parseFowlerResult(s string) (ok, compiled, matched bool, pos []int) {
+	//   Field 4: the test outcome. This is either one of the posix error
+	//     codes (with REG_ omitted) or the match array, a list of (m,n)
+	//     entries with m and n being first and last+1 positions in the
+	//     field 3 string, or NULL if REG_NOSUB is in effect and success
+	//     is expected. BADPAT is acceptable in place of any regcomp(3)
+	//     error code. The match[] array is initialized to (-2,-2) before
+	//     each test. All array elements from 0 to nmatch-1 must be specified
+	//     in the outcome. Unspecified endpoints (offset -1) are denoted by ?.
+	//     Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a
+	//     matched (?{...}) expression, where x is the text enclosed by {...},
+	//     o is the expression ordinal counting from 1, and n is the length of
+	//     the unmatched portion of the subject string. If x starts with a
+	//     number then that is the return value of re_execf(), otherwise 0 is
+	//     returned.
+	switch {
+	case s == "":
+		// Match with no position information.
+		ok = true
+		compiled = true
+		matched = true
+		return
+	case s == "NOMATCH":
+		// Match failure.
+		ok = true
+		compiled = true
+		matched = false
+		return
+	case 'A' <= s[0] && s[0] <= 'Z':
+		// All the other error codes are compile errors.
+		ok = true
+		compiled = false
+		return
+	}
+	compiled = true
+
+	var x []int
+	for s != "" {
+		var end byte = ')'
+		if len(x)%2 == 0 {
+			if s[0] != '(' {
+				ok = false
+				return
+			}
+			s = s[1:]
+			end = ','
+		}
+		i := 0
+		for i < len(s) && s[i] != end {
+			i++
+		}
+		if i == 0 || i == len(s) {
+			ok = false
+			return
+		}
+		var v = -1
+		var err error
+		if s[:i] != "?" {
+			v, err = strconv.Atoi(s[:i])
+			if err != nil {
+				ok = false
+				return
+			}
+		}
+		x = append(x, v)
+		s = s[i+1:]
+	}
+	if len(x)%2 != 0 {
+		ok = false
+		return
+	}
+	ok = true
+	matched = true
+	pos = x
+	return
+}
+
+var text []byte
+
+func makeText(n int) []byte {
+	if len(text) >= n {
+		return text[:n]
+	}
+	text = make([]byte, n)
+	x := ^uint32(0)
+	for i := range text {
+		x += x
+		x ^= 1
+		if int32(x) < 0 {
+			x ^= 0x88888eef
+		}
+		if x%31 == 0 {
+			text[i] = '\n'
+		} else {
+			text[i] = byte(x%(0x7E+1-0x20) + 0x20)
+		}
+	}
+	return text
+}
+
+func benchmark(b *testing.B, re string, n int) {
+	r := MustCompile(re)
+	t := makeText(n)
+	b.ResetTimer()
+	b.SetBytes(int64(n))
+	for i := 0; i < b.N; i++ {
+		if r.Match(t) {
+			b.Fatal("match!")
+		}
+	}
+}
+
+const (
+	easy0  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+	easy1  = "A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$"
+	medium = "[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+	hard   = "[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+	parens = "([ -~])*(A)(B)(C)(D)(E)(F)(G)(H)(I)(J)(K)(L)(M)" +
+		"(N)(O)(P)(Q)(R)(S)(T)(U)(V)(W)(X)(Y)(Z)$"
+)
+
+func BenchmarkMatchEasy0_32(b *testing.B)   { benchmark(b, easy0, 32<<0) }
+func BenchmarkMatchEasy0_1K(b *testing.B)   { benchmark(b, easy0, 1<<10) }
+func BenchmarkMatchEasy0_32K(b *testing.B)  { benchmark(b, easy0, 32<<10) }
+func BenchmarkMatchEasy0_1M(b *testing.B)   { benchmark(b, easy0, 1<<20) }
+func BenchmarkMatchEasy0_32M(b *testing.B)  { benchmark(b, easy0, 32<<20) }
+func BenchmarkMatchEasy1_32(b *testing.B)   { benchmark(b, easy1, 32<<0) }
+func BenchmarkMatchEasy1_1K(b *testing.B)   { benchmark(b, easy1, 1<<10) }
+func BenchmarkMatchEasy1_32K(b *testing.B)  { benchmark(b, easy1, 32<<10) }
+func BenchmarkMatchEasy1_1M(b *testing.B)   { benchmark(b, easy1, 1<<20) }
+func BenchmarkMatchEasy1_32M(b *testing.B)  { benchmark(b, easy1, 32<<20) }
+func BenchmarkMatchMedium_32(b *testing.B)  { benchmark(b, medium, 32<<0) }
+func BenchmarkMatchMedium_1K(b *testing.B)  { benchmark(b, medium, 1<<10) }
+func BenchmarkMatchMedium_32K(b *testing.B) { benchmark(b, medium, 32<<10) }
+func BenchmarkMatchMedium_1M(b *testing.B)  { benchmark(b, medium, 1<<20) }
+func BenchmarkMatchMedium_32M(b *testing.B) { benchmark(b, medium, 32<<20) }
+func BenchmarkMatchHard_32(b *testing.B)    { benchmark(b, hard, 32<<0) }
+func BenchmarkMatchHard_1K(b *testing.B)    { benchmark(b, hard, 1<<10) }
+func BenchmarkMatchHard_32K(b *testing.B)   { benchmark(b, hard, 32<<10) }
+func BenchmarkMatchHard_1M(b *testing.B)    { benchmark(b, hard, 1<<20) }
+func BenchmarkMatchHard_32M(b *testing.B)   { benchmark(b, hard, 32<<20) }
+
+func TestLongest(t *testing.T) {
+	re, err := Compile(`a(|b)`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, w := re.FindString("ab"), "a"; g != w {
+		t.Errorf("first match was %q, want %q", g, w)
+	}
+	re.Longest()
+	if g, w := re.FindString("ab"), "ab"; g != w {
+		t.Errorf("longest match was %q, want %q", g, w)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/find_test.go b/third_party/gofrontend/libgo/go/regexp/find_test.go
new file mode 100644
index 0000000..e07eb7d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/find_test.go
@@ -0,0 +1,498 @@
+// Copyright 2010 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 regexp
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+)
+
+// For each pattern/text pair, what is the expected output of each function?
+// We can derive the textual results from the indexed results, the non-submatch
+// results from the submatched results, the single results from the 'all' results,
+// and the byte results from the string results. Therefore the table includes
+// only the FindAllStringSubmatchIndex result.
+type FindTest struct {
+	pat     string
+	text    string
+	matches [][]int
+}
+
+func (t FindTest) String() string {
+	return fmt.Sprintf("pat: %#q text: %#q", t.pat, t.text)
+}
+
+var findTests = []FindTest{
+	{``, ``, build(1, 0, 0)},
+	{`^abcdefg`, "abcdefg", build(1, 0, 7)},
+	{`a+`, "baaab", build(1, 1, 4)},
+	{"abcd..", "abcdef", build(1, 0, 6)},
+	{`a`, "a", build(1, 0, 1)},
+	{`x`, "y", nil},
+	{`b`, "abc", build(1, 1, 2)},
+	{`.`, "a", build(1, 0, 1)},
+	{`.*`, "abcdef", build(1, 0, 6)},
+	{`^`, "abcde", build(1, 0, 0)},
+	{`$`, "abcde", build(1, 5, 5)},
+	{`^abcd$`, "abcd", build(1, 0, 4)},
+	{`^bcd'`, "abcdef", nil},
+	{`^abcd$`, "abcde", nil},
+	{`a+`, "baaab", build(1, 1, 4)},
+	{`a*`, "baaab", build(3, 0, 0, 1, 4, 5, 5)},
+	{`[a-z]+`, "abcd", build(1, 0, 4)},
+	{`[^a-z]+`, "ab1234cd", build(1, 2, 6)},
+	{`[a\-\]z]+`, "az]-bcz", build(2, 0, 4, 6, 7)},
+	{`[^\n]+`, "abcd\n", build(1, 0, 4)},
+	{`[日本語]+`, "日本語日本語", build(1, 0, 18)},
+	{`日本語+`, "日本語", build(1, 0, 9)},
+	{`日本語+`, "日本語語語語", build(1, 0, 18)},
+	{`()`, "", build(1, 0, 0, 0, 0)},
+	{`(a)`, "a", build(1, 0, 1, 0, 1)},
+	{`(.)(.)`, "日a", build(1, 0, 4, 0, 3, 3, 4)},
+	{`(.*)`, "", build(1, 0, 0, 0, 0)},
+	{`(.*)`, "abcd", build(1, 0, 4, 0, 4)},
+	{`(..)(..)`, "abcd", build(1, 0, 4, 0, 2, 2, 4)},
+	{`(([^xyz]*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 3, 4)},
+	{`((a|b|c)*(d))`, "abcd", build(1, 0, 4, 0, 4, 2, 3, 3, 4)},
+	{`(((a|b|c)*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)},
+	{`\a\f\n\r\t\v`, "\a\f\n\r\t\v", build(1, 0, 6)},
+	{`[\a\f\n\r\t\v]+`, "\a\f\n\r\t\v", build(1, 0, 6)},
+
+	{`a*(|(b))c*`, "aacc", build(1, 0, 4, 2, 2, -1, -1)},
+	{`(.*).*`, "ab", build(1, 0, 2, 0, 2)},
+	{`[.]`, ".", build(1, 0, 1)},
+	{`/$`, "/abc/", build(1, 4, 5)},
+	{`/$`, "/abc", nil},
+
+	// multiple matches
+	{`.`, "abc", build(3, 0, 1, 1, 2, 2, 3)},
+	{`(.)`, "abc", build(3, 0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 2, 3)},
+	{`.(.)`, "abcd", build(2, 0, 2, 1, 2, 2, 4, 3, 4)},
+	{`ab*`, "abbaab", build(3, 0, 3, 3, 4, 4, 6)},
+	{`a(b*)`, "abbaab", build(3, 0, 3, 1, 3, 3, 4, 4, 4, 4, 6, 5, 6)},
+
+	// fixed bugs
+	{`ab$`, "cab", build(1, 1, 3)},
+	{`axxb$`, "axxcb", nil},
+	{`data`, "daXY data", build(1, 5, 9)},
+	{`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)},
+	{`zx+`, "zzx", build(1, 1, 3)},
+	{`ab$`, "abcab", build(1, 3, 5)},
+	{`(aa)*$`, "a", build(1, 1, 1, -1, -1)},
+	{`(?:.|(?:.a))`, "", nil},
+	{`(?:A(?:A|a))`, "Aa", build(1, 0, 2)},
+	{`(?:A|(?:A|a))`, "a", build(1, 0, 1)},
+	{`(a){0}`, "", build(1, 0, 0, -1, -1)},
+	{`(?-s)(?:(?:^).)`, "\n", nil},
+	{`(?s)(?:(?:^).)`, "\n", build(1, 0, 1)},
+	{`(?:(?:^).)`, "\n", nil},
+	{`\b`, "x", build(2, 0, 0, 1, 1)},
+	{`\b`, "xx", build(2, 0, 0, 2, 2)},
+	{`\b`, "x y", build(4, 0, 0, 1, 1, 2, 2, 3, 3)},
+	{`\b`, "xx yy", build(4, 0, 0, 2, 2, 3, 3, 5, 5)},
+	{`\B`, "x", nil},
+	{`\B`, "xx", build(1, 1, 1)},
+	{`\B`, "x y", nil},
+	{`\B`, "xx yy", build(2, 1, 1, 4, 4)},
+
+	// RE2 tests
+	{`[^\S\s]`, "abcd", nil},
+	{`[^\S[:space:]]`, "abcd", nil},
+	{`[^\D\d]`, "abcd", nil},
+	{`[^\D[:digit:]]`, "abcd", nil},
+	{`(?i)\W`, "x", nil},
+	{`(?i)\W`, "k", nil},
+	{`(?i)\W`, "s", nil},
+
+	// can backslash-escape any punctuation
+	{`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
+		`!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
+	{`[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~]+`,
+		`!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
+	{"\\`", "`", build(1, 0, 1)},
+	{"[\\`]+", "`", build(1, 0, 1)},
+
+	// long set of matches (longer than startSize)
+	{
+		".",
+		"qwertyuiopasdfghjklzxcvbnm1234567890",
+		build(36, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
+			10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
+			20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30,
+			30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36),
+	},
+}
+
+// build is a helper to construct a [][]int by extracting n sequences from x.
+// This represents n matches with len(x)/n submatches each.
+func build(n int, x ...int) [][]int {
+	ret := make([][]int, n)
+	runLength := len(x) / n
+	j := 0
+	for i := range ret {
+		ret[i] = make([]int, runLength)
+		copy(ret[i], x[j:])
+		j += runLength
+		if j > len(x) {
+			panic("invalid build entry")
+		}
+	}
+	return ret
+}
+
+// First the simple cases.
+
+func TestFind(t *testing.T) {
+	for _, test := range findTests {
+		re := MustCompile(test.pat)
+		if re.String() != test.pat {
+			t.Errorf("String() = `%s`; should be `%s`", re.String(), test.pat)
+		}
+		result := re.Find([]byte(test.text))
+		switch {
+		case len(test.matches) == 0 && len(result) == 0:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case test.matches != nil && result != nil:
+			expect := test.text[test.matches[0][0]:test.matches[0][1]]
+			if expect != string(result) {
+				t.Errorf("expected %q got %q: %s", expect, result, test)
+			}
+		}
+	}
+}
+
+func TestFindString(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindString(test.text)
+		switch {
+		case len(test.matches) == 0 && len(result) == 0:
+			// ok
+		case test.matches == nil && result != "":
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == "":
+			// Tricky because an empty result has two meanings: no match or empty match.
+			if test.matches[0][0] != test.matches[0][1] {
+				t.Errorf("expected match; got none: %s", test)
+			}
+		case test.matches != nil && result != "":
+			expect := test.text[test.matches[0][0]:test.matches[0][1]]
+			if expect != result {
+				t.Errorf("expected %q got %q: %s", expect, result, test)
+			}
+		}
+	}
+}
+
+func testFindIndex(test *FindTest, result []int, t *testing.T) {
+	switch {
+	case len(test.matches) == 0 && len(result) == 0:
+		// ok
+	case test.matches == nil && result != nil:
+		t.Errorf("expected no match; got one: %s", test)
+	case test.matches != nil && result == nil:
+		t.Errorf("expected match; got none: %s", test)
+	case test.matches != nil && result != nil:
+		expect := test.matches[0]
+		if expect[0] != result[0] || expect[1] != result[1] {
+			t.Errorf("expected %v got %v: %s", expect, result, test)
+		}
+	}
+}
+
+func TestFindIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindIndex(&test, MustCompile(test.pat).FindIndex([]byte(test.text)), t)
+	}
+}
+
+func TestFindStringIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindIndex(&test, MustCompile(test.pat).FindStringIndex(test.text), t)
+	}
+}
+
+func TestFindReaderIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindIndex(&test, MustCompile(test.pat).FindReaderIndex(strings.NewReader(test.text)), t)
+	}
+}
+
+// Now come the simple All cases.
+
+func TestFindAll(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindAll([]byte(test.text), -1)
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Fatalf("expected match; got none: %s", test)
+		case test.matches != nil && result != nil:
+			if len(test.matches) != len(result) {
+				t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+				continue
+			}
+			for k, e := range test.matches {
+				expect := test.text[e[0]:e[1]]
+				if expect != string(result[k]) {
+					t.Errorf("match %d: expected %q got %q: %s", k, expect, result[k], test)
+				}
+			}
+		}
+	}
+}
+
+func TestFindAllString(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindAllString(test.text, -1)
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case test.matches != nil && result != nil:
+			if len(test.matches) != len(result) {
+				t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+				continue
+			}
+			for k, e := range test.matches {
+				expect := test.text[e[0]:e[1]]
+				if expect != result[k] {
+					t.Errorf("expected %q got %q: %s", expect, result, test)
+				}
+			}
+		}
+	}
+}
+
+func testFindAllIndex(test *FindTest, result [][]int, t *testing.T) {
+	switch {
+	case test.matches == nil && result == nil:
+		// ok
+	case test.matches == nil && result != nil:
+		t.Errorf("expected no match; got one: %s", test)
+	case test.matches != nil && result == nil:
+		t.Errorf("expected match; got none: %s", test)
+	case test.matches != nil && result != nil:
+		if len(test.matches) != len(result) {
+			t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+			return
+		}
+		for k, e := range test.matches {
+			if e[0] != result[k][0] || e[1] != result[k][1] {
+				t.Errorf("match %d: expected %v got %v: %s", k, e, result[k], test)
+			}
+		}
+	}
+}
+
+func TestFindAllIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindAllIndex(&test, MustCompile(test.pat).FindAllIndex([]byte(test.text), -1), t)
+	}
+}
+
+func TestFindAllStringIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindAllIndex(&test, MustCompile(test.pat).FindAllStringIndex(test.text, -1), t)
+	}
+}
+
+// Now come the Submatch cases.
+
+func testSubmatchBytes(test *FindTest, n int, submatches []int, result [][]byte, t *testing.T) {
+	if len(submatches) != len(result)*2 {
+		t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
+		return
+	}
+	for k := 0; k < len(submatches); k += 2 {
+		if submatches[k] == -1 {
+			if result[k/2] != nil {
+				t.Errorf("match %d: expected nil got %q: %s", n, result, test)
+			}
+			continue
+		}
+		expect := test.text[submatches[k]:submatches[k+1]]
+		if expect != string(result[k/2]) {
+			t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
+			return
+		}
+	}
+}
+
+func TestFindSubmatch(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindSubmatch([]byte(test.text))
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case test.matches != nil && result != nil:
+			testSubmatchBytes(&test, 0, test.matches[0], result, t)
+		}
+	}
+}
+
+func testSubmatchString(test *FindTest, n int, submatches []int, result []string, t *testing.T) {
+	if len(submatches) != len(result)*2 {
+		t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
+		return
+	}
+	for k := 0; k < len(submatches); k += 2 {
+		if submatches[k] == -1 {
+			if result[k/2] != "" {
+				t.Errorf("match %d: expected nil got %q: %s", n, result, test)
+			}
+			continue
+		}
+		expect := test.text[submatches[k]:submatches[k+1]]
+		if expect != result[k/2] {
+			t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
+			return
+		}
+	}
+}
+
+func TestFindStringSubmatch(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindStringSubmatch(test.text)
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case test.matches != nil && result != nil:
+			testSubmatchString(&test, 0, test.matches[0], result, t)
+		}
+	}
+}
+
+func testSubmatchIndices(test *FindTest, n int, expect, result []int, t *testing.T) {
+	if len(expect) != len(result) {
+		t.Errorf("match %d: expected %d matches; got %d: %s", n, len(expect)/2, len(result)/2, test)
+		return
+	}
+	for k, e := range expect {
+		if e != result[k] {
+			t.Errorf("match %d: submatch error: expected %v got %v: %s", n, expect, result, test)
+		}
+	}
+}
+
+func testFindSubmatchIndex(test *FindTest, result []int, t *testing.T) {
+	switch {
+	case test.matches == nil && result == nil:
+		// ok
+	case test.matches == nil && result != nil:
+		t.Errorf("expected no match; got one: %s", test)
+	case test.matches != nil && result == nil:
+		t.Errorf("expected match; got none: %s", test)
+	case test.matches != nil && result != nil:
+		testSubmatchIndices(test, 0, test.matches[0], result, t)
+	}
+}
+
+func TestFindSubmatchIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindSubmatchIndex(&test, MustCompile(test.pat).FindSubmatchIndex([]byte(test.text)), t)
+	}
+}
+
+func TestFindStringSubmatchIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindSubmatchIndex(&test, MustCompile(test.pat).FindStringSubmatchIndex(test.text), t)
+	}
+}
+
+func TestFindReaderSubmatchIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindSubmatchIndex(&test, MustCompile(test.pat).FindReaderSubmatchIndex(strings.NewReader(test.text)), t)
+	}
+}
+
+// Now come the monster AllSubmatch cases.
+
+func TestFindAllSubmatch(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindAllSubmatch([]byte(test.text), -1)
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case len(test.matches) != len(result):
+			t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+		case test.matches != nil && result != nil:
+			for k, match := range test.matches {
+				testSubmatchBytes(&test, k, match, result[k], t)
+			}
+		}
+	}
+}
+
+func TestFindAllStringSubmatch(t *testing.T) {
+	for _, test := range findTests {
+		result := MustCompile(test.pat).FindAllStringSubmatch(test.text, -1)
+		switch {
+		case test.matches == nil && result == nil:
+			// ok
+		case test.matches == nil && result != nil:
+			t.Errorf("expected no match; got one: %s", test)
+		case test.matches != nil && result == nil:
+			t.Errorf("expected match; got none: %s", test)
+		case len(test.matches) != len(result):
+			t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+		case test.matches != nil && result != nil:
+			for k, match := range test.matches {
+				testSubmatchString(&test, k, match, result[k], t)
+			}
+		}
+	}
+}
+
+func testFindAllSubmatchIndex(test *FindTest, result [][]int, t *testing.T) {
+	switch {
+	case test.matches == nil && result == nil:
+		// ok
+	case test.matches == nil && result != nil:
+		t.Errorf("expected no match; got one: %s", test)
+	case test.matches != nil && result == nil:
+		t.Errorf("expected match; got none: %s", test)
+	case len(test.matches) != len(result):
+		t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+	case test.matches != nil && result != nil:
+		for k, match := range test.matches {
+			testSubmatchIndices(test, k, match, result[k], t)
+		}
+	}
+}
+
+func TestFindAllSubmatchIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllSubmatchIndex([]byte(test.text), -1), t)
+	}
+}
+
+func TestFindAllStringSubmatchIndex(t *testing.T) {
+	for _, test := range findTests {
+		testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllStringSubmatchIndex(test.text, -1), t)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/onepass.go b/third_party/gofrontend/libgo/go/regexp/onepass.go
new file mode 100644
index 0000000..501fb28
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/onepass.go
@@ -0,0 +1,582 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+
+package regexp
+
+import (
+	"bytes"
+	"regexp/syntax"
+	"sort"
+	"unicode"
+)
+
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// "One-pass" regexp execution.
+// Some regexps can be analyzed to determine that they never need
+// backtracking: they are guaranteed to run in one pass over the string
+// without bothering to save all the usual NFA state.
+// Detect those and execute them more quickly.
+
+// A onePassProg is a compiled one-pass regular expression program.
+// It is the same as syntax.Prog except for the use of onePassInst.
+type onePassProg struct {
+	Inst   []onePassInst
+	Start  int // index of start instruction
+	NumCap int // number of InstCapture insts in re
+}
+
+// A onePassInst is a single instruction in a one-pass regular expression program.
+// It is the same as syntax.Inst except for the new 'Next' field.
+type onePassInst struct {
+	syntax.Inst
+	Next []uint32
+}
+
+// OnePassPrefix returns a literal string that all matches for the
+// regexp must start with.  Complete is true if the prefix
+// is the entire match. Pc is the index of the last rune instruction
+// in the string. The OnePassPrefix skips over the mandatory
+// EmptyBeginText
+func onePassPrefix(p *syntax.Prog) (prefix string, complete bool, pc uint32) {
+	i := &p.Inst[p.Start]
+	if i.Op != syntax.InstEmptyWidth || (syntax.EmptyOp(i.Arg))&syntax.EmptyBeginText == 0 {
+		return "", i.Op == syntax.InstMatch, uint32(p.Start)
+	}
+	pc = i.Out
+	i = &p.Inst[pc]
+	for i.Op == syntax.InstNop {
+		pc = i.Out
+		i = &p.Inst[pc]
+	}
+	// Avoid allocation of buffer if prefix is empty.
+	if iop(i) != syntax.InstRune || len(i.Rune) != 1 {
+		return "", i.Op == syntax.InstMatch, uint32(p.Start)
+	}
+
+	// Have prefix; gather characters.
+	var buf bytes.Buffer
+	for iop(i) == syntax.InstRune && len(i.Rune) == 1 && syntax.Flags(i.Arg)&syntax.FoldCase == 0 {
+		buf.WriteRune(i.Rune[0])
+		pc, i = i.Out, &p.Inst[i.Out]
+	}
+	return buf.String(), i.Op == syntax.InstEmptyWidth && (syntax.EmptyOp(i.Arg))&syntax.EmptyBeginText != 0, pc
+}
+
+// OnePassNext selects the next actionable state of the prog, based on the input character.
+// It should only be called when i.Op == InstAlt or InstAltMatch, and from the one-pass machine.
+// One of the alternates may ultimately lead without input to end of line. If the instruction
+// is InstAltMatch the path to the InstMatch is in i.Out, the normal node in i.Next.
+func onePassNext(i *onePassInst, r rune) uint32 {
+	next := i.MatchRunePos(r)
+	if next >= 0 {
+		return i.Next[next]
+	}
+	if i.Op == syntax.InstAltMatch {
+		return i.Out
+	}
+	return 0
+}
+
+func iop(i *syntax.Inst) syntax.InstOp {
+	op := i.Op
+	switch op {
+	case syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
+		op = syntax.InstRune
+	}
+	return op
+}
+
+// Sparse Array implementation is used as a queueOnePass.
+type queueOnePass struct {
+	sparse          []uint32
+	dense           []uint32
+	size, nextIndex uint32
+}
+
+func (q *queueOnePass) empty() bool {
+	return q.nextIndex >= q.size
+}
+
+func (q *queueOnePass) next() (n uint32) {
+	n = q.dense[q.nextIndex]
+	q.nextIndex++
+	return
+}
+
+func (q *queueOnePass) clear() {
+	q.size = 0
+	q.nextIndex = 0
+}
+
+func (q *queueOnePass) reset() {
+	q.nextIndex = 0
+}
+
+func (q *queueOnePass) contains(u uint32) bool {
+	if u >= uint32(len(q.sparse)) {
+		return false
+	}
+	return q.sparse[u] < q.size && q.dense[q.sparse[u]] == u
+}
+
+func (q *queueOnePass) insert(u uint32) {
+	if !q.contains(u) {
+		q.insertNew(u)
+	}
+}
+
+func (q *queueOnePass) insertNew(u uint32) {
+	if u >= uint32(len(q.sparse)) {
+		return
+	}
+	q.sparse[u] = q.size
+	q.dense[q.size] = u
+	q.size++
+}
+
+func newQueue(size int) (q *queueOnePass) {
+	return &queueOnePass{
+		sparse: make([]uint32, size),
+		dense:  make([]uint32, size),
+	}
+}
+
+// mergeRuneSets merges two non-intersecting runesets, and returns the merged result,
+// and a NextIp array. The idea is that if a rune matches the OnePassRunes at index
+// i, NextIp[i/2] is the target. If the input sets intersect, an empty runeset and a
+// NextIp array with the single element mergeFailed is returned.
+// The code assumes that both inputs contain ordered and non-intersecting rune pairs.
+const mergeFailed = uint32(0xffffffff)
+
+var (
+	noRune = []rune{}
+	noNext = []uint32{mergeFailed}
+)
+
+func mergeRuneSets(leftRunes, rightRunes *[]rune, leftPC, rightPC uint32) ([]rune, []uint32) {
+	leftLen := len(*leftRunes)
+	rightLen := len(*rightRunes)
+	if leftLen&0x1 != 0 || rightLen&0x1 != 0 {
+		panic("mergeRuneSets odd length []rune")
+	}
+	var (
+		lx, rx int
+	)
+	merged := make([]rune, 0)
+	next := make([]uint32, 0)
+	ok := true
+	defer func() {
+		if !ok {
+			merged = nil
+			next = nil
+		}
+	}()
+
+	ix := -1
+	extend := func(newLow *int, newArray *[]rune, pc uint32) bool {
+		if ix > 0 && (*newArray)[*newLow] <= merged[ix] {
+			return false
+		}
+		merged = append(merged, (*newArray)[*newLow], (*newArray)[*newLow+1])
+		*newLow += 2
+		ix += 2
+		next = append(next, pc)
+		return true
+	}
+
+	for lx < leftLen || rx < rightLen {
+		switch {
+		case rx >= rightLen:
+			ok = extend(&lx, leftRunes, leftPC)
+		case lx >= leftLen:
+			ok = extend(&rx, rightRunes, rightPC)
+		case (*rightRunes)[rx] < (*leftRunes)[lx]:
+			ok = extend(&rx, rightRunes, rightPC)
+		default:
+			ok = extend(&lx, leftRunes, leftPC)
+		}
+		if !ok {
+			return noRune, noNext
+		}
+	}
+	return merged, next
+}
+
+// cleanupOnePass drops working memory, and restores certain shortcut instructions.
+func cleanupOnePass(prog *onePassProg, original *syntax.Prog) {
+	for ix, instOriginal := range original.Inst {
+		switch instOriginal.Op {
+		case syntax.InstAlt, syntax.InstAltMatch, syntax.InstRune:
+		case syntax.InstCapture, syntax.InstEmptyWidth, syntax.InstNop, syntax.InstMatch, syntax.InstFail:
+			prog.Inst[ix].Next = nil
+		case syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
+			prog.Inst[ix].Next = nil
+			prog.Inst[ix] = onePassInst{Inst: instOriginal}
+		}
+	}
+}
+
+// onePassCopy creates a copy of the original Prog, as we'll be modifying it
+func onePassCopy(prog *syntax.Prog) *onePassProg {
+	p := &onePassProg{
+		Start:  prog.Start,
+		NumCap: prog.NumCap,
+	}
+	for _, inst := range prog.Inst {
+		p.Inst = append(p.Inst, onePassInst{Inst: inst})
+	}
+
+	// rewrites one or more common Prog constructs that enable some otherwise
+	// non-onepass Progs to be onepass. A:BD (for example) means an InstAlt at
+	// ip A, that points to ips B & C.
+	// A:BC + B:DA => A:BC + B:CD
+	// A:BC + B:DC => A:DC + B:DC
+	for pc := range p.Inst {
+		switch p.Inst[pc].Op {
+		default:
+			continue
+		case syntax.InstAlt, syntax.InstAltMatch:
+			// A:Bx + B:Ay
+			p_A_Other := &p.Inst[pc].Out
+			p_A_Alt := &p.Inst[pc].Arg
+			// make sure a target is another Alt
+			instAlt := p.Inst[*p_A_Alt]
+			if !(instAlt.Op == syntax.InstAlt || instAlt.Op == syntax.InstAltMatch) {
+				p_A_Alt, p_A_Other = p_A_Other, p_A_Alt
+				instAlt = p.Inst[*p_A_Alt]
+				if !(instAlt.Op == syntax.InstAlt || instAlt.Op == syntax.InstAltMatch) {
+					continue
+				}
+			}
+			instOther := p.Inst[*p_A_Other]
+			// Analyzing both legs pointing to Alts is for another day
+			if instOther.Op == syntax.InstAlt || instOther.Op == syntax.InstAltMatch {
+				// too complicated
+				continue
+			}
+			// simple empty transition loop
+			// A:BC + B:DA => A:BC + B:DC
+			p_B_Alt := &p.Inst[*p_A_Alt].Out
+			p_B_Other := &p.Inst[*p_A_Alt].Arg
+			patch := false
+			if instAlt.Out == uint32(pc) {
+				patch = true
+			} else if instAlt.Arg == uint32(pc) {
+				patch = true
+				p_B_Alt, p_B_Other = p_B_Other, p_B_Alt
+			}
+			if patch {
+				*p_B_Alt = *p_A_Other
+			}
+
+			// empty transition to common target
+			// A:BC + B:DC => A:DC + B:DC
+			if *p_A_Other == *p_B_Alt {
+				*p_A_Alt = *p_B_Other
+			}
+		}
+	}
+	return p
+}
+
+// runeSlice exists to permit sorting the case-folded rune sets.
+type runeSlice []rune
+
+func (p runeSlice) Len() int           { return len(p) }
+func (p runeSlice) Less(i, j int) bool { return p[i] < p[j] }
+func (p runeSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// Sort is a convenience method.
+func (p runeSlice) Sort() {
+	sort.Sort(p)
+}
+
+var anyRuneNotNL = []rune{0, '\n' - 1, '\n' + 1, unicode.MaxRune}
+var anyRune = []rune{0, unicode.MaxRune}
+
+// makeOnePass creates a onepass Prog, if possible. It is possible if at any alt,
+// the match engine can always tell which branch to take. The routine may modify
+// p if it is turned into a onepass Prog. If it isn't possible for this to be a
+// onepass Prog, the Prog notOnePass is returned. makeOnePass is recursive
+// to the size of the Prog.
+func makeOnePass(p *onePassProg) *onePassProg {
+	// If the machine is very long, it's not worth the time to check if we can use one pass.
+	if len(p.Inst) >= 1000 {
+		return notOnePass
+	}
+
+	var (
+		instQueue    = newQueue(len(p.Inst))
+		visitQueue   = newQueue(len(p.Inst))
+		build        func(uint32, *queueOnePass)
+		check        func(uint32, map[uint32]bool) bool
+		onePassRunes = make([][]rune, len(p.Inst))
+	)
+	build = func(pc uint32, q *queueOnePass) {
+		if q.contains(pc) {
+			return
+		}
+		inst := p.Inst[pc]
+		switch inst.Op {
+		case syntax.InstAlt, syntax.InstAltMatch:
+			q.insert(inst.Out)
+			build(inst.Out, q)
+			q.insert(inst.Arg)
+		case syntax.InstMatch, syntax.InstFail:
+		default:
+			q.insert(inst.Out)
+		}
+	}
+
+	// check that paths from Alt instructions are unambiguous, and rebuild the new
+	// program as a onepass program
+	check = func(pc uint32, m map[uint32]bool) (ok bool) {
+		ok = true
+		inst := &p.Inst[pc]
+		if visitQueue.contains(pc) {
+			return
+		}
+		visitQueue.insert(pc)
+		switch inst.Op {
+		case syntax.InstAlt, syntax.InstAltMatch:
+			ok = check(inst.Out, m) && check(inst.Arg, m)
+			// check no-input paths to InstMatch
+			matchOut := m[inst.Out]
+			matchArg := m[inst.Arg]
+			if matchOut && matchArg {
+				ok = false
+				break
+			}
+			// Match on empty goes in inst.Out
+			if matchArg {
+				inst.Out, inst.Arg = inst.Arg, inst.Out
+				matchOut, matchArg = matchArg, matchOut
+			}
+			if matchOut {
+				m[pc] = true
+				inst.Op = syntax.InstAltMatch
+			}
+
+			// build a dispatch operator from the two legs of the alt.
+			onePassRunes[pc], inst.Next = mergeRuneSets(
+				&onePassRunes[inst.Out], &onePassRunes[inst.Arg], inst.Out, inst.Arg)
+			if len(inst.Next) > 0 && inst.Next[0] == mergeFailed {
+				ok = false
+				break
+			}
+		case syntax.InstCapture, syntax.InstNop:
+			ok = check(inst.Out, m)
+			m[pc] = m[inst.Out]
+			// pass matching runes back through these no-ops.
+			onePassRunes[pc] = append([]rune{}, onePassRunes[inst.Out]...)
+			inst.Next = []uint32{}
+			for i := len(onePassRunes[pc]) / 2; i >= 0; i-- {
+				inst.Next = append(inst.Next, inst.Out)
+			}
+		case syntax.InstEmptyWidth:
+			ok = check(inst.Out, m)
+			m[pc] = m[inst.Out]
+			onePassRunes[pc] = append([]rune{}, onePassRunes[inst.Out]...)
+			inst.Next = []uint32{}
+			for i := len(onePassRunes[pc]) / 2; i >= 0; i-- {
+				inst.Next = append(inst.Next, inst.Out)
+			}
+		case syntax.InstMatch, syntax.InstFail:
+			m[pc] = inst.Op == syntax.InstMatch
+			break
+		case syntax.InstRune:
+			ok = check(inst.Out, m)
+			m[pc] = false
+			if len(inst.Next) > 0 {
+				break
+			}
+			if len(inst.Rune) == 0 {
+				onePassRunes[pc] = []rune{}
+				inst.Next = []uint32{inst.Out}
+				break
+			}
+			runes := make([]rune, 0)
+			if len(inst.Rune) == 1 && syntax.Flags(inst.Arg)&syntax.FoldCase != 0 {
+				r0 := inst.Rune[0]
+				runes = append(runes, r0, r0)
+				for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) {
+					runes = append(runes, r1, r1)
+				}
+				sort.Sort(runeSlice(runes))
+			} else {
+				runes = append(runes, inst.Rune...)
+			}
+			onePassRunes[pc] = runes
+			inst.Next = []uint32{}
+			for i := len(onePassRunes[pc]) / 2; i >= 0; i-- {
+				inst.Next = append(inst.Next, inst.Out)
+			}
+			inst.Op = syntax.InstRune
+		case syntax.InstRune1:
+			ok = check(inst.Out, m)
+			m[pc] = false
+			if len(inst.Next) > 0 {
+				break
+			}
+			runes := []rune{}
+			// expand case-folded runes
+			if syntax.Flags(inst.Arg)&syntax.FoldCase != 0 {
+				r0 := inst.Rune[0]
+				runes = append(runes, r0, r0)
+				for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) {
+					runes = append(runes, r1, r1)
+				}
+				sort.Sort(runeSlice(runes))
+			} else {
+				runes = append(runes, inst.Rune[0], inst.Rune[0])
+			}
+			onePassRunes[pc] = runes
+			inst.Next = []uint32{}
+			for i := len(onePassRunes[pc]) / 2; i >= 0; i-- {
+				inst.Next = append(inst.Next, inst.Out)
+			}
+			inst.Op = syntax.InstRune
+		case syntax.InstRuneAny:
+			ok = check(inst.Out, m)
+			m[pc] = false
+			if len(inst.Next) > 0 {
+				break
+			}
+			onePassRunes[pc] = append([]rune{}, anyRune...)
+			inst.Next = []uint32{inst.Out}
+		case syntax.InstRuneAnyNotNL:
+			ok = check(inst.Out, m)
+			m[pc] = false
+			if len(inst.Next) > 0 {
+				break
+			}
+			onePassRunes[pc] = append([]rune{}, anyRuneNotNL...)
+			inst.Next = []uint32{}
+			for i := len(onePassRunes[pc]) / 2; i >= 0; i-- {
+				inst.Next = append(inst.Next, inst.Out)
+			}
+		}
+		return
+	}
+
+	instQueue.clear()
+	instQueue.insert(uint32(p.Start))
+	m := make(map[uint32]bool, len(p.Inst))
+	for !instQueue.empty() {
+		pc := instQueue.next()
+		inst := p.Inst[pc]
+		visitQueue.clear()
+		if !check(uint32(pc), m) {
+			p = notOnePass
+			break
+		}
+		switch inst.Op {
+		case syntax.InstAlt, syntax.InstAltMatch:
+			instQueue.insert(inst.Out)
+			instQueue.insert(inst.Arg)
+		case syntax.InstCapture, syntax.InstEmptyWidth, syntax.InstNop:
+			instQueue.insert(inst.Out)
+		case syntax.InstMatch:
+		case syntax.InstFail:
+		case syntax.InstRune, syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
+		default:
+		}
+	}
+	if p != notOnePass {
+		for i, _ := range p.Inst {
+			p.Inst[i].Rune = onePassRunes[i]
+		}
+	}
+	return p
+}
+
+// walk visits each Inst in the prog once, and applies the argument
+// function(ip, next), in pre-order.
+func walk(prog *syntax.Prog, funcs ...func(ip, next uint32)) {
+	var walk1 func(uint32)
+	progQueue := newQueue(len(prog.Inst))
+	walk1 = func(ip uint32) {
+		if progQueue.contains(ip) {
+			return
+		}
+		progQueue.insert(ip)
+		inst := prog.Inst[ip]
+		switch inst.Op {
+		case syntax.InstAlt, syntax.InstAltMatch:
+			for _, f := range funcs {
+				f(ip, inst.Out)
+				f(ip, inst.Arg)
+			}
+			walk1(inst.Out)
+			walk1(inst.Arg)
+		default:
+			for _, f := range funcs {
+				f(ip, inst.Out)
+			}
+			walk1(inst.Out)
+		}
+	}
+	walk1(uint32(prog.Start))
+}
+
+// find returns the Insts that match the argument predicate function
+func find(prog *syntax.Prog, f func(*syntax.Prog, int) bool) (matches []uint32) {
+	matches = []uint32{}
+
+	for ip := range prog.Inst {
+		if f(prog, ip) {
+			matches = append(matches, uint32(ip))
+		}
+	}
+	return
+}
+
+var notOnePass *onePassProg = nil
+
+// compileOnePass returns a new *syntax.Prog suitable for onePass execution if the original Prog
+// can be recharacterized as a one-pass regexp program, or syntax.notOnePass if the
+// Prog cannot be converted. For a one pass prog, the fundamental condition that must
+// be true is: at any InstAlt, there must be no ambiguity about what branch to  take.
+func compileOnePass(prog *syntax.Prog) (p *onePassProg) {
+	if prog.Start == 0 {
+		return notOnePass
+	}
+	// onepass regexp is anchored
+	if prog.Inst[prog.Start].Op != syntax.InstEmptyWidth ||
+		syntax.EmptyOp(prog.Inst[prog.Start].Arg)&syntax.EmptyBeginText != syntax.EmptyBeginText {
+		return notOnePass
+	}
+	// every instruction leading to InstMatch must be EmptyEndText
+	for _, inst := range prog.Inst {
+		opOut := prog.Inst[inst.Out].Op
+		switch inst.Op {
+		default:
+			if opOut == syntax.InstMatch {
+				return notOnePass
+			}
+		case syntax.InstAlt, syntax.InstAltMatch:
+			if opOut == syntax.InstMatch || prog.Inst[inst.Arg].Op == syntax.InstMatch {
+				return notOnePass
+			}
+		case syntax.InstEmptyWidth:
+			if opOut == syntax.InstMatch {
+				if syntax.EmptyOp(inst.Arg)&syntax.EmptyEndText == syntax.EmptyEndText {
+					continue
+				}
+				return notOnePass
+			}
+		}
+	}
+	// Creates a slightly optimized copy of the original Prog
+	// that cleans up some Prog idioms that block valid onepass programs
+	p = onePassCopy(prog)
+
+	// checkAmbiguity on InstAlts, build onepass Prog if possible
+	p = makeOnePass(p)
+
+	if p != notOnePass {
+		cleanupOnePass(p, prog)
+	}
+	return p
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/onepass_test.go b/third_party/gofrontend/libgo/go/regexp/onepass_test.go
new file mode 100644
index 0000000..7b2beea
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/onepass_test.go
@@ -0,0 +1,208 @@
+// Copyright 2014 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 regexp
+
+import (
+	"reflect"
+	"regexp/syntax"
+	"testing"
+)
+
+var runeMergeTests = []struct {
+	left, right, merged []rune
+	next                []uint32
+	leftPC, rightPC     uint32
+}{
+	{
+		// empty rhs
+		[]rune{69, 69},
+		[]rune{},
+		[]rune{69, 69},
+		[]uint32{1},
+		1, 2,
+	},
+	{
+		// identical runes, identical targets
+		[]rune{69, 69},
+		[]rune{69, 69},
+		[]rune{},
+		[]uint32{mergeFailed},
+		1, 1,
+	},
+	{
+		// identical runes, different targets
+		[]rune{69, 69},
+		[]rune{69, 69},
+		[]rune{},
+		[]uint32{mergeFailed},
+		1, 2,
+	},
+	{
+		// append right-first
+		[]rune{69, 69},
+		[]rune{71, 71},
+		[]rune{69, 69, 71, 71},
+		[]uint32{1, 2},
+		1, 2,
+	},
+	{
+		// append, left-first
+		[]rune{71, 71},
+		[]rune{69, 69},
+		[]rune{69, 69, 71, 71},
+		[]uint32{2, 1},
+		1, 2,
+	},
+	{
+		// successful interleave
+		[]rune{60, 60, 71, 71, 101, 101},
+		[]rune{69, 69, 88, 88},
+		[]rune{60, 60, 69, 69, 71, 71, 88, 88, 101, 101},
+		[]uint32{1, 2, 1, 2, 1},
+		1, 2,
+	},
+	{
+		// left surrounds right
+		[]rune{69, 74},
+		[]rune{71, 71},
+		[]rune{},
+		[]uint32{mergeFailed},
+		1, 2,
+	},
+	{
+		// right surrounds left
+		[]rune{69, 74},
+		[]rune{68, 75},
+		[]rune{},
+		[]uint32{mergeFailed},
+		1, 2,
+	},
+	{
+		// overlap at interval begin
+		[]rune{69, 74},
+		[]rune{74, 75},
+		[]rune{},
+		[]uint32{mergeFailed},
+		1, 2,
+	},
+	{
+		// overlap ar interval end
+		[]rune{69, 74},
+		[]rune{65, 69},
+		[]rune{},
+		[]uint32{mergeFailed},
+		1, 2,
+	},
+	{
+		// overlap from above
+		[]rune{69, 74},
+		[]rune{71, 74},
+		[]rune{},
+		[]uint32{mergeFailed},
+		1, 2,
+	},
+	{
+		// overlap from below
+		[]rune{69, 74},
+		[]rune{65, 71},
+		[]rune{},
+		[]uint32{mergeFailed},
+		1, 2,
+	},
+	{
+		// out of order []rune
+		[]rune{69, 74, 60, 65},
+		[]rune{66, 67},
+		[]rune{},
+		[]uint32{mergeFailed},
+		1, 2,
+	},
+}
+
+func TestMergeRuneSet(t *testing.T) {
+	for ix, test := range runeMergeTests {
+		merged, next := mergeRuneSets(&test.left, &test.right, test.leftPC, test.rightPC)
+		if !reflect.DeepEqual(merged, test.merged) {
+			t.Errorf("mergeRuneSet :%d (%v, %v) merged\n have\n%v\nwant\n%v", ix, test.left, test.right, merged, test.merged)
+		}
+		if !reflect.DeepEqual(next, test.next) {
+			t.Errorf("mergeRuneSet :%d(%v, %v) next\n have\n%v\nwant\n%v", ix, test.left, test.right, next, test.next)
+		}
+	}
+}
+
+const noStr = `!`
+
+var onePass = &onePassProg{}
+
+var onePassTests = []struct {
+	re      string
+	onePass *onePassProg
+	prog    string
+}{
+	{`^(?:a|(?:a*))$`, notOnePass, noStr},
+	{`^(?:(a)|(?:a*))$`, notOnePass, noStr},
+	{`^(?:(?:(?:.(?:$))?))$`, onePass, `a`},
+	{`^abcd$`, onePass, `abcd`},
+	{`^abcd$`, onePass, `abcde`},
+	{`^(?:(?:a{0,})*?)$`, onePass, `a`},
+	{`^(?:(?:a+)*)$`, onePass, ``},
+	{`^(?:(?:a|(?:aa)))$`, onePass, ``},
+	{`^(?:[^\s\S])$`, onePass, ``},
+	{`^(?:(?:a{3,4}){0,})$`, notOnePass, `aaaaaa`},
+	{`^(?:(?:a+)*)$`, onePass, `a`},
+	{`^(?:(?:(?:a*)+))$`, onePass, noStr},
+	{`^(?:(?:a+)*)$`, onePass, ``},
+	{`^[a-c]+$`, onePass, `abc`},
+	{`^[a-c]*$`, onePass, `abcdabc`},
+	{`^(?:a*)$`, onePass, `aaaaaaa`},
+	{`^(?:(?:aa)|a)$`, onePass, `a`},
+	{`^[a-c]*`, notOnePass, `abcdabc`},
+	{`^[a-c]*$`, onePass, `abc`},
+	{`^...$`, onePass, ``},
+	{`^(?:a|(?:aa))$`, onePass, `a`},
+	{`^[a-c]*`, notOnePass, `abcabc`},
+	{`^a((b))c$`, onePass, noStr},
+	{`^a.[l-nA-Cg-j]?e$`, onePass, noStr},
+	{`^a((b))$`, onePass, noStr},
+	{`^a(?:(b)|(c))c$`, onePass, noStr},
+	{`^a(?:(b*)|(c))c$`, notOnePass, noStr},
+	{`^a(?:b|c)$`, onePass, noStr},
+	{`^a(?:b?|c)$`, onePass, noStr},
+	{`^a(?:b?|c?)$`, notOnePass, noStr},
+	{`^a(?:b?|c+)$`, onePass, noStr},
+	{`^a(?:b+|(bc))d$`, notOnePass, noStr},
+	{`^a(?:bc)+$`, onePass, noStr},
+	{`^a(?:[bcd])+$`, onePass, noStr},
+	{`^a((?:[bcd])+)$`, onePass, noStr},
+	{`^a(:?b|c)*d$`, onePass, `abbbccbbcbbd"`},
+	{`^.bc(d|e)*$`, onePass, `abcddddddeeeededd`},
+	{`^(?:(?:aa)|.)$`, notOnePass, `a`},
+	{`^(?:(?:a{1,2}){1,2})$`, notOnePass, `aaaa`},
+}
+
+func TestCompileOnePass(t *testing.T) {
+	var (
+		p   *syntax.Prog
+		re  *syntax.Regexp
+		err error
+	)
+	for _, test := range onePassTests {
+		if re, err = syntax.Parse(test.re, syntax.Perl); err != nil {
+			t.Errorf("Parse(%q) got err:%s, want success", test.re, err)
+			continue
+		}
+		// needs to be done before compile...
+		re = re.Simplify()
+		if p, err = syntax.Compile(re); err != nil {
+			t.Errorf("Compile(%q) got err:%s, want success", test.re, err)
+			continue
+		}
+		onePass = compileOnePass(p)
+		if (onePass == notOnePass) != (test.onePass == notOnePass) {
+			t.Errorf("CompileOnePass(%q) got %v, expected %v", test.re, onePass, test.onePass)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/regexp.go b/third_party/gofrontend/libgo/go/regexp/regexp.go
new file mode 100644
index 0000000..0b8336a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/regexp.go
@@ -0,0 +1,1120 @@
+// 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 regexp implements regular expression search.
+//
+// The syntax of the regular expressions accepted is the same
+// general syntax used by Perl, Python, and other languages.
+// More precisely, it is the syntax accepted by RE2 and described at
+// http://code.google.com/p/re2/wiki/Syntax, except for \C.
+// For an overview of the syntax, run
+//   godoc regexp/syntax
+//
+// The regexp implementation provided by this package is
+// guaranteed to run in time linear in the size of the input.
+// (This is a property not guaranteed by most open source
+// implementations of regular expressions.) For more information
+// about this property, see
+//	http://swtch.com/~rsc/regexp/regexp1.html
+// or any book about automata theory.
+//
+// All characters are UTF-8-encoded code points.
+//
+// There are 16 methods of Regexp that match a regular expression and identify
+// the matched text.  Their names are matched by this regular expression:
+//
+//	Find(All)?(String)?(Submatch)?(Index)?
+//
+// If 'All' is present, the routine matches successive non-overlapping
+// matches of the entire expression.  Empty matches abutting a preceding
+// match are ignored.  The return value is a slice containing the successive
+// return values of the corresponding non-'All' routine.  These routines take
+// an extra integer argument, n; if n >= 0, the function returns at most n
+// matches/submatches.
+//
+// If 'String' is present, the argument is a string; otherwise it is a slice
+// of bytes; return values are adjusted as appropriate.
+//
+// If 'Submatch' is present, the return value is a slice identifying the
+// successive submatches of the expression. Submatches are matches of
+// parenthesized subexpressions (also known as capturing groups) within the
+// regular expression, numbered from left to right in order of opening
+// parenthesis. Submatch 0 is the match of the entire expression, submatch 1
+// the match of the first parenthesized subexpression, and so on.
+//
+// If 'Index' is present, matches and submatches are identified by byte index
+// pairs within the input string: result[2*n:2*n+1] identifies the indexes of
+// the nth submatch.  The pair for n==0 identifies the match of the entire
+// expression.  If 'Index' is not present, the match is identified by the
+// text of the match/submatch.  If an index is negative, it means that
+// subexpression did not match any string in the input.
+//
+// There is also a subset of the methods that can be applied to text read
+// from a RuneReader:
+//
+//	MatchReader, FindReaderIndex, FindReaderSubmatchIndex
+//
+// This set may grow.  Note that regular expression matches may need to
+// examine text beyond the text returned by a match, so the methods that
+// match text from a RuneReader may read arbitrarily far into the input
+// before returning.
+//
+// (There are a few other methods that do not match this pattern.)
+//
+package regexp
+
+import (
+	"bytes"
+	"io"
+	"regexp/syntax"
+	"strconv"
+	"strings"
+	"sync"
+	"unicode"
+	"unicode/utf8"
+)
+
+var debug = false
+
+// Regexp is the representation of a compiled regular expression.
+// A Regexp is safe for concurrent use by multiple goroutines.
+type Regexp struct {
+	// read-only after Compile
+	expr           string         // as passed to Compile
+	prog           *syntax.Prog   // compiled program
+	onepass        *onePassProg   // onpass program or nil
+	prefix         string         // required prefix in unanchored matches
+	prefixBytes    []byte         // prefix, as a []byte
+	prefixComplete bool           // prefix is the entire regexp
+	prefixRune     rune           // first rune in prefix
+	prefixEnd      uint32         // pc for last rune in prefix
+	cond           syntax.EmptyOp // empty-width conditions required at start of match
+	numSubexp      int
+	subexpNames    []string
+	longest        bool
+
+	// cache of machines for running regexp
+	mu      sync.Mutex
+	machine []*machine
+}
+
+// String returns the source text used to compile the regular expression.
+func (re *Regexp) String() string {
+	return re.expr
+}
+
+// Compile parses a regular expression and returns, if successful,
+// a Regexp object that can be used to match against text.
+//
+// When matching against text, the regexp returns a match that
+// begins as early as possible in the input (leftmost), and among those
+// it chooses the one that a backtracking search would have found first.
+// This so-called leftmost-first matching is the same semantics
+// that Perl, Python, and other implementations use, although this
+// package implements it without the expense of backtracking.
+// For POSIX leftmost-longest matching, see CompilePOSIX.
+func Compile(expr string) (*Regexp, error) {
+	return compile(expr, syntax.Perl, false)
+}
+
+// CompilePOSIX is like Compile but restricts the regular expression
+// to POSIX ERE (egrep) syntax and changes the match semantics to
+// leftmost-longest.
+//
+// That is, when matching against text, the regexp returns a match that
+// begins as early as possible in the input (leftmost), and among those
+// it chooses a match that is as long as possible.
+// This so-called leftmost-longest matching is the same semantics
+// that early regular expression implementations used and that POSIX
+// specifies.
+//
+// However, there can be multiple leftmost-longest matches, with different
+// submatch choices, and here this package diverges from POSIX.
+// Among the possible leftmost-longest matches, this package chooses
+// the one that a backtracking search would have found first, while POSIX
+// specifies that the match be chosen to maximize the length of the first
+// subexpression, then the second, and so on from left to right.
+// The POSIX rule is computationally prohibitive and not even well-defined.
+// See http://swtch.com/~rsc/regexp/regexp2.html#posix for details.
+func CompilePOSIX(expr string) (*Regexp, error) {
+	return compile(expr, syntax.POSIX, true)
+}
+
+// Longest makes future searches prefer the leftmost-longest match.
+// That is, when matching against text, the regexp returns a match that
+// begins as early as possible in the input (leftmost), and among those
+// it chooses a match that is as long as possible.
+func (re *Regexp) Longest() {
+	re.longest = true
+}
+
+func compile(expr string, mode syntax.Flags, longest bool) (*Regexp, error) {
+	re, err := syntax.Parse(expr, mode)
+	if err != nil {
+		return nil, err
+	}
+	maxCap := re.MaxCap()
+	capNames := re.CapNames()
+
+	re = re.Simplify()
+	prog, err := syntax.Compile(re)
+	if err != nil {
+		return nil, err
+	}
+	regexp := &Regexp{
+		expr:        expr,
+		prog:        prog,
+		onepass:     compileOnePass(prog),
+		numSubexp:   maxCap,
+		subexpNames: capNames,
+		cond:        prog.StartCond(),
+		longest:     longest,
+	}
+	if regexp.onepass == notOnePass {
+		regexp.prefix, regexp.prefixComplete = prog.Prefix()
+	} else {
+		regexp.prefix, regexp.prefixComplete, regexp.prefixEnd = onePassPrefix(prog)
+	}
+	if regexp.prefix != "" {
+		// TODO(rsc): Remove this allocation by adding
+		// IndexString to package bytes.
+		regexp.prefixBytes = []byte(regexp.prefix)
+		regexp.prefixRune, _ = utf8.DecodeRuneInString(regexp.prefix)
+	}
+	return regexp, nil
+}
+
+// get returns a machine to use for matching re.
+// It uses the re's machine cache if possible, to avoid
+// unnecessary allocation.
+func (re *Regexp) get() *machine {
+	re.mu.Lock()
+	if n := len(re.machine); n > 0 {
+		z := re.machine[n-1]
+		re.machine = re.machine[:n-1]
+		re.mu.Unlock()
+		return z
+	}
+	re.mu.Unlock()
+	z := progMachine(re.prog, re.onepass)
+	z.re = re
+	return z
+}
+
+// put returns a machine to the re's machine cache.
+// There is no attempt to limit the size of the cache, so it will
+// grow to the maximum number of simultaneous matches
+// run using re.  (The cache empties when re gets garbage collected.)
+func (re *Regexp) put(z *machine) {
+	re.mu.Lock()
+	re.machine = append(re.machine, z)
+	re.mu.Unlock()
+}
+
+// MustCompile is like Compile but panics if the expression cannot be parsed.
+// It simplifies safe initialization of global variables holding compiled regular
+// expressions.
+func MustCompile(str string) *Regexp {
+	regexp, error := Compile(str)
+	if error != nil {
+		panic(`regexp: Compile(` + quote(str) + `): ` + error.Error())
+	}
+	return regexp
+}
+
+// MustCompilePOSIX is like CompilePOSIX but panics if the expression cannot be parsed.
+// It simplifies safe initialization of global variables holding compiled regular
+// expressions.
+func MustCompilePOSIX(str string) *Regexp {
+	regexp, error := CompilePOSIX(str)
+	if error != nil {
+		panic(`regexp: CompilePOSIX(` + quote(str) + `): ` + error.Error())
+	}
+	return regexp
+}
+
+func quote(s string) string {
+	if strconv.CanBackquote(s) {
+		return "`" + s + "`"
+	}
+	return strconv.Quote(s)
+}
+
+// NumSubexp returns the number of parenthesized subexpressions in this Regexp.
+func (re *Regexp) NumSubexp() int {
+	return re.numSubexp
+}
+
+// SubexpNames returns the names of the parenthesized subexpressions
+// in this Regexp.  The name for the first sub-expression is names[1],
+// so that if m is a match slice, the name for m[i] is SubexpNames()[i].
+// Since the Regexp as a whole cannot be named, names[0] is always
+// the empty string.  The slice should not be modified.
+func (re *Regexp) SubexpNames() []string {
+	return re.subexpNames
+}
+
+const endOfText rune = -1
+
+// input abstracts different representations of the input text. It provides
+// one-character lookahead.
+type input interface {
+	step(pos int) (r rune, width int) // advance one rune
+	canCheckPrefix() bool             // can we look ahead without losing info?
+	hasPrefix(re *Regexp) bool
+	index(re *Regexp, pos int) int
+	context(pos int) syntax.EmptyOp
+}
+
+// inputString scans a string.
+type inputString struct {
+	str string
+}
+
+func (i *inputString) step(pos int) (rune, int) {
+	if pos < len(i.str) {
+		c := i.str[pos]
+		if c < utf8.RuneSelf {
+			return rune(c), 1
+		}
+		return utf8.DecodeRuneInString(i.str[pos:])
+	}
+	return endOfText, 0
+}
+
+func (i *inputString) canCheckPrefix() bool {
+	return true
+}
+
+func (i *inputString) hasPrefix(re *Regexp) bool {
+	return strings.HasPrefix(i.str, re.prefix)
+}
+
+func (i *inputString) index(re *Regexp, pos int) int {
+	return strings.Index(i.str[pos:], re.prefix)
+}
+
+func (i *inputString) context(pos int) syntax.EmptyOp {
+	r1, r2 := endOfText, endOfText
+	if pos > 0 && pos <= len(i.str) {
+		r1, _ = utf8.DecodeLastRuneInString(i.str[:pos])
+	}
+	if pos < len(i.str) {
+		r2, _ = utf8.DecodeRuneInString(i.str[pos:])
+	}
+	return syntax.EmptyOpContext(r1, r2)
+}
+
+// inputBytes scans a byte slice.
+type inputBytes struct {
+	str []byte
+}
+
+func (i *inputBytes) step(pos int) (rune, int) {
+	if pos < len(i.str) {
+		c := i.str[pos]
+		if c < utf8.RuneSelf {
+			return rune(c), 1
+		}
+		return utf8.DecodeRune(i.str[pos:])
+	}
+	return endOfText, 0
+}
+
+func (i *inputBytes) canCheckPrefix() bool {
+	return true
+}
+
+func (i *inputBytes) hasPrefix(re *Regexp) bool {
+	return bytes.HasPrefix(i.str, re.prefixBytes)
+}
+
+func (i *inputBytes) index(re *Regexp, pos int) int {
+	return bytes.Index(i.str[pos:], re.prefixBytes)
+}
+
+func (i *inputBytes) context(pos int) syntax.EmptyOp {
+	r1, r2 := endOfText, endOfText
+	if pos > 0 && pos <= len(i.str) {
+		r1, _ = utf8.DecodeLastRune(i.str[:pos])
+	}
+	if pos < len(i.str) {
+		r2, _ = utf8.DecodeRune(i.str[pos:])
+	}
+	return syntax.EmptyOpContext(r1, r2)
+}
+
+// inputReader scans a RuneReader.
+type inputReader struct {
+	r     io.RuneReader
+	atEOT bool
+	pos   int
+}
+
+func (i *inputReader) step(pos int) (rune, int) {
+	if !i.atEOT && pos != i.pos {
+		return endOfText, 0
+
+	}
+	r, w, err := i.r.ReadRune()
+	if err != nil {
+		i.atEOT = true
+		return endOfText, 0
+	}
+	i.pos += w
+	return r, w
+}
+
+func (i *inputReader) canCheckPrefix() bool {
+	return false
+}
+
+func (i *inputReader) hasPrefix(re *Regexp) bool {
+	return false
+}
+
+func (i *inputReader) index(re *Regexp, pos int) int {
+	return -1
+}
+
+func (i *inputReader) context(pos int) syntax.EmptyOp {
+	return 0
+}
+
+// LiteralPrefix returns a literal string that must begin any match
+// of the regular expression re.  It returns the boolean true if the
+// literal string comprises the entire regular expression.
+func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
+	return re.prefix, re.prefixComplete
+}
+
+// MatchReader reports whether the Regexp matches the text read by the
+// RuneReader.
+func (re *Regexp) MatchReader(r io.RuneReader) bool {
+	return re.doExecute(r, nil, "", 0, 0) != nil
+}
+
+// MatchString reports whether the Regexp matches the string s.
+func (re *Regexp) MatchString(s string) bool {
+	return re.doExecute(nil, nil, s, 0, 0) != nil
+}
+
+// Match reports whether the Regexp matches the byte slice b.
+func (re *Regexp) Match(b []byte) bool {
+	return re.doExecute(nil, b, "", 0, 0) != nil
+}
+
+// MatchReader checks whether a textual regular expression matches the text
+// read by the RuneReader.  More complicated queries need to use Compile and
+// the full Regexp interface.
+func MatchReader(pattern string, r io.RuneReader) (matched bool, err error) {
+	re, err := Compile(pattern)
+	if err != nil {
+		return false, err
+	}
+	return re.MatchReader(r), nil
+}
+
+// MatchString checks whether a textual regular expression
+// matches a string.  More complicated queries need
+// to use Compile and the full Regexp interface.
+func MatchString(pattern string, s string) (matched bool, err error) {
+	re, err := Compile(pattern)
+	if err != nil {
+		return false, err
+	}
+	return re.MatchString(s), nil
+}
+
+// Match checks whether a textual regular expression
+// matches a byte slice.  More complicated queries need
+// to use Compile and the full Regexp interface.
+func Match(pattern string, b []byte) (matched bool, err error) {
+	re, err := Compile(pattern)
+	if err != nil {
+		return false, err
+	}
+	return re.Match(b), nil
+}
+
+// ReplaceAllString returns a copy of src, replacing matches of the Regexp
+// with the replacement string repl.  Inside repl, $ signs are interpreted as
+// in Expand, so for instance $1 represents the text of the first submatch.
+func (re *Regexp) ReplaceAllString(src, repl string) string {
+	n := 2
+	if strings.Index(repl, "$") >= 0 {
+		n = 2 * (re.numSubexp + 1)
+	}
+	b := re.replaceAll(nil, src, n, func(dst []byte, match []int) []byte {
+		return re.expand(dst, repl, nil, src, match)
+	})
+	return string(b)
+}
+
+// ReplaceAllStringLiteral returns a copy of src, replacing matches of the Regexp
+// with the replacement string repl.  The replacement repl is substituted directly,
+// without using Expand.
+func (re *Regexp) ReplaceAllLiteralString(src, repl string) string {
+	return string(re.replaceAll(nil, src, 2, func(dst []byte, match []int) []byte {
+		return append(dst, repl...)
+	}))
+}
+
+// ReplaceAllStringFunc returns a copy of src in which all matches of the
+// Regexp have been replaced by the return value of function repl applied
+// to the matched substring.  The replacement returned by repl is substituted
+// directly, without using Expand.
+func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
+	b := re.replaceAll(nil, src, 2, func(dst []byte, match []int) []byte {
+		return append(dst, repl(src[match[0]:match[1]])...)
+	})
+	return string(b)
+}
+
+func (re *Regexp) replaceAll(bsrc []byte, src string, nmatch int, repl func(dst []byte, m []int) []byte) []byte {
+	lastMatchEnd := 0 // end position of the most recent match
+	searchPos := 0    // position where we next look for a match
+	var buf []byte
+	var endPos int
+	if bsrc != nil {
+		endPos = len(bsrc)
+	} else {
+		endPos = len(src)
+	}
+	for searchPos <= endPos {
+		a := re.doExecute(nil, bsrc, src, searchPos, nmatch)
+		if len(a) == 0 {
+			break // no more matches
+		}
+
+		// Copy the unmatched characters before this match.
+		if bsrc != nil {
+			buf = append(buf, bsrc[lastMatchEnd:a[0]]...)
+		} else {
+			buf = append(buf, src[lastMatchEnd:a[0]]...)
+		}
+
+		// Now insert a copy of the replacement string, but not for a
+		// match of the empty string immediately after another match.
+		// (Otherwise, we get double replacement for patterns that
+		// match both empty and nonempty strings.)
+		if a[1] > lastMatchEnd || a[0] == 0 {
+			buf = repl(buf, a)
+		}
+		lastMatchEnd = a[1]
+
+		// Advance past this match; always advance at least one character.
+		var width int
+		if bsrc != nil {
+			_, width = utf8.DecodeRune(bsrc[searchPos:])
+		} else {
+			_, width = utf8.DecodeRuneInString(src[searchPos:])
+		}
+		if searchPos+width > a[1] {
+			searchPos += width
+		} else if searchPos+1 > a[1] {
+			// This clause is only needed at the end of the input
+			// string.  In that case, DecodeRuneInString returns width=0.
+			searchPos++
+		} else {
+			searchPos = a[1]
+		}
+	}
+
+	// Copy the unmatched characters after the last match.
+	if bsrc != nil {
+		buf = append(buf, bsrc[lastMatchEnd:]...)
+	} else {
+		buf = append(buf, src[lastMatchEnd:]...)
+	}
+
+	return buf
+}
+
+// ReplaceAll returns a copy of src, replacing matches of the Regexp
+// with the replacement text repl.  Inside repl, $ signs are interpreted as
+// in Expand, so for instance $1 represents the text of the first submatch.
+func (re *Regexp) ReplaceAll(src, repl []byte) []byte {
+	n := 2
+	if bytes.IndexByte(repl, '$') >= 0 {
+		n = 2 * (re.numSubexp + 1)
+	}
+	srepl := ""
+	b := re.replaceAll(src, "", n, func(dst []byte, match []int) []byte {
+		if len(srepl) != len(repl) {
+			srepl = string(repl)
+		}
+		return re.expand(dst, srepl, src, "", match)
+	})
+	return b
+}
+
+// ReplaceAllLiteral returns a copy of src, replacing matches of the Regexp
+// with the replacement bytes repl.  The replacement repl is substituted directly,
+// without using Expand.
+func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte {
+	return re.replaceAll(src, "", 2, func(dst []byte, match []int) []byte {
+		return append(dst, repl...)
+	})
+}
+
+// ReplaceAllFunc returns a copy of src in which all matches of the
+// Regexp have been replaced by the return value of function repl applied
+// to the matched byte slice.  The replacement returned by repl is substituted
+// directly, without using Expand.
+func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
+	return re.replaceAll(src, "", 2, func(dst []byte, match []int) []byte {
+		return append(dst, repl(src[match[0]:match[1]])...)
+	})
+}
+
+var specialBytes = []byte(`\.+*?()|[]{}^$`)
+
+func special(b byte) bool {
+	return bytes.IndexByte(specialBytes, b) >= 0
+}
+
+// QuoteMeta returns a string that quotes all regular expression metacharacters
+// inside the argument text; the returned string is a regular expression matching
+// the literal text.  For example, QuoteMeta(`[foo]`) returns `\[foo\]`.
+func QuoteMeta(s string) string {
+	b := make([]byte, 2*len(s))
+
+	// A byte loop is correct because all metacharacters are ASCII.
+	j := 0
+	for i := 0; i < len(s); i++ {
+		if special(s[i]) {
+			b[j] = '\\'
+			j++
+		}
+		b[j] = s[i]
+		j++
+	}
+	return string(b[0:j])
+}
+
+// The number of capture values in the program may correspond
+// to fewer capturing expressions than are in the regexp.
+// For example, "(a){0}" turns into an empty program, so the
+// maximum capture in the program is 0 but we need to return
+// an expression for \1.  Pad appends -1s to the slice a as needed.
+func (re *Regexp) pad(a []int) []int {
+	if a == nil {
+		// No match.
+		return nil
+	}
+	n := (1 + re.numSubexp) * 2
+	for len(a) < n {
+		a = append(a, -1)
+	}
+	return a
+}
+
+// Find matches in slice b if b is non-nil, otherwise find matches in string s.
+func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
+	var end int
+	if b == nil {
+		end = len(s)
+	} else {
+		end = len(b)
+	}
+
+	for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; {
+		matches := re.doExecute(nil, b, s, pos, re.prog.NumCap)
+		if len(matches) == 0 {
+			break
+		}
+
+		accept := true
+		if matches[1] == pos {
+			// We've found an empty match.
+			if matches[0] == prevMatchEnd {
+				// We don't allow an empty match right
+				// after a previous match, so ignore it.
+				accept = false
+			}
+			var width int
+			// TODO: use step()
+			if b == nil {
+				_, width = utf8.DecodeRuneInString(s[pos:end])
+			} else {
+				_, width = utf8.DecodeRune(b[pos:end])
+			}
+			if width > 0 {
+				pos += width
+			} else {
+				pos = end + 1
+			}
+		} else {
+			pos = matches[1]
+		}
+		prevMatchEnd = matches[1]
+
+		if accept {
+			deliver(re.pad(matches))
+			i++
+		}
+	}
+}
+
+// Find returns a slice holding the text of the leftmost match in b of the regular expression.
+// A return value of nil indicates no match.
+func (re *Regexp) Find(b []byte) []byte {
+	a := re.doExecute(nil, b, "", 0, 2)
+	if a == nil {
+		return nil
+	}
+	return b[a[0]:a[1]]
+}
+
+// FindIndex returns a two-element slice of integers defining the location of
+// the leftmost match in b of the regular expression.  The match itself is at
+// b[loc[0]:loc[1]].
+// A return value of nil indicates no match.
+func (re *Regexp) FindIndex(b []byte) (loc []int) {
+	a := re.doExecute(nil, b, "", 0, 2)
+	if a == nil {
+		return nil
+	}
+	return a[0:2]
+}
+
+// FindString returns a string holding the text of the leftmost match in s of the regular
+// expression.  If there is no match, the return value is an empty string,
+// but it will also be empty if the regular expression successfully matches
+// an empty string.  Use FindStringIndex or FindStringSubmatch if it is
+// necessary to distinguish these cases.
+func (re *Regexp) FindString(s string) string {
+	a := re.doExecute(nil, nil, s, 0, 2)
+	if a == nil {
+		return ""
+	}
+	return s[a[0]:a[1]]
+}
+
+// FindStringIndex returns a two-element slice of integers defining the
+// location of the leftmost match in s of the regular expression.  The match
+// itself is at s[loc[0]:loc[1]].
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringIndex(s string) (loc []int) {
+	a := re.doExecute(nil, nil, s, 0, 2)
+	if a == nil {
+		return nil
+	}
+	return a[0:2]
+}
+
+// FindReaderIndex returns a two-element slice of integers defining the
+// location of the leftmost match of the regular expression in text read from
+// the RuneReader.  The match text was found in the input stream at
+// byte offset loc[0] through loc[1]-1.
+// A return value of nil indicates no match.
+func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) {
+	a := re.doExecute(r, nil, "", 0, 2)
+	if a == nil {
+		return nil
+	}
+	return a[0:2]
+}
+
+// FindSubmatch returns a slice of slices holding the text of the leftmost
+// match of the regular expression in b and the matches, if any, of its
+// subexpressions, as defined by the 'Submatch' descriptions in the package
+// comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindSubmatch(b []byte) [][]byte {
+	a := re.doExecute(nil, b, "", 0, re.prog.NumCap)
+	if a == nil {
+		return nil
+	}
+	ret := make([][]byte, 1+re.numSubexp)
+	for i := range ret {
+		if 2*i < len(a) && a[2*i] >= 0 {
+			ret[i] = b[a[2*i]:a[2*i+1]]
+		}
+	}
+	return ret
+}
+
+// Expand appends template to dst and returns the result; during the
+// append, Expand replaces variables in the template with corresponding
+// matches drawn from src.  The match slice should have been returned by
+// FindSubmatchIndex.
+//
+// In the template, a variable is denoted by a substring of the form
+// $name or ${name}, where name is a non-empty sequence of letters,
+// digits, and underscores.  A purely numeric name like $1 refers to
+// the submatch with the corresponding index; other names refer to
+// capturing parentheses named with the (?P<name>...) syntax.  A
+// reference to an out of range or unmatched index or a name that is not
+// present in the regular expression is replaced with an empty slice.
+//
+// In the $name form, name is taken to be as long as possible: $1x is
+// equivalent to ${1x}, not ${1}x, and, $10 is equivalent to ${10}, not ${1}0.
+//
+// To insert a literal $ in the output, use $$ in the template.
+func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte {
+	return re.expand(dst, string(template), src, "", match)
+}
+
+// ExpandString is like Expand but the template and source are strings.
+// It appends to and returns a byte slice in order to give the calling
+// code control over allocation.
+func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte {
+	return re.expand(dst, template, nil, src, match)
+}
+
+func (re *Regexp) expand(dst []byte, template string, bsrc []byte, src string, match []int) []byte {
+	for len(template) > 0 {
+		i := strings.Index(template, "$")
+		if i < 0 {
+			break
+		}
+		dst = append(dst, template[:i]...)
+		template = template[i:]
+		if len(template) > 1 && template[1] == '$' {
+			// Treat $$ as $.
+			dst = append(dst, '$')
+			template = template[2:]
+			continue
+		}
+		name, num, rest, ok := extract(template)
+		if !ok {
+			// Malformed; treat $ as raw text.
+			dst = append(dst, '$')
+			template = template[1:]
+			continue
+		}
+		template = rest
+		if num >= 0 {
+			if 2*num+1 < len(match) && match[2*num] >= 0 {
+				if bsrc != nil {
+					dst = append(dst, bsrc[match[2*num]:match[2*num+1]]...)
+				} else {
+					dst = append(dst, src[match[2*num]:match[2*num+1]]...)
+				}
+			}
+		} else {
+			for i, namei := range re.subexpNames {
+				if name == namei && 2*i+1 < len(match) && match[2*i] >= 0 {
+					if bsrc != nil {
+						dst = append(dst, bsrc[match[2*i]:match[2*i+1]]...)
+					} else {
+						dst = append(dst, src[match[2*i]:match[2*i+1]]...)
+					}
+					break
+				}
+			}
+		}
+	}
+	dst = append(dst, template...)
+	return dst
+}
+
+// extract returns the name from a leading "$name" or "${name}" in str.
+// If it is a number, extract returns num set to that number; otherwise num = -1.
+func extract(str string) (name string, num int, rest string, ok bool) {
+	if len(str) < 2 || str[0] != '$' {
+		return
+	}
+	brace := false
+	if str[1] == '{' {
+		brace = true
+		str = str[2:]
+	} else {
+		str = str[1:]
+	}
+	i := 0
+	for i < len(str) {
+		rune, size := utf8.DecodeRuneInString(str[i:])
+		if !unicode.IsLetter(rune) && !unicode.IsDigit(rune) && rune != '_' {
+			break
+		}
+		i += size
+	}
+	if i == 0 {
+		// empty name is not okay
+		return
+	}
+	name = str[:i]
+	if brace {
+		if i >= len(str) || str[i] != '}' {
+			// missing closing brace
+			return
+		}
+		i++
+	}
+
+	// Parse number.
+	num = 0
+	for i := 0; i < len(name); i++ {
+		if name[i] < '0' || '9' < name[i] || num >= 1e8 {
+			num = -1
+			break
+		}
+		num = num*10 + int(name[i]) - '0'
+	}
+	// Disallow leading zeros.
+	if name[0] == '0' && len(name) > 1 {
+		num = -1
+	}
+
+	rest = str[i:]
+	ok = true
+	return
+}
+
+// FindSubmatchIndex returns a slice holding the index pairs identifying the
+// leftmost match of the regular expression in b and the matches, if any, of
+// its subexpressions, as defined by the 'Submatch' and 'Index' descriptions
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindSubmatchIndex(b []byte) []int {
+	return re.pad(re.doExecute(nil, b, "", 0, re.prog.NumCap))
+}
+
+// FindStringSubmatch returns a slice of strings holding the text of the
+// leftmost match of the regular expression in s and the matches, if any, of
+// its subexpressions, as defined by the 'Submatch' description in the
+// package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringSubmatch(s string) []string {
+	a := re.doExecute(nil, nil, s, 0, re.prog.NumCap)
+	if a == nil {
+		return nil
+	}
+	ret := make([]string, 1+re.numSubexp)
+	for i := range ret {
+		if 2*i < len(a) && a[2*i] >= 0 {
+			ret[i] = s[a[2*i]:a[2*i+1]]
+		}
+	}
+	return ret
+}
+
+// FindStringSubmatchIndex returns a slice holding the index pairs
+// identifying the leftmost match of the regular expression in s and the
+// matches, if any, of its subexpressions, as defined by the 'Submatch' and
+// 'Index' descriptions in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringSubmatchIndex(s string) []int {
+	return re.pad(re.doExecute(nil, nil, s, 0, re.prog.NumCap))
+}
+
+// FindReaderSubmatchIndex returns a slice holding the index pairs
+// identifying the leftmost match of the regular expression of text read by
+// the RuneReader, and the matches, if any, of its subexpressions, as defined
+// by the 'Submatch' and 'Index' descriptions in the package comment.  A
+// return value of nil indicates no match.
+func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int {
+	return re.pad(re.doExecute(r, nil, "", 0, re.prog.NumCap))
+}
+
+const startSize = 10 // The size at which to start a slice in the 'All' routines.
+
+// FindAll is the 'All' version of Find; it returns a slice of all successive
+// matches of the expression, as defined by the 'All' description in the
+// package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAll(b []byte, n int) [][]byte {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][]byte, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		result = append(result, b[match[0]:match[1]])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllIndex is the 'All' version of FindIndex; it returns a slice of all
+// successive matches of the expression, as defined by the 'All' description
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllIndex(b []byte, n int) [][]int {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		result = append(result, match[0:2])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllString is the 'All' version of FindString; it returns a slice of all
+// successive matches of the expression, as defined by the 'All' description
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllString(s string, n int) []string {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([]string, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		result = append(result, s[match[0]:match[1]])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllStringIndex is the 'All' version of FindStringIndex; it returns a
+// slice of all successive matches of the expression, as defined by the 'All'
+// description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringIndex(s string, n int) [][]int {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		result = append(result, match[0:2])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllSubmatch is the 'All' version of FindSubmatch; it returns a slice
+// of all successive matches of the expression, as defined by the 'All'
+// description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][][]byte, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		slice := make([][]byte, len(match)/2)
+		for j := range slice {
+			if match[2*j] >= 0 {
+				slice[j] = b[match[2*j]:match[2*j+1]]
+			}
+		}
+		result = append(result, slice)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllSubmatchIndex is the 'All' version of FindSubmatchIndex; it returns
+// a slice of all successive matches of the expression, as defined by the
+// 'All' description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		result = append(result, match)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllStringSubmatch is the 'All' version of FindStringSubmatch; it
+// returns a slice of all successive matches of the expression, as defined by
+// the 'All' description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([][]string, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		slice := make([]string, len(match)/2)
+		for j := range slice {
+			if match[2*j] >= 0 {
+				slice[j] = s[match[2*j]:match[2*j+1]]
+			}
+		}
+		result = append(result, slice)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllStringSubmatchIndex is the 'All' version of
+// FindStringSubmatchIndex; it returns a slice of all successive matches of
+// the expression, as defined by the 'All' description in the package
+// comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		result = append(result, match)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// Split slices s into substrings separated by the expression and returns a slice of
+// the substrings between those expression matches.
+//
+// The slice returned by this method consists of all the substrings of s
+// not contained in the slice returned by FindAllString. When called on an expression
+// that contains no metacharacters, it is equivalent to strings.SplitN.
+//
+// Example:
+//   s := regexp.MustCompile("a*").Split("abaabaccadaaae", 5)
+//   // s: ["", "b", "b", "c", "cadaaae"]
+//
+// The count determines the number of substrings to return:
+//   n > 0: at most n substrings; the last substring will be the unsplit remainder.
+//   n == 0: the result is nil (zero substrings)
+//   n < 0: all substrings
+func (re *Regexp) Split(s string, n int) []string {
+
+	if n == 0 {
+		return nil
+	}
+
+	if len(re.expr) > 0 && len(s) == 0 {
+		return []string{""}
+	}
+
+	matches := re.FindAllStringIndex(s, n)
+	strings := make([]string, 0, len(matches))
+
+	beg := 0
+	end := 0
+	for _, match := range matches {
+		if n > 0 && len(strings) >= n-1 {
+			break
+		}
+
+		end = match[0]
+		if match[1] != 0 {
+			strings = append(strings, s[beg:end])
+		}
+		beg = match[1]
+	}
+
+	if end != len(s) {
+		strings = append(strings, s[beg:])
+	}
+
+	return strings
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/syntax/compile.go b/third_party/gofrontend/libgo/go/regexp/syntax/compile.go
new file mode 100644
index 0000000..95f6f15
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/syntax/compile.go
@@ -0,0 +1,289 @@
+// 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.
+
+package syntax
+
+import "unicode"
+
+// A patchList is a list of instruction pointers that need to be filled in (patched).
+// Because the pointers haven't been filled in yet, we can reuse their storage
+// to hold the list.  It's kind of sleazy, but works well in practice.
+// See http://swtch.com/~rsc/regexp/regexp1.html for inspiration.
+//
+// These aren't really pointers: they're integers, so we can reinterpret them
+// this way without using package unsafe.  A value l denotes
+// p.inst[l>>1].Out (l&1==0) or .Arg (l&1==1).
+// l == 0 denotes the empty list, okay because we start every program
+// with a fail instruction, so we'll never want to point at its output link.
+type patchList uint32
+
+func (l patchList) next(p *Prog) patchList {
+	i := &p.Inst[l>>1]
+	if l&1 == 0 {
+		return patchList(i.Out)
+	}
+	return patchList(i.Arg)
+}
+
+func (l patchList) patch(p *Prog, val uint32) {
+	for l != 0 {
+		i := &p.Inst[l>>1]
+		if l&1 == 0 {
+			l = patchList(i.Out)
+			i.Out = val
+		} else {
+			l = patchList(i.Arg)
+			i.Arg = val
+		}
+	}
+}
+
+func (l1 patchList) append(p *Prog, l2 patchList) patchList {
+	if l1 == 0 {
+		return l2
+	}
+	if l2 == 0 {
+		return l1
+	}
+
+	last := l1
+	for {
+		next := last.next(p)
+		if next == 0 {
+			break
+		}
+		last = next
+	}
+
+	i := &p.Inst[last>>1]
+	if last&1 == 0 {
+		i.Out = uint32(l2)
+	} else {
+		i.Arg = uint32(l2)
+	}
+	return l1
+}
+
+// A frag represents a compiled program fragment.
+type frag struct {
+	i   uint32    // index of first instruction
+	out patchList // where to record end instruction
+}
+
+type compiler struct {
+	p *Prog
+}
+
+// Compile compiles the regexp into a program to be executed.
+// The regexp should have been simplified already (returned from re.Simplify).
+func Compile(re *Regexp) (*Prog, error) {
+	var c compiler
+	c.init()
+	f := c.compile(re)
+	f.out.patch(c.p, c.inst(InstMatch).i)
+	c.p.Start = int(f.i)
+	return c.p, nil
+}
+
+func (c *compiler) init() {
+	c.p = new(Prog)
+	c.p.NumCap = 2 // implicit ( and ) for whole match $0
+	c.inst(InstFail)
+}
+
+var anyRuneNotNL = []rune{0, '\n' - 1, '\n' + 1, unicode.MaxRune}
+var anyRune = []rune{0, unicode.MaxRune}
+
+func (c *compiler) compile(re *Regexp) frag {
+	switch re.Op {
+	case OpNoMatch:
+		return c.fail()
+	case OpEmptyMatch:
+		return c.nop()
+	case OpLiteral:
+		if len(re.Rune) == 0 {
+			return c.nop()
+		}
+		var f frag
+		for j := range re.Rune {
+			f1 := c.rune(re.Rune[j:j+1], re.Flags)
+			if j == 0 {
+				f = f1
+			} else {
+				f = c.cat(f, f1)
+			}
+		}
+		return f
+	case OpCharClass:
+		return c.rune(re.Rune, re.Flags)
+	case OpAnyCharNotNL:
+		return c.rune(anyRuneNotNL, 0)
+	case OpAnyChar:
+		return c.rune(anyRune, 0)
+	case OpBeginLine:
+		return c.empty(EmptyBeginLine)
+	case OpEndLine:
+		return c.empty(EmptyEndLine)
+	case OpBeginText:
+		return c.empty(EmptyBeginText)
+	case OpEndText:
+		return c.empty(EmptyEndText)
+	case OpWordBoundary:
+		return c.empty(EmptyWordBoundary)
+	case OpNoWordBoundary:
+		return c.empty(EmptyNoWordBoundary)
+	case OpCapture:
+		bra := c.cap(uint32(re.Cap << 1))
+		sub := c.compile(re.Sub[0])
+		ket := c.cap(uint32(re.Cap<<1 | 1))
+		return c.cat(c.cat(bra, sub), ket)
+	case OpStar:
+		return c.star(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
+	case OpPlus:
+		return c.plus(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
+	case OpQuest:
+		return c.quest(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
+	case OpConcat:
+		if len(re.Sub) == 0 {
+			return c.nop()
+		}
+		var f frag
+		for i, sub := range re.Sub {
+			if i == 0 {
+				f = c.compile(sub)
+			} else {
+				f = c.cat(f, c.compile(sub))
+			}
+		}
+		return f
+	case OpAlternate:
+		var f frag
+		for _, sub := range re.Sub {
+			f = c.alt(f, c.compile(sub))
+		}
+		return f
+	}
+	panic("regexp: unhandled case in compile")
+}
+
+func (c *compiler) inst(op InstOp) frag {
+	// TODO: impose length limit
+	f := frag{i: uint32(len(c.p.Inst))}
+	c.p.Inst = append(c.p.Inst, Inst{Op: op})
+	return f
+}
+
+func (c *compiler) nop() frag {
+	f := c.inst(InstNop)
+	f.out = patchList(f.i << 1)
+	return f
+}
+
+func (c *compiler) fail() frag {
+	return frag{}
+}
+
+func (c *compiler) cap(arg uint32) frag {
+	f := c.inst(InstCapture)
+	f.out = patchList(f.i << 1)
+	c.p.Inst[f.i].Arg = arg
+
+	if c.p.NumCap < int(arg)+1 {
+		c.p.NumCap = int(arg) + 1
+	}
+	return f
+}
+
+func (c *compiler) cat(f1, f2 frag) frag {
+	// concat of failure is failure
+	if f1.i == 0 || f2.i == 0 {
+		return frag{}
+	}
+
+	// TODO: elide nop
+
+	f1.out.patch(c.p, f2.i)
+	return frag{f1.i, f2.out}
+}
+
+func (c *compiler) alt(f1, f2 frag) frag {
+	// alt of failure is other
+	if f1.i == 0 {
+		return f2
+	}
+	if f2.i == 0 {
+		return f1
+	}
+
+	f := c.inst(InstAlt)
+	i := &c.p.Inst[f.i]
+	i.Out = f1.i
+	i.Arg = f2.i
+	f.out = f1.out.append(c.p, f2.out)
+	return f
+}
+
+func (c *compiler) quest(f1 frag, nongreedy bool) frag {
+	f := c.inst(InstAlt)
+	i := &c.p.Inst[f.i]
+	if nongreedy {
+		i.Arg = f1.i
+		f.out = patchList(f.i << 1)
+	} else {
+		i.Out = f1.i
+		f.out = patchList(f.i<<1 | 1)
+	}
+	f.out = f.out.append(c.p, f1.out)
+	return f
+}
+
+func (c *compiler) star(f1 frag, nongreedy bool) frag {
+	f := c.inst(InstAlt)
+	i := &c.p.Inst[f.i]
+	if nongreedy {
+		i.Arg = f1.i
+		f.out = patchList(f.i << 1)
+	} else {
+		i.Out = f1.i
+		f.out = patchList(f.i<<1 | 1)
+	}
+	f1.out.patch(c.p, f.i)
+	return f
+}
+
+func (c *compiler) plus(f1 frag, nongreedy bool) frag {
+	return frag{f1.i, c.star(f1, nongreedy).out}
+}
+
+func (c *compiler) empty(op EmptyOp) frag {
+	f := c.inst(InstEmptyWidth)
+	c.p.Inst[f.i].Arg = uint32(op)
+	f.out = patchList(f.i << 1)
+	return f
+}
+
+func (c *compiler) rune(r []rune, flags Flags) frag {
+	f := c.inst(InstRune)
+	i := &c.p.Inst[f.i]
+	i.Rune = r
+	flags &= FoldCase // only relevant flag is FoldCase
+	if len(r) != 1 || unicode.SimpleFold(r[0]) == r[0] {
+		// and sometimes not even that
+		flags &^= FoldCase
+	}
+	i.Arg = uint32(flags)
+	f.out = patchList(f.i << 1)
+
+	// Special cases for exec machine.
+	switch {
+	case flags&FoldCase == 0 && (len(r) == 1 || len(r) == 2 && r[0] == r[1]):
+		i.Op = InstRune1
+	case len(r) == 2 && r[0] == 0 && r[1] == unicode.MaxRune:
+		i.Op = InstRuneAny
+	case len(r) == 4 && r[0] == 0 && r[1] == '\n'-1 && r[2] == '\n'+1 && r[3] == unicode.MaxRune:
+		i.Op = InstRuneAnyNotNL
+	}
+
+	return f
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/syntax/doc.go b/third_party/gofrontend/libgo/go/regexp/syntax/doc.go
new file mode 100644
index 0000000..8e72c90
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/syntax/doc.go
@@ -0,0 +1,131 @@
+// 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.
+
+// DO NOT EDIT. This file is generated by mksyntaxgo from the RE2 distribution.
+
+/*
+Package syntax parses regular expressions into parse trees and compiles
+parse trees into programs. Most clients of regular expressions will use the
+facilities of package regexp (such as Compile and Match) instead of this package.
+
+Syntax
+
+The regular expression syntax understood by this package when parsing with the Perl flag is as follows.
+Parts of the syntax can be disabled by passing alternate flags to Parse.
+
+
+Single characters:
+  .              any character, possibly including newline (flag s=true)
+  [xyz]          character class
+  [^xyz]         negated character class
+  \d             Perl character class
+  \D             negated Perl character class
+  [:alpha:]      ASCII character class
+  [:^alpha:]     negated ASCII character class
+  \pN            Unicode character class (one-letter name)
+  \p{Greek}      Unicode character class
+  \PN            negated Unicode character class (one-letter name)
+  \P{Greek}      negated Unicode character class
+
+Composites:
+  xy             x followed by y
+  x|y            x or y (prefer x)
+
+Repetitions:
+  x*             zero or more x, prefer more
+  x+             one or more x, prefer more
+  x?             zero or one x, prefer one
+  x{n,m}         n or n+1 or ... or m x, prefer more
+  x{n,}          n or more x, prefer more
+  x{n}           exactly n x
+  x*?            zero or more x, prefer fewer
+  x+?            one or more x, prefer fewer
+  x??            zero or one x, prefer zero
+  x{n,m}?        n or n+1 or ... or m x, prefer fewer
+  x{n,}?         n or more x, prefer fewer
+  x{n}?          exactly n x
+
+Implementation restriction: The counting forms x{n} etc. (but not the other
+forms x* etc.) have an upper limit of n=1000. Negative or higher explicit
+counts yield the parse error ErrInvalidRepeatSize.
+
+Grouping:
+  (re)           numbered capturing group (submatch)
+  (?P<name>re)   named & numbered capturing group (submatch)
+  (?:re)         non-capturing group (submatch)
+  (?flags)       set flags within current group; non-capturing
+  (?flags:re)    set flags during re; non-capturing
+
+  Flag syntax is xyz (set) or -xyz (clear) or xy-z (set xy, clear z). The flags are:
+
+  i              case-insensitive (default false)
+  m              multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false)
+  s              let . match \n (default false)
+  U              ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false)
+
+Empty strings:
+  ^              at beginning of text or line (flag m=true)
+  $              at end of text (like \z not \Z) or line (flag m=true)
+  \A             at beginning of text
+  \b             at ASCII word boundary (\w on one side and \W, \A, or \z on the other)
+  \B             not an ASCII word boundary
+  \z             at end of text
+
+Escape sequences:
+  \a             bell (== \007)
+  \f             form feed (== \014)
+  \t             horizontal tab (== \011)
+  \n             newline (== \012)
+  \r             carriage return (== \015)
+  \v             vertical tab character (== \013)
+  \*             literal *, for any punctuation character *
+  \123           octal character code (up to three digits)
+  \x7F           hex character code (exactly two digits)
+  \x{10FFFF}     hex character code
+  \Q...\E        literal text ... even if ... has punctuation
+
+Character class elements:
+  x              single character
+  A-Z            character range (inclusive)
+  \d             Perl character class
+  [:foo:]        ASCII character class foo
+  \p{Foo}        Unicode character class Foo
+  \pF            Unicode character class F (one-letter name)
+
+Named character classes as character class elements:
+  [\d]           digits (== \d)
+  [^\d]          not digits (== \D)
+  [\D]           not digits (== \D)
+  [^\D]          not not digits (== \d)
+  [[:name:]]     named ASCII class inside character class (== [:name:])
+  [^[:name:]]    named ASCII class inside negated character class (== [:^name:])
+  [\p{Name}]     named Unicode property inside character class (== \p{Name})
+  [^\p{Name}]    named Unicode property inside negated character class (== \P{Name})
+
+Perl character classes:
+  \d             digits (== [0-9])
+  \D             not digits (== [^0-9])
+  \s             whitespace (== [\t\n\f\r ])
+  \S             not whitespace (== [^\t\n\f\r ])
+  \w             ASCII word characters (== [0-9A-Za-z_])
+  \W             not ASCII word characters (== [^0-9A-Za-z_])
+
+ASCII character classes:
+  [:alnum:]      alphanumeric (== [0-9A-Za-z])
+  [:alpha:]      alphabetic (== [A-Za-z])
+  [:ascii:]      ASCII (== [\x00-\x7F])
+  [:blank:]      blank (== [\t ])
+  [:cntrl:]      control (== [\x00-\x1F\x7F])
+  [:digit:]      digits (== [0-9])
+  [:graph:]      graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
+  [:lower:]      lower case (== [a-z])
+  [:print:]      printable (== [ -~] == [ [:graph:]])
+  [:punct:]      punctuation (== [!-/:-@[-`{-~])
+  [:space:]      whitespace (== [\t\n\v\f\r ])
+  [:upper:]      upper case (== [A-Z])
+  [:word:]       word characters (== [0-9A-Za-z_])
+  [:xdigit:]     hex digit (== [0-9A-Fa-f])
+
+*/
+package syntax
diff --git a/third_party/gofrontend/libgo/go/regexp/syntax/parse.go b/third_party/gofrontend/libgo/go/regexp/syntax/parse.go
new file mode 100644
index 0000000..cb25dca
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/syntax/parse.go
@@ -0,0 +1,1863 @@
+// 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.
+
+package syntax
+
+import (
+	"sort"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// An Error describes a failure to parse a regular expression
+// and gives the offending expression.
+type Error struct {
+	Code ErrorCode
+	Expr string
+}
+
+func (e *Error) Error() string {
+	return "error parsing regexp: " + e.Code.String() + ": `" + e.Expr + "`"
+}
+
+// An ErrorCode describes a failure to parse a regular expression.
+type ErrorCode string
+
+const (
+	// Unexpected error
+	ErrInternalError ErrorCode = "regexp/syntax: internal error"
+
+	// Parse errors
+	ErrInvalidCharClass      ErrorCode = "invalid character class"
+	ErrInvalidCharRange      ErrorCode = "invalid character class range"
+	ErrInvalidEscape         ErrorCode = "invalid escape sequence"
+	ErrInvalidNamedCapture   ErrorCode = "invalid named capture"
+	ErrInvalidPerlOp         ErrorCode = "invalid or unsupported Perl syntax"
+	ErrInvalidRepeatOp       ErrorCode = "invalid nested repetition operator"
+	ErrInvalidRepeatSize     ErrorCode = "invalid repeat count"
+	ErrInvalidUTF8           ErrorCode = "invalid UTF-8"
+	ErrMissingBracket        ErrorCode = "missing closing ]"
+	ErrMissingParen          ErrorCode = "missing closing )"
+	ErrMissingRepeatArgument ErrorCode = "missing argument to repetition operator"
+	ErrTrailingBackslash     ErrorCode = "trailing backslash at end of expression"
+	ErrUnexpectedParen       ErrorCode = "unexpected )"
+)
+
+func (e ErrorCode) String() string {
+	return string(e)
+}
+
+// Flags control the behavior of the parser and record information about regexp context.
+type Flags uint16
+
+const (
+	FoldCase      Flags = 1 << iota // case-insensitive match
+	Literal                         // treat pattern as literal string
+	ClassNL                         // allow character classes like [^a-z] and [[:space:]] to match newline
+	DotNL                           // allow . to match newline
+	OneLine                         // treat ^ and $ as only matching at beginning and end of text
+	NonGreedy                       // make repetition operators default to non-greedy
+	PerlX                           // allow Perl extensions
+	UnicodeGroups                   // allow \p{Han}, \P{Han} for Unicode group and negation
+	WasDollar                       // regexp OpEndText was $, not \z
+	Simple                          // regexp contains no counted repetition
+
+	MatchNL = ClassNL | DotNL
+
+	Perl        = ClassNL | OneLine | PerlX | UnicodeGroups // as close to Perl as possible
+	POSIX Flags = 0                                         // POSIX syntax
+)
+
+// Pseudo-ops for parsing stack.
+const (
+	opLeftParen = opPseudo + iota
+	opVerticalBar
+)
+
+type parser struct {
+	flags       Flags     // parse mode flags
+	stack       []*Regexp // stack of parsed expressions
+	free        *Regexp
+	numCap      int // number of capturing groups seen
+	wholeRegexp string
+	tmpClass    []rune // temporary char class work space
+}
+
+func (p *parser) newRegexp(op Op) *Regexp {
+	re := p.free
+	if re != nil {
+		p.free = re.Sub0[0]
+		*re = Regexp{}
+	} else {
+		re = new(Regexp)
+	}
+	re.Op = op
+	return re
+}
+
+func (p *parser) reuse(re *Regexp) {
+	re.Sub0[0] = p.free
+	p.free = re
+}
+
+// Parse stack manipulation.
+
+// push pushes the regexp re onto the parse stack and returns the regexp.
+func (p *parser) push(re *Regexp) *Regexp {
+	if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] {
+		// Single rune.
+		if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) {
+			return nil
+		}
+		re.Op = OpLiteral
+		re.Rune = re.Rune[:1]
+		re.Flags = p.flags &^ FoldCase
+	} else if re.Op == OpCharClass && len(re.Rune) == 4 &&
+		re.Rune[0] == re.Rune[1] && re.Rune[2] == re.Rune[3] &&
+		unicode.SimpleFold(re.Rune[0]) == re.Rune[2] &&
+		unicode.SimpleFold(re.Rune[2]) == re.Rune[0] ||
+		re.Op == OpCharClass && len(re.Rune) == 2 &&
+			re.Rune[0]+1 == re.Rune[1] &&
+			unicode.SimpleFold(re.Rune[0]) == re.Rune[1] &&
+			unicode.SimpleFold(re.Rune[1]) == re.Rune[0] {
+		// Case-insensitive rune like [Aa] or [Δδ].
+		if p.maybeConcat(re.Rune[0], p.flags|FoldCase) {
+			return nil
+		}
+
+		// Rewrite as (case-insensitive) literal.
+		re.Op = OpLiteral
+		re.Rune = re.Rune[:1]
+		re.Flags = p.flags | FoldCase
+	} else {
+		// Incremental concatenation.
+		p.maybeConcat(-1, 0)
+	}
+
+	p.stack = append(p.stack, re)
+	return re
+}
+
+// maybeConcat implements incremental concatenation
+// of literal runes into string nodes.  The parser calls this
+// before each push, so only the top fragment of the stack
+// might need processing.  Since this is called before a push,
+// the topmost literal is no longer subject to operators like *
+// (Otherwise ab* would turn into (ab)*.)
+// If r >= 0 and there's a node left over, maybeConcat uses it
+// to push r with the given flags.
+// maybeConcat reports whether r was pushed.
+func (p *parser) maybeConcat(r rune, flags Flags) bool {
+	n := len(p.stack)
+	if n < 2 {
+		return false
+	}
+
+	re1 := p.stack[n-1]
+	re2 := p.stack[n-2]
+	if re1.Op != OpLiteral || re2.Op != OpLiteral || re1.Flags&FoldCase != re2.Flags&FoldCase {
+		return false
+	}
+
+	// Push re1 into re2.
+	re2.Rune = append(re2.Rune, re1.Rune...)
+
+	// Reuse re1 if possible.
+	if r >= 0 {
+		re1.Rune = re1.Rune0[:1]
+		re1.Rune[0] = r
+		re1.Flags = flags
+		return true
+	}
+
+	p.stack = p.stack[:n-1]
+	p.reuse(re1)
+	return false // did not push r
+}
+
+// newLiteral returns a new OpLiteral Regexp with the given flags
+func (p *parser) newLiteral(r rune, flags Flags) *Regexp {
+	re := p.newRegexp(OpLiteral)
+	re.Flags = flags
+	if flags&FoldCase != 0 {
+		r = minFoldRune(r)
+	}
+	re.Rune0[0] = r
+	re.Rune = re.Rune0[:1]
+	return re
+}
+
+// minFoldRune returns the minimum rune fold-equivalent to r.
+func minFoldRune(r rune) rune {
+	if r < minFold || r > maxFold {
+		return r
+	}
+	min := r
+	r0 := r
+	for r = unicode.SimpleFold(r); r != r0; r = unicode.SimpleFold(r) {
+		if min > r {
+			min = r
+		}
+	}
+	return min
+}
+
+// literal pushes a literal regexp for the rune r on the stack
+// and returns that regexp.
+func (p *parser) literal(r rune) {
+	p.push(p.newLiteral(r, p.flags))
+}
+
+// op pushes a regexp with the given op onto the stack
+// and returns that regexp.
+func (p *parser) op(op Op) *Regexp {
+	re := p.newRegexp(op)
+	re.Flags = p.flags
+	return p.push(re)
+}
+
+// repeat replaces the top stack element with itself repeated according to op, min, max.
+// before is the regexp suffix starting at the repetition operator.
+// after is the regexp suffix following after the repetition operator.
+// repeat returns an updated 'after' and an error, if any.
+func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (string, error) {
+	flags := p.flags
+	if p.flags&PerlX != 0 {
+		if len(after) > 0 && after[0] == '?' {
+			after = after[1:]
+			flags ^= NonGreedy
+		}
+		if lastRepeat != "" {
+			// In Perl it is not allowed to stack repetition operators:
+			// a** is a syntax error, not a doubled star, and a++ means
+			// something else entirely, which we don't support!
+			return "", &Error{ErrInvalidRepeatOp, lastRepeat[:len(lastRepeat)-len(after)]}
+		}
+	}
+	n := len(p.stack)
+	if n == 0 {
+		return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
+	}
+	sub := p.stack[n-1]
+	if sub.Op >= opPseudo {
+		return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
+	}
+	re := p.newRegexp(op)
+	re.Min = min
+	re.Max = max
+	re.Flags = flags
+	re.Sub = re.Sub0[:1]
+	re.Sub[0] = sub
+	p.stack[n-1] = re
+	return after, nil
+}
+
+// concat replaces the top of the stack (above the topmost '|' or '(') with its concatenation.
+func (p *parser) concat() *Regexp {
+	p.maybeConcat(-1, 0)
+
+	// Scan down to find pseudo-operator | or (.
+	i := len(p.stack)
+	for i > 0 && p.stack[i-1].Op < opPseudo {
+		i--
+	}
+	subs := p.stack[i:]
+	p.stack = p.stack[:i]
+
+	// Empty concatenation is special case.
+	if len(subs) == 0 {
+		return p.push(p.newRegexp(OpEmptyMatch))
+	}
+
+	return p.push(p.collapse(subs, OpConcat))
+}
+
+// alternate replaces the top of the stack (above the topmost '(') with its alternation.
+func (p *parser) alternate() *Regexp {
+	// Scan down to find pseudo-operator (.
+	// There are no | above (.
+	i := len(p.stack)
+	for i > 0 && p.stack[i-1].Op < opPseudo {
+		i--
+	}
+	subs := p.stack[i:]
+	p.stack = p.stack[:i]
+
+	// Make sure top class is clean.
+	// All the others already are (see swapVerticalBar).
+	if len(subs) > 0 {
+		cleanAlt(subs[len(subs)-1])
+	}
+
+	// Empty alternate is special case
+	// (shouldn't happen but easy to handle).
+	if len(subs) == 0 {
+		return p.push(p.newRegexp(OpNoMatch))
+	}
+
+	return p.push(p.collapse(subs, OpAlternate))
+}
+
+// cleanAlt cleans re for eventual inclusion in an alternation.
+func cleanAlt(re *Regexp) {
+	switch re.Op {
+	case OpCharClass:
+		re.Rune = cleanClass(&re.Rune)
+		if len(re.Rune) == 2 && re.Rune[0] == 0 && re.Rune[1] == unicode.MaxRune {
+			re.Rune = nil
+			re.Op = OpAnyChar
+			return
+		}
+		if len(re.Rune) == 4 && re.Rune[0] == 0 && re.Rune[1] == '\n'-1 && re.Rune[2] == '\n'+1 && re.Rune[3] == unicode.MaxRune {
+			re.Rune = nil
+			re.Op = OpAnyCharNotNL
+			return
+		}
+		if cap(re.Rune)-len(re.Rune) > 100 {
+			// re.Rune will not grow any more.
+			// Make a copy or inline to reclaim storage.
+			re.Rune = append(re.Rune0[:0], re.Rune...)
+		}
+	}
+}
+
+// collapse returns the result of applying op to sub.
+// If sub contains op nodes, they all get hoisted up
+// so that there is never a concat of a concat or an
+// alternate of an alternate.
+func (p *parser) collapse(subs []*Regexp, op Op) *Regexp {
+	if len(subs) == 1 {
+		return subs[0]
+	}
+	re := p.newRegexp(op)
+	re.Sub = re.Sub0[:0]
+	for _, sub := range subs {
+		if sub.Op == op {
+			re.Sub = append(re.Sub, sub.Sub...)
+			p.reuse(sub)
+		} else {
+			re.Sub = append(re.Sub, sub)
+		}
+	}
+	if op == OpAlternate {
+		re.Sub = p.factor(re.Sub, re.Flags)
+		if len(re.Sub) == 1 {
+			old := re
+			re = re.Sub[0]
+			p.reuse(old)
+		}
+	}
+	return re
+}
+
+// factor factors common prefixes from the alternation list sub.
+// It returns a replacement list that reuses the same storage and
+// frees (passes to p.reuse) any removed *Regexps.
+//
+// For example,
+//     ABC|ABD|AEF|BCX|BCY
+// simplifies by literal prefix extraction to
+//     A(B(C|D)|EF)|BC(X|Y)
+// which simplifies by character class introduction to
+//     A(B[CD]|EF)|BC[XY]
+//
+func (p *parser) factor(sub []*Regexp, flags Flags) []*Regexp {
+	if len(sub) < 2 {
+		return sub
+	}
+
+	// Round 1: Factor out common literal prefixes.
+	var str []rune
+	var strflags Flags
+	start := 0
+	out := sub[:0]
+	for i := 0; i <= len(sub); i++ {
+		// Invariant: the Regexps that were in sub[0:start] have been
+		// used or marked for reuse, and the slice space has been reused
+		// for out (len(out) <= start).
+		//
+		// Invariant: sub[start:i] consists of regexps that all begin
+		// with str as modified by strflags.
+		var istr []rune
+		var iflags Flags
+		if i < len(sub) {
+			istr, iflags = p.leadingString(sub[i])
+			if iflags == strflags {
+				same := 0
+				for same < len(str) && same < len(istr) && str[same] == istr[same] {
+					same++
+				}
+				if same > 0 {
+					// Matches at least one rune in current range.
+					// Keep going around.
+					str = str[:same]
+					continue
+				}
+			}
+		}
+
+		// Found end of a run with common leading literal string:
+		// sub[start:i] all begin with str[0:len(str)], but sub[i]
+		// does not even begin with str[0].
+		//
+		// Factor out common string and append factored expression to out.
+		if i == start {
+			// Nothing to do - run of length 0.
+		} else if i == start+1 {
+			// Just one: don't bother factoring.
+			out = append(out, sub[start])
+		} else {
+			// Construct factored form: prefix(suffix1|suffix2|...)
+			prefix := p.newRegexp(OpLiteral)
+			prefix.Flags = strflags
+			prefix.Rune = append(prefix.Rune[:0], str...)
+
+			for j := start; j < i; j++ {
+				sub[j] = p.removeLeadingString(sub[j], len(str))
+			}
+			suffix := p.collapse(sub[start:i], OpAlternate) // recurse
+
+			re := p.newRegexp(OpConcat)
+			re.Sub = append(re.Sub[:0], prefix, suffix)
+			out = append(out, re)
+		}
+
+		// Prepare for next iteration.
+		start = i
+		str = istr
+		strflags = iflags
+	}
+	sub = out
+
+	// Round 2: Factor out common complex prefixes,
+	// just the first piece of each concatenation,
+	// whatever it is.  This is good enough a lot of the time.
+	start = 0
+	out = sub[:0]
+	var first *Regexp
+	for i := 0; i <= len(sub); i++ {
+		// Invariant: the Regexps that were in sub[0:start] have been
+		// used or marked for reuse, and the slice space has been reused
+		// for out (len(out) <= start).
+		//
+		// Invariant: sub[start:i] consists of regexps that all begin with ifirst.
+		var ifirst *Regexp
+		if i < len(sub) {
+			ifirst = p.leadingRegexp(sub[i])
+			if first != nil && first.Equal(ifirst) {
+				continue
+			}
+		}
+
+		// Found end of a run with common leading regexp:
+		// sub[start:i] all begin with first but sub[i] does not.
+		//
+		// Factor out common regexp and append factored expression to out.
+		if i == start {
+			// Nothing to do - run of length 0.
+		} else if i == start+1 {
+			// Just one: don't bother factoring.
+			out = append(out, sub[start])
+		} else {
+			// Construct factored form: prefix(suffix1|suffix2|...)
+			prefix := first
+			for j := start; j < i; j++ {
+				reuse := j != start // prefix came from sub[start]
+				sub[j] = p.removeLeadingRegexp(sub[j], reuse)
+			}
+			suffix := p.collapse(sub[start:i], OpAlternate) // recurse
+
+			re := p.newRegexp(OpConcat)
+			re.Sub = append(re.Sub[:0], prefix, suffix)
+			out = append(out, re)
+		}
+
+		// Prepare for next iteration.
+		start = i
+		first = ifirst
+	}
+	sub = out
+
+	// Round 3: Collapse runs of single literals into character classes.
+	start = 0
+	out = sub[:0]
+	for i := 0; i <= len(sub); i++ {
+		// Invariant: the Regexps that were in sub[0:start] have been
+		// used or marked for reuse, and the slice space has been reused
+		// for out (len(out) <= start).
+		//
+		// Invariant: sub[start:i] consists of regexps that are either
+		// literal runes or character classes.
+		if i < len(sub) && isCharClass(sub[i]) {
+			continue
+		}
+
+		// sub[i] is not a char or char class;
+		// emit char class for sub[start:i]...
+		if i == start {
+			// Nothing to do - run of length 0.
+		} else if i == start+1 {
+			out = append(out, sub[start])
+		} else {
+			// Make new char class.
+			// Start with most complex regexp in sub[start].
+			max := start
+			for j := start + 1; j < i; j++ {
+				if sub[max].Op < sub[j].Op || sub[max].Op == sub[j].Op && len(sub[max].Rune) < len(sub[j].Rune) {
+					max = j
+				}
+			}
+			sub[start], sub[max] = sub[max], sub[start]
+
+			for j := start + 1; j < i; j++ {
+				mergeCharClass(sub[start], sub[j])
+				p.reuse(sub[j])
+			}
+			cleanAlt(sub[start])
+			out = append(out, sub[start])
+		}
+
+		// ... and then emit sub[i].
+		if i < len(sub) {
+			out = append(out, sub[i])
+		}
+		start = i + 1
+	}
+	sub = out
+
+	// Round 4: Collapse runs of empty matches into a single empty match.
+	start = 0
+	out = sub[:0]
+	for i := range sub {
+		if i+1 < len(sub) && sub[i].Op == OpEmptyMatch && sub[i+1].Op == OpEmptyMatch {
+			continue
+		}
+		out = append(out, sub[i])
+	}
+	sub = out
+
+	return sub
+}
+
+// leadingString returns the leading literal string that re begins with.
+// The string refers to storage in re or its children.
+func (p *parser) leadingString(re *Regexp) ([]rune, Flags) {
+	if re.Op == OpConcat && len(re.Sub) > 0 {
+		re = re.Sub[0]
+	}
+	if re.Op != OpLiteral {
+		return nil, 0
+	}
+	return re.Rune, re.Flags & FoldCase
+}
+
+// removeLeadingString removes the first n leading runes
+// from the beginning of re.  It returns the replacement for re.
+func (p *parser) removeLeadingString(re *Regexp, n int) *Regexp {
+	if re.Op == OpConcat && len(re.Sub) > 0 {
+		// Removing a leading string in a concatenation
+		// might simplify the concatenation.
+		sub := re.Sub[0]
+		sub = p.removeLeadingString(sub, n)
+		re.Sub[0] = sub
+		if sub.Op == OpEmptyMatch {
+			p.reuse(sub)
+			switch len(re.Sub) {
+			case 0, 1:
+				// Impossible but handle.
+				re.Op = OpEmptyMatch
+				re.Sub = nil
+			case 2:
+				old := re
+				re = re.Sub[1]
+				p.reuse(old)
+			default:
+				copy(re.Sub, re.Sub[1:])
+				re.Sub = re.Sub[:len(re.Sub)-1]
+			}
+		}
+		return re
+	}
+
+	if re.Op == OpLiteral {
+		re.Rune = re.Rune[:copy(re.Rune, re.Rune[n:])]
+		if len(re.Rune) == 0 {
+			re.Op = OpEmptyMatch
+		}
+	}
+	return re
+}
+
+// leadingRegexp returns the leading regexp that re begins with.
+// The regexp refers to storage in re or its children.
+func (p *parser) leadingRegexp(re *Regexp) *Regexp {
+	if re.Op == OpEmptyMatch {
+		return nil
+	}
+	if re.Op == OpConcat && len(re.Sub) > 0 {
+		sub := re.Sub[0]
+		if sub.Op == OpEmptyMatch {
+			return nil
+		}
+		return sub
+	}
+	return re
+}
+
+// removeLeadingRegexp removes the leading regexp in re.
+// It returns the replacement for re.
+// If reuse is true, it passes the removed regexp (if no longer needed) to p.reuse.
+func (p *parser) removeLeadingRegexp(re *Regexp, reuse bool) *Regexp {
+	if re.Op == OpConcat && len(re.Sub) > 0 {
+		if reuse {
+			p.reuse(re.Sub[0])
+		}
+		re.Sub = re.Sub[:copy(re.Sub, re.Sub[1:])]
+		switch len(re.Sub) {
+		case 0:
+			re.Op = OpEmptyMatch
+			re.Sub = nil
+		case 1:
+			old := re
+			re = re.Sub[0]
+			p.reuse(old)
+		}
+		return re
+	}
+	if reuse {
+		p.reuse(re)
+	}
+	return p.newRegexp(OpEmptyMatch)
+}
+
+func literalRegexp(s string, flags Flags) *Regexp {
+	re := &Regexp{Op: OpLiteral}
+	re.Flags = flags
+	re.Rune = re.Rune0[:0] // use local storage for small strings
+	for _, c := range s {
+		if len(re.Rune) >= cap(re.Rune) {
+			// string is too long to fit in Rune0.  let Go handle it
+			re.Rune = []rune(s)
+			break
+		}
+		re.Rune = append(re.Rune, c)
+	}
+	return re
+}
+
+// Parsing.
+
+// Parse parses a regular expression string s, controlled by the specified
+// Flags, and returns a regular expression parse tree. The syntax is
+// described in the top-level comment.
+func Parse(s string, flags Flags) (*Regexp, error) {
+	if flags&Literal != 0 {
+		// Trivial parser for literal string.
+		if err := checkUTF8(s); err != nil {
+			return nil, err
+		}
+		return literalRegexp(s, flags), nil
+	}
+
+	// Otherwise, must do real work.
+	var (
+		p          parser
+		err        error
+		c          rune
+		op         Op
+		lastRepeat string
+	)
+	p.flags = flags
+	p.wholeRegexp = s
+	t := s
+	for t != "" {
+		repeat := ""
+	BigSwitch:
+		switch t[0] {
+		default:
+			if c, t, err = nextRune(t); err != nil {
+				return nil, err
+			}
+			p.literal(c)
+
+		case '(':
+			if p.flags&PerlX != 0 && len(t) >= 2 && t[1] == '?' {
+				// Flag changes and non-capturing groups.
+				if t, err = p.parsePerlFlags(t); err != nil {
+					return nil, err
+				}
+				break
+			}
+			p.numCap++
+			p.op(opLeftParen).Cap = p.numCap
+			t = t[1:]
+		case '|':
+			if err = p.parseVerticalBar(); err != nil {
+				return nil, err
+			}
+			t = t[1:]
+		case ')':
+			if err = p.parseRightParen(); err != nil {
+				return nil, err
+			}
+			t = t[1:]
+		case '^':
+			if p.flags&OneLine != 0 {
+				p.op(OpBeginText)
+			} else {
+				p.op(OpBeginLine)
+			}
+			t = t[1:]
+		case '$':
+			if p.flags&OneLine != 0 {
+				p.op(OpEndText).Flags |= WasDollar
+			} else {
+				p.op(OpEndLine)
+			}
+			t = t[1:]
+		case '.':
+			if p.flags&DotNL != 0 {
+				p.op(OpAnyChar)
+			} else {
+				p.op(OpAnyCharNotNL)
+			}
+			t = t[1:]
+		case '[':
+			if t, err = p.parseClass(t); err != nil {
+				return nil, err
+			}
+		case '*', '+', '?':
+			before := t
+			switch t[0] {
+			case '*':
+				op = OpStar
+			case '+':
+				op = OpPlus
+			case '?':
+				op = OpQuest
+			}
+			after := t[1:]
+			if after, err = p.repeat(op, 0, 0, before, after, lastRepeat); err != nil {
+				return nil, err
+			}
+			repeat = before
+			t = after
+		case '{':
+			op = OpRepeat
+			before := t
+			min, max, after, ok := p.parseRepeat(t)
+			if !ok {
+				// If the repeat cannot be parsed, { is a literal.
+				p.literal('{')
+				t = t[1:]
+				break
+			}
+			if min < 0 || min > 1000 || max > 1000 || max >= 0 && min > max {
+				// Numbers were too big, or max is present and min > max.
+				return nil, &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
+			}
+			if after, err = p.repeat(op, min, max, before, after, lastRepeat); err != nil {
+				return nil, err
+			}
+			repeat = before
+			t = after
+		case '\\':
+			if p.flags&PerlX != 0 && len(t) >= 2 {
+				switch t[1] {
+				case 'A':
+					p.op(OpBeginText)
+					t = t[2:]
+					break BigSwitch
+				case 'b':
+					p.op(OpWordBoundary)
+					t = t[2:]
+					break BigSwitch
+				case 'B':
+					p.op(OpNoWordBoundary)
+					t = t[2:]
+					break BigSwitch
+				case 'C':
+					// any byte; not supported
+					return nil, &Error{ErrInvalidEscape, t[:2]}
+				case 'Q':
+					// \Q ... \E: the ... is always literals
+					var lit string
+					if i := strings.Index(t, `\E`); i < 0 {
+						lit = t[2:]
+						t = ""
+					} else {
+						lit = t[2:i]
+						t = t[i+2:]
+					}
+					p.push(literalRegexp(lit, p.flags))
+					break BigSwitch
+				case 'z':
+					p.op(OpEndText)
+					t = t[2:]
+					break BigSwitch
+				}
+			}
+
+			re := p.newRegexp(OpCharClass)
+			re.Flags = p.flags
+
+			// Look for Unicode character group like \p{Han}
+			if len(t) >= 2 && (t[1] == 'p' || t[1] == 'P') {
+				r, rest, err := p.parseUnicodeClass(t, re.Rune0[:0])
+				if err != nil {
+					return nil, err
+				}
+				if r != nil {
+					re.Rune = r
+					t = rest
+					p.push(re)
+					break BigSwitch
+				}
+			}
+
+			// Perl character class escape.
+			if r, rest := p.parsePerlClassEscape(t, re.Rune0[:0]); r != nil {
+				re.Rune = r
+				t = rest
+				p.push(re)
+				break BigSwitch
+			}
+			p.reuse(re)
+
+			// Ordinary single-character escape.
+			if c, t, err = p.parseEscape(t); err != nil {
+				return nil, err
+			}
+			p.literal(c)
+		}
+		lastRepeat = repeat
+	}
+
+	p.concat()
+	if p.swapVerticalBar() {
+		// pop vertical bar
+		p.stack = p.stack[:len(p.stack)-1]
+	}
+	p.alternate()
+
+	n := len(p.stack)
+	if n != 1 {
+		return nil, &Error{ErrMissingParen, s}
+	}
+	return p.stack[0], nil
+}
+
+// parseRepeat parses {min} (max=min) or {min,} (max=-1) or {min,max}.
+// If s is not of that form, it returns ok == false.
+// If s has the right form but the values are too big, it returns min == -1, ok == true.
+func (p *parser) parseRepeat(s string) (min, max int, rest string, ok bool) {
+	if s == "" || s[0] != '{' {
+		return
+	}
+	s = s[1:]
+	var ok1 bool
+	if min, s, ok1 = p.parseInt(s); !ok1 {
+		return
+	}
+	if s == "" {
+		return
+	}
+	if s[0] != ',' {
+		max = min
+	} else {
+		s = s[1:]
+		if s == "" {
+			return
+		}
+		if s[0] == '}' {
+			max = -1
+		} else if max, s, ok1 = p.parseInt(s); !ok1 {
+			return
+		} else if max < 0 {
+			// parseInt found too big a number
+			min = -1
+		}
+	}
+	if s == "" || s[0] != '}' {
+		return
+	}
+	rest = s[1:]
+	ok = true
+	return
+}
+
+// parsePerlFlags parses a Perl flag setting or non-capturing group or both,
+// like (?i) or (?: or (?i:.  It removes the prefix from s and updates the parse state.
+// The caller must have ensured that s begins with "(?".
+func (p *parser) parsePerlFlags(s string) (rest string, err error) {
+	t := s
+
+	// Check for named captures, first introduced in Python's regexp library.
+	// As usual, there are three slightly different syntaxes:
+	//
+	//   (?P<name>expr)   the original, introduced by Python
+	//   (?<name>expr)    the .NET alteration, adopted by Perl 5.10
+	//   (?'name'expr)    another .NET alteration, adopted by Perl 5.10
+	//
+	// Perl 5.10 gave in and implemented the Python version too,
+	// but they claim that the last two are the preferred forms.
+	// PCRE and languages based on it (specifically, PHP and Ruby)
+	// support all three as well.  EcmaScript 4 uses only the Python form.
+	//
+	// In both the open source world (via Code Search) and the
+	// Google source tree, (?P<expr>name) is the dominant form,
+	// so that's the one we implement.  One is enough.
+	if len(t) > 4 && t[2] == 'P' && t[3] == '<' {
+		// Pull out name.
+		end := strings.IndexRune(t, '>')
+		if end < 0 {
+			if err = checkUTF8(t); err != nil {
+				return "", err
+			}
+			return "", &Error{ErrInvalidNamedCapture, s}
+		}
+
+		capture := t[:end+1] // "(?P<name>"
+		name := t[4:end]     // "name"
+		if err = checkUTF8(name); err != nil {
+			return "", err
+		}
+		if !isValidCaptureName(name) {
+			return "", &Error{ErrInvalidNamedCapture, capture}
+		}
+
+		// Like ordinary capture, but named.
+		p.numCap++
+		re := p.op(opLeftParen)
+		re.Cap = p.numCap
+		re.Name = name
+		return t[end+1:], nil
+	}
+
+	// Non-capturing group.  Might also twiddle Perl flags.
+	var c rune
+	t = t[2:] // skip (?
+	flags := p.flags
+	sign := +1
+	sawFlag := false
+Loop:
+	for t != "" {
+		if c, t, err = nextRune(t); err != nil {
+			return "", err
+		}
+		switch c {
+		default:
+			break Loop
+
+		// Flags.
+		case 'i':
+			flags |= FoldCase
+			sawFlag = true
+		case 'm':
+			flags &^= OneLine
+			sawFlag = true
+		case 's':
+			flags |= DotNL
+			sawFlag = true
+		case 'U':
+			flags |= NonGreedy
+			sawFlag = true
+
+		// Switch to negation.
+		case '-':
+			if sign < 0 {
+				break Loop
+			}
+			sign = -1
+			// Invert flags so that | above turn into &^ and vice versa.
+			// We'll invert flags again before using it below.
+			flags = ^flags
+			sawFlag = false
+
+		// End of flags, starting group or not.
+		case ':', ')':
+			if sign < 0 {
+				if !sawFlag {
+					break Loop
+				}
+				flags = ^flags
+			}
+			if c == ':' {
+				// Open new group
+				p.op(opLeftParen)
+			}
+			p.flags = flags
+			return t, nil
+		}
+	}
+
+	return "", &Error{ErrInvalidPerlOp, s[:len(s)-len(t)]}
+}
+
+// isValidCaptureName reports whether name
+// is a valid capture name: [A-Za-z0-9_]+.
+// PCRE limits names to 32 bytes.
+// Python rejects names starting with digits.
+// We don't enforce either of those.
+func isValidCaptureName(name string) bool {
+	if name == "" {
+		return false
+	}
+	for _, c := range name {
+		if c != '_' && !isalnum(c) {
+			return false
+		}
+	}
+	return true
+}
+
+// parseInt parses a decimal integer.
+func (p *parser) parseInt(s string) (n int, rest string, ok bool) {
+	if s == "" || s[0] < '0' || '9' < s[0] {
+		return
+	}
+	// Disallow leading zeros.
+	if len(s) >= 2 && s[0] == '0' && '0' <= s[1] && s[1] <= '9' {
+		return
+	}
+	t := s
+	for s != "" && '0' <= s[0] && s[0] <= '9' {
+		s = s[1:]
+	}
+	rest = s
+	ok = true
+	// Have digits, compute value.
+	t = t[:len(t)-len(s)]
+	for i := 0; i < len(t); i++ {
+		// Avoid overflow.
+		if n >= 1e8 {
+			n = -1
+			break
+		}
+		n = n*10 + int(t[i]) - '0'
+	}
+	return
+}
+
+// can this be represented as a character class?
+// single-rune literal string, char class, ., and .|\n.
+func isCharClass(re *Regexp) bool {
+	return re.Op == OpLiteral && len(re.Rune) == 1 ||
+		re.Op == OpCharClass ||
+		re.Op == OpAnyCharNotNL ||
+		re.Op == OpAnyChar
+}
+
+// does re match r?
+func matchRune(re *Regexp, r rune) bool {
+	switch re.Op {
+	case OpLiteral:
+		return len(re.Rune) == 1 && re.Rune[0] == r
+	case OpCharClass:
+		for i := 0; i < len(re.Rune); i += 2 {
+			if re.Rune[i] <= r && r <= re.Rune[i+1] {
+				return true
+			}
+		}
+		return false
+	case OpAnyCharNotNL:
+		return r != '\n'
+	case OpAnyChar:
+		return true
+	}
+	return false
+}
+
+// parseVerticalBar handles a | in the input.
+func (p *parser) parseVerticalBar() error {
+	p.concat()
+
+	// The concatenation we just parsed is on top of the stack.
+	// If it sits above an opVerticalBar, swap it below
+	// (things below an opVerticalBar become an alternation).
+	// Otherwise, push a new vertical bar.
+	if !p.swapVerticalBar() {
+		p.op(opVerticalBar)
+	}
+
+	return nil
+}
+
+// mergeCharClass makes dst = dst|src.
+// The caller must ensure that dst.Op >= src.Op,
+// to reduce the amount of copying.
+func mergeCharClass(dst, src *Regexp) {
+	switch dst.Op {
+	case OpAnyChar:
+		// src doesn't add anything.
+	case OpAnyCharNotNL:
+		// src might add \n
+		if matchRune(src, '\n') {
+			dst.Op = OpAnyChar
+		}
+	case OpCharClass:
+		// src is simpler, so either literal or char class
+		if src.Op == OpLiteral {
+			dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags)
+		} else {
+			dst.Rune = appendClass(dst.Rune, src.Rune)
+		}
+	case OpLiteral:
+		// both literal
+		if src.Rune[0] == dst.Rune[0] && src.Flags == dst.Flags {
+			break
+		}
+		dst.Op = OpCharClass
+		dst.Rune = appendLiteral(dst.Rune[:0], dst.Rune[0], dst.Flags)
+		dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags)
+	}
+}
+
+// If the top of the stack is an element followed by an opVerticalBar
+// swapVerticalBar swaps the two and returns true.
+// Otherwise it returns false.
+func (p *parser) swapVerticalBar() bool {
+	// If above and below vertical bar are literal or char class,
+	// can merge into a single char class.
+	n := len(p.stack)
+	if n >= 3 && p.stack[n-2].Op == opVerticalBar && isCharClass(p.stack[n-1]) && isCharClass(p.stack[n-3]) {
+		re1 := p.stack[n-1]
+		re3 := p.stack[n-3]
+		// Make re3 the more complex of the two.
+		if re1.Op > re3.Op {
+			re1, re3 = re3, re1
+			p.stack[n-3] = re3
+		}
+		mergeCharClass(re3, re1)
+		p.reuse(re1)
+		p.stack = p.stack[:n-1]
+		return true
+	}
+
+	if n >= 2 {
+		re1 := p.stack[n-1]
+		re2 := p.stack[n-2]
+		if re2.Op == opVerticalBar {
+			if n >= 3 {
+				// Now out of reach.
+				// Clean opportunistically.
+				cleanAlt(p.stack[n-3])
+			}
+			p.stack[n-2] = re1
+			p.stack[n-1] = re2
+			return true
+		}
+	}
+	return false
+}
+
+// parseRightParen handles a ) in the input.
+func (p *parser) parseRightParen() error {
+	p.concat()
+	if p.swapVerticalBar() {
+		// pop vertical bar
+		p.stack = p.stack[:len(p.stack)-1]
+	}
+	p.alternate()
+
+	n := len(p.stack)
+	if n < 2 {
+		return &Error{ErrUnexpectedParen, p.wholeRegexp}
+	}
+	re1 := p.stack[n-1]
+	re2 := p.stack[n-2]
+	p.stack = p.stack[:n-2]
+	if re2.Op != opLeftParen {
+		return &Error{ErrUnexpectedParen, p.wholeRegexp}
+	}
+	// Restore flags at time of paren.
+	p.flags = re2.Flags
+	if re2.Cap == 0 {
+		// Just for grouping.
+		p.push(re1)
+	} else {
+		re2.Op = OpCapture
+		re2.Sub = re2.Sub0[:1]
+		re2.Sub[0] = re1
+		p.push(re2)
+	}
+	return nil
+}
+
+// parseEscape parses an escape sequence at the beginning of s
+// and returns the rune.
+func (p *parser) parseEscape(s string) (r rune, rest string, err error) {
+	t := s[1:]
+	if t == "" {
+		return 0, "", &Error{ErrTrailingBackslash, ""}
+	}
+	c, t, err := nextRune(t)
+	if err != nil {
+		return 0, "", err
+	}
+
+Switch:
+	switch c {
+	default:
+		if c < utf8.RuneSelf && !isalnum(c) {
+			// Escaped non-word characters are always themselves.
+			// PCRE is not quite so rigorous: it accepts things like
+			// \q, but we don't.  We once rejected \_, but too many
+			// programs and people insist on using it, so allow \_.
+			return c, t, nil
+		}
+
+	// Octal escapes.
+	case '1', '2', '3', '4', '5', '6', '7':
+		// Single non-zero digit is a backreference; not supported
+		if t == "" || t[0] < '0' || t[0] > '7' {
+			break
+		}
+		fallthrough
+	case '0':
+		// Consume up to three octal digits; already have one.
+		r = c - '0'
+		for i := 1; i < 3; i++ {
+			if t == "" || t[0] < '0' || t[0] > '7' {
+				break
+			}
+			r = r*8 + rune(t[0]) - '0'
+			t = t[1:]
+		}
+		return r, t, nil
+
+	// Hexadecimal escapes.
+	case 'x':
+		if t == "" {
+			break
+		}
+		if c, t, err = nextRune(t); err != nil {
+			return 0, "", err
+		}
+		if c == '{' {
+			// Any number of digits in braces.
+			// Perl accepts any text at all; it ignores all text
+			// after the first non-hex digit.  We require only hex digits,
+			// and at least one.
+			nhex := 0
+			r = 0
+			for {
+				if t == "" {
+					break Switch
+				}
+				if c, t, err = nextRune(t); err != nil {
+					return 0, "", err
+				}
+				if c == '}' {
+					break
+				}
+				v := unhex(c)
+				if v < 0 {
+					break Switch
+				}
+				r = r*16 + v
+				if r > unicode.MaxRune {
+					break Switch
+				}
+				nhex++
+			}
+			if nhex == 0 {
+				break Switch
+			}
+			return r, t, nil
+		}
+
+		// Easy case: two hex digits.
+		x := unhex(c)
+		if c, t, err = nextRune(t); err != nil {
+			return 0, "", err
+		}
+		y := unhex(c)
+		if x < 0 || y < 0 {
+			break
+		}
+		return x*16 + y, t, nil
+
+	// C escapes.  There is no case 'b', to avoid misparsing
+	// the Perl word-boundary \b as the C backspace \b
+	// when in POSIX mode.  In Perl, /\b/ means word-boundary
+	// but /[\b]/ means backspace.  We don't support that.
+	// If you want a backspace, embed a literal backspace
+	// character or use \x08.
+	case 'a':
+		return '\a', t, err
+	case 'f':
+		return '\f', t, err
+	case 'n':
+		return '\n', t, err
+	case 'r':
+		return '\r', t, err
+	case 't':
+		return '\t', t, err
+	case 'v':
+		return '\v', t, err
+	}
+	return 0, "", &Error{ErrInvalidEscape, s[:len(s)-len(t)]}
+}
+
+// parseClassChar parses a character class character at the beginning of s
+// and returns it.
+func (p *parser) parseClassChar(s, wholeClass string) (r rune, rest string, err error) {
+	if s == "" {
+		return 0, "", &Error{Code: ErrMissingBracket, Expr: wholeClass}
+	}
+
+	// Allow regular escape sequences even though
+	// many need not be escaped in this context.
+	if s[0] == '\\' {
+		return p.parseEscape(s)
+	}
+
+	return nextRune(s)
+}
+
+type charGroup struct {
+	sign  int
+	class []rune
+}
+
+// parsePerlClassEscape parses a leading Perl character class escape like \d
+// from the beginning of s.  If one is present, it appends the characters to r
+// and returns the new slice r and the remainder of the string.
+func (p *parser) parsePerlClassEscape(s string, r []rune) (out []rune, rest string) {
+	if p.flags&PerlX == 0 || len(s) < 2 || s[0] != '\\' {
+		return
+	}
+	g := perlGroup[s[0:2]]
+	if g.sign == 0 {
+		return
+	}
+	return p.appendGroup(r, g), s[2:]
+}
+
+// parseNamedClass parses a leading POSIX named character class like [:alnum:]
+// from the beginning of s.  If one is present, it appends the characters to r
+// and returns the new slice r and the remainder of the string.
+func (p *parser) parseNamedClass(s string, r []rune) (out []rune, rest string, err error) {
+	if len(s) < 2 || s[0] != '[' || s[1] != ':' {
+		return
+	}
+
+	i := strings.Index(s[2:], ":]")
+	if i < 0 {
+		return
+	}
+	i += 2
+	name, s := s[0:i+2], s[i+2:]
+	g := posixGroup[name]
+	if g.sign == 0 {
+		return nil, "", &Error{ErrInvalidCharRange, name}
+	}
+	return p.appendGroup(r, g), s, nil
+}
+
+func (p *parser) appendGroup(r []rune, g charGroup) []rune {
+	if p.flags&FoldCase == 0 {
+		if g.sign < 0 {
+			r = appendNegatedClass(r, g.class)
+		} else {
+			r = appendClass(r, g.class)
+		}
+	} else {
+		tmp := p.tmpClass[:0]
+		tmp = appendFoldedClass(tmp, g.class)
+		p.tmpClass = tmp
+		tmp = cleanClass(&p.tmpClass)
+		if g.sign < 0 {
+			r = appendNegatedClass(r, tmp)
+		} else {
+			r = appendClass(r, tmp)
+		}
+	}
+	return r
+}
+
+var anyTable = &unicode.RangeTable{
+	R16: []unicode.Range16{{Lo: 0, Hi: 1<<16 - 1, Stride: 1}},
+	R32: []unicode.Range32{{Lo: 1 << 16, Hi: unicode.MaxRune, Stride: 1}},
+}
+
+// unicodeTable returns the unicode.RangeTable identified by name
+// and the table of additional fold-equivalent code points.
+func unicodeTable(name string) (*unicode.RangeTable, *unicode.RangeTable) {
+	// Special case: "Any" means any.
+	if name == "Any" {
+		return anyTable, anyTable
+	}
+	if t := unicode.Categories[name]; t != nil {
+		return t, unicode.FoldCategory[name]
+	}
+	if t := unicode.Scripts[name]; t != nil {
+		return t, unicode.FoldScript[name]
+	}
+	return nil, nil
+}
+
+// parseUnicodeClass parses a leading Unicode character class like \p{Han}
+// from the beginning of s.  If one is present, it appends the characters to r
+// and returns the new slice r and the remainder of the string.
+func (p *parser) parseUnicodeClass(s string, r []rune) (out []rune, rest string, err error) {
+	if p.flags&UnicodeGroups == 0 || len(s) < 2 || s[0] != '\\' || s[1] != 'p' && s[1] != 'P' {
+		return
+	}
+
+	// Committed to parse or return error.
+	sign := +1
+	if s[1] == 'P' {
+		sign = -1
+	}
+	t := s[2:]
+	c, t, err := nextRune(t)
+	if err != nil {
+		return
+	}
+	var seq, name string
+	if c != '{' {
+		// Single-letter name.
+		seq = s[:len(s)-len(t)]
+		name = seq[2:]
+	} else {
+		// Name is in braces.
+		end := strings.IndexRune(s, '}')
+		if end < 0 {
+			if err = checkUTF8(s); err != nil {
+				return
+			}
+			return nil, "", &Error{ErrInvalidCharRange, s}
+		}
+		seq, t = s[:end+1], s[end+1:]
+		name = s[3:end]
+		if err = checkUTF8(name); err != nil {
+			return
+		}
+	}
+
+	// Group can have leading negation too.  \p{^Han} == \P{Han}, \P{^Han} == \p{Han}.
+	if name != "" && name[0] == '^' {
+		sign = -sign
+		name = name[1:]
+	}
+
+	tab, fold := unicodeTable(name)
+	if tab == nil {
+		return nil, "", &Error{ErrInvalidCharRange, seq}
+	}
+
+	if p.flags&FoldCase == 0 || fold == nil {
+		if sign > 0 {
+			r = appendTable(r, tab)
+		} else {
+			r = appendNegatedTable(r, tab)
+		}
+	} else {
+		// Merge and clean tab and fold in a temporary buffer.
+		// This is necessary for the negative case and just tidy
+		// for the positive case.
+		tmp := p.tmpClass[:0]
+		tmp = appendTable(tmp, tab)
+		tmp = appendTable(tmp, fold)
+		p.tmpClass = tmp
+		tmp = cleanClass(&p.tmpClass)
+		if sign > 0 {
+			r = appendClass(r, tmp)
+		} else {
+			r = appendNegatedClass(r, tmp)
+		}
+	}
+	return r, t, nil
+}
+
+// parseClass parses a character class at the beginning of s
+// and pushes it onto the parse stack.
+func (p *parser) parseClass(s string) (rest string, err error) {
+	t := s[1:] // chop [
+	re := p.newRegexp(OpCharClass)
+	re.Flags = p.flags
+	re.Rune = re.Rune0[:0]
+
+	sign := +1
+	if t != "" && t[0] == '^' {
+		sign = -1
+		t = t[1:]
+
+		// If character class does not match \n, add it here,
+		// so that negation later will do the right thing.
+		if p.flags&ClassNL == 0 {
+			re.Rune = append(re.Rune, '\n', '\n')
+		}
+	}
+
+	class := re.Rune
+	first := true // ] and - are okay as first char in class
+	for t == "" || t[0] != ']' || first {
+		// POSIX: - is only okay unescaped as first or last in class.
+		// Perl: - is okay anywhere.
+		if t != "" && t[0] == '-' && p.flags&PerlX == 0 && !first && (len(t) == 1 || t[1] != ']') {
+			_, size := utf8.DecodeRuneInString(t[1:])
+			return "", &Error{Code: ErrInvalidCharRange, Expr: t[:1+size]}
+		}
+		first = false
+
+		// Look for POSIX [:alnum:] etc.
+		if len(t) > 2 && t[0] == '[' && t[1] == ':' {
+			nclass, nt, err := p.parseNamedClass(t, class)
+			if err != nil {
+				return "", err
+			}
+			if nclass != nil {
+				class, t = nclass, nt
+				continue
+			}
+		}
+
+		// Look for Unicode character group like \p{Han}.
+		nclass, nt, err := p.parseUnicodeClass(t, class)
+		if err != nil {
+			return "", err
+		}
+		if nclass != nil {
+			class, t = nclass, nt
+			continue
+		}
+
+		// Look for Perl character class symbols (extension).
+		if nclass, nt := p.parsePerlClassEscape(t, class); nclass != nil {
+			class, t = nclass, nt
+			continue
+		}
+
+		// Single character or simple range.
+		rng := t
+		var lo, hi rune
+		if lo, t, err = p.parseClassChar(t, s); err != nil {
+			return "", err
+		}
+		hi = lo
+		// [a-] means (a|-) so check for final ].
+		if len(t) >= 2 && t[0] == '-' && t[1] != ']' {
+			t = t[1:]
+			if hi, t, err = p.parseClassChar(t, s); err != nil {
+				return "", err
+			}
+			if hi < lo {
+				rng = rng[:len(rng)-len(t)]
+				return "", &Error{Code: ErrInvalidCharRange, Expr: rng}
+			}
+		}
+		if p.flags&FoldCase == 0 {
+			class = appendRange(class, lo, hi)
+		} else {
+			class = appendFoldedRange(class, lo, hi)
+		}
+	}
+	t = t[1:] // chop ]
+
+	// Use &re.Rune instead of &class to avoid allocation.
+	re.Rune = class
+	class = cleanClass(&re.Rune)
+	if sign < 0 {
+		class = negateClass(class)
+	}
+	re.Rune = class
+	p.push(re)
+	return t, nil
+}
+
+// cleanClass sorts the ranges (pairs of elements of r),
+// merges them, and eliminates duplicates.
+func cleanClass(rp *[]rune) []rune {
+
+	// Sort by lo increasing, hi decreasing to break ties.
+	sort.Sort(ranges{rp})
+
+	r := *rp
+	if len(r) < 2 {
+		return r
+	}
+
+	// Merge abutting, overlapping.
+	w := 2 // write index
+	for i := 2; i < len(r); i += 2 {
+		lo, hi := r[i], r[i+1]
+		if lo <= r[w-1]+1 {
+			// merge with previous range
+			if hi > r[w-1] {
+				r[w-1] = hi
+			}
+			continue
+		}
+		// new disjoint range
+		r[w] = lo
+		r[w+1] = hi
+		w += 2
+	}
+
+	return r[:w]
+}
+
+// appendLiteral returns the result of appending the literal x to the class r.
+func appendLiteral(r []rune, x rune, flags Flags) []rune {
+	if flags&FoldCase != 0 {
+		return appendFoldedRange(r, x, x)
+	}
+	return appendRange(r, x, x)
+}
+
+// appendRange returns the result of appending the range lo-hi to the class r.
+func appendRange(r []rune, lo, hi rune) []rune {
+	// Expand last range or next to last range if it overlaps or abuts.
+	// Checking two ranges helps when appending case-folded
+	// alphabets, so that one range can be expanding A-Z and the
+	// other expanding a-z.
+	n := len(r)
+	for i := 2; i <= 4; i += 2 { // twice, using i=2, i=4
+		if n >= i {
+			rlo, rhi := r[n-i], r[n-i+1]
+			if lo <= rhi+1 && rlo <= hi+1 {
+				if lo < rlo {
+					r[n-i] = lo
+				}
+				if hi > rhi {
+					r[n-i+1] = hi
+				}
+				return r
+			}
+		}
+	}
+
+	return append(r, lo, hi)
+}
+
+const (
+	// minimum and maximum runes involved in folding.
+	// checked during test.
+	minFold = 0x0041
+	maxFold = 0x1044f
+)
+
+// appendFoldedRange returns the result of appending the range lo-hi
+// and its case folding-equivalent runes to the class r.
+func appendFoldedRange(r []rune, lo, hi rune) []rune {
+	// Optimizations.
+	if lo <= minFold && hi >= maxFold {
+		// Range is full: folding can't add more.
+		return appendRange(r, lo, hi)
+	}
+	if hi < minFold || lo > maxFold {
+		// Range is outside folding possibilities.
+		return appendRange(r, lo, hi)
+	}
+	if lo < minFold {
+		// [lo, minFold-1] needs no folding.
+		r = appendRange(r, lo, minFold-1)
+		lo = minFold
+	}
+	if hi > maxFold {
+		// [maxFold+1, hi] needs no folding.
+		r = appendRange(r, maxFold+1, hi)
+		hi = maxFold
+	}
+
+	// Brute force.  Depend on appendRange to coalesce ranges on the fly.
+	for c := lo; c <= hi; c++ {
+		r = appendRange(r, c, c)
+		f := unicode.SimpleFold(c)
+		for f != c {
+			r = appendRange(r, f, f)
+			f = unicode.SimpleFold(f)
+		}
+	}
+	return r
+}
+
+// appendClass returns the result of appending the class x to the class r.
+// It assume x is clean.
+func appendClass(r []rune, x []rune) []rune {
+	for i := 0; i < len(x); i += 2 {
+		r = appendRange(r, x[i], x[i+1])
+	}
+	return r
+}
+
+// appendFolded returns the result of appending the case folding of the class x to the class r.
+func appendFoldedClass(r []rune, x []rune) []rune {
+	for i := 0; i < len(x); i += 2 {
+		r = appendFoldedRange(r, x[i], x[i+1])
+	}
+	return r
+}
+
+// appendNegatedClass returns the result of appending the negation of the class x to the class r.
+// It assumes x is clean.
+func appendNegatedClass(r []rune, x []rune) []rune {
+	nextLo := '\u0000'
+	for i := 0; i < len(x); i += 2 {
+		lo, hi := x[i], x[i+1]
+		if nextLo <= lo-1 {
+			r = appendRange(r, nextLo, lo-1)
+		}
+		nextLo = hi + 1
+	}
+	if nextLo <= unicode.MaxRune {
+		r = appendRange(r, nextLo, unicode.MaxRune)
+	}
+	return r
+}
+
+// appendTable returns the result of appending x to the class r.
+func appendTable(r []rune, x *unicode.RangeTable) []rune {
+	for _, xr := range x.R16 {
+		lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
+		if stride == 1 {
+			r = appendRange(r, lo, hi)
+			continue
+		}
+		for c := lo; c <= hi; c += stride {
+			r = appendRange(r, c, c)
+		}
+	}
+	for _, xr := range x.R32 {
+		lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
+		if stride == 1 {
+			r = appendRange(r, lo, hi)
+			continue
+		}
+		for c := lo; c <= hi; c += stride {
+			r = appendRange(r, c, c)
+		}
+	}
+	return r
+}
+
+// appendNegatedTable returns the result of appending the negation of x to the class r.
+func appendNegatedTable(r []rune, x *unicode.RangeTable) []rune {
+	nextLo := '\u0000' // lo end of next class to add
+	for _, xr := range x.R16 {
+		lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
+		if stride == 1 {
+			if nextLo <= lo-1 {
+				r = appendRange(r, nextLo, lo-1)
+			}
+			nextLo = hi + 1
+			continue
+		}
+		for c := lo; c <= hi; c += stride {
+			if nextLo <= c-1 {
+				r = appendRange(r, nextLo, c-1)
+			}
+			nextLo = c + 1
+		}
+	}
+	for _, xr := range x.R32 {
+		lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
+		if stride == 1 {
+			if nextLo <= lo-1 {
+				r = appendRange(r, nextLo, lo-1)
+			}
+			nextLo = hi + 1
+			continue
+		}
+		for c := lo; c <= hi; c += stride {
+			if nextLo <= c-1 {
+				r = appendRange(r, nextLo, c-1)
+			}
+			nextLo = c + 1
+		}
+	}
+	if nextLo <= unicode.MaxRune {
+		r = appendRange(r, nextLo, unicode.MaxRune)
+	}
+	return r
+}
+
+// negateClass overwrites r and returns r's negation.
+// It assumes the class r is already clean.
+func negateClass(r []rune) []rune {
+	nextLo := '\u0000' // lo end of next class to add
+	w := 0             // write index
+	for i := 0; i < len(r); i += 2 {
+		lo, hi := r[i], r[i+1]
+		if nextLo <= lo-1 {
+			r[w] = nextLo
+			r[w+1] = lo - 1
+			w += 2
+		}
+		nextLo = hi + 1
+	}
+	r = r[:w]
+	if nextLo <= unicode.MaxRune {
+		// It's possible for the negation to have one more
+		// range - this one - than the original class, so use append.
+		r = append(r, nextLo, unicode.MaxRune)
+	}
+	return r
+}
+
+// ranges implements sort.Interface on a []rune.
+// The choice of receiver type definition is strange
+// but avoids an allocation since we already have
+// a *[]rune.
+type ranges struct {
+	p *[]rune
+}
+
+func (ra ranges) Less(i, j int) bool {
+	p := *ra.p
+	i *= 2
+	j *= 2
+	return p[i] < p[j] || p[i] == p[j] && p[i+1] > p[j+1]
+}
+
+func (ra ranges) Len() int {
+	return len(*ra.p) / 2
+}
+
+func (ra ranges) Swap(i, j int) {
+	p := *ra.p
+	i *= 2
+	j *= 2
+	p[i], p[i+1], p[j], p[j+1] = p[j], p[j+1], p[i], p[i+1]
+}
+
+func checkUTF8(s string) error {
+	for s != "" {
+		rune, size := utf8.DecodeRuneInString(s)
+		if rune == utf8.RuneError && size == 1 {
+			return &Error{Code: ErrInvalidUTF8, Expr: s}
+		}
+		s = s[size:]
+	}
+	return nil
+}
+
+func nextRune(s string) (c rune, t string, err error) {
+	c, size := utf8.DecodeRuneInString(s)
+	if c == utf8.RuneError && size == 1 {
+		return 0, "", &Error{Code: ErrInvalidUTF8, Expr: s}
+	}
+	return c, s[size:], nil
+}
+
+func isalnum(c rune) bool {
+	return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
+}
+
+func unhex(c rune) rune {
+	if '0' <= c && c <= '9' {
+		return c - '0'
+	}
+	if 'a' <= c && c <= 'f' {
+		return c - 'a' + 10
+	}
+	if 'A' <= c && c <= 'F' {
+		return c - 'A' + 10
+	}
+	return -1
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/syntax/parse_test.go b/third_party/gofrontend/libgo/go/regexp/syntax/parse_test.go
new file mode 100644
index 0000000..f308929
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/syntax/parse_test.go
@@ -0,0 +1,559 @@
+// 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.
+
+package syntax
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+	"unicode"
+)
+
+type parseTest struct {
+	Regexp string
+	Dump   string
+}
+
+var parseTests = []parseTest{
+	// Base cases
+	{`a`, `lit{a}`},
+	{`a.`, `cat{lit{a}dot{}}`},
+	{`a.b`, `cat{lit{a}dot{}lit{b}}`},
+	{`ab`, `str{ab}`},
+	{`a.b.c`, `cat{lit{a}dot{}lit{b}dot{}lit{c}}`},
+	{`abc`, `str{abc}`},
+	{`a|^`, `alt{lit{a}bol{}}`},
+	{`a|b`, `cc{0x61-0x62}`},
+	{`(a)`, `cap{lit{a}}`},
+	{`(a)|b`, `alt{cap{lit{a}}lit{b}}`},
+	{`a*`, `star{lit{a}}`},
+	{`a+`, `plus{lit{a}}`},
+	{`a?`, `que{lit{a}}`},
+	{`a{2}`, `rep{2,2 lit{a}}`},
+	{`a{2,3}`, `rep{2,3 lit{a}}`},
+	{`a{2,}`, `rep{2,-1 lit{a}}`},
+	{`a*?`, `nstar{lit{a}}`},
+	{`a+?`, `nplus{lit{a}}`},
+	{`a??`, `nque{lit{a}}`},
+	{`a{2}?`, `nrep{2,2 lit{a}}`},
+	{`a{2,3}?`, `nrep{2,3 lit{a}}`},
+	{`a{2,}?`, `nrep{2,-1 lit{a}}`},
+	// Malformed { } are treated as literals.
+	{`x{1001`, `str{x{1001}`},
+	{`x{9876543210`, `str{x{9876543210}`},
+	{`x{9876543210,`, `str{x{9876543210,}`},
+	{`x{2,1`, `str{x{2,1}`},
+	{`x{1,9876543210`, `str{x{1,9876543210}`},
+	{``, `emp{}`},
+	{`|`, `emp{}`}, // alt{emp{}emp{}} but got factored
+	{`|x|`, `alt{emp{}lit{x}emp{}}`},
+	{`.`, `dot{}`},
+	{`^`, `bol{}`},
+	{`$`, `eol{}`},
+	{`\|`, `lit{|}`},
+	{`\(`, `lit{(}`},
+	{`\)`, `lit{)}`},
+	{`\*`, `lit{*}`},
+	{`\+`, `lit{+}`},
+	{`\?`, `lit{?}`},
+	{`{`, `lit{{}`},
+	{`}`, `lit{}}`},
+	{`\.`, `lit{.}`},
+	{`\^`, `lit{^}`},
+	{`\$`, `lit{$}`},
+	{`\\`, `lit{\}`},
+	{`[ace]`, `cc{0x61 0x63 0x65}`},
+	{`[abc]`, `cc{0x61-0x63}`},
+	{`[a-z]`, `cc{0x61-0x7a}`},
+	{`[a]`, `lit{a}`},
+	{`\-`, `lit{-}`},
+	{`-`, `lit{-}`},
+	{`\_`, `lit{_}`},
+	{`abc`, `str{abc}`},
+	{`abc|def`, `alt{str{abc}str{def}}`},
+	{`abc|def|ghi`, `alt{str{abc}str{def}str{ghi}}`},
+
+	// Posix and Perl extensions
+	{`[[:lower:]]`, `cc{0x61-0x7a}`},
+	{`[a-z]`, `cc{0x61-0x7a}`},
+	{`[^[:lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`},
+	{`[[:^lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`},
+	{`(?i)[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+	{`(?i)[a-z]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+	{`(?i)[^[:lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
+	{`(?i)[[:^lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
+	{`\d`, `cc{0x30-0x39}`},
+	{`\D`, `cc{0x0-0x2f 0x3a-0x10ffff}`},
+	{`\s`, `cc{0x9-0xa 0xc-0xd 0x20}`},
+	{`\S`, `cc{0x0-0x8 0xb 0xe-0x1f 0x21-0x10ffff}`},
+	{`\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a}`},
+	{`\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x10ffff}`},
+	{`(?i)\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a 0x17f 0x212a}`},
+	{`(?i)\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
+	{`[^\\]`, `cc{0x0-0x5b 0x5d-0x10ffff}`},
+	//	{ `\C`, `byte{}` },  // probably never
+
+	// Unicode, negatives, and a double negative.
+	{`\p{Braille}`, `cc{0x2800-0x28ff}`},
+	{`\P{Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+	{`\p{^Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+	{`\P{^Braille}`, `cc{0x2800-0x28ff}`},
+	{`\pZ`, `cc{0x20 0xa0 0x1680 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`},
+	{`[\p{Braille}]`, `cc{0x2800-0x28ff}`},
+	{`[\P{Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+	{`[\p{^Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+	{`[\P{^Braille}]`, `cc{0x2800-0x28ff}`},
+	{`[\pZ]`, `cc{0x20 0xa0 0x1680 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`},
+	{`\p{Lu}`, mkCharClass(unicode.IsUpper)},
+	{`[\p{Lu}]`, mkCharClass(unicode.IsUpper)},
+	{`(?i)[\p{Lu}]`, mkCharClass(isUpperFold)},
+	{`\p{Any}`, `dot{}`},
+	{`\p{^Any}`, `cc{}`},
+
+	// Hex, octal.
+	{`[\012-\234]\141`, `cat{cc{0xa-0x9c}lit{a}}`},
+	{`[\x{41}-\x7a]\x61`, `cat{cc{0x41-0x7a}lit{a}}`},
+
+	// More interesting regular expressions.
+	{`a{,2}`, `str{a{,2}}`},
+	{`\.\^\$\\`, `str{.^$\}`},
+	{`[a-zABC]`, `cc{0x41-0x43 0x61-0x7a}`},
+	{`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`},
+	{`[α-ε☺]`, `cc{0x3b1-0x3b5 0x263a}`}, // utf-8
+	{`a*{`, `cat{star{lit{a}}lit{{}}`},
+
+	// Test precedences
+	{`(?:ab)*`, `star{str{ab}}`},
+	{`(ab)*`, `star{cap{str{ab}}}`},
+	{`ab|cd`, `alt{str{ab}str{cd}}`},
+	{`a(b|c)d`, `cat{lit{a}cap{cc{0x62-0x63}}lit{d}}`},
+
+	// Test flattening.
+	{`(?:a)`, `lit{a}`},
+	{`(?:ab)(?:cd)`, `str{abcd}`},
+	{`(?:a+b+)(?:c+d+)`, `cat{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`},
+	{`(?:a+|b+)|(?:c+|d+)`, `alt{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`},
+	{`(?:a|b)|(?:c|d)`, `cc{0x61-0x64}`},
+	{`a|.`, `dot{}`},
+	{`.|a`, `dot{}`},
+	{`(?:[abc]|A|Z|hello|world)`, `alt{cc{0x41 0x5a 0x61-0x63}str{hello}str{world}}`},
+	{`(?:[abc]|A|Z)`, `cc{0x41 0x5a 0x61-0x63}`},
+
+	// Test Perl quoted literals
+	{`\Q+|*?{[\E`, `str{+|*?{[}`},
+	{`\Q+\E+`, `plus{lit{+}}`},
+	{`\Q\\E`, `lit{\}`},
+	{`\Q\\\E`, `str{\\}`},
+
+	// Test Perl \A and \z
+	{`(?m)^`, `bol{}`},
+	{`(?m)$`, `eol{}`},
+	{`(?-m)^`, `bot{}`},
+	{`(?-m)$`, `eot{}`},
+	{`(?m)\A`, `bot{}`},
+	{`(?m)\z`, `eot{\z}`},
+	{`(?-m)\A`, `bot{}`},
+	{`(?-m)\z`, `eot{\z}`},
+
+	// Test named captures
+	{`(?P<name>a)`, `cap{name:lit{a}}`},
+
+	// Case-folded literals
+	{`[Aa]`, `litfold{A}`},
+	{`[\x{100}\x{101}]`, `litfold{Ā}`},
+	{`[Δδ]`, `litfold{Δ}`},
+
+	// Strings
+	{`abcde`, `str{abcde}`},
+	{`[Aa][Bb]cd`, `cat{strfold{AB}str{cd}}`},
+
+	// Factoring.
+	{`abc|abd|aef|bcx|bcy`, `alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}cat{str{bc}cc{0x78-0x79}}}`},
+	{`ax+y|ax+z|ay+w`, `cat{lit{a}alt{cat{plus{lit{x}}cc{0x79-0x7a}}cat{plus{lit{y}}lit{w}}}}`},
+
+	// Bug fixes.
+	{`(?:.)`, `dot{}`},
+	{`(?:x|(?:xa))`, `cat{lit{x}alt{emp{}lit{a}}}`},
+	{`(?:.|(?:.a))`, `cat{dot{}alt{emp{}lit{a}}}`},
+	{`(?:A(?:A|a))`, `cat{lit{A}litfold{A}}`},
+	{`(?:A|a)`, `litfold{A}`},
+	{`A|(?:A|a)`, `litfold{A}`},
+	{`(?s).`, `dot{}`},
+	{`(?-s).`, `dnl{}`},
+	{`(?:(?:^).)`, `cat{bol{}dot{}}`},
+	{`(?-s)(?:(?:^).)`, `cat{bol{}dnl{}}`},
+
+	// RE2 prefix_tests
+	{`abc|abd`, `cat{str{ab}cc{0x63-0x64}}`},
+	{`a(?:b)c|abd`, `cat{str{ab}cc{0x63-0x64}}`},
+	{`abc|abd|aef|bcx|bcy`,
+		`alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}` +
+			`cat{str{bc}cc{0x78-0x79}}}`},
+	{`abc|x|abd`, `alt{str{abc}lit{x}str{abd}}`},
+	{`(?i)abc|ABD`, `cat{strfold{AB}cc{0x43-0x44 0x63-0x64}}`},
+	{`[ab]c|[ab]d`, `cat{cc{0x61-0x62}cc{0x63-0x64}}`},
+	{`(?:xx|yy)c|(?:xx|yy)d`,
+		`cat{alt{str{xx}str{yy}}cc{0x63-0x64}}`},
+	{`x{2}|x{2}[0-9]`,
+		`cat{rep{2,2 lit{x}}alt{emp{}cc{0x30-0x39}}}`},
+	{`x{2}y|x{2}[0-9]y`,
+		`cat{rep{2,2 lit{x}}alt{lit{y}cat{cc{0x30-0x39}lit{y}}}}`},
+}
+
+const testFlags = MatchNL | PerlX | UnicodeGroups
+
+func TestParseSimple(t *testing.T) {
+	testParseDump(t, parseTests, testFlags)
+}
+
+var foldcaseTests = []parseTest{
+	{`AbCdE`, `strfold{ABCDE}`},
+	{`[Aa]`, `litfold{A}`},
+	{`a`, `litfold{A}`},
+
+	// 0x17F is an old English long s (looks like an f) and folds to s.
+	// 0x212A is the Kelvin symbol and folds to k.
+	{`A[F-g]`, `cat{litfold{A}cc{0x41-0x7a 0x17f 0x212a}}`}, // [Aa][A-z...]
+	{`[[:upper:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+	{`[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+}
+
+func TestParseFoldCase(t *testing.T) {
+	testParseDump(t, foldcaseTests, FoldCase)
+}
+
+var literalTests = []parseTest{
+	{"(|)^$.[*+?]{5,10},\\", "str{(|)^$.[*+?]{5,10},\\}"},
+}
+
+func TestParseLiteral(t *testing.T) {
+	testParseDump(t, literalTests, Literal)
+}
+
+var matchnlTests = []parseTest{
+	{`.`, `dot{}`},
+	{"\n", "lit{\n}"},
+	{`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`},
+	{`[a\n]`, `cc{0xa 0x61}`},
+}
+
+func TestParseMatchNL(t *testing.T) {
+	testParseDump(t, matchnlTests, MatchNL)
+}
+
+var nomatchnlTests = []parseTest{
+	{`.`, `dnl{}`},
+	{"\n", "lit{\n}"},
+	{`[^a]`, `cc{0x0-0x9 0xb-0x60 0x62-0x10ffff}`},
+	{`[a\n]`, `cc{0xa 0x61}`},
+}
+
+func TestParseNoMatchNL(t *testing.T) {
+	testParseDump(t, nomatchnlTests, 0)
+}
+
+// Test Parse -> Dump.
+func testParseDump(t *testing.T, tests []parseTest, flags Flags) {
+	for _, tt := range tests {
+		re, err := Parse(tt.Regexp, flags)
+		if err != nil {
+			t.Errorf("Parse(%#q): %v", tt.Regexp, err)
+			continue
+		}
+		d := dump(re)
+		if d != tt.Dump {
+			t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
+		}
+	}
+}
+
+// dump prints a string representation of the regexp showing
+// the structure explicitly.
+func dump(re *Regexp) string {
+	var b bytes.Buffer
+	dumpRegexp(&b, re)
+	return b.String()
+}
+
+var opNames = []string{
+	OpNoMatch:        "no",
+	OpEmptyMatch:     "emp",
+	OpLiteral:        "lit",
+	OpCharClass:      "cc",
+	OpAnyCharNotNL:   "dnl",
+	OpAnyChar:        "dot",
+	OpBeginLine:      "bol",
+	OpEndLine:        "eol",
+	OpBeginText:      "bot",
+	OpEndText:        "eot",
+	OpWordBoundary:   "wb",
+	OpNoWordBoundary: "nwb",
+	OpCapture:        "cap",
+	OpStar:           "star",
+	OpPlus:           "plus",
+	OpQuest:          "que",
+	OpRepeat:         "rep",
+	OpConcat:         "cat",
+	OpAlternate:      "alt",
+}
+
+// dumpRegexp writes an encoding of the syntax tree for the regexp re to b.
+// It is used during testing to distinguish between parses that might print
+// the same using re's String method.
+func dumpRegexp(b *bytes.Buffer, re *Regexp) {
+	if int(re.Op) >= len(opNames) || opNames[re.Op] == "" {
+		fmt.Fprintf(b, "op%d", re.Op)
+	} else {
+		switch re.Op {
+		default:
+			b.WriteString(opNames[re.Op])
+		case OpStar, OpPlus, OpQuest, OpRepeat:
+			if re.Flags&NonGreedy != 0 {
+				b.WriteByte('n')
+			}
+			b.WriteString(opNames[re.Op])
+		case OpLiteral:
+			if len(re.Rune) > 1 {
+				b.WriteString("str")
+			} else {
+				b.WriteString("lit")
+			}
+			if re.Flags&FoldCase != 0 {
+				for _, r := range re.Rune {
+					if unicode.SimpleFold(r) != r {
+						b.WriteString("fold")
+						break
+					}
+				}
+			}
+		}
+	}
+	b.WriteByte('{')
+	switch re.Op {
+	case OpEndText:
+		if re.Flags&WasDollar == 0 {
+			b.WriteString(`\z`)
+		}
+	case OpLiteral:
+		for _, r := range re.Rune {
+			b.WriteRune(r)
+		}
+	case OpConcat, OpAlternate:
+		for _, sub := range re.Sub {
+			dumpRegexp(b, sub)
+		}
+	case OpStar, OpPlus, OpQuest:
+		dumpRegexp(b, re.Sub[0])
+	case OpRepeat:
+		fmt.Fprintf(b, "%d,%d ", re.Min, re.Max)
+		dumpRegexp(b, re.Sub[0])
+	case OpCapture:
+		if re.Name != "" {
+			b.WriteString(re.Name)
+			b.WriteByte(':')
+		}
+		dumpRegexp(b, re.Sub[0])
+	case OpCharClass:
+		sep := ""
+		for i := 0; i < len(re.Rune); i += 2 {
+			b.WriteString(sep)
+			sep = " "
+			lo, hi := re.Rune[i], re.Rune[i+1]
+			if lo == hi {
+				fmt.Fprintf(b, "%#x", lo)
+			} else {
+				fmt.Fprintf(b, "%#x-%#x", lo, hi)
+			}
+		}
+	}
+	b.WriteByte('}')
+}
+
+func mkCharClass(f func(rune) bool) string {
+	re := &Regexp{Op: OpCharClass}
+	lo := rune(-1)
+	for i := rune(0); i <= unicode.MaxRune; i++ {
+		if f(i) {
+			if lo < 0 {
+				lo = i
+			}
+		} else {
+			if lo >= 0 {
+				re.Rune = append(re.Rune, lo, i-1)
+				lo = -1
+			}
+		}
+	}
+	if lo >= 0 {
+		re.Rune = append(re.Rune, lo, unicode.MaxRune)
+	}
+	return dump(re)
+}
+
+func isUpperFold(r rune) bool {
+	if unicode.IsUpper(r) {
+		return true
+	}
+	c := unicode.SimpleFold(r)
+	for c != r {
+		if unicode.IsUpper(c) {
+			return true
+		}
+		c = unicode.SimpleFold(c)
+	}
+	return false
+}
+
+func TestFoldConstants(t *testing.T) {
+	last := rune(-1)
+	for i := rune(0); i <= unicode.MaxRune; i++ {
+		if unicode.SimpleFold(i) == i {
+			continue
+		}
+		if last == -1 && minFold != i {
+			t.Errorf("minFold=%#U should be %#U", minFold, i)
+		}
+		last = i
+	}
+	if maxFold != last {
+		t.Errorf("maxFold=%#U should be %#U", maxFold, last)
+	}
+}
+
+func TestAppendRangeCollapse(t *testing.T) {
+	// AppendRange should collapse each of the new ranges
+	// into the earlier ones (it looks back two ranges), so that
+	// the slice never grows very large.
+	// Note that we are not calling cleanClass.
+	var r []rune
+	for i := rune('A'); i <= 'Z'; i++ {
+		r = appendRange(r, i, i)
+		r = appendRange(r, i+'a'-'A', i+'a'-'A')
+	}
+	if string(r) != "AZaz" {
+		t.Errorf("appendRange interlaced A-Z a-z = %s, want AZaz", string(r))
+	}
+}
+
+var invalidRegexps = []string{
+	`(`,
+	`)`,
+	`(a`,
+	`a)`,
+	`(a))`,
+	`(a|b|`,
+	`a|b|)`,
+	`(a|b|))`,
+	`(a|b`,
+	`a|b)`,
+	`(a|b))`,
+	`[a-z`,
+	`([a-z)`,
+	`[a-z)`,
+	`([a-z]))`,
+	`x{1001}`,
+	`x{9876543210}`,
+	`x{2,1}`,
+	`x{1,9876543210}`,
+	"\xff", // Invalid UTF-8
+	"[\xff]",
+	"[\\\xff]",
+	"\\\xff",
+	`(?P<name>a`,
+	`(?P<name>`,
+	`(?P<name`,
+	`(?P<x y>a)`,
+	`(?P<>a)`,
+	`[a-Z]`,
+	`(?i)[a-Z]`,
+	`a{100000}`,
+	`a{100000,}`,
+}
+
+var onlyPerl = []string{
+	`[a-b-c]`,
+	`\Qabc\E`,
+	`\Q*+?{[\E`,
+	`\Q\\E`,
+	`\Q\\\E`,
+	`\Q\\\\E`,
+	`\Q\\\\\E`,
+	`(?:a)`,
+	`(?P<name>a)`,
+}
+
+var onlyPOSIX = []string{
+	"a++",
+	"a**",
+	"a?*",
+	"a+*",
+	"a{1}*",
+	".{1}{2}.{3}",
+}
+
+func TestParseInvalidRegexps(t *testing.T) {
+	for _, regexp := range invalidRegexps {
+		if re, err := Parse(regexp, Perl); err == nil {
+			t.Errorf("Parse(%#q, Perl) = %s, should have failed", regexp, dump(re))
+		}
+		if re, err := Parse(regexp, POSIX); err == nil {
+			t.Errorf("Parse(%#q, POSIX) = %s, should have failed", regexp, dump(re))
+		}
+	}
+	for _, regexp := range onlyPerl {
+		if _, err := Parse(regexp, Perl); err != nil {
+			t.Errorf("Parse(%#q, Perl): %v", regexp, err)
+		}
+		if re, err := Parse(regexp, POSIX); err == nil {
+			t.Errorf("Parse(%#q, POSIX) = %s, should have failed", regexp, dump(re))
+		}
+	}
+	for _, regexp := range onlyPOSIX {
+		if re, err := Parse(regexp, Perl); err == nil {
+			t.Errorf("Parse(%#q, Perl) = %s, should have failed", regexp, dump(re))
+		}
+		if _, err := Parse(regexp, POSIX); err != nil {
+			t.Errorf("Parse(%#q, POSIX): %v", regexp, err)
+		}
+	}
+}
+
+func TestToStringEquivalentParse(t *testing.T) {
+	for _, tt := range parseTests {
+		re, err := Parse(tt.Regexp, testFlags)
+		if err != nil {
+			t.Errorf("Parse(%#q): %v", tt.Regexp, err)
+			continue
+		}
+		d := dump(re)
+		if d != tt.Dump {
+			t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
+			continue
+		}
+
+		s := re.String()
+		if s != tt.Regexp {
+			// If ToString didn't return the original regexp,
+			// it must have found one with fewer parens.
+			// Unfortunately we can't check the length here, because
+			// ToString produces "\\{" for a literal brace,
+			// but "{" is a shorter equivalent in some contexts.
+			nre, err := Parse(s, testFlags)
+			if err != nil {
+				t.Errorf("Parse(%#q.String() = %#q): %v", tt.Regexp, s, err)
+				continue
+			}
+			nd := dump(nre)
+			if d != nd {
+				t.Errorf("Parse(%#q) -> %#q; %#q vs %#q", tt.Regexp, s, d, nd)
+			}
+
+			ns := nre.String()
+			if s != ns {
+				t.Errorf("Parse(%#q) -> %#q -> %#q", tt.Regexp, s, ns)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/syntax/perl_groups.go b/third_party/gofrontend/libgo/go/regexp/syntax/perl_groups.go
new file mode 100644
index 0000000..effe4e6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/syntax/perl_groups.go
@@ -0,0 +1,134 @@
+// Copyright 2013 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.
+
+// GENERATED BY make_perl_groups.pl; DO NOT EDIT.
+// make_perl_groups.pl >perl_groups.go
+
+package syntax
+
+var code1 = []rune{ /* \d */
+	0x30, 0x39,
+}
+
+var code2 = []rune{ /* \s */
+	0x9, 0xa,
+	0xc, 0xd,
+	0x20, 0x20,
+}
+
+var code3 = []rune{ /* \w */
+	0x30, 0x39,
+	0x41, 0x5a,
+	0x5f, 0x5f,
+	0x61, 0x7a,
+}
+
+var perlGroup = map[string]charGroup{
+	`\d`: {+1, code1},
+	`\D`: {-1, code1},
+	`\s`: {+1, code2},
+	`\S`: {-1, code2},
+	`\w`: {+1, code3},
+	`\W`: {-1, code3},
+}
+var code4 = []rune{ /* [:alnum:] */
+	0x30, 0x39,
+	0x41, 0x5a,
+	0x61, 0x7a,
+}
+
+var code5 = []rune{ /* [:alpha:] */
+	0x41, 0x5a,
+	0x61, 0x7a,
+}
+
+var code6 = []rune{ /* [:ascii:] */
+	0x0, 0x7f,
+}
+
+var code7 = []rune{ /* [:blank:] */
+	0x9, 0x9,
+	0x20, 0x20,
+}
+
+var code8 = []rune{ /* [:cntrl:] */
+	0x0, 0x1f,
+	0x7f, 0x7f,
+}
+
+var code9 = []rune{ /* [:digit:] */
+	0x30, 0x39,
+}
+
+var code10 = []rune{ /* [:graph:] */
+	0x21, 0x7e,
+}
+
+var code11 = []rune{ /* [:lower:] */
+	0x61, 0x7a,
+}
+
+var code12 = []rune{ /* [:print:] */
+	0x20, 0x7e,
+}
+
+var code13 = []rune{ /* [:punct:] */
+	0x21, 0x2f,
+	0x3a, 0x40,
+	0x5b, 0x60,
+	0x7b, 0x7e,
+}
+
+var code14 = []rune{ /* [:space:] */
+	0x9, 0xd,
+	0x20, 0x20,
+}
+
+var code15 = []rune{ /* [:upper:] */
+	0x41, 0x5a,
+}
+
+var code16 = []rune{ /* [:word:] */
+	0x30, 0x39,
+	0x41, 0x5a,
+	0x5f, 0x5f,
+	0x61, 0x7a,
+}
+
+var code17 = []rune{ /* [:xdigit:] */
+	0x30, 0x39,
+	0x41, 0x46,
+	0x61, 0x66,
+}
+
+var posixGroup = map[string]charGroup{
+	`[:alnum:]`:   {+1, code4},
+	`[:^alnum:]`:  {-1, code4},
+	`[:alpha:]`:   {+1, code5},
+	`[:^alpha:]`:  {-1, code5},
+	`[:ascii:]`:   {+1, code6},
+	`[:^ascii:]`:  {-1, code6},
+	`[:blank:]`:   {+1, code7},
+	`[:^blank:]`:  {-1, code7},
+	`[:cntrl:]`:   {+1, code8},
+	`[:^cntrl:]`:  {-1, code8},
+	`[:digit:]`:   {+1, code9},
+	`[:^digit:]`:  {-1, code9},
+	`[:graph:]`:   {+1, code10},
+	`[:^graph:]`:  {-1, code10},
+	`[:lower:]`:   {+1, code11},
+	`[:^lower:]`:  {-1, code11},
+	`[:print:]`:   {+1, code12},
+	`[:^print:]`:  {-1, code12},
+	`[:punct:]`:   {+1, code13},
+	`[:^punct:]`:  {-1, code13},
+	`[:space:]`:   {+1, code14},
+	`[:^space:]`:  {-1, code14},
+	`[:upper:]`:   {+1, code15},
+	`[:^upper:]`:  {-1, code15},
+	`[:word:]`:    {+1, code16},
+	`[:^word:]`:   {-1, code16},
+	`[:xdigit:]`:  {+1, code17},
+	`[:^xdigit:]`: {-1, code17},
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/syntax/prog.go b/third_party/gofrontend/libgo/go/regexp/syntax/prog.go
new file mode 100644
index 0000000..29bd282
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/syntax/prog.go
@@ -0,0 +1,345 @@
+// 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.
+
+package syntax
+
+import (
+	"bytes"
+	"strconv"
+	"unicode"
+)
+
+// Compiled program.
+// May not belong in this package, but convenient for now.
+
+// A Prog is a compiled regular expression program.
+type Prog struct {
+	Inst   []Inst
+	Start  int // index of start instruction
+	NumCap int // number of InstCapture insts in re
+}
+
+// An InstOp is an instruction opcode.
+type InstOp uint8
+
+const (
+	InstAlt InstOp = iota
+	InstAltMatch
+	InstCapture
+	InstEmptyWidth
+	InstMatch
+	InstFail
+	InstNop
+	InstRune
+	InstRune1
+	InstRuneAny
+	InstRuneAnyNotNL
+)
+
+var instOpNames = []string{
+	"InstAlt",
+	"InstAltMatch",
+	"InstCapture",
+	"InstEmptyWidth",
+	"InstMatch",
+	"InstFail",
+	"InstNop",
+	"InstRune",
+	"InstRune1",
+	"InstRuneAny",
+	"InstRuneAnyNotNL",
+}
+
+func (i InstOp) String() string {
+	if uint(i) >= uint(len(instOpNames)) {
+		return ""
+	}
+	return instOpNames[i]
+}
+
+// An EmptyOp specifies a kind or mixture of zero-width assertions.
+type EmptyOp uint8
+
+const (
+	EmptyBeginLine EmptyOp = 1 << iota
+	EmptyEndLine
+	EmptyBeginText
+	EmptyEndText
+	EmptyWordBoundary
+	EmptyNoWordBoundary
+)
+
+// EmptyOpContext returns the zero-width assertions
+// satisfied at the position between the runes r1 and r2.
+// Passing r1 == -1 indicates that the position is
+// at the beginning of the text.
+// Passing r2 == -1 indicates that the position is
+// at the end of the text.
+func EmptyOpContext(r1, r2 rune) EmptyOp {
+	var op EmptyOp = EmptyNoWordBoundary
+	var boundary byte
+	switch {
+	case IsWordChar(r1):
+		boundary = 1
+	case r1 == '\n':
+		op |= EmptyBeginLine
+	case r1 < 0:
+		op |= EmptyBeginText | EmptyBeginLine
+	}
+	switch {
+	case IsWordChar(r2):
+		boundary ^= 1
+	case r2 == '\n':
+		op |= EmptyEndLine
+	case r2 < 0:
+		op |= EmptyEndText | EmptyEndLine
+	}
+	if boundary != 0 { // IsWordChar(r1) != IsWordChar(r2)
+		op ^= (EmptyWordBoundary | EmptyNoWordBoundary)
+	}
+	return op
+}
+
+// IsWordChar reports whether r is consider a ``word character''
+// during the evaluation of the \b and \B zero-width assertions.
+// These assertions are ASCII-only: the word characters are [A-Za-z0-9_].
+func IsWordChar(r rune) bool {
+	return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' || '0' <= r && r <= '9' || r == '_'
+}
+
+// An Inst is a single instruction in a regular expression program.
+type Inst struct {
+	Op   InstOp
+	Out  uint32 // all but InstMatch, InstFail
+	Arg  uint32 // InstAlt, InstAltMatch, InstCapture, InstEmptyWidth
+	Rune []rune
+}
+
+func (p *Prog) String() string {
+	var b bytes.Buffer
+	dumpProg(&b, p)
+	return b.String()
+}
+
+// skipNop follows any no-op or capturing instructions
+// and returns the resulting pc.
+func (p *Prog) skipNop(pc uint32) (*Inst, uint32) {
+	i := &p.Inst[pc]
+	for i.Op == InstNop || i.Op == InstCapture {
+		pc = i.Out
+		i = &p.Inst[pc]
+	}
+	return i, pc
+}
+
+// op returns i.Op but merges all the Rune special cases into InstRune
+func (i *Inst) op() InstOp {
+	op := i.Op
+	switch op {
+	case InstRune1, InstRuneAny, InstRuneAnyNotNL:
+		op = InstRune
+	}
+	return op
+}
+
+// Prefix returns a literal string that all matches for the
+// regexp must start with.  Complete is true if the prefix
+// is the entire match.
+func (p *Prog) Prefix() (prefix string, complete bool) {
+	i, _ := p.skipNop(uint32(p.Start))
+
+	// Avoid allocation of buffer if prefix is empty.
+	if i.op() != InstRune || len(i.Rune) != 1 {
+		return "", i.Op == InstMatch
+	}
+
+	// Have prefix; gather characters.
+	var buf bytes.Buffer
+	for i.op() == InstRune && len(i.Rune) == 1 && Flags(i.Arg)&FoldCase == 0 {
+		buf.WriteRune(i.Rune[0])
+		i, _ = p.skipNop(i.Out)
+	}
+	return buf.String(), i.Op == InstMatch
+}
+
+// StartCond returns the leading empty-width conditions that must
+// be true in any match.  It returns ^EmptyOp(0) if no matches are possible.
+func (p *Prog) StartCond() EmptyOp {
+	var flag EmptyOp
+	pc := uint32(p.Start)
+	i := &p.Inst[pc]
+Loop:
+	for {
+		switch i.Op {
+		case InstEmptyWidth:
+			flag |= EmptyOp(i.Arg)
+		case InstFail:
+			return ^EmptyOp(0)
+		case InstCapture, InstNop:
+			// skip
+		default:
+			break Loop
+		}
+		pc = i.Out
+		i = &p.Inst[pc]
+	}
+	return flag
+}
+
+const noMatch = -1
+
+// MatchRune returns true if the instruction matches (and consumes) r.
+// It should only be called when i.Op == InstRune.
+func (i *Inst) MatchRune(r rune) bool {
+	return i.MatchRunePos(r) != noMatch
+}
+
+// MatchRunePos checks whether the instruction matches (and consumes) r.
+// If so, MatchRunePos returns the index of the matching rune pair
+// (or, when len(i.Rune) == 1, rune singleton).
+// If not, MatchRunePos returns -1.
+// MatchRunePos should only be called when i.Op == InstRune.
+func (i *Inst) MatchRunePos(r rune) int {
+	rune := i.Rune
+
+	// Special case: single-rune slice is from literal string, not char class.
+	if len(rune) == 1 {
+		r0 := rune[0]
+		if r == r0 {
+			return 0
+		}
+		if Flags(i.Arg)&FoldCase != 0 {
+			for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) {
+				if r == r1 {
+					return 0
+				}
+			}
+		}
+		return noMatch
+	}
+
+	// Peek at the first few pairs.
+	// Should handle ASCII well.
+	for j := 0; j < len(rune) && j <= 8; j += 2 {
+		if r < rune[j] {
+			return noMatch
+		}
+		if r <= rune[j+1] {
+			return j / 2
+		}
+	}
+
+	// Otherwise binary search.
+	lo := 0
+	hi := len(rune) / 2
+	for lo < hi {
+		m := lo + (hi-lo)/2
+		if c := rune[2*m]; c <= r {
+			if r <= rune[2*m+1] {
+				return m
+			}
+			lo = m + 1
+		} else {
+			hi = m
+		}
+	}
+	return noMatch
+}
+
+// As per re2's Prog::IsWordChar. Determines whether rune is an ASCII word char.
+// Since we act on runes, it would be easy to support Unicode here.
+func wordRune(r rune) bool {
+	return r == '_' ||
+		('A' <= r && r <= 'Z') ||
+		('a' <= r && r <= 'z') ||
+		('0' <= r && r <= '9')
+}
+
+// MatchEmptyWidth returns true if the instruction matches
+// an empty string between the runes before and after.
+// It should only be called when i.Op == InstEmptyWidth.
+func (i *Inst) MatchEmptyWidth(before rune, after rune) bool {
+	switch EmptyOp(i.Arg) {
+	case EmptyBeginLine:
+		return before == '\n' || before == -1
+	case EmptyEndLine:
+		return after == '\n' || after == -1
+	case EmptyBeginText:
+		return before == -1
+	case EmptyEndText:
+		return after == -1
+	case EmptyWordBoundary:
+		return wordRune(before) != wordRune(after)
+	case EmptyNoWordBoundary:
+		return wordRune(before) == wordRune(after)
+	}
+	panic("unknown empty width arg")
+}
+
+func (i *Inst) String() string {
+	var b bytes.Buffer
+	dumpInst(&b, i)
+	return b.String()
+}
+
+func bw(b *bytes.Buffer, args ...string) {
+	for _, s := range args {
+		b.WriteString(s)
+	}
+}
+
+func dumpProg(b *bytes.Buffer, p *Prog) {
+	for j := range p.Inst {
+		i := &p.Inst[j]
+		pc := strconv.Itoa(j)
+		if len(pc) < 3 {
+			b.WriteString("   "[len(pc):])
+		}
+		if j == p.Start {
+			pc += "*"
+		}
+		bw(b, pc, "\t")
+		dumpInst(b, i)
+		bw(b, "\n")
+	}
+}
+
+func u32(i uint32) string {
+	return strconv.FormatUint(uint64(i), 10)
+}
+
+func dumpInst(b *bytes.Buffer, i *Inst) {
+	switch i.Op {
+	case InstAlt:
+		bw(b, "alt -> ", u32(i.Out), ", ", u32(i.Arg))
+	case InstAltMatch:
+		bw(b, "altmatch -> ", u32(i.Out), ", ", u32(i.Arg))
+	case InstCapture:
+		bw(b, "cap ", u32(i.Arg), " -> ", u32(i.Out))
+	case InstEmptyWidth:
+		bw(b, "empty ", u32(i.Arg), " -> ", u32(i.Out))
+	case InstMatch:
+		bw(b, "match")
+	case InstFail:
+		bw(b, "fail")
+	case InstNop:
+		bw(b, "nop -> ", u32(i.Out))
+	case InstRune:
+		if i.Rune == nil {
+			// shouldn't happen
+			bw(b, "rune <nil>")
+		}
+		bw(b, "rune ", strconv.QuoteToASCII(string(i.Rune)))
+		if Flags(i.Arg)&FoldCase != 0 {
+			bw(b, "/i")
+		}
+		bw(b, " -> ", u32(i.Out))
+	case InstRune1:
+		bw(b, "rune1 ", strconv.QuoteToASCII(string(i.Rune)), " -> ", u32(i.Out))
+	case InstRuneAny:
+		bw(b, "any -> ", u32(i.Out))
+	case InstRuneAnyNotNL:
+		bw(b, "anynotnl -> ", u32(i.Out))
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/syntax/prog_test.go b/third_party/gofrontend/libgo/go/regexp/syntax/prog_test.go
new file mode 100644
index 0000000..50bfa3d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/syntax/prog_test.go
@@ -0,0 +1,114 @@
+// 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.
+
+package syntax
+
+import "testing"
+
+var compileTests = []struct {
+	Regexp string
+	Prog   string
+}{
+	{"a", `  0	fail
+  1*	rune1 "a" -> 2
+  2	match
+`},
+	{"[A-M][n-z]", `  0	fail
+  1*	rune "AM" -> 2
+  2	rune "nz" -> 3
+  3	match
+`},
+	{"", `  0	fail
+  1*	nop -> 2
+  2	match
+`},
+	{"a?", `  0	fail
+  1	rune1 "a" -> 3
+  2*	alt -> 1, 3
+  3	match
+`},
+	{"a??", `  0	fail
+  1	rune1 "a" -> 3
+  2*	alt -> 3, 1
+  3	match
+`},
+	{"a+", `  0	fail
+  1*	rune1 "a" -> 2
+  2	alt -> 1, 3
+  3	match
+`},
+	{"a+?", `  0	fail
+  1*	rune1 "a" -> 2
+  2	alt -> 3, 1
+  3	match
+`},
+	{"a*", `  0	fail
+  1	rune1 "a" -> 2
+  2*	alt -> 1, 3
+  3	match
+`},
+	{"a*?", `  0	fail
+  1	rune1 "a" -> 2
+  2*	alt -> 3, 1
+  3	match
+`},
+	{"a+b+", `  0	fail
+  1*	rune1 "a" -> 2
+  2	alt -> 1, 3
+  3	rune1 "b" -> 4
+  4	alt -> 3, 5
+  5	match
+`},
+	{"(a+)(b+)", `  0	fail
+  1*	cap 2 -> 2
+  2	rune1 "a" -> 3
+  3	alt -> 2, 4
+  4	cap 3 -> 5
+  5	cap 4 -> 6
+  6	rune1 "b" -> 7
+  7	alt -> 6, 8
+  8	cap 5 -> 9
+  9	match
+`},
+	{"a+|b+", `  0	fail
+  1	rune1 "a" -> 2
+  2	alt -> 1, 6
+  3	rune1 "b" -> 4
+  4	alt -> 3, 6
+  5*	alt -> 1, 3
+  6	match
+`},
+	{"A[Aa]", `  0	fail
+  1*	rune1 "A" -> 2
+  2	rune "A"/i -> 3
+  3	match
+`},
+	{"(?:(?:^).)", `  0	fail
+  1*	empty 4 -> 2
+  2	anynotnl -> 3
+  3	match
+`},
+}
+
+func TestCompile(t *testing.T) {
+	for _, tt := range compileTests {
+		re, _ := Parse(tt.Regexp, Perl)
+		p, _ := Compile(re)
+		s := p.String()
+		if s != tt.Prog {
+			t.Errorf("compiled %#q:\n--- have\n%s---\n--- want\n%s---", tt.Regexp, s, tt.Prog)
+		}
+	}
+}
+
+func BenchmarkEmptyOpContext(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		var r1 rune = -1
+		for _, r2 := range "foo, bar, baz\nsome input text.\n" {
+			EmptyOpContext(r1, r2)
+			r1 = r2
+		}
+		EmptyOpContext(r1, -1)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/syntax/regexp.go b/third_party/gofrontend/libgo/go/regexp/syntax/regexp.go
new file mode 100644
index 0000000..329a90e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/syntax/regexp.go
@@ -0,0 +1,319 @@
+// 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.
+
+package syntax
+
+// Note to implementers:
+// In this package, re is always a *Regexp and r is always a rune.
+
+import (
+	"bytes"
+	"strconv"
+	"strings"
+	"unicode"
+)
+
+// A Regexp is a node in a regular expression syntax tree.
+type Regexp struct {
+	Op       Op // operator
+	Flags    Flags
+	Sub      []*Regexp  // subexpressions, if any
+	Sub0     [1]*Regexp // storage for short Sub
+	Rune     []rune     // matched runes, for OpLiteral, OpCharClass
+	Rune0    [2]rune    // storage for short Rune
+	Min, Max int        // min, max for OpRepeat
+	Cap      int        // capturing index, for OpCapture
+	Name     string     // capturing name, for OpCapture
+}
+
+// An Op is a single regular expression operator.
+type Op uint8
+
+// Operators are listed in precedence order, tightest binding to weakest.
+// Character class operators are listed simplest to most complex
+// (OpLiteral, OpCharClass, OpAnyCharNotNL, OpAnyChar).
+
+const (
+	OpNoMatch        Op = 1 + iota // matches no strings
+	OpEmptyMatch                   // matches empty string
+	OpLiteral                      // matches Runes sequence
+	OpCharClass                    // matches Runes interpreted as range pair list
+	OpAnyCharNotNL                 // matches any character
+	OpAnyChar                      // matches any character
+	OpBeginLine                    // matches empty string at beginning of line
+	OpEndLine                      // matches empty string at end of line
+	OpBeginText                    // matches empty string at beginning of text
+	OpEndText                      // matches empty string at end of text
+	OpWordBoundary                 // matches word boundary `\b`
+	OpNoWordBoundary               // matches word non-boundary `\B`
+	OpCapture                      // capturing subexpression with index Cap, optional name Name
+	OpStar                         // matches Sub[0] zero or more times
+	OpPlus                         // matches Sub[0] one or more times
+	OpQuest                        // matches Sub[0] zero or one times
+	OpRepeat                       // matches Sub[0] at least Min times, at most Max (Max == -1 is no limit)
+	OpConcat                       // matches concatenation of Subs
+	OpAlternate                    // matches alternation of Subs
+)
+
+const opPseudo Op = 128 // where pseudo-ops start
+
+// Equal returns true if x and y have identical structure.
+func (x *Regexp) Equal(y *Regexp) bool {
+	if x == nil || y == nil {
+		return x == y
+	}
+	if x.Op != y.Op {
+		return false
+	}
+	switch x.Op {
+	case OpEndText:
+		// The parse flags remember whether this is \z or \Z.
+		if x.Flags&WasDollar != y.Flags&WasDollar {
+			return false
+		}
+
+	case OpLiteral, OpCharClass:
+		if len(x.Rune) != len(y.Rune) {
+			return false
+		}
+		for i, r := range x.Rune {
+			if r != y.Rune[i] {
+				return false
+			}
+		}
+
+	case OpAlternate, OpConcat:
+		if len(x.Sub) != len(y.Sub) {
+			return false
+		}
+		for i, sub := range x.Sub {
+			if !sub.Equal(y.Sub[i]) {
+				return false
+			}
+		}
+
+	case OpStar, OpPlus, OpQuest:
+		if x.Flags&NonGreedy != y.Flags&NonGreedy || !x.Sub[0].Equal(y.Sub[0]) {
+			return false
+		}
+
+	case OpRepeat:
+		if x.Flags&NonGreedy != y.Flags&NonGreedy || x.Min != y.Min || x.Max != y.Max || !x.Sub[0].Equal(y.Sub[0]) {
+			return false
+		}
+
+	case OpCapture:
+		if x.Cap != y.Cap || x.Name != y.Name || !x.Sub[0].Equal(y.Sub[0]) {
+			return false
+		}
+	}
+	return true
+}
+
+// writeRegexp writes the Perl syntax for the regular expression re to b.
+func writeRegexp(b *bytes.Buffer, re *Regexp) {
+	switch re.Op {
+	default:
+		b.WriteString("<invalid op" + strconv.Itoa(int(re.Op)) + ">")
+	case OpNoMatch:
+		b.WriteString(`[^\x00-\x{10FFFF}]`)
+	case OpEmptyMatch:
+		b.WriteString(`(?:)`)
+	case OpLiteral:
+		if re.Flags&FoldCase != 0 {
+			b.WriteString(`(?i:`)
+		}
+		for _, r := range re.Rune {
+			escape(b, r, false)
+		}
+		if re.Flags&FoldCase != 0 {
+			b.WriteString(`)`)
+		}
+	case OpCharClass:
+		if len(re.Rune)%2 != 0 {
+			b.WriteString(`[invalid char class]`)
+			break
+		}
+		b.WriteRune('[')
+		if len(re.Rune) == 0 {
+			b.WriteString(`^\x00-\x{10FFFF}`)
+		} else if re.Rune[0] == 0 && re.Rune[len(re.Rune)-1] == unicode.MaxRune {
+			// Contains 0 and MaxRune.  Probably a negated class.
+			// Print the gaps.
+			b.WriteRune('^')
+			for i := 1; i < len(re.Rune)-1; i += 2 {
+				lo, hi := re.Rune[i]+1, re.Rune[i+1]-1
+				escape(b, lo, lo == '-')
+				if lo != hi {
+					b.WriteRune('-')
+					escape(b, hi, hi == '-')
+				}
+			}
+		} else {
+			for i := 0; i < len(re.Rune); i += 2 {
+				lo, hi := re.Rune[i], re.Rune[i+1]
+				escape(b, lo, lo == '-')
+				if lo != hi {
+					b.WriteRune('-')
+					escape(b, hi, hi == '-')
+				}
+			}
+		}
+		b.WriteRune(']')
+	case OpAnyCharNotNL:
+		b.WriteString(`(?-s:.)`)
+	case OpAnyChar:
+		b.WriteString(`(?s:.)`)
+	case OpBeginLine:
+		b.WriteRune('^')
+	case OpEndLine:
+		b.WriteRune('$')
+	case OpBeginText:
+		b.WriteString(`\A`)
+	case OpEndText:
+		if re.Flags&WasDollar != 0 {
+			b.WriteString(`(?-m:$)`)
+		} else {
+			b.WriteString(`\z`)
+		}
+	case OpWordBoundary:
+		b.WriteString(`\b`)
+	case OpNoWordBoundary:
+		b.WriteString(`\B`)
+	case OpCapture:
+		if re.Name != "" {
+			b.WriteString(`(?P<`)
+			b.WriteString(re.Name)
+			b.WriteRune('>')
+		} else {
+			b.WriteRune('(')
+		}
+		if re.Sub[0].Op != OpEmptyMatch {
+			writeRegexp(b, re.Sub[0])
+		}
+		b.WriteRune(')')
+	case OpStar, OpPlus, OpQuest, OpRepeat:
+		if sub := re.Sub[0]; sub.Op > OpCapture || sub.Op == OpLiteral && len(sub.Rune) > 1 {
+			b.WriteString(`(?:`)
+			writeRegexp(b, sub)
+			b.WriteString(`)`)
+		} else {
+			writeRegexp(b, sub)
+		}
+		switch re.Op {
+		case OpStar:
+			b.WriteRune('*')
+		case OpPlus:
+			b.WriteRune('+')
+		case OpQuest:
+			b.WriteRune('?')
+		case OpRepeat:
+			b.WriteRune('{')
+			b.WriteString(strconv.Itoa(re.Min))
+			if re.Max != re.Min {
+				b.WriteRune(',')
+				if re.Max >= 0 {
+					b.WriteString(strconv.Itoa(re.Max))
+				}
+			}
+			b.WriteRune('}')
+		}
+		if re.Flags&NonGreedy != 0 {
+			b.WriteRune('?')
+		}
+	case OpConcat:
+		for _, sub := range re.Sub {
+			if sub.Op == OpAlternate {
+				b.WriteString(`(?:`)
+				writeRegexp(b, sub)
+				b.WriteString(`)`)
+			} else {
+				writeRegexp(b, sub)
+			}
+		}
+	case OpAlternate:
+		for i, sub := range re.Sub {
+			if i > 0 {
+				b.WriteRune('|')
+			}
+			writeRegexp(b, sub)
+		}
+	}
+}
+
+func (re *Regexp) String() string {
+	var b bytes.Buffer
+	writeRegexp(&b, re)
+	return b.String()
+}
+
+const meta = `\.+*?()|[]{}^$`
+
+func escape(b *bytes.Buffer, r rune, force bool) {
+	if unicode.IsPrint(r) {
+		if strings.IndexRune(meta, r) >= 0 || force {
+			b.WriteRune('\\')
+		}
+		b.WriteRune(r)
+		return
+	}
+
+	switch r {
+	case '\a':
+		b.WriteString(`\a`)
+	case '\f':
+		b.WriteString(`\f`)
+	case '\n':
+		b.WriteString(`\n`)
+	case '\r':
+		b.WriteString(`\r`)
+	case '\t':
+		b.WriteString(`\t`)
+	case '\v':
+		b.WriteString(`\v`)
+	default:
+		if r < 0x100 {
+			b.WriteString(`\x`)
+			s := strconv.FormatInt(int64(r), 16)
+			if len(s) == 1 {
+				b.WriteRune('0')
+			}
+			b.WriteString(s)
+			break
+		}
+		b.WriteString(`\x{`)
+		b.WriteString(strconv.FormatInt(int64(r), 16))
+		b.WriteString(`}`)
+	}
+}
+
+// MaxCap walks the regexp to find the maximum capture index.
+func (re *Regexp) MaxCap() int {
+	m := 0
+	if re.Op == OpCapture {
+		m = re.Cap
+	}
+	for _, sub := range re.Sub {
+		if n := sub.MaxCap(); m < n {
+			m = n
+		}
+	}
+	return m
+}
+
+// CapNames walks the regexp to find the names of capturing groups.
+func (re *Regexp) CapNames() []string {
+	names := make([]string, re.MaxCap()+1)
+	re.capNames(names)
+	return names
+}
+
+func (re *Regexp) capNames(names []string) {
+	if re.Op == OpCapture {
+		names[re.Cap] = re.Name
+	}
+	for _, sub := range re.Sub {
+		sub.capNames(names)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/syntax/simplify.go b/third_party/gofrontend/libgo/go/regexp/syntax/simplify.go
new file mode 100644
index 0000000..7239041
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/syntax/simplify.go
@@ -0,0 +1,151 @@
+// 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.
+
+package syntax
+
+// Simplify returns a regexp equivalent to re but without counted repetitions
+// and with various other simplifications, such as rewriting /(?:a+)+/ to /a+/.
+// The resulting regexp will execute correctly but its string representation
+// will not produce the same parse tree, because capturing parentheses
+// may have been duplicated or removed.  For example, the simplified form
+// for /(x){1,2}/ is /(x)(x)?/ but both parentheses capture as $1.
+// The returned regexp may share structure with or be the original.
+func (re *Regexp) Simplify() *Regexp {
+	if re == nil {
+		return nil
+	}
+	switch re.Op {
+	case OpCapture, OpConcat, OpAlternate:
+		// Simplify children, building new Regexp if children change.
+		nre := re
+		for i, sub := range re.Sub {
+			nsub := sub.Simplify()
+			if nre == re && nsub != sub {
+				// Start a copy.
+				nre = new(Regexp)
+				*nre = *re
+				nre.Rune = nil
+				nre.Sub = append(nre.Sub0[:0], re.Sub[:i]...)
+			}
+			if nre != re {
+				nre.Sub = append(nre.Sub, nsub)
+			}
+		}
+		return nre
+
+	case OpStar, OpPlus, OpQuest:
+		sub := re.Sub[0].Simplify()
+		return simplify1(re.Op, re.Flags, sub, re)
+
+	case OpRepeat:
+		// Special special case: x{0} matches the empty string
+		// and doesn't even need to consider x.
+		if re.Min == 0 && re.Max == 0 {
+			return &Regexp{Op: OpEmptyMatch}
+		}
+
+		// The fun begins.
+		sub := re.Sub[0].Simplify()
+
+		// x{n,} means at least n matches of x.
+		if re.Max == -1 {
+			// Special case: x{0,} is x*.
+			if re.Min == 0 {
+				return simplify1(OpStar, re.Flags, sub, nil)
+			}
+
+			// Special case: x{1,} is x+.
+			if re.Min == 1 {
+				return simplify1(OpPlus, re.Flags, sub, nil)
+			}
+
+			// General case: x{4,} is xxxx+.
+			nre := &Regexp{Op: OpConcat}
+			nre.Sub = nre.Sub0[:0]
+			for i := 0; i < re.Min-1; i++ {
+				nre.Sub = append(nre.Sub, sub)
+			}
+			nre.Sub = append(nre.Sub, simplify1(OpPlus, re.Flags, sub, nil))
+			return nre
+		}
+
+		// Special case x{0} handled above.
+
+		// Special case: x{1} is just x.
+		if re.Min == 1 && re.Max == 1 {
+			return sub
+		}
+
+		// General case: x{n,m} means n copies of x and m copies of x?
+		// The machine will do less work if we nest the final m copies,
+		// so that x{2,5} = xx(x(x(x)?)?)?
+
+		// Build leading prefix: xx.
+		var prefix *Regexp
+		if re.Min > 0 {
+			prefix = &Regexp{Op: OpConcat}
+			prefix.Sub = prefix.Sub0[:0]
+			for i := 0; i < re.Min; i++ {
+				prefix.Sub = append(prefix.Sub, sub)
+			}
+		}
+
+		// Build and attach suffix: (x(x(x)?)?)?
+		if re.Max > re.Min {
+			suffix := simplify1(OpQuest, re.Flags, sub, nil)
+			for i := re.Min + 1; i < re.Max; i++ {
+				nre2 := &Regexp{Op: OpConcat}
+				nre2.Sub = append(nre2.Sub0[:0], sub, suffix)
+				suffix = simplify1(OpQuest, re.Flags, nre2, nil)
+			}
+			if prefix == nil {
+				return suffix
+			}
+			prefix.Sub = append(prefix.Sub, suffix)
+		}
+		if prefix != nil {
+			return prefix
+		}
+
+		// Some degenerate case like min > max or min < max < 0.
+		// Handle as impossible match.
+		return &Regexp{Op: OpNoMatch}
+	}
+
+	return re
+}
+
+// simplify1 implements Simplify for the unary OpStar,
+// OpPlus, and OpQuest operators.  It returns the simple regexp
+// equivalent to
+//
+//	Regexp{Op: op, Flags: flags, Sub: {sub}}
+//
+// under the assumption that sub is already simple, and
+// without first allocating that structure.  If the regexp
+// to be returned turns out to be equivalent to re, simplify1
+// returns re instead.
+//
+// simplify1 is factored out of Simplify because the implementation
+// for other operators generates these unary expressions.
+// Letting them call simplify1 makes sure the expressions they
+// generate are simple.
+func simplify1(op Op, flags Flags, sub, re *Regexp) *Regexp {
+	// Special case: repeat the empty string as much as
+	// you want, but it's still the empty string.
+	if sub.Op == OpEmptyMatch {
+		return sub
+	}
+	// The operators are idempotent if the flags match.
+	if op == sub.Op && flags&NonGreedy == sub.Flags&NonGreedy {
+		return sub
+	}
+	if re != nil && re.Op == op && re.Flags&NonGreedy == flags&NonGreedy && sub == re.Sub[0] {
+		return re
+	}
+
+	re = &Regexp{Op: op, Flags: flags}
+	re.Sub = append(re.Sub0[:0], sub)
+	return re
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/syntax/simplify_test.go b/third_party/gofrontend/libgo/go/regexp/syntax/simplify_test.go
new file mode 100644
index 0000000..879eff5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/syntax/simplify_test.go
@@ -0,0 +1,151 @@
+// 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.
+
+package syntax
+
+import "testing"
+
+var simplifyTests = []struct {
+	Regexp string
+	Simple string
+}{
+	// Already-simple constructs
+	{`a`, `a`},
+	{`ab`, `ab`},
+	{`a|b`, `[a-b]`},
+	{`ab|cd`, `ab|cd`},
+	{`(ab)*`, `(ab)*`},
+	{`(ab)+`, `(ab)+`},
+	{`(ab)?`, `(ab)?`},
+	{`.`, `(?s:.)`},
+	{`^`, `^`},
+	{`$`, `$`},
+	{`[ac]`, `[ac]`},
+	{`[^ac]`, `[^ac]`},
+
+	// Posix character classes
+	{`[[:alnum:]]`, `[0-9A-Za-z]`},
+	{`[[:alpha:]]`, `[A-Za-z]`},
+	{`[[:blank:]]`, `[\t ]`},
+	{`[[:cntrl:]]`, `[\x00-\x1f\x7f]`},
+	{`[[:digit:]]`, `[0-9]`},
+	{`[[:graph:]]`, `[!-~]`},
+	{`[[:lower:]]`, `[a-z]`},
+	{`[[:print:]]`, `[ -~]`},
+	{`[[:punct:]]`, "[!-/:-@\\[-`\\{-~]"},
+	{`[[:space:]]`, `[\t-\r ]`},
+	{`[[:upper:]]`, `[A-Z]`},
+	{`[[:xdigit:]]`, `[0-9A-Fa-f]`},
+
+	// Perl character classes
+	{`\d`, `[0-9]`},
+	{`\s`, `[\t-\n\f-\r ]`},
+	{`\w`, `[0-9A-Z_a-z]`},
+	{`\D`, `[^0-9]`},
+	{`\S`, `[^\t-\n\f-\r ]`},
+	{`\W`, `[^0-9A-Z_a-z]`},
+	{`[\d]`, `[0-9]`},
+	{`[\s]`, `[\t-\n\f-\r ]`},
+	{`[\w]`, `[0-9A-Z_a-z]`},
+	{`[\D]`, `[^0-9]`},
+	{`[\S]`, `[^\t-\n\f-\r ]`},
+	{`[\W]`, `[^0-9A-Z_a-z]`},
+
+	// Posix repetitions
+	{`a{1}`, `a`},
+	{`a{2}`, `aa`},
+	{`a{5}`, `aaaaa`},
+	{`a{0,1}`, `a?`},
+	// The next three are illegible because Simplify inserts (?:)
+	// parens instead of () parens to avoid creating extra
+	// captured subexpressions.  The comments show a version with fewer parens.
+	{`(a){0,2}`, `(?:(a)(a)?)?`},                       //       (aa?)?
+	{`(a){0,4}`, `(?:(a)(?:(a)(?:(a)(a)?)?)?)?`},       //   (a(a(aa?)?)?)?
+	{`(a){2,6}`, `(a)(a)(?:(a)(?:(a)(?:(a)(a)?)?)?)?`}, // aa(a(a(aa?)?)?)?
+	{`a{0,2}`, `(?:aa?)?`},                             //       (aa?)?
+	{`a{0,4}`, `(?:a(?:a(?:aa?)?)?)?`},                 //   (a(a(aa?)?)?)?
+	{`a{2,6}`, `aa(?:a(?:a(?:aa?)?)?)?`},               // aa(a(a(aa?)?)?)?
+	{`a{0,}`, `a*`},
+	{`a{1,}`, `a+`},
+	{`a{2,}`, `aa+`},
+	{`a{5,}`, `aaaaa+`},
+
+	// Test that operators simplify their arguments.
+	{`(?:a{1,}){1,}`, `a+`},
+	{`(a{1,}b{1,})`, `(a+b+)`},
+	{`a{1,}|b{1,}`, `a+|b+`},
+	{`(?:a{1,})*`, `(?:a+)*`},
+	{`(?:a{1,})+`, `a+`},
+	{`(?:a{1,})?`, `(?:a+)?`},
+	{``, `(?:)`},
+	{`a{0}`, `(?:)`},
+
+	// Character class simplification
+	{`[ab]`, `[a-b]`},
+	{`[a-za-za-z]`, `[a-z]`},
+	{`[A-Za-zA-Za-z]`, `[A-Za-z]`},
+	{`[ABCDEFGH]`, `[A-H]`},
+	{`[AB-CD-EF-GH]`, `[A-H]`},
+	{`[W-ZP-XE-R]`, `[E-Z]`},
+	{`[a-ee-gg-m]`, `[a-m]`},
+	{`[a-ea-ha-m]`, `[a-m]`},
+	{`[a-ma-ha-e]`, `[a-m]`},
+	{`[a-zA-Z0-9 -~]`, `[ -~]`},
+
+	// Empty character classes
+	{`[^[:cntrl:][:^cntrl:]]`, `[^\x00-\x{10FFFF}]`},
+
+	// Full character classes
+	{`[[:cntrl:][:^cntrl:]]`, `(?s:.)`},
+
+	// Unicode case folding.
+	{`(?i)A`, `(?i:A)`},
+	{`(?i)a`, `(?i:A)`},
+	{`(?i)[A]`, `(?i:A)`},
+	{`(?i)[a]`, `(?i:A)`},
+	{`(?i)K`, `(?i:K)`},
+	{`(?i)k`, `(?i:K)`},
+	{`(?i)\x{212a}`, "(?i:K)"},
+	{`(?i)[K]`, "[Kk\u212A]"},
+	{`(?i)[k]`, "[Kk\u212A]"},
+	{`(?i)[\x{212a}]`, "[Kk\u212A]"},
+	{`(?i)[a-z]`, "[A-Za-z\u017F\u212A]"},
+	{`(?i)[\x00-\x{FFFD}]`, "[\\x00-\uFFFD]"},
+	{`(?i)[\x00-\x{10FFFF}]`, `(?s:.)`},
+
+	// Empty string as a regular expression.
+	// The empty string must be preserved inside parens in order
+	// to make submatches work right, so these tests are less
+	// interesting than they might otherwise be.  String inserts
+	// explicit (?:) in place of non-parenthesized empty strings,
+	// to make them easier to spot for other parsers.
+	{`(a|b|)`, `([a-b]|(?:))`},
+	{`(|)`, `()`},
+	{`a()`, `a()`},
+	{`(()|())`, `(()|())`},
+	{`(a|)`, `(a|(?:))`},
+	{`ab()cd()`, `ab()cd()`},
+	{`()`, `()`},
+	{`()*`, `()*`},
+	{`()+`, `()+`},
+	{`()?`, `()?`},
+	{`(){0}`, `(?:)`},
+	{`(){1}`, `()`},
+	{`(){1,}`, `()+`},
+	{`(){0,2}`, `(?:()()?)?`},
+}
+
+func TestSimplify(t *testing.T) {
+	for _, tt := range simplifyTests {
+		re, err := Parse(tt.Regexp, MatchNL|Perl&^OneLine)
+		if err != nil {
+			t.Errorf("Parse(%#q) = error %v", tt.Regexp, err)
+			continue
+		}
+		s := re.Simplify().String()
+		if s != tt.Simple {
+			t.Errorf("Simplify(%#q) = %#q, want %#q", tt.Regexp, s, tt.Simple)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/regexp/testdata/README b/third_party/gofrontend/libgo/go/regexp/testdata/README
new file mode 100644
index 0000000..b1b301b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/testdata/README
@@ -0,0 +1,23 @@
+AT&T POSIX Test Files
+See textregex.c for copyright + license.
+
+testregex.c	http://www2.research.att.com/~gsf/testregex/testregex.c
+basic.dat	http://www2.research.att.com/~gsf/testregex/basic.dat
+nullsubexpr.dat	http://www2.research.att.com/~gsf/testregex/nullsubexpr.dat
+repetition.dat	http://www2.research.att.com/~gsf/testregex/repetition.dat
+
+The test data has been edited to reflect RE2/Go differences:
+  * In a star of a possibly empty match like (a*)* matching x,
+    the no match case runs the starred subexpression zero times,
+    not once.  This is consistent with (a*)* matching a, which
+    runs the starred subexpression one time, not twice.
+  * The submatch choice is first match, not the POSIX rule.
+
+Such changes are marked with 'RE2/Go'.
+
+
+RE2 Test Files
+
+re2-exhaustive.txt.bz2 and re2-search.txt are built by running
+'make log' in the RE2 distribution.  http://code.google.com/p/re2/.
+The exhaustive file is compressed because it is huge.
diff --git a/third_party/gofrontend/libgo/go/regexp/testdata/basic.dat b/third_party/gofrontend/libgo/go/regexp/testdata/basic.dat
new file mode 100644
index 0000000..7859290
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/testdata/basic.dat
@@ -0,0 +1,221 @@
+NOTE	all standard compliant implementations should pass these : 2002-05-31
+
+BE	abracadabra$	abracadabracadabra	(7,18)
+BE	a...b		abababbb		(2,7)
+BE	XXXXXX		..XXXXXX		(2,8)
+E	\)		()	(1,2)
+BE	a]		a]a	(0,2)
+B	}		}	(0,1)
+E	\}		}	(0,1)
+BE	\]		]	(0,1)
+B	]		]	(0,1)
+E	]		]	(0,1)
+B	{		{	(0,1)
+B	}		}	(0,1)
+BE	^a		ax	(0,1)
+BE	\^a		a^a	(1,3)
+BE	a\^		a^	(0,2)
+BE	a$		aa	(1,2)
+BE	a\$		a$	(0,2)
+BE	^$		NULL	(0,0)
+E	$^		NULL	(0,0)
+E	a($)		aa	(1,2)(2,2)
+E	a*(^a)		aa	(0,1)(0,1)
+E	(..)*(...)*		a	(0,0)
+E	(..)*(...)*		abcd	(0,4)(2,4)
+E	(ab|a)(bc|c)		abc	(0,3)(0,2)(2,3)
+E	(ab)c|abc		abc	(0,3)(0,2)
+E	a{0}b		ab			(1,2)
+E	(a*)(b?)(b+)b{3}	aaabbbbbbb	(0,10)(0,3)(3,4)(4,7)
+E	(a*)(b{0,1})(b{1,})b{3}	aaabbbbbbb	(0,10)(0,3)(3,4)(4,7)
+E	a{9876543210}	NULL	BADBR
+E	((a|a)|a)			a	(0,1)(0,1)(0,1)
+E	(a*)(a|aa)			aaaa	(0,4)(0,3)(3,4)
+E	a*(a.|aa)			aaaa	(0,4)(2,4)
+E	a(b)|c(d)|a(e)f			aef	(0,3)(?,?)(?,?)(1,2)
+E	(a|b)?.*			b	(0,1)(0,1)
+E	(a|b)c|a(b|c)			ac	(0,2)(0,1)
+E	(a|b)c|a(b|c)			ab	(0,2)(?,?)(1,2)
+E	(a|b)*c|(a|ab)*c		abc	(0,3)(1,2)
+E	(a|b)*c|(a|ab)*c		xc	(1,2)
+E	(.a|.b).*|.*(.a|.b)		xa	(0,2)(0,2)
+E	a?(ab|ba)ab			abab	(0,4)(0,2)
+E	a?(ac{0}b|ba)ab			abab	(0,4)(0,2)
+E	ab|abab				abbabab	(0,2)
+E	aba|bab|bba			baaabbbaba	(5,8)
+E	aba|bab				baaabbbaba	(6,9)
+E	(aa|aaa)*|(a|aaaaa)		aa	(0,2)(0,2)
+E	(a.|.a.)*|(a|.a...)		aa	(0,2)(0,2)
+E	ab|a				xabc	(1,3)
+E	ab|a				xxabc	(2,4)
+Ei	(Ab|cD)*			aBcD	(0,4)(2,4)
+BE	[^-]			--a		(2,3)
+BE	[a-]*			--a		(0,3)
+BE	[a-m-]*			--amoma--	(0,4)
+E	:::1:::0:|:::1:1:0:	:::0:::1:::1:::0:	(8,17)
+E	:::1:::0:|:::1:1:1:	:::0:::1:::1:::0:	(8,17)
+{E	[[:upper:]]		A		(0,1)	[[<element>]] not supported
+E	[[:lower:]]+		`az{		(1,3)
+E	[[:upper:]]+		@AZ[		(1,3)
+# No collation in Go
+#BE	[[-]]			[[-]]		(2,4)
+#BE	[[.NIL.]]	NULL	ECOLLATE
+#BE	[[=aleph=]]	NULL	ECOLLATE
+}
+BE$	\n		\n	(0,1)
+BEn$	\n		\n	(0,1)
+BE$	[^a]		\n	(0,1)
+BE$	\na		\na	(0,2)
+E	(a)(b)(c)	abc	(0,3)(0,1)(1,2)(2,3)
+BE	xxx		xxx	(0,3)
+E1	(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)	feb 6,	(0,6)
+E1	(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)	2/7	(0,3)
+E1	(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)	feb 1,Feb 6	(5,11)
+E3	((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))	x	(0,1)(0,1)(0,1)
+E3	((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*	xx	(0,2)(1,2)(1,2)
+E	a?(ab|ba)*	ababababababababababababababababababababababababababababababababababababababababa	(0,81)(79,81)
+E	abaa|abbaa|abbbaa|abbbbaa	ababbabbbabbbabbbbabbbbaa	(18,25)
+E	abaa|abbaa|abbbaa|abbbbaa	ababbabbbabbbabbbbabaa	(18,22)
+E	aaac|aabc|abac|abbc|baac|babc|bbac|bbbc	baaabbbabac	(7,11)
+BE$	.*			\x01\xff	(0,2)
+E	aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll		XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa	(53,57)
+L	aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll		XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa	NOMATCH
+E	a*a*a*a*a*b		aaaaaaaaab	(0,10)
+BE	^			NULL		(0,0)
+BE	$			NULL		(0,0)
+BE	^$			NULL		(0,0)
+BE	^a$			a		(0,1)
+BE	abc			abc		(0,3)
+BE	abc			xabcy		(1,4)
+BE	abc			ababc		(2,5)
+BE	ab*c			abc		(0,3)
+BE	ab*bc			abc		(0,3)
+BE	ab*bc			abbc		(0,4)
+BE	ab*bc			abbbbc		(0,6)
+E	ab+bc			abbc		(0,4)
+E	ab+bc			abbbbc		(0,6)
+E	ab?bc			abbc		(0,4)
+E	ab?bc			abc		(0,3)
+E	ab?c			abc		(0,3)
+BE	^abc$			abc		(0,3)
+BE	^abc			abcc		(0,3)
+BE	abc$			aabc		(1,4)
+BE	^			abc		(0,0)
+BE	$			abc		(3,3)
+BE	a.c			abc		(0,3)
+BE	a.c			axc		(0,3)
+BE	a.*c			axyzc		(0,5)
+BE	a[bc]d			abd		(0,3)
+BE	a[b-d]e			ace		(0,3)
+BE	a[b-d]			aac		(1,3)
+BE	a[-b]			a-		(0,2)
+BE	a[b-]			a-		(0,2)
+BE	a]			a]		(0,2)
+BE	a[]]b			a]b		(0,3)
+BE	a[^bc]d			aed		(0,3)
+BE	a[^-b]c			adc		(0,3)
+BE	a[^]b]c			adc		(0,3)
+E	ab|cd			abc		(0,2)
+E	ab|cd			abcd		(0,2)
+E	a\(b			a(b		(0,3)
+E	a\(*b			ab		(0,2)
+E	a\(*b			a((b		(0,4)
+E	((a))			abc		(0,1)(0,1)(0,1)
+E	(a)b(c)			abc		(0,3)(0,1)(2,3)
+E	a+b+c			aabbabc		(4,7)
+E	a*			aaa		(0,3)
+#E	(a*)*			-		(0,0)(0,0)
+E	(a*)*			-		(0,0)(?,?)	RE2/Go
+E	(a*)+			-		(0,0)(0,0)
+#E	(a*|b)*			-		(0,0)(0,0)
+E	(a*|b)*			-		(0,0)(?,?)	RE2/Go
+E	(a+|b)*			ab		(0,2)(1,2)
+E	(a+|b)+			ab		(0,2)(1,2)
+E	(a+|b)?			ab		(0,1)(0,1)
+BE	[^ab]*			cde		(0,3)
+#E	(^)*			-		(0,0)(0,0)
+E	(^)*			-		(0,0)(?,?)	RE2/Go
+BE	a*			NULL		(0,0)
+E	([abc])*d		abbbcd		(0,6)(4,5)
+E	([abc])*bcd		abcd		(0,4)(0,1)
+E	a|b|c|d|e		e		(0,1)
+E	(a|b|c|d|e)f		ef		(0,2)(0,1)
+#E	((a*|b))*		-		(0,0)(0,0)(0,0)
+E	((a*|b))*		-		(0,0)(?,?)(?,?)	RE2/Go
+BE	abcd*efg		abcdefg		(0,7)
+BE	ab*			xabyabbbz	(1,3)
+BE	ab*			xayabbbz	(1,2)
+E	(ab|cd)e		abcde		(2,5)(2,4)
+BE	[abhgefdc]ij		hij		(0,3)
+E	(a|b)c*d		abcd		(1,4)(1,2)
+E	(ab|ab*)bc		abc		(0,3)(0,1)
+E	a([bc]*)c*		abc		(0,3)(1,3)
+E	a([bc]*)(c*d)		abcd		(0,4)(1,3)(3,4)
+E	a([bc]+)(c*d)		abcd		(0,4)(1,3)(3,4)
+E	a([bc]*)(c+d)		abcd		(0,4)(1,2)(2,4)
+E	a[bcd]*dcdcde		adcdcde		(0,7)
+E	(ab|a)b*c		abc		(0,3)(0,2)
+E	((a)(b)c)(d)		abcd		(0,4)(0,3)(0,1)(1,2)(3,4)
+BE	[A-Za-z_][A-Za-z0-9_]*	alpha		(0,5)
+E	^a(bc+|b[eh])g|.h$	abh		(1,3)
+E	(bc+d$|ef*g.|h?i(j|k))	effgz		(0,5)(0,5)
+E	(bc+d$|ef*g.|h?i(j|k))	ij		(0,2)(0,2)(1,2)
+E	(bc+d$|ef*g.|h?i(j|k))	reffgz		(1,6)(1,6)
+E	(((((((((a)))))))))	a		(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)
+BE	multiple words		multiple words yeah	(0,14)
+E	(.*)c(.*)		abcde		(0,5)(0,2)(3,5)
+BE	abcd			abcd		(0,4)
+E	a(bc)d			abcd		(0,4)(1,3)
+E	a[-]?c		ac		(0,3)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Qaddafi	(0,15)(?,?)(10,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Mo'ammar Gadhafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Kaddafi	(0,15)(?,?)(10,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Qadhafi	(0,15)(?,?)(10,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Gadafi	(0,14)(?,?)(10,11)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Mu'ammar Qadafi	(0,15)(?,?)(11,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Moamar Gaddafi	(0,14)(?,?)(9,11)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Mu'ammar Qadhdhafi	(0,18)(?,?)(13,15)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Khaddafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Ghaddafy	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Ghadafi	(0,15)(?,?)(11,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Ghaddafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muamar Kaddafi	(0,14)(?,?)(9,11)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Quathafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Gheddafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Moammar Khadafy	(0,15)(?,?)(11,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Moammar Qudhafi	(0,15)(?,?)(10,12)
+E	a+(b|c)*d+		aabcdd			(0,6)(3,4)
+E	^.+$			vivi			(0,4)
+E	^(.+)$			vivi			(0,4)(0,4)
+E	^([^!.]+).att.com!(.+)$	gryphon.att.com!eby	(0,19)(0,7)(16,19)
+E	^([^!]+!)?([^!]+)$	bas			(0,3)(?,?)(0,3)
+E	^([^!]+!)?([^!]+)$	bar!bas			(0,7)(0,4)(4,7)
+E	^([^!]+!)?([^!]+)$	foo!bas			(0,7)(0,4)(4,7)
+E	^.+!([^!]+!)([^!]+)$	foo!bar!bas		(0,11)(4,8)(8,11)
+E	((foo)|(bar))!bas	bar!bas			(0,7)(0,3)(?,?)(0,3)
+E	((foo)|(bar))!bas	foo!bar!bas		(4,11)(4,7)(?,?)(4,7)
+E	((foo)|(bar))!bas	foo!bas			(0,7)(0,3)(0,3)
+E	((foo)|bar)!bas		bar!bas			(0,7)(0,3)
+E	((foo)|bar)!bas		foo!bar!bas		(4,11)(4,7)
+E	((foo)|bar)!bas		foo!bas			(0,7)(0,3)(0,3)
+E	(foo|(bar))!bas		bar!bas			(0,7)(0,3)(0,3)
+E	(foo|(bar))!bas		foo!bar!bas		(4,11)(4,7)(4,7)
+E	(foo|(bar))!bas		foo!bas			(0,7)(0,3)
+E	(foo|bar)!bas		bar!bas			(0,7)(0,3)
+E	(foo|bar)!bas		foo!bar!bas		(4,11)(4,7)
+E	(foo|bar)!bas		foo!bas			(0,7)(0,3)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	foo!bar!bas	(0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	bas		(0,3)(?,?)(0,3)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	bar!bas		(0,7)(0,4)(4,7)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	foo!bar!bas	(0,11)(?,?)(?,?)(4,8)(8,11)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	foo!bas		(0,7)(0,4)(4,7)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	bas		(0,3)(0,3)(?,?)(0,3)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	bar!bas		(0,7)(0,7)(0,4)(4,7)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	foo!bar!bas	(0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	foo!bas		(0,7)(0,7)(0,4)(4,7)
+E	.*(/XXX).*			/XXX			(0,4)(0,4)
+E	.*(\\XXX).*			\XXX			(0,4)(0,4)
+E	\\XXX				\XXX			(0,4)
+E	.*(/000).*			/000			(0,4)(0,4)
+E	.*(\\000).*			\000			(0,4)(0,4)
+E	\\000				\000			(0,4)
diff --git a/third_party/gofrontend/libgo/go/regexp/testdata/nullsubexpr.dat b/third_party/gofrontend/libgo/go/regexp/testdata/nullsubexpr.dat
new file mode 100644
index 0000000..2e18fbb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/testdata/nullsubexpr.dat
@@ -0,0 +1,79 @@
+NOTE	null subexpression matches : 2002-06-06
+
+E	(a*)*		a		(0,1)(0,1)
+#E	SAME		x		(0,0)(0,0)
+E	SAME		x		(0,0)(?,?)	RE2/Go
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	(a*)+		a		(0,1)(0,1)
+E	SAME		x		(0,0)(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	(a+)*		a		(0,1)(0,1)
+E	SAME		x		(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	(a+)+		a		(0,1)(0,1)
+E	SAME		x		NOMATCH
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+
+E	([a]*)*		a		(0,1)(0,1)
+#E	SAME		x		(0,0)(0,0)
+E	SAME		x		(0,0)(?,?)	RE2/Go
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	([a]*)+		a		(0,1)(0,1)
+E	SAME		x		(0,0)(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	([^b]*)*	a		(0,1)(0,1)
+#E	SAME		b		(0,0)(0,0)
+E	SAME		b		(0,0)(?,?)	RE2/Go
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaab		(0,6)(0,6)
+E	([ab]*)*	a		(0,1)(0,1)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		ababab		(0,6)(0,6)
+E	SAME		bababa		(0,6)(0,6)
+E	SAME		b		(0,1)(0,1)
+E	SAME		bbbbbb		(0,6)(0,6)
+E	SAME		aaaabcde	(0,5)(0,5)
+E	([^a]*)*	b		(0,1)(0,1)
+E	SAME		bbbbbb		(0,6)(0,6)
+#E	SAME		aaaaaa		(0,0)(0,0)
+E	SAME		aaaaaa		(0,0)(?,?)	RE2/Go
+E	([^ab]*)*	ccccxx		(0,6)(0,6)
+#E	SAME		ababab		(0,0)(0,0)
+E	SAME		ababab		(0,0)(?,?)	RE2/Go
+
+E	((z)+|a)*	zabcde		(0,2)(1,2)
+
+#{E	a+?		aaaaaa		(0,1)	no *? +? mimimal match ops
+#E	(a)		aaa		(0,1)(0,1)
+#E	(a*?)		aaa		(0,0)(0,0)
+#E	(a)*?		aaa		(0,0)
+#E	(a*?)*?		aaa		(0,0)
+#}
+
+B	\(a*\)*\(x\)		x	(0,1)(0,0)(0,1)
+B	\(a*\)*\(x\)		ax	(0,2)(0,1)(1,2)
+B	\(a*\)*\(x\)		axa	(0,2)(0,1)(1,2)
+B	\(a*\)*\(x\)\(\1\)	x	(0,1)(0,0)(0,1)(1,1)
+B	\(a*\)*\(x\)\(\1\)	ax	(0,2)(1,1)(1,2)(2,2)
+B	\(a*\)*\(x\)\(\1\)	axa	(0,3)(0,1)(1,2)(2,3)
+B	\(a*\)*\(x\)\(\1\)\(x\)	axax	(0,4)(0,1)(1,2)(2,3)(3,4)
+B	\(a*\)*\(x\)\(\1\)\(x\)	axxa	(0,3)(1,1)(1,2)(2,2)(2,3)
+
+#E	(a*)*(x)		x	(0,1)(0,0)(0,1)
+E	(a*)*(x)		x	(0,1)(?,?)(0,1)	RE2/Go
+E	(a*)*(x)		ax	(0,2)(0,1)(1,2)
+E	(a*)*(x)		axa	(0,2)(0,1)(1,2)
+
+E	(a*)+(x)		x	(0,1)(0,0)(0,1)
+E	(a*)+(x)		ax	(0,2)(0,1)(1,2)
+E	(a*)+(x)		axa	(0,2)(0,1)(1,2)
+
+E	(a*){2}(x)		x	(0,1)(0,0)(0,1)
+E	(a*){2}(x)		ax	(0,2)(1,1)(1,2)
+E	(a*){2}(x)		axa	(0,2)(1,1)(1,2)
diff --git a/third_party/gofrontend/libgo/go/regexp/testdata/re2-exhaustive.txt.bz2 b/third_party/gofrontend/libgo/go/regexp/testdata/re2-exhaustive.txt.bz2
new file mode 100644
index 0000000..a357f28
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/testdata/re2-exhaustive.txt.bz2
Binary files differ
diff --git a/third_party/gofrontend/libgo/go/regexp/testdata/re2-search.txt b/third_party/gofrontend/libgo/go/regexp/testdata/re2-search.txt
new file mode 100644
index 0000000..f648e55
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/testdata/re2-search.txt
@@ -0,0 +1,3667 @@
+# RE2 basic search tests built by make log
+# Thu Sep 8 13:43:43 EDT 2011
+Regexp.SearchTests
+strings
+""
+"a"
+regexps
+"a"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"zyzzyva"
+regexps
+"a"
+-;-;-;-
+-;6-7;-;6-7
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;6-7;-;6-7
+strings
+""
+"aa"
+regexps
+"a+"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:a+)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:a+)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:a+)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+"ab"
+regexps
+"(a+|b)+"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+"^(?:(a+|b)+)$"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+"^(?:(a+|b)+)"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+"(?:(a+|b)+)$"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+strings
+""
+"xabcdx"
+regexps
+"ab|cd"
+-;-;-;-
+-;1-3;-;1-3
+"^(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+"^(?:ab|cd)"
+-;-;-;-
+-;-;-;-
+"(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"hello\ngoodbye\n"
+regexps
+"h.*od?"
+-;-;-;-
+-;0-5;-;0-5
+"^(?:h.*od?)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*od?)"
+-;-;-;-
+-;0-5;-;0-5
+"(?:h.*od?)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"hello\ngoodbye\n"
+regexps
+"h.*o"
+-;-;-;-
+-;0-5;-;0-5
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;0-5;-;0-5
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"goodbye\nhello\n"
+regexps
+"h.*o"
+-;-;-;-
+-;8-13;-;8-13
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;-;-;-
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"hello world"
+regexps
+"h.*o"
+-;-;-;-
+-;0-8;-;0-8
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;0-8;-;0-8
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"othello, world"
+regexps
+"h.*o"
+-;-;-;-
+-;2-11;-;2-11
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;-;-;-
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aaaaaaa"
+regexps
+"[^\\s\\S]"
+-;-;-;-
+-;-;-;-
+"^(?:[^\\s\\S])$"
+-;-;-;-
+-;-;-;-
+"^(?:[^\\s\\S])"
+-;-;-;-
+-;-;-;-
+"(?:[^\\s\\S])$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aaaaaaa"
+regexps
+"a"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:a)$"
+-;-;-;-
+-;6-7;-;6-7
+strings
+""
+"aaaaaaa"
+regexps
+"a*"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+"^(?:a*)$"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+"^(?:a*)"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+"(?:a*)$"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+strings
+""
+""
+regexps
+"a*"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"a*"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"xabcdx"
+regexps
+"ab|cd"
+-;-;-;-
+-;1-3;-;1-3
+"^(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+"^(?:ab|cd)"
+-;-;-;-
+-;-;-;-
+"(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"cab"
+regexps
+"a"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"cab"
+regexps
+"a*b"
+-;-;-;-
+-;1-3;-;1-3
+"^(?:a*b)$"
+-;-;-;-
+-;-;-;-
+"^(?:a*b)"
+-;-;-;-
+-;-;-;-
+"(?:a*b)$"
+-;-;-;-
+-;1-3;-;1-3
+strings
+""
+"x"
+regexps
+"((((((((((((((((((((x))))))))))))))))))))"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+"^(?:((((((((((((((((((((x)))))))))))))))))))))$"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+"^(?:((((((((((((((((((((x)))))))))))))))))))))"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+"(?:((((((((((((((((((((x)))))))))))))))))))))$"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+strings
+""
+"xxxabcdxxx"
+regexps
+"[abcd]"
+-;-;-;-
+-;3-4;-;3-4
+"^(?:[abcd])$"
+-;-;-;-
+-;-;-;-
+"^(?:[abcd])"
+-;-;-;-
+-;-;-;-
+"(?:[abcd])$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xxxabcdxxx"
+regexps
+"[^x]"
+-;-;-;-
+-;3-4;-;3-4
+"^(?:[^x])$"
+-;-;-;-
+-;-;-;-
+"^(?:[^x])"
+-;-;-;-
+-;-;-;-
+"(?:[^x])$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xxxabcdxxx"
+regexps
+"[abcd]+"
+-;-;-;-
+-;3-7;-;3-7
+"^(?:[abcd]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[abcd]+)"
+-;-;-;-
+-;-;-;-
+"(?:[abcd]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xxxabcdxxx"
+regexps
+"[^x]+"
+-;-;-;-
+-;3-7;-;3-7
+"^(?:[^x]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[^x]+)"
+-;-;-;-
+-;-;-;-
+"(?:[^x]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"(fo|foo)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:(fo|foo))$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:(fo|foo))"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:(fo|foo))$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"(foo|fo)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|fo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|fo))"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:(foo|fo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"aA"
+regexps
+"aa"
+-;-;-;-
+-;-;-;-
+"^(?:aa)$"
+-;-;-;-
+-;-;-;-
+"^(?:aa)"
+-;-;-;-
+-;-;-;-
+"(?:aa)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"Aa"
+regexps
+"a"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;1-2;-;1-2
+strings
+""
+"A"
+regexps
+"a"
+-;-;-;-
+-;-;-;-
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc"
+regexps
+"ABC"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)$"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)"
+-;-;-;-
+-;-;-;-
+"(?:ABC)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"XABCY"
+regexps
+"abc"
+-;-;-;-
+-;-;-;-
+"^(?:abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:abc)"
+-;-;-;-
+-;-;-;-
+"(?:abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xabcy"
+regexps
+"ABC"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)$"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)"
+-;-;-;-
+-;-;-;-
+"(?:ABC)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"foo|bar|[A-Z]"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:foo|bar|[A-Z])$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:foo|bar|[A-Z])"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:foo|bar|[A-Z])$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"foo"
+regexps
+"^(foo|bar|[A-Z])"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z]))"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"(foo|bar|[A-Z])$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])$)"
+-;-;-;-
+-;-;-;-
+"(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"(foo|bar|[A-Z])$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+-;-;-;-
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"bar"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"X"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+strings
+""
+"XY"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+-;-;-;-
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"^(fo|foo)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^(fo|foo)$)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"^(fo|foo)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(fo|foo)$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"fo"
+regexps
+"^^(fo|foo)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^^(fo|foo)$)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:^^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"^^(fo|foo)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^^(fo|foo)$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+""
+regexps
+"^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"^$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^$$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^^$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^^$$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^^^^^^^^$$$$$$$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^$$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^$$$$$$$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^^^^^^^$$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"^(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^)"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"$"
+0-0;0-0;0-0;0-0
+-;1-1;-;1-1
+"^(?:$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$)$"
+0-0;0-0;0-0;0-0
+-;1-1;-;1-1
+strings
+""
+"nofoo foo that"
+regexps
+"\\bfoo\\b"
+-;-;-;-
+-;6-9;-;6-9
+"^(?:\\bfoo\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bfoo\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bfoo\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"faoa x"
+regexps
+"a\\b"
+-;-;-;-
+-;3-4;-;3-4
+"^(?:a\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\b)"
+-;-;-;-
+-;-;-;-
+"(?:a\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"bar x"
+regexps
+"\\bbar"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bbar)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo\nbar x"
+regexps
+"\\bbar"
+-;-;-;-
+-;4-7;-;4-7
+"^(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bbar)"
+-;-;-;-
+-;-;-;-
+"(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foobar"
+regexps
+"bar\\b"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:bar\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\b)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\b)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"foobar\nxxx"
+regexps
+"bar\\b"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:bar\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\b)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:\\b)$"
+-;-;-;-
+-;1-1;-;1-1
+strings
+""
+"foo"
+regexps
+"\\b(foo|bar|[A-Z])"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z]))"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"X"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+strings
+""
+"XY"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"bar"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"ffoo bbar N x"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;10-11 10-11;-;10-11 10-11
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"\\b(fo|foo)\\b"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:\\b(fo|foo)\\b)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"\\b(fo|foo)\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(fo|foo)\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+""
+regexps
+"\\b\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\b\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:\\b\\b)$"
+-;-;-;-
+-;1-1;-;1-1
+strings
+""
+""
+regexps
+"\\b$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\b$"
+-;-;-;-
+-;1-1;-;1-1
+"^(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:\\b$)$"
+-;-;-;-
+-;1-1;-;1-1
+strings
+""
+"y x"
+regexps
+"\\b$"
+-;-;-;-
+-;3-3;-;3-3
+"^(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:\\b$)$"
+-;-;-;-
+-;3-3;-;3-3
+strings
+""
+"x"
+regexps
+"\\b.$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\b.$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"fo"
+regexps
+"^\\b(fo|foo)\\b"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^\\b(fo|foo)\\b)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"^\\b(fo|foo)\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^\\b(fo|foo)\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+""
+regexps
+"^\\b"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\b\\b"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b\\b)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\b$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b.$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:^\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"x"
+regexps
+"^\\b.\\b$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.\\b$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.\\b$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:^\\b.\\b$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+""
+regexps
+"^^^^^^^^\\b$$$$$$$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)"
+-;-;-;-
+-;-;-;-
+"(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\b.$$$$$$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^^^^^^^^\\b.$$$$$$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^^^^^^^^\\b.$$$$$$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:^^^^^^^^\\b.$$$$$$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\b$$$$$$$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)"
+-;-;-;-
+-;-;-;-
+"(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"n foo xfoox that"
+regexps
+"\\Bfoo\\B"
+-;-;-;-
+-;7-10;-;7-10
+"^(?:\\Bfoo\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bfoo\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bfoo\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"faoa x"
+regexps
+"a\\B"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:a\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\B)"
+-;-;-;-
+-;-;-;-
+"(?:a\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"bar x"
+regexps
+"\\Bbar"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo\nbar x"
+regexps
+"\\Bbar"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foobar"
+regexps
+"bar\\B"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foobar\nxxx"
+regexps
+"bar\\B"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foox"
+regexps
+"(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo\n"
+regexps
+"(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"\\B(foo|bar|[A-Z])"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z]))$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z]))"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z]))$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xXy"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-2 1-2;-;1-2 1-2
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"XY"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"XYZ"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-2 1-2;-;1-2 1-2
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abara"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-4 1-4;-;1-4 1-4
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfoo_"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-4 1-4;-;1-4 1-4
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfoo\n"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo bar vNx"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;9-10 9-10;-;9-10 9-10
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfoo"
+regexps
+"\\B(fo|foo)\\B"
+-;-;-;-
+-;1-3 1-3;-;1-3 1-3
+"^(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfooo"
+regexps
+"\\B(foo|fo)\\B"
+-;-;-;-
+-;1-4 1-4;-;1-4 1-4
+"^(?:\\B(foo|fo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|fo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|fo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"\\B\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"\\B\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"\\B$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"\\B$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"y x"
+regexps
+"\\B$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\B.$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B.$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B.$)"
+-;-;-;-
+-;-;-;-
+"(?:\\B.$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"^\\B(fo|foo)\\B"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"^\\B(fo|foo)\\B"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\B\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^\\B\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\B$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^\\B$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\B.$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B.$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\B.\\B$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.\\B$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.\\B$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B.\\B$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^^^^^^^^\\B$$$$$$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^\\B$$$$$$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\B.$$$$$$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\B.$$$$$$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\B.$$$$$$)"
+-;-;-;-
+-;-;-;-
+"(?:^^^^^^^^\\B.$$$$$$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\B$$$$$$$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^^^^^^^\\B$$$$$$$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\bx\\b"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\bx\\b)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\bx\\b)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\bx\\b)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"x>"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"<x"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;1-2;-;1-2
+strings
+""
+"<x>"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"ax"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xb"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"axb"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"«x"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;2-3;-;2-3
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;2-3;-;2-3
+strings
+""
+"x»"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"«x»"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;2-3;-;2-3
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"axb"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"áxβ"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;2-3;-;2-3
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"axb"
+regexps
+"\\Bx\\B"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bx\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"áxβ"
+regexps
+"\\Bx\\B"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bx\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\ny"
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\ny"
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\ny"
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\n\ny"
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\n\ny"
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\n\ny"
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"foo$bar"
+regexps
+"^(foo\\$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo\\$)$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo\\$)$)"
+-;-;-;-
+-;-;-;-
+"(?:^(foo\\$)$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo$bar"
+regexps
+"(foo\\$)"
+-;-;-;-
+-;0-4 0-4;-;0-4 0-4
+"^(?:(foo\\$))$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo\\$))"
+-;-;-;-
+-;0-4 0-4;-;0-4 0-4
+"(?:(foo\\$))$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc"
+regexps
+"^...$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^...$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^...$)"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:^...$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"本"
+regexps
+"^本$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^本$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^本$)"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:^本$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"日本語"
+regexps
+"^...$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+strings
+""
+".本."
+regexps
+"^...$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+strings
+""
+"本"
+regexps
+"^\\C\\C\\C$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^\\C\\C\\C$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^\\C\\C\\C$)"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:^\\C\\C\\C$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"本"
+regexps
+"^\\C$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\C$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"日本語"
+regexps
+"^\\C\\C\\C$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C\\C\\C$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C\\C\\C$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\C\\C\\C$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"日本語"
+regexps
+"^...$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+strings
+""
+"日本語"
+regexps
+"^.........$"
+-;-;-;-
+-;-;-;-
+"^(?:^.........$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^.........$)"
+-;-;-;-
+-;-;-;-
+"(?:^.........$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+".本."
+regexps
+"^...$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+strings
+""
+".本."
+regexps
+"^.....$"
+-;-;-;-
+-;-;-;-
+"^(?:^.....$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^.....$)"
+-;-;-;-
+-;-;-;-
+"(?:^.....$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfooo"
+regexps
+"\\B(fo|foo)\\B"
+-;-;-;-
+-;1-3 1-3;-;1-4 1-4
+"^(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"(fo|foo)"
+-;-;-;-
+0-3 0-3;0-2 0-2;0-3 0-3;0-3 0-3
+"^(?:(fo|foo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(fo|foo))"
+-;-;-;-
+0-3 0-3;0-2 0-2;0-3 0-3;0-3 0-3
+"(?:(fo|foo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"a"
+regexps
+"\\141"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\141)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\141)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\141)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"0"
+regexps
+"\\060"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\060)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\060)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\060)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"00"
+regexps
+"\\0600"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\0600)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\0600)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:\\0600)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+"08"
+regexps
+"\\608"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\608)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\608)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:\\608)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+""
+regexps
+"\\01"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\01)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\01)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\01)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"8"
+regexps
+"\\018"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\018)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\018)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:\\018)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+"a"
+regexps
+"\\x{61}"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{61})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{61})"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\x{61})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"\\x61"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x61)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x61)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\x61)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"\\x{00000061}"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{00000061})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{00000061})"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\x{00000061})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"aαβb"
+regexps
+"\\p{Greek}+"
+-;-;-;-
+-;1-5;-;1-5
+"^(?:\\p{Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{Greek}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\p{Greek}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aαβb"
+regexps
+"\\P{Greek}+"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\P{Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{Greek}+)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\P{Greek}+)$"
+-;-;-;-
+-;5-6;-;5-6
+strings
+""
+"aαβb"
+regexps
+"\\p{^Greek}+"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\p{^Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{^Greek}+)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\p{^Greek}+)$"
+-;-;-;-
+-;5-6;-;5-6
+strings
+""
+"aαβb"
+regexps
+"\\P{^Greek}+"
+-;-;-;-
+-;1-5;-;1-5
+"^(?:\\P{^Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{^Greek}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\P{^Greek}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123"
+regexps
+"[^0-9]+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:[^0-9]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[^0-9]+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:[^0-9]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{Nd}+"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:\\p{Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{Nd}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\p{Nd}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{^Nd}+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\p{^Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{^Nd}+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\p{^Nd}+)$"
+-;-;-;-
+-;6-22;-;6-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\P{Nd}+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\P{Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{Nd}+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\P{Nd}+)$"
+-;-;-;-
+-;6-22;-;6-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\P{^Nd}+"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:\\P{^Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{^Nd}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\P{^Nd}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\pN+"
+-;-;-;-
+-;3-22;-;3-22
+"^(?:\\pN+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\pN+)"
+-;-;-;-
+-;-;-;-
+"(?:\\pN+)$"
+-;-;-;-
+-;3-22;-;3-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{N}+"
+-;-;-;-
+-;3-22;-;3-22
+"^(?:\\p{N}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{N}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\p{N}+)$"
+-;-;-;-
+-;3-22;-;3-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{^N}+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\p{^N}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{^N}+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\p{^N}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123"
+regexps
+"\\p{Any}+"
+-;-;-;-
+0-6;0-6;0-6;0-6
+"^(?:\\p{Any}+)$"
+-;-;-;-
+0-6;0-6;0-6;0-6
+"^(?:\\p{Any}+)"
+-;-;-;-
+0-6;0-6;0-6;0-6
+"(?:\\p{Any}+)$"
+-;-;-;-
+0-6;0-6;0-6;0-6
+strings
+""
+"@AaB"
+regexps
+"(?i)[@-A]+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:(?i)[@-A]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?i)[@-A]+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:(?i)[@-A]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aAzZ"
+regexps
+"(?i)[A-Z]+"
+-;-;-;-
+0-4;0-4;0-4;0-4
+"^(?:(?i)[A-Z]+)$"
+-;-;-;-
+0-4;0-4;0-4;0-4
+"^(?:(?i)[A-Z]+)"
+-;-;-;-
+0-4;0-4;0-4;0-4
+"(?:(?i)[A-Z]+)$"
+-;-;-;-
+0-4;0-4;0-4;0-4
+strings
+""
+"Aa\\"
+regexps
+"(?i)[^\\\\]+"
+-;-;-;-
+-;0-2;-;0-2
+"^(?:(?i)[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?i)[^\\\\]+)"
+-;-;-;-
+-;0-2;-;0-2
+"(?:(?i)[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"acegikmoqsuwyACEGIKMOQSUWY"
+regexps
+"(?i)[acegikmoqsuwy]+"
+-;-;-;-
+0-26;0-26;0-26;0-26
+"^(?:(?i)[acegikmoqsuwy]+)$"
+-;-;-;-
+0-26;0-26;0-26;0-26
+"^(?:(?i)[acegikmoqsuwy]+)"
+-;-;-;-
+0-26;0-26;0-26;0-26
+"(?:(?i)[acegikmoqsuwy]+)$"
+-;-;-;-
+0-26;0-26;0-26;0-26
+strings
+""
+"@AaB"
+regexps
+"[@-A]+"
+-;-;-;-
+-;0-2;-;0-2
+"^(?:[@-A]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[@-A]+)"
+-;-;-;-
+-;0-2;-;0-2
+"(?:[@-A]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aAzZ"
+regexps
+"[A-Z]+"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:[A-Z]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[A-Z]+)"
+-;-;-;-
+-;-;-;-
+"(?:[A-Z]+)$"
+-;-;-;-
+-;3-4;-;3-4
+strings
+""
+"Aa\\"
+regexps
+"[^\\\\]+"
+-;-;-;-
+-;0-2;-;0-2
+"^(?:[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[^\\\\]+)"
+-;-;-;-
+-;0-2;-;0-2
+"(?:[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"acegikmoqsuwyACEGIKMOQSUWY"
+regexps
+"[acegikmoqsuwy]+"
+-;-;-;-
+-;0-13;-;0-13
+"^(?:[acegikmoqsuwy]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[acegikmoqsuwy]+)"
+-;-;-;-
+-;0-13;-;0-13
+"(?:[acegikmoqsuwy]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"^abc"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:^abc)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"^abc"
+-;-;-;-
+-;-;-;-
+"^(?:^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:^abc)"
+-;-;-;-
+-;-;-;-
+"(?:^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"^[ay]*[bx]+c"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:^[ay]*[bx]+c)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"^[ay]*[bx]+c"
+-;-;-;-
+-;0-4;-;0-4
+"^(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:^[ay]*[bx]+c)"
+-;-;-;-
+-;0-4;-;0-4
+"(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"def$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:def$)"
+-;-;-;-
+-;-;-;-
+"(?:def$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"def$"
+-;-;-;-
+-;-;-;-
+"^(?:def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:def$)"
+-;-;-;-
+-;-;-;-
+"(?:def$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"d[ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:d[ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"d[ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"[dz][ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"[dz][ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)^abc"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^abc)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"(?m)^abc"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^abc)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)^[ay]*[bx]+c"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^[ay]*[bx]+c)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"(?m)^[ay]*[bx]+c"
+-;-;-;-
+-;0-4;-;0-4
+"^(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^[ay]*[bx]+c)"
+-;-;-;-
+-;0-4;-;0-4
+"(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)def$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:(?m)def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)def$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)def$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"(?m)def$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)def$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)def$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)d[ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"(?m)d[ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)[dz][ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"(?m)[dz][ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"a"
+regexps
+"^"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"^(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^)"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"a"
+regexps
+"^^"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"^(?:^^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^)"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"(?:^^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"a"
+regexps
+"a"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"ab*"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:ab*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:ab*)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:ab*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"a\\C*"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C*)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a\\C*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"baba"
+regexps
+"a\\C*|ba\\C"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:a\\C*|ba\\C)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\C*|ba\\C)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:a\\C*|ba\\C)$"
+-;-;-;-
+-;1-4;-;1-4
diff --git a/third_party/gofrontend/libgo/go/regexp/testdata/repetition.dat b/third_party/gofrontend/libgo/go/regexp/testdata/repetition.dat
new file mode 100644
index 0000000..e6361f5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/testdata/repetition.dat
@@ -0,0 +1,163 @@
+NOTE	implicit vs. explicit repetitions : 2009-02-02
+
+# Glenn Fowler <gsf@research.att.com>
+# conforming matches (column 4) must match one of the following BREs
+#	NOMATCH
+#	(0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)*
+#	(0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)*
+# i.e., each 3-tuple has two identical elements and one (?,?)
+
+E	((..)|(.))				NULL		NOMATCH
+E	((..)|(.))((..)|(.))			NULL		NOMATCH
+E	((..)|(.))((..)|(.))((..)|(.))		NULL		NOMATCH
+
+E	((..)|(.)){1}				NULL		NOMATCH
+E	((..)|(.)){2}				NULL		NOMATCH
+E	((..)|(.)){3}				NULL		NOMATCH
+
+E	((..)|(.))*				NULL		(0,0)
+
+E	((..)|(.))				a		(0,1)(0,1)(?,?)(0,1)
+E	((..)|(.))((..)|(.))			a		NOMATCH
+E	((..)|(.))((..)|(.))((..)|(.))		a		NOMATCH
+
+E	((..)|(.)){1}				a		(0,1)(0,1)(?,?)(0,1)
+E	((..)|(.)){2}				a		NOMATCH
+E	((..)|(.)){3}				a		NOMATCH
+
+E	((..)|(.))*				a		(0,1)(0,1)(?,?)(0,1)
+
+E	((..)|(.))				aa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aa		(0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)
+E	((..)|(.))((..)|(.))((..)|(.))		aa		NOMATCH
+
+E	((..)|(.)){1}				aa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aa		(0,2)(1,2)(?,?)(1,2)
+E	((..)|(.)){3}				aa		NOMATCH
+
+E	((..)|(.))*				aa		(0,2)(0,2)(0,2)(?,?)
+
+E	((..)|(.))				aaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaa		(0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)
+E	((..)|(.))((..)|(.))((..)|(.))		aaa		(0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3)
+
+E	((..)|(.)){1}				aaa		(0,2)(0,2)(0,2)(?,?)
+#E	((..)|(.)){2}				aaa		(0,3)(2,3)(?,?)(2,3)
+E	((..)|(.)){2}				aaa		(0,3)(2,3)(0,2)(2,3)	RE2/Go
+E	((..)|(.)){3}				aaa		(0,3)(2,3)(?,?)(2,3)
+
+#E	((..)|(.))*				aaa		(0,3)(2,3)(?,?)(2,3)
+E	((..)|(.))*				aaa		(0,3)(2,3)(0,2)(2,3)	RE2/Go
+
+E	((..)|(.))				aaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaaa		(0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E	((..)|(.))((..)|(.))((..)|(.))		aaaa		(0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4)
+
+E	((..)|(.)){1}				aaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aaaa		(0,4)(2,4)(2,4)(?,?)
+#E	((..)|(.)){3}				aaaa		(0,4)(3,4)(?,?)(3,4)
+E	((..)|(.)){3}				aaaa		(0,4)(3,4)(0,2)(3,4)	RE2/Go
+
+E	((..)|(.))*				aaaa		(0,4)(2,4)(2,4)(?,?)
+
+E	((..)|(.))				aaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaaaa		(0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E	((..)|(.))((..)|(.))((..)|(.))		aaaaa		(0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5)
+
+E	((..)|(.)){1}				aaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aaaaa		(0,4)(2,4)(2,4)(?,?)
+#E	((..)|(.)){3}				aaaaa		(0,5)(4,5)(?,?)(4,5)
+E	((..)|(.)){3}				aaaaa		(0,5)(4,5)(2,4)(4,5)	RE2/Go
+
+#E	((..)|(.))*				aaaaa		(0,5)(4,5)(?,?)(4,5)
+E	((..)|(.))*				aaaaa		(0,5)(4,5)(2,4)(4,5)	RE2/Go
+
+E	((..)|(.))				aaaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaaaaa		(0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E	((..)|(.))((..)|(.))((..)|(.))		aaaaaa		(0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?)
+
+E	((..)|(.)){1}				aaaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aaaaaa		(0,4)(2,4)(2,4)(?,?)
+E	((..)|(.)){3}				aaaaaa		(0,6)(4,6)(4,6)(?,?)
+
+E	((..)|(.))*				aaaaaa		(0,6)(4,6)(4,6)(?,?)
+
+NOTE	additional repetition tests graciously provided by Chris Kuklewicz www.haskell.org 2009-02-02
+
+# These test a bug in OS X / FreeBSD / NetBSD, and libtree. 
+# Linux/GLIBC gets the {8,} and {8,8} wrong.
+
+:HA#100:E	X(.?){0,}Y	X1234567Y	(0,9)(7,8)
+:HA#101:E	X(.?){1,}Y	X1234567Y	(0,9)(7,8)
+:HA#102:E	X(.?){2,}Y	X1234567Y	(0,9)(7,8)
+:HA#103:E	X(.?){3,}Y	X1234567Y	(0,9)(7,8)
+:HA#104:E	X(.?){4,}Y	X1234567Y	(0,9)(7,8)
+:HA#105:E	X(.?){5,}Y	X1234567Y	(0,9)(7,8)
+:HA#106:E	X(.?){6,}Y	X1234567Y	(0,9)(7,8)
+:HA#107:E	X(.?){7,}Y	X1234567Y	(0,9)(7,8)
+:HA#108:E	X(.?){8,}Y	X1234567Y	(0,9)(8,8)
+#:HA#110:E	X(.?){0,8}Y	X1234567Y	(0,9)(7,8)
+:HA#110:E	X(.?){0,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#111:E	X(.?){1,8}Y	X1234567Y	(0,9)(7,8)
+:HA#111:E	X(.?){1,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#112:E	X(.?){2,8}Y	X1234567Y	(0,9)(7,8)
+:HA#112:E	X(.?){2,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#113:E	X(.?){3,8}Y	X1234567Y	(0,9)(7,8)
+:HA#113:E	X(.?){3,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#114:E	X(.?){4,8}Y	X1234567Y	(0,9)(7,8)
+:HA#114:E	X(.?){4,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#115:E	X(.?){5,8}Y	X1234567Y	(0,9)(7,8)
+:HA#115:E	X(.?){5,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#116:E	X(.?){6,8}Y	X1234567Y	(0,9)(7,8)
+:HA#116:E	X(.?){6,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#117:E	X(.?){7,8}Y	X1234567Y	(0,9)(7,8)
+:HA#117:E	X(.?){7,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+:HA#118:E	X(.?){8,8}Y	X1234567Y	(0,9)(8,8)
+
+# These test a fixed bug in my regex-tdfa that did not keep the expanded
+# form properly grouped, so right association did the wrong thing with
+# these ambiguous patterns (crafted just to test my code when I became
+# suspicious of my implementation).  The first subexpression should use
+# "ab" then "a" then "bcd".
+
+# OS X / FreeBSD / NetBSD badly fail many of these, with impossible
+# results like (0,6)(4,5)(6,6).
+
+:HA#260:E	(a|ab|c|bcd){0,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#261:E	(a|ab|c|bcd){1,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#262:E	(a|ab|c|bcd){2,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#263:E	(a|ab|c|bcd){3,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#264:E	(a|ab|c|bcd){4,}(d*)	ababcd	NOMATCH
+:HA#265:E	(a|ab|c|bcd){0,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#266:E	(a|ab|c|bcd){1,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#267:E	(a|ab|c|bcd){2,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#268:E	(a|ab|c|bcd){3,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#269:E	(a|ab|c|bcd){4,10}(d*)	ababcd	NOMATCH
+:HA#270:E	(a|ab|c|bcd)*(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#271:E	(a|ab|c|bcd)+(d*)	ababcd	(0,6)(3,6)(6,6)
+
+# The above worked on Linux/GLIBC but the following often fail.
+# They also trip up OS X / FreeBSD / NetBSD:
+
+#:HA#280:E	(ab|a|c|bcd){0,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#280:E	(ab|a|c|bcd){0,}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#281:E	(ab|a|c|bcd){1,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#281:E	(ab|a|c|bcd){1,}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#282:E	(ab|a|c|bcd){2,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#282:E	(ab|a|c|bcd){2,}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#283:E	(ab|a|c|bcd){3,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#283:E	(ab|a|c|bcd){3,}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+:HA#284:E	(ab|a|c|bcd){4,}(d*)	ababcd	NOMATCH
+#:HA#285:E	(ab|a|c|bcd){0,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#285:E	(ab|a|c|bcd){0,10}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#286:E	(ab|a|c|bcd){1,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#286:E	(ab|a|c|bcd){1,10}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#287:E	(ab|a|c|bcd){2,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#287:E	(ab|a|c|bcd){2,10}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#288:E	(ab|a|c|bcd){3,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#288:E	(ab|a|c|bcd){3,10}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+:HA#289:E	(ab|a|c|bcd){4,10}(d*)	ababcd	NOMATCH
+#:HA#290:E	(ab|a|c|bcd)*(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#290:E	(ab|a|c|bcd)*(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#291:E	(ab|a|c|bcd)+(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#291:E	(ab|a|c|bcd)+(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
diff --git a/third_party/gofrontend/libgo/go/regexp/testdata/testregex.c b/third_party/gofrontend/libgo/go/regexp/testdata/testregex.c
new file mode 100644
index 0000000..37545d0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/regexp/testdata/testregex.c
@@ -0,0 +1,2286 @@
+#pragma prototyped noticed
+
+/*
+ * regex(3) test harness
+ *
+ * build:	cc -o testregex testregex.c
+ * help:	testregex --man
+ * note:	REG_* features are detected by #ifdef; if REG_* are enums
+ *		then supply #define REG_foo REG_foo for each enum REG_foo
+ *
+ *	Glenn Fowler <gsf@research.att.com>
+ *	AT&T Research
+ *
+ * PLEASE: publish your tests so everyone can benefit
+ *
+ * The following license covers testregex.c and all associated test data.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following disclaimer:
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL AT&T BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+static const char id[] = "\n@(#)$Id: testregex (AT&T Research) 2010-06-10 $\0\n";
+
+#if _PACKAGE_ast
+#include <ast.h>
+#else
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+#include <regex.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef	__STDC__
+#include <stdlib.h>
+#include <locale.h>
+#endif
+
+#ifndef RE_DUP_MAX
+#define RE_DUP_MAX	32767
+#endif
+
+#if !_PACKAGE_ast
+#undef	REG_DISCIPLINE
+#endif
+
+#ifndef REG_DELIMITED
+#undef	_REG_subcomp
+#endif
+
+#define TEST_ARE		0x00000001
+#define TEST_BRE		0x00000002
+#define TEST_ERE		0x00000004
+#define TEST_KRE		0x00000008
+#define TEST_LRE		0x00000010
+#define TEST_SRE		0x00000020
+
+#define TEST_EXPAND		0x00000100
+#define TEST_LENIENT		0x00000200
+
+#define TEST_QUERY		0x00000400
+#define TEST_SUB		0x00000800
+#define TEST_UNSPECIFIED	0x00001000
+#define TEST_VERIFY		0x00002000
+#define TEST_AND		0x00004000
+#define TEST_OR			0x00008000
+
+#define TEST_DELIMIT		0x00010000
+#define TEST_OK			0x00020000
+#define TEST_SAME		0x00040000
+
+#define TEST_ACTUAL		0x00100000
+#define TEST_BASELINE		0x00200000
+#define TEST_FAIL		0x00400000
+#define TEST_PASS		0x00800000
+#define TEST_SUMMARY		0x01000000
+
+#define TEST_IGNORE_ERROR	0x02000000
+#define TEST_IGNORE_OVER	0x04000000
+#define TEST_IGNORE_POSITION	0x08000000
+
+#define TEST_CATCH		0x10000000
+#define TEST_VERBOSE		0x20000000
+
+#define TEST_DECOMP		0x40000000
+
+#define TEST_GLOBAL		(TEST_ACTUAL|TEST_AND|TEST_BASELINE|TEST_CATCH|TEST_FAIL|TEST_IGNORE_ERROR|TEST_IGNORE_OVER|TEST_IGNORE_POSITION|TEST_OR|TEST_PASS|TEST_SUMMARY|TEST_VERBOSE)
+
+#ifdef REG_DISCIPLINE
+
+
+#include <stk.h>
+
+typedef struct Disc_s
+{
+	regdisc_t	disc;
+	int		ordinal;
+	Sfio_t*		sp;
+} Disc_t;
+
+static void*
+compf(const regex_t* re, const char* xstr, size_t xlen, regdisc_t* disc)
+{
+	Disc_t*		dp = (Disc_t*)disc;
+
+	return (void*)((char*)0 + ++dp->ordinal);
+}
+
+static int
+execf(const regex_t* re, void* data, const char* xstr, size_t xlen, const char* sstr, size_t slen, char** snxt, regdisc_t* disc)
+{
+	Disc_t*		dp = (Disc_t*)disc;
+
+	sfprintf(dp->sp, "{%-.*s}(%lu:%d)", xlen, xstr, (char*)data - (char*)0, slen);
+	return atoi(xstr);
+}
+
+static void*
+resizef(void* handle, void* data, size_t size)
+{
+	if (!size)
+		return 0;
+	return stkalloc((Sfio_t*)handle, size);
+}
+
+#endif
+
+#ifndef NiL
+#ifdef	__STDC__
+#define NiL		0
+#else
+#define NiL		(char*)0
+#endif
+#endif
+
+#define H(x)		do{if(html)fprintf(stderr,x);}while(0)
+#define T(x)		fprintf(stderr,x)
+
+static void
+help(int html)
+{
+H("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n");
+H("<HTML>\n");
+H("<HEAD>\n");
+H("<TITLE>testregex man document</TITLE>\n");
+H("</HEAD>\n");
+H("<BODY bgcolor=white>\n");
+H("<PRE>\n");
+T("NAME\n");
+T("  testregex - regex(3) test harness\n");
+T("\n");
+T("SYNOPSIS\n");
+T("  testregex [ options ]\n");
+T("\n");
+T("DESCRIPTION\n");
+T("  testregex reads regex(3) test specifications, one per line, from the\n");
+T("  standard input and writes one output line for each failed test. A\n");
+T("  summary line is written after all tests are done. Each successful\n");
+T("  test is run again with REG_NOSUB. Unsupported features are noted\n");
+T("  before the first test, and tests requiring these features are\n");
+T("  silently ignored.\n");
+T("\n");
+T("OPTIONS\n");
+T("  -c	catch signals and non-terminating calls\n");
+T("  -e	ignore error return mismatches\n");
+T("  -h	list help on standard error\n");
+T("  -n	do not repeat successful tests with regnexec()\n");
+T("  -o	ignore match[] overrun errors\n");
+T("  -p	ignore negative position mismatches\n");
+T("  -s	use stack instead of malloc\n");
+T("  -x	do not repeat successful tests with REG_NOSUB\n");
+T("  -v	list each test line\n");
+T("  -A	list failed test lines with actual answers\n");
+T("  -B	list all test lines with actual answers\n");
+T("  -F	list failed test lines\n");
+T("  -P	list passed test lines\n");
+T("  -S	output one summary line\n");
+T("\n");
+T("INPUT FORMAT\n");
+T("  Input lines may be blank, a comment beginning with #, or a test\n");
+T("  specification. A specification is five fields separated by one\n");
+T("  or more tabs. NULL denotes the empty string and NIL denotes the\n");
+T("  0 pointer.\n");
+T("\n");
+T("  Field 1: the regex(3) flags to apply, one character per REG_feature\n");
+T("  flag. The test is skipped if REG_feature is not supported by the\n");
+T("  implementation. If the first character is not [BEASKLP] then the\n");
+T("  specification is a global control line. One or more of [BEASKLP] may be\n");
+T("  specified; the test will be repeated for each mode.\n");
+T("\n");
+T("    B 	basic			BRE	(grep, ed, sed)\n");
+T("    E 	REG_EXTENDED		ERE	(egrep)\n");
+T("    A	REG_AUGMENTED		ARE	(egrep with negation)\n");
+T("    S	REG_SHELL		SRE	(sh glob)\n");
+T("    K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)\n");
+T("    L	REG_LITERAL		LRE	(fgrep)\n");
+T("\n");
+T("    a	REG_LEFT|REG_RIGHT	implicit ^...$\n");
+T("    b	REG_NOTBOL		lhs does not match ^\n");
+T("    c	REG_COMMENT		ignore space and #...\\n\n");
+T("    d	REG_SHELL_DOT		explicit leading . match\n");
+T("    e	REG_NOTEOL		rhs does not match $\n");
+T("    f	REG_MULTIPLE		multiple \\n separated patterns\n");
+T("    g	FNM_LEADING_DIR		testfnmatch only -- match until /\n");
+T("    h	REG_MULTIREF		multiple digit backref\n");
+T("    i	REG_ICASE		ignore case\n");
+T("    j	REG_SPAN		. matches \\n\n");
+T("    k	REG_ESCAPE		\\ to ecape [...] delimiter\n");
+T("    l	REG_LEFT		implicit ^...\n");
+T("    m	REG_MINIMAL		minimal match\n");
+T("    n	REG_NEWLINE		explicit \\n match\n");
+T("    o	REG_ENCLOSED		(|&) magic inside [@|&](...)\n");
+T("    p	REG_SHELL_PATH		explicit / match\n");
+T("    q	REG_DELIMITED		delimited pattern\n");
+T("    r	REG_RIGHT		implicit ...$\n");
+T("    s	REG_SHELL_ESCAPED	\\ not special\n");
+T("    t	REG_MUSTDELIM		all delimiters must be specified\n");
+T("    u	standard unspecified behavior -- errors not counted\n");
+T("    v	REG_CLASS_ESCAPE	\\ special inside [...]\n");
+T("    w	REG_NOSUB		no subexpression match array\n");
+T("    x	REG_LENIENT		let some errors slide\n");
+T("    y	REG_LEFT		regexec() implicit ^...\n");
+T("    z	REG_NULL		NULL subexpressions ok\n");
+T("    $	                        expand C \\c escapes in fields 2 and 3\n");
+T("    /	                        field 2 is a regsubcomp() expression\n");
+T("    =	                        field 3 is a regdecomp() expression\n");
+T("\n");
+T("  Field 1 control lines:\n");
+T("\n");
+T("    C		set LC_COLLATE and LC_CTYPE to locale in field 2\n");
+T("\n");
+T("    ?test ...	output field 5 if passed and != EXPECTED, silent otherwise\n");
+T("    &test ...	output field 5 if current and previous passed\n");
+T("    |test ...	output field 5 if current passed and previous failed\n");
+T("    ; ...	output field 2 if previous failed\n");
+T("    {test ...	skip if failed until }\n");
+T("    }		end of skip\n");
+T("\n");
+T("    : comment		comment copied as output NOTE\n");
+T("    :comment:test	:comment: ignored\n");
+T("    N[OTE] comment	comment copied as output NOTE\n");
+T("    T[EST] comment	comment\n");
+T("\n");
+T("    number		use number for nmatch (20 by default)\n");
+T("\n");
+T("  Field 2: the regular expression pattern; SAME uses the pattern from\n");
+T("    the previous specification. RE_DUP_MAX inside {...} expands to the\n");
+T("    value from <limits.h>.\n");
+T("\n");
+T("  Field 3: the string to match. X...{RE_DUP_MAX} expands to RE_DUP_MAX\n");
+T("    copies of X.\n");
+T("\n");
+T("  Field 4: the test outcome. This is either one of the posix error\n");
+T("    codes (with REG_ omitted) or the match array, a list of (m,n)\n");
+T("    entries with m and n being first and last+1 positions in the\n");
+T("    field 3 string, or NULL if REG_NOSUB is in effect and success\n");
+T("    is expected. BADPAT is acceptable in place of any regcomp(3)\n");
+T("    error code. The match[] array is initialized to (-2,-2) before\n");
+T("    each test. All array elements from 0 to nmatch-1 must be specified\n");
+T("    in the outcome. Unspecified endpoints (offset -1) are denoted by ?.\n");
+T("    Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a\n");
+T("    matched (?{...}) expression, where x is the text enclosed by {...},\n");
+T("    o is the expression ordinal counting from 1, and n is the length of\n");
+T("    the unmatched portion of the subject string. If x starts with a\n");
+T("    number then that is the return value of re_execf(), otherwise 0 is\n");
+T("    returned. RE_DUP_MAX[-+]N expands to the <limits.h> value -+N.\n");
+T("\n");
+T("  Field 5: optional comment appended to the report.\n");
+T("\n");
+T("CAVEAT\n");
+T("    If a regex implementation misbehaves with memory then all bets are off.\n");
+T("\n");
+T("CONTRIBUTORS\n");
+T("  Glenn Fowler    gsf@research.att.com        (ksh strmatch, regex extensions)\n");
+T("  David Korn      dgk@research.att.com        (ksh glob matcher)\n");
+T("  Doug McIlroy    mcilroy@dartmouth.edu       (ast regex/testre in C++)\n");
+T("  Tom Lord        lord@regexps.com            (rx tests)\n");
+T("  Henry Spencer   henry@zoo.toronto.edu       (original public regex)\n");
+T("  Andrew Hume     andrew@research.att.com     (gre tests)\n");
+T("  John Maddock    John_Maddock@compuserve.com (regex++ tests)\n");
+T("  Philip Hazel    ph10@cam.ac.uk              (pcre tests)\n");
+T("  Ville Laurikari vl@iki.fi                   (libtre tests)\n");
+H("</PRE>\n");
+H("</BODY>\n");
+H("</HTML>\n");
+}
+
+#ifndef elementsof
+#define elementsof(x)	(sizeof(x)/sizeof(x[0]))
+#endif
+
+#ifndef streq
+#define streq(a,b)	(*(a)==*(b)&&!strcmp(a,b))
+#endif
+
+#define HUNG		2
+#define NOTEST		(~0)
+
+#ifndef REG_TEST_DEFAULT
+#define REG_TEST_DEFAULT	0
+#endif
+
+#ifndef REG_EXEC_DEFAULT
+#define REG_EXEC_DEFAULT	0
+#endif
+
+static const char* unsupported[] =
+{
+	"BASIC",
+#ifndef REG_EXTENDED
+	"EXTENDED",
+#endif
+#ifndef REG_AUGMENTED
+	"AUGMENTED",
+#endif
+#ifndef REG_SHELL
+	"SHELL",
+#endif
+
+#ifndef REG_CLASS_ESCAPE
+	"CLASS_ESCAPE",
+#endif
+#ifndef REG_COMMENT
+	"COMMENT",
+#endif
+#ifndef REG_DELIMITED
+	"DELIMITED",
+#endif
+#ifndef REG_DISCIPLINE
+	"DISCIPLINE",
+#endif
+#ifndef REG_ESCAPE
+	"ESCAPE",
+#endif
+#ifndef REG_ICASE
+	"ICASE",
+#endif
+#ifndef REG_LEFT
+	"LEFT",
+#endif
+#ifndef REG_LENIENT
+	"LENIENT",
+#endif
+#ifndef REG_LITERAL
+	"LITERAL",
+#endif
+#ifndef REG_MINIMAL
+	"MINIMAL",
+#endif
+#ifndef REG_MULTIPLE
+	"MULTIPLE",
+#endif
+#ifndef REG_MULTIREF
+	"MULTIREF",
+#endif
+#ifndef REG_MUSTDELIM
+	"MUSTDELIM",
+#endif
+#ifndef REG_NEWLINE
+	"NEWLINE",
+#endif
+#ifndef REG_NOTBOL
+	"NOTBOL",
+#endif
+#ifndef REG_NOTEOL
+	"NOTEOL",
+#endif
+#ifndef REG_NULL
+	"NULL",
+#endif
+#ifndef REG_RIGHT
+	"RIGHT",
+#endif
+#ifndef REG_SHELL_DOT
+	"SHELL_DOT",
+#endif
+#ifndef REG_SHELL_ESCAPED
+	"SHELL_ESCAPED",
+#endif
+#ifndef REG_SHELL_GROUP
+	"SHELL_GROUP",
+#endif
+#ifndef REG_SHELL_PATH
+	"SHELL_PATH",
+#endif
+#ifndef REG_SPAN
+	"SPAN",
+#endif
+#if REG_NOSUB & REG_TEST_DEFAULT
+	"SUBMATCH",
+#endif
+#if !_REG_nexec
+	"regnexec",
+#endif
+#if !_REG_subcomp
+	"regsubcomp",
+#endif
+#if !_REG_decomp
+	"redecomp",
+#endif
+	0
+};
+
+#ifndef REG_CLASS_ESCAPE
+#define REG_CLASS_ESCAPE	NOTEST
+#endif
+#ifndef REG_COMMENT
+#define REG_COMMENT	NOTEST
+#endif
+#ifndef REG_DELIMITED
+#define REG_DELIMITED	NOTEST
+#endif
+#ifndef REG_ESCAPE
+#define REG_ESCAPE	NOTEST
+#endif
+#ifndef REG_ICASE
+#define REG_ICASE	NOTEST
+#endif
+#ifndef REG_LEFT
+#define REG_LEFT	NOTEST
+#endif
+#ifndef REG_LENIENT
+#define REG_LENIENT	0
+#endif
+#ifndef REG_MINIMAL
+#define REG_MINIMAL	NOTEST
+#endif
+#ifndef REG_MULTIPLE
+#define REG_MULTIPLE	NOTEST
+#endif
+#ifndef REG_MULTIREF
+#define REG_MULTIREF	NOTEST
+#endif
+#ifndef REG_MUSTDELIM
+#define REG_MUSTDELIM	NOTEST
+#endif
+#ifndef REG_NEWLINE
+#define REG_NEWLINE	NOTEST
+#endif
+#ifndef REG_NOTBOL
+#define REG_NOTBOL	NOTEST
+#endif
+#ifndef REG_NOTEOL
+#define REG_NOTEOL	NOTEST
+#endif
+#ifndef REG_NULL
+#define REG_NULL	NOTEST
+#endif
+#ifndef REG_RIGHT
+#define REG_RIGHT	NOTEST
+#endif
+#ifndef REG_SHELL_DOT
+#define REG_SHELL_DOT	NOTEST
+#endif
+#ifndef REG_SHELL_ESCAPED
+#define REG_SHELL_ESCAPED	NOTEST
+#endif
+#ifndef REG_SHELL_GROUP
+#define REG_SHELL_GROUP	NOTEST
+#endif
+#ifndef REG_SHELL_PATH
+#define REG_SHELL_PATH	NOTEST
+#endif
+#ifndef REG_SPAN
+#define REG_SPAN	NOTEST
+#endif
+
+#define REG_UNKNOWN	(-1)
+
+#ifndef REG_ENEWLINE
+#define REG_ENEWLINE	(REG_UNKNOWN-1)
+#endif
+#ifndef REG_ENULL
+#ifndef REG_EMPTY
+#define REG_ENULL	(REG_UNKNOWN-2)
+#else
+#define REG_ENULL	REG_EMPTY
+#endif
+#endif
+#ifndef REG_ECOUNT
+#define REG_ECOUNT	(REG_UNKNOWN-3)
+#endif
+#ifndef REG_BADESC
+#define REG_BADESC	(REG_UNKNOWN-4)
+#endif
+#ifndef REG_EMEM
+#define REG_EMEM	(REG_UNKNOWN-5)
+#endif
+#ifndef REG_EHUNG
+#define REG_EHUNG	(REG_UNKNOWN-6)
+#endif
+#ifndef REG_EBUS
+#define REG_EBUS	(REG_UNKNOWN-7)
+#endif
+#ifndef REG_EFAULT
+#define REG_EFAULT	(REG_UNKNOWN-8)
+#endif
+#ifndef REG_EFLAGS
+#define REG_EFLAGS	(REG_UNKNOWN-9)
+#endif
+#ifndef REG_EDELIM
+#define REG_EDELIM	(REG_UNKNOWN-9)
+#endif
+
+static const struct { int code; char* name; } codes[] =
+{
+	REG_UNKNOWN,	"UNKNOWN",
+	REG_NOMATCH,	"NOMATCH",
+	REG_BADPAT,	"BADPAT",
+	REG_ECOLLATE,	"ECOLLATE",
+	REG_ECTYPE,	"ECTYPE",
+	REG_EESCAPE,	"EESCAPE",
+	REG_ESUBREG,	"ESUBREG",
+	REG_EBRACK,	"EBRACK",
+	REG_EPAREN,	"EPAREN",
+	REG_EBRACE,	"EBRACE",
+	REG_BADBR,	"BADBR",
+	REG_ERANGE,	"ERANGE",
+	REG_ESPACE,	"ESPACE",
+	REG_BADRPT,	"BADRPT",
+	REG_ENEWLINE,	"ENEWLINE",
+	REG_ENULL,	"ENULL",
+	REG_ECOUNT,	"ECOUNT",
+	REG_BADESC,	"BADESC",
+	REG_EMEM,	"EMEM",
+	REG_EHUNG,	"EHUNG",
+	REG_EBUS,	"EBUS",
+	REG_EFAULT,	"EFAULT",
+	REG_EFLAGS,	"EFLAGS",
+	REG_EDELIM,	"EDELIM",
+};
+
+static struct
+{
+	regmatch_t	NOMATCH;
+	int		errors;
+	int		extracted;
+	int		ignored;
+	int		lineno;
+	int		passed;
+	int		signals;
+	int		unspecified;
+	int		verify;
+	int		warnings;
+	char*		file;
+	char*		stack;
+	char*		which;
+	jmp_buf		gotcha;
+#ifdef REG_DISCIPLINE
+	Disc_t		disc;
+#endif
+} state;
+
+static void
+quote(char* s, int len, unsigned long test)
+{
+	unsigned char*	u = (unsigned char*)s;
+	unsigned char*	e;
+	int		c;
+#ifdef MB_CUR_MAX
+	int		w;
+#endif
+
+	if (!u)
+		printf("NIL");
+	else if (!*u && len <= 1)
+		printf("NULL");
+	else if (test & TEST_EXPAND)
+	{
+		if (len < 0)
+			len = strlen((char*)u);
+		e = u + len;
+		if (test & TEST_DELIMIT)
+			printf("\"");
+		while (u < e)
+			switch (c = *u++)
+			{
+			case '\\':
+				printf("\\\\");
+				break;
+			case '"':
+				if (test & TEST_DELIMIT)
+					printf("\\\"");
+				else
+					printf("\"");
+				break;
+			case '\a':
+				printf("\\a");
+				break;
+			case '\b':
+				printf("\\b");
+				break;
+			case 033:
+				printf("\\e");
+				break;
+			case '\f':
+				printf("\\f");
+				break;
+			case '\n':
+				printf("\\n");
+				break;
+			case '\r':
+				printf("\\r");
+				break;
+			case '\t':
+				printf("\\t");
+				break;
+			case '\v':
+				printf("\\v");
+				break;
+			default:
+#ifdef MB_CUR_MAX
+				s = (char*)u - 1;
+				if ((w = mblen(s, (char*)e - s)) > 1)
+				{
+					u += w - 1;
+					fwrite(s, 1, w, stdout);
+				}
+				else
+#endif
+				if (!iscntrl(c) && isprint(c))
+					putchar(c);
+				else
+					printf("\\x%02x", c);
+				break;
+			}
+		if (test & TEST_DELIMIT)
+			printf("\"");
+	}
+	else
+		printf("%s", s);
+}
+
+static void
+report(char* comment, char* fun, char* re, char* s, int len, char* msg, int flags, unsigned long test)
+{
+	if (state.file)
+		printf("%s:", state.file);
+	printf("%d:", state.lineno);
+	if (re)
+	{
+		printf(" ");
+		quote(re, -1, test|TEST_DELIMIT);
+		if (s)
+		{
+			printf(" versus ");
+			quote(s, len, test|TEST_DELIMIT);
+		}
+	}
+	if (test & TEST_UNSPECIFIED)
+	{
+		state.unspecified++;
+		printf(" unspecified behavior");
+	}
+	else
+		state.errors++;
+	if (state.which)
+		printf(" %s", state.which);
+	if (flags & REG_NOSUB)
+		printf(" NOSUB");
+	if (fun)
+		printf(" %s", fun);
+	if (comment[strlen(comment)-1] == '\n')
+		printf(" %s", comment);
+	else
+	{
+		printf(" %s: ", comment);
+		if (msg)
+			printf("%s: ", msg);
+	}
+}
+
+static void
+error(regex_t* preg, int code)
+{
+	char*	msg;
+	char	buf[256];
+
+	switch (code)
+	{
+	case REG_EBUS:
+		msg = "bus error";
+		break;
+	case REG_EFAULT:
+		msg = "memory fault";
+		break;
+	case REG_EHUNG:
+		msg = "did not terminate";
+		break;
+	default:
+		regerror(code, preg, msg = buf, sizeof buf);
+		break;
+	}
+	printf("%s\n", msg);
+}
+
+static void
+bad(char* comment, char* re, char* s, int len, unsigned long test)
+{
+	printf("bad test case ");
+	report(comment, NiL, re, s, len, NiL, 0, test);
+	exit(1);
+}
+
+static int
+escape(char* s)
+{
+	char*	b;
+	char*	t;
+	char*	q;
+	char*	e;
+	int	c;
+
+	for (b = t = s; *t = *s; s++, t++)
+		if (*s == '\\')
+			switch (*++s)
+			{
+			case '\\':
+				break;
+			case 'a':
+				*t = '\a';
+				break;
+			case 'b':
+				*t = '\b';
+				break;
+			case 'c':
+				if (*t = *++s)
+					*t &= 037;
+				else
+					s--;
+				break;
+			case 'e':
+			case 'E':
+				*t = 033;
+				break;
+			case 'f':
+				*t = '\f';
+				break;
+			case 'n':
+				*t = '\n';
+				break;
+			case 'r':
+				*t = '\r';
+				break;
+			case 's':
+				*t = ' ';
+				break;
+			case 't':
+				*t = '\t';
+				break;
+			case 'v':
+				*t = '\v';
+				break;
+			case 'u':
+			case 'x':
+				c = 0;
+				q = c == 'u' ? (s + 5) : (char*)0;
+				e = s + 1;
+				while (!e || !q || s < q)
+				{
+					switch (*++s)
+					{
+					case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+						c = (c << 4) + *s - 'a' + 10;
+						continue;
+					case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+						c = (c << 4) + *s - 'A' + 10;
+						continue;
+					case '0': case '1': case '2': case '3': case '4':
+					case '5': case '6': case '7': case '8': case '9':
+						c = (c << 4) + *s - '0';
+						continue;
+					case '{':
+					case '[':
+						if (s != e)
+						{
+							s--;
+							break;
+						}
+						e = 0;
+						continue;
+					case '}':
+					case ']':
+						if (e)
+							s--;
+						break;
+					default:
+						s--;
+						break;
+					}
+					break;
+				}
+				*t = c;
+				break;
+			case '0': case '1': case '2': case '3':
+			case '4': case '5': case '6': case '7':
+				c = *s - '0';
+				q = s + 2;
+				while (s < q)
+				{
+					switch (*++s)
+					{
+					case '0': case '1': case '2': case '3':
+					case '4': case '5': case '6': case '7':
+						c = (c << 3) + *s - '0';
+						break;
+					default:
+						q = --s;
+						break;
+					}
+				}
+				*t = c;
+				break;
+			default:
+				*(s + 1) = 0;
+				bad("invalid C \\ escape\n", s - 1, NiL, 0, 0);
+			}
+	return t - b;
+}
+
+static void
+matchoffprint(int off)
+{
+	switch (off)
+	{
+	case -2:
+		printf("X");
+		break;
+	case -1:
+		printf("?");
+		break;
+	default:
+		printf("%d", off);
+		break;
+	}
+}
+
+static void
+matchprint(regmatch_t* match, int nmatch, int nsub, char* ans, unsigned long test)
+{
+	int	i;
+
+	for (; nmatch > nsub + 1; nmatch--)
+		if ((match[nmatch-1].rm_so != -1 || match[nmatch-1].rm_eo != -1) && (!(test & TEST_IGNORE_POSITION) || match[nmatch-1].rm_so >= 0 && match[nmatch-1].rm_eo >= 0))
+			break;
+	for (i = 0; i < nmatch; i++)
+	{
+		printf("(");
+		matchoffprint(match[i].rm_so);
+		printf(",");
+		matchoffprint(match[i].rm_eo);
+		printf(")");
+	}
+	if (!(test & (TEST_ACTUAL|TEST_BASELINE)))
+	{
+		if (ans)
+			printf(" expected: %s", ans);
+		printf("\n");
+	}
+}
+
+static int
+matchcheck(regmatch_t* match, int nmatch, int nsub, char* ans, char* re, char* s, int len, int flags, unsigned long test)
+{
+	char*	p;
+	int	i;
+	int	m;
+	int	n;
+
+	if (streq(ans, "OK"))
+		return test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY);
+	for (i = 0, p = ans; i < nmatch && *p; i++)
+	{
+		if (*p == '{')
+		{
+#ifdef REG_DISCIPLINE
+			char*	x;
+
+			if (!(x = sfstruse(state.disc.sp)))
+				bad("out of space [discipline string]\n", NiL, NiL, 0, 0);
+			if (strcmp(p, x))
+			{
+				if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+					return 0;
+				report("callout failed", NiL, re, s, len, NiL, flags, test);
+				quote(p, -1, test);
+				printf(" expected, ");
+				quote(x, -1, test);
+				printf(" returned\n");
+			}
+#endif
+			break;
+		}
+		if (*p++ != '(')
+			bad("improper answer\n", re, s, -1, test);
+		if (*p == '?')
+		{
+			m = -1;
+			p++;
+		}
+		else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10))
+		{
+			m = RE_DUP_MAX;
+			p += 10;
+			if (*p == '+' || *p == '-')
+				m += strtol(p, &p, 10);
+		}
+		else
+			m = strtol(p, &p, 10);
+		if (*p++ != ',')
+			bad("improper answer\n", re, s, -1, test);
+		if (*p == '?')
+		{
+			n = -1;
+			p++;
+		}
+		else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10))
+		{
+			n = RE_DUP_MAX;
+			p += 10;
+			if (*p == '+' || *p == '-')
+				n += strtol(p, &p, 10);
+		}
+		else
+			n = strtol(p, &p, 10);
+		if (*p++ != ')')
+			bad("improper answer\n", re, s, -1, test);
+		if (m!=match[i].rm_so || n!=match[i].rm_eo)
+		{
+			if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)))
+			{
+				report("failed: match was", NiL, re, s, len, NiL, flags, test);
+				matchprint(match, nmatch, nsub, ans, test);
+			}
+			return 0;
+		}
+	}
+	for (; i < nmatch; i++)
+	{
+		if (match[i].rm_so!=-1 || match[i].rm_eo!=-1)
+		{
+			if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_VERIFY)))
+			{
+				if ((test & TEST_IGNORE_POSITION) && (match[i].rm_so<0 || match[i].rm_eo<0))
+				{
+					state.ignored++;
+					return 0;
+				}
+				if (!(test & TEST_SUMMARY))
+				{
+					report("failed: match was", NiL, re, s, len, NiL, flags, test);
+					matchprint(match, nmatch, nsub, ans, test);
+				}
+			}
+			return 0;
+		}
+	}
+	if (!(test & TEST_IGNORE_OVER) && match[nmatch].rm_so != state.NOMATCH.rm_so)
+	{
+		if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)))
+		{
+			report("failed: overran match array", NiL, re, s, len, NiL, flags, test);
+			matchprint(match, nmatch + 1, nsub, NiL, test);
+		}
+		return 0;
+	}
+	return 1;
+}
+
+static void
+sigunblock(int s)
+{
+#ifdef SIG_SETMASK
+	int		op;
+	sigset_t	mask;
+
+	sigemptyset(&mask);
+	if (s)
+	{
+		sigaddset(&mask, s);
+		op = SIG_UNBLOCK;
+	}
+	else op = SIG_SETMASK;
+	sigprocmask(op, &mask, NiL);
+#else
+#ifdef sigmask
+	sigsetmask(s ? (sigsetmask(0L) & ~sigmask(s)) : 0L);
+#endif
+#endif
+}
+
+static void
+gotcha(int sig)
+{
+	int	ret;
+
+	signal(sig, gotcha);
+	alarm(0);
+	state.signals++;
+	switch (sig)
+	{
+	case SIGALRM:
+		ret = REG_EHUNG;
+		break;
+	case SIGBUS:
+		ret = REG_EBUS;
+		break;
+	default:
+		ret = REG_EFAULT;
+		break;
+	}
+	sigunblock(sig);
+	longjmp(state.gotcha, ret);
+}
+
+static char*
+getline(FILE* fp)
+{
+	static char	buf[32 * 1024];
+
+	register char*	s = buf;
+	register char*	e = &buf[sizeof(buf)];
+	register char*	b;
+
+	for (;;)
+	{
+		if (!(b = fgets(s, e - s, fp)))
+			return 0;
+		state.lineno++;
+		s += strlen(s);
+		if (s == b || *--s != '\n' || s == b || *(s - 1) != '\\')
+		{
+			*s = 0;
+			break;
+		}
+		s--;
+	}
+	return buf;
+}
+
+static unsigned long
+note(unsigned long level, char* msg, unsigned long skip, unsigned long test)
+{
+	if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)) && !skip)
+	{
+		printf("NOTE\t");
+		if (msg)
+			printf("%s: ", msg);
+		printf("skipping lines %d", state.lineno);
+	}
+	return skip | level;
+}
+
+#define TABS(n)		&ts[7-((n)&7)]
+
+static char		ts[] = "\t\t\t\t\t\t\t";
+
+static unsigned long
+extract(int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test)
+{
+	if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_OK|TEST_PASS|TEST_SUMMARY))
+	{
+		state.extracted = 1;
+		if (test & TEST_OK)
+		{
+			state.passed++;
+			if ((test & TEST_VERIFY) && !(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+			{
+				if (msg && strcmp(msg, "EXPECTED"))
+					printf("NOTE\t%s\n", msg);
+				return skip;
+			}
+			test &= ~(TEST_PASS|TEST_QUERY);
+		}
+		if (test & (TEST_QUERY|TEST_VERIFY))
+		{
+			if (test & TEST_BASELINE)
+				test &= ~(TEST_BASELINE|TEST_PASS);
+			else
+				test |= TEST_PASS;
+			skip |= level;
+		}
+		if (!(test & TEST_OK))
+		{
+			if (test & TEST_UNSPECIFIED)
+				state.unspecified++;
+			else
+				state.errors++;
+		}
+		if (test & (TEST_PASS|TEST_SUMMARY))
+			return skip;
+		test &= ~TEST_DELIMIT;
+		printf("%s%s", spec, TABS(*tabs++));
+		if ((test & (TEST_BASELINE|TEST_SAME)) == (TEST_BASELINE|TEST_SAME))
+			printf("SAME");
+		else
+			quote(re, -1, test);
+		printf("%s", TABS(*tabs++));
+		quote(s, -1, test);
+		printf("%s", TABS(*tabs++));
+		if (!(test & (TEST_ACTUAL|TEST_BASELINE)) || !accept && !match)
+			printf("%s", ans);
+		else if (accept)
+			printf("%s", accept);
+		else
+			matchprint(match, nmatch, nsub, NiL, test);
+		if (msg)
+			printf("%s%s", TABS(*tabs++), msg);
+		putchar('\n');
+	}
+	else if (test & TEST_QUERY)
+		skip = note(level, msg, skip, test);
+	else if (test & TEST_VERIFY)
+		state.extracted = 1;
+	return skip;
+}
+
+static int
+catchfree(regex_t* preg, int flags, int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test)
+{
+	int	eret;
+
+	if (!(test & TEST_CATCH))
+	{
+		regfree(preg);
+		eret = 0;
+	}
+	else if (!(eret = setjmp(state.gotcha)))
+	{
+		alarm(HUNG);
+		regfree(preg);
+		alarm(0);
+	}
+	else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+		extract(tabs, spec, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+	else
+	{
+		report("failed", "regfree", re, NiL, -1, msg, flags, test);
+		error(preg, eret);
+	}
+	return eret;
+}
+
+static char*
+expand(char* os, char* ot)
+{
+	char*	s = os;
+	char*	t;
+	int	n = 0;
+	int	r;
+	long	m;
+
+	for (;;)
+	{
+		switch (*s++)
+		{
+		case 0:
+			break;
+		case '{':
+			n++;
+			continue;
+		case '}':
+			n--;
+			continue;
+		case 'R':
+			if (n == 1 && !memcmp(s, "E_DUP_MAX", 9))
+			{
+				s--;
+				for (t = ot; os < s; *t++ = *os++);
+				r = ((t - ot) >= 5 && t[-1] == '{' && t[-2] == '.' && t[-3] == '.' && t[-4] == '.') ? t[-5] : 0;
+				os = ot;
+				m = RE_DUP_MAX;
+				if (*(s += 10) == '+' || *s == '-')
+					m += strtol(s, &s, 10);
+				if (r)
+				{
+					t -= 5;
+					while (m-- > 0)
+						*t++ = r;
+					while (*s && *s++ != '}');
+				}
+				else
+					t += snprintf(t, 32, "%ld", m);
+				while (*t = *s++)
+					t++;
+				break;
+			}
+			continue;
+		default:
+			continue;
+		}
+		break;
+	}
+	return os;
+}
+
+int
+main(int argc, char** argv)
+{
+	int		flags;
+	int		cflags;
+	int		eflags;
+	int		nmatch;
+	int		nexec;
+	int		nstr;
+	int		cret;
+	int		eret;
+	int		nsub;
+	int		i;
+	int		j;
+	int		expected;
+	int		got;
+	int		locale;
+	int		subunitlen;
+	int		testno;
+	unsigned long	level;
+	unsigned long	skip;
+	char*		p;
+	char*		line;
+	char*		spec;
+	char*		re;
+	char*		s;
+	char*		ans;
+	char*		msg;
+	char*		fun;
+	char*		ppat;
+	char*		subunit;
+	char*		version;
+	char*		field[6];
+	char*		delim[6];
+	FILE*		fp;
+	int		tabs[6];
+	char		unit[64];
+	regmatch_t	match[100];
+	regex_t		preg;
+
+	static char	pat[32 * 1024];
+	static char	patbuf[32 * 1024];
+	static char	strbuf[32 * 1024];
+
+	int		nonosub = REG_NOSUB == 0;
+	int		nonexec = 0;
+
+	unsigned long	test = 0;
+
+	static char*	filter[] = { "-", 0 };
+
+	state.NOMATCH.rm_so = state.NOMATCH.rm_eo = -2;
+	p = unit;
+	version = (char*)id + 10;
+	while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace(*p))
+		p++;
+	*p = 0;
+	while ((p = *++argv) && *p == '-')
+		for (;;)
+		{
+			switch (*++p)
+			{
+			case 0:
+				break;
+			case 'c':
+				test |= TEST_CATCH;
+				continue;
+			case 'e':
+				test |= TEST_IGNORE_ERROR;
+				continue;
+			case 'h':
+			case '?':
+				help(0);
+				return 2;
+			case '-':
+				help(p[1] == 'h');
+				return 2;
+			case 'n':
+				nonexec = 1;
+				continue;
+			case 'o':
+				test |= TEST_IGNORE_OVER;
+				continue;
+			case 'p':
+				test |= TEST_IGNORE_POSITION;
+				continue;
+			case 's':
+#ifdef REG_DISCIPLINE
+				if (!(state.stack = stkalloc(stkstd, 0)))
+					fprintf(stderr, "%s: out of space [stack]", unit);
+				state.disc.disc.re_resizef = resizef;
+				state.disc.disc.re_resizehandle = (void*)stkstd;
+#endif
+				continue;
+			case 'x':
+				nonosub = 1;
+				continue;
+			case 'v':
+				test |= TEST_VERBOSE;
+				continue;
+			case 'A':
+				test |= TEST_ACTUAL;
+				continue;
+			case 'B':
+				test |= TEST_BASELINE;
+				continue;
+			case 'F':
+				test |= TEST_FAIL;
+				continue;
+			case 'P':
+				test |= TEST_PASS;
+				continue;
+			case 'S':
+				test |= TEST_SUMMARY;
+				continue;
+			default:
+				fprintf(stderr, "%s: %c: invalid option\n", unit, *p);
+				return 2;
+			}
+			break;
+		}
+	if (!*argv)
+		argv = filter;
+	locale = 0;
+	while (state.file = *argv++)
+	{
+		if (streq(state.file, "-") || streq(state.file, "/dev/stdin") || streq(state.file, "/dev/fd/0"))
+		{
+			state.file = 0;
+			fp = stdin;
+		}
+		else if (!(fp = fopen(state.file, "r")))
+		{
+			fprintf(stderr, "%s: %s: cannot read\n", unit, state.file);
+			return 2;
+		}
+		testno = state.errors = state.ignored = state.lineno = state.passed =
+		state.signals = state.unspecified = state.warnings = 0;
+		skip = 0;
+		level = 1;
+		if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+		{
+			printf("TEST\t%s ", unit);
+			if (s = state.file)
+			{
+				subunit = p = 0;
+				for (;;)
+				{
+					switch (*s++)
+					{
+					case 0:
+						break;
+					case '/':
+						subunit = s;
+						continue;
+					case '.':
+						p = s - 1;
+						continue;
+					default:
+						continue;
+					}
+					break;
+				}
+				if (!subunit)
+					subunit = state.file;
+				if (p < subunit)
+					p = s - 1;
+				subunitlen = p - subunit;
+				printf("%-.*s ", subunitlen, subunit);
+			}
+			else
+				subunit = 0;
+			for (s = version; *s && (*s != ' ' || *(s + 1) != '$'); s++)
+				putchar(*s);
+			if (test & TEST_CATCH)
+				printf(", catch");
+			if (test & TEST_IGNORE_ERROR)
+				printf(", ignore error code mismatches");
+			if (test & TEST_IGNORE_POSITION)
+				printf(", ignore negative position mismatches");
+#ifdef REG_DISCIPLINE
+			if (state.stack)
+				printf(", stack");
+#endif
+			if (test & TEST_VERBOSE)
+				printf(", verbose");
+			printf("\n");
+#ifdef REG_VERSIONID
+			if (regerror(REG_VERSIONID, NiL, pat, sizeof(pat)) > 0)
+				s = pat;
+			else
+#endif
+#ifdef REG_TEST_VERSION
+			s = REG_TEST_VERSION;
+#else
+			s = "regex";
+#endif
+			printf("NOTE\t%s\n", s);
+			if (elementsof(unsupported) > 1)
+			{
+#if (REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) || !defined(REG_EXTENDED)
+				i = 0;
+#else
+				i = REG_EXTENDED != 0;
+#endif
+				for (got = 0; i < elementsof(unsupported) - 1; i++)
+				{
+					if (!got)
+					{
+						got = 1;
+						printf("NOTE\tunsupported: %s", unsupported[i]);
+					}
+					else
+						printf(",%s", unsupported[i]);
+				}
+				if (got)
+					printf("\n");
+			}
+		}
+#ifdef REG_DISCIPLINE
+		state.disc.disc.re_version = REG_VERSION;
+		state.disc.disc.re_compf = compf;
+		state.disc.disc.re_execf = execf;
+		if (!(state.disc.sp = sfstropen()))
+			bad("out of space [discipline string stream]\n", NiL, NiL, 0, 0);
+		preg.re_disc = &state.disc.disc;
+#endif
+		if (test & TEST_CATCH)
+		{
+			signal(SIGALRM, gotcha);
+			signal(SIGBUS, gotcha);
+			signal(SIGSEGV, gotcha);
+		}
+		while (p = getline(fp))
+		{
+
+		/* parse: */
+
+			line = p;
+			if (*p == ':' && !isspace(*(p + 1)))
+			{
+				while (*++p && *p != ':');
+				if (!*p++)
+				{
+					if (test & TEST_BASELINE)
+						printf("%s\n", line);
+					continue;
+				}
+			}
+			while (isspace(*p))
+				p++;
+			if (*p == 0 || *p == '#' || *p == 'T')
+			{
+				if (test & TEST_BASELINE)
+					printf("%s\n", line);
+				continue;
+			}
+			if (*p == ':' || *p == 'N')
+			{
+				if (test & TEST_BASELINE)
+					printf("%s\n", line);
+				else if (!(test & (TEST_ACTUAL|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+				{
+					while (*++p && !isspace(*p));
+					while (isspace(*p))
+						p++;
+					printf("NOTE	%s\n", p);
+				}
+				continue;
+			}
+			j = 0;
+			i = 0;
+			field[i++] = p;
+			for (;;)
+			{
+				switch (*p++)
+				{
+				case 0:
+					p--;
+					j = 0;
+					goto checkfield;
+				case '\t':
+					*(delim[i] = p - 1) = 0;
+					j = 1;
+				checkfield:
+					s = field[i - 1];
+					if (streq(s, "NIL"))
+						field[i - 1] = 0;
+					else if (streq(s, "NULL"))
+						*s = 0;
+					while (*p == '\t')
+					{
+						p++;
+						j++;
+					}
+					tabs[i - 1] = j;
+					if (!*p)
+						break;
+					if (i >= elementsof(field))
+						bad("too many fields\n", NiL, NiL, 0, 0);
+					field[i++] = p;
+					/*FALLTHROUGH*/
+				default:
+					continue;
+				}
+				break;
+			}
+			if (!(spec = field[0]))
+				bad("NIL spec\n", NiL, NiL, 0, 0);
+
+		/* interpret: */
+
+			cflags = REG_TEST_DEFAULT;
+			eflags = REG_EXEC_DEFAULT;
+			test &= TEST_GLOBAL;
+			state.extracted = 0;
+			nmatch = 20;
+			nsub = -1;
+			for (p = spec; *p; p++)
+			{
+				if (isdigit(*p))
+				{
+					nmatch = strtol(p, &p, 10);
+					if (nmatch >= elementsof(match))
+						bad("nmatch must be < 100\n", NiL, NiL, 0, 0);
+					p--;
+					continue;
+				}
+				switch (*p)
+				{
+				case 'A':
+					test |= TEST_ARE;
+					continue;
+				case 'B':
+					test |= TEST_BRE;
+					continue;
+				case 'C':
+					if (!(test & TEST_QUERY) && !(skip & level))
+						bad("locale must be nested\n", NiL, NiL, 0, 0);
+					test &= ~TEST_QUERY;
+					if (locale)
+						bad("locale nesting not supported\n", NiL, NiL, 0, 0);
+					if (i != 2)
+						bad("locale field expected\n", NiL, NiL, 0, 0);
+					if (!(skip & level))
+					{
+#if defined(LC_COLLATE) && defined(LC_CTYPE)
+						s = field[1];
+						if (!s || streq(s, "POSIX"))
+							s = "C";
+						if ((ans = setlocale(LC_COLLATE, s)) && streq(ans, "POSIX"))
+							ans = "C";
+						if (!ans || !streq(ans, s) && streq(s, "C"))
+							ans = 0;
+						else if ((ans = setlocale(LC_CTYPE, s)) && streq(ans, "POSIX"))
+							ans = "C";
+						if (!ans || !streq(ans, s) && streq(s, "C"))
+							skip = note(level, s, skip, test);
+						else
+						{
+							if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+								printf("NOTE	\"%s\" locale\n", s);
+							locale = level;
+						}
+#else
+						skip = note(level, skip, test, "locales not supported");
+#endif
+					}
+					cflags = NOTEST;
+					continue;
+				case 'E':
+					test |= TEST_ERE;
+					continue;
+				case 'K':
+					test |= TEST_KRE;
+					continue;
+				case 'L':
+					test |= TEST_LRE;
+					continue;
+				case 'S':
+					test |= TEST_SRE;
+					continue;
+
+				case 'a':
+					cflags |= REG_LEFT|REG_RIGHT;
+					continue;
+				case 'b':
+					eflags |= REG_NOTBOL;
+					continue;
+				case 'c':
+					cflags |= REG_COMMENT;
+					continue;
+				case 'd':
+					cflags |= REG_SHELL_DOT;
+					continue;
+				case 'e':
+					eflags |= REG_NOTEOL;
+					continue;
+				case 'f':
+					cflags |= REG_MULTIPLE;
+					continue;
+				case 'g':
+					cflags |= NOTEST;
+					continue;
+				case 'h':
+					cflags |= REG_MULTIREF;
+					continue;
+				case 'i':
+					cflags |= REG_ICASE;
+					continue;
+				case 'j':
+					cflags |= REG_SPAN;
+					continue;
+				case 'k':
+					cflags |= REG_ESCAPE;
+					continue;
+				case 'l':
+					cflags |= REG_LEFT;
+					continue;
+				case 'm':
+					cflags |= REG_MINIMAL;
+					continue;
+				case 'n':
+					cflags |= REG_NEWLINE;
+					continue;
+				case 'o':
+					cflags |= REG_SHELL_GROUP;
+					continue;
+				case 'p':
+					cflags |= REG_SHELL_PATH;
+					continue;
+				case 'q':
+					cflags |= REG_DELIMITED;
+					continue;
+				case 'r':
+					cflags |= REG_RIGHT;
+					continue;
+				case 's':
+					cflags |= REG_SHELL_ESCAPED;
+					continue;
+				case 't':
+					cflags |= REG_MUSTDELIM;
+					continue;
+				case 'u':
+					test |= TEST_UNSPECIFIED;
+					continue;
+				case 'v':
+					cflags |= REG_CLASS_ESCAPE;
+					continue;
+				case 'w':
+					cflags |= REG_NOSUB;
+					continue;
+				case 'x':
+					if (REG_LENIENT)
+						cflags |= REG_LENIENT;
+					else
+						test |= TEST_LENIENT;
+					continue;
+				case 'y':
+					eflags |= REG_LEFT;
+					continue;
+				case 'z':
+					cflags |= REG_NULL;
+					continue;
+
+				case '$':
+					test |= TEST_EXPAND;
+					continue;
+
+				case '/':
+					test |= TEST_SUB;
+					continue;
+
+				case '=':
+					test |= TEST_DECOMP;
+					continue;
+
+				case '?':
+					test |= TEST_VERIFY;
+					test &= ~(TEST_AND|TEST_OR);
+					state.verify = state.passed;
+					continue;
+				case '&':
+					test |= TEST_VERIFY|TEST_AND;
+					test &= ~TEST_OR;
+					continue;
+				case '|':
+					test |= TEST_VERIFY|TEST_OR;
+					test &= ~TEST_AND;
+					continue;
+				case ';':
+					test |= TEST_OR;
+					test &= ~TEST_AND;
+					continue;
+
+				case '{':
+					level <<= 1;
+					if (skip & (level >> 1))
+					{
+						skip |= level;
+						cflags = NOTEST;
+					}
+					else
+					{
+						skip &= ~level;
+						test |= TEST_QUERY;
+					}
+					continue;
+				case '}':
+					if (level == 1)
+						bad("invalid {...} nesting\n", NiL, NiL, 0, 0);
+					if ((skip & level) && !(skip & (level>>1)))
+					{
+						if (!(test & (TEST_BASELINE|TEST_SUMMARY)))
+						{
+							if (test & (TEST_ACTUAL|TEST_FAIL))
+								printf("}\n");
+							else if (!(test & TEST_PASS))
+								printf("-%d\n", state.lineno);
+						}
+					}
+#if defined(LC_COLLATE) && defined(LC_CTYPE)
+					else if (locale & level)
+					{
+						locale = 0;
+						if (!(skip & level))
+						{
+							s = "C";
+							setlocale(LC_COLLATE, s);
+							setlocale(LC_CTYPE, s);
+							if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+								printf("NOTE	\"%s\" locale\n", s);
+							else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_PASS))
+								printf("}\n");
+						}
+						else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL))
+							printf("}\n");
+					}
+#endif
+					level >>= 1;
+					cflags = NOTEST;
+					continue;
+
+				default:
+					bad("bad spec\n", spec, NiL, 0, test);
+					break;
+
+				}
+				break;
+			}
+			if ((cflags|eflags) == NOTEST || (skip & level) && (test & TEST_BASELINE))
+			{
+				if (test & TEST_BASELINE)
+				{
+					while (i > 1)
+						*delim[--i] = '\t';
+					printf("%s\n", line);
+				}
+				continue;
+			}
+			if (test & TEST_OR)
+			{
+				if (!(test & TEST_VERIFY))
+				{
+					test &= ~TEST_OR;
+					if (state.passed == state.verify && i > 1)
+						printf("NOTE\t%s\n", field[1]);
+					continue;
+				}
+				else if (state.passed > state.verify)
+					continue;
+			}
+			else if (test & TEST_AND)
+			{
+				if (state.passed == state.verify)
+					continue;
+				state.passed = state.verify;
+			}
+			if (i < ((test & TEST_DECOMP) ? 3 : 4))
+				bad("too few fields\n", NiL, NiL, 0, test);
+			while (i < elementsof(field))
+				field[i++] = 0;
+			if (re = field[1])
+			{
+				if (streq(re, "SAME"))
+				{
+					re = ppat;
+					test |= TEST_SAME;
+				}
+				else
+				{
+					if (test & TEST_EXPAND)
+						escape(re);
+					re = expand(re, patbuf);
+					strcpy(ppat = pat, re);
+				}
+			}
+			else
+				ppat = 0;
+			nstr = -1;
+			if (s = field[2])
+			{
+				s = expand(s, strbuf);
+				if (test & TEST_EXPAND)
+				{
+					nstr = escape(s);
+#if _REG_nexec
+					if (nstr != strlen(s))
+						nexec = nstr;
+#endif
+				}
+			}
+			if (!(ans = field[(test & TEST_DECOMP) ? 2 : 3]))
+				bad("NIL answer\n", NiL, NiL, 0, test);
+			msg = field[4];
+			fflush(stdout);
+			if (test & TEST_SUB)
+#if _REG_subcomp
+				cflags |= REG_DELIMITED;
+#else
+				continue;
+#endif
+#if !_REG_decomp
+			if (test & TEST_DECOMP)
+				continue;
+#endif
+
+		compile:
+
+			if (state.extracted || (skip & level))
+				continue;
+#if !(REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL))
+#ifdef REG_EXTENDED
+			if (REG_EXTENDED != 0 && (test & TEST_BRE))
+#else
+			if (test & TEST_BRE)
+#endif
+			{
+				test &= ~TEST_BRE;
+				flags = cflags;
+				state.which = "BRE";
+			}
+			else
+#endif
+#ifdef REG_EXTENDED
+			if (test & TEST_ERE)
+			{
+				test &= ~TEST_ERE;
+				flags = cflags | REG_EXTENDED;
+				state.which = "ERE";
+			}
+			else
+#endif
+#ifdef REG_AUGMENTED
+			if (test & TEST_ARE)
+			{
+				test &= ~TEST_ARE;
+				flags = cflags | REG_AUGMENTED;
+				state.which = "ARE";
+			}
+			else
+#endif
+#ifdef REG_LITERAL
+			if (test & TEST_LRE)
+			{
+				test &= ~TEST_LRE;
+				flags = cflags | REG_LITERAL;
+				state.which = "LRE";
+			}
+			else
+#endif
+#ifdef REG_SHELL
+			if (test & TEST_SRE)
+			{
+				test &= ~TEST_SRE;
+				flags = cflags | REG_SHELL;
+				state.which = "SRE";
+			}
+			else
+#ifdef REG_AUGMENTED
+			if (test & TEST_KRE)
+			{
+				test &= ~TEST_KRE;
+				flags = cflags | REG_SHELL | REG_AUGMENTED;
+				state.which = "KRE";
+			}
+			else
+#endif
+#endif
+			{
+				if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY))
+					extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test|TEST_OK);
+				continue;
+			}
+			if ((test & (TEST_QUERY|TEST_VERBOSE|TEST_VERIFY)) == TEST_VERBOSE)
+			{
+				printf("test %-3d %s ", state.lineno, state.which);
+				quote(re, -1, test|TEST_DELIMIT);
+				printf(" ");
+				quote(s, nstr, test|TEST_DELIMIT);
+				printf("\n");
+			}
+
+		nosub:
+			fun = "regcomp";
+#if _REG_nexec
+			if (nstr >= 0 && nstr != strlen(s))
+				nexec = nstr;
+
+			else
+#endif
+				nexec = -1;
+			if (state.extracted || (skip & level))
+				continue;
+			if (!(test & TEST_QUERY))
+				testno++;
+#ifdef REG_DISCIPLINE
+			if (state.stack)
+				stkset(stkstd, state.stack, 0);
+			flags |= REG_DISCIPLINE;
+			state.disc.ordinal = 0;
+			sfstrseek(state.disc.sp, 0, SEEK_SET);
+#endif
+			if (!(test & TEST_CATCH))
+				cret = regcomp(&preg, re, flags);
+			else if (!(cret = setjmp(state.gotcha)))
+			{
+				alarm(HUNG);
+				cret = regcomp(&preg, re, flags);
+				alarm(0);
+			}
+#if _REG_subcomp
+			if (!cret && (test & TEST_SUB))
+			{
+				fun = "regsubcomp";
+				p = re + preg.re_npat;
+				if (!(test & TEST_CATCH))
+					cret = regsubcomp(&preg, p, NiL, 0, 0);
+				else if (!(cret = setjmp(state.gotcha)))
+				{
+					alarm(HUNG);
+					cret = regsubcomp(&preg, p, NiL, 0, 0);
+					alarm(0);
+				}
+				if (!cret && *(p += preg.re_npat) && !(preg.re_sub->re_flags & REG_SUB_LAST))
+				{
+					if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
+						continue;
+					cret = REG_EFLAGS;
+				}
+			}
+#endif
+#if _REG_decomp
+			if (!cret && (test & TEST_DECOMP))
+			{
+				char	buf[128];
+
+				if ((j = nmatch) > sizeof(buf))
+					j = sizeof(buf);
+				fun = "regdecomp";
+				p = re + preg.re_npat;
+				if (!(test & TEST_CATCH))
+					i = regdecomp(&preg, -1, buf, j);
+				else if (!(cret = setjmp(state.gotcha)))
+				{
+					alarm(HUNG);
+					i = regdecomp(&preg, -1, buf, j);
+					alarm(0);
+				}
+				if (!cret)
+				{
+					catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+					if (i > j)
+					{
+						if (i != (strlen(ans) + 1))
+						{
+							report("failed", fun, re, s, nstr, msg, flags, test);
+							printf(" %d byte buffer supplied, %d byte buffer required\n", j, i);
+						}
+					}
+					else if (strcmp(buf, ans))
+					{
+						report("failed", fun, re, s, nstr, msg, flags, test);
+						quote(ans, -1, test|TEST_DELIMIT);
+						printf(" expected, ");
+						quote(buf, -1, test|TEST_DELIMIT);
+						printf(" returned\n");
+					}
+					continue;
+				}
+			}
+#endif
+			if (!cret)
+			{
+				if (!(flags & REG_NOSUB) && nsub < 0 && *ans == '(')
+				{
+					for (p = ans; *p; p++)
+						if (*p == '(')
+							nsub++;
+						else if (*p == '{')
+							nsub--;
+					if (nsub >= 0)
+					{
+						if (test & TEST_IGNORE_OVER)
+						{
+							if (nmatch > nsub)
+								nmatch = nsub + 1;
+						}
+						else if (nsub != preg.re_nsub)
+						{
+							if (nsub > preg.re_nsub)
+							{
+								if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+									skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+								else
+								{
+									report("re_nsub incorrect", fun, re, NiL, -1, msg, flags, test);
+									printf("at least %d expected, %d returned\n", nsub, preg.re_nsub);
+									state.errors++;
+								}
+							}
+							else
+								nsub = preg.re_nsub;
+						}
+					}
+				}
+				if (!(test & (TEST_DECOMP|TEST_SUB)) && *ans && *ans != '(' && !streq(ans, "OK") && !streq(ans, "NOMATCH"))
+				{
+					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+						skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+					else if (!(test & TEST_LENIENT))
+					{
+						report("failed", fun, re, NiL, -1, msg, flags, test);
+						printf("%s expected, OK returned\n", ans);
+					}
+					catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+					continue;
+				}
+			}
+			else
+			{
+				if (test & TEST_LENIENT)
+					/* we'll let it go this time */;
+				else if (!*ans || ans[0]=='(' || cret == REG_BADPAT && streq(ans, "NOMATCH"))
+				{
+					got = 0;
+					for (i = 1; i < elementsof(codes); i++)
+						if (cret==codes[i].code)
+							got = i;
+					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+						skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+					else
+					{
+						report("failed", fun, re, NiL, -1, msg, flags, test);
+						printf("%s returned: ", codes[got].name);
+						error(&preg, cret);
+					}
+				}
+				else
+				{
+					expected = got = 0;
+					for (i = 1; i < elementsof(codes); i++)
+					{
+						if (streq(ans, codes[i].name))
+							expected = i;
+						if (cret==codes[i].code)
+							got = i;
+					}
+					if (!expected)
+					{
+						if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+							skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+						else
+						{
+							report("failed: invalid error code", NiL, re, NiL, -1, msg, flags, test);
+							printf("%s expected, %s returned\n", ans, codes[got].name);
+						}
+					}
+					else if (cret != codes[expected].code && cret != REG_BADPAT)
+					{
+						if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+							skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+						else if (test & TEST_IGNORE_ERROR)
+							state.ignored++;
+						else
+						{
+							report("should fail and did", fun, re, NiL, -1, msg, flags, test);
+							printf("%s expected, %s returned: ", ans, codes[got].name);
+							state.errors--;
+							state.warnings++;
+							error(&preg, cret);
+						}
+					}
+				}
+				goto compile;
+			}
+
+#if _REG_nexec
+		execute:
+			if (nexec >= 0)
+				fun = "regnexec";
+			else
+#endif
+				fun = "regexec";
+			
+			for (i = 0; i < elementsof(match); i++)
+				match[i] = state.NOMATCH;
+
+#if _REG_nexec
+			if (nexec >= 0)
+			{
+				eret = regnexec(&preg, s, nexec, nmatch, match, eflags);
+				s[nexec] = 0;
+			}
+			else
+#endif
+			{
+				if (!(test & TEST_CATCH))
+					eret = regexec(&preg, s, nmatch, match, eflags);
+				else if (!(eret = setjmp(state.gotcha)))
+				{
+					alarm(HUNG);
+					eret = regexec(&preg, s, nmatch, match, eflags);
+					alarm(0);
+				}
+			}
+#if _REG_subcomp
+			if ((test & TEST_SUB) && !eret)
+			{
+				fun = "regsubexec";
+				if (!(test & TEST_CATCH))
+					eret = regsubexec(&preg, s, nmatch, match);
+				else if (!(eret = setjmp(state.gotcha)))
+				{
+					alarm(HUNG);
+					eret = regsubexec(&preg, s, nmatch, match);
+					alarm(0);
+				}
+			}
+#endif
+			if (flags & REG_NOSUB)
+			{
+				if (eret)
+				{
+					if (eret != REG_NOMATCH || !streq(ans, "NOMATCH"))
+					{
+						if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+							skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+						else
+						{
+							report("REG_NOSUB failed", fun, re, s, nstr, msg, flags, test);
+							error(&preg, eret);
+						}
+					}
+				}
+				else if (streq(ans, "NOMATCH"))
+				{
+					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+						skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
+					else
+					{
+						report("should fail and didn't", fun, re, s, nstr, msg, flags, test);
+						error(&preg, eret);
+					}
+				}
+			}
+			else if (eret)
+			{
+				if (eret != REG_NOMATCH || !streq(ans, "NOMATCH"))
+				{
+					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+						skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, nsub, skip, level, test|TEST_DELIMIT);
+					else
+					{
+						report("failed", fun, re, s, nstr, msg, flags, test);
+						if (eret != REG_NOMATCH)
+							error(&preg, eret);
+						else if (*ans)
+							printf("expected: %s\n", ans);
+						else
+							printf("\n");
+					}
+				}
+			}
+			else if (streq(ans, "NOMATCH"))
+			{
+				if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+					skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
+				else
+				{
+					report("should fail and didn't", fun, re, s, nstr, msg, flags, test);
+					matchprint(match, nmatch, nsub, NiL, test);
+				}
+			}
+#if _REG_subcomp
+			else if (test & TEST_SUB)
+			{
+				p = preg.re_sub->re_buf;
+				if (strcmp(p, ans))
+				{
+					report("failed", fun, re, s, nstr, msg, flags, test);
+					quote(ans, -1, test|TEST_DELIMIT);
+					printf(" expected, ");
+					quote(p, -1, test|TEST_DELIMIT);
+					printf(" returned\n");
+				}
+			}
+#endif
+			else if (!*ans)
+			{
+				if (match[0].rm_so != state.NOMATCH.rm_so)
+				{
+					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+						skip = extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+					else
+					{
+						report("failed: no match but match array assigned", NiL, re, s, nstr, msg, flags, test);
+						matchprint(match, nmatch, nsub, NiL, test);
+					}
+				}
+			}
+			else if (matchcheck(match, nmatch, nsub, ans, re, s, nstr, flags, test))
+			{
+#if _REG_nexec
+				if (nexec < 0 && !nonexec)
+				{
+					nexec = nstr >= 0 ? nstr : strlen(s);
+					s[nexec] = '\n';
+					testno++;
+					goto execute;
+				}
+#endif
+				if (!(test & (TEST_DECOMP|TEST_SUB|TEST_VERIFY)) && !nonosub)
+				{
+					if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
+						continue;
+					flags |= REG_NOSUB;
+					goto nosub;
+				}
+				if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY))
+					skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_OK);
+			}
+			else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+				skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
+			if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
+				continue;
+			goto compile;
+		}
+		if (test & TEST_SUMMARY)
+			printf("tests=%-4d errors=%-4d warnings=%-2d ignored=%-2d unspecified=%-2d signals=%d\n", testno, state.errors, state.warnings, state.ignored, state.unspecified, state.signals);
+		else if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS)))
+		{
+			printf("TEST\t%s", unit);
+			if (subunit)
+				printf(" %-.*s", subunitlen, subunit);
+			printf(", %d test%s", testno, testno == 1 ? "" : "s");
+			if (state.ignored)
+				printf(", %d ignored mismatche%s", state.ignored, state.ignored == 1 ? "" : "s");
+			if (state.warnings)
+				printf(", %d warning%s", state.warnings, state.warnings == 1 ? "" : "s");
+			if (state.unspecified)
+				printf(", %d unspecified difference%s", state.unspecified, state.unspecified == 1 ? "" : "s");
+			if (state.signals)
+				printf(", %d signal%s", state.signals, state.signals == 1 ? "" : "s");
+			printf(", %d error%s\n", state.errors, state.errors == 1 ? "" : "s");
+		}
+		if (fp != stdin)
+			fclose(fp);
+	}
+	return 0;
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/append_test.go b/third_party/gofrontend/libgo/go/runtime/append_test.go
new file mode 100644
index 0000000..a67dc9b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/append_test.go
@@ -0,0 +1,190 @@
+// 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.
+package runtime_test
+
+import "testing"
+
+const N = 20
+
+func BenchmarkAppend(b *testing.B) {
+	b.StopTimer()
+	x := make([]int, 0, N)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		x = x[0:0]
+		for j := 0; j < N; j++ {
+			x = append(x, j)
+		}
+	}
+}
+
+func BenchmarkAppendGrowByte(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		var x []byte
+		for j := 0; j < 1<<20; j++ {
+			x = append(x, byte(j))
+		}
+	}
+}
+
+func BenchmarkAppendGrowString(b *testing.B) {
+	var s string
+	for i := 0; i < b.N; i++ {
+		var x []string
+		for j := 0; j < 1<<20; j++ {
+			x = append(x, s)
+		}
+	}
+}
+
+func benchmarkAppendBytes(b *testing.B, length int) {
+	b.StopTimer()
+	x := make([]byte, 0, N)
+	y := make([]byte, length)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		x = x[0:0]
+		x = append(x, y...)
+	}
+}
+
+func BenchmarkAppend1Byte(b *testing.B) {
+	benchmarkAppendBytes(b, 1)
+}
+
+func BenchmarkAppend4Bytes(b *testing.B) {
+	benchmarkAppendBytes(b, 4)
+}
+
+func BenchmarkAppend7Bytes(b *testing.B) {
+	benchmarkAppendBytes(b, 7)
+}
+
+func BenchmarkAppend8Bytes(b *testing.B) {
+	benchmarkAppendBytes(b, 8)
+}
+
+func BenchmarkAppend15Bytes(b *testing.B) {
+	benchmarkAppendBytes(b, 15)
+}
+
+func BenchmarkAppend16Bytes(b *testing.B) {
+	benchmarkAppendBytes(b, 16)
+}
+
+func BenchmarkAppend32Bytes(b *testing.B) {
+	benchmarkAppendBytes(b, 32)
+}
+
+func benchmarkAppendStr(b *testing.B, str string) {
+	b.StopTimer()
+	x := make([]byte, 0, N)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		x = x[0:0]
+		x = append(x, str...)
+	}
+}
+
+func BenchmarkAppendStr1Byte(b *testing.B) {
+	benchmarkAppendStr(b, "1")
+}
+
+func BenchmarkAppendStr4Bytes(b *testing.B) {
+	benchmarkAppendStr(b, "1234")
+}
+
+func BenchmarkAppendStr8Bytes(b *testing.B) {
+	benchmarkAppendStr(b, "12345678")
+}
+
+func BenchmarkAppendStr16Bytes(b *testing.B) {
+	benchmarkAppendStr(b, "1234567890123456")
+}
+
+func BenchmarkAppendStr32Bytes(b *testing.B) {
+	benchmarkAppendStr(b, "12345678901234567890123456789012")
+}
+
+func BenchmarkAppendSpecialCase(b *testing.B) {
+	b.StopTimer()
+	x := make([]int, 0, N)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		x = x[0:0]
+		for j := 0; j < N; j++ {
+			if len(x) < cap(x) {
+				x = x[:len(x)+1]
+				x[len(x)-1] = j
+			} else {
+				x = append(x, j)
+			}
+		}
+	}
+}
+
+var x []int
+
+func f() int {
+	x[:1][0] = 3
+	return 2
+}
+
+func TestSideEffectOrder(t *testing.T) {
+	x = make([]int, 0, 10)
+	x = append(x, 1, f())
+	if x[0] != 1 || x[1] != 2 {
+		t.Error("append failed: ", x[0], x[1])
+	}
+}
+
+func TestAppendOverlap(t *testing.T) {
+	x := []byte("1234")
+	x = append(x[1:], x...) // p > q in runtime·appendslice.
+	got := string(x)
+	want := "2341234"
+	if got != want {
+		t.Errorf("overlap failed: got %q want %q", got, want)
+	}
+}
+
+func benchmarkCopySlice(b *testing.B, l int) {
+	s := make([]byte, l)
+	buf := make([]byte, 4096)
+	var n int
+	for i := 0; i < b.N; i++ {
+		n = copy(buf, s)
+	}
+	b.SetBytes(int64(n))
+}
+
+func benchmarkCopyStr(b *testing.B, l int) {
+	s := string(make([]byte, l))
+	buf := make([]byte, 4096)
+	var n int
+	for i := 0; i < b.N; i++ {
+		n = copy(buf, s)
+	}
+	b.SetBytes(int64(n))
+}
+
+func BenchmarkCopy1Byte(b *testing.B)    { benchmarkCopySlice(b, 1) }
+func BenchmarkCopy2Byte(b *testing.B)    { benchmarkCopySlice(b, 2) }
+func BenchmarkCopy4Byte(b *testing.B)    { benchmarkCopySlice(b, 4) }
+func BenchmarkCopy8Byte(b *testing.B)    { benchmarkCopySlice(b, 8) }
+func BenchmarkCopy12Byte(b *testing.B)   { benchmarkCopySlice(b, 12) }
+func BenchmarkCopy16Byte(b *testing.B)   { benchmarkCopySlice(b, 16) }
+func BenchmarkCopy32Byte(b *testing.B)   { benchmarkCopySlice(b, 32) }
+func BenchmarkCopy128Byte(b *testing.B)  { benchmarkCopySlice(b, 128) }
+func BenchmarkCopy1024Byte(b *testing.B) { benchmarkCopySlice(b, 1024) }
+
+func BenchmarkCopy1String(b *testing.B)    { benchmarkCopyStr(b, 1) }
+func BenchmarkCopy2String(b *testing.B)    { benchmarkCopyStr(b, 2) }
+func BenchmarkCopy4String(b *testing.B)    { benchmarkCopyStr(b, 4) }
+func BenchmarkCopy8String(b *testing.B)    { benchmarkCopyStr(b, 8) }
+func BenchmarkCopy12String(b *testing.B)   { benchmarkCopyStr(b, 12) }
+func BenchmarkCopy16String(b *testing.B)   { benchmarkCopyStr(b, 16) }
+func BenchmarkCopy32String(b *testing.B)   { benchmarkCopyStr(b, 32) }
+func BenchmarkCopy128String(b *testing.B)  { benchmarkCopyStr(b, 128) }
+func BenchmarkCopy1024String(b *testing.B) { benchmarkCopyStr(b, 1024) }
diff --git a/third_party/gofrontend/libgo/go/runtime/chan_test.go b/third_party/gofrontend/libgo/go/runtime/chan_test.go
new file mode 100644
index 0000000..ce4b396
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/chan_test.go
@@ -0,0 +1,711 @@
+// 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 runtime_test
+
+import (
+	"runtime"
+	"sync"
+	"sync/atomic"
+	"testing"
+	"time"
+)
+
+func TestChan(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	N := 200
+	if testing.Short() {
+		N = 20
+	}
+	for chanCap := 0; chanCap < N; chanCap++ {
+		{
+			// Ensure that receive from empty chan blocks.
+			c := make(chan int, chanCap)
+			recv1 := false
+			go func() {
+				_ = <-c
+				recv1 = true
+			}()
+			recv2 := false
+			go func() {
+				_, _ = <-c
+				recv2 = true
+			}()
+			time.Sleep(time.Millisecond)
+			if recv1 || recv2 {
+				t.Fatalf("chan[%d]: receive from empty chan", chanCap)
+			}
+			// Ensure that non-blocking receive does not block.
+			select {
+			case _ = <-c:
+				t.Fatalf("chan[%d]: receive from empty chan", chanCap)
+			default:
+			}
+			select {
+			case _, _ = <-c:
+				t.Fatalf("chan[%d]: receive from empty chan", chanCap)
+			default:
+			}
+			c <- 0
+			c <- 0
+		}
+
+		{
+			// Ensure that send to full chan blocks.
+			c := make(chan int, chanCap)
+			for i := 0; i < chanCap; i++ {
+				c <- i
+			}
+			sent := uint32(0)
+			go func() {
+				c <- 0
+				atomic.StoreUint32(&sent, 1)
+			}()
+			time.Sleep(time.Millisecond)
+			if atomic.LoadUint32(&sent) != 0 {
+				t.Fatalf("chan[%d]: send to full chan", chanCap)
+			}
+			// Ensure that non-blocking send does not block.
+			select {
+			case c <- 0:
+				t.Fatalf("chan[%d]: send to full chan", chanCap)
+			default:
+			}
+			<-c
+		}
+
+		{
+			// Ensure that we receive 0 from closed chan.
+			c := make(chan int, chanCap)
+			for i := 0; i < chanCap; i++ {
+				c <- i
+			}
+			close(c)
+			for i := 0; i < chanCap; i++ {
+				v := <-c
+				if v != i {
+					t.Fatalf("chan[%d]: received %v, expected %v", chanCap, v, i)
+				}
+			}
+			if v := <-c; v != 0 {
+				t.Fatalf("chan[%d]: received %v, expected %v", chanCap, v, 0)
+			}
+			if v, ok := <-c; v != 0 || ok {
+				t.Fatalf("chan[%d]: received %v/%v, expected %v/%v", chanCap, v, ok, 0, false)
+			}
+		}
+
+		{
+			// Ensure that close unblocks receive.
+			c := make(chan int, chanCap)
+			done := make(chan bool)
+			go func() {
+				v, ok := <-c
+				done <- v == 0 && ok == false
+			}()
+			time.Sleep(time.Millisecond)
+			close(c)
+			if !<-done {
+				t.Fatalf("chan[%d]: received non zero from closed chan", chanCap)
+			}
+		}
+
+		{
+			// Send 100 integers,
+			// ensure that we receive them non-corrupted in FIFO order.
+			c := make(chan int, chanCap)
+			go func() {
+				for i := 0; i < 100; i++ {
+					c <- i
+				}
+			}()
+			for i := 0; i < 100; i++ {
+				v := <-c
+				if v != i {
+					t.Fatalf("chan[%d]: received %v, expected %v", chanCap, v, i)
+				}
+			}
+
+			// Same, but using recv2.
+			go func() {
+				for i := 0; i < 100; i++ {
+					c <- i
+				}
+			}()
+			for i := 0; i < 100; i++ {
+				v, ok := <-c
+				if !ok {
+					t.Fatalf("chan[%d]: receive failed, expected %v", chanCap, i)
+				}
+				if v != i {
+					t.Fatalf("chan[%d]: received %v, expected %v", chanCap, v, i)
+				}
+			}
+
+			// Send 1000 integers in 4 goroutines,
+			// ensure that we receive what we send.
+			const P = 4
+			const L = 1000
+			for p := 0; p < P; p++ {
+				go func() {
+					for i := 0; i < L; i++ {
+						c <- i
+					}
+				}()
+			}
+			done := make(chan map[int]int)
+			for p := 0; p < P; p++ {
+				go func() {
+					recv := make(map[int]int)
+					for i := 0; i < L; i++ {
+						v := <-c
+						recv[v] = recv[v] + 1
+					}
+					done <- recv
+				}()
+			}
+			recv := make(map[int]int)
+			for p := 0; p < P; p++ {
+				for k, v := range <-done {
+					recv[k] = recv[k] + v
+				}
+			}
+			if len(recv) != L {
+				t.Fatalf("chan[%d]: received %v values, expected %v", chanCap, len(recv), L)
+			}
+			for _, v := range recv {
+				if v != P {
+					t.Fatalf("chan[%d]: received %v values, expected %v", chanCap, v, P)
+				}
+			}
+		}
+
+		{
+			// Test len/cap.
+			c := make(chan int, chanCap)
+			if len(c) != 0 || cap(c) != chanCap {
+				t.Fatalf("chan[%d]: bad len/cap, expect %v/%v, got %v/%v", chanCap, 0, chanCap, len(c), cap(c))
+			}
+			for i := 0; i < chanCap; i++ {
+				c <- i
+			}
+			if len(c) != chanCap || cap(c) != chanCap {
+				t.Fatalf("chan[%d]: bad len/cap, expect %v/%v, got %v/%v", chanCap, chanCap, chanCap, len(c), cap(c))
+			}
+		}
+
+	}
+}
+
+func TestSelfSelect(t *testing.T) {
+	// Ensure that send/recv on the same chan in select
+	// does not crash nor deadlock.
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+	for _, chanCap := range []int{0, 10} {
+		var wg sync.WaitGroup
+		wg.Add(2)
+		c := make(chan int, chanCap)
+		for p := 0; p < 2; p++ {
+			p := p
+			go func() {
+				defer wg.Done()
+				for i := 0; i < 1000; i++ {
+					if p == 0 || i%2 == 0 {
+						select {
+						case c <- p:
+						case v := <-c:
+							if chanCap == 0 && v == p {
+								t.Fatalf("self receive")
+							}
+						}
+					} else {
+						select {
+						case v := <-c:
+							if chanCap == 0 && v == p {
+								t.Fatalf("self receive")
+							}
+						case c <- p:
+						}
+					}
+				}
+			}()
+		}
+		wg.Wait()
+	}
+}
+
+func TestSelectStress(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(10))
+	var c [4]chan int
+	c[0] = make(chan int)
+	c[1] = make(chan int)
+	c[2] = make(chan int, 2)
+	c[3] = make(chan int, 3)
+	N := int(1e5)
+	if testing.Short() {
+		N /= 10
+	}
+	// There are 4 goroutines that send N values on each of the chans,
+	// + 4 goroutines that receive N values on each of the chans,
+	// + 1 goroutine that sends N values on each of the chans in a single select,
+	// + 1 goroutine that receives N values on each of the chans in a single select.
+	// All these sends, receives and selects interact chaotically at runtime,
+	// but we are careful that this whole construct does not deadlock.
+	var wg sync.WaitGroup
+	wg.Add(10)
+	for k := 0; k < 4; k++ {
+		k := k
+		go func() {
+			for i := 0; i < N; i++ {
+				c[k] <- 0
+			}
+			wg.Done()
+		}()
+		go func() {
+			for i := 0; i < N; i++ {
+				<-c[k]
+			}
+			wg.Done()
+		}()
+	}
+	go func() {
+		var n [4]int
+		c1 := c
+		for i := 0; i < 4*N; i++ {
+			select {
+			case c1[3] <- 0:
+				n[3]++
+				if n[3] == N {
+					c1[3] = nil
+				}
+			case c1[2] <- 0:
+				n[2]++
+				if n[2] == N {
+					c1[2] = nil
+				}
+			case c1[0] <- 0:
+				n[0]++
+				if n[0] == N {
+					c1[0] = nil
+				}
+			case c1[1] <- 0:
+				n[1]++
+				if n[1] == N {
+					c1[1] = nil
+				}
+			}
+		}
+		wg.Done()
+	}()
+	go func() {
+		var n [4]int
+		c1 := c
+		for i := 0; i < 4*N; i++ {
+			select {
+			case <-c1[0]:
+				n[0]++
+				if n[0] == N {
+					c1[0] = nil
+				}
+			case <-c1[1]:
+				n[1]++
+				if n[1] == N {
+					c1[1] = nil
+				}
+			case <-c1[2]:
+				n[2]++
+				if n[2] == N {
+					c1[2] = nil
+				}
+			case <-c1[3]:
+				n[3]++
+				if n[3] == N {
+					c1[3] = nil
+				}
+			}
+		}
+		wg.Done()
+	}()
+	wg.Wait()
+}
+
+func TestChanSendInterface(t *testing.T) {
+	type mt struct{}
+	m := &mt{}
+	c := make(chan interface{}, 1)
+	c <- m
+	select {
+	case c <- m:
+	default:
+	}
+	select {
+	case c <- m:
+	case c <- &mt{}:
+	default:
+	}
+}
+
+func TestPseudoRandomSend(t *testing.T) {
+	n := 100
+	for _, chanCap := range []int{0, n} {
+		c := make(chan int, chanCap)
+		l := make([]int, n)
+		var m sync.Mutex
+		m.Lock()
+		go func() {
+			for i := 0; i < n; i++ {
+				runtime.Gosched()
+				l[i] = <-c
+			}
+			m.Unlock()
+		}()
+		for i := 0; i < n; i++ {
+			select {
+			case c <- 1:
+			case c <- 0:
+			}
+		}
+		m.Lock() // wait
+		n0 := 0
+		n1 := 0
+		for _, i := range l {
+			n0 += (i + 1) % 2
+			n1 += i
+		}
+		if n0 <= n/10 || n1 <= n/10 {
+			t.Errorf("Want pseudorandom, got %d zeros and %d ones (chan cap %d)", n0, n1, chanCap)
+		}
+	}
+}
+
+func TestMultiConsumer(t *testing.T) {
+	const nwork = 23
+	const niter = 271828
+
+	pn := []int{2, 3, 7, 11, 13, 17, 19, 23, 27, 31}
+
+	q := make(chan int, nwork*3)
+	r := make(chan int, nwork*3)
+
+	// workers
+	var wg sync.WaitGroup
+	for i := 0; i < nwork; i++ {
+		wg.Add(1)
+		go func(w int) {
+			for v := range q {
+				// mess with the fifo-ish nature of range
+				if pn[w%len(pn)] == v {
+					runtime.Gosched()
+				}
+				r <- v
+			}
+			wg.Done()
+		}(i)
+	}
+
+	// feeder & closer
+	expect := 0
+	go func() {
+		for i := 0; i < niter; i++ {
+			v := pn[i%len(pn)]
+			expect += v
+			q <- v
+		}
+		close(q)  // no more work
+		wg.Wait() // workers done
+		close(r)  // ... so there can be no more results
+	}()
+
+	// consume & check
+	n := 0
+	s := 0
+	for v := range r {
+		n++
+		s += v
+	}
+	if n != niter || s != expect {
+		t.Errorf("Expected sum %d (got %d) from %d iter (saw %d)",
+			expect, s, niter, n)
+	}
+}
+
+func BenchmarkChanNonblocking(b *testing.B) {
+	myc := make(chan int)
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			select {
+			case <-myc:
+			default:
+			}
+		}
+	})
+}
+
+func BenchmarkSelectUncontended(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		myc1 := make(chan int, 1)
+		myc2 := make(chan int, 1)
+		myc1 <- 0
+		for pb.Next() {
+			select {
+			case <-myc1:
+				myc2 <- 0
+			case <-myc2:
+				myc1 <- 0
+			}
+		}
+	})
+}
+
+func BenchmarkSelectContended(b *testing.B) {
+	procs := runtime.GOMAXPROCS(0)
+	myc1 := make(chan int, procs)
+	myc2 := make(chan int, procs)
+	b.RunParallel(func(pb *testing.PB) {
+		myc1 <- 0
+		for pb.Next() {
+			select {
+			case <-myc1:
+				myc2 <- 0
+			case <-myc2:
+				myc1 <- 0
+			}
+		}
+	})
+}
+
+func BenchmarkSelectNonblock(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		myc1 := make(chan int)
+		myc2 := make(chan int)
+		myc3 := make(chan int, 1)
+		myc4 := make(chan int, 1)
+		for pb.Next() {
+			select {
+			case <-myc1:
+			default:
+			}
+			select {
+			case myc2 <- 0:
+			default:
+			}
+			select {
+			case <-myc3:
+			default:
+			}
+			select {
+			case myc4 <- 0:
+			default:
+			}
+		}
+	})
+}
+
+func BenchmarkChanUncontended(b *testing.B) {
+	const C = 100
+	b.RunParallel(func(pb *testing.PB) {
+		myc := make(chan int, C)
+		for pb.Next() {
+			for i := 0; i < C; i++ {
+				myc <- 0
+			}
+			for i := 0; i < C; i++ {
+				<-myc
+			}
+		}
+	})
+}
+
+func BenchmarkChanContended(b *testing.B) {
+	const C = 100
+	myc := make(chan int, C*runtime.GOMAXPROCS(0))
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			for i := 0; i < C; i++ {
+				myc <- 0
+			}
+			for i := 0; i < C; i++ {
+				<-myc
+			}
+		}
+	})
+}
+
+func BenchmarkChanSync(b *testing.B) {
+	const CallsPerSched = 1000
+	procs := 2
+	N := int32(b.N / CallsPerSched / procs * procs)
+	c := make(chan bool, procs)
+	myc := make(chan int)
+	for p := 0; p < procs; p++ {
+		go func() {
+			for {
+				i := atomic.AddInt32(&N, -1)
+				if i < 0 {
+					break
+				}
+				for g := 0; g < CallsPerSched; g++ {
+					if i%2 == 0 {
+						<-myc
+						myc <- 0
+					} else {
+						myc <- 0
+						<-myc
+					}
+				}
+			}
+			c <- true
+		}()
+	}
+	for p := 0; p < procs; p++ {
+		<-c
+	}
+}
+
+func benchmarkChanProdCons(b *testing.B, chanSize, localWork int) {
+	const CallsPerSched = 1000
+	procs := runtime.GOMAXPROCS(-1)
+	N := int32(b.N / CallsPerSched)
+	c := make(chan bool, 2*procs)
+	myc := make(chan int, chanSize)
+	for p := 0; p < procs; p++ {
+		go func() {
+			foo := 0
+			for atomic.AddInt32(&N, -1) >= 0 {
+				for g := 0; g < CallsPerSched; g++ {
+					for i := 0; i < localWork; i++ {
+						foo *= 2
+						foo /= 2
+					}
+					myc <- 1
+				}
+			}
+			myc <- 0
+			c <- foo == 42
+		}()
+		go func() {
+			foo := 0
+			for {
+				v := <-myc
+				if v == 0 {
+					break
+				}
+				for i := 0; i < localWork; i++ {
+					foo *= 2
+					foo /= 2
+				}
+			}
+			c <- foo == 42
+		}()
+	}
+	for p := 0; p < procs; p++ {
+		<-c
+		<-c
+	}
+}
+
+func BenchmarkChanProdCons0(b *testing.B) {
+	benchmarkChanProdCons(b, 0, 0)
+}
+
+func BenchmarkChanProdCons10(b *testing.B) {
+	benchmarkChanProdCons(b, 10, 0)
+}
+
+func BenchmarkChanProdCons100(b *testing.B) {
+	benchmarkChanProdCons(b, 100, 0)
+}
+
+func BenchmarkChanProdConsWork0(b *testing.B) {
+	benchmarkChanProdCons(b, 0, 100)
+}
+
+func BenchmarkChanProdConsWork10(b *testing.B) {
+	benchmarkChanProdCons(b, 10, 100)
+}
+
+func BenchmarkChanProdConsWork100(b *testing.B) {
+	benchmarkChanProdCons(b, 100, 100)
+}
+
+func BenchmarkSelectProdCons(b *testing.B) {
+	const CallsPerSched = 1000
+	procs := runtime.GOMAXPROCS(-1)
+	N := int32(b.N / CallsPerSched)
+	c := make(chan bool, 2*procs)
+	myc := make(chan int, 128)
+	myclose := make(chan bool)
+	for p := 0; p < procs; p++ {
+		go func() {
+			// Producer: sends to myc.
+			foo := 0
+			// Intended to not fire during benchmarking.
+			mytimer := time.After(time.Hour)
+			for atomic.AddInt32(&N, -1) >= 0 {
+				for g := 0; g < CallsPerSched; g++ {
+					// Model some local work.
+					for i := 0; i < 100; i++ {
+						foo *= 2
+						foo /= 2
+					}
+					select {
+					case myc <- 1:
+					case <-mytimer:
+					case <-myclose:
+					}
+				}
+			}
+			myc <- 0
+			c <- foo == 42
+		}()
+		go func() {
+			// Consumer: receives from myc.
+			foo := 0
+			// Intended to not fire during benchmarking.
+			mytimer := time.After(time.Hour)
+		loop:
+			for {
+				select {
+				case v := <-myc:
+					if v == 0 {
+						break loop
+					}
+				case <-mytimer:
+				case <-myclose:
+				}
+				// Model some local work.
+				for i := 0; i < 100; i++ {
+					foo *= 2
+					foo /= 2
+				}
+			}
+			c <- foo == 42
+		}()
+	}
+	for p := 0; p < procs; p++ {
+		<-c
+		<-c
+	}
+}
+
+func BenchmarkChanCreation(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			myc := make(chan int, 1)
+			myc <- 0
+			<-myc
+		}
+	})
+}
+
+func BenchmarkChanSem(b *testing.B) {
+	type Empty struct{}
+	myc := make(chan Empty, runtime.GOMAXPROCS(0))
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			myc <- Empty{}
+			<-myc
+		}
+	})
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/closure_test.go b/third_party/gofrontend/libgo/go/runtime/closure_test.go
new file mode 100644
index 0000000..ea65fbd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/closure_test.go
@@ -0,0 +1,53 @@
+// 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.
+package runtime_test
+
+import "testing"
+
+var s int
+
+func BenchmarkCallClosure(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		s += func(ii int) int { return 2 * ii }(i)
+	}
+}
+
+func BenchmarkCallClosure1(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		j := i
+		s += func(ii int) int { return 2*ii + j }(i)
+	}
+}
+
+var ss *int
+
+func BenchmarkCallClosure2(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		j := i
+		s += func() int {
+			ss = &j
+			return 2
+		}()
+	}
+}
+
+func addr1(x int) *int {
+	return func() *int { return &x }()
+}
+
+func BenchmarkCallClosure3(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ss = addr1(i)
+	}
+}
+
+func addr2() (x int, p *int) {
+	return 0, func() *int { return &x }()
+}
+
+func BenchmarkCallClosure4(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_, ss = addr2()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/compiler.go b/third_party/gofrontend/libgo/go/runtime/compiler.go
new file mode 100644
index 0000000..0ed3b18
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/compiler.go
@@ -0,0 +1,13 @@
+// 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 runtime
+
+// Compiler is the name of the compiler toolchain that built the
+// running binary.  Known toolchains are:
+//
+//	gc      The 5g/6g/8g compiler suite at code.google.com/p/go.
+//	gccgo   The gccgo front end, part of the GCC compiler suite.
+//
+const Compiler = "gccgo"
diff --git a/third_party/gofrontend/libgo/go/runtime/complex_test.go b/third_party/gofrontend/libgo/go/runtime/complex_test.go
new file mode 100644
index 0000000..f41e6a3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/complex_test.go
@@ -0,0 +1,67 @@
+// 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 runtime_test
+
+import (
+	"math/cmplx"
+	"testing"
+)
+
+var result complex128
+
+func BenchmarkComplex128DivNormal(b *testing.B) {
+	d := 15 + 2i
+	n := 32 + 3i
+	res := 0i
+	for i := 0; i < b.N; i++ {
+		n += 0.1i
+		res += n / d
+	}
+	result = res
+}
+
+func BenchmarkComplex128DivNisNaN(b *testing.B) {
+	d := cmplx.NaN()
+	n := 32 + 3i
+	res := 0i
+	for i := 0; i < b.N; i++ {
+		n += 0.1i
+		res += n / d
+	}
+	result = res
+}
+
+func BenchmarkComplex128DivDisNaN(b *testing.B) {
+	d := 15 + 2i
+	n := cmplx.NaN()
+	res := 0i
+	for i := 0; i < b.N; i++ {
+		d += 0.1i
+		res += n / d
+	}
+	result = res
+}
+
+func BenchmarkComplex128DivNisInf(b *testing.B) {
+	d := 15 + 2i
+	n := cmplx.Inf()
+	res := 0i
+	for i := 0; i < b.N; i++ {
+		d += 0.1i
+		res += n / d
+	}
+	result = res
+}
+
+func BenchmarkComplex128DivDisInf(b *testing.B) {
+	d := cmplx.Inf()
+	n := 32 + 3i
+	res := 0i
+	for i := 0; i < b.N; i++ {
+		n += 0.1i
+		res += n / d
+	}
+	result = res
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/crash_cgo_test.go b/third_party/gofrontend/libgo/go/runtime/crash_cgo_test.go
new file mode 100644
index 0000000..b534b89
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/crash_cgo_test.go
@@ -0,0 +1,120 @@
+// 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.
+
+// +build cgo
+
+package runtime_test
+
+import (
+	"runtime"
+	"testing"
+)
+
+func TestCgoCrashHandler(t *testing.T) {
+	testCrashHandler(t, true)
+}
+
+func TestCgoSignalDeadlock(t *testing.T) {
+	if testing.Short() && runtime.GOOS == "windows" {
+		t.Skip("Skipping in short mode") // takes up to 64 seconds
+	}
+	t.Skip("gccgo does not have a go command")
+	got := executeTest(t, cgoSignalDeadlockSource, nil)
+	want := "OK\n"
+	if got != want {
+		t.Fatalf("expected %q, but got %q", want, got)
+	}
+}
+
+func TestCgoTraceback(t *testing.T) {
+	got := executeTest(t, cgoTracebackSource, nil)
+	want := "OK\n"
+	if got != want {
+		t.Fatalf("expected %q, but got %q", want, got)
+	}
+}
+
+const cgoSignalDeadlockSource = `
+package main
+
+import "C"
+
+import (
+	"fmt"
+	"runtime"
+	"time"
+)
+
+func main() {
+	runtime.GOMAXPROCS(100)
+	ping := make(chan bool)
+	go func() {
+		for i := 0; ; i++ {
+			runtime.Gosched()
+			select {
+			case done := <-ping:
+				if done {
+					ping <- true
+					return
+				}
+				ping <- true
+			default:
+			}
+			func() {
+				defer func() {
+					recover()
+				}()
+				var s *string
+				*s = ""
+			}()
+		}
+	}()
+	time.Sleep(time.Millisecond)
+	for i := 0; i < 64; i++ {
+		go func() {
+			runtime.LockOSThread()
+			select {}
+		}()
+		go func() {
+			runtime.LockOSThread()
+			select {}
+		}()
+		time.Sleep(time.Millisecond)
+		ping <- false
+		select {
+		case <-ping:
+		case <-time.After(time.Second):
+			fmt.Printf("HANG\n")
+			return
+		}
+	}
+	ping <- true
+	select {
+	case <-ping:
+	case <-time.After(time.Second):
+		fmt.Printf("HANG\n")
+		return
+	}
+	fmt.Printf("OK\n")
+}
+`
+
+const cgoTracebackSource = `
+package main
+
+/* void foo(void) {} */
+import "C"
+
+import (
+	"fmt"
+	"runtime"
+)
+
+func main() {
+	C.foo()
+	buf := make([]byte, 1)
+	runtime.Stack(buf, true)
+	fmt.Printf("OK\n")
+}
+`
diff --git a/third_party/gofrontend/libgo/go/runtime/crash_test.go b/third_party/gofrontend/libgo/go/runtime/crash_test.go
new file mode 100644
index 0000000..39e0434
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/crash_test.go
@@ -0,0 +1,367 @@
+// 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 runtime_test
+
+import (
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"text/template"
+)
+
+// testEnv excludes GODEBUG from the environment
+// to prevent its output from breaking tests that
+// are trying to parse other command output.
+func testEnv(cmd *exec.Cmd) *exec.Cmd {
+	if cmd.Env != nil {
+		panic("environment already set")
+	}
+	for _, env := range os.Environ() {
+		if strings.HasPrefix(env, "GODEBUG=") {
+			continue
+		}
+		cmd.Env = append(cmd.Env, env)
+	}
+	return cmd
+}
+
+func executeTest(t *testing.T, templ string, data interface{}) string {
+	t.Skip("gccgo does not have a go command")
+	if runtime.GOOS == "nacl" {
+		t.Skip("skipping on nacl")
+	}
+
+	checkStaleRuntime(t)
+
+	st := template.Must(template.New("crashSource").Parse(templ))
+
+	dir, err := ioutil.TempDir("", "go-build")
+	if err != nil {
+		t.Fatalf("failed to create temp directory: %v", err)
+	}
+	defer os.RemoveAll(dir)
+
+	src := filepath.Join(dir, "main.go")
+	f, err := os.Create(src)
+	if err != nil {
+		t.Fatalf("failed to create file: %v", err)
+	}
+	err = st.Execute(f, data)
+	if err != nil {
+		f.Close()
+		t.Fatalf("failed to execute template: %v", err)
+	}
+	if err := f.Close(); err != nil {
+		t.Fatalf("failed to close file: %v", err)
+	}
+
+	got, _ := testEnv(exec.Command("go", "run", src)).CombinedOutput()
+	return string(got)
+}
+
+func checkStaleRuntime(t *testing.T) {
+	// 'go run' uses the installed copy of runtime.a, which may be out of date.
+	out, err := testEnv(exec.Command("go", "list", "-f", "{{.Stale}}", "runtime")).CombinedOutput()
+	if err != nil {
+		t.Fatalf("failed to execute 'go list': %v\n%v", err, string(out))
+	}
+	if string(out) != "false\n" {
+		t.Fatalf("Stale runtime.a. Run 'go install runtime'.")
+	}
+}
+
+func testCrashHandler(t *testing.T, cgo bool) {
+	type crashTest struct {
+		Cgo bool
+	}
+	output := executeTest(t, crashSource, &crashTest{Cgo: cgo})
+	want := "main: recovered done\nnew-thread: recovered done\nsecond-new-thread: recovered done\nmain-again: recovered done\n"
+	if output != want {
+		t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want)
+	}
+}
+
+func TestCrashHandler(t *testing.T) {
+	testCrashHandler(t, false)
+}
+
+func testDeadlock(t *testing.T, source string) {
+	output := executeTest(t, source, nil)
+	want := "fatal error: all goroutines are asleep - deadlock!\n"
+	if !strings.HasPrefix(output, want) {
+		t.Fatalf("output does not start with %q:\n%s", want, output)
+	}
+}
+
+func TestSimpleDeadlock(t *testing.T) {
+	testDeadlock(t, simpleDeadlockSource)
+}
+
+func TestInitDeadlock(t *testing.T) {
+	testDeadlock(t, initDeadlockSource)
+}
+
+func TestLockedDeadlock(t *testing.T) {
+	testDeadlock(t, lockedDeadlockSource)
+}
+
+func TestLockedDeadlock2(t *testing.T) {
+	testDeadlock(t, lockedDeadlockSource2)
+}
+
+func TestGoexitDeadlock(t *testing.T) {
+	output := executeTest(t, goexitDeadlockSource, nil)
+	want := "no goroutines (main called runtime.Goexit) - deadlock!"
+	if !strings.Contains(output, want) {
+		t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
+	}
+}
+
+func TestStackOverflow(t *testing.T) {
+	output := executeTest(t, stackOverflowSource, nil)
+	want := "runtime: goroutine stack exceeds 4194304-byte limit\nfatal error: stack overflow"
+	if !strings.HasPrefix(output, want) {
+		t.Fatalf("output does not start with %q:\n%s", want, output)
+	}
+}
+
+func TestThreadExhaustion(t *testing.T) {
+	output := executeTest(t, threadExhaustionSource, nil)
+	want := "runtime: program exceeds 10-thread limit\nfatal error: thread exhaustion"
+	if !strings.HasPrefix(output, want) {
+		t.Fatalf("output does not start with %q:\n%s", want, output)
+	}
+}
+
+func TestRecursivePanic(t *testing.T) {
+	output := executeTest(t, recursivePanicSource, nil)
+	want := `wrap: bad
+panic: again
+
+`
+	if !strings.HasPrefix(output, want) {
+		t.Fatalf("output does not start with %q:\n%s", want, output)
+	}
+
+}
+
+func TestGoexitCrash(t *testing.T) {
+	output := executeTest(t, goexitExitSource, nil)
+	want := "no goroutines (main called runtime.Goexit) - deadlock!"
+	if !strings.Contains(output, want) {
+		t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
+	}
+}
+
+func TestGoNil(t *testing.T) {
+	output := executeTest(t, goNilSource, nil)
+	want := "go of nil func value"
+	if !strings.Contains(output, want) {
+		t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
+	}
+}
+
+const crashSource = `
+package main
+
+import (
+	"fmt"
+	"runtime"
+)
+
+{{if .Cgo}}
+import "C"
+{{end}}
+
+func test(name string) {
+	defer func() {
+		if x := recover(); x != nil {
+			fmt.Printf(" recovered")
+		}
+		fmt.Printf(" done\n")
+	}()
+	fmt.Printf("%s:", name)
+	var s *string
+	_ = *s
+	fmt.Print("SHOULD NOT BE HERE")
+}
+
+func testInNewThread(name string) {
+	c := make(chan bool)
+	go func() {
+		runtime.LockOSThread()
+		test(name)
+		c <- true
+	}()
+	<-c
+}
+
+func main() {
+	runtime.LockOSThread()
+	test("main")
+	testInNewThread("new-thread")
+	testInNewThread("second-new-thread")
+	test("main-again")
+}
+`
+
+const simpleDeadlockSource = `
+package main
+func main() {
+	select {}
+}
+`
+
+const initDeadlockSource = `
+package main
+func init() {
+	select {}
+}
+func main() {
+}
+`
+
+const lockedDeadlockSource = `
+package main
+import "runtime"
+func main() {
+	runtime.LockOSThread()
+	select {}
+}
+`
+
+const lockedDeadlockSource2 = `
+package main
+import (
+	"runtime"
+	"time"
+)
+func main() {
+	go func() {
+		runtime.LockOSThread()
+		select {}
+	}()
+	time.Sleep(time.Millisecond)
+	select {}
+}
+`
+
+const goexitDeadlockSource = `
+package main
+import (
+      "runtime"
+)
+
+func F() {
+      for i := 0; i < 10; i++ {
+      }
+}
+
+func main() {
+      go F()
+      go F()
+      runtime.Goexit()
+}
+`
+
+const stackOverflowSource = `
+package main
+
+import "runtime/debug"
+
+func main() {
+	debug.SetMaxStack(4<<20)
+	f(make([]byte, 10))
+}
+
+func f(x []byte) byte {
+	var buf [64<<10]byte
+	return x[0] + f(buf[:])
+}
+`
+
+const threadExhaustionSource = `
+package main
+
+import (
+	"runtime"
+	"runtime/debug"
+)
+
+func main() {
+	debug.SetMaxThreads(10)
+	c := make(chan int)
+	for i := 0; i < 100; i++ {
+		go func() {
+			runtime.LockOSThread()
+			c <- 0
+			select{}
+		}()
+		<-c
+	}
+}
+`
+
+const recursivePanicSource = `
+package main
+
+import (
+	"fmt"
+)
+
+func main() {
+	func() {
+		defer func() {
+			fmt.Println(recover())
+		}()
+		var x [8192]byte
+		func(x [8192]byte) {
+			defer func() {
+				if err := recover(); err != nil {
+					panic("wrap: " + err.(string))
+				}
+			}()
+			panic("bad")
+		}(x)
+	}()
+	panic("again")
+}
+`
+
+const goexitExitSource = `
+package main
+
+import (
+	"runtime"
+	"time"
+)
+
+func main() {
+	go func() {
+		time.Sleep(time.Millisecond)
+	}()
+	i := 0
+	runtime.SetFinalizer(&i, func(p *int) {})
+	runtime.GC()
+	runtime.Goexit()
+}
+`
+
+const goNilSource = `
+package main
+
+func main() {
+	defer func() {
+		recover()
+	}()
+	var f func()
+	go f()
+	select{}
+}
+`
diff --git a/third_party/gofrontend/libgo/go/runtime/debug.go b/third_party/gofrontend/libgo/go/runtime/debug.go
new file mode 100644
index 0000000..bcdde4b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/debug.go
@@ -0,0 +1,179 @@
+// 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 runtime
+
+// Breakpoint executes a breakpoint trap.
+func Breakpoint()
+
+// LockOSThread wires the calling goroutine to its current operating system thread.
+// Until the calling goroutine exits or calls UnlockOSThread, it will always
+// execute in that thread, and no other goroutine can.
+func LockOSThread()
+
+// UnlockOSThread unwires the calling goroutine from its fixed operating system thread.
+// If the calling goroutine has not called LockOSThread, UnlockOSThread is a no-op.
+func UnlockOSThread()
+
+// GOMAXPROCS sets the maximum number of CPUs that can be executing
+// simultaneously and returns the previous setting.  If n < 1, it does not
+// change the current setting.
+// The number of logical CPUs on the local machine can be queried with NumCPU.
+// This call will go away when the scheduler improves.
+func GOMAXPROCS(n int) int
+
+// NumCPU returns the number of logical CPUs on the local machine.
+func NumCPU() int
+
+// NumCgoCall returns the number of cgo calls made by the current process.
+func NumCgoCall() int64
+
+// NumGoroutine returns the number of goroutines that currently exist.
+func NumGoroutine() int
+
+// MemProfileRate controls the fraction of memory allocations
+// that are recorded and reported in the memory profile.
+// The profiler aims to sample an average of
+// one allocation per MemProfileRate bytes allocated.
+//
+// To include every allocated block in the profile, set MemProfileRate to 1.
+// To turn off profiling entirely, set MemProfileRate to 0.
+//
+// The tools that process the memory profiles assume that the
+// profile rate is constant across the lifetime of the program
+// and equal to the current value.  Programs that change the
+// memory profiling rate should do so just once, as early as
+// possible in the execution of the program (for example,
+// at the beginning of main).
+var MemProfileRate int = 512 * 1024
+
+// A MemProfileRecord describes the live objects allocated
+// by a particular call sequence (stack trace).
+type MemProfileRecord struct {
+	AllocBytes, FreeBytes     int64       // number of bytes allocated, freed
+	AllocObjects, FreeObjects int64       // number of objects allocated, freed
+	Stack0                    [32]uintptr // stack trace for this record; ends at first 0 entry
+}
+
+// InUseBytes returns the number of bytes in use (AllocBytes - FreeBytes).
+func (r *MemProfileRecord) InUseBytes() int64 { return r.AllocBytes - r.FreeBytes }
+
+// InUseObjects returns the number of objects in use (AllocObjects - FreeObjects).
+func (r *MemProfileRecord) InUseObjects() int64 {
+	return r.AllocObjects - r.FreeObjects
+}
+
+// Stack returns the stack trace associated with the record,
+// a prefix of r.Stack0.
+func (r *MemProfileRecord) Stack() []uintptr {
+	for i, v := range r.Stack0 {
+		if v == 0 {
+			return r.Stack0[0:i]
+		}
+	}
+	return r.Stack0[0:]
+}
+
+// MemProfile returns n, the number of records in the current memory profile.
+// If len(p) >= n, MemProfile copies the profile into p and returns n, true.
+// If len(p) < n, MemProfile does not change p and returns n, false.
+//
+// If inuseZero is true, the profile includes allocation records
+// where r.AllocBytes > 0 but r.AllocBytes == r.FreeBytes.
+// These are sites where memory was allocated, but it has all
+// been released back to the runtime.
+//
+// Most clients should use the runtime/pprof package or
+// the testing package's -test.memprofile flag instead
+// of calling MemProfile directly.
+func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool)
+
+// A StackRecord describes a single execution stack.
+type StackRecord struct {
+	Stack0 [32]uintptr // stack trace for this record; ends at first 0 entry
+}
+
+// Stack returns the stack trace associated with the record,
+// a prefix of r.Stack0.
+func (r *StackRecord) Stack() []uintptr {
+	for i, v := range r.Stack0 {
+		if v == 0 {
+			return r.Stack0[0:i]
+		}
+	}
+	return r.Stack0[0:]
+}
+
+// ThreadCreateProfile returns n, the number of records in the thread creation profile.
+// If len(p) >= n, ThreadCreateProfile copies the profile into p and returns n, true.
+// If len(p) < n, ThreadCreateProfile does not change p and returns n, false.
+//
+// Most clients should use the runtime/pprof package instead
+// of calling ThreadCreateProfile directly.
+func ThreadCreateProfile(p []StackRecord) (n int, ok bool)
+
+// GoroutineProfile returns n, the number of records in the active goroutine stack profile.
+// If len(p) >= n, GoroutineProfile copies the profile into p and returns n, true.
+// If len(p) < n, GoroutineProfile does not change p and returns n, false.
+//
+// Most clients should use the runtime/pprof package instead
+// of calling GoroutineProfile directly.
+func GoroutineProfile(p []StackRecord) (n int, ok bool)
+
+// CPUProfile returns the next chunk of binary CPU profiling stack trace data,
+// blocking until data is available.  If profiling is turned off and all the profile
+// data accumulated while it was on has been returned, CPUProfile returns nil.
+// The caller must save the returned data before calling CPUProfile again.
+//
+// Most clients should use the runtime/pprof package or
+// the testing package's -test.cpuprofile flag instead of calling
+// CPUProfile directly.
+func CPUProfile() []byte
+
+// SetCPUProfileRate sets the CPU profiling rate to hz samples per second.
+// If hz <= 0, SetCPUProfileRate turns off profiling.
+// If the profiler is on, the rate cannot be changed without first turning it off.
+//
+// Most clients should use the runtime/pprof package or
+// the testing package's -test.cpuprofile flag instead of calling
+// SetCPUProfileRate directly.
+func SetCPUProfileRate(hz int)
+
+// SetBlockProfileRate controls the fraction of goroutine blocking events
+// that are reported in the blocking profile.  The profiler aims to sample
+// an average of one blocking event per rate nanoseconds spent blocked.
+//
+// To include every blocking event in the profile, pass rate = 1.
+// To turn off profiling entirely, pass rate <= 0.
+func SetBlockProfileRate(rate int)
+
+// BlockProfileRecord describes blocking events originated
+// at a particular call sequence (stack trace).
+type BlockProfileRecord struct {
+	Count  int64
+	Cycles int64
+	StackRecord
+}
+
+// BlockProfile returns n, the number of records in the current blocking profile.
+// If len(p) >= n, BlockProfile copies the profile into p and returns n, true.
+// If len(p) < n, BlockProfile does not change p and returns n, false.
+//
+// Most clients should use the runtime/pprof package or
+// the testing package's -test.blockprofile flag instead
+// of calling BlockProfile directly.
+func BlockProfile(p []BlockProfileRecord) (n int, ok bool)
+
+// Stack formats a stack trace of the calling goroutine into buf
+// and returns the number of bytes written to buf.
+// If all is true, Stack formats stack traces of all other goroutines
+// into buf after the trace for the current goroutine.
+func Stack(buf []byte, all bool) int
+
+// Get field tracking information.  Only fields with a tag go:"track"
+// are tracked.  This function will add every such field that is
+// referenced to the map.  The keys in the map will be
+// PkgPath.Name.FieldName.  The value will be true for each field
+// added.
+func Fieldtrack(map[string]bool)
diff --git a/third_party/gofrontend/libgo/go/runtime/debug/garbage.go b/third_party/gofrontend/libgo/go/runtime/debug/garbage.go
new file mode 100644
index 0000000..edb3643
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/debug/garbage.go
@@ -0,0 +1,153 @@
+// Copyright 2013 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 debug
+
+import (
+	"runtime"
+	"sort"
+	"time"
+)
+
+// GCStats collect information about recent garbage collections.
+type GCStats struct {
+	LastGC         time.Time       // time of last collection
+	NumGC          int64           // number of garbage collections
+	PauseTotal     time.Duration   // total pause for all collections
+	Pause          []time.Duration // pause history, most recent first
+	PauseQuantiles []time.Duration
+}
+
+// Implemented in package runtime.
+func readGCStats(*[]time.Duration)
+func enableGC(bool) bool
+func setGCPercent(int) int
+func freeOSMemory()
+func setMaxStack(int) int
+func setMaxThreads(int) int
+
+// ReadGCStats reads statistics about garbage collection into stats.
+// The number of entries in the pause history is system-dependent;
+// stats.Pause slice will be reused if large enough, reallocated otherwise.
+// ReadGCStats may use the full capacity of the stats.Pause slice.
+// If stats.PauseQuantiles is non-empty, ReadGCStats fills it with quantiles
+// summarizing the distribution of pause time. For example, if
+// len(stats.PauseQuantiles) is 5, it will be filled with the minimum,
+// 25%, 50%, 75%, and maximum pause times.
+func ReadGCStats(stats *GCStats) {
+	// Create a buffer with space for at least two copies of the
+	// pause history tracked by the runtime. One will be returned
+	// to the caller and the other will be used as a temporary buffer
+	// for computing quantiles.
+	const maxPause = len(((*runtime.MemStats)(nil)).PauseNs)
+	if cap(stats.Pause) < 2*maxPause {
+		stats.Pause = make([]time.Duration, 2*maxPause)
+	}
+
+	// readGCStats fills in the pause history (up to maxPause entries)
+	// and then three more: Unix ns time of last GC, number of GC,
+	// and total pause time in nanoseconds. Here we depend on the
+	// fact that time.Duration's native unit is nanoseconds, so the
+	// pauses and the total pause time do not need any conversion.
+	readGCStats(&stats.Pause)
+	n := len(stats.Pause) - 3
+	stats.LastGC = time.Unix(0, int64(stats.Pause[n]))
+	stats.NumGC = int64(stats.Pause[n+1])
+	stats.PauseTotal = stats.Pause[n+2]
+	stats.Pause = stats.Pause[:n]
+
+	if len(stats.PauseQuantiles) > 0 {
+		if n == 0 {
+			for i := range stats.PauseQuantiles {
+				stats.PauseQuantiles[i] = 0
+			}
+		} else {
+			// There's room for a second copy of the data in stats.Pause.
+			// See the allocation at the top of the function.
+			sorted := stats.Pause[n : n+n]
+			copy(sorted, stats.Pause)
+			sort.Sort(byDuration(sorted))
+			nq := len(stats.PauseQuantiles) - 1
+			for i := 0; i < nq; i++ {
+				stats.PauseQuantiles[i] = sorted[len(sorted)*i/nq]
+			}
+			stats.PauseQuantiles[nq] = sorted[len(sorted)-1]
+		}
+	}
+}
+
+type byDuration []time.Duration
+
+func (x byDuration) Len() int           { return len(x) }
+func (x byDuration) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byDuration) Less(i, j int) bool { return x[i] < x[j] }
+
+// SetGCPercent sets the garbage collection target percentage:
+// a collection is triggered when the ratio of freshly allocated data
+// to live data remaining after the previous collection reaches this percentage.
+// SetGCPercent returns the previous setting.
+// The initial setting is the value of the GOGC environment variable
+// at startup, or 100 if the variable is not set.
+// A negative percentage disables garbage collection.
+func SetGCPercent(percent int) int {
+	old := setGCPercent(percent)
+	runtime.GC()
+	return old
+}
+
+// FreeOSMemory forces a garbage collection followed by an
+// attempt to return as much memory to the operating system
+// as possible. (Even if this is not called, the runtime gradually
+// returns memory to the operating system in a background task.)
+func FreeOSMemory() {
+	freeOSMemory()
+}
+
+// SetMaxStack sets the maximum amount of memory that
+// can be used by a single goroutine stack.
+// If any goroutine exceeds this limit while growing its stack,
+// the program crashes.
+// SetMaxStack returns the previous setting.
+// The initial setting is 1 GB on 64-bit systems, 250 MB on 32-bit systems.
+//
+// SetMaxStack is useful mainly for limiting the damage done by
+// goroutines that enter an infinite recursion. It only limits future
+// stack growth.
+func SetMaxStack(bytes int) int {
+	return setMaxStack(bytes)
+}
+
+// SetMaxThreads sets the maximum number of operating system
+// threads that the Go program can use. If it attempts to use more than
+// this many, the program crashes.
+// SetMaxThreads returns the previous setting.
+// The initial setting is 10,000 threads.
+//
+// The limit controls the number of operating system threads, not the number
+// of goroutines. A Go program creates a new thread only when a goroutine
+// is ready to run but all the existing threads are blocked in system calls, cgo calls,
+// or are locked to other goroutines due to use of runtime.LockOSThread.
+//
+// SetMaxThreads is useful mainly for limiting the damage done by
+// programs that create an unbounded number of threads. The idea is
+// to take down the program before it takes down the operating system.
+func SetMaxThreads(threads int) int {
+	return setMaxThreads(threads)
+}
+
+// SetPanicOnFault controls the runtime's behavior when a program faults
+// at an unexpected (non-nil) address. Such faults are typically caused by
+// bugs such as runtime memory corruption, so the default response is to crash
+// the program. Programs working with memory-mapped files or unsafe
+// manipulation of memory may cause faults at non-nil addresses in less
+// dramatic situations; SetPanicOnFault allows such programs to request
+// that the runtime trigger only a panic, not a crash.
+// SetPanicOnFault applies only to the current goroutine.
+// It returns the previous setting.
+func SetPanicOnFault(enabled bool) bool
+
+// WriteHeapDump writes a description of the heap and the objects in
+// it to the given file descriptor.
+// The heap dump format is defined at http://golang.org/s/go13heapdump.
+func WriteHeapDump(fd uintptr)
diff --git a/third_party/gofrontend/libgo/go/runtime/debug/garbage_test.go b/third_party/gofrontend/libgo/go/runtime/debug/garbage_test.go
new file mode 100644
index 0000000..149bafc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/debug/garbage_test.go
@@ -0,0 +1,102 @@
+// Copyright 2013 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 debug
+
+import (
+	"runtime"
+	"testing"
+	"time"
+)
+
+func TestReadGCStats(t *testing.T) {
+	defer SetGCPercent(SetGCPercent(-1))
+
+	var stats GCStats
+	var mstats runtime.MemStats
+	var min, max time.Duration
+
+	// First ReadGCStats will allocate, second should not,
+	// especially if we follow up with an explicit garbage collection.
+	stats.PauseQuantiles = make([]time.Duration, 10)
+	ReadGCStats(&stats)
+	runtime.GC()
+
+	// Assume these will return same data: no GC during ReadGCStats.
+	ReadGCStats(&stats)
+	runtime.ReadMemStats(&mstats)
+
+	if stats.NumGC != int64(mstats.NumGC) {
+		t.Errorf("stats.NumGC = %d, but mstats.NumGC = %d", stats.NumGC, mstats.NumGC)
+	}
+	if stats.PauseTotal != time.Duration(mstats.PauseTotalNs) {
+		t.Errorf("stats.PauseTotal = %d, but mstats.PauseTotalNs = %d", stats.PauseTotal, mstats.PauseTotalNs)
+	}
+	if stats.LastGC.UnixNano() != int64(mstats.LastGC) {
+		t.Errorf("stats.LastGC.UnixNano = %d, but mstats.LastGC = %d", stats.LastGC.UnixNano(), mstats.LastGC)
+	}
+	n := int(mstats.NumGC)
+	if n > len(mstats.PauseNs) {
+		n = len(mstats.PauseNs)
+	}
+	if len(stats.Pause) != n {
+		t.Errorf("len(stats.Pause) = %d, want %d", len(stats.Pause), n)
+	} else {
+		off := (int(mstats.NumGC) + len(mstats.PauseNs) - 1) % len(mstats.PauseNs)
+		for i := 0; i < n; i++ {
+			dt := stats.Pause[i]
+			if dt != time.Duration(mstats.PauseNs[off]) {
+				t.Errorf("stats.Pause[%d] = %d, want %d", i, dt, mstats.PauseNs[off])
+			}
+			if max < dt {
+				max = dt
+			}
+			if min > dt || i == 0 {
+				min = dt
+			}
+			off = (off + len(mstats.PauseNs) - 1) % len(mstats.PauseNs)
+		}
+	}
+
+	q := stats.PauseQuantiles
+	nq := len(q)
+	if q[0] != min || q[nq-1] != max {
+		t.Errorf("stats.PauseQuantiles = [%d, ..., %d], want [%d, ..., %d]", q[0], q[nq-1], min, max)
+	}
+
+	for i := 0; i < nq-1; i++ {
+		if q[i] > q[i+1] {
+			t.Errorf("stats.PauseQuantiles[%d]=%d > stats.PauseQuantiles[%d]=%d", i, q[i], i+1, q[i+1])
+		}
+	}
+}
+
+var big = make([]byte, 1<<20)
+
+func TestFreeOSMemory(t *testing.T) {
+	var ms1, ms2 runtime.MemStats
+
+	if big == nil {
+		t.Skip("test is not reliable when run multiple times")
+	}
+	big = nil
+	runtime.GC()
+	runtime.ReadMemStats(&ms1)
+	FreeOSMemory()
+	runtime.ReadMemStats(&ms2)
+	if ms1.HeapReleased >= ms2.HeapReleased {
+		t.Errorf("released before=%d; released after=%d; did not go up", ms1.HeapReleased, ms2.HeapReleased)
+	}
+}
+
+func TestSetGCPercent(t *testing.T) {
+	// Test that the variable is being set and returned correctly.
+	// Assume the percentage itself is implemented fine during GC,
+	// which is harder to test.
+	old := SetGCPercent(123)
+	new := SetGCPercent(old)
+	if new != 123 {
+		t.Errorf("SetGCPercent(123); SetGCPercent(x) = %d, want 123", new)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/debug/heapdump_test.go b/third_party/gofrontend/libgo/go/runtime/debug/heapdump_test.go
new file mode 100644
index 0000000..9201901
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/debug/heapdump_test.go
@@ -0,0 +1,33 @@
+// Copyright 2014 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 debug
+
+import (
+	"io/ioutil"
+	"os"
+	"runtime"
+	"testing"
+)
+
+func TestWriteHeapDumpNonempty(t *testing.T) {
+	if runtime.GOOS == "nacl" {
+		t.Skip("WriteHeapDump is not available on NaCl.")
+	}
+	f, err := ioutil.TempFile("", "heapdumptest")
+	if err != nil {
+		t.Fatalf("TempFile failed: %v", err)
+	}
+	defer os.Remove(f.Name())
+	defer f.Close()
+	WriteHeapDump(f.Fd())
+	fi, err := f.Stat()
+	if err != nil {
+		t.Fatalf("Stat failed: %v", err)
+	}
+	const minSize = 1
+	if size := fi.Size(); size < minSize {
+		t.Fatalf("Heap dump size %d bytes, expected at least %d bytes", size, minSize)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/debug/stack.go b/third_party/gofrontend/libgo/go/runtime/debug/stack.go
new file mode 100644
index 0000000..c29b0a2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/debug/stack.go
@@ -0,0 +1,98 @@
+// 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.
+
+// Package debug contains facilities for programs to debug themselves while
+// they are running.
+package debug
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"runtime"
+)
+
+var (
+	dunno     = []byte("???")
+	centerDot = []byte("·")
+	dot       = []byte(".")
+	slash     = []byte("/")
+)
+
+// PrintStack prints to standard error the stack trace returned by Stack.
+func PrintStack() {
+	os.Stderr.Write(stack())
+}
+
+// Stack returns a formatted stack trace of the goroutine that calls it.
+// For each routine, it includes the source line information and PC value,
+// then attempts to discover, for Go functions, the calling function or
+// method and the text of the line containing the invocation.
+//
+// This function is deprecated. Use package runtime's Stack instead.
+func Stack() []byte {
+	return stack()
+}
+
+// stack implements Stack, skipping 2 frames
+func stack() []byte {
+	buf := new(bytes.Buffer) // the returned data
+	// As we loop, we open files and read them. These variables record the currently
+	// loaded file.
+	var lines [][]byte
+	var lastFile string
+	for i := 2; ; i++ { // Caller we care about is the user, 2 frames up
+		pc, file, line, ok := runtime.Caller(i)
+		if !ok {
+			break
+		}
+		// Print this much at least.  If we can't find the source, it won't show.
+		fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
+		if file != lastFile {
+			data, err := ioutil.ReadFile(file)
+			if err != nil {
+				continue
+			}
+			lines = bytes.Split(data, []byte{'\n'})
+			lastFile = file
+		}
+		line-- // in stack trace, lines are 1-indexed but our array is 0-indexed
+		fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
+	}
+	return buf.Bytes()
+}
+
+// source returns a space-trimmed slice of the n'th line.
+func source(lines [][]byte, n int) []byte {
+	if n < 0 || n >= len(lines) {
+		return dunno
+	}
+	return bytes.Trim(lines[n], " \t")
+}
+
+// function returns, if possible, the name of the function containing the PC.
+func function(pc uintptr) []byte {
+	fn := runtime.FuncForPC(pc)
+	if fn == nil {
+		return dunno
+	}
+	name := []byte(fn.Name())
+	// The name includes the path name to the package, which is unnecessary
+	// since the file name is already included.  Plus, it has center dots.
+	// That is, we see
+	//	runtime/debug.*T·ptrmethod
+	// and want
+	//	*T.ptrmethod
+	// Since the package path might contains dots (e.g. code.google.com/...),
+	// we first remove the path prefix if there is one.
+	if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
+		name = name[lastslash+1:]
+	}
+	if period := bytes.Index(name, dot); period >= 0 {
+		name = name[period+1:]
+	}
+	name = bytes.Replace(name, centerDot, dot, -1)
+	return name
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/debug/stack_test.go b/third_party/gofrontend/libgo/go/runtime/debug/stack_test.go
new file mode 100644
index 0000000..263d715
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/debug/stack_test.go
@@ -0,0 +1,62 @@
+// 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.
+
+package debug
+
+import (
+	"strings"
+	"testing"
+)
+
+type T int
+
+func (t *T) ptrmethod() []byte {
+	return Stack()
+}
+func (t T) method() []byte {
+	return t.ptrmethod()
+}
+
+/*
+	The traceback should look something like this, modulo line numbers and hex constants.
+	Don't worry much about the base levels, but check the ones in our own package.
+
+		/Users/r/go/src/pkg/runtime/debug/stack_test.go:15 (0x13878)
+			(*T).ptrmethod: return Stack()
+		/Users/r/go/src/pkg/runtime/debug/stack_test.go:18 (0x138dd)
+			T.method: return t.ptrmethod()
+		/Users/r/go/src/pkg/runtime/debug/stack_test.go:23 (0x13920)
+			TestStack: b := T(0).method()
+		/Users/r/go/src/pkg/testing/testing.go:132 (0x14a7a)
+			tRunner: test.F(t)
+		/Users/r/go/src/pkg/runtime/proc.c:145 (0xc970)
+			???: runtime·unlock(&runtime·sched);
+*/
+func TestStack(t *testing.T) {
+	b := T(0).method()
+	lines := strings.Split(string(b), "\n")
+	if len(lines) < 6 {
+		t.Fatal("too few lines")
+	}
+	n := 0
+	frame := func(line, code string) {
+		check(t, lines[n], line)
+		n++
+		// The source might not be available while running the test.
+		if strings.HasPrefix(lines[n], "\t") {
+			check(t, lines[n], code)
+			n++
+		}
+	}
+	frame("stack_test.go", "\tmethod.N15_runtime_debug.T: return Stack()")
+	frame("stack_test.go", "\tmethod.N15_runtime_debug.T: return t.ptrmethod()")
+	frame("stack_test.go", "\tTestStack: b := T(0).method()")
+	frame("testing/testing.go", "")
+}
+
+func check(t *testing.T, line, has string) {
+	if strings.Index(line, has) < 0 {
+		t.Errorf("expected %q in %q", has, line)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/error.go b/third_party/gofrontend/libgo/go/runtime/error.go
new file mode 100644
index 0000000..d759a54
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/error.go
@@ -0,0 +1,156 @@
+// Copyright 2010 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 runtime
+
+// The Error interface identifies a run time error.
+type Error interface {
+	error
+
+	// RuntimeError is a no-op function but
+	// serves to distinguish types that are runtime
+	// errors from ordinary errors: a type is a
+	// runtime error if it has a RuntimeError method.
+	RuntimeError()
+}
+
+// A TypeAssertionError explains a failed type assertion.
+type TypeAssertionError struct {
+	interfaceString string
+	concreteString  string
+	assertedString  string
+	missingMethod   string // one method needed by Interface, missing from Concrete
+}
+
+func (*TypeAssertionError) RuntimeError() {}
+
+func (e *TypeAssertionError) Error() string {
+	inter := e.interfaceString
+	if inter == "" {
+		inter = "interface"
+	}
+	if e.concreteString == "" {
+		return "interface conversion: " + inter + " is nil, not " + e.assertedString
+	}
+	if e.missingMethod == "" {
+		return "interface conversion: " + inter + " is " + e.concreteString +
+			", not " + e.assertedString
+	}
+	return "interface conversion: " + e.concreteString + " is not " + e.assertedString +
+		": missing method " + e.missingMethod
+}
+
+// For calling from C.
+func NewTypeAssertionError(ps1, ps2, ps3 *string, pmeth *string, ret *interface{}) {
+	var s1, s2, s3, meth string
+
+	if ps1 != nil {
+		s1 = *ps1
+	}
+	if ps2 != nil {
+		s2 = *ps2
+	}
+	if ps3 != nil {
+		s3 = *ps3
+	}
+	if pmeth != nil {
+		meth = *pmeth
+	}
+
+	// For gccgo, strip out quoted strings.
+	s1 = unquote(s1)
+	s2 = unquote(s2)
+	s3 = unquote(s3)
+
+	*ret = &TypeAssertionError{s1, s2, s3, meth}
+}
+
+// Remove quoted strings from gccgo reflection strings.
+func unquote(s string) string {
+	ls := len(s)
+	var i int
+	for i = 0; i < ls; i++ {
+		if s[i] == '\t' {
+			break
+		}
+	}
+	if i == ls {
+		return s
+	}
+	var q bool
+	r := make([]byte, len(s))
+	j := 0
+	for i = 0; i < ls; i++ {
+		if s[i] == '\t' {
+			q = !q
+		} else if !q {
+			r[j] = s[i]
+			j++
+		}
+	}
+	return string(r[:j])
+}
+
+// An errorString represents a runtime error described by a single string.
+type errorString string
+
+func (e errorString) RuntimeError() {}
+
+func (e errorString) Error() string {
+	return "runtime error: " + string(e)
+}
+
+// For calling from C.
+func NewErrorString(s string, ret *interface{}) {
+	*ret = errorString(s)
+}
+
+// An errorCString represents a runtime error described by a single C string.
+// Not "type errorCString uintptr" because of http://golang.org/issue/7084.
+type errorCString struct{ cstr uintptr }
+
+func (e errorCString) RuntimeError() {}
+
+func cstringToGo(uintptr) string
+
+func (e errorCString) Error() string {
+	return "runtime error: " + cstringToGo(e.cstr)
+}
+
+// For calling from C.
+func NewErrorCString(s uintptr, ret *interface{}) {
+	*ret = errorCString{s}
+}
+
+type stringer interface {
+	String() string
+}
+
+func typestring(interface{}) string
+
+// For calling from C.
+// Prints an argument passed to panic.
+// There's room for arbitrary complexity here, but we keep it
+// simple and handle just a few important cases: int, string, and Stringer.
+func Printany(i interface{}) {
+	switch v := i.(type) {
+	case nil:
+		print("nil")
+	case stringer:
+		print(v.String())
+	case error:
+		print(v.Error())
+	case int:
+		print(v)
+	case string:
+		print(v)
+	default:
+		print("(", typestring(i), ") ", i)
+	}
+}
+
+// called from generated code
+func panicwrap(pkg, typ, meth string) {
+	panic("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer")
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/export_test.go b/third_party/gofrontend/libgo/go/runtime/export_test.go
new file mode 100644
index 0000000..165bebf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/export_test.go
@@ -0,0 +1,90 @@
+// Copyright 2010 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.
+
+// Export guts for testing.
+
+package runtime
+
+var Fadd64 = fadd64
+var Fsub64 = fsub64
+var Fmul64 = fmul64
+var Fdiv64 = fdiv64
+var F64to32 = f64to32
+var F32to64 = f32to64
+var Fcmp64 = fcmp64
+var Fintto64 = fintto64
+var F64toint = f64toint
+
+func entersyscall()
+func exitsyscall()
+func golockedOSThread() bool
+
+var Entersyscall = entersyscall
+var Exitsyscall = exitsyscall
+var LockedOSThread = golockedOSThread
+
+type LFNode struct {
+	Next    *LFNode
+	Pushcnt uintptr
+}
+
+func lfstackpush_go(head *uint64, node *LFNode)
+func lfstackpop_go(head *uint64) *LFNode
+
+var LFStackPush = lfstackpush_go
+var LFStackPop = lfstackpop_go
+
+type ParFor struct {
+	body    *byte
+	done    uint32
+	Nthr    uint32
+	nthrmax uint32
+	thrseq  uint32
+	Cnt     uint32
+	Ctx     *byte
+	wait    bool
+}
+
+func newParFor(nthrmax uint32) *ParFor
+func parForSetup(desc *ParFor, nthr, n uint32, ctx *byte, wait bool, body func(*ParFor, uint32))
+func parForDo(desc *ParFor)
+func parForIters(desc *ParFor, tid uintptr) (uintptr, uintptr)
+
+var NewParFor = newParFor
+var ParForSetup = parForSetup
+var ParForDo = parForDo
+
+func ParForIters(desc *ParFor, tid uint32) (uint32, uint32) {
+	begin, end := parForIters(desc, uintptr(tid))
+	return uint32(begin), uint32(end)
+}
+
+func testSchedLocalQueue()
+func testSchedLocalQueueSteal()
+
+var TestSchedLocalQueue1 = testSchedLocalQueue
+var TestSchedLocalQueueSteal1 = testSchedLocalQueueSteal
+
+// func haveGoodHash() bool
+// func stringHash(s string, seed uintptr) uintptr
+// func bytesHash(b []byte, seed uintptr) uintptr
+// func int32Hash(i uint32, seed uintptr) uintptr
+// func int64Hash(i uint64, seed uintptr) uintptr
+
+// var HaveGoodHash = haveGoodHash
+// var StringHash = stringHash
+// var BytesHash = bytesHash
+// var Int32Hash = int32Hash
+// var Int64Hash = int64Hash
+
+var hashLoad float64 // declared in hashmap.c
+var HashLoad = &hashLoad
+
+func memclrBytes(b []byte)
+
+var MemclrBytes = memclrBytes
+
+// func gogoBytes() int32
+
+// var GogoBytes = gogoBytes
diff --git a/third_party/gofrontend/libgo/go/runtime/extern.go b/third_party/gofrontend/libgo/go/runtime/extern.go
new file mode 100644
index 0000000..333d4fd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/extern.go
@@ -0,0 +1,205 @@
+// 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 runtime contains operations that interact with Go's runtime system,
+such as functions to control goroutines. It also includes the low-level type information
+used by the reflect package; see reflect's documentation for the programmable
+interface to the run-time type system.
+
+Environment Variables
+
+The following environment variables ($name or %name%, depending on the host
+operating system) control the run-time behavior of Go programs. The meanings
+and use may change from release to release.
+
+The GOGC variable sets the initial garbage collection target percentage.
+A collection is triggered when the ratio of freshly allocated data to live data
+remaining after the previous collection reaches this percentage. The default
+is GOGC=100. Setting GOGC=off disables the garbage collector entirely.
+The runtime/debug package's SetGCPercent function allows changing this
+percentage at run time. See http://golang.org/pkg/runtime/debug/#SetGCPercent.
+
+The GODEBUG variable controls debug output from the runtime. GODEBUG value is
+a comma-separated list of name=val pairs. Supported names are:
+
+	allocfreetrace: setting allocfreetrace=1 causes every allocation to be
+	profiled and a stack trace printed on each object's allocation and free.
+
+	efence: setting efence=1 causes the allocator to run in a mode
+	where each object is allocated on a unique page and addresses are
+	never recycled.
+
+	gctrace: setting gctrace=1 causes the garbage collector to emit a single line to standard
+	error at each collection, summarizing the amount of memory collected and the
+	length of the pause. Setting gctrace=2 emits the same summary but also
+	repeats each collection.
+
+	gcdead: setting gcdead=1 causes the garbage collector to clobber all stack slots
+	that it thinks are dead.
+
+	scheddetail: setting schedtrace=X and scheddetail=1 causes the scheduler to emit
+	detailed multiline info every X milliseconds, describing state of the scheduler,
+	processors, threads and goroutines.
+
+	schedtrace: setting schedtrace=X causes the scheduler to emit a single line to standard
+	error every X milliseconds, summarizing the scheduler state.
+
+The GOMAXPROCS variable limits the number of operating system threads that
+can execute user-level Go code simultaneously. There is no limit to the number of threads
+that can be blocked in system calls on behalf of Go code; those do not count against
+the GOMAXPROCS limit. This package's GOMAXPROCS function queries and changes
+the limit.
+
+The GOTRACEBACK variable controls the amount of output generated when a Go
+program fails due to an unrecovered panic or an unexpected runtime condition.
+By default, a failure prints a stack trace for every extant goroutine, eliding functions
+internal to the run-time system, and then exits with exit code 2.
+If GOTRACEBACK=0, the per-goroutine stack traces are omitted entirely.
+If GOTRACEBACK=1, the default behavior is used.
+If GOTRACEBACK=2, the per-goroutine stack traces include run-time functions.
+If GOTRACEBACK=crash, the per-goroutine stack traces include run-time functions,
+and if possible the program crashes in an operating-specific manner instead of
+exiting. For example, on Unix systems, the program raises SIGABRT to trigger a
+core dump.
+
+The GOARCH, GOOS, GOPATH, and GOROOT environment variables complete
+the set of Go environment variables. They influence the building of Go programs
+(see http://golang.org/cmd/go and http://golang.org/pkg/go/build).
+GOARCH, GOOS, and GOROOT are recorded at compile time and made available by
+constants or functions in this package, but they do not influence the execution
+of the run-time system.
+*/
+package runtime
+
+// Gosched yields the processor, allowing other goroutines to run.  It does not
+// suspend the current goroutine, so execution resumes automatically.
+func Gosched()
+
+// Goexit terminates the goroutine that calls it.  No other goroutine is affected.
+// Goexit runs all deferred calls before terminating the goroutine.
+//
+// Calling Goexit from the main goroutine terminates that goroutine
+// without func main returning. Since func main has not returned,
+// the program continues execution of other goroutines.
+// If all other goroutines exit, the program crashes.
+func Goexit()
+
+// Caller reports file and line number information about function invocations on
+// the calling goroutine's stack.  The argument skip is the number of stack frames
+// to ascend, with 0 identifying the caller of Caller.  (For historical reasons the
+// meaning of skip differs between Caller and Callers.) The return values report the
+// program counter, file name, and line number within the file of the corresponding
+// call.  The boolean ok is false if it was not possible to recover the information.
+func Caller(skip int) (pc uintptr, file string, line int, ok bool)
+
+// Callers fills the slice pc with the program counters of function invocations
+// on the calling goroutine's stack.  The argument skip is the number of stack frames
+// to skip before recording in pc, with 0 identifying the frame for Callers itself and
+// 1 identifying the caller of Callers.
+// It returns the number of entries written to pc.
+func Callers(skip int, pc []uintptr) int
+
+type Func struct {
+	opaque struct{} // unexported field to disallow conversions
+}
+
+// FuncForPC returns a *Func describing the function that contains the
+// given program counter address, or else nil.
+func FuncForPC(pc uintptr) *Func
+
+// Name returns the name of the function.
+func (f *Func) Name() string {
+	return funcname_go(f)
+}
+
+// Entry returns the entry address of the function.
+func (f *Func) Entry() uintptr {
+	return funcentry_go(f)
+}
+
+// FileLine returns the file name and line number of the
+// source code corresponding to the program counter pc.
+// The result will not be accurate if pc is not a program
+// counter within f.
+func (f *Func) FileLine(pc uintptr) (file string, line int) {
+	return funcline_go(f, pc)
+}
+
+// implemented in symtab.c
+func funcline_go(*Func, uintptr) (string, int)
+func funcname_go(*Func) string
+func funcentry_go(*Func) uintptr
+
+// SetFinalizer sets the finalizer associated with x to f.
+// When the garbage collector finds an unreachable block
+// with an associated finalizer, it clears the association and runs
+// f(x) in a separate goroutine.  This makes x reachable again, but
+// now without an associated finalizer.  Assuming that SetFinalizer
+// is not called again, the next time the garbage collector sees
+// that x is unreachable, it will free x.
+//
+// SetFinalizer(x, nil) clears any finalizer associated with x.
+//
+// The argument x must be a pointer to an object allocated by
+// calling new or by taking the address of a composite literal.
+// The argument f must be a function that takes a single argument
+// to which x's type can be assigned, and can have arbitrary ignored return
+// values. If either of these is not true, SetFinalizer aborts the
+// program.
+//
+// Finalizers are run in dependency order: if A points at B, both have
+// finalizers, and they are otherwise unreachable, only the finalizer
+// for A runs; once A is freed, the finalizer for B can run.
+// If a cyclic structure includes a block with a finalizer, that
+// cycle is not guaranteed to be garbage collected and the finalizer
+// is not guaranteed to run, because there is no ordering that
+// respects the dependencies.
+//
+// The finalizer for x is scheduled to run at some arbitrary time after
+// x becomes unreachable.
+// There is no guarantee that finalizers will run before a program exits,
+// so typically they are useful only for releasing non-memory resources
+// associated with an object during a long-running program.
+// For example, an os.File object could use a finalizer to close the
+// associated operating system file descriptor when a program discards
+// an os.File without calling Close, but it would be a mistake
+// to depend on a finalizer to flush an in-memory I/O buffer such as a
+// bufio.Writer, because the buffer would not be flushed at program exit.
+//
+// It is not guaranteed that a finalizer will run if the size of *x is
+// zero bytes.
+//
+// A single goroutine runs all finalizers for a program, sequentially.
+// If a finalizer must run for a long time, it should do so by starting
+// a new goroutine.
+func SetFinalizer(x, f interface{})
+
+func getgoroot() string
+
+// GOROOT returns the root of the Go tree.
+// It uses the GOROOT environment variable, if set,
+// or else the root used during the Go build.
+func GOROOT() string {
+	s := getgoroot()
+	if s != "" {
+		return s
+	}
+	return defaultGoroot
+}
+
+// Version returns the Go tree's version string.
+// It is either the commit hash and date at the time of the build or,
+// when possible, a release tag like "go1.3".
+func Version() string {
+	return theVersion
+}
+
+// GOOS is the running program's operating system target:
+// one of darwin, freebsd, linux, and so on.
+const GOOS string = theGoos
+
+// GOARCH is the running program's architecture target:
+// 386, amd64, arm or arm64.
+const GOARCH string = theGoarch
diff --git a/third_party/gofrontend/libgo/go/runtime/gc_test.go b/third_party/gofrontend/libgo/go/runtime/gc_test.go
new file mode 100644
index 0000000..5a1e9b8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/gc_test.go
@@ -0,0 +1,238 @@
+// 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.
+
+package runtime_test
+
+import (
+	// "os"
+	"runtime"
+	"runtime/debug"
+	"testing"
+	"time"
+)
+
+func TestGcSys(t *testing.T) {
+	/* gccgo does not have a go command
+	if os.Getenv("GOGC") == "off" {
+		t.Skip("skipping test; GOGC=off in environment")
+	}
+	data := struct{ Short bool }{testing.Short()}
+	got := executeTest(t, testGCSysSource, &data)
+	want := "OK\n"
+	if got != want {
+		t.Fatalf("expected %q, but got %q", want, got)
+	}
+	*/
+}
+
+const testGCSysSource = `
+package main
+
+import (
+	"fmt"
+	"runtime"
+)
+
+func main() {
+	runtime.GOMAXPROCS(1)
+	memstats := new(runtime.MemStats)
+	runtime.GC()
+	runtime.ReadMemStats(memstats)
+	sys := memstats.Sys
+
+	runtime.MemProfileRate = 0 // disable profiler
+
+	itercount := 1000000
+{{if .Short}}
+	itercount = 100000
+{{end}}
+	for i := 0; i < itercount; i++ {
+		workthegc()
+	}
+
+	// Should only be using a few MB.
+	// We allocated 100 MB or (if not short) 1 GB.
+	runtime.ReadMemStats(memstats)
+	if sys > memstats.Sys {
+		sys = 0
+	} else {
+		sys = memstats.Sys - sys
+	}
+	if sys > 16<<20 {
+		fmt.Printf("using too much memory: %d bytes\n", sys)
+		return
+	}
+	fmt.Printf("OK\n")
+}
+
+func workthegc() []byte {
+	return make([]byte, 1029)
+}
+`
+
+func TestGcDeepNesting(t *testing.T) {
+	type T [2][2][2][2][2][2][2][2][2][2]*int
+	a := new(T)
+
+	// Prevent the compiler from applying escape analysis.
+	// This makes sure new(T) is allocated on heap, not on the stack.
+	t.Logf("%p", a)
+
+	a[0][0][0][0][0][0][0][0][0][0] = new(int)
+	*a[0][0][0][0][0][0][0][0][0][0] = 13
+	runtime.GC()
+	if *a[0][0][0][0][0][0][0][0][0][0] != 13 {
+		t.Fail()
+	}
+}
+
+func TestGcHashmapIndirection(t *testing.T) {
+	defer debug.SetGCPercent(debug.SetGCPercent(1))
+	runtime.GC()
+	type T struct {
+		a [256]int
+	}
+	m := make(map[T]T)
+	for i := 0; i < 2000; i++ {
+		var a T
+		a.a[0] = i
+		m[a] = T{}
+	}
+}
+
+func TestGcArraySlice(t *testing.T) {
+	type X struct {
+		buf     [1]byte
+		nextbuf []byte
+		next    *X
+	}
+	var head *X
+	for i := 0; i < 10; i++ {
+		p := &X{}
+		p.buf[0] = 42
+		p.next = head
+		if head != nil {
+			p.nextbuf = head.buf[:]
+		}
+		head = p
+		runtime.GC()
+	}
+	for p := head; p != nil; p = p.next {
+		if p.buf[0] != 42 {
+			t.Fatal("corrupted heap")
+		}
+	}
+}
+
+func TestGcRescan(t *testing.T) {
+	type X struct {
+		c     chan error
+		nextx *X
+	}
+	type Y struct {
+		X
+		nexty *Y
+		p     *int
+	}
+	var head *Y
+	for i := 0; i < 10; i++ {
+		p := &Y{}
+		p.c = make(chan error)
+		if head != nil {
+			p.nextx = &head.X
+		}
+		p.nexty = head
+		p.p = new(int)
+		*p.p = 42
+		head = p
+		runtime.GC()
+	}
+	for p := head; p != nil; p = p.nexty {
+		if *p.p != 42 {
+			t.Fatal("corrupted heap")
+		}
+	}
+}
+
+func TestGcLastTime(t *testing.T) {
+	ms := new(runtime.MemStats)
+	t0 := time.Now().UnixNano()
+	runtime.GC()
+	t1 := time.Now().UnixNano()
+	runtime.ReadMemStats(ms)
+	last := int64(ms.LastGC)
+	if t0 > last || last > t1 {
+		t.Fatalf("bad last GC time: got %v, want [%v, %v]", last, t0, t1)
+	}
+}
+
+func BenchmarkSetTypeNoPtr1(b *testing.B) {
+	type NoPtr1 struct {
+		p uintptr
+	}
+	var p *NoPtr1
+	for i := 0; i < b.N; i++ {
+		p = &NoPtr1{}
+	}
+	_ = p
+}
+func BenchmarkSetTypeNoPtr2(b *testing.B) {
+	type NoPtr2 struct {
+		p, q uintptr
+	}
+	var p *NoPtr2
+	for i := 0; i < b.N; i++ {
+		p = &NoPtr2{}
+	}
+	_ = p
+}
+func BenchmarkSetTypePtr1(b *testing.B) {
+	type Ptr1 struct {
+		p *byte
+	}
+	var p *Ptr1
+	for i := 0; i < b.N; i++ {
+		p = &Ptr1{}
+	}
+	_ = p
+}
+func BenchmarkSetTypePtr2(b *testing.B) {
+	type Ptr2 struct {
+		p, q *byte
+	}
+	var p *Ptr2
+	for i := 0; i < b.N; i++ {
+		p = &Ptr2{}
+	}
+	_ = p
+}
+
+func BenchmarkAllocation(b *testing.B) {
+	type T struct {
+		x, y *byte
+	}
+	ngo := runtime.GOMAXPROCS(0)
+	work := make(chan bool, b.N+ngo)
+	result := make(chan *T)
+	for i := 0; i < b.N; i++ {
+		work <- true
+	}
+	for i := 0; i < ngo; i++ {
+		work <- false
+	}
+	for i := 0; i < ngo; i++ {
+		go func() {
+			var x *T
+			for <-work {
+				for i := 0; i < 1000; i++ {
+					x = &T{}
+				}
+			}
+			result <- x
+		}()
+	}
+	for i := 0; i < ngo; i++ {
+		<-result
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/iface_test.go b/third_party/gofrontend/libgo/go/runtime/iface_test.go
new file mode 100644
index 0000000..bca0ea0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/iface_test.go
@@ -0,0 +1,138 @@
+// 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 runtime_test
+
+import (
+	"testing"
+)
+
+type I1 interface {
+	Method1()
+}
+
+type I2 interface {
+	Method1()
+	Method2()
+}
+
+type TS uint16
+type TM uintptr
+type TL [2]uintptr
+
+func (TS) Method1() {}
+func (TS) Method2() {}
+func (TM) Method1() {}
+func (TM) Method2() {}
+func (TL) Method1() {}
+func (TL) Method2() {}
+
+var (
+	e  interface{}
+	e_ interface{}
+	i1 I1
+	i2 I2
+	ts TS
+	tm TM
+	tl TL
+)
+
+func BenchmarkConvT2ESmall(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		e = ts
+	}
+}
+
+func BenchmarkConvT2EUintptr(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		e = tm
+	}
+}
+
+func BenchmarkConvT2ELarge(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		e = tl
+	}
+}
+
+func BenchmarkConvT2ISmall(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		i1 = ts
+	}
+}
+
+func BenchmarkConvT2IUintptr(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		i1 = tm
+	}
+}
+
+func BenchmarkConvT2ILarge(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		i1 = tl
+	}
+}
+
+func BenchmarkConvI2E(b *testing.B) {
+	i2 = tm
+	for i := 0; i < b.N; i++ {
+		e = i2
+	}
+}
+
+func BenchmarkConvI2I(b *testing.B) {
+	i2 = tm
+	for i := 0; i < b.N; i++ {
+		i1 = i2
+	}
+}
+
+func BenchmarkAssertE2T(b *testing.B) {
+	e = tm
+	for i := 0; i < b.N; i++ {
+		tm = e.(TM)
+	}
+}
+
+func BenchmarkAssertE2TLarge(b *testing.B) {
+	e = tl
+	for i := 0; i < b.N; i++ {
+		tl = e.(TL)
+	}
+}
+
+func BenchmarkAssertE2I(b *testing.B) {
+	e = tm
+	for i := 0; i < b.N; i++ {
+		i1 = e.(I1)
+	}
+}
+
+func BenchmarkAssertI2T(b *testing.B) {
+	i1 = tm
+	for i := 0; i < b.N; i++ {
+		tm = i1.(TM)
+	}
+}
+
+func BenchmarkAssertI2I(b *testing.B) {
+	i1 = tm
+	for i := 0; i < b.N; i++ {
+		i2 = i1.(I2)
+	}
+}
+
+func BenchmarkAssertI2E(b *testing.B) {
+	i1 = tm
+	for i := 0; i < b.N; i++ {
+		e = i1.(interface{})
+	}
+}
+
+func BenchmarkAssertE2E(b *testing.B) {
+	e = tm
+	for i := 0; i < b.N; i++ {
+		e_ = e
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/lfstack_test.go b/third_party/gofrontend/libgo/go/runtime/lfstack_test.go
new file mode 100644
index 0000000..e518777
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/lfstack_test.go
@@ -0,0 +1,136 @@
+// 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 runtime_test
+
+import (
+	"math/rand"
+	. "runtime"
+	"testing"
+	"unsafe"
+)
+
+type MyNode struct {
+	LFNode
+	data int
+}
+
+func fromMyNode(node *MyNode) *LFNode {
+	return (*LFNode)(unsafe.Pointer(node))
+}
+
+func toMyNode(node *LFNode) *MyNode {
+	return (*MyNode)(unsafe.Pointer(node))
+}
+
+func TestLFStack(t *testing.T) {
+	stack := new(uint64)
+	// Need to keep additional referenfces to nodes, the stack is not all that type-safe.
+	var nodes []*MyNode
+
+	// Check the stack is initially empty.
+	if LFStackPop(stack) != nil {
+		t.Fatalf("stack is not empty")
+	}
+
+	// Push one element.
+	node := &MyNode{data: 42}
+	nodes = append(nodes, node)
+	LFStackPush(stack, fromMyNode(node))
+
+	// Push another.
+	node = &MyNode{data: 43}
+	nodes = append(nodes, node)
+	LFStackPush(stack, fromMyNode(node))
+
+	// Pop one element.
+	node = toMyNode(LFStackPop(stack))
+	if node == nil {
+		t.Fatalf("stack is empty")
+	}
+	if node.data != 43 {
+		t.Fatalf("no lifo")
+	}
+
+	// Pop another.
+	node = toMyNode(LFStackPop(stack))
+	if node == nil {
+		t.Fatalf("stack is empty")
+	}
+	if node.data != 42 {
+		t.Fatalf("no lifo")
+	}
+
+	// Check the stack is empty again.
+	if LFStackPop(stack) != nil {
+		t.Fatalf("stack is not empty")
+	}
+	if *stack != 0 {
+		t.Fatalf("stack is not empty")
+	}
+}
+
+var stress []*MyNode
+
+func TestLFStackStress(t *testing.T) {
+	const K = 100
+	P := 4 * GOMAXPROCS(-1)
+	N := 100000
+	if testing.Short() {
+		N /= 10
+	}
+	// Create 2 stacks.
+	stacks := [2]*uint64{new(uint64), new(uint64)}
+	// Need to keep additional references to nodes,
+	// the lock-free stack is not type-safe.
+	stress = nil
+	// Push K elements randomly onto the stacks.
+	sum := 0
+	for i := 0; i < K; i++ {
+		sum += i
+		node := &MyNode{data: i}
+		stress = append(stress, node)
+		LFStackPush(stacks[i%2], fromMyNode(node))
+	}
+	c := make(chan bool, P)
+	for p := 0; p < P; p++ {
+		go func() {
+			r := rand.New(rand.NewSource(rand.Int63()))
+			// Pop a node from a random stack, then push it onto a random stack.
+			for i := 0; i < N; i++ {
+				node := toMyNode(LFStackPop(stacks[r.Intn(2)]))
+				if node != nil {
+					LFStackPush(stacks[r.Intn(2)], fromMyNode(node))
+				}
+			}
+			c <- true
+		}()
+	}
+	for i := 0; i < P; i++ {
+		<-c
+	}
+	// Pop all elements from both stacks, and verify that nothing lost.
+	sum2 := 0
+	cnt := 0
+	for i := 0; i < 2; i++ {
+		for {
+			node := toMyNode(LFStackPop(stacks[i]))
+			if node == nil {
+				break
+			}
+			cnt++
+			sum2 += node.data
+			node.Next = nil
+		}
+	}
+	if cnt != K {
+		t.Fatalf("Wrong number of nodes %d/%d", cnt, K)
+	}
+	if sum2 != sum {
+		t.Fatalf("Wrong sum %d/%d", sum2, sum)
+	}
+
+	// Let nodes be collected now.
+	stress = nil
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/malloc1.go b/third_party/gofrontend/libgo/go/runtime/malloc1.go
new file mode 100644
index 0000000..da92f4c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/malloc1.go
@@ -0,0 +1,26 @@
+// 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.
+
+// +build ignore
+
+// trivial malloc test
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"runtime"
+)
+
+var chatty = flag.Bool("v", false, "chatty")
+
+func main() {
+	memstats := new(runtime.MemStats)
+	runtime.Free(runtime.Alloc(1))
+	runtime.ReadMemStats(memstats)
+	if *chatty {
+		fmt.Printf("%+v %v\n", memstats, uint64(0))
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/malloc_test.go b/third_party/gofrontend/libgo/go/runtime/malloc_test.go
new file mode 100644
index 0000000..054f6a7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/malloc_test.go
@@ -0,0 +1,156 @@
+// Copyright 2013 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 runtime_test
+
+import (
+	"flag"
+	. "runtime"
+	"testing"
+	"time"
+	"unsafe"
+)
+
+func TestMemStats(t *testing.T) {
+	// Test that MemStats has sane values.
+	st := new(MemStats)
+	ReadMemStats(st)
+	if st.HeapSys == 0 || /* st.StackSys == 0 || */ st.MSpanSys == 0 || st.MCacheSys == 0 ||
+		st.BuckHashSys == 0 || st.GCSys == 0 || st.OtherSys == 0 {
+		t.Fatalf("Zero sys value: %+v", *st)
+	}
+	if st.Sys != st.HeapSys+st.StackSys+st.MSpanSys+st.MCacheSys+
+		st.BuckHashSys+st.GCSys+st.OtherSys {
+		t.Fatalf("Bad sys value: %+v", *st)
+	}
+}
+
+var mallocSink uintptr
+
+func BenchmarkMalloc8(b *testing.B) {
+	var x uintptr
+	for i := 0; i < b.N; i++ {
+		p := new(int64)
+		x ^= uintptr(unsafe.Pointer(p))
+	}
+	mallocSink = x
+}
+
+func BenchmarkMalloc16(b *testing.B) {
+	var x uintptr
+	for i := 0; i < b.N; i++ {
+		p := new([2]int64)
+		x ^= uintptr(unsafe.Pointer(p))
+	}
+	mallocSink = x
+}
+
+func BenchmarkMallocTypeInfo8(b *testing.B) {
+	var x uintptr
+	for i := 0; i < b.N; i++ {
+		p := new(struct {
+			p [8 / unsafe.Sizeof(uintptr(0))]*int
+		})
+		x ^= uintptr(unsafe.Pointer(p))
+	}
+	mallocSink = x
+}
+
+func BenchmarkMallocTypeInfo16(b *testing.B) {
+	var x uintptr
+	for i := 0; i < b.N; i++ {
+		p := new(struct {
+			p [16 / unsafe.Sizeof(uintptr(0))]*int
+		})
+		x ^= uintptr(unsafe.Pointer(p))
+	}
+	mallocSink = x
+}
+
+var n = flag.Int("n", 1000, "number of goroutines")
+
+func BenchmarkGoroutineSelect(b *testing.B) {
+	quit := make(chan struct{})
+	read := func(ch chan struct{}) {
+		for {
+			select {
+			case _, ok := <-ch:
+				if !ok {
+					return
+				}
+			case <-quit:
+				return
+			}
+		}
+	}
+	benchHelper(b, *n, read)
+}
+
+func BenchmarkGoroutineBlocking(b *testing.B) {
+	read := func(ch chan struct{}) {
+		for {
+			if _, ok := <-ch; !ok {
+				return
+			}
+		}
+	}
+	benchHelper(b, *n, read)
+}
+
+func BenchmarkGoroutineForRange(b *testing.B) {
+	read := func(ch chan struct{}) {
+		for _ = range ch {
+		}
+	}
+	benchHelper(b, *n, read)
+}
+
+func benchHelper(b *testing.B, n int, read func(chan struct{})) {
+	m := make([]chan struct{}, n)
+	for i := range m {
+		m[i] = make(chan struct{}, 1)
+		go read(m[i])
+	}
+	b.StopTimer()
+	b.ResetTimer()
+	GC()
+
+	for i := 0; i < b.N; i++ {
+		for _, ch := range m {
+			if ch != nil {
+				ch <- struct{}{}
+			}
+		}
+		time.Sleep(10 * time.Millisecond)
+		b.StartTimer()
+		GC()
+		b.StopTimer()
+	}
+
+	for _, ch := range m {
+		close(ch)
+	}
+	time.Sleep(10 * time.Millisecond)
+}
+
+func BenchmarkGoroutineIdle(b *testing.B) {
+	quit := make(chan struct{})
+	fn := func() {
+		<-quit
+	}
+	for i := 0; i < *n; i++ {
+		go fn()
+	}
+
+	GC()
+	b.ResetTimer()
+
+	for i := 0; i < b.N; i++ {
+		GC()
+	}
+
+	b.StopTimer()
+	close(quit)
+	time.Sleep(10 * time.Millisecond)
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/mallocrand.go b/third_party/gofrontend/libgo/go/runtime/mallocrand.go
new file mode 100644
index 0000000..f1bcb89
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/mallocrand.go
@@ -0,0 +1,93 @@
+// 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.
+
+// +build ignore
+
+// Random malloc test.
+
+package main
+
+import (
+	"flag"
+	"math/rand"
+	"runtime"
+	"unsafe"
+)
+
+var chatty = flag.Bool("v", false, "chatty")
+
+var footprint uint64
+var allocated uint64
+
+func bigger() {
+	memstats := new(runtime.MemStats)
+	runtime.ReadMemStats(memstats)
+	if f := memstats.Sys; footprint < f {
+		footprint = f
+		if *chatty {
+			println("Footprint", footprint, " for ", allocated)
+		}
+		if footprint > 1e9 {
+			println("too big")
+			panic("fail")
+		}
+	}
+}
+
+// Prime the data structures by allocating one of
+// each block in order.  After this, there should be
+// little reason to ask for more memory from the OS.
+func prime() {
+	for i := 0; i < 16; i++ {
+		b := runtime.Alloc(1 << uint(i))
+		runtime.Free(b)
+	}
+	for i := uintptr(0); i < 256; i++ {
+		b := runtime.Alloc(i << 12)
+		runtime.Free(b)
+	}
+}
+
+func memset(b *byte, c byte, n uintptr) {
+	np := uintptr(n)
+	for i := uintptr(0); i < np; i++ {
+		*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(b)) + i)) = c
+	}
+}
+
+func main() {
+	flag.Parse()
+	//	prime()
+	var blocks [1]struct {
+		base *byte
+		siz  uintptr
+	}
+	for i := 0; i < 1<<10; i++ {
+		if i%(1<<10) == 0 && *chatty {
+			println(i)
+		}
+		b := rand.Int() % len(blocks)
+		if blocks[b].base != nil {
+			//	println("Free", blocks[b].siz, blocks[b].base)
+			runtime.Free(blocks[b].base)
+			blocks[b].base = nil
+			allocated -= uint64(blocks[b].siz)
+			continue
+		}
+		siz := uintptr(rand.Int() >> (11 + rand.Uint32()%20))
+		base := runtime.Alloc(siz)
+		//	ptr := uintptr(syscall.BytePtr(base))+uintptr(siz/2)
+		//	obj, size, ref, ok := allocator.find(ptr)
+		//	if obj != base || *ref != 0 || !ok {
+		//		println("find", siz, obj, ref, ok)
+		//		panic("fail")
+		//	}
+		blocks[b].base = base
+		blocks[b].siz = siz
+		allocated += uint64(siz)
+		//	println("Alloc", siz, base)
+		memset(base, 0xbb, siz)
+		bigger()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/mallocrep.go b/third_party/gofrontend/libgo/go/runtime/mallocrep.go
new file mode 100644
index 0000000..03ee71e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/mallocrep.go
@@ -0,0 +1,72 @@
+// 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.
+
+// Repeated malloc test.
+
+// +build ignore
+
+package main
+
+import (
+	"flag"
+	"runtime"
+)
+
+var chatty = flag.Bool("v", false, "chatty")
+
+var oldsys uint64
+var memstats runtime.MemStats
+
+func bigger() {
+	st := &memstats
+	runtime.ReadMemStats(st)
+	if oldsys < st.Sys {
+		oldsys = st.Sys
+		if *chatty {
+			println(st.Sys, " system bytes for ", st.Alloc, " Go bytes")
+		}
+		if st.Sys > 1e9 {
+			println("too big")
+			panic("fail")
+		}
+	}
+}
+
+func main() {
+	runtime.GC()                    // clean up garbage from init
+	runtime.ReadMemStats(&memstats) // first call can do some allocations
+	runtime.MemProfileRate = 0      // disable profiler
+	stacks := memstats.Alloc        // ignore stacks
+	flag.Parse()
+	for i := 0; i < 1<<7; i++ {
+		for j := 1; j <= 1<<22; j <<= 1 {
+			if i == 0 && *chatty {
+				println("First alloc:", j)
+			}
+			if a := memstats.Alloc - stacks; a != 0 {
+				println("no allocations but stats report", a, "bytes allocated")
+				panic("fail")
+			}
+			b := runtime.Alloc(uintptr(j))
+			runtime.ReadMemStats(&memstats)
+			during := memstats.Alloc - stacks
+			runtime.Free(b)
+			runtime.ReadMemStats(&memstats)
+			if a := memstats.Alloc - stacks; a != 0 {
+				println("allocated ", j, ": wrong stats: during=", during, " after=", a, " (want 0)")
+				panic("fail")
+			}
+			bigger()
+		}
+		if i%(1<<10) == 0 && *chatty {
+			println(i)
+		}
+		if i == 0 {
+			if *chatty {
+				println("Primed", i)
+			}
+			//	runtime.frozen = true
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/mallocrep1.go b/third_party/gofrontend/libgo/go/runtime/mallocrep1.go
new file mode 100644
index 0000000..bc33e3a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/mallocrep1.go
@@ -0,0 +1,144 @@
+// 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.
+
+// +build ignore
+
+// Repeated malloc test.
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"runtime"
+	"strconv"
+)
+
+var chatty = flag.Bool("v", false, "chatty")
+var reverse = flag.Bool("r", false, "reverse")
+var longtest = flag.Bool("l", false, "long test")
+
+var b []*byte
+var stats = new(runtime.MemStats)
+
+func OkAmount(size, n uintptr) bool {
+	if n < size {
+		return false
+	}
+	if size < 16*8 {
+		if n > size+16 {
+			return false
+		}
+	} else {
+		if n > size*9/8 {
+			return false
+		}
+	}
+	return true
+}
+
+func AllocAndFree(size, count int) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
+	if *chatty {
+		fmt.Printf("size=%d count=%d ...\n", size, count)
+	}
+	runtime.ReadMemStats(stats)
+	n1 := stats.Alloc
+	for i := 0; i < count; i++ {
+		b[i] = runtime.Alloc(uintptr(size))
+		base, n := runtime.Lookup(b[i])
+		if base != b[i] || !OkAmount(uintptr(size), n) {
+			println("lookup failed: got", base, n, "for", b[i])
+			panic("fail")
+		}
+		runtime.ReadMemStats(stats)
+		if stats.Sys > 1e9 {
+			println("too much memory allocated")
+			panic("fail")
+		}
+	}
+	runtime.ReadMemStats(stats)
+	n2 := stats.Alloc
+	if *chatty {
+		fmt.Printf("size=%d count=%d stats=%+v\n", size, count, *stats)
+	}
+	n3 := stats.Alloc
+	for j := 0; j < count; j++ {
+		i := j
+		if *reverse {
+			i = count - 1 - j
+		}
+		alloc := uintptr(stats.Alloc)
+		base, n := runtime.Lookup(b[i])
+		if base != b[i] || !OkAmount(uintptr(size), n) {
+			println("lookup failed: got", base, n, "for", b[i])
+			panic("fail")
+		}
+		runtime.Free(b[i])
+		runtime.ReadMemStats(stats)
+		if stats.Alloc != uint64(alloc-n) {
+			println("free alloc got", stats.Alloc, "expected", alloc-n, "after free of", n)
+			panic("fail")
+		}
+		if stats.Sys > 1e9 {
+			println("too much memory allocated")
+			panic("fail")
+		}
+	}
+	runtime.ReadMemStats(stats)
+	n4 := stats.Alloc
+
+	if *chatty {
+		fmt.Printf("size=%d count=%d stats=%+v\n", size, count, *stats)
+	}
+	if n2-n1 != n3-n4 {
+		println("wrong alloc count: ", n2-n1, n3-n4)
+		panic("fail")
+	}
+}
+
+func atoi(s string) int {
+	i, _ := strconv.Atoi(s)
+	return i
+}
+
+func main() {
+	runtime.MemProfileRate = 0 // disable profiler
+	flag.Parse()
+	b = make([]*byte, 10000)
+	if flag.NArg() > 0 {
+		AllocAndFree(atoi(flag.Arg(0)), atoi(flag.Arg(1)))
+		return
+	}
+	maxb := 1 << 22
+	if !*longtest {
+		maxb = 1 << 19
+	}
+	for j := 1; j <= maxb; j <<= 1 {
+		n := len(b)
+		max := uintptr(1 << 28)
+		if !*longtest {
+			max = uintptr(maxb)
+		}
+		if uintptr(j)*uintptr(n) > max {
+			n = int(max / uintptr(j))
+		}
+		if n < 10 {
+			n = 10
+		}
+		for m := 1; m <= n; {
+			AllocAndFree(j, m)
+			if m == n {
+				break
+			}
+			m = 5 * m / 4
+			if m < 4 {
+				m++
+			}
+			if m > n {
+				m = n
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/map_test.go b/third_party/gofrontend/libgo/go/runtime/map_test.go
new file mode 100644
index 0000000..d969025
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/map_test.go
@@ -0,0 +1,491 @@
+// Copyright 2013 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 runtime_test
+
+import (
+	"fmt"
+	"math"
+	"reflect"
+	"runtime"
+	"sort"
+	"strings"
+	"sync"
+	"testing"
+)
+
+// negative zero is a good test because:
+//  1) 0 and -0 are equal, yet have distinct representations.
+//  2) 0 is represented as all zeros, -0 isn't.
+// I'm not sure the language spec actually requires this behavior,
+// but it's what the current map implementation does.
+func TestNegativeZero(t *testing.T) {
+	m := make(map[float64]bool, 0)
+
+	m[+0.0] = true
+	m[math.Copysign(0.0, -1.0)] = true // should overwrite +0 entry
+
+	if len(m) != 1 {
+		t.Error("length wrong")
+	}
+
+	/* gccgo fails this test; this is not required by the spec.
+	for k := range m {
+		if math.Copysign(1.0, k) > 0 {
+			t.Error("wrong sign")
+		}
+	}
+	*/
+
+	m = make(map[float64]bool, 0)
+	m[math.Copysign(0.0, -1.0)] = true
+	m[+0.0] = true // should overwrite -0.0 entry
+
+	if len(m) != 1 {
+		t.Error("length wrong")
+	}
+
+	/* gccgo fails this test; this is not required by the spec.
+	for k := range m {
+		if math.Copysign(1.0, k) < 0 {
+			t.Error("wrong sign")
+		}
+	}
+	*/
+}
+
+// nan is a good test because nan != nan, and nan has
+// a randomized hash value.
+func TestNan(t *testing.T) {
+	m := make(map[float64]int, 0)
+	nan := math.NaN()
+	m[nan] = 1
+	m[nan] = 2
+	m[nan] = 4
+	if len(m) != 3 {
+		t.Error("length wrong")
+	}
+	s := 0
+	for k, v := range m {
+		if k == k {
+			t.Error("nan disappeared")
+		}
+		if (v & (v - 1)) != 0 {
+			t.Error("value wrong")
+		}
+		s |= v
+	}
+	if s != 7 {
+		t.Error("values wrong")
+	}
+}
+
+// Maps aren't actually copied on assignment.
+func TestAlias(t *testing.T) {
+	m := make(map[int]int, 0)
+	m[0] = 5
+	n := m
+	n[0] = 6
+	if m[0] != 6 {
+		t.Error("alias didn't work")
+	}
+}
+
+func TestGrowWithNaN(t *testing.T) {
+	t.Skip("fails with gccgo")
+	m := make(map[float64]int, 4)
+	nan := math.NaN()
+	m[nan] = 1
+	m[nan] = 2
+	m[nan] = 4
+	cnt := 0
+	s := 0
+	growflag := true
+	for k, v := range m {
+		if growflag {
+			// force a hashtable resize
+			for i := 0; i < 100; i++ {
+				m[float64(i)] = i
+			}
+			growflag = false
+		}
+		if k != k {
+			cnt++
+			s |= v
+		}
+	}
+	t.Log("cnt:", cnt, "s:", s)
+	if cnt != 3 {
+		t.Error("NaN keys lost during grow")
+	}
+	if s != 7 {
+		t.Error("NaN values lost during grow")
+	}
+}
+
+type FloatInt struct {
+	x float64
+	y int
+}
+
+func TestGrowWithNegativeZero(t *testing.T) {
+	t.Skip("fails with gccgo")
+	negzero := math.Copysign(0.0, -1.0)
+	m := make(map[FloatInt]int, 4)
+	m[FloatInt{0.0, 0}] = 1
+	m[FloatInt{0.0, 1}] = 2
+	m[FloatInt{0.0, 2}] = 4
+	m[FloatInt{0.0, 3}] = 8
+	growflag := true
+	s := 0
+	cnt := 0
+	negcnt := 0
+	// The first iteration should return the +0 key.
+	// The subsequent iterations should return the -0 key.
+	// I'm not really sure this is required by the spec,
+	// but it makes sense.
+	// TODO: are we allowed to get the first entry returned again???
+	for k, v := range m {
+		if v == 0 {
+			continue
+		} // ignore entries added to grow table
+		cnt++
+		if math.Copysign(1.0, k.x) < 0 {
+			if v&16 == 0 {
+				t.Error("key/value not updated together 1")
+			}
+			negcnt++
+			s |= v & 15
+		} else {
+			if v&16 == 16 {
+				t.Error("key/value not updated together 2", k, v)
+			}
+			s |= v
+		}
+		if growflag {
+			// force a hashtable resize
+			for i := 0; i < 100; i++ {
+				m[FloatInt{3.0, i}] = 0
+			}
+			// then change all the entries
+			// to negative zero
+			m[FloatInt{negzero, 0}] = 1 | 16
+			m[FloatInt{negzero, 1}] = 2 | 16
+			m[FloatInt{negzero, 2}] = 4 | 16
+			m[FloatInt{negzero, 3}] = 8 | 16
+			growflag = false
+		}
+	}
+	if s != 15 {
+		t.Error("entry missing", s)
+	}
+	if cnt != 4 {
+		t.Error("wrong number of entries returned by iterator", cnt)
+	}
+	if negcnt != 3 {
+		t.Error("update to negzero missed by iteration", negcnt)
+	}
+}
+
+func TestIterGrowAndDelete(t *testing.T) {
+	m := make(map[int]int, 4)
+	for i := 0; i < 100; i++ {
+		m[i] = i
+	}
+	growflag := true
+	for k := range m {
+		if growflag {
+			// grow the table
+			for i := 100; i < 1000; i++ {
+				m[i] = i
+			}
+			// delete all odd keys
+			for i := 1; i < 1000; i += 2 {
+				delete(m, i)
+			}
+			growflag = false
+		} else {
+			if k&1 == 1 {
+				t.Error("odd value returned")
+			}
+		}
+	}
+}
+
+// make sure old bucket arrays don't get GCd while
+// an iterator is still using them.
+func TestIterGrowWithGC(t *testing.T) {
+	m := make(map[int]int, 4)
+	for i := 0; i < 16; i++ {
+		m[i] = i
+	}
+	growflag := true
+	bitmask := 0
+	for k := range m {
+		if k < 16 {
+			bitmask |= 1 << uint(k)
+		}
+		if growflag {
+			// grow the table
+			for i := 100; i < 1000; i++ {
+				m[i] = i
+			}
+			// trigger a gc
+			runtime.GC()
+			growflag = false
+		}
+	}
+	if bitmask != 1<<16-1 {
+		t.Error("missing key", bitmask)
+	}
+}
+
+func testConcurrentReadsAfterGrowth(t *testing.T, useReflect bool) {
+	if runtime.GOMAXPROCS(-1) == 1 {
+		defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(16))
+	}
+	numLoop := 10
+	numGrowStep := 250
+	numReader := 16
+	if testing.Short() {
+		numLoop, numGrowStep = 2, 500
+	}
+	for i := 0; i < numLoop; i++ {
+		m := make(map[int]int, 0)
+		for gs := 0; gs < numGrowStep; gs++ {
+			m[gs] = gs
+			var wg sync.WaitGroup
+			wg.Add(numReader * 2)
+			for nr := 0; nr < numReader; nr++ {
+				go func() {
+					defer wg.Done()
+					for _ = range m {
+					}
+				}()
+				go func() {
+					defer wg.Done()
+					for key := 0; key < gs; key++ {
+						_ = m[key]
+					}
+				}()
+				if useReflect {
+					wg.Add(1)
+					go func() {
+						defer wg.Done()
+						mv := reflect.ValueOf(m)
+						keys := mv.MapKeys()
+						for _, k := range keys {
+							mv.MapIndex(k)
+						}
+					}()
+				}
+			}
+			wg.Wait()
+		}
+	}
+}
+
+func TestConcurrentReadsAfterGrowth(t *testing.T) {
+	testConcurrentReadsAfterGrowth(t, false)
+}
+
+func TestConcurrentReadsAfterGrowthReflect(t *testing.T) {
+	testConcurrentReadsAfterGrowth(t, true)
+}
+
+func TestBigItems(t *testing.T) {
+	var key [256]string
+	for i := 0; i < 256; i++ {
+		key[i] = "foo"
+	}
+	m := make(map[[256]string][256]string, 4)
+	for i := 0; i < 100; i++ {
+		key[37] = fmt.Sprintf("string%02d", i)
+		m[key] = key
+	}
+	var keys [100]string
+	var values [100]string
+	i := 0
+	for k, v := range m {
+		keys[i] = k[37]
+		values[i] = v[37]
+		i++
+	}
+	sort.Strings(keys[:])
+	sort.Strings(values[:])
+	for i := 0; i < 100; i++ {
+		if keys[i] != fmt.Sprintf("string%02d", i) {
+			t.Errorf("#%d: missing key: %v", i, keys[i])
+		}
+		if values[i] != fmt.Sprintf("string%02d", i) {
+			t.Errorf("#%d: missing value: %v", i, values[i])
+		}
+	}
+}
+
+type empty struct {
+}
+
+func TestEmptyKeyAndValue(t *testing.T) {
+	a := make(map[int]empty, 4)
+	b := make(map[empty]int, 4)
+	c := make(map[empty]empty, 4)
+	a[0] = empty{}
+	b[empty{}] = 0
+	b[empty{}] = 1
+	c[empty{}] = empty{}
+
+	if len(a) != 1 {
+		t.Errorf("empty value insert problem")
+	}
+	if b[empty{}] != 1 {
+		t.Errorf("empty key returned wrong value")
+	}
+}
+
+// Tests a map with a single bucket, with same-lengthed short keys
+// ("quick keys") as well as long keys.
+func TestSingleBucketMapStringKeys_DupLen(t *testing.T) {
+	testMapLookups(t, map[string]string{
+		"x":    "x1val",
+		"xx":   "x2val",
+		"foo":  "fooval",
+		"bar":  "barval", // same key length as "foo"
+		"xxxx": "x4val",
+		strings.Repeat("x", 128): "longval1",
+		strings.Repeat("y", 128): "longval2",
+	})
+}
+
+// Tests a map with a single bucket, with all keys having different lengths.
+func TestSingleBucketMapStringKeys_NoDupLen(t *testing.T) {
+	testMapLookups(t, map[string]string{
+		"x":                      "x1val",
+		"xx":                     "x2val",
+		"foo":                    "fooval",
+		"xxxx":                   "x4val",
+		"xxxxx":                  "x5val",
+		"xxxxxx":                 "x6val",
+		strings.Repeat("x", 128): "longval",
+	})
+}
+
+func testMapLookups(t *testing.T, m map[string]string) {
+	for k, v := range m {
+		if m[k] != v {
+			t.Fatalf("m[%q] = %q; want %q", k, m[k], v)
+		}
+	}
+}
+
+// Tests whether the iterator returns the right elements when
+// started in the middle of a grow, when the keys are NaNs.
+func TestMapNanGrowIterator(t *testing.T) {
+	m := make(map[float64]int)
+	nan := math.NaN()
+	const nBuckets = 16
+	// To fill nBuckets buckets takes LOAD * nBuckets keys.
+	nKeys := int(nBuckets * *runtime.HashLoad)
+
+	// Get map to full point with nan keys.
+	for i := 0; i < nKeys; i++ {
+		m[nan] = i
+	}
+	// Trigger grow
+	m[1.0] = 1
+	delete(m, 1.0)
+
+	// Run iterator
+	found := make(map[int]struct{})
+	for _, v := range m {
+		if v != -1 {
+			if _, repeat := found[v]; repeat {
+				t.Fatalf("repeat of value %d", v)
+			}
+			found[v] = struct{}{}
+		}
+		if len(found) == nKeys/2 {
+			// Halfway through iteration, finish grow.
+			for i := 0; i < nBuckets; i++ {
+				delete(m, 1.0)
+			}
+		}
+	}
+	if len(found) != nKeys {
+		t.Fatalf("missing value")
+	}
+}
+
+func TestMapIterOrder(t *testing.T) {
+	if runtime.Compiler == "gccgo" {
+		t.Skip("skipping for gccgo")
+	}
+
+	for _, n := range [...]int{3, 7, 9, 15} {
+		// Make m be {0: true, 1: true, ..., n-1: true}.
+		m := make(map[int]bool)
+		for i := 0; i < n; i++ {
+			m[i] = true
+		}
+		// Check that iterating over the map produces at least two different orderings.
+		ord := func() []int {
+			var s []int
+			for key := range m {
+				s = append(s, key)
+			}
+			return s
+		}
+		first := ord()
+		ok := false
+		for try := 0; try < 100; try++ {
+			if !reflect.DeepEqual(first, ord()) {
+				ok = true
+				break
+			}
+		}
+		if !ok {
+			t.Errorf("Map with n=%d elements had consistent iteration order: %v", n, first)
+		}
+	}
+}
+
+func TestMapStringBytesLookup(t *testing.T) {
+	if runtime.Compiler == "gccgo" {
+		t.Skip("skipping for gccgo")
+	}
+	// Use large string keys to avoid small-allocation coalescing,
+	// which can cause AllocsPerRun to report lower counts than it should.
+	m := map[string]int{
+		"1000000000000000000000000000000000000000000000000": 1,
+		"2000000000000000000000000000000000000000000000000": 2,
+	}
+	buf := []byte("1000000000000000000000000000000000000000000000000")
+	if x := m[string(buf)]; x != 1 {
+		t.Errorf(`m[string([]byte("1"))] = %d, want 1`, x)
+	}
+	buf[0] = '2'
+	if x := m[string(buf)]; x != 2 {
+		t.Errorf(`m[string([]byte("2"))] = %d, want 2`, x)
+	}
+
+	var x int
+	n := testing.AllocsPerRun(100, func() {
+		x += m[string(buf)]
+	})
+	if n != 0 {
+		t.Errorf("AllocsPerRun for m[string(buf)] = %v, want 0", n)
+	}
+
+	x = 0
+	n = testing.AllocsPerRun(100, func() {
+		y, ok := m[string(buf)]
+		if !ok {
+			panic("!ok")
+		}
+		x += y
+	})
+	if n != 0 {
+		t.Errorf("AllocsPerRun for x,ok = m[string(buf)] = %v, want 0", n)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/mapspeed_test.go b/third_party/gofrontend/libgo/go/runtime/mapspeed_test.go
new file mode 100644
index 0000000..da45ea1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/mapspeed_test.go
@@ -0,0 +1,300 @@
+// Copyright 2013 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 runtime_test
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+)
+
+const size = 10
+
+func BenchmarkHashStringSpeed(b *testing.B) {
+	strings := make([]string, size)
+	for i := 0; i < size; i++ {
+		strings[i] = fmt.Sprintf("string#%d", i)
+	}
+	sum := 0
+	m := make(map[string]int, size)
+	for i := 0; i < size; i++ {
+		m[strings[i]] = 0
+	}
+	idx := 0
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		sum += m[strings[idx]]
+		idx++
+		if idx == size {
+			idx = 0
+		}
+	}
+}
+
+type chunk [17]byte
+
+func BenchmarkHashBytesSpeed(b *testing.B) {
+	// a bunch of chunks, each with a different alignment mod 16
+	var chunks [size]chunk
+	// initialize each to a different value
+	for i := 0; i < size; i++ {
+		chunks[i][0] = byte(i)
+	}
+	// put into a map
+	m := make(map[chunk]int, size)
+	for i, c := range chunks {
+		m[c] = i
+	}
+	idx := 0
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		if m[chunks[idx]] != idx {
+			b.Error("bad map entry for chunk")
+		}
+		idx++
+		if idx == size {
+			idx = 0
+		}
+	}
+}
+
+func BenchmarkHashInt32Speed(b *testing.B) {
+	ints := make([]int32, size)
+	for i := 0; i < size; i++ {
+		ints[i] = int32(i)
+	}
+	sum := 0
+	m := make(map[int32]int, size)
+	for i := 0; i < size; i++ {
+		m[ints[i]] = 0
+	}
+	idx := 0
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		sum += m[ints[idx]]
+		idx++
+		if idx == size {
+			idx = 0
+		}
+	}
+}
+
+func BenchmarkHashInt64Speed(b *testing.B) {
+	ints := make([]int64, size)
+	for i := 0; i < size; i++ {
+		ints[i] = int64(i)
+	}
+	sum := 0
+	m := make(map[int64]int, size)
+	for i := 0; i < size; i++ {
+		m[ints[i]] = 0
+	}
+	idx := 0
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		sum += m[ints[idx]]
+		idx++
+		if idx == size {
+			idx = 0
+		}
+	}
+}
+func BenchmarkHashStringArraySpeed(b *testing.B) {
+	stringpairs := make([][2]string, size)
+	for i := 0; i < size; i++ {
+		for j := 0; j < 2; j++ {
+			stringpairs[i][j] = fmt.Sprintf("string#%d/%d", i, j)
+		}
+	}
+	sum := 0
+	m := make(map[[2]string]int, size)
+	for i := 0; i < size; i++ {
+		m[stringpairs[i]] = 0
+	}
+	idx := 0
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		sum += m[stringpairs[idx]]
+		idx++
+		if idx == size {
+			idx = 0
+		}
+	}
+}
+
+func BenchmarkMegMap(b *testing.B) {
+	m := make(map[string]bool)
+	for suffix := 'A'; suffix <= 'G'; suffix++ {
+		m[strings.Repeat("X", 1<<20-1)+fmt.Sprint(suffix)] = true
+	}
+	key := strings.Repeat("X", 1<<20-1) + "k"
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, _ = m[key]
+	}
+}
+
+func BenchmarkMegOneMap(b *testing.B) {
+	m := make(map[string]bool)
+	m[strings.Repeat("X", 1<<20)] = true
+	key := strings.Repeat("Y", 1<<20)
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, _ = m[key]
+	}
+}
+
+func BenchmarkMegEqMap(b *testing.B) {
+	m := make(map[string]bool)
+	key1 := strings.Repeat("X", 1<<20)
+	key2 := strings.Repeat("X", 1<<20) // equal but different instance
+	m[key1] = true
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, _ = m[key2]
+	}
+}
+
+func BenchmarkMegEmptyMap(b *testing.B) {
+	m := make(map[string]bool)
+	key := strings.Repeat("X", 1<<20)
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, _ = m[key]
+	}
+}
+
+func BenchmarkSmallStrMap(b *testing.B) {
+	m := make(map[string]bool)
+	for suffix := 'A'; suffix <= 'G'; suffix++ {
+		m[fmt.Sprint(suffix)] = true
+	}
+	key := "k"
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, _ = m[key]
+	}
+}
+
+func BenchmarkMapStringKeysEight_16(b *testing.B) { benchmarkMapStringKeysEight(b, 16) }
+func BenchmarkMapStringKeysEight_32(b *testing.B) { benchmarkMapStringKeysEight(b, 32) }
+func BenchmarkMapStringKeysEight_64(b *testing.B) { benchmarkMapStringKeysEight(b, 64) }
+func BenchmarkMapStringKeysEight_1M(b *testing.B) { benchmarkMapStringKeysEight(b, 1<<20) }
+
+func benchmarkMapStringKeysEight(b *testing.B, keySize int) {
+	m := make(map[string]bool)
+	for i := 0; i < 8; i++ {
+		m[strings.Repeat("K", i+1)] = true
+	}
+	key := strings.Repeat("K", keySize)
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_ = m[key]
+	}
+}
+
+func BenchmarkIntMap(b *testing.B) {
+	m := make(map[int]bool)
+	for i := 0; i < 8; i++ {
+		m[i] = true
+	}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, _ = m[7]
+	}
+}
+
+// Accessing the same keys in a row.
+func benchmarkRepeatedLookup(b *testing.B, lookupKeySize int) {
+	m := make(map[string]bool)
+	// At least bigger than a single bucket:
+	for i := 0; i < 64; i++ {
+		m[fmt.Sprintf("some key %d", i)] = true
+	}
+	base := strings.Repeat("x", lookupKeySize-1)
+	key1 := base + "1"
+	key2 := base + "2"
+	b.ResetTimer()
+	for i := 0; i < b.N/4; i++ {
+		_ = m[key1]
+		_ = m[key1]
+		_ = m[key2]
+		_ = m[key2]
+	}
+}
+
+func BenchmarkRepeatedLookupStrMapKey32(b *testing.B) { benchmarkRepeatedLookup(b, 32) }
+func BenchmarkRepeatedLookupStrMapKey1M(b *testing.B) { benchmarkRepeatedLookup(b, 1<<20) }
+
+func BenchmarkNewEmptyMap(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		_ = make(map[int]int)
+	}
+}
+
+func BenchmarkMapIter(b *testing.B) {
+	m := make(map[int]bool)
+	for i := 0; i < 8; i++ {
+		m[i] = true
+	}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		for _, _ = range m {
+		}
+	}
+}
+
+func BenchmarkMapIterEmpty(b *testing.B) {
+	m := make(map[int]bool)
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		for _, _ = range m {
+		}
+	}
+}
+
+func BenchmarkSameLengthMap(b *testing.B) {
+	// long strings, same length, differ in first few
+	// and last few bytes.
+	m := make(map[string]bool)
+	s1 := "foo" + strings.Repeat("-", 100) + "bar"
+	s2 := "goo" + strings.Repeat("-", 100) + "ber"
+	m[s1] = true
+	m[s2] = true
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_ = m[s1]
+	}
+}
+
+type BigKey [3]int64
+
+func BenchmarkBigKeyMap(b *testing.B) {
+	m := make(map[BigKey]bool)
+	k := BigKey{3, 4, 5}
+	m[k] = true
+	for i := 0; i < b.N; i++ {
+		_ = m[k]
+	}
+}
+
+type BigVal [3]int64
+
+func BenchmarkBigValMap(b *testing.B) {
+	m := make(map[BigKey]BigVal)
+	k := BigKey{3, 4, 5}
+	m[k] = BigVal{6, 7, 8}
+	for i := 0; i < b.N; i++ {
+		_ = m[k]
+	}
+}
+
+func BenchmarkSmallKeyMap(b *testing.B) {
+	m := make(map[int16]bool)
+	m[5] = true
+	for i := 0; i < b.N; i++ {
+		_ = m[5]
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/mem.go b/third_party/gofrontend/libgo/go/runtime/mem.go
new file mode 100644
index 0000000..fb35535
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/mem.go
@@ -0,0 +1,75 @@
+// 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 runtime
+
+import "unsafe"
+
+// Note: the MemStats struct should be kept in sync with
+// struct MStats in malloc.h
+
+// A MemStats records statistics about the memory allocator.
+type MemStats struct {
+	// General statistics.
+	Alloc      uint64 // bytes allocated and still in use
+	TotalAlloc uint64 // bytes allocated (even if freed)
+	Sys        uint64 // bytes obtained from system (sum of XxxSys below)
+	Lookups    uint64 // number of pointer lookups
+	Mallocs    uint64 // number of mallocs
+	Frees      uint64 // number of frees
+
+	// Main allocation heap statistics.
+	HeapAlloc    uint64 // bytes allocated and still in use
+	HeapSys      uint64 // bytes obtained from system
+	HeapIdle     uint64 // bytes in idle spans
+	HeapInuse    uint64 // bytes in non-idle span
+	HeapReleased uint64 // bytes released to the OS
+	HeapObjects  uint64 // total number of allocated objects
+
+	// Low-level fixed-size structure allocator statistics.
+	//	Inuse is bytes used now.
+	//	Sys is bytes obtained from system.
+	StackInuse  uint64 // bootstrap stacks
+	StackSys    uint64
+	MSpanInuse  uint64 // mspan structures
+	MSpanSys    uint64
+	MCacheInuse uint64 // mcache structures
+	MCacheSys   uint64
+	BuckHashSys uint64 // profiling bucket hash table
+	GCSys       uint64 // GC metadata
+	OtherSys    uint64 // other system allocations
+
+	// Garbage collector statistics.
+	NextGC       uint64 // next run in HeapAlloc time (bytes)
+	LastGC       uint64 // last run in absolute time (ns)
+	PauseTotalNs uint64
+	PauseNs      [256]uint64 // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
+	NumGC        uint32
+	EnableGC     bool
+	DebugGC      bool
+
+	// Per-size allocation statistics.
+	// 61 is NumSizeClasses in the C code.
+	BySize [61]struct {
+		Size    uint32
+		Mallocs uint64
+		Frees   uint64
+	}
+}
+
+var Sizeof_C_MStats uintptr // filled in by malloc.goc
+
+func init() {
+	var memStats MemStats
+	if Sizeof_C_MStats != unsafe.Sizeof(memStats) {
+		println(Sizeof_C_MStats, unsafe.Sizeof(memStats))
+		panic("MStats vs MemStatsType size mismatch")
+	}
+}
+
+// ReadMemStats populates m with memory allocator statistics.
+func ReadMemStats(m *MemStats)
+
+// GC runs a garbage collection.
+func GC()
diff --git a/third_party/gofrontend/libgo/go/runtime/memmove_test.go b/third_party/gofrontend/libgo/go/runtime/memmove_test.go
new file mode 100644
index 0000000..540f0fe
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/memmove_test.go
@@ -0,0 +1,243 @@
+// Copyright 2013 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 runtime_test
+
+import (
+	. "runtime"
+	"testing"
+)
+
+func TestMemmove(t *testing.T) {
+	size := 256
+	if testing.Short() {
+		size = 128 + 16
+	}
+	src := make([]byte, size)
+	dst := make([]byte, size)
+	for i := 0; i < size; i++ {
+		src[i] = byte(128 + (i & 127))
+	}
+	for i := 0; i < size; i++ {
+		dst[i] = byte(i & 127)
+	}
+	for n := 0; n <= size; n++ {
+		for x := 0; x <= size-n; x++ { // offset in src
+			for y := 0; y <= size-n; y++ { // offset in dst
+				copy(dst[y:y+n], src[x:x+n])
+				for i := 0; i < y; i++ {
+					if dst[i] != byte(i&127) {
+						t.Fatalf("prefix dst[%d] = %d", i, dst[i])
+					}
+				}
+				for i := y; i < y+n; i++ {
+					if dst[i] != byte(128+((i-y+x)&127)) {
+						t.Fatalf("copied dst[%d] = %d", i, dst[i])
+					}
+					dst[i] = byte(i & 127) // reset dst
+				}
+				for i := y + n; i < size; i++ {
+					if dst[i] != byte(i&127) {
+						t.Fatalf("suffix dst[%d] = %d", i, dst[i])
+					}
+				}
+			}
+		}
+	}
+}
+
+func TestMemmoveAlias(t *testing.T) {
+	size := 256
+	if testing.Short() {
+		size = 128 + 16
+	}
+	buf := make([]byte, size)
+	for i := 0; i < size; i++ {
+		buf[i] = byte(i)
+	}
+	for n := 0; n <= size; n++ {
+		for x := 0; x <= size-n; x++ { // src offset
+			for y := 0; y <= size-n; y++ { // dst offset
+				copy(buf[y:y+n], buf[x:x+n])
+				for i := 0; i < y; i++ {
+					if buf[i] != byte(i) {
+						t.Fatalf("prefix buf[%d] = %d", i, buf[i])
+					}
+				}
+				for i := y; i < y+n; i++ {
+					if buf[i] != byte(i-y+x) {
+						t.Fatalf("copied buf[%d] = %d", i, buf[i])
+					}
+					buf[i] = byte(i) // reset buf
+				}
+				for i := y + n; i < size; i++ {
+					if buf[i] != byte(i) {
+						t.Fatalf("suffix buf[%d] = %d", i, buf[i])
+					}
+				}
+			}
+		}
+	}
+}
+
+func bmMemmove(b *testing.B, n int) {
+	x := make([]byte, n)
+	y := make([]byte, n)
+	b.SetBytes(int64(n))
+	for i := 0; i < b.N; i++ {
+		copy(x, y)
+	}
+}
+
+func BenchmarkMemmove0(b *testing.B)    { bmMemmove(b, 0) }
+func BenchmarkMemmove1(b *testing.B)    { bmMemmove(b, 1) }
+func BenchmarkMemmove2(b *testing.B)    { bmMemmove(b, 2) }
+func BenchmarkMemmove3(b *testing.B)    { bmMemmove(b, 3) }
+func BenchmarkMemmove4(b *testing.B)    { bmMemmove(b, 4) }
+func BenchmarkMemmove5(b *testing.B)    { bmMemmove(b, 5) }
+func BenchmarkMemmove6(b *testing.B)    { bmMemmove(b, 6) }
+func BenchmarkMemmove7(b *testing.B)    { bmMemmove(b, 7) }
+func BenchmarkMemmove8(b *testing.B)    { bmMemmove(b, 8) }
+func BenchmarkMemmove9(b *testing.B)    { bmMemmove(b, 9) }
+func BenchmarkMemmove10(b *testing.B)   { bmMemmove(b, 10) }
+func BenchmarkMemmove11(b *testing.B)   { bmMemmove(b, 11) }
+func BenchmarkMemmove12(b *testing.B)   { bmMemmove(b, 12) }
+func BenchmarkMemmove13(b *testing.B)   { bmMemmove(b, 13) }
+func BenchmarkMemmove14(b *testing.B)   { bmMemmove(b, 14) }
+func BenchmarkMemmove15(b *testing.B)   { bmMemmove(b, 15) }
+func BenchmarkMemmove16(b *testing.B)   { bmMemmove(b, 16) }
+func BenchmarkMemmove32(b *testing.B)   { bmMemmove(b, 32) }
+func BenchmarkMemmove64(b *testing.B)   { bmMemmove(b, 64) }
+func BenchmarkMemmove128(b *testing.B)  { bmMemmove(b, 128) }
+func BenchmarkMemmove256(b *testing.B)  { bmMemmove(b, 256) }
+func BenchmarkMemmove512(b *testing.B)  { bmMemmove(b, 512) }
+func BenchmarkMemmove1024(b *testing.B) { bmMemmove(b, 1024) }
+func BenchmarkMemmove2048(b *testing.B) { bmMemmove(b, 2048) }
+func BenchmarkMemmove4096(b *testing.B) { bmMemmove(b, 4096) }
+
+func TestMemclr(t *testing.T) {
+	size := 512
+	if testing.Short() {
+		size = 128 + 16
+	}
+	mem := make([]byte, size)
+	for i := 0; i < size; i++ {
+		mem[i] = 0xee
+	}
+	for n := 0; n < size; n++ {
+		for x := 0; x <= size-n; x++ { // offset in mem
+			MemclrBytes(mem[x : x+n])
+			for i := 0; i < x; i++ {
+				if mem[i] != 0xee {
+					t.Fatalf("overwrite prefix mem[%d] = %d", i, mem[i])
+				}
+			}
+			for i := x; i < x+n; i++ {
+				if mem[i] != 0 {
+					t.Fatalf("failed clear mem[%d] = %d", i, mem[i])
+				}
+				mem[i] = 0xee
+			}
+			for i := x + n; i < size; i++ {
+				if mem[i] != 0xee {
+					t.Fatalf("overwrite suffix mem[%d] = %d", i, mem[i])
+				}
+			}
+		}
+	}
+}
+
+func bmMemclr(b *testing.B, n int) {
+	x := make([]byte, n)
+	b.SetBytes(int64(n))
+	for i := 0; i < b.N; i++ {
+		MemclrBytes(x)
+	}
+}
+func BenchmarkMemclr5(b *testing.B)     { bmMemclr(b, 5) }
+func BenchmarkMemclr16(b *testing.B)    { bmMemclr(b, 16) }
+func BenchmarkMemclr64(b *testing.B)    { bmMemclr(b, 64) }
+func BenchmarkMemclr256(b *testing.B)   { bmMemclr(b, 256) }
+func BenchmarkMemclr4096(b *testing.B)  { bmMemclr(b, 4096) }
+func BenchmarkMemclr65536(b *testing.B) { bmMemclr(b, 65536) }
+
+func BenchmarkClearFat32(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		var x [32]byte
+		_ = x
+	}
+}
+func BenchmarkClearFat64(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		var x [64]byte
+		_ = x
+	}
+}
+func BenchmarkClearFat128(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		var x [128]byte
+		_ = x
+	}
+}
+func BenchmarkClearFat256(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		var x [256]byte
+		_ = x
+	}
+}
+func BenchmarkClearFat512(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		var x [512]byte
+		_ = x
+	}
+}
+func BenchmarkClearFat1024(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		var x [1024]byte
+		_ = x
+	}
+}
+
+func BenchmarkCopyFat32(b *testing.B) {
+	var x [32 / 4]uint32
+	for i := 0; i < b.N; i++ {
+		y := x
+		_ = y
+	}
+}
+func BenchmarkCopyFat64(b *testing.B) {
+	var x [64 / 4]uint32
+	for i := 0; i < b.N; i++ {
+		y := x
+		_ = y
+	}
+}
+func BenchmarkCopyFat128(b *testing.B) {
+	var x [128 / 4]uint32
+	for i := 0; i < b.N; i++ {
+		y := x
+		_ = y
+	}
+}
+func BenchmarkCopyFat256(b *testing.B) {
+	var x [256 / 4]uint32
+	for i := 0; i < b.N; i++ {
+		y := x
+		_ = y
+	}
+}
+func BenchmarkCopyFat512(b *testing.B) {
+	var x [512 / 4]uint32
+	for i := 0; i < b.N; i++ {
+		y := x
+		_ = y
+	}
+}
+func BenchmarkCopyFat1024(b *testing.B) {
+	var x [1024 / 4]uint32
+	for i := 0; i < b.N; i++ {
+		y := x
+		_ = y
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/mfinal_test.go b/third_party/gofrontend/libgo/go/runtime/mfinal_test.go
new file mode 100644
index 0000000..b47f83c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/mfinal_test.go
@@ -0,0 +1,243 @@
+// 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.
+
+package runtime_test
+
+import (
+	"runtime"
+	"testing"
+	"time"
+	"unsafe"
+)
+
+type Tintptr *int // assignable to *int
+type Tint int     // *Tint implements Tinter, interface{}
+
+func (t *Tint) m() {}
+
+type Tinter interface {
+	m()
+}
+
+func TestFinalizerType(t *testing.T) {
+	if runtime.GOARCH != "amd64" {
+		t.Skipf("Skipping on non-amd64 machine")
+	}
+
+	ch := make(chan bool, 10)
+	finalize := func(x *int) {
+		if *x != 97531 {
+			t.Errorf("finalizer %d, want %d", *x, 97531)
+		}
+		ch <- true
+	}
+
+	var finalizerTests = []struct {
+		convert   func(*int) interface{}
+		finalizer interface{}
+	}{
+		{func(x *int) interface{} { return x }, func(v *int) { finalize(v) }},
+		{func(x *int) interface{} { return Tintptr(x) }, func(v Tintptr) { finalize(v) }},
+		{func(x *int) interface{} { return Tintptr(x) }, func(v *int) { finalize(v) }},
+		{func(x *int) interface{} { return (*Tint)(x) }, func(v *Tint) { finalize((*int)(v)) }},
+		{func(x *int) interface{} { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }},
+	}
+
+	for _, tt := range finalizerTests {
+		done := make(chan bool, 1)
+		go func() {
+			v := new(int)
+			*v = 97531
+			runtime.SetFinalizer(tt.convert(v), tt.finalizer)
+			v = nil
+			done <- true
+		}()
+		<-done
+		runtime.GC()
+		select {
+		case <-ch:
+		case <-time.After(time.Second * 4):
+			t.Errorf("finalizer for type %T didn't run", tt.finalizer)
+		}
+	}
+}
+
+type bigValue struct {
+	fill uint64
+	it   bool
+	up   string
+}
+
+func TestFinalizerInterfaceBig(t *testing.T) {
+	if runtime.GOARCH != "amd64" {
+		t.Skipf("Skipping on non-amd64 machine")
+	}
+	ch := make(chan bool)
+	done := make(chan bool, 1)
+	go func() {
+		v := &bigValue{0xDEADBEEFDEADBEEF, true, "It matters not how strait the gate"}
+		old := *v
+		runtime.SetFinalizer(v, func(v interface{}) {
+			i, ok := v.(*bigValue)
+			if !ok {
+				t.Errorf("finalizer called with type %T, want *bigValue", v)
+			}
+			if *i != old {
+				t.Errorf("finalizer called with %+v, want %+v", *i, old)
+			}
+			close(ch)
+		})
+		v = nil
+		done <- true
+	}()
+	<-done
+	runtime.GC()
+	select {
+	case <-ch:
+	case <-time.After(4 * time.Second):
+		t.Errorf("finalizer for type *bigValue didn't run")
+	}
+}
+
+func fin(v *int) {
+}
+
+// Verify we don't crash at least. golang.org/issue/6857
+func TestFinalizerZeroSizedStruct(t *testing.T) {
+	type Z struct{}
+	z := new(Z)
+	runtime.SetFinalizer(z, func(*Z) {})
+}
+
+func BenchmarkFinalizer(b *testing.B) {
+	const Batch = 1000
+	b.RunParallel(func(pb *testing.PB) {
+		var data [Batch]*int
+		for i := 0; i < Batch; i++ {
+			data[i] = new(int)
+		}
+		for pb.Next() {
+			for i := 0; i < Batch; i++ {
+				runtime.SetFinalizer(data[i], fin)
+			}
+			for i := 0; i < Batch; i++ {
+				runtime.SetFinalizer(data[i], nil)
+			}
+		}
+	})
+}
+
+func BenchmarkFinalizerRun(b *testing.B) {
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			v := new(int)
+			runtime.SetFinalizer(v, fin)
+		}
+	})
+}
+
+// One chunk must be exactly one sizeclass in size.
+// It should be a sizeclass not used much by others, so we
+// have a greater chance of finding adjacent ones.
+// size class 19: 320 byte objects, 25 per page, 1 page alloc at a time
+const objsize = 320
+
+type objtype [objsize]byte
+
+func adjChunks() (*objtype, *objtype) {
+	var s []*objtype
+
+	for {
+		c := new(objtype)
+		for _, d := range s {
+			if uintptr(unsafe.Pointer(c))+unsafe.Sizeof(*c) == uintptr(unsafe.Pointer(d)) {
+				return c, d
+			}
+			if uintptr(unsafe.Pointer(d))+unsafe.Sizeof(*c) == uintptr(unsafe.Pointer(c)) {
+				return d, c
+			}
+		}
+		s = append(s, c)
+	}
+}
+
+// Make sure an empty slice on the stack doesn't pin the next object in memory.
+func TestEmptySlice(t *testing.T) {
+	if true { // disable until bug 7564 is fixed.
+		return
+	}
+	x, y := adjChunks()
+
+	// the pointer inside xs points to y.
+	xs := x[objsize:] // change objsize to objsize-1 and the test passes
+
+	fin := make(chan bool, 1)
+	runtime.SetFinalizer(y, func(z *objtype) { fin <- true })
+	runtime.GC()
+	select {
+	case <-fin:
+	case <-time.After(4 * time.Second):
+		t.Errorf("finalizer of next object in memory didn't run")
+	}
+	xsglobal = xs // keep empty slice alive until here
+}
+
+var xsglobal []byte
+
+func adjStringChunk() (string, *objtype) {
+	b := make([]byte, objsize)
+	for {
+		s := string(b)
+		t := new(objtype)
+		p := *(*uintptr)(unsafe.Pointer(&s))
+		q := uintptr(unsafe.Pointer(t))
+		if p+objsize == q {
+			return s, t
+		}
+	}
+}
+
+// Make sure an empty string on the stack doesn't pin the next object in memory.
+func TestEmptyString(t *testing.T) {
+	if runtime.Compiler == "gccgo" {
+		t.Skip("skipping for gccgo")
+	}
+
+	x, y := adjStringChunk()
+
+	ss := x[objsize:] // change objsize to objsize-1 and the test passes
+	fin := make(chan bool, 1)
+	// set finalizer on string contents of y
+	runtime.SetFinalizer(y, func(z *objtype) { fin <- true })
+	runtime.GC()
+	select {
+	case <-fin:
+	case <-time.After(4 * time.Second):
+		t.Errorf("finalizer of next string in memory didn't run")
+	}
+	ssglobal = ss // keep 0-length string live until here
+}
+
+var ssglobal string
+
+// Test for issue 7656.
+func TestFinalizerOnGlobal(t *testing.T) {
+	runtime.SetFinalizer(Foo1, func(p *Object1) {})
+	runtime.SetFinalizer(Foo2, func(p *Object2) {})
+	runtime.SetFinalizer(Foo1, nil)
+	runtime.SetFinalizer(Foo2, nil)
+}
+
+type Object1 struct {
+	Something []byte
+}
+
+type Object2 struct {
+	Something byte
+}
+
+var (
+	Foo2 = &Object2{}
+	Foo1 = &Object1{}
+)
diff --git a/third_party/gofrontend/libgo/go/runtime/mgc0.go b/third_party/gofrontend/libgo/go/runtime/mgc0.go
new file mode 100644
index 0000000..624485d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/mgc0.go
@@ -0,0 +1,27 @@
+// 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 runtime
+
+// Called from C. Returns the Go type *m.
+func gc_m_ptr(ret *interface{}) {
+	*ret = (*m)(nil)
+}
+
+// Called from C. Returns the Go type *g.
+func gc_g_ptr(ret *interface{}) {
+	*ret = (*g)(nil)
+}
+
+// Called from C. Returns the Go type *itab.
+func gc_itab_ptr(ret *interface{}) {
+	*ret = (*itab)(nil)
+}
+
+func timenow() (sec int64, nsec int32)
+
+func gc_unixnanotime(now *int64) {
+	sec, nsec := timenow()
+	*now = sec*1e9 + int64(nsec)
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/norace_test.go b/third_party/gofrontend/libgo/go/runtime/norace_test.go
new file mode 100644
index 0000000..3b17187
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/norace_test.go
@@ -0,0 +1,46 @@
+// Copyright 2013 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.
+
+// The file contains tests that can not run under race detector for some reason.
+// +build !race
+
+package runtime_test
+
+import (
+	"runtime"
+	"testing"
+)
+
+// Syscall tests split stack between Entersyscall and Exitsyscall under race detector.
+func BenchmarkSyscall(b *testing.B) {
+	benchmarkSyscall(b, 0, 1)
+}
+
+func BenchmarkSyscallWork(b *testing.B) {
+	benchmarkSyscall(b, 100, 1)
+}
+
+func BenchmarkSyscallExcess(b *testing.B) {
+	benchmarkSyscall(b, 0, 4)
+}
+
+func BenchmarkSyscallExcessWork(b *testing.B) {
+	benchmarkSyscall(b, 100, 4)
+}
+
+func benchmarkSyscall(b *testing.B, work, excess int) {
+	b.SetParallelism(excess)
+	b.RunParallel(func(pb *testing.PB) {
+		foo := 42
+		for pb.Next() {
+			runtime.Entersyscall()
+			for i := 0; i < work; i++ {
+				foo *= 2
+				foo /= 2
+			}
+			runtime.Exitsyscall()
+		}
+		_ = foo
+	})
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/parfor_test.go b/third_party/gofrontend/libgo/go/runtime/parfor_test.go
new file mode 100644
index 0000000..de64285
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/parfor_test.go
@@ -0,0 +1,139 @@
+// 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.
+
+// The race detector does not understand ParFor synchronization.
+// +build !race
+
+package runtime_test
+
+import (
+	. "runtime"
+	"testing"
+	"unsafe"
+)
+
+var gdata []uint64
+
+// Simple serial sanity test for parallelfor.
+func TestParFor(t *testing.T) {
+	const P = 1
+	const N = 20
+	data := make([]uint64, N)
+	for i := uint64(0); i < N; i++ {
+		data[i] = i
+	}
+	desc := NewParFor(P)
+	// Avoid making func a closure: parfor cannot invoke them.
+	// Since it doesn't happen in the C code, it's not worth doing
+	// just for the test.
+	gdata = data
+	ParForSetup(desc, P, N, nil, true, func(desc *ParFor, i uint32) {
+		data := gdata
+		data[i] = data[i]*data[i] + 1
+	})
+	ParForDo(desc)
+	for i := uint64(0); i < N; i++ {
+		if data[i] != i*i+1 {
+			t.Fatalf("Wrong element %d: %d", i, data[i])
+		}
+	}
+}
+
+// Test that nonblocking parallelfor does not block.
+func TestParFor2(t *testing.T) {
+	const P = 7
+	const N = 1003
+	data := make([]uint64, N)
+	for i := uint64(0); i < N; i++ {
+		data[i] = i
+	}
+	desc := NewParFor(P)
+	ParForSetup(desc, P, N, (*byte)(unsafe.Pointer(&data)), false, func(desc *ParFor, i uint32) {
+		d := *(*[]uint64)(unsafe.Pointer(desc.Ctx))
+		d[i] = d[i]*d[i] + 1
+	})
+	for p := 0; p < P; p++ {
+		ParForDo(desc)
+	}
+	for i := uint64(0); i < N; i++ {
+		if data[i] != i*i+1 {
+			t.Fatalf("Wrong element %d: %d", i, data[i])
+		}
+	}
+}
+
+// Test that iterations are properly distributed.
+func TestParForSetup(t *testing.T) {
+	const P = 11
+	const N = 101
+	desc := NewParFor(P)
+	for n := uint32(0); n < N; n++ {
+		for p := uint32(1); p <= P; p++ {
+			ParForSetup(desc, p, n, nil, true, func(desc *ParFor, i uint32) {})
+			sum := uint32(0)
+			size0 := uint32(0)
+			end0 := uint32(0)
+			for i := uint32(0); i < p; i++ {
+				begin, end := ParForIters(desc, i)
+				size := end - begin
+				sum += size
+				if i == 0 {
+					size0 = size
+					if begin != 0 {
+						t.Fatalf("incorrect begin: %d (n=%d, p=%d)", begin, n, p)
+					}
+				} else {
+					if size != size0 && size != size0+1 {
+						t.Fatalf("incorrect size: %d/%d (n=%d, p=%d)", size, size0, n, p)
+					}
+					if begin != end0 {
+						t.Fatalf("incorrect begin/end: %d/%d (n=%d, p=%d)", begin, end0, n, p)
+					}
+				}
+				end0 = end
+			}
+			if sum != n {
+				t.Fatalf("incorrect sum: %d/%d (p=%d)", sum, n, p)
+			}
+		}
+	}
+}
+
+// Test parallel parallelfor.
+func TestParForParallel(t *testing.T) {
+	N := uint64(1e7)
+	if testing.Short() {
+		N /= 10
+	}
+	data := make([]uint64, N)
+	for i := uint64(0); i < N; i++ {
+		data[i] = i
+	}
+	P := GOMAXPROCS(-1)
+	c := make(chan bool, P)
+	desc := NewParFor(uint32(P))
+	gdata = data
+	ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) {
+		data := gdata
+		data[i] = data[i]*data[i] + 1
+	})
+	for p := 1; p < P; p++ {
+		go func() {
+			ParForDo(desc)
+			c <- true
+		}()
+	}
+	ParForDo(desc)
+	for p := 1; p < P; p++ {
+		<-c
+	}
+	for i := uint64(0); i < N; i++ {
+		if data[i] != i*i+1 {
+			t.Fatalf("Wrong element %d: %d", i, data[i])
+		}
+	}
+
+	data, desc = nil, nil
+	GC()
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/pprof/pprof.go b/third_party/gofrontend/libgo/go/runtime/pprof/pprof.go
new file mode 100644
index 0000000..bd0b25f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/pprof/pprof.go
@@ -0,0 +1,684 @@
+// Copyright 2010 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 pprof writes runtime profiling data in the format expected
+// by the pprof visualization tool.
+// For more information about pprof, see
+// http://code.google.com/p/google-perftools/.
+package pprof
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"runtime"
+	"sort"
+	"strings"
+	"sync"
+	"text/tabwriter"
+)
+
+// BUG(rsc): Profiles are incomplete and inaccurate on NetBSD and OS X.
+// See http://golang.org/issue/6047 for details.
+
+// A Profile is a collection of stack traces showing the call sequences
+// that led to instances of a particular event, such as allocation.
+// Packages can create and maintain their own profiles; the most common
+// use is for tracking resources that must be explicitly closed, such as files
+// or network connections.
+//
+// A Profile's methods can be called from multiple goroutines simultaneously.
+//
+// Each Profile has a unique name.  A few profiles are predefined:
+//
+//	goroutine    - stack traces of all current goroutines
+//	heap         - a sampling of all heap allocations
+//	threadcreate - stack traces that led to the creation of new OS threads
+//	block        - stack traces that led to blocking on synchronization primitives
+//
+// These predefined profiles maintain themselves and panic on an explicit
+// Add or Remove method call.
+//
+// The CPU profile is not available as a Profile.  It has a special API,
+// the StartCPUProfile and StopCPUProfile functions, because it streams
+// output to a writer during profiling.
+//
+type Profile struct {
+	name  string
+	mu    sync.Mutex
+	m     map[interface{}][]uintptr
+	count func() int
+	write func(io.Writer, int) error
+}
+
+// profiles records all registered profiles.
+var profiles struct {
+	mu sync.Mutex
+	m  map[string]*Profile
+}
+
+var goroutineProfile = &Profile{
+	name:  "goroutine",
+	count: countGoroutine,
+	write: writeGoroutine,
+}
+
+var threadcreateProfile = &Profile{
+	name:  "threadcreate",
+	count: countThreadCreate,
+	write: writeThreadCreate,
+}
+
+var heapProfile = &Profile{
+	name:  "heap",
+	count: countHeap,
+	write: writeHeap,
+}
+
+var blockProfile = &Profile{
+	name:  "block",
+	count: countBlock,
+	write: writeBlock,
+}
+
+func lockProfiles() {
+	profiles.mu.Lock()
+	if profiles.m == nil {
+		// Initial built-in profiles.
+		profiles.m = map[string]*Profile{
+			"goroutine":    goroutineProfile,
+			"threadcreate": threadcreateProfile,
+			"heap":         heapProfile,
+			"block":        blockProfile,
+		}
+	}
+}
+
+func unlockProfiles() {
+	profiles.mu.Unlock()
+}
+
+// NewProfile creates a new profile with the given name.
+// If a profile with that name already exists, NewProfile panics.
+// The convention is to use a 'import/path.' prefix to create
+// separate name spaces for each package.
+func NewProfile(name string) *Profile {
+	lockProfiles()
+	defer unlockProfiles()
+	if name == "" {
+		panic("pprof: NewProfile with empty name")
+	}
+	if profiles.m[name] != nil {
+		panic("pprof: NewProfile name already in use: " + name)
+	}
+	p := &Profile{
+		name: name,
+		m:    map[interface{}][]uintptr{},
+	}
+	profiles.m[name] = p
+	return p
+}
+
+// Lookup returns the profile with the given name, or nil if no such profile exists.
+func Lookup(name string) *Profile {
+	lockProfiles()
+	defer unlockProfiles()
+	return profiles.m[name]
+}
+
+// Profiles returns a slice of all the known profiles, sorted by name.
+func Profiles() []*Profile {
+	lockProfiles()
+	defer unlockProfiles()
+
+	var all []*Profile
+	for _, p := range profiles.m {
+		all = append(all, p)
+	}
+
+	sort.Sort(byName(all))
+	return all
+}
+
+type byName []*Profile
+
+func (x byName) Len() int           { return len(x) }
+func (x byName) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byName) Less(i, j int) bool { return x[i].name < x[j].name }
+
+// Name returns this profile's name, which can be passed to Lookup to reobtain the profile.
+func (p *Profile) Name() string {
+	return p.name
+}
+
+// Count returns the number of execution stacks currently in the profile.
+func (p *Profile) Count() int {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	if p.count != nil {
+		return p.count()
+	}
+	return len(p.m)
+}
+
+// Add adds the current execution stack to the profile, associated with value.
+// Add stores value in an internal map, so value must be suitable for use as
+// a map key and will not be garbage collected until the corresponding
+// call to Remove.  Add panics if the profile already contains a stack for value.
+//
+// The skip parameter has the same meaning as runtime.Caller's skip
+// and controls where the stack trace begins.  Passing skip=0 begins the
+// trace in the function calling Add.  For example, given this
+// execution stack:
+//
+//	Add
+//	called from rpc.NewClient
+//	called from mypkg.Run
+//	called from main.main
+//
+// Passing skip=0 begins the stack trace at the call to Add inside rpc.NewClient.
+// Passing skip=1 begins the stack trace at the call to NewClient inside mypkg.Run.
+//
+func (p *Profile) Add(value interface{}, skip int) {
+	if p.name == "" {
+		panic("pprof: use of uninitialized Profile")
+	}
+	if p.write != nil {
+		panic("pprof: Add called on built-in Profile " + p.name)
+	}
+
+	stk := make([]uintptr, 32)
+	n := runtime.Callers(skip+1, stk[:])
+
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	if p.m[value] != nil {
+		panic("pprof: Profile.Add of duplicate value")
+	}
+	p.m[value] = stk[:n]
+}
+
+// Remove removes the execution stack associated with value from the profile.
+// It is a no-op if the value is not in the profile.
+func (p *Profile) Remove(value interface{}) {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	delete(p.m, value)
+}
+
+// WriteTo writes a pprof-formatted snapshot of the profile to w.
+// If a write to w returns an error, WriteTo returns that error.
+// Otherwise, WriteTo returns nil.
+//
+// The debug parameter enables additional output.
+// Passing debug=0 prints only the hexadecimal addresses that pprof needs.
+// Passing debug=1 adds comments translating addresses to function names
+// and line numbers, so that a programmer can read the profile without tools.
+//
+// The predefined profiles may assign meaning to other debug values;
+// for example, when printing the "goroutine" profile, debug=2 means to
+// print the goroutine stacks in the same form that a Go program uses
+// when dying due to an unrecovered panic.
+func (p *Profile) WriteTo(w io.Writer, debug int) error {
+	if p.name == "" {
+		panic("pprof: use of zero Profile")
+	}
+	if p.write != nil {
+		return p.write(w, debug)
+	}
+
+	// Obtain consistent snapshot under lock; then process without lock.
+	var all [][]uintptr
+	p.mu.Lock()
+	for _, stk := range p.m {
+		all = append(all, stk)
+	}
+	p.mu.Unlock()
+
+	// Map order is non-deterministic; make output deterministic.
+	sort.Sort(stackProfile(all))
+
+	return printCountProfile(w, debug, p.name, stackProfile(all))
+}
+
+type stackProfile [][]uintptr
+
+func (x stackProfile) Len() int              { return len(x) }
+func (x stackProfile) Stack(i int) []uintptr { return x[i] }
+func (x stackProfile) Swap(i, j int)         { x[i], x[j] = x[j], x[i] }
+func (x stackProfile) Less(i, j int) bool {
+	t, u := x[i], x[j]
+	for k := 0; k < len(t) && k < len(u); k++ {
+		if t[k] != u[k] {
+			return t[k] < u[k]
+		}
+	}
+	return len(t) < len(u)
+}
+
+// A countProfile is a set of stack traces to be printed as counts
+// grouped by stack trace.  There are multiple implementations:
+// all that matters is that we can find out how many traces there are
+// and obtain each trace in turn.
+type countProfile interface {
+	Len() int
+	Stack(i int) []uintptr
+}
+
+// printCountProfile prints a countProfile at the specified debug level.
+func printCountProfile(w io.Writer, debug int, name string, p countProfile) error {
+	b := bufio.NewWriter(w)
+	var tw *tabwriter.Writer
+	w = b
+	if debug > 0 {
+		tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
+		w = tw
+	}
+
+	fmt.Fprintf(w, "%s profile: total %d\n", name, p.Len())
+
+	// Build count of each stack.
+	var buf bytes.Buffer
+	key := func(stk []uintptr) string {
+		buf.Reset()
+		fmt.Fprintf(&buf, "@")
+		for _, pc := range stk {
+			fmt.Fprintf(&buf, " %#x", pc)
+		}
+		return buf.String()
+	}
+	m := map[string]int{}
+	n := p.Len()
+	for i := 0; i < n; i++ {
+		m[key(p.Stack(i))]++
+	}
+
+	// Print stacks, listing count on first occurrence of a unique stack.
+	for i := 0; i < n; i++ {
+		stk := p.Stack(i)
+		s := key(stk)
+		if count := m[s]; count != 0 {
+			fmt.Fprintf(w, "%d %s\n", count, s)
+			if debug > 0 {
+				printStackRecord(w, stk, false)
+			}
+			delete(m, s)
+		}
+	}
+
+	if tw != nil {
+		tw.Flush()
+	}
+	return b.Flush()
+}
+
+// printStackRecord prints the function + source line information
+// for a single stack trace.
+func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) {
+	show := allFrames
+	wasPanic := false
+	for i, pc := range stk {
+		f := runtime.FuncForPC(pc)
+		if f == nil {
+			show = true
+			fmt.Fprintf(w, "#\t%#x\n", pc)
+			wasPanic = false
+		} else {
+			tracepc := pc
+			// Back up to call instruction.
+			if i > 0 && pc > f.Entry() && !wasPanic {
+				if runtime.GOARCH == "386" || runtime.GOARCH == "amd64" {
+					tracepc--
+				} else if runtime.GOARCH == "s390" || runtime.GOARCH == "s390x" {
+					// only works if function was called
+					// with the brasl instruction (or a
+					// different 6-byte instruction).
+					tracepc -= 6
+				} else {
+					tracepc -= 4 // arm, etc
+				}
+			}
+			file, line := f.FileLine(tracepc)
+			name := f.Name()
+			// Hide runtime.goexit and any runtime functions at the beginning.
+			// This is useful mainly for allocation traces.
+			wasPanic = name == "runtime.panic"
+			if name == "runtime.goexit" || !show && strings.HasPrefix(name, "runtime.") {
+				continue
+			}
+			show = true
+			fmt.Fprintf(w, "#\t%#x\t%s+%#x\t%s:%d\n", pc, name, pc-f.Entry(), file, line)
+		}
+	}
+	if !show {
+		// We didn't print anything; do it again,
+		// and this time include runtime functions.
+		printStackRecord(w, stk, true)
+		return
+	}
+	fmt.Fprintf(w, "\n")
+}
+
+// Interface to system profiles.
+
+type byInUseBytes []runtime.MemProfileRecord
+
+func (x byInUseBytes) Len() int           { return len(x) }
+func (x byInUseBytes) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byInUseBytes) Less(i, j int) bool { return x[i].InUseBytes() > x[j].InUseBytes() }
+
+// WriteHeapProfile is shorthand for Lookup("heap").WriteTo(w, 0).
+// It is preserved for backwards compatibility.
+func WriteHeapProfile(w io.Writer) error {
+	return writeHeap(w, 0)
+}
+
+// countHeap returns the number of records in the heap profile.
+func countHeap() int {
+	n, _ := runtime.MemProfile(nil, true)
+	return n
+}
+
+// writeHeap writes the current runtime heap profile to w.
+func writeHeap(w io.Writer, debug int) error {
+	// Find out how many records there are (MemProfile(nil, true)),
+	// allocate that many records, and get the data.
+	// There's a race—more records might be added between
+	// the two calls—so allocate a few extra records for safety
+	// and also try again if we're very unlucky.
+	// The loop should only execute one iteration in the common case.
+	var p []runtime.MemProfileRecord
+	n, ok := runtime.MemProfile(nil, true)
+	for {
+		// Allocate room for a slightly bigger profile,
+		// in case a few more entries have been added
+		// since the call to MemProfile.
+		p = make([]runtime.MemProfileRecord, n+50)
+		n, ok = runtime.MemProfile(p, true)
+		if ok {
+			p = p[0:n]
+			break
+		}
+		// Profile grew; try again.
+	}
+
+	sort.Sort(byInUseBytes(p))
+
+	b := bufio.NewWriter(w)
+	var tw *tabwriter.Writer
+	w = b
+	if debug > 0 {
+		tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
+		w = tw
+	}
+
+	var total runtime.MemProfileRecord
+	for i := range p {
+		r := &p[i]
+		total.AllocBytes += r.AllocBytes
+		total.AllocObjects += r.AllocObjects
+		total.FreeBytes += r.FreeBytes
+		total.FreeObjects += r.FreeObjects
+	}
+
+	// Technically the rate is MemProfileRate not 2*MemProfileRate,
+	// but early versions of the C++ heap profiler reported 2*MemProfileRate,
+	// so that's what pprof has come to expect.
+	fmt.Fprintf(w, "heap profile: %d: %d [%d: %d] @ heap/%d\n",
+		total.InUseObjects(), total.InUseBytes(),
+		total.AllocObjects, total.AllocBytes,
+		2*runtime.MemProfileRate)
+
+	for i := range p {
+		r := &p[i]
+		fmt.Fprintf(w, "%d: %d [%d: %d] @",
+			r.InUseObjects(), r.InUseBytes(),
+			r.AllocObjects, r.AllocBytes)
+		for _, pc := range r.Stack() {
+			fmt.Fprintf(w, " %#x", pc)
+		}
+		fmt.Fprintf(w, "\n")
+		if debug > 0 {
+			printStackRecord(w, r.Stack(), false)
+		}
+	}
+
+	// Print memstats information too.
+	// Pprof will ignore, but useful for people
+	if debug > 0 {
+		s := new(runtime.MemStats)
+		runtime.ReadMemStats(s)
+		fmt.Fprintf(w, "\n# runtime.MemStats\n")
+		fmt.Fprintf(w, "# Alloc = %d\n", s.Alloc)
+		fmt.Fprintf(w, "# TotalAlloc = %d\n", s.TotalAlloc)
+		fmt.Fprintf(w, "# Sys = %d\n", s.Sys)
+		fmt.Fprintf(w, "# Lookups = %d\n", s.Lookups)
+		fmt.Fprintf(w, "# Mallocs = %d\n", s.Mallocs)
+		fmt.Fprintf(w, "# Frees = %d\n", s.Frees)
+
+		fmt.Fprintf(w, "# HeapAlloc = %d\n", s.HeapAlloc)
+		fmt.Fprintf(w, "# HeapSys = %d\n", s.HeapSys)
+		fmt.Fprintf(w, "# HeapIdle = %d\n", s.HeapIdle)
+		fmt.Fprintf(w, "# HeapInuse = %d\n", s.HeapInuse)
+		fmt.Fprintf(w, "# HeapReleased = %d\n", s.HeapReleased)
+		fmt.Fprintf(w, "# HeapObjects = %d\n", s.HeapObjects)
+
+		fmt.Fprintf(w, "# Stack = %d / %d\n", s.StackInuse, s.StackSys)
+		fmt.Fprintf(w, "# MSpan = %d / %d\n", s.MSpanInuse, s.MSpanSys)
+		fmt.Fprintf(w, "# MCache = %d / %d\n", s.MCacheInuse, s.MCacheSys)
+		fmt.Fprintf(w, "# BuckHashSys = %d\n", s.BuckHashSys)
+
+		fmt.Fprintf(w, "# NextGC = %d\n", s.NextGC)
+		fmt.Fprintf(w, "# PauseNs = %d\n", s.PauseNs)
+		fmt.Fprintf(w, "# NumGC = %d\n", s.NumGC)
+		fmt.Fprintf(w, "# EnableGC = %v\n", s.EnableGC)
+		fmt.Fprintf(w, "# DebugGC = %v\n", s.DebugGC)
+	}
+
+	if tw != nil {
+		tw.Flush()
+	}
+	return b.Flush()
+}
+
+// countThreadCreate returns the size of the current ThreadCreateProfile.
+func countThreadCreate() int {
+	n, _ := runtime.ThreadCreateProfile(nil)
+	return n
+}
+
+// writeThreadCreate writes the current runtime ThreadCreateProfile to w.
+func writeThreadCreate(w io.Writer, debug int) error {
+	return writeRuntimeProfile(w, debug, "threadcreate", runtime.ThreadCreateProfile)
+}
+
+// countGoroutine returns the number of goroutines.
+func countGoroutine() int {
+	return runtime.NumGoroutine()
+}
+
+// writeGoroutine writes the current runtime GoroutineProfile to w.
+func writeGoroutine(w io.Writer, debug int) error {
+	if debug >= 2 {
+		return writeGoroutineStacks(w)
+	}
+	return writeRuntimeProfile(w, debug, "goroutine", runtime.GoroutineProfile)
+}
+
+func writeGoroutineStacks(w io.Writer) error {
+	// We don't know how big the buffer needs to be to collect
+	// all the goroutines.  Start with 1 MB and try a few times, doubling each time.
+	// Give up and use a truncated trace if 64 MB is not enough.
+	buf := make([]byte, 1<<20)
+	for i := 0; ; i++ {
+		n := runtime.Stack(buf, true)
+		if n < len(buf) {
+			buf = buf[:n]
+			break
+		}
+		if len(buf) >= 64<<20 {
+			// Filled 64 MB - stop there.
+			break
+		}
+		buf = make([]byte, 2*len(buf))
+	}
+	_, err := w.Write(buf)
+	return err
+}
+
+func writeRuntimeProfile(w io.Writer, debug int, name string, fetch func([]runtime.StackRecord) (int, bool)) error {
+	// Find out how many records there are (fetch(nil)),
+	// allocate that many records, and get the data.
+	// There's a race—more records might be added between
+	// the two calls—so allocate a few extra records for safety
+	// and also try again if we're very unlucky.
+	// The loop should only execute one iteration in the common case.
+	var p []runtime.StackRecord
+	n, ok := fetch(nil)
+	for {
+		// Allocate room for a slightly bigger profile,
+		// in case a few more entries have been added
+		// since the call to ThreadProfile.
+		p = make([]runtime.StackRecord, n+10)
+		n, ok = fetch(p)
+		if ok {
+			p = p[0:n]
+			break
+		}
+		// Profile grew; try again.
+	}
+
+	return printCountProfile(w, debug, name, runtimeProfile(p))
+}
+
+type runtimeProfile []runtime.StackRecord
+
+func (p runtimeProfile) Len() int              { return len(p) }
+func (p runtimeProfile) Stack(i int) []uintptr { return p[i].Stack() }
+
+var cpu struct {
+	sync.Mutex
+	profiling bool
+	done      chan bool
+}
+
+// StartCPUProfile enables CPU profiling for the current process.
+// While profiling, the profile will be buffered and written to w.
+// StartCPUProfile returns an error if profiling is already enabled.
+func StartCPUProfile(w io.Writer) error {
+	// The runtime routines allow a variable profiling rate,
+	// but in practice operating systems cannot trigger signals
+	// at more than about 500 Hz, and our processing of the
+	// signal is not cheap (mostly getting the stack trace).
+	// 100 Hz is a reasonable choice: it is frequent enough to
+	// produce useful data, rare enough not to bog down the
+	// system, and a nice round number to make it easy to
+	// convert sample counts to seconds.  Instead of requiring
+	// each client to specify the frequency, we hard code it.
+	const hz = 100
+
+	// Avoid queueing behind StopCPUProfile.
+	// Could use TryLock instead if we had it.
+	if cpu.profiling {
+		return fmt.Errorf("cpu profiling already in use")
+	}
+
+	cpu.Lock()
+	defer cpu.Unlock()
+	if cpu.done == nil {
+		cpu.done = make(chan bool)
+	}
+	// Double-check.
+	if cpu.profiling {
+		return fmt.Errorf("cpu profiling already in use")
+	}
+	cpu.profiling = true
+	runtime.SetCPUProfileRate(hz)
+	go profileWriter(w)
+	return nil
+}
+
+func profileWriter(w io.Writer) {
+	for {
+		data := runtime.CPUProfile()
+		if data == nil {
+			break
+		}
+		w.Write(data)
+	}
+	cpu.done <- true
+}
+
+// StopCPUProfile stops the current CPU profile, if any.
+// StopCPUProfile only returns after all the writes for the
+// profile have completed.
+func StopCPUProfile() {
+	cpu.Lock()
+	defer cpu.Unlock()
+
+	if !cpu.profiling {
+		return
+	}
+	cpu.profiling = false
+	runtime.SetCPUProfileRate(0)
+	<-cpu.done
+}
+
+type byCycles []runtime.BlockProfileRecord
+
+func (x byCycles) Len() int           { return len(x) }
+func (x byCycles) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byCycles) Less(i, j int) bool { return x[i].Cycles > x[j].Cycles }
+
+// countBlock returns the number of records in the blocking profile.
+func countBlock() int {
+	n, _ := runtime.BlockProfile(nil)
+	return n
+}
+
+// writeBlock writes the current blocking profile to w.
+func writeBlock(w io.Writer, debug int) error {
+	var p []runtime.BlockProfileRecord
+	n, ok := runtime.BlockProfile(nil)
+	for {
+		p = make([]runtime.BlockProfileRecord, n+50)
+		n, ok = runtime.BlockProfile(p)
+		if ok {
+			p = p[:n]
+			break
+		}
+	}
+
+	sort.Sort(byCycles(p))
+
+	b := bufio.NewWriter(w)
+	var tw *tabwriter.Writer
+	w = b
+	if debug > 0 {
+		tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
+		w = tw
+	}
+
+	fmt.Fprintf(w, "--- contention:\n")
+	fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
+	for i := range p {
+		r := &p[i]
+		fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
+		for _, pc := range r.Stack() {
+			fmt.Fprintf(w, " %#x", pc)
+		}
+		fmt.Fprint(w, "\n")
+		if debug > 0 {
+			printStackRecord(w, r.Stack(), true)
+		}
+	}
+
+	if tw != nil {
+		tw.Flush()
+	}
+	return b.Flush()
+}
+
+func runtime_cyclesPerSecond() int64
diff --git a/third_party/gofrontend/libgo/go/runtime/pprof/pprof_test.go b/third_party/gofrontend/libgo/go/runtime/pprof/pprof_test.go
new file mode 100644
index 0000000..f714472
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/pprof/pprof_test.go
@@ -0,0 +1,404 @@
+// 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.
+
+// +build !nacl
+
+package pprof_test
+
+import (
+	"bytes"
+	"fmt"
+	"hash/crc32"
+	"math/big"
+	"os/exec"
+	"regexp"
+	"runtime"
+	. "runtime/pprof"
+	"strings"
+	"sync"
+	"testing"
+	"time"
+	"unsafe"
+)
+
+func TestCPUProfile(t *testing.T) {
+	buf := make([]byte, 100000)
+	testCPUProfile(t, []string{"crc32.update"}, func() {
+		// This loop takes about a quarter second on a 2 GHz laptop.
+		// We only need to get one 100 Hz clock tick, so we've got
+		// a 25x safety buffer.
+		for i := 0; i < 1000; i++ {
+			crc32.ChecksumIEEE(buf)
+		}
+	})
+}
+
+func TestCPUProfileMultithreaded(t *testing.T) {
+	buf := make([]byte, 100000)
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+	testCPUProfile(t, []string{"crc32.update"}, func() {
+		c := make(chan int)
+		go func() {
+			for i := 0; i < 2000; i++ {
+				crc32.Update(0, crc32.IEEETable, buf)
+			}
+			c <- 1
+		}()
+		// This loop takes about a quarter second on a 2 GHz laptop.
+		// We only need to get one 100 Hz clock tick, so we've got
+		// a 25x safety buffer.
+		for i := 0; i < 2000; i++ {
+			crc32.ChecksumIEEE(buf)
+		}
+		<-c
+	})
+}
+
+func parseProfile(t *testing.T, bytes []byte, f func(uintptr, []uintptr)) {
+	// Convert []byte to []uintptr.
+	l := len(bytes) / int(unsafe.Sizeof(uintptr(0)))
+	val := *(*[]uintptr)(unsafe.Pointer(&bytes))
+	val = val[:l]
+
+	// 5 for the header, 2 for the per-sample header on at least one sample, 3 for the trailer.
+	if l < 5+2+3 {
+		t.Logf("profile too short: %#x", val)
+		if badOS[runtime.GOOS] {
+			t.Skipf("ignoring failure on %s; see golang.org/issue/6047", runtime.GOOS)
+			return
+		}
+		t.FailNow()
+	}
+
+	hd, val, tl := val[:5], val[5:l-3], val[l-3:]
+	if hd[0] != 0 || hd[1] != 3 || hd[2] != 0 || hd[3] != 1e6/100 || hd[4] != 0 {
+		t.Fatalf("unexpected header %#x", hd)
+	}
+
+	if tl[0] != 0 || tl[1] != 1 || tl[2] != 0 {
+		t.Fatalf("malformed end-of-data marker %#x", tl)
+	}
+
+	for len(val) > 0 {
+		if len(val) < 2 || val[0] < 1 || val[1] < 1 || uintptr(len(val)) < 2+val[1] {
+			t.Fatalf("malformed profile.  leftover: %#x", val)
+		}
+		f(val[0], val[2:2+val[1]])
+		val = val[2+val[1]:]
+	}
+}
+
+func testCPUProfile(t *testing.T, need []string, f func()) {
+	switch runtime.GOOS {
+	case "darwin":
+		out, err := exec.Command("uname", "-a").CombinedOutput()
+		if err != nil {
+			t.Fatal(err)
+		}
+		vers := string(out)
+		t.Logf("uname -a: %v", vers)
+	case "plan9":
+		// unimplemented
+		return
+	}
+
+	var prof bytes.Buffer
+	if err := StartCPUProfile(&prof); err != nil {
+		t.Fatal(err)
+	}
+	f()
+	StopCPUProfile()
+
+	// Check that profile is well formed and contains ChecksumIEEE.
+	have := make([]uintptr, len(need))
+	parseProfile(t, prof.Bytes(), func(count uintptr, stk []uintptr) {
+		for _, pc := range stk {
+			f := runtime.FuncForPC(pc)
+			if f == nil {
+				continue
+			}
+			for i, name := range need {
+				if strings.Contains(f.Name(), name) {
+					have[i] += count
+				}
+			}
+		}
+	})
+
+	if len(need) == 0 {
+		return
+	}
+
+	var total uintptr
+	for i, name := range need {
+		total += have[i]
+		t.Logf("%s: %d\n", name, have[i])
+	}
+	ok := true
+	if total == 0 {
+		t.Logf("no CPU profile samples collected")
+		ok = false
+	}
+	// We'd like to check a reasonable minimum, like
+	// total / len(have) / smallconstant, but this test is
+	// pretty flaky (see bug 7095).  So we'll just test to
+	// make sure we got at least one sample.
+	min := uintptr(1)
+	for i, name := range need {
+		if have[i] < min {
+			t.Logf("%s has %d samples out of %d, want at least %d, ideally %d", name, have[i], total, min, total/uintptr(len(have)))
+			ok = false
+		}
+	}
+
+	if !ok {
+		if badOS[runtime.GOOS] {
+			t.Skipf("ignoring failure on %s; see golang.org/issue/6047", runtime.GOOS)
+			return
+		}
+		t.FailNow()
+	}
+}
+
+func TestCPUProfileWithFork(t *testing.T) {
+	// Fork can hang if preempted with signals frequently enough (see issue 5517).
+	// Ensure that we do not do this.
+	heap := 1 << 30
+	if testing.Short() {
+		heap = 100 << 20
+	}
+	// This makes fork slower.
+	garbage := make([]byte, heap)
+	// Need to touch the slice, otherwise it won't be paged in.
+	done := make(chan bool)
+	go func() {
+		for i := range garbage {
+			garbage[i] = 42
+		}
+		done <- true
+	}()
+	<-done
+
+	var prof bytes.Buffer
+	if err := StartCPUProfile(&prof); err != nil {
+		t.Fatal(err)
+	}
+	defer StopCPUProfile()
+
+	for i := 0; i < 10; i++ {
+		exec.Command("go").CombinedOutput()
+	}
+}
+
+// Test that profiler does not observe runtime.gogo as "user" goroutine execution.
+// If it did, it would see inconsistent state and would either record an incorrect stack
+// or crash because the stack was malformed.
+func TestGoroutineSwitch(t *testing.T) {
+	// How much to try. These defaults take about 1 seconds
+	// on a 2012 MacBook Pro. The ones in short mode take
+	// about 0.1 seconds.
+	tries := 10
+	count := 1000000
+	if testing.Short() {
+		tries = 1
+	}
+	for try := 0; try < tries; try++ {
+		var prof bytes.Buffer
+		if err := StartCPUProfile(&prof); err != nil {
+			t.Fatal(err)
+		}
+		for i := 0; i < count; i++ {
+			runtime.Gosched()
+		}
+		StopCPUProfile()
+
+		// Read profile to look for entries for runtime.gogo with an attempt at a traceback.
+		// The special entry
+		parseProfile(t, prof.Bytes(), func(count uintptr, stk []uintptr) {
+			// An entry with two frames with 'System' in its top frame
+			// exists to record a PC without a traceback. Those are okay.
+			if len(stk) == 2 {
+				f := runtime.FuncForPC(stk[1])
+				if f != nil && (f.Name() == "System" || f.Name() == "ExternalCode") {
+					return
+				}
+			}
+
+			// Otherwise, should not see runtime.gogo.
+			// The place we'd see it would be the inner most frame.
+			f := runtime.FuncForPC(stk[0])
+			if f != nil && f.Name() == "runtime.gogo" {
+				var buf bytes.Buffer
+				for _, pc := range stk {
+					f := runtime.FuncForPC(pc)
+					if f == nil {
+						fmt.Fprintf(&buf, "%#x ?:0\n", pc)
+					} else {
+						file, line := f.FileLine(pc)
+						fmt.Fprintf(&buf, "%#x %s:%d\n", pc, file, line)
+					}
+				}
+				t.Fatalf("found profile entry for runtime.gogo:\n%s", buf.String())
+			}
+		})
+	}
+}
+
+// Test that profiling of division operations is okay, especially on ARM. See issue 6681.
+func TestMathBigDivide(t *testing.T) {
+	testCPUProfile(t, nil, func() {
+		t := time.After(5 * time.Second)
+		pi := new(big.Int)
+		for {
+			for i := 0; i < 100; i++ {
+				n := big.NewInt(2646693125139304345)
+				d := big.NewInt(842468587426513207)
+				pi.Div(n, d)
+			}
+			select {
+			case <-t:
+				return
+			default:
+			}
+		}
+	})
+}
+
+// Operating systems that are expected to fail the tests. See issue 6047.
+var badOS = map[string]bool{
+	"darwin": true,
+	"netbsd": true,
+	"plan9":  true,
+}
+
+func TestBlockProfile(t *testing.T) {
+	t.Skip("lots of details are different for gccgo; FIXME")
+	type TestCase struct {
+		name string
+		f    func()
+		re   string
+	}
+	tests := [...]TestCase{
+		{"chan recv", blockChanRecv, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+#	0x[0-9,a-f]+	runtime\.chanrecv1\+0x[0-9,a-f]+	.*/src/pkg/runtime/chan.goc:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.blockChanRecv\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+		{"chan send", blockChanSend, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+#	0x[0-9,a-f]+	runtime\.chansend1\+0x[0-9,a-f]+	.*/src/pkg/runtime/chan.goc:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.blockChanSend\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+		{"chan close", blockChanClose, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+#	0x[0-9,a-f]+	runtime\.chanrecv1\+0x[0-9,a-f]+	.*/src/pkg/runtime/chan.goc:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.blockChanClose\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+		{"select recv async", blockSelectRecvAsync, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+#	0x[0-9,a-f]+	runtime\.selectgo\+0x[0-9,a-f]+	.*/src/pkg/runtime/chan.goc:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.blockSelectRecvAsync\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+		{"select send sync", blockSelectSendSync, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+#	0x[0-9,a-f]+	runtime\.selectgo\+0x[0-9,a-f]+	.*/src/pkg/runtime/chan.goc:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.blockSelectSendSync\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+		{"mutex", blockMutex, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+#	0x[0-9,a-f]+	sync\.\(\*Mutex\)\.Lock\+0x[0-9,a-f]+	.*/src/pkg/sync/mutex\.go:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.blockMutex\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+#	0x[0-9,a-f]+	runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+	.*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+	}
+
+	runtime.SetBlockProfileRate(1)
+	defer runtime.SetBlockProfileRate(0)
+	for _, test := range tests {
+		test.f()
+	}
+	var w bytes.Buffer
+	Lookup("block").WriteTo(&w, 1)
+	prof := w.String()
+
+	if !strings.HasPrefix(prof, "--- contention:\ncycles/second=") {
+		t.Fatalf("Bad profile header:\n%v", prof)
+	}
+
+	for _, test := range tests {
+		if !regexp.MustCompile(test.re).MatchString(prof) {
+			t.Fatalf("Bad %v entry, expect:\n%v\ngot:\n%v", test.name, test.re, prof)
+		}
+	}
+}
+
+const blockDelay = 10 * time.Millisecond
+
+func blockChanRecv() {
+	c := make(chan bool)
+	go func() {
+		time.Sleep(blockDelay)
+		c <- true
+	}()
+	<-c
+}
+
+func blockChanSend() {
+	c := make(chan bool)
+	go func() {
+		time.Sleep(blockDelay)
+		<-c
+	}()
+	c <- true
+}
+
+func blockChanClose() {
+	c := make(chan bool)
+	go func() {
+		time.Sleep(blockDelay)
+		close(c)
+	}()
+	<-c
+}
+
+func blockSelectRecvAsync() {
+	c := make(chan bool, 1)
+	c2 := make(chan bool, 1)
+	go func() {
+		time.Sleep(blockDelay)
+		c <- true
+	}()
+	select {
+	case <-c:
+	case <-c2:
+	}
+}
+
+func blockSelectSendSync() {
+	c := make(chan bool)
+	c2 := make(chan bool)
+	go func() {
+		time.Sleep(blockDelay)
+		<-c
+	}()
+	select {
+	case c <- true:
+	case c2 <- true:
+	}
+}
+
+func blockMutex() {
+	var mu sync.Mutex
+	mu.Lock()
+	go func() {
+		time.Sleep(blockDelay)
+		mu.Unlock()
+	}()
+	mu.Lock()
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/proc_test.go b/third_party/gofrontend/libgo/go/runtime/proc_test.go
new file mode 100644
index 0000000..4f364dc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/proc_test.go
@@ -0,0 +1,479 @@
+// 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.
+
+package runtime_test
+
+import (
+	"math"
+	"runtime"
+	"sync/atomic"
+	"syscall"
+	"testing"
+	"time"
+)
+
+var stop = make(chan bool, 1)
+
+func perpetuumMobile() {
+	select {
+	case <-stop:
+	default:
+		go perpetuumMobile()
+	}
+}
+
+func TestStopTheWorldDeadlock(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping during short test")
+	}
+	maxprocs := runtime.GOMAXPROCS(3)
+	compl := make(chan bool, 2)
+	go func() {
+		for i := 0; i != 1000; i += 1 {
+			runtime.GC()
+		}
+		compl <- true
+	}()
+	go func() {
+		for i := 0; i != 1000; i += 1 {
+			runtime.GOMAXPROCS(3)
+		}
+		compl <- true
+	}()
+	go perpetuumMobile()
+	<-compl
+	<-compl
+	stop <- true
+	runtime.GOMAXPROCS(maxprocs)
+}
+
+func TestYieldProgress(t *testing.T) {
+	testYieldProgress(t, false)
+}
+
+func TestYieldLockedProgress(t *testing.T) {
+	testYieldProgress(t, true)
+}
+
+func testYieldProgress(t *testing.T, locked bool) {
+	c := make(chan bool)
+	cack := make(chan bool)
+	go func() {
+		if locked {
+			runtime.LockOSThread()
+		}
+		for {
+			select {
+			case <-c:
+				cack <- true
+				return
+			default:
+				runtime.Gosched()
+			}
+		}
+	}()
+	time.Sleep(10 * time.Millisecond)
+	c <- true
+	<-cack
+}
+
+func TestYieldLocked(t *testing.T) {
+	const N = 10
+	c := make(chan bool)
+	go func() {
+		runtime.LockOSThread()
+		for i := 0; i < N; i++ {
+			runtime.Gosched()
+			time.Sleep(time.Millisecond)
+		}
+		c <- true
+		// runtime.UnlockOSThread() is deliberately omitted
+	}()
+	<-c
+}
+
+func TestGoroutineParallelism(t *testing.T) {
+	P := 4
+	N := 10
+	if testing.Short() {
+		P = 3
+		N = 3
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
+	for try := 0; try < N; try++ {
+		done := make(chan bool)
+		x := uint32(0)
+		for p := 0; p < P; p++ {
+			// Test that all P goroutines are scheduled at the same time
+			go func(p int) {
+				for i := 0; i < 3; i++ {
+					expected := uint32(P*i + p)
+					for atomic.LoadUint32(&x) != expected {
+					}
+					atomic.StoreUint32(&x, expected+1)
+				}
+				done <- true
+			}(p)
+		}
+		for p := 0; p < P; p++ {
+			<-done
+		}
+	}
+}
+
+func TestBlockLocked(t *testing.T) {
+	const N = 10
+	c := make(chan bool)
+	go func() {
+		runtime.LockOSThread()
+		for i := 0; i < N; i++ {
+			c <- true
+		}
+		runtime.UnlockOSThread()
+	}()
+	for i := 0; i < N; i++ {
+		<-c
+	}
+}
+
+func TestTimerFairness(t *testing.T) {
+	done := make(chan bool)
+	c := make(chan bool)
+	for i := 0; i < 2; i++ {
+		go func() {
+			for {
+				select {
+				case c <- true:
+				case <-done:
+					return
+				}
+			}
+		}()
+	}
+
+	timer := time.After(20 * time.Millisecond)
+	for {
+		select {
+		case <-c:
+		case <-timer:
+			close(done)
+			return
+		}
+	}
+}
+
+func TestTimerFairness2(t *testing.T) {
+	done := make(chan bool)
+	c := make(chan bool)
+	for i := 0; i < 2; i++ {
+		go func() {
+			timer := time.After(20 * time.Millisecond)
+			var buf [1]byte
+			for {
+				syscall.Read(0, buf[0:0])
+				select {
+				case c <- true:
+				case <-c:
+				case <-timer:
+					done <- true
+					return
+				}
+			}
+		}()
+	}
+	<-done
+	<-done
+}
+
+// The function is used to test preemption at split stack checks.
+// Declaring a var avoids inlining at the call site.
+var preempt = func() int {
+	var a [128]int
+	sum := 0
+	for _, v := range a {
+		sum += v
+	}
+	return sum
+}
+
+func TestPreemption(t *testing.T) {
+	t.Skip("gccgo does not implement preemption")
+	// Test that goroutines are preempted at function calls.
+	N := 5
+	if testing.Short() {
+		N = 2
+	}
+	c := make(chan bool)
+	var x uint32
+	for g := 0; g < 2; g++ {
+		go func(g int) {
+			for i := 0; i < N; i++ {
+				for atomic.LoadUint32(&x) != uint32(g) {
+					preempt()
+				}
+				atomic.StoreUint32(&x, uint32(1-g))
+			}
+			c <- true
+		}(g)
+	}
+	<-c
+	<-c
+}
+
+func TestPreemptionGC(t *testing.T) {
+	t.Skip("gccgo does not implement preemption")
+	// Test that pending GC preempts running goroutines.
+	P := 5
+	N := 10
+	if testing.Short() {
+		P = 3
+		N = 2
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P + 1))
+	var stop uint32
+	for i := 0; i < P; i++ {
+		go func() {
+			for atomic.LoadUint32(&stop) == 0 {
+				preempt()
+			}
+		}()
+	}
+	for i := 0; i < N; i++ {
+		runtime.Gosched()
+		runtime.GC()
+	}
+	atomic.StoreUint32(&stop, 1)
+}
+
+func TestGCFairness(t *testing.T) {
+	output := executeTest(t, testGCFairnessSource, nil)
+	want := "OK\n"
+	if output != want {
+		t.Fatalf("want %s, got %s\n", want, output)
+	}
+}
+
+const testGCFairnessSource = `
+package main
+
+import (
+	"fmt"
+	"os"
+	"runtime"
+	"time"
+)
+
+func main() {
+	runtime.GOMAXPROCS(1)
+	f, err := os.Open("/dev/null")
+	if os.IsNotExist(err) {
+		// This test tests what it is intended to test only if writes are fast.
+		// If there is no /dev/null, we just don't execute the test.
+		fmt.Println("OK")
+		return
+	}
+	if err != nil {
+		fmt.Println(err)
+		os.Exit(1)
+	}
+	for i := 0; i < 2; i++ {
+		go func() {
+			for {
+				f.Write([]byte("."))
+			}
+		}()
+	}
+	time.Sleep(10 * time.Millisecond)
+	fmt.Println("OK")
+}
+`
+
+func stackGrowthRecursive(i int) {
+	var pad [128]uint64
+	if i != 0 && pad[0] == 0 {
+		stackGrowthRecursive(i - 1)
+	}
+}
+
+func TestPreemptSplitBig(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in -short mode")
+	}
+	t.Skip("gccgo does not implement preemption")
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+	stop := make(chan int)
+	go big(stop)
+	for i := 0; i < 3; i++ {
+		time.Sleep(10 * time.Microsecond) // let big start running
+		runtime.GC()
+	}
+	close(stop)
+}
+
+func big(stop chan int) int {
+	n := 0
+	for {
+		// delay so that gc is sure to have asked for a preemption
+		for i := 0; i < 1e9; i++ {
+			n++
+		}
+
+		// call bigframe, which used to miss the preemption in its prologue.
+		bigframe(stop)
+
+		// check if we've been asked to stop.
+		select {
+		case <-stop:
+			return n
+		}
+	}
+}
+
+func bigframe(stop chan int) int {
+	// not splitting the stack will overflow.
+	// small will notice that it needs a stack split and will
+	// catch the overflow.
+	var x [8192]byte
+	return small(stop, &x)
+}
+
+func small(stop chan int, x *[8192]byte) int {
+	for i := range x {
+		x[i] = byte(i)
+	}
+	sum := 0
+	for i := range x {
+		sum += int(x[i])
+	}
+
+	// keep small from being a leaf function, which might
+	// make it not do any stack check at all.
+	nonleaf(stop)
+
+	return sum
+}
+
+func nonleaf(stop chan int) bool {
+	// do something that won't be inlined:
+	select {
+	case <-stop:
+		return true
+	default:
+		return false
+	}
+}
+
+func TestSchedLocalQueue(t *testing.T) {
+	runtime.TestSchedLocalQueue1()
+}
+
+func TestSchedLocalQueueSteal(t *testing.T) {
+	runtime.TestSchedLocalQueueSteal1()
+}
+
+func benchmarkStackGrowth(b *testing.B, rec int) {
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			stackGrowthRecursive(rec)
+		}
+	})
+}
+
+func BenchmarkStackGrowth(b *testing.B) {
+	benchmarkStackGrowth(b, 10)
+}
+
+func BenchmarkStackGrowthDeep(b *testing.B) {
+	benchmarkStackGrowth(b, 1024)
+}
+
+func BenchmarkCreateGoroutines(b *testing.B) {
+	benchmarkCreateGoroutines(b, 1)
+}
+
+func BenchmarkCreateGoroutinesParallel(b *testing.B) {
+	benchmarkCreateGoroutines(b, runtime.GOMAXPROCS(-1))
+}
+
+func benchmarkCreateGoroutines(b *testing.B, procs int) {
+	c := make(chan bool)
+	var f func(n int)
+	f = func(n int) {
+		if n == 0 {
+			c <- true
+			return
+		}
+		go f(n - 1)
+	}
+	for i := 0; i < procs; i++ {
+		go f(b.N / procs)
+	}
+	for i := 0; i < procs; i++ {
+		<-c
+	}
+}
+
+type Matrix [][]float64
+
+func BenchmarkMatmult(b *testing.B) {
+	b.StopTimer()
+	// matmult is O(N**3) but testing expects O(b.N),
+	// so we need to take cube root of b.N
+	n := int(math.Cbrt(float64(b.N))) + 1
+	A := makeMatrix(n)
+	B := makeMatrix(n)
+	C := makeMatrix(n)
+	b.StartTimer()
+	matmult(nil, A, B, C, 0, n, 0, n, 0, n, 8)
+}
+
+func makeMatrix(n int) Matrix {
+	m := make(Matrix, n)
+	for i := 0; i < n; i++ {
+		m[i] = make([]float64, n)
+		for j := 0; j < n; j++ {
+			m[i][j] = float64(i*n + j)
+		}
+	}
+	return m
+}
+
+func matmult(done chan<- struct{}, A, B, C Matrix, i0, i1, j0, j1, k0, k1, threshold int) {
+	di := i1 - i0
+	dj := j1 - j0
+	dk := k1 - k0
+	if di >= dj && di >= dk && di >= threshold {
+		// divide in two by y axis
+		mi := i0 + di/2
+		done1 := make(chan struct{}, 1)
+		go matmult(done1, A, B, C, i0, mi, j0, j1, k0, k1, threshold)
+		matmult(nil, A, B, C, mi, i1, j0, j1, k0, k1, threshold)
+		<-done1
+	} else if dj >= dk && dj >= threshold {
+		// divide in two by x axis
+		mj := j0 + dj/2
+		done1 := make(chan struct{}, 1)
+		go matmult(done1, A, B, C, i0, i1, j0, mj, k0, k1, threshold)
+		matmult(nil, A, B, C, i0, i1, mj, j1, k0, k1, threshold)
+		<-done1
+	} else if dk >= threshold {
+		// divide in two by "k" axis
+		// deliberately not parallel because of data races
+		mk := k0 + dk/2
+		matmult(nil, A, B, C, i0, i1, j0, j1, k0, mk, threshold)
+		matmult(nil, A, B, C, i0, i1, j0, j1, mk, k1, threshold)
+	} else {
+		// the matrices are small enough, compute directly
+		for i := i0; i < i1; i++ {
+			for j := j0; j < j1; j++ {
+				for k := k0; k < k1; k++ {
+					C[i][j] += A[i][k] * B[k][j]
+				}
+			}
+		}
+	}
+	if done != nil {
+		done <- struct{}{}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/runtime_test.go b/third_party/gofrontend/libgo/go/runtime/runtime_test.go
new file mode 100644
index 0000000..5c50467
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/runtime_test.go
@@ -0,0 +1,212 @@
+// 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 runtime_test
+
+import (
+	"io"
+	// "io/ioutil"
+	// "os"
+	// "os/exec"
+	. "runtime"
+	"runtime/debug"
+	// "strconv"
+	// "strings"
+	"testing"
+	"unsafe"
+)
+
+var errf error
+
+func errfn() error {
+	return errf
+}
+
+func errfn1() error {
+	return io.EOF
+}
+
+func BenchmarkIfaceCmp100(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for j := 0; j < 100; j++ {
+			if errfn() == io.EOF {
+				b.Fatal("bad comparison")
+			}
+		}
+	}
+}
+
+func BenchmarkIfaceCmpNil100(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for j := 0; j < 100; j++ {
+			if errfn1() == nil {
+				b.Fatal("bad comparison")
+			}
+		}
+	}
+}
+
+func BenchmarkDefer(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		defer1()
+	}
+}
+
+func defer1() {
+	defer func(x, y, z int) {
+		if recover() != nil || x != 1 || y != 2 || z != 3 {
+			panic("bad recover")
+		}
+	}(1, 2, 3)
+	return
+}
+
+func BenchmarkDefer10(b *testing.B) {
+	for i := 0; i < b.N/10; i++ {
+		defer2()
+	}
+}
+
+func defer2() {
+	for i := 0; i < 10; i++ {
+		defer func(x, y, z int) {
+			if recover() != nil || x != 1 || y != 2 || z != 3 {
+				panic("bad recover")
+			}
+		}(1, 2, 3)
+	}
+}
+
+func BenchmarkDeferMany(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		defer func(x, y, z int) {
+			if recover() != nil || x != 1 || y != 2 || z != 3 {
+				panic("bad recover")
+			}
+		}(1, 2, 3)
+	}
+}
+
+/* The go tool is not present in gccgo.
+
+// The profiling signal handler needs to know whether it is executing runtime.gogo.
+// The constant RuntimeGogoBytes in arch_*.h gives the size of the function;
+// we don't have a way to obtain it from the linker (perhaps someday).
+// Test that the constant matches the size determined by 'go tool nm -S'.
+// The value reported will include the padding between runtime.gogo and the
+// next function in memory. That's fine.
+func TestRuntimeGogoBytes(t *testing.T) {
+	if GOOS == "nacl" {
+		t.Skip("skipping on nacl")
+	}
+
+	dir, err := ioutil.TempDir("", "go-build")
+	if err != nil {
+		t.Fatalf("failed to create temp directory: %v", err)
+	}
+	defer os.RemoveAll(dir)
+
+	out, err := exec.Command("go", "build", "-o", dir+"/hello", "../../../test/helloworld.go").CombinedOutput()
+	if err != nil {
+		t.Fatalf("building hello world: %v\n%s", err, out)
+	}
+
+	out, err = exec.Command("go", "tool", "nm", "-size", dir+"/hello").CombinedOutput()
+	if err != nil {
+		t.Fatalf("go tool nm: %v\n%s", err, out)
+	}
+
+	for _, line := range strings.Split(string(out), "\n") {
+		f := strings.Fields(line)
+		if len(f) == 4 && f[3] == "runtime.gogo" {
+			size, _ := strconv.Atoi(f[1])
+			if GogoBytes() != int32(size) {
+				t.Fatalf("RuntimeGogoBytes = %d, should be %d", GogoBytes(), size)
+			}
+			return
+		}
+	}
+
+	t.Fatalf("go tool nm did not report size for runtime.gogo")
+}
+*/
+
+// golang.org/issue/7063
+func TestStopCPUProfilingWithProfilerOff(t *testing.T) {
+	SetCPUProfileRate(0)
+}
+
+// Addresses to test for faulting behavior.
+// This is less a test of SetPanicOnFault and more a check that
+// the operating system and the runtime can process these faults
+// correctly. That is, we're indirectly testing that without SetPanicOnFault
+// these would manage to turn into ordinary crashes.
+// Note that these are truncated on 32-bit systems, so the bottom 32 bits
+// of the larger addresses must themselves be invalid addresses.
+// We might get unlucky and the OS might have mapped one of these
+// addresses, but probably not: they're all in the first page, very high
+// adderesses that normally an OS would reserve for itself, or malformed
+// addresses. Even so, we might have to remove one or two on different
+// systems. We will see.
+
+var faultAddrs = []uint64{
+	// low addresses
+	0,
+	1,
+	0xfff,
+	// high (kernel) addresses
+	// or else malformed.
+	0xffffffffffffffff,
+	0xfffffffffffff001,
+	// no 0xffffffffffff0001; 0xffff0001 is mapped for 32-bit user space on OS X
+	// no 0xfffffffffff00001; 0xfff00001 is mapped for 32-bit user space sometimes on Linux
+	0xffffffffff000001,
+	0xfffffffff0000001,
+	0xffffffff00000001,
+	0xfffffff000000001,
+	0xffffff0000000001,
+	0xfffff00000000001,
+	0xffff000000000001,
+	0xfff0000000000001,
+	0xff00000000000001,
+	0xf000000000000001,
+	0x8000000000000001,
+}
+
+func TestSetPanicOnFault(t *testing.T) {
+	// This currently results in a fault in the signal trampoline on
+	// dragonfly/386 - see issue 7421.
+	if GOOS == "dragonfly" && GOARCH == "386" {
+		t.Skip("skipping test on dragonfly/386")
+	}
+
+	old := debug.SetPanicOnFault(true)
+	defer debug.SetPanicOnFault(old)
+
+	for _, addr := range faultAddrs {
+		if Compiler == "gccgo" && GOARCH == "386" && (addr&0xff000000) != 0 {
+			// On gccgo these addresses can be used for
+			// the thread stack.
+			continue
+		}
+		testSetPanicOnFault(t, uintptr(addr))
+	}
+}
+
+func testSetPanicOnFault(t *testing.T, addr uintptr) {
+	if GOOS == "nacl" {
+		t.Skip("nacl doesn't seem to fault on high addresses")
+	}
+
+	defer func() {
+		if err := recover(); err == nil {
+			t.Fatalf("did not find error in recover")
+		}
+	}()
+
+	var p *int
+	p = (*int)(unsafe.Pointer(addr))
+	println(*p)
+	t.Fatalf("still here - should have faulted on address %#x", addr)
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/runtime_unix_test.go b/third_party/gofrontend/libgo/go/runtime/runtime_unix_test.go
new file mode 100644
index 0000000..963de8c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/runtime_unix_test.go
@@ -0,0 +1,56 @@
+// Copyright 2013 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.
+
+// Only works on systems with syscall.Close.
+// We need a fast system call to provoke the race,
+// and Close(-1) is nearly universally fast.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd plan9
+
+package runtime_test
+
+import (
+	"runtime"
+	"sync"
+	"sync/atomic"
+	"syscall"
+	"testing"
+)
+
+func TestGoroutineProfile(t *testing.T) {
+	// GoroutineProfile used to use the wrong starting sp for
+	// goroutines coming out of system calls, causing possible
+	// crashes.
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(100))
+
+	var stop uint32
+	defer atomic.StoreUint32(&stop, 1) // in case of panic
+
+	var wg sync.WaitGroup
+	for i := 0; i < 4; i++ {
+		wg.Add(1)
+		go func() {
+			for atomic.LoadUint32(&stop) == 0 {
+				syscall.Close(-1)
+			}
+			wg.Done()
+		}()
+	}
+
+	max := 10000
+	if testing.Short() {
+		max = 100
+	}
+	stk := make([]runtime.StackRecord, 100)
+	for n := 0; n < max; n++ {
+		_, ok := runtime.GoroutineProfile(stk)
+		if !ok {
+			t.Fatalf("GoroutineProfile failed")
+		}
+	}
+
+	// If the program didn't crash, we passed.
+	atomic.StoreUint32(&stop, 1)
+	wg.Wait()
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/softfloat64.go b/third_party/gofrontend/libgo/go/runtime/softfloat64.go
new file mode 100644
index 0000000..4fcf8f2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/softfloat64.go
@@ -0,0 +1,498 @@
+// Copyright 2010 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.
+
+// Software IEEE754 64-bit floating point.
+// Only referred to (and thus linked in) by arm port
+// and by tests in this directory.
+
+package runtime
+
+const (
+	mantbits64 uint = 52
+	expbits64  uint = 11
+	bias64          = -1<<(expbits64-1) + 1
+
+	nan64 uint64 = (1<<expbits64-1)<<mantbits64 + 1
+	inf64 uint64 = (1<<expbits64 - 1) << mantbits64
+	neg64 uint64 = 1 << (expbits64 + mantbits64)
+
+	mantbits32 uint = 23
+	expbits32  uint = 8
+	bias32          = -1<<(expbits32-1) + 1
+
+	nan32 uint32 = (1<<expbits32-1)<<mantbits32 + 1
+	inf32 uint32 = (1<<expbits32 - 1) << mantbits32
+	neg32 uint32 = 1 << (expbits32 + mantbits32)
+)
+
+func funpack64(f uint64) (sign, mant uint64, exp int, inf, nan bool) {
+	sign = f & (1 << (mantbits64 + expbits64))
+	mant = f & (1<<mantbits64 - 1)
+	exp = int(f>>mantbits64) & (1<<expbits64 - 1)
+
+	switch exp {
+	case 1<<expbits64 - 1:
+		if mant != 0 {
+			nan = true
+			return
+		}
+		inf = true
+		return
+
+	case 0:
+		// denormalized
+		if mant != 0 {
+			exp += bias64 + 1
+			for mant < 1<<mantbits64 {
+				mant <<= 1
+				exp--
+			}
+		}
+
+	default:
+		// add implicit top bit
+		mant |= 1 << mantbits64
+		exp += bias64
+	}
+	return
+}
+
+func funpack32(f uint32) (sign, mant uint32, exp int, inf, nan bool) {
+	sign = f & (1 << (mantbits32 + expbits32))
+	mant = f & (1<<mantbits32 - 1)
+	exp = int(f>>mantbits32) & (1<<expbits32 - 1)
+
+	switch exp {
+	case 1<<expbits32 - 1:
+		if mant != 0 {
+			nan = true
+			return
+		}
+		inf = true
+		return
+
+	case 0:
+		// denormalized
+		if mant != 0 {
+			exp += bias32 + 1
+			for mant < 1<<mantbits32 {
+				mant <<= 1
+				exp--
+			}
+		}
+
+	default:
+		// add implicit top bit
+		mant |= 1 << mantbits32
+		exp += bias32
+	}
+	return
+}
+
+func fpack64(sign, mant uint64, exp int, trunc uint64) uint64 {
+	mant0, exp0, trunc0 := mant, exp, trunc
+	if mant == 0 {
+		return sign
+	}
+	for mant < 1<<mantbits64 {
+		mant <<= 1
+		exp--
+	}
+	for mant >= 4<<mantbits64 {
+		trunc |= mant & 1
+		mant >>= 1
+		exp++
+	}
+	if mant >= 2<<mantbits64 {
+		if mant&1 != 0 && (trunc != 0 || mant&2 != 0) {
+			mant++
+			if mant >= 4<<mantbits64 {
+				mant >>= 1
+				exp++
+			}
+		}
+		mant >>= 1
+		exp++
+	}
+	if exp >= 1<<expbits64-1+bias64 {
+		return sign ^ inf64
+	}
+	if exp < bias64+1 {
+		if exp < bias64-int(mantbits64) {
+			return sign | 0
+		}
+		// repeat expecting denormal
+		mant, exp, trunc = mant0, exp0, trunc0
+		for exp < bias64 {
+			trunc |= mant & 1
+			mant >>= 1
+			exp++
+		}
+		if mant&1 != 0 && (trunc != 0 || mant&2 != 0) {
+			mant++
+		}
+		mant >>= 1
+		exp++
+		if mant < 1<<mantbits64 {
+			return sign | mant
+		}
+	}
+	return sign | uint64(exp-bias64)<<mantbits64 | mant&(1<<mantbits64-1)
+}
+
+func fpack32(sign, mant uint32, exp int, trunc uint32) uint32 {
+	mant0, exp0, trunc0 := mant, exp, trunc
+	if mant == 0 {
+		return sign
+	}
+	for mant < 1<<mantbits32 {
+		mant <<= 1
+		exp--
+	}
+	for mant >= 4<<mantbits32 {
+		trunc |= mant & 1
+		mant >>= 1
+		exp++
+	}
+	if mant >= 2<<mantbits32 {
+		if mant&1 != 0 && (trunc != 0 || mant&2 != 0) {
+			mant++
+			if mant >= 4<<mantbits32 {
+				mant >>= 1
+				exp++
+			}
+		}
+		mant >>= 1
+		exp++
+	}
+	if exp >= 1<<expbits32-1+bias32 {
+		return sign ^ inf32
+	}
+	if exp < bias32+1 {
+		if exp < bias32-int(mantbits32) {
+			return sign | 0
+		}
+		// repeat expecting denormal
+		mant, exp, trunc = mant0, exp0, trunc0
+		for exp < bias32 {
+			trunc |= mant & 1
+			mant >>= 1
+			exp++
+		}
+		if mant&1 != 0 && (trunc != 0 || mant&2 != 0) {
+			mant++
+		}
+		mant >>= 1
+		exp++
+		if mant < 1<<mantbits32 {
+			return sign | mant
+		}
+	}
+	return sign | uint32(exp-bias32)<<mantbits32 | mant&(1<<mantbits32-1)
+}
+
+func fadd64(f, g uint64) uint64 {
+	fs, fm, fe, fi, fn := funpack64(f)
+	gs, gm, ge, gi, gn := funpack64(g)
+
+	// Special cases.
+	switch {
+	case fn || gn: // NaN + x or x + NaN = NaN
+		return nan64
+
+	case fi && gi && fs != gs: // +Inf + -Inf or -Inf + +Inf = NaN
+		return nan64
+
+	case fi: // ±Inf + g = ±Inf
+		return f
+
+	case gi: // f + ±Inf = ±Inf
+		return g
+
+	case fm == 0 && gm == 0 && fs != 0 && gs != 0: // -0 + -0 = -0
+		return f
+
+	case fm == 0: // 0 + g = g but 0 + -0 = +0
+		if gm == 0 {
+			g ^= gs
+		}
+		return g
+
+	case gm == 0: // f + 0 = f
+		return f
+
+	}
+
+	if fe < ge || fe == ge && fm < gm {
+		f, g, fs, fm, fe, gs, gm, ge = g, f, gs, gm, ge, fs, fm, fe
+	}
+
+	shift := uint(fe - ge)
+	fm <<= 2
+	gm <<= 2
+	trunc := gm & (1<<shift - 1)
+	gm >>= shift
+	if fs == gs {
+		fm += gm
+	} else {
+		fm -= gm
+		if trunc != 0 {
+			fm--
+		}
+	}
+	if fm == 0 {
+		fs = 0
+	}
+	return fpack64(fs, fm, fe-2, trunc)
+}
+
+func fsub64(f, g uint64) uint64 {
+	return fadd64(f, fneg64(g))
+}
+
+func fneg64(f uint64) uint64 {
+	return f ^ (1 << (mantbits64 + expbits64))
+}
+
+func fmul64(f, g uint64) uint64 {
+	fs, fm, fe, fi, fn := funpack64(f)
+	gs, gm, ge, gi, gn := funpack64(g)
+
+	// Special cases.
+	switch {
+	case fn || gn: // NaN * g or f * NaN = NaN
+		return nan64
+
+	case fi && gi: // Inf * Inf = Inf (with sign adjusted)
+		return f ^ gs
+
+	case fi && gm == 0, fm == 0 && gi: // 0 * Inf = Inf * 0 = NaN
+		return nan64
+
+	case fm == 0: // 0 * x = 0 (with sign adjusted)
+		return f ^ gs
+
+	case gm == 0: // x * 0 = 0 (with sign adjusted)
+		return g ^ fs
+	}
+
+	// 53-bit * 53-bit = 107- or 108-bit
+	lo, hi := mullu(fm, gm)
+	shift := mantbits64 - 1
+	trunc := lo & (1<<shift - 1)
+	mant := hi<<(64-shift) | lo>>shift
+	return fpack64(fs^gs, mant, fe+ge-1, trunc)
+}
+
+func fdiv64(f, g uint64) uint64 {
+	fs, fm, fe, fi, fn := funpack64(f)
+	gs, gm, ge, gi, gn := funpack64(g)
+
+	// Special cases.
+	switch {
+	case fn || gn: // NaN / g = f / NaN = NaN
+		return nan64
+
+	case fi && gi: // ±Inf / ±Inf = NaN
+		return nan64
+
+	case !fi && !gi && fm == 0 && gm == 0: // 0 / 0 = NaN
+		return nan64
+
+	case fi, !gi && gm == 0: // Inf / g = f / 0 = Inf
+		return fs ^ gs ^ inf64
+
+	case gi, fm == 0: // f / Inf = 0 / g = Inf
+		return fs ^ gs ^ 0
+	}
+	_, _, _, _ = fi, fn, gi, gn
+
+	// 53-bit<<54 / 53-bit = 53- or 54-bit.
+	shift := mantbits64 + 2
+	q, r := divlu(fm>>(64-shift), fm<<shift, gm)
+	return fpack64(fs^gs, q, fe-ge-2, r)
+}
+
+func f64to32(f uint64) uint32 {
+	fs, fm, fe, fi, fn := funpack64(f)
+	if fn {
+		return nan32
+	}
+	fs32 := uint32(fs >> 32)
+	if fi {
+		return fs32 ^ inf32
+	}
+	const d = mantbits64 - mantbits32 - 1
+	return fpack32(fs32, uint32(fm>>d), fe-1, uint32(fm&(1<<d-1)))
+}
+
+func f32to64(f uint32) uint64 {
+	const d = mantbits64 - mantbits32
+	fs, fm, fe, fi, fn := funpack32(f)
+	if fn {
+		return nan64
+	}
+	fs64 := uint64(fs) << 32
+	if fi {
+		return fs64 ^ inf64
+	}
+	return fpack64(fs64, uint64(fm)<<d, fe, 0)
+}
+
+func fcmp64(f, g uint64) (cmp int, isnan bool) {
+	fs, fm, _, fi, fn := funpack64(f)
+	gs, gm, _, gi, gn := funpack64(g)
+
+	switch {
+	case fn, gn: // flag NaN
+		return 0, true
+
+	case !fi && !gi && fm == 0 && gm == 0: // ±0 == ±0
+		return 0, false
+
+	case fs > gs: // f < 0, g > 0
+		return -1, false
+
+	case fs < gs: // f > 0, g < 0
+		return +1, false
+
+	// Same sign, not NaN.
+	// Can compare encodings directly now.
+	// Reverse for sign.
+	case fs == 0 && f < g, fs != 0 && f > g:
+		return -1, false
+
+	case fs == 0 && f > g, fs != 0 && f < g:
+		return +1, false
+	}
+
+	// f == g
+	return 0, false
+}
+
+func f64toint(f uint64) (val int64, ok bool) {
+	fs, fm, fe, fi, fn := funpack64(f)
+
+	switch {
+	case fi, fn: // NaN
+		return 0, false
+
+	case fe < -1: // f < 0.5
+		return 0, false
+
+	case fe > 63: // f >= 2^63
+		if fs != 0 && fm == 0 { // f == -2^63
+			return -1 << 63, true
+		}
+		if fs != 0 {
+			return 0, false
+		}
+		return 0, false
+	}
+
+	for fe > int(mantbits64) {
+		fe--
+		fm <<= 1
+	}
+	for fe < int(mantbits64) {
+		fe++
+		fm >>= 1
+	}
+	val = int64(fm)
+	if fs != 0 {
+		val = -val
+	}
+	return val, true
+}
+
+func fintto64(val int64) (f uint64) {
+	fs := uint64(val) & (1 << 63)
+	mant := uint64(val)
+	if fs != 0 {
+		mant = -mant
+	}
+	return fpack64(fs, mant, int(mantbits64), 0)
+}
+
+// 64x64 -> 128 multiply.
+// adapted from hacker's delight.
+func mullu(u, v uint64) (lo, hi uint64) {
+	const (
+		s    = 32
+		mask = 1<<s - 1
+	)
+	u0 := u & mask
+	u1 := u >> s
+	v0 := v & mask
+	v1 := v >> s
+	w0 := u0 * v0
+	t := u1*v0 + w0>>s
+	w1 := t & mask
+	w2 := t >> s
+	w1 += u0 * v1
+	return u * v, u1*v1 + w2 + w1>>s
+}
+
+// 128/64 -> 64 quotient, 64 remainder.
+// adapted from hacker's delight
+func divlu(u1, u0, v uint64) (q, r uint64) {
+	const b = 1 << 32
+
+	if u1 >= v {
+		return 1<<64 - 1, 1<<64 - 1
+	}
+
+	// s = nlz(v); v <<= s
+	s := uint(0)
+	for v&(1<<63) == 0 {
+		s++
+		v <<= 1
+	}
+
+	vn1 := v >> 32
+	vn0 := v & (1<<32 - 1)
+	un32 := u1<<s | u0>>(64-s)
+	un10 := u0 << s
+	un1 := un10 >> 32
+	un0 := un10 & (1<<32 - 1)
+	q1 := un32 / vn1
+	rhat := un32 - q1*vn1
+
+again1:
+	if q1 >= b || q1*vn0 > b*rhat+un1 {
+		q1--
+		rhat += vn1
+		if rhat < b {
+			goto again1
+		}
+	}
+
+	un21 := un32*b + un1 - q1*v
+	q0 := un21 / vn1
+	rhat = un21 - q0*vn1
+
+again2:
+	if q0 >= b || q0*vn0 > b*rhat+un0 {
+		q0--
+		rhat += vn1
+		if rhat < b {
+			goto again2
+		}
+	}
+
+	return q1*b + q0, (un21*b + un0 - q0*v) >> s
+}
+
+// callable from C
+
+func fadd64c(f, g uint64, ret *uint64)            { *ret = fadd64(f, g) }
+func fsub64c(f, g uint64, ret *uint64)            { *ret = fsub64(f, g) }
+func fmul64c(f, g uint64, ret *uint64)            { *ret = fmul64(f, g) }
+func fdiv64c(f, g uint64, ret *uint64)            { *ret = fdiv64(f, g) }
+func fneg64c(f uint64, ret *uint64)               { *ret = fneg64(f) }
+func f32to64c(f uint32, ret *uint64)              { *ret = f32to64(f) }
+func f64to32c(f uint64, ret *uint32)              { *ret = f64to32(f) }
+func fcmp64c(f, g uint64, ret *int, retnan *bool) { *ret, *retnan = fcmp64(f, g) }
+func fintto64c(val int64, ret *uint64)            { *ret = fintto64(val) }
+func f64tointc(f uint64, ret *int64, retok *bool) { *ret, *retok = f64toint(f) }
diff --git a/third_party/gofrontend/libgo/go/runtime/softfloat64_test.go b/third_party/gofrontend/libgo/go/runtime/softfloat64_test.go
new file mode 100644
index 0000000..df63010
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/softfloat64_test.go
@@ -0,0 +1,198 @@
+// Copyright 2010 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 runtime_test
+
+import (
+	"math"
+	"math/rand"
+	. "runtime"
+	"testing"
+)
+
+// turn uint64 op into float64 op
+func fop(f func(x, y uint64) uint64) func(x, y float64) float64 {
+	return func(x, y float64) float64 {
+		bx := math.Float64bits(x)
+		by := math.Float64bits(y)
+		return math.Float64frombits(f(bx, by))
+	}
+}
+
+func add(x, y float64) float64 { return x + y }
+func sub(x, y float64) float64 { return x - y }
+func mul(x, y float64) float64 { return x * y }
+func div(x, y float64) float64 { return x / y }
+
+func TestFloat64(t *testing.T) {
+	base := []float64{
+		0,
+		math.Copysign(0, -1),
+		-1,
+		1,
+		math.NaN(),
+		math.Inf(+1),
+		math.Inf(-1),
+		0.1,
+		1.5,
+		1.9999999999999998,     // all 1s mantissa
+		1.3333333333333333,     // 1.010101010101...
+		1.1428571428571428,     // 1.001001001001...
+		1.112536929253601e-308, // first normal
+		2,
+		4,
+		8,
+		16,
+		32,
+		64,
+		128,
+		256,
+		3,
+		12,
+		1234,
+		123456,
+		-0.1,
+		-1.5,
+		-1.9999999999999998,
+		-1.3333333333333333,
+		-1.1428571428571428,
+		-2,
+		-3,
+		1e-200,
+		1e-300,
+		1e-310,
+		5e-324,
+		1e-105,
+		1e-305,
+		1e+200,
+		1e+306,
+		1e+307,
+		1e+308,
+	}
+	all := make([]float64, 200)
+	copy(all, base)
+	for i := len(base); i < len(all); i++ {
+		all[i] = rand.NormFloat64()
+	}
+
+	test(t, "+", add, fop(Fadd64), all)
+	test(t, "-", sub, fop(Fsub64), all)
+	if GOARCH != "386" { // 386 is not precise!
+		test(t, "*", mul, fop(Fmul64), all)
+		test(t, "/", div, fop(Fdiv64), all)
+	}
+}
+
+// 64 -hw-> 32 -hw-> 64
+func trunc32(f float64) float64 {
+	return float64(float32(f))
+}
+
+// 64 -sw->32 -hw-> 64
+func to32sw(f float64) float64 {
+	return float64(math.Float32frombits(F64to32(math.Float64bits(f))))
+}
+
+// 64 -hw->32 -sw-> 64
+func to64sw(f float64) float64 {
+	return math.Float64frombits(F32to64(math.Float32bits(float32(f))))
+}
+
+// float64 -hw-> int64 -hw-> float64
+func hwint64(f float64) float64 {
+	return float64(int64(f))
+}
+
+// float64 -hw-> int32 -hw-> float64
+func hwint32(f float64) float64 {
+	return float64(int32(f))
+}
+
+// float64 -sw-> int64 -hw-> float64
+func toint64sw(f float64) float64 {
+	i, ok := F64toint(math.Float64bits(f))
+	if !ok {
+		// There's no right answer for out of range.
+		// Match the hardware to pass the test.
+		i = int64(f)
+	}
+	return float64(i)
+}
+
+// float64 -hw-> int64 -sw-> float64
+func fromint64sw(f float64) float64 {
+	return math.Float64frombits(Fintto64(int64(f)))
+}
+
+var nerr int
+
+func err(t *testing.T, format string, args ...interface{}) {
+	t.Errorf(format, args...)
+
+	// cut errors off after a while.
+	// otherwise we spend all our time
+	// allocating memory to hold the
+	// formatted output.
+	if nerr++; nerr >= 10 {
+		t.Fatal("too many errors")
+	}
+}
+
+func test(t *testing.T, op string, hw, sw func(float64, float64) float64, all []float64) {
+	for _, f := range all {
+		for _, g := range all {
+			h := hw(f, g)
+			s := sw(f, g)
+			if !same(h, s) {
+				err(t, "%g %s %g = sw %g, hw %g\n", f, op, g, s, h)
+			}
+			testu(t, "to32", trunc32, to32sw, h)
+			testu(t, "to64", trunc32, to64sw, h)
+			testu(t, "toint64", hwint64, toint64sw, h)
+			testu(t, "fromint64", hwint64, fromint64sw, h)
+			testcmp(t, f, h)
+			testcmp(t, h, f)
+			testcmp(t, g, h)
+			testcmp(t, h, g)
+		}
+	}
+}
+
+func testu(t *testing.T, op string, hw, sw func(float64) float64, v float64) {
+	h := hw(v)
+	s := sw(v)
+	if !same(h, s) {
+		err(t, "%s %g = sw %g, hw %g\n", op, v, s, h)
+	}
+}
+
+func hwcmp(f, g float64) (cmp int, isnan bool) {
+	switch {
+	case f < g:
+		return -1, false
+	case f > g:
+		return +1, false
+	case f == g:
+		return 0, false
+	}
+	return 0, true // must be NaN
+}
+
+func testcmp(t *testing.T, f, g float64) {
+	hcmp, hisnan := hwcmp(f, g)
+	scmp, sisnan := Fcmp64(math.Float64bits(f), math.Float64bits(g))
+	if hcmp != scmp || hisnan != sisnan {
+		err(t, "cmp(%g, %g) = sw %v, %v, hw %v, %v\n", f, g, scmp, sisnan, hcmp, hisnan)
+	}
+}
+
+func same(f, g float64) bool {
+	if math.IsNaN(f) && math.IsNaN(g) {
+		return true
+	}
+	if math.Copysign(1, f) != math.Copysign(1, g) {
+		return false
+	}
+	return f == g
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/string_test.go b/third_party/gofrontend/libgo/go/runtime/string_test.go
new file mode 100644
index 0000000..df3ff06
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/string_test.go
@@ -0,0 +1,77 @@
+// 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 runtime_test
+
+import (
+	"testing"
+)
+
+func BenchmarkCompareStringEqual(b *testing.B) {
+	bytes := []byte("Hello Gophers!")
+	s1, s2 := string(bytes), string(bytes)
+	for i := 0; i < b.N; i++ {
+		if s1 != s2 {
+			b.Fatal("s1 != s2")
+		}
+	}
+}
+
+func BenchmarkCompareStringIdentical(b *testing.B) {
+	s1 := "Hello Gophers!"
+	s2 := s1
+	for i := 0; i < b.N; i++ {
+		if s1 != s2 {
+			b.Fatal("s1 != s2")
+		}
+	}
+}
+
+func BenchmarkCompareStringSameLength(b *testing.B) {
+	s1 := "Hello Gophers!"
+	s2 := "Hello, Gophers"
+	for i := 0; i < b.N; i++ {
+		if s1 == s2 {
+			b.Fatal("s1 == s2")
+		}
+	}
+}
+
+func BenchmarkCompareStringDifferentLength(b *testing.B) {
+	s1 := "Hello Gophers!"
+	s2 := "Hello, Gophers!"
+	for i := 0; i < b.N; i++ {
+		if s1 == s2 {
+			b.Fatal("s1 == s2")
+		}
+	}
+}
+
+func BenchmarkCompareStringBigUnaligned(b *testing.B) {
+	bytes := make([]byte, 0, 1<<20)
+	for len(bytes) < 1<<20 {
+		bytes = append(bytes, "Hello Gophers!"...)
+	}
+	s1, s2 := string(bytes), "hello"+string(bytes)
+	for i := 0; i < b.N; i++ {
+		if s1 != s2[len("hello"):] {
+			b.Fatal("s1 != s2")
+		}
+	}
+	b.SetBytes(int64(len(s1)))
+}
+
+func BenchmarkCompareStringBig(b *testing.B) {
+	bytes := make([]byte, 0, 1<<20)
+	for len(bytes) < 1<<20 {
+		bytes = append(bytes, "Hello Gophers!"...)
+	}
+	s1, s2 := string(bytes), string(bytes)
+	for i := 0; i < b.N; i++ {
+		if s1 != s2 {
+			b.Fatal("s1 != s2")
+		}
+	}
+	b.SetBytes(int64(len(s1)))
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/symtab_test.go b/third_party/gofrontend/libgo/go/runtime/symtab_test.go
new file mode 100644
index 0000000..0db63c3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/symtab_test.go
@@ -0,0 +1,55 @@
+// 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 runtime_test
+
+import (
+	"runtime"
+	"strings"
+	"testing"
+)
+
+var _ = runtime.Caller
+var _ = strings.HasSuffix
+type _ testing.T
+
+/* runtime.Caller is not fully implemented for gccgo.
+
+func TestCaller(t *testing.T) {
+	procs := runtime.GOMAXPROCS(-1)
+	c := make(chan bool, procs)
+	for p := 0; p < procs; p++ {
+		go func() {
+			for i := 0; i < 1000; i++ {
+				testCallerFoo(t)
+			}
+			c <- true
+		}()
+		defer func() {
+			<-c
+		}()
+	}
+}
+
+func testCallerFoo(t *testing.T) {
+	testCallerBar(t)
+}
+
+func testCallerBar(t *testing.T) {
+	for i := 0; i < 2; i++ {
+		pc, file, line, ok := runtime.Caller(i)
+		f := runtime.FuncForPC(pc)
+		if !ok ||
+			!strings.HasSuffix(file, "symtab_test.go") ||
+			(i == 0 && !strings.HasSuffix(f.Name(), "testCallerBar")) ||
+			(i == 1 && !strings.HasSuffix(f.Name(), "testCallerFoo")) ||
+			line < 5 || line > 1000 ||
+			f.Entry() >= pc {
+			t.Errorf("incorrect symbol info %d: %t %d %d %s %s %d",
+				i, ok, f.Entry(), pc, f.Name(), file, line)
+		}
+	}
+}
+
+*/
diff --git a/third_party/gofrontend/libgo/go/runtime/type.go b/third_party/gofrontend/libgo/go/runtime/type.go
new file mode 100644
index 0000000..a5ed8af
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/type.go
@@ -0,0 +1,57 @@
+// 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.
+
+/*
+ * Runtime type representation.
+ * This file exists only to provide types that 6l can turn into
+ * DWARF information for use by gdb.  Nothing else uses these.
+ * They should match the same types in ../reflect/type.go.
+ * For comments see ../reflect/type.go.
+ */
+
+package runtime
+
+import "unsafe"
+
+type rtype struct {
+	kind       uint8
+	align      uint8
+	fieldAlign uint8
+	size       uintptr
+	hash       uint32
+
+	hashfn  func(unsafe.Pointer, uintptr) uintptr
+	equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) bool
+
+	gc     unsafe.Pointer
+	string *string
+	*uncommonType
+	ptrToThis *rtype
+	zero      unsafe.Pointer
+}
+
+type _method struct {
+	name    *string
+	pkgPath *string
+	mtyp    *rtype
+	typ     *rtype
+	tfn     unsafe.Pointer
+}
+
+type uncommonType struct {
+	name    *string
+	pkgPath *string
+	methods []_method
+}
+
+type _imethod struct {
+	name    *string
+	pkgPath *string
+	typ     *rtype
+}
+
+type interfaceType struct {
+	rtype
+	methods []_imethod
+}
diff --git a/third_party/gofrontend/libgo/go/runtime/vlop_arm_test.go b/third_party/gofrontend/libgo/go/runtime/vlop_arm_test.go
new file mode 100644
index 0000000..cd28419
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/runtime/vlop_arm_test.go
@@ -0,0 +1,70 @@
+// 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 runtime_test
+
+import "testing"
+
+// arm soft division benchmarks adapted from
+// http://ridiculousfish.com/files/division_benchmarks.tar.gz
+
+const numeratorsSize = 1 << 21
+
+var numerators = randomNumerators()
+
+type randstate struct {
+	hi, lo uint32
+}
+
+func (r *randstate) rand() uint32 {
+	r.hi = r.hi<<16 + r.hi>>16
+	r.hi += r.lo
+	r.lo += r.hi
+	return r.hi
+}
+
+func randomNumerators() []uint32 {
+	numerators := make([]uint32, numeratorsSize)
+	random := &randstate{2147483563, 2147483563 ^ 0x49616E42}
+	for i := range numerators {
+		numerators[i] = random.rand()
+	}
+	return numerators
+}
+
+func bmUint32Div(divisor uint32, b *testing.B) {
+	var sum uint32
+	for i := 0; i < b.N; i++ {
+		sum += numerators[i&(numeratorsSize-1)] / divisor
+	}
+}
+
+func BenchmarkUint32Div7(b *testing.B)         { bmUint32Div(7, b) }
+func BenchmarkUint32Div37(b *testing.B)        { bmUint32Div(37, b) }
+func BenchmarkUint32Div123(b *testing.B)       { bmUint32Div(123, b) }
+func BenchmarkUint32Div763(b *testing.B)       { bmUint32Div(763, b) }
+func BenchmarkUint32Div1247(b *testing.B)      { bmUint32Div(1247, b) }
+func BenchmarkUint32Div9305(b *testing.B)      { bmUint32Div(9305, b) }
+func BenchmarkUint32Div13307(b *testing.B)     { bmUint32Div(13307, b) }
+func BenchmarkUint32Div52513(b *testing.B)     { bmUint32Div(52513, b) }
+func BenchmarkUint32Div60978747(b *testing.B)  { bmUint32Div(60978747, b) }
+func BenchmarkUint32Div106956295(b *testing.B) { bmUint32Div(106956295, b) }
+
+func bmUint32Mod(divisor uint32, b *testing.B) {
+	var sum uint32
+	for i := 0; i < b.N; i++ {
+		sum += numerators[i&(numeratorsSize-1)] % divisor
+	}
+}
+
+func BenchmarkUint32Mod7(b *testing.B)         { bmUint32Mod(7, b) }
+func BenchmarkUint32Mod37(b *testing.B)        { bmUint32Mod(37, b) }
+func BenchmarkUint32Mod123(b *testing.B)       { bmUint32Mod(123, b) }
+func BenchmarkUint32Mod763(b *testing.B)       { bmUint32Mod(763, b) }
+func BenchmarkUint32Mod1247(b *testing.B)      { bmUint32Mod(1247, b) }
+func BenchmarkUint32Mod9305(b *testing.B)      { bmUint32Mod(9305, b) }
+func BenchmarkUint32Mod13307(b *testing.B)     { bmUint32Mod(13307, b) }
+func BenchmarkUint32Mod52513(b *testing.B)     { bmUint32Mod(52513, b) }
+func BenchmarkUint32Mod60978747(b *testing.B)  { bmUint32Mod(60978747, b) }
+func BenchmarkUint32Mod106956295(b *testing.B) { bmUint32Mod(106956295, b) }
diff --git a/third_party/gofrontend/libgo/go/sort/example_interface_test.go b/third_party/gofrontend/libgo/go/sort/example_interface_test.go
new file mode 100644
index 0000000..442204e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sort/example_interface_test.go
@@ -0,0 +1,44 @@
+// 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.
+
+package sort_test
+
+import (
+	"fmt"
+	"sort"
+)
+
+type Person struct {
+	Name string
+	Age  int
+}
+
+func (p Person) String() string {
+	return fmt.Sprintf("%s: %d", p.Name, p.Age)
+}
+
+// ByAge implements sort.Interface for []Person based on
+// the Age field.
+type ByAge []Person
+
+func (a ByAge) Len() int           { return len(a) }
+func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
+
+func Example() {
+	people := []Person{
+		{"Bob", 31},
+		{"John", 42},
+		{"Michael", 17},
+		{"Jenny", 26},
+	}
+
+	fmt.Println(people)
+	sort.Sort(ByAge(people))
+	fmt.Println(people)
+
+	// Output:
+	// [Bob: 31 John: 42 Michael: 17 Jenny: 26]
+	// [Michael: 17 Jenny: 26 Bob: 31 John: 42]
+}
diff --git a/third_party/gofrontend/libgo/go/sort/example_keys_test.go b/third_party/gofrontend/libgo/go/sort/example_keys_test.go
new file mode 100644
index 0000000..a8e47e4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sort/example_keys_test.go
@@ -0,0 +1,96 @@
+// Copyright 2013 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 sort_test
+
+import (
+	"fmt"
+	"sort"
+)
+
+// A couple of type definitions to make the units clear.
+type earthMass float64
+type au float64
+
+// A Planet defines the properties of a solar system object.
+type Planet struct {
+	name     string
+	mass     earthMass
+	distance au
+}
+
+// By is the type of a "less" function that defines the ordering of its Planet arguments.
+type By func(p1, p2 *Planet) bool
+
+// Sort is a method on the function type, By, that sorts the argument slice according to the function.
+func (by By) Sort(planets []Planet) {
+	ps := &planetSorter{
+		planets: planets,
+		by:      by, // The Sort method's receiver is the function (closure) that defines the sort order.
+	}
+	sort.Sort(ps)
+}
+
+// planetSorter joins a By function and a slice of Planets to be sorted.
+type planetSorter struct {
+	planets []Planet
+	by      func(p1, p2 *Planet) bool // Closure used in the Less method.
+}
+
+// Len is part of sort.Interface.
+func (s *planetSorter) Len() int {
+	return len(s.planets)
+}
+
+// Swap is part of sort.Interface.
+func (s *planetSorter) Swap(i, j int) {
+	s.planets[i], s.planets[j] = s.planets[j], s.planets[i]
+}
+
+// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
+func (s *planetSorter) Less(i, j int) bool {
+	return s.by(&s.planets[i], &s.planets[j])
+}
+
+var planets = []Planet{
+	{"Mercury", 0.055, 0.4},
+	{"Venus", 0.815, 0.7},
+	{"Earth", 1.0, 1.0},
+	{"Mars", 0.107, 1.5},
+}
+
+// ExampleSortKeys demonstrates a technique for sorting a struct type using programmable sort criteria.
+func Example_sortKeys() {
+	// Closures that order the Planet structure.
+	name := func(p1, p2 *Planet) bool {
+		return p1.name < p2.name
+	}
+	mass := func(p1, p2 *Planet) bool {
+		return p1.mass < p2.mass
+	}
+	distance := func(p1, p2 *Planet) bool {
+		return p1.distance < p2.distance
+	}
+	decreasingDistance := func(p1, p2 *Planet) bool {
+		return !distance(p1, p2)
+	}
+
+	// Sort the planets by the various criteria.
+	By(name).Sort(planets)
+	fmt.Println("By name:", planets)
+
+	By(mass).Sort(planets)
+	fmt.Println("By mass:", planets)
+
+	By(distance).Sort(planets)
+	fmt.Println("By distance:", planets)
+
+	By(decreasingDistance).Sort(planets)
+	fmt.Println("By decreasing distance:", planets)
+
+	// Output: By name: [{Earth 1 1} {Mars 0.107 1.5} {Mercury 0.055 0.4} {Venus 0.815 0.7}]
+	// By mass: [{Mercury 0.055 0.4} {Mars 0.107 1.5} {Venus 0.815 0.7} {Earth 1 1}]
+	// By distance: [{Mercury 0.055 0.4} {Venus 0.815 0.7} {Earth 1 1} {Mars 0.107 1.5}]
+	// By decreasing distance: [{Mars 0.107 1.5} {Earth 1 1} {Venus 0.815 0.7} {Mercury 0.055 0.4}]
+}
diff --git a/third_party/gofrontend/libgo/go/sort/example_multi_test.go b/third_party/gofrontend/libgo/go/sort/example_multi_test.go
new file mode 100644
index 0000000..ac31654
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sort/example_multi_test.go
@@ -0,0 +1,131 @@
+// Copyright 2013 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 sort_test
+
+import (
+	"fmt"
+	"sort"
+)
+
+// A Change is a record of source code changes, recording user, language, and delta size.
+type Change struct {
+	user     string
+	language string
+	lines    int
+}
+
+type lessFunc func(p1, p2 *Change) bool
+
+// multiSorter implements the Sort interface, sorting the changes within.
+type multiSorter struct {
+	changes []Change
+	less    []lessFunc
+}
+
+// Sort sorts the argument slice according to the less functions passed to OrderedBy.
+func (ms *multiSorter) Sort(changes []Change) {
+	ms.changes = changes
+	sort.Sort(ms)
+}
+
+// OrderedBy returns a Sorter that sorts using the less functions, in order.
+// Call its Sort method to sort the data.
+func OrderedBy(less ...lessFunc) *multiSorter {
+	return &multiSorter{
+		less: less,
+	}
+}
+
+// Len is part of sort.Interface.
+func (ms *multiSorter) Len() int {
+	return len(ms.changes)
+}
+
+// Swap is part of sort.Interface.
+func (ms *multiSorter) Swap(i, j int) {
+	ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
+}
+
+// Less is part of sort.Interface. It is implemented by looping along the
+// less functions until it finds a comparison that is either Less or
+// !Less. Note that it can call the less functions twice per call. We
+// could change the functions to return -1, 0, 1 and reduce the
+// number of calls for greater efficiency: an exercise for the reader.
+func (ms *multiSorter) Less(i, j int) bool {
+	p, q := &ms.changes[i], &ms.changes[j]
+	// Try all but the last comparison.
+	var k int
+	for k = 0; k < len(ms.less)-1; k++ {
+		less := ms.less[k]
+		switch {
+		case less(p, q):
+			// p < q, so we have a decision.
+			return true
+		case less(q, p):
+			// p > q, so we have a decision.
+			return false
+		}
+		// p == q; try the next comparison.
+	}
+	// All comparisons to here said "equal", so just return whatever
+	// the final comparison reports.
+	return ms.less[k](p, q)
+}
+
+var changes = []Change{
+	{"gri", "Go", 100},
+	{"ken", "C", 150},
+	{"glenda", "Go", 200},
+	{"rsc", "Go", 200},
+	{"r", "Go", 100},
+	{"ken", "Go", 200},
+	{"dmr", "C", 100},
+	{"r", "C", 150},
+	{"gri", "Smalltalk", 80},
+}
+
+// ExampleMultiKeys demonstrates a technique for sorting a struct type using different
+// sets of multiple fields in the comparison. We chain together "Less" functions, each of
+// which compares a single field.
+func Example_sortMultiKeys() {
+	// Closures that order the Change structure.
+	user := func(c1, c2 *Change) bool {
+		return c1.user < c2.user
+	}
+	language := func(c1, c2 *Change) bool {
+		return c1.language < c2.language
+	}
+	increasingLines := func(c1, c2 *Change) bool {
+		return c1.lines < c2.lines
+	}
+	decreasingLines := func(c1, c2 *Change) bool {
+		return c1.lines > c2.lines // Note: > orders downwards.
+	}
+
+	// Simple use: Sort by user.
+	OrderedBy(user).Sort(changes)
+	fmt.Println("By user:", changes)
+
+	// More examples.
+	OrderedBy(user, increasingLines).Sort(changes)
+	fmt.Println("By user,<lines:", changes)
+
+	OrderedBy(user, decreasingLines).Sort(changes)
+	fmt.Println("By user,>lines:", changes)
+
+	OrderedBy(language, increasingLines).Sort(changes)
+	fmt.Println("By language,<lines:", changes)
+
+	OrderedBy(language, increasingLines, user).Sort(changes)
+	fmt.Println("By language,<lines,user:", changes)
+
+	// Output:
+	// By user: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken Go 200} {ken C 150} {r Go 100} {r C 150} {rsc Go 200}]
+	// By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
+	// By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
+	// By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
+	// By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
+
+}
diff --git a/third_party/gofrontend/libgo/go/sort/example_test.go b/third_party/gofrontend/libgo/go/sort/example_test.go
new file mode 100644
index 0000000..f7372be
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sort/example_test.go
@@ -0,0 +1,24 @@
+// 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.
+
+package sort_test
+
+import (
+	"fmt"
+	"sort"
+)
+
+func ExampleInts() {
+	s := []int{5, 2, 6, 3, 1, 4} // unsorted
+	sort.Ints(s)
+	fmt.Println(s)
+	// Output: [1 2 3 4 5 6]
+}
+
+func ExampleReverse() {
+	s := []int{5, 2, 6, 3, 1, 4} // unsorted
+	sort.Sort(sort.Reverse(sort.IntSlice(s)))
+	fmt.Println(s)
+	// Output: [6 5 4 3 2 1]
+}
diff --git a/third_party/gofrontend/libgo/go/sort/example_wrapper_test.go b/third_party/gofrontend/libgo/go/sort/example_wrapper_test.go
new file mode 100644
index 0000000..cf6d74c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sort/example_wrapper_test.go
@@ -0,0 +1,77 @@
+// 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.
+
+package sort_test
+
+import (
+	"fmt"
+	"sort"
+)
+
+type Grams int
+
+func (g Grams) String() string { return fmt.Sprintf("%dg", int(g)) }
+
+type Organ struct {
+	Name   string
+	Weight Grams
+}
+
+type Organs []*Organ
+
+func (s Organs) Len() int      { return len(s) }
+func (s Organs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// ByName implements sort.Interface by providing Less and using the Len and
+// Swap methods of the embedded Organs value.
+type ByName struct{ Organs }
+
+func (s ByName) Less(i, j int) bool { return s.Organs[i].Name < s.Organs[j].Name }
+
+// ByWeight implements sort.Interface by providing Less and using the Len and
+// Swap methods of the embedded Organs value.
+type ByWeight struct{ Organs }
+
+func (s ByWeight) Less(i, j int) bool { return s.Organs[i].Weight < s.Organs[j].Weight }
+
+func Example_sortWrapper() {
+	s := []*Organ{
+		{"brain", 1340},
+		{"heart", 290},
+		{"liver", 1494},
+		{"pancreas", 131},
+		{"prostate", 62},
+		{"spleen", 162},
+	}
+
+	sort.Sort(ByWeight{s})
+	fmt.Println("Organs by weight:")
+	printOrgans(s)
+
+	sort.Sort(ByName{s})
+	fmt.Println("Organs by name:")
+	printOrgans(s)
+
+	// Output:
+	// Organs by weight:
+	// prostate (62g)
+	// pancreas (131g)
+	// spleen   (162g)
+	// heart    (290g)
+	// brain    (1340g)
+	// liver    (1494g)
+	// Organs by name:
+	// brain    (1340g)
+	// heart    (290g)
+	// liver    (1494g)
+	// pancreas (131g)
+	// prostate (62g)
+	// spleen   (162g)
+}
+
+func printOrgans(s []*Organ) {
+	for _, o := range s {
+		fmt.Printf("%-8s (%v)\n", o.Name, o.Weight)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/sort/export_test.go b/third_party/gofrontend/libgo/go/sort/export_test.go
new file mode 100644
index 0000000..b6e30ce
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sort/export_test.go
@@ -0,0 +1,9 @@
+// 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.
+
+package sort
+
+func Heapsort(data Interface) {
+	heapSort(data, 0, data.Len())
+}
diff --git a/third_party/gofrontend/libgo/go/sort/search.go b/third_party/gofrontend/libgo/go/sort/search.go
new file mode 100644
index 0000000..8a2c1c3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sort/search.go
@@ -0,0 +1,112 @@
+// Copyright 2010 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.
+
+// This file implements binary search.
+
+package sort
+
+// Search uses binary search to find and return the smallest index i
+// in [0, n) at which f(i) is true, assuming that on the range [0, n),
+// f(i) == true implies f(i+1) == true.  That is, Search requires that
+// f is false for some (possibly empty) prefix of the input range [0, n)
+// and then true for the (possibly empty) remainder; Search returns
+// the first true index.  If there is no such index, Search returns n.
+// (Note that the "not found" return value is not -1 as in, for instance,
+// strings.Index).
+// Search calls f(i) only for i in the range [0, n).
+//
+// A common use of Search is to find the index i for a value x in
+// a sorted, indexable data structure such as an array or slice.
+// In this case, the argument f, typically a closure, captures the value
+// to be searched for, and how the data structure is indexed and
+// ordered.
+//
+// For instance, given a slice data sorted in ascending order,
+// the call Search(len(data), func(i int) bool { return data[i] >= 23 })
+// returns the smallest index i such that data[i] >= 23.  If the caller
+// wants to find whether 23 is in the slice, it must test data[i] == 23
+// separately.
+//
+// Searching data sorted in descending order would use the <=
+// operator instead of the >= operator.
+//
+// To complete the example above, the following code tries to find the value
+// x in an integer slice data sorted in ascending order:
+//
+//	x := 23
+//	i := sort.Search(len(data), func(i int) bool { return data[i] >= x })
+//	if i < len(data) && data[i] == x {
+//		// x is present at data[i]
+//	} else {
+//		// x is not present in data,
+//		// but i is the index where it would be inserted.
+//	}
+//
+// As a more whimsical example, this program guesses your number:
+//
+//	func GuessingGame() {
+//		var s string
+//		fmt.Printf("Pick an integer from 0 to 100.\n")
+//		answer := sort.Search(100, func(i int) bool {
+//			fmt.Printf("Is your number <= %d? ", i)
+//			fmt.Scanf("%s", &s)
+//			return s != "" && s[0] == 'y'
+//		})
+//		fmt.Printf("Your number is %d.\n", answer)
+//	}
+//
+func Search(n int, f func(int) bool) int {
+	// Define f(-1) == false and f(n) == true.
+	// Invariant: f(i-1) == false, f(j) == true.
+	i, j := 0, n
+	for i < j {
+		h := i + (j-i)/2 // avoid overflow when computing h
+		// i ≤ h < j
+		if !f(h) {
+			i = h + 1 // preserves f(i-1) == false
+		} else {
+			j = h // preserves f(j) == true
+		}
+	}
+	// i == j, f(i-1) == false, and f(j) (= f(i)) == true  =>  answer is i.
+	return i
+}
+
+// Convenience wrappers for common cases.
+
+// SearchInts searches for x in a sorted slice of ints and returns the index
+// as specified by Search. The return value is the index to insert x if x is
+// not present (it could be len(a)).
+// The slice must be sorted in ascending order.
+//
+func SearchInts(a []int, x int) int {
+	return Search(len(a), func(i int) bool { return a[i] >= x })
+}
+
+// SearchFloat64s searches for x in a sorted slice of float64s and returns the index
+// as specified by Search.  The return value is the index to insert x if x is not
+// present (it could be len(a)).
+// The slice must be sorted in ascending order.
+//
+func SearchFloat64s(a []float64, x float64) int {
+	return Search(len(a), func(i int) bool { return a[i] >= x })
+}
+
+// SearchStrings searches for x in a sorted slice of strings and returns the index
+// as specified by Search.  The return value is the index to insert x if x is not
+// present (it could be len(a)).
+// The slice must be sorted in ascending order.
+//
+func SearchStrings(a []string, x string) int {
+	return Search(len(a), func(i int) bool { return a[i] >= x })
+}
+
+// Search returns the result of applying SearchInts to the receiver and x.
+func (p IntSlice) Search(x int) int { return SearchInts(p, x) }
+
+// Search returns the result of applying SearchFloat64s to the receiver and x.
+func (p Float64Slice) Search(x float64) int { return SearchFloat64s(p, x) }
+
+// Search returns the result of applying SearchStrings to the receiver and x.
+func (p StringSlice) Search(x string) int { return SearchStrings(p, x) }
diff --git a/third_party/gofrontend/libgo/go/sort/search_test.go b/third_party/gofrontend/libgo/go/sort/search_test.go
new file mode 100644
index 0000000..4265b95
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sort/search_test.go
@@ -0,0 +1,162 @@
+// Copyright 2010 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 sort_test
+
+import (
+	"runtime"
+	. "sort"
+	"testing"
+)
+
+func f(a []int, x int) func(int) bool {
+	return func(i int) bool {
+		return a[i] >= x
+	}
+}
+
+var data = []int{0: -10, 1: -5, 2: 0, 3: 1, 4: 2, 5: 3, 6: 5, 7: 7, 8: 11, 9: 100, 10: 100, 11: 100, 12: 1000, 13: 10000}
+
+var tests = []struct {
+	name string
+	n    int
+	f    func(int) bool
+	i    int
+}{
+	{"empty", 0, nil, 0},
+	{"1 1", 1, func(i int) bool { return i >= 1 }, 1},
+	{"1 true", 1, func(i int) bool { return true }, 0},
+	{"1 false", 1, func(i int) bool { return false }, 1},
+	{"1e9 991", 1e9, func(i int) bool { return i >= 991 }, 991},
+	{"1e9 true", 1e9, func(i int) bool { return true }, 0},
+	{"1e9 false", 1e9, func(i int) bool { return false }, 1e9},
+	{"data -20", len(data), f(data, -20), 0},
+	{"data -10", len(data), f(data, -10), 0},
+	{"data -9", len(data), f(data, -9), 1},
+	{"data -6", len(data), f(data, -6), 1},
+	{"data -5", len(data), f(data, -5), 1},
+	{"data 3", len(data), f(data, 3), 5},
+	{"data 11", len(data), f(data, 11), 8},
+	{"data 99", len(data), f(data, 99), 9},
+	{"data 100", len(data), f(data, 100), 9},
+	{"data 101", len(data), f(data, 101), 12},
+	{"data 10000", len(data), f(data, 10000), 13},
+	{"data 10001", len(data), f(data, 10001), 14},
+	{"descending a", 7, func(i int) bool { return []int{99, 99, 59, 42, 7, 0, -1, -1}[i] <= 7 }, 4},
+	{"descending 7", 1e9, func(i int) bool { return 1e9-i <= 7 }, 1e9 - 7},
+	{"overflow", 2e9, func(i int) bool { return false }, 2e9},
+}
+
+func TestSearch(t *testing.T) {
+	for _, e := range tests {
+		i := Search(e.n, e.f)
+		if i != e.i {
+			t.Errorf("%s: expected index %d; got %d", e.name, e.i, i)
+		}
+	}
+}
+
+// log2 computes the binary logarithm of x, rounded up to the next integer.
+// (log2(0) == 0, log2(1) == 0, log2(2) == 1, log2(3) == 2, etc.)
+//
+func log2(x int) int {
+	n := 0
+	for p := 1; p < x; p += p {
+		// p == 2**n
+		n++
+	}
+	// p/2 < x <= p == 2**n
+	return n
+}
+
+func TestSearchEfficiency(t *testing.T) {
+	n := 100
+	step := 1
+	for exp := 2; exp < 10; exp++ {
+		// n == 10**exp
+		// step == 10**(exp-2)
+		max := log2(n)
+		for x := 0; x < n; x += step {
+			count := 0
+			i := Search(n, func(i int) bool { count++; return i >= x })
+			if i != x {
+				t.Errorf("n = %d: expected index %d; got %d", n, x, i)
+			}
+			if count > max {
+				t.Errorf("n = %d, x = %d: expected <= %d calls; got %d", n, x, max, count)
+			}
+		}
+		n *= 10
+		step *= 10
+	}
+}
+
+// Smoke tests for convenience wrappers - not comprehensive.
+
+var fdata = []float64{0: -3.14, 1: 0, 2: 1, 3: 2, 4: 1000.7}
+var sdata = []string{0: "f", 1: "foo", 2: "foobar", 3: "x"}
+
+var wrappertests = []struct {
+	name   string
+	result int
+	i      int
+}{
+	{"SearchInts", SearchInts(data, 11), 8},
+	{"SearchFloat64s", SearchFloat64s(fdata, 2.1), 4},
+	{"SearchStrings", SearchStrings(sdata, ""), 0},
+	{"IntSlice.Search", IntSlice(data).Search(0), 2},
+	{"Float64Slice.Search", Float64Slice(fdata).Search(2.0), 3},
+	{"StringSlice.Search", StringSlice(sdata).Search("x"), 3},
+}
+
+func TestSearchWrappers(t *testing.T) {
+	for _, e := range wrappertests {
+		if e.result != e.i {
+			t.Errorf("%s: expected index %d; got %d", e.name, e.i, e.result)
+		}
+	}
+}
+
+func runSearchWrappers() {
+	SearchInts(data, 11)
+	SearchFloat64s(fdata, 2.1)
+	SearchStrings(sdata, "")
+	IntSlice(data).Search(0)
+	Float64Slice(fdata).Search(2.0)
+	StringSlice(sdata).Search("x")
+}
+
+func TestSearchWrappersDontAlloc(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Skip("skipping; GOMAXPROCS>1")
+	}
+	t.Skip("skipping alloc test for gccgo")
+	allocs := testing.AllocsPerRun(100, runSearchWrappers)
+	if allocs != 0 {
+		t.Errorf("expected no allocs for runSearchWrappers, got %v", allocs)
+	}
+}
+
+func BenchmarkSearchWrappers(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		runSearchWrappers()
+	}
+}
+
+// Abstract exhaustive test: all sizes up to 100,
+// all possible return values.  If there are any small
+// corner cases, this test exercises them.
+func TestSearchExhaustive(t *testing.T) {
+	for size := 0; size <= 100; size++ {
+		for targ := 0; targ <= size; targ++ {
+			i := Search(size, func(i int) bool { return i >= targ })
+			if i != targ {
+				t.Errorf("Search(%d, %d) = %d", size, targ, i)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/sort/sort.go b/third_party/gofrontend/libgo/go/sort/sort.go
new file mode 100644
index 0000000..e980c29
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sort/sort.go
@@ -0,0 +1,474 @@
+// 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 sort provides primitives for sorting slices and user-defined
+// collections.
+package sort
+
+// A type, typically a collection, that satisfies sort.Interface can be
+// sorted by the routines in this package.  The methods require that the
+// elements of the collection be enumerated by an integer index.
+type Interface interface {
+	// Len is the number of elements in the collection.
+	Len() int
+	// Less reports whether the element with
+	// index i should sort before the element with index j.
+	Less(i, j int) bool
+	// Swap swaps the elements with indexes i and j.
+	Swap(i, j int)
+}
+
+func min(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}
+
+// Insertion sort
+func insertionSort(data Interface, a, b int) {
+	for i := a + 1; i < b; i++ {
+		for j := i; j > a && data.Less(j, j-1); j-- {
+			data.Swap(j, j-1)
+		}
+	}
+}
+
+// siftDown implements the heap property on data[lo, hi).
+// first is an offset into the array where the root of the heap lies.
+func siftDown(data Interface, lo, hi, first int) {
+	root := lo
+	for {
+		child := 2*root + 1
+		if child >= hi {
+			break
+		}
+		if child+1 < hi && data.Less(first+child, first+child+1) {
+			child++
+		}
+		if !data.Less(first+root, first+child) {
+			return
+		}
+		data.Swap(first+root, first+child)
+		root = child
+	}
+}
+
+func heapSort(data Interface, a, b int) {
+	first := a
+	lo := 0
+	hi := b - a
+
+	// Build heap with greatest element at top.
+	for i := (hi - 1) / 2; i >= 0; i-- {
+		siftDown(data, i, hi, first)
+	}
+
+	// Pop elements, largest first, into end of data.
+	for i := hi - 1; i >= 0; i-- {
+		data.Swap(first, first+i)
+		siftDown(data, lo, i, first)
+	}
+}
+
+// Quicksort, following Bentley and McIlroy,
+// ``Engineering a Sort Function,'' SP&E November 1993.
+
+// medianOfThree moves the median of the three values data[a], data[b], data[c] into data[a].
+func medianOfThree(data Interface, a, b, c int) {
+	m0 := b
+	m1 := a
+	m2 := c
+	// bubble sort on 3 elements
+	if data.Less(m1, m0) {
+		data.Swap(m1, m0)
+	}
+	if data.Less(m2, m1) {
+		data.Swap(m2, m1)
+	}
+	if data.Less(m1, m0) {
+		data.Swap(m1, m0)
+	}
+	// now data[m0] <= data[m1] <= data[m2]
+}
+
+func swapRange(data Interface, a, b, n int) {
+	for i := 0; i < n; i++ {
+		data.Swap(a+i, b+i)
+	}
+}
+
+func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
+	m := lo + (hi-lo)/2 // Written like this to avoid integer overflow.
+	if hi-lo > 40 {
+		// Tukey's ``Ninther,'' median of three medians of three.
+		s := (hi - lo) / 8
+		medianOfThree(data, lo, lo+s, lo+2*s)
+		medianOfThree(data, m, m-s, m+s)
+		medianOfThree(data, hi-1, hi-1-s, hi-1-2*s)
+	}
+	medianOfThree(data, lo, m, hi-1)
+
+	// Invariants are:
+	//	data[lo] = pivot (set up by ChoosePivot)
+	//	data[lo <= i < a] = pivot
+	//	data[a <= i < b] < pivot
+	//	data[b <= i < c] is unexamined
+	//	data[c <= i < d] > pivot
+	//	data[d <= i < hi] = pivot
+	//
+	// Once b meets c, can swap the "= pivot" sections
+	// into the middle of the slice.
+	pivot := lo
+	a, b, c, d := lo+1, lo+1, hi, hi
+	for {
+		for b < c {
+			if data.Less(b, pivot) { // data[b] < pivot
+				b++
+			} else if !data.Less(pivot, b) { // data[b] = pivot
+				data.Swap(a, b)
+				a++
+				b++
+			} else {
+				break
+			}
+		}
+		for b < c {
+			if data.Less(pivot, c-1) { // data[c-1] > pivot
+				c--
+			} else if !data.Less(c-1, pivot) { // data[c-1] = pivot
+				data.Swap(c-1, d-1)
+				c--
+				d--
+			} else {
+				break
+			}
+		}
+		if b >= c {
+			break
+		}
+		// data[b] > pivot; data[c-1] < pivot
+		data.Swap(b, c-1)
+		b++
+		c--
+	}
+
+	n := min(b-a, a-lo)
+	swapRange(data, lo, b-n, n)
+
+	n = min(hi-d, d-c)
+	swapRange(data, c, hi-n, n)
+
+	return lo + b - a, hi - (d - c)
+}
+
+func quickSort(data Interface, a, b, maxDepth int) {
+	for b-a > 7 {
+		if maxDepth == 0 {
+			heapSort(data, a, b)
+			return
+		}
+		maxDepth--
+		mlo, mhi := doPivot(data, a, b)
+		// Avoiding recursion on the larger subproblem guarantees
+		// a stack depth of at most lg(b-a).
+		if mlo-a < b-mhi {
+			quickSort(data, a, mlo, maxDepth)
+			a = mhi // i.e., quickSort(data, mhi, b)
+		} else {
+			quickSort(data, mhi, b, maxDepth)
+			b = mlo // i.e., quickSort(data, a, mlo)
+		}
+	}
+	if b-a > 1 {
+		insertionSort(data, a, b)
+	}
+}
+
+// Sort sorts data.
+// It makes one call to data.Len to determine n, and O(n*log(n)) calls to
+// data.Less and data.Swap. The sort is not guaranteed to be stable.
+func Sort(data Interface) {
+	// Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached.
+	n := data.Len()
+	maxDepth := 0
+	for i := n; i > 0; i >>= 1 {
+		maxDepth++
+	}
+	maxDepth *= 2
+	quickSort(data, 0, n, maxDepth)
+}
+
+type reverse struct {
+	// This embedded Interface permits Reverse to use the methods of
+	// another Interface implementation.
+	Interface
+}
+
+// Less returns the opposite of the embedded implementation's Less method.
+func (r reverse) Less(i, j int) bool {
+	return r.Interface.Less(j, i)
+}
+
+// Reverse returns the reverse order for data.
+func Reverse(data Interface) Interface {
+	return &reverse{data}
+}
+
+// IsSorted reports whether data is sorted.
+func IsSorted(data Interface) bool {
+	n := data.Len()
+	for i := n - 1; i > 0; i-- {
+		if data.Less(i, i-1) {
+			return false
+		}
+	}
+	return true
+}
+
+// Convenience types for common cases
+
+// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
+type IntSlice []int
+
+func (p IntSlice) Len() int           { return len(p) }
+func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
+func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// Sort is a convenience method.
+func (p IntSlice) Sort() { Sort(p) }
+
+// Float64Slice attaches the methods of Interface to []float64, sorting in increasing order.
+type Float64Slice []float64
+
+func (p Float64Slice) Len() int           { return len(p) }
+func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || isNaN(p[i]) && !isNaN(p[j]) }
+func (p Float64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// isNaN is a copy of math.IsNaN to avoid a dependency on the math package.
+func isNaN(f float64) bool {
+	return f != f
+}
+
+// Sort is a convenience method.
+func (p Float64Slice) Sort() { Sort(p) }
+
+// StringSlice attaches the methods of Interface to []string, sorting in increasing order.
+type StringSlice []string
+
+func (p StringSlice) Len() int           { return len(p) }
+func (p StringSlice) Less(i, j int) bool { return p[i] < p[j] }
+func (p StringSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// Sort is a convenience method.
+func (p StringSlice) Sort() { Sort(p) }
+
+// Convenience wrappers for common cases
+
+// Ints sorts a slice of ints in increasing order.
+func Ints(a []int) { Sort(IntSlice(a)) }
+
+// Float64s sorts a slice of float64s in increasing order.
+func Float64s(a []float64) { Sort(Float64Slice(a)) }
+
+// Strings sorts a slice of strings in increasing order.
+func Strings(a []string) { Sort(StringSlice(a)) }
+
+// IntsAreSorted tests whether a slice of ints is sorted in increasing order.
+func IntsAreSorted(a []int) bool { return IsSorted(IntSlice(a)) }
+
+// Float64sAreSorted tests whether a slice of float64s is sorted in increasing order.
+func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Slice(a)) }
+
+// StringsAreSorted tests whether a slice of strings is sorted in increasing order.
+func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
+
+// Notes on stable sorting:
+// The used algorithms are simple and provable correct on all input and use
+// only logarithmic additional stack space.  They perform well if compared
+// experimentally to other stable in-place sorting algorithms.
+//
+// Remarks on other algorithms evaluated:
+//  - GCC's 4.6.3 stable_sort with merge_without_buffer from libstdc++:
+//    Not faster.
+//  - GCC's __rotate for block rotations: Not faster.
+//  - "Practical in-place mergesort" from  Jyrki Katajainen, Tomi A. Pasanen
+//    and Jukka Teuhola; Nordic Journal of Computing 3,1 (1996), 27-40:
+//    The given algorithms are in-place, number of Swap and Assignments
+//    grow as n log n but the algorithm is not stable.
+//  - "Fast Stable In-Plcae Sorting with O(n) Data Moves" J.I. Munro and
+//    V. Raman in Algorithmica (1996) 16, 115-160:
+//    This algorithm either needs additional 2n bits or works only if there
+//    are enough different elements available to encode some permutations
+//    which have to be undone later (so not stable an any input).
+//  - All the optimal in-place sorting/merging algorithms I found are either
+//    unstable or rely on enough different elements in each step to encode the
+//    performed block rearrangements. See also "In-Place Merging Algorithms",
+//    Denham Coates-Evely, Department of Computer Science, Kings College,
+//    January 2004 and the reverences in there.
+//  - Often "optimal" algorithms are optimal in the number of assignments
+//    but Interface has only Swap as operation.
+
+// Stable sorts data while keeping the original order of equal elements.
+//
+// It makes one call to data.Len to determine n, O(n*log(n)) calls to
+// data.Less and O(n*log(n)*log(n)) calls to data.Swap.
+func Stable(data Interface) {
+	n := data.Len()
+	blockSize := 20
+	a, b := 0, blockSize
+	for b <= n {
+		insertionSort(data, a, b)
+		a = b
+		b += blockSize
+	}
+	insertionSort(data, a, n)
+
+	for blockSize < n {
+		a, b = 0, 2*blockSize
+		for b <= n {
+			symMerge(data, a, a+blockSize, b)
+			a = b
+			b += 2 * blockSize
+		}
+		symMerge(data, a, a+blockSize, n)
+		blockSize *= 2
+	}
+}
+
+// SymMerge merges the two sorted subsequences data[a:m] and data[m:b] using
+// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum
+// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz
+// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in
+// Computer Science, pages 714-723. Springer, 2004.
+//
+// Let M = m-a and N = b-n. Wolog M < N.
+// The recursion depth is bound by ceil(log(N+M)).
+// The algorithm needs O(M*log(N/M + 1)) calls to data.Less.
+// The algorithm needs O((M+N)*log(M)) calls to data.Swap.
+//
+// The paper gives O((M+N)*log(M)) as the number of assignments assuming a
+// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation
+// in the paper carries through for Swap operations, especially as the block
+// swapping rotate uses only O(M+N) Swaps.
+func symMerge(data Interface, a, m, b int) {
+	if a >= m || m >= b {
+		return
+	}
+
+	mid := a + (b-a)/2
+	n := mid + m
+	start := 0
+	if m > mid {
+		start = n - b
+		r, p := mid, n-1
+		for start < r {
+			c := start + (r-start)/2
+			if !data.Less(p-c, c) {
+				start = c + 1
+			} else {
+				r = c
+			}
+		}
+	} else {
+		start = a
+		r, p := m, n-1
+		for start < r {
+			c := start + (r-start)/2
+			if !data.Less(p-c, c) {
+				start = c + 1
+			} else {
+				r = c
+			}
+		}
+	}
+	end := n - start
+	rotate(data, start, m, end)
+	symMerge(data, a, start, mid)
+	symMerge(data, mid, end, b)
+}
+
+// Rotate two consecutives blocks u = data[a:m] and v = data[m:b] in data:
+// Data of the form 'x u v y' is changed to 'x v u y'.
+// Rotate performs at most b-a many calls to data.Swap.
+func rotate(data Interface, a, m, b int) {
+	i := m - a
+	if i == 0 {
+		return
+	}
+	j := b - m
+	if j == 0 {
+		return
+	}
+
+	if i == j {
+		swapRange(data, a, m, i)
+		return
+	}
+
+	p := a + i
+	for i != j {
+		if i > j {
+			swapRange(data, p-i, p, j)
+			i -= j
+		} else {
+			swapRange(data, p-i, p+j-i, i)
+			j -= i
+		}
+	}
+	swapRange(data, p-i, p, i)
+}
+
+/*
+Complexity of Stable Sorting
+
+
+Complexity of block swapping rotation
+
+Each Swap puts one new element into its correct, final position.
+Elements which reach their final position are no longer moved.
+Thus block swapping rotation needs |u|+|v| calls to Swaps.
+This is best possible as each element might need a move.
+
+Pay attention when comparing to other optimal algorithms which
+typically count the number of assignments instead of swaps:
+E.g. the optimal algorithm of Dudzinski and Dydek for in-place
+rotations uses O(u + v + gcd(u,v)) assignments which is
+better than our O(3 * (u+v)) as gcd(u,v) <= u.
+
+
+Stable sorting by SymMerge and BlockSwap rotations
+
+SymMerg complexity for same size input M = N:
+Calls to Less:  O(M*log(N/M+1)) = O(N*log(2)) = O(N)
+Calls to Swap:  O((M+N)*log(M)) = O(2*N*log(N)) = O(N*log(N))
+
+(The following argument does not fuzz over a missing -1 or
+other stuff which does not impact the final result).
+
+Let n = data.Len(). Assume n = 2^k.
+
+Plain merge sort performs log(n) = k iterations.
+On iteration i the algorithm merges 2^(k-i) blocks, each of size 2^i.
+
+Thus iteration i of merge sort performs:
+Calls to Less  O(2^(k-i) * 2^i) = O(2^k) = O(2^log(n)) = O(n)
+Calls to Swap  O(2^(k-i) * 2^i * log(2^i)) = O(2^k * i) = O(n*i)
+
+In total k = log(n) iterations are performed; so in total:
+Calls to Less O(log(n) * n)
+Calls to Swap O(n + 2*n + 3*n + ... + (k-1)*n + k*n)
+   = O((k/2) * k * n) = O(n * k^2) = O(n * log^2(n))
+
+
+Above results should generalize to arbitrary n = 2^k + p
+and should not be influenced by the initial insertion sort phase:
+Insertion sort is O(n^2) on Swap and Less, thus O(bs^2) per block of
+size bs at n/bs blocks:  O(bs*n) Swaps and Less during insertion sort.
+Merge sort iterations start at i = log(bs). With t = log(bs) constant:
+Calls to Less O((log(n)-t) * n + bs*n) = O(log(n)*n + (bs-t)*n)
+   = O(n * log(n))
+Calls to Swap O(n * log^2(n) - (t^2+t)/2*n) = O(n * log^2(n))
+
+*/
diff --git a/third_party/gofrontend/libgo/go/sort/sort_test.go b/third_party/gofrontend/libgo/go/sort/sort_test.go
new file mode 100644
index 0000000..6c36f30
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sort/sort_test.go
@@ -0,0 +1,553 @@
+// 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 sort_test
+
+import (
+	"fmt"
+	"math"
+	"math/rand"
+	. "sort"
+	"strconv"
+	"testing"
+)
+
+var ints = [...]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
+var float64s = [...]float64{74.3, 59.0, math.Inf(1), 238.2, -784.0, 2.3, math.NaN(), math.NaN(), math.Inf(-1), 9845.768, -959.7485, 905, 7.8, 7.8}
+var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}
+
+func TestSortIntSlice(t *testing.T) {
+	data := ints
+	a := IntSlice(data[0:])
+	Sort(a)
+	if !IsSorted(a) {
+		t.Errorf("sorted %v", ints)
+		t.Errorf("   got %v", data)
+	}
+}
+
+func TestSortFloat64Slice(t *testing.T) {
+	data := float64s
+	a := Float64Slice(data[0:])
+	Sort(a)
+	if !IsSorted(a) {
+		t.Errorf("sorted %v", float64s)
+		t.Errorf("   got %v", data)
+	}
+}
+
+func TestSortStringSlice(t *testing.T) {
+	data := strings
+	a := StringSlice(data[0:])
+	Sort(a)
+	if !IsSorted(a) {
+		t.Errorf("sorted %v", strings)
+		t.Errorf("   got %v", data)
+	}
+}
+
+func TestInts(t *testing.T) {
+	data := ints
+	Ints(data[0:])
+	if !IntsAreSorted(data[0:]) {
+		t.Errorf("sorted %v", ints)
+		t.Errorf("   got %v", data)
+	}
+}
+
+func TestFloat64s(t *testing.T) {
+	data := float64s
+	Float64s(data[0:])
+	if !Float64sAreSorted(data[0:]) {
+		t.Errorf("sorted %v", float64s)
+		t.Errorf("   got %v", data)
+	}
+}
+
+func TestStrings(t *testing.T) {
+	data := strings
+	Strings(data[0:])
+	if !StringsAreSorted(data[0:]) {
+		t.Errorf("sorted %v", strings)
+		t.Errorf("   got %v", data)
+	}
+}
+
+func TestSortLarge_Random(t *testing.T) {
+	n := 1000000
+	if testing.Short() {
+		n /= 100
+	}
+	data := make([]int, n)
+	for i := 0; i < len(data); i++ {
+		data[i] = rand.Intn(100)
+	}
+	if IntsAreSorted(data) {
+		t.Fatalf("terrible rand.rand")
+	}
+	Ints(data)
+	if !IntsAreSorted(data) {
+		t.Errorf("sort didn't sort - 1M ints")
+	}
+}
+
+func TestReverseSortIntSlice(t *testing.T) {
+	data := ints
+	data1 := ints
+	a := IntSlice(data[0:])
+	Sort(a)
+	r := IntSlice(data1[0:])
+	Sort(Reverse(r))
+	for i := 0; i < len(data); i++ {
+		if a[i] != r[len(data)-1-i] {
+			t.Errorf("reverse sort didn't sort")
+		}
+		if i > len(data)/2 {
+			break
+		}
+	}
+}
+
+func BenchmarkSortString1K(b *testing.B) {
+	b.StopTimer()
+	for i := 0; i < b.N; i++ {
+		data := make([]string, 1<<10)
+		for i := 0; i < len(data); i++ {
+			data[i] = strconv.Itoa(i ^ 0x2cc)
+		}
+		b.StartTimer()
+		Strings(data)
+		b.StopTimer()
+	}
+}
+
+func BenchmarkStableString1K(b *testing.B) {
+	b.StopTimer()
+	for i := 0; i < b.N; i++ {
+		data := make([]string, 1<<10)
+		for i := 0; i < len(data); i++ {
+			data[i] = strconv.Itoa(i ^ 0x2cc)
+		}
+		b.StartTimer()
+		Stable(StringSlice(data))
+		b.StopTimer()
+	}
+}
+
+func BenchmarkSortInt1K(b *testing.B) {
+	b.StopTimer()
+	for i := 0; i < b.N; i++ {
+		data := make([]int, 1<<10)
+		for i := 0; i < len(data); i++ {
+			data[i] = i ^ 0x2cc
+		}
+		b.StartTimer()
+		Ints(data)
+		b.StopTimer()
+	}
+}
+
+func BenchmarkStableInt1K(b *testing.B) {
+	b.StopTimer()
+	for i := 0; i < b.N; i++ {
+		data := make([]int, 1<<10)
+		for i := 0; i < len(data); i++ {
+			data[i] = i ^ 0x2cc
+		}
+		b.StartTimer()
+		Stable(IntSlice(data))
+		b.StopTimer()
+	}
+}
+
+func BenchmarkSortInt64K(b *testing.B) {
+	b.StopTimer()
+	for i := 0; i < b.N; i++ {
+		data := make([]int, 1<<16)
+		for i := 0; i < len(data); i++ {
+			data[i] = i ^ 0xcccc
+		}
+		b.StartTimer()
+		Ints(data)
+		b.StopTimer()
+	}
+}
+
+func BenchmarkStableInt64K(b *testing.B) {
+	b.StopTimer()
+	for i := 0; i < b.N; i++ {
+		data := make([]int, 1<<16)
+		for i := 0; i < len(data); i++ {
+			data[i] = i ^ 0xcccc
+		}
+		b.StartTimer()
+		Stable(IntSlice(data))
+		b.StopTimer()
+	}
+}
+
+const (
+	_Sawtooth = iota
+	_Rand
+	_Stagger
+	_Plateau
+	_Shuffle
+	_NDist
+)
+
+const (
+	_Copy = iota
+	_Reverse
+	_ReverseFirstHalf
+	_ReverseSecondHalf
+	_Sorted
+	_Dither
+	_NMode
+)
+
+type testingData struct {
+	desc        string
+	t           *testing.T
+	data        []int
+	maxswap     int // number of swaps allowed
+	ncmp, nswap int
+}
+
+func (d *testingData) Len() int { return len(d.data) }
+func (d *testingData) Less(i, j int) bool {
+	d.ncmp++
+	return d.data[i] < d.data[j]
+}
+func (d *testingData) Swap(i, j int) {
+	if d.nswap >= d.maxswap {
+		d.t.Errorf("%s: used %d swaps sorting slice of %d", d.desc, d.nswap, len(d.data))
+		d.t.FailNow()
+	}
+	d.nswap++
+	d.data[i], d.data[j] = d.data[j], d.data[i]
+}
+
+func min(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}
+
+func lg(n int) int {
+	i := 0
+	for 1<<uint(i) < n {
+		i++
+	}
+	return i
+}
+
+func testBentleyMcIlroy(t *testing.T, sort func(Interface), maxswap func(int) int) {
+	sizes := []int{100, 1023, 1024, 1025}
+	if testing.Short() {
+		sizes = []int{100, 127, 128, 129}
+	}
+	dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"}
+	modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"}
+	var tmp1, tmp2 [1025]int
+	for _, n := range sizes {
+		for m := 1; m < 2*n; m *= 2 {
+			for dist := 0; dist < _NDist; dist++ {
+				j := 0
+				k := 1
+				data := tmp1[0:n]
+				for i := 0; i < n; i++ {
+					switch dist {
+					case _Sawtooth:
+						data[i] = i % m
+					case _Rand:
+						data[i] = rand.Intn(m)
+					case _Stagger:
+						data[i] = (i*m + i) % n
+					case _Plateau:
+						data[i] = min(i, m)
+					case _Shuffle:
+						if rand.Intn(m) != 0 {
+							j += 2
+							data[i] = j
+						} else {
+							k += 2
+							data[i] = k
+						}
+					}
+				}
+
+				mdata := tmp2[0:n]
+				for mode := 0; mode < _NMode; mode++ {
+					switch mode {
+					case _Copy:
+						for i := 0; i < n; i++ {
+							mdata[i] = data[i]
+						}
+					case _Reverse:
+						for i := 0; i < n; i++ {
+							mdata[i] = data[n-i-1]
+						}
+					case _ReverseFirstHalf:
+						for i := 0; i < n/2; i++ {
+							mdata[i] = data[n/2-i-1]
+						}
+						for i := n / 2; i < n; i++ {
+							mdata[i] = data[i]
+						}
+					case _ReverseSecondHalf:
+						for i := 0; i < n/2; i++ {
+							mdata[i] = data[i]
+						}
+						for i := n / 2; i < n; i++ {
+							mdata[i] = data[n-(i-n/2)-1]
+						}
+					case _Sorted:
+						for i := 0; i < n; i++ {
+							mdata[i] = data[i]
+						}
+						// Ints is known to be correct
+						// because mode Sort runs after mode _Copy.
+						Ints(mdata)
+					case _Dither:
+						for i := 0; i < n; i++ {
+							mdata[i] = data[i] + i%5
+						}
+					}
+
+					desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode])
+					d := &testingData{desc: desc, t: t, data: mdata[0:n], maxswap: maxswap(n)}
+					sort(d)
+					// Uncomment if you are trying to improve the number of compares/swaps.
+					//t.Logf("%s: ncmp=%d, nswp=%d", desc, d.ncmp, d.nswap)
+
+					// If we were testing C qsort, we'd have to make a copy
+					// of the slice and sort it ourselves and then compare
+					// x against it, to ensure that qsort was only permuting
+					// the data, not (for example) overwriting it with zeros.
+					//
+					// In go, we don't have to be so paranoid: since the only
+					// mutating method Sort can call is TestingData.swap,
+					// it suffices here just to check that the final slice is sorted.
+					if !IntsAreSorted(mdata) {
+						t.Errorf("%s: ints not sorted", desc)
+						t.Errorf("\t%v", mdata)
+						t.FailNow()
+					}
+				}
+			}
+		}
+	}
+}
+
+func TestSortBM(t *testing.T) {
+	testBentleyMcIlroy(t, Sort, func(n int) int { return n * lg(n) * 12 / 10 })
+}
+
+func TestHeapsortBM(t *testing.T) {
+	testBentleyMcIlroy(t, Heapsort, func(n int) int { return n * lg(n) * 12 / 10 })
+}
+
+func TestStableBM(t *testing.T) {
+	testBentleyMcIlroy(t, Stable, func(n int) int { return n * lg(n) * lg(n) / 3 })
+}
+
+// This is based on the "antiquicksort" implementation by M. Douglas McIlroy.
+// See http://www.cs.dartmouth.edu/~doug/mdmspe.pdf for more info.
+type adversaryTestingData struct {
+	data      []int
+	keys      map[int]int
+	candidate int
+}
+
+func (d *adversaryTestingData) Len() int { return len(d.data) }
+
+func (d *adversaryTestingData) Less(i, j int) bool {
+	if _, present := d.keys[i]; !present {
+		if _, present := d.keys[j]; !present {
+			if i == d.candidate {
+				d.keys[i] = len(d.keys)
+			} else {
+				d.keys[j] = len(d.keys)
+			}
+		}
+	}
+
+	if _, present := d.keys[i]; !present {
+		d.candidate = i
+		return false
+	}
+	if _, present := d.keys[j]; !present {
+		d.candidate = j
+		return true
+	}
+
+	return d.keys[i] >= d.keys[j]
+}
+
+func (d *adversaryTestingData) Swap(i, j int) {
+	d.data[i], d.data[j] = d.data[j], d.data[i]
+}
+
+func TestAdversary(t *testing.T) {
+	const size = 100
+	data := make([]int, size)
+	for i := 0; i < size; i++ {
+		data[i] = i
+	}
+
+	d := &adversaryTestingData{data, make(map[int]int), 0}
+	Sort(d) // This should degenerate to heapsort.
+}
+
+func TestStableInts(t *testing.T) {
+	data := ints
+	Stable(IntSlice(data[0:]))
+	if !IntsAreSorted(data[0:]) {
+		t.Errorf("nsorted %v\n   got %v", ints, data)
+	}
+}
+
+type intPairs []struct {
+	a, b int
+}
+
+// IntPairs compare on a only.
+func (d intPairs) Len() int           { return len(d) }
+func (d intPairs) Less(i, j int) bool { return d[i].a < d[j].a }
+func (d intPairs) Swap(i, j int)      { d[i], d[j] = d[j], d[i] }
+
+// Record initial order in B.
+func (d intPairs) initB() {
+	for i := range d {
+		d[i].b = i
+	}
+}
+
+// InOrder checks if a-equal elements were not reordered.
+func (d intPairs) inOrder() bool {
+	lastA, lastB := -1, 0
+	for i := 0; i < len(d); i++ {
+		if lastA != d[i].a {
+			lastA = d[i].a
+			lastB = d[i].b
+			continue
+		}
+		if d[i].b <= lastB {
+			return false
+		}
+		lastB = d[i].b
+	}
+	return true
+}
+
+func TestStability(t *testing.T) {
+	n, m := 100000, 1000
+	if testing.Short() {
+		n, m = 1000, 100
+	}
+	data := make(intPairs, n)
+
+	// random distribution
+	for i := 0; i < len(data); i++ {
+		data[i].a = rand.Intn(m)
+	}
+	if IsSorted(data) {
+		t.Fatalf("terrible rand.rand")
+	}
+	data.initB()
+	Stable(data)
+	if !IsSorted(data) {
+		t.Errorf("Stable didn't sort %d ints", n)
+	}
+	if !data.inOrder() {
+		t.Errorf("Stable wasn't stable on %d ints", n)
+	}
+
+	// already sorted
+	data.initB()
+	Stable(data)
+	if !IsSorted(data) {
+		t.Errorf("Stable shuffeled sorted %d ints (order)", n)
+	}
+	if !data.inOrder() {
+		t.Errorf("Stable shuffeled sorted %d ints (stability)", n)
+	}
+
+	// sorted reversed
+	for i := 0; i < len(data); i++ {
+		data[i].a = len(data) - i
+	}
+	data.initB()
+	Stable(data)
+	if !IsSorted(data) {
+		t.Errorf("Stable didn't sort %d ints", n)
+	}
+	if !data.inOrder() {
+		t.Errorf("Stable wasn't stable on %d ints", n)
+	}
+}
+
+var countOpsSizes = []int{1e2, 3e2, 1e3, 3e3, 1e4, 3e4, 1e5, 3e5, 1e6}
+
+func countOps(t *testing.T, algo func(Interface), name string) {
+	sizes := countOpsSizes
+	if testing.Short() {
+		sizes = sizes[:5]
+	}
+	if !testing.Verbose() {
+		t.Skip("Counting skipped as non-verbose mode.")
+	}
+	for _, n := range sizes {
+		td := testingData{
+			desc:    name,
+			t:       t,
+			data:    make([]int, n),
+			maxswap: 1<<31 - 1,
+		}
+		for i := 0; i < n; i++ {
+			td.data[i] = rand.Intn(n / 5)
+		}
+		algo(&td)
+		t.Logf("%s %8d elements: %11d Swap, %10d Less", name, n, td.nswap, td.ncmp)
+	}
+}
+
+func TestCountStableOps(t *testing.T) { countOps(t, Stable, "Stable") }
+func TestCountSortOps(t *testing.T)   { countOps(t, Sort, "Sort  ") }
+
+func bench(b *testing.B, size int, algo func(Interface), name string) {
+	b.StopTimer()
+	data := make(intPairs, size)
+	x := ^uint32(0)
+	for i := 0; i < b.N; i++ {
+		for n := size - 3; n <= size+3; n++ {
+			for i := 0; i < len(data); i++ {
+				x += x
+				x ^= 1
+				if int32(x) < 0 {
+					x ^= 0x88888eef
+				}
+				data[i].a = int(x % uint32(n/5))
+			}
+			data.initB()
+			b.StartTimer()
+			algo(data)
+			b.StopTimer()
+			if !IsSorted(data) {
+				b.Errorf("%s did not sort %d ints", name, n)
+			}
+			if name == "Stable" && !data.inOrder() {
+				b.Errorf("%s unstable on %d ints", name, n)
+			}
+		}
+	}
+}
+
+func BenchmarkSort1e2(b *testing.B)   { bench(b, 1e2, Sort, "Sort") }
+func BenchmarkStable1e2(b *testing.B) { bench(b, 1e2, Stable, "Stable") }
+func BenchmarkSort1e4(b *testing.B)   { bench(b, 1e4, Sort, "Sort") }
+func BenchmarkStable1e4(b *testing.B) { bench(b, 1e4, Stable, "Stable") }
+func BenchmarkSort1e6(b *testing.B)   { bench(b, 1e6, Sort, "Sort") }
+func BenchmarkStable1e6(b *testing.B) { bench(b, 1e6, Stable, "Stable") }
diff --git a/third_party/gofrontend/libgo/go/strconv/atob.go b/third_party/gofrontend/libgo/go/strconv/atob.go
new file mode 100644
index 0000000..d0cb097
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/atob.go
@@ -0,0 +1,35 @@
+// 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 strconv
+
+// ParseBool returns the boolean value represented by the string.
+// It accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.
+// Any other value returns an error.
+func ParseBool(str string) (value bool, err error) {
+	switch str {
+	case "1", "t", "T", "true", "TRUE", "True":
+		return true, nil
+	case "0", "f", "F", "false", "FALSE", "False":
+		return false, nil
+	}
+	return false, syntaxError("ParseBool", str)
+}
+
+// FormatBool returns "true" or "false" according to the value of b
+func FormatBool(b bool) string {
+	if b {
+		return "true"
+	}
+	return "false"
+}
+
+// AppendBool appends "true" or "false", according to the value of b,
+// to dst and returns the extended buffer.
+func AppendBool(dst []byte, b bool) []byte {
+	if b {
+		return append(dst, "true"...)
+	}
+	return append(dst, "false"...)
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/atob_test.go b/third_party/gofrontend/libgo/go/strconv/atob_test.go
new file mode 100644
index 0000000..28f469f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/atob_test.go
@@ -0,0 +1,91 @@
+// 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 strconv_test
+
+import (
+	"bytes"
+	. "strconv"
+	"testing"
+)
+
+type atobTest struct {
+	in  string
+	out bool
+	err error
+}
+
+var atobtests = []atobTest{
+	{"", false, ErrSyntax},
+	{"asdf", false, ErrSyntax},
+	{"0", false, nil},
+	{"f", false, nil},
+	{"F", false, nil},
+	{"FALSE", false, nil},
+	{"false", false, nil},
+	{"False", false, nil},
+	{"1", true, nil},
+	{"t", true, nil},
+	{"T", true, nil},
+	{"TRUE", true, nil},
+	{"true", true, nil},
+	{"True", true, nil},
+}
+
+func TestParseBool(t *testing.T) {
+	for _, test := range atobtests {
+		b, e := ParseBool(test.in)
+		if test.err != nil {
+			// expect an error
+			if e == nil {
+				t.Errorf("%s: expected %s but got nil", test.in, test.err)
+			} else {
+				// NumError assertion must succeed; it's the only thing we return.
+				if test.err != e.(*NumError).Err {
+					t.Errorf("%s: expected %s but got %s", test.in, test.err, e)
+				}
+			}
+		} else {
+			if e != nil {
+				t.Errorf("%s: expected no error but got %s", test.in, e)
+			}
+			if b != test.out {
+				t.Errorf("%s: expected %t but got %t", test.in, test.out, b)
+			}
+		}
+	}
+}
+
+var boolString = map[bool]string{
+	true:  "true",
+	false: "false",
+}
+
+func TestFormatBool(t *testing.T) {
+	for b, s := range boolString {
+		if f := FormatBool(b); f != s {
+			t.Errorf(`FormatBool(%v): expected %q but got %q`, b, s, f)
+		}
+	}
+}
+
+type appendBoolTest struct {
+	b   bool
+	in  []byte
+	out []byte
+}
+
+var appendBoolTests = []appendBoolTest{
+	{true, []byte("foo "), []byte("foo true")},
+	{false, []byte("foo "), []byte("foo false")},
+}
+
+func TestAppendBool(t *testing.T) {
+	for _, test := range appendBoolTests {
+		b := AppendBool(test.in, test.b)
+		if !bytes.Equal(b, test.out) {
+			t.Errorf("AppendBool(%q, %v): expected %q but got %q", test.in, test.b, test.out, b)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/atof.go b/third_party/gofrontend/libgo/go/strconv/atof.go
new file mode 100644
index 0000000..beaa68d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/atof.go
@@ -0,0 +1,546 @@
+// 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 strconv implements conversions to and from string representations
+// of basic data types.
+package strconv
+
+// decimal to binary floating point conversion.
+// Algorithm:
+//   1) Store input in multiprecision decimal.
+//   2) Multiply/divide decimal by powers of two until in range [0.5, 1)
+//   3) Multiply by 2^precision and round to get mantissa.
+
+import "math"
+import "runtime"
+
+var optimize = true // can change for testing
+
+func equalIgnoreCase(s1, s2 string) bool {
+	if len(s1) != len(s2) {
+		return false
+	}
+	for i := 0; i < len(s1); i++ {
+		c1 := s1[i]
+		if 'A' <= c1 && c1 <= 'Z' {
+			c1 += 'a' - 'A'
+		}
+		c2 := s2[i]
+		if 'A' <= c2 && c2 <= 'Z' {
+			c2 += 'a' - 'A'
+		}
+		if c1 != c2 {
+			return false
+		}
+	}
+	return true
+}
+
+func special(s string) (f float64, ok bool) {
+	if len(s) == 0 {
+		return
+	}
+	switch s[0] {
+	default:
+		return
+	case '+':
+		if equalIgnoreCase(s, "+inf") || equalIgnoreCase(s, "+infinity") {
+			return math.Inf(1), true
+		}
+	case '-':
+		if equalIgnoreCase(s, "-inf") || equalIgnoreCase(s, "-infinity") {
+			return math.Inf(-1), true
+		}
+	case 'n', 'N':
+		if equalIgnoreCase(s, "nan") {
+			return math.NaN(), true
+		}
+	case 'i', 'I':
+		if equalIgnoreCase(s, "inf") || equalIgnoreCase(s, "infinity") {
+			return math.Inf(1), true
+		}
+	}
+	return
+}
+
+func (b *decimal) set(s string) (ok bool) {
+	i := 0
+	b.neg = false
+	b.trunc = false
+
+	// optional sign
+	if i >= len(s) {
+		return
+	}
+	switch {
+	case s[i] == '+':
+		i++
+	case s[i] == '-':
+		b.neg = true
+		i++
+	}
+
+	// digits
+	sawdot := false
+	sawdigits := false
+	for ; i < len(s); i++ {
+		switch {
+		case s[i] == '.':
+			if sawdot {
+				return
+			}
+			sawdot = true
+			b.dp = b.nd
+			continue
+
+		case '0' <= s[i] && s[i] <= '9':
+			sawdigits = true
+			if s[i] == '0' && b.nd == 0 { // ignore leading zeros
+				b.dp--
+				continue
+			}
+			if b.nd < len(b.d) {
+				b.d[b.nd] = s[i]
+				b.nd++
+			} else if s[i] != '0' {
+				b.trunc = true
+			}
+			continue
+		}
+		break
+	}
+	if !sawdigits {
+		return
+	}
+	if !sawdot {
+		b.dp = b.nd
+	}
+
+	// optional exponent moves decimal point.
+	// if we read a very large, very long number,
+	// just be sure to move the decimal point by
+	// a lot (say, 100000).  it doesn't matter if it's
+	// not the exact number.
+	if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
+		i++
+		if i >= len(s) {
+			return
+		}
+		esign := 1
+		if s[i] == '+' {
+			i++
+		} else if s[i] == '-' {
+			i++
+			esign = -1
+		}
+		if i >= len(s) || s[i] < '0' || s[i] > '9' {
+			return
+		}
+		e := 0
+		for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
+			if e < 10000 {
+				e = e*10 + int(s[i]) - '0'
+			}
+		}
+		b.dp += e * esign
+	}
+
+	if i != len(s) {
+		return
+	}
+
+	ok = true
+	return
+}
+
+// readFloat reads a decimal mantissa and exponent from a float
+// string representation. It sets ok to false if the number could
+// not fit return types or is invalid.
+func readFloat(s string) (mantissa uint64, exp int, neg, trunc, ok bool) {
+	const uint64digits = 19
+	i := 0
+
+	// optional sign
+	if i >= len(s) {
+		return
+	}
+	switch {
+	case s[i] == '+':
+		i++
+	case s[i] == '-':
+		neg = true
+		i++
+	}
+
+	// digits
+	sawdot := false
+	sawdigits := false
+	nd := 0
+	ndMant := 0
+	dp := 0
+	for ; i < len(s); i++ {
+		switch c := s[i]; true {
+		case c == '.':
+			if sawdot {
+				return
+			}
+			sawdot = true
+			dp = nd
+			continue
+
+		case '0' <= c && c <= '9':
+			sawdigits = true
+			if c == '0' && nd == 0 { // ignore leading zeros
+				dp--
+				continue
+			}
+			nd++
+			if ndMant < uint64digits {
+				mantissa *= 10
+				mantissa += uint64(c - '0')
+				ndMant++
+			} else if s[i] != '0' {
+				trunc = true
+			}
+			continue
+		}
+		break
+	}
+	if !sawdigits {
+		return
+	}
+	if !sawdot {
+		dp = nd
+	}
+
+	// optional exponent moves decimal point.
+	// if we read a very large, very long number,
+	// just be sure to move the decimal point by
+	// a lot (say, 100000).  it doesn't matter if it's
+	// not the exact number.
+	if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
+		i++
+		if i >= len(s) {
+			return
+		}
+		esign := 1
+		if s[i] == '+' {
+			i++
+		} else if s[i] == '-' {
+			i++
+			esign = -1
+		}
+		if i >= len(s) || s[i] < '0' || s[i] > '9' {
+			return
+		}
+		e := 0
+		for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
+			if e < 10000 {
+				e = e*10 + int(s[i]) - '0'
+			}
+		}
+		dp += e * esign
+	}
+
+	if i != len(s) {
+		return
+	}
+
+	exp = dp - ndMant
+	ok = true
+	return
+
+}
+
+// decimal power of ten to binary power of two.
+var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26}
+
+func (d *decimal) floatBits(flt *floatInfo) (b uint64, overflow bool) {
+	var exp int
+	var mant uint64
+
+	// Zero is always a special case.
+	if d.nd == 0 {
+		mant = 0
+		exp = flt.bias
+		goto out
+	}
+
+	// Obvious overflow/underflow.
+	// These bounds are for 64-bit floats.
+	// Will have to change if we want to support 80-bit floats in the future.
+	if d.dp > 310 {
+		goto overflow
+	}
+	if d.dp < -330 {
+		// zero
+		mant = 0
+		exp = flt.bias
+		goto out
+	}
+
+	// Scale by powers of two until in range [0.5, 1.0)
+	exp = 0
+	for d.dp > 0 {
+		var n int
+		if d.dp >= len(powtab) {
+			n = 27
+		} else {
+			n = powtab[d.dp]
+		}
+		d.Shift(-n)
+		exp += n
+	}
+	for d.dp < 0 || d.dp == 0 && d.d[0] < '5' {
+		var n int
+		if -d.dp >= len(powtab) {
+			n = 27
+		} else {
+			n = powtab[-d.dp]
+		}
+		d.Shift(n)
+		exp -= n
+	}
+
+	// Our range is [0.5,1) but floating point range is [1,2).
+	exp--
+
+	// Minimum representable exponent is flt.bias+1.
+	// If the exponent is smaller, move it up and
+	// adjust d accordingly.
+	if exp < flt.bias+1 {
+		n := flt.bias + 1 - exp
+		d.Shift(-n)
+		exp += n
+	}
+
+	if exp-flt.bias >= 1<<flt.expbits-1 {
+		goto overflow
+	}
+
+	// Extract 1+flt.mantbits bits.
+	d.Shift(int(1 + flt.mantbits))
+	mant = d.RoundedInteger()
+
+	// Rounding might have added a bit; shift down.
+	if mant == 2<<flt.mantbits {
+		mant >>= 1
+		exp++
+		if exp-flt.bias >= 1<<flt.expbits-1 {
+			goto overflow
+		}
+	}
+
+	// Denormalized?
+	if mant&(1<<flt.mantbits) == 0 {
+		exp = flt.bias
+	}
+	goto out
+
+overflow:
+	// ±Inf
+	mant = 0
+	exp = 1<<flt.expbits - 1 + flt.bias
+	overflow = true
+
+out:
+	// Assemble bits.
+	bits := mant & (uint64(1)<<flt.mantbits - 1)
+	bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
+	if d.neg {
+		bits |= 1 << flt.mantbits << flt.expbits
+	}
+	return bits, overflow
+}
+
+// Exact powers of 10.
+var float64pow10 = []float64{
+	1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+	1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+	1e20, 1e21, 1e22,
+}
+var float32pow10 = []float32{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10}
+
+// If possible to convert decimal representation to 64-bit float f exactly,
+// entirely in floating-point math, do so, avoiding the expense of decimalToFloatBits.
+// Three common cases:
+//	value is exact integer
+//	value is exact integer * exact power of ten
+//	value is exact integer / exact power of ten
+// These all produce potentially inexact but correctly rounded answers.
+func atof64exact(mantissa uint64, exp int, neg bool) (f float64, ok bool) {
+	if mantissa>>float64info.mantbits != 0 {
+		return
+	}
+	// gccgo gets this wrong on 32-bit i386 when not using -msse.
+	// See TestRoundTrip in atof_test.go for a test case.
+	if runtime.GOARCH == "386" {
+		return
+	}
+	f = float64(mantissa)
+	if neg {
+		f = -f
+	}
+	switch {
+	case exp == 0:
+		// an integer.
+		return f, true
+	// Exact integers are <= 10^15.
+	// Exact powers of ten are <= 10^22.
+	case exp > 0 && exp <= 15+22: // int * 10^k
+		// If exponent is big but number of digits is not,
+		// can move a few zeros into the integer part.
+		if exp > 22 {
+			f *= float64pow10[exp-22]
+			exp = 22
+		}
+		if f > 1e15 || f < -1e15 {
+			// the exponent was really too large.
+			return
+		}
+		return f * float64pow10[exp], true
+	case exp < 0 && exp >= -22: // int / 10^k
+		return f / float64pow10[-exp], true
+	}
+	return
+}
+
+// If possible to compute mantissa*10^exp to 32-bit float f exactly,
+// entirely in floating-point math, do so, avoiding the machinery above.
+func atof32exact(mantissa uint64, exp int, neg bool) (f float32, ok bool) {
+	if mantissa>>float32info.mantbits != 0 {
+		return
+	}
+	f = float32(mantissa)
+	if neg {
+		f = -f
+	}
+	switch {
+	case exp == 0:
+		return f, true
+	// Exact integers are <= 10^7.
+	// Exact powers of ten are <= 10^10.
+	case exp > 0 && exp <= 7+10: // int * 10^k
+		// If exponent is big but number of digits is not,
+		// can move a few zeros into the integer part.
+		if exp > 10 {
+			f *= float32pow10[exp-10]
+			exp = 10
+		}
+		if f > 1e7 || f < -1e7 {
+			// the exponent was really too large.
+			return
+		}
+		return f * float32pow10[exp], true
+	case exp < 0 && exp >= -10: // int / 10^k
+		return f / float32pow10[-exp], true
+	}
+	return
+}
+
+const fnParseFloat = "ParseFloat"
+
+func atof32(s string) (f float32, err error) {
+	if val, ok := special(s); ok {
+		return float32(val), nil
+	}
+
+	if optimize {
+		// Parse mantissa and exponent.
+		mantissa, exp, neg, trunc, ok := readFloat(s)
+		if ok {
+			// Try pure floating-point arithmetic conversion.
+			if !trunc {
+				if f, ok := atof32exact(mantissa, exp, neg); ok {
+					return f, nil
+				}
+			}
+			// Try another fast path.
+			ext := new(extFloat)
+			if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float32info); ok {
+				b, ovf := ext.floatBits(&float32info)
+				f = math.Float32frombits(uint32(b))
+				if ovf {
+					err = rangeError(fnParseFloat, s)
+				}
+				return f, err
+			}
+		}
+	}
+	var d decimal
+	if !d.set(s) {
+		return 0, syntaxError(fnParseFloat, s)
+	}
+	b, ovf := d.floatBits(&float32info)
+	f = math.Float32frombits(uint32(b))
+	if ovf {
+		err = rangeError(fnParseFloat, s)
+	}
+	return f, err
+}
+
+func atof64(s string) (f float64, err error) {
+	if val, ok := special(s); ok {
+		return val, nil
+	}
+
+	if optimize {
+		// Parse mantissa and exponent.
+		mantissa, exp, neg, trunc, ok := readFloat(s)
+		if ok {
+			// Try pure floating-point arithmetic conversion.
+			if !trunc {
+				if f, ok := atof64exact(mantissa, exp, neg); ok {
+					return f, nil
+				}
+			}
+			// Try another fast path.
+			ext := new(extFloat)
+			if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float64info); ok {
+				b, ovf := ext.floatBits(&float64info)
+				f = math.Float64frombits(b)
+				if ovf {
+					err = rangeError(fnParseFloat, s)
+				}
+				return f, err
+			}
+		}
+	}
+	var d decimal
+	if !d.set(s) {
+		return 0, syntaxError(fnParseFloat, s)
+	}
+	b, ovf := d.floatBits(&float64info)
+	f = math.Float64frombits(b)
+	if ovf {
+		err = rangeError(fnParseFloat, s)
+	}
+	return f, err
+}
+
+// ParseFloat converts the string s to a floating-point number
+// with the precision specified by bitSize: 32 for float32, or 64 for float64.
+// When bitSize=32, the result still has type float64, but it will be
+// convertible to float32 without changing its value.
+//
+// If s is well-formed and near a valid floating point number,
+// ParseFloat returns the nearest floating point number rounded
+// using IEEE754 unbiased rounding.
+//
+// The errors that ParseFloat returns have concrete type *NumError
+// and include err.Num = s.
+//
+// If s is not syntactically well-formed, ParseFloat returns err.Err = ErrSyntax.
+//
+// If s is syntactically well-formed but is more than 1/2 ULP
+// away from the largest floating point number of the given size,
+// ParseFloat returns f = ±Inf, err.Err = ErrRange.
+func ParseFloat(s string, bitSize int) (f float64, err error) {
+	if bitSize == 32 {
+		f1, err1 := atof32(s)
+		return float64(f1), err1
+	}
+	f1, err1 := atof64(s)
+	return f1, err1
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/atof_test.go b/third_party/gofrontend/libgo/go/strconv/atof_test.go
new file mode 100644
index 0000000..ba49332
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/atof_test.go
@@ -0,0 +1,430 @@
+// 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 strconv_test
+
+import (
+	"math"
+	"math/rand"
+	"reflect"
+	. "strconv"
+	"strings"
+	"testing"
+	"time"
+)
+
+type atofTest struct {
+	in  string
+	out string
+	err error
+}
+
+var atoftests = []atofTest{
+	{"", "0", ErrSyntax},
+	{"1", "1", nil},
+	{"+1", "1", nil},
+	{"1x", "0", ErrSyntax},
+	{"1.1.", "0", ErrSyntax},
+	{"1e23", "1e+23", nil},
+	{"1E23", "1e+23", nil},
+	{"100000000000000000000000", "1e+23", nil},
+	{"1e-100", "1e-100", nil},
+	{"123456700", "1.234567e+08", nil},
+	{"99999999999999974834176", "9.999999999999997e+22", nil},
+	{"100000000000000000000001", "1.0000000000000001e+23", nil},
+	{"100000000000000008388608", "1.0000000000000001e+23", nil},
+	{"100000000000000016777215", "1.0000000000000001e+23", nil},
+	{"100000000000000016777216", "1.0000000000000003e+23", nil},
+	{"-1", "-1", nil},
+	{"-0.1", "-0.1", nil},
+	{"-0", "-0", nil},
+	{"1e-20", "1e-20", nil},
+	{"625e-3", "0.625", nil},
+
+	// NaNs
+	{"nan", "NaN", nil},
+	{"NaN", "NaN", nil},
+	{"NAN", "NaN", nil},
+
+	// Infs
+	{"inf", "+Inf", nil},
+	{"-Inf", "-Inf", nil},
+	{"+INF", "+Inf", nil},
+	{"-Infinity", "-Inf", nil},
+	{"+INFINITY", "+Inf", nil},
+	{"Infinity", "+Inf", nil},
+
+	// largest float64
+	{"1.7976931348623157e308", "1.7976931348623157e+308", nil},
+	{"-1.7976931348623157e308", "-1.7976931348623157e+308", nil},
+	// next float64 - too large
+	{"1.7976931348623159e308", "+Inf", ErrRange},
+	{"-1.7976931348623159e308", "-Inf", ErrRange},
+	// the border is ...158079
+	// borderline - okay
+	{"1.7976931348623158e308", "1.7976931348623157e+308", nil},
+	{"-1.7976931348623158e308", "-1.7976931348623157e+308", nil},
+	// borderline - too large
+	{"1.797693134862315808e308", "+Inf", ErrRange},
+	{"-1.797693134862315808e308", "-Inf", ErrRange},
+
+	// a little too large
+	{"1e308", "1e+308", nil},
+	{"2e308", "+Inf", ErrRange},
+	{"1e309", "+Inf", ErrRange},
+
+	// way too large
+	{"1e310", "+Inf", ErrRange},
+	{"-1e310", "-Inf", ErrRange},
+	{"1e400", "+Inf", ErrRange},
+	{"-1e400", "-Inf", ErrRange},
+	{"1e400000", "+Inf", ErrRange},
+	{"-1e400000", "-Inf", ErrRange},
+
+	// denormalized
+	{"1e-305", "1e-305", nil},
+	{"1e-306", "1e-306", nil},
+	{"1e-307", "1e-307", nil},
+	{"1e-308", "1e-308", nil},
+	{"1e-309", "1e-309", nil},
+	{"1e-310", "1e-310", nil},
+	{"1e-322", "1e-322", nil},
+	// smallest denormal
+	{"5e-324", "5e-324", nil},
+	{"4e-324", "5e-324", nil},
+	{"3e-324", "5e-324", nil},
+	// too small
+	{"2e-324", "0", nil},
+	// way too small
+	{"1e-350", "0", nil},
+	{"1e-400000", "0", nil},
+
+	// try to overflow exponent
+	{"1e-4294967296", "0", nil},
+	{"1e+4294967296", "+Inf", ErrRange},
+	{"1e-18446744073709551616", "0", nil},
+	{"1e+18446744073709551616", "+Inf", ErrRange},
+
+	// Parse errors
+	{"1e", "0", ErrSyntax},
+	{"1e-", "0", ErrSyntax},
+	{".e-1", "0", ErrSyntax},
+	{"1\x00.2", "0", ErrSyntax},
+
+	// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
+	{"2.2250738585072012e-308", "2.2250738585072014e-308", nil},
+	// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
+	{"2.2250738585072011e-308", "2.225073858507201e-308", nil},
+
+	// A very large number (initially wrongly parsed by the fast algorithm).
+	{"4.630813248087435e+307", "4.630813248087435e+307", nil},
+
+	// A different kind of very large number.
+	{"22.222222222222222", "22.22222222222222", nil},
+	{"2." + strings.Repeat("2", 4000) + "e+1", "22.22222222222222", nil},
+
+	// Exactly halfway between 1 and math.Nextafter(1, 2).
+	// Round to even (down).
+	{"1.00000000000000011102230246251565404236316680908203125", "1", nil},
+	// Slightly lower; still round down.
+	{"1.00000000000000011102230246251565404236316680908203124", "1", nil},
+	// Slightly higher; round up.
+	{"1.00000000000000011102230246251565404236316680908203126", "1.0000000000000002", nil},
+	// Slightly higher, but you have to read all the way to the end.
+	{"1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1", "1.0000000000000002", nil},
+}
+
+var atof32tests = []atofTest{
+	// Exactly halfway between 1 and the next float32.
+	// Round to even (down).
+	{"1.000000059604644775390625", "1", nil},
+	// Slightly lower.
+	{"1.000000059604644775390624", "1", nil},
+	// Slightly higher.
+	{"1.000000059604644775390626", "1.0000001", nil},
+	// Slightly higher, but you have to read all the way to the end.
+	{"1.000000059604644775390625" + strings.Repeat("0", 10000) + "1", "1.0000001", nil},
+
+	// largest float32: (1<<128) * (1 - 2^-24)
+	{"340282346638528859811704183484516925440", "3.4028235e+38", nil},
+	{"-340282346638528859811704183484516925440", "-3.4028235e+38", nil},
+	// next float32 - too large
+	{"3.4028236e38", "+Inf", ErrRange},
+	{"-3.4028236e38", "-Inf", ErrRange},
+	// the border is 3.40282356779...e+38
+	// borderline - okay
+	{"3.402823567e38", "3.4028235e+38", nil},
+	{"-3.402823567e38", "-3.4028235e+38", nil},
+	// borderline - too large
+	{"3.4028235678e38", "+Inf", ErrRange},
+	{"-3.4028235678e38", "-Inf", ErrRange},
+
+	// Denormals: less than 2^-126
+	{"1e-38", "1e-38", nil},
+	{"1e-39", "1e-39", nil},
+	{"1e-40", "1e-40", nil},
+	{"1e-41", "1e-41", nil},
+	{"1e-42", "1e-42", nil},
+	{"1e-43", "1e-43", nil},
+	{"1e-44", "1e-44", nil},
+	{"6e-45", "6e-45", nil}, // 4p-149 = 5.6e-45
+	{"5e-45", "6e-45", nil},
+	// Smallest denormal
+	{"1e-45", "1e-45", nil}, // 1p-149 = 1.4e-45
+	{"2e-45", "1e-45", nil},
+
+	// 2^92 = 8388608p+69 = 4951760157141521099596496896 (4.9517602e27)
+	// is an exact power of two that needs 8 decimal digits to be correctly
+	// parsed back.
+	// The float32 before is 16777215p+68 = 4.95175986e+27
+	// The halfway is 4.951760009. A bad algorithm that thinks the previous
+	// float32 is 8388607p+69 will shorten incorrectly to 4.95176e+27.
+	{"4951760157141521099596496896", "4.9517602e+27", nil},
+}
+
+type atofSimpleTest struct {
+	x float64
+	s string
+}
+
+var (
+	atofRandomTests        []atofSimpleTest
+	benchmarksRandomBits   [1024]string
+	benchmarksRandomNormal [1024]string
+)
+
+func init() {
+	// The atof routines return NumErrors wrapping
+	// the error and the string.  Convert the table above.
+	for i := range atoftests {
+		test := &atoftests[i]
+		if test.err != nil {
+			test.err = &NumError{"ParseFloat", test.in, test.err}
+		}
+	}
+	for i := range atof32tests {
+		test := &atof32tests[i]
+		if test.err != nil {
+			test.err = &NumError{"ParseFloat", test.in, test.err}
+		}
+	}
+
+	// Generate random inputs for tests and benchmarks
+	rand.Seed(time.Now().UnixNano())
+	if testing.Short() {
+		atofRandomTests = make([]atofSimpleTest, 100)
+	} else {
+		atofRandomTests = make([]atofSimpleTest, 10000)
+	}
+	for i := range atofRandomTests {
+		n := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
+		x := math.Float64frombits(n)
+		s := FormatFloat(x, 'g', -1, 64)
+		atofRandomTests[i] = atofSimpleTest{x, s}
+	}
+
+	for i := range benchmarksRandomBits {
+		bits := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
+		x := math.Float64frombits(bits)
+		benchmarksRandomBits[i] = FormatFloat(x, 'g', -1, 64)
+	}
+
+	for i := range benchmarksRandomNormal {
+		x := rand.NormFloat64()
+		benchmarksRandomNormal[i] = FormatFloat(x, 'g', -1, 64)
+	}
+}
+
+func testAtof(t *testing.T, opt bool) {
+	oldopt := SetOptimize(opt)
+	for i := 0; i < len(atoftests); i++ {
+		test := &atoftests[i]
+		out, err := ParseFloat(test.in, 64)
+		outs := FormatFloat(out, 'g', -1, 64)
+		if outs != test.out || !reflect.DeepEqual(err, test.err) {
+			t.Errorf("ParseFloat(%v, 64) = %v, %v want %v, %v",
+				test.in, out, err, test.out, test.err)
+		}
+
+		if float64(float32(out)) == out {
+			out, err := ParseFloat(test.in, 32)
+			out32 := float32(out)
+			if float64(out32) != out {
+				t.Errorf("ParseFloat(%v, 32) = %v, not a float32 (closest is %v)", test.in, out, float64(out32))
+				continue
+			}
+			outs := FormatFloat(float64(out32), 'g', -1, 32)
+			if outs != test.out || !reflect.DeepEqual(err, test.err) {
+				t.Errorf("ParseFloat(%v, 32) = %v, %v want %v, %v  # %v",
+					test.in, out32, err, test.out, test.err, out)
+			}
+		}
+	}
+	for _, test := range atof32tests {
+		out, err := ParseFloat(test.in, 32)
+		out32 := float32(out)
+		if float64(out32) != out {
+			t.Errorf("ParseFloat(%v, 32) = %v, not a float32 (closest is %v)", test.in, out, float64(out32))
+			continue
+		}
+		outs := FormatFloat(float64(out32), 'g', -1, 32)
+		if outs != test.out || !reflect.DeepEqual(err, test.err) {
+			t.Errorf("ParseFloat(%v, 32) = %v, %v want %v, %v  # %v",
+				test.in, out32, err, test.out, test.err, out)
+		}
+	}
+	SetOptimize(oldopt)
+}
+
+func TestAtof(t *testing.T) { testAtof(t, true) }
+
+func TestAtofSlow(t *testing.T) { testAtof(t, false) }
+
+func TestAtofRandom(t *testing.T) {
+	for _, test := range atofRandomTests {
+		x, _ := ParseFloat(test.s, 64)
+		switch {
+		default:
+			t.Errorf("number %s badly parsed as %b (expected %b)", test.s, x, test.x)
+		case x == test.x:
+		case math.IsNaN(test.x) && math.IsNaN(x):
+		}
+	}
+	t.Logf("tested %d random numbers", len(atofRandomTests))
+}
+
+var roundTripCases = []struct {
+	f float64
+	s string
+}{
+	// Issue 2917.
+	// This test will break the optimized conversion if the
+	// FPU is using 80-bit registers instead of 64-bit registers,
+	// usually because the operating system initialized the
+	// thread with 80-bit precision and the Go runtime didn't
+	// fix the FP control word.
+	{8865794286000691 << 39, "4.87402195346389e+27"},
+	{8865794286000692 << 39, "4.8740219534638903e+27"},
+}
+
+func TestRoundTrip(t *testing.T) {
+	for _, tt := range roundTripCases {
+		old := SetOptimize(false)
+		s := FormatFloat(tt.f, 'g', -1, 64)
+		if s != tt.s {
+			t.Errorf("no-opt FormatFloat(%b) = %s, want %s", tt.f, s, tt.s)
+		}
+		f, err := ParseFloat(tt.s, 64)
+		if f != tt.f || err != nil {
+			t.Errorf("no-opt ParseFloat(%s) = %b, %v want %b, nil", tt.s, f, err, tt.f)
+		}
+		SetOptimize(true)
+		s = FormatFloat(tt.f, 'g', -1, 64)
+		if s != tt.s {
+			t.Errorf("opt FormatFloat(%b) = %s, want %s", tt.f, s, tt.s)
+		}
+		f, err = ParseFloat(tt.s, 64)
+		if f != tt.f || err != nil {
+			t.Errorf("opt ParseFloat(%s) = %b, %v want %b, nil", tt.s, f, err, tt.f)
+		}
+		SetOptimize(old)
+	}
+}
+
+// TestRoundTrip32 tries a fraction of all finite positive float32 values.
+func TestRoundTrip32(t *testing.T) {
+	step := uint32(997)
+	if testing.Short() {
+		step = 99991
+	}
+	count := 0
+	for i := uint32(0); i < 0xff<<23; i += step {
+		f := math.Float32frombits(i)
+		if i&1 == 1 {
+			f = -f // negative
+		}
+		s := FormatFloat(float64(f), 'g', -1, 32)
+
+		parsed, err := ParseFloat(s, 32)
+		parsed32 := float32(parsed)
+		switch {
+		case err != nil:
+			t.Errorf("ParseFloat(%q, 32) gave error %s", s, err)
+		case float64(parsed32) != parsed:
+			t.Errorf("ParseFloat(%q, 32) = %v, not a float32 (nearest is %v)", s, parsed, parsed32)
+		case parsed32 != f:
+			t.Errorf("ParseFloat(%q, 32) = %b (expected %b)", s, parsed32, f)
+		}
+		count++
+	}
+	t.Logf("tested %d float32's", count)
+}
+
+func BenchmarkAtof64Decimal(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat("33909", 64)
+	}
+}
+
+func BenchmarkAtof64Float(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat("339.7784", 64)
+	}
+}
+
+func BenchmarkAtof64FloatExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat("-5.09e75", 64)
+	}
+}
+
+func BenchmarkAtof64Big(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat("123456789123456789123456789", 64)
+	}
+}
+
+func BenchmarkAtof64RandomBits(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat(benchmarksRandomBits[i%1024], 64)
+	}
+}
+
+func BenchmarkAtof64RandomFloats(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat(benchmarksRandomNormal[i%1024], 64)
+	}
+}
+
+func BenchmarkAtof32Decimal(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat("33909", 32)
+	}
+}
+
+func BenchmarkAtof32Float(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat("339.778", 32)
+	}
+}
+
+func BenchmarkAtof32FloatExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat("12.3456e32", 32)
+	}
+}
+
+var float32strings [4096]string
+
+func BenchmarkAtof32Random(b *testing.B) {
+	n := uint32(997)
+	for i := range float32strings {
+		n = (99991*n + 42) % (0xff << 23)
+		float32strings[i] = FormatFloat(float64(math.Float32frombits(n)), 'g', -1, 32)
+	}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		ParseFloat(float32strings[i%4096], 32)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/atoi.go b/third_party/gofrontend/libgo/go/strconv/atoi.go
new file mode 100644
index 0000000..cbf0380
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/atoi.go
@@ -0,0 +1,198 @@
+// 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 strconv
+
+import "errors"
+
+// ErrRange indicates that a value is out of range for the target type.
+var ErrRange = errors.New("value out of range")
+
+// ErrSyntax indicates that a value does not have the right syntax for the target type.
+var ErrSyntax = errors.New("invalid syntax")
+
+// A NumError records a failed conversion.
+type NumError struct {
+	Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
+	Num  string // the input
+	Err  error  // the reason the conversion failed (ErrRange, ErrSyntax)
+}
+
+func (e *NumError) Error() string {
+	return "strconv." + e.Func + ": " + "parsing " + Quote(e.Num) + ": " + e.Err.Error()
+}
+
+func syntaxError(fn, str string) *NumError {
+	return &NumError{fn, str, ErrSyntax}
+}
+
+func rangeError(fn, str string) *NumError {
+	return &NumError{fn, str, ErrRange}
+}
+
+const intSize = 32 << uint(^uint(0)>>63)
+
+// IntSize is the size in bits of an int or uint value.
+const IntSize = intSize
+
+// Return the first number n such that n*base >= 1<<64.
+func cutoff64(base int) uint64 {
+	if base < 2 {
+		return 0
+	}
+	return (1<<64-1)/uint64(base) + 1
+}
+
+// ParseUint is like ParseInt but for unsigned numbers.
+func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
+	var cutoff, maxVal uint64
+
+	if bitSize == 0 {
+		bitSize = int(IntSize)
+	}
+
+	s0 := s
+	switch {
+	case len(s) < 1:
+		err = ErrSyntax
+		goto Error
+
+	case 2 <= base && base <= 36:
+		// valid base; nothing to do
+
+	case base == 0:
+		// Look for octal, hex prefix.
+		switch {
+		case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
+			base = 16
+			s = s[2:]
+			if len(s) < 1 {
+				err = ErrSyntax
+				goto Error
+			}
+		case s[0] == '0':
+			base = 8
+		default:
+			base = 10
+		}
+
+	default:
+		err = errors.New("invalid base " + Itoa(base))
+		goto Error
+	}
+
+	n = 0
+	cutoff = cutoff64(base)
+	maxVal = 1<<uint(bitSize) - 1
+
+	for i := 0; i < len(s); i++ {
+		var v byte
+		d := s[i]
+		switch {
+		case '0' <= d && d <= '9':
+			v = d - '0'
+		case 'a' <= d && d <= 'z':
+			v = d - 'a' + 10
+		case 'A' <= d && d <= 'Z':
+			v = d - 'A' + 10
+		default:
+			n = 0
+			err = ErrSyntax
+			goto Error
+		}
+		if int(v) >= base {
+			n = 0
+			err = ErrSyntax
+			goto Error
+		}
+
+		if n >= cutoff {
+			// n*base overflows
+			n = 1<<64 - 1
+			err = ErrRange
+			goto Error
+		}
+		n *= uint64(base)
+
+		n1 := n + uint64(v)
+		if n1 < n || n1 > maxVal {
+			// n+v overflows
+			n = 1<<64 - 1
+			err = ErrRange
+			goto Error
+		}
+		n = n1
+	}
+
+	return n, nil
+
+Error:
+	return n, &NumError{"ParseUint", s0, err}
+}
+
+// ParseInt interprets a string s in the given base (2 to 36) and
+// returns the corresponding value i.  If base == 0, the base is
+// implied by the string's prefix: base 16 for "0x", base 8 for
+// "0", and base 10 otherwise.
+//
+// The bitSize argument specifies the integer type
+// that the result must fit into.  Bit sizes 0, 8, 16, 32, and 64
+// correspond to int, int8, int16, int32, and int64.
+//
+// The errors that ParseInt returns have concrete type *NumError
+// and include err.Num = s.  If s is empty or contains invalid
+// digits, err.Err = ErrSyntax and the returned value is 0;
+// if the value corresponding to s cannot be represented by a
+// signed integer of the given size, err.Err = ErrRange and the
+// returned value is the maximum magnitude integer of the
+// appropriate bitSize and sign.
+func ParseInt(s string, base int, bitSize int) (i int64, err error) {
+	const fnParseInt = "ParseInt"
+
+	if bitSize == 0 {
+		bitSize = int(IntSize)
+	}
+
+	// Empty string bad.
+	if len(s) == 0 {
+		return 0, syntaxError(fnParseInt, s)
+	}
+
+	// Pick off leading sign.
+	s0 := s
+	neg := false
+	if s[0] == '+' {
+		s = s[1:]
+	} else if s[0] == '-' {
+		neg = true
+		s = s[1:]
+	}
+
+	// Convert unsigned and check range.
+	var un uint64
+	un, err = ParseUint(s, base, bitSize)
+	if err != nil && err.(*NumError).Err != ErrRange {
+		err.(*NumError).Func = fnParseInt
+		err.(*NumError).Num = s0
+		return 0, err
+	}
+	cutoff := uint64(1 << uint(bitSize-1))
+	if !neg && un >= cutoff {
+		return int64(cutoff - 1), rangeError(fnParseInt, s0)
+	}
+	if neg && un > cutoff {
+		return -int64(cutoff), rangeError(fnParseInt, s0)
+	}
+	n := int64(un)
+	if neg {
+		n = -n
+	}
+	return n, nil
+}
+
+// Atoi is shorthand for ParseInt(s, 10, 0).
+func Atoi(s string) (i int, err error) {
+	i64, err := ParseInt(s, 10, 0)
+	return int(i64), err
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/atoi_test.go b/third_party/gofrontend/libgo/go/strconv/atoi_test.go
new file mode 100644
index 0000000..9407573
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/atoi_test.go
@@ -0,0 +1,326 @@
+// 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 strconv_test
+
+import (
+	"errors"
+	"reflect"
+	. "strconv"
+	"testing"
+)
+
+type atoui64Test struct {
+	in  string
+	out uint64
+	err error
+}
+
+var atoui64tests = []atoui64Test{
+	{"", 0, ErrSyntax},
+	{"0", 0, nil},
+	{"1", 1, nil},
+	{"12345", 12345, nil},
+	{"012345", 12345, nil},
+	{"12345x", 0, ErrSyntax},
+	{"98765432100", 98765432100, nil},
+	{"18446744073709551615", 1<<64 - 1, nil},
+	{"18446744073709551616", 1<<64 - 1, ErrRange},
+	{"18446744073709551620", 1<<64 - 1, ErrRange},
+}
+
+var btoui64tests = []atoui64Test{
+	{"", 0, ErrSyntax},
+	{"0", 0, nil},
+	{"1", 1, nil},
+	{"12345", 12345, nil},
+	{"012345", 012345, nil},
+	{"0x12345", 0x12345, nil},
+	{"0X12345", 0x12345, nil},
+	{"12345x", 0, ErrSyntax},
+	{"98765432100", 98765432100, nil},
+	{"18446744073709551615", 1<<64 - 1, nil},
+	{"18446744073709551616", 1<<64 - 1, ErrRange},
+	{"18446744073709551620", 1<<64 - 1, ErrRange},
+	{"0xFFFFFFFFFFFFFFFF", 1<<64 - 1, nil},
+	{"0x10000000000000000", 1<<64 - 1, ErrRange},
+	{"01777777777777777777777", 1<<64 - 1, nil},
+	{"01777777777777777777778", 0, ErrSyntax},
+	{"02000000000000000000000", 1<<64 - 1, ErrRange},
+	{"0200000000000000000000", 1 << 61, nil},
+}
+
+type atoi64Test struct {
+	in  string
+	out int64
+	err error
+}
+
+var atoi64tests = []atoi64Test{
+	{"", 0, ErrSyntax},
+	{"0", 0, nil},
+	{"-0", 0, nil},
+	{"1", 1, nil},
+	{"-1", -1, nil},
+	{"12345", 12345, nil},
+	{"-12345", -12345, nil},
+	{"012345", 12345, nil},
+	{"-012345", -12345, nil},
+	{"98765432100", 98765432100, nil},
+	{"-98765432100", -98765432100, nil},
+	{"9223372036854775807", 1<<63 - 1, nil},
+	{"-9223372036854775807", -(1<<63 - 1), nil},
+	{"9223372036854775808", 1<<63 - 1, ErrRange},
+	{"-9223372036854775808", -1 << 63, nil},
+	{"9223372036854775809", 1<<63 - 1, ErrRange},
+	{"-9223372036854775809", -1 << 63, ErrRange},
+}
+
+var btoi64tests = []atoi64Test{
+	{"", 0, ErrSyntax},
+	{"0", 0, nil},
+	{"-0", 0, nil},
+	{"1", 1, nil},
+	{"-1", -1, nil},
+	{"12345", 12345, nil},
+	{"-12345", -12345, nil},
+	{"012345", 012345, nil},
+	{"-012345", -012345, nil},
+	{"0x12345", 0x12345, nil},
+	{"-0X12345", -0x12345, nil},
+	{"12345x", 0, ErrSyntax},
+	{"-12345x", 0, ErrSyntax},
+	{"98765432100", 98765432100, nil},
+	{"-98765432100", -98765432100, nil},
+	{"9223372036854775807", 1<<63 - 1, nil},
+	{"-9223372036854775807", -(1<<63 - 1), nil},
+	{"9223372036854775808", 1<<63 - 1, ErrRange},
+	{"-9223372036854775808", -1 << 63, nil},
+	{"9223372036854775809", 1<<63 - 1, ErrRange},
+	{"-9223372036854775809", -1 << 63, ErrRange},
+}
+
+type atoui32Test struct {
+	in  string
+	out uint32
+	err error
+}
+
+var atoui32tests = []atoui32Test{
+	{"", 0, ErrSyntax},
+	{"0", 0, nil},
+	{"1", 1, nil},
+	{"12345", 12345, nil},
+	{"012345", 12345, nil},
+	{"12345x", 0, ErrSyntax},
+	{"987654321", 987654321, nil},
+	{"4294967295", 1<<32 - 1, nil},
+	{"4294967296", 1<<32 - 1, ErrRange},
+}
+
+type atoi32Test struct {
+	in  string
+	out int32
+	err error
+}
+
+var atoi32tests = []atoi32Test{
+	{"", 0, ErrSyntax},
+	{"0", 0, nil},
+	{"-0", 0, nil},
+	{"1", 1, nil},
+	{"-1", -1, nil},
+	{"12345", 12345, nil},
+	{"-12345", -12345, nil},
+	{"012345", 12345, nil},
+	{"-012345", -12345, nil},
+	{"12345x", 0, ErrSyntax},
+	{"-12345x", 0, ErrSyntax},
+	{"987654321", 987654321, nil},
+	{"-987654321", -987654321, nil},
+	{"2147483647", 1<<31 - 1, nil},
+	{"-2147483647", -(1<<31 - 1), nil},
+	{"2147483648", 1<<31 - 1, ErrRange},
+	{"-2147483648", -1 << 31, nil},
+	{"2147483649", 1<<31 - 1, ErrRange},
+	{"-2147483649", -1 << 31, ErrRange},
+}
+
+type numErrorTest struct {
+	num, want string
+}
+
+var numErrorTests = []numErrorTest{
+	{"0", `strconv.ParseFloat: parsing "0": failed`},
+	{"`", "strconv.ParseFloat: parsing \"`\": failed"},
+	{"1\x00.2", `strconv.ParseFloat: parsing "1\x00.2": failed`},
+}
+
+func init() {
+	// The atoi routines return NumErrors wrapping
+	// the error and the string.  Convert the tables above.
+	for i := range atoui64tests {
+		test := &atoui64tests[i]
+		if test.err != nil {
+			test.err = &NumError{"ParseUint", test.in, test.err}
+		}
+	}
+	for i := range btoui64tests {
+		test := &btoui64tests[i]
+		if test.err != nil {
+			test.err = &NumError{"ParseUint", test.in, test.err}
+		}
+	}
+	for i := range atoi64tests {
+		test := &atoi64tests[i]
+		if test.err != nil {
+			test.err = &NumError{"ParseInt", test.in, test.err}
+		}
+	}
+	for i := range btoi64tests {
+		test := &btoi64tests[i]
+		if test.err != nil {
+			test.err = &NumError{"ParseInt", test.in, test.err}
+		}
+	}
+	for i := range atoui32tests {
+		test := &atoui32tests[i]
+		if test.err != nil {
+			test.err = &NumError{"ParseUint", test.in, test.err}
+		}
+	}
+	for i := range atoi32tests {
+		test := &atoi32tests[i]
+		if test.err != nil {
+			test.err = &NumError{"ParseInt", test.in, test.err}
+		}
+	}
+}
+
+func TestParseUint64(t *testing.T) {
+	for i := range atoui64tests {
+		test := &atoui64tests[i]
+		out, err := ParseUint(test.in, 10, 64)
+		if test.out != out || !reflect.DeepEqual(test.err, err) {
+			t.Errorf("Atoui64(%q) = %v, %v want %v, %v",
+				test.in, out, err, test.out, test.err)
+		}
+	}
+}
+
+func TestParseUint64Base(t *testing.T) {
+	for i := range btoui64tests {
+		test := &btoui64tests[i]
+		out, err := ParseUint(test.in, 0, 64)
+		if test.out != out || !reflect.DeepEqual(test.err, err) {
+			t.Errorf("ParseUint(%q) = %v, %v want %v, %v",
+				test.in, out, err, test.out, test.err)
+		}
+	}
+}
+
+func TestParseInt64(t *testing.T) {
+	for i := range atoi64tests {
+		test := &atoi64tests[i]
+		out, err := ParseInt(test.in, 10, 64)
+		if test.out != out || !reflect.DeepEqual(test.err, err) {
+			t.Errorf("Atoi64(%q) = %v, %v want %v, %v",
+				test.in, out, err, test.out, test.err)
+		}
+	}
+}
+
+func TestParseInt64Base(t *testing.T) {
+	for i := range btoi64tests {
+		test := &btoi64tests[i]
+		out, err := ParseInt(test.in, 0, 64)
+		if test.out != out || !reflect.DeepEqual(test.err, err) {
+			t.Errorf("ParseInt(%q) = %v, %v want %v, %v",
+				test.in, out, err, test.out, test.err)
+		}
+	}
+}
+
+func TestParseUint(t *testing.T) {
+	switch IntSize {
+	case 32:
+		for i := range atoui32tests {
+			test := &atoui32tests[i]
+			out, err := ParseUint(test.in, 10, 0)
+			if test.out != uint32(out) || !reflect.DeepEqual(test.err, err) {
+				t.Errorf("Atoui(%q) = %v, %v want %v, %v",
+					test.in, out, err, test.out, test.err)
+			}
+		}
+	case 64:
+		for i := range atoui64tests {
+			test := &atoui64tests[i]
+			out, err := ParseUint(test.in, 10, 0)
+			if test.out != uint64(out) || !reflect.DeepEqual(test.err, err) {
+				t.Errorf("Atoui(%q) = %v, %v want %v, %v",
+					test.in, out, err, test.out, test.err)
+			}
+		}
+	}
+}
+
+func TestParseInt(t *testing.T) {
+	switch IntSize {
+	case 32:
+		for i := range atoi32tests {
+			test := &atoi32tests[i]
+			out, err := ParseInt(test.in, 10, 0)
+			if test.out != int32(out) || !reflect.DeepEqual(test.err, err) {
+				t.Errorf("Atoi(%q) = %v, %v want %v, %v",
+					test.in, out, err, test.out, test.err)
+			}
+		}
+	case 64:
+		for i := range atoi64tests {
+			test := &atoi64tests[i]
+			out, err := ParseInt(test.in, 10, 0)
+			if test.out != int64(out) || !reflect.DeepEqual(test.err, err) {
+				t.Errorf("Atoi(%q) = %v, %v want %v, %v",
+					test.in, out, err, test.out, test.err)
+			}
+		}
+	}
+}
+
+func TestNumError(t *testing.T) {
+	for _, test := range numErrorTests {
+		err := &NumError{
+			Func: "ParseFloat",
+			Num:  test.num,
+			Err:  errors.New("failed"),
+		}
+		if got := err.Error(); got != test.want {
+			t.Errorf(`(&NumError{"ParseFloat", %q, "failed"}).Error() = %v, want %v`, test.num, got, test.want)
+		}
+	}
+}
+
+func BenchmarkAtoi(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseInt("12345678", 10, 0)
+	}
+}
+
+func BenchmarkAtoiNeg(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseInt("-12345678", 10, 0)
+	}
+}
+
+func BenchmarkAtoi64(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseInt("12345678901234", 10, 64)
+	}
+}
+
+func BenchmarkAtoi64Neg(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseInt("-12345678901234", 10, 64)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/decimal.go b/third_party/gofrontend/libgo/go/strconv/decimal.go
new file mode 100644
index 0000000..4260128
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/decimal.go
@@ -0,0 +1,378 @@
+// 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.
+
+// Multiprecision decimal numbers.
+// For floating-point formatting only; not general purpose.
+// Only operations are assign and (binary) left/right shift.
+// Can do binary floating point in multiprecision decimal precisely
+// because 2 divides 10; cannot do decimal floating point
+// in multiprecision binary precisely.
+
+package strconv
+
+type decimal struct {
+	d     [800]byte // digits
+	nd    int       // number of digits used
+	dp    int       // decimal point
+	neg   bool
+	trunc bool // discarded nonzero digits beyond d[:nd]
+}
+
+func (a *decimal) String() string {
+	n := 10 + a.nd
+	if a.dp > 0 {
+		n += a.dp
+	}
+	if a.dp < 0 {
+		n += -a.dp
+	}
+
+	buf := make([]byte, n)
+	w := 0
+	switch {
+	case a.nd == 0:
+		return "0"
+
+	case a.dp <= 0:
+		// zeros fill space between decimal point and digits
+		buf[w] = '0'
+		w++
+		buf[w] = '.'
+		w++
+		w += digitZero(buf[w : w+-a.dp])
+		w += copy(buf[w:], a.d[0:a.nd])
+
+	case a.dp < a.nd:
+		// decimal point in middle of digits
+		w += copy(buf[w:], a.d[0:a.dp])
+		buf[w] = '.'
+		w++
+		w += copy(buf[w:], a.d[a.dp:a.nd])
+
+	default:
+		// zeros fill space between digits and decimal point
+		w += copy(buf[w:], a.d[0:a.nd])
+		w += digitZero(buf[w : w+a.dp-a.nd])
+	}
+	return string(buf[0:w])
+}
+
+func digitZero(dst []byte) int {
+	for i := range dst {
+		dst[i] = '0'
+	}
+	return len(dst)
+}
+
+// trim trailing zeros from number.
+// (They are meaningless; the decimal point is tracked
+// independent of the number of digits.)
+func trim(a *decimal) {
+	for a.nd > 0 && a.d[a.nd-1] == '0' {
+		a.nd--
+	}
+	if a.nd == 0 {
+		a.dp = 0
+	}
+}
+
+// Assign v to a.
+func (a *decimal) Assign(v uint64) {
+	var buf [24]byte
+
+	// Write reversed decimal in buf.
+	n := 0
+	for v > 0 {
+		v1 := v / 10
+		v -= 10 * v1
+		buf[n] = byte(v + '0')
+		n++
+		v = v1
+	}
+
+	// Reverse again to produce forward decimal in a.d.
+	a.nd = 0
+	for n--; n >= 0; n-- {
+		a.d[a.nd] = buf[n]
+		a.nd++
+	}
+	a.dp = a.nd
+	trim(a)
+}
+
+// Maximum shift that we can do in one pass without overflow.
+// Signed int has 31 bits, and we have to be able to accommodate 9<<k.
+const maxShift = 27
+
+// Binary shift right (* 2) by k bits.  k <= maxShift to avoid overflow.
+func rightShift(a *decimal, k uint) {
+	r := 0 // read pointer
+	w := 0 // write pointer
+
+	// Pick up enough leading digits to cover first shift.
+	n := 0
+	for ; n>>k == 0; r++ {
+		if r >= a.nd {
+			if n == 0 {
+				// a == 0; shouldn't get here, but handle anyway.
+				a.nd = 0
+				return
+			}
+			for n>>k == 0 {
+				n = n * 10
+				r++
+			}
+			break
+		}
+		c := int(a.d[r])
+		n = n*10 + c - '0'
+	}
+	a.dp -= r - 1
+
+	// Pick up a digit, put down a digit.
+	for ; r < a.nd; r++ {
+		c := int(a.d[r])
+		dig := n >> k
+		n -= dig << k
+		a.d[w] = byte(dig + '0')
+		w++
+		n = n*10 + c - '0'
+	}
+
+	// Put down extra digits.
+	for n > 0 {
+		dig := n >> k
+		n -= dig << k
+		if w < len(a.d) {
+			a.d[w] = byte(dig + '0')
+			w++
+		} else if dig > 0 {
+			a.trunc = true
+		}
+		n = n * 10
+	}
+
+	a.nd = w
+	trim(a)
+}
+
+// Cheat sheet for left shift: table indexed by shift count giving
+// number of new digits that will be introduced by that shift.
+//
+// For example, leftcheats[4] = {2, "625"}.  That means that
+// if we are shifting by 4 (multiplying by 16), it will add 2 digits
+// when the string prefix is "625" through "999", and one fewer digit
+// if the string prefix is "000" through "624".
+//
+// Credit for this trick goes to Ken.
+
+type leftCheat struct {
+	delta  int    // number of new digits
+	cutoff string //   minus one digit if original < a.
+}
+
+var leftcheats = []leftCheat{
+	// Leading digits of 1/2^i = 5^i.
+	// 5^23 is not an exact 64-bit floating point number,
+	// so have to use bc for the math.
+	/*
+		seq 27 | sed 's/^/5^/' | bc |
+		awk 'BEGIN{ print "\tleftCheat{ 0, \"\" }," }
+		{
+			log2 = log(2)/log(10)
+			printf("\tleftCheat{ %d, \"%s\" },\t// * %d\n",
+				int(log2*NR+1), $0, 2**NR)
+		}'
+	*/
+	{0, ""},
+	{1, "5"},                   // * 2
+	{1, "25"},                  // * 4
+	{1, "125"},                 // * 8
+	{2, "625"},                 // * 16
+	{2, "3125"},                // * 32
+	{2, "15625"},               // * 64
+	{3, "78125"},               // * 128
+	{3, "390625"},              // * 256
+	{3, "1953125"},             // * 512
+	{4, "9765625"},             // * 1024
+	{4, "48828125"},            // * 2048
+	{4, "244140625"},           // * 4096
+	{4, "1220703125"},          // * 8192
+	{5, "6103515625"},          // * 16384
+	{5, "30517578125"},         // * 32768
+	{5, "152587890625"},        // * 65536
+	{6, "762939453125"},        // * 131072
+	{6, "3814697265625"},       // * 262144
+	{6, "19073486328125"},      // * 524288
+	{7, "95367431640625"},      // * 1048576
+	{7, "476837158203125"},     // * 2097152
+	{7, "2384185791015625"},    // * 4194304
+	{7, "11920928955078125"},   // * 8388608
+	{8, "59604644775390625"},   // * 16777216
+	{8, "298023223876953125"},  // * 33554432
+	{8, "1490116119384765625"}, // * 67108864
+	{9, "7450580596923828125"}, // * 134217728
+}
+
+// Is the leading prefix of b lexicographically less than s?
+func prefixIsLessThan(b []byte, s string) bool {
+	for i := 0; i < len(s); i++ {
+		if i >= len(b) {
+			return true
+		}
+		if b[i] != s[i] {
+			return b[i] < s[i]
+		}
+	}
+	return false
+}
+
+// Binary shift left (/ 2) by k bits.  k <= maxShift to avoid overflow.
+func leftShift(a *decimal, k uint) {
+	delta := leftcheats[k].delta
+	if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
+		delta--
+	}
+
+	r := a.nd         // read index
+	w := a.nd + delta // write index
+	n := 0
+
+	// Pick up a digit, put down a digit.
+	for r--; r >= 0; r-- {
+		n += (int(a.d[r]) - '0') << k
+		quo := n / 10
+		rem := n - 10*quo
+		w--
+		if w < len(a.d) {
+			a.d[w] = byte(rem + '0')
+		} else if rem != 0 {
+			a.trunc = true
+		}
+		n = quo
+	}
+
+	// Put down extra digits.
+	for n > 0 {
+		quo := n / 10
+		rem := n - 10*quo
+		w--
+		if w < len(a.d) {
+			a.d[w] = byte(rem + '0')
+		} else if rem != 0 {
+			a.trunc = true
+		}
+		n = quo
+	}
+
+	a.nd += delta
+	if a.nd >= len(a.d) {
+		a.nd = len(a.d)
+	}
+	a.dp += delta
+	trim(a)
+}
+
+// Binary shift left (k > 0) or right (k < 0).
+func (a *decimal) Shift(k int) {
+	switch {
+	case a.nd == 0:
+		// nothing to do: a == 0
+	case k > 0:
+		for k > maxShift {
+			leftShift(a, maxShift)
+			k -= maxShift
+		}
+		leftShift(a, uint(k))
+	case k < 0:
+		for k < -maxShift {
+			rightShift(a, maxShift)
+			k += maxShift
+		}
+		rightShift(a, uint(-k))
+	}
+}
+
+// If we chop a at nd digits, should we round up?
+func shouldRoundUp(a *decimal, nd int) bool {
+	if nd < 0 || nd >= a.nd {
+		return false
+	}
+	if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even
+		// if we truncated, a little higher than what's recorded - always round up
+		if a.trunc {
+			return true
+		}
+		return nd > 0 && (a.d[nd-1]-'0')%2 != 0
+	}
+	// not halfway - digit tells all
+	return a.d[nd] >= '5'
+}
+
+// Round a to nd digits (or fewer).
+// If nd is zero, it means we're rounding
+// just to the left of the digits, as in
+// 0.09 -> 0.1.
+func (a *decimal) Round(nd int) {
+	if nd < 0 || nd >= a.nd {
+		return
+	}
+	if shouldRoundUp(a, nd) {
+		a.RoundUp(nd)
+	} else {
+		a.RoundDown(nd)
+	}
+}
+
+// Round a down to nd digits (or fewer).
+func (a *decimal) RoundDown(nd int) {
+	if nd < 0 || nd >= a.nd {
+		return
+	}
+	a.nd = nd
+	trim(a)
+}
+
+// Round a up to nd digits (or fewer).
+func (a *decimal) RoundUp(nd int) {
+	if nd < 0 || nd >= a.nd {
+		return
+	}
+
+	// round up
+	for i := nd - 1; i >= 0; i-- {
+		c := a.d[i]
+		if c < '9' { // can stop after this digit
+			a.d[i]++
+			a.nd = i + 1
+			return
+		}
+	}
+
+	// Number is all 9s.
+	// Change to single 1 with adjusted decimal point.
+	a.d[0] = '1'
+	a.nd = 1
+	a.dp++
+}
+
+// Extract integer part, rounded appropriately.
+// No guarantees about overflow.
+func (a *decimal) RoundedInteger() uint64 {
+	if a.dp > 20 {
+		return 0xFFFFFFFFFFFFFFFF
+	}
+	var i int
+	n := uint64(0)
+	for i = 0; i < a.dp && i < a.nd; i++ {
+		n = n*10 + uint64(a.d[i]-'0')
+	}
+	for ; i < a.dp; i++ {
+		n *= 10
+	}
+	if shouldRoundUp(a, a.dp) {
+		n++
+	}
+	return n
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/decimal_test.go b/third_party/gofrontend/libgo/go/strconv/decimal_test.go
new file mode 100644
index 0000000..13a127f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/decimal_test.go
@@ -0,0 +1,127 @@
+// 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 strconv_test
+
+import (
+	. "strconv"
+	"testing"
+)
+
+type shiftTest struct {
+	i     uint64
+	shift int
+	out   string
+}
+
+var shifttests = []shiftTest{
+	{0, -100, "0"},
+	{0, 100, "0"},
+	{1, 100, "1267650600228229401496703205376"},
+	{1, -100,
+		"0.00000000000000000000000000000078886090522101180541" +
+			"17285652827862296732064351090230047702789306640625",
+	},
+	{12345678, 8, "3160493568"},
+	{12345678, -8, "48225.3046875"},
+	{195312, 9, "99999744"},
+	{1953125, 9, "1000000000"},
+}
+
+func TestDecimalShift(t *testing.T) {
+	for i := 0; i < len(shifttests); i++ {
+		test := &shifttests[i]
+		d := NewDecimal(test.i)
+		d.Shift(test.shift)
+		s := d.String()
+		if s != test.out {
+			t.Errorf("Decimal %v << %v = %v, want %v",
+				test.i, test.shift, s, test.out)
+		}
+	}
+}
+
+type roundTest struct {
+	i               uint64
+	nd              int
+	down, round, up string
+	int             uint64
+}
+
+var roundtests = []roundTest{
+	{0, 4, "0", "0", "0", 0},
+	{12344999, 4, "12340000", "12340000", "12350000", 12340000},
+	{12345000, 4, "12340000", "12340000", "12350000", 12340000},
+	{12345001, 4, "12340000", "12350000", "12350000", 12350000},
+	{23454999, 4, "23450000", "23450000", "23460000", 23450000},
+	{23455000, 4, "23450000", "23460000", "23460000", 23460000},
+	{23455001, 4, "23450000", "23460000", "23460000", 23460000},
+
+	{99994999, 4, "99990000", "99990000", "100000000", 99990000},
+	{99995000, 4, "99990000", "100000000", "100000000", 100000000},
+	{99999999, 4, "99990000", "100000000", "100000000", 100000000},
+
+	{12994999, 4, "12990000", "12990000", "13000000", 12990000},
+	{12995000, 4, "12990000", "13000000", "13000000", 13000000},
+	{12999999, 4, "12990000", "13000000", "13000000", 13000000},
+}
+
+func TestDecimalRound(t *testing.T) {
+	for i := 0; i < len(roundtests); i++ {
+		test := &roundtests[i]
+		d := NewDecimal(test.i)
+		d.RoundDown(test.nd)
+		s := d.String()
+		if s != test.down {
+			t.Errorf("Decimal %v RoundDown %d = %v, want %v",
+				test.i, test.nd, s, test.down)
+		}
+		d = NewDecimal(test.i)
+		d.Round(test.nd)
+		s = d.String()
+		if s != test.round {
+			t.Errorf("Decimal %v Round %d = %v, want %v",
+				test.i, test.nd, s, test.down)
+		}
+		d = NewDecimal(test.i)
+		d.RoundUp(test.nd)
+		s = d.String()
+		if s != test.up {
+			t.Errorf("Decimal %v RoundUp %d = %v, want %v",
+				test.i, test.nd, s, test.up)
+		}
+	}
+}
+
+type roundIntTest struct {
+	i     uint64
+	shift int
+	int   uint64
+}
+
+var roundinttests = []roundIntTest{
+	{0, 100, 0},
+	{512, -8, 2},
+	{513, -8, 2},
+	{640, -8, 2},
+	{641, -8, 3},
+	{384, -8, 2},
+	{385, -8, 2},
+	{383, -8, 1},
+	{1, 100, 1<<64 - 1},
+	{1000, 0, 1000},
+}
+
+func TestDecimalRoundedInteger(t *testing.T) {
+	for i := 0; i < len(roundinttests); i++ {
+		test := roundinttests[i]
+		d := NewDecimal(test.i)
+		d.Shift(test.shift)
+		int := d.RoundedInteger()
+		if int != test.int {
+			t.Errorf("Decimal %v >> %v RoundedInteger = %v, want %v",
+				test.i, test.shift, int, test.int)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/extfloat.go b/third_party/gofrontend/libgo/go/strconv/extfloat.go
new file mode 100644
index 0000000..bed8b16
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/extfloat.go
@@ -0,0 +1,668 @@
+// 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.
+
+package strconv
+
+// An extFloat represents an extended floating-point number, with more
+// precision than a float64. It does not try to save bits: the
+// number represented by the structure is mant*(2^exp), with a negative
+// sign if neg is true.
+type extFloat struct {
+	mant uint64
+	exp  int
+	neg  bool
+}
+
+// Powers of ten taken from double-conversion library.
+// http://code.google.com/p/double-conversion/
+const (
+	firstPowerOfTen = -348
+	stepPowerOfTen  = 8
+)
+
+var smallPowersOfTen = [...]extFloat{
+	{1 << 63, -63, false},        // 1
+	{0xa << 60, -60, false},      // 1e1
+	{0x64 << 57, -57, false},     // 1e2
+	{0x3e8 << 54, -54, false},    // 1e3
+	{0x2710 << 50, -50, false},   // 1e4
+	{0x186a0 << 47, -47, false},  // 1e5
+	{0xf4240 << 44, -44, false},  // 1e6
+	{0x989680 << 40, -40, false}, // 1e7
+}
+
+var powersOfTen = [...]extFloat{
+	{0xfa8fd5a0081c0288, -1220, false}, // 10^-348
+	{0xbaaee17fa23ebf76, -1193, false}, // 10^-340
+	{0x8b16fb203055ac76, -1166, false}, // 10^-332
+	{0xcf42894a5dce35ea, -1140, false}, // 10^-324
+	{0x9a6bb0aa55653b2d, -1113, false}, // 10^-316
+	{0xe61acf033d1a45df, -1087, false}, // 10^-308
+	{0xab70fe17c79ac6ca, -1060, false}, // 10^-300
+	{0xff77b1fcbebcdc4f, -1034, false}, // 10^-292
+	{0xbe5691ef416bd60c, -1007, false}, // 10^-284
+	{0x8dd01fad907ffc3c, -980, false},  // 10^-276
+	{0xd3515c2831559a83, -954, false},  // 10^-268
+	{0x9d71ac8fada6c9b5, -927, false},  // 10^-260
+	{0xea9c227723ee8bcb, -901, false},  // 10^-252
+	{0xaecc49914078536d, -874, false},  // 10^-244
+	{0x823c12795db6ce57, -847, false},  // 10^-236
+	{0xc21094364dfb5637, -821, false},  // 10^-228
+	{0x9096ea6f3848984f, -794, false},  // 10^-220
+	{0xd77485cb25823ac7, -768, false},  // 10^-212
+	{0xa086cfcd97bf97f4, -741, false},  // 10^-204
+	{0xef340a98172aace5, -715, false},  // 10^-196
+	{0xb23867fb2a35b28e, -688, false},  // 10^-188
+	{0x84c8d4dfd2c63f3b, -661, false},  // 10^-180
+	{0xc5dd44271ad3cdba, -635, false},  // 10^-172
+	{0x936b9fcebb25c996, -608, false},  // 10^-164
+	{0xdbac6c247d62a584, -582, false},  // 10^-156
+	{0xa3ab66580d5fdaf6, -555, false},  // 10^-148
+	{0xf3e2f893dec3f126, -529, false},  // 10^-140
+	{0xb5b5ada8aaff80b8, -502, false},  // 10^-132
+	{0x87625f056c7c4a8b, -475, false},  // 10^-124
+	{0xc9bcff6034c13053, -449, false},  // 10^-116
+	{0x964e858c91ba2655, -422, false},  // 10^-108
+	{0xdff9772470297ebd, -396, false},  // 10^-100
+	{0xa6dfbd9fb8e5b88f, -369, false},  // 10^-92
+	{0xf8a95fcf88747d94, -343, false},  // 10^-84
+	{0xb94470938fa89bcf, -316, false},  // 10^-76
+	{0x8a08f0f8bf0f156b, -289, false},  // 10^-68
+	{0xcdb02555653131b6, -263, false},  // 10^-60
+	{0x993fe2c6d07b7fac, -236, false},  // 10^-52
+	{0xe45c10c42a2b3b06, -210, false},  // 10^-44
+	{0xaa242499697392d3, -183, false},  // 10^-36
+	{0xfd87b5f28300ca0e, -157, false},  // 10^-28
+	{0xbce5086492111aeb, -130, false},  // 10^-20
+	{0x8cbccc096f5088cc, -103, false},  // 10^-12
+	{0xd1b71758e219652c, -77, false},   // 10^-4
+	{0x9c40000000000000, -50, false},   // 10^4
+	{0xe8d4a51000000000, -24, false},   // 10^12
+	{0xad78ebc5ac620000, 3, false},     // 10^20
+	{0x813f3978f8940984, 30, false},    // 10^28
+	{0xc097ce7bc90715b3, 56, false},    // 10^36
+	{0x8f7e32ce7bea5c70, 83, false},    // 10^44
+	{0xd5d238a4abe98068, 109, false},   // 10^52
+	{0x9f4f2726179a2245, 136, false},   // 10^60
+	{0xed63a231d4c4fb27, 162, false},   // 10^68
+	{0xb0de65388cc8ada8, 189, false},   // 10^76
+	{0x83c7088e1aab65db, 216, false},   // 10^84
+	{0xc45d1df942711d9a, 242, false},   // 10^92
+	{0x924d692ca61be758, 269, false},   // 10^100
+	{0xda01ee641a708dea, 295, false},   // 10^108
+	{0xa26da3999aef774a, 322, false},   // 10^116
+	{0xf209787bb47d6b85, 348, false},   // 10^124
+	{0xb454e4a179dd1877, 375, false},   // 10^132
+	{0x865b86925b9bc5c2, 402, false},   // 10^140
+	{0xc83553c5c8965d3d, 428, false},   // 10^148
+	{0x952ab45cfa97a0b3, 455, false},   // 10^156
+	{0xde469fbd99a05fe3, 481, false},   // 10^164
+	{0xa59bc234db398c25, 508, false},   // 10^172
+	{0xf6c69a72a3989f5c, 534, false},   // 10^180
+	{0xb7dcbf5354e9bece, 561, false},   // 10^188
+	{0x88fcf317f22241e2, 588, false},   // 10^196
+	{0xcc20ce9bd35c78a5, 614, false},   // 10^204
+	{0x98165af37b2153df, 641, false},   // 10^212
+	{0xe2a0b5dc971f303a, 667, false},   // 10^220
+	{0xa8d9d1535ce3b396, 694, false},   // 10^228
+	{0xfb9b7cd9a4a7443c, 720, false},   // 10^236
+	{0xbb764c4ca7a44410, 747, false},   // 10^244
+	{0x8bab8eefb6409c1a, 774, false},   // 10^252
+	{0xd01fef10a657842c, 800, false},   // 10^260
+	{0x9b10a4e5e9913129, 827, false},   // 10^268
+	{0xe7109bfba19c0c9d, 853, false},   // 10^276
+	{0xac2820d9623bf429, 880, false},   // 10^284
+	{0x80444b5e7aa7cf85, 907, false},   // 10^292
+	{0xbf21e44003acdd2d, 933, false},   // 10^300
+	{0x8e679c2f5e44ff8f, 960, false},   // 10^308
+	{0xd433179d9c8cb841, 986, false},   // 10^316
+	{0x9e19db92b4e31ba9, 1013, false},  // 10^324
+	{0xeb96bf6ebadf77d9, 1039, false},  // 10^332
+	{0xaf87023b9bf0ee6b, 1066, false},  // 10^340
+}
+
+// floatBits returns the bits of the float64 that best approximates
+// the extFloat passed as receiver. Overflow is set to true if
+// the resulting float64 is ±Inf.
+func (f *extFloat) floatBits(flt *floatInfo) (bits uint64, overflow bool) {
+	f.Normalize()
+
+	exp := f.exp + 63
+
+	// Exponent too small.
+	if exp < flt.bias+1 {
+		n := flt.bias + 1 - exp
+		f.mant >>= uint(n)
+		exp += n
+	}
+
+	// Extract 1+flt.mantbits bits from the 64-bit mantissa.
+	mant := f.mant >> (63 - flt.mantbits)
+	if f.mant&(1<<(62-flt.mantbits)) != 0 {
+		// Round up.
+		mant += 1
+	}
+
+	// Rounding might have added a bit; shift down.
+	if mant == 2<<flt.mantbits {
+		mant >>= 1
+		exp++
+	}
+
+	// Infinities.
+	if exp-flt.bias >= 1<<flt.expbits-1 {
+		// ±Inf
+		mant = 0
+		exp = 1<<flt.expbits - 1 + flt.bias
+		overflow = true
+	} else if mant&(1<<flt.mantbits) == 0 {
+		// Denormalized?
+		exp = flt.bias
+	}
+	// Assemble bits.
+	bits = mant & (uint64(1)<<flt.mantbits - 1)
+	bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
+	if f.neg {
+		bits |= 1 << (flt.mantbits + flt.expbits)
+	}
+	return
+}
+
+// AssignComputeBounds sets f to the floating point value
+// defined by mant, exp and precision given by flt. It returns
+// lower, upper such that any number in the closed interval
+// [lower, upper] is converted back to the same floating point number.
+func (f *extFloat) AssignComputeBounds(mant uint64, exp int, neg bool, flt *floatInfo) (lower, upper extFloat) {
+	f.mant = mant
+	f.exp = exp - int(flt.mantbits)
+	f.neg = neg
+	if f.exp <= 0 && mant == (mant>>uint(-f.exp))<<uint(-f.exp) {
+		// An exact integer
+		f.mant >>= uint(-f.exp)
+		f.exp = 0
+		return *f, *f
+	}
+	expBiased := exp - flt.bias
+
+	upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg}
+	if mant != 1<<flt.mantbits || expBiased == 1 {
+		lower = extFloat{mant: 2*f.mant - 1, exp: f.exp - 1, neg: f.neg}
+	} else {
+		lower = extFloat{mant: 4*f.mant - 1, exp: f.exp - 2, neg: f.neg}
+	}
+	return
+}
+
+// Normalize normalizes f so that the highest bit of the mantissa is
+// set, and returns the number by which the mantissa was left-shifted.
+func (f *extFloat) Normalize() (shift uint) {
+	mant, exp := f.mant, f.exp
+	if mant == 0 {
+		return 0
+	}
+	if mant>>(64-32) == 0 {
+		mant <<= 32
+		exp -= 32
+	}
+	if mant>>(64-16) == 0 {
+		mant <<= 16
+		exp -= 16
+	}
+	if mant>>(64-8) == 0 {
+		mant <<= 8
+		exp -= 8
+	}
+	if mant>>(64-4) == 0 {
+		mant <<= 4
+		exp -= 4
+	}
+	if mant>>(64-2) == 0 {
+		mant <<= 2
+		exp -= 2
+	}
+	if mant>>(64-1) == 0 {
+		mant <<= 1
+		exp -= 1
+	}
+	shift = uint(f.exp - exp)
+	f.mant, f.exp = mant, exp
+	return
+}
+
+// Multiply sets f to the product f*g: the result is correctly rounded,
+// but not normalized.
+func (f *extFloat) Multiply(g extFloat) {
+	fhi, flo := f.mant>>32, uint64(uint32(f.mant))
+	ghi, glo := g.mant>>32, uint64(uint32(g.mant))
+
+	// Cross products.
+	cross1 := fhi * glo
+	cross2 := flo * ghi
+
+	// f.mant*g.mant is fhi*ghi << 64 + (cross1+cross2) << 32 + flo*glo
+	f.mant = fhi*ghi + (cross1 >> 32) + (cross2 >> 32)
+	rem := uint64(uint32(cross1)) + uint64(uint32(cross2)) + ((flo * glo) >> 32)
+	// Round up.
+	rem += (1 << 31)
+
+	f.mant += (rem >> 32)
+	f.exp = f.exp + g.exp + 64
+}
+
+var uint64pow10 = [...]uint64{
+	1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+	1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+}
+
+// AssignDecimal sets f to an approximate value mantissa*10^exp. It
+// returns true if the value represented by f is guaranteed to be the
+// best approximation of d after being rounded to a float64 or
+// float32 depending on flt.
+func (f *extFloat) AssignDecimal(mantissa uint64, exp10 int, neg bool, trunc bool, flt *floatInfo) (ok bool) {
+	const uint64digits = 19
+	const errorscale = 8
+	errors := 0 // An upper bound for error, computed in errorscale*ulp.
+	if trunc {
+		// the decimal number was truncated.
+		errors += errorscale / 2
+	}
+
+	f.mant = mantissa
+	f.exp = 0
+	f.neg = neg
+
+	// Multiply by powers of ten.
+	i := (exp10 - firstPowerOfTen) / stepPowerOfTen
+	if exp10 < firstPowerOfTen || i >= len(powersOfTen) {
+		return false
+	}
+	adjExp := (exp10 - firstPowerOfTen) % stepPowerOfTen
+
+	// We multiply by exp%step
+	if adjExp < uint64digits && mantissa < uint64pow10[uint64digits-adjExp] {
+		// We can multiply the mantissa exactly.
+		f.mant *= uint64pow10[adjExp]
+		f.Normalize()
+	} else {
+		f.Normalize()
+		f.Multiply(smallPowersOfTen[adjExp])
+		errors += errorscale / 2
+	}
+
+	// We multiply by 10 to the exp - exp%step.
+	f.Multiply(powersOfTen[i])
+	if errors > 0 {
+		errors += 1
+	}
+	errors += errorscale / 2
+
+	// Normalize
+	shift := f.Normalize()
+	errors <<= shift
+
+	// Now f is a good approximation of the decimal.
+	// Check whether the error is too large: that is, if the mantissa
+	// is perturbated by the error, the resulting float64 will change.
+	// The 64 bits mantissa is 1 + 52 bits for float64 + 11 extra bits.
+	//
+	// In many cases the approximation will be good enough.
+	denormalExp := flt.bias - 63
+	var extrabits uint
+	if f.exp <= denormalExp {
+		// f.mant * 2^f.exp is smaller than 2^(flt.bias+1).
+		extrabits = uint(63 - flt.mantbits + 1 + uint(denormalExp-f.exp))
+	} else {
+		extrabits = uint(63 - flt.mantbits)
+	}
+
+	halfway := uint64(1) << (extrabits - 1)
+	mant_extra := f.mant & (1<<extrabits - 1)
+
+	// Do a signed comparison here! If the error estimate could make
+	// the mantissa round differently for the conversion to double,
+	// then we can't give a definite answer.
+	if int64(halfway)-int64(errors) < int64(mant_extra) &&
+		int64(mant_extra) < int64(halfway)+int64(errors) {
+		return false
+	}
+	return true
+}
+
+// Frexp10 is an analogue of math.Frexp for decimal powers. It scales
+// f by an approximate power of ten 10^-exp, and returns exp10, so
+// that f*10^exp10 has the same value as the old f, up to an ulp,
+// as well as the index of 10^-exp in the powersOfTen table.
+func (f *extFloat) frexp10() (exp10, index int) {
+	// The constants expMin and expMax constrain the final value of the
+	// binary exponent of f. We want a small integral part in the result
+	// because finding digits of an integer requires divisions, whereas
+	// digits of the fractional part can be found by repeatedly multiplying
+	// by 10.
+	const expMin = -60
+	const expMax = -32
+	// Find power of ten such that x * 10^n has a binary exponent
+	// between expMin and expMax.
+	approxExp10 := ((expMin+expMax)/2 - f.exp) * 28 / 93 // log(10)/log(2) is close to 93/28.
+	i := (approxExp10 - firstPowerOfTen) / stepPowerOfTen
+Loop:
+	for {
+		exp := f.exp + powersOfTen[i].exp + 64
+		switch {
+		case exp < expMin:
+			i++
+		case exp > expMax:
+			i--
+		default:
+			break Loop
+		}
+	}
+	// Apply the desired decimal shift on f. It will have exponent
+	// in the desired range. This is multiplication by 10^-exp10.
+	f.Multiply(powersOfTen[i])
+
+	return -(firstPowerOfTen + i*stepPowerOfTen), i
+}
+
+// frexp10Many applies a common shift by a power of ten to a, b, c.
+func frexp10Many(a, b, c *extFloat) (exp10 int) {
+	exp10, i := c.frexp10()
+	a.Multiply(powersOfTen[i])
+	b.Multiply(powersOfTen[i])
+	return
+}
+
+// FixedDecimal stores in d the first n significant digits
+// of the decimal representation of f. It returns false
+// if it cannot be sure of the answer.
+func (f *extFloat) FixedDecimal(d *decimalSlice, n int) bool {
+	if f.mant == 0 {
+		d.nd = 0
+		d.dp = 0
+		d.neg = f.neg
+		return true
+	}
+	if n == 0 {
+		panic("strconv: internal error: extFloat.FixedDecimal called with n == 0")
+	}
+	// Multiply by an appropriate power of ten to have a reasonable
+	// number to process.
+	f.Normalize()
+	exp10, _ := f.frexp10()
+
+	shift := uint(-f.exp)
+	integer := uint32(f.mant >> shift)
+	fraction := f.mant - (uint64(integer) << shift)
+	ε := uint64(1) // ε is the uncertainty we have on the mantissa of f.
+
+	// Write exactly n digits to d.
+	needed := n        // how many digits are left to write.
+	integerDigits := 0 // the number of decimal digits of integer.
+	pow10 := uint64(1) // the power of ten by which f was scaled.
+	for i, pow := 0, uint64(1); i < 20; i++ {
+		if pow > uint64(integer) {
+			integerDigits = i
+			break
+		}
+		pow *= 10
+	}
+	rest := integer
+	if integerDigits > needed {
+		// the integral part is already large, trim the last digits.
+		pow10 = uint64pow10[integerDigits-needed]
+		integer /= uint32(pow10)
+		rest -= integer * uint32(pow10)
+	} else {
+		rest = 0
+	}
+
+	// Write the digits of integer: the digits of rest are omitted.
+	var buf [32]byte
+	pos := len(buf)
+	for v := integer; v > 0; {
+		v1 := v / 10
+		v -= 10 * v1
+		pos--
+		buf[pos] = byte(v + '0')
+		v = v1
+	}
+	for i := pos; i < len(buf); i++ {
+		d.d[i-pos] = buf[i]
+	}
+	nd := len(buf) - pos
+	d.nd = nd
+	d.dp = integerDigits + exp10
+	needed -= nd
+
+	if needed > 0 {
+		if rest != 0 || pow10 != 1 {
+			panic("strconv: internal error, rest != 0 but needed > 0")
+		}
+		// Emit digits for the fractional part. Each time, 10*fraction
+		// fits in a uint64 without overflow.
+		for needed > 0 {
+			fraction *= 10
+			ε *= 10 // the uncertainty scales as we multiply by ten.
+			if 2*ε > 1<<shift {
+				// the error is so large it could modify which digit to write, abort.
+				return false
+			}
+			digit := fraction >> shift
+			d.d[nd] = byte(digit + '0')
+			fraction -= digit << shift
+			nd++
+			needed--
+		}
+		d.nd = nd
+	}
+
+	// We have written a truncation of f (a numerator / 10^d.dp). The remaining part
+	// can be interpreted as a small number (< 1) to be added to the last digit of the
+	// numerator.
+	//
+	// If rest > 0, the amount is:
+	//    (rest<<shift | fraction) / (pow10 << shift)
+	//    fraction being known with a ±ε uncertainty.
+	//    The fact that n > 0 guarantees that pow10 << shift does not overflow a uint64.
+	//
+	// If rest = 0, pow10 == 1 and the amount is
+	//    fraction / (1 << shift)
+	//    fraction being known with a ±ε uncertainty.
+	//
+	// We pass this information to the rounding routine for adjustment.
+
+	ok := adjustLastDigitFixed(d, uint64(rest)<<shift|fraction, pow10, shift, ε)
+	if !ok {
+		return false
+	}
+	// Trim trailing zeros.
+	for i := d.nd - 1; i >= 0; i-- {
+		if d.d[i] != '0' {
+			d.nd = i + 1
+			break
+		}
+	}
+	return true
+}
+
+// adjustLastDigitFixed assumes d contains the representation of the integral part
+// of some number, whose fractional part is num / (den << shift). The numerator
+// num is only known up to an uncertainty of size ε, assumed to be less than
+// (den << shift)/2.
+//
+// It will increase the last digit by one to account for correct rounding, typically
+// when the fractional part is greater than 1/2, and will return false if ε is such
+// that no correct answer can be given.
+func adjustLastDigitFixed(d *decimalSlice, num, den uint64, shift uint, ε uint64) bool {
+	if num > den<<shift {
+		panic("strconv: num > den<<shift in adjustLastDigitFixed")
+	}
+	if 2*ε > den<<shift {
+		panic("strconv: ε > (den<<shift)/2")
+	}
+	if 2*(num+ε) < den<<shift {
+		return true
+	}
+	if 2*(num-ε) > den<<shift {
+		// increment d by 1.
+		i := d.nd - 1
+		for ; i >= 0; i-- {
+			if d.d[i] == '9' {
+				d.nd--
+			} else {
+				break
+			}
+		}
+		if i < 0 {
+			d.d[0] = '1'
+			d.nd = 1
+			d.dp++
+		} else {
+			d.d[i]++
+		}
+		return true
+	}
+	return false
+}
+
+// ShortestDecimal stores in d the shortest decimal representation of f
+// which belongs to the open interval (lower, upper), where f is supposed
+// to lie. It returns false whenever the result is unsure. The implementation
+// uses the Grisu3 algorithm.
+func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool {
+	if f.mant == 0 {
+		d.nd = 0
+		d.dp = 0
+		d.neg = f.neg
+		return true
+	}
+	if f.exp == 0 && *lower == *f && *lower == *upper {
+		// an exact integer.
+		var buf [24]byte
+		n := len(buf) - 1
+		for v := f.mant; v > 0; {
+			v1 := v / 10
+			v -= 10 * v1
+			buf[n] = byte(v + '0')
+			n--
+			v = v1
+		}
+		nd := len(buf) - n - 1
+		for i := 0; i < nd; i++ {
+			d.d[i] = buf[n+1+i]
+		}
+		d.nd, d.dp = nd, nd
+		for d.nd > 0 && d.d[d.nd-1] == '0' {
+			d.nd--
+		}
+		if d.nd == 0 {
+			d.dp = 0
+		}
+		d.neg = f.neg
+		return true
+	}
+	upper.Normalize()
+	// Uniformize exponents.
+	if f.exp > upper.exp {
+		f.mant <<= uint(f.exp - upper.exp)
+		f.exp = upper.exp
+	}
+	if lower.exp > upper.exp {
+		lower.mant <<= uint(lower.exp - upper.exp)
+		lower.exp = upper.exp
+	}
+
+	exp10 := frexp10Many(lower, f, upper)
+	// Take a safety margin due to rounding in frexp10Many, but we lose precision.
+	upper.mant++
+	lower.mant--
+
+	// The shortest representation of f is either rounded up or down, but
+	// in any case, it is a truncation of upper.
+	shift := uint(-upper.exp)
+	integer := uint32(upper.mant >> shift)
+	fraction := upper.mant - (uint64(integer) << shift)
+
+	// How far we can go down from upper until the result is wrong.
+	allowance := upper.mant - lower.mant
+	// How far we should go to get a very precise result.
+	targetDiff := upper.mant - f.mant
+
+	// Count integral digits: there are at most 10.
+	var integerDigits int
+	for i, pow := 0, uint64(1); i < 20; i++ {
+		if pow > uint64(integer) {
+			integerDigits = i
+			break
+		}
+		pow *= 10
+	}
+	for i := 0; i < integerDigits; i++ {
+		pow := uint64pow10[integerDigits-i-1]
+		digit := integer / uint32(pow)
+		d.d[i] = byte(digit + '0')
+		integer -= digit * uint32(pow)
+		// evaluate whether we should stop.
+		if currentDiff := uint64(integer)<<shift + fraction; currentDiff < allowance {
+			d.nd = i + 1
+			d.dp = integerDigits + exp10
+			d.neg = f.neg
+			// Sometimes allowance is so large the last digit might need to be
+			// decremented to get closer to f.
+			return adjustLastDigit(d, currentDiff, targetDiff, allowance, pow<<shift, 2)
+		}
+	}
+	d.nd = integerDigits
+	d.dp = d.nd + exp10
+	d.neg = f.neg
+
+	// Compute digits of the fractional part. At each step fraction does not
+	// overflow. The choice of minExp implies that fraction is less than 2^60.
+	var digit int
+	multiplier := uint64(1)
+	for {
+		fraction *= 10
+		multiplier *= 10
+		digit = int(fraction >> shift)
+		d.d[d.nd] = byte(digit + '0')
+		d.nd++
+		fraction -= uint64(digit) << shift
+		if fraction < allowance*multiplier {
+			// We are in the admissible range. Note that if allowance is about to
+			// overflow, that is, allowance > 2^64/10, the condition is automatically
+			// true due to the limited range of fraction.
+			return adjustLastDigit(d,
+				fraction, targetDiff*multiplier, allowance*multiplier,
+				1<<shift, multiplier*2)
+		}
+	}
+}
+
+// adjustLastDigit modifies d = x-currentDiff*ε, to get closest to
+// d = x-targetDiff*ε, without becoming smaller than x-maxDiff*ε.
+// It assumes that a decimal digit is worth ulpDecimal*ε, and that
+// all data is known with a error estimate of ulpBinary*ε.
+func adjustLastDigit(d *decimalSlice, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool {
+	if ulpDecimal < 2*ulpBinary {
+		// Approximation is too wide.
+		return false
+	}
+	for currentDiff+ulpDecimal/2+ulpBinary < targetDiff {
+		d.d[d.nd-1]--
+		currentDiff += ulpDecimal
+	}
+	if currentDiff+ulpDecimal <= targetDiff+ulpDecimal/2+ulpBinary {
+		// we have two choices, and don't know what to do.
+		return false
+	}
+	if currentDiff < ulpBinary || currentDiff > maxDiff-ulpBinary {
+		// we went too far
+		return false
+	}
+	if d.nd == 1 && d.d[0] == '0' {
+		// the number has actually reached zero.
+		d.nd = 0
+		d.dp = 0
+	}
+	return true
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/fp_test.go b/third_party/gofrontend/libgo/go/strconv/fp_test.go
new file mode 100644
index 0000000..6de2f8b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/fp_test.go
@@ -0,0 +1,144 @@
+// 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 strconv_test
+
+import (
+	"bufio"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func pow2(i int) float64 {
+	switch {
+	case i < 0:
+		return 1 / pow2(-i)
+	case i == 0:
+		return 1
+	case i == 1:
+		return 2
+	}
+	return pow2(i/2) * pow2(i-i/2)
+}
+
+// Wrapper around strconv.ParseFloat(x, 64).  Handles dddddp+ddd (binary exponent)
+// itself, passes the rest on to strconv.ParseFloat.
+func myatof64(s string) (f float64, ok bool) {
+	a := strings.SplitN(s, "p", 2)
+	if len(a) == 2 {
+		n, err := strconv.ParseInt(a[0], 10, 64)
+		if err != nil {
+			return 0, false
+		}
+		e, err1 := strconv.Atoi(a[1])
+		if err1 != nil {
+			println("bad e", a[1])
+			return 0, false
+		}
+		v := float64(n)
+		// We expect that v*pow2(e) fits in a float64,
+		// but pow2(e) by itself may not.  Be careful.
+		if e <= -1000 {
+			v *= pow2(-1000)
+			e += 1000
+			for e < 0 {
+				v /= 2
+				e++
+			}
+			return v, true
+		}
+		if e >= 1000 {
+			v *= pow2(1000)
+			e -= 1000
+			for e > 0 {
+				v *= 2
+				e--
+			}
+			return v, true
+		}
+		return v * pow2(e), true
+	}
+	f1, err := strconv.ParseFloat(s, 64)
+	if err != nil {
+		return 0, false
+	}
+	return f1, true
+}
+
+// Wrapper around strconv.ParseFloat(x, 32).  Handles dddddp+ddd (binary exponent)
+// itself, passes the rest on to strconv.ParseFloat.
+func myatof32(s string) (f float32, ok bool) {
+	a := strings.SplitN(s, "p", 2)
+	if len(a) == 2 {
+		n, err := strconv.Atoi(a[0])
+		if err != nil {
+			println("bad n", a[0])
+			return 0, false
+		}
+		e, err1 := strconv.Atoi(a[1])
+		if err1 != nil {
+			println("bad p", a[1])
+			return 0, false
+		}
+		return float32(float64(n) * pow2(e)), true
+	}
+	f64, err1 := strconv.ParseFloat(s, 32)
+	f1 := float32(f64)
+	if err1 != nil {
+		return 0, false
+	}
+	return f1, true
+}
+
+func TestFp(t *testing.T) {
+	f, err := os.Open("testdata/testfp.txt")
+	if err != nil {
+		t.Fatal("testfp: open testdata/testfp.txt:", err)
+	}
+	defer f.Close()
+
+	s := bufio.NewScanner(f)
+
+	for lineno := 1; s.Scan(); lineno++ {
+		line := s.Text()
+		if len(line) == 0 || line[0] == '#' {
+			continue
+		}
+		a := strings.Split(line, " ")
+		if len(a) != 4 {
+			t.Error("testdata/testfp.txt:", lineno, ": wrong field count")
+			continue
+		}
+		var s string
+		var v float64
+		switch a[0] {
+		case "float64":
+			var ok bool
+			v, ok = myatof64(a[2])
+			if !ok {
+				t.Error("testdata/testfp.txt:", lineno, ": cannot atof64 ", a[2])
+				continue
+			}
+			s = fmt.Sprintf(a[1], v)
+		case "float32":
+			v1, ok := myatof32(a[2])
+			if !ok {
+				t.Error("testdata/testfp.txt:", lineno, ": cannot atof32 ", a[2])
+				continue
+			}
+			s = fmt.Sprintf(a[1], v1)
+			v = float64(v1)
+		}
+		if s != a[3] {
+			t.Error("testdata/testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ",
+				"want ", a[3], " got ", s)
+		}
+	}
+	if s.Err() != nil {
+		t.Fatal("testfp: read testdata/testfp.txt: ", s.Err())
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/ftoa.go b/third_party/gofrontend/libgo/go/strconv/ftoa.go
new file mode 100644
index 0000000..1a9c41b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/ftoa.go
@@ -0,0 +1,475 @@
+// 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.
+
+// Binary to decimal floating point conversion.
+// Algorithm:
+//   1) store mantissa in multiprecision decimal
+//   2) shift decimal by exponent
+//   3) read digits out & format
+
+package strconv
+
+import "math"
+
+// TODO: move elsewhere?
+type floatInfo struct {
+	mantbits uint
+	expbits  uint
+	bias     int
+}
+
+var float32info = floatInfo{23, 8, -127}
+var float64info = floatInfo{52, 11, -1023}
+
+// FormatFloat converts the floating-point number f to a string,
+// according to the format fmt and precision prec.  It rounds the
+// result assuming that the original was obtained from a floating-point
+// value of bitSize bits (32 for float32, 64 for float64).
+//
+// The format fmt is one of
+// 'b' (-ddddp±ddd, a binary exponent),
+// 'e' (-d.dddde±dd, a decimal exponent),
+// 'E' (-d.ddddE±dd, a decimal exponent),
+// 'f' (-ddd.dddd, no exponent),
+// 'g' ('e' for large exponents, 'f' otherwise), or
+// 'G' ('E' for large exponents, 'f' otherwise).
+//
+// The precision prec controls the number of digits
+// (excluding the exponent) printed by the 'e', 'E', 'f', 'g', and 'G' formats.
+// For 'e', 'E', and 'f' it is the number of digits after the decimal point.
+// For 'g' and 'G' it is the total number of digits.
+// The special precision -1 uses the smallest number of digits
+// necessary such that ParseFloat will return f exactly.
+func FormatFloat(f float64, fmt byte, prec, bitSize int) string {
+	return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize))
+}
+
+// AppendFloat appends the string form of the floating-point number f,
+// as generated by FormatFloat, to dst and returns the extended buffer.
+func AppendFloat(dst []byte, f float64, fmt byte, prec int, bitSize int) []byte {
+	return genericFtoa(dst, f, fmt, prec, bitSize)
+}
+
+func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
+	var bits uint64
+	var flt *floatInfo
+	switch bitSize {
+	case 32:
+		bits = uint64(math.Float32bits(float32(val)))
+		flt = &float32info
+	case 64:
+		bits = math.Float64bits(val)
+		flt = &float64info
+	default:
+		panic("strconv: illegal AppendFloat/FormatFloat bitSize")
+	}
+
+	neg := bits>>(flt.expbits+flt.mantbits) != 0
+	exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
+	mant := bits & (uint64(1)<<flt.mantbits - 1)
+
+	switch exp {
+	case 1<<flt.expbits - 1:
+		// Inf, NaN
+		var s string
+		switch {
+		case mant != 0:
+			s = "NaN"
+		case neg:
+			s = "-Inf"
+		default:
+			s = "+Inf"
+		}
+		return append(dst, s...)
+
+	case 0:
+		// denormalized
+		exp++
+
+	default:
+		// add implicit top bit
+		mant |= uint64(1) << flt.mantbits
+	}
+	exp += flt.bias
+
+	// Pick off easy binary format.
+	if fmt == 'b' {
+		return fmtB(dst, neg, mant, exp, flt)
+	}
+
+	if !optimize {
+		return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
+	}
+
+	var digs decimalSlice
+	ok := false
+	// Negative precision means "only as much as needed to be exact."
+	shortest := prec < 0
+	if shortest {
+		// Try Grisu3 algorithm.
+		f := new(extFloat)
+		lower, upper := f.AssignComputeBounds(mant, exp, neg, flt)
+		var buf [32]byte
+		digs.d = buf[:]
+		ok = f.ShortestDecimal(&digs, &lower, &upper)
+		if !ok {
+			return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
+		}
+		// Precision for shortest representation mode.
+		switch fmt {
+		case 'e', 'E':
+			prec = digs.nd - 1
+		case 'f':
+			prec = max(digs.nd-digs.dp, 0)
+		case 'g', 'G':
+			prec = digs.nd
+		}
+	} else if fmt != 'f' {
+		// Fixed number of digits.
+		digits := prec
+		switch fmt {
+		case 'e', 'E':
+			digits++
+		case 'g', 'G':
+			if prec == 0 {
+				prec = 1
+			}
+			digits = prec
+		}
+		if digits <= 15 {
+			// try fast algorithm when the number of digits is reasonable.
+			var buf [24]byte
+			digs.d = buf[:]
+			f := extFloat{mant, exp - int(flt.mantbits), neg}
+			ok = f.FixedDecimal(&digs, digits)
+		}
+	}
+	if !ok {
+		return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
+	}
+	return formatDigits(dst, shortest, neg, digs, prec, fmt)
+}
+
+// bigFtoa uses multiprecision computations to format a float.
+func bigFtoa(dst []byte, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {
+	d := new(decimal)
+	d.Assign(mant)
+	d.Shift(exp - int(flt.mantbits))
+	var digs decimalSlice
+	shortest := prec < 0
+	if shortest {
+		roundShortest(d, mant, exp, flt)
+		digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
+		// Precision for shortest representation mode.
+		switch fmt {
+		case 'e', 'E':
+			prec = digs.nd - 1
+		case 'f':
+			prec = max(digs.nd-digs.dp, 0)
+		case 'g', 'G':
+			prec = digs.nd
+		}
+	} else {
+		// Round appropriately.
+		switch fmt {
+		case 'e', 'E':
+			d.Round(prec + 1)
+		case 'f':
+			d.Round(d.dp + prec)
+		case 'g', 'G':
+			if prec == 0 {
+				prec = 1
+			}
+			d.Round(prec)
+		}
+		digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
+	}
+	return formatDigits(dst, shortest, neg, digs, prec, fmt)
+}
+
+func formatDigits(dst []byte, shortest bool, neg bool, digs decimalSlice, prec int, fmt byte) []byte {
+	switch fmt {
+	case 'e', 'E':
+		return fmtE(dst, neg, digs, prec, fmt)
+	case 'f':
+		return fmtF(dst, neg, digs, prec)
+	case 'g', 'G':
+		// trailing fractional zeros in 'e' form will be trimmed.
+		eprec := prec
+		if eprec > digs.nd && digs.nd >= digs.dp {
+			eprec = digs.nd
+		}
+		// %e is used if the exponent from the conversion
+		// is less than -4 or greater than or equal to the precision.
+		// if precision was the shortest possible, use precision 6 for this decision.
+		if shortest {
+			eprec = 6
+		}
+		exp := digs.dp - 1
+		if exp < -4 || exp >= eprec {
+			if prec > digs.nd {
+				prec = digs.nd
+			}
+			return fmtE(dst, neg, digs, prec-1, fmt+'e'-'g')
+		}
+		if prec > digs.dp {
+			prec = digs.nd
+		}
+		return fmtF(dst, neg, digs, max(prec-digs.dp, 0))
+	}
+
+	// unknown format
+	return append(dst, '%', fmt)
+}
+
+// Round d (= mant * 2^exp) to the shortest number of digits
+// that will let the original floating point value be precisely
+// reconstructed.  Size is original floating point size (64 or 32).
+func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
+	// If mantissa is zero, the number is zero; stop now.
+	if mant == 0 {
+		d.nd = 0
+		return
+	}
+
+	// Compute upper and lower such that any decimal number
+	// between upper and lower (possibly inclusive)
+	// will round to the original floating point number.
+
+	// We may see at once that the number is already shortest.
+	//
+	// Suppose d is not denormal, so that 2^exp <= d < 10^dp.
+	// The closest shorter number is at least 10^(dp-nd) away.
+	// The lower/upper bounds computed below are at distance
+	// at most 2^(exp-mantbits).
+	//
+	// So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits),
+	// or equivalently log2(10)*(dp-nd) > exp-mantbits.
+	// It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32).
+	minexp := flt.bias + 1 // minimum possible exponent
+	if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) {
+		// The number is already shortest.
+		return
+	}
+
+	// d = mant << (exp - mantbits)
+	// Next highest floating point number is mant+1 << exp-mantbits.
+	// Our upper bound is halfway between, mant*2+1 << exp-mantbits-1.
+	upper := new(decimal)
+	upper.Assign(mant*2 + 1)
+	upper.Shift(exp - int(flt.mantbits) - 1)
+
+	// d = mant << (exp - mantbits)
+	// Next lowest floating point number is mant-1 << exp-mantbits,
+	// unless mant-1 drops the significant bit and exp is not the minimum exp,
+	// in which case the next lowest is mant*2-1 << exp-mantbits-1.
+	// Either way, call it mantlo << explo-mantbits.
+	// Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1.
+	var mantlo uint64
+	var explo int
+	if mant > 1<<flt.mantbits || exp == minexp {
+		mantlo = mant - 1
+		explo = exp
+	} else {
+		mantlo = mant*2 - 1
+		explo = exp - 1
+	}
+	lower := new(decimal)
+	lower.Assign(mantlo*2 + 1)
+	lower.Shift(explo - int(flt.mantbits) - 1)
+
+	// The upper and lower bounds are possible outputs only if
+	// the original mantissa is even, so that IEEE round-to-even
+	// would round to the original mantissa and not the neighbors.
+	inclusive := mant%2 == 0
+
+	// Now we can figure out the minimum number of digits required.
+	// Walk along until d has distinguished itself from upper and lower.
+	for i := 0; i < d.nd; i++ {
+		var l, m, u byte // lower, middle, upper digits
+		if i < lower.nd {
+			l = lower.d[i]
+		} else {
+			l = '0'
+		}
+		m = d.d[i]
+		if i < upper.nd {
+			u = upper.d[i]
+		} else {
+			u = '0'
+		}
+
+		// Okay to round down (truncate) if lower has a different digit
+		// or if lower is inclusive and is exactly the result of rounding down.
+		okdown := l != m || (inclusive && l == m && i+1 == lower.nd)
+
+		// Okay to round up if upper has a different digit and
+		// either upper is inclusive or upper is bigger than the result of rounding up.
+		okup := m != u && (inclusive || m+1 < u || i+1 < upper.nd)
+
+		// If it's okay to do either, then round to the nearest one.
+		// If it's okay to do only one, do it.
+		switch {
+		case okdown && okup:
+			d.Round(i + 1)
+			return
+		case okdown:
+			d.RoundDown(i + 1)
+			return
+		case okup:
+			d.RoundUp(i + 1)
+			return
+		}
+	}
+}
+
+type decimalSlice struct {
+	d      []byte
+	nd, dp int
+	neg    bool
+}
+
+// %e: -d.ddddde±dd
+func fmtE(dst []byte, neg bool, d decimalSlice, prec int, fmt byte) []byte {
+	// sign
+	if neg {
+		dst = append(dst, '-')
+	}
+
+	// first digit
+	ch := byte('0')
+	if d.nd != 0 {
+		ch = d.d[0]
+	}
+	dst = append(dst, ch)
+
+	// .moredigits
+	if prec > 0 {
+		dst = append(dst, '.')
+		i := 1
+		m := d.nd + prec + 1 - max(d.nd, prec+1)
+		for i < m {
+			dst = append(dst, d.d[i])
+			i++
+		}
+		for i <= prec {
+			dst = append(dst, '0')
+			i++
+		}
+	}
+
+	// e±
+	dst = append(dst, fmt)
+	exp := d.dp - 1
+	if d.nd == 0 { // special case: 0 has exponent 0
+		exp = 0
+	}
+	if exp < 0 {
+		ch = '-'
+		exp = -exp
+	} else {
+		ch = '+'
+	}
+	dst = append(dst, ch)
+
+	// dddd
+	var buf [3]byte
+	i := len(buf)
+	for exp >= 10 {
+		i--
+		buf[i] = byte(exp%10 + '0')
+		exp /= 10
+	}
+	// exp < 10
+	i--
+	buf[i] = byte(exp + '0')
+
+	switch i {
+	case 0:
+		dst = append(dst, buf[0], buf[1], buf[2])
+	case 1:
+		dst = append(dst, buf[1], buf[2])
+	case 2:
+		// leading zeroes
+		dst = append(dst, '0', buf[2])
+	}
+	return dst
+}
+
+// %f: -ddddddd.ddddd
+func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte {
+	// sign
+	if neg {
+		dst = append(dst, '-')
+	}
+
+	// integer, padded with zeros as needed.
+	if d.dp > 0 {
+		var i int
+		for i = 0; i < d.dp && i < d.nd; i++ {
+			dst = append(dst, d.d[i])
+		}
+		for ; i < d.dp; i++ {
+			dst = append(dst, '0')
+		}
+	} else {
+		dst = append(dst, '0')
+	}
+
+	// fraction
+	if prec > 0 {
+		dst = append(dst, '.')
+		for i := 0; i < prec; i++ {
+			ch := byte('0')
+			if j := d.dp + i; 0 <= j && j < d.nd {
+				ch = d.d[j]
+			}
+			dst = append(dst, ch)
+		}
+	}
+
+	return dst
+}
+
+// %b: -ddddddddp+ddd
+func fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {
+	var buf [50]byte
+	w := len(buf)
+	exp -= int(flt.mantbits)
+	esign := byte('+')
+	if exp < 0 {
+		esign = '-'
+		exp = -exp
+	}
+	n := 0
+	for exp > 0 || n < 1 {
+		n++
+		w--
+		buf[w] = byte(exp%10 + '0')
+		exp /= 10
+	}
+	w--
+	buf[w] = esign
+	w--
+	buf[w] = 'p'
+	n = 0
+	for mant > 0 || n < 1 {
+		n++
+		w--
+		buf[w] = byte(mant%10 + '0')
+		mant /= 10
+	}
+	if neg {
+		w--
+		buf[w] = '-'
+	}
+	return append(dst, buf[w:]...)
+}
+
+func max(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/ftoa_test.go b/third_party/gofrontend/libgo/go/strconv/ftoa_test.go
new file mode 100644
index 0000000..39b8615
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/ftoa_test.go
@@ -0,0 +1,240 @@
+// 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 strconv_test
+
+import (
+	"math"
+	"math/rand"
+	. "strconv"
+	"testing"
+)
+
+type ftoaTest struct {
+	f    float64
+	fmt  byte
+	prec int
+	s    string
+}
+
+func fdiv(a, b float64) float64 { return a / b } // keep compiler in the dark
+
+const (
+	below1e23 = 99999999999999974834176
+	above1e23 = 100000000000000008388608
+)
+
+var ftoatests = []ftoaTest{
+	{1, 'e', 5, "1.00000e+00"},
+	{1, 'f', 5, "1.00000"},
+	{1, 'g', 5, "1"},
+	{1, 'g', -1, "1"},
+	{20, 'g', -1, "20"},
+	{1234567.8, 'g', -1, "1.2345678e+06"},
+	{200000, 'g', -1, "200000"},
+	{2000000, 'g', -1, "2e+06"},
+
+	// g conversion and zero suppression
+	{400, 'g', 2, "4e+02"},
+	{40, 'g', 2, "40"},
+	{4, 'g', 2, "4"},
+	{.4, 'g', 2, "0.4"},
+	{.04, 'g', 2, "0.04"},
+	{.004, 'g', 2, "0.004"},
+	{.0004, 'g', 2, "0.0004"},
+	{.00004, 'g', 2, "4e-05"},
+	{.000004, 'g', 2, "4e-06"},
+
+	{0, 'e', 5, "0.00000e+00"},
+	{0, 'f', 5, "0.00000"},
+	{0, 'g', 5, "0"},
+	{0, 'g', -1, "0"},
+
+	{-1, 'e', 5, "-1.00000e+00"},
+	{-1, 'f', 5, "-1.00000"},
+	{-1, 'g', 5, "-1"},
+	{-1, 'g', -1, "-1"},
+
+	{12, 'e', 5, "1.20000e+01"},
+	{12, 'f', 5, "12.00000"},
+	{12, 'g', 5, "12"},
+	{12, 'g', -1, "12"},
+
+	{123456700, 'e', 5, "1.23457e+08"},
+	{123456700, 'f', 5, "123456700.00000"},
+	{123456700, 'g', 5, "1.2346e+08"},
+	{123456700, 'g', -1, "1.234567e+08"},
+
+	{1.2345e6, 'e', 5, "1.23450e+06"},
+	{1.2345e6, 'f', 5, "1234500.00000"},
+	{1.2345e6, 'g', 5, "1.2345e+06"},
+
+	{1e23, 'e', 17, "9.99999999999999916e+22"},
+	{1e23, 'f', 17, "99999999999999991611392.00000000000000000"},
+	{1e23, 'g', 17, "9.9999999999999992e+22"},
+
+	{1e23, 'e', -1, "1e+23"},
+	{1e23, 'f', -1, "100000000000000000000000"},
+	{1e23, 'g', -1, "1e+23"},
+
+	{below1e23, 'e', 17, "9.99999999999999748e+22"},
+	{below1e23, 'f', 17, "99999999999999974834176.00000000000000000"},
+	{below1e23, 'g', 17, "9.9999999999999975e+22"},
+
+	{below1e23, 'e', -1, "9.999999999999997e+22"},
+	{below1e23, 'f', -1, "99999999999999970000000"},
+	{below1e23, 'g', -1, "9.999999999999997e+22"},
+
+	{above1e23, 'e', 17, "1.00000000000000008e+23"},
+	{above1e23, 'f', 17, "100000000000000008388608.00000000000000000"},
+	{above1e23, 'g', 17, "1.0000000000000001e+23"},
+
+	{above1e23, 'e', -1, "1.0000000000000001e+23"},
+	{above1e23, 'f', -1, "100000000000000010000000"},
+	{above1e23, 'g', -1, "1.0000000000000001e+23"},
+
+	{fdiv(5e-304, 1e20), 'g', -1, "5e-324"},
+	{fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"},
+
+	{32, 'g', -1, "32"},
+	{32, 'g', 0, "3e+01"},
+
+	{100, 'x', -1, "%x"},
+
+	{math.NaN(), 'g', -1, "NaN"},
+	{-math.NaN(), 'g', -1, "NaN"},
+	{math.Inf(0), 'g', -1, "+Inf"},
+	{math.Inf(-1), 'g', -1, "-Inf"},
+	{-math.Inf(0), 'g', -1, "-Inf"},
+
+	{-1, 'b', -1, "-4503599627370496p-52"},
+
+	// fixed bugs
+	{0.9, 'f', 1, "0.9"},
+	{0.09, 'f', 1, "0.1"},
+	{0.0999, 'f', 1, "0.1"},
+	{0.05, 'f', 1, "0.1"},
+	{0.05, 'f', 0, "0"},
+	{0.5, 'f', 1, "0.5"},
+	{0.5, 'f', 0, "0"},
+	{1.5, 'f', 0, "2"},
+
+	// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
+	{2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
+	// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
+	{2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
+
+	// Issue 2625.
+	{383260575764816448, 'f', 0, "383260575764816448"},
+	{383260575764816448, 'g', -1, "3.8326057576481645e+17"},
+}
+
+func TestFtoa(t *testing.T) {
+	for i := 0; i < len(ftoatests); i++ {
+		test := &ftoatests[i]
+		s := FormatFloat(test.f, test.fmt, test.prec, 64)
+		if s != test.s {
+			t.Error("testN=64", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
+		}
+		x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 64)
+		if string(x) != "abc"+test.s {
+			t.Error("AppendFloat testN=64", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x))
+		}
+		if float64(float32(test.f)) == test.f && test.fmt != 'b' {
+			s := FormatFloat(test.f, test.fmt, test.prec, 32)
+			if s != test.s {
+				t.Error("testN=32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
+			}
+			x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 32)
+			if string(x) != "abc"+test.s {
+				t.Error("AppendFloat testN=32", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x))
+			}
+		}
+	}
+}
+
+func TestFtoaRandom(t *testing.T) {
+	N := int(1e4)
+	if testing.Short() {
+		N = 100
+	}
+	t.Logf("testing %d random numbers with fast and slow FormatFloat", N)
+	for i := 0; i < N; i++ {
+		bits := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
+		x := math.Float64frombits(bits)
+
+		shortFast := FormatFloat(x, 'g', -1, 64)
+		SetOptimize(false)
+		shortSlow := FormatFloat(x, 'g', -1, 64)
+		SetOptimize(true)
+		if shortSlow != shortFast {
+			t.Errorf("%b printed as %s, want %s", x, shortFast, shortSlow)
+		}
+
+		prec := rand.Intn(12) + 5
+		shortFast = FormatFloat(x, 'e', prec, 64)
+		SetOptimize(false)
+		shortSlow = FormatFloat(x, 'e', prec, 64)
+		SetOptimize(true)
+		if shortSlow != shortFast {
+			t.Errorf("%b printed as %s, want %s", x, shortFast, shortSlow)
+		}
+	}
+}
+
+func BenchmarkFormatFloatDecimal(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		FormatFloat(33909, 'g', -1, 64)
+	}
+}
+
+func BenchmarkFormatFloat(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		FormatFloat(339.7784, 'g', -1, 64)
+	}
+}
+
+func BenchmarkFormatFloatExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		FormatFloat(-5.09e75, 'g', -1, 64)
+	}
+}
+
+func BenchmarkFormatFloatNegExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		FormatFloat(-5.11e-95, 'g', -1, 64)
+	}
+}
+
+func BenchmarkFormatFloatBig(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		FormatFloat(123456789123456789123456789, 'g', -1, 64)
+	}
+}
+
+func benchmarkAppendFloat(b *testing.B, f float64, fmt byte, prec, bitSize int) {
+	dst := make([]byte, 30)
+	for i := 0; i < b.N; i++ {
+		AppendFloat(dst[:0], f, fmt, prec, bitSize)
+	}
+}
+
+func BenchmarkAppendFloatDecimal(b *testing.B) { benchmarkAppendFloat(b, 33909, 'g', -1, 64) }
+func BenchmarkAppendFloat(b *testing.B)        { benchmarkAppendFloat(b, 339.7784, 'g', -1, 64) }
+func BenchmarkAppendFloatExp(b *testing.B)     { benchmarkAppendFloat(b, -5.09e75, 'g', -1, 64) }
+func BenchmarkAppendFloatNegExp(b *testing.B)  { benchmarkAppendFloat(b, -5.11e-95, 'g', -1, 64) }
+func BenchmarkAppendFloatBig(b *testing.B) {
+	benchmarkAppendFloat(b, 123456789123456789123456789, 'g', -1, 64)
+}
+
+func BenchmarkAppendFloat32Integer(b *testing.B)       { benchmarkAppendFloat(b, 33909, 'g', -1, 32) }
+func BenchmarkAppendFloat32ExactFraction(b *testing.B) { benchmarkAppendFloat(b, 3.375, 'g', -1, 32) }
+func BenchmarkAppendFloat32Point(b *testing.B)         { benchmarkAppendFloat(b, 339.7784, 'g', -1, 32) }
+func BenchmarkAppendFloat32Exp(b *testing.B)           { benchmarkAppendFloat(b, -5.09e25, 'g', -1, 32) }
+func BenchmarkAppendFloat32NegExp(b *testing.B)        { benchmarkAppendFloat(b, -5.11e-25, 'g', -1, 32) }
+
+func BenchmarkAppendFloat64Fixed1(b *testing.B) { benchmarkAppendFloat(b, 123456, 'e', 3, 64) }
+func BenchmarkAppendFloat64Fixed2(b *testing.B) { benchmarkAppendFloat(b, 123.456, 'e', 3, 64) }
+func BenchmarkAppendFloat64Fixed3(b *testing.B) { benchmarkAppendFloat(b, 1.23456e+78, 'e', 3, 64) }
+func BenchmarkAppendFloat64Fixed4(b *testing.B) { benchmarkAppendFloat(b, 1.23456e-78, 'e', 3, 64) }
diff --git a/third_party/gofrontend/libgo/go/strconv/internal_test.go b/third_party/gofrontend/libgo/go/strconv/internal_test.go
new file mode 100644
index 0000000..d0fa80e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/internal_test.go
@@ -0,0 +1,19 @@
+// 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.
+
+// export access to strconv internals for tests
+
+package strconv
+
+func NewDecimal(i uint64) *decimal {
+	d := new(decimal)
+	d.Assign(i)
+	return d
+}
+
+func SetOptimize(b bool) bool {
+	old := optimize
+	optimize = b
+	return old
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/isprint.go b/third_party/gofrontend/libgo/go/strconv/isprint.go
new file mode 100644
index 0000000..91f1795
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/isprint.go
@@ -0,0 +1,562 @@
+// Copyright 2013 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.
+
+// DO NOT EDIT.  GENERATED BY
+//     go run makeisprint.go >x && mv x isprint.go
+
+package strconv
+
+// (470+136+60)*2 + (218)*4 = 2204 bytes
+
+var isPrint16 = []uint16{
+	0x0020, 0x007e,
+	0x00a1, 0x0377,
+	0x037a, 0x037e,
+	0x0384, 0x0527,
+	0x0531, 0x0556,
+	0x0559, 0x058a,
+	0x058f, 0x05c7,
+	0x05d0, 0x05ea,
+	0x05f0, 0x05f4,
+	0x0606, 0x061b,
+	0x061e, 0x070d,
+	0x0710, 0x074a,
+	0x074d, 0x07b1,
+	0x07c0, 0x07fa,
+	0x0800, 0x082d,
+	0x0830, 0x085b,
+	0x085e, 0x085e,
+	0x08a0, 0x08ac,
+	0x08e4, 0x098c,
+	0x098f, 0x0990,
+	0x0993, 0x09b2,
+	0x09b6, 0x09b9,
+	0x09bc, 0x09c4,
+	0x09c7, 0x09c8,
+	0x09cb, 0x09ce,
+	0x09d7, 0x09d7,
+	0x09dc, 0x09e3,
+	0x09e6, 0x09fb,
+	0x0a01, 0x0a0a,
+	0x0a0f, 0x0a10,
+	0x0a13, 0x0a39,
+	0x0a3c, 0x0a42,
+	0x0a47, 0x0a48,
+	0x0a4b, 0x0a4d,
+	0x0a51, 0x0a51,
+	0x0a59, 0x0a5e,
+	0x0a66, 0x0a75,
+	0x0a81, 0x0ab9,
+	0x0abc, 0x0acd,
+	0x0ad0, 0x0ad0,
+	0x0ae0, 0x0ae3,
+	0x0ae6, 0x0af1,
+	0x0b01, 0x0b0c,
+	0x0b0f, 0x0b10,
+	0x0b13, 0x0b39,
+	0x0b3c, 0x0b44,
+	0x0b47, 0x0b48,
+	0x0b4b, 0x0b4d,
+	0x0b56, 0x0b57,
+	0x0b5c, 0x0b63,
+	0x0b66, 0x0b77,
+	0x0b82, 0x0b8a,
+	0x0b8e, 0x0b95,
+	0x0b99, 0x0b9f,
+	0x0ba3, 0x0ba4,
+	0x0ba8, 0x0baa,
+	0x0bae, 0x0bb9,
+	0x0bbe, 0x0bc2,
+	0x0bc6, 0x0bcd,
+	0x0bd0, 0x0bd0,
+	0x0bd7, 0x0bd7,
+	0x0be6, 0x0bfa,
+	0x0c01, 0x0c39,
+	0x0c3d, 0x0c4d,
+	0x0c55, 0x0c59,
+	0x0c60, 0x0c63,
+	0x0c66, 0x0c6f,
+	0x0c78, 0x0c7f,
+	0x0c82, 0x0cb9,
+	0x0cbc, 0x0ccd,
+	0x0cd5, 0x0cd6,
+	0x0cde, 0x0ce3,
+	0x0ce6, 0x0cf2,
+	0x0d02, 0x0d3a,
+	0x0d3d, 0x0d4e,
+	0x0d57, 0x0d57,
+	0x0d60, 0x0d63,
+	0x0d66, 0x0d75,
+	0x0d79, 0x0d7f,
+	0x0d82, 0x0d96,
+	0x0d9a, 0x0dbd,
+	0x0dc0, 0x0dc6,
+	0x0dca, 0x0dca,
+	0x0dcf, 0x0ddf,
+	0x0df2, 0x0df4,
+	0x0e01, 0x0e3a,
+	0x0e3f, 0x0e5b,
+	0x0e81, 0x0e84,
+	0x0e87, 0x0e8a,
+	0x0e8d, 0x0e8d,
+	0x0e94, 0x0ea7,
+	0x0eaa, 0x0ebd,
+	0x0ec0, 0x0ecd,
+	0x0ed0, 0x0ed9,
+	0x0edc, 0x0edf,
+	0x0f00, 0x0f6c,
+	0x0f71, 0x0fda,
+	0x1000, 0x10c7,
+	0x10cd, 0x10cd,
+	0x10d0, 0x124d,
+	0x1250, 0x125d,
+	0x1260, 0x128d,
+	0x1290, 0x12b5,
+	0x12b8, 0x12c5,
+	0x12c8, 0x1315,
+	0x1318, 0x135a,
+	0x135d, 0x137c,
+	0x1380, 0x1399,
+	0x13a0, 0x13f4,
+	0x1400, 0x169c,
+	0x16a0, 0x16f0,
+	0x1700, 0x1714,
+	0x1720, 0x1736,
+	0x1740, 0x1753,
+	0x1760, 0x1773,
+	0x1780, 0x17dd,
+	0x17e0, 0x17e9,
+	0x17f0, 0x17f9,
+	0x1800, 0x180d,
+	0x1810, 0x1819,
+	0x1820, 0x1877,
+	0x1880, 0x18aa,
+	0x18b0, 0x18f5,
+	0x1900, 0x191c,
+	0x1920, 0x192b,
+	0x1930, 0x193b,
+	0x1940, 0x1940,
+	0x1944, 0x196d,
+	0x1970, 0x1974,
+	0x1980, 0x19ab,
+	0x19b0, 0x19c9,
+	0x19d0, 0x19da,
+	0x19de, 0x1a1b,
+	0x1a1e, 0x1a7c,
+	0x1a7f, 0x1a89,
+	0x1a90, 0x1a99,
+	0x1aa0, 0x1aad,
+	0x1b00, 0x1b4b,
+	0x1b50, 0x1b7c,
+	0x1b80, 0x1bf3,
+	0x1bfc, 0x1c37,
+	0x1c3b, 0x1c49,
+	0x1c4d, 0x1c7f,
+	0x1cc0, 0x1cc7,
+	0x1cd0, 0x1cf6,
+	0x1d00, 0x1de6,
+	0x1dfc, 0x1f15,
+	0x1f18, 0x1f1d,
+	0x1f20, 0x1f45,
+	0x1f48, 0x1f4d,
+	0x1f50, 0x1f7d,
+	0x1f80, 0x1fd3,
+	0x1fd6, 0x1fef,
+	0x1ff2, 0x1ffe,
+	0x2010, 0x2027,
+	0x2030, 0x205e,
+	0x2070, 0x2071,
+	0x2074, 0x209c,
+	0x20a0, 0x20ba,
+	0x20d0, 0x20f0,
+	0x2100, 0x2189,
+	0x2190, 0x23f3,
+	0x2400, 0x2426,
+	0x2440, 0x244a,
+	0x2460, 0x2b4c,
+	0x2b50, 0x2b59,
+	0x2c00, 0x2cf3,
+	0x2cf9, 0x2d27,
+	0x2d2d, 0x2d2d,
+	0x2d30, 0x2d67,
+	0x2d6f, 0x2d70,
+	0x2d7f, 0x2d96,
+	0x2da0, 0x2e3b,
+	0x2e80, 0x2ef3,
+	0x2f00, 0x2fd5,
+	0x2ff0, 0x2ffb,
+	0x3001, 0x3096,
+	0x3099, 0x30ff,
+	0x3105, 0x312d,
+	0x3131, 0x31ba,
+	0x31c0, 0x31e3,
+	0x31f0, 0x4db5,
+	0x4dc0, 0x9fcc,
+	0xa000, 0xa48c,
+	0xa490, 0xa4c6,
+	0xa4d0, 0xa62b,
+	0xa640, 0xa697,
+	0xa69f, 0xa6f7,
+	0xa700, 0xa793,
+	0xa7a0, 0xa7aa,
+	0xa7f8, 0xa82b,
+	0xa830, 0xa839,
+	0xa840, 0xa877,
+	0xa880, 0xa8c4,
+	0xa8ce, 0xa8d9,
+	0xa8e0, 0xa8fb,
+	0xa900, 0xa953,
+	0xa95f, 0xa97c,
+	0xa980, 0xa9d9,
+	0xa9de, 0xa9df,
+	0xaa00, 0xaa36,
+	0xaa40, 0xaa4d,
+	0xaa50, 0xaa59,
+	0xaa5c, 0xaa7b,
+	0xaa80, 0xaac2,
+	0xaadb, 0xaaf6,
+	0xab01, 0xab06,
+	0xab09, 0xab0e,
+	0xab11, 0xab16,
+	0xab20, 0xab2e,
+	0xabc0, 0xabed,
+	0xabf0, 0xabf9,
+	0xac00, 0xd7a3,
+	0xd7b0, 0xd7c6,
+	0xd7cb, 0xd7fb,
+	0xf900, 0xfa6d,
+	0xfa70, 0xfad9,
+	0xfb00, 0xfb06,
+	0xfb13, 0xfb17,
+	0xfb1d, 0xfbc1,
+	0xfbd3, 0xfd3f,
+	0xfd50, 0xfd8f,
+	0xfd92, 0xfdc7,
+	0xfdf0, 0xfdfd,
+	0xfe00, 0xfe19,
+	0xfe20, 0xfe26,
+	0xfe30, 0xfe6b,
+	0xfe70, 0xfefc,
+	0xff01, 0xffbe,
+	0xffc2, 0xffc7,
+	0xffca, 0xffcf,
+	0xffd2, 0xffd7,
+	0xffda, 0xffdc,
+	0xffe0, 0xffee,
+	0xfffc, 0xfffd,
+}
+
+var isNotPrint16 = []uint16{
+	0x00ad,
+	0x038b,
+	0x038d,
+	0x03a2,
+	0x0560,
+	0x0588,
+	0x0590,
+	0x06dd,
+	0x083f,
+	0x08a1,
+	0x08ff,
+	0x0978,
+	0x0980,
+	0x0984,
+	0x09a9,
+	0x09b1,
+	0x09de,
+	0x0a04,
+	0x0a29,
+	0x0a31,
+	0x0a34,
+	0x0a37,
+	0x0a3d,
+	0x0a5d,
+	0x0a84,
+	0x0a8e,
+	0x0a92,
+	0x0aa9,
+	0x0ab1,
+	0x0ab4,
+	0x0ac6,
+	0x0aca,
+	0x0b04,
+	0x0b29,
+	0x0b31,
+	0x0b34,
+	0x0b5e,
+	0x0b84,
+	0x0b91,
+	0x0b9b,
+	0x0b9d,
+	0x0bc9,
+	0x0c04,
+	0x0c0d,
+	0x0c11,
+	0x0c29,
+	0x0c34,
+	0x0c45,
+	0x0c49,
+	0x0c57,
+	0x0c84,
+	0x0c8d,
+	0x0c91,
+	0x0ca9,
+	0x0cb4,
+	0x0cc5,
+	0x0cc9,
+	0x0cdf,
+	0x0cf0,
+	0x0d04,
+	0x0d0d,
+	0x0d11,
+	0x0d45,
+	0x0d49,
+	0x0d84,
+	0x0db2,
+	0x0dbc,
+	0x0dd5,
+	0x0dd7,
+	0x0e83,
+	0x0e89,
+	0x0e98,
+	0x0ea0,
+	0x0ea4,
+	0x0ea6,
+	0x0eac,
+	0x0eba,
+	0x0ec5,
+	0x0ec7,
+	0x0f48,
+	0x0f98,
+	0x0fbd,
+	0x0fcd,
+	0x10c6,
+	0x1249,
+	0x1257,
+	0x1259,
+	0x1289,
+	0x12b1,
+	0x12bf,
+	0x12c1,
+	0x12d7,
+	0x1311,
+	0x1680,
+	0x170d,
+	0x176d,
+	0x1771,
+	0x1a5f,
+	0x1f58,
+	0x1f5a,
+	0x1f5c,
+	0x1f5e,
+	0x1fb5,
+	0x1fc5,
+	0x1fdc,
+	0x1ff5,
+	0x208f,
+	0x2700,
+	0x2c2f,
+	0x2c5f,
+	0x2d26,
+	0x2da7,
+	0x2daf,
+	0x2db7,
+	0x2dbf,
+	0x2dc7,
+	0x2dcf,
+	0x2dd7,
+	0x2ddf,
+	0x2e9a,
+	0x3040,
+	0x318f,
+	0x321f,
+	0x32ff,
+	0xa78f,
+	0xa9ce,
+	0xab27,
+	0xfb37,
+	0xfb3d,
+	0xfb3f,
+	0xfb42,
+	0xfb45,
+	0xfe53,
+	0xfe67,
+	0xfe75,
+	0xffe7,
+}
+
+var isPrint32 = []uint32{
+	0x010000, 0x01004d,
+	0x010050, 0x01005d,
+	0x010080, 0x0100fa,
+	0x010100, 0x010102,
+	0x010107, 0x010133,
+	0x010137, 0x01018a,
+	0x010190, 0x01019b,
+	0x0101d0, 0x0101fd,
+	0x010280, 0x01029c,
+	0x0102a0, 0x0102d0,
+	0x010300, 0x010323,
+	0x010330, 0x01034a,
+	0x010380, 0x0103c3,
+	0x0103c8, 0x0103d5,
+	0x010400, 0x01049d,
+	0x0104a0, 0x0104a9,
+	0x010800, 0x010805,
+	0x010808, 0x010838,
+	0x01083c, 0x01083c,
+	0x01083f, 0x01085f,
+	0x010900, 0x01091b,
+	0x01091f, 0x010939,
+	0x01093f, 0x01093f,
+	0x010980, 0x0109b7,
+	0x0109be, 0x0109bf,
+	0x010a00, 0x010a06,
+	0x010a0c, 0x010a33,
+	0x010a38, 0x010a3a,
+	0x010a3f, 0x010a47,
+	0x010a50, 0x010a58,
+	0x010a60, 0x010a7f,
+	0x010b00, 0x010b35,
+	0x010b39, 0x010b55,
+	0x010b58, 0x010b72,
+	0x010b78, 0x010b7f,
+	0x010c00, 0x010c48,
+	0x010e60, 0x010e7e,
+	0x011000, 0x01104d,
+	0x011052, 0x01106f,
+	0x011080, 0x0110c1,
+	0x0110d0, 0x0110e8,
+	0x0110f0, 0x0110f9,
+	0x011100, 0x011143,
+	0x011180, 0x0111c8,
+	0x0111d0, 0x0111d9,
+	0x011680, 0x0116b7,
+	0x0116c0, 0x0116c9,
+	0x012000, 0x01236e,
+	0x012400, 0x012462,
+	0x012470, 0x012473,
+	0x013000, 0x01342e,
+	0x016800, 0x016a38,
+	0x016f00, 0x016f44,
+	0x016f50, 0x016f7e,
+	0x016f8f, 0x016f9f,
+	0x01b000, 0x01b001,
+	0x01d000, 0x01d0f5,
+	0x01d100, 0x01d126,
+	0x01d129, 0x01d172,
+	0x01d17b, 0x01d1dd,
+	0x01d200, 0x01d245,
+	0x01d300, 0x01d356,
+	0x01d360, 0x01d371,
+	0x01d400, 0x01d49f,
+	0x01d4a2, 0x01d4a2,
+	0x01d4a5, 0x01d4a6,
+	0x01d4a9, 0x01d50a,
+	0x01d50d, 0x01d546,
+	0x01d54a, 0x01d6a5,
+	0x01d6a8, 0x01d7cb,
+	0x01d7ce, 0x01d7ff,
+	0x01ee00, 0x01ee24,
+	0x01ee27, 0x01ee3b,
+	0x01ee42, 0x01ee42,
+	0x01ee47, 0x01ee54,
+	0x01ee57, 0x01ee64,
+	0x01ee67, 0x01ee9b,
+	0x01eea1, 0x01eebb,
+	0x01eef0, 0x01eef1,
+	0x01f000, 0x01f02b,
+	0x01f030, 0x01f093,
+	0x01f0a0, 0x01f0ae,
+	0x01f0b1, 0x01f0be,
+	0x01f0c1, 0x01f0df,
+	0x01f100, 0x01f10a,
+	0x01f110, 0x01f16b,
+	0x01f170, 0x01f19a,
+	0x01f1e6, 0x01f202,
+	0x01f210, 0x01f23a,
+	0x01f240, 0x01f248,
+	0x01f250, 0x01f251,
+	0x01f300, 0x01f320,
+	0x01f330, 0x01f37c,
+	0x01f380, 0x01f393,
+	0x01f3a0, 0x01f3ca,
+	0x01f3e0, 0x01f3f0,
+	0x01f400, 0x01f4fc,
+	0x01f500, 0x01f53d,
+	0x01f540, 0x01f543,
+	0x01f550, 0x01f567,
+	0x01f5fb, 0x01f640,
+	0x01f645, 0x01f64f,
+	0x01f680, 0x01f6c5,
+	0x01f700, 0x01f773,
+	0x020000, 0x02a6d6,
+	0x02a700, 0x02b734,
+	0x02b740, 0x02b81d,
+	0x02f800, 0x02fa1d,
+	0x0e0100, 0x0e01ef,
+}
+
+var isNotPrint32 = []uint16{ // add 0x10000 to each entry
+	0x000c,
+	0x0027,
+	0x003b,
+	0x003e,
+	0x031f,
+	0x039e,
+	0x0809,
+	0x0836,
+	0x0856,
+	0x0a04,
+	0x0a14,
+	0x0a18,
+	0x10bd,
+	0x1135,
+	0xd455,
+	0xd49d,
+	0xd4ad,
+	0xd4ba,
+	0xd4bc,
+	0xd4c4,
+	0xd506,
+	0xd515,
+	0xd51d,
+	0xd53a,
+	0xd53f,
+	0xd545,
+	0xd551,
+	0xee04,
+	0xee20,
+	0xee23,
+	0xee28,
+	0xee33,
+	0xee38,
+	0xee3a,
+	0xee48,
+	0xee4a,
+	0xee4c,
+	0xee50,
+	0xee53,
+	0xee58,
+	0xee5a,
+	0xee5c,
+	0xee5e,
+	0xee60,
+	0xee63,
+	0xee6b,
+	0xee73,
+	0xee78,
+	0xee7d,
+	0xee7f,
+	0xee8a,
+	0xeea4,
+	0xeeaa,
+	0xf0d0,
+	0xf12f,
+	0xf336,
+	0xf3c5,
+	0xf43f,
+	0xf441,
+	0xf4f8,
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/itoa.go b/third_party/gofrontend/libgo/go/strconv/itoa.go
new file mode 100644
index 0000000..67f17d8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/itoa.go
@@ -0,0 +1,131 @@
+// 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 strconv
+
+// FormatUint returns the string representation of i in the given base,
+// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
+// for digit values >= 10.
+func FormatUint(i uint64, base int) string {
+	_, s := formatBits(nil, i, base, false, false)
+	return s
+}
+
+// FormatInt returns the string representation of i in the given base,
+// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
+// for digit values >= 10.
+func FormatInt(i int64, base int) string {
+	_, s := formatBits(nil, uint64(i), base, i < 0, false)
+	return s
+}
+
+// Itoa is shorthand for FormatInt(i, 10).
+func Itoa(i int) string {
+	return FormatInt(int64(i), 10)
+}
+
+// AppendInt appends the string form of the integer i,
+// as generated by FormatInt, to dst and returns the extended buffer.
+func AppendInt(dst []byte, i int64, base int) []byte {
+	dst, _ = formatBits(dst, uint64(i), base, i < 0, true)
+	return dst
+}
+
+// AppendUint appends the string form of the unsigned integer i,
+// as generated by FormatUint, to dst and returns the extended buffer.
+func AppendUint(dst []byte, i uint64, base int) []byte {
+	dst, _ = formatBits(dst, i, base, false, true)
+	return dst
+}
+
+const (
+	digits   = "0123456789abcdefghijklmnopqrstuvwxyz"
+	digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
+	digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
+)
+
+var shifts = [len(digits) + 1]uint{
+	1 << 1: 1,
+	1 << 2: 2,
+	1 << 3: 3,
+	1 << 4: 4,
+	1 << 5: 5,
+}
+
+// formatBits computes the string representation of u in the given base.
+// If neg is set, u is treated as negative int64 value. If append_ is
+// set, the string is appended to dst and the resulting byte slice is
+// returned as the first result value; otherwise the string is returned
+// as the second result value.
+//
+func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) {
+	if base < 2 || base > len(digits) {
+		panic("strconv: illegal AppendInt/FormatInt base")
+	}
+	// 2 <= base && base <= len(digits)
+
+	var a [64 + 1]byte // +1 for sign of 64bit value in base 2
+	i := len(a)
+
+	if neg {
+		u = -u
+	}
+
+	// convert bits
+	if base == 10 {
+		// common case: use constants for / and % because
+		// the compiler can optimize it into a multiply+shift,
+		// and unroll loop
+		for u >= 100 {
+			i -= 2
+			q := u / 100
+			j := uintptr(u - q*100)
+			a[i+1] = digits01[j]
+			a[i+0] = digits10[j]
+			u = q
+		}
+		if u >= 10 {
+			i--
+			q := u / 10
+			a[i] = digits[uintptr(u-q*10)]
+			u = q
+		}
+
+	} else if s := shifts[base]; s > 0 {
+		// base is power of 2: use shifts and masks instead of / and %
+		b := uint64(base)
+		m := uintptr(b) - 1 // == 1<<s - 1
+		for u >= b {
+			i--
+			a[i] = digits[uintptr(u)&m]
+			u >>= s
+		}
+
+	} else {
+		// general case
+		b := uint64(base)
+		for u >= b {
+			i--
+			a[i] = digits[uintptr(u%b)]
+			u /= b
+		}
+	}
+
+	// u < base
+	i--
+	a[i] = digits[uintptr(u)]
+
+	// add sign, if any
+	if neg {
+		i--
+		a[i] = '-'
+	}
+
+	if append_ {
+		d = append(dst, a[i:]...)
+		return
+	}
+	s = string(a[i:])
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/itoa_test.go b/third_party/gofrontend/libgo/go/strconv/itoa_test.go
new file mode 100644
index 0000000..e0213ae
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/itoa_test.go
@@ -0,0 +1,160 @@
+// 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 strconv_test
+
+import (
+	. "strconv"
+	"testing"
+)
+
+type itob64Test struct {
+	in   int64
+	base int
+	out  string
+}
+
+var itob64tests = []itob64Test{
+	{0, 10, "0"},
+	{1, 10, "1"},
+	{-1, 10, "-1"},
+	{12345678, 10, "12345678"},
+	{-987654321, 10, "-987654321"},
+	{1<<31 - 1, 10, "2147483647"},
+	{-1<<31 + 1, 10, "-2147483647"},
+	{1 << 31, 10, "2147483648"},
+	{-1 << 31, 10, "-2147483648"},
+	{1<<31 + 1, 10, "2147483649"},
+	{-1<<31 - 1, 10, "-2147483649"},
+	{1<<32 - 1, 10, "4294967295"},
+	{-1<<32 + 1, 10, "-4294967295"},
+	{1 << 32, 10, "4294967296"},
+	{-1 << 32, 10, "-4294967296"},
+	{1<<32 + 1, 10, "4294967297"},
+	{-1<<32 - 1, 10, "-4294967297"},
+	{1 << 50, 10, "1125899906842624"},
+	{1<<63 - 1, 10, "9223372036854775807"},
+	{-1<<63 + 1, 10, "-9223372036854775807"},
+	{-1 << 63, 10, "-9223372036854775808"},
+
+	{0, 2, "0"},
+	{10, 2, "1010"},
+	{-1, 2, "-1"},
+	{1 << 15, 2, "1000000000000000"},
+
+	{-8, 8, "-10"},
+	{057635436545, 8, "57635436545"},
+	{1 << 24, 8, "100000000"},
+
+	{16, 16, "10"},
+	{-0x123456789abcdef, 16, "-123456789abcdef"},
+	{1<<63 - 1, 16, "7fffffffffffffff"},
+	{1<<63 - 1, 2, "111111111111111111111111111111111111111111111111111111111111111"},
+
+	{16, 17, "g"},
+	{25, 25, "10"},
+	{(((((17*35+24)*35+21)*35+34)*35+12)*35+24)*35 + 32, 35, "holycow"},
+	{(((((17*36+24)*36+21)*36+34)*36+12)*36+24)*36 + 32, 36, "holycow"},
+}
+
+func TestItoa(t *testing.T) {
+	for _, test := range itob64tests {
+		s := FormatInt(test.in, test.base)
+		if s != test.out {
+			t.Errorf("FormatInt(%v, %v) = %v want %v",
+				test.in, test.base, s, test.out)
+		}
+		x := AppendInt([]byte("abc"), test.in, test.base)
+		if string(x) != "abc"+test.out {
+			t.Errorf("AppendInt(%q, %v, %v) = %q want %v",
+				"abc", test.in, test.base, x, test.out)
+		}
+
+		if test.in >= 0 {
+			s := FormatUint(uint64(test.in), test.base)
+			if s != test.out {
+				t.Errorf("FormatUint(%v, %v) = %v want %v",
+					test.in, test.base, s, test.out)
+			}
+			x := AppendUint(nil, uint64(test.in), test.base)
+			if string(x) != test.out {
+				t.Errorf("AppendUint(%q, %v, %v) = %q want %v",
+					"abc", uint64(test.in), test.base, x, test.out)
+			}
+		}
+
+		if test.base == 10 && int64(int(test.in)) == test.in {
+			s := Itoa(int(test.in))
+			if s != test.out {
+				t.Errorf("Itoa(%v) = %v want %v",
+					test.in, s, test.out)
+			}
+		}
+	}
+}
+
+type uitob64Test struct {
+	in   uint64
+	base int
+	out  string
+}
+
+var uitob64tests = []uitob64Test{
+	{1<<63 - 1, 10, "9223372036854775807"},
+	{1 << 63, 10, "9223372036854775808"},
+	{1<<63 + 1, 10, "9223372036854775809"},
+	{1<<64 - 2, 10, "18446744073709551614"},
+	{1<<64 - 1, 10, "18446744073709551615"},
+	{1<<64 - 1, 2, "1111111111111111111111111111111111111111111111111111111111111111"},
+}
+
+func TestUitoa(t *testing.T) {
+	for _, test := range uitob64tests {
+		s := FormatUint(test.in, test.base)
+		if s != test.out {
+			t.Errorf("FormatUint(%v, %v) = %v want %v",
+				test.in, test.base, s, test.out)
+		}
+		x := AppendUint([]byte("abc"), test.in, test.base)
+		if string(x) != "abc"+test.out {
+			t.Errorf("AppendUint(%q, %v, %v) = %q want %v",
+				"abc", test.in, test.base, x, test.out)
+		}
+
+	}
+}
+
+func BenchmarkFormatInt(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, test := range itob64tests {
+			FormatInt(test.in, test.base)
+		}
+	}
+}
+
+func BenchmarkAppendInt(b *testing.B) {
+	dst := make([]byte, 0, 30)
+	for i := 0; i < b.N; i++ {
+		for _, test := range itob64tests {
+			AppendInt(dst, test.in, test.base)
+		}
+	}
+}
+
+func BenchmarkFormatUint(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, test := range uitob64tests {
+			FormatUint(test.in, test.base)
+		}
+	}
+}
+
+func BenchmarkAppendUint(b *testing.B) {
+	dst := make([]byte, 0, 30)
+	for i := 0; i < b.N; i++ {
+		for _, test := range uitob64tests {
+			AppendUint(dst, test.in, test.base)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/makeisprint.go b/third_party/gofrontend/libgo/go/strconv/makeisprint.go
new file mode 100644
index 0000000..216159c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/makeisprint.go
@@ -0,0 +1,165 @@
+// 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.
+
+// +build ignore
+
+// makeisprint generates the tables for strconv's compact isPrint.
+package main
+
+import (
+	"fmt"
+	"os"
+	"unicode"
+)
+
+var (
+	range16  []uint16
+	except16 []uint16
+	range32  []uint32
+	except32 []uint32
+)
+
+// bsearch16 returns the smallest i such that a[i] >= x.
+// If there is no such i, bsearch16 returns len(a).
+func bsearch16(a []uint16, x uint16) int {
+	i, j := 0, len(a)
+	for i < j {
+		h := i + (j-i)/2
+		if a[h] < x {
+			i = h + 1
+		} else {
+			j = h
+		}
+	}
+	return i
+}
+
+// bsearch32 returns the smallest i such that a[i] >= x.
+// If there is no such i, bsearch32 returns len(a).
+func bsearch32(a []uint32, x uint32) int {
+	i, j := 0, len(a)
+	for i < j {
+		h := i + (j-i)/2
+		if a[h] < x {
+			i = h + 1
+		} else {
+			j = h
+		}
+	}
+	return i
+}
+
+func isPrint(r rune) bool {
+	// Same algorithm, either on uint16 or uint32 value.
+	// First, find first i such that rang[i] >= x.
+	// This is the index of either the start or end of a pair that might span x.
+	// The start is even (rang[i&^1]) and the end is odd (rang[i|1]).
+	// If we find x in a range, make sure x is not in exception list.
+
+	if 0 <= r && r < 1<<16 {
+		rr, rang, except := uint16(r), range16, except16
+		i := bsearch16(rang, rr)
+		if i >= len(rang) || rr < rang[i&^1] || rang[i|1] < rr {
+			return false
+		}
+		j := bsearch16(except, rr)
+		return j >= len(except) || except[j] != rr
+	}
+
+	rr, rang, except := uint32(r), range32, except32
+	i := bsearch32(rang, rr)
+	if i >= len(rang) || rr < rang[i&^1] || rang[i|1] < rr {
+		return false
+	}
+	j := bsearch32(except, rr)
+	return j >= len(except) || except[j] != rr
+}
+
+func scan(min, max rune) (rang, except []uint32) {
+	lo := rune(-1)
+	for i := min; ; i++ {
+		if (i > max || !unicode.IsPrint(i)) && lo >= 0 {
+			// End range, but avoid flip flop.
+			if i+1 <= max && unicode.IsPrint(i+1) {
+				except = append(except, uint32(i))
+				continue
+			}
+			rang = append(rang, uint32(lo), uint32(i-1))
+			lo = -1
+		}
+		if i > max {
+			break
+		}
+		if lo < 0 && unicode.IsPrint(i) {
+			lo = i
+		}
+	}
+	return
+}
+
+func to16(x []uint32) []uint16 {
+	var y []uint16
+	for _, v := range x {
+		if uint32(uint16(v)) != v {
+			panic("bad 32->16 conversion")
+		}
+		y = append(y, uint16(v))
+	}
+	return y
+}
+
+func main() {
+	rang, except := scan(0, 0xFFFF)
+	range16 = to16(rang)
+	except16 = to16(except)
+	range32, except32 = scan(0x10000, unicode.MaxRune)
+
+	for i := rune(0); i <= unicode.MaxRune; i++ {
+		if isPrint(i) != unicode.IsPrint(i) {
+			fmt.Fprintf(os.Stderr, "%U: isPrint=%v, want %v\n", i, isPrint(i), unicode.IsPrint(i))
+			return
+		}
+	}
+
+	fmt.Printf(`// Copyright 2013 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.` + "\n\n")
+	fmt.Printf("// DO NOT EDIT.  GENERATED BY\n")
+	fmt.Printf("//     go run makeisprint.go >x && mv x isprint.go\n\n")
+	fmt.Printf("package strconv\n\n")
+
+	fmt.Printf("// (%d+%d+%d)*2 + (%d)*4 = %d bytes\n\n",
+		len(range16), len(except16), len(except32),
+		len(range32),
+		(len(range16)+len(except16)+len(except32))*2+
+			(len(range32))*4)
+
+	fmt.Printf("var isPrint16 = []uint16{\n")
+	for i := 0; i < len(range16); i += 2 {
+		fmt.Printf("\t%#04x, %#04x,\n", range16[i], range16[i+1])
+	}
+	fmt.Printf("}\n\n")
+
+	fmt.Printf("var isNotPrint16 = []uint16{\n")
+	for _, r := range except16 {
+		fmt.Printf("\t%#04x,\n", r)
+	}
+	fmt.Printf("}\n\n")
+
+	fmt.Printf("var isPrint32 = []uint32{\n")
+	for i := 0; i < len(range32); i += 2 {
+		fmt.Printf("\t%#06x, %#06x,\n", range32[i], range32[i+1])
+	}
+	fmt.Printf("}\n\n")
+
+	fmt.Printf("var isNotPrint32 = []uint16{ // add 0x10000 to each entry\n")
+	for _, r := range except32 {
+		if r >= 0x20000 {
+			fmt.Fprintf(os.Stderr, "%U too big for isNotPrint32\n", r)
+			return
+		}
+		fmt.Printf("\t%#04x,\n", r-0x10000)
+	}
+	fmt.Printf("}\n")
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/quote.go b/third_party/gofrontend/libgo/go/strconv/quote.go
new file mode 100644
index 0000000..aded7e5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/quote.go
@@ -0,0 +1,443 @@
+// 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 strconv
+
+import (
+	"unicode/utf8"
+)
+
+const lowerhex = "0123456789abcdef"
+
+func quoteWith(s string, quote byte, ASCIIonly bool) string {
+	var runeTmp [utf8.UTFMax]byte
+	buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
+	buf = append(buf, quote)
+	for width := 0; len(s) > 0; s = s[width:] {
+		r := rune(s[0])
+		width = 1
+		if r >= utf8.RuneSelf {
+			r, width = utf8.DecodeRuneInString(s)
+		}
+		if width == 1 && r == utf8.RuneError {
+			buf = append(buf, `\x`...)
+			buf = append(buf, lowerhex[s[0]>>4])
+			buf = append(buf, lowerhex[s[0]&0xF])
+			continue
+		}
+		if r == rune(quote) || r == '\\' { // always backslashed
+			buf = append(buf, '\\')
+			buf = append(buf, byte(r))
+			continue
+		}
+		if ASCIIonly {
+			if r < utf8.RuneSelf && IsPrint(r) {
+				buf = append(buf, byte(r))
+				continue
+			}
+		} else if IsPrint(r) {
+			n := utf8.EncodeRune(runeTmp[:], r)
+			buf = append(buf, runeTmp[:n]...)
+			continue
+		}
+		switch r {
+		case '\a':
+			buf = append(buf, `\a`...)
+		case '\b':
+			buf = append(buf, `\b`...)
+		case '\f':
+			buf = append(buf, `\f`...)
+		case '\n':
+			buf = append(buf, `\n`...)
+		case '\r':
+			buf = append(buf, `\r`...)
+		case '\t':
+			buf = append(buf, `\t`...)
+		case '\v':
+			buf = append(buf, `\v`...)
+		default:
+			switch {
+			case r < ' ':
+				buf = append(buf, `\x`...)
+				buf = append(buf, lowerhex[s[0]>>4])
+				buf = append(buf, lowerhex[s[0]&0xF])
+			case r > utf8.MaxRune:
+				r = 0xFFFD
+				fallthrough
+			case r < 0x10000:
+				buf = append(buf, `\u`...)
+				for s := 12; s >= 0; s -= 4 {
+					buf = append(buf, lowerhex[r>>uint(s)&0xF])
+				}
+			default:
+				buf = append(buf, `\U`...)
+				for s := 28; s >= 0; s -= 4 {
+					buf = append(buf, lowerhex[r>>uint(s)&0xF])
+				}
+			}
+		}
+	}
+	buf = append(buf, quote)
+	return string(buf)
+
+}
+
+// Quote returns a double-quoted Go string literal representing s.  The
+// returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for
+// control characters and non-printable characters as defined by
+// IsPrint.
+func Quote(s string) string {
+	return quoteWith(s, '"', false)
+}
+
+// AppendQuote appends a double-quoted Go string literal representing s,
+// as generated by Quote, to dst and returns the extended buffer.
+func AppendQuote(dst []byte, s string) []byte {
+	return append(dst, Quote(s)...)
+}
+
+// QuoteToASCII returns a double-quoted Go string literal representing s.
+// The returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for
+// non-ASCII characters and non-printable characters as defined by IsPrint.
+func QuoteToASCII(s string) string {
+	return quoteWith(s, '"', true)
+}
+
+// AppendQuoteToASCII appends a double-quoted Go string literal representing s,
+// as generated by QuoteToASCII, to dst and returns the extended buffer.
+func AppendQuoteToASCII(dst []byte, s string) []byte {
+	return append(dst, QuoteToASCII(s)...)
+}
+
+// QuoteRune returns a single-quoted Go character literal representing the
+// rune.  The returned string uses Go escape sequences (\t, \n, \xFF, \u0100)
+// for control characters and non-printable characters as defined by IsPrint.
+func QuoteRune(r rune) string {
+	// TODO: avoid the allocation here.
+	return quoteWith(string(r), '\'', false)
+}
+
+// AppendQuoteRune appends a single-quoted Go character literal representing the rune,
+// as generated by QuoteRune, to dst and returns the extended buffer.
+func AppendQuoteRune(dst []byte, r rune) []byte {
+	return append(dst, QuoteRune(r)...)
+}
+
+// QuoteRuneToASCII returns a single-quoted Go character literal representing
+// the rune.  The returned string uses Go escape sequences (\t, \n, \xFF,
+// \u0100) for non-ASCII characters and non-printable characters as defined
+// by IsPrint.
+func QuoteRuneToASCII(r rune) string {
+	// TODO: avoid the allocation here.
+	return quoteWith(string(r), '\'', true)
+}
+
+// AppendQuoteRuneToASCII appends a single-quoted Go character literal representing the rune,
+// as generated by QuoteRuneToASCII, to dst and returns the extended buffer.
+func AppendQuoteRuneToASCII(dst []byte, r rune) []byte {
+	return append(dst, QuoteRuneToASCII(r)...)
+}
+
+// CanBackquote reports whether the string s can be represented
+// unchanged as a single-line backquoted string without control
+// characters other than space and tab.
+func CanBackquote(s string) bool {
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		if (c < ' ' && c != '\t') || c == '`' || c == '\u007F' {
+			return false
+		}
+	}
+	return true
+}
+
+func unhex(b byte) (v rune, ok bool) {
+	c := rune(b)
+	switch {
+	case '0' <= c && c <= '9':
+		return c - '0', true
+	case 'a' <= c && c <= 'f':
+		return c - 'a' + 10, true
+	case 'A' <= c && c <= 'F':
+		return c - 'A' + 10, true
+	}
+	return
+}
+
+// UnquoteChar decodes the first character or byte in the escaped string
+// or character literal represented by the string s.
+// It returns four values:
+//
+//	1) value, the decoded Unicode code point or byte value;
+//	2) multibyte, a boolean indicating whether the decoded character requires a multibyte UTF-8 representation;
+//	3) tail, the remainder of the string after the character; and
+//	4) an error that will be nil if the character is syntactically valid.
+//
+// The second argument, quote, specifies the type of literal being parsed
+// and therefore which escaped quote character is permitted.
+// If set to a single quote, it permits the sequence \' and disallows unescaped '.
+// If set to a double quote, it permits \" and disallows unescaped ".
+// If set to zero, it does not permit either escape and allows both quote characters to appear unescaped.
+func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {
+	// easy cases
+	switch c := s[0]; {
+	case c == quote && (quote == '\'' || quote == '"'):
+		err = ErrSyntax
+		return
+	case c >= utf8.RuneSelf:
+		r, size := utf8.DecodeRuneInString(s)
+		return r, true, s[size:], nil
+	case c != '\\':
+		return rune(s[0]), false, s[1:], nil
+	}
+
+	// hard case: c is backslash
+	if len(s) <= 1 {
+		err = ErrSyntax
+		return
+	}
+	c := s[1]
+	s = s[2:]
+
+	switch c {
+	case 'a':
+		value = '\a'
+	case 'b':
+		value = '\b'
+	case 'f':
+		value = '\f'
+	case 'n':
+		value = '\n'
+	case 'r':
+		value = '\r'
+	case 't':
+		value = '\t'
+	case 'v':
+		value = '\v'
+	case 'x', 'u', 'U':
+		n := 0
+		switch c {
+		case 'x':
+			n = 2
+		case 'u':
+			n = 4
+		case 'U':
+			n = 8
+		}
+		var v rune
+		if len(s) < n {
+			err = ErrSyntax
+			return
+		}
+		for j := 0; j < n; j++ {
+			x, ok := unhex(s[j])
+			if !ok {
+				err = ErrSyntax
+				return
+			}
+			v = v<<4 | x
+		}
+		s = s[n:]
+		if c == 'x' {
+			// single-byte string, possibly not UTF-8
+			value = v
+			break
+		}
+		if v > utf8.MaxRune {
+			err = ErrSyntax
+			return
+		}
+		value = v
+		multibyte = true
+	case '0', '1', '2', '3', '4', '5', '6', '7':
+		v := rune(c) - '0'
+		if len(s) < 2 {
+			err = ErrSyntax
+			return
+		}
+		for j := 0; j < 2; j++ { // one digit already; two more
+			x := rune(s[j]) - '0'
+			if x < 0 || x > 7 {
+				err = ErrSyntax
+				return
+			}
+			v = (v << 3) | x
+		}
+		s = s[2:]
+		if v > 255 {
+			err = ErrSyntax
+			return
+		}
+		value = v
+	case '\\':
+		value = '\\'
+	case '\'', '"':
+		if c != quote {
+			err = ErrSyntax
+			return
+		}
+		value = rune(c)
+	default:
+		err = ErrSyntax
+		return
+	}
+	tail = s
+	return
+}
+
+// Unquote interprets s as a single-quoted, double-quoted,
+// or backquoted Go string literal, returning the string value
+// that s quotes.  (If s is single-quoted, it would be a Go
+// character literal; Unquote returns the corresponding
+// one-character string.)
+func Unquote(s string) (t string, err error) {
+	n := len(s)
+	if n < 2 {
+		return "", ErrSyntax
+	}
+	quote := s[0]
+	if quote != s[n-1] {
+		return "", ErrSyntax
+	}
+	s = s[1 : n-1]
+
+	if quote == '`' {
+		if contains(s, '`') {
+			return "", ErrSyntax
+		}
+		return s, nil
+	}
+	if quote != '"' && quote != '\'' {
+		return "", ErrSyntax
+	}
+	if contains(s, '\n') {
+		return "", ErrSyntax
+	}
+
+	// Is it trivial?  Avoid allocation.
+	if !contains(s, '\\') && !contains(s, quote) {
+		switch quote {
+		case '"':
+			return s, nil
+		case '\'':
+			r, size := utf8.DecodeRuneInString(s)
+			if size == len(s) && (r != utf8.RuneError || size != 1) {
+				return s, nil
+			}
+		}
+	}
+
+	var runeTmp [utf8.UTFMax]byte
+	buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
+	for len(s) > 0 {
+		c, multibyte, ss, err := UnquoteChar(s, quote)
+		if err != nil {
+			return "", err
+		}
+		s = ss
+		if c < utf8.RuneSelf || !multibyte {
+			buf = append(buf, byte(c))
+		} else {
+			n := utf8.EncodeRune(runeTmp[:], c)
+			buf = append(buf, runeTmp[:n]...)
+		}
+		if quote == '\'' && len(s) != 0 {
+			// single-quoted must be single character
+			return "", ErrSyntax
+		}
+	}
+	return string(buf), nil
+}
+
+// contains reports whether the string contains the byte c.
+func contains(s string, c byte) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] == c {
+			return true
+		}
+	}
+	return false
+}
+
+// bsearch16 returns the smallest i such that a[i] >= x.
+// If there is no such i, bsearch16 returns len(a).
+func bsearch16(a []uint16, x uint16) int {
+	i, j := 0, len(a)
+	for i < j {
+		h := i + (j-i)/2
+		if a[h] < x {
+			i = h + 1
+		} else {
+			j = h
+		}
+	}
+	return i
+}
+
+// bsearch32 returns the smallest i such that a[i] >= x.
+// If there is no such i, bsearch32 returns len(a).
+func bsearch32(a []uint32, x uint32) int {
+	i, j := 0, len(a)
+	for i < j {
+		h := i + (j-i)/2
+		if a[h] < x {
+			i = h + 1
+		} else {
+			j = h
+		}
+	}
+	return i
+}
+
+// TODO: IsPrint is a local implementation of unicode.IsPrint, verified by the tests
+// to give the same answer. It allows this package not to depend on unicode,
+// and therefore not pull in all the Unicode tables. If the linker were better
+// at tossing unused tables, we could get rid of this implementation.
+// That would be nice.
+
+// IsPrint reports whether the rune is defined as printable by Go, with
+// the same definition as unicode.IsPrint: letters, numbers, punctuation,
+// symbols and ASCII space.
+func IsPrint(r rune) bool {
+	// Fast check for Latin-1
+	if r <= 0xFF {
+		if 0x20 <= r && r <= 0x7E {
+			// All the ASCII is printable from space through DEL-1.
+			return true
+		}
+		if 0xA1 <= r && r <= 0xFF {
+			// Similarly for ¡ through ÿ...
+			return r != 0xAD // ...except for the bizarre soft hyphen.
+		}
+		return false
+	}
+
+	// Same algorithm, either on uint16 or uint32 value.
+	// First, find first i such that isPrint[i] >= x.
+	// This is the index of either the start or end of a pair that might span x.
+	// The start is even (isPrint[i&^1]) and the end is odd (isPrint[i|1]).
+	// If we find x in a range, make sure x is not in isNotPrint list.
+
+	if 0 <= r && r < 1<<16 {
+		rr, isPrint, isNotPrint := uint16(r), isPrint16, isNotPrint16
+		i := bsearch16(isPrint, rr)
+		if i >= len(isPrint) || rr < isPrint[i&^1] || isPrint[i|1] < rr {
+			return false
+		}
+		j := bsearch16(isNotPrint, rr)
+		return j >= len(isNotPrint) || isNotPrint[j] != rr
+	}
+
+	rr, isPrint, isNotPrint := uint32(r), isPrint32, isNotPrint32
+	i := bsearch32(isPrint, rr)
+	if i >= len(isPrint) || rr < isPrint[i&^1] || isPrint[i|1] < rr {
+		return false
+	}
+	if r >= 0x20000 {
+		return true
+	}
+	r -= 0x10000
+	j := bsearch16(isNotPrint, uint16(r))
+	return j >= len(isNotPrint) || isNotPrint[j] != uint16(r)
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/quote_example_test.go b/third_party/gofrontend/libgo/go/strconv/quote_example_test.go
new file mode 100644
index 0000000..405a57e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/quote_example_test.go
@@ -0,0 +1,35 @@
+// Copyright 2013 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 strconv_test
+
+import (
+	"fmt"
+	"strconv"
+)
+
+func ExampleUnquote() {
+	test := func(s string) {
+		t, err := strconv.Unquote(s)
+		if err != nil {
+			fmt.Printf("Unquote(%#v): %v\n", s, err)
+		} else {
+			fmt.Printf("Unquote(%#v) = %v\n", s, t)
+		}
+	}
+
+	s := `cafe\u0301`
+	// If the string doesn't have quotes, it can't be unquoted.
+	test(s) // invalid syntax
+	test("`" + s + "`")
+	test(`"` + s + `"`)
+
+	test(`'\u00e9'`)
+
+	// Output:
+	// Unquote("cafe\\u0301"): invalid syntax
+	// Unquote("`cafe\\u0301`") = cafe\u0301
+	// Unquote("\"cafe\\u0301\"") = café
+	// Unquote("'\\u00e9'") = é
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/quote_test.go b/third_party/gofrontend/libgo/go/strconv/quote_test.go
new file mode 100644
index 0000000..e4b5b6b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/quote_test.go
@@ -0,0 +1,262 @@
+// 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 strconv_test
+
+import (
+	. "strconv"
+	"testing"
+	"unicode"
+)
+
+// Verify that our isPrint agrees with unicode.IsPrint
+func TestIsPrint(t *testing.T) {
+	n := 0
+	for r := rune(0); r <= unicode.MaxRune; r++ {
+		if IsPrint(r) != unicode.IsPrint(r) {
+			t.Errorf("IsPrint(%U)=%t incorrect", r, IsPrint(r))
+			n++
+			if n > 10 {
+				return
+			}
+		}
+	}
+}
+
+type quoteTest struct {
+	in    string
+	out   string
+	ascii string
+}
+
+var quotetests = []quoteTest{
+	{"\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`, `"\a\b\f\r\n\t\v"`},
+	{"\\", `"\\"`, `"\\"`},
+	{"abc\xffdef", `"abc\xffdef"`, `"abc\xffdef"`},
+	{"\u263a", `"☺"`, `"\u263a"`},
+	{"\U0010ffff", `"\U0010ffff"`, `"\U0010ffff"`},
+	{"\x04", `"\x04"`, `"\x04"`},
+}
+
+func TestQuote(t *testing.T) {
+	for _, tt := range quotetests {
+		if out := Quote(tt.in); out != tt.out {
+			t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
+		}
+		if out := AppendQuote([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
+			t.Errorf("AppendQuote(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
+		}
+	}
+}
+
+func TestQuoteToASCII(t *testing.T) {
+	for _, tt := range quotetests {
+		if out := QuoteToASCII(tt.in); out != tt.ascii {
+			t.Errorf("QuoteToASCII(%s) = %s, want %s", tt.in, out, tt.ascii)
+		}
+		if out := AppendQuoteToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
+			t.Errorf("AppendQuoteToASCII(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
+		}
+	}
+}
+
+type quoteRuneTest struct {
+	in    rune
+	out   string
+	ascii string
+}
+
+var quoterunetests = []quoteRuneTest{
+	{'a', `'a'`, `'a'`},
+	{'\a', `'\a'`, `'\a'`},
+	{'\\', `'\\'`, `'\\'`},
+	{0xFF, `'ÿ'`, `'\u00ff'`},
+	{0x263a, `'☺'`, `'\u263a'`},
+	{0xfffd, `'�'`, `'\ufffd'`},
+	{0x0010ffff, `'\U0010ffff'`, `'\U0010ffff'`},
+	{0x0010ffff + 1, `'�'`, `'\ufffd'`},
+	{0x04, `'\x04'`, `'\x04'`},
+}
+
+func TestQuoteRune(t *testing.T) {
+	for _, tt := range quoterunetests {
+		if out := QuoteRune(tt.in); out != tt.out {
+			t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out)
+		}
+		if out := AppendQuoteRune([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
+			t.Errorf("AppendQuoteRune(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
+		}
+	}
+}
+
+func TestQuoteRuneToASCII(t *testing.T) {
+	for _, tt := range quoterunetests {
+		if out := QuoteRuneToASCII(tt.in); out != tt.ascii {
+			t.Errorf("QuoteRuneToASCII(%U) = %s, want %s", tt.in, out, tt.ascii)
+		}
+		if out := AppendQuoteRuneToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
+			t.Errorf("AppendQuoteRuneToASCII(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
+		}
+	}
+}
+
+type canBackquoteTest struct {
+	in  string
+	out bool
+}
+
+var canbackquotetests = []canBackquoteTest{
+	{"`", false},
+	{string(0), false},
+	{string(1), false},
+	{string(2), false},
+	{string(3), false},
+	{string(4), false},
+	{string(5), false},
+	{string(6), false},
+	{string(7), false},
+	{string(8), false},
+	{string(9), true}, // \t
+	{string(10), false},
+	{string(11), false},
+	{string(12), false},
+	{string(13), false},
+	{string(14), false},
+	{string(15), false},
+	{string(16), false},
+	{string(17), false},
+	{string(18), false},
+	{string(19), false},
+	{string(20), false},
+	{string(21), false},
+	{string(22), false},
+	{string(23), false},
+	{string(24), false},
+	{string(25), false},
+	{string(26), false},
+	{string(27), false},
+	{string(28), false},
+	{string(29), false},
+	{string(30), false},
+	{string(31), false},
+	{string(0x7F), false},
+	{`' !"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, true},
+	{`0123456789`, true},
+	{`ABCDEFGHIJKLMNOPQRSTUVWXYZ`, true},
+	{`abcdefghijklmnopqrstuvwxyz`, true},
+	{`☺`, true},
+}
+
+func TestCanBackquote(t *testing.T) {
+	for _, tt := range canbackquotetests {
+		if out := CanBackquote(tt.in); out != tt.out {
+			t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out)
+		}
+	}
+}
+
+type unQuoteTest struct {
+	in  string
+	out string
+}
+
+var unquotetests = []unQuoteTest{
+	{`""`, ""},
+	{`"a"`, "a"},
+	{`"abc"`, "abc"},
+	{`"☺"`, "☺"},
+	{`"hello world"`, "hello world"},
+	{`"\xFF"`, "\xFF"},
+	{`"\377"`, "\377"},
+	{`"\u1234"`, "\u1234"},
+	{`"\U00010111"`, "\U00010111"},
+	{`"\U0001011111"`, "\U0001011111"},
+	{`"\a\b\f\n\r\t\v\\\""`, "\a\b\f\n\r\t\v\\\""},
+	{`"'"`, "'"},
+
+	{`'a'`, "a"},
+	{`'☹'`, "☹"},
+	{`'\a'`, "\a"},
+	{`'\x10'`, "\x10"},
+	{`'\377'`, "\377"},
+	{`'\u1234'`, "\u1234"},
+	{`'\U00010111'`, "\U00010111"},
+	{`'\t'`, "\t"},
+	{`' '`, " "},
+	{`'\''`, "'"},
+	{`'"'`, "\""},
+
+	{"``", ``},
+	{"`a`", `a`},
+	{"`abc`", `abc`},
+	{"`☺`", `☺`},
+	{"`hello world`", `hello world`},
+	{"`\\xFF`", `\xFF`},
+	{"`\\377`", `\377`},
+	{"`\\`", `\`},
+	{"`\n`", "\n"},
+	{"`	`", `	`},
+	{"` `", ` `},
+}
+
+var misquoted = []string{
+	``,
+	`"`,
+	`"a`,
+	`"'`,
+	`b"`,
+	`"\"`,
+	`"\9"`,
+	`"\19"`,
+	`"\129"`,
+	`'\'`,
+	`'\9'`,
+	`'\19'`,
+	`'\129'`,
+	`'ab'`,
+	`"\x1!"`,
+	`"\U12345678"`,
+	`"\z"`,
+	"`",
+	"`xxx",
+	"`\"",
+	`"\'"`,
+	`'\"'`,
+	"\"\n\"",
+	"\"\\n\n\"",
+	"'\n'",
+}
+
+func TestUnquote(t *testing.T) {
+	for _, tt := range unquotetests {
+		if out, err := Unquote(tt.in); err != nil && out != tt.out {
+			t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
+		}
+	}
+
+	// run the quote tests too, backward
+	for _, tt := range quotetests {
+		if in, err := Unquote(tt.out); in != tt.in {
+			t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in)
+		}
+	}
+
+	for _, s := range misquoted {
+		if out, err := Unquote(s); out != "" || err != ErrSyntax {
+			t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", ErrSyntax)
+		}
+	}
+}
+
+func BenchmarkUnquoteEasy(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Unquote(`"Give me a rock, paper and scissors and I will move the world."`)
+	}
+}
+
+func BenchmarkUnquoteHard(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Unquote(`"\x47ive me a \x72ock, \x70aper and \x73cissors and \x49 will move the world."`)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/strconv/strconv_test.go b/third_party/gofrontend/libgo/go/strconv/strconv_test.go
new file mode 100644
index 0000000..207e00e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/strconv_test.go
@@ -0,0 +1,63 @@
+// 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 strconv_test
+
+/*
+
+gccgo does not pass this.
+
+import (
+	"runtime"
+	. "strconv"
+	"strings"
+	"testing"
+)
+
+var (
+	globalBuf [64]byte
+	nextToOne = "1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1"
+
+	mallocTest = []struct {
+		count int
+		desc  string
+		fn    func()
+	}{
+		{0, `AppendInt(localBuf[:0], 123, 10)`, func() {
+			var localBuf [64]byte
+			AppendInt(localBuf[:0], 123, 10)
+		}},
+		{0, `AppendInt(globalBuf[:0], 123, 10)`, func() { AppendInt(globalBuf[:0], 123, 10) }},
+		{0, `AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)`, func() {
+			var localBuf [64]byte
+			AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)
+		}},
+		{0, `AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64)`, func() { AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64) }},
+		{0, `ParseFloat("123.45", 64)`, func() { ParseFloat("123.45", 64) }},
+		{0, `ParseFloat("123.456789123456789", 64)`, func() { ParseFloat("123.456789123456789", 64) }},
+		{0, `ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64)`, func() {
+			ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64)
+		}},
+		{0, `ParseFloat("1.0000000000000001110223024625156540423631668090820312500...001", 64)`, func() {
+			ParseFloat(nextToOne, 64)
+		}},
+	}
+)
+
+func TestCountMallocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Skip("skipping; GOMAXPROCS>1")
+	}
+	for _, mt := range mallocTest {
+		allocs := testing.AllocsPerRun(100, mt.fn)
+		if max := float64(mt.count); allocs > max {
+			t.Errorf("%s: %v allocs, want <=%v", mt.desc, allocs, max)
+		}
+	}
+}
+
+*/
diff --git a/third_party/gofrontend/libgo/go/strconv/testdata/testfp.txt b/third_party/gofrontend/libgo/go/strconv/testdata/testfp.txt
new file mode 100644
index 0000000..08d3c4e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/testdata/testfp.txt
@@ -0,0 +1,181 @@
+# Floating-point conversion test cases.
+# Empty lines and lines beginning with # are ignored.
+# The rest have four fields per line: type, format, input, and output.
+# The input is given either in decimal or binary scientific notation.
+# The output is the string that should be produced by formatting the
+# input with the given format.
+#
+# The formats are as in C's printf, except that %b means print
+# binary scientific notation: NpE = N x 2^E.
+
+# TODO:
+#	Powers of 10.
+#	Powers of 2.
+#	%.20g versions.
+#	random sources
+#	random targets
+#	random targets ± half a ULP
+
+# Difficult boundary cases, derived from tables given in
+#	Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion
+#	ftp://ftp.ee.lbl.gov/testbase-report.ps.Z
+
+# Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
+float64 %b 5e+125 6653062250012735p+365
+float64 %b 69e+267 4705683757438170p+841
+float64 %b 999e-026 6798841691080350p-129
+float64 %b 7861e-034 8975675289889240p-153
+float64 %b 75569e-254 6091718967192243p-880
+float64 %b 928609e-261 7849264900213743p-900
+float64 %b 9210917e+080 8341110837370930p+236
+float64 %b 84863171e+114 4625202867375927p+353
+float64 %b 653777767e+273 5068902999763073p+884
+float64 %b 5232604057e-298 5741343011915040p-1010
+float64 %b 27235667517e-109 6707124626673586p-380
+float64 %b 653532977297e-123 7078246407265384p-422
+float64 %b 3142213164987e-294 8219991337640559p-988
+float64 %b 46202199371337e-072 5224462102115359p-246
+float64 %b 231010996856685e-073 5224462102115359p-247
+float64 %b 9324754620109615e+212 5539753864394442p+705
+float64 %b 78459735791271921e+049 8388176519442766p+166
+float64 %b 272104041512242479e+200 5554409530847367p+670
+float64 %b 6802601037806061975e+198 5554409530847367p+668
+float64 %b 20505426358836677347e-221 4524032052079546p-722
+float64 %b 836168422905420598437e-234 5070963299887562p-760
+float64 %b 4891559871276714924261e+222 6452687840519111p+757
+
+# Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
+float64 %b 9e-265 8168427841980010p-930
+float64 %b 85e-037 6360455125664090p-169
+float64 %b 623e+100 6263531988747231p+289
+float64 %b 3571e+263 6234526311072170p+833
+float64 %b 81661e+153 6696636728760206p+472
+float64 %b 920657e-023 5975405561110124p-109
+float64 %b 4603285e-024 5975405561110124p-110
+float64 %b 87575437e-309 8452160731874668p-1053
+float64 %b 245540327e+122 4985336549131723p+381
+float64 %b 6138508175e+120 4985336549131723p+379
+float64 %b 83356057653e+193 5986732817132056p+625
+float64 %b 619534293513e+124 4798406992060657p+399
+float64 %b 2335141086879e+218 5419088166961646p+713
+float64 %b 36167929443327e-159 8135819834632444p-536
+float64 %b 609610927149051e-255 4576664294594737p-850
+float64 %b 3743626360493413e-165 6898586531774201p-549
+float64 %b 94080055902682397e-242 6273271706052298p-800
+float64 %b 899810892172646163e+283 7563892574477827p+947
+float64 %b 7120190517612959703e+120 5385467232557565p+409
+float64 %b 25188282901709339043e-252 5635662608542340p-825
+float64 %b 308984926168550152811e-052 5644774693823803p-157
+float64 %b 6372891218502368041059e+064 4616868614322430p+233
+
+# Table 3: Stress Inputs for Converting 53-bit Binary to Decimal, < 1/2 ULP
+float64 %.0e 8511030020275656p-342 9e-88
+float64 %.1e 5201988407066741p-824 4.6e-233
+float64 %.2e 6406892948269899p+237 1.41e+87
+float64 %.3e 8431154198732492p+72 3.981e+37
+float64 %.4e 6475049196144587p+99 4.1040e+45
+float64 %.5e 8274307542972842p+726 2.92084e+234
+float64 %.6e 5381065484265332p-456 2.891946e-122
+float64 %.7e 6761728585499734p-1057 4.3787718e-303
+float64 %.8e 7976538478610756p+376 1.22770163e+129
+float64 %.9e 5982403858958067p+377 1.841552452e+129
+float64 %.10e 5536995190630837p+93 5.4835744350e+43
+float64 %.11e 7225450889282194p+710 3.89190181146e+229
+float64 %.12e 7225450889282194p+709 1.945950905732e+229
+float64 %.13e 8703372741147379p+117 1.4460958381605e+51
+float64 %.14e 8944262675275217p-1001 4.17367747458531e-286
+float64 %.15e 7459803696087692p-707 1.107950772878888e-197
+float64 %.16e 6080469016670379p-381 1.2345501366327440e-99
+float64 %.17e 8385515147034757p+721 9.25031711960365024e+232
+float64 %.18e 7514216811389786p-828 4.198047150284889840e-234
+float64 %.19e 8397297803260511p-345 1.1716315319786511046e-88
+float64 %.20e 6733459239310543p+202 4.32810072844612493629e+76
+float64 %.21e 8091450587292794p-473 3.317710118160031081518e-127
+
+# Table 4: Stress Inputs for Converting 53-bit Binary to Decimal, > 1/2 ULP
+float64 %.0e 6567258882077402p+952 3e+302
+float64 %.1e 6712731423444934p+535 7.6e+176
+float64 %.2e 6712731423444934p+534 3.78e+176
+float64 %.3e 5298405411573037p-957 4.350e-273
+float64 %.4e 5137311167659507p-144 2.3037e-28
+float64 %.5e 6722280709661868p+363 1.26301e+125
+float64 %.6e 5344436398034927p-169 7.142211e-36
+float64 %.7e 8369123604277281p-853 1.3934574e-241
+float64 %.8e 8995822108487663p-780 1.41463449e-219
+float64 %.9e 8942832835564782p-383 4.539277920e-100
+float64 %.10e 8942832835564782p-384 2.2696389598e-100
+float64 %.11e 8942832835564782p-385 1.13481947988e-100
+float64 %.12e 6965949469487146p-249 7.700366561890e-60
+float64 %.13e 6965949469487146p-250 3.8501832809448e-60
+float64 %.14e 6965949469487146p-251 1.92509164047238e-60
+float64 %.15e 7487252720986826p+548 6.898586531774201e+180
+float64 %.16e 5592117679628511p+164 1.3076622631878654e+65
+float64 %.17e 8887055249355788p+665 1.36052020756121240e+216
+float64 %.18e 6994187472632449p+690 3.592810217475959676e+223
+float64 %.19e 8797576579012143p+588 8.9125197712484551899e+192
+float64 %.20e 7363326733505337p+272 5.58769757362301140950e+97
+float64 %.21e 8549497411294502p-448 1.176257830728540379990e-119
+
+# Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
+# NOTE: The lines with exponent p-149 have been changed from the
+# paper.  Those entries originally read p-150 and had a mantissa
+# twice as large (and even), but IEEE single-precision has no p-150:
+# that's the start of the denormals.
+float32 %b 5e-20 15474250p-88
+float32 %b 67e+14 12479722p+29
+float32 %b 985e+15 14333636p+36
+# float32 %b 7693e-42 10979816p-150
+float32 %b 7693e-42 5489908p-149
+float32 %b 55895e-16 12888509p-61
+# float32 %b 996622e-44 14224264p-150
+float32 %b 996622e-44 7112132p-149
+float32 %b 7038531e-32 11420669p-107
+# float32 %b 60419369e-46 8623340p-150
+float32 %b 60419369e-46 4311670p-149
+float32 %b 702990899e-20 16209866p-61
+# float32 %b 6930161142e-48 9891056p-150
+float32 %b 6930161142e-48 4945528p-149
+float32 %b 25933168707e+13 14395800p+54
+float32 %b 596428896559e+20 12333860p+82
+
+# Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
+float32 %b 3e-23 9507380p-98
+float32 %b 57e+18 12960300p+42
+float32 %b 789e-35 10739312p-130
+float32 %b 2539e-18 11990089p-72
+float32 %b 76173e+28 9845130p+86
+float32 %b 887745e-11 9760860p-40
+float32 %b 5382571e-37 11447463p-124
+float32 %b 82381273e-35 8554961p-113
+float32 %b 750486563e-38 9975678p-120
+float32 %b 3752432815e-39 9975678p-121
+float32 %b 75224575729e-45 13105970p-137
+float32 %b 459926601011e+15 12466336p+65
+
+# Table 16: Stress Inputs for Converting 24-bit Binary to Decimal, < 1/2 ULP
+float32 %.0e 12676506p-102 2e-24
+float32 %.1e 12676506p-103 1.2e-24
+float32 %.2e 15445013p+86 1.19e+33
+float32 %.3e 13734123p-138 3.941e-35
+float32 %.4e 12428269p-130 9.1308e-33
+float32 %.5e 15334037p-146 1.71900e-37
+float32 %.6e 11518287p-41 5.237910e-06
+float32 %.7e 12584953p-145 2.8216440e-37
+float32 %.8e 15961084p-125 3.75243281e-31
+float32 %.9e 14915817p-146 1.672120916e-37
+float32 %.10e 10845484p-102 2.1388945814e-24
+float32 %.11e 16431059p-61 7.12583594561e-12
+
+# Table 17: Stress Inputs for Converting 24-bit Binary to Decimal, > 1/2 ULP
+float32 %.0e 16093626p+69 1e+28
+float32 %.1e 9983778p+25 3.4e+14
+float32 %.2e 12745034p+104 2.59e+38
+float32 %.3e 12706553p+72 6.001e+28
+float32 %.4e 11005028p+45 3.8721e+20
+float32 %.5e 15059547p+71 3.55584e+28
+float32 %.6e 16015691p-99 2.526831e-23
+float32 %.7e 8667859p+56 6.2458507e+23
+float32 %.8e 14855922p-82 3.07213267e-18
+float32 %.9e 14855922p-83 1.536066333e-18
+float32 %.10e 10144164p-110 7.8147796834e-27
+float32 %.11e 13248074p+95 5.24810279937e+35
diff --git a/third_party/gofrontend/libgo/go/strconv/testfp.txt b/third_party/gofrontend/libgo/go/strconv/testfp.txt
new file mode 100644
index 0000000..08d3c4e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strconv/testfp.txt
@@ -0,0 +1,181 @@
+# Floating-point conversion test cases.
+# Empty lines and lines beginning with # are ignored.
+# The rest have four fields per line: type, format, input, and output.
+# The input is given either in decimal or binary scientific notation.
+# The output is the string that should be produced by formatting the
+# input with the given format.
+#
+# The formats are as in C's printf, except that %b means print
+# binary scientific notation: NpE = N x 2^E.
+
+# TODO:
+#	Powers of 10.
+#	Powers of 2.
+#	%.20g versions.
+#	random sources
+#	random targets
+#	random targets ± half a ULP
+
+# Difficult boundary cases, derived from tables given in
+#	Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion
+#	ftp://ftp.ee.lbl.gov/testbase-report.ps.Z
+
+# Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
+float64 %b 5e+125 6653062250012735p+365
+float64 %b 69e+267 4705683757438170p+841
+float64 %b 999e-026 6798841691080350p-129
+float64 %b 7861e-034 8975675289889240p-153
+float64 %b 75569e-254 6091718967192243p-880
+float64 %b 928609e-261 7849264900213743p-900
+float64 %b 9210917e+080 8341110837370930p+236
+float64 %b 84863171e+114 4625202867375927p+353
+float64 %b 653777767e+273 5068902999763073p+884
+float64 %b 5232604057e-298 5741343011915040p-1010
+float64 %b 27235667517e-109 6707124626673586p-380
+float64 %b 653532977297e-123 7078246407265384p-422
+float64 %b 3142213164987e-294 8219991337640559p-988
+float64 %b 46202199371337e-072 5224462102115359p-246
+float64 %b 231010996856685e-073 5224462102115359p-247
+float64 %b 9324754620109615e+212 5539753864394442p+705
+float64 %b 78459735791271921e+049 8388176519442766p+166
+float64 %b 272104041512242479e+200 5554409530847367p+670
+float64 %b 6802601037806061975e+198 5554409530847367p+668
+float64 %b 20505426358836677347e-221 4524032052079546p-722
+float64 %b 836168422905420598437e-234 5070963299887562p-760
+float64 %b 4891559871276714924261e+222 6452687840519111p+757
+
+# Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
+float64 %b 9e-265 8168427841980010p-930
+float64 %b 85e-037 6360455125664090p-169
+float64 %b 623e+100 6263531988747231p+289
+float64 %b 3571e+263 6234526311072170p+833
+float64 %b 81661e+153 6696636728760206p+472
+float64 %b 920657e-023 5975405561110124p-109
+float64 %b 4603285e-024 5975405561110124p-110
+float64 %b 87575437e-309 8452160731874668p-1053
+float64 %b 245540327e+122 4985336549131723p+381
+float64 %b 6138508175e+120 4985336549131723p+379
+float64 %b 83356057653e+193 5986732817132056p+625
+float64 %b 619534293513e+124 4798406992060657p+399
+float64 %b 2335141086879e+218 5419088166961646p+713
+float64 %b 36167929443327e-159 8135819834632444p-536
+float64 %b 609610927149051e-255 4576664294594737p-850
+float64 %b 3743626360493413e-165 6898586531774201p-549
+float64 %b 94080055902682397e-242 6273271706052298p-800
+float64 %b 899810892172646163e+283 7563892574477827p+947
+float64 %b 7120190517612959703e+120 5385467232557565p+409
+float64 %b 25188282901709339043e-252 5635662608542340p-825
+float64 %b 308984926168550152811e-052 5644774693823803p-157
+float64 %b 6372891218502368041059e+064 4616868614322430p+233
+
+# Table 3: Stress Inputs for Converting 53-bit Binary to Decimal, < 1/2 ULP
+float64 %.0e 8511030020275656p-342 9e-88
+float64 %.1e 5201988407066741p-824 4.6e-233
+float64 %.2e 6406892948269899p+237 1.41e+87
+float64 %.3e 8431154198732492p+72 3.981e+37
+float64 %.4e 6475049196144587p+99 4.1040e+45
+float64 %.5e 8274307542972842p+726 2.92084e+234
+float64 %.6e 5381065484265332p-456 2.891946e-122
+float64 %.7e 6761728585499734p-1057 4.3787718e-303
+float64 %.8e 7976538478610756p+376 1.22770163e+129
+float64 %.9e 5982403858958067p+377 1.841552452e+129
+float64 %.10e 5536995190630837p+93 5.4835744350e+43
+float64 %.11e 7225450889282194p+710 3.89190181146e+229
+float64 %.12e 7225450889282194p+709 1.945950905732e+229
+float64 %.13e 8703372741147379p+117 1.4460958381605e+51
+float64 %.14e 8944262675275217p-1001 4.17367747458531e-286
+float64 %.15e 7459803696087692p-707 1.107950772878888e-197
+float64 %.16e 6080469016670379p-381 1.2345501366327440e-99
+float64 %.17e 8385515147034757p+721 9.25031711960365024e+232
+float64 %.18e 7514216811389786p-828 4.198047150284889840e-234
+float64 %.19e 8397297803260511p-345 1.1716315319786511046e-88
+float64 %.20e 6733459239310543p+202 4.32810072844612493629e+76
+float64 %.21e 8091450587292794p-473 3.317710118160031081518e-127
+
+# Table 4: Stress Inputs for Converting 53-bit Binary to Decimal, > 1/2 ULP
+float64 %.0e 6567258882077402p+952 3e+302
+float64 %.1e 6712731423444934p+535 7.6e+176
+float64 %.2e 6712731423444934p+534 3.78e+176
+float64 %.3e 5298405411573037p-957 4.350e-273
+float64 %.4e 5137311167659507p-144 2.3037e-28
+float64 %.5e 6722280709661868p+363 1.26301e+125
+float64 %.6e 5344436398034927p-169 7.142211e-36
+float64 %.7e 8369123604277281p-853 1.3934574e-241
+float64 %.8e 8995822108487663p-780 1.41463449e-219
+float64 %.9e 8942832835564782p-383 4.539277920e-100
+float64 %.10e 8942832835564782p-384 2.2696389598e-100
+float64 %.11e 8942832835564782p-385 1.13481947988e-100
+float64 %.12e 6965949469487146p-249 7.700366561890e-60
+float64 %.13e 6965949469487146p-250 3.8501832809448e-60
+float64 %.14e 6965949469487146p-251 1.92509164047238e-60
+float64 %.15e 7487252720986826p+548 6.898586531774201e+180
+float64 %.16e 5592117679628511p+164 1.3076622631878654e+65
+float64 %.17e 8887055249355788p+665 1.36052020756121240e+216
+float64 %.18e 6994187472632449p+690 3.592810217475959676e+223
+float64 %.19e 8797576579012143p+588 8.9125197712484551899e+192
+float64 %.20e 7363326733505337p+272 5.58769757362301140950e+97
+float64 %.21e 8549497411294502p-448 1.176257830728540379990e-119
+
+# Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
+# NOTE: The lines with exponent p-149 have been changed from the
+# paper.  Those entries originally read p-150 and had a mantissa
+# twice as large (and even), but IEEE single-precision has no p-150:
+# that's the start of the denormals.
+float32 %b 5e-20 15474250p-88
+float32 %b 67e+14 12479722p+29
+float32 %b 985e+15 14333636p+36
+# float32 %b 7693e-42 10979816p-150
+float32 %b 7693e-42 5489908p-149
+float32 %b 55895e-16 12888509p-61
+# float32 %b 996622e-44 14224264p-150
+float32 %b 996622e-44 7112132p-149
+float32 %b 7038531e-32 11420669p-107
+# float32 %b 60419369e-46 8623340p-150
+float32 %b 60419369e-46 4311670p-149
+float32 %b 702990899e-20 16209866p-61
+# float32 %b 6930161142e-48 9891056p-150
+float32 %b 6930161142e-48 4945528p-149
+float32 %b 25933168707e+13 14395800p+54
+float32 %b 596428896559e+20 12333860p+82
+
+# Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
+float32 %b 3e-23 9507380p-98
+float32 %b 57e+18 12960300p+42
+float32 %b 789e-35 10739312p-130
+float32 %b 2539e-18 11990089p-72
+float32 %b 76173e+28 9845130p+86
+float32 %b 887745e-11 9760860p-40
+float32 %b 5382571e-37 11447463p-124
+float32 %b 82381273e-35 8554961p-113
+float32 %b 750486563e-38 9975678p-120
+float32 %b 3752432815e-39 9975678p-121
+float32 %b 75224575729e-45 13105970p-137
+float32 %b 459926601011e+15 12466336p+65
+
+# Table 16: Stress Inputs for Converting 24-bit Binary to Decimal, < 1/2 ULP
+float32 %.0e 12676506p-102 2e-24
+float32 %.1e 12676506p-103 1.2e-24
+float32 %.2e 15445013p+86 1.19e+33
+float32 %.3e 13734123p-138 3.941e-35
+float32 %.4e 12428269p-130 9.1308e-33
+float32 %.5e 15334037p-146 1.71900e-37
+float32 %.6e 11518287p-41 5.237910e-06
+float32 %.7e 12584953p-145 2.8216440e-37
+float32 %.8e 15961084p-125 3.75243281e-31
+float32 %.9e 14915817p-146 1.672120916e-37
+float32 %.10e 10845484p-102 2.1388945814e-24
+float32 %.11e 16431059p-61 7.12583594561e-12
+
+# Table 17: Stress Inputs for Converting 24-bit Binary to Decimal, > 1/2 ULP
+float32 %.0e 16093626p+69 1e+28
+float32 %.1e 9983778p+25 3.4e+14
+float32 %.2e 12745034p+104 2.59e+38
+float32 %.3e 12706553p+72 6.001e+28
+float32 %.4e 11005028p+45 3.8721e+20
+float32 %.5e 15059547p+71 3.55584e+28
+float32 %.6e 16015691p-99 2.526831e-23
+float32 %.7e 8667859p+56 6.2458507e+23
+float32 %.8e 14855922p-82 3.07213267e-18
+float32 %.9e 14855922p-83 1.536066333e-18
+float32 %.10e 10144164p-110 7.8147796834e-27
+float32 %.11e 13248074p+95 5.24810279937e+35
diff --git a/third_party/gofrontend/libgo/go/strings/example_test.go b/third_party/gofrontend/libgo/go/strings/example_test.go
new file mode 100644
index 0000000..7243e16
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/example_test.go
@@ -0,0 +1,225 @@
+// 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 strings_test
+
+import (
+	"fmt"
+	"strings"
+	"unicode"
+)
+
+func ExampleFields() {
+	fmt.Printf("Fields are: %q", strings.Fields("  foo bar  baz   "))
+	// Output: Fields are: ["foo" "bar" "baz"]
+}
+
+func ExampleFieldsFunc() {
+	f := func(c rune) bool {
+		return !unicode.IsLetter(c) && !unicode.IsNumber(c)
+	}
+	fmt.Printf("Fields are: %q", strings.FieldsFunc("  foo1;bar2,baz3...", f))
+	// Output: Fields are: ["foo1" "bar2" "baz3"]
+}
+
+func ExampleContains() {
+	fmt.Println(strings.Contains("seafood", "foo"))
+	fmt.Println(strings.Contains("seafood", "bar"))
+	fmt.Println(strings.Contains("seafood", ""))
+	fmt.Println(strings.Contains("", ""))
+	// Output:
+	// true
+	// false
+	// true
+	// true
+}
+
+func ExampleContainsAny() {
+	fmt.Println(strings.ContainsAny("team", "i"))
+	fmt.Println(strings.ContainsAny("failure", "u & i"))
+	fmt.Println(strings.ContainsAny("foo", ""))
+	fmt.Println(strings.ContainsAny("", ""))
+	// Output:
+	// false
+	// true
+	// false
+	// false
+}
+
+func ExampleCount() {
+	fmt.Println(strings.Count("cheese", "e"))
+	fmt.Println(strings.Count("five", "")) // before & after each rune
+	// Output:
+	// 3
+	// 5
+}
+
+func ExampleEqualFold() {
+	fmt.Println(strings.EqualFold("Go", "go"))
+	// Output: true
+}
+
+func ExampleIndex() {
+	fmt.Println(strings.Index("chicken", "ken"))
+	fmt.Println(strings.Index("chicken", "dmr"))
+	// Output:
+	// 4
+	// -1
+}
+
+func ExampleIndexFunc() {
+	f := func(c rune) bool {
+		return unicode.Is(unicode.Han, c)
+	}
+	fmt.Println(strings.IndexFunc("Hello, 世界", f))
+	fmt.Println(strings.IndexFunc("Hello, world", f))
+	// Output:
+	// 7
+	// -1
+}
+
+func ExampleIndexAny() {
+	fmt.Println(strings.IndexAny("chicken", "aeiouy"))
+	fmt.Println(strings.IndexAny("crwth", "aeiouy"))
+	// Output:
+	// 2
+	// -1
+}
+
+func ExampleIndexRune() {
+	fmt.Println(strings.IndexRune("chicken", 'k'))
+	fmt.Println(strings.IndexRune("chicken", 'd'))
+	// Output:
+	// 4
+	// -1
+}
+
+func ExampleLastIndex() {
+	fmt.Println(strings.Index("go gopher", "go"))
+	fmt.Println(strings.LastIndex("go gopher", "go"))
+	fmt.Println(strings.LastIndex("go gopher", "rodent"))
+	// Output:
+	// 0
+	// 3
+	// -1
+}
+
+func ExampleJoin() {
+	s := []string{"foo", "bar", "baz"}
+	fmt.Println(strings.Join(s, ", "))
+	// Output: foo, bar, baz
+}
+
+func ExampleRepeat() {
+	fmt.Println("ba" + strings.Repeat("na", 2))
+	// Output: banana
+}
+
+func ExampleReplace() {
+	fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2))
+	fmt.Println(strings.Replace("oink oink oink", "oink", "moo", -1))
+	// Output:
+	// oinky oinky oink
+	// moo moo moo
+}
+
+func ExampleSplit() {
+	fmt.Printf("%q\n", strings.Split("a,b,c", ","))
+	fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a "))
+	fmt.Printf("%q\n", strings.Split(" xyz ", ""))
+	fmt.Printf("%q\n", strings.Split("", "Bernardo O'Higgins"))
+	// Output:
+	// ["a" "b" "c"]
+	// ["" "man " "plan " "canal panama"]
+	// [" " "x" "y" "z" " "]
+	// [""]
+}
+
+func ExampleSplitN() {
+	fmt.Printf("%q\n", strings.SplitN("a,b,c", ",", 2))
+	z := strings.SplitN("a,b,c", ",", 0)
+	fmt.Printf("%q (nil = %v)\n", z, z == nil)
+	// Output:
+	// ["a" "b,c"]
+	// [] (nil = true)
+}
+
+func ExampleSplitAfter() {
+	fmt.Printf("%q\n", strings.SplitAfter("a,b,c", ","))
+	// Output: ["a," "b," "c"]
+}
+
+func ExampleSplitAfterN() {
+	fmt.Printf("%q\n", strings.SplitAfterN("a,b,c", ",", 2))
+	// Output: ["a," "b,c"]
+}
+
+func ExampleTitle() {
+	fmt.Println(strings.Title("her royal highness"))
+	// Output: Her Royal Highness
+}
+
+func ExampleToTitle() {
+	fmt.Println(strings.ToTitle("loud noises"))
+	fmt.Println(strings.ToTitle("хлеб"))
+	// Output:
+	// LOUD NOISES
+	// ХЛЕБ
+}
+
+func ExampleTrim() {
+	fmt.Printf("[%q]", strings.Trim(" !!! Achtung! Achtung! !!! ", "! "))
+	// Output: ["Achtung! Achtung"]
+}
+
+func ExampleMap() {
+	rot13 := func(r rune) rune {
+		switch {
+		case r >= 'A' && r <= 'Z':
+			return 'A' + (r-'A'+13)%26
+		case r >= 'a' && r <= 'z':
+			return 'a' + (r-'a'+13)%26
+		}
+		return r
+	}
+	fmt.Println(strings.Map(rot13, "'Twas brillig and the slithy gopher..."))
+	// Output: 'Gjnf oevyyvt naq gur fyvgul tbcure...
+}
+
+func ExampleTrimSpace() {
+	fmt.Println(strings.TrimSpace(" \t\n a lone gopher \n\t\r\n"))
+	// Output: a lone gopher
+}
+
+func ExampleNewReplacer() {
+	r := strings.NewReplacer("<", "&lt;", ">", "&gt;")
+	fmt.Println(r.Replace("This is <b>HTML</b>!"))
+	// Output: This is &lt;b&gt;HTML&lt;/b&gt;!
+}
+
+func ExampleToUpper() {
+	fmt.Println(strings.ToUpper("Gopher"))
+	// Output: GOPHER
+}
+
+func ExampleToLower() {
+	fmt.Println(strings.ToLower("Gopher"))
+	// Output: gopher
+}
+
+func ExampleTrimSuffix() {
+	var s = "Hello, goodbye, etc!"
+	s = strings.TrimSuffix(s, "goodbye, etc!")
+	s = strings.TrimSuffix(s, "planet")
+	fmt.Print(s, "world!")
+	// Output: Hello, world!
+}
+
+func ExampleTrimPrefix() {
+	var s = "Goodbye,, world!"
+	s = strings.TrimPrefix(s, "Goodbye,")
+	s = strings.TrimPrefix(s, "Howdy,")
+	fmt.Print("Hello" + s)
+	// Output: Hello, world!
+}
diff --git a/third_party/gofrontend/libgo/go/strings/export_test.go b/third_party/gofrontend/libgo/go/strings/export_test.go
new file mode 100644
index 0000000..17c806a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/export_test.go
@@ -0,0 +1,45 @@
+// 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.
+
+package strings
+
+func (r *Replacer) Replacer() interface{} {
+	return r.r
+}
+
+func (r *Replacer) PrintTrie() string {
+	gen := r.r.(*genericReplacer)
+	return gen.printNode(&gen.root, 0)
+}
+
+func (r *genericReplacer) printNode(t *trieNode, depth int) (s string) {
+	if t.priority > 0 {
+		s += "+"
+	} else {
+		s += "-"
+	}
+	s += "\n"
+
+	if t.prefix != "" {
+		s += Repeat(".", depth) + t.prefix
+		s += r.printNode(t.next, depth+len(t.prefix))
+	} else if t.table != nil {
+		for b, m := range r.mapping {
+			if int(m) != r.tableSize && t.table[m] != nil {
+				s += Repeat(".", depth) + string([]byte{byte(b)})
+				s += r.printNode(t.table[m], depth+1)
+			}
+		}
+	}
+	return
+}
+
+func StringFind(pattern, text string) int {
+	return makeStringFinder(pattern).next(text)
+}
+
+func DumpTables(pattern string) ([]int, []int) {
+	finder := makeStringFinder(pattern)
+	return finder.badCharSkip[:], finder.goodSuffixSkip
+}
diff --git a/third_party/gofrontend/libgo/go/strings/indexbyte.c b/third_party/gofrontend/libgo/go/strings/indexbyte.c
new file mode 100644
index 0000000..27f4240
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/indexbyte.c
@@ -0,0 +1,29 @@
+/* indexbyte.c -- implement strings.IndexByte for Go.
+
+   Copyright 2013 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 <stddef.h>
+
+#include "runtime.h"
+#include "go-string.h"
+
+/* This is in C so that the compiler can optimize it appropriately.
+   We deliberately don't split the stack in case it does call the
+   library function, which shouldn't need much stack space.  */
+
+intgo IndexByte (String, char)
+  __asm__ (GOSYM_PREFIX "strings.IndexByte")
+  __attribute__ ((no_split_stack));
+
+intgo
+IndexByte (String s, char b)
+{
+  const char *p;
+
+  p = __builtin_memchr ((const char *) s.str, b, s.len);
+  if (p == NULL)
+    return -1;
+  return p - (const char *) s.str;
+}
diff --git a/third_party/gofrontend/libgo/go/strings/reader.go b/third_party/gofrontend/libgo/go/strings/reader.go
new file mode 100644
index 0000000..82df974
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/reader.go
@@ -0,0 +1,144 @@
+// 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 strings
+
+import (
+	"errors"
+	"io"
+	"unicode/utf8"
+)
+
+// A Reader implements the io.Reader, io.ReaderAt, io.Seeker, io.WriterTo,
+// io.ByteScanner, and io.RuneScanner interfaces by reading
+// from a string.
+type Reader struct {
+	s        string
+	i        int64 // current reading index
+	prevRune int   // index of previous rune; or < 0
+}
+
+// Len returns the number of bytes of the unread portion of the
+// string.
+func (r *Reader) Len() int {
+	if r.i >= int64(len(r.s)) {
+		return 0
+	}
+	return int(int64(len(r.s)) - r.i)
+}
+
+func (r *Reader) Read(b []byte) (n int, err error) {
+	if len(b) == 0 {
+		return 0, nil
+	}
+	if r.i >= int64(len(r.s)) {
+		return 0, io.EOF
+	}
+	r.prevRune = -1
+	n = copy(b, r.s[r.i:])
+	r.i += int64(n)
+	return
+}
+
+func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
+	// cannot modify state - see io.ReaderAt
+	if off < 0 {
+		return 0, errors.New("strings.Reader.ReadAt: negative offset")
+	}
+	if off >= int64(len(r.s)) {
+		return 0, io.EOF
+	}
+	n = copy(b, r.s[off:])
+	if n < len(b) {
+		err = io.EOF
+	}
+	return
+}
+
+func (r *Reader) ReadByte() (b byte, err error) {
+	r.prevRune = -1
+	if r.i >= int64(len(r.s)) {
+		return 0, io.EOF
+	}
+	b = r.s[r.i]
+	r.i++
+	return
+}
+
+func (r *Reader) UnreadByte() error {
+	r.prevRune = -1
+	if r.i <= 0 {
+		return errors.New("strings.Reader.UnreadByte: at beginning of string")
+	}
+	r.i--
+	return nil
+}
+
+func (r *Reader) ReadRune() (ch rune, size int, err error) {
+	if r.i >= int64(len(r.s)) {
+		r.prevRune = -1
+		return 0, 0, io.EOF
+	}
+	r.prevRune = int(r.i)
+	if c := r.s[r.i]; c < utf8.RuneSelf {
+		r.i++
+		return rune(c), 1, nil
+	}
+	ch, size = utf8.DecodeRuneInString(r.s[r.i:])
+	r.i += int64(size)
+	return
+}
+
+func (r *Reader) UnreadRune() error {
+	if r.prevRune < 0 {
+		return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune")
+	}
+	r.i = int64(r.prevRune)
+	r.prevRune = -1
+	return nil
+}
+
+// Seek implements the io.Seeker interface.
+func (r *Reader) Seek(offset int64, whence int) (int64, error) {
+	r.prevRune = -1
+	var abs int64
+	switch whence {
+	case 0:
+		abs = offset
+	case 1:
+		abs = int64(r.i) + offset
+	case 2:
+		abs = int64(len(r.s)) + offset
+	default:
+		return 0, errors.New("strings.Reader.Seek: invalid whence")
+	}
+	if abs < 0 {
+		return 0, errors.New("strings.Reader.Seek: negative position")
+	}
+	r.i = abs
+	return abs, nil
+}
+
+// WriteTo implements the io.WriterTo interface.
+func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
+	r.prevRune = -1
+	if r.i >= int64(len(r.s)) {
+		return 0, nil
+	}
+	s := r.s[r.i:]
+	m, err := io.WriteString(w, s)
+	if m > len(s) {
+		panic("strings.Reader.WriteTo: invalid WriteString count")
+	}
+	r.i += int64(m)
+	n = int64(m)
+	if m != len(s) && err == nil {
+		err = io.ErrShortWrite
+	}
+	return
+}
+
+// NewReader returns a new Reader reading from s.
+// It is similar to bytes.NewBufferString but more efficient and read-only.
+func NewReader(s string) *Reader { return &Reader{s, 0, -1} }
diff --git a/third_party/gofrontend/libgo/go/strings/reader_test.go b/third_party/gofrontend/libgo/go/strings/reader_test.go
new file mode 100644
index 0000000..bee90eb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/reader_test.go
@@ -0,0 +1,159 @@
+// 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 strings_test
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"sync"
+	"testing"
+)
+
+func TestReader(t *testing.T) {
+	r := strings.NewReader("0123456789")
+	tests := []struct {
+		off     int64
+		seek    int
+		n       int
+		want    string
+		wantpos int64
+		seekerr string
+	}{
+		{seek: os.SEEK_SET, off: 0, n: 20, want: "0123456789"},
+		{seek: os.SEEK_SET, off: 1, n: 1, want: "1"},
+		{seek: os.SEEK_CUR, off: 1, wantpos: 3, n: 2, want: "34"},
+		{seek: os.SEEK_SET, off: -1, seekerr: "strings.Reader.Seek: negative position"},
+		{seek: os.SEEK_SET, off: 1 << 33, wantpos: 1 << 33},
+		{seek: os.SEEK_CUR, off: 1, wantpos: 1<<33 + 1},
+		{seek: os.SEEK_SET, n: 5, want: "01234"},
+		{seek: os.SEEK_CUR, n: 5, want: "56789"},
+		{seek: os.SEEK_END, off: -1, n: 1, wantpos: 9, want: "9"},
+	}
+
+	for i, tt := range tests {
+		pos, err := r.Seek(tt.off, tt.seek)
+		if err == nil && tt.seekerr != "" {
+			t.Errorf("%d. want seek error %q", i, tt.seekerr)
+			continue
+		}
+		if err != nil && err.Error() != tt.seekerr {
+			t.Errorf("%d. seek error = %q; want %q", i, err.Error(), tt.seekerr)
+			continue
+		}
+		if tt.wantpos != 0 && tt.wantpos != pos {
+			t.Errorf("%d. pos = %d, want %d", i, pos, tt.wantpos)
+		}
+		buf := make([]byte, tt.n)
+		n, err := r.Read(buf)
+		if err != nil {
+			t.Errorf("%d. read = %v", i, err)
+			continue
+		}
+		got := string(buf[:n])
+		if got != tt.want {
+			t.Errorf("%d. got %q; want %q", i, got, tt.want)
+		}
+	}
+}
+
+func TestReadAfterBigSeek(t *testing.T) {
+	r := strings.NewReader("0123456789")
+	if _, err := r.Seek(1<<31+5, os.SEEK_SET); err != nil {
+		t.Fatal(err)
+	}
+	if n, err := r.Read(make([]byte, 10)); n != 0 || err != io.EOF {
+		t.Errorf("Read = %d, %v; want 0, EOF", n, err)
+	}
+}
+
+func TestReaderAt(t *testing.T) {
+	r := strings.NewReader("0123456789")
+	tests := []struct {
+		off     int64
+		n       int
+		want    string
+		wanterr interface{}
+	}{
+		{0, 10, "0123456789", nil},
+		{1, 10, "123456789", io.EOF},
+		{1, 9, "123456789", nil},
+		{11, 10, "", io.EOF},
+		{0, 0, "", nil},
+		{-1, 0, "", "strings.Reader.ReadAt: negative offset"},
+	}
+	for i, tt := range tests {
+		b := make([]byte, tt.n)
+		rn, err := r.ReadAt(b, tt.off)
+		got := string(b[:rn])
+		if got != tt.want {
+			t.Errorf("%d. got %q; want %q", i, got, tt.want)
+		}
+		if fmt.Sprintf("%v", err) != fmt.Sprintf("%v", tt.wanterr) {
+			t.Errorf("%d. got error = %v; want %v", i, err, tt.wanterr)
+		}
+	}
+}
+
+func TestReaderAtConcurrent(t *testing.T) {
+	// Test for the race detector, to verify ReadAt doesn't mutate
+	// any state.
+	r := strings.NewReader("0123456789")
+	var wg sync.WaitGroup
+	for i := 0; i < 5; i++ {
+		wg.Add(1)
+		go func(i int) {
+			defer wg.Done()
+			var buf [1]byte
+			r.ReadAt(buf[:], int64(i))
+		}(i)
+	}
+	wg.Wait()
+}
+
+func TestEmptyReaderConcurrent(t *testing.T) {
+	// Test for the race detector, to verify a Read that doesn't yield any bytes
+	// is okay to use from multiple goroutines. This was our historic behavior.
+	// See golang.org/issue/7856
+	r := strings.NewReader("")
+	var wg sync.WaitGroup
+	for i := 0; i < 5; i++ {
+		wg.Add(2)
+		go func() {
+			defer wg.Done()
+			var buf [1]byte
+			r.Read(buf[:])
+		}()
+		go func() {
+			defer wg.Done()
+			r.Read(nil)
+		}()
+	}
+	wg.Wait()
+}
+
+func TestWriteTo(t *testing.T) {
+	const str = "0123456789"
+	for i := 0; i <= len(str); i++ {
+		s := str[i:]
+		r := strings.NewReader(s)
+		var b bytes.Buffer
+		n, err := r.WriteTo(&b)
+		if expect := int64(len(s)); n != expect {
+			t.Errorf("got %v; want %v", n, expect)
+		}
+		if err != nil {
+			t.Errorf("for length %d: got error = %v; want nil", len(s), err)
+		}
+		if b.String() != s {
+			t.Errorf("got string %q; want %q", b.String(), s)
+		}
+		if r.Len() != 0 {
+			t.Errorf("reader contains %v bytes; want 0", r.Len())
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/strings/replace.go b/third_party/gofrontend/libgo/go/strings/replace.go
new file mode 100644
index 0000000..3e05d20
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/replace.go
@@ -0,0 +1,549 @@
+// 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.
+
+package strings
+
+import "io"
+
+// A Replacer replaces a list of strings with replacements.
+type Replacer struct {
+	r replacer
+}
+
+// replacer is the interface that a replacement algorithm needs to implement.
+type replacer interface {
+	Replace(s string) string
+	WriteString(w io.Writer, s string) (n int, err error)
+}
+
+// byteBitmap represents bytes which are sought for replacement.
+// byteBitmap is 256 bits wide, with a bit set for each old byte to be
+// replaced.
+type byteBitmap [256 / 32]uint32
+
+func (m *byteBitmap) set(b byte) {
+	m[b>>5] |= uint32(1 << (b & 31))
+}
+
+// NewReplacer returns a new Replacer from a list of old, new string pairs.
+// Replacements are performed in order, without overlapping matches.
+func NewReplacer(oldnew ...string) *Replacer {
+	if len(oldnew)%2 == 1 {
+		panic("strings.NewReplacer: odd argument count")
+	}
+
+	if len(oldnew) == 2 && len(oldnew[0]) > 1 {
+		return &Replacer{r: makeSingleStringReplacer(oldnew[0], oldnew[1])}
+	}
+
+	allNewBytes := true
+	for i := 0; i < len(oldnew); i += 2 {
+		if len(oldnew[i]) != 1 {
+			return &Replacer{r: makeGenericReplacer(oldnew)}
+		}
+		if len(oldnew[i+1]) != 1 {
+			allNewBytes = false
+		}
+	}
+
+	if allNewBytes {
+		bb := &byteReplacer{}
+		for i := 0; i < len(oldnew); i += 2 {
+			o, n := oldnew[i][0], oldnew[i+1][0]
+			if bb.old[o>>5]&uint32(1<<(o&31)) != 0 {
+				// Later old->new maps do not override previous ones with the same old string.
+				continue
+			}
+			bb.old.set(o)
+			bb.new[o] = n
+		}
+		return &Replacer{r: bb}
+	}
+
+	bs := &byteStringReplacer{}
+	for i := 0; i < len(oldnew); i += 2 {
+		o, new := oldnew[i][0], oldnew[i+1]
+		if bs.old[o>>5]&uint32(1<<(o&31)) != 0 {
+			// Later old->new maps do not override previous ones with the same old string.
+			continue
+		}
+		bs.old.set(o)
+		bs.new[o] = []byte(new)
+	}
+	return &Replacer{r: bs}
+}
+
+// Replace returns a copy of s with all replacements performed.
+func (r *Replacer) Replace(s string) string {
+	return r.r.Replace(s)
+}
+
+// WriteString writes s to w with all replacements performed.
+func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error) {
+	return r.r.WriteString(w, s)
+}
+
+// trieNode is a node in a lookup trie for prioritized key/value pairs. Keys
+// and values may be empty. For example, the trie containing keys "ax", "ay",
+// "bcbc", "x" and "xy" could have eight nodes:
+//
+//  n0  -
+//  n1  a-
+//  n2  .x+
+//  n3  .y+
+//  n4  b-
+//  n5  .cbc+
+//  n6  x+
+//  n7  .y+
+//
+// n0 is the root node, and its children are n1, n4 and n6; n1's children are
+// n2 and n3; n4's child is n5; n6's child is n7. Nodes n0, n1 and n4 (marked
+// with a trailing "-") are partial keys, and nodes n2, n3, n5, n6 and n7
+// (marked with a trailing "+") are complete keys.
+type trieNode struct {
+	// value is the value of the trie node's key/value pair. It is empty if
+	// this node is not a complete key.
+	value string
+	// priority is the priority (higher is more important) of the trie node's
+	// key/value pair; keys are not necessarily matched shortest- or longest-
+	// first. Priority is positive if this node is a complete key, and zero
+	// otherwise. In the example above, positive/zero priorities are marked
+	// with a trailing "+" or "-".
+	priority int
+
+	// A trie node may have zero, one or more child nodes:
+	//  * if the remaining fields are zero, there are no children.
+	//  * if prefix and next are non-zero, there is one child in next.
+	//  * if table is non-zero, it defines all the children.
+	//
+	// Prefixes are preferred over tables when there is one child, but the
+	// root node always uses a table for lookup efficiency.
+
+	// prefix is the difference in keys between this trie node and the next.
+	// In the example above, node n4 has prefix "cbc" and n4's next node is n5.
+	// Node n5 has no children and so has zero prefix, next and table fields.
+	prefix string
+	next   *trieNode
+
+	// table is a lookup table indexed by the next byte in the key, after
+	// remapping that byte through genericReplacer.mapping to create a dense
+	// index. In the example above, the keys only use 'a', 'b', 'c', 'x' and
+	// 'y', which remap to 0, 1, 2, 3 and 4. All other bytes remap to 5, and
+	// genericReplacer.tableSize will be 5. Node n0's table will be
+	// []*trieNode{ 0:n1, 1:n4, 3:n6 }, where the 0, 1 and 3 are the remapped
+	// 'a', 'b' and 'x'.
+	table []*trieNode
+}
+
+func (t *trieNode) add(key, val string, priority int, r *genericReplacer) {
+	if key == "" {
+		if t.priority == 0 {
+			t.value = val
+			t.priority = priority
+		}
+		return
+	}
+
+	if t.prefix != "" {
+		// Need to split the prefix among multiple nodes.
+		var n int // length of the longest common prefix
+		for ; n < len(t.prefix) && n < len(key); n++ {
+			if t.prefix[n] != key[n] {
+				break
+			}
+		}
+		if n == len(t.prefix) {
+			t.next.add(key[n:], val, priority, r)
+		} else if n == 0 {
+			// First byte differs, start a new lookup table here. Looking up
+			// what is currently t.prefix[0] will lead to prefixNode, and
+			// looking up key[0] will lead to keyNode.
+			var prefixNode *trieNode
+			if len(t.prefix) == 1 {
+				prefixNode = t.next
+			} else {
+				prefixNode = &trieNode{
+					prefix: t.prefix[1:],
+					next:   t.next,
+				}
+			}
+			keyNode := new(trieNode)
+			t.table = make([]*trieNode, r.tableSize)
+			t.table[r.mapping[t.prefix[0]]] = prefixNode
+			t.table[r.mapping[key[0]]] = keyNode
+			t.prefix = ""
+			t.next = nil
+			keyNode.add(key[1:], val, priority, r)
+		} else {
+			// Insert new node after the common section of the prefix.
+			next := &trieNode{
+				prefix: t.prefix[n:],
+				next:   t.next,
+			}
+			t.prefix = t.prefix[:n]
+			t.next = next
+			next.add(key[n:], val, priority, r)
+		}
+	} else if t.table != nil {
+		// Insert into existing table.
+		m := r.mapping[key[0]]
+		if t.table[m] == nil {
+			t.table[m] = new(trieNode)
+		}
+		t.table[m].add(key[1:], val, priority, r)
+	} else {
+		t.prefix = key
+		t.next = new(trieNode)
+		t.next.add("", val, priority, r)
+	}
+}
+
+func (r *genericReplacer) lookup(s string, ignoreRoot bool) (val string, keylen int, found bool) {
+	// Iterate down the trie to the end, and grab the value and keylen with
+	// the highest priority.
+	bestPriority := 0
+	node := &r.root
+	n := 0
+	for node != nil {
+		if node.priority > bestPriority && !(ignoreRoot && node == &r.root) {
+			bestPriority = node.priority
+			val = node.value
+			keylen = n
+			found = true
+		}
+
+		if s == "" {
+			break
+		}
+		if node.table != nil {
+			index := r.mapping[s[0]]
+			if int(index) == r.tableSize {
+				break
+			}
+			node = node.table[index]
+			s = s[1:]
+			n++
+		} else if node.prefix != "" && HasPrefix(s, node.prefix) {
+			n += len(node.prefix)
+			s = s[len(node.prefix):]
+			node = node.next
+		} else {
+			break
+		}
+	}
+	return
+}
+
+// genericReplacer is the fully generic algorithm.
+// It's used as a fallback when nothing faster can be used.
+type genericReplacer struct {
+	root trieNode
+	// tableSize is the size of a trie node's lookup table. It is the number
+	// of unique key bytes.
+	tableSize int
+	// mapping maps from key bytes to a dense index for trieNode.table.
+	mapping [256]byte
+}
+
+func makeGenericReplacer(oldnew []string) *genericReplacer {
+	r := new(genericReplacer)
+	// Find each byte used, then assign them each an index.
+	for i := 0; i < len(oldnew); i += 2 {
+		key := oldnew[i]
+		for j := 0; j < len(key); j++ {
+			r.mapping[key[j]] = 1
+		}
+	}
+
+	for _, b := range r.mapping {
+		r.tableSize += int(b)
+	}
+
+	var index byte
+	for i, b := range r.mapping {
+		if b == 0 {
+			r.mapping[i] = byte(r.tableSize)
+		} else {
+			r.mapping[i] = index
+			index++
+		}
+	}
+	// Ensure root node uses a lookup table (for performance).
+	r.root.table = make([]*trieNode, r.tableSize)
+
+	for i := 0; i < len(oldnew); i += 2 {
+		r.root.add(oldnew[i], oldnew[i+1], len(oldnew)-i, r)
+	}
+	return r
+}
+
+type appendSliceWriter []byte
+
+// Write writes to the buffer to satisfy io.Writer.
+func (w *appendSliceWriter) Write(p []byte) (int, error) {
+	*w = append(*w, p...)
+	return len(p), nil
+}
+
+// WriteString writes to the buffer without string->[]byte->string allocations.
+func (w *appendSliceWriter) WriteString(s string) (int, error) {
+	*w = append(*w, s...)
+	return len(s), nil
+}
+
+type stringWriterIface interface {
+	WriteString(string) (int, error)
+}
+
+type stringWriter struct {
+	w io.Writer
+}
+
+func (w stringWriter) WriteString(s string) (int, error) {
+	return w.w.Write([]byte(s))
+}
+
+func getStringWriter(w io.Writer) stringWriterIface {
+	sw, ok := w.(stringWriterIface)
+	if !ok {
+		sw = stringWriter{w}
+	}
+	return sw
+}
+
+func (r *genericReplacer) Replace(s string) string {
+	buf := make(appendSliceWriter, 0, len(s))
+	r.WriteString(&buf, s)
+	return string(buf)
+}
+
+func (r *genericReplacer) WriteString(w io.Writer, s string) (n int, err error) {
+	sw := getStringWriter(w)
+	var last, wn int
+	var prevMatchEmpty bool
+	for i := 0; i <= len(s); {
+		// Ignore the empty match iff the previous loop found the empty match.
+		val, keylen, match := r.lookup(s[i:], prevMatchEmpty)
+		prevMatchEmpty = match && keylen == 0
+		if match {
+			wn, err = sw.WriteString(s[last:i])
+			n += wn
+			if err != nil {
+				return
+			}
+			wn, err = sw.WriteString(val)
+			n += wn
+			if err != nil {
+				return
+			}
+			i += keylen
+			last = i
+			continue
+		}
+		i++
+	}
+	if last != len(s) {
+		wn, err = sw.WriteString(s[last:])
+		n += wn
+	}
+	return
+}
+
+// singleStringReplacer is the implementation that's used when there is only
+// one string to replace (and that string has more than one byte).
+type singleStringReplacer struct {
+	finder *stringFinder
+	// value is the new string that replaces that pattern when it's found.
+	value string
+}
+
+func makeSingleStringReplacer(pattern string, value string) *singleStringReplacer {
+	return &singleStringReplacer{finder: makeStringFinder(pattern), value: value}
+}
+
+func (r *singleStringReplacer) Replace(s string) string {
+	var buf []byte
+	i, matched := 0, false
+	for {
+		match := r.finder.next(s[i:])
+		if match == -1 {
+			break
+		}
+		matched = true
+		buf = append(buf, s[i:i+match]...)
+		buf = append(buf, r.value...)
+		i += match + len(r.finder.pattern)
+	}
+	if !matched {
+		return s
+	}
+	buf = append(buf, s[i:]...)
+	return string(buf)
+}
+
+func (r *singleStringReplacer) WriteString(w io.Writer, s string) (n int, err error) {
+	sw := getStringWriter(w)
+	var i, wn int
+	for {
+		match := r.finder.next(s[i:])
+		if match == -1 {
+			break
+		}
+		wn, err = sw.WriteString(s[i : i+match])
+		n += wn
+		if err != nil {
+			return
+		}
+		wn, err = sw.WriteString(r.value)
+		n += wn
+		if err != nil {
+			return
+		}
+		i += match + len(r.finder.pattern)
+	}
+	wn, err = sw.WriteString(s[i:])
+	n += wn
+	return
+}
+
+// byteReplacer is the implementation that's used when all the "old"
+// and "new" values are single ASCII bytes.
+type byteReplacer struct {
+	// old has a bit set for each old byte that should be replaced.
+	old byteBitmap
+
+	// replacement byte, indexed by old byte. only valid if
+	// corresponding old bit is set.
+	new [256]byte
+}
+
+func (r *byteReplacer) Replace(s string) string {
+	var buf []byte // lazily allocated
+	for i := 0; i < len(s); i++ {
+		b := s[i]
+		if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+			if buf == nil {
+				buf = []byte(s)
+			}
+			buf[i] = r.new[b]
+		}
+	}
+	if buf == nil {
+		return s
+	}
+	return string(buf)
+}
+
+func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) {
+	// TODO(bradfitz): use io.WriteString with slices of s, avoiding allocation.
+	bufsize := 32 << 10
+	if len(s) < bufsize {
+		bufsize = len(s)
+	}
+	buf := make([]byte, bufsize)
+
+	for len(s) > 0 {
+		ncopy := copy(buf, s[:])
+		s = s[ncopy:]
+		for i, b := range buf[:ncopy] {
+			if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+				buf[i] = r.new[b]
+			}
+		}
+		wn, err := w.Write(buf[:ncopy])
+		n += wn
+		if err != nil {
+			return n, err
+		}
+	}
+	return n, nil
+}
+
+// byteStringReplacer is the implementation that's used when all the
+// "old" values are single ASCII bytes but the "new" values vary in
+// size.
+type byteStringReplacer struct {
+	// old has a bit set for each old byte that should be replaced.
+	old byteBitmap
+
+	// replacement string, indexed by old byte. only valid if
+	// corresponding old bit is set.
+	new [256][]byte
+}
+
+func (r *byteStringReplacer) Replace(s string) string {
+	newSize := 0
+	anyChanges := false
+	for i := 0; i < len(s); i++ {
+		b := s[i]
+		if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+			anyChanges = true
+			newSize += len(r.new[b])
+		} else {
+			newSize++
+		}
+	}
+	if !anyChanges {
+		return s
+	}
+	buf := make([]byte, newSize)
+	bi := buf
+	for i := 0; i < len(s); i++ {
+		b := s[i]
+		if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+			n := copy(bi, r.new[b])
+			bi = bi[n:]
+		} else {
+			bi[0] = b
+			bi = bi[1:]
+		}
+	}
+	return string(buf)
+}
+
+// WriteString maintains one buffer that's at most 32KB.  The bytes in
+// s are enumerated and the buffer is filled.  If it reaches its
+// capacity or a byte has a replacement, the buffer is flushed to w.
+func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err error) {
+	// TODO(bradfitz): use io.WriteString with slices of s instead.
+	bufsize := 32 << 10
+	if len(s) < bufsize {
+		bufsize = len(s)
+	}
+	buf := make([]byte, bufsize)
+	bi := buf[:0]
+
+	for i := 0; i < len(s); i++ {
+		b := s[i]
+		var new []byte
+		if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+			new = r.new[b]
+		} else {
+			bi = append(bi, b)
+		}
+		if len(bi) == cap(bi) || (len(bi) > 0 && len(new) > 0) {
+			nw, err := w.Write(bi)
+			n += nw
+			if err != nil {
+				return n, err
+			}
+			bi = buf[:0]
+		}
+		if len(new) > 0 {
+			nw, err := w.Write(new)
+			n += nw
+			if err != nil {
+				return n, err
+			}
+		}
+	}
+	if len(bi) > 0 {
+		nw, err := w.Write(bi)
+		n += nw
+		if err != nil {
+			return n, err
+		}
+	}
+	return n, nil
+}
diff --git a/third_party/gofrontend/libgo/go/strings/replace_test.go b/third_party/gofrontend/libgo/go/strings/replace_test.go
new file mode 100644
index 0000000..82e4b6e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/replace_test.go
@@ -0,0 +1,506 @@
+// 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 strings_test
+
+import (
+	"bytes"
+	"fmt"
+	. "strings"
+	"testing"
+)
+
+var htmlEscaper = NewReplacer(
+	"&", "&amp;",
+	"<", "&lt;",
+	">", "&gt;",
+	`"`, "&quot;",
+	"'", "&apos;",
+)
+
+var htmlUnescaper = NewReplacer(
+	"&amp;", "&",
+	"&lt;", "<",
+	"&gt;", ">",
+	"&quot;", `"`,
+	"&apos;", "'",
+)
+
+// The http package's old HTML escaping function.
+func oldHTMLEscape(s string) string {
+	s = Replace(s, "&", "&amp;", -1)
+	s = Replace(s, "<", "&lt;", -1)
+	s = Replace(s, ">", "&gt;", -1)
+	s = Replace(s, `"`, "&quot;", -1)
+	s = Replace(s, "'", "&apos;", -1)
+	return s
+}
+
+var capitalLetters = NewReplacer("a", "A", "b", "B")
+
+// TestReplacer tests the replacer implementations.
+func TestReplacer(t *testing.T) {
+	type testCase struct {
+		r       *Replacer
+		in, out string
+	}
+	var testCases []testCase
+
+	// str converts 0xff to "\xff". This isn't just string(b) since that converts to UTF-8.
+	str := func(b byte) string {
+		return string([]byte{b})
+	}
+	var s []string
+
+	// inc maps "\x00"->"\x01", ..., "a"->"b", "b"->"c", ..., "\xff"->"\x00".
+	s = nil
+	for i := 0; i < 256; i++ {
+		s = append(s, str(byte(i)), str(byte(i+1)))
+	}
+	inc := NewReplacer(s...)
+
+	// Test cases with 1-byte old strings, 1-byte new strings.
+	testCases = append(testCases,
+		testCase{capitalLetters, "brad", "BrAd"},
+		testCase{capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)},
+		testCase{capitalLetters, "", ""},
+
+		testCase{inc, "brad", "csbe"},
+		testCase{inc, "\x00\xff", "\x01\x00"},
+		testCase{inc, "", ""},
+
+		testCase{NewReplacer("a", "1", "a", "2"), "brad", "br1d"},
+	)
+
+	// repeat maps "a"->"a", "b"->"bb", "c"->"ccc", ...
+	s = nil
+	for i := 0; i < 256; i++ {
+		n := i + 1 - 'a'
+		if n < 1 {
+			n = 1
+		}
+		s = append(s, str(byte(i)), Repeat(str(byte(i)), n))
+	}
+	repeat := NewReplacer(s...)
+
+	// Test cases with 1-byte old strings, variable length new strings.
+	testCases = append(testCases,
+		testCase{htmlEscaper, "No changes", "No changes"},
+		testCase{htmlEscaper, "I <3 escaping & stuff", "I &lt;3 escaping &amp; stuff"},
+		testCase{htmlEscaper, "&&&", "&amp;&amp;&amp;"},
+		testCase{htmlEscaper, "", ""},
+
+		testCase{repeat, "brad", "bbrrrrrrrrrrrrrrrrrradddd"},
+		testCase{repeat, "abba", "abbbba"},
+		testCase{repeat, "", ""},
+
+		testCase{NewReplacer("a", "11", "a", "22"), "brad", "br11d"},
+	)
+
+	// The remaining test cases have variable length old strings.
+
+	testCases = append(testCases,
+		testCase{htmlUnescaper, "&amp;amp;", "&amp;"},
+		testCase{htmlUnescaper, "&lt;b&gt;HTML&apos;s neat&lt;/b&gt;", "<b>HTML's neat</b>"},
+		testCase{htmlUnescaper, "", ""},
+
+		testCase{NewReplacer("a", "1", "a", "2", "xxx", "xxx"), "brad", "br1d"},
+
+		testCase{NewReplacer("a", "1", "aa", "2", "aaa", "3"), "aaaa", "1111"},
+
+		testCase{NewReplacer("aaa", "3", "aa", "2", "a", "1"), "aaaa", "31"},
+	)
+
+	// gen1 has multiple old strings of variable length. There is no
+	// overall non-empty common prefix, but some pairwise common prefixes.
+	gen1 := NewReplacer(
+		"aaa", "3[aaa]",
+		"aa", "2[aa]",
+		"a", "1[a]",
+		"i", "i",
+		"longerst", "most long",
+		"longer", "medium",
+		"long", "short",
+		"xx", "xx",
+		"x", "X",
+		"X", "Y",
+		"Y", "Z",
+	)
+	testCases = append(testCases,
+		testCase{gen1, "fooaaabar", "foo3[aaa]b1[a]r"},
+		testCase{gen1, "long, longerst, longer", "short, most long, medium"},
+		testCase{gen1, "xxxxx", "xxxxX"},
+		testCase{gen1, "XiX", "YiY"},
+		testCase{gen1, "", ""},
+	)
+
+	// gen2 has multiple old strings with no pairwise common prefix.
+	gen2 := NewReplacer(
+		"roses", "red",
+		"violets", "blue",
+		"sugar", "sweet",
+	)
+	testCases = append(testCases,
+		testCase{gen2, "roses are red, violets are blue...", "red are red, blue are blue..."},
+		testCase{gen2, "", ""},
+	)
+
+	// gen3 has multiple old strings with an overall common prefix.
+	gen3 := NewReplacer(
+		"abracadabra", "poof",
+		"abracadabrakazam", "splat",
+		"abraham", "lincoln",
+		"abrasion", "scrape",
+		"abraham", "isaac",
+	)
+	testCases = append(testCases,
+		testCase{gen3, "abracadabrakazam abraham", "poofkazam lincoln"},
+		testCase{gen3, "abrasion abracad", "scrape abracad"},
+		testCase{gen3, "abba abram abrasive", "abba abram abrasive"},
+		testCase{gen3, "", ""},
+	)
+
+	// foo{1,2,3,4} have multiple old strings with an overall common prefix
+	// and 1- or 2- byte extensions from the common prefix.
+	foo1 := NewReplacer(
+		"foo1", "A",
+		"foo2", "B",
+		"foo3", "C",
+	)
+	foo2 := NewReplacer(
+		"foo1", "A",
+		"foo2", "B",
+		"foo31", "C",
+		"foo32", "D",
+	)
+	foo3 := NewReplacer(
+		"foo11", "A",
+		"foo12", "B",
+		"foo31", "C",
+		"foo32", "D",
+	)
+	foo4 := NewReplacer(
+		"foo12", "B",
+		"foo32", "D",
+	)
+	testCases = append(testCases,
+		testCase{foo1, "fofoofoo12foo32oo", "fofooA2C2oo"},
+		testCase{foo1, "", ""},
+
+		testCase{foo2, "fofoofoo12foo32oo", "fofooA2Doo"},
+		testCase{foo2, "", ""},
+
+		testCase{foo3, "fofoofoo12foo32oo", "fofooBDoo"},
+		testCase{foo3, "", ""},
+
+		testCase{foo4, "fofoofoo12foo32oo", "fofooBDoo"},
+		testCase{foo4, "", ""},
+	)
+
+	// genAll maps "\x00\x01\x02...\xfe\xff" to "[all]", amongst other things.
+	allBytes := make([]byte, 256)
+	for i := range allBytes {
+		allBytes[i] = byte(i)
+	}
+	allString := string(allBytes)
+	genAll := NewReplacer(
+		allString, "[all]",
+		"\xff", "[ff]",
+		"\x00", "[00]",
+	)
+	testCases = append(testCases,
+		testCase{genAll, allString, "[all]"},
+		testCase{genAll, "a\xff" + allString + "\x00", "a[ff][all][00]"},
+		testCase{genAll, "", ""},
+	)
+
+	// Test cases with empty old strings.
+
+	blankToX1 := NewReplacer("", "X")
+	blankToX2 := NewReplacer("", "X", "", "")
+	blankHighPriority := NewReplacer("", "X", "o", "O")
+	blankLowPriority := NewReplacer("o", "O", "", "X")
+	blankNoOp1 := NewReplacer("", "")
+	blankNoOp2 := NewReplacer("", "", "", "A")
+	blankFoo := NewReplacer("", "X", "foobar", "R", "foobaz", "Z")
+	testCases = append(testCases,
+		testCase{blankToX1, "foo", "XfXoXoX"},
+		testCase{blankToX1, "", "X"},
+
+		testCase{blankToX2, "foo", "XfXoXoX"},
+		testCase{blankToX2, "", "X"},
+
+		testCase{blankHighPriority, "oo", "XOXOX"},
+		testCase{blankHighPriority, "ii", "XiXiX"},
+		testCase{blankHighPriority, "oiio", "XOXiXiXOX"},
+		testCase{blankHighPriority, "iooi", "XiXOXOXiX"},
+		testCase{blankHighPriority, "", "X"},
+
+		testCase{blankLowPriority, "oo", "OOX"},
+		testCase{blankLowPriority, "ii", "XiXiX"},
+		testCase{blankLowPriority, "oiio", "OXiXiOX"},
+		testCase{blankLowPriority, "iooi", "XiOOXiX"},
+		testCase{blankLowPriority, "", "X"},
+
+		testCase{blankNoOp1, "foo", "foo"},
+		testCase{blankNoOp1, "", ""},
+
+		testCase{blankNoOp2, "foo", "foo"},
+		testCase{blankNoOp2, "", ""},
+
+		testCase{blankFoo, "foobarfoobaz", "XRXZX"},
+		testCase{blankFoo, "foobar-foobaz", "XRX-XZX"},
+		testCase{blankFoo, "", "X"},
+	)
+
+	// single string replacer
+
+	abcMatcher := NewReplacer("abc", "[match]")
+
+	testCases = append(testCases,
+		testCase{abcMatcher, "", ""},
+		testCase{abcMatcher, "ab", "ab"},
+		testCase{abcMatcher, "abc", "[match]"},
+		testCase{abcMatcher, "abcd", "[match]d"},
+		testCase{abcMatcher, "cabcabcdabca", "c[match][match]d[match]a"},
+	)
+
+	// Issue 6659 cases (more single string replacer)
+
+	noHello := NewReplacer("Hello", "")
+	testCases = append(testCases,
+		testCase{noHello, "Hello", ""},
+		testCase{noHello, "Hellox", "x"},
+		testCase{noHello, "xHello", "x"},
+		testCase{noHello, "xHellox", "xx"},
+	)
+
+	// No-arg test cases.
+
+	nop := NewReplacer()
+	testCases = append(testCases,
+		testCase{nop, "abc", "abc"},
+		testCase{nop, "", ""},
+	)
+
+	// Run the test cases.
+
+	for i, tc := range testCases {
+		if s := tc.r.Replace(tc.in); s != tc.out {
+			t.Errorf("%d. Replace(%q) = %q, want %q", i, tc.in, s, tc.out)
+		}
+		var buf bytes.Buffer
+		n, err := tc.r.WriteString(&buf, tc.in)
+		if err != nil {
+			t.Errorf("%d. WriteString: %v", i, err)
+			continue
+		}
+		got := buf.String()
+		if got != tc.out {
+			t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tc.in, got, tc.out)
+			continue
+		}
+		if n != len(tc.out) {
+			t.Errorf("%d. WriteString(%q) wrote correct string but reported %d bytes; want %d (%q)",
+				i, tc.in, n, len(tc.out), tc.out)
+		}
+	}
+}
+
+// TestPickAlgorithm tests that NewReplacer picks the correct algorithm.
+func TestPickAlgorithm(t *testing.T) {
+	testCases := []struct {
+		r    *Replacer
+		want string
+	}{
+		{capitalLetters, "*strings.byteReplacer"},
+		{htmlEscaper, "*strings.byteStringReplacer"},
+		{NewReplacer("12", "123"), "*strings.singleStringReplacer"},
+		{NewReplacer("1", "12"), "*strings.byteStringReplacer"},
+		{NewReplacer("", "X"), "*strings.genericReplacer"},
+		{NewReplacer("a", "1", "b", "12", "cde", "123"), "*strings.genericReplacer"},
+	}
+	for i, tc := range testCases {
+		got := fmt.Sprintf("%T", tc.r.Replacer())
+		if got != tc.want {
+			t.Errorf("%d. algorithm = %s, want %s", i, got, tc.want)
+		}
+	}
+}
+
+// TestGenericTrieBuilding verifies the structure of the generated trie. There
+// is one node per line, and the key ending with the current line is in the
+// trie if it ends with a "+".
+func TestGenericTrieBuilding(t *testing.T) {
+	testCases := []struct{ in, out string }{
+		{"abc;abdef;abdefgh;xx;xy;z", `-
+			a-
+			.b-
+			..c+
+			..d-
+			...ef+
+			.....gh+
+			x-
+			.x+
+			.y+
+			z+
+			`},
+		{"abracadabra;abracadabrakazam;abraham;abrasion", `-
+			a-
+			.bra-
+			....c-
+			.....adabra+
+			...........kazam+
+			....h-
+			.....am+
+			....s-
+			.....ion+
+			`},
+		{"aaa;aa;a;i;longerst;longer;long;xx;x;X;Y", `-
+			X+
+			Y+
+			a+
+			.a+
+			..a+
+			i+
+			l-
+			.ong+
+			....er+
+			......st+
+			x+
+			.x+
+			`},
+		{"foo;;foo;foo1", `+
+			f-
+			.oo+
+			...1+
+			`},
+	}
+
+	for _, tc := range testCases {
+		keys := Split(tc.in, ";")
+		args := make([]string, len(keys)*2)
+		for i, key := range keys {
+			args[i*2] = key
+		}
+
+		got := NewReplacer(args...).PrintTrie()
+		// Remove tabs from tc.out
+		wantbuf := make([]byte, 0, len(tc.out))
+		for i := 0; i < len(tc.out); i++ {
+			if tc.out[i] != '\t' {
+				wantbuf = append(wantbuf, tc.out[i])
+			}
+		}
+		want := string(wantbuf)
+
+		if got != want {
+			t.Errorf("PrintTrie(%q)\ngot\n%swant\n%s", tc.in, got, want)
+		}
+	}
+}
+
+func BenchmarkGenericNoMatch(b *testing.B) {
+	str := Repeat("A", 100) + Repeat("B", 100)
+	generic := NewReplacer("a", "A", "b", "B", "12", "123") // varying lengths forces generic
+	for i := 0; i < b.N; i++ {
+		generic.Replace(str)
+	}
+}
+
+func BenchmarkGenericMatch1(b *testing.B) {
+	str := Repeat("a", 100) + Repeat("b", 100)
+	generic := NewReplacer("a", "A", "b", "B", "12", "123")
+	for i := 0; i < b.N; i++ {
+		generic.Replace(str)
+	}
+}
+
+func BenchmarkGenericMatch2(b *testing.B) {
+	str := Repeat("It&apos;s &lt;b&gt;HTML&lt;/b&gt;!", 100)
+	for i := 0; i < b.N; i++ {
+		htmlUnescaper.Replace(str)
+	}
+}
+
+func benchmarkSingleString(b *testing.B, pattern, text string) {
+	r := NewReplacer(pattern, "[match]")
+	b.SetBytes(int64(len(text)))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		r.Replace(text)
+	}
+}
+
+func BenchmarkSingleMaxSkipping(b *testing.B) {
+	benchmarkSingleString(b, Repeat("b", 25), Repeat("a", 10000))
+}
+
+func BenchmarkSingleLongSuffixFail(b *testing.B) {
+	benchmarkSingleString(b, "b"+Repeat("a", 500), Repeat("a", 1002))
+}
+
+func BenchmarkSingleMatch(b *testing.B) {
+	benchmarkSingleString(b, "abcdef", Repeat("abcdefghijklmno", 1000))
+}
+
+func BenchmarkByteByteNoMatch(b *testing.B) {
+	str := Repeat("A", 100) + Repeat("B", 100)
+	for i := 0; i < b.N; i++ {
+		capitalLetters.Replace(str)
+	}
+}
+
+func BenchmarkByteByteMatch(b *testing.B) {
+	str := Repeat("a", 100) + Repeat("b", 100)
+	for i := 0; i < b.N; i++ {
+		capitalLetters.Replace(str)
+	}
+}
+
+func BenchmarkByteStringMatch(b *testing.B) {
+	str := "<" + Repeat("a", 99) + Repeat("b", 99) + ">"
+	for i := 0; i < b.N; i++ {
+		htmlEscaper.Replace(str)
+	}
+}
+
+func BenchmarkHTMLEscapeNew(b *testing.B) {
+	str := "I <3 to escape HTML & other text too."
+	for i := 0; i < b.N; i++ {
+		htmlEscaper.Replace(str)
+	}
+}
+
+func BenchmarkHTMLEscapeOld(b *testing.B) {
+	str := "I <3 to escape HTML & other text too."
+	for i := 0; i < b.N; i++ {
+		oldHTMLEscape(str)
+	}
+}
+
+// BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces.
+func BenchmarkByteByteReplaces(b *testing.B) {
+	str := Repeat("a", 100) + Repeat("b", 100)
+	for i := 0; i < b.N; i++ {
+		Replace(Replace(str, "a", "A", -1), "b", "B", -1)
+	}
+}
+
+// BenchmarkByteByteMap compares byteByteImpl against Map.
+func BenchmarkByteByteMap(b *testing.B) {
+	str := Repeat("a", 100) + Repeat("b", 100)
+	fn := func(r rune) rune {
+		switch r {
+		case 'a':
+			return 'A'
+		case 'b':
+			return 'B'
+		}
+		return r
+	}
+	for i := 0; i < b.N; i++ {
+		Map(fn, str)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/strings/search.go b/third_party/gofrontend/libgo/go/strings/search.go
new file mode 100644
index 0000000..f77c879
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/search.go
@@ -0,0 +1,124 @@
+// 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 strings
+
+// stringFinder efficiently finds strings in a source text. It's implemented
+// using the Boyer-Moore string search algorithm:
+// http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm
+// http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf (note: this aged
+// document uses 1-based indexing)
+type stringFinder struct {
+	// pattern is the string that we are searching for in the text.
+	pattern string
+
+	// badCharSkip[b] contains the distance between the last byte of pattern
+	// and the rightmost occurrence of b in pattern. If b is not in pattern,
+	// badCharSkip[b] is len(pattern).
+	//
+	// Whenever a mismatch is found with byte b in the text, we can safely
+	// shift the matching frame at least badCharSkip[b] until the next time
+	// the matching char could be in alignment.
+	badCharSkip [256]int
+
+	// goodSuffixSkip[i] defines how far we can shift the matching frame given
+	// that the suffix pattern[i+1:] matches, but the byte pattern[i] does
+	// not. There are two cases to consider:
+	//
+	// 1. The matched suffix occurs elsewhere in pattern (with a different
+	// byte preceding it that we might possibly match). In this case, we can
+	// shift the matching frame to align with the next suffix chunk. For
+	// example, the pattern "mississi" has the suffix "issi" next occurring
+	// (in right-to-left order) at index 1, so goodSuffixSkip[3] ==
+	// shift+len(suffix) == 3+4 == 7.
+	//
+	// 2. If the matched suffix does not occur elsewhere in pattern, then the
+	// matching frame may share part of its prefix with the end of the
+	// matching suffix. In this case, goodSuffixSkip[i] will contain how far
+	// to shift the frame to align this portion of the prefix to the
+	// suffix. For example, in the pattern "abcxxxabc", when the first
+	// mismatch from the back is found to be in position 3, the matching
+	// suffix "xxabc" is not found elsewhere in the pattern. However, its
+	// rightmost "abc" (at position 6) is a prefix of the whole pattern, so
+	// goodSuffixSkip[3] == shift+len(suffix) == 6+5 == 11.
+	goodSuffixSkip []int
+}
+
+func makeStringFinder(pattern string) *stringFinder {
+	f := &stringFinder{
+		pattern:        pattern,
+		goodSuffixSkip: make([]int, len(pattern)),
+	}
+	// last is the index of the last character in the pattern.
+	last := len(pattern) - 1
+
+	// Build bad character table.
+	// Bytes not in the pattern can skip one pattern's length.
+	for i := range f.badCharSkip {
+		f.badCharSkip[i] = len(pattern)
+	}
+	// The loop condition is < instead of <= so that the last byte does not
+	// have a zero distance to itself. Finding this byte out of place implies
+	// that it is not in the last position.
+	for i := 0; i < last; i++ {
+		f.badCharSkip[pattern[i]] = last - i
+	}
+
+	// Build good suffix table.
+	// First pass: set each value to the next index which starts a prefix of
+	// pattern.
+	lastPrefix := last
+	for i := last; i >= 0; i-- {
+		if HasPrefix(pattern, pattern[i+1:]) {
+			lastPrefix = i + 1
+		}
+		// lastPrefix is the shift, and (last-i) is len(suffix).
+		f.goodSuffixSkip[i] = lastPrefix + last - i
+	}
+	// Second pass: find repeats of pattern's suffix starting from the front.
+	for i := 0; i < last; i++ {
+		lenSuffix := longestCommonSuffix(pattern, pattern[1:i+1])
+		if pattern[i-lenSuffix] != pattern[last-lenSuffix] {
+			// (last-i) is the shift, and lenSuffix is len(suffix).
+			f.goodSuffixSkip[last-lenSuffix] = lenSuffix + last - i
+		}
+	}
+
+	return f
+}
+
+func longestCommonSuffix(a, b string) (i int) {
+	for ; i < len(a) && i < len(b); i++ {
+		if a[len(a)-1-i] != b[len(b)-1-i] {
+			break
+		}
+	}
+	return
+}
+
+// next returns the index in text of the first occurrence of the pattern. If
+// the pattern is not found, it returns -1.
+func (f *stringFinder) next(text string) int {
+	i := len(f.pattern) - 1
+	for i < len(text) {
+		// Compare backwards from the end until the first unmatching character.
+		j := len(f.pattern) - 1
+		for j >= 0 && text[i] == f.pattern[j] {
+			i--
+			j--
+		}
+		if j < 0 {
+			return i + 1 // match
+		}
+		i += max(f.badCharSkip[text[i]], f.goodSuffixSkip[j])
+	}
+	return -1
+}
+
+func max(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}
diff --git a/third_party/gofrontend/libgo/go/strings/search_test.go b/third_party/gofrontend/libgo/go/strings/search_test.go
new file mode 100644
index 0000000..966c05e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/search_test.go
@@ -0,0 +1,90 @@
+// 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 strings_test
+
+import (
+	"reflect"
+	. "strings"
+	"testing"
+)
+
+func TestFinderNext(t *testing.T) {
+	testCases := []struct {
+		pat, text string
+		index     int
+	}{
+		{"", "", 0},
+		{"", "abc", 0},
+		{"abc", "", -1},
+		{"abc", "abc", 0},
+		{"d", "abcdefg", 3},
+		{"nan", "banana", 2},
+		{"pan", "anpanman", 2},
+		{"nnaaman", "anpanmanam", -1},
+		{"abcd", "abc", -1},
+		{"abcd", "bcd", -1},
+		{"bcd", "abcd", 1},
+		{"abc", "acca", -1},
+		{"aa", "aaa", 0},
+		{"baa", "aaaaa", -1},
+		{"at that", "which finally halts.  at that point", 22},
+	}
+
+	for _, tc := range testCases {
+		got := StringFind(tc.pat, tc.text)
+		want := tc.index
+		if got != want {
+			t.Errorf("stringFind(%q, %q) got %d, want %d\n", tc.pat, tc.text, got, want)
+		}
+	}
+}
+
+func TestFinderCreation(t *testing.T) {
+	testCases := []struct {
+		pattern string
+		bad     [256]int
+		suf     []int
+	}{
+		{
+			"abc",
+			[256]int{'a': 2, 'b': 1, 'c': 3},
+			[]int{5, 4, 1},
+		},
+		{
+			"mississi",
+			[256]int{'i': 3, 'm': 7, 's': 1},
+			[]int{15, 14, 13, 7, 11, 10, 7, 1},
+		},
+		// From http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf
+		{
+			"abcxxxabc",
+			[256]int{'a': 2, 'b': 1, 'c': 6, 'x': 3},
+			[]int{14, 13, 12, 11, 10, 9, 11, 10, 1},
+		},
+		{
+			"abyxcdeyx",
+			[256]int{'a': 8, 'b': 7, 'c': 4, 'd': 3, 'e': 2, 'y': 1, 'x': 5},
+			[]int{17, 16, 15, 14, 13, 12, 7, 10, 1},
+		},
+	}
+
+	for _, tc := range testCases {
+		bad, good := DumpTables(tc.pattern)
+
+		for i, got := range bad {
+			want := tc.bad[i]
+			if want == 0 {
+				want = len(tc.pattern)
+			}
+			if got != want {
+				t.Errorf("boyerMoore(%q) bad['%c']: got %d want %d", tc.pattern, i, got, want)
+			}
+		}
+
+		if !reflect.DeepEqual(good, tc.suf) {
+			t.Errorf("boyerMoore(%q) got %v want %v", tc.pattern, good, tc.suf)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/strings/strings.go b/third_party/gofrontend/libgo/go/strings/strings.go
new file mode 100644
index 0000000..5d46211
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/strings.go
@@ -0,0 +1,725 @@
+// 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 strings implements simple functions to manipulate strings.
+package strings
+
+import (
+	"unicode"
+	"unicode/utf8"
+)
+
+// explode splits s into an array of UTF-8 sequences, one per Unicode character (still strings) up to a maximum of n (n < 0 means no limit).
+// Invalid UTF-8 sequences become correct encodings of U+FFF8.
+func explode(s string, n int) []string {
+	if n == 0 {
+		return nil
+	}
+	l := utf8.RuneCountInString(s)
+	if n <= 0 || n > l {
+		n = l
+	}
+	a := make([]string, n)
+	var size int
+	var ch rune
+	i, cur := 0, 0
+	for ; i+1 < n; i++ {
+		ch, size = utf8.DecodeRuneInString(s[cur:])
+		if ch == utf8.RuneError {
+			a[i] = string(utf8.RuneError)
+		} else {
+			a[i] = s[cur : cur+size]
+		}
+		cur += size
+	}
+	// add the rest, if there is any
+	if cur < len(s) {
+		a[i] = s[cur:]
+	}
+	return a
+}
+
+// primeRK is the prime base used in Rabin-Karp algorithm.
+const primeRK = 16777619
+
+// hashstr returns the hash and the appropriate multiplicative
+// factor for use in Rabin-Karp algorithm.
+func hashstr(sep string) (uint32, uint32) {
+	hash := uint32(0)
+	for i := 0; i < len(sep); i++ {
+		hash = hash*primeRK + uint32(sep[i])
+
+	}
+	var pow, sq uint32 = 1, primeRK
+	for i := len(sep); i > 0; i >>= 1 {
+		if i&1 != 0 {
+			pow *= sq
+		}
+		sq *= sq
+	}
+	return hash, pow
+}
+
+// Count counts the number of non-overlapping instances of sep in s.
+func Count(s, sep string) int {
+	n := 0
+	// special cases
+	switch {
+	case len(sep) == 0:
+		return utf8.RuneCountInString(s) + 1
+	case len(sep) == 1:
+		// special case worth making fast
+		c := sep[0]
+		for i := 0; i < len(s); i++ {
+			if s[i] == c {
+				n++
+			}
+		}
+		return n
+	case len(sep) > len(s):
+		return 0
+	case len(sep) == len(s):
+		if sep == s {
+			return 1
+		}
+		return 0
+	}
+	hashsep, pow := hashstr(sep)
+	h := uint32(0)
+	for i := 0; i < len(sep); i++ {
+		h = h*primeRK + uint32(s[i])
+	}
+	lastmatch := 0
+	if h == hashsep && s[:len(sep)] == sep {
+		n++
+		lastmatch = len(sep)
+	}
+	for i := len(sep); i < len(s); {
+		h *= primeRK
+		h += uint32(s[i])
+		h -= pow * uint32(s[i-len(sep)])
+		i++
+		if h == hashsep && lastmatch <= i-len(sep) && s[i-len(sep):i] == sep {
+			n++
+			lastmatch = i
+		}
+	}
+	return n
+}
+
+// Contains returns true if substr is within s.
+func Contains(s, substr string) bool {
+	return Index(s, substr) >= 0
+}
+
+// ContainsAny returns true if any Unicode code points in chars are within s.
+func ContainsAny(s, chars string) bool {
+	return IndexAny(s, chars) >= 0
+}
+
+// ContainsRune returns true if the Unicode code point r is within s.
+func ContainsRune(s string, r rune) bool {
+	return IndexRune(s, r) >= 0
+}
+
+// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
+func Index(s, sep string) int {
+	n := len(sep)
+	switch {
+	case n == 0:
+		return 0
+	case n == 1:
+		return IndexByte(s, sep[0])
+	case n == len(s):
+		if sep == s {
+			return 0
+		}
+		return -1
+	case n > len(s):
+		return -1
+	}
+	// Hash sep.
+	hashsep, pow := hashstr(sep)
+	var h uint32
+	for i := 0; i < n; i++ {
+		h = h*primeRK + uint32(s[i])
+	}
+	if h == hashsep && s[:n] == sep {
+		return 0
+	}
+	for i := n; i < len(s); {
+		h *= primeRK
+		h += uint32(s[i])
+		h -= pow * uint32(s[i-n])
+		i++
+		if h == hashsep && s[i-n:i] == sep {
+			return i - n
+		}
+	}
+	return -1
+}
+
+// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
+func LastIndex(s, sep string) int {
+	n := len(sep)
+	if n == 0 {
+		return len(s)
+	}
+	c := sep[0]
+	if n == 1 {
+		// special case worth making fast
+		for i := len(s) - 1; i >= 0; i-- {
+			if s[i] == c {
+				return i
+			}
+		}
+		return -1
+	}
+	// n > 1
+	for i := len(s) - n; i >= 0; i-- {
+		if s[i] == c && s[i:i+n] == sep {
+			return i
+		}
+	}
+	return -1
+}
+
+// IndexRune returns the index of the first instance of the Unicode code point
+// r, or -1 if rune is not present in s.
+func IndexRune(s string, r rune) int {
+	switch {
+	case r < 0x80:
+		b := byte(r)
+		for i := 0; i < len(s); i++ {
+			if s[i] == b {
+				return i
+			}
+		}
+	default:
+		for i, c := range s {
+			if c == r {
+				return i
+			}
+		}
+	}
+	return -1
+}
+
+// IndexAny returns the index of the first instance of any Unicode code point
+// from chars in s, or -1 if no Unicode code point from chars is present in s.
+func IndexAny(s, chars string) int {
+	if len(chars) > 0 {
+		for i, c := range s {
+			for _, m := range chars {
+				if c == m {
+					return i
+				}
+			}
+		}
+	}
+	return -1
+}
+
+// LastIndexAny returns the index of the last instance of any Unicode code
+// point from chars in s, or -1 if no Unicode code point from chars is
+// present in s.
+func LastIndexAny(s, chars string) int {
+	if len(chars) > 0 {
+		for i := len(s); i > 0; {
+			rune, size := utf8.DecodeLastRuneInString(s[0:i])
+			i -= size
+			for _, m := range chars {
+				if rune == m {
+					return i
+				}
+			}
+		}
+	}
+	return -1
+}
+
+// Generic split: splits after each instance of sep,
+// including sepSave bytes of sep in the subarrays.
+func genSplit(s, sep string, sepSave, n int) []string {
+	if n == 0 {
+		return nil
+	}
+	if sep == "" {
+		return explode(s, n)
+	}
+	if n < 0 {
+		n = Count(s, sep) + 1
+	}
+	c := sep[0]
+	start := 0
+	a := make([]string, n)
+	na := 0
+	for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ {
+		if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) {
+			a[na] = s[start : i+sepSave]
+			na++
+			start = i + len(sep)
+			i += len(sep) - 1
+		}
+	}
+	a[na] = s[start:]
+	return a[0 : na+1]
+}
+
+// SplitN slices s into substrings separated by sep and returns a slice of
+// the substrings between those separators.
+// If sep is empty, SplitN splits after each UTF-8 sequence.
+// The count determines the number of substrings to return:
+//   n > 0: at most n substrings; the last substring will be the unsplit remainder.
+//   n == 0: the result is nil (zero substrings)
+//   n < 0: all substrings
+func SplitN(s, sep string, n int) []string { return genSplit(s, sep, 0, n) }
+
+// SplitAfterN slices s into substrings after each instance of sep and
+// returns a slice of those substrings.
+// If sep is empty, SplitAfterN splits after each UTF-8 sequence.
+// The count determines the number of substrings to return:
+//   n > 0: at most n substrings; the last substring will be the unsplit remainder.
+//   n == 0: the result is nil (zero substrings)
+//   n < 0: all substrings
+func SplitAfterN(s, sep string, n int) []string {
+	return genSplit(s, sep, len(sep), n)
+}
+
+// Split slices s into all substrings separated by sep and returns a slice of
+// the substrings between those separators.
+// If sep is empty, Split splits after each UTF-8 sequence.
+// It is equivalent to SplitN with a count of -1.
+func Split(s, sep string) []string { return genSplit(s, sep, 0, -1) }
+
+// SplitAfter slices s into all substrings after each instance of sep and
+// returns a slice of those substrings.
+// If sep is empty, SplitAfter splits after each UTF-8 sequence.
+// It is equivalent to SplitAfterN with a count of -1.
+func SplitAfter(s, sep string) []string {
+	return genSplit(s, sep, len(sep), -1)
+}
+
+// Fields splits the string s around each instance of one or more consecutive white space
+// characters, as defined by unicode.IsSpace, returning an array of substrings of s or an
+// empty list if s contains only white space.
+func Fields(s string) []string {
+	return FieldsFunc(s, unicode.IsSpace)
+}
+
+// FieldsFunc splits the string s at each run of Unicode code points c satisfying f(c)
+// and returns an array of slices of s. If all code points in s satisfy f(c) or the
+// string is empty, an empty slice is returned.
+func FieldsFunc(s string, f func(rune) bool) []string {
+	// First count the fields.
+	n := 0
+	inField := false
+	for _, rune := range s {
+		wasInField := inField
+		inField = !f(rune)
+		if inField && !wasInField {
+			n++
+		}
+	}
+
+	// Now create them.
+	a := make([]string, n)
+	na := 0
+	fieldStart := -1 // Set to -1 when looking for start of field.
+	for i, rune := range s {
+		if f(rune) {
+			if fieldStart >= 0 {
+				a[na] = s[fieldStart:i]
+				na++
+				fieldStart = -1
+			}
+		} else if fieldStart == -1 {
+			fieldStart = i
+		}
+	}
+	if fieldStart >= 0 { // Last field might end at EOF.
+		a[na] = s[fieldStart:]
+	}
+	return a
+}
+
+// Join concatenates the elements of a to create a single string.   The separator string
+// sep is placed between elements in the resulting string.
+func Join(a []string, sep string) string {
+	if len(a) == 0 {
+		return ""
+	}
+	if len(a) == 1 {
+		return a[0]
+	}
+	n := len(sep) * (len(a) - 1)
+	for i := 0; i < len(a); i++ {
+		n += len(a[i])
+	}
+
+	b := make([]byte, n)
+	bp := copy(b, a[0])
+	for _, s := range a[1:] {
+		bp += copy(b[bp:], sep)
+		bp += copy(b[bp:], s)
+	}
+	return string(b)
+}
+
+// HasPrefix tests whether the string s begins with prefix.
+func HasPrefix(s, prefix string) bool {
+	return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
+}
+
+// HasSuffix tests whether the string s ends with suffix.
+func HasSuffix(s, suffix string) bool {
+	return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
+}
+
+// Map returns a copy of the string s with all its characters modified
+// according to the mapping function. If mapping returns a negative value, the character is
+// dropped from the string with no replacement.
+func Map(mapping func(rune) rune, s string) string {
+	// In the worst case, the string can grow when mapped, making
+	// things unpleasant.  But it's so rare we barge in assuming it's
+	// fine.  It could also shrink but that falls out naturally.
+	maxbytes := len(s) // length of b
+	nbytes := 0        // number of bytes encoded in b
+	// The output buffer b is initialized on demand, the first
+	// time a character differs.
+	var b []byte
+
+	for i, c := range s {
+		r := mapping(c)
+		if b == nil {
+			if r == c {
+				continue
+			}
+			b = make([]byte, maxbytes)
+			nbytes = copy(b, s[:i])
+		}
+		if r >= 0 {
+			wid := 1
+			if r >= utf8.RuneSelf {
+				wid = utf8.RuneLen(r)
+			}
+			if nbytes+wid > maxbytes {
+				// Grow the buffer.
+				maxbytes = maxbytes*2 + utf8.UTFMax
+				nb := make([]byte, maxbytes)
+				copy(nb, b[0:nbytes])
+				b = nb
+			}
+			nbytes += utf8.EncodeRune(b[nbytes:maxbytes], r)
+		}
+	}
+	if b == nil {
+		return s
+	}
+	return string(b[0:nbytes])
+}
+
+// Repeat returns a new string consisting of count copies of the string s.
+func Repeat(s string, count int) string {
+	b := make([]byte, len(s)*count)
+	bp := 0
+	for i := 0; i < count; i++ {
+		bp += copy(b[bp:], s)
+	}
+	return string(b)
+}
+
+// ToUpper returns a copy of the string s with all Unicode letters mapped to their upper case.
+func ToUpper(s string) string { return Map(unicode.ToUpper, s) }
+
+// ToLower returns a copy of the string s with all Unicode letters mapped to their lower case.
+func ToLower(s string) string { return Map(unicode.ToLower, s) }
+
+// ToTitle returns a copy of the string s with all Unicode letters mapped to their title case.
+func ToTitle(s string) string { return Map(unicode.ToTitle, s) }
+
+// ToUpperSpecial returns a copy of the string s with all Unicode letters mapped to their
+// upper case, giving priority to the special casing rules.
+func ToUpperSpecial(_case unicode.SpecialCase, s string) string {
+	return Map(func(r rune) rune { return _case.ToUpper(r) }, s)
+}
+
+// ToLowerSpecial returns a copy of the string s with all Unicode letters mapped to their
+// lower case, giving priority to the special casing rules.
+func ToLowerSpecial(_case unicode.SpecialCase, s string) string {
+	return Map(func(r rune) rune { return _case.ToLower(r) }, s)
+}
+
+// ToTitleSpecial returns a copy of the string s with all Unicode letters mapped to their
+// title case, giving priority to the special casing rules.
+func ToTitleSpecial(_case unicode.SpecialCase, s string) string {
+	return Map(func(r rune) rune { return _case.ToTitle(r) }, s)
+}
+
+// isSeparator reports whether the rune could mark a word boundary.
+// TODO: update when package unicode captures more of the properties.
+func isSeparator(r rune) bool {
+	// ASCII alphanumerics and underscore are not separators
+	if r <= 0x7F {
+		switch {
+		case '0' <= r && r <= '9':
+			return false
+		case 'a' <= r && r <= 'z':
+			return false
+		case 'A' <= r && r <= 'Z':
+			return false
+		case r == '_':
+			return false
+		}
+		return true
+	}
+	// Letters and digits are not separators
+	if unicode.IsLetter(r) || unicode.IsDigit(r) {
+		return false
+	}
+	// Otherwise, all we can do for now is treat spaces as separators.
+	return unicode.IsSpace(r)
+}
+
+// Title returns a copy of the string s with all Unicode letters that begin words
+// mapped to their title case.
+//
+// BUG: The rule Title uses for word boundaries does not handle Unicode punctuation properly.
+func Title(s string) string {
+	// Use a closure here to remember state.
+	// Hackish but effective. Depends on Map scanning in order and calling
+	// the closure once per rune.
+	prev := ' '
+	return Map(
+		func(r rune) rune {
+			if isSeparator(prev) {
+				prev = r
+				return unicode.ToTitle(r)
+			}
+			prev = r
+			return r
+		},
+		s)
+}
+
+// TrimLeftFunc returns a slice of the string s with all leading
+// Unicode code points c satisfying f(c) removed.
+func TrimLeftFunc(s string, f func(rune) bool) string {
+	i := indexFunc(s, f, false)
+	if i == -1 {
+		return ""
+	}
+	return s[i:]
+}
+
+// TrimRightFunc returns a slice of the string s with all trailing
+// Unicode code points c satisfying f(c) removed.
+func TrimRightFunc(s string, f func(rune) bool) string {
+	i := lastIndexFunc(s, f, false)
+	if i >= 0 && s[i] >= utf8.RuneSelf {
+		_, wid := utf8.DecodeRuneInString(s[i:])
+		i += wid
+	} else {
+		i++
+	}
+	return s[0:i]
+}
+
+// TrimFunc returns a slice of the string s with all leading
+// and trailing Unicode code points c satisfying f(c) removed.
+func TrimFunc(s string, f func(rune) bool) string {
+	return TrimRightFunc(TrimLeftFunc(s, f), f)
+}
+
+// IndexFunc returns the index into s of the first Unicode
+// code point satisfying f(c), or -1 if none do.
+func IndexFunc(s string, f func(rune) bool) int {
+	return indexFunc(s, f, true)
+}
+
+// LastIndexFunc returns the index into s of the last
+// Unicode code point satisfying f(c), or -1 if none do.
+func LastIndexFunc(s string, f func(rune) bool) int {
+	return lastIndexFunc(s, f, true)
+}
+
+// indexFunc is the same as IndexFunc except that if
+// truth==false, the sense of the predicate function is
+// inverted.
+func indexFunc(s string, f func(rune) bool, truth bool) int {
+	start := 0
+	for start < len(s) {
+		wid := 1
+		r := rune(s[start])
+		if r >= utf8.RuneSelf {
+			r, wid = utf8.DecodeRuneInString(s[start:])
+		}
+		if f(r) == truth {
+			return start
+		}
+		start += wid
+	}
+	return -1
+}
+
+// lastIndexFunc is the same as LastIndexFunc except that if
+// truth==false, the sense of the predicate function is
+// inverted.
+func lastIndexFunc(s string, f func(rune) bool, truth bool) int {
+	for i := len(s); i > 0; {
+		r, size := utf8.DecodeLastRuneInString(s[0:i])
+		i -= size
+		if f(r) == truth {
+			return i
+		}
+	}
+	return -1
+}
+
+func makeCutsetFunc(cutset string) func(rune) bool {
+	return func(r rune) bool { return IndexRune(cutset, r) >= 0 }
+}
+
+// Trim returns a slice of the string s with all leading and
+// trailing Unicode code points contained in cutset removed.
+func Trim(s string, cutset string) string {
+	if s == "" || cutset == "" {
+		return s
+	}
+	return TrimFunc(s, makeCutsetFunc(cutset))
+}
+
+// TrimLeft returns a slice of the string s with all leading
+// Unicode code points contained in cutset removed.
+func TrimLeft(s string, cutset string) string {
+	if s == "" || cutset == "" {
+		return s
+	}
+	return TrimLeftFunc(s, makeCutsetFunc(cutset))
+}
+
+// TrimRight returns a slice of the string s, with all trailing
+// Unicode code points contained in cutset removed.
+func TrimRight(s string, cutset string) string {
+	if s == "" || cutset == "" {
+		return s
+	}
+	return TrimRightFunc(s, makeCutsetFunc(cutset))
+}
+
+// TrimSpace returns a slice of the string s, with all leading
+// and trailing white space removed, as defined by Unicode.
+func TrimSpace(s string) string {
+	return TrimFunc(s, unicode.IsSpace)
+}
+
+// TrimPrefix returns s without the provided leading prefix string.
+// If s doesn't start with prefix, s is returned unchanged.
+func TrimPrefix(s, prefix string) string {
+	if HasPrefix(s, prefix) {
+		return s[len(prefix):]
+	}
+	return s
+}
+
+// TrimSuffix returns s without the provided trailing suffix string.
+// If s doesn't end with suffix, s is returned unchanged.
+func TrimSuffix(s, suffix string) string {
+	if HasSuffix(s, suffix) {
+		return s[:len(s)-len(suffix)]
+	}
+	return s
+}
+
+// Replace returns a copy of the string s with the first n
+// non-overlapping instances of old replaced by new.
+// If n < 0, there is no limit on the number of replacements.
+func Replace(s, old, new string, n int) string {
+	if old == new || n == 0 {
+		return s // avoid allocation
+	}
+
+	// Compute number of replacements.
+	if m := Count(s, old); m == 0 {
+		return s // avoid allocation
+	} else if n < 0 || m < n {
+		n = m
+	}
+
+	// Apply replacements to buffer.
+	t := make([]byte, len(s)+n*(len(new)-len(old)))
+	w := 0
+	start := 0
+	for i := 0; i < n; i++ {
+		j := start
+		if len(old) == 0 {
+			if i > 0 {
+				_, wid := utf8.DecodeRuneInString(s[start:])
+				j += wid
+			}
+		} else {
+			j += Index(s[start:], old)
+		}
+		w += copy(t[w:], s[start:j])
+		w += copy(t[w:], new)
+		start = j + len(old)
+	}
+	w += copy(t[w:], s[start:])
+	return string(t[0:w])
+}
+
+// EqualFold reports whether s and t, interpreted as UTF-8 strings,
+// are equal under Unicode case-folding.
+func EqualFold(s, t string) bool {
+	for s != "" && t != "" {
+		// Extract first rune from each string.
+		var sr, tr rune
+		if s[0] < utf8.RuneSelf {
+			sr, s = rune(s[0]), s[1:]
+		} else {
+			r, size := utf8.DecodeRuneInString(s)
+			sr, s = r, s[size:]
+		}
+		if t[0] < utf8.RuneSelf {
+			tr, t = rune(t[0]), t[1:]
+		} else {
+			r, size := utf8.DecodeRuneInString(t)
+			tr, t = r, t[size:]
+		}
+
+		// If they match, keep going; if not, return false.
+
+		// Easy case.
+		if tr == sr {
+			continue
+		}
+
+		// Make sr < tr to simplify what follows.
+		if tr < sr {
+			tr, sr = sr, tr
+		}
+		// Fast check for ASCII.
+		if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
+			// ASCII, and sr is upper case.  tr must be lower case.
+			if tr == sr+'a'-'A' {
+				continue
+			}
+			return false
+		}
+
+		// General case.  SimpleFold(x) returns the next equivalent rune > x
+		// or wraps around to smaller values.
+		r := unicode.SimpleFold(sr)
+		for r != sr && r < tr {
+			r = unicode.SimpleFold(r)
+		}
+		if r == tr {
+			continue
+		}
+		return false
+	}
+
+	// One string is empty.  Are both?
+	return s == t
+}
diff --git a/third_party/gofrontend/libgo/go/strings/strings_decl.go b/third_party/gofrontend/libgo/go/strings/strings_decl.go
new file mode 100644
index 0000000..810a696
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/strings_decl.go
@@ -0,0 +1,8 @@
+// Copyright 2013 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 strings
+
+// IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s.
+func IndexByte(s string, c byte) int // ../runtime/asm_$GOARCH.s
diff --git a/third_party/gofrontend/libgo/go/strings/strings_test.go b/third_party/gofrontend/libgo/go/strings/strings_test.go
new file mode 100644
index 0000000..e40a180
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/strings/strings_test.go
@@ -0,0 +1,1176 @@
+// 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 strings_test
+
+import (
+	"bytes"
+	"io"
+	"math/rand"
+	"reflect"
+	. "strings"
+	"testing"
+	"unicode"
+	"unicode/utf8"
+	"unsafe"
+)
+
+func eq(a, b []string) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i := 0; i < len(a); i++ {
+		if a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+var abcd = "abcd"
+var faces = "☺☻☹"
+var commas = "1,2,3,4"
+var dots = "1....2....3....4"
+
+type IndexTest struct {
+	s   string
+	sep string
+	out int
+}
+
+var indexTests = []IndexTest{
+	{"", "", 0},
+	{"", "a", -1},
+	{"", "foo", -1},
+	{"fo", "foo", -1},
+	{"foo", "foo", 0},
+	{"oofofoofooo", "f", 2},
+	{"oofofoofooo", "foo", 4},
+	{"barfoobarfoo", "foo", 3},
+	{"foo", "", 0},
+	{"foo", "o", 1},
+	{"abcABCabc", "A", 3},
+	// cases with one byte strings - test special case in Index()
+	{"", "a", -1},
+	{"x", "a", -1},
+	{"x", "x", 0},
+	{"abc", "a", 0},
+	{"abc", "b", 1},
+	{"abc", "c", 2},
+	{"abc", "x", -1},
+}
+
+var lastIndexTests = []IndexTest{
+	{"", "", 0},
+	{"", "a", -1},
+	{"", "foo", -1},
+	{"fo", "foo", -1},
+	{"foo", "foo", 0},
+	{"foo", "f", 0},
+	{"oofofoofooo", "f", 7},
+	{"oofofoofooo", "foo", 7},
+	{"barfoobarfoo", "foo", 9},
+	{"foo", "", 3},
+	{"foo", "o", 2},
+	{"abcABCabc", "A", 3},
+	{"abcABCabc", "a", 6},
+}
+
+var indexAnyTests = []IndexTest{
+	{"", "", -1},
+	{"", "a", -1},
+	{"", "abc", -1},
+	{"a", "", -1},
+	{"a", "a", 0},
+	{"aaa", "a", 0},
+	{"abc", "xyz", -1},
+	{"abc", "xcz", 2},
+	{"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
+	{"aRegExp*", ".(|)*+?^$[]", 7},
+	{dots + dots + dots, " ", -1},
+}
+var lastIndexAnyTests = []IndexTest{
+	{"", "", -1},
+	{"", "a", -1},
+	{"", "abc", -1},
+	{"a", "", -1},
+	{"a", "a", 0},
+	{"aaa", "a", 2},
+	{"abc", "xyz", -1},
+	{"abc", "ab", 1},
+	{"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
+	{"a.RegExp*", ".(|)*+?^$[]", 8},
+	{dots + dots + dots, " ", -1},
+}
+
+// Execute f on each test case.  funcName should be the name of f; it's used
+// in failure reports.
+func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) {
+	for _, test := range testCases {
+		actual := f(test.s, test.sep)
+		if actual != test.out {
+			t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out)
+		}
+	}
+}
+
+func TestIndex(t *testing.T)        { runIndexTests(t, Index, "Index", indexTests) }
+func TestLastIndex(t *testing.T)    { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }
+func TestIndexAny(t *testing.T)     { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) }
+func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) }
+
+var indexRuneTests = []struct {
+	s    string
+	rune rune
+	out  int
+}{
+	{"a A x", 'A', 2},
+	{"some_text=some_value", '=', 9},
+	{"☺a", 'a', 3},
+	{"a☻☺b", '☺', 4},
+}
+
+func TestIndexRune(t *testing.T) {
+	for _, test := range indexRuneTests {
+		if actual := IndexRune(test.s, test.rune); actual != test.out {
+			t.Errorf("IndexRune(%q,%d)= %v; want %v", test.s, test.rune, actual, test.out)
+		}
+	}
+}
+
+const benchmarkString = "some_text=some☺value"
+
+func BenchmarkIndexRune(b *testing.B) {
+	if got := IndexRune(benchmarkString, '☺'); got != 14 {
+		b.Fatalf("wrong index: expected 14, got=%d", got)
+	}
+	for i := 0; i < b.N; i++ {
+		IndexRune(benchmarkString, '☺')
+	}
+}
+
+func BenchmarkIndexRuneFastPath(b *testing.B) {
+	if got := IndexRune(benchmarkString, 'v'); got != 17 {
+		b.Fatalf("wrong index: expected 17, got=%d", got)
+	}
+	for i := 0; i < b.N; i++ {
+		IndexRune(benchmarkString, 'v')
+	}
+}
+
+func BenchmarkIndex(b *testing.B) {
+	if got := Index(benchmarkString, "v"); got != 17 {
+		b.Fatalf("wrong index: expected 17, got=%d", got)
+	}
+	for i := 0; i < b.N; i++ {
+		Index(benchmarkString, "v")
+	}
+}
+
+func BenchmarkIndexByte(b *testing.B) {
+	if got := IndexByte(benchmarkString, 'v'); got != 17 {
+		b.Fatalf("wrong index: expected 17, got=%d", got)
+	}
+	for i := 0; i < b.N; i++ {
+		IndexByte(benchmarkString, 'v')
+	}
+}
+
+var explodetests = []struct {
+	s string
+	n int
+	a []string
+}{
+	{"", -1, []string{}},
+	{abcd, 4, []string{"a", "b", "c", "d"}},
+	{faces, 3, []string{"☺", "☻", "☹"}},
+	{abcd, 2, []string{"a", "bcd"}},
+}
+
+func TestExplode(t *testing.T) {
+	for _, tt := range explodetests {
+		a := SplitN(tt.s, "", tt.n)
+		if !eq(a, tt.a) {
+			t.Errorf("explode(%q, %d) = %v; want %v", tt.s, tt.n, a, tt.a)
+			continue
+		}
+		s := Join(a, "")
+		if s != tt.s {
+			t.Errorf(`Join(explode(%q, %d), "") = %q`, tt.s, tt.n, s)
+		}
+	}
+}
+
+type SplitTest struct {
+	s   string
+	sep string
+	n   int
+	a   []string
+}
+
+var splittests = []SplitTest{
+	{abcd, "a", 0, nil},
+	{abcd, "a", -1, []string{"", "bcd"}},
+	{abcd, "z", -1, []string{"abcd"}},
+	{abcd, "", -1, []string{"a", "b", "c", "d"}},
+	{commas, ",", -1, []string{"1", "2", "3", "4"}},
+	{dots, "...", -1, []string{"1", ".2", ".3", ".4"}},
+	{faces, "☹", -1, []string{"☺☻", ""}},
+	{faces, "~", -1, []string{faces}},
+	{faces, "", -1, []string{"☺", "☻", "☹"}},
+	{"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}},
+	{"1 2", " ", 3, []string{"1", "2"}},
+	{"123", "", 2, []string{"1", "23"}},
+	{"123", "", 17, []string{"1", "2", "3"}},
+}
+
+func TestSplit(t *testing.T) {
+	for _, tt := range splittests {
+		a := SplitN(tt.s, tt.sep, tt.n)
+		if !eq(a, tt.a) {
+			t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a)
+			continue
+		}
+		if tt.n == 0 {
+			continue
+		}
+		s := Join(a, tt.sep)
+		if s != tt.s {
+			t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s)
+		}
+		if tt.n < 0 {
+			b := Split(tt.s, tt.sep)
+			if !reflect.DeepEqual(a, b) {
+				t.Errorf("Split disagrees with SplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
+			}
+		}
+	}
+}
+
+var splitaftertests = []SplitTest{
+	{abcd, "a", -1, []string{"a", "bcd"}},
+	{abcd, "z", -1, []string{"abcd"}},
+	{abcd, "", -1, []string{"a", "b", "c", "d"}},
+	{commas, ",", -1, []string{"1,", "2,", "3,", "4"}},
+	{dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}},
+	{faces, "☹", -1, []string{"☺☻☹", ""}},
+	{faces, "~", -1, []string{faces}},
+	{faces, "", -1, []string{"☺", "☻", "☹"}},
+	{"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}},
+	{"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}},
+	{"1 2", " ", 3, []string{"1 ", "2"}},
+	{"123", "", 2, []string{"1", "23"}},
+	{"123", "", 17, []string{"1", "2", "3"}},
+}
+
+func TestSplitAfter(t *testing.T) {
+	for _, tt := range splitaftertests {
+		a := SplitAfterN(tt.s, tt.sep, tt.n)
+		if !eq(a, tt.a) {
+			t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a)
+			continue
+		}
+		s := Join(a, "")
+		if s != tt.s {
+			t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
+		}
+		if tt.n < 0 {
+			b := SplitAfter(tt.s, tt.sep)
+			if !reflect.DeepEqual(a, b) {
+				t.Errorf("SplitAfter disagrees with SplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
+			}
+		}
+	}
+}
+
+type FieldsTest struct {
+	s string
+	a []string
+}
+
+var fieldstests = []FieldsTest{
+	{"", []string{}},
+	{" ", []string{}},
+	{" \t ", []string{}},
+	{"  abc  ", []string{"abc"}},
+	{"1 2 3 4", []string{"1", "2", "3", "4"}},
+	{"1  2  3  4", []string{"1", "2", "3", "4"}},
+	{"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}},
+	{"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}},
+	{"\u2000\u2001\u2002", []string{}},
+	{"\n™\t™\n", []string{"™", "™"}},
+	{faces, []string{faces}},
+}
+
+func TestFields(t *testing.T) {
+	for _, tt := range fieldstests {
+		a := Fields(tt.s)
+		if !eq(a, tt.a) {
+			t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a)
+			continue
+		}
+	}
+}
+
+var FieldsFuncTests = []FieldsTest{
+	{"", []string{}},
+	{"XX", []string{}},
+	{"XXhiXXX", []string{"hi"}},
+	{"aXXbXXXcX", []string{"a", "b", "c"}},
+}
+
+func TestFieldsFunc(t *testing.T) {
+	for _, tt := range fieldstests {
+		a := FieldsFunc(tt.s, unicode.IsSpace)
+		if !eq(a, tt.a) {
+			t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a)
+			continue
+		}
+	}
+	pred := func(c rune) bool { return c == 'X' }
+	for _, tt := range FieldsFuncTests {
+		a := FieldsFunc(tt.s, pred)
+		if !eq(a, tt.a) {
+			t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a)
+		}
+	}
+}
+
+// Test case for any function which accepts and returns a single string.
+type StringTest struct {
+	in, out string
+}
+
+// Execute f on each test case.  funcName should be the name of f; it's used
+// in failure reports.
+func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) {
+	for _, tc := range testCases {
+		actual := f(tc.in)
+		if actual != tc.out {
+			t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
+		}
+	}
+}
+
+var upperTests = []StringTest{
+	{"", ""},
+	{"abc", "ABC"},
+	{"AbC123", "ABC123"},
+	{"azAZ09_", "AZAZ09_"},
+	{"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
+}
+
+var lowerTests = []StringTest{
+	{"", ""},
+	{"abc", "abc"},
+	{"AbC123", "abc123"},
+	{"azAZ09_", "azaz09_"},
+	{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
+}
+
+const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
+
+var trimSpaceTests = []StringTest{
+	{"", ""},
+	{"abc", "abc"},
+	{space + "abc" + space, "abc"},
+	{" ", ""},
+	{" \t\r\n \t\t\r\r\n\n ", ""},
+	{" \t\r\n x\t\t\r\r\n\n ", "x"},
+	{" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"},
+	{"1 \t\r\n2", "1 \t\r\n2"},
+	{" x\x80", "x\x80"},
+	{" x\xc0", "x\xc0"},
+	{"x \xc0\xc0 ", "x \xc0\xc0"},
+	{"x \xc0", "x \xc0"},
+	{"x \xc0 ", "x \xc0"},
+	{"x \xc0\xc0 ", "x \xc0\xc0"},
+	{"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"},
+	{"x ☺ ", "x ☺"},
+}
+
+func tenRunes(ch rune) string {
+	r := make([]rune, 10)
+	for i := range r {
+		r[i] = ch
+	}
+	return string(r)
+}
+
+// User-defined self-inverse mapping function
+func rot13(r rune) rune {
+	step := rune(13)
+	if r >= 'a' && r <= 'z' {
+		return ((r - 'a' + step) % 26) + 'a'
+	}
+	if r >= 'A' && r <= 'Z' {
+		return ((r - 'A' + step) % 26) + 'A'
+	}
+	return r
+}
+
+func TestMap(t *testing.T) {
+	// Run a couple of awful growth/shrinkage tests
+	a := tenRunes('a')
+	// 1.  Grow.  This triggers two reallocations in Map.
+	maxRune := func(rune) rune { return unicode.MaxRune }
+	m := Map(maxRune, a)
+	expect := tenRunes(unicode.MaxRune)
+	if m != expect {
+		t.Errorf("growing: expected %q got %q", expect, m)
+	}
+
+	// 2. Shrink
+	minRune := func(rune) rune { return 'a' }
+	m = Map(minRune, tenRunes(unicode.MaxRune))
+	expect = a
+	if m != expect {
+		t.Errorf("shrinking: expected %q got %q", expect, m)
+	}
+
+	// 3. Rot13
+	m = Map(rot13, "a to zed")
+	expect = "n gb mrq"
+	if m != expect {
+		t.Errorf("rot13: expected %q got %q", expect, m)
+	}
+
+	// 4. Rot13^2
+	m = Map(rot13, Map(rot13, "a to zed"))
+	expect = "a to zed"
+	if m != expect {
+		t.Errorf("rot13: expected %q got %q", expect, m)
+	}
+
+	// 5. Drop
+	dropNotLatin := func(r rune) rune {
+		if unicode.Is(unicode.Latin, r) {
+			return r
+		}
+		return -1
+	}
+	m = Map(dropNotLatin, "Hello, 세계")
+	expect = "Hello"
+	if m != expect {
+		t.Errorf("drop: expected %q got %q", expect, m)
+	}
+
+	// 6. Identity
+	identity := func(r rune) rune {
+		return r
+	}
+	orig := "Input string that we expect not to be copied."
+	m = Map(identity, orig)
+	if (*reflect.StringHeader)(unsafe.Pointer(&orig)).Data !=
+		(*reflect.StringHeader)(unsafe.Pointer(&m)).Data {
+		t.Error("unexpected copy during identity map")
+	}
+}
+
+func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) }
+
+func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) }
+
+func BenchmarkMapNoChanges(b *testing.B) {
+	identity := func(r rune) rune {
+		return r
+	}
+	for i := 0; i < b.N; i++ {
+		Map(identity, "Some string that won't be modified.")
+	}
+}
+
+func TestSpecialCase(t *testing.T) {
+	lower := "abcçdefgğhıijklmnoöprsştuüvyz"
+	upper := "ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ"
+	u := ToUpperSpecial(unicode.TurkishCase, upper)
+	if u != upper {
+		t.Errorf("Upper(upper) is %s not %s", u, upper)
+	}
+	u = ToUpperSpecial(unicode.TurkishCase, lower)
+	if u != upper {
+		t.Errorf("Upper(lower) is %s not %s", u, upper)
+	}
+	l := ToLowerSpecial(unicode.TurkishCase, lower)
+	if l != lower {
+		t.Errorf("Lower(lower) is %s not %s", l, lower)
+	}
+	l = ToLowerSpecial(unicode.TurkishCase, upper)
+	if l != lower {
+		t.Errorf("Lower(upper) is %s not %s", l, lower)
+	}
+}
+
+func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
+
+var trimTests = []struct {
+	f            string
+	in, arg, out string
+}{
+	{"Trim", "abba", "a", "bb"},
+	{"Trim", "abba", "ab", ""},
+	{"TrimLeft", "abba", "ab", ""},
+	{"TrimRight", "abba", "ab", ""},
+	{"TrimLeft", "abba", "a", "bba"},
+	{"TrimRight", "abba", "a", "abb"},
+	{"Trim", "<tag>", "<>", "tag"},
+	{"Trim", "* listitem", " *", "listitem"},
+	{"Trim", `"quote"`, `"`, "quote"},
+	{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
+	//empty string tests
+	{"Trim", "abba", "", "abba"},
+	{"Trim", "", "123", ""},
+	{"Trim", "", "", ""},
+	{"TrimLeft", "abba", "", "abba"},
+	{"TrimLeft", "", "123", ""},
+	{"TrimLeft", "", "", ""},
+	{"TrimRight", "abba", "", "abba"},
+	{"TrimRight", "", "123", ""},
+	{"TrimRight", "", "", ""},
+	{"TrimRight", "☺\xc0", "☺", "☺\xc0"},
+	{"TrimPrefix", "aabb", "a", "abb"},
+	{"TrimPrefix", "aabb", "b", "aabb"},
+	{"TrimSuffix", "aabb", "a", "aabb"},
+	{"TrimSuffix", "aabb", "b", "aab"},
+}
+
+func TestTrim(t *testing.T) {
+	for _, tc := range trimTests {
+		name := tc.f
+		var f func(string, string) string
+		switch name {
+		case "Trim":
+			f = Trim
+		case "TrimLeft":
+			f = TrimLeft
+		case "TrimRight":
+			f = TrimRight
+		case "TrimPrefix":
+			f = TrimPrefix
+		case "TrimSuffix":
+			f = TrimSuffix
+		default:
+			t.Errorf("Undefined trim function %s", name)
+		}
+		actual := f(tc.in, tc.arg)
+		if actual != tc.out {
+			t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
+		}
+	}
+}
+
+type predicate struct {
+	f    func(rune) bool
+	name string
+}
+
+var isSpace = predicate{unicode.IsSpace, "IsSpace"}
+var isDigit = predicate{unicode.IsDigit, "IsDigit"}
+var isUpper = predicate{unicode.IsUpper, "IsUpper"}
+var isValidRune = predicate{
+	func(r rune) bool {
+		return r != utf8.RuneError
+	},
+	"IsValidRune",
+}
+
+func not(p predicate) predicate {
+	return predicate{
+		func(r rune) bool {
+			return !p.f(r)
+		},
+		"not " + p.name,
+	}
+}
+
+var trimFuncTests = []struct {
+	f       predicate
+	in, out string
+}{
+	{isSpace, space + " hello " + space, "hello"},
+	{isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
+	{isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
+	{not(isSpace), "hello" + space + "hello", space},
+	{not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"},
+	{isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"},
+	{not(isValidRune), "\xc0a\xc0", "a"},
+}
+
+func TestTrimFunc(t *testing.T) {
+	for _, tc := range trimFuncTests {
+		actual := TrimFunc(tc.in, tc.f.f)
+		if actual != tc.out {
+			t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out)
+		}
+	}
+}
+
+var indexFuncTests = []struct {
+	in          string
+	f           predicate
+	first, last int
+}{
+	{"", isValidRune, -1, -1},
+	{"abc", isDigit, -1, -1},
+	{"0123", isDigit, 0, 3},
+	{"a1b", isDigit, 1, 1},
+	{space, isSpace, 0, len(space) - 3}, // last rune in space is 3 bytes
+	{"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit, 0, 18},
+	{"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper, 0, 34},
+	{"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit), 8, 12},
+
+	// tests of invalid UTF-8
+	{"\x801", isDigit, 1, 1},
+	{"\x80abc", isDigit, -1, -1},
+	{"\xc0a\xc0", isValidRune, 1, 1},
+	{"\xc0a\xc0", not(isValidRune), 0, 2},
+	{"\xc0☺\xc0", not(isValidRune), 0, 4},
+	{"\xc0☺\xc0\xc0", not(isValidRune), 0, 5},
+	{"ab\xc0a\xc0cd", not(isValidRune), 2, 4},
+	{"a\xe0\x80cd", not(isValidRune), 1, 2},
+	{"\x80\x80\x80\x80", not(isValidRune), 0, 3},
+}
+
+func TestIndexFunc(t *testing.T) {
+	for _, tc := range indexFuncTests {
+		first := IndexFunc(tc.in, tc.f.f)
+		if first != tc.first {
+			t.Errorf("IndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, first, tc.first)
+		}
+		last := LastIndexFunc(tc.in, tc.f.f)
+		if last != tc.last {
+			t.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, last, tc.last)
+		}
+	}
+}
+
+func equal(m string, s1, s2 string, t *testing.T) bool {
+	if s1 == s2 {
+		return true
+	}
+	e1 := Split(s1, "")
+	e2 := Split(s2, "")
+	for i, c1 := range e1 {
+		if i >= len(e2) {
+			break
+		}
+		r1, _ := utf8.DecodeRuneInString(c1)
+		r2, _ := utf8.DecodeRuneInString(e2[i])
+		if r1 != r2 {
+			t.Errorf("%s diff at %d: U+%04X U+%04X", m, i, r1, r2)
+		}
+	}
+	return false
+}
+
+func TestCaseConsistency(t *testing.T) {
+	// Make a string of all the runes.
+	numRunes := int(unicode.MaxRune + 1)
+	if testing.Short() {
+		numRunes = 1000
+	}
+	a := make([]rune, numRunes)
+	for i := range a {
+		a[i] = rune(i)
+	}
+	s := string(a)
+	// convert the cases.
+	upper := ToUpper(s)
+	lower := ToLower(s)
+
+	// Consistency checks
+	if n := utf8.RuneCountInString(upper); n != numRunes {
+		t.Error("rune count wrong in upper:", n)
+	}
+	if n := utf8.RuneCountInString(lower); n != numRunes {
+		t.Error("rune count wrong in lower:", n)
+	}
+	if !equal("ToUpper(upper)", ToUpper(upper), upper, t) {
+		t.Error("ToUpper(upper) consistency fail")
+	}
+	if !equal("ToLower(lower)", ToLower(lower), lower, t) {
+		t.Error("ToLower(lower) consistency fail")
+	}
+	/*
+		  These fail because of non-one-to-oneness of the data, such as multiple
+		  upper case 'I' mapping to 'i'.  We comment them out but keep them for
+		  interest.
+		  For instance: CAPITAL LETTER I WITH DOT ABOVE:
+			unicode.ToUpper(unicode.ToLower('\u0130')) != '\u0130'
+
+		if !equal("ToUpper(lower)", ToUpper(lower), upper, t) {
+			t.Error("ToUpper(lower) consistency fail");
+		}
+		if !equal("ToLower(upper)", ToLower(upper), lower, t) {
+			t.Error("ToLower(upper) consistency fail");
+		}
+	*/
+}
+
+var RepeatTests = []struct {
+	in, out string
+	count   int
+}{
+	{"", "", 0},
+	{"", "", 1},
+	{"", "", 2},
+	{"-", "", 0},
+	{"-", "-", 1},
+	{"-", "----------", 10},
+	{"abc ", "abc abc abc ", 3},
+}
+
+func TestRepeat(t *testing.T) {
+	for _, tt := range RepeatTests {
+		a := Repeat(tt.in, tt.count)
+		if !equal("Repeat(s)", a, tt.out, t) {
+			t.Errorf("Repeat(%v, %d) = %v; want %v", tt.in, tt.count, a, tt.out)
+			continue
+		}
+	}
+}
+
+func runesEqual(a, b []rune) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i, r := range a {
+		if r != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+var RunesTests = []struct {
+	in    string
+	out   []rune
+	lossy bool
+}{
+	{"", []rune{}, false},
+	{" ", []rune{32}, false},
+	{"ABC", []rune{65, 66, 67}, false},
+	{"abc", []rune{97, 98, 99}, false},
+	{"\u65e5\u672c\u8a9e", []rune{26085, 26412, 35486}, false},
+	{"ab\x80c", []rune{97, 98, 0xFFFD, 99}, true},
+	{"ab\xc0c", []rune{97, 98, 0xFFFD, 99}, true},
+}
+
+func TestRunes(t *testing.T) {
+	for _, tt := range RunesTests {
+		a := []rune(tt.in)
+		if !runesEqual(a, tt.out) {
+			t.Errorf("[]rune(%q) = %v; want %v", tt.in, a, tt.out)
+			continue
+		}
+		if !tt.lossy {
+			// can only test reassembly if we didn't lose information
+			s := string(a)
+			if s != tt.in {
+				t.Errorf("string([]rune(%q)) = %x; want %x", tt.in, s, tt.in)
+			}
+		}
+	}
+}
+
+func TestReadByte(t *testing.T) {
+	testStrings := []string{"", abcd, faces, commas}
+	for _, s := range testStrings {
+		reader := NewReader(s)
+		if e := reader.UnreadByte(); e == nil {
+			t.Errorf("Unreading %q at beginning: expected error", s)
+		}
+		var res bytes.Buffer
+		for {
+			b, e := reader.ReadByte()
+			if e == io.EOF {
+				break
+			}
+			if e != nil {
+				t.Errorf("Reading %q: %s", s, e)
+				break
+			}
+			res.WriteByte(b)
+			// unread and read again
+			e = reader.UnreadByte()
+			if e != nil {
+				t.Errorf("Unreading %q: %s", s, e)
+				break
+			}
+			b1, e := reader.ReadByte()
+			if e != nil {
+				t.Errorf("Reading %q after unreading: %s", s, e)
+				break
+			}
+			if b1 != b {
+				t.Errorf("Reading %q after unreading: want byte %q, got %q", s, b, b1)
+				break
+			}
+		}
+		if res.String() != s {
+			t.Errorf("Reader(%q).ReadByte() produced %q", s, res.String())
+		}
+	}
+}
+
+func TestReadRune(t *testing.T) {
+	testStrings := []string{"", abcd, faces, commas}
+	for _, s := range testStrings {
+		reader := NewReader(s)
+		if e := reader.UnreadRune(); e == nil {
+			t.Errorf("Unreading %q at beginning: expected error", s)
+		}
+		res := ""
+		for {
+			r, z, e := reader.ReadRune()
+			if e == io.EOF {
+				break
+			}
+			if e != nil {
+				t.Errorf("Reading %q: %s", s, e)
+				break
+			}
+			res += string(r)
+			// unread and read again
+			e = reader.UnreadRune()
+			if e != nil {
+				t.Errorf("Unreading %q: %s", s, e)
+				break
+			}
+			r1, z1, e := reader.ReadRune()
+			if e != nil {
+				t.Errorf("Reading %q after unreading: %s", s, e)
+				break
+			}
+			if r1 != r {
+				t.Errorf("Reading %q after unreading: want rune %q, got %q", s, r, r1)
+				break
+			}
+			if z1 != z {
+				t.Errorf("Reading %q after unreading: want size %d, got %d", s, z, z1)
+				break
+			}
+		}
+		if res != s {
+			t.Errorf("Reader(%q).ReadRune() produced %q", s, res)
+		}
+	}
+}
+
+var UnreadRuneErrorTests = []struct {
+	name string
+	f    func(*Reader)
+}{
+	{"Read", func(r *Reader) { r.Read([]byte{0}) }},
+	{"ReadByte", func(r *Reader) { r.ReadByte() }},
+	{"UnreadRune", func(r *Reader) { r.UnreadRune() }},
+	{"Seek", func(r *Reader) { r.Seek(0, 1) }},
+	{"WriteTo", func(r *Reader) { r.WriteTo(&bytes.Buffer{}) }},
+}
+
+func TestUnreadRuneError(t *testing.T) {
+	for _, tt := range UnreadRuneErrorTests {
+		reader := NewReader("0123456789")
+		if _, _, err := reader.ReadRune(); err != nil {
+			// should not happen
+			t.Fatal(err)
+		}
+		tt.f(reader)
+		err := reader.UnreadRune()
+		if err == nil {
+			t.Errorf("Unreading after %s: expected error", tt.name)
+		}
+	}
+}
+
+var ReplaceTests = []struct {
+	in       string
+	old, new string
+	n        int
+	out      string
+}{
+	{"hello", "l", "L", 0, "hello"},
+	{"hello", "l", "L", -1, "heLLo"},
+	{"hello", "x", "X", -1, "hello"},
+	{"", "x", "X", -1, ""},
+	{"radar", "r", "<r>", -1, "<r>ada<r>"},
+	{"", "", "<>", -1, "<>"},
+	{"banana", "a", "<>", -1, "b<>n<>n<>"},
+	{"banana", "a", "<>", 1, "b<>nana"},
+	{"banana", "a", "<>", 1000, "b<>n<>n<>"},
+	{"banana", "an", "<>", -1, "b<><>a"},
+	{"banana", "ana", "<>", -1, "b<>na"},
+	{"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"},
+	{"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"},
+	{"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"},
+	{"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"},
+	{"banana", "", "<>", 1, "<>banana"},
+	{"banana", "a", "a", -1, "banana"},
+	{"banana", "a", "a", 1, "banana"},
+	{"☺☻☹", "", "<>", -1, "<>☺<>☻<>☹<>"},
+}
+
+func TestReplace(t *testing.T) {
+	for _, tt := range ReplaceTests {
+		if s := Replace(tt.in, tt.old, tt.new, tt.n); s != tt.out {
+			t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out)
+		}
+	}
+}
+
+var TitleTests = []struct {
+	in, out string
+}{
+	{"", ""},
+	{"a", "A"},
+	{" aaa aaa aaa ", " Aaa Aaa Aaa "},
+	{" Aaa Aaa Aaa ", " Aaa Aaa Aaa "},
+	{"123a456", "123a456"},
+	{"double-blind", "Double-Blind"},
+	{"ÿøû", "Ÿøû"},
+	{"with_underscore", "With_underscore"},
+	{"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"},
+}
+
+func TestTitle(t *testing.T) {
+	for _, tt := range TitleTests {
+		if s := Title(tt.in); s != tt.out {
+			t.Errorf("Title(%q) = %q, want %q", tt.in, s, tt.out)
+		}
+	}
+}
+
+var ContainsTests = []struct {
+	str, substr string
+	expected    bool
+}{
+	{"abc", "bc", true},
+	{"abc", "bcd", false},
+	{"abc", "", true},
+	{"", "a", false},
+}
+
+func TestContains(t *testing.T) {
+	for _, ct := range ContainsTests {
+		if Contains(ct.str, ct.substr) != ct.expected {
+			t.Errorf("Contains(%s, %s) = %v, want %v",
+				ct.str, ct.substr, !ct.expected, ct.expected)
+		}
+	}
+}
+
+var ContainsAnyTests = []struct {
+	str, substr string
+	expected    bool
+}{
+	{"", "", false},
+	{"", "a", false},
+	{"", "abc", false},
+	{"a", "", false},
+	{"a", "a", true},
+	{"aaa", "a", true},
+	{"abc", "xyz", false},
+	{"abc", "xcz", true},
+	{"a☺b☻c☹d", "uvw☻xyz", true},
+	{"aRegExp*", ".(|)*+?^$[]", true},
+	{dots + dots + dots, " ", false},
+}
+
+func TestContainsAny(t *testing.T) {
+	for _, ct := range ContainsAnyTests {
+		if ContainsAny(ct.str, ct.substr) != ct.expected {
+			t.Errorf("ContainsAny(%s, %s) = %v, want %v",
+				ct.str, ct.substr, !ct.expected, ct.expected)
+		}
+	}
+}
+
+var ContainsRuneTests = []struct {
+	str      string
+	r        rune
+	expected bool
+}{
+	{"", 'a', false},
+	{"a", 'a', true},
+	{"aaa", 'a', true},
+	{"abc", 'y', false},
+	{"abc", 'c', true},
+	{"a☺b☻c☹d", 'x', false},
+	{"a☺b☻c☹d", '☻', true},
+	{"aRegExp*", '*', true},
+}
+
+func TestContainsRune(t *testing.T) {
+	for _, ct := range ContainsRuneTests {
+		if ContainsRune(ct.str, ct.r) != ct.expected {
+			t.Errorf("ContainsRune(%q, %q) = %v, want %v",
+				ct.str, ct.r, !ct.expected, ct.expected)
+		}
+	}
+}
+
+var EqualFoldTests = []struct {
+	s, t string
+	out  bool
+}{
+	{"abc", "abc", true},
+	{"ABcd", "ABcd", true},
+	{"123abc", "123ABC", true},
+	{"αβδ", "ΑΒΔ", true},
+	{"abc", "xyz", false},
+	{"abc", "XYZ", false},
+	{"abcdefghijk", "abcdefghijX", false},
+	{"abcdefghijk", "abcdefghij\u212A", true},
+	{"abcdefghijK", "abcdefghij\u212A", true},
+	{"abcdefghijkz", "abcdefghij\u212Ay", false},
+	{"abcdefghijKz", "abcdefghij\u212Ay", false},
+}
+
+func TestEqualFold(t *testing.T) {
+	for _, tt := range EqualFoldTests {
+		if out := EqualFold(tt.s, tt.t); out != tt.out {
+			t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out)
+		}
+		if out := EqualFold(tt.t, tt.s); out != tt.out {
+			t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out)
+		}
+	}
+}
+
+var CountTests = []struct {
+	s, sep string
+	num    int
+}{
+	{"", "", 1},
+	{"", "notempty", 0},
+	{"notempty", "", 9},
+	{"smaller", "not smaller", 0},
+	{"12345678987654321", "6", 2},
+	{"611161116", "6", 3},
+	{"notequal", "NotEqual", 0},
+	{"equal", "equal", 1},
+	{"abc1231231123q", "123", 3},
+	{"11111", "11", 2},
+}
+
+func TestCount(t *testing.T) {
+	for _, tt := range CountTests {
+		if num := Count(tt.s, tt.sep); num != tt.num {
+			t.Errorf("Count(\"%s\", \"%s\") = %d, want %d", tt.s, tt.sep, num, tt.num)
+		}
+	}
+}
+
+func makeBenchInputHard() string {
+	tokens := [...]string{
+		"<a>", "<p>", "<b>", "<strong>",
+		"</a>", "</p>", "</b>", "</strong>",
+		"hello", "world",
+	}
+	x := make([]byte, 0, 1<<20)
+	for len(x) < 1<<20 {
+		i := rand.Intn(len(tokens))
+		x = append(x, tokens[i]...)
+	}
+	return string(x)
+}
+
+var benchInputHard = makeBenchInputHard()
+
+func benchmarkIndexHard(b *testing.B, sep string) {
+	for i := 0; i < b.N; i++ {
+		Index(benchInputHard, sep)
+	}
+}
+
+func benchmarkCountHard(b *testing.B, sep string) {
+	for i := 0; i < b.N; i++ {
+		Count(benchInputHard, sep)
+	}
+}
+
+func BenchmarkIndexHard1(b *testing.B) { benchmarkIndexHard(b, "<>") }
+func BenchmarkIndexHard2(b *testing.B) { benchmarkIndexHard(b, "</pre>") }
+func BenchmarkIndexHard3(b *testing.B) { benchmarkIndexHard(b, "<b>hello world</b>") }
+
+func BenchmarkCountHard1(b *testing.B) { benchmarkCountHard(b, "<>") }
+func BenchmarkCountHard2(b *testing.B) { benchmarkCountHard(b, "</pre>") }
+func BenchmarkCountHard3(b *testing.B) { benchmarkCountHard(b, "<b>hello world</b>") }
+
+var benchInputTorture = Repeat("ABC", 1<<10) + "123" + Repeat("ABC", 1<<10)
+var benchNeedleTorture = Repeat("ABC", 1<<10+1)
+
+func BenchmarkIndexTorture(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Index(benchInputTorture, benchNeedleTorture)
+	}
+}
+
+func BenchmarkCountTorture(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Count(benchInputTorture, benchNeedleTorture)
+	}
+}
+
+func BenchmarkCountTortureOverlapping(b *testing.B) {
+	A := Repeat("ABC", 1<<20)
+	B := Repeat("ABC", 1<<10)
+	for i := 0; i < b.N; i++ {
+		Count(A, B)
+	}
+}
+
+var makeFieldsInput = func() string {
+	x := make([]byte, 1<<20)
+	// Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
+	for i := range x {
+		switch rand.Intn(10) {
+		case 0:
+			x[i] = ' '
+		case 1:
+			if i > 0 && x[i-1] == 'x' {
+				copy(x[i-1:], "χ")
+				break
+			}
+			fallthrough
+		default:
+			x[i] = 'x'
+		}
+	}
+	return string(x)
+}
+
+var fieldsInput = makeFieldsInput()
+
+func BenchmarkFields(b *testing.B) {
+	b.SetBytes(int64(len(fieldsInput)))
+	for i := 0; i < b.N; i++ {
+		Fields(fieldsInput)
+	}
+}
+
+func BenchmarkFieldsFunc(b *testing.B) {
+	b.SetBytes(int64(len(fieldsInput)))
+	for i := 0; i < b.N; i++ {
+		FieldsFunc(fieldsInput, unicode.IsSpace)
+	}
+}
+
+func BenchmarkSplit1(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Split(benchInputHard, "")
+	}
+}
+
+func BenchmarkSplit2(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Split(benchInputHard, "/")
+	}
+}
+
+func BenchmarkSplit3(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Split(benchInputHard, "hello")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/sync/atomic/64bit_arm.go b/third_party/gofrontend/libgo/go/sync/atomic/64bit_arm.go
new file mode 100644
index 0000000..c08f214
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/atomic/64bit_arm.go
@@ -0,0 +1,46 @@
+// 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 atomic
+
+func loadUint64(addr *uint64) (val uint64) {
+	for {
+		val = *addr
+		if CompareAndSwapUint64(addr, val, val) {
+			break
+		}
+	}
+	return
+}
+
+func storeUint64(addr *uint64, val uint64) {
+	for {
+		old := *addr
+		if CompareAndSwapUint64(addr, old, val) {
+			break
+		}
+	}
+	return
+}
+
+func addUint64(val *uint64, delta uint64) (new uint64) {
+	for {
+		old := *val
+		new = old + delta
+		if CompareAndSwapUint64(val, old, new) {
+			break
+		}
+	}
+	return
+}
+
+func swapUint64(addr *uint64, new uint64) (old uint64) {
+	for {
+		old = *addr
+		if CompareAndSwapUint64(addr, old, new) {
+			break
+		}
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/sync/atomic/atomic.c b/third_party/gofrontend/libgo/go/sync/atomic/atomic.c
new file mode 100644
index 0000000..f0ba57b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/atomic/atomic.c
@@ -0,0 +1,353 @@
+/* atomic.c -- implement atomic routines for Go.
+
+   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.  */
+
+#include <stdint.h>
+
+#include "runtime.h"
+
+int32_t SwapInt32 (int32_t *, int32_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.SwapInt32")
+  __attribute__ ((no_split_stack));
+
+int32_t
+SwapInt32 (int32_t *addr, int32_t new)
+{
+  return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+int64_t SwapInt64 (int64_t *, int64_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.SwapInt64")
+  __attribute__ ((no_split_stack));
+
+int64_t
+SwapInt64 (int64_t *addr, int64_t new)
+{
+  return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+uint32_t SwapUint32 (uint32_t *, uint32_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.SwapUint32")
+  __attribute__ ((no_split_stack));
+
+uint32_t
+SwapUint32 (uint32_t *addr, uint32_t new)
+{
+  return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+uint64_t SwapUint64 (uint64_t *, uint64_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.SwapUint64")
+  __attribute__ ((no_split_stack));
+
+uint64_t
+SwapUint64 (uint64_t *addr, uint64_t new)
+{
+  return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+uintptr_t SwapUintptr (uintptr_t *, uintptr_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.SwapUintptr")
+  __attribute__ ((no_split_stack));
+
+uintptr_t
+SwapUintptr (uintptr_t *addr, uintptr_t new)
+{
+  return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+void *SwapPointer (void **, void *)
+  __asm__ (GOSYM_PREFIX "sync_atomic.SwapPointer")
+  __attribute__ ((no_split_stack));
+
+void *
+SwapPointer (void **addr, void *new)
+{
+  return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+_Bool CompareAndSwapInt32 (int32_t *, int32_t, int32_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt32")
+  __attribute__ ((no_split_stack));
+
+_Bool
+CompareAndSwapInt32 (int32_t *val, int32_t old, int32_t new)
+{
+  return __sync_bool_compare_and_swap (val, old, new);
+}
+
+_Bool CompareAndSwapInt64 (int64_t *, int64_t, int64_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt64")
+  __attribute__ ((no_split_stack));
+
+_Bool
+CompareAndSwapInt64 (int64_t *val, int64_t old, int64_t new)
+{
+  return __sync_bool_compare_and_swap (val, old, new);
+}
+
+_Bool CompareAndSwapUint32 (uint32_t *, uint32_t, uint32_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUint32")
+  __attribute__ ((no_split_stack));
+
+_Bool
+CompareAndSwapUint32 (uint32_t *val, uint32_t old, uint32_t new)
+{
+  return __sync_bool_compare_and_swap (val, old, new);
+}
+
+_Bool CompareAndSwapUint64 (uint64_t *, uint64_t, uint64_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUint64")
+  __attribute__ ((no_split_stack));
+
+_Bool
+CompareAndSwapUint64 (uint64_t *val, uint64_t old, uint64_t new)
+{
+  return __sync_bool_compare_and_swap (val, old, new);
+}
+
+_Bool CompareAndSwapUintptr (uintptr_t *, uintptr_t, uintptr_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUintptr")
+  __attribute__ ((no_split_stack));
+
+_Bool
+CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new)
+{
+  return __sync_bool_compare_and_swap (val, old, new);
+}
+
+_Bool CompareAndSwapPointer (void **, void *, void *)
+  __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapPointer")
+  __attribute__ ((no_split_stack));
+
+_Bool
+CompareAndSwapPointer (void **val, void *old, void *new)
+{
+  return __sync_bool_compare_and_swap (val, old, new);
+}
+
+int32_t AddInt32 (int32_t *, int32_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.AddInt32")
+  __attribute__ ((no_split_stack));
+
+int32_t
+AddInt32 (int32_t *val, int32_t delta)
+{
+  return __sync_add_and_fetch (val, delta);
+}
+
+uint32_t AddUint32 (uint32_t *, uint32_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.AddUint32")
+  __attribute__ ((no_split_stack));
+
+uint32_t
+AddUint32 (uint32_t *val, uint32_t delta)
+{
+  return __sync_add_and_fetch (val, delta);
+}
+
+int64_t AddInt64 (int64_t *, int64_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.AddInt64")
+  __attribute__ ((no_split_stack));
+
+int64_t
+AddInt64 (int64_t *val, int64_t delta)
+{
+  return __sync_add_and_fetch (val, delta);
+}
+
+uint64_t AddUint64 (uint64_t *, uint64_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.AddUint64")
+  __attribute__ ((no_split_stack));
+
+uint64_t
+AddUint64 (uint64_t *val, uint64_t delta)
+{
+  return __sync_add_and_fetch (val, delta);
+}
+
+uintptr_t AddUintptr (uintptr_t *, uintptr_t)
+  __asm__ (GOSYM_PREFIX "sync_atomic.AddUintptr")
+  __attribute__ ((no_split_stack));
+
+uintptr_t
+AddUintptr (uintptr_t *val, uintptr_t delta)
+{
+  return __sync_add_and_fetch (val, delta);
+}
+
+int32_t LoadInt32 (int32_t *addr)
+  __asm__ (GOSYM_PREFIX "sync_atomic.LoadInt32")
+  __attribute__ ((no_split_stack));
+
+int32_t
+LoadInt32 (int32_t *addr)
+{
+  int32_t v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, v))
+    v = *addr;
+  return v;
+}
+
+int64_t LoadInt64 (int64_t *addr)
+  __asm__ (GOSYM_PREFIX "sync_atomic.LoadInt64")
+  __attribute__ ((no_split_stack));
+
+int64_t
+LoadInt64 (int64_t *addr)
+{
+  int64_t v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, v))
+    v = *addr;
+  return v;
+}
+
+uint32_t LoadUint32 (uint32_t *addr)
+  __asm__ (GOSYM_PREFIX "sync_atomic.LoadUint32")
+  __attribute__ ((no_split_stack));
+
+uint32_t
+LoadUint32 (uint32_t *addr)
+{
+  uint32_t v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, v))
+    v = *addr;
+  return v;
+}
+
+uint64_t LoadUint64 (uint64_t *addr)
+  __asm__ (GOSYM_PREFIX "sync_atomic.LoadUint64")
+  __attribute__ ((no_split_stack));
+
+uint64_t
+LoadUint64 (uint64_t *addr)
+{
+  uint64_t v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, v))
+    v = *addr;
+  return v;
+}
+
+uintptr_t LoadUintptr (uintptr_t *addr)
+  __asm__ (GOSYM_PREFIX "sync_atomic.LoadUintptr")
+  __attribute__ ((no_split_stack));
+
+uintptr_t
+LoadUintptr (uintptr_t *addr)
+{
+  uintptr_t v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, v))
+    v = *addr;
+  return v;
+}
+
+void *LoadPointer (void **addr)
+  __asm__ (GOSYM_PREFIX "sync_atomic.LoadPointer")
+  __attribute__ ((no_split_stack));
+
+void *
+LoadPointer (void **addr)
+{
+  void *v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, v))
+    v = *addr;
+  return v;
+}
+
+void StoreInt32 (int32_t *addr, int32_t val)
+  __asm__ (GOSYM_PREFIX "sync_atomic.StoreInt32")
+  __attribute__ ((no_split_stack));
+
+void
+StoreInt32 (int32_t *addr, int32_t val)
+{
+  int32_t v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, val))
+    v = *addr;
+}
+
+void StoreInt64 (int64_t *addr, int64_t val)
+  __asm__ (GOSYM_PREFIX "sync_atomic.StoreInt64")
+  __attribute__ ((no_split_stack));
+
+void
+StoreInt64 (int64_t *addr, int64_t val)
+{
+  int64_t v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, val))
+    v = *addr;
+}
+
+void StoreUint32 (uint32_t *addr, uint32_t val)
+  __asm__ (GOSYM_PREFIX "sync_atomic.StoreUint32")
+  __attribute__ ((no_split_stack));
+
+void
+StoreUint32 (uint32_t *addr, uint32_t val)
+{
+  uint32_t v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, val))
+    v = *addr;
+}
+
+void StoreUint64 (uint64_t *addr, uint64_t val)
+  __asm__ (GOSYM_PREFIX "sync_atomic.StoreUint64")
+  __attribute__ ((no_split_stack));
+
+void
+StoreUint64 (uint64_t *addr, uint64_t val)
+{
+  uint64_t v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, val))
+    v = *addr;
+}
+
+void StoreUintptr (uintptr_t *addr, uintptr_t val)
+  __asm__ (GOSYM_PREFIX "sync_atomic.StoreUintptr")
+  __attribute__ ((no_split_stack));
+
+void
+StoreUintptr (uintptr_t *addr, uintptr_t val)
+{
+  uintptr_t v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, val))
+    v = *addr;
+}
+
+void StorePointer (void **addr, void *val)
+  __asm__ (GOSYM_PREFIX "sync_atomic.StorePointer")
+  __attribute__ ((no_split_stack));
+
+void
+StorePointer (void **addr, void *val)
+{
+  void *v;
+
+  v = *addr;
+  while (! __sync_bool_compare_and_swap (addr, v, val))
+    v = *addr;
+}
diff --git a/third_party/gofrontend/libgo/go/sync/atomic/atomic_test.go b/third_party/gofrontend/libgo/go/sync/atomic/atomic_test.go
new file mode 100644
index 0000000..eaa3b6b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/atomic/atomic_test.go
@@ -0,0 +1,1511 @@
+// 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.
+
+package atomic_test
+
+import (
+	"fmt"
+	"runtime"
+	"strings"
+	. "sync/atomic"
+	"testing"
+	"unsafe"
+)
+
+// Tests of correct behavior, without contention.
+// (Does the function work as advertised?)
+//
+// Test that the Add functions add correctly.
+// Test that the CompareAndSwap functions actually
+// do the comparison and the swap correctly.
+//
+// The loop over power-of-two values is meant to
+// ensure that the operations apply to the full word size.
+// The struct fields x.before and x.after check that the
+// operations do not extend past the full word size.
+
+const (
+	magic32 = 0xdedbeef
+	magic64 = 0xdeddeadbeefbeef
+)
+
+// Do the 64-bit functions panic?  If so, don't bother testing.
+var test64err = func() (err interface{}) {
+	defer func() {
+		err = recover()
+	}()
+	var x int64
+	AddInt64(&x, 1)
+	return nil
+}()
+
+func TestSwapInt32(t *testing.T) {
+	var x struct {
+		before int32
+		i      int32
+		after  int32
+	}
+	x.before = magic32
+	x.after = magic32
+	var j int32
+	for delta := int32(1); delta+delta > delta; delta += delta {
+		k := SwapInt32(&x.i, delta)
+		if x.i != delta || k != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+		j = delta
+	}
+	if x.before != magic32 || x.after != magic32 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+	}
+}
+
+func TestSwapUint32(t *testing.T) {
+	var x struct {
+		before uint32
+		i      uint32
+		after  uint32
+	}
+	x.before = magic32
+	x.after = magic32
+	var j uint32
+	for delta := uint32(1); delta+delta > delta; delta += delta {
+		k := SwapUint32(&x.i, delta)
+		if x.i != delta || k != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+		j = delta
+	}
+	if x.before != magic32 || x.after != magic32 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+	}
+}
+
+func TestSwapInt64(t *testing.T) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	var x struct {
+		before int64
+		i      int64
+		after  int64
+	}
+	x.before = magic64
+	x.after = magic64
+	var j int64
+	for delta := int64(1); delta+delta > delta; delta += delta {
+		k := SwapInt64(&x.i, delta)
+		if x.i != delta || k != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+		j = delta
+	}
+	if x.before != magic64 || x.after != magic64 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+	}
+}
+
+func TestSwapUint64(t *testing.T) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	var x struct {
+		before uint64
+		i      uint64
+		after  uint64
+	}
+	x.before = magic64
+	x.after = magic64
+	var j uint64
+	for delta := uint64(1); delta+delta > delta; delta += delta {
+		k := SwapUint64(&x.i, delta)
+		if x.i != delta || k != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+		j = delta
+	}
+	if x.before != magic64 || x.after != magic64 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+	}
+}
+
+func TestSwapUintptr(t *testing.T) {
+	var x struct {
+		before uintptr
+		i      uintptr
+		after  uintptr
+	}
+	var m uint64 = magic64
+	magicptr := uintptr(m)
+	x.before = magicptr
+	x.after = magicptr
+	var j uintptr
+	for delta := uintptr(1); delta+delta > delta; delta += delta {
+		k := SwapUintptr(&x.i, delta)
+		if x.i != delta || k != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+		j = delta
+	}
+	if x.before != magicptr || x.after != magicptr {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+	}
+}
+
+func TestSwapPointer(t *testing.T) {
+	var x struct {
+		before uintptr
+		i      unsafe.Pointer
+		after  uintptr
+	}
+	var m uint64 = magic64
+	magicptr := uintptr(m)
+	x.before = magicptr
+	x.after = magicptr
+	var j uintptr
+	for delta := uintptr(1); delta+delta > delta; delta += delta {
+		k := SwapPointer(&x.i, unsafe.Pointer(delta))
+		if uintptr(x.i) != delta || uintptr(k) != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+		j = delta
+	}
+	if x.before != magicptr || x.after != magicptr {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+	}
+}
+
+func TestAddInt32(t *testing.T) {
+	var x struct {
+		before int32
+		i      int32
+		after  int32
+	}
+	x.before = magic32
+	x.after = magic32
+	var j int32
+	for delta := int32(1); delta+delta > delta; delta += delta {
+		k := AddInt32(&x.i, delta)
+		j += delta
+		if x.i != j || k != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+	}
+	if x.before != magic32 || x.after != magic32 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+	}
+}
+
+func TestAddUint32(t *testing.T) {
+	var x struct {
+		before uint32
+		i      uint32
+		after  uint32
+	}
+	x.before = magic32
+	x.after = magic32
+	var j uint32
+	for delta := uint32(1); delta+delta > delta; delta += delta {
+		k := AddUint32(&x.i, delta)
+		j += delta
+		if x.i != j || k != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+	}
+	if x.before != magic32 || x.after != magic32 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+	}
+}
+
+func TestAddInt64(t *testing.T) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	var x struct {
+		before int64
+		i      int64
+		after  int64
+	}
+	x.before = magic64
+	x.after = magic64
+	var j int64
+	for delta := int64(1); delta+delta > delta; delta += delta {
+		k := AddInt64(&x.i, delta)
+		j += delta
+		if x.i != j || k != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+	}
+	if x.before != magic64 || x.after != magic64 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, int64(magic64), int64(magic64))
+	}
+}
+
+func TestAddUint64(t *testing.T) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	var x struct {
+		before uint64
+		i      uint64
+		after  uint64
+	}
+	x.before = magic64
+	x.after = magic64
+	var j uint64
+	for delta := uint64(1); delta+delta > delta; delta += delta {
+		k := AddUint64(&x.i, delta)
+		j += delta
+		if x.i != j || k != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+	}
+	if x.before != magic64 || x.after != magic64 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+	}
+}
+
+func TestAddUintptr(t *testing.T) {
+	var x struct {
+		before uintptr
+		i      uintptr
+		after  uintptr
+	}
+	var m uint64 = magic64
+	magicptr := uintptr(m)
+	x.before = magicptr
+	x.after = magicptr
+	var j uintptr
+	for delta := uintptr(1); delta+delta > delta; delta += delta {
+		k := AddUintptr(&x.i, delta)
+		j += delta
+		if x.i != j || k != j {
+			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+		}
+	}
+	if x.before != magicptr || x.after != magicptr {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+	}
+}
+
+func TestCompareAndSwapInt32(t *testing.T) {
+	var x struct {
+		before int32
+		i      int32
+		after  int32
+	}
+	x.before = magic32
+	x.after = magic32
+	for val := int32(1); val+val > val; val += val {
+		x.i = val
+		if !CompareAndSwapInt32(&x.i, val, val+1) {
+			t.Fatalf("should have swapped %#x %#x", val, val+1)
+		}
+		if x.i != val+1 {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+		x.i = val + 1
+		if CompareAndSwapInt32(&x.i, val, val+2) {
+			t.Fatalf("should not have swapped %#x %#x", val, val+2)
+		}
+		if x.i != val+1 {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+	}
+	if x.before != magic32 || x.after != magic32 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+	}
+}
+
+func TestCompareAndSwapUint32(t *testing.T) {
+	var x struct {
+		before uint32
+		i      uint32
+		after  uint32
+	}
+	x.before = magic32
+	x.after = magic32
+	for val := uint32(1); val+val > val; val += val {
+		x.i = val
+		if !CompareAndSwapUint32(&x.i, val, val+1) {
+			t.Fatalf("should have swapped %#x %#x", val, val+1)
+		}
+		if x.i != val+1 {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+		x.i = val + 1
+		if CompareAndSwapUint32(&x.i, val, val+2) {
+			t.Fatalf("should not have swapped %#x %#x", val, val+2)
+		}
+		if x.i != val+1 {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+	}
+	if x.before != magic32 || x.after != magic32 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+	}
+}
+
+func TestCompareAndSwapInt64(t *testing.T) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	var x struct {
+		before int64
+		i      int64
+		after  int64
+	}
+	x.before = magic64
+	x.after = magic64
+	for val := int64(1); val+val > val; val += val {
+		x.i = val
+		if !CompareAndSwapInt64(&x.i, val, val+1) {
+			t.Fatalf("should have swapped %#x %#x", val, val+1)
+		}
+		if x.i != val+1 {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+		x.i = val + 1
+		if CompareAndSwapInt64(&x.i, val, val+2) {
+			t.Fatalf("should not have swapped %#x %#x", val, val+2)
+		}
+		if x.i != val+1 {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+	}
+	if x.before != magic64 || x.after != magic64 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+	}
+}
+
+func testCompareAndSwapUint64(t *testing.T, cas func(*uint64, uint64, uint64) bool) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	var x struct {
+		before uint64
+		i      uint64
+		after  uint64
+	}
+	x.before = magic64
+	x.after = magic64
+	for val := uint64(1); val+val > val; val += val {
+		x.i = val
+		if !cas(&x.i, val, val+1) {
+			t.Fatalf("should have swapped %#x %#x", val, val+1)
+		}
+		if x.i != val+1 {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+		x.i = val + 1
+		if cas(&x.i, val, val+2) {
+			t.Fatalf("should not have swapped %#x %#x", val, val+2)
+		}
+		if x.i != val+1 {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+	}
+	if x.before != magic64 || x.after != magic64 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+	}
+}
+
+func TestCompareAndSwapUint64(t *testing.T) {
+	testCompareAndSwapUint64(t, CompareAndSwapUint64)
+}
+
+func TestCompareAndSwapUintptr(t *testing.T) {
+	var x struct {
+		before uintptr
+		i      uintptr
+		after  uintptr
+	}
+	var m uint64 = magic64
+	magicptr := uintptr(m)
+	x.before = magicptr
+	x.after = magicptr
+	for val := uintptr(1); val+val > val; val += val {
+		x.i = val
+		if !CompareAndSwapUintptr(&x.i, val, val+1) {
+			t.Fatalf("should have swapped %#x %#x", val, val+1)
+		}
+		if x.i != val+1 {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+		x.i = val + 1
+		if CompareAndSwapUintptr(&x.i, val, val+2) {
+			t.Fatalf("should not have swapped %#x %#x", val, val+2)
+		}
+		if x.i != val+1 {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+	}
+	if x.before != magicptr || x.after != magicptr {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+	}
+}
+
+func TestCompareAndSwapPointer(t *testing.T) {
+	var x struct {
+		before uintptr
+		i      unsafe.Pointer
+		after  uintptr
+	}
+	var m uint64 = magic64
+	magicptr := uintptr(m)
+	x.before = magicptr
+	x.after = magicptr
+	for val := uintptr(1); val+val > val; val += val {
+		x.i = unsafe.Pointer(val)
+		if !CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+1)) {
+			t.Fatalf("should have swapped %#x %#x", val, val+1)
+		}
+		if x.i != unsafe.Pointer(val+1) {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+		x.i = unsafe.Pointer(val + 1)
+		if CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+2)) {
+			t.Fatalf("should not have swapped %#x %#x", val, val+2)
+		}
+		if x.i != unsafe.Pointer(val+1) {
+			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+		}
+	}
+	if x.before != magicptr || x.after != magicptr {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+	}
+}
+
+func TestLoadInt32(t *testing.T) {
+	var x struct {
+		before int32
+		i      int32
+		after  int32
+	}
+	x.before = magic32
+	x.after = magic32
+	for delta := int32(1); delta+delta > delta; delta += delta {
+		k := LoadInt32(&x.i)
+		if k != x.i {
+			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
+		}
+		x.i += delta
+	}
+	if x.before != magic32 || x.after != magic32 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+	}
+}
+
+func TestLoadUint32(t *testing.T) {
+	var x struct {
+		before uint32
+		i      uint32
+		after  uint32
+	}
+	x.before = magic32
+	x.after = magic32
+	for delta := uint32(1); delta+delta > delta; delta += delta {
+		k := LoadUint32(&x.i)
+		if k != x.i {
+			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
+		}
+		x.i += delta
+	}
+	if x.before != magic32 || x.after != magic32 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+	}
+}
+
+func TestLoadInt64(t *testing.T) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	var x struct {
+		before int64
+		i      int64
+		after  int64
+	}
+	x.before = magic64
+	x.after = magic64
+	for delta := int64(1); delta+delta > delta; delta += delta {
+		k := LoadInt64(&x.i)
+		if k != x.i {
+			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
+		}
+		x.i += delta
+	}
+	if x.before != magic64 || x.after != magic64 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+	}
+}
+
+func TestLoadUint64(t *testing.T) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	var x struct {
+		before uint64
+		i      uint64
+		after  uint64
+	}
+	x.before = magic64
+	x.after = magic64
+	for delta := uint64(1); delta+delta > delta; delta += delta {
+		k := LoadUint64(&x.i)
+		if k != x.i {
+			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
+		}
+		x.i += delta
+	}
+	if x.before != magic64 || x.after != magic64 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+	}
+}
+
+func TestLoadUintptr(t *testing.T) {
+	var x struct {
+		before uintptr
+		i      uintptr
+		after  uintptr
+	}
+	var m uint64 = magic64
+	magicptr := uintptr(m)
+	x.before = magicptr
+	x.after = magicptr
+	for delta := uintptr(1); delta+delta > delta; delta += delta {
+		k := LoadUintptr(&x.i)
+		if k != x.i {
+			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
+		}
+		x.i += delta
+	}
+	if x.before != magicptr || x.after != magicptr {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+	}
+}
+
+func TestLoadPointer(t *testing.T) {
+	var x struct {
+		before uintptr
+		i      unsafe.Pointer
+		after  uintptr
+	}
+	var m uint64 = magic64
+	magicptr := uintptr(m)
+	x.before = magicptr
+	x.after = magicptr
+	for delta := uintptr(1); delta+delta > delta; delta += delta {
+		k := LoadPointer(&x.i)
+		if k != x.i {
+			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
+		}
+		x.i = unsafe.Pointer(uintptr(x.i) + delta)
+	}
+	if x.before != magicptr || x.after != magicptr {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+	}
+}
+
+func TestStoreInt32(t *testing.T) {
+	var x struct {
+		before int32
+		i      int32
+		after  int32
+	}
+	x.before = magic32
+	x.after = magic32
+	v := int32(0)
+	for delta := int32(1); delta+delta > delta; delta += delta {
+		StoreInt32(&x.i, v)
+		if x.i != v {
+			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+		}
+		v += delta
+	}
+	if x.before != magic32 || x.after != magic32 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+	}
+}
+
+func TestStoreUint32(t *testing.T) {
+	var x struct {
+		before uint32
+		i      uint32
+		after  uint32
+	}
+	x.before = magic32
+	x.after = magic32
+	v := uint32(0)
+	for delta := uint32(1); delta+delta > delta; delta += delta {
+		StoreUint32(&x.i, v)
+		if x.i != v {
+			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+		}
+		v += delta
+	}
+	if x.before != magic32 || x.after != magic32 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+	}
+}
+
+func TestStoreInt64(t *testing.T) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	var x struct {
+		before int64
+		i      int64
+		after  int64
+	}
+	x.before = magic64
+	x.after = magic64
+	v := int64(0)
+	for delta := int64(1); delta+delta > delta; delta += delta {
+		StoreInt64(&x.i, v)
+		if x.i != v {
+			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+		}
+		v += delta
+	}
+	if x.before != magic64 || x.after != magic64 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+	}
+}
+
+func TestStoreUint64(t *testing.T) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	var x struct {
+		before uint64
+		i      uint64
+		after  uint64
+	}
+	x.before = magic64
+	x.after = magic64
+	v := uint64(0)
+	for delta := uint64(1); delta+delta > delta; delta += delta {
+		StoreUint64(&x.i, v)
+		if x.i != v {
+			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+		}
+		v += delta
+	}
+	if x.before != magic64 || x.after != magic64 {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+	}
+}
+
+func TestStoreUintptr(t *testing.T) {
+	var x struct {
+		before uintptr
+		i      uintptr
+		after  uintptr
+	}
+	var m uint64 = magic64
+	magicptr := uintptr(m)
+	x.before = magicptr
+	x.after = magicptr
+	v := uintptr(0)
+	for delta := uintptr(1); delta+delta > delta; delta += delta {
+		StoreUintptr(&x.i, v)
+		if x.i != v {
+			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+		}
+		v += delta
+	}
+	if x.before != magicptr || x.after != magicptr {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+	}
+}
+
+func TestStorePointer(t *testing.T) {
+	var x struct {
+		before uintptr
+		i      unsafe.Pointer
+		after  uintptr
+	}
+	var m uint64 = magic64
+	magicptr := uintptr(m)
+	x.before = magicptr
+	x.after = magicptr
+	v := unsafe.Pointer(uintptr(0))
+	for delta := uintptr(1); delta+delta > delta; delta += delta {
+		StorePointer(&x.i, unsafe.Pointer(v))
+		if x.i != v {
+			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+		}
+		v = unsafe.Pointer(uintptr(v) + delta)
+	}
+	if x.before != magicptr || x.after != magicptr {
+		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+	}
+}
+
+// Tests of correct behavior, with contention.
+// (Is the function atomic?)
+//
+// For each function, we write a "hammer" function that repeatedly
+// uses the atomic operation to add 1 to a value.  After running
+// multiple hammers in parallel, check that we end with the correct
+// total.
+// Swap can't add 1, so it uses a different scheme.
+// The functions repeatedly generate a pseudo-random number such that
+// low bits are equal to high bits, swap, check that the old value
+// has low and high bits equal.
+
+var hammer32 = map[string]func(*uint32, int){
+	"SwapInt32":             hammerSwapInt32,
+	"SwapUint32":            hammerSwapUint32,
+	"SwapUintptr":           hammerSwapUintptr32,
+	"SwapPointer":           hammerSwapPointer32,
+	"AddInt32":              hammerAddInt32,
+	"AddUint32":             hammerAddUint32,
+	"AddUintptr":            hammerAddUintptr32,
+	"CompareAndSwapInt32":   hammerCompareAndSwapInt32,
+	"CompareAndSwapUint32":  hammerCompareAndSwapUint32,
+	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr32,
+	"CompareAndSwapPointer": hammerCompareAndSwapPointer32,
+}
+
+func init() {
+	var v uint64 = 1 << 50
+	if uintptr(v) != 0 {
+		// 64-bit system; clear uintptr tests
+		delete(hammer32, "SwapUintptr")
+		delete(hammer32, "SwapPointer")
+		delete(hammer32, "AddUintptr")
+		delete(hammer32, "CompareAndSwapUintptr")
+		delete(hammer32, "CompareAndSwapPointer")
+	}
+}
+
+func hammerSwapInt32(uaddr *uint32, count int) {
+	addr := (*int32)(unsafe.Pointer(uaddr))
+	seed := int(uintptr(unsafe.Pointer(&count)))
+	for i := 0; i < count; i++ {
+		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
+		old := uint32(SwapInt32(addr, int32(new)))
+		if old>>16 != old<<16>>16 {
+			panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
+		}
+	}
+}
+
+func hammerSwapUint32(addr *uint32, count int) {
+	seed := int(uintptr(unsafe.Pointer(&count)))
+	for i := 0; i < count; i++ {
+		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
+		old := SwapUint32(addr, new)
+		if old>>16 != old<<16>>16 {
+			panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
+		}
+	}
+}
+
+func hammerSwapUintptr32(uaddr *uint32, count int) {
+	// only safe when uintptr is 32-bit.
+	// not called on 64-bit systems.
+	addr := (*uintptr)(unsafe.Pointer(uaddr))
+	seed := int(uintptr(unsafe.Pointer(&count)))
+	for i := 0; i < count; i++ {
+		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
+		old := SwapUintptr(addr, new)
+		if old>>16 != old<<16>>16 {
+			panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old))
+		}
+	}
+}
+
+func hammerSwapPointer32(uaddr *uint32, count int) {
+	// only safe when uintptr is 32-bit.
+	// not called on 64-bit systems.
+	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
+	seed := int(uintptr(unsafe.Pointer(&count)))
+	for i := 0; i < count; i++ {
+		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
+		old := uintptr(SwapPointer(addr, unsafe.Pointer(new)))
+		if old>>16 != old<<16>>16 {
+			panic(fmt.Sprintf("SwapPointer is not atomic: %#08x", old))
+		}
+	}
+}
+
+func hammerAddInt32(uaddr *uint32, count int) {
+	addr := (*int32)(unsafe.Pointer(uaddr))
+	for i := 0; i < count; i++ {
+		AddInt32(addr, 1)
+	}
+}
+
+func hammerAddUint32(addr *uint32, count int) {
+	for i := 0; i < count; i++ {
+		AddUint32(addr, 1)
+	}
+}
+
+func hammerAddUintptr32(uaddr *uint32, count int) {
+	// only safe when uintptr is 32-bit.
+	// not called on 64-bit systems.
+	addr := (*uintptr)(unsafe.Pointer(uaddr))
+	for i := 0; i < count; i++ {
+		AddUintptr(addr, 1)
+	}
+}
+
+func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
+	addr := (*int32)(unsafe.Pointer(uaddr))
+	for i := 0; i < count; i++ {
+		for {
+			v := LoadInt32(addr)
+			if CompareAndSwapInt32(addr, v, v+1) {
+				break
+			}
+		}
+	}
+}
+
+func hammerCompareAndSwapUint32(addr *uint32, count int) {
+	for i := 0; i < count; i++ {
+		for {
+			v := LoadUint32(addr)
+			if CompareAndSwapUint32(addr, v, v+1) {
+				break
+			}
+		}
+	}
+}
+
+func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
+	// only safe when uintptr is 32-bit.
+	// not called on 64-bit systems.
+	addr := (*uintptr)(unsafe.Pointer(uaddr))
+	for i := 0; i < count; i++ {
+		for {
+			v := LoadUintptr(addr)
+			if CompareAndSwapUintptr(addr, v, v+1) {
+				break
+			}
+		}
+	}
+}
+
+func hammerCompareAndSwapPointer32(uaddr *uint32, count int) {
+	// only safe when uintptr is 32-bit.
+	// not called on 64-bit systems.
+	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
+	for i := 0; i < count; i++ {
+		for {
+			v := LoadPointer(addr)
+			if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
+				break
+			}
+		}
+	}
+}
+
+func TestHammer32(t *testing.T) {
+	const p = 4
+	n := 100000
+	if testing.Short() {
+		n = 1000
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
+
+	for name, testf := range hammer32 {
+		c := make(chan int)
+		var val uint32
+		for i := 0; i < p; i++ {
+			go func() {
+				defer func() {
+					if err := recover(); err != nil {
+						t.Error(err.(string))
+					}
+					c <- 1
+				}()
+				testf(&val, n)
+			}()
+		}
+		for i := 0; i < p; i++ {
+			<-c
+		}
+		if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p {
+			t.Fatalf("%s: val=%d want %d", name, val, n*p)
+		}
+	}
+}
+
+var hammer64 = map[string]func(*uint64, int){
+	"SwapInt64":             hammerSwapInt64,
+	"SwapUint64":            hammerSwapUint64,
+	"SwapUintptr":           hammerSwapUintptr64,
+	"SwapPointer":           hammerSwapPointer64,
+	"AddInt64":              hammerAddInt64,
+	"AddUint64":             hammerAddUint64,
+	"AddUintptr":            hammerAddUintptr64,
+	"CompareAndSwapInt64":   hammerCompareAndSwapInt64,
+	"CompareAndSwapUint64":  hammerCompareAndSwapUint64,
+	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr64,
+	"CompareAndSwapPointer": hammerCompareAndSwapPointer64,
+}
+
+func init() {
+	var v uint64 = 1 << 50
+	if uintptr(v) == 0 {
+		// 32-bit system; clear uintptr tests
+		delete(hammer64, "SwapUintptr")
+		delete(hammer64, "SwapPointer")
+		delete(hammer64, "AddUintptr")
+		delete(hammer64, "CompareAndSwapUintptr")
+		delete(hammer64, "CompareAndSwapPointer")
+	}
+}
+
+func hammerSwapInt64(uaddr *uint64, count int) {
+	addr := (*int64)(unsafe.Pointer(uaddr))
+	seed := int(uintptr(unsafe.Pointer(&count)))
+	for i := 0; i < count; i++ {
+		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
+		old := uint64(SwapInt64(addr, int64(new)))
+		if old>>32 != old<<32>>32 {
+			panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
+		}
+	}
+}
+
+func hammerSwapUint64(addr *uint64, count int) {
+	seed := int(uintptr(unsafe.Pointer(&count)))
+	for i := 0; i < count; i++ {
+		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
+		old := SwapUint64(addr, new)
+		if old>>32 != old<<32>>32 {
+			panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
+		}
+	}
+}
+
+func hammerSwapUintptr64(uaddr *uint64, count int) {
+	// only safe when uintptr is 64-bit.
+	// not called on 32-bit systems.
+	addr := (*uintptr)(unsafe.Pointer(uaddr))
+	seed := int(uintptr(unsafe.Pointer(&count)))
+	for i := 0; i < count; i++ {
+		new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
+		old := SwapUintptr(addr, new)
+		if old>>32 != old<<32>>32 {
+			panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
+		}
+	}
+}
+
+func hammerSwapPointer64(uaddr *uint64, count int) {
+	// only safe when uintptr is 64-bit.
+	// not called on 32-bit systems.
+	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
+	seed := int(uintptr(unsafe.Pointer(&count)))
+	for i := 0; i < count; i++ {
+		new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
+		old := uintptr(SwapPointer(addr, unsafe.Pointer(new)))
+		if old>>32 != old<<32>>32 {
+			panic(fmt.Sprintf("SwapPointer is not atomic: %v", old))
+		}
+	}
+}
+
+func hammerAddInt64(uaddr *uint64, count int) {
+	addr := (*int64)(unsafe.Pointer(uaddr))
+	for i := 0; i < count; i++ {
+		AddInt64(addr, 1)
+	}
+}
+
+func hammerAddUint64(addr *uint64, count int) {
+	for i := 0; i < count; i++ {
+		AddUint64(addr, 1)
+	}
+}
+
+func hammerAddUintptr64(uaddr *uint64, count int) {
+	// only safe when uintptr is 64-bit.
+	// not called on 32-bit systems.
+	addr := (*uintptr)(unsafe.Pointer(uaddr))
+	for i := 0; i < count; i++ {
+		AddUintptr(addr, 1)
+	}
+}
+
+func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
+	addr := (*int64)(unsafe.Pointer(uaddr))
+	for i := 0; i < count; i++ {
+		for {
+			v := LoadInt64(addr)
+			if CompareAndSwapInt64(addr, v, v+1) {
+				break
+			}
+		}
+	}
+}
+
+func hammerCompareAndSwapUint64(addr *uint64, count int) {
+	for i := 0; i < count; i++ {
+		for {
+			v := LoadUint64(addr)
+			if CompareAndSwapUint64(addr, v, v+1) {
+				break
+			}
+		}
+	}
+}
+
+func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
+	// only safe when uintptr is 64-bit.
+	// not called on 32-bit systems.
+	addr := (*uintptr)(unsafe.Pointer(uaddr))
+	for i := 0; i < count; i++ {
+		for {
+			v := LoadUintptr(addr)
+			if CompareAndSwapUintptr(addr, v, v+1) {
+				break
+			}
+		}
+	}
+}
+
+func hammerCompareAndSwapPointer64(uaddr *uint64, count int) {
+	// only safe when uintptr is 64-bit.
+	// not called on 32-bit systems.
+	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
+	for i := 0; i < count; i++ {
+		for {
+			v := LoadPointer(addr)
+			if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
+				break
+			}
+		}
+	}
+}
+
+func TestHammer64(t *testing.T) {
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	const p = 4
+	n := 100000
+	if testing.Short() {
+		n = 1000
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
+
+	for name, testf := range hammer64 {
+		c := make(chan int)
+		var val uint64
+		for i := 0; i < p; i++ {
+			go func() {
+				defer func() {
+					if err := recover(); err != nil {
+						t.Error(err.(string))
+					}
+					c <- 1
+				}()
+				testf(&val, n)
+			}()
+		}
+		for i := 0; i < p; i++ {
+			<-c
+		}
+		if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p {
+			t.Fatalf("%s: val=%d want %d", name, val, n*p)
+		}
+	}
+}
+
+func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*int32)(paddr)
+	v := LoadInt32(addr)
+	vlo := v & ((1 << 16) - 1)
+	vhi := v >> 16
+	if vlo != vhi {
+		t.Fatalf("Int32: %#x != %#x", vlo, vhi)
+	}
+	new := v + 1 + 1<<16
+	if vlo == 1e4 {
+		new = 0
+	}
+	StoreInt32(addr, new)
+}
+
+func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*uint32)(paddr)
+	v := LoadUint32(addr)
+	vlo := v & ((1 << 16) - 1)
+	vhi := v >> 16
+	if vlo != vhi {
+		t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
+	}
+	new := v + 1 + 1<<16
+	if vlo == 1e4 {
+		new = 0
+	}
+	StoreUint32(addr, new)
+}
+
+func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*int64)(paddr)
+	v := LoadInt64(addr)
+	vlo := v & ((1 << 32) - 1)
+	vhi := v >> 32
+	if vlo != vhi {
+		t.Fatalf("Int64: %#x != %#x", vlo, vhi)
+	}
+	new := v + 1 + 1<<32
+	StoreInt64(addr, new)
+}
+
+func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*uint64)(paddr)
+	v := LoadUint64(addr)
+	vlo := v & ((1 << 32) - 1)
+	vhi := v >> 32
+	if vlo != vhi {
+		t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
+	}
+	new := v + 1 + 1<<32
+	StoreUint64(addr, new)
+}
+
+func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*uintptr)(paddr)
+	var test64 uint64 = 1 << 50
+	arch32 := uintptr(test64) == 0
+	v := LoadUintptr(addr)
+	new := v
+	if arch32 {
+		vlo := v & ((1 << 16) - 1)
+		vhi := v >> 16
+		if vlo != vhi {
+			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
+		}
+		new = v + 1 + 1<<16
+		if vlo == 1e4 {
+			new = 0
+		}
+	} else {
+		vlo := v & ((1 << 32) - 1)
+		vhi := v >> 32
+		if vlo != vhi {
+			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
+		}
+		inc := uint64(1 + 1<<32)
+		new = v + uintptr(inc)
+	}
+	StoreUintptr(addr, new)
+}
+
+func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*unsafe.Pointer)(paddr)
+	var test64 uint64 = 1 << 50
+	arch32 := uintptr(test64) == 0
+	v := uintptr(LoadPointer(addr))
+	new := v
+	if arch32 {
+		vlo := v & ((1 << 16) - 1)
+		vhi := v >> 16
+		if vlo != vhi {
+			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
+		}
+		new = v + 1 + 1<<16
+		if vlo == 1e4 {
+			new = 0
+		}
+	} else {
+		vlo := v & ((1 << 32) - 1)
+		vhi := v >> 32
+		if vlo != vhi {
+			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
+		}
+		inc := uint64(1 + 1<<32)
+		new = v + uintptr(inc)
+	}
+	StorePointer(addr, unsafe.Pointer(new))
+}
+
+func TestHammerStoreLoad(t *testing.T) {
+	var tests []func(*testing.T, unsafe.Pointer)
+	tests = append(tests, hammerStoreLoadInt32, hammerStoreLoadUint32,
+		hammerStoreLoadUintptr, hammerStoreLoadPointer)
+	if test64err == nil {
+		tests = append(tests, hammerStoreLoadInt64, hammerStoreLoadUint64)
+	}
+	n := int(1e6)
+	if testing.Short() {
+		n = int(1e4)
+	}
+	const procs = 8
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))
+	for _, tt := range tests {
+		c := make(chan int)
+		var val uint64
+		for p := 0; p < procs; p++ {
+			go func() {
+				for i := 0; i < n; i++ {
+					tt(t, unsafe.Pointer(&val))
+				}
+				c <- 1
+			}()
+		}
+		for p := 0; p < procs; p++ {
+			<-c
+		}
+	}
+}
+
+func TestStoreLoadSeqCst32(t *testing.T) {
+	if runtime.NumCPU() == 1 {
+		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	N := int32(1e3)
+	if testing.Short() {
+		N = int32(1e2)
+	}
+	c := make(chan bool, 2)
+	X := [2]int32{}
+	ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}}
+	for p := 0; p < 2; p++ {
+		go func(me int) {
+			he := 1 - me
+			for i := int32(1); i < N; i++ {
+				StoreInt32(&X[me], i)
+				my := LoadInt32(&X[he])
+				StoreInt32(&ack[me][i%3], my)
+				for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ {
+					if w%1000 == 0 {
+						runtime.Gosched()
+					}
+				}
+				his := LoadInt32(&ack[he][i%3])
+				if (my != i && my != i-1) || (his != i && his != i-1) {
+					t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
+				}
+				if my != i && his != i {
+					t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
+				}
+				StoreInt32(&ack[me][(i-1)%3], -1)
+			}
+			c <- true
+		}(p)
+	}
+	<-c
+	<-c
+}
+
+func TestStoreLoadSeqCst64(t *testing.T) {
+	if runtime.NumCPU() == 1 {
+		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
+	}
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	N := int64(1e3)
+	if testing.Short() {
+		N = int64(1e2)
+	}
+	c := make(chan bool, 2)
+	X := [2]int64{}
+	ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}}
+	for p := 0; p < 2; p++ {
+		go func(me int) {
+			he := 1 - me
+			for i := int64(1); i < N; i++ {
+				StoreInt64(&X[me], i)
+				my := LoadInt64(&X[he])
+				StoreInt64(&ack[me][i%3], my)
+				for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ {
+					if w%1000 == 0 {
+						runtime.Gosched()
+					}
+				}
+				his := LoadInt64(&ack[he][i%3])
+				if (my != i && my != i-1) || (his != i && his != i-1) {
+					t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
+				}
+				if my != i && his != i {
+					t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
+				}
+				StoreInt64(&ack[me][(i-1)%3], -1)
+			}
+			c <- true
+		}(p)
+	}
+	<-c
+	<-c
+}
+
+func TestStoreLoadRelAcq32(t *testing.T) {
+	if runtime.NumCPU() == 1 {
+		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	N := int32(1e3)
+	if testing.Short() {
+		N = int32(1e2)
+	}
+	c := make(chan bool, 2)
+	type Data struct {
+		signal int32
+		pad1   [128]int8
+		data1  int32
+		pad2   [128]int8
+		data2  float32
+	}
+	var X Data
+	for p := int32(0); p < 2; p++ {
+		go func(p int32) {
+			for i := int32(1); i < N; i++ {
+				if (i+p)%2 == 0 {
+					X.data1 = i
+					X.data2 = float32(i)
+					StoreInt32(&X.signal, i)
+				} else {
+					for w := 1; LoadInt32(&X.signal) != i; w++ {
+						if w%1000 == 0 {
+							runtime.Gosched()
+						}
+					}
+					d1 := X.data1
+					d2 := X.data2
+					if d1 != i || d2 != float32(i) {
+						t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
+					}
+				}
+			}
+			c <- true
+		}(p)
+	}
+	<-c
+	<-c
+}
+
+func TestStoreLoadRelAcq64(t *testing.T) {
+	if runtime.NumCPU() == 1 {
+		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
+	}
+	if test64err != nil {
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	N := int64(1e3)
+	if testing.Short() {
+		N = int64(1e2)
+	}
+	c := make(chan bool, 2)
+	type Data struct {
+		signal int64
+		pad1   [128]int8
+		data1  int64
+		pad2   [128]int8
+		data2  float64
+	}
+	var X Data
+	for p := int64(0); p < 2; p++ {
+		go func(p int64) {
+			for i := int64(1); i < N; i++ {
+				if (i+p)%2 == 0 {
+					X.data1 = i
+					X.data2 = float64(i)
+					StoreInt64(&X.signal, i)
+				} else {
+					for w := 1; LoadInt64(&X.signal) != i; w++ {
+						if w%1000 == 0 {
+							runtime.Gosched()
+						}
+					}
+					d1 := X.data1
+					d2 := X.data2
+					if d1 != i || d2 != float64(i) {
+						t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
+					}
+				}
+			}
+			c <- true
+		}(p)
+	}
+	<-c
+	<-c
+}
+
+func shouldPanic(t *testing.T, name string, f func()) {
+	defer func() {
+		if recover() == nil {
+			t.Errorf("%s did not panic", name)
+		}
+	}()
+	f()
+}
+
+func TestUnaligned64(t *testing.T) {
+	// Unaligned 64-bit atomics on 32-bit systems are
+	// a continual source of pain. Test that on 32-bit systems they crash
+	// instead of failing silently.
+	if unsafe.Sizeof(int(0)) != 4 {
+		t.Skip("test only runs on 32-bit systems")
+	}
+
+	t.Skip("skipping test for gccgo")
+
+	x := make([]uint32, 4)
+	p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
+
+	shouldPanic(t, "LoadUint64", func() { LoadUint64(p) })
+	shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) })
+	shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
+	shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
+}
+
+func TestNilDeref(t *testing.T) {
+	if p := runtime.GOOS + "/" + runtime.GOARCH; p == "freebsd/arm" || p == "netbsd/arm" {
+		t.Skipf("issue 7338: skipping test on %q", p)
+	}
+	funcs := [...]func(){
+		func() { CompareAndSwapInt32(nil, 0, 0) },
+		func() { CompareAndSwapInt64(nil, 0, 0) },
+		func() { CompareAndSwapUint32(nil, 0, 0) },
+		func() { CompareAndSwapUint64(nil, 0, 0) },
+		func() { CompareAndSwapUintptr(nil, 0, 0) },
+		func() { CompareAndSwapPointer(nil, nil, nil) },
+		func() { SwapInt32(nil, 0) },
+		func() { SwapUint32(nil, 0) },
+		func() { SwapInt64(nil, 0) },
+		func() { SwapUint64(nil, 0) },
+		func() { SwapUintptr(nil, 0) },
+		func() { SwapPointer(nil, nil) },
+		func() { AddInt32(nil, 0) },
+		func() { AddUint32(nil, 0) },
+		func() { AddInt64(nil, 0) },
+		func() { AddUint64(nil, 0) },
+		func() { AddUintptr(nil, 0) },
+		func() { LoadInt32(nil) },
+		func() { LoadInt64(nil) },
+		func() { LoadUint32(nil) },
+		func() { LoadUint64(nil) },
+		func() { LoadUintptr(nil) },
+		func() { LoadPointer(nil) },
+		func() { StoreInt32(nil, 0) },
+		func() { StoreInt64(nil, 0) },
+		func() { StoreUint32(nil, 0) },
+		func() { StoreUint64(nil, 0) },
+		func() { StoreUintptr(nil, 0) },
+		func() { StorePointer(nil, nil) },
+	}
+	for _, f := range funcs {
+		func() {
+			defer func() {
+				runtime.GC()
+				recover()
+			}()
+			f()
+		}()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/sync/atomic/doc.go b/third_party/gofrontend/libgo/go/sync/atomic/doc.go
new file mode 100644
index 0000000..17ba72f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/atomic/doc.go
@@ -0,0 +1,151 @@
+// 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.
+
+// +build !race
+
+// Package atomic provides low-level atomic memory primitives
+// useful for implementing synchronization algorithms.
+//
+// These functions require great care to be used correctly.
+// Except for special, low-level applications, synchronization is better
+// done with channels or the facilities of the sync package.
+// Share memory by communicating;
+// don't communicate by sharing memory.
+//
+// The swap operation, implemented by the SwapT functions, is the atomic
+// equivalent of:
+//
+//	old = *addr
+//	*addr = new
+//	return old
+//
+// The compare-and-swap operation, implemented by the CompareAndSwapT
+// functions, is the atomic equivalent of:
+//
+//	if *addr == old {
+//		*addr = new
+//		return true
+//	}
+//	return false
+//
+// The add operation, implemented by the AddT functions, is the atomic
+// equivalent of:
+//
+//	*addr += delta
+//	return *addr
+//
+// The load and store operations, implemented by the LoadT and StoreT
+// functions, are the atomic equivalents of "return *addr" and
+// "*addr = val".
+//
+package atomic
+
+import (
+	"unsafe"
+)
+
+// BUG(rsc): On x86-32, the 64-bit functions use instructions unavailable before the Pentium MMX.
+//
+// On non-Linux ARM, the 64-bit functions use instructions unavailable before the ARMv6k core.
+//
+// On both ARM and x86-32, it is the caller's responsibility to arrange for 64-bit
+// alignment of 64-bit words accessed atomically. The first word in a global
+// variable or in an allocated struct or slice can be relied upon to be
+// 64-bit aligned.
+
+// SwapInt32 atomically stores new into *addr and returns the previous *addr value.
+func SwapInt32(addr *int32, new int32) (old int32)
+
+// SwapInt64 atomically stores new into *addr and returns the previous *addr value.
+func SwapInt64(addr *int64, new int64) (old int64)
+
+// SwapUint32 atomically stores new into *addr and returns the previous *addr value.
+func SwapUint32(addr *uint32, new uint32) (old uint32)
+
+// SwapUint64 atomically stores new into *addr and returns the previous *addr value.
+func SwapUint64(addr *uint64, new uint64) (old uint64)
+
+// SwapUintptr atomically stores new into *addr and returns the previous *addr value.
+func SwapUintptr(addr *uintptr, new uintptr) (old uintptr)
+
+// SwapPointer atomically stores new into *addr and returns the previous *addr value.
+func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)
+
+// CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value.
+func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
+
+// CompareAndSwapInt64 executes the compare-and-swap operation for an int64 value.
+func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
+
+// CompareAndSwapUint32 executes the compare-and-swap operation for a uint32 value.
+func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)
+
+// CompareAndSwapUint64 executes the compare-and-swap operation for a uint64 value.
+func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool)
+
+// CompareAndSwapUintptr executes the compare-and-swap operation for a uintptr value.
+func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool)
+
+// CompareAndSwapPointer executes the compare-and-swap operation for a unsafe.Pointer value.
+func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
+
+// AddInt32 atomically adds delta to *addr and returns the new value.
+func AddInt32(addr *int32, delta int32) (new int32)
+
+// AddUint32 atomically adds delta to *addr and returns the new value.
+// To subtract a signed positive constant value c from x, do AddUint32(&x, ^uint32(c-1)).
+// In particular, to decrement x, do AddUint32(&x, ^uint32(0)).
+func AddUint32(addr *uint32, delta uint32) (new uint32)
+
+// AddInt64 atomically adds delta to *addr and returns the new value.
+func AddInt64(addr *int64, delta int64) (new int64)
+
+// AddUint64 atomically adds delta to *addr and returns the new value.
+// To subtract a signed positive constant value c from x, do AddUint64(&x, ^uint64(c-1)).
+// In particular, to decrement x, do AddUint64(&x, ^uint64(0)).
+func AddUint64(addr *uint64, delta uint64) (new uint64)
+
+// AddUintptr atomically adds delta to *addr and returns the new value.
+func AddUintptr(addr *uintptr, delta uintptr) (new uintptr)
+
+// LoadInt32 atomically loads *addr.
+func LoadInt32(addr *int32) (val int32)
+
+// LoadInt64 atomically loads *addr.
+func LoadInt64(addr *int64) (val int64)
+
+// LoadUint32 atomically loads *addr.
+func LoadUint32(addr *uint32) (val uint32)
+
+// LoadUint64 atomically loads *addr.
+func LoadUint64(addr *uint64) (val uint64)
+
+// LoadUintptr atomically loads *addr.
+func LoadUintptr(addr *uintptr) (val uintptr)
+
+// LoadPointer atomically loads *addr.
+func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)
+
+// StoreInt32 atomically stores val into *addr.
+func StoreInt32(addr *int32, val int32)
+
+// StoreInt64 atomically stores val into *addr.
+func StoreInt64(addr *int64, val int64)
+
+// StoreUint32 atomically stores val into *addr.
+func StoreUint32(addr *uint32, val uint32)
+
+// StoreUint64 atomically stores val into *addr.
+func StoreUint64(addr *uint64, val uint64)
+
+// StoreUintptr atomically stores val into *addr.
+func StoreUintptr(addr *uintptr, val uintptr)
+
+// StorePointer atomically stores val into *addr.
+func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer)
+
+// Helper for ARM.  Linker will discard on other systems
+func panic64() {
+	panic("sync/atomic: broken 64-bit atomic operations (buggy QEMU)")
+}
diff --git a/third_party/gofrontend/libgo/go/sync/atomic/race.go b/third_party/gofrontend/libgo/go/sync/atomic/race.go
new file mode 100644
index 0000000..6cbbf12
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/atomic/race.go
@@ -0,0 +1,276 @@
+// 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.
+
+// +build race
+
+package atomic
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+// We use runtime.RaceRead() inside of atomic operations to catch races
+// between atomic and non-atomic operations.  It will also catch races
+// between Mutex.Lock() and mutex overwrite (mu = Mutex{}).  Since we use
+// only RaceRead() we won't catch races with non-atomic loads.
+// Otherwise (if we use RaceWrite()) we will report races
+// between atomic operations (false positives).
+
+var mtx uint32 = 1 // same for all
+
+func SwapInt32(addr *int32, new int32) (old int32) {
+	return int32(SwapUint32((*uint32)(unsafe.Pointer(addr)), uint32(new)))
+}
+
+func SwapUint32(addr *uint32, new uint32) (old uint32) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	runtime.RaceAcquire(unsafe.Pointer(addr))
+	old = *addr
+	*addr = new
+	runtime.RaceReleaseMerge(unsafe.Pointer(addr))
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func SwapInt64(addr *int64, new int64) (old int64) {
+	return int64(SwapUint64((*uint64)(unsafe.Pointer(addr)), uint64(new)))
+}
+
+func SwapUint64(addr *uint64, new uint64) (old uint64) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	runtime.RaceAcquire(unsafe.Pointer(addr))
+	old = *addr
+	*addr = new
+	runtime.RaceReleaseMerge(unsafe.Pointer(addr))
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func SwapUintptr(addr *uintptr, new uintptr) (old uintptr) {
+	return uintptr(SwapPointer((*unsafe.Pointer)(unsafe.Pointer(addr)), unsafe.Pointer(new)))
+}
+
+func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	runtime.RaceAcquire(unsafe.Pointer(addr))
+	old = *addr
+	*addr = new
+	runtime.RaceReleaseMerge(unsafe.Pointer(addr))
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func CompareAndSwapInt32(val *int32, old, new int32) bool {
+	return CompareAndSwapUint32((*uint32)(unsafe.Pointer(val)), uint32(old), uint32(new))
+}
+
+func CompareAndSwapUint32(val *uint32, old, new uint32) (swapped bool) {
+	_ = *val
+	swapped = false
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(val))
+	runtime.RaceAcquire(unsafe.Pointer(val))
+	if *val == old {
+		*val = new
+		swapped = true
+		runtime.RaceReleaseMerge(unsafe.Pointer(val))
+	}
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func CompareAndSwapInt64(val *int64, old, new int64) bool {
+	return CompareAndSwapUint64((*uint64)(unsafe.Pointer(val)), uint64(old), uint64(new))
+}
+
+func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool) {
+	_ = *val
+	swapped = false
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(val))
+	runtime.RaceAcquire(unsafe.Pointer(val))
+	if *val == old {
+		*val = new
+		swapped = true
+		runtime.RaceReleaseMerge(unsafe.Pointer(val))
+	}
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) {
+	_ = *val
+	swapped = false
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(val))
+	runtime.RaceAcquire(unsafe.Pointer(val))
+	if *val == old {
+		*val = new
+		swapped = true
+		runtime.RaceReleaseMerge(unsafe.Pointer(val))
+	}
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool) {
+	_ = *val
+	swapped = false
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(val))
+	runtime.RaceAcquire(unsafe.Pointer(val))
+	if *val == old {
+		*val = new
+		swapped = true
+		runtime.RaceReleaseMerge(unsafe.Pointer(val))
+	}
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func AddInt32(val *int32, delta int32) int32 {
+	return int32(AddUint32((*uint32)(unsafe.Pointer(val)), uint32(delta)))
+}
+
+func AddUint32(val *uint32, delta uint32) (new uint32) {
+	_ = *val
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(val))
+	runtime.RaceAcquire(unsafe.Pointer(val))
+	*val = *val + delta
+	new = *val
+	runtime.RaceReleaseMerge(unsafe.Pointer(val))
+	runtime.RaceSemrelease(&mtx)
+
+	return
+}
+
+func AddInt64(val *int64, delta int64) int64 {
+	return int64(AddUint64((*uint64)(unsafe.Pointer(val)), uint64(delta)))
+}
+
+func AddUint64(val *uint64, delta uint64) (new uint64) {
+	_ = *val
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(val))
+	runtime.RaceAcquire(unsafe.Pointer(val))
+	*val = *val + delta
+	new = *val
+	runtime.RaceReleaseMerge(unsafe.Pointer(val))
+	runtime.RaceSemrelease(&mtx)
+
+	return
+}
+
+func AddUintptr(val *uintptr, delta uintptr) (new uintptr) {
+	_ = *val
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(val))
+	runtime.RaceAcquire(unsafe.Pointer(val))
+	*val = *val + delta
+	new = *val
+	runtime.RaceReleaseMerge(unsafe.Pointer(val))
+	runtime.RaceSemrelease(&mtx)
+
+	return
+}
+
+func LoadInt32(addr *int32) int32 {
+	return int32(LoadUint32((*uint32)(unsafe.Pointer(addr))))
+}
+
+func LoadUint32(addr *uint32) (val uint32) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	runtime.RaceAcquire(unsafe.Pointer(addr))
+	val = *addr
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func LoadInt64(addr *int64) int64 {
+	return int64(LoadUint64((*uint64)(unsafe.Pointer(addr))))
+}
+
+func LoadUint64(addr *uint64) (val uint64) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	runtime.RaceAcquire(unsafe.Pointer(addr))
+	val = *addr
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	runtime.RaceAcquire(unsafe.Pointer(addr))
+	val = *addr
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func LoadUintptr(addr *uintptr) (val uintptr) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	runtime.RaceAcquire(unsafe.Pointer(addr))
+	val = *addr
+	runtime.RaceSemrelease(&mtx)
+	return
+}
+
+func StoreInt32(addr *int32, val int32) {
+	StoreUint32((*uint32)(unsafe.Pointer(addr)), uint32(val))
+}
+
+func StoreUint32(addr *uint32, val uint32) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	*addr = val
+	runtime.RaceRelease(unsafe.Pointer(addr))
+	runtime.RaceSemrelease(&mtx)
+}
+
+func StoreInt64(addr *int64, val int64) {
+	StoreUint64((*uint64)(unsafe.Pointer(addr)), uint64(val))
+}
+
+func StoreUint64(addr *uint64, val uint64) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	*addr = val
+	runtime.RaceRelease(unsafe.Pointer(addr))
+	runtime.RaceSemrelease(&mtx)
+}
+
+func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	*addr = val
+	runtime.RaceRelease(unsafe.Pointer(addr))
+	runtime.RaceSemrelease(&mtx)
+}
+
+func StoreUintptr(addr *uintptr, val uintptr) {
+	_ = *addr
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	*addr = val
+	runtime.RaceRelease(unsafe.Pointer(addr))
+	runtime.RaceSemrelease(&mtx)
+}
diff --git a/third_party/gofrontend/libgo/go/sync/cas.c b/third_party/gofrontend/libgo/go/sync/cas.c
new file mode 100644
index 0000000..7571c64
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/cas.c
@@ -0,0 +1,17 @@
+/* cas.c -- implement sync.cas for Go.
+
+   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.  */
+
+#include <stdint.h>
+
+#include "runtime.h"
+
+_Bool cas (int32_t *, int32_t, int32_t) __asm__ (GOSYM_PREFIX "libgo_sync.sync.cas");
+
+_Bool
+cas (int32_t *ptr, int32_t old, int32_t new)
+{
+  return __sync_bool_compare_and_swap (ptr, old, new);
+}
diff --git a/third_party/gofrontend/libgo/go/sync/cond.go b/third_party/gofrontend/libgo/go/sync/cond.go
new file mode 100644
index 0000000..9e6bc17
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/cond.go
@@ -0,0 +1,118 @@
+// 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.
+
+package sync
+
+import (
+	"sync/atomic"
+	"unsafe"
+)
+
+// Cond implements a condition variable, a rendezvous point
+// for goroutines waiting for or announcing the occurrence
+// of an event.
+//
+// Each Cond has an associated Locker L (often a *Mutex or *RWMutex),
+// which must be held when changing the condition and
+// when calling the Wait method.
+//
+// A Cond can be created as part of other structures.
+// A Cond must not be copied after first use.
+type Cond struct {
+	// L is held while observing or changing the condition
+	L Locker
+
+	sema    syncSema
+	waiters uint32 // number of waiters
+	checker copyChecker
+}
+
+// NewCond returns a new Cond with Locker l.
+func NewCond(l Locker) *Cond {
+	return &Cond{L: l}
+}
+
+// Wait atomically unlocks c.L and suspends execution
+// of the calling goroutine.  After later resuming execution,
+// Wait locks c.L before returning.  Unlike in other systems,
+// Wait cannot return unless awoken by Broadcast or Signal.
+//
+// Because c.L is not locked when Wait first resumes, the caller
+// typically cannot assume that the condition is true when
+// Wait returns.  Instead, the caller should Wait in a loop:
+//
+//    c.L.Lock()
+//    for !condition() {
+//        c.Wait()
+//    }
+//    ... make use of condition ...
+//    c.L.Unlock()
+//
+func (c *Cond) Wait() {
+	c.checker.check()
+	if raceenabled {
+		raceDisable()
+	}
+	atomic.AddUint32(&c.waiters, 1)
+	if raceenabled {
+		raceEnable()
+	}
+	c.L.Unlock()
+	runtime_Syncsemacquire(&c.sema)
+	c.L.Lock()
+}
+
+// Signal wakes one goroutine waiting on c, if there is any.
+//
+// It is allowed but not required for the caller to hold c.L
+// during the call.
+func (c *Cond) Signal() {
+	c.signalImpl(false)
+}
+
+// Broadcast wakes all goroutines waiting on c.
+//
+// It is allowed but not required for the caller to hold c.L
+// during the call.
+func (c *Cond) Broadcast() {
+	c.signalImpl(true)
+}
+
+func (c *Cond) signalImpl(all bool) {
+	c.checker.check()
+	if raceenabled {
+		raceDisable()
+	}
+	for {
+		old := atomic.LoadUint32(&c.waiters)
+		if old == 0 {
+			if raceenabled {
+				raceEnable()
+			}
+			return
+		}
+		new := old - 1
+		if all {
+			new = 0
+		}
+		if atomic.CompareAndSwapUint32(&c.waiters, old, new) {
+			if raceenabled {
+				raceEnable()
+			}
+			runtime_Syncsemrelease(&c.sema, old-new)
+			return
+		}
+	}
+}
+
+// copyChecker holds back pointer to itself to detect object copying.
+type copyChecker uintptr
+
+func (c *copyChecker) check() {
+	if uintptr(*c) != uintptr(unsafe.Pointer(c)) &&
+		!atomic.CompareAndSwapUintptr((*uintptr)(c), 0, uintptr(unsafe.Pointer(c))) &&
+		uintptr(*c) != uintptr(unsafe.Pointer(c)) {
+		panic("sync.Cond is copied")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/sync/cond_test.go b/third_party/gofrontend/libgo/go/sync/cond_test.go
new file mode 100644
index 0000000..467c806
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/cond_test.go
@@ -0,0 +1,255 @@
+// 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.
+package sync_test
+
+import (
+	. "sync"
+
+	"runtime"
+	"testing"
+)
+
+func TestCondSignal(t *testing.T) {
+	var m Mutex
+	c := NewCond(&m)
+	n := 2
+	running := make(chan bool, n)
+	awake := make(chan bool, n)
+	for i := 0; i < n; i++ {
+		go func() {
+			m.Lock()
+			running <- true
+			c.Wait()
+			awake <- true
+			m.Unlock()
+		}()
+	}
+	for i := 0; i < n; i++ {
+		<-running // Wait for everyone to run.
+	}
+	for n > 0 {
+		select {
+		case <-awake:
+			t.Fatal("goroutine not asleep")
+		default:
+		}
+		m.Lock()
+		c.Signal()
+		m.Unlock()
+		<-awake // Will deadlock if no goroutine wakes up
+		select {
+		case <-awake:
+			t.Fatal("too many goroutines awake")
+		default:
+		}
+		n--
+	}
+	c.Signal()
+}
+
+func TestCondSignalGenerations(t *testing.T) {
+	var m Mutex
+	c := NewCond(&m)
+	n := 100
+	running := make(chan bool, n)
+	awake := make(chan int, n)
+	for i := 0; i < n; i++ {
+		go func(i int) {
+			m.Lock()
+			running <- true
+			c.Wait()
+			awake <- i
+			m.Unlock()
+		}(i)
+		if i > 0 {
+			a := <-awake
+			if a != i-1 {
+				t.Fatalf("wrong goroutine woke up: want %d, got %d", i-1, a)
+			}
+		}
+		<-running
+		m.Lock()
+		c.Signal()
+		m.Unlock()
+	}
+}
+
+func TestCondBroadcast(t *testing.T) {
+	var m Mutex
+	c := NewCond(&m)
+	n := 200
+	running := make(chan int, n)
+	awake := make(chan int, n)
+	exit := false
+	for i := 0; i < n; i++ {
+		go func(g int) {
+			m.Lock()
+			for !exit {
+				running <- g
+				c.Wait()
+				awake <- g
+			}
+			m.Unlock()
+		}(i)
+	}
+	for i := 0; i < n; i++ {
+		for i := 0; i < n; i++ {
+			<-running // Will deadlock unless n are running.
+		}
+		if i == n-1 {
+			m.Lock()
+			exit = true
+			m.Unlock()
+		}
+		select {
+		case <-awake:
+			t.Fatal("goroutine not asleep")
+		default:
+		}
+		m.Lock()
+		c.Broadcast()
+		m.Unlock()
+		seen := make([]bool, n)
+		for i := 0; i < n; i++ {
+			g := <-awake
+			if seen[g] {
+				t.Fatal("goroutine woke up twice")
+			}
+			seen[g] = true
+		}
+	}
+	select {
+	case <-running:
+		t.Fatal("goroutine did not exit")
+	default:
+	}
+	c.Broadcast()
+}
+
+func TestRace(t *testing.T) {
+	x := 0
+	c := NewCond(&Mutex{})
+	done := make(chan bool)
+	go func() {
+		c.L.Lock()
+		x = 1
+		c.Wait()
+		if x != 2 {
+			t.Fatal("want 2")
+		}
+		x = 3
+		c.Signal()
+		c.L.Unlock()
+		done <- true
+	}()
+	go func() {
+		c.L.Lock()
+		for {
+			if x == 1 {
+				x = 2
+				c.Signal()
+				break
+			}
+			c.L.Unlock()
+			runtime.Gosched()
+			c.L.Lock()
+		}
+		c.L.Unlock()
+		done <- true
+	}()
+	go func() {
+		c.L.Lock()
+		for {
+			if x == 2 {
+				c.Wait()
+				if x != 3 {
+					t.Fatal("want 3")
+				}
+				break
+			}
+			if x == 3 {
+				break
+			}
+			c.L.Unlock()
+			runtime.Gosched()
+			c.L.Lock()
+		}
+		c.L.Unlock()
+		done <- true
+	}()
+	<-done
+	<-done
+	<-done
+}
+
+func TestCondCopy(t *testing.T) {
+	defer func() {
+		err := recover()
+		if err == nil || err.(string) != "sync.Cond is copied" {
+			t.Fatalf("got %v, expect sync.Cond is copied", err)
+		}
+	}()
+	c := Cond{L: &Mutex{}}
+	c.Signal()
+	c2 := c
+	c2.Signal()
+}
+
+func BenchmarkCond1(b *testing.B) {
+	benchmarkCond(b, 1)
+}
+
+func BenchmarkCond2(b *testing.B) {
+	benchmarkCond(b, 2)
+}
+
+func BenchmarkCond4(b *testing.B) {
+	benchmarkCond(b, 4)
+}
+
+func BenchmarkCond8(b *testing.B) {
+	benchmarkCond(b, 8)
+}
+
+func BenchmarkCond16(b *testing.B) {
+	benchmarkCond(b, 16)
+}
+
+func BenchmarkCond32(b *testing.B) {
+	benchmarkCond(b, 32)
+}
+
+func benchmarkCond(b *testing.B, waiters int) {
+	c := NewCond(&Mutex{})
+	done := make(chan bool)
+	id := 0
+
+	for routine := 0; routine < waiters+1; routine++ {
+		go func() {
+			for i := 0; i < b.N; i++ {
+				c.L.Lock()
+				if id == -1 {
+					c.L.Unlock()
+					break
+				}
+				id++
+				if id == waiters+1 {
+					id = 0
+					c.Broadcast()
+				} else {
+					c.Wait()
+				}
+				c.L.Unlock()
+			}
+			c.L.Lock()
+			id = -1
+			c.Broadcast()
+			c.L.Unlock()
+			done <- true
+		}()
+	}
+	for routine := 0; routine < waiters+1; routine++ {
+		<-done
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/sync/example_test.go b/third_party/gofrontend/libgo/go/sync/example_test.go
new file mode 100644
index 0000000..bdd3af6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/example_test.go
@@ -0,0 +1,59 @@
+// 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 sync_test
+
+import (
+	"fmt"
+	"sync"
+)
+
+type httpPkg struct{}
+
+func (httpPkg) Get(url string) {}
+
+var http httpPkg
+
+// This example fetches several URLs concurrently,
+// using a WaitGroup to block until all the fetches are complete.
+func ExampleWaitGroup() {
+	var wg sync.WaitGroup
+	var urls = []string{
+		"http://www.golang.org/",
+		"http://www.google.com/",
+		"http://www.somestupidname.com/",
+	}
+	for _, url := range urls {
+		// Increment the WaitGroup counter.
+		wg.Add(1)
+		// Launch a goroutine to fetch the URL.
+		go func(url string) {
+			// Decrement the counter when the goroutine completes.
+			defer wg.Done()
+			// Fetch the URL.
+			http.Get(url)
+		}(url)
+	}
+	// Wait for all HTTP fetches to complete.
+	wg.Wait()
+}
+
+func ExampleOnce() {
+	var once sync.Once
+	onceBody := func() {
+		fmt.Println("Only once")
+	}
+	done := make(chan bool)
+	for i := 0; i < 10; i++ {
+		go func() {
+			once.Do(onceBody)
+			done <- true
+		}()
+	}
+	for i := 0; i < 10; i++ {
+		<-done
+	}
+	// Output:
+	// Only once
+}
diff --git a/third_party/gofrontend/libgo/go/sync/export_test.go b/third_party/gofrontend/libgo/go/sync/export_test.go
new file mode 100644
index 0000000..fa5983a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/export_test.go
@@ -0,0 +1,9 @@
+// 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 sync
+
+// Export for testing.
+var Runtime_Semacquire = runtime_Semacquire
+var Runtime_Semrelease = runtime_Semrelease
diff --git a/third_party/gofrontend/libgo/go/sync/mutex.go b/third_party/gofrontend/libgo/go/sync/mutex.go
new file mode 100644
index 0000000..73b3377
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/mutex.go
@@ -0,0 +1,109 @@
+// 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 sync provides basic synchronization primitives such as mutual
+// exclusion locks.  Other than the Once and WaitGroup types, most are intended
+// for use by low-level library routines.  Higher-level synchronization is
+// better done via channels and communication.
+//
+// Values containing the types defined in this package should not be copied.
+package sync
+
+import (
+	"sync/atomic"
+	"unsafe"
+)
+
+// A Mutex is a mutual exclusion lock.
+// Mutexes can be created as part of other structures;
+// the zero value for a Mutex is an unlocked mutex.
+type Mutex struct {
+	state int32
+	sema  uint32
+}
+
+// A Locker represents an object that can be locked and unlocked.
+type Locker interface {
+	Lock()
+	Unlock()
+}
+
+const (
+	mutexLocked = 1 << iota // mutex is locked
+	mutexWoken
+	mutexWaiterShift = iota
+)
+
+// Lock locks m.
+// If the lock is already in use, the calling goroutine
+// blocks until the mutex is available.
+func (m *Mutex) Lock() {
+	// Fast path: grab unlocked mutex.
+	if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {
+		if raceenabled {
+			raceAcquire(unsafe.Pointer(m))
+		}
+		return
+	}
+
+	awoke := false
+	for {
+		old := m.state
+		new := old | mutexLocked
+		if old&mutexLocked != 0 {
+			new = old + 1<<mutexWaiterShift
+		}
+		if awoke {
+			// The goroutine has been woken from sleep,
+			// so we need to reset the flag in either case.
+			new &^= mutexWoken
+		}
+		if atomic.CompareAndSwapInt32(&m.state, old, new) {
+			if old&mutexLocked == 0 {
+				break
+			}
+			runtime_Semacquire(&m.sema)
+			awoke = true
+		}
+	}
+
+	if raceenabled {
+		raceAcquire(unsafe.Pointer(m))
+	}
+}
+
+// Unlock unlocks m.
+// It is a run-time error if m is not locked on entry to Unlock.
+//
+// A locked Mutex is not associated with a particular goroutine.
+// It is allowed for one goroutine to lock a Mutex and then
+// arrange for another goroutine to unlock it.
+func (m *Mutex) Unlock() {
+	if raceenabled {
+		_ = m.state
+		raceRelease(unsafe.Pointer(m))
+	}
+
+	// Fast path: drop lock bit.
+	new := atomic.AddInt32(&m.state, -mutexLocked)
+	if (new+mutexLocked)&mutexLocked == 0 {
+		panic("sync: unlock of unlocked mutex")
+	}
+
+	old := new
+	for {
+		// If there are no waiters or a goroutine has already
+		// been woken or grabbed the lock, no need to wake anyone.
+		if old>>mutexWaiterShift == 0 || old&(mutexLocked|mutexWoken) != 0 {
+			return
+		}
+		// Grab the right to wake someone.
+		new = (old - 1<<mutexWaiterShift) | mutexWoken
+		if atomic.CompareAndSwapInt32(&m.state, old, new) {
+			runtime_Semrelease(&m.sema)
+			return
+		}
+		old = m.state
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/sync/mutex_test.go b/third_party/gofrontend/libgo/go/sync/mutex_test.go
new file mode 100644
index 0000000..151b25c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/mutex_test.go
@@ -0,0 +1,136 @@
+// 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.
+
+// GOMAXPROCS=10 go test
+
+package sync_test
+
+import (
+	"runtime"
+	. "sync"
+	"testing"
+)
+
+func HammerSemaphore(s *uint32, loops int, cdone chan bool) {
+	for i := 0; i < loops; i++ {
+		Runtime_Semacquire(s)
+		Runtime_Semrelease(s)
+	}
+	cdone <- true
+}
+
+func TestSemaphore(t *testing.T) {
+	s := new(uint32)
+	*s = 1
+	c := make(chan bool)
+	for i := 0; i < 10; i++ {
+		go HammerSemaphore(s, 1000, c)
+	}
+	for i := 0; i < 10; i++ {
+		<-c
+	}
+}
+
+func BenchmarkUncontendedSemaphore(b *testing.B) {
+	s := new(uint32)
+	*s = 1
+	HammerSemaphore(s, b.N, make(chan bool, 2))
+}
+
+func BenchmarkContendedSemaphore(b *testing.B) {
+	b.StopTimer()
+	s := new(uint32)
+	*s = 1
+	c := make(chan bool)
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+	b.StartTimer()
+
+	go HammerSemaphore(s, b.N/2, c)
+	go HammerSemaphore(s, b.N/2, c)
+	<-c
+	<-c
+}
+
+func HammerMutex(m *Mutex, loops int, cdone chan bool) {
+	for i := 0; i < loops; i++ {
+		m.Lock()
+		m.Unlock()
+	}
+	cdone <- true
+}
+
+func TestMutex(t *testing.T) {
+	m := new(Mutex)
+	c := make(chan bool)
+	for i := 0; i < 10; i++ {
+		go HammerMutex(m, 1000, c)
+	}
+	for i := 0; i < 10; i++ {
+		<-c
+	}
+}
+
+func TestMutexPanic(t *testing.T) {
+	defer func() {
+		if recover() == nil {
+			t.Fatalf("unlock of unlocked mutex did not panic")
+		}
+	}()
+
+	var mu Mutex
+	mu.Lock()
+	mu.Unlock()
+	mu.Unlock()
+}
+
+func BenchmarkMutexUncontended(b *testing.B) {
+	type PaddedMutex struct {
+		Mutex
+		pad [128]uint8
+	}
+	b.RunParallel(func(pb *testing.PB) {
+		var mu PaddedMutex
+		for pb.Next() {
+			mu.Lock()
+			mu.Unlock()
+		}
+	})
+}
+
+func benchmarkMutex(b *testing.B, slack, work bool) {
+	var mu Mutex
+	if slack {
+		b.SetParallelism(10)
+	}
+	b.RunParallel(func(pb *testing.PB) {
+		foo := 0
+		for pb.Next() {
+			mu.Lock()
+			mu.Unlock()
+			if work {
+				for i := 0; i < 100; i++ {
+					foo *= 2
+					foo /= 2
+				}
+			}
+		}
+		_ = foo
+	})
+}
+
+func BenchmarkMutex(b *testing.B) {
+	benchmarkMutex(b, false, false)
+}
+
+func BenchmarkMutexSlack(b *testing.B) {
+	benchmarkMutex(b, true, false)
+}
+
+func BenchmarkMutexWork(b *testing.B) {
+	benchmarkMutex(b, false, true)
+}
+
+func BenchmarkMutexWorkSlack(b *testing.B) {
+	benchmarkMutex(b, true, true)
+}
diff --git a/third_party/gofrontend/libgo/go/sync/once.go b/third_party/gofrontend/libgo/go/sync/once.go
new file mode 100644
index 0000000..161ae3b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/once.go
@@ -0,0 +1,43 @@
+// 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 sync
+
+import (
+	"sync/atomic"
+)
+
+// Once is an object that will perform exactly one action.
+type Once struct {
+	m    Mutex
+	done uint32
+}
+
+// Do calls the function f if and only if Do is being called for the
+// first time for this instance of Once.  In other words, given
+// 	var once Once
+// if once.Do(f) is called multiple times, only the first call will invoke f,
+// even if f has a different value in each invocation.  A new instance of
+// Once is required for each function to execute.
+//
+// Do is intended for initialization that must be run exactly once.  Since f
+// is niladic, it may be necessary to use a function literal to capture the
+// arguments to a function to be invoked by Do:
+// 	config.once.Do(func() { config.init(filename) })
+//
+// Because no call to Do returns until the one call to f returns, if f causes
+// Do to be called, it will deadlock.
+//
+func (o *Once) Do(f func()) {
+	if atomic.LoadUint32(&o.done) == 1 {
+		return
+	}
+	// Slow-path.
+	o.m.Lock()
+	defer o.m.Unlock()
+	if o.done == 0 {
+		f()
+		atomic.StoreUint32(&o.done, 1)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/sync/once_test.go b/third_party/gofrontend/libgo/go/sync/once_test.go
new file mode 100644
index 0000000..8afda82
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/once_test.go
@@ -0,0 +1,70 @@
+// 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 sync_test
+
+import (
+	. "sync"
+	"testing"
+)
+
+type one int
+
+func (o *one) Increment() {
+	*o++
+}
+
+func run(t *testing.T, once *Once, o *one, c chan bool) {
+	once.Do(func() { o.Increment() })
+	if v := *o; v != 1 {
+		t.Errorf("once failed inside run: %d is not 1", v)
+	}
+	c <- true
+}
+
+func TestOnce(t *testing.T) {
+	o := new(one)
+	once := new(Once)
+	c := make(chan bool)
+	const N = 10
+	for i := 0; i < N; i++ {
+		go run(t, once, o, c)
+	}
+	for i := 0; i < N; i++ {
+		<-c
+	}
+	if *o != 1 {
+		t.Errorf("once failed outside run: %d is not 1", *o)
+	}
+}
+
+func TestOncePanic(t *testing.T) {
+	once := new(Once)
+	for i := 0; i < 2; i++ {
+		func() {
+			defer func() {
+				if recover() == nil {
+					t.Fatalf("Once.Do() has not panic'ed")
+				}
+			}()
+			once.Do(func() {
+				panic("failed")
+			})
+		}()
+	}
+	once.Do(func() {})
+	once.Do(func() {
+		t.Fatalf("Once called twice")
+	})
+}
+
+func BenchmarkOnce(b *testing.B) {
+	var once Once
+	f := func() {}
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			once.Do(f)
+		}
+	})
+}
diff --git a/third_party/gofrontend/libgo/go/sync/pool.go b/third_party/gofrontend/libgo/go/sync/pool.go
new file mode 100644
index 0000000..1f08707
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/pool.go
@@ -0,0 +1,223 @@
+// Copyright 2013 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 sync
+
+import (
+	"runtime"
+	"sync/atomic"
+	"unsafe"
+)
+
+// A Pool is a set of temporary objects that may be individually saved and
+// retrieved.
+//
+// Any item stored in the Pool may be removed automatically at any time without
+// notification. If the Pool holds the only reference when this happens, the
+// item might be deallocated.
+//
+// A Pool is safe for use by multiple goroutines simultaneously.
+//
+// Pool's purpose is to cache allocated but unused items for later reuse,
+// relieving pressure on the garbage collector. That is, it makes it easy to
+// build efficient, thread-safe free lists. However, it is not suitable for all
+// free lists.
+//
+// An appropriate use of a Pool is to manage a group of temporary items
+// silently shared among and potentially reused by concurrent independent
+// clients of a package. Pool provides a way to amortize allocation overhead
+// across many clients.
+//
+// An example of good use of a Pool is in the fmt package, which maintains a
+// dynamically-sized store of temporary output buffers. The store scales under
+// load (when many goroutines are actively printing) and shrinks when
+// quiescent.
+//
+// On the other hand, a free list maintained as part of a short-lived object is
+// not a suitable use for a Pool, since the overhead does not amortize well in
+// that scenario. It is more efficient to have such objects implement their own
+// free list.
+//
+type Pool struct {
+	local     unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal
+	localSize uintptr        // size of the local array
+
+	// New optionally specifies a function to generate
+	// a value when Get would otherwise return nil.
+	// It may not be changed concurrently with calls to Get.
+	New func() interface{}
+}
+
+// Local per-P Pool appendix.
+type poolLocal struct {
+	private interface{}   // Can be used only by the respective P.
+	shared  []interface{} // Can be used by any P.
+	Mutex                 // Protects shared.
+	pad     [128]byte     // Prevents false sharing.
+}
+
+// Put adds x to the pool.
+func (p *Pool) Put(x interface{}) {
+	if raceenabled {
+		// Under race detector the Pool degenerates into no-op.
+		// It's conforming, simple and does not introduce excessive
+		// happens-before edges between unrelated goroutines.
+		return
+	}
+	if x == nil {
+		return
+	}
+	l := p.pin()
+	if l.private == nil {
+		l.private = x
+		x = nil
+	}
+	runtime_procUnpin()
+	if x == nil {
+		return
+	}
+	l.Lock()
+	l.shared = append(l.shared, x)
+	l.Unlock()
+}
+
+// Get selects an arbitrary item from the Pool, removes it from the
+// Pool, and returns it to the caller.
+// Get may choose to ignore the pool and treat it as empty.
+// Callers should not assume any relation between values passed to Put and
+// the values returned by Get.
+//
+// If Get would otherwise return nil and p.New is non-nil, Get returns
+// the result of calling p.New.
+func (p *Pool) Get() interface{} {
+	if raceenabled {
+		if p.New != nil {
+			return p.New()
+		}
+		return nil
+	}
+	l := p.pin()
+	x := l.private
+	l.private = nil
+	runtime_procUnpin()
+	if x != nil {
+		return x
+	}
+	l.Lock()
+	last := len(l.shared) - 1
+	if last >= 0 {
+		x = l.shared[last]
+		l.shared = l.shared[:last]
+	}
+	l.Unlock()
+	if x != nil {
+		return x
+	}
+	return p.getSlow()
+}
+
+func (p *Pool) getSlow() (x interface{}) {
+	// See the comment in pin regarding ordering of the loads.
+	size := atomic.LoadUintptr(&p.localSize) // load-acquire
+	local := p.local                         // load-consume
+	// Try to steal one element from other procs.
+	pid := runtime_procPin()
+	runtime_procUnpin()
+	for i := 0; i < int(size); i++ {
+		l := indexLocal(local, (pid+i+1)%int(size))
+		l.Lock()
+		last := len(l.shared) - 1
+		if last >= 0 {
+			x = l.shared[last]
+			l.shared = l.shared[:last]
+			l.Unlock()
+			break
+		}
+		l.Unlock()
+	}
+
+	if x == nil && p.New != nil {
+		x = p.New()
+	}
+	return x
+}
+
+// pin pins the current goroutine to P, disables preemption and returns poolLocal pool for the P.
+// Caller must call runtime_procUnpin() when done with the pool.
+func (p *Pool) pin() *poolLocal {
+	pid := runtime_procPin()
+	// In pinSlow we store to localSize and then to local, here we load in opposite order.
+	// Since we've disabled preemption, GC can not happen in between.
+	// Thus here we must observe local at least as large localSize.
+	// We can observe a newer/larger local, it is fine (we must observe its zero-initialized-ness).
+	s := atomic.LoadUintptr(&p.localSize) // load-acquire
+	l := p.local                          // load-consume
+	if uintptr(pid) < s {
+		return indexLocal(l, pid)
+	}
+	return p.pinSlow()
+}
+
+func (p *Pool) pinSlow() *poolLocal {
+	// Retry under the mutex.
+	// Can not lock the mutex while pinned.
+	runtime_procUnpin()
+	allPoolsMu.Lock()
+	defer allPoolsMu.Unlock()
+	pid := runtime_procPin()
+	// poolCleanup won't be called while we are pinned.
+	s := p.localSize
+	l := p.local
+	if uintptr(pid) < s {
+		return indexLocal(l, pid)
+	}
+	if p.local == nil {
+		allPools = append(allPools, p)
+	}
+	// If GOMAXPROCS changes between GCs, we re-allocate the array and lose the old one.
+	size := runtime.GOMAXPROCS(0)
+	local := make([]poolLocal, size)
+	atomic.StorePointer((*unsafe.Pointer)(&p.local), unsafe.Pointer(&local[0])) // store-release
+	atomic.StoreUintptr(&p.localSize, uintptr(size))                            // store-release
+	return &local[pid]
+}
+
+func poolCleanup() {
+	// This function is called with the world stopped, at the beginning of a garbage collection.
+	// It must not allocate and probably should not call any runtime functions.
+	// Defensively zero out everything, 2 reasons:
+	// 1. To prevent false retention of whole Pools.
+	// 2. If GC happens while a goroutine works with l.shared in Put/Get,
+	//    it will retain whole Pool. So next cycle memory consumption would be doubled.
+	for i, p := range allPools {
+		allPools[i] = nil
+		for i := 0; i < int(p.localSize); i++ {
+			l := indexLocal(p.local, i)
+			l.private = nil
+			for j := range l.shared {
+				l.shared[j] = nil
+			}
+			l.shared = nil
+		}
+	}
+	allPools = []*Pool{}
+}
+
+var (
+	allPoolsMu Mutex
+	allPools   []*Pool
+)
+
+func init() {
+	runtime_registerPoolCleanup(poolCleanup)
+}
+
+func indexLocal(l unsafe.Pointer, i int) *poolLocal {
+	return &(*[1000000]poolLocal)(l)[i]
+}
+
+// Implemented in runtime.
+func runtime_registerPoolCleanup(cleanup func())
+func runtime_procPin() int
+func runtime_procUnpin()
diff --git a/third_party/gofrontend/libgo/go/sync/pool_test.go b/third_party/gofrontend/libgo/go/sync/pool_test.go
new file mode 100644
index 0000000..c13477d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/pool_test.go
@@ -0,0 +1,156 @@
+// Copyright 2013 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.
+
+// Pool is no-op under race detector, so all these tests do not work.
+// +build !race
+
+package sync_test
+
+import (
+	"runtime"
+	"runtime/debug"
+	. "sync"
+	"sync/atomic"
+	"testing"
+	"time"
+)
+
+func TestPool(t *testing.T) {
+	// disable GC so we can control when it happens.
+	defer debug.SetGCPercent(debug.SetGCPercent(-1))
+	var p Pool
+	if p.Get() != nil {
+		t.Fatal("expected empty")
+	}
+	p.Put("a")
+	p.Put("b")
+	if g := p.Get(); g != "a" {
+		t.Fatalf("got %#v; want a", g)
+	}
+	if g := p.Get(); g != "b" {
+		t.Fatalf("got %#v; want b", g)
+	}
+	if g := p.Get(); g != nil {
+		t.Fatalf("got %#v; want nil", g)
+	}
+
+	p.Put("c")
+	debug.SetGCPercent(100) // to allow following GC to actually run
+	runtime.GC()
+	if g := p.Get(); g != nil {
+		t.Fatalf("got %#v; want nil after GC", g)
+	}
+}
+
+func TestPoolNew(t *testing.T) {
+	// disable GC so we can control when it happens.
+	defer debug.SetGCPercent(debug.SetGCPercent(-1))
+
+	i := 0
+	p := Pool{
+		New: func() interface{} {
+			i++
+			return i
+		},
+	}
+	if v := p.Get(); v != 1 {
+		t.Fatalf("got %v; want 1", v)
+	}
+	if v := p.Get(); v != 2 {
+		t.Fatalf("got %v; want 2", v)
+	}
+	p.Put(42)
+	if v := p.Get(); v != 42 {
+		t.Fatalf("got %v; want 42", v)
+	}
+	if v := p.Get(); v != 3 {
+		t.Fatalf("got %v; want 3", v)
+	}
+}
+
+// Test that Pool does not hold pointers to previously cached
+// resources
+func TestPoolGC(t *testing.T) {
+	var p Pool
+	var fin uint32
+	const N = 100
+	for i := 0; i < N; i++ {
+		v := new(string)
+		runtime.SetFinalizer(v, func(vv *string) {
+			atomic.AddUint32(&fin, 1)
+		})
+		p.Put(v)
+	}
+	for i := 0; i < N; i++ {
+		p.Get()
+	}
+	for i := 0; i < 5; i++ {
+		runtime.GC()
+		time.Sleep(time.Duration(i*100+10) * time.Millisecond)
+		// 1 pointer can remain on stack or elsewhere
+		if atomic.LoadUint32(&fin) >= N-1 {
+			return
+		}
+
+		// gccgo has a less precise heap.
+		if runtime.Compiler == "gccgo" && atomic.LoadUint32(&fin) >= N-5 {
+			return
+		}
+	}
+	t.Fatalf("only %v out of %v resources are finalized",
+		atomic.LoadUint32(&fin), N)
+}
+
+func TestPoolStress(t *testing.T) {
+	const P = 10
+	N := int(1e6)
+	if testing.Short() {
+		N /= 100
+	}
+	var p Pool
+	done := make(chan bool)
+	for i := 0; i < P; i++ {
+		go func() {
+			var v interface{} = 0
+			for j := 0; j < N; j++ {
+				if v == nil {
+					v = 0
+				}
+				p.Put(v)
+				v = p.Get()
+				if v != nil && v.(int) != 0 {
+					t.Fatalf("expect 0, got %v", v)
+				}
+			}
+			done <- true
+		}()
+	}
+	for i := 0; i < P; i++ {
+		<-done
+	}
+}
+
+func BenchmarkPool(b *testing.B) {
+	var p Pool
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			p.Put(1)
+			p.Get()
+		}
+	})
+}
+
+func BenchmarkPoolOverlflow(b *testing.B) {
+	var p Pool
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			for b := 0; b < 100; b++ {
+				p.Put(1)
+			}
+			for b := 0; b < 100; b++ {
+				p.Get()
+			}
+		}
+	})
+}
diff --git a/third_party/gofrontend/libgo/go/sync/race.go b/third_party/gofrontend/libgo/go/sync/race.go
new file mode 100644
index 0000000..fd0277d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/race.go
@@ -0,0 +1,42 @@
+// 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.
+
+// +build race
+
+package sync
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+const raceenabled = true
+
+func raceAcquire(addr unsafe.Pointer) {
+	runtime.RaceAcquire(addr)
+}
+
+func raceRelease(addr unsafe.Pointer) {
+	runtime.RaceRelease(addr)
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+	runtime.RaceReleaseMerge(addr)
+}
+
+func raceDisable() {
+	runtime.RaceDisable()
+}
+
+func raceEnable() {
+	runtime.RaceEnable()
+}
+
+func raceRead(addr unsafe.Pointer) {
+	runtime.RaceRead(addr)
+}
+
+func raceWrite(addr unsafe.Pointer) {
+	runtime.RaceWrite(addr)
+}
diff --git a/third_party/gofrontend/libgo/go/sync/race0.go b/third_party/gofrontend/libgo/go/sync/race0.go
new file mode 100644
index 0000000..65ada1c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/race0.go
@@ -0,0 +1,34 @@
+// 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.
+
+// +build !race
+
+package sync
+
+import (
+	"unsafe"
+)
+
+const raceenabled = false
+
+func raceAcquire(addr unsafe.Pointer) {
+}
+
+func raceRelease(addr unsafe.Pointer) {
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+}
+
+func raceDisable() {
+}
+
+func raceEnable() {
+}
+
+func raceRead(addr unsafe.Pointer) {
+}
+
+func raceWrite(addr unsafe.Pointer) {
+}
diff --git a/third_party/gofrontend/libgo/go/sync/runtime.go b/third_party/gofrontend/libgo/go/sync/runtime.go
new file mode 100644
index 0000000..3bf47ea
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/runtime.go
@@ -0,0 +1,36 @@
+// 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 sync
+
+import "unsafe"
+
+// defined in package runtime
+
+// Semacquire waits until *s > 0 and then atomically decrements it.
+// It is intended as a simple sleep primitive for use by the synchronization
+// library and should not be used directly.
+func runtime_Semacquire(s *uint32)
+
+// Semrelease atomically increments *s and notifies a waiting goroutine
+// if one is blocked in Semacquire.
+// It is intended as a simple wakeup primitive for use by the synchronization
+// library and should not be used directly.
+func runtime_Semrelease(s *uint32)
+
+// Opaque representation of SyncSema in runtime/sema.goc.
+type syncSema [3]uintptr
+
+// Syncsemacquire waits for a pairing Syncsemrelease on the same semaphore s.
+func runtime_Syncsemacquire(s *syncSema)
+
+// Syncsemrelease waits for n pairing Syncsemacquire on the same semaphore s.
+func runtime_Syncsemrelease(s *syncSema, n uint32)
+
+// Ensure that sync and runtime agree on size of syncSema.
+func runtime_Syncsemcheck(size uintptr)
+func init() {
+	var s syncSema
+	runtime_Syncsemcheck(unsafe.Sizeof(s))
+}
diff --git a/third_party/gofrontend/libgo/go/sync/runtime_sema_test.go b/third_party/gofrontend/libgo/go/sync/runtime_sema_test.go
new file mode 100644
index 0000000..5b7dd3d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/runtime_sema_test.go
@@ -0,0 +1,72 @@
+// 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 sync_test
+
+import (
+	"runtime"
+	. "sync"
+	"testing"
+)
+
+func BenchmarkSemaUncontended(b *testing.B) {
+	type PaddedSem struct {
+		sem uint32
+		pad [32]uint32
+	}
+	b.RunParallel(func(pb *testing.PB) {
+		sem := new(PaddedSem)
+		for pb.Next() {
+			Runtime_Semrelease(&sem.sem)
+			Runtime_Semacquire(&sem.sem)
+		}
+	})
+}
+
+func benchmarkSema(b *testing.B, block, work bool) {
+	sem := uint32(0)
+	if block {
+		done := make(chan bool)
+		go func() {
+			for p := 0; p < runtime.GOMAXPROCS(0)/2; p++ {
+				Runtime_Semacquire(&sem)
+			}
+			done <- true
+		}()
+		defer func() {
+			<-done
+		}()
+	}
+	b.RunParallel(func(pb *testing.PB) {
+		foo := 0
+		for pb.Next() {
+			Runtime_Semrelease(&sem)
+			if work {
+				for i := 0; i < 100; i++ {
+					foo *= 2
+					foo /= 2
+				}
+			}
+			Runtime_Semacquire(&sem)
+		}
+		_ = foo
+		Runtime_Semrelease(&sem)
+	})
+}
+
+func BenchmarkSemaSyntNonblock(b *testing.B) {
+	benchmarkSema(b, false, false)
+}
+
+func BenchmarkSemaSyntBlock(b *testing.B) {
+	benchmarkSema(b, true, false)
+}
+
+func BenchmarkSemaWorkNonblock(b *testing.B) {
+	benchmarkSema(b, false, true)
+}
+
+func BenchmarkSemaWorkBlock(b *testing.B) {
+	benchmarkSema(b, true, true)
+}
diff --git a/third_party/gofrontend/libgo/go/sync/rwmutex.go b/third_party/gofrontend/libgo/go/sync/rwmutex.go
new file mode 100644
index 0000000..3db5419
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/rwmutex.go
@@ -0,0 +1,128 @@
+// 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 sync
+
+import (
+	"sync/atomic"
+	"unsafe"
+)
+
+// An RWMutex is a reader/writer mutual exclusion lock.
+// The lock can be held by an arbitrary number of readers
+// or a single writer.
+// RWMutexes can be created as part of other
+// structures; the zero value for a RWMutex is
+// an unlocked mutex.
+type RWMutex struct {
+	w           Mutex  // held if there are pending writers
+	writerSem   uint32 // semaphore for writers to wait for completing readers
+	readerSem   uint32 // semaphore for readers to wait for completing writers
+	readerCount int32  // number of pending readers
+	readerWait  int32  // number of departing readers
+}
+
+const rwmutexMaxReaders = 1 << 30
+
+// RLock locks rw for reading.
+func (rw *RWMutex) RLock() {
+	if raceenabled {
+		_ = rw.w.state
+		raceDisable()
+	}
+	if atomic.AddInt32(&rw.readerCount, 1) < 0 {
+		// A writer is pending, wait for it.
+		runtime_Semacquire(&rw.readerSem)
+	}
+	if raceenabled {
+		raceEnable()
+		raceAcquire(unsafe.Pointer(&rw.readerSem))
+	}
+}
+
+// RUnlock undoes a single RLock call;
+// it does not affect other simultaneous readers.
+// It is a run-time error if rw is not locked for reading
+// on entry to RUnlock.
+func (rw *RWMutex) RUnlock() {
+	if raceenabled {
+		_ = rw.w.state
+		raceReleaseMerge(unsafe.Pointer(&rw.writerSem))
+		raceDisable()
+	}
+	if atomic.AddInt32(&rw.readerCount, -1) < 0 {
+		// A writer is pending.
+		if atomic.AddInt32(&rw.readerWait, -1) == 0 {
+			// The last reader unblocks the writer.
+			runtime_Semrelease(&rw.writerSem)
+		}
+	}
+	if raceenabled {
+		raceEnable()
+	}
+}
+
+// Lock locks rw for writing.
+// If the lock is already locked for reading or writing,
+// Lock blocks until the lock is available.
+// To ensure that the lock eventually becomes available,
+// a blocked Lock call excludes new readers from acquiring
+// the lock.
+func (rw *RWMutex) Lock() {
+	if raceenabled {
+		_ = rw.w.state
+		raceDisable()
+	}
+	// First, resolve competition with other writers.
+	rw.w.Lock()
+	// Announce to readers there is a pending writer.
+	r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
+	// Wait for active readers.
+	if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
+		runtime_Semacquire(&rw.writerSem)
+	}
+	if raceenabled {
+		raceEnable()
+		raceAcquire(unsafe.Pointer(&rw.readerSem))
+		raceAcquire(unsafe.Pointer(&rw.writerSem))
+	}
+}
+
+// Unlock unlocks rw for writing.  It is a run-time error if rw is
+// not locked for writing on entry to Unlock.
+//
+// As with Mutexes, a locked RWMutex is not associated with a particular
+// goroutine.  One goroutine may RLock (Lock) an RWMutex and then
+// arrange for another goroutine to RUnlock (Unlock) it.
+func (rw *RWMutex) Unlock() {
+	if raceenabled {
+		_ = rw.w.state
+		raceRelease(unsafe.Pointer(&rw.readerSem))
+		raceRelease(unsafe.Pointer(&rw.writerSem))
+		raceDisable()
+	}
+
+	// Announce to readers there is no active writer.
+	r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
+	// Unblock blocked readers, if any.
+	for i := 0; i < int(r); i++ {
+		runtime_Semrelease(&rw.readerSem)
+	}
+	// Allow other writers to proceed.
+	rw.w.Unlock()
+	if raceenabled {
+		raceEnable()
+	}
+}
+
+// RLocker returns a Locker interface that implements
+// the Lock and Unlock methods by calling rw.RLock and rw.RUnlock.
+func (rw *RWMutex) RLocker() Locker {
+	return (*rlocker)(rw)
+}
+
+type rlocker RWMutex
+
+func (r *rlocker) Lock()   { (*RWMutex)(r).RLock() }
+func (r *rlocker) Unlock() { (*RWMutex)(r).RUnlock() }
diff --git a/third_party/gofrontend/libgo/go/sync/rwmutex_test.go b/third_party/gofrontend/libgo/go/sync/rwmutex_test.go
new file mode 100644
index 0000000..0436f97
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/rwmutex_test.go
@@ -0,0 +1,212 @@
+// 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.
+
+// GOMAXPROCS=10 go test
+
+package sync_test
+
+import (
+	"fmt"
+	"runtime"
+	. "sync"
+	"sync/atomic"
+	"testing"
+)
+
+func parallelReader(m *RWMutex, clocked, cunlock, cdone chan bool) {
+	m.RLock()
+	clocked <- true
+	<-cunlock
+	m.RUnlock()
+	cdone <- true
+}
+
+func doTestParallelReaders(numReaders, gomaxprocs int) {
+	runtime.GOMAXPROCS(gomaxprocs)
+	var m RWMutex
+	clocked := make(chan bool)
+	cunlock := make(chan bool)
+	cdone := make(chan bool)
+	for i := 0; i < numReaders; i++ {
+		go parallelReader(&m, clocked, cunlock, cdone)
+	}
+	// Wait for all parallel RLock()s to succeed.
+	for i := 0; i < numReaders; i++ {
+		<-clocked
+	}
+	for i := 0; i < numReaders; i++ {
+		cunlock <- true
+	}
+	// Wait for the goroutines to finish.
+	for i := 0; i < numReaders; i++ {
+		<-cdone
+	}
+}
+
+func TestParallelReaders(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1))
+	doTestParallelReaders(1, 4)
+	doTestParallelReaders(3, 4)
+	doTestParallelReaders(4, 2)
+}
+
+func reader(rwm *RWMutex, num_iterations int, activity *int32, cdone chan bool) {
+	for i := 0; i < num_iterations; i++ {
+		rwm.RLock()
+		n := atomic.AddInt32(activity, 1)
+		if n < 1 || n >= 10000 {
+			panic(fmt.Sprintf("wlock(%d)\n", n))
+		}
+		for i := 0; i < 100; i++ {
+		}
+		atomic.AddInt32(activity, -1)
+		rwm.RUnlock()
+	}
+	cdone <- true
+}
+
+func writer(rwm *RWMutex, num_iterations int, activity *int32, cdone chan bool) {
+	for i := 0; i < num_iterations; i++ {
+		rwm.Lock()
+		n := atomic.AddInt32(activity, 10000)
+		if n != 10000 {
+			panic(fmt.Sprintf("wlock(%d)\n", n))
+		}
+		for i := 0; i < 100; i++ {
+		}
+		atomic.AddInt32(activity, -10000)
+		rwm.Unlock()
+	}
+	cdone <- true
+}
+
+func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) {
+	runtime.GOMAXPROCS(gomaxprocs)
+	// Number of active readers + 10000 * number of active writers.
+	var activity int32
+	var rwm RWMutex
+	cdone := make(chan bool)
+	go writer(&rwm, num_iterations, &activity, cdone)
+	var i int
+	for i = 0; i < numReaders/2; i++ {
+		go reader(&rwm, num_iterations, &activity, cdone)
+	}
+	go writer(&rwm, num_iterations, &activity, cdone)
+	for ; i < numReaders; i++ {
+		go reader(&rwm, num_iterations, &activity, cdone)
+	}
+	// Wait for the 2 writers and all readers to finish.
+	for i := 0; i < 2+numReaders; i++ {
+		<-cdone
+	}
+}
+
+func TestRWMutex(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1))
+	n := 1000
+	if testing.Short() {
+		n = 5
+	}
+	HammerRWMutex(1, 1, n)
+	HammerRWMutex(1, 3, n)
+	HammerRWMutex(1, 10, n)
+	HammerRWMutex(4, 1, n)
+	HammerRWMutex(4, 3, n)
+	HammerRWMutex(4, 10, n)
+	HammerRWMutex(10, 1, n)
+	HammerRWMutex(10, 3, n)
+	HammerRWMutex(10, 10, n)
+	HammerRWMutex(10, 5, n)
+}
+
+func TestRLocker(t *testing.T) {
+	var wl RWMutex
+	var rl Locker
+	wlocked := make(chan bool, 1)
+	rlocked := make(chan bool, 1)
+	rl = wl.RLocker()
+	n := 10
+	go func() {
+		for i := 0; i < n; i++ {
+			rl.Lock()
+			rl.Lock()
+			rlocked <- true
+			wl.Lock()
+			wlocked <- true
+		}
+	}()
+	for i := 0; i < n; i++ {
+		<-rlocked
+		rl.Unlock()
+		select {
+		case <-wlocked:
+			t.Fatal("RLocker() didn't read-lock it")
+		default:
+		}
+		rl.Unlock()
+		<-wlocked
+		select {
+		case <-rlocked:
+			t.Fatal("RLocker() didn't respect the write lock")
+		default:
+		}
+		wl.Unlock()
+	}
+}
+
+func BenchmarkRWMutexUncontended(b *testing.B) {
+	type PaddedRWMutex struct {
+		RWMutex
+		pad [32]uint32
+	}
+	b.RunParallel(func(pb *testing.PB) {
+		var rwm PaddedRWMutex
+		for pb.Next() {
+			rwm.RLock()
+			rwm.RLock()
+			rwm.RUnlock()
+			rwm.RUnlock()
+			rwm.Lock()
+			rwm.Unlock()
+		}
+	})
+}
+
+func benchmarkRWMutex(b *testing.B, localWork, writeRatio int) {
+	var rwm RWMutex
+	b.RunParallel(func(pb *testing.PB) {
+		foo := 0
+		for pb.Next() {
+			foo++
+			if foo%writeRatio == 0 {
+				rwm.Lock()
+				rwm.Unlock()
+			} else {
+				rwm.RLock()
+				for i := 0; i != localWork; i += 1 {
+					foo *= 2
+					foo /= 2
+				}
+				rwm.RUnlock()
+			}
+		}
+		_ = foo
+	})
+}
+
+func BenchmarkRWMutexWrite100(b *testing.B) {
+	benchmarkRWMutex(b, 0, 100)
+}
+
+func BenchmarkRWMutexWrite10(b *testing.B) {
+	benchmarkRWMutex(b, 0, 10)
+}
+
+func BenchmarkRWMutexWorkWrite100(b *testing.B) {
+	benchmarkRWMutex(b, 100, 100)
+}
+
+func BenchmarkRWMutexWorkWrite10(b *testing.B) {
+	benchmarkRWMutex(b, 100, 10)
+}
diff --git a/third_party/gofrontend/libgo/go/sync/waitgroup.go b/third_party/gofrontend/libgo/go/sync/waitgroup.go
new file mode 100644
index 0000000..4c64dca
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/waitgroup.go
@@ -0,0 +1,134 @@
+// 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.
+
+package sync
+
+import (
+	"sync/atomic"
+	"unsafe"
+)
+
+// A WaitGroup waits for a collection of goroutines to finish.
+// The main goroutine calls Add to set the number of
+// goroutines to wait for.  Then each of the goroutines
+// runs and calls Done when finished.  At the same time,
+// Wait can be used to block until all goroutines have finished.
+type WaitGroup struct {
+	m       Mutex
+	counter int32
+	waiters int32
+	sema    *uint32
+}
+
+// WaitGroup creates a new semaphore each time the old semaphore
+// is released. This is to avoid the following race:
+//
+// G1: Add(1)
+// G1: go G2()
+// G1: Wait() // Context switch after Unlock() and before Semacquire().
+// G2: Done() // Release semaphore: sema == 1, waiters == 0. G1 doesn't run yet.
+// G3: Wait() // Finds counter == 0, waiters == 0, doesn't block.
+// G3: Add(1) // Makes counter == 1, waiters == 0.
+// G3: go G4()
+// G3: Wait() // G1 still hasn't run, G3 finds sema == 1, unblocked! Bug.
+
+// Add adds delta, which may be negative, to the WaitGroup counter.
+// If the counter becomes zero, all goroutines blocked on Wait are released.
+// If the counter goes negative, Add panics.
+//
+// Note that calls with positive delta must happen before the call to Wait,
+// or else Wait may wait for too small a group. Typically this means the calls
+// to Add should execute before the statement creating the goroutine or
+// other event to be waited for. See the WaitGroup example.
+func (wg *WaitGroup) Add(delta int) {
+	if raceenabled {
+		_ = wg.m.state // trigger nil deref early
+		if delta < 0 {
+			// Synchronize decrements with Wait.
+			raceReleaseMerge(unsafe.Pointer(wg))
+		}
+		raceDisable()
+		defer raceEnable()
+	}
+	v := atomic.AddInt32(&wg.counter, int32(delta))
+	if raceenabled {
+		if delta > 0 && v == int32(delta) {
+			// The first increment must be synchronized with Wait.
+			// Need to model this as a read, because there can be
+			// several concurrent wg.counter transitions from 0.
+			raceRead(unsafe.Pointer(&wg.sema))
+		}
+	}
+	if v < 0 {
+		panic("sync: negative WaitGroup counter")
+	}
+	if v > 0 || atomic.LoadInt32(&wg.waiters) == 0 {
+		return
+	}
+	wg.m.Lock()
+	if atomic.LoadInt32(&wg.counter) == 0 {
+		for i := int32(0); i < wg.waiters; i++ {
+			runtime_Semrelease(wg.sema)
+		}
+		wg.waiters = 0
+		wg.sema = nil
+	}
+	wg.m.Unlock()
+}
+
+// Done decrements the WaitGroup counter.
+func (wg *WaitGroup) Done() {
+	wg.Add(-1)
+}
+
+// Wait blocks until the WaitGroup counter is zero.
+func (wg *WaitGroup) Wait() {
+	if raceenabled {
+		_ = wg.m.state // trigger nil deref early
+		raceDisable()
+	}
+	if atomic.LoadInt32(&wg.counter) == 0 {
+		if raceenabled {
+			raceEnable()
+			raceAcquire(unsafe.Pointer(wg))
+		}
+		return
+	}
+	wg.m.Lock()
+	w := atomic.AddInt32(&wg.waiters, 1)
+	// This code is racing with the unlocked path in Add above.
+	// The code above modifies counter and then reads waiters.
+	// We must modify waiters and then read counter (the opposite order)
+	// to avoid missing an Add.
+	if atomic.LoadInt32(&wg.counter) == 0 {
+		atomic.AddInt32(&wg.waiters, -1)
+		if raceenabled {
+			raceEnable()
+			raceAcquire(unsafe.Pointer(wg))
+			raceDisable()
+		}
+		wg.m.Unlock()
+		if raceenabled {
+			raceEnable()
+		}
+		return
+	}
+	if raceenabled && w == 1 {
+		// Wait must be synchronized with the first Add.
+		// Need to model this is as a write to race with the read in Add.
+		// As a consequence, can do the write only for the first waiter,
+		// otherwise concurrent Waits will race with each other.
+		raceWrite(unsafe.Pointer(&wg.sema))
+	}
+	if wg.sema == nil {
+		wg.sema = new(uint32)
+	}
+	s := wg.sema
+	wg.m.Unlock()
+	runtime_Semacquire(s)
+	if raceenabled {
+		raceEnable()
+		raceAcquire(unsafe.Pointer(wg))
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/sync/waitgroup_test.go b/third_party/gofrontend/libgo/go/sync/waitgroup_test.go
new file mode 100644
index 0000000..4c0a043
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/sync/waitgroup_test.go
@@ -0,0 +1,148 @@
+// 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.
+
+package sync_test
+
+import (
+	. "sync"
+	"sync/atomic"
+	"testing"
+)
+
+func testWaitGroup(t *testing.T, wg1 *WaitGroup, wg2 *WaitGroup) {
+	n := 16
+	wg1.Add(n)
+	wg2.Add(n)
+	exited := make(chan bool, n)
+	for i := 0; i != n; i++ {
+		go func(i int) {
+			wg1.Done()
+			wg2.Wait()
+			exited <- true
+		}(i)
+	}
+	wg1.Wait()
+	for i := 0; i != n; i++ {
+		select {
+		case <-exited:
+			t.Fatal("WaitGroup released group too soon")
+		default:
+		}
+		wg2.Done()
+	}
+	for i := 0; i != n; i++ {
+		<-exited // Will block if barrier fails to unlock someone.
+	}
+}
+
+func TestWaitGroup(t *testing.T) {
+	wg1 := &WaitGroup{}
+	wg2 := &WaitGroup{}
+
+	// Run the same test a few times to ensure barrier is in a proper state.
+	for i := 0; i != 8; i++ {
+		testWaitGroup(t, wg1, wg2)
+	}
+}
+
+func TestWaitGroupMisuse(t *testing.T) {
+	defer func() {
+		err := recover()
+		if err != "sync: negative WaitGroup counter" {
+			t.Fatalf("Unexpected panic: %#v", err)
+		}
+	}()
+	wg := &WaitGroup{}
+	wg.Add(1)
+	wg.Done()
+	wg.Done()
+	t.Fatal("Should panic")
+}
+
+func TestWaitGroupRace(t *testing.T) {
+	// Run this test for about 1ms.
+	for i := 0; i < 1000; i++ {
+		wg := &WaitGroup{}
+		n := new(int32)
+		// spawn goroutine 1
+		wg.Add(1)
+		go func() {
+			atomic.AddInt32(n, 1)
+			wg.Done()
+		}()
+		// spawn goroutine 2
+		wg.Add(1)
+		go func() {
+			atomic.AddInt32(n, 1)
+			wg.Done()
+		}()
+		// Wait for goroutine 1 and 2
+		wg.Wait()
+		if atomic.LoadInt32(n) != 2 {
+			t.Fatal("Spurious wakeup from Wait")
+		}
+	}
+}
+
+func BenchmarkWaitGroupUncontended(b *testing.B) {
+	type PaddedWaitGroup struct {
+		WaitGroup
+		pad [128]uint8
+	}
+	b.RunParallel(func(pb *testing.PB) {
+		var wg PaddedWaitGroup
+		for pb.Next() {
+			wg.Add(1)
+			wg.Done()
+			wg.Wait()
+		}
+	})
+}
+
+func benchmarkWaitGroupAddDone(b *testing.B, localWork int) {
+	var wg WaitGroup
+	b.RunParallel(func(pb *testing.PB) {
+		foo := 0
+		for pb.Next() {
+			wg.Add(1)
+			for i := 0; i < localWork; i++ {
+				foo *= 2
+				foo /= 2
+			}
+			wg.Done()
+		}
+		_ = foo
+	})
+}
+
+func BenchmarkWaitGroupAddDone(b *testing.B) {
+	benchmarkWaitGroupAddDone(b, 0)
+}
+
+func BenchmarkWaitGroupAddDoneWork(b *testing.B) {
+	benchmarkWaitGroupAddDone(b, 100)
+}
+
+func benchmarkWaitGroupWait(b *testing.B, localWork int) {
+	var wg WaitGroup
+	b.RunParallel(func(pb *testing.PB) {
+		foo := 0
+		for pb.Next() {
+			wg.Wait()
+			for i := 0; i < localWork; i++ {
+				foo *= 2
+				foo /= 2
+			}
+		}
+		_ = foo
+	})
+}
+
+func BenchmarkWaitGroupWait(b *testing.B) {
+	benchmarkWaitGroupWait(b, 0)
+}
+
+func BenchmarkWaitGroupWaitWork(b *testing.B) {
+	benchmarkWaitGroupWait(b, 100)
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/bpf_bsd.go b/third_party/gofrontend/libgo/go/syscall/bpf_bsd.go
new file mode 100644
index 0000000..cc6c1e7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/bpf_bsd.go
@@ -0,0 +1,169 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+// Berkeley packet filter for BSD variants
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+func BpfStmt(code, k int) *BpfInsn {
+	return &BpfInsn{Code: uint16(code), K: uint32(k)}
+}
+
+func BpfJump(code, k, jt, jf int) *BpfInsn {
+	return &BpfInsn{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
+}
+
+func BpfBuflen(fd int) (int, error) {
+	var l int
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGBLEN, uintptr(unsafe.Pointer(&l)))
+	if err != 0 {
+		return 0, Errno(err)
+	}
+	return l, nil
+}
+
+func SetBpfBuflen(fd, l int) (int, error) {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSBLEN, uintptr(unsafe.Pointer(&l)))
+	if err != 0 {
+		return 0, Errno(err)
+	}
+	return l, nil
+}
+
+func BpfDatalink(fd int) (int, error) {
+	var t int
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGDLT, uintptr(unsafe.Pointer(&t)))
+	if err != 0 {
+		return 0, Errno(err)
+	}
+	return t, nil
+}
+
+func SetBpfDatalink(fd, t int) (int, error) {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSDLT, uintptr(unsafe.Pointer(&t)))
+	if err != 0 {
+		return 0, Errno(err)
+	}
+	return t, nil
+}
+
+func SetBpfPromisc(fd, m int) error {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCPROMISC, uintptr(unsafe.Pointer(&m)))
+	if err != 0 {
+		return Errno(err)
+	}
+	return nil
+}
+
+func FlushBpf(fd int) error {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCFLUSH, 0)
+	if err != 0 {
+		return Errno(err)
+	}
+	return nil
+}
+
+type ivalue struct {
+	name  [IFNAMSIZ]byte
+	value int16
+}
+
+func BpfInterface(fd int, name string) (string, error) {
+	var iv ivalue
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGETIF, uintptr(unsafe.Pointer(&iv)))
+	if err != 0 {
+		return "", Errno(err)
+	}
+	return name, nil
+}
+
+func SetBpfInterface(fd int, name string) error {
+	var iv ivalue
+	copy(iv.name[:], []byte(name))
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETIF, uintptr(unsafe.Pointer(&iv)))
+	if err != 0 {
+		return Errno(err)
+	}
+	return nil
+}
+
+func BpfTimeout(fd int) (*Timeval, error) {
+	var tv Timeval
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGRTIMEOUT, uintptr(unsafe.Pointer(&tv)))
+	if err != 0 {
+		return nil, Errno(err)
+	}
+	return &tv, nil
+}
+
+func SetBpfTimeout(fd int, tv *Timeval) error {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSRTIMEOUT, uintptr(unsafe.Pointer(tv)))
+	if err != 0 {
+		return Errno(err)
+	}
+	return nil
+}
+
+func BpfStats(fd int) (*BpfStat, error) {
+	var s BpfStat
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGSTATS, uintptr(unsafe.Pointer(&s)))
+	if err != 0 {
+		return nil, Errno(err)
+	}
+	return &s, nil
+}
+
+func SetBpfImmediate(fd, m int) error {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCIMMEDIATE, uintptr(unsafe.Pointer(&m)))
+	if err != 0 {
+		return Errno(err)
+	}
+	return nil
+}
+
+func SetBpf(fd int, i []BpfInsn) error {
+	var p BpfProgram
+	p.Len = uint32(len(i))
+	p.Insns = (*BpfInsn)(unsafe.Pointer(&i[0]))
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETF, uintptr(unsafe.Pointer(&p)))
+	if err != 0 {
+		return Errno(err)
+	}
+	return nil
+}
+
+func CheckBpfVersion(fd int) error {
+	var v BpfVersion
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCVERSION, uintptr(unsafe.Pointer(&v)))
+	if err != 0 {
+		return Errno(err)
+	}
+	if v.Major != BPF_MAJOR_VERSION || v.Minor != BPF_MINOR_VERSION {
+		return EINVAL
+	}
+	return nil
+}
+
+func BpfHeadercmpl(fd int) (int, error) {
+	var f int
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGHDRCMPLT, uintptr(unsafe.Pointer(&f)))
+	if err != 0 {
+		return 0, Errno(err)
+	}
+	return f, nil
+}
+
+func SetBpfHeadercmpl(fd, f int) error {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSHDRCMPLT, uintptr(unsafe.Pointer(&f)))
+	if err != 0 {
+		return Errno(err)
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/creds_test.go b/third_party/gofrontend/libgo/go/syscall/creds_test.go
new file mode 100644
index 0000000..b1894c6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/creds_test.go
@@ -0,0 +1,113 @@
+// 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.
+
+// +build linux
+
+package syscall_test
+
+import (
+	"bytes"
+	"net"
+	"os"
+	"syscall"
+	"testing"
+)
+
+// TestSCMCredentials tests the sending and receiving of credentials
+// (PID, UID, GID) in an ancillary message between two UNIX
+// sockets. The SO_PASSCRED socket option is enabled on the sending
+// socket for this to work.
+func TestSCMCredentials(t *testing.T) {
+	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
+	if err != nil {
+		t.Fatalf("Socketpair: %v", err)
+	}
+	defer syscall.Close(fds[0])
+	defer syscall.Close(fds[1])
+
+	err = syscall.SetsockoptInt(fds[0], syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1)
+	if err != nil {
+		t.Fatalf("SetsockoptInt: %v", err)
+	}
+
+	srvFile := os.NewFile(uintptr(fds[0]), "server")
+	defer srvFile.Close()
+	srv, err := net.FileConn(srvFile)
+	if err != nil {
+		t.Errorf("FileConn: %v", err)
+		return
+	}
+	defer srv.Close()
+
+	cliFile := os.NewFile(uintptr(fds[1]), "client")
+	defer cliFile.Close()
+	cli, err := net.FileConn(cliFile)
+	if err != nil {
+		t.Errorf("FileConn: %v", err)
+		return
+	}
+	defer cli.Close()
+
+	var ucred syscall.Ucred
+	if os.Getuid() != 0 {
+		ucred.Pid = int32(os.Getpid())
+		ucred.Uid = 0
+		ucred.Gid = 0
+		oob := syscall.UnixCredentials(&ucred)
+		_, _, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+		if err.(*net.OpError).Err != syscall.EPERM {
+			t.Fatalf("WriteMsgUnix failed with %v, want EPERM", err)
+		}
+	}
+
+	ucred.Pid = int32(os.Getpid())
+	ucred.Uid = uint32(os.Getuid())
+	ucred.Gid = uint32(os.Getgid())
+	oob := syscall.UnixCredentials(&ucred)
+
+	// this is going to send a dummy byte
+	n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+	if err != nil {
+		t.Fatalf("WriteMsgUnix: %v", err)
+	}
+	if n != 0 {
+		t.Fatalf("WriteMsgUnix n = %d, want 0", n)
+	}
+	if oobn != len(oob) {
+		t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob))
+	}
+
+	oob2 := make([]byte, 10*len(oob))
+	n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2)
+	if err != nil {
+		t.Fatalf("ReadMsgUnix: %v", err)
+	}
+	if flags != 0 {
+		t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
+	}
+	if n != 1 {
+		t.Fatalf("ReadMsgUnix n = %d, want 1 (dummy byte)", n)
+	}
+	if oobn2 != oobn {
+		// without SO_PASSCRED set on the socket, ReadMsgUnix will
+		// return zero oob bytes
+		t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn)
+	}
+	oob2 = oob2[:oobn2]
+	if !bytes.Equal(oob, oob2) {
+		t.Fatal("ReadMsgUnix oob bytes don't match")
+	}
+
+	scm, err := syscall.ParseSocketControlMessage(oob2)
+	if err != nil {
+		t.Fatalf("ParseSocketControlMessage: %v", err)
+	}
+	newUcred, err := syscall.ParseUnixCredentials(&scm[0])
+	if err != nil {
+		t.Fatalf("ParseUnixCredentials: %v", err)
+	}
+	if *newUcred != ucred {
+		t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/dir_plan9.go b/third_party/gofrontend/libgo/go/syscall/dir_plan9.go
new file mode 100644
index 0000000..697bf54
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/dir_plan9.go
@@ -0,0 +1,212 @@
+// 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.
+
+// Plan 9 directory marshalling. See intro(5).
+
+package syscall
+
+import "errors"
+
+var (
+	ErrShortStat = errors.New("stat buffer too short")
+	ErrBadStat   = errors.New("malformed stat buffer")
+	ErrBadName   = errors.New("bad character in file name")
+)
+
+// A Qid represents a 9P server's unique identification for a file.
+type Qid struct {
+	Path uint64 // the file server's unique identification for the file
+	Vers uint32 // version number for given Path
+	Type uint8  // the type of the file (syscall.QTDIR for example)
+}
+
+// A Dir contains the metadata for a file.
+type Dir struct {
+	// system-modified data
+	Type uint16 // server type
+	Dev  uint32 // server subtype
+
+	// file data
+	Qid    Qid    // unique id from server
+	Mode   uint32 // permissions
+	Atime  uint32 // last read time
+	Mtime  uint32 // last write time
+	Length int64  // file length
+	Name   string // last element of path
+	Uid    string // owner name
+	Gid    string // group name
+	Muid   string // last modifier name
+}
+
+var nullDir = Dir{
+	Type: ^uint16(0),
+	Dev:  ^uint32(0),
+	Qid: Qid{
+		Path: ^uint64(0),
+		Vers: ^uint32(0),
+		Type: ^uint8(0),
+	},
+	Mode:   ^uint32(0),
+	Atime:  ^uint32(0),
+	Mtime:  ^uint32(0),
+	Length: ^int64(0),
+}
+
+// Null assigns special "don't touch" values to members of d to
+// avoid modifying them during syscall.Wstat.
+func (d *Dir) Null() { *d = nullDir }
+
+// Marshal encodes a 9P stat message corresponding to d into b
+//
+// If there isn't enough space in b for a stat message, ErrShortStat is returned.
+func (d *Dir) Marshal(b []byte) (n int, err error) {
+	n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid)
+	if n > len(b) {
+		return n, ErrShortStat
+	}
+
+	for _, c := range d.Name {
+		if c == '/' {
+			return n, ErrBadName
+		}
+	}
+
+	b = pbit16(b, uint16(n)-2)
+	b = pbit16(b, d.Type)
+	b = pbit32(b, d.Dev)
+	b = pbit8(b, d.Qid.Type)
+	b = pbit32(b, d.Qid.Vers)
+	b = pbit64(b, d.Qid.Path)
+	b = pbit32(b, d.Mode)
+	b = pbit32(b, d.Atime)
+	b = pbit32(b, d.Mtime)
+	b = pbit64(b, uint64(d.Length))
+	b = pstring(b, d.Name)
+	b = pstring(b, d.Uid)
+	b = pstring(b, d.Gid)
+	b = pstring(b, d.Muid)
+
+	return n, nil
+}
+
+// UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
+//
+// If b is too small to hold a valid stat message, ErrShortStat is returned.
+//
+// If the stat message itself is invalid, ErrBadStat is returned.
+func UnmarshalDir(b []byte) (*Dir, error) {
+	if len(b) < STATFIXLEN {
+		return nil, ErrShortStat
+	}
+	size, buf := gbit16(b)
+	if len(b) != int(size)+2 {
+		return nil, ErrBadStat
+	}
+	b = buf
+
+	var d Dir
+	d.Type, b = gbit16(b)
+	d.Dev, b = gbit32(b)
+	d.Qid.Type, b = gbit8(b)
+	d.Qid.Vers, b = gbit32(b)
+	d.Qid.Path, b = gbit64(b)
+	d.Mode, b = gbit32(b)
+	d.Atime, b = gbit32(b)
+	d.Mtime, b = gbit32(b)
+
+	n, b := gbit64(b)
+	d.Length = int64(n)
+
+	var ok bool
+	if d.Name, b, ok = gstring(b); !ok {
+		return nil, ErrBadStat
+	}
+	if d.Uid, b, ok = gstring(b); !ok {
+		return nil, ErrBadStat
+	}
+	if d.Gid, b, ok = gstring(b); !ok {
+		return nil, ErrBadStat
+	}
+	if d.Muid, b, ok = gstring(b); !ok {
+		return nil, ErrBadStat
+	}
+
+	return &d, nil
+}
+
+// pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
+func pbit8(b []byte, v uint8) []byte {
+	b[0] = byte(v)
+	return b[1:]
+}
+
+// pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
+func pbit16(b []byte, v uint16) []byte {
+	b[0] = byte(v)
+	b[1] = byte(v >> 8)
+	return b[2:]
+}
+
+// pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
+func pbit32(b []byte, v uint32) []byte {
+	b[0] = byte(v)
+	b[1] = byte(v >> 8)
+	b[2] = byte(v >> 16)
+	b[3] = byte(v >> 24)
+	return b[4:]
+}
+
+// pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
+func pbit64(b []byte, v uint64) []byte {
+	b[0] = byte(v)
+	b[1] = byte(v >> 8)
+	b[2] = byte(v >> 16)
+	b[3] = byte(v >> 24)
+	b[4] = byte(v >> 32)
+	b[5] = byte(v >> 40)
+	b[6] = byte(v >> 48)
+	b[7] = byte(v >> 56)
+	return b[8:]
+}
+
+// pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
+// returning the remaining slice of b..
+func pstring(b []byte, s string) []byte {
+	b = pbit16(b, uint16(len(s)))
+	n := copy(b, s)
+	return b[n:]
+}
+
+// gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
+func gbit8(b []byte) (uint8, []byte) {
+	return uint8(b[0]), b[1:]
+}
+
+// gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
+func gbit16(b []byte) (uint16, []byte) {
+	return uint16(b[0]) | uint16(b[1])<<8, b[2:]
+}
+
+// gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
+func gbit32(b []byte) (uint32, []byte) {
+	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
+}
+
+// gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
+func gbit64(b []byte) (uint64, []byte) {
+	lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+	hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
+	return uint64(lo) | uint64(hi)<<32, b[8:]
+}
+
+// gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
+// It returns the string with the remaining slice of b and a boolean. If the length is
+// greater than the number of bytes in b, the boolean will be false.
+func gstring(b []byte) (string, []byte, bool) {
+	n, b := gbit16(b)
+	if int(n) > len(b) {
+		return "", b, false
+	}
+	return string(b[:n]), b[n:], true
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/env_plan9.go b/third_party/gofrontend/libgo/go/syscall/env_plan9.go
new file mode 100644
index 0000000..9587ab5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/env_plan9.go
@@ -0,0 +1,142 @@
+// 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.
+
+// Plan 9 environment variables.
+
+package syscall
+
+import (
+	"errors"
+	"sync"
+)
+
+var (
+	// envOnce guards copyenv, which populates env.
+	envOnce sync.Once
+
+	// envLock guards env and envs.
+	envLock sync.RWMutex
+
+	// env maps from an environment variable to its value.
+	env = make(map[string]string)
+
+	// envs contains elements of env in the form "key=value".
+	envs []string
+
+	errZeroLengthKey = errors.New("zero length key")
+	errShortWrite    = errors.New("i/o count too small")
+)
+
+func readenv(key string) (string, error) {
+	fd, err := Open("/env/"+key, O_RDONLY)
+	if err != nil {
+		return "", err
+	}
+	defer Close(fd)
+	l, _ := Seek(fd, 0, 2)
+	Seek(fd, 0, 0)
+	buf := make([]byte, l)
+	n, err := Read(fd, buf)
+	if err != nil {
+		return "", err
+	}
+	if n > 0 && buf[n-1] == 0 {
+		buf = buf[:n-1]
+	}
+	return string(buf), nil
+}
+
+func writeenv(key, value string) error {
+	fd, err := Create("/env/"+key, O_RDWR, 0666)
+	if err != nil {
+		return err
+	}
+	defer Close(fd)
+	b := []byte(value)
+	n, err := Write(fd, b)
+	if err != nil {
+		return err
+	}
+	if n != len(b) {
+		return errShortWrite
+	}
+	return nil
+}
+
+func copyenv() {
+	fd, err := Open("/env", O_RDONLY)
+	if err != nil {
+		return
+	}
+	defer Close(fd)
+	files, err := readdirnames(fd)
+	if err != nil {
+		return
+	}
+	envs = make([]string, len(files))
+	i := 0
+	for _, key := range files {
+		v, err := readenv(key)
+		if err != nil {
+			continue
+		}
+		env[key] = v
+		envs[i] = key + "=" + v
+		i++
+	}
+}
+
+func Getenv(key string) (value string, found bool) {
+	if len(key) == 0 {
+		return "", false
+	}
+
+	envLock.RLock()
+	defer envLock.RUnlock()
+
+	if v, ok := env[key]; ok {
+		return v, true
+	}
+	v, err := readenv(key)
+	if err != nil {
+		return "", false
+	}
+	env[key] = v
+	envs = append(envs, key+"="+v)
+	return v, true
+}
+
+func Setenv(key, value string) error {
+	if len(key) == 0 {
+		return errZeroLengthKey
+	}
+
+	envLock.Lock()
+	defer envLock.Unlock()
+
+	err := writeenv(key, value)
+	if err != nil {
+		return err
+	}
+	env[key] = value
+	envs = append(envs, key+"="+value)
+	return nil
+}
+
+func Clearenv() {
+	envLock.Lock()
+	defer envLock.Unlock()
+
+	env = make(map[string]string)
+	envs = []string{}
+	RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
+}
+
+func Environ() []string {
+	envLock.RLock()
+	defer envLock.RUnlock()
+
+	envOnce.Do(copyenv)
+	return append([]string(nil), envs...)
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/env_unix.go b/third_party/gofrontend/libgo/go/syscall/env_unix.go
new file mode 100644
index 0000000..7f39958
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/env_unix.go
@@ -0,0 +1,119 @@
+// Copyright 2010 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+// Unix environment variables.
+
+package syscall
+
+import "sync"
+
+var (
+	// envOnce guards initialization by copyenv, which populates env.
+	envOnce sync.Once
+
+	// envLock guards env and envs.
+	envLock sync.RWMutex
+
+	// env maps from an environment variable to its first occurrence in envs.
+	env map[string]int
+
+	// envs is provided by the runtime. elements are expected to be
+	// of the form "key=value".
+	Envs []string
+)
+
+// setenv_c is provided by the runtime, but is a no-op if cgo isn't
+// loaded.
+func setenv_c(k, v string)
+
+func copyenv() {
+	env = make(map[string]int)
+	for i, s := range Envs {
+		for j := 0; j < len(s); j++ {
+			if s[j] == '=' {
+				key := s[:j]
+				if _, ok := env[key]; !ok {
+					env[key] = i
+				}
+				break
+			}
+		}
+	}
+}
+
+func Getenv(key string) (value string, found bool) {
+	envOnce.Do(copyenv)
+	if len(key) == 0 {
+		return "", false
+	}
+
+	envLock.RLock()
+	defer envLock.RUnlock()
+
+	i, ok := env[key]
+	if !ok {
+		return "", false
+	}
+	s := Envs[i]
+	for i := 0; i < len(s); i++ {
+		if s[i] == '=' {
+			return s[i+1:], true
+		}
+	}
+	return "", false
+}
+
+func Setenv(key, value string) error {
+	envOnce.Do(copyenv)
+	if len(key) == 0 {
+		return EINVAL
+	}
+	for i := 0; i < len(key); i++ {
+		if key[i] == '=' || key[i] == 0 {
+			return EINVAL
+		}
+	}
+	for i := 0; i < len(value); i++ {
+		if value[i] == 0 {
+			return EINVAL
+		}
+	}
+
+	envLock.Lock()
+	defer envLock.Unlock()
+
+	i, ok := env[key]
+	kv := key + "=" + value
+	if ok {
+		Envs[i] = kv
+	} else {
+		i = len(Envs)
+		Envs = append(Envs, kv)
+	}
+	env[key] = i
+	setenv_c(key, value)
+	return nil
+}
+
+func Clearenv() {
+	envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
+
+	envLock.Lock()
+	defer envLock.Unlock()
+
+	env = make(map[string]int)
+	Envs = []string{}
+	// TODO(bradfitz): pass through to C
+}
+
+func Environ() []string {
+	envOnce.Do(copyenv)
+	envLock.RLock()
+	defer envLock.RUnlock()
+	a := make([]string, len(Envs))
+	copy(a, Envs)
+	return a
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/env_windows.go b/third_party/gofrontend/libgo/go/syscall/env_windows.go
new file mode 100644
index 0000000..420b387
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/env_windows.go
@@ -0,0 +1,82 @@
+// Copyright 2010 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.
+
+// Windows environment variables.
+
+package syscall
+
+import (
+	"unicode/utf16"
+	"unsafe"
+)
+
+func Getenv(key string) (value string, found bool) {
+	keyp, err := UTF16PtrFromString(key)
+	if err != nil {
+		return "", false
+	}
+	b := make([]uint16, 100)
+	n, e := GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
+	if n == 0 && e == ERROR_ENVVAR_NOT_FOUND {
+		return "", false
+	}
+	if n > uint32(len(b)) {
+		b = make([]uint16, n)
+		n, e = GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
+		if n > uint32(len(b)) {
+			n = 0
+		}
+	}
+	return string(utf16.Decode(b[0:n])), true
+}
+
+func Setenv(key, value string) error {
+	v, err := UTF16PtrFromString(value)
+	if err != nil {
+		return err
+	}
+	keyp, err := UTF16PtrFromString(key)
+	if err != nil {
+		return err
+	}
+	e := SetEnvironmentVariable(keyp, v)
+	if e != nil {
+		return e
+	}
+	return nil
+}
+
+func Clearenv() {
+	for _, s := range Environ() {
+		// Environment variables can begin with =
+		// so start looking for the separator = at j=1.
+		// http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
+		for j := 1; j < len(s); j++ {
+			if s[j] == '=' {
+				Setenv(s[0:j], "")
+				break
+			}
+		}
+	}
+}
+
+func Environ() []string {
+	s, e := GetEnvironmentStrings()
+	if e != nil {
+		return nil
+	}
+	defer FreeEnvironmentStrings(s)
+	r := make([]string, 0, 50) // Empty with room to grow.
+	for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(s)); true; i++ {
+		if p[i] == 0 {
+			// empty string marks the end
+			if i <= from {
+				break
+			}
+			r = append(r, string(utf16.Decode(p[from:i])))
+			from = i + 1
+		}
+	}
+	return r
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/errno.c b/third_party/gofrontend/libgo/go/syscall/errno.c
new file mode 100644
index 0000000..5cdc773
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/errno.c
@@ -0,0 +1,27 @@
+/* errno.c -- functions for getting and setting errno
+
+   Copyright 2010 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 <errno.h>
+#include <stdint.h>
+
+#include "runtime.h"
+
+/* errno is typically a macro. These functions set 
+   and get errno specific to the libc being used.  */
+
+uintptr_t GetErrno() __asm__ (GOSYM_PREFIX "syscall.GetErrno");
+void SetErrno(uintptr_t) __asm__ (GOSYM_PREFIX "syscall.SetErrno");
+
+uintptr_t
+GetErrno()
+{
+  return (uintptr_t) errno;
+}
+
+void
+SetErrno(uintptr_t value)
+{
+  errno = (int) value;
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/errstr.go b/third_party/gofrontend/libgo/go/syscall/errstr.go
new file mode 100644
index 0000000..aa656ca
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/errstr.go
@@ -0,0 +1,32 @@
+// errstr.go -- Error strings.
+
+// 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 syscall
+
+//sysnb	strerror_r(errnum int, buf []byte) (err Errno)
+//strerror_r(errnum _C_int, buf *byte, buflen Size_t) _C_int
+
+func Errstr(errnum int) string {
+	for len := 128; ; len *= 2 {
+		b := make([]byte, len)
+		errno := strerror_r(errnum, b)
+		if errno == 0 {
+			i := 0
+			for b[i] != 0 {
+				i++
+			}
+			// Lowercase first letter: Bad -> bad, but
+			// STREAM -> STREAM.
+			if i > 1 && 'A' <= b[0] && b[0] <= 'Z' && 'a' <= b[1] && b[1] <= 'z' {
+				b[0] += 'a' - 'A'
+			}
+			return string(b[:i])
+		}
+		if errno != ERANGE {
+			return "errstr failure"
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/errstr_linux.go b/third_party/gofrontend/libgo/go/syscall/errstr_linux.go
new file mode 100644
index 0000000..d10476d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/errstr_linux.go
@@ -0,0 +1,28 @@
+// errstr_rtems.go -- RTEMS specific error strings.
+
+// Copyright 2010 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 syscall
+
+import "unsafe"
+
+//sysnb	strerror_r(errnum int, b []byte) (errstr *byte)
+//strerror_r(errnum _C_int, b *byte, len Size_t) *byte
+
+func Errstr(errnum int) string {
+	a := make([]byte, 128)
+	p := strerror_r(errnum, a)
+	b := (*[1000]byte)(unsafe.Pointer(p))
+	i := 0
+	for b[i] != 0 {
+		i++
+	}
+	// Lowercase first letter: Bad -> bad, but STREAM -> STREAM.
+	if i > 1 && 'A' <= b[0] && b[0] <= 'Z' && 'a' <= b[1] && b[1] <= 'z' {
+		c := b[0] + 'a' - 'A'
+		return string(c) + string(b[1:i])
+	}
+	return string(b[:i])
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/errstr_nor.go b/third_party/gofrontend/libgo/go/syscall/errstr_nor.go
new file mode 100644
index 0000000..796561a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/errstr_nor.go
@@ -0,0 +1,41 @@
+// errstr.go -- Error strings when there is no strerror_r.
+
+// 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.
+
+package syscall
+
+import (
+	"sync"
+	"unsafe"
+)
+
+//sysnb	strerror(errnum int) (buf *byte)
+//strerror(errnum _C_int) *byte
+
+var errstr_lock sync.Mutex
+
+func Errstr(errno int) string {
+	errstr_lock.Lock()
+
+	bp := strerror(errno)
+	b := (*[1000]byte)(unsafe.Pointer(bp))
+	i := 0
+	for b[i] != 0 {
+		i++
+	}
+
+	// Lowercase first letter: Bad -> bad, but STREAM -> STREAM.
+	var s string
+	if i > 1 && 'A' <= b[0] && b[0] <= 'Z' && 'a' <= b[1] && b[1] <= 'z' {
+		c := b[0] + 'a' - 'A'
+		s = string(c) + string(b[1:i])
+	} else {
+		s = string(b[:i])
+	}
+
+	errstr_lock.Unlock()
+
+	return s
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/exec_bsd.go b/third_party/gofrontend/libgo/go/syscall/exec_bsd.go
new file mode 100644
index 0000000..217e0c8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/exec_bsd.go
@@ -0,0 +1,249 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+type SysProcAttr struct {
+	Chroot     string      // Chroot.
+	Credential *Credential // Credential.
+	Ptrace     bool        // Enable tracing.
+	Setsid     bool        // Create session.
+	Setpgid    bool        // Set process group ID to new pid (SYSV setpgrp)
+	Setctty    bool        // Set controlling terminal to fd 0
+	Noctty     bool        // Detach fd 0 from controlling terminal
+}
+
+// Implemented in runtime package.
+func runtime_BeforeFork()
+func runtime_AfterFork()
+
+// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
+// If a dup or exec fails, write the errno error to pipe.
+// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
+// In the child, this function must not acquire any locks, because
+// they might have been locked at the time of the fork.  This means
+// no rescheduling, no malloc calls, and no new stack segments.
+// For the same reason compiler does not race instrument it.
+// The calls to RawSyscall are okay because they are assembly
+// functions that do not grow the stack.
+func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
+	// Declare all variables at top in case any
+	// declarations require heap allocation (e.g., err1).
+	var (
+		r1     Pid_t
+		err1   Errno
+		nextfd int
+		i      int
+	)
+
+	// guard against side effects of shuffling fds below.
+	// Make sure that nextfd is beyond any currently open files so
+	// that we can't run the risk of overwriting any of them.
+	fd := make([]int, len(attr.Files))
+	nextfd = len(attr.Files)
+	for i, ufd := range attr.Files {
+		if nextfd < int(ufd) {
+			nextfd = int(ufd)
+		}
+		fd[i] = int(ufd)
+	}
+	nextfd++
+
+	// About to call fork.
+	// No more allocation or calls of non-assembly functions.
+	runtime_BeforeFork()
+	r1, err1 = raw_fork()
+	if err1 != 0 {
+		runtime_AfterFork()
+		return 0, err1
+	}
+
+	if r1 != 0 {
+		// parent; return PID
+		runtime_AfterFork()
+		return int(r1), 0
+	}
+
+	// Fork succeeded, now in child.
+
+	// Enable tracing if requested.
+	if sys.Ptrace {
+		err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Session ID
+	if sys.Setsid {
+		err1 = raw_setsid()
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Set process group
+	if sys.Setpgid {
+		err1 = raw_setpgid(0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Chroot
+	if chroot != nil {
+		err1 = raw_chroot(chroot)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// User and groups
+	if cred := sys.Credential; cred != nil {
+		ngroups := len(cred.Groups)
+		if ngroups == 0 {
+			err2 := setgroups(0, nil)
+			if err2 == nil {
+				err1 = 0
+			} else {
+				err1 = err2.(Errno)
+			}
+		} else {
+			groups := make([]Gid_t, ngroups)
+			for i, v := range cred.Groups {
+				groups[i] = Gid_t(v)
+			}
+			err2 := setgroups(ngroups, &groups[0])
+			if err2 == nil {
+				err1 = 0
+			} else {
+				err1 = err2.(Errno)
+			}
+		}
+		if err1 != 0 {
+			goto childerror
+		}
+		err2 := Setgid(int(cred.Gid))
+		if err2 != nil {
+			err1 = err2.(Errno)
+			goto childerror
+		}
+		err2 = Setuid(int(cred.Uid))
+		if err2 != nil {
+			err1 = err2.(Errno)
+			goto childerror
+		}
+	}
+
+	// Chdir
+	if dir != nil {
+		err1 = raw_chdir(dir)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Pass 1: look for fd[i] < i and move those up above len(fd)
+	// so that pass 2 won't stomp on an fd it needs later.
+	if pipe < nextfd {
+		err1 = raw_dup2(pipe, nextfd)
+		if err1 != 0 {
+			goto childerror
+		}
+		raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
+		pipe = nextfd
+		nextfd++
+	}
+	for i = 0; i < len(fd); i++ {
+		if fd[i] >= 0 && fd[i] < int(i) {
+			err1 = raw_dup2(fd[i], nextfd)
+			if err1 != 0 {
+				goto childerror
+			}
+			raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
+			fd[i] = nextfd
+			nextfd++
+			if nextfd == pipe { // don't stomp on pipe
+				nextfd++
+			}
+		}
+	}
+
+	// Pass 2: dup fd[i] down onto i.
+	for i = 0; i < len(fd); i++ {
+		if fd[i] == -1 {
+			raw_close(i)
+			continue
+		}
+		if fd[i] == int(i) {
+			// dup2(i, i) won't clear close-on-exec flag on Linux,
+			// probably not elsewhere either.
+			_, err1 = raw_fcntl(fd[i], F_SETFD, 0)
+			if err1 != 0 {
+				goto childerror
+			}
+			continue
+		}
+		// The new fd is created NOT close-on-exec,
+		// which is exactly what we want.
+		err1 = raw_dup2(fd[i], i)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// By convention, we don't close-on-exec the fds we are
+	// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
+	// Programs that know they inherit fds >= 3 will need
+	// to set them close-on-exec.
+	for i = len(fd); i < 3; i++ {
+		raw_close(i)
+	}
+
+	// Detach fd 0 from tty
+	if sys.Noctty {
+		_, err1 = raw_ioctl(0, TIOCNOTTY, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Make fd 0 the tty
+	if sys.Setctty {
+		_, err1 = raw_ioctl(0, TIOCSCTTY, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Time to exec.
+	err1 = raw_execve(argv0, &argv[0], &envv[0])
+
+childerror:
+	// send error code on pipe
+	raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+	for {
+		raw_exit(253)
+	}
+}
+
+// Try to open a pipe with O_CLOEXEC set on both file descriptors.
+func forkExecPipe(p []int) error {
+	err := Pipe(p)
+	if err != nil {
+		return err
+	}
+	_, err = fcntl(p[0], F_SETFD, FD_CLOEXEC)
+	if err != nil {
+		return err
+	}
+	_, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
+	return err
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/exec_linux.go b/third_party/gofrontend/libgo/go/syscall/exec_linux.go
new file mode 100644
index 0000000..2371902
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/exec_linux.go
@@ -0,0 +1,284 @@
+// 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.
+
+// +build linux
+
+package syscall
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+//sysnb	raw_prctl(option int, arg2 int, arg3 int, arg4 int, arg5 int) (ret int, err Errno)
+//prctl(option _C_int, arg2 _C_long, arg3 _C_long, arg4 _C_long, arg5 _C_long) _C_int
+
+type SysProcAttr struct {
+	Chroot     string      // Chroot.
+	Credential *Credential // Credential.
+	Ptrace     bool        // Enable tracing.
+	Setsid     bool        // Create session.
+	Setpgid    bool        // Set process group ID to new pid (SYSV setpgrp)
+	Setctty    bool        // Set controlling terminal to fd Ctty (only meaningful if Setsid is set)
+	Noctty     bool        // Detach fd 0 from controlling terminal
+	Ctty       int         // Controlling TTY fd (Linux only)
+	Pdeathsig  Signal      // Signal that the process will get when its parent dies (Linux only)
+	Cloneflags uintptr     // Flags for clone calls (Linux only)
+}
+
+// Implemented in runtime package.
+func runtime_BeforeFork()
+func runtime_AfterFork()
+
+// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
+// If a dup or exec fails, write the errno error to pipe.
+// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
+// In the child, this function must not acquire any locks, because
+// they might have been locked at the time of the fork.  This means
+// no rescheduling, no malloc calls, and no new stack segments.
+// For the same reason compiler does not race instrument it.
+// The calls to RawSyscall are okay because they are assembly
+// functions that do not grow the stack.
+func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
+	// Declare all variables at top in case any
+	// declarations require heap allocation (e.g., err1).
+	var (
+		r1     uintptr
+		err1   Errno
+		nextfd int
+		i      int
+	)
+
+	// Guard against side effects of shuffling fds below.
+	// Make sure that nextfd is beyond any currently open files so
+	// that we can't run the risk of overwriting any of them.
+	fd := make([]int, len(attr.Files))
+	nextfd = len(attr.Files)
+	for i, ufd := range attr.Files {
+		if nextfd < int(ufd) {
+			nextfd = int(ufd)
+		}
+		fd[i] = int(ufd)
+	}
+	nextfd++
+
+	// About to call fork.
+	// No more allocation or calls of non-assembly functions.
+	runtime_BeforeFork()
+	if runtime.GOARCH == "s390x" || runtime.GOARCH == "s390" {
+		r1, _, err1 = RawSyscall6(SYS_CLONE, 0, uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0)
+	} else {
+		r1, _, err1 = RawSyscall6(SYS_CLONE, uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0, 0)
+	}
+	if err1 != 0 {
+		runtime_AfterFork()
+		return 0, err1
+	}
+
+	if r1 != 0 {
+		// parent; return PID
+		runtime_AfterFork()
+		return int(r1), 0
+	}
+
+	// Fork succeeded, now in child.
+
+	// Parent death signal
+	if sys.Pdeathsig != 0 {
+		_, err1 = raw_prctl(PR_SET_PDEATHSIG, int(sys.Pdeathsig), 0, 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+
+		// Signal self if parent is already dead. This might cause a
+		// duplicate signal in rare cases, but it won't matter when
+		// using SIGKILL.
+		ppid := Getppid()
+		if ppid == 1 {
+			pid = Getpid()
+			err2 := Kill(pid, sys.Pdeathsig)
+			if err2 != nil {
+				err1 = err2.(Errno)
+				goto childerror
+			}
+		}
+	}
+
+	// Enable tracing if requested.
+	if sys.Ptrace {
+		err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Session ID
+	if sys.Setsid {
+		err1 = raw_setsid()
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Set process group
+	if sys.Setpgid {
+		err1 = raw_setpgid(0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Chroot
+	if chroot != nil {
+		err1 = raw_chroot(chroot)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// User and groups
+	if cred := sys.Credential; cred != nil {
+		ngroups := len(cred.Groups)
+		if ngroups == 0 {
+			err2 := setgroups(0, nil)
+			if err2 == nil {
+				err1 = 0
+			} else {
+				err1 = err2.(Errno)
+			}
+		} else {
+			groups := make([]Gid_t, ngroups)
+			for i, v := range cred.Groups {
+				groups[i] = Gid_t(v)
+			}
+			err2 := setgroups(ngroups, &groups[0])
+			if err2 == nil {
+				err1 = 0
+			} else {
+				err1 = err2.(Errno)
+			}
+		}
+		if err1 != 0 {
+			goto childerror
+		}
+		err2 := Setgid(int(cred.Gid))
+		if err2 != nil {
+			err1 = err2.(Errno)
+			goto childerror
+		}
+		err2 = Setuid(int(cred.Uid))
+		if err2 != nil {
+			err1 = err2.(Errno)
+			goto childerror
+		}
+	}
+
+	// Chdir
+	if dir != nil {
+		err1 = raw_chdir(dir)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Pass 1: look for fd[i] < i and move those up above len(fd)
+	// so that pass 2 won't stomp on an fd it needs later.
+	if pipe < nextfd {
+		err1 = raw_dup2(pipe, nextfd)
+		if err1 != 0 {
+			goto childerror
+		}
+		raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
+		pipe = nextfd
+		nextfd++
+	}
+	for i = 0; i < len(fd); i++ {
+		if fd[i] >= 0 && fd[i] < int(i) {
+			err1 = raw_dup2(fd[i], nextfd)
+			if err1 != 0 {
+				goto childerror
+			}
+			raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
+			fd[i] = nextfd
+			nextfd++
+			if nextfd == pipe { // don't stomp on pipe
+				nextfd++
+			}
+		}
+	}
+
+	// Pass 2: dup fd[i] down onto i.
+	for i = 0; i < len(fd); i++ {
+		if fd[i] == -1 {
+			raw_close(i)
+			continue
+		}
+		if fd[i] == int(i) {
+			// dup2(i, i) won't clear close-on-exec flag on Linux,
+			// probably not elsewhere either.
+			_, err1 = raw_fcntl(fd[i], F_SETFD, 0)
+			if err1 != 0 {
+				goto childerror
+			}
+			continue
+		}
+		// The new fd is created NOT close-on-exec,
+		// which is exactly what we want.
+		err1 = raw_dup2(fd[i], i)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// By convention, we don't close-on-exec the fds we are
+	// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
+	// Programs that know they inherit fds >= 3 will need
+	// to set them close-on-exec.
+	for i = len(fd); i < 3; i++ {
+		raw_close(i)
+	}
+
+	// Detach fd 0 from tty
+	if sys.Noctty {
+		_, err1 = raw_ioctl(0, TIOCNOTTY, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Make fd 0 the tty
+	if sys.Setctty && sys.Ctty >= 0 {
+		_, err1 = raw_ioctl(0, TIOCSCTTY, sys.Ctty)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Time to exec.
+	err1 = raw_execve(argv0, &argv[0], &envv[0])
+
+childerror:
+	// send error code on pipe
+	raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+	for {
+		raw_exit(253)
+	}
+}
+
+// Try to open a pipe with O_CLOEXEC set on both file descriptors.
+func forkExecPipe(p []int) (err error) {
+	err = Pipe2(p, O_CLOEXEC)
+	// pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so it
+	// might not be implemented.
+	if err == ENOSYS {
+		if err = Pipe(p); err != nil {
+			return
+		}
+		if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != nil {
+			return
+		}
+		_, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/exec_stubs.go b/third_party/gofrontend/libgo/go/syscall/exec_stubs.go
new file mode 100644
index 0000000..35bb174
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/exec_stubs.go
@@ -0,0 +1,33 @@
+// Copyright 2010 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.
+
+// Stubs for fork, exec and wait.
+
+package syscall
+
+func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
+	return -1, ENOSYS
+}
+
+func Exec(argv0 string, argv []string, envv []string) (err int) {
+	return ENOSYS
+}
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
+	return -1, ENOSYS
+}
+
+func (w WaitStatus) Exited() bool    { return false }
+func (w WaitStatus) Signaled() bool  { return false }
+func (w WaitStatus) Stopped() bool   { return false }
+func (w WaitStatus) Continued() bool { return false }
+func (w WaitStatus) CoreDump() bool  { return false }
+func (w WaitStatus) ExitStatus() int { return 0 }
+func (w WaitStatus) Signal() int     { return 0 }
+func (w WaitStatus) StopSignal() int { return 0 }
+func (w WaitStatus) TrapCause() int  { return 0 }
+
+func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno {
+	return ENOSYS
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/exec_unix.go b/third_party/gofrontend/libgo/go/syscall/exec_unix.go
new file mode 100644
index 0000000..6bf28cc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/exec_unix.go
@@ -0,0 +1,293 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+// Fork, exec, wait, etc.
+
+package syscall
+
+import (
+	"runtime"
+	"sync"
+	"unsafe"
+)
+
+//sysnb	raw_fork() (pid Pid_t, err Errno)
+//fork() Pid_t
+
+//sysnb raw_setsid() (err Errno)
+//setsid() Pid_t
+
+//sysnb raw_setpgid(pid int, pgid int) (err Errno)
+//setpgid(pid Pid_t, pgid Pid_t) _C_int
+
+//sysnb	raw_chroot(path *byte) (err Errno)
+//chroot(path *byte) _C_int
+
+//sysnb	raw_chdir(path *byte) (err Errno)
+//chdir(path *byte) _C_int
+
+//sysnb	raw_fcntl(fd int, cmd int, arg int) (val int, err Errno)
+//__go_fcntl(fd _C_int, cmd _C_int, arg _C_int) _C_int
+
+//sysnb	raw_close(fd int) (err Errno)
+//close(fd _C_int) _C_int
+
+//sysnb	raw_ioctl(fd int, cmd int, val int) (rval int, err Errno)
+//ioctl(fd _C_int, cmd _C_int, val _C_int) _C_int
+
+//sysnb	raw_execve(argv0 *byte, argv **byte, envv **byte) (err Errno)
+//execve(argv0 *byte, argv **byte, envv **byte) _C_int
+
+//sysnb	raw_write(fd int, buf *byte, count int) (err Errno)
+//write(fd _C_int, buf *byte, count Size_t) Ssize_t
+
+//sysnb	raw_exit(status int)
+//_exit(status _C_int)
+
+//sysnb raw_dup2(oldfd int, newfd int) (err Errno)
+//dup2(oldfd _C_int, newfd _C_int) _C_int
+
+// Lock synchronizing creation of new file descriptors with fork.
+//
+// We want the child in a fork/exec sequence to inherit only the
+// file descriptors we intend.  To do that, we mark all file
+// descriptors close-on-exec and then, in the child, explicitly
+// unmark the ones we want the exec'ed program to keep.
+// Unix doesn't make this easy: there is, in general, no way to
+// allocate a new file descriptor close-on-exec.  Instead you
+// have to allocate the descriptor and then mark it close-on-exec.
+// If a fork happens between those two events, the child's exec
+// will inherit an unwanted file descriptor.
+//
+// This lock solves that race: the create new fd/mark close-on-exec
+// operation is done holding ForkLock for reading, and the fork itself
+// is done holding ForkLock for writing.  At least, that's the idea.
+// There are some complications.
+//
+// Some system calls that create new file descriptors can block
+// for arbitrarily long times: open on a hung NFS server or named
+// pipe, accept on a socket, and so on.  We can't reasonably grab
+// the lock across those operations.
+//
+// It is worse to inherit some file descriptors than others.
+// If a non-malicious child accidentally inherits an open ordinary file,
+// that's not a big deal.  On the other hand, if a long-lived child
+// accidentally inherits the write end of a pipe, then the reader
+// of that pipe will not see EOF until that child exits, potentially
+// causing the parent program to hang.  This is a common problem
+// in threaded C programs that use popen.
+//
+// Luckily, the file descriptors that are most important not to
+// inherit are not the ones that can take an arbitrarily long time
+// to create: pipe returns instantly, and the net package uses
+// non-blocking I/O to accept on a listening socket.
+// The rules for which file descriptor-creating operations use the
+// ForkLock are as follows:
+//
+// 1) Pipe.    Does not block.  Use the ForkLock.
+// 2) Socket.  Does not block.  Use the ForkLock.
+// 3) Accept.  If using non-blocking mode, use the ForkLock.
+//             Otherwise, live with the race.
+// 4) Open.    Can block.  Use O_CLOEXEC if available (GNU/Linux).
+//             Otherwise, live with the race.
+// 5) Dup.     Does not block.  Use the ForkLock.
+//             On GNU/Linux, could use fcntl F_DUPFD_CLOEXEC
+//             instead of the ForkLock, but only for dup(fd, -1).
+
+var ForkLock sync.RWMutex
+
+// StringSlicePtr is deprecated. Use SlicePtrFromStrings instead.
+// If any string contains a NUL byte this function panics instead
+// of returning an error.
+func StringSlicePtr(ss []string) []*byte {
+	bb := make([]*byte, len(ss)+1)
+	for i := 0; i < len(ss); i++ {
+		bb[i] = StringBytePtr(ss[i])
+	}
+	bb[len(ss)] = nil
+	return bb
+}
+
+// SlicePtrFromStrings converts a slice of strings to a slice of
+// pointers to NUL-terminated byte slices. If any string contains
+// a NUL byte, it returns (nil, EINVAL).
+func SlicePtrFromStrings(ss []string) ([]*byte, error) {
+	var err error
+	bb := make([]*byte, len(ss)+1)
+	for i := 0; i < len(ss); i++ {
+		bb[i], err = BytePtrFromString(ss[i])
+		if err != nil {
+			return nil, err
+		}
+	}
+	bb[len(ss)] = nil
+	return bb, nil
+}
+
+func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
+
+func SetNonblock(fd int, nonblocking bool) (err error) {
+	flag, err := fcntl(fd, F_GETFL, 0)
+	if err != nil {
+		return err
+	}
+	if nonblocking {
+		flag |= O_NONBLOCK
+	} else {
+		flag &= ^O_NONBLOCK
+	}
+	_, err = fcntl(fd, F_SETFL, flag)
+	return err
+}
+
+// Credential holds user and group identities to be assumed
+// by a child process started by StartProcess.
+type Credential struct {
+	Uid    uint32   // User ID.
+	Gid    uint32   // Group ID.
+	Groups []uint32 // Supplementary group IDs.
+}
+
+// ProcAttr holds attributes that will be applied to a new process started
+// by StartProcess.
+type ProcAttr struct {
+	Dir   string    // Current working directory.
+	Env   []string  // Environment.
+	Files []uintptr // File descriptors.
+	Sys   *SysProcAttr
+}
+
+var zeroProcAttr ProcAttr
+var zeroSysProcAttr SysProcAttr
+
+func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
+	var p [2]int
+	var n int
+	var err1 Errno
+	var wstatus WaitStatus
+
+	if attr == nil {
+		attr = &zeroProcAttr
+	}
+	sys := attr.Sys
+	if sys == nil {
+		sys = &zeroSysProcAttr
+	}
+
+	p[0] = -1
+	p[1] = -1
+
+	// Convert args to C form.
+	argv0p, err := BytePtrFromString(argv0)
+	if err != nil {
+		return 0, err
+	}
+	argvp, err := SlicePtrFromStrings(argv)
+	if err != nil {
+		return 0, err
+	}
+	envvp, err := SlicePtrFromStrings(attr.Env)
+	if err != nil {
+		return 0, err
+	}
+
+	if (runtime.GOOS == "freebsd" || runtime.GOOS == "dragonfly") && len(argv[0]) > len(argv0) {
+		argvp[0] = argv0p
+	}
+
+	var chroot *byte
+	if sys.Chroot != "" {
+		chroot, err = BytePtrFromString(sys.Chroot)
+		if err != nil {
+			return 0, err
+		}
+	}
+	var dir *byte
+	if attr.Dir != "" {
+		dir, err = BytePtrFromString(attr.Dir)
+		if err != nil {
+			return 0, err
+		}
+	}
+
+	// Acquire the fork lock so that no other threads
+	// create new fds that are not yet close-on-exec
+	// before we fork.
+	ForkLock.Lock()
+
+	// Allocate child status pipe close on exec.
+	if err = forkExecPipe(p[:]); err != nil {
+		goto error
+	}
+
+	// Kick off child.
+	pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
+	if err1 != 0 {
+		goto error
+	}
+	ForkLock.Unlock()
+
+	// Read child error status from pipe.
+	Close(p[1])
+	n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+	Close(p[0])
+	if err != nil || n != 0 {
+		if n == int(unsafe.Sizeof(err1)) {
+			err = Errno(err1)
+		}
+		if err == nil {
+			err = EPIPE
+		}
+
+		// Child failed; wait for it to exit, to make sure
+		// the zombies don't accumulate.
+		_, err1 := Wait4(pid, &wstatus, 0, nil)
+		for err1 == EINTR {
+			_, err1 = Wait4(pid, &wstatus, 0, nil)
+		}
+		return 0, err
+	}
+
+	// Read got EOF, so pipe closed on exec, so exec succeeded.
+	return pid, nil
+
+error:
+	if p[0] >= 0 {
+		Close(p[0])
+		Close(p[1])
+	}
+	ForkLock.Unlock()
+	return 0, err
+}
+
+// Combination of fork and exec, careful to be thread safe.
+func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
+	return forkExec(argv0, argv, attr)
+}
+
+// StartProcess wraps ForkExec for package os.
+func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
+	pid, err = forkExec(argv0, argv, attr)
+	return pid, 0, err
+}
+
+// Ordinary exec.
+func Exec(argv0 string, argv []string, envv []string) (err error) {
+	argv0p, err := BytePtrFromString(argv0)
+	if err != nil {
+		return err
+	}
+	argvp, err := SlicePtrFromStrings(argv)
+	if err != nil {
+		return err
+	}
+	envvp, err := SlicePtrFromStrings(envv)
+	if err != nil {
+		return err
+	}
+	err1 := raw_execve(argv0p, &argvp[0], &envvp[0])
+	return Errno(err1)
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/exec_windows.go b/third_party/gofrontend/libgo/go/syscall/exec_windows.go
new file mode 100644
index 0000000..82abc07
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/exec_windows.go
@@ -0,0 +1,341 @@
+// 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.
+
+// Fork, exec, wait, etc.
+
+package syscall
+
+import (
+	"sync"
+	"unicode/utf16"
+	"unsafe"
+)
+
+var ForkLock sync.RWMutex
+
+// EscapeArg rewrites command line argument s as prescribed
+// in http://msdn.microsoft.com/en-us/library/ms880421.
+// This function returns "" (2 double quotes) if s is empty.
+// Alternatively, these transformations are done:
+// - every back slash (\) is doubled, but only if immediately
+//   followed by double quote (");
+// - every double quote (") is escaped by back slash (\);
+// - finally, s is wrapped with double quotes (arg -> "arg"),
+//   but only if there is space or tab inside s.
+func EscapeArg(s string) string {
+	if len(s) == 0 {
+		return "\"\""
+	}
+	n := len(s)
+	hasSpace := false
+	for i := 0; i < len(s); i++ {
+		switch s[i] {
+		case '"', '\\':
+			n++
+		case ' ', '\t':
+			hasSpace = true
+		}
+	}
+	if hasSpace {
+		n += 2
+	}
+	if n == len(s) {
+		return s
+	}
+
+	qs := make([]byte, n)
+	j := 0
+	if hasSpace {
+		qs[j] = '"'
+		j++
+	}
+	slashes := 0
+	for i := 0; i < len(s); i++ {
+		switch s[i] {
+		default:
+			slashes = 0
+			qs[j] = s[i]
+		case '\\':
+			slashes++
+			qs[j] = s[i]
+		case '"':
+			for ; slashes > 0; slashes-- {
+				qs[j] = '\\'
+				j++
+			}
+			qs[j] = '\\'
+			j++
+			qs[j] = s[i]
+		}
+		j++
+	}
+	if hasSpace {
+		for ; slashes > 0; slashes-- {
+			qs[j] = '\\'
+			j++
+		}
+		qs[j] = '"'
+		j++
+	}
+	return string(qs[:j])
+}
+
+// makeCmdLine builds a command line out of args by escaping "special"
+// characters and joining the arguments with spaces.
+func makeCmdLine(args []string) string {
+	var s string
+	for _, v := range args {
+		if s != "" {
+			s += " "
+		}
+		s += EscapeArg(v)
+	}
+	return s
+}
+
+// createEnvBlock converts an array of environment strings into
+// the representation required by CreateProcess: a sequence of NUL
+// terminated strings followed by a nil.
+// Last bytes are two UCS-2 NULs, or four NUL bytes.
+func createEnvBlock(envv []string) *uint16 {
+	if len(envv) == 0 {
+		return &utf16.Encode([]rune("\x00\x00"))[0]
+	}
+	length := 0
+	for _, s := range envv {
+		length += len(s) + 1
+	}
+	length += 1
+
+	b := make([]byte, length)
+	i := 0
+	for _, s := range envv {
+		l := len(s)
+		copy(b[i:i+l], []byte(s))
+		copy(b[i+l:i+l+1], []byte{0})
+		i = i + l + 1
+	}
+	copy(b[i:i+1], []byte{0})
+
+	return &utf16.Encode([]rune(string(b)))[0]
+}
+
+func CloseOnExec(fd Handle) {
+	SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
+}
+
+func SetNonblock(fd Handle, nonblocking bool) (err error) {
+	return nil
+}
+
+// getFullPath retrieves the full path of the specified file.
+// Just a wrapper for Windows GetFullPathName api.
+func getFullPath(name string) (path string, err error) {
+	p, err := UTF16PtrFromString(name)
+	if err != nil {
+		return "", err
+	}
+	buf := make([]uint16, 100)
+	n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
+	if err != nil {
+		return "", err
+	}
+	if n > uint32(len(buf)) {
+		// Windows is asking for bigger buffer.
+		buf = make([]uint16, n)
+		n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
+		if err != nil {
+			return "", err
+		}
+		if n > uint32(len(buf)) {
+			return "", EINVAL
+		}
+	}
+	return UTF16ToString(buf[:n]), nil
+}
+
+func isSlash(c uint8) bool {
+	return c == '\\' || c == '/'
+}
+
+func normalizeDir(dir string) (name string, err error) {
+	ndir, err := getFullPath(dir)
+	if err != nil {
+		return "", err
+	}
+	if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) {
+		// dir cannot have \\server\share\path form
+		return "", EINVAL
+	}
+	return ndir, nil
+}
+
+func volToUpper(ch int) int {
+	if 'a' <= ch && ch <= 'z' {
+		ch += 'A' - 'a'
+	}
+	return ch
+}
+
+func joinExeDirAndFName(dir, p string) (name string, err error) {
+	if len(p) == 0 {
+		return "", EINVAL
+	}
+	if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) {
+		// \\server\share\path form
+		return p, nil
+	}
+	if len(p) > 1 && p[1] == ':' {
+		// has drive letter
+		if len(p) == 2 {
+			return "", EINVAL
+		}
+		if isSlash(p[2]) {
+			return p, nil
+		} else {
+			d, err := normalizeDir(dir)
+			if err != nil {
+				return "", err
+			}
+			if volToUpper(int(p[0])) == volToUpper(int(d[0])) {
+				return getFullPath(d + "\\" + p[2:])
+			} else {
+				return getFullPath(p)
+			}
+		}
+	} else {
+		// no drive letter
+		d, err := normalizeDir(dir)
+		if err != nil {
+			return "", err
+		}
+		if isSlash(p[0]) {
+			return getFullPath(d[:2] + p)
+		} else {
+			return getFullPath(d + "\\" + p)
+		}
+	}
+	// we shouldn't be here
+	return "", EINVAL
+}
+
+type ProcAttr struct {
+	Dir   string
+	Env   []string
+	Files []uintptr
+	Sys   *SysProcAttr
+}
+
+type SysProcAttr struct {
+	HideWindow    bool
+	CmdLine       string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
+	CreationFlags uint32
+}
+
+var zeroProcAttr ProcAttr
+var zeroSysProcAttr SysProcAttr
+
+func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
+	if len(argv0) == 0 {
+		return 0, 0, EWINDOWS
+	}
+	if attr == nil {
+		attr = &zeroProcAttr
+	}
+	sys := attr.Sys
+	if sys == nil {
+		sys = &zeroSysProcAttr
+	}
+
+	if len(attr.Files) > 3 {
+		return 0, 0, EWINDOWS
+	}
+
+	if len(attr.Dir) != 0 {
+		// StartProcess assumes that argv0 is relative to attr.Dir,
+		// because it implies Chdir(attr.Dir) before executing argv0.
+		// Windows CreateProcess assumes the opposite: it looks for
+		// argv0 relative to the current directory, and, only once the new
+		// process is started, it does Chdir(attr.Dir). We are adjusting
+		// for that difference here by making argv0 absolute.
+		var err error
+		argv0, err = joinExeDirAndFName(attr.Dir, argv0)
+		if err != nil {
+			return 0, 0, err
+		}
+	}
+	argv0p, err := UTF16PtrFromString(argv0)
+	if err != nil {
+		return 0, 0, err
+	}
+
+	var cmdline string
+	// Windows CreateProcess takes the command line as a single string:
+	// use attr.CmdLine if set, else build the command line by escaping
+	// and joining each argument with spaces
+	if sys.CmdLine != "" {
+		cmdline = sys.CmdLine
+	} else {
+		cmdline = makeCmdLine(argv)
+	}
+
+	var argvp *uint16
+	if len(cmdline) != 0 {
+		argvp, err = UTF16PtrFromString(cmdline)
+		if err != nil {
+			return 0, 0, err
+		}
+	}
+
+	var dirp *uint16
+	if len(attr.Dir) != 0 {
+		dirp, err = UTF16PtrFromString(attr.Dir)
+		if err != nil {
+			return 0, 0, err
+		}
+	}
+
+	// Acquire the fork lock so that no other threads
+	// create new fds that are not yet close-on-exec
+	// before we fork.
+	ForkLock.Lock()
+	defer ForkLock.Unlock()
+
+	p, _ := GetCurrentProcess()
+	fd := make([]Handle, len(attr.Files))
+	for i := range attr.Files {
+		if attr.Files[i] > 0 {
+			err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
+			if err != nil {
+				return 0, 0, err
+			}
+			defer CloseHandle(Handle(fd[i]))
+		}
+	}
+	si := new(StartupInfo)
+	si.Cb = uint32(unsafe.Sizeof(*si))
+	si.Flags = STARTF_USESTDHANDLES
+	if sys.HideWindow {
+		si.Flags |= STARTF_USESHOWWINDOW
+		si.ShowWindow = SW_HIDE
+	}
+	si.StdInput = fd[0]
+	si.StdOutput = fd[1]
+	si.StdErr = fd[2]
+
+	pi := new(ProcessInformation)
+
+	flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT
+	err = CreateProcess(argv0p, argvp, nil, nil, true, flags, createEnvBlock(attr.Env), dirp, si, pi)
+	if err != nil {
+		return 0, 0, err
+	}
+	defer CloseHandle(Handle(pi.Thread))
+
+	return int(pi.ProcessId), uintptr(pi.Process), nil
+}
+
+func Exec(argv0 string, argv []string, envv []string) (err error) {
+	return EWINDOWS
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_irix.go b/third_party/gofrontend/libgo/go/syscall/libcall_irix.go
new file mode 100644
index 0000000..50863fa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_irix.go
@@ -0,0 +1,8 @@
+// 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.
+
+package syscall
+
+//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno)
+//ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_linux.go b/third_party/gofrontend/libgo/go/syscall/libcall_linux.go
new file mode 100644
index 0000000..d5bedd0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_linux.go
@@ -0,0 +1,415 @@
+// 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.
+
+// GNU/Linux library calls.
+
+package syscall
+
+import "unsafe"
+
+//sys	Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
+//__go_openat(dirfd _C_int, path *byte, flags _C_int, mode Mode_t) _C_int
+
+//sys	futimesat(dirfd int, path *byte, times *[2]Timeval) (err error)
+//futimesat(dirfd _C_int, path *byte, times *[2]Timeval) _C_int
+func Futimesat(dirfd int, path string, tv []Timeval) (err error) {
+	if len(tv) != 2 {
+		return EINVAL
+	}
+	return futimesat(dirfd, StringBytePtr(path), (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
+
+func Futimes(fd int, tv []Timeval) (err error) {
+	// Believe it or not, this is the best we can do on GNU/Linux
+	// (and is what glibc does).
+	return Utimes("/proc/self/fd/"+itoa(fd), tv)
+}
+
+//sys	ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
+//ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
+
+//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno)
+//ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
+
+func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) {
+	// The peek requests are machine-size oriented, so we wrap it
+	// to retrieve arbitrary-length data.
+
+	// The ptrace syscall differs from glibc's ptrace.
+	// Peeks returns the word in *data, not as the return value.
+
+	var buf [sizeofPtr]byte
+
+	// Leading edge.  PEEKTEXT/PEEKDATA don't require aligned
+	// access (PEEKUSER warns that it might), but if we don't
+	// align our reads, we might straddle an unmapped page
+	// boundary and not get the bytes leading up to the page
+	// boundary.
+	n := 0
+	if addr%sizeofPtr != 0 {
+		err = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
+		if err != nil {
+			return 0, err
+		}
+		n += copy(out, buf[addr%sizeofPtr:])
+		out = out[n:]
+	}
+
+	// Remainder.
+	for len(out) > 0 {
+		// We use an internal buffer to gaurantee alignment.
+		// It's not documented if this is necessary, but we're paranoid.
+		err = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
+		if err != nil {
+			return n, err
+		}
+		copied := copy(out, buf[0:])
+		n += copied
+		out = out[copied:]
+	}
+
+	return n, nil
+}
+
+func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) {
+	return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out)
+}
+
+func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
+	return ptracePeek(PTRACE_PEEKDATA, pid, addr, out)
+}
+
+func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, err error) {
+	// As for ptracePeek, we need to align our accesses to deal
+	// with the possibility of straddling an invalid page.
+
+	// Leading edge.
+	n := 0
+	if addr%sizeofPtr != 0 {
+		var buf [sizeofPtr]byte
+		err = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
+		if err != nil {
+			return 0, err
+		}
+		n += copy(buf[addr%sizeofPtr:], data)
+		word := *((*uintptr)(unsafe.Pointer(&buf[0])))
+		err = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
+		if err != nil {
+			return 0, err
+		}
+		data = data[n:]
+	}
+
+	// Interior.
+	for len(data) > int(sizeofPtr) {
+		word := *((*uintptr)(unsafe.Pointer(&data[0])))
+		err = ptrace(pokeReq, pid, addr+uintptr(n), word)
+		if err != nil {
+			return n, err
+		}
+		n += int(sizeofPtr)
+		data = data[sizeofPtr:]
+	}
+
+	// Trailing edge.
+	if len(data) > 0 {
+		var buf [sizeofPtr]byte
+		err = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
+		if err != nil {
+			return n, err
+		}
+		copy(buf[0:], data)
+		word := *((*uintptr)(unsafe.Pointer(&buf[0])))
+		err = ptrace(pokeReq, pid, addr+uintptr(n), word)
+		if err != nil {
+			return n, err
+		}
+		n += len(data)
+	}
+
+	return n, nil
+}
+
+func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
+	return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data)
+}
+
+func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
+	return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
+}
+
+func PtraceSetOptions(pid int, options int) (err error) {
+	return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options))
+}
+
+func PtraceGetEventMsg(pid int) (msg uint, err error) {
+	var data _C_long
+	err = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
+	msg = uint(data)
+	return
+}
+
+func PtraceCont(pid int, signal int) (err error) {
+	return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
+}
+
+func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
+
+func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
+
+func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
+
+//sys	reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error)
+//reboot(magic1 _C_uint, magic2 _C_uint, cmd _C_int, arg *byte) _C_int
+func Reboot(cmd int) (err error) {
+	return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
+}
+
+//sys	accept4(fd int, sa *RawSockaddrAny, len *Socklen_t, flags int) (nfd int, err error)
+//accept4(fd _C_int, sa *RawSockaddrAny, len *Socklen_t, flags _C_int) _C_int
+
+func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
+	var rsa RawSockaddrAny
+	var len Socklen_t = SizeofSockaddrAny
+	nfd, err = accept4(fd, &rsa, &len, flags)
+	if err != nil {
+		return -1, nil, err
+	}
+	sa, err = anyToSockaddr(&rsa)
+	if err != nil {
+		Close(nfd)
+		return -1, nil, err
+	}
+	return nfd, sa, nil
+}
+
+//sys	Acct(path string) (err error)
+//acct(path *byte) _C_int
+
+//sys	Adjtimex(buf *Timex) (state int, err error)
+//adjtimex(buf *Timex) _C_int
+
+//sysnb	Dup3(oldfd int, newfd int, flags int) (err error)
+//dup3(oldfd _C_int, newfd _C_int, flags _C_int) _C_int
+
+//sys	Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
+//faccessat(dirfd _C_int, pathname *byte, mode _C_int, flags _C_int) _C_int
+
+//sys	Fallocate(fd int, mode uint32, off int64, len int64) (err error)
+//fallocate(fd _C_int, mode _C_int, offset Offset_t, len Offset_t) _C_int
+
+//sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
+//fchmodat(dirfd _C_int, pathname *byte, mode Mode_t, flags _C_int) _C_int
+
+//sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
+//fchownat(dirfd _C_int, path *byte, owner Uid_t, group Gid_t, flags _C_int) _C_int
+
+//sys	Flock(fd int, how int) (err error)
+//flock(fd _C_int, how _C_int) _C_int
+
+//sys	Fstatfs(fd int, buf *Statfs_t) (err error)
+//fstatfs(fd _C_int, buf *Statfs_t) _C_int
+
+func Gettid() (tid int) {
+	r1, _, _ := Syscall(SYS_GETTID, 0, 0, 0)
+	return int(r1)
+}
+
+func Getdents(fd int, buf []byte) (n int, err error) {
+	var p *byte
+	if len(buf) > 0 {
+		p = &buf[0]
+	} else {
+		p = (*byte)(unsafe.Pointer(&_zero))
+	}
+	Entersyscall()
+	s := SYS_GETDENTS64
+	if s == 0 {
+		s = SYS_GETDENTS
+	}
+	r1, _, errno := Syscall(uintptr(s), uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(len(buf)))
+	n = int(r1)
+	if n < 0 {
+		err = errno
+	}
+	Exitsyscall()
+	return
+}
+
+func clen(n []byte) int {
+	for i := 0; i < len(n); i++ {
+		if n[i] == 0 {
+			return i
+		}
+	}
+	return len(n)
+}
+
+func ReadDirent(fd int, buf []byte) (n int, err error) {
+	return Getdents(fd, buf)
+}
+
+func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
+	origlen := len(buf)
+	count = 0
+	for max != 0 && len(buf) > 0 {
+		dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
+		buf = buf[dirent.Reclen:]
+		if dirent.Ino == 0 { // File absent in directory.
+			continue
+		}
+		bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
+		var name = string(bytes[0:clen(bytes[:])])
+		if name == "." || name == ".." { // Useless names
+			continue
+		}
+		max--
+		count++
+		names = append(names, name)
+	}
+	return origlen - len(buf), count, names
+}
+
+//sys	Getxattr(path string, attr string, dest []byte) (sz int, err error)
+//getxattr(path *byte, attr *byte, buf *byte, count Size_t) Ssize_t
+
+//sys	InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error)
+//inotify_add_watch(fd _C_int, pathname *byte, mask uint32) _C_int
+
+//sysnb	InotifyInit() (fd int, err error)
+//inotify_init() _C_int
+
+//sysnb	InotifyInit1(flags int) (fd int, err error)
+//inotify_init1(flags _C_int) _C_int
+
+//sysnb	InotifyRmWatch(fd int, watchdesc uint32) (success int, err error)
+//inotify_rm_watch(fd _C_int, wd uint32) _C_int
+
+//sys	Klogctl(typ int, buf []byte) (n int, err error)
+//klogctl(typ _C_int, bufp *byte, len _C_int) _C_int
+
+//sys	Listxattr(path string, dest []byte) (sz int, err error)
+//listxattr(path *byte, list *byte, size Size_t) Ssize_t
+
+//sys	Mkdirat(dirfd int, path string, mode uint32) (err error)
+//mkdirat(dirfd _C_int, path *byte, mode Mode_t) _C_int
+
+//sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
+//mknodat(dirfd _C_int, path *byte, mode Mode_t, dev _dev_t) _C_int
+
+//sysnb	pipe2(p *[2]_C_int, flags int) (err error)
+//pipe2(p *[2]_C_int, flags _C_int) _C_int
+func Pipe2(p []int, flags int) (err error) {
+	if len(p) != 2 {
+		return EINVAL
+	}
+	var pp [2]_C_int
+	err = pipe2(&pp, flags)
+	p[0] = int(pp[0])
+	p[1] = int(pp[1])
+	return
+}
+
+//sys	PivotRoot(newroot string, putold string) (err error)
+//pivot_root(newroot *byte, putold *byte) _C_int
+
+//sys	Removexattr(path string, attr string) (err error)
+//removexattr(path *byte, name *byte) _C_int
+
+//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
+//renameat(olddirfd _C_int, oldpath *byte, newdirfd _C_int, newpath *byte) _C_int
+
+//sys	sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, err error)
+//sendfile64(outfd _C_int, infd _C_int, offset *Offset_t, count Size_t) Ssize_t
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	if raceenabled {
+		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	}
+	var soff Offset_t
+	var psoff *Offset_t
+	if offset != nil {
+		psoff = &soff
+	}
+	written, err = sendfile(outfd, infd, psoff, count)
+	if offset != nil {
+		*offset = int64(soff)
+	}
+	return
+}
+
+//sys	Setfsgid(gid int) (err error)
+//setfsgid(gid Gid_t) _C_int
+
+//sys	Setfsuid(uid int) (err error)
+//setfsuid(uid Uid_t) _C_int
+
+//sysnb	Setresgid(rgid int, egid int, sgid int) (err error)
+//setresgid(rgid Gid_t, egid Gid_t, sgid Gid_t) _C_int
+
+//sysnb	Setresuid(ruid int, eguid int, suid int) (err error)
+//setresuid(ruid Uid_t, euid Uid_t, suid Uid_t) _C_int
+
+//sys	Setxattr(path string, attr string, data []byte, flags int) (err error)
+//setxattr(path *byte, name *byte, value *byte, size Size_t, flags _C_int) _C_int
+
+//sys	splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, err error)
+//splice(rfd _C_int, roff *_loff_t, wfd _C_int, woff *_loff_t, len Size_t, flags _C_uint) Ssize_t
+func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
+	var lroff _loff_t
+	var plroff *_loff_t
+	if roff != nil {
+		lroff = _loff_t(*roff)
+		plroff = &lroff
+	}
+	var lwoff _loff_t
+	var plwoff *_loff_t
+	if woff != nil {
+		lwoff = _loff_t(*woff)
+		plwoff = &lwoff
+	}
+	n, err = splice(rfd, plroff, wfd, plwoff, len, flags)
+	if roff != nil {
+		*roff = int64(lroff)
+	}
+	if woff != nil {
+		*woff = int64(lwoff)
+	}
+	return
+}
+
+//sys	Statfs(path string, buf *Statfs_t) (err error)
+//statfs(path *byte, buf *Statfs_t) _C_int
+
+//sys	SyncFileRange(fd int, off int64, n int64, flags int) (err error)
+//sync_file_range(fd _C_int, off Offset_t, n Offset_t, flags _C_uint) _C_int
+
+//sysnb	Sysinfo(info *Sysinfo_t) (err error)
+//sysinfo(info *Sysinfo_t) _C_int
+
+//sys	Tee(rfd int, wfd int, len int, flags int) (n int64, err error)
+//tee(rfd _C_int, wfd _C_int, len Size_t, flags _C_uint) Ssize_t
+
+func Tgkill(tgid int, tid int, sig Signal) error {
+	r1, _, errno := Syscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
+	if r1 < 0 {
+		return errno
+	}
+	return nil
+}
+
+//sys	unlinkat(dirfd int, path string, flags int) (err error)
+//unlinkat(dirfd _C_int, path *byte, flags _C_int) _C_int
+
+func Unlinkat(dirfd int, path string) (err error) {
+	return unlinkat(dirfd, path, 0)
+}
+
+//sys	Unmount(target string, flags int) (err error) = SYS_UMOUNT2
+//umount2(target *byte, flags _C_int) _C_int
+
+//sys	Unshare(flags int) (err error)
+//unshare(flags _C_int) _C_int
+
+//sys	Ustat(dev int, ubuf *Ustat_t) (err error)
+//ustat(dev _dev_t, ubuf *Ustat_t) _C_int
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_linux_386.go b/third_party/gofrontend/libgo/go/syscall/libcall_linux_386.go
new file mode 100644
index 0000000..bdf0fda
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_linux_386.go
@@ -0,0 +1,13 @@
+// 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.
+
+// GNU/Linux library calls 386 specific.
+
+package syscall
+
+//sys	Ioperm(from int, num int, on int) (err error)
+//ioperm(from _C_long, num _C_long, on _C_int) _C_int
+
+//sys	Iopl(level int) (err error)
+//iopl(level _C_int) _C_int
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_linux_alpha.go b/third_party/gofrontend/libgo/go/syscall/libcall_linux_alpha.go
new file mode 100644
index 0000000..13ccf05
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_linux_alpha.go
@@ -0,0 +1,13 @@
+// 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.
+
+// GNU/Linux library calls Alpha specific.
+
+package syscall
+
+//sys	Ioperm(from int, num int, on int) (err error)
+//ioperm(from _C_long, num _C_long, on _C_int) _C_int
+
+//sys	Iopl(level int) (err error)
+//iopl(level _C_int) _C_int
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_linux_amd64.go b/third_party/gofrontend/libgo/go/syscall/libcall_linux_amd64.go
new file mode 100644
index 0000000..675de3d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_linux_amd64.go
@@ -0,0 +1,13 @@
+// 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.
+
+// GNU/Linux library calls amd64 specific.
+
+package syscall
+
+//sys	Ioperm(from int, num int, on int) (err error)
+//ioperm(from _C_long, num _C_long, on _C_int) _C_int
+
+//sys	Iopl(level int) (err error)
+//iopl(level _C_int) _C_int
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_linux_s390.go b/third_party/gofrontend/libgo/go/syscall/libcall_linux_s390.go
new file mode 100644
index 0000000..c5f3b30
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_linux_s390.go
@@ -0,0 +1,7 @@
+// Copyright 2014 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.
+
+// GNU/Linux library calls s390 specific.
+
+package syscall
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_linux_s390x.go b/third_party/gofrontend/libgo/go/syscall/libcall_linux_s390x.go
new file mode 100644
index 0000000..c5f3b30
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_linux_s390x.go
@@ -0,0 +1,7 @@
+// Copyright 2014 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.
+
+// GNU/Linux library calls s390 specific.
+
+package syscall
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_linux_utimesnano.go b/third_party/gofrontend/libgo/go/syscall/libcall_linux_utimesnano.go
new file mode 100644
index 0000000..90da2ae
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_linux_utimesnano.go
@@ -0,0 +1,29 @@
+// 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.
+
+// GNU/Linux version of UtimesNano.
+
+package syscall
+
+import "unsafe"
+
+//sys	utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)
+//utimensat(dirfd _C_int, path *byte, times *[2]Timespec, flags _C_int) _C_int
+func UtimesNano(path string, ts []Timespec) (err error) {
+	if len(ts) != 2 {
+		return EINVAL
+	}
+	err = utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
+	if err != ENOSYS {
+		return err
+	}
+	// If the utimensat syscall isn't available (utimensat was added to Linux
+	// in 2.6.22, Released, 8 July 2007) then fall back to utimes
+	var tv [2]Timeval
+	for i := 0; i < 2; i++ {
+		tv[i].Sec = Timeval_sec_t(ts[i].Sec)
+		tv[i].Usec = Timeval_usec_t(ts[i].Nsec / 1000)
+	}
+	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_posix.go b/third_party/gofrontend/libgo/go/syscall/libcall_posix.go
new file mode 100644
index 0000000..d3580a1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_posix.go
@@ -0,0 +1,401 @@
+// 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.
+
+// POSIX library calls.
+// This file is compiled as ordinary Go code,
+// but it is also input to mksyscall,
+// which parses the //sys lines and generates library call stubs.
+// Note that sometimes we use a lowercase //sys name and
+// wrap it in our own nicer implementation.
+
+package syscall
+
+import "unsafe"
+
+/*
+ * Wrapped
+ */
+
+//sysnb	pipe(p *[2]_C_int) (err error)
+//pipe(p *[2]_C_int) _C_int
+func Pipe(p []int) (err error) {
+	if len(p) != 2 {
+		return EINVAL
+	}
+	var pp [2]_C_int
+	err = pipe(&pp)
+	p[0] = int(pp[0])
+	p[1] = int(pp[1])
+	return
+}
+
+//sys	utimes(path string, times *[2]Timeval) (err error)
+//utimes(path *byte, times *[2]Timeval) _C_int
+func Utimes(path string, tv []Timeval) (err error) {
+	if len(tv) != 2 {
+		return EINVAL
+	}
+	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
+
+//sys	getcwd(buf *byte, size Size_t) (err error)
+//getcwd(buf *byte, size Size_t) *byte
+
+const ImplementsGetwd = true
+
+func Getwd() (ret string, err error) {
+	for len := Size_t(4096); ; len *= 2 {
+		b := make([]byte, len)
+		err := getcwd(&b[0], len)
+		if err == nil {
+			i := 0
+			for b[i] != 0 {
+				i++
+			}
+			return string(b[0:i]), nil
+		}
+		if err != ERANGE {
+			return "", err
+		}
+	}
+}
+
+func Getcwd(buf []byte) (n int, err error) {
+	err = getcwd(&buf[0], Size_t(len(buf)))
+	if err == nil {
+		i := 0
+		for buf[i] != 0 {
+			i++
+		}
+		n = i + 1
+	}
+	return
+}
+
+//sysnb	getgroups(size int, list *Gid_t) (nn int, err error)
+//getgroups(size _C_int, list *Gid_t) _C_int
+
+func Getgroups() (gids []int, err error) {
+	n, err := getgroups(0, nil)
+	if err != nil {
+		return nil, err
+	}
+	if n == 0 {
+		return nil, nil
+	}
+
+	// Sanity check group count.  Max is 1<<16 on GNU/Linux.
+	if n < 0 || n > 1<<20 {
+		return nil, EINVAL
+	}
+
+	a := make([]Gid_t, n)
+	n, err = getgroups(n, &a[0])
+	if err != nil {
+		return nil, err
+	}
+	gids = make([]int, n)
+	for i, v := range a[0:n] {
+		gids[i] = int(v)
+	}
+	return
+}
+
+//sysnb	setgroups(n int, list *Gid_t) (err error)
+//setgroups(n Size_t, list *Gid_t) _C_int
+
+func Setgroups(gids []int) (err error) {
+	if len(gids) == 0 {
+		return setgroups(0, nil)
+	}
+
+	a := make([]Gid_t, len(gids))
+	for i, v := range gids {
+		a[i] = Gid_t(v)
+	}
+	return setgroups(len(a), &a[0])
+}
+
+type WaitStatus uint32
+
+// The WaitStatus methods are implemented in C, to pick up the macros
+// #defines in <sys/wait.h>.
+
+func (w WaitStatus) Exited() bool
+func (w WaitStatus) Signaled() bool
+func (w WaitStatus) Stopped() bool
+func (w WaitStatus) Continued() bool
+func (w WaitStatus) CoreDump() bool
+func (w WaitStatus) ExitStatus() int
+func (w WaitStatus) Signal() Signal
+func (w WaitStatus) StopSignal() Signal
+func (w WaitStatus) TrapCause() int
+
+//sys	Mkfifo(path string, mode uint32) (err error)
+//mkfifo(path *byte, mode Mode_t) _C_int
+
+//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
+//select(nfd _C_int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) _C_int
+
+const nfdbits = int(unsafe.Sizeof(fds_bits_type(0)) * 8)
+
+type FdSet struct {
+	Bits [(FD_SETSIZE + nfdbits - 1) / nfdbits]fds_bits_type
+}
+
+func FDSet(fd int, set *FdSet) {
+	set.Bits[fd/nfdbits] |= (1 << (uint)(fd%nfdbits))
+}
+
+func FDClr(fd int, set *FdSet) {
+	set.Bits[fd/nfdbits] &^= (1 << (uint)(fd%nfdbits))
+}
+
+func FDIsSet(fd int, set *FdSet) bool {
+	if set.Bits[fd/nfdbits]&(1<<(uint)(fd%nfdbits)) != 0 {
+		return true
+	} else {
+		return false
+	}
+}
+
+func FDZero(set *FdSet) {
+	for i := range set.Bits {
+		set.Bits[i] = 0
+	}
+}
+
+//sys	Access(path string, mode uint32) (err error)
+//access(path *byte, mode _C_int) _C_int
+
+//sys	Chdir(path string) (err error)
+//chdir(path *byte) _C_int
+
+//sys	Chmod(path string, mode uint32) (err error)
+//chmod(path *byte, mode Mode_t) _C_int
+
+//sys	Chown(path string, uid int, gid int) (err error)
+//chown(path *byte, uid Uid_t, gid Gid_t) _C_int
+
+//sys	Chroot(path string) (err error)
+//chroot(path *byte) _C_int
+
+//sys	Close(fd int) (err error)
+//close(fd _C_int) _C_int
+
+//sys	Creat(path string, mode uint32) (fd int, err error)
+//creat(path *byte, mode Mode_t) _C_int
+
+//sysnb	Dup(oldfd int) (fd int, err error)
+//dup(oldfd _C_int) _C_int
+
+//sysnb	Dup2(oldfd int, newfd int) (err error)
+//dup2(oldfd _C_int, newfd _C_int) _C_int
+
+//sys	Exit(code int)
+//exit(code _C_int)
+
+//sys	Fchdir(fd int) (err error)
+//fchdir(fd _C_int) _C_int
+
+//sys	Fchmod(fd int, mode uint32) (err error)
+//fchmod(fd _C_int, mode Mode_t) _C_int
+
+//sys	Fchown(fd int, uid int, gid int) (err error)
+//fchown(fd _C_int, uid Uid_t, gid Gid_t) _C_int
+
+//sys	fcntl(fd int, cmd int, arg int) (val int, err error)
+//__go_fcntl(fd _C_int, cmd _C_int, arg _C_int) _C_int
+
+//sys	FcntlFlock(fd uintptr, cmd int, lk *Flock_t) (err error)
+//__go_fcntl_flock(fd _C_int, cmd _C_int, arg *Flock_t) _C_int
+
+//sys	Fdatasync(fd int) (err error)
+//fdatasync(fd _C_int) _C_int
+
+//sys	Fsync(fd int) (err error)
+//fsync(fd _C_int) _C_int
+
+//sysnb Getegid() (egid int)
+//getegid() Gid_t
+
+//sysnb Geteuid() (euid int)
+//geteuid() Uid_t
+
+//sysnb Getgid() (gid int)
+//getgid() Gid_t
+
+//sysnb	Getpagesize() (pagesize int)
+//getpagesize() _C_int
+
+//sysnb	Getpgid(pid int) (pgid int, err error)
+//getpgid(pid Pid_t) Pid_t
+
+//sysnb	Getpgrp() (pid int)
+//getpgrp() Pid_t
+
+//sysnb	Getpid() (pid int)
+//getpid() Pid_t
+
+//sysnb	Getppid() (ppid int)
+//getppid() Pid_t
+
+//sys Getpriority(which int, who int) (prio int, err error)
+//getpriority(which _C_int, who _C_int) _C_int
+
+//sysnb	Getrusage(who int, rusage *Rusage) (err error)
+//getrusage(who _C_int, rusage *Rusage) _C_int
+
+//sysnb	gettimeofday(tv *Timeval, tz *byte) (err error)
+//gettimeofday(tv *Timeval, tz *byte) _C_int
+func Gettimeofday(tv *Timeval) (err error) {
+	return gettimeofday(tv, nil)
+}
+
+//sysnb Getuid() (uid int)
+//getuid() Uid_t
+
+//sysnb	Kill(pid int, sig Signal) (err error)
+//kill(pid Pid_t, sig _C_int) _C_int
+
+//sys	Lchown(path string, uid int, gid int) (err error)
+//lchown(path *byte, uid Uid_t, gid Gid_t) _C_int
+
+//sys	Link(oldpath string, newpath string) (err error)
+//link(oldpath *byte, newpath *byte) _C_int
+
+//sys	Mkdir(path string, mode uint32) (err error)
+//mkdir(path *byte, mode Mode_t) _C_int
+
+//sys	Mknod(path string, mode uint32, dev int) (err error)
+//mknod(path *byte, mode Mode_t, dev _dev_t) _C_int
+
+//sys	Mount(source string, target string, fstype string, flags uintptr, data string) (err error)
+//mount(source *byte, target *byte, fstype *byte, flags _C_long, data *byte) _C_int
+
+//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
+//nanosleep(time *Timespec, leftover *Timespec) _C_int
+
+//sys	Pause() (err error)
+//pause() _C_int
+
+//sys	read(fd int, p []byte) (n int, err error)
+//read(fd _C_int, buf *byte, count Size_t) Ssize_t
+
+//sys	readlen(fd int, p *byte, np int) (n int, err error)
+//read(fd _C_int, buf *byte, count Size_t) Ssize_t
+
+//sys	Readlink(path string, buf []byte) (n int, err error)
+//readlink(path *byte, buf *byte, bufsiz Size_t) Ssize_t
+
+//sys	Rename(oldpath string, newpath string) (err error)
+//rename(oldpath *byte, newpath *byte) _C_int
+
+//sys	Rmdir(path string) (err error)
+//rmdir(path *byte) _C_int
+
+//sys	Setdomainname(p []byte) (err error)
+//setdomainname(name *byte, len Size_t) _C_int
+
+//sys	Sethostname(p []byte) (err error)
+//sethostname(name *byte, len Size_t) _C_int
+
+//sysnb	Setgid(gid int) (err error)
+//setgid(gid Gid_t) _C_int
+
+//sysnb Setregid(rgid int, egid int) (err error)
+//setregid(rgid Gid_t, egid Gid_t) _C_int
+
+//sysnb	Setpgid(pid int, pgid int) (err error)
+//setpgid(pid Pid_t, pgid Pid_t) _C_int
+
+//sys Setpriority(which int, who int, prio int) (err error)
+//setpriority(which _C_int, who _C_int, prio _C_int) _C_int
+
+//sysnb	Setreuid(ruid int, euid int) (err error)
+//setreuid(ruid Uid_t, euid Uid_t) _C_int
+
+//sysnb	Setsid() (pid int, err error)
+//setsid() Pid_t
+
+//sysnb	settimeofday(tv *Timeval, tz *byte) (err error)
+//settimeofday(tv *Timeval, tz *byte) _C_int
+
+func Settimeofday(tv *Timeval) (err error) {
+	return settimeofday(tv, nil)
+}
+
+//sysnb	Setuid(uid int) (err error)
+//setuid(uid Uid_t) _C_int
+
+//sys	Symlink(oldpath string, newpath string) (err error)
+//symlink(oldpath *byte, newpath *byte) _C_int
+
+//sys	Sync()
+//sync()
+
+//sysnb	Time(t *Time_t) (tt Time_t, err error)
+//time(t *Time_t) Time_t
+
+//sysnb	Times(tms *Tms) (ticks uintptr, err error)
+//times(tms *Tms) _clock_t
+
+//sysnb	Umask(mask int) (oldmask int)
+//umask(mask Mode_t) Mode_t
+
+//sys	Unlink(path string) (err error)
+//unlink(path *byte) _C_int
+
+//sys	Utime(path string, buf *Utimbuf) (err error)
+//utime(path *byte, buf *Utimbuf) _C_int
+
+//sys	write(fd int, p []byte) (n int, err error)
+//write(fd _C_int, buf *byte, count Size_t) Ssize_t
+
+//sys	writelen(fd int, p *byte, np int) (n int, err error)
+//write(fd _C_int, buf *byte, count Size_t) Ssize_t
+
+//sys	munmap(addr uintptr, length uintptr) (err error)
+//munmap(addr *byte, length Size_t) _C_int
+
+//sys Madvise(b []byte, advice int) (err error)
+//madvise(addr *byte, len Size_t, advice _C_int) _C_int
+
+//sys	Mprotect(b []byte, prot int) (err error)
+//mprotect(addr *byte, len Size_t, prot _C_int) _C_int
+
+//sys	Mlock(b []byte) (err error)
+//mlock(addr *byte, len Size_t) _C_int
+
+//sys	Munlock(b []byte) (err error)
+//munlock(addr *byte, len Size_t) _C_int
+
+//sys	Mlockall(flags int) (err error)
+//mlockall(flags _C_int) _C_int
+
+//sys	Munlockall() (err error)
+//munlockall() _C_int
+
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+	ts.Sec = Timespec_sec_t(nsec / 1e9)
+	ts.Nsec = Timespec_nsec_t(nsec % 1e9)
+	return
+}
+
+func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+	nsec += 999 // round up to microsecond
+	tv.Sec = Timeval_sec_t(nsec / 1e9)
+	tv.Usec = Timeval_usec_t(nsec % 1e9 / 1e3)
+	return
+}
+
+//sysnb	Tcgetattr(fd int, p *Termios) (err error)
+//tcgetattr(fd _C_int, p *Termios) _C_int
+
+//sys	Tcsetattr(fd int, actions int, p *Termios) (err error)
+//tcsetattr(fd _C_int, actions _C_int, p *Termios) _C_int
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_posix_largefile.go b/third_party/gofrontend/libgo/go/syscall/libcall_posix_largefile.go
new file mode 100644
index 0000000..c05d3d2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_posix_largefile.go
@@ -0,0 +1,43 @@
+// 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.
+
+// POSIX library calls on systems which use the largefile interface.
+
+package syscall
+
+//sys	Fstat(fd int, stat *Stat_t) (err error)
+//fstat64(fd _C_int, stat *Stat_t) _C_int
+
+//sys	Ftruncate(fd int, length int64) (err error)
+//ftruncate64(fd _C_int, length Offset_t) _C_int
+
+//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error)
+//getrlimit64(resource _C_int, rlim *Rlimit) _C_int
+
+//sys	Lstat(path string, stat *Stat_t) (err error)
+//lstat64(path *byte, stat *Stat_t) _C_int
+
+//sys	mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
+//mmap64(addr *byte, length Size_t, prot _C_int, flags _C_int, fd _C_int, offset Offset_t) *byte
+
+//sys	Open(path string, mode int, perm uint32) (fd int, err error)
+//__go_open64(path *byte, mode _C_int, perm Mode_t) _C_int
+
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
+//pread64(fd _C_int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//pwrite64(fd _C_int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys	Seek(fd int, offset int64, whence int) (off int64, err error)
+//lseek64(fd _C_int, offset Offset_t, whence _C_int) Offset_t
+
+//sysnb	Setrlimit(resource int, rlim *Rlimit) (err error)
+//setrlimit64(resource int, rlim *Rlimit) _C_int
+
+//sys	Stat(path string, stat *Stat_t) (err error)
+//stat64(path *byte, stat *Stat_t) _C_int
+
+//sys	Truncate(path string, length int64) (err error)
+//truncate64(path *byte, length Offset_t) _C_int
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_posix_regfile.go b/third_party/gofrontend/libgo/go/syscall/libcall_posix_regfile.go
new file mode 100644
index 0000000..7de5800
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_posix_regfile.go
@@ -0,0 +1,44 @@
+// 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.
+
+// POSIX library calls on systems which do not use the largefile
+// interface.
+
+package syscall
+
+//sys	Fstat(fd int, stat *Stat_t) (err error)
+//fstat(fd _C_int, stat *Stat_t) _C_int
+
+//sys	Ftruncate(fd int, length int64) (err error)
+//ftruncate(fd _C_int, length Offset_t) _C_int
+
+//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error)
+//getrlimit(resource _C_int, rlim *Rlimit) _C_int
+
+//sys	Lstat(path string, stat *Stat_t) (err error)
+//lstat(path *byte, stat *Stat_t) _C_int
+
+//sys	mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
+//mmap(addr *byte, length Size_t, prot _C_int, flags _C_int, fd _C_int, offset Offset_t) *byte
+
+//sys	Open(path string, mode int, perm uint32) (fd int, err error)
+//__go_open(path *byte, mode _C_int, perm Mode_t) _C_int
+
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
+//pread(fd _C_int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//pwrite(fd _C_int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys	Seek(fd int, offset int64, whence int) (off int64, err error)
+//lseek(fd _C_int, offset Offset_t, whence _C_int) Offset_t
+
+//sysnb	Setrlimit(resource int, rlim *Rlimit) (err error)
+//setrlimit(resource int, rlim *Rlimit) _C_int
+
+//sys	Stat(path string, stat *Stat_t) (err error)
+//stat(path *byte, stat *Stat_t) _C_int
+
+//sys	Truncate(path string, length int64) (err error)
+//truncate(path *byte, length Offset_t) _C_int
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_posix_utimesnano.go b/third_party/gofrontend/libgo/go/syscall/libcall_posix_utimesnano.go
new file mode 100644
index 0000000..e0751f5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_posix_utimesnano.go
@@ -0,0 +1,24 @@
+// 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.
+
+// General POSIX version of UtimesNano.
+
+package syscall
+
+import "unsafe"
+
+func UtimesNano(path string, ts []Timespec) error {
+	// TODO: The BSDs can do utimensat with SYS_UTIMENSAT but it
+	// isn't supported by darwin so this uses utimes instead
+	if len(ts) != 2 {
+		return EINVAL
+	}
+	// Not as efficient as it could be because Timespec and
+	// Timeval have different types in the different OSes
+	tv := [2]Timeval{
+		NsecToTimeval(TimespecToNsec(ts[0])),
+		NsecToTimeval(TimespecToNsec(ts[1])),
+	}
+	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_solaris_386.go b/third_party/gofrontend/libgo/go/syscall/libcall_solaris_386.go
new file mode 100644
index 0000000..20eba22
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_solaris_386.go
@@ -0,0 +1,12 @@
+// 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.
+
+package syscall
+
+// 32-bit Solaris 2/x86 needs to use _nuname internally, cf. <sys/utsname.h>.
+//sysnb	Uname(buf *Utsname) (err error)
+//_nuname(buf *Utsname) _C_int
+
+//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno)
+//ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_solaris_amd64.go b/third_party/gofrontend/libgo/go/syscall/libcall_solaris_amd64.go
new file mode 100644
index 0000000..69b11ba
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_solaris_amd64.go
@@ -0,0 +1,10 @@
+// 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.
+
+package syscall
+
+// 64-bit ptrace(3C) doesn't exist
+func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno {
+	return ENOSYS
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_solaris_sparc.go b/third_party/gofrontend/libgo/go/syscall/libcall_solaris_sparc.go
new file mode 100644
index 0000000..50863fa
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_solaris_sparc.go
@@ -0,0 +1,8 @@
+// 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.
+
+package syscall
+
+//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno)
+//ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_solaris_sparc64.go b/third_party/gofrontend/libgo/go/syscall/libcall_solaris_sparc64.go
new file mode 100644
index 0000000..69b11ba
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_solaris_sparc64.go
@@ -0,0 +1,10 @@
+// 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.
+
+package syscall
+
+// 64-bit ptrace(3C) doesn't exist
+func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno {
+	return ENOSYS
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_support.go b/third_party/gofrontend/libgo/go/syscall/libcall_support.go
new file mode 100644
index 0000000..cacc556
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_support.go
@@ -0,0 +1,18 @@
+// 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.
+
+// Declarations for functions which are actually written in C.
+
+package syscall
+
+func Entersyscall()
+func Exitsyscall()
+func GetErrno() Errno
+func SetErrno(Errno)
+
+// These functions are used by CGO and SWIG.
+func Cgocall()
+func CgocallDone()
+func CgocallBack()
+func CgocallBackDone()
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_uname.go b/third_party/gofrontend/libgo/go/syscall/libcall_uname.go
new file mode 100644
index 0000000..1e164ef
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_uname.go
@@ -0,0 +1,8 @@
+// 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.
+
+package syscall
+
+//sysnb	Uname(buf *Utsname) (err error)
+//uname(buf *Utsname) _C_int
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_wait4.go b/third_party/gofrontend/libgo/go/syscall/libcall_wait4.go
new file mode 100644
index 0000000..559d780
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_wait4.go
@@ -0,0 +1,20 @@
+// 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.
+
+// For systems with the wait4 library call.
+
+package syscall
+
+//sys	wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, err error)
+//wait4(pid Pid_t, status *_C_int, options _C_int, rusage *Rusage) Pid_t
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
+	var status _C_int
+	r, err := wait4(Pid_t(pid), &status, options, rusage)
+	wpid = int(r)
+	if wstatus != nil {
+		*wstatus = WaitStatus(status)
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/libcall_waitpid.go b/third_party/gofrontend/libgo/go/syscall/libcall_waitpid.go
new file mode 100644
index 0000000..b0e04b5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/libcall_waitpid.go
@@ -0,0 +1,20 @@
+// 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.
+
+// For systems with the waitpid library call.
+
+package syscall
+
+//sys	waitpid(pid Pid_t, status *_C_int, options int) (wpid Pid_t, err error)
+//waitpid(pid Pid_t, status *_C_int, options _C_int) Pid_t
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
+	var status _C_int
+	r, err := waitpid(Pid_t(pid), &status, options)
+	wpid = int(r)
+	if wstatus != nil {
+		*wstatus = WaitStatus(status)
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/lsf_linux.go b/third_party/gofrontend/libgo/go/syscall/lsf_linux.go
new file mode 100644
index 0000000..48ba191
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/lsf_linux.go
@@ -0,0 +1,78 @@
+// 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.
+
+// Linux socket filter
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+func LsfStmt(code, k int) *SockFilter {
+	return &SockFilter{Code: uint16(code), K: uint32(k)}
+}
+
+func LsfJump(code, k, jt, jf int) *SockFilter {
+	return &SockFilter{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
+}
+
+func LsfSocket(ifindex, proto int) (int, error) {
+	var lsall SockaddrLinklayer
+	s, e := Socket(AF_PACKET, SOCK_RAW, proto)
+	if e != nil {
+		return 0, e
+	}
+	p := (*[2]byte)(unsafe.Pointer(&lsall.Protocol))
+	p[0] = byte(proto >> 8)
+	p[1] = byte(proto)
+	lsall.Ifindex = ifindex
+	e = Bind(s, &lsall)
+	if e != nil {
+		Close(s)
+		return 0, e
+	}
+	return s, nil
+}
+
+type iflags struct {
+	name  [IFNAMSIZ]byte
+	flags uint16
+}
+
+func SetLsfPromisc(name string, m bool) error {
+	s, e := Socket(AF_INET, SOCK_DGRAM, 0)
+	if e != nil {
+		return e
+	}
+	defer Close(s)
+	var ifl iflags
+	copy(ifl.name[:], []byte(name))
+	_, _, ep := Syscall(SYS_IOCTL, uintptr(s), SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
+	if ep != 0 {
+		return Errno(ep)
+	}
+	if m {
+		ifl.flags |= uint16(IFF_PROMISC)
+	} else {
+		ifl.flags &= ^uint16(IFF_PROMISC)
+	}
+	_, _, ep = Syscall(SYS_IOCTL, uintptr(s), SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
+	if ep != 0 {
+		return Errno(ep)
+	}
+	return nil
+}
+
+func AttachLsf(fd int, i []SockFilter) error {
+	var p SockFprog
+	p.Len = uint16(len(i))
+	p.Filter = (*SockFilter)(unsafe.Pointer(&i[0]))
+	return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, unsafe.Pointer(&p), Socklen_t(unsafe.Sizeof(p)))
+}
+
+func DetachLsf(fd int) error {
+	var dummy int
+	return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, unsafe.Pointer(&dummy), Socklen_t(unsafe.Sizeof(dummy)))
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/mksyscall.awk b/third_party/gofrontend/libgo/go/syscall/mksyscall.awk
new file mode 100644
index 0000000..6fbd2ac
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/mksyscall.awk
@@ -0,0 +1,300 @@
+# 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.
+
+# This AWK script reads a Go file with comments describing syscall
+# functions and the C routines they map to.  It generates the Go code
+# which calls the C routines.
+
+# The syscall functins are marked by lines beginning with "//sys" and
+# read like func declarations if //sys is replaced by func, but:
+#	* The parameter lists must give a name for each argument.
+#	  This includes return parameters.
+#	* The parameter lists must give a type for each argument:
+#	   the (x, y, z int) shorthand is not allowed.
+#	* If the return parameter is an error, it must be named err.
+
+# A line beginning with //sysnb is like //sys, except that the
+# goroutine will not be suspended during the execution of the library
+# call.  This must only be used for library calls which can never
+# block, as otherwise the library call could cause all goroutines to
+# hang.
+
+# After the //sys or //sysnb line comes a second line which describes
+# the C function.  The name must be the name of the function in the C
+# library, and may be the same as the Go function.  The limitations on
+# the argument list are the same as for the //sys line, but there must
+# be at most one result parameter, and it must be given as just a
+# type, without a name.
+
+BEGIN {
+    print "// This file was automatically generated by mksyscall.awk"
+    print ""
+    print "package syscall"
+    print ""
+    print "import \"unsafe\""
+    print ""
+    status = 0
+}
+
+/^\/\/sys/ {
+    if ($1 == "//sysnb") {
+	blocking = 0
+    } else {
+	blocking = 1
+    }
+
+    line = $0
+
+    if (match(line, "//sys(nb)?[ 	]*[a-zA-Z0-9_]+\\([^()]*\\) *(\\(([^()]+)\\))?") == 0) {
+	print "unmatched line:", $0 | "cat 1>&2"
+	status = 1
+	next
+    }
+
+    # Sets a[1] = //sysnb, a[2] == function name.
+    split(line, a, "[ 	(]+")
+    gofnname = a[2]
+
+    off = match(line, "\\([^()]*\\)")
+    end = index(substr(line, off, length(line) - off + 1), ")")
+    gofnparams = substr(line, off + 1, end - 2)
+
+    line = substr(line, off + end, length(line) - (off + end) + 1)
+    off = match(line, "\\([^()]*\\)")
+    if (off == 0) {
+	gofnresults = ""
+    } else {
+	end = index(substr(line, off, length(line) - off + 1), ")")
+	gofnresults = substr(line, off + 1, end - 2)
+    }
+
+    getline
+    line = $0
+
+    if (match(line, "//[a-zA-Z0-9_]+\\([^()]*\\)") == 0) {
+	print "unmatched C line", $0, "after", gofnname | "cat 1>&2"
+	status = 1
+	next
+    }
+
+    split(line, a, "[ 	(]+")
+    cfnname = substr(a[1], 3, length(a[1]) - 2)
+
+    off = match(line, "\\([^()]*\\)")
+    end = index(substr(line, off, length(line) - off + 1), ")")
+    cfnparams = substr(line, off + 1, end - 2)
+
+    line = substr(line, off + end + 1, length(line) - (off + end) + 1)
+    while (substr(line, 1, 1) == " ") {
+	line = substr(line, 2, length(line) - 1)
+    }
+    end = index(line, " ")
+    if (end != 0) {
+	line = substr(line, 1, end)
+    }
+    cfnresult = line
+
+    printf("// Automatically generated wrapper for %s/%s\n", gofnname, cfnname)
+    if (!(cfnname in cfns)) {
+        cfns[cfnname] = 1
+        printf("//extern %s\n", cfnname)
+        printf("func c_%s(%s) %s\n", cfnname, cfnparams, cfnresult)
+    }
+    printf("func %s(%s) %s%s%s%s{\n",
+	   gofnname, gofnparams, gofnresults == "" ? "" : "(", gofnresults,
+	   gofnresults == "" ? "" : ")", gofnresults == "" ? "" : " ")
+
+    loc = gofnname "/" cfnname ":"
+
+    haserr = 0
+    if (gofnresults != "") {
+	fields = split(gofnresults, goresults, ", *")
+	for (goresult = 1; goresults[goresult] != ""; goresult++) {
+	    if (split(goresults[goresult], goparam) == 2) {
+		if (goparam[1] == "err") {
+		    haserr = 1
+		    break
+		}
+	    }
+	}
+    }
+
+    split(gofnparams, goargs, ", *")
+    split(cfnparams, cargs, ", *")
+    args = ""
+    carg = 1
+    for (goarg = 1; goargs[goarg] != ""; goarg++) {
+	if (cargs[carg] == "") {
+	    print loc, "not enough C parameters"
+	}
+
+	if (args != "") {
+	    args = args ", "
+	}
+
+	if (split(goargs[goarg], a) != 2) {
+	    print loc, "bad parameter:", goargs[goarg] | "cat 1>&2"
+	    status = 1
+	    next
+	}
+
+	goname = a[1]
+	gotype = a[2]
+
+	if (split(cargs[carg], a) != 2) {
+	    print loc, "bad C parameter:", cargs[carg] | "cat 1>&2"
+	    status = 1
+	    next
+	}
+
+	ctype = a[2]
+
+	if (gotype ~ /^\*/) {
+	    if (gotype != ctype) {
+		print loc, "Go/C pointer type mismatch:", gotype, ctype | "cat 1>&2"
+		status = 1
+		next
+	    }
+	    args = args goname
+	} else if (gotype == "string") {
+	    if (ctype != "*byte") {
+		print loc, "Go string not matched to C *byte:", gotype, ctype | "cat 1>&2"
+		status = 1
+		next
+	    }
+	    printf("\tvar _p%d *byte\n", goarg)
+	    if (haserr) {
+		printf("\t_p%d, err = BytePtrFromString(%s)\n", goarg, goname)
+		printf("\tif err != nil {\n\t\treturn\n\t}\n")
+	    } else {
+		print loc, "uses string arguments but has no error return" | "cat 1>&2"
+		printf("\t_p%d, _ = BytePtrFromString(%s)\n", goarg, goname)
+	    }
+	    args = sprintf("%s_p%d", args, goarg)
+	} else if (gotype ~ /^\[\](.*)/) {
+	    if (ctype !~ /^\*/ || cargs[carg + 1] == "") {
+		print loc, "bad C type for slice:", gotype, ctype | "cat 1>&2"
+		status = 1
+		next
+	    }
+
+	    # Convert a slice into a pair of pointer, length.
+	    # Don't try to take the address of the zeroth element of a
+	    # nil slice.
+	    printf("\tvar _p%d %s\n", goarg, ctype)
+	    printf("\tif len(%s) > 0 {\n", goname)
+	    printf("\t\t_p%d = (%s)(unsafe.Pointer(&%s[0]))\n", goarg, ctype, goname)
+	    printf("\t} else {\n")
+	    printf("\t\t_p%d = (%s)(unsafe.Pointer(&_zero))\n", goarg, ctype)
+	    printf("\t}\n")
+
+	    ++carg
+	    if (split(cargs[carg], cparam) != 2) {
+		print loc, "bad C parameter:", cargs[carg] | "cat 1>&2"
+		status = 1
+		next
+	    }
+
+	    args = sprintf("%s_p%d, %s(len(%s))", args, goarg, cparam[2], goname)
+	} else if (gotype == "uintptr" && ctype ~ /^\*/) {
+	    args = sprintf("%s(%s)(unsafe.Pointer(%s))", args, ctype, goname)
+	} else if (gotype == "unsafe.Pointer" && ctype ~ /^\*/) {
+	    args = sprintf("%s(%s)(%s)", args, ctype, goname)
+	} else {
+	    args = sprintf("%s%s(%s)", args, ctype, goname)
+	}
+
+	carg++
+    }
+
+    if (cargs[carg] != "") {
+	print loc, "too many C parameters" | "cat 1>&2"
+	status = 1
+	next
+    }
+
+    if (blocking) {
+	print "\tEntersyscall()"
+    }
+
+    printf("\t")
+    if (gofnresults != "") {
+	printf("_r := ")
+    }
+    printf("c_%s(%s)\n", cfnname, args)
+
+    seterr = 0
+    if (gofnresults != "") {
+	fields = split(gofnresults, goresults, ", *")
+	if (fields > 2) {
+	    print loc, "too many Go results" | "cat 1>&2"
+	    status = 1
+	    next
+	}
+	usedr = 0
+	for (goresult = 1; goresults[goresult] != ""; goresult++) {
+	    if (split(goresults[goresult], goparam) != 2) {
+		print loc, "bad result:", goresults[goresult] | "cat 1>&2"
+		status = 1
+		next
+	    }
+
+	    goname = goparam[1]
+	    gotype = goparam[2]
+
+	    if (goname == "err") {
+		print "\tvar errno Errno"
+		print "\tsetErrno := false"
+		if (cfnresult ~ /^\*/) {
+		    print "\tif _r == nil {"
+		} else {
+		    print "\tif _r < 0 {"
+		}
+		print "\t\terrno = GetErrno()"
+		print "\t\tsetErrno = true"
+		print "\t}"
+		seterr = 1
+	    } else if (gotype == "uintptr" && cfnresult ~ /^\*/) {
+		printf("\t%s = (%s)(unsafe.Pointer(_r))\n", goname, gotype)
+	    } else {
+		if (usedr) {
+		    print loc, "two parameters but no errno parameter" | "cat 1>&2"
+		    status = 1
+		    next
+		}
+		printf("\t%s = (%s)(_r)\n", goname, gotype)
+		usedr = 1
+	    }
+	}
+    }
+
+    if (blocking) {
+	print "\tExitsyscall()"
+    }
+
+    if (seterr) {
+	print "\tif setErrno {"
+	print "\t\terr = errno"
+	print "\t}"
+    }
+
+    if (gofnresults != "") {
+	print "\treturn"
+    }
+
+    print "}"
+
+    print ""
+
+    next
+}
+
+{ next }
+
+END {
+    if (status != 0) {
+	print "*** mksyscall.awk failed" | "cat 1>&2"
+	exit status
+    }
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/mmap_unix_test.go b/third_party/gofrontend/libgo/go/syscall/mmap_unix_test.go
new file mode 100644
index 0000000..01f7783
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/mmap_unix_test.go
@@ -0,0 +1,22 @@
+// Copyright 2014 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package syscall_test
+
+import (
+	"syscall"
+	"testing"
+)
+
+func TestMmap(t *testing.T) {
+	b, err := syscall.Mmap(-1, 0, syscall.Getpagesize(), syscall.PROT_NONE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
+	if err != nil {
+		t.Fatalf("Mmap: %v", err)
+	}
+	if err := syscall.Munmap(b); err != nil {
+		t.Fatalf("Munmap: %v", err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/netlink_linux.go b/third_party/gofrontend/libgo/go/syscall/netlink_linux.go
new file mode 100644
index 0000000..49550ea
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/netlink_linux.go
@@ -0,0 +1,177 @@
+// 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.
+
+// Netlink sockets and messages
+
+package syscall
+
+import "unsafe"
+
+// Round the length of a netlink message up to align it properly.
+func nlmAlignOf(msglen int) int {
+	return (msglen + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1)
+}
+
+// Round the length of a netlink route attribute up to align it
+// properly.
+func rtaAlignOf(attrlen int) int {
+	return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1)
+}
+
+// NetlinkRouteRequest represents a request message to receive routing
+// and link states from the kernel.
+type NetlinkRouteRequest struct {
+	Header NlMsghdr
+	Data   RtGenmsg
+}
+
+func (rr *NetlinkRouteRequest) toWireFormat() []byte {
+	b := make([]byte, rr.Header.Len)
+	*(*uint32)(unsafe.Pointer(&b[0:4][0])) = rr.Header.Len
+	*(*uint16)(unsafe.Pointer(&b[4:6][0])) = rr.Header.Type
+	*(*uint16)(unsafe.Pointer(&b[6:8][0])) = rr.Header.Flags
+	*(*uint32)(unsafe.Pointer(&b[8:12][0])) = rr.Header.Seq
+	*(*uint32)(unsafe.Pointer(&b[12:16][0])) = rr.Header.Pid
+	b[16] = byte(rr.Data.Family)
+	return b
+}
+
+func newNetlinkRouteRequest(proto, seq, family int) []byte {
+	rr := &NetlinkRouteRequest{}
+	rr.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg)
+	rr.Header.Type = uint16(proto)
+	rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST
+	rr.Header.Seq = uint32(seq)
+	rr.Data.Family = uint8(family)
+	return rr.toWireFormat()
+}
+
+// NetlinkRIB returns routing information base, as known as RIB, which
+// consists of network facility information, states and parameters.
+func NetlinkRIB(proto, family int) ([]byte, error) {
+	s, err := Socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)
+	if err != nil {
+		return nil, err
+	}
+	defer Close(s)
+	lsa := &SockaddrNetlink{Family: AF_NETLINK}
+	if err := Bind(s, lsa); err != nil {
+		return nil, err
+	}
+	wb := newNetlinkRouteRequest(proto, 1, family)
+	if err := Sendto(s, wb, 0, lsa); err != nil {
+		return nil, err
+	}
+	var tab []byte
+done:
+	for {
+		rb := make([]byte, Getpagesize())
+		nr, _, err := Recvfrom(s, rb, 0)
+		if err != nil {
+			return nil, err
+		}
+		if nr < NLMSG_HDRLEN {
+			return nil, EINVAL
+		}
+		rb = rb[:nr]
+		tab = append(tab, rb...)
+		msgs, err := ParseNetlinkMessage(rb)
+		if err != nil {
+			return nil, err
+		}
+		for _, m := range msgs {
+			lsa, err := Getsockname(s)
+			if err != nil {
+				return nil, err
+			}
+			switch v := lsa.(type) {
+			case *SockaddrNetlink:
+				if m.Header.Seq != 1 || m.Header.Pid != v.Pid {
+					return nil, EINVAL
+				}
+			default:
+				return nil, EINVAL
+			}
+			if m.Header.Type == NLMSG_DONE {
+				break done
+			}
+			if m.Header.Type == NLMSG_ERROR {
+				return nil, EINVAL
+			}
+		}
+	}
+	return tab, nil
+}
+
+// NetlinkMessage represents a netlink message.
+type NetlinkMessage struct {
+	Header NlMsghdr
+	Data   []byte
+}
+
+// ParseNetlinkMessage parses b as an array of netlink messages and
+// returns the slice containing the NetlinkMessage structures.
+func ParseNetlinkMessage(b []byte) ([]NetlinkMessage, error) {
+	var msgs []NetlinkMessage
+	for len(b) >= NLMSG_HDRLEN {
+		h, dbuf, dlen, err := netlinkMessageHeaderAndData(b)
+		if err != nil {
+			return nil, err
+		}
+		m := NetlinkMessage{Header: *h, Data: dbuf[:int(h.Len)-NLMSG_HDRLEN]}
+		msgs = append(msgs, m)
+		b = b[dlen:]
+	}
+	return msgs, nil
+}
+
+func netlinkMessageHeaderAndData(b []byte) (*NlMsghdr, []byte, int, error) {
+	h := (*NlMsghdr)(unsafe.Pointer(&b[0]))
+	if int(h.Len) < NLMSG_HDRLEN || int(h.Len) > len(b) {
+		return nil, nil, 0, EINVAL
+	}
+	return h, b[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), nil
+}
+
+// NetlinkRouteAttr represents a netlink route attribute.
+type NetlinkRouteAttr struct {
+	Attr  RtAttr
+	Value []byte
+}
+
+// ParseNetlinkRouteAttr parses m's payload as an array of netlink
+// route attributes and returns the slice containing the
+// NetlinkRouteAttr structures.
+func ParseNetlinkRouteAttr(m *NetlinkMessage) ([]NetlinkRouteAttr, error) {
+	var b []byte
+	switch m.Header.Type {
+	case RTM_NEWLINK, RTM_DELLINK:
+		b = m.Data[SizeofIfInfomsg:]
+	case RTM_NEWADDR, RTM_DELADDR:
+		b = m.Data[SizeofIfAddrmsg:]
+	case RTM_NEWROUTE, RTM_DELROUTE:
+		b = m.Data[SizeofRtMsg:]
+	default:
+		return nil, EINVAL
+	}
+	var attrs []NetlinkRouteAttr
+	for len(b) >= SizeofRtAttr {
+		a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
+		if err != nil {
+			return nil, err
+		}
+		ra := NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-SizeofRtAttr]}
+		attrs = append(attrs, ra)
+		b = b[alen:]
+	}
+	return attrs, nil
+}
+
+func netlinkRouteAttrAndValue(b []byte) (*RtAttr, []byte, int, error) {
+	a := (*RtAttr)(unsafe.Pointer(&b[0]))
+	if int(a.Len) < SizeofRtAttr || int(a.Len) > len(b) {
+		return nil, nil, 0, EINVAL
+	}
+	return a, b[SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/race0.go b/third_party/gofrontend/libgo/go/syscall/race0.go
new file mode 100644
index 0000000..b02f882
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/race0.go
@@ -0,0 +1,25 @@
+// 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.
+
+// +build !race
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+const raceenabled = false
+
+func raceAcquire(addr unsafe.Pointer) {
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+}
+
+func raceReadRange(addr unsafe.Pointer, len int) {
+}
+
+func raceWriteRange(addr unsafe.Pointer, len int) {
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/route_bsd.go b/third_party/gofrontend/libgo/go/syscall/route_bsd.go
new file mode 100644
index 0000000..48af587
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/route_bsd.go
@@ -0,0 +1,224 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+// Routing sockets and messages
+
+package syscall
+
+import "unsafe"
+
+// Round the length of a raw sockaddr up to align it properly.
+func rsaAlignOf(salen int) int {
+	salign := sizeofPtr
+	// NOTE: It seems like 64-bit Darwin kernel still requires
+	// 32-bit aligned access to BSD subsystem. Also NetBSD 6
+	// kernel and beyond require 64-bit aligned access to routing
+	// facilities.
+	if darwin64Bit {
+		salign = 4
+	} else if netbsd32Bit {
+		salign = 8
+	}
+	if salen == 0 {
+		return salign
+	}
+	return (salen + salign - 1) & ^(salign - 1)
+}
+
+// RouteRIB returns routing information base, as known as RIB,
+// which consists of network facility information, states and
+// parameters.
+func RouteRIB(facility, param int) ([]byte, error) {
+	mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
+	// Find size.
+	n := uintptr(0)
+	if err := sysctl(mib, nil, &n, nil, 0); err != nil {
+		return nil, err
+	}
+	if n == 0 {
+		return nil, nil
+	}
+	tab := make([]byte, n)
+	if err := sysctl(mib, &tab[0], &n, nil, 0); err != nil {
+		return nil, err
+	}
+	return tab[:n], nil
+}
+
+// RoutingMessage represents a routing message.
+type RoutingMessage interface {
+	sockaddr() []Sockaddr
+}
+
+const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
+
+type anyMessage struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+}
+
+// RouteMessage represents a routing message containing routing
+// entries.
+type RouteMessage struct {
+	Header RtMsghdr
+	Data   []byte
+}
+
+const rtaRtMask = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_GENMASK
+
+func (m *RouteMessage) sockaddr() []Sockaddr {
+	var (
+		af  int
+		sas [4]Sockaddr
+	)
+	b := m.Data[:]
+	for i := uint(0); i < RTAX_MAX; i++ {
+		if m.Header.Addrs&rtaRtMask&(1<<i) == 0 {
+			continue
+		}
+		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
+		switch i {
+		case RTAX_DST, RTAX_GATEWAY:
+			sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+			if err != nil {
+				return nil
+			}
+			if i == RTAX_DST {
+				af = int(rsa.Family)
+			}
+			sas[i] = sa
+		case RTAX_NETMASK, RTAX_GENMASK:
+			switch af {
+			case AF_INET:
+				rsa4 := (*RawSockaddrInet4)(unsafe.Pointer(&b[0]))
+				sa := new(SockaddrInet4)
+				for j := 0; rsa4.Len > 0 && j < int(rsa4.Len)-int(unsafe.Offsetof(rsa4.Addr)); j++ {
+					sa.Addr[j] = rsa4.Addr[j]
+				}
+				sas[i] = sa
+			case AF_INET6:
+				rsa6 := (*RawSockaddrInet6)(unsafe.Pointer(&b[0]))
+				sa := new(SockaddrInet6)
+				for j := 0; rsa6.Len > 0 && j < int(rsa6.Len)-int(unsafe.Offsetof(rsa6.Addr)); j++ {
+					sa.Addr[j] = rsa6.Addr[j]
+				}
+				sas[i] = sa
+			}
+		}
+		b = b[rsaAlignOf(int(rsa.Len)):]
+	}
+	return sas[:]
+}
+
+// InterfaceMessage represents a routing message containing
+// network interface entries.
+type InterfaceMessage struct {
+	Header IfMsghdr
+	Data   []byte
+}
+
+func (m *InterfaceMessage) sockaddr() (sas []Sockaddr) {
+	if m.Header.Addrs&RTA_IFP == 0 {
+		return nil
+	}
+	sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
+	if err != nil {
+		return nil
+	}
+	return append(sas, sa)
+}
+
+// InterfaceAddrMessage represents a routing message containing
+// network interface address entries.
+type InterfaceAddrMessage struct {
+	Header IfaMsghdr
+	Data   []byte
+}
+
+const rtaIfaMask = RTA_IFA | RTA_NETMASK | RTA_BRD
+
+func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
+	if m.Header.Addrs&rtaIfaMask == 0 {
+		return nil
+	}
+	b := m.Data[:]
+	// We still see AF_UNSPEC in socket addresses on some
+	// platforms. To identify each address family correctly, we
+	// will use the address family of RTAX_NETMASK as a preferred
+	// one on the 32-bit NetBSD kernel, also use the length of
+	// RTAX_NETMASK socket address on the FreeBSD kernel.
+	preferredFamily := uint8(AF_UNSPEC)
+	for i := uint(0); i < RTAX_MAX; i++ {
+		if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 {
+			continue
+		}
+		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
+		switch i {
+		case RTAX_IFA:
+			if rsa.Family == AF_UNSPEC {
+				rsa.Family = preferredFamily
+			}
+			sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+			if err != nil {
+				return nil
+			}
+			sas = append(sas, sa)
+		case RTAX_NETMASK:
+			switch rsa.Family {
+			case AF_UNSPEC:
+				switch rsa.Len {
+				case SizeofSockaddrInet4:
+					rsa.Family = AF_INET
+				case SizeofSockaddrInet6:
+					rsa.Family = AF_INET6
+				default:
+					rsa.Family = AF_INET // an old fashion, AF_UNSPEC means AF_INET
+				}
+			case AF_INET, AF_INET6:
+				preferredFamily = rsa.Family
+			default:
+				return nil
+			}
+			sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+			if err != nil {
+				return nil
+			}
+			sas = append(sas, sa)
+		case RTAX_BRD:
+			// nothing to do
+		}
+		b = b[rsaAlignOf(int(rsa.Len)):]
+	}
+	return sas
+}
+
+// ParseRoutingMessage parses b as routing messages and returns the
+// slice containing the RoutingMessage interfaces.
+func ParseRoutingMessage(b []byte) (msgs []RoutingMessage, err error) {
+	msgCount := 0
+	for len(b) >= anyMessageLen {
+		msgCount++
+		any := (*anyMessage)(unsafe.Pointer(&b[0]))
+		if any.Version != RTM_VERSION {
+			b = b[any.Msglen:]
+			continue
+		}
+		msgs = append(msgs, any.toRoutingMessage(b))
+		b = b[any.Msglen:]
+	}
+	// We failed to parse any of the messages - version mismatch?
+	if msgCount > 0 && len(msgs) == 0 {
+		return nil, EINVAL
+	}
+	return msgs, nil
+}
+
+// ParseRoutingMessage parses msg's payload as raw sockaddrs and
+// returns the slice containing the Sockaddr interfaces.
+func ParseRoutingSockaddr(msg RoutingMessage) (sas []Sockaddr, err error) {
+	return append(sas, msg.sockaddr()...), nil
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/route_darwin.go b/third_party/gofrontend/libgo/go/syscall/route_darwin.go
new file mode 100644
index 0000000..ad27907
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/route_darwin.go
@@ -0,0 +1,61 @@
+// 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.
+
+// Routing sockets and messages for Darwin
+
+package syscall
+
+import "unsafe"
+
+func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
+	switch any.Type {
+	case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+		p := (*RouteMessage)(unsafe.Pointer(any))
+		return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
+	case RTM_IFINFO:
+		p := (*InterfaceMessage)(unsafe.Pointer(any))
+		return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+	case RTM_NEWADDR, RTM_DELADDR:
+		p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+		return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
+	case RTM_NEWMADDR2, RTM_DELMADDR:
+		p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
+		return &InterfaceMulticastAddrMessage{Header: p.Header, Data: b[SizeofIfmaMsghdr2:any.Msglen]}
+	}
+	return nil
+}
+
+// InterfaceMulticastAddrMessage represents a routing message
+// containing network interface address entries.
+type InterfaceMulticastAddrMessage struct {
+	Header IfmaMsghdr2
+	Data   []byte
+}
+
+const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
+
+func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
+	if m.Header.Addrs&rtaIfmaMask == 0 {
+		return nil
+	}
+	b := m.Data[:]
+	for i := uint(0); i < RTAX_MAX; i++ {
+		if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
+			continue
+		}
+		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
+		switch i {
+		case RTAX_IFA:
+			sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+			if e != nil {
+				return nil
+			}
+			sas = append(sas, sa)
+		case RTAX_GATEWAY, RTAX_IFP:
+			// nothing to do
+		}
+		b = b[rsaAlignOf(int(rsa.Len)):]
+	}
+	return sas
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/route_dragonfly.go b/third_party/gofrontend/libgo/go/syscall/route_dragonfly.go
new file mode 100644
index 0000000..79190d2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/route_dragonfly.go
@@ -0,0 +1,72 @@
+// 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.
+
+// Routing sockets and messages for Dragonfly
+
+package syscall
+
+import "unsafe"
+
+func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
+	switch any.Type {
+	case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+		p := (*RouteMessage)(unsafe.Pointer(any))
+		return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
+	case RTM_IFINFO:
+		p := (*InterfaceMessage)(unsafe.Pointer(any))
+		return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+	case RTM_IFANNOUNCE:
+		p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
+		return &InterfaceAnnounceMessage{Header: p.Header}
+	case RTM_NEWADDR, RTM_DELADDR:
+		p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+		return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
+	case RTM_NEWMADDR, RTM_DELMADDR:
+		p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
+		return &InterfaceMulticastAddrMessage{Header: p.Header, Data: b[SizeofIfmaMsghdr:any.Msglen]}
+	}
+	return nil
+}
+
+// InterfaceAnnounceMessage represents a routing message containing
+// network interface arrival and departure information.
+type InterfaceAnnounceMessage struct {
+	Header IfAnnounceMsghdr
+}
+
+func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
+
+// InterfaceMulticastAddrMessage represents a routing message
+// containing network interface address entries.
+type InterfaceMulticastAddrMessage struct {
+	Header IfmaMsghdr
+	Data   []byte
+}
+
+const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
+
+func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
+	if m.Header.Addrs&rtaIfmaMask == 0 {
+		return nil
+	}
+	b := m.Data[:]
+	for i := uint(0); i < RTAX_MAX; i++ {
+		if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
+			continue
+		}
+		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
+		switch i {
+		case RTAX_IFA:
+			sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+			if e != nil {
+				return nil
+			}
+			sas = append(sas, sa)
+		case RTAX_GATEWAY, RTAX_IFP:
+			// nothing to do
+		}
+		b = b[rsaAlignOf(int(rsa.Len)):]
+	}
+	return sas
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/route_freebsd.go b/third_party/gofrontend/libgo/go/syscall/route_freebsd.go
new file mode 100644
index 0000000..15897b1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/route_freebsd.go
@@ -0,0 +1,78 @@
+// 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.
+
+// Routing sockets and messages for FreeBSD
+
+package syscall
+
+import "unsafe"
+
+// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
+var freebsdVersion uint32
+
+func init() {
+	freebsdVersion, _ = SysctlUint32("kern.osreldate")
+}
+
+func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
+	switch any.Type {
+	case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+		p := (*RouteMessage)(unsafe.Pointer(any))
+		return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
+	case RTM_IFINFO:
+		return any.parseInterfaceMessage(b)
+	case RTM_IFANNOUNCE:
+		p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
+		return &InterfaceAnnounceMessage{Header: p.Header}
+	case RTM_NEWADDR, RTM_DELADDR:
+		p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+		return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
+	case RTM_NEWMADDR, RTM_DELMADDR:
+		p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
+		return &InterfaceMulticastAddrMessage{Header: p.Header, Data: b[SizeofIfmaMsghdr:any.Msglen]}
+	}
+	return nil
+}
+
+// InterfaceAnnounceMessage represents a routing message containing
+// network interface arrival and departure information.
+type InterfaceAnnounceMessage struct {
+	Header IfAnnounceMsghdr
+}
+
+func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
+
+// InterfaceMulticastAddrMessage represents a routing message
+// containing network interface address entries.
+type InterfaceMulticastAddrMessage struct {
+	Header IfmaMsghdr
+	Data   []byte
+}
+
+const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
+
+func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
+	if m.Header.Addrs&rtaIfmaMask == 0 {
+		return nil
+	}
+	b := m.Data[:]
+	for i := uint(0); i < RTAX_MAX; i++ {
+		if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
+			continue
+		}
+		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
+		switch i {
+		case RTAX_IFA:
+			sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+			if e != nil {
+				return nil
+			}
+			sas = append(sas, sa)
+		case RTAX_GATEWAY, RTAX_IFP:
+			// nothing to do
+		}
+		b = b[rsaAlignOf(int(rsa.Len)):]
+	}
+	return sas
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/route_freebsd_32bit.go b/third_party/gofrontend/libgo/go/syscall/route_freebsd_32bit.go
new file mode 100644
index 0000000..93efddd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/route_freebsd_32bit.go
@@ -0,0 +1,24 @@
+// Copyright 2014 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.
+
+// +build freebsd,386 freebsd,arm
+
+package syscall
+
+import "unsafe"
+
+func (any *anyMessage) parseInterfaceMessage(b []byte) *InterfaceMessage {
+	p := (*InterfaceMessage)(unsafe.Pointer(any))
+	// FreeBSD 10 and beyond have a restructured mbuf
+	// packet header view.
+	// See http://svnweb.freebsd.org/base?view=revision&revision=254804.
+	if freebsdVersion >= 1000000 {
+		m := (*ifMsghdr)(unsafe.Pointer(any))
+		p.Header.Data.Hwassist = uint32(m.Data.Hwassist)
+		p.Header.Data.Epoch = m.Data.Epoch
+		p.Header.Data.Lastchange = m.Data.Lastchange
+		return &InterfaceMessage{Header: p.Header, Data: b[sizeofIfMsghdr:any.Msglen]}
+	}
+	return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/route_freebsd_64bit.go b/third_party/gofrontend/libgo/go/syscall/route_freebsd_64bit.go
new file mode 100644
index 0000000..9377f2f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/route_freebsd_64bit.go
@@ -0,0 +1,14 @@
+// Copyright 2014 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.
+
+// +build freebsd,amd64
+
+package syscall
+
+import "unsafe"
+
+func (any *anyMessage) parseInterfaceMessage(b []byte) *InterfaceMessage {
+	p := (*InterfaceMessage)(unsafe.Pointer(any))
+	return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/route_netbsd.go b/third_party/gofrontend/libgo/go/syscall/route_netbsd.go
new file mode 100644
index 0000000..9883aeb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/route_netbsd.go
@@ -0,0 +1,35 @@
+// 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.
+
+// Routing sockets and messages for NetBSD
+
+package syscall
+
+import "unsafe"
+
+func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
+	switch any.Type {
+	case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+		p := (*RouteMessage)(unsafe.Pointer(any))
+		return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
+	case RTM_IFINFO:
+		p := (*InterfaceMessage)(unsafe.Pointer(any))
+		return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+	case RTM_IFANNOUNCE:
+		p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
+		return &InterfaceAnnounceMessage{Header: p.Header}
+	case RTM_NEWADDR, RTM_DELADDR:
+		p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+		return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
+	}
+	return nil
+}
+
+// InterfaceAnnounceMessage represents a routing message containing
+// network interface arrival and departure information.
+type InterfaceAnnounceMessage struct {
+	Header IfAnnounceMsghdr
+}
+
+func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
diff --git a/third_party/gofrontend/libgo/go/syscall/route_openbsd.go b/third_party/gofrontend/libgo/go/syscall/route_openbsd.go
new file mode 100644
index 0000000..19f902d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/route_openbsd.go
@@ -0,0 +1,35 @@
+// 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.
+
+// Routing sockets and messages for OpenBSD
+
+package syscall
+
+import "unsafe"
+
+func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
+	switch any.Type {
+	case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+		p := (*RouteMessage)(unsafe.Pointer(any))
+		return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
+	case RTM_IFINFO:
+		p := (*InterfaceMessage)(unsafe.Pointer(any))
+		return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+	case RTM_IFANNOUNCE:
+		p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
+		return &InterfaceAnnounceMessage{Header: p.Header}
+	case RTM_NEWADDR, RTM_DELADDR:
+		p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+		return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
+	}
+	return nil
+}
+
+// InterfaceAnnounceMessage represents a routing message containing
+// network interface arrival and departure information.
+type InterfaceAnnounceMessage struct {
+	Header IfAnnounceMsghdr
+}
+
+func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
diff --git a/third_party/gofrontend/libgo/go/syscall/security_windows.go b/third_party/gofrontend/libgo/go/syscall/security_windows.go
new file mode 100644
index 0000000..b22ecf5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/security_windows.go
@@ -0,0 +1,384 @@
+// 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 syscall
+
+import (
+	"unsafe"
+)
+
+const (
+	STANDARD_RIGHTS_REQUIRED = 0xf0000
+	STANDARD_RIGHTS_READ     = 0x20000
+	STANDARD_RIGHTS_WRITE    = 0x20000
+	STANDARD_RIGHTS_EXECUTE  = 0x20000
+	STANDARD_RIGHTS_ALL      = 0x1F0000
+)
+
+const (
+	NameUnknown          = 0
+	NameFullyQualifiedDN = 1
+	NameSamCompatible    = 2
+	NameDisplay          = 3
+	NameUniqueId         = 6
+	NameCanonical        = 7
+	NameUserPrincipal    = 8
+	NameCanonicalEx      = 9
+	NameServicePrincipal = 10
+	NameDnsDomain        = 12
+)
+
+// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
+// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
+//sys	TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
+//sys	GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
+
+// TranslateAccountName converts a directory service
+// object name from one format to another.
+func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
+	u, e := UTF16PtrFromString(username)
+	if e != nil {
+		return "", e
+	}
+	b := make([]uint16, 50)
+	n := uint32(len(b))
+	e = TranslateName(u, from, to, &b[0], &n)
+	if e != nil {
+		if e != ERROR_INSUFFICIENT_BUFFER {
+			return "", e
+		}
+		// make receive buffers of requested size and try again
+		b = make([]uint16, n)
+		e = TranslateName(u, from, to, &b[0], &n)
+		if e != nil {
+			return "", e
+		}
+	}
+	return UTF16ToString(b), nil
+}
+
+const (
+	// do not reorder
+	NetSetupUnknownStatus = iota
+	NetSetupUnjoined
+	NetSetupWorkgroupName
+	NetSetupDomainName
+)
+
+type UserInfo10 struct {
+	Name       *uint16
+	Comment    *uint16
+	UsrComment *uint16
+	FullName   *uint16
+}
+
+//sys	NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
+//sys	NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
+//sys	NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
+
+const (
+	// do not reorder
+	SidTypeUser = 1 + iota
+	SidTypeGroup
+	SidTypeDomain
+	SidTypeAlias
+	SidTypeWellKnownGroup
+	SidTypeDeletedAccount
+	SidTypeInvalid
+	SidTypeUnknown
+	SidTypeComputer
+	SidTypeLabel
+)
+
+//sys	LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
+//sys	LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
+//sys	ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
+//sys	ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
+//sys	GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
+//sys	CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
+
+// The security identifier (SID) structure is a variable-length
+// structure used to uniquely identify users or groups.
+type SID struct{}
+
+// StringToSid converts a string-format security identifier
+// sid into a valid, functional sid.
+func StringToSid(s string) (*SID, error) {
+	var sid *SID
+	p, e := UTF16PtrFromString(s)
+	if e != nil {
+		return nil, e
+	}
+	e = ConvertStringSidToSid(p, &sid)
+	if e != nil {
+		return nil, e
+	}
+	defer LocalFree((Handle)(unsafe.Pointer(sid)))
+	return sid.Copy()
+}
+
+// LookupSID retrieves a security identifier sid for the account
+// and the name of the domain on which the account was found.
+// System specify target computer to search.
+func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
+	if len(account) == 0 {
+		return nil, "", 0, EINVAL
+	}
+	acc, e := UTF16PtrFromString(account)
+	if e != nil {
+		return nil, "", 0, e
+	}
+	var sys *uint16
+	if len(system) > 0 {
+		sys, e = UTF16PtrFromString(system)
+		if e != nil {
+			return nil, "", 0, e
+		}
+	}
+	db := make([]uint16, 50)
+	dn := uint32(len(db))
+	b := make([]byte, 50)
+	n := uint32(len(b))
+	sid = (*SID)(unsafe.Pointer(&b[0]))
+	e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
+	if e != nil {
+		if e != ERROR_INSUFFICIENT_BUFFER {
+			return nil, "", 0, e
+		}
+		// make receive buffers of requested size and try again
+		b = make([]byte, n)
+		sid = (*SID)(unsafe.Pointer(&b[0]))
+		db = make([]uint16, dn)
+		e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
+		if e != nil {
+			return nil, "", 0, e
+		}
+	}
+	return sid, UTF16ToString(db), accType, nil
+}
+
+// String converts sid to a string format
+// suitable for display, storage, or transmission.
+func (sid *SID) String() (string, error) {
+	var s *uint16
+	e := ConvertSidToStringSid(sid, &s)
+	if e != nil {
+		return "", e
+	}
+	defer LocalFree((Handle)(unsafe.Pointer(s)))
+	return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
+}
+
+// Len returns the length, in bytes, of a valid security identifier sid.
+func (sid *SID) Len() int {
+	return int(GetLengthSid(sid))
+}
+
+// Copy creates a duplicate of security identifier sid.
+func (sid *SID) Copy() (*SID, error) {
+	b := make([]byte, sid.Len())
+	sid2 := (*SID)(unsafe.Pointer(&b[0]))
+	e := CopySid(uint32(len(b)), sid2, sid)
+	if e != nil {
+		return nil, e
+	}
+	return sid2, nil
+}
+
+// LookupAccount retrieves the name of the account for this sid
+// and the name of the first domain on which this sid is found.
+// System specify target computer to search for.
+func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
+	var sys *uint16
+	if len(system) > 0 {
+		sys, err = UTF16PtrFromString(system)
+		if err != nil {
+			return "", "", 0, err
+		}
+	}
+	b := make([]uint16, 50)
+	n := uint32(len(b))
+	db := make([]uint16, 50)
+	dn := uint32(len(db))
+	e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
+	if e != nil {
+		if e != ERROR_INSUFFICIENT_BUFFER {
+			return "", "", 0, e
+		}
+		// make receive buffers of requested size and try again
+		b = make([]uint16, n)
+		db = make([]uint16, dn)
+		e = LookupAccountSid(nil, sid, &b[0], &n, &db[0], &dn, &accType)
+		if e != nil {
+			return "", "", 0, e
+		}
+	}
+	return UTF16ToString(b), UTF16ToString(db), accType, nil
+}
+
+const (
+	// do not reorder
+	TOKEN_ASSIGN_PRIMARY = 1 << iota
+	TOKEN_DUPLICATE
+	TOKEN_IMPERSONATE
+	TOKEN_QUERY
+	TOKEN_QUERY_SOURCE
+	TOKEN_ADJUST_PRIVILEGES
+	TOKEN_ADJUST_GROUPS
+	TOKEN_ADJUST_DEFAULT
+
+	TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
+		TOKEN_ASSIGN_PRIMARY |
+		TOKEN_DUPLICATE |
+		TOKEN_IMPERSONATE |
+		TOKEN_QUERY |
+		TOKEN_QUERY_SOURCE |
+		TOKEN_ADJUST_PRIVILEGES |
+		TOKEN_ADJUST_GROUPS |
+		TOKEN_ADJUST_DEFAULT
+	TOKEN_READ  = STANDARD_RIGHTS_READ | TOKEN_QUERY
+	TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
+		TOKEN_ADJUST_PRIVILEGES |
+		TOKEN_ADJUST_GROUPS |
+		TOKEN_ADJUST_DEFAULT
+	TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
+)
+
+const (
+	// do not reorder
+	TokenUser = 1 + iota
+	TokenGroups
+	TokenPrivileges
+	TokenOwner
+	TokenPrimaryGroup
+	TokenDefaultDacl
+	TokenSource
+	TokenType
+	TokenImpersonationLevel
+	TokenStatistics
+	TokenRestrictedSids
+	TokenSessionId
+	TokenGroupsAndPrivileges
+	TokenSessionReference
+	TokenSandBoxInert
+	TokenAuditPolicy
+	TokenOrigin
+	TokenElevationType
+	TokenLinkedToken
+	TokenElevation
+	TokenHasRestrictions
+	TokenAccessInformation
+	TokenVirtualizationAllowed
+	TokenVirtualizationEnabled
+	TokenIntegrityLevel
+	TokenUIAccess
+	TokenMandatoryPolicy
+	TokenLogonSid
+	MaxTokenInfoClass
+)
+
+type SIDAndAttributes struct {
+	Sid        *SID
+	Attributes uint32
+}
+
+type Tokenuser struct {
+	User SIDAndAttributes
+}
+
+type Tokenprimarygroup struct {
+	PrimaryGroup *SID
+}
+
+//sys	OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
+//sys	GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
+//sys	GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
+
+// An access token contains the security information for a logon session.
+// The system creates an access token when a user logs on, and every
+// process executed on behalf of the user has a copy of the token.
+// The token identifies the user, the user's groups, and the user's
+// privileges. The system uses the token to control access to securable
+// objects and to control the ability of the user to perform various
+// system-related operations on the local computer.
+type Token Handle
+
+// OpenCurrentProcessToken opens the access token
+// associated with current process.
+func OpenCurrentProcessToken() (Token, error) {
+	p, e := GetCurrentProcess()
+	if e != nil {
+		return 0, e
+	}
+	var t Token
+	e = OpenProcessToken(p, TOKEN_QUERY, &t)
+	if e != nil {
+		return 0, e
+	}
+	return t, nil
+}
+
+// Close releases access to access token.
+func (t Token) Close() error {
+	return CloseHandle(Handle(t))
+}
+
+// getInfo retrieves a specified type of information about an access token.
+func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
+	b := make([]byte, initSize)
+	var n uint32
+	e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
+	if e != nil {
+		if e != ERROR_INSUFFICIENT_BUFFER {
+			return nil, e
+		}
+		// make receive buffers of requested size and try again
+		b = make([]byte, n)
+		e = GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
+		if e != nil {
+			return nil, e
+		}
+	}
+	return unsafe.Pointer(&b[0]), nil
+}
+
+// GetTokenUser retrieves access token t user account information.
+func (t Token) GetTokenUser() (*Tokenuser, error) {
+	i, e := t.getInfo(TokenUser, 50)
+	if e != nil {
+		return nil, e
+	}
+	return (*Tokenuser)(i), nil
+}
+
+// GetTokenPrimaryGroup retrieves access token t primary group information.
+// A pointer to a SID structure representing a group that will become
+// the primary group of any objects created by a process using this access token.
+func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
+	i, e := t.getInfo(TokenPrimaryGroup, 50)
+	if e != nil {
+		return nil, e
+	}
+	return (*Tokenprimarygroup)(i), nil
+}
+
+// GetUserProfileDirectory retrieves path to the
+// root directory of the access token t user's profile.
+func (t Token) GetUserProfileDirectory() (string, error) {
+	b := make([]uint16, 100)
+	n := uint32(len(b))
+	e := GetUserProfileDirectory(t, &b[0], &n)
+	if e != nil {
+		if e != ERROR_INSUFFICIENT_BUFFER {
+			return "", e
+		}
+		// make receive buffers of requested size and try again
+		b = make([]uint16, n)
+		e = GetUserProfileDirectory(t, &b[0], &n)
+		if e != nil {
+			return "", e
+		}
+	}
+	return UTF16ToString(b), nil
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/signame.c b/third_party/gofrontend/libgo/go/syscall/signame.c
new file mode 100644
index 0000000..0453c06
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/signame.c
@@ -0,0 +1,39 @@
+/* signame.c -- get the name of a signal
+
+   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 <string.h>
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+String Signame (intgo sig) __asm__ (GOSYM_PREFIX "syscall.Signame");
+
+String
+Signame (intgo sig)
+{
+  const char* s = NULL;
+  char buf[100];
+  size_t len;
+  byte *data;
+  String ret;
+
+#if defined(HAVE_STRSIGNAL)
+  s = strsignal (sig);
+#endif
+
+  if (s == NULL)
+    {
+      snprintf(buf, sizeof buf, "signal %ld", (long) sig);
+      s = buf;
+    }
+  len = __builtin_strlen (s);
+  data = runtime_mallocgc (len, 0, FlagNoScan);
+  __builtin_memcpy (data, s, len);
+  ret.str = data;
+  ret.len = len;
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/sleep_rtems.go b/third_party/gofrontend/libgo/go/syscall/sleep_rtems.go
new file mode 100644
index 0000000..9d72203
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/sleep_rtems.go
@@ -0,0 +1,13 @@
+// sleep_rtems.go -- Sleep on RTEMS.
+
+// Copyright 2010 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 syscall
+
+func Sleep(nsec int64) (err error) {
+	ts := NsecToTimespec(nsec)
+	err = Nanosleep(&ts, nil)
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/sleep_select.go b/third_party/gofrontend/libgo/go/syscall/sleep_select.go
new file mode 100644
index 0000000..533f554
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/sleep_select.go
@@ -0,0 +1,13 @@
+// sleep_select.go -- Sleep using select.
+
+// 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.
+
+package syscall
+
+func Sleep(nsec int64) (err error) {
+	tv := NsecToTimeval(nsec);
+	_, err = Select(0, nil, nil, nil, &tv);
+	return err;
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/sockcmsg_linux.go b/third_party/gofrontend/libgo/go/syscall/sockcmsg_linux.go
new file mode 100644
index 0000000..a2e26a1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/sockcmsg_linux.go
@@ -0,0 +1,36 @@
+// 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.
+
+// Socket control messages
+
+package syscall
+
+import "unsafe"
+
+// UnixCredentials encodes credentials into a socket control message
+// for sending to another process. This can be used for
+// authentication.
+func UnixCredentials(ucred *Ucred) []byte {
+	b := make([]byte, CmsgSpace(SizeofUcred))
+	h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
+	h.Level = SOL_SOCKET
+	h.Type = SCM_CREDENTIALS
+	h.SetLen(CmsgLen(SizeofUcred))
+	*((*Ucred)(cmsgData(h))) = *ucred
+	return b
+}
+
+// ParseUnixCredentials decodes a socket control message that contains
+// credentials in a Ucred structure. To receive such a message, the
+// SO_PASSCRED option must be enabled on the socket.
+func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
+	if m.Header.Level != SOL_SOCKET {
+		return nil, EINVAL
+	}
+	if m.Header.Type != SCM_CREDENTIALS {
+		return nil, EINVAL
+	}
+	ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
+	return &ucred, nil
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/sockcmsg_unix.go b/third_party/gofrontend/libgo/go/syscall/sockcmsg_unix.go
new file mode 100644
index 0000000..34c707d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/sockcmsg_unix.go
@@ -0,0 +1,111 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+// Socket control messages
+
+package syscall
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+// Round the length of a raw sockaddr up to align it properly.
+func cmsgAlignOf(salen int) int {
+	salign := int(sizeofPtr)
+	// NOTE: It seems like 64-bit Darwin and DragonFly BSD kernels
+	// still require 32-bit aligned access to network subsystem.
+	if darwin64Bit || dragonfly64Bit {
+		salign = 4
+	}
+	// NOTE: Solaris always uses 32-bit alignment,
+	// cf. _CMSG_DATA_ALIGNMENT in <sys/socket.h>.
+	if runtime.GOOS == "solaris" {
+		salign = 4
+	}
+	return (salen + salign - 1) & ^(salign - 1)
+}
+
+// CmsgLen returns the value to store in the Len field of the Cmsghdr
+// structure, taking into account any necessary alignment.
+func CmsgLen(datalen int) int {
+	return cmsgAlignOf(SizeofCmsghdr) + datalen
+}
+
+// CmsgSpace returns the number of bytes an ancillary element with
+// payload of the passed data length occupies.
+func CmsgSpace(datalen int) int {
+	return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen)
+}
+
+func cmsgData(h *Cmsghdr) unsafe.Pointer {
+	return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(SizeofCmsghdr)))
+}
+
+// SocketControlMessage represents a socket control message.
+type SocketControlMessage struct {
+	Header Cmsghdr
+	Data   []byte
+}
+
+// ParseSocketControlMessage parses b as an array of socket control
+// messages.
+func ParseSocketControlMessage(b []byte) ([]SocketControlMessage, error) {
+	var msgs []SocketControlMessage
+	i := 0
+	for i+CmsgLen(0) <= len(b) {
+		h, dbuf, err := socketControlMessageHeaderAndData(b[i:])
+		if err != nil {
+			return nil, err
+		}
+		m := SocketControlMessage{Header: *h, Data: dbuf}
+		msgs = append(msgs, m)
+		i += cmsgAlignOf(int(h.Len))
+	}
+	return msgs, nil
+}
+
+func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) {
+	h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
+	if h.Len < SizeofCmsghdr || int(h.Len) > len(b) {
+		return nil, nil, EINVAL
+	}
+	return h, b[cmsgAlignOf(SizeofCmsghdr):h.Len], nil
+}
+
+// UnixRights encodes a set of open file descriptors into a socket
+// control message for sending to another process.
+func UnixRights(fds ...int) []byte {
+	datalen := len(fds) * 4
+	b := make([]byte, CmsgSpace(datalen))
+	h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
+	h.Level = SOL_SOCKET
+	h.Type = SCM_RIGHTS
+	h.SetLen(CmsgLen(datalen))
+	data := uintptr(cmsgData(h))
+	for _, fd := range fds {
+		*(*int32)(unsafe.Pointer(data)) = int32(fd)
+		data += 4
+	}
+	return b
+}
+
+// ParseUnixRights decodes a socket control message that contains an
+// integer array of open file descriptors from another process.
+func ParseUnixRights(m *SocketControlMessage) ([]int, error) {
+	if m.Header.Level != SOL_SOCKET {
+		return nil, EINVAL
+	}
+	if m.Header.Type != SCM_RIGHTS {
+		return nil, EINVAL
+	}
+	fds := make([]int, len(m.Data)>>2)
+	for i, j := 0, 0; i < len(m.Data); i += 4 {
+		fds[j] = int(*(*int32)(unsafe.Pointer(&m.Data[i])))
+		j++
+	}
+	return fds, nil
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/socket.go b/third_party/gofrontend/libgo/go/syscall/socket.go
new file mode 100644
index 0000000..d96a717
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/socket.go
@@ -0,0 +1,421 @@
+// socket.go -- Socket handling.
+
+// 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.
+
+// Low-level socket interface.
+// Only for implementing net package.
+// DO NOT USE DIRECTLY.
+
+package syscall
+
+import "unsafe"
+
+// For testing: clients can set this flag to force
+// creation of IPv6 sockets to return EAFNOSUPPORT.
+var SocketDisableIPv6 bool
+
+type Sockaddr interface {
+	sockaddr() (ptr *RawSockaddrAny, len Socklen_t, err error) // lowercase; only we can define Sockaddrs
+}
+
+type RawSockaddrAny struct {
+	Addr RawSockaddr
+	Pad  [96]int8
+}
+
+const SizeofSockaddrAny = 0x6c
+
+type SockaddrInet4 struct {
+	Port int
+	Addr [4]byte
+	raw  RawSockaddrInet4
+}
+
+func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return nil, 0, EINVAL
+	}
+	sa.raw.Family = AF_INET
+	n := sa.raw.setLen()
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
+	p[0] = byte(sa.Port >> 8)
+	p[1] = byte(sa.Port)
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i]
+	}
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, nil
+}
+
+type SockaddrInet6 struct {
+	Port   int
+	ZoneId uint32
+	Addr   [16]byte
+	raw    RawSockaddrInet6
+}
+
+func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return nil, 0, EINVAL
+	}
+	sa.raw.Family = AF_INET6
+	n := sa.raw.setLen()
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
+	p[0] = byte(sa.Port >> 8)
+	p[1] = byte(sa.Port)
+	sa.raw.Scope_id = sa.ZoneId
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i]
+	}
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, nil
+}
+
+type SockaddrUnix struct {
+	Name string
+	raw  RawSockaddrUnix
+}
+
+func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
+	name := sa.Name
+	n := len(name)
+	if n >= len(sa.raw.Path) {
+		return nil, 0, EINVAL
+	}
+	sa.raw.Family = AF_UNIX
+	sa.raw.setLen(n)
+	for i := 0; i < n; i++ {
+		sa.raw.Path[i] = int8(name[i])
+	}
+	// length is family (uint16), name, NUL.
+	sl := Socklen_t(2)
+	if n > 0 {
+		sl += Socklen_t(n) + 1
+	}
+	sl = sa.raw.adjustAbstract(sl)
+
+	// length is family (uint16), name, NUL.
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), sl, nil
+}
+
+func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
+	switch rsa.Addr.Family {
+	case AF_UNIX:
+		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
+		sa := new(SockaddrUnix)
+		n, err := pp.getLen()
+		if err != nil {
+			return nil, err
+		}
+		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
+		sa.Name = string(bytes[0:n])
+		return sa, nil
+
+	case AF_INET:
+		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
+		sa := new(SockaddrInet4)
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
+		sa.Port = int(p[0])<<8 + int(p[1])
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i]
+		}
+		return sa, nil
+
+	case AF_INET6:
+		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
+		sa := new(SockaddrInet6)
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
+		sa.Port = int(p[0])<<8 + int(p[1])
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i]
+		}
+		return sa, nil
+	}
+	return anyToSockaddrOS(rsa)
+}
+
+//sys	accept(fd int, sa *RawSockaddrAny, len *Socklen_t) (nfd int, err error)
+//accept(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
+
+func Accept(fd int) (nfd int, sa Sockaddr, err error) {
+	var rsa RawSockaddrAny
+	var len Socklen_t = SizeofSockaddrAny
+	nfd, err = accept(fd, &rsa, &len)
+	if err != nil {
+		return
+	}
+	sa, err = anyToSockaddr(&rsa)
+	if err != nil {
+		Close(nfd)
+		nfd = 0
+	}
+	return
+}
+
+//sysnb	getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) (err error)
+//getsockname(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
+
+func Getsockname(fd int) (sa Sockaddr, err error) {
+	var rsa RawSockaddrAny
+	var len Socklen_t = SizeofSockaddrAny
+	if err = getsockname(fd, &rsa, &len); err != nil {
+		return
+	}
+	return anyToSockaddr(&rsa)
+}
+
+//sysnb getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) (err error)
+//getpeername(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
+
+func Getpeername(fd int) (sa Sockaddr, err error) {
+	var rsa RawSockaddrAny
+	var len Socklen_t = SizeofSockaddrAny
+	if err = getpeername(fd, &rsa, &len); err != nil {
+		return
+	}
+	return anyToSockaddr(&rsa)
+}
+
+func Bind(fd int, sa Sockaddr) (err error) {
+	ptr, n, err := sa.sockaddr()
+	if err != nil {
+		return err
+	}
+	return bind(fd, ptr, n)
+}
+
+func Connect(fd int, sa Sockaddr) (err error) {
+	ptr, n, err := sa.sockaddr()
+	if err != nil {
+		return err
+	}
+	return connect(fd, ptr, n)
+}
+
+func Socket(domain, typ, proto int) (fd int, err error) {
+	if domain == AF_INET6 && SocketDisableIPv6 {
+		return -1, EAFNOSUPPORT
+	}
+	fd, err = socket(domain, typ, proto)
+	return
+}
+
+func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
+	var fdx [2]_C_int
+	err = socketpair(domain, typ, proto, &fdx)
+	if err == nil {
+		fd[0] = int(fdx[0])
+		fd[1] = int(fdx[1])
+	}
+	return
+}
+
+func GetsockoptByte(fd, level, opt int) (value byte, err error) {
+	var n byte
+	vallen := Socklen_t(1)
+	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
+	return n, err
+}
+
+func GetsockoptInt(fd, level, opt int) (value int, err error) {
+	var n int32
+	vallen := Socklen_t(4)
+	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
+	return int(n), err
+}
+
+func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
+	vallen := Socklen_t(4)
+	err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
+	return value, err
+}
+
+func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
+	var value IPMreq
+	vallen := Socklen_t(SizeofIPMreq)
+	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
+	return &value, err
+}
+
+func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
+	var value IPMreqn
+	vallen := Socklen_t(SizeofIPMreqn)
+	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
+	return &value, err
+}
+
+func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
+	var value IPv6Mreq
+	vallen := Socklen_t(SizeofIPv6Mreq)
+	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
+	return &value, err
+}
+
+//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen Socklen_t) (err error)
+//setsockopt(s _C_int, level _C_int, optname _C_int, val *byte, vallen Socklen_t) _C_int
+
+func SetsockoptByte(fd, level, opt int, value byte) (err error) {
+	var n = byte(value)
+	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 1)
+}
+
+func SetsockoptInt(fd, level, opt int, value int) (err error) {
+	var n = int32(value)
+	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
+}
+
+func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
+	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
+}
+
+func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
+	return setsockopt(fd, level, opt, unsafe.Pointer(tv), Socklen_t(unsafe.Sizeof(*tv)))
+}
+
+func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
+	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
+}
+
+type Linger struct {
+	Onoff  int32
+	Linger int32
+}
+
+func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
+	return setsockopt(fd, level, opt, unsafe.Pointer(l), Socklen_t(unsafe.Sizeof(*l)))
+}
+
+func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
+	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
+}
+
+func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
+	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
+}
+
+func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
+	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
+}
+
+func SetsockoptString(fd, level, opt int, s string) (err error) {
+	return setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), Socklen_t(len(s)))
+}
+
+//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *Socklen_t) (n int, err error)
+//recvfrom(fd _C_int, buf *byte, len Size_t, flags _C_int, from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t
+
+func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
+	var rsa RawSockaddrAny
+	var len Socklen_t = SizeofSockaddrAny
+	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
+		return
+	}
+	if rsa.Addr.Family != AF_UNSPEC {
+		from, err = anyToSockaddr(&rsa)
+	}
+	return
+}
+
+func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
+	ptr, n, err := to.sockaddr()
+	if err != nil {
+		return err
+	}
+	return sendto(fd, p, flags, ptr, n)
+}
+
+func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
+	var msg Msghdr
+	var rsa RawSockaddrAny
+	msg.Name = (*byte)(unsafe.Pointer(&rsa))
+	msg.Namelen = uint32(SizeofSockaddrAny)
+	var iov Iovec
+	if len(p) > 0 {
+		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+		iov.SetLen(len(p))
+	}
+	var dummy byte
+	if len(oob) > 0 {
+		// receive at least one normal byte
+		if len(p) == 0 {
+			iov.Base = &dummy
+			iov.SetLen(1)
+		}
+		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
+		msg.SetControllen(len(oob))
+	}
+	msg.Iov = &iov
+	msg.Iovlen = 1
+	if n, err = recvmsg(fd, &msg, flags); err != nil {
+		return
+	}
+	oobn = int(msg.Controllen)
+	recvflags = int(msg.Flags)
+	// source address is only specified if the socket is unconnected
+	if rsa.Addr.Family != AF_UNSPEC {
+		from, err = anyToSockaddr(&rsa)
+	}
+	return
+}
+
+func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
+	_, err = SendmsgN(fd, p, oob, to, flags)
+	return
+}
+
+func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
+	var ptr *RawSockaddrAny
+	var salen Socklen_t
+	if to != nil {
+		var err error
+		ptr, salen, err = to.sockaddr()
+		if err != nil {
+			return 0, err
+		}
+	}
+	var msg Msghdr
+	msg.Name = (*byte)(unsafe.Pointer(ptr))
+	msg.Namelen = uint32(salen)
+	var iov Iovec
+	if len(p) > 0 {
+		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+		iov.SetLen(len(p))
+	}
+	var dummy byte
+	if len(oob) > 0 {
+		// send at least one normal byte
+		if len(p) == 0 {
+			iov.Base = &dummy
+			iov.SetLen(1)
+		}
+		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
+		msg.SetControllen(len(oob))
+	}
+	msg.Iov = &iov
+	msg.Iovlen = 1
+	if n, err = sendmsg(fd, &msg, flags); err != nil {
+		return 0, err
+	}
+	if len(oob) > 0 && len(p) == 0 {
+		n = 0
+	}
+	return n, nil
+}
+
+//sys	Listen(fd int, n int) (err error)
+//listen(fd _C_int, n _C_int) _C_int
+
+//sys	Shutdown(fd int, how int) (err error)
+//shutdown(fd _C_int, how _C_int) _C_int
+
+func (iov *Iovec) SetLen(length int) {
+	iov.Len = Iovec_len_t(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+	msghdr.Controllen = Msghdr_controllen_t(length)
+}
+
+func (cmsg *Cmsghdr) SetLen(length int) {
+	cmsg.Len = Cmsghdr_len_t(length)
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/socket_bsd.go b/third_party/gofrontend/libgo/go/syscall/socket_bsd.go
new file mode 100644
index 0000000..72d7180
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/socket_bsd.go
@@ -0,0 +1,82 @@
+// socket_bsd.go -- Socket handling specific to *BSD based systems.
+
+// Copyright 2010 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 syscall
+
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 28
+const SizeofSockaddrUnix = 110
+
+type RawSockaddrInet4 struct {
+	Len    uint8
+	Family uint8
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]uint8
+}
+
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+	sa.Len = SizeofSockaddrInet4
+	return SizeofSockaddrInet4
+}
+
+type RawSockaddrInet6 struct {
+	Len      uint8
+	Family   uint8
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+	sa.Len = SizeofSockaddrInet6
+	return SizeofSockaddrInet6
+}
+
+type RawSockaddrUnix struct {
+	Len    uint8
+	Family uint8
+	Path   [108]int8
+}
+
+func (sa *RawSockaddrUnix) setLen(n int) {
+	sa.Len = uint8(3 + n) // 2 for Family, Len; 1 for NUL.
+}
+
+func (sa *RawSockaddrUnix) getLen() (int, error) {
+	if sa.Len < 3 || sa.Len > SizeofSockaddrUnix {
+		return 0, EINVAL
+	}
+	n := int(sa.Len) - 3 // subtract leading Family, Len, terminating NUL.
+	for i := 0; i < n; i++ {
+		if sa.Path[i] == 0 {
+			// found early NUL; assume Len is overestimating.
+			n = i
+			break
+		}
+	}
+	return n, nil
+}
+
+func (sa *RawSockaddrUnix) adjustAbstract(sl Socklen_t) Socklen_t {
+	return sl
+}
+
+type RawSockaddr struct {
+	Len    uint8
+	Family uint8
+	Data   [14]int8
+}
+
+// BindToDevice binds the socket associated with fd to device.
+func BindToDevice(fd int, device string) (err error) {
+	return ENOSYS
+}
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, error) {
+	return nil, EAFNOSUPPORT
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/socket_irix.go b/third_party/gofrontend/libgo/go/syscall/socket_irix.go
new file mode 100644
index 0000000..bcd1781
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/socket_irix.go
@@ -0,0 +1,134 @@
+// socket_irix.go -- Socket handling specific to IRIX 6.
+
+// 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.
+
+package syscall
+
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 28
+const SizeofSockaddrUnix = 110
+
+type RawSockaddrInet4 struct {
+	Family uint16
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]uint8
+}
+
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+	return SizeofSockaddrInet4
+}
+
+type RawSockaddrInet6 struct {
+	Family   uint16
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+	return SizeofSockaddrInet6
+}
+
+type RawSockaddrUnix struct {
+	Family uint16
+	Path   [108]int8
+}
+
+func (sa *RawSockaddrUnix) setLen(int) {
+}
+
+func (sa *RawSockaddrUnix) getLen() (int, error) {
+	if sa.Path[0] == 0 {
+		// "Abstract" Unix domain socket.
+		// Rewrite leading NUL as @ for textual display.
+		// (This is the standard convention.)
+		// Not friendly to overwrite in place,
+		// but the callers below don't care.
+		sa.Path[0] = '@'
+	}
+
+	// Assume path ends at NUL.
+	// This is not technically the GNU/Linux semantics for
+	// abstract Unix domain sockets--they are supposed
+	// to be uninterpreted fixed-size binary blobs--but
+	// everyone uses this convention.
+	n := 0
+	for n < len(sa.Path)-3 && sa.Path[n] != 0 {
+		n++
+	}
+
+	return n, nil
+}
+
+func (sa *RawSockaddrUnix) adjustAbstract(sl Socklen_t) Socklen_t {
+	return sl
+}
+
+type RawSockaddr struct {
+	Family uint16
+	Data   [14]int8
+}
+
+// BindToDevice binds the socket associated with fd to device.
+func BindToDevice(fd int, device string) (err error) {
+	return ENOSYS
+}
+
+// <netdb.h> only provides struct addrinfo, AI_* and EAI_* if  _NO_XOPEN4
+// && _NO_XOPEN5, but -D_XOPEN_SOURCE=500 is required for msg_control etc.
+// in struct msghgr, so simply provide them here.
+type Addrinfo struct {
+	Ai_flags     int32
+	Ai_family    int32
+	Ai_socktype  int32
+	Ai_protocol  int32
+	Ai_addrlen   int32
+	Ai_canonname *uint8
+	Ai_addr      *_sockaddr
+	Ai_next      *Addrinfo
+}
+
+const (
+	AI_PASSIVE     = 0x00000001
+	AI_CANONNAME   = 0x00000002
+	AI_NUMERICHOST = 0x00000004
+	AI_NUMERICSERV = 0x00000008
+	AI_ALL         = 0x00000100
+	AI_ADDRCONFIG  = 0x00000400
+	AI_V4MAPPED    = 0x00000800
+	AI_DEFAULT     = (AI_V4MAPPED | AI_ADDRCONFIG)
+)
+
+const (
+	EAI_ADDRFAMILY = 1
+	EAI_AGAIN      = 2
+	EAI_BADFLAGS   = 3
+	EAI_FAIL       = 4
+	EAI_FAMILY     = 5
+	EAI_MEMORY     = 6
+	EAI_NODATA     = 7
+	EAI_NONAME     = 8
+	EAI_SERVICE    = 9
+	EAI_SOCKTYPE   = 10
+	EAI_SYSTEM     = 11
+	EAI_BADHINTS   = 12
+	EAI_OVERFLOW   = 13
+	EAI_MAX        = 14
+)
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, error) {
+	return nil, EAFNOSUPPORT
+}
+
+// <netinet/in.h.h> only provides IPV6_* etc. if  _NO_XOPEN4 && _NO_XOPEN5,
+// so as above simply provide them here.
+const (
+	IPV6_UNICAST_HOPS   = 48
+	IPV6_MULTICAST_IF   = IP_MULTICAST_IF
+	IPV6_MULTICAST_HOPS = IP_MULTICAST_TTL
+	IPV6_MULTICAST_LOOP = IP_MULTICAST_LOOP
+)
diff --git a/third_party/gofrontend/libgo/go/syscall/socket_linux.go b/third_party/gofrontend/libgo/go/syscall/socket_linux.go
new file mode 100644
index 0000000..8546abc
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/socket_linux.go
@@ -0,0 +1,186 @@
+// socket_linux.go -- Socket handling specific to GNU/Linux.
+
+// Copyright 2010 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 syscall
+
+import "unsafe"
+
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 28
+const SizeofSockaddrUnix = 110
+const SizeofSockaddrLinklayer = 20
+const SizeofSockaddrNetlink = 12
+
+type SockaddrLinklayer struct {
+	Protocol uint16
+	Ifindex  int
+	Hatype   uint16
+	Pkttype  uint8
+	Halen    uint8
+	Addr     [8]byte
+	raw      RawSockaddrLinklayer
+}
+
+func (sa *SockaddrLinklayer) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
+	if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
+		return nil, 0, EINVAL
+	}
+	sa.raw.Family = AF_PACKET
+	sa.raw.Protocol = sa.Protocol
+	sa.raw.Ifindex = int32(sa.Ifindex)
+	sa.raw.Hatype = sa.Hatype
+	sa.raw.Pkttype = sa.Pkttype
+	sa.raw.Halen = sa.Halen
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i]
+	}
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrLinklayer, nil
+}
+
+type SockaddrNetlink struct {
+	Family uint16
+	Pad    uint16
+	Pid    uint32
+	Groups uint32
+	raw    RawSockaddrNetlink
+}
+
+func (sa *SockaddrNetlink) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
+	sa.raw.Family = AF_NETLINK
+	sa.raw.Pad = sa.Pad
+	sa.raw.Pid = sa.Pid
+	sa.raw.Groups = sa.Groups
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrNetlink, nil
+}
+
+type RawSockaddrInet4 struct {
+	Family uint16
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]uint8
+}
+
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+	return SizeofSockaddrInet4
+}
+
+type RawSockaddrInet6 struct {
+	Family   uint16
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+	return SizeofSockaddrInet6
+}
+
+type RawSockaddrUnix struct {
+	Family uint16
+	Path   [108]int8
+}
+
+func (sa *RawSockaddrUnix) setLen(int) {
+}
+
+func (sa *RawSockaddrUnix) getLen() (int, error) {
+	if sa.Path[0] == 0 {
+		// "Abstract" Unix domain socket.
+		// Rewrite leading NUL as @ for textual display.
+		// (This is the standard convention.)
+		// Not friendly to overwrite in place,
+		// but the callers below don't care.
+		sa.Path[0] = '@'
+	}
+
+	// Assume path ends at NUL.
+	// This is not technically the GNU/Linux semantics for
+	// abstract Unix domain sockets--they are supposed
+	// to be uninterpreted fixed-size binary blobs--but
+	// everyone uses this convention.
+	n := 0
+	for n < len(sa.Path) && sa.Path[n] != 0 {
+		n++
+	}
+
+	return n, nil
+}
+
+func (sa *RawSockaddrUnix) adjustAbstract(sl Socklen_t) Socklen_t {
+	if sa.Path[0] == '@' {
+		sa.Path[0] = 0
+		// Don't count trailing NUL for abstract address.
+		sl--
+	}
+	return sl
+}
+
+type RawSockaddrLinklayer struct {
+	Family   uint16
+	Protocol uint16
+	Ifindex  int32
+	Hatype   uint16
+	Pkttype  uint8
+	Halen    uint8
+	Addr     [8]uint8
+}
+
+type RawSockaddrNetlink struct {
+	Family uint16
+	Pad    uint16
+	Pid    uint32
+	Groups uint32
+}
+
+type RawSockaddr struct {
+	Family uint16
+	Data   [14]int8
+}
+
+// BindToDevice binds the socket associated with fd to device.
+func BindToDevice(fd int, device string) (err error) {
+	return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device)
+}
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, error) {
+	switch rsa.Addr.Family {
+	case AF_NETLINK:
+		pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa))
+		sa := new(SockaddrNetlink)
+		sa.Family = pp.Family
+		sa.Pad = pp.Pad
+		sa.Pid = pp.Pid
+		sa.Groups = pp.Groups
+		return sa, nil
+
+	case AF_PACKET:
+		pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa))
+		sa := new(SockaddrLinklayer)
+		sa.Protocol = pp.Protocol
+		sa.Ifindex = int(pp.Ifindex)
+		sa.Hatype = pp.Hatype
+		sa.Pkttype = pp.Pkttype
+		sa.Halen = pp.Halen
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i]
+		}
+		return sa, nil
+	}
+	return nil, EAFNOSUPPORT
+}
+
+//sysnb	EpollCreate(size int) (fd int, err error)
+//epoll_create(size _C_int) _C_int
+
+//sysnb EpollCreate1(flags int) (fd int, err error)
+//epoll_create1(flags _C_int) _C_int
+
+//sysnb	EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error)
+//epoll_ctl(epfd _C_int, op _C_int, fd _C_int, event *EpollEvent) _C_int
+
+//sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
+//epoll_wait(epfd _C_int, events *EpollEvent, maxevents _C_int, timeout _C_int) _C_int
diff --git a/third_party/gofrontend/libgo/go/syscall/socket_posix.go b/third_party/gofrontend/libgo/go/syscall/socket_posix.go
new file mode 100644
index 0000000..fda7dc6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/socket_posix.go
@@ -0,0 +1,31 @@
+// socket_posix.go -- Socket handling for generic POSIX systems.
+
+// Copyright 2013 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 syscall
+
+//sys	bind(fd int, sa *RawSockaddrAny, len Socklen_t) (err error)
+//bind(fd _C_int, sa *RawSockaddrAny, len Socklen_t) _C_int
+
+//sys	connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) (err error)
+//connect(s _C_int, addr *RawSockaddrAny, addrlen Socklen_t) _C_int
+
+//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
+//socket(domain _C_int, typ _C_int, protocol _C_int) _C_int
+
+//sysnb	socketpair(domain int, typ int, proto int, fd *[2]_C_int) (err error)
+//socketpair(domain _C_int, typ _C_int, protocol _C_int, fd *[2]_C_int) _C_int
+
+//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *Socklen_t) (err error)
+//getsockopt(s _C_int, level _C_int, name _C_int, val *byte, vallen *Socklen_t) _C_int
+
+//sys	sendto(s int, buf []byte, flags int, to *RawSockaddrAny, tolen Socklen_t) (err error)
+//sendto(s _C_int, buf *byte, len Size_t, flags _C_int, to *RawSockaddrAny, tolen Socklen_t) Ssize_t
+
+//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//recvmsg(s _C_int, msg *Msghdr, flags _C_int) Ssize_t
+
+//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//sendmsg(s _C_int, msg *Msghdr, flags _C_int) Ssize_t
diff --git a/third_party/gofrontend/libgo/go/syscall/socket_solaris.go b/third_party/gofrontend/libgo/go/syscall/socket_solaris.go
new file mode 100644
index 0000000..3958889
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/socket_solaris.go
@@ -0,0 +1,69 @@
+// socket_solaris.go -- Socket handling specific to Solaris.
+
+// Copyright 2010 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 syscall
+
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 32
+const SizeofSockaddrUnix = 110
+
+type RawSockaddrInet4 struct {
+	Family uint16
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]uint8
+}
+
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+	return SizeofSockaddrInet4
+}
+
+type RawSockaddrInet6 struct {
+	Family   uint16
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+	Src_id   uint32
+}
+
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+	return SizeofSockaddrInet6
+}
+
+type RawSockaddrUnix struct {
+	Family uint16
+	Path   [108]int8
+}
+
+func (sa *RawSockaddrUnix) setLen(int) {
+}
+
+func (sa *RawSockaddrUnix) getLen() (int, error) {
+	n := 0
+	for n < len(sa.Path) && sa.Path[n] != 0 {
+		n++
+	}
+	return n, nil
+}
+
+func (sa *RawSockaddrUnix) adjustAbstract(sl Socklen_t) Socklen_t {
+	return sl
+}
+
+type RawSockaddr struct {
+	Family uint16
+	Data   [14]int8
+}
+
+// BindToDevice binds the socket associated with fd to device.
+func BindToDevice(fd int, device string) (err error) {
+	return ENOSYS
+}
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, error) {
+	return nil, EAFNOSUPPORT
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/socket_xnet.go b/third_party/gofrontend/libgo/go/syscall/socket_xnet.go
new file mode 100644
index 0000000..3c5b6b4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/socket_xnet.go
@@ -0,0 +1,32 @@
+// socket_xnet.go -- Socket handling specific to Solaris.
+// Enforce use of XPG 4.2 versions of socket functions.
+
+// Copyright 2013 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 syscall
+
+//sys	bind(fd int, sa *RawSockaddrAny, len Socklen_t) (err error)
+//__xnet_bind(fd _C_int, sa *RawSockaddrAny, len Socklen_t) _C_int
+
+//sys	connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) (err error)
+//__xnet_connect(s _C_int, addr *RawSockaddrAny, addrlen Socklen_t) _C_int
+
+//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
+//__xnet_socket(domain _C_int, typ _C_int, protocol _C_int) _C_int
+
+//sysnb	socketpair(domain int, typ int, proto int, fd *[2]_C_int) (err error)
+//__xnet_socketpair(domain _C_int, typ _C_int, protocol _C_int, fd *[2]_C_int) _C_int
+
+//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *Socklen_t) (err error)
+//__xnet_getsockopt(s _C_int, level _C_int, name _C_int, val *byte, vallen *Socklen_t) _C_int
+
+//sys	sendto(s int, buf []byte, flags int, to *RawSockaddrAny, tolen Socklen_t) (err error)
+//__xnet_sendto(s _C_int, buf *byte, len Size_t, flags _C_int, to *RawSockaddrAny, tolen Socklen_t) Ssize_t
+
+//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//__xnet_recvmsg(s _C_int, msg *Msghdr, flags _C_int) Ssize_t
+
+//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//__xnet_sendmsg(s _C_int, msg *Msghdr, flags _C_int) Ssize_t
diff --git a/third_party/gofrontend/libgo/go/syscall/str.go b/third_party/gofrontend/libgo/go/syscall/str.go
new file mode 100644
index 0000000..0fce842
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/str.go
@@ -0,0 +1,20 @@
+// 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 syscall
+
+func itoa(val int) string { // do it here rather than with fmt to avoid dependency
+	if val < 0 {
+		return "-" + itoa(-val)
+	}
+	var buf [32]byte // big enough for int64
+	i := len(buf) - 1
+	for val >= 10 {
+		buf[i] = byte(val%10 + '0')
+		i--
+		val /= 10
+	}
+	buf[i] = byte(val + '0')
+	return string(buf[i:])
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall.go b/third_party/gofrontend/libgo/go/syscall/syscall.go
new file mode 100644
index 0000000..c4f2125
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall.go
@@ -0,0 +1,87 @@
+// 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 syscall contains an interface to the low-level operating system
+// primitives.  The details vary depending on the underlying system, and
+// by default, godoc will display the syscall documentation for the current
+// system.  If you want godoc to display syscall documentation for another
+// system, set $GOOS and $GOARCH to the desired system.  For example, if
+// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
+// to freebsd and $GOARCH to arm.
+// The primary use of syscall is inside other packages that provide a more
+// portable interface to the system, such as "os", "time" and "net".  Use
+// those packages rather than this one if you can.
+// For details of the functions and data types in this package consult
+// the manuals for the appropriate operating system.
+// These calls return err == nil to indicate success; otherwise
+// err is an operating system error describing the failure.
+// On most systems, that error has type syscall.Errno.
+package syscall
+
+import "unsafe"
+
+// StringByteSlice is deprecated. Use ByteSliceFromString instead.
+// If s contains a NUL byte this function panics instead of
+// returning an error.
+func StringByteSlice(s string) []byte {
+	a, err := ByteSliceFromString(s)
+	if err != nil {
+		panic("syscall: string with NUL passed to StringByteSlice")
+	}
+	return a
+}
+
+// ByteSliceFromString returns a NUL-terminated slice of bytes
+// containing the text of s. If s contains a NUL byte at any
+// location, it returns (nil, EINVAL).
+func ByteSliceFromString(s string) ([]byte, error) {
+	for i := 0; i < len(s); i++ {
+		if s[i] == 0 {
+			return nil, EINVAL
+		}
+	}
+	a := make([]byte, len(s)+1)
+	copy(a, s)
+	return a, nil
+}
+
+// StringBytePtr is deprecated. Use BytePtrFromString instead.
+// If s contains a NUL byte this function panics instead of
+// returning an error.
+func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }
+
+// BytePtrFromString returns a pointer to a NUL-terminated array of
+// bytes containing the text of s. If s contains a NUL byte at any
+// location, it returns (nil, EINVAL).
+func BytePtrFromString(s string) (*byte, error) {
+	a, err := ByteSliceFromString(s)
+	if err != nil {
+		return nil, err
+	}
+	return &a[0], nil
+}
+
+// Single-word zero for use when we need a valid pointer to 0 bytes.
+// See mksyscall.pl.
+var _zero uintptr
+
+var dummy *byte
+
+const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
+
+func (ts *Timespec) Unix() (sec int64, nsec int64) {
+	return int64(ts.Sec), int64(ts.Nsec)
+}
+
+func (tv *Timeval) Unix() (sec int64, nsec int64) {
+	return int64(tv.Sec), int64(tv.Usec) * 1000
+}
+
+func (ts *Timespec) Nano() int64 {
+	return int64(ts.Sec)*1e9 + int64(ts.Nsec)
+}
+
+func (tv *Timeval) Nano() int64 {
+	return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_errno.go b/third_party/gofrontend/libgo/go/syscall/syscall_errno.go
new file mode 100644
index 0000000..810572f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_errno.go
@@ -0,0 +1,26 @@
+// 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 syscall
+
+// An Errno is an unsigned number describing an error condition.
+// It implements the error interface.  The zero Errno is by convention
+// a non-error, so code to convert from Errno to error should use:
+//	err = nil
+//	if errno != 0 {
+//		err = errno
+//	}
+type Errno uintptr
+
+func (e Errno) Error() string {
+	return Errstr(int(e))
+}
+
+func (e Errno) Temporary() bool {
+	return e == EINTR || e == EMFILE || e.Timeout()
+}
+
+func (e Errno) Timeout() bool {
+	return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_linux_386.go b/third_party/gofrontend/libgo/go/syscall/syscall_linux_386.go
new file mode 100644
index 0000000..591d3e1
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_linux_386.go
@@ -0,0 +1,24 @@
+// syscall_linux_386.go -- GNU/Linux 386 specific support
+
+// 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.
+
+// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
+// so that go vet can check that they are correct.
+
+package syscall
+
+import "unsafe"
+
+func (r *PtraceRegs) PC() uint64 { return uint64(uint32(r.Eip)) }
+
+func (r *PtraceRegs) SetPC(pc uint64) { r.Eip = int32(pc) }
+
+func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
+	return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
+}
+
+func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
+	return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_linux_alpha.go b/third_party/gofrontend/libgo/go/syscall/syscall_linux_alpha.go
new file mode 100644
index 0000000..713546c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_linux_alpha.go
@@ -0,0 +1,57 @@
+// syscall_linux_alpha.go -- GNU/Linux ALPHA specific support
+
+// 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.
+
+package syscall
+
+import "unsafe"
+
+type PtraceRegs struct {
+	R0      uint64
+	R1      uint64
+	R2      uint64
+	R3      uint64
+	R4      uint64
+	R5      uint64
+	R6      uint64
+	R7      uint64
+	R8      uint64
+	R19     uint64
+	R20     uint64
+	R21     uint64
+	R22     uint64
+	R23     uint64
+	R24     uint64
+	R25     uint64
+	R26     uint64
+	R27     uint64
+	R28     uint64
+	Hae     uint64
+	Trap_a0 uint64
+	Trap_a1 uint64
+	Trap_a2 uint64
+	Ps      uint64
+	Pc      uint64
+	Gp      uint64
+	R16     uint64
+	R17     uint64
+	R18     uint64
+}
+
+func (r *PtraceRegs) PC() uint64 {
+	return r.Pc
+}
+
+func (r *PtraceRegs) SetPC(pc uint64) {
+	r.Pc = pc
+}
+
+func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
+	return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
+}
+
+func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
+	return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_linux_amd64.go b/third_party/gofrontend/libgo/go/syscall/syscall_linux_amd64.go
new file mode 100644
index 0000000..609faed
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_linux_amd64.go
@@ -0,0 +1,25 @@
+// syscall_linux_amd64.go -- GNU/Linux 386 specific support
+
+// 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 syscall
+
+import "unsafe"
+
+func (r *PtraceRegs) PC() uint64 {
+	return r.Rip
+}
+
+func (r *PtraceRegs) SetPC(pc uint64) {
+	r.Rip = pc
+}
+
+func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
+	return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
+}
+
+func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
+	return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_linux_s390.go b/third_party/gofrontend/libgo/go/syscall/syscall_linux_s390.go
new file mode 100644
index 0000000..a744f6b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_linux_s390.go
@@ -0,0 +1,21 @@
+// syscall_linux_s390.go -- GNU/Linux s390 specific support
+
+// Copyright 2014 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 syscall
+
+import "unsafe"
+
+func (r *PtraceRegs) PC() uint64 { return uint64(r.Psw.Addr) }
+
+func (r *PtraceRegs) SetPC(pc uint64) { r.Psw.Addr = uint32(pc) }
+
+func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
+	return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
+}
+
+func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
+	return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_linux_s390x.go b/third_party/gofrontend/libgo/go/syscall/syscall_linux_s390x.go
new file mode 100644
index 0000000..44d5679
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_linux_s390x.go
@@ -0,0 +1,21 @@
+// syscall_linux_s390x.go -- GNU/Linux s390x specific support
+
+// Copyright 2014 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 syscall
+
+import "unsafe"
+
+func (r *PtraceRegs) PC() uint64 { return r.Psw.Addr }
+
+func (r *PtraceRegs) SetPC(pc uint64) { r.Psw.Addr = pc }
+
+func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
+	return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
+}
+
+func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
+	return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_solaris.go b/third_party/gofrontend/libgo/go/syscall/syscall_solaris.go
new file mode 100644
index 0000000..c191917
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_solaris.go
@@ -0,0 +1,13 @@
+// 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 syscall
+
+func (ts *Timestruc) Unix() (sec int64, nsec int64) {
+	return int64(ts.Sec), int64(ts.Nsec)
+}
+
+func (ts *Timestruc) Nano() int64 {
+	return int64(ts.Sec)*1e9 + int64(ts.Nsec)
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_stubs.go b/third_party/gofrontend/libgo/go/syscall/syscall_stubs.go
new file mode 100644
index 0000000..76c05cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_stubs.go
@@ -0,0 +1,27 @@
+// Copyright 2010 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.
+
+// These are stubs.
+
+package syscall
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+	z := -1
+	return uintptr(z), 0, uintptr(ENOSYS)
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+	z := -1
+	return uintptr(z), 0, uintptr(ENOSYS)
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+	z := -1
+	return uintptr(z), 0, uintptr(ENOSYS)
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+	z := -1
+	return uintptr(z), 0, uintptr(ENOSYS)
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_test.go b/third_party/gofrontend/libgo/go/syscall/syscall_test.go
new file mode 100644
index 0000000..2a39b54
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_test.go
@@ -0,0 +1,30 @@
+// Copyright 2013 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 syscall_test
+
+import (
+	"syscall"
+	"testing"
+)
+
+func testSetGetenv(t *testing.T, key, value string) {
+	err := syscall.Setenv(key, value)
+	if err != nil {
+		t.Fatalf("Setenv failed to set %q: %v", value, err)
+	}
+	newvalue, found := syscall.Getenv(key)
+	if !found {
+		t.Fatalf("Getenv failed to find %v variable (want value %q)", key, value)
+	}
+	if newvalue != value {
+		t.Fatalf("Getenv(%v) = %q; want %q", key, newvalue, value)
+	}
+}
+
+func TestEnv(t *testing.T) {
+	testSetGetenv(t, "TESTENV", "AVALUE")
+	// make sure TESTENV gets set to "", not deleted
+	testSetGetenv(t, "TESTENV", "")
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_unix.go b/third_party/gofrontend/libgo/go/syscall/syscall_unix.go
new file mode 100644
index 0000000..a64b05f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_unix.go
@@ -0,0 +1,211 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package syscall
+
+import (
+	"runtime"
+	"sync"
+	"unsafe"
+)
+
+var (
+	Stdin  = 0
+	Stdout = 1
+	Stderr = 2
+)
+
+//extern syscall
+func c_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32
+
+//extern syscall
+func c_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64
+
+const (
+	darwin64Bit    = runtime.GOOS == "darwin" && sizeofPtr == 8
+	dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
+	netbsd32Bit    = runtime.GOOS == "netbsd" && sizeofPtr == 4
+)
+
+// Do a system call.  We look at the size of uintptr to see how to pass
+// the arguments, so that we don't pass a 64-bit value when the function
+// expects a 32-bit one.
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
+	Entersyscall()
+	SetErrno(0)
+	var r uintptr
+	if unsafe.Sizeof(r) == 4 {
+		r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
+		r = uintptr(r1)
+	} else {
+		r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
+		r = uintptr(r1)
+	}
+	err = GetErrno()
+	Exitsyscall()
+	return r, 0, err
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
+	Entersyscall()
+	SetErrno(0)
+	var r uintptr
+	if unsafe.Sizeof(r) == 4 {
+		r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
+			int32(a4), int32(a5), int32(a6))
+		r = uintptr(r1)
+	} else {
+		r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
+			int64(a4), int64(a5), int64(a6))
+		r = uintptr(r1)
+	}
+	err = GetErrno()
+	Exitsyscall()
+	return r, 0, err
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
+	var r uintptr
+	SetErrno(0)
+	if unsafe.Sizeof(r) == 4 {
+		r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
+		r = uintptr(r1)
+	} else {
+		r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
+		r = uintptr(r1)
+	}
+	err = GetErrno()
+	return r, 0, err
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
+	var r uintptr
+	SetErrno(0)
+	if unsafe.Sizeof(r) == 4 {
+		r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
+			int32(a4), int32(a5), int32(a6))
+		r = uintptr(r1)
+	} else {
+		r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
+			int64(a4), int64(a5), int64(a6))
+		r = uintptr(r1)
+	}
+	err = GetErrno()
+	return r, 0, err
+}
+
+// Mmap manager, for use by operating system-specific implementations.
+// Gccgo only has one implementation but we do this to correspond to gc.
+
+type mmapper struct {
+	sync.Mutex
+	active map[*byte][]byte // active mappings; key is last byte in mapping
+	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
+	munmap func(addr uintptr, length uintptr) error
+}
+
+func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
+	if length <= 0 {
+		return nil, EINVAL
+	}
+
+	// Map the requested memory.
+	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
+	if errno != nil {
+		return nil, errno
+	}
+
+	// Slice memory layout
+	var sl = struct {
+		addr uintptr
+		len  int
+		cap  int
+	}{addr, length, length}
+
+	// Use unsafeto turn sl into a []byte.
+	b := *(*[]byte)(unsafe.Pointer(&sl))
+
+	// Register mapping in m and return it.
+	p := &b[cap(b)-1]
+	m.Lock()
+	defer m.Unlock()
+	m.active[p] = b
+	return b, nil
+}
+
+func (m *mmapper) Munmap(data []byte) (err error) {
+	if len(data) == 0 || len(data) != cap(data) {
+		return EINVAL
+	}
+
+	// Find the base of the mapping.
+	p := &data[cap(data)-1]
+	m.Lock()
+	defer m.Unlock()
+	b := m.active[p]
+	if b == nil || &b[0] != &data[0] {
+		return EINVAL
+	}
+
+	// Unmap the memory and update m.
+	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
+		return errno
+	}
+	delete(m.active, p)
+	return nil
+}
+
+var mapper = &mmapper{
+	active: make(map[*byte][]byte),
+	mmap:   mmap,
+	munmap: munmap,
+}
+
+func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
+	return mapper.Mmap(fd, offset, length, prot, flags)
+}
+
+func Munmap(b []byte) (err error) {
+	return mapper.Munmap(b)
+}
+
+// A Signal is a number describing a process signal.
+// It implements the os.Signal interface.
+type Signal int
+
+func (s Signal) Signal() {}
+
+func Signame(s Signal) string
+
+func (s Signal) String() string {
+	return Signame(s)
+}
+
+func Read(fd int, p []byte) (n int, err error) {
+	n, err = read(fd, p)
+	if raceenabled {
+		if n > 0 {
+			raceWriteRange(unsafe.Pointer(&p[0]), n)
+		}
+		if err == nil {
+			raceAcquire(unsafe.Pointer(&ioSync))
+		}
+	}
+	return
+}
+
+func Write(fd int, p []byte) (n int, err error) {
+	if raceenabled {
+		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	}
+	n, err = write(fd, p)
+	if raceenabled && n > 0 {
+		raceReadRange(unsafe.Pointer(&p[0]), n)
+	}
+	return
+}
+
+var ioSync int64
diff --git a/third_party/gofrontend/libgo/go/syscall/syscall_unix_test.go b/third_party/gofrontend/libgo/go/syscall/syscall_unix_test.go
new file mode 100644
index 0000000..897ad18
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/syscall_unix_test.go
@@ -0,0 +1,318 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package syscall_test
+
+import (
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"net"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"syscall"
+	"testing"
+	"time"
+)
+
+// Tests that below functions, structures and constants are consistent
+// on all Unix-like systems.
+func _() {
+	// program scheduling priority functions and constants
+	var (
+		_ func(int, int, int) error   = syscall.Setpriority
+		_ func(int, int) (int, error) = syscall.Getpriority
+	)
+	const (
+		_ int = syscall.PRIO_USER
+		_ int = syscall.PRIO_PROCESS
+		_ int = syscall.PRIO_PGRP
+	)
+
+	// termios constants
+	const (
+		_ int = syscall.TCIFLUSH
+		_ int = syscall.TCIOFLUSH
+		_ int = syscall.TCOFLUSH
+	)
+
+	// fcntl file locking structure and constants
+	var (
+		_ = syscall.Flock_t{
+			Type:   int16(0),
+			Whence: int16(0),
+			Start:  int64(0),
+			Len:    int64(0),
+			Pid:    int32(0),
+		}
+	)
+	const (
+		_ = syscall.F_GETLK
+		_ = syscall.F_SETLK
+		_ = syscall.F_SETLKW
+	)
+}
+
+// TestFcntlFlock tests whether the file locking structure matches
+// the calling convention of each kernel.
+func TestFcntlFlock(t *testing.T) {
+	name := filepath.Join(os.TempDir(), "TestFcntlFlock")
+	fd, err := syscall.Open(name, syscall.O_CREAT|syscall.O_RDWR|syscall.O_CLOEXEC, 0)
+	if err != nil {
+		t.Fatalf("Open failed: %v", err)
+	}
+	defer syscall.Unlink(name)
+	defer syscall.Close(fd)
+	flock := syscall.Flock_t{
+		Type:  syscall.F_RDLCK,
+		Start: 0, Len: 0, Whence: 1,
+	}
+	if err := syscall.FcntlFlock(uintptr(fd), syscall.F_GETLK, &flock); err != nil {
+		t.Fatalf("FcntlFlock failed: %v", err)
+	}
+}
+
+// TestPassFD tests passing a file descriptor over a Unix socket.
+//
+// This test involved both a parent and child process. The parent
+// process is invoked as a normal test, with "go test", which then
+// runs the child process by running the current test binary with args
+// "-test.run=^TestPassFD$" and an environment variable used to signal
+// that the test should become the child process instead.
+func TestPassFD(t *testing.T) {
+	switch runtime.GOOS {
+	case "dragonfly":
+		// TODO(jsing): Figure out why sendmsg is returning EINVAL.
+		t.Skip("skipping test on dragonfly")
+	case "solaris":
+		// TODO(aram): Figure out why ReadMsgUnix is returning empty message.
+		t.Skip("skipping test on solaris, see issue 7402")
+	}
+	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
+		passFDChild()
+		return
+	}
+
+	tempDir, err := ioutil.TempDir("", "TestPassFD")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tempDir)
+
+	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
+	if err != nil {
+		t.Fatalf("Socketpair: %v", err)
+	}
+	defer syscall.Close(fds[0])
+	defer syscall.Close(fds[1])
+	writeFile := os.NewFile(uintptr(fds[0]), "child-writes")
+	readFile := os.NewFile(uintptr(fds[1]), "parent-reads")
+	defer writeFile.Close()
+	defer readFile.Close()
+
+	cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir)
+	cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
+	path := os.Getenv("LD_LIBRARY_PATH")
+	if path != "" {
+		cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+path)
+	}
+	cmd.ExtraFiles = []*os.File{writeFile}
+
+	out, err := cmd.CombinedOutput()
+	if len(out) > 0 || err != nil {
+		t.Fatalf("child process: %q, %v", out, err)
+	}
+
+	c, err := net.FileConn(readFile)
+	if err != nil {
+		t.Fatalf("FileConn: %v", err)
+	}
+	defer c.Close()
+
+	uc, ok := c.(*net.UnixConn)
+	if !ok {
+		t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c)
+	}
+
+	buf := make([]byte, 32) // expect 1 byte
+	oob := make([]byte, 32) // expect 24 bytes
+	closeUnix := time.AfterFunc(5*time.Second, func() {
+		t.Logf("timeout reading from unix socket")
+		uc.Close()
+	})
+	_, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
+	closeUnix.Stop()
+
+	scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
+	if err != nil {
+		t.Fatalf("ParseSocketControlMessage: %v", err)
+	}
+	if len(scms) != 1 {
+		t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms)
+	}
+	scm := scms[0]
+	gotFds, err := syscall.ParseUnixRights(&scm)
+	if err != nil {
+		t.Fatalf("syscall.ParseUnixRights: %v", err)
+	}
+	if len(gotFds) != 1 {
+		t.Fatalf("wanted 1 fd; got %#v", gotFds)
+	}
+
+	f := os.NewFile(uintptr(gotFds[0]), "fd-from-child")
+	defer f.Close()
+
+	got, err := ioutil.ReadAll(f)
+	want := "Hello from child process!\n"
+	if string(got) != want {
+		t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want)
+	}
+}
+
+// passFDChild is the child process used by TestPassFD.
+func passFDChild() {
+	defer os.Exit(0)
+
+	// Look for our fd. It should be fd 3, but we work around an fd leak
+	// bug here (http://golang.org/issue/2603) to let it be elsewhere.
+	var uc *net.UnixConn
+	for fd := uintptr(3); fd <= 10; fd++ {
+		f := os.NewFile(fd, "unix-conn")
+		var ok bool
+		netc, _ := net.FileConn(f)
+		uc, ok = netc.(*net.UnixConn)
+		if ok {
+			break
+		}
+	}
+	if uc == nil {
+		fmt.Println("failed to find unix fd")
+		return
+	}
+
+	// Make a file f to send to our parent process on uc.
+	// We make it in tempDir, which our parent will clean up.
+	flag.Parse()
+	tempDir := flag.Arg(0)
+	f, err := ioutil.TempFile(tempDir, "")
+	if err != nil {
+		fmt.Printf("TempFile: %v", err)
+		return
+	}
+
+	f.Write([]byte("Hello from child process!\n"))
+	f.Seek(0, 0)
+
+	rights := syscall.UnixRights(int(f.Fd()))
+	dummyByte := []byte("x")
+	n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil)
+	if err != nil {
+		fmt.Printf("WriteMsgUnix: %v", err)
+		return
+	}
+	if n != 1 || oobn != len(rights) {
+		fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights))
+		return
+	}
+}
+
+// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage,
+// and ParseUnixRights are able to successfully round-trip lists of file descriptors.
+func TestUnixRightsRoundtrip(t *testing.T) {
+	testCases := [...][][]int{
+		{{42}},
+		{{1, 2}},
+		{{3, 4, 5}},
+		{{}},
+		{{1, 2}, {3, 4, 5}, {}, {7}},
+	}
+	for _, testCase := range testCases {
+		b := []byte{}
+		var n int
+		for _, fds := range testCase {
+			// Last assignment to n wins
+			n = len(b) + syscall.CmsgLen(4*len(fds))
+			b = append(b, syscall.UnixRights(fds...)...)
+		}
+		// Truncate b
+		b = b[:n]
+
+		scms, err := syscall.ParseSocketControlMessage(b)
+		if err != nil {
+			t.Fatalf("ParseSocketControlMessage: %v", err)
+		}
+		if len(scms) != len(testCase) {
+			t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms)
+		}
+		for i, scm := range scms {
+			gotFds, err := syscall.ParseUnixRights(&scm)
+			if err != nil {
+				t.Fatalf("ParseUnixRights: %v", err)
+			}
+			wantFds := testCase[i]
+			if len(gotFds) != len(wantFds) {
+				t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds)
+			}
+			for j, fd := range gotFds {
+				if fd != wantFds[j] {
+					t.Fatalf("expected fd %v, got %v", wantFds[j], fd)
+				}
+			}
+		}
+	}
+}
+
+func TestRlimit(t *testing.T) {
+	var rlimit, zero syscall.Rlimit
+	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit)
+	if err != nil {
+		t.Fatalf("Getrlimit: save failed: %v", err)
+	}
+	if zero == rlimit {
+		t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit)
+	}
+	set := rlimit
+	set.Cur = set.Max - 1
+	err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &set)
+	if err != nil {
+		t.Fatalf("Setrlimit: set failed: %#v %v", set, err)
+	}
+	var get syscall.Rlimit
+	err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &get)
+	if err != nil {
+		t.Fatalf("Getrlimit: get failed: %v", err)
+	}
+	set = rlimit
+	set.Cur = set.Max - 1
+	if set != get {
+		// Seems like Darwin requires some privilege to
+		// increase the soft limit of rlimit sandbox, though
+		// Setrlimit never reports an error.
+		switch runtime.GOOS {
+		case "darwin":
+		default:
+			t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
+		}
+	}
+	err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit)
+	if err != nil {
+		t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err)
+	}
+}
+
+func TestSeekFailure(t *testing.T) {
+	_, err := syscall.Seek(-1, 0, 0)
+	if err == nil {
+		t.Fatalf("Seek(-1, 0, 0) did not fail")
+	}
+	str := err.Error() // used to crash on Linux
+	t.Logf("Seek: %v", str)
+	if str == "" {
+		t.Fatalf("Seek(-1, 0, 0) return error with empty message")
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/syscall/wait.c b/third_party/gofrontend/libgo/go/syscall/wait.c
new file mode 100644
index 0000000..8c3b53f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/syscall/wait.c
@@ -0,0 +1,106 @@
+/* wait.c -- functions for getting wait status values.
+
+   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.
+
+   We use C code to extract the wait status so that we can easily be
+   OS-independent.  */
+
+#include <stdint.h>
+#include <sys/wait.h>
+
+#include "runtime.h"
+
+extern _Bool Exited (uint32_t *w)
+  __asm__ (GOSYM_PREFIX "syscall.Exited.N18_syscall.WaitStatus");
+
+_Bool
+Exited (uint32_t *w)
+{
+  return WIFEXITED (*w) != 0;
+}
+
+extern _Bool Signaled (uint32_t *w)
+  __asm__ (GOSYM_PREFIX "syscall.Signaled.N18_syscall.WaitStatus");
+
+_Bool
+Signaled (uint32_t *w)
+{
+  return WIFSIGNALED (*w) != 0;
+}
+
+extern _Bool Stopped (uint32_t *w)
+  __asm__ (GOSYM_PREFIX "syscall.Stopped.N18_syscall.WaitStatus");
+
+_Bool
+Stopped (uint32_t *w)
+{
+  return WIFSTOPPED (*w) != 0;
+}
+
+extern _Bool Continued (uint32_t *w)
+  __asm__ (GOSYM_PREFIX "syscall.Continued.N18_syscall.WaitStatus");
+
+_Bool
+Continued (uint32_t *w)
+{
+  return WIFCONTINUED (*w) != 0;
+}
+
+extern _Bool CoreDump (uint32_t *w)
+  __asm__ (GOSYM_PREFIX "syscall.CoreDump.N18_syscall.WaitStatus");
+
+_Bool
+CoreDump (uint32_t *w)
+{
+  return WCOREDUMP (*w) != 0;
+}
+
+extern int ExitStatus (uint32_t *w)
+  __asm__ (GOSYM_PREFIX "syscall.ExitStatus.N18_syscall.WaitStatus");
+
+int
+ExitStatus (uint32_t *w)
+{
+  if (!WIFEXITED (*w))
+    return -1;
+  return WEXITSTATUS (*w);
+}
+
+extern int Signal (uint32_t *w)
+  __asm__ (GOSYM_PREFIX "syscall.Signal.N18_syscall.WaitStatus");
+
+int
+Signal (uint32_t *w)
+{
+  if (!WIFSIGNALED (*w))
+    return -1;
+  return WTERMSIG (*w);
+}
+
+extern int StopSignal (uint32_t *w)
+  __asm__ (GOSYM_PREFIX "syscall.StopSignal.N18_syscall.WaitStatus");
+
+int
+StopSignal (uint32_t *w)
+{
+  if (!WIFSTOPPED (*w))
+    return -1;
+  return WSTOPSIG (*w);
+}
+
+extern int TrapCause (uint32_t *w)
+  __asm__ (GOSYM_PREFIX "syscall.TrapCause.N18_syscall.WaitStatus");
+
+int
+TrapCause (uint32_t *w __attribute__ ((unused)))
+{
+#ifndef __linux__
+  return -1;
+#else
+  if (!WIFSTOPPED (*w) || WSTOPSIG (*w) != SIGTRAP)
+    return -1;
+  return *w >> 16;
+#endif
+}
diff --git a/third_party/gofrontend/libgo/go/testing/allocs.go b/third_party/gofrontend/libgo/go/testing/allocs.go
new file mode 100644
index 0000000..9ec47bd
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/allocs.go
@@ -0,0 +1,45 @@
+// Copyright 2013 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 testing
+
+import (
+	"runtime"
+)
+
+// AllocsPerRun returns the average number of allocations during calls to f.
+// Although the return value has type float64, it will always be an integral value.
+//
+// To compute the number of allocations, the function will first be run once as
+// a warm-up.  The average number of allocations over the specified number of
+// runs will then be measured and returned.
+//
+// AllocsPerRun sets GOMAXPROCS to 1 during its measurement and will restore
+// it before returning.
+func AllocsPerRun(runs int, f func()) (avg float64) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
+
+	// Warm up the function
+	f()
+
+	// Measure the starting statistics
+	var memstats runtime.MemStats
+	runtime.ReadMemStats(&memstats)
+	mallocs := 0 - memstats.Mallocs
+
+	// Run the function the specified number of times
+	for i := 0; i < runs; i++ {
+		f()
+	}
+
+	// Read the final statistics
+	runtime.ReadMemStats(&memstats)
+	mallocs += memstats.Mallocs
+
+	// Average the mallocs over the runs (not counting the warm-up).
+	// We are forced to return a float64 because the API is silly, but do
+	// the division as integers so we can ask if AllocsPerRun()==1
+	// instead of AllocsPerRun()<2.
+	return float64(mallocs / uint64(runs))
+}
diff --git a/third_party/gofrontend/libgo/go/testing/benchmark.go b/third_party/gofrontend/libgo/go/testing/benchmark.go
new file mode 100644
index 0000000..1fbf5c8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/benchmark.go
@@ -0,0 +1,444 @@
+// 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 testing
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"runtime"
+	"sync"
+	"sync/atomic"
+	"time"
+)
+
+var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
+var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
+var benchmarkMemory = flag.Bool("test.benchmem", false, "print memory allocations for benchmarks")
+
+// Global lock to ensure only one benchmark runs at a time.
+var benchmarkLock sync.Mutex
+
+// Used for every benchmark for measuring memory.
+var memStats runtime.MemStats
+
+// An internal type but exported because it is cross-package; part of the implementation
+// of the "go test" command.
+type InternalBenchmark struct {
+	Name string
+	F    func(b *B)
+}
+
+// B is a type passed to Benchmark functions to manage benchmark
+// timing and to specify the number of iterations to run.
+type B struct {
+	common
+	N                int
+	previousN        int           // number of iterations in the previous run
+	previousDuration time.Duration // total duration of the previous run
+	benchmark        InternalBenchmark
+	bytes            int64
+	timerOn          bool
+	showAllocResult  bool
+	result           BenchmarkResult
+	parallelism      int // RunParallel creates parallelism*GOMAXPROCS goroutines
+	// The initial states of memStats.Mallocs and memStats.TotalAlloc.
+	startAllocs uint64
+	startBytes  uint64
+	// The net total of this test after being run.
+	netAllocs uint64
+	netBytes  uint64
+}
+
+// StartTimer starts timing a test.  This function is called automatically
+// before a benchmark starts, but it can also used to resume timing after
+// a call to StopTimer.
+func (b *B) StartTimer() {
+	if !b.timerOn {
+		runtime.ReadMemStats(&memStats)
+		b.startAllocs = memStats.Mallocs
+		b.startBytes = memStats.TotalAlloc
+		b.start = time.Now()
+		b.timerOn = true
+	}
+}
+
+// StopTimer stops timing a test.  This can be used to pause the timer
+// while performing complex initialization that you don't
+// want to measure.
+func (b *B) StopTimer() {
+	if b.timerOn {
+		b.duration += time.Now().Sub(b.start)
+		runtime.ReadMemStats(&memStats)
+		b.netAllocs += memStats.Mallocs - b.startAllocs
+		b.netBytes += memStats.TotalAlloc - b.startBytes
+		b.timerOn = false
+	}
+}
+
+// ResetTimer zeros the elapsed benchmark time and memory allocation counters.
+// It does not affect whether the timer is running.
+func (b *B) ResetTimer() {
+	if b.timerOn {
+		runtime.ReadMemStats(&memStats)
+		b.startAllocs = memStats.Mallocs
+		b.startBytes = memStats.TotalAlloc
+		b.start = time.Now()
+	}
+	b.duration = 0
+	b.netAllocs = 0
+	b.netBytes = 0
+}
+
+// SetBytes records the number of bytes processed in a single operation.
+// If this is called, the benchmark will report ns/op and MB/s.
+func (b *B) SetBytes(n int64) { b.bytes = n }
+
+// ReportAllocs enables malloc statistics for this benchmark.
+// It is equivalent to setting -test.benchmem, but it only affects the
+// benchmark function that calls ReportAllocs.
+func (b *B) ReportAllocs() {
+	b.showAllocResult = true
+}
+
+func (b *B) nsPerOp() int64 {
+	if b.N <= 0 {
+		return 0
+	}
+	return b.duration.Nanoseconds() / int64(b.N)
+}
+
+// runN runs a single benchmark for the specified number of iterations.
+func (b *B) runN(n int) {
+	benchmarkLock.Lock()
+	defer benchmarkLock.Unlock()
+	// Try to get a comparable environment for each run
+	// by clearing garbage from previous runs.
+	runtime.GC()
+	b.N = n
+	b.parallelism = 1
+	b.ResetTimer()
+	b.StartTimer()
+	b.benchmark.F(b)
+	b.StopTimer()
+	b.previousN = n
+	b.previousDuration = b.duration
+}
+
+func min(x, y int) int {
+	if x > y {
+		return y
+	}
+	return x
+}
+
+func max(x, y int) int {
+	if x < y {
+		return y
+	}
+	return x
+}
+
+// roundDown10 rounds a number down to the nearest power of 10.
+func roundDown10(n int) int {
+	var tens = 0
+	// tens = floor(log_10(n))
+	for n >= 10 {
+		n = n / 10
+		tens++
+	}
+	// result = 10^tens
+	result := 1
+	for i := 0; i < tens; i++ {
+		result *= 10
+	}
+	return result
+}
+
+// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
+func roundUp(n int) int {
+	base := roundDown10(n)
+	switch {
+	case n <= base:
+		return base
+	case n <= (2 * base):
+		return 2 * base
+	case n <= (5 * base):
+		return 5 * base
+	default:
+		return 10 * base
+	}
+}
+
+// run times the benchmark function in a separate goroutine.
+func (b *B) run() BenchmarkResult {
+	go b.launch()
+	<-b.signal
+	return b.result
+}
+
+// launch launches the benchmark function.  It gradually increases the number
+// of benchmark iterations until the benchmark runs for a second in order
+// to get a reasonable measurement.  It prints timing information in this form
+//		testing.BenchmarkHello	100000		19 ns/op
+// launch is run by the fun function as a separate goroutine.
+func (b *B) launch() {
+	// Run the benchmark for a single iteration in case it's expensive.
+	n := 1
+
+	// Signal that we're done whether we return normally
+	// or by FailNow's runtime.Goexit.
+	defer func() {
+		b.signal <- b
+	}()
+
+	b.runN(n)
+	// Run the benchmark for at least the specified amount of time.
+	d := *benchTime
+	for !b.failed && b.duration < d && n < 1e9 {
+		last := n
+		// Predict iterations/sec.
+		if b.nsPerOp() == 0 {
+			n = 1e9
+		} else {
+			n = int(d.Nanoseconds() / b.nsPerOp())
+		}
+		// Run more iterations than we think we'll need for a second (1.5x).
+		// Don't grow too fast in case we had timing errors previously.
+		// Be sure to run at least one more than last time.
+		n = max(min(n+n/2, 100*last), last+1)
+		// Round up to something easy to read.
+		n = roundUp(n)
+		b.runN(n)
+	}
+	b.result = BenchmarkResult{b.N, b.duration, b.bytes, b.netAllocs, b.netBytes}
+}
+
+// The results of a benchmark run.
+type BenchmarkResult struct {
+	N         int           // The number of iterations.
+	T         time.Duration // The total time taken.
+	Bytes     int64         // Bytes processed in one iteration.
+	MemAllocs uint64        // The total number of memory allocations.
+	MemBytes  uint64        // The total number of bytes allocated.
+}
+
+func (r BenchmarkResult) NsPerOp() int64 {
+	if r.N <= 0 {
+		return 0
+	}
+	return r.T.Nanoseconds() / int64(r.N)
+}
+
+func (r BenchmarkResult) mbPerSec() float64 {
+	if r.Bytes <= 0 || r.T <= 0 || r.N <= 0 {
+		return 0
+	}
+	return (float64(r.Bytes) * float64(r.N) / 1e6) / r.T.Seconds()
+}
+
+func (r BenchmarkResult) AllocsPerOp() int64 {
+	if r.N <= 0 {
+		return 0
+	}
+	return int64(r.MemAllocs) / int64(r.N)
+}
+
+func (r BenchmarkResult) AllocedBytesPerOp() int64 {
+	if r.N <= 0 {
+		return 0
+	}
+	return int64(r.MemBytes) / int64(r.N)
+}
+
+func (r BenchmarkResult) String() string {
+	mbs := r.mbPerSec()
+	mb := ""
+	if mbs != 0 {
+		mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
+	}
+	nsop := r.NsPerOp()
+	ns := fmt.Sprintf("%10d ns/op", nsop)
+	if r.N > 0 && nsop < 100 {
+		// The format specifiers here make sure that
+		// the ones digits line up for all three possible formats.
+		if nsop < 10 {
+			ns = fmt.Sprintf("%13.2f ns/op", float64(r.T.Nanoseconds())/float64(r.N))
+		} else {
+			ns = fmt.Sprintf("%12.1f ns/op", float64(r.T.Nanoseconds())/float64(r.N))
+		}
+	}
+	return fmt.Sprintf("%8d\t%s%s", r.N, ns, mb)
+}
+
+func (r BenchmarkResult) MemString() string {
+	return fmt.Sprintf("%8d B/op\t%8d allocs/op",
+		r.AllocedBytesPerOp(), r.AllocsPerOp())
+}
+
+// An internal function but exported because it is cross-package; part of the implementation
+// of the "go test" command.
+func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
+	// If no flag was specified, don't run benchmarks.
+	if len(*matchBenchmarks) == 0 {
+		return
+	}
+	for _, Benchmark := range benchmarks {
+		matched, err := matchString(*matchBenchmarks, Benchmark.Name)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.bench: %s\n", err)
+			os.Exit(1)
+		}
+		if !matched {
+			continue
+		}
+		for _, procs := range cpuList {
+			runtime.GOMAXPROCS(procs)
+			b := &B{
+				common: common{
+					signal: make(chan interface{}),
+				},
+				benchmark: Benchmark,
+			}
+			benchName := Benchmark.Name
+			if procs != 1 {
+				benchName = fmt.Sprintf("%s-%d", Benchmark.Name, procs)
+			}
+			fmt.Printf("%s\t", benchName)
+			r := b.run()
+			if b.failed {
+				// The output could be very long here, but probably isn't.
+				// We print it all, regardless, because we don't want to trim the reason
+				// the benchmark failed.
+				fmt.Printf("--- FAIL: %s\n%s", benchName, b.output)
+				continue
+			}
+			results := r.String()
+			if *benchmarkMemory || b.showAllocResult {
+				results += "\t" + r.MemString()
+			}
+			fmt.Println(results)
+			// Unlike with tests, we ignore the -chatty flag and always print output for
+			// benchmarks since the output generation time will skew the results.
+			if len(b.output) > 0 {
+				b.trimOutput()
+				fmt.Printf("--- BENCH: %s\n%s", benchName, b.output)
+			}
+			if p := runtime.GOMAXPROCS(-1); p != procs {
+				fmt.Fprintf(os.Stderr, "testing: %s left GOMAXPROCS set to %d\n", benchName, p)
+			}
+		}
+	}
+}
+
+// trimOutput shortens the output from a benchmark, which can be very long.
+func (b *B) trimOutput() {
+	// The output is likely to appear multiple times because the benchmark
+	// is run multiple times, but at least it will be seen. This is not a big deal
+	// because benchmarks rarely print, but just in case, we trim it if it's too long.
+	const maxNewlines = 10
+	for nlCount, j := 0, 0; j < len(b.output); j++ {
+		if b.output[j] == '\n' {
+			nlCount++
+			if nlCount >= maxNewlines {
+				b.output = append(b.output[:j], "\n\t... [output truncated]\n"...)
+				break
+			}
+		}
+	}
+}
+
+// A PB is used by RunParallel for running parallel benchmarks.
+type PB struct {
+	globalN *uint64 // shared between all worker goroutines iteration counter
+	grain   uint64  // acquire that many iterations from globalN at once
+	cache   uint64  // local cache of acquired iterations
+	bN      uint64  // total number of iterations to execute (b.N)
+}
+
+// Next reports whether there are more iterations to execute.
+func (pb *PB) Next() bool {
+	if pb.cache == 0 {
+		n := atomic.AddUint64(pb.globalN, pb.grain)
+		if n <= pb.bN {
+			pb.cache = pb.grain
+		} else if n < pb.bN+pb.grain {
+			pb.cache = pb.bN + pb.grain - n
+		} else {
+			return false
+		}
+	}
+	pb.cache--
+	return true
+}
+
+// RunParallel runs a benchmark in parallel.
+// It creates multiple goroutines and distributes b.N iterations among them.
+// The number of goroutines defaults to GOMAXPROCS. To increase parallelism for
+// non-CPU-bound benchmarks, call SetParallelism before RunParallel.
+// RunParallel is usually used with the go test -cpu flag.
+//
+// The body function will be run in each goroutine. It should set up any
+// goroutine-local state and then iterate until pb.Next returns false.
+// It should not use the StartTimer, StopTimer, or ResetTimer functions,
+// because they have global effect.
+func (b *B) RunParallel(body func(*PB)) {
+	// Calculate grain size as number of iterations that take ~100µs.
+	// 100µs is enough to amortize the overhead and provide sufficient
+	// dynamic load balancing.
+	grain := uint64(0)
+	if b.previousN > 0 && b.previousDuration > 0 {
+		grain = 1e5 * uint64(b.previousN) / uint64(b.previousDuration)
+	}
+	if grain < 1 {
+		grain = 1
+	}
+	// We expect the inner loop and function call to take at least 10ns,
+	// so do not do more than 100µs/10ns=1e4 iterations.
+	if grain > 1e4 {
+		grain = 1e4
+	}
+
+	n := uint64(0)
+	numProcs := b.parallelism * runtime.GOMAXPROCS(0)
+	var wg sync.WaitGroup
+	wg.Add(numProcs)
+	for p := 0; p < numProcs; p++ {
+		go func() {
+			defer wg.Done()
+			pb := &PB{
+				globalN: &n,
+				grain:   grain,
+				bN:      uint64(b.N),
+			}
+			body(pb)
+		}()
+	}
+	wg.Wait()
+	if n <= uint64(b.N) && !b.Failed() {
+		b.Fatal("RunParallel: body exited without pb.Next() == false")
+	}
+}
+
+// SetParallelism sets the number of goroutines used by RunParallel to p*GOMAXPROCS.
+// There is usually no need to call SetParallelism for CPU-bound benchmarks.
+// If p is less than 1, this call will have no effect.
+func (b *B) SetParallelism(p int) {
+	if p >= 1 {
+		b.parallelism = p
+	}
+}
+
+// Benchmark benchmarks a single function. Useful for creating
+// custom benchmarks that do not use the "go test" command.
+func Benchmark(f func(b *B)) BenchmarkResult {
+	b := &B{
+		common: common{
+			signal: make(chan interface{}),
+		},
+		benchmark: InternalBenchmark{"", f},
+	}
+	return b.run()
+}
diff --git a/third_party/gofrontend/libgo/go/testing/benchmark_test.go b/third_party/gofrontend/libgo/go/testing/benchmark_test.go
new file mode 100644
index 0000000..f7ea64e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/benchmark_test.go
@@ -0,0 +1,111 @@
+// Copyright 2013 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 testing_test
+
+import (
+	"bytes"
+	"runtime"
+	"sync/atomic"
+	"testing"
+	"text/template"
+)
+
+var roundDownTests = []struct {
+	v, expected int
+}{
+	{1, 1},
+	{9, 1},
+	{10, 10},
+	{11, 10},
+	{100, 100},
+	{101, 100},
+	{999, 100},
+	{1000, 1000},
+	{1001, 1000},
+}
+
+func TestRoundDown10(t *testing.T) {
+	for _, tt := range roundDownTests {
+		actual := testing.RoundDown10(tt.v)
+		if tt.expected != actual {
+			t.Errorf("roundDown10(%d): expected %d, actual %d", tt.v, tt.expected, actual)
+		}
+	}
+}
+
+var roundUpTests = []struct {
+	v, expected int
+}{
+	{0, 1},
+	{1, 1},
+	{2, 2},
+	{5, 5},
+	{9, 10},
+	{999, 1000},
+	{1000, 1000},
+	{1400, 2000},
+	{1700, 2000},
+	{4999, 5000},
+	{5000, 5000},
+	{5001, 10000},
+}
+
+func TestRoundUp(t *testing.T) {
+	for _, tt := range roundUpTests {
+		actual := testing.RoundUp(tt.v)
+		if tt.expected != actual {
+			t.Errorf("roundUp(%d): expected %d, actual %d", tt.v, tt.expected, actual)
+		}
+	}
+}
+
+func TestRunParallel(t *testing.T) {
+	testing.Benchmark(func(b *testing.B) {
+		procs := uint32(0)
+		iters := uint64(0)
+		b.SetParallelism(3)
+		b.RunParallel(func(pb *testing.PB) {
+			atomic.AddUint32(&procs, 1)
+			for pb.Next() {
+				atomic.AddUint64(&iters, 1)
+			}
+		})
+		if want := uint32(3 * runtime.GOMAXPROCS(0)); procs != want {
+			t.Errorf("got %v procs, want %v", procs, want)
+		}
+		if iters != uint64(b.N) {
+			t.Errorf("got %v iters, want %v", iters, b.N)
+		}
+	})
+}
+
+func TestRunParallelFail(t *testing.T) {
+	testing.Benchmark(func(b *testing.B) {
+		b.RunParallel(func(pb *testing.PB) {
+			// The function must be able to log/abort
+			// w/o crashing/deadlocking the whole benchmark.
+			b.Log("log")
+			b.Error("error")
+		})
+	})
+}
+
+func ExampleB_RunParallel() {
+	// Parallel benchmark for text/template.Template.Execute on a single object.
+	testing.Benchmark(func(b *testing.B) {
+		templ := template.Must(template.New("test").Parse("Hello, {{.}}!"))
+		// RunParallel will create GOMAXPROCS goroutines
+		// and distribute work among them.
+		b.RunParallel(func(pb *testing.PB) {
+			// Each goroutine has its own bytes.Buffer.
+			var buf bytes.Buffer
+			for pb.Next() {
+				// The loop body is executed b.N times total across all goroutines.
+				buf.Reset()
+				templ.Execute(&buf, "World")
+			}
+		})
+	})
+}
diff --git a/third_party/gofrontend/libgo/go/testing/cover.go b/third_party/gofrontend/libgo/go/testing/cover.go
new file mode 100644
index 0000000..dd29364
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/cover.go
@@ -0,0 +1,86 @@
+// Copyright 2013 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.
+
+// Support for test coverage.
+
+package testing
+
+import (
+	"fmt"
+	"os"
+)
+
+// CoverBlock records the coverage data for a single basic block.
+// NOTE: This struct is internal to the testing infrastructure and may change.
+// It is not covered (yet) by the Go 1 compatibility guidelines.
+type CoverBlock struct {
+	Line0 uint32
+	Col0  uint16
+	Line1 uint32
+	Col1  uint16
+	Stmts uint16
+}
+
+var cover Cover
+
+// Cover records information about test coverage checking.
+// NOTE: This struct is internal to the testing infrastructure and may change.
+// It is not covered (yet) by the Go 1 compatibility guidelines.
+type Cover struct {
+	Mode            string
+	Counters        map[string][]uint32
+	Blocks          map[string][]CoverBlock
+	CoveredPackages string
+}
+
+// RegisterCover records the coverage data accumulators for the tests.
+// NOTE: This function is internal to the testing infrastructure and may change.
+// It is not covered (yet) by the Go 1 compatibility guidelines.
+func RegisterCover(c Cover) {
+	cover = c
+}
+
+// mustBeNil checks the error and, if present, reports it and exits.
+func mustBeNil(err error) {
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+		os.Exit(2)
+	}
+}
+
+// coverReport reports the coverage percentage and writes a coverage profile if requested.
+func coverReport() {
+	var f *os.File
+	var err error
+	if *coverProfile != "" {
+		f, err = os.Create(toOutputDir(*coverProfile))
+		mustBeNil(err)
+		fmt.Fprintf(f, "mode: %s\n", cover.Mode)
+		defer func() { mustBeNil(f.Close()) }()
+	}
+
+	var active, total int64
+	for name, counts := range cover.Counters {
+		blocks := cover.Blocks[name]
+		for i, count := range counts {
+			stmts := int64(blocks[i].Stmts)
+			total += stmts
+			if count > 0 {
+				active += stmts
+			}
+			if f != nil {
+				_, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n", name,
+					blocks[i].Line0, blocks[i].Col0,
+					blocks[i].Line1, blocks[i].Col1,
+					stmts,
+					count)
+				mustBeNil(err)
+			}
+		}
+	}
+	if total == 0 {
+		total = 1
+	}
+	fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages)
+}
diff --git a/third_party/gofrontend/libgo/go/testing/example.go b/third_party/gofrontend/libgo/go/testing/example.go
new file mode 100644
index 0000000..828c2d3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/example.go
@@ -0,0 +1,100 @@
+// 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 testing
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"time"
+)
+
+type InternalExample struct {
+	Name   string
+	F      func()
+	Output string
+}
+
+func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool) {
+	ok = true
+
+	var eg InternalExample
+
+	for _, eg = range examples {
+		matched, err := matchString(*match, eg.Name)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err)
+			os.Exit(1)
+		}
+		if !matched {
+			continue
+		}
+		if !runExample(eg) {
+			ok = false
+		}
+	}
+
+	return
+}
+
+func runExample(eg InternalExample) (ok bool) {
+	if *chatty {
+		fmt.Printf("=== RUN: %s\n", eg.Name)
+	}
+
+	// Capture stdout.
+	stdout := os.Stdout
+	r, w, err := os.Pipe()
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+	os.Stdout = w
+	outC := make(chan string)
+	go func() {
+		buf := new(bytes.Buffer)
+		_, err := io.Copy(buf, r)
+		r.Close()
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: copying pipe: %v\n", err)
+			os.Exit(1)
+		}
+		outC <- buf.String()
+	}()
+
+	start := time.Now()
+	ok = true
+
+	// Clean up in a deferred call so we can recover if the example panics.
+	defer func() {
+		d := time.Now().Sub(start)
+
+		// Close pipe, restore stdout, get output.
+		w.Close()
+		os.Stdout = stdout
+		out := <-outC
+
+		var fail string
+		err := recover()
+		if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e && err == nil {
+			fail = fmt.Sprintf("got:\n%s\nwant:\n%s\n", g, e)
+		}
+		if fail != "" || err != nil {
+			fmt.Printf("--- FAIL: %s (%v)\n%s", eg.Name, d, fail)
+			ok = false
+		} else if *chatty {
+			fmt.Printf("--- PASS: %s (%v)\n", eg.Name, d)
+		}
+		if err != nil {
+			panic(err)
+		}
+	}()
+
+	// Run example.
+	eg.F()
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/testing/export_test.go b/third_party/gofrontend/libgo/go/testing/export_test.go
new file mode 100644
index 0000000..89781b4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/export_test.go
@@ -0,0 +1,10 @@
+// Copyright 2013 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 testing
+
+var (
+	RoundDown10 = roundDown10
+	RoundUp     = roundUp
+)
diff --git a/third_party/gofrontend/libgo/go/testing/iotest/logger.go b/third_party/gofrontend/libgo/go/testing/iotest/logger.go
new file mode 100644
index 0000000..1475d9b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/iotest/logger.go
@@ -0,0 +1,54 @@
+// 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 iotest
+
+import (
+	"io"
+	"log"
+)
+
+type writeLogger struct {
+	prefix string
+	w      io.Writer
+}
+
+func (l *writeLogger) Write(p []byte) (n int, err error) {
+	n, err = l.w.Write(p)
+	if err != nil {
+		log.Printf("%s %x: %v", l.prefix, p[0:n], err)
+	} else {
+		log.Printf("%s %x", l.prefix, p[0:n])
+	}
+	return
+}
+
+// NewWriteLogger returns a writer that behaves like w except
+// that it logs (using log.Printf) each write to standard error,
+// printing the prefix and the hexadecimal data written.
+func NewWriteLogger(prefix string, w io.Writer) io.Writer {
+	return &writeLogger{prefix, w}
+}
+
+type readLogger struct {
+	prefix string
+	r      io.Reader
+}
+
+func (l *readLogger) Read(p []byte) (n int, err error) {
+	n, err = l.r.Read(p)
+	if err != nil {
+		log.Printf("%s %x: %v", l.prefix, p[0:n], err)
+	} else {
+		log.Printf("%s %x", l.prefix, p[0:n])
+	}
+	return
+}
+
+// NewReadLogger returns a reader that behaves like r except
+// that it logs (using log.Print) each read to standard error,
+// printing the prefix and the hexadecimal data written.
+func NewReadLogger(prefix string, r io.Reader) io.Reader {
+	return &readLogger{prefix, r}
+}
diff --git a/third_party/gofrontend/libgo/go/testing/iotest/reader.go b/third_party/gofrontend/libgo/go/testing/iotest/reader.go
new file mode 100644
index 0000000..a5bccca
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/iotest/reader.go
@@ -0,0 +1,88 @@
+// 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 iotest implements Readers and Writers useful mainly for testing.
+package iotest
+
+import (
+	"errors"
+	"io"
+)
+
+// OneByteReader returns a Reader that implements
+// each non-empty Read by reading one byte from r.
+func OneByteReader(r io.Reader) io.Reader { return &oneByteReader{r} }
+
+type oneByteReader struct {
+	r io.Reader
+}
+
+func (r *oneByteReader) Read(p []byte) (int, error) {
+	if len(p) == 0 {
+		return 0, nil
+	}
+	return r.r.Read(p[0:1])
+}
+
+// HalfReader returns a Reader that implements Read
+// by reading half as many requested bytes from r.
+func HalfReader(r io.Reader) io.Reader { return &halfReader{r} }
+
+type halfReader struct {
+	r io.Reader
+}
+
+func (r *halfReader) Read(p []byte) (int, error) {
+	return r.r.Read(p[0 : (len(p)+1)/2])
+}
+
+// DataErrReader changes the way errors are handled by a Reader. Normally, a
+// Reader returns an error (typically EOF) from the first Read call after the
+// last piece of data is read. DataErrReader wraps a Reader and changes its
+// behavior so the final error is returned along with the final data, instead
+// of in the first call after the final data.
+func DataErrReader(r io.Reader) io.Reader { return &dataErrReader{r, nil, make([]byte, 1024)} }
+
+type dataErrReader struct {
+	r      io.Reader
+	unread []byte
+	data   []byte
+}
+
+func (r *dataErrReader) Read(p []byte) (n int, err error) {
+	// loop because first call needs two reads:
+	// one to get data and a second to look for an error.
+	for {
+		if len(r.unread) == 0 {
+			n1, err1 := r.r.Read(r.data)
+			r.unread = r.data[0:n1]
+			err = err1
+		}
+		if n > 0 || err != nil {
+			break
+		}
+		n = copy(p, r.unread)
+		r.unread = r.unread[n:]
+	}
+	return
+}
+
+var ErrTimeout = errors.New("timeout")
+
+// TimeoutReader returns ErrTimeout on the second read
+// with no data.  Subsequent calls to read succeed.
+func TimeoutReader(r io.Reader) io.Reader { return &timeoutReader{r, 0} }
+
+type timeoutReader struct {
+	r     io.Reader
+	count int
+}
+
+func (r *timeoutReader) Read(p []byte) (int, error) {
+	r.count++
+	if r.count == 2 {
+		return 0, ErrTimeout
+	}
+	return r.r.Read(p)
+}
diff --git a/third_party/gofrontend/libgo/go/testing/iotest/writer.go b/third_party/gofrontend/libgo/go/testing/iotest/writer.go
new file mode 100644
index 0000000..af61ab8
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/iotest/writer.go
@@ -0,0 +1,35 @@
+// 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 iotest
+
+import "io"
+
+// TruncateWriter returns a Writer that writes to w
+// but stops silently after n bytes.
+func TruncateWriter(w io.Writer, n int64) io.Writer {
+	return &truncateWriter{w, n}
+}
+
+type truncateWriter struct {
+	w io.Writer
+	n int64
+}
+
+func (t *truncateWriter) Write(p []byte) (n int, err error) {
+	if t.n <= 0 {
+		return len(p), nil
+	}
+	// real write
+	n = len(p)
+	if int64(n) > t.n {
+		n = int(t.n)
+	}
+	n, err = t.w.Write(p[0:n])
+	t.n -= int64(n)
+	if err == nil {
+		n = len(p)
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/testing/quick/quick.go b/third_party/gofrontend/libgo/go/testing/quick/quick.go
new file mode 100644
index 0000000..bc79cc3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/quick/quick.go
@@ -0,0 +1,358 @@
+// 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 quick implements utility functions to help with black box testing.
+package quick
+
+import (
+	"flag"
+	"fmt"
+	"math"
+	"math/rand"
+	"reflect"
+	"strings"
+)
+
+var defaultMaxCount *int = flag.Int("quickchecks", 100, "The default number of iterations for each check")
+
+// A Generator can generate random values of its own type.
+type Generator interface {
+	// Generate returns a random instance of the type on which it is a
+	// method using the size as a size hint.
+	Generate(rand *rand.Rand, size int) reflect.Value
+}
+
+// randFloat32 generates a random float taking the full range of a float32.
+func randFloat32(rand *rand.Rand) float32 {
+	f := rand.Float64() * math.MaxFloat32
+	if rand.Int()&1 == 1 {
+		f = -f
+	}
+	return float32(f)
+}
+
+// randFloat64 generates a random float taking the full range of a float64.
+func randFloat64(rand *rand.Rand) float64 {
+	f := rand.Float64() * math.MaxFloat64
+	if rand.Int()&1 == 1 {
+		f = -f
+	}
+	return f
+}
+
+// randInt64 returns a random integer taking half the range of an int64.
+func randInt64(rand *rand.Rand) int64 { return rand.Int63() - 1<<62 }
+
+// complexSize is the maximum length of arbitrary values that contain other
+// values.
+const complexSize = 50
+
+// Value returns an arbitrary value of the given type.
+// If the type implements the Generator interface, that will be used.
+// Note: To create arbitrary values for structs, all the fields must be exported.
+func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
+	if m, ok := reflect.Zero(t).Interface().(Generator); ok {
+		return m.Generate(rand, complexSize), true
+	}
+
+	v := reflect.New(t).Elem()
+	switch concrete := t; concrete.Kind() {
+	case reflect.Bool:
+		v.SetBool(rand.Int()&1 == 0)
+	case reflect.Float32:
+		v.SetFloat(float64(randFloat32(rand)))
+	case reflect.Float64:
+		v.SetFloat(randFloat64(rand))
+	case reflect.Complex64:
+		v.SetComplex(complex(float64(randFloat32(rand)), float64(randFloat32(rand))))
+	case reflect.Complex128:
+		v.SetComplex(complex(randFloat64(rand), randFloat64(rand)))
+	case reflect.Int16:
+		v.SetInt(randInt64(rand))
+	case reflect.Int32:
+		v.SetInt(randInt64(rand))
+	case reflect.Int64:
+		v.SetInt(randInt64(rand))
+	case reflect.Int8:
+		v.SetInt(randInt64(rand))
+	case reflect.Int:
+		v.SetInt(randInt64(rand))
+	case reflect.Uint16:
+		v.SetUint(uint64(randInt64(rand)))
+	case reflect.Uint32:
+		v.SetUint(uint64(randInt64(rand)))
+	case reflect.Uint64:
+		v.SetUint(uint64(randInt64(rand)))
+	case reflect.Uint8:
+		v.SetUint(uint64(randInt64(rand)))
+	case reflect.Uint:
+		v.SetUint(uint64(randInt64(rand)))
+	case reflect.Uintptr:
+		v.SetUint(uint64(randInt64(rand)))
+	case reflect.Map:
+		numElems := rand.Intn(complexSize)
+		v.Set(reflect.MakeMap(concrete))
+		for i := 0; i < numElems; i++ {
+			key, ok1 := Value(concrete.Key(), rand)
+			value, ok2 := Value(concrete.Elem(), rand)
+			if !ok1 || !ok2 {
+				return reflect.Value{}, false
+			}
+			v.SetMapIndex(key, value)
+		}
+	case reflect.Ptr:
+		elem, ok := Value(concrete.Elem(), rand)
+		if !ok {
+			return reflect.Value{}, false
+		}
+		v.Set(reflect.New(concrete.Elem()))
+		v.Elem().Set(elem)
+	case reflect.Slice:
+		numElems := rand.Intn(complexSize)
+		v.Set(reflect.MakeSlice(concrete, numElems, numElems))
+		for i := 0; i < numElems; i++ {
+			elem, ok := Value(concrete.Elem(), rand)
+			if !ok {
+				return reflect.Value{}, false
+			}
+			v.Index(i).Set(elem)
+		}
+	case reflect.String:
+		numChars := rand.Intn(complexSize)
+		codePoints := make([]rune, numChars)
+		for i := 0; i < numChars; i++ {
+			codePoints[i] = rune(rand.Intn(0x10ffff))
+		}
+		v.SetString(string(codePoints))
+	case reflect.Struct:
+		for i := 0; i < v.NumField(); i++ {
+			elem, ok := Value(concrete.Field(i).Type, rand)
+			if !ok {
+				return reflect.Value{}, false
+			}
+			v.Field(i).Set(elem)
+		}
+	default:
+		return reflect.Value{}, false
+	}
+
+	return v, true
+}
+
+// A Config structure contains options for running a test.
+type Config struct {
+	// MaxCount sets the maximum number of iterations. If zero,
+	// MaxCountScale is used.
+	MaxCount int
+	// MaxCountScale is a non-negative scale factor applied to the default
+	// maximum. If zero, the default is unchanged.
+	MaxCountScale float64
+	// If non-nil, rand is a source of random numbers. Otherwise a default
+	// pseudo-random source will be used.
+	Rand *rand.Rand
+	// If non-nil, the Values function generates a slice of arbitrary
+	// reflect.Values that are congruent with the arguments to the function
+	// being tested. Otherwise, the top-level Values function is used
+	// to generate them.
+	Values func([]reflect.Value, *rand.Rand)
+}
+
+var defaultConfig Config
+
+// getRand returns the *rand.Rand to use for a given Config.
+func (c *Config) getRand() *rand.Rand {
+	if c.Rand == nil {
+		return rand.New(rand.NewSource(0))
+	}
+	return c.Rand
+}
+
+// getMaxCount returns the maximum number of iterations to run for a given
+// Config.
+func (c *Config) getMaxCount() (maxCount int) {
+	maxCount = c.MaxCount
+	if maxCount == 0 {
+		if c.MaxCountScale != 0 {
+			maxCount = int(c.MaxCountScale * float64(*defaultMaxCount))
+		} else {
+			maxCount = *defaultMaxCount
+		}
+	}
+
+	return
+}
+
+// A SetupError is the result of an error in the way that check is being
+// used, independent of the functions being tested.
+type SetupError string
+
+func (s SetupError) Error() string { return string(s) }
+
+// A CheckError is the result of Check finding an error.
+type CheckError struct {
+	Count int
+	In    []interface{}
+}
+
+func (s *CheckError) Error() string {
+	return fmt.Sprintf("#%d: failed on input %s", s.Count, toString(s.In))
+}
+
+// A CheckEqualError is the result CheckEqual finding an error.
+type CheckEqualError struct {
+	CheckError
+	Out1 []interface{}
+	Out2 []interface{}
+}
+
+func (s *CheckEqualError) Error() string {
+	return fmt.Sprintf("#%d: failed on input %s. Output 1: %s. Output 2: %s", s.Count, toString(s.In), toString(s.Out1), toString(s.Out2))
+}
+
+// Check looks for an input to f, any function that returns bool,
+// such that f returns false.  It calls f repeatedly, with arbitrary
+// values for each argument.  If f returns false on a given input,
+// Check returns that input as a *CheckError.
+// For example:
+//
+// 	func TestOddMultipleOfThree(t *testing.T) {
+// 		f := func(x int) bool {
+// 			y := OddMultipleOfThree(x)
+// 			return y%2 == 1 && y%3 == 0
+// 		}
+// 		if err := quick.Check(f, nil); err != nil {
+// 			t.Error(err)
+// 		}
+// 	}
+func Check(function interface{}, config *Config) (err error) {
+	if config == nil {
+		config = &defaultConfig
+	}
+
+	f, fType, ok := functionAndType(function)
+	if !ok {
+		err = SetupError("argument is not a function")
+		return
+	}
+
+	if fType.NumOut() != 1 {
+		err = SetupError("function returns more than one value.")
+		return
+	}
+	if fType.Out(0).Kind() != reflect.Bool {
+		err = SetupError("function does not return a bool")
+		return
+	}
+
+	arguments := make([]reflect.Value, fType.NumIn())
+	rand := config.getRand()
+	maxCount := config.getMaxCount()
+
+	for i := 0; i < maxCount; i++ {
+		err = arbitraryValues(arguments, fType, config, rand)
+		if err != nil {
+			return
+		}
+
+		if !f.Call(arguments)[0].Bool() {
+			err = &CheckError{i + 1, toInterfaces(arguments)}
+			return
+		}
+	}
+
+	return
+}
+
+// CheckEqual looks for an input on which f and g return different results.
+// It calls f and g repeatedly with arbitrary values for each argument.
+// If f and g return different answers, CheckEqual returns a *CheckEqualError
+// describing the input and the outputs.
+func CheckEqual(f, g interface{}, config *Config) (err error) {
+	if config == nil {
+		config = &defaultConfig
+	}
+
+	x, xType, ok := functionAndType(f)
+	if !ok {
+		err = SetupError("f is not a function")
+		return
+	}
+	y, yType, ok := functionAndType(g)
+	if !ok {
+		err = SetupError("g is not a function")
+		return
+	}
+
+	if xType != yType {
+		err = SetupError("functions have different types")
+		return
+	}
+
+	arguments := make([]reflect.Value, xType.NumIn())
+	rand := config.getRand()
+	maxCount := config.getMaxCount()
+
+	for i := 0; i < maxCount; i++ {
+		err = arbitraryValues(arguments, xType, config, rand)
+		if err != nil {
+			return
+		}
+
+		xOut := toInterfaces(x.Call(arguments))
+		yOut := toInterfaces(y.Call(arguments))
+
+		if !reflect.DeepEqual(xOut, yOut) {
+			err = &CheckEqualError{CheckError{i + 1, toInterfaces(arguments)}, xOut, yOut}
+			return
+		}
+	}
+
+	return
+}
+
+// arbitraryValues writes Values to args such that args contains Values
+// suitable for calling f.
+func arbitraryValues(args []reflect.Value, f reflect.Type, config *Config, rand *rand.Rand) (err error) {
+	if config.Values != nil {
+		config.Values(args, rand)
+		return
+	}
+
+	for j := 0; j < len(args); j++ {
+		var ok bool
+		args[j], ok = Value(f.In(j), rand)
+		if !ok {
+			err = SetupError(fmt.Sprintf("cannot create arbitrary value of type %s for argument %d", f.In(j), j))
+			return
+		}
+	}
+
+	return
+}
+
+func functionAndType(f interface{}) (v reflect.Value, t reflect.Type, ok bool) {
+	v = reflect.ValueOf(f)
+	ok = v.Kind() == reflect.Func
+	if !ok {
+		return
+	}
+	t = v.Type()
+	return
+}
+
+func toInterfaces(values []reflect.Value) []interface{} {
+	ret := make([]interface{}, len(values))
+	for i, v := range values {
+		ret[i] = v.Interface()
+	}
+	return ret
+}
+
+func toString(interfaces []interface{}) string {
+	s := make([]string, len(interfaces))
+	for i, v := range interfaces {
+		s[i] = fmt.Sprintf("%#v", v)
+	}
+	return strings.Join(s, ", ")
+}
diff --git a/third_party/gofrontend/libgo/go/testing/quick/quick_test.go b/third_party/gofrontend/libgo/go/testing/quick/quick_test.go
new file mode 100644
index 0000000..36745ae
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/quick/quick_test.go
@@ -0,0 +1,252 @@
+// 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 quick
+
+import (
+	"math/rand"
+	"reflect"
+	"runtime"
+	"testing"
+)
+
+func fBool(a bool) bool { return a }
+
+type TestBoolAlias bool
+
+func fBoolAlias(a TestBoolAlias) TestBoolAlias { return a }
+
+func fFloat32(a float32) float32 { return a }
+
+type TestFloat32Alias float32
+
+func fFloat32Alias(a TestFloat32Alias) TestFloat32Alias { return a }
+
+func fFloat64(a float64) float64 { return a }
+
+type TestFloat64Alias float64
+
+func fFloat64Alias(a TestFloat64Alias) TestFloat64Alias { return a }
+
+func fComplex64(a complex64) complex64 { return a }
+
+type TestComplex64Alias complex64
+
+func fComplex64Alias(a TestComplex64Alias) TestComplex64Alias { return a }
+
+func fComplex128(a complex128) complex128 { return a }
+
+type TestComplex128Alias complex128
+
+func fComplex128Alias(a TestComplex128Alias) TestComplex128Alias { return a }
+
+func fInt16(a int16) int16 { return a }
+
+type TestInt16Alias int16
+
+func fInt16Alias(a TestInt16Alias) TestInt16Alias { return a }
+
+func fInt32(a int32) int32 { return a }
+
+type TestInt32Alias int32
+
+func fInt32Alias(a TestInt32Alias) TestInt32Alias { return a }
+
+func fInt64(a int64) int64 { return a }
+
+type TestInt64Alias int64
+
+func fInt64Alias(a TestInt64Alias) TestInt64Alias { return a }
+
+func fInt8(a int8) int8 { return a }
+
+type TestInt8Alias int8
+
+func fInt8Alias(a TestInt8Alias) TestInt8Alias { return a }
+
+func fInt(a int) int { return a }
+
+type TestIntAlias int
+
+func fIntAlias(a TestIntAlias) TestIntAlias { return a }
+
+func fMap(a map[int]int) map[int]int { return a }
+
+type TestMapAlias map[int]int
+
+func fMapAlias(a TestMapAlias) TestMapAlias { return a }
+
+func fSlice(a []byte) []byte { return a }
+
+type TestSliceAlias []byte
+
+func fSliceAlias(a TestSliceAlias) TestSliceAlias { return a }
+
+func fString(a string) string { return a }
+
+type TestStringAlias string
+
+func fStringAlias(a TestStringAlias) TestStringAlias { return a }
+
+type TestStruct struct {
+	A int
+	B string
+}
+
+func fStruct(a TestStruct) TestStruct { return a }
+
+type TestStructAlias TestStruct
+
+func fStructAlias(a TestStructAlias) TestStructAlias { return a }
+
+func fUint16(a uint16) uint16 { return a }
+
+type TestUint16Alias uint16
+
+func fUint16Alias(a TestUint16Alias) TestUint16Alias { return a }
+
+func fUint32(a uint32) uint32 { return a }
+
+type TestUint32Alias uint32
+
+func fUint32Alias(a TestUint32Alias) TestUint32Alias { return a }
+
+func fUint64(a uint64) uint64 { return a }
+
+type TestUint64Alias uint64
+
+func fUint64Alias(a TestUint64Alias) TestUint64Alias { return a }
+
+func fUint8(a uint8) uint8 { return a }
+
+type TestUint8Alias uint8
+
+func fUint8Alias(a TestUint8Alias) TestUint8Alias { return a }
+
+func fUint(a uint) uint { return a }
+
+type TestUintAlias uint
+
+func fUintAlias(a TestUintAlias) TestUintAlias { return a }
+
+func fUintptr(a uintptr) uintptr { return a }
+
+type TestUintptrAlias uintptr
+
+func fUintptrAlias(a TestUintptrAlias) TestUintptrAlias { return a }
+
+func fIntptr(a *int) *int {
+	b := *a
+	return &b
+}
+
+type TestIntptrAlias *int
+
+func fIntptrAlias(a TestIntptrAlias) TestIntptrAlias { return a }
+
+func reportError(property string, err error, t *testing.T) {
+	if err != nil {
+		t.Errorf("%s: %s", property, err)
+	}
+}
+
+func TestCheckEqual(t *testing.T) {
+	reportError("fBool", CheckEqual(fBool, fBool, nil), t)
+	reportError("fBoolAlias", CheckEqual(fBoolAlias, fBoolAlias, nil), t)
+	reportError("fFloat32", CheckEqual(fFloat32, fFloat32, nil), t)
+	reportError("fFloat32Alias", CheckEqual(fFloat32Alias, fFloat32Alias, nil), t)
+	reportError("fFloat64", CheckEqual(fFloat64, fFloat64, nil), t)
+	reportError("fFloat64Alias", CheckEqual(fFloat64Alias, fFloat64Alias, nil), t)
+	if runtime.GOARCH != "alpha" {
+		reportError("fComplex64", CheckEqual(fComplex64, fComplex64, nil), t)
+		reportError("fComplex64Alias", CheckEqual(fComplex64Alias, fComplex64Alias, nil), t)
+		reportError("fComplex128", CheckEqual(fComplex128, fComplex128, nil), t)
+		reportError("fComplex128Alias", CheckEqual(fComplex128Alias, fComplex128Alias, nil), t)
+	}
+	reportError("fInt16", CheckEqual(fInt16, fInt16, nil), t)
+	reportError("fInt16Alias", CheckEqual(fInt16Alias, fInt16Alias, nil), t)
+	reportError("fInt32", CheckEqual(fInt32, fInt32, nil), t)
+	reportError("fInt32Alias", CheckEqual(fInt32Alias, fInt32Alias, nil), t)
+	reportError("fInt64", CheckEqual(fInt64, fInt64, nil), t)
+	reportError("fInt64Alias", CheckEqual(fInt64Alias, fInt64Alias, nil), t)
+	reportError("fInt8", CheckEqual(fInt8, fInt8, nil), t)
+	reportError("fInt8Alias", CheckEqual(fInt8Alias, fInt8Alias, nil), t)
+	reportError("fInt", CheckEqual(fInt, fInt, nil), t)
+	reportError("fIntAlias", CheckEqual(fIntAlias, fIntAlias, nil), t)
+	reportError("fInt32", CheckEqual(fInt32, fInt32, nil), t)
+	reportError("fInt32Alias", CheckEqual(fInt32Alias, fInt32Alias, nil), t)
+	reportError("fMap", CheckEqual(fMap, fMap, nil), t)
+	reportError("fMapAlias", CheckEqual(fMapAlias, fMapAlias, nil), t)
+	reportError("fSlice", CheckEqual(fSlice, fSlice, nil), t)
+	reportError("fSliceAlias", CheckEqual(fSliceAlias, fSliceAlias, nil), t)
+	reportError("fString", CheckEqual(fString, fString, nil), t)
+	reportError("fStringAlias", CheckEqual(fStringAlias, fStringAlias, nil), t)
+	reportError("fStruct", CheckEqual(fStruct, fStruct, nil), t)
+	reportError("fStructAlias", CheckEqual(fStructAlias, fStructAlias, nil), t)
+	reportError("fUint16", CheckEqual(fUint16, fUint16, nil), t)
+	reportError("fUint16Alias", CheckEqual(fUint16Alias, fUint16Alias, nil), t)
+	reportError("fUint32", CheckEqual(fUint32, fUint32, nil), t)
+	reportError("fUint32Alias", CheckEqual(fUint32Alias, fUint32Alias, nil), t)
+	reportError("fUint64", CheckEqual(fUint64, fUint64, nil), t)
+	reportError("fUint64Alias", CheckEqual(fUint64Alias, fUint64Alias, nil), t)
+	reportError("fUint8", CheckEqual(fUint8, fUint8, nil), t)
+	reportError("fUint8Alias", CheckEqual(fUint8Alias, fUint8Alias, nil), t)
+	reportError("fUint", CheckEqual(fUint, fUint, nil), t)
+	reportError("fUintAlias", CheckEqual(fUintAlias, fUintAlias, nil), t)
+	reportError("fUintptr", CheckEqual(fUintptr, fUintptr, nil), t)
+	reportError("fUintptrAlias", CheckEqual(fUintptrAlias, fUintptrAlias, nil), t)
+	reportError("fIntptr", CheckEqual(fIntptr, fIntptr, nil), t)
+	reportError("fIntptrAlias", CheckEqual(fIntptrAlias, fIntptrAlias, nil), t)
+}
+
+// This tests that ArbitraryValue is working by checking that all the arbitrary
+// values of type MyStruct have x = 42.
+type myStruct struct {
+	x int
+}
+
+func (m myStruct) Generate(r *rand.Rand, _ int) reflect.Value {
+	return reflect.ValueOf(myStruct{x: 42})
+}
+
+func myStructProperty(in myStruct) bool { return in.x == 42 }
+
+func TestCheckProperty(t *testing.T) {
+	reportError("myStructProperty", Check(myStructProperty, nil), t)
+}
+
+func TestFailure(t *testing.T) {
+	f := func(x int) bool { return false }
+	err := Check(f, nil)
+	if err == nil {
+		t.Errorf("Check didn't return an error")
+	}
+	if _, ok := err.(*CheckError); !ok {
+		t.Errorf("Error was not a CheckError: %s", err)
+	}
+
+	err = CheckEqual(fUint, fUint32, nil)
+	if err == nil {
+		t.Errorf("#1 CheckEqual didn't return an error")
+	}
+	if _, ok := err.(SetupError); !ok {
+		t.Errorf("#1 Error was not a SetupError: %s", err)
+	}
+
+	err = CheckEqual(func(x, y int) {}, func(x int) {}, nil)
+	if err == nil {
+		t.Errorf("#2 CheckEqual didn't return an error")
+	}
+	if _, ok := err.(SetupError); !ok {
+		t.Errorf("#2 Error was not a SetupError: %s", err)
+	}
+
+	err = CheckEqual(func(x int) int { return 0 }, func(x int) int32 { return 0 }, nil)
+	if err == nil {
+		t.Errorf("#3 CheckEqual didn't return an error")
+	}
+	if _, ok := err.(SetupError); !ok {
+		t.Errorf("#3 Error was not a SetupError: %s", err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/testing/testing.go b/third_party/gofrontend/libgo/go/testing/testing.go
new file mode 100644
index 0000000..8078ba7
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/testing/testing.go
@@ -0,0 +1,657 @@
+// 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 testing provides support for automated testing of Go packages.
+// It is intended to be used in concert with the ``go test'' command, which automates
+// execution of any function of the form
+//     func TestXxx(*testing.T)
+// where Xxx can be any alphanumeric string (but the first letter must not be in
+// [a-z]) and serves to identify the test routine.
+//
+// Within these functions, use the Error, Fail or related methods to signal failure.
+//
+// To write a new test suite, create a file whose name ends _test.go that
+// contains the TestXxx functions as described here. Put the file in the same
+// package as the one being tested. The file will be excluded from regular
+// package builds but will be included when the ``go test'' command is run.
+// For more detail, run ``go help test'' and ``go help testflag''.
+//
+// Tests and benchmarks may be skipped if not applicable with a call to
+// the Skip method of *T and *B:
+//     func TestTimeConsuming(t *testing.T) {
+//         if testing.Short() {
+//             t.Skip("skipping test in short mode.")
+//         }
+//         ...
+//     }
+//
+// Benchmarks
+//
+// Functions of the form
+//     func BenchmarkXxx(*testing.B)
+// are considered benchmarks, and are executed by the "go test" command when
+// its -bench flag is provided. Benchmarks are run sequentially.
+//
+// For a description of the testing flags, see
+// http://golang.org/cmd/go/#hdr-Description_of_testing_flags.
+//
+// A sample benchmark function looks like this:
+//     func BenchmarkHello(b *testing.B) {
+//         for i := 0; i < b.N; i++ {
+//             fmt.Sprintf("hello")
+//         }
+//     }
+//
+// The benchmark function must run the target code b.N times.
+// The benchmark package will vary b.N until the benchmark function lasts
+// long enough to be timed reliably.  The output
+//     BenchmarkHello    10000000    282 ns/op
+// means that the loop ran 10000000 times at a speed of 282 ns per loop.
+//
+// If a benchmark needs some expensive setup before running, the timer
+// may be reset:
+//
+//     func BenchmarkBigLen(b *testing.B) {
+//         big := NewBig()
+//         b.ResetTimer()
+//         for i := 0; i < b.N; i++ {
+//             big.Len()
+//         }
+//     }
+//
+// If a benchmark needs to test performance in a parallel setting, it may use
+// the RunParallel helper function; such benchmarks are intended to be used with
+// the go test -cpu flag:
+//
+//     func BenchmarkTemplateParallel(b *testing.B) {
+//         templ := template.Must(template.New("test").Parse("Hello, {{.}}!"))
+//         b.RunParallel(func(pb *testing.PB) {
+//             var buf bytes.Buffer
+//             for pb.Next() {
+//                 buf.Reset()
+//                 templ.Execute(&buf, "World")
+//             }
+//         })
+//     }
+//
+// Examples
+//
+// The package also runs and verifies example code. Example functions may
+// include a concluding line comment that begins with "Output:" and is compared with
+// the standard output of the function when the tests are run. (The comparison
+// ignores leading and trailing space.) These are examples of an example:
+//
+//     func ExampleHello() {
+//             fmt.Println("hello")
+//             // Output: hello
+//     }
+//
+//     func ExampleSalutations() {
+//             fmt.Println("hello, and")
+//             fmt.Println("goodbye")
+//             // Output:
+//             // hello, and
+//             // goodbye
+//     }
+//
+// Example functions without output comments are compiled but not executed.
+//
+// The naming convention to declare examples for the package, a function F, a type T and
+// method M on type T are:
+//
+//     func Example() { ... }
+//     func ExampleF() { ... }
+//     func ExampleT() { ... }
+//     func ExampleT_M() { ... }
+//
+// Multiple example functions for a package/type/function/method may be provided by
+// appending a distinct suffix to the name. The suffix must start with a
+// lower-case letter.
+//
+//     func Example_suffix() { ... }
+//     func ExampleF_suffix() { ... }
+//     func ExampleT_suffix() { ... }
+//     func ExampleT_M_suffix() { ... }
+//
+// The entire test file is presented as the example when it contains a single
+// example function, at least one other function, type, variable, or constant
+// declaration, and no test or benchmark functions.
+package testing
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"os"
+	"runtime"
+	"runtime/pprof"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+var (
+	// The short flag requests that tests run more quickly, but its functionality
+	// is provided by test writers themselves.  The testing package is just its
+	// home.  The all.bash installation script sets it to make installation more
+	// efficient, but by default the flag is off so a plain "go test" will do a
+	// full test of the package.
+	short = flag.Bool("test.short", false, "run smaller test suite to save time")
+
+	// The directory in which to create profile files and the like. When run from
+	// "go test", the binary always runs in the source directory for the package;
+	// this flag lets "go test" tell the binary to write the files in the directory where
+	// the "go test" command is run.
+	outputDir = flag.String("test.outputdir", "", "directory in which to write profiles")
+
+	// Report as tests are run; default is silent for success.
+	chatty           = flag.Bool("test.v", false, "verbose: print additional output")
+	coverProfile     = flag.String("test.coverprofile", "", "write a coverage profile to the named file after execution")
+	match            = flag.String("test.run", "", "regular expression to select tests and examples to run")
+	memProfile       = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
+	memProfileRate   = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
+	cpuProfile       = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
+	blockProfile     = flag.String("test.blockprofile", "", "write a goroutine blocking profile to the named file after execution")
+	blockProfileRate = flag.Int("test.blockprofilerate", 1, "if >= 0, calls runtime.SetBlockProfileRate()")
+	timeout          = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
+	cpuListStr       = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+	parallel         = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+
+	haveExamples bool // are there examples?
+
+	cpuList []int
+)
+
+// common holds the elements common between T and B and
+// captures common methods such as Errorf.
+type common struct {
+	mu       sync.RWMutex // guards output and failed
+	output   []byte       // Output generated by test or benchmark.
+	failed   bool         // Test or benchmark has failed.
+	skipped  bool         // Test of benchmark has been skipped.
+	finished bool
+
+	start    time.Time // Time test or benchmark started
+	duration time.Duration
+	self     interface{}      // To be sent on signal channel when done.
+	signal   chan interface{} // Output for serial tests.
+}
+
+// Short reports whether the -test.short flag is set.
+func Short() bool {
+	return *short
+}
+
+// Verbose reports whether the -test.v flag is set.
+func Verbose() bool {
+	return *chatty
+}
+
+// decorate prefixes the string with the file and line of the call site
+// and inserts the final newline if needed and indentation tabs for formatting.
+func decorate(s string) string {
+	_, file, line, ok := runtime.Caller(3) // decorate + log + public function.
+	if ok {
+		// Truncate file name at last file name separator.
+		if index := strings.LastIndex(file, "/"); index >= 0 {
+			file = file[index+1:]
+		} else if index = strings.LastIndex(file, "\\"); index >= 0 {
+			file = file[index+1:]
+		}
+	} else {
+		file = "???"
+		line = 1
+	}
+	buf := new(bytes.Buffer)
+	// Every line is indented at least one tab.
+	buf.WriteByte('\t')
+	fmt.Fprintf(buf, "%s:%d: ", file, line)
+	lines := strings.Split(s, "\n")
+	if l := len(lines); l > 1 && lines[l-1] == "" {
+		lines = lines[:l-1]
+	}
+	for i, line := range lines {
+		if i > 0 {
+			// Second and subsequent lines are indented an extra tab.
+			buf.WriteString("\n\t\t")
+		}
+		buf.WriteString(line)
+	}
+	buf.WriteByte('\n')
+	return buf.String()
+}
+
+// TB is the interface common to T and B.
+type TB interface {
+	Error(args ...interface{})
+	Errorf(format string, args ...interface{})
+	Fail()
+	FailNow()
+	Failed() bool
+	Fatal(args ...interface{})
+	Fatalf(format string, args ...interface{})
+	Log(args ...interface{})
+	Logf(format string, args ...interface{})
+	Skip(args ...interface{})
+	SkipNow()
+	Skipf(format string, args ...interface{})
+	Skipped() bool
+
+	// A private method to prevent users implementing the
+	// interface and so future additions to it will not
+	// violate Go 1 compatibility.
+	private()
+}
+
+var _ TB = (*T)(nil)
+var _ TB = (*B)(nil)
+
+// T is a type passed to Test functions to manage test state and support formatted test logs.
+// Logs are accumulated during execution and dumped to standard error when done.
+type T struct {
+	common
+	name          string    // Name of test.
+	startParallel chan bool // Parallel tests will wait on this.
+}
+
+func (c *common) private() {}
+
+// Fail marks the function as having failed but continues execution.
+func (c *common) Fail() {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	c.failed = true
+}
+
+// Failed reports whether the function has failed.
+func (c *common) Failed() bool {
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+	return c.failed
+}
+
+// FailNow marks the function as having failed and stops its execution.
+// Execution will continue at the next test or benchmark.
+// FailNow must be called from the goroutine running the
+// test or benchmark function, not from other goroutines
+// created during the test. Calling FailNow does not stop
+// those other goroutines.
+func (c *common) FailNow() {
+	c.Fail()
+
+	// Calling runtime.Goexit will exit the goroutine, which
+	// will run the deferred functions in this goroutine,
+	// which will eventually run the deferred lines in tRunner,
+	// which will signal to the test loop that this test is done.
+	//
+	// A previous version of this code said:
+	//
+	//	c.duration = ...
+	//	c.signal <- c.self
+	//	runtime.Goexit()
+	//
+	// This previous version duplicated code (those lines are in
+	// tRunner no matter what), but worse the goroutine teardown
+	// implicit in runtime.Goexit was not guaranteed to complete
+	// before the test exited.  If a test deferred an important cleanup
+	// function (like removing temporary files), there was no guarantee
+	// it would run on a test failure.  Because we send on c.signal during
+	// a top-of-stack deferred function now, we know that the send
+	// only happens after any other stacked defers have completed.
+	c.finished = true
+	runtime.Goexit()
+}
+
+// log generates the output. It's always at the same stack depth.
+func (c *common) log(s string) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	c.output = append(c.output, decorate(s)...)
+}
+
+// Log formats its arguments using default formatting, analogous to Println,
+// and records the text in the error log. The text will be printed only if
+// the test fails or the -test.v flag is set.
+func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
+
+// Logf formats its arguments according to the format, analogous to Printf,
+// and records the text in the error log. The text will be printed only if
+// the test fails or the -test.v flag is set.
+func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
+
+// Error is equivalent to Log followed by Fail.
+func (c *common) Error(args ...interface{}) {
+	c.log(fmt.Sprintln(args...))
+	c.Fail()
+}
+
+// Errorf is equivalent to Logf followed by Fail.
+func (c *common) Errorf(format string, args ...interface{}) {
+	c.log(fmt.Sprintf(format, args...))
+	c.Fail()
+}
+
+// Fatal is equivalent to Log followed by FailNow.
+func (c *common) Fatal(args ...interface{}) {
+	c.log(fmt.Sprintln(args...))
+	c.FailNow()
+}
+
+// Fatalf is equivalent to Logf followed by FailNow.
+func (c *common) Fatalf(format string, args ...interface{}) {
+	c.log(fmt.Sprintf(format, args...))
+	c.FailNow()
+}
+
+// Skip is equivalent to Log followed by SkipNow.
+func (c *common) Skip(args ...interface{}) {
+	c.log(fmt.Sprintln(args...))
+	c.SkipNow()
+}
+
+// Skipf is equivalent to Logf followed by SkipNow.
+func (c *common) Skipf(format string, args ...interface{}) {
+	c.log(fmt.Sprintf(format, args...))
+	c.SkipNow()
+}
+
+// SkipNow marks the test as having been skipped and stops its execution.
+// Execution will continue at the next test or benchmark. See also FailNow.
+// SkipNow must be called from the goroutine running the test, not from
+// other goroutines created during the test. Calling SkipNow does not stop
+// those other goroutines.
+func (c *common) SkipNow() {
+	c.skip()
+	c.finished = true
+	runtime.Goexit()
+}
+
+func (c *common) skip() {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	c.skipped = true
+}
+
+// Skipped reports whether the test was skipped.
+func (c *common) Skipped() bool {
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+	return c.skipped
+}
+
+// Parallel signals that this test is to be run in parallel with (and only with)
+// other parallel tests.
+func (t *T) Parallel() {
+	t.signal <- (*T)(nil) // Release main testing loop
+	<-t.startParallel     // Wait for serial tests to finish
+	// Assuming Parallel is the first thing a test does, which is reasonable,
+	// reinitialize the test's start time because it's actually starting now.
+	t.start = time.Now()
+}
+
+// An internal type but exported because it is cross-package; part of the implementation
+// of the "go test" command.
+type InternalTest struct {
+	Name string
+	F    func(*T)
+}
+
+func tRunner(t *T, test *InternalTest) {
+	// When this goroutine is done, either because test.F(t)
+	// returned normally or because a test failure triggered
+	// a call to runtime.Goexit, record the duration and send
+	// a signal saying that the test is done.
+	defer func() {
+		t.duration = time.Now().Sub(t.start)
+		// If the test panicked, print any test output before dying.
+		err := recover()
+		if !t.finished && err == nil {
+			err = fmt.Errorf("test executed panic(nil) or runtime.Goexit")
+		}
+		if err != nil {
+			t.Fail()
+			t.report()
+			panic(err)
+		}
+		t.signal <- t
+	}()
+
+	t.start = time.Now()
+	test.F(t)
+	t.finished = true
+}
+
+// An internal function but exported because it is cross-package; part of the implementation
+// of the "go test" command.
+func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
+	flag.Parse()
+	parseCpuList()
+
+	before()
+	startAlarm()
+	haveExamples = len(examples) > 0
+	testOk := RunTests(matchString, tests)
+	exampleOk := RunExamples(matchString, examples)
+	stopAlarm()
+	if !testOk || !exampleOk {
+		fmt.Println("FAIL")
+		after()
+		os.Exit(1)
+	}
+	fmt.Println("PASS")
+	RunBenchmarks(matchString, benchmarks)
+	after()
+}
+
+func (t *T) report() {
+	tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
+	format := "--- %s: %s %s\n%s"
+	if t.Failed() {
+		fmt.Printf(format, "FAIL", t.name, tstr, t.output)
+	} else if *chatty {
+		if t.Skipped() {
+			fmt.Printf(format, "SKIP", t.name, tstr, t.output)
+		} else {
+			fmt.Printf(format, "PASS", t.name, tstr, t.output)
+		}
+	}
+}
+
+func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
+	ok = true
+	if len(tests) == 0 && !haveExamples {
+		fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
+		return
+	}
+	for _, procs := range cpuList {
+		runtime.GOMAXPROCS(procs)
+		// We build a new channel tree for each run of the loop.
+		// collector merges in one channel all the upstream signals from parallel tests.
+		// If all tests pump to the same channel, a bug can occur where a test
+		// kicks off a goroutine that Fails, yet the test still delivers a completion signal,
+		// which skews the counting.
+		var collector = make(chan interface{})
+
+		numParallel := 0
+		startParallel := make(chan bool)
+
+		for i := 0; i < len(tests); i++ {
+			matched, err := matchString(*match, tests[i].Name)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err)
+				os.Exit(1)
+			}
+			if !matched {
+				continue
+			}
+			testName := tests[i].Name
+			if procs != 1 {
+				testName = fmt.Sprintf("%s-%d", tests[i].Name, procs)
+			}
+			t := &T{
+				common: common{
+					signal: make(chan interface{}),
+				},
+				name:          testName,
+				startParallel: startParallel,
+			}
+			t.self = t
+			if *chatty {
+				fmt.Printf("=== RUN %s\n", t.name)
+			}
+			go tRunner(t, &tests[i])
+			out := (<-t.signal).(*T)
+			if out == nil { // Parallel run.
+				go func() {
+					collector <- <-t.signal
+				}()
+				numParallel++
+				continue
+			}
+			t.report()
+			ok = ok && !out.Failed()
+		}
+
+		running := 0
+		for numParallel+running > 0 {
+			if running < *parallel && numParallel > 0 {
+				startParallel <- true
+				running++
+				numParallel--
+				continue
+			}
+			t := (<-collector).(*T)
+			t.report()
+			ok = ok && !t.Failed()
+			running--
+		}
+	}
+	return
+}
+
+// before runs before all testing.
+func before() {
+	if *memProfileRate > 0 {
+		runtime.MemProfileRate = *memProfileRate
+	}
+	if *cpuProfile != "" {
+		f, err := os.Create(toOutputDir(*cpuProfile))
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: %s", err)
+			return
+		}
+		if err := pprof.StartCPUProfile(f); err != nil {
+			fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s", err)
+			f.Close()
+			return
+		}
+		// Could save f so after can call f.Close; not worth the effort.
+	}
+	if *blockProfile != "" && *blockProfileRate >= 0 {
+		runtime.SetBlockProfileRate(*blockProfileRate)
+	}
+	if *coverProfile != "" && cover.Mode == "" {
+		fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n")
+		os.Exit(2)
+	}
+}
+
+// after runs after all testing.
+func after() {
+	if *cpuProfile != "" {
+		pprof.StopCPUProfile() // flushes profile to disk
+	}
+	if *memProfile != "" {
+		f, err := os.Create(toOutputDir(*memProfile))
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+			os.Exit(2)
+		}
+		if err = pprof.WriteHeapProfile(f); err != nil {
+			fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *memProfile, err)
+			os.Exit(2)
+		}
+		f.Close()
+	}
+	if *blockProfile != "" && *blockProfileRate >= 0 {
+		f, err := os.Create(toOutputDir(*blockProfile))
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+			os.Exit(2)
+		}
+		if err = pprof.Lookup("block").WriteTo(f, 0); err != nil {
+			fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
+			os.Exit(2)
+		}
+		f.Close()
+	}
+	if cover.Mode != "" {
+		coverReport()
+	}
+}
+
+// toOutputDir returns the file name relocated, if required, to outputDir.
+// Simple implementation to avoid pulling in path/filepath.
+func toOutputDir(path string) string {
+	if *outputDir == "" || path == "" {
+		return path
+	}
+	if runtime.GOOS == "windows" {
+		// On Windows, it's clumsy, but we can be almost always correct
+		// by just looking for a drive letter and a colon.
+		// Absolute paths always have a drive letter (ignoring UNC).
+		// Problem: if path == "C:A" and outputdir == "C:\Go" it's unclear
+		// what to do, but even then path/filepath doesn't help.
+		// TODO: Worth doing better? Probably not, because we're here only
+		// under the management of go test.
+		if len(path) >= 2 {
+			letter, colon := path[0], path[1]
+			if ('a' <= letter && letter <= 'z' || 'A' <= letter && letter <= 'Z') && colon == ':' {
+				// If path starts with a drive letter we're stuck with it regardless.
+				return path
+			}
+		}
+	}
+	if os.IsPathSeparator(path[0]) {
+		return path
+	}
+	return fmt.Sprintf("%s%c%s", *outputDir, os.PathSeparator, path)
+}
+
+var timer *time.Timer
+
+// startAlarm starts an alarm if requested.
+func startAlarm() {
+	if *timeout > 0 {
+		timer = time.AfterFunc(*timeout, func() {
+			panic(fmt.Sprintf("test timed out after %v", *timeout))
+		})
+	}
+}
+
+// stopAlarm turns off the alarm.
+func stopAlarm() {
+	if *timeout > 0 {
+		timer.Stop()
+	}
+}
+
+func parseCpuList() {
+	for _, val := range strings.Split(*cpuListStr, ",") {
+		val = strings.TrimSpace(val)
+		if val == "" {
+			continue
+		}
+		cpu, err := strconv.Atoi(val)
+		if err != nil || cpu <= 0 {
+			fmt.Fprintf(os.Stderr, "testing: invalid value %q for -test.cpu\n", val)
+			os.Exit(1)
+		}
+		cpuList = append(cpuList, cpu)
+	}
+	if cpuList == nil {
+		cpuList = append(cpuList, runtime.GOMAXPROCS(-1))
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/text/scanner/scanner.go b/third_party/gofrontend/libgo/go/text/scanner/scanner.go
new file mode 100644
index 0000000..db7ca73
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/scanner/scanner.go
@@ -0,0 +1,674 @@
+// 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 scanner provides a scanner and tokenizer for UTF-8-encoded text.
+// It takes an io.Reader providing the source, which then can be tokenized
+// through repeated calls to the Scan function.  For compatibility with
+// existing tools, the NUL character is not allowed. If the first character
+// in the source is a UTF-8 encoded byte order mark (BOM), it is discarded.
+//
+// By default, a Scanner skips white space and Go comments and recognizes all
+// literals as defined by the Go language specification.  It may be
+// customized to recognize only a subset of those literals and to recognize
+// different white space characters.
+//
+// Basic usage pattern:
+//
+//	var s scanner.Scanner
+//	s.Init(src)
+//	tok := s.Scan()
+//	for tok != scanner.EOF {
+//		// do something with tok
+//		tok = s.Scan()
+//	}
+//
+package scanner
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"unicode"
+	"unicode/utf8"
+)
+
+// TODO(gri): Consider changing this to use the new (token) Position package.
+
+// A source position is represented by a Position value.
+// A position is valid if Line > 0.
+type Position struct {
+	Filename string // filename, if any
+	Offset   int    // byte offset, starting at 0
+	Line     int    // line number, starting at 1
+	Column   int    // column number, starting at 1 (character count per line)
+}
+
+// IsValid returns true if the position is valid.
+func (pos *Position) IsValid() bool { return pos.Line > 0 }
+
+func (pos Position) String() string {
+	s := pos.Filename
+	if pos.IsValid() {
+		if s != "" {
+			s += ":"
+		}
+		s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
+	}
+	if s == "" {
+		s = "???"
+	}
+	return s
+}
+
+// Predefined mode bits to control recognition of tokens. For instance,
+// to configure a Scanner such that it only recognizes (Go) identifiers,
+// integers, and skips comments, set the Scanner's Mode field to:
+//
+//	ScanIdents | ScanInts | SkipComments
+//
+const (
+	ScanIdents     = 1 << -Ident
+	ScanInts       = 1 << -Int
+	ScanFloats     = 1 << -Float // includes Ints
+	ScanChars      = 1 << -Char
+	ScanStrings    = 1 << -String
+	ScanRawStrings = 1 << -RawString
+	ScanComments   = 1 << -Comment
+	SkipComments   = 1 << -skipComment // if set with ScanComments, comments become white space
+	GoTokens       = ScanIdents | ScanFloats | ScanChars | ScanStrings | ScanRawStrings | ScanComments | SkipComments
+)
+
+// The result of Scan is one of the following tokens or a Unicode character.
+const (
+	EOF = -(iota + 1)
+	Ident
+	Int
+	Float
+	Char
+	String
+	RawString
+	Comment
+	skipComment
+)
+
+var tokenString = map[rune]string{
+	EOF:       "EOF",
+	Ident:     "Ident",
+	Int:       "Int",
+	Float:     "Float",
+	Char:      "Char",
+	String:    "String",
+	RawString: "RawString",
+	Comment:   "Comment",
+}
+
+// TokenString returns a printable string for a token or Unicode character.
+func TokenString(tok rune) string {
+	if s, found := tokenString[tok]; found {
+		return s
+	}
+	return fmt.Sprintf("%q", string(tok))
+}
+
+// GoWhitespace is the default value for the Scanner's Whitespace field.
+// Its value selects Go's white space characters.
+const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '
+
+const bufLen = 1024 // at least utf8.UTFMax
+
+// A Scanner implements reading of Unicode characters and tokens from an io.Reader.
+type Scanner struct {
+	// Input
+	src io.Reader
+
+	// Source buffer
+	srcBuf [bufLen + 1]byte // +1 for sentinel for common case of s.next()
+	srcPos int              // reading position (srcBuf index)
+	srcEnd int              // source end (srcBuf index)
+
+	// Source position
+	srcBufOffset int // byte offset of srcBuf[0] in source
+	line         int // line count
+	column       int // character count
+	lastLineLen  int // length of last line in characters (for correct column reporting)
+	lastCharLen  int // length of last character in bytes
+
+	// Token text buffer
+	// Typically, token text is stored completely in srcBuf, but in general
+	// the token text's head may be buffered in tokBuf while the token text's
+	// tail is stored in srcBuf.
+	tokBuf bytes.Buffer // token text head that is not in srcBuf anymore
+	tokPos int          // token text tail position (srcBuf index); valid if >= 0
+	tokEnd int          // token text tail end (srcBuf index)
+
+	// One character look-ahead
+	ch rune // character before current srcPos
+
+	// Error is called for each error encountered. If no Error
+	// function is set, the error is reported to os.Stderr.
+	Error func(s *Scanner, msg string)
+
+	// ErrorCount is incremented by one for each error encountered.
+	ErrorCount int
+
+	// The Mode field controls which tokens are recognized. For instance,
+	// to recognize Ints, set the ScanInts bit in Mode. The field may be
+	// changed at any time.
+	Mode uint
+
+	// The Whitespace field controls which characters are recognized
+	// as white space. To recognize a character ch <= ' ' as white space,
+	// set the ch'th bit in Whitespace (the Scanner's behavior is undefined
+	// for values ch > ' '). The field may be changed at any time.
+	Whitespace uint64
+
+	// Start position of most recently scanned token; set by Scan.
+	// Calling Init or Next invalidates the position (Line == 0).
+	// The Filename field is always left untouched by the Scanner.
+	// If an error is reported (via Error) and Position is invalid,
+	// the scanner is not inside a token. Call Pos to obtain an error
+	// position in that case.
+	Position
+}
+
+// Init initializes a Scanner with a new source and returns s.
+// Error is set to nil, ErrorCount is set to 0, Mode is set to GoTokens,
+// and Whitespace is set to GoWhitespace.
+func (s *Scanner) Init(src io.Reader) *Scanner {
+	s.src = src
+
+	// initialize source buffer
+	// (the first call to next() will fill it by calling src.Read)
+	s.srcBuf[0] = utf8.RuneSelf // sentinel
+	s.srcPos = 0
+	s.srcEnd = 0
+
+	// initialize source position
+	s.srcBufOffset = 0
+	s.line = 1
+	s.column = 0
+	s.lastLineLen = 0
+	s.lastCharLen = 0
+
+	// initialize token text buffer
+	// (required for first call to next()).
+	s.tokPos = -1
+
+	// initialize one character look-ahead
+	s.ch = -1 // no char read yet
+
+	// initialize public fields
+	s.Error = nil
+	s.ErrorCount = 0
+	s.Mode = GoTokens
+	s.Whitespace = GoWhitespace
+	s.Line = 0 // invalidate token position
+
+	return s
+}
+
+// next reads and returns the next Unicode character. It is designed such
+// that only a minimal amount of work needs to be done in the common ASCII
+// case (one test to check for both ASCII and end-of-buffer, and one test
+// to check for newlines).
+func (s *Scanner) next() rune {
+	ch, width := rune(s.srcBuf[s.srcPos]), 1
+
+	if ch >= utf8.RuneSelf {
+		// uncommon case: not ASCII or not enough bytes
+		for s.srcPos+utf8.UTFMax > s.srcEnd && !utf8.FullRune(s.srcBuf[s.srcPos:s.srcEnd]) {
+			// not enough bytes: read some more, but first
+			// save away token text if any
+			if s.tokPos >= 0 {
+				s.tokBuf.Write(s.srcBuf[s.tokPos:s.srcPos])
+				s.tokPos = 0
+				// s.tokEnd is set by Scan()
+			}
+			// move unread bytes to beginning of buffer
+			copy(s.srcBuf[0:], s.srcBuf[s.srcPos:s.srcEnd])
+			s.srcBufOffset += s.srcPos
+			// read more bytes
+			// (an io.Reader must return io.EOF when it reaches
+			// the end of what it is reading - simply returning
+			// n == 0 will make this loop retry forever; but the
+			// error is in the reader implementation in that case)
+			i := s.srcEnd - s.srcPos
+			n, err := s.src.Read(s.srcBuf[i:bufLen])
+			s.srcPos = 0
+			s.srcEnd = i + n
+			s.srcBuf[s.srcEnd] = utf8.RuneSelf // sentinel
+			if err != nil {
+				if err != io.EOF {
+					s.error(err.Error())
+				}
+				if s.srcEnd == 0 {
+					if s.lastCharLen > 0 {
+						// previous character was not EOF
+						s.column++
+					}
+					s.lastCharLen = 0
+					return EOF
+				}
+				// If err == EOF, we won't be getting more
+				// bytes; break to avoid infinite loop. If
+				// err is something else, we don't know if
+				// we can get more bytes; thus also break.
+				break
+			}
+		}
+		// at least one byte
+		ch = rune(s.srcBuf[s.srcPos])
+		if ch >= utf8.RuneSelf {
+			// uncommon case: not ASCII
+			ch, width = utf8.DecodeRune(s.srcBuf[s.srcPos:s.srcEnd])
+			if ch == utf8.RuneError && width == 1 {
+				// advance for correct error position
+				s.srcPos += width
+				s.lastCharLen = width
+				s.column++
+				s.error("illegal UTF-8 encoding")
+				return ch
+			}
+		}
+	}
+
+	// advance
+	s.srcPos += width
+	s.lastCharLen = width
+	s.column++
+
+	// special situations
+	switch ch {
+	case 0:
+		// for compatibility with other tools
+		s.error("illegal character NUL")
+	case '\n':
+		s.line++
+		s.lastLineLen = s.column
+		s.column = 0
+	}
+
+	return ch
+}
+
+// Next reads and returns the next Unicode character.
+// It returns EOF at the end of the source. It reports
+// a read error by calling s.Error, if not nil; otherwise
+// it prints an error message to os.Stderr. Next does not
+// update the Scanner's Position field; use Pos() to
+// get the current position.
+func (s *Scanner) Next() rune {
+	s.tokPos = -1 // don't collect token text
+	s.Line = 0    // invalidate token position
+	ch := s.Peek()
+	s.ch = s.next()
+	return ch
+}
+
+// Peek returns the next Unicode character in the source without advancing
+// the scanner. It returns EOF if the scanner's position is at the last
+// character of the source.
+func (s *Scanner) Peek() rune {
+	if s.ch < 0 {
+		// this code is only run for the very first character
+		s.ch = s.next()
+		if s.ch == '\uFEFF' {
+			s.ch = s.next() // ignore BOM
+		}
+	}
+	return s.ch
+}
+
+func (s *Scanner) error(msg string) {
+	s.ErrorCount++
+	if s.Error != nil {
+		s.Error(s, msg)
+		return
+	}
+	pos := s.Position
+	if !pos.IsValid() {
+		pos = s.Pos()
+	}
+	fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
+}
+
+func (s *Scanner) scanIdentifier() rune {
+	ch := s.next() // read character after first '_' or letter
+	for ch == '_' || unicode.IsLetter(ch) || unicode.IsDigit(ch) {
+		ch = s.next()
+	}
+	return ch
+}
+
+func digitVal(ch rune) int {
+	switch {
+	case '0' <= ch && ch <= '9':
+		return int(ch - '0')
+	case 'a' <= ch && ch <= 'f':
+		return int(ch - 'a' + 10)
+	case 'A' <= ch && ch <= 'F':
+		return int(ch - 'A' + 10)
+	}
+	return 16 // larger than any legal digit val
+}
+
+func isDecimal(ch rune) bool { return '0' <= ch && ch <= '9' }
+
+func (s *Scanner) scanMantissa(ch rune) rune {
+	for isDecimal(ch) {
+		ch = s.next()
+	}
+	return ch
+}
+
+func (s *Scanner) scanFraction(ch rune) rune {
+	if ch == '.' {
+		ch = s.scanMantissa(s.next())
+	}
+	return ch
+}
+
+func (s *Scanner) scanExponent(ch rune) rune {
+	if ch == 'e' || ch == 'E' {
+		ch = s.next()
+		if ch == '-' || ch == '+' {
+			ch = s.next()
+		}
+		ch = s.scanMantissa(ch)
+	}
+	return ch
+}
+
+func (s *Scanner) scanNumber(ch rune) (rune, rune) {
+	// isDecimal(ch)
+	if ch == '0' {
+		// int or float
+		ch = s.next()
+		if ch == 'x' || ch == 'X' {
+			// hexadecimal int
+			ch = s.next()
+			hasMantissa := false
+			for digitVal(ch) < 16 {
+				ch = s.next()
+				hasMantissa = true
+			}
+			if !hasMantissa {
+				s.error("illegal hexadecimal number")
+			}
+		} else {
+			// octal int or float
+			has8or9 := false
+			for isDecimal(ch) {
+				if ch > '7' {
+					has8or9 = true
+				}
+				ch = s.next()
+			}
+			if s.Mode&ScanFloats != 0 && (ch == '.' || ch == 'e' || ch == 'E') {
+				// float
+				ch = s.scanFraction(ch)
+				ch = s.scanExponent(ch)
+				return Float, ch
+			}
+			// octal int
+			if has8or9 {
+				s.error("illegal octal number")
+			}
+		}
+		return Int, ch
+	}
+	// decimal int or float
+	ch = s.scanMantissa(ch)
+	if s.Mode&ScanFloats != 0 && (ch == '.' || ch == 'e' || ch == 'E') {
+		// float
+		ch = s.scanFraction(ch)
+		ch = s.scanExponent(ch)
+		return Float, ch
+	}
+	return Int, ch
+}
+
+func (s *Scanner) scanDigits(ch rune, base, n int) rune {
+	for n > 0 && digitVal(ch) < base {
+		ch = s.next()
+		n--
+	}
+	if n > 0 {
+		s.error("illegal char escape")
+	}
+	return ch
+}
+
+func (s *Scanner) scanEscape(quote rune) rune {
+	ch := s.next() // read character after '/'
+	switch ch {
+	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
+		// nothing to do
+		ch = s.next()
+	case '0', '1', '2', '3', '4', '5', '6', '7':
+		ch = s.scanDigits(ch, 8, 3)
+	case 'x':
+		ch = s.scanDigits(s.next(), 16, 2)
+	case 'u':
+		ch = s.scanDigits(s.next(), 16, 4)
+	case 'U':
+		ch = s.scanDigits(s.next(), 16, 8)
+	default:
+		s.error("illegal char escape")
+	}
+	return ch
+}
+
+func (s *Scanner) scanString(quote rune) (n int) {
+	ch := s.next() // read character after quote
+	for ch != quote {
+		if ch == '\n' || ch < 0 {
+			s.error("literal not terminated")
+			return
+		}
+		if ch == '\\' {
+			ch = s.scanEscape(quote)
+		} else {
+			ch = s.next()
+		}
+		n++
+	}
+	return
+}
+
+func (s *Scanner) scanRawString() {
+	ch := s.next() // read character after '`'
+	for ch != '`' {
+		if ch < 0 {
+			s.error("literal not terminated")
+			return
+		}
+		ch = s.next()
+	}
+}
+
+func (s *Scanner) scanChar() {
+	if s.scanString('\'') != 1 {
+		s.error("illegal char literal")
+	}
+}
+
+func (s *Scanner) scanComment(ch rune) rune {
+	// ch == '/' || ch == '*'
+	if ch == '/' {
+		// line comment
+		ch = s.next() // read character after "//"
+		for ch != '\n' && ch >= 0 {
+			ch = s.next()
+		}
+		return ch
+	}
+
+	// general comment
+	ch = s.next() // read character after "/*"
+	for {
+		if ch < 0 {
+			s.error("comment not terminated")
+			break
+		}
+		ch0 := ch
+		ch = s.next()
+		if ch0 == '*' && ch == '/' {
+			ch = s.next()
+			break
+		}
+	}
+	return ch
+}
+
+// Scan reads the next token or Unicode character from source and returns it.
+// It only recognizes tokens t for which the respective Mode bit (1<<-t) is set.
+// It returns EOF at the end of the source. It reports scanner errors (read and
+// token errors) by calling s.Error, if not nil; otherwise it prints an error
+// message to os.Stderr.
+func (s *Scanner) Scan() rune {
+	ch := s.Peek()
+
+	// reset token text position
+	s.tokPos = -1
+	s.Line = 0
+
+redo:
+	// skip white space
+	for s.Whitespace&(1<<uint(ch)) != 0 {
+		ch = s.next()
+	}
+
+	// start collecting token text
+	s.tokBuf.Reset()
+	s.tokPos = s.srcPos - s.lastCharLen
+
+	// set token position
+	// (this is a slightly optimized version of the code in Pos())
+	s.Offset = s.srcBufOffset + s.tokPos
+	if s.column > 0 {
+		// common case: last character was not a '\n'
+		s.Line = s.line
+		s.Column = s.column
+	} else {
+		// last character was a '\n'
+		// (we cannot be at the beginning of the source
+		// since we have called next() at least once)
+		s.Line = s.line - 1
+		s.Column = s.lastLineLen
+	}
+
+	// determine token value
+	tok := ch
+	switch {
+	case unicode.IsLetter(ch) || ch == '_':
+		if s.Mode&ScanIdents != 0 {
+			tok = Ident
+			ch = s.scanIdentifier()
+		} else {
+			ch = s.next()
+		}
+	case isDecimal(ch):
+		if s.Mode&(ScanInts|ScanFloats) != 0 {
+			tok, ch = s.scanNumber(ch)
+		} else {
+			ch = s.next()
+		}
+	default:
+		switch ch {
+		case '"':
+			if s.Mode&ScanStrings != 0 {
+				s.scanString('"')
+				tok = String
+			}
+			ch = s.next()
+		case '\'':
+			if s.Mode&ScanChars != 0 {
+				s.scanChar()
+				tok = Char
+			}
+			ch = s.next()
+		case '.':
+			ch = s.next()
+			if isDecimal(ch) && s.Mode&ScanFloats != 0 {
+				tok = Float
+				ch = s.scanMantissa(ch)
+				ch = s.scanExponent(ch)
+			}
+		case '/':
+			ch = s.next()
+			if (ch == '/' || ch == '*') && s.Mode&ScanComments != 0 {
+				if s.Mode&SkipComments != 0 {
+					s.tokPos = -1 // don't collect token text
+					ch = s.scanComment(ch)
+					goto redo
+				}
+				ch = s.scanComment(ch)
+				tok = Comment
+			}
+		case '`':
+			if s.Mode&ScanRawStrings != 0 {
+				s.scanRawString()
+				tok = String
+			}
+			ch = s.next()
+		default:
+			ch = s.next()
+		}
+	}
+
+	// end of token text
+	s.tokEnd = s.srcPos - s.lastCharLen
+
+	s.ch = ch
+	return tok
+}
+
+// Pos returns the position of the character immediately after
+// the character or token returned by the last call to Next or Scan.
+func (s *Scanner) Pos() (pos Position) {
+	pos.Filename = s.Filename
+	pos.Offset = s.srcBufOffset + s.srcPos - s.lastCharLen
+	switch {
+	case s.column > 0:
+		// common case: last character was not a '\n'
+		pos.Line = s.line
+		pos.Column = s.column
+	case s.lastLineLen > 0:
+		// last character was a '\n'
+		pos.Line = s.line - 1
+		pos.Column = s.lastLineLen
+	default:
+		// at the beginning of the source
+		pos.Line = 1
+		pos.Column = 1
+	}
+	return
+}
+
+// TokenText returns the string corresponding to the most recently scanned token.
+// Valid after calling Scan().
+func (s *Scanner) TokenText() string {
+	if s.tokPos < 0 {
+		// no token text
+		return ""
+	}
+
+	if s.tokEnd < 0 {
+		// if EOF was reached, s.tokEnd is set to -1 (s.srcPos == 0)
+		s.tokEnd = s.tokPos
+	}
+
+	if s.tokBuf.Len() == 0 {
+		// common case: the entire token text is still in srcBuf
+		return string(s.srcBuf[s.tokPos:s.tokEnd])
+	}
+
+	// part of the token text was saved in tokBuf: save the rest in
+	// tokBuf as well and return its content
+	s.tokBuf.Write(s.srcBuf[s.tokPos:s.tokEnd])
+	s.tokPos = s.tokEnd // ensure idempotency of TokenText() call
+	return s.tokBuf.String()
+}
diff --git a/third_party/gofrontend/libgo/go/text/scanner/scanner_test.go b/third_party/gofrontend/libgo/go/text/scanner/scanner_test.go
new file mode 100644
index 0000000..7d3f597
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/scanner/scanner_test.go
@@ -0,0 +1,596 @@
+// 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 scanner
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"strings"
+	"testing"
+	"unicode/utf8"
+)
+
+// A StringReader delivers its data one string segment at a time via Read.
+type StringReader struct {
+	data []string
+	step int
+}
+
+func (r *StringReader) Read(p []byte) (n int, err error) {
+	if r.step < len(r.data) {
+		s := r.data[r.step]
+		n = copy(p, s)
+		r.step++
+	} else {
+		err = io.EOF
+	}
+	return
+}
+
+func readRuneSegments(t *testing.T, segments []string) {
+	got := ""
+	want := strings.Join(segments, "")
+	s := new(Scanner).Init(&StringReader{data: segments})
+	for {
+		ch := s.Next()
+		if ch == EOF {
+			break
+		}
+		got += string(ch)
+	}
+	if got != want {
+		t.Errorf("segments=%v got=%s want=%s", segments, got, want)
+	}
+}
+
+var segmentList = [][]string{
+	{},
+	{""},
+	{"日", "本語"},
+	{"\u65e5", "\u672c", "\u8a9e"},
+	{"\U000065e5", " ", "\U0000672c", "\U00008a9e"},
+	{"\xe6", "\x97\xa5\xe6", "\x9c\xac\xe8\xaa\x9e"},
+	{"Hello", ", ", "World", "!"},
+	{"Hello", ", ", "", "World", "!"},
+}
+
+func TestNext(t *testing.T) {
+	for _, s := range segmentList {
+		readRuneSegments(t, s)
+	}
+}
+
+type token struct {
+	tok  rune
+	text string
+}
+
+var f100 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+
+var tokenList = []token{
+	{Comment, "// line comments"},
+	{Comment, "//"},
+	{Comment, "////"},
+	{Comment, "// comment"},
+	{Comment, "// /* comment */"},
+	{Comment, "// // comment //"},
+	{Comment, "//" + f100},
+
+	{Comment, "// general comments"},
+	{Comment, "/**/"},
+	{Comment, "/***/"},
+	{Comment, "/* comment */"},
+	{Comment, "/* // comment */"},
+	{Comment, "/* /* comment */"},
+	{Comment, "/*\n comment\n*/"},
+	{Comment, "/*" + f100 + "*/"},
+
+	{Comment, "// identifiers"},
+	{Ident, "a"},
+	{Ident, "a0"},
+	{Ident, "foobar"},
+	{Ident, "abc123"},
+	{Ident, "LGTM"},
+	{Ident, "_"},
+	{Ident, "_abc123"},
+	{Ident, "abc123_"},
+	{Ident, "_abc_123_"},
+	{Ident, "_äöü"},
+	{Ident, "_本"},
+	{Ident, "äöü"},
+	{Ident, "本"},
+	{Ident, "a۰۱۸"},
+	{Ident, "foo६४"},
+	{Ident, "bar9876"},
+	{Ident, f100},
+
+	{Comment, "// decimal ints"},
+	{Int, "0"},
+	{Int, "1"},
+	{Int, "9"},
+	{Int, "42"},
+	{Int, "1234567890"},
+
+	{Comment, "// octal ints"},
+	{Int, "00"},
+	{Int, "01"},
+	{Int, "07"},
+	{Int, "042"},
+	{Int, "01234567"},
+
+	{Comment, "// hexadecimal ints"},
+	{Int, "0x0"},
+	{Int, "0x1"},
+	{Int, "0xf"},
+	{Int, "0x42"},
+	{Int, "0x123456789abcDEF"},
+	{Int, "0x" + f100},
+	{Int, "0X0"},
+	{Int, "0X1"},
+	{Int, "0XF"},
+	{Int, "0X42"},
+	{Int, "0X123456789abcDEF"},
+	{Int, "0X" + f100},
+
+	{Comment, "// floats"},
+	{Float, "0."},
+	{Float, "1."},
+	{Float, "42."},
+	{Float, "01234567890."},
+	{Float, ".0"},
+	{Float, ".1"},
+	{Float, ".42"},
+	{Float, ".0123456789"},
+	{Float, "0.0"},
+	{Float, "1.0"},
+	{Float, "42.0"},
+	{Float, "01234567890.0"},
+	{Float, "0e0"},
+	{Float, "1e0"},
+	{Float, "42e0"},
+	{Float, "01234567890e0"},
+	{Float, "0E0"},
+	{Float, "1E0"},
+	{Float, "42E0"},
+	{Float, "01234567890E0"},
+	{Float, "0e+10"},
+	{Float, "1e-10"},
+	{Float, "42e+10"},
+	{Float, "01234567890e-10"},
+	{Float, "0E+10"},
+	{Float, "1E-10"},
+	{Float, "42E+10"},
+	{Float, "01234567890E-10"},
+
+	{Comment, "// chars"},
+	{Char, `' '`},
+	{Char, `'a'`},
+	{Char, `'本'`},
+	{Char, `'\a'`},
+	{Char, `'\b'`},
+	{Char, `'\f'`},
+	{Char, `'\n'`},
+	{Char, `'\r'`},
+	{Char, `'\t'`},
+	{Char, `'\v'`},
+	{Char, `'\''`},
+	{Char, `'\000'`},
+	{Char, `'\777'`},
+	{Char, `'\x00'`},
+	{Char, `'\xff'`},
+	{Char, `'\u0000'`},
+	{Char, `'\ufA16'`},
+	{Char, `'\U00000000'`},
+	{Char, `'\U0000ffAB'`},
+
+	{Comment, "// strings"},
+	{String, `" "`},
+	{String, `"a"`},
+	{String, `"本"`},
+	{String, `"\a"`},
+	{String, `"\b"`},
+	{String, `"\f"`},
+	{String, `"\n"`},
+	{String, `"\r"`},
+	{String, `"\t"`},
+	{String, `"\v"`},
+	{String, `"\""`},
+	{String, `"\000"`},
+	{String, `"\777"`},
+	{String, `"\x00"`},
+	{String, `"\xff"`},
+	{String, `"\u0000"`},
+	{String, `"\ufA16"`},
+	{String, `"\U00000000"`},
+	{String, `"\U0000ffAB"`},
+	{String, `"` + f100 + `"`},
+
+	{Comment, "// raw strings"},
+	{String, "``"},
+	{String, "`\\`"},
+	{String, "`" + "\n\n/* foobar */\n\n" + "`"},
+	{String, "`" + f100 + "`"},
+
+	{Comment, "// individual characters"},
+	// NUL character is not allowed
+	{'\x01', "\x01"},
+	{' ' - 1, string(' ' - 1)},
+	{'+', "+"},
+	{'/', "/"},
+	{'.', "."},
+	{'~', "~"},
+	{'(', "("},
+}
+
+func makeSource(pattern string) *bytes.Buffer {
+	var buf bytes.Buffer
+	for _, k := range tokenList {
+		fmt.Fprintf(&buf, pattern, k.text)
+	}
+	return &buf
+}
+
+func checkTok(t *testing.T, s *Scanner, line int, got, want rune, text string) {
+	if got != want {
+		t.Fatalf("tok = %s, want %s for %q", TokenString(got), TokenString(want), text)
+	}
+	if s.Line != line {
+		t.Errorf("line = %d, want %d for %q", s.Line, line, text)
+	}
+	stext := s.TokenText()
+	if stext != text {
+		t.Errorf("text = %q, want %q", stext, text)
+	} else {
+		// check idempotency of TokenText() call
+		stext = s.TokenText()
+		if stext != text {
+			t.Errorf("text = %q, want %q (idempotency check)", stext, text)
+		}
+	}
+}
+
+func countNewlines(s string) int {
+	n := 0
+	for _, ch := range s {
+		if ch == '\n' {
+			n++
+		}
+	}
+	return n
+}
+
+func testScan(t *testing.T, mode uint) {
+	s := new(Scanner).Init(makeSource(" \t%s\n"))
+	s.Mode = mode
+	tok := s.Scan()
+	line := 1
+	for _, k := range tokenList {
+		if mode&SkipComments == 0 || k.tok != Comment {
+			checkTok(t, s, line, tok, k.tok, k.text)
+			tok = s.Scan()
+		}
+		line += countNewlines(k.text) + 1 // each token is on a new line
+	}
+	checkTok(t, s, line, tok, EOF, "")
+}
+
+func TestScan(t *testing.T) {
+	testScan(t, GoTokens)
+	testScan(t, GoTokens&^SkipComments)
+}
+
+func TestPosition(t *testing.T) {
+	src := makeSource("\t\t\t\t%s\n")
+	s := new(Scanner).Init(src)
+	s.Mode = GoTokens &^ SkipComments
+	s.Scan()
+	pos := Position{"", 4, 1, 5}
+	for _, k := range tokenList {
+		if s.Offset != pos.Offset {
+			t.Errorf("offset = %d, want %d for %q", s.Offset, pos.Offset, k.text)
+		}
+		if s.Line != pos.Line {
+			t.Errorf("line = %d, want %d for %q", s.Line, pos.Line, k.text)
+		}
+		if s.Column != pos.Column {
+			t.Errorf("column = %d, want %d for %q", s.Column, pos.Column, k.text)
+		}
+		pos.Offset += 4 + len(k.text) + 1     // 4 tabs + token bytes + newline
+		pos.Line += countNewlines(k.text) + 1 // each token is on a new line
+		s.Scan()
+	}
+	// make sure there were no token-internal errors reported by scanner
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+}
+
+func TestScanZeroMode(t *testing.T) {
+	src := makeSource("%s\n")
+	str := src.String()
+	s := new(Scanner).Init(src)
+	s.Mode = 0       // don't recognize any token classes
+	s.Whitespace = 0 // don't skip any whitespace
+	tok := s.Scan()
+	for i, ch := range str {
+		if tok != ch {
+			t.Fatalf("%d. tok = %s, want %s", i, TokenString(tok), TokenString(ch))
+		}
+		tok = s.Scan()
+	}
+	if tok != EOF {
+		t.Fatalf("tok = %s, want EOF", TokenString(tok))
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+}
+
+func testScanSelectedMode(t *testing.T, mode uint, class rune) {
+	src := makeSource("%s\n")
+	s := new(Scanner).Init(src)
+	s.Mode = mode
+	tok := s.Scan()
+	for tok != EOF {
+		if tok < 0 && tok != class {
+			t.Fatalf("tok = %s, want %s", TokenString(tok), TokenString(class))
+		}
+		tok = s.Scan()
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+}
+
+func TestScanSelectedMask(t *testing.T) {
+	testScanSelectedMode(t, 0, 0)
+	testScanSelectedMode(t, ScanIdents, Ident)
+	// Don't test ScanInts and ScanNumbers since some parts of
+	// the floats in the source look like (illegal) octal ints
+	// and ScanNumbers may return either Int or Float.
+	testScanSelectedMode(t, ScanChars, Char)
+	testScanSelectedMode(t, ScanStrings, String)
+	testScanSelectedMode(t, SkipComments, 0)
+	testScanSelectedMode(t, ScanComments, Comment)
+}
+
+func TestScanNext(t *testing.T) {
+	const BOM = '\uFEFF'
+	BOMs := string(BOM)
+	s := new(Scanner).Init(strings.NewReader(BOMs + "if a == bcd /* com" + BOMs + "ment */ {\n\ta += c\n}" + BOMs + "// line comment ending in eof"))
+	checkTok(t, s, 1, s.Scan(), Ident, "if") // the first BOM is ignored
+	checkTok(t, s, 1, s.Scan(), Ident, "a")
+	checkTok(t, s, 1, s.Scan(), '=', "=")
+	checkTok(t, s, 0, s.Next(), '=', "")
+	checkTok(t, s, 0, s.Next(), ' ', "")
+	checkTok(t, s, 0, s.Next(), 'b', "")
+	checkTok(t, s, 1, s.Scan(), Ident, "cd")
+	checkTok(t, s, 1, s.Scan(), '{', "{")
+	checkTok(t, s, 2, s.Scan(), Ident, "a")
+	checkTok(t, s, 2, s.Scan(), '+', "+")
+	checkTok(t, s, 0, s.Next(), '=', "")
+	checkTok(t, s, 2, s.Scan(), Ident, "c")
+	checkTok(t, s, 3, s.Scan(), '}', "}")
+	checkTok(t, s, 3, s.Scan(), BOM, BOMs)
+	checkTok(t, s, 3, s.Scan(), -1, "")
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+}
+
+func TestScanWhitespace(t *testing.T) {
+	var buf bytes.Buffer
+	var ws uint64
+	// start at 1, NUL character is not allowed
+	for ch := byte(1); ch < ' '; ch++ {
+		buf.WriteByte(ch)
+		ws |= 1 << ch
+	}
+	const orig = 'x'
+	buf.WriteByte(orig)
+
+	s := new(Scanner).Init(&buf)
+	s.Mode = 0
+	s.Whitespace = ws
+	tok := s.Scan()
+	if tok != orig {
+		t.Errorf("tok = %s, want %s", TokenString(tok), TokenString(orig))
+	}
+}
+
+func testError(t *testing.T, src, pos, msg string, tok rune) {
+	s := new(Scanner).Init(strings.NewReader(src))
+	errorCalled := false
+	s.Error = func(s *Scanner, m string) {
+		if !errorCalled {
+			// only look at first error
+			if p := s.Pos().String(); p != pos {
+				t.Errorf("pos = %q, want %q for %q", p, pos, src)
+			}
+			if m != msg {
+				t.Errorf("msg = %q, want %q for %q", m, msg, src)
+			}
+			errorCalled = true
+		}
+	}
+	tk := s.Scan()
+	if tk != tok {
+		t.Errorf("tok = %s, want %s for %q", TokenString(tk), TokenString(tok), src)
+	}
+	if !errorCalled {
+		t.Errorf("error handler not called for %q", src)
+	}
+	if s.ErrorCount == 0 {
+		t.Errorf("count = %d, want > 0 for %q", s.ErrorCount, src)
+	}
+}
+
+func TestError(t *testing.T) {
+	testError(t, "\x00", "1:1", "illegal character NUL", 0)
+	testError(t, "\x80", "1:1", "illegal UTF-8 encoding", utf8.RuneError)
+	testError(t, "\xff", "1:1", "illegal UTF-8 encoding", utf8.RuneError)
+
+	testError(t, "a\x00", "1:2", "illegal character NUL", Ident)
+	testError(t, "ab\x80", "1:3", "illegal UTF-8 encoding", Ident)
+	testError(t, "abc\xff", "1:4", "illegal UTF-8 encoding", Ident)
+
+	testError(t, `"a`+"\x00", "1:3", "illegal character NUL", String)
+	testError(t, `"ab`+"\x80", "1:4", "illegal UTF-8 encoding", String)
+	testError(t, `"abc`+"\xff", "1:5", "illegal UTF-8 encoding", String)
+
+	testError(t, "`a"+"\x00", "1:3", "illegal character NUL", String)
+	testError(t, "`ab"+"\x80", "1:4", "illegal UTF-8 encoding", String)
+	testError(t, "`abc"+"\xff", "1:5", "illegal UTF-8 encoding", String)
+
+	testError(t, `'\"'`, "1:3", "illegal char escape", Char)
+	testError(t, `"\'"`, "1:3", "illegal char escape", String)
+
+	testError(t, `01238`, "1:6", "illegal octal number", Int)
+	testError(t, `01238123`, "1:9", "illegal octal number", Int)
+	testError(t, `0x`, "1:3", "illegal hexadecimal number", Int)
+	testError(t, `0xg`, "1:3", "illegal hexadecimal number", Int)
+	testError(t, `'aa'`, "1:4", "illegal char literal", Char)
+
+	testError(t, `'`, "1:2", "literal not terminated", Char)
+	testError(t, `'`+"\n", "1:2", "literal not terminated", Char)
+	testError(t, `"abc`, "1:5", "literal not terminated", String)
+	testError(t, `"abc`+"\n", "1:5", "literal not terminated", String)
+	testError(t, "`abc\n", "2:1", "literal not terminated", String)
+	testError(t, `/*/`, "1:4", "comment not terminated", EOF)
+}
+
+// An errReader returns (0, err) where err is not io.EOF.
+type errReader struct{}
+
+func (errReader) Read(b []byte) (int, error) {
+	return 0, io.ErrNoProgress // some error that is not io.EOF
+}
+
+func TestIOError(t *testing.T) {
+	s := new(Scanner).Init(errReader{})
+	errorCalled := false
+	s.Error = func(s *Scanner, msg string) {
+		if !errorCalled {
+			if want := io.ErrNoProgress.Error(); msg != want {
+				t.Errorf("msg = %q, want %q", msg, want)
+			}
+			errorCalled = true
+		}
+	}
+	tok := s.Scan()
+	if tok != EOF {
+		t.Errorf("tok = %s, want EOF", TokenString(tok))
+	}
+	if !errorCalled {
+		t.Errorf("error handler not called")
+	}
+}
+
+func checkPos(t *testing.T, got, want Position) {
+	if got.Offset != want.Offset || got.Line != want.Line || got.Column != want.Column {
+		t.Errorf("got offset, line, column = %d, %d, %d; want %d, %d, %d",
+			got.Offset, got.Line, got.Column, want.Offset, want.Line, want.Column)
+	}
+}
+
+func checkNextPos(t *testing.T, s *Scanner, offset, line, column int, char rune) {
+	if ch := s.Next(); ch != char {
+		t.Errorf("ch = %s, want %s", TokenString(ch), TokenString(char))
+	}
+	want := Position{Offset: offset, Line: line, Column: column}
+	checkPos(t, s.Pos(), want)
+}
+
+func checkScanPos(t *testing.T, s *Scanner, offset, line, column int, char rune) {
+	want := Position{Offset: offset, Line: line, Column: column}
+	checkPos(t, s.Pos(), want)
+	if ch := s.Scan(); ch != char {
+		t.Errorf("ch = %s, want %s", TokenString(ch), TokenString(char))
+		if string(ch) != s.TokenText() {
+			t.Errorf("tok = %q, want %q", s.TokenText(), string(ch))
+		}
+	}
+	checkPos(t, s.Position, want)
+}
+
+func TestPos(t *testing.T) {
+	// corner case: empty source
+	s := new(Scanner).Init(strings.NewReader(""))
+	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
+	s.Peek() // peek doesn't affect the position
+	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
+
+	// corner case: source with only a newline
+	s = new(Scanner).Init(strings.NewReader("\n"))
+	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
+	checkNextPos(t, s, 1, 2, 1, '\n')
+	// after EOF position doesn't change
+	for i := 10; i > 0; i-- {
+		checkScanPos(t, s, 1, 2, 1, EOF)
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+
+	// corner case: source with only a single character
+	s = new(Scanner).Init(strings.NewReader("本"))
+	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
+	checkNextPos(t, s, 3, 1, 2, '本')
+	// after EOF position doesn't change
+	for i := 10; i > 0; i-- {
+		checkScanPos(t, s, 3, 1, 2, EOF)
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+
+	// positions after calling Next
+	s = new(Scanner).Init(strings.NewReader("  foo६४  \n\n本語\n"))
+	checkNextPos(t, s, 1, 1, 2, ' ')
+	s.Peek() // peek doesn't affect the position
+	checkNextPos(t, s, 2, 1, 3, ' ')
+	checkNextPos(t, s, 3, 1, 4, 'f')
+	checkNextPos(t, s, 4, 1, 5, 'o')
+	checkNextPos(t, s, 5, 1, 6, 'o')
+	checkNextPos(t, s, 8, 1, 7, '६')
+	checkNextPos(t, s, 11, 1, 8, '४')
+	checkNextPos(t, s, 12, 1, 9, ' ')
+	checkNextPos(t, s, 13, 1, 10, ' ')
+	checkNextPos(t, s, 14, 2, 1, '\n')
+	checkNextPos(t, s, 15, 3, 1, '\n')
+	checkNextPos(t, s, 18, 3, 2, '本')
+	checkNextPos(t, s, 21, 3, 3, '語')
+	checkNextPos(t, s, 22, 4, 1, '\n')
+	// after EOF position doesn't change
+	for i := 10; i > 0; i-- {
+		checkScanPos(t, s, 22, 4, 1, EOF)
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+
+	// positions after calling Scan
+	s = new(Scanner).Init(strings.NewReader("abc\n本語\n\nx"))
+	s.Mode = 0
+	s.Whitespace = 0
+	checkScanPos(t, s, 0, 1, 1, 'a')
+	s.Peek() // peek doesn't affect the position
+	checkScanPos(t, s, 1, 1, 2, 'b')
+	checkScanPos(t, s, 2, 1, 3, 'c')
+	checkScanPos(t, s, 3, 1, 4, '\n')
+	checkScanPos(t, s, 4, 2, 1, '本')
+	checkScanPos(t, s, 7, 2, 2, '語')
+	checkScanPos(t, s, 10, 2, 3, '\n')
+	checkScanPos(t, s, 11, 3, 1, '\n')
+	checkScanPos(t, s, 12, 4, 1, 'x')
+	// after EOF position doesn't change
+	for i := 10; i > 0; i-- {
+		checkScanPos(t, s, 13, 4, 2, EOF)
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/text/tabwriter/example_test.go b/third_party/gofrontend/libgo/go/text/tabwriter/example_test.go
new file mode 100644
index 0000000..20443cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/tabwriter/example_test.go
@@ -0,0 +1,38 @@
+// 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 tabwriter_test
+
+import (
+	"fmt"
+	"os"
+	"text/tabwriter"
+)
+
+func ExampleWriter_Init() {
+	w := new(tabwriter.Writer)
+
+	// Format in tab-separated columns with a tab stop of 8.
+	w.Init(os.Stdout, 0, 8, 0, '\t', 0)
+	fmt.Fprintln(w, "a\tb\tc\td\t.")
+	fmt.Fprintln(w, "123\t12345\t1234567\t123456789\t.")
+	fmt.Fprintln(w)
+	w.Flush()
+
+	// Format right-aligned in space-separated columns of minimal width 5
+	// and at least one blank of padding (so wider column entries do not
+	// touch each other).
+	w.Init(os.Stdout, 5, 0, 1, ' ', tabwriter.AlignRight)
+	fmt.Fprintln(w, "a\tb\tc\td\t.")
+	fmt.Fprintln(w, "123\t12345\t1234567\t123456789\t.")
+	fmt.Fprintln(w)
+	w.Flush()
+
+	// output:
+	// a	b	c	d		.
+	// 123	12345	1234567	123456789	.
+	//
+	//     a     b       c         d.
+	//   123 12345 1234567 123456789.
+}
diff --git a/third_party/gofrontend/libgo/go/text/tabwriter/tabwriter.go b/third_party/gofrontend/libgo/go/text/tabwriter/tabwriter.go
new file mode 100644
index 0000000..c0c32d5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/tabwriter/tabwriter.go
@@ -0,0 +1,558 @@
+// 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 tabwriter implements a write filter (tabwriter.Writer) that
+// translates tabbed columns in input into properly aligned text.
+//
+// The package is using the Elastic Tabstops algorithm described at
+// http://nickgravgaard.com/elastictabstops/index.html.
+//
+package tabwriter
+
+import (
+	"bytes"
+	"io"
+	"unicode/utf8"
+)
+
+// ----------------------------------------------------------------------------
+// Filter implementation
+
+// A cell represents a segment of text terminated by tabs or line breaks.
+// The text itself is stored in a separate buffer; cell only describes the
+// segment's size in bytes, its width in runes, and whether it's an htab
+// ('\t') terminated cell.
+//
+type cell struct {
+	size  int  // cell size in bytes
+	width int  // cell width in runes
+	htab  bool // true if the cell is terminated by an htab ('\t')
+}
+
+// A Writer is a filter that inserts padding around tab-delimited
+// columns in its input to align them in the output.
+//
+// The Writer treats incoming bytes as UTF-8 encoded text consisting
+// of cells terminated by (horizontal or vertical) tabs or line
+// breaks (newline or formfeed characters). Cells in adjacent lines
+// constitute a column. The Writer inserts padding as needed to
+// make all cells in a column have the same width, effectively
+// aligning the columns. It assumes that all characters have the
+// same width except for tabs for which a tabwidth must be specified.
+// Note that cells are tab-terminated, not tab-separated: trailing
+// non-tab text at the end of a line does not form a column cell.
+//
+// The Writer assumes that all Unicode code points have the same width;
+// this may not be true in some fonts.
+//
+// If DiscardEmptyColumns is set, empty columns that are terminated
+// entirely by vertical (or "soft") tabs are discarded. Columns
+// terminated by horizontal (or "hard") tabs are not affected by
+// this flag.
+//
+// If a Writer is configured to filter HTML, HTML tags and entities
+// are passed through. The widths of tags and entities are
+// assumed to be zero (tags) and one (entities) for formatting purposes.
+//
+// A segment of text may be escaped by bracketing it with Escape
+// characters. The tabwriter passes escaped text segments through
+// unchanged. In particular, it does not interpret any tabs or line
+// breaks within the segment. If the StripEscape flag is set, the
+// Escape characters are stripped from the output; otherwise they
+// are passed through as well. For the purpose of formatting, the
+// width of the escaped text is always computed excluding the Escape
+// characters.
+//
+// The formfeed character ('\f') acts like a newline but it also
+// terminates all columns in the current line (effectively calling
+// Flush). Cells in the next line start new columns. Unless found
+// inside an HTML tag or inside an escaped text segment, formfeed
+// characters appear as newlines in the output.
+//
+// The Writer must buffer input internally, because proper spacing
+// of one line may depend on the cells in future lines. Clients must
+// call Flush when done calling Write.
+//
+type Writer struct {
+	// configuration
+	output   io.Writer
+	minwidth int
+	tabwidth int
+	padding  int
+	padbytes [8]byte
+	flags    uint
+
+	// current state
+	buf     bytes.Buffer // collected text excluding tabs or line breaks
+	pos     int          // buffer position up to which cell.width of incomplete cell has been computed
+	cell    cell         // current incomplete cell; cell.width is up to buf[pos] excluding ignored sections
+	endChar byte         // terminating char of escaped sequence (Escape for escapes, '>', ';' for HTML tags/entities, or 0)
+	lines   [][]cell     // list of lines; each line is a list of cells
+	widths  []int        // list of column widths in runes - re-used during formatting
+}
+
+func (b *Writer) addLine() { b.lines = append(b.lines, []cell{}) }
+
+// Reset the current state.
+func (b *Writer) reset() {
+	b.buf.Reset()
+	b.pos = 0
+	b.cell = cell{}
+	b.endChar = 0
+	b.lines = b.lines[0:0]
+	b.widths = b.widths[0:0]
+	b.addLine()
+}
+
+// Internal representation (current state):
+//
+// - all text written is appended to buf; tabs and line breaks are stripped away
+// - at any given time there is a (possibly empty) incomplete cell at the end
+//   (the cell starts after a tab or line break)
+// - cell.size is the number of bytes belonging to the cell so far
+// - cell.width is text width in runes of that cell from the start of the cell to
+//   position pos; html tags and entities are excluded from this width if html
+//   filtering is enabled
+// - the sizes and widths of processed text are kept in the lines list
+//   which contains a list of cells for each line
+// - the widths list is a temporary list with current widths used during
+//   formatting; it is kept in Writer because it's re-used
+//
+//                    |<---------- size ---------->|
+//                    |                            |
+//                    |<- width ->|<- ignored ->|  |
+//                    |           |             |  |
+// [---processed---tab------------<tag>...</tag>...]
+// ^                  ^                         ^
+// |                  |                         |
+// buf                start of incomplete cell  pos
+
+// Formatting can be controlled with these flags.
+const (
+	// Ignore html tags and treat entities (starting with '&'
+	// and ending in ';') as single characters (width = 1).
+	FilterHTML uint = 1 << iota
+
+	// Strip Escape characters bracketing escaped text segments
+	// instead of passing them through unchanged with the text.
+	StripEscape
+
+	// Force right-alignment of cell content.
+	// Default is left-alignment.
+	AlignRight
+
+	// Handle empty columns as if they were not present in
+	// the input in the first place.
+	DiscardEmptyColumns
+
+	// Always use tabs for indentation columns (i.e., padding of
+	// leading empty cells on the left) independent of padchar.
+	TabIndent
+
+	// Print a vertical bar ('|') between columns (after formatting).
+	// Discarded columns appear as zero-width columns ("||").
+	Debug
+)
+
+// A Writer must be initialized with a call to Init. The first parameter (output)
+// specifies the filter output. The remaining parameters control the formatting:
+//
+//	minwidth	minimal cell width including any padding
+//	tabwidth	width of tab characters (equivalent number of spaces)
+//	padding		padding added to a cell before computing its width
+//	padchar		ASCII char used for padding
+//			if padchar == '\t', the Writer will assume that the
+//			width of a '\t' in the formatted output is tabwidth,
+//			and cells are left-aligned independent of align_left
+//			(for correct-looking results, tabwidth must correspond
+//			to the tab width in the viewer displaying the result)
+//	flags		formatting control
+//
+func (b *Writer) Init(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer {
+	if minwidth < 0 || tabwidth < 0 || padding < 0 {
+		panic("negative minwidth, tabwidth, or padding")
+	}
+	b.output = output
+	b.minwidth = minwidth
+	b.tabwidth = tabwidth
+	b.padding = padding
+	for i := range b.padbytes {
+		b.padbytes[i] = padchar
+	}
+	if padchar == '\t' {
+		// tab padding enforces left-alignment
+		flags &^= AlignRight
+	}
+	b.flags = flags
+
+	b.reset()
+
+	return b
+}
+
+// debugging support (keep code around)
+func (b *Writer) dump() {
+	pos := 0
+	for i, line := range b.lines {
+		print("(", i, ") ")
+		for _, c := range line {
+			print("[", string(b.buf.Bytes()[pos:pos+c.size]), "]")
+			pos += c.size
+		}
+		print("\n")
+	}
+	print("\n")
+}
+
+// local error wrapper so we can distinguish errors we want to return
+// as errors from genuine panics (which we don't want to return as errors)
+type osError struct {
+	err error
+}
+
+func (b *Writer) write0(buf []byte) {
+	n, err := b.output.Write(buf)
+	if n != len(buf) && err == nil {
+		err = io.ErrShortWrite
+	}
+	if err != nil {
+		panic(osError{err})
+	}
+}
+
+func (b *Writer) writeN(src []byte, n int) {
+	for n > len(src) {
+		b.write0(src)
+		n -= len(src)
+	}
+	b.write0(src[0:n])
+}
+
+var (
+	newline = []byte{'\n'}
+	tabs    = []byte("\t\t\t\t\t\t\t\t")
+)
+
+func (b *Writer) writePadding(textw, cellw int, useTabs bool) {
+	if b.padbytes[0] == '\t' || useTabs {
+		// padding is done with tabs
+		if b.tabwidth == 0 {
+			return // tabs have no width - can't do any padding
+		}
+		// make cellw the smallest multiple of b.tabwidth
+		cellw = (cellw + b.tabwidth - 1) / b.tabwidth * b.tabwidth
+		n := cellw - textw // amount of padding
+		if n < 0 {
+			panic("internal error")
+		}
+		b.writeN(tabs, (n+b.tabwidth-1)/b.tabwidth)
+		return
+	}
+
+	// padding is done with non-tab characters
+	b.writeN(b.padbytes[0:], cellw-textw)
+}
+
+var vbar = []byte{'|'}
+
+func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int) {
+	pos = pos0
+	for i := line0; i < line1; i++ {
+		line := b.lines[i]
+
+		// if TabIndent is set, use tabs to pad leading empty cells
+		useTabs := b.flags&TabIndent != 0
+
+		for j, c := range line {
+			if j > 0 && b.flags&Debug != 0 {
+				// indicate column break
+				b.write0(vbar)
+			}
+
+			if c.size == 0 {
+				// empty cell
+				if j < len(b.widths) {
+					b.writePadding(c.width, b.widths[j], useTabs)
+				}
+			} else {
+				// non-empty cell
+				useTabs = false
+				if b.flags&AlignRight == 0 { // align left
+					b.write0(b.buf.Bytes()[pos : pos+c.size])
+					pos += c.size
+					if j < len(b.widths) {
+						b.writePadding(c.width, b.widths[j], false)
+					}
+				} else { // align right
+					if j < len(b.widths) {
+						b.writePadding(c.width, b.widths[j], false)
+					}
+					b.write0(b.buf.Bytes()[pos : pos+c.size])
+					pos += c.size
+				}
+			}
+		}
+
+		if i+1 == len(b.lines) {
+			// last buffered line - we don't have a newline, so just write
+			// any outstanding buffered data
+			b.write0(b.buf.Bytes()[pos : pos+b.cell.size])
+			pos += b.cell.size
+		} else {
+			// not the last line - write newline
+			b.write0(newline)
+		}
+	}
+	return
+}
+
+// Format the text between line0 and line1 (excluding line1); pos
+// is the buffer position corresponding to the beginning of line0.
+// Returns the buffer position corresponding to the beginning of
+// line1 and an error, if any.
+//
+func (b *Writer) format(pos0 int, line0, line1 int) (pos int) {
+	pos = pos0
+	column := len(b.widths)
+	for this := line0; this < line1; this++ {
+		line := b.lines[this]
+
+		if column < len(line)-1 {
+			// cell exists in this column => this line
+			// has more cells than the previous line
+			// (the last cell per line is ignored because cells are
+			// tab-terminated; the last cell per line describes the
+			// text before the newline/formfeed and does not belong
+			// to a column)
+
+			// print unprinted lines until beginning of block
+			pos = b.writeLines(pos, line0, this)
+			line0 = this
+
+			// column block begin
+			width := b.minwidth // minimal column width
+			discardable := true // true if all cells in this column are empty and "soft"
+			for ; this < line1; this++ {
+				line = b.lines[this]
+				if column < len(line)-1 {
+					// cell exists in this column
+					c := line[column]
+					// update width
+					if w := c.width + b.padding; w > width {
+						width = w
+					}
+					// update discardable
+					if c.width > 0 || c.htab {
+						discardable = false
+					}
+				} else {
+					break
+				}
+			}
+			// column block end
+
+			// discard empty columns if necessary
+			if discardable && b.flags&DiscardEmptyColumns != 0 {
+				width = 0
+			}
+
+			// format and print all columns to the right of this column
+			// (we know the widths of this column and all columns to the left)
+			b.widths = append(b.widths, width) // push width
+			pos = b.format(pos, line0, this)
+			b.widths = b.widths[0 : len(b.widths)-1] // pop width
+			line0 = this
+		}
+	}
+
+	// print unprinted lines until end
+	return b.writeLines(pos, line0, line1)
+}
+
+// Append text to current cell.
+func (b *Writer) append(text []byte) {
+	b.buf.Write(text)
+	b.cell.size += len(text)
+}
+
+// Update the cell width.
+func (b *Writer) updateWidth() {
+	b.cell.width += utf8.RuneCount(b.buf.Bytes()[b.pos:b.buf.Len()])
+	b.pos = b.buf.Len()
+}
+
+// To escape a text segment, bracket it with Escape characters.
+// For instance, the tab in this string "Ignore this tab: \xff\t\xff"
+// does not terminate a cell and constitutes a single character of
+// width one for formatting purposes.
+//
+// The value 0xff was chosen because it cannot appear in a valid UTF-8 sequence.
+//
+const Escape = '\xff'
+
+// Start escaped mode.
+func (b *Writer) startEscape(ch byte) {
+	switch ch {
+	case Escape:
+		b.endChar = Escape
+	case '<':
+		b.endChar = '>'
+	case '&':
+		b.endChar = ';'
+	}
+}
+
+// Terminate escaped mode. If the escaped text was an HTML tag, its width
+// is assumed to be zero for formatting purposes; if it was an HTML entity,
+// its width is assumed to be one. In all other cases, the width is the
+// unicode width of the text.
+//
+func (b *Writer) endEscape() {
+	switch b.endChar {
+	case Escape:
+		b.updateWidth()
+		if b.flags&StripEscape == 0 {
+			b.cell.width -= 2 // don't count the Escape chars
+		}
+	case '>': // tag of zero width
+	case ';':
+		b.cell.width++ // entity, count as one rune
+	}
+	b.pos = b.buf.Len()
+	b.endChar = 0
+}
+
+// Terminate the current cell by adding it to the list of cells of the
+// current line. Returns the number of cells in that line.
+//
+func (b *Writer) terminateCell(htab bool) int {
+	b.cell.htab = htab
+	line := &b.lines[len(b.lines)-1]
+	*line = append(*line, b.cell)
+	b.cell = cell{}
+	return len(*line)
+}
+
+func handlePanic(err *error, op string) {
+	if e := recover(); e != nil {
+		if nerr, ok := e.(osError); ok {
+			*err = nerr.err
+			return
+		}
+		panic("tabwriter: panic during " + op)
+	}
+}
+
+// Flush should be called after the last call to Write to ensure
+// that any data buffered in the Writer is written to output. Any
+// incomplete escape sequence at the end is considered
+// complete for formatting purposes.
+//
+func (b *Writer) Flush() (err error) {
+	defer b.reset() // even in the presence of errors
+	defer handlePanic(&err, "Flush")
+
+	// add current cell if not empty
+	if b.cell.size > 0 {
+		if b.endChar != 0 {
+			// inside escape - terminate it even if incomplete
+			b.endEscape()
+		}
+		b.terminateCell(false)
+	}
+
+	// format contents of buffer
+	b.format(0, 0, len(b.lines))
+
+	return
+}
+
+var hbar = []byte("---\n")
+
+// Write writes buf to the writer b.
+// The only errors returned are ones encountered
+// while writing to the underlying output stream.
+//
+func (b *Writer) Write(buf []byte) (n int, err error) {
+	defer handlePanic(&err, "Write")
+
+	// split text into cells
+	n = 0
+	for i, ch := range buf {
+		if b.endChar == 0 {
+			// outside escape
+			switch ch {
+			case '\t', '\v', '\n', '\f':
+				// end of cell
+				b.append(buf[n:i])
+				b.updateWidth()
+				n = i + 1 // ch consumed
+				ncells := b.terminateCell(ch == '\t')
+				if ch == '\n' || ch == '\f' {
+					// terminate line
+					b.addLine()
+					if ch == '\f' || ncells == 1 {
+						// A '\f' always forces a flush. Otherwise, if the previous
+						// line has only one cell which does not have an impact on
+						// the formatting of the following lines (the last cell per
+						// line is ignored by format()), thus we can flush the
+						// Writer contents.
+						if err = b.Flush(); err != nil {
+							return
+						}
+						if ch == '\f' && b.flags&Debug != 0 {
+							// indicate section break
+							b.write0(hbar)
+						}
+					}
+				}
+
+			case Escape:
+				// start of escaped sequence
+				b.append(buf[n:i])
+				b.updateWidth()
+				n = i
+				if b.flags&StripEscape != 0 {
+					n++ // strip Escape
+				}
+				b.startEscape(Escape)
+
+			case '<', '&':
+				// possibly an html tag/entity
+				if b.flags&FilterHTML != 0 {
+					// begin of tag/entity
+					b.append(buf[n:i])
+					b.updateWidth()
+					n = i
+					b.startEscape(ch)
+				}
+			}
+
+		} else {
+			// inside escape
+			if ch == b.endChar {
+				// end of tag/entity
+				j := i + 1
+				if ch == Escape && b.flags&StripEscape != 0 {
+					j = i // strip Escape
+				}
+				b.append(buf[n:j])
+				n = i + 1 // ch consumed
+				b.endEscape()
+			}
+		}
+	}
+
+	// append leftover text
+	b.append(buf[n:])
+	n = len(buf)
+	return
+}
+
+// NewWriter allocates and initializes a new tabwriter.Writer.
+// The parameters are the same as for the Init function.
+//
+func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer {
+	return new(Writer).Init(output, minwidth, tabwidth, padding, padchar, flags)
+}
diff --git a/third_party/gofrontend/libgo/go/text/tabwriter/tabwriter_test.go b/third_party/gofrontend/libgo/go/text/tabwriter/tabwriter_test.go
new file mode 100644
index 0000000..9d3111e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/tabwriter/tabwriter_test.go
@@ -0,0 +1,652 @@
+// 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 tabwriter_test
+
+import (
+	"io"
+	"testing"
+	. "text/tabwriter"
+)
+
+type buffer struct {
+	a []byte
+}
+
+func (b *buffer) init(n int) { b.a = make([]byte, 0, n) }
+
+func (b *buffer) clear() { b.a = b.a[0:0] }
+
+func (b *buffer) Write(buf []byte) (written int, err error) {
+	n := len(b.a)
+	m := len(buf)
+	if n+m <= cap(b.a) {
+		b.a = b.a[0 : n+m]
+		for i := 0; i < m; i++ {
+			b.a[n+i] = buf[i]
+		}
+	} else {
+		panic("buffer.Write: buffer too small")
+	}
+	return len(buf), nil
+}
+
+func (b *buffer) String() string { return string(b.a) }
+
+func write(t *testing.T, testname string, w *Writer, src string) {
+	written, err := io.WriteString(w, src)
+	if err != nil {
+		t.Errorf("--- test: %s\n--- src:\n%q\n--- write error: %v\n", testname, src, err)
+	}
+	if written != len(src) {
+		t.Errorf("--- test: %s\n--- src:\n%q\n--- written = %d, len(src) = %d\n", testname, src, written, len(src))
+	}
+}
+
+func verify(t *testing.T, testname string, w *Writer, b *buffer, src, expected string) {
+	err := w.Flush()
+	if err != nil {
+		t.Errorf("--- test: %s\n--- src:\n%q\n--- flush error: %v\n", testname, src, err)
+	}
+
+	res := b.String()
+	if res != expected {
+		t.Errorf("--- test: %s\n--- src:\n%q\n--- found:\n%q\n--- expected:\n%q\n", testname, src, res, expected)
+	}
+}
+
+func check(t *testing.T, testname string, minwidth, tabwidth, padding int, padchar byte, flags uint, src, expected string) {
+	var b buffer
+	b.init(1000)
+
+	var w Writer
+	w.Init(&b, minwidth, tabwidth, padding, padchar, flags)
+
+	// write all at once
+	title := testname + " (written all at once)"
+	b.clear()
+	write(t, title, &w, src)
+	verify(t, title, &w, &b, src, expected)
+
+	// write byte-by-byte
+	title = testname + " (written byte-by-byte)"
+	b.clear()
+	for i := 0; i < len(src); i++ {
+		write(t, title, &w, src[i:i+1])
+	}
+	verify(t, title, &w, &b, src, expected)
+
+	// write using Fibonacci slice sizes
+	title = testname + " (written in fibonacci slices)"
+	b.clear()
+	for i, d := 0, 0; i < len(src); {
+		write(t, title, &w, src[i:i+d])
+		i, d = i+d, d+1
+		if i+d > len(src) {
+			d = len(src) - i
+		}
+	}
+	verify(t, title, &w, &b, src, expected)
+}
+
+var tests = []struct {
+	testname                    string
+	minwidth, tabwidth, padding int
+	padchar                     byte
+	flags                       uint
+	src, expected               string
+}{
+	{
+		"1a",
+		8, 0, 1, '.', 0,
+		"",
+		"",
+	},
+
+	{
+		"1a debug",
+		8, 0, 1, '.', Debug,
+		"",
+		"",
+	},
+
+	{
+		"1b esc stripped",
+		8, 0, 1, '.', StripEscape,
+		"\xff\xff",
+		"",
+	},
+
+	{
+		"1b esc",
+		8, 0, 1, '.', 0,
+		"\xff\xff",
+		"\xff\xff",
+	},
+
+	{
+		"1c esc stripped",
+		8, 0, 1, '.', StripEscape,
+		"\xff\t\xff",
+		"\t",
+	},
+
+	{
+		"1c esc",
+		8, 0, 1, '.', 0,
+		"\xff\t\xff",
+		"\xff\t\xff",
+	},
+
+	{
+		"1d esc stripped",
+		8, 0, 1, '.', StripEscape,
+		"\xff\"foo\t\n\tbar\"\xff",
+		"\"foo\t\n\tbar\"",
+	},
+
+	{
+		"1d esc",
+		8, 0, 1, '.', 0,
+		"\xff\"foo\t\n\tbar\"\xff",
+		"\xff\"foo\t\n\tbar\"\xff",
+	},
+
+	{
+		"1e esc stripped",
+		8, 0, 1, '.', StripEscape,
+		"abc\xff\tdef", // unterminated escape
+		"abc\tdef",
+	},
+
+	{
+		"1e esc",
+		8, 0, 1, '.', 0,
+		"abc\xff\tdef", // unterminated escape
+		"abc\xff\tdef",
+	},
+
+	{
+		"2",
+		8, 0, 1, '.', 0,
+		"\n\n\n",
+		"\n\n\n",
+	},
+
+	{
+		"3",
+		8, 0, 1, '.', 0,
+		"a\nb\nc",
+		"a\nb\nc",
+	},
+
+	{
+		"4a",
+		8, 0, 1, '.', 0,
+		"\t", // '\t' terminates an empty cell on last line - nothing to print
+		"",
+	},
+
+	{
+		"4b",
+		8, 0, 1, '.', AlignRight,
+		"\t", // '\t' terminates an empty cell on last line - nothing to print
+		"",
+	},
+
+	{
+		"5",
+		8, 0, 1, '.', 0,
+		"*\t*",
+		"*.......*",
+	},
+
+	{
+		"5b",
+		8, 0, 1, '.', 0,
+		"*\t*\n",
+		"*.......*\n",
+	},
+
+	{
+		"5c",
+		8, 0, 1, '.', 0,
+		"*\t*\t",
+		"*.......*",
+	},
+
+	{
+		"5c debug",
+		8, 0, 1, '.', Debug,
+		"*\t*\t",
+		"*.......|*",
+	},
+
+	{
+		"5d",
+		8, 0, 1, '.', AlignRight,
+		"*\t*\t",
+		".......**",
+	},
+
+	{
+		"6",
+		8, 0, 1, '.', 0,
+		"\t\n",
+		"........\n",
+	},
+
+	{
+		"7a",
+		8, 0, 1, '.', 0,
+		"a) foo",
+		"a) foo",
+	},
+
+	{
+		"7b",
+		8, 0, 1, ' ', 0,
+		"b) foo\tbar",
+		"b) foo  bar",
+	},
+
+	{
+		"7c",
+		8, 0, 1, '.', 0,
+		"c) foo\tbar\t",
+		"c) foo..bar",
+	},
+
+	{
+		"7d",
+		8, 0, 1, '.', 0,
+		"d) foo\tbar\n",
+		"d) foo..bar\n",
+	},
+
+	{
+		"7e",
+		8, 0, 1, '.', 0,
+		"e) foo\tbar\t\n",
+		"e) foo..bar.....\n",
+	},
+
+	{
+		"7f",
+		8, 0, 1, '.', FilterHTML,
+		"f) f&lt;o\t<b>bar</b>\t\n",
+		"f) f&lt;o..<b>bar</b>.....\n",
+	},
+
+	{
+		"7g",
+		8, 0, 1, '.', FilterHTML,
+		"g) f&lt;o\t<b>bar</b>\t non-terminated entity &amp",
+		"g) f&lt;o..<b>bar</b>..... non-terminated entity &amp",
+	},
+
+	{
+		"7g debug",
+		8, 0, 1, '.', FilterHTML | Debug,
+		"g) f&lt;o\t<b>bar</b>\t non-terminated entity &amp",
+		"g) f&lt;o..|<b>bar</b>.....| non-terminated entity &amp",
+	},
+
+	{
+		"8",
+		8, 0, 1, '*', 0,
+		"Hello, world!\n",
+		"Hello, world!\n",
+	},
+
+	{
+		"9a",
+		1, 0, 0, '.', 0,
+		"1\t2\t3\t4\n" +
+			"11\t222\t3333\t44444\n",
+
+		"1.2..3...4\n" +
+			"11222333344444\n",
+	},
+
+	{
+		"9b",
+		1, 0, 0, '.', FilterHTML,
+		"1\t2<!---\f--->\t3\t4\n" + // \f inside HTML is ignored
+			"11\t222\t3333\t44444\n",
+
+		"1.2<!---\f--->..3...4\n" +
+			"11222333344444\n",
+	},
+
+	{
+		"9c",
+		1, 0, 0, '.', 0,
+		"1\t2\t3\t4\f" + // \f causes a newline and flush
+			"11\t222\t3333\t44444\n",
+
+		"1234\n" +
+			"11222333344444\n",
+	},
+
+	{
+		"9c debug",
+		1, 0, 0, '.', Debug,
+		"1\t2\t3\t4\f" + // \f causes a newline and flush
+			"11\t222\t3333\t44444\n",
+
+		"1|2|3|4\n" +
+			"---\n" +
+			"11|222|3333|44444\n",
+	},
+
+	{
+		"10a",
+		5, 0, 0, '.', 0,
+		"1\t2\t3\t4\n",
+		"1....2....3....4\n",
+	},
+
+	{
+		"10b",
+		5, 0, 0, '.', 0,
+		"1\t2\t3\t4\t\n",
+		"1....2....3....4....\n",
+	},
+
+	{
+		"11",
+		8, 0, 1, '.', 0,
+		"本\tb\tc\n" +
+			"aa\t\u672c\u672c\u672c\tcccc\tddddd\n" +
+			"aaa\tbbbb\n",
+
+		"本.......b.......c\n" +
+			"aa......本本本.....cccc....ddddd\n" +
+			"aaa.....bbbb\n",
+	},
+
+	{
+		"12a",
+		8, 0, 1, ' ', AlignRight,
+		"a\tè\tc\t\n" +
+			"aa\tèèè\tcccc\tddddd\t\n" +
+			"aaa\tèèèè\t\n",
+
+		"       a       è       c\n" +
+			"      aa     èèè    cccc   ddddd\n" +
+			"     aaa    èèèè\n",
+	},
+
+	{
+		"12b",
+		2, 0, 0, ' ', 0,
+		"a\tb\tc\n" +
+			"aa\tbbb\tcccc\n" +
+			"aaa\tbbbb\n",
+
+		"a  b  c\n" +
+			"aa bbbcccc\n" +
+			"aaabbbb\n",
+	},
+
+	{
+		"12c",
+		8, 0, 1, '_', 0,
+		"a\tb\tc\n" +
+			"aa\tbbb\tcccc\n" +
+			"aaa\tbbbb\n",
+
+		"a_______b_______c\n" +
+			"aa______bbb_____cccc\n" +
+			"aaa_____bbbb\n",
+	},
+
+	{
+		"13a",
+		4, 0, 1, '-', 0,
+		"4444\t日本語\t22\t1\t333\n" +
+			"999999999\t22\n" +
+			"7\t22\n" +
+			"\t\t\t88888888\n" +
+			"\n" +
+			"666666\t666666\t666666\t4444\n" +
+			"1\t1\t999999999\t0000000000\n",
+
+		"4444------日本語-22--1---333\n" +
+			"999999999-22\n" +
+			"7---------22\n" +
+			"------------------88888888\n" +
+			"\n" +
+			"666666-666666-666666----4444\n" +
+			"1------1------999999999-0000000000\n",
+	},
+
+	{
+		"13b",
+		4, 0, 3, '.', 0,
+		"4444\t333\t22\t1\t333\n" +
+			"999999999\t22\n" +
+			"7\t22\n" +
+			"\t\t\t88888888\n" +
+			"\n" +
+			"666666\t666666\t666666\t4444\n" +
+			"1\t1\t999999999\t0000000000\n",
+
+		"4444........333...22...1...333\n" +
+			"999999999...22\n" +
+			"7...........22\n" +
+			"....................88888888\n" +
+			"\n" +
+			"666666...666666...666666......4444\n" +
+			"1........1........999999999...0000000000\n",
+	},
+
+	{
+		"13c",
+		8, 8, 1, '\t', FilterHTML,
+		"4444\t333\t22\t1\t333\n" +
+			"999999999\t22\n" +
+			"7\t22\n" +
+			"\t\t\t88888888\n" +
+			"\n" +
+			"666666\t666666\t666666\t4444\n" +
+			"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n",
+
+		"4444\t\t333\t22\t1\t333\n" +
+			"999999999\t22\n" +
+			"7\t\t22\n" +
+			"\t\t\t\t88888888\n" +
+			"\n" +
+			"666666\t666666\t666666\t\t4444\n" +
+			"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n",
+	},
+
+	{
+		"14",
+		1, 0, 2, ' ', AlignRight,
+		".0\t.3\t2.4\t-5.1\t\n" +
+			"23.0\t12345678.9\t2.4\t-989.4\t\n" +
+			"5.1\t12.0\t2.4\t-7.0\t\n" +
+			".0\t0.0\t332.0\t8908.0\t\n" +
+			".0\t-.3\t456.4\t22.1\t\n" +
+			".0\t1.2\t44.4\t-13.3\t\t",
+
+		"    .0          .3    2.4    -5.1\n" +
+			"  23.0  12345678.9    2.4  -989.4\n" +
+			"   5.1        12.0    2.4    -7.0\n" +
+			"    .0         0.0  332.0  8908.0\n" +
+			"    .0         -.3  456.4    22.1\n" +
+			"    .0         1.2   44.4   -13.3",
+	},
+
+	{
+		"14 debug",
+		1, 0, 2, ' ', AlignRight | Debug,
+		".0\t.3\t2.4\t-5.1\t\n" +
+			"23.0\t12345678.9\t2.4\t-989.4\t\n" +
+			"5.1\t12.0\t2.4\t-7.0\t\n" +
+			".0\t0.0\t332.0\t8908.0\t\n" +
+			".0\t-.3\t456.4\t22.1\t\n" +
+			".0\t1.2\t44.4\t-13.3\t\t",
+
+		"    .0|          .3|    2.4|    -5.1|\n" +
+			"  23.0|  12345678.9|    2.4|  -989.4|\n" +
+			"   5.1|        12.0|    2.4|    -7.0|\n" +
+			"    .0|         0.0|  332.0|  8908.0|\n" +
+			"    .0|         -.3|  456.4|    22.1|\n" +
+			"    .0|         1.2|   44.4|   -13.3|",
+	},
+
+	{
+		"15a",
+		4, 0, 0, '.', 0,
+		"a\t\tb",
+		"a.......b",
+	},
+
+	{
+		"15b",
+		4, 0, 0, '.', DiscardEmptyColumns,
+		"a\t\tb", // htabs - do not discard column
+		"a.......b",
+	},
+
+	{
+		"15c",
+		4, 0, 0, '.', DiscardEmptyColumns,
+		"a\v\vb",
+		"a...b",
+	},
+
+	{
+		"15d",
+		4, 0, 0, '.', AlignRight | DiscardEmptyColumns,
+		"a\v\vb",
+		"...ab",
+	},
+
+	{
+		"16a",
+		100, 100, 0, '\t', 0,
+		"a\tb\t\td\n" +
+			"a\tb\t\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+
+		"a\tb\t\td\n" +
+			"a\tb\t\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+	},
+
+	{
+		"16b",
+		100, 100, 0, '\t', DiscardEmptyColumns,
+		"a\vb\v\vd\n" +
+			"a\vb\v\vd\ve\n" +
+			"a\n" +
+			"a\vb\vc\vd\n" +
+			"a\vb\vc\vd\ve\n",
+
+		"a\tb\td\n" +
+			"a\tb\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+	},
+
+	{
+		"16b debug",
+		100, 100, 0, '\t', DiscardEmptyColumns | Debug,
+		"a\vb\v\vd\n" +
+			"a\vb\v\vd\ve\n" +
+			"a\n" +
+			"a\vb\vc\vd\n" +
+			"a\vb\vc\vd\ve\n",
+
+		"a\t|b\t||d\n" +
+			"a\t|b\t||d\t|e\n" +
+			"a\n" +
+			"a\t|b\t|c\t|d\n" +
+			"a\t|b\t|c\t|d\t|e\n",
+	},
+
+	{
+		"16c",
+		100, 100, 0, '\t', DiscardEmptyColumns,
+		"a\tb\t\td\n" + // hard tabs - do not discard column
+			"a\tb\t\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+
+		"a\tb\t\td\n" +
+			"a\tb\t\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+	},
+
+	{
+		"16c debug",
+		100, 100, 0, '\t', DiscardEmptyColumns | Debug,
+		"a\tb\t\td\n" + // hard tabs - do not discard column
+			"a\tb\t\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+
+		"a\t|b\t|\t|d\n" +
+			"a\t|b\t|\t|d\t|e\n" +
+			"a\n" +
+			"a\t|b\t|c\t|d\n" +
+			"a\t|b\t|c\t|d\t|e\n",
+	},
+}
+
+func Test(t *testing.T) {
+	for _, e := range tests {
+		check(t, e.testname, e.minwidth, e.tabwidth, e.padding, e.padchar, e.flags, e.src, e.expected)
+	}
+}
+
+type panicWriter struct{}
+
+func (panicWriter) Write([]byte) (int, error) {
+	panic("cannot write")
+}
+
+func wantPanicString(t *testing.T, want string) {
+	if e := recover(); e != nil {
+		got, ok := e.(string)
+		switch {
+		case !ok:
+			t.Errorf("got %v (%T), want panic string", e, e)
+		case got != want:
+			t.Errorf("wrong panic message: got %q, want %q", got, want)
+		}
+	}
+}
+
+func TestPanicDuringFlush(t *testing.T) {
+	defer wantPanicString(t, "tabwriter: panic during Flush")
+	var p panicWriter
+	w := new(Writer)
+	w.Init(p, 0, 0, 5, ' ', 0)
+	io.WriteString(w, "a")
+	w.Flush()
+	t.Errorf("failed to panic during Flush")
+}
+
+func TestPanicDuringWrite(t *testing.T) {
+	defer wantPanicString(t, "tabwriter: panic during Write")
+	var p panicWriter
+	w := new(Writer)
+	w.Init(p, 0, 0, 5, ' ', 0)
+	io.WriteString(w, "a\n\n") // the second \n triggers a call to w.Write and thus a panic
+	t.Errorf("failed to panic during Write")
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/doc.go b/third_party/gofrontend/libgo/go/text/template/doc.go
new file mode 100644
index 0000000..7c6efd5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/doc.go
@@ -0,0 +1,405 @@
+// 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.
+
+/*
+Package template implements data-driven templates for generating textual output.
+
+To generate HTML output, see package html/template, which has the same interface
+as this package but automatically secures HTML output against certain attacks.
+
+Templates are executed by applying them to a data structure. Annotations in the
+template refer to elements of the data structure (typically a field of a struct
+or a key in a map) to control execution and derive values to be displayed.
+Execution of the template walks the structure and sets the cursor, represented
+by a period '.' and called "dot", to the value at the current location in the
+structure as execution proceeds.
+
+The input text for a template is UTF-8-encoded text in any format.
+"Actions"--data evaluations or control structures--are delimited by
+"{{" and "}}"; all text outside actions is copied to the output unchanged.
+Actions may not span newlines, although comments can.
+
+Once parsed, a template may be executed safely in parallel.
+
+Here is a trivial example that prints "17 items are made of wool".
+
+	type Inventory struct {
+		Material string
+		Count    uint
+	}
+	sweaters := Inventory{"wool", 17}
+	tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
+	if err != nil { panic(err) }
+	err = tmpl.Execute(os.Stdout, sweaters)
+	if err != nil { panic(err) }
+
+More intricate examples appear below.
+
+Actions
+
+Here is the list of actions. "Arguments" and "pipelines" are evaluations of
+data, defined in detail below.
+
+*/
+//	{{/* a comment */}}
+//		A comment; discarded. May contain newlines.
+//		Comments do not nest and must start and end at the
+//		delimiters, as shown here.
+/*
+
+	{{pipeline}}
+		The default textual representation of the value of the pipeline
+		is copied to the output.
+
+	{{if pipeline}} T1 {{end}}
+		If the value of the pipeline is empty, no output is generated;
+		otherwise, T1 is executed.  The empty values are false, 0, any
+		nil pointer or interface value, and any array, slice, map, or
+		string of length zero.
+		Dot is unaffected.
+
+	{{if pipeline}} T1 {{else}} T0 {{end}}
+		If the value of the pipeline is empty, T0 is executed;
+		otherwise, T1 is executed.  Dot is unaffected.
+
+	{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
+		To simplify the appearance of if-else chains, the else action
+		of an if may include another if directly; the effect is exactly
+		the same as writing
+			{{if pipeline}} T1 {{else}}{{if pipeline}} T0 {{end}}{{end}}
+
+	{{range pipeline}} T1 {{end}}
+		The value of the pipeline must be an array, slice, map, or channel.
+		If the value of the pipeline has length zero, nothing is output;
+		otherwise, dot is set to the successive elements of the array,
+		slice, or map and T1 is executed. If the value is a map and the
+		keys are of basic type with a defined order ("comparable"), the
+		elements will be visited in sorted key order.
+
+	{{range pipeline}} T1 {{else}} T0 {{end}}
+		The value of the pipeline must be an array, slice, map, or channel.
+		If the value of the pipeline has length zero, dot is unaffected and
+		T0 is executed; otherwise, dot is set to the successive elements
+		of the array, slice, or map and T1 is executed.
+
+	{{template "name"}}
+		The template with the specified name is executed with nil data.
+
+	{{template "name" pipeline}}
+		The template with the specified name is executed with dot set
+		to the value of the pipeline.
+
+	{{with pipeline}} T1 {{end}}
+		If the value of the pipeline is empty, no output is generated;
+		otherwise, dot is set to the value of the pipeline and T1 is
+		executed.
+
+	{{with pipeline}} T1 {{else}} T0 {{end}}
+		If the value of the pipeline is empty, dot is unaffected and T0
+		is executed; otherwise, dot is set to the value of the pipeline
+		and T1 is executed.
+
+Arguments
+
+An argument is a simple value, denoted by one of the following.
+
+	- A boolean, string, character, integer, floating-point, imaginary
+	  or complex constant in Go syntax. These behave like Go's untyped
+	  constants, although raw strings may not span newlines.
+	- The keyword nil, representing an untyped Go nil.
+	- The character '.' (period):
+		.
+	  The result is the value of dot.
+	- A variable name, which is a (possibly empty) alphanumeric string
+	  preceded by a dollar sign, such as
+		$piOver2
+	  or
+		$
+	  The result is the value of the variable.
+	  Variables are described below.
+	- The name of a field of the data, which must be a struct, preceded
+	  by a period, such as
+		.Field
+	  The result is the value of the field. Field invocations may be
+	  chained:
+	    .Field1.Field2
+	  Fields can also be evaluated on variables, including chaining:
+	    $x.Field1.Field2
+	- The name of a key of the data, which must be a map, preceded
+	  by a period, such as
+		.Key
+	  The result is the map element value indexed by the key.
+	  Key invocations may be chained and combined with fields to any
+	  depth:
+	    .Field1.Key1.Field2.Key2
+	  Although the key must be an alphanumeric identifier, unlike with
+	  field names they do not need to start with an upper case letter.
+	  Keys can also be evaluated on variables, including chaining:
+	    $x.key1.key2
+	- The name of a niladic method of the data, preceded by a period,
+	  such as
+		.Method
+	  The result is the value of invoking the method with dot as the
+	  receiver, dot.Method(). Such a method must have one return value (of
+	  any type) or two return values, the second of which is an error.
+	  If it has two and the returned error is non-nil, execution terminates
+	  and an error is returned to the caller as the value of Execute.
+	  Method invocations may be chained and combined with fields and keys
+	  to any depth:
+	    .Field1.Key1.Method1.Field2.Key2.Method2
+	  Methods can also be evaluated on variables, including chaining:
+	    $x.Method1.Field
+	- The name of a niladic function, such as
+		fun
+	  The result is the value of invoking the function, fun(). The return
+	  types and values behave as in methods. Functions and function
+	  names are described below.
+	- A parenthesized instance of one the above, for grouping. The result
+	  may be accessed by a field or map key invocation.
+		print (.F1 arg1) (.F2 arg2)
+		(.StructValuedMethod "arg").Field
+
+Arguments may evaluate to any type; if they are pointers the implementation
+automatically indirects to the base type when required.
+If an evaluation yields a function value, such as a function-valued
+field of a struct, the function is not invoked automatically, but it
+can be used as a truth value for an if action and the like. To invoke
+it, use the call function, defined below.
+
+A pipeline is a possibly chained sequence of "commands". A command is a simple
+value (argument) or a function or method call, possibly with multiple arguments:
+
+	Argument
+		The result is the value of evaluating the argument.
+	.Method [Argument...]
+		The method can be alone or the last element of a chain but,
+		unlike methods in the middle of a chain, it can take arguments.
+		The result is the value of calling the method with the
+		arguments:
+			dot.Method(Argument1, etc.)
+	functionName [Argument...]
+		The result is the value of calling the function associated
+		with the name:
+			function(Argument1, etc.)
+		Functions and function names are described below.
+
+Pipelines
+
+A pipeline may be "chained" by separating a sequence of commands with pipeline
+characters '|'. In a chained pipeline, the result of the each command is
+passed as the last argument of the following command. The output of the final
+command in the pipeline is the value of the pipeline.
+
+The output of a command will be either one value or two values, the second of
+which has type error. If that second value is present and evaluates to
+non-nil, execution terminates and the error is returned to the caller of
+Execute.
+
+Variables
+
+A pipeline inside an action may initialize a variable to capture the result.
+The initialization has syntax
+
+	$variable := pipeline
+
+where $variable is the name of the variable. An action that declares a
+variable produces no output.
+
+If a "range" action initializes a variable, the variable is set to the
+successive elements of the iteration.  Also, a "range" may declare two
+variables, separated by a comma:
+
+	range $index, $element := pipeline
+
+in which case $index and $element are set to the successive values of the
+array/slice index or map key and element, respectively.  Note that if there is
+only one variable, it is assigned the element; this is opposite to the
+convention in Go range clauses.
+
+A variable's scope extends to the "end" action of the control structure ("if",
+"with", or "range") in which it is declared, or to the end of the template if
+there is no such control structure.  A template invocation does not inherit
+variables from the point of its invocation.
+
+When execution begins, $ is set to the data argument passed to Execute, that is,
+to the starting value of dot.
+
+Examples
+
+Here are some example one-line templates demonstrating pipelines and variables.
+All produce the quoted word "output":
+
+	{{"\"output\""}}
+		A string constant.
+	{{`"output"`}}
+		A raw string constant.
+	{{printf "%q" "output"}}
+		A function call.
+	{{"output" | printf "%q"}}
+		A function call whose final argument comes from the previous
+		command.
+	{{printf "%q" (print "out" "put")}}
+		A parenthesized argument.
+	{{"put" | printf "%s%s" "out" | printf "%q"}}
+		A more elaborate call.
+	{{"output" | printf "%s" | printf "%q"}}
+		A longer chain.
+	{{with "output"}}{{printf "%q" .}}{{end}}
+		A with action using dot.
+	{{with $x := "output" | printf "%q"}}{{$x}}{{end}}
+		A with action that creates and uses a variable.
+	{{with $x := "output"}}{{printf "%q" $x}}{{end}}
+		A with action that uses the variable in another action.
+	{{with $x := "output"}}{{$x | printf "%q"}}{{end}}
+		The same, but pipelined.
+
+Functions
+
+During execution functions are found in two function maps: first in the
+template, then in the global function map. By default, no functions are defined
+in the template but the Funcs method can be used to add them.
+
+Predefined global functions are named as follows.
+
+	and
+		Returns the boolean AND of its arguments by returning the
+		first empty argument or the last argument, that is,
+		"and x y" behaves as "if x then y else x". All the
+		arguments are evaluated.
+	call
+		Returns the result of calling the first argument, which
+		must be a function, with the remaining arguments as parameters.
+		Thus "call .X.Y 1 2" is, in Go notation, dot.X.Y(1, 2) where
+		Y is a func-valued field, map entry, or the like.
+		The first argument must be the result of an evaluation
+		that yields a value of function type (as distinct from
+		a predefined function such as print). The function must
+		return either one or two result values, the second of which
+		is of type error. If the arguments don't match the function
+		or the returned error value is non-nil, execution stops.
+	html
+		Returns the escaped HTML equivalent of the textual
+		representation of its arguments.
+	index
+		Returns the result of indexing its first argument by the
+		following arguments. Thus "index x 1 2 3" is, in Go syntax,
+		x[1][2][3]. Each indexed item must be a map, slice, or array.
+	js
+		Returns the escaped JavaScript equivalent of the textual
+		representation of its arguments.
+	len
+		Returns the integer length of its argument.
+	not
+		Returns the boolean negation of its single argument.
+	or
+		Returns the boolean OR of its arguments by returning the
+		first non-empty argument or the last argument, that is,
+		"or x y" behaves as "if x then x else y". All the
+		arguments are evaluated.
+	print
+		An alias for fmt.Sprint
+	printf
+		An alias for fmt.Sprintf
+	println
+		An alias for fmt.Sprintln
+	urlquery
+		Returns the escaped value of the textual representation of
+		its arguments in a form suitable for embedding in a URL query.
+
+The boolean functions take any zero value to be false and a non-zero
+value to be true.
+
+There is also a set of binary comparison operators defined as
+functions:
+
+	eq
+		Returns the boolean truth of arg1 == arg2
+	ne
+		Returns the boolean truth of arg1 != arg2
+	lt
+		Returns the boolean truth of arg1 < arg2
+	le
+		Returns the boolean truth of arg1 <= arg2
+	gt
+		Returns the boolean truth of arg1 > arg2
+	ge
+		Returns the boolean truth of arg1 >= arg2
+
+For simpler multi-way equality tests, eq (only) accepts two or more
+arguments and compares the second and subsequent to the first,
+returning in effect
+
+	arg1==arg2 || arg1==arg3 || arg1==arg4 ...
+
+(Unlike with || in Go, however, eq is a function call and all the
+arguments will be evaluated.)
+
+The comparison functions work on basic types only (or named basic
+types, such as "type Celsius float32"). They implement the Go rules
+for comparison of values, except that size and exact type are
+ignored, so any integer value may be compared with any other integer
+value, any unsigned integer value may be compared with any other
+unsigned integer value, and so on. However, as usual, one may not
+compare an int with a float32 and so on.
+
+Associated templates
+
+Each template is named by a string specified when it is created. Also, each
+template is associated with zero or more other templates that it may invoke by
+name; such associations are transitive and form a name space of templates.
+
+A template may use a template invocation to instantiate another associated
+template; see the explanation of the "template" action above. The name must be
+that of a template associated with the template that contains the invocation.
+
+Nested template definitions
+
+When parsing a template, another template may be defined and associated with the
+template being parsed. Template definitions must appear at the top level of the
+template, much like global variables in a Go program.
+
+The syntax of such definitions is to surround each template declaration with a
+"define" and "end" action.
+
+The define action names the template being created by providing a string
+constant. Here is a simple example:
+
+	`{{define "T1"}}ONE{{end}}
+	{{define "T2"}}TWO{{end}}
+	{{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
+	{{template "T3"}}`
+
+This defines two templates, T1 and T2, and a third T3 that invokes the other two
+when it is executed. Finally it invokes T3. If executed this template will
+produce the text
+
+	ONE TWO
+
+By construction, a template may reside in only one association. If it's
+necessary to have a template addressable from multiple associations, the
+template definition must be parsed multiple times to create distinct *Template
+values, or must be copied with the Clone or AddParseTree method.
+
+Parse may be called multiple times to assemble the various associated templates;
+see the ParseFiles and ParseGlob functions and methods for simple ways to parse
+related templates stored in files.
+
+A template may be executed directly or through ExecuteTemplate, which executes
+an associated template identified by name. To invoke our example above, we
+might write,
+
+	err := tmpl.Execute(os.Stdout, "no data needed")
+	if err != nil {
+		log.Fatalf("execution failed: %s", err)
+	}
+
+or to invoke a particular template explicitly by name,
+
+	err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed")
+	if err != nil {
+		log.Fatalf("execution failed: %s", err)
+	}
+
+*/
+package template
diff --git a/third_party/gofrontend/libgo/go/text/template/exec.go b/third_party/gofrontend/libgo/go/text/template/exec.go
new file mode 100644
index 0000000..2f32312
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/exec.go
@@ -0,0 +1,838 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"runtime"
+	"sort"
+	"strings"
+	"text/template/parse"
+)
+
+// state represents the state of an execution. It's not part of the
+// template so that multiple executions of the same template
+// can execute in parallel.
+type state struct {
+	tmpl *Template
+	wr   io.Writer
+	node parse.Node // current node, for errors
+	vars []variable // push-down stack of variable values.
+}
+
+// variable holds the dynamic value of a variable such as $, $x etc.
+type variable struct {
+	name  string
+	value reflect.Value
+}
+
+// push pushes a new variable on the stack.
+func (s *state) push(name string, value reflect.Value) {
+	s.vars = append(s.vars, variable{name, value})
+}
+
+// mark returns the length of the variable stack.
+func (s *state) mark() int {
+	return len(s.vars)
+}
+
+// pop pops the variable stack up to the mark.
+func (s *state) pop(mark int) {
+	s.vars = s.vars[0:mark]
+}
+
+// setVar overwrites the top-nth variable on the stack. Used by range iterations.
+func (s *state) setVar(n int, value reflect.Value) {
+	s.vars[len(s.vars)-n].value = value
+}
+
+// varValue returns the value of the named variable.
+func (s *state) varValue(name string) reflect.Value {
+	for i := s.mark() - 1; i >= 0; i-- {
+		if s.vars[i].name == name {
+			return s.vars[i].value
+		}
+	}
+	s.errorf("undefined variable: %s", name)
+	return zero
+}
+
+var zero reflect.Value
+
+// at marks the state to be on node n, for error reporting.
+func (s *state) at(node parse.Node) {
+	s.node = node
+}
+
+// doublePercent returns the string with %'s replaced by %%, if necessary,
+// so it can be used safely inside a Printf format string.
+func doublePercent(str string) string {
+	if strings.Contains(str, "%") {
+		str = strings.Replace(str, "%", "%%", -1)
+	}
+	return str
+}
+
+// errorf formats the error and terminates processing.
+func (s *state) errorf(format string, args ...interface{}) {
+	name := doublePercent(s.tmpl.Name())
+	if s.node == nil {
+		format = fmt.Sprintf("template: %s: %s", name, format)
+	} else {
+		location, context := s.tmpl.ErrorContext(s.node)
+		format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format)
+	}
+	panic(fmt.Errorf(format, args...))
+}
+
+// errRecover is the handler that turns panics into returns from the top
+// level of Parse.
+func errRecover(errp *error) {
+	e := recover()
+	if e != nil {
+		switch err := e.(type) {
+		case runtime.Error:
+			panic(e)
+		case error:
+			*errp = err
+		default:
+			panic(e)
+		}
+	}
+}
+
+// ExecuteTemplate applies the template associated with t that has the given name
+// to the specified data object and writes the output to wr.
+// If an error occurs executing the template or writing its output,
+// execution stops, but partial results may already have been written to
+// the output writer.
+// A template may be executed safely in parallel.
+func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
+	tmpl := t.tmpl[name]
+	if tmpl == nil {
+		return fmt.Errorf("template: no template %q associated with template %q", name, t.name)
+	}
+	return tmpl.Execute(wr, data)
+}
+
+// Execute applies a parsed template to the specified data object,
+// and writes the output to wr.
+// If an error occurs executing the template or writing its output,
+// execution stops, but partial results may already have been written to
+// the output writer.
+// A template may be executed safely in parallel.
+func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
+	defer errRecover(&err)
+	value := reflect.ValueOf(data)
+	state := &state{
+		tmpl: t,
+		wr:   wr,
+		vars: []variable{{"$", value}},
+	}
+	t.init()
+	if t.Tree == nil || t.Root == nil {
+		var b bytes.Buffer
+		for name, tmpl := range t.tmpl {
+			if tmpl.Tree == nil || tmpl.Root == nil {
+				continue
+			}
+			if b.Len() > 0 {
+				b.WriteString(", ")
+			}
+			fmt.Fprintf(&b, "%q", name)
+		}
+		var s string
+		if b.Len() > 0 {
+			s = "; defined templates are: " + b.String()
+		}
+		state.errorf("%q is an incomplete or empty template%s", t.Name(), s)
+	}
+	state.walk(value, t.Root)
+	return
+}
+
+// Walk functions step through the major pieces of the template structure,
+// generating output as they go.
+func (s *state) walk(dot reflect.Value, node parse.Node) {
+	s.at(node)
+	switch node := node.(type) {
+	case *parse.ActionNode:
+		// Do not pop variables so they persist until next end.
+		// Also, if the action declares variables, don't print the result.
+		val := s.evalPipeline(dot, node.Pipe)
+		if len(node.Pipe.Decl) == 0 {
+			s.printValue(node, val)
+		}
+	case *parse.IfNode:
+		s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
+	case *parse.ListNode:
+		for _, node := range node.Nodes {
+			s.walk(dot, node)
+		}
+	case *parse.RangeNode:
+		s.walkRange(dot, node)
+	case *parse.TemplateNode:
+		s.walkTemplate(dot, node)
+	case *parse.TextNode:
+		if _, err := s.wr.Write(node.Text); err != nil {
+			s.errorf("%s", err)
+		}
+	case *parse.WithNode:
+		s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
+	default:
+		s.errorf("unknown node: %s", node)
+	}
+}
+
+// walkIfOrWith walks an 'if' or 'with' node. The two control structures
+// are identical in behavior except that 'with' sets dot.
+func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) {
+	defer s.pop(s.mark())
+	val := s.evalPipeline(dot, pipe)
+	truth, ok := isTrue(val)
+	if !ok {
+		s.errorf("if/with can't use %v", val)
+	}
+	if truth {
+		if typ == parse.NodeWith {
+			s.walk(val, list)
+		} else {
+			s.walk(dot, list)
+		}
+	} else if elseList != nil {
+		s.walk(dot, elseList)
+	}
+}
+
+// isTrue reports whether the value is 'true', in the sense of not the zero of its type,
+// and whether the value has a meaningful truth value.
+func isTrue(val reflect.Value) (truth, ok bool) {
+	if !val.IsValid() {
+		// Something like var x interface{}, never set. It's a form of nil.
+		return false, true
+	}
+	switch val.Kind() {
+	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+		truth = val.Len() > 0
+	case reflect.Bool:
+		truth = val.Bool()
+	case reflect.Complex64, reflect.Complex128:
+		truth = val.Complex() != 0
+	case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface:
+		truth = !val.IsNil()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		truth = val.Int() != 0
+	case reflect.Float32, reflect.Float64:
+		truth = val.Float() != 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		truth = val.Uint() != 0
+	case reflect.Struct:
+		truth = true // Struct values are always true.
+	default:
+		return
+	}
+	return truth, true
+}
+
+func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
+	s.at(r)
+	defer s.pop(s.mark())
+	val, _ := indirect(s.evalPipeline(dot, r.Pipe))
+	// mark top of stack before any variables in the body are pushed.
+	mark := s.mark()
+	oneIteration := func(index, elem reflect.Value) {
+		// Set top var (lexically the second if there are two) to the element.
+		if len(r.Pipe.Decl) > 0 {
+			s.setVar(1, elem)
+		}
+		// Set next var (lexically the first if there are two) to the index.
+		if len(r.Pipe.Decl) > 1 {
+			s.setVar(2, index)
+		}
+		s.walk(elem, r.List)
+		s.pop(mark)
+	}
+	switch val.Kind() {
+	case reflect.Array, reflect.Slice:
+		if val.Len() == 0 {
+			break
+		}
+		for i := 0; i < val.Len(); i++ {
+			oneIteration(reflect.ValueOf(i), val.Index(i))
+		}
+		return
+	case reflect.Map:
+		if val.Len() == 0 {
+			break
+		}
+		for _, key := range sortKeys(val.MapKeys()) {
+			oneIteration(key, val.MapIndex(key))
+		}
+		return
+	case reflect.Chan:
+		if val.IsNil() {
+			break
+		}
+		i := 0
+		for ; ; i++ {
+			elem, ok := val.Recv()
+			if !ok {
+				break
+			}
+			oneIteration(reflect.ValueOf(i), elem)
+		}
+		if i == 0 {
+			break
+		}
+		return
+	case reflect.Invalid:
+		break // An invalid value is likely a nil map, etc. and acts like an empty map.
+	default:
+		s.errorf("range can't iterate over %v", val)
+	}
+	if r.ElseList != nil {
+		s.walk(dot, r.ElseList)
+	}
+}
+
+func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
+	s.at(t)
+	tmpl := s.tmpl.tmpl[t.Name]
+	if tmpl == nil {
+		s.errorf("template %q not defined", t.Name)
+	}
+	// Variables declared by the pipeline persist.
+	dot = s.evalPipeline(dot, t.Pipe)
+	newState := *s
+	newState.tmpl = tmpl
+	// No dynamic scoping: template invocations inherit no variables.
+	newState.vars = []variable{{"$", dot}}
+	newState.walk(dot, tmpl.Root)
+}
+
+// Eval functions evaluate pipelines, commands, and their elements and extract
+// values from the data structure by examining fields, calling methods, and so on.
+// The printing of those values happens only through walk functions.
+
+// evalPipeline returns the value acquired by evaluating a pipeline. If the
+// pipeline has a variable declaration, the variable will be pushed on the
+// stack. Callers should therefore pop the stack after they are finished
+// executing commands depending on the pipeline value.
+func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value reflect.Value) {
+	if pipe == nil {
+		return
+	}
+	s.at(pipe)
+	for _, cmd := range pipe.Cmds {
+		value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
+		// If the object has type interface{}, dig down one level to the thing inside.
+		if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 {
+			value = reflect.ValueOf(value.Interface()) // lovely!
+		}
+	}
+	for _, variable := range pipe.Decl {
+		s.push(variable.Ident[0], value)
+	}
+	return value
+}
+
+func (s *state) notAFunction(args []parse.Node, final reflect.Value) {
+	if len(args) > 1 || final.IsValid() {
+		s.errorf("can't give argument to non-function %s", args[0])
+	}
+}
+
+func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final reflect.Value) reflect.Value {
+	firstWord := cmd.Args[0]
+	switch n := firstWord.(type) {
+	case *parse.FieldNode:
+		return s.evalFieldNode(dot, n, cmd.Args, final)
+	case *parse.ChainNode:
+		return s.evalChainNode(dot, n, cmd.Args, final)
+	case *parse.IdentifierNode:
+		// Must be a function.
+		return s.evalFunction(dot, n, cmd, cmd.Args, final)
+	case *parse.PipeNode:
+		// Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored.
+		return s.evalPipeline(dot, n)
+	case *parse.VariableNode:
+		return s.evalVariableNode(dot, n, cmd.Args, final)
+	}
+	s.at(firstWord)
+	s.notAFunction(cmd.Args, final)
+	switch word := firstWord.(type) {
+	case *parse.BoolNode:
+		return reflect.ValueOf(word.True)
+	case *parse.DotNode:
+		return dot
+	case *parse.NilNode:
+		s.errorf("nil is not a command")
+	case *parse.NumberNode:
+		return s.idealConstant(word)
+	case *parse.StringNode:
+		return reflect.ValueOf(word.Text)
+	}
+	s.errorf("can't evaluate command %q", firstWord)
+	panic("not reached")
+}
+
+// idealConstant is called to return the value of a number in a context where
+// we don't know the type. In that case, the syntax of the number tells us
+// its type, and we use Go rules to resolve.  Note there is no such thing as
+// a uint ideal constant in this situation - the value must be of int type.
+func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
+	// These are ideal constants but we don't know the type
+	// and we have no context.  (If it was a method argument,
+	// we'd know what we need.) The syntax guides us to some extent.
+	s.at(constant)
+	switch {
+	case constant.IsComplex:
+		return reflect.ValueOf(constant.Complex128) // incontrovertible.
+	case constant.IsFloat && strings.IndexAny(constant.Text, ".eE") >= 0:
+		return reflect.ValueOf(constant.Float64)
+	case constant.IsInt:
+		n := int(constant.Int64)
+		if int64(n) != constant.Int64 {
+			s.errorf("%s overflows int", constant.Text)
+		}
+		return reflect.ValueOf(n)
+	case constant.IsUint:
+		s.errorf("%s overflows int", constant.Text)
+	}
+	return zero
+}
+
+func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value {
+	s.at(field)
+	return s.evalFieldChain(dot, dot, field, field.Ident, args, final)
+}
+
+func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value {
+	s.at(chain)
+	// (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields.
+	pipe := s.evalArg(dot, nil, chain.Node)
+	if len(chain.Field) == 0 {
+		s.errorf("internal error: no fields in evalChainNode")
+	}
+	return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final)
+}
+
+func (s *state) evalVariableNode(dot reflect.Value, variable *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
+	// $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
+	s.at(variable)
+	value := s.varValue(variable.Ident[0])
+	if len(variable.Ident) == 1 {
+		s.notAFunction(args, final)
+		return value
+	}
+	return s.evalFieldChain(dot, value, variable, variable.Ident[1:], args, final)
+}
+
+// evalFieldChain evaluates .X.Y.Z possibly followed by arguments.
+// dot is the environment in which to evaluate arguments, while
+// receiver is the value being walked along the chain.
+func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
+	n := len(ident)
+	for i := 0; i < n-1; i++ {
+		receiver = s.evalField(dot, ident[i], node, nil, zero, receiver)
+	}
+	// Now if it's a method, it gets the arguments.
+	return s.evalField(dot, ident[n-1], node, args, final, receiver)
+}
+
+func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value {
+	s.at(node)
+	name := node.Ident
+	function, ok := findFunction(name, s.tmpl)
+	if !ok {
+		s.errorf("%q is not a defined function", name)
+	}
+	return s.evalCall(dot, function, cmd, name, args, final)
+}
+
+// evalField evaluates an expression like (.Field) or (.Field arg1 arg2).
+// The 'final' argument represents the return value from the preceding
+// value of the pipeline, if any.
+func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value {
+	if !receiver.IsValid() {
+		return zero
+	}
+	typ := receiver.Type()
+	receiver, _ = indirect(receiver)
+	// Unless it's an interface, need to get to a value of type *T to guarantee
+	// we see all methods of T and *T.
+	ptr := receiver
+	if ptr.Kind() != reflect.Interface && ptr.CanAddr() {
+		ptr = ptr.Addr()
+	}
+	if method := ptr.MethodByName(fieldName); method.IsValid() {
+		return s.evalCall(dot, method, node, fieldName, args, final)
+	}
+	hasArgs := len(args) > 1 || final.IsValid()
+	// It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
+	receiver, isNil := indirect(receiver)
+	if isNil {
+		s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
+	}
+	switch receiver.Kind() {
+	case reflect.Struct:
+		tField, ok := receiver.Type().FieldByName(fieldName)
+		if ok {
+			field := receiver.FieldByIndex(tField.Index)
+			if tField.PkgPath != "" { // field is unexported
+				s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
+			}
+			// If it's a function, we must call it.
+			if hasArgs {
+				s.errorf("%s has arguments but cannot be invoked as function", fieldName)
+			}
+			return field
+		}
+		s.errorf("%s is not a field of struct type %s", fieldName, typ)
+	case reflect.Map:
+		// If it's a map, attempt to use the field name as a key.
+		nameVal := reflect.ValueOf(fieldName)
+		if nameVal.Type().AssignableTo(receiver.Type().Key()) {
+			if hasArgs {
+				s.errorf("%s is not a method but has arguments", fieldName)
+			}
+			return receiver.MapIndex(nameVal)
+		}
+	}
+	s.errorf("can't evaluate field %s in type %s", fieldName, typ)
+	panic("not reached")
+}
+
+var (
+	errorType       = reflect.TypeOf((*error)(nil)).Elem()
+	fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+)
+
+// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
+// it looks just like a function call.  The arg list, if non-nil, includes (in the manner of the shell), arg[0]
+// as the function itself.
+func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value {
+	if args != nil {
+		args = args[1:] // Zeroth arg is function name/node; not passed to function.
+	}
+	typ := fun.Type()
+	numIn := len(args)
+	if final.IsValid() {
+		numIn++
+	}
+	numFixed := len(args)
+	if typ.IsVariadic() {
+		numFixed = typ.NumIn() - 1 // last arg is the variadic one.
+		if numIn < numFixed {
+			s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args))
+		}
+	} else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.NumIn() {
+		s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args))
+	}
+	if !goodFunc(typ) {
+		// TODO: This could still be a confusing error; maybe goodFunc should provide info.
+		s.errorf("can't call method/function %q with %d results", name, typ.NumOut())
+	}
+	// Build the arg list.
+	argv := make([]reflect.Value, numIn)
+	// Args must be evaluated. Fixed args first.
+	i := 0
+	for ; i < numFixed; i++ {
+		argv[i] = s.evalArg(dot, typ.In(i), args[i])
+	}
+	// Now the ... args.
+	if typ.IsVariadic() {
+		argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice.
+		for ; i < len(args); i++ {
+			argv[i] = s.evalArg(dot, argType, args[i])
+		}
+	}
+	// Add final value if necessary.
+	if final.IsValid() {
+		t := typ.In(typ.NumIn() - 1)
+		if typ.IsVariadic() {
+			t = t.Elem()
+		}
+		argv[i] = s.validateType(final, t)
+	}
+	result := fun.Call(argv)
+	// If we have an error that is not nil, stop execution and return that error to the caller.
+	if len(result) == 2 && !result[1].IsNil() {
+		s.at(node)
+		s.errorf("error calling %s: %s", name, result[1].Interface().(error))
+	}
+	return result[0]
+}
+
+// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
+func canBeNil(typ reflect.Type) bool {
+	switch typ.Kind() {
+	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+		return true
+	}
+	return false
+}
+
+// validateType guarantees that the value is valid and assignable to the type.
+func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
+	if !value.IsValid() {
+		if typ == nil || canBeNil(typ) {
+			// An untyped nil interface{}. Accept as a proper nil value.
+			return reflect.Zero(typ)
+		}
+		s.errorf("invalid value; expected %s", typ)
+	}
+	if typ != nil && !value.Type().AssignableTo(typ) {
+		if value.Kind() == reflect.Interface && !value.IsNil() {
+			value = value.Elem()
+			if value.Type().AssignableTo(typ) {
+				return value
+			}
+			// fallthrough
+		}
+		// Does one dereference or indirection work? We could do more, as we
+		// do with method receivers, but that gets messy and method receivers
+		// are much more constrained, so it makes more sense there than here.
+		// Besides, one is almost always all you need.
+		switch {
+		case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ):
+			value = value.Elem()
+			if !value.IsValid() {
+				s.errorf("dereference of nil pointer of type %s", typ)
+			}
+		case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr():
+			value = value.Addr()
+		default:
+			s.errorf("wrong type for value; expected %s; got %s", typ, value.Type())
+		}
+	}
+	return value
+}
+
+func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
+	switch arg := n.(type) {
+	case *parse.DotNode:
+		return s.validateType(dot, typ)
+	case *parse.NilNode:
+		if canBeNil(typ) {
+			return reflect.Zero(typ)
+		}
+		s.errorf("cannot assign nil to %s", typ)
+	case *parse.FieldNode:
+		return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ)
+	case *parse.VariableNode:
+		return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
+	case *parse.PipeNode:
+		return s.validateType(s.evalPipeline(dot, arg), typ)
+	case *parse.IdentifierNode:
+		return s.evalFunction(dot, arg, arg, nil, zero)
+	}
+	switch typ.Kind() {
+	case reflect.Bool:
+		return s.evalBool(typ, n)
+	case reflect.Complex64, reflect.Complex128:
+		return s.evalComplex(typ, n)
+	case reflect.Float32, reflect.Float64:
+		return s.evalFloat(typ, n)
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return s.evalInteger(typ, n)
+	case reflect.Interface:
+		if typ.NumMethod() == 0 {
+			return s.evalEmptyInterface(dot, n)
+		}
+	case reflect.String:
+		return s.evalString(typ, n)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return s.evalUnsignedInteger(typ, n)
+	}
+	s.errorf("can't handle %s for arg of type %s", n, typ)
+	panic("not reached")
+}
+
+func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
+	if n, ok := n.(*parse.BoolNode); ok {
+		value := reflect.New(typ).Elem()
+		value.SetBool(n.True)
+		return value
+	}
+	s.errorf("expected bool; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
+	if n, ok := n.(*parse.StringNode); ok {
+		value := reflect.New(typ).Elem()
+		value.SetString(n.Text)
+		return value
+	}
+	s.errorf("expected string; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
+	if n, ok := n.(*parse.NumberNode); ok && n.IsInt {
+		value := reflect.New(typ).Elem()
+		value.SetInt(n.Int64)
+		return value
+	}
+	s.errorf("expected integer; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
+	if n, ok := n.(*parse.NumberNode); ok && n.IsUint {
+		value := reflect.New(typ).Elem()
+		value.SetUint(n.Uint64)
+		return value
+	}
+	s.errorf("expected unsigned integer; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
+	if n, ok := n.(*parse.NumberNode); ok && n.IsFloat {
+		value := reflect.New(typ).Elem()
+		value.SetFloat(n.Float64)
+		return value
+	}
+	s.errorf("expected float; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value {
+	if n, ok := n.(*parse.NumberNode); ok && n.IsComplex {
+		value := reflect.New(typ).Elem()
+		value.SetComplex(n.Complex128)
+		return value
+	}
+	s.errorf("expected complex; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value {
+	s.at(n)
+	switch n := n.(type) {
+	case *parse.BoolNode:
+		return reflect.ValueOf(n.True)
+	case *parse.DotNode:
+		return dot
+	case *parse.FieldNode:
+		return s.evalFieldNode(dot, n, nil, zero)
+	case *parse.IdentifierNode:
+		return s.evalFunction(dot, n, n, nil, zero)
+	case *parse.NilNode:
+		// NilNode is handled in evalArg, the only place that calls here.
+		s.errorf("evalEmptyInterface: nil (can't happen)")
+	case *parse.NumberNode:
+		return s.idealConstant(n)
+	case *parse.StringNode:
+		return reflect.ValueOf(n.Text)
+	case *parse.VariableNode:
+		return s.evalVariableNode(dot, n, nil, zero)
+	case *parse.PipeNode:
+		return s.evalPipeline(dot, n)
+	}
+	s.errorf("can't handle assignment of %s to empty interface argument", n)
+	panic("not reached")
+}
+
+// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
+// We indirect through pointers and empty interfaces (only) because
+// non-empty interfaces have methods we might need.
+func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
+	for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
+		if v.IsNil() {
+			return v, true
+		}
+		if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
+			break
+		}
+	}
+	return v, false
+}
+
+// printValue writes the textual representation of the value to the output of
+// the template.
+func (s *state) printValue(n parse.Node, v reflect.Value) {
+	s.at(n)
+	iface, ok := printableValue(v)
+	if !ok {
+		s.errorf("can't print %s of type %s", n, v.Type())
+	}
+	fmt.Fprint(s.wr, iface)
+}
+
+// printableValue returns the, possibly indirected, interface value inside v that
+// is best for a call to formatted printer.
+func printableValue(v reflect.Value) (interface{}, bool) {
+	if v.Kind() == reflect.Ptr {
+		v, _ = indirect(v) // fmt.Fprint handles nil.
+	}
+	if !v.IsValid() {
+		return "<no value>", true
+	}
+
+	if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) {
+		if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) {
+			v = v.Addr()
+		} else {
+			switch v.Kind() {
+			case reflect.Chan, reflect.Func:
+				return nil, false
+			}
+		}
+	}
+	return v.Interface(), true
+}
+
+// Types to help sort the keys in a map for reproducible output.
+
+type rvs []reflect.Value
+
+func (x rvs) Len() int      { return len(x) }
+func (x rvs) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+type rvInts struct{ rvs }
+
+func (x rvInts) Less(i, j int) bool { return x.rvs[i].Int() < x.rvs[j].Int() }
+
+type rvUints struct{ rvs }
+
+func (x rvUints) Less(i, j int) bool { return x.rvs[i].Uint() < x.rvs[j].Uint() }
+
+type rvFloats struct{ rvs }
+
+func (x rvFloats) Less(i, j int) bool { return x.rvs[i].Float() < x.rvs[j].Float() }
+
+type rvStrings struct{ rvs }
+
+func (x rvStrings) Less(i, j int) bool { return x.rvs[i].String() < x.rvs[j].String() }
+
+// sortKeys sorts (if it can) the slice of reflect.Values, which is a slice of map keys.
+func sortKeys(v []reflect.Value) []reflect.Value {
+	if len(v) <= 1 {
+		return v
+	}
+	switch v[0].Kind() {
+	case reflect.Float32, reflect.Float64:
+		sort.Sort(rvFloats{v})
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		sort.Sort(rvInts{v})
+	case reflect.String:
+		sort.Sort(rvStrings{v})
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		sort.Sort(rvUints{v})
+	}
+	return v
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/exec_test.go b/third_party/gofrontend/libgo/go/text/template/exec_test.go
new file mode 100644
index 0000000..868f2cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/exec_test.go
@@ -0,0 +1,989 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+var debug = flag.Bool("debug", false, "show the errors produced by the tests")
+
+// T has lots of interesting pieces to use to test execution.
+type T struct {
+	// Basics
+	True        bool
+	I           int
+	U16         uint16
+	X           string
+	FloatZero   float64
+	ComplexZero complex128
+	// Nested structs.
+	U *U
+	// Struct with String method.
+	V0     V
+	V1, V2 *V
+	// Struct with Error method.
+	W0     W
+	W1, W2 *W
+	// Slices
+	SI      []int
+	SIEmpty []int
+	SB      []bool
+	// Maps
+	MSI      map[string]int
+	MSIone   map[string]int // one element, for deterministic output
+	MSIEmpty map[string]int
+	MXI      map[interface{}]int
+	MII      map[int]int
+	SMSI     []map[string]int
+	// Empty interfaces; used to see if we can dig inside one.
+	Empty0 interface{} // nil
+	Empty1 interface{}
+	Empty2 interface{}
+	Empty3 interface{}
+	Empty4 interface{}
+	// Non-empty interface.
+	NonEmptyInterface I
+	// Stringer.
+	Str fmt.Stringer
+	Err error
+	// Pointers
+	PI  *int
+	PS  *string
+	PSI *[]int
+	NIL *int
+	// Function (not method)
+	BinaryFunc      func(string, string) string
+	VariadicFunc    func(...string) string
+	VariadicFuncInt func(int, ...string) string
+	NilOKFunc       func(*int) bool
+	ErrFunc         func() (string, error)
+	// Template to test evaluation of templates.
+	Tmpl *Template
+	// Unexported field; cannot be accessed by template.
+	unexported int
+}
+
+type U struct {
+	V string
+}
+
+type V struct {
+	j int
+}
+
+func (v *V) String() string {
+	if v == nil {
+		return "nilV"
+	}
+	return fmt.Sprintf("<%d>", v.j)
+}
+
+type W struct {
+	k int
+}
+
+func (w *W) Error() string {
+	if w == nil {
+		return "nilW"
+	}
+	return fmt.Sprintf("[%d]", w.k)
+}
+
+var tVal = &T{
+	True:   true,
+	I:      17,
+	U16:    16,
+	X:      "x",
+	U:      &U{"v"},
+	V0:     V{6666},
+	V1:     &V{7777}, // leave V2 as nil
+	W0:     W{888},
+	W1:     &W{999}, // leave W2 as nil
+	SI:     []int{3, 4, 5},
+	SB:     []bool{true, false},
+	MSI:    map[string]int{"one": 1, "two": 2, "three": 3},
+	MSIone: map[string]int{"one": 1},
+	MXI:    map[interface{}]int{"one": 1},
+	MII:    map[int]int{1: 1},
+	SMSI: []map[string]int{
+		{"one": 1, "two": 2},
+		{"eleven": 11, "twelve": 12},
+	},
+	Empty1:            3,
+	Empty2:            "empty2",
+	Empty3:            []int{7, 8},
+	Empty4:            &U{"UinEmpty"},
+	NonEmptyInterface: new(T),
+	Str:               bytes.NewBuffer([]byte("foozle")),
+	Err:               errors.New("erroozle"),
+	PI:                newInt(23),
+	PS:                newString("a string"),
+	PSI:               newIntSlice(21, 22, 23),
+	BinaryFunc:        func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) },
+	VariadicFunc:      func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
+	VariadicFuncInt:   func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
+	NilOKFunc:         func(s *int) bool { return s == nil },
+	ErrFunc:           func() (string, error) { return "bla", nil },
+	Tmpl:              Must(New("x").Parse("test template")), // "x" is the value of .X
+}
+
+// A non-empty interface.
+type I interface {
+	Method0() string
+}
+
+var iVal I = tVal
+
+// Helpers for creation.
+func newInt(n int) *int {
+	return &n
+}
+
+func newString(s string) *string {
+	return &s
+}
+
+func newIntSlice(n ...int) *[]int {
+	p := new([]int)
+	*p = make([]int, len(n))
+	copy(*p, n)
+	return p
+}
+
+// Simple methods with and without arguments.
+func (t *T) Method0() string {
+	return "M0"
+}
+
+func (t *T) Method1(a int) int {
+	return a
+}
+
+func (t *T) Method2(a uint16, b string) string {
+	return fmt.Sprintf("Method2: %d %s", a, b)
+}
+
+func (t *T) Method3(v interface{}) string {
+	return fmt.Sprintf("Method3: %v", v)
+}
+
+func (t *T) MAdd(a int, b []int) []int {
+	v := make([]int, len(b))
+	for i, x := range b {
+		v[i] = x + a
+	}
+	return v
+}
+
+var myError = errors.New("my error")
+
+// MyError returns a value and an error according to its argument.
+func (t *T) MyError(error bool) (bool, error) {
+	if error {
+		return true, myError
+	}
+	return false, nil
+}
+
+// A few methods to test chaining.
+func (t *T) GetU() *U {
+	return t.U
+}
+
+func (u *U) TrueFalse(b bool) string {
+	if b {
+		return "true"
+	}
+	return ""
+}
+
+func typeOf(arg interface{}) string {
+	return fmt.Sprintf("%T", arg)
+}
+
+type execTest struct {
+	name   string
+	input  string
+	output string
+	data   interface{}
+	ok     bool
+}
+
+// bigInt and bigUint are hex string representing numbers either side
+// of the max int boundary.
+// We do it this way so the test doesn't depend on ints being 32 bits.
+var (
+	bigInt  = fmt.Sprintf("0x%x", int(1<<uint(reflect.TypeOf(0).Bits()-1)-1))
+	bigUint = fmt.Sprintf("0x%x", uint(1<<uint(reflect.TypeOf(0).Bits()-1)))
+)
+
+var execTests = []execTest{
+	// Trivial cases.
+	{"empty", "", "", nil, true},
+	{"text", "some text", "some text", nil, true},
+	{"nil action", "{{nil}}", "", nil, false},
+
+	// Ideal constants.
+	{"ideal int", "{{typeOf 3}}", "int", 0, true},
+	{"ideal float", "{{typeOf 1.0}}", "float64", 0, true},
+	{"ideal exp float", "{{typeOf 1e1}}", "float64", 0, true},
+	{"ideal complex", "{{typeOf 1i}}", "complex128", 0, true},
+	{"ideal int", "{{typeOf " + bigInt + "}}", "int", 0, true},
+	{"ideal too big", "{{typeOf " + bigUint + "}}", "", 0, false},
+	{"ideal nil without type", "{{nil}}", "", 0, false},
+
+	// Fields of structs.
+	{".X", "-{{.X}}-", "-x-", tVal, true},
+	{".U.V", "-{{.U.V}}-", "-v-", tVal, true},
+	{".unexported", "{{.unexported}}", "", tVal, false},
+
+	// Fields on maps.
+	{"map .one", "{{.MSI.one}}", "1", tVal, true},
+	{"map .two", "{{.MSI.two}}", "2", tVal, true},
+	{"map .NO", "{{.MSI.NO}}", "<no value>", tVal, true},
+	{"map .one interface", "{{.MXI.one}}", "1", tVal, true},
+	{"map .WRONG args", "{{.MSI.one 1}}", "", tVal, false},
+	{"map .WRONG type", "{{.MII.one}}", "", tVal, false},
+
+	// Dots of all kinds to test basic evaluation.
+	{"dot int", "<{{.}}>", "<13>", 13, true},
+	{"dot uint", "<{{.}}>", "<14>", uint(14), true},
+	{"dot float", "<{{.}}>", "<15.1>", 15.1, true},
+	{"dot bool", "<{{.}}>", "<true>", true, true},
+	{"dot complex", "<{{.}}>", "<(16.2-17i)>", 16.2 - 17i, true},
+	{"dot string", "<{{.}}>", "<hello>", "hello", true},
+	{"dot slice", "<{{.}}>", "<[-1 -2 -3]>", []int{-1, -2, -3}, true},
+	{"dot map", "<{{.}}>", "<map[two:22]>", map[string]int{"two": 22}, true},
+	{"dot struct", "<{{.}}>", "<{7 seven}>", struct {
+		a int
+		b string
+	}{7, "seven"}, true},
+
+	// Variables.
+	{"$ int", "{{$}}", "123", 123, true},
+	{"$.I", "{{$.I}}", "17", tVal, true},
+	{"$.U.V", "{{$.U.V}}", "v", tVal, true},
+	{"declare in action", "{{$x := $.U.V}}{{$x}}", "v", tVal, true},
+
+	// Type with String method.
+	{"V{6666}.String()", "-{{.V0}}-", "-<6666>-", tVal, true},
+	{"&V{7777}.String()", "-{{.V1}}-", "-<7777>-", tVal, true},
+	{"(*V)(nil).String()", "-{{.V2}}-", "-nilV-", tVal, true},
+
+	// Type with Error method.
+	{"W{888}.Error()", "-{{.W0}}-", "-[888]-", tVal, true},
+	{"&W{999}.Error()", "-{{.W1}}-", "-[999]-", tVal, true},
+	{"(*W)(nil).Error()", "-{{.W2}}-", "-nilW-", tVal, true},
+
+	// Pointers.
+	{"*int", "{{.PI}}", "23", tVal, true},
+	{"*string", "{{.PS}}", "a string", tVal, true},
+	{"*[]int", "{{.PSI}}", "[21 22 23]", tVal, true},
+	{"*[]int[1]", "{{index .PSI 1}}", "22", tVal, true},
+	{"NIL", "{{.NIL}}", "<nil>", tVal, true},
+
+	// Empty interfaces holding values.
+	{"empty nil", "{{.Empty0}}", "<no value>", tVal, true},
+	{"empty with int", "{{.Empty1}}", "3", tVal, true},
+	{"empty with string", "{{.Empty2}}", "empty2", tVal, true},
+	{"empty with slice", "{{.Empty3}}", "[7 8]", tVal, true},
+	{"empty with struct", "{{.Empty4}}", "{UinEmpty}", tVal, true},
+	{"empty with struct, field", "{{.Empty4.V}}", "UinEmpty", tVal, true},
+
+	// Method calls.
+	{".Method0", "-{{.Method0}}-", "-M0-", tVal, true},
+	{".Method1(1234)", "-{{.Method1 1234}}-", "-1234-", tVal, true},
+	{".Method1(.I)", "-{{.Method1 .I}}-", "-17-", tVal, true},
+	{".Method2(3, .X)", "-{{.Method2 3 .X}}-", "-Method2: 3 x-", tVal, true},
+	{".Method2(.U16, `str`)", "-{{.Method2 .U16 `str`}}-", "-Method2: 16 str-", tVal, true},
+	{".Method2(.U16, $x)", "{{if $x := .X}}-{{.Method2 .U16 $x}}{{end}}-", "-Method2: 16 x-", tVal, true},
+	{".Method3(nil constant)", "-{{.Method3 nil}}-", "-Method3: <nil>-", tVal, true},
+	{".Method3(nil value)", "-{{.Method3 .MXI.unset}}-", "-Method3: <nil>-", tVal, true},
+	{"method on var", "{{if $x := .}}-{{$x.Method2 .U16 $x.X}}{{end}}-", "-Method2: 16 x-", tVal, true},
+	{"method on chained var",
+		"{{range .MSIone}}{{if $.U.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}",
+		"true", tVal, true},
+	{"chained method",
+		"{{range .MSIone}}{{if $.GetU.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}",
+		"true", tVal, true},
+	{"chained method on variable",
+		"{{with $x := .}}{{with .SI}}{{$.GetU.TrueFalse $.True}}{{end}}{{end}}",
+		"true", tVal, true},
+	{".NilOKFunc not nil", "{{call .NilOKFunc .PI}}", "false", tVal, true},
+	{".NilOKFunc nil", "{{call .NilOKFunc nil}}", "true", tVal, true},
+
+	// Function call builtin.
+	{".BinaryFunc", "{{call .BinaryFunc `1` `2`}}", "[1=2]", tVal, true},
+	{".VariadicFunc0", "{{call .VariadicFunc}}", "<>", tVal, true},
+	{".VariadicFunc2", "{{call .VariadicFunc `he` `llo`}}", "<he+llo>", tVal, true},
+	{".VariadicFuncInt", "{{call .VariadicFuncInt 33 `he` `llo`}}", "33=<he+llo>", tVal, true},
+	{"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", tVal, true},
+	{"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true},
+	{"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true},
+	{".ErrFunc", "{{call .ErrFunc}}", "bla", tVal, true},
+
+	// Erroneous function calls (check args).
+	{".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false},
+	{".BinaryFuncTooMany", "{{call .BinaryFunc `1` `2` `3`}}", "", tVal, false},
+	{".BinaryFuncBad0", "{{call .BinaryFunc 1 3}}", "", tVal, false},
+	{".BinaryFuncBad1", "{{call .BinaryFunc `1` 3}}", "", tVal, false},
+	{".VariadicFuncBad0", "{{call .VariadicFunc 3}}", "", tVal, false},
+	{".VariadicFuncIntBad0", "{{call .VariadicFuncInt}}", "", tVal, false},
+	{".VariadicFuncIntBad`", "{{call .VariadicFuncInt `x`}}", "", tVal, false},
+	{".VariadicFuncNilBad", "{{call .VariadicFunc nil}}", "", tVal, false},
+
+	// Pipelines.
+	{"pipeline", "-{{.Method0 | .Method2 .U16}}-", "-Method2: 16 M0-", tVal, true},
+	{"pipeline func", "-{{call .VariadicFunc `llo` | call .VariadicFunc `he` }}-", "-<he+<llo>>-", tVal, true},
+
+	// Parenthesized expressions
+	{"parens in pipeline", "{{printf `%d %d %d` (1) (2 | add 3) (add 4 (add 5 6))}}", "1 5 15", tVal, true},
+
+	// Parenthesized expressions with field accesses
+	{"parens: $ in paren", "{{($).X}}", "x", tVal, true},
+	{"parens: $.GetU in paren", "{{($.GetU).V}}", "v", tVal, true},
+	{"parens: $ in paren in pipe", "{{($ | echo).X}}", "x", tVal, true},
+	{"parens: spaces and args", `{{(makemap "up" "down" "left" "right").left}}`, "right", tVal, true},
+
+	// If.
+	{"if true", "{{if true}}TRUE{{end}}", "TRUE", tVal, true},
+	{"if false", "{{if false}}TRUE{{else}}FALSE{{end}}", "FALSE", tVal, true},
+	{"if nil", "{{if nil}}TRUE{{end}}", "", tVal, false},
+	{"if 1", "{{if 1}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
+	{"if 0", "{{if 0}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"if 1.5", "{{if 1.5}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
+	{"if 0.0", "{{if .FloatZero}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"if 1.5i", "{{if 1.5i}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
+	{"if 0.0i", "{{if .ComplexZero}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"if emptystring", "{{if ``}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"if string", "{{if `notempty`}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
+	{"if emptyslice", "{{if .SIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"if slice", "{{if .SI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
+	{"if emptymap", "{{if .MSIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"if map", "{{if .MSI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
+	{"if map unset", "{{if .MXI.none}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"if map not unset", "{{if not .MXI.none}}ZERO{{else}}NON-ZERO{{end}}", "ZERO", tVal, true},
+	{"if $x with $y int", "{{if $x := true}}{{with $y := .I}}{{$x}},{{$y}}{{end}}{{end}}", "true,17", tVal, true},
+	{"if $x with $x int", "{{if $x := true}}{{with $x := .I}}{{$x}},{{end}}{{$x}}{{end}}", "17,true", tVal, true},
+	{"if else if", "{{if false}}FALSE{{else if true}}TRUE{{end}}", "TRUE", tVal, true},
+	{"if else chain", "{{if eq 1 3}}1{{else if eq 2 3}}2{{else if eq 3 3}}3{{end}}", "3", tVal, true},
+
+	// Print etc.
+	{"print", `{{print "hello, print"}}`, "hello, print", tVal, true},
+	{"print 123", `{{print 1 2 3}}`, "1 2 3", tVal, true},
+	{"print nil", `{{print nil}}`, "<nil>", tVal, true},
+	{"println", `{{println 1 2 3}}`, "1 2 3\n", tVal, true},
+	{"printf int", `{{printf "%04x" 127}}`, "007f", tVal, true},
+	{"printf float", `{{printf "%g" 3.5}}`, "3.5", tVal, true},
+	{"printf complex", `{{printf "%g" 1+7i}}`, "(1+7i)", tVal, true},
+	{"printf string", `{{printf "%s" "hello"}}`, "hello", tVal, true},
+	{"printf function", `{{printf "%#q" zeroArgs}}`, "`zeroArgs`", tVal, true},
+	{"printf field", `{{printf "%s" .U.V}}`, "v", tVal, true},
+	{"printf method", `{{printf "%s" .Method0}}`, "M0", tVal, true},
+	{"printf dot", `{{with .I}}{{printf "%d" .}}{{end}}`, "17", tVal, true},
+	{"printf var", `{{with $x := .I}}{{printf "%d" $x}}{{end}}`, "17", tVal, true},
+	{"printf lots", `{{printf "%d %s %g %s" 127 "hello" 7-3i .Method0}}`, "127 hello (7-3i) M0", tVal, true},
+
+	// HTML.
+	{"html", `{{html "<script>alert(\"XSS\");</script>"}}`,
+		"&lt;script&gt;alert(&#34;XSS&#34;);&lt;/script&gt;", nil, true},
+	{"html pipeline", `{{printf "<script>alert(\"XSS\");</script>" | html}}`,
+		"&lt;script&gt;alert(&#34;XSS&#34;);&lt;/script&gt;", nil, true},
+	{"html", `{{html .PS}}`, "a string", tVal, true},
+
+	// JavaScript.
+	{"js", `{{js .}}`, `It\'d be nice.`, `It'd be nice.`, true},
+
+	// URL query.
+	{"urlquery", `{{"http://www.example.org/"|urlquery}}`, "http%3A%2F%2Fwww.example.org%2F", nil, true},
+
+	// Booleans
+	{"not", "{{not true}} {{not false}}", "false true", nil, true},
+	{"and", "{{and false 0}} {{and 1 0}} {{and 0 true}} {{and 1 1}}", "false 0 0 1", nil, true},
+	{"or", "{{or 0 0}} {{or 1 0}} {{or 0 true}} {{or 1 1}}", "0 1 true 1", nil, true},
+	{"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true},
+	{"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true},
+
+	// Indexing.
+	{"slice[0]", "{{index .SI 0}}", "3", tVal, true},
+	{"slice[1]", "{{index .SI 1}}", "4", tVal, true},
+	{"slice[HUGE]", "{{index .SI 10}}", "", tVal, false},
+	{"slice[WRONG]", "{{index .SI `hello`}}", "", tVal, false},
+	{"map[one]", "{{index .MSI `one`}}", "1", tVal, true},
+	{"map[two]", "{{index .MSI `two`}}", "2", tVal, true},
+	{"map[NO]", "{{index .MSI `XXX`}}", "0", tVal, true},
+	{"map[nil]", "{{index .MSI nil}}", "0", tVal, true},
+	{"map[WRONG]", "{{index .MSI 10}}", "", tVal, false},
+	{"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true},
+
+	// Len.
+	{"slice", "{{len .SI}}", "3", tVal, true},
+	{"map", "{{len .MSI }}", "3", tVal, true},
+	{"len of int", "{{len 3}}", "", tVal, false},
+	{"len of nothing", "{{len .Empty0}}", "", tVal, false},
+
+	// With.
+	{"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true},
+	{"with false", "{{with false}}{{.}}{{else}}FALSE{{end}}", "FALSE", tVal, true},
+	{"with 1", "{{with 1}}{{.}}{{else}}ZERO{{end}}", "1", tVal, true},
+	{"with 0", "{{with 0}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"with 1.5", "{{with 1.5}}{{.}}{{else}}ZERO{{end}}", "1.5", tVal, true},
+	{"with 0.0", "{{with .FloatZero}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"with 1.5i", "{{with 1.5i}}{{.}}{{else}}ZERO{{end}}", "(0+1.5i)", tVal, true},
+	{"with 0.0i", "{{with .ComplexZero}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"with emptystring", "{{with ``}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"with string", "{{with `notempty`}}{{.}}{{else}}EMPTY{{end}}", "notempty", tVal, true},
+	{"with emptyslice", "{{with .SIEmpty}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"with slice", "{{with .SI}}{{.}}{{else}}EMPTY{{end}}", "[3 4 5]", tVal, true},
+	{"with emptymap", "{{with .MSIEmpty}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"with map", "{{with .MSIone}}{{.}}{{else}}EMPTY{{end}}", "map[one:1]", tVal, true},
+	{"with empty interface, struct field", "{{with .Empty4}}{{.V}}{{end}}", "UinEmpty", tVal, true},
+	{"with $x int", "{{with $x := .I}}{{$x}}{{end}}", "17", tVal, true},
+	{"with $x struct.U.V", "{{with $x := $}}{{$x.U.V}}{{end}}", "v", tVal, true},
+	{"with variable and action", "{{with $x := $}}{{$y := $.U.V}}{{$y}}{{end}}", "v", tVal, true},
+
+	// Range.
+	{"range []int", "{{range .SI}}-{{.}}-{{end}}", "-3--4--5-", tVal, true},
+	{"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true},
+	{"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true},
+	{"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true},
+	{"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true},
+	{"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true},
+	{"range empty map no else", "{{range .MSIEmpty}}-{{.}}-{{end}}", "", tVal, true},
+	{"range map else", "{{range .MSI}}-{{.}}-{{else}}EMPTY{{end}}", "-1--3--2-", tVal, true},
+	{"range empty map else", "{{range .MSIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"range empty interface", "{{range .Empty3}}-{{.}}-{{else}}EMPTY{{end}}", "-7--8-", tVal, true},
+	{"range empty nil", "{{range .Empty0}}-{{.}}-{{end}}", "", tVal, true},
+	{"range $x SI", "{{range $x := .SI}}<{{$x}}>{{end}}", "<3><4><5>", tVal, true},
+	{"range $x $y SI", "{{range $x, $y := .SI}}<{{$x}}={{$y}}>{{end}}", "<0=3><1=4><2=5>", tVal, true},
+	{"range $x MSIone", "{{range $x := .MSIone}}<{{$x}}>{{end}}", "<1>", tVal, true},
+	{"range $x $y MSIone", "{{range $x, $y := .MSIone}}<{{$x}}={{$y}}>{{end}}", "<one=1>", tVal, true},
+	{"range $x PSI", "{{range $x := .PSI}}<{{$x}}>{{end}}", "<21><22><23>", tVal, true},
+	{"declare in range", "{{range $x := .PSI}}<{{$foo:=$x}}{{$x}}>{{end}}", "<21><22><23>", tVal, true},
+	{"range count", `{{range $i, $x := count 5}}[{{$i}}]{{$x}}{{end}}`, "[0]a[1]b[2]c[3]d[4]e", tVal, true},
+	{"range nil count", `{{range $i, $x := count 0}}{{else}}empty{{end}}`, "empty", tVal, true},
+
+	// Cute examples.
+	{"or as if true", `{{or .SI "slice is empty"}}`, "[3 4 5]", tVal, true},
+	{"or as if false", `{{or .SIEmpty "slice is empty"}}`, "slice is empty", tVal, true},
+
+	// Error handling.
+	{"error method, error", "{{.MyError true}}", "", tVal, false},
+	{"error method, no error", "{{.MyError false}}", "false", tVal, true},
+
+	// Fixed bugs.
+	// Must separate dot and receiver; otherwise args are evaluated with dot set to variable.
+	{"bug0", "{{range .MSIone}}{{if $.Method1 .}}X{{end}}{{end}}", "X", tVal, true},
+	// Do not loop endlessly in indirect for non-empty interfaces.
+	// The bug appears with *interface only; looped forever.
+	{"bug1", "{{.Method0}}", "M0", &iVal, true},
+	// Was taking address of interface field, so method set was empty.
+	{"bug2", "{{$.NonEmptyInterface.Method0}}", "M0", tVal, true},
+	// Struct values were not legal in with - mere oversight.
+	{"bug3", "{{with $}}{{.Method0}}{{end}}", "M0", tVal, true},
+	// Nil interface values in if.
+	{"bug4", "{{if .Empty0}}non-nil{{else}}nil{{end}}", "nil", tVal, true},
+	// Stringer.
+	{"bug5", "{{.Str}}", "foozle", tVal, true},
+	{"bug5a", "{{.Err}}", "erroozle", tVal, true},
+	// Args need to be indirected and dereferenced sometimes.
+	{"bug6a", "{{vfunc .V0 .V1}}", "vfunc", tVal, true},
+	{"bug6b", "{{vfunc .V0 .V0}}", "vfunc", tVal, true},
+	{"bug6c", "{{vfunc .V1 .V0}}", "vfunc", tVal, true},
+	{"bug6d", "{{vfunc .V1 .V1}}", "vfunc", tVal, true},
+	// Legal parse but illegal execution: non-function should have no arguments.
+	{"bug7a", "{{3 2}}", "", tVal, false},
+	{"bug7b", "{{$x := 1}}{{$x 2}}", "", tVal, false},
+	{"bug7c", "{{$x := 1}}{{3 | $x}}", "", tVal, false},
+	// Pipelined arg was not being type-checked.
+	{"bug8a", "{{3|oneArg}}", "", tVal, false},
+	{"bug8b", "{{4|dddArg 3}}", "", tVal, false},
+	// A bug was introduced that broke map lookups for lower-case names.
+	{"bug9", "{{.cause}}", "neglect", map[string]string{"cause": "neglect"}, true},
+	// Field chain starting with function did not work.
+	{"bug10", "{{mapOfThree.three}}-{{(mapOfThree).three}}", "3-3", 0, true},
+	// Dereferencing nil pointer while evaluating function arguments should not panic. Issue 7333.
+	{"bug11", "{{valueString .PS}}", "", T{}, false},
+}
+
+func zeroArgs() string {
+	return "zeroArgs"
+}
+
+func oneArg(a string) string {
+	return "oneArg=" + a
+}
+
+func dddArg(a int, b ...string) string {
+	return fmt.Sprintln(a, b)
+}
+
+// count returns a channel that will deliver n sequential 1-letter strings starting at "a"
+func count(n int) chan string {
+	if n == 0 {
+		return nil
+	}
+	c := make(chan string)
+	go func() {
+		for i := 0; i < n; i++ {
+			c <- "abcdefghijklmnop"[i : i+1]
+		}
+		close(c)
+	}()
+	return c
+}
+
+// vfunc takes a *V and a V
+func vfunc(V, *V) string {
+	return "vfunc"
+}
+
+// valueString takes a string, not a pointer.
+func valueString(v string) string {
+	return "value is ignored"
+}
+
+func add(args ...int) int {
+	sum := 0
+	for _, x := range args {
+		sum += x
+	}
+	return sum
+}
+
+func echo(arg interface{}) interface{} {
+	return arg
+}
+
+func makemap(arg ...string) map[string]string {
+	if len(arg)%2 != 0 {
+		panic("bad makemap")
+	}
+	m := make(map[string]string)
+	for i := 0; i < len(arg); i += 2 {
+		m[arg[i]] = arg[i+1]
+	}
+	return m
+}
+
+func stringer(s fmt.Stringer) string {
+	return s.String()
+}
+
+func mapOfThree() interface{} {
+	return map[string]int{"three": 3}
+}
+
+func testExecute(execTests []execTest, template *Template, t *testing.T) {
+	b := new(bytes.Buffer)
+	funcs := FuncMap{
+		"add":         add,
+		"count":       count,
+		"dddArg":      dddArg,
+		"echo":        echo,
+		"makemap":     makemap,
+		"mapOfThree":  mapOfThree,
+		"oneArg":      oneArg,
+		"stringer":    stringer,
+		"typeOf":      typeOf,
+		"valueString": valueString,
+		"vfunc":       vfunc,
+		"zeroArgs":    zeroArgs,
+	}
+	for _, test := range execTests {
+		var tmpl *Template
+		var err error
+		if template == nil {
+			tmpl, err = New(test.name).Funcs(funcs).Parse(test.input)
+		} else {
+			tmpl, err = template.New(test.name).Funcs(funcs).Parse(test.input)
+		}
+		if err != nil {
+			t.Errorf("%s: parse error: %s", test.name, err)
+			continue
+		}
+		b.Reset()
+		err = tmpl.Execute(b, test.data)
+		switch {
+		case !test.ok && err == nil:
+			t.Errorf("%s: expected error; got none", test.name)
+			continue
+		case test.ok && err != nil:
+			t.Errorf("%s: unexpected execute error: %s", test.name, err)
+			continue
+		case !test.ok && err != nil:
+			// expected error, got one
+			if *debug {
+				fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
+			}
+		}
+		result := b.String()
+		if result != test.output {
+			t.Errorf("%s: expected\n\t%q\ngot\n\t%q", test.name, test.output, result)
+		}
+	}
+}
+
+func TestExecute(t *testing.T) {
+	testExecute(execTests, nil, t)
+}
+
+var delimPairs = []string{
+	"", "", // default
+	"{{", "}}", // same as default
+	"<<", ">>", // distinct
+	"|", "|", // same
+	"(日)", "(本)", // peculiar
+}
+
+func TestDelims(t *testing.T) {
+	const hello = "Hello, world"
+	var value = struct{ Str string }{hello}
+	for i := 0; i < len(delimPairs); i += 2 {
+		text := ".Str"
+		left := delimPairs[i+0]
+		trueLeft := left
+		right := delimPairs[i+1]
+		trueRight := right
+		if left == "" { // default case
+			trueLeft = "{{"
+		}
+		if right == "" { // default case
+			trueRight = "}}"
+		}
+		text = trueLeft + text + trueRight
+		// Now add a comment
+		text += trueLeft + "/*comment*/" + trueRight
+		// Now add  an action containing a string.
+		text += trueLeft + `"` + trueLeft + `"` + trueRight
+		// At this point text looks like `{{.Str}}{{/*comment*/}}{{"{{"}}`.
+		tmpl, err := New("delims").Delims(left, right).Parse(text)
+		if err != nil {
+			t.Fatalf("delim %q text %q parse err %s", left, text, err)
+		}
+		var b = new(bytes.Buffer)
+		err = tmpl.Execute(b, value)
+		if err != nil {
+			t.Fatalf("delim %q exec err %s", left, err)
+		}
+		if b.String() != hello+trueLeft {
+			t.Errorf("expected %q got %q", hello+trueLeft, b.String())
+		}
+	}
+}
+
+// Check that an error from a method flows back to the top.
+func TestExecuteError(t *testing.T) {
+	b := new(bytes.Buffer)
+	tmpl := New("error")
+	_, err := tmpl.Parse("{{.MyError true}}")
+	if err != nil {
+		t.Fatalf("parse error: %s", err)
+	}
+	err = tmpl.Execute(b, tVal)
+	if err == nil {
+		t.Errorf("expected error; got none")
+	} else if !strings.Contains(err.Error(), myError.Error()) {
+		if *debug {
+			fmt.Printf("test execute error: %s\n", err)
+		}
+		t.Errorf("expected myError; got %s", err)
+	}
+}
+
+const execErrorText = `line 1
+line 2
+line 3
+{{template "one" .}}
+{{define "one"}}{{template "two" .}}{{end}}
+{{define "two"}}{{template "three" .}}{{end}}
+{{define "three"}}{{index "hi" $}}{{end}}`
+
+// Check that an error from a nested template contains all the relevant information.
+func TestExecError(t *testing.T) {
+	tmpl, err := New("top").Parse(execErrorText)
+	if err != nil {
+		t.Fatal("parse error:", err)
+	}
+	var b bytes.Buffer
+	err = tmpl.Execute(&b, 5) // 5 is out of range indexing "hi"
+	if err == nil {
+		t.Fatal("expected error")
+	}
+	const want = `template: top:7:20: executing "three" at <index "hi" $>: error calling index: index out of range: 5`
+	got := err.Error()
+	if got != want {
+		t.Errorf("expected\n%q\ngot\n%q", want, got)
+	}
+}
+
+func TestJSEscaping(t *testing.T) {
+	testCases := []struct {
+		in, exp string
+	}{
+		{`a`, `a`},
+		{`'foo`, `\'foo`},
+		{`Go "jump" \`, `Go \"jump\" \\`},
+		{`Yukihiro says "今日は世界"`, `Yukihiro says \"今日は世界\"`},
+		{"unprintable \uFDFF", `unprintable \uFDFF`},
+		{`<html>`, `\x3Chtml\x3E`},
+	}
+	for _, tc := range testCases {
+		s := JSEscapeString(tc.in)
+		if s != tc.exp {
+			t.Errorf("JS escaping [%s] got [%s] want [%s]", tc.in, s, tc.exp)
+		}
+	}
+}
+
+// A nice example: walk a binary tree.
+
+type Tree struct {
+	Val         int
+	Left, Right *Tree
+}
+
+// Use different delimiters to test Set.Delims.
+const treeTemplate = `
+	(define "tree")
+	[
+		(.Val)
+		(with .Left)
+			(template "tree" .)
+		(end)
+		(with .Right)
+			(template "tree" .)
+		(end)
+	]
+	(end)
+`
+
+func TestTree(t *testing.T) {
+	var tree = &Tree{
+		1,
+		&Tree{
+			2, &Tree{
+				3,
+				&Tree{
+					4, nil, nil,
+				},
+				nil,
+			},
+			&Tree{
+				5,
+				&Tree{
+					6, nil, nil,
+				},
+				nil,
+			},
+		},
+		&Tree{
+			7,
+			&Tree{
+				8,
+				&Tree{
+					9, nil, nil,
+				},
+				nil,
+			},
+			&Tree{
+				10,
+				&Tree{
+					11, nil, nil,
+				},
+				nil,
+			},
+		},
+	}
+	tmpl, err := New("root").Delims("(", ")").Parse(treeTemplate)
+	if err != nil {
+		t.Fatal("parse error:", err)
+	}
+	var b bytes.Buffer
+	stripSpace := func(r rune) rune {
+		if r == '\t' || r == '\n' {
+			return -1
+		}
+		return r
+	}
+	const expect = "[1[2[3[4]][5[6]]][7[8[9]][10[11]]]]"
+	// First by looking up the template.
+	err = tmpl.Lookup("tree").Execute(&b, tree)
+	if err != nil {
+		t.Fatal("exec error:", err)
+	}
+	result := strings.Map(stripSpace, b.String())
+	if result != expect {
+		t.Errorf("expected %q got %q", expect, result)
+	}
+	// Then direct to execution.
+	b.Reset()
+	err = tmpl.ExecuteTemplate(&b, "tree", tree)
+	if err != nil {
+		t.Fatal("exec error:", err)
+	}
+	result = strings.Map(stripSpace, b.String())
+	if result != expect {
+		t.Errorf("expected %q got %q", expect, result)
+	}
+}
+
+func TestExecuteOnNewTemplate(t *testing.T) {
+	// This is issue 3872.
+	_ = New("Name").Templates()
+}
+
+const testTemplates = `{{define "one"}}one{{end}}{{define "two"}}two{{end}}`
+
+func TestMessageForExecuteEmpty(t *testing.T) {
+	// Test a truly empty template.
+	tmpl := New("empty")
+	var b bytes.Buffer
+	err := tmpl.Execute(&b, 0)
+	if err == nil {
+		t.Fatal("expected initial error")
+	}
+	got := err.Error()
+	want := `template: empty: "empty" is an incomplete or empty template`
+	if got != want {
+		t.Errorf("expected error %s got %s", want, got)
+	}
+	// Add a non-empty template to check that the error is helpful.
+	tests, err := New("").Parse(testTemplates)
+	if err != nil {
+		t.Fatal(err)
+	}
+	tmpl.AddParseTree("secondary", tests.Tree)
+	err = tmpl.Execute(&b, 0)
+	if err == nil {
+		t.Fatal("expected second error")
+	}
+	got = err.Error()
+	want = `template: empty: "empty" is an incomplete or empty template; defined templates are: "secondary"`
+	if got != want {
+		t.Errorf("expected error %s got %s", want, got)
+	}
+	// Make sure we can execute the secondary.
+	err = tmpl.ExecuteTemplate(&b, "secondary", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+type cmpTest struct {
+	expr  string
+	truth string
+	ok    bool
+}
+
+var cmpTests = []cmpTest{
+	{"eq true true", "true", true},
+	{"eq true false", "false", true},
+	{"eq 1+2i 1+2i", "true", true},
+	{"eq 1+2i 1+3i", "false", true},
+	{"eq 1.5 1.5", "true", true},
+	{"eq 1.5 2.5", "false", true},
+	{"eq 1 1", "true", true},
+	{"eq 1 2", "false", true},
+	{"eq `xy` `xy`", "true", true},
+	{"eq `xy` `xyz`", "false", true},
+	{"eq .Xuint .Xuint", "true", true},
+	{"eq .Xuint .Yuint", "false", true},
+	{"eq 3 4 5 6 3", "true", true},
+	{"eq 3 4 5 6 7", "false", true},
+	{"ne true true", "false", true},
+	{"ne true false", "true", true},
+	{"ne 1+2i 1+2i", "false", true},
+	{"ne 1+2i 1+3i", "true", true},
+	{"ne 1.5 1.5", "false", true},
+	{"ne 1.5 2.5", "true", true},
+	{"ne 1 1", "false", true},
+	{"ne 1 2", "true", true},
+	{"ne `xy` `xy`", "false", true},
+	{"ne `xy` `xyz`", "true", true},
+	{"ne .Xuint .Xuint", "false", true},
+	{"ne .Xuint .Yuint", "true", true},
+	{"lt 1.5 1.5", "false", true},
+	{"lt 1.5 2.5", "true", true},
+	{"lt 1 1", "false", true},
+	{"lt 1 2", "true", true},
+	{"lt `xy` `xy`", "false", true},
+	{"lt `xy` `xyz`", "true", true},
+	{"lt .Xuint .Xuint", "false", true},
+	{"lt .Xuint .Yuint", "true", true},
+	{"le 1.5 1.5", "true", true},
+	{"le 1.5 2.5", "true", true},
+	{"le 2.5 1.5", "false", true},
+	{"le 1 1", "true", true},
+	{"le 1 2", "true", true},
+	{"le 2 1", "false", true},
+	{"le `xy` `xy`", "true", true},
+	{"le `xy` `xyz`", "true", true},
+	{"le `xyz` `xy`", "false", true},
+	{"le .Xuint .Xuint", "true", true},
+	{"le .Xuint .Yuint", "true", true},
+	{"le .Yuint .Xuint", "false", true},
+	{"gt 1.5 1.5", "false", true},
+	{"gt 1.5 2.5", "false", true},
+	{"gt 1 1", "false", true},
+	{"gt 2 1", "true", true},
+	{"gt 1 2", "false", true},
+	{"gt `xy` `xy`", "false", true},
+	{"gt `xy` `xyz`", "false", true},
+	{"gt .Xuint .Xuint", "false", true},
+	{"gt .Xuint .Yuint", "false", true},
+	{"gt .Yuint .Xuint", "true", true},
+	{"ge 1.5 1.5", "true", true},
+	{"ge 1.5 2.5", "false", true},
+	{"ge 2.5 1.5", "true", true},
+	{"ge 1 1", "true", true},
+	{"ge 1 2", "false", true},
+	{"ge 2 1", "true", true},
+	{"ge `xy` `xy`", "true", true},
+	{"ge `xy` `xyz`", "false", true},
+	{"ge `xyz` `xy`", "true", true},
+	{"ge .Xuint .Xuint", "true", true},
+	{"ge .Xuint .Yuint", "false", true},
+	{"ge .Yuint .Xuint", "true", true},
+	// Errors
+	{"eq `xy` 1", "", false},    // Different types.
+	{"lt true true", "", false}, // Unordered types.
+	{"lt 1+0i 1+0i", "", false}, // Unordered types.
+}
+
+func TestComparison(t *testing.T) {
+	b := new(bytes.Buffer)
+	var cmpStruct = struct {
+		Xuint, Yuint uint
+	}{3, 4}
+	for _, test := range cmpTests {
+		text := fmt.Sprintf("{{if %s}}true{{else}}false{{end}}", test.expr)
+		tmpl, err := New("empty").Parse(text)
+		if err != nil {
+			t.Fatal(err)
+		}
+		b.Reset()
+		err = tmpl.Execute(b, &cmpStruct)
+		if test.ok && err != nil {
+			t.Errorf("%s errored incorrectly: %s", test.expr, err)
+			continue
+		}
+		if !test.ok && err == nil {
+			t.Errorf("%s did not error", test.expr)
+			continue
+		}
+		if b.String() != test.truth {
+			t.Errorf("%s: want %s; got %s", test.expr, test.truth, b.String())
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/funcs.go b/third_party/gofrontend/libgo/go/text/template/funcs.go
new file mode 100644
index 0000000..e854122
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/funcs.go
@@ -0,0 +1,580 @@
+// 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.
+
+package template
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"net/url"
+	"reflect"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// FuncMap is the type of the map defining the mapping from names to functions.
+// Each function must have either a single return value, or two return values of
+// which the second has type error. In that case, if the second (error)
+// return value evaluates to non-nil during execution, execution terminates and
+// Execute returns that error.
+type FuncMap map[string]interface{}
+
+var builtins = FuncMap{
+	"and":      and,
+	"call":     call,
+	"html":     HTMLEscaper,
+	"index":    index,
+	"js":       JSEscaper,
+	"len":      length,
+	"not":      not,
+	"or":       or,
+	"print":    fmt.Sprint,
+	"printf":   fmt.Sprintf,
+	"println":  fmt.Sprintln,
+	"urlquery": URLQueryEscaper,
+
+	// Comparisons
+	"eq": eq, // ==
+	"ge": ge, // >=
+	"gt": gt, // >
+	"le": le, // <=
+	"lt": lt, // <
+	"ne": ne, // !=
+}
+
+var builtinFuncs = createValueFuncs(builtins)
+
+// createValueFuncs turns a FuncMap into a map[string]reflect.Value
+func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
+	m := make(map[string]reflect.Value)
+	addValueFuncs(m, funcMap)
+	return m
+}
+
+// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
+func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
+	for name, fn := range in {
+		v := reflect.ValueOf(fn)
+		if v.Kind() != reflect.Func {
+			panic("value for " + name + " not a function")
+		}
+		if !goodFunc(v.Type()) {
+			panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut()))
+		}
+		out[name] = v
+	}
+}
+
+// addFuncs adds to values the functions in funcs. It does no checking of the input -
+// call addValueFuncs first.
+func addFuncs(out, in FuncMap) {
+	for name, fn := range in {
+		out[name] = fn
+	}
+}
+
+// goodFunc checks that the function or method has the right result signature.
+func goodFunc(typ reflect.Type) bool {
+	// We allow functions with 1 result or 2 results where the second is an error.
+	switch {
+	case typ.NumOut() == 1:
+		return true
+	case typ.NumOut() == 2 && typ.Out(1) == errorType:
+		return true
+	}
+	return false
+}
+
+// findFunction looks for a function in the template, and global map.
+func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
+	if tmpl != nil && tmpl.common != nil {
+		if fn := tmpl.execFuncs[name]; fn.IsValid() {
+			return fn, true
+		}
+	}
+	if fn := builtinFuncs[name]; fn.IsValid() {
+		return fn, true
+	}
+	return reflect.Value{}, false
+}
+
+// Indexing.
+
+// index returns the result of indexing its first argument by the following
+// arguments.  Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
+// indexed item must be a map, slice, or array.
+func index(item interface{}, indices ...interface{}) (interface{}, error) {
+	v := reflect.ValueOf(item)
+	for _, i := range indices {
+		index := reflect.ValueOf(i)
+		var isNil bool
+		if v, isNil = indirect(v); isNil {
+			return nil, fmt.Errorf("index of nil pointer")
+		}
+		switch v.Kind() {
+		case reflect.Array, reflect.Slice, reflect.String:
+			var x int64
+			switch index.Kind() {
+			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+				x = index.Int()
+			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+				x = int64(index.Uint())
+			default:
+				return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
+			}
+			if x < 0 || x >= int64(v.Len()) {
+				return nil, fmt.Errorf("index out of range: %d", x)
+			}
+			v = v.Index(int(x))
+		case reflect.Map:
+			if !index.IsValid() {
+				index = reflect.Zero(v.Type().Key())
+			}
+			if !index.Type().AssignableTo(v.Type().Key()) {
+				return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
+			}
+			if x := v.MapIndex(index); x.IsValid() {
+				v = x
+			} else {
+				v = reflect.Zero(v.Type().Elem())
+			}
+		default:
+			return nil, fmt.Errorf("can't index item of type %s", v.Type())
+		}
+	}
+	return v.Interface(), nil
+}
+
+// Length
+
+// length returns the length of the item, with an error if it has no defined length.
+func length(item interface{}) (int, error) {
+	v, isNil := indirect(reflect.ValueOf(item))
+	if isNil {
+		return 0, fmt.Errorf("len of nil pointer")
+	}
+	switch v.Kind() {
+	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
+		return v.Len(), nil
+	}
+	return 0, fmt.Errorf("len of type %s", v.Type())
+}
+
+// Function invocation
+
+// call returns the result of evaluating the first argument as a function.
+// The function must return 1 result, or 2 results, the second of which is an error.
+func call(fn interface{}, args ...interface{}) (interface{}, error) {
+	v := reflect.ValueOf(fn)
+	typ := v.Type()
+	if typ.Kind() != reflect.Func {
+		return nil, fmt.Errorf("non-function of type %s", typ)
+	}
+	if !goodFunc(typ) {
+		return nil, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut())
+	}
+	numIn := typ.NumIn()
+	var dddType reflect.Type
+	if typ.IsVariadic() {
+		if len(args) < numIn-1 {
+			return nil, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1)
+		}
+		dddType = typ.In(numIn - 1).Elem()
+	} else {
+		if len(args) != numIn {
+			return nil, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn)
+		}
+	}
+	argv := make([]reflect.Value, len(args))
+	for i, arg := range args {
+		value := reflect.ValueOf(arg)
+		// Compute the expected type. Clumsy because of variadics.
+		var argType reflect.Type
+		if !typ.IsVariadic() || i < numIn-1 {
+			argType = typ.In(i)
+		} else {
+			argType = dddType
+		}
+		if !value.IsValid() && canBeNil(argType) {
+			value = reflect.Zero(argType)
+		}
+		if !value.Type().AssignableTo(argType) {
+			return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType)
+		}
+		argv[i] = value
+	}
+	result := v.Call(argv)
+	if len(result) == 2 && !result[1].IsNil() {
+		return result[0].Interface(), result[1].Interface().(error)
+	}
+	return result[0].Interface(), nil
+}
+
+// Boolean logic.
+
+func truth(a interface{}) bool {
+	t, _ := isTrue(reflect.ValueOf(a))
+	return t
+}
+
+// and computes the Boolean AND of its arguments, returning
+// the first false argument it encounters, or the last argument.
+func and(arg0 interface{}, args ...interface{}) interface{} {
+	if !truth(arg0) {
+		return arg0
+	}
+	for i := range args {
+		arg0 = args[i]
+		if !truth(arg0) {
+			break
+		}
+	}
+	return arg0
+}
+
+// or computes the Boolean OR of its arguments, returning
+// the first true argument it encounters, or the last argument.
+func or(arg0 interface{}, args ...interface{}) interface{} {
+	if truth(arg0) {
+		return arg0
+	}
+	for i := range args {
+		arg0 = args[i]
+		if truth(arg0) {
+			break
+		}
+	}
+	return arg0
+}
+
+// not returns the Boolean negation of its argument.
+func not(arg interface{}) (truth bool) {
+	truth, _ = isTrue(reflect.ValueOf(arg))
+	return !truth
+}
+
+// Comparison.
+
+// TODO: Perhaps allow comparison between signed and unsigned integers.
+
+var (
+	errBadComparisonType = errors.New("invalid type for comparison")
+	errBadComparison     = errors.New("incompatible types for comparison")
+	errNoComparison      = errors.New("missing argument for comparison")
+)
+
+type kind int
+
+const (
+	invalidKind kind = iota
+	boolKind
+	complexKind
+	intKind
+	floatKind
+	integerKind
+	stringKind
+	uintKind
+)
+
+func basicKind(v reflect.Value) (kind, error) {
+	switch v.Kind() {
+	case reflect.Bool:
+		return boolKind, nil
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return intKind, nil
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return uintKind, nil
+	case reflect.Float32, reflect.Float64:
+		return floatKind, nil
+	case reflect.Complex64, reflect.Complex128:
+		return complexKind, nil
+	case reflect.String:
+		return stringKind, nil
+	}
+	return invalidKind, errBadComparisonType
+}
+
+// eq evaluates the comparison a == b || a == c || ...
+func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
+	v1 := reflect.ValueOf(arg1)
+	k1, err := basicKind(v1)
+	if err != nil {
+		return false, err
+	}
+	if len(arg2) == 0 {
+		return false, errNoComparison
+	}
+	for _, arg := range arg2 {
+		v2 := reflect.ValueOf(arg)
+		k2, err := basicKind(v2)
+		if err != nil {
+			return false, err
+		}
+		if k1 != k2 {
+			return false, errBadComparison
+		}
+		truth := false
+		switch k1 {
+		case boolKind:
+			truth = v1.Bool() == v2.Bool()
+		case complexKind:
+			truth = v1.Complex() == v2.Complex()
+		case floatKind:
+			truth = v1.Float() == v2.Float()
+		case intKind:
+			truth = v1.Int() == v2.Int()
+		case stringKind:
+			truth = v1.String() == v2.String()
+		case uintKind:
+			truth = v1.Uint() == v2.Uint()
+		default:
+			panic("invalid kind")
+		}
+		if truth {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
+// ne evaluates the comparison a != b.
+func ne(arg1, arg2 interface{}) (bool, error) {
+	// != is the inverse of ==.
+	equal, err := eq(arg1, arg2)
+	return !equal, err
+}
+
+// lt evaluates the comparison a < b.
+func lt(arg1, arg2 interface{}) (bool, error) {
+	v1 := reflect.ValueOf(arg1)
+	k1, err := basicKind(v1)
+	if err != nil {
+		return false, err
+	}
+	v2 := reflect.ValueOf(arg2)
+	k2, err := basicKind(v2)
+	if err != nil {
+		return false, err
+	}
+	if k1 != k2 {
+		return false, errBadComparison
+	}
+	truth := false
+	switch k1 {
+	case boolKind, complexKind:
+		return false, errBadComparisonType
+	case floatKind:
+		truth = v1.Float() < v2.Float()
+	case intKind:
+		truth = v1.Int() < v2.Int()
+	case stringKind:
+		truth = v1.String() < v2.String()
+	case uintKind:
+		truth = v1.Uint() < v2.Uint()
+	default:
+		panic("invalid kind")
+	}
+	return truth, nil
+}
+
+// le evaluates the comparison <= b.
+func le(arg1, arg2 interface{}) (bool, error) {
+	// <= is < or ==.
+	lessThan, err := lt(arg1, arg2)
+	if lessThan || err != nil {
+		return lessThan, err
+	}
+	return eq(arg1, arg2)
+}
+
+// gt evaluates the comparison a > b.
+func gt(arg1, arg2 interface{}) (bool, error) {
+	// > is the inverse of <=.
+	lessOrEqual, err := le(arg1, arg2)
+	if err != nil {
+		return false, err
+	}
+	return !lessOrEqual, nil
+}
+
+// ge evaluates the comparison a >= b.
+func ge(arg1, arg2 interface{}) (bool, error) {
+	// >= is the inverse of <.
+	lessThan, err := lt(arg1, arg2)
+	if err != nil {
+		return false, err
+	}
+	return !lessThan, nil
+}
+
+// HTML escaping.
+
+var (
+	htmlQuot = []byte("&#34;") // shorter than "&quot;"
+	htmlApos = []byte("&#39;") // shorter than "&apos;" and apos was not in HTML until HTML5
+	htmlAmp  = []byte("&amp;")
+	htmlLt   = []byte("&lt;")
+	htmlGt   = []byte("&gt;")
+)
+
+// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
+func HTMLEscape(w io.Writer, b []byte) {
+	last := 0
+	for i, c := range b {
+		var html []byte
+		switch c {
+		case '"':
+			html = htmlQuot
+		case '\'':
+			html = htmlApos
+		case '&':
+			html = htmlAmp
+		case '<':
+			html = htmlLt
+		case '>':
+			html = htmlGt
+		default:
+			continue
+		}
+		w.Write(b[last:i])
+		w.Write(html)
+		last = i + 1
+	}
+	w.Write(b[last:])
+}
+
+// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
+func HTMLEscapeString(s string) string {
+	// Avoid allocation if we can.
+	if strings.IndexAny(s, `'"&<>`) < 0 {
+		return s
+	}
+	var b bytes.Buffer
+	HTMLEscape(&b, []byte(s))
+	return b.String()
+}
+
+// HTMLEscaper returns the escaped HTML equivalent of the textual
+// representation of its arguments.
+func HTMLEscaper(args ...interface{}) string {
+	return HTMLEscapeString(evalArgs(args))
+}
+
+// JavaScript escaping.
+
+var (
+	jsLowUni = []byte(`\u00`)
+	hex      = []byte("0123456789ABCDEF")
+
+	jsBackslash = []byte(`\\`)
+	jsApos      = []byte(`\'`)
+	jsQuot      = []byte(`\"`)
+	jsLt        = []byte(`\x3C`)
+	jsGt        = []byte(`\x3E`)
+)
+
+// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
+func JSEscape(w io.Writer, b []byte) {
+	last := 0
+	for i := 0; i < len(b); i++ {
+		c := b[i]
+
+		if !jsIsSpecial(rune(c)) {
+			// fast path: nothing to do
+			continue
+		}
+		w.Write(b[last:i])
+
+		if c < utf8.RuneSelf {
+			// Quotes, slashes and angle brackets get quoted.
+			// Control characters get written as \u00XX.
+			switch c {
+			case '\\':
+				w.Write(jsBackslash)
+			case '\'':
+				w.Write(jsApos)
+			case '"':
+				w.Write(jsQuot)
+			case '<':
+				w.Write(jsLt)
+			case '>':
+				w.Write(jsGt)
+			default:
+				w.Write(jsLowUni)
+				t, b := c>>4, c&0x0f
+				w.Write(hex[t : t+1])
+				w.Write(hex[b : b+1])
+			}
+		} else {
+			// Unicode rune.
+			r, size := utf8.DecodeRune(b[i:])
+			if unicode.IsPrint(r) {
+				w.Write(b[i : i+size])
+			} else {
+				fmt.Fprintf(w, "\\u%04X", r)
+			}
+			i += size - 1
+		}
+		last = i + 1
+	}
+	w.Write(b[last:])
+}
+
+// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
+func JSEscapeString(s string) string {
+	// Avoid allocation if we can.
+	if strings.IndexFunc(s, jsIsSpecial) < 0 {
+		return s
+	}
+	var b bytes.Buffer
+	JSEscape(&b, []byte(s))
+	return b.String()
+}
+
+func jsIsSpecial(r rune) bool {
+	switch r {
+	case '\\', '\'', '"', '<', '>':
+		return true
+	}
+	return r < ' ' || utf8.RuneSelf <= r
+}
+
+// JSEscaper returns the escaped JavaScript equivalent of the textual
+// representation of its arguments.
+func JSEscaper(args ...interface{}) string {
+	return JSEscapeString(evalArgs(args))
+}
+
+// URLQueryEscaper returns the escaped value of the textual representation of
+// its arguments in a form suitable for embedding in a URL query.
+func URLQueryEscaper(args ...interface{}) string {
+	return url.QueryEscape(evalArgs(args))
+}
+
+// evalArgs formats the list of arguments into a string. It is therefore equivalent to
+//	fmt.Sprint(args...)
+// except that each argument is indirected (if a pointer), as required,
+// using the same rules as the default string evaluation during template
+// execution.
+func evalArgs(args []interface{}) string {
+	ok := false
+	var s string
+	// Fast path for simple common case.
+	if len(args) == 1 {
+		s, ok = args[0].(string)
+	}
+	if !ok {
+		for i, arg := range args {
+			a, ok := printableValue(reflect.ValueOf(arg))
+			if ok {
+				args[i] = a
+			} // else left fmt do its thing
+		}
+		s = fmt.Sprint(args...)
+	}
+	return s
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/helper.go b/third_party/gofrontend/libgo/go/text/template/helper.go
new file mode 100644
index 0000000..3636fb5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/helper.go
@@ -0,0 +1,108 @@
+// 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.
+
+// Helper functions to make constructing templates easier.
+
+package template
+
+import (
+	"fmt"
+	"io/ioutil"
+	"path/filepath"
+)
+
+// Functions and methods to parse templates.
+
+// Must is a helper that wraps a call to a function returning (*Template, error)
+// and panics if the error is non-nil. It is intended for use in variable
+// initializations such as
+//	var t = template.Must(template.New("name").Parse("text"))
+func Must(t *Template, err error) *Template {
+	if err != nil {
+		panic(err)
+	}
+	return t
+}
+
+// ParseFiles creates a new Template and parses the template definitions from
+// the named files. The returned template's name will have the (base) name and
+// (parsed) contents of the first file. There must be at least one file.
+// If an error occurs, parsing stops and the returned *Template is nil.
+func ParseFiles(filenames ...string) (*Template, error) {
+	return parseFiles(nil, filenames...)
+}
+
+// ParseFiles parses the named files and associates the resulting templates with
+// t. If an error occurs, parsing stops and the returned template is nil;
+// otherwise it is t. There must be at least one file.
+func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
+	return parseFiles(t, filenames...)
+}
+
+// parseFiles is the helper for the method and function. If the argument
+// template is nil, it is created from the first file.
+func parseFiles(t *Template, filenames ...string) (*Template, error) {
+	if len(filenames) == 0 {
+		// Not really a problem, but be consistent.
+		return nil, fmt.Errorf("template: no files named in call to ParseFiles")
+	}
+	for _, filename := range filenames {
+		b, err := ioutil.ReadFile(filename)
+		if err != nil {
+			return nil, err
+		}
+		s := string(b)
+		name := filepath.Base(filename)
+		// First template becomes return value if not already defined,
+		// and we use that one for subsequent New calls to associate
+		// all the templates together. Also, if this file has the same name
+		// as t, this file becomes the contents of t, so
+		//  t, err := New(name).Funcs(xxx).ParseFiles(name)
+		// works. Otherwise we create a new template associated with t.
+		var tmpl *Template
+		if t == nil {
+			t = New(name)
+		}
+		if name == t.Name() {
+			tmpl = t
+		} else {
+			tmpl = t.New(name)
+		}
+		_, err = tmpl.Parse(s)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return t, nil
+}
+
+// ParseGlob creates a new Template and parses the template definitions from the
+// files identified by the pattern, which must match at least one file. The
+// returned template will have the (base) name and (parsed) contents of the
+// first file matched by the pattern. ParseGlob is equivalent to calling
+// ParseFiles with the list of files matched by the pattern.
+func ParseGlob(pattern string) (*Template, error) {
+	return parseGlob(nil, pattern)
+}
+
+// ParseGlob parses the template definitions in the files identified by the
+// pattern and associates the resulting templates with t. The pattern is
+// processed by filepath.Glob and must match at least one file. ParseGlob is
+// equivalent to calling t.ParseFiles with the list of files matched by the
+// pattern.
+func (t *Template) ParseGlob(pattern string) (*Template, error) {
+	return parseGlob(t, pattern)
+}
+
+// parseGlob is the implementation of the function and method ParseGlob.
+func parseGlob(t *Template, pattern string) (*Template, error) {
+	filenames, err := filepath.Glob(pattern)
+	if err != nil {
+		return nil, err
+	}
+	if len(filenames) == 0 {
+		return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
+	}
+	return parseFiles(t, filenames...)
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/multi_test.go b/third_party/gofrontend/libgo/go/text/template/multi_test.go
new file mode 100644
index 0000000..e4e8048
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/multi_test.go
@@ -0,0 +1,292 @@
+// 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.
+
+package template
+
+// Tests for mulitple-template parsing and execution.
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"testing"
+	"text/template/parse"
+)
+
+const (
+	noError  = true
+	hasError = false
+)
+
+type multiParseTest struct {
+	name    string
+	input   string
+	ok      bool
+	names   []string
+	results []string
+}
+
+var multiParseTests = []multiParseTest{
+	{"empty", "", noError,
+		nil,
+		nil},
+	{"one", `{{define "foo"}} FOO {{end}}`, noError,
+		[]string{"foo"},
+		[]string{" FOO "}},
+	{"two", `{{define "foo"}} FOO {{end}}{{define "bar"}} BAR {{end}}`, noError,
+		[]string{"foo", "bar"},
+		[]string{" FOO ", " BAR "}},
+	// errors
+	{"missing end", `{{define "foo"}} FOO `, hasError,
+		nil,
+		nil},
+	{"malformed name", `{{define "foo}} FOO `, hasError,
+		nil,
+		nil},
+}
+
+func TestMultiParse(t *testing.T) {
+	for _, test := range multiParseTests {
+		template, err := New("root").Parse(test.input)
+		switch {
+		case err == nil && !test.ok:
+			t.Errorf("%q: expected error; got none", test.name)
+			continue
+		case err != nil && test.ok:
+			t.Errorf("%q: unexpected error: %v", test.name, err)
+			continue
+		case err != nil && !test.ok:
+			// expected error, got one
+			if *debug {
+				fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
+			}
+			continue
+		}
+		if template == nil {
+			continue
+		}
+		if len(template.tmpl) != len(test.names)+1 { // +1 for root
+			t.Errorf("%s: wrong number of templates; wanted %d got %d", test.name, len(test.names), len(template.tmpl))
+			continue
+		}
+		for i, name := range test.names {
+			tmpl, ok := template.tmpl[name]
+			if !ok {
+				t.Errorf("%s: can't find template %q", test.name, name)
+				continue
+			}
+			result := tmpl.Root.String()
+			if result != test.results[i] {
+				t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.results[i])
+			}
+		}
+	}
+}
+
+var multiExecTests = []execTest{
+	{"empty", "", "", nil, true},
+	{"text", "some text", "some text", nil, true},
+	{"invoke x", `{{template "x" .SI}}`, "TEXT", tVal, true},
+	{"invoke x no args", `{{template "x"}}`, "TEXT", tVal, true},
+	{"invoke dot int", `{{template "dot" .I}}`, "17", tVal, true},
+	{"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true},
+	{"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true},
+	{"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
+	{"variable declared by template", `{{template "nested" $x:=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true},
+
+	// User-defined function: test argument evaluator.
+	{"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true},
+	{"testFunc .", `{{oneArg .}}`, "oneArg=joe", "joe", true},
+}
+
+// These strings are also in testdata/*.
+const multiText1 = `
+	{{define "x"}}TEXT{{end}}
+	{{define "dotV"}}{{.V}}{{end}}
+`
+
+const multiText2 = `
+	{{define "dot"}}{{.}}{{end}}
+	{{define "nested"}}{{template "dot" .}}{{end}}
+`
+
+func TestMultiExecute(t *testing.T) {
+	// Declare a couple of templates first.
+	template, err := New("root").Parse(multiText1)
+	if err != nil {
+		t.Fatalf("parse error for 1: %s", err)
+	}
+	_, err = template.Parse(multiText2)
+	if err != nil {
+		t.Fatalf("parse error for 2: %s", err)
+	}
+	testExecute(multiExecTests, template, t)
+}
+
+func TestParseFiles(t *testing.T) {
+	_, err := ParseFiles("DOES NOT EXIST")
+	if err == nil {
+		t.Error("expected error for non-existent file; got none")
+	}
+	template := New("root")
+	_, err = template.ParseFiles("testdata/file1.tmpl", "testdata/file2.tmpl")
+	if err != nil {
+		t.Fatalf("error parsing files: %v", err)
+	}
+	testExecute(multiExecTests, template, t)
+}
+
+func TestParseGlob(t *testing.T) {
+	_, err := ParseGlob("DOES NOT EXIST")
+	if err == nil {
+		t.Error("expected error for non-existent file; got none")
+	}
+	_, err = New("error").ParseGlob("[x")
+	if err == nil {
+		t.Error("expected error for bad pattern; got none")
+	}
+	template := New("root")
+	_, err = template.ParseGlob("testdata/file*.tmpl")
+	if err != nil {
+		t.Fatalf("error parsing files: %v", err)
+	}
+	testExecute(multiExecTests, template, t)
+}
+
+// In these tests, actual content (not just template definitions) comes from the parsed files.
+
+var templateFileExecTests = []execTest{
+	{"test", `{{template "tmpl1.tmpl"}}{{template "tmpl2.tmpl"}}`, "template1\n\ny\ntemplate2\n\nx\n", 0, true},
+}
+
+func TestParseFilesWithData(t *testing.T) {
+	template, err := New("root").ParseFiles("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl")
+	if err != nil {
+		t.Fatalf("error parsing files: %v", err)
+	}
+	testExecute(templateFileExecTests, template, t)
+}
+
+func TestParseGlobWithData(t *testing.T) {
+	template, err := New("root").ParseGlob("testdata/tmpl*.tmpl")
+	if err != nil {
+		t.Fatalf("error parsing files: %v", err)
+	}
+	testExecute(templateFileExecTests, template, t)
+}
+
+const (
+	cloneText1 = `{{define "a"}}{{template "b"}}{{template "c"}}{{end}}`
+	cloneText2 = `{{define "b"}}b{{end}}`
+	cloneText3 = `{{define "c"}}root{{end}}`
+	cloneText4 = `{{define "c"}}clone{{end}}`
+)
+
+func TestClone(t *testing.T) {
+	// Create some templates and clone the root.
+	root, err := New("root").Parse(cloneText1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = root.Parse(cloneText2)
+	if err != nil {
+		t.Fatal(err)
+	}
+	clone := Must(root.Clone())
+	// Add variants to both.
+	_, err = root.Parse(cloneText3)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = clone.Parse(cloneText4)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Verify that the clone is self-consistent.
+	for k, v := range clone.tmpl {
+		if k == clone.name && v.tmpl[k] != clone {
+			t.Error("clone does not contain root")
+		}
+		if v != v.tmpl[v.name] {
+			t.Errorf("clone does not contain self for %q", k)
+		}
+	}
+	// Execute root.
+	var b bytes.Buffer
+	err = root.ExecuteTemplate(&b, "a", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if b.String() != "broot" {
+		t.Errorf("expected %q got %q", "broot", b.String())
+	}
+	// Execute copy.
+	b.Reset()
+	err = clone.ExecuteTemplate(&b, "a", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if b.String() != "bclone" {
+		t.Errorf("expected %q got %q", "bclone", b.String())
+	}
+}
+
+func TestAddParseTree(t *testing.T) {
+	// Create some templates.
+	root, err := New("root").Parse(cloneText1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = root.Parse(cloneText2)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Add a new parse tree.
+	tree, err := parse.Parse("cloneText3", cloneText3, "", "", nil, builtins)
+	if err != nil {
+		t.Fatal(err)
+	}
+	added, err := root.AddParseTree("c", tree["c"])
+	// Execute.
+	var b bytes.Buffer
+	err = added.ExecuteTemplate(&b, "a", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if b.String() != "broot" {
+		t.Errorf("expected %q got %q", "broot", b.String())
+	}
+}
+
+// Issue 7032
+func TestAddParseTreeToUnparsedTemplate(t *testing.T) {
+	master := "{{define \"master\"}}{{end}}"
+	tmpl := New("master")
+	tree, err := parse.Parse("master", master, "", "", nil)
+	if err != nil {
+		t.Fatalf("unexpected parse err: %v", err)
+	}
+	masterTree := tree["master"]
+	tmpl.AddParseTree("master", masterTree) // used to panic
+}
+
+func TestRedefinition(t *testing.T) {
+	var tmpl *Template
+	var err error
+	if tmpl, err = New("tmpl1").Parse(`{{define "test"}}foo{{end}}`); err != nil {
+		t.Fatalf("parse 1: %v", err)
+	}
+	if _, err = tmpl.Parse(`{{define "test"}}bar{{end}}`); err == nil {
+		t.Fatal("expected error")
+	}
+	if !strings.Contains(err.Error(), "redefinition") {
+		t.Fatalf("expected redefinition error; got %v", err)
+	}
+	if _, err = tmpl.New("tmpl2").Parse(`{{define "test"}}bar{{end}}`); err == nil {
+		t.Fatal("expected error")
+	}
+	if !strings.Contains(err.Error(), "redefinition") {
+		t.Fatalf("expected redefinition error; got %v", err)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/parse/lex.go b/third_party/gofrontend/libgo/go/text/template/parse/lex.go
new file mode 100644
index 0000000..1674aaf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/parse/lex.go
@@ -0,0 +1,551 @@
+// 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.
+
+package parse
+
+import (
+	"fmt"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// item represents a token or text string returned from the scanner.
+type item struct {
+	typ itemType // The type of this item.
+	pos Pos      // The starting position, in bytes, of this item in the input string.
+	val string   // The value of this item.
+}
+
+func (i item) String() string {
+	switch {
+	case i.typ == itemEOF:
+		return "EOF"
+	case i.typ == itemError:
+		return i.val
+	case i.typ > itemKeyword:
+		return fmt.Sprintf("<%s>", i.val)
+	case len(i.val) > 10:
+		return fmt.Sprintf("%.10q...", i.val)
+	}
+	return fmt.Sprintf("%q", i.val)
+}
+
+// itemType identifies the type of lex items.
+type itemType int
+
+const (
+	itemError        itemType = iota // error occurred; value is text of error
+	itemBool                         // boolean constant
+	itemChar                         // printable ASCII character; grab bag for comma etc.
+	itemCharConstant                 // character constant
+	itemComplex                      // complex constant (1+2i); imaginary is just a number
+	itemColonEquals                  // colon-equals (':=') introducing a declaration
+	itemEOF
+	itemField      // alphanumeric identifier starting with '.'
+	itemIdentifier // alphanumeric identifier not starting with '.'
+	itemLeftDelim  // left action delimiter
+	itemLeftParen  // '(' inside action
+	itemNumber     // simple number, including imaginary
+	itemPipe       // pipe symbol
+	itemRawString  // raw quoted string (includes quotes)
+	itemRightDelim // right action delimiter
+	itemRightParen // ')' inside action
+	itemSpace      // run of spaces separating arguments
+	itemString     // quoted string (includes quotes)
+	itemText       // plain text
+	itemVariable   // variable starting with '$', such as '$' or  '$1' or '$hello'
+	// Keywords appear after all the rest.
+	itemKeyword  // used only to delimit the keywords
+	itemDot      // the cursor, spelled '.'
+	itemDefine   // define keyword
+	itemElse     // else keyword
+	itemEnd      // end keyword
+	itemIf       // if keyword
+	itemNil      // the untyped nil constant, easiest to treat as a keyword
+	itemRange    // range keyword
+	itemTemplate // template keyword
+	itemWith     // with keyword
+)
+
+var key = map[string]itemType{
+	".":        itemDot,
+	"define":   itemDefine,
+	"else":     itemElse,
+	"end":      itemEnd,
+	"if":       itemIf,
+	"range":    itemRange,
+	"nil":      itemNil,
+	"template": itemTemplate,
+	"with":     itemWith,
+}
+
+const eof = -1
+
+// stateFn represents the state of the scanner as a function that returns the next state.
+type stateFn func(*lexer) stateFn
+
+// lexer holds the state of the scanner.
+type lexer struct {
+	name       string    // the name of the input; used only for error reports
+	input      string    // the string being scanned
+	leftDelim  string    // start of action
+	rightDelim string    // end of action
+	state      stateFn   // the next lexing function to enter
+	pos        Pos       // current position in the input
+	start      Pos       // start position of this item
+	width      Pos       // width of last rune read from input
+	lastPos    Pos       // position of most recent item returned by nextItem
+	items      chan item // channel of scanned items
+	parenDepth int       // nesting depth of ( ) exprs
+}
+
+// next returns the next rune in the input.
+func (l *lexer) next() rune {
+	if int(l.pos) >= len(l.input) {
+		l.width = 0
+		return eof
+	}
+	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
+	l.width = Pos(w)
+	l.pos += l.width
+	return r
+}
+
+// peek returns but does not consume the next rune in the input.
+func (l *lexer) peek() rune {
+	r := l.next()
+	l.backup()
+	return r
+}
+
+// backup steps back one rune. Can only be called once per call of next.
+func (l *lexer) backup() {
+	l.pos -= l.width
+}
+
+// emit passes an item back to the client.
+func (l *lexer) emit(t itemType) {
+	l.items <- item{t, l.start, l.input[l.start:l.pos]}
+	l.start = l.pos
+}
+
+// ignore skips over the pending input before this point.
+func (l *lexer) ignore() {
+	l.start = l.pos
+}
+
+// accept consumes the next rune if it's from the valid set.
+func (l *lexer) accept(valid string) bool {
+	if strings.IndexRune(valid, l.next()) >= 0 {
+		return true
+	}
+	l.backup()
+	return false
+}
+
+// acceptRun consumes a run of runes from the valid set.
+func (l *lexer) acceptRun(valid string) {
+	for strings.IndexRune(valid, l.next()) >= 0 {
+	}
+	l.backup()
+}
+
+// lineNumber reports which line we're on, based on the position of
+// the previous item returned by nextItem. Doing it this way
+// means we don't have to worry about peek double counting.
+func (l *lexer) lineNumber() int {
+	return 1 + strings.Count(l.input[:l.lastPos], "\n")
+}
+
+// errorf returns an error token and terminates the scan by passing
+// back a nil pointer that will be the next state, terminating l.nextItem.
+func (l *lexer) errorf(format string, args ...interface{}) stateFn {
+	l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
+	return nil
+}
+
+// nextItem returns the next item from the input.
+func (l *lexer) nextItem() item {
+	item := <-l.items
+	l.lastPos = item.pos
+	return item
+}
+
+// lex creates a new scanner for the input string.
+func lex(name, input, left, right string) *lexer {
+	if left == "" {
+		left = leftDelim
+	}
+	if right == "" {
+		right = rightDelim
+	}
+	l := &lexer{
+		name:       name,
+		input:      input,
+		leftDelim:  left,
+		rightDelim: right,
+		items:      make(chan item),
+	}
+	go l.run()
+	return l
+}
+
+// run runs the state machine for the lexer.
+func (l *lexer) run() {
+	for l.state = lexText; l.state != nil; {
+		l.state = l.state(l)
+	}
+}
+
+// state functions
+
+const (
+	leftDelim    = "{{"
+	rightDelim   = "}}"
+	leftComment  = "/*"
+	rightComment = "*/"
+)
+
+// lexText scans until an opening action delimiter, "{{".
+func lexText(l *lexer) stateFn {
+	for {
+		if strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
+			if l.pos > l.start {
+				l.emit(itemText)
+			}
+			return lexLeftDelim
+		}
+		if l.next() == eof {
+			break
+		}
+	}
+	// Correctly reached EOF.
+	if l.pos > l.start {
+		l.emit(itemText)
+	}
+	l.emit(itemEOF)
+	return nil
+}
+
+// lexLeftDelim scans the left delimiter, which is known to be present.
+func lexLeftDelim(l *lexer) stateFn {
+	l.pos += Pos(len(l.leftDelim))
+	if strings.HasPrefix(l.input[l.pos:], leftComment) {
+		return lexComment
+	}
+	l.emit(itemLeftDelim)
+	l.parenDepth = 0
+	return lexInsideAction
+}
+
+// lexComment scans a comment. The left comment marker is known to be present.
+func lexComment(l *lexer) stateFn {
+	l.pos += Pos(len(leftComment))
+	i := strings.Index(l.input[l.pos:], rightComment)
+	if i < 0 {
+		return l.errorf("unclosed comment")
+	}
+	l.pos += Pos(i + len(rightComment))
+	if !strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+		return l.errorf("comment ends before closing delimiter")
+
+	}
+	l.pos += Pos(len(l.rightDelim))
+	l.ignore()
+	return lexText
+}
+
+// lexRightDelim scans the right delimiter, which is known to be present.
+func lexRightDelim(l *lexer) stateFn {
+	l.pos += Pos(len(l.rightDelim))
+	l.emit(itemRightDelim)
+	return lexText
+}
+
+// lexInsideAction scans the elements inside action delimiters.
+func lexInsideAction(l *lexer) stateFn {
+	// Either number, quoted string, or identifier.
+	// Spaces separate arguments; runs of spaces turn into itemSpace.
+	// Pipe symbols separate and are emitted.
+	if strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+		if l.parenDepth == 0 {
+			return lexRightDelim
+		}
+		return l.errorf("unclosed left paren")
+	}
+	switch r := l.next(); {
+	case r == eof || isEndOfLine(r):
+		return l.errorf("unclosed action")
+	case isSpace(r):
+		return lexSpace
+	case r == ':':
+		if l.next() != '=' {
+			return l.errorf("expected :=")
+		}
+		l.emit(itemColonEquals)
+	case r == '|':
+		l.emit(itemPipe)
+	case r == '"':
+		return lexQuote
+	case r == '`':
+		return lexRawQuote
+	case r == '$':
+		return lexVariable
+	case r == '\'':
+		return lexChar
+	case r == '.':
+		// special look-ahead for ".field" so we don't break l.backup().
+		if l.pos < Pos(len(l.input)) {
+			r := l.input[l.pos]
+			if r < '0' || '9' < r {
+				return lexField
+			}
+		}
+		fallthrough // '.' can start a number.
+	case r == '+' || r == '-' || ('0' <= r && r <= '9'):
+		l.backup()
+		return lexNumber
+	case isAlphaNumeric(r):
+		l.backup()
+		return lexIdentifier
+	case r == '(':
+		l.emit(itemLeftParen)
+		l.parenDepth++
+		return lexInsideAction
+	case r == ')':
+		l.emit(itemRightParen)
+		l.parenDepth--
+		if l.parenDepth < 0 {
+			return l.errorf("unexpected right paren %#U", r)
+		}
+		return lexInsideAction
+	case r <= unicode.MaxASCII && unicode.IsPrint(r):
+		l.emit(itemChar)
+		return lexInsideAction
+	default:
+		return l.errorf("unrecognized character in action: %#U", r)
+	}
+	return lexInsideAction
+}
+
+// lexSpace scans a run of space characters.
+// One space has already been seen.
+func lexSpace(l *lexer) stateFn {
+	for isSpace(l.peek()) {
+		l.next()
+	}
+	l.emit(itemSpace)
+	return lexInsideAction
+}
+
+// lexIdentifier scans an alphanumeric.
+func lexIdentifier(l *lexer) stateFn {
+Loop:
+	for {
+		switch r := l.next(); {
+		case isAlphaNumeric(r):
+			// absorb.
+		default:
+			l.backup()
+			word := l.input[l.start:l.pos]
+			if !l.atTerminator() {
+				return l.errorf("bad character %#U", r)
+			}
+			switch {
+			case key[word] > itemKeyword:
+				l.emit(key[word])
+			case word[0] == '.':
+				l.emit(itemField)
+			case word == "true", word == "false":
+				l.emit(itemBool)
+			default:
+				l.emit(itemIdentifier)
+			}
+			break Loop
+		}
+	}
+	return lexInsideAction
+}
+
+// lexField scans a field: .Alphanumeric.
+// The . has been scanned.
+func lexField(l *lexer) stateFn {
+	return lexFieldOrVariable(l, itemField)
+}
+
+// lexVariable scans a Variable: $Alphanumeric.
+// The $ has been scanned.
+func lexVariable(l *lexer) stateFn {
+	if l.atTerminator() { // Nothing interesting follows -> "$".
+		l.emit(itemVariable)
+		return lexInsideAction
+	}
+	return lexFieldOrVariable(l, itemVariable)
+}
+
+// lexVariable scans a field or variable: [.$]Alphanumeric.
+// The . or $ has been scanned.
+func lexFieldOrVariable(l *lexer, typ itemType) stateFn {
+	if l.atTerminator() { // Nothing interesting follows -> "." or "$".
+		if typ == itemVariable {
+			l.emit(itemVariable)
+		} else {
+			l.emit(itemDot)
+		}
+		return lexInsideAction
+	}
+	var r rune
+	for {
+		r = l.next()
+		if !isAlphaNumeric(r) {
+			l.backup()
+			break
+		}
+	}
+	if !l.atTerminator() {
+		return l.errorf("bad character %#U", r)
+	}
+	l.emit(typ)
+	return lexInsideAction
+}
+
+// atTerminator reports whether the input is at valid termination character to
+// appear after an identifier. Breaks .X.Y into two pieces. Also catches cases
+// like "$x+2" not being acceptable without a space, in case we decide one
+// day to implement arithmetic.
+func (l *lexer) atTerminator() bool {
+	r := l.peek()
+	if isSpace(r) || isEndOfLine(r) {
+		return true
+	}
+	switch r {
+	case eof, '.', ',', '|', ':', ')', '(':
+		return true
+	}
+	// Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will
+	// succeed but should fail) but only in extremely rare cases caused by willfully
+	// bad choice of delimiter.
+	if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r {
+		return true
+	}
+	return false
+}
+
+// lexChar scans a character constant. The initial quote is already
+// scanned. Syntax checking is done by the parser.
+func lexChar(l *lexer) stateFn {
+Loop:
+	for {
+		switch l.next() {
+		case '\\':
+			if r := l.next(); r != eof && r != '\n' {
+				break
+			}
+			fallthrough
+		case eof, '\n':
+			return l.errorf("unterminated character constant")
+		case '\'':
+			break Loop
+		}
+	}
+	l.emit(itemCharConstant)
+	return lexInsideAction
+}
+
+// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This
+// isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
+// and "089" - but when it's wrong the input is invalid and the parser (via
+// strconv) will notice.
+func lexNumber(l *lexer) stateFn {
+	if !l.scanNumber() {
+		return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
+	}
+	if sign := l.peek(); sign == '+' || sign == '-' {
+		// Complex: 1+2i. No spaces, must end in 'i'.
+		if !l.scanNumber() || l.input[l.pos-1] != 'i' {
+			return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
+		}
+		l.emit(itemComplex)
+	} else {
+		l.emit(itemNumber)
+	}
+	return lexInsideAction
+}
+
+func (l *lexer) scanNumber() bool {
+	// Optional leading sign.
+	l.accept("+-")
+	// Is it hex?
+	digits := "0123456789"
+	if l.accept("0") && l.accept("xX") {
+		digits = "0123456789abcdefABCDEF"
+	}
+	l.acceptRun(digits)
+	if l.accept(".") {
+		l.acceptRun(digits)
+	}
+	if l.accept("eE") {
+		l.accept("+-")
+		l.acceptRun("0123456789")
+	}
+	// Is it imaginary?
+	l.accept("i")
+	// Next thing mustn't be alphanumeric.
+	if isAlphaNumeric(l.peek()) {
+		l.next()
+		return false
+	}
+	return true
+}
+
+// lexQuote scans a quoted string.
+func lexQuote(l *lexer) stateFn {
+Loop:
+	for {
+		switch l.next() {
+		case '\\':
+			if r := l.next(); r != eof && r != '\n' {
+				break
+			}
+			fallthrough
+		case eof, '\n':
+			return l.errorf("unterminated quoted string")
+		case '"':
+			break Loop
+		}
+	}
+	l.emit(itemString)
+	return lexInsideAction
+}
+
+// lexRawQuote scans a raw quoted string.
+func lexRawQuote(l *lexer) stateFn {
+Loop:
+	for {
+		switch l.next() {
+		case eof, '\n':
+			return l.errorf("unterminated raw quoted string")
+		case '`':
+			break Loop
+		}
+	}
+	l.emit(itemRawString)
+	return lexInsideAction
+}
+
+// isSpace reports whether r is a space character.
+func isSpace(r rune) bool {
+	return r == ' ' || r == '\t'
+}
+
+// isEndOfLine reports whether r is an end-of-line character.
+func isEndOfLine(r rune) bool {
+	return r == '\r' || r == '\n'
+}
+
+// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
+func isAlphaNumeric(r rune) bool {
+	return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/parse/lex_test.go b/third_party/gofrontend/libgo/go/text/template/parse/lex_test.go
new file mode 100644
index 0000000..d251ccf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/parse/lex_test.go
@@ -0,0 +1,465 @@
+// 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.
+
+package parse
+
+import (
+	"fmt"
+	"testing"
+)
+
+// Make the types prettyprint.
+var itemName = map[itemType]string{
+	itemError:        "error",
+	itemBool:         "bool",
+	itemChar:         "char",
+	itemCharConstant: "charconst",
+	itemComplex:      "complex",
+	itemColonEquals:  ":=",
+	itemEOF:          "EOF",
+	itemField:        "field",
+	itemIdentifier:   "identifier",
+	itemLeftDelim:    "left delim",
+	itemLeftParen:    "(",
+	itemNumber:       "number",
+	itemPipe:         "pipe",
+	itemRawString:    "raw string",
+	itemRightDelim:   "right delim",
+	itemRightParen:   ")",
+	itemSpace:        "space",
+	itemString:       "string",
+	itemVariable:     "variable",
+
+	// keywords
+	itemDot:      ".",
+	itemDefine:   "define",
+	itemElse:     "else",
+	itemIf:       "if",
+	itemEnd:      "end",
+	itemNil:      "nil",
+	itemRange:    "range",
+	itemTemplate: "template",
+	itemWith:     "with",
+}
+
+func (i itemType) String() string {
+	s := itemName[i]
+	if s == "" {
+		return fmt.Sprintf("item%d", int(i))
+	}
+	return s
+}
+
+type lexTest struct {
+	name  string
+	input string
+	items []item
+}
+
+var (
+	tEOF      = item{itemEOF, 0, ""}
+	tFor      = item{itemIdentifier, 0, "for"}
+	tLeft     = item{itemLeftDelim, 0, "{{"}
+	tLpar     = item{itemLeftParen, 0, "("}
+	tPipe     = item{itemPipe, 0, "|"}
+	tQuote    = item{itemString, 0, `"abc \n\t\" "`}
+	tRange    = item{itemRange, 0, "range"}
+	tRight    = item{itemRightDelim, 0, "}}"}
+	tRpar     = item{itemRightParen, 0, ")"}
+	tSpace    = item{itemSpace, 0, " "}
+	raw       = "`" + `abc\n\t\" ` + "`"
+	tRawQuote = item{itemRawString, 0, raw}
+)
+
+var lexTests = []lexTest{
+	{"empty", "", []item{tEOF}},
+	{"spaces", " \t\n", []item{{itemText, 0, " \t\n"}, tEOF}},
+	{"text", `now is the time`, []item{{itemText, 0, "now is the time"}, tEOF}},
+	{"text with comment", "hello-{{/* this is a comment */}}-world", []item{
+		{itemText, 0, "hello-"},
+		{itemText, 0, "-world"},
+		tEOF,
+	}},
+	{"punctuation", "{{,@% }}", []item{
+		tLeft,
+		{itemChar, 0, ","},
+		{itemChar, 0, "@"},
+		{itemChar, 0, "%"},
+		tSpace,
+		tRight,
+		tEOF,
+	}},
+	{"parens", "{{((3))}}", []item{
+		tLeft,
+		tLpar,
+		tLpar,
+		{itemNumber, 0, "3"},
+		tRpar,
+		tRpar,
+		tRight,
+		tEOF,
+	}},
+	{"empty action", `{{}}`, []item{tLeft, tRight, tEOF}},
+	{"for", `{{for}}`, []item{tLeft, tFor, tRight, tEOF}},
+	{"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}},
+	{"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}},
+	{"numbers", "{{1 02 0x14 -7.2i 1e3 +1.2e-4 4.2i 1+2i}}", []item{
+		tLeft,
+		{itemNumber, 0, "1"},
+		tSpace,
+		{itemNumber, 0, "02"},
+		tSpace,
+		{itemNumber, 0, "0x14"},
+		tSpace,
+		{itemNumber, 0, "-7.2i"},
+		tSpace,
+		{itemNumber, 0, "1e3"},
+		tSpace,
+		{itemNumber, 0, "+1.2e-4"},
+		tSpace,
+		{itemNumber, 0, "4.2i"},
+		tSpace,
+		{itemComplex, 0, "1+2i"},
+		tRight,
+		tEOF,
+	}},
+	{"characters", `{{'a' '\n' '\'' '\\' '\u00FF' '\xFF' '本'}}`, []item{
+		tLeft,
+		{itemCharConstant, 0, `'a'`},
+		tSpace,
+		{itemCharConstant, 0, `'\n'`},
+		tSpace,
+		{itemCharConstant, 0, `'\''`},
+		tSpace,
+		{itemCharConstant, 0, `'\\'`},
+		tSpace,
+		{itemCharConstant, 0, `'\u00FF'`},
+		tSpace,
+		{itemCharConstant, 0, `'\xFF'`},
+		tSpace,
+		{itemCharConstant, 0, `'本'`},
+		tRight,
+		tEOF,
+	}},
+	{"bools", "{{true false}}", []item{
+		tLeft,
+		{itemBool, 0, "true"},
+		tSpace,
+		{itemBool, 0, "false"},
+		tRight,
+		tEOF,
+	}},
+	{"dot", "{{.}}", []item{
+		tLeft,
+		{itemDot, 0, "."},
+		tRight,
+		tEOF,
+	}},
+	{"nil", "{{nil}}", []item{
+		tLeft,
+		{itemNil, 0, "nil"},
+		tRight,
+		tEOF,
+	}},
+	{"dots", "{{.x . .2 .x.y.z}}", []item{
+		tLeft,
+		{itemField, 0, ".x"},
+		tSpace,
+		{itemDot, 0, "."},
+		tSpace,
+		{itemNumber, 0, ".2"},
+		tSpace,
+		{itemField, 0, ".x"},
+		{itemField, 0, ".y"},
+		{itemField, 0, ".z"},
+		tRight,
+		tEOF,
+	}},
+	{"keywords", "{{range if else end with}}", []item{
+		tLeft,
+		{itemRange, 0, "range"},
+		tSpace,
+		{itemIf, 0, "if"},
+		tSpace,
+		{itemElse, 0, "else"},
+		tSpace,
+		{itemEnd, 0, "end"},
+		tSpace,
+		{itemWith, 0, "with"},
+		tRight,
+		tEOF,
+	}},
+	{"variables", "{{$c := printf $ $hello $23 $ $var.Field .Method}}", []item{
+		tLeft,
+		{itemVariable, 0, "$c"},
+		tSpace,
+		{itemColonEquals, 0, ":="},
+		tSpace,
+		{itemIdentifier, 0, "printf"},
+		tSpace,
+		{itemVariable, 0, "$"},
+		tSpace,
+		{itemVariable, 0, "$hello"},
+		tSpace,
+		{itemVariable, 0, "$23"},
+		tSpace,
+		{itemVariable, 0, "$"},
+		tSpace,
+		{itemVariable, 0, "$var"},
+		{itemField, 0, ".Field"},
+		tSpace,
+		{itemField, 0, ".Method"},
+		tRight,
+		tEOF,
+	}},
+	{"variable invocation", "{{$x 23}}", []item{
+		tLeft,
+		{itemVariable, 0, "$x"},
+		tSpace,
+		{itemNumber, 0, "23"},
+		tRight,
+		tEOF,
+	}},
+	{"pipeline", `intro {{echo hi 1.2 |noargs|args 1 "hi"}} outro`, []item{
+		{itemText, 0, "intro "},
+		tLeft,
+		{itemIdentifier, 0, "echo"},
+		tSpace,
+		{itemIdentifier, 0, "hi"},
+		tSpace,
+		{itemNumber, 0, "1.2"},
+		tSpace,
+		tPipe,
+		{itemIdentifier, 0, "noargs"},
+		tPipe,
+		{itemIdentifier, 0, "args"},
+		tSpace,
+		{itemNumber, 0, "1"},
+		tSpace,
+		{itemString, 0, `"hi"`},
+		tRight,
+		{itemText, 0, " outro"},
+		tEOF,
+	}},
+	{"declaration", "{{$v := 3}}", []item{
+		tLeft,
+		{itemVariable, 0, "$v"},
+		tSpace,
+		{itemColonEquals, 0, ":="},
+		tSpace,
+		{itemNumber, 0, "3"},
+		tRight,
+		tEOF,
+	}},
+	{"2 declarations", "{{$v , $w := 3}}", []item{
+		tLeft,
+		{itemVariable, 0, "$v"},
+		tSpace,
+		{itemChar, 0, ","},
+		tSpace,
+		{itemVariable, 0, "$w"},
+		tSpace,
+		{itemColonEquals, 0, ":="},
+		tSpace,
+		{itemNumber, 0, "3"},
+		tRight,
+		tEOF,
+	}},
+	{"field of parenthesized expression", "{{(.X).Y}}", []item{
+		tLeft,
+		tLpar,
+		{itemField, 0, ".X"},
+		tRpar,
+		{itemField, 0, ".Y"},
+		tRight,
+		tEOF,
+	}},
+	// errors
+	{"badchar", "#{{\x01}}", []item{
+		{itemText, 0, "#"},
+		tLeft,
+		{itemError, 0, "unrecognized character in action: U+0001"},
+	}},
+	{"unclosed action", "{{\n}}", []item{
+		tLeft,
+		{itemError, 0, "unclosed action"},
+	}},
+	{"EOF in action", "{{range", []item{
+		tLeft,
+		tRange,
+		{itemError, 0, "unclosed action"},
+	}},
+	{"unclosed quote", "{{\"\n\"}}", []item{
+		tLeft,
+		{itemError, 0, "unterminated quoted string"},
+	}},
+	{"unclosed raw quote", "{{`xx\n`}}", []item{
+		tLeft,
+		{itemError, 0, "unterminated raw quoted string"},
+	}},
+	{"unclosed char constant", "{{'\n}}", []item{
+		tLeft,
+		{itemError, 0, "unterminated character constant"},
+	}},
+	{"bad number", "{{3k}}", []item{
+		tLeft,
+		{itemError, 0, `bad number syntax: "3k"`},
+	}},
+	{"unclosed paren", "{{(3}}", []item{
+		tLeft,
+		tLpar,
+		{itemNumber, 0, "3"},
+		{itemError, 0, `unclosed left paren`},
+	}},
+	{"extra right paren", "{{3)}}", []item{
+		tLeft,
+		{itemNumber, 0, "3"},
+		tRpar,
+		{itemError, 0, `unexpected right paren U+0029 ')'`},
+	}},
+
+	// Fixed bugs
+	// Many elements in an action blew the lookahead until
+	// we made lexInsideAction not loop.
+	{"long pipeline deadlock", "{{|||||}}", []item{
+		tLeft,
+		tPipe,
+		tPipe,
+		tPipe,
+		tPipe,
+		tPipe,
+		tRight,
+		tEOF,
+	}},
+	{"text with bad comment", "hello-{{/*/}}-world", []item{
+		{itemText, 0, "hello-"},
+		{itemError, 0, `unclosed comment`},
+	}},
+	{"text with comment close separted from delim", "hello-{{/* */ }}-world", []item{
+		{itemText, 0, "hello-"},
+		{itemError, 0, `comment ends before closing delimiter`},
+	}},
+	// This one is an error that we can't catch because it breaks templates with
+	// minimized JavaScript. Should have fixed it before Go 1.1.
+	{"unmatched right delimiter", "hello-{.}}-world", []item{
+		{itemText, 0, "hello-{.}}-world"},
+		tEOF,
+	}},
+}
+
+// collect gathers the emitted items into a slice.
+func collect(t *lexTest, left, right string) (items []item) {
+	l := lex(t.name, t.input, left, right)
+	for {
+		item := l.nextItem()
+		items = append(items, item)
+		if item.typ == itemEOF || item.typ == itemError {
+			break
+		}
+	}
+	return
+}
+
+func equal(i1, i2 []item, checkPos bool) bool {
+	if len(i1) != len(i2) {
+		return false
+	}
+	for k := range i1 {
+		if i1[k].typ != i2[k].typ {
+			return false
+		}
+		if i1[k].val != i2[k].val {
+			return false
+		}
+		if checkPos && i1[k].pos != i2[k].pos {
+			return false
+		}
+	}
+	return true
+}
+
+func TestLex(t *testing.T) {
+	for _, test := range lexTests {
+		items := collect(&test, "", "")
+		if !equal(items, test.items, false) {
+			t.Errorf("%s: got\n\t%+v\nexpected\n\t%v", test.name, items, test.items)
+		}
+	}
+}
+
+// Some easy cases from above, but with delimiters $$ and @@
+var lexDelimTests = []lexTest{
+	{"punctuation", "$$,@%{{}}@@", []item{
+		tLeftDelim,
+		{itemChar, 0, ","},
+		{itemChar, 0, "@"},
+		{itemChar, 0, "%"},
+		{itemChar, 0, "{"},
+		{itemChar, 0, "{"},
+		{itemChar, 0, "}"},
+		{itemChar, 0, "}"},
+		tRightDelim,
+		tEOF,
+	}},
+	{"empty action", `$$@@`, []item{tLeftDelim, tRightDelim, tEOF}},
+	{"for", `$$for@@`, []item{tLeftDelim, tFor, tRightDelim, tEOF}},
+	{"quote", `$$"abc \n\t\" "@@`, []item{tLeftDelim, tQuote, tRightDelim, tEOF}},
+	{"raw quote", "$$" + raw + "@@", []item{tLeftDelim, tRawQuote, tRightDelim, tEOF}},
+}
+
+var (
+	tLeftDelim  = item{itemLeftDelim, 0, "$$"}
+	tRightDelim = item{itemRightDelim, 0, "@@"}
+)
+
+func TestDelims(t *testing.T) {
+	for _, test := range lexDelimTests {
+		items := collect(&test, "$$", "@@")
+		if !equal(items, test.items, false) {
+			t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+		}
+	}
+}
+
+var lexPosTests = []lexTest{
+	{"empty", "", []item{tEOF}},
+	{"punctuation", "{{,@%#}}", []item{
+		{itemLeftDelim, 0, "{{"},
+		{itemChar, 2, ","},
+		{itemChar, 3, "@"},
+		{itemChar, 4, "%"},
+		{itemChar, 5, "#"},
+		{itemRightDelim, 6, "}}"},
+		{itemEOF, 8, ""},
+	}},
+	{"sample", "0123{{hello}}xyz", []item{
+		{itemText, 0, "0123"},
+		{itemLeftDelim, 4, "{{"},
+		{itemIdentifier, 6, "hello"},
+		{itemRightDelim, 11, "}}"},
+		{itemText, 13, "xyz"},
+		{itemEOF, 16, ""},
+	}},
+}
+
+// The other tests don't check position, to make the test cases easier to construct.
+// This one does.
+func TestPos(t *testing.T) {
+	for _, test := range lexPosTests {
+		items := collect(&test, "", "")
+		if !equal(items, test.items, true) {
+			t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+			if len(items) == len(test.items) {
+				// Detailed print; avoid item.String() to expose the position value.
+				for i := range items {
+					if !equal(items[i:i+1], test.items[i:i+1], true) {
+						i1 := items[i]
+						i2 := test.items[i]
+						t.Errorf("\t#%d: got {%v %d %q} expected  {%v %d %q}", i, i1.typ, i1.pos, i1.val, i2.typ, i2.pos, i2.val)
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/parse/node.go b/third_party/gofrontend/libgo/go/text/template/parse/node.go
new file mode 100644
index 0000000..dc6a3bb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/parse/node.go
@@ -0,0 +1,722 @@
+// 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.
+
+// Parse nodes.
+
+package parse
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+var textFormat = "%s" // Changed to "%q" in tests for better error messages.
+
+// A Node is an element in the parse tree. The interface is trivial.
+// The interface contains an unexported method so that only
+// types local to this package can satisfy it.
+type Node interface {
+	Type() NodeType
+	String() string
+	// Copy does a deep copy of the Node and all its components.
+	// To avoid type assertions, some XxxNodes also have specialized
+	// CopyXxx methods that return *XxxNode.
+	Copy() Node
+	Position() Pos // byte position of start of node in full original input string
+	// Make sure only functions in this package can create Nodes.
+	unexported()
+}
+
+// NodeType identifies the type of a parse tree node.
+type NodeType int
+
+// Pos represents a byte position in the original input text from which
+// this template was parsed.
+type Pos int
+
+func (p Pos) Position() Pos {
+	return p
+}
+
+// unexported keeps Node implementations local to the package.
+// All implementations embed Pos, so this takes care of it.
+func (Pos) unexported() {
+}
+
+// Type returns itself and provides an easy default implementation
+// for embedding in a Node. Embedded in all non-trivial Nodes.
+func (t NodeType) Type() NodeType {
+	return t
+}
+
+const (
+	NodeText       NodeType = iota // Plain text.
+	NodeAction                     // A non-control action such as a field evaluation.
+	NodeBool                       // A boolean constant.
+	NodeChain                      // A sequence of field accesses.
+	NodeCommand                    // An element of a pipeline.
+	NodeDot                        // The cursor, dot.
+	nodeElse                       // An else action. Not added to tree.
+	nodeEnd                        // An end action. Not added to tree.
+	NodeField                      // A field or method name.
+	NodeIdentifier                 // An identifier; always a function name.
+	NodeIf                         // An if action.
+	NodeList                       // A list of Nodes.
+	NodeNil                        // An untyped nil constant.
+	NodeNumber                     // A numerical constant.
+	NodePipe                       // A pipeline of commands.
+	NodeRange                      // A range action.
+	NodeString                     // A string constant.
+	NodeTemplate                   // A template invocation action.
+	NodeVariable                   // A $ variable.
+	NodeWith                       // A with action.
+)
+
+// Nodes.
+
+// ListNode holds a sequence of nodes.
+type ListNode struct {
+	NodeType
+	Pos
+	Nodes []Node // The element nodes in lexical order.
+}
+
+func newList(pos Pos) *ListNode {
+	return &ListNode{NodeType: NodeList, Pos: pos}
+}
+
+func (l *ListNode) append(n Node) {
+	l.Nodes = append(l.Nodes, n)
+}
+
+func (l *ListNode) String() string {
+	b := new(bytes.Buffer)
+	for _, n := range l.Nodes {
+		fmt.Fprint(b, n)
+	}
+	return b.String()
+}
+
+func (l *ListNode) CopyList() *ListNode {
+	if l == nil {
+		return l
+	}
+	n := newList(l.Pos)
+	for _, elem := range l.Nodes {
+		n.append(elem.Copy())
+	}
+	return n
+}
+
+func (l *ListNode) Copy() Node {
+	return l.CopyList()
+}
+
+// TextNode holds plain text.
+type TextNode struct {
+	NodeType
+	Pos
+	Text []byte // The text; may span newlines.
+}
+
+func newText(pos Pos, text string) *TextNode {
+	return &TextNode{NodeType: NodeText, Pos: pos, Text: []byte(text)}
+}
+
+func (t *TextNode) String() string {
+	return fmt.Sprintf(textFormat, t.Text)
+}
+
+func (t *TextNode) Copy() Node {
+	return &TextNode{NodeType: NodeText, Text: append([]byte{}, t.Text...)}
+}
+
+// PipeNode holds a pipeline with optional declaration
+type PipeNode struct {
+	NodeType
+	Pos
+	Line int             // The line number in the input (deprecated; kept for compatibility)
+	Decl []*VariableNode // Variable declarations in lexical order.
+	Cmds []*CommandNode  // The commands in lexical order.
+}
+
+func newPipeline(pos Pos, line int, decl []*VariableNode) *PipeNode {
+	return &PipeNode{NodeType: NodePipe, Pos: pos, Line: line, Decl: decl}
+}
+
+func (p *PipeNode) append(command *CommandNode) {
+	p.Cmds = append(p.Cmds, command)
+}
+
+func (p *PipeNode) String() string {
+	s := ""
+	if len(p.Decl) > 0 {
+		for i, v := range p.Decl {
+			if i > 0 {
+				s += ", "
+			}
+			s += v.String()
+		}
+		s += " := "
+	}
+	for i, c := range p.Cmds {
+		if i > 0 {
+			s += " | "
+		}
+		s += c.String()
+	}
+	return s
+}
+
+func (p *PipeNode) CopyPipe() *PipeNode {
+	if p == nil {
+		return p
+	}
+	var decl []*VariableNode
+	for _, d := range p.Decl {
+		decl = append(decl, d.Copy().(*VariableNode))
+	}
+	n := newPipeline(p.Pos, p.Line, decl)
+	for _, c := range p.Cmds {
+		n.append(c.Copy().(*CommandNode))
+	}
+	return n
+}
+
+func (p *PipeNode) Copy() Node {
+	return p.CopyPipe()
+}
+
+// ActionNode holds an action (something bounded by delimiters).
+// Control actions have their own nodes; ActionNode represents simple
+// ones such as field evaluations and parenthesized pipelines.
+type ActionNode struct {
+	NodeType
+	Pos
+	Line int       // The line number in the input (deprecated; kept for compatibility)
+	Pipe *PipeNode // The pipeline in the action.
+}
+
+func newAction(pos Pos, line int, pipe *PipeNode) *ActionNode {
+	return &ActionNode{NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe}
+}
+
+func (a *ActionNode) String() string {
+	return fmt.Sprintf("{{%s}}", a.Pipe)
+
+}
+
+func (a *ActionNode) Copy() Node {
+	return newAction(a.Pos, a.Line, a.Pipe.CopyPipe())
+
+}
+
+// CommandNode holds a command (a pipeline inside an evaluating action).
+type CommandNode struct {
+	NodeType
+	Pos
+	Args []Node // Arguments in lexical order: Identifier, field, or constant.
+}
+
+func newCommand(pos Pos) *CommandNode {
+	return &CommandNode{NodeType: NodeCommand, Pos: pos}
+}
+
+func (c *CommandNode) append(arg Node) {
+	c.Args = append(c.Args, arg)
+}
+
+func (c *CommandNode) String() string {
+	s := ""
+	for i, arg := range c.Args {
+		if i > 0 {
+			s += " "
+		}
+		if arg, ok := arg.(*PipeNode); ok {
+			s += "(" + arg.String() + ")"
+			continue
+		}
+		s += arg.String()
+	}
+	return s
+}
+
+func (c *CommandNode) Copy() Node {
+	if c == nil {
+		return c
+	}
+	n := newCommand(c.Pos)
+	for _, c := range c.Args {
+		n.append(c.Copy())
+	}
+	return n
+}
+
+// IdentifierNode holds an identifier.
+type IdentifierNode struct {
+	NodeType
+	Pos
+	Ident string // The identifier's name.
+}
+
+// NewIdentifier returns a new IdentifierNode with the given identifier name.
+func NewIdentifier(ident string) *IdentifierNode {
+	return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident}
+}
+
+// SetPos sets the position. NewIdentifier is a public method so we can't modify its signature.
+// Chained for convenience.
+// TODO: fix one day?
+func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode {
+	i.Pos = pos
+	return i
+}
+
+func (i *IdentifierNode) String() string {
+	return i.Ident
+}
+
+func (i *IdentifierNode) Copy() Node {
+	return NewIdentifier(i.Ident).SetPos(i.Pos)
+}
+
+// VariableNode holds a list of variable names, possibly with chained field
+// accesses. The dollar sign is part of the (first) name.
+type VariableNode struct {
+	NodeType
+	Pos
+	Ident []string // Variable name and fields in lexical order.
+}
+
+func newVariable(pos Pos, ident string) *VariableNode {
+	return &VariableNode{NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")}
+}
+
+func (v *VariableNode) String() string {
+	s := ""
+	for i, id := range v.Ident {
+		if i > 0 {
+			s += "."
+		}
+		s += id
+	}
+	return s
+}
+
+func (v *VariableNode) Copy() Node {
+	return &VariableNode{NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)}
+}
+
+// DotNode holds the special identifier '.'.
+type DotNode struct {
+	Pos
+}
+
+func newDot(pos Pos) *DotNode {
+	return &DotNode{Pos: pos}
+}
+
+func (d *DotNode) Type() NodeType {
+	return NodeDot
+}
+
+func (d *DotNode) String() string {
+	return "."
+}
+
+func (d *DotNode) Copy() Node {
+	return newDot(d.Pos)
+}
+
+// NilNode holds the special identifier 'nil' representing an untyped nil constant.
+type NilNode struct {
+	Pos
+}
+
+func newNil(pos Pos) *NilNode {
+	return &NilNode{Pos: pos}
+}
+
+func (n *NilNode) Type() NodeType {
+	return NodeNil
+}
+
+func (n *NilNode) String() string {
+	return "nil"
+}
+
+func (n *NilNode) Copy() Node {
+	return newNil(n.Pos)
+}
+
+// FieldNode holds a field (identifier starting with '.').
+// The names may be chained ('.x.y').
+// The period is dropped from each ident.
+type FieldNode struct {
+	NodeType
+	Pos
+	Ident []string // The identifiers in lexical order.
+}
+
+func newField(pos Pos, ident string) *FieldNode {
+	return &FieldNode{NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
+}
+
+func (f *FieldNode) String() string {
+	s := ""
+	for _, id := range f.Ident {
+		s += "." + id
+	}
+	return s
+}
+
+func (f *FieldNode) Copy() Node {
+	return &FieldNode{NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)}
+}
+
+// ChainNode holds a term followed by a chain of field accesses (identifier starting with '.').
+// The names may be chained ('.x.y').
+// The periods are dropped from each ident.
+type ChainNode struct {
+	NodeType
+	Pos
+	Node  Node
+	Field []string // The identifiers in lexical order.
+}
+
+func newChain(pos Pos, node Node) *ChainNode {
+	return &ChainNode{NodeType: NodeChain, Pos: pos, Node: node}
+}
+
+// Add adds the named field (which should start with a period) to the end of the chain.
+func (c *ChainNode) Add(field string) {
+	if len(field) == 0 || field[0] != '.' {
+		panic("no dot in field")
+	}
+	field = field[1:] // Remove leading dot.
+	if field == "" {
+		panic("empty field")
+	}
+	c.Field = append(c.Field, field)
+}
+
+func (c *ChainNode) String() string {
+	s := c.Node.String()
+	if _, ok := c.Node.(*PipeNode); ok {
+		s = "(" + s + ")"
+	}
+	for _, field := range c.Field {
+		s += "." + field
+	}
+	return s
+}
+
+func (c *ChainNode) Copy() Node {
+	return &ChainNode{NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)}
+}
+
+// BoolNode holds a boolean constant.
+type BoolNode struct {
+	NodeType
+	Pos
+	True bool // The value of the boolean constant.
+}
+
+func newBool(pos Pos, true bool) *BoolNode {
+	return &BoolNode{NodeType: NodeBool, Pos: pos, True: true}
+}
+
+func (b *BoolNode) String() string {
+	if b.True {
+		return "true"
+	}
+	return "false"
+}
+
+func (b *BoolNode) Copy() Node {
+	return newBool(b.Pos, b.True)
+}
+
+// NumberNode holds a number: signed or unsigned integer, float, or complex.
+// The value is parsed and stored under all the types that can represent the value.
+// This simulates in a small amount of code the behavior of Go's ideal constants.
+type NumberNode struct {
+	NodeType
+	Pos
+	IsInt      bool       // Number has an integral value.
+	IsUint     bool       // Number has an unsigned integral value.
+	IsFloat    bool       // Number has a floating-point value.
+	IsComplex  bool       // Number is complex.
+	Int64      int64      // The signed integer value.
+	Uint64     uint64     // The unsigned integer value.
+	Float64    float64    // The floating-point value.
+	Complex128 complex128 // The complex value.
+	Text       string     // The original textual representation from the input.
+}
+
+func newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) {
+	n := &NumberNode{NodeType: NodeNumber, Pos: pos, Text: text}
+	switch typ {
+	case itemCharConstant:
+		rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
+		if err != nil {
+			return nil, err
+		}
+		if tail != "'" {
+			return nil, fmt.Errorf("malformed character constant: %s", text)
+		}
+		n.Int64 = int64(rune)
+		n.IsInt = true
+		n.Uint64 = uint64(rune)
+		n.IsUint = true
+		n.Float64 = float64(rune) // odd but those are the rules.
+		n.IsFloat = true
+		return n, nil
+	case itemComplex:
+		// fmt.Sscan can parse the pair, so let it do the work.
+		if _, err := fmt.Sscan(text, &n.Complex128); err != nil {
+			return nil, err
+		}
+		n.IsComplex = true
+		n.simplifyComplex()
+		return n, nil
+	}
+	// Imaginary constants can only be complex unless they are zero.
+	if len(text) > 0 && text[len(text)-1] == 'i' {
+		f, err := strconv.ParseFloat(text[:len(text)-1], 64)
+		if err == nil {
+			n.IsComplex = true
+			n.Complex128 = complex(0, f)
+			n.simplifyComplex()
+			return n, nil
+		}
+	}
+	// Do integer test first so we get 0x123 etc.
+	u, err := strconv.ParseUint(text, 0, 64) // will fail for -0; fixed below.
+	if err == nil {
+		n.IsUint = true
+		n.Uint64 = u
+	}
+	i, err := strconv.ParseInt(text, 0, 64)
+	if err == nil {
+		n.IsInt = true
+		n.Int64 = i
+		if i == 0 {
+			n.IsUint = true // in case of -0.
+			n.Uint64 = u
+		}
+	}
+	// If an integer extraction succeeded, promote the float.
+	if n.IsInt {
+		n.IsFloat = true
+		n.Float64 = float64(n.Int64)
+	} else if n.IsUint {
+		n.IsFloat = true
+		n.Float64 = float64(n.Uint64)
+	} else {
+		f, err := strconv.ParseFloat(text, 64)
+		if err == nil {
+			n.IsFloat = true
+			n.Float64 = f
+			// If a floating-point extraction succeeded, extract the int if needed.
+			if !n.IsInt && float64(int64(f)) == f {
+				n.IsInt = true
+				n.Int64 = int64(f)
+			}
+			if !n.IsUint && float64(uint64(f)) == f {
+				n.IsUint = true
+				n.Uint64 = uint64(f)
+			}
+		}
+	}
+	if !n.IsInt && !n.IsUint && !n.IsFloat {
+		return nil, fmt.Errorf("illegal number syntax: %q", text)
+	}
+	return n, nil
+}
+
+// simplifyComplex pulls out any other types that are represented by the complex number.
+// These all require that the imaginary part be zero.
+func (n *NumberNode) simplifyComplex() {
+	n.IsFloat = imag(n.Complex128) == 0
+	if n.IsFloat {
+		n.Float64 = real(n.Complex128)
+		n.IsInt = float64(int64(n.Float64)) == n.Float64
+		if n.IsInt {
+			n.Int64 = int64(n.Float64)
+		}
+		n.IsUint = float64(uint64(n.Float64)) == n.Float64
+		if n.IsUint {
+			n.Uint64 = uint64(n.Float64)
+		}
+	}
+}
+
+func (n *NumberNode) String() string {
+	return n.Text
+}
+
+func (n *NumberNode) Copy() Node {
+	nn := new(NumberNode)
+	*nn = *n // Easy, fast, correct.
+	return nn
+}
+
+// StringNode holds a string constant. The value has been "unquoted".
+type StringNode struct {
+	NodeType
+	Pos
+	Quoted string // The original text of the string, with quotes.
+	Text   string // The string, after quote processing.
+}
+
+func newString(pos Pos, orig, text string) *StringNode {
+	return &StringNode{NodeType: NodeString, Pos: pos, Quoted: orig, Text: text}
+}
+
+func (s *StringNode) String() string {
+	return s.Quoted
+}
+
+func (s *StringNode) Copy() Node {
+	return newString(s.Pos, s.Quoted, s.Text)
+}
+
+// endNode represents an {{end}} action.
+// It does not appear in the final parse tree.
+type endNode struct {
+	Pos
+}
+
+func newEnd(pos Pos) *endNode {
+	return &endNode{Pos: pos}
+}
+
+func (e *endNode) Type() NodeType {
+	return nodeEnd
+}
+
+func (e *endNode) String() string {
+	return "{{end}}"
+}
+
+func (e *endNode) Copy() Node {
+	return newEnd(e.Pos)
+}
+
+// elseNode represents an {{else}} action. Does not appear in the final tree.
+type elseNode struct {
+	NodeType
+	Pos
+	Line int // The line number in the input (deprecated; kept for compatibility)
+}
+
+func newElse(pos Pos, line int) *elseNode {
+	return &elseNode{NodeType: nodeElse, Pos: pos, Line: line}
+}
+
+func (e *elseNode) Type() NodeType {
+	return nodeElse
+}
+
+func (e *elseNode) String() string {
+	return "{{else}}"
+}
+
+func (e *elseNode) Copy() Node {
+	return newElse(e.Pos, e.Line)
+}
+
+// BranchNode is the common representation of if, range, and with.
+type BranchNode struct {
+	NodeType
+	Pos
+	Line     int       // The line number in the input (deprecated; kept for compatibility)
+	Pipe     *PipeNode // The pipeline to be evaluated.
+	List     *ListNode // What to execute if the value is non-empty.
+	ElseList *ListNode // What to execute if the value is empty (nil if absent).
+}
+
+func (b *BranchNode) String() string {
+	name := ""
+	switch b.NodeType {
+	case NodeIf:
+		name = "if"
+	case NodeRange:
+		name = "range"
+	case NodeWith:
+		name = "with"
+	default:
+		panic("unknown branch type")
+	}
+	if b.ElseList != nil {
+		return fmt.Sprintf("{{%s %s}}%s{{else}}%s{{end}}", name, b.Pipe, b.List, b.ElseList)
+	}
+	return fmt.Sprintf("{{%s %s}}%s{{end}}", name, b.Pipe, b.List)
+}
+
+// IfNode represents an {{if}} action and its commands.
+type IfNode struct {
+	BranchNode
+}
+
+func newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
+	return &IfNode{BranchNode{NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+func (i *IfNode) Copy() Node {
+	return newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
+}
+
+// RangeNode represents a {{range}} action and its commands.
+type RangeNode struct {
+	BranchNode
+}
+
+func newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
+	return &RangeNode{BranchNode{NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+func (r *RangeNode) Copy() Node {
+	return newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
+}
+
+// WithNode represents a {{with}} action and its commands.
+type WithNode struct {
+	BranchNode
+}
+
+func newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
+	return &WithNode{BranchNode{NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+func (w *WithNode) Copy() Node {
+	return newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
+}
+
+// TemplateNode represents a {{template}} action.
+type TemplateNode struct {
+	NodeType
+	Pos
+	Line int       // The line number in the input (deprecated; kept for compatibility)
+	Name string    // The name of the template (unquoted).
+	Pipe *PipeNode // The command to evaluate as dot for the template.
+}
+
+func newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode {
+	return &TemplateNode{NodeType: NodeTemplate, Line: line, Pos: pos, Name: name, Pipe: pipe}
+}
+
+func (t *TemplateNode) String() string {
+	if t.Pipe == nil {
+		return fmt.Sprintf("{{template %q}}", t.Name)
+	}
+	return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe)
+}
+
+func (t *TemplateNode) Copy() Node {
+	return newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe())
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/parse/parse.go b/third_party/gofrontend/libgo/go/text/template/parse/parse.go
new file mode 100644
index 0000000..34112fb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/parse/parse.go
@@ -0,0 +1,671 @@
+// 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.
+
+// Package parse builds parse trees for templates as defined by text/template
+// and html/template. Clients should use those packages to construct templates
+// rather than this one, which provides shared internal data structures not
+// intended for general use.
+package parse
+
+import (
+	"bytes"
+	"fmt"
+	"runtime"
+	"strconv"
+	"strings"
+)
+
+// Tree is the representation of a single parsed template.
+type Tree struct {
+	Name      string    // name of the template represented by the tree.
+	ParseName string    // name of the top-level template during parsing, for error messages.
+	Root      *ListNode // top-level root of the tree.
+	text      string    // text parsed to create the template (or its parent)
+	// Parsing only; cleared after parse.
+	funcs     []map[string]interface{}
+	lex       *lexer
+	token     [3]item // three-token lookahead for parser.
+	peekCount int
+	vars      []string // variables defined at the moment.
+}
+
+// Copy returns a copy of the Tree. Any parsing state is discarded.
+func (t *Tree) Copy() *Tree {
+	if t == nil {
+		return nil
+	}
+	return &Tree{
+		Name:      t.Name,
+		ParseName: t.ParseName,
+		Root:      t.Root.CopyList(),
+		text:      t.text,
+	}
+}
+
+// Parse returns a map from template name to parse.Tree, created by parsing the
+// templates described in the argument string. The top-level template will be
+// given the specified name. If an error is encountered, parsing stops and an
+// empty map is returned with the error.
+func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (treeSet map[string]*Tree, err error) {
+	treeSet = make(map[string]*Tree)
+	t := New(name)
+	t.text = text
+	_, err = t.Parse(text, leftDelim, rightDelim, treeSet, funcs...)
+	return
+}
+
+// next returns the next token.
+func (t *Tree) next() item {
+	if t.peekCount > 0 {
+		t.peekCount--
+	} else {
+		t.token[0] = t.lex.nextItem()
+	}
+	return t.token[t.peekCount]
+}
+
+// backup backs the input stream up one token.
+func (t *Tree) backup() {
+	t.peekCount++
+}
+
+// backup2 backs the input stream up two tokens.
+// The zeroth token is already there.
+func (t *Tree) backup2(t1 item) {
+	t.token[1] = t1
+	t.peekCount = 2
+}
+
+// backup3 backs the input stream up three tokens
+// The zeroth token is already there.
+func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back.
+	t.token[1] = t1
+	t.token[2] = t2
+	t.peekCount = 3
+}
+
+// peek returns but does not consume the next token.
+func (t *Tree) peek() item {
+	if t.peekCount > 0 {
+		return t.token[t.peekCount-1]
+	}
+	t.peekCount = 1
+	t.token[0] = t.lex.nextItem()
+	return t.token[0]
+}
+
+// nextNonSpace returns the next non-space token.
+func (t *Tree) nextNonSpace() (token item) {
+	for {
+		token = t.next()
+		if token.typ != itemSpace {
+			break
+		}
+	}
+	return token
+}
+
+// peekNonSpace returns but does not consume the next non-space token.
+func (t *Tree) peekNonSpace() (token item) {
+	for {
+		token = t.next()
+		if token.typ != itemSpace {
+			break
+		}
+	}
+	t.backup()
+	return token
+}
+
+// Parsing.
+
+// New allocates a new parse tree with the given name.
+func New(name string, funcs ...map[string]interface{}) *Tree {
+	return &Tree{
+		Name:  name,
+		funcs: funcs,
+	}
+}
+
+// ErrorContext returns a textual representation of the location of the node in the input text.
+func (t *Tree) ErrorContext(n Node) (location, context string) {
+	pos := int(n.Position())
+	text := t.text[:pos]
+	byteNum := strings.LastIndex(text, "\n")
+	if byteNum == -1 {
+		byteNum = pos // On first line.
+	} else {
+		byteNum++ // After the newline.
+		byteNum = pos - byteNum
+	}
+	lineNum := 1 + strings.Count(text, "\n")
+	context = n.String()
+	if len(context) > 20 {
+		context = fmt.Sprintf("%.20s...", context)
+	}
+	return fmt.Sprintf("%s:%d:%d", t.ParseName, lineNum, byteNum), context
+}
+
+// errorf formats the error and terminates processing.
+func (t *Tree) errorf(format string, args ...interface{}) {
+	t.Root = nil
+	format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.lex.lineNumber(), format)
+	panic(fmt.Errorf(format, args...))
+}
+
+// error terminates processing.
+func (t *Tree) error(err error) {
+	t.errorf("%s", err)
+}
+
+// expect consumes the next token and guarantees it has the required type.
+func (t *Tree) expect(expected itemType, context string) item {
+	token := t.nextNonSpace()
+	if token.typ != expected {
+		t.unexpected(token, context)
+	}
+	return token
+}
+
+// expectOneOf consumes the next token and guarantees it has one of the required types.
+func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
+	token := t.nextNonSpace()
+	if token.typ != expected1 && token.typ != expected2 {
+		t.unexpected(token, context)
+	}
+	return token
+}
+
+// unexpected complains about the token and terminates processing.
+func (t *Tree) unexpected(token item, context string) {
+	t.errorf("unexpected %s in %s", token, context)
+}
+
+// recover is the handler that turns panics into returns from the top level of Parse.
+func (t *Tree) recover(errp *error) {
+	e := recover()
+	if e != nil {
+		if _, ok := e.(runtime.Error); ok {
+			panic(e)
+		}
+		if t != nil {
+			t.stopParse()
+		}
+		*errp = e.(error)
+	}
+	return
+}
+
+// startParse initializes the parser, using the lexer.
+func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer) {
+	t.Root = nil
+	t.lex = lex
+	t.vars = []string{"$"}
+	t.funcs = funcs
+}
+
+// stopParse terminates parsing.
+func (t *Tree) stopParse() {
+	t.lex = nil
+	t.vars = nil
+	t.funcs = nil
+}
+
+// Parse parses the template definition string to construct a representation of
+// the template for execution. If either action delimiter string is empty, the
+// default ("{{" or "}}") is used. Embedded template definitions are added to
+// the treeSet map.
+func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
+	defer t.recover(&err)
+	t.ParseName = t.Name
+	t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim))
+	t.text = text
+	t.parse(treeSet)
+	t.add(treeSet)
+	t.stopParse()
+	return t, nil
+}
+
+// add adds tree to the treeSet.
+func (t *Tree) add(treeSet map[string]*Tree) {
+	tree := treeSet[t.Name]
+	if tree == nil || IsEmptyTree(tree.Root) {
+		treeSet[t.Name] = t
+		return
+	}
+	if !IsEmptyTree(t.Root) {
+		t.errorf("template: multiple definition of template %q", t.Name)
+	}
+}
+
+// IsEmptyTree reports whether this tree (node) is empty of everything but space.
+func IsEmptyTree(n Node) bool {
+	switch n := n.(type) {
+	case nil:
+		return true
+	case *ActionNode:
+	case *IfNode:
+	case *ListNode:
+		for _, node := range n.Nodes {
+			if !IsEmptyTree(node) {
+				return false
+			}
+		}
+		return true
+	case *RangeNode:
+	case *TemplateNode:
+	case *TextNode:
+		return len(bytes.TrimSpace(n.Text)) == 0
+	case *WithNode:
+	default:
+		panic("unknown node: " + n.String())
+	}
+	return false
+}
+
+// parse is the top-level parser for a template, essentially the same
+// as itemList except it also parses {{define}} actions.
+// It runs to EOF.
+func (t *Tree) parse(treeSet map[string]*Tree) (next Node) {
+	t.Root = newList(t.peek().pos)
+	for t.peek().typ != itemEOF {
+		if t.peek().typ == itemLeftDelim {
+			delim := t.next()
+			if t.nextNonSpace().typ == itemDefine {
+				newT := New("definition") // name will be updated once we know it.
+				newT.text = t.text
+				newT.ParseName = t.ParseName
+				newT.startParse(t.funcs, t.lex)
+				newT.parseDefinition(treeSet)
+				continue
+			}
+			t.backup2(delim)
+		}
+		n := t.textOrAction()
+		if n.Type() == nodeEnd {
+			t.errorf("unexpected %s", n)
+		}
+		t.Root.append(n)
+	}
+	return nil
+}
+
+// parseDefinition parses a {{define}} ...  {{end}} template definition and
+// installs the definition in the treeSet map.  The "define" keyword has already
+// been scanned.
+func (t *Tree) parseDefinition(treeSet map[string]*Tree) {
+	const context = "define clause"
+	name := t.expectOneOf(itemString, itemRawString, context)
+	var err error
+	t.Name, err = strconv.Unquote(name.val)
+	if err != nil {
+		t.error(err)
+	}
+	t.expect(itemRightDelim, context)
+	var end Node
+	t.Root, end = t.itemList()
+	if end.Type() != nodeEnd {
+		t.errorf("unexpected %s in %s", end, context)
+	}
+	t.add(treeSet)
+	t.stopParse()
+}
+
+// itemList:
+//	textOrAction*
+// Terminates at {{end}} or {{else}}, returned separately.
+func (t *Tree) itemList() (list *ListNode, next Node) {
+	list = newList(t.peekNonSpace().pos)
+	for t.peekNonSpace().typ != itemEOF {
+		n := t.textOrAction()
+		switch n.Type() {
+		case nodeEnd, nodeElse:
+			return list, n
+		}
+		list.append(n)
+	}
+	t.errorf("unexpected EOF")
+	return
+}
+
+// textOrAction:
+//	text | action
+func (t *Tree) textOrAction() Node {
+	switch token := t.nextNonSpace(); token.typ {
+	case itemText:
+		return newText(token.pos, token.val)
+	case itemLeftDelim:
+		return t.action()
+	default:
+		t.unexpected(token, "input")
+	}
+	return nil
+}
+
+// Action:
+//	control
+//	command ("|" command)*
+// Left delim is past. Now get actions.
+// First word could be a keyword such as range.
+func (t *Tree) action() (n Node) {
+	switch token := t.nextNonSpace(); token.typ {
+	case itemElse:
+		return t.elseControl()
+	case itemEnd:
+		return t.endControl()
+	case itemIf:
+		return t.ifControl()
+	case itemRange:
+		return t.rangeControl()
+	case itemTemplate:
+		return t.templateControl()
+	case itemWith:
+		return t.withControl()
+	}
+	t.backup()
+	// Do not pop variables; they persist until "end".
+	return newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
+}
+
+// Pipeline:
+//	declarations? command ('|' command)*
+func (t *Tree) pipeline(context string) (pipe *PipeNode) {
+	var decl []*VariableNode
+	pos := t.peekNonSpace().pos
+	// Are there declarations?
+	for {
+		if v := t.peekNonSpace(); v.typ == itemVariable {
+			t.next()
+			// Since space is a token, we need 3-token look-ahead here in the worst case:
+			// in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an
+			// argument variable rather than a declaration. So remember the token
+			// adjacent to the variable so we can push it back if necessary.
+			tokenAfterVariable := t.peek()
+			if next := t.peekNonSpace(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
+				t.nextNonSpace()
+				variable := newVariable(v.pos, v.val)
+				decl = append(decl, variable)
+				t.vars = append(t.vars, v.val)
+				if next.typ == itemChar && next.val == "," {
+					if context == "range" && len(decl) < 2 {
+						continue
+					}
+					t.errorf("too many declarations in %s", context)
+				}
+			} else if tokenAfterVariable.typ == itemSpace {
+				t.backup3(v, tokenAfterVariable)
+			} else {
+				t.backup2(v)
+			}
+		}
+		break
+	}
+	pipe = newPipeline(pos, t.lex.lineNumber(), decl)
+	for {
+		switch token := t.nextNonSpace(); token.typ {
+		case itemRightDelim, itemRightParen:
+			if len(pipe.Cmds) == 0 {
+				t.errorf("missing value for %s", context)
+			}
+			if token.typ == itemRightParen {
+				t.backup()
+			}
+			return
+		case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
+			itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen:
+			t.backup()
+			pipe.append(t.command())
+		default:
+			t.unexpected(token, context)
+		}
+	}
+}
+
+func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
+	defer t.popVars(len(t.vars))
+	line = t.lex.lineNumber()
+	pipe = t.pipeline(context)
+	var next Node
+	list, next = t.itemList()
+	switch next.Type() {
+	case nodeEnd: //done
+	case nodeElse:
+		if allowElseIf {
+			// Special case for "else if". If the "else" is followed immediately by an "if",
+			// the elseControl will have left the "if" token pending. Treat
+			//	{{if a}}_{{else if b}}_{{end}}
+			// as
+			//	{{if a}}_{{else}}{{if b}}_{{end}}{{end}}.
+			// To do this, parse the if as usual and stop at it {{end}}; the subsequent{{end}}
+			// is assumed. This technique works even for long if-else-if chains.
+			// TODO: Should we allow else-if in with and range?
+			if t.peek().typ == itemIf {
+				t.next() // Consume the "if" token.
+				elseList = newList(next.Position())
+				elseList.append(t.ifControl())
+				// Do not consume the next item - only one {{end}} required.
+				break
+			}
+		}
+		elseList, next = t.itemList()
+		if next.Type() != nodeEnd {
+			t.errorf("expected end; found %s", next)
+		}
+	}
+	return pipe.Position(), line, pipe, list, elseList
+}
+
+// If:
+//	{{if pipeline}} itemList {{end}}
+//	{{if pipeline}} itemList {{else}} itemList {{end}}
+// If keyword is past.
+func (t *Tree) ifControl() Node {
+	return newIf(t.parseControl(true, "if"))
+}
+
+// Range:
+//	{{range pipeline}} itemList {{end}}
+//	{{range pipeline}} itemList {{else}} itemList {{end}}
+// Range keyword is past.
+func (t *Tree) rangeControl() Node {
+	return newRange(t.parseControl(false, "range"))
+}
+
+// With:
+//	{{with pipeline}} itemList {{end}}
+//	{{with pipeline}} itemList {{else}} itemList {{end}}
+// If keyword is past.
+func (t *Tree) withControl() Node {
+	return newWith(t.parseControl(false, "with"))
+}
+
+// End:
+//	{{end}}
+// End keyword is past.
+func (t *Tree) endControl() Node {
+	return newEnd(t.expect(itemRightDelim, "end").pos)
+}
+
+// Else:
+//	{{else}}
+// Else keyword is past.
+func (t *Tree) elseControl() Node {
+	// Special case for "else if".
+	peek := t.peekNonSpace()
+	if peek.typ == itemIf {
+		// We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ".
+		return newElse(peek.pos, t.lex.lineNumber())
+	}
+	return newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
+}
+
+// Template:
+//	{{template stringValue pipeline}}
+// Template keyword is past.  The name must be something that can evaluate
+// to a string.
+func (t *Tree) templateControl() Node {
+	var name string
+	token := t.nextNonSpace()
+	switch token.typ {
+	case itemString, itemRawString:
+		s, err := strconv.Unquote(token.val)
+		if err != nil {
+			t.error(err)
+		}
+		name = s
+	default:
+		t.unexpected(token, "template invocation")
+	}
+	var pipe *PipeNode
+	if t.nextNonSpace().typ != itemRightDelim {
+		t.backup()
+		// Do not pop variables; they persist until "end".
+		pipe = t.pipeline("template")
+	}
+	return newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
+}
+
+// command:
+//	operand (space operand)*
+// space-separated arguments up to a pipeline character or right delimiter.
+// we consume the pipe character but leave the right delim to terminate the action.
+func (t *Tree) command() *CommandNode {
+	cmd := newCommand(t.peekNonSpace().pos)
+	for {
+		t.peekNonSpace() // skip leading spaces.
+		operand := t.operand()
+		if operand != nil {
+			cmd.append(operand)
+		}
+		switch token := t.next(); token.typ {
+		case itemSpace:
+			continue
+		case itemError:
+			t.errorf("%s", token.val)
+		case itemRightDelim, itemRightParen:
+			t.backup()
+		case itemPipe:
+		default:
+			t.errorf("unexpected %s in operand; missing space?", token)
+		}
+		break
+	}
+	if len(cmd.Args) == 0 {
+		t.errorf("empty command")
+	}
+	return cmd
+}
+
+// operand:
+//	term .Field*
+// An operand is a space-separated component of a command,
+// a term possibly followed by field accesses.
+// A nil return means the next item is not an operand.
+func (t *Tree) operand() Node {
+	node := t.term()
+	if node == nil {
+		return nil
+	}
+	if t.peek().typ == itemField {
+		chain := newChain(t.peek().pos, node)
+		for t.peek().typ == itemField {
+			chain.Add(t.next().val)
+		}
+		// Compatibility with original API: If the term is of type NodeField
+		// or NodeVariable, just put more fields on the original.
+		// Otherwise, keep the Chain node.
+		// TODO: Switch to Chains always when we can.
+		switch node.Type() {
+		case NodeField:
+			node = newField(chain.Position(), chain.String())
+		case NodeVariable:
+			node = newVariable(chain.Position(), chain.String())
+		default:
+			node = chain
+		}
+	}
+	return node
+}
+
+// term:
+//	literal (number, string, nil, boolean)
+//	function (identifier)
+//	.
+//	.Field
+//	$
+//	'(' pipeline ')'
+// A term is a simple "expression".
+// A nil return means the next item is not a term.
+func (t *Tree) term() Node {
+	switch token := t.nextNonSpace(); token.typ {
+	case itemError:
+		t.errorf("%s", token.val)
+	case itemIdentifier:
+		if !t.hasFunction(token.val) {
+			t.errorf("function %q not defined", token.val)
+		}
+		return NewIdentifier(token.val).SetPos(token.pos)
+	case itemDot:
+		return newDot(token.pos)
+	case itemNil:
+		return newNil(token.pos)
+	case itemVariable:
+		return t.useVar(token.pos, token.val)
+	case itemField:
+		return newField(token.pos, token.val)
+	case itemBool:
+		return newBool(token.pos, token.val == "true")
+	case itemCharConstant, itemComplex, itemNumber:
+		number, err := newNumber(token.pos, token.val, token.typ)
+		if err != nil {
+			t.error(err)
+		}
+		return number
+	case itemLeftParen:
+		pipe := t.pipeline("parenthesized pipeline")
+		if token := t.next(); token.typ != itemRightParen {
+			t.errorf("unclosed right paren: unexpected %s", token)
+		}
+		return pipe
+	case itemString, itemRawString:
+		s, err := strconv.Unquote(token.val)
+		if err != nil {
+			t.error(err)
+		}
+		return newString(token.pos, token.val, s)
+	}
+	t.backup()
+	return nil
+}
+
+// hasFunction reports if a function name exists in the Tree's maps.
+func (t *Tree) hasFunction(name string) bool {
+	for _, funcMap := range t.funcs {
+		if funcMap == nil {
+			continue
+		}
+		if funcMap[name] != nil {
+			return true
+		}
+	}
+	return false
+}
+
+// popVars trims the variable list to the specified length
+func (t *Tree) popVars(n int) {
+	t.vars = t.vars[:n]
+}
+
+// useVar returns a node for a variable reference. It errors if the
+// variable is not defined.
+func (t *Tree) useVar(pos Pos, name string) Node {
+	v := newVariable(pos, name)
+	for _, varName := range t.vars {
+		if varName == v.Ident[0] {
+			return v
+		}
+	}
+	t.errorf("undefined variable %q", v.Ident[0])
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/parse/parse_test.go b/third_party/gofrontend/libgo/go/text/template/parse/parse_test.go
new file mode 100644
index 0000000..ba1a18e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/parse/parse_test.go
@@ -0,0 +1,420 @@
+// 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.
+
+package parse
+
+import (
+	"flag"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+var debug = flag.Bool("debug", false, "show the errors produced by the main tests")
+
+type numberTest struct {
+	text      string
+	isInt     bool
+	isUint    bool
+	isFloat   bool
+	isComplex bool
+	int64
+	uint64
+	float64
+	complex128
+}
+
+var numberTests = []numberTest{
+	// basics
+	{"0", true, true, true, false, 0, 0, 0, 0},
+	{"-0", true, true, true, false, 0, 0, 0, 0}, // check that -0 is a uint.
+	{"73", true, true, true, false, 73, 73, 73, 0},
+	{"073", true, true, true, false, 073, 073, 073, 0},
+	{"0x73", true, true, true, false, 0x73, 0x73, 0x73, 0},
+	{"-73", true, false, true, false, -73, 0, -73, 0},
+	{"+73", true, false, true, false, 73, 0, 73, 0},
+	{"100", true, true, true, false, 100, 100, 100, 0},
+	{"1e9", true, true, true, false, 1e9, 1e9, 1e9, 0},
+	{"-1e9", true, false, true, false, -1e9, 0, -1e9, 0},
+	{"-1.2", false, false, true, false, 0, 0, -1.2, 0},
+	{"1e19", false, true, true, false, 0, 1e19, 1e19, 0},
+	{"-1e19", false, false, true, false, 0, 0, -1e19, 0},
+	{"4i", false, false, false, true, 0, 0, 0, 4i},
+	{"-1.2+4.2i", false, false, false, true, 0, 0, 0, -1.2 + 4.2i},
+	{"073i", false, false, false, true, 0, 0, 0, 73i}, // not octal!
+	// complex with 0 imaginary are float (and maybe integer)
+	{"0i", true, true, true, true, 0, 0, 0, 0},
+	{"-1.2+0i", false, false, true, true, 0, 0, -1.2, -1.2},
+	{"-12+0i", true, false, true, true, -12, 0, -12, -12},
+	{"13+0i", true, true, true, true, 13, 13, 13, 13},
+	// funny bases
+	{"0123", true, true, true, false, 0123, 0123, 0123, 0},
+	{"-0x0", true, true, true, false, 0, 0, 0, 0},
+	{"0xdeadbeef", true, true, true, false, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0},
+	// character constants
+	{`'a'`, true, true, true, false, 'a', 'a', 'a', 0},
+	{`'\n'`, true, true, true, false, '\n', '\n', '\n', 0},
+	{`'\\'`, true, true, true, false, '\\', '\\', '\\', 0},
+	{`'\''`, true, true, true, false, '\'', '\'', '\'', 0},
+	{`'\xFF'`, true, true, true, false, 0xFF, 0xFF, 0xFF, 0},
+	{`'パ'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0},
+	{`'\u30d1'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0},
+	{`'\U000030d1'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0},
+	// some broken syntax
+	{text: "+-2"},
+	{text: "0x123."},
+	{text: "1e."},
+	{text: "0xi."},
+	{text: "1+2."},
+	{text: "'x"},
+	{text: "'xx'"},
+}
+
+func TestNumberParse(t *testing.T) {
+	for _, test := range numberTests {
+		// If fmt.Sscan thinks it's complex, it's complex.  We can't trust the output
+		// because imaginary comes out as a number.
+		var c complex128
+		typ := itemNumber
+		if test.text[0] == '\'' {
+			typ = itemCharConstant
+		} else {
+			_, err := fmt.Sscan(test.text, &c)
+			if err == nil {
+				typ = itemComplex
+			}
+		}
+		n, err := newNumber(0, test.text, typ)
+		ok := test.isInt || test.isUint || test.isFloat || test.isComplex
+		if ok && err != nil {
+			t.Errorf("unexpected error for %q: %s", test.text, err)
+			continue
+		}
+		if !ok && err == nil {
+			t.Errorf("expected error for %q", test.text)
+			continue
+		}
+		if !ok {
+			if *debug {
+				fmt.Printf("%s\n\t%s\n", test.text, err)
+			}
+			continue
+		}
+		if n.IsComplex != test.isComplex {
+			t.Errorf("complex incorrect for %q; should be %t", test.text, test.isComplex)
+		}
+		if test.isInt {
+			if !n.IsInt {
+				t.Errorf("expected integer for %q", test.text)
+			}
+			if n.Int64 != test.int64 {
+				t.Errorf("int64 for %q should be %d Is %d", test.text, test.int64, n.Int64)
+			}
+		} else if n.IsInt {
+			t.Errorf("did not expect integer for %q", test.text)
+		}
+		if test.isUint {
+			if !n.IsUint {
+				t.Errorf("expected unsigned integer for %q", test.text)
+			}
+			if n.Uint64 != test.uint64 {
+				t.Errorf("uint64 for %q should be %d Is %d", test.text, test.uint64, n.Uint64)
+			}
+		} else if n.IsUint {
+			t.Errorf("did not expect unsigned integer for %q", test.text)
+		}
+		if test.isFloat {
+			if !n.IsFloat {
+				t.Errorf("expected float for %q", test.text)
+			}
+			if n.Float64 != test.float64 {
+				t.Errorf("float64 for %q should be %g Is %g", test.text, test.float64, n.Float64)
+			}
+		} else if n.IsFloat {
+			t.Errorf("did not expect float for %q", test.text)
+		}
+		if test.isComplex {
+			if !n.IsComplex {
+				t.Errorf("expected complex for %q", test.text)
+			}
+			if n.Complex128 != test.complex128 {
+				t.Errorf("complex128 for %q should be %g Is %g", test.text, test.complex128, n.Complex128)
+			}
+		} else if n.IsComplex {
+			t.Errorf("did not expect complex for %q", test.text)
+		}
+	}
+}
+
+type parseTest struct {
+	name   string
+	input  string
+	ok     bool
+	result string // what the user would see in an error message.
+}
+
+const (
+	noError  = true
+	hasError = false
+)
+
+var parseTests = []parseTest{
+	{"empty", "", noError,
+		``},
+	{"comment", "{{/*\n\n\n*/}}", noError,
+		``},
+	{"spaces", " \t\n", noError,
+		`" \t\n"`},
+	{"text", "some text", noError,
+		`"some text"`},
+	{"emptyAction", "{{}}", hasError,
+		`{{}}`},
+	{"field", "{{.X}}", noError,
+		`{{.X}}`},
+	{"simple command", "{{printf}}", noError,
+		`{{printf}}`},
+	{"$ invocation", "{{$}}", noError,
+		"{{$}}"},
+	{"variable invocation", "{{with $x := 3}}{{$x 23}}{{end}}", noError,
+		"{{with $x := 3}}{{$x 23}}{{end}}"},
+	{"variable with fields", "{{$.I}}", noError,
+		"{{$.I}}"},
+	{"multi-word command", "{{printf `%d` 23}}", noError,
+		"{{printf `%d` 23}}"},
+	{"pipeline", "{{.X|.Y}}", noError,
+		`{{.X | .Y}}`},
+	{"pipeline with decl", "{{$x := .X|.Y}}", noError,
+		`{{$x := .X | .Y}}`},
+	{"nested pipeline", "{{.X (.Y .Z) (.A | .B .C) (.E)}}", noError,
+		`{{.X (.Y .Z) (.A | .B .C) (.E)}}`},
+	{"field applied to parentheses", "{{(.Y .Z).Field}}", noError,
+		`{{(.Y .Z).Field}}`},
+	{"simple if", "{{if .X}}hello{{end}}", noError,
+		`{{if .X}}"hello"{{end}}`},
+	{"if with else", "{{if .X}}true{{else}}false{{end}}", noError,
+		`{{if .X}}"true"{{else}}"false"{{end}}`},
+	{"if with else if", "{{if .X}}true{{else if .Y}}false{{end}}", noError,
+		`{{if .X}}"true"{{else}}{{if .Y}}"false"{{end}}{{end}}`},
+	{"if else chain", "+{{if .X}}X{{else if .Y}}Y{{else if .Z}}Z{{end}}+", noError,
+		`"+"{{if .X}}"X"{{else}}{{if .Y}}"Y"{{else}}{{if .Z}}"Z"{{end}}{{end}}{{end}}"+"`},
+	{"simple range", "{{range .X}}hello{{end}}", noError,
+		`{{range .X}}"hello"{{end}}`},
+	{"chained field range", "{{range .X.Y.Z}}hello{{end}}", noError,
+		`{{range .X.Y.Z}}"hello"{{end}}`},
+	{"nested range", "{{range .X}}hello{{range .Y}}goodbye{{end}}{{end}}", noError,
+		`{{range .X}}"hello"{{range .Y}}"goodbye"{{end}}{{end}}`},
+	{"range with else", "{{range .X}}true{{else}}false{{end}}", noError,
+		`{{range .X}}"true"{{else}}"false"{{end}}`},
+	{"range over pipeline", "{{range .X|.M}}true{{else}}false{{end}}", noError,
+		`{{range .X | .M}}"true"{{else}}"false"{{end}}`},
+	{"range []int", "{{range .SI}}{{.}}{{end}}", noError,
+		`{{range .SI}}{{.}}{{end}}`},
+	{"range 1 var", "{{range $x := .SI}}{{.}}{{end}}", noError,
+		`{{range $x := .SI}}{{.}}{{end}}`},
+	{"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
+		`{{range $x, $y := .SI}}{{.}}{{end}}`},
+	{"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError,
+		`{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`},
+	{"template", "{{template `x`}}", noError,
+		`{{template "x"}}`},
+	{"template with arg", "{{template `x` .Y}}", noError,
+		`{{template "x" .Y}}`},
+	{"with", "{{with .X}}hello{{end}}", noError,
+		`{{with .X}}"hello"{{end}}`},
+	{"with with else", "{{with .X}}hello{{else}}goodbye{{end}}", noError,
+		`{{with .X}}"hello"{{else}}"goodbye"{{end}}`},
+	// Errors.
+	{"unclosed action", "hello{{range", hasError, ""},
+	{"unmatched end", "{{end}}", hasError, ""},
+	{"missing end", "hello{{range .x}}", hasError, ""},
+	{"missing end after else", "hello{{range .x}}{{else}}", hasError, ""},
+	{"undefined function", "hello{{undefined}}", hasError, ""},
+	{"undefined variable", "{{$x}}", hasError, ""},
+	{"variable undefined after end", "{{with $x := 4}}{{end}}{{$x}}", hasError, ""},
+	{"variable undefined in template", "{{template $v}}", hasError, ""},
+	{"declare with field", "{{with $x.Y := 4}}{{end}}", hasError, ""},
+	{"template with field ref", "{{template .X}}", hasError, ""},
+	{"template with var", "{{template $v}}", hasError, ""},
+	{"invalid punctuation", "{{printf 3, 4}}", hasError, ""},
+	{"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""},
+	{"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""},
+	{"dot applied to parentheses", "{{printf (printf .).}}", hasError, ""},
+	{"adjacent args", "{{printf 3`x`}}", hasError, ""},
+	{"adjacent args with .", "{{printf `x`.}}", hasError, ""},
+	{"extra end after if", "{{if .X}}a{{else if .Y}}b{{end}}{{end}}", hasError, ""},
+	// Equals (and other chars) do not assignments make (yet).
+	{"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"},
+	{"bug0b", "{{$x = 1}}{{$x}}", hasError, ""},
+	{"bug0c", "{{$x ! 2}}{{$x}}", hasError, ""},
+	{"bug0d", "{{$x % 3}}{{$x}}", hasError, ""},
+	// Check the parse fails for := rather than comma.
+	{"bug0e", "{{range $x := $y := 3}}{{end}}", hasError, ""},
+	// Another bug: variable read must ignore following punctuation.
+	{"bug1a", "{{$x:=.}}{{$x!2}}", hasError, ""},                     // ! is just illegal here.
+	{"bug1b", "{{$x:=.}}{{$x+2}}", hasError, ""},                     // $x+2 should not parse as ($x) (+2).
+	{"bug1c", "{{$x:=.}}{{$x +2}}", noError, "{{$x := .}}{{$x +2}}"}, // It's OK with a space.
+}
+
+var builtins = map[string]interface{}{
+	"printf": fmt.Sprintf,
+}
+
+func testParse(doCopy bool, t *testing.T) {
+	textFormat = "%q"
+	defer func() { textFormat = "%s" }()
+	for _, test := range parseTests {
+		tmpl, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree), builtins)
+		switch {
+		case err == nil && !test.ok:
+			t.Errorf("%q: expected error; got none", test.name)
+			continue
+		case err != nil && test.ok:
+			t.Errorf("%q: unexpected error: %v", test.name, err)
+			continue
+		case err != nil && !test.ok:
+			// expected error, got one
+			if *debug {
+				fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
+			}
+			continue
+		}
+		var result string
+		if doCopy {
+			result = tmpl.Root.Copy().String()
+		} else {
+			result = tmpl.Root.String()
+		}
+		if result != test.result {
+			t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.result)
+		}
+	}
+}
+
+func TestParse(t *testing.T) {
+	testParse(false, t)
+}
+
+// Same as TestParse, but we copy the node first
+func TestParseCopy(t *testing.T) {
+	testParse(true, t)
+}
+
+type isEmptyTest struct {
+	name  string
+	input string
+	empty bool
+}
+
+var isEmptyTests = []isEmptyTest{
+	{"empty", ``, true},
+	{"nonempty", `hello`, false},
+	{"spaces only", " \t\n \t\n", true},
+	{"definition", `{{define "x"}}something{{end}}`, true},
+	{"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true},
+	{"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n", false},
+	{"definition and action", "{{define `x`}}something{{end}}{{if 3}}foo{{end}}", false},
+}
+
+func TestIsEmpty(t *testing.T) {
+	if !IsEmptyTree(nil) {
+		t.Errorf("nil tree is not empty")
+	}
+	for _, test := range isEmptyTests {
+		tree, err := New("root").Parse(test.input, "", "", make(map[string]*Tree), nil)
+		if err != nil {
+			t.Errorf("%q: unexpected error: %v", test.name, err)
+			continue
+		}
+		if empty := IsEmptyTree(tree.Root); empty != test.empty {
+			t.Errorf("%q: expected %t got %t", test.name, test.empty, empty)
+		}
+	}
+}
+
+func TestErrorContextWithTreeCopy(t *testing.T) {
+	tree, err := New("root").Parse("{{if true}}{{end}}", "", "", make(map[string]*Tree), nil)
+	if err != nil {
+		t.Fatalf("unexpected tree parse failure: %v", err)
+	}
+	treeCopy := tree.Copy()
+	wantLocation, wantContext := tree.ErrorContext(tree.Root.Nodes[0])
+	gotLocation, gotContext := treeCopy.ErrorContext(treeCopy.Root.Nodes[0])
+	if wantLocation != gotLocation {
+		t.Errorf("wrong error location want %q got %q", wantLocation, gotLocation)
+	}
+	if wantContext != gotContext {
+		t.Errorf("wrong error location want %q got %q", wantContext, gotContext)
+	}
+}
+
+// All failures, and the result is a string that must appear in the error message.
+var errorTests = []parseTest{
+	// Check line numbers are accurate.
+	{"unclosed1",
+		"line1\n{{",
+		hasError, `unclosed1:2: unexpected unclosed action in command`},
+	{"unclosed2",
+		"line1\n{{define `x`}}line2\n{{",
+		hasError, `unclosed2:3: unexpected unclosed action in command`},
+	// Specific errors.
+	{"function",
+		"{{foo}}",
+		hasError, `function "foo" not defined`},
+	{"comment",
+		"{{/*}}",
+		hasError, `unclosed comment`},
+	{"lparen",
+		"{{.X (1 2 3}}",
+		hasError, `unclosed left paren`},
+	{"rparen",
+		"{{.X 1 2 3)}}",
+		hasError, `unexpected ")"`},
+	{"space",
+		"{{`x`3}}",
+		hasError, `missing space?`},
+	{"idchar",
+		"{{a#}}",
+		hasError, `'#'`},
+	{"charconst",
+		"{{'a}}",
+		hasError, `unterminated character constant`},
+	{"stringconst",
+		`{{"a}}`,
+		hasError, `unterminated quoted string`},
+	{"rawstringconst",
+		"{{`a}}",
+		hasError, `unterminated raw quoted string`},
+	{"number",
+		"{{0xi}}",
+		hasError, `number syntax`},
+	{"multidefine",
+		"{{define `a`}}a{{end}}{{define `a`}}b{{end}}",
+		hasError, `multiple definition of template`},
+	{"eof",
+		"{{range .X}}",
+		hasError, `unexpected EOF`},
+	{"variable",
+		// Declare $x so it's defined, to avoid that error, and then check we don't parse a declaration.
+		"{{$x := 23}}{{with $x.y := 3}}{{$x 23}}{{end}}",
+		hasError, `unexpected ":="`},
+	{"multidecl",
+		"{{$a,$b,$c := 23}}",
+		hasError, `too many declarations`},
+	{"undefvar",
+		"{{$a}}",
+		hasError, `undefined variable`},
+}
+
+func TestErrors(t *testing.T) {
+	for _, test := range errorTests {
+		_, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree))
+		if err == nil {
+			t.Errorf("%q: expected error", test.name)
+			continue
+		}
+		if !strings.Contains(err.Error(), test.result) {
+			t.Errorf("%q: error %q does not contain %q", test.name, err, test.result)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/template.go b/third_party/gofrontend/libgo/go/text/template/template.go
new file mode 100644
index 0000000..249d0cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/template.go
@@ -0,0 +1,217 @@
+// 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.
+
+package template
+
+import (
+	"fmt"
+	"reflect"
+	"text/template/parse"
+)
+
+// common holds the information shared by related templates.
+type common struct {
+	tmpl map[string]*Template
+	// We use two maps, one for parsing and one for execution.
+	// This separation makes the API cleaner since it doesn't
+	// expose reflection to the client.
+	parseFuncs FuncMap
+	execFuncs  map[string]reflect.Value
+}
+
+// Template is the representation of a parsed template. The *parse.Tree
+// field is exported only for use by html/template and should be treated
+// as unexported by all other clients.
+type Template struct {
+	name string
+	*parse.Tree
+	*common
+	leftDelim  string
+	rightDelim string
+}
+
+// New allocates a new template with the given name.
+func New(name string) *Template {
+	return &Template{
+		name: name,
+	}
+}
+
+// Name returns the name of the template.
+func (t *Template) Name() string {
+	return t.name
+}
+
+// New allocates a new template associated with the given one and with the same
+// delimiters. The association, which is transitive, allows one template to
+// invoke another with a {{template}} action.
+func (t *Template) New(name string) *Template {
+	t.init()
+	return &Template{
+		name:       name,
+		common:     t.common,
+		leftDelim:  t.leftDelim,
+		rightDelim: t.rightDelim,
+	}
+}
+
+func (t *Template) init() {
+	if t.common == nil {
+		t.common = new(common)
+		t.tmpl = make(map[string]*Template)
+		t.parseFuncs = make(FuncMap)
+		t.execFuncs = make(map[string]reflect.Value)
+	}
+}
+
+// Clone returns a duplicate of the template, including all associated
+// templates. The actual representation is not copied, but the name space of
+// associated templates is, so further calls to Parse in the copy will add
+// templates to the copy but not to the original. Clone can be used to prepare
+// common templates and use them with variant definitions for other templates
+// by adding the variants after the clone is made.
+func (t *Template) Clone() (*Template, error) {
+	nt := t.copy(nil)
+	nt.init()
+	nt.tmpl[t.name] = nt
+	for k, v := range t.tmpl {
+		if k == t.name { // Already installed.
+			continue
+		}
+		// The associated templates share nt's common structure.
+		tmpl := v.copy(nt.common)
+		nt.tmpl[k] = tmpl
+	}
+	for k, v := range t.parseFuncs {
+		nt.parseFuncs[k] = v
+	}
+	for k, v := range t.execFuncs {
+		nt.execFuncs[k] = v
+	}
+	return nt, nil
+}
+
+// copy returns a shallow copy of t, with common set to the argument.
+func (t *Template) copy(c *common) *Template {
+	nt := New(t.name)
+	nt.Tree = t.Tree
+	nt.common = c
+	nt.leftDelim = t.leftDelim
+	nt.rightDelim = t.rightDelim
+	return nt
+}
+
+// AddParseTree creates a new template with the name and parse tree
+// and associates it with t.
+func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
+	if t.common != nil && t.tmpl[name] != nil {
+		return nil, fmt.Errorf("template: redefinition of template %q", name)
+	}
+	nt := t.New(name)
+	nt.Tree = tree
+	t.tmpl[name] = nt
+	return nt, nil
+}
+
+// Templates returns a slice of the templates associated with t, including t
+// itself.
+func (t *Template) Templates() []*Template {
+	if t.common == nil {
+		return nil
+	}
+	// Return a slice so we don't expose the map.
+	m := make([]*Template, 0, len(t.tmpl))
+	for _, v := range t.tmpl {
+		m = append(m, v)
+	}
+	return m
+}
+
+// Delims sets the action delimiters to the specified strings, to be used in
+// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
+// definitions will inherit the settings. An empty delimiter stands for the
+// corresponding default: {{ or }}.
+// The return value is the template, so calls can be chained.
+func (t *Template) Delims(left, right string) *Template {
+	t.leftDelim = left
+	t.rightDelim = right
+	return t
+}
+
+// Funcs adds the elements of the argument map to the template's function map.
+// It panics if a value in the map is not a function with appropriate return
+// type. However, it is legal to overwrite elements of the map. The return
+// value is the template, so calls can be chained.
+func (t *Template) Funcs(funcMap FuncMap) *Template {
+	t.init()
+	addValueFuncs(t.execFuncs, funcMap)
+	addFuncs(t.parseFuncs, funcMap)
+	return t
+}
+
+// Lookup returns the template with the given name that is associated with t,
+// or nil if there is no such template.
+func (t *Template) Lookup(name string) *Template {
+	if t.common == nil {
+		return nil
+	}
+	return t.tmpl[name]
+}
+
+// Parse parses a string into a template. Nested template definitions will be
+// associated with the top-level template t. Parse may be called multiple times
+// to parse definitions of templates to associate with t. It is an error if a
+// resulting template is non-empty (contains content other than template
+// definitions) and would replace a non-empty template with the same name.
+// (In multiple calls to Parse with the same receiver template, only one call
+// can contain text other than space, comments, and template definitions.)
+func (t *Template) Parse(text string) (*Template, error) {
+	t.init()
+	trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins)
+	if err != nil {
+		return nil, err
+	}
+	// Add the newly parsed trees, including the one for t, into our common structure.
+	for name, tree := range trees {
+		// If the name we parsed is the name of this template, overwrite this template.
+		// The associate method checks it's not a redefinition.
+		tmpl := t
+		if name != t.name {
+			tmpl = t.New(name)
+		}
+		// Even if t == tmpl, we need to install it in the common.tmpl map.
+		if replace, err := t.associate(tmpl, tree); err != nil {
+			return nil, err
+		} else if replace {
+			tmpl.Tree = tree
+		}
+		tmpl.leftDelim = t.leftDelim
+		tmpl.rightDelim = t.rightDelim
+	}
+	return t, nil
+}
+
+// associate installs the new template into the group of templates associated
+// with t. It is an error to reuse a name except to overwrite an empty
+// template. The two are already known to share the common structure.
+// The boolean return value reports wither to store this tree as t.Tree.
+func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) {
+	if new.common != t.common {
+		panic("internal error: associate not common")
+	}
+	name := new.name
+	if old := t.tmpl[name]; old != nil {
+		oldIsEmpty := parse.IsEmptyTree(old.Root)
+		newIsEmpty := parse.IsEmptyTree(tree.Root)
+		if newIsEmpty {
+			// Whether old is empty or not, new is empty; no reason to replace old.
+			return false, nil
+		}
+		if !oldIsEmpty {
+			return false, fmt.Errorf("template: redefinition of template %q", name)
+		}
+	}
+	t.tmpl[name] = new
+	return true, nil
+}
diff --git a/third_party/gofrontend/libgo/go/text/template/testdata/file1.tmpl b/third_party/gofrontend/libgo/go/text/template/testdata/file1.tmpl
new file mode 100644
index 0000000..febf9d9
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/testdata/file1.tmpl
@@ -0,0 +1,2 @@
+{{define "x"}}TEXT{{end}}
+{{define "dotV"}}{{.V}}{{end}}
diff --git a/third_party/gofrontend/libgo/go/text/template/testdata/file2.tmpl b/third_party/gofrontend/libgo/go/text/template/testdata/file2.tmpl
new file mode 100644
index 0000000..39bf6fb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/testdata/file2.tmpl
@@ -0,0 +1,2 @@
+{{define "dot"}}{{.}}{{end}}
+{{define "nested"}}{{template "dot" .}}{{end}}
diff --git a/third_party/gofrontend/libgo/go/text/template/testdata/tmpl1.tmpl b/third_party/gofrontend/libgo/go/text/template/testdata/tmpl1.tmpl
new file mode 100644
index 0000000..b72b3a3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/testdata/tmpl1.tmpl
@@ -0,0 +1,3 @@
+template1
+{{define "x"}}x{{end}}
+{{template "y"}}
diff --git a/third_party/gofrontend/libgo/go/text/template/testdata/tmpl2.tmpl b/third_party/gofrontend/libgo/go/text/template/testdata/tmpl2.tmpl
new file mode 100644
index 0000000..16beba6
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/text/template/testdata/tmpl2.tmpl
@@ -0,0 +1,3 @@
+template2
+{{define "y"}}y{{end}}
+{{template "x"}}
diff --git a/third_party/gofrontend/libgo/go/time/example_test.go b/third_party/gofrontend/libgo/go/time/example_test.go
new file mode 100644
index 0000000..cfa5b38
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/example_test.go
@@ -0,0 +1,160 @@
+// 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.
+
+package time_test
+
+import (
+	"fmt"
+	"time"
+)
+
+func expensiveCall() {}
+
+func ExampleDuration() {
+	t0 := time.Now()
+	expensiveCall()
+	t1 := time.Now()
+	fmt.Printf("The call took %v to run.\n", t1.Sub(t0))
+}
+
+var c chan int
+
+func handle(int) {}
+
+func ExampleAfter() {
+	select {
+	case m := <-c:
+		handle(m)
+	case <-time.After(5 * time.Minute):
+		fmt.Println("timed out")
+	}
+}
+
+func ExampleSleep() {
+	time.Sleep(100 * time.Millisecond)
+}
+
+func statusUpdate() string { return "" }
+
+func ExampleTick() {
+	c := time.Tick(1 * time.Minute)
+	for now := range c {
+		fmt.Printf("%v %s\n", now, statusUpdate())
+	}
+}
+
+func ExampleMonth() {
+	_, month, day := time.Now().Date()
+	if month == time.November && day == 10 {
+		fmt.Println("Happy Go day!")
+	}
+}
+
+func ExampleDate() {
+	t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+	fmt.Printf("Go launched at %s\n", t.Local())
+	// Output: Go launched at 2009-11-10 15:00:00 -0800 PST
+}
+
+func ExampleTime_Format() {
+	// layout shows by example how the reference time should be represented.
+	const layout = "Jan 2, 2006 at 3:04pm (MST)"
+	t := time.Date(2009, time.November, 10, 15, 0, 0, 0, time.Local)
+	fmt.Println(t.Format(layout))
+	fmt.Println(t.UTC().Format(layout))
+	// Output:
+	// Nov 10, 2009 at 3:00pm (PST)
+	// Nov 10, 2009 at 11:00pm (UTC)
+}
+
+func ExampleParse() {
+	// longForm shows by example how the reference time would be represented in
+	// the desired layout.
+	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
+	t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
+	fmt.Println(t)
+
+	// shortForm is another way the reference time would be represented
+	// in the desired layout; it has no time zone present.
+	// Note: without explicit zone, returns time in UTC.
+	const shortForm = "2006-Jan-02"
+	t, _ = time.Parse(shortForm, "2013-Feb-03")
+	fmt.Println(t)
+
+	// Output:
+	// 2013-02-03 19:54:00 -0800 PST
+	// 2013-02-03 00:00:00 +0000 UTC
+}
+
+func ExampleParseInLocation() {
+	loc, _ := time.LoadLocation("Europe/Berlin")
+
+	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
+	t, _ := time.ParseInLocation(longForm, "Jul 9, 2012 at 5:02am (CEST)", loc)
+	fmt.Println(t)
+
+	// Note: without explicit zone, returns time in given location.
+	const shortForm = "2006-Jan-02"
+	t, _ = time.ParseInLocation(shortForm, "2012-Jul-09", loc)
+	fmt.Println(t)
+
+	// Output:
+	// 2012-07-09 05:02:00 +0200 CEST
+	// 2012-07-09 00:00:00 +0200 CEST
+}
+
+func ExampleTime_Round() {
+	t := time.Date(0, 0, 0, 12, 15, 30, 918273645, time.UTC)
+	round := []time.Duration{
+		time.Nanosecond,
+		time.Microsecond,
+		time.Millisecond,
+		time.Second,
+		2 * time.Second,
+		time.Minute,
+		10 * time.Minute,
+		time.Hour,
+	}
+
+	for _, d := range round {
+		fmt.Printf("t.Round(%6s) = %s\n", d, t.Round(d).Format("15:04:05.999999999"))
+	}
+	// Output:
+	// t.Round(   1ns) = 12:15:30.918273645
+	// t.Round(   1us) = 12:15:30.918274
+	// t.Round(   1ms) = 12:15:30.918
+	// t.Round(    1s) = 12:15:31
+	// t.Round(    2s) = 12:15:30
+	// t.Round(  1m0s) = 12:16:00
+	// t.Round( 10m0s) = 12:20:00
+	// t.Round(1h0m0s) = 12:00:00
+}
+
+func ExampleTime_Truncate() {
+	t, _ := time.Parse("2006 Jan 02 15:04:05", "2012 Dec 07 12:15:30.918273645")
+	trunc := []time.Duration{
+		time.Nanosecond,
+		time.Microsecond,
+		time.Millisecond,
+		time.Second,
+		2 * time.Second,
+		time.Minute,
+		10 * time.Minute,
+		time.Hour,
+	}
+
+	for _, d := range trunc {
+		fmt.Printf("t.Truncate(%6s) = %s\n", d, t.Truncate(d).Format("15:04:05.999999999"))
+	}
+
+	// Output:
+	// t.Truncate(   1ns) = 12:15:30.918273645
+	// t.Truncate(   1us) = 12:15:30.918273
+	// t.Truncate(   1ms) = 12:15:30.918
+	// t.Truncate(    1s) = 12:15:30
+	// t.Truncate(    2s) = 12:15:30
+	// t.Truncate(  1m0s) = 12:15:00
+	// t.Truncate( 10m0s) = 12:10:00
+	// t.Truncate(1h0m0s) = 12:00:00
+}
diff --git a/third_party/gofrontend/libgo/go/time/export_test.go b/third_party/gofrontend/libgo/go/time/export_test.go
new file mode 100644
index 0000000..6cd535f
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/export_test.go
@@ -0,0 +1,24 @@
+// Copyright 2013 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 time
+
+import (
+	"sync"
+)
+
+func ResetLocalOnceForTest() {
+	localOnce = sync.Once{}
+	localLoc = Location{}
+}
+
+func ForceUSPacificForTesting() {
+	ResetLocalOnceForTest()
+	localOnce.Do(initTestingZone)
+}
+
+var (
+	ForceZipFileForTesting = forceZipFileForTesting
+	ParseTimeZone          = parseTimeZone
+)
diff --git a/third_party/gofrontend/libgo/go/time/format.go b/third_party/gofrontend/libgo/go/time/format.go
new file mode 100644
index 0000000..9f210ea
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/format.go
@@ -0,0 +1,1247 @@
+// Copyright 2010 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 time
+
+import "errors"
+
+// These are predefined layouts for use in Time.Format and Time.Parse.
+// The reference time used in the layouts is:
+//	Mon Jan 2 15:04:05 MST 2006
+// which is Unix time 1136239445. Since MST is GMT-0700,
+// the reference time can be thought of as
+//	01/02 03:04:05PM '06 -0700
+// To define your own format, write down what the reference time would look
+// like formatted your way; see the values of constants like ANSIC,
+// StampMicro or Kitchen for examples. The model is to demonstrate what the
+// reference time looks like so that the Format and Parse methods can apply
+// the same transformation to a general time value.
+//
+// Within the format string, an underscore _ represents a space that may be
+// replaced by a digit if the following number (a day) has two digits; for
+// compatibility with fixed-width Unix time formats.
+//
+// A decimal point followed by one or more zeros represents a fractional
+// second, printed to the given number of decimal places.  A decimal point
+// followed by one or more nines represents a fractional second, printed to
+// the given number of decimal places, with trailing zeros removed.
+// When parsing (only), the input may contain a fractional second
+// field immediately after the seconds field, even if the layout does not
+// signify its presence. In that case a decimal point followed by a maximal
+// series of digits is parsed as a fractional second.
+//
+// Numeric time zone offsets format as follows:
+//	-0700  ±hhmm
+//	-07:00 ±hh:mm
+// Replacing the sign in the format with a Z triggers
+// the ISO 8601 behavior of printing Z instead of an
+// offset for the UTC zone.  Thus:
+//	Z0700  Z or ±hhmm
+//	Z07:00 Z or ±hh:mm
+const (
+	ANSIC       = "Mon Jan _2 15:04:05 2006"
+	UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
+	RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
+	RFC822      = "02 Jan 06 15:04 MST"
+	RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
+	RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
+	RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
+	RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
+	RFC3339     = "2006-01-02T15:04:05Z07:00"
+	RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
+	Kitchen     = "3:04PM"
+	// Handy time stamps.
+	Stamp      = "Jan _2 15:04:05"
+	StampMilli = "Jan _2 15:04:05.000"
+	StampMicro = "Jan _2 15:04:05.000000"
+	StampNano  = "Jan _2 15:04:05.000000000"
+)
+
+const (
+	_                        = iota
+	stdLongMonth             = iota + stdNeedDate  // "January"
+	stdMonth                                       // "Jan"
+	stdNumMonth                                    // "1"
+	stdZeroMonth                                   // "01"
+	stdLongWeekDay                                 // "Monday"
+	stdWeekDay                                     // "Mon"
+	stdDay                                         // "2"
+	stdUnderDay                                    // "_2"
+	stdZeroDay                                     // "02"
+	stdHour                  = iota + stdNeedClock // "15"
+	stdHour12                                      // "3"
+	stdZeroHour12                                  // "03"
+	stdMinute                                      // "4"
+	stdZeroMinute                                  // "04"
+	stdSecond                                      // "5"
+	stdZeroSecond                                  // "05"
+	stdLongYear              = iota + stdNeedDate  // "2006"
+	stdYear                                        // "06"
+	stdPM                    = iota + stdNeedClock // "PM"
+	stdpm                                          // "pm"
+	stdTZ                    = iota                // "MST"
+	stdISO8601TZ                                   // "Z0700"  // prints Z for UTC
+	stdISO8601SecondsTZ                            // "Z070000"
+	stdISO8601ColonTZ                              // "Z07:00" // prints Z for UTC
+	stdISO8601ColonSecondsTZ                       // "Z07:00:00"
+	stdNumTZ                                       // "-0700"  // always numeric
+	stdNumSecondsTz                                // "-070000"
+	stdNumShortTZ                                  // "-07"    // always numeric
+	stdNumColonTZ                                  // "-07:00" // always numeric
+	stdNumColonSecondsTZ                           // "-07:00:00"
+	stdFracSecond0                                 // ".0", ".00", ... , trailing zeros included
+	stdFracSecond9                                 // ".9", ".99", ..., trailing zeros omitted
+
+	stdNeedDate  = 1 << 8             // need month, day, year
+	stdNeedClock = 2 << 8             // need hour, minute, second
+	stdArgShift  = 16                 // extra argument in high bits, above low stdArgShift
+	stdMask      = 1<<stdArgShift - 1 // mask out argument
+)
+
+// std0x records the std values for "01", "02", ..., "06".
+var std0x = [...]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear}
+
+// startsWithLowerCase reports whether the string has a lower-case letter at the beginning.
+// Its purpose is to prevent matching strings like "Month" when looking for "Mon".
+func startsWithLowerCase(str string) bool {
+	if len(str) == 0 {
+		return false
+	}
+	c := str[0]
+	return 'a' <= c && c <= 'z'
+}
+
+// nextStdChunk finds the first occurrence of a std string in
+// layout and returns the text before, the std string, and the text after.
+func nextStdChunk(layout string) (prefix string, std int, suffix string) {
+	for i := 0; i < len(layout); i++ {
+		switch c := int(layout[i]); c {
+		case 'J': // January, Jan
+			if len(layout) >= i+3 && layout[i:i+3] == "Jan" {
+				if len(layout) >= i+7 && layout[i:i+7] == "January" {
+					return layout[0:i], stdLongMonth, layout[i+7:]
+				}
+				if !startsWithLowerCase(layout[i+3:]) {
+					return layout[0:i], stdMonth, layout[i+3:]
+				}
+			}
+
+		case 'M': // Monday, Mon, MST
+			if len(layout) >= i+3 {
+				if layout[i:i+3] == "Mon" {
+					if len(layout) >= i+6 && layout[i:i+6] == "Monday" {
+						return layout[0:i], stdLongWeekDay, layout[i+6:]
+					}
+					if !startsWithLowerCase(layout[i+3:]) {
+						return layout[0:i], stdWeekDay, layout[i+3:]
+					}
+				}
+				if layout[i:i+3] == "MST" {
+					return layout[0:i], stdTZ, layout[i+3:]
+				}
+			}
+
+		case '0': // 01, 02, 03, 04, 05, 06
+			if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' {
+				return layout[0:i], std0x[layout[i+1]-'1'], layout[i+2:]
+			}
+
+		case '1': // 15, 1
+			if len(layout) >= i+2 && layout[i+1] == '5' {
+				return layout[0:i], stdHour, layout[i+2:]
+			}
+			return layout[0:i], stdNumMonth, layout[i+1:]
+
+		case '2': // 2006, 2
+			if len(layout) >= i+4 && layout[i:i+4] == "2006" {
+				return layout[0:i], stdLongYear, layout[i+4:]
+			}
+			return layout[0:i], stdDay, layout[i+1:]
+
+		case '_': // _2
+			if len(layout) >= i+2 && layout[i+1] == '2' {
+				return layout[0:i], stdUnderDay, layout[i+2:]
+			}
+
+		case '3':
+			return layout[0:i], stdHour12, layout[i+1:]
+
+		case '4':
+			return layout[0:i], stdMinute, layout[i+1:]
+
+		case '5':
+			return layout[0:i], stdSecond, layout[i+1:]
+
+		case 'P': // PM
+			if len(layout) >= i+2 && layout[i+1] == 'M' {
+				return layout[0:i], stdPM, layout[i+2:]
+			}
+
+		case 'p': // pm
+			if len(layout) >= i+2 && layout[i+1] == 'm' {
+				return layout[0:i], stdpm, layout[i+2:]
+			}
+
+		case '-': // -070000, -07:00:00, -0700, -07:00, -07
+			if len(layout) >= i+7 && layout[i:i+7] == "-070000" {
+				return layout[0:i], stdNumSecondsTz, layout[i+7:]
+			}
+			if len(layout) >= i+9 && layout[i:i+9] == "-07:00:00" {
+				return layout[0:i], stdNumColonSecondsTZ, layout[i+9:]
+			}
+			if len(layout) >= i+5 && layout[i:i+5] == "-0700" {
+				return layout[0:i], stdNumTZ, layout[i+5:]
+			}
+			if len(layout) >= i+6 && layout[i:i+6] == "-07:00" {
+				return layout[0:i], stdNumColonTZ, layout[i+6:]
+			}
+			if len(layout) >= i+3 && layout[i:i+3] == "-07" {
+				return layout[0:i], stdNumShortTZ, layout[i+3:]
+			}
+
+		case 'Z': // Z070000, Z07:00:00, Z0700, Z07:00,
+			if len(layout) >= i+7 && layout[i:i+7] == "Z070000" {
+				return layout[0:i], stdISO8601SecondsTZ, layout[i+7:]
+			}
+			if len(layout) >= i+9 && layout[i:i+9] == "Z07:00:00" {
+				return layout[0:i], stdISO8601ColonSecondsTZ, layout[i+9:]
+			}
+			if len(layout) >= i+5 && layout[i:i+5] == "Z0700" {
+				return layout[0:i], stdISO8601TZ, layout[i+5:]
+			}
+			if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
+				return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
+			}
+
+		case '.': // .000 or .999 - repeated digits for fractional seconds.
+			if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
+				ch := layout[i+1]
+				j := i + 1
+				for j < len(layout) && layout[j] == ch {
+					j++
+				}
+				// String of digits must end here - only fractional second is all digits.
+				if !isDigit(layout, j) {
+					std := stdFracSecond0
+					if layout[i+1] == '9' {
+						std = stdFracSecond9
+					}
+					std |= (j - (i + 1)) << stdArgShift
+					return layout[0:i], std, layout[j:]
+				}
+			}
+		}
+	}
+	return layout, 0, ""
+}
+
+var longDayNames = []string{
+	"Sunday",
+	"Monday",
+	"Tuesday",
+	"Wednesday",
+	"Thursday",
+	"Friday",
+	"Saturday",
+}
+
+var shortDayNames = []string{
+	"Sun",
+	"Mon",
+	"Tue",
+	"Wed",
+	"Thu",
+	"Fri",
+	"Sat",
+}
+
+var shortMonthNames = []string{
+	"---",
+	"Jan",
+	"Feb",
+	"Mar",
+	"Apr",
+	"May",
+	"Jun",
+	"Jul",
+	"Aug",
+	"Sep",
+	"Oct",
+	"Nov",
+	"Dec",
+}
+
+var longMonthNames = []string{
+	"---",
+	"January",
+	"February",
+	"March",
+	"April",
+	"May",
+	"June",
+	"July",
+	"August",
+	"September",
+	"October",
+	"November",
+	"December",
+}
+
+// match returns true if s1 and s2 match ignoring case.
+// It is assumed s1 and s2 are the same length.
+func match(s1, s2 string) bool {
+	for i := 0; i < len(s1); i++ {
+		c1 := s1[i]
+		c2 := s2[i]
+		if c1 != c2 {
+			// Switch to lower-case; 'a'-'A' is known to be a single bit.
+			c1 |= 'a' - 'A'
+			c2 |= 'a' - 'A'
+			if c1 != c2 || c1 < 'a' || c1 > 'z' {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+func lookup(tab []string, val string) (int, string, error) {
+	for i, v := range tab {
+		if len(val) >= len(v) && match(val[0:len(v)], v) {
+			return i, val[len(v):], nil
+		}
+	}
+	return -1, val, errBad
+}
+
+// appendUint appends the decimal form of x to b and returns the result.
+// If x is a single-digit number and pad != 0, appendUint inserts the pad byte
+// before the digit.
+// Duplicates functionality in strconv, but avoids dependency.
+func appendUint(b []byte, x uint, pad byte) []byte {
+	if x < 10 {
+		if pad != 0 {
+			b = append(b, pad)
+		}
+		return append(b, byte('0'+x))
+	}
+	if x < 100 {
+		b = append(b, byte('0'+x/10))
+		b = append(b, byte('0'+x%10))
+		return b
+	}
+
+	var buf [32]byte
+	n := len(buf)
+	if x == 0 {
+		return append(b, '0')
+	}
+	for x >= 10 {
+		n--
+		buf[n] = byte(x%10 + '0')
+		x /= 10
+	}
+	n--
+	buf[n] = byte(x + '0')
+	return append(b, buf[n:]...)
+}
+
+// Never printed, just needs to be non-nil for return by atoi.
+var atoiError = errors.New("time: invalid number")
+
+// Duplicates functionality in strconv, but avoids dependency.
+func atoi(s string) (x int, err error) {
+	neg := false
+	if s != "" && (s[0] == '-' || s[0] == '+') {
+		neg = s[0] == '-'
+		s = s[1:]
+	}
+	q, rem, err := leadingInt(s)
+	x = int(q)
+	if err != nil || rem != "" {
+		return 0, atoiError
+	}
+	if neg {
+		x = -x
+	}
+	return x, nil
+}
+
+// formatNano appends a fractional second, as nanoseconds, to b
+// and returns the result.
+func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
+	u := nanosec
+	var buf [9]byte
+	for start := len(buf); start > 0; {
+		start--
+		buf[start] = byte(u%10 + '0')
+		u /= 10
+	}
+
+	if n > 9 {
+		n = 9
+	}
+	if trim {
+		for n > 0 && buf[n-1] == '0' {
+			n--
+		}
+		if n == 0 {
+			return b
+		}
+	}
+	b = append(b, '.')
+	return append(b, buf[:n]...)
+}
+
+// String returns the time formatted using the format string
+//	"2006-01-02 15:04:05.999999999 -0700 MST"
+func (t Time) String() string {
+	return t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
+}
+
+// Format returns a textual representation of the time value formatted
+// according to layout, which defines the format by showing how the reference
+// time,
+//	Mon Jan 2 15:04:05 -0700 MST 2006
+// would be displayed if it were the value; it serves as an example of the
+// desired output. The same display rules will then be applied to the time
+// value.
+// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard
+// and convenient representations of the reference time. For more information
+// about the formats and the definition of the reference time, see the
+// documentation for ANSIC and the other constants defined by this package.
+func (t Time) Format(layout string) string {
+	var (
+		name, offset, abs = t.locabs()
+
+		year  int = -1
+		month Month
+		day   int
+		hour  int = -1
+		min   int
+		sec   int
+
+		b   []byte
+		buf [64]byte
+	)
+	max := len(layout) + 10
+	if max <= len(buf) {
+		b = buf[:0]
+	} else {
+		b = make([]byte, 0, max)
+	}
+	// Each iteration generates one std value.
+	for layout != "" {
+		prefix, std, suffix := nextStdChunk(layout)
+		if prefix != "" {
+			b = append(b, prefix...)
+		}
+		if std == 0 {
+			break
+		}
+		layout = suffix
+
+		// Compute year, month, day if needed.
+		if year < 0 && std&stdNeedDate != 0 {
+			year, month, day, _ = absDate(abs, true)
+		}
+
+		// Compute hour, minute, second if needed.
+		if hour < 0 && std&stdNeedClock != 0 {
+			hour, min, sec = absClock(abs)
+		}
+
+		switch std & stdMask {
+		case stdYear:
+			y := year
+			if y < 0 {
+				y = -y
+			}
+			b = appendUint(b, uint(y%100), '0')
+		case stdLongYear:
+			// Pad year to at least 4 digits.
+			y := year
+			switch {
+			case year <= -1000:
+				b = append(b, '-')
+				y = -y
+			case year <= -100:
+				b = append(b, "-0"...)
+				y = -y
+			case year <= -10:
+				b = append(b, "-00"...)
+				y = -y
+			case year < 0:
+				b = append(b, "-000"...)
+				y = -y
+			case year < 10:
+				b = append(b, "000"...)
+			case year < 100:
+				b = append(b, "00"...)
+			case year < 1000:
+				b = append(b, '0')
+			}
+			b = appendUint(b, uint(y), 0)
+		case stdMonth:
+			b = append(b, month.String()[:3]...)
+		case stdLongMonth:
+			m := month.String()
+			b = append(b, m...)
+		case stdNumMonth:
+			b = appendUint(b, uint(month), 0)
+		case stdZeroMonth:
+			b = appendUint(b, uint(month), '0')
+		case stdWeekDay:
+			b = append(b, absWeekday(abs).String()[:3]...)
+		case stdLongWeekDay:
+			s := absWeekday(abs).String()
+			b = append(b, s...)
+		case stdDay:
+			b = appendUint(b, uint(day), 0)
+		case stdUnderDay:
+			b = appendUint(b, uint(day), ' ')
+		case stdZeroDay:
+			b = appendUint(b, uint(day), '0')
+		case stdHour:
+			b = appendUint(b, uint(hour), '0')
+		case stdHour12:
+			// Noon is 12PM, midnight is 12AM.
+			hr := hour % 12
+			if hr == 0 {
+				hr = 12
+			}
+			b = appendUint(b, uint(hr), 0)
+		case stdZeroHour12:
+			// Noon is 12PM, midnight is 12AM.
+			hr := hour % 12
+			if hr == 0 {
+				hr = 12
+			}
+			b = appendUint(b, uint(hr), '0')
+		case stdMinute:
+			b = appendUint(b, uint(min), 0)
+		case stdZeroMinute:
+			b = appendUint(b, uint(min), '0')
+		case stdSecond:
+			b = appendUint(b, uint(sec), 0)
+		case stdZeroSecond:
+			b = appendUint(b, uint(sec), '0')
+		case stdPM:
+			if hour >= 12 {
+				b = append(b, "PM"...)
+			} else {
+				b = append(b, "AM"...)
+			}
+		case stdpm:
+			if hour >= 12 {
+				b = append(b, "pm"...)
+			} else {
+				b = append(b, "am"...)
+			}
+		case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
+			// Ugly special case.  We cheat and take the "Z" variants
+			// to mean "the time zone as formatted for ISO 8601".
+			if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ColonSecondsTZ) {
+				b = append(b, 'Z')
+				break
+			}
+			zone := offset / 60 // convert to minutes
+			absoffset := offset
+			if zone < 0 {
+				b = append(b, '-')
+				zone = -zone
+				absoffset = -absoffset
+			} else {
+				b = append(b, '+')
+			}
+			b = appendUint(b, uint(zone/60), '0')
+			if std == stdISO8601ColonTZ || std == stdNumColonTZ {
+				b = append(b, ':')
+			}
+			b = appendUint(b, uint(zone%60), '0')
+
+			// append seconds if appropriate
+			if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
+				if std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
+					b = append(b, ':')
+				}
+				b = appendUint(b, uint(absoffset%60), '0')
+			}
+
+		case stdTZ:
+			if name != "" {
+				b = append(b, name...)
+				break
+			}
+			// No time zone known for this time, but we must print one.
+			// Use the -0700 format.
+			zone := offset / 60 // convert to minutes
+			if zone < 0 {
+				b = append(b, '-')
+				zone = -zone
+			} else {
+				b = append(b, '+')
+			}
+			b = appendUint(b, uint(zone/60), '0')
+			b = appendUint(b, uint(zone%60), '0')
+		case stdFracSecond0, stdFracSecond9:
+			b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9)
+		}
+	}
+	return string(b)
+}
+
+var errBad = errors.New("bad value for field") // placeholder not passed to user
+
+// ParseError describes a problem parsing a time string.
+type ParseError struct {
+	Layout     string
+	Value      string
+	LayoutElem string
+	ValueElem  string
+	Message    string
+}
+
+func quote(s string) string {
+	return "\"" + s + "\""
+}
+
+// Error returns the string representation of a ParseError.
+func (e *ParseError) Error() string {
+	if e.Message == "" {
+		return "parsing time " +
+			quote(e.Value) + " as " +
+			quote(e.Layout) + ": cannot parse " +
+			quote(e.ValueElem) + " as " +
+			quote(e.LayoutElem)
+	}
+	return "parsing time " +
+		quote(e.Value) + e.Message
+}
+
+// isDigit returns true if s[i] is a decimal digit, false if not or
+// if s[i] is out of range.
+func isDigit(s string, i int) bool {
+	if len(s) <= i {
+		return false
+	}
+	c := s[i]
+	return '0' <= c && c <= '9'
+}
+
+// getnum parses s[0:1] or s[0:2] (fixed forces the latter)
+// as a decimal integer and returns the integer and the
+// remainder of the string.
+func getnum(s string, fixed bool) (int, string, error) {
+	if !isDigit(s, 0) {
+		return 0, s, errBad
+	}
+	if !isDigit(s, 1) {
+		if fixed {
+			return 0, s, errBad
+		}
+		return int(s[0] - '0'), s[1:], nil
+	}
+	return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil
+}
+
+func cutspace(s string) string {
+	for len(s) > 0 && s[0] == ' ' {
+		s = s[1:]
+	}
+	return s
+}
+
+// skip removes the given prefix from value,
+// treating runs of space characters as equivalent.
+func skip(value, prefix string) (string, error) {
+	for len(prefix) > 0 {
+		if prefix[0] == ' ' {
+			if len(value) > 0 && value[0] != ' ' {
+				return value, errBad
+			}
+			prefix = cutspace(prefix)
+			value = cutspace(value)
+			continue
+		}
+		if len(value) == 0 || value[0] != prefix[0] {
+			return value, errBad
+		}
+		prefix = prefix[1:]
+		value = value[1:]
+	}
+	return value, nil
+}
+
+// Parse parses a formatted string and returns the time value it represents.
+// The layout  defines the format by showing how the reference time,
+//	Mon Jan 2 15:04:05 -0700 MST 2006
+// would be interpreted if it were the value; it serves as an example of
+// the input format. The same interpretation will then be made to the
+// input string.
+// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard
+// and convenient representations of the reference time. For more information
+// about the formats and the definition of the reference time, see the
+// documentation for ANSIC and the other constants defined by this package.
+//
+// Elements omitted from the value are assumed to be zero or, when
+// zero is impossible, one, so parsing "3:04pm" returns the time
+// corresponding to Jan 1, year 0, 15:04:00 UTC (note that because the year is
+// 0, this time is before the zero Time).
+// Years must be in the range 0000..9999. The day of the week is checked
+// for syntax but it is otherwise ignored.
+//
+// In the absence of a time zone indicator, Parse returns a time in UTC.
+//
+// When parsing a time with a zone offset like -0700, if the offset corresponds
+// to a time zone used by the current location (Local), then Parse uses that
+// location and zone in the returned time. Otherwise it records the time as
+// being in a fabricated location with time fixed at the given zone offset.
+//
+// When parsing a time with a zone abbreviation like MST, if the zone abbreviation
+// has a defined offset in the current location, then that offset is used.
+// The zone abbreviation "UTC" is recognized as UTC regardless of location.
+// If the zone abbreviation is unknown, Parse records the time as being
+// in a fabricated location with the given zone abbreviation and a zero offset.
+// This choice means that such a time can be parse and reformatted with the
+// same layout losslessly, but the exact instant used in the representation will
+// differ by the actual zone offset. To avoid such problems, prefer time layouts
+// that use a numeric zone offset, or use ParseInLocation.
+func Parse(layout, value string) (Time, error) {
+	return parse(layout, value, UTC, Local)
+}
+
+// ParseInLocation is like Parse but differs in two important ways.
+// First, in the absence of time zone information, Parse interprets a time as UTC;
+// ParseInLocation interprets the time as in the given location.
+// Second, when given a zone offset or abbreviation, Parse tries to match it
+// against the Local location; ParseInLocation uses the given location.
+func ParseInLocation(layout, value string, loc *Location) (Time, error) {
+	return parse(layout, value, loc, loc)
+}
+
+func parse(layout, value string, defaultLocation, local *Location) (Time, error) {
+	alayout, avalue := layout, value
+	rangeErrString := "" // set if a value is out of range
+	amSet := false       // do we need to subtract 12 from the hour for midnight?
+	pmSet := false       // do we need to add 12 to the hour?
+
+	// Time being constructed.
+	var (
+		year       int
+		month      int = 1 // January
+		day        int = 1
+		hour       int
+		min        int
+		sec        int
+		nsec       int
+		z          *Location
+		zoneOffset int = -1
+		zoneName   string
+	)
+
+	// Each iteration processes one std value.
+	for {
+		var err error
+		prefix, std, suffix := nextStdChunk(layout)
+		stdstr := layout[len(prefix) : len(layout)-len(suffix)]
+		value, err = skip(value, prefix)
+		if err != nil {
+			return Time{}, &ParseError{alayout, avalue, prefix, value, ""}
+		}
+		if std == 0 {
+			if len(value) != 0 {
+				return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
+			}
+			break
+		}
+		layout = suffix
+		var p string
+		switch std & stdMask {
+		case stdYear:
+			if len(value) < 2 {
+				err = errBad
+				break
+			}
+			p, value = value[0:2], value[2:]
+			year, err = atoi(p)
+			if year >= 69 { // Unix time starts Dec 31 1969 in some time zones
+				year += 1900
+			} else {
+				year += 2000
+			}
+		case stdLongYear:
+			if len(value) < 4 || !isDigit(value, 0) {
+				err = errBad
+				break
+			}
+			p, value = value[0:4], value[4:]
+			year, err = atoi(p)
+		case stdMonth:
+			month, value, err = lookup(shortMonthNames, value)
+		case stdLongMonth:
+			month, value, err = lookup(longMonthNames, value)
+		case stdNumMonth, stdZeroMonth:
+			month, value, err = getnum(value, std == stdZeroMonth)
+			if month <= 0 || 12 < month {
+				rangeErrString = "month"
+			}
+		case stdWeekDay:
+			// Ignore weekday except for error checking.
+			_, value, err = lookup(shortDayNames, value)
+		case stdLongWeekDay:
+			_, value, err = lookup(longDayNames, value)
+		case stdDay, stdUnderDay, stdZeroDay:
+			if std == stdUnderDay && len(value) > 0 && value[0] == ' ' {
+				value = value[1:]
+			}
+			day, value, err = getnum(value, std == stdZeroDay)
+			if day < 0 || 31 < day {
+				rangeErrString = "day"
+			}
+		case stdHour:
+			hour, value, err = getnum(value, false)
+			if hour < 0 || 24 <= hour {
+				rangeErrString = "hour"
+			}
+		case stdHour12, stdZeroHour12:
+			hour, value, err = getnum(value, std == stdZeroHour12)
+			if hour < 0 || 12 < hour {
+				rangeErrString = "hour"
+			}
+		case stdMinute, stdZeroMinute:
+			min, value, err = getnum(value, std == stdZeroMinute)
+			if min < 0 || 60 <= min {
+				rangeErrString = "minute"
+			}
+		case stdSecond, stdZeroSecond:
+			sec, value, err = getnum(value, std == stdZeroSecond)
+			if sec < 0 || 60 <= sec {
+				rangeErrString = "second"
+			}
+			// Special case: do we have a fractional second but no
+			// fractional second in the format?
+			if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
+				_, std, _ = nextStdChunk(layout)
+				std &= stdMask
+				if std == stdFracSecond0 || std == stdFracSecond9 {
+					// Fractional second in the layout; proceed normally
+					break
+				}
+				// No fractional second in the layout but we have one in the input.
+				n := 2
+				for ; n < len(value) && isDigit(value, n); n++ {
+				}
+				nsec, rangeErrString, err = parseNanoseconds(value, n)
+				value = value[n:]
+			}
+		case stdPM:
+			if len(value) < 2 {
+				err = errBad
+				break
+			}
+			p, value = value[0:2], value[2:]
+			switch p {
+			case "PM":
+				pmSet = true
+			case "AM":
+				amSet = true
+			default:
+				err = errBad
+			}
+		case stdpm:
+			if len(value) < 2 {
+				err = errBad
+				break
+			}
+			p, value = value[0:2], value[2:]
+			switch p {
+			case "pm":
+				pmSet = true
+			case "am":
+				amSet = true
+			default:
+				err = errBad
+			}
+		case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
+			if (std == stdISO8601TZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' {
+				value = value[1:]
+				z = UTC
+				break
+			}
+			var sign, hour, min, seconds string
+			if std == stdISO8601ColonTZ || std == stdNumColonTZ {
+				if len(value) < 6 {
+					err = errBad
+					break
+				}
+				if value[3] != ':' {
+					err = errBad
+					break
+				}
+				sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], "00", value[6:]
+			} else if std == stdNumShortTZ {
+				if len(value) < 3 {
+					err = errBad
+					break
+				}
+				sign, hour, min, seconds, value = value[0:1], value[1:3], "00", "00", value[3:]
+			} else if std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
+				if len(value) < 9 {
+					err = errBad
+					break
+				}
+				if value[3] != ':' || value[6] != ':' {
+					err = errBad
+					break
+				}
+				sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], value[7:9], value[9:]
+			} else if std == stdISO8601SecondsTZ || std == stdNumSecondsTz {
+				if len(value) < 7 {
+					err = errBad
+					break
+				}
+				sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], value[5:7], value[7:]
+			} else {
+				if len(value) < 5 {
+					err = errBad
+					break
+				}
+				sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], "00", value[5:]
+			}
+			var hr, mm, ss int
+			hr, err = atoi(hour)
+			if err == nil {
+				mm, err = atoi(min)
+			}
+			if err == nil {
+				ss, err = atoi(seconds)
+			}
+			zoneOffset = (hr*60+mm)*60 + ss // offset is in seconds
+			switch sign[0] {
+			case '+':
+			case '-':
+				zoneOffset = -zoneOffset
+			default:
+				err = errBad
+			}
+		case stdTZ:
+			// Does it look like a time zone?
+			if len(value) >= 3 && value[0:3] == "UTC" {
+				z = UTC
+				value = value[3:]
+				break
+			}
+			n, ok := parseTimeZone(value)
+			if !ok {
+				err = errBad
+				break
+			}
+			zoneName, value = value[:n], value[n:]
+
+		case stdFracSecond0:
+			// stdFracSecond0 requires the exact number of digits as specified in
+			// the layout.
+			ndigit := 1 + (std >> stdArgShift)
+			if len(value) < ndigit {
+				err = errBad
+				break
+			}
+			nsec, rangeErrString, err = parseNanoseconds(value, ndigit)
+			value = value[ndigit:]
+
+		case stdFracSecond9:
+			if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] {
+				// Fractional second omitted.
+				break
+			}
+			// Take any number of digits, even more than asked for,
+			// because it is what the stdSecond case would do.
+			i := 0
+			for i < 9 && i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' {
+				i++
+			}
+			nsec, rangeErrString, err = parseNanoseconds(value, 1+i)
+			value = value[1+i:]
+		}
+		if rangeErrString != "" {
+			return Time{}, &ParseError{alayout, avalue, stdstr, value, ": " + rangeErrString + " out of range"}
+		}
+		if err != nil {
+			return Time{}, &ParseError{alayout, avalue, stdstr, value, ""}
+		}
+	}
+	if pmSet && hour < 12 {
+		hour += 12
+	} else if amSet && hour == 12 {
+		hour = 0
+	}
+
+	if z != nil {
+		return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
+	}
+
+	if zoneOffset != -1 {
+		t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
+		t.sec -= int64(zoneOffset)
+
+		// Look for local zone with the given offset.
+		// If that zone was in effect at the given time, use it.
+		name, offset, _, _, _ := local.lookup(t.sec + internalToUnix)
+		if offset == zoneOffset && (zoneName == "" || name == zoneName) {
+			t.loc = local
+			return t, nil
+		}
+
+		// Otherwise create fake zone to record offset.
+		t.loc = FixedZone(zoneName, zoneOffset)
+		return t, nil
+	}
+
+	if zoneName != "" {
+		t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
+		// Look for local zone with the given offset.
+		// If that zone was in effect at the given time, use it.
+		offset, _, ok := local.lookupName(zoneName, t.sec+internalToUnix)
+		if ok {
+			t.sec -= int64(offset)
+			t.loc = local
+			return t, nil
+		}
+
+		// Otherwise, create fake zone with unknown offset.
+		if len(zoneName) > 3 && zoneName[:3] == "GMT" {
+			offset, _ = atoi(zoneName[3:]) // Guaranteed OK by parseGMT.
+			offset *= 3600
+		}
+		t.loc = FixedZone(zoneName, offset)
+		return t, nil
+	}
+
+	// Otherwise, fall back to default.
+	return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
+}
+
+// parseTimeZone parses a time zone string and returns its length. Time zones
+// are human-generated and unpredictable. We can't do precise error checking.
+// On the other hand, for a correct parse there must be a time zone at the
+// beginning of the string, so it's almost always true that there's one
+// there. We look at the beginning of the string for a run of upper-case letters.
+// If there are more than 5, it's an error.
+// If there are 4 or 5 and the last is a T, it's a time zone.
+// If there are 3, it's a time zone.
+// Otherwise, other than special cases, it's not a time zone.
+// GMT is special because it can have an hour offset.
+func parseTimeZone(value string) (length int, ok bool) {
+	if len(value) < 3 {
+		return 0, false
+	}
+	// Special case 1: ChST and MeST are the only zones with a lower-case letter.
+	if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST") {
+		return 4, true
+	}
+	// Special case 2: GMT may have an hour offset; treat it specially.
+	if value[:3] == "GMT" {
+		length = parseGMT(value)
+		return length, true
+	}
+	// How many upper-case letters are there? Need at least three, at most five.
+	var nUpper int
+	for nUpper = 0; nUpper < 6; nUpper++ {
+		if nUpper >= len(value) {
+			break
+		}
+		if c := value[nUpper]; c < 'A' || 'Z' < c {
+			break
+		}
+	}
+	switch nUpper {
+	case 0, 1, 2, 6:
+		return 0, false
+	case 5: // Must end in T to match.
+		if value[4] == 'T' {
+			return 5, true
+		}
+	case 4: // Must end in T to match.
+		if value[3] == 'T' {
+			return 4, true
+		}
+	case 3:
+		return 3, true
+	}
+	return 0, false
+}
+
+// parseGMT parses a GMT time zone. The input string is known to start "GMT".
+// The function checks whether that is followed by a sign and a number in the
+// range -14 through 12 excluding zero.
+func parseGMT(value string) int {
+	value = value[3:]
+	if len(value) == 0 {
+		return 3
+	}
+	sign := value[0]
+	if sign != '-' && sign != '+' {
+		return 3
+	}
+	x, rem, err := leadingInt(value[1:])
+	if err != nil {
+		return 3
+	}
+	if sign == '-' {
+		x = -x
+	}
+	if x == 0 || x < -14 || 12 < x {
+		return 3
+	}
+	return 3 + len(value) - len(rem)
+}
+
+func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
+	if value[0] != '.' {
+		err = errBad
+		return
+	}
+	if ns, err = atoi(value[1:nbytes]); err != nil {
+		return
+	}
+	if ns < 0 || 1e9 <= ns {
+		rangeErrString = "fractional second"
+		return
+	}
+	// We need nanoseconds, which means scaling by the number
+	// of missing digits in the format, maximum length 10. If it's
+	// longer than 10, we won't scale.
+	scaleDigits := 10 - nbytes
+	for i := 0; i < scaleDigits; i++ {
+		ns *= 10
+	}
+	return
+}
+
+var errLeadingInt = errors.New("time: bad [0-9]*") // never printed
+
+// leadingInt consumes the leading [0-9]* from s.
+func leadingInt(s string) (x int64, rem string, err error) {
+	i := 0
+	for ; i < len(s); i++ {
+		c := s[i]
+		if c < '0' || c > '9' {
+			break
+		}
+		if x >= (1<<63-10)/10 {
+			// overflow
+			return 0, "", errLeadingInt
+		}
+		x = x*10 + int64(c) - '0'
+	}
+	return x, s[i:], nil
+}
+
+var unitMap = map[string]float64{
+	"ns": float64(Nanosecond),
+	"us": float64(Microsecond),
+	"µs": float64(Microsecond), // U+00B5 = micro symbol
+	"μs": float64(Microsecond), // U+03BC = Greek letter mu
+	"ms": float64(Millisecond),
+	"s":  float64(Second),
+	"m":  float64(Minute),
+	"h":  float64(Hour),
+}
+
+// ParseDuration parses a duration string.
+// A duration string is a possibly signed sequence of
+// decimal numbers, each with optional fraction and a unit suffix,
+// such as "300ms", "-1.5h" or "2h45m".
+// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
+func ParseDuration(s string) (Duration, error) {
+	// [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
+	orig := s
+	f := float64(0)
+	neg := false
+
+	// Consume [-+]?
+	if s != "" {
+		c := s[0]
+		if c == '-' || c == '+' {
+			neg = c == '-'
+			s = s[1:]
+		}
+	}
+	// Special case: if all that is left is "0", this is zero.
+	if s == "0" {
+		return 0, nil
+	}
+	if s == "" {
+		return 0, errors.New("time: invalid duration " + orig)
+	}
+	for s != "" {
+		g := float64(0) // this element of the sequence
+
+		var x int64
+		var err error
+
+		// The next character must be [0-9.]
+		if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
+			return 0, errors.New("time: invalid duration " + orig)
+		}
+		// Consume [0-9]*
+		pl := len(s)
+		x, s, err = leadingInt(s)
+		if err != nil {
+			return 0, errors.New("time: invalid duration " + orig)
+		}
+		g = float64(x)
+		pre := pl != len(s) // whether we consumed anything before a period
+
+		// Consume (\.[0-9]*)?
+		post := false
+		if s != "" && s[0] == '.' {
+			s = s[1:]
+			pl := len(s)
+			x, s, err = leadingInt(s)
+			if err != nil {
+				return 0, errors.New("time: invalid duration " + orig)
+			}
+			scale := 1.0
+			for n := pl - len(s); n > 0; n-- {
+				scale *= 10
+			}
+			g += float64(x) / scale
+			post = pl != len(s)
+		}
+		if !pre && !post {
+			// no digits (e.g. ".s" or "-.s")
+			return 0, errors.New("time: invalid duration " + orig)
+		}
+
+		// Consume unit.
+		i := 0
+		for ; i < len(s); i++ {
+			c := s[i]
+			if c == '.' || ('0' <= c && c <= '9') {
+				break
+			}
+		}
+		if i == 0 {
+			return 0, errors.New("time: missing unit in duration " + orig)
+		}
+		u := s[:i]
+		s = s[i:]
+		unit, ok := unitMap[u]
+		if !ok {
+			return 0, errors.New("time: unknown unit " + u + " in duration " + orig)
+		}
+
+		f += g * unit
+	}
+
+	if neg {
+		f = -f
+	}
+	if f < float64(-1<<63) || f > float64(1<<63-1) {
+		return 0, errors.New("time: overflow parsing duration")
+	}
+	return Duration(f), nil
+}
diff --git a/third_party/gofrontend/libgo/go/time/format_test.go b/third_party/gofrontend/libgo/go/time/format_test.go
new file mode 100644
index 0000000..01717ca
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/format_test.go
@@ -0,0 +1,519 @@
+// 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 time_test
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+	"testing"
+	"testing/quick"
+	. "time"
+)
+
+type TimeFormatTest struct {
+	time           Time
+	formattedValue string
+}
+
+var rfc3339Formats = []TimeFormatTest{
+	{Date(2008, 9, 17, 20, 4, 26, 0, UTC), "2008-09-17T20:04:26Z"},
+	{Date(1994, 9, 17, 20, 4, 26, 0, FixedZone("EST", -18000)), "1994-09-17T20:04:26-05:00"},
+	{Date(2000, 12, 26, 1, 15, 6, 0, FixedZone("OTO", 15600)), "2000-12-26T01:15:06+04:20"},
+}
+
+func TestRFC3339Conversion(t *testing.T) {
+	for _, f := range rfc3339Formats {
+		if f.time.Format(RFC3339) != f.formattedValue {
+			t.Error("RFC3339:")
+			t.Errorf("  want=%+v", f.formattedValue)
+			t.Errorf("  have=%+v", f.time.Format(RFC3339))
+		}
+	}
+}
+
+type FormatTest struct {
+	name   string
+	format string
+	result string
+}
+
+var formatTests = []FormatTest{
+	{"ANSIC", ANSIC, "Wed Feb  4 21:00:57 2009"},
+	{"UnixDate", UnixDate, "Wed Feb  4 21:00:57 PST 2009"},
+	{"RubyDate", RubyDate, "Wed Feb 04 21:00:57 -0800 2009"},
+	{"RFC822", RFC822, "04 Feb 09 21:00 PST"},
+	{"RFC850", RFC850, "Wednesday, 04-Feb-09 21:00:57 PST"},
+	{"RFC1123", RFC1123, "Wed, 04 Feb 2009 21:00:57 PST"},
+	{"RFC1123Z", RFC1123Z, "Wed, 04 Feb 2009 21:00:57 -0800"},
+	{"RFC3339", RFC3339, "2009-02-04T21:00:57-08:00"},
+	{"RFC3339Nano", RFC3339Nano, "2009-02-04T21:00:57.0123456-08:00"},
+	{"Kitchen", Kitchen, "9:00PM"},
+	{"am/pm", "3pm", "9pm"},
+	{"AM/PM", "3PM", "9PM"},
+	{"two-digit year", "06 01 02", "09 02 04"},
+	// Three-letter months and days must not be followed by lower-case letter.
+	{"Janet", "Hi Janet, the Month is January", "Hi Janet, the Month is February"},
+	// Time stamps, Fractional seconds.
+	{"Stamp", Stamp, "Feb  4 21:00:57"},
+	{"StampMilli", StampMilli, "Feb  4 21:00:57.012"},
+	{"StampMicro", StampMicro, "Feb  4 21:00:57.012345"},
+	{"StampNano", StampNano, "Feb  4 21:00:57.012345600"},
+}
+
+func TestFormat(t *testing.T) {
+	// The numeric time represents Thu Feb  4 21:00:57.012345600 PST 2010
+	time := Unix(0, 1233810057012345600)
+	for _, test := range formatTests {
+		result := time.Format(test.format)
+		if result != test.result {
+			t.Errorf("%s expected %q got %q", test.name, test.result, result)
+		}
+	}
+}
+
+func TestFormatShortYear(t *testing.T) {
+	years := []int{
+		-100001, -100000, -99999,
+		-10001, -10000, -9999,
+		-1001, -1000, -999,
+		-101, -100, -99,
+		-11, -10, -9,
+		-1, 0, 1,
+		9, 10, 11,
+		99, 100, 101,
+		999, 1000, 1001,
+		9999, 10000, 10001,
+		99999, 100000, 100001,
+	}
+
+	for _, y := range years {
+		time := Date(y, January, 1, 0, 0, 0, 0, UTC)
+		result := time.Format("2006.01.02")
+		var want string
+		if y < 0 {
+			// The 4 in %04d counts the - sign, so print -y instead
+			// and introduce our own - sign.
+			want = fmt.Sprintf("-%04d.%02d.%02d", -y, 1, 1)
+		} else {
+			want = fmt.Sprintf("%04d.%02d.%02d", y, 1, 1)
+		}
+		if result != want {
+			t.Errorf("(jan 1 %d).Format(\"2006.01.02\") = %q, want %q", y, result, want)
+		}
+	}
+}
+
+type ParseTest struct {
+	name       string
+	format     string
+	value      string
+	hasTZ      bool // contains a time zone
+	hasWD      bool // contains a weekday
+	yearSign   int  // sign of year, -1 indicates the year is not present in the format
+	fracDigits int  // number of digits of fractional second
+}
+
+var parseTests = []ParseTest{
+	{"ANSIC", ANSIC, "Thu Feb  4 21:00:57 2010", false, true, 1, 0},
+	{"UnixDate", UnixDate, "Thu Feb  4 21:00:57 PST 2010", true, true, 1, 0},
+	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
+	{"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57 PST", true, true, 1, 0},
+	{"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57 PST", true, true, 1, 0},
+	{"RFC1123", RFC1123, "Thu, 04 Feb 2010 22:00:57 PDT", true, true, 1, 0},
+	{"RFC1123Z", RFC1123Z, "Thu, 04 Feb 2010 21:00:57 -0800", true, true, 1, 0},
+	{"RFC3339", RFC3339, "2010-02-04T21:00:57-08:00", true, false, 1, 0},
+	{"custom: \"2006-01-02 15:04:05-07\"", "2006-01-02 15:04:05-07", "2010-02-04 21:00:57-08", true, false, 1, 0},
+	// Optional fractional seconds.
+	{"ANSIC", ANSIC, "Thu Feb  4 21:00:57.0 2010", false, true, 1, 1},
+	{"UnixDate", UnixDate, "Thu Feb  4 21:00:57.01 PST 2010", true, true, 1, 2},
+	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57.012 -0800 2010", true, true, 1, 3},
+	{"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57.0123 PST", true, true, 1, 4},
+	{"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57.01234 PST", true, true, 1, 5},
+	{"RFC1123Z", RFC1123Z, "Thu, 04 Feb 2010 21:00:57.01234 -0800", true, true, 1, 5},
+	{"RFC3339", RFC3339, "2010-02-04T21:00:57.012345678-08:00", true, false, 1, 9},
+	{"custom: \"2006-01-02 15:04:05\"", "2006-01-02 15:04:05", "2010-02-04 21:00:57.0", false, false, 1, 0},
+	// Amount of white space should not matter.
+	{"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0},
+	{"ANSIC", ANSIC, "Thu      Feb     4     21:00:57     2010", false, true, 1, 0},
+	// Case should not matter
+	{"ANSIC", ANSIC, "THU FEB 4 21:00:57 2010", false, true, 1, 0},
+	{"ANSIC", ANSIC, "thu feb 4 21:00:57 2010", false, true, 1, 0},
+	// Fractional seconds.
+	{"millisecond", "Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 21:00:57.012 2010", false, true, 1, 3},
+	{"microsecond", "Mon Jan _2 15:04:05.000000 2006", "Thu Feb  4 21:00:57.012345 2010", false, true, 1, 6},
+	{"nanosecond", "Mon Jan _2 15:04:05.000000000 2006", "Thu Feb  4 21:00:57.012345678 2010", false, true, 1, 9},
+	// Leading zeros in other places should not be taken as fractional seconds.
+	{"zero1", "2006.01.02.15.04.05.0", "2010.02.04.21.00.57.0", false, false, 1, 1},
+	{"zero2", "2006.01.02.15.04.05.00", "2010.02.04.21.00.57.01", false, false, 1, 2},
+	// Month and day names only match when not followed by a lower-case letter.
+	{"Janet", "Hi Janet, the Month is January: Jan _2 15:04:05 2006", "Hi Janet, the Month is February: Feb  4 21:00:57 2010", false, true, 1, 0},
+
+	// GMT with offset.
+	{"GMT-8", UnixDate, "Fri Feb  5 05:00:57 GMT-8 2010", true, true, 1, 0},
+
+	// Accept any number of fractional second digits (including none) for .999...
+	// In Go 1, .999... was completely ignored in the format, meaning the first two
+	// cases would succeed, but the next four would not. Go 1.1 accepts all six.
+	{"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
+	{"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
+	{"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
+	{"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
+	{"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
+	{"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
+
+	// issue 4502.
+	{"", StampNano, "Feb  4 21:00:57.012345678", false, false, -1, 9},
+	{"", "Jan _2 15:04:05.999", "Feb  4 21:00:57.012300000", false, false, -1, 4},
+	{"", "Jan _2 15:04:05.999", "Feb  4 21:00:57.012345678", false, false, -1, 9},
+	{"", "Jan _2 15:04:05.999999999", "Feb  4 21:00:57.0123", false, false, -1, 4},
+	{"", "Jan _2 15:04:05.999999999", "Feb  4 21:00:57.012345678", false, false, -1, 9},
+}
+
+func TestParse(t *testing.T) {
+	for _, test := range parseTests {
+		time, err := Parse(test.format, test.value)
+		if err != nil {
+			t.Errorf("%s error: %v", test.name, err)
+		} else {
+			checkTime(time, &test, t)
+		}
+	}
+}
+
+func TestParseInLocation(t *testing.T) {
+	// Check that Parse (and ParseInLocation) understand that
+	// Feb 01 AST (Arabia Standard Time) and Feb 01 AST (Atlantic Standard Time)
+	// are in different time zones even though both are called AST
+
+	baghdad, err := LoadLocation("Asia/Baghdad")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	t1, err := ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", baghdad)
+	if err != nil {
+		t.Fatal(err)
+	}
+	t2 := Date(2013, February, 1, 00, 00, 00, 0, baghdad)
+	if t1 != t2 {
+		t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad) = %v, want %v", t1, t2)
+	}
+	_, offset := t1.Zone()
+	if offset != 3*60*60 {
+		t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad).Zone = _, %d, want _, %d", offset, 3*60*60)
+	}
+
+	blancSablon, err := LoadLocation("America/Blanc-Sablon")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	t1, err = ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", blancSablon)
+	if err != nil {
+		t.Fatal(err)
+	}
+	t2 = Date(2013, February, 1, 00, 00, 00, 0, blancSablon)
+	if t1 != t2 {
+		t.Fatalf("ParseInLocation(Feb 01 2013 AST, Blanc-Sablon) = %v, want %v", t1, t2)
+	}
+	_, offset = t1.Zone()
+	if offset != -4*60*60 {
+		t.Fatalf("ParseInLocation(Feb 01 2013 AST, Blanc-Sablon).Zone = _, %d, want _, %d", offset, -4*60*60)
+	}
+}
+
+func TestLoadLocationZipFile(t *testing.T) {
+	t.Skip("gccgo does not use the zip file")
+
+	ForceZipFileForTesting(true)
+	defer ForceZipFileForTesting(false)
+
+	_, err := LoadLocation("Australia/Sydney")
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+var rubyTests = []ParseTest{
+	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
+	// Ignore the time zone in the test. If it parses, it'll be OK.
+	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0000 2010", false, true, 1, 0},
+	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 +0000 2010", false, true, 1, 0},
+	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 +1130 2010", false, true, 1, 0},
+}
+
+// Problematic time zone format needs special tests.
+func TestRubyParse(t *testing.T) {
+	for _, test := range rubyTests {
+		time, err := Parse(test.format, test.value)
+		if err != nil {
+			t.Errorf("%s error: %v", test.name, err)
+		} else {
+			checkTime(time, &test, t)
+		}
+	}
+}
+
+func checkTime(time Time, test *ParseTest, t *testing.T) {
+	// The time should be Thu Feb  4 21:00:57 PST 2010
+	if test.yearSign >= 0 && test.yearSign*time.Year() != 2010 {
+		t.Errorf("%s: bad year: %d not %d", test.name, time.Year(), 2010)
+	}
+	if time.Month() != February {
+		t.Errorf("%s: bad month: %s not %s", test.name, time.Month(), February)
+	}
+	if time.Day() != 4 {
+		t.Errorf("%s: bad day: %d not %d", test.name, time.Day(), 4)
+	}
+	if time.Hour() != 21 {
+		t.Errorf("%s: bad hour: %d not %d", test.name, time.Hour(), 21)
+	}
+	if time.Minute() != 0 {
+		t.Errorf("%s: bad minute: %d not %d", test.name, time.Minute(), 0)
+	}
+	if time.Second() != 57 {
+		t.Errorf("%s: bad second: %d not %d", test.name, time.Second(), 57)
+	}
+	// Nanoseconds must be checked against the precision of the input.
+	nanosec, err := strconv.ParseUint("012345678"[:test.fracDigits]+"000000000"[:9-test.fracDigits], 10, 0)
+	if err != nil {
+		panic(err)
+	}
+	if time.Nanosecond() != int(nanosec) {
+		t.Errorf("%s: bad nanosecond: %d not %d", test.name, time.Nanosecond(), nanosec)
+	}
+	name, offset := time.Zone()
+	if test.hasTZ && offset != -28800 {
+		t.Errorf("%s: bad tz offset: %s %d not %d", test.name, name, offset, -28800)
+	}
+	if test.hasWD && time.Weekday() != Thursday {
+		t.Errorf("%s: bad weekday: %s not %s", test.name, time.Weekday(), Thursday)
+	}
+}
+
+func TestFormatAndParse(t *testing.T) {
+	const fmt = "Mon MST " + RFC3339 // all fields
+	f := func(sec int64) bool {
+		t1 := Unix(sec, 0)
+		if t1.Year() < 1000 || t1.Year() > 9999 {
+			// not required to work
+			return true
+		}
+		t2, err := Parse(fmt, t1.Format(fmt))
+		if err != nil {
+			t.Errorf("error: %s", err)
+			return false
+		}
+		if t1.Unix() != t2.Unix() || t1.Nanosecond() != t2.Nanosecond() {
+			t.Errorf("FormatAndParse %d: %q(%d) %q(%d)", sec, t1, t1.Unix(), t2, t2.Unix())
+			return false
+		}
+		return true
+	}
+	f32 := func(sec int32) bool { return f(int64(sec)) }
+	cfg := &quick.Config{MaxCount: 10000}
+
+	// Try a reasonable date first, then the huge ones.
+	if err := quick.Check(f32, cfg); err != nil {
+		t.Fatal(err)
+	}
+	if err := quick.Check(f, cfg); err != nil {
+		t.Fatal(err)
+	}
+}
+
+type ParseTimeZoneTest struct {
+	value  string
+	length int
+	ok     bool
+}
+
+var parseTimeZoneTests = []ParseTimeZoneTest{
+	{"gmt hi there", 0, false},
+	{"GMT hi there", 3, true},
+	{"GMT+12 hi there", 6, true},
+	{"GMT+00 hi there", 3, true}, // 0 or 00 is not a legal offset.
+	{"GMT-5 hi there", 5, true},
+	{"GMT-51 hi there", 3, true},
+	{"ChST hi there", 4, true},
+	{"MeST hi there", 4, true},
+	{"MSDx", 3, true},
+	{"MSDY", 0, false}, // four letters must end in T.
+	{"ESAST hi", 5, true},
+	{"ESASTT hi", 0, false}, // run of upper-case letters too long.
+	{"ESATY hi", 0, false},  // five letters must end in T.
+}
+
+func TestParseTimeZone(t *testing.T) {
+	for _, test := range parseTimeZoneTests {
+		length, ok := ParseTimeZone(test.value)
+		if ok != test.ok {
+			t.Errorf("expected %t for %q got %t", test.ok, test.value, ok)
+		} else if length != test.length {
+			t.Errorf("expected %d for %q got %d", test.length, test.value, length)
+		}
+	}
+}
+
+type ParseErrorTest struct {
+	format string
+	value  string
+	expect string // must appear within the error
+}
+
+var parseErrorTests = []ParseErrorTest{
+	{ANSIC, "Feb  4 21:00:60 2010", "cannot parse"}, // cannot parse Feb as Mon
+	{ANSIC, "Thu Feb  4 21:00:57 @2010", "cannot parse"},
+	{ANSIC, "Thu Feb  4 21:00:60 2010", "second out of range"},
+	{ANSIC, "Thu Feb  4 21:61:57 2010", "minute out of range"},
+	{ANSIC, "Thu Feb  4 24:00:60 2010", "hour out of range"},
+	{"Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 23:00:59x01 2010", "cannot parse"},
+	{"Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 23:00:59.xxx 2010", "cannot parse"},
+	{"Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 23:00:59.-123 2010", "fractional second out of range"},
+	// issue 4502. StampNano requires exactly 9 digits of precision.
+	{StampNano, "Dec  7 11:22:01.000000", `cannot parse ".000000" as ".000000000"`},
+	{StampNano, "Dec  7 11:22:01.0000000000", "extra text: 0"},
+	// issue 4493. Helpful errors.
+	{RFC3339, "2006-01-02T15:04:05Z07:00", `parsing time "2006-01-02T15:04:05Z07:00": extra text: 07:00`},
+	{RFC3339, "2006-01-02T15:04_abc", `parsing time "2006-01-02T15:04_abc" as "2006-01-02T15:04:05Z07:00": cannot parse "_abc" as ":"`},
+	{RFC3339, "2006-01-02T15:04:05_abc", `parsing time "2006-01-02T15:04:05_abc" as "2006-01-02T15:04:05Z07:00": cannot parse "_abc" as "Z07:00"`},
+	{RFC3339, "2006-01-02T15:04:05Z_abc", `parsing time "2006-01-02T15:04:05Z_abc": extra text: _abc`},
+}
+
+func TestParseErrors(t *testing.T) {
+	for _, test := range parseErrorTests {
+		_, err := Parse(test.format, test.value)
+		if err == nil {
+			t.Errorf("expected error for %q %q", test.format, test.value)
+		} else if strings.Index(err.Error(), test.expect) < 0 {
+			t.Errorf("expected error with %q for %q %q; got %s", test.expect, test.format, test.value, err)
+		}
+	}
+}
+
+func TestNoonIs12PM(t *testing.T) {
+	noon := Date(0, January, 1, 12, 0, 0, 0, UTC)
+	const expect = "12:00PM"
+	got := noon.Format("3:04PM")
+	if got != expect {
+		t.Errorf("got %q; expect %q", got, expect)
+	}
+	got = noon.Format("03:04PM")
+	if got != expect {
+		t.Errorf("got %q; expect %q", got, expect)
+	}
+}
+
+func TestMidnightIs12AM(t *testing.T) {
+	midnight := Date(0, January, 1, 0, 0, 0, 0, UTC)
+	expect := "12:00AM"
+	got := midnight.Format("3:04PM")
+	if got != expect {
+		t.Errorf("got %q; expect %q", got, expect)
+	}
+	got = midnight.Format("03:04PM")
+	if got != expect {
+		t.Errorf("got %q; expect %q", got, expect)
+	}
+}
+
+func Test12PMIsNoon(t *testing.T) {
+	noon, err := Parse("3:04PM", "12:00PM")
+	if err != nil {
+		t.Fatal("error parsing date:", err)
+	}
+	if noon.Hour() != 12 {
+		t.Errorf("got %d; expect 12", noon.Hour())
+	}
+	noon, err = Parse("03:04PM", "12:00PM")
+	if err != nil {
+		t.Fatal("error parsing date:", err)
+	}
+	if noon.Hour() != 12 {
+		t.Errorf("got %d; expect 12", noon.Hour())
+	}
+}
+
+func Test12AMIsMidnight(t *testing.T) {
+	midnight, err := Parse("3:04PM", "12:00AM")
+	if err != nil {
+		t.Fatal("error parsing date:", err)
+	}
+	if midnight.Hour() != 0 {
+		t.Errorf("got %d; expect 0", midnight.Hour())
+	}
+	midnight, err = Parse("03:04PM", "12:00AM")
+	if err != nil {
+		t.Fatal("error parsing date:", err)
+	}
+	if midnight.Hour() != 0 {
+		t.Errorf("got %d; expect 0", midnight.Hour())
+	}
+}
+
+// Check that a time without a Zone still produces a (numeric) time zone
+// when formatted with MST as a requested zone.
+func TestMissingZone(t *testing.T) {
+	time, err := Parse(RubyDate, "Thu Feb 02 16:10:03 -0500 2006")
+	if err != nil {
+		t.Fatal("error parsing date:", err)
+	}
+	expect := "Thu Feb  2 16:10:03 -0500 2006" // -0500 not EST
+	str := time.Format(UnixDate)               // uses MST as its time zone
+	if str != expect {
+		t.Errorf("got %s; expect %s", str, expect)
+	}
+}
+
+func TestMinutesInTimeZone(t *testing.T) {
+	time, err := Parse(RubyDate, "Mon Jan 02 15:04:05 +0123 2006")
+	if err != nil {
+		t.Fatal("error parsing date:", err)
+	}
+	expected := (1*60 + 23) * 60
+	_, offset := time.Zone()
+	if offset != expected {
+		t.Errorf("ZoneOffset = %d, want %d", offset, expected)
+	}
+}
+
+type SecondsTimeZoneOffsetTest struct {
+	format         string
+	value          string
+	expectedoffset int
+}
+
+var secondsTimeZoneOffsetTests = []SecondsTimeZoneOffsetTest{
+	{"2006-01-02T15:04:05-070000", "1871-01-01T05:33:02-003408", -(34*60 + 8)},
+	{"2006-01-02T15:04:05-07:00:00", "1871-01-01T05:33:02-00:34:08", -(34*60 + 8)},
+	{"2006-01-02T15:04:05-070000", "1871-01-01T05:33:02+003408", 34*60 + 8},
+	{"2006-01-02T15:04:05-07:00:00", "1871-01-01T05:33:02+00:34:08", 34*60 + 8},
+	{"2006-01-02T15:04:05Z070000", "1871-01-01T05:33:02-003408", -(34*60 + 8)},
+	{"2006-01-02T15:04:05Z07:00:00", "1871-01-01T05:33:02+00:34:08", 34*60 + 8},
+}
+
+func TestParseSecondsInTimeZone(t *testing.T) {
+	// should accept timezone offsets with seconds like: Zone America/New_York   -4:56:02 -      LMT     1883 Nov 18 12:03:58
+	for _, test := range secondsTimeZoneOffsetTests {
+		time, err := Parse(test.format, test.value)
+		if err != nil {
+			t.Fatal("error parsing date:", err)
+		}
+		_, offset := time.Zone()
+		if offset != test.expectedoffset {
+			t.Errorf("ZoneOffset = %d, want %d", offset, test.expectedoffset)
+		}
+	}
+}
+
+func TestFormatSecondsInTimeZone(t *testing.T) {
+	d := Date(1871, 9, 17, 20, 4, 26, 0, FixedZone("LMT", -(34*60+8)))
+	timestr := d.Format("2006-01-02T15:04:05Z070000")
+	expected := "1871-09-17T20:04:26-003408"
+	if timestr != expected {
+		t.Errorf("Got %s, want %s", timestr, expected)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/time/genzabbrs.go b/third_party/gofrontend/libgo/go/time/genzabbrs.go
new file mode 100644
index 0000000..7c637cb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/genzabbrs.go
@@ -0,0 +1,145 @@
+// Copyright 2013 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.
+
+// +build ignore
+
+//
+// usage:
+//
+// go run genzabbrs.go | gofmt > $GOROOT/src/pkg/time/zoneinfo_abbrs_windows.go
+//
+
+package main
+
+import (
+	"encoding/xml"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"os"
+	"sort"
+	"text/template"
+	"time"
+)
+
+// getAbbrs finds timezone abbreviations (standard and daylight saving time)
+// for location l.
+func getAbbrs(l *time.Location) (st, dt string) {
+	t := time.Date(time.Now().Year(), 0, 0, 0, 0, 0, 0, l)
+	abbr1, off1 := t.Zone()
+	for i := 0; i < 12; i++ {
+		t = t.AddDate(0, 1, 0)
+		abbr2, off2 := t.Zone()
+		if abbr1 != abbr2 {
+			if off2-off1 < 0 { // southern hemisphere
+				abbr1, abbr2 = abbr2, abbr1
+			}
+			return abbr1, abbr2
+		}
+	}
+	return abbr1, abbr1
+}
+
+type zone struct {
+	WinName  string
+	UnixName string
+	StTime   string
+	DSTime   string
+}
+
+type zones []*zone
+
+func (zs zones) Len() int           { return len(zs) }
+func (zs zones) Swap(i, j int)      { zs[i], zs[j] = zs[j], zs[i] }
+func (zs zones) Less(i, j int) bool { return zs[i].UnixName < zs[j].UnixName }
+
+const wzURL = "http://unicode.org/cldr/data/common/supplemental/windowsZones.xml"
+
+type MapZone struct {
+	Other     string `xml:"other,attr"`
+	Territory string `xml:"territory,attr"`
+	Type      string `xml:"type,attr"`
+}
+
+type SupplementalData struct {
+	Zones []MapZone `xml:"windowsZones>mapTimezones>mapZone"`
+}
+
+func readWindowsZones() (zones, error) {
+	r, err := http.Get(wzURL)
+	if err != nil {
+		return nil, err
+	}
+	defer r.Body.Close()
+
+	data, err := ioutil.ReadAll(r.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	var sd SupplementalData
+	err = xml.Unmarshal(data, &sd)
+	if err != nil {
+		return nil, err
+	}
+	zs := make(zones, 0)
+	for _, z := range sd.Zones {
+		if z.Territory != "001" {
+			// to avoid dups. I don't know why.
+			continue
+		}
+		l, err := time.LoadLocation(z.Type)
+		if err != nil {
+			return nil, err
+		}
+		st, dt := getAbbrs(l)
+		zs = append(zs, &zone{
+			WinName:  z.Other,
+			UnixName: z.Type,
+			StTime:   st,
+			DSTime:   dt,
+		})
+	}
+	return zs, nil
+}
+
+func main() {
+	zs, err := readWindowsZones()
+	if err != nil {
+		log.Fatal(err)
+	}
+	sort.Sort(zs)
+	var v = struct {
+		URL string
+		Zs  zones
+	}{
+		wzURL,
+		zs,
+	}
+	err = template.Must(template.New("prog").Parse(prog)).Execute(os.Stdout, v)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+const prog = `
+// Copyright 2013 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.
+
+// generated by genzabbrs.go from
+// {{.URL}}
+
+package time
+
+type abbr struct {
+	std string
+	dst string
+}
+
+var abbrs = map[string]abbr{
+{{range .Zs}}	"{{.WinName}}": {"{{.StTime}}", "{{.DSTime}}"}, // {{.UnixName}}
+{{end}}}
+
+`
diff --git a/third_party/gofrontend/libgo/go/time/internal_test.go b/third_party/gofrontend/libgo/go/time/internal_test.go
new file mode 100644
index 0000000..2243d36
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/internal_test.go
@@ -0,0 +1,92 @@
+// 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.
+
+package time
+
+import (
+	"errors"
+	"runtime"
+)
+
+func init() {
+	// force US/Pacific for time zone tests
+	ForceUSPacificForTesting()
+}
+
+var Interrupt = interrupt
+var DaysIn = daysIn
+
+func empty(now int64, arg interface{}) {}
+
+// Test that a runtimeTimer with a duration so large it overflows
+// does not cause other timers to hang.
+//
+// This test has to be in internal_test.go since it fiddles with
+// unexported data structures.
+func CheckRuntimeTimerOverflow() error {
+	// We manually create a runtimeTimer to bypass the overflow
+	// detection logic in NewTimer: we're testing the underlying
+	// runtime.addtimer function.
+	r := &runtimeTimer{
+		when: runtimeNano() + (1<<63 - 1),
+		f:    empty,
+		arg:  nil,
+	}
+	startTimer(r)
+
+	timeout := 100 * Millisecond
+	switch runtime.GOOS {
+	// Allow more time for gobuilder to succeed.
+	case "windows":
+		timeout = Second
+	case "plan9":
+		// TODO(0intro): We don't know why it is needed.
+		timeout = 3 * Second
+	}
+
+	// Start a goroutine that should send on t.C before the timeout.
+	t := NewTimer(1)
+
+	defer func() {
+		// Subsequent tests won't work correctly if we don't stop the
+		// overflow timer and kick the timer proc back into service.
+		//
+		// The timer proc is now sleeping and can only be awoken by
+		// adding a timer to the *beginning* of the heap. We can't
+		// wake it up by calling NewTimer since other tests may have
+		// left timers running that should have expired before ours.
+		// Instead we zero the overflow timer duration and start it
+		// once more.
+		stopTimer(r)
+		t.Stop()
+		r.when = 0
+		startTimer(r)
+	}()
+
+	// Try to receive from t.C before the timeout. It will succeed
+	// iff the previous sleep was able to finish. We're forced to
+	// spin and yield after trying to receive since we can't start
+	// any more timers (they might hang due to the same bug we're
+	// now testing).
+	stop := Now().Add(timeout)
+	for {
+		select {
+		case <-t.C:
+			return nil // It worked!
+		default:
+			if Now().After(stop) {
+				return errors.New("runtime timer stuck: overflow in addtimer")
+			}
+			// Issue 6874. This test previously called runtime.Gosched to try to yield
+			// to the goroutine servicing t, however the scheduler has a bias towards the
+			// previously running goroutine in an idle system. Combined with high load due
+			// to all CPUs busy running tests t's goroutine could be delayed beyond the
+			// timeout window.
+			//
+			// Calling runtime.GC() reduces the worst case lantency for scheduling t by 20x
+			// under the current Go 1.3 scheduler.
+			runtime.GC()
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/time/sleep.go b/third_party/gofrontend/libgo/go/time/sleep.go
new file mode 100644
index 0000000..6a03f41
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/sleep.go
@@ -0,0 +1,122 @@
+// 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 time
+
+// Sleep pauses the current goroutine for at least the duration d.
+// A negative or zero duration causes Sleep to return immediately.
+func Sleep(d Duration)
+
+// runtimeNano returns the current value of the runtime clock in nanoseconds.
+func runtimeNano() int64
+
+// Interface to timers implemented in package runtime.
+// Must be in sync with ../runtime/runtime.h:/^struct.Timer$
+type runtimeTimer struct {
+	i      int32
+	when   int64
+	period int64
+	f      func(int64, interface{}) // NOTE: must not be closure
+	arg    interface{}
+}
+
+// when is a helper function for setting the 'when' field of a runtimeTimer.
+// It returns what the time will be, in nanoseconds, Duration d in the future.
+// If d is negative, it is ignored.  If the returned value would be less than
+// zero because of an overflow, MaxInt64 is returned.
+func when(d Duration) int64 {
+	if d <= 0 {
+		return runtimeNano()
+	}
+	t := runtimeNano() + int64(d)
+	if t < 0 {
+		t = 1<<63 - 1 // math.MaxInt64
+	}
+	return t
+}
+
+func startTimer(*runtimeTimer)
+func stopTimer(*runtimeTimer) bool
+
+// The Timer type represents a single event.
+// When the Timer expires, the current time will be sent on C,
+// unless the Timer was created by AfterFunc.
+type Timer struct {
+	C <-chan Time
+	r runtimeTimer
+}
+
+// Stop prevents the Timer from firing.
+// It returns true if the call stops the timer, false if the timer has already
+// expired or been stopped.
+// Stop does not close the channel, to prevent a read from the channel succeeding
+// incorrectly.
+func (t *Timer) Stop() bool {
+	return stopTimer(&t.r)
+}
+
+// NewTimer creates a new Timer that will send
+// the current time on its channel after at least duration d.
+func NewTimer(d Duration) *Timer {
+	c := make(chan Time, 1)
+	t := &Timer{
+		C: c,
+		r: runtimeTimer{
+			when: when(d),
+			f:    sendTime,
+			arg:  c,
+		},
+	}
+	startTimer(&t.r)
+	return t
+}
+
+// Reset changes the timer to expire after duration d.
+// It returns true if the timer had been active, false if the timer had
+// expired or been stopped.
+func (t *Timer) Reset(d Duration) bool {
+	w := when(d)
+	active := stopTimer(&t.r)
+	t.r.when = w
+	startTimer(&t.r)
+	return active
+}
+
+func sendTime(now int64, c interface{}) {
+	// Non-blocking send of time on c.
+	// Used in NewTimer, it cannot block anyway (buffer).
+	// Used in NewTicker, dropping sends on the floor is
+	// the desired behavior when the reader gets behind,
+	// because the sends are periodic.
+	select {
+	case c.(chan Time) <- Now():
+	default:
+	}
+}
+
+// After waits for the duration to elapse and then sends the current time
+// on the returned channel.
+// It is equivalent to NewTimer(d).C.
+func After(d Duration) <-chan Time {
+	return NewTimer(d).C
+}
+
+// AfterFunc waits for the duration to elapse and then calls f
+// in its own goroutine. It returns a Timer that can
+// be used to cancel the call using its Stop method.
+func AfterFunc(d Duration, f func()) *Timer {
+	t := &Timer{
+		r: runtimeTimer{
+			when: when(d),
+			f:    goFunc,
+			arg:  f,
+		},
+	}
+	startTimer(&t.r)
+	return t
+}
+
+func goFunc(now int64, arg interface{}) {
+	go arg.(func())()
+}
diff --git a/third_party/gofrontend/libgo/go/time/sleep_test.go b/third_party/gofrontend/libgo/go/time/sleep_test.go
new file mode 100644
index 0000000..7c2dcaf
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/sleep_test.go
@@ -0,0 +1,394 @@
+// 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 time_test
+
+import (
+	"errors"
+	"fmt"
+	"runtime"
+	"sort"
+	"sync"
+	"sync/atomic"
+	"testing"
+	. "time"
+)
+
+func TestSleep(t *testing.T) {
+	const delay = 100 * Millisecond
+	go func() {
+		Sleep(delay / 2)
+		Interrupt()
+	}()
+	start := Now()
+	Sleep(delay)
+	duration := Now().Sub(start)
+	if duration < delay {
+		t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
+	}
+}
+
+// Test the basic function calling behavior. Correct queueing
+// behavior is tested elsewhere, since After and AfterFunc share
+// the same code.
+func TestAfterFunc(t *testing.T) {
+	i := 10
+	c := make(chan bool)
+	var f func()
+	f = func() {
+		i--
+		if i >= 0 {
+			AfterFunc(0, f)
+			Sleep(1 * Second)
+		} else {
+			c <- true
+		}
+	}
+
+	AfterFunc(0, f)
+	<-c
+}
+
+func TestAfterStress(t *testing.T) {
+	stop := uint32(0)
+	go func() {
+		for atomic.LoadUint32(&stop) == 0 {
+			runtime.GC()
+			// Yield so that the OS can wake up the timer thread,
+			// so that it can generate channel sends for the main goroutine,
+			// which will eventually set stop = 1 for us.
+			Sleep(Nanosecond)
+		}
+	}()
+	ticker := NewTicker(1)
+	for i := 0; i < 100; i++ {
+		<-ticker.C
+	}
+	ticker.Stop()
+	atomic.StoreUint32(&stop, 1)
+}
+
+func benchmark(b *testing.B, bench func(n int)) {
+	garbage := make([]*Timer, 1<<17)
+	for i := 0; i < len(garbage); i++ {
+		garbage[i] = AfterFunc(Hour, nil)
+	}
+	b.ResetTimer()
+
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			bench(1000)
+		}
+	})
+
+	b.StopTimer()
+	for i := 0; i < len(garbage); i++ {
+		garbage[i].Stop()
+	}
+}
+
+func BenchmarkAfterFunc(b *testing.B) {
+	benchmark(b, func(n int) {
+		c := make(chan bool)
+		var f func()
+		f = func() {
+			n--
+			if n >= 0 {
+				AfterFunc(0, f)
+			} else {
+				c <- true
+			}
+		}
+
+		AfterFunc(0, f)
+		<-c
+	})
+}
+
+func BenchmarkAfter(b *testing.B) {
+	benchmark(b, func(n int) {
+		for i := 0; i < n; i++ {
+			<-After(1)
+		}
+	})
+}
+
+func BenchmarkStop(b *testing.B) {
+	benchmark(b, func(n int) {
+		for i := 0; i < n; i++ {
+			NewTimer(1 * Second).Stop()
+		}
+	})
+}
+
+func BenchmarkSimultaneousAfterFunc(b *testing.B) {
+	benchmark(b, func(n int) {
+		var wg sync.WaitGroup
+		wg.Add(n)
+		for i := 0; i < n; i++ {
+			AfterFunc(0, wg.Done)
+		}
+		wg.Wait()
+	})
+}
+
+func BenchmarkStartStop(b *testing.B) {
+	benchmark(b, func(n int) {
+		timers := make([]*Timer, n)
+		for i := 0; i < n; i++ {
+			timers[i] = AfterFunc(Hour, nil)
+		}
+
+		for i := 0; i < n; i++ {
+			timers[i].Stop()
+		}
+	})
+}
+
+func TestAfter(t *testing.T) {
+	const delay = 100 * Millisecond
+	start := Now()
+	end := <-After(delay)
+	if duration := Now().Sub(start); duration < delay {
+		t.Fatalf("After(%s) slept for only %d ns", delay, duration)
+	}
+	if min := start.Add(delay); end.Before(min) {
+		t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
+	}
+}
+
+func TestAfterTick(t *testing.T) {
+	const Count = 10
+	Delta := 100 * Millisecond
+	if testing.Short() {
+		Delta = 10 * Millisecond
+	}
+	t0 := Now()
+	for i := 0; i < Count; i++ {
+		<-After(Delta)
+	}
+	t1 := Now()
+	d := t1.Sub(t0)
+	target := Delta * Count
+	if d < target*9/10 {
+		t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target)
+	}
+	if !testing.Short() && d > target*30/10 {
+		t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target)
+	}
+}
+
+func TestAfterStop(t *testing.T) {
+	AfterFunc(100*Millisecond, func() {})
+	t0 := NewTimer(50 * Millisecond)
+	c1 := make(chan bool, 1)
+	t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
+	c2 := After(200 * Millisecond)
+	if !t0.Stop() {
+		t.Fatalf("failed to stop event 0")
+	}
+	if !t1.Stop() {
+		t.Fatalf("failed to stop event 1")
+	}
+	<-c2
+	select {
+	case <-t0.C:
+		t.Fatalf("event 0 was not stopped")
+	case <-c1:
+		t.Fatalf("event 1 was not stopped")
+	default:
+	}
+	if t1.Stop() {
+		t.Fatalf("Stop returned true twice")
+	}
+}
+
+func TestAfterQueuing(t *testing.T) {
+	// This test flakes out on some systems,
+	// so we'll try it a few times before declaring it a failure.
+	const attempts = 3
+	err := errors.New("!=nil")
+	for i := 0; i < attempts && err != nil; i++ {
+		if err = testAfterQueuing(t); err != nil {
+			t.Logf("attempt %v failed: %v", i, err)
+		}
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+// For gccgo omit 0 for now because it can take too long to start the
+var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8 /*0*/}
+
+type afterResult struct {
+	slot int
+	t    Time
+}
+
+func await(slot int, result chan<- afterResult, ac <-chan Time) {
+	result <- afterResult{slot, <-ac}
+}
+
+func testAfterQueuing(t *testing.T) error {
+	Delta := 100 * Millisecond
+	if testing.Short() {
+		Delta = 20 * Millisecond
+	}
+	// make the result channel buffered because we don't want
+	// to depend on channel queueing semantics that might
+	// possibly change in the future.
+	result := make(chan afterResult, len(slots))
+
+	t0 := Now()
+	for _, slot := range slots {
+		go await(slot, result, After(Duration(slot)*Delta))
+	}
+	sort.Ints(slots)
+	for _, slot := range slots {
+		r := <-result
+		if r.slot != slot {
+			return fmt.Errorf("after slot %d, expected %d", r.slot, slot)
+		}
+		dt := r.t.Sub(t0)
+		target := Duration(slot) * Delta
+		if dt < target-Delta/2 || dt > target+Delta*10 {
+			return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-Delta/2, target+Delta*10)
+		}
+	}
+	return nil
+}
+
+func TestTimerStopStress(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+	for i := 0; i < 100; i++ {
+		go func(i int) {
+			timer := AfterFunc(2*Second, func() {
+				t.Fatalf("timer %d was not stopped", i)
+			})
+			Sleep(1 * Second)
+			timer.Stop()
+		}(i)
+	}
+	Sleep(3 * Second)
+}
+
+func TestSleepZeroDeadlock(t *testing.T) {
+	// Sleep(0) used to hang, the sequence of events was as follows.
+	// Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
+	// Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
+	// After the GC nobody wakes up the goroutine from Gwaiting status.
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	c := make(chan bool)
+	go func() {
+		for i := 0; i < 100; i++ {
+			runtime.GC()
+		}
+		c <- true
+	}()
+	for i := 0; i < 100; i++ {
+		Sleep(0)
+		tmp := make(chan bool, 1)
+		tmp <- true
+		<-tmp
+	}
+	<-c
+}
+
+func testReset(d Duration) error {
+	t0 := NewTimer(2 * d)
+	Sleep(d)
+	if t0.Reset(3*d) != true {
+		return errors.New("resetting unfired timer returned false")
+	}
+	Sleep(2 * d)
+	select {
+	case <-t0.C:
+		return errors.New("timer fired early")
+	default:
+	}
+	Sleep(2 * d)
+	select {
+	case <-t0.C:
+	default:
+		return errors.New("reset timer did not fire")
+	}
+
+	if t0.Reset(50*Millisecond) != false {
+		return errors.New("resetting expired timer returned true")
+	}
+	return nil
+}
+
+func TestReset(t *testing.T) {
+	// We try to run this test with increasingly larger multiples
+	// until one works so slow, loaded hardware isn't as flaky,
+	// but without slowing down fast machines unnecessarily.
+	const unit = 25 * Millisecond
+	tries := []Duration{
+		1 * unit,
+		3 * unit,
+		7 * unit,
+		15 * unit,
+	}
+	var err error
+	for _, d := range tries {
+		err = testReset(d)
+		if err == nil {
+			t.Logf("passed using duration %v", d)
+			return
+		}
+	}
+	t.Error(err)
+}
+
+// Test that sleeping for an interval so large it overflows does not
+// result in a short sleep duration.
+func TestOverflowSleep(t *testing.T) {
+	const big = Duration(int64(1<<63 - 1))
+	select {
+	case <-After(big):
+		t.Fatalf("big timeout fired")
+	case <-After(25 * Millisecond):
+		// OK
+	}
+	const neg = Duration(-1 << 63)
+	select {
+	case <-After(neg):
+		// OK
+	case <-After(1 * Second):
+		t.Fatalf("negative timeout didn't fire")
+	}
+}
+
+// Test that a panic while deleting a timer does not leave
+// the timers mutex held, deadlocking a ticker.Stop in a defer.
+func TestIssue5745(t *testing.T) {
+	ticker := NewTicker(Hour)
+	defer func() {
+		// would deadlock here before the fix due to
+		// lock taken before the segfault.
+		ticker.Stop()
+
+		if r := recover(); r == nil {
+			t.Error("Expected panic, but none happened.")
+		}
+	}()
+
+	// cause a panic due to a segfault
+	var timer *Timer
+	timer.Stop()
+	t.Error("Should be unreachable.")
+}
+
+func TestOverflowRuntimeTimer(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode, see issue 6874")
+	}
+	if err := CheckRuntimeTimerOverflow(); err != nil {
+		t.Fatalf(err.Error())
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/time/sys_plan9.go b/third_party/gofrontend/libgo/go/time/sys_plan9.go
new file mode 100644
index 0000000..8484729
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/sys_plan9.go
@@ -0,0 +1,76 @@
+// 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.
+
+// +build plan9
+
+package time
+
+import (
+	"errors"
+	"syscall"
+)
+
+// for testing: whatever interrupts a sleep
+func interrupt() {
+	// cannot predict pid, don't want to kill group
+}
+
+// readFile reads and returns the content of the named file.
+// It is a trivial implementation of ioutil.ReadFile, reimplemented
+// here to avoid depending on io/ioutil or os.
+func readFile(name string) ([]byte, error) {
+	f, err := syscall.Open(name, syscall.O_RDONLY)
+	if err != nil {
+		return nil, err
+	}
+	defer syscall.Close(f)
+	var (
+		buf [4096]byte
+		ret []byte
+		n   int
+	)
+	for {
+		n, err = syscall.Read(f, buf[:])
+		if n > 0 {
+			ret = append(ret, buf[:n]...)
+		}
+		if n == 0 || err != nil {
+			break
+		}
+	}
+	return ret, err
+}
+
+func open(name string) (uintptr, error) {
+	fd, err := syscall.Open(name, syscall.O_RDONLY)
+	if err != nil {
+		return 0, err
+	}
+	return uintptr(fd), nil
+}
+
+func closefd(fd uintptr) {
+	syscall.Close(int(fd))
+}
+
+func preadn(fd uintptr, buf []byte, off int) error {
+	whence := 0
+	if off < 0 {
+		whence = 2
+	}
+	if _, err := syscall.Seek(int(fd), int64(off), whence); err != nil {
+		return err
+	}
+	for len(buf) > 0 {
+		m, err := syscall.Read(int(fd), buf)
+		if m <= 0 {
+			if err == nil {
+				return errors.New("short read")
+			}
+			return err
+		}
+		buf = buf[m:]
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/time/sys_unix.go b/third_party/gofrontend/libgo/go/time/sys_unix.go
new file mode 100644
index 0000000..379e13d
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/sys_unix.go
@@ -0,0 +1,76 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package time
+
+import (
+	"errors"
+	"syscall"
+)
+
+// for testing: whatever interrupts a sleep
+func interrupt() {
+	syscall.Kill(syscall.Getpid(), syscall.SIGCHLD)
+}
+
+// readFile reads and returns the content of the named file.
+// It is a trivial implementation of ioutil.ReadFile, reimplemented
+// here to avoid depending on io/ioutil or os.
+func readFile(name string) ([]byte, error) {
+	f, err := syscall.Open(name, syscall.O_RDONLY, 0)
+	if err != nil {
+		return nil, err
+	}
+	defer syscall.Close(f)
+	var (
+		buf [4096]byte
+		ret []byte
+		n   int
+	)
+	for {
+		n, err = syscall.Read(f, buf[:])
+		if n > 0 {
+			ret = append(ret, buf[:n]...)
+		}
+		if n == 0 || err != nil {
+			break
+		}
+	}
+	return ret, err
+}
+
+func open(name string) (uintptr, error) {
+	fd, err := syscall.Open(name, syscall.O_RDONLY, 0)
+	if err != nil {
+		return 0, err
+	}
+	return uintptr(fd), nil
+}
+
+func closefd(fd uintptr) {
+	syscall.Close(int(fd))
+}
+
+func preadn(fd uintptr, buf []byte, off int) error {
+	whence := 0
+	if off < 0 {
+		whence = 2
+	}
+	if _, err := syscall.Seek(int(fd), int64(off), whence); err != nil {
+		return err
+	}
+	for len(buf) > 0 {
+		m, err := syscall.Read(int(fd), buf)
+		if m <= 0 {
+			if err == nil {
+				return errors.New("short read")
+			}
+			return err
+		}
+		buf = buf[m:]
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/time/sys_windows.go b/third_party/gofrontend/libgo/go/time/sys_windows.go
new file mode 100644
index 0000000..de63b4b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/sys_windows.go
@@ -0,0 +1,73 @@
+// 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.
+
+package time
+
+import (
+	"errors"
+	"syscall"
+)
+
+// for testing: whatever interrupts a sleep
+func interrupt() {
+}
+
+// readFile reads and returns the content of the named file.
+// It is a trivial implementation of ioutil.ReadFile, reimplemented
+// here to avoid depending on io/ioutil or os.
+func readFile(name string) ([]byte, error) {
+	f, err := syscall.Open(name, syscall.O_RDONLY, 0)
+	if err != nil {
+		return nil, err
+	}
+	defer syscall.Close(f)
+	var (
+		buf [4096]byte
+		ret []byte
+		n   int
+	)
+	for {
+		n, err = syscall.Read(f, buf[:])
+		if n > 0 {
+			ret = append(ret, buf[:n]...)
+		}
+		if n == 0 || err != nil {
+			break
+		}
+	}
+	return ret, err
+}
+
+func open(name string) (uintptr, error) {
+	fd, err := syscall.Open(name, syscall.O_RDONLY, 0)
+	if err != nil {
+		return 0, err
+	}
+	return uintptr(fd), nil
+}
+
+func closefd(fd uintptr) {
+	syscall.Close(syscall.Handle(fd))
+}
+
+func preadn(fd uintptr, buf []byte, off int) error {
+	whence := 0
+	if off < 0 {
+		whence = 2
+	}
+	if _, err := syscall.Seek(syscall.Handle(fd), int64(off), whence); err != nil {
+		return err
+	}
+	for len(buf) > 0 {
+		m, err := syscall.Read(syscall.Handle(fd), buf)
+		if m <= 0 {
+			if err == nil {
+				return errors.New("short read")
+			}
+			return err
+		}
+		buf = buf[m:]
+	}
+	return nil
+}
diff --git a/third_party/gofrontend/libgo/go/time/tick.go b/third_party/gofrontend/libgo/go/time/tick.go
new file mode 100644
index 0000000..1900784
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/tick.go
@@ -0,0 +1,56 @@
+// 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 time
+
+import "errors"
+
+// A Ticker holds a channel that delivers `ticks' of a clock
+// at intervals.
+type Ticker struct {
+	C <-chan Time // The channel on which the ticks are delivered.
+	r runtimeTimer
+}
+
+// NewTicker returns a new Ticker containing a channel that will send the
+// time with a period specified by the duration argument.
+// It adjusts the intervals or drops ticks to make up for slow receivers.
+// The duration d must be greater than zero; if not, NewTicker will panic.
+// Stop the ticker to release associated resources.
+func NewTicker(d Duration) *Ticker {
+	if d <= 0 {
+		panic(errors.New("non-positive interval for NewTicker"))
+	}
+	// Give the channel a 1-element time buffer.
+	// If the client falls behind while reading, we drop ticks
+	// on the floor until the client catches up.
+	c := make(chan Time, 1)
+	t := &Ticker{
+		C: c,
+		r: runtimeTimer{
+			when:   when(d),
+			period: int64(d),
+			f:      sendTime,
+			arg:    c,
+		},
+	}
+	startTimer(&t.r)
+	return t
+}
+
+// Stop turns off a ticker.  After Stop, no more ticks will be sent.
+// Stop does not close the channel, to prevent a read from the channel succeeding
+// incorrectly.
+func (t *Ticker) Stop() {
+	stopTimer(&t.r)
+}
+
+// Tick is a convenience wrapper for NewTicker providing access to the ticking
+// channel only.  Useful for clients that have no need to shut down the ticker.
+func Tick(d Duration) <-chan Time {
+	if d <= 0 {
+		return nil
+	}
+	return NewTicker(d).C
+}
diff --git a/third_party/gofrontend/libgo/go/time/tick_test.go b/third_party/gofrontend/libgo/go/time/tick_test.go
new file mode 100644
index 0000000..32f4740
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/tick_test.go
@@ -0,0 +1,78 @@
+// 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 time_test
+
+import (
+	"testing"
+	. "time"
+)
+
+func TestTicker(t *testing.T) {
+	const Count = 10
+	Delta := 100 * Millisecond
+	ticker := NewTicker(Delta)
+	t0 := Now()
+	for i := 0; i < Count; i++ {
+		<-ticker.C
+	}
+	ticker.Stop()
+	t1 := Now()
+	dt := t1.Sub(t0)
+	target := Delta * Count
+	slop := target * 2 / 10
+	if dt < target-slop || (!testing.Short() && dt > target+slop) {
+		t.Fatalf("%d %s ticks took %s, expected [%s,%s]", Count, Delta, dt, target-slop, target+slop)
+	}
+	// Now test that the ticker stopped
+	Sleep(2 * Delta)
+	select {
+	case <-ticker.C:
+		t.Fatal("Ticker did not shut down")
+	default:
+		// ok
+	}
+}
+
+// Test that a bug tearing down a ticker has been fixed.  This routine should not deadlock.
+func TestTeardown(t *testing.T) {
+	Delta := 100 * Millisecond
+	if testing.Short() {
+		Delta = 20 * Millisecond
+	}
+	for i := 0; i < 3; i++ {
+		ticker := NewTicker(Delta)
+		<-ticker.C
+		ticker.Stop()
+	}
+}
+
+// Test the Tick convenience wrapper.
+func TestTick(t *testing.T) {
+	// Test that giving a negative duration returns nil.
+	if got := Tick(-1); got != nil {
+		t.Errorf("Tick(-1) = %v; want nil", got)
+	}
+}
+
+// Test that NewTicker panics when given a duration less than zero.
+func TestNewTickerLtZeroDuration(t *testing.T) {
+	defer func() {
+		if err := recover(); err == nil {
+			t.Errorf("NewTicker(-1) should have panicked")
+		}
+	}()
+	NewTicker(-1)
+}
+
+func BenchmarkTicker(b *testing.B) {
+	ticker := NewTicker(1)
+	b.ResetTimer()
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		<-ticker.C
+	}
+	b.StopTimer()
+	ticker.Stop()
+}
diff --git a/third_party/gofrontend/libgo/go/time/time.go b/third_party/gofrontend/libgo/go/time/time.go
new file mode 100644
index 0000000..0a2b091
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/time.go
@@ -0,0 +1,1206 @@
+// 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 time provides functionality for measuring and displaying time.
+//
+// The calendrical calculations always assume a Gregorian calendar.
+package time
+
+import "errors"
+
+// A Time represents an instant in time with nanosecond precision.
+//
+// Programs using times should typically store and pass them as values,
+// not pointers.  That is, time variables and struct fields should be of
+// type time.Time, not *time.Time.  A Time value can be used by
+// multiple goroutines simultaneously.
+//
+// Time instants can be compared using the Before, After, and Equal methods.
+// The Sub method subtracts two instants, producing a Duration.
+// The Add method adds a Time and a Duration, producing a Time.
+//
+// The zero value of type Time is January 1, year 1, 00:00:00.000000000 UTC.
+// As this time is unlikely to come up in practice, the IsZero method gives
+// a simple way of detecting a time that has not been initialized explicitly.
+//
+// Each Time has associated with it a Location, consulted when computing the
+// presentation form of the time, such as in the Format, Hour, and Year methods.
+// The methods Local, UTC, and In return a Time with a specific location.
+// Changing the location in this way changes only the presentation; it does not
+// change the instant in time being denoted and therefore does not affect the
+// computations described in earlier paragraphs.
+//
+type Time struct {
+	// sec gives the number of seconds elapsed since
+	// January 1, year 1 00:00:00 UTC.
+	sec int64
+
+	// nsec specifies a non-negative nanosecond
+	// offset within the second named by Seconds.
+	// It must be in the range [0, 999999999].
+	//
+	// It is declared as uintptr instead of int32 or uint32
+	// to avoid garbage collector aliasing in the case where
+	// on a 64-bit system the int32 or uint32 field is written
+	// over the low half of a pointer, creating another pointer.
+	// TODO(rsc): When the garbage collector is completely
+	// precise, change back to int32.
+	nsec uintptr
+
+	// loc specifies the Location that should be used to
+	// determine the minute, hour, month, day, and year
+	// that correspond to this Time.
+	// Only the zero Time has a nil Location.
+	// In that case it is interpreted to mean UTC.
+	loc *Location
+}
+
+// After reports whether the time instant t is after u.
+func (t Time) After(u Time) bool {
+	return t.sec > u.sec || t.sec == u.sec && t.nsec > u.nsec
+}
+
+// Before reports whether the time instant t is before u.
+func (t Time) Before(u Time) bool {
+	return t.sec < u.sec || t.sec == u.sec && t.nsec < u.nsec
+}
+
+// Equal reports whether t and u represent the same time instant.
+// Two times can be equal even if they are in different locations.
+// For example, 6:00 +0200 CEST and 4:00 UTC are Equal.
+// This comparison is different from using t == u, which also compares
+// the locations.
+func (t Time) Equal(u Time) bool {
+	return t.sec == u.sec && t.nsec == u.nsec
+}
+
+// A Month specifies a month of the year (January = 1, ...).
+type Month int
+
+const (
+	January Month = 1 + iota
+	February
+	March
+	April
+	May
+	June
+	July
+	August
+	September
+	October
+	November
+	December
+)
+
+var months = [...]string{
+	"January",
+	"February",
+	"March",
+	"April",
+	"May",
+	"June",
+	"July",
+	"August",
+	"September",
+	"October",
+	"November",
+	"December",
+}
+
+// String returns the English name of the month ("January", "February", ...).
+func (m Month) String() string { return months[m-1] }
+
+// A Weekday specifies a day of the week (Sunday = 0, ...).
+type Weekday int
+
+const (
+	Sunday Weekday = iota
+	Monday
+	Tuesday
+	Wednesday
+	Thursday
+	Friday
+	Saturday
+)
+
+var days = [...]string{
+	"Sunday",
+	"Monday",
+	"Tuesday",
+	"Wednesday",
+	"Thursday",
+	"Friday",
+	"Saturday",
+}
+
+// String returns the English name of the day ("Sunday", "Monday", ...).
+func (d Weekday) String() string { return days[d] }
+
+// Computations on time.
+//
+// The zero value for a Time is defined to be
+//	January 1, year 1, 00:00:00.000000000 UTC
+// which (1) looks like a zero, or as close as you can get in a date
+// (1-1-1 00:00:00 UTC), (2) is unlikely enough to arise in practice to
+// be a suitable "not set" sentinel, unlike Jan 1 1970, and (3) has a
+// non-negative year even in time zones west of UTC, unlike 1-1-0
+// 00:00:00 UTC, which would be 12-31-(-1) 19:00:00 in New York.
+//
+// The zero Time value does not force a specific epoch for the time
+// representation.  For example, to use the Unix epoch internally, we
+// could define that to distinguish a zero value from Jan 1 1970, that
+// time would be represented by sec=-1, nsec=1e9.  However, it does
+// suggest a representation, namely using 1-1-1 00:00:00 UTC as the
+// epoch, and that's what we do.
+//
+// The Add and Sub computations are oblivious to the choice of epoch.
+//
+// The presentation computations - year, month, minute, and so on - all
+// rely heavily on division and modulus by positive constants.  For
+// calendrical calculations we want these divisions to round down, even
+// for negative values, so that the remainder is always positive, but
+// Go's division (like most hardware division instructions) rounds to
+// zero.  We can still do those computations and then adjust the result
+// for a negative numerator, but it's annoying to write the adjustment
+// over and over.  Instead, we can change to a different epoch so long
+// ago that all the times we care about will be positive, and then round
+// to zero and round down coincide.  These presentation routines already
+// have to add the zone offset, so adding the translation to the
+// alternate epoch is cheap.  For example, having a non-negative time t
+// means that we can write
+//
+//	sec = t % 60
+//
+// instead of
+//
+//	sec = t % 60
+//	if sec < 0 {
+//		sec += 60
+//	}
+//
+// everywhere.
+//
+// The calendar runs on an exact 400 year cycle: a 400-year calendar
+// printed for 1970-2469 will apply as well to 2470-2869.  Even the days
+// of the week match up.  It simplifies the computations to choose the
+// cycle boundaries so that the exceptional years are always delayed as
+// long as possible.  That means choosing a year equal to 1 mod 400, so
+// that the first leap year is the 4th year, the first missed leap year
+// is the 100th year, and the missed missed leap year is the 400th year.
+// So we'd prefer instead to print a calendar for 2001-2400 and reuse it
+// for 2401-2800.
+//
+// Finally, it's convenient if the delta between the Unix epoch and
+// long-ago epoch is representable by an int64 constant.
+//
+// These three considerations—choose an epoch as early as possible, that
+// uses a year equal to 1 mod 400, and that is no more than 2⁶³ seconds
+// earlier than 1970—bring us to the year -292277022399.  We refer to
+// this year as the absolute zero year, and to times measured as a uint64
+// seconds since this year as absolute times.
+//
+// Times measured as an int64 seconds since the year 1—the representation
+// used for Time's sec field—are called internal times.
+//
+// Times measured as an int64 seconds since the year 1970 are called Unix
+// times.
+//
+// It is tempting to just use the year 1 as the absolute epoch, defining
+// that the routines are only valid for years >= 1.  However, the
+// routines would then be invalid when displaying the epoch in time zones
+// west of UTC, since it is year 0.  It doesn't seem tenable to say that
+// printing the zero time correctly isn't supported in half the time
+// zones.  By comparison, it's reasonable to mishandle some times in
+// the year -292277022399.
+//
+// All this is opaque to clients of the API and can be changed if a
+// better implementation presents itself.
+
+const (
+	// The unsigned zero year for internal calculations.
+	// Must be 1 mod 400, and times before it will not compute correctly,
+	// but otherwise can be changed at will.
+	absoluteZeroYear = -292277022399
+
+	// The year of the zero Time.
+	// Assumed by the unixToInternal computation below.
+	internalYear = 1
+
+	// The year of the zero Unix time.
+	unixYear = 1970
+
+	// Offsets to convert between internal and absolute or Unix times.
+	absoluteToInternal int64 = (absoluteZeroYear - internalYear) * 365.2425 * secondsPerDay
+	internalToAbsolute       = -absoluteToInternal
+
+	unixToInternal int64 = (1969*365 + 1969/4 - 1969/100 + 1969/400) * secondsPerDay
+	internalToUnix int64 = -unixToInternal
+)
+
+// IsZero reports whether t represents the zero time instant,
+// January 1, year 1, 00:00:00 UTC.
+func (t Time) IsZero() bool {
+	return t.sec == 0 && t.nsec == 0
+}
+
+// abs returns the time t as an absolute time, adjusted by the zone offset.
+// It is called when computing a presentation property like Month or Hour.
+func (t Time) abs() uint64 {
+	l := t.loc
+	// Avoid function calls when possible.
+	if l == nil || l == &localLoc {
+		l = l.get()
+	}
+	sec := t.sec + internalToUnix
+	if l != &utcLoc {
+		if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
+			sec += int64(l.cacheZone.offset)
+		} else {
+			_, offset, _, _, _ := l.lookup(sec)
+			sec += int64(offset)
+		}
+	}
+	return uint64(sec + (unixToInternal + internalToAbsolute))
+}
+
+// locabs is a combination of the Zone and abs methods,
+// extracting both return values from a single zone lookup.
+func (t Time) locabs() (name string, offset int, abs uint64) {
+	l := t.loc
+	if l == nil || l == &localLoc {
+		l = l.get()
+	}
+	// Avoid function call if we hit the local time cache.
+	sec := t.sec + internalToUnix
+	if l != &utcLoc {
+		if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
+			name = l.cacheZone.name
+			offset = l.cacheZone.offset
+		} else {
+			name, offset, _, _, _ = l.lookup(sec)
+		}
+		sec += int64(offset)
+	} else {
+		name = "UTC"
+	}
+	abs = uint64(sec + (unixToInternal + internalToAbsolute))
+	return
+}
+
+// Date returns the year, month, and day in which t occurs.
+func (t Time) Date() (year int, month Month, day int) {
+	year, month, day, _ = t.date(true)
+	return
+}
+
+// Year returns the year in which t occurs.
+func (t Time) Year() int {
+	year, _, _, _ := t.date(false)
+	return year
+}
+
+// Month returns the month of the year specified by t.
+func (t Time) Month() Month {
+	_, month, _, _ := t.date(true)
+	return month
+}
+
+// Day returns the day of the month specified by t.
+func (t Time) Day() int {
+	_, _, day, _ := t.date(true)
+	return day
+}
+
+// Weekday returns the day of the week specified by t.
+func (t Time) Weekday() Weekday {
+	return absWeekday(t.abs())
+}
+
+// absWeekday is like Weekday but operates on an absolute time.
+func absWeekday(abs uint64) Weekday {
+	// January 1 of the absolute year, like January 1 of 2001, was a Monday.
+	sec := (abs + uint64(Monday)*secondsPerDay) % secondsPerWeek
+	return Weekday(int(sec) / secondsPerDay)
+}
+
+// ISOWeek returns the ISO 8601 year and week number in which t occurs.
+// Week ranges from 1 to 53. Jan 01 to Jan 03 of year n might belong to
+// week 52 or 53 of year n-1, and Dec 29 to Dec 31 might belong to week 1
+// of year n+1.
+func (t Time) ISOWeek() (year, week int) {
+	year, month, day, yday := t.date(true)
+	wday := int(t.Weekday()+6) % 7 // weekday but Monday = 0.
+	const (
+		Mon int = iota
+		Tue
+		Wed
+		Thu
+		Fri
+		Sat
+		Sun
+	)
+
+	// Calculate week as number of Mondays in year up to
+	// and including today, plus 1 because the first week is week 0.
+	// Putting the + 1 inside the numerator as a + 7 keeps the
+	// numerator from being negative, which would cause it to
+	// round incorrectly.
+	week = (yday - wday + 7) / 7
+
+	// The week number is now correct under the assumption
+	// that the first Monday of the year is in week 1.
+	// If Jan 1 is a Tuesday, Wednesday, or Thursday, the first Monday
+	// is actually in week 2.
+	jan1wday := (wday - yday + 7*53) % 7
+	if Tue <= jan1wday && jan1wday <= Thu {
+		week++
+	}
+
+	// If the week number is still 0, we're in early January but in
+	// the last week of last year.
+	if week == 0 {
+		year--
+		week = 52
+		// A year has 53 weeks when Jan 1 or Dec 31 is a Thursday,
+		// meaning Jan 1 of the next year is a Friday
+		// or it was a leap year and Jan 1 of the next year is a Saturday.
+		if jan1wday == Fri || (jan1wday == Sat && isLeap(year)) {
+			week++
+		}
+	}
+
+	// December 29 to 31 are in week 1 of next year if
+	// they are after the last Thursday of the year and
+	// December 31 is a Monday, Tuesday, or Wednesday.
+	if month == December && day >= 29 && wday < Thu {
+		if dec31wday := (wday + 31 - day) % 7; Mon <= dec31wday && dec31wday <= Wed {
+			year++
+			week = 1
+		}
+	}
+
+	return
+}
+
+// Clock returns the hour, minute, and second within the day specified by t.
+func (t Time) Clock() (hour, min, sec int) {
+	return absClock(t.abs())
+}
+
+// absClock is like clock but operates on an absolute time.
+func absClock(abs uint64) (hour, min, sec int) {
+	sec = int(abs % secondsPerDay)
+	hour = sec / secondsPerHour
+	sec -= hour * secondsPerHour
+	min = sec / secondsPerMinute
+	sec -= min * secondsPerMinute
+	return
+}
+
+// Hour returns the hour within the day specified by t, in the range [0, 23].
+func (t Time) Hour() int {
+	return int(t.abs()%secondsPerDay) / secondsPerHour
+}
+
+// Minute returns the minute offset within the hour specified by t, in the range [0, 59].
+func (t Time) Minute() int {
+	return int(t.abs()%secondsPerHour) / secondsPerMinute
+}
+
+// Second returns the second offset within the minute specified by t, in the range [0, 59].
+func (t Time) Second() int {
+	return int(t.abs() % secondsPerMinute)
+}
+
+// Nanosecond returns the nanosecond offset within the second specified by t,
+// in the range [0, 999999999].
+func (t Time) Nanosecond() int {
+	return int(t.nsec)
+}
+
+// YearDay returns the day of the year specified by t, in the range [1,365] for non-leap years,
+// and [1,366] in leap years.
+func (t Time) YearDay() int {
+	_, _, _, yday := t.date(false)
+	return yday + 1
+}
+
+// A Duration represents the elapsed time between two instants
+// as an int64 nanosecond count.  The representation limits the
+// largest representable duration to approximately 290 years.
+type Duration int64
+
+const (
+	minDuration Duration = -1 << 63
+	maxDuration Duration = 1<<63 - 1
+)
+
+// Common durations.  There is no definition for units of Day or larger
+// to avoid confusion across daylight savings time zone transitions.
+//
+// To count the number of units in a Duration, divide:
+//	second := time.Second
+//	fmt.Print(int64(second/time.Millisecond)) // prints 1000
+//
+// To convert an integer number of units to a Duration, multiply:
+//	seconds := 10
+//	fmt.Print(time.Duration(seconds)*time.Second) // prints 10s
+//
+const (
+	Nanosecond  Duration = 1
+	Microsecond          = 1000 * Nanosecond
+	Millisecond          = 1000 * Microsecond
+	Second               = 1000 * Millisecond
+	Minute               = 60 * Second
+	Hour                 = 60 * Minute
+)
+
+// String returns a string representing the duration in the form "72h3m0.5s".
+// Leading zero units are omitted.  As a special case, durations less than one
+// second format use a smaller unit (milli-, micro-, or nanoseconds) to ensure
+// that the leading digit is non-zero.  The zero duration formats as 0,
+// with no unit.
+func (d Duration) String() string {
+	// Largest time is 2540400h10m10.000000000s
+	var buf [32]byte
+	w := len(buf)
+
+	u := uint64(d)
+	neg := d < 0
+	if neg {
+		u = -u
+	}
+
+	if u < uint64(Second) {
+		// Special case: if duration is smaller than a second,
+		// use smaller units, like 1.2ms
+		var (
+			prec int
+			unit byte
+		)
+		switch {
+		case u == 0:
+			return "0"
+		case u < uint64(Microsecond):
+			// print nanoseconds
+			prec = 0
+			unit = 'n'
+		case u < uint64(Millisecond):
+			// print microseconds
+			prec = 3
+			unit = 'u'
+		default:
+			// print milliseconds
+			prec = 6
+			unit = 'm'
+		}
+		w -= 2
+		buf[w] = unit
+		buf[w+1] = 's'
+		w, u = fmtFrac(buf[:w], u, prec)
+		w = fmtInt(buf[:w], u)
+	} else {
+		w--
+		buf[w] = 's'
+
+		w, u = fmtFrac(buf[:w], u, 9)
+
+		// u is now integer seconds
+		w = fmtInt(buf[:w], u%60)
+		u /= 60
+
+		// u is now integer minutes
+		if u > 0 {
+			w--
+			buf[w] = 'm'
+			w = fmtInt(buf[:w], u%60)
+			u /= 60
+
+			// u is now integer hours
+			// Stop at hours because days can be different lengths.
+			if u > 0 {
+				w--
+				buf[w] = 'h'
+				w = fmtInt(buf[:w], u)
+			}
+		}
+	}
+
+	if neg {
+		w--
+		buf[w] = '-'
+	}
+
+	return string(buf[w:])
+}
+
+// fmtFrac formats the fraction of v/10**prec (e.g., ".12345") into the
+// tail of buf, omitting trailing zeros.  it omits the decimal
+// point too when the fraction is 0.  It returns the index where the
+// output bytes begin and the value v/10**prec.
+func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) {
+	// Omit trailing zeros up to and including decimal point.
+	w := len(buf)
+	print := false
+	for i := 0; i < prec; i++ {
+		digit := v % 10
+		print = print || digit != 0
+		if print {
+			w--
+			buf[w] = byte(digit) + '0'
+		}
+		v /= 10
+	}
+	if print {
+		w--
+		buf[w] = '.'
+	}
+	return w, v
+}
+
+// fmtInt formats v into the tail of buf.
+// It returns the index where the output begins.
+func fmtInt(buf []byte, v uint64) int {
+	w := len(buf)
+	if v == 0 {
+		w--
+		buf[w] = '0'
+	} else {
+		for v > 0 {
+			w--
+			buf[w] = byte(v%10) + '0'
+			v /= 10
+		}
+	}
+	return w
+}
+
+// Nanoseconds returns the duration as an integer nanosecond count.
+func (d Duration) Nanoseconds() int64 { return int64(d) }
+
+// These methods return float64 because the dominant
+// use case is for printing a floating point number like 1.5s, and
+// a truncation to integer would make them not useful in those cases.
+// Splitting the integer and fraction ourselves guarantees that
+// converting the returned float64 to an integer rounds the same
+// way that a pure integer conversion would have, even in cases
+// where, say, float64(d.Nanoseconds())/1e9 would have rounded
+// differently.
+
+// Seconds returns the duration as a floating point number of seconds.
+func (d Duration) Seconds() float64 {
+	sec := d / Second
+	nsec := d % Second
+	return float64(sec) + float64(nsec)*1e-9
+}
+
+// Minutes returns the duration as a floating point number of minutes.
+func (d Duration) Minutes() float64 {
+	min := d / Minute
+	nsec := d % Minute
+	return float64(min) + float64(nsec)*(1e-9/60)
+}
+
+// Hours returns the duration as a floating point number of hours.
+func (d Duration) Hours() float64 {
+	hour := d / Hour
+	nsec := d % Hour
+	return float64(hour) + float64(nsec)*(1e-9/60/60)
+}
+
+// Add returns the time t+d.
+func (t Time) Add(d Duration) Time {
+	t.sec += int64(d / 1e9)
+	nsec := int32(t.nsec) + int32(d%1e9)
+	if nsec >= 1e9 {
+		t.sec++
+		nsec -= 1e9
+	} else if nsec < 0 {
+		t.sec--
+		nsec += 1e9
+	}
+	t.nsec = uintptr(nsec)
+	return t
+}
+
+// Sub returns the duration t-u. If the result exceeds the maximum (or minimum)
+// value that can be stored in a Duration, the maximum (or minimum) duration
+// will be returned.
+// To compute t-d for a duration d, use t.Add(-d).
+func (t Time) Sub(u Time) Duration {
+	d := Duration(t.sec-u.sec)*Second + Duration(int32(t.nsec)-int32(u.nsec))
+	// Check for overflow or underflow.
+	switch {
+	case u.Add(d).Equal(t):
+		return d // d is correct
+	case t.Before(u):
+		return minDuration // t - u is negative out of range
+	default:
+		return maxDuration // t - u is positive out of range
+	}
+}
+
+// Since returns the time elapsed since t.
+// It is shorthand for time.Now().Sub(t).
+func Since(t Time) Duration {
+	return Now().Sub(t)
+}
+
+// AddDate returns the time corresponding to adding the
+// given number of years, months, and days to t.
+// For example, AddDate(-1, 2, 3) applied to January 1, 2011
+// returns March 4, 2010.
+//
+// AddDate normalizes its result in the same way that Date does,
+// so, for example, adding one month to October 31 yields
+// December 1, the normalized form for November 31.
+func (t Time) AddDate(years int, months int, days int) Time {
+	year, month, day := t.Date()
+	hour, min, sec := t.Clock()
+	return Date(year+years, month+Month(months), day+days, hour, min, sec, int(t.nsec), t.loc)
+}
+
+const (
+	secondsPerMinute = 60
+	secondsPerHour   = 60 * 60
+	secondsPerDay    = 24 * secondsPerHour
+	secondsPerWeek   = 7 * secondsPerDay
+	daysPer400Years  = 365*400 + 97
+	daysPer100Years  = 365*100 + 24
+	daysPer4Years    = 365*4 + 1
+)
+
+// date computes the year, day of year, and when full=true,
+// the month and day in which t occurs.
+func (t Time) date(full bool) (year int, month Month, day int, yday int) {
+	return absDate(t.abs(), full)
+}
+
+// absDate is like date but operates on an absolute time.
+func absDate(abs uint64, full bool) (year int, month Month, day int, yday int) {
+	// Split into time and day.
+	d := abs / secondsPerDay
+
+	// Account for 400 year cycles.
+	n := d / daysPer400Years
+	y := 400 * n
+	d -= daysPer400Years * n
+
+	// Cut off 100-year cycles.
+	// The last cycle has one extra leap year, so on the last day
+	// of that year, day / daysPer100Years will be 4 instead of 3.
+	// Cut it back down to 3 by subtracting n>>2.
+	n = d / daysPer100Years
+	n -= n >> 2
+	y += 100 * n
+	d -= daysPer100Years * n
+
+	// Cut off 4-year cycles.
+	// The last cycle has a missing leap year, which does not
+	// affect the computation.
+	n = d / daysPer4Years
+	y += 4 * n
+	d -= daysPer4Years * n
+
+	// Cut off years within a 4-year cycle.
+	// The last year is a leap year, so on the last day of that year,
+	// day / 365 will be 4 instead of 3.  Cut it back down to 3
+	// by subtracting n>>2.
+	n = d / 365
+	n -= n >> 2
+	y += n
+	d -= 365 * n
+
+	year = int(int64(y) + absoluteZeroYear)
+	yday = int(d)
+
+	if !full {
+		return
+	}
+
+	day = yday
+	if isLeap(year) {
+		// Leap year
+		switch {
+		case day > 31+29-1:
+			// After leap day; pretend it wasn't there.
+			day--
+		case day == 31+29-1:
+			// Leap day.
+			month = February
+			day = 29
+			return
+		}
+	}
+
+	// Estimate month on assumption that every month has 31 days.
+	// The estimate may be too low by at most one month, so adjust.
+	month = Month(day / 31)
+	end := int(daysBefore[month+1])
+	var begin int
+	if day >= end {
+		month++
+		begin = end
+	} else {
+		begin = int(daysBefore[month])
+	}
+
+	month++ // because January is 1
+	day = day - begin + 1
+	return
+}
+
+// daysBefore[m] counts the number of days in a non-leap year
+// before month m begins.  There is an entry for m=12, counting
+// the number of days before January of next year (365).
+var daysBefore = [...]int32{
+	0,
+	31,
+	31 + 28,
+	31 + 28 + 31,
+	31 + 28 + 31 + 30,
+	31 + 28 + 31 + 30 + 31,
+	31 + 28 + 31 + 30 + 31 + 30,
+	31 + 28 + 31 + 30 + 31 + 30 + 31,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
+}
+
+func daysIn(m Month, year int) int {
+	if m == February && isLeap(year) {
+		return 29
+	}
+	return int(daysBefore[m] - daysBefore[m-1])
+}
+
+// Provided by package runtime.
+func now() (sec int64, nsec int32)
+
+// Now returns the current local time.
+func Now() Time {
+	sec, nsec := now()
+	return Time{sec + unixToInternal, uintptr(nsec), Local}
+}
+
+// UTC returns t with the location set to UTC.
+func (t Time) UTC() Time {
+	t.loc = UTC
+	return t
+}
+
+// Local returns t with the location set to local time.
+func (t Time) Local() Time {
+	t.loc = Local
+	return t
+}
+
+// In returns t with the location information set to loc.
+//
+// In panics if loc is nil.
+func (t Time) In(loc *Location) Time {
+	if loc == nil {
+		panic("time: missing Location in call to Time.In")
+	}
+	t.loc = loc
+	return t
+}
+
+// Location returns the time zone information associated with t.
+func (t Time) Location() *Location {
+	l := t.loc
+	if l == nil {
+		l = UTC
+	}
+	return l
+}
+
+// Zone computes the time zone in effect at time t, returning the abbreviated
+// name of the zone (such as "CET") and its offset in seconds east of UTC.
+func (t Time) Zone() (name string, offset int) {
+	name, offset, _, _, _ = t.loc.lookup(t.sec + internalToUnix)
+	return
+}
+
+// Unix returns t as a Unix time, the number of seconds elapsed
+// since January 1, 1970 UTC.
+func (t Time) Unix() int64 {
+	return t.sec + internalToUnix
+}
+
+// UnixNano returns t as a Unix time, the number of nanoseconds elapsed
+// since January 1, 1970 UTC. The result is undefined if the Unix time
+// in nanoseconds cannot be represented by an int64. Note that this
+// means the result of calling UnixNano on the zero Time is undefined.
+func (t Time) UnixNano() int64 {
+	return (t.sec+internalToUnix)*1e9 + int64(t.nsec)
+}
+
+const timeBinaryVersion byte = 1
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface.
+func (t Time) MarshalBinary() ([]byte, error) {
+	var offsetMin int16 // minutes east of UTC. -1 is UTC.
+
+	if t.Location() == &utcLoc {
+		offsetMin = -1
+	} else {
+		_, offset := t.Zone()
+		if offset%60 != 0 {
+			return nil, errors.New("Time.MarshalBinary: zone offset has fractional minute")
+		}
+		offset /= 60
+		if offset < -32768 || offset == -1 || offset > 32767 {
+			return nil, errors.New("Time.MarshalBinary: unexpected zone offset")
+		}
+		offsetMin = int16(offset)
+	}
+
+	enc := []byte{
+		timeBinaryVersion, // byte 0 : version
+		byte(t.sec >> 56), // bytes 1-8: seconds
+		byte(t.sec >> 48),
+		byte(t.sec >> 40),
+		byte(t.sec >> 32),
+		byte(t.sec >> 24),
+		byte(t.sec >> 16),
+		byte(t.sec >> 8),
+		byte(t.sec),
+		byte(t.nsec >> 24), // bytes 9-12: nanoseconds
+		byte(t.nsec >> 16),
+		byte(t.nsec >> 8),
+		byte(t.nsec),
+		byte(offsetMin >> 8), // bytes 13-14: zone offset in minutes
+		byte(offsetMin),
+	}
+
+	return enc, nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
+func (t *Time) UnmarshalBinary(data []byte) error {
+	buf := data
+	if len(buf) == 0 {
+		return errors.New("Time.UnmarshalBinary: no data")
+	}
+
+	if buf[0] != timeBinaryVersion {
+		return errors.New("Time.UnmarshalBinary: unsupported version")
+	}
+
+	if len(buf) != /*version*/ 1+ /*sec*/ 8+ /*nsec*/ 4+ /*zone offset*/ 2 {
+		return errors.New("Time.UnmarshalBinary: invalid length")
+	}
+
+	buf = buf[1:]
+	t.sec = int64(buf[7]) | int64(buf[6])<<8 | int64(buf[5])<<16 | int64(buf[4])<<24 |
+		int64(buf[3])<<32 | int64(buf[2])<<40 | int64(buf[1])<<48 | int64(buf[0])<<56
+
+	buf = buf[8:]
+	t.nsec = uintptr(int32(buf[3]) | int32(buf[2])<<8 | int32(buf[1])<<16 | int32(buf[0])<<24)
+
+	buf = buf[4:]
+	offset := int(int16(buf[1])|int16(buf[0])<<8) * 60
+
+	if offset == -1*60 {
+		t.loc = &utcLoc
+	} else if _, localoff, _, _, _ := Local.lookup(t.sec + internalToUnix); offset == localoff {
+		t.loc = Local
+	} else {
+		t.loc = FixedZone("", offset)
+	}
+
+	return nil
+}
+
+// TODO(rsc): Remove GobEncoder, GobDecoder, MarshalJSON, UnmarshalJSON in Go 2.
+// The same semantics will be provided by the generic MarshalBinary, MarshalText,
+// UnmarshalBinary, UnmarshalText.
+
+// GobEncode implements the gob.GobEncoder interface.
+func (t Time) GobEncode() ([]byte, error) {
+	return t.MarshalBinary()
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (t *Time) GobDecode(data []byte) error {
+	return t.UnmarshalBinary(data)
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+// The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
+func (t Time) MarshalJSON() ([]byte, error) {
+	if y := t.Year(); y < 0 || y >= 10000 {
+		// RFC 3339 is clear that years are 4 digits exactly.
+		// See golang.org/issue/4556#c15 for more discussion.
+		return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
+	}
+	return []byte(t.Format(`"` + RFC3339Nano + `"`)), nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+// The time is expected to be a quoted string in RFC 3339 format.
+func (t *Time) UnmarshalJSON(data []byte) (err error) {
+	// Fractional seconds are handled implicitly by Parse.
+	*t, err = Parse(`"`+RFC3339+`"`, string(data))
+	return
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+// The time is formatted in RFC 3339 format, with sub-second precision added if present.
+func (t Time) MarshalText() ([]byte, error) {
+	if y := t.Year(); y < 0 || y >= 10000 {
+		return nil, errors.New("Time.MarshalText: year outside of range [0,9999]")
+	}
+	return []byte(t.Format(RFC3339Nano)), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+// The time is expected to be in RFC 3339 format.
+func (t *Time) UnmarshalText(data []byte) (err error) {
+	// Fractional seconds are handled implicitly by Parse.
+	*t, err = Parse(RFC3339, string(data))
+	return
+}
+
+// Unix returns the local Time corresponding to the given Unix time,
+// sec seconds and nsec nanoseconds since January 1, 1970 UTC.
+// It is valid to pass nsec outside the range [0, 999999999].
+func Unix(sec int64, nsec int64) Time {
+	if nsec < 0 || nsec >= 1e9 {
+		n := nsec / 1e9
+		sec += n
+		nsec -= n * 1e9
+		if nsec < 0 {
+			nsec += 1e9
+			sec--
+		}
+	}
+	return Time{sec + unixToInternal, uintptr(nsec), Local}
+}
+
+func isLeap(year int) bool {
+	return year%4 == 0 && (year%100 != 0 || year%400 == 0)
+}
+
+// norm returns nhi, nlo such that
+//	hi * base + lo == nhi * base + nlo
+//	0 <= nlo < base
+func norm(hi, lo, base int) (nhi, nlo int) {
+	if lo < 0 {
+		n := (-lo-1)/base + 1
+		hi -= n
+		lo += n * base
+	}
+	if lo >= base {
+		n := lo / base
+		hi += n
+		lo -= n * base
+	}
+	return hi, lo
+}
+
+// Date returns the Time corresponding to
+//	yyyy-mm-dd hh:mm:ss + nsec nanoseconds
+// in the appropriate zone for that time in the given location.
+//
+// The month, day, hour, min, sec, and nsec values may be outside
+// their usual ranges and will be normalized during the conversion.
+// For example, October 32 converts to November 1.
+//
+// A daylight savings time transition skips or repeats times.
+// For example, in the United States, March 13, 2011 2:15am never occurred,
+// while November 6, 2011 1:15am occurred twice.  In such cases, the
+// choice of time zone, and therefore the time, is not well-defined.
+// Date returns a time that is correct in one of the two zones involved
+// in the transition, but it does not guarantee which.
+//
+// Date panics if loc is nil.
+func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {
+	if loc == nil {
+		panic("time: missing Location in call to Date")
+	}
+
+	// Normalize month, overflowing into year.
+	m := int(month) - 1
+	year, m = norm(year, m, 12)
+	month = Month(m) + 1
+
+	// Normalize nsec, sec, min, hour, overflowing into day.
+	sec, nsec = norm(sec, nsec, 1e9)
+	min, sec = norm(min, sec, 60)
+	hour, min = norm(hour, min, 60)
+	day, hour = norm(day, hour, 24)
+
+	y := uint64(int64(year) - absoluteZeroYear)
+
+	// Compute days since the absolute epoch.
+
+	// Add in days from 400-year cycles.
+	n := y / 400
+	y -= 400 * n
+	d := daysPer400Years * n
+
+	// Add in 100-year cycles.
+	n = y / 100
+	y -= 100 * n
+	d += daysPer100Years * n
+
+	// Add in 4-year cycles.
+	n = y / 4
+	y -= 4 * n
+	d += daysPer4Years * n
+
+	// Add in non-leap years.
+	n = y
+	d += 365 * n
+
+	// Add in days before this month.
+	d += uint64(daysBefore[month-1])
+	if isLeap(year) && month >= March {
+		d++ // February 29
+	}
+
+	// Add in days before today.
+	d += uint64(day - 1)
+
+	// Add in time elapsed today.
+	abs := d * secondsPerDay
+	abs += uint64(hour*secondsPerHour + min*secondsPerMinute + sec)
+
+	unix := int64(abs) + (absoluteToInternal + internalToUnix)
+
+	// Look for zone offset for t, so we can adjust to UTC.
+	// The lookup function expects UTC, so we pass t in the
+	// hope that it will not be too close to a zone transition,
+	// and then adjust if it is.
+	_, offset, _, start, end := loc.lookup(unix)
+	if offset != 0 {
+		switch utc := unix - int64(offset); {
+		case utc < start:
+			_, offset, _, _, _ = loc.lookup(start - 1)
+		case utc >= end:
+			_, offset, _, _, _ = loc.lookup(end)
+		}
+		unix -= int64(offset)
+	}
+
+	return Time{unix + unixToInternal, uintptr(nsec), loc}
+}
+
+// Truncate returns the result of rounding t down to a multiple of d (since the zero time).
+// If d <= 0, Truncate returns t unchanged.
+func (t Time) Truncate(d Duration) Time {
+	if d <= 0 {
+		return t
+	}
+	_, r := div(t, d)
+	return t.Add(-r)
+}
+
+// Round returns the result of rounding t to the nearest multiple of d (since the zero time).
+// The rounding behavior for halfway values is to round up.
+// If d <= 0, Round returns t unchanged.
+func (t Time) Round(d Duration) Time {
+	if d <= 0 {
+		return t
+	}
+	_, r := div(t, d)
+	if r+r < d {
+		return t.Add(-r)
+	}
+	return t.Add(d - r)
+}
+
+// div divides t by d and returns the quotient parity and remainder.
+// We don't use the quotient parity anymore (round half up instead of round to even)
+// but it's still here in case we change our minds.
+func div(t Time, d Duration) (qmod2 int, r Duration) {
+	neg := false
+	nsec := int32(t.nsec)
+	if t.sec < 0 {
+		// Operate on absolute value.
+		neg = true
+		t.sec = -t.sec
+		nsec = -nsec
+		if nsec < 0 {
+			nsec += 1e9
+			t.sec-- // t.sec >= 1 before the -- so safe
+		}
+	}
+
+	switch {
+	// Special case: 2d divides 1 second.
+	case d < Second && Second%(d+d) == 0:
+		qmod2 = int(nsec/int32(d)) & 1
+		r = Duration(nsec % int32(d))
+
+	// Special case: d is a multiple of 1 second.
+	case d%Second == 0:
+		d1 := int64(d / Second)
+		qmod2 = int(t.sec/d1) & 1
+		r = Duration(t.sec%d1)*Second + Duration(nsec)
+
+	// General case.
+	// This could be faster if more cleverness were applied,
+	// but it's really only here to avoid special case restrictions in the API.
+	// No one will care about these cases.
+	default:
+		// Compute nanoseconds as 128-bit number.
+		sec := uint64(t.sec)
+		tmp := (sec >> 32) * 1e9
+		u1 := tmp >> 32
+		u0 := tmp << 32
+		tmp = uint64(sec&0xFFFFFFFF) * 1e9
+		u0x, u0 := u0, u0+tmp
+		if u0 < u0x {
+			u1++
+		}
+		u0x, u0 = u0, u0+uint64(nsec)
+		if u0 < u0x {
+			u1++
+		}
+
+		// Compute remainder by subtracting r<<k for decreasing k.
+		// Quotient parity is whether we subtract on last round.
+		d1 := uint64(d)
+		for d1>>63 != 1 {
+			d1 <<= 1
+		}
+		d0 := uint64(0)
+		for {
+			qmod2 = 0
+			if u1 > d1 || u1 == d1 && u0 >= d0 {
+				// subtract
+				qmod2 = 1
+				u0x, u0 = u0, u0-d0
+				if u0 > u0x {
+					u1--
+				}
+				u1 -= d1
+			}
+			if d1 == 0 && d0 == uint64(d) {
+				break
+			}
+			d0 >>= 1
+			d0 |= (d1 & 1) << 63
+			d1 >>= 1
+		}
+		r = Duration(u0)
+	}
+
+	if neg && r != 0 {
+		// If input was negative and not an exact multiple of d, we computed q, r such that
+		//	q*d + r = -t
+		// But the right answers are given by -(q-1), d-r:
+		//	q*d + r = -t
+		//	-q*d - r = t
+		//	-(q-1)*d + (d - r) = t
+		qmod2 ^= 1
+		r = d - r
+	}
+	return
+}
diff --git a/third_party/gofrontend/libgo/go/time/time_test.go b/third_party/gofrontend/libgo/go/time/time_test.go
new file mode 100644
index 0000000..4ae7da5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/time_test.go
@@ -0,0 +1,1081 @@
+// 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 time_test
+
+import (
+	"bytes"
+	"encoding/gob"
+	"encoding/json"
+	"fmt"
+	"math/big"
+	"math/rand"
+	"runtime"
+	"testing"
+	"testing/quick"
+	. "time"
+)
+
+// We should be in PST/PDT, but if the time zone files are missing we
+// won't be. The purpose of this test is to at least explain why some of
+// the subsequent tests fail.
+func TestZoneData(t *testing.T) {
+	lt := Now()
+	// PST is 8 hours west, PDT is 7 hours west.  We could use the name but it's not unique.
+	if name, off := lt.Zone(); off != -8*60*60 && off != -7*60*60 {
+		t.Errorf("Unable to find US Pacific time zone data for testing; time zone is %q offset %d", name, off)
+		t.Error("Likely problem: the time zone files have not been installed.")
+	}
+}
+
+// parsedTime is the struct representing a parsed time value.
+type parsedTime struct {
+	Year                 int
+	Month                Month
+	Day                  int
+	Hour, Minute, Second int // 15:04:05 is 15, 4, 5.
+	Nanosecond           int // Fractional second.
+	Weekday              Weekday
+	ZoneOffset           int    // seconds east of UTC, e.g. -7*60*60 for -0700
+	Zone                 string // e.g., "MST"
+}
+
+type TimeTest struct {
+	seconds int64
+	golden  parsedTime
+}
+
+var utctests = []TimeTest{
+	{0, parsedTime{1970, January, 1, 0, 0, 0, 0, Thursday, 0, "UTC"}},
+	{1221681866, parsedTime{2008, September, 17, 20, 4, 26, 0, Wednesday, 0, "UTC"}},
+	{-1221681866, parsedTime{1931, April, 16, 3, 55, 34, 0, Thursday, 0, "UTC"}},
+	{-11644473600, parsedTime{1601, January, 1, 0, 0, 0, 0, Monday, 0, "UTC"}},
+	{599529660, parsedTime{1988, December, 31, 0, 1, 0, 0, Saturday, 0, "UTC"}},
+	{978220860, parsedTime{2000, December, 31, 0, 1, 0, 0, Sunday, 0, "UTC"}},
+}
+
+var nanoutctests = []TimeTest{
+	{0, parsedTime{1970, January, 1, 0, 0, 0, 1e8, Thursday, 0, "UTC"}},
+	{1221681866, parsedTime{2008, September, 17, 20, 4, 26, 2e8, Wednesday, 0, "UTC"}},
+}
+
+var localtests = []TimeTest{
+	{0, parsedTime{1969, December, 31, 16, 0, 0, 0, Wednesday, -8 * 60 * 60, "PST"}},
+	{1221681866, parsedTime{2008, September, 17, 13, 4, 26, 0, Wednesday, -7 * 60 * 60, "PDT"}},
+}
+
+var nanolocaltests = []TimeTest{
+	{0, parsedTime{1969, December, 31, 16, 0, 0, 1e8, Wednesday, -8 * 60 * 60, "PST"}},
+	{1221681866, parsedTime{2008, September, 17, 13, 4, 26, 3e8, Wednesday, -7 * 60 * 60, "PDT"}},
+}
+
+func same(t Time, u *parsedTime) bool {
+	// Check aggregates.
+	year, month, day := t.Date()
+	hour, min, sec := t.Clock()
+	name, offset := t.Zone()
+	if year != u.Year || month != u.Month || day != u.Day ||
+		hour != u.Hour || min != u.Minute || sec != u.Second ||
+		name != u.Zone || offset != u.ZoneOffset {
+		return false
+	}
+	// Check individual entries.
+	return t.Year() == u.Year &&
+		t.Month() == u.Month &&
+		t.Day() == u.Day &&
+		t.Hour() == u.Hour &&
+		t.Minute() == u.Minute &&
+		t.Second() == u.Second &&
+		t.Nanosecond() == u.Nanosecond &&
+		t.Weekday() == u.Weekday
+}
+
+func TestSecondsToUTC(t *testing.T) {
+	for _, test := range utctests {
+		sec := test.seconds
+		golden := &test.golden
+		tm := Unix(sec, 0).UTC()
+		newsec := tm.Unix()
+		if newsec != sec {
+			t.Errorf("SecondsToUTC(%d).Seconds() = %d", sec, newsec)
+		}
+		if !same(tm, golden) {
+			t.Errorf("SecondsToUTC(%d):  // %#v", sec, tm)
+			t.Errorf("  want=%+v", *golden)
+			t.Errorf("  have=%v", tm.Format(RFC3339+" MST"))
+		}
+	}
+}
+
+func TestNanosecondsToUTC(t *testing.T) {
+	for _, test := range nanoutctests {
+		golden := &test.golden
+		nsec := test.seconds*1e9 + int64(golden.Nanosecond)
+		tm := Unix(0, nsec).UTC()
+		newnsec := tm.Unix()*1e9 + int64(tm.Nanosecond())
+		if newnsec != nsec {
+			t.Errorf("NanosecondsToUTC(%d).Nanoseconds() = %d", nsec, newnsec)
+		}
+		if !same(tm, golden) {
+			t.Errorf("NanosecondsToUTC(%d):", nsec)
+			t.Errorf("  want=%+v", *golden)
+			t.Errorf("  have=%+v", tm.Format(RFC3339+" MST"))
+		}
+	}
+}
+
+func TestSecondsToLocalTime(t *testing.T) {
+	for _, test := range localtests {
+		sec := test.seconds
+		golden := &test.golden
+		tm := Unix(sec, 0)
+		newsec := tm.Unix()
+		if newsec != sec {
+			t.Errorf("SecondsToLocalTime(%d).Seconds() = %d", sec, newsec)
+		}
+		if !same(tm, golden) {
+			t.Errorf("SecondsToLocalTime(%d):", sec)
+			t.Errorf("  want=%+v", *golden)
+			t.Errorf("  have=%+v", tm.Format(RFC3339+" MST"))
+		}
+	}
+}
+
+func TestNanosecondsToLocalTime(t *testing.T) {
+	for _, test := range nanolocaltests {
+		golden := &test.golden
+		nsec := test.seconds*1e9 + int64(golden.Nanosecond)
+		tm := Unix(0, nsec)
+		newnsec := tm.Unix()*1e9 + int64(tm.Nanosecond())
+		if newnsec != nsec {
+			t.Errorf("NanosecondsToLocalTime(%d).Seconds() = %d", nsec, newnsec)
+		}
+		if !same(tm, golden) {
+			t.Errorf("NanosecondsToLocalTime(%d):", nsec)
+			t.Errorf("  want=%+v", *golden)
+			t.Errorf("  have=%+v", tm.Format(RFC3339+" MST"))
+		}
+	}
+}
+
+func TestSecondsToUTCAndBack(t *testing.T) {
+	f := func(sec int64) bool { return Unix(sec, 0).UTC().Unix() == sec }
+	f32 := func(sec int32) bool { return f(int64(sec)) }
+	cfg := &quick.Config{MaxCount: 10000}
+
+	// Try a reasonable date first, then the huge ones.
+	if err := quick.Check(f32, cfg); err != nil {
+		t.Fatal(err)
+	}
+	if err := quick.Check(f, cfg); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestNanosecondsToUTCAndBack(t *testing.T) {
+	f := func(nsec int64) bool {
+		t := Unix(0, nsec).UTC()
+		ns := t.Unix()*1e9 + int64(t.Nanosecond())
+		return ns == nsec
+	}
+	f32 := func(nsec int32) bool { return f(int64(nsec)) }
+	cfg := &quick.Config{MaxCount: 10000}
+
+	// Try a small date first, then the large ones. (The span is only a few hundred years
+	// for nanoseconds in an int64.)
+	if err := quick.Check(f32, cfg); err != nil {
+		t.Fatal(err)
+	}
+	if err := quick.Check(f, cfg); err != nil {
+		t.Fatal(err)
+	}
+}
+
+// The time routines provide no way to get absolute time
+// (seconds since zero), but we need it to compute the right
+// answer for bizarre roundings like "to the nearest 3 ns".
+// Compute as t - year1 = (t - 1970) + (1970 - 2001) + (2001 - 1).
+// t - 1970 is returned by Unix and Nanosecond.
+// 1970 - 2001 is -(31*365+8)*86400 = -978307200 seconds.
+// 2001 - 1 is 2000*365.2425*86400 = 63113904000 seconds.
+const unixToZero = -978307200 + 63113904000
+
+// abs returns the absolute time stored in t, as seconds and nanoseconds.
+func abs(t Time) (sec, nsec int64) {
+	unix := t.Unix()
+	nano := t.Nanosecond()
+	return unix + unixToZero, int64(nano)
+}
+
+// absString returns abs as a decimal string.
+func absString(t Time) string {
+	sec, nsec := abs(t)
+	if sec < 0 {
+		sec = -sec
+		nsec = -nsec
+		if nsec < 0 {
+			nsec += 1e9
+			sec--
+		}
+		return fmt.Sprintf("-%d%09d", sec, nsec)
+	}
+	return fmt.Sprintf("%d%09d", sec, nsec)
+}
+
+var truncateRoundTests = []struct {
+	t Time
+	d Duration
+}{
+	{Date(-1, January, 1, 12, 15, 30, 5e8, UTC), 3},
+	{Date(-1, January, 1, 12, 15, 31, 5e8, UTC), 3},
+	{Date(2012, January, 1, 12, 15, 30, 5e8, UTC), Second},
+	{Date(2012, January, 1, 12, 15, 31, 5e8, UTC), Second},
+}
+
+func TestTruncateRound(t *testing.T) {
+	var (
+		bsec  = new(big.Int)
+		bnsec = new(big.Int)
+		bd    = new(big.Int)
+		bt    = new(big.Int)
+		br    = new(big.Int)
+		bq    = new(big.Int)
+		b1e9  = new(big.Int)
+	)
+
+	b1e9.SetInt64(1e9)
+
+	testOne := func(ti, tns, di int64) bool {
+		t0 := Unix(ti, int64(tns)).UTC()
+		d := Duration(di)
+		if d < 0 {
+			d = -d
+		}
+		if d <= 0 {
+			d = 1
+		}
+
+		// Compute bt = absolute nanoseconds.
+		sec, nsec := abs(t0)
+		bsec.SetInt64(sec)
+		bnsec.SetInt64(nsec)
+		bt.Mul(bsec, b1e9)
+		bt.Add(bt, bnsec)
+
+		// Compute quotient and remainder mod d.
+		bd.SetInt64(int64(d))
+		bq.DivMod(bt, bd, br)
+
+		// To truncate, subtract remainder.
+		// br is < d, so it fits in an int64.
+		r := br.Int64()
+		t1 := t0.Add(-Duration(r))
+
+		// Check that time.Truncate works.
+		if trunc := t0.Truncate(d); trunc != t1 {
+			t.Errorf("Time.Truncate(%s, %s) = %s, want %s\n"+
+				"%v trunc %v =\n%v want\n%v",
+				t0.Format(RFC3339Nano), d, trunc, t1.Format(RFC3339Nano),
+				absString(t0), int64(d), absString(trunc), absString(t1))
+			return false
+		}
+
+		// To round, add d back if remainder r > d/2 or r == exactly d/2.
+		// The commented out code would round half to even instead of up,
+		// but that makes it time-zone dependent, which is a bit strange.
+		if r > int64(d)/2 || r+r == int64(d) /*&& bq.Bit(0) == 1*/ {
+			t1 = t1.Add(Duration(d))
+		}
+
+		// Check that time.Round works.
+		if rnd := t0.Round(d); rnd != t1 {
+			t.Errorf("Time.Round(%s, %s) = %s, want %s\n"+
+				"%v round %v =\n%v want\n%v",
+				t0.Format(RFC3339Nano), d, rnd, t1.Format(RFC3339Nano),
+				absString(t0), int64(d), absString(rnd), absString(t1))
+			return false
+		}
+		return true
+	}
+
+	// manual test cases
+	for _, tt := range truncateRoundTests {
+		testOne(tt.t.Unix(), int64(tt.t.Nanosecond()), int64(tt.d))
+	}
+
+	// exhaustive near 0
+	for i := 0; i < 100; i++ {
+		for j := 1; j < 100; j++ {
+			testOne(unixToZero, int64(i), int64(j))
+			testOne(unixToZero, -int64(i), int64(j))
+			if t.Failed() {
+				return
+			}
+		}
+	}
+
+	if t.Failed() {
+		return
+	}
+
+	// randomly generated test cases
+	cfg := &quick.Config{MaxCount: 100000}
+	if testing.Short() {
+		cfg.MaxCount = 1000
+	}
+
+	// divisors of Second
+	f1 := func(ti int64, tns int32, logdi int32) bool {
+		d := Duration(1)
+		a, b := uint(logdi%9), (logdi>>16)%9
+		d <<= a
+		for i := 0; i < int(b); i++ {
+			d *= 5
+		}
+		return testOne(ti, int64(tns), int64(d))
+	}
+	quick.Check(f1, cfg)
+
+	// multiples of Second
+	f2 := func(ti int64, tns int32, di int32) bool {
+		d := Duration(di) * Second
+		if d < 0 {
+			d = -d
+		}
+		return testOne(ti, int64(tns), int64(d))
+	}
+	quick.Check(f2, cfg)
+
+	// halfway cases
+	f3 := func(tns, di int64) bool {
+		di &= 0xfffffffe
+		if di == 0 {
+			di = 2
+		}
+		tns -= tns % di
+		if tns < 0 {
+			tns += di / 2
+		} else {
+			tns -= di / 2
+		}
+		return testOne(0, tns, di)
+	}
+	quick.Check(f3, cfg)
+
+	// full generality
+	f4 := func(ti int64, tns int32, di int64) bool {
+		return testOne(ti, int64(tns), di)
+	}
+	quick.Check(f4, cfg)
+}
+
+type ISOWeekTest struct {
+	year       int // year
+	month, day int // month and day
+	yex        int // expected year
+	wex        int // expected week
+}
+
+var isoWeekTests = []ISOWeekTest{
+	{1981, 1, 1, 1981, 1}, {1982, 1, 1, 1981, 53}, {1983, 1, 1, 1982, 52},
+	{1984, 1, 1, 1983, 52}, {1985, 1, 1, 1985, 1}, {1986, 1, 1, 1986, 1},
+	{1987, 1, 1, 1987, 1}, {1988, 1, 1, 1987, 53}, {1989, 1, 1, 1988, 52},
+	{1990, 1, 1, 1990, 1}, {1991, 1, 1, 1991, 1}, {1992, 1, 1, 1992, 1},
+	{1993, 1, 1, 1992, 53}, {1994, 1, 1, 1993, 52}, {1995, 1, 2, 1995, 1},
+	{1996, 1, 1, 1996, 1}, {1996, 1, 7, 1996, 1}, {1996, 1, 8, 1996, 2},
+	{1997, 1, 1, 1997, 1}, {1998, 1, 1, 1998, 1}, {1999, 1, 1, 1998, 53},
+	{2000, 1, 1, 1999, 52}, {2001, 1, 1, 2001, 1}, {2002, 1, 1, 2002, 1},
+	{2003, 1, 1, 2003, 1}, {2004, 1, 1, 2004, 1}, {2005, 1, 1, 2004, 53},
+	{2006, 1, 1, 2005, 52}, {2007, 1, 1, 2007, 1}, {2008, 1, 1, 2008, 1},
+	{2009, 1, 1, 2009, 1}, {2010, 1, 1, 2009, 53}, {2010, 1, 1, 2009, 53},
+	{2011, 1, 1, 2010, 52}, {2011, 1, 2, 2010, 52}, {2011, 1, 3, 2011, 1},
+	{2011, 1, 4, 2011, 1}, {2011, 1, 5, 2011, 1}, {2011, 1, 6, 2011, 1},
+	{2011, 1, 7, 2011, 1}, {2011, 1, 8, 2011, 1}, {2011, 1, 9, 2011, 1},
+	{2011, 1, 10, 2011, 2}, {2011, 1, 11, 2011, 2}, {2011, 6, 12, 2011, 23},
+	{2011, 6, 13, 2011, 24}, {2011, 12, 25, 2011, 51}, {2011, 12, 26, 2011, 52},
+	{2011, 12, 27, 2011, 52}, {2011, 12, 28, 2011, 52}, {2011, 12, 29, 2011, 52},
+	{2011, 12, 30, 2011, 52}, {2011, 12, 31, 2011, 52}, {1995, 1, 1, 1994, 52},
+	{2012, 1, 1, 2011, 52}, {2012, 1, 2, 2012, 1}, {2012, 1, 8, 2012, 1},
+	{2012, 1, 9, 2012, 2}, {2012, 12, 23, 2012, 51}, {2012, 12, 24, 2012, 52},
+	{2012, 12, 30, 2012, 52}, {2012, 12, 31, 2013, 1}, {2013, 1, 1, 2013, 1},
+	{2013, 1, 6, 2013, 1}, {2013, 1, 7, 2013, 2}, {2013, 12, 22, 2013, 51},
+	{2013, 12, 23, 2013, 52}, {2013, 12, 29, 2013, 52}, {2013, 12, 30, 2014, 1},
+	{2014, 1, 1, 2014, 1}, {2014, 1, 5, 2014, 1}, {2014, 1, 6, 2014, 2},
+	{2015, 1, 1, 2015, 1}, {2016, 1, 1, 2015, 53}, {2017, 1, 1, 2016, 52},
+	{2018, 1, 1, 2018, 1}, {2019, 1, 1, 2019, 1}, {2020, 1, 1, 2020, 1},
+	{2021, 1, 1, 2020, 53}, {2022, 1, 1, 2021, 52}, {2023, 1, 1, 2022, 52},
+	{2024, 1, 1, 2024, 1}, {2025, 1, 1, 2025, 1}, {2026, 1, 1, 2026, 1},
+	{2027, 1, 1, 2026, 53}, {2028, 1, 1, 2027, 52}, {2029, 1, 1, 2029, 1},
+	{2030, 1, 1, 2030, 1}, {2031, 1, 1, 2031, 1}, {2032, 1, 1, 2032, 1},
+	{2033, 1, 1, 2032, 53}, {2034, 1, 1, 2033, 52}, {2035, 1, 1, 2035, 1},
+	{2036, 1, 1, 2036, 1}, {2037, 1, 1, 2037, 1}, {2038, 1, 1, 2037, 53},
+	{2039, 1, 1, 2038, 52}, {2040, 1, 1, 2039, 52},
+}
+
+func TestISOWeek(t *testing.T) {
+	// Selected dates and corner cases
+	for _, wt := range isoWeekTests {
+		dt := Date(wt.year, Month(wt.month), wt.day, 0, 0, 0, 0, UTC)
+		y, w := dt.ISOWeek()
+		if w != wt.wex || y != wt.yex {
+			t.Errorf("got %d/%d; expected %d/%d for %d-%02d-%02d",
+				y, w, wt.yex, wt.wex, wt.year, wt.month, wt.day)
+		}
+	}
+
+	// The only real invariant: Jan 04 is in week 1
+	for year := 1950; year < 2100; year++ {
+		if y, w := Date(year, January, 4, 0, 0, 0, 0, UTC).ISOWeek(); y != year || w != 1 {
+			t.Errorf("got %d/%d; expected %d/1 for Jan 04", y, w, year)
+		}
+	}
+}
+
+type YearDayTest struct {
+	year, month, day int
+	yday             int
+}
+
+// Test YearDay in several different scenarios
+// and corner cases
+var yearDayTests = []YearDayTest{
+	// Non-leap-year tests
+	{2007, 1, 1, 1},
+	{2007, 1, 15, 15},
+	{2007, 2, 1, 32},
+	{2007, 2, 15, 46},
+	{2007, 3, 1, 60},
+	{2007, 3, 15, 74},
+	{2007, 4, 1, 91},
+	{2007, 12, 31, 365},
+
+	// Leap-year tests
+	{2008, 1, 1, 1},
+	{2008, 1, 15, 15},
+	{2008, 2, 1, 32},
+	{2008, 2, 15, 46},
+	{2008, 3, 1, 61},
+	{2008, 3, 15, 75},
+	{2008, 4, 1, 92},
+	{2008, 12, 31, 366},
+
+	// Looks like leap-year (but isn't) tests
+	{1900, 1, 1, 1},
+	{1900, 1, 15, 15},
+	{1900, 2, 1, 32},
+	{1900, 2, 15, 46},
+	{1900, 3, 1, 60},
+	{1900, 3, 15, 74},
+	{1900, 4, 1, 91},
+	{1900, 12, 31, 365},
+
+	// Year one tests (non-leap)
+	{1, 1, 1, 1},
+	{1, 1, 15, 15},
+	{1, 2, 1, 32},
+	{1, 2, 15, 46},
+	{1, 3, 1, 60},
+	{1, 3, 15, 74},
+	{1, 4, 1, 91},
+	{1, 12, 31, 365},
+
+	// Year minus one tests (non-leap)
+	{-1, 1, 1, 1},
+	{-1, 1, 15, 15},
+	{-1, 2, 1, 32},
+	{-1, 2, 15, 46},
+	{-1, 3, 1, 60},
+	{-1, 3, 15, 74},
+	{-1, 4, 1, 91},
+	{-1, 12, 31, 365},
+
+	// 400 BC tests (leap-year)
+	{-400, 1, 1, 1},
+	{-400, 1, 15, 15},
+	{-400, 2, 1, 32},
+	{-400, 2, 15, 46},
+	{-400, 3, 1, 61},
+	{-400, 3, 15, 75},
+	{-400, 4, 1, 92},
+	{-400, 12, 31, 366},
+
+	// Special Cases
+
+	// Gregorian calendar change (no effect)
+	{1582, 10, 4, 277},
+	{1582, 10, 15, 288},
+}
+
+// Check to see if YearDay is location sensitive
+var yearDayLocations = []*Location{
+	FixedZone("UTC-8", -8*60*60),
+	FixedZone("UTC-4", -4*60*60),
+	UTC,
+	FixedZone("UTC+4", 4*60*60),
+	FixedZone("UTC+8", 8*60*60),
+}
+
+func TestYearDay(t *testing.T) {
+	for _, loc := range yearDayLocations {
+		for _, ydt := range yearDayTests {
+			dt := Date(ydt.year, Month(ydt.month), ydt.day, 0, 0, 0, 0, loc)
+			yday := dt.YearDay()
+			if yday != ydt.yday {
+				t.Errorf("got %d, expected %d for %d-%02d-%02d in %v",
+					yday, ydt.yday, ydt.year, ydt.month, ydt.day, loc)
+			}
+		}
+	}
+}
+
+var durationTests = []struct {
+	str string
+	d   Duration
+}{
+	{"0", 0},
+	{"1ns", 1 * Nanosecond},
+	{"1.1us", 1100 * Nanosecond},
+	{"2.2ms", 2200 * Microsecond},
+	{"3.3s", 3300 * Millisecond},
+	{"4m5s", 4*Minute + 5*Second},
+	{"4m5.001s", 4*Minute + 5001*Millisecond},
+	{"5h6m7.001s", 5*Hour + 6*Minute + 7001*Millisecond},
+	{"8m0.000000001s", 8*Minute + 1*Nanosecond},
+	{"2562047h47m16.854775807s", 1<<63 - 1},
+	{"-2562047h47m16.854775808s", -1 << 63},
+}
+
+func TestDurationString(t *testing.T) {
+	for _, tt := range durationTests {
+		if str := tt.d.String(); str != tt.str {
+			t.Errorf("Duration(%d).String() = %s, want %s", int64(tt.d), str, tt.str)
+		}
+		if tt.d > 0 {
+			if str := (-tt.d).String(); str != "-"+tt.str {
+				t.Errorf("Duration(%d).String() = %s, want %s", int64(-tt.d), str, "-"+tt.str)
+			}
+		}
+	}
+}
+
+var dateTests = []struct {
+	year, month, day, hour, min, sec, nsec int
+	z                                      *Location
+	unix                                   int64
+}{
+	{2011, 11, 6, 1, 0, 0, 0, Local, 1320566400},   // 1:00:00 PDT
+	{2011, 11, 6, 1, 59, 59, 0, Local, 1320569999}, // 1:59:59 PDT
+	{2011, 11, 6, 2, 0, 0, 0, Local, 1320573600},   // 2:00:00 PST
+
+	{2011, 3, 13, 1, 0, 0, 0, Local, 1300006800},   // 1:00:00 PST
+	{2011, 3, 13, 1, 59, 59, 0, Local, 1300010399}, // 1:59:59 PST
+	{2011, 3, 13, 3, 0, 0, 0, Local, 1300010400},   // 3:00:00 PDT
+	{2011, 3, 13, 2, 30, 0, 0, Local, 1300008600},  // 2:30:00 PDT ≡ 1:30 PST
+
+	// Many names for Fri Nov 18 7:56:35 PST 2011
+	{2011, 11, 18, 7, 56, 35, 0, Local, 1321631795},                 // Nov 18 7:56:35
+	{2011, 11, 19, -17, 56, 35, 0, Local, 1321631795},               // Nov 19 -17:56:35
+	{2011, 11, 17, 31, 56, 35, 0, Local, 1321631795},                // Nov 17 31:56:35
+	{2011, 11, 18, 6, 116, 35, 0, Local, 1321631795},                // Nov 18 6:116:35
+	{2011, 10, 49, 7, 56, 35, 0, Local, 1321631795},                 // Oct 49 7:56:35
+	{2011, 11, 18, 7, 55, 95, 0, Local, 1321631795},                 // Nov 18 7:55:95
+	{2011, 11, 18, 7, 56, 34, 1e9, Local, 1321631795},               // Nov 18 7:56:34 + 10⁹ns
+	{2011, 12, -12, 7, 56, 35, 0, Local, 1321631795},                // Dec -21 7:56:35
+	{2012, 1, -43, 7, 56, 35, 0, Local, 1321631795},                 // Jan -52 7:56:35 2012
+	{2012, int(January - 2), 18, 7, 56, 35, 0, Local, 1321631795},   // (Jan-2) 18 7:56:35 2012
+	{2010, int(December + 11), 18, 7, 56, 35, 0, Local, 1321631795}, // (Dec+11) 18 7:56:35 2010
+}
+
+func TestDate(t *testing.T) {
+	for _, tt := range dateTests {
+		time := Date(tt.year, Month(tt.month), tt.day, tt.hour, tt.min, tt.sec, tt.nsec, tt.z)
+		want := Unix(tt.unix, 0)
+		if !time.Equal(want) {
+			t.Errorf("Date(%d, %d, %d, %d, %d, %d, %d, %s) = %v, want %v",
+				tt.year, tt.month, tt.day, tt.hour, tt.min, tt.sec, tt.nsec, tt.z,
+				time, want)
+		}
+	}
+}
+
+// Several ways of getting from
+// Fri Nov 18 7:56:35 PST 2011
+// to
+// Thu Mar 19 7:56:35 PST 2016
+var addDateTests = []struct {
+	years, months, days int
+}{
+	{4, 4, 1},
+	{3, 16, 1},
+	{3, 15, 30},
+	{5, -6, -18 - 30 - 12},
+}
+
+func TestAddDate(t *testing.T) {
+	t0 := Date(2011, 11, 18, 7, 56, 35, 0, UTC)
+	t1 := Date(2016, 3, 19, 7, 56, 35, 0, UTC)
+	for _, at := range addDateTests {
+		time := t0.AddDate(at.years, at.months, at.days)
+		if !time.Equal(t1) {
+			t.Errorf("AddDate(%d, %d, %d) = %v, want %v",
+				at.years, at.months, at.days,
+				time, t1)
+		}
+	}
+}
+
+var daysInTests = []struct {
+	year, month, di int
+}{
+	{2011, 1, 31},  // January, first month, 31 days
+	{2011, 2, 28},  // February, non-leap year, 28 days
+	{2012, 2, 29},  // February, leap year, 29 days
+	{2011, 6, 30},  // June, 30 days
+	{2011, 12, 31}, // December, last month, 31 days
+}
+
+func TestDaysIn(t *testing.T) {
+	// The daysIn function is not exported.
+	// Test the daysIn function via the `var DaysIn = daysIn`
+	// statement in the internal_test.go file.
+	for _, tt := range daysInTests {
+		di := DaysIn(Month(tt.month), tt.year)
+		if di != tt.di {
+			t.Errorf("got %d; expected %d for %d-%02d",
+				di, tt.di, tt.year, tt.month)
+		}
+	}
+}
+
+func TestAddToExactSecond(t *testing.T) {
+	// Add an amount to the current time to round it up to the next exact second.
+	// This test checks that the nsec field still lies within the range [0, 999999999].
+	t1 := Now()
+	t2 := t1.Add(Second - Duration(t1.Nanosecond()))
+	sec := (t1.Second() + 1) % 60
+	if t2.Second() != sec || t2.Nanosecond() != 0 {
+		t.Errorf("sec = %d, nsec = %d, want sec = %d, nsec = 0", t2.Second(), t2.Nanosecond(), sec)
+	}
+}
+
+func equalTimeAndZone(a, b Time) bool {
+	aname, aoffset := a.Zone()
+	bname, boffset := b.Zone()
+	return a.Equal(b) && aoffset == boffset && aname == bname
+}
+
+var gobTests = []Time{
+	Date(0, 1, 2, 3, 4, 5, 6, UTC),
+	Date(7, 8, 9, 10, 11, 12, 13, FixedZone("", 0)),
+	Unix(81985467080890095, 0x76543210), // Time.sec: 0x0123456789ABCDEF
+	{}, // nil location
+	Date(1, 2, 3, 4, 5, 6, 7, FixedZone("", 32767*60)),
+	Date(1, 2, 3, 4, 5, 6, 7, FixedZone("", -32768*60)),
+}
+
+func TestTimeGob(t *testing.T) {
+	var b bytes.Buffer
+	enc := gob.NewEncoder(&b)
+	dec := gob.NewDecoder(&b)
+	for _, tt := range gobTests {
+		var gobtt Time
+		if err := enc.Encode(&tt); err != nil {
+			t.Errorf("%v gob Encode error = %q, want nil", tt, err)
+		} else if err := dec.Decode(&gobtt); err != nil {
+			t.Errorf("%v gob Decode error = %q, want nil", tt, err)
+		} else if !equalTimeAndZone(gobtt, tt) {
+			t.Errorf("Decoded time = %v, want %v", gobtt, tt)
+		}
+		b.Reset()
+	}
+}
+
+var invalidEncodingTests = []struct {
+	bytes []byte
+	want  string
+}{
+	{[]byte{}, "Time.UnmarshalBinary: no data"},
+	{[]byte{0, 2, 3}, "Time.UnmarshalBinary: unsupported version"},
+	{[]byte{1, 2, 3}, "Time.UnmarshalBinary: invalid length"},
+}
+
+func TestInvalidTimeGob(t *testing.T) {
+	for _, tt := range invalidEncodingTests {
+		var ignored Time
+		err := ignored.GobDecode(tt.bytes)
+		if err == nil || err.Error() != tt.want {
+			t.Errorf("time.GobDecode(%#v) error = %v, want %v", tt.bytes, err, tt.want)
+		}
+		err = ignored.UnmarshalBinary(tt.bytes)
+		if err == nil || err.Error() != tt.want {
+			t.Errorf("time.UnmarshalBinary(%#v) error = %v, want %v", tt.bytes, err, tt.want)
+		}
+	}
+}
+
+var notEncodableTimes = []struct {
+	time Time
+	want string
+}{
+	{Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 1)), "Time.MarshalBinary: zone offset has fractional minute"},
+	{Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -1*60)), "Time.MarshalBinary: unexpected zone offset"},
+	{Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -32769*60)), "Time.MarshalBinary: unexpected zone offset"},
+	{Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 32768*60)), "Time.MarshalBinary: unexpected zone offset"},
+}
+
+func TestNotGobEncodableTime(t *testing.T) {
+	for _, tt := range notEncodableTimes {
+		_, err := tt.time.GobEncode()
+		if err == nil || err.Error() != tt.want {
+			t.Errorf("%v GobEncode error = %v, want %v", tt.time, err, tt.want)
+		}
+		_, err = tt.time.MarshalBinary()
+		if err == nil || err.Error() != tt.want {
+			t.Errorf("%v MarshalBinary error = %v, want %v", tt.time, err, tt.want)
+		}
+	}
+}
+
+var jsonTests = []struct {
+	time Time
+	json string
+}{
+	{Date(9999, 4, 12, 23, 20, 50, 520*1e6, UTC), `"9999-04-12T23:20:50.52Z"`},
+	{Date(1996, 12, 19, 16, 39, 57, 0, Local), `"1996-12-19T16:39:57-08:00"`},
+	{Date(0, 1, 1, 0, 0, 0, 1, FixedZone("", 1*60)), `"0000-01-01T00:00:00.000000001+00:01"`},
+}
+
+func TestTimeJSON(t *testing.T) {
+	for _, tt := range jsonTests {
+		var jsonTime Time
+
+		if jsonBytes, err := json.Marshal(tt.time); err != nil {
+			t.Errorf("%v json.Marshal error = %v, want nil", tt.time, err)
+		} else if string(jsonBytes) != tt.json {
+			t.Errorf("%v JSON = %#q, want %#q", tt.time, string(jsonBytes), tt.json)
+		} else if err = json.Unmarshal(jsonBytes, &jsonTime); err != nil {
+			t.Errorf("%v json.Unmarshal error = %v, want nil", tt.time, err)
+		} else if !equalTimeAndZone(jsonTime, tt.time) {
+			t.Errorf("Unmarshaled time = %v, want %v", jsonTime, tt.time)
+		}
+	}
+}
+
+func TestInvalidTimeJSON(t *testing.T) {
+	var tt Time
+	err := json.Unmarshal([]byte(`{"now is the time":"buddy"}`), &tt)
+	_, isParseErr := err.(*ParseError)
+	if !isParseErr {
+		t.Errorf("expected *time.ParseError unmarshaling JSON, got %v", err)
+	}
+}
+
+var notJSONEncodableTimes = []struct {
+	time Time
+	want string
+}{
+	{Date(10000, 1, 1, 0, 0, 0, 0, UTC), "Time.MarshalJSON: year outside of range [0,9999]"},
+	{Date(-1, 1, 1, 0, 0, 0, 0, UTC), "Time.MarshalJSON: year outside of range [0,9999]"},
+}
+
+func TestNotJSONEncodableTime(t *testing.T) {
+	for _, tt := range notJSONEncodableTimes {
+		_, err := tt.time.MarshalJSON()
+		if err == nil || err.Error() != tt.want {
+			t.Errorf("%v MarshalJSON error = %v, want %v", tt.time, err, tt.want)
+		}
+	}
+}
+
+var parseDurationTests = []struct {
+	in   string
+	ok   bool
+	want Duration
+}{
+	// simple
+	{"0", true, 0},
+	{"5s", true, 5 * Second},
+	{"30s", true, 30 * Second},
+	{"1478s", true, 1478 * Second},
+	// sign
+	{"-5s", true, -5 * Second},
+	{"+5s", true, 5 * Second},
+	{"-0", true, 0},
+	{"+0", true, 0},
+	// decimal
+	{"5.0s", true, 5 * Second},
+	{"5.6s", true, 5*Second + 600*Millisecond},
+	{"5.s", true, 5 * Second},
+	{".5s", true, 500 * Millisecond},
+	{"1.0s", true, 1 * Second},
+	{"1.00s", true, 1 * Second},
+	{"1.004s", true, 1*Second + 4*Millisecond},
+	{"1.0040s", true, 1*Second + 4*Millisecond},
+	{"100.00100s", true, 100*Second + 1*Millisecond},
+	// different units
+	{"10ns", true, 10 * Nanosecond},
+	{"11us", true, 11 * Microsecond},
+	{"12µs", true, 12 * Microsecond}, // U+00B5
+	{"12μs", true, 12 * Microsecond}, // U+03BC
+	{"13ms", true, 13 * Millisecond},
+	{"14s", true, 14 * Second},
+	{"15m", true, 15 * Minute},
+	{"16h", true, 16 * Hour},
+	// composite durations
+	{"3h30m", true, 3*Hour + 30*Minute},
+	{"10.5s4m", true, 4*Minute + 10*Second + 500*Millisecond},
+	{"-2m3.4s", true, -(2*Minute + 3*Second + 400*Millisecond)},
+	{"1h2m3s4ms5us6ns", true, 1*Hour + 2*Minute + 3*Second + 4*Millisecond + 5*Microsecond + 6*Nanosecond},
+	{"39h9m14.425s", true, 39*Hour + 9*Minute + 14*Second + 425*Millisecond},
+	// large value
+	{"52763797000ns", true, 52763797000 * Nanosecond},
+	// more than 9 digits after decimal point, see http://golang.org/issue/6617
+	{"0.3333333333333333333h", true, 20 * Minute},
+
+	// errors
+	{"", false, 0},
+	{"3", false, 0},
+	{"-", false, 0},
+	{"s", false, 0},
+	{".", false, 0},
+	{"-.", false, 0},
+	{".s", false, 0},
+	{"+.s", false, 0},
+	{"3000000h", false, 0}, // overflow
+}
+
+func TestParseDuration(t *testing.T) {
+	for _, tc := range parseDurationTests {
+		d, err := ParseDuration(tc.in)
+		if tc.ok && (err != nil || d != tc.want) {
+			t.Errorf("ParseDuration(%q) = %v, %v, want %v, nil", tc.in, d, err, tc.want)
+		} else if !tc.ok && err == nil {
+			t.Errorf("ParseDuration(%q) = _, nil, want _, non-nil", tc.in)
+		}
+	}
+}
+
+func TestParseDurationRoundTrip(t *testing.T) {
+	for i := 0; i < 100; i++ {
+		// Resolutions finer than milliseconds will result in
+		// imprecise round-trips.
+		d0 := Duration(rand.Int31()) * Millisecond
+		s := d0.String()
+		d1, err := ParseDuration(s)
+		if err != nil || d0 != d1 {
+			t.Errorf("round-trip failed: %d => %q => %d, %v", d0, s, d1, err)
+		}
+	}
+}
+
+// golang.org/issue/4622
+func TestLocationRace(t *testing.T) {
+	ResetLocalOnceForTest() // reset the Once to trigger the race
+
+	c := make(chan string, 1)
+	go func() {
+		c <- Now().String()
+	}()
+	Now().String()
+	<-c
+	Sleep(100 * Millisecond)
+
+	// Back to Los Angeles for subsequent tests:
+	ForceUSPacificForTesting()
+}
+
+var (
+	t Time
+	u int64
+)
+
+var mallocTest = []struct {
+	count int
+	desc  string
+	fn    func()
+}{
+	{0, `time.Now()`, func() { t = Now() }},
+	{0, `time.Now().UnixNano()`, func() { u = Now().UnixNano() }},
+}
+
+func TestCountMallocs(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping malloc count in short mode")
+	}
+	if runtime.GOMAXPROCS(0) > 1 {
+		t.Skip("skipping; GOMAXPROCS>1")
+	}
+	for _, mt := range mallocTest {
+		allocs := int(testing.AllocsPerRun(100, mt.fn))
+		if allocs > mt.count {
+			t.Errorf("%s: %d allocs, want %d", mt.desc, allocs, mt.count)
+		}
+	}
+}
+
+func TestLoadFixed(t *testing.T) {
+	// Issue 4064: handle locations without any zone transitions.
+	loc, err := LoadLocation("Etc/GMT+1")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// The tzdata name Etc/GMT+1 uses "east is negative",
+	// but Go and most other systems use "east is positive".
+	// So GMT+1 corresponds to -3600 in the Go zone, not +3600.
+	name, offset := Now().In(loc).Zone()
+	if name != "GMT+1" || offset != -1*60*60 {
+		t.Errorf("Now().In(loc).Zone() = %q, %d, want %q, %d", name, offset, "GMT+1", -1*60*60)
+	}
+}
+
+const (
+	minDuration Duration = -1 << 63
+	maxDuration Duration = 1<<63 - 1
+)
+
+var subTests = []struct {
+	t Time
+	u Time
+	d Duration
+}{
+	{Time{}, Time{}, Duration(0)},
+	{Date(2009, 11, 23, 0, 0, 0, 1, UTC), Date(2009, 11, 23, 0, 0, 0, 0, UTC), Duration(1)},
+	{Date(2009, 11, 23, 0, 0, 0, 0, UTC), Date(2009, 11, 24, 0, 0, 0, 0, UTC), -24 * Hour},
+	{Date(2009, 11, 24, 0, 0, 0, 0, UTC), Date(2009, 11, 23, 0, 0, 0, 0, UTC), 24 * Hour},
+	{Date(-2009, 11, 24, 0, 0, 0, 0, UTC), Date(-2009, 11, 23, 0, 0, 0, 0, UTC), 24 * Hour},
+	{Time{}, Date(2109, 11, 23, 0, 0, 0, 0, UTC), Duration(minDuration)},
+	{Date(2109, 11, 23, 0, 0, 0, 0, UTC), Time{}, Duration(maxDuration)},
+	{Time{}, Date(-2109, 11, 23, 0, 0, 0, 0, UTC), Duration(maxDuration)},
+	{Date(-2109, 11, 23, 0, 0, 0, 0, UTC), Time{}, Duration(minDuration)},
+	{Date(2290, 1, 1, 0, 0, 0, 0, UTC), Date(2000, 1, 1, 0, 0, 0, 0, UTC), 290*365*24*Hour + 71*24*Hour},
+	{Date(2300, 1, 1, 0, 0, 0, 0, UTC), Date(2000, 1, 1, 0, 0, 0, 0, UTC), Duration(maxDuration)},
+	{Date(2000, 1, 1, 0, 0, 0, 0, UTC), Date(2290, 1, 1, 0, 0, 0, 0, UTC), -290*365*24*Hour - 71*24*Hour},
+	{Date(2000, 1, 1, 0, 0, 0, 0, UTC), Date(2300, 1, 1, 0, 0, 0, 0, UTC), Duration(minDuration)},
+}
+
+func TestSub(t *testing.T) {
+	for i, st := range subTests {
+		got := st.t.Sub(st.u)
+		if got != st.d {
+			t.Errorf("#%d: Sub(%v, %v): got %v; want %v", i, st.t, st.u, got, st.d)
+		}
+	}
+}
+
+var nsDurationTests = []struct {
+	d    Duration
+	want int64
+}{
+	{Duration(-1000), -1000},
+	{Duration(-1), -1},
+	{Duration(1), 1},
+	{Duration(1000), 1000},
+}
+
+func TestDurationNanoseconds(t *testing.T) {
+	for _, tt := range nsDurationTests {
+		if got := tt.d.Nanoseconds(); got != tt.want {
+			t.Errorf("d.Nanoseconds() = %d; want: %d", got, tt.want)
+		}
+	}
+}
+
+var minDurationTests = []struct {
+	d    Duration
+	want float64
+}{
+	{Duration(-60000000000), -1},
+	{Duration(-1), -1 / 60e9},
+	{Duration(1), 1 / 60e9},
+	{Duration(60000000000), 1},
+}
+
+func TestDurationMinutes(t *testing.T) {
+	for _, tt := range minDurationTests {
+		if got := tt.d.Minutes(); got != tt.want {
+			t.Errorf("d.Minutes() = %g; want: %g", got, tt.want)
+		}
+	}
+}
+
+var hourDurationTests = []struct {
+	d    Duration
+	want float64
+}{
+	{Duration(-3600000000000), -1},
+	{Duration(-1), -1 / 3600e9},
+	{Duration(1), 1 / 3600e9},
+	{Duration(3600000000000), 1},
+}
+
+func TestDurationHours(t *testing.T) {
+	for _, tt := range hourDurationTests {
+		if got := tt.d.Hours(); got != tt.want {
+			t.Errorf("d.Hours() = %g; want: %g", got, tt.want)
+		}
+	}
+}
+
+func BenchmarkNow(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		t = Now()
+	}
+}
+
+func BenchmarkNowUnixNano(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		u = Now().UnixNano()
+	}
+}
+
+func BenchmarkFormat(b *testing.B) {
+	t := Unix(1265346057, 0)
+	for i := 0; i < b.N; i++ {
+		t.Format("Mon Jan  2 15:04:05 2006")
+	}
+}
+
+func BenchmarkFormatNow(b *testing.B) {
+	// Like BenchmarkFormat, but easier, because the time zone
+	// lookup cache is optimized for the present.
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		t.Format("Mon Jan  2 15:04:05 2006")
+	}
+}
+
+func BenchmarkParse(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Parse(ANSIC, "Mon Jan  2 15:04:05 2006")
+	}
+}
+
+func BenchmarkHour(b *testing.B) {
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		_ = t.Hour()
+	}
+}
+
+func BenchmarkSecond(b *testing.B) {
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		_ = t.Second()
+	}
+}
+
+func BenchmarkYear(b *testing.B) {
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		_ = t.Year()
+	}
+}
+
+func BenchmarkDay(b *testing.B) {
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		_ = t.Day()
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/time/zoneinfo.go b/third_party/gofrontend/libgo/go/time/zoneinfo.go
new file mode 100644
index 0000000..c8e53a2
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/zoneinfo.go
@@ -0,0 +1,287 @@
+// 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.
+
+package time
+
+import (
+	"sync"
+	"syscall"
+)
+
+// A Location maps time instants to the zone in use at that time.
+// Typically, the Location represents the collection of time offsets
+// in use in a geographical area, such as CEST and CET for central Europe.
+type Location struct {
+	name string
+	zone []zone
+	tx   []zoneTrans
+
+	// Most lookups will be for the current time.
+	// To avoid the binary search through tx, keep a
+	// static one-element cache that gives the correct
+	// zone for the time when the Location was created.
+	// if cacheStart <= t <= cacheEnd,
+	// lookup can return cacheZone.
+	// The units for cacheStart and cacheEnd are seconds
+	// since January 1, 1970 UTC, to match the argument
+	// to lookup.
+	cacheStart int64
+	cacheEnd   int64
+	cacheZone  *zone
+}
+
+// A zone represents a single time zone such as CEST or CET.
+type zone struct {
+	name   string // abbreviated name, "CET"
+	offset int    // seconds east of UTC
+	isDST  bool   // is this zone Daylight Savings Time?
+}
+
+// A zoneTrans represents a single time zone transition.
+type zoneTrans struct {
+	when         int64 // transition time, in seconds since 1970 GMT
+	index        uint8 // the index of the zone that goes into effect at that time
+	isstd, isutc bool  // ignored - no idea what these mean
+}
+
+// alpha and omega are the beginning and end of time for zone
+// transitions.
+const (
+	alpha = -1 << 63  // math.MinInt64
+	omega = 1<<63 - 1 // math.MaxInt64
+)
+
+// UTC represents Universal Coordinated Time (UTC).
+var UTC *Location = &utcLoc
+
+// utcLoc is separate so that get can refer to &utcLoc
+// and ensure that it never returns a nil *Location,
+// even if a badly behaved client has changed UTC.
+var utcLoc = Location{name: "UTC"}
+
+// Local represents the system's local time zone.
+var Local *Location = &localLoc
+
+// localLoc is separate so that initLocal can initialize
+// it even if a client has changed Local.
+var localLoc Location
+var localOnce sync.Once
+
+func (l *Location) get() *Location {
+	if l == nil {
+		return &utcLoc
+	}
+	if l == &localLoc {
+		localOnce.Do(initLocal)
+	}
+	return l
+}
+
+// String returns a descriptive name for the time zone information,
+// corresponding to the argument to LoadLocation.
+func (l *Location) String() string {
+	return l.get().name
+}
+
+// FixedZone returns a Location that always uses
+// the given zone name and offset (seconds east of UTC).
+func FixedZone(name string, offset int) *Location {
+	l := &Location{
+		name:       name,
+		zone:       []zone{{name, offset, false}},
+		tx:         []zoneTrans{{alpha, 0, false, false}},
+		cacheStart: alpha,
+		cacheEnd:   omega,
+	}
+	l.cacheZone = &l.zone[0]
+	return l
+}
+
+// lookup returns information about the time zone in use at an
+// instant in time expressed as seconds since January 1, 1970 00:00:00 UTC.
+//
+// The returned information gives the name of the zone (such as "CET"),
+// the start and end times bracketing sec when that zone is in effect,
+// the offset in seconds east of UTC (such as -5*60*60), and whether
+// the daylight savings is being observed at that time.
+func (l *Location) lookup(sec int64) (name string, offset int, isDST bool, start, end int64) {
+	l = l.get()
+
+	if len(l.zone) == 0 {
+		name = "UTC"
+		offset = 0
+		isDST = false
+		start = alpha
+		end = omega
+		return
+	}
+
+	if zone := l.cacheZone; zone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
+		name = zone.name
+		offset = zone.offset
+		isDST = zone.isDST
+		start = l.cacheStart
+		end = l.cacheEnd
+		return
+	}
+
+	if len(l.tx) == 0 || sec < l.tx[0].when {
+		zone := &l.zone[l.lookupFirstZone()]
+		name = zone.name
+		offset = zone.offset
+		isDST = zone.isDST
+		start = alpha
+		if len(l.tx) > 0 {
+			end = l.tx[0].when
+		} else {
+			end = omega
+		}
+		return
+	}
+
+	// Binary search for entry with largest time <= sec.
+	// Not using sort.Search to avoid dependencies.
+	tx := l.tx
+	end = omega
+	lo := 0
+	hi := len(tx)
+	for hi-lo > 1 {
+		m := lo + (hi-lo)/2
+		lim := tx[m].when
+		if sec < lim {
+			end = lim
+			hi = m
+		} else {
+			lo = m
+		}
+	}
+	zone := &l.zone[tx[lo].index]
+	name = zone.name
+	offset = zone.offset
+	isDST = zone.isDST
+	start = tx[lo].when
+	// end = maintained during the search
+	return
+}
+
+// lookupFirstZone returns the index of the time zone to use for times
+// before the first transition time, or when there are no transition
+// times.
+//
+// The reference implementation in localtime.c from
+// http://www.iana.org/time-zones/repository/releases/tzcode2013g.tar.gz
+// implements the following algorithm for these cases:
+// 1) If the first zone is unused by the transitions, use it.
+// 2) Otherwise, if there are transition times, and the first
+//    transition is to a zone in daylight time, find the first
+//    non-daylight-time zone before and closest to the first transition
+//    zone.
+// 3) Otherwise, use the first zone that is not daylight time, if
+//    there is one.
+// 4) Otherwise, use the first zone.
+func (l *Location) lookupFirstZone() int {
+	// Case 1.
+	if !l.firstZoneUsed() {
+		return 0
+	}
+
+	// Case 2.
+	if len(l.tx) > 0 && l.zone[l.tx[0].index].isDST {
+		for zi := int(l.tx[0].index) - 1; zi >= 0; zi-- {
+			if !l.zone[zi].isDST {
+				return zi
+			}
+		}
+	}
+
+	// Case 3.
+	for zi := range l.zone {
+		if !l.zone[zi].isDST {
+			return zi
+		}
+	}
+
+	// Case 4.
+	return 0
+}
+
+// firstZoneUsed returns whether the first zone is used by some
+// transition.
+func (l *Location) firstZoneUsed() bool {
+	for _, tx := range l.tx {
+		if tx.index == 0 {
+			return true
+		}
+	}
+	return false
+}
+
+// lookupName returns information about the time zone with
+// the given name (such as "EST") at the given pseudo-Unix time
+// (what the given time of day would be in UTC).
+func (l *Location) lookupName(name string, unix int64) (offset int, isDST bool, ok bool) {
+	l = l.get()
+
+	// First try for a zone with the right name that was actually
+	// in effect at the given time. (In Sydney, Australia, both standard
+	// and daylight-savings time are abbreviated "EST". Using the
+	// offset helps us pick the right one for the given time.
+	// It's not perfect: during the backward transition we might pick
+	// either one.)
+	for i := range l.zone {
+		zone := &l.zone[i]
+		if zone.name == name {
+			nam, offset, isDST, _, _ := l.lookup(unix - int64(zone.offset))
+			if nam == zone.name {
+				return offset, isDST, true
+			}
+		}
+	}
+
+	// Otherwise fall back to an ordinary name match.
+	for i := range l.zone {
+		zone := &l.zone[i]
+		if zone.name == name {
+			return zone.offset, zone.isDST, true
+		}
+	}
+
+	// Otherwise, give up.
+	return
+}
+
+// NOTE(rsc): Eventually we will need to accept the POSIX TZ environment
+// syntax too, but I don't feel like implementing it today.
+
+var zoneinfo, _ = syscall.Getenv("ZONEINFO")
+
+// LoadLocation returns the Location with the given name.
+//
+// If the name is "" or "UTC", LoadLocation returns UTC.
+// If the name is "Local", LoadLocation returns Local.
+//
+// Otherwise, the name is taken to be a location name corresponding to a file
+// in the IANA Time Zone database, such as "America/New_York".
+//
+// The time zone database needed by LoadLocation may not be
+// present on all systems, especially non-Unix systems.
+// LoadLocation looks in the directory or uncompressed zip file
+// named by the ZONEINFO environment variable, if any, then looks in
+// known installation locations on Unix systems,
+// and finally looks in $GOROOT/lib/time/zoneinfo.zip.
+func LoadLocation(name string) (*Location, error) {
+	if name == "" || name == "UTC" {
+		return UTC, nil
+	}
+	if name == "Local" {
+		return Local, nil
+	}
+	if zoneinfo != "" {
+		if z, err := loadZoneFile(zoneinfo, name); err == nil {
+			z.name = name
+			return z, nil
+		}
+	}
+	return loadLocation(name)
+}
diff --git a/third_party/gofrontend/libgo/go/time/zoneinfo_abbrs_windows.go b/third_party/gofrontend/libgo/go/time/zoneinfo_abbrs_windows.go
new file mode 100644
index 0000000..8033437
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/zoneinfo_abbrs_windows.go
@@ -0,0 +1,115 @@
+// Copyright 2013 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.
+
+// generated by genzabbrs.go from
+// http://unicode.org/cldr/data/common/supplemental/windowsZones.xml
+
+package time
+
+type abbr struct {
+	std string
+	dst string
+}
+
+var abbrs = map[string]abbr{
+	"Egypt Standard Time":             {"EET", "EET"},    // Africa/Cairo
+	"Morocco Standard Time":           {"WET", "WEST"},   // Africa/Casablanca
+	"South Africa Standard Time":      {"SAST", "SAST"},  // Africa/Johannesburg
+	"W. Central Africa Standard Time": {"WAT", "WAT"},    // Africa/Lagos
+	"E. Africa Standard Time":         {"EAT", "EAT"},    // Africa/Nairobi
+	"Namibia Standard Time":           {"WAT", "WAST"},   // Africa/Windhoek
+	"Alaskan Standard Time":           {"AKST", "AKDT"},  // America/Anchorage
+	"Paraguay Standard Time":          {"PYT", "PYST"},   // America/Asuncion
+	"Bahia Standard Time":             {"BRT", "BRST"},   // America/Bahia
+	"SA Pacific Standard Time":        {"COT", "COT"},    // America/Bogota
+	"Argentina Standard Time":         {"ART", "ART"},    // America/Buenos_Aires
+	"Venezuela Standard Time":         {"VET", "VET"},    // America/Caracas
+	"SA Eastern Standard Time":        {"GFT", "GFT"},    // America/Cayenne
+	"Central Standard Time":           {"CST", "CDT"},    // America/Chicago
+	"Mountain Standard Time (Mexico)": {"MST", "MDT"},    // America/Chihuahua
+	"Central Brazilian Standard Time": {"AMT", "AMST"},   // America/Cuiaba
+	"Mountain Standard Time":          {"MST", "MDT"},    // America/Denver
+	"Greenland Standard Time":         {"WGT", "WGST"},   // America/Godthab
+	"Central America Standard Time":   {"CST", "CST"},    // America/Guatemala
+	"Atlantic Standard Time":          {"AST", "ADT"},    // America/Halifax
+	"US Eastern Standard Time":        {"EST", "EDT"},    // America/Indianapolis
+	"SA Western Standard Time":        {"BOT", "BOT"},    // America/La_Paz
+	"Pacific Standard Time":           {"PST", "PDT"},    // America/Los_Angeles
+	"Central Standard Time (Mexico)":  {"CST", "CDT"},    // America/Mexico_City
+	"Montevideo Standard Time":        {"UYT", "UYST"},   // America/Montevideo
+	"Eastern Standard Time":           {"EST", "EDT"},    // America/New_York
+	"US Mountain Standard Time":       {"MST", "MST"},    // America/Phoenix
+	"Canada Central Standard Time":    {"CST", "CST"},    // America/Regina
+	"Pacific Standard Time (Mexico)":  {"PST", "PDT"},    // America/Santa_Isabel
+	"Pacific SA Standard Time":        {"CLT", "CLST"},   // America/Santiago
+	"E. South America Standard Time":  {"BRT", "BRST"},   // America/Sao_Paulo
+	"Newfoundland Standard Time":      {"NST", "NDT"},    // America/St_Johns
+	"Central Asia Standard Time":      {"ALMT", "ALMT"},  // Asia/Almaty
+	"Jordan Standard Time":            {"EET", "EEST"},   // Asia/Amman
+	"Arabic Standard Time":            {"AST", "AST"},    // Asia/Baghdad
+	"Azerbaijan Standard Time":        {"AZT", "AZST"},   // Asia/Baku
+	"SE Asia Standard Time":           {"ICT", "ICT"},    // Asia/Bangkok
+	"Middle East Standard Time":       {"EET", "EEST"},   // Asia/Beirut
+	"India Standard Time":             {"IST", "IST"},    // Asia/Calcutta
+	"Sri Lanka Standard Time":         {"IST", "IST"},    // Asia/Colombo
+	"Syria Standard Time":             {"EET", "EEST"},   // Asia/Damascus
+	"Bangladesh Standard Time":        {"BDT", "BDT"},    // Asia/Dhaka
+	"Arabian Standard Time":           {"GST", "GST"},    // Asia/Dubai
+	"North Asia East Standard Time":   {"IRKT", "IRKT"},  // Asia/Irkutsk
+	"Israel Standard Time":            {"IST", "IDT"},    // Asia/Jerusalem
+	"Afghanistan Standard Time":       {"AFT", "AFT"},    // Asia/Kabul
+	"Pakistan Standard Time":          {"PKT", "PKT"},    // Asia/Karachi
+	"Nepal Standard Time":             {"NPT", "NPT"},    // Asia/Katmandu
+	"North Asia Standard Time":        {"KRAT", "KRAT"},  // Asia/Krasnoyarsk
+	"Magadan Standard Time":           {"MAGT", "MAGT"},  // Asia/Magadan
+	"E. Europe Standard Time":         {"EET", "EEST"},   // Asia/Nicosia
+	"N. Central Asia Standard Time":   {"NOVT", "NOVT"},  // Asia/Novosibirsk
+	"Myanmar Standard Time":           {"MMT", "MMT"},    // Asia/Rangoon
+	"Arab Standard Time":              {"AST", "AST"},    // Asia/Riyadh
+	"Korea Standard Time":             {"KST", "KST"},    // Asia/Seoul
+	"China Standard Time":             {"CST", "CST"},    // Asia/Shanghai
+	"Singapore Standard Time":         {"SGT", "SGT"},    // Asia/Singapore
+	"Taipei Standard Time":            {"CST", "CST"},    // Asia/Taipei
+	"West Asia Standard Time":         {"UZT", "UZT"},    // Asia/Tashkent
+	"Georgian Standard Time":          {"GET", "GET"},    // Asia/Tbilisi
+	"Iran Standard Time":              {"IRST", "IRDT"},  // Asia/Tehran
+	"Tokyo Standard Time":             {"JST", "JST"},    // Asia/Tokyo
+	"Ulaanbaatar Standard Time":       {"ULAT", "ULAT"},  // Asia/Ulaanbaatar
+	"Vladivostok Standard Time":       {"VLAT", "VLAT"},  // Asia/Vladivostok
+	"Yakutsk Standard Time":           {"YAKT", "YAKT"},  // Asia/Yakutsk
+	"Ekaterinburg Standard Time":      {"YEKT", "YEKT"},  // Asia/Yekaterinburg
+	"Caucasus Standard Time":          {"AMT", "AMT"},    // Asia/Yerevan
+	"Azores Standard Time":            {"AZOT", "AZOST"}, // Atlantic/Azores
+	"Cape Verde Standard Time":        {"CVT", "CVT"},    // Atlantic/Cape_Verde
+	"Greenwich Standard Time":         {"GMT", "GMT"},    // Atlantic/Reykjavik
+	"Cen. Australia Standard Time":    {"CST", "CST"},    // Australia/Adelaide
+	"E. Australia Standard Time":      {"EST", "EST"},    // Australia/Brisbane
+	"AUS Central Standard Time":       {"CST", "CST"},    // Australia/Darwin
+	"Tasmania Standard Time":          {"EST", "EST"},    // Australia/Hobart
+	"W. Australia Standard Time":      {"WST", "WST"},    // Australia/Perth
+	"AUS Eastern Standard Time":       {"EST", "EST"},    // Australia/Sydney
+	"UTC":                            {"GMT", "GMT"},       // Etc/GMT
+	"UTC-11":                         {"GMT+11", "GMT+11"}, // Etc/GMT+11
+	"Dateline Standard Time":         {"GMT+12", "GMT+12"}, // Etc/GMT+12
+	"UTC-02":                         {"GMT+2", "GMT+2"},   // Etc/GMT+2
+	"UTC+12":                         {"GMT-12", "GMT-12"}, // Etc/GMT-12
+	"W. Europe Standard Time":        {"CET", "CEST"},      // Europe/Berlin
+	"GTB Standard Time":              {"EET", "EEST"},      // Europe/Bucharest
+	"Central Europe Standard Time":   {"CET", "CEST"},      // Europe/Budapest
+	"Turkey Standard Time":           {"EET", "EEST"},      // Europe/Istanbul
+	"Kaliningrad Standard Time":      {"FET", "FET"},       // Europe/Kaliningrad
+	"FLE Standard Time":              {"EET", "EEST"},      // Europe/Kiev
+	"GMT Standard Time":              {"GMT", "BST"},       // Europe/London
+	"Russian Standard Time":          {"MSK", "MSK"},       // Europe/Moscow
+	"Romance Standard Time":          {"CET", "CEST"},      // Europe/Paris
+	"Central European Standard Time": {"CET", "CEST"},      // Europe/Warsaw
+	"Mauritius Standard Time":        {"MUT", "MUT"},       // Indian/Mauritius
+	"Samoa Standard Time":            {"WST", "WST"},       // Pacific/Apia
+	"New Zealand Standard Time":      {"NZST", "NZDT"},     // Pacific/Auckland
+	"Fiji Standard Time":             {"FJT", "FJT"},       // Pacific/Fiji
+	"Central Pacific Standard Time":  {"SBT", "SBT"},       // Pacific/Guadalcanal
+	"Hawaiian Standard Time":         {"HST", "HST"},       // Pacific/Honolulu
+	"West Pacific Standard Time":     {"PGT", "PGT"},       // Pacific/Port_Moresby
+	"Tonga Standard Time":            {"TOT", "TOT"},       // Pacific/Tongatapu
+}
diff --git a/third_party/gofrontend/libgo/go/time/zoneinfo_plan9.go b/third_party/gofrontend/libgo/go/time/zoneinfo_plan9.go
new file mode 100644
index 0000000..4bb0cb3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/zoneinfo_plan9.go
@@ -0,0 +1,160 @@
+// 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.
+
+// Parse Plan 9 timezone(2) files.
+
+package time
+
+import (
+	"errors"
+	"runtime"
+	"syscall"
+)
+
+func isSpace(r rune) bool {
+	return r == ' ' || r == '\t' || r == '\n'
+}
+
+// Copied from strings to avoid a dependency.
+func fields(s string) []string {
+	// First count the fields.
+	n := 0
+	inField := false
+	for _, rune := range s {
+		wasInField := inField
+		inField = !isSpace(rune)
+		if inField && !wasInField {
+			n++
+		}
+	}
+
+	// Now create them.
+	a := make([]string, n)
+	na := 0
+	fieldStart := -1 // Set to -1 when looking for start of field.
+	for i, rune := range s {
+		if isSpace(rune) {
+			if fieldStart >= 0 {
+				a[na] = s[fieldStart:i]
+				na++
+				fieldStart = -1
+			}
+		} else if fieldStart == -1 {
+			fieldStart = i
+		}
+	}
+	if fieldStart >= 0 { // Last field might end at EOF.
+		a[na] = s[fieldStart:]
+	}
+	return a
+}
+
+func loadZoneDataPlan9(s string) (l *Location, err error) {
+	f := fields(s)
+	if len(f) < 4 {
+		if len(f) == 2 && f[0] == "GMT" {
+			return UTC, nil
+		}
+		return nil, badData
+	}
+
+	var zones [2]zone
+
+	// standard timezone offset
+	o, err := atoi(f[1])
+	if err != nil {
+		return nil, badData
+	}
+	zones[0] = zone{name: f[0], offset: o, isDST: false}
+
+	// alternate timezone offset
+	o, err = atoi(f[3])
+	if err != nil {
+		return nil, badData
+	}
+	zones[1] = zone{name: f[2], offset: o, isDST: true}
+
+	// transition time pairs
+	var tx []zoneTrans
+	f = f[4:]
+	for i := 0; i < len(f); i++ {
+		zi := 0
+		if i%2 == 0 {
+			zi = 1
+		}
+		t, err := atoi(f[i])
+		if err != nil {
+			return nil, badData
+		}
+		t -= zones[0].offset
+		tx = append(tx, zoneTrans{when: int64(t), index: uint8(zi)})
+	}
+
+	// Committed to succeed.
+	l = &Location{zone: zones[:], tx: tx}
+
+	// Fill in the cache with information about right now,
+	// since that will be the most common lookup.
+	sec, _ := now()
+	for i := range tx {
+		if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
+			l.cacheStart = tx[i].when
+			l.cacheEnd = omega
+			if i+1 < len(tx) {
+				l.cacheEnd = tx[i+1].when
+			}
+			l.cacheZone = &l.zone[tx[i].index]
+		}
+	}
+
+	return l, nil
+}
+
+func loadZoneFilePlan9(name string) (*Location, error) {
+	b, err := readFile(name)
+	if err != nil {
+		return nil, err
+	}
+	return loadZoneDataPlan9(string(b))
+}
+
+func initTestingZone() {
+	z, err := loadLocation("America/Los_Angeles")
+	if err != nil {
+		panic("cannot load America/Los_Angeles for testing: " + err.Error())
+	}
+	z.name = "Local"
+	localLoc = *z
+}
+
+func initLocal() {
+	t, ok := syscall.Getenv("timezone")
+	if ok {
+		if z, err := loadZoneDataPlan9(t); err == nil {
+			localLoc = *z
+			return
+		}
+	} else {
+		if z, err := loadZoneFilePlan9("/adm/timezone/local"); err == nil {
+			localLoc = *z
+			localLoc.name = "Local"
+			return
+		}
+	}
+
+	// Fall back to UTC.
+	localLoc.name = "UTC"
+}
+
+func loadLocation(name string) (*Location, error) {
+	if z, err := loadZoneFile(runtime.GOROOT()+"/lib/time/zoneinfo.zip", name); err == nil {
+		z.name = name
+		return z, nil
+	}
+	return nil, errors.New("unknown time zone " + name)
+}
+
+func forceZipFileForTesting(zipOnly bool) {
+	// We only use the zip file anyway.
+}
diff --git a/third_party/gofrontend/libgo/go/time/zoneinfo_read.go b/third_party/gofrontend/libgo/go/time/zoneinfo_read.go
new file mode 100644
index 0000000..de9ebb4
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/zoneinfo_read.go
@@ -0,0 +1,343 @@
+// 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.
+
+// Parse "zoneinfo" time zone file.
+// This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others.
+// See tzfile(5), http://en.wikipedia.org/wiki/Zoneinfo,
+// and ftp://munnari.oz.au/pub/oldtz/
+
+package time
+
+import "errors"
+
+// Simple I/O interface to binary blob of data.
+type data struct {
+	p     []byte
+	error bool
+}
+
+func (d *data) read(n int) []byte {
+	if len(d.p) < n {
+		d.p = nil
+		d.error = true
+		return nil
+	}
+	p := d.p[0:n]
+	d.p = d.p[n:]
+	return p
+}
+
+func (d *data) big4() (n uint32, ok bool) {
+	p := d.read(4)
+	if len(p) < 4 {
+		d.error = true
+		return 0, false
+	}
+	return uint32(p[0])<<24 | uint32(p[1])<<16 | uint32(p[2])<<8 | uint32(p[3]), true
+}
+
+func (d *data) byte() (n byte, ok bool) {
+	p := d.read(1)
+	if len(p) < 1 {
+		d.error = true
+		return 0, false
+	}
+	return p[0], true
+}
+
+// Make a string by stopping at the first NUL
+func byteString(p []byte) string {
+	for i := 0; i < len(p); i++ {
+		if p[i] == 0 {
+			return string(p[0:i])
+		}
+	}
+	return string(p)
+}
+
+var badData = errors.New("malformed time zone information")
+
+func loadZoneData(bytes []byte) (l *Location, err error) {
+	d := data{bytes, false}
+
+	// 4-byte magic "TZif"
+	if magic := d.read(4); string(magic) != "TZif" {
+		return nil, badData
+	}
+
+	// 1-byte version, then 15 bytes of padding
+	var p []byte
+	if p = d.read(16); len(p) != 16 || p[0] != 0 && p[0] != '2' && p[0] != '3' {
+		return nil, badData
+	}
+
+	// six big-endian 32-bit integers:
+	//	number of UTC/local indicators
+	//	number of standard/wall indicators
+	//	number of leap seconds
+	//	number of transition times
+	//	number of local time zones
+	//	number of characters of time zone abbrev strings
+	const (
+		NUTCLocal = iota
+		NStdWall
+		NLeap
+		NTime
+		NZone
+		NChar
+	)
+	var n [6]int
+	for i := 0; i < 6; i++ {
+		nn, ok := d.big4()
+		if !ok {
+			return nil, badData
+		}
+		n[i] = int(nn)
+	}
+
+	// Transition times.
+	txtimes := data{d.read(n[NTime] * 4), false}
+
+	// Time zone indices for transition times.
+	txzones := d.read(n[NTime])
+
+	// Zone info structures
+	zonedata := data{d.read(n[NZone] * 6), false}
+
+	// Time zone abbreviations.
+	abbrev := d.read(n[NChar])
+
+	// Leap-second time pairs
+	d.read(n[NLeap] * 8)
+
+	// Whether tx times associated with local time types
+	// are specified as standard time or wall time.
+	isstd := d.read(n[NStdWall])
+
+	// Whether tx times associated with local time types
+	// are specified as UTC or local time.
+	isutc := d.read(n[NUTCLocal])
+
+	if d.error { // ran out of data
+		return nil, badData
+	}
+
+	// If version == 2 or 3, the entire file repeats, this time using
+	// 8-byte ints for txtimes and leap seconds.
+	// We won't need those until 2106.
+
+	// Now we can build up a useful data structure.
+	// First the zone information.
+	//	utcoff[4] isdst[1] nameindex[1]
+	zone := make([]zone, n[NZone])
+	for i := range zone {
+		var ok bool
+		var n uint32
+		if n, ok = zonedata.big4(); !ok {
+			return nil, badData
+		}
+		zone[i].offset = int(int32(n))
+		var b byte
+		if b, ok = zonedata.byte(); !ok {
+			return nil, badData
+		}
+		zone[i].isDST = b != 0
+		if b, ok = zonedata.byte(); !ok || int(b) >= len(abbrev) {
+			return nil, badData
+		}
+		zone[i].name = byteString(abbrev[b:])
+	}
+
+	// Now the transition time info.
+	tx := make([]zoneTrans, n[NTime])
+	for i := range tx {
+		var ok bool
+		var n uint32
+		if n, ok = txtimes.big4(); !ok {
+			return nil, badData
+		}
+		tx[i].when = int64(int32(n))
+		if int(txzones[i]) >= len(zone) {
+			return nil, badData
+		}
+		tx[i].index = txzones[i]
+		if i < len(isstd) {
+			tx[i].isstd = isstd[i] != 0
+		}
+		if i < len(isutc) {
+			tx[i].isutc = isutc[i] != 0
+		}
+	}
+
+	if len(tx) == 0 {
+		// Build fake transition to cover all time.
+		// This happens in fixed locations like "Etc/GMT0".
+		tx = append(tx, zoneTrans{when: alpha, index: 0})
+	}
+
+	// Committed to succeed.
+	l = &Location{zone: zone, tx: tx}
+
+	// Fill in the cache with information about right now,
+	// since that will be the most common lookup.
+	sec, _ := now()
+	for i := range tx {
+		if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
+			l.cacheStart = tx[i].when
+			l.cacheEnd = omega
+			if i+1 < len(tx) {
+				l.cacheEnd = tx[i+1].when
+			}
+			l.cacheZone = &l.zone[tx[i].index]
+		}
+	}
+
+	return l, nil
+}
+
+func loadZoneFile(dir, name string) (l *Location, err error) {
+	if len(dir) > 4 && dir[len(dir)-4:] == ".zip" {
+		return loadZoneZip(dir, name)
+	}
+	if dir != "" {
+		name = dir + "/" + name
+	}
+	buf, err := readFile(name)
+	if err != nil {
+		return
+	}
+	return loadZoneData(buf)
+}
+
+// There are 500+ zoneinfo files.  Rather than distribute them all
+// individually, we ship them in an uncompressed zip file.
+// Used this way, the zip file format serves as a commonly readable
+// container for the individual small files.  We choose zip over tar
+// because zip files have a contiguous table of contents, making
+// individual file lookups faster, and because the per-file overhead
+// in a zip file is considerably less than tar's 512 bytes.
+
+// get4 returns the little-endian 32-bit value in b.
+func get4(b []byte) int {
+	if len(b) < 4 {
+		return 0
+	}
+	return int(b[0]) | int(b[1])<<8 | int(b[2])<<16 | int(b[3])<<24
+}
+
+// get2 returns the little-endian 16-bit value in b.
+func get2(b []byte) int {
+	if len(b) < 2 {
+		return 0
+	}
+	return int(b[0]) | int(b[1])<<8
+}
+
+func loadZoneZip(zipfile, name string) (l *Location, err error) {
+	fd, err := open(zipfile)
+	if err != nil {
+		return nil, errors.New("open " + zipfile + ": " + err.Error())
+	}
+	defer closefd(fd)
+
+	const (
+		zecheader = 0x06054b50
+		zcheader  = 0x02014b50
+		ztailsize = 22
+
+		zheadersize = 30
+		zheader     = 0x04034b50
+	)
+
+	buf := make([]byte, ztailsize)
+	if err := preadn(fd, buf, -ztailsize); err != nil || get4(buf) != zecheader {
+		return nil, errors.New("corrupt zip file " + zipfile)
+	}
+	n := get2(buf[10:])
+	size := get4(buf[12:])
+	off := get4(buf[16:])
+
+	buf = make([]byte, size)
+	if err := preadn(fd, buf, off); err != nil {
+		return nil, errors.New("corrupt zip file " + zipfile)
+	}
+
+	for i := 0; i < n; i++ {
+		// zip entry layout:
+		//	0	magic[4]
+		//	4	madevers[1]
+		//	5	madeos[1]
+		//	6	extvers[1]
+		//	7	extos[1]
+		//	8	flags[2]
+		//	10	meth[2]
+		//	12	modtime[2]
+		//	14	moddate[2]
+		//	16	crc[4]
+		//	20	csize[4]
+		//	24	uncsize[4]
+		//	28	namelen[2]
+		//	30	xlen[2]
+		//	32	fclen[2]
+		//	34	disknum[2]
+		//	36	iattr[2]
+		//	38	eattr[4]
+		//	42	off[4]
+		//	46	name[namelen]
+		//	46+namelen+xlen+fclen - next header
+		//
+		if get4(buf) != zcheader {
+			break
+		}
+		meth := get2(buf[10:])
+		size := get4(buf[24:])
+		namelen := get2(buf[28:])
+		xlen := get2(buf[30:])
+		fclen := get2(buf[32:])
+		off := get4(buf[42:])
+		zname := buf[46 : 46+namelen]
+		buf = buf[46+namelen+xlen+fclen:]
+		if string(zname) != name {
+			continue
+		}
+		if meth != 0 {
+			return nil, errors.New("unsupported compression for " + name + " in " + zipfile)
+		}
+
+		// zip per-file header layout:
+		//	0	magic[4]
+		//	4	extvers[1]
+		//	5	extos[1]
+		//	6	flags[2]
+		//	8	meth[2]
+		//	10	modtime[2]
+		//	12	moddate[2]
+		//	14	crc[4]
+		//	18	csize[4]
+		//	22	uncsize[4]
+		//	26	namelen[2]
+		//	28	xlen[2]
+		//	30	name[namelen]
+		//	30+namelen+xlen - file data
+		//
+		buf = make([]byte, zheadersize+namelen)
+		if err := preadn(fd, buf, off); err != nil ||
+			get4(buf) != zheader ||
+			get2(buf[8:]) != meth ||
+			get2(buf[26:]) != namelen ||
+			string(buf[30:30+namelen]) != name {
+			return nil, errors.New("corrupt zip file " + zipfile)
+		}
+		xlen = get2(buf[28:])
+
+		buf = make([]byte, size)
+		if err := preadn(fd, buf, off+30+namelen+xlen); err != nil {
+			return nil, errors.New("corrupt zip file " + zipfile)
+		}
+
+		return loadZoneData(buf)
+	}
+
+	return nil, errors.New("cannot find " + name + " in zip file " + zipfile)
+}
diff --git a/third_party/gofrontend/libgo/go/time/zoneinfo_test.go b/third_party/gofrontend/libgo/go/time/zoneinfo_test.go
new file mode 100644
index 0000000..ede5330
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/zoneinfo_test.go
@@ -0,0 +1,66 @@
+// Copyright 2014 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 time_test
+
+import (
+	"testing"
+	"time"
+)
+
+func TestVersion3(t *testing.T) {
+	t.Skip("gccgo does not use the zip file")
+	time.ForceZipFileForTesting(true)
+	defer time.ForceZipFileForTesting(false)
+	_, err := time.LoadLocation("Asia/Jerusalem")
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+// Test that we get the correct results for times before the first
+// transition time.  To do this we explicitly check early dates in a
+// couple of specific timezones.
+func TestFirstZone(t *testing.T) {
+	t.Skip("gccgo does not use the zip file")
+
+	time.ForceZipFileForTesting(true)
+	defer time.ForceZipFileForTesting(false)
+
+	const format = "Mon, 02 Jan 2006 15:04:05 -0700 (MST)"
+	var tests = []struct {
+		zone  string
+		unix  int64
+		want1 string
+		want2 string
+	}{
+		{
+			"PST8PDT",
+			-1633269601,
+			"Sun, 31 Mar 1918 01:59:59 -0800 (PST)",
+			"Sun, 31 Mar 1918 03:00:00 -0700 (PDT)",
+		},
+		{
+			"Pacific/Fakaofo",
+			1325242799,
+			"Thu, 29 Dec 2011 23:59:59 -1100 (TKT)",
+			"Sat, 31 Dec 2011 00:00:00 +1300 (TKT)",
+		},
+	}
+
+	for _, test := range tests {
+		z, err := time.LoadLocation(test.zone)
+		if err != nil {
+			t.Fatal(err)
+		}
+		s := time.Unix(test.unix, 0).In(z).Format(format)
+		if s != test.want1 {
+			t.Errorf("for %s %d got %q want %q", test.zone, test.unix, s, test.want1)
+		}
+		s = time.Unix(test.unix+1, 0).In(z).Format(format)
+		if s != test.want2 {
+			t.Errorf("for %s %d got %q want %q", test.zone, test.unix, s, test.want2)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/time/zoneinfo_unix.go b/third_party/gofrontend/libgo/go/time/zoneinfo_unix.go
new file mode 100644
index 0000000..3fe8e55
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/zoneinfo_unix.go
@@ -0,0 +1,80 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+// Parse "zoneinfo" time zone file.
+// This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others.
+// See tzfile(5), http://en.wikipedia.org/wiki/Zoneinfo,
+// and ftp://munnari.oz.au/pub/oldtz/
+
+package time
+
+import (
+	"errors"
+	"runtime"
+	"syscall"
+)
+
+func initTestingZone() {
+	syscall.Setenv("TZ", "America/Los_Angeles")
+	initLocal()
+}
+
+// Many systems use /usr/share/zoneinfo, Solaris 2 has
+// /usr/share/lib/zoneinfo, IRIX 6 has /usr/lib/locale/TZ.
+var zoneDirs = []string{
+	"/usr/share/zoneinfo/",
+	"/usr/share/lib/zoneinfo/",
+	"/usr/lib/locale/TZ/",
+	runtime.GOROOT() + "/lib/time/zoneinfo.zip",
+}
+
+var origZoneDirs = zoneDirs
+
+func forceZipFileForTesting(zipOnly bool) {
+	zoneDirs = make([]string, len(origZoneDirs))
+	copy(zoneDirs, origZoneDirs)
+	if zipOnly {
+		for i := 0; i < len(zoneDirs)-1; i++ {
+			zoneDirs[i] = "/XXXNOEXIST"
+		}
+	}
+}
+
+func initLocal() {
+	// consult $TZ to find the time zone to use.
+	// no $TZ means use the system default /etc/localtime.
+	// $TZ="" means use UTC.
+	// $TZ="foo" means use /usr/share/zoneinfo/foo.
+
+	tz, ok := syscall.Getenv("TZ")
+	switch {
+	case !ok:
+		z, err := loadZoneFile("", "/etc/localtime")
+		if err == nil {
+			localLoc = *z
+			localLoc.name = "Local"
+			return
+		}
+	case tz != "" && tz != "UTC":
+		if z, err := loadLocation(tz); err == nil {
+			localLoc = *z
+			return
+		}
+	}
+
+	// Fall back to UTC.
+	localLoc.name = "UTC"
+}
+
+func loadLocation(name string) (*Location, error) {
+	for _, zoneDir := range zoneDirs {
+		if z, err := loadZoneFile(zoneDir, name); err == nil {
+			z.name = name
+			return z, nil
+		}
+	}
+	return nil, errors.New("unknown time zone " + name)
+}
diff --git a/third_party/gofrontend/libgo/go/time/zoneinfo_windows.go b/third_party/gofrontend/libgo/go/time/zoneinfo_windows.go
new file mode 100644
index 0000000..6046743
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/time/zoneinfo_windows.go
@@ -0,0 +1,270 @@
+// 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 time
+
+import (
+	"errors"
+	"runtime"
+	"syscall"
+	"unsafe"
+)
+
+// TODO(rsc): Fall back to copy of zoneinfo files.
+
+// BUG(brainman,rsc): On Windows, the operating system does not provide complete
+// time zone information.
+// The implementation assumes that this year's rules for daylight savings
+// time apply to all previous and future years as well.
+
+// getKeyValue retrieves the string value kname associated with the open registry key kh.
+func getKeyValue(kh syscall.Handle, kname string) (string, error) {
+	var buf [50]uint16 // buf needs to be large enough to fit zone descriptions
+	var typ uint32
+	n := uint32(len(buf) * 2) // RegQueryValueEx's signature expects array of bytes, not uint16
+	p, _ := syscall.UTF16PtrFromString(kname)
+	if err := syscall.RegQueryValueEx(kh, p, nil, &typ, (*byte)(unsafe.Pointer(&buf[0])), &n); err != nil {
+		return "", err
+	}
+	if typ != syscall.REG_SZ { // null terminated strings only
+		return "", errors.New("Key is not string")
+	}
+	return syscall.UTF16ToString(buf[:]), nil
+}
+
+// matchZoneKey checks if stdname and dstname match the corresponding "Std"
+// and "Dlt" key values in the kname key stored under the open registry key zones.
+func matchZoneKey(zones syscall.Handle, kname string, stdname, dstname string) (matched bool, err2 error) {
+	var h syscall.Handle
+	p, _ := syscall.UTF16PtrFromString(kname)
+	if err := syscall.RegOpenKeyEx(zones, p, 0, syscall.KEY_READ, &h); err != nil {
+		return false, err
+	}
+	defer syscall.RegCloseKey(h)
+
+	s, err := getKeyValue(h, "Std")
+	if err != nil {
+		return false, err
+	}
+	if s != stdname {
+		return false, nil
+	}
+	s, err = getKeyValue(h, "Dlt")
+	if err != nil {
+		return false, err
+	}
+	if s != dstname && dstname != stdname {
+		return false, nil
+	}
+	return true, nil
+}
+
+// toEnglishName searches the registry for an English name of a time zone
+// whose zone names are stdname and dstname and returns the English name.
+func toEnglishName(stdname, dstname string) (string, error) {
+	var zones syscall.Handle
+	p, _ := syscall.UTF16PtrFromString(`SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones`)
+	if err := syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, p, 0, syscall.KEY_READ, &zones); err != nil {
+		return "", err
+	}
+	defer syscall.RegCloseKey(zones)
+
+	var count uint32
+	if err := syscall.RegQueryInfoKey(zones, nil, nil, nil, &count, nil, nil, nil, nil, nil, nil, nil); err != nil {
+		return "", err
+	}
+
+	var buf [50]uint16 // buf needs to be large enough to fit zone descriptions
+	for i := uint32(0); i < count; i++ {
+		n := uint32(len(buf))
+		if syscall.RegEnumKeyEx(zones, i, &buf[0], &n, nil, nil, nil, nil) != nil {
+			continue
+		}
+		kname := syscall.UTF16ToString(buf[:])
+		matched, err := matchZoneKey(zones, kname, stdname, dstname)
+		if err == nil && matched {
+			return kname, nil
+		}
+	}
+	return "", errors.New(`English name for time zone "` + stdname + `" not found in registry`)
+}
+
+// extractCAPS extracts capital letters from description desc.
+func extractCAPS(desc string) string {
+	var short []rune
+	for _, c := range desc {
+		if 'A' <= c && c <= 'Z' {
+			short = append(short, rune(c))
+		}
+	}
+	return string(short)
+}
+
+// abbrev returns the abbreviations to use for the given zone z.
+func abbrev(z *syscall.Timezoneinformation) (std, dst string) {
+	stdName := syscall.UTF16ToString(z.StandardName[:])
+	a, ok := abbrs[stdName]
+	if !ok {
+		dstName := syscall.UTF16ToString(z.DaylightName[:])
+		// Perhaps stdName is not English. Try to convert it.
+		englishName, err := toEnglishName(stdName, dstName)
+		if err == nil {
+			a, ok = abbrs[englishName]
+			if ok {
+				return a.std, a.dst
+			}
+		}
+		// fallback to using capital letters
+		return extractCAPS(stdName), extractCAPS(dstName)
+	}
+	return a.std, a.dst
+}
+
+// pseudoUnix returns the pseudo-Unix time (seconds since Jan 1 1970 *LOCAL TIME*)
+// denoted by the system date+time d in the given year.
+// It is up to the caller to convert this local time into a UTC-based time.
+func pseudoUnix(year int, d *syscall.Systemtime) int64 {
+	// Windows specifies daylight savings information in "day in month" format:
+	// d.Month is month number (1-12)
+	// d.DayOfWeek is appropriate weekday (Sunday=0 to Saturday=6)
+	// d.Day is week within the month (1 to 5, where 5 is last week of the month)
+	// d.Hour, d.Minute and d.Second are absolute time
+	day := 1
+	t := Date(year, Month(d.Month), day, int(d.Hour), int(d.Minute), int(d.Second), 0, UTC)
+	i := int(d.DayOfWeek) - int(t.Weekday())
+	if i < 0 {
+		i += 7
+	}
+	day += i
+	if week := int(d.Day) - 1; week < 4 {
+		day += week * 7
+	} else {
+		// "Last" instance of the day.
+		day += 4 * 7
+		if day > daysIn(Month(d.Month), year) {
+			day -= 7
+		}
+	}
+	return t.sec + int64(day-1)*secondsPerDay + internalToUnix
+}
+
+func initLocalFromTZI(i *syscall.Timezoneinformation) {
+	l := &localLoc
+
+	nzone := 1
+	if i.StandardDate.Month > 0 {
+		nzone++
+	}
+	l.zone = make([]zone, nzone)
+
+	stdname, dstname := abbrev(i)
+
+	std := &l.zone[0]
+	std.name = stdname
+	if nzone == 1 {
+		// No daylight savings.
+		std.offset = -int(i.Bias) * 60
+		l.cacheStart = alpha
+		l.cacheEnd = omega
+		l.cacheZone = std
+		l.tx = make([]zoneTrans, 1)
+		l.tx[0].when = l.cacheStart
+		l.tx[0].index = 0
+		return
+	}
+
+	// StandardBias must be ignored if StandardDate is not set,
+	// so this computation is delayed until after the nzone==1
+	// return above.
+	std.offset = -int(i.Bias+i.StandardBias) * 60
+
+	dst := &l.zone[1]
+	dst.name = dstname
+	dst.offset = -int(i.Bias+i.DaylightBias) * 60
+	dst.isDST = true
+
+	// Arrange so that d0 is first transition date, d1 second,
+	// i0 is index of zone after first transition, i1 second.
+	d0 := &i.StandardDate
+	d1 := &i.DaylightDate
+	i0 := 0
+	i1 := 1
+	if d0.Month > d1.Month {
+		d0, d1 = d1, d0
+		i0, i1 = i1, i0
+	}
+
+	// 2 tx per year, 100 years on each side of this year
+	l.tx = make([]zoneTrans, 400)
+
+	t := Now().UTC()
+	year := t.Year()
+	txi := 0
+	for y := year - 100; y < year+100; y++ {
+		tx := &l.tx[txi]
+		tx.when = pseudoUnix(y, d0) - int64(l.zone[i1].offset)
+		tx.index = uint8(i0)
+		txi++
+
+		tx = &l.tx[txi]
+		tx.when = pseudoUnix(y, d1) - int64(l.zone[i0].offset)
+		tx.index = uint8(i1)
+		txi++
+	}
+}
+
+var usPacific = syscall.Timezoneinformation{
+	Bias: 8 * 60,
+	StandardName: [32]uint16{
+		'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e',
+	},
+	StandardDate: syscall.Systemtime{Month: 11, Day: 1, Hour: 2},
+	DaylightName: [32]uint16{
+		'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'D', 'a', 'y', 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e',
+	},
+	DaylightDate: syscall.Systemtime{Month: 3, Day: 2, Hour: 2},
+	DaylightBias: -60,
+}
+
+var aus = syscall.Timezoneinformation{
+	Bias: -10 * 60,
+	StandardName: [32]uint16{
+		'A', 'U', 'S', ' ', 'E', 'a', 's', 't', 'e', 'r', 'n', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e',
+	},
+	StandardDate: syscall.Systemtime{Month: 4, Day: 1, Hour: 3},
+	DaylightName: [32]uint16{
+		'A', 'U', 'S', ' ', 'E', 'a', 's', 't', 'e', 'r', 'n', ' ', 'D', 'a', 'y', 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e',
+	},
+	DaylightDate: syscall.Systemtime{Month: 10, Day: 1, Hour: 2},
+	DaylightBias: -60,
+}
+
+func initTestingZone() {
+	initLocalFromTZI(&usPacific)
+}
+
+func initAusTestingZone() {
+	initLocalFromTZI(&aus)
+}
+
+func initLocal() {
+	var i syscall.Timezoneinformation
+	if _, err := syscall.GetTimeZoneInformation(&i); err != nil {
+		localLoc.name = "UTC"
+		return
+	}
+	initLocalFromTZI(&i)
+}
+
+func loadLocation(name string) (*Location, error) {
+	if z, err := loadZoneFile(runtime.GOROOT()+`\lib\time\zoneinfo.zip`, name); err == nil {
+		z.name = name
+		return z, nil
+	}
+	return nil, errors.New("unknown time zone " + name)
+}
+
+func forceZipFileForTesting(zipOnly bool) {
+	// We only use the zip file anyway.
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/casetables.go b/third_party/gofrontend/libgo/go/unicode/casetables.go
new file mode 100644
index 0000000..29bf167
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/casetables.go
@@ -0,0 +1,20 @@
+// 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.
+
+// TODO: This file contains the special casing rules for Turkish and Azeri only.
+// It should encompass all the languages with special casing rules
+// and be generated automatically, but that requires some API
+// development first.
+
+package unicode
+
+var TurkishCase SpecialCase = _TurkishCase
+var _TurkishCase = SpecialCase{
+	CaseRange{0x0049, 0x0049, d{0, 0x131 - 0x49, 0}},
+	CaseRange{0x0069, 0x0069, d{0x130 - 0x69, 0, 0x130 - 0x69}},
+	CaseRange{0x0130, 0x0130, d{0, 0x69 - 0x130, 0}},
+	CaseRange{0x0131, 0x0131, d{0x49 - 0x131, 0, 0x49 - 0x131}},
+}
+
+var AzeriCase SpecialCase = _TurkishCase
diff --git a/third_party/gofrontend/libgo/go/unicode/digit.go b/third_party/gofrontend/libgo/go/unicode/digit.go
new file mode 100644
index 0000000..53171b3
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/digit.go
@@ -0,0 +1,13 @@
+// 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 unicode
+
+// IsDigit reports whether the rune is a decimal digit.
+func IsDigit(r rune) bool {
+	if r <= MaxLatin1 {
+		return '0' <= r && r <= '9'
+	}
+	return isExcludingLatin(Digit, r)
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/digit_test.go b/third_party/gofrontend/libgo/go/unicode/digit_test.go
new file mode 100644
index 0000000..551c42a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/digit_test.go
@@ -0,0 +1,126 @@
+// 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 unicode_test
+
+import (
+	"testing"
+	. "unicode"
+)
+
+var testDigit = []rune{
+	0x0030,
+	0x0039,
+	0x0661,
+	0x06F1,
+	0x07C9,
+	0x0966,
+	0x09EF,
+	0x0A66,
+	0x0AEF,
+	0x0B66,
+	0x0B6F,
+	0x0BE6,
+	0x0BEF,
+	0x0C66,
+	0x0CEF,
+	0x0D66,
+	0x0D6F,
+	0x0E50,
+	0x0E59,
+	0x0ED0,
+	0x0ED9,
+	0x0F20,
+	0x0F29,
+	0x1040,
+	0x1049,
+	0x1090,
+	0x1091,
+	0x1099,
+	0x17E0,
+	0x17E9,
+	0x1810,
+	0x1819,
+	0x1946,
+	0x194F,
+	0x19D0,
+	0x19D9,
+	0x1B50,
+	0x1B59,
+	0x1BB0,
+	0x1BB9,
+	0x1C40,
+	0x1C49,
+	0x1C50,
+	0x1C59,
+	0xA620,
+	0xA629,
+	0xA8D0,
+	0xA8D9,
+	0xA900,
+	0xA909,
+	0xAA50,
+	0xAA59,
+	0xFF10,
+	0xFF19,
+	0x104A1,
+	0x1D7CE,
+}
+
+var testLetter = []rune{
+	0x0041,
+	0x0061,
+	0x00AA,
+	0x00BA,
+	0x00C8,
+	0x00DB,
+	0x00F9,
+	0x02EC,
+	0x0535,
+	0x06E6,
+	0x093D,
+	0x0A15,
+	0x0B99,
+	0x0DC0,
+	0x0EDD,
+	0x1000,
+	0x1200,
+	0x1312,
+	0x1401,
+	0x1885,
+	0x2C00,
+	0xA800,
+	0xF900,
+	0xFA30,
+	0xFFDA,
+	0xFFDC,
+	0x10000,
+	0x10300,
+	0x10400,
+	0x20000,
+	0x2F800,
+	0x2FA1D,
+}
+
+func TestDigit(t *testing.T) {
+	for _, r := range testDigit {
+		if !IsDigit(r) {
+			t.Errorf("IsDigit(U+%04X) = false, want true", r)
+		}
+	}
+	for _, r := range testLetter {
+		if IsDigit(r) {
+			t.Errorf("IsDigit(U+%04X) = true, want false", r)
+		}
+	}
+}
+
+// Test that the special case in IsDigit agrees with the table
+func TestDigitOptimization(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		if Is(Digit, i) != IsDigit(i) {
+			t.Errorf("IsDigit(U+%04X) disagrees with Is(Digit)", i)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/graphic.go b/third_party/gofrontend/libgo/go/unicode/graphic.go
new file mode 100644
index 0000000..ba90b4e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/graphic.go
@@ -0,0 +1,144 @@
+// 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.
+
+package unicode
+
+// Bit masks for each code point under U+0100, for fast lookup.
+const (
+	pC     = 1 << iota // a control character.
+	pP                 // a punctuation character.
+	pN                 // a numeral.
+	pS                 // a symbolic character.
+	pZ                 // a spacing character.
+	pLu                // an upper-case letter.
+	pLl                // a lower-case letter.
+	pp                 // a printable character according to Go's definition.
+	pg     = pp | pZ   // a graphical character according to the Unicode definition.
+	pLo    = pLl | pLu // a letter that is neither upper nor lower case.
+	pLmask = pLo
+)
+
+// GraphicRanges defines the set of graphic characters according to Unicode.
+var GraphicRanges = []*RangeTable{
+	L, M, N, P, S, Zs,
+}
+
+// PrintRanges defines the set of printable characters according to Go.
+// ASCII space, U+0020, is handled separately.
+var PrintRanges = []*RangeTable{
+	L, M, N, P, S,
+}
+
+// IsGraphic reports whether the rune is defined as a Graphic by Unicode.
+// Such characters include letters, marks, numbers, punctuation, symbols, and
+// spaces, from categories L, M, N, P, S, Zs.
+func IsGraphic(r rune) bool {
+	// We convert to uint32 to avoid the extra test for negative,
+	// and in the index we convert to uint8 to avoid the range check.
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pg != 0
+	}
+	return In(r, GraphicRanges...)
+}
+
+// IsPrint reports whether the rune is defined as printable by Go. Such
+// characters include letters, marks, numbers, punctuation, symbols, and the
+// ASCII space character, from categories L, M, N, P, S and the ASCII space
+// character.  This categorization is the same as IsGraphic except that the
+// only spacing character is ASCII space, U+0020.
+func IsPrint(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pp != 0
+	}
+	return In(r, PrintRanges...)
+}
+
+// IsOneOf reports whether the rune is a member of one of the ranges.
+// The function "In" provides a nicer signature and should be used in preference to IsOneOf.
+func IsOneOf(ranges []*RangeTable, r rune) bool {
+	for _, inside := range ranges {
+		if Is(inside, r) {
+			return true
+		}
+	}
+	return false
+}
+
+// In reports whether the rune is a member of one of the ranges.
+func In(r rune, ranges ...*RangeTable) bool {
+	for _, inside := range ranges {
+		if Is(inside, r) {
+			return true
+		}
+	}
+	return false
+}
+
+// IsControl reports whether the rune is a control character.
+// The C (Other) Unicode category includes more code points
+// such as surrogates; use Is(C, r) to test for them.
+func IsControl(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pC != 0
+	}
+	// All control characters are < Latin1Max.
+	return false
+}
+
+// IsLetter reports whether the rune is a letter (category L).
+func IsLetter(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&(pLmask) != 0
+	}
+	return isExcludingLatin(Letter, r)
+}
+
+// IsMark reports whether the rune is a mark character (category M).
+func IsMark(r rune) bool {
+	// There are no mark characters in Latin-1.
+	return isExcludingLatin(Mark, r)
+}
+
+// IsNumber reports whether the rune is a number (category N).
+func IsNumber(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pN != 0
+	}
+	return isExcludingLatin(Number, r)
+}
+
+// IsPunct reports whether the rune is a Unicode punctuation character
+// (category P).
+func IsPunct(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pP != 0
+	}
+	return Is(Punct, r)
+}
+
+// IsSpace reports whether the rune is a space character as defined
+// by Unicode's White Space property; in the Latin-1 space
+// this is
+//	'\t', '\n', '\v', '\f', '\r', ' ', U+0085 (NEL), U+00A0 (NBSP).
+// Other definitions of spacing characters are set by category
+// Z and property Pattern_White_Space.
+func IsSpace(r rune) bool {
+	// This property isn't the same as Z; special-case it.
+	if uint32(r) <= MaxLatin1 {
+		switch r {
+		case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xA0:
+			return true
+		}
+		return false
+	}
+	return isExcludingLatin(White_Space, r)
+}
+
+// IsSymbol reports whether the rune is a symbolic character.
+func IsSymbol(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pS != 0
+	}
+	return isExcludingLatin(Symbol, r)
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/graphic_test.go b/third_party/gofrontend/libgo/go/unicode/graphic_test.go
new file mode 100644
index 0000000..c9f289c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/graphic_test.go
@@ -0,0 +1,122 @@
+// 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.
+
+package unicode_test
+
+import (
+	"testing"
+	. "unicode"
+)
+
+// Independently check that the special "Is" functions work
+// in the Latin-1 range through the property table.
+
+func TestIsControlLatin1(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		got := IsControl(i)
+		want := false
+		switch {
+		case 0x00 <= i && i <= 0x1F:
+			want = true
+		case 0x7F <= i && i <= 0x9F:
+			want = true
+		}
+		if got != want {
+			t.Errorf("%U incorrect: got %t; want %t", i, got, want)
+		}
+	}
+}
+
+func TestIsLetterLatin1(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		got := IsLetter(i)
+		want := Is(Letter, i)
+		if got != want {
+			t.Errorf("%U incorrect: got %t; want %t", i, got, want)
+		}
+	}
+}
+
+func TestIsUpperLatin1(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		got := IsUpper(i)
+		want := Is(Upper, i)
+		if got != want {
+			t.Errorf("%U incorrect: got %t; want %t", i, got, want)
+		}
+	}
+}
+
+func TestIsLowerLatin1(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		got := IsLower(i)
+		want := Is(Lower, i)
+		if got != want {
+			t.Errorf("%U incorrect: got %t; want %t", i, got, want)
+		}
+	}
+}
+
+func TestNumberLatin1(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		got := IsNumber(i)
+		want := Is(Number, i)
+		if got != want {
+			t.Errorf("%U incorrect: got %t; want %t", i, got, want)
+		}
+	}
+}
+
+func TestIsPrintLatin1(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		got := IsPrint(i)
+		want := In(i, PrintRanges...)
+		if i == ' ' {
+			want = true
+		}
+		if got != want {
+			t.Errorf("%U incorrect: got %t; want %t", i, got, want)
+		}
+	}
+}
+
+func TestIsGraphicLatin1(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		got := IsGraphic(i)
+		want := In(i, GraphicRanges...)
+		if got != want {
+			t.Errorf("%U incorrect: got %t; want %t", i, got, want)
+		}
+	}
+}
+
+func TestIsPunctLatin1(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		got := IsPunct(i)
+		want := Is(Punct, i)
+		if got != want {
+			t.Errorf("%U incorrect: got %t; want %t", i, got, want)
+		}
+	}
+}
+
+func TestIsSpaceLatin1(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		got := IsSpace(i)
+		want := Is(White_Space, i)
+		if got != want {
+			t.Errorf("%U incorrect: got %t; want %t", i, got, want)
+		}
+	}
+}
+
+func TestIsSymbolLatin1(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		got := IsSymbol(i)
+		want := Is(Symbol, i)
+		if got != want {
+			t.Errorf("%U incorrect: got %t; want %t", i, got, want)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/letter.go b/third_party/gofrontend/libgo/go/unicode/letter.go
new file mode 100644
index 0000000..977bd2b
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/letter.go
@@ -0,0 +1,354 @@
+// 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 unicode provides data and functions to test some properties of
+// Unicode code points.
+package unicode
+
+const (
+	MaxRune         = '\U0010FFFF' // Maximum valid Unicode code point.
+	ReplacementChar = '\uFFFD'     // Represents invalid code points.
+	MaxASCII        = '\u007F'     // maximum ASCII value.
+	MaxLatin1       = '\u00FF'     // maximum Latin-1 value.
+)
+
+// RangeTable defines a set of Unicode code points by listing the ranges of
+// code points within the set. The ranges are listed in two slices
+// to save space: a slice of 16-bit ranges and a slice of 32-bit ranges.
+// The two slices must be in sorted order and non-overlapping.
+// Also, R32 should contain only values >= 0x10000 (1<<16).
+type RangeTable struct {
+	R16         []Range16
+	R32         []Range32
+	LatinOffset int // number of entries in R16 with Hi <= MaxLatin1
+}
+
+// Range16 represents of a range of 16-bit Unicode code points.  The range runs from Lo to Hi
+// inclusive and has the specified stride.
+type Range16 struct {
+	Lo     uint16
+	Hi     uint16
+	Stride uint16
+}
+
+// Range32 represents of a range of Unicode code points and is used when one or
+// more of the values will not fit in 16 bits.  The range runs from Lo to Hi
+// inclusive and has the specified stride. Lo and Hi must always be >= 1<<16.
+type Range32 struct {
+	Lo     uint32
+	Hi     uint32
+	Stride uint32
+}
+
+// CaseRange represents a range of Unicode code points for simple (one
+// code point to one code point) case conversion.
+// The range runs from Lo to Hi inclusive, with a fixed stride of 1.  Deltas
+// are the number to add to the code point to reach the code point for a
+// different case for that character.  They may be negative.  If zero, it
+// means the character is in the corresponding case. There is a special
+// case representing sequences of alternating corresponding Upper and Lower
+// pairs.  It appears with a fixed Delta of
+//	{UpperLower, UpperLower, UpperLower}
+// The constant UpperLower has an otherwise impossible delta value.
+type CaseRange struct {
+	Lo    uint32
+	Hi    uint32
+	Delta d
+}
+
+// SpecialCase represents language-specific case mappings such as Turkish.
+// Methods of SpecialCase customize (by overriding) the standard mappings.
+type SpecialCase []CaseRange
+
+// BUG(r): There is no mechanism for full case folding, that is, for
+// characters that involve multiple runes in the input or output.
+
+// Indices into the Delta arrays inside CaseRanges for case mapping.
+const (
+	UpperCase = iota
+	LowerCase
+	TitleCase
+	MaxCase
+)
+
+type d [MaxCase]rune // to make the CaseRanges text shorter
+
+// If the Delta field of a CaseRange is UpperLower, it means
+// this CaseRange represents a sequence of the form (say)
+// Upper Lower Upper Lower.
+const (
+	UpperLower = MaxRune + 1 // (Cannot be a valid delta.)
+)
+
+// linearMax is the maximum size table for linear search for non-Latin1 rune.
+// Derived by running 'go test -calibrate'.
+const linearMax = 18
+
+// is16 reports whether r is in the sorted slice of 16-bit ranges.
+func is16(ranges []Range16, r uint16) bool {
+	if len(ranges) <= linearMax || r <= MaxLatin1 {
+		for i := range ranges {
+			range_ := &ranges[i]
+			if r < range_.Lo {
+				return false
+			}
+			if r <= range_.Hi {
+				return (r-range_.Lo)%range_.Stride == 0
+			}
+		}
+		return false
+	}
+
+	// binary search over ranges
+	lo := 0
+	hi := len(ranges)
+	for lo < hi {
+		m := lo + (hi-lo)/2
+		range_ := &ranges[m]
+		if range_.Lo <= r && r <= range_.Hi {
+			return (r-range_.Lo)%range_.Stride == 0
+		}
+		if r < range_.Lo {
+			hi = m
+		} else {
+			lo = m + 1
+		}
+	}
+	return false
+}
+
+// is32 reports whether r is in the sorted slice of 32-bit ranges.
+func is32(ranges []Range32, r uint32) bool {
+	if len(ranges) <= linearMax {
+		for i := range ranges {
+			range_ := &ranges[i]
+			if r < range_.Lo {
+				return false
+			}
+			if r <= range_.Hi {
+				return (r-range_.Lo)%range_.Stride == 0
+			}
+		}
+		return false
+	}
+
+	// binary search over ranges
+	lo := 0
+	hi := len(ranges)
+	for lo < hi {
+		m := lo + (hi-lo)/2
+		range_ := ranges[m]
+		if range_.Lo <= r && r <= range_.Hi {
+			return (r-range_.Lo)%range_.Stride == 0
+		}
+		if r < range_.Lo {
+			hi = m
+		} else {
+			lo = m + 1
+		}
+	}
+	return false
+}
+
+// Is reports whether the rune is in the specified table of ranges.
+func Is(rangeTab *RangeTable, r rune) bool {
+	r16 := rangeTab.R16
+	if len(r16) > 0 && r <= rune(r16[len(r16)-1].Hi) {
+		return is16(r16, uint16(r))
+	}
+	r32 := rangeTab.R32
+	if len(r32) > 0 && r >= rune(r32[0].Lo) {
+		return is32(r32, uint32(r))
+	}
+	return false
+}
+
+func isExcludingLatin(rangeTab *RangeTable, r rune) bool {
+	r16 := rangeTab.R16
+	if off := rangeTab.LatinOffset; len(r16) > off && r <= rune(r16[len(r16)-1].Hi) {
+		return is16(r16[off:], uint16(r))
+	}
+	r32 := rangeTab.R32
+	if len(r32) > 0 && r >= rune(r32[0].Lo) {
+		return is32(r32, uint32(r))
+	}
+	return false
+}
+
+// IsUpper reports whether the rune is an upper case letter.
+func IsUpper(r rune) bool {
+	// See comment in IsGraphic.
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pLmask == pLu
+	}
+	return isExcludingLatin(Upper, r)
+}
+
+// IsLower reports whether the rune is a lower case letter.
+func IsLower(r rune) bool {
+	// See comment in IsGraphic.
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pLmask == pLl
+	}
+	return isExcludingLatin(Lower, r)
+}
+
+// IsTitle reports whether the rune is a title case letter.
+func IsTitle(r rune) bool {
+	if r <= MaxLatin1 {
+		return false
+	}
+	return isExcludingLatin(Title, r)
+}
+
+// to maps the rune using the specified case mapping.
+func to(_case int, r rune, caseRange []CaseRange) rune {
+	if _case < 0 || MaxCase <= _case {
+		return ReplacementChar // as reasonable an error as any
+	}
+	// binary search over ranges
+	lo := 0
+	hi := len(caseRange)
+	for lo < hi {
+		m := lo + (hi-lo)/2
+		cr := caseRange[m]
+		if rune(cr.Lo) <= r && r <= rune(cr.Hi) {
+			delta := rune(cr.Delta[_case])
+			if delta > MaxRune {
+				// In an Upper-Lower sequence, which always starts with
+				// an UpperCase letter, the real deltas always look like:
+				//	{0, 1, 0}    UpperCase (Lower is next)
+				//	{-1, 0, -1}  LowerCase (Upper, Title are previous)
+				// The characters at even offsets from the beginning of the
+				// sequence are upper case; the ones at odd offsets are lower.
+				// The correct mapping can be done by clearing or setting the low
+				// bit in the sequence offset.
+				// The constants UpperCase and TitleCase are even while LowerCase
+				// is odd so we take the low bit from _case.
+				return rune(cr.Lo) + ((r-rune(cr.Lo))&^1 | rune(_case&1))
+			}
+			return r + delta
+		}
+		if r < rune(cr.Lo) {
+			hi = m
+		} else {
+			lo = m + 1
+		}
+	}
+	return r
+}
+
+// To maps the rune to the specified case: UpperCase, LowerCase, or TitleCase.
+func To(_case int, r rune) rune {
+	return to(_case, r, CaseRanges)
+}
+
+// ToUpper maps the rune to upper case.
+func ToUpper(r rune) rune {
+	if r <= MaxASCII {
+		if 'a' <= r && r <= 'z' {
+			r -= 'a' - 'A'
+		}
+		return r
+	}
+	return To(UpperCase, r)
+}
+
+// ToLower maps the rune to lower case.
+func ToLower(r rune) rune {
+	if r <= MaxASCII {
+		if 'A' <= r && r <= 'Z' {
+			r += 'a' - 'A'
+		}
+		return r
+	}
+	return To(LowerCase, r)
+}
+
+// ToTitle maps the rune to title case.
+func ToTitle(r rune) rune {
+	if r <= MaxASCII {
+		if 'a' <= r && r <= 'z' { // title case is upper case for ASCII
+			r -= 'a' - 'A'
+		}
+		return r
+	}
+	return To(TitleCase, r)
+}
+
+// ToUpper maps the rune to upper case giving priority to the special mapping.
+func (special SpecialCase) ToUpper(r rune) rune {
+	r1 := to(UpperCase, r, []CaseRange(special))
+	if r1 == r {
+		r1 = ToUpper(r)
+	}
+	return r1
+}
+
+// ToTitle maps the rune to title case giving priority to the special mapping.
+func (special SpecialCase) ToTitle(r rune) rune {
+	r1 := to(TitleCase, r, []CaseRange(special))
+	if r1 == r {
+		r1 = ToTitle(r)
+	}
+	return r1
+}
+
+// ToLower maps the rune to lower case giving priority to the special mapping.
+func (special SpecialCase) ToLower(r rune) rune {
+	r1 := to(LowerCase, r, []CaseRange(special))
+	if r1 == r {
+		r1 = ToLower(r)
+	}
+	return r1
+}
+
+// caseOrbit is defined in tables.go as []foldPair.  Right now all the
+// entries fit in uint16, so use uint16.  If that changes, compilation
+// will fail (the constants in the composite literal will not fit in uint16)
+// and the types here can change to uint32.
+type foldPair struct {
+	From uint16
+	To   uint16
+}
+
+// SimpleFold iterates over Unicode code points equivalent under
+// the Unicode-defined simple case folding.  Among the code points
+// equivalent to rune (including rune itself), SimpleFold returns the
+// smallest rune > r if one exists, or else the smallest rune >= 0.
+//
+// For example:
+//	SimpleFold('A') = 'a'
+//	SimpleFold('a') = 'A'
+//
+//	SimpleFold('K') = 'k'
+//	SimpleFold('k') = '\u212A' (Kelvin symbol, K)
+//	SimpleFold('\u212A') = 'K'
+//
+//	SimpleFold('1') = '1'
+//
+func SimpleFold(r rune) rune {
+	// Consult caseOrbit table for special cases.
+	lo := 0
+	hi := len(caseOrbit)
+	for lo < hi {
+		m := lo + (hi-lo)/2
+		if rune(caseOrbit[m].From) < r {
+			lo = m + 1
+		} else {
+			hi = m
+		}
+	}
+	if lo < len(caseOrbit) && rune(caseOrbit[lo].From) == r {
+		return rune(caseOrbit[lo].To)
+	}
+
+	// No folding specified.  This is a one- or two-element
+	// equivalence class containing rune and ToLower(rune)
+	// and ToUpper(rune) if they are different from rune.
+	if l := ToLower(r); l != r {
+		return l
+	}
+	return ToUpper(r)
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/letter_test.go b/third_party/gofrontend/libgo/go/unicode/letter_test.go
new file mode 100644
index 0000000..4ee11fb
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/letter_test.go
@@ -0,0 +1,535 @@
+// 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 unicode_test
+
+import (
+	"flag"
+	"fmt"
+	"runtime"
+	"sort"
+	"testing"
+	. "unicode"
+)
+
+var upperTest = []rune{
+	0x41,
+	0xc0,
+	0xd8,
+	0x100,
+	0x139,
+	0x14a,
+	0x178,
+	0x181,
+	0x376,
+	0x3cf,
+	0x1f2a,
+	0x2102,
+	0x2c00,
+	0x2c10,
+	0x2c20,
+	0xa650,
+	0xa722,
+	0xff3a,
+	0x10400,
+	0x1d400,
+	0x1d7ca,
+}
+
+var notupperTest = []rune{
+	0x40,
+	0x5b,
+	0x61,
+	0x185,
+	0x1b0,
+	0x377,
+	0x387,
+	0x2150,
+	0xffff,
+	0x10000,
+}
+
+var letterTest = []rune{
+	0x41,
+	0x61,
+	0xaa,
+	0xba,
+	0xc8,
+	0xdb,
+	0xf9,
+	0x2ec,
+	0x535,
+	0x620,
+	0x6e6,
+	0x93d,
+	0xa15,
+	0xb99,
+	0xdc0,
+	0xedd,
+	0x1000,
+	0x1200,
+	0x1312,
+	0x1401,
+	0x1885,
+	0x2c00,
+	0xa800,
+	0xf900,
+	0xfa30,
+	0xffda,
+	0xffdc,
+	0x10000,
+	0x10300,
+	0x10400,
+	0x20000,
+	0x2f800,
+	0x2fa1d,
+}
+
+var notletterTest = []rune{
+	0x20,
+	0x35,
+	0x375,
+	0x619,
+	0x700,
+	0xfffe,
+	0x1ffff,
+	0x10ffff,
+}
+
+// Contains all the special cased Latin-1 chars.
+var spaceTest = []rune{
+	0x09,
+	0x0a,
+	0x0b,
+	0x0c,
+	0x0d,
+	0x20,
+	0x85,
+	0xA0,
+	0x2000,
+	0x3000,
+}
+
+type caseT struct {
+	cas     int
+	in, out rune
+}
+
+var caseTest = []caseT{
+	// errors
+	{-1, '\n', 0xFFFD},
+	{UpperCase, -1, -1},
+	{UpperCase, 1 << 30, 1 << 30},
+
+	// ASCII (special-cased so test carefully)
+	{UpperCase, '\n', '\n'},
+	{UpperCase, 'a', 'A'},
+	{UpperCase, 'A', 'A'},
+	{UpperCase, '7', '7'},
+	{LowerCase, '\n', '\n'},
+	{LowerCase, 'a', 'a'},
+	{LowerCase, 'A', 'a'},
+	{LowerCase, '7', '7'},
+	{TitleCase, '\n', '\n'},
+	{TitleCase, 'a', 'A'},
+	{TitleCase, 'A', 'A'},
+	{TitleCase, '7', '7'},
+
+	// Latin-1: easy to read the tests!
+	{UpperCase, 0x80, 0x80},
+	{UpperCase, 'Å', 'Å'},
+	{UpperCase, 'å', 'Å'},
+	{LowerCase, 0x80, 0x80},
+	{LowerCase, 'Å', 'å'},
+	{LowerCase, 'å', 'å'},
+	{TitleCase, 0x80, 0x80},
+	{TitleCase, 'Å', 'Å'},
+	{TitleCase, 'å', 'Å'},
+
+	// 0131;LATIN SMALL LETTER DOTLESS I;Ll;0;L;;;;;N;;;0049;;0049
+	{UpperCase, 0x0131, 'I'},
+	{LowerCase, 0x0131, 0x0131},
+	{TitleCase, 0x0131, 'I'},
+
+	// 0133;LATIN SMALL LIGATURE IJ;Ll;0;L;<compat> 0069 006A;;;;N;LATIN SMALL LETTER I J;;0132;;0132
+	{UpperCase, 0x0133, 0x0132},
+	{LowerCase, 0x0133, 0x0133},
+	{TitleCase, 0x0133, 0x0132},
+
+	// 212A;KELVIN SIGN;Lu;0;L;004B;;;;N;DEGREES KELVIN;;;006B;
+	{UpperCase, 0x212A, 0x212A},
+	{LowerCase, 0x212A, 'k'},
+	{TitleCase, 0x212A, 0x212A},
+
+	// From an UpperLower sequence
+	// A640;CYRILLIC CAPITAL LETTER ZEMLYA;Lu;0;L;;;;;N;;;;A641;
+	{UpperCase, 0xA640, 0xA640},
+	{LowerCase, 0xA640, 0xA641},
+	{TitleCase, 0xA640, 0xA640},
+	// A641;CYRILLIC SMALL LETTER ZEMLYA;Ll;0;L;;;;;N;;;A640;;A640
+	{UpperCase, 0xA641, 0xA640},
+	{LowerCase, 0xA641, 0xA641},
+	{TitleCase, 0xA641, 0xA640},
+	// A64E;CYRILLIC CAPITAL LETTER NEUTRAL YER;Lu;0;L;;;;;N;;;;A64F;
+	{UpperCase, 0xA64E, 0xA64E},
+	{LowerCase, 0xA64E, 0xA64F},
+	{TitleCase, 0xA64E, 0xA64E},
+	// A65F;CYRILLIC SMALL LETTER YN;Ll;0;L;;;;;N;;;A65E;;A65E
+	{UpperCase, 0xA65F, 0xA65E},
+	{LowerCase, 0xA65F, 0xA65F},
+	{TitleCase, 0xA65F, 0xA65E},
+
+	// From another UpperLower sequence
+	// 0139;LATIN CAPITAL LETTER L WITH ACUTE;Lu;0;L;004C 0301;;;;N;LATIN CAPITAL LETTER L ACUTE;;;013A;
+	{UpperCase, 0x0139, 0x0139},
+	{LowerCase, 0x0139, 0x013A},
+	{TitleCase, 0x0139, 0x0139},
+	// 013F;LATIN CAPITAL LETTER L WITH MIDDLE DOT;Lu;0;L;<compat> 004C 00B7;;;;N;;;;0140;
+	{UpperCase, 0x013f, 0x013f},
+	{LowerCase, 0x013f, 0x0140},
+	{TitleCase, 0x013f, 0x013f},
+	// 0148;LATIN SMALL LETTER N WITH CARON;Ll;0;L;006E 030C;;;;N;LATIN SMALL LETTER N HACEK;;0147;;0147
+	{UpperCase, 0x0148, 0x0147},
+	{LowerCase, 0x0148, 0x0148},
+	{TitleCase, 0x0148, 0x0147},
+
+	// Last block in the 5.1.0 table
+	// 10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428;
+	{UpperCase, 0x10400, 0x10400},
+	{LowerCase, 0x10400, 0x10428},
+	{TitleCase, 0x10400, 0x10400},
+	// 10427;DESERET CAPITAL LETTER EW;Lu;0;L;;;;;N;;;;1044F;
+	{UpperCase, 0x10427, 0x10427},
+	{LowerCase, 0x10427, 0x1044F},
+	{TitleCase, 0x10427, 0x10427},
+	// 10428;DESERET SMALL LETTER LONG I;Ll;0;L;;;;;N;;;10400;;10400
+	{UpperCase, 0x10428, 0x10400},
+	{LowerCase, 0x10428, 0x10428},
+	{TitleCase, 0x10428, 0x10400},
+	// 1044F;DESERET SMALL LETTER EW;Ll;0;L;;;;;N;;;10427;;10427
+	{UpperCase, 0x1044F, 0x10427},
+	{LowerCase, 0x1044F, 0x1044F},
+	{TitleCase, 0x1044F, 0x10427},
+
+	// First one not in the 5.1.0 table
+	// 10450;SHAVIAN LETTER PEEP;Lo;0;L;;;;;N;;;;;
+	{UpperCase, 0x10450, 0x10450},
+	{LowerCase, 0x10450, 0x10450},
+	{TitleCase, 0x10450, 0x10450},
+
+	// Non-letters with case.
+	{LowerCase, 0x2161, 0x2171},
+	{UpperCase, 0x0345, 0x0399},
+}
+
+func TestIsLetter(t *testing.T) {
+	for _, r := range upperTest {
+		if !IsLetter(r) {
+			t.Errorf("IsLetter(U+%04X) = false, want true", r)
+		}
+	}
+	for _, r := range letterTest {
+		if !IsLetter(r) {
+			t.Errorf("IsLetter(U+%04X) = false, want true", r)
+		}
+	}
+	for _, r := range notletterTest {
+		if IsLetter(r) {
+			t.Errorf("IsLetter(U+%04X) = true, want false", r)
+		}
+	}
+}
+
+func TestIsUpper(t *testing.T) {
+	for _, r := range upperTest {
+		if !IsUpper(r) {
+			t.Errorf("IsUpper(U+%04X) = false, want true", r)
+		}
+	}
+	for _, r := range notupperTest {
+		if IsUpper(r) {
+			t.Errorf("IsUpper(U+%04X) = true, want false", r)
+		}
+	}
+	for _, r := range notletterTest {
+		if IsUpper(r) {
+			t.Errorf("IsUpper(U+%04X) = true, want false", r)
+		}
+	}
+}
+
+func caseString(c int) string {
+	switch c {
+	case UpperCase:
+		return "UpperCase"
+	case LowerCase:
+		return "LowerCase"
+	case TitleCase:
+		return "TitleCase"
+	}
+	return "ErrorCase"
+}
+
+func TestTo(t *testing.T) {
+	for _, c := range caseTest {
+		r := To(c.cas, c.in)
+		if c.out != r {
+			t.Errorf("To(U+%04X, %s) = U+%04X want U+%04X", c.in, caseString(c.cas), r, c.out)
+		}
+	}
+}
+
+func TestToUpperCase(t *testing.T) {
+	for _, c := range caseTest {
+		if c.cas != UpperCase {
+			continue
+		}
+		r := ToUpper(c.in)
+		if c.out != r {
+			t.Errorf("ToUpper(U+%04X) = U+%04X want U+%04X", c.in, r, c.out)
+		}
+	}
+}
+
+func TestToLowerCase(t *testing.T) {
+	for _, c := range caseTest {
+		if c.cas != LowerCase {
+			continue
+		}
+		r := ToLower(c.in)
+		if c.out != r {
+			t.Errorf("ToLower(U+%04X) = U+%04X want U+%04X", c.in, r, c.out)
+		}
+	}
+}
+
+func TestToTitleCase(t *testing.T) {
+	for _, c := range caseTest {
+		if c.cas != TitleCase {
+			continue
+		}
+		r := ToTitle(c.in)
+		if c.out != r {
+			t.Errorf("ToTitle(U+%04X) = U+%04X want U+%04X", c.in, r, c.out)
+		}
+	}
+}
+
+func TestIsSpace(t *testing.T) {
+	for _, c := range spaceTest {
+		if !IsSpace(c) {
+			t.Errorf("IsSpace(U+%04X) = false; want true", c)
+		}
+	}
+	for _, c := range letterTest {
+		if IsSpace(c) {
+			t.Errorf("IsSpace(U+%04X) = true; want false", c)
+		}
+	}
+}
+
+// Check that the optimizations for IsLetter etc. agree with the tables.
+// We only need to check the Latin-1 range.
+func TestLetterOptimizations(t *testing.T) {
+	for i := rune(0); i <= MaxLatin1; i++ {
+		if Is(Letter, i) != IsLetter(i) {
+			t.Errorf("IsLetter(U+%04X) disagrees with Is(Letter)", i)
+		}
+		if Is(Upper, i) != IsUpper(i) {
+			t.Errorf("IsUpper(U+%04X) disagrees with Is(Upper)", i)
+		}
+		if Is(Lower, i) != IsLower(i) {
+			t.Errorf("IsLower(U+%04X) disagrees with Is(Lower)", i)
+		}
+		if Is(Title, i) != IsTitle(i) {
+			t.Errorf("IsTitle(U+%04X) disagrees with Is(Title)", i)
+		}
+		if Is(White_Space, i) != IsSpace(i) {
+			t.Errorf("IsSpace(U+%04X) disagrees with Is(White_Space)", i)
+		}
+		if To(UpperCase, i) != ToUpper(i) {
+			t.Errorf("ToUpper(U+%04X) disagrees with To(Upper)", i)
+		}
+		if To(LowerCase, i) != ToLower(i) {
+			t.Errorf("ToLower(U+%04X) disagrees with To(Lower)", i)
+		}
+		if To(TitleCase, i) != ToTitle(i) {
+			t.Errorf("ToTitle(U+%04X) disagrees with To(Title)", i)
+		}
+	}
+}
+
+func TestTurkishCase(t *testing.T) {
+	lower := []rune("abcçdefgğhıijklmnoöprsştuüvyz")
+	upper := []rune("ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ")
+	for i, l := range lower {
+		u := upper[i]
+		if TurkishCase.ToLower(l) != l {
+			t.Errorf("lower(U+%04X) is U+%04X not U+%04X", l, TurkishCase.ToLower(l), l)
+		}
+		if TurkishCase.ToUpper(u) != u {
+			t.Errorf("upper(U+%04X) is U+%04X not U+%04X", u, TurkishCase.ToUpper(u), u)
+		}
+		if TurkishCase.ToUpper(l) != u {
+			t.Errorf("upper(U+%04X) is U+%04X not U+%04X", l, TurkishCase.ToUpper(l), u)
+		}
+		if TurkishCase.ToLower(u) != l {
+			t.Errorf("lower(U+%04X) is U+%04X not U+%04X", u, TurkishCase.ToLower(l), l)
+		}
+		if TurkishCase.ToTitle(u) != u {
+			t.Errorf("title(U+%04X) is U+%04X not U+%04X", u, TurkishCase.ToTitle(u), u)
+		}
+		if TurkishCase.ToTitle(l) != u {
+			t.Errorf("title(U+%04X) is U+%04X not U+%04X", l, TurkishCase.ToTitle(l), u)
+		}
+	}
+}
+
+var simpleFoldTests = []string{
+	// SimpleFold(x) returns the next equivalent rune > x or wraps
+	// around to smaller values.
+
+	// Easy cases.
+	"Aa",
+	"δΔ",
+
+	// ASCII special cases.
+	"KkK",
+	"Ssſ",
+
+	// Non-ASCII special cases.
+	"ρϱΡ",
+	"ͅΙιι",
+
+	// Extra special cases: has lower/upper but no case fold.
+	"İ",
+	"ı",
+}
+
+func TestSimpleFold(t *testing.T) {
+	for _, tt := range simpleFoldTests {
+		cycle := []rune(tt)
+		r := cycle[len(cycle)-1]
+		for _, out := range cycle {
+			if r := SimpleFold(r); r != out {
+				t.Errorf("SimpleFold(%#U) = %#U, want %#U", r, r, out)
+			}
+			r = out
+		}
+	}
+}
+
+// Running 'go test -calibrate' runs the calibration to find a plausible
+// cutoff point for linear search of a range list vs. binary search.
+// We create a fake table and then time how long it takes to do a
+// sequence of searches within that table, for all possible inputs
+// relative to the ranges (something before all, in each, between each, after all).
+// This assumes that all possible runes are equally likely.
+// In practice most runes are ASCII so this is a conservative estimate
+// of an effective cutoff value. In practice we could probably set it higher
+// than what this function recommends.
+
+var calibrate = flag.Bool("calibrate", false, "compute crossover for linear vs. binary search")
+
+func TestCalibrate(t *testing.T) {
+	if !*calibrate {
+		return
+	}
+
+	if runtime.GOARCH == "amd64" {
+		fmt.Printf("warning: running calibration on %s\n", runtime.GOARCH)
+	}
+
+	// Find the point where binary search wins by more than 10%.
+	// The 10% bias gives linear search an edge when they're close,
+	// because on predominantly ASCII inputs linear search is even
+	// better than our benchmarks measure.
+	n := sort.Search(64, func(n int) bool {
+		tab := fakeTable(n)
+		blinear := func(b *testing.B) {
+			tab := tab
+			max := n*5 + 20
+			for i := 0; i < b.N; i++ {
+				for j := 0; j <= max; j++ {
+					linear(tab, uint16(j))
+				}
+			}
+		}
+		bbinary := func(b *testing.B) {
+			tab := tab
+			max := n*5 + 20
+			for i := 0; i < b.N; i++ {
+				for j := 0; j <= max; j++ {
+					binary(tab, uint16(j))
+				}
+			}
+		}
+		bmlinear := testing.Benchmark(blinear)
+		bmbinary := testing.Benchmark(bbinary)
+		fmt.Printf("n=%d: linear=%d binary=%d\n", n, bmlinear.NsPerOp(), bmbinary.NsPerOp())
+		return bmlinear.NsPerOp()*100 > bmbinary.NsPerOp()*110
+	})
+	fmt.Printf("calibration: linear cutoff = %d\n", n)
+}
+
+func fakeTable(n int) []Range16 {
+	var r16 []Range16
+	for i := 0; i < n; i++ {
+		r16 = append(r16, Range16{uint16(i*5 + 10), uint16(i*5 + 12), 1})
+	}
+	return r16
+}
+
+func linear(ranges []Range16, r uint16) bool {
+	for i := range ranges {
+		range_ := &ranges[i]
+		if r < range_.Lo {
+			return false
+		}
+		if r <= range_.Hi {
+			return (r-range_.Lo)%range_.Stride == 0
+		}
+	}
+	return false
+}
+
+func binary(ranges []Range16, r uint16) bool {
+	// binary search over ranges
+	lo := 0
+	hi := len(ranges)
+	for lo < hi {
+		m := lo + (hi-lo)/2
+		range_ := &ranges[m]
+		if range_.Lo <= r && r <= range_.Hi {
+			return (r-range_.Lo)%range_.Stride == 0
+		}
+		if r < range_.Lo {
+			hi = m
+		} else {
+			lo = m + 1
+		}
+	}
+	return false
+}
+
+func TestLatinOffset(t *testing.T) {
+	var maps = []map[string]*RangeTable{
+		Categories,
+		FoldCategory,
+		FoldScript,
+		Properties,
+		Scripts,
+	}
+	for _, m := range maps {
+		for name, tab := range m {
+			i := 0
+			for i < len(tab.R16) && tab.R16[i].Hi <= MaxLatin1 {
+				i++
+			}
+			if tab.LatinOffset != i {
+				t.Errorf("%s: LatinOffset=%d, want %d", name, tab.LatinOffset, i)
+			}
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/script_test.go b/third_party/gofrontend/libgo/go/unicode/script_test.go
new file mode 100644
index 0000000..e2ba001
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/script_test.go
@@ -0,0 +1,264 @@
+// 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 unicode_test
+
+import (
+	"testing"
+	. "unicode"
+)
+
+type T struct {
+	rune   rune
+	script string
+}
+
+// Hand-chosen tests from Unicode 5.1.0, 6.0.0 and 6.2.0 mostly to discover when new
+// scripts and categories arise.
+var inTest = []T{
+	{0x06e2, "Arabic"},
+	{0x0567, "Armenian"},
+	{0x10b20, "Avestan"},
+	{0x1b37, "Balinese"},
+	{0xa6af, "Bamum"},
+	{0x1be1, "Batak"},
+	{0x09c2, "Bengali"},
+	{0x3115, "Bopomofo"},
+	{0x282d, "Braille"},
+	{0x1a1a, "Buginese"},
+	{0x1747, "Buhid"},
+	{0x11011, "Brahmi"},
+	{0x156d, "Canadian_Aboriginal"},
+	{0x102a9, "Carian"},
+	{0x11111, "Chakma"},
+	{0xaa4d, "Cham"},
+	{0x13c2, "Cherokee"},
+	{0x0020, "Common"},
+	{0x1d4a5, "Common"},
+	{0x2cfc, "Coptic"},
+	{0x12420, "Cuneiform"},
+	{0x1080c, "Cypriot"},
+	{0xa663, "Cyrillic"},
+	{0x10430, "Deseret"},
+	{0x094a, "Devanagari"},
+	{0x13001, "Egyptian_Hieroglyphs"},
+	{0x1271, "Ethiopic"},
+	{0x10fc, "Georgian"},
+	{0x2c40, "Glagolitic"},
+	{0x10347, "Gothic"},
+	{0x03ae, "Greek"},
+	{0x0abf, "Gujarati"},
+	{0x0a24, "Gurmukhi"},
+	{0x3028, "Han"},
+	{0x11b8, "Hangul"},
+	{0x1727, "Hanunoo"},
+	{0x05a0, "Hebrew"},
+	{0x3058, "Hiragana"},
+	{0x10841, "Imperial_Aramaic"},
+	{0x20e6, "Inherited"},
+	{0x10b70, "Inscriptional_Pahlavi"},
+	{0x10b5a, "Inscriptional_Parthian"},
+	{0xa9d0, "Javanese"},
+	{0x1109f, "Kaithi"},
+	{0x0cbd, "Kannada"},
+	{0x30a6, "Katakana"},
+	{0xa928, "Kayah_Li"},
+	{0x10a11, "Kharoshthi"},
+	{0x17c6, "Khmer"},
+	{0x0eaa, "Lao"},
+	{0x1d79, "Latin"},
+	{0x1c10, "Lepcha"},
+	{0x1930, "Limbu"},
+	{0x1003c, "Linear_B"},
+	{0xa4e1, "Lisu"},
+	{0x10290, "Lycian"},
+	{0x10930, "Lydian"},
+	{0x0d42, "Malayalam"},
+	{0x0843, "Mandaic"},
+	{0xabd0, "Meetei_Mayek"},
+	{0x1099f, "Meroitic_Hieroglyphs"},
+	{0x109a0, "Meroitic_Cursive"},
+	{0x16f00, "Miao"},
+	{0x1822, "Mongolian"},
+	{0x104c, "Myanmar"},
+	{0x19c3, "New_Tai_Lue"},
+	{0x07f8, "Nko"},
+	{0x169b, "Ogham"},
+	{0x1c6a, "Ol_Chiki"},
+	{0x10310, "Old_Italic"},
+	{0x103c9, "Old_Persian"},
+	{0x10a6f, "Old_South_Arabian"},
+	{0x10c20, "Old_Turkic"},
+	{0x0b3e, "Oriya"},
+	{0x10491, "Osmanya"},
+	{0xa860, "Phags_Pa"},
+	{0x10918, "Phoenician"},
+	{0xa949, "Rejang"},
+	{0x16c0, "Runic"},
+	{0x081d, "Samaritan"},
+	{0xa892, "Saurashtra"},
+	{0x111a0, "Sharada"},
+	{0x10463, "Shavian"},
+	{0x0dbd, "Sinhala"},
+	{0x110d0, "Sora_Sompeng"},
+	{0x1ba3, "Sundanese"},
+	{0xa803, "Syloti_Nagri"},
+	{0x070f, "Syriac"},
+	{0x170f, "Tagalog"},
+	{0x176f, "Tagbanwa"},
+	{0x1972, "Tai_Le"},
+	{0x1a62, "Tai_Tham"},
+	{0xaadc, "Tai_Viet"},
+	{0x116c9, "Takri"},
+	{0x0bbf, "Tamil"},
+	{0x0c55, "Telugu"},
+	{0x07a7, "Thaana"},
+	{0x0e46, "Thai"},
+	{0x0f36, "Tibetan"},
+	{0x2d55, "Tifinagh"},
+	{0x10388, "Ugaritic"},
+	{0xa60e, "Vai"},
+	{0xa216, "Yi"},
+}
+
+var outTest = []T{ // not really worth being thorough
+	{0x20, "Telugu"},
+}
+
+var inCategoryTest = []T{
+	{0x0081, "Cc"},
+	{0x200B, "Cf"},
+	{0xf0000, "Co"},
+	{0xdb80, "Cs"},
+	{0x0236, "Ll"},
+	{0x1d9d, "Lm"},
+	{0x07cf, "Lo"},
+	{0x1f8a, "Lt"},
+	{0x03ff, "Lu"},
+	{0x0bc1, "Mc"},
+	{0x20df, "Me"},
+	{0x07f0, "Mn"},
+	{0x1bb2, "Nd"},
+	{0x10147, "Nl"},
+	{0x2478, "No"},
+	{0xfe33, "Pc"},
+	{0x2011, "Pd"},
+	{0x301e, "Pe"},
+	{0x2e03, "Pf"},
+	{0x2e02, "Pi"},
+	{0x0022, "Po"},
+	{0x2770, "Ps"},
+	{0x00a4, "Sc"},
+	{0xa711, "Sk"},
+	{0x25f9, "Sm"},
+	{0x2108, "So"},
+	{0x2028, "Zl"},
+	{0x2029, "Zp"},
+	{0x202f, "Zs"},
+	// Unifieds.
+	{0x04aa, "L"},
+	{0x0009, "C"},
+	{0x1712, "M"},
+	{0x0031, "N"},
+	{0x00bb, "P"},
+	{0x00a2, "S"},
+	{0x00a0, "Z"},
+}
+
+var inPropTest = []T{
+	{0x0046, "ASCII_Hex_Digit"},
+	{0x200F, "Bidi_Control"},
+	{0x2212, "Dash"},
+	{0xE0001, "Deprecated"},
+	{0x00B7, "Diacritic"},
+	{0x30FE, "Extender"},
+	{0xFF46, "Hex_Digit"},
+	{0x2E17, "Hyphen"},
+	{0x2FFB, "IDS_Binary_Operator"},
+	{0x2FF3, "IDS_Trinary_Operator"},
+	{0xFA6A, "Ideographic"},
+	{0x200D, "Join_Control"},
+	{0x0EC4, "Logical_Order_Exception"},
+	{0x2FFFF, "Noncharacter_Code_Point"},
+	{0x065E, "Other_Alphabetic"},
+	{0x2065, "Other_Default_Ignorable_Code_Point"},
+	{0x0BD7, "Other_Grapheme_Extend"},
+	{0x0387, "Other_ID_Continue"},
+	{0x212E, "Other_ID_Start"},
+	{0x2094, "Other_Lowercase"},
+	{0x2040, "Other_Math"},
+	{0x216F, "Other_Uppercase"},
+	{0x0027, "Pattern_Syntax"},
+	{0x0020, "Pattern_White_Space"},
+	{0x300D, "Quotation_Mark"},
+	{0x2EF3, "Radical"},
+	{0x061F, "STerm"},
+	{0x2071, "Soft_Dotted"},
+	{0x003A, "Terminal_Punctuation"},
+	{0x9FC3, "Unified_Ideograph"},
+	{0xFE0F, "Variation_Selector"},
+	{0x0020, "White_Space"},
+}
+
+func TestScripts(t *testing.T) {
+	notTested := make(map[string]bool)
+	for k := range Scripts {
+		notTested[k] = true
+	}
+	for _, test := range inTest {
+		if _, ok := Scripts[test.script]; !ok {
+			t.Fatal(test.script, "not a known script")
+		}
+		if !Is(Scripts[test.script], test.rune) {
+			t.Errorf("IsScript(%U, %s) = false, want true", test.rune, test.script)
+		}
+		delete(notTested, test.script)
+	}
+	for _, test := range outTest {
+		if Is(Scripts[test.script], test.rune) {
+			t.Errorf("IsScript(%U, %s) = true, want false", test.rune, test.script)
+		}
+	}
+	for k := range notTested {
+		t.Error("script not tested:", k)
+	}
+}
+
+func TestCategories(t *testing.T) {
+	notTested := make(map[string]bool)
+	for k := range Categories {
+		notTested[k] = true
+	}
+	for _, test := range inCategoryTest {
+		if _, ok := Categories[test.script]; !ok {
+			t.Fatal(test.script, "not a known category")
+		}
+		if !Is(Categories[test.script], test.rune) {
+			t.Errorf("IsCategory(%U, %s) = false, want true", test.rune, test.script)
+		}
+		delete(notTested, test.script)
+	}
+	for k := range notTested {
+		t.Error("category not tested:", k)
+	}
+}
+
+func TestProperties(t *testing.T) {
+	notTested := make(map[string]bool)
+	for k := range Properties {
+		notTested[k] = true
+	}
+	for _, test := range inPropTest {
+		if _, ok := Properties[test.script]; !ok {
+			t.Fatal(test.script, "not a known prop")
+		}
+		if !Is(Properties[test.script], test.rune) {
+			t.Errorf("IsCategory(%U, %s) = false, want true", test.rune, test.script)
+		}
+		delete(notTested, test.script)
+	}
+	for k := range notTested {
+		t.Error("property not tested:", k)
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/tables.go b/third_party/gofrontend/libgo/go/unicode/tables.go
new file mode 100644
index 0000000..5670d1c
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/tables.go
@@ -0,0 +1,6391 @@
+// Copyright 2013 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.
+
+// Generated by running
+//	maketables --tables=all --data=http://www.unicode.org/Public/6.3.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/6.3.0/ucd/CaseFolding.txt
+// DO NOT EDIT
+
+package unicode
+
+// Version is the Unicode edition from which the tables are derived.
+const Version = "6.3.0"
+
+// Categories is the set of Unicode category tables.
+var Categories = map[string]*RangeTable{
+	"C":  C,
+	"Cc": Cc,
+	"Cf": Cf,
+	"Co": Co,
+	"Cs": Cs,
+	"L":  L,
+	"Ll": Ll,
+	"Lm": Lm,
+	"Lo": Lo,
+	"Lt": Lt,
+	"Lu": Lu,
+	"M":  M,
+	"Mc": Mc,
+	"Me": Me,
+	"Mn": Mn,
+	"N":  N,
+	"Nd": Nd,
+	"Nl": Nl,
+	"No": No,
+	"P":  P,
+	"Pc": Pc,
+	"Pd": Pd,
+	"Pe": Pe,
+	"Pf": Pf,
+	"Pi": Pi,
+	"Po": Po,
+	"Ps": Ps,
+	"S":  S,
+	"Sc": Sc,
+	"Sk": Sk,
+	"Sm": Sm,
+	"So": So,
+	"Z":  Z,
+	"Zl": Zl,
+	"Zp": Zp,
+	"Zs": Zs,
+}
+
+var _C = &RangeTable{
+	R16: []Range16{
+		{0x0001, 0x001f, 1},
+		{0x007f, 0x009f, 1},
+		{0x00ad, 0x0600, 1363},
+		{0x0601, 0x0604, 1},
+		{0x061c, 0x06dd, 193},
+		{0x070f, 0x180e, 4351},
+		{0x200b, 0x200f, 1},
+		{0x202a, 0x202e, 1},
+		{0x2060, 0x2064, 1},
+		{0x2066, 0x206f, 1},
+		{0xd800, 0xf8ff, 1},
+		{0xfeff, 0xfff9, 250},
+		{0xfffa, 0xfffb, 1},
+	},
+	R32: []Range32{
+		{0x110bd, 0x1d173, 49334},
+		{0x1d174, 0x1d17a, 1},
+		{0xe0001, 0xe0020, 31},
+		{0xe0021, 0xe007f, 1},
+		{0xf0000, 0xffffd, 1},
+		{0x100000, 0x10fffd, 1},
+	},
+	LatinOffset: 2,
+}
+
+var _Cc = &RangeTable{
+	R16: []Range16{
+		{0x0001, 0x001f, 1},
+		{0x007f, 0x009f, 1},
+	},
+	LatinOffset: 2,
+}
+
+var _Cf = &RangeTable{
+	R16: []Range16{
+		{0x00ad, 0x0600, 1363},
+		{0x0601, 0x0604, 1},
+		{0x061c, 0x06dd, 193},
+		{0x070f, 0x180e, 4351},
+		{0x200b, 0x200f, 1},
+		{0x202a, 0x202e, 1},
+		{0x2060, 0x2064, 1},
+		{0x2066, 0x206f, 1},
+		{0xfeff, 0xfff9, 250},
+		{0xfffa, 0xfffb, 1},
+	},
+	R32: []Range32{
+		{0x110bd, 0x1d173, 49334},
+		{0x1d174, 0x1d17a, 1},
+		{0xe0001, 0xe0020, 31},
+		{0xe0021, 0xe007f, 1},
+	},
+}
+
+var _Co = &RangeTable{
+	R16: []Range16{
+		{0xe000, 0xf8ff, 1},
+	},
+	R32: []Range32{
+		{0xf0000, 0xffffd, 1},
+		{0x100000, 0x10fffd, 1},
+	},
+}
+
+var _Cs = &RangeTable{
+	R16: []Range16{
+		{0xd800, 0xdfff, 1},
+	},
+}
+
+var _L = &RangeTable{
+	R16: []Range16{
+		{0x0041, 0x005a, 1},
+		{0x0061, 0x007a, 1},
+		{0x00aa, 0x00b5, 11},
+		{0x00ba, 0x00c0, 6},
+		{0x00c1, 0x00d6, 1},
+		{0x00d8, 0x00f6, 1},
+		{0x00f8, 0x02c1, 1},
+		{0x02c6, 0x02d1, 1},
+		{0x02e0, 0x02e4, 1},
+		{0x02ec, 0x02ee, 2},
+		{0x0370, 0x0374, 1},
+		{0x0376, 0x0377, 1},
+		{0x037a, 0x037d, 1},
+		{0x0386, 0x0388, 2},
+		{0x0389, 0x038a, 1},
+		{0x038c, 0x038e, 2},
+		{0x038f, 0x03a1, 1},
+		{0x03a3, 0x03f5, 1},
+		{0x03f7, 0x0481, 1},
+		{0x048a, 0x0527, 1},
+		{0x0531, 0x0556, 1},
+		{0x0559, 0x0561, 8},
+		{0x0562, 0x0587, 1},
+		{0x05d0, 0x05ea, 1},
+		{0x05f0, 0x05f2, 1},
+		{0x0620, 0x064a, 1},
+		{0x066e, 0x066f, 1},
+		{0x0671, 0x06d3, 1},
+		{0x06d5, 0x06e5, 16},
+		{0x06e6, 0x06ee, 8},
+		{0x06ef, 0x06fa, 11},
+		{0x06fb, 0x06fc, 1},
+		{0x06ff, 0x0710, 17},
+		{0x0712, 0x072f, 1},
+		{0x074d, 0x07a5, 1},
+		{0x07b1, 0x07ca, 25},
+		{0x07cb, 0x07ea, 1},
+		{0x07f4, 0x07f5, 1},
+		{0x07fa, 0x0800, 6},
+		{0x0801, 0x0815, 1},
+		{0x081a, 0x0824, 10},
+		{0x0828, 0x0840, 24},
+		{0x0841, 0x0858, 1},
+		{0x08a0, 0x08a2, 2},
+		{0x08a3, 0x08ac, 1},
+		{0x0904, 0x0939, 1},
+		{0x093d, 0x0950, 19},
+		{0x0958, 0x0961, 1},
+		{0x0971, 0x0977, 1},
+		{0x0979, 0x097f, 1},
+		{0x0985, 0x098c, 1},
+		{0x098f, 0x0990, 1},
+		{0x0993, 0x09a8, 1},
+		{0x09aa, 0x09b0, 1},
+		{0x09b2, 0x09b6, 4},
+		{0x09b7, 0x09b9, 1},
+		{0x09bd, 0x09ce, 17},
+		{0x09dc, 0x09dd, 1},
+		{0x09df, 0x09e1, 1},
+		{0x09f0, 0x09f1, 1},
+		{0x0a05, 0x0a0a, 1},
+		{0x0a0f, 0x0a10, 1},
+		{0x0a13, 0x0a28, 1},
+		{0x0a2a, 0x0a30, 1},
+		{0x0a32, 0x0a33, 1},
+		{0x0a35, 0x0a36, 1},
+		{0x0a38, 0x0a39, 1},
+		{0x0a59, 0x0a5c, 1},
+		{0x0a5e, 0x0a72, 20},
+		{0x0a73, 0x0a74, 1},
+		{0x0a85, 0x0a8d, 1},
+		{0x0a8f, 0x0a91, 1},
+		{0x0a93, 0x0aa8, 1},
+		{0x0aaa, 0x0ab0, 1},
+		{0x0ab2, 0x0ab3, 1},
+		{0x0ab5, 0x0ab9, 1},
+		{0x0abd, 0x0ad0, 19},
+		{0x0ae0, 0x0ae1, 1},
+		{0x0b05, 0x0b0c, 1},
+		{0x0b0f, 0x0b10, 1},
+		{0x0b13, 0x0b28, 1},
+		{0x0b2a, 0x0b30, 1},
+		{0x0b32, 0x0b33, 1},
+		{0x0b35, 0x0b39, 1},
+		{0x0b3d, 0x0b5c, 31},
+		{0x0b5d, 0x0b5f, 2},
+		{0x0b60, 0x0b61, 1},
+		{0x0b71, 0x0b83, 18},
+		{0x0b85, 0x0b8a, 1},
+		{0x0b8e, 0x0b90, 1},
+		{0x0b92, 0x0b95, 1},
+		{0x0b99, 0x0b9a, 1},
+		{0x0b9c, 0x0b9e, 2},
+		{0x0b9f, 0x0ba3, 4},
+		{0x0ba4, 0x0ba8, 4},
+		{0x0ba9, 0x0baa, 1},
+		{0x0bae, 0x0bb9, 1},
+		{0x0bd0, 0x0c05, 53},
+		{0x0c06, 0x0c0c, 1},
+		{0x0c0e, 0x0c10, 1},
+		{0x0c12, 0x0c28, 1},
+		{0x0c2a, 0x0c33, 1},
+		{0x0c35, 0x0c39, 1},
+		{0x0c3d, 0x0c58, 27},
+		{0x0c59, 0x0c60, 7},
+		{0x0c61, 0x0c85, 36},
+		{0x0c86, 0x0c8c, 1},
+		{0x0c8e, 0x0c90, 1},
+		{0x0c92, 0x0ca8, 1},
+		{0x0caa, 0x0cb3, 1},
+		{0x0cb5, 0x0cb9, 1},
+		{0x0cbd, 0x0cde, 33},
+		{0x0ce0, 0x0ce1, 1},
+		{0x0cf1, 0x0cf2, 1},
+		{0x0d05, 0x0d0c, 1},
+		{0x0d0e, 0x0d10, 1},
+		{0x0d12, 0x0d3a, 1},
+		{0x0d3d, 0x0d4e, 17},
+		{0x0d60, 0x0d61, 1},
+		{0x0d7a, 0x0d7f, 1},
+		{0x0d85, 0x0d96, 1},
+		{0x0d9a, 0x0db1, 1},
+		{0x0db3, 0x0dbb, 1},
+		{0x0dbd, 0x0dc0, 3},
+		{0x0dc1, 0x0dc6, 1},
+		{0x0e01, 0x0e30, 1},
+		{0x0e32, 0x0e33, 1},
+		{0x0e40, 0x0e46, 1},
+		{0x0e81, 0x0e82, 1},
+		{0x0e84, 0x0e87, 3},
+		{0x0e88, 0x0e8a, 2},
+		{0x0e8d, 0x0e94, 7},
+		{0x0e95, 0x0e97, 1},
+		{0x0e99, 0x0e9f, 1},
+		{0x0ea1, 0x0ea3, 1},
+		{0x0ea5, 0x0ea7, 2},
+		{0x0eaa, 0x0eab, 1},
+		{0x0ead, 0x0eb0, 1},
+		{0x0eb2, 0x0eb3, 1},
+		{0x0ebd, 0x0ec0, 3},
+		{0x0ec1, 0x0ec4, 1},
+		{0x0ec6, 0x0edc, 22},
+		{0x0edd, 0x0edf, 1},
+		{0x0f00, 0x0f40, 64},
+		{0x0f41, 0x0f47, 1},
+		{0x0f49, 0x0f6c, 1},
+		{0x0f88, 0x0f8c, 1},
+		{0x1000, 0x102a, 1},
+		{0x103f, 0x1050, 17},
+		{0x1051, 0x1055, 1},
+		{0x105a, 0x105d, 1},
+		{0x1061, 0x1065, 4},
+		{0x1066, 0x106e, 8},
+		{0x106f, 0x1070, 1},
+		{0x1075, 0x1081, 1},
+		{0x108e, 0x10a0, 18},
+		{0x10a1, 0x10c5, 1},
+		{0x10c7, 0x10cd, 6},
+		{0x10d0, 0x10fa, 1},
+		{0x10fc, 0x1248, 1},
+		{0x124a, 0x124d, 1},
+		{0x1250, 0x1256, 1},
+		{0x1258, 0x125a, 2},
+		{0x125b, 0x125d, 1},
+		{0x1260, 0x1288, 1},
+		{0x128a, 0x128d, 1},
+		{0x1290, 0x12b0, 1},
+		{0x12b2, 0x12b5, 1},
+		{0x12b8, 0x12be, 1},
+		{0x12c0, 0x12c2, 2},
+		{0x12c3, 0x12c5, 1},
+		{0x12c8, 0x12d6, 1},
+		{0x12d8, 0x1310, 1},
+		{0x1312, 0x1315, 1},
+		{0x1318, 0x135a, 1},
+		{0x1380, 0x138f, 1},
+		{0x13a0, 0x13f4, 1},
+		{0x1401, 0x166c, 1},
+		{0x166f, 0x167f, 1},
+		{0x1681, 0x169a, 1},
+		{0x16a0, 0x16ea, 1},
+		{0x1700, 0x170c, 1},
+		{0x170e, 0x1711, 1},
+		{0x1720, 0x1731, 1},
+		{0x1740, 0x1751, 1},
+		{0x1760, 0x176c, 1},
+		{0x176e, 0x1770, 1},
+		{0x1780, 0x17b3, 1},
+		{0x17d7, 0x17dc, 5},
+		{0x1820, 0x1877, 1},
+		{0x1880, 0x18a8, 1},
+		{0x18aa, 0x18b0, 6},
+		{0x18b1, 0x18f5, 1},
+		{0x1900, 0x191c, 1},
+		{0x1950, 0x196d, 1},
+		{0x1970, 0x1974, 1},
+		{0x1980, 0x19ab, 1},
+		{0x19c1, 0x19c7, 1},
+		{0x1a00, 0x1a16, 1},
+		{0x1a20, 0x1a54, 1},
+		{0x1aa7, 0x1b05, 94},
+		{0x1b06, 0x1b33, 1},
+		{0x1b45, 0x1b4b, 1},
+		{0x1b83, 0x1ba0, 1},
+		{0x1bae, 0x1baf, 1},
+		{0x1bba, 0x1be5, 1},
+		{0x1c00, 0x1c23, 1},
+		{0x1c4d, 0x1c4f, 1},
+		{0x1c5a, 0x1c7d, 1},
+		{0x1ce9, 0x1cec, 1},
+		{0x1cee, 0x1cf1, 1},
+		{0x1cf5, 0x1cf6, 1},
+		{0x1d00, 0x1dbf, 1},
+		{0x1e00, 0x1f15, 1},
+		{0x1f18, 0x1f1d, 1},
+		{0x1f20, 0x1f45, 1},
+		{0x1f48, 0x1f4d, 1},
+		{0x1f50, 0x1f57, 1},
+		{0x1f59, 0x1f5f, 2},
+		{0x1f60, 0x1f7d, 1},
+		{0x1f80, 0x1fb4, 1},
+		{0x1fb6, 0x1fbc, 1},
+		{0x1fbe, 0x1fc2, 4},
+		{0x1fc3, 0x1fc4, 1},
+		{0x1fc6, 0x1fcc, 1},
+		{0x1fd0, 0x1fd3, 1},
+		{0x1fd6, 0x1fdb, 1},
+		{0x1fe0, 0x1fec, 1},
+		{0x1ff2, 0x1ff4, 1},
+		{0x1ff6, 0x1ffc, 1},
+		{0x2071, 0x207f, 14},
+		{0x2090, 0x209c, 1},
+		{0x2102, 0x2107, 5},
+		{0x210a, 0x2113, 1},
+		{0x2115, 0x2119, 4},
+		{0x211a, 0x211d, 1},
+		{0x2124, 0x212a, 2},
+		{0x212b, 0x212d, 1},
+		{0x212f, 0x2139, 1},
+		{0x213c, 0x213f, 1},
+		{0x2145, 0x2149, 1},
+		{0x214e, 0x2183, 53},
+		{0x2184, 0x2c00, 2684},
+		{0x2c01, 0x2c2e, 1},
+		{0x2c30, 0x2c5e, 1},
+		{0x2c60, 0x2ce4, 1},
+		{0x2ceb, 0x2cee, 1},
+		{0x2cf2, 0x2cf3, 1},
+		{0x2d00, 0x2d25, 1},
+		{0x2d27, 0x2d2d, 6},
+		{0x2d30, 0x2d67, 1},
+		{0x2d6f, 0x2d80, 17},
+		{0x2d81, 0x2d96, 1},
+		{0x2da0, 0x2da6, 1},
+		{0x2da8, 0x2dae, 1},
+		{0x2db0, 0x2db6, 1},
+		{0x2db8, 0x2dbe, 1},
+		{0x2dc0, 0x2dc6, 1},
+		{0x2dc8, 0x2dce, 1},
+		{0x2dd0, 0x2dd6, 1},
+		{0x2dd8, 0x2dde, 1},
+		{0x2e2f, 0x3005, 470},
+		{0x3006, 0x3031, 43},
+		{0x3032, 0x3035, 1},
+		{0x303b, 0x303c, 1},
+		{0x3041, 0x3096, 1},
+		{0x309d, 0x309f, 1},
+		{0x30a1, 0x30fa, 1},
+		{0x30fc, 0x30ff, 1},
+		{0x3105, 0x312d, 1},
+		{0x3131, 0x318e, 1},
+		{0x31a0, 0x31ba, 1},
+		{0x31f0, 0x31ff, 1},
+		{0x3400, 0x4db5, 1},
+		{0x4e00, 0x9fcc, 1},
+		{0xa000, 0xa48c, 1},
+		{0xa4d0, 0xa4fd, 1},
+		{0xa500, 0xa60c, 1},
+		{0xa610, 0xa61f, 1},
+		{0xa62a, 0xa62b, 1},
+		{0xa640, 0xa66e, 1},
+		{0xa67f, 0xa697, 1},
+		{0xa6a0, 0xa6e5, 1},
+		{0xa717, 0xa71f, 1},
+		{0xa722, 0xa788, 1},
+		{0xa78b, 0xa78e, 1},
+		{0xa790, 0xa793, 1},
+		{0xa7a0, 0xa7aa, 1},
+		{0xa7f8, 0xa801, 1},
+		{0xa803, 0xa805, 1},
+		{0xa807, 0xa80a, 1},
+		{0xa80c, 0xa822, 1},
+		{0xa840, 0xa873, 1},
+		{0xa882, 0xa8b3, 1},
+		{0xa8f2, 0xa8f7, 1},
+		{0xa8fb, 0xa90a, 15},
+		{0xa90b, 0xa925, 1},
+		{0xa930, 0xa946, 1},
+		{0xa960, 0xa97c, 1},
+		{0xa984, 0xa9b2, 1},
+		{0xa9cf, 0xaa00, 49},
+		{0xaa01, 0xaa28, 1},
+		{0xaa40, 0xaa42, 1},
+		{0xaa44, 0xaa4b, 1},
+		{0xaa60, 0xaa76, 1},
+		{0xaa7a, 0xaa80, 6},
+		{0xaa81, 0xaaaf, 1},
+		{0xaab1, 0xaab5, 4},
+		{0xaab6, 0xaab9, 3},
+		{0xaaba, 0xaabd, 1},
+		{0xaac0, 0xaac2, 2},
+		{0xaadb, 0xaadd, 1},
+		{0xaae0, 0xaaea, 1},
+		{0xaaf2, 0xaaf4, 1},
+		{0xab01, 0xab06, 1},
+		{0xab09, 0xab0e, 1},
+		{0xab11, 0xab16, 1},
+		{0xab20, 0xab26, 1},
+		{0xab28, 0xab2e, 1},
+		{0xabc0, 0xabe2, 1},
+		{0xac00, 0xd7a3, 1},
+		{0xd7b0, 0xd7c6, 1},
+		{0xd7cb, 0xd7fb, 1},
+		{0xf900, 0xfa6d, 1},
+		{0xfa70, 0xfad9, 1},
+		{0xfb00, 0xfb06, 1},
+		{0xfb13, 0xfb17, 1},
+		{0xfb1d, 0xfb1f, 2},
+		{0xfb20, 0xfb28, 1},
+		{0xfb2a, 0xfb36, 1},
+		{0xfb38, 0xfb3c, 1},
+		{0xfb3e, 0xfb40, 2},
+		{0xfb41, 0xfb43, 2},
+		{0xfb44, 0xfb46, 2},
+		{0xfb47, 0xfbb1, 1},
+		{0xfbd3, 0xfd3d, 1},
+		{0xfd50, 0xfd8f, 1},
+		{0xfd92, 0xfdc7, 1},
+		{0xfdf0, 0xfdfb, 1},
+		{0xfe70, 0xfe74, 1},
+		{0xfe76, 0xfefc, 1},
+		{0xff21, 0xff3a, 1},
+		{0xff41, 0xff5a, 1},
+		{0xff66, 0xffbe, 1},
+		{0xffc2, 0xffc7, 1},
+		{0xffca, 0xffcf, 1},
+		{0xffd2, 0xffd7, 1},
+		{0xffda, 0xffdc, 1},
+	},
+	R32: []Range32{
+		{0x10000, 0x1000b, 1},
+		{0x1000d, 0x10026, 1},
+		{0x10028, 0x1003a, 1},
+		{0x1003c, 0x1003d, 1},
+		{0x1003f, 0x1004d, 1},
+		{0x10050, 0x1005d, 1},
+		{0x10080, 0x100fa, 1},
+		{0x10280, 0x1029c, 1},
+		{0x102a0, 0x102d0, 1},
+		{0x10300, 0x1031e, 1},
+		{0x10330, 0x10340, 1},
+		{0x10342, 0x10349, 1},
+		{0x10380, 0x1039d, 1},
+		{0x103a0, 0x103c3, 1},
+		{0x103c8, 0x103cf, 1},
+		{0x10400, 0x1049d, 1},
+		{0x10800, 0x10805, 1},
+		{0x10808, 0x1080a, 2},
+		{0x1080b, 0x10835, 1},
+		{0x10837, 0x10838, 1},
+		{0x1083c, 0x1083f, 3},
+		{0x10840, 0x10855, 1},
+		{0x10900, 0x10915, 1},
+		{0x10920, 0x10939, 1},
+		{0x10980, 0x109b7, 1},
+		{0x109be, 0x109bf, 1},
+		{0x10a00, 0x10a10, 16},
+		{0x10a11, 0x10a13, 1},
+		{0x10a15, 0x10a17, 1},
+		{0x10a19, 0x10a33, 1},
+		{0x10a60, 0x10a7c, 1},
+		{0x10b00, 0x10b35, 1},
+		{0x10b40, 0x10b55, 1},
+		{0x10b60, 0x10b72, 1},
+		{0x10c00, 0x10c48, 1},
+		{0x11003, 0x11037, 1},
+		{0x11083, 0x110af, 1},
+		{0x110d0, 0x110e8, 1},
+		{0x11103, 0x11126, 1},
+		{0x11183, 0x111b2, 1},
+		{0x111c1, 0x111c4, 1},
+		{0x11680, 0x116aa, 1},
+		{0x12000, 0x1236e, 1},
+		{0x13000, 0x1342e, 1},
+		{0x16800, 0x16a38, 1},
+		{0x16f00, 0x16f44, 1},
+		{0x16f50, 0x16f93, 67},
+		{0x16f94, 0x16f9f, 1},
+		{0x1b000, 0x1b001, 1},
+		{0x1d400, 0x1d454, 1},
+		{0x1d456, 0x1d49c, 1},
+		{0x1d49e, 0x1d49f, 1},
+		{0x1d4a2, 0x1d4a5, 3},
+		{0x1d4a6, 0x1d4a9, 3},
+		{0x1d4aa, 0x1d4ac, 1},
+		{0x1d4ae, 0x1d4b9, 1},
+		{0x1d4bb, 0x1d4bd, 2},
+		{0x1d4be, 0x1d4c3, 1},
+		{0x1d4c5, 0x1d505, 1},
+		{0x1d507, 0x1d50a, 1},
+		{0x1d50d, 0x1d514, 1},
+		{0x1d516, 0x1d51c, 1},
+		{0x1d51e, 0x1d539, 1},
+		{0x1d53b, 0x1d53e, 1},
+		{0x1d540, 0x1d544, 1},
+		{0x1d546, 0x1d54a, 4},
+		{0x1d54b, 0x1d550, 1},
+		{0x1d552, 0x1d6a5, 1},
+		{0x1d6a8, 0x1d6c0, 1},
+		{0x1d6c2, 0x1d6da, 1},
+		{0x1d6dc, 0x1d6fa, 1},
+		{0x1d6fc, 0x1d714, 1},
+		{0x1d716, 0x1d734, 1},
+		{0x1d736, 0x1d74e, 1},
+		{0x1d750, 0x1d76e, 1},
+		{0x1d770, 0x1d788, 1},
+		{0x1d78a, 0x1d7a8, 1},
+		{0x1d7aa, 0x1d7c2, 1},
+		{0x1d7c4, 0x1d7cb, 1},
+		{0x1ee00, 0x1ee03, 1},
+		{0x1ee05, 0x1ee1f, 1},
+		{0x1ee21, 0x1ee22, 1},
+		{0x1ee24, 0x1ee27, 3},
+		{0x1ee29, 0x1ee32, 1},
+		{0x1ee34, 0x1ee37, 1},
+		{0x1ee39, 0x1ee3b, 2},
+		{0x1ee42, 0x1ee47, 5},
+		{0x1ee49, 0x1ee4d, 2},
+		{0x1ee4e, 0x1ee4f, 1},
+		{0x1ee51, 0x1ee52, 1},
+		{0x1ee54, 0x1ee57, 3},
+		{0x1ee59, 0x1ee61, 2},
+		{0x1ee62, 0x1ee64, 2},
+		{0x1ee67, 0x1ee6a, 1},
+		{0x1ee6c, 0x1ee72, 1},
+		{0x1ee74, 0x1ee77, 1},
+		{0x1ee79, 0x1ee7c, 1},
+		{0x1ee7e, 0x1ee80, 2},
+		{0x1ee81, 0x1ee89, 1},
+		{0x1ee8b, 0x1ee9b, 1},
+		{0x1eea1, 0x1eea3, 1},
+		{0x1eea5, 0x1eea9, 1},
+		{0x1eeab, 0x1eebb, 1},
+		{0x20000, 0x2a6d6, 1},
+		{0x2a700, 0x2b734, 1},
+		{0x2b740, 0x2b81d, 1},
+		{0x2f800, 0x2fa1d, 1},
+	},
+	LatinOffset: 6,
+}
+
+var _Ll = &RangeTable{
+	R16: []Range16{
+		{0x0061, 0x007a, 1},
+		{0x00b5, 0x00df, 42},
+		{0x00e0, 0x00f6, 1},
+		{0x00f8, 0x00ff, 1},
+		{0x0101, 0x0137, 2},
+		{0x0138, 0x0148, 2},
+		{0x0149, 0x0177, 2},
+		{0x017a, 0x017e, 2},
+		{0x017f, 0x0180, 1},
+		{0x0183, 0x0185, 2},
+		{0x0188, 0x018c, 4},
+		{0x018d, 0x0192, 5},
+		{0x0195, 0x0199, 4},
+		{0x019a, 0x019b, 1},
+		{0x019e, 0x01a1, 3},
+		{0x01a3, 0x01a5, 2},
+		{0x01a8, 0x01aa, 2},
+		{0x01ab, 0x01ad, 2},
+		{0x01b0, 0x01b4, 4},
+		{0x01b6, 0x01b9, 3},
+		{0x01ba, 0x01bd, 3},
+		{0x01be, 0x01bf, 1},
+		{0x01c6, 0x01cc, 3},
+		{0x01ce, 0x01dc, 2},
+		{0x01dd, 0x01ef, 2},
+		{0x01f0, 0x01f3, 3},
+		{0x01f5, 0x01f9, 4},
+		{0x01fb, 0x0233, 2},
+		{0x0234, 0x0239, 1},
+		{0x023c, 0x023f, 3},
+		{0x0240, 0x0242, 2},
+		{0x0247, 0x024f, 2},
+		{0x0250, 0x0293, 1},
+		{0x0295, 0x02af, 1},
+		{0x0371, 0x0373, 2},
+		{0x0377, 0x037b, 4},
+		{0x037c, 0x037d, 1},
+		{0x0390, 0x03ac, 28},
+		{0x03ad, 0x03ce, 1},
+		{0x03d0, 0x03d1, 1},
+		{0x03d5, 0x03d7, 1},
+		{0x03d9, 0x03ef, 2},
+		{0x03f0, 0x03f3, 1},
+		{0x03f5, 0x03fb, 3},
+		{0x03fc, 0x0430, 52},
+		{0x0431, 0x045f, 1},
+		{0x0461, 0x0481, 2},
+		{0x048b, 0x04bf, 2},
+		{0x04c2, 0x04ce, 2},
+		{0x04cf, 0x0527, 2},
+		{0x0561, 0x0587, 1},
+		{0x1d00, 0x1d2b, 1},
+		{0x1d6b, 0x1d77, 1},
+		{0x1d79, 0x1d9a, 1},
+		{0x1e01, 0x1e95, 2},
+		{0x1e96, 0x1e9d, 1},
+		{0x1e9f, 0x1eff, 2},
+		{0x1f00, 0x1f07, 1},
+		{0x1f10, 0x1f15, 1},
+		{0x1f20, 0x1f27, 1},
+		{0x1f30, 0x1f37, 1},
+		{0x1f40, 0x1f45, 1},
+		{0x1f50, 0x1f57, 1},
+		{0x1f60, 0x1f67, 1},
+		{0x1f70, 0x1f7d, 1},
+		{0x1f80, 0x1f87, 1},
+		{0x1f90, 0x1f97, 1},
+		{0x1fa0, 0x1fa7, 1},
+		{0x1fb0, 0x1fb4, 1},
+		{0x1fb6, 0x1fb7, 1},
+		{0x1fbe, 0x1fc2, 4},
+		{0x1fc3, 0x1fc4, 1},
+		{0x1fc6, 0x1fc7, 1},
+		{0x1fd0, 0x1fd3, 1},
+		{0x1fd6, 0x1fd7, 1},
+		{0x1fe0, 0x1fe7, 1},
+		{0x1ff2, 0x1ff4, 1},
+		{0x1ff6, 0x1ff7, 1},
+		{0x210a, 0x210e, 4},
+		{0x210f, 0x2113, 4},
+		{0x212f, 0x2139, 5},
+		{0x213c, 0x213d, 1},
+		{0x2146, 0x2149, 1},
+		{0x214e, 0x2184, 54},
+		{0x2c30, 0x2c5e, 1},
+		{0x2c61, 0x2c65, 4},
+		{0x2c66, 0x2c6c, 2},
+		{0x2c71, 0x2c73, 2},
+		{0x2c74, 0x2c76, 2},
+		{0x2c77, 0x2c7b, 1},
+		{0x2c81, 0x2ce3, 2},
+		{0x2ce4, 0x2cec, 8},
+		{0x2cee, 0x2cf3, 5},
+		{0x2d00, 0x2d25, 1},
+		{0x2d27, 0x2d2d, 6},
+		{0xa641, 0xa66d, 2},
+		{0xa681, 0xa697, 2},
+		{0xa723, 0xa72f, 2},
+		{0xa730, 0xa731, 1},
+		{0xa733, 0xa771, 2},
+		{0xa772, 0xa778, 1},
+		{0xa77a, 0xa77c, 2},
+		{0xa77f, 0xa787, 2},
+		{0xa78c, 0xa78e, 2},
+		{0xa791, 0xa793, 2},
+		{0xa7a1, 0xa7a9, 2},
+		{0xa7fa, 0xfb00, 21254},
+		{0xfb01, 0xfb06, 1},
+		{0xfb13, 0xfb17, 1},
+		{0xff41, 0xff5a, 1},
+	},
+	R32: []Range32{
+		{0x10428, 0x1044f, 1},
+		{0x1d41a, 0x1d433, 1},
+		{0x1d44e, 0x1d454, 1},
+		{0x1d456, 0x1d467, 1},
+		{0x1d482, 0x1d49b, 1},
+		{0x1d4b6, 0x1d4b9, 1},
+		{0x1d4bb, 0x1d4bd, 2},
+		{0x1d4be, 0x1d4c3, 1},
+		{0x1d4c5, 0x1d4cf, 1},
+		{0x1d4ea, 0x1d503, 1},
+		{0x1d51e, 0x1d537, 1},
+		{0x1d552, 0x1d56b, 1},
+		{0x1d586, 0x1d59f, 1},
+		{0x1d5ba, 0x1d5d3, 1},
+		{0x1d5ee, 0x1d607, 1},
+		{0x1d622, 0x1d63b, 1},
+		{0x1d656, 0x1d66f, 1},
+		{0x1d68a, 0x1d6a5, 1},
+		{0x1d6c2, 0x1d6da, 1},
+		{0x1d6dc, 0x1d6e1, 1},
+		{0x1d6fc, 0x1d714, 1},
+		{0x1d716, 0x1d71b, 1},
+		{0x1d736, 0x1d74e, 1},
+		{0x1d750, 0x1d755, 1},
+		{0x1d770, 0x1d788, 1},
+		{0x1d78a, 0x1d78f, 1},
+		{0x1d7aa, 0x1d7c2, 1},
+		{0x1d7c4, 0x1d7c9, 1},
+		{0x1d7cb, 0x1d7cb, 1},
+	},
+	LatinOffset: 4,
+}
+
+var _Lm = &RangeTable{
+	R16: []Range16{
+		{0x02b0, 0x02c1, 1},
+		{0x02c6, 0x02d1, 1},
+		{0x02e0, 0x02e4, 1},
+		{0x02ec, 0x02ee, 2},
+		{0x0374, 0x037a, 6},
+		{0x0559, 0x0640, 231},
+		{0x06e5, 0x06e6, 1},
+		{0x07f4, 0x07f5, 1},
+		{0x07fa, 0x081a, 32},
+		{0x0824, 0x0828, 4},
+		{0x0971, 0x0e46, 1237},
+		{0x0ec6, 0x10fc, 566},
+		{0x17d7, 0x1843, 108},
+		{0x1aa7, 0x1c78, 465},
+		{0x1c79, 0x1c7d, 1},
+		{0x1d2c, 0x1d6a, 1},
+		{0x1d78, 0x1d9b, 35},
+		{0x1d9c, 0x1dbf, 1},
+		{0x2071, 0x207f, 14},
+		{0x2090, 0x209c, 1},
+		{0x2c7c, 0x2c7d, 1},
+		{0x2d6f, 0x2e2f, 192},
+		{0x3005, 0x3031, 44},
+		{0x3032, 0x3035, 1},
+		{0x303b, 0x309d, 98},
+		{0x309e, 0x30fc, 94},
+		{0x30fd, 0x30fe, 1},
+		{0xa015, 0xa4f8, 1251},
+		{0xa4f9, 0xa4fd, 1},
+		{0xa60c, 0xa67f, 115},
+		{0xa717, 0xa71f, 1},
+		{0xa770, 0xa788, 24},
+		{0xa7f8, 0xa7f9, 1},
+		{0xa9cf, 0xaa70, 161},
+		{0xaadd, 0xaaf3, 22},
+		{0xaaf4, 0xff70, 21628},
+		{0xff9e, 0xff9f, 1},
+	},
+	R32: []Range32{
+		{0x16f93, 0x16f9f, 1},
+	},
+}
+
+var _Lo = &RangeTable{
+	R16: []Range16{
+		{0x00aa, 0x00ba, 16},
+		{0x01bb, 0x01c0, 5},
+		{0x01c1, 0x01c3, 1},
+		{0x0294, 0x05d0, 828},
+		{0x05d1, 0x05ea, 1},
+		{0x05f0, 0x05f2, 1},
+		{0x0620, 0x063f, 1},
+		{0x0641, 0x064a, 1},
+		{0x066e, 0x066f, 1},
+		{0x0671, 0x06d3, 1},
+		{0x06d5, 0x06ee, 25},
+		{0x06ef, 0x06fa, 11},
+		{0x06fb, 0x06fc, 1},
+		{0x06ff, 0x0710, 17},
+		{0x0712, 0x072f, 1},
+		{0x074d, 0x07a5, 1},
+		{0x07b1, 0x07ca, 25},
+		{0x07cb, 0x07ea, 1},
+		{0x0800, 0x0815, 1},
+		{0x0840, 0x0858, 1},
+		{0x08a0, 0x08a2, 2},
+		{0x08a3, 0x08ac, 1},
+		{0x0904, 0x0939, 1},
+		{0x093d, 0x0950, 19},
+		{0x0958, 0x0961, 1},
+		{0x0972, 0x0977, 1},
+		{0x0979, 0x097f, 1},
+		{0x0985, 0x098c, 1},
+		{0x098f, 0x0990, 1},
+		{0x0993, 0x09a8, 1},
+		{0x09aa, 0x09b0, 1},
+		{0x09b2, 0x09b6, 4},
+		{0x09b7, 0x09b9, 1},
+		{0x09bd, 0x09ce, 17},
+		{0x09dc, 0x09dd, 1},
+		{0x09df, 0x09e1, 1},
+		{0x09f0, 0x09f1, 1},
+		{0x0a05, 0x0a0a, 1},
+		{0x0a0f, 0x0a10, 1},
+		{0x0a13, 0x0a28, 1},
+		{0x0a2a, 0x0a30, 1},
+		{0x0a32, 0x0a33, 1},
+		{0x0a35, 0x0a36, 1},
+		{0x0a38, 0x0a39, 1},
+		{0x0a59, 0x0a5c, 1},
+		{0x0a5e, 0x0a72, 20},
+		{0x0a73, 0x0a74, 1},
+		{0x0a85, 0x0a8d, 1},
+		{0x0a8f, 0x0a91, 1},
+		{0x0a93, 0x0aa8, 1},
+		{0x0aaa, 0x0ab0, 1},
+		{0x0ab2, 0x0ab3, 1},
+		{0x0ab5, 0x0ab9, 1},
+		{0x0abd, 0x0ad0, 19},
+		{0x0ae0, 0x0ae1, 1},
+		{0x0b05, 0x0b0c, 1},
+		{0x0b0f, 0x0b10, 1},
+		{0x0b13, 0x0b28, 1},
+		{0x0b2a, 0x0b30, 1},
+		{0x0b32, 0x0b33, 1},
+		{0x0b35, 0x0b39, 1},
+		{0x0b3d, 0x0b5c, 31},
+		{0x0b5d, 0x0b5f, 2},
+		{0x0b60, 0x0b61, 1},
+		{0x0b71, 0x0b83, 18},
+		{0x0b85, 0x0b8a, 1},
+		{0x0b8e, 0x0b90, 1},
+		{0x0b92, 0x0b95, 1},
+		{0x0b99, 0x0b9a, 1},
+		{0x0b9c, 0x0b9e, 2},
+		{0x0b9f, 0x0ba3, 4},
+		{0x0ba4, 0x0ba8, 4},
+		{0x0ba9, 0x0baa, 1},
+		{0x0bae, 0x0bb9, 1},
+		{0x0bd0, 0x0c05, 53},
+		{0x0c06, 0x0c0c, 1},
+		{0x0c0e, 0x0c10, 1},
+		{0x0c12, 0x0c28, 1},
+		{0x0c2a, 0x0c33, 1},
+		{0x0c35, 0x0c39, 1},
+		{0x0c3d, 0x0c58, 27},
+		{0x0c59, 0x0c60, 7},
+		{0x0c61, 0x0c85, 36},
+		{0x0c86, 0x0c8c, 1},
+		{0x0c8e, 0x0c90, 1},
+		{0x0c92, 0x0ca8, 1},
+		{0x0caa, 0x0cb3, 1},
+		{0x0cb5, 0x0cb9, 1},
+		{0x0cbd, 0x0cde, 33},
+		{0x0ce0, 0x0ce1, 1},
+		{0x0cf1, 0x0cf2, 1},
+		{0x0d05, 0x0d0c, 1},
+		{0x0d0e, 0x0d10, 1},
+		{0x0d12, 0x0d3a, 1},
+		{0x0d3d, 0x0d4e, 17},
+		{0x0d60, 0x0d61, 1},
+		{0x0d7a, 0x0d7f, 1},
+		{0x0d85, 0x0d96, 1},
+		{0x0d9a, 0x0db1, 1},
+		{0x0db3, 0x0dbb, 1},
+		{0x0dbd, 0x0dc0, 3},
+		{0x0dc1, 0x0dc6, 1},
+		{0x0e01, 0x0e30, 1},
+		{0x0e32, 0x0e33, 1},
+		{0x0e40, 0x0e45, 1},
+		{0x0e81, 0x0e82, 1},
+		{0x0e84, 0x0e87, 3},
+		{0x0e88, 0x0e8a, 2},
+		{0x0e8d, 0x0e94, 7},
+		{0x0e95, 0x0e97, 1},
+		{0x0e99, 0x0e9f, 1},
+		{0x0ea1, 0x0ea3, 1},
+		{0x0ea5, 0x0ea7, 2},
+		{0x0eaa, 0x0eab, 1},
+		{0x0ead, 0x0eb0, 1},
+		{0x0eb2, 0x0eb3, 1},
+		{0x0ebd, 0x0ec0, 3},
+		{0x0ec1, 0x0ec4, 1},
+		{0x0edc, 0x0edf, 1},
+		{0x0f00, 0x0f40, 64},
+		{0x0f41, 0x0f47, 1},
+		{0x0f49, 0x0f6c, 1},
+		{0x0f88, 0x0f8c, 1},
+		{0x1000, 0x102a, 1},
+		{0x103f, 0x1050, 17},
+		{0x1051, 0x1055, 1},
+		{0x105a, 0x105d, 1},
+		{0x1061, 0x1065, 4},
+		{0x1066, 0x106e, 8},
+		{0x106f, 0x1070, 1},
+		{0x1075, 0x1081, 1},
+		{0x108e, 0x10d0, 66},
+		{0x10d1, 0x10fa, 1},
+		{0x10fd, 0x1248, 1},
+		{0x124a, 0x124d, 1},
+		{0x1250, 0x1256, 1},
+		{0x1258, 0x125a, 2},
+		{0x125b, 0x125d, 1},
+		{0x1260, 0x1288, 1},
+		{0x128a, 0x128d, 1},
+		{0x1290, 0x12b0, 1},
+		{0x12b2, 0x12b5, 1},
+		{0x12b8, 0x12be, 1},
+		{0x12c0, 0x12c2, 2},
+		{0x12c3, 0x12c5, 1},
+		{0x12c8, 0x12d6, 1},
+		{0x12d8, 0x1310, 1},
+		{0x1312, 0x1315, 1},
+		{0x1318, 0x135a, 1},
+		{0x1380, 0x138f, 1},
+		{0x13a0, 0x13f4, 1},
+		{0x1401, 0x166c, 1},
+		{0x166f, 0x167f, 1},
+		{0x1681, 0x169a, 1},
+		{0x16a0, 0x16ea, 1},
+		{0x1700, 0x170c, 1},
+		{0x170e, 0x1711, 1},
+		{0x1720, 0x1731, 1},
+		{0x1740, 0x1751, 1},
+		{0x1760, 0x176c, 1},
+		{0x176e, 0x1770, 1},
+		{0x1780, 0x17b3, 1},
+		{0x17dc, 0x1820, 68},
+		{0x1821, 0x1842, 1},
+		{0x1844, 0x1877, 1},
+		{0x1880, 0x18a8, 1},
+		{0x18aa, 0x18b0, 6},
+		{0x18b1, 0x18f5, 1},
+		{0x1900, 0x191c, 1},
+		{0x1950, 0x196d, 1},
+		{0x1970, 0x1974, 1},
+		{0x1980, 0x19ab, 1},
+		{0x19c1, 0x19c7, 1},
+		{0x1a00, 0x1a16, 1},
+		{0x1a20, 0x1a54, 1},
+		{0x1b05, 0x1b33, 1},
+		{0x1b45, 0x1b4b, 1},
+		{0x1b83, 0x1ba0, 1},
+		{0x1bae, 0x1baf, 1},
+		{0x1bba, 0x1be5, 1},
+		{0x1c00, 0x1c23, 1},
+		{0x1c4d, 0x1c4f, 1},
+		{0x1c5a, 0x1c77, 1},
+		{0x1ce9, 0x1cec, 1},
+		{0x1cee, 0x1cf1, 1},
+		{0x1cf5, 0x1cf6, 1},
+		{0x2135, 0x2138, 1},
+		{0x2d30, 0x2d67, 1},
+		{0x2d80, 0x2d96, 1},
+		{0x2da0, 0x2da6, 1},
+		{0x2da8, 0x2dae, 1},
+		{0x2db0, 0x2db6, 1},
+		{0x2db8, 0x2dbe, 1},
+		{0x2dc0, 0x2dc6, 1},
+		{0x2dc8, 0x2dce, 1},
+		{0x2dd0, 0x2dd6, 1},
+		{0x2dd8, 0x2dde, 1},
+		{0x3006, 0x303c, 54},
+		{0x3041, 0x3096, 1},
+		{0x309f, 0x30a1, 2},
+		{0x30a2, 0x30fa, 1},
+		{0x30ff, 0x3105, 6},
+		{0x3106, 0x312d, 1},
+		{0x3131, 0x318e, 1},
+		{0x31a0, 0x31ba, 1},
+		{0x31f0, 0x31ff, 1},
+		{0x3400, 0x4db5, 1},
+		{0x4e00, 0x9fcc, 1},
+		{0xa000, 0xa014, 1},
+		{0xa016, 0xa48c, 1},
+		{0xa4d0, 0xa4f7, 1},
+		{0xa500, 0xa60b, 1},
+		{0xa610, 0xa61f, 1},
+		{0xa62a, 0xa62b, 1},
+		{0xa66e, 0xa6a0, 50},
+		{0xa6a1, 0xa6e5, 1},
+		{0xa7fb, 0xa801, 1},
+		{0xa803, 0xa805, 1},
+		{0xa807, 0xa80a, 1},
+		{0xa80c, 0xa822, 1},
+		{0xa840, 0xa873, 1},
+		{0xa882, 0xa8b3, 1},
+		{0xa8f2, 0xa8f7, 1},
+		{0xa8fb, 0xa90a, 15},
+		{0xa90b, 0xa925, 1},
+		{0xa930, 0xa946, 1},
+		{0xa960, 0xa97c, 1},
+		{0xa984, 0xa9b2, 1},
+		{0xaa00, 0xaa28, 1},
+		{0xaa40, 0xaa42, 1},
+		{0xaa44, 0xaa4b, 1},
+		{0xaa60, 0xaa6f, 1},
+		{0xaa71, 0xaa76, 1},
+		{0xaa7a, 0xaa80, 6},
+		{0xaa81, 0xaaaf, 1},
+		{0xaab1, 0xaab5, 4},
+		{0xaab6, 0xaab9, 3},
+		{0xaaba, 0xaabd, 1},
+		{0xaac0, 0xaac2, 2},
+		{0xaadb, 0xaadc, 1},
+		{0xaae0, 0xaaea, 1},
+		{0xaaf2, 0xab01, 15},
+		{0xab02, 0xab06, 1},
+		{0xab09, 0xab0e, 1},
+		{0xab11, 0xab16, 1},
+		{0xab20, 0xab26, 1},
+		{0xab28, 0xab2e, 1},
+		{0xabc0, 0xabe2, 1},
+		{0xac00, 0xd7a3, 1},
+		{0xd7b0, 0xd7c6, 1},
+		{0xd7cb, 0xd7fb, 1},
+		{0xf900, 0xfa6d, 1},
+		{0xfa70, 0xfad9, 1},
+		{0xfb1d, 0xfb1f, 2},
+		{0xfb20, 0xfb28, 1},
+		{0xfb2a, 0xfb36, 1},
+		{0xfb38, 0xfb3c, 1},
+		{0xfb3e, 0xfb40, 2},
+		{0xfb41, 0xfb43, 2},
+		{0xfb44, 0xfb46, 2},
+		{0xfb47, 0xfbb1, 1},
+		{0xfbd3, 0xfd3d, 1},
+		{0xfd50, 0xfd8f, 1},
+		{0xfd92, 0xfdc7, 1},
+		{0xfdf0, 0xfdfb, 1},
+		{0xfe70, 0xfe74, 1},
+		{0xfe76, 0xfefc, 1},
+		{0xff66, 0xff6f, 1},
+		{0xff71, 0xff9d, 1},
+		{0xffa0, 0xffbe, 1},
+		{0xffc2, 0xffc7, 1},
+		{0xffca, 0xffcf, 1},
+		{0xffd2, 0xffd7, 1},
+		{0xffda, 0xffdc, 1},
+	},
+	R32: []Range32{
+		{0x10000, 0x1000b, 1},
+		{0x1000d, 0x10026, 1},
+		{0x10028, 0x1003a, 1},
+		{0x1003c, 0x1003d, 1},
+		{0x1003f, 0x1004d, 1},
+		{0x10050, 0x1005d, 1},
+		{0x10080, 0x100fa, 1},
+		{0x10280, 0x1029c, 1},
+		{0x102a0, 0x102d0, 1},
+		{0x10300, 0x1031e, 1},
+		{0x10330, 0x10340, 1},
+		{0x10342, 0x10349, 1},
+		{0x10380, 0x1039d, 1},
+		{0x103a0, 0x103c3, 1},
+		{0x103c8, 0x103cf, 1},
+		{0x10450, 0x1049d, 1},
+		{0x10800, 0x10805, 1},
+		{0x10808, 0x1080a, 2},
+		{0x1080b, 0x10835, 1},
+		{0x10837, 0x10838, 1},
+		{0x1083c, 0x1083f, 3},
+		{0x10840, 0x10855, 1},
+		{0x10900, 0x10915, 1},
+		{0x10920, 0x10939, 1},
+		{0x10980, 0x109b7, 1},
+		{0x109be, 0x109bf, 1},
+		{0x10a00, 0x10a10, 16},
+		{0x10a11, 0x10a13, 1},
+		{0x10a15, 0x10a17, 1},
+		{0x10a19, 0x10a33, 1},
+		{0x10a60, 0x10a7c, 1},
+		{0x10b00, 0x10b35, 1},
+		{0x10b40, 0x10b55, 1},
+		{0x10b60, 0x10b72, 1},
+		{0x10c00, 0x10c48, 1},
+		{0x11003, 0x11037, 1},
+		{0x11083, 0x110af, 1},
+		{0x110d0, 0x110e8, 1},
+		{0x11103, 0x11126, 1},
+		{0x11183, 0x111b2, 1},
+		{0x111c1, 0x111c4, 1},
+		{0x11680, 0x116aa, 1},
+		{0x12000, 0x1236e, 1},
+		{0x13000, 0x1342e, 1},
+		{0x16800, 0x16a38, 1},
+		{0x16f00, 0x16f44, 1},
+		{0x16f50, 0x1b000, 16560},
+		{0x1b001, 0x1ee00, 15871},
+		{0x1ee01, 0x1ee03, 1},
+		{0x1ee05, 0x1ee1f, 1},
+		{0x1ee21, 0x1ee22, 1},
+		{0x1ee24, 0x1ee27, 3},
+		{0x1ee29, 0x1ee32, 1},
+		{0x1ee34, 0x1ee37, 1},
+		{0x1ee39, 0x1ee3b, 2},
+		{0x1ee42, 0x1ee47, 5},
+		{0x1ee49, 0x1ee4d, 2},
+		{0x1ee4e, 0x1ee4f, 1},
+		{0x1ee51, 0x1ee52, 1},
+		{0x1ee54, 0x1ee57, 3},
+		{0x1ee59, 0x1ee61, 2},
+		{0x1ee62, 0x1ee64, 2},
+		{0x1ee67, 0x1ee6a, 1},
+		{0x1ee6c, 0x1ee72, 1},
+		{0x1ee74, 0x1ee77, 1},
+		{0x1ee79, 0x1ee7c, 1},
+		{0x1ee7e, 0x1ee80, 2},
+		{0x1ee81, 0x1ee89, 1},
+		{0x1ee8b, 0x1ee9b, 1},
+		{0x1eea1, 0x1eea3, 1},
+		{0x1eea5, 0x1eea9, 1},
+		{0x1eeab, 0x1eebb, 1},
+		{0x20000, 0x2a6d6, 1},
+		{0x2a700, 0x2b734, 1},
+		{0x2b740, 0x2b81d, 1},
+		{0x2f800, 0x2fa1d, 1},
+	},
+	LatinOffset: 1,
+}
+
+var _Lt = &RangeTable{
+	R16: []Range16{
+		{0x01c5, 0x01cb, 3},
+		{0x01f2, 0x1f88, 7574},
+		{0x1f89, 0x1f8f, 1},
+		{0x1f98, 0x1f9f, 1},
+		{0x1fa8, 0x1faf, 1},
+		{0x1fbc, 0x1fcc, 16},
+		{0x1ffc, 0x1ffc, 1},
+	},
+}
+
+var _Lu = &RangeTable{
+	R16: []Range16{
+		{0x0041, 0x005a, 1},
+		{0x00c0, 0x00d6, 1},
+		{0x00d8, 0x00de, 1},
+		{0x0100, 0x0136, 2},
+		{0x0139, 0x0147, 2},
+		{0x014a, 0x0178, 2},
+		{0x0179, 0x017d, 2},
+		{0x0181, 0x0182, 1},
+		{0x0184, 0x0186, 2},
+		{0x0187, 0x0189, 2},
+		{0x018a, 0x018b, 1},
+		{0x018e, 0x0191, 1},
+		{0x0193, 0x0194, 1},
+		{0x0196, 0x0198, 1},
+		{0x019c, 0x019d, 1},
+		{0x019f, 0x01a0, 1},
+		{0x01a2, 0x01a6, 2},
+		{0x01a7, 0x01a9, 2},
+		{0x01ac, 0x01ae, 2},
+		{0x01af, 0x01b1, 2},
+		{0x01b2, 0x01b3, 1},
+		{0x01b5, 0x01b7, 2},
+		{0x01b8, 0x01bc, 4},
+		{0x01c4, 0x01cd, 3},
+		{0x01cf, 0x01db, 2},
+		{0x01de, 0x01ee, 2},
+		{0x01f1, 0x01f4, 3},
+		{0x01f6, 0x01f8, 1},
+		{0x01fa, 0x0232, 2},
+		{0x023a, 0x023b, 1},
+		{0x023d, 0x023e, 1},
+		{0x0241, 0x0243, 2},
+		{0x0244, 0x0246, 1},
+		{0x0248, 0x024e, 2},
+		{0x0370, 0x0372, 2},
+		{0x0376, 0x0386, 16},
+		{0x0388, 0x038a, 1},
+		{0x038c, 0x038e, 2},
+		{0x038f, 0x0391, 2},
+		{0x0392, 0x03a1, 1},
+		{0x03a3, 0x03ab, 1},
+		{0x03cf, 0x03d2, 3},
+		{0x03d3, 0x03d4, 1},
+		{0x03d8, 0x03ee, 2},
+		{0x03f4, 0x03f7, 3},
+		{0x03f9, 0x03fa, 1},
+		{0x03fd, 0x042f, 1},
+		{0x0460, 0x0480, 2},
+		{0x048a, 0x04c0, 2},
+		{0x04c1, 0x04cd, 2},
+		{0x04d0, 0x0526, 2},
+		{0x0531, 0x0556, 1},
+		{0x10a0, 0x10c5, 1},
+		{0x10c7, 0x10cd, 6},
+		{0x1e00, 0x1e94, 2},
+		{0x1e9e, 0x1efe, 2},
+		{0x1f08, 0x1f0f, 1},
+		{0x1f18, 0x1f1d, 1},
+		{0x1f28, 0x1f2f, 1},
+		{0x1f38, 0x1f3f, 1},
+		{0x1f48, 0x1f4d, 1},
+		{0x1f59, 0x1f5f, 2},
+		{0x1f68, 0x1f6f, 1},
+		{0x1fb8, 0x1fbb, 1},
+		{0x1fc8, 0x1fcb, 1},
+		{0x1fd8, 0x1fdb, 1},
+		{0x1fe8, 0x1fec, 1},
+		{0x1ff8, 0x1ffb, 1},
+		{0x2102, 0x2107, 5},
+		{0x210b, 0x210d, 1},
+		{0x2110, 0x2112, 1},
+		{0x2115, 0x2119, 4},
+		{0x211a, 0x211d, 1},
+		{0x2124, 0x212a, 2},
+		{0x212b, 0x212d, 1},
+		{0x2130, 0x2133, 1},
+		{0x213e, 0x213f, 1},
+		{0x2145, 0x2183, 62},
+		{0x2c00, 0x2c2e, 1},
+		{0x2c60, 0x2c62, 2},
+		{0x2c63, 0x2c64, 1},
+		{0x2c67, 0x2c6d, 2},
+		{0x2c6e, 0x2c70, 1},
+		{0x2c72, 0x2c75, 3},
+		{0x2c7e, 0x2c80, 1},
+		{0x2c82, 0x2ce2, 2},
+		{0x2ceb, 0x2ced, 2},
+		{0x2cf2, 0xa640, 31054},
+		{0xa642, 0xa66c, 2},
+		{0xa680, 0xa696, 2},
+		{0xa722, 0xa72e, 2},
+		{0xa732, 0xa76e, 2},
+		{0xa779, 0xa77d, 2},
+		{0xa77e, 0xa786, 2},
+		{0xa78b, 0xa78d, 2},
+		{0xa790, 0xa792, 2},
+		{0xa7a0, 0xa7aa, 2},
+		{0xff21, 0xff3a, 1},
+	},
+	R32: []Range32{
+		{0x10400, 0x10427, 1},
+		{0x1d400, 0x1d419, 1},
+		{0x1d434, 0x1d44d, 1},
+		{0x1d468, 0x1d481, 1},
+		{0x1d49c, 0x1d49e, 2},
+		{0x1d49f, 0x1d4a5, 3},
+		{0x1d4a6, 0x1d4a9, 3},
+		{0x1d4aa, 0x1d4ac, 1},
+		{0x1d4ae, 0x1d4b5, 1},
+		{0x1d4d0, 0x1d4e9, 1},
+		{0x1d504, 0x1d505, 1},
+		{0x1d507, 0x1d50a, 1},
+		{0x1d50d, 0x1d514, 1},
+		{0x1d516, 0x1d51c, 1},
+		{0x1d538, 0x1d539, 1},
+		{0x1d53b, 0x1d53e, 1},
+		{0x1d540, 0x1d544, 1},
+		{0x1d546, 0x1d54a, 4},
+		{0x1d54b, 0x1d550, 1},
+		{0x1d56c, 0x1d585, 1},
+		{0x1d5a0, 0x1d5b9, 1},
+		{0x1d5d4, 0x1d5ed, 1},
+		{0x1d608, 0x1d621, 1},
+		{0x1d63c, 0x1d655, 1},
+		{0x1d670, 0x1d689, 1},
+		{0x1d6a8, 0x1d6c0, 1},
+		{0x1d6e2, 0x1d6fa, 1},
+		{0x1d71c, 0x1d734, 1},
+		{0x1d756, 0x1d76e, 1},
+		{0x1d790, 0x1d7a8, 1},
+		{0x1d7ca, 0x1d7ca, 1},
+	},
+	LatinOffset: 3,
+}
+
+var _M = &RangeTable{
+	R16: []Range16{
+		{0x0300, 0x036f, 1},
+		{0x0483, 0x0489, 1},
+		{0x0591, 0x05bd, 1},
+		{0x05bf, 0x05c1, 2},
+		{0x05c2, 0x05c4, 2},
+		{0x05c5, 0x05c7, 2},
+		{0x0610, 0x061a, 1},
+		{0x064b, 0x065f, 1},
+		{0x0670, 0x06d6, 102},
+		{0x06d7, 0x06dc, 1},
+		{0x06df, 0x06e4, 1},
+		{0x06e7, 0x06e8, 1},
+		{0x06ea, 0x06ed, 1},
+		{0x0711, 0x0730, 31},
+		{0x0731, 0x074a, 1},
+		{0x07a6, 0x07b0, 1},
+		{0x07eb, 0x07f3, 1},
+		{0x0816, 0x0819, 1},
+		{0x081b, 0x0823, 1},
+		{0x0825, 0x0827, 1},
+		{0x0829, 0x082d, 1},
+		{0x0859, 0x085b, 1},
+		{0x08e4, 0x08fe, 1},
+		{0x0900, 0x0903, 1},
+		{0x093a, 0x093c, 1},
+		{0x093e, 0x094f, 1},
+		{0x0951, 0x0957, 1},
+		{0x0962, 0x0963, 1},
+		{0x0981, 0x0983, 1},
+		{0x09bc, 0x09be, 2},
+		{0x09bf, 0x09c4, 1},
+		{0x09c7, 0x09c8, 1},
+		{0x09cb, 0x09cd, 1},
+		{0x09d7, 0x09e2, 11},
+		{0x09e3, 0x0a01, 30},
+		{0x0a02, 0x0a03, 1},
+		{0x0a3c, 0x0a3e, 2},
+		{0x0a3f, 0x0a42, 1},
+		{0x0a47, 0x0a48, 1},
+		{0x0a4b, 0x0a4d, 1},
+		{0x0a51, 0x0a70, 31},
+		{0x0a71, 0x0a75, 4},
+		{0x0a81, 0x0a83, 1},
+		{0x0abc, 0x0abe, 2},
+		{0x0abf, 0x0ac5, 1},
+		{0x0ac7, 0x0ac9, 1},
+		{0x0acb, 0x0acd, 1},
+		{0x0ae2, 0x0ae3, 1},
+		{0x0b01, 0x0b03, 1},
+		{0x0b3c, 0x0b3e, 2},
+		{0x0b3f, 0x0b44, 1},
+		{0x0b47, 0x0b48, 1},
+		{0x0b4b, 0x0b4d, 1},
+		{0x0b56, 0x0b57, 1},
+		{0x0b62, 0x0b63, 1},
+		{0x0b82, 0x0bbe, 60},
+		{0x0bbf, 0x0bc2, 1},
+		{0x0bc6, 0x0bc8, 1},
+		{0x0bca, 0x0bcd, 1},
+		{0x0bd7, 0x0c01, 42},
+		{0x0c02, 0x0c03, 1},
+		{0x0c3e, 0x0c44, 1},
+		{0x0c46, 0x0c48, 1},
+		{0x0c4a, 0x0c4d, 1},
+		{0x0c55, 0x0c56, 1},
+		{0x0c62, 0x0c63, 1},
+		{0x0c82, 0x0c83, 1},
+		{0x0cbc, 0x0cbe, 2},
+		{0x0cbf, 0x0cc4, 1},
+		{0x0cc6, 0x0cc8, 1},
+		{0x0cca, 0x0ccd, 1},
+		{0x0cd5, 0x0cd6, 1},
+		{0x0ce2, 0x0ce3, 1},
+		{0x0d02, 0x0d03, 1},
+		{0x0d3e, 0x0d44, 1},
+		{0x0d46, 0x0d48, 1},
+		{0x0d4a, 0x0d4d, 1},
+		{0x0d57, 0x0d62, 11},
+		{0x0d63, 0x0d82, 31},
+		{0x0d83, 0x0dca, 71},
+		{0x0dcf, 0x0dd4, 1},
+		{0x0dd6, 0x0dd8, 2},
+		{0x0dd9, 0x0ddf, 1},
+		{0x0df2, 0x0df3, 1},
+		{0x0e31, 0x0e34, 3},
+		{0x0e35, 0x0e3a, 1},
+		{0x0e47, 0x0e4e, 1},
+		{0x0eb1, 0x0eb4, 3},
+		{0x0eb5, 0x0eb9, 1},
+		{0x0ebb, 0x0ebc, 1},
+		{0x0ec8, 0x0ecd, 1},
+		{0x0f18, 0x0f19, 1},
+		{0x0f35, 0x0f39, 2},
+		{0x0f3e, 0x0f3f, 1},
+		{0x0f71, 0x0f84, 1},
+		{0x0f86, 0x0f87, 1},
+		{0x0f8d, 0x0f97, 1},
+		{0x0f99, 0x0fbc, 1},
+		{0x0fc6, 0x102b, 101},
+		{0x102c, 0x103e, 1},
+		{0x1056, 0x1059, 1},
+		{0x105e, 0x1060, 1},
+		{0x1062, 0x1064, 1},
+		{0x1067, 0x106d, 1},
+		{0x1071, 0x1074, 1},
+		{0x1082, 0x108d, 1},
+		{0x108f, 0x109a, 11},
+		{0x109b, 0x109d, 1},
+		{0x135d, 0x135f, 1},
+		{0x1712, 0x1714, 1},
+		{0x1732, 0x1734, 1},
+		{0x1752, 0x1753, 1},
+		{0x1772, 0x1773, 1},
+		{0x17b4, 0x17d3, 1},
+		{0x17dd, 0x180b, 46},
+		{0x180c, 0x180d, 1},
+		{0x18a9, 0x1920, 119},
+		{0x1921, 0x192b, 1},
+		{0x1930, 0x193b, 1},
+		{0x19b0, 0x19c0, 1},
+		{0x19c8, 0x19c9, 1},
+		{0x1a17, 0x1a1b, 1},
+		{0x1a55, 0x1a5e, 1},
+		{0x1a60, 0x1a7c, 1},
+		{0x1a7f, 0x1b00, 129},
+		{0x1b01, 0x1b04, 1},
+		{0x1b34, 0x1b44, 1},
+		{0x1b6b, 0x1b73, 1},
+		{0x1b80, 0x1b82, 1},
+		{0x1ba1, 0x1bad, 1},
+		{0x1be6, 0x1bf3, 1},
+		{0x1c24, 0x1c37, 1},
+		{0x1cd0, 0x1cd2, 1},
+		{0x1cd4, 0x1ce8, 1},
+		{0x1ced, 0x1cf2, 5},
+		{0x1cf3, 0x1cf4, 1},
+		{0x1dc0, 0x1de6, 1},
+		{0x1dfc, 0x1dff, 1},
+		{0x20d0, 0x20f0, 1},
+		{0x2cef, 0x2cf1, 1},
+		{0x2d7f, 0x2de0, 97},
+		{0x2de1, 0x2dff, 1},
+		{0x302a, 0x302f, 1},
+		{0x3099, 0x309a, 1},
+		{0xa66f, 0xa672, 1},
+		{0xa674, 0xa67d, 1},
+		{0xa69f, 0xa6f0, 81},
+		{0xa6f1, 0xa802, 273},
+		{0xa806, 0xa80b, 5},
+		{0xa823, 0xa827, 1},
+		{0xa880, 0xa881, 1},
+		{0xa8b4, 0xa8c4, 1},
+		{0xa8e0, 0xa8f1, 1},
+		{0xa926, 0xa92d, 1},
+		{0xa947, 0xa953, 1},
+		{0xa980, 0xa983, 1},
+		{0xa9b3, 0xa9c0, 1},
+		{0xaa29, 0xaa36, 1},
+		{0xaa43, 0xaa4c, 9},
+		{0xaa4d, 0xaa7b, 46},
+		{0xaab0, 0xaab2, 2},
+		{0xaab3, 0xaab4, 1},
+		{0xaab7, 0xaab8, 1},
+		{0xaabe, 0xaabf, 1},
+		{0xaac1, 0xaaeb, 42},
+		{0xaaec, 0xaaef, 1},
+		{0xaaf5, 0xaaf6, 1},
+		{0xabe3, 0xabea, 1},
+		{0xabec, 0xabed, 1},
+		{0xfb1e, 0xfe00, 738},
+		{0xfe01, 0xfe0f, 1},
+		{0xfe20, 0xfe26, 1},
+	},
+	R32: []Range32{
+		{0x101fd, 0x10a01, 2052},
+		{0x10a02, 0x10a03, 1},
+		{0x10a05, 0x10a06, 1},
+		{0x10a0c, 0x10a0f, 1},
+		{0x10a38, 0x10a3a, 1},
+		{0x10a3f, 0x11000, 1473},
+		{0x11001, 0x11002, 1},
+		{0x11038, 0x11046, 1},
+		{0x11080, 0x11082, 1},
+		{0x110b0, 0x110ba, 1},
+		{0x11100, 0x11102, 1},
+		{0x11127, 0x11134, 1},
+		{0x11180, 0x11182, 1},
+		{0x111b3, 0x111c0, 1},
+		{0x116ab, 0x116b7, 1},
+		{0x16f51, 0x16f7e, 1},
+		{0x16f8f, 0x16f92, 1},
+		{0x1d165, 0x1d169, 1},
+		{0x1d16d, 0x1d172, 1},
+		{0x1d17b, 0x1d182, 1},
+		{0x1d185, 0x1d18b, 1},
+		{0x1d1aa, 0x1d1ad, 1},
+		{0x1d242, 0x1d244, 1},
+		{0xe0100, 0xe01ef, 1},
+	},
+}
+
+var _Mc = &RangeTable{
+	R16: []Range16{
+		{0x0903, 0x093b, 56},
+		{0x093e, 0x0940, 1},
+		{0x0949, 0x094c, 1},
+		{0x094e, 0x094f, 1},
+		{0x0982, 0x0983, 1},
+		{0x09be, 0x09c0, 1},
+		{0x09c7, 0x09c8, 1},
+		{0x09cb, 0x09cc, 1},
+		{0x09d7, 0x0a03, 44},
+		{0x0a3e, 0x0a40, 1},
+		{0x0a83, 0x0abe, 59},
+		{0x0abf, 0x0ac0, 1},
+		{0x0ac9, 0x0acb, 2},
+		{0x0acc, 0x0b02, 54},
+		{0x0b03, 0x0b3e, 59},
+		{0x0b40, 0x0b47, 7},
+		{0x0b48, 0x0b4b, 3},
+		{0x0b4c, 0x0b57, 11},
+		{0x0bbe, 0x0bbf, 1},
+		{0x0bc1, 0x0bc2, 1},
+		{0x0bc6, 0x0bc8, 1},
+		{0x0bca, 0x0bcc, 1},
+		{0x0bd7, 0x0c01, 42},
+		{0x0c02, 0x0c03, 1},
+		{0x0c41, 0x0c44, 1},
+		{0x0c82, 0x0c83, 1},
+		{0x0cbe, 0x0cc0, 2},
+		{0x0cc1, 0x0cc4, 1},
+		{0x0cc7, 0x0cc8, 1},
+		{0x0cca, 0x0ccb, 1},
+		{0x0cd5, 0x0cd6, 1},
+		{0x0d02, 0x0d03, 1},
+		{0x0d3e, 0x0d40, 1},
+		{0x0d46, 0x0d48, 1},
+		{0x0d4a, 0x0d4c, 1},
+		{0x0d57, 0x0d82, 43},
+		{0x0d83, 0x0dcf, 76},
+		{0x0dd0, 0x0dd1, 1},
+		{0x0dd8, 0x0ddf, 1},
+		{0x0df2, 0x0df3, 1},
+		{0x0f3e, 0x0f3f, 1},
+		{0x0f7f, 0x102b, 172},
+		{0x102c, 0x1031, 5},
+		{0x1038, 0x103b, 3},
+		{0x103c, 0x1056, 26},
+		{0x1057, 0x1062, 11},
+		{0x1063, 0x1064, 1},
+		{0x1067, 0x106d, 1},
+		{0x1083, 0x1084, 1},
+		{0x1087, 0x108c, 1},
+		{0x108f, 0x109a, 11},
+		{0x109b, 0x109c, 1},
+		{0x17b6, 0x17be, 8},
+		{0x17bf, 0x17c5, 1},
+		{0x17c7, 0x17c8, 1},
+		{0x1923, 0x1926, 1},
+		{0x1929, 0x192b, 1},
+		{0x1930, 0x1931, 1},
+		{0x1933, 0x1938, 1},
+		{0x19b0, 0x19c0, 1},
+		{0x19c8, 0x19c9, 1},
+		{0x1a19, 0x1a1a, 1},
+		{0x1a55, 0x1a57, 2},
+		{0x1a61, 0x1a63, 2},
+		{0x1a64, 0x1a6d, 9},
+		{0x1a6e, 0x1a72, 1},
+		{0x1b04, 0x1b35, 49},
+		{0x1b3b, 0x1b3d, 2},
+		{0x1b3e, 0x1b41, 1},
+		{0x1b43, 0x1b44, 1},
+		{0x1b82, 0x1ba1, 31},
+		{0x1ba6, 0x1ba7, 1},
+		{0x1baa, 0x1bac, 2},
+		{0x1bad, 0x1be7, 58},
+		{0x1bea, 0x1bec, 1},
+		{0x1bee, 0x1bf2, 4},
+		{0x1bf3, 0x1c24, 49},
+		{0x1c25, 0x1c2b, 1},
+		{0x1c34, 0x1c35, 1},
+		{0x1ce1, 0x1cf2, 17},
+		{0x1cf3, 0x302e, 4923},
+		{0x302f, 0xa823, 30708},
+		{0xa824, 0xa827, 3},
+		{0xa880, 0xa881, 1},
+		{0xa8b4, 0xa8c3, 1},
+		{0xa952, 0xa953, 1},
+		{0xa983, 0xa9b4, 49},
+		{0xa9b5, 0xa9ba, 5},
+		{0xa9bb, 0xa9bd, 2},
+		{0xa9be, 0xa9c0, 1},
+		{0xaa2f, 0xaa30, 1},
+		{0xaa33, 0xaa34, 1},
+		{0xaa4d, 0xaa7b, 46},
+		{0xaaeb, 0xaaee, 3},
+		{0xaaef, 0xaaf5, 6},
+		{0xabe3, 0xabe4, 1},
+		{0xabe6, 0xabe7, 1},
+		{0xabe9, 0xabea, 1},
+		{0xabec, 0xabec, 1},
+	},
+	R32: []Range32{
+		{0x11000, 0x11000, 1},
+		{0x11002, 0x11082, 128},
+		{0x110b0, 0x110b2, 1},
+		{0x110b7, 0x110b8, 1},
+		{0x1112c, 0x11182, 86},
+		{0x111b3, 0x111b5, 1},
+		{0x111bf, 0x111c0, 1},
+		{0x116ac, 0x116ae, 2},
+		{0x116af, 0x116b6, 7},
+		{0x16f51, 0x16f7e, 1},
+		{0x1d165, 0x1d166, 1},
+		{0x1d16d, 0x1d172, 1},
+	},
+}
+
+var _Me = &RangeTable{
+	R16: []Range16{
+		{0x0488, 0x0489, 1},
+		{0x20dd, 0x20e0, 1},
+		{0x20e2, 0x20e4, 1},
+		{0xa670, 0xa672, 1},
+	},
+}
+
+var _Mn = &RangeTable{
+	R16: []Range16{
+		{0x0300, 0x036f, 1},
+		{0x0483, 0x0487, 1},
+		{0x0591, 0x05bd, 1},
+		{0x05bf, 0x05c1, 2},
+		{0x05c2, 0x05c4, 2},
+		{0x05c5, 0x05c7, 2},
+		{0x0610, 0x061a, 1},
+		{0x064b, 0x065f, 1},
+		{0x0670, 0x06d6, 102},
+		{0x06d7, 0x06dc, 1},
+		{0x06df, 0x06e4, 1},
+		{0x06e7, 0x06e8, 1},
+		{0x06ea, 0x06ed, 1},
+		{0x0711, 0x0730, 31},
+		{0x0731, 0x074a, 1},
+		{0x07a6, 0x07b0, 1},
+		{0x07eb, 0x07f3, 1},
+		{0x0816, 0x0819, 1},
+		{0x081b, 0x0823, 1},
+		{0x0825, 0x0827, 1},
+		{0x0829, 0x082d, 1},
+		{0x0859, 0x085b, 1},
+		{0x08e4, 0x08fe, 1},
+		{0x0900, 0x0902, 1},
+		{0x093a, 0x093c, 2},
+		{0x0941, 0x0948, 1},
+		{0x094d, 0x0951, 4},
+		{0x0952, 0x0957, 1},
+		{0x0962, 0x0963, 1},
+		{0x0981, 0x09bc, 59},
+		{0x09c1, 0x09c4, 1},
+		{0x09cd, 0x09e2, 21},
+		{0x09e3, 0x0a01, 30},
+		{0x0a02, 0x0a3c, 58},
+		{0x0a41, 0x0a42, 1},
+		{0x0a47, 0x0a48, 1},
+		{0x0a4b, 0x0a4d, 1},
+		{0x0a51, 0x0a70, 31},
+		{0x0a71, 0x0a75, 4},
+		{0x0a81, 0x0a82, 1},
+		{0x0abc, 0x0ac1, 5},
+		{0x0ac2, 0x0ac5, 1},
+		{0x0ac7, 0x0ac8, 1},
+		{0x0acd, 0x0ae2, 21},
+		{0x0ae3, 0x0b01, 30},
+		{0x0b3c, 0x0b3f, 3},
+		{0x0b41, 0x0b44, 1},
+		{0x0b4d, 0x0b56, 9},
+		{0x0b62, 0x0b63, 1},
+		{0x0b82, 0x0bc0, 62},
+		{0x0bcd, 0x0c3e, 113},
+		{0x0c3f, 0x0c40, 1},
+		{0x0c46, 0x0c48, 1},
+		{0x0c4a, 0x0c4d, 1},
+		{0x0c55, 0x0c56, 1},
+		{0x0c62, 0x0c63, 1},
+		{0x0cbc, 0x0cbf, 3},
+		{0x0cc6, 0x0ccc, 6},
+		{0x0ccd, 0x0ce2, 21},
+		{0x0ce3, 0x0d41, 94},
+		{0x0d42, 0x0d44, 1},
+		{0x0d4d, 0x0d62, 21},
+		{0x0d63, 0x0dca, 103},
+		{0x0dd2, 0x0dd4, 1},
+		{0x0dd6, 0x0e31, 91},
+		{0x0e34, 0x0e3a, 1},
+		{0x0e47, 0x0e4e, 1},
+		{0x0eb1, 0x0eb4, 3},
+		{0x0eb5, 0x0eb9, 1},
+		{0x0ebb, 0x0ebc, 1},
+		{0x0ec8, 0x0ecd, 1},
+		{0x0f18, 0x0f19, 1},
+		{0x0f35, 0x0f39, 2},
+		{0x0f71, 0x0f7e, 1},
+		{0x0f80, 0x0f84, 1},
+		{0x0f86, 0x0f87, 1},
+		{0x0f8d, 0x0f97, 1},
+		{0x0f99, 0x0fbc, 1},
+		{0x0fc6, 0x102d, 103},
+		{0x102e, 0x1030, 1},
+		{0x1032, 0x1037, 1},
+		{0x1039, 0x103a, 1},
+		{0x103d, 0x103e, 1},
+		{0x1058, 0x1059, 1},
+		{0x105e, 0x1060, 1},
+		{0x1071, 0x1074, 1},
+		{0x1082, 0x1085, 3},
+		{0x1086, 0x108d, 7},
+		{0x109d, 0x135d, 704},
+		{0x135e, 0x135f, 1},
+		{0x1712, 0x1714, 1},
+		{0x1732, 0x1734, 1},
+		{0x1752, 0x1753, 1},
+		{0x1772, 0x1773, 1},
+		{0x17b4, 0x17b5, 1},
+		{0x17b7, 0x17bd, 1},
+		{0x17c6, 0x17c9, 3},
+		{0x17ca, 0x17d3, 1},
+		{0x17dd, 0x180b, 46},
+		{0x180c, 0x180d, 1},
+		{0x18a9, 0x1920, 119},
+		{0x1921, 0x1922, 1},
+		{0x1927, 0x1928, 1},
+		{0x1932, 0x1939, 7},
+		{0x193a, 0x193b, 1},
+		{0x1a17, 0x1a18, 1},
+		{0x1a1b, 0x1a56, 59},
+		{0x1a58, 0x1a5e, 1},
+		{0x1a60, 0x1a62, 2},
+		{0x1a65, 0x1a6c, 1},
+		{0x1a73, 0x1a7c, 1},
+		{0x1a7f, 0x1b00, 129},
+		{0x1b01, 0x1b03, 1},
+		{0x1b34, 0x1b36, 2},
+		{0x1b37, 0x1b3a, 1},
+		{0x1b3c, 0x1b42, 6},
+		{0x1b6b, 0x1b73, 1},
+		{0x1b80, 0x1b81, 1},
+		{0x1ba2, 0x1ba5, 1},
+		{0x1ba8, 0x1ba9, 1},
+		{0x1bab, 0x1be6, 59},
+		{0x1be8, 0x1be9, 1},
+		{0x1bed, 0x1bef, 2},
+		{0x1bf0, 0x1bf1, 1},
+		{0x1c2c, 0x1c33, 1},
+		{0x1c36, 0x1c37, 1},
+		{0x1cd0, 0x1cd2, 1},
+		{0x1cd4, 0x1ce0, 1},
+		{0x1ce2, 0x1ce8, 1},
+		{0x1ced, 0x1cf4, 7},
+		{0x1dc0, 0x1de6, 1},
+		{0x1dfc, 0x1dff, 1},
+		{0x20d0, 0x20dc, 1},
+		{0x20e1, 0x20e5, 4},
+		{0x20e6, 0x20f0, 1},
+		{0x2cef, 0x2cf1, 1},
+		{0x2d7f, 0x2de0, 97},
+		{0x2de1, 0x2dff, 1},
+		{0x302a, 0x302d, 1},
+		{0x3099, 0x309a, 1},
+		{0xa66f, 0xa674, 5},
+		{0xa675, 0xa67d, 1},
+		{0xa69f, 0xa6f0, 81},
+		{0xa6f1, 0xa802, 273},
+		{0xa806, 0xa80b, 5},
+		{0xa825, 0xa826, 1},
+		{0xa8c4, 0xa8e0, 28},
+		{0xa8e1, 0xa8f1, 1},
+		{0xa926, 0xa92d, 1},
+		{0xa947, 0xa951, 1},
+		{0xa980, 0xa982, 1},
+		{0xa9b3, 0xa9b6, 3},
+		{0xa9b7, 0xa9b9, 1},
+		{0xa9bc, 0xaa29, 109},
+		{0xaa2a, 0xaa2e, 1},
+		{0xaa31, 0xaa32, 1},
+		{0xaa35, 0xaa36, 1},
+		{0xaa43, 0xaa4c, 9},
+		{0xaab0, 0xaab2, 2},
+		{0xaab3, 0xaab4, 1},
+		{0xaab7, 0xaab8, 1},
+		{0xaabe, 0xaabf, 1},
+		{0xaac1, 0xaaec, 43},
+		{0xaaed, 0xaaf6, 9},
+		{0xabe5, 0xabe8, 3},
+		{0xabed, 0xfb1e, 20273},
+		{0xfe00, 0xfe0f, 1},
+		{0xfe20, 0xfe26, 1},
+	},
+	R32: []Range32{
+		{0x101fd, 0x10a01, 2052},
+		{0x10a02, 0x10a03, 1},
+		{0x10a05, 0x10a06, 1},
+		{0x10a0c, 0x10a0f, 1},
+		{0x10a38, 0x10a3a, 1},
+		{0x10a3f, 0x11001, 1474},
+		{0x11038, 0x11046, 1},
+		{0x11080, 0x11081, 1},
+		{0x110b3, 0x110b6, 1},
+		{0x110b9, 0x110ba, 1},
+		{0x11100, 0x11102, 1},
+		{0x11127, 0x1112b, 1},
+		{0x1112d, 0x11134, 1},
+		{0x11180, 0x11181, 1},
+		{0x111b6, 0x111be, 1},
+		{0x116ab, 0x116ad, 2},
+		{0x116b0, 0x116b5, 1},
+		{0x116b7, 0x16f8f, 22744},
+		{0x16f90, 0x16f92, 1},
+		{0x1d167, 0x1d169, 1},
+		{0x1d17b, 0x1d182, 1},
+		{0x1d185, 0x1d18b, 1},
+		{0x1d1aa, 0x1d1ad, 1},
+		{0x1d242, 0x1d244, 1},
+		{0xe0100, 0xe01ef, 1},
+	},
+}
+
+var _N = &RangeTable{
+	R16: []Range16{
+		{0x0030, 0x0039, 1},
+		{0x00b2, 0x00b3, 1},
+		{0x00b9, 0x00bc, 3},
+		{0x00bd, 0x00be, 1},
+		{0x0660, 0x0669, 1},
+		{0x06f0, 0x06f9, 1},
+		{0x07c0, 0x07c9, 1},
+		{0x0966, 0x096f, 1},
+		{0x09e6, 0x09ef, 1},
+		{0x09f4, 0x09f9, 1},
+		{0x0a66, 0x0a6f, 1},
+		{0x0ae6, 0x0aef, 1},
+		{0x0b66, 0x0b6f, 1},
+		{0x0b72, 0x0b77, 1},
+		{0x0be6, 0x0bf2, 1},
+		{0x0c66, 0x0c6f, 1},
+		{0x0c78, 0x0c7e, 1},
+		{0x0ce6, 0x0cef, 1},
+		{0x0d66, 0x0d75, 1},
+		{0x0e50, 0x0e59, 1},
+		{0x0ed0, 0x0ed9, 1},
+		{0x0f20, 0x0f33, 1},
+		{0x1040, 0x1049, 1},
+		{0x1090, 0x1099, 1},
+		{0x1369, 0x137c, 1},
+		{0x16ee, 0x16f0, 1},
+		{0x17e0, 0x17e9, 1},
+		{0x17f0, 0x17f9, 1},
+		{0x1810, 0x1819, 1},
+		{0x1946, 0x194f, 1},
+		{0x19d0, 0x19da, 1},
+		{0x1a80, 0x1a89, 1},
+		{0x1a90, 0x1a99, 1},
+		{0x1b50, 0x1b59, 1},
+		{0x1bb0, 0x1bb9, 1},
+		{0x1c40, 0x1c49, 1},
+		{0x1c50, 0x1c59, 1},
+		{0x2070, 0x2074, 4},
+		{0x2075, 0x2079, 1},
+		{0x2080, 0x2089, 1},
+		{0x2150, 0x2182, 1},
+		{0x2185, 0x2189, 1},
+		{0x2460, 0x249b, 1},
+		{0x24ea, 0x24ff, 1},
+		{0x2776, 0x2793, 1},
+		{0x2cfd, 0x3007, 778},
+		{0x3021, 0x3029, 1},
+		{0x3038, 0x303a, 1},
+		{0x3192, 0x3195, 1},
+		{0x3220, 0x3229, 1},
+		{0x3248, 0x324f, 1},
+		{0x3251, 0x325f, 1},
+		{0x3280, 0x3289, 1},
+		{0x32b1, 0x32bf, 1},
+		{0xa620, 0xa629, 1},
+		{0xa6e6, 0xa6ef, 1},
+		{0xa830, 0xa835, 1},
+		{0xa8d0, 0xa8d9, 1},
+		{0xa900, 0xa909, 1},
+		{0xa9d0, 0xa9d9, 1},
+		{0xaa50, 0xaa59, 1},
+		{0xabf0, 0xabf9, 1},
+		{0xff10, 0xff19, 1},
+	},
+	R32: []Range32{
+		{0x10107, 0x10133, 1},
+		{0x10140, 0x10178, 1},
+		{0x1018a, 0x10320, 406},
+		{0x10321, 0x10323, 1},
+		{0x10341, 0x1034a, 9},
+		{0x103d1, 0x103d5, 1},
+		{0x104a0, 0x104a9, 1},
+		{0x10858, 0x1085f, 1},
+		{0x10916, 0x1091b, 1},
+		{0x10a40, 0x10a47, 1},
+		{0x10a7d, 0x10a7e, 1},
+		{0x10b58, 0x10b5f, 1},
+		{0x10b78, 0x10b7f, 1},
+		{0x10e60, 0x10e7e, 1},
+		{0x11052, 0x1106f, 1},
+		{0x110f0, 0x110f9, 1},
+		{0x11136, 0x1113f, 1},
+		{0x111d0, 0x111d9, 1},
+		{0x116c0, 0x116c9, 1},
+		{0x12400, 0x12462, 1},
+		{0x1d360, 0x1d371, 1},
+		{0x1d7ce, 0x1d7ff, 1},
+		{0x1f100, 0x1f10a, 1},
+	},
+	LatinOffset: 4,
+}
+
+var _Nd = &RangeTable{
+	R16: []Range16{
+		{0x0030, 0x0039, 1},
+		{0x0660, 0x0669, 1},
+		{0x06f0, 0x06f9, 1},
+		{0x07c0, 0x07c9, 1},
+		{0x0966, 0x096f, 1},
+		{0x09e6, 0x09ef, 1},
+		{0x0a66, 0x0a6f, 1},
+		{0x0ae6, 0x0aef, 1},
+		{0x0b66, 0x0b6f, 1},
+		{0x0be6, 0x0bef, 1},
+		{0x0c66, 0x0c6f, 1},
+		{0x0ce6, 0x0cef, 1},
+		{0x0d66, 0x0d6f, 1},
+		{0x0e50, 0x0e59, 1},
+		{0x0ed0, 0x0ed9, 1},
+		{0x0f20, 0x0f29, 1},
+		{0x1040, 0x1049, 1},
+		{0x1090, 0x1099, 1},
+		{0x17e0, 0x17e9, 1},
+		{0x1810, 0x1819, 1},
+		{0x1946, 0x194f, 1},
+		{0x19d0, 0x19d9, 1},
+		{0x1a80, 0x1a89, 1},
+		{0x1a90, 0x1a99, 1},
+		{0x1b50, 0x1b59, 1},
+		{0x1bb0, 0x1bb9, 1},
+		{0x1c40, 0x1c49, 1},
+		{0x1c50, 0x1c59, 1},
+		{0xa620, 0xa629, 1},
+		{0xa8d0, 0xa8d9, 1},
+		{0xa900, 0xa909, 1},
+		{0xa9d0, 0xa9d9, 1},
+		{0xaa50, 0xaa59, 1},
+		{0xabf0, 0xabf9, 1},
+		{0xff10, 0xff19, 1},
+	},
+	R32: []Range32{
+		{0x104a0, 0x104a9, 1},
+		{0x11066, 0x1106f, 1},
+		{0x110f0, 0x110f9, 1},
+		{0x11136, 0x1113f, 1},
+		{0x111d0, 0x111d9, 1},
+		{0x116c0, 0x116c9, 1},
+		{0x1d7ce, 0x1d7ff, 1},
+	},
+	LatinOffset: 1,
+}
+
+var _Nl = &RangeTable{
+	R16: []Range16{
+		{0x16ee, 0x16f0, 1},
+		{0x2160, 0x2182, 1},
+		{0x2185, 0x2188, 1},
+		{0x3007, 0x3021, 26},
+		{0x3022, 0x3029, 1},
+		{0x3038, 0x303a, 1},
+		{0xa6e6, 0xa6ef, 1},
+	},
+	R32: []Range32{
+		{0x10140, 0x10174, 1},
+		{0x10341, 0x1034a, 9},
+		{0x103d1, 0x103d5, 1},
+		{0x12400, 0x12462, 1},
+	},
+}
+
+var _No = &RangeTable{
+	R16: []Range16{
+		{0x00b2, 0x00b3, 1},
+		{0x00b9, 0x00bc, 3},
+		{0x00bd, 0x00be, 1},
+		{0x09f4, 0x09f9, 1},
+		{0x0b72, 0x0b77, 1},
+		{0x0bf0, 0x0bf2, 1},
+		{0x0c78, 0x0c7e, 1},
+		{0x0d70, 0x0d75, 1},
+		{0x0f2a, 0x0f33, 1},
+		{0x1369, 0x137c, 1},
+		{0x17f0, 0x17f9, 1},
+		{0x19da, 0x2070, 1686},
+		{0x2074, 0x2079, 1},
+		{0x2080, 0x2089, 1},
+		{0x2150, 0x215f, 1},
+		{0x2189, 0x2460, 727},
+		{0x2461, 0x249b, 1},
+		{0x24ea, 0x24ff, 1},
+		{0x2776, 0x2793, 1},
+		{0x2cfd, 0x3192, 1173},
+		{0x3193, 0x3195, 1},
+		{0x3220, 0x3229, 1},
+		{0x3248, 0x324f, 1},
+		{0x3251, 0x325f, 1},
+		{0x3280, 0x3289, 1},
+		{0x32b1, 0x32bf, 1},
+		{0xa830, 0xa835, 1},
+	},
+	R32: []Range32{
+		{0x10107, 0x10133, 1},
+		{0x10175, 0x10178, 1},
+		{0x1018a, 0x10320, 406},
+		{0x10321, 0x10323, 1},
+		{0x10858, 0x1085f, 1},
+		{0x10916, 0x1091b, 1},
+		{0x10a40, 0x10a47, 1},
+		{0x10a7d, 0x10a7e, 1},
+		{0x10b58, 0x10b5f, 1},
+		{0x10b78, 0x10b7f, 1},
+		{0x10e60, 0x10e7e, 1},
+		{0x11052, 0x11065, 1},
+		{0x1d360, 0x1d371, 1},
+		{0x1f100, 0x1f10a, 1},
+	},
+	LatinOffset: 3,
+}
+
+var _P = &RangeTable{
+	R16: []Range16{
+		{0x0021, 0x0023, 1},
+		{0x0025, 0x002a, 1},
+		{0x002c, 0x002f, 1},
+		{0x003a, 0x003b, 1},
+		{0x003f, 0x0040, 1},
+		{0x005b, 0x005d, 1},
+		{0x005f, 0x007b, 28},
+		{0x007d, 0x00a1, 36},
+		{0x00a7, 0x00ab, 4},
+		{0x00b6, 0x00b7, 1},
+		{0x00bb, 0x00bf, 4},
+		{0x037e, 0x0387, 9},
+		{0x055a, 0x055f, 1},
+		{0x0589, 0x058a, 1},
+		{0x05be, 0x05c0, 2},
+		{0x05c3, 0x05c6, 3},
+		{0x05f3, 0x05f4, 1},
+		{0x0609, 0x060a, 1},
+		{0x060c, 0x060d, 1},
+		{0x061b, 0x061e, 3},
+		{0x061f, 0x066a, 75},
+		{0x066b, 0x066d, 1},
+		{0x06d4, 0x0700, 44},
+		{0x0701, 0x070d, 1},
+		{0x07f7, 0x07f9, 1},
+		{0x0830, 0x083e, 1},
+		{0x085e, 0x0964, 262},
+		{0x0965, 0x0970, 11},
+		{0x0af0, 0x0df4, 772},
+		{0x0e4f, 0x0e5a, 11},
+		{0x0e5b, 0x0f04, 169},
+		{0x0f05, 0x0f12, 1},
+		{0x0f14, 0x0f3a, 38},
+		{0x0f3b, 0x0f3d, 1},
+		{0x0f85, 0x0fd0, 75},
+		{0x0fd1, 0x0fd4, 1},
+		{0x0fd9, 0x0fda, 1},
+		{0x104a, 0x104f, 1},
+		{0x10fb, 0x1360, 613},
+		{0x1361, 0x1368, 1},
+		{0x1400, 0x166d, 621},
+		{0x166e, 0x169b, 45},
+		{0x169c, 0x16eb, 79},
+		{0x16ec, 0x16ed, 1},
+		{0x1735, 0x1736, 1},
+		{0x17d4, 0x17d6, 1},
+		{0x17d8, 0x17da, 1},
+		{0x1800, 0x180a, 1},
+		{0x1944, 0x1945, 1},
+		{0x1a1e, 0x1a1f, 1},
+		{0x1aa0, 0x1aa6, 1},
+		{0x1aa8, 0x1aad, 1},
+		{0x1b5a, 0x1b60, 1},
+		{0x1bfc, 0x1bff, 1},
+		{0x1c3b, 0x1c3f, 1},
+		{0x1c7e, 0x1c7f, 1},
+		{0x1cc0, 0x1cc7, 1},
+		{0x1cd3, 0x2010, 829},
+		{0x2011, 0x2027, 1},
+		{0x2030, 0x2043, 1},
+		{0x2045, 0x2051, 1},
+		{0x2053, 0x205e, 1},
+		{0x207d, 0x207e, 1},
+		{0x208d, 0x208e, 1},
+		{0x2308, 0x230b, 1},
+		{0x2329, 0x232a, 1},
+		{0x2768, 0x2775, 1},
+		{0x27c5, 0x27c6, 1},
+		{0x27e6, 0x27ef, 1},
+		{0x2983, 0x2998, 1},
+		{0x29d8, 0x29db, 1},
+		{0x29fc, 0x29fd, 1},
+		{0x2cf9, 0x2cfc, 1},
+		{0x2cfe, 0x2cff, 1},
+		{0x2d70, 0x2e00, 144},
+		{0x2e01, 0x2e2e, 1},
+		{0x2e30, 0x2e3b, 1},
+		{0x3001, 0x3003, 1},
+		{0x3008, 0x3011, 1},
+		{0x3014, 0x301f, 1},
+		{0x3030, 0x303d, 13},
+		{0x30a0, 0x30fb, 91},
+		{0xa4fe, 0xa4ff, 1},
+		{0xa60d, 0xa60f, 1},
+		{0xa673, 0xa67e, 11},
+		{0xa6f2, 0xa6f7, 1},
+		{0xa874, 0xa877, 1},
+		{0xa8ce, 0xa8cf, 1},
+		{0xa8f8, 0xa8fa, 1},
+		{0xa92e, 0xa92f, 1},
+		{0xa95f, 0xa9c1, 98},
+		{0xa9c2, 0xa9cd, 1},
+		{0xa9de, 0xa9df, 1},
+		{0xaa5c, 0xaa5f, 1},
+		{0xaade, 0xaadf, 1},
+		{0xaaf0, 0xaaf1, 1},
+		{0xabeb, 0xfd3e, 20819},
+		{0xfd3f, 0xfe10, 209},
+		{0xfe11, 0xfe19, 1},
+		{0xfe30, 0xfe52, 1},
+		{0xfe54, 0xfe61, 1},
+		{0xfe63, 0xfe68, 5},
+		{0xfe6a, 0xfe6b, 1},
+		{0xff01, 0xff03, 1},
+		{0xff05, 0xff0a, 1},
+		{0xff0c, 0xff0f, 1},
+		{0xff1a, 0xff1b, 1},
+		{0xff1f, 0xff20, 1},
+		{0xff3b, 0xff3d, 1},
+		{0xff3f, 0xff5b, 28},
+		{0xff5d, 0xff5f, 2},
+		{0xff60, 0xff65, 1},
+	},
+	R32: []Range32{
+		{0x10100, 0x10102, 1},
+		{0x1039f, 0x103d0, 49},
+		{0x10857, 0x1091f, 200},
+		{0x1093f, 0x10a50, 273},
+		{0x10a51, 0x10a58, 1},
+		{0x10a7f, 0x10b39, 186},
+		{0x10b3a, 0x10b3f, 1},
+		{0x11047, 0x1104d, 1},
+		{0x110bb, 0x110bc, 1},
+		{0x110be, 0x110c1, 1},
+		{0x11140, 0x11143, 1},
+		{0x111c5, 0x111c8, 1},
+		{0x12470, 0x12473, 1},
+	},
+	LatinOffset: 11,
+}
+
+var _Pc = &RangeTable{
+	R16: []Range16{
+		{0x005f, 0x203f, 8160},
+		{0x2040, 0x2054, 20},
+		{0xfe33, 0xfe34, 1},
+		{0xfe4d, 0xfe4f, 1},
+		{0xff3f, 0xff3f, 1},
+	},
+}
+
+var _Pd = &RangeTable{
+	R16: []Range16{
+		{0x002d, 0x058a, 1373},
+		{0x05be, 0x1400, 3650},
+		{0x1806, 0x2010, 2058},
+		{0x2011, 0x2015, 1},
+		{0x2e17, 0x2e1a, 3},
+		{0x2e3a, 0x2e3b, 1},
+		{0x301c, 0x3030, 20},
+		{0x30a0, 0xfe31, 52625},
+		{0xfe32, 0xfe58, 38},
+		{0xfe63, 0xff0d, 170},
+	},
+}
+
+var _Pe = &RangeTable{
+	R16: []Range16{
+		{0x0029, 0x005d, 52},
+		{0x007d, 0x0f3b, 3774},
+		{0x0f3d, 0x169c, 1887},
+		{0x2046, 0x207e, 56},
+		{0x208e, 0x2309, 635},
+		{0x230b, 0x232a, 31},
+		{0x2769, 0x2775, 2},
+		{0x27c6, 0x27e7, 33},
+		{0x27e9, 0x27ef, 2},
+		{0x2984, 0x2998, 2},
+		{0x29d9, 0x29db, 2},
+		{0x29fd, 0x2e23, 1062},
+		{0x2e25, 0x2e29, 2},
+		{0x3009, 0x3011, 2},
+		{0x3015, 0x301b, 2},
+		{0x301e, 0x301f, 1},
+		{0xfd3f, 0xfe18, 217},
+		{0xfe36, 0xfe44, 2},
+		{0xfe48, 0xfe5a, 18},
+		{0xfe5c, 0xfe5e, 2},
+		{0xff09, 0xff3d, 52},
+		{0xff5d, 0xff63, 3},
+	},
+	LatinOffset: 1,
+}
+
+var _Pf = &RangeTable{
+	R16: []Range16{
+		{0x00bb, 0x2019, 8030},
+		{0x201d, 0x203a, 29},
+		{0x2e03, 0x2e05, 2},
+		{0x2e0a, 0x2e0d, 3},
+		{0x2e1d, 0x2e21, 4},
+	},
+}
+
+var _Pi = &RangeTable{
+	R16: []Range16{
+		{0x00ab, 0x2018, 8045},
+		{0x201b, 0x201c, 1},
+		{0x201f, 0x2039, 26},
+		{0x2e02, 0x2e04, 2},
+		{0x2e09, 0x2e0c, 3},
+		{0x2e1c, 0x2e20, 4},
+	},
+}
+
+var _Po = &RangeTable{
+	R16: []Range16{
+		{0x0021, 0x0023, 1},
+		{0x0025, 0x0027, 1},
+		{0x002a, 0x002e, 2},
+		{0x002f, 0x003a, 11},
+		{0x003b, 0x003f, 4},
+		{0x0040, 0x005c, 28},
+		{0x00a1, 0x00a7, 6},
+		{0x00b6, 0x00b7, 1},
+		{0x00bf, 0x037e, 703},
+		{0x0387, 0x055a, 467},
+		{0x055b, 0x055f, 1},
+		{0x0589, 0x05c0, 55},
+		{0x05c3, 0x05c6, 3},
+		{0x05f3, 0x05f4, 1},
+		{0x0609, 0x060a, 1},
+		{0x060c, 0x060d, 1},
+		{0x061b, 0x061e, 3},
+		{0x061f, 0x066a, 75},
+		{0x066b, 0x066d, 1},
+		{0x06d4, 0x0700, 44},
+		{0x0701, 0x070d, 1},
+		{0x07f7, 0x07f9, 1},
+		{0x0830, 0x083e, 1},
+		{0x085e, 0x0964, 262},
+		{0x0965, 0x0970, 11},
+		{0x0af0, 0x0df4, 772},
+		{0x0e4f, 0x0e5a, 11},
+		{0x0e5b, 0x0f04, 169},
+		{0x0f05, 0x0f12, 1},
+		{0x0f14, 0x0f85, 113},
+		{0x0fd0, 0x0fd4, 1},
+		{0x0fd9, 0x0fda, 1},
+		{0x104a, 0x104f, 1},
+		{0x10fb, 0x1360, 613},
+		{0x1361, 0x1368, 1},
+		{0x166d, 0x166e, 1},
+		{0x16eb, 0x16ed, 1},
+		{0x1735, 0x1736, 1},
+		{0x17d4, 0x17d6, 1},
+		{0x17d8, 0x17da, 1},
+		{0x1800, 0x1805, 1},
+		{0x1807, 0x180a, 1},
+		{0x1944, 0x1945, 1},
+		{0x1a1e, 0x1a1f, 1},
+		{0x1aa0, 0x1aa6, 1},
+		{0x1aa8, 0x1aad, 1},
+		{0x1b5a, 0x1b60, 1},
+		{0x1bfc, 0x1bff, 1},
+		{0x1c3b, 0x1c3f, 1},
+		{0x1c7e, 0x1c7f, 1},
+		{0x1cc0, 0x1cc7, 1},
+		{0x1cd3, 0x2016, 835},
+		{0x2017, 0x2020, 9},
+		{0x2021, 0x2027, 1},
+		{0x2030, 0x2038, 1},
+		{0x203b, 0x203e, 1},
+		{0x2041, 0x2043, 1},
+		{0x2047, 0x2051, 1},
+		{0x2053, 0x2055, 2},
+		{0x2056, 0x205e, 1},
+		{0x2cf9, 0x2cfc, 1},
+		{0x2cfe, 0x2cff, 1},
+		{0x2d70, 0x2e00, 144},
+		{0x2e01, 0x2e06, 5},
+		{0x2e07, 0x2e08, 1},
+		{0x2e0b, 0x2e0e, 3},
+		{0x2e0f, 0x2e16, 1},
+		{0x2e18, 0x2e19, 1},
+		{0x2e1b, 0x2e1e, 3},
+		{0x2e1f, 0x2e2a, 11},
+		{0x2e2b, 0x2e2e, 1},
+		{0x2e30, 0x2e39, 1},
+		{0x3001, 0x3003, 1},
+		{0x303d, 0x30fb, 190},
+		{0xa4fe, 0xa4ff, 1},
+		{0xa60d, 0xa60f, 1},
+		{0xa673, 0xa67e, 11},
+		{0xa6f2, 0xa6f7, 1},
+		{0xa874, 0xa877, 1},
+		{0xa8ce, 0xa8cf, 1},
+		{0xa8f8, 0xa8fa, 1},
+		{0xa92e, 0xa92f, 1},
+		{0xa95f, 0xa9c1, 98},
+		{0xa9c2, 0xa9cd, 1},
+		{0xa9de, 0xa9df, 1},
+		{0xaa5c, 0xaa5f, 1},
+		{0xaade, 0xaadf, 1},
+		{0xaaf0, 0xaaf1, 1},
+		{0xabeb, 0xfe10, 21029},
+		{0xfe11, 0xfe16, 1},
+		{0xfe19, 0xfe30, 23},
+		{0xfe45, 0xfe46, 1},
+		{0xfe49, 0xfe4c, 1},
+		{0xfe50, 0xfe52, 1},
+		{0xfe54, 0xfe57, 1},
+		{0xfe5f, 0xfe61, 1},
+		{0xfe68, 0xfe6a, 2},
+		{0xfe6b, 0xff01, 150},
+		{0xff02, 0xff03, 1},
+		{0xff05, 0xff07, 1},
+		{0xff0a, 0xff0e, 2},
+		{0xff0f, 0xff1a, 11},
+		{0xff1b, 0xff1f, 4},
+		{0xff20, 0xff3c, 28},
+		{0xff61, 0xff64, 3},
+		{0xff65, 0xff65, 1},
+	},
+	R32: []Range32{
+		{0x10100, 0x10100, 1},
+		{0x10101, 0x10102, 1},
+		{0x1039f, 0x103d0, 49},
+		{0x10857, 0x1091f, 200},
+		{0x1093f, 0x10a50, 273},
+		{0x10a51, 0x10a58, 1},
+		{0x10a7f, 0x10b39, 186},
+		{0x10b3a, 0x10b3f, 1},
+		{0x11047, 0x1104d, 1},
+		{0x110bb, 0x110bc, 1},
+		{0x110be, 0x110c1, 1},
+		{0x11140, 0x11143, 1},
+		{0x111c5, 0x111c8, 1},
+		{0x12470, 0x12473, 1},
+	},
+	LatinOffset: 8,
+}
+
+var _Ps = &RangeTable{
+	R16: []Range16{
+		{0x0028, 0x005b, 51},
+		{0x007b, 0x0f3a, 3775},
+		{0x0f3c, 0x169b, 1887},
+		{0x201a, 0x201e, 4},
+		{0x2045, 0x207d, 56},
+		{0x208d, 0x2308, 635},
+		{0x230a, 0x2329, 31},
+		{0x2768, 0x2774, 2},
+		{0x27c5, 0x27e6, 33},
+		{0x27e8, 0x27ee, 2},
+		{0x2983, 0x2997, 2},
+		{0x29d8, 0x29da, 2},
+		{0x29fc, 0x2e22, 1062},
+		{0x2e24, 0x2e28, 2},
+		{0x3008, 0x3010, 2},
+		{0x3014, 0x301a, 2},
+		{0x301d, 0xfd3e, 52513},
+		{0xfe17, 0xfe35, 30},
+		{0xfe37, 0xfe43, 2},
+		{0xfe47, 0xfe59, 18},
+		{0xfe5b, 0xfe5d, 2},
+		{0xff08, 0xff3b, 51},
+		{0xff5b, 0xff5f, 4},
+		{0xff62, 0xff62, 1},
+	},
+	LatinOffset: 1,
+}
+
+var _S = &RangeTable{
+	R16: []Range16{
+		{0x0024, 0x002b, 7},
+		{0x003c, 0x003e, 1},
+		{0x005e, 0x0060, 2},
+		{0x007c, 0x007e, 2},
+		{0x00a2, 0x00a6, 1},
+		{0x00a8, 0x00a9, 1},
+		{0x00ac, 0x00ae, 2},
+		{0x00af, 0x00b1, 1},
+		{0x00b4, 0x00b8, 4},
+		{0x00d7, 0x00f7, 32},
+		{0x02c2, 0x02c5, 1},
+		{0x02d2, 0x02df, 1},
+		{0x02e5, 0x02eb, 1},
+		{0x02ed, 0x02ef, 2},
+		{0x02f0, 0x02ff, 1},
+		{0x0375, 0x0384, 15},
+		{0x0385, 0x03f6, 113},
+		{0x0482, 0x058f, 269},
+		{0x0606, 0x0608, 1},
+		{0x060b, 0x060e, 3},
+		{0x060f, 0x06de, 207},
+		{0x06e9, 0x06fd, 20},
+		{0x06fe, 0x07f6, 248},
+		{0x09f2, 0x09f3, 1},
+		{0x09fa, 0x09fb, 1},
+		{0x0af1, 0x0b70, 127},
+		{0x0bf3, 0x0bfa, 1},
+		{0x0c7f, 0x0d79, 250},
+		{0x0e3f, 0x0f01, 194},
+		{0x0f02, 0x0f03, 1},
+		{0x0f13, 0x0f15, 2},
+		{0x0f16, 0x0f17, 1},
+		{0x0f1a, 0x0f1f, 1},
+		{0x0f34, 0x0f38, 2},
+		{0x0fbe, 0x0fc5, 1},
+		{0x0fc7, 0x0fcc, 1},
+		{0x0fce, 0x0fcf, 1},
+		{0x0fd5, 0x0fd8, 1},
+		{0x109e, 0x109f, 1},
+		{0x1390, 0x1399, 1},
+		{0x17db, 0x1940, 357},
+		{0x19de, 0x19ff, 1},
+		{0x1b61, 0x1b6a, 1},
+		{0x1b74, 0x1b7c, 1},
+		{0x1fbd, 0x1fbf, 2},
+		{0x1fc0, 0x1fc1, 1},
+		{0x1fcd, 0x1fcf, 1},
+		{0x1fdd, 0x1fdf, 1},
+		{0x1fed, 0x1fef, 1},
+		{0x1ffd, 0x1ffe, 1},
+		{0x2044, 0x2052, 14},
+		{0x207a, 0x207c, 1},
+		{0x208a, 0x208c, 1},
+		{0x20a0, 0x20ba, 1},
+		{0x2100, 0x2101, 1},
+		{0x2103, 0x2106, 1},
+		{0x2108, 0x2109, 1},
+		{0x2114, 0x2116, 2},
+		{0x2117, 0x2118, 1},
+		{0x211e, 0x2123, 1},
+		{0x2125, 0x2129, 2},
+		{0x212e, 0x213a, 12},
+		{0x213b, 0x2140, 5},
+		{0x2141, 0x2144, 1},
+		{0x214a, 0x214d, 1},
+		{0x214f, 0x2190, 65},
+		{0x2191, 0x2307, 1},
+		{0x230c, 0x2328, 1},
+		{0x232b, 0x23f3, 1},
+		{0x2400, 0x2426, 1},
+		{0x2440, 0x244a, 1},
+		{0x249c, 0x24e9, 1},
+		{0x2500, 0x26ff, 1},
+		{0x2701, 0x2767, 1},
+		{0x2794, 0x27c4, 1},
+		{0x27c7, 0x27e5, 1},
+		{0x27f0, 0x2982, 1},
+		{0x2999, 0x29d7, 1},
+		{0x29dc, 0x29fb, 1},
+		{0x29fe, 0x2b4c, 1},
+		{0x2b50, 0x2b59, 1},
+		{0x2ce5, 0x2cea, 1},
+		{0x2e80, 0x2e99, 1},
+		{0x2e9b, 0x2ef3, 1},
+		{0x2f00, 0x2fd5, 1},
+		{0x2ff0, 0x2ffb, 1},
+		{0x3004, 0x3012, 14},
+		{0x3013, 0x3020, 13},
+		{0x3036, 0x3037, 1},
+		{0x303e, 0x303f, 1},
+		{0x309b, 0x309c, 1},
+		{0x3190, 0x3191, 1},
+		{0x3196, 0x319f, 1},
+		{0x31c0, 0x31e3, 1},
+		{0x3200, 0x321e, 1},
+		{0x322a, 0x3247, 1},
+		{0x3250, 0x3260, 16},
+		{0x3261, 0x327f, 1},
+		{0x328a, 0x32b0, 1},
+		{0x32c0, 0x32fe, 1},
+		{0x3300, 0x33ff, 1},
+		{0x4dc0, 0x4dff, 1},
+		{0xa490, 0xa4c6, 1},
+		{0xa700, 0xa716, 1},
+		{0xa720, 0xa721, 1},
+		{0xa789, 0xa78a, 1},
+		{0xa828, 0xa82b, 1},
+		{0xa836, 0xa839, 1},
+		{0xaa77, 0xaa79, 1},
+		{0xfb29, 0xfbb2, 137},
+		{0xfbb3, 0xfbc1, 1},
+		{0xfdfc, 0xfdfd, 1},
+		{0xfe62, 0xfe64, 2},
+		{0xfe65, 0xfe66, 1},
+		{0xfe69, 0xff04, 155},
+		{0xff0b, 0xff1c, 17},
+		{0xff1d, 0xff1e, 1},
+		{0xff3e, 0xff40, 2},
+		{0xff5c, 0xff5e, 2},
+		{0xffe0, 0xffe6, 1},
+		{0xffe8, 0xffee, 1},
+		{0xfffc, 0xfffd, 1},
+	},
+	R32: []Range32{
+		{0x10137, 0x1013f, 1},
+		{0x10179, 0x10189, 1},
+		{0x10190, 0x1019b, 1},
+		{0x101d0, 0x101fc, 1},
+		{0x1d000, 0x1d0f5, 1},
+		{0x1d100, 0x1d126, 1},
+		{0x1d129, 0x1d164, 1},
+		{0x1d16a, 0x1d16c, 1},
+		{0x1d183, 0x1d184, 1},
+		{0x1d18c, 0x1d1a9, 1},
+		{0x1d1ae, 0x1d1dd, 1},
+		{0x1d200, 0x1d241, 1},
+		{0x1d245, 0x1d300, 187},
+		{0x1d301, 0x1d356, 1},
+		{0x1d6c1, 0x1d6db, 26},
+		{0x1d6fb, 0x1d715, 26},
+		{0x1d735, 0x1d74f, 26},
+		{0x1d76f, 0x1d789, 26},
+		{0x1d7a9, 0x1d7c3, 26},
+		{0x1eef0, 0x1eef1, 1},
+		{0x1f000, 0x1f02b, 1},
+		{0x1f030, 0x1f093, 1},
+		{0x1f0a0, 0x1f0ae, 1},
+		{0x1f0b1, 0x1f0be, 1},
+		{0x1f0c1, 0x1f0cf, 1},
+		{0x1f0d1, 0x1f0df, 1},
+		{0x1f110, 0x1f12e, 1},
+		{0x1f130, 0x1f16b, 1},
+		{0x1f170, 0x1f19a, 1},
+		{0x1f1e6, 0x1f202, 1},
+		{0x1f210, 0x1f23a, 1},
+		{0x1f240, 0x1f248, 1},
+		{0x1f250, 0x1f251, 1},
+		{0x1f300, 0x1f320, 1},
+		{0x1f330, 0x1f335, 1},
+		{0x1f337, 0x1f37c, 1},
+		{0x1f380, 0x1f393, 1},
+		{0x1f3a0, 0x1f3c4, 1},
+		{0x1f3c6, 0x1f3ca, 1},
+		{0x1f3e0, 0x1f3f0, 1},
+		{0x1f400, 0x1f43e, 1},
+		{0x1f440, 0x1f442, 2},
+		{0x1f443, 0x1f4f7, 1},
+		{0x1f4f9, 0x1f4fc, 1},
+		{0x1f500, 0x1f53d, 1},
+		{0x1f540, 0x1f543, 1},
+		{0x1f550, 0x1f567, 1},
+		{0x1f5fb, 0x1f640, 1},
+		{0x1f645, 0x1f64f, 1},
+		{0x1f680, 0x1f6c5, 1},
+		{0x1f700, 0x1f773, 1},
+	},
+	LatinOffset: 10,
+}
+
+var _Sc = &RangeTable{
+	R16: []Range16{
+		{0x0024, 0x00a2, 126},
+		{0x00a3, 0x00a5, 1},
+		{0x058f, 0x060b, 124},
+		{0x09f2, 0x09f3, 1},
+		{0x09fb, 0x0af1, 246},
+		{0x0bf9, 0x0e3f, 582},
+		{0x17db, 0x20a0, 2245},
+		{0x20a1, 0x20ba, 1},
+		{0xa838, 0xfdfc, 21956},
+		{0xfe69, 0xff04, 155},
+		{0xffe0, 0xffe1, 1},
+		{0xffe5, 0xffe6, 1},
+	},
+	LatinOffset: 2,
+}
+
+var _Sk = &RangeTable{
+	R16: []Range16{
+		{0x005e, 0x0060, 2},
+		{0x00a8, 0x00af, 7},
+		{0x00b4, 0x00b8, 4},
+		{0x02c2, 0x02c5, 1},
+		{0x02d2, 0x02df, 1},
+		{0x02e5, 0x02eb, 1},
+		{0x02ed, 0x02ef, 2},
+		{0x02f0, 0x02ff, 1},
+		{0x0375, 0x0384, 15},
+		{0x0385, 0x1fbd, 7224},
+		{0x1fbf, 0x1fc1, 1},
+		{0x1fcd, 0x1fcf, 1},
+		{0x1fdd, 0x1fdf, 1},
+		{0x1fed, 0x1fef, 1},
+		{0x1ffd, 0x1ffe, 1},
+		{0x309b, 0x309c, 1},
+		{0xa700, 0xa716, 1},
+		{0xa720, 0xa721, 1},
+		{0xa789, 0xa78a, 1},
+		{0xfbb2, 0xfbc1, 1},
+		{0xff3e, 0xff40, 2},
+		{0xffe3, 0xffe3, 1},
+	},
+	LatinOffset: 3,
+}
+
+var _Sm = &RangeTable{
+	R16: []Range16{
+		{0x002b, 0x003c, 17},
+		{0x003d, 0x003e, 1},
+		{0x007c, 0x007e, 2},
+		{0x00ac, 0x00b1, 5},
+		{0x00d7, 0x00f7, 32},
+		{0x03f6, 0x0606, 528},
+		{0x0607, 0x0608, 1},
+		{0x2044, 0x2052, 14},
+		{0x207a, 0x207c, 1},
+		{0x208a, 0x208c, 1},
+		{0x2118, 0x2140, 40},
+		{0x2141, 0x2144, 1},
+		{0x214b, 0x2190, 69},
+		{0x2191, 0x2194, 1},
+		{0x219a, 0x219b, 1},
+		{0x21a0, 0x21a6, 3},
+		{0x21ae, 0x21ce, 32},
+		{0x21cf, 0x21d2, 3},
+		{0x21d4, 0x21f4, 32},
+		{0x21f5, 0x22ff, 1},
+		{0x2320, 0x2321, 1},
+		{0x237c, 0x239b, 31},
+		{0x239c, 0x23b3, 1},
+		{0x23dc, 0x23e1, 1},
+		{0x25b7, 0x25c1, 10},
+		{0x25f8, 0x25ff, 1},
+		{0x266f, 0x27c0, 337},
+		{0x27c1, 0x27c4, 1},
+		{0x27c7, 0x27e5, 1},
+		{0x27f0, 0x27ff, 1},
+		{0x2900, 0x2982, 1},
+		{0x2999, 0x29d7, 1},
+		{0x29dc, 0x29fb, 1},
+		{0x29fe, 0x2aff, 1},
+		{0x2b30, 0x2b44, 1},
+		{0x2b47, 0x2b4c, 1},
+		{0xfb29, 0xfe62, 825},
+		{0xfe64, 0xfe66, 1},
+		{0xff0b, 0xff1c, 17},
+		{0xff1d, 0xff1e, 1},
+		{0xff5c, 0xff5e, 2},
+		{0xffe2, 0xffe9, 7},
+		{0xffea, 0xffec, 1},
+	},
+	R32: []Range32{
+		{0x1d6c1, 0x1d6db, 26},
+		{0x1d6fb, 0x1d715, 26},
+		{0x1d735, 0x1d74f, 26},
+		{0x1d76f, 0x1d789, 26},
+		{0x1d7a9, 0x1d7c3, 26},
+		{0x1eef0, 0x1eef1, 1},
+	},
+	LatinOffset: 5,
+}
+
+var _So = &RangeTable{
+	R16: []Range16{
+		{0x00a6, 0x00a9, 3},
+		{0x00ae, 0x00b0, 2},
+		{0x0482, 0x060e, 396},
+		{0x060f, 0x06de, 207},
+		{0x06e9, 0x06fd, 20},
+		{0x06fe, 0x07f6, 248},
+		{0x09fa, 0x0b70, 374},
+		{0x0bf3, 0x0bf8, 1},
+		{0x0bfa, 0x0c7f, 133},
+		{0x0d79, 0x0f01, 392},
+		{0x0f02, 0x0f03, 1},
+		{0x0f13, 0x0f15, 2},
+		{0x0f16, 0x0f17, 1},
+		{0x0f1a, 0x0f1f, 1},
+		{0x0f34, 0x0f38, 2},
+		{0x0fbe, 0x0fc5, 1},
+		{0x0fc7, 0x0fcc, 1},
+		{0x0fce, 0x0fcf, 1},
+		{0x0fd5, 0x0fd8, 1},
+		{0x109e, 0x109f, 1},
+		{0x1390, 0x1399, 1},
+		{0x1940, 0x19de, 158},
+		{0x19df, 0x19ff, 1},
+		{0x1b61, 0x1b6a, 1},
+		{0x1b74, 0x1b7c, 1},
+		{0x2100, 0x2101, 1},
+		{0x2103, 0x2106, 1},
+		{0x2108, 0x2109, 1},
+		{0x2114, 0x2116, 2},
+		{0x2117, 0x211e, 7},
+		{0x211f, 0x2123, 1},
+		{0x2125, 0x2129, 2},
+		{0x212e, 0x213a, 12},
+		{0x213b, 0x214a, 15},
+		{0x214c, 0x214d, 1},
+		{0x214f, 0x2195, 70},
+		{0x2196, 0x2199, 1},
+		{0x219c, 0x219f, 1},
+		{0x21a1, 0x21a2, 1},
+		{0x21a4, 0x21a5, 1},
+		{0x21a7, 0x21ad, 1},
+		{0x21af, 0x21cd, 1},
+		{0x21d0, 0x21d1, 1},
+		{0x21d3, 0x21d5, 2},
+		{0x21d6, 0x21f3, 1},
+		{0x2300, 0x2307, 1},
+		{0x230c, 0x231f, 1},
+		{0x2322, 0x2328, 1},
+		{0x232b, 0x237b, 1},
+		{0x237d, 0x239a, 1},
+		{0x23b4, 0x23db, 1},
+		{0x23e2, 0x23f3, 1},
+		{0x2400, 0x2426, 1},
+		{0x2440, 0x244a, 1},
+		{0x249c, 0x24e9, 1},
+		{0x2500, 0x25b6, 1},
+		{0x25b8, 0x25c0, 1},
+		{0x25c2, 0x25f7, 1},
+		{0x2600, 0x266e, 1},
+		{0x2670, 0x26ff, 1},
+		{0x2701, 0x2767, 1},
+		{0x2794, 0x27bf, 1},
+		{0x2800, 0x28ff, 1},
+		{0x2b00, 0x2b2f, 1},
+		{0x2b45, 0x2b46, 1},
+		{0x2b50, 0x2b59, 1},
+		{0x2ce5, 0x2cea, 1},
+		{0x2e80, 0x2e99, 1},
+		{0x2e9b, 0x2ef3, 1},
+		{0x2f00, 0x2fd5, 1},
+		{0x2ff0, 0x2ffb, 1},
+		{0x3004, 0x3012, 14},
+		{0x3013, 0x3020, 13},
+		{0x3036, 0x3037, 1},
+		{0x303e, 0x303f, 1},
+		{0x3190, 0x3191, 1},
+		{0x3196, 0x319f, 1},
+		{0x31c0, 0x31e3, 1},
+		{0x3200, 0x321e, 1},
+		{0x322a, 0x3247, 1},
+		{0x3250, 0x3260, 16},
+		{0x3261, 0x327f, 1},
+		{0x328a, 0x32b0, 1},
+		{0x32c0, 0x32fe, 1},
+		{0x3300, 0x33ff, 1},
+		{0x4dc0, 0x4dff, 1},
+		{0xa490, 0xa4c6, 1},
+		{0xa828, 0xa82b, 1},
+		{0xa836, 0xa837, 1},
+		{0xa839, 0xaa77, 574},
+		{0xaa78, 0xaa79, 1},
+		{0xfdfd, 0xffe4, 487},
+		{0xffe8, 0xffed, 5},
+		{0xffee, 0xfffc, 14},
+		{0xfffd, 0xfffd, 1},
+	},
+	R32: []Range32{
+		{0x10137, 0x10137, 1},
+		{0x10138, 0x1013f, 1},
+		{0x10179, 0x10189, 1},
+		{0x10190, 0x1019b, 1},
+		{0x101d0, 0x101fc, 1},
+		{0x1d000, 0x1d0f5, 1},
+		{0x1d100, 0x1d126, 1},
+		{0x1d129, 0x1d164, 1},
+		{0x1d16a, 0x1d16c, 1},
+		{0x1d183, 0x1d184, 1},
+		{0x1d18c, 0x1d1a9, 1},
+		{0x1d1ae, 0x1d1dd, 1},
+		{0x1d200, 0x1d241, 1},
+		{0x1d245, 0x1d300, 187},
+		{0x1d301, 0x1d356, 1},
+		{0x1f000, 0x1f02b, 1},
+		{0x1f030, 0x1f093, 1},
+		{0x1f0a0, 0x1f0ae, 1},
+		{0x1f0b1, 0x1f0be, 1},
+		{0x1f0c1, 0x1f0cf, 1},
+		{0x1f0d1, 0x1f0df, 1},
+		{0x1f110, 0x1f12e, 1},
+		{0x1f130, 0x1f16b, 1},
+		{0x1f170, 0x1f19a, 1},
+		{0x1f1e6, 0x1f202, 1},
+		{0x1f210, 0x1f23a, 1},
+		{0x1f240, 0x1f248, 1},
+		{0x1f250, 0x1f251, 1},
+		{0x1f300, 0x1f320, 1},
+		{0x1f330, 0x1f335, 1},
+		{0x1f337, 0x1f37c, 1},
+		{0x1f380, 0x1f393, 1},
+		{0x1f3a0, 0x1f3c4, 1},
+		{0x1f3c6, 0x1f3ca, 1},
+		{0x1f3e0, 0x1f3f0, 1},
+		{0x1f400, 0x1f43e, 1},
+		{0x1f440, 0x1f442, 2},
+		{0x1f443, 0x1f4f7, 1},
+		{0x1f4f9, 0x1f4fc, 1},
+		{0x1f500, 0x1f53d, 1},
+		{0x1f540, 0x1f543, 1},
+		{0x1f550, 0x1f567, 1},
+		{0x1f5fb, 0x1f640, 1},
+		{0x1f645, 0x1f64f, 1},
+		{0x1f680, 0x1f6c5, 1},
+		{0x1f700, 0x1f773, 1},
+	},
+	LatinOffset: 2,
+}
+
+var _Z = &RangeTable{
+	R16: []Range16{
+		{0x0020, 0x00a0, 128},
+		{0x1680, 0x2000, 2432},
+		{0x2001, 0x200a, 1},
+		{0x2028, 0x2029, 1},
+		{0x202f, 0x205f, 48},
+		{0x3000, 0x3000, 1},
+	},
+	LatinOffset: 1,
+}
+
+var _Zl = &RangeTable{
+	R16: []Range16{
+		{0x2028, 0x2028, 1},
+	},
+}
+
+var _Zp = &RangeTable{
+	R16: []Range16{
+		{0x2029, 0x2029, 1},
+	},
+}
+
+var _Zs = &RangeTable{
+	R16: []Range16{
+		{0x0020, 0x00a0, 128},
+		{0x1680, 0x2000, 2432},
+		{0x2001, 0x200a, 1},
+		{0x202f, 0x205f, 48},
+		{0x3000, 0x3000, 1},
+	},
+	LatinOffset: 1,
+}
+
+// These variables have type *RangeTable.
+var (
+	Cc     = _Cc // Cc is the set of Unicode characters in category Cc.
+	Cf     = _Cf // Cf is the set of Unicode characters in category Cf.
+	Co     = _Co // Co is the set of Unicode characters in category Co.
+	Cs     = _Cs // Cs is the set of Unicode characters in category Cs.
+	Digit  = _Nd // Digit is the set of Unicode characters with the "decimal digit" property.
+	Nd     = _Nd // Nd is the set of Unicode characters in category Nd.
+	Letter = _L  // Letter/L is the set of Unicode letters, category L.
+	L      = _L
+	Lm     = _Lm // Lm is the set of Unicode characters in category Lm.
+	Lo     = _Lo // Lo is the set of Unicode characters in category Lo.
+	Lower  = _Ll // Lower is the set of Unicode lower case letters.
+	Ll     = _Ll // Ll is the set of Unicode characters in category Ll.
+	Mark   = _M  // Mark/M is the set of Unicode mark characters, category M.
+	M      = _M
+	Mc     = _Mc // Mc is the set of Unicode characters in category Mc.
+	Me     = _Me // Me is the set of Unicode characters in category Me.
+	Mn     = _Mn // Mn is the set of Unicode characters in category Mn.
+	Nl     = _Nl // Nl is the set of Unicode characters in category Nl.
+	No     = _No // No is the set of Unicode characters in category No.
+	Number = _N  // Number/N is the set of Unicode number characters, category N.
+	N      = _N
+	Other  = _C // Other/C is the set of Unicode control and special characters, category C.
+	C      = _C
+	Pc     = _Pc // Pc is the set of Unicode characters in category Pc.
+	Pd     = _Pd // Pd is the set of Unicode characters in category Pd.
+	Pe     = _Pe // Pe is the set of Unicode characters in category Pe.
+	Pf     = _Pf // Pf is the set of Unicode characters in category Pf.
+	Pi     = _Pi // Pi is the set of Unicode characters in category Pi.
+	Po     = _Po // Po is the set of Unicode characters in category Po.
+	Ps     = _Ps // Ps is the set of Unicode characters in category Ps.
+	Punct  = _P  // Punct/P is the set of Unicode punctuation characters, category P.
+	P      = _P
+	Sc     = _Sc // Sc is the set of Unicode characters in category Sc.
+	Sk     = _Sk // Sk is the set of Unicode characters in category Sk.
+	Sm     = _Sm // Sm is the set of Unicode characters in category Sm.
+	So     = _So // So is the set of Unicode characters in category So.
+	Space  = _Z  // Space/Z is the set of Unicode space characters, category Z.
+	Z      = _Z
+	Symbol = _S // Symbol/S is the set of Unicode symbol characters, category S.
+	S      = _S
+	Title  = _Lt // Title is the set of Unicode title case letters.
+	Lt     = _Lt // Lt is the set of Unicode characters in category Lt.
+	Upper  = _Lu // Upper is the set of Unicode upper case letters.
+	Lu     = _Lu // Lu is the set of Unicode characters in category Lu.
+	Zl     = _Zl // Zl is the set of Unicode characters in category Zl.
+	Zp     = _Zp // Zp is the set of Unicode characters in category Zp.
+	Zs     = _Zs // Zs is the set of Unicode characters in category Zs.
+)
+
+// Generated by running
+//	maketables --scripts=all --url=http://www.unicode.org/Public/6.3.0/ucd/
+// DO NOT EDIT
+
+// Scripts is the set of Unicode script tables.
+var Scripts = map[string]*RangeTable{
+	"Arabic":                 Arabic,
+	"Armenian":               Armenian,
+	"Avestan":                Avestan,
+	"Balinese":               Balinese,
+	"Bamum":                  Bamum,
+	"Batak":                  Batak,
+	"Bengali":                Bengali,
+	"Bopomofo":               Bopomofo,
+	"Brahmi":                 Brahmi,
+	"Braille":                Braille,
+	"Buginese":               Buginese,
+	"Buhid":                  Buhid,
+	"Canadian_Aboriginal":    Canadian_Aboriginal,
+	"Carian":                 Carian,
+	"Chakma":                 Chakma,
+	"Cham":                   Cham,
+	"Cherokee":               Cherokee,
+	"Common":                 Common,
+	"Coptic":                 Coptic,
+	"Cuneiform":              Cuneiform,
+	"Cypriot":                Cypriot,
+	"Cyrillic":               Cyrillic,
+	"Deseret":                Deseret,
+	"Devanagari":             Devanagari,
+	"Egyptian_Hieroglyphs":   Egyptian_Hieroglyphs,
+	"Ethiopic":               Ethiopic,
+	"Georgian":               Georgian,
+	"Glagolitic":             Glagolitic,
+	"Gothic":                 Gothic,
+	"Greek":                  Greek,
+	"Gujarati":               Gujarati,
+	"Gurmukhi":               Gurmukhi,
+	"Han":                    Han,
+	"Hangul":                 Hangul,
+	"Hanunoo":                Hanunoo,
+	"Hebrew":                 Hebrew,
+	"Hiragana":               Hiragana,
+	"Imperial_Aramaic":       Imperial_Aramaic,
+	"Inherited":              Inherited,
+	"Inscriptional_Pahlavi":  Inscriptional_Pahlavi,
+	"Inscriptional_Parthian": Inscriptional_Parthian,
+	"Javanese":               Javanese,
+	"Kaithi":                 Kaithi,
+	"Kannada":                Kannada,
+	"Katakana":               Katakana,
+	"Kayah_Li":               Kayah_Li,
+	"Kharoshthi":             Kharoshthi,
+	"Khmer":                  Khmer,
+	"Lao":                    Lao,
+	"Latin":                  Latin,
+	"Lepcha":                 Lepcha,
+	"Limbu":                  Limbu,
+	"Linear_B":               Linear_B,
+	"Lisu":                   Lisu,
+	"Lycian":                 Lycian,
+	"Lydian":                 Lydian,
+	"Malayalam":              Malayalam,
+	"Mandaic":                Mandaic,
+	"Meetei_Mayek":           Meetei_Mayek,
+	"Meroitic_Cursive":       Meroitic_Cursive,
+	"Meroitic_Hieroglyphs":   Meroitic_Hieroglyphs,
+	"Miao":                   Miao,
+	"Mongolian":              Mongolian,
+	"Myanmar":                Myanmar,
+	"New_Tai_Lue":            New_Tai_Lue,
+	"Nko":                    Nko,
+	"Ogham":                  Ogham,
+	"Ol_Chiki":               Ol_Chiki,
+	"Old_Italic":             Old_Italic,
+	"Old_Persian":            Old_Persian,
+	"Old_South_Arabian":      Old_South_Arabian,
+	"Old_Turkic":             Old_Turkic,
+	"Oriya":                  Oriya,
+	"Osmanya":                Osmanya,
+	"Phags_Pa":               Phags_Pa,
+	"Phoenician":             Phoenician,
+	"Rejang":                 Rejang,
+	"Runic":                  Runic,
+	"Samaritan":              Samaritan,
+	"Saurashtra":             Saurashtra,
+	"Sharada":                Sharada,
+	"Shavian":                Shavian,
+	"Sinhala":                Sinhala,
+	"Sora_Sompeng":           Sora_Sompeng,
+	"Sundanese":              Sundanese,
+	"Syloti_Nagri":           Syloti_Nagri,
+	"Syriac":                 Syriac,
+	"Tagalog":                Tagalog,
+	"Tagbanwa":               Tagbanwa,
+	"Tai_Le":                 Tai_Le,
+	"Tai_Tham":               Tai_Tham,
+	"Tai_Viet":               Tai_Viet,
+	"Takri":                  Takri,
+	"Tamil":                  Tamil,
+	"Telugu":                 Telugu,
+	"Thaana":                 Thaana,
+	"Thai":                   Thai,
+	"Tibetan":                Tibetan,
+	"Tifinagh":               Tifinagh,
+	"Ugaritic":               Ugaritic,
+	"Vai":                    Vai,
+	"Yi":                     Yi,
+}
+
+var _Arabic = &RangeTable{
+	R16: []Range16{
+		{0x0600, 0x0604, 1},
+		{0x0606, 0x060b, 1},
+		{0x060d, 0x061a, 1},
+		{0x061c, 0x061c, 1},
+		{0x061e, 0x061e, 1},
+		{0x0620, 0x063f, 1},
+		{0x0641, 0x064a, 1},
+		{0x0656, 0x065f, 1},
+		{0x066a, 0x066f, 1},
+		{0x0671, 0x06dc, 1},
+		{0x06de, 0x06ff, 1},
+		{0x0750, 0x077f, 1},
+		{0x08a0, 0x08a0, 1},
+		{0x08a2, 0x08ac, 1},
+		{0x08e4, 0x08fe, 1},
+		{0xfb50, 0xfbc1, 1},
+		{0xfbd3, 0xfd3d, 1},
+		{0xfd50, 0xfd8f, 1},
+		{0xfd92, 0xfdc7, 1},
+		{0xfdf0, 0xfdfc, 1},
+		{0xfe70, 0xfe74, 1},
+		{0xfe76, 0xfefc, 1},
+	},
+	R32: []Range32{
+		{0x10e60, 0x10e7e, 1},
+		{0x1ee00, 0x1ee03, 1},
+		{0x1ee05, 0x1ee1f, 1},
+		{0x1ee21, 0x1ee22, 1},
+		{0x1ee24, 0x1ee24, 1},
+		{0x1ee27, 0x1ee27, 1},
+		{0x1ee29, 0x1ee32, 1},
+		{0x1ee34, 0x1ee37, 1},
+		{0x1ee39, 0x1ee39, 1},
+		{0x1ee3b, 0x1ee3b, 1},
+		{0x1ee42, 0x1ee42, 1},
+		{0x1ee47, 0x1ee47, 1},
+		{0x1ee49, 0x1ee49, 1},
+		{0x1ee4b, 0x1ee4b, 1},
+		{0x1ee4d, 0x1ee4f, 1},
+		{0x1ee51, 0x1ee52, 1},
+		{0x1ee54, 0x1ee54, 1},
+		{0x1ee57, 0x1ee57, 1},
+		{0x1ee59, 0x1ee59, 1},
+		{0x1ee5b, 0x1ee5b, 1},
+		{0x1ee5d, 0x1ee5d, 1},
+		{0x1ee5f, 0x1ee5f, 1},
+		{0x1ee61, 0x1ee62, 1},
+		{0x1ee64, 0x1ee64, 1},
+		{0x1ee67, 0x1ee6a, 1},
+		{0x1ee6c, 0x1ee72, 1},
+		{0x1ee74, 0x1ee77, 1},
+		{0x1ee79, 0x1ee7c, 1},
+		{0x1ee7e, 0x1ee7e, 1},
+		{0x1ee80, 0x1ee89, 1},
+		{0x1ee8b, 0x1ee9b, 1},
+		{0x1eea1, 0x1eea3, 1},
+		{0x1eea5, 0x1eea9, 1},
+		{0x1eeab, 0x1eebb, 1},
+		{0x1eef0, 0x1eef1, 1},
+	},
+}
+
+var _Armenian = &RangeTable{
+	R16: []Range16{
+		{0x0531, 0x0556, 1},
+		{0x0559, 0x055f, 1},
+		{0x0561, 0x0587, 1},
+		{0x058a, 0x058a, 1},
+		{0x058f, 0x058f, 1},
+		{0xfb13, 0xfb17, 1},
+	},
+}
+
+var _Avestan = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10b00, 0x10b35, 1},
+		{0x10b39, 0x10b3f, 1},
+	},
+}
+
+var _Balinese = &RangeTable{
+	R16: []Range16{
+		{0x1b00, 0x1b4b, 1},
+		{0x1b50, 0x1b7c, 1},
+	},
+}
+
+var _Bamum = &RangeTable{
+	R16: []Range16{
+		{0xa6a0, 0xa6f7, 1},
+	},
+	R32: []Range32{
+		{0x16800, 0x16a38, 1},
+	},
+}
+
+var _Batak = &RangeTable{
+	R16: []Range16{
+		{0x1bc0, 0x1bf3, 1},
+		{0x1bfc, 0x1bff, 1},
+	},
+}
+
+var _Bengali = &RangeTable{
+	R16: []Range16{
+		{0x0981, 0x0983, 1},
+		{0x0985, 0x098c, 1},
+		{0x098f, 0x0990, 1},
+		{0x0993, 0x09a8, 1},
+		{0x09aa, 0x09b0, 1},
+		{0x09b2, 0x09b2, 1},
+		{0x09b6, 0x09b9, 1},
+		{0x09bc, 0x09c4, 1},
+		{0x09c7, 0x09c8, 1},
+		{0x09cb, 0x09ce, 1},
+		{0x09d7, 0x09d7, 1},
+		{0x09dc, 0x09dd, 1},
+		{0x09df, 0x09e3, 1},
+		{0x09e6, 0x09fb, 1},
+	},
+}
+
+var _Bopomofo = &RangeTable{
+	R16: []Range16{
+		{0x02ea, 0x02eb, 1},
+		{0x3105, 0x312d, 1},
+		{0x31a0, 0x31ba, 1},
+	},
+}
+
+var _Brahmi = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x11000, 0x1104d, 1},
+		{0x11052, 0x1106f, 1},
+	},
+}
+
+var _Braille = &RangeTable{
+	R16: []Range16{
+		{0x2800, 0x28ff, 1},
+	},
+}
+
+var _Buginese = &RangeTable{
+	R16: []Range16{
+		{0x1a00, 0x1a1b, 1},
+		{0x1a1e, 0x1a1f, 1},
+	},
+}
+
+var _Buhid = &RangeTable{
+	R16: []Range16{
+		{0x1740, 0x1753, 1},
+	},
+}
+
+var _Canadian_Aboriginal = &RangeTable{
+	R16: []Range16{
+		{0x1400, 0x167f, 1},
+		{0x18b0, 0x18f5, 1},
+	},
+}
+
+var _Carian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x102a0, 0x102d0, 1},
+	},
+}
+
+var _Chakma = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x11100, 0x11134, 1},
+		{0x11136, 0x11143, 1},
+	},
+}
+
+var _Cham = &RangeTable{
+	R16: []Range16{
+		{0xaa00, 0xaa36, 1},
+		{0xaa40, 0xaa4d, 1},
+		{0xaa50, 0xaa59, 1},
+		{0xaa5c, 0xaa5f, 1},
+	},
+}
+
+var _Cherokee = &RangeTable{
+	R16: []Range16{
+		{0x13a0, 0x13f4, 1},
+	},
+}
+
+var _Common = &RangeTable{
+	R16: []Range16{
+		{0x0000, 0x0040, 1},
+		{0x005b, 0x0060, 1},
+		{0x007b, 0x00a9, 1},
+		{0x00ab, 0x00b9, 1},
+		{0x00bb, 0x00bf, 1},
+		{0x00d7, 0x00d7, 1},
+		{0x00f7, 0x00f7, 1},
+		{0x02b9, 0x02df, 1},
+		{0x02e5, 0x02e9, 1},
+		{0x02ec, 0x02ff, 1},
+		{0x0374, 0x0374, 1},
+		{0x037e, 0x037e, 1},
+		{0x0385, 0x0385, 1},
+		{0x0387, 0x0387, 1},
+		{0x0589, 0x0589, 1},
+		{0x060c, 0x060c, 1},
+		{0x061b, 0x061b, 1},
+		{0x061f, 0x061f, 1},
+		{0x0640, 0x0640, 1},
+		{0x0660, 0x0669, 1},
+		{0x06dd, 0x06dd, 1},
+		{0x0964, 0x0965, 1},
+		{0x0e3f, 0x0e3f, 1},
+		{0x0fd5, 0x0fd8, 1},
+		{0x10fb, 0x10fb, 1},
+		{0x16eb, 0x16ed, 1},
+		{0x1735, 0x1736, 1},
+		{0x1802, 0x1803, 1},
+		{0x1805, 0x1805, 1},
+		{0x1cd3, 0x1cd3, 1},
+		{0x1ce1, 0x1ce1, 1},
+		{0x1ce9, 0x1cec, 1},
+		{0x1cee, 0x1cf3, 1},
+		{0x1cf5, 0x1cf6, 1},
+		{0x2000, 0x200b, 1},
+		{0x200e, 0x2064, 1},
+		{0x2066, 0x2070, 1},
+		{0x2074, 0x207e, 1},
+		{0x2080, 0x208e, 1},
+		{0x20a0, 0x20ba, 1},
+		{0x2100, 0x2125, 1},
+		{0x2127, 0x2129, 1},
+		{0x212c, 0x2131, 1},
+		{0x2133, 0x214d, 1},
+		{0x214f, 0x215f, 1},
+		{0x2189, 0x2189, 1},
+		{0x2190, 0x23f3, 1},
+		{0x2400, 0x2426, 1},
+		{0x2440, 0x244a, 1},
+		{0x2460, 0x26ff, 1},
+		{0x2701, 0x27ff, 1},
+		{0x2900, 0x2b4c, 1},
+		{0x2b50, 0x2b59, 1},
+		{0x2e00, 0x2e3b, 1},
+		{0x2ff0, 0x2ffb, 1},
+		{0x3000, 0x3004, 1},
+		{0x3006, 0x3006, 1},
+		{0x3008, 0x3020, 1},
+		{0x3030, 0x3037, 1},
+		{0x303c, 0x303f, 1},
+		{0x309b, 0x309c, 1},
+		{0x30a0, 0x30a0, 1},
+		{0x30fb, 0x30fc, 1},
+		{0x3190, 0x319f, 1},
+		{0x31c0, 0x31e3, 1},
+		{0x3220, 0x325f, 1},
+		{0x327f, 0x32cf, 1},
+		{0x3358, 0x33ff, 1},
+		{0x4dc0, 0x4dff, 1},
+		{0xa700, 0xa721, 1},
+		{0xa788, 0xa78a, 1},
+		{0xa830, 0xa839, 1},
+		{0xa9cf, 0xa9cf, 1},
+		{0xfd3e, 0xfd3f, 1},
+		{0xfdfd, 0xfdfd, 1},
+		{0xfe10, 0xfe19, 1},
+		{0xfe30, 0xfe52, 1},
+		{0xfe54, 0xfe66, 1},
+		{0xfe68, 0xfe6b, 1},
+		{0xfeff, 0xfeff, 1},
+		{0xff01, 0xff20, 1},
+		{0xff3b, 0xff40, 1},
+		{0xff5b, 0xff65, 1},
+		{0xff70, 0xff70, 1},
+		{0xff9e, 0xff9f, 1},
+		{0xffe0, 0xffe6, 1},
+		{0xffe8, 0xffee, 1},
+		{0xfff9, 0xfffd, 1},
+	},
+	R32: []Range32{
+		{0x10100, 0x10102, 1},
+		{0x10107, 0x10133, 1},
+		{0x10137, 0x1013f, 1},
+		{0x10190, 0x1019b, 1},
+		{0x101d0, 0x101fc, 1},
+		{0x1d000, 0x1d0f5, 1},
+		{0x1d100, 0x1d126, 1},
+		{0x1d129, 0x1d166, 1},
+		{0x1d16a, 0x1d17a, 1},
+		{0x1d183, 0x1d184, 1},
+		{0x1d18c, 0x1d1a9, 1},
+		{0x1d1ae, 0x1d1dd, 1},
+		{0x1d300, 0x1d356, 1},
+		{0x1d360, 0x1d371, 1},
+		{0x1d400, 0x1d454, 1},
+		{0x1d456, 0x1d49c, 1},
+		{0x1d49e, 0x1d49f, 1},
+		{0x1d4a2, 0x1d4a2, 1},
+		{0x1d4a5, 0x1d4a6, 1},
+		{0x1d4a9, 0x1d4ac, 1},
+		{0x1d4ae, 0x1d4b9, 1},
+		{0x1d4bb, 0x1d4bb, 1},
+		{0x1d4bd, 0x1d4c3, 1},
+		{0x1d4c5, 0x1d505, 1},
+		{0x1d507, 0x1d50a, 1},
+		{0x1d50d, 0x1d514, 1},
+		{0x1d516, 0x1d51c, 1},
+		{0x1d51e, 0x1d539, 1},
+		{0x1d53b, 0x1d53e, 1},
+		{0x1d540, 0x1d544, 1},
+		{0x1d546, 0x1d546, 1},
+		{0x1d54a, 0x1d550, 1},
+		{0x1d552, 0x1d6a5, 1},
+		{0x1d6a8, 0x1d7cb, 1},
+		{0x1d7ce, 0x1d7ff, 1},
+		{0x1f000, 0x1f02b, 1},
+		{0x1f030, 0x1f093, 1},
+		{0x1f0a0, 0x1f0ae, 1},
+		{0x1f0b1, 0x1f0be, 1},
+		{0x1f0c1, 0x1f0cf, 1},
+		{0x1f0d1, 0x1f0df, 1},
+		{0x1f100, 0x1f10a, 1},
+		{0x1f110, 0x1f12e, 1},
+		{0x1f130, 0x1f16b, 1},
+		{0x1f170, 0x1f19a, 1},
+		{0x1f1e6, 0x1f1ff, 1},
+		{0x1f201, 0x1f202, 1},
+		{0x1f210, 0x1f23a, 1},
+		{0x1f240, 0x1f248, 1},
+		{0x1f250, 0x1f251, 1},
+		{0x1f300, 0x1f320, 1},
+		{0x1f330, 0x1f335, 1},
+		{0x1f337, 0x1f37c, 1},
+		{0x1f380, 0x1f393, 1},
+		{0x1f3a0, 0x1f3c4, 1},
+		{0x1f3c6, 0x1f3ca, 1},
+		{0x1f3e0, 0x1f3f0, 1},
+		{0x1f400, 0x1f43e, 1},
+		{0x1f440, 0x1f440, 1},
+		{0x1f442, 0x1f4f7, 1},
+		{0x1f4f9, 0x1f4fc, 1},
+		{0x1f500, 0x1f53d, 1},
+		{0x1f540, 0x1f543, 1},
+		{0x1f550, 0x1f567, 1},
+		{0x1f5fb, 0x1f640, 1},
+		{0x1f645, 0x1f64f, 1},
+		{0x1f680, 0x1f6c5, 1},
+		{0x1f700, 0x1f773, 1},
+		{0xe0001, 0xe0001, 1},
+		{0xe0020, 0xe007f, 1},
+	},
+	LatinOffset: 7,
+}
+
+var _Coptic = &RangeTable{
+	R16: []Range16{
+		{0x03e2, 0x03ef, 1},
+		{0x2c80, 0x2cf3, 1},
+		{0x2cf9, 0x2cff, 1},
+	},
+}
+
+var _Cuneiform = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x12000, 0x1236e, 1},
+		{0x12400, 0x12462, 1},
+		{0x12470, 0x12473, 1},
+	},
+}
+
+var _Cypriot = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10800, 0x10805, 1},
+		{0x10808, 0x10808, 1},
+		{0x1080a, 0x10835, 1},
+		{0x10837, 0x10838, 1},
+		{0x1083c, 0x1083c, 1},
+		{0x1083f, 0x1083f, 1},
+	},
+}
+
+var _Cyrillic = &RangeTable{
+	R16: []Range16{
+		{0x0400, 0x0484, 1},
+		{0x0487, 0x0527, 1},
+		{0x1d2b, 0x1d2b, 1},
+		{0x1d78, 0x1d78, 1},
+		{0x2de0, 0x2dff, 1},
+		{0xa640, 0xa697, 1},
+		{0xa69f, 0xa69f, 1},
+	},
+}
+
+var _Deseret = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10400, 0x1044f, 1},
+	},
+}
+
+var _Devanagari = &RangeTable{
+	R16: []Range16{
+		{0x0900, 0x0950, 1},
+		{0x0953, 0x0963, 1},
+		{0x0966, 0x0977, 1},
+		{0x0979, 0x097f, 1},
+		{0xa8e0, 0xa8fb, 1},
+	},
+}
+
+var _Egyptian_Hieroglyphs = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x13000, 0x1342e, 1},
+	},
+}
+
+var _Ethiopic = &RangeTable{
+	R16: []Range16{
+		{0x1200, 0x1248, 1},
+		{0x124a, 0x124d, 1},
+		{0x1250, 0x1256, 1},
+		{0x1258, 0x1258, 1},
+		{0x125a, 0x125d, 1},
+		{0x1260, 0x1288, 1},
+		{0x128a, 0x128d, 1},
+		{0x1290, 0x12b0, 1},
+		{0x12b2, 0x12b5, 1},
+		{0x12b8, 0x12be, 1},
+		{0x12c0, 0x12c0, 1},
+		{0x12c2, 0x12c5, 1},
+		{0x12c8, 0x12d6, 1},
+		{0x12d8, 0x1310, 1},
+		{0x1312, 0x1315, 1},
+		{0x1318, 0x135a, 1},
+		{0x135d, 0x137c, 1},
+		{0x1380, 0x1399, 1},
+		{0x2d80, 0x2d96, 1},
+		{0x2da0, 0x2da6, 1},
+		{0x2da8, 0x2dae, 1},
+		{0x2db0, 0x2db6, 1},
+		{0x2db8, 0x2dbe, 1},
+		{0x2dc0, 0x2dc6, 1},
+		{0x2dc8, 0x2dce, 1},
+		{0x2dd0, 0x2dd6, 1},
+		{0x2dd8, 0x2dde, 1},
+		{0xab01, 0xab06, 1},
+		{0xab09, 0xab0e, 1},
+		{0xab11, 0xab16, 1},
+		{0xab20, 0xab26, 1},
+		{0xab28, 0xab2e, 1},
+	},
+}
+
+var _Georgian = &RangeTable{
+	R16: []Range16{
+		{0x10a0, 0x10c5, 1},
+		{0x10c7, 0x10c7, 1},
+		{0x10cd, 0x10cd, 1},
+		{0x10d0, 0x10fa, 1},
+		{0x10fc, 0x10ff, 1},
+		{0x2d00, 0x2d25, 1},
+		{0x2d27, 0x2d27, 1},
+		{0x2d2d, 0x2d2d, 1},
+	},
+}
+
+var _Glagolitic = &RangeTable{
+	R16: []Range16{
+		{0x2c00, 0x2c2e, 1},
+		{0x2c30, 0x2c5e, 1},
+	},
+}
+
+var _Gothic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10330, 0x1034a, 1},
+	},
+}
+
+var _Greek = &RangeTable{
+	R16: []Range16{
+		{0x0370, 0x0373, 1},
+		{0x0375, 0x0377, 1},
+		{0x037a, 0x037d, 1},
+		{0x0384, 0x0384, 1},
+		{0x0386, 0x0386, 1},
+		{0x0388, 0x038a, 1},
+		{0x038c, 0x038c, 1},
+		{0x038e, 0x03a1, 1},
+		{0x03a3, 0x03e1, 1},
+		{0x03f0, 0x03ff, 1},
+		{0x1d26, 0x1d2a, 1},
+		{0x1d5d, 0x1d61, 1},
+		{0x1d66, 0x1d6a, 1},
+		{0x1dbf, 0x1dbf, 1},
+		{0x1f00, 0x1f15, 1},
+		{0x1f18, 0x1f1d, 1},
+		{0x1f20, 0x1f45, 1},
+		{0x1f48, 0x1f4d, 1},
+		{0x1f50, 0x1f57, 1},
+		{0x1f59, 0x1f59, 1},
+		{0x1f5b, 0x1f5b, 1},
+		{0x1f5d, 0x1f5d, 1},
+		{0x1f5f, 0x1f7d, 1},
+		{0x1f80, 0x1fb4, 1},
+		{0x1fb6, 0x1fc4, 1},
+		{0x1fc6, 0x1fd3, 1},
+		{0x1fd6, 0x1fdb, 1},
+		{0x1fdd, 0x1fef, 1},
+		{0x1ff2, 0x1ff4, 1},
+		{0x1ff6, 0x1ffe, 1},
+		{0x2126, 0x2126, 1},
+	},
+	R32: []Range32{
+		{0x10140, 0x1018a, 1},
+		{0x1d200, 0x1d245, 1},
+	},
+}
+
+var _Gujarati = &RangeTable{
+	R16: []Range16{
+		{0x0a81, 0x0a83, 1},
+		{0x0a85, 0x0a8d, 1},
+		{0x0a8f, 0x0a91, 1},
+		{0x0a93, 0x0aa8, 1},
+		{0x0aaa, 0x0ab0, 1},
+		{0x0ab2, 0x0ab3, 1},
+		{0x0ab5, 0x0ab9, 1},
+		{0x0abc, 0x0ac5, 1},
+		{0x0ac7, 0x0ac9, 1},
+		{0x0acb, 0x0acd, 1},
+		{0x0ad0, 0x0ad0, 1},
+		{0x0ae0, 0x0ae3, 1},
+		{0x0ae6, 0x0af1, 1},
+	},
+}
+
+var _Gurmukhi = &RangeTable{
+	R16: []Range16{
+		{0x0a01, 0x0a03, 1},
+		{0x0a05, 0x0a0a, 1},
+		{0x0a0f, 0x0a10, 1},
+		{0x0a13, 0x0a28, 1},
+		{0x0a2a, 0x0a30, 1},
+		{0x0a32, 0x0a33, 1},
+		{0x0a35, 0x0a36, 1},
+		{0x0a38, 0x0a39, 1},
+		{0x0a3c, 0x0a3c, 1},
+		{0x0a3e, 0x0a42, 1},
+		{0x0a47, 0x0a48, 1},
+		{0x0a4b, 0x0a4d, 1},
+		{0x0a51, 0x0a51, 1},
+		{0x0a59, 0x0a5c, 1},
+		{0x0a5e, 0x0a5e, 1},
+		{0x0a66, 0x0a75, 1},
+	},
+}
+
+var _Han = &RangeTable{
+	R16: []Range16{
+		{0x2e80, 0x2e99, 1},
+		{0x2e9b, 0x2ef3, 1},
+		{0x2f00, 0x2fd5, 1},
+		{0x3005, 0x3005, 1},
+		{0x3007, 0x3007, 1},
+		{0x3021, 0x3029, 1},
+		{0x3038, 0x303b, 1},
+		{0x3400, 0x4db5, 1},
+		{0x4e00, 0x9fcc, 1},
+		{0xf900, 0xfa6d, 1},
+		{0xfa70, 0xfad9, 1},
+	},
+	R32: []Range32{
+		{0x20000, 0x2a6d6, 1},
+		{0x2a700, 0x2b734, 1},
+		{0x2b740, 0x2b81d, 1},
+		{0x2f800, 0x2fa1d, 1},
+	},
+}
+
+var _Hangul = &RangeTable{
+	R16: []Range16{
+		{0x1100, 0x11ff, 1},
+		{0x302e, 0x302f, 1},
+		{0x3131, 0x318e, 1},
+		{0x3200, 0x321e, 1},
+		{0x3260, 0x327e, 1},
+		{0xa960, 0xa97c, 1},
+		{0xac00, 0xd7a3, 1},
+		{0xd7b0, 0xd7c6, 1},
+		{0xd7cb, 0xd7fb, 1},
+		{0xffa0, 0xffbe, 1},
+		{0xffc2, 0xffc7, 1},
+		{0xffca, 0xffcf, 1},
+		{0xffd2, 0xffd7, 1},
+		{0xffda, 0xffdc, 1},
+	},
+}
+
+var _Hanunoo = &RangeTable{
+	R16: []Range16{
+		{0x1720, 0x1734, 1},
+	},
+}
+
+var _Hebrew = &RangeTable{
+	R16: []Range16{
+		{0x0591, 0x05c7, 1},
+		{0x05d0, 0x05ea, 1},
+		{0x05f0, 0x05f4, 1},
+		{0xfb1d, 0xfb36, 1},
+		{0xfb38, 0xfb3c, 1},
+		{0xfb3e, 0xfb3e, 1},
+		{0xfb40, 0xfb41, 1},
+		{0xfb43, 0xfb44, 1},
+		{0xfb46, 0xfb4f, 1},
+	},
+}
+
+var _Hiragana = &RangeTable{
+	R16: []Range16{
+		{0x3041, 0x3096, 1},
+		{0x309d, 0x309f, 1},
+	},
+	R32: []Range32{
+		{0x1b001, 0x1b001, 1},
+		{0x1f200, 0x1f200, 1},
+	},
+}
+
+var _Imperial_Aramaic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10840, 0x10855, 1},
+		{0x10857, 0x1085f, 1},
+	},
+}
+
+var _Inherited = &RangeTable{
+	R16: []Range16{
+		{0x0300, 0x036f, 1},
+		{0x0485, 0x0486, 1},
+		{0x064b, 0x0655, 1},
+		{0x0670, 0x0670, 1},
+		{0x0951, 0x0952, 1},
+		{0x1cd0, 0x1cd2, 1},
+		{0x1cd4, 0x1ce0, 1},
+		{0x1ce2, 0x1ce8, 1},
+		{0x1ced, 0x1ced, 1},
+		{0x1cf4, 0x1cf4, 1},
+		{0x1dc0, 0x1de6, 1},
+		{0x1dfc, 0x1dff, 1},
+		{0x200c, 0x200d, 1},
+		{0x20d0, 0x20f0, 1},
+		{0x302a, 0x302d, 1},
+		{0x3099, 0x309a, 1},
+		{0xfe00, 0xfe0f, 1},
+		{0xfe20, 0xfe26, 1},
+	},
+	R32: []Range32{
+		{0x101fd, 0x101fd, 1},
+		{0x1d167, 0x1d169, 1},
+		{0x1d17b, 0x1d182, 1},
+		{0x1d185, 0x1d18b, 1},
+		{0x1d1aa, 0x1d1ad, 1},
+		{0xe0100, 0xe01ef, 1},
+	},
+}
+
+var _Inscriptional_Pahlavi = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10b60, 0x10b72, 1},
+		{0x10b78, 0x10b7f, 1},
+	},
+}
+
+var _Inscriptional_Parthian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10b40, 0x10b55, 1},
+		{0x10b58, 0x10b5f, 1},
+	},
+}
+
+var _Javanese = &RangeTable{
+	R16: []Range16{
+		{0xa980, 0xa9cd, 1},
+		{0xa9d0, 0xa9d9, 1},
+		{0xa9de, 0xa9df, 1},
+	},
+}
+
+var _Kaithi = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x11080, 0x110c1, 1},
+	},
+}
+
+var _Kannada = &RangeTable{
+	R16: []Range16{
+		{0x0c82, 0x0c83, 1},
+		{0x0c85, 0x0c8c, 1},
+		{0x0c8e, 0x0c90, 1},
+		{0x0c92, 0x0ca8, 1},
+		{0x0caa, 0x0cb3, 1},
+		{0x0cb5, 0x0cb9, 1},
+		{0x0cbc, 0x0cc4, 1},
+		{0x0cc6, 0x0cc8, 1},
+		{0x0cca, 0x0ccd, 1},
+		{0x0cd5, 0x0cd6, 1},
+		{0x0cde, 0x0cde, 1},
+		{0x0ce0, 0x0ce3, 1},
+		{0x0ce6, 0x0cef, 1},
+		{0x0cf1, 0x0cf2, 1},
+	},
+}
+
+var _Katakana = &RangeTable{
+	R16: []Range16{
+		{0x30a1, 0x30fa, 1},
+		{0x30fd, 0x30ff, 1},
+		{0x31f0, 0x31ff, 1},
+		{0x32d0, 0x32fe, 1},
+		{0x3300, 0x3357, 1},
+		{0xff66, 0xff6f, 1},
+		{0xff71, 0xff9d, 1},
+	},
+	R32: []Range32{
+		{0x1b000, 0x1b000, 1},
+	},
+}
+
+var _Kayah_Li = &RangeTable{
+	R16: []Range16{
+		{0xa900, 0xa92f, 1},
+	},
+}
+
+var _Kharoshthi = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10a00, 0x10a03, 1},
+		{0x10a05, 0x10a06, 1},
+		{0x10a0c, 0x10a13, 1},
+		{0x10a15, 0x10a17, 1},
+		{0x10a19, 0x10a33, 1},
+		{0x10a38, 0x10a3a, 1},
+		{0x10a3f, 0x10a47, 1},
+		{0x10a50, 0x10a58, 1},
+	},
+}
+
+var _Khmer = &RangeTable{
+	R16: []Range16{
+		{0x1780, 0x17dd, 1},
+		{0x17e0, 0x17e9, 1},
+		{0x17f0, 0x17f9, 1},
+		{0x19e0, 0x19ff, 1},
+	},
+}
+
+var _Lao = &RangeTable{
+	R16: []Range16{
+		{0x0e81, 0x0e82, 1},
+		{0x0e84, 0x0e84, 1},
+		{0x0e87, 0x0e88, 1},
+		{0x0e8a, 0x0e8a, 1},
+		{0x0e8d, 0x0e8d, 1},
+		{0x0e94, 0x0e97, 1},
+		{0x0e99, 0x0e9f, 1},
+		{0x0ea1, 0x0ea3, 1},
+		{0x0ea5, 0x0ea5, 1},
+		{0x0ea7, 0x0ea7, 1},
+		{0x0eaa, 0x0eab, 1},
+		{0x0ead, 0x0eb9, 1},
+		{0x0ebb, 0x0ebd, 1},
+		{0x0ec0, 0x0ec4, 1},
+		{0x0ec6, 0x0ec6, 1},
+		{0x0ec8, 0x0ecd, 1},
+		{0x0ed0, 0x0ed9, 1},
+		{0x0edc, 0x0edf, 1},
+	},
+}
+
+var _Latin = &RangeTable{
+	R16: []Range16{
+		{0x0041, 0x005a, 1},
+		{0x0061, 0x007a, 1},
+		{0x00aa, 0x00aa, 1},
+		{0x00ba, 0x00ba, 1},
+		{0x00c0, 0x00d6, 1},
+		{0x00d8, 0x00f6, 1},
+		{0x00f8, 0x02b8, 1},
+		{0x02e0, 0x02e4, 1},
+		{0x1d00, 0x1d25, 1},
+		{0x1d2c, 0x1d5c, 1},
+		{0x1d62, 0x1d65, 1},
+		{0x1d6b, 0x1d77, 1},
+		{0x1d79, 0x1dbe, 1},
+		{0x1e00, 0x1eff, 1},
+		{0x2071, 0x2071, 1},
+		{0x207f, 0x207f, 1},
+		{0x2090, 0x209c, 1},
+		{0x212a, 0x212b, 1},
+		{0x2132, 0x2132, 1},
+		{0x214e, 0x214e, 1},
+		{0x2160, 0x2188, 1},
+		{0x2c60, 0x2c7f, 1},
+		{0xa722, 0xa787, 1},
+		{0xa78b, 0xa78e, 1},
+		{0xa790, 0xa793, 1},
+		{0xa7a0, 0xa7aa, 1},
+		{0xa7f8, 0xa7ff, 1},
+		{0xfb00, 0xfb06, 1},
+		{0xff21, 0xff3a, 1},
+		{0xff41, 0xff5a, 1},
+	},
+	LatinOffset: 6,
+}
+
+var _Lepcha = &RangeTable{
+	R16: []Range16{
+		{0x1c00, 0x1c37, 1},
+		{0x1c3b, 0x1c49, 1},
+		{0x1c4d, 0x1c4f, 1},
+	},
+}
+
+var _Limbu = &RangeTable{
+	R16: []Range16{
+		{0x1900, 0x191c, 1},
+		{0x1920, 0x192b, 1},
+		{0x1930, 0x193b, 1},
+		{0x1940, 0x1940, 1},
+		{0x1944, 0x194f, 1},
+	},
+}
+
+var _Linear_B = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10000, 0x1000b, 1},
+		{0x1000d, 0x10026, 1},
+		{0x10028, 0x1003a, 1},
+		{0x1003c, 0x1003d, 1},
+		{0x1003f, 0x1004d, 1},
+		{0x10050, 0x1005d, 1},
+		{0x10080, 0x100fa, 1},
+	},
+}
+
+var _Lisu = &RangeTable{
+	R16: []Range16{
+		{0xa4d0, 0xa4ff, 1},
+	},
+}
+
+var _Lycian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10280, 0x1029c, 1},
+	},
+}
+
+var _Lydian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10920, 0x10939, 1},
+		{0x1093f, 0x1093f, 1},
+	},
+}
+
+var _Malayalam = &RangeTable{
+	R16: []Range16{
+		{0x0d02, 0x0d03, 1},
+		{0x0d05, 0x0d0c, 1},
+		{0x0d0e, 0x0d10, 1},
+		{0x0d12, 0x0d3a, 1},
+		{0x0d3d, 0x0d44, 1},
+		{0x0d46, 0x0d48, 1},
+		{0x0d4a, 0x0d4e, 1},
+		{0x0d57, 0x0d57, 1},
+		{0x0d60, 0x0d63, 1},
+		{0x0d66, 0x0d75, 1},
+		{0x0d79, 0x0d7f, 1},
+	},
+}
+
+var _Mandaic = &RangeTable{
+	R16: []Range16{
+		{0x0840, 0x085b, 1},
+		{0x085e, 0x085e, 1},
+	},
+}
+
+var _Meetei_Mayek = &RangeTable{
+	R16: []Range16{
+		{0xaae0, 0xaaf6, 1},
+		{0xabc0, 0xabed, 1},
+		{0xabf0, 0xabf9, 1},
+	},
+}
+
+var _Meroitic_Cursive = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x109a0, 0x109b7, 1},
+		{0x109be, 0x109bf, 1},
+	},
+}
+
+var _Meroitic_Hieroglyphs = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10980, 0x1099f, 1},
+	},
+}
+
+var _Miao = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x16f00, 0x16f44, 1},
+		{0x16f50, 0x16f7e, 1},
+		{0x16f8f, 0x16f9f, 1},
+	},
+}
+
+var _Mongolian = &RangeTable{
+	R16: []Range16{
+		{0x1800, 0x1801, 1},
+		{0x1804, 0x1804, 1},
+		{0x1806, 0x180e, 1},
+		{0x1810, 0x1819, 1},
+		{0x1820, 0x1877, 1},
+		{0x1880, 0x18aa, 1},
+	},
+}
+
+var _Myanmar = &RangeTable{
+	R16: []Range16{
+		{0x1000, 0x109f, 1},
+		{0xaa60, 0xaa7b, 1},
+	},
+}
+
+var _New_Tai_Lue = &RangeTable{
+	R16: []Range16{
+		{0x1980, 0x19ab, 1},
+		{0x19b0, 0x19c9, 1},
+		{0x19d0, 0x19da, 1},
+		{0x19de, 0x19df, 1},
+	},
+}
+
+var _Nko = &RangeTable{
+	R16: []Range16{
+		{0x07c0, 0x07fa, 1},
+	},
+}
+
+var _Ogham = &RangeTable{
+	R16: []Range16{
+		{0x1680, 0x169c, 1},
+	},
+}
+
+var _Ol_Chiki = &RangeTable{
+	R16: []Range16{
+		{0x1c50, 0x1c7f, 1},
+	},
+}
+
+var _Old_Italic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10300, 0x1031e, 1},
+		{0x10320, 0x10323, 1},
+	},
+}
+
+var _Old_Persian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x103a0, 0x103c3, 1},
+		{0x103c8, 0x103d5, 1},
+	},
+}
+
+var _Old_South_Arabian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10a60, 0x10a7f, 1},
+	},
+}
+
+var _Old_Turkic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10c00, 0x10c48, 1},
+	},
+}
+
+var _Oriya = &RangeTable{
+	R16: []Range16{
+		{0x0b01, 0x0b03, 1},
+		{0x0b05, 0x0b0c, 1},
+		{0x0b0f, 0x0b10, 1},
+		{0x0b13, 0x0b28, 1},
+		{0x0b2a, 0x0b30, 1},
+		{0x0b32, 0x0b33, 1},
+		{0x0b35, 0x0b39, 1},
+		{0x0b3c, 0x0b44, 1},
+		{0x0b47, 0x0b48, 1},
+		{0x0b4b, 0x0b4d, 1},
+		{0x0b56, 0x0b57, 1},
+		{0x0b5c, 0x0b5d, 1},
+		{0x0b5f, 0x0b63, 1},
+		{0x0b66, 0x0b77, 1},
+	},
+}
+
+var _Osmanya = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10480, 0x1049d, 1},
+		{0x104a0, 0x104a9, 1},
+	},
+}
+
+var _Phags_Pa = &RangeTable{
+	R16: []Range16{
+		{0xa840, 0xa877, 1},
+	},
+}
+
+var _Phoenician = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10900, 0x1091b, 1},
+		{0x1091f, 0x1091f, 1},
+	},
+}
+
+var _Rejang = &RangeTable{
+	R16: []Range16{
+		{0xa930, 0xa953, 1},
+		{0xa95f, 0xa95f, 1},
+	},
+}
+
+var _Runic = &RangeTable{
+	R16: []Range16{
+		{0x16a0, 0x16ea, 1},
+		{0x16ee, 0x16f0, 1},
+	},
+}
+
+var _Samaritan = &RangeTable{
+	R16: []Range16{
+		{0x0800, 0x082d, 1},
+		{0x0830, 0x083e, 1},
+	},
+}
+
+var _Saurashtra = &RangeTable{
+	R16: []Range16{
+		{0xa880, 0xa8c4, 1},
+		{0xa8ce, 0xa8d9, 1},
+	},
+}
+
+var _Sharada = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x11180, 0x111c8, 1},
+		{0x111d0, 0x111d9, 1},
+	},
+}
+
+var _Shavian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10450, 0x1047f, 1},
+	},
+}
+
+var _Sinhala = &RangeTable{
+	R16: []Range16{
+		{0x0d82, 0x0d83, 1},
+		{0x0d85, 0x0d96, 1},
+		{0x0d9a, 0x0db1, 1},
+		{0x0db3, 0x0dbb, 1},
+		{0x0dbd, 0x0dbd, 1},
+		{0x0dc0, 0x0dc6, 1},
+		{0x0dca, 0x0dca, 1},
+		{0x0dcf, 0x0dd4, 1},
+		{0x0dd6, 0x0dd6, 1},
+		{0x0dd8, 0x0ddf, 1},
+		{0x0df2, 0x0df4, 1},
+	},
+}
+
+var _Sora_Sompeng = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x110d0, 0x110e8, 1},
+		{0x110f0, 0x110f9, 1},
+	},
+}
+
+var _Sundanese = &RangeTable{
+	R16: []Range16{
+		{0x1b80, 0x1bbf, 1},
+		{0x1cc0, 0x1cc7, 1},
+	},
+}
+
+var _Syloti_Nagri = &RangeTable{
+	R16: []Range16{
+		{0xa800, 0xa82b, 1},
+	},
+}
+
+var _Syriac = &RangeTable{
+	R16: []Range16{
+		{0x0700, 0x070d, 1},
+		{0x070f, 0x074a, 1},
+		{0x074d, 0x074f, 1},
+	},
+}
+
+var _Tagalog = &RangeTable{
+	R16: []Range16{
+		{0x1700, 0x170c, 1},
+		{0x170e, 0x1714, 1},
+	},
+}
+
+var _Tagbanwa = &RangeTable{
+	R16: []Range16{
+		{0x1760, 0x176c, 1},
+		{0x176e, 0x1770, 1},
+		{0x1772, 0x1773, 1},
+	},
+}
+
+var _Tai_Le = &RangeTable{
+	R16: []Range16{
+		{0x1950, 0x196d, 1},
+		{0x1970, 0x1974, 1},
+	},
+}
+
+var _Tai_Tham = &RangeTable{
+	R16: []Range16{
+		{0x1a20, 0x1a5e, 1},
+		{0x1a60, 0x1a7c, 1},
+		{0x1a7f, 0x1a89, 1},
+		{0x1a90, 0x1a99, 1},
+		{0x1aa0, 0x1aad, 1},
+	},
+}
+
+var _Tai_Viet = &RangeTable{
+	R16: []Range16{
+		{0xaa80, 0xaac2, 1},
+		{0xaadb, 0xaadf, 1},
+	},
+}
+
+var _Takri = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x11680, 0x116b7, 1},
+		{0x116c0, 0x116c9, 1},
+	},
+}
+
+var _Tamil = &RangeTable{
+	R16: []Range16{
+		{0x0b82, 0x0b83, 1},
+		{0x0b85, 0x0b8a, 1},
+		{0x0b8e, 0x0b90, 1},
+		{0x0b92, 0x0b95, 1},
+		{0x0b99, 0x0b9a, 1},
+		{0x0b9c, 0x0b9c, 1},
+		{0x0b9e, 0x0b9f, 1},
+		{0x0ba3, 0x0ba4, 1},
+		{0x0ba8, 0x0baa, 1},
+		{0x0bae, 0x0bb9, 1},
+		{0x0bbe, 0x0bc2, 1},
+		{0x0bc6, 0x0bc8, 1},
+		{0x0bca, 0x0bcd, 1},
+		{0x0bd0, 0x0bd0, 1},
+		{0x0bd7, 0x0bd7, 1},
+		{0x0be6, 0x0bfa, 1},
+	},
+}
+
+var _Telugu = &RangeTable{
+	R16: []Range16{
+		{0x0c01, 0x0c03, 1},
+		{0x0c05, 0x0c0c, 1},
+		{0x0c0e, 0x0c10, 1},
+		{0x0c12, 0x0c28, 1},
+		{0x0c2a, 0x0c33, 1},
+		{0x0c35, 0x0c39, 1},
+		{0x0c3d, 0x0c44, 1},
+		{0x0c46, 0x0c48, 1},
+		{0x0c4a, 0x0c4d, 1},
+		{0x0c55, 0x0c56, 1},
+		{0x0c58, 0x0c59, 1},
+		{0x0c60, 0x0c63, 1},
+		{0x0c66, 0x0c6f, 1},
+		{0x0c78, 0x0c7f, 1},
+	},
+}
+
+var _Thaana = &RangeTable{
+	R16: []Range16{
+		{0x0780, 0x07b1, 1},
+	},
+}
+
+var _Thai = &RangeTable{
+	R16: []Range16{
+		{0x0e01, 0x0e3a, 1},
+		{0x0e40, 0x0e5b, 1},
+	},
+}
+
+var _Tibetan = &RangeTable{
+	R16: []Range16{
+		{0x0f00, 0x0f47, 1},
+		{0x0f49, 0x0f6c, 1},
+		{0x0f71, 0x0f97, 1},
+		{0x0f99, 0x0fbc, 1},
+		{0x0fbe, 0x0fcc, 1},
+		{0x0fce, 0x0fd4, 1},
+		{0x0fd9, 0x0fda, 1},
+	},
+}
+
+var _Tifinagh = &RangeTable{
+	R16: []Range16{
+		{0x2d30, 0x2d67, 1},
+		{0x2d6f, 0x2d70, 1},
+		{0x2d7f, 0x2d7f, 1},
+	},
+}
+
+var _Ugaritic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10380, 0x1039d, 1},
+		{0x1039f, 0x1039f, 1},
+	},
+}
+
+var _Vai = &RangeTable{
+	R16: []Range16{
+		{0xa500, 0xa62b, 1},
+	},
+}
+
+var _Yi = &RangeTable{
+	R16: []Range16{
+		{0xa000, 0xa48c, 1},
+		{0xa490, 0xa4c6, 1},
+	},
+}
+
+// These variables have type *RangeTable.
+var (
+	Arabic                 = _Arabic                 // Arabic is the set of Unicode characters in script Arabic.
+	Armenian               = _Armenian               // Armenian is the set of Unicode characters in script Armenian.
+	Avestan                = _Avestan                // Avestan is the set of Unicode characters in script Avestan.
+	Balinese               = _Balinese               // Balinese is the set of Unicode characters in script Balinese.
+	Bamum                  = _Bamum                  // Bamum is the set of Unicode characters in script Bamum.
+	Batak                  = _Batak                  // Batak is the set of Unicode characters in script Batak.
+	Bengali                = _Bengali                // Bengali is the set of Unicode characters in script Bengali.
+	Bopomofo               = _Bopomofo               // Bopomofo is the set of Unicode characters in script Bopomofo.
+	Brahmi                 = _Brahmi                 // Brahmi is the set of Unicode characters in script Brahmi.
+	Braille                = _Braille                // Braille is the set of Unicode characters in script Braille.
+	Buginese               = _Buginese               // Buginese is the set of Unicode characters in script Buginese.
+	Buhid                  = _Buhid                  // Buhid is the set of Unicode characters in script Buhid.
+	Canadian_Aboriginal    = _Canadian_Aboriginal    // Canadian_Aboriginal is the set of Unicode characters in script Canadian_Aboriginal.
+	Carian                 = _Carian                 // Carian is the set of Unicode characters in script Carian.
+	Chakma                 = _Chakma                 // Chakma is the set of Unicode characters in script Chakma.
+	Cham                   = _Cham                   // Cham is the set of Unicode characters in script Cham.
+	Cherokee               = _Cherokee               // Cherokee is the set of Unicode characters in script Cherokee.
+	Common                 = _Common                 // Common is the set of Unicode characters in script Common.
+	Coptic                 = _Coptic                 // Coptic is the set of Unicode characters in script Coptic.
+	Cuneiform              = _Cuneiform              // Cuneiform is the set of Unicode characters in script Cuneiform.
+	Cypriot                = _Cypriot                // Cypriot is the set of Unicode characters in script Cypriot.
+	Cyrillic               = _Cyrillic               // Cyrillic is the set of Unicode characters in script Cyrillic.
+	Deseret                = _Deseret                // Deseret is the set of Unicode characters in script Deseret.
+	Devanagari             = _Devanagari             // Devanagari is the set of Unicode characters in script Devanagari.
+	Egyptian_Hieroglyphs   = _Egyptian_Hieroglyphs   // Egyptian_Hieroglyphs is the set of Unicode characters in script Egyptian_Hieroglyphs.
+	Ethiopic               = _Ethiopic               // Ethiopic is the set of Unicode characters in script Ethiopic.
+	Georgian               = _Georgian               // Georgian is the set of Unicode characters in script Georgian.
+	Glagolitic             = _Glagolitic             // Glagolitic is the set of Unicode characters in script Glagolitic.
+	Gothic                 = _Gothic                 // Gothic is the set of Unicode characters in script Gothic.
+	Greek                  = _Greek                  // Greek is the set of Unicode characters in script Greek.
+	Gujarati               = _Gujarati               // Gujarati is the set of Unicode characters in script Gujarati.
+	Gurmukhi               = _Gurmukhi               // Gurmukhi is the set of Unicode characters in script Gurmukhi.
+	Han                    = _Han                    // Han is the set of Unicode characters in script Han.
+	Hangul                 = _Hangul                 // Hangul is the set of Unicode characters in script Hangul.
+	Hanunoo                = _Hanunoo                // Hanunoo is the set of Unicode characters in script Hanunoo.
+	Hebrew                 = _Hebrew                 // Hebrew is the set of Unicode characters in script Hebrew.
+	Hiragana               = _Hiragana               // Hiragana is the set of Unicode characters in script Hiragana.
+	Imperial_Aramaic       = _Imperial_Aramaic       // Imperial_Aramaic is the set of Unicode characters in script Imperial_Aramaic.
+	Inherited              = _Inherited              // Inherited is the set of Unicode characters in script Inherited.
+	Inscriptional_Pahlavi  = _Inscriptional_Pahlavi  // Inscriptional_Pahlavi is the set of Unicode characters in script Inscriptional_Pahlavi.
+	Inscriptional_Parthian = _Inscriptional_Parthian // Inscriptional_Parthian is the set of Unicode characters in script Inscriptional_Parthian.
+	Javanese               = _Javanese               // Javanese is the set of Unicode characters in script Javanese.
+	Kaithi                 = _Kaithi                 // Kaithi is the set of Unicode characters in script Kaithi.
+	Kannada                = _Kannada                // Kannada is the set of Unicode characters in script Kannada.
+	Katakana               = _Katakana               // Katakana is the set of Unicode characters in script Katakana.
+	Kayah_Li               = _Kayah_Li               // Kayah_Li is the set of Unicode characters in script Kayah_Li.
+	Kharoshthi             = _Kharoshthi             // Kharoshthi is the set of Unicode characters in script Kharoshthi.
+	Khmer                  = _Khmer                  // Khmer is the set of Unicode characters in script Khmer.
+	Lao                    = _Lao                    // Lao is the set of Unicode characters in script Lao.
+	Latin                  = _Latin                  // Latin is the set of Unicode characters in script Latin.
+	Lepcha                 = _Lepcha                 // Lepcha is the set of Unicode characters in script Lepcha.
+	Limbu                  = _Limbu                  // Limbu is the set of Unicode characters in script Limbu.
+	Linear_B               = _Linear_B               // Linear_B is the set of Unicode characters in script Linear_B.
+	Lisu                   = _Lisu                   // Lisu is the set of Unicode characters in script Lisu.
+	Lycian                 = _Lycian                 // Lycian is the set of Unicode characters in script Lycian.
+	Lydian                 = _Lydian                 // Lydian is the set of Unicode characters in script Lydian.
+	Malayalam              = _Malayalam              // Malayalam is the set of Unicode characters in script Malayalam.
+	Mandaic                = _Mandaic                // Mandaic is the set of Unicode characters in script Mandaic.
+	Meetei_Mayek           = _Meetei_Mayek           // Meetei_Mayek is the set of Unicode characters in script Meetei_Mayek.
+	Meroitic_Cursive       = _Meroitic_Cursive       // Meroitic_Cursive is the set of Unicode characters in script Meroitic_Cursive.
+	Meroitic_Hieroglyphs   = _Meroitic_Hieroglyphs   // Meroitic_Hieroglyphs is the set of Unicode characters in script Meroitic_Hieroglyphs.
+	Miao                   = _Miao                   // Miao is the set of Unicode characters in script Miao.
+	Mongolian              = _Mongolian              // Mongolian is the set of Unicode characters in script Mongolian.
+	Myanmar                = _Myanmar                // Myanmar is the set of Unicode characters in script Myanmar.
+	New_Tai_Lue            = _New_Tai_Lue            // New_Tai_Lue is the set of Unicode characters in script New_Tai_Lue.
+	Nko                    = _Nko                    // Nko is the set of Unicode characters in script Nko.
+	Ogham                  = _Ogham                  // Ogham is the set of Unicode characters in script Ogham.
+	Ol_Chiki               = _Ol_Chiki               // Ol_Chiki is the set of Unicode characters in script Ol_Chiki.
+	Old_Italic             = _Old_Italic             // Old_Italic is the set of Unicode characters in script Old_Italic.
+	Old_Persian            = _Old_Persian            // Old_Persian is the set of Unicode characters in script Old_Persian.
+	Old_South_Arabian      = _Old_South_Arabian      // Old_South_Arabian is the set of Unicode characters in script Old_South_Arabian.
+	Old_Turkic             = _Old_Turkic             // Old_Turkic is the set of Unicode characters in script Old_Turkic.
+	Oriya                  = _Oriya                  // Oriya is the set of Unicode characters in script Oriya.
+	Osmanya                = _Osmanya                // Osmanya is the set of Unicode characters in script Osmanya.
+	Phags_Pa               = _Phags_Pa               // Phags_Pa is the set of Unicode characters in script Phags_Pa.
+	Phoenician             = _Phoenician             // Phoenician is the set of Unicode characters in script Phoenician.
+	Rejang                 = _Rejang                 // Rejang is the set of Unicode characters in script Rejang.
+	Runic                  = _Runic                  // Runic is the set of Unicode characters in script Runic.
+	Samaritan              = _Samaritan              // Samaritan is the set of Unicode characters in script Samaritan.
+	Saurashtra             = _Saurashtra             // Saurashtra is the set of Unicode characters in script Saurashtra.
+	Sharada                = _Sharada                // Sharada is the set of Unicode characters in script Sharada.
+	Shavian                = _Shavian                // Shavian is the set of Unicode characters in script Shavian.
+	Sinhala                = _Sinhala                // Sinhala is the set of Unicode characters in script Sinhala.
+	Sora_Sompeng           = _Sora_Sompeng           // Sora_Sompeng is the set of Unicode characters in script Sora_Sompeng.
+	Sundanese              = _Sundanese              // Sundanese is the set of Unicode characters in script Sundanese.
+	Syloti_Nagri           = _Syloti_Nagri           // Syloti_Nagri is the set of Unicode characters in script Syloti_Nagri.
+	Syriac                 = _Syriac                 // Syriac is the set of Unicode characters in script Syriac.
+	Tagalog                = _Tagalog                // Tagalog is the set of Unicode characters in script Tagalog.
+	Tagbanwa               = _Tagbanwa               // Tagbanwa is the set of Unicode characters in script Tagbanwa.
+	Tai_Le                 = _Tai_Le                 // Tai_Le is the set of Unicode characters in script Tai_Le.
+	Tai_Tham               = _Tai_Tham               // Tai_Tham is the set of Unicode characters in script Tai_Tham.
+	Tai_Viet               = _Tai_Viet               // Tai_Viet is the set of Unicode characters in script Tai_Viet.
+	Takri                  = _Takri                  // Takri is the set of Unicode characters in script Takri.
+	Tamil                  = _Tamil                  // Tamil is the set of Unicode characters in script Tamil.
+	Telugu                 = _Telugu                 // Telugu is the set of Unicode characters in script Telugu.
+	Thaana                 = _Thaana                 // Thaana is the set of Unicode characters in script Thaana.
+	Thai                   = _Thai                   // Thai is the set of Unicode characters in script Thai.
+	Tibetan                = _Tibetan                // Tibetan is the set of Unicode characters in script Tibetan.
+	Tifinagh               = _Tifinagh               // Tifinagh is the set of Unicode characters in script Tifinagh.
+	Ugaritic               = _Ugaritic               // Ugaritic is the set of Unicode characters in script Ugaritic.
+	Vai                    = _Vai                    // Vai is the set of Unicode characters in script Vai.
+	Yi                     = _Yi                     // Yi is the set of Unicode characters in script Yi.
+)
+
+// Generated by running
+//	maketables --props=all --url=http://www.unicode.org/Public/6.3.0/ucd/
+// DO NOT EDIT
+
+// Properties is the set of Unicode property tables.
+var Properties = map[string]*RangeTable{
+	"ASCII_Hex_Digit":                    ASCII_Hex_Digit,
+	"Bidi_Control":                       Bidi_Control,
+	"Dash":                               Dash,
+	"Deprecated":                         Deprecated,
+	"Diacritic":                          Diacritic,
+	"Extender":                           Extender,
+	"Hex_Digit":                          Hex_Digit,
+	"Hyphen":                             Hyphen,
+	"IDS_Binary_Operator":                IDS_Binary_Operator,
+	"IDS_Trinary_Operator":               IDS_Trinary_Operator,
+	"Ideographic":                        Ideographic,
+	"Join_Control":                       Join_Control,
+	"Logical_Order_Exception":            Logical_Order_Exception,
+	"Noncharacter_Code_Point":            Noncharacter_Code_Point,
+	"Other_Alphabetic":                   Other_Alphabetic,
+	"Other_Default_Ignorable_Code_Point": Other_Default_Ignorable_Code_Point,
+	"Other_Grapheme_Extend":              Other_Grapheme_Extend,
+	"Other_ID_Continue":                  Other_ID_Continue,
+	"Other_ID_Start":                     Other_ID_Start,
+	"Other_Lowercase":                    Other_Lowercase,
+	"Other_Math":                         Other_Math,
+	"Other_Uppercase":                    Other_Uppercase,
+	"Pattern_Syntax":                     Pattern_Syntax,
+	"Pattern_White_Space":                Pattern_White_Space,
+	"Quotation_Mark":                     Quotation_Mark,
+	"Radical":                            Radical,
+	"STerm":                              STerm,
+	"Soft_Dotted":                        Soft_Dotted,
+	"Terminal_Punctuation":               Terminal_Punctuation,
+	"Unified_Ideograph":                  Unified_Ideograph,
+	"Variation_Selector":                 Variation_Selector,
+	"White_Space":                        White_Space,
+}
+
+var _ASCII_Hex_Digit = &RangeTable{
+	R16: []Range16{
+		{0x0030, 0x0039, 1},
+		{0x0041, 0x0046, 1},
+		{0x0061, 0x0066, 1},
+	},
+	LatinOffset: 3,
+}
+
+var _Bidi_Control = &RangeTable{
+	R16: []Range16{
+		{0x061c, 0x061c, 1},
+		{0x200e, 0x200f, 1},
+		{0x202a, 0x202e, 1},
+		{0x2066, 0x2069, 1},
+	},
+}
+
+var _Dash = &RangeTable{
+	R16: []Range16{
+		{0x002d, 0x002d, 1},
+		{0x058a, 0x058a, 1},
+		{0x05be, 0x05be, 1},
+		{0x1400, 0x1400, 1},
+		{0x1806, 0x1806, 1},
+		{0x2010, 0x2015, 1},
+		{0x2053, 0x2053, 1},
+		{0x207b, 0x207b, 1},
+		{0x208b, 0x208b, 1},
+		{0x2212, 0x2212, 1},
+		{0x2e17, 0x2e17, 1},
+		{0x2e1a, 0x2e1a, 1},
+		{0x2e3a, 0x2e3b, 1},
+		{0x301c, 0x301c, 1},
+		{0x3030, 0x3030, 1},
+		{0x30a0, 0x30a0, 1},
+		{0xfe31, 0xfe32, 1},
+		{0xfe58, 0xfe58, 1},
+		{0xfe63, 0xfe63, 1},
+		{0xff0d, 0xff0d, 1},
+	},
+	LatinOffset: 1,
+}
+
+var _Deprecated = &RangeTable{
+	R16: []Range16{
+		{0x0149, 0x0149, 1},
+		{0x0673, 0x0673, 1},
+		{0x0f77, 0x0f77, 1},
+		{0x0f79, 0x0f79, 1},
+		{0x17a3, 0x17a4, 1},
+		{0x206a, 0x206f, 1},
+		{0x2329, 0x232a, 1},
+	},
+	R32: []Range32{
+		{0xe0001, 0xe0001, 1},
+		{0xe0020, 0xe007f, 1},
+	},
+}
+
+var _Diacritic = &RangeTable{
+	R16: []Range16{
+		{0x005e, 0x005e, 1},
+		{0x0060, 0x0060, 1},
+		{0x00a8, 0x00a8, 1},
+		{0x00af, 0x00af, 1},
+		{0x00b4, 0x00b4, 1},
+		{0x00b7, 0x00b8, 1},
+		{0x02b0, 0x034e, 1},
+		{0x0350, 0x0357, 1},
+		{0x035d, 0x0362, 1},
+		{0x0374, 0x0375, 1},
+		{0x037a, 0x037a, 1},
+		{0x0384, 0x0385, 1},
+		{0x0483, 0x0487, 1},
+		{0x0559, 0x0559, 1},
+		{0x0591, 0x05a1, 1},
+		{0x05a3, 0x05bd, 1},
+		{0x05bf, 0x05bf, 1},
+		{0x05c1, 0x05c2, 1},
+		{0x05c4, 0x05c4, 1},
+		{0x064b, 0x0652, 1},
+		{0x0657, 0x0658, 1},
+		{0x06df, 0x06e0, 1},
+		{0x06e5, 0x06e6, 1},
+		{0x06ea, 0x06ec, 1},
+		{0x0730, 0x074a, 1},
+		{0x07a6, 0x07b0, 1},
+		{0x07eb, 0x07f5, 1},
+		{0x0818, 0x0819, 1},
+		{0x08e4, 0x08fe, 1},
+		{0x093c, 0x093c, 1},
+		{0x094d, 0x094d, 1},
+		{0x0951, 0x0954, 1},
+		{0x0971, 0x0971, 1},
+		{0x09bc, 0x09bc, 1},
+		{0x09cd, 0x09cd, 1},
+		{0x0a3c, 0x0a3c, 1},
+		{0x0a4d, 0x0a4d, 1},
+		{0x0abc, 0x0abc, 1},
+		{0x0acd, 0x0acd, 1},
+		{0x0b3c, 0x0b3c, 1},
+		{0x0b4d, 0x0b4d, 1},
+		{0x0bcd, 0x0bcd, 1},
+		{0x0c4d, 0x0c4d, 1},
+		{0x0cbc, 0x0cbc, 1},
+		{0x0ccd, 0x0ccd, 1},
+		{0x0d4d, 0x0d4d, 1},
+		{0x0dca, 0x0dca, 1},
+		{0x0e47, 0x0e4c, 1},
+		{0x0e4e, 0x0e4e, 1},
+		{0x0ec8, 0x0ecc, 1},
+		{0x0f18, 0x0f19, 1},
+		{0x0f35, 0x0f35, 1},
+		{0x0f37, 0x0f37, 1},
+		{0x0f39, 0x0f39, 1},
+		{0x0f3e, 0x0f3f, 1},
+		{0x0f82, 0x0f84, 1},
+		{0x0f86, 0x0f87, 1},
+		{0x0fc6, 0x0fc6, 1},
+		{0x1037, 0x1037, 1},
+		{0x1039, 0x103a, 1},
+		{0x1087, 0x108d, 1},
+		{0x108f, 0x108f, 1},
+		{0x109a, 0x109b, 1},
+		{0x17c9, 0x17d3, 1},
+		{0x17dd, 0x17dd, 1},
+		{0x1939, 0x193b, 1},
+		{0x1a75, 0x1a7c, 1},
+		{0x1a7f, 0x1a7f, 1},
+		{0x1b34, 0x1b34, 1},
+		{0x1b44, 0x1b44, 1},
+		{0x1b6b, 0x1b73, 1},
+		{0x1baa, 0x1bab, 1},
+		{0x1c36, 0x1c37, 1},
+		{0x1c78, 0x1c7d, 1},
+		{0x1cd0, 0x1ce8, 1},
+		{0x1ced, 0x1ced, 1},
+		{0x1cf4, 0x1cf4, 1},
+		{0x1d2c, 0x1d6a, 1},
+		{0x1dc4, 0x1dcf, 1},
+		{0x1dfd, 0x1dff, 1},
+		{0x1fbd, 0x1fbd, 1},
+		{0x1fbf, 0x1fc1, 1},
+		{0x1fcd, 0x1fcf, 1},
+		{0x1fdd, 0x1fdf, 1},
+		{0x1fed, 0x1fef, 1},
+		{0x1ffd, 0x1ffe, 1},
+		{0x2cef, 0x2cf1, 1},
+		{0x2e2f, 0x2e2f, 1},
+		{0x302a, 0x302f, 1},
+		{0x3099, 0x309c, 1},
+		{0x30fc, 0x30fc, 1},
+		{0xa66f, 0xa66f, 1},
+		{0xa67c, 0xa67d, 1},
+		{0xa67f, 0xa67f, 1},
+		{0xa6f0, 0xa6f1, 1},
+		{0xa717, 0xa721, 1},
+		{0xa788, 0xa788, 1},
+		{0xa7f8, 0xa7f9, 1},
+		{0xa8c4, 0xa8c4, 1},
+		{0xa8e0, 0xa8f1, 1},
+		{0xa92b, 0xa92e, 1},
+		{0xa953, 0xa953, 1},
+		{0xa9b3, 0xa9b3, 1},
+		{0xa9c0, 0xa9c0, 1},
+		{0xaa7b, 0xaa7b, 1},
+		{0xaabf, 0xaac2, 1},
+		{0xaaf6, 0xaaf6, 1},
+		{0xabec, 0xabed, 1},
+		{0xfb1e, 0xfb1e, 1},
+		{0xfe20, 0xfe26, 1},
+		{0xff3e, 0xff3e, 1},
+		{0xff40, 0xff40, 1},
+		{0xff70, 0xff70, 1},
+		{0xff9e, 0xff9f, 1},
+		{0xffe3, 0xffe3, 1},
+	},
+	R32: []Range32{
+		{0x110b9, 0x110ba, 1},
+		{0x11133, 0x11134, 1},
+		{0x111c0, 0x111c0, 1},
+		{0x116b6, 0x116b7, 1},
+		{0x16f8f, 0x16f9f, 1},
+		{0x1d167, 0x1d169, 1},
+		{0x1d16d, 0x1d172, 1},
+		{0x1d17b, 0x1d182, 1},
+		{0x1d185, 0x1d18b, 1},
+		{0x1d1aa, 0x1d1ad, 1},
+	},
+	LatinOffset: 6,
+}
+
+var _Extender = &RangeTable{
+	R16: []Range16{
+		{0x00b7, 0x00b7, 1},
+		{0x02d0, 0x02d1, 1},
+		{0x0640, 0x0640, 1},
+		{0x07fa, 0x07fa, 1},
+		{0x0e46, 0x0e46, 1},
+		{0x0ec6, 0x0ec6, 1},
+		{0x180a, 0x180a, 1},
+		{0x1843, 0x1843, 1},
+		{0x1aa7, 0x1aa7, 1},
+		{0x1c36, 0x1c36, 1},
+		{0x1c7b, 0x1c7b, 1},
+		{0x3005, 0x3005, 1},
+		{0x3031, 0x3035, 1},
+		{0x309d, 0x309e, 1},
+		{0x30fc, 0x30fe, 1},
+		{0xa015, 0xa015, 1},
+		{0xa60c, 0xa60c, 1},
+		{0xa9cf, 0xa9cf, 1},
+		{0xaa70, 0xaa70, 1},
+		{0xaadd, 0xaadd, 1},
+		{0xaaf3, 0xaaf4, 1},
+		{0xff70, 0xff70, 1},
+	},
+	LatinOffset: 1,
+}
+
+var _Hex_Digit = &RangeTable{
+	R16: []Range16{
+		{0x0030, 0x0039, 1},
+		{0x0041, 0x0046, 1},
+		{0x0061, 0x0066, 1},
+		{0xff10, 0xff19, 1},
+		{0xff21, 0xff26, 1},
+		{0xff41, 0xff46, 1},
+	},
+	LatinOffset: 3,
+}
+
+var _Hyphen = &RangeTable{
+	R16: []Range16{
+		{0x002d, 0x002d, 1},
+		{0x00ad, 0x00ad, 1},
+		{0x058a, 0x058a, 1},
+		{0x1806, 0x1806, 1},
+		{0x2010, 0x2011, 1},
+		{0x2e17, 0x2e17, 1},
+		{0x30fb, 0x30fb, 1},
+		{0xfe63, 0xfe63, 1},
+		{0xff0d, 0xff0d, 1},
+		{0xff65, 0xff65, 1},
+	},
+	LatinOffset: 2,
+}
+
+var _IDS_Binary_Operator = &RangeTable{
+	R16: []Range16{
+		{0x2ff0, 0x2ff1, 1},
+		{0x2ff4, 0x2ffb, 1},
+	},
+}
+
+var _IDS_Trinary_Operator = &RangeTable{
+	R16: []Range16{
+		{0x2ff2, 0x2ff3, 1},
+	},
+}
+
+var _Ideographic = &RangeTable{
+	R16: []Range16{
+		{0x3006, 0x3007, 1},
+		{0x3021, 0x3029, 1},
+		{0x3038, 0x303a, 1},
+		{0x3400, 0x4db5, 1},
+		{0x4e00, 0x9fcc, 1},
+		{0xf900, 0xfa6d, 1},
+		{0xfa70, 0xfad9, 1},
+	},
+	R32: []Range32{
+		{0x20000, 0x2a6d6, 1},
+		{0x2a700, 0x2b734, 1},
+		{0x2b740, 0x2b81d, 1},
+		{0x2f800, 0x2fa1d, 1},
+	},
+}
+
+var _Join_Control = &RangeTable{
+	R16: []Range16{
+		{0x200c, 0x200d, 1},
+	},
+}
+
+var _Logical_Order_Exception = &RangeTable{
+	R16: []Range16{
+		{0x0e40, 0x0e44, 1},
+		{0x0ec0, 0x0ec4, 1},
+		{0xaab5, 0xaab6, 1},
+		{0xaab9, 0xaab9, 1},
+		{0xaabb, 0xaabc, 1},
+	},
+}
+
+var _Noncharacter_Code_Point = &RangeTable{
+	R16: []Range16{
+		{0xfdd0, 0xfdef, 1},
+		{0xfffe, 0xffff, 1},
+	},
+	R32: []Range32{
+		{0x1fffe, 0x1ffff, 1},
+		{0x2fffe, 0x2ffff, 1},
+		{0x3fffe, 0x3ffff, 1},
+		{0x4fffe, 0x4ffff, 1},
+		{0x5fffe, 0x5ffff, 1},
+		{0x6fffe, 0x6ffff, 1},
+		{0x7fffe, 0x7ffff, 1},
+		{0x8fffe, 0x8ffff, 1},
+		{0x9fffe, 0x9ffff, 1},
+		{0xafffe, 0xaffff, 1},
+		{0xbfffe, 0xbffff, 1},
+		{0xcfffe, 0xcffff, 1},
+		{0xdfffe, 0xdffff, 1},
+		{0xefffe, 0xeffff, 1},
+		{0xffffe, 0xfffff, 1},
+		{0x10fffe, 0x10ffff, 1},
+	},
+}
+
+var _Other_Alphabetic = &RangeTable{
+	R16: []Range16{
+		{0x0345, 0x0345, 1},
+		{0x05b0, 0x05bd, 1},
+		{0x05bf, 0x05bf, 1},
+		{0x05c1, 0x05c2, 1},
+		{0x05c4, 0x05c5, 1},
+		{0x05c7, 0x05c7, 1},
+		{0x0610, 0x061a, 1},
+		{0x064b, 0x0657, 1},
+		{0x0659, 0x065f, 1},
+		{0x0670, 0x0670, 1},
+		{0x06d6, 0x06dc, 1},
+		{0x06e1, 0x06e4, 1},
+		{0x06e7, 0x06e8, 1},
+		{0x06ed, 0x06ed, 1},
+		{0x0711, 0x0711, 1},
+		{0x0730, 0x073f, 1},
+		{0x07a6, 0x07b0, 1},
+		{0x0816, 0x0817, 1},
+		{0x081b, 0x0823, 1},
+		{0x0825, 0x0827, 1},
+		{0x0829, 0x082c, 1},
+		{0x08e4, 0x08e9, 1},
+		{0x08f0, 0x08fe, 1},
+		{0x0900, 0x0903, 1},
+		{0x093a, 0x093b, 1},
+		{0x093e, 0x094c, 1},
+		{0x094e, 0x094f, 1},
+		{0x0955, 0x0957, 1},
+		{0x0962, 0x0963, 1},
+		{0x0981, 0x0983, 1},
+		{0x09be, 0x09c4, 1},
+		{0x09c7, 0x09c8, 1},
+		{0x09cb, 0x09cc, 1},
+		{0x09d7, 0x09d7, 1},
+		{0x09e2, 0x09e3, 1},
+		{0x0a01, 0x0a03, 1},
+		{0x0a3e, 0x0a42, 1},
+		{0x0a47, 0x0a48, 1},
+		{0x0a4b, 0x0a4c, 1},
+		{0x0a51, 0x0a51, 1},
+		{0x0a70, 0x0a71, 1},
+		{0x0a75, 0x0a75, 1},
+		{0x0a81, 0x0a83, 1},
+		{0x0abe, 0x0ac5, 1},
+		{0x0ac7, 0x0ac9, 1},
+		{0x0acb, 0x0acc, 1},
+		{0x0ae2, 0x0ae3, 1},
+		{0x0b01, 0x0b03, 1},
+		{0x0b3e, 0x0b44, 1},
+		{0x0b47, 0x0b48, 1},
+		{0x0b4b, 0x0b4c, 1},
+		{0x0b56, 0x0b57, 1},
+		{0x0b62, 0x0b63, 1},
+		{0x0b82, 0x0b82, 1},
+		{0x0bbe, 0x0bc2, 1},
+		{0x0bc6, 0x0bc8, 1},
+		{0x0bca, 0x0bcc, 1},
+		{0x0bd7, 0x0bd7, 1},
+		{0x0c01, 0x0c03, 1},
+		{0x0c3e, 0x0c44, 1},
+		{0x0c46, 0x0c48, 1},
+		{0x0c4a, 0x0c4c, 1},
+		{0x0c55, 0x0c56, 1},
+		{0x0c62, 0x0c63, 1},
+		{0x0c82, 0x0c83, 1},
+		{0x0cbe, 0x0cc4, 1},
+		{0x0cc6, 0x0cc8, 1},
+		{0x0cca, 0x0ccc, 1},
+		{0x0cd5, 0x0cd6, 1},
+		{0x0ce2, 0x0ce3, 1},
+		{0x0d02, 0x0d03, 1},
+		{0x0d3e, 0x0d44, 1},
+		{0x0d46, 0x0d48, 1},
+		{0x0d4a, 0x0d4c, 1},
+		{0x0d57, 0x0d57, 1},
+		{0x0d62, 0x0d63, 1},
+		{0x0d82, 0x0d83, 1},
+		{0x0dcf, 0x0dd4, 1},
+		{0x0dd6, 0x0dd6, 1},
+		{0x0dd8, 0x0ddf, 1},
+		{0x0df2, 0x0df3, 1},
+		{0x0e31, 0x0e31, 1},
+		{0x0e34, 0x0e3a, 1},
+		{0x0e4d, 0x0e4d, 1},
+		{0x0eb1, 0x0eb1, 1},
+		{0x0eb4, 0x0eb9, 1},
+		{0x0ebb, 0x0ebc, 1},
+		{0x0ecd, 0x0ecd, 1},
+		{0x0f71, 0x0f81, 1},
+		{0x0f8d, 0x0f97, 1},
+		{0x0f99, 0x0fbc, 1},
+		{0x102b, 0x1036, 1},
+		{0x1038, 0x1038, 1},
+		{0x103b, 0x103e, 1},
+		{0x1056, 0x1059, 1},
+		{0x105e, 0x1060, 1},
+		{0x1062, 0x1062, 1},
+		{0x1067, 0x1068, 1},
+		{0x1071, 0x1074, 1},
+		{0x1082, 0x1086, 1},
+		{0x109c, 0x109d, 1},
+		{0x135f, 0x135f, 1},
+		{0x1712, 0x1713, 1},
+		{0x1732, 0x1733, 1},
+		{0x1752, 0x1753, 1},
+		{0x1772, 0x1773, 1},
+		{0x17b6, 0x17c8, 1},
+		{0x18a9, 0x18a9, 1},
+		{0x1920, 0x192b, 1},
+		{0x1930, 0x1938, 1},
+		{0x19b0, 0x19c0, 1},
+		{0x19c8, 0x19c9, 1},
+		{0x1a17, 0x1a1b, 1},
+		{0x1a55, 0x1a5e, 1},
+		{0x1a61, 0x1a74, 1},
+		{0x1b00, 0x1b04, 1},
+		{0x1b35, 0x1b43, 1},
+		{0x1b80, 0x1b82, 1},
+		{0x1ba1, 0x1ba9, 1},
+		{0x1bac, 0x1bad, 1},
+		{0x1be7, 0x1bf1, 1},
+		{0x1c24, 0x1c35, 1},
+		{0x1cf2, 0x1cf3, 1},
+		{0x24b6, 0x24e9, 1},
+		{0x2de0, 0x2dff, 1},
+		{0xa674, 0xa67b, 1},
+		{0xa69f, 0xa69f, 1},
+		{0xa823, 0xa827, 1},
+		{0xa880, 0xa881, 1},
+		{0xa8b4, 0xa8c3, 1},
+		{0xa926, 0xa92a, 1},
+		{0xa947, 0xa952, 1},
+		{0xa980, 0xa983, 1},
+		{0xa9b4, 0xa9bf, 1},
+		{0xaa29, 0xaa36, 1},
+		{0xaa43, 0xaa43, 1},
+		{0xaa4c, 0xaa4d, 1},
+		{0xaab0, 0xaab0, 1},
+		{0xaab2, 0xaab4, 1},
+		{0xaab7, 0xaab8, 1},
+		{0xaabe, 0xaabe, 1},
+		{0xaaeb, 0xaaef, 1},
+		{0xaaf5, 0xaaf5, 1},
+		{0xabe3, 0xabea, 1},
+		{0xfb1e, 0xfb1e, 1},
+	},
+	R32: []Range32{
+		{0x10a01, 0x10a03, 1},
+		{0x10a05, 0x10a06, 1},
+		{0x10a0c, 0x10a0f, 1},
+		{0x11000, 0x11002, 1},
+		{0x11038, 0x11045, 1},
+		{0x11082, 0x11082, 1},
+		{0x110b0, 0x110b8, 1},
+		{0x11100, 0x11102, 1},
+		{0x11127, 0x11132, 1},
+		{0x11180, 0x11182, 1},
+		{0x111b3, 0x111bf, 1},
+		{0x116ab, 0x116b5, 1},
+		{0x16f51, 0x16f7e, 1},
+	},
+}
+
+var _Other_Default_Ignorable_Code_Point = &RangeTable{
+	R16: []Range16{
+		{0x034f, 0x034f, 1},
+		{0x115f, 0x1160, 1},
+		{0x17b4, 0x17b5, 1},
+		{0x2065, 0x2065, 1},
+		{0x3164, 0x3164, 1},
+		{0xffa0, 0xffa0, 1},
+		{0xfff0, 0xfff8, 1},
+	},
+	R32: []Range32{
+		{0xe0000, 0xe0000, 1},
+		{0xe0002, 0xe001f, 1},
+		{0xe0080, 0xe00ff, 1},
+		{0xe01f0, 0xe0fff, 1},
+	},
+}
+
+var _Other_Grapheme_Extend = &RangeTable{
+	R16: []Range16{
+		{0x09be, 0x09be, 1},
+		{0x09d7, 0x09d7, 1},
+		{0x0b3e, 0x0b3e, 1},
+		{0x0b57, 0x0b57, 1},
+		{0x0bbe, 0x0bbe, 1},
+		{0x0bd7, 0x0bd7, 1},
+		{0x0cc2, 0x0cc2, 1},
+		{0x0cd5, 0x0cd6, 1},
+		{0x0d3e, 0x0d3e, 1},
+		{0x0d57, 0x0d57, 1},
+		{0x0dcf, 0x0dcf, 1},
+		{0x0ddf, 0x0ddf, 1},
+		{0x200c, 0x200d, 1},
+		{0x302e, 0x302f, 1},
+		{0xff9e, 0xff9f, 1},
+	},
+	R32: []Range32{
+		{0x1d165, 0x1d165, 1},
+		{0x1d16e, 0x1d172, 1},
+	},
+}
+
+var _Other_ID_Continue = &RangeTable{
+	R16: []Range16{
+		{0x00b7, 0x00b7, 1},
+		{0x0387, 0x0387, 1},
+		{0x1369, 0x1371, 1},
+		{0x19da, 0x19da, 1},
+	},
+	LatinOffset: 1,
+}
+
+var _Other_ID_Start = &RangeTable{
+	R16: []Range16{
+		{0x2118, 0x2118, 1},
+		{0x212e, 0x212e, 1},
+		{0x309b, 0x309c, 1},
+	},
+}
+
+var _Other_Lowercase = &RangeTable{
+	R16: []Range16{
+		{0x00aa, 0x00aa, 1},
+		{0x00ba, 0x00ba, 1},
+		{0x02b0, 0x02b8, 1},
+		{0x02c0, 0x02c1, 1},
+		{0x02e0, 0x02e4, 1},
+		{0x0345, 0x0345, 1},
+		{0x037a, 0x037a, 1},
+		{0x1d2c, 0x1d6a, 1},
+		{0x1d78, 0x1d78, 1},
+		{0x1d9b, 0x1dbf, 1},
+		{0x2071, 0x2071, 1},
+		{0x207f, 0x207f, 1},
+		{0x2090, 0x209c, 1},
+		{0x2170, 0x217f, 1},
+		{0x24d0, 0x24e9, 1},
+		{0x2c7c, 0x2c7d, 1},
+		{0xa770, 0xa770, 1},
+		{0xa7f8, 0xa7f9, 1},
+	},
+	LatinOffset: 2,
+}
+
+var _Other_Math = &RangeTable{
+	R16: []Range16{
+		{0x005e, 0x005e, 1},
+		{0x03d0, 0x03d2, 1},
+		{0x03d5, 0x03d5, 1},
+		{0x03f0, 0x03f1, 1},
+		{0x03f4, 0x03f5, 1},
+		{0x2016, 0x2016, 1},
+		{0x2032, 0x2034, 1},
+		{0x2040, 0x2040, 1},
+		{0x2061, 0x2064, 1},
+		{0x207d, 0x207e, 1},
+		{0x208d, 0x208e, 1},
+		{0x20d0, 0x20dc, 1},
+		{0x20e1, 0x20e1, 1},
+		{0x20e5, 0x20e6, 1},
+		{0x20eb, 0x20ef, 1},
+		{0x2102, 0x2102, 1},
+		{0x2107, 0x2107, 1},
+		{0x210a, 0x2113, 1},
+		{0x2115, 0x2115, 1},
+		{0x2119, 0x211d, 1},
+		{0x2124, 0x2124, 1},
+		{0x2128, 0x2129, 1},
+		{0x212c, 0x212d, 1},
+		{0x212f, 0x2131, 1},
+		{0x2133, 0x2138, 1},
+		{0x213c, 0x213f, 1},
+		{0x2145, 0x2149, 1},
+		{0x2195, 0x2199, 1},
+		{0x219c, 0x219f, 1},
+		{0x21a1, 0x21a2, 1},
+		{0x21a4, 0x21a5, 1},
+		{0x21a7, 0x21a7, 1},
+		{0x21a9, 0x21ad, 1},
+		{0x21b0, 0x21b1, 1},
+		{0x21b6, 0x21b7, 1},
+		{0x21bc, 0x21cd, 1},
+		{0x21d0, 0x21d1, 1},
+		{0x21d3, 0x21d3, 1},
+		{0x21d5, 0x21db, 1},
+		{0x21dd, 0x21dd, 1},
+		{0x21e4, 0x21e5, 1},
+		{0x2308, 0x230b, 1},
+		{0x23b4, 0x23b5, 1},
+		{0x23b7, 0x23b7, 1},
+		{0x23d0, 0x23d0, 1},
+		{0x23e2, 0x23e2, 1},
+		{0x25a0, 0x25a1, 1},
+		{0x25ae, 0x25b6, 1},
+		{0x25bc, 0x25c0, 1},
+		{0x25c6, 0x25c7, 1},
+		{0x25ca, 0x25cb, 1},
+		{0x25cf, 0x25d3, 1},
+		{0x25e2, 0x25e2, 1},
+		{0x25e4, 0x25e4, 1},
+		{0x25e7, 0x25ec, 1},
+		{0x2605, 0x2606, 1},
+		{0x2640, 0x2640, 1},
+		{0x2642, 0x2642, 1},
+		{0x2660, 0x2663, 1},
+		{0x266d, 0x266e, 1},
+		{0x27c5, 0x27c6, 1},
+		{0x27e6, 0x27ef, 1},
+		{0x2983, 0x2998, 1},
+		{0x29d8, 0x29db, 1},
+		{0x29fc, 0x29fd, 1},
+		{0xfe61, 0xfe61, 1},
+		{0xfe63, 0xfe63, 1},
+		{0xfe68, 0xfe68, 1},
+		{0xff3c, 0xff3c, 1},
+		{0xff3e, 0xff3e, 1},
+	},
+	R32: []Range32{
+		{0x1d400, 0x1d454, 1},
+		{0x1d456, 0x1d49c, 1},
+		{0x1d49e, 0x1d49f, 1},
+		{0x1d4a2, 0x1d4a2, 1},
+		{0x1d4a5, 0x1d4a6, 1},
+		{0x1d4a9, 0x1d4ac, 1},
+		{0x1d4ae, 0x1d4b9, 1},
+		{0x1d4bb, 0x1d4bb, 1},
+		{0x1d4bd, 0x1d4c3, 1},
+		{0x1d4c5, 0x1d505, 1},
+		{0x1d507, 0x1d50a, 1},
+		{0x1d50d, 0x1d514, 1},
+		{0x1d516, 0x1d51c, 1},
+		{0x1d51e, 0x1d539, 1},
+		{0x1d53b, 0x1d53e, 1},
+		{0x1d540, 0x1d544, 1},
+		{0x1d546, 0x1d546, 1},
+		{0x1d54a, 0x1d550, 1},
+		{0x1d552, 0x1d6a5, 1},
+		{0x1d6a8, 0x1d6c0, 1},
+		{0x1d6c2, 0x1d6da, 1},
+		{0x1d6dc, 0x1d6fa, 1},
+		{0x1d6fc, 0x1d714, 1},
+		{0x1d716, 0x1d734, 1},
+		{0x1d736, 0x1d74e, 1},
+		{0x1d750, 0x1d76e, 1},
+		{0x1d770, 0x1d788, 1},
+		{0x1d78a, 0x1d7a8, 1},
+		{0x1d7aa, 0x1d7c2, 1},
+		{0x1d7c4, 0x1d7cb, 1},
+		{0x1d7ce, 0x1d7ff, 1},
+		{0x1ee00, 0x1ee03, 1},
+		{0x1ee05, 0x1ee1f, 1},
+		{0x1ee21, 0x1ee22, 1},
+		{0x1ee24, 0x1ee24, 1},
+		{0x1ee27, 0x1ee27, 1},
+		{0x1ee29, 0x1ee32, 1},
+		{0x1ee34, 0x1ee37, 1},
+		{0x1ee39, 0x1ee39, 1},
+		{0x1ee3b, 0x1ee3b, 1},
+		{0x1ee42, 0x1ee42, 1},
+		{0x1ee47, 0x1ee47, 1},
+		{0x1ee49, 0x1ee49, 1},
+		{0x1ee4b, 0x1ee4b, 1},
+		{0x1ee4d, 0x1ee4f, 1},
+		{0x1ee51, 0x1ee52, 1},
+		{0x1ee54, 0x1ee54, 1},
+		{0x1ee57, 0x1ee57, 1},
+		{0x1ee59, 0x1ee59, 1},
+		{0x1ee5b, 0x1ee5b, 1},
+		{0x1ee5d, 0x1ee5d, 1},
+		{0x1ee5f, 0x1ee5f, 1},
+		{0x1ee61, 0x1ee62, 1},
+		{0x1ee64, 0x1ee64, 1},
+		{0x1ee67, 0x1ee6a, 1},
+		{0x1ee6c, 0x1ee72, 1},
+		{0x1ee74, 0x1ee77, 1},
+		{0x1ee79, 0x1ee7c, 1},
+		{0x1ee7e, 0x1ee7e, 1},
+		{0x1ee80, 0x1ee89, 1},
+		{0x1ee8b, 0x1ee9b, 1},
+		{0x1eea1, 0x1eea3, 1},
+		{0x1eea5, 0x1eea9, 1},
+		{0x1eeab, 0x1eebb, 1},
+	},
+	LatinOffset: 1,
+}
+
+var _Other_Uppercase = &RangeTable{
+	R16: []Range16{
+		{0x2160, 0x216f, 1},
+		{0x24b6, 0x24cf, 1},
+	},
+}
+
+var _Pattern_Syntax = &RangeTable{
+	R16: []Range16{
+		{0x0021, 0x002f, 1},
+		{0x003a, 0x0040, 1},
+		{0x005b, 0x005e, 1},
+		{0x0060, 0x0060, 1},
+		{0x007b, 0x007e, 1},
+		{0x00a1, 0x00a7, 1},
+		{0x00a9, 0x00a9, 1},
+		{0x00ab, 0x00ac, 1},
+		{0x00ae, 0x00ae, 1},
+		{0x00b0, 0x00b1, 1},
+		{0x00b6, 0x00b6, 1},
+		{0x00bb, 0x00bb, 1},
+		{0x00bf, 0x00bf, 1},
+		{0x00d7, 0x00d7, 1},
+		{0x00f7, 0x00f7, 1},
+		{0x2010, 0x2027, 1},
+		{0x2030, 0x203e, 1},
+		{0x2041, 0x2053, 1},
+		{0x2055, 0x205e, 1},
+		{0x2190, 0x245f, 1},
+		{0x2500, 0x2775, 1},
+		{0x2794, 0x2bff, 1},
+		{0x2e00, 0x2e7f, 1},
+		{0x3001, 0x3003, 1},
+		{0x3008, 0x3020, 1},
+		{0x3030, 0x3030, 1},
+		{0xfd3e, 0xfd3f, 1},
+		{0xfe45, 0xfe46, 1},
+	},
+	LatinOffset: 15,
+}
+
+var _Pattern_White_Space = &RangeTable{
+	R16: []Range16{
+		{0x0009, 0x000d, 1},
+		{0x0020, 0x0020, 1},
+		{0x0085, 0x0085, 1},
+		{0x200e, 0x200f, 1},
+		{0x2028, 0x2029, 1},
+	},
+	LatinOffset: 3,
+}
+
+var _Quotation_Mark = &RangeTable{
+	R16: []Range16{
+		{0x0022, 0x0022, 1},
+		{0x0027, 0x0027, 1},
+		{0x00ab, 0x00ab, 1},
+		{0x00bb, 0x00bb, 1},
+		{0x2018, 0x201f, 1},
+		{0x2039, 0x203a, 1},
+		{0x300c, 0x300f, 1},
+		{0x301d, 0x301f, 1},
+		{0xfe41, 0xfe44, 1},
+		{0xff02, 0xff02, 1},
+		{0xff07, 0xff07, 1},
+		{0xff62, 0xff63, 1},
+	},
+	LatinOffset: 4,
+}
+
+var _Radical = &RangeTable{
+	R16: []Range16{
+		{0x2e80, 0x2e99, 1},
+		{0x2e9b, 0x2ef3, 1},
+		{0x2f00, 0x2fd5, 1},
+	},
+}
+
+var _STerm = &RangeTable{
+	R16: []Range16{
+		{0x0021, 0x0021, 1},
+		{0x002e, 0x002e, 1},
+		{0x003f, 0x003f, 1},
+		{0x055c, 0x055c, 1},
+		{0x055e, 0x055e, 1},
+		{0x0589, 0x0589, 1},
+		{0x061f, 0x061f, 1},
+		{0x06d4, 0x06d4, 1},
+		{0x0700, 0x0702, 1},
+		{0x07f9, 0x07f9, 1},
+		{0x0964, 0x0965, 1},
+		{0x104a, 0x104b, 1},
+		{0x1362, 0x1362, 1},
+		{0x1367, 0x1368, 1},
+		{0x166e, 0x166e, 1},
+		{0x1735, 0x1736, 1},
+		{0x1803, 0x1803, 1},
+		{0x1809, 0x1809, 1},
+		{0x1944, 0x1945, 1},
+		{0x1aa8, 0x1aab, 1},
+		{0x1b5a, 0x1b5b, 1},
+		{0x1b5e, 0x1b5f, 1},
+		{0x1c3b, 0x1c3c, 1},
+		{0x1c7e, 0x1c7f, 1},
+		{0x203c, 0x203d, 1},
+		{0x2047, 0x2049, 1},
+		{0x2e2e, 0x2e2e, 1},
+		{0x3002, 0x3002, 1},
+		{0xa4ff, 0xa4ff, 1},
+		{0xa60e, 0xa60f, 1},
+		{0xa6f3, 0xa6f3, 1},
+		{0xa6f7, 0xa6f7, 1},
+		{0xa876, 0xa877, 1},
+		{0xa8ce, 0xa8cf, 1},
+		{0xa92f, 0xa92f, 1},
+		{0xa9c8, 0xa9c9, 1},
+		{0xaa5d, 0xaa5f, 1},
+		{0xaaf0, 0xaaf1, 1},
+		{0xabeb, 0xabeb, 1},
+		{0xfe52, 0xfe52, 1},
+		{0xfe56, 0xfe57, 1},
+		{0xff01, 0xff01, 1},
+		{0xff0e, 0xff0e, 1},
+		{0xff1f, 0xff1f, 1},
+		{0xff61, 0xff61, 1},
+	},
+	R32: []Range32{
+		{0x10a56, 0x10a57, 1},
+		{0x11047, 0x11048, 1},
+		{0x110be, 0x110c1, 1},
+		{0x11141, 0x11143, 1},
+		{0x111c5, 0x111c6, 1},
+	},
+	LatinOffset: 3,
+}
+
+var _Soft_Dotted = &RangeTable{
+	R16: []Range16{
+		{0x0069, 0x006a, 1},
+		{0x012f, 0x012f, 1},
+		{0x0249, 0x0249, 1},
+		{0x0268, 0x0268, 1},
+		{0x029d, 0x029d, 1},
+		{0x02b2, 0x02b2, 1},
+		{0x03f3, 0x03f3, 1},
+		{0x0456, 0x0456, 1},
+		{0x0458, 0x0458, 1},
+		{0x1d62, 0x1d62, 1},
+		{0x1d96, 0x1d96, 1},
+		{0x1da4, 0x1da4, 1},
+		{0x1da8, 0x1da8, 1},
+		{0x1e2d, 0x1e2d, 1},
+		{0x1ecb, 0x1ecb, 1},
+		{0x2071, 0x2071, 1},
+		{0x2148, 0x2149, 1},
+		{0x2c7c, 0x2c7c, 1},
+	},
+	R32: []Range32{
+		{0x1d422, 0x1d423, 1},
+		{0x1d456, 0x1d457, 1},
+		{0x1d48a, 0x1d48b, 1},
+		{0x1d4be, 0x1d4bf, 1},
+		{0x1d4f2, 0x1d4f3, 1},
+		{0x1d526, 0x1d527, 1},
+		{0x1d55a, 0x1d55b, 1},
+		{0x1d58e, 0x1d58f, 1},
+		{0x1d5c2, 0x1d5c3, 1},
+		{0x1d5f6, 0x1d5f7, 1},
+		{0x1d62a, 0x1d62b, 1},
+		{0x1d65e, 0x1d65f, 1},
+		{0x1d692, 0x1d693, 1},
+	},
+	LatinOffset: 1,
+}
+
+var _Terminal_Punctuation = &RangeTable{
+	R16: []Range16{
+		{0x0021, 0x0021, 1},
+		{0x002c, 0x002c, 1},
+		{0x002e, 0x002e, 1},
+		{0x003a, 0x003b, 1},
+		{0x003f, 0x003f, 1},
+		{0x037e, 0x037e, 1},
+		{0x0387, 0x0387, 1},
+		{0x0589, 0x0589, 1},
+		{0x05c3, 0x05c3, 1},
+		{0x060c, 0x060c, 1},
+		{0x061b, 0x061b, 1},
+		{0x061f, 0x061f, 1},
+		{0x06d4, 0x06d4, 1},
+		{0x0700, 0x070a, 1},
+		{0x070c, 0x070c, 1},
+		{0x07f8, 0x07f9, 1},
+		{0x0830, 0x083e, 1},
+		{0x085e, 0x085e, 1},
+		{0x0964, 0x0965, 1},
+		{0x0e5a, 0x0e5b, 1},
+		{0x0f08, 0x0f08, 1},
+		{0x0f0d, 0x0f12, 1},
+		{0x104a, 0x104b, 1},
+		{0x1361, 0x1368, 1},
+		{0x166d, 0x166e, 1},
+		{0x16eb, 0x16ed, 1},
+		{0x17d4, 0x17d6, 1},
+		{0x17da, 0x17da, 1},
+		{0x1802, 0x1805, 1},
+		{0x1808, 0x1809, 1},
+		{0x1944, 0x1945, 1},
+		{0x1aa8, 0x1aab, 1},
+		{0x1b5a, 0x1b5b, 1},
+		{0x1b5d, 0x1b5f, 1},
+		{0x1c3b, 0x1c3f, 1},
+		{0x1c7e, 0x1c7f, 1},
+		{0x203c, 0x203d, 1},
+		{0x2047, 0x2049, 1},
+		{0x2e2e, 0x2e2e, 1},
+		{0x3001, 0x3002, 1},
+		{0xa4fe, 0xa4ff, 1},
+		{0xa60d, 0xa60f, 1},
+		{0xa6f3, 0xa6f7, 1},
+		{0xa876, 0xa877, 1},
+		{0xa8ce, 0xa8cf, 1},
+		{0xa92f, 0xa92f, 1},
+		{0xa9c7, 0xa9c9, 1},
+		{0xaa5d, 0xaa5f, 1},
+		{0xaadf, 0xaadf, 1},
+		{0xaaf0, 0xaaf1, 1},
+		{0xabeb, 0xabeb, 1},
+		{0xfe50, 0xfe52, 1},
+		{0xfe54, 0xfe57, 1},
+		{0xff01, 0xff01, 1},
+		{0xff0c, 0xff0c, 1},
+		{0xff0e, 0xff0e, 1},
+		{0xff1a, 0xff1b, 1},
+		{0xff1f, 0xff1f, 1},
+		{0xff61, 0xff61, 1},
+		{0xff64, 0xff64, 1},
+	},
+	R32: []Range32{
+		{0x1039f, 0x1039f, 1},
+		{0x103d0, 0x103d0, 1},
+		{0x10857, 0x10857, 1},
+		{0x1091f, 0x1091f, 1},
+		{0x10b3a, 0x10b3f, 1},
+		{0x11047, 0x1104d, 1},
+		{0x110be, 0x110c1, 1},
+		{0x11141, 0x11143, 1},
+		{0x111c5, 0x111c6, 1},
+		{0x12470, 0x12473, 1},
+	},
+	LatinOffset: 5,
+}
+
+var _Unified_Ideograph = &RangeTable{
+	R16: []Range16{
+		{0x3400, 0x4db5, 1},
+		{0x4e00, 0x9fcc, 1},
+		{0xfa0e, 0xfa0f, 1},
+		{0xfa11, 0xfa11, 1},
+		{0xfa13, 0xfa14, 1},
+		{0xfa1f, 0xfa1f, 1},
+		{0xfa21, 0xfa21, 1},
+		{0xfa23, 0xfa24, 1},
+		{0xfa27, 0xfa29, 1},
+	},
+	R32: []Range32{
+		{0x20000, 0x2a6d6, 1},
+		{0x2a700, 0x2b734, 1},
+		{0x2b740, 0x2b81d, 1},
+	},
+}
+
+var _Variation_Selector = &RangeTable{
+	R16: []Range16{
+		{0x180b, 0x180d, 1},
+		{0xfe00, 0xfe0f, 1},
+	},
+	R32: []Range32{
+		{0xe0100, 0xe01ef, 1},
+	},
+}
+
+var _White_Space = &RangeTable{
+	R16: []Range16{
+		{0x0009, 0x000d, 1},
+		{0x0020, 0x0020, 1},
+		{0x0085, 0x0085, 1},
+		{0x00a0, 0x00a0, 1},
+		{0x1680, 0x1680, 1},
+		{0x2000, 0x200a, 1},
+		{0x2028, 0x2029, 1},
+		{0x202f, 0x202f, 1},
+		{0x205f, 0x205f, 1},
+		{0x3000, 0x3000, 1},
+	},
+	LatinOffset: 4,
+}
+
+// These variables have type *RangeTable.
+var (
+	ASCII_Hex_Digit                    = _ASCII_Hex_Digit                    // ASCII_Hex_Digit is the set of Unicode characters with property ASCII_Hex_Digit.
+	Bidi_Control                       = _Bidi_Control                       // Bidi_Control is the set of Unicode characters with property Bidi_Control.
+	Dash                               = _Dash                               // Dash is the set of Unicode characters with property Dash.
+	Deprecated                         = _Deprecated                         // Deprecated is the set of Unicode characters with property Deprecated.
+	Diacritic                          = _Diacritic                          // Diacritic is the set of Unicode characters with property Diacritic.
+	Extender                           = _Extender                           // Extender is the set of Unicode characters with property Extender.
+	Hex_Digit                          = _Hex_Digit                          // Hex_Digit is the set of Unicode characters with property Hex_Digit.
+	Hyphen                             = _Hyphen                             // Hyphen is the set of Unicode characters with property Hyphen.
+	IDS_Binary_Operator                = _IDS_Binary_Operator                // IDS_Binary_Operator is the set of Unicode characters with property IDS_Binary_Operator.
+	IDS_Trinary_Operator               = _IDS_Trinary_Operator               // IDS_Trinary_Operator is the set of Unicode characters with property IDS_Trinary_Operator.
+	Ideographic                        = _Ideographic                        // Ideographic is the set of Unicode characters with property Ideographic.
+	Join_Control                       = _Join_Control                       // Join_Control is the set of Unicode characters with property Join_Control.
+	Logical_Order_Exception            = _Logical_Order_Exception            // Logical_Order_Exception is the set of Unicode characters with property Logical_Order_Exception.
+	Noncharacter_Code_Point            = _Noncharacter_Code_Point            // Noncharacter_Code_Point is the set of Unicode characters with property Noncharacter_Code_Point.
+	Other_Alphabetic                   = _Other_Alphabetic                   // Other_Alphabetic is the set of Unicode characters with property Other_Alphabetic.
+	Other_Default_Ignorable_Code_Point = _Other_Default_Ignorable_Code_Point // Other_Default_Ignorable_Code_Point is the set of Unicode characters with property Other_Default_Ignorable_Code_Point.
+	Other_Grapheme_Extend              = _Other_Grapheme_Extend              // Other_Grapheme_Extend is the set of Unicode characters with property Other_Grapheme_Extend.
+	Other_ID_Continue                  = _Other_ID_Continue                  // Other_ID_Continue is the set of Unicode characters with property Other_ID_Continue.
+	Other_ID_Start                     = _Other_ID_Start                     // Other_ID_Start is the set of Unicode characters with property Other_ID_Start.
+	Other_Lowercase                    = _Other_Lowercase                    // Other_Lowercase is the set of Unicode characters with property Other_Lowercase.
+	Other_Math                         = _Other_Math                         // Other_Math is the set of Unicode characters with property Other_Math.
+	Other_Uppercase                    = _Other_Uppercase                    // Other_Uppercase is the set of Unicode characters with property Other_Uppercase.
+	Pattern_Syntax                     = _Pattern_Syntax                     // Pattern_Syntax is the set of Unicode characters with property Pattern_Syntax.
+	Pattern_White_Space                = _Pattern_White_Space                // Pattern_White_Space is the set of Unicode characters with property Pattern_White_Space.
+	Quotation_Mark                     = _Quotation_Mark                     // Quotation_Mark is the set of Unicode characters with property Quotation_Mark.
+	Radical                            = _Radical                            // Radical is the set of Unicode characters with property Radical.
+	STerm                              = _STerm                              // STerm is the set of Unicode characters with property STerm.
+	Soft_Dotted                        = _Soft_Dotted                        // Soft_Dotted is the set of Unicode characters with property Soft_Dotted.
+	Terminal_Punctuation               = _Terminal_Punctuation               // Terminal_Punctuation is the set of Unicode characters with property Terminal_Punctuation.
+	Unified_Ideograph                  = _Unified_Ideograph                  // Unified_Ideograph is the set of Unicode characters with property Unified_Ideograph.
+	Variation_Selector                 = _Variation_Selector                 // Variation_Selector is the set of Unicode characters with property Variation_Selector.
+	White_Space                        = _White_Space                        // White_Space is the set of Unicode characters with property White_Space.
+)
+
+// Generated by running
+//	maketables --data=http://www.unicode.org/Public/6.3.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/6.3.0/ucd/CaseFolding.txt
+// DO NOT EDIT
+
+// CaseRanges is the table describing case mappings for all letters with
+// non-self mappings.
+var CaseRanges = _CaseRanges
+var _CaseRanges = []CaseRange{
+	{0x0041, 0x005A, d{0, 32, 0}},
+	{0x0061, 0x007A, d{-32, 0, -32}},
+	{0x00B5, 0x00B5, d{743, 0, 743}},
+	{0x00C0, 0x00D6, d{0, 32, 0}},
+	{0x00D8, 0x00DE, d{0, 32, 0}},
+	{0x00E0, 0x00F6, d{-32, 0, -32}},
+	{0x00F8, 0x00FE, d{-32, 0, -32}},
+	{0x00FF, 0x00FF, d{121, 0, 121}},
+	{0x0100, 0x012F, d{UpperLower, UpperLower, UpperLower}},
+	{0x0130, 0x0130, d{0, -199, 0}},
+	{0x0131, 0x0131, d{-232, 0, -232}},
+	{0x0132, 0x0137, d{UpperLower, UpperLower, UpperLower}},
+	{0x0139, 0x0148, d{UpperLower, UpperLower, UpperLower}},
+	{0x014A, 0x0177, d{UpperLower, UpperLower, UpperLower}},
+	{0x0178, 0x0178, d{0, -121, 0}},
+	{0x0179, 0x017E, d{UpperLower, UpperLower, UpperLower}},
+	{0x017F, 0x017F, d{-300, 0, -300}},
+	{0x0180, 0x0180, d{195, 0, 195}},
+	{0x0181, 0x0181, d{0, 210, 0}},
+	{0x0182, 0x0185, d{UpperLower, UpperLower, UpperLower}},
+	{0x0186, 0x0186, d{0, 206, 0}},
+	{0x0187, 0x0188, d{UpperLower, UpperLower, UpperLower}},
+	{0x0189, 0x018A, d{0, 205, 0}},
+	{0x018B, 0x018C, d{UpperLower, UpperLower, UpperLower}},
+	{0x018E, 0x018E, d{0, 79, 0}},
+	{0x018F, 0x018F, d{0, 202, 0}},
+	{0x0190, 0x0190, d{0, 203, 0}},
+	{0x0191, 0x0192, d{UpperLower, UpperLower, UpperLower}},
+	{0x0193, 0x0193, d{0, 205, 0}},
+	{0x0194, 0x0194, d{0, 207, 0}},
+	{0x0195, 0x0195, d{97, 0, 97}},
+	{0x0196, 0x0196, d{0, 211, 0}},
+	{0x0197, 0x0197, d{0, 209, 0}},
+	{0x0198, 0x0199, d{UpperLower, UpperLower, UpperLower}},
+	{0x019A, 0x019A, d{163, 0, 163}},
+	{0x019C, 0x019C, d{0, 211, 0}},
+	{0x019D, 0x019D, d{0, 213, 0}},
+	{0x019E, 0x019E, d{130, 0, 130}},
+	{0x019F, 0x019F, d{0, 214, 0}},
+	{0x01A0, 0x01A5, d{UpperLower, UpperLower, UpperLower}},
+	{0x01A6, 0x01A6, d{0, 218, 0}},
+	{0x01A7, 0x01A8, d{UpperLower, UpperLower, UpperLower}},
+	{0x01A9, 0x01A9, d{0, 218, 0}},
+	{0x01AC, 0x01AD, d{UpperLower, UpperLower, UpperLower}},
+	{0x01AE, 0x01AE, d{0, 218, 0}},
+	{0x01AF, 0x01B0, d{UpperLower, UpperLower, UpperLower}},
+	{0x01B1, 0x01B2, d{0, 217, 0}},
+	{0x01B3, 0x01B6, d{UpperLower, UpperLower, UpperLower}},
+	{0x01B7, 0x01B7, d{0, 219, 0}},
+	{0x01B8, 0x01B9, d{UpperLower, UpperLower, UpperLower}},
+	{0x01BC, 0x01BD, d{UpperLower, UpperLower, UpperLower}},
+	{0x01BF, 0x01BF, d{56, 0, 56}},
+	{0x01C4, 0x01C4, d{0, 2, 1}},
+	{0x01C5, 0x01C5, d{-1, 1, 0}},
+	{0x01C6, 0x01C6, d{-2, 0, -1}},
+	{0x01C7, 0x01C7, d{0, 2, 1}},
+	{0x01C8, 0x01C8, d{-1, 1, 0}},
+	{0x01C9, 0x01C9, d{-2, 0, -1}},
+	{0x01CA, 0x01CA, d{0, 2, 1}},
+	{0x01CB, 0x01CB, d{-1, 1, 0}},
+	{0x01CC, 0x01CC, d{-2, 0, -1}},
+	{0x01CD, 0x01DC, d{UpperLower, UpperLower, UpperLower}},
+	{0x01DD, 0x01DD, d{-79, 0, -79}},
+	{0x01DE, 0x01EF, d{UpperLower, UpperLower, UpperLower}},
+	{0x01F1, 0x01F1, d{0, 2, 1}},
+	{0x01F2, 0x01F2, d{-1, 1, 0}},
+	{0x01F3, 0x01F3, d{-2, 0, -1}},
+	{0x01F4, 0x01F5, d{UpperLower, UpperLower, UpperLower}},
+	{0x01F6, 0x01F6, d{0, -97, 0}},
+	{0x01F7, 0x01F7, d{0, -56, 0}},
+	{0x01F8, 0x021F, d{UpperLower, UpperLower, UpperLower}},
+	{0x0220, 0x0220, d{0, -130, 0}},
+	{0x0222, 0x0233, d{UpperLower, UpperLower, UpperLower}},
+	{0x023A, 0x023A, d{0, 10795, 0}},
+	{0x023B, 0x023C, d{UpperLower, UpperLower, UpperLower}},
+	{0x023D, 0x023D, d{0, -163, 0}},
+	{0x023E, 0x023E, d{0, 10792, 0}},
+	{0x023F, 0x0240, d{10815, 0, 10815}},
+	{0x0241, 0x0242, d{UpperLower, UpperLower, UpperLower}},
+	{0x0243, 0x0243, d{0, -195, 0}},
+	{0x0244, 0x0244, d{0, 69, 0}},
+	{0x0245, 0x0245, d{0, 71, 0}},
+	{0x0246, 0x024F, d{UpperLower, UpperLower, UpperLower}},
+	{0x0250, 0x0250, d{10783, 0, 10783}},
+	{0x0251, 0x0251, d{10780, 0, 10780}},
+	{0x0252, 0x0252, d{10782, 0, 10782}},
+	{0x0253, 0x0253, d{-210, 0, -210}},
+	{0x0254, 0x0254, d{-206, 0, -206}},
+	{0x0256, 0x0257, d{-205, 0, -205}},
+	{0x0259, 0x0259, d{-202, 0, -202}},
+	{0x025B, 0x025B, d{-203, 0, -203}},
+	{0x0260, 0x0260, d{-205, 0, -205}},
+	{0x0263, 0x0263, d{-207, 0, -207}},
+	{0x0265, 0x0265, d{42280, 0, 42280}},
+	{0x0266, 0x0266, d{42308, 0, 42308}},
+	{0x0268, 0x0268, d{-209, 0, -209}},
+	{0x0269, 0x0269, d{-211, 0, -211}},
+	{0x026B, 0x026B, d{10743, 0, 10743}},
+	{0x026F, 0x026F, d{-211, 0, -211}},
+	{0x0271, 0x0271, d{10749, 0, 10749}},
+	{0x0272, 0x0272, d{-213, 0, -213}},
+	{0x0275, 0x0275, d{-214, 0, -214}},
+	{0x027D, 0x027D, d{10727, 0, 10727}},
+	{0x0280, 0x0280, d{-218, 0, -218}},
+	{0x0283, 0x0283, d{-218, 0, -218}},
+	{0x0288, 0x0288, d{-218, 0, -218}},
+	{0x0289, 0x0289, d{-69, 0, -69}},
+	{0x028A, 0x028B, d{-217, 0, -217}},
+	{0x028C, 0x028C, d{-71, 0, -71}},
+	{0x0292, 0x0292, d{-219, 0, -219}},
+	{0x0345, 0x0345, d{84, 0, 84}},
+	{0x0370, 0x0373, d{UpperLower, UpperLower, UpperLower}},
+	{0x0376, 0x0377, d{UpperLower, UpperLower, UpperLower}},
+	{0x037B, 0x037D, d{130, 0, 130}},
+	{0x0386, 0x0386, d{0, 38, 0}},
+	{0x0388, 0x038A, d{0, 37, 0}},
+	{0x038C, 0x038C, d{0, 64, 0}},
+	{0x038E, 0x038F, d{0, 63, 0}},
+	{0x0391, 0x03A1, d{0, 32, 0}},
+	{0x03A3, 0x03AB, d{0, 32, 0}},
+	{0x03AC, 0x03AC, d{-38, 0, -38}},
+	{0x03AD, 0x03AF, d{-37, 0, -37}},
+	{0x03B1, 0x03C1, d{-32, 0, -32}},
+	{0x03C2, 0x03C2, d{-31, 0, -31}},
+	{0x03C3, 0x03CB, d{-32, 0, -32}},
+	{0x03CC, 0x03CC, d{-64, 0, -64}},
+	{0x03CD, 0x03CE, d{-63, 0, -63}},
+	{0x03CF, 0x03CF, d{0, 8, 0}},
+	{0x03D0, 0x03D0, d{-62, 0, -62}},
+	{0x03D1, 0x03D1, d{-57, 0, -57}},
+	{0x03D5, 0x03D5, d{-47, 0, -47}},
+	{0x03D6, 0x03D6, d{-54, 0, -54}},
+	{0x03D7, 0x03D7, d{-8, 0, -8}},
+	{0x03D8, 0x03EF, d{UpperLower, UpperLower, UpperLower}},
+	{0x03F0, 0x03F0, d{-86, 0, -86}},
+	{0x03F1, 0x03F1, d{-80, 0, -80}},
+	{0x03F2, 0x03F2, d{7, 0, 7}},
+	{0x03F4, 0x03F4, d{0, -60, 0}},
+	{0x03F5, 0x03F5, d{-96, 0, -96}},
+	{0x03F7, 0x03F8, d{UpperLower, UpperLower, UpperLower}},
+	{0x03F9, 0x03F9, d{0, -7, 0}},
+	{0x03FA, 0x03FB, d{UpperLower, UpperLower, UpperLower}},
+	{0x03FD, 0x03FF, d{0, -130, 0}},
+	{0x0400, 0x040F, d{0, 80, 0}},
+	{0x0410, 0x042F, d{0, 32, 0}},
+	{0x0430, 0x044F, d{-32, 0, -32}},
+	{0x0450, 0x045F, d{-80, 0, -80}},
+	{0x0460, 0x0481, d{UpperLower, UpperLower, UpperLower}},
+	{0x048A, 0x04BF, d{UpperLower, UpperLower, UpperLower}},
+	{0x04C0, 0x04C0, d{0, 15, 0}},
+	{0x04C1, 0x04CE, d{UpperLower, UpperLower, UpperLower}},
+	{0x04CF, 0x04CF, d{-15, 0, -15}},
+	{0x04D0, 0x0527, d{UpperLower, UpperLower, UpperLower}},
+	{0x0531, 0x0556, d{0, 48, 0}},
+	{0x0561, 0x0586, d{-48, 0, -48}},
+	{0x10A0, 0x10C5, d{0, 7264, 0}},
+	{0x10C7, 0x10C7, d{0, 7264, 0}},
+	{0x10CD, 0x10CD, d{0, 7264, 0}},
+	{0x1D79, 0x1D79, d{35332, 0, 35332}},
+	{0x1D7D, 0x1D7D, d{3814, 0, 3814}},
+	{0x1E00, 0x1E95, d{UpperLower, UpperLower, UpperLower}},
+	{0x1E9B, 0x1E9B, d{-59, 0, -59}},
+	{0x1E9E, 0x1E9E, d{0, -7615, 0}},
+	{0x1EA0, 0x1EFF, d{UpperLower, UpperLower, UpperLower}},
+	{0x1F00, 0x1F07, d{8, 0, 8}},
+	{0x1F08, 0x1F0F, d{0, -8, 0}},
+	{0x1F10, 0x1F15, d{8, 0, 8}},
+	{0x1F18, 0x1F1D, d{0, -8, 0}},
+	{0x1F20, 0x1F27, d{8, 0, 8}},
+	{0x1F28, 0x1F2F, d{0, -8, 0}},
+	{0x1F30, 0x1F37, d{8, 0, 8}},
+	{0x1F38, 0x1F3F, d{0, -8, 0}},
+	{0x1F40, 0x1F45, d{8, 0, 8}},
+	{0x1F48, 0x1F4D, d{0, -8, 0}},
+	{0x1F51, 0x1F51, d{8, 0, 8}},
+	{0x1F53, 0x1F53, d{8, 0, 8}},
+	{0x1F55, 0x1F55, d{8, 0, 8}},
+	{0x1F57, 0x1F57, d{8, 0, 8}},
+	{0x1F59, 0x1F59, d{0, -8, 0}},
+	{0x1F5B, 0x1F5B, d{0, -8, 0}},
+	{0x1F5D, 0x1F5D, d{0, -8, 0}},
+	{0x1F5F, 0x1F5F, d{0, -8, 0}},
+	{0x1F60, 0x1F67, d{8, 0, 8}},
+	{0x1F68, 0x1F6F, d{0, -8, 0}},
+	{0x1F70, 0x1F71, d{74, 0, 74}},
+	{0x1F72, 0x1F75, d{86, 0, 86}},
+	{0x1F76, 0x1F77, d{100, 0, 100}},
+	{0x1F78, 0x1F79, d{128, 0, 128}},
+	{0x1F7A, 0x1F7B, d{112, 0, 112}},
+	{0x1F7C, 0x1F7D, d{126, 0, 126}},
+	{0x1F80, 0x1F87, d{8, 0, 8}},
+	{0x1F88, 0x1F8F, d{0, -8, 0}},
+	{0x1F90, 0x1F97, d{8, 0, 8}},
+	{0x1F98, 0x1F9F, d{0, -8, 0}},
+	{0x1FA0, 0x1FA7, d{8, 0, 8}},
+	{0x1FA8, 0x1FAF, d{0, -8, 0}},
+	{0x1FB0, 0x1FB1, d{8, 0, 8}},
+	{0x1FB3, 0x1FB3, d{9, 0, 9}},
+	{0x1FB8, 0x1FB9, d{0, -8, 0}},
+	{0x1FBA, 0x1FBB, d{0, -74, 0}},
+	{0x1FBC, 0x1FBC, d{0, -9, 0}},
+	{0x1FBE, 0x1FBE, d{-7205, 0, -7205}},
+	{0x1FC3, 0x1FC3, d{9, 0, 9}},
+	{0x1FC8, 0x1FCB, d{0, -86, 0}},
+	{0x1FCC, 0x1FCC, d{0, -9, 0}},
+	{0x1FD0, 0x1FD1, d{8, 0, 8}},
+	{0x1FD8, 0x1FD9, d{0, -8, 0}},
+	{0x1FDA, 0x1FDB, d{0, -100, 0}},
+	{0x1FE0, 0x1FE1, d{8, 0, 8}},
+	{0x1FE5, 0x1FE5, d{7, 0, 7}},
+	{0x1FE8, 0x1FE9, d{0, -8, 0}},
+	{0x1FEA, 0x1FEB, d{0, -112, 0}},
+	{0x1FEC, 0x1FEC, d{0, -7, 0}},
+	{0x1FF3, 0x1FF3, d{9, 0, 9}},
+	{0x1FF8, 0x1FF9, d{0, -128, 0}},
+	{0x1FFA, 0x1FFB, d{0, -126, 0}},
+	{0x1FFC, 0x1FFC, d{0, -9, 0}},
+	{0x2126, 0x2126, d{0, -7517, 0}},
+	{0x212A, 0x212A, d{0, -8383, 0}},
+	{0x212B, 0x212B, d{0, -8262, 0}},
+	{0x2132, 0x2132, d{0, 28, 0}},
+	{0x214E, 0x214E, d{-28, 0, -28}},
+	{0x2160, 0x216F, d{0, 16, 0}},
+	{0x2170, 0x217F, d{-16, 0, -16}},
+	{0x2183, 0x2184, d{UpperLower, UpperLower, UpperLower}},
+	{0x24B6, 0x24CF, d{0, 26, 0}},
+	{0x24D0, 0x24E9, d{-26, 0, -26}},
+	{0x2C00, 0x2C2E, d{0, 48, 0}},
+	{0x2C30, 0x2C5E, d{-48, 0, -48}},
+	{0x2C60, 0x2C61, d{UpperLower, UpperLower, UpperLower}},
+	{0x2C62, 0x2C62, d{0, -10743, 0}},
+	{0x2C63, 0x2C63, d{0, -3814, 0}},
+	{0x2C64, 0x2C64, d{0, -10727, 0}},
+	{0x2C65, 0x2C65, d{-10795, 0, -10795}},
+	{0x2C66, 0x2C66, d{-10792, 0, -10792}},
+	{0x2C67, 0x2C6C, d{UpperLower, UpperLower, UpperLower}},
+	{0x2C6D, 0x2C6D, d{0, -10780, 0}},
+	{0x2C6E, 0x2C6E, d{0, -10749, 0}},
+	{0x2C6F, 0x2C6F, d{0, -10783, 0}},
+	{0x2C70, 0x2C70, d{0, -10782, 0}},
+	{0x2C72, 0x2C73, d{UpperLower, UpperLower, UpperLower}},
+	{0x2C75, 0x2C76, d{UpperLower, UpperLower, UpperLower}},
+	{0x2C7E, 0x2C7F, d{0, -10815, 0}},
+	{0x2C80, 0x2CE3, d{UpperLower, UpperLower, UpperLower}},
+	{0x2CEB, 0x2CEE, d{UpperLower, UpperLower, UpperLower}},
+	{0x2CF2, 0x2CF3, d{UpperLower, UpperLower, UpperLower}},
+	{0x2D00, 0x2D25, d{-7264, 0, -7264}},
+	{0x2D27, 0x2D27, d{-7264, 0, -7264}},
+	{0x2D2D, 0x2D2D, d{-7264, 0, -7264}},
+	{0xA640, 0xA66D, d{UpperLower, UpperLower, UpperLower}},
+	{0xA680, 0xA697, d{UpperLower, UpperLower, UpperLower}},
+	{0xA722, 0xA72F, d{UpperLower, UpperLower, UpperLower}},
+	{0xA732, 0xA76F, d{UpperLower, UpperLower, UpperLower}},
+	{0xA779, 0xA77C, d{UpperLower, UpperLower, UpperLower}},
+	{0xA77D, 0xA77D, d{0, -35332, 0}},
+	{0xA77E, 0xA787, d{UpperLower, UpperLower, UpperLower}},
+	{0xA78B, 0xA78C, d{UpperLower, UpperLower, UpperLower}},
+	{0xA78D, 0xA78D, d{0, -42280, 0}},
+	{0xA790, 0xA793, d{UpperLower, UpperLower, UpperLower}},
+	{0xA7A0, 0xA7A9, d{UpperLower, UpperLower, UpperLower}},
+	{0xA7AA, 0xA7AA, d{0, -42308, 0}},
+	{0xFF21, 0xFF3A, d{0, 32, 0}},
+	{0xFF41, 0xFF5A, d{-32, 0, -32}},
+	{0x10400, 0x10427, d{0, 40, 0}},
+	{0x10428, 0x1044F, d{-40, 0, -40}},
+}
+var properties = [MaxLatin1 + 1]uint8{
+	0x00: pC,       // '\x00'
+	0x01: pC,       // '\x01'
+	0x02: pC,       // '\x02'
+	0x03: pC,       // '\x03'
+	0x04: pC,       // '\x04'
+	0x05: pC,       // '\x05'
+	0x06: pC,       // '\x06'
+	0x07: pC,       // '\a'
+	0x08: pC,       // '\b'
+	0x09: pC,       // '\t'
+	0x0A: pC,       // '\n'
+	0x0B: pC,       // '\v'
+	0x0C: pC,       // '\f'
+	0x0D: pC,       // '\r'
+	0x0E: pC,       // '\x0e'
+	0x0F: pC,       // '\x0f'
+	0x10: pC,       // '\x10'
+	0x11: pC,       // '\x11'
+	0x12: pC,       // '\x12'
+	0x13: pC,       // '\x13'
+	0x14: pC,       // '\x14'
+	0x15: pC,       // '\x15'
+	0x16: pC,       // '\x16'
+	0x17: pC,       // '\x17'
+	0x18: pC,       // '\x18'
+	0x19: pC,       // '\x19'
+	0x1A: pC,       // '\x1a'
+	0x1B: pC,       // '\x1b'
+	0x1C: pC,       // '\x1c'
+	0x1D: pC,       // '\x1d'
+	0x1E: pC,       // '\x1e'
+	0x1F: pC,       // '\x1f'
+	0x20: pZ | pp,  // ' '
+	0x21: pP | pp,  // '!'
+	0x22: pP | pp,  // '"'
+	0x23: pP | pp,  // '#'
+	0x24: pS | pp,  // '$'
+	0x25: pP | pp,  // '%'
+	0x26: pP | pp,  // '&'
+	0x27: pP | pp,  // '\''
+	0x28: pP | pp,  // '('
+	0x29: pP | pp,  // ')'
+	0x2A: pP | pp,  // '*'
+	0x2B: pS | pp,  // '+'
+	0x2C: pP | pp,  // ','
+	0x2D: pP | pp,  // '-'
+	0x2E: pP | pp,  // '.'
+	0x2F: pP | pp,  // '/'
+	0x30: pN | pp,  // '0'
+	0x31: pN | pp,  // '1'
+	0x32: pN | pp,  // '2'
+	0x33: pN | pp,  // '3'
+	0x34: pN | pp,  // '4'
+	0x35: pN | pp,  // '5'
+	0x36: pN | pp,  // '6'
+	0x37: pN | pp,  // '7'
+	0x38: pN | pp,  // '8'
+	0x39: pN | pp,  // '9'
+	0x3A: pP | pp,  // ':'
+	0x3B: pP | pp,  // ';'
+	0x3C: pS | pp,  // '<'
+	0x3D: pS | pp,  // '='
+	0x3E: pS | pp,  // '>'
+	0x3F: pP | pp,  // '?'
+	0x40: pP | pp,  // '@'
+	0x41: pLu | pp, // 'A'
+	0x42: pLu | pp, // 'B'
+	0x43: pLu | pp, // 'C'
+	0x44: pLu | pp, // 'D'
+	0x45: pLu | pp, // 'E'
+	0x46: pLu | pp, // 'F'
+	0x47: pLu | pp, // 'G'
+	0x48: pLu | pp, // 'H'
+	0x49: pLu | pp, // 'I'
+	0x4A: pLu | pp, // 'J'
+	0x4B: pLu | pp, // 'K'
+	0x4C: pLu | pp, // 'L'
+	0x4D: pLu | pp, // 'M'
+	0x4E: pLu | pp, // 'N'
+	0x4F: pLu | pp, // 'O'
+	0x50: pLu | pp, // 'P'
+	0x51: pLu | pp, // 'Q'
+	0x52: pLu | pp, // 'R'
+	0x53: pLu | pp, // 'S'
+	0x54: pLu | pp, // 'T'
+	0x55: pLu | pp, // 'U'
+	0x56: pLu | pp, // 'V'
+	0x57: pLu | pp, // 'W'
+	0x58: pLu | pp, // 'X'
+	0x59: pLu | pp, // 'Y'
+	0x5A: pLu | pp, // 'Z'
+	0x5B: pP | pp,  // '['
+	0x5C: pP | pp,  // '\\'
+	0x5D: pP | pp,  // ']'
+	0x5E: pS | pp,  // '^'
+	0x5F: pP | pp,  // '_'
+	0x60: pS | pp,  // '`'
+	0x61: pLl | pp, // 'a'
+	0x62: pLl | pp, // 'b'
+	0x63: pLl | pp, // 'c'
+	0x64: pLl | pp, // 'd'
+	0x65: pLl | pp, // 'e'
+	0x66: pLl | pp, // 'f'
+	0x67: pLl | pp, // 'g'
+	0x68: pLl | pp, // 'h'
+	0x69: pLl | pp, // 'i'
+	0x6A: pLl | pp, // 'j'
+	0x6B: pLl | pp, // 'k'
+	0x6C: pLl | pp, // 'l'
+	0x6D: pLl | pp, // 'm'
+	0x6E: pLl | pp, // 'n'
+	0x6F: pLl | pp, // 'o'
+	0x70: pLl | pp, // 'p'
+	0x71: pLl | pp, // 'q'
+	0x72: pLl | pp, // 'r'
+	0x73: pLl | pp, // 's'
+	0x74: pLl | pp, // 't'
+	0x75: pLl | pp, // 'u'
+	0x76: pLl | pp, // 'v'
+	0x77: pLl | pp, // 'w'
+	0x78: pLl | pp, // 'x'
+	0x79: pLl | pp, // 'y'
+	0x7A: pLl | pp, // 'z'
+	0x7B: pP | pp,  // '{'
+	0x7C: pS | pp,  // '|'
+	0x7D: pP | pp,  // '}'
+	0x7E: pS | pp,  // '~'
+	0x7F: pC,       // '\u007f'
+	0x80: pC,       // '\u0080'
+	0x81: pC,       // '\u0081'
+	0x82: pC,       // '\u0082'
+	0x83: pC,       // '\u0083'
+	0x84: pC,       // '\u0084'
+	0x85: pC,       // '\u0085'
+	0x86: pC,       // '\u0086'
+	0x87: pC,       // '\u0087'
+	0x88: pC,       // '\u0088'
+	0x89: pC,       // '\u0089'
+	0x8A: pC,       // '\u008a'
+	0x8B: pC,       // '\u008b'
+	0x8C: pC,       // '\u008c'
+	0x8D: pC,       // '\u008d'
+	0x8E: pC,       // '\u008e'
+	0x8F: pC,       // '\u008f'
+	0x90: pC,       // '\u0090'
+	0x91: pC,       // '\u0091'
+	0x92: pC,       // '\u0092'
+	0x93: pC,       // '\u0093'
+	0x94: pC,       // '\u0094'
+	0x95: pC,       // '\u0095'
+	0x96: pC,       // '\u0096'
+	0x97: pC,       // '\u0097'
+	0x98: pC,       // '\u0098'
+	0x99: pC,       // '\u0099'
+	0x9A: pC,       // '\u009a'
+	0x9B: pC,       // '\u009b'
+	0x9C: pC,       // '\u009c'
+	0x9D: pC,       // '\u009d'
+	0x9E: pC,       // '\u009e'
+	0x9F: pC,       // '\u009f'
+	0xA0: pZ,       // '\u00a0'
+	0xA1: pP | pp,  // '¡'
+	0xA2: pS | pp,  // '¢'
+	0xA3: pS | pp,  // '£'
+	0xA4: pS | pp,  // '¤'
+	0xA5: pS | pp,  // '¥'
+	0xA6: pS | pp,  // '¦'
+	0xA7: pP | pp,  // '§'
+	0xA8: pS | pp,  // '¨'
+	0xA9: pS | pp,  // '©'
+	0xAA: pLo | pp, // 'ª'
+	0xAB: pP | pp,  // '«'
+	0xAC: pS | pp,  // '¬'
+	0xAD: 0,        // '\u00ad'
+	0xAE: pS | pp,  // '®'
+	0xAF: pS | pp,  // '¯'
+	0xB0: pS | pp,  // '°'
+	0xB1: pS | pp,  // '±'
+	0xB2: pN | pp,  // '²'
+	0xB3: pN | pp,  // '³'
+	0xB4: pS | pp,  // '´'
+	0xB5: pLl | pp, // 'µ'
+	0xB6: pP | pp,  // '¶'
+	0xB7: pP | pp,  // '·'
+	0xB8: pS | pp,  // '¸'
+	0xB9: pN | pp,  // '¹'
+	0xBA: pLo | pp, // 'º'
+	0xBB: pP | pp,  // '»'
+	0xBC: pN | pp,  // '¼'
+	0xBD: pN | pp,  // '½'
+	0xBE: pN | pp,  // '¾'
+	0xBF: pP | pp,  // '¿'
+	0xC0: pLu | pp, // 'À'
+	0xC1: pLu | pp, // 'Á'
+	0xC2: pLu | pp, // 'Â'
+	0xC3: pLu | pp, // 'Ã'
+	0xC4: pLu | pp, // 'Ä'
+	0xC5: pLu | pp, // 'Å'
+	0xC6: pLu | pp, // 'Æ'
+	0xC7: pLu | pp, // 'Ç'
+	0xC8: pLu | pp, // 'È'
+	0xC9: pLu | pp, // 'É'
+	0xCA: pLu | pp, // 'Ê'
+	0xCB: pLu | pp, // 'Ë'
+	0xCC: pLu | pp, // 'Ì'
+	0xCD: pLu | pp, // 'Í'
+	0xCE: pLu | pp, // 'Î'
+	0xCF: pLu | pp, // 'Ï'
+	0xD0: pLu | pp, // 'Ð'
+	0xD1: pLu | pp, // 'Ñ'
+	0xD2: pLu | pp, // 'Ò'
+	0xD3: pLu | pp, // 'Ó'
+	0xD4: pLu | pp, // 'Ô'
+	0xD5: pLu | pp, // 'Õ'
+	0xD6: pLu | pp, // 'Ö'
+	0xD7: pS | pp,  // '×'
+	0xD8: pLu | pp, // 'Ø'
+	0xD9: pLu | pp, // 'Ù'
+	0xDA: pLu | pp, // 'Ú'
+	0xDB: pLu | pp, // 'Û'
+	0xDC: pLu | pp, // 'Ü'
+	0xDD: pLu | pp, // 'Ý'
+	0xDE: pLu | pp, // 'Þ'
+	0xDF: pLl | pp, // 'ß'
+	0xE0: pLl | pp, // 'à'
+	0xE1: pLl | pp, // 'á'
+	0xE2: pLl | pp, // 'â'
+	0xE3: pLl | pp, // 'ã'
+	0xE4: pLl | pp, // 'ä'
+	0xE5: pLl | pp, // 'å'
+	0xE6: pLl | pp, // 'æ'
+	0xE7: pLl | pp, // 'ç'
+	0xE8: pLl | pp, // 'è'
+	0xE9: pLl | pp, // 'é'
+	0xEA: pLl | pp, // 'ê'
+	0xEB: pLl | pp, // 'ë'
+	0xEC: pLl | pp, // 'ì'
+	0xED: pLl | pp, // 'í'
+	0xEE: pLl | pp, // 'î'
+	0xEF: pLl | pp, // 'ï'
+	0xF0: pLl | pp, // 'ð'
+	0xF1: pLl | pp, // 'ñ'
+	0xF2: pLl | pp, // 'ò'
+	0xF3: pLl | pp, // 'ó'
+	0xF4: pLl | pp, // 'ô'
+	0xF5: pLl | pp, // 'õ'
+	0xF6: pLl | pp, // 'ö'
+	0xF7: pS | pp,  // '÷'
+	0xF8: pLl | pp, // 'ø'
+	0xF9: pLl | pp, // 'ù'
+	0xFA: pLl | pp, // 'ú'
+	0xFB: pLl | pp, // 'û'
+	0xFC: pLl | pp, // 'ü'
+	0xFD: pLl | pp, // 'ý'
+	0xFE: pLl | pp, // 'þ'
+	0xFF: pLl | pp, // 'ÿ'
+}
+
+var caseOrbit = []foldPair{
+	{0x004B, 0x006B},
+	{0x0053, 0x0073},
+	{0x006B, 0x212A},
+	{0x0073, 0x017F},
+	{0x00B5, 0x039C},
+	{0x00C5, 0x00E5},
+	{0x00DF, 0x1E9E},
+	{0x00E5, 0x212B},
+	{0x0130, 0x0130},
+	{0x0131, 0x0131},
+	{0x017F, 0x0053},
+	{0x01C4, 0x01C5},
+	{0x01C5, 0x01C6},
+	{0x01C6, 0x01C4},
+	{0x01C7, 0x01C8},
+	{0x01C8, 0x01C9},
+	{0x01C9, 0x01C7},
+	{0x01CA, 0x01CB},
+	{0x01CB, 0x01CC},
+	{0x01CC, 0x01CA},
+	{0x01F1, 0x01F2},
+	{0x01F2, 0x01F3},
+	{0x01F3, 0x01F1},
+	{0x0345, 0x0399},
+	{0x0392, 0x03B2},
+	{0x0395, 0x03B5},
+	{0x0398, 0x03B8},
+	{0x0399, 0x03B9},
+	{0x039A, 0x03BA},
+	{0x039C, 0x03BC},
+	{0x03A0, 0x03C0},
+	{0x03A1, 0x03C1},
+	{0x03A3, 0x03C2},
+	{0x03A6, 0x03C6},
+	{0x03A9, 0x03C9},
+	{0x03B2, 0x03D0},
+	{0x03B5, 0x03F5},
+	{0x03B8, 0x03D1},
+	{0x03B9, 0x1FBE},
+	{0x03BA, 0x03F0},
+	{0x03BC, 0x00B5},
+	{0x03C0, 0x03D6},
+	{0x03C1, 0x03F1},
+	{0x03C2, 0x03C3},
+	{0x03C3, 0x03A3},
+	{0x03C6, 0x03D5},
+	{0x03C9, 0x2126},
+	{0x03D0, 0x0392},
+	{0x03D1, 0x03F4},
+	{0x03D5, 0x03A6},
+	{0x03D6, 0x03A0},
+	{0x03F0, 0x039A},
+	{0x03F1, 0x03A1},
+	{0x03F4, 0x0398},
+	{0x03F5, 0x0395},
+	{0x1E60, 0x1E61},
+	{0x1E61, 0x1E9B},
+	{0x1E9B, 0x1E60},
+	{0x1E9E, 0x00DF},
+	{0x1FBE, 0x0345},
+	{0x2126, 0x03A9},
+	{0x212A, 0x004B},
+	{0x212B, 0x00C5},
+}
+
+// FoldCategory maps a category name to a table of
+// code points outside the category that are equivalent under
+// simple case folding to code points inside the category.
+// If there is no entry for a category name, there are no such points.
+var FoldCategory = map[string]*RangeTable{
+	"Common":    foldCommon,
+	"Greek":     foldGreek,
+	"Inherited": foldInherited,
+	"L":         foldL,
+	"Ll":        foldLl,
+	"Lt":        foldLt,
+	"Lu":        foldLu,
+	"M":         foldM,
+	"Mn":        foldMn,
+}
+
+var foldCommon = &RangeTable{
+	R16: []Range16{
+		{0x039c, 0x03bc, 32},
+	},
+}
+
+var foldGreek = &RangeTable{
+	R16: []Range16{
+		{0x00b5, 0x0345, 656},
+	},
+}
+
+var foldInherited = &RangeTable{
+	R16: []Range16{
+		{0x0399, 0x03b9, 32},
+		{0x1fbe, 0x1fbe, 1},
+	},
+}
+
+var foldL = &RangeTable{
+	R16: []Range16{
+		{0x0345, 0x0345, 1},
+	},
+}
+
+var foldLl = &RangeTable{
+	R16: []Range16{
+		{0x0041, 0x005a, 1},
+		{0x00c0, 0x00d6, 1},
+		{0x00d8, 0x00de, 1},
+		{0x0100, 0x012e, 2},
+		{0x0132, 0x0136, 2},
+		{0x0139, 0x0147, 2},
+		{0x014a, 0x0178, 2},
+		{0x0179, 0x017d, 2},
+		{0x0181, 0x0182, 1},
+		{0x0184, 0x0186, 2},
+		{0x0187, 0x0189, 2},
+		{0x018a, 0x018b, 1},
+		{0x018e, 0x0191, 1},
+		{0x0193, 0x0194, 1},
+		{0x0196, 0x0198, 1},
+		{0x019c, 0x019d, 1},
+		{0x019f, 0x01a0, 1},
+		{0x01a2, 0x01a6, 2},
+		{0x01a7, 0x01a9, 2},
+		{0x01ac, 0x01ae, 2},
+		{0x01af, 0x01b1, 2},
+		{0x01b2, 0x01b3, 1},
+		{0x01b5, 0x01b7, 2},
+		{0x01b8, 0x01bc, 4},
+		{0x01c4, 0x01c5, 1},
+		{0x01c7, 0x01c8, 1},
+		{0x01ca, 0x01cb, 1},
+		{0x01cd, 0x01db, 2},
+		{0x01de, 0x01ee, 2},
+		{0x01f1, 0x01f2, 1},
+		{0x01f4, 0x01f6, 2},
+		{0x01f7, 0x01f8, 1},
+		{0x01fa, 0x0232, 2},
+		{0x023a, 0x023b, 1},
+		{0x023d, 0x023e, 1},
+		{0x0241, 0x0243, 2},
+		{0x0244, 0x0246, 1},
+		{0x0248, 0x024e, 2},
+		{0x0345, 0x0370, 43},
+		{0x0372, 0x0376, 4},
+		{0x0386, 0x0388, 2},
+		{0x0389, 0x038a, 1},
+		{0x038c, 0x038e, 2},
+		{0x038f, 0x0391, 2},
+		{0x0392, 0x03a1, 1},
+		{0x03a3, 0x03ab, 1},
+		{0x03cf, 0x03d8, 9},
+		{0x03da, 0x03ee, 2},
+		{0x03f4, 0x03f7, 3},
+		{0x03f9, 0x03fa, 1},
+		{0x03fd, 0x042f, 1},
+		{0x0460, 0x0480, 2},
+		{0x048a, 0x04c0, 2},
+		{0x04c1, 0x04cd, 2},
+		{0x04d0, 0x0526, 2},
+		{0x0531, 0x0556, 1},
+		{0x10a0, 0x10c5, 1},
+		{0x10c7, 0x10cd, 6},
+		{0x1e00, 0x1e94, 2},
+		{0x1e9e, 0x1efe, 2},
+		{0x1f08, 0x1f0f, 1},
+		{0x1f18, 0x1f1d, 1},
+		{0x1f28, 0x1f2f, 1},
+		{0x1f38, 0x1f3f, 1},
+		{0x1f48, 0x1f4d, 1},
+		{0x1f59, 0x1f5f, 2},
+		{0x1f68, 0x1f6f, 1},
+		{0x1f88, 0x1f8f, 1},
+		{0x1f98, 0x1f9f, 1},
+		{0x1fa8, 0x1faf, 1},
+		{0x1fb8, 0x1fbc, 1},
+		{0x1fc8, 0x1fcc, 1},
+		{0x1fd8, 0x1fdb, 1},
+		{0x1fe8, 0x1fec, 1},
+		{0x1ff8, 0x1ffc, 1},
+		{0x2126, 0x212a, 4},
+		{0x212b, 0x2132, 7},
+		{0x2183, 0x2c00, 2685},
+		{0x2c01, 0x2c2e, 1},
+		{0x2c60, 0x2c62, 2},
+		{0x2c63, 0x2c64, 1},
+		{0x2c67, 0x2c6d, 2},
+		{0x2c6e, 0x2c70, 1},
+		{0x2c72, 0x2c75, 3},
+		{0x2c7e, 0x2c80, 1},
+		{0x2c82, 0x2ce2, 2},
+		{0x2ceb, 0x2ced, 2},
+		{0x2cf2, 0xa640, 31054},
+		{0xa642, 0xa66c, 2},
+		{0xa680, 0xa696, 2},
+		{0xa722, 0xa72e, 2},
+		{0xa732, 0xa76e, 2},
+		{0xa779, 0xa77d, 2},
+		{0xa77e, 0xa786, 2},
+		{0xa78b, 0xa78d, 2},
+		{0xa790, 0xa792, 2},
+		{0xa7a0, 0xa7aa, 2},
+		{0xff21, 0xff3a, 1},
+	},
+	R32: []Range32{
+		{0x10400, 0x10427, 1},
+	},
+	LatinOffset: 3,
+}
+
+var foldLt = &RangeTable{
+	R16: []Range16{
+		{0x01c4, 0x01c6, 2},
+		{0x01c7, 0x01c9, 2},
+		{0x01ca, 0x01cc, 2},
+		{0x01f1, 0x01f3, 2},
+		{0x1f80, 0x1f87, 1},
+		{0x1f90, 0x1f97, 1},
+		{0x1fa0, 0x1fa7, 1},
+		{0x1fb3, 0x1fc3, 16},
+		{0x1ff3, 0x1ff3, 1},
+	},
+}
+
+var foldLu = &RangeTable{
+	R16: []Range16{
+		{0x0061, 0x007a, 1},
+		{0x00b5, 0x00df, 42},
+		{0x00e0, 0x00f6, 1},
+		{0x00f8, 0x00ff, 1},
+		{0x0101, 0x012f, 2},
+		{0x0133, 0x0137, 2},
+		{0x013a, 0x0148, 2},
+		{0x014b, 0x0177, 2},
+		{0x017a, 0x017e, 2},
+		{0x017f, 0x0180, 1},
+		{0x0183, 0x0185, 2},
+		{0x0188, 0x018c, 4},
+		{0x0192, 0x0195, 3},
+		{0x0199, 0x019a, 1},
+		{0x019e, 0x01a1, 3},
+		{0x01a3, 0x01a5, 2},
+		{0x01a8, 0x01ad, 5},
+		{0x01b0, 0x01b4, 4},
+		{0x01b6, 0x01b9, 3},
+		{0x01bd, 0x01bf, 2},
+		{0x01c5, 0x01c6, 1},
+		{0x01c8, 0x01c9, 1},
+		{0x01cb, 0x01cc, 1},
+		{0x01ce, 0x01dc, 2},
+		{0x01dd, 0x01ef, 2},
+		{0x01f2, 0x01f3, 1},
+		{0x01f5, 0x01f9, 4},
+		{0x01fb, 0x021f, 2},
+		{0x0223, 0x0233, 2},
+		{0x023c, 0x023f, 3},
+		{0x0240, 0x0242, 2},
+		{0x0247, 0x024f, 2},
+		{0x0250, 0x0254, 1},
+		{0x0256, 0x0257, 1},
+		{0x0259, 0x025b, 2},
+		{0x0260, 0x0263, 3},
+		{0x0265, 0x0266, 1},
+		{0x0268, 0x0269, 1},
+		{0x026b, 0x026f, 4},
+		{0x0271, 0x0272, 1},
+		{0x0275, 0x027d, 8},
+		{0x0280, 0x0283, 3},
+		{0x0288, 0x028c, 1},
+		{0x0292, 0x0345, 179},
+		{0x0371, 0x0373, 2},
+		{0x0377, 0x037b, 4},
+		{0x037c, 0x037d, 1},
+		{0x03ac, 0x03af, 1},
+		{0x03b1, 0x03ce, 1},
+		{0x03d0, 0x03d1, 1},
+		{0x03d5, 0x03d7, 1},
+		{0x03d9, 0x03ef, 2},
+		{0x03f0, 0x03f2, 1},
+		{0x03f5, 0x03fb, 3},
+		{0x0430, 0x045f, 1},
+		{0x0461, 0x0481, 2},
+		{0x048b, 0x04bf, 2},
+		{0x04c2, 0x04ce, 2},
+		{0x04cf, 0x0527, 2},
+		{0x0561, 0x0586, 1},
+		{0x1d79, 0x1d7d, 4},
+		{0x1e01, 0x1e95, 2},
+		{0x1e9b, 0x1ea1, 6},
+		{0x1ea3, 0x1eff, 2},
+		{0x1f00, 0x1f07, 1},
+		{0x1f10, 0x1f15, 1},
+		{0x1f20, 0x1f27, 1},
+		{0x1f30, 0x1f37, 1},
+		{0x1f40, 0x1f45, 1},
+		{0x1f51, 0x1f57, 2},
+		{0x1f60, 0x1f67, 1},
+		{0x1f70, 0x1f7d, 1},
+		{0x1fb0, 0x1fb1, 1},
+		{0x1fbe, 0x1fd0, 18},
+		{0x1fd1, 0x1fe0, 15},
+		{0x1fe1, 0x1fe5, 4},
+		{0x214e, 0x2184, 54},
+		{0x2c30, 0x2c5e, 1},
+		{0x2c61, 0x2c65, 4},
+		{0x2c66, 0x2c6c, 2},
+		{0x2c73, 0x2c76, 3},
+		{0x2c81, 0x2ce3, 2},
+		{0x2cec, 0x2cee, 2},
+		{0x2cf3, 0x2d00, 13},
+		{0x2d01, 0x2d25, 1},
+		{0x2d27, 0x2d2d, 6},
+		{0xa641, 0xa66d, 2},
+		{0xa681, 0xa697, 2},
+		{0xa723, 0xa72f, 2},
+		{0xa733, 0xa76f, 2},
+		{0xa77a, 0xa77c, 2},
+		{0xa77f, 0xa787, 2},
+		{0xa78c, 0xa791, 5},
+		{0xa793, 0xa7a1, 14},
+		{0xa7a3, 0xa7a9, 2},
+		{0xff41, 0xff5a, 1},
+	},
+	R32: []Range32{
+		{0x10428, 0x1044f, 1},
+	},
+	LatinOffset: 4,
+}
+
+var foldM = &RangeTable{
+	R16: []Range16{
+		{0x0399, 0x03b9, 32},
+		{0x1fbe, 0x1fbe, 1},
+	},
+}
+
+var foldMn = &RangeTable{
+	R16: []Range16{
+		{0x0399, 0x03b9, 32},
+		{0x1fbe, 0x1fbe, 1},
+	},
+}
+
+// FoldScript maps a script name to a table of
+// code points outside the script that are equivalent under
+// simple case folding to code points inside the script.
+// If there is no entry for a script name, there are no such points.
+var FoldScript = map[string]*RangeTable{}
+
+// Range entries: 3471 16-bit, 832 32-bit, 4303 total.
+// Range bytes: 20826 16-bit, 9984 32-bit, 30810 total.
+
+// Fold orbit bytes: 63 pairs, 252 bytes
diff --git a/third_party/gofrontend/libgo/go/unicode/utf16/export_test.go b/third_party/gofrontend/libgo/go/unicode/utf16/export_test.go
new file mode 100644
index 0000000..306247e
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/utf16/export_test.go
@@ -0,0 +1,11 @@
+// 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 utf16
+
+// Extra names for constants so we can validate them during testing.
+const (
+	MaxRune         = maxRune
+	ReplacementChar = replacementChar
+)
diff --git a/third_party/gofrontend/libgo/go/unicode/utf16/utf16.go b/third_party/gofrontend/libgo/go/unicode/utf16/utf16.go
new file mode 100644
index 0000000..c0e47c5
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/utf16/utf16.go
@@ -0,0 +1,108 @@
+// Copyright 2010 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 utf16 implements encoding and decoding of UTF-16 sequences.
+package utf16
+
+// The conditions replacementChar==unicode.ReplacementChar and
+// maxRune==unicode.MaxRune are verified in the tests.
+// Defining them locally avoids this package depending on package unicode.
+
+const (
+	replacementChar = '\uFFFD'     // Unicode replacement character
+	maxRune         = '\U0010FFFF' // Maximum valid Unicode code point.
+)
+
+const (
+	// 0xd800-0xdc00 encodes the high 10 bits of a pair.
+	// 0xdc00-0xe000 encodes the low 10 bits of a pair.
+	// the value is those 20 bits plus 0x10000.
+	surr1 = 0xd800
+	surr2 = 0xdc00
+	surr3 = 0xe000
+
+	surrSelf = 0x10000
+)
+
+// IsSurrogate returns true if the specified Unicode code point
+// can appear in a surrogate pair.
+func IsSurrogate(r rune) bool {
+	return surr1 <= r && r < surr3
+}
+
+// DecodeRune returns the UTF-16 decoding of a surrogate pair.
+// If the pair is not a valid UTF-16 surrogate pair, DecodeRune returns
+// the Unicode replacement code point U+FFFD.
+func DecodeRune(r1, r2 rune) rune {
+	if surr1 <= r1 && r1 < surr2 && surr2 <= r2 && r2 < surr3 {
+		return (r1-surr1)<<10 | (r2 - surr2) + 0x10000
+	}
+	return replacementChar
+}
+
+// EncodeRune returns the UTF-16 surrogate pair r1, r2 for the given rune.
+// If the rune is not a valid Unicode code point or does not need encoding,
+// EncodeRune returns U+FFFD, U+FFFD.
+func EncodeRune(r rune) (r1, r2 rune) {
+	if r < surrSelf || r > maxRune || IsSurrogate(r) {
+		return replacementChar, replacementChar
+	}
+	r -= surrSelf
+	return surr1 + (r>>10)&0x3ff, surr2 + r&0x3ff
+}
+
+// Encode returns the UTF-16 encoding of the Unicode code point sequence s.
+func Encode(s []rune) []uint16 {
+	n := len(s)
+	for _, v := range s {
+		if v >= surrSelf {
+			n++
+		}
+	}
+
+	a := make([]uint16, n)
+	n = 0
+	for _, v := range s {
+		switch {
+		case v < 0, surr1 <= v && v < surr3, v > maxRune:
+			v = replacementChar
+			fallthrough
+		case v < surrSelf:
+			a[n] = uint16(v)
+			n++
+		default:
+			r1, r2 := EncodeRune(v)
+			a[n] = uint16(r1)
+			a[n+1] = uint16(r2)
+			n += 2
+		}
+	}
+	return a[0:n]
+}
+
+// Decode returns the Unicode code point sequence represented
+// by the UTF-16 encoding s.
+func Decode(s []uint16) []rune {
+	a := make([]rune, len(s))
+	n := 0
+	for i := 0; i < len(s); i++ {
+		switch r := s[i]; {
+		case surr1 <= r && r < surr2 && i+1 < len(s) &&
+			surr2 <= s[i+1] && s[i+1] < surr3:
+			// valid surrogate sequence
+			a[n] = DecodeRune(rune(r), rune(s[i+1]))
+			i++
+			n++
+		case surr1 <= r && r < surr3:
+			// invalid surrogate sequence
+			a[n] = replacementChar
+			n++
+		default:
+			// normal rune
+			a[n] = rune(r)
+			n++
+		}
+	}
+	return a[0:n]
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/utf16/utf16_test.go b/third_party/gofrontend/libgo/go/unicode/utf16/utf16_test.go
new file mode 100644
index 0000000..3dca472
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/utf16/utf16_test.go
@@ -0,0 +1,149 @@
+// Copyright 2010 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 utf16_test
+
+import (
+	"reflect"
+	"testing"
+	"unicode"
+	. "unicode/utf16"
+)
+
+// Validate the constants redefined from unicode.
+func TestConstants(t *testing.T) {
+	if MaxRune != unicode.MaxRune {
+		t.Errorf("utf16.maxRune is wrong: %x should be %x", MaxRune, unicode.MaxRune)
+	}
+	if ReplacementChar != unicode.ReplacementChar {
+		t.Errorf("utf16.replacementChar is wrong: %x should be %x", ReplacementChar, unicode.ReplacementChar)
+	}
+}
+
+type encodeTest struct {
+	in  []rune
+	out []uint16
+}
+
+var encodeTests = []encodeTest{
+	{[]rune{1, 2, 3, 4}, []uint16{1, 2, 3, 4}},
+	{[]rune{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff},
+		[]uint16{0xffff, 0xd800, 0xdc00, 0xd800, 0xdc01, 0xd808, 0xdf45, 0xdbff, 0xdfff}},
+	{[]rune{'a', 'b', 0xd7ff, 0xd800, 0xdfff, 0xe000, 0x110000, -1},
+		[]uint16{'a', 'b', 0xd7ff, 0xfffd, 0xfffd, 0xe000, 0xfffd, 0xfffd}},
+}
+
+func TestEncode(t *testing.T) {
+	for _, tt := range encodeTests {
+		out := Encode(tt.in)
+		if !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("Encode(%x) = %x; want %x", tt.in, out, tt.out)
+		}
+	}
+}
+
+func TestEncodeRune(t *testing.T) {
+	for i, tt := range encodeTests {
+		j := 0
+		for _, r := range tt.in {
+			r1, r2 := EncodeRune(r)
+			if r < 0x10000 || r > unicode.MaxRune {
+				if j >= len(tt.out) {
+					t.Errorf("#%d: ran out of tt.out", i)
+					break
+				}
+				if r1 != unicode.ReplacementChar || r2 != unicode.ReplacementChar {
+					t.Errorf("EncodeRune(%#x) = %#x, %#x; want 0xfffd, 0xfffd", r, r1, r2)
+				}
+				j++
+			} else {
+				if j+1 >= len(tt.out) {
+					t.Errorf("#%d: ran out of tt.out", i)
+					break
+				}
+				if r1 != rune(tt.out[j]) || r2 != rune(tt.out[j+1]) {
+					t.Errorf("EncodeRune(%#x) = %#x, %#x; want %#x, %#x", r, r1, r2, tt.out[j], tt.out[j+1])
+				}
+				j += 2
+				dec := DecodeRune(r1, r2)
+				if dec != r {
+					t.Errorf("DecodeRune(%#x, %#x) = %#x; want %#x", r1, r2, dec, r)
+				}
+			}
+		}
+		if j != len(tt.out) {
+			t.Errorf("#%d: EncodeRune didn't generate enough output", i)
+		}
+	}
+}
+
+type decodeTest struct {
+	in  []uint16
+	out []rune
+}
+
+var decodeTests = []decodeTest{
+	{[]uint16{1, 2, 3, 4}, []rune{1, 2, 3, 4}},
+	{[]uint16{0xffff, 0xd800, 0xdc00, 0xd800, 0xdc01, 0xd808, 0xdf45, 0xdbff, 0xdfff},
+		[]rune{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff}},
+	{[]uint16{0xd800, 'a'}, []rune{0xfffd, 'a'}},
+	{[]uint16{0xdfff}, []rune{0xfffd}},
+}
+
+func TestDecode(t *testing.T) {
+	for _, tt := range decodeTests {
+		out := Decode(tt.in)
+		if !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("Decode(%x) = %x; want %x", tt.in, out, tt.out)
+		}
+	}
+}
+
+var decodeRuneTests = []struct {
+	r1, r2 rune
+	want   rune
+}{
+	{0xd800, 0xdc00, 0x10000},
+	{0xd800, 0xdc01, 0x10001},
+	{0xd808, 0xdf45, 0x12345},
+	{0xdbff, 0xdfff, 0x10ffff},
+	{0xd800, 'a', 0xfffd}, // illegal, replacement rune substituted
+}
+
+func TestDecodeRune(t *testing.T) {
+	for i, tt := range decodeRuneTests {
+		got := DecodeRune(tt.r1, tt.r2)
+		if got != tt.want {
+			t.Errorf("%d: DecodeRune(%q, %q) = %v; want %v", i, tt.r1, tt.r2, got, tt.want)
+		}
+	}
+}
+
+var surrogateTests = []struct {
+	r    rune
+	want bool
+}{
+	// from http://en.wikipedia.org/wiki/UTF-16
+	{'\u007A', false},     // LATIN SMALL LETTER Z
+	{'\u6C34', false},     // CJK UNIFIED IDEOGRAPH-6C34 (water)
+	{'\uFEFF', false},     // Byte Order Mark
+	{'\U00010000', false}, // LINEAR B SYLLABLE B008 A (first non-BMP code point)
+	{'\U0001D11E', false}, // MUSICAL SYMBOL G CLEF
+	{'\U0010FFFD', false}, // PRIVATE USE CHARACTER-10FFFD (last Unicode code point)
+
+	{rune(0xd7ff), false}, // surr1-1
+	{rune(0xd800), true},  // surr1
+	{rune(0xdc00), true},  // surr2
+	{rune(0xe000), false}, // surr3
+	{rune(0xdfff), true},  // surr3-1
+}
+
+func TestIsSurrogate(t *testing.T) {
+	for i, tt := range surrogateTests {
+		got := IsSurrogate(tt.r)
+		if got != tt.want {
+			t.Errorf("%d: IsSurrogate(%q) = %v; want %v", i, tt.r, got, tt.want)
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/utf8/example_test.go b/third_party/gofrontend/libgo/go/unicode/utf8/example_test.go
new file mode 100644
index 0000000..7b3e7ac
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/utf8/example_test.go
@@ -0,0 +1,196 @@
+// Copyright 2013 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 utf8_test
+
+import (
+	"fmt"
+	"unicode/utf8"
+)
+
+func ExampleDecodeLastRune() {
+	b := []byte("Hello, 世界")
+
+	for len(b) > 0 {
+		r, size := utf8.DecodeLastRune(b)
+		fmt.Printf("%c %v\n", r, size)
+
+		b = b[:len(b)-size]
+	}
+	// Output:
+	// 界 3
+	// 世 3
+	//   1
+	// , 1
+	// o 1
+	// l 1
+	// l 1
+	// e 1
+	// H 1
+}
+
+func ExampleDecodeLastRuneInString() {
+	str := "Hello, 世界"
+
+	for len(str) > 0 {
+		r, size := utf8.DecodeLastRuneInString(str)
+		fmt.Printf("%c %v\n", r, size)
+
+		str = str[:len(str)-size]
+	}
+	// Output:
+	// 界 3
+	// 世 3
+	//   1
+	// , 1
+	// o 1
+	// l 1
+	// l 1
+	// e 1
+	// H 1
+
+}
+
+func ExampleDecodeRune() {
+	b := []byte("Hello, 世界")
+
+	for len(b) > 0 {
+		r, size := utf8.DecodeRune(b)
+		fmt.Printf("%c %v\n", r, size)
+
+		b = b[size:]
+	}
+	// Output:
+	// H 1
+	// e 1
+	// l 1
+	// l 1
+	// o 1
+	// , 1
+	//   1
+	// 世 3
+	// 界 3
+}
+
+func ExampleDecodeRuneInString() {
+	str := "Hello, 世界"
+
+	for len(str) > 0 {
+		r, size := utf8.DecodeRuneInString(str)
+		fmt.Printf("%c %v\n", r, size)
+
+		str = str[size:]
+	}
+	// Output:
+	// H 1
+	// e 1
+	// l 1
+	// l 1
+	// o 1
+	// , 1
+	//   1
+	// 世 3
+	// 界 3
+}
+
+func ExampleEncodeRune() {
+	r := '世'
+	buf := make([]byte, 3)
+
+	n := utf8.EncodeRune(buf, r)
+
+	fmt.Println(buf)
+	fmt.Println(n)
+	// Output:
+	// [228 184 150]
+	// 3
+}
+
+func ExampleFullRune() {
+	buf := []byte{228, 184, 150} // 世
+	fmt.Println(utf8.FullRune(buf))
+	fmt.Println(utf8.FullRune(buf[:2]))
+	// Output:
+	// true
+	// false
+}
+
+func ExampleFullRuneInString() {
+	str := "世"
+	fmt.Println(utf8.FullRuneInString(str))
+	fmt.Println(utf8.FullRuneInString(str[:2]))
+	// Output:
+	// true
+	// false
+}
+
+func ExampleRuneCount() {
+	buf := []byte("Hello, 世界")
+	fmt.Println("bytes =", len(buf))
+	fmt.Println("runes =", utf8.RuneCount(buf))
+	// Output:
+	// bytes = 13
+	// runes = 9
+}
+
+func ExampleRuneCountInString() {
+	str := "Hello, 世界"
+	fmt.Println("bytes =", len(str))
+	fmt.Println("runes =", utf8.RuneCountInString(str))
+	// Output:
+	// bytes = 13
+	// runes = 9
+}
+
+func ExampleRuneLen() {
+	fmt.Println(utf8.RuneLen('a'))
+	fmt.Println(utf8.RuneLen('界'))
+	// Output:
+	// 1
+	// 3
+}
+
+func ExampleRuneStart() {
+	buf := []byte("a界")
+	fmt.Println(utf8.RuneStart(buf[0]))
+	fmt.Println(utf8.RuneStart(buf[1]))
+	fmt.Println(utf8.RuneStart(buf[2]))
+	// Output:
+	// true
+	// true
+	// false
+}
+
+func ExampleValid() {
+	valid := []byte("Hello, 世界")
+	invalid := []byte{0xff, 0xfe, 0xfd}
+
+	fmt.Println(utf8.Valid(valid))
+	fmt.Println(utf8.Valid(invalid))
+	// Output:
+	// true
+	// false
+}
+
+func ExampleValidRune() {
+	valid := 'a'
+	invalid := rune(0xfffffff)
+
+	fmt.Println(utf8.ValidRune(valid))
+	fmt.Println(utf8.ValidRune(invalid))
+	// Output:
+	// true
+	// false
+}
+
+func ExampleValidString() {
+	valid := "Hello, 世界"
+	invalid := string([]byte{0xff, 0xfe, 0xfd})
+
+	fmt.Println(utf8.ValidString(valid))
+	fmt.Println(utf8.ValidString(invalid))
+	// Output:
+	// true
+	// false
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/utf8/utf8.go b/third_party/gofrontend/libgo/go/unicode/utf8/utf8.go
new file mode 100644
index 0000000..0dc859a
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/utf8/utf8.go
@@ -0,0 +1,435 @@
+// 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 utf8 implements functions and constants to support text encoded in
+// UTF-8. It includes functions to translate between runes and UTF-8 byte sequences.
+package utf8
+
+// The conditions RuneError==unicode.ReplacementChar and
+// MaxRune==unicode.MaxRune are verified in the tests.
+// Defining them locally avoids this package depending on package unicode.
+
+// Numbers fundamental to the encoding.
+const (
+	RuneError = '\uFFFD'     // the "error" Rune or "Unicode replacement character"
+	RuneSelf  = 0x80         // characters below Runeself are represented as themselves in a single byte.
+	MaxRune   = '\U0010FFFF' // Maximum valid Unicode code point.
+	UTFMax    = 4            // maximum number of bytes of a UTF-8 encoded Unicode character.
+)
+
+// Code points in the surrogate range are not valid for UTF-8.
+const (
+	surrogateMin = 0xD800
+	surrogateMax = 0xDFFF
+)
+
+const (
+	t1 = 0x00 // 0000 0000
+	tx = 0x80 // 1000 0000
+	t2 = 0xC0 // 1100 0000
+	t3 = 0xE0 // 1110 0000
+	t4 = 0xF0 // 1111 0000
+	t5 = 0xF8 // 1111 1000
+
+	maskx = 0x3F // 0011 1111
+	mask2 = 0x1F // 0001 1111
+	mask3 = 0x0F // 0000 1111
+	mask4 = 0x07 // 0000 0111
+
+	rune1Max = 1<<7 - 1
+	rune2Max = 1<<11 - 1
+	rune3Max = 1<<16 - 1
+)
+
+func decodeRuneInternal(p []byte) (r rune, size int, short bool) {
+	n := len(p)
+	if n < 1 {
+		return RuneError, 0, true
+	}
+	c0 := p[0]
+
+	// 1-byte, 7-bit sequence?
+	if c0 < tx {
+		return rune(c0), 1, false
+	}
+
+	// unexpected continuation byte?
+	if c0 < t2 {
+		return RuneError, 1, false
+	}
+
+	// need first continuation byte
+	if n < 2 {
+		return RuneError, 1, true
+	}
+	c1 := p[1]
+	if c1 < tx || t2 <= c1 {
+		return RuneError, 1, false
+	}
+
+	// 2-byte, 11-bit sequence?
+	if c0 < t3 {
+		r = rune(c0&mask2)<<6 | rune(c1&maskx)
+		if r <= rune1Max {
+			return RuneError, 1, false
+		}
+		return r, 2, false
+	}
+
+	// need second continuation byte
+	if n < 3 {
+		return RuneError, 1, true
+	}
+	c2 := p[2]
+	if c2 < tx || t2 <= c2 {
+		return RuneError, 1, false
+	}
+
+	// 3-byte, 16-bit sequence?
+	if c0 < t4 {
+		r = rune(c0&mask3)<<12 | rune(c1&maskx)<<6 | rune(c2&maskx)
+		if r <= rune2Max {
+			return RuneError, 1, false
+		}
+		if surrogateMin <= r && r <= surrogateMax {
+			return RuneError, 1, false
+		}
+		return r, 3, false
+	}
+
+	// need third continuation byte
+	if n < 4 {
+		return RuneError, 1, true
+	}
+	c3 := p[3]
+	if c3 < tx || t2 <= c3 {
+		return RuneError, 1, false
+	}
+
+	// 4-byte, 21-bit sequence?
+	if c0 < t5 {
+		r = rune(c0&mask4)<<18 | rune(c1&maskx)<<12 | rune(c2&maskx)<<6 | rune(c3&maskx)
+		if r <= rune3Max || MaxRune < r {
+			return RuneError, 1, false
+		}
+		return r, 4, false
+	}
+
+	// error
+	return RuneError, 1, false
+}
+
+func decodeRuneInStringInternal(s string) (r rune, size int, short bool) {
+	n := len(s)
+	if n < 1 {
+		return RuneError, 0, true
+	}
+	c0 := s[0]
+
+	// 1-byte, 7-bit sequence?
+	if c0 < tx {
+		return rune(c0), 1, false
+	}
+
+	// unexpected continuation byte?
+	if c0 < t2 {
+		return RuneError, 1, false
+	}
+
+	// need first continuation byte
+	if n < 2 {
+		return RuneError, 1, true
+	}
+	c1 := s[1]
+	if c1 < tx || t2 <= c1 {
+		return RuneError, 1, false
+	}
+
+	// 2-byte, 11-bit sequence?
+	if c0 < t3 {
+		r = rune(c0&mask2)<<6 | rune(c1&maskx)
+		if r <= rune1Max {
+			return RuneError, 1, false
+		}
+		return r, 2, false
+	}
+
+	// need second continuation byte
+	if n < 3 {
+		return RuneError, 1, true
+	}
+	c2 := s[2]
+	if c2 < tx || t2 <= c2 {
+		return RuneError, 1, false
+	}
+
+	// 3-byte, 16-bit sequence?
+	if c0 < t4 {
+		r = rune(c0&mask3)<<12 | rune(c1&maskx)<<6 | rune(c2&maskx)
+		if r <= rune2Max {
+			return RuneError, 1, false
+		}
+		if surrogateMin <= r && r <= surrogateMax {
+			return RuneError, 1, false
+		}
+		return r, 3, false
+	}
+
+	// need third continuation byte
+	if n < 4 {
+		return RuneError, 1, true
+	}
+	c3 := s[3]
+	if c3 < tx || t2 <= c3 {
+		return RuneError, 1, false
+	}
+
+	// 4-byte, 21-bit sequence?
+	if c0 < t5 {
+		r = rune(c0&mask4)<<18 | rune(c1&maskx)<<12 | rune(c2&maskx)<<6 | rune(c3&maskx)
+		if r <= rune3Max || MaxRune < r {
+			return RuneError, 1, false
+		}
+		return r, 4, false
+	}
+
+	// error
+	return RuneError, 1, false
+}
+
+// FullRune reports whether the bytes in p begin with a full UTF-8 encoding of a rune.
+// An invalid encoding is considered a full Rune since it will convert as a width-1 error rune.
+func FullRune(p []byte) bool {
+	_, _, short := decodeRuneInternal(p)
+	return !short
+}
+
+// FullRuneInString is like FullRune but its input is a string.
+func FullRuneInString(s string) bool {
+	_, _, short := decodeRuneInStringInternal(s)
+	return !short
+}
+
+// DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and its width in bytes.
+// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
+func DecodeRune(p []byte) (r rune, size int) {
+	r, size, _ = decodeRuneInternal(p)
+	return
+}
+
+// DecodeRuneInString is like DecodeRune but its input is a string.
+// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
+func DecodeRuneInString(s string) (r rune, size int) {
+	r, size, _ = decodeRuneInStringInternal(s)
+	return
+}
+
+// DecodeLastRune unpacks the last UTF-8 encoding in p and returns the rune and its width in bytes.
+// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
+func DecodeLastRune(p []byte) (r rune, size int) {
+	end := len(p)
+	if end == 0 {
+		return RuneError, 0
+	}
+	start := end - 1
+	r = rune(p[start])
+	if r < RuneSelf {
+		return r, 1
+	}
+	// guard against O(n^2) behavior when traversing
+	// backwards through strings with long sequences of
+	// invalid UTF-8.
+	lim := end - UTFMax
+	if lim < 0 {
+		lim = 0
+	}
+	for start--; start >= lim; start-- {
+		if RuneStart(p[start]) {
+			break
+		}
+	}
+	if start < 0 {
+		start = 0
+	}
+	r, size = DecodeRune(p[start:end])
+	if start+size != end {
+		return RuneError, 1
+	}
+	return r, size
+}
+
+// DecodeLastRuneInString is like DecodeLastRune but its input is a string.
+// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
+func DecodeLastRuneInString(s string) (r rune, size int) {
+	end := len(s)
+	if end == 0 {
+		return RuneError, 0
+	}
+	start := end - 1
+	r = rune(s[start])
+	if r < RuneSelf {
+		return r, 1
+	}
+	// guard against O(n^2) behavior when traversing
+	// backwards through strings with long sequences of
+	// invalid UTF-8.
+	lim := end - UTFMax
+	if lim < 0 {
+		lim = 0
+	}
+	for start--; start >= lim; start-- {
+		if RuneStart(s[start]) {
+			break
+		}
+	}
+	if start < 0 {
+		start = 0
+	}
+	r, size = DecodeRuneInString(s[start:end])
+	if start+size != end {
+		return RuneError, 1
+	}
+	return r, size
+}
+
+// RuneLen returns the number of bytes required to encode the rune.
+// It returns -1 if the rune is not a valid value to encode in UTF-8.
+func RuneLen(r rune) int {
+	switch {
+	case r < 0:
+		return -1
+	case r <= rune1Max:
+		return 1
+	case r <= rune2Max:
+		return 2
+	case surrogateMin <= r && r <= surrogateMax:
+		return -1
+	case r <= rune3Max:
+		return 3
+	case r <= MaxRune:
+		return 4
+	}
+	return -1
+}
+
+// EncodeRune writes into p (which must be large enough) the UTF-8 encoding of the rune.
+// It returns the number of bytes written.
+func EncodeRune(p []byte, r rune) int {
+	// Negative values are erroneous.  Making it unsigned addresses the problem.
+	switch i := uint32(r); {
+	case i <= rune1Max:
+		p[0] = byte(r)
+		return 1
+	case i <= rune2Max:
+		p[0] = t2 | byte(r>>6)
+		p[1] = tx | byte(r)&maskx
+		return 2
+	case i > MaxRune, surrogateMin <= i && i <= surrogateMax:
+		r = RuneError
+		fallthrough
+	case i <= rune3Max:
+		p[0] = t3 | byte(r>>12)
+		p[1] = tx | byte(r>>6)&maskx
+		p[2] = tx | byte(r)&maskx
+		return 3
+	default:
+		p[0] = t4 | byte(r>>18)
+		p[1] = tx | byte(r>>12)&maskx
+		p[2] = tx | byte(r>>6)&maskx
+		p[3] = tx | byte(r)&maskx
+		return 4
+	}
+}
+
+// RuneCount returns the number of runes in p.  Erroneous and short
+// encodings are treated as single runes of width 1 byte.
+func RuneCount(p []byte) int {
+	i := 0
+	var n int
+	for n = 0; i < len(p); n++ {
+		if p[i] < RuneSelf {
+			i++
+		} else {
+			_, size := DecodeRune(p[i:])
+			i += size
+		}
+	}
+	return n
+}
+
+// RuneCountInString is like RuneCount but its input is a string.
+func RuneCountInString(s string) (n int) {
+	for _ = range s {
+		n++
+	}
+	return
+}
+
+// RuneStart reports whether the byte could be the first byte of
+// an encoded rune.  Second and subsequent bytes always have the top
+// two bits set to 10.
+func RuneStart(b byte) bool { return b&0xC0 != 0x80 }
+
+// Valid reports whether p consists entirely of valid UTF-8-encoded runes.
+func Valid(p []byte) bool {
+	i := 0
+	for i < len(p) {
+		if p[i] < RuneSelf {
+			i++
+		} else {
+			_, size := DecodeRune(p[i:])
+			if size == 1 {
+				// All valid runes of size 1 (those
+				// below RuneSelf) were handled above.
+				// This must be a RuneError.
+				return false
+			}
+			i += size
+		}
+	}
+	return true
+}
+
+// ValidString reports whether s consists entirely of valid UTF-8-encoded runes.
+func ValidString(s string) bool {
+	for i, r := range s {
+		if r == RuneError {
+			// The RuneError value can be an error
+			// sentinel value (if it's size 1) or the same
+			// value encoded properly. Decode it to see if
+			// it's the 1 byte sentinel value.
+			_, size := DecodeRuneInString(s[i:])
+			if size == 1 {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+// ValidRune reports whether r can be legally encoded as UTF-8.
+// Code points that are out of range or a surrogate half are illegal.
+func ValidRune(r rune) bool {
+	switch {
+	case r < 0:
+		return false
+	case surrogateMin <= r && r <= surrogateMax:
+		return false
+	case r > MaxRune:
+		return false
+	}
+	return true
+}
diff --git a/third_party/gofrontend/libgo/go/unicode/utf8/utf8_test.go b/third_party/gofrontend/libgo/go/unicode/utf8/utf8_test.go
new file mode 100644
index 0000000..758d7a0
--- /dev/null
+++ b/third_party/gofrontend/libgo/go/unicode/utf8/utf8_test.go
@@ -0,0 +1,444 @@
+// 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 utf8_test
+
+import (
+	"bytes"
+	"testing"
+	"unicode"
+	. "unicode/utf8"
+)
+
+// Validate the constants redefined from unicode.
+func init() {
+	if MaxRune != unicode.MaxRune {
+		panic("utf8.MaxRune is wrong")
+	}
+	if RuneError != unicode.ReplacementChar {
+		panic("utf8.RuneError is wrong")
+	}
+}
+
+// Validate the constants redefined from unicode.
+func TestConstants(t *testing.T) {
+	if MaxRune != unicode.MaxRune {
+		t.Errorf("utf8.MaxRune is wrong: %x should be %x", MaxRune, unicode.MaxRune)
+	}
+	if RuneError != unicode.ReplacementChar {
+		t.Errorf("utf8.RuneError is wrong: %x should be %x", RuneError, unicode.ReplacementChar)
+	}
+}
+
+type Utf8Map struct {
+	r   rune
+	str string
+}
+
+var utf8map = []Utf8Map{
+	{0x0000, "\x00"},
+	{0x0001, "\x01"},
+	{0x007e, "\x7e"},
+	{0x007f, "\x7f"},
+	{0x0080, "\xc2\x80"},
+	{0x0081, "\xc2\x81"},
+	{0x00bf, "\xc2\xbf"},
+	{0x00c0, "\xc3\x80"},
+	{0x00c1, "\xc3\x81"},
+	{0x00c8, "\xc3\x88"},
+	{0x00d0, "\xc3\x90"},
+	{0x00e0, "\xc3\xa0"},
+	{0x00f0, "\xc3\xb0"},
+	{0x00f8, "\xc3\xb8"},
+	{0x00ff, "\xc3\xbf"},
+	{0x0100, "\xc4\x80"},
+	{0x07ff, "\xdf\xbf"},
+	{0x0800, "\xe0\xa0\x80"},
+	{0x0801, "\xe0\xa0\x81"},
+	{0xd7ff, "\xed\x9f\xbf"}, // last code point before surrogate half.
+	{0xe000, "\xee\x80\x80"}, // first code point after surrogate half.
+	{0xfffe, "\xef\xbf\xbe"},
+	{0xffff, "\xef\xbf\xbf"},
+	{0x10000, "\xf0\x90\x80\x80"},
+	{0x10001, "\xf0\x90\x80\x81"},
+	{0x10fffe, "\xf4\x8f\xbf\xbe"},
+	{0x10ffff, "\xf4\x8f\xbf\xbf"},
+	{0xFFFD, "\xef\xbf\xbd"},
+}
+
+var surrogateMap = []Utf8Map{
+	{0xd800, "\xed\xa0\x80"}, // surrogate min decodes to (RuneError, 1)
+	{0xdfff, "\xed\xbf\xbf"}, // surrogate max decodes to (RuneError, 1)
+}
+
+var testStrings = []string{
+	"",
+	"abcd",
+	"☺☻☹",
+	"日a本b語ç日ð本Ê語þ日¥本¼語i日©",
+	"日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©",
+	"\x80\x80\x80\x80",
+}
+
+func TestFullRune(t *testing.T) {
+	for _, m := range utf8map {
+		b := []byte(m.str)
+		if !FullRune(b) {
+			t.Errorf("FullRune(%q) (%U) = false, want true", b, m.r)
+		}
+		s := m.str
+		if !FullRuneInString(s) {
+			t.Errorf("FullRuneInString(%q) (%U) = false, want true", s, m.r)
+		}
+		b1 := b[0 : len(b)-1]
+		if FullRune(b1) {
+			t.Errorf("FullRune(%q) = true, want false", b1)
+		}
+		s1 := string(b1)
+		if FullRuneInString(s1) {
+			t.Errorf("FullRune(%q) = true, want false", s1)
+		}
+	}
+}
+
+func TestEncodeRune(t *testing.T) {
+	for _, m := range utf8map {
+		b := []byte(m.str)
+		var buf [10]byte
+		n := EncodeRune(buf[0:], m.r)
+		b1 := buf[0:n]
+		if !bytes.Equal(b, b1) {
+			t.Errorf("EncodeRune(%#04x) = %q want %q", m.r, b1, b)
+		}
+	}
+}
+
+func TestDecodeRune(t *testing.T) {
+	for _, m := range utf8map {
+		b := []byte(m.str)
+		r, size := DecodeRune(b)
+		if r != m.r || size != len(b) {
+			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, r, size, m.r, len(b))
+		}
+		s := m.str
+		r, size = DecodeRuneInString(s)
+		if r != m.r || size != len(b) {
+			t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, m.r, len(b))
+		}
+
+		// there's an extra byte that bytes left behind - make sure trailing byte works
+		r, size = DecodeRune(b[0:cap(b)])
+		if r != m.r || size != len(b) {
+			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, r, size, m.r, len(b))
+		}
+		s = m.str + "\x00"
+		r, size = DecodeRuneInString(s)
+		if r != m.r || size != len(b) {
+			t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, m.r, len(b))
+		}
+
+		// make sure missing bytes fail
+		wantsize := 1
+		if wantsize >= len(b) {
+			wantsize = 0
+		}
+		r, size = DecodeRune(b[0 : len(b)-1])
+		if r != RuneError || size != wantsize {
+			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b[0:len(b)-1], r, size, RuneError, wantsize)
+		}
+		s = m.str[0 : len(m.str)-1]
+		r, size = DecodeRuneInString(s)
+		if r != RuneError || size != wantsize {
+			t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, RuneError, wantsize)
+		}
+
+		// make sure bad sequences fail
+		if len(b) == 1 {
+			b[0] = 0x80
+		} else {
+			b[len(b)-1] = 0x7F
+		}
+		r, size = DecodeRune(b)
+		if r != RuneError || size != 1 {
+			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, r, size, RuneError, 1)
+		}
+		s = string(b)
+		r, size = DecodeRuneInString(s)
+		if r != RuneError || size != 1 {
+			t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, RuneError, 1)
+		}
+
+	}
+}
+
+func TestDecodeSurrogateRune(t *testing.T) {
+	for _, m := range surrogateMap {
+		b := []byte(m.str)
+		r, size := DecodeRune(b)
+		if r != RuneError || size != 1 {
+			t.Errorf("DecodeRune(%q) = %x, %d want %x, %d", b, r, size, RuneError, 1)
+		}
+		s := m.str
+		r, size = DecodeRuneInString(s)
+		if r != RuneError || size != 1 {
+			t.Errorf("DecodeRuneInString(%q) = %x, %d want %x, %d", b, r, size, RuneError, 1)
+		}
+	}
+}
+
+// Check that DecodeRune and DecodeLastRune correspond to
+// the equivalent range loop.
+func TestSequencing(t *testing.T) {
+	for _, ts := range testStrings {
+		for _, m := range utf8map {
+			for _, s := range []string{ts + m.str, m.str + ts, ts + m.str + ts} {
+				testSequence(t, s)
+			}
+		}
+	}
+}
+
+// Check that a range loop and a []int conversion visit the same runes.
+// Not really a test of this package, but the assumption is used here and
+// it's good to verify
+func TestIntConversion(t *testing.T) {
+	for _, ts := range testStrings {
+		runes := []rune(ts)
+		if RuneCountInString(ts) != len(runes) {
+			t.Errorf("%q: expected %d runes; got %d", ts, len(runes), RuneCountInString(ts))
+			break
+		}
+		i := 0
+		for _, r := range ts {
+			if r != runes[i] {
+				t.Errorf("%q[%d]: expected %c (%U); got %c (%U)", ts, i, runes[i], runes[i], r, r)
+			}
+			i++
+		}
+	}
+}
+
+func testSequence(t *testing.T, s string) {
+	type info struct {
+		index int
+		r     rune
+	}
+	index := make([]info, len(s))
+	b := []byte(s)
+	si := 0
+	j := 0
+	for i, r := range s {
+		if si != i {
+			t.Errorf("Sequence(%q) mismatched index %d, want %d", s, si, i)
+			return
+		}
+		index[j] = info{i, r}
+		j++
+		r1, size1 := DecodeRune(b[i:])
+		if r != r1 {
+			t.Errorf("DecodeRune(%q) = %#04x, want %#04x", s[i:], r1, r)
+			return
+		}
+		r2, size2 := DecodeRuneInString(s[i:])
+		if r != r2 {
+			t.Errorf("DecodeRuneInString(%q) = %#04x, want %#04x", s[i:], r2, r)
+			return
+		}
+		if size1 != size2 {
+			t.Errorf("DecodeRune/DecodeRuneInString(%q) size mismatch %d/%d", s[i:], size1, size2)
+			return
+		}
+		si += size1
+	}
+	j--
+	for si = len(s); si > 0; {
+		r1, size1 := DecodeLastRune(b[0:si])
+		r2, size2 := DecodeLastRuneInString(s[0:si])
+		if size1 != size2 {
+			t.Errorf("DecodeLastRune/DecodeLastRuneInString(%q, %d) size mismatch %d/%d", s, si, size1, size2)
+			return
+		}
+		if r1 != index[j].r {
+			t.Errorf("DecodeLastRune(%q, %d) = %#04x, want %#04x", s, si, r1, index[j].r)
+			return
+		}
+		if r2 != index[j].r {
+			t.Errorf("DecodeLastRuneInString(%q, %d) = %#04x, want %#04x", s, si, r2, index[j].r)
+			return
+		}
+		si -= size1
+		if si != index[j].index {
+			t.Errorf("DecodeLastRune(%q) index mismatch at %d, want %d", s, si, index[j].index)
+			return
+		}
+		j--
+	}
+	if si != 0 {
+		t.Errorf("DecodeLastRune(%q) finished at %d, not 0", s, si)
+	}
+}
+
+// Check that negative runes encode as U+FFFD.
+func TestNegativeRune(t *testing.T) {
+	errorbuf := make([]byte, UTFMax)
+	errorbuf = errorbuf[0:EncodeRune(errorbuf, RuneError)]
+	buf := make([]byte, UTFMax)
+	buf = buf[0:EncodeRune(buf, -1)]
+	if !bytes.Equal(buf, errorbuf) {
+		t.Errorf("incorrect encoding [% x] for -1; expected [% x]", buf, errorbuf)
+	}
+}
+
+type RuneCountTest struct {
+	in  string
+	out int
+}
+
+var runecounttests = []RuneCountTest{
+	{"abcd", 4},
+	{"☺☻☹", 3},
+	{"1,2,3,4", 7},
+	{"\xe2\x00", 2},
+}
+
+func TestRuneCount(t *testing.T) {
+	for _, tt := range runecounttests {
+		if out := RuneCountInString(tt.in); out != tt.out {
+			t.Errorf("RuneCountInString(%q) = %d, want %d", tt.in, out, tt.out)
+		}
+		if out := RuneCount([]byte(tt.in)); out != tt.out {
+			t.Errorf("RuneCount(%q) = %d, want %d", tt.in, out, tt.out)
+		}
+	}
+}
+
+type RuneLenTest struct {
+	r    rune
+	size int
+}
+
+var runelentests = []RuneLenTest{
+	{0, 1},
+	{'e', 1},
+	{'é', 2},
+	{'☺', 3},
+	{RuneError, 3},
+	{MaxRune, 4},
+	{0xD800, -1},
+	{0xDFFF, -1},
+	{MaxRune + 1, -1},
+	{-1, -1},
+}
+
+func TestRuneLen(t *testing.T) {
+	for _, tt := range runelentests {
+		if size := RuneLen(tt.r); size != tt.size {
+			t.Errorf("RuneLen(%#U) = %d, want %d", tt.r, size, tt.size)
+		}
+	}
+}
+
+type ValidTest struct {
+	in  string
+	out bool
+}
+
+var validTests = []ValidTest{
+	{"", true},
+	{"a", true},
+	{"abc", true},
+	{"Ж", true},
+	{"ЖЖ", true},
+	{"брэд-ЛГТМ", true},
+	{"☺☻☹", true},
+	{string([]byte{66, 250}), false},
+	{string([]byte{66, 250, 67}), false},
+	{"a\uFFFDb", true},
+	{string("\xF4\x8F\xBF\xBF"), true},      // U+10FFFF
+	{string("\xF4\x90\x80\x80"), false},     // U+10FFFF+1; out of range
+	{string("\xF7\xBF\xBF\xBF"), false},     // 0x1FFFFF; out of range
+	{string("\xFB\xBF\xBF\xBF\xBF"), false}, // 0x3FFFFFF; out of range
+	{string("\xc0\x80"), false},             // U+0000 encoded in two bytes: incorrect
+	{string("\xed\xa0\x80"), false},         // U+D800 high surrogate (sic)
+	{string("\xed\xbf\xbf"), false},         // U+DFFF low surrogate (sic)
+}
+
+func TestValid(t *testing.T) {
+	for _, tt := range validTests {
+		if Valid([]byte(tt.in)) != tt.out {
+			t.Errorf("Valid(%q) = %v; want %v", tt.in, !tt.out, tt.out)
+		}
+		if ValidString(tt.in) != tt.out {
+			t.Errorf("ValidString(%q) = %v; want %v", tt.in, !tt.out, tt.out)
+		}
+	}
+}
+
+type ValidRuneTest struct {
+	r  rune
+	ok bool
+}
+
+var validrunetests = []ValidRuneTest{
+	{0, true},
+	{'e', true},
+	{'é', true},
+	{'☺', true},
+	{RuneError, true},
+	{MaxRune, true},
+	{0xD7FF, true},
+	{0xD800, false},
+	{0xDFFF, false},
+	{0xE000, true},
+	{MaxRune + 1, false},
+	{-1, false},
+}
+
+func TestValidRune(t *testing.T) {
+	for _, tt := range validrunetests {
+		if ok := ValidRune(tt.r); ok != tt.ok {
+			t.Errorf("ValidRune(%#U) = %t, want %t", tt.r, ok, tt.ok)
+		}
+	}
+}
+
+func BenchmarkRuneCountTenASCIIChars(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		RuneCountInString("0123456789")
+	}
+}
+
+func BenchmarkRuneCountTenJapaneseChars(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		RuneCountInString("日本語日本語日本語日")
+	}
+}
+
+func BenchmarkEncodeASCIIRune(b *testing.B) {
+	buf := make([]byte, UTFMax)
+	for i := 0; i < b.N; i++ {
+		EncodeRune(buf, 'a')
+	}
+}
+
+func BenchmarkEncodeJapaneseRune(b *testing.B) {
+	buf := make([]byte, UTFMax)
+	for i := 0; i < b.N; i++ {
+		EncodeRune(buf, '本')
+	}
+}
+
+func BenchmarkDecodeASCIIRune(b *testing.B) {
+	a := []byte{'a'}
+	for i := 0; i < b.N; i++ {
+		DecodeRune(a)
+	}
+}
+
+func BenchmarkDecodeJapaneseRune(b *testing.B) {
+	nihon := []byte("本")
+	for i := 0; i < b.N; i++ {
+		DecodeRune(nihon)
+	}
+}
diff --git a/third_party/gofrontend/libgo/godeps.sh b/third_party/gofrontend/libgo/godeps.sh
new file mode 100755
index 0000000..7ae5af9
--- /dev/null
+++ b/third_party/gofrontend/libgo/godeps.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# 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.
+
+# The godeps.sh script outputs a dependency file for a package.  The
+# dependency file is then included in the libgo Makefile.  This is
+# automatic dependency generation, Go style.
+
+# The first parameter is the name of the file being generated.  The
+# remaining parameters are the names of Go files which are scanned for
+# imports.
+
+set -e
+
+if test $# = 0; then
+    echo 1>&2 "Usage: godeps.sh OUTPUT INPUTS..."
+    exit 1
+fi
+
+output=$1
+shift
+
+deps=`for f in $*; do cat $f; done | 
+  sed -n -e '/^import.*"/p; /^import[ 	]*(/,/^)/p' |
+  grep '"' |
+  grep -v '"unsafe"' |
+  sed -e 's/^.*"\([^"]*\)".*$/\1/' -e 's/$/.gox/' |
+  sort -u`
+
+echo $output: $deps
diff --git a/third_party/gofrontend/libgo/merge.sh b/third_party/gofrontend/libgo/merge.sh
new file mode 100755
index 0000000..e579ac7
--- /dev/null
+++ b/third_party/gofrontend/libgo/merge.sh
@@ -0,0 +1,190 @@
+#!/bin/sh
+
+# 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.
+
+# This script merges changes from the master copy of the Go library
+# into the libgo library.  This does the easy stuff; the hard stuff is
+# left to the user.
+
+# The file MERGE should hold the Mercurial revision number of the last
+# revision which was merged into these sources.  Given that, and given
+# the current sources, we can run the usual diff3 algorithm to merge
+# all changes into our sources.
+
+set -e
+
+TMPDIR=${TMPDIR:-/tmp}
+
+OLDDIR=${TMPDIR}/libgo-merge-old
+NEWDIR=${TMPDIR}/libgo-merge-new
+
+if ! test -f MERGE; then
+  echo 1>&2 "merge.sh: must be run in libgo source directory"
+  exit 1
+fi
+
+rev=weekly
+case $# in
+1) ;;
+2) rev=$2 ;;
+*)
+  echo 1>&2 "merge.sh: Usage: merge.sh mercurial-repository [revision]"
+  exit 1
+  ;;
+esac
+
+repository=$1
+
+old_rev=`sed 1q MERGE`
+
+rm -rf ${OLDDIR}
+hg clone -r ${old_rev} ${repository} ${OLDDIR}
+
+rm -rf ${NEWDIR}
+hg clone -u ${rev} ${repository} ${NEWDIR}
+
+new_rev=`cd ${NEWDIR} && hg log -r ${rev} | sed 1q | sed -e 's/.*://'`
+
+merge() {
+  name=$1
+  old=$2
+  new=$3
+  libgo=$4
+  if ! test -f ${new}; then
+    # The file does not exist in the new version.
+    if ! test -f ${old}; then
+      echo 1>&2 "merge.sh internal error no files $old $new"
+      exit 1
+    fi
+    if ! test -f ${libgo}; then
+      # File removed in new version and libgo.
+      :;
+    else
+      echo "merge.sh: ${name}: REMOVED"
+      rm -f ${libgo}
+      hg rm ${libgo}
+    fi
+  elif test -f ${old}; then
+    # The file exists in the old version.
+    if ! test -f ${libgo}; then
+      echo "merge.sh: $name: skipping: exists in old and new hg, but not in libgo"
+      continue
+    fi
+    if cmp -s ${old} ${libgo}; then
+      # The libgo file is unchanged from the old version.
+      if cmp -s ${new} ${libgo}; then
+        # File is unchanged from old to new version.
+        continue
+      fi
+      # Update file in libgo.
+      echo "merge.sh: $name: updating"
+      cp ${new} ${libgo}
+    else
+      # The libgo file has local changes.
+      set +e
+      diff3 -m -E ${libgo} ${old} ${new} > ${libgo}.tmp
+      status=$?
+      set -e
+      case $status in
+      0)
+        echo "merge.sh: $name: updating"
+        mv ${libgo}.tmp ${libgo}
+        ;;
+      1)
+        echo "merge.sh: $name: CONFLICTS"
+        mv ${libgo}.tmp ${libgo}
+        hg resolve -u ${libgo}
+        ;;
+      *)
+        echo 1>&2 "merge.sh: $name: diff3 failure"
+        exit 1
+        ;;
+      esac
+    fi
+  else
+    # The file does not exist in the old version.
+    if test -f ${libgo}; then
+      if ! cmp -s ${new} ${libgo}; then
+        echo 1>&2 "merge.sh: $name: IN NEW AND LIBGO BUT NOT OLD"
+      fi
+    else
+      echo "merge.sh: $name: NEW"
+      dir=`dirname ${libgo}`
+      if ! test -d ${dir}; then
+        mkdir -p ${dir}
+      fi
+      cp ${new} ${libgo}
+      hg add ${libgo}
+    fi
+  fi
+}
+
+merge_c() {
+  from=$1
+  to=$2
+  oldfile=${OLDDIR}/src/pkg/runtime/$from
+  if test -f ${oldfile}; then
+    sed -e 's/·/_/g' < ${oldfile} > ${oldfile}.tmp
+    oldfile=${oldfile}.tmp
+    newfile=${NEWDIR}/src/pkg/runtime/$from
+    sed -e 's/·/_/g' < ${newfile} > ${newfile}.tmp
+    newfile=${newfile}.tmp
+    libgofile=runtime/$to
+    merge $from ${oldfile} ${newfile} ${libgofile}
+  fi
+}
+
+(cd ${NEWDIR}/src/pkg && find . -name '*.go' -print) | while read f; do
+  oldfile=${OLDDIR}/src/pkg/$f
+  newfile=${NEWDIR}/src/pkg/$f
+  libgofile=go/$f
+  merge $f ${oldfile} ${newfile} ${libgofile}
+done
+
+(cd ${NEWDIR}/src/pkg && find . -name testdata -print) | while read d; do
+  oldtd=${OLDDIR}/src/pkg/$d
+  newtd=${NEWDIR}/src/pkg/$d
+  libgotd=go/$d
+  if ! test -d ${oldtd}; then
+    continue
+  fi
+  (cd ${oldtd} && hg status -A .) | while read f; do
+    if test "`basename $f`" = ".hgignore"; then
+      continue
+    fi
+    f=`echo $f | sed -e 's/^..//'`
+    name=$d/$f
+    oldfile=${oldtd}/$f
+    newfile=${newtd}/$f
+    libgofile=${libgotd}/$f
+    merge ${name} ${oldfile} ${newfile} ${libgofile}
+  done
+done
+
+runtime="chan.goc chan.h cpuprof.goc env_posix.c heapdump.c lock_futex.c lfstack.goc lock_sema.c mcache.c mcentral.c mfixalloc.c mgc0.c mgc0.h mheap.c msize.c netpoll.goc netpoll_epoll.c netpoll_kqueue.c netpoll_stub.c panic.c print.c proc.c race.h rdebug.goc runtime.c runtime.h signal_unix.c signal_unix.h malloc.h malloc.goc mprof.goc parfor.c runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
+for f in $runtime; do
+  merge_c $f $f
+done
+
+merge_c os_linux.c thread-linux.c
+merge_c mem_linux.c mem.c
+
+(cd ${OLDDIR}/src/pkg && find . -name '*.go' -print) | while read f; do
+  oldfile=${OLDDIR}/src/pkg/$f
+  newfile=${NEWDIR}/src/pkg/$f
+  libgofile=go/$f
+  if test -f ${newfile}; then
+    continue
+  fi
+  if ! test -f ${libgofile}; then
+    continue
+  fi
+  echo "merge.sh: ${libgofile}: REMOVED"
+  rm -f ${libgofile}
+  hg rm ${libgofile}
+done
+
+(echo ${new_rev}; sed -ne '2,$p' MERGE) > MERGE.tmp
+mv MERGE.tmp MERGE
diff --git a/third_party/gofrontend/libgo/mksysinfo.sh b/third_party/gofrontend/libgo/mksysinfo.sh
new file mode 100755
index 0000000..ddfa8bb
--- /dev/null
+++ b/third_party/gofrontend/libgo/mksysinfo.sh
@@ -0,0 +1,1281 @@
+#!/bin/sh
+
+# 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.
+
+# Create sysinfo.go.
+
+# This shell script creates the sysinfo.go file which holds types and
+# constants extracted from the system header files.  This relies on a
+# hook in gcc: the -fdump-go-spec option will generate debugging
+# information in Go syntax.
+
+# We currently #include all the files at once, which works, but leads
+# to exposing some names which ideally should not be exposed, as they
+# match grep patterns.  E.g., WCHAR_MIN gets exposed because it starts
+# with W, like the wait flags.
+
+CC=${CC:-gcc}
+OUT=tmp-sysinfo.go
+
+set -e
+
+rm -f sysinfo.c
+cat > sysinfo.c <<EOF
+#include "config.h"
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+/* <netinet/tcp.h> needs u_char/u_short, but <sys/bsd_types> is only
+   included by <netinet/in.h> if _SGIAPI (i.e. _SGI_SOURCE
+   && !_XOPEN_SOURCE.
+   <sys/termios.h> only defines TIOCNOTTY if !_XOPEN_SOURCE, while
+   <sys/ttold.h> does so unconditionally.  */
+#ifdef __sgi__
+#include <sys/bsd_types.h>
+#include <sys/ttold.h>
+#endif
+#include <netinet/tcp.h>
+#if defined(HAVE_NETINET_IN_SYSTM_H)
+#include <netinet/in_systm.h>
+#endif
+#if defined(HAVE_NETINET_IP_H)
+#include <netinet/ip.h>
+#endif
+#if defined(HAVE_NETINET_IP_MROUTE_H)
+#include <netinet/ip_mroute.h>
+#endif
+#if defined(HAVE_NETINET_IF_ETHER_H)
+#include <netinet/if_ether.h>
+#endif
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#if defined(HAVE_SYSCALL_H)
+#include <syscall.h>
+#endif
+#if defined(HAVE_SYS_SYSCALL_H)
+#include <sys/syscall.h>
+#endif
+#if defined(HAVE_SYS_EPOLL_H)
+#include <sys/epoll.h>
+#endif
+#if defined(HAVE_SYS_FILE_H)
+#include <sys/file.h>
+#endif
+#if defined(HAVE_SYS_MMAN_H)
+#include <sys/mman.h>
+#endif
+#if defined(HAVE_SYS_PRCTL_H)
+#include <sys/prctl.h>
+#endif
+#if defined(HAVE_SYS_PTRACE_H)
+#include <sys/ptrace.h>
+#endif
+#include <sys/resource.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#if defined(HAVE_SYS_USER_H)
+#include <sys/user.h>
+#endif
+#if defined(HAVE_SYS_UTSNAME_H)
+#include <sys/utsname.h>
+#endif
+#if defined(HAVE_SYS_SELECT_H)
+#include <sys/select.h>
+#endif
+#include <time.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <pwd.h>
+#if defined(HAVE_LINUX_FILTER_H)
+#include <linux/filter.h>
+#endif
+#if defined(HAVE_LINUX_IF_ADDR_H)
+#include <linux/if_addr.h>
+#endif
+#if defined(HAVE_LINUX_IF_ETHER_H)
+#include <linux/if_ether.h>
+#endif
+#if defined(HAVE_LINUX_IF_TUN_H)
+#include <linux/if_tun.h>
+#endif
+#if defined(HAVE_LINUX_NETLINK_H)
+#include <linux/netlink.h>
+#endif
+#if defined(HAVE_LINUX_RTNETLINK_H)
+#include <linux/rtnetlink.h>
+#endif
+#if defined(HAVE_NET_IF_H)
+#include <net/if.h>
+#endif
+#if defined(HAVE_NET_IF_ARP_H)
+#include <net/if_arp.h>
+#endif
+#if defined(HAVE_NET_ROUTE_H)
+#include <net/route.h>
+#endif
+#if defined (HAVE_NETPACKET_PACKET_H)
+#include <netpacket/packet.h>
+#endif
+#if defined(HAVE_SYS_MOUNT_H)
+#include <sys/mount.h>
+#endif
+#if defined(HAVE_SYS_VFS_H)
+#include <sys/vfs.h>
+#endif
+#if defined(HAVE_STATFS_H)
+#include <sys/statfs.h>
+#endif
+#if defined(HAVE_SYS_TIMEX_H)
+#include <sys/timex.h>
+#endif
+#if defined(HAVE_SYS_SYSINFO_H)
+#include <sys/sysinfo.h>
+#endif
+#if defined(HAVE_USTAT_H)
+#include <ustat.h>
+#endif
+#if defined(HAVE_UTIME_H)
+#include <utime.h>
+#endif
+#if defined(HAVE_LINUX_ETHER_H)
+#include <linux/ether.h>
+#endif
+#if defined(HAVE_LINUX_FS_H)
+#include <linux/fs.h>
+#endif
+#if defined(HAVE_LINUX_REBOOT_H)
+#include <linux/reboot.h>
+#endif
+#if defined(HAVE_SYS_INOTIFY_H)
+#include <sys/inotify.h>
+#endif
+#if defined(HAVE_NETINET_ICMP6_H)
+#include <netinet/icmp6.h>
+#endif
+#if defined(HAVE_SCHED_H)
+#include <sched.h>
+#endif
+
+/* Constants that may only be defined as expressions on some systems,
+   expressions too complex for -fdump-go-spec to handle.  These are
+   handled specially below.  */
+enum {
+#ifdef TIOCGWINSZ
+  TIOCGWINSZ_val = TIOCGWINSZ,
+#endif
+#ifdef TIOCSWINSZ
+  TIOCSWINSZ_val = TIOCSWINSZ,
+#endif
+#ifdef TIOCNOTTY
+  TIOCNOTTY_val = TIOCNOTTY,
+#endif
+#ifdef TIOCSCTTY
+  TIOCSCTTY_val = TIOCSCTTY,
+#endif
+#ifdef TIOCGPTN
+  TIOCGPTN_val = TIOCGPTN,
+#endif
+#ifdef TIOCSPTLCK
+  TIOCSPTLCK_val = TIOCSPTLCK,
+#endif
+#ifdef TIOCGDEV
+  TIOCGDEV_val = TIOCGDEV,
+#endif
+#ifdef TIOCSIG
+  TIOCSIG_val = TIOCSIG,
+#endif
+#ifdef TCGETS
+  TCGETS_val = TCGETS,
+#endif
+#ifdef TCSETS
+  TCSETS_val = TCSETS,
+#endif
+};
+EOF
+
+${CC} -fdump-go-spec=gen-sysinfo.go -std=gnu99 -S -o sysinfo.s sysinfo.c
+
+echo 'package syscall' > ${OUT}
+echo 'import "unsafe"' >> ${OUT}
+echo 'type _ unsafe.Pointer' >> ${OUT}
+
+# Get all the consts and types, skipping ones which could not be
+# represented in Go and ones which we need to rewrite.  We also skip
+# function declarations, as we don't need them here.  All the symbols
+# will all have a leading underscore.
+grep -v '^// ' gen-sysinfo.go | \
+  grep -v '^func' | \
+  grep -v '^type _timeval ' | \
+  grep -v '^type _timespec_t ' | \
+  grep -v '^type _timespec ' | \
+  grep -v '^type _timestruc_t ' | \
+  grep -v '^type _epoll_' | \
+  grep -v 'in6_addr' | \
+  grep -v 'sockaddr_in6' | \
+  sed -e 's/\([^a-zA-Z0-9_]\)_timeval\([^a-zA-Z0-9_]\)/\1Timeval\2/g' \
+      -e 's/\([^a-zA-Z0-9_]\)_timespec_t\([^a-zA-Z0-9_]\)/\1Timespec\2/g' \
+      -e 's/\([^a-zA-Z0-9_]\)_timespec\([^a-zA-Z0-9_]\)/\1Timespec\2/g' \
+      -e 's/\([^a-zA-Z0-9_]\)_timestruc_t\([^a-zA-Z0-9_]\)/\1Timestruc\2/g' \
+    >> ${OUT}
+
+# The errno constants.  These get type Errno.
+echo '#include <errno.h>' | ${CC} -x c - -E -dM | \
+  egrep '#define E[A-Z0-9_]+ ' | \
+  sed -e 's/^#define \(E[A-Z0-9_]*\) .*$/const \1 = Errno(_\1)/' >> ${OUT}
+
+# The O_xxx flags.
+egrep '^const _(O|F|FD)_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\([^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+if ! grep '^const O_ASYNC' ${OUT} >/dev/null 2>&1; then
+  echo "const O_ASYNC = 0" >> ${OUT}
+fi
+if ! grep '^const O_CLOEXEC' ${OUT} >/dev/null 2>&1; then
+  echo "const O_CLOEXEC = 0" >> ${OUT}
+fi
+
+# The os package requires F_DUPFD_CLOEXEC to be defined.
+if ! grep '^const F_DUPFD_CLOEXEC' ${OUT} >/dev/null 2>&1; then
+  echo "const F_DUPFD_CLOEXEC = 0" >> ${OUT}
+fi
+
+# These flags can be lost on i386 GNU/Linux when using
+# -D_FILE_OFFSET_BITS=64, because we see "#define F_SETLK F_SETLK64"
+# before we see the definition of F_SETLK64.
+for flag in F_GETLK F_SETLK F_SETLKW; do
+  if ! grep "^const ${flag} " ${OUT} >/dev/null 2>&1 \
+      && grep "^const ${flag}64 " ${OUT} >/dev/null 2>&1; then
+    echo "const ${flag} = ${flag}64" >> ${OUT}
+  fi
+done
+
+# The Flock_t struct for fcntl.
+grep '^type _flock ' gen-sysinfo.go | \
+    sed -e 's/type _flock/type Flock_t/' \
+      -e 's/l_type/Type/' \
+      -e 's/l_whence/Whence/' \
+      -e 's/l_start/Start/' \
+      -e 's/l_len/Len/' \
+      -e 's/l_pid/Pid/' \
+    >> ${OUT}
+
+# The signal numbers.
+grep '^const _SIG[^_]' gen-sysinfo.go | \
+  grep -v '^const _SIGEV_' | \
+  sed -e 's/^\(const \)_\(SIG[^= ]*\)\(.*\)$/\1\2 = Signal(_\2)/' >> ${OUT}
+if ! grep '^const SIGPOLL ' ${OUT} >/dev/null 2>&1; then
+  if grep '^const SIGIO ' ${OUT} > /dev/null 2>&1; then
+    echo "const SIGPOLL = SIGIO" >> ${OUT}
+  fi
+fi
+if ! grep '^const SIGCLD ' ${OUT} >/dev/null 2>&1; then
+  if grep '^const SIGCHLD ' ${OUT} >/dev/null 2>&1; then
+    echo "const SIGCLD = SIGCHLD" >> ${OUT}
+  fi
+fi
+
+# The syscall numbers.  We force the names to upper case.
+grep '^const _SYS_' gen-sysinfo.go | \
+  sed -e 's/const _\(SYS_[^= ]*\).*$/\1/' | \
+  while read sys; do
+    sup=`echo $sys | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+    echo "const $sup = _$sys" >> ${OUT}
+  done
+
+# The GNU/Linux support wants to use SYS_GETDENTS64 if available.
+if ! grep '^const SYS_GETDENTS ' ${OUT} >/dev/null 2>&1; then
+  echo "const SYS_GETDENTS = 0" >> ${OUT}
+fi
+if ! grep '^const SYS_GETDENTS64 ' ${OUT} >/dev/null 2>&1; then
+  echo "const SYS_GETDENTS64 = 0" >> ${OUT}
+fi
+
+# Stat constants.
+grep '^const _S_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(S_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# Mmap constants.
+grep '^const _PROT_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(PROT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _MAP_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(MAP_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _MADV_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(MADV_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _MCL_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(MCL_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# Process status constants.
+grep '^const _W' gen-sysinfo.go |
+  sed -e 's/^\(const \)_\(W[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+# WSTOPPED was introduced in glibc 2.3.4.
+if ! grep '^const _WSTOPPED = ' gen-sysinfo.go >/dev/null 2>&1; then
+  if grep '^const _WUNTRACED = ' gen-sysinfo.go > /dev/null 2>&1; then
+    echo 'const WSTOPPED = _WUNTRACED' >> ${OUT}
+  else
+    echo 'const WSTOPPED = 2' >> ${OUT}
+  fi
+fi
+if grep '^const ___WALL = ' gen-sysinfo.go >/dev/null 2>&1 \
+   && ! grep '^const _WALL = ' gen-sysinfo.go >/dev/null 2>&1; then
+  echo 'const WALL = ___WALL' >> ${OUT}
+fi
+
+# Networking constants.
+egrep '^const _(AF|ARPHRD|ETH|IN|SOCK|SOL|SO|IPPROTO|TCP|IP|IPV6)_' gen-sysinfo.go |
+  sed -e 's/^\(const \)_\([^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _SOMAXCONN' gen-sysinfo.go |
+  sed -e 's/^\(const \)_\(SOMAXCONN[^= ]*\)\(.*\)$/\1\2 = _\2/' \
+    >> ${OUT}
+grep '^const _SHUT_' gen-sysinfo.go |
+  sed -e 's/^\(const \)_\(SHUT[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The net package requires some const definitions.
+for m in IP_PKTINFO IPV6_V6ONLY IPPROTO_IPV6 IPV6_JOIN_GROUP IPV6_LEAVE_GROUP IPV6_TCLASS SO_REUSEPORT; do
+  if ! grep "^const $m " ${OUT} >/dev/null 2>&1; then
+    echo "const $m = 0" >> ${OUT}
+  fi
+done
+for m in SOCK_CLOEXEC SOCK_NONBLOCK; do
+  if ! grep "^const $m " ${OUT} >/dev/null 2>&1; then
+    echo "const $m = -1" >> ${OUT}
+  fi
+done
+
+# The syscall package requires AF_LOCAL.
+if ! grep '^const AF_LOCAL ' ${OUT} >/dev/null 2>&1; then
+  if grep '^const AF_UNIX ' ${OUT} >/dev/null 2>&1; then
+    echo "const AF_LOCAL = AF_UNIX" >> ${OUT}
+  fi
+fi
+
+# pathconf constants.
+grep '^const __PC' gen-sysinfo.go |
+  sed -e 's/^\(const \)__\(PC[^= ]*\)\(.*\)$/\1\2 = __\2/' >> ${OUT}
+
+# The PATH_MAX constant.
+if grep '^const _PATH_MAX ' gen-sysinfo.go >/dev/null 2>&1; then
+  echo 'const PathMax = _PATH_MAX' >> ${OUT}
+fi
+
+# epoll constants.
+grep '^const _EPOLL' gen-sysinfo.go |
+  sed -e 's/^\(const \)_\(EPOLL[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+# Make sure EPOLLRDHUP and EPOLL_CLOEXEC are defined.
+if ! grep '^const EPOLLRDHUP' ${OUT} >/dev/null 2>&1; then
+  echo "const EPOLLRDHUP = 0x2000" >> ${OUT}
+fi
+if ! grep '^const EPOLL_CLOEXEC' ${OUT} >/dev/null 2>&1; then
+  echo "const EPOLL_CLOEXEC = 02000000" >> ${OUT}
+fi
+
+# Prctl constants.
+grep '^const _PR_' gen-sysinfo.go |
+  sed -e 's/^\(const \)_\(PR_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# Ptrace constants.
+grep '^const _PTRACE' gen-sysinfo.go |
+  sed -e 's/^\(const \)_\(PTRACE[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+# We need some ptrace options that are not defined in older versions
+# of glibc.
+if ! grep '^const PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_SETOPTIONS = 0x4200" >> ${OUT}
+fi
+if ! grep '^const PTRACE_O_TRACESYSGOOD' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_O_TRACESYSGOOD = 0x1" >> ${OUT}
+fi
+if ! grep '^const PTRACE_O_TRACEFORK' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_O_TRACEFORK = 0x2" >> ${OUT}
+fi
+if ! grep '^const PTRACE_O_TRACEVFORK' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_O_TRACEVFORK = 0x4" >> ${OUT}
+fi
+if ! grep '^const PTRACE_O_TRACECLONE' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_O_TRACECLONE = 0x8" >> ${OUT}
+fi
+if ! grep '^const PTRACE_O_TRACEEXEC' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_O_TRACEEXEC = 0x10" >> ${OUT}
+fi
+if ! grep '^const PTRACE_O_TRACEVFORKDONE' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_O_TRACEVFORKDONE = 0x20" >> ${OUT}
+fi
+if ! grep '^const PTRACE_O_TRACEEXIT' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_O_TRACEEXIT = 0x40" >> ${OUT}
+fi
+if ! grep '^const PTRACE_O_MASK' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_O_MASK = 0x7f" >> ${OUT}
+fi
+if ! grep '^const _PTRACE_GETEVENTMSG' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_GETEVENTMSG = 0x4201" >> ${OUT}
+fi
+if ! grep '^const PTRACE_EVENT_FORK' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_EVENT_FORK = 1" >> ${OUT}
+fi
+if ! grep '^const PTRACE_EVENT_VFORK' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_EVENT_VFORK = 2" >> ${OUT}
+fi
+if ! grep '^const PTRACE_EVENT_CLONE' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_EVENT_CLONE = 3" >> ${OUT}
+fi
+if ! grep '^const PTRACE_EVENT_EXEC' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_EVENT_EXEC = 4" >> ${OUT}
+fi
+if ! grep '^const PTRACE_EVENT_VFORK_DONE' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_EVENT_VFORK_DONE = 5" >> ${OUT}
+fi
+if ! grep '^const PTRACE_EVENT_EXIT' ${OUT} > /dev/null 2>&1; then
+  echo "const PTRACE_EVENT_EXIT = 6" >> ${OUT}
+fi
+if ! grep '^const _PTRACE_TRACEME' ${OUT} > /dev/null 2>&1; then
+  echo "const _PTRACE_TRACEME = 0" >> ${OUT}
+fi
+
+# A helper function that prints a structure from gen-sysinfo.go with the first
+# letter of the field names in upper case.  $1 is the name of structure.  If $2
+# is not empty, the structure or type is renamed to $2.
+upcase_fields () {
+  name="$1"
+  def=`grep "^type $name" gen-sysinfo.go`
+  fields=`echo $def | sed -e 's/^[^{]*{\(.*\)}$/\1/'`
+  prefix=`echo $def | sed -e 's/{.*//'`
+  if test "$2" != ""; then
+    prefix=`echo $prefix | sed -e "s/$1/$2/"`
+  fi
+  if test "$fields" != ""; then
+    nfields=
+    while test -n "$fields"; do
+      field=`echo $fields | sed -e 's/^\([^;]*\);.*$/\1/'`
+      fields=`echo $fields | sed -e 's/^[^;]*; *\(.*\)$/\1/'`
+      # capitalize the next character.
+      f=`echo $field | sed -e 's/^\(.\).*$/\1/'`
+      r=`echo $field | sed -e 's/^.\(.*\)$/\1/'`
+      f=`echo $f | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+      field="$f$r"
+      nfields="$nfields $field;"
+    done
+    echo "${prefix} {$nfields }"
+  fi
+}
+
+# The registers returned by PTRACE_GETREGS.  This is probably
+# GNU/Linux specific; it should do no harm if there is no
+# _user_regs_struct.
+regs=`grep '^type _user_regs_struct struct' gen-sysinfo.go || true`
+if test "$regs" == ""; then
+  # s390
+  regs=`grep '^type __user_regs_struct struct' gen-sysinfo.go || true`
+  if test "$regs" != ""; then
+    # Substructures of __user_regs_struct on s390
+    upcase_fields "__user_psw_struct" "PtracePsw" >> ${OUT} || true
+    upcase_fields "__user_fpregs_struct" "PtraceFpregs" >> ${OUT} || true
+    upcase_fields "__user_per_struct" "PtracePer" >> ${OUT} || true
+  fi
+fi
+if test "$regs" != ""; then
+  regs=`echo $regs |
+    sed -e 's/type __*user_regs_struct struct //' -e 's/[{}]//g'`
+  regs=`echo $regs | sed -e s'/^ *//'`
+  nregs=
+  while test -n "$regs"; do
+    field=`echo $regs | sed -e 's/^\([^;]*\);.*$/\1/'`
+    regs=`echo $regs | sed -e 's/^[^;]*; *\(.*\)$/\1/'`
+    # Capitalize the first character of the field.
+    f=`echo $field | sed -e 's/^\(.\).*$/\1/'`
+    r=`echo $field | sed -e 's/^.\(.*\)$/\1/'`
+    f=`echo $f | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+    field="$f$r"
+    field=`echo "$field" | sed \
+      -e 's/__user_psw_struct/PtracePsw/' \
+      -e 's/__user_fpregs_struct/PtraceFpregs/' \
+      -e 's/__user_per_struct/PtracePer/'`
+    nregs="$nregs $field;"
+  done
+  echo "type PtraceRegs struct {$nregs }" >> ${OUT}
+fi
+
+# Some basic types.
+echo 'type Size_t _size_t' >> ${OUT}
+echo "type Ssize_t _ssize_t" >> ${OUT}
+if grep '^const _HAVE_OFF64_T = ' gen-sysinfo.go > /dev/null 2>&1; then
+  echo "type Offset_t _off64_t" >> ${OUT}
+else
+  echo "type Offset_t _off_t" >> ${OUT}
+fi
+echo "type Mode_t _mode_t" >> ${OUT}
+echo "type Pid_t _pid_t" >> ${OUT}
+echo "type Uid_t _uid_t" >> ${OUT}
+echo "type Gid_t _gid_t" >> ${OUT}
+echo "type Socklen_t _socklen_t" >> ${OUT}
+
+# The C int type.
+sizeof_int=`grep '^const ___SIZEOF_INT__ = ' gen-sysinfo.go | sed -e 's/.*= //'`
+if test "$sizeof_int" = "4"; then
+  echo "type _C_int int32" >> ${OUT}
+  echo "type _C_uint uint32" >> ${OUT}
+elif test "$sizeof_int" = "8"; then
+  echo "type _C_int int64" >> ${OUT}
+  echo "type _C_uint uint64" >> ${OUT}
+else
+  echo 1>&2 "mksysinfo.sh: could not determine size of int (got $sizeof_int)"
+  exit 1
+fi
+
+# The C long type, needed because that is the type that ptrace returns.
+sizeof_long=`grep '^const ___SIZEOF_LONG__ = ' gen-sysinfo.go | sed -e 's/.*= //'`
+if test "$sizeof_long" = "4"; then
+  echo "type _C_long int32" >> ${OUT}
+elif test "$sizeof_long" = "8"; then
+  echo "type _C_long int64" >> ${OUT}
+else
+  echo 1>&2 "mksysinfo.sh: could not determine size of long (got $sizeof_long)"
+  exit 1
+fi
+
+# Solaris 2 needs _u?pad128_t, but its default definition in terms of long
+# double is commented by -fdump-go-spec.
+if grep "^// type _pad128_t" gen-sysinfo.go > /dev/null 2>&1; then
+  echo "type _pad128_t struct { _l [4]int32; }" >> ${OUT}
+fi
+if grep "^// type _upad128_t" gen-sysinfo.go > /dev/null 2>&1; then
+  echo "type _upad128_t struct { _l [4]uint32; }" >> ${OUT}
+fi
+
+# The time_t type.
+if grep '^type _time_t ' gen-sysinfo.go > /dev/null 2>&1; then
+  echo 'type Time_t _time_t' >> ${OUT}
+fi
+
+# The time structures need special handling: we need to name the
+# types, so that we can cast integers to the right types when
+# assigning to the structures.
+timeval=`grep '^type _timeval ' gen-sysinfo.go`
+timeval_sec=`echo $timeval | sed -n -e 's/^.*tv_sec \([^ ]*\);.*$/\1/p'`
+timeval_usec=`echo $timeval | sed -n -e 's/^.*tv_usec \([^ ]*\);.*$/\1/p'`
+echo "type Timeval_sec_t $timeval_sec" >> ${OUT}
+echo "type Timeval_usec_t $timeval_usec" >> ${OUT}
+echo $timeval | \
+  sed -e 's/type _timeval /type Timeval /' \
+      -e 's/tv_sec *[a-zA-Z0-9_]*/Sec Timeval_sec_t/' \
+      -e 's/tv_usec *[a-zA-Z0-9_]*/Usec Timeval_usec_t/' >> ${OUT}
+timespec=`grep '^type _timespec ' gen-sysinfo.go || true`
+if test "$timespec" = ""; then
+  # IRIX 6.5 has __timespec instead.
+  timespec=`grep '^type ___timespec ' gen-sysinfo.go || true`
+fi
+timespec_sec=`echo $timespec | sed -n -e 's/^.*tv_sec \([^ ]*\);.*$/\1/p'`
+timespec_nsec=`echo $timespec | sed -n -e 's/^.*tv_nsec \([^ ]*\);.*$/\1/p'`
+echo "type Timespec_sec_t $timespec_sec" >> ${OUT}
+echo "type Timespec_nsec_t $timespec_nsec" >> ${OUT}
+echo $timespec | \
+  sed -e 's/^type ___timespec /type Timespec /' \
+      -e 's/^type _timespec /type Timespec /' \
+      -e 's/tv_sec *[a-zA-Z0-9_]*/Sec Timespec_sec_t/' \
+      -e 's/tv_nsec *[a-zA-Z0-9_]*/Nsec Timespec_nsec_t/' >> ${OUT}
+
+timestruc=`grep '^type _timestruc_t ' gen-sysinfo.go || true`
+if test "$timestruc" != ""; then
+  timestruc_sec=`echo $timestruc | sed -n -e 's/^.*tv_sec \([^ ]*\);.*$/\1/p'`
+  timestruc_nsec=`echo $timestruc | sed -n -e 's/^.*tv_nsec \([^ ]*\);.*$/\1/p'`
+  echo "type Timestruc_sec_t $timestruc_sec" >> ${OUT}
+  echo "type Timestruc_nsec_t $timestruc_nsec" >> ${OUT}
+  echo $timestruc | \
+    sed -e 's/^type _timestruc_t /type Timestruc /' \
+        -e 's/tv_sec *[a-zA-Z0-9_]*/Sec Timestruc_sec_t/' \
+        -e 's/tv_nsec *[a-zA-Z0-9_]*/Nsec Timestruc_nsec_t/' >> ${OUT}
+fi
+
+# The tms struct.
+grep '^type _tms ' gen-sysinfo.go | \
+    sed -e 's/type _tms/type Tms/' \
+      -e 's/tms_utime/Utime/' \
+      -e 's/tms_stime/Stime/' \
+      -e 's/tms_cutime/Cutime/' \
+      -e 's/tms_cstime/Cstime/' \
+    >> ${OUT}
+
+# The stat type.
+# Prefer largefile variant if available.
+stat=`grep '^type _stat64 ' gen-sysinfo.go || true`
+if test "$stat" != ""; then
+  grep '^type _stat64 ' gen-sysinfo.go
+else
+  grep '^type _stat ' gen-sysinfo.go
+fi | sed -e 's/type _stat64/type Stat_t/' \
+         -e 's/type _stat/type Stat_t/' \
+         -e 's/st_dev/Dev/' \
+         -e 's/st_ino/Ino/g' \
+         -e 's/st_nlink/Nlink/' \
+         -e 's/st_mode/Mode/' \
+         -e 's/st_uid/Uid/' \
+         -e 's/st_gid/Gid/' \
+         -e 's/st_rdev/Rdev/' \
+         -e 's/st_size/Size/' \
+         -e 's/st_blksize/Blksize/' \
+         -e 's/st_blocks/Blocks/' \
+         -e 's/st_atim/Atim/' \
+         -e 's/st_mtim/Mtim/' \
+         -e 's/st_ctim/Ctim/' \
+         -e 's/\([^a-zA-Z0-9_]\)_timeval\([^a-zA-Z0-9_]\)/\1Timeval\2/g' \
+         -e 's/\([^a-zA-Z0-9_]\)_timespec_t\([^a-zA-Z0-9_]\)/\1Timespec\2/g' \
+         -e 's/\([^a-zA-Z0-9_]\)_timespec\([^a-zA-Z0-9_]\)/\1Timespec\2/g' \
+         -e 's/\([^a-zA-Z0-9_]\)_timestruc_t\([^a-zA-Z0-9_]\)/\1Timestruc\2/g' \
+         -e 's/Godump_[0-9] struct { \([^;]*;\) };/\1/g' \
+       >> ${OUT}
+
+# The directory searching types.
+# Prefer largefile variant if available.
+dirent=`grep '^type _dirent64 ' gen-sysinfo.go || true`
+if test "$dirent" != ""; then
+  grep '^type _dirent64 ' gen-sysinfo.go
+else
+  grep '^type _dirent ' gen-sysinfo.go
+fi | sed -e 's/type _dirent64/type Dirent/' \
+         -e 's/type _dirent/type Dirent/' \
+         -e 's/d_name \[0+1\]/d_name [0+256]/' \
+         -e 's/d_name/Name/' \
+         -e 's/]int8/]byte/' \
+         -e 's/d_ino/Ino/' \
+         -e 's/d_off/Off/' \
+         -e 's/d_reclen/Reclen/' \
+         -e 's/d_type/Type/' \
+      >> ${OUT}
+echo "type DIR _DIR" >> ${OUT}
+
+# Values for d_type field in dirent.
+grep '^const _DT_' gen-sysinfo.go |
+  sed -e 's/^\(const \)_\(DT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The rusage struct.
+rusage=`grep '^type _rusage struct' gen-sysinfo.go`
+if test "$rusage" != ""; then
+  # Remove anonymous unions from GNU/Linux <bits/resource.h>.
+  rusage=`echo $rusage | sed -e 's/Godump_[0-9][0-9]* struct {\([^}]*\)};/\1/g'`
+  rusage=`echo $rusage | sed -e 's/type _rusage struct //' -e 's/[{}]//g'`
+  rusage=`echo $rusage | sed -e 's/^ *//'`
+  nrusage=
+  while test -n "$rusage"; do
+    field=`echo $rusage | sed -e 's/^\([^;]*\);.*$/\1/'`
+    rusage=`echo $rusage | sed -e 's/^[^;]*; *\(.*\)$/\1/'`
+    # Drop the leading ru_, capitalize the next character.
+    field=`echo $field | sed -e 's/^ru_//'`
+    f=`echo $field | sed -e 's/^\(.\).*$/\1/'`
+    r=`echo $field | sed -e 's/^.\(.*\)$/\1/'`
+    f=`echo $f | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+    # Fix _timeval _timespec, and _timestruc_t.
+    r=`echo $r | sed -e s'/ _timeval$/ Timeval/'`
+    r=`echo $r | sed -e s'/ _timespec$/ Timespec/'`
+    r=`echo $r | sed -e s'/ _timestruc_t$/ Timestruc/'`
+    field="$f$r"
+    nrusage="$nrusage $field;"
+  done
+  echo "type Rusage struct {$nrusage }" >> ${OUT}
+else
+  echo "type Rusage struct {}" >> ${OUT}
+fi
+
+# The RUSAGE constants.
+grep '^const _RUSAGE_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(RUSAGE_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The utsname struct.
+grep '^type _utsname ' gen-sysinfo.go | \
+    sed -e 's/_utsname/Utsname/' \
+      -e 's/sysname/Sysname/' \
+      -e 's/nodename/Nodename/' \
+      -e 's/release/Release/' \
+      -e 's/version/Version/' \
+      -e 's/machine/Machine/' \
+      -e 's/domainname/Domainname/' \
+    >> ${OUT}
+
+# The iovec struct.
+iovec=`grep '^type _iovec ' gen-sysinfo.go`
+iovec_len=`echo $iovec | sed -n -e 's/^.*iov_len \([^ ]*\);.*$/\1/p'`
+echo "type Iovec_len_t $iovec_len" >> ${OUT}
+echo $iovec | \
+    sed -e 's/_iovec/Iovec/' \
+      -e 's/iov_base/Base/' \
+      -e 's/iov_len *[a-zA-Z0-9_]*/Len Iovec_len_t/' \
+    >> ${OUT}
+
+# The msghdr struct.
+msghdr=`grep '^type _msghdr ' gen-sysinfo.go`
+msghdr_controllen=`echo $msghdr | sed -n -e 's/^.*msg_controllen \([^ ]*\);.*$/\1/p'`
+echo "type Msghdr_controllen_t $msghdr_controllen" >> ${OUT}
+echo $msghdr | \
+    sed -e 's/_msghdr/Msghdr/' \
+      -e 's/msg_name/Name/' \
+      -e 's/msg_namelen/Namelen/' \
+      -e 's/msg_iov/Iov/' \
+      -e 's/msg_iovlen/Iovlen/' \
+      -e 's/_iovec/Iovec/' \
+      -e 's/msg_control/Control/' \
+      -e 's/msg_controllen *[a-zA-Z0-9_]*/Controllen Msghdr_controllen_t/' \
+      -e 's/msg_flags/Flags/' \
+    >> ${OUT}
+
+# The MSG_ flags for Msghdr.
+grep '^const _MSG_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(MSG_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The cmsghdr struct.
+cmsghdr=`grep '^type _cmsghdr ' gen-sysinfo.go`
+if test -n "$cmsghdr"; then
+  cmsghdr_len=`echo $cmsghdr | sed -n -e 's/^.*cmsg_len \([^ ]*\);.*$/\1/p'`
+  echo "type Cmsghdr_len_t $cmsghdr_len" >> ${OUT}
+  echo "$cmsghdr" | \
+      sed -e 's/_cmsghdr/Cmsghdr/' \
+        -e 's/cmsg_len *[a-zA-Z0-9_]*/Len Cmsghdr_len_t/' \
+        -e 's/cmsg_level/Level/' \
+        -e 's/cmsg_type/Type/' \
+        -e 's/\[\]/[0]/' \
+      >> ${OUT}
+fi
+
+# The SCM_ flags for Cmsghdr.
+grep '^const _SCM_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(SCM_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The ucred struct.
+upcase_fields "_ucred" "Ucred" >> ${OUT} || true
+
+# The ip_mreq struct.
+grep '^type _ip_mreq ' gen-sysinfo.go | \
+    sed -e 's/_ip_mreq/IPMreq/' \
+      -e 's/imr_multiaddr/Multiaddr/' \
+      -e 's/imr_interface/Interface/' \
+      -e 's/_in_addr/[4]byte/g' \
+    >> ${OUT}
+
+# We need IPMreq to compile the net package.
+if ! grep 'type IPMreq ' ${OUT} >/dev/null 2>&1; then
+  echo 'type IPMreq struct { Multiaddr [4]byte; Interface [4]byte; }' >> ${OUT}
+fi
+
+# The ipv6_mreq struct.
+grep '^type _ipv6_mreq ' gen-sysinfo.go | \
+    sed -e 's/_ipv6_mreq/IPv6Mreq/' \
+      -e 's/ipv6mr_multiaddr/Multiaddr/' \
+      -e 's/ipv6mr_interface/Interface/' \
+      -e 's/_in6_addr/[16]byte/' \
+    >> ${OUT}
+
+# We need IPv6Mreq to compile the net package.
+if ! grep 'type IPv6Mreq ' ${OUT} >/dev/null 2>&1; then
+  echo 'type IPv6Mreq struct { Multiaddr [16]byte; Interface uint32; }' >> ${OUT}
+fi
+
+# The ip_mreqn struct.
+grep '^type _ip_mreqn ' gen-sysinfo.go | \
+    sed -e 's/_ip_mreqn/IPMreqn/' \
+      -e 's/imr_multiaddr/Multiaddr/' \
+      -e 's/imr_address/Address/' \
+      -e 's/imr_ifindex/Ifindex/' \
+      -e 's/_in_addr/[4]byte/g' \
+    >> ${OUT}
+
+# We need IPMreq to compile the net package.
+if ! grep 'type IPMreqn ' ${OUT} >/dev/null 2>&1; then
+  echo 'type IPMreqn struct { Multiaddr [4]byte; Interface [4]byte; Ifindex int32 }' >> ${OUT}
+fi
+
+# The icmp6_filter struct.
+grep '^type _icmp6_filter ' gen-sysinfo.go | \
+    sed -e 's/_icmp6_filter/ICMPv6Filter/' \
+      -e 's/data/Data/' \
+      -e 's/filt/Filt/' \
+    >> ${OUT}
+
+# We need ICMPv6Filter to compile the syscall package.
+if ! grep 'type ICMPv6Filter ' ${OUT} > /dev/null 2>&1; then
+  echo 'type ICMPv6Filter struct { Data [8]uint32 }' >> ${OUT}
+fi
+
+# Try to guess the type to use for fd_set.
+fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true`
+fds_bits_type="_C_long"
+if test "$fd_set" != ""; then
+    fds_bits_type=`echo $fd_set | sed -e 's/.*[]]\([^;]*\); }$/\1/'`
+fi
+echo "type fds_bits_type $fds_bits_type" >> ${OUT}
+
+# The addrinfo struct.
+grep '^type _addrinfo ' gen-sysinfo.go | \
+    sed -e 's/_addrinfo/Addrinfo/g' \
+      -e 's/ ai_/ Ai_/g' \
+    >> ${OUT}
+
+# The addrinfo flags and errors.
+grep '^const _AI_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(AI_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _EAI_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(EAI_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The passwd struct.
+grep '^type _passwd ' gen-sysinfo.go | \
+    sed -e 's/_passwd/Passwd/' \
+      -e 's/ pw_/ Pw_/g' \
+    >> ${OUT}
+
+# The ioctl flags for the controlling TTY.
+grep '^const _TIOC' gen-sysinfo.go | \
+    grep -v '_val =' | \
+    sed -e 's/^\(const \)_\(TIOC[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+# We need TIOCGWINSZ.
+if ! grep '^const TIOCGWINSZ' ${OUT} >/dev/null 2>&1; then
+  if grep '^const _TIOCGWINSZ_val' ${OUT} >/dev/null 2>&1; then
+    echo 'const TIOCGWINSZ = _TIOCGWINSZ_val' >> ${OUT}
+  fi
+fi
+if ! grep '^const TIOCSWINSZ' ${OUT} >/dev/null 2>&1; then
+  if grep '^const _TIOCSWINSZ_val' ${OUT} >/dev/null 2>&1; then
+    echo 'const TIOCSWINSZ = _TIOCSWINSZ_val' >> ${OUT}
+  fi
+fi
+if ! grep '^const TIOCNOTTY' ${OUT} >/dev/null 2>&1; then
+  if grep '^const _TIOCNOTTY_val' ${OUT} >/dev/null 2>&1; then
+    echo 'const TIOCNOTTY = _TIOCNOTTY_val' >> ${OUT}
+  fi
+fi
+if ! grep '^const TIOCSCTTY' ${OUT} >/dev/null 2>&1; then
+  if grep '^const _TIOCSCTTY_val' ${OUT} >/dev/null 2>&1; then
+    echo 'const TIOCSCTTY = _TIOCSCTTY_val' >> ${OUT}
+  fi
+fi
+if ! grep '^const TIOCGPTN' ${OUT} >/dev/null 2>&1; then
+  if grep '^const _TIOCGPTN_val' ${OUT} >/dev/null 2>&1; then
+    echo 'const TIOCGPTN = _TIOCGPTN_val' >> ${OUT}
+  fi
+fi
+if ! grep '^const TIOCSPTLCK' ${OUT} >/dev/null 2>&1; then
+  if grep '^const _TIOCSPTLCK_val' ${OUT} >/dev/null 2>&1; then
+    echo 'const TIOCSPTLCK = _TIOCSPTLCK_val' >> ${OUT}
+  fi
+fi
+if ! grep '^const TIOCGDEV' ${OUT} >/dev/null 2>&1; then
+  if grep '^const _TIOCGDEV_val' ${OUT} >/dev/null 2>&1; then
+    echo 'const TIOCGDEV = _TIOCGDEV_val' >> ${OUT}
+  fi
+fi
+if ! grep '^const TIOCSIG' ${OUT} >/dev/null 2>&1; then
+  if grep '^const _TIOCSIG_val' ${OUT} >/dev/null 2>&1; then
+    echo 'const TIOCSIG = _TIOCSIG_val' >> ${OUT}
+  fi
+fi
+
+# The ioctl flags for terminal control
+grep '^const _TC[GS]ET' gen-sysinfo.go | grep -v _val | \
+    sed -e 's/^\(const \)_\(TC[GS]ET[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+if ! grep '^const TCGETS' ${OUT} >/dev/null 2>&1; then
+  if grep '^const _TCGETS_val' ${OUT} >/dev/null 2>&1; then
+    echo 'const TCGETS = _TCGETS_val' >> ${OUT}
+  fi
+fi
+if ! grep '^const TCSETS' ${OUT} >/dev/null 2>&1; then
+  if grep '^const _TCSETS_val' ${OUT} >/dev/null 2>&1; then
+    echo 'const TCSETS = _TCSETS_val' >> ${OUT}
+  fi
+fi
+
+# ioctl constants.  Might fall back to 0 if TIOCNXCL is missing, too, but
+# needs handling in syscalls.exec.go.
+if ! grep '^const _TIOCSCTTY ' gen-sysinfo.go >/dev/null 2>&1; then
+  if grep '^const _TIOCNXCL ' gen-sysinfo.go >/dev/null 2>&1; then
+    echo "const TIOCSCTTY = TIOCNXCL" >> ${OUT}
+  fi
+fi
+
+# The nlmsghdr struct.
+grep '^type _nlmsghdr ' gen-sysinfo.go | \
+    sed -e 's/_nlmsghdr/NlMsghdr/' \
+      -e 's/nlmsg_len/Len/' \
+      -e 's/nlmsg_type/Type/' \
+      -e 's/nlmsg_flags/Flags/' \
+      -e 's/nlmsg_seq/Seq/' \
+      -e 's/nlmsg_pid/Pid/' \
+    >> ${OUT}
+
+# The nlmsg flags and operators.
+grep '^const _NLM' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(NLM[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# NLMSG_HDRLEN is defined as an expression using sizeof.
+if ! grep '^const NLMSG_HDRLEN' ${OUT} > /dev/null 2>&1; then
+  if grep '^const _sizeof_nlmsghdr ' ${OUT} > /dev/null 2>&1; then
+    echo 'const NLMSG_HDRLEN = (_sizeof_nlmsghdr + (NLMSG_ALIGNTO-1)) &^ (NLMSG_ALIGNTO-1)' >> ${OUT}
+  fi
+fi
+
+# The rtmsg struct.
+grep '^type _rtmsg ' gen-sysinfo.go | \
+    sed -e 's/_rtmsg/RtMsg/' \
+      -e 's/rtm_family/Family/' \
+      -e 's/rtm_dst_len/Dst_len/' \
+      -e 's/rtm_src_len/Src_len/' \
+      -e 's/rtm_tos/Tos/' \
+      -e 's/rtm_table/Table/' \
+      -e 's/rtm_protocol/Protocol/' \
+      -e 's/rtm_scope/Scope/' \
+      -e 's/rtm_type/Type/' \
+      -e 's/rtm_flags/Flags/' \
+    >> ${OUT}
+
+# The rtgenmsg struct.
+grep '^type _rtgenmsg ' gen-sysinfo.go | \
+    sed -e 's/_rtgenmsg/RtGenmsg/' \
+      -e 's/rtgen_family/Family/' \
+    >> ${OUT}
+
+# The routing message flags.
+grep '^const _RT_' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(RT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _RTA' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(RTA[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _RTF' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(RTF[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _RTCF' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(RTCF[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _RTM' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(RTM[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _RTN' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(RTN[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _RTPROT' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(RTPROT[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The ifinfomsg struct.
+grep '^type _ifinfomsg ' gen-sysinfo.go | \
+    sed -e 's/_ifinfomsg/IfInfomsg/' \
+      -e 's/ifi_family/Family/' \
+      -e 's/ifi_type/Type/' \
+      -e 's/ifi_index/Index/' \
+      -e 's/ifi_flags/Flags/' \
+      -e 's/ifi_change/Change/' \
+    >> ${OUT}
+
+# The interface information types and flags.
+grep '^const _IFA' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(IFA[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _IFLA' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(IFLA[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _IFF' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(IFF[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _IFNAMSIZ' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(IFNAMSIZ[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _SIOC' gen-sysinfo.go |
+    sed -e 's/^\(const \)_\(SIOC[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The ifaddrmsg struct.
+grep '^type _ifaddrmsg ' gen-sysinfo.go | \
+    sed -e 's/_ifaddrmsg/IfAddrmsg/' \
+      -e 's/ifa_family/Family/' \
+      -e 's/ifa_prefixlen/Prefixlen/' \
+      -e 's/ifa_flags/Flags/' \
+      -e 's/ifa_scope/Scope/' \
+      -e 's/ifa_index/Index/' \
+    >> ${OUT}
+
+# The rtattr struct.
+grep '^type _rtattr ' gen-sysinfo.go | \
+    sed -e 's/_rtattr/RtAttr/' \
+      -e 's/rta_len/Len/' \
+      -e 's/rta_type/Type/' \
+    >> ${OUT}
+
+# The in_pktinfo struct.
+grep '^type _in_pktinfo ' gen-sysinfo.go | \
+    sed -e 's/_in_pktinfo/Inet4Pktinfo/' \
+      -e 's/ipi_ifindex/Ifindex/' \
+      -e 's/ipi_spec_dst/Spec_dst/' \
+      -e 's/ipi_addr/Addr/' \
+      -e 's/_in_addr/[4]byte/g' \
+    >> ${OUT}
+
+# The in6_pktinfo struct.
+grep '^type _in6_pktinfo ' gen-sysinfo.go | \
+    sed -e 's/_in6_pktinfo/Inet6Pktinfo/' \
+      -e 's/ipi6_addr/Addr/' \
+      -e 's/ipi6_ifindex/Ifindex/' \
+      -e 's/_in6_addr/[16]byte/' \
+    >> ${OUT}
+
+# The termios struct.
+grep '^type _termios ' gen-sysinfo.go | \
+    sed -e 's/_termios/Termios/' \
+      -e 's/c_iflag/Iflag/' \
+      -e 's/c_oflag/Oflag/' \
+      -e 's/c_cflag/Cflag/' \
+      -e 's/c_lflag/Lflag/' \
+      -e 's/c_line/Line/' \
+      -e 's/c_cc/Cc/' \
+      -e 's/c_ispeed/Ispeed/' \
+      -e 's/c_ospeed/Ospeed/' \
+    >> ${OUT}
+
+# The termios constants.
+for n in IGNBRK BRKINT IGNPAR PARMRK INPCK ISTRIP INLCR IGNCR ICRNL IUCLC \
+    IXON IXANY IXOFF IMAXBEL IUTF8 OPOST OLCUC ONLCR OCRNL ONOCR ONLRET \
+    OFILL OFDEL NLDLY NL0 NL1 CRDLY CR0 CR1 CR2 CR3 CS5 CS6 CS7 CS8 TABDLY \
+    BSDLY VTDLY FFDLY CBAUD CBAUDEX CSIZE CSTOPB CREAD PARENB PARODD HUPCL \
+    CLOCAL LOBLK CIBAUD CMSPAR CRTSCTS ISIG ICANON XCASE ECHO ECHOE ECHOK \
+    ECHONL ECHOCTL ECHOPRT ECHOKE DEFECHO FLUSHO NOFLSH TOSTOP PENDIN IEXTEN \
+    VINTR VQUIT VERASE VKILL VEOF VMIN VEOL VTIME VEOL2 VSWTCH VSTART VSTOP \
+    VSUSP VDSUSP VLNEXT VWERASE VREPRINT VDISCARD VSTATUS TCSANOW TCSADRAIN \
+    TCSAFLUSH TCIFLUSH TCOFLUSH TCIOFLUSH TCOOFF TCOON TCIOFF TCION B0 B50 \
+    B75 B110 B134 B150 B200 B300 B600 B1200 B1800 B2400 B4800 B9600 B19200 \
+    B38400 B57600 B115200 B230400 B460800 B500000 B576000 B921600 B1000000 \
+    B1152000 B1500000 B2000000 B2500000 B3000000 B3500000 B4000000; do
+
+    grep "^const _$n " gen-sysinfo.go | \
+	sed -e 's/^\(const \)_\([^=]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+done
+
+# The mount flags
+grep '^const _MNT_' gen-sysinfo.go |
+    sed -e 's/^\(const \)_\(MNT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _MS_' gen-sysinfo.go |
+    sed -e 's/^\(const \)_\(MS_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The fallocate flags.
+grep '^const _FALLOC_' gen-sysinfo.go |
+    sed -e 's/^\(const \)_\(FALLOC_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The statfs struct.
+# Prefer largefile variant if available.
+statfs=`grep '^type _statfs64 ' gen-sysinfo.go || true`
+if test "$statfs" != ""; then
+  grep '^type _statfs64 ' gen-sysinfo.go
+else
+  grep '^type _statfs ' gen-sysinfo.go
+fi | sed -e 's/type _statfs64/type Statfs_t/' \
+	 -e 's/type _statfs/type Statfs_t/' \
+	 -e 's/f_type/Type/' \
+	 -e 's/f_bsize/Bsize/' \
+	 -e 's/f_blocks/Blocks/' \
+	 -e 's/f_bfree/Bfree/' \
+	 -e 's/f_bavail/Bavail/' \
+	 -e 's/f_files/Files/' \
+	 -e 's/f_ffree/Ffree/' \
+	 -e 's/f_fsid/Fsid/' \
+	 -e 's/f_namelen/Namelen/' \
+	 -e 's/f_frsize/Frsize/' \
+	 -e 's/f_flags/Flags/' \
+	 -e 's/f_spare/Spare/' \
+    >> ${OUT}
+
+# The timex struct.
+timex=`grep '^type _timex ' gen-sysinfo.go || true`
+if test "$timex" = ""; then
+  timex=`grep '^// type _timex ' gen-sysinfo.go || true`
+  if test "$timex" != ""; then
+    timex=`echo $timex | sed -e 's|// ||' -e 's/INVALID-bit-field/int32/g'`
+  fi
+fi
+if test "$timex" != ""; then
+  echo "$timex" | \
+    sed -e 's/_timex/Timex/' \
+      -e 's/modes/Modes/' \
+      -e 's/offset/Offset/' \
+      -e 's/freq/Freq/' \
+      -e 's/maxerror/Maxerror/' \
+      -e 's/esterror/Esterror/' \
+      -e 's/status/Status/' \
+      -e 's/constant/Constant/' \
+      -e 's/precision/Precision/' \
+      -e 's/tolerance/Tolerance/' \
+      -e 's/ time / Time /' \
+      -e 's/tick/Tick/' \
+      -e 's/ppsfreq/Ppsfreq/' \
+      -e 's/jitter/Jitter/' \
+      -e 's/shift/Shift/' \
+      -e 's/stabil/Stabil/' \
+      -e 's/jitcnt/Jitcnt/' \
+      -e 's/calcnt/Calcnt/' \
+      -e 's/errcnt/Errcnt/' \
+      -e 's/stbcnt/Stbcnt/' \
+      -e 's/tai/Tai/' \
+      -e 's/_timeval/Timeval/' \
+    >> ${OUT}
+fi
+
+# The rlimit struct.
+grep '^type _rlimit ' gen-sysinfo.go | \
+    sed -e 's/_rlimit/Rlimit/' \
+      -e 's/rlim_cur/Cur/' \
+      -e 's/rlim_max/Max/' \
+    >> ${OUT}
+
+# The RLIMIT constants.
+grep '^const _RLIMIT_' gen-sysinfo.go |
+    sed -e 's/^\(const \)_\(RLIMIT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _RLIM_' gen-sysinfo.go |
+    sed -e 's/^\(const \)_\(RLIM_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The sysinfo struct.
+grep '^type _sysinfo ' gen-sysinfo.go | \
+    sed -e 's/_sysinfo/Sysinfo_t/' \
+      -e 's/uptime/Uptime/' \
+      -e 's/loads/Loads/' \
+      -e 's/totalram/Totalram/' \
+      -e 's/freeram/Freeram/' \
+      -e 's/sharedram/Sharedram/' \
+      -e 's/bufferram/Bufferram/' \
+      -e 's/totalswap/Totalswap/' \
+      -e 's/freeswap/Freeswap/' \
+      -e 's/procs/Procs/' \
+      -e 's/totalhigh/Totalhigh/' \
+      -e 's/freehigh/Freehigh/' \
+      -e 's/mem_unit/Unit/' \
+    >> ${OUT}
+
+# The ustat struct.
+grep '^type _ustat ' gen-sysinfo.go | \
+    sed -e 's/_ustat/Ustat_t/' \
+      -e 's/f_tfree/Tfree/' \
+      -e 's/f_tinode/Tinoe/' \
+      -e 's/f_fname/Fname/' \
+      -e 's/f_fpack/Fpack/' \
+    >> ${OUT}
+# Force it to be defined, as on some older GNU/Linux systems the
+# header file fails when using with <linux/filter.h>.
+if ! grep 'type _ustat ' gen-sysinfo.go >/dev/null 2>&1; then
+  echo 'type Ustat_t struct { Tfree int32; Tinoe uint64; Fname [5+1]int8; Fpack [5+1]int8; }' >> ${OUT}
+fi
+
+# The utimbuf struct.
+grep '^type _utimbuf ' gen-sysinfo.go | \
+    sed -e 's/_utimbuf/Utimbuf/' \
+      -e 's/actime/Actime/' \
+      -e 's/modtime/Modtime/' \
+    >> ${OUT}
+
+# The LOCK flags for flock.
+grep '^const _LOCK_' gen-sysinfo.go |
+    sed -e 's/^\(const \)_\(LOCK_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The PRIO constants.
+grep '^const _PRIO_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(PRIO_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The GNU/Linux LINUX_REBOOT flags.
+grep '^const _LINUX_REBOOT_' gen-sysinfo.go |
+    sed -e 's/^\(const \)_\(LINUX_REBOOT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The GNU/Linux sock_filter struct.
+grep '^type _sock_filter ' gen-sysinfo.go | \
+    sed -e 's/_sock_filter/SockFilter/' \
+      -e 's/code/Code/' \
+      -e 's/jt/Jt/' \
+      -e 's/jf/Jf/' \
+      -e 's/k /K /' \
+    >> ${OUT}
+
+# The GNU/Linux sock_fprog struct.
+grep '^type _sock_fprog ' gen-sysinfo.go | \
+    sed -e 's/_sock_fprog/SockFprog/' \
+      -e 's/len/Len/' \
+      -e 's/filter/Filter/' \
+      -e 's/_sock_filter/SockFilter/' \
+    >> ${OUT}
+
+# The GNU/Linux filter flags.
+grep '^const _BPF_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(BPF_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The GNU/Linux nlattr struct.
+grep '^type _nlattr ' gen-sysinfo.go | \
+    sed -e 's/_nlattr/NlAttr/' \
+      -e 's/nla_len/Len/' \
+      -e 's/nla_type/Type/' \
+    >> ${OUT}
+
+# The GNU/Linux nlmsgerr struct.
+grep '^type _nlmsgerr ' gen-sysinfo.go | \
+    sed -e 's/_nlmsgerr/NlMsgerr/' \
+      -e 's/error/Error/' \
+      -e 's/msg/Msg/' \
+      -e 's/_nlmsghdr/NlMsghdr/' \
+    >> ${OUT}
+
+# The GNU/Linux rtnexthop struct.
+grep '^type _rtnexthop ' gen-sysinfo.go | \
+    sed -e 's/_rtnexthop/RtNexthop/' \
+      -e 's/rtnh_len/Len/' \
+      -e 's/rtnh_flags/Flags/' \
+      -e 's/rtnh_hops/Hops/' \
+      -e 's/rtnh_ifindex/Ifindex/' \
+    >> ${OUT}
+
+# The GNU/Linux netlink flags.
+grep '^const _NETLINK_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(NETLINK_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _NLA_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(NLA_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The GNU/Linux packet socket flags.
+grep '^const _PACKET_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(PACKET_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The GNU/Linux inotify_event struct.
+grep '^type _inotify_event ' gen-sysinfo.go | \
+    sed -e 's/_inotify_event/InotifyEvent/' \
+      -e 's/wd/Wd/' \
+      -e 's/mask/Mask/' \
+      -e 's/cookie/Cookie/' \
+      -e 's/len/Len/' \
+      -e 's/name/Name/' \
+      -e 's/\[\]/[0]/' \
+      -e 's/\[0\]byte/[0]int8/' \
+    >> ${OUT}
+
+# The GNU/Linux CLONE flags.
+grep '^const _CLONE_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(CLONE_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
+# The Solaris 11 Update 1 _zone_net_addr_t struct.
+grep '^type _zone_net_addr_t ' gen-sysinfo.go | \
+    sed -e 's/_in6_addr/[16]byte/' \
+    >> ${OUT}
+
+# Struct sizes.
+set cmsghdr Cmsghdr ip_mreq IPMreq ip_mreqn IPMreqn ipv6_mreq IPv6Mreq \
+    ifaddrmsg IfAddrmsg ifinfomsg IfInfomsg in_pktinfo Inet4Pktinfo \
+    in6_pktinfo Inet6Pktinfo inotify_event InotifyEvent linger Linger \
+    msghdr Msghdr nlattr NlAttr nlmsgerr NlMsgerr nlmsghdr NlMsghdr \
+    rtattr RtAttr rtgenmsg RtGenmsg rtmsg RtMsg rtnexthop RtNexthop \
+    sock_filter SockFilter sock_fprog SockFprog ucred Ucred \
+    icmp6_filter ICMPv6Filter
+while test $# != 0; do
+    nc=$1
+    ngo=$2
+    shift
+    shift
+    if grep "^const _sizeof_$nc =" gen-sysinfo.go >/dev/null 2>&1; then
+	echo "const Sizeof$ngo = _sizeof_$nc" >> ${OUT}
+    fi
+done
+
+# In order to compile the net package, we need some sizes to exist
+# even if the types do not.
+if ! grep 'const SizeofIPMreq ' ${OUT} >/dev/null 2>&1; then
+    echo 'const SizeofIPMreq = 8' >> ${OUT}
+fi
+if ! grep 'const SizeofIPv6Mreq ' ${OUT} >/dev/null 2>&1; then
+    echo 'const SizeofIPv6Mreq = 20' >> ${OUT}
+fi
+if ! grep 'const SizeofIPMreqn ' ${OUT} >/dev/null 2>&1; then
+    echo 'const SizeofIPMreqn = 12' >> ${OUT}
+fi
+if ! grep 'const SizeofICMPv6Filter ' ${OUT} >/dev/null 2>&1; then
+    echo 'const SizeofICMPv6Filter = 32' >> ${OUT}
+fi
+
+exit $?
diff --git a/third_party/gofrontend/libgo/runtime/arch.h b/third_party/gofrontend/libgo/runtime/arch.h
new file mode 100644
index 0000000..0546a5d
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/arch.h
@@ -0,0 +1,8 @@
+// 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.
+
+// FIXME: Ideally CacheLineSize would be dependent on the host architecture.
+enum {
+	CacheLineSize = 64
+};
diff --git a/third_party/gofrontend/libgo/runtime/array.h b/third_party/gofrontend/libgo/runtime/array.h
new file mode 100644
index 0000000..14a9bb4
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/array.h
@@ -0,0 +1,28 @@
+/* array.h -- the open array type for Go.
+
+   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.  */
+
+#ifndef LIBGO_ARRAY_H
+#define LIBGO_ARRAY_H
+
+/* An open array is an instance of this structure.  */
+
+struct __go_open_array
+{
+  /* The elements of the array.  In use in the compiler this is a
+     pointer to the element type.  */
+  void* __values;
+  /* The number of elements in the array.  Note that this is "int",
+     not "size_t".  The language definition says that "int" is large
+     enough to hold the size of any allocated object.  Using "int"
+     saves 8 bytes per slice header on a 64-bit system with 32-bit
+     ints.  */
+  intgo __count;
+  /* The capacity of the array--the number of elements that can fit in
+     the __VALUES field.  */
+  intgo __capacity;
+};
+
+#endif /* !defined(LIBGO_ARRAY_H) */
diff --git a/third_party/gofrontend/libgo/runtime/chan.goc b/third_party/gofrontend/libgo/runtime/chan.goc
new file mode 100644
index 0000000..9504369
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/chan.goc
@@ -0,0 +1,1205 @@
+// 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 runtime
+#include "runtime.h"
+#include "arch.h"
+#include "go-type.h"
+#include "race.h"
+#include "malloc.h"
+#include "chan.h"
+
+uint32 runtime_Hchansize = sizeof(Hchan);
+
+static	void	dequeueg(WaitQ*);
+static	SudoG*	dequeue(WaitQ*);
+static	void	enqueue(WaitQ*, SudoG*);
+static	void	racesync(Hchan*, SudoG*);
+
+static Hchan*
+makechan(ChanType *t, int64 hint)
+{
+	Hchan *c;
+	uintptr n;
+	const Type *elem;
+
+	elem = t->__element_type;
+
+	// compiler checks this but be safe.
+	if(elem->__size >= (1<<16))
+		runtime_throw("makechan: invalid channel element type");
+
+	if(hint < 0 || (intgo)hint != hint || (elem->__size > 0 && (uintptr)hint > (MaxMem - sizeof(*c)) / elem->__size))
+		runtime_panicstring("makechan: size out of range");
+
+	n = sizeof(*c);
+	n = ROUND(n, elem->__align);
+
+	// allocate memory in one call
+	c = (Hchan*)runtime_mallocgc(sizeof(*c) + hint*elem->__size, (uintptr)t | TypeInfo_Chan, 0);
+	c->elemsize = elem->__size;
+	c->elemtype = elem;
+	c->dataqsiz = hint;
+
+	if(debug)
+		runtime_printf("makechan: chan=%p; elemsize=%D; dataqsiz=%D\n",
+			c, (int64)elem->__size, (int64)c->dataqsiz);
+
+	return c;
+}
+
+func reflect.makechan(t *ChanType, size uint64) (c *Hchan) {
+	c = makechan(t, size);
+}
+
+Hchan*
+__go_new_channel(ChanType *t, uintptr hint)
+{
+	return makechan(t, hint);
+}
+
+Hchan*
+__go_new_channel_big(ChanType *t, uint64 hint)
+{
+	return makechan(t, hint);
+}
+
+/*
+ * generic single channel send/recv
+ * if the bool pointer is nil,
+ * then the full exchange will
+ * occur. if pres is not nil,
+ * then the protocol will not
+ * sleep but return if it could
+ * not complete.
+ *
+ * sleep can wake up with g->param == nil
+ * when a channel involved in the sleep has
+ * been closed.  it is easiest to loop and re-run
+ * the operation; we'll see that it's now closed.
+ */
+static bool
+chansend(ChanType *t, Hchan *c, byte *ep, bool block, void *pc)
+{
+	SudoG *sg;
+	SudoG mysg;
+	G* gp;
+	int64 t0;
+	G* g;
+
+	g = runtime_g();
+
+	if(raceenabled)
+		runtime_racereadobjectpc(ep, t->__element_type, runtime_getcallerpc(&t), chansend);
+
+	if(c == nil) {
+		USED(t);
+		if(!block)
+			return false;
+		runtime_park(nil, nil, "chan send (nil chan)");
+		return false;  // not reached
+	}
+
+	if(runtime_gcwaiting())
+		runtime_gosched();
+
+	if(debug) {
+		runtime_printf("chansend: chan=%p\n", c);
+	}
+
+	t0 = 0;
+	mysg.releasetime = 0;
+	if(runtime_blockprofilerate > 0) {
+		t0 = runtime_cputicks();
+		mysg.releasetime = -1;
+	}
+
+	runtime_lock(&c->lock);
+	if(raceenabled)
+		runtime_racereadpc(c, pc, chansend);
+	if(c->closed)
+		goto closed;
+
+	if(c->dataqsiz > 0)
+		goto asynch;
+
+	sg = dequeue(&c->recvq);
+	if(sg != nil) {
+		if(raceenabled)
+			racesync(c, sg);
+		runtime_unlock(&c->lock);
+
+		gp = sg->g;
+		gp->param = sg;
+		if(sg->elem != nil)
+			runtime_memmove(sg->elem, ep, c->elemsize);
+		if(sg->releasetime)
+			sg->releasetime = runtime_cputicks();
+		runtime_ready(gp);
+		return true;
+	}
+
+	if(!block) {
+		runtime_unlock(&c->lock);
+		return false;
+	}
+
+	mysg.elem = ep;
+	mysg.g = g;
+	mysg.selectdone = nil;
+	g->param = nil;
+	enqueue(&c->sendq, &mysg);
+	runtime_parkunlock(&c->lock, "chan send");
+
+	if(g->param == nil) {
+		runtime_lock(&c->lock);
+		if(!c->closed)
+			runtime_throw("chansend: spurious wakeup");
+		goto closed;
+	}
+
+	if(mysg.releasetime > 0)
+		runtime_blockevent(mysg.releasetime - t0, 2);
+
+	return true;
+
+asynch:
+	if(c->closed)
+		goto closed;
+
+	if(c->qcount >= c->dataqsiz) {
+		if(!block) {
+			runtime_unlock(&c->lock);
+			return false;
+		}
+		mysg.g = g;
+		mysg.elem = nil;
+		mysg.selectdone = nil;
+		enqueue(&c->sendq, &mysg);
+		runtime_parkunlock(&c->lock, "chan send");
+
+		runtime_lock(&c->lock);
+		goto asynch;
+	}
+
+	if(raceenabled) {
+		runtime_raceacquire(chanbuf(c, c->sendx));
+		runtime_racerelease(chanbuf(c, c->sendx));
+	}
+
+	runtime_memmove(chanbuf(c, c->sendx), ep, c->elemsize);
+	if(++c->sendx == c->dataqsiz)
+		c->sendx = 0;
+	c->qcount++;
+
+	sg = dequeue(&c->recvq);
+	if(sg != nil) {
+		gp = sg->g;
+		runtime_unlock(&c->lock);
+		if(sg->releasetime)
+			sg->releasetime = runtime_cputicks();
+		runtime_ready(gp);
+	} else
+		runtime_unlock(&c->lock);
+	if(mysg.releasetime > 0)
+		runtime_blockevent(mysg.releasetime - t0, 2);
+	return true;
+
+closed:
+	runtime_unlock(&c->lock);
+	runtime_panicstring("send on closed channel");
+	return false;  // not reached
+}
+
+
+static bool
+chanrecv(ChanType *t, Hchan* c, byte *ep, bool block, bool *received)
+{
+	SudoG *sg;
+	SudoG mysg;
+	G *gp;
+	int64 t0;
+	G *g;
+
+	if(runtime_gcwaiting())
+		runtime_gosched();
+
+	// raceenabled: don't need to check ep, as it is always on the stack.
+
+	if(debug)
+		runtime_printf("chanrecv: chan=%p\n", c);
+
+	g = runtime_g();
+
+	if(c == nil) {
+		USED(t);
+		if(!block)
+			return false;
+		runtime_park(nil, nil, "chan receive (nil chan)");
+		return false;  // not reached
+	}
+
+	t0 = 0;
+	mysg.releasetime = 0;
+	if(runtime_blockprofilerate > 0) {
+		t0 = runtime_cputicks();
+		mysg.releasetime = -1;
+	}
+
+	runtime_lock(&c->lock);
+	if(c->dataqsiz > 0)
+		goto asynch;
+
+	if(c->closed)
+		goto closed;
+
+	sg = dequeue(&c->sendq);
+	if(sg != nil) {
+		if(raceenabled)
+			racesync(c, sg);
+		runtime_unlock(&c->lock);
+
+		if(ep != nil)
+			runtime_memmove(ep, sg->elem, c->elemsize);
+		gp = sg->g;
+		gp->param = sg;
+		if(sg->releasetime)
+			sg->releasetime = runtime_cputicks();
+		runtime_ready(gp);
+
+		if(received != nil)
+			*received = true;
+		return true;
+	}
+
+	if(!block) {
+		runtime_unlock(&c->lock);
+		return false;
+	}
+
+	mysg.elem = ep;
+	mysg.g = g;
+	mysg.selectdone = nil;
+	g->param = nil;
+	enqueue(&c->recvq, &mysg);
+	runtime_parkunlock(&c->lock, "chan receive");
+
+	if(g->param == nil) {
+		runtime_lock(&c->lock);
+		if(!c->closed)
+			runtime_throw("chanrecv: spurious wakeup");
+		goto closed;
+	}
+
+	if(received != nil)
+		*received = true;
+	if(mysg.releasetime > 0)
+		runtime_blockevent(mysg.releasetime - t0, 2);
+	return true;
+
+asynch:
+	if(c->qcount <= 0) {
+		if(c->closed)
+			goto closed;
+
+		if(!block) {
+			runtime_unlock(&c->lock);
+			if(received != nil)
+				*received = false;
+			return false;
+		}
+		mysg.g = g;
+		mysg.elem = nil;
+		mysg.selectdone = nil;
+		enqueue(&c->recvq, &mysg);
+		runtime_parkunlock(&c->lock, "chan receive");
+
+		runtime_lock(&c->lock);
+		goto asynch;
+	}
+
+	if(raceenabled) {
+		runtime_raceacquire(chanbuf(c, c->recvx));
+		runtime_racerelease(chanbuf(c, c->recvx));
+	}
+
+	if(ep != nil)
+		runtime_memmove(ep, chanbuf(c, c->recvx), c->elemsize);
+	runtime_memclr(chanbuf(c, c->recvx), c->elemsize);
+	if(++c->recvx == c->dataqsiz)
+		c->recvx = 0;
+	c->qcount--;
+
+	sg = dequeue(&c->sendq);
+	if(sg != nil) {
+		gp = sg->g;
+		runtime_unlock(&c->lock);
+		if(sg->releasetime)
+			sg->releasetime = runtime_cputicks();
+		runtime_ready(gp);
+	} else
+		runtime_unlock(&c->lock);
+
+	if(received != nil)
+		*received = true;
+	if(mysg.releasetime > 0)
+		runtime_blockevent(mysg.releasetime - t0, 2);
+	return true;
+
+closed:
+	if(ep != nil)
+		runtime_memclr(ep, c->elemsize);
+	if(received != nil)
+		*received = false;
+	if(raceenabled)
+		runtime_raceacquire(c);
+	runtime_unlock(&c->lock);
+	if(mysg.releasetime > 0)
+		runtime_blockevent(mysg.releasetime - t0, 2);
+	return true;
+}
+
+// The compiler generates a call to __go_send_small to send a value 8
+// bytes or smaller.
+void
+__go_send_small(ChanType *t, Hchan* c, uint64 val)
+{
+	union
+	{
+		byte b[sizeof(uint64)];
+		uint64 v;
+	} u;
+	byte *v;
+
+	u.v = val;
+#ifndef WORDS_BIGENDIAN
+	v = u.b;
+#else
+	v = u.b + sizeof(uint64) - t->__element_type->__size;
+#endif
+	chansend(t, c, v, true, runtime_getcallerpc(&t));
+}
+
+// The compiler generates a call to __go_send_big to send a value
+// larger than 8 bytes or smaller.
+void
+__go_send_big(ChanType *t, Hchan* c, byte* v)
+{
+	chansend(t, c, v, true, runtime_getcallerpc(&t));
+}
+
+// The compiler generates a call to __go_receive to receive a
+// value from a channel.
+void
+__go_receive(ChanType *t, Hchan* c, byte* v)
+{
+	chanrecv(t, c, v, true, nil);
+}
+
+_Bool runtime_chanrecv2(ChanType *t, Hchan* c, byte* v)
+  __asm__ (GOSYM_PREFIX "runtime.chanrecv2");
+
+_Bool
+runtime_chanrecv2(ChanType *t, Hchan* c, byte* v)
+{
+	bool received = false;
+
+	chanrecv(t, c, v, true, &received);
+	return received;
+}
+
+// compiler implements
+//
+//	select {
+//	case c <- v:
+//		... foo
+//	default:
+//		... bar
+//	}
+//
+// as
+//
+//	if selectnbsend(c, v) {
+//		... foo
+//	} else {
+//		... bar
+//	}
+//
+func selectnbsend(t *ChanType, c *Hchan, elem *byte) (selected bool) {
+	selected = chansend(t, c, elem, false, runtime_getcallerpc(&t));
+}
+
+// compiler implements
+//
+//	select {
+//	case v = <-c:
+//		... foo
+//	default:
+//		... bar
+//	}
+//
+// as
+//
+//	if selectnbrecv(&v, c) {
+//		... foo
+//	} else {
+//		... bar
+//	}
+//
+func selectnbrecv(t *ChanType, elem *byte, c *Hchan) (selected bool) {
+	selected = chanrecv(t, c, elem, false, nil);
+}
+
+// compiler implements
+//
+//	select {
+//	case v, ok = <-c:
+//		... foo
+//	default:
+//		... bar
+//	}
+//
+// as
+//
+//	if c != nil && selectnbrecv2(&v, &ok, c) {
+//		... foo
+//	} else {
+//		... bar
+//	}
+//
+func selectnbrecv2(t *ChanType, elem *byte, received *bool, c *Hchan) (selected bool) {
+	bool r;
+
+	selected = chanrecv(t, c, elem, false, received == nil ? nil : &r);
+	if(received != nil)
+		*received = r;
+}
+
+func reflect.chansend(t *ChanType, c *Hchan, elem *byte, nb bool) (selected bool) {
+	selected = chansend(t, c, elem, !nb, runtime_getcallerpc(&t));
+}
+
+func reflect.chanrecv(t *ChanType, c *Hchan, nb bool, elem *byte) (selected bool, received bool) {
+	received = false;
+	selected = chanrecv(t, c, elem, !nb, &received);
+}
+
+static Select* newselect(int32);
+
+func newselect(size int32) (sel *byte) {
+ 	sel = (byte*)newselect(size);
+}
+
+static Select*
+newselect(int32 size)
+{
+	int32 n;
+	Select *sel;
+
+	n = 0;
+	if(size > 1)
+		n = size-1;
+
+	// allocate all the memory we need in a single allocation
+	// start with Select with size cases
+	// then lockorder with size entries
+	// then pollorder with size entries
+	sel = runtime_mal(sizeof(*sel) +
+		n*sizeof(sel->scase[0]) +
+		size*sizeof(sel->lockorder[0]) +
+		size*sizeof(sel->pollorder[0]));
+
+	sel->tcase = size;
+	sel->ncase = 0;
+	sel->lockorder = (void*)(sel->scase + size);
+	sel->pollorder = (void*)(sel->lockorder + size);
+
+	if(debug)
+		runtime_printf("newselect s=%p size=%d\n", sel, size);
+	return sel;
+}
+
+// cut in half to give stack a chance to split
+static void selectsend(Select *sel, Hchan *c, int index, void *elem);
+
+func selectsend(sel *Select, c *Hchan, elem *byte, index int32) {
+	// nil cases do not compete
+	if(c != nil)
+		selectsend(sel, c, index, elem);
+}
+
+static void
+selectsend(Select *sel, Hchan *c, int index, void *elem)
+{
+	int32 i;
+	Scase *cas;
+
+	i = sel->ncase;
+	if(i >= sel->tcase)
+		runtime_throw("selectsend: too many cases");
+	sel->ncase = i+1;
+	cas = &sel->scase[i];
+
+	cas->index = index;
+	cas->chan = c;
+	cas->kind = CaseSend;
+	cas->sg.elem = elem;
+
+	if(debug)
+		runtime_printf("selectsend s=%p index=%d chan=%p\n",
+			sel, cas->index, cas->chan);
+}
+
+// cut in half to give stack a chance to split
+static void selectrecv(Select *sel, Hchan *c, int index, void *elem, bool*);
+
+func selectrecv(sel *Select, c *Hchan, elem *byte, index int32) {
+	// nil cases do not compete
+	if(c != nil)
+		selectrecv(sel, c, index, elem, nil);
+}
+
+func selectrecv2(sel *Select, c *Hchan, elem *byte, received *bool, index int32) {
+	// nil cases do not compete
+	if(c != nil)
+		selectrecv(sel, c, index, elem, received);
+}
+
+static void
+selectrecv(Select *sel, Hchan *c, int index, void *elem, bool *received)
+{
+	int32 i;
+	Scase *cas;
+
+	i = sel->ncase;
+	if(i >= sel->tcase)
+		runtime_throw("selectrecv: too many cases");
+	sel->ncase = i+1;
+	cas = &sel->scase[i];
+	cas->index = index;
+	cas->chan = c;
+
+	cas->kind = CaseRecv;
+	cas->sg.elem = elem;
+	cas->receivedp = received;
+
+	if(debug)
+		runtime_printf("selectrecv s=%p index=%d chan=%p\n",
+			sel, cas->index, cas->chan);
+}
+
+// cut in half to give stack a chance to split
+static void selectdefault(Select*, int);
+
+func selectdefault(sel *Select, index int32) {
+	selectdefault(sel, index);
+}
+
+static void
+selectdefault(Select *sel, int32 index)
+{
+	int32 i;
+	Scase *cas;
+
+	i = sel->ncase;
+	if(i >= sel->tcase)
+		runtime_throw("selectdefault: too many cases");
+	sel->ncase = i+1;
+	cas = &sel->scase[i];
+	cas->index = index;
+	cas->chan = nil;
+
+	cas->kind = CaseDefault;
+
+	if(debug)
+		runtime_printf("selectdefault s=%p index=%d\n",
+			sel, cas->index);
+}
+
+static void
+sellock(Select *sel)
+{
+	uint32 i;
+	Hchan *c, *c0;
+
+	c = nil;
+	for(i=0; i<sel->ncase; i++) {
+		c0 = sel->lockorder[i];
+		if(c0 && c0 != c) {
+			c = sel->lockorder[i];
+			runtime_lock(&c->lock);
+		}
+	}
+}
+
+static void
+selunlock(Select *sel)
+{
+	int32 i, n, r;
+	Hchan *c;
+
+	// We must be very careful here to not touch sel after we have unlocked
+	// the last lock, because sel can be freed right after the last unlock.
+	// Consider the following situation.
+	// First M calls runtime_park() in runtime_selectgo() passing the sel.
+	// Once runtime_park() has unlocked the last lock, another M makes
+	// the G that calls select runnable again and schedules it for execution.
+	// When the G runs on another M, it locks all the locks and frees sel.
+	// Now if the first M touches sel, it will access freed memory.
+	n = (int32)sel->ncase;
+	r = 0;
+	// skip the default case
+	if(n>0 && sel->lockorder[0] == nil)
+		r = 1;
+	for(i = n-1; i >= r; i--) {
+		c = sel->lockorder[i];
+		if(i>0 && sel->lockorder[i-1] == c)
+			continue;  // will unlock it on the next iteration
+		runtime_unlock(&c->lock);
+	}
+}
+
+static bool
+selparkcommit(G *gp, void *sel)
+{
+	USED(gp);
+	selunlock(sel);
+	return true;
+}
+
+func block() {
+	runtime_park(nil, nil, "select (no cases)");	// forever
+}
+
+static int selectgo(Select**);
+
+// selectgo(sel *byte);
+
+func selectgo(sel *Select) (ret int32) {
+	return selectgo(&sel);
+}
+
+static int
+selectgo(Select **selp)
+{
+	Select *sel;
+	uint32 o, i, j, k, done;
+	int64 t0;
+	Scase *cas, *dfl;
+	Hchan *c;
+	SudoG *sg;
+	G *gp;
+	int index;
+	G *g;
+
+	sel = *selp;
+	if(runtime_gcwaiting())
+		runtime_gosched();
+
+	if(debug)
+		runtime_printf("select: sel=%p\n", sel);
+
+	g = runtime_g();
+
+	t0 = 0;
+	if(runtime_blockprofilerate > 0) {
+		t0 = runtime_cputicks();
+		for(i=0; i<sel->ncase; i++)
+			sel->scase[i].sg.releasetime = -1;
+	}
+
+	// The compiler rewrites selects that statically have
+	// only 0 or 1 cases plus default into simpler constructs.
+	// The only way we can end up with such small sel->ncase
+	// values here is for a larger select in which most channels
+	// have been nilled out.  The general code handles those
+	// cases correctly, and they are rare enough not to bother
+	// optimizing (and needing to test).
+
+	// generate permuted order
+	for(i=0; i<sel->ncase; i++)
+		sel->pollorder[i] = i;
+	for(i=1; i<sel->ncase; i++) {
+		o = sel->pollorder[i];
+		j = runtime_fastrand1()%(i+1);
+		sel->pollorder[i] = sel->pollorder[j];
+		sel->pollorder[j] = o;
+	}
+
+	// sort the cases by Hchan address to get the locking order.
+	// simple heap sort, to guarantee n log n time and constant stack footprint.
+	for(i=0; i<sel->ncase; i++) {
+		j = i;
+		c = sel->scase[j].chan;
+		while(j > 0 && sel->lockorder[k=(j-1)/2] < c) {
+			sel->lockorder[j] = sel->lockorder[k];
+			j = k;
+		}
+		sel->lockorder[j] = c;
+	}
+	for(i=sel->ncase; i-->0; ) {
+		c = sel->lockorder[i];
+		sel->lockorder[i] = sel->lockorder[0];
+		j = 0;
+		for(;;) {
+			k = j*2+1;
+			if(k >= i)
+				break;
+			if(k+1 < i && sel->lockorder[k] < sel->lockorder[k+1])
+				k++;
+			if(c < sel->lockorder[k]) {
+				sel->lockorder[j] = sel->lockorder[k];
+				j = k;
+				continue;
+			}
+			break;
+		}
+		sel->lockorder[j] = c;
+	}
+	/*
+	for(i=0; i+1<sel->ncase; i++)
+		if(sel->lockorder[i] > sel->lockorder[i+1]) {
+			runtime_printf("i=%d %p %p\n", i, sel->lockorder[i], sel->lockorder[i+1]);
+			runtime_throw("select: broken sort");
+		}
+	*/
+	sellock(sel);
+
+loop:
+	// pass 1 - look for something already waiting
+	dfl = nil;
+	for(i=0; i<sel->ncase; i++) {
+		o = sel->pollorder[i];
+		cas = &sel->scase[o];
+		c = cas->chan;
+
+		switch(cas->kind) {
+		case CaseRecv:
+			if(c->dataqsiz > 0) {
+				if(c->qcount > 0)
+					goto asyncrecv;
+			} else {
+				sg = dequeue(&c->sendq);
+				if(sg != nil)
+					goto syncrecv;
+			}
+			if(c->closed)
+				goto rclose;
+			break;
+
+		case CaseSend:
+			if(raceenabled)
+				runtime_racereadpc(c, runtime_selectgo, chansend);
+			if(c->closed)
+				goto sclose;
+			if(c->dataqsiz > 0) {
+				if(c->qcount < c->dataqsiz)
+					goto asyncsend;
+			} else {
+				sg = dequeue(&c->recvq);
+				if(sg != nil)
+					goto syncsend;
+			}
+			break;
+
+		case CaseDefault:
+			dfl = cas;
+			break;
+		}
+	}
+
+	if(dfl != nil) {
+		selunlock(sel);
+		cas = dfl;
+		goto retc;
+	}
+
+
+	// pass 2 - enqueue on all chans
+	done = 0;
+	for(i=0; i<sel->ncase; i++) {
+		o = sel->pollorder[i];
+		cas = &sel->scase[o];
+		c = cas->chan;
+		sg = &cas->sg;
+		sg->g = g;
+		sg->selectdone = &done;
+
+		switch(cas->kind) {
+		case CaseRecv:
+			enqueue(&c->recvq, sg);
+			break;
+
+		case CaseSend:
+			enqueue(&c->sendq, sg);
+			break;
+		}
+	}
+
+	g->param = nil;
+	runtime_park(selparkcommit, sel, "select");
+
+	sellock(sel);
+	sg = g->param;
+
+	// pass 3 - dequeue from unsuccessful chans
+	// otherwise they stack up on quiet channels
+	for(i=0; i<sel->ncase; i++) {
+		cas = &sel->scase[i];
+		if(cas != (Scase*)sg) {
+			c = cas->chan;
+			if(cas->kind == CaseSend)
+				dequeueg(&c->sendq);
+			else
+				dequeueg(&c->recvq);
+		}
+	}
+
+	if(sg == nil)
+		goto loop;
+
+	cas = (Scase*)sg;
+	c = cas->chan;
+
+	if(c->dataqsiz > 0)
+		runtime_throw("selectgo: shouldn't happen");
+
+	if(debug)
+		runtime_printf("wait-return: sel=%p c=%p cas=%p kind=%d\n",
+			sel, c, cas, cas->kind);
+
+	if(cas->kind == CaseRecv) {
+		if(cas->receivedp != nil)
+			*cas->receivedp = true;
+	}
+
+	if(raceenabled) {
+		if(cas->kind == CaseRecv && cas->sg.elem != nil)
+			runtime_racewriteobjectpc(cas->sg.elem, c->elemtype, selectgo, chanrecv);
+		else if(cas->kind == CaseSend)
+			runtime_racereadobjectpc(cas->sg.elem, c->elemtype, selectgo, chansend);
+	}
+
+	selunlock(sel);
+	goto retc;
+
+asyncrecv:
+	// can receive from buffer
+	if(raceenabled) {
+		if(cas->sg.elem != nil)
+			runtime_racewriteobjectpc(cas->sg.elem, c->elemtype, selectgo, chanrecv);
+		runtime_raceacquire(chanbuf(c, c->recvx));
+		runtime_racerelease(chanbuf(c, c->recvx));
+	}
+	if(cas->receivedp != nil)
+		*cas->receivedp = true;
+	if(cas->sg.elem != nil)
+		runtime_memmove(cas->sg.elem, chanbuf(c, c->recvx), c->elemsize);
+	runtime_memclr(chanbuf(c, c->recvx), c->elemsize);
+	if(++c->recvx == c->dataqsiz)
+		c->recvx = 0;
+	c->qcount--;
+	sg = dequeue(&c->sendq);
+	if(sg != nil) {
+		gp = sg->g;
+		selunlock(sel);
+		if(sg->releasetime)
+			sg->releasetime = runtime_cputicks();
+		runtime_ready(gp);
+	} else {
+		selunlock(sel);
+	}
+	goto retc;
+
+asyncsend:
+	// can send to buffer
+	if(raceenabled) {
+		runtime_raceacquire(chanbuf(c, c->sendx));
+		runtime_racerelease(chanbuf(c, c->sendx));
+		runtime_racereadobjectpc(cas->sg.elem, c->elemtype, selectgo, chansend);
+	}
+	runtime_memmove(chanbuf(c, c->sendx), cas->sg.elem, c->elemsize);
+	if(++c->sendx == c->dataqsiz)
+		c->sendx = 0;
+	c->qcount++;
+	sg = dequeue(&c->recvq);
+	if(sg != nil) {
+		gp = sg->g;
+		selunlock(sel);
+		if(sg->releasetime)
+			sg->releasetime = runtime_cputicks();
+		runtime_ready(gp);
+	} else {
+		selunlock(sel);
+	}
+	goto retc;
+
+syncrecv:
+	// can receive from sleeping sender (sg)
+	if(raceenabled) {
+		if(cas->sg.elem != nil)
+			runtime_racewriteobjectpc(cas->sg.elem, c->elemtype, selectgo, chanrecv);
+		racesync(c, sg);
+	}
+	selunlock(sel);
+	if(debug)
+		runtime_printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
+	if(cas->receivedp != nil)
+		*cas->receivedp = true;
+	if(cas->sg.elem != nil)
+		runtime_memmove(cas->sg.elem, sg->elem, c->elemsize);
+	gp = sg->g;
+	gp->param = sg;
+	if(sg->releasetime)
+		sg->releasetime = runtime_cputicks();
+	runtime_ready(gp);
+	goto retc;
+
+rclose:
+	// read at end of closed channel
+	selunlock(sel);
+	if(cas->receivedp != nil)
+		*cas->receivedp = false;
+	if(cas->sg.elem != nil)
+		runtime_memclr(cas->sg.elem, c->elemsize);
+	if(raceenabled)
+		runtime_raceacquire(c);
+	goto retc;
+
+syncsend:
+	// can send to sleeping receiver (sg)
+	if(raceenabled) {
+		runtime_racereadobjectpc(cas->sg.elem, c->elemtype, selectgo, chansend);
+		racesync(c, sg);
+	}
+	selunlock(sel);
+	if(debug)
+		runtime_printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
+	if(sg->elem != nil)
+		runtime_memmove(sg->elem, cas->sg.elem, c->elemsize);
+	gp = sg->g;
+	gp->param = sg;
+	if(sg->releasetime)
+		sg->releasetime = runtime_cputicks();
+	runtime_ready(gp);
+
+retc:
+	// return index corresponding to chosen case
+	index = cas->index;
+	if(cas->sg.releasetime > 0)
+		runtime_blockevent(cas->sg.releasetime - t0, 2);
+	runtime_free(sel);
+	return index;
+
+sclose:
+	// send on closed channel
+	selunlock(sel);
+	runtime_panicstring("send on closed channel");
+	return 0;  // not reached
+}
+
+// This struct must match ../reflect/value.go:/runtimeSelect.
+typedef struct runtimeSelect runtimeSelect;
+struct runtimeSelect
+{
+	uintptr dir;
+	ChanType *typ;
+	Hchan *ch;
+	byte *val;
+};
+
+// This enum must match ../reflect/value.go:/SelectDir.
+enum SelectDir {
+	SelectSend = 1,
+	SelectRecv,
+	SelectDefault,
+};
+
+func reflect.rselect(cases Slice) (chosen int, recvOK bool) {
+	int32 i;
+	Select *sel;
+	runtimeSelect* rcase, *rc;
+
+	chosen = -1;
+	recvOK = false;
+
+	rcase = (runtimeSelect*)cases.__values;
+
+	sel = newselect(cases.__count);
+	for(i=0; i<cases.__count; i++) {
+		rc = &rcase[i];
+		switch(rc->dir) {
+		case SelectDefault:
+			selectdefault(sel, i);
+			break;
+		case SelectSend:
+			if(rc->ch == nil)
+				break;
+			selectsend(sel, rc->ch, i, rc->val);
+			break;
+		case SelectRecv:
+			if(rc->ch == nil)
+				break;
+			selectrecv(sel, rc->ch, i, rc->val, &recvOK);
+			break;
+		}
+	}
+
+	chosen = (intgo)(uintptr)selectgo(&sel);
+}
+
+static void closechan(Hchan *c, void *pc);
+
+func closechan(c *Hchan) {
+	closechan(c, runtime_getcallerpc(&c));
+}
+
+func reflect.chanclose(c *Hchan) {
+	closechan(c, runtime_getcallerpc(&c));
+}
+
+static void
+closechan(Hchan *c, void *pc)
+{
+	SudoG *sg;
+	G* gp;
+
+	if(c == nil)
+		runtime_panicstring("close of nil channel");
+
+	if(runtime_gcwaiting())
+		runtime_gosched();
+
+	runtime_lock(&c->lock);
+	if(c->closed) {
+		runtime_unlock(&c->lock);
+		runtime_panicstring("close of closed channel");
+	}
+
+	if(raceenabled) {
+		runtime_racewritepc(c, pc, runtime_closechan);
+		runtime_racerelease(c);
+	}
+
+	c->closed = true;
+
+	// release all readers
+	for(;;) {
+		sg = dequeue(&c->recvq);
+		if(sg == nil)
+			break;
+		gp = sg->g;
+		gp->param = nil;
+		if(sg->releasetime)
+			sg->releasetime = runtime_cputicks();
+		runtime_ready(gp);
+	}
+
+	// release all writers
+	for(;;) {
+		sg = dequeue(&c->sendq);
+		if(sg == nil)
+			break;
+		gp = sg->g;
+		gp->param = nil;
+		if(sg->releasetime)
+			sg->releasetime = runtime_cputicks();
+		runtime_ready(gp);
+	}
+
+	runtime_unlock(&c->lock);
+}
+
+void
+__go_builtin_close(Hchan *c)
+{
+	runtime_closechan(c);
+}
+
+func reflect.chanlen(c *Hchan) (len int) {
+	if(c == nil)
+		len = 0;
+	else
+		len = c->qcount;
+}
+
+intgo
+__go_chan_len(Hchan *c)
+{
+	return reflect_chanlen(c);
+}
+
+func reflect.chancap(c *Hchan) (cap int) {
+	if(c == nil)
+		cap = 0;
+	else
+		cap = c->dataqsiz;
+}
+
+intgo
+__go_chan_cap(Hchan *c)
+{
+	return reflect_chancap(c);
+}
+
+static SudoG*
+dequeue(WaitQ *q)
+{
+	SudoG *sgp;
+
+loop:
+	sgp = q->first;
+	if(sgp == nil)
+		return nil;
+	q->first = sgp->link;
+
+	// if sgp participates in a select and is already signaled, ignore it
+	if(sgp->selectdone != nil) {
+		// claim the right to signal
+		if(*sgp->selectdone != 0 || !runtime_cas(sgp->selectdone, 0, 1))
+			goto loop;
+	}
+
+	return sgp;
+}
+
+static void
+dequeueg(WaitQ *q)
+{
+	SudoG **l, *sgp, *prevsgp;
+	G *g;
+
+	g = runtime_g();
+	prevsgp = nil;
+	for(l=&q->first; (sgp=*l) != nil; l=&sgp->link, prevsgp=sgp) {
+		if(sgp->g == g) {
+			*l = sgp->link;
+			if(q->last == sgp)
+				q->last = prevsgp;
+			break;
+		}
+	}
+}
+
+static void
+enqueue(WaitQ *q, SudoG *sgp)
+{
+	sgp->link = nil;
+	if(q->first == nil) {
+		q->first = sgp;
+		q->last = sgp;
+		return;
+	}
+	q->last->link = sgp;
+	q->last = sgp;
+}
+
+static void
+racesync(Hchan *c, SudoG *sg)
+{
+	runtime_racerelease(chanbuf(c, 0));
+	runtime_raceacquireg(sg->g, chanbuf(c, 0));
+	runtime_racereleaseg(sg->g, chanbuf(c, 0));
+	runtime_raceacquire(chanbuf(c, 0));
+}
diff --git a/third_party/gofrontend/libgo/runtime/chan.h b/third_party/gofrontend/libgo/runtime/chan.h
new file mode 100644
index 0000000..271803c
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/chan.h
@@ -0,0 +1,75 @@
+// 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.
+
+typedef	struct	WaitQ	WaitQ;
+typedef	struct	SudoG	SudoG;
+typedef	struct	Select	Select;
+typedef	struct	Scase	Scase;
+
+typedef struct	__go_type_descriptor	Type;
+typedef struct	__go_channel_type	ChanType;
+
+struct	SudoG
+{
+	G*	g;
+	uint32*	selectdone;
+	SudoG*	link;
+	int64	releasetime;
+	byte*	elem;		// data element
+};
+
+struct	WaitQ
+{
+	SudoG*	first;
+	SudoG*	last;
+};
+
+// The garbage collector is assuming that Hchan can only contain pointers into the stack
+// and cannot contain pointers into the heap.
+struct	Hchan
+{
+	uintgo	qcount;			// total data in the q
+	uintgo	dataqsiz;		// size of the circular q
+	uint16	elemsize;
+	uint16	pad;			// ensures proper alignment of the buffer that follows Hchan in memory
+	bool	closed;
+	const Type* elemtype;		// element type
+	uintgo	sendx;			// send index
+	uintgo	recvx;			// receive index
+	WaitQ	recvq;			// list of recv waiters
+	WaitQ	sendq;			// list of send waiters
+	Lock	lock;
+};
+
+// Buffer follows Hchan immediately in memory.
+// chanbuf(c, i) is pointer to the i'th slot in the buffer.
+#define chanbuf(c, i) ((byte*)((c)+1)+(uintptr)(c)->elemsize*(i))
+
+enum
+{
+	debug = 0,
+
+	// Scase.kind
+	CaseRecv,
+	CaseSend,
+	CaseDefault,
+};
+
+struct	Scase
+{
+	SudoG	sg;			// must be first member (cast to Scase)
+	Hchan*	chan;			// chan
+	uint16	kind;
+	uint16	index;			// index to return
+	bool*	receivedp;		// pointer to received bool (recv2)
+};
+
+struct	Select
+{
+	uint16	tcase;			// total count of scase[]
+	uint16	ncase;			// currently filled scase[]
+	uint16*	pollorder;		// case poll order
+	Hchan**	lockorder;		// channel lock order
+	Scase	scase[1];		// one per case (in order of appearance)
+};
diff --git a/third_party/gofrontend/libgo/runtime/cpuprof.goc b/third_party/gofrontend/libgo/runtime/cpuprof.goc
new file mode 100644
index 0000000..7d27bc6
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/cpuprof.goc
@@ -0,0 +1,442 @@
+// 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.
+
+// CPU profiling.
+// Based on algorithms and data structures used in
+// http://code.google.com/p/google-perftools/.
+//
+// The main difference between this code and the google-perftools
+// code is that this code is written to allow copying the profile data
+// to an arbitrary io.Writer, while the google-perftools code always
+// writes to an operating system file.
+//
+// The signal handler for the profiling clock tick adds a new stack trace
+// to a hash table tracking counts for recent traces.  Most clock ticks
+// hit in the cache.  In the event of a cache miss, an entry must be 
+// evicted from the hash table, copied to a log that will eventually be
+// written as profile data.  The google-perftools code flushed the
+// log itself during the signal handler.  This code cannot do that, because
+// the io.Writer might block or need system calls or locks that are not
+// safe to use from within the signal handler.  Instead, we split the log
+// into two halves and let the signal handler fill one half while a goroutine
+// is writing out the other half.  When the signal handler fills its half, it
+// offers to swap with the goroutine.  If the writer is not done with its half,
+// we lose the stack trace for this clock tick (and record that loss).
+// The goroutine interacts with the signal handler by calling getprofile() to
+// get the next log piece to write, implicitly handing back the last log
+// piece it obtained.
+//
+// The state of this dance between the signal handler and the goroutine
+// is encoded in the Profile.handoff field.  If handoff == 0, then the goroutine
+// is not using either log half and is waiting (or will soon be waiting) for
+// a new piece by calling notesleep(&p->wait).  If the signal handler
+// changes handoff from 0 to non-zero, it must call notewakeup(&p->wait)
+// to wake the goroutine.  The value indicates the number of entries in the
+// log half being handed off.  The goroutine leaves the non-zero value in
+// place until it has finished processing the log half and then flips the number
+// back to zero.  Setting the high bit in handoff means that the profiling is over, 
+// and the goroutine is now in charge of flushing the data left in the hash table
+// to the log and returning that data.  
+//
+// The handoff field is manipulated using atomic operations.
+// For the most part, the manipulation of handoff is orderly: if handoff == 0
+// then the signal handler owns it and can change it to non-zero.  
+// If handoff != 0 then the goroutine owns it and can change it to zero.
+// If that were the end of the story then we would not need to manipulate
+// handoff using atomic operations.  The operations are needed, however,
+// in order to let the log closer set the high bit to indicate "EOF" safely
+// in the situation when normally the goroutine "owns" handoff.
+
+package runtime
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+#include "array.h"
+typedef struct __go_open_array Slice;
+#define array __values
+#define len __count
+#define cap __capacity
+
+enum
+{
+	HashSize = 1<<10,
+	LogSize = 1<<17,
+	Assoc = 4,
+	MaxStack = 64,
+};
+
+typedef struct Profile Profile;
+typedef struct Bucket Bucket;
+typedef struct Entry Entry;
+
+struct Entry {
+	uintptr count;
+	uintptr depth;
+	uintptr stack[MaxStack];
+};
+
+struct Bucket {
+	Entry entry[Assoc];
+};
+
+struct Profile {
+	bool on;		// profiling is on
+	Note wait;		// goroutine waits here
+	uintptr count;		// tick count
+	uintptr evicts;		// eviction count
+	uintptr lost;		// lost ticks that need to be logged
+
+	// Active recent stack traces.
+	Bucket hash[HashSize];
+
+	// Log of traces evicted from hash.
+	// Signal handler has filled log[toggle][:nlog].
+	// Goroutine is writing log[1-toggle][:handoff].
+	uintptr log[2][LogSize/2];
+	uintptr nlog;
+	int32 toggle;
+	uint32 handoff;
+	
+	// Writer state.
+	// Writer maintains its own toggle to avoid races
+	// looking at signal handler's toggle.
+	uint32 wtoggle;
+	bool wholding;	// holding & need to release a log half
+	bool flushing;	// flushing hash table - profile is over
+	bool eod_sent;  // special end-of-data record sent; => flushing
+};
+
+static Lock lk;
+static Profile *prof;
+
+static void tick(uintptr*, int32);
+static void add(Profile*, uintptr*, int32);
+static bool evict(Profile*, Entry*);
+static bool flushlog(Profile*);
+
+static uintptr eod[3] = {0, 1, 0};
+
+// LostProfileData is a no-op function used in profiles
+// to mark the number of profiling stack traces that were
+// discarded due to slow data writers.
+static void
+LostProfileData(void)
+{
+}
+
+extern void runtime_SetCPUProfileRate(intgo)
+     __asm__ (GOSYM_PREFIX "runtime.SetCPUProfileRate");
+
+// SetCPUProfileRate sets the CPU profiling rate.
+// The user documentation is in debug.go.
+void
+runtime_SetCPUProfileRate(intgo hz)
+{
+	uintptr *p;
+	uintptr n;
+
+	// Clamp hz to something reasonable.
+	if(hz < 0)
+		hz = 0;
+	if(hz > 1000000)
+		hz = 1000000;
+
+	runtime_lock(&lk);
+	if(hz > 0) {
+		if(prof == nil) {
+			prof = runtime_SysAlloc(sizeof *prof, &mstats.other_sys);
+			if(prof == nil) {
+				runtime_printf("runtime: cpu profiling cannot allocate memory\n");
+				runtime_unlock(&lk);
+				return;
+			}
+		}
+		if(prof->on || prof->handoff != 0) {
+			runtime_printf("runtime: cannot set cpu profile rate until previous profile has finished.\n");
+			runtime_unlock(&lk);
+			return;
+		}
+
+		prof->on = true;
+		p = prof->log[0];
+		// pprof binary header format.
+		// http://code.google.com/p/google-perftools/source/browse/trunk/src/profiledata.cc#117
+		*p++ = 0;  // count for header
+		*p++ = 3;  // depth for header
+		*p++ = 0;  // version number
+		*p++ = 1000000 / hz;  // period (microseconds)
+		*p++ = 0;
+		prof->nlog = p - prof->log[0];
+		prof->toggle = 0;
+		prof->wholding = false;
+		prof->wtoggle = 0;
+		prof->flushing = false;
+		prof->eod_sent = false;
+		runtime_noteclear(&prof->wait);
+
+		runtime_setcpuprofilerate(tick, hz);
+	} else if(prof != nil && prof->on) {
+		runtime_setcpuprofilerate(nil, 0);
+		prof->on = false;
+
+		// Now add is not running anymore, and getprofile owns the entire log.
+		// Set the high bit in prof->handoff to tell getprofile.
+		for(;;) {
+			n = prof->handoff;
+			if(n&0x80000000)
+				runtime_printf("runtime: setcpuprofile(off) twice");
+			if(runtime_cas(&prof->handoff, n, n|0x80000000))
+				break;
+		}
+		if(n == 0) {
+			// we did the transition from 0 -> nonzero so we wake getprofile
+			runtime_notewakeup(&prof->wait);
+		}
+	}
+	runtime_unlock(&lk);
+}
+
+static void
+tick(uintptr *pc, int32 n)
+{
+	add(prof, pc, n);
+}
+
+// add adds the stack trace to the profile.
+// It is called from signal handlers and other limited environments
+// and cannot allocate memory or acquire locks that might be
+// held at the time of the signal, nor can it use substantial amounts
+// of stack.  It is allowed to call evict.
+static void
+add(Profile *p, uintptr *pc, int32 n)
+{
+	int32 i, j;
+	uintptr h, x;
+	Bucket *b;
+	Entry *e;
+
+	if(n > MaxStack)
+		n = MaxStack;
+	
+	// Compute hash.
+	h = 0;
+	for(i=0; i<n; i++) {
+		h = h<<8 | (h>>(8*(sizeof(h)-1)));
+		x = pc[i];
+		h += x*31 + x*7 + x*3;
+	}
+	p->count++;
+
+	// Add to entry count if already present in table.
+	b = &p->hash[h%HashSize];
+	for(i=0; i<Assoc; i++) {
+		e = &b->entry[i];
+		if(e->depth != (uintptr)n)	
+			continue;
+		for(j=0; j<n; j++)
+			if(e->stack[j] != pc[j])
+				goto ContinueAssoc;
+		e->count++;
+		return;
+	ContinueAssoc:;
+	}
+
+	// Evict entry with smallest count.
+	e = &b->entry[0];
+	for(i=1; i<Assoc; i++)
+		if(b->entry[i].count < e->count)
+			e = &b->entry[i];
+	if(e->count > 0) {
+		if(!evict(p, e)) {
+			// Could not evict entry.  Record lost stack.
+			p->lost++;
+			return;
+		}
+		p->evicts++;
+	}
+	
+	// Reuse the newly evicted entry.
+	e->depth = n;
+	e->count = 1;
+	for(i=0; i<n; i++)
+		e->stack[i] = pc[i];
+}
+
+// evict copies the given entry's data into the log, so that
+// the entry can be reused.  evict is called from add, which
+// is called from the profiling signal handler, so it must not
+// allocate memory or block.  It is safe to call flushLog.
+// evict returns true if the entry was copied to the log,
+// false if there was no room available.
+static bool
+evict(Profile *p, Entry *e)
+{
+	int32 i, d, nslot;
+	uintptr *log, *q;
+	
+	d = e->depth;
+	nslot = d+2;
+	log = p->log[p->toggle];
+	if(p->nlog+nslot > nelem(p->log[0])) {
+		if(!flushlog(p))
+			return false;
+		log = p->log[p->toggle];
+	}
+	
+	q = log+p->nlog;
+	*q++ = e->count;
+	*q++ = d;
+	for(i=0; i<d; i++)
+		*q++ = e->stack[i];
+	p->nlog = q - log;
+	e->count = 0;
+	return true;
+}
+
+// flushlog tries to flush the current log and switch to the other one.
+// flushlog is called from evict, called from add, called from the signal handler,
+// so it cannot allocate memory or block.  It can try to swap logs with
+// the writing goroutine, as explained in the comment at the top of this file.
+static bool
+flushlog(Profile *p)
+{
+	uintptr *log, *q;
+
+	if(!runtime_cas(&p->handoff, 0, p->nlog))
+		return false;
+	runtime_notewakeup(&p->wait);
+
+	p->toggle = 1 - p->toggle;
+	log = p->log[p->toggle];
+	q = log;
+	if(p->lost > 0) {
+		*q++ = p->lost;
+		*q++ = 1;
+		*q++ = (uintptr)LostProfileData;
+		p->lost = 0;
+	}
+	p->nlog = q - log;
+	return true;
+}
+
+// getprofile blocks until the next block of profiling data is available
+// and returns it as a []byte.  It is called from the writing goroutine.
+Slice
+getprofile(Profile *p)
+{
+	uint32 i, j, n;
+	Slice ret;
+	Bucket *b;
+	Entry *e;
+
+	ret.array = nil;
+	ret.len = 0;
+	ret.cap = 0;
+	
+	if(p == nil)	
+		return ret;
+
+	if(p->wholding) {
+		// Release previous log to signal handling side.
+		// Loop because we are racing against SetCPUProfileRate(0).
+		for(;;) {
+			n = p->handoff;
+			if(n == 0) {
+				runtime_printf("runtime: phase error during cpu profile handoff\n");
+				return ret;
+			}
+			if(n & 0x80000000) {
+				p->wtoggle = 1 - p->wtoggle;
+				p->wholding = false;
+				p->flushing = true;
+				goto flush;
+			}
+			if(runtime_cas(&p->handoff, n, 0))
+				break;
+		}
+		p->wtoggle = 1 - p->wtoggle;
+		p->wholding = false;
+	}
+	
+	if(p->flushing)
+		goto flush;
+	
+	if(!p->on && p->handoff == 0)
+		return ret;
+
+	// Wait for new log.
+	runtime_notetsleepg(&p->wait, -1);
+	runtime_noteclear(&p->wait);
+
+	n = p->handoff;
+	if(n == 0) {
+		runtime_printf("runtime: phase error during cpu profile wait\n");
+		return ret;
+	}
+	if(n == 0x80000000) {
+		p->flushing = true;
+		goto flush;
+	}
+	n &= ~0x80000000;
+
+	// Return new log to caller.
+	p->wholding = true;
+
+	ret.array = (byte*)p->log[p->wtoggle];
+	ret.len = n*sizeof(uintptr);
+	ret.cap = ret.len;
+	return ret;
+
+flush:
+	// In flush mode.
+	// Add is no longer being called.  We own the log.
+	// Also, p->handoff is non-zero, so flushlog will return false.
+	// Evict the hash table into the log and return it.
+	for(i=0; i<HashSize; i++) {
+		b = &p->hash[i];
+		for(j=0; j<Assoc; j++) {
+			e = &b->entry[j];
+			if(e->count > 0 && !evict(p, e)) {
+				// Filled the log.  Stop the loop and return what we've got.
+				goto breakflush;
+			}
+		}
+	}
+breakflush:
+
+	// Return pending log data.
+	if(p->nlog > 0) {
+		// Note that we're using toggle now, not wtoggle,
+		// because we're working on the log directly.
+		ret.array = (byte*)p->log[p->toggle];
+		ret.len = p->nlog*sizeof(uintptr);
+		ret.cap = ret.len;
+		p->nlog = 0;
+		return ret;
+	}
+
+	// Made it through the table without finding anything to log.
+	if(!p->eod_sent) {
+		// We may not have space to append this to the partial log buf,
+		// so we always return a new slice for the end-of-data marker.
+		p->eod_sent = true;
+		ret.array = (byte*)eod;
+		ret.len = sizeof eod;
+		ret.cap = ret.len;
+		return ret;
+	}
+
+	// Finally done.  Clean up and return nil.
+	p->flushing = false;
+	if(!runtime_cas(&p->handoff, p->handoff, 0))
+		runtime_printf("runtime: profile flush racing with something\n");
+	return ret;  // set to nil at top of function
+}
+
+// CPUProfile returns the next cpu profile block as a []byte.
+// The user documentation is in debug.go.
+func CPUProfile() (ret Slice) {
+	ret = getprofile(prof);
+}
diff --git a/third_party/gofrontend/libgo/runtime/defs.h b/third_party/gofrontend/libgo/runtime/defs.h
new file mode 100644
index 0000000..67ad212
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/defs.h
@@ -0,0 +1,12 @@
+/* defs.h -- runtime definitions for Go.
+
+   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.  */
+
+/* The gc library uses this file for system defines, and generates it
+   automatically using the godefs program.  The logical thing to put
+   here for gccgo would be #include statements for system header
+   files.  We can't do that, though, because runtime.h #define's the
+   standard types.  So we #include the system headers from runtime.h
+   instead.  */
diff --git a/third_party/gofrontend/libgo/runtime/env_posix.c b/third_party/gofrontend/libgo/runtime/env_posix.c
new file mode 100644
index 0000000..ff4bf0c
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/env_posix.c
@@ -0,0 +1,40 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+#include "runtime.h"
+#include "array.h"
+#include "arch.h"
+#include "malloc.h"
+
+extern Slice syscall_Envs __asm__ (GOSYM_PREFIX "syscall.Envs");
+
+const byte*
+runtime_getenv(const char *s)
+{
+	int32 i, j;
+	intgo len;
+	const byte *v, *bs;
+	String* envv;
+	int32 envc;
+
+	bs = (const byte*)s;
+	len = runtime_findnull(bs);
+	envv = (String*)syscall_Envs.__values;
+	envc = syscall_Envs.__count;
+	for(i=0; i<envc; i++){
+		if(envv[i].len <= len)
+			continue;
+		v = (const byte*)envv[i].str;
+		for(j=0; j<len; j++)
+			if(bs[j] != v[j])
+				goto nomatch;
+		if(v[len] != '=')
+			goto nomatch;
+		return v+len+1;
+	nomatch:;
+	}
+	return nil;
+}
diff --git a/third_party/gofrontend/libgo/runtime/getncpu-bsd.c b/third_party/gofrontend/libgo/runtime/getncpu-bsd.c
new file mode 100644
index 0000000..00a81d1
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/getncpu-bsd.c
@@ -0,0 +1,24 @@
+// 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 <sys/types.h>
+#include <sys/sysctl.h>
+
+#include "runtime.h"
+#include "defs.h"
+
+int32
+getproccount(void)
+{
+	int mib[2], out;
+	size_t len;
+
+	mib[0] = CTL_HW;
+	mib[1] = HW_NCPU;
+	len = sizeof(out);
+	if(sysctl(mib, 2, &out, &len, NULL, 0) >= 0)
+		return (int32)out;
+	else
+		return 0;
+}
diff --git a/third_party/gofrontend/libgo/runtime/getncpu-irix.c b/third_party/gofrontend/libgo/runtime/getncpu-irix.c
new file mode 100644
index 0000000..a65ca63
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/getncpu-irix.c
@@ -0,0 +1,16 @@
+// 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 <unistd.h>
+
+#include "runtime.h"
+#include "defs.h"
+
+int32
+getproccount(void)
+{
+	int32 n;
+	n = (int32)sysconf(_SC_NPROC_ONLN);
+	return n > 1 ? n : 1;
+}
diff --git a/third_party/gofrontend/libgo/runtime/getncpu-linux.c b/third_party/gofrontend/libgo/runtime/getncpu-linux.c
new file mode 100644
index 0000000..de6606f
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/getncpu-linux.c
@@ -0,0 +1,36 @@
+// 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 <features.h>
+#include <sched.h>
+
+// CPU_COUNT is only provided by glibc 2.6 or higher
+#ifndef CPU_COUNT
+#define CPU_COUNT(set) _CPU_COUNT((unsigned int *)(set), sizeof(*(set))/sizeof(unsigned int))
+static int _CPU_COUNT(unsigned int *set, size_t len) {
+	int cnt;
+
+	cnt = 0;
+	while (len--)
+		cnt += __builtin_popcount(*set++);
+	return cnt;
+}
+#endif
+
+#include "runtime.h"
+#include "defs.h"
+
+int32
+getproccount(void)
+{
+	cpu_set_t set;
+	int32 r, cnt;
+
+	cnt = 0;
+	r = sched_getaffinity(0, sizeof(set), &set);
+	if(r == 0)
+		cnt += CPU_COUNT(&set);
+
+	return cnt ? cnt : 1;
+}
diff --git a/third_party/gofrontend/libgo/runtime/getncpu-none.c b/third_party/gofrontend/libgo/runtime/getncpu-none.c
new file mode 100644
index 0000000..ba6fd4e
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/getncpu-none.c
@@ -0,0 +1,12 @@
+// 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 "runtime.h"
+#include "defs.h"
+
+int32
+getproccount(void)
+{
+	return 0;
+}
diff --git a/third_party/gofrontend/libgo/runtime/getncpu-solaris.c b/third_party/gofrontend/libgo/runtime/getncpu-solaris.c
new file mode 100644
index 0000000..5d5d702
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/getncpu-solaris.c
@@ -0,0 +1,16 @@
+// 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 <unistd.h>
+
+#include "runtime.h"
+#include "defs.h"
+
+int32
+getproccount(void)
+{
+	int32 n;
+	n = (int32)sysconf(_SC_NPROCESSORS_ONLN);
+	return n > 1 ? n : 1;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-alloc.h b/third_party/gofrontend/libgo/runtime/go-alloc.h
new file mode 100644
index 0000000..c880a04
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-alloc.h
@@ -0,0 +1,11 @@
+/* go-alloc.h -- allocate memory for Go.
+
+   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.  */
+
+#include <stddef.h>
+#include <stdint.h>
+
+extern void *__go_alloc (unsigned int __attribute__ ((mode (pointer))));
+extern void __go_free (void *);
diff --git a/third_party/gofrontend/libgo/runtime/go-append.c b/third_party/gofrontend/libgo/runtime/go-append.c
new file mode 100644
index 0000000..1b2d49e
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-append.c
@@ -0,0 +1,74 @@
+/* go-append.c -- the go builtin append function.
+
+   Copyright 2010 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 "runtime.h"
+#include "go-panic.h"
+#include "go-type.h"
+#include "array.h"
+#include "arch.h"
+#include "malloc.h"
+
+/* We should be OK if we don't split the stack here, since the only
+   libc functions we call are memcpy and memmove.  If we don't do
+   this, we will always split the stack, because of memcpy and
+   memmove.  */
+extern struct __go_open_array
+__go_append (struct __go_open_array, void *, uintptr_t, uintptr_t)
+  __attribute__ ((no_split_stack));
+
+struct __go_open_array
+__go_append (struct __go_open_array a, void *bvalues, uintptr_t bcount,
+	     uintptr_t element_size)
+{
+  uintptr_t ucount;
+  intgo count;
+
+  if (bvalues == NULL || bcount == 0)
+    return a;
+
+  ucount = (uintptr_t) a.__count + bcount;
+  count = (intgo) ucount;
+  if ((uintptr_t) count != ucount || count <= a.__count)
+    runtime_panicstring ("append: slice overflow");
+
+  if (count > a.__capacity)
+    {
+      intgo m;
+      uintptr capmem;
+      void *n;
+
+      m = a.__capacity;
+      if (m + m < count)
+	m = count;
+      else
+	{
+	  do
+	    {
+	      if (a.__count < 1024)
+		m += m;
+	      else
+		m += m / 4;
+	    }
+	  while (m < count);
+	}
+
+      if (element_size > 0 && (uintptr) m > MaxMem / element_size)
+	runtime_panicstring ("growslice: cap out of range");
+
+      capmem = runtime_roundupsize (m * element_size);
+
+      n = __go_alloc (capmem);
+      __builtin_memcpy (n, a.__values, a.__count * element_size);
+
+      a.__values = n;
+      a.__capacity = m;
+    }
+
+  __builtin_memmove ((char *) a.__values + a.__count * element_size,
+		     bvalues, bcount * element_size);
+  a.__count = count;
+  return a;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-assert-interface.c b/third_party/gofrontend/libgo/runtime/go-assert-interface.c
new file mode 100644
index 0000000..2510f9a
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-assert-interface.c
@@ -0,0 +1,45 @@
+/* go-assert-interface.c -- interface type assertion for Go.
+
+   Copyright 2010 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 "runtime.h"
+#include "go-alloc.h"
+#include "go-assert.h"
+#include "go-panic.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* This is called by the compiler to implement a type assertion from
+   one interface type to another.  This returns the value that should
+   go in the first field of the result tuple.  The result may be an
+   empty or a non-empty interface.  */
+
+const void *
+__go_assert_interface (const struct __go_type_descriptor *lhs_descriptor,
+		       const struct __go_type_descriptor *rhs_descriptor)
+{
+  const struct __go_interface_type *lhs_interface;
+
+  if (rhs_descriptor == NULL)
+    {
+      struct __go_empty_interface panic_arg;
+
+      /* A type assertion is not permitted with a nil interface.  */
+
+      runtime_newTypeAssertionError (NULL, NULL, lhs_descriptor->__reflection,
+				     NULL, &panic_arg);
+      __go_panic (panic_arg);
+    }
+
+  /* A type assertion to an empty interface just returns the object
+     descriptor.  */
+
+  __go_assert (lhs_descriptor->__code == GO_INTERFACE);
+  lhs_interface = (const struct __go_interface_type *) lhs_descriptor;
+  if (lhs_interface->__methods.__count == 0)
+    return rhs_descriptor;
+
+  return __go_convert_interface_2 (lhs_descriptor, rhs_descriptor, 0);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-assert.c b/third_party/gofrontend/libgo/runtime/go-assert.c
new file mode 100644
index 0000000..a36f43a
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-assert.c
@@ -0,0 +1,19 @@
+/* go-assert.c -- libgo specific assertions
+
+   Copyright 2010 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 <stdio.h>
+#include <stdlib.h>
+
+#include "runtime.h"
+#include "go-assert.h"
+
+void
+__go_assert_fail (const char *file, unsigned int lineno)
+{
+  /* FIXME: Eventually we should dump a stack trace here.  */
+  runtime_printf ("%s:%U: libgo assertion failure\n", file, (uint64) lineno);
+  abort ();
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-assert.h b/third_party/gofrontend/libgo/runtime/go-assert.h
new file mode 100644
index 0000000..6365595
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-assert.h
@@ -0,0 +1,18 @@
+/* go-assert.h -- libgo specific assertions
+
+   Copyright 2010 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.  */
+
+#ifndef LIBGO_GO_ASSERT_H
+#define LIBGO_GO_ASSERT_H
+
+/* We use a Go specific assert function so that functions which call
+   assert aren't required to always split the stack.  */
+
+extern void __go_assert_fail (const char *file, unsigned int lineno)
+  __attribute__ ((noreturn));
+
+#define __go_assert(e) ((e) ? (void) 0 : __go_assert_fail (__FILE__, __LINE__))
+
+#endif /* !defined(LIBGO_GO_ASSERT_H) */
diff --git a/third_party/gofrontend/libgo/runtime/go-breakpoint.c b/third_party/gofrontend/libgo/runtime/go-breakpoint.c
new file mode 100644
index 0000000..e403a2a
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-breakpoint.c
@@ -0,0 +1,17 @@
+/* go-breakpoint.c -- the runtime.Breakpoint function.
+
+   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.  */
+
+#include <sched.h>
+
+#include "runtime.h"
+
+void Breakpoint (void) __asm__ (GOSYM_PREFIX "runtime.Breakpoint");
+
+void
+Breakpoint (void)
+{
+  __builtin_trap ();
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-byte-array-to-string.c b/third_party/gofrontend/libgo/runtime/go-byte-array-to-string.c
new file mode 100644
index 0000000..088b786
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-byte-array-to-string.c
@@ -0,0 +1,24 @@
+/* go-byte-array-to-string.c -- convert an array of bytes to a string in Go.
+
+   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.  */
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+String
+__go_byte_array_to_string (const void* p, intgo len)
+{
+  const unsigned char *bytes;
+  unsigned char *retdata;
+  String ret;
+
+  bytes = (const unsigned char *) p;
+  retdata = runtime_mallocgc ((uintptr) len, 0, FlagNoScan);
+  __builtin_memcpy (retdata, bytes, len);
+  ret.str = retdata;
+  ret.len = len;
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-caller.c b/third_party/gofrontend/libgo/runtime/go-caller.c
new file mode 100644
index 0000000..7fcdf20
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-caller.c
@@ -0,0 +1,269 @@
+/* go-caller.c -- runtime.Caller and runtime.FuncForPC for Go.
+
+   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.  */
+
+/* Implement runtime.Caller.  */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "backtrace.h"
+
+#include "runtime.h"
+
+/* Get the function name, file name, and line number for a PC value.
+   We use the backtrace library to get this.  */
+
+/* Data structure to gather file/line information.  */
+
+struct caller
+{
+  String fn;
+  String file;
+  intgo line;
+};
+
+/* Collect file/line information for a PC value.  If this is called
+   more than once, due to inlined functions, we use the last call, as
+   that is usually the most useful one.  */
+
+static int
+callback (void *data, uintptr_t pc __attribute__ ((unused)),
+	  const char *filename, int lineno, const char *function)
+{
+  struct caller *c = (struct caller *) data;
+
+  if (function == NULL)
+    {
+      c->fn.str = NULL;
+      c->fn.len = 0;
+    }
+  else
+    {
+      byte *s;
+
+      c->fn.len = __builtin_strlen (function);
+      s = runtime_malloc (c->fn.len);
+      __builtin_memcpy (s, function, c->fn.len);
+      c->fn.str = s;
+    }
+
+  if (filename == NULL)
+    {
+      c->file.str = NULL;
+      c->file.len = 0;
+    }
+  else
+    {
+      byte *s;
+
+      c->file.len = __builtin_strlen (filename);
+      s = runtime_malloc (c->file.len);
+      __builtin_memcpy (s, filename, c->file.len);
+      c->file.str = s;
+    }
+
+  c->line = lineno;
+
+  return 0;
+}
+
+/* The error callback for backtrace_pcinfo and backtrace_syminfo.  */
+
+static void
+error_callback (void *data __attribute__ ((unused)),
+		const char *msg, int errnum)
+{
+  if (errnum == -1)
+    return;
+  if (errnum > 0)
+    runtime_printf ("%s errno %d\n", msg, errnum);
+  runtime_throw (msg);
+}
+
+/* The backtrace library state.  */
+
+static void *back_state;
+
+/* A lock to control creating back_state.  */
+
+static Lock back_state_lock;
+
+/* Fetch back_state, creating it if necessary.  */
+
+struct backtrace_state *
+__go_get_backtrace_state ()
+{
+  runtime_lock (&back_state_lock);
+  if (back_state == NULL)
+    {
+      const char *filename;
+      struct stat s;
+
+      filename = (const char *) runtime_progname ();
+
+      /* If there is no '/' in FILENAME, it was found on PATH, and
+	 might not be the same as the file with the same name in the
+	 current directory.  */
+      if (__builtin_strchr (filename, '/') == NULL)
+	filename = NULL;
+
+      /* If the file is small, then it's not the real executable.
+	 This is specifically to deal with Docker, which uses a bogus
+	 argv[0] (http://gcc.gnu.org/PR61895).  It would be nice to
+	 have a better check for whether this file is the real
+	 executable.  */
+      if (stat (filename, &s) < 0 || s.st_size < 1024)
+	filename = NULL;
+
+      back_state = backtrace_create_state (filename, 1, error_callback, NULL);
+    }
+  runtime_unlock (&back_state_lock);
+  return back_state;
+}
+
+/* Return function/file/line information for PC.  */
+
+_Bool
+__go_file_line (uintptr pc, String *fn, String *file, intgo *line)
+{
+  struct caller c;
+
+  runtime_memclr (&c, sizeof c);
+  backtrace_pcinfo (__go_get_backtrace_state (), pc, callback,
+		    error_callback, &c);
+  *fn = c.fn;
+  *file = c.file;
+  *line = c.line;
+  return c.file.len > 0;
+}
+
+/* Collect symbol information.  */
+
+static void
+syminfo_callback (void *data, uintptr_t pc __attribute__ ((unused)),
+		  const char *symname __attribute__ ((unused)),
+		  uintptr_t address, uintptr_t size __attribute__ ((unused)))
+{
+  uintptr_t *pval = (uintptr_t *) data;
+
+  *pval = address;
+}
+
+/* Set *VAL to the value of the symbol for PC.  */
+
+static _Bool
+__go_symbol_value (uintptr_t pc, uintptr_t *val)
+{
+  *val = 0;
+  backtrace_syminfo (__go_get_backtrace_state (), pc, syminfo_callback,
+		     error_callback, val);
+  return *val != 0;
+}
+
+/* The values returned by runtime.Caller.  */
+
+struct caller_ret
+{
+  uintptr_t pc;
+  String file;
+  intgo line;
+  _Bool ok;
+};
+
+struct caller_ret Caller (int n) __asm__ (GOSYM_PREFIX "runtime.Caller");
+
+Func *FuncForPC (uintptr_t) __asm__ (GOSYM_PREFIX "runtime.FuncForPC");
+
+/* Implement runtime.Caller.  */
+
+struct caller_ret
+Caller (int skip)
+{
+  struct caller_ret ret;
+  Location loc;
+  int32 n;
+
+  runtime_memclr (&ret, sizeof ret);
+  n = runtime_callers (skip + 1, &loc, 1, false);
+  if (n < 1)
+    return ret;
+  ret.pc = loc.pc;
+  ret.file = loc.filename;
+  ret.line = loc.lineno;
+  ret.ok = 1;
+  return ret;
+}
+
+/* Implement runtime.FuncForPC.  */
+
+Func *
+FuncForPC (uintptr_t pc)
+{
+  Func *ret;
+  String fn;
+  String file;
+  intgo line;
+  uintptr_t val;
+
+  if (!__go_file_line (pc, &fn, &file, &line))
+    return NULL;
+
+  ret = (Func *) runtime_malloc (sizeof (*ret));
+  ret->name = fn;
+
+  if (__go_symbol_value (pc, &val))
+    ret->entry = val;
+  else
+    ret->entry = 0;
+
+  return ret;
+}
+
+/* Look up the file and line information for a PC within a
+   function.  */
+
+struct funcline_go_return
+{
+  String retfile;
+  intgo retline;
+};
+
+struct funcline_go_return
+runtime_funcline_go (Func *f, uintptr targetpc)
+  __asm__ (GOSYM_PREFIX "runtime.funcline_go");
+
+struct funcline_go_return
+runtime_funcline_go (Func *f __attribute__((unused)), uintptr targetpc)
+{
+  struct funcline_go_return ret;
+  String fn;
+
+  if (!__go_file_line (targetpc, &fn, &ret.retfile,  &ret.retline))
+    runtime_memclr (&ret, sizeof ret);
+  return ret;
+}
+
+/* Return the name of a function.  */
+String runtime_funcname_go (Func *f)
+  __asm__ (GOSYM_PREFIX "runtime.funcname_go");
+
+String
+runtime_funcname_go (Func *f)
+{
+  return f->name;
+}
+
+/* Return the entry point of a function.  */
+uintptr runtime_funcentry_go(Func *f)
+  __asm__ (GOSYM_PREFIX "runtime.funcentry_go");
+
+uintptr
+runtime_funcentry_go (Func *f)
+{
+  return f->entry;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-callers.c b/third_party/gofrontend/libgo/runtime/go-callers.c
new file mode 100644
index 0000000..0470345
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-callers.c
@@ -0,0 +1,178 @@
+/* go-callers.c -- get callers for 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.  */
+
+#include "config.h"
+
+#include "backtrace.h"
+
+#include "runtime.h"
+#include "array.h"
+
+/* This is set to non-zero when calling backtrace_full.  This is used
+   to avoid getting hanging on a recursive lock in dl_iterate_phdr on
+   older versions of glibc when a SIGPROF signal arrives while
+   collecting a backtrace.  */
+
+uint32 runtime_in_callers;
+
+/* Argument passed to callback function.  */
+
+struct callers_data
+{
+  Location *locbuf;
+  int skip;
+  int index;
+  int max;
+  int keep_thunks;
+};
+
+/* Callback function for backtrace_full.  Just collect the locations.
+   Return zero to continue, non-zero to stop.  */
+
+static int
+callback (void *data, uintptr_t pc, const char *filename, int lineno,
+	  const char *function)
+{
+  struct callers_data *arg = (struct callers_data *) data;
+  Location *loc;
+
+  /* Skip split stack functions.  */
+  if (function != NULL)
+    {
+      const char *p;
+
+      p = function;
+      if (__builtin_strncmp (p, "___", 3) == 0)
+	++p;
+      if (__builtin_strncmp (p, "__morestack_", 12) == 0)
+	return 0;
+    }
+  else if (filename != NULL)
+    {
+      const char *p;
+
+      p = strrchr (filename, '/');
+      if (p == NULL)
+	p = filename;
+      if (__builtin_strncmp (p, "/morestack.S", 12) == 0)
+	return 0;
+    }
+
+  /* Skip thunks and recover functions.  There is no equivalent to
+     these functions in the gc toolchain, so returning them here means
+     significantly different results for runtime.Caller(N).  */
+  if (function != NULL && !arg->keep_thunks)
+    {
+      const char *p;
+
+      p = __builtin_strchr (function, '.');
+      if (p != NULL && __builtin_strncmp (p + 1, "$thunk", 6) == 0)
+	return 0;
+      p = __builtin_strrchr (function, '$');
+      if (p != NULL && __builtin_strcmp(p, "$recover") == 0)
+	return 0;
+    }
+
+  if (arg->skip > 0)
+    {
+      --arg->skip;
+      return 0;
+    }
+
+  loc = &arg->locbuf[arg->index];
+  loc->pc = pc;
+
+  /* The libbacktrace library says that these strings might disappear,
+     but with the current implementation they won't.  We can't easily
+     allocate memory here, so for now assume that we can save a
+     pointer to the strings.  */
+  loc->filename = runtime_gostringnocopy ((const byte *) filename);
+  loc->function = runtime_gostringnocopy ((const byte *) function);
+
+  loc->lineno = lineno;
+  ++arg->index;
+
+  /* There is no point to tracing past certain runtime functions.
+     Stopping the backtrace here can avoid problems on systems that
+     don't provide proper unwind information for makecontext, such as
+     Solaris (http://gcc.gnu.org/PR52583 comment #21).  */
+  if (function != NULL)
+    {
+      if (__builtin_strcmp (function, "makecontext") == 0)
+	return 1;
+      if (filename != NULL)
+	{
+	  const char *p;
+
+	  p = strrchr (filename, '/');
+	  if (p == NULL)
+	    p = filename;
+	  if (__builtin_strcmp (p, "/proc.c") == 0)
+	    {
+	      if (__builtin_strcmp (function, "kickoff") == 0
+		  || __builtin_strcmp (function, "runtime_mstart") == 0
+		  || __builtin_strcmp (function, "runtime_main") == 0)
+		return 1;
+	    }
+	}
+    }
+
+  return arg->index >= arg->max;
+}
+
+/* Error callback.  */
+
+static void
+error_callback (void *data __attribute__ ((unused)),
+		const char *msg, int errnum)
+{
+  if (errnum != 0)
+    runtime_printf ("%s errno %d\n", msg, errnum);
+  runtime_throw (msg);
+}
+
+/* Gather caller PC's.  */
+
+int32
+runtime_callers (int32 skip, Location *locbuf, int32 m, bool keep_thunks)
+{
+  struct callers_data data;
+
+  data.locbuf = locbuf;
+  data.skip = skip + 1;
+  data.index = 0;
+  data.max = m;
+  data.keep_thunks = keep_thunks;
+  runtime_xadd (&runtime_in_callers, 1);
+  backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback,
+		  &data);
+  runtime_xadd (&runtime_in_callers, -1);
+  return data.index;
+}
+
+int Callers (int, struct __go_open_array)
+  __asm__ (GOSYM_PREFIX "runtime.Callers");
+
+int
+Callers (int skip, struct __go_open_array pc)
+{
+  Location *locbuf;
+  int ret;
+  int i;
+
+  locbuf = (Location *) runtime_mal (pc.__count * sizeof (Location));
+
+  /* In the Go 1 release runtime.Callers has an off-by-one error,
+     which we can not correct because it would break backward
+     compatibility.  Normally we would add 1 to SKIP here, but we
+     don't so that we are compatible.  */
+  ret = runtime_callers (skip, locbuf, pc.__count, false);
+
+  for (i = 0; i < ret; i++)
+    ((uintptr *) pc.__values)[i] = locbuf[i].pc;
+
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-can-convert-interface.c b/third_party/gofrontend/libgo/runtime/go-can-convert-interface.c
new file mode 100644
index 0000000..4de5580
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-can-convert-interface.c
@@ -0,0 +1,78 @@
+/* go-can-convert-interface.c -- can we convert to an interface?
+
+   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.  */
+
+#include "runtime.h"
+#include "go-assert.h"
+#include "go-string.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* Return whether we can convert from the type in FROM_DESCRIPTOR to
+   the interface in TO_DESCRIPTOR.  This is used for type
+   switches.  */
+
+_Bool
+__go_can_convert_to_interface (
+    const struct __go_type_descriptor *to_descriptor,
+    const struct __go_type_descriptor *from_descriptor)
+{
+  const struct __go_interface_type *to_interface;
+  int to_method_count;
+  const struct __go_interface_method *to_method;
+  const struct __go_uncommon_type *from_uncommon;
+  int from_method_count;
+  const struct __go_method *from_method;
+  int i;
+
+  /* In a type switch FROM_DESCRIPTOR can be NULL.  */
+  if (from_descriptor == NULL)
+    return 0;
+
+  __go_assert (to_descriptor->__code == GO_INTERFACE);
+  to_interface = (const struct __go_interface_type *) to_descriptor;
+  to_method_count = to_interface->__methods.__count;
+  to_method = ((const struct __go_interface_method *)
+	       to_interface->__methods.__values);
+
+  from_uncommon = from_descriptor->__uncommon;
+  if (from_uncommon == NULL)
+    {
+      from_method_count = 0;
+      from_method = NULL;
+    }
+  else
+    {
+      from_method_count = from_uncommon->__methods.__count;
+      from_method = ((const struct __go_method *)
+		     from_uncommon->__methods.__values);
+    }
+
+  for (i = 0; i < to_method_count; ++i)
+    {
+      while (from_method_count > 0
+	     && (!__go_ptr_strings_equal (from_method->__name,
+					  to_method->__name)
+		 || !__go_ptr_strings_equal (from_method->__pkg_path,
+					     to_method->__pkg_path)))
+	{
+	  ++from_method;
+	  --from_method_count;
+	}
+
+      if (from_method_count == 0)
+	return 0;
+
+      if (!__go_type_descriptors_equal (from_method->__mtype,
+					to_method->__type))
+	return 0;
+
+      ++to_method;
+      ++from_method;
+      --from_method_count;
+    }
+
+  return 1;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-cdiv.c b/third_party/gofrontend/libgo/runtime/go-cdiv.c
new file mode 100644
index 0000000..0355e26
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-cdiv.c
@@ -0,0 +1,49 @@
+/* go-cdiv.c -- complex division routines
+
+   Copyright 2013 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 <complex.h>
+#include <math.h>
+
+/* Calls to these functions are generated by the Go frontend for
+   division of complex64 or complex128.  We use these because Go's
+   complex division expects slightly different results from the GCC
+   default.  When dividing NaN+1.0i / 0+0i, Go expects NaN+NaNi but
+   GCC generates NaN+Infi.  NaN+Infi seems wrong seems the rules of
+   C99 Annex G specify that if either side of a complex number is Inf,
+   the the whole number is Inf, but an operation involving NaN ought
+   to result in NaN, not Inf.  */
+
+complex float
+__go_complex64_div (complex float a, complex float b)
+{
+  if (__builtin_expect (b == 0, 0))
+    {
+      if (!isinf (crealf (a))
+	  && !isinf (cimagf (a))
+	  && (isnan (crealf (a)) || isnan (cimagf (a))))
+	{
+	  /* Pass "1" to nanf to match math/bits.go.  */
+	  return nanf("1") + nanf("1")*I;
+	}
+    }
+  return a / b;
+}
+
+complex double
+__go_complex128_div (complex double a, complex double b)
+{
+  if (__builtin_expect (b == 0, 0))
+    {
+      if (!isinf (creal (a))
+	  && !isinf (cimag (a))
+	  && (isnan (creal (a)) || isnan (cimag (a))))
+	{
+	  /* Pass "1" to nan to match math/bits.go.  */
+	  return nan("1") + nan("1")*I;
+	}
+    }
+  return a / b;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-cgo.c b/third_party/gofrontend/libgo/runtime/go-cgo.c
new file mode 100644
index 0000000..2b7baa4
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-cgo.c
@@ -0,0 +1,179 @@
+/* go-cgo.c -- SWIG support routines for libgo.
+
+   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.  */
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "interface.h"
+#include "go-panic.h"
+
+/* Prepare to call from code written in Go to code written in C or
+   C++.  This takes the current goroutine out of the Go scheduler, as
+   though it were making a system call.  Otherwise the program can
+   lock up if the C code goes to sleep on a mutex or for some other
+   reason.  This idea is to call this function, then immediately call
+   the C/C++ function.  After the C/C++ function returns, call
+   syscall_cgocalldone.  The usual Go code would look like
+
+       syscall.Cgocall()
+       defer syscall.Cgocalldone()
+       cfunction()
+
+   */
+
+/* We let Go code call these via the syscall package.  */
+void syscall_cgocall(void) __asm__ (GOSYM_PREFIX "syscall.Cgocall");
+void syscall_cgocalldone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallDone");
+void syscall_cgocallback(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBack");
+void syscall_cgocallbackdone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBackDone");
+
+void
+syscall_cgocall ()
+{
+  M* m;
+  G* g;
+
+  if (runtime_needextram && runtime_cas (&runtime_needextram, 1, 0))
+    runtime_newextram ();
+
+  m = runtime_m ();
+  ++m->ncgocall;
+  g = runtime_g ();
+  ++g->ncgo;
+  runtime_entersyscall ();
+}
+
+/* Prepare to return to Go code from C/C++ code.  */
+
+void
+syscall_cgocalldone ()
+{
+  G* g;
+
+  g = runtime_g ();
+  __go_assert (g != NULL);
+  --g->ncgo;
+  if (g->ncgo == 0)
+    {
+      /* We are going back to Go, and we are not in a recursive call.
+	 Let the garbage collector clean up any unreferenced
+	 memory.  */
+      g->cgomal = NULL;
+    }
+
+  /* If we are invoked because the C function called _cgo_panic, then
+     _cgo_panic will already have exited syscall mode.  */
+  if (g->status == Gsyscall)
+    runtime_exitsyscall ();
+}
+
+/* Call back from C/C++ code to Go code.  */
+
+void
+syscall_cgocallback ()
+{
+  M *mp;
+
+  mp = runtime_m ();
+  if (mp == NULL)
+    {
+      runtime_needm ();
+      mp = runtime_m ();
+      mp->dropextram = true;
+    }
+
+  runtime_exitsyscall ();
+
+  mp = runtime_m ();
+  if (mp->needextram)
+    {
+      mp->needextram = 0;
+      runtime_newextram ();
+    }
+}
+
+/* Prepare to return to C/C++ code from a callback to Go code.  */
+
+void
+syscall_cgocallbackdone ()
+{
+  M *mp;
+
+  runtime_entersyscall ();
+  mp = runtime_m ();
+  if (mp->dropextram && runtime_g ()->ncgo == 0)
+    {
+      mp->dropextram = false;
+      runtime_dropm ();
+    }
+}
+
+/* Allocate memory and save it in a list visible to the Go garbage
+   collector.  */
+
+void *
+alloc_saved (size_t n)
+{
+  void *ret;
+  G *g;
+  CgoMal *c;
+
+  ret = __go_alloc (n);
+
+  g = runtime_g ();
+  c = (CgoMal *) __go_alloc (sizeof (CgoMal));
+  c->next = g->cgomal;
+  c->alloc = ret;
+  g->cgomal = c;
+
+  return ret;
+}
+
+/* These are routines used by SWIG.  The gc runtime library provides
+   the same routines under the same name, though in that case the code
+   is required to import runtime/cgo.  */
+
+void *
+_cgo_allocate (size_t n)
+{
+  void *ret;
+
+  runtime_exitsyscall ();
+  ret = alloc_saved (n);
+  runtime_entersyscall ();
+  return ret;
+}
+
+extern const struct __go_type_descriptor string_type_descriptor
+  __asm__ (GOSYM_PREFIX "__go_tdn_string");
+
+void
+_cgo_panic (const char *p)
+{
+  intgo len;
+  unsigned char *data;
+  String *ps;
+  struct __go_empty_interface e;
+
+  runtime_exitsyscall ();
+  len = __builtin_strlen (p);
+  data = alloc_saved (len);
+  __builtin_memcpy (data, p, len);
+  ps = alloc_saved (sizeof *ps);
+  ps->str = data;
+  ps->len = len;
+  e.__type_descriptor = &string_type_descriptor;
+  e.__object = ps;
+
+  /* We don't call runtime_entersyscall here, because normally what
+     will happen is that we will walk up the stack to a Go deferred
+     function that calls recover.  However, this will do the wrong
+     thing if this panic is recovered and the stack unwinding is
+     caught by a C++ exception handler.  It might be possible to
+     handle this by calling runtime_entersyscall in the personality
+     function in go-unwind.c.  FIXME.  */
+
+  __go_panic (e);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-check-interface.c b/third_party/gofrontend/libgo/runtime/go-check-interface.c
new file mode 100644
index 0000000..c29971a
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-check-interface.c
@@ -0,0 +1,46 @@
+/* go-check-interface.c -- check an interface type for a conversion
+
+   Copyright 2010 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 "runtime.h"
+#include "go-panic.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* Check that an interface type matches for a conversion to a
+   non-interface type.  This panics if the types are bad.  The actual
+   extraction of the object is inlined.  */
+
+void
+__go_check_interface_type (
+    const struct __go_type_descriptor *lhs_descriptor,
+    const struct __go_type_descriptor *rhs_descriptor,
+    const struct __go_type_descriptor *rhs_inter_descriptor)
+{
+  if (rhs_descriptor == NULL)
+    {
+      struct __go_empty_interface panic_arg;
+
+      runtime_newTypeAssertionError(NULL, NULL, lhs_descriptor->__reflection,
+				    NULL, &panic_arg);
+      __go_panic(panic_arg);
+    }
+
+  if (lhs_descriptor != rhs_descriptor
+      && !__go_type_descriptors_equal (lhs_descriptor, rhs_descriptor)
+      && (lhs_descriptor->__code != GO_UNSAFE_POINTER
+	  || !__go_is_pointer_type (rhs_descriptor))
+      && (rhs_descriptor->__code != GO_UNSAFE_POINTER
+	  || !__go_is_pointer_type (lhs_descriptor)))
+    {
+      struct __go_empty_interface panic_arg;
+
+      runtime_newTypeAssertionError(rhs_inter_descriptor->__reflection,
+				    rhs_descriptor->__reflection,
+				    lhs_descriptor->__reflection,
+				    NULL, &panic_arg);
+      __go_panic(panic_arg);
+    }
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-construct-map.c b/third_party/gofrontend/libgo/runtime/go-construct-map.c
new file mode 100644
index 0000000..4bd79d2
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-construct-map.c
@@ -0,0 +1,35 @@
+/* go-construct-map.c -- construct a map from an initializer.
+
+   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.  */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "runtime.h"
+#include "map.h"
+
+struct __go_map *
+__go_construct_map (const struct __go_map_descriptor *descriptor,
+		    uintptr_t count, uintptr_t entry_size,
+		    uintptr_t val_offset, uintptr_t val_size,
+		    const void *ventries)
+{
+  struct __go_map *ret;
+  const unsigned char *entries;
+  uintptr_t i;
+
+  ret = __go_new_map (descriptor, count);
+
+  entries = (const unsigned char *) ventries;
+  for (i = 0; i < count; ++i)
+    {
+      void *val = __go_map_index (ret, entries, 1);
+      __builtin_memcpy (val, entries + val_offset, val_size);
+      entries += entry_size;
+    }
+
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-convert-interface.c b/third_party/gofrontend/libgo/runtime/go-convert-interface.c
new file mode 100644
index 0000000..3eee6bf
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-convert-interface.c
@@ -0,0 +1,132 @@
+/* go-convert-interface.c -- convert interfaces for Go.
+
+   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.  */
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "go-assert.h"
+#include "go-panic.h"
+#include "go-string.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* This is called when converting one interface type into another
+   interface type.  LHS_DESCRIPTOR is the type descriptor of the
+   resulting interface.  RHS_DESCRIPTOR is the type descriptor of the
+   object being converted.  This builds and returns a new interface
+   method table.  If any method in the LHS_DESCRIPTOR interface is not
+   implemented by the object, the conversion fails.  If the conversion
+   fails, then if MAY_FAIL is true this returns NULL; otherwise, it
+   panics.  */
+
+void *
+__go_convert_interface_2 (const struct __go_type_descriptor *lhs_descriptor,
+			  const struct __go_type_descriptor *rhs_descriptor,
+			  _Bool may_fail)
+{
+  const struct __go_interface_type *lhs_interface;
+  int lhs_method_count;
+  const struct __go_interface_method* lhs_methods;
+  const void **methods;
+  const struct __go_uncommon_type *rhs_uncommon;
+  int rhs_method_count;
+  const struct __go_method *p_rhs_method;
+  int i;
+
+  if (rhs_descriptor == NULL)
+    {
+      /* A nil value always converts to nil.  */
+      return NULL;
+    }
+
+  __go_assert (lhs_descriptor->__code == GO_INTERFACE);
+  lhs_interface = (const struct __go_interface_type *) lhs_descriptor;
+  lhs_method_count = lhs_interface->__methods.__count;
+  lhs_methods = ((const struct __go_interface_method *)
+		 lhs_interface->__methods.__values);
+
+  /* This should not be called for an empty interface.  */
+  __go_assert (lhs_method_count > 0);
+
+  rhs_uncommon = rhs_descriptor->__uncommon;
+  if (rhs_uncommon == NULL || rhs_uncommon->__methods.__count == 0)
+    {
+      struct __go_empty_interface panic_arg;
+
+      if (may_fail)
+	return NULL;
+
+      runtime_newTypeAssertionError (NULL, rhs_descriptor->__reflection,
+				     lhs_descriptor->__reflection,
+				     lhs_methods[0].__name,
+				     &panic_arg);
+      __go_panic (panic_arg);
+    }
+
+  rhs_method_count = rhs_uncommon->__methods.__count;
+  p_rhs_method = ((const struct __go_method *)
+		  rhs_uncommon->__methods.__values);
+
+  methods = NULL;
+
+  for (i = 0; i < lhs_method_count; ++i)
+    {
+      const struct __go_interface_method *p_lhs_method;
+
+      p_lhs_method = &lhs_methods[i];
+
+      while (rhs_method_count > 0
+	     && (!__go_ptr_strings_equal (p_lhs_method->__name,
+					  p_rhs_method->__name)
+		 || !__go_ptr_strings_equal (p_lhs_method->__pkg_path,
+					     p_rhs_method->__pkg_path)))
+	{
+	  ++p_rhs_method;
+	  --rhs_method_count;
+	}
+
+      if (rhs_method_count == 0
+	  || !__go_type_descriptors_equal (p_lhs_method->__type,
+					   p_rhs_method->__mtype))
+	{
+	  struct __go_empty_interface panic_arg;
+
+	  if (methods != NULL)
+	    __go_free (methods);
+
+	  if (may_fail)
+	    return NULL;
+
+	  runtime_newTypeAssertionError (NULL, rhs_descriptor->__reflection,
+					 lhs_descriptor->__reflection,
+					 p_lhs_method->__name, &panic_arg);
+	  __go_panic (panic_arg);
+	}
+
+      if (methods == NULL)
+	{
+	  methods = (const void **) __go_alloc ((lhs_method_count + 1)
+						* sizeof (void *));
+
+	  /* The first field in the method table is always the type of
+	     the object.  */
+	  methods[0] = rhs_descriptor;
+	}
+
+      methods[i + 1] = p_rhs_method->__function;
+    }
+
+  return methods;
+}
+
+/* This is called by the compiler to convert a value from one
+   interface type to another.  */
+
+void *
+__go_convert_interface (const struct __go_type_descriptor *lhs_descriptor,
+			const struct __go_type_descriptor *rhs_descriptor)
+{
+  return __go_convert_interface_2 (lhs_descriptor, rhs_descriptor, 0);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-copy.c b/third_party/gofrontend/libgo/runtime/go-copy.c
new file mode 100644
index 0000000..05e16ac
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-copy.c
@@ -0,0 +1,22 @@
+/* go-append.c -- the go builtin copy function.
+
+   Copyright 2010 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 <stddef.h>
+#include <stdint.h>
+
+/* We should be OK if we don't split the stack here, since we are just
+   calling memmove which shouldn't need much stack.  If we don't do
+   this we will always split the stack, because of memmove.  */
+
+extern void
+__go_copy (void *, void *, uintptr_t)
+  __attribute__ ((no_split_stack));
+
+void
+__go_copy (void *a, void *b, uintptr_t len)
+{
+  __builtin_memmove (a, b, len);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-defer.c b/third_party/gofrontend/libgo/runtime/go-defer.c
new file mode 100644
index 0000000..3a48fe1
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-defer.c
@@ -0,0 +1,85 @@
+/* go-defer.c -- manage the defer stack.
+
+   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.  */
+
+#include <stddef.h>
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "go-panic.h"
+#include "go-defer.h"
+
+/* This function is called each time we need to defer a call.  */
+
+void
+__go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
+{
+  G *g;
+  struct __go_defer_stack *n;
+
+  g = runtime_g ();
+  n = runtime_newdefer ();
+  n->__next = g->defer;
+  n->__frame = frame;
+  n->__panic = g->panic;
+  n->__pfn = pfn;
+  n->__arg = arg;
+  n->__retaddr = NULL;
+  n->__makefunc_can_recover = 0;
+  n->__special = 0;
+  g->defer = n;
+}
+
+/* This function is called when we want to undefer the stack.  */
+
+void
+__go_undefer (_Bool *frame)
+{
+  G *g;
+
+  g = runtime_g ();
+  while (g->defer != NULL && g->defer->__frame == frame)
+    {
+      struct __go_defer_stack *d;
+      void (*pfn) (void *);
+
+      d = g->defer;
+      pfn = d->__pfn;
+      d->__pfn = NULL;
+
+      if (pfn != NULL)
+	(*pfn) (d->__arg);
+
+      g->defer = d->__next;
+
+      /* This may be called by a cgo callback routine to defer the
+	 call to syscall.CgocallBackDone, in which case we will not
+	 have a memory context.  Don't try to free anything in that
+	 case--the GC will release it later.  */
+      if (runtime_m () != NULL)
+	runtime_freedefer (d);
+
+      /* Since we are executing a defer function here, we know we are
+	 returning from the calling function.  If the calling
+	 function, or one of its callees, paniced, then the defer
+	 functions would be executed by __go_panic.  */
+      *frame = 1;
+    }
+}
+
+/* This function is called to record the address to which the deferred
+   function returns.  This may in turn be checked by __go_can_recover.
+   The frontend relies on this function returning false.  */
+
+_Bool
+__go_set_defer_retaddr (void *retaddr)
+{
+  G *g;
+
+  g = runtime_g ();
+  if (g->defer != NULL)
+    g->defer->__retaddr = __builtin_extract_return_addr (retaddr);
+  return 0;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-defer.h b/third_party/gofrontend/libgo/runtime/go-defer.h
new file mode 100644
index 0000000..acf2d40
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-defer.h
@@ -0,0 +1,47 @@
+/* go-defer.h -- the defer stack.
+
+   Copyright 2010 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.  */
+
+struct __go_panic_stack;
+
+/* The defer stack is a list of these structures.  */
+
+struct __go_defer_stack
+{
+  /* The next entry in the stack.  */
+  struct __go_defer_stack *__next;
+
+  /* The stack variable for the function which called this defer
+     statement.  This is set to 1 if we are returning from that
+     function, 0 if we are panicing through it.  */
+  _Bool *__frame;
+
+  /* The value of the panic stack when this function is deferred.
+     This function can not recover this value from the panic stack.
+     This can happen if a deferred function has a defer statement
+     itself.  */
+  struct __go_panic_stack *__panic;
+
+  /* The function to call.  */
+  void (*__pfn) (void *);
+
+  /* The argument to pass to the function.  */
+  void *__arg;
+
+  /* The return address that a recover thunk matches against.  This is
+     set by __go_set_defer_retaddr which is called by the thunks
+     created by defer statements.  */
+  const void *__retaddr;
+
+  /* Set to true if a function created by reflect.MakeFunc is
+     permitted to recover.  The return address of such a function
+     function will be somewhere in libffi, so __retaddr is not
+     useful.  */
+  _Bool __makefunc_can_recover;
+
+  /* Set to true if this defer stack entry is not part of the defer
+     pool.  */
+  _Bool __special;
+};
diff --git a/third_party/gofrontend/libgo/runtime/go-deferred-recover.c b/third_party/gofrontend/libgo/runtime/go-deferred-recover.c
new file mode 100644
index 0000000..78ef287
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-deferred-recover.c
@@ -0,0 +1,94 @@
+/* go-deferred-recover.c -- support for a deferred recover function.
+
+   Copyright 2010 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 <stddef.h>
+
+#include "runtime.h"
+#include "go-panic.h"
+#include "go-defer.h"
+
+/* This is called when a call to recover is deferred.  That is,
+   something like
+     defer recover()
+
+   We need to handle this specially.  In 6g/8g, the recover function
+   looks up the stack frame.  In particular, that means that a
+   deferred recover will not recover a panic thrown in the same
+   function that defers the recover.  It will only recover a panic
+   thrown in a function that defers the deferred call to recover.
+
+   In other words:
+
+   func f1() {
+	defer recover()	// does not stop panic
+	panic(0)
+   }
+
+   func f2() {
+	defer func() {
+		defer recover()	// stops panic(0)
+	}()
+	panic(0)
+   }
+
+   func f3() {
+	defer func() {
+		defer recover()	// does not stop panic
+		panic(0)
+	}()
+	panic(1)
+   }
+
+   func f4() {
+	defer func() {
+		defer func() {
+			defer recover()	// stops panic(0)
+		}()
+		panic(0)
+	}()
+	panic(1)
+   }
+
+   The interesting case here is f3.  As can be seen from f2, the
+   deferred recover could pick up panic(1).  However, this does not
+   happen because it is blocked by the panic(0).
+
+   When a function calls recover, then when we invoke it we pass a
+   hidden parameter indicating whether it should recover something.
+   This parameter is set based on whether the function is being
+   invoked directly from defer.  The parameter winds up determining
+   whether __go_recover or __go_deferred_recover is called at all.
+
+   In the case of a deferred recover, the hidden parameter which
+   controls the call is actually the one set up for the function which
+   runs the defer recover() statement.  That is the right thing in all
+   the cases above except for f3.  In f3 the function is permitted to
+   call recover, but the deferred recover call is not.  We address
+   that here by checking for that specific case before calling
+   recover.  If this function was deferred when there is already a
+   panic on the panic stack, then we can only recover that panic, not
+   any other.
+
+   Note that we can get away with using a special function here
+   because you are not permitted to take the address of a predeclared
+   function like recover.  */
+
+struct __go_empty_interface
+__go_deferred_recover ()
+{
+  G *g;
+
+  g = runtime_g ();
+  if (g->defer == NULL || g->defer->__panic != g->panic)
+    {
+      struct __go_empty_interface ret;
+
+      ret.__type_descriptor = NULL;
+      ret.__object = NULL;
+      return ret;
+    }
+  return __go_recover ();
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-eface-compare.c b/third_party/gofrontend/libgo/runtime/go-eface-compare.c
new file mode 100644
index 0000000..3555a65
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-eface-compare.c
@@ -0,0 +1,35 @@
+/* go-eface-compare.c -- compare two empty values.
+
+   Copyright 2010 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 "runtime.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* Compare two interface values.  Return 0 for equal, not zero for not
+   equal (return value is like strcmp).  */
+
+intgo
+__go_empty_interface_compare (struct __go_empty_interface left,
+			      struct __go_empty_interface right)
+{
+  const struct __go_type_descriptor *left_descriptor;
+
+  left_descriptor = left.__type_descriptor;
+
+  if (left_descriptor == NULL && right.__type_descriptor == NULL)
+    return 0;
+  if (left_descriptor == NULL || right.__type_descriptor == NULL)
+    return 1;
+  if (!__go_type_descriptors_equal (left_descriptor,
+				    right.__type_descriptor))
+    return 1;
+  if (__go_is_pointer_type (left_descriptor))
+    return left.__object == right.__object ? 0 : 1;
+  if (!left_descriptor->__equalfn (left.__object, right.__object,
+				   left_descriptor->__size))
+    return 1;
+  return 0;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-eface-val-compare.c b/third_party/gofrontend/libgo/runtime/go-eface-val-compare.c
new file mode 100644
index 0000000..743f126
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-eface-val-compare.c
@@ -0,0 +1,33 @@
+/* go-eface-val-compare.c -- compare an empty interface with a value.
+
+   Copyright 2010 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 "runtime.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* Compare an empty interface with a value.  Return 0 for equal, not
+   zero for not equal (return value is like strcmp).  */
+
+intgo
+__go_empty_interface_value_compare (
+    struct __go_empty_interface left,
+    const struct __go_type_descriptor *right_descriptor,
+    const void *val)
+{
+  const struct __go_type_descriptor *left_descriptor;
+
+  left_descriptor = left.__type_descriptor;
+  if (left_descriptor == NULL)
+    return 1;
+  if (!__go_type_descriptors_equal (left_descriptor, right_descriptor))
+    return 1;
+  if (__go_is_pointer_type (left_descriptor))
+    return left.__object == val ? 0 : 1;
+  if (!left_descriptor->__equalfn (left.__object, val,
+				   left_descriptor->__size))
+    return 1;
+  return 0;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-ffi.c b/third_party/gofrontend/libgo/runtime/go-ffi.c
new file mode 100644
index 0000000..21879b9
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-ffi.c
@@ -0,0 +1,338 @@
+/* go-ffi.c -- convert Go type description to libffi.
+
+   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.  */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "go-assert.h"
+#include "go-type.h"
+
+#ifdef USE_LIBFFI
+
+#include "ffi.h"
+
+/* The functions in this file are only called from reflect_call and
+   reflect.ffi.  As these functions call libffi functions, which will
+   be compiled without -fsplit-stack, they will always run with a
+   large stack.  */
+
+static ffi_type *go_array_to_ffi (const struct __go_array_type *)
+  __attribute__ ((no_split_stack));
+static ffi_type *go_slice_to_ffi (const struct __go_slice_type *)
+  __attribute__ ((no_split_stack));
+static ffi_type *go_struct_to_ffi (const struct __go_struct_type *)
+  __attribute__ ((no_split_stack));
+static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack));
+static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack));
+static ffi_type *go_complex_to_ffi (ffi_type *)
+  __attribute__ ((no_split_stack, unused));
+static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *)
+  __attribute__ ((no_split_stack));
+static ffi_type *go_func_return_ffi (const struct __go_func_type *)
+  __attribute__ ((no_split_stack));
+
+/* Return an ffi_type for a Go array type.  The libffi library does
+   not have any builtin support for passing arrays as values.  We work
+   around this by pretending that the array is a struct.  */
+
+static ffi_type *
+go_array_to_ffi (const struct __go_array_type *descriptor)
+{
+  ffi_type *ret;
+  uintptr_t len;
+  ffi_type *element;
+  uintptr_t i;
+
+  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
+  ret->type = FFI_TYPE_STRUCT;
+  len = descriptor->__len;
+  ret->elements = (ffi_type **) __go_alloc ((len + 1) * sizeof (ffi_type *));
+  element = go_type_to_ffi (descriptor->__element_type);
+  for (i = 0; i < len; ++i)
+    ret->elements[i] = element;
+  ret->elements[len] = NULL;
+  return ret;
+}
+
+/* Return an ffi_type for a Go slice type.  This describes the
+   __go_open_array type defines in array.h.  */
+
+static ffi_type *
+go_slice_to_ffi (
+    const struct __go_slice_type *descriptor __attribute__ ((unused)))
+{
+  ffi_type *ret;
+  ffi_type *ffi_intgo;
+
+  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
+  ret->type = FFI_TYPE_STRUCT;
+  ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *));
+  ret->elements[0] = &ffi_type_pointer;
+  ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
+  ret->elements[1] = ffi_intgo;
+  ret->elements[2] = ffi_intgo;
+  ret->elements[3] = NULL;
+  return ret;
+}
+
+/* Return an ffi_type for a Go struct type.  */
+
+static ffi_type *
+go_struct_to_ffi (const struct __go_struct_type *descriptor)
+{
+  ffi_type *ret;
+  int field_count;
+  const struct __go_struct_field *fields;
+  int i;
+
+  field_count = descriptor->__fields.__count;
+  if (field_count == 0) {
+    return &ffi_type_void;
+  }
+  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
+  ret->type = FFI_TYPE_STRUCT;
+  fields = (const struct __go_struct_field *) descriptor->__fields.__values;
+  ret->elements = (ffi_type **) __go_alloc ((field_count + 1)
+					    * sizeof (ffi_type *));
+  for (i = 0; i < field_count; ++i)
+    ret->elements[i] = go_type_to_ffi (fields[i].__type);
+  ret->elements[field_count] = NULL;
+  return ret;
+}
+
+/* Return an ffi_type for a Go string type.  This describes the String
+   struct.  */
+
+static ffi_type *
+go_string_to_ffi (void)
+{
+  ffi_type *ret;
+  ffi_type *ffi_intgo;
+
+  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
+  ret->type = FFI_TYPE_STRUCT;
+  ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
+  ret->elements[0] = &ffi_type_pointer;
+  ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
+  ret->elements[1] = ffi_intgo;
+  ret->elements[2] = NULL;
+  return ret;
+}
+
+/* Return an ffi_type for a Go interface type.  This describes the
+   __go_interface and __go_empty_interface structs.  */
+
+static ffi_type *
+go_interface_to_ffi (void)
+{
+  ffi_type *ret;
+
+  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
+  ret->type = FFI_TYPE_STRUCT;
+  ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
+  ret->elements[0] = &ffi_type_pointer;
+  ret->elements[1] = &ffi_type_pointer;
+  ret->elements[2] = NULL;
+  return ret;
+}
+
+/* Return an ffi_type for a Go complex type.  */
+
+static ffi_type *
+go_complex_to_ffi (ffi_type *float_type)
+{
+  ffi_type *ret;
+
+  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
+  ret->type = FFI_TYPE_STRUCT;
+  ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
+  ret->elements[0] = float_type;
+  ret->elements[1] = float_type;
+  ret->elements[2] = NULL;
+  return ret;
+}
+
+/* Return an ffi_type for a type described by a
+   __go_type_descriptor.  */
+
+static ffi_type *
+go_type_to_ffi (const struct __go_type_descriptor *descriptor)
+{
+  switch (descriptor->__code & GO_CODE_MASK)
+    {
+    case GO_BOOL:
+      if (sizeof (_Bool) == 1)
+	return &ffi_type_uint8;
+      else if (sizeof (_Bool) == sizeof (int))
+	return &ffi_type_uint;
+      abort ();
+    case GO_FLOAT32:
+      if (sizeof (float) == 4)
+	return &ffi_type_float;
+      abort ();
+    case GO_FLOAT64:
+      if (sizeof (double) == 8)
+	return &ffi_type_double;
+      abort ();
+    case GO_COMPLEX64:
+#ifdef __alpha__
+      runtime_throw("the libffi library does not support Complex64 type with "
+		    "reflect.Call or runtime.SetFinalizer");
+#else
+      if (sizeof (float) == 4)
+	return go_complex_to_ffi (&ffi_type_float);
+      abort ();
+#endif
+    case GO_COMPLEX128:
+#ifdef __alpha__
+      runtime_throw("the libffi library does not support Complex128 type with "
+		    "reflect.Call or runtime.SetFinalizer");
+#else
+      if (sizeof (double) == 8)
+	return go_complex_to_ffi (&ffi_type_double);
+      abort ();
+#endif
+    case GO_INT16:
+      return &ffi_type_sint16;
+    case GO_INT32:
+      return &ffi_type_sint32;
+    case GO_INT64:
+      return &ffi_type_sint64;
+    case GO_INT8:
+      return &ffi_type_sint8;
+    case GO_INT:
+      return sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
+    case GO_UINT16:
+      return &ffi_type_uint16;
+    case GO_UINT32:
+      return &ffi_type_uint32;
+    case GO_UINT64:
+      return &ffi_type_uint64;
+    case GO_UINT8:
+      return &ffi_type_uint8;
+    case GO_UINT:
+      return sizeof (uintgo) == 4 ? &ffi_type_uint32 : &ffi_type_uint64;
+    case GO_UINTPTR:
+      if (sizeof (void *) == 2)
+	return &ffi_type_uint16;
+      else if (sizeof (void *) == 4)
+	return &ffi_type_uint32;
+      else if (sizeof (void *) == 8)
+	return &ffi_type_uint64;
+      abort ();
+    case GO_ARRAY:
+      return go_array_to_ffi ((const struct __go_array_type *) descriptor);
+    case GO_SLICE:
+      return go_slice_to_ffi ((const struct __go_slice_type *) descriptor);
+    case GO_STRUCT:
+      return go_struct_to_ffi ((const struct __go_struct_type *) descriptor);
+    case GO_STRING:
+      return go_string_to_ffi ();
+    case GO_INTERFACE:
+      return go_interface_to_ffi ();
+    case GO_CHAN:
+    case GO_FUNC:
+    case GO_MAP:
+    case GO_PTR:
+    case GO_UNSAFE_POINTER:
+      /* These types are always pointers, and for FFI purposes nothing
+	 else matters.  */
+      return &ffi_type_pointer;
+    default:
+      abort ();
+    }
+}
+
+/* Return the return type for a function, given the number of out
+   parameters and their types.  */
+
+static ffi_type *
+go_func_return_ffi (const struct __go_func_type *func)
+{
+  int count;
+  const struct __go_type_descriptor **types;
+  ffi_type *ret;
+  int i;
+
+  count = func->__out.__count;
+  if (count == 0)
+    return &ffi_type_void;
+
+  types = (const struct __go_type_descriptor **) func->__out.__values;
+
+  if (count == 1)
+    {
+
+#if defined (__i386__) && !defined (__x86_64__)
+      /* FFI does not support complex types.  On 32-bit x86, a
+	 complex64 will be returned in %eax/%edx.  We normally tell
+	 FFI that a complex64 is a struct of two floats.  On 32-bit
+	 x86 a struct of two floats is returned via a hidden first
+	 pointer parameter.  Fortunately we can make everything work
+	 by pretending that complex64 is int64.  */
+      if ((types[0]->__code & GO_CODE_MASK) == GO_COMPLEX64)
+	return &ffi_type_sint64;
+#endif
+
+      return go_type_to_ffi (types[0]);
+    }
+
+  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
+  ret->type = FFI_TYPE_STRUCT;
+  ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *));
+  for (i = 0; i < count; ++i)
+    ret->elements[i] = go_type_to_ffi (types[i]);
+  ret->elements[count] = NULL;
+  return ret;
+}
+
+/* Build an ffi_cif structure for a function described by a
+   __go_func_type structure.  */
+
+void
+__go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
+		_Bool is_method, ffi_cif *cif)
+{
+  int num_params;
+  const struct __go_type_descriptor **in_types;
+  size_t num_args;
+  ffi_type **args;
+  int off;
+  int i;
+  ffi_type *rettype;
+  ffi_status status;
+
+  num_params = func->__in.__count;
+  in_types = ((const struct __go_type_descriptor **)
+	      func->__in.__values);
+
+  num_args = num_params + (is_interface ? 1 : 0);
+  args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *));
+  i = 0;
+  off = 0;
+  if (is_interface)
+    {
+      args[0] = &ffi_type_pointer;
+      off = 1;
+    }
+  else if (is_method)
+    {
+      args[0] = &ffi_type_pointer;
+      i = 1;
+    }
+  for (; i < num_params; ++i)
+    args[i + off] = go_type_to_ffi (in_types[i]);
+
+  rettype = go_func_return_ffi (func);
+
+  status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args);
+  __go_assert (status == FFI_OK);
+}
+
+#endif /* defined(USE_LIBFFI) */
diff --git a/third_party/gofrontend/libgo/runtime/go-ffi.h b/third_party/gofrontend/libgo/runtime/go-ffi.h
new file mode 100644
index 0000000..afae4b6
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-ffi.h
@@ -0,0 +1,16 @@
+/* go-ffi.c -- convert Go type description to libffi.
+
+   Copyright 2014 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 "config.h"
+#include "go-type.h"
+
+#ifdef USE_LIBFFI
+
+#include "ffi.h"
+
+void __go_func_to_cif (const struct __go_func_type *, _Bool, _Bool, ffi_cif *);
+
+#endif
diff --git a/third_party/gofrontend/libgo/runtime/go-fieldtrack.c b/third_party/gofrontend/libgo/runtime/go-fieldtrack.c
new file mode 100644
index 0000000..a7e2c13
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-fieldtrack.c
@@ -0,0 +1,101 @@
+/* go-fieldtrack.c -- structure field data analysis.
+
+   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 "runtime.h"
+#include "go-type.h"
+#include "map.h"
+
+/* The compiler will track fields that have the tag go:"track".  Any
+   function that refers to such a field will call this function with a
+   string
+       fieldtrack "package.type.field"
+
+   This function does not actually do anything.  Instead, we gather
+   the field tracking information by looking for strings of that form
+   in the read-only data section.  This is, of course, a horrible
+   hack, but it's good enough for now.  We can improve it, e.g., by a
+   linker plugin, if this turns out to be useful.  */
+
+void
+__go_fieldtrack (byte *p __attribute__ ((unused)))
+{
+}
+
+/* A runtime function to add all the tracked fields to a
+   map[string]bool.  */
+
+extern const char _etext[] __attribute__ ((weak));
+extern const char __etext[] __attribute__ ((weak));
+extern const char __data_start[] __attribute__ ((weak));
+extern const char _edata[] __attribute__ ((weak));
+extern const char __edata[] __attribute__ ((weak));
+extern const char __bss_start[] __attribute__ ((weak));
+
+void runtime_Fieldtrack (struct __go_map *) __asm__ (GOSYM_PREFIX "runtime.Fieldtrack");
+
+void
+runtime_Fieldtrack (struct __go_map *m)
+{
+  const char *p;
+  const char *pend;
+  const char *prefix;
+  size_t prefix_len;
+
+  p = __data_start;
+  if (p == NULL)
+    p = __etext;
+  if (p == NULL)
+    p = _etext;
+  if (p == NULL)
+    return;
+
+  pend = __edata;
+  if (pend == NULL)
+    pend = _edata;
+  if (pend == NULL)
+    pend = __bss_start;
+  if (pend == NULL)
+    return;
+
+  prefix = "fieldtrack ";
+  prefix_len = __builtin_strlen (prefix);
+
+  while (p < pend)
+    {
+      const char *q1;
+      const char *q2;
+
+      q1 = __builtin_memchr (p + prefix_len, '"', pend - (p + prefix_len));
+      if (q1 == NULL)
+	break;
+
+      if (__builtin_memcmp (q1 - prefix_len, prefix, prefix_len) != 0)
+	{
+	  p = q1 + 1;
+	  continue;
+	}
+
+      q1++;
+      q2 = __builtin_memchr (q1, '"', pend - q1);
+      if (q2 == NULL)
+	break;
+
+      if (__builtin_memchr (q1, '\0', q2 - q1) == NULL)
+	{
+	  String s;
+	  void *v;
+	  _Bool *pb;
+
+	  s.str = (const byte *) q1;
+	  s.len = q2 - q1;
+	  v = __go_map_index (m, &s, 1);
+	  pb = (_Bool *) v;
+	  *pb = 1;
+	}
+
+      p = q2;
+    }
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-iface.goc b/third_party/gofrontend/libgo/runtime/go-iface.goc
new file mode 100644
index 0000000..0d5cb5e
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-iface.goc
@@ -0,0 +1,130 @@
+// Copyright 2010 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 runtime
+#include "runtime.h"
+#include "go-type.h"
+#include "interface.h"
+
+typedef struct __go_type_descriptor descriptor;
+typedef const struct __go_type_descriptor const_descriptor;
+typedef struct __go_interface interface;
+typedef struct __go_empty_interface empty_interface;
+
+// Compare two type descriptors.
+func ifacetypeeq(a *descriptor, b *descriptor) (eq bool) {
+	eq = __go_type_descriptors_equal(a, b);
+}
+
+// Return the descriptor for an empty interface type.n
+func efacetype(e empty_interface) (d *const_descriptor) {
+	return e.__type_descriptor;
+}
+
+// Return the descriptor for a non-empty interface type.
+func ifacetype(i interface) (d *const_descriptor) {
+	if (i.__methods == nil) {
+		return nil;
+	}
+	d = i.__methods[0];
+}
+
+// Convert an empty interface to an empty interface.
+func ifaceE2E2(e empty_interface) (ret empty_interface, ok bool) {
+	ret = e;
+	ok = ret.__type_descriptor != nil;
+}
+
+// Convert a non-empty interface to an empty interface.
+func ifaceI2E2(i interface) (ret empty_interface, ok bool) {
+	if (i.__methods == nil) {
+		ret.__type_descriptor = nil;
+		ret.__object = nil;
+		ok = 0;
+	} else {
+		ret.__type_descriptor = i.__methods[0];
+		ret.__object = i.__object;
+		ok = 1;
+	}
+}
+
+// Convert an empty interface to a non-empty interface.
+func ifaceE2I2(inter *descriptor, e empty_interface) (ret interface, ok bool) {
+	if (e.__type_descriptor == nil) {
+		ret.__methods = nil;
+		ret.__object = nil;
+		ok = 0;
+	} else {
+		ret.__methods = __go_convert_interface_2(inter,
+							 e.__type_descriptor,
+							 1);
+		ret.__object = e.__object;
+		ok = ret.__methods != nil;
+	}
+}
+
+// Convert a non-empty interface to a non-empty interface.
+func ifaceI2I2(inter *descriptor, i interface) (ret interface, ok bool) {
+	if (i.__methods == nil) {
+		ret.__methods = nil;
+		ret.__object = nil;
+		ok = 0;
+	} else {
+		ret.__methods = __go_convert_interface_2(inter,
+							 i.__methods[0], 1);
+		ret.__object = i.__object;
+		ok = ret.__methods != nil;
+	}
+}
+
+// Convert an empty interface to a pointer type.
+func ifaceE2T2P(inter *descriptor, e empty_interface) (ret *void, ok bool) {
+	if (!__go_type_descriptors_equal(inter, e.__type_descriptor)) {
+		ret = nil;
+		ok = 0;
+	} else {
+		ret = e.__object;
+		ok = 1;
+	}
+}
+
+// Convert a non-empty interface to a pointer type.
+func ifaceI2T2P(inter *descriptor, i interface) (ret *void, ok bool) {
+	if (i.__methods == nil
+	    || !__go_type_descriptors_equal(inter, i.__methods[0])) {
+		ret = nil;
+		ok = 0;
+	} else {
+		ret = i.__object;
+		ok = 1;
+	}
+}
+
+// Convert an empty interface to a non-pointer type.
+func ifaceE2T2(inter *descriptor, e empty_interface, ret *void) (ok bool) {
+	if (!__go_type_descriptors_equal(inter, e.__type_descriptor)) {
+		__builtin_memset(ret, 0, inter->__size);
+		ok = 0;
+	} else {
+		__builtin_memcpy(ret, e.__object, inter->__size);
+		ok = 1;
+	}
+}
+
+// Convert a non-empty interface to a non-pointer type.
+func ifaceI2T2(inter *descriptor, i interface, ret *void) (ok bool) {
+	if (i.__methods == nil
+	    || !__go_type_descriptors_equal(inter, i.__methods[0])) {
+		__builtin_memset(ret, 0, inter->__size);
+		ok = 0;
+	} else {
+		__builtin_memcpy(ret, i.__object, inter->__size);
+		ok = 1;
+	}
+}
+
+// Return whether we can convert an interface to a type.
+func ifaceI2Tp(to *descriptor, from *descriptor) (ok bool) {
+	ok = __go_can_convert_to_interface(to, from);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-int-array-to-string.c b/third_party/gofrontend/libgo/runtime/go-int-array-to-string.c
new file mode 100644
index 0000000..f372131
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-int-array-to-string.c
@@ -0,0 +1,89 @@
+/* go-int-array-to-string.c -- convert an array of ints to a string in Go.
+
+   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.  */
+
+#include "go-assert.h"
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+String
+__go_int_array_to_string (const void* p, intgo len)
+{
+  const int32 *ints;
+  intgo slen;
+  intgo i;
+  unsigned char *retdata;
+  String ret;
+  unsigned char *s;
+
+  ints = (const int32 *) p;
+
+  slen = 0;
+  for (i = 0; i < len; ++i)
+    {
+      int32 v;
+
+      v = ints[i];
+
+      if (v < 0 || v > 0x10ffff)
+	v = 0xfffd;
+      else if (0xd800 <= v && v <= 0xdfff)
+	v = 0xfffd;
+
+      if (v <= 0x7f)
+	slen += 1;
+      else if (v <= 0x7ff)
+	slen += 2;
+      else if (v <= 0xffff)
+	slen += 3;
+      else
+	slen += 4;
+    }
+
+  retdata = runtime_mallocgc ((uintptr) slen, 0, FlagNoScan);
+  ret.str = retdata;
+  ret.len = slen;
+
+  s = retdata;
+  for (i = 0; i < len; ++i)
+    {
+      int32 v;
+
+      v = ints[i];
+
+      /* If V is out of range for UTF-8, substitute the replacement
+	 character.  */
+      if (v < 0 || v > 0x10ffff)
+	v = 0xfffd;
+      else if (0xd800 <= v && v <= 0xdfff)
+	v = 0xfffd;
+
+      if (v <= 0x7f)
+	*s++ = v;
+      else if (v <= 0x7ff)
+	{
+	  *s++ = 0xc0 | ((v >> 6) & 0x1f);
+	  *s++ = 0x80 | (v & 0x3f);
+	}
+      else if (v <= 0xffff)
+	{
+	  *s++ = 0xe0 | ((v >> 12) & 0xf);
+	  *s++ = 0x80 | ((v >> 6) & 0x3f);
+	  *s++ = 0x80 | (v & 0x3f);
+	}
+      else
+	{
+	  *s++ = 0xf0 | ((v >> 18) & 0x7);
+	  *s++ = 0x80 | ((v >> 12) & 0x3f);
+	  *s++ = 0x80 | ((v >> 6) & 0x3f);
+	  *s++ = 0x80 | (v & 0x3f);
+	}
+    }
+
+  __go_assert (s - retdata == slen);
+
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-int-to-string.c b/third_party/gofrontend/libgo/runtime/go-int-to-string.c
new file mode 100644
index 0000000..d90b1dd
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-int-to-string.c
@@ -0,0 +1,69 @@
+/* go-int-to-string.c -- convert an integer to a string in Go.
+
+   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.  */
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+String
+__go_int_to_string (intgo v)
+{
+  char buf[4];
+  int len;
+  unsigned char *retdata;
+  String ret;
+
+  /* A negative value is not valid UTF-8; turn it into the replacement
+     character.  */
+  if (v < 0)
+    v = 0xfffd;
+
+  if (v <= 0x7f)
+    {
+      buf[0] = v;
+      len = 1;
+    }
+  else if (v <= 0x7ff)
+    {
+      buf[0] = 0xc0 + (v >> 6);
+      buf[1] = 0x80 + (v & 0x3f);
+      len = 2;
+    }
+  else
+    {
+      /* If the value is out of range for UTF-8, turn it into the
+	 "replacement character".  */
+      if (v > 0x10ffff)
+	v = 0xfffd;
+      /* If the value is a surrogate pair, which is invalid in UTF-8,
+	 turn it into the replacement character.  */
+      if (v >= 0xd800 && v < 0xe000)
+	v = 0xfffd;
+
+      if (v <= 0xffff)
+	{
+	  buf[0] = 0xe0 + (v >> 12);
+	  buf[1] = 0x80 + ((v >> 6) & 0x3f);
+	  buf[2] = 0x80 + (v & 0x3f);
+	  len = 3;
+	}
+      else
+	{
+	  buf[0] = 0xf0 + (v >> 18);
+	  buf[1] = 0x80 + ((v >> 12) & 0x3f);
+	  buf[2] = 0x80 + ((v >> 6) & 0x3f);
+	  buf[3] = 0x80 + (v & 0x3f);
+	  len = 4;
+	}
+    }
+
+  retdata = runtime_mallocgc (len, 0, FlagNoScan);
+  __builtin_memcpy (retdata, buf, len);
+  ret.str = retdata;
+  ret.len = len;
+
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-interface-compare.c b/third_party/gofrontend/libgo/runtime/go-interface-compare.c
new file mode 100644
index 0000000..6374bd2
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-interface-compare.c
@@ -0,0 +1,35 @@
+/* go-interface-compare.c -- compare two interface values.
+
+   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.  */
+
+#include <stddef.h>
+
+#include "runtime.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* Compare two interface values.  Return 0 for equal, not zero for not
+   equal (return value is like strcmp).  */
+
+int
+__go_interface_compare (struct __go_interface left,
+			struct __go_interface right)
+{
+  const struct __go_type_descriptor *left_descriptor;
+
+  if (left.__methods == NULL && right.__methods == NULL)
+    return 0;
+  if (left.__methods == NULL || right.__methods == NULL)
+    return 1;
+  left_descriptor = left.__methods[0];
+  if (!__go_type_descriptors_equal (left_descriptor, right.__methods[0]))
+    return 1;
+  if (__go_is_pointer_type (left_descriptor))
+    return left.__object == right.__object ? 0 : 1;
+  if (!left_descriptor->__equalfn (left.__object, right.__object,
+				   left_descriptor->__size))
+    return 1;
+  return 0;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-interface-eface-compare.c b/third_party/gofrontend/libgo/runtime/go-interface-eface-compare.c
new file mode 100644
index 0000000..a38917f
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-interface-eface-compare.c
@@ -0,0 +1,34 @@
+/* go-interface-eface-compare.c -- compare non-empty and empty interface.
+
+   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.  */
+
+#include "runtime.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* Compare a non-empty interface value with an empty interface value.
+   Return 0 for equal, not zero for not equal (return value is like
+   strcmp).  */
+
+intgo
+__go_interface_empty_compare (struct __go_interface left,
+			      struct __go_empty_interface right)
+{
+  const struct __go_type_descriptor *left_descriptor;
+
+  if (left.__methods == NULL && right.__type_descriptor == NULL)
+    return 0;
+  if (left.__methods == NULL || right.__type_descriptor == NULL)
+    return 1;
+  left_descriptor = left.__methods[0];
+  if (!__go_type_descriptors_equal (left_descriptor, right.__type_descriptor))
+    return 1;
+  if (__go_is_pointer_type (left_descriptor))
+    return left.__object == right.__object ? 0 : 1;
+  if (!left_descriptor->__equalfn (left.__object, right.__object,
+				   left_descriptor->__size))
+    return 1;
+  return 0;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-interface-val-compare.c b/third_party/gofrontend/libgo/runtime/go-interface-val-compare.c
new file mode 100644
index 0000000..e2dae6a
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-interface-val-compare.c
@@ -0,0 +1,33 @@
+/* go-interface-val-compare.c -- compare an interface to a value.
+
+   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.  */
+
+#include "runtime.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* Compare two interface values.  Return 0 for equal, not zero for not
+   equal (return value is like strcmp).  */
+
+intgo
+__go_interface_value_compare (
+    struct __go_interface left,
+    const struct __go_type_descriptor *right_descriptor,
+    const void *val)
+{
+  const struct __go_type_descriptor *left_descriptor;
+
+  if (left.__methods == NULL)
+    return 1;
+  left_descriptor = left.__methods[0];
+  if (!__go_type_descriptors_equal (left_descriptor, right_descriptor))
+    return 1;
+  if (__go_is_pointer_type (left_descriptor))
+    return left.__object == val ? 0 : 1;
+  if (!left_descriptor->__equalfn (left.__object, val,
+				   left_descriptor->__size))
+    return 1;
+  return 0;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-main.c b/third_party/gofrontend/libgo/runtime/go-main.c
new file mode 100644
index 0000000..77233d3
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-main.c
@@ -0,0 +1,45 @@
+/* go-main.c -- the main function for a Go program.
+
+   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.  */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifdef HAVE_FPU_CONTROL_H
+#include <fpu_control.h>
+#endif
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "array.h"
+#include "arch.h"
+#include "malloc.h"
+
+#undef int
+#undef char
+#undef unsigned
+
+/* The main function for a Go program.  This records the command line
+   parameters, calls the real main function, and returns a zero status
+   if the real main function returns.  */
+
+extern char **environ;
+
+/* The main function.  */
+
+int
+main (int argc, char **argv)
+{
+  runtime_check ();
+  runtime_args (argc, (byte **) argv);
+  runtime_osinit ();
+  runtime_schedinit ();
+  __go_go (runtime_main, NULL);
+  runtime_mstart (runtime_m ());
+  abort ();
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-make-slice.c b/third_party/gofrontend/libgo/runtime/go-make-slice.c
new file mode 100644
index 0000000..855bb17
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-make-slice.c
@@ -0,0 +1,99 @@
+/* go-make-slice.c -- make a slice.
+
+   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.  */
+
+#include <stdint.h>
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "go-assert.h"
+#include "go-panic.h"
+#include "go-type.h"
+#include "array.h"
+#include "arch.h"
+#include "malloc.h"
+
+/* Dummy word to use as base pointer for make([]T, 0).
+   Since you cannot take the address of such a slice,
+   you can't tell that they all have the same base pointer.  */
+uintptr runtime_zerobase;
+
+struct __go_open_array
+__go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
+		  uintptr_t cap)
+{
+  const struct __go_slice_type* std;
+  intgo ilen;
+  intgo icap;
+  uintptr_t size;
+  struct __go_open_array ret;
+
+  __go_assert (td->__code == GO_SLICE);
+  std = (const struct __go_slice_type *) td;
+
+  ilen = (intgo) len;
+  if (ilen < 0
+      || (uintptr_t) ilen != len
+      || (std->__element_type->__size > 0
+	  && len > MaxMem / std->__element_type->__size))
+    runtime_panicstring ("makeslice: len out of range");
+
+  icap = (intgo) cap;
+  if (cap < len
+      || (uintptr_t) icap != cap
+      || (std->__element_type->__size > 0
+	  && cap > MaxMem / std->__element_type->__size))
+    runtime_panicstring ("makeslice: cap out of range");
+
+  ret.__count = ilen;
+  ret.__capacity = icap;
+
+  size = cap * std->__element_type->__size;
+
+  if (size == 0)
+    ret.__values = &runtime_zerobase;
+  else if ((std->__element_type->__code & GO_NO_POINTERS) != 0)
+    ret.__values =
+      runtime_mallocgc (size,
+			(uintptr) std->__element_type | TypeInfo_Array,
+			FlagNoScan);
+  else
+    ret.__values =
+      runtime_mallocgc (size,
+			(uintptr) std->__element_type | TypeInfo_Array,
+			0);
+
+  return ret;
+}
+
+struct __go_open_array
+__go_make_slice1 (const struct __go_type_descriptor *td, uintptr_t len)
+{
+  return __go_make_slice2 (td, len, len);
+}
+
+struct __go_open_array
+__go_make_slice2_big (const struct __go_type_descriptor *td, uint64_t len,
+		      uint64_t cap)
+{
+  uintptr_t slen;
+  uintptr_t scap;
+
+  slen = (uintptr_t) len;
+  if ((uint64_t) slen != len)
+    runtime_panicstring ("makeslice: len out of range");
+
+  scap = (uintptr_t) cap;
+  if ((uint64_t) scap != cap)
+    runtime_panicstring ("makeslice: cap out of range");
+
+  return __go_make_slice2 (td, slen, scap);
+}
+
+struct __go_open_array
+__go_make_slice1_big (const struct __go_type_descriptor *td, uint64_t len)
+{
+  return __go_make_slice2_big (td, len, len);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-map-delete.c b/third_party/gofrontend/libgo/runtime/go-map-delete.c
new file mode 100644
index 0000000..de8b046
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-map-delete.c
@@ -0,0 +1,58 @@
+/* go-map-delete.c -- delete an entry from a map.
+
+   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.  */
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "runtime.h"
+#include "malloc.h"
+#include "go-alloc.h"
+#include "go-assert.h"
+#include "map.h"
+
+/* Delete the entry matching KEY from MAP.  */
+
+void
+__go_map_delete (struct __go_map *map, const void *key)
+{
+  const struct __go_map_descriptor *descriptor;
+  const struct __go_type_descriptor *key_descriptor;
+  uintptr_t key_offset;
+  _Bool (*equalfn) (const void*, const void*, uintptr_t);
+  size_t key_hash;
+  size_t key_size;
+  size_t bucket_index;
+  void **pentry;
+
+  if (map == NULL)
+    return;
+
+  descriptor = map->__descriptor;
+
+  key_descriptor = descriptor->__map_descriptor->__key_type;
+  key_offset = descriptor->__key_offset;
+  key_size = key_descriptor->__size;
+  __go_assert (key_size != 0 && key_size != -1UL);
+  equalfn = key_descriptor->__equalfn;
+
+  key_hash = key_descriptor->__hashfn (key, key_size);
+  bucket_index = key_hash % map->__bucket_count;
+
+  pentry = map->__buckets + bucket_index;
+  while (*pentry != NULL)
+    {
+      char *entry = (char *) *pentry;
+      if (equalfn (key, entry + key_offset, key_size))
+	{
+	  *pentry = *(void **) entry;
+	  if (descriptor->__entry_size >= TinySize)
+	    __go_free (entry);
+	  map->__element_count -= 1;
+	  break;
+	}
+      pentry = (void **) entry;
+    }
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-map-index.c b/third_party/gofrontend/libgo/runtime/go-map-index.c
new file mode 100644
index 0000000..499641c
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-map-index.c
@@ -0,0 +1,135 @@
+/* go-map-index.c -- find or insert an entry in a map.
+
+   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.  */
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "go-assert.h"
+#include "map.h"
+
+/* Rehash MAP to a larger size.  */
+
+static void
+__go_map_rehash (struct __go_map *map)
+{
+  const struct __go_map_descriptor *descriptor;
+  const struct __go_type_descriptor *key_descriptor;
+  uintptr_t key_offset;
+  size_t key_size;
+  uintptr_t (*hashfn) (const void *, uintptr_t);
+  uintptr_t old_bucket_count;
+  void **old_buckets;
+  uintptr_t new_bucket_count;
+  void **new_buckets;
+  uintptr_t i;
+
+  descriptor = map->__descriptor;
+
+  key_descriptor = descriptor->__map_descriptor->__key_type;
+  key_offset = descriptor->__key_offset;
+  key_size = key_descriptor->__size;
+  hashfn = key_descriptor->__hashfn;
+
+  old_bucket_count = map->__bucket_count;
+  old_buckets = map->__buckets;
+
+  new_bucket_count = __go_map_next_prime (old_bucket_count * 2);
+  new_buckets = (void **) __go_alloc (new_bucket_count * sizeof (void *));
+  __builtin_memset (new_buckets, 0, new_bucket_count * sizeof (void *));
+
+  for (i = 0; i < old_bucket_count; ++i)
+    {
+      char* entry;
+      char* next;
+
+      for (entry = old_buckets[i]; entry != NULL; entry = next)
+	{
+	  size_t key_hash;
+	  size_t new_bucket_index;
+
+	  /* We could speed up rehashing at the cost of memory space
+	     by caching the hash code.  */
+	  key_hash = hashfn (entry + key_offset, key_size);
+	  new_bucket_index = key_hash % new_bucket_count;
+
+	  next = *(char **) entry;
+	  *(char **) entry = new_buckets[new_bucket_index];
+	  new_buckets[new_bucket_index] = entry;
+	}
+    }
+
+  __go_free (old_buckets);
+
+  map->__bucket_count = new_bucket_count;
+  map->__buckets = new_buckets;
+}
+
+/* Find KEY in MAP, return a pointer to the value.  If KEY is not
+   present, then if INSERT is false, return NULL, and if INSERT is
+   true, insert a new value and zero-initialize it before returning a
+   pointer to it.  */
+
+void *
+__go_map_index (struct __go_map *map, const void *key, _Bool insert)
+{
+  const struct __go_map_descriptor *descriptor;
+  const struct __go_type_descriptor *key_descriptor;
+  uintptr_t key_offset;
+  _Bool (*equalfn) (const void*, const void*, uintptr_t);
+  size_t key_hash;
+  size_t key_size;
+  size_t bucket_index;
+  char *entry;
+
+  if (map == NULL)
+    {
+      if (insert)
+	runtime_panicstring ("assignment to entry in nil map");
+      return NULL;
+    }
+
+  descriptor = map->__descriptor;
+
+  key_descriptor = descriptor->__map_descriptor->__key_type;
+  key_offset = descriptor->__key_offset;
+  key_size = key_descriptor->__size;
+  __go_assert (key_size != -1UL);
+  equalfn = key_descriptor->__equalfn;
+
+  key_hash = key_descriptor->__hashfn (key, key_size);
+  bucket_index = key_hash % map->__bucket_count;
+
+  entry = (char *) map->__buckets[bucket_index];
+  while (entry != NULL)
+    {
+      if (equalfn (key, entry + key_offset, key_size))
+	return entry + descriptor->__val_offset;
+      entry = *(char **) entry;
+    }
+
+  if (!insert)
+    return NULL;
+
+  if (map->__element_count >= map->__bucket_count)
+    {
+      __go_map_rehash (map);
+      bucket_index = key_hash % map->__bucket_count;
+    }
+
+  entry = (char *) __go_alloc (descriptor->__entry_size);
+  __builtin_memset (entry, 0, descriptor->__entry_size);
+
+  __builtin_memcpy (entry + key_offset, key, key_size);
+
+  *(char **) entry = map->__buckets[bucket_index];
+  map->__buckets[bucket_index] = entry;
+
+  map->__element_count += 1;
+
+  return entry + descriptor->__val_offset;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-map-len.c b/third_party/gofrontend/libgo/runtime/go-map-len.c
new file mode 100644
index 0000000..7da10c2
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-map-len.c
@@ -0,0 +1,25 @@
+/* go-map-len.c -- return the length of a map.
+
+   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.  */
+
+#include <stddef.h>
+
+#include "runtime.h"
+#include "go-assert.h"
+#include "map.h"
+
+/* Return the length of a map.  This could be done inline, of course,
+   but I'm doing it as a function for now to make it easy to change
+   the map structure.  */
+
+intgo
+__go_map_len (struct __go_map *map)
+{
+  if (map == NULL)
+    return 0;
+  __go_assert (map->__element_count
+	       == (uintptr_t) (intgo) map->__element_count);
+  return map->__element_count;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-map-range.c b/third_party/gofrontend/libgo/runtime/go-map-range.c
new file mode 100644
index 0000000..5dbb92c
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-map-range.c
@@ -0,0 +1,103 @@
+/* go-map-range.c -- implement a range clause over a map.
+
+   Copyright 2009, 2010 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 "runtime.h"
+#include "go-assert.h"
+#include "map.h"
+
+/* Initialize a range over a map.  */
+
+void
+__go_mapiterinit (const struct __go_map *h, struct __go_hash_iter *it)
+{
+  it->entry = NULL;
+  if (h != NULL)
+    {
+      it->map = h;
+      it->next_entry = NULL;
+      it->bucket = 0;
+      --it->bucket;
+      __go_mapiternext(it);
+    }
+}
+
+/* Move to the next iteration, updating *HITER.  */
+
+void
+__go_mapiternext (struct __go_hash_iter *it)
+{
+  const void *entry;
+
+  entry = it->next_entry;
+  if (entry == NULL)
+    {
+      const struct __go_map *map;
+      uintptr_t bucket;
+
+      map = it->map;
+      bucket = it->bucket;
+      while (1)
+	{
+	  ++bucket;
+	  if (bucket >= map->__bucket_count)
+	    {
+	      /* Map iteration is complete.  */
+	      it->entry = NULL;
+	      return;
+	    }
+	  entry = map->__buckets[bucket];
+	  if (entry != NULL)
+	    break;
+	}
+      it->bucket = bucket;
+    }
+  it->entry = entry;
+  it->next_entry = *(const void * const *) entry;
+}
+
+/* Get the key of the current iteration.  */
+
+void
+__go_mapiter1 (struct __go_hash_iter *it, unsigned char *key)
+{
+  const struct __go_map *map;
+  const struct __go_map_descriptor *descriptor;
+  const struct __go_type_descriptor *key_descriptor;
+  const char *p;
+
+  map = it->map;
+  descriptor = map->__descriptor;
+  key_descriptor = descriptor->__map_descriptor->__key_type;
+  p = it->entry;
+  __go_assert (p != NULL);
+  __builtin_memcpy (key, p + descriptor->__key_offset, key_descriptor->__size);
+}
+
+/* Get the key and value of the current iteration.  */
+
+void
+__go_mapiter2 (struct __go_hash_iter *it, unsigned char *key,
+	       unsigned char *val)
+{
+  const struct __go_map *map;
+  const struct __go_map_descriptor *descriptor;
+  const struct __go_map_type *map_descriptor;
+  const struct __go_type_descriptor *key_descriptor;
+  const struct __go_type_descriptor *val_descriptor;
+  const char *p;
+
+  map = it->map;
+  descriptor = map->__descriptor;
+  map_descriptor = descriptor->__map_descriptor;
+  key_descriptor = map_descriptor->__key_type;
+  val_descriptor = map_descriptor->__val_type;
+  p = it->entry;
+  __go_assert (p != NULL);
+  __builtin_memcpy (key, p + descriptor->__key_offset,
+		    key_descriptor->__size);
+  __builtin_memcpy (val, p + descriptor->__val_offset,
+		    val_descriptor->__size);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-matherr.c b/third_party/gofrontend/libgo/runtime/go-matherr.c
new file mode 100644
index 0000000..d620ba0
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-matherr.c
@@ -0,0 +1,88 @@
+/* go-matherr.c -- a Go version of the matherr function.
+
+   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.  */
+
+/* The gccgo version of the math library calls libc functions.  On
+   some systems, such as Solaris, those functions will call matherr on
+   exceptional conditions.  This is a version of matherr appropriate
+   for Go, one which returns the values that the Go math library
+   expects.  This is fine for pure Go programs.  For mixed Go and C
+   programs this will be problematic if the C programs themselves use
+   matherr.  Normally the C version of matherr will override this, and
+   the Go code will just have to cope.  If this turns out to be too
+   problematic we can change to run pure Go code in the math library
+   on systems that use matherr.  */
+
+#include <math.h>
+#include <stdint.h>
+
+#include "config.h"
+
+#if defined(HAVE_MATHERR) && defined(HAVE_STRUCT_EXCEPTION)
+
+#define PI 3.14159265358979323846264338327950288419716939937510582097494459
+
+int
+matherr (struct exception* e)
+{
+  const char *n;
+
+  if (e->type != DOMAIN)
+    return 0;
+
+  n = e->name;
+  if (__builtin_strcmp (n, "acos") == 0
+      || __builtin_strcmp (n, "asin") == 0)
+    e->retval = __builtin_nan ("");
+  else if (__builtin_strcmp (n, "atan2") == 0)
+    {
+      if (e->arg1 == 0 && e->arg2 == 0)
+	{
+	  double nz;
+
+	  nz = -0.0;
+	  if (__builtin_memcmp (&e->arg2, &nz, sizeof (double)) != 0)
+	    e->retval = e->arg1;
+	  else
+	    e->retval = copysign (PI, e->arg1);
+	}
+      else
+	return 0;
+    }
+  else if (__builtin_strcmp (n, "log") == 0
+	   || __builtin_strcmp (n, "log10") == 0)
+    e->retval = __builtin_nan ("");
+  else if (__builtin_strcmp (n, "pow") == 0)
+    {
+      if (e->arg1 < 0)
+	e->retval = __builtin_nan ("");
+      else if (e->arg1 == 0 && e->arg2 == 0)
+	e->retval = 1.0;
+      else if (e->arg1 == 0 && e->arg2 < 0)
+	{
+	  double i;
+
+	  if (modf (e->arg2, &i) == 0 && ((int64_t) i & 1) == 1)
+	    e->retval = copysign (__builtin_inf (), e->arg1);
+	  else
+	    e->retval = __builtin_inf ();
+	}
+      else
+	return 0;
+    }
+  else if (__builtin_strcmp (n, "sqrt") == 0)
+    {
+      if (e->arg1 < 0)
+	e->retval = __builtin_nan ("");
+      else
+	return 0;
+    }
+  else
+    return 0;
+
+  return 1;
+}
+
+#endif
diff --git a/third_party/gofrontend/libgo/runtime/go-memcmp.c b/third_party/gofrontend/libgo/runtime/go-memcmp.c
new file mode 100644
index 0000000..78a356b
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-memcmp.c
@@ -0,0 +1,13 @@
+/* go-memcmp.c -- the go memory comparison function.
+
+   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 "runtime.h"
+
+intgo
+__go_memcmp (const void *p1, const void *p2, uintptr len)
+{
+  return __builtin_memcmp (p1, p2, len);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-nanotime.c b/third_party/gofrontend/libgo/runtime/go-nanotime.c
new file mode 100644
index 0000000..7e5e3e0
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-nanotime.c
@@ -0,0 +1,21 @@
+// 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.
+
+// Return current time in nanoseconds.
+
+#include <sys/time.h>
+
+#include "runtime.h"
+
+int64 runtime_nanotime (void)
+  __attribute__ ((no_split_stack));
+
+int64
+runtime_nanotime (void)
+{
+  struct timeval tv;
+
+  gettimeofday (&tv, NULL);
+  return (int64) tv.tv_sec * 1000000000 + (int64) tv.tv_usec * 1000;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-new-map.c b/third_party/gofrontend/libgo/runtime/go-new-map.c
new file mode 100644
index 0000000..c289bc0
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-new-map.c
@@ -0,0 +1,142 @@
+/* go-new-map.c -- allocate a new map.
+
+   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.  */
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "map.h"
+
+/* List of prime numbers, copied from libstdc++/src/hashtable.c.  */
+
+static const unsigned long prime_list[] = /* 256 + 1 or 256 + 48 + 1 */
+{
+  2ul, 3ul, 5ul, 7ul, 11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul,
+  37ul, 41ul, 43ul, 47ul, 53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul,
+  83ul, 89ul, 97ul, 103ul, 109ul, 113ul, 127ul, 137ul, 139ul, 149ul,
+  157ul, 167ul, 179ul, 193ul, 199ul, 211ul, 227ul, 241ul, 257ul,
+  277ul, 293ul, 313ul, 337ul, 359ul, 383ul, 409ul, 439ul, 467ul,
+  503ul, 541ul, 577ul, 619ul, 661ul, 709ul, 761ul, 823ul, 887ul,
+  953ul, 1031ul, 1109ul, 1193ul, 1289ul, 1381ul, 1493ul, 1613ul,
+  1741ul, 1879ul, 2029ul, 2179ul, 2357ul, 2549ul, 2753ul, 2971ul,
+  3209ul, 3469ul, 3739ul, 4027ul, 4349ul, 4703ul, 5087ul, 5503ul,
+  5953ul, 6427ul, 6949ul, 7517ul, 8123ul, 8783ul, 9497ul, 10273ul,
+  11113ul, 12011ul, 12983ul, 14033ul, 15173ul, 16411ul, 17749ul,
+  19183ul, 20753ul, 22447ul, 24281ul, 26267ul, 28411ul, 30727ul,
+  33223ul, 35933ul, 38873ul, 42043ul, 45481ul, 49201ul, 53201ul,
+  57557ul, 62233ul, 67307ul, 72817ul, 78779ul, 85229ul, 92203ul,
+  99733ul, 107897ul, 116731ul, 126271ul, 136607ul, 147793ul,
+  159871ul, 172933ul, 187091ul, 202409ul, 218971ul, 236897ul,
+  256279ul, 277261ul, 299951ul, 324503ul, 351061ul, 379787ul,
+  410857ul, 444487ul, 480881ul, 520241ul, 562841ul, 608903ul,
+  658753ul, 712697ul, 771049ul, 834181ul, 902483ul, 976369ul,
+  1056323ul, 1142821ul, 1236397ul, 1337629ul, 1447153ul, 1565659ul,
+  1693859ul, 1832561ul, 1982627ul, 2144977ul, 2320627ul, 2510653ul,
+  2716249ul, 2938679ul, 3179303ul, 3439651ul, 3721303ul, 4026031ul,
+  4355707ul, 4712381ul, 5098259ul, 5515729ul, 5967347ul, 6456007ul,
+  6984629ul, 7556579ul, 8175383ul, 8844859ul, 9569143ul, 10352717ul,
+  11200489ul, 12117689ul, 13109983ul, 14183539ul, 15345007ul,
+  16601593ul, 17961079ul, 19431899ul, 21023161ul, 22744717ul,
+  24607243ul, 26622317ul, 28802401ul, 31160981ul, 33712729ul,
+  36473443ul, 39460231ul, 42691603ul, 46187573ul, 49969847ul,
+  54061849ul, 58488943ul, 63278561ul, 68460391ul, 74066549ul,
+  80131819ul, 86693767ul, 93793069ul, 101473717ul, 109783337ul,
+  118773397ul, 128499677ul, 139022417ul, 150406843ul, 162723577ul,
+  176048909ul, 190465427ul, 206062531ul, 222936881ul, 241193053ul,
+  260944219ul, 282312799ul, 305431229ul, 330442829ul, 357502601ul,
+  386778277ul, 418451333ul, 452718089ul, 489790921ul, 529899637ul,
+  573292817ul, 620239453ul, 671030513ul, 725980837ul, 785430967ul,
+  849749479ul, 919334987ul, 994618837ul, 1076067617ul, 1164186217ul,
+  1259520799ul, 1362662261ul, 1474249943ul, 1594975441ul, 1725587117ul,
+  1866894511ul, 2019773507ul, 2185171673ul, 2364114217ul, 2557710269ul,
+  2767159799ul, 2993761039ul, 3238918481ul, 3504151727ul, 3791104843ul,
+  4101556399ul, 4294967291ul,
+#if __SIZEOF_LONG__ >= 8
+  6442450933ul, 8589934583ul, 12884901857ul, 17179869143ul,
+  25769803693ul, 34359738337ul, 51539607367ul, 68719476731ul,
+  103079215087ul, 137438953447ul, 206158430123ul, 274877906899ul,
+  412316860387ul, 549755813881ul, 824633720731ul, 1099511627689ul,
+  1649267441579ul, 2199023255531ul, 3298534883309ul, 4398046511093ul,
+  6597069766607ul, 8796093022151ul, 13194139533241ul, 17592186044399ul,
+  26388279066581ul, 35184372088777ul, 52776558133177ul, 70368744177643ul,
+  105553116266399ul, 140737488355213ul, 211106232532861ul, 281474976710597ul,
+  562949953421231ul, 1125899906842597ul, 2251799813685119ul,
+  4503599627370449ul, 9007199254740881ul, 18014398509481951ul,
+  36028797018963913ul, 72057594037927931ul, 144115188075855859ul,
+  288230376151711717ul, 576460752303423433ul,
+  1152921504606846883ul, 2305843009213693951ul,
+  4611686018427387847ul, 9223372036854775783ul,
+  18446744073709551557ul
+#endif
+};
+
+/* Return the next number from PRIME_LIST >= N.  */
+
+uintptr_t
+__go_map_next_prime (uintptr_t n)
+{
+  size_t low;
+  size_t high;
+
+  low = 0;
+  high = sizeof prime_list / sizeof prime_list[0];
+  while (low < high)
+    {
+      size_t mid;
+
+      mid = (low + high) / 2;
+
+      /* Here LOW <= MID < HIGH.  */
+
+      if (prime_list[mid] < n)
+	low = mid + 1;
+      else if (prime_list[mid] > n)
+	high = mid;
+      else
+	return n;
+    }
+  if (low >= sizeof prime_list / sizeof prime_list[0])
+    return n;
+  return prime_list[low];
+}
+
+/* Allocate a new map.  */
+
+struct __go_map *
+__go_new_map (const struct __go_map_descriptor *descriptor, uintptr_t entries)
+{
+  int32 ientries;
+  struct __go_map *ret;
+
+  /* The master library limits map entries to int32, so we do too.  */
+  ientries = (int32) entries;
+  if (ientries < 0 || (uintptr_t) ientries != entries)
+    runtime_panicstring ("map size out of range");
+
+  if (entries == 0)
+    entries = 5;
+  else
+    entries = __go_map_next_prime (entries);
+  ret = (struct __go_map *) __go_alloc (sizeof (struct __go_map));
+  ret->__descriptor = descriptor;
+  ret->__element_count = 0;
+  ret->__bucket_count = entries;
+  ret->__buckets = (void **) __go_alloc (entries * sizeof (void *));
+  __builtin_memset (ret->__buckets, 0, entries * sizeof (void *));
+  return ret;
+}
+
+/* Allocate a new map when the argument to make is a large type.  */
+
+struct __go_map *
+__go_new_map_big (const struct __go_map_descriptor *descriptor,
+		  uint64_t entries)
+{
+  uintptr_t sentries;
+
+  sentries = (uintptr_t) entries;
+  if ((uint64_t) sentries != entries)
+    runtime_panicstring ("map size out of range");
+  return __go_new_map (descriptor, sentries);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-new.c b/third_party/gofrontend/libgo/runtime/go-new.c
new file mode 100644
index 0000000..dad6efb
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-new.c
@@ -0,0 +1,26 @@
+/* go-new.c -- the generic go new() function.
+
+   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.  */
+
+#include "go-alloc.h"
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+void *
+__go_new (const struct __go_type_descriptor *td, uintptr_t size)
+{
+  return runtime_mallocgc (size,
+			   (uintptr) td | TypeInfo_SingleObject,
+			   0);
+}
+
+void *
+__go_new_nopointers (const struct __go_type_descriptor *td,  uintptr_t size)
+{
+  return runtime_mallocgc (size,
+			   (uintptr) td | TypeInfo_SingleObject,
+			   FlagNoScan);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-nosys.c b/third_party/gofrontend/libgo/runtime/go-nosys.c
new file mode 100644
index 0000000..0a94de0
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-nosys.c
@@ -0,0 +1,450 @@
+/* go-nosys.c -- functions missing from system.
+
+   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.  */
+
+/* This file exists to provide definitions for functions that are
+   missing from libc, according to the configure script.  This permits
+   the Go syscall package to not worry about whether the functions
+   exist or not.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifndef HAVE_OFF64_T
+typedef signed int off64_t __attribute__ ((mode (DI)));
+#endif
+
+#ifndef HAVE_LOFF_T
+typedef off64_t loff_t;
+#endif
+
+#ifndef HAVE_ACCEPT4
+struct sockaddr;
+int
+accept4 (int sockfd __attribute__ ((unused)),
+	 struct sockaddr *addr __attribute__ ((unused)),
+	 socklen_t *addrlen __attribute__ ((unused)),
+	 int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_DUP3
+int
+dup3 (int oldfd __attribute__ ((unused)),
+      int newfd __attribute__ ((unused)),
+      int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_EPOLL_CREATE1
+int
+epoll_create1 (int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_FACCESSAT
+int
+faccessat (int fd __attribute__ ((unused)),
+	   const char *pathname __attribute__ ((unused)),
+	   int mode __attribute__ ((unused)),
+	   int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_FALLOCATE
+int
+fallocate (int fd __attribute__ ((unused)),
+	   int mode __attribute__ ((unused)),
+	   off_t offset __attribute__ ((unused)),
+	   off_t len __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_FCHMODAT
+int
+fchmodat (int dirfd __attribute__ ((unused)),
+	  const char *pathname __attribute__ ((unused)),
+	  mode_t mode __attribute__ ((unused)),
+	  int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_FCHOWNAT
+int
+fchownat (int dirfd __attribute__ ((unused)),
+	  const char *pathname __attribute__ ((unused)),
+	  uid_t owner __attribute__ ((unused)),
+	  gid_t group __attribute__ ((unused)),
+	  int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_FUTIMESAT
+int
+futimesat (int dirfd __attribute__ ((unused)),
+	   const char *pathname __attribute__ ((unused)),
+	   const struct timeval times[2] __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_GETXATTR
+ssize_t
+getxattr (const char *path __attribute__ ((unused)),
+	  const char *name __attribute__ ((unused)),
+	  void *value __attribute__ ((unused)),
+	  size_t size __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_INOTIFY_ADD_WATCH
+int
+inotify_add_watch (int fd __attribute__ ((unused)),
+		   const char* pathname __attribute__ ((unused)),
+		   uint32_t mask __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_INOTIFY_INIT
+int
+inotify_init (void)
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_INOTIFY_INIT1
+int
+inotify_init1 (int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_INOTIFY_RM_WATCH
+int
+inotify_rm_watch (int fd __attribute__ ((unused)),
+		  uint32_t wd __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_LISTXATTR
+ssize_t
+listxattr (const char *path __attribute__ ((unused)),
+	   char *list __attribute__ ((unused)),
+	   size_t size __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_MKDIRAT
+int
+mkdirat (int dirfd __attribute__ ((unused)),
+	 const char *pathname __attribute__ ((unused)),
+	 mode_t mode __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_MKNODAT
+int
+mknodat (int dirfd __attribute__ ((unused)),
+	 const char *pathname __attribute__ ((unused)),
+	 mode_t mode __attribute__ ((unused)),
+	 dev_t dev __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_OPENAT
+int
+openat (int dirfd __attribute__ ((unused)),
+	const char *pathname __attribute__ ((unused)),
+	int oflag __attribute__ ((unused)),
+	...)
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_PIPE2
+int
+pipe2 (int pipefd[2] __attribute__ ((unused)),
+       int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_REMOVEXATTR
+int
+removexattr (const char *path __attribute__ ((unused)),
+	     const char *name __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_RENAMEAT
+int
+renameat (int olddirfd __attribute__ ((unused)),
+	  const char *oldpath __attribute__ ((unused)),
+	  int newdirfd __attribute__ ((unused)),
+	  const char *newpath __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_SETXATTR
+int
+setxattr (const char *path __attribute__ ((unused)),
+	  const char *name __attribute__ ((unused)),
+	  const void *value __attribute__ ((unused)),
+	  size_t size __attribute__ ((unused)),
+	  int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_SPLICE
+int
+splice (int fd __attribute__ ((unused)),
+	loff_t *off_in __attribute__ ((unused)),
+	int fd_out __attribute__ ((unused)),
+	loff_t *off_out __attribute__ ((unused)),
+	size_t len __attribute__ ((unused)),
+	unsigned int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_SYNC_FILE_RANGE
+int
+sync_file_range (int fd __attribute__ ((unused)),
+		 off64_t offset __attribute__ ((unused)),
+		 off64_t nbytes __attribute__ ((unused)),
+		 unsigned int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_TEE
+int
+tee (int fd_in __attribute__ ((unused)),
+     int fd_out __attribute__ ((unused)),
+     size_t len __attribute__ ((unused)),
+     unsigned int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_UNLINKAT
+int
+unlinkat (int dirfd __attribute__ ((unused)),
+	  const char *pathname __attribute__ ((unused)),
+	  int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_UNSHARE
+int
+unshare (int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+#ifndef HAVE_UTIMENSAT
+struct timespec;
+int
+utimensat(int dirfd __attribute__ ((unused)),
+	  const char *pathname __attribute__ ((unused)),
+	  const struct timespec times[2] __attribute__ ((unused)),
+	  int flags __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  return -1;
+}
+#endif
+
+/* Long double math functions.  These are needed on old i386 systems
+   that don't have them in libm.  The compiler translates calls to
+   these functions on float64 to call an 80-bit floating point
+   function instead, because when optimizing that function can be
+   executed as an x87 instructure.  However, when not optimizing, this
+   translates into a call to the math function.  So on systems that
+   don't provide these functions, we provide a version that just calls
+   the float64 version.  */
+
+#ifndef HAVE_COSL
+long double
+cosl (long double a)
+{
+  return (long double) cos ((double) a);
+}
+#endif
+
+#ifndef HAVE_EXPL
+long double
+expl (long double a)
+{
+  return (long double) exp ((double) a);
+}
+#endif
+
+#ifndef HAVE_LOGL
+long double
+logl (long double a)
+{
+  return (long double) log ((double) a);
+}
+#endif
+
+#ifndef HAVE_SINL
+long double
+sinl (long double a)
+{
+  return (long double) sin ((double) a);
+}
+#endif
+
+#ifndef HAVE_TANL
+long double
+tanl (long double a)
+{
+  return (long double) tan ((double) a);
+}
+#endif
+
+#ifndef HAVE_ACOSL
+long double
+acosl (long double a)
+{
+  return (long double) acos ((double) a);
+}
+#endif
+
+#ifndef HAVE_ASINL
+long double
+asinl (long double a)
+{
+  return (long double) asin ((double) a);
+}
+#endif
+
+#ifndef HAVE_ATANL
+long double
+atanl (long double a)
+{
+  return (long double) atan ((double) a);
+}
+#endif
+
+#ifndef HAVE_ATAN2L
+long double
+atan2l (long double a, long double b)
+{
+  return (long double) atan2 ((double) a, (double) b);
+}
+#endif
+
+#ifndef HAVE_EXPM1L
+long double
+expm1l (long double a)
+{
+  return (long double) expm1 ((double) a);
+}
+#endif
+
+#ifndef HAVE_LDEXPL
+long double
+ldexpl (long double a, int exp)
+{
+  return (long double) ldexp ((double) a, exp);
+}
+#endif
+
+#ifndef HAVE_LOG10L
+long double
+log10l (long double a)
+{
+  return (long double) log10 ((double) a);
+}
+#endif
+
+#ifndef HAVE_LOG1PL
+long double
+log1pl (long double a)
+{
+  return (long double) log1p ((double) a);
+}
+#endif
diff --git a/third_party/gofrontend/libgo/runtime/go-now.c b/third_party/gofrontend/libgo/runtime/go-now.c
new file mode 100644
index 0000000..ea8d070
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-now.c
@@ -0,0 +1,23 @@
+// 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.
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/time.h>
+
+#include "runtime.h"
+
+// Return current time.  This is the implementation of time.now().
+
+struct time_now_ret
+now()
+{
+  struct timeval tv;
+  struct time_now_ret ret;
+
+  gettimeofday (&tv, NULL);
+  ret.sec = tv.tv_sec;
+  ret.nsec = tv.tv_usec * 1000;
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-panic.c b/third_party/gofrontend/libgo/runtime/go-panic.c
new file mode 100644
index 0000000..77975c6
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-panic.c
@@ -0,0 +1,112 @@
+/* go-panic.c -- support for the go panic function.
+
+   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.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+#include "go-alloc.h"
+#include "go-defer.h"
+#include "go-panic.h"
+#include "interface.h"
+
+/* Print the panic stack.  This is used when there is no recover.  */
+
+static void
+__printpanics (struct __go_panic_stack *p)
+{
+  if (p->__next != NULL)
+    {
+      __printpanics (p->__next);
+      runtime_printf ("\t");
+    }
+  runtime_printf ("panic: ");
+  runtime_printany (p->__arg);
+  if (p->__was_recovered)
+    runtime_printf (" [recovered]");
+  runtime_printf ("\n");
+}
+
+/* This implements __go_panic which is used for the panic
+   function.  */
+
+void
+__go_panic (struct __go_empty_interface arg)
+{
+  G *g;
+  struct __go_panic_stack *n;
+
+  g = runtime_g ();
+
+  n = (struct __go_panic_stack *) __go_alloc (sizeof (struct __go_panic_stack));
+  n->__arg = arg;
+  n->__next = g->panic;
+  g->panic = n;
+
+  /* Run all the defer functions.  */
+
+  while (1)
+    {
+      struct __go_defer_stack *d;
+      void (*pfn) (void *);
+
+      d = g->defer;
+      if (d == NULL)
+	break;
+
+      pfn = d->__pfn;
+      d->__pfn = NULL;
+
+      if (pfn != NULL)
+	{
+	  (*pfn) (d->__arg);
+
+	  if (n->__was_recovered)
+	    {
+	      /* Some defer function called recover.  That means that
+		 we should stop running this panic.  */
+
+	      g->panic = n->__next;
+	      __go_free (n);
+
+	      /* Now unwind the stack by throwing an exception.  The
+		 compiler has arranged to create exception handlers in
+		 each function which uses a defer statement.  These
+		 exception handlers will check whether the entry on
+		 the top of the defer stack is from the current
+		 function.  If it is, we have unwound the stack far
+		 enough.  */
+	      __go_unwind_stack ();
+
+	      /* __go_unwind_stack should not return.  */
+	      abort ();
+	    }
+
+	  /* Because we executed that defer function by a panic, and
+	     it did not call recover, we know that we are not
+	     returning from the calling function--we are panicing
+	     through it.  */
+	  *d->__frame = 0;
+	}
+
+      g->defer = d->__next;
+
+      /* This may be called by a cgo callback routine to defer the
+	 call to syscall.CgocallBackDone, in which case we will not
+	 have a memory context.  Don't try to free anything in that
+	 case--the GC will release it later.  */
+      if (runtime_m () != NULL)
+	runtime_freedefer (d);
+    }
+
+  /* The panic was not recovered.  */
+
+  runtime_startpanic ();
+  __printpanics (g->panic);
+  runtime_dopanic (0);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-panic.h b/third_party/gofrontend/libgo/runtime/go-panic.h
new file mode 100644
index 0000000..d29fe88
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-panic.h
@@ -0,0 +1,52 @@
+/* go-panic.h -- declare the go panic functions.
+
+   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.  */
+
+#ifndef LIBGO_GO_PANIC_H
+#define LIBGO_GO_PANIC_H
+
+#include "interface.h"
+
+struct String;
+struct __go_type_descriptor;
+struct __go_defer_stack;
+
+/* The stack of panic calls.  */
+
+struct __go_panic_stack
+{
+  /* The next entry in the stack.  */
+  struct __go_panic_stack *__next;
+
+  /* The value associated with this panic.  */
+  struct __go_empty_interface __arg;
+
+  /* Whether this panic has been recovered.  */
+  _Bool __was_recovered;
+
+  /* Whether this panic was pushed on the stack because of an
+     exception thrown in some other language.  */
+  _Bool __is_foreign;
+};
+
+extern void __go_panic (struct __go_empty_interface)
+  __attribute__ ((noreturn));
+
+extern void __go_print_string (struct String);
+
+extern struct __go_empty_interface __go_recover (void);
+
+extern _Bool __go_can_recover (void *);
+
+extern void __go_makefunc_can_recover (void *retaddr);
+
+struct Location;
+extern void __go_makefunc_ffi_can_recover (struct Location *, int);
+
+extern void __go_makefunc_returning (void);
+
+extern void __go_unwind_stack (void);
+
+#endif /* !defined(LIBGO_GO_PANIC_H) */
diff --git a/third_party/gofrontend/libgo/runtime/go-print.c b/third_party/gofrontend/libgo/runtime/go-print.c
new file mode 100644
index 0000000..4c520de
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-print.c
@@ -0,0 +1,36 @@
+/* go-print.c -- support for the go print statement.
+
+   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.  */
+
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "runtime.h"
+#include "array.h"
+#include "go-panic.h"
+#include "interface.h"
+
+/* This implements the various little functions which are called by
+   the predeclared functions print/println/panic/panicln.  */
+
+void
+__go_print_empty_interface (struct __go_empty_interface e)
+{
+  runtime_printf ("(%p,%p)", e.__type_descriptor, e.__object);
+}
+
+void
+__go_print_interface (struct __go_interface i)
+{
+  runtime_printf ("(%p,%p)", i.__methods, i.__object);
+}
+
+void
+__go_print_slice (struct __go_open_array val)
+{
+  runtime_printf ("[%d/%d]", val.__count, val.__capacity);
+  runtime_printpointer (val.__values);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-recover.c b/third_party/gofrontend/libgo/runtime/go-recover.c
new file mode 100644
index 0000000..fc66f61
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-recover.c
@@ -0,0 +1,275 @@
+/* go-recover.c -- support for the go recover function.
+
+   Copyright 2010 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 "runtime.h"
+#include "interface.h"
+#include "go-panic.h"
+#include "go-defer.h"
+
+/* If the top of the defer stack can be recovered, then return it.
+   Otherwise return NULL.  */
+
+static struct __go_defer_stack *
+current_defer ()
+{
+  G *g;
+  struct __go_defer_stack *d;
+
+  g = runtime_g ();
+
+  d = g->defer;
+  if (d == NULL)
+    return NULL;
+
+  /* The panic which would be recovered is the one on the top of the
+     panic stack.  We do not want to recover it if that panic was on
+     the top of the panic stack when this function was deferred.  */
+  if (d->__panic == g->panic)
+    return NULL;
+
+  /* The deferred thunk will call _go_set_defer_retaddr.  If this has
+     not happened, then we have not been called via defer, and we can
+     not recover.  */
+  if (d->__retaddr == NULL)
+    return NULL;
+
+  return d;
+}
+
+/* This is called by a thunk to see if the real function should be
+   permitted to recover a panic value.  Recovering a value is
+   permitted if the thunk was called directly by defer.  RETADDR is
+   the return address of the function which is calling
+   __go_can_recover--this is, the thunk.  */
+
+_Bool
+__go_can_recover (void *retaddr)
+{
+  struct __go_defer_stack *d;
+  const char* ret;
+  const char* dret;
+  Location locs[16];
+  const byte *name;
+  intgo len;
+  int n;
+  int i;
+  _Bool found_ffi_callback;
+
+  d = current_defer ();
+  if (d == NULL)
+    return 0;
+
+  ret = (const char *) __builtin_extract_return_addr (retaddr);
+
+  dret = (const char *) d->__retaddr;
+  if (ret <= dret && ret + 16 >= dret)
+    return 1;
+
+  /* On some systems, in some cases, the return address does not work
+     reliably.  See http://gcc.gnu.org/PR60406.  If we are permitted
+     to call recover, the call stack will look like this:
+       __go_panic, __go_undefer, etc.
+       thunk to call deferred function (calls __go_set_defer_retaddr)
+       function that calls __go_can_recover (passing return address)
+       __go_can_recover
+     Calling runtime_callers will skip the thunks.  So if our caller's
+     caller starts with __go, then we are permitted to call
+     recover.  */
+
+  if (runtime_callers (1, &locs[0], 2, false) < 2)
+    return 0;
+
+  name = locs[1].function.str;
+  len = locs[1].function.len;
+
+  /* Although locs[1].function is a Go string, we know it is
+     NUL-terminated.  */
+  if (len > 4
+      && __builtin_strchr ((const char *) name, '.') == NULL
+      && __builtin_strncmp ((const char *) name, "__go_", 4) == 0)
+    return 1;
+
+  /* If we are called from __go_makefunc_can_recover, then we need to
+     look one level higher.  */
+  if (locs[0].function.len > 0
+      && __builtin_strcmp ((const char *) locs[0].function.str,
+			   "__go_makefunc_can_recover") == 0)
+    {
+      if (runtime_callers (3, &locs[0], 1, false) < 1)
+	return 0;
+      name = locs[0].function.str;
+      len = locs[0].function.len;
+      if (len > 4
+	  && __builtin_strchr ((const char *) name, '.') == NULL
+	  && __builtin_strncmp ((const char *) name, "__go_", 4) == 0)
+	return 1;
+    }
+
+  /* If the function calling recover was created by reflect.MakeFunc,
+     then __go_makefunc_can_recover or __go_makefunc_ffi_can_recover
+     will have set the __makefunc_can_recover field.  */
+  if (!d->__makefunc_can_recover)
+    return 0;
+
+  /* We look up the stack, ignoring libffi functions and functions in
+     the reflect package, until we find reflect.makeFuncStub or
+     reflect.ffi_callback called by FFI functions.  Then we check the
+     caller of that function.  */
+
+  n = runtime_callers (2, &locs[0], sizeof locs / sizeof locs[0], false);
+  found_ffi_callback = 0;
+  for (i = 0; i < n; i++)
+    {
+      const byte *name;
+
+      if (locs[i].function.len == 0)
+	{
+	  /* No function name means this caller isn't Go code.  Assume
+	     that this is libffi.  */
+	  continue;
+	}
+
+      /* Ignore functions in libffi.  */
+      name = locs[i].function.str;
+      if (__builtin_strncmp ((const char *) name, "ffi_", 4) == 0)
+	continue;
+
+      if (found_ffi_callback)
+	break;
+
+      if (__builtin_strcmp ((const char *) name, "reflect.ffi_callback") == 0)
+	{
+	  found_ffi_callback = 1;
+	  continue;
+	}
+
+      if (__builtin_strcmp ((const char *) name, "reflect.makeFuncStub") == 0)
+	{
+	  i++;
+	  break;
+	}
+
+      /* Ignore other functions in the reflect package.  */
+      if (__builtin_strncmp ((const char *) name, "reflect.", 8) == 0)
+	continue;
+
+      /* We should now be looking at the real caller.  */
+      break;
+    }
+
+  if (i < n && locs[i].function.len > 0)
+    {
+      name = locs[i].function.str;
+      if (__builtin_strncmp ((const char *) name, "__go_", 4) == 0)
+	return 1;
+    }
+
+  return 0;
+}
+
+/* This function is called when code is about to enter a function
+   created by reflect.MakeFunc.  It is called by the function stub
+   used by MakeFunc.  If the stub is permitted to call recover, then a
+   real MakeFunc function is permitted to call recover.  */
+
+void
+__go_makefunc_can_recover (void *retaddr)
+{
+  struct __go_defer_stack *d;
+
+  d = current_defer ();
+  if (d == NULL)
+    return;
+
+  /* If we are already in a call stack of MakeFunc functions, there is
+     nothing we can usefully check here.  */
+  if (d->__makefunc_can_recover)
+    return;
+
+  if (__go_can_recover (retaddr))
+    d->__makefunc_can_recover = 1;
+}
+
+/* This function is called when code is about to enter a function
+   created by the libffi version of reflect.MakeFunc.  This function
+   is passed the names of the callers of the libffi code that called
+   the stub.  It uses to decide whether it is permitted to call
+   recover, and sets d->__makefunc_can_recover so that __go_recover
+   can make the same decision.  */
+
+void
+__go_makefunc_ffi_can_recover (struct Location *loc, int n)
+{
+  struct __go_defer_stack *d;
+  const byte *name;
+  intgo len;
+
+  d = current_defer ();
+  if (d == NULL)
+    return;
+
+  /* If we are already in a call stack of MakeFunc functions, there is
+     nothing we can usefully check here.  */
+  if (d->__makefunc_can_recover)
+    return;
+
+  /* LOC points to the caller of our caller.  That will be a thunk.
+     If its caller was a runtime function, then it was called directly
+     by defer.  */
+
+  if (n < 2)
+    return;
+
+  name = (loc + 1)->function.str;
+  len = (loc + 1)->function.len;
+  if (len > 4
+      && __builtin_strchr ((const char *) name, '.') == NULL
+      && __builtin_strncmp ((const char *) name, "__go_", 4) == 0)
+    d->__makefunc_can_recover = 1;
+}
+
+/* This function is called when code is about to exit a function
+   created by reflect.MakeFunc.  It is called by the function stub
+   used by MakeFunc.  It clears the __makefunc_can_recover field.
+   It's OK to always clear this field, because __go_can_recover will
+   only be called by a stub created for a function that calls recover.
+   That stub will not call a function created by reflect.MakeFunc, so
+   by the time we get here any caller higher up on the call stack no
+   longer needs the information.  */
+
+void
+__go_makefunc_returning (void)
+{
+  struct __go_defer_stack *d;
+
+  d = runtime_g ()->defer;
+  if (d != NULL)
+    d->__makefunc_can_recover = 0;
+}
+
+/* This is only called when it is valid for the caller to recover the
+   value on top of the panic stack, if there is one.  */
+
+struct __go_empty_interface
+__go_recover ()
+{
+  G *g;
+  struct __go_panic_stack *p;
+
+  g = runtime_g ();
+
+  if (g->panic == NULL || g->panic->__was_recovered)
+    {
+      struct __go_empty_interface ret;
+
+      ret.__type_descriptor = NULL;
+      ret.__object = NULL;
+      return ret;
+    }
+  p = g->panic;
+  p->__was_recovered = 1;
+  return p->__arg;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-reflect-call.c b/third_party/gofrontend/libgo/runtime/go-reflect-call.c
new file mode 100644
index 0000000..dfc703e
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-reflect-call.c
@@ -0,0 +1,251 @@
+/* go-reflect-call.c -- call reflection support for Go.
+
+   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.  */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "go-assert.h"
+#include "go-type.h"
+
+#ifdef USE_LIBFFI
+
+#include "go-ffi.h"
+
+/* The functions in this file are only called from reflect_call.  As
+   reflect_call calls a libffi function, which will be compiled
+   without -fsplit-stack, it will always run with a large stack.  */
+
+static size_t go_results_size (const struct __go_func_type *)
+  __attribute__ ((no_split_stack));
+static void go_set_results (const struct __go_func_type *, unsigned char *,
+			    void **)
+  __attribute__ ((no_split_stack));
+
+/* Get the total size required for the result parameters of a
+   function.  */
+
+static size_t
+go_results_size (const struct __go_func_type *func)
+{
+  int count;
+  const struct __go_type_descriptor **types;
+  size_t off;
+  size_t maxalign;
+  int i;
+
+  count = func->__out.__count;
+  if (count == 0)
+    return 0;
+
+  types = (const struct __go_type_descriptor **) func->__out.__values;
+
+  /* A single integer return value is always promoted to a full
+     word.  */
+  if (count == 1)
+    {
+      switch (types[0]->__code & GO_CODE_MASK)
+	{
+	case GO_BOOL:
+	case GO_INT8:
+	case GO_INT16:
+	case GO_INT32:
+	case GO_UINT8:
+	case GO_UINT16:
+	case GO_UINT32:
+	case GO_INT:
+	case GO_UINT:
+	  return sizeof (ffi_arg);
+
+	default:
+	  break;
+	}
+    }
+
+  off = 0;
+  maxalign = 0;
+  for (i = 0; i < count; ++i)
+    {
+      size_t align;
+
+      align = types[i]->__field_align;
+      if (align > maxalign)
+	maxalign = align;
+      off = (off + align - 1) & ~ (align - 1);
+      off += types[i]->__size;
+    }
+
+  off = (off + maxalign - 1) & ~ (maxalign - 1);
+
+  return off;
+}
+
+/* Copy the results of calling a function via FFI from CALL_RESULT
+   into the addresses in RESULTS.  */
+
+static void
+go_set_results (const struct __go_func_type *func, unsigned char *call_result,
+		void **results)
+{
+  int count;
+  const struct __go_type_descriptor **types;
+  size_t off;
+  int i;
+
+  count = func->__out.__count;
+  if (count == 0)
+    return;
+
+  types = (const struct __go_type_descriptor **) func->__out.__values;
+
+  /* A single integer return value is always promoted to a full
+     word.  */
+  if (count == 1)
+    {
+      switch (types[0]->__code & GO_CODE_MASK)
+	{
+	case GO_BOOL:
+	case GO_INT8:
+	case GO_INT16:
+	case GO_INT32:
+	case GO_UINT8:
+	case GO_UINT16:
+	case GO_UINT32:
+	case GO_INT:
+	case GO_UINT:
+	  {
+	    union
+	    {
+	      unsigned char buf[sizeof (ffi_arg)];
+	      ffi_arg v;
+	    } u;
+	    ffi_arg v;
+
+	    __builtin_memcpy (&u.buf, call_result, sizeof (ffi_arg));
+	    v = u.v;
+
+	    switch (types[0]->__size)
+	      {
+	      case 1:
+		{
+		  uint8_t b;
+
+		  b = (uint8_t) v;
+		  __builtin_memcpy (results[0], &b, 1);
+		}
+		break;
+
+	      case 2:
+		{
+		  uint16_t s;
+
+		  s = (uint16_t) v;
+		  __builtin_memcpy (results[0], &s, 2);
+		}
+		break;
+
+	      case 4:
+		{
+		  uint32_t w;
+
+		  w = (uint32_t) v;
+		  __builtin_memcpy (results[0], &w, 4);
+		}
+		break;
+
+	      case 8:
+		{
+		  uint64_t d;
+
+		  d = (uint64_t) v;
+		  __builtin_memcpy (results[0], &d, 8);
+		}
+		break;
+
+	      default:
+		abort ();
+	      }
+	  }
+	  return;
+
+	default:
+	  break;
+	}
+    }
+
+  off = 0;
+  for (i = 0; i < count; ++i)
+    {
+      size_t align;
+      size_t size;
+
+      align = types[i]->__field_align;
+      size = types[i]->__size;
+      off = (off + align - 1) & ~ (align - 1);
+      __builtin_memcpy (results[i], call_result + off, size);
+      off += size;
+    }
+}
+
+/* Call a function.  The type of the function is FUNC_TYPE, and the
+   closure is FUNC_VAL.  PARAMS is an array of parameter addresses.
+   RESULTS is an array of result addresses.
+
+   If IS_INTERFACE is true this is a call to an interface method and
+   the first argument is the receiver, which is always a pointer.
+   This argument, the receiver, is not described in FUNC_TYPE.
+
+   If IS_METHOD is true this is a call to a method expression.  The
+   first argument is the receiver.  It is described in FUNC_TYPE, but
+   regardless of FUNC_TYPE, it is passed as a pointer.
+
+   If neither IS_INTERFACE nor IS_METHOD is true then we are calling a
+   function indirectly, and we must pass a closure pointer via
+   __go_set_closure.  The pointer to pass is simply FUNC_VAL.  */
+
+void
+reflect_call (const struct __go_func_type *func_type, FuncVal *func_val,
+	      _Bool is_interface, _Bool is_method, void **params,
+	      void **results)
+{
+  ffi_cif cif;
+  unsigned char *call_result;
+
+  __go_assert ((func_type->__common.__code & GO_CODE_MASK) == GO_FUNC);
+  __go_func_to_cif (func_type, is_interface, is_method, &cif);
+
+  call_result = (unsigned char *) malloc (go_results_size (func_type));
+
+  if (!is_interface && !is_method)
+    __go_set_closure (func_val);
+  ffi_call (&cif, func_val->fn, call_result, params);
+
+  /* Some day we may need to free result values if RESULTS is
+     NULL.  */
+  if (results != NULL)
+    go_set_results (func_type, call_result, results);
+
+  free (call_result);
+}
+
+#else /* !defined(USE_LIBFFI) */
+
+void
+reflect_call (const struct __go_func_type *func_type __attribute__ ((unused)),
+	      FuncVal *func_val __attribute__ ((unused)),
+	      _Bool is_interface __attribute__ ((unused)),
+	      _Bool is_method __attribute__ ((unused)),
+	      void **params __attribute__ ((unused)),
+	      void **results __attribute__ ((unused)))
+{
+  /* Without FFI there is nothing we can do.  */
+  runtime_throw("libgo built without FFI does not support "
+		"reflect.Call or runtime.SetFinalizer");
+}
+
+#endif /* !defined(USE_LIBFFI) */
diff --git a/third_party/gofrontend/libgo/runtime/go-reflect-map.c b/third_party/gofrontend/libgo/runtime/go-reflect-map.c
new file mode 100644
index 0000000..ab116e8
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-reflect-map.c
@@ -0,0 +1,155 @@
+/* go-reflect-map.c -- map reflection support for Go.
+
+   Copyright 2009, 2010 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 <stdlib.h>
+#include <stdint.h>
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "go-assert.h"
+#include "go-type.h"
+#include "map.h"
+
+/* This file implements support for reflection on maps.  These
+   functions are called from reflect/value.go.  */
+
+extern void *mapaccess (struct __go_map_type *, void *, void *)
+  __asm__ (GOSYM_PREFIX "reflect.mapaccess");
+
+void *
+mapaccess (struct __go_map_type *mt, void *m, void *key)
+{
+  struct __go_map *map = (struct __go_map *) m;
+
+  __go_assert (mt->__common.__code == GO_MAP);
+  if (map == NULL)
+    return NULL;
+  else
+    return __go_map_index (map, key, 0);
+}
+
+extern void mapassign (struct __go_map_type *, void *, void *, void *)
+  __asm__ (GOSYM_PREFIX "reflect.mapassign");
+
+void
+mapassign (struct __go_map_type *mt, void *m, void *key, void *val)
+{
+  struct __go_map *map = (struct __go_map *) m;
+  void *p;
+
+  __go_assert (mt->__common.__code == GO_MAP);
+  if (map == NULL)
+    runtime_panicstring ("assignment to entry in nil map");
+  p = __go_map_index (map, key, 1);
+  __builtin_memcpy (p, val, mt->__val_type->__size);
+}
+
+extern void mapdelete (struct __go_map_type *, void *, void *)
+  __asm__ (GOSYM_PREFIX "reflect.mapdelete");
+
+void
+mapdelete (struct __go_map_type *mt, void *m, void *key)
+{
+  struct __go_map *map = (struct __go_map *) m;
+
+  __go_assert (mt->__common.__code == GO_MAP);
+  if (map == NULL)
+    return;
+  __go_map_delete (map, key);
+}
+
+extern int32_t maplen (void *) __asm__ (GOSYM_PREFIX "reflect.maplen");
+
+int32_t
+maplen (void *m)
+{
+  struct __go_map *map = (struct __go_map *) m;
+
+  if (map == NULL)
+    return 0;
+  return (int32_t) map->__element_count;
+}
+
+extern unsigned char *mapiterinit (struct __go_map_type *, void *)
+  __asm__ (GOSYM_PREFIX "reflect.mapiterinit");
+
+unsigned char *
+mapiterinit (struct __go_map_type *mt, void *m)
+{
+  struct __go_hash_iter *it;
+
+  __go_assert (mt->__common.__code == GO_MAP);
+  it = __go_alloc (sizeof (struct __go_hash_iter));
+  __go_mapiterinit ((struct __go_map *) m, it);
+  return (unsigned char *) it;
+}
+
+extern void mapiternext (void *) __asm__ (GOSYM_PREFIX "reflect.mapiternext");
+
+void
+mapiternext (void *it)
+{
+  __go_mapiternext ((struct __go_hash_iter *) it);
+}
+
+extern void *mapiterkey (void *) __asm__ (GOSYM_PREFIX "reflect.mapiterkey");
+
+void *
+mapiterkey (void *ita)
+{
+  struct __go_hash_iter *it = (struct __go_hash_iter *) ita;
+  const struct __go_type_descriptor *key_descriptor;
+  void *key;
+
+  if (it->entry == NULL)
+    return NULL;
+
+  key_descriptor = it->map->__descriptor->__map_descriptor->__key_type;
+  key = __go_alloc (key_descriptor->__size);
+  __go_mapiter1 (it, key);
+  return key;
+}
+
+/* Make a new map.  We have to build our own map descriptor.  */
+
+extern struct __go_map *makemap (const struct __go_map_type *)
+  __asm__ (GOSYM_PREFIX "reflect.makemap");
+
+struct __go_map *
+makemap (const struct __go_map_type *t)
+{
+  struct __go_map_descriptor *md;
+  unsigned int o;
+  const struct __go_type_descriptor *kt;
+  const struct __go_type_descriptor *vt;
+
+  md = (struct __go_map_descriptor *) __go_alloc (sizeof (*md));
+  md->__map_descriptor = t;
+  o = sizeof (void *);
+  kt = t->__key_type;
+  o = (o + kt->__field_align - 1) & ~ (kt->__field_align - 1);
+  md->__key_offset = o;
+  o += kt->__size;
+  vt = t->__val_type;
+  o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1);
+  md->__val_offset = o;
+  o += vt->__size;
+  o = (o + sizeof (void *) - 1) & ~ (sizeof (void *) - 1);
+  o = (o + kt->__field_align - 1) & ~ (kt->__field_align - 1);
+  o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1);
+  md->__entry_size = o;
+
+  return __go_new_map (md, 0);
+}
+
+extern _Bool ismapkey (const struct __go_type_descriptor *)
+  __asm__ (GOSYM_PREFIX "reflect.ismapkey");
+
+_Bool
+ismapkey (const struct __go_type_descriptor *typ)
+{
+  return typ != NULL && typ->__hashfn != __go_type_hash_error;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-rune.c b/third_party/gofrontend/libgo/runtime/go-rune.c
new file mode 100644
index 0000000..4c65e21
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-rune.c
@@ -0,0 +1,97 @@
+/* go-rune.c -- rune functions for Go.
+
+   Copyright 2009, 2010 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 <stddef.h>
+
+#include "runtime.h"
+#include "go-string.h"
+
+/* Get a character from the UTF-8 string STR, of length LEN.  Store
+   the Unicode character, if any, in *RUNE.  Return the number of
+   characters used from STR.  */
+
+int
+__go_get_rune (const unsigned char *str, size_t len, int32 *rune)
+{
+  int c, c1, c2, c3, l;
+
+  /* Default to the "replacement character".  */
+  *rune = 0xfffd;
+
+  if (len <= 0)
+    return 1;
+
+  c = *str;
+  if (c <= 0x7f)
+    {
+      *rune = c;
+      return 1;
+    }
+
+  if (len <= 1)
+    return 1;
+
+  c1 = str[1];
+  if ((c & 0xe0) == 0xc0
+      && (c1 & 0xc0) == 0x80)
+    {
+      l = (((c & 0x1f) << 6) + (c1 & 0x3f));
+      if (l <= 0x7f)
+	return 1;
+      *rune = l;
+      return 2;
+    }
+
+  if (len <= 2)
+    return 1;
+
+  c2 = str[2];
+  if ((c & 0xf0) == 0xe0
+      && (c1 & 0xc0) == 0x80
+      && (c2 & 0xc0) == 0x80)
+    {
+      l = (((c & 0xf) << 12)
+	   + ((c1 & 0x3f) << 6)
+	   + (c2 & 0x3f));
+
+      if (l <= 0x7ff)
+	return 1;
+
+      if (l >= 0xd800 && l < 0xe000)
+	{
+	  /* Invalid surrogate half; return replace character.  */
+	  return 1;
+	}
+
+      *rune = l;
+
+      return 3;
+    }
+
+  if (len <= 3)
+    return 1;
+
+  c3 = str[3];
+  if ((c & 0xf8) == 0xf0
+      && (c1 & 0xc0) == 0x80
+      && (c2 & 0xc0) == 0x80
+      && (c3 & 0xc0) == 0x80)
+    {
+      l = (((c & 0x7) << 18)
+	   + ((c1 & 0x3f) << 12)
+	   + ((c2 & 0x3f) << 6)
+	   + (c3 & 0x3f));
+
+      if (l <= 0xffff || l > 0x10ffff)
+	return 1;
+
+      *rune = l;
+      return 4;
+    }
+
+  /* Invalid encoding.  Return 1 so that we advance.  */
+  return 1;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-runtime-error.c b/third_party/gofrontend/libgo/runtime/go-runtime-error.c
new file mode 100644
index 0000000..f5ab4f9
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-runtime-error.c
@@ -0,0 +1,90 @@
+/* go-runtime-error.c -- Go runtime error.
+
+   Copyright 2010 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 "runtime.h"
+
+/* The compiler generates calls to this function.  This enum values
+   are known to the compiler and used by compiled code.  Any change
+   here must be reflected in the compiler.  */
+
+enum
+{
+  /* Slice index out of bounds: negative or larger than the length of
+     the slice.  */
+  SLICE_INDEX_OUT_OF_BOUNDS = 0,
+
+  /* Array index out of bounds.  */
+  ARRAY_INDEX_OUT_OF_BOUNDS = 1,
+
+  /* String index out of bounds.  */
+  STRING_INDEX_OUT_OF_BOUNDS = 2,
+
+  /* Slice slice out of bounds: negative or larger than the length of
+     the slice or high bound less than low bound.  */
+  SLICE_SLICE_OUT_OF_BOUNDS = 3,
+
+  /* Array slice out of bounds.  */
+  ARRAY_SLICE_OUT_OF_BOUNDS = 4,
+
+  /* String slice out of bounds.  */
+  STRING_SLICE_OUT_OF_BOUNDS = 5,
+
+  /* Dereference of nil pointer.  This is used when there is a
+     dereference of a pointer to a very large struct or array, to
+     ensure that a gigantic array is not used a proxy to access random
+     memory locations.  */
+  NIL_DEREFERENCE = 6,
+
+  /* Slice length or capacity out of bounds in make: negative or
+     overflow or length greater than capacity.  */
+  MAKE_SLICE_OUT_OF_BOUNDS = 7,
+
+  /* Map capacity out of bounds in make: negative or overflow.  */
+  MAKE_MAP_OUT_OF_BOUNDS = 8,
+
+  /* Channel capacity out of bounds in make: negative or overflow.  */
+  MAKE_CHAN_OUT_OF_BOUNDS = 9,
+
+  /* Integer division by zero.  */
+  DIVISION_BY_ZERO = 10
+};
+
+extern void __go_runtime_error () __attribute__ ((noreturn));
+
+void
+__go_runtime_error (int32 i)
+{
+  switch (i)
+    {
+    case SLICE_INDEX_OUT_OF_BOUNDS:
+    case ARRAY_INDEX_OUT_OF_BOUNDS:
+    case STRING_INDEX_OUT_OF_BOUNDS:
+      runtime_panicstring ("index out of range");
+
+    case SLICE_SLICE_OUT_OF_BOUNDS:
+    case ARRAY_SLICE_OUT_OF_BOUNDS:
+    case STRING_SLICE_OUT_OF_BOUNDS:
+      runtime_panicstring ("slice bounds out of range");
+
+    case NIL_DEREFERENCE:
+      runtime_panicstring ("nil pointer dereference");
+
+    case MAKE_SLICE_OUT_OF_BOUNDS:
+      runtime_panicstring ("make slice len or cap out of range");
+
+    case MAKE_MAP_OUT_OF_BOUNDS:
+      runtime_panicstring ("make map len out of range");
+
+    case MAKE_CHAN_OUT_OF_BOUNDS:
+      runtime_panicstring ("make chan len out of range");
+
+    case DIVISION_BY_ZERO:
+      runtime_panicstring ("integer divide by zero");
+
+    default:
+      runtime_panicstring ("unknown runtime error");
+    }
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-setenv.c b/third_party/gofrontend/libgo/runtime/go-setenv.c
new file mode 100644
index 0000000..a75d7c4
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-setenv.c
@@ -0,0 +1,84 @@
+/* go-setenv.c -- set the C environment from Go.
+
+   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.  */
+
+#include "config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "go-alloc.h"
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+/* Set the C environment from Go.  This is called by syscall.Setenv.  */
+
+void setenv_c (String, String) __asm__ (GOSYM_PREFIX "syscall.setenv_c");
+
+void
+setenv_c (String k, String v)
+{
+  const byte *ks;
+  unsigned char *kn;
+  const byte *vs;
+  unsigned char *vn;
+  intgo len;
+
+  ks = k.str;
+  if (ks == NULL)
+    ks = (const byte *) "";
+  kn = NULL;
+
+  vs = v.str;
+  if (vs == NULL)
+    vs = (const byte *) "";
+  vn = NULL;
+
+#ifdef HAVE_SETENV
+
+  if (ks != NULL && ks[k.len] != 0)
+    {
+      // Objects that are explicitly freed must be at least 16 bytes in size,
+      // so that they are not allocated using tiny alloc.
+      len = k.len + 1;
+      if (len < TinySize)
+	len = TinySize;
+      kn = __go_alloc (len);
+      __builtin_memcpy (kn, ks, k.len);
+      ks = kn;
+    }
+
+  if (vs != NULL && vs[v.len] != 0)
+    {
+      len = v.len + 1;
+      if (len < TinySize)
+	len = TinySize;
+      vn = __go_alloc (len);
+      __builtin_memcpy (vn, vs, v.len);
+      vs = vn;
+    }
+
+  setenv ((const char *) ks, (const char *) vs, 1);
+
+#else /* !defined(HAVE_SETENV) */
+
+  len = k.len + v.len + 2;
+  if (len < TinySize)
+    len = TinySize;
+  kn = __go_alloc (len);
+  __builtin_memcpy (kn, ks, k.len);
+  kn[k.len] = '=';
+  __builtin_memcpy (kn + k.len + 1, vs, v.len);
+  kn[k.len + v.len + 1] = '\0';
+  putenv ((char *) kn);
+
+#endif /* !defined(HAVE_SETENV) */
+
+  if (kn != NULL)
+    __go_free (kn);
+  if (vn != NULL)
+    __go_free (vn);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-signal.c b/third_party/gofrontend/libgo/runtime/go-signal.c
new file mode 100644
index 0000000..4a1bf56
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-signal.c
@@ -0,0 +1,546 @@
+/* go-signal.c -- signal handling for Go.
+
+   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.  */
+
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "runtime.h"
+#include "go-assert.h"
+#include "go-panic.h"
+#include "signal_unix.h"
+
+#ifndef SA_RESTART
+  #define SA_RESTART 0
+#endif
+
+#ifdef USING_SPLIT_STACK
+
+extern void __splitstack_getcontext(void *context[10]);
+
+extern void __splitstack_setcontext(void *context[10]);
+
+#endif
+
+#define N SigNotify
+#define K SigKill
+#define T SigThrow
+#define P SigPanic
+#define D SigDefault
+
+/* Signal actions.  This collects the sigtab tables for several
+   different targets from the master library.  SIGKILL, SIGCONT, and
+   SIGSTOP are not listed, as we don't want to set signal handlers for
+   them.  */
+
+SigTab runtime_sigtab[] = {
+#ifdef SIGHUP
+  { SIGHUP,	N + K },
+#endif
+#ifdef SIGINT
+  { SIGINT, 	N + K },
+#endif
+#ifdef SIGQUIT
+  { SIGQUIT, 	N + T },
+#endif
+#ifdef SIGILL
+  { SIGILL, 	T },
+#endif
+#ifdef SIGTRAP
+  { SIGTRAP, 	T },
+#endif
+#ifdef SIGABRT
+  { SIGABRT, 	N + T },
+#endif
+#ifdef SIGBUS
+  { SIGBUS, 	P },
+#endif
+#ifdef SIGFPE
+  { SIGFPE, 	P },
+#endif
+#ifdef SIGUSR1
+  { SIGUSR1, 	N },
+#endif
+#ifdef SIGSEGV
+  { SIGSEGV, 	P },
+#endif
+#ifdef SIGUSR2
+  { SIGUSR2, 	N },
+#endif
+#ifdef SIGPIPE
+  { SIGPIPE, 	N },
+#endif
+#ifdef SIGALRM
+  { SIGALRM, 	N },
+#endif
+#ifdef SIGTERM
+  { SIGTERM, 	N + K },
+#endif
+#ifdef SIGSTKFLT
+  { SIGSTKFLT, 	T },
+#endif
+#ifdef SIGCHLD
+  { SIGCHLD, 	N },
+#endif
+#ifdef SIGTSTP
+  { SIGTSTP, 	N + D },
+#endif
+#ifdef SIGTTIN
+  { SIGTTIN, 	N + D },
+#endif
+#ifdef SIGTTOU
+  { SIGTTOU, 	N + D },
+#endif
+#ifdef SIGURG
+  { SIGURG, 	N },
+#endif
+#ifdef SIGXCPU
+  { SIGXCPU, 	N },
+#endif
+#ifdef SIGXFSZ
+  { SIGXFSZ, 	N },
+#endif
+#ifdef SIGVTALRM
+  { SIGVTALRM, 	N },
+#endif
+#ifdef SIGPROF
+  { SIGPROF, 	N },
+#endif
+#ifdef SIGWINCH
+  { SIGWINCH, 	N },
+#endif
+#ifdef SIGIO
+  { SIGIO, 	N },
+#endif
+#ifdef SIGPWR
+  { SIGPWR, 	N },
+#endif
+#ifdef SIGSYS
+  { SIGSYS, 	N },
+#endif
+#ifdef SIGEMT
+  { SIGEMT,	T },
+#endif
+#ifdef SIGINFO
+  { SIGINFO,	N },
+#endif
+#ifdef SIGTHR
+  { SIGTHR,	N },
+#endif
+  { -1,		0 }
+};
+#undef N
+#undef K
+#undef T
+#undef P
+#undef D
+
+/* Handle a signal, for cases where we don't panic.  We can split the
+   stack here.  */
+
+void
+runtime_sighandler (int sig, Siginfo *info,
+		    void *context __attribute__ ((unused)), G *gp)
+{
+  M *m;
+  int i;
+
+  m = runtime_m ();
+
+#ifdef SIGPROF
+  if (sig == SIGPROF)
+    {
+      if (m != NULL && gp != m->g0 && gp != m->gsignal)
+	runtime_sigprof ();
+      return;
+    }
+#endif
+
+  if (m == NULL)
+    {
+      runtime_badsignal (sig);
+      return;
+    }
+
+  for (i = 0; runtime_sigtab[i].sig != -1; ++i)
+    {
+      SigTab *t;
+      bool notify, crash;
+
+      t = &runtime_sigtab[i];
+
+      if (t->sig != sig)
+	continue;
+
+      notify = false;
+#ifdef SA_SIGINFO
+      notify = info != NULL && info->si_code == SI_USER;
+#endif
+      if (notify || (t->flags & SigNotify) != 0)
+	{
+	  if (__go_sigsend (sig))
+	    return;
+	}
+      if ((t->flags & SigKill) != 0)
+	runtime_exit (2);
+      if ((t->flags & SigThrow) == 0)
+	return;
+
+      runtime_startpanic ();
+
+      {
+	const char *name = NULL;
+
+#ifdef HAVE_STRSIGNAL
+	name = strsignal (sig);
+#endif
+
+	if (name == NULL)
+	  runtime_printf ("Signal %d\n", sig);
+	else
+	  runtime_printf ("%s\n", name);
+      }
+
+      if (m->lockedg != NULL && m->ncgo > 0 && gp == m->g0)
+	{
+	  runtime_printf("signal arrived during cgo execution\n");
+	  gp = m->lockedg;
+	}
+
+      runtime_printf ("\n");
+
+      if (runtime_gotraceback (&crash))
+	{
+	  G *g;
+
+	  g = runtime_g ();
+	  runtime_traceback ();
+	  runtime_tracebackothers (g);
+
+	  /* The gc library calls runtime_dumpregs here, and provides
+	     a function that prints the registers saved in context in
+	     a readable form.  */
+	}
+
+      if (crash)
+	runtime_crash ();
+
+      runtime_exit (2);
+    }
+
+  __builtin_unreachable ();
+}
+
+/* The start of handling a signal which panics.  */
+
+static void
+sig_panic_leadin (G *gp)
+{
+  int i;
+  sigset_t clear;
+
+  if (!runtime_canpanic (gp))
+    runtime_throw ("unexpected signal during runtime execution");
+
+  /* The signal handler blocked signals; unblock them.  */
+  i = sigfillset (&clear);
+  __go_assert (i == 0);
+  i = pthread_sigmask (SIG_UNBLOCK, &clear, NULL);
+  __go_assert (i == 0);
+}
+
+#ifdef SA_SIGINFO
+
+/* Signal dispatch for signals which panic, on systems which support
+   SA_SIGINFO.  This is called on the thread stack, and as such it is
+   permitted to split the stack.  */
+
+static void
+sig_panic_info_handler (int sig, Siginfo *info, void *context)
+{
+  G *g;
+
+  g = runtime_g ();
+  if (g == NULL || info->si_code == SI_USER)
+    {
+      runtime_sighandler (sig, info, context, g);
+      return;
+    }
+
+  g->sig = sig;
+  g->sigcode0 = info->si_code;
+  g->sigcode1 = (uintptr_t) info->si_addr;
+
+  /* It would be nice to set g->sigpc here as the gc library does, but
+     I don't know how to get it portably.  */
+
+  sig_panic_leadin (g);
+
+  switch (sig)
+    {
+#ifdef SIGBUS
+    case SIGBUS:
+      if ((info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
+	  || g->paniconfault)
+	runtime_panicstring ("invalid memory address or "
+			     "nil pointer dereference");
+      runtime_printf ("unexpected fault address %p\n", info->si_addr);
+      runtime_throw ("fault");
+#endif
+
+#ifdef SIGSEGV
+    case SIGSEGV:
+      if (((info->si_code == 0
+	    || info->si_code == SEGV_MAPERR
+	    || info->si_code == SEGV_ACCERR)
+	   && (uintptr_t) info->si_addr < 0x1000)
+	  || g->paniconfault)
+	runtime_panicstring ("invalid memory address or "
+			     "nil pointer dereference");
+      runtime_printf ("unexpected fault address %p\n", info->si_addr);
+      runtime_throw ("fault");
+#endif
+
+#ifdef SIGFPE
+    case SIGFPE:
+      switch (info->si_code)
+	{
+	case FPE_INTDIV:
+	  runtime_panicstring ("integer divide by zero");
+	case FPE_INTOVF:
+	  runtime_panicstring ("integer overflow");
+	}
+      runtime_panicstring ("floating point error");
+#endif
+    }
+
+  /* All signals with SigPanic should be in cases above, and this
+     handler should only be invoked for those signals.  */
+  __builtin_unreachable ();
+}
+
+#else /* !defined (SA_SIGINFO) */
+
+static void
+sig_panic_handler (int sig)
+{
+  G *g;
+
+  g = runtime_g ();
+  if (g == NULL)
+    {
+      runtime_sighandler (sig, NULL, NULL, g);
+      return;
+    }
+
+  g->sig = sig;
+  g->sigcode0 = 0;
+  g->sigcode1 = 0;
+
+  sig_panic_leadin (g);
+
+  switch (sig)
+    {
+#ifdef SIGBUS
+    case SIGBUS:
+      runtime_panicstring ("invalid memory address or "
+			   "nil pointer dereference");
+#endif
+
+#ifdef SIGSEGV
+    case SIGSEGV:
+      runtime_panicstring ("invalid memory address or "
+			   "nil pointer dereference");
+#endif
+
+#ifdef SIGFPE
+    case SIGFPE:
+      runtime_panicstring ("integer divide by zero or floating point error");
+#endif
+    }
+
+  /* All signals with SigPanic should be in cases above, and this
+     handler should only be invoked for those signals.  */
+  __builtin_unreachable ();
+}
+
+#endif /* !defined (SA_SIGINFO) */
+
+/* A signal handler used for signals which are not going to panic.
+   This is called on the alternate signal stack so it may not split
+   the stack.  */
+
+static void
+sig_tramp_info (int, Siginfo *, void *) __attribute__ ((no_split_stack));
+
+static void
+sig_tramp_info (int sig, Siginfo *info, void *context)
+{
+  G *gp;
+  M *mp;
+#ifdef USING_SPLIT_STACK
+  void *stack_context[10];
+#endif
+
+  /* We are now running on the stack registered via sigaltstack.
+     (Actually there is a small span of time between runtime_siginit
+     and sigaltstack when the program starts.)  */
+  gp = runtime_g ();
+  mp = runtime_m ();
+
+  if (gp != NULL)
+    {
+#ifdef USING_SPLIT_STACK
+      __splitstack_getcontext (&stack_context[0]);
+#endif
+    }
+
+  if (gp != NULL && mp->gsignal != NULL)
+    {
+      /* We are running on the signal stack.  Set the split stack
+	 context so that the stack guards are checked correctly.  */
+#ifdef USING_SPLIT_STACK
+      __splitstack_setcontext (&mp->gsignal->stack_context[0]);
+#endif
+    }
+
+  runtime_sighandler (sig, info, context, gp);
+
+  /* We are going to return back to the signal trampoline and then to
+     whatever we were doing before we got the signal.  Restore the
+     split stack context so that stack guards are checked
+     correctly.  */
+
+  if (gp != NULL)
+    {
+#ifdef USING_SPLIT_STACK
+      __splitstack_setcontext (&stack_context[0]);
+#endif
+    }
+}
+
+#ifndef SA_SIGINFO
+
+static void sig_tramp (int sig) __attribute__ ((no_split_stack));
+
+static void
+sig_tramp (int sig)
+{
+  sig_tramp_info (sig, NULL, NULL);
+}
+
+#endif
+
+void
+runtime_setsig (int32 i, GoSighandler *fn, bool restart)
+{
+  struct sigaction sa;
+  int r;
+  SigTab *t;
+
+  memset (&sa, 0, sizeof sa);
+
+  r = sigfillset (&sa.sa_mask);
+  __go_assert (r == 0);
+
+  t = &runtime_sigtab[i];
+
+  if ((t->flags & SigPanic) == 0)
+    {
+#ifdef SA_SIGINFO
+      sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
+      if (fn == runtime_sighandler)
+	fn = (void *) sig_tramp_info;
+      sa.sa_sigaction = (void *) fn;
+#else
+      sa.sa_flags = SA_ONSTACK;
+      if (fn == runtime_sighandler)
+	fn = (void *) sig_tramp;
+      sa.sa_handler = (void *) fn;
+#endif
+    }
+  else
+    {
+#ifdef SA_SIGINFO
+      sa.sa_flags = SA_SIGINFO;
+      if (fn == runtime_sighandler)
+	fn = (void *) sig_panic_info_handler;
+      sa.sa_sigaction = (void *) fn;
+#else
+      sa.sa_flags = 0;
+      if (fn == runtime_sighandler)
+	fn = (void *) sig_panic_handler;
+      sa.sa_handler = (void *) fn;
+#endif
+    }
+
+  if (restart)
+    sa.sa_flags |= SA_RESTART;
+
+  if (sigaction (t->sig, &sa, NULL) != 0)
+    __go_assert (0);
+}
+
+GoSighandler*
+runtime_getsig (int32 i)
+{
+  struct sigaction sa;
+  int r;
+  SigTab *t;
+
+  memset (&sa, 0, sizeof sa);
+
+  r = sigemptyset (&sa.sa_mask);
+  __go_assert (r == 0);
+
+  t = &runtime_sigtab[i];
+
+  if (sigaction (t->sig, NULL, &sa) != 0)
+    runtime_throw ("sigaction read failure");
+
+  if ((void *) sa.sa_handler == sig_tramp_info)
+    return runtime_sighandler;
+#ifdef SA_SIGINFO
+  if ((void *) sa.sa_handler == sig_panic_info_handler)
+    return runtime_sighandler;
+#else
+  if ((void *) sa.sa_handler == sig_tramp
+      || (void *) sa.sa_handler == sig_panic_handler)
+    return runtime_sighandler;
+#endif
+
+  return (void *) sa.sa_handler;
+}
+
+/* Used by the os package to raise SIGPIPE.  */
+
+void os_sigpipe (void) __asm__ (GOSYM_PREFIX "os.sigpipe");
+
+void
+os_sigpipe (void)
+{
+  struct sigaction sa;
+  int i;
+
+  memset (&sa, 0, sizeof sa);
+
+  sa.sa_handler = SIG_DFL;
+
+  i = sigemptyset (&sa.sa_mask);
+  __go_assert (i == 0);
+
+  if (sigaction (SIGPIPE, &sa, NULL) != 0)
+    abort ();
+
+  raise (SIGPIPE);
+}
+
+void
+runtime_setprof(bool on)
+{
+	USED(on);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-strcmp.c b/third_party/gofrontend/libgo/runtime/go-strcmp.c
new file mode 100644
index 0000000..bcc270b
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-strcmp.c
@@ -0,0 +1,25 @@
+/* go-strcmp.c -- the go string comparison function.
+
+   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.  */
+
+#include "runtime.h"
+
+intgo
+__go_strcmp(String s1, String s2)
+{
+  int i;
+
+  i = __builtin_memcmp(s1.str, s2.str,
+		       (s1.len < s2.len ? s1.len : s2.len));
+  if (i != 0)
+    return i;
+
+  if (s1.len < s2.len)
+    return -1;
+  else if (s1.len > s2.len)
+    return 1;
+  else
+    return 0;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-string-to-byte-array.c b/third_party/gofrontend/libgo/runtime/go-string-to-byte-array.c
new file mode 100644
index 0000000..a4edb50
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-string-to-byte-array.c
@@ -0,0 +1,28 @@
+/* go-string-to-byte-array.c -- convert a string to an array of bytes in Go.
+
+   Copyright 2010 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 "runtime.h"
+#include "array.h"
+#include "arch.h"
+#include "malloc.h"
+
+struct __go_open_array
+__go_string_to_byte_array (String str)
+{
+  uintptr cap;
+  unsigned char *data;
+  struct __go_open_array ret;
+
+  cap = runtime_roundupsize (str.len);
+  data = (unsigned char *) runtime_mallocgc (cap, 0, FlagNoScan | FlagNoZero);
+  __builtin_memcpy (data, str.str, str.len);
+  if (cap != (uintptr) str.len)
+    __builtin_memset (data + str.len, 0, cap - (uintptr) str.len);
+  ret.__values = (void *) data;
+  ret.__count = str.len;
+  ret.__capacity = (intgo) cap;
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-string-to-int-array.c b/third_party/gofrontend/libgo/runtime/go-string-to-int-array.c
new file mode 100644
index 0000000..5546889
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-string-to-int-array.c
@@ -0,0 +1,56 @@
+/* go-string-to-int-array.c -- convert a string to an array of ints in Go.
+
+   Copyright 2010 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 "runtime.h"
+#include "go-alloc.h"
+#include "go-string.h"
+#include "array.h"
+#include "arch.h"
+#include "malloc.h"
+
+struct __go_open_array
+__go_string_to_int_array (String str)
+{
+  size_t c;
+  const unsigned char *p;
+  const unsigned char *pend;
+  uintptr mem;
+  uint32_t *data;
+  uint32_t *pd;
+  struct __go_open_array ret;
+
+  c = 0;
+  p = str.str;
+  pend = p + str.len;
+  while (p < pend)
+    {
+      int rune;
+
+      ++c;
+      p += __go_get_rune (p, pend - p, &rune);
+    }
+
+  if (c > MaxMem / sizeof (uint32_t))
+    runtime_throw ("out of memory");
+
+  mem = runtime_roundupsize (c * sizeof (uint32_t));
+  data = (uint32_t *) runtime_mallocgc (mem, 0, FlagNoScan | FlagNoZero);
+  p = str.str;
+  pd = data;
+  while (p < pend)
+    {
+      int rune;
+
+      p += __go_get_rune (p, pend - p, &rune);
+      *pd++ = rune;
+    }
+  if (mem > (uintptr) c * sizeof (uint32_t))
+    __builtin_memset (data + c, 0, mem - (uintptr) c * sizeof (uint32_t));
+  ret.__values = (void *) data;
+  ret.__count = c;
+  ret.__capacity = (intgo) (mem / sizeof (uint32_t));
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-string.h b/third_party/gofrontend/libgo/runtime/go-string.h
new file mode 100644
index 0000000..7fee1da
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-string.h
@@ -0,0 +1,31 @@
+/* go-string.h -- the string type for Go.
+
+   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.  */
+
+#ifndef LIBGO_GO_STRING_H
+#define LIBGO_GO_STRING_H
+
+#include <stddef.h>
+
+static inline _Bool
+__go_strings_equal (String s1, String s2)
+{
+  return (s1.len == s2.len
+	  && __builtin_memcmp (s1.str, s2.str, s1.len) == 0);
+}
+
+static inline _Bool
+__go_ptr_strings_equal (const String *ps1, const String *ps2)
+{
+  if (ps1 == NULL)
+    return ps2 == NULL;
+  if (ps2 == NULL)
+    return 0;
+  return __go_strings_equal (*ps1, *ps2);
+}
+
+extern int __go_get_rune (const unsigned char *, size_t, int32 *);
+
+#endif /* !defined(LIBGO_GO_STRING_H) */
diff --git a/third_party/gofrontend/libgo/runtime/go-strplus.c b/third_party/gofrontend/libgo/runtime/go-strplus.c
new file mode 100644
index 0000000..13915e3
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-strplus.c
@@ -0,0 +1,30 @@
+/* go-strplus.c -- the go string append function.
+
+   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.  */
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+String
+__go_string_plus (String s1, String s2)
+{
+  int len;
+  byte *retdata;
+  String ret;
+
+  if (s1.len == 0)
+    return s2;
+  else if (s2.len == 0)
+    return s1;
+
+  len = s1.len + s2.len;
+  retdata = runtime_mallocgc (len, 0, FlagNoScan | FlagNoZero);
+  __builtin_memcpy (retdata, s1.str, s1.len);
+  __builtin_memcpy (retdata + s1.len, s2.str, s2.len);
+  ret.str = retdata;
+  ret.len = len;
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-strslice.c b/third_party/gofrontend/libgo/runtime/go-strslice.c
new file mode 100644
index 0000000..21e1bc0
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-strslice.c
@@ -0,0 +1,26 @@
+/* go-strslice.c -- the go string slice function.
+
+   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.  */
+
+#include "go-panic.h"
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+String
+__go_string_slice (String s, intgo start, intgo end)
+{
+  intgo len;
+  String ret;
+
+  len = s.len;
+  if (end == -1)
+    end = len;
+  if (start > len || end < start || end > len)
+    runtime_panicstring ("string index out of bounds");
+  ret.str = s.str + start;
+  ret.len = end - start;
+  return ret;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-traceback.c b/third_party/gofrontend/libgo/runtime/go-traceback.c
new file mode 100644
index 0000000..7b33cca
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-traceback.c
@@ -0,0 +1,37 @@
+/* go-traceback.c -- stack backtrace for 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.  */
+
+#include "config.h"
+
+#include "runtime.h"
+
+/* Print a stack trace for the current goroutine.  */
+
+void
+runtime_traceback ()
+{
+  Location locbuf[100];
+  int32 c;
+
+  c = runtime_callers (1, locbuf, nelem (locbuf), false);
+  runtime_printtrace (locbuf, c, true);
+}
+
+void
+runtime_printtrace (Location *locbuf, int32 c, bool current)
+{
+  int32 i;
+
+  for (i = 0; i < c; ++i)
+    {
+      if (runtime_showframe (locbuf[i].function, current))
+	{
+	  runtime_printf ("%S\n", locbuf[i].function);
+	  runtime_printf ("\t%S:%D\n", locbuf[i].filename,
+			  (int64) locbuf[i].lineno);
+	}
+    }
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-type-complex.c b/third_party/gofrontend/libgo/runtime/go-type-complex.c
new file mode 100644
index 0000000..0f8f062
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-type-complex.c
@@ -0,0 +1,114 @@
+/* go-type-complex.c -- hash and equality complex functions.
+
+   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 <complex.h>
+#include <math.h>
+#include <stdint.h>
+#include <string.h>
+#include "runtime.h"
+#include "go-type.h"
+
+/* Hash function for float types.  */
+
+uintptr_t
+__go_type_hash_complex (const void *vkey, uintptr_t key_size)
+{
+  if (key_size == 8)
+    {
+      const complex float *cfp;
+      complex float cf;
+      float cfr;
+      float cfi;
+      uint64_t fi;
+
+      cfp = (const complex float *) vkey;
+      cf = *cfp;
+
+      cfr = crealf (cf);
+      cfi = cimagf (cf);
+
+      if (isinf (cfr) || isinf (cfi))
+	return 0;
+
+      /* NaN != NaN, so the hash code of a NaN is irrelevant.  Make it
+	 random so that not all NaNs wind up in the same place.  */
+      if (isnan (cfr) || isnan (cfi))
+	return runtime_fastrand1 ();
+
+      /* Avoid negative zero.  */
+      if (cfr == 0 && cfi == 0)
+	return 0;
+      else if (cfr == 0)
+	cf = cfi * I;
+      else if (cfi == 0)
+	cf = cfr;
+
+      memcpy (&fi, &cf, 8);
+      return (uintptr_t) cfi;
+    }
+  else if (key_size == 16)
+    {
+      const complex double *cdp;
+      complex double cd;
+      double cdr;
+      double cdi;
+      uint64_t di[2];
+
+      cdp = (const complex double *) vkey;
+      cd = *cdp;
+
+      cdr = creal (cd);
+      cdi = cimag (cd);
+
+      if (isinf (cdr) || isinf (cdi))
+	return 0;
+
+      if (isnan (cdr) || isnan (cdi))
+	return runtime_fastrand1 ();
+
+      /* Avoid negative zero.  */
+      if (cdr == 0 && cdi == 0)
+	return 0;
+      else if (cdr == 0)
+	cd = cdi * I;
+      else if (cdi == 0)
+	cd = cdr;
+
+      memcpy (&di, &cd, 16);
+      return di[0] ^ di[1];
+    }
+  else
+    runtime_throw ("__go_type_hash_complex: invalid complex size");
+}
+
+/* Equality function for complex types.  */
+
+_Bool
+__go_type_equal_complex (const void *vk1, const void *vk2, uintptr_t key_size)
+{
+  if (key_size == 8)
+    {
+      const complex float *cfp1;
+      const complex float *cfp2;
+      
+      cfp1 = (const complex float *) vk1;
+      cfp2 = (const complex float *) vk2;
+
+      return *cfp1 == *cfp2;
+    }
+  else if (key_size == 16)
+    {
+      const complex double *cdp1;
+      const complex double *cdp2;
+      
+      cdp1 = (const complex double *) vk1;
+      cdp2 = (const complex double *) vk2;
+
+      return *cdp1 == *cdp2;
+    }
+  else
+    runtime_throw ("__go_type_equal_complex: invalid complex size");
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-type-eface.c b/third_party/gofrontend/libgo/runtime/go-type-eface.c
new file mode 100644
index 0000000..30614d2
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-type-eface.c
@@ -0,0 +1,56 @@
+/* go-type-eface.c -- hash and equality empty interface functions.
+
+   Copyright 2010 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 "runtime.h"
+#include "interface.h"
+#include "go-type.h"
+
+/* A hash function for an empty interface.  */
+
+uintptr_t
+__go_type_hash_empty_interface (const void *vval,
+				uintptr_t key_size __attribute__ ((unused)))
+{
+  const struct __go_empty_interface *val;
+  const struct __go_type_descriptor *descriptor;
+  uintptr_t size;
+
+  val = (const struct __go_empty_interface *) vval;
+  descriptor = val->__type_descriptor;
+  if (descriptor == NULL)
+    return 0;
+  size = descriptor->__size;
+  if (__go_is_pointer_type (descriptor))
+    return descriptor->__hashfn (&val->__object, size);
+  else
+    return descriptor->__hashfn (val->__object, size);
+}
+
+/* An equality function for an empty interface.  */
+
+_Bool
+__go_type_equal_empty_interface (const void *vv1, const void *vv2,
+				 uintptr_t key_size __attribute__ ((unused)))
+{
+  const struct __go_empty_interface *v1;
+  const struct __go_empty_interface *v2;
+  const struct __go_type_descriptor* v1_descriptor;
+  const struct __go_type_descriptor* v2_descriptor;
+
+  v1 = (const struct __go_empty_interface *) vv1;
+  v2 = (const struct __go_empty_interface *) vv2;
+  v1_descriptor = v1->__type_descriptor;
+  v2_descriptor = v2->__type_descriptor;
+  if (v1_descriptor == NULL || v2_descriptor == NULL)
+    return v1_descriptor == v2_descriptor;
+  if (!__go_type_descriptors_equal (v1_descriptor, v2_descriptor))
+    return 0;
+  if (__go_is_pointer_type (v1_descriptor))
+    return v1->__object == v2->__object;
+  else
+    return v1_descriptor->__equalfn (v1->__object, v2->__object,
+				     v1_descriptor->__size);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-type-error.c b/third_party/gofrontend/libgo/runtime/go-type-error.c
new file mode 100644
index 0000000..b4c609b
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-type-error.c
@@ -0,0 +1,28 @@
+/* go-type-error.c -- invalid hash and equality functions.
+
+   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.  */
+
+#include "runtime.h"
+#include "go-type.h"
+
+/* A hash function used for a type which does not support hash
+   functions.  */
+
+uintptr_t
+__go_type_hash_error (const void *val __attribute__ ((unused)),
+		      uintptr_t key_size __attribute__ ((unused)))
+{
+  runtime_panicstring ("hash of unhashable type");
+}
+
+/* An equality function for an interface.  */
+
+_Bool
+__go_type_equal_error (const void *v1 __attribute__ ((unused)),
+		       const void *v2 __attribute__ ((unused)),
+		       uintptr_t key_size __attribute__ ((unused)))
+{
+  runtime_panicstring ("comparing uncomparable types");
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-type-float.c b/third_party/gofrontend/libgo/runtime/go-type-float.c
new file mode 100644
index 0000000..4ae7347
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-type-float.c
@@ -0,0 +1,86 @@
+/* go-type-float.c -- hash and equality float functions.
+
+   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 <math.h>
+#include <stdint.h>
+#include "runtime.h"
+#include "go-type.h"
+
+/* Hash function for float types.  */
+
+uintptr_t
+__go_type_hash_float (const void *vkey, uintptr_t key_size)
+{
+  if (key_size == 4)
+    {
+      const float *fp;
+      float f;
+      uint32_t si;
+
+      fp = (const float *) vkey;
+      f = *fp;
+
+      if (isinf (f) || f == 0)
+	return 0;
+
+      /* NaN != NaN, so the hash code of a NaN is irrelevant.  Make it
+	 random so that not all NaNs wind up in the same place.  */
+      if (isnan (f))
+	return runtime_fastrand1 ();
+
+      memcpy (&si, vkey, 4);
+      return (uintptr_t) si;
+    }
+  else if (key_size == 8)
+    {
+      const double *dp;
+      double d;
+      uint64_t di;
+
+      dp = (const double *) vkey;
+      d = *dp;
+
+      if (isinf (d) || d == 0)
+	return 0;
+
+      if (isnan (d))
+	return runtime_fastrand1 ();
+
+      memcpy (&di, vkey, 8);
+      return (uintptr_t) di;
+    }
+  else
+    runtime_throw ("__go_type_hash_float: invalid float size");
+}
+
+/* Equality function for float types.  */
+
+_Bool
+__go_type_equal_float (const void *vk1, const void *vk2, uintptr_t key_size)
+{
+  if (key_size == 4)
+    {
+      const float *fp1;
+      const float *fp2;
+
+      fp1 = (const float *) vk1;
+      fp2 = (const float *) vk2;
+
+      return *fp1 == *fp2;
+    }
+  else if (key_size == 8)
+    {
+      const double *dp1;
+      const double *dp2;
+
+      dp1 = (const double *) vk1;
+      dp2 = (const double *) vk2;
+
+      return *dp1 == *dp2;
+    }
+  else
+    runtime_throw ("__go_type_equal_float: invalid float size");
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-type-identity.c b/third_party/gofrontend/libgo/runtime/go-type-identity.c
new file mode 100644
index 0000000..ed510f7
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-type-identity.c
@@ -0,0 +1,56 @@
+/* go-type-identity.c -- hash and equality identity functions.
+
+   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.  */
+
+#include <stddef.h>
+
+#include "runtime.h"
+#include "go-type.h"
+
+/* An identity hash function for a type.  This is used for types where
+   we can simply use the type value itself as a hash code.  This is
+   true of, e.g., integers and pointers.  */
+
+uintptr_t
+__go_type_hash_identity (const void *key, uintptr_t key_size)
+{
+  uintptr_t ret;
+  uintptr_t i;
+  const unsigned char *p;
+
+  if (key_size <= 8)
+    {
+      union
+      {
+	uint64 v;
+	unsigned char a[8];
+      } u;
+      u.v = 0;
+#ifdef WORDS_BIGENDIAN
+      __builtin_memcpy (&u.a[8 - key_size], key, key_size);
+#else
+      __builtin_memcpy (&u.a[0], key, key_size);
+#endif
+      if (sizeof (uintptr_t) >= 8)
+	return (uintptr_t) u.v;
+      else
+	return (uintptr_t) ((u.v >> 32) ^ (u.v & 0xffffffff));
+    }
+
+  ret = 5381;
+  for (i = 0, p = (const unsigned char *) key; i < key_size; i++, p++)
+    ret = ret * 33 + *p;
+  return ret;
+}
+
+/* An identity equality function for a type.  This is used for types
+   where we can check for equality by checking that the values have
+   the same bits.  */
+
+_Bool
+__go_type_equal_identity (const void *k1, const void *k2, uintptr_t key_size)
+{
+  return __builtin_memcmp (k1, k2, key_size) == 0;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-type-interface.c b/third_party/gofrontend/libgo/runtime/go-type-interface.c
new file mode 100644
index 0000000..9aad720
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-type-interface.c
@@ -0,0 +1,56 @@
+/* go-type-interface.c -- hash and equality interface functions.
+
+   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.  */
+
+#include "runtime.h"
+#include "interface.h"
+#include "go-type.h"
+
+/* A hash function for an interface.  */
+
+uintptr_t
+__go_type_hash_interface (const void *vval,
+			  uintptr_t key_size __attribute__ ((unused)))
+{
+  const struct __go_interface *val;
+  const struct __go_type_descriptor *descriptor;
+  uintptr_t size;
+
+  val = (const struct __go_interface *) vval;
+  if (val->__methods == NULL)
+    return 0;
+  descriptor = (const struct __go_type_descriptor *) val->__methods[0];
+  size = descriptor->__size;
+  if (__go_is_pointer_type (descriptor))
+    return descriptor->__hashfn (&val->__object, size);
+  else
+    return descriptor->__hashfn (val->__object, size);
+}
+
+/* An equality function for an interface.  */
+
+_Bool
+__go_type_equal_interface (const void *vv1, const void *vv2,
+			   uintptr_t key_size __attribute__ ((unused)))
+{
+  const struct __go_interface *v1;
+  const struct __go_interface *v2;
+  const struct __go_type_descriptor* v1_descriptor;
+  const struct __go_type_descriptor* v2_descriptor;
+
+  v1 = (const struct __go_interface *) vv1;
+  v2 = (const struct __go_interface *) vv2;
+  if (v1->__methods == NULL || v2->__methods == NULL)
+    return v1->__methods == v2->__methods;
+  v1_descriptor = (const struct __go_type_descriptor *) v1->__methods[0];
+  v2_descriptor = (const struct __go_type_descriptor *) v2->__methods[0];
+  if (!__go_type_descriptors_equal (v1_descriptor, v2_descriptor))
+    return 0;
+  if (__go_is_pointer_type (v1_descriptor))
+    return v1->__object == v2->__object;
+  else
+    return v1_descriptor->__equalfn (v1->__object, v2->__object,
+				     v1_descriptor->__size);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-type-string.c b/third_party/gofrontend/libgo/runtime/go-type-string.c
new file mode 100644
index 0000000..a96af02
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-type-string.c
@@ -0,0 +1,43 @@
+/* go-type-string.c -- hash and equality string functions.
+
+   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.  */
+
+#include "runtime.h"
+#include "go-type.h"
+#include "go-string.h"
+
+/* A string hash function for a map.  */
+
+uintptr_t
+__go_type_hash_string (const void *vkey,
+		       uintptr_t key_size __attribute__ ((unused)))
+{
+  uintptr_t ret;
+  const String *key;
+  intgo len;
+  intgo i;
+  const byte *p;
+
+  ret = 5381;
+  key = (const String *) vkey;
+  len = key->len;
+  for (i = 0, p = key->str; i < len; i++, p++)
+    ret = ret * 33 + *p;
+  return ret;
+}
+
+/* A string equality function for a map.  */
+
+_Bool
+__go_type_equal_string (const void *vk1, const void *vk2,
+			uintptr_t key_size __attribute__ ((unused)))
+{
+  const String *k1;
+  const String *k2;
+
+  k1 = (const String *) vk1;
+  k2 = (const String *) vk2;
+  return __go_ptr_strings_equal (k1, k2);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-type.h b/third_party/gofrontend/libgo/runtime/go-type.h
new file mode 100644
index 0000000..74e8340
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-type.h
@@ -0,0 +1,333 @@
+/* go-type.h -- basic information for a Go type.
+
+   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.  */
+
+#ifndef LIBGO_GO_TYPE_H
+#define LIBGO_GO_TYPE_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "array.h"
+
+struct String;
+
+/* Many of the types in this file must match the data structures
+   generated by the compiler, and must also match the Go types which
+   appear in go/runtime/type.go and go/reflect/type.go.  */
+
+/* Type kinds.  These are used to get the type descriptor to use for
+   the type itself, when using unsafe.Typeof or unsafe.Reflect.  The
+   values here must match the values generated by the compiler (the
+   RUNTIME_TYPE_KIND_xxx values in gcc/go/types.h).  These are macros
+   rather than an enum to make it easy to change values in the future
+   and hard to get confused about it.
+
+   These correspond to the kind values used by the gc compiler.  */
+
+#define GO_BOOL 1
+#define GO_INT 2
+#define GO_INT8 3
+#define GO_INT16 4
+#define GO_INT32 5
+#define GO_INT64 6
+#define GO_UINT 7
+#define GO_UINT8 8
+#define GO_UINT16 9
+#define GO_UINT32 10
+#define GO_UINT64 11
+#define GO_UINTPTR 12
+#define GO_FLOAT32 13
+#define GO_FLOAT64 14
+#define GO_COMPLEX64 15
+#define GO_COMPLEX128 16
+#define GO_ARRAY 17
+#define GO_CHAN 18
+#define GO_FUNC 19
+#define GO_INTERFACE 20
+#define GO_MAP 21
+#define GO_PTR 22
+#define GO_SLICE 23
+#define GO_STRING 24
+#define GO_STRUCT 25
+#define GO_UNSAFE_POINTER 26
+
+#define GO_NO_POINTERS (1 << 7)
+
+#define GO_CODE_MASK 0x7f
+
+/* For each Go type the compiler constructs one of these structures.
+   This is used for type reflection, interfaces, maps, and reference
+   counting.  */
+
+struct __go_type_descriptor
+{
+  /* The type code for this type, one of the type kind values above.
+     This is used by unsafe.Reflect and unsafe.Typeof to determine the
+     type descriptor to return for this type itself.  It is also used
+     by reflect.toType when mapping to a reflect Type structure.  */
+  unsigned char __code;
+
+  /* The alignment in bytes of a variable with this type.  */
+  unsigned char __align;
+
+  /* The alignment in bytes of a struct field with this type.  */
+  unsigned char __field_align;
+
+  /* The size in bytes of a value of this type.  Note that all types
+     in Go have a fixed size.  */
+  uintptr_t __size;
+
+  /* The type's hash code.  */
+  uint32_t __hash;
+
+  /* This function takes a pointer to a value of this type, and the
+     size of this type, and returns a hash code.  We pass the size
+     explicitly becaues it means that we can share a single instance
+     of this function for various different types.  */
+  uintptr_t (*__hashfn) (const void *, uintptr_t);
+
+  /* This function takes two pointers to values of this type, and the
+     size of this type, and returns whether the values are equal.  */
+  _Bool (*__equalfn) (const void *, const void *, uintptr_t);
+
+  /* The garbage collection data. */
+  const uintptr *__gc;
+
+  /* A string describing this type.  This is only used for
+     debugging.  */
+  const struct String *__reflection;
+
+  /* A pointer to fields which are only used for some types.  */
+  const struct __go_uncommon_type *__uncommon;
+
+  /* The descriptor for the type which is a pointer to this type.
+     This may be NULL.  */
+  const struct __go_type_descriptor *__pointer_to_this;
+
+  /* A pointer to a zero value for this type.  All types will point to
+     the same zero value, go$zerovalue, which is a common variable so
+     that it will be large enough.  */
+  void *__zero;
+};
+
+/* The information we store for each method of a type.  */
+
+struct __go_method
+{
+  /* The name of the method.  */
+  const struct String *__name;
+
+  /* This is NULL for an exported method, or the name of the package
+     where it lives.  */
+  const struct String *__pkg_path;
+
+  /* The type of the method, without the receiver.  This will be a
+     function type.  */
+  const struct __go_type_descriptor *__mtype;
+
+  /* The type of the method, with the receiver.  This will be a
+     function type.  */
+  const struct __go_type_descriptor *__type;
+
+  /* A pointer to the code which implements the method.  This is
+     really a function pointer.  */
+  const void *__function;
+};
+
+/* Additional information that we keep for named types and for types
+   with methods.  */
+
+struct __go_uncommon_type
+{
+  /* The name of the type.  */
+  const struct String *__name;
+
+  /* The type's package.  This is NULL for builtin types.  */
+  const struct String *__pkg_path;
+
+  /* The type's methods.  This is an array of struct __go_method.  */
+  struct __go_open_array __methods;
+};
+
+/* The type descriptor for a fixed array type.  */
+
+struct __go_array_type
+{
+  /* Starts like all type descriptors.  */
+  struct __go_type_descriptor __common;
+
+  /* The element type.  */
+  struct __go_type_descriptor *__element_type;
+
+  /* The type of a slice of the same element type.  */
+  struct __go_type_descriptor *__slice_type;
+
+  /* The length of the array.  */
+  uintptr_t __len;
+};
+
+/* The type descriptor for a slice.  */
+
+struct __go_slice_type
+{
+  /* Starts like all other type descriptors.  */
+  struct __go_type_descriptor __common;
+
+  /* The element type.  */
+  struct __go_type_descriptor *__element_type;
+};
+
+/* The direction of a channel.  */
+#define CHANNEL_RECV_DIR 1
+#define CHANNEL_SEND_DIR 2
+#define CHANNEL_BOTH_DIR (CHANNEL_RECV_DIR | CHANNEL_SEND_DIR)
+
+/* The type descriptor for a channel.  */
+
+struct __go_channel_type
+{
+  /* Starts like all other type descriptors.  */
+  struct __go_type_descriptor __common;
+
+  /* The element type.  */
+  const struct __go_type_descriptor *__element_type;
+
+  /* The direction.  */
+  uintptr_t __dir;
+};
+
+/* The type descriptor for a function.  */
+
+struct __go_func_type
+{
+  /* Starts like all other type descriptors.  */
+  struct __go_type_descriptor __common;
+
+  /* Whether this is a varargs function.  If this is true, there will
+     be at least one parameter.  For "..." the last parameter type is
+     "interface{}".  For "... T" the last parameter type is "[]T".  */
+  _Bool __dotdotdot;
+
+  /* The input parameter types.  This is an array of pointers to
+     struct __go_type_descriptor.  */
+  struct __go_open_array __in;
+
+  /* The output parameter types.  This is an array of pointers to
+     struct __go_type_descriptor.  */
+  struct __go_open_array __out;
+};
+
+/* A method on an interface type.  */
+
+struct __go_interface_method
+{
+  /* The name of the method.  */
+  const struct String *__name;
+
+  /* This is NULL for an exported method, or the name of the package
+     where it lives.  */
+  const struct String *__pkg_path;
+
+  /* The real type of the method.  */
+  struct __go_type_descriptor *__type;
+};
+
+/* An interface type.  */
+
+struct __go_interface_type
+{
+  /* Starts like all other type descriptors.  */
+  struct __go_type_descriptor __common;
+
+  /* Array of __go_interface_method .  The methods are sorted in the
+     same order that they appear in the definition of the
+     interface.  */
+  struct __go_open_array __methods;
+};
+
+/* A map type.  */
+
+struct __go_map_type
+{
+  /* Starts like all other type descriptors.  */
+  struct __go_type_descriptor __common;
+
+  /* The map key type.  */
+  const struct __go_type_descriptor *__key_type;
+
+  /* The map value type.  */
+  const struct __go_type_descriptor *__val_type;
+};
+
+/* A pointer type.  */
+
+struct __go_ptr_type
+{
+  /* Starts like all other type descriptors.  */
+  struct __go_type_descriptor __common;
+
+  /* The type to which this points.  */
+  const struct __go_type_descriptor *__element_type;
+};
+
+/* A field in a structure.  */
+
+struct __go_struct_field
+{
+  /* The name of the field--NULL for an anonymous field.  */
+  const struct String *__name;
+
+  /* This is NULL for an exported method, or the name of the package
+     where it lives.  */
+  const struct String *__pkg_path;
+
+  /* The type of the field.  */
+  const struct __go_type_descriptor *__type;
+
+  /* The field tag, or NULL.  */
+  const struct String *__tag;
+
+  /* The offset of the field in the struct.  */
+  uintptr_t __offset;
+};
+
+/* A struct type.  */
+
+struct __go_struct_type
+{
+  /* Starts like all other type descriptors.  */
+  struct __go_type_descriptor __common;
+
+  /* An array of struct __go_struct_field.  */
+  struct __go_open_array __fields;
+};
+
+/* Whether a type descriptor is a pointer.  */
+
+static inline _Bool
+__go_is_pointer_type (const struct __go_type_descriptor *td)
+{
+  return td->__code == GO_PTR || td->__code == GO_UNSAFE_POINTER;
+}
+
+extern _Bool
+__go_type_descriptors_equal(const struct __go_type_descriptor*,
+			    const struct __go_type_descriptor*);
+
+extern uintptr_t __go_type_hash_identity (const void *, uintptr_t);
+extern _Bool __go_type_equal_identity (const void *, const void *, uintptr_t);
+extern uintptr_t __go_type_hash_string (const void *, uintptr_t);
+extern _Bool __go_type_equal_string (const void *, const void *, uintptr_t);
+extern uintptr_t __go_type_hash_float (const void *, uintptr_t);
+extern _Bool __go_type_equal_float (const void *, const void *, uintptr_t);
+extern uintptr_t __go_type_hash_complex (const void *, uintptr_t);
+extern _Bool __go_type_equal_complex (const void *, const void *, uintptr_t);
+extern uintptr_t __go_type_hash_interface (const void *, uintptr_t);
+extern _Bool __go_type_equal_interface (const void *, const void *, uintptr_t);
+extern uintptr_t __go_type_hash_error (const void *, uintptr_t);
+extern _Bool __go_type_equal_error (const void *, const void *, uintptr_t);
+
+#endif /* !defined(LIBGO_GO_TYPE_H) */
diff --git a/third_party/gofrontend/libgo/runtime/go-typedesc-equal.c b/third_party/gofrontend/libgo/runtime/go-typedesc-equal.c
new file mode 100644
index 0000000..f8474fc
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-typedesc-equal.c
@@ -0,0 +1,39 @@
+/* go-typedesc-equal.c -- return whether two type descriptors are equal.
+
+   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.  */
+
+#include "runtime.h"
+#include "go-string.h"
+#include "go-type.h"
+
+/* Compare type descriptors for equality.  This is necessary because
+   types may have different descriptors in different shared libraries.
+   Also, unnamed types may have multiple type descriptors even in a
+   single shared library.  */
+
+_Bool
+__go_type_descriptors_equal (const struct __go_type_descriptor *td1,
+			     const struct __go_type_descriptor *td2)
+{
+  if (td1 == td2)
+    return 1;
+  /* In a type switch we can get a NULL descriptor.  */
+  if (td1 == NULL || td2 == NULL)
+    return 0;
+  if (td1->__code != td2->__code || td1->__hash != td2->__hash)
+    return 0;
+  if (td1->__uncommon != NULL && td1->__uncommon->__name != NULL)
+    {
+      if (td2->__uncommon == NULL || td2->__uncommon->__name == NULL)
+	return 0;
+      return (__go_ptr_strings_equal (td1->__uncommon->__name,
+				      td2->__uncommon->__name)
+	      && __go_ptr_strings_equal (td1->__uncommon->__pkg_path,
+					 td2->__uncommon->__pkg_path));
+    }
+  if (td2->__uncommon != NULL && td2->__uncommon->__name != NULL)
+    return 0;
+  return __go_ptr_strings_equal (td1->__reflection, td2->__reflection);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-unsafe-new.c b/third_party/gofrontend/libgo/runtime/go-unsafe-new.c
new file mode 100644
index 0000000..7848642
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-unsafe-new.c
@@ -0,0 +1,25 @@
+/* go-unsafe-new.c -- unsafe.New function for Go.
+
+   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.  */
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* Implement unsafe_New, called from the reflect package.  */
+
+void *unsafe_New (const struct __go_type_descriptor *)
+  __asm__ (GOSYM_PREFIX "reflect.unsafe_New");
+
+/* The dynamic type of the argument will be a pointer to a type
+   descriptor.  */
+
+void *
+unsafe_New (const struct __go_type_descriptor *descriptor)
+{
+  return runtime_cnew (descriptor);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-unsafe-newarray.c b/third_party/gofrontend/libgo/runtime/go-unsafe-newarray.c
new file mode 100644
index 0000000..f5c5efc
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-unsafe-newarray.c
@@ -0,0 +1,25 @@
+/* go-unsafe-newarray.c -- unsafe.NewArray function for Go.
+
+   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.  */
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+#include "go-type.h"
+#include "interface.h"
+
+/* Implement unsafe_NewArray, called from the reflect package.  */
+
+void *unsafe_NewArray (const struct __go_type_descriptor *, intgo)
+  __asm__ (GOSYM_PREFIX "reflect.unsafe_NewArray");
+
+/* The dynamic type of the argument will be a pointer to a type
+   descriptor.  */
+
+void *
+unsafe_NewArray (const struct __go_type_descriptor *descriptor, intgo n)
+{
+  return runtime_cnewarray (descriptor, n);
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-unsafe-pointer.c b/third_party/gofrontend/libgo/runtime/go-unsafe-pointer.c
new file mode 100644
index 0000000..729e9a1
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-unsafe-pointer.c
@@ -0,0 +1,118 @@
+/* go-unsafe-pointer.c -- unsafe.Pointer type descriptor for Go.
+
+   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.  */
+
+#include <stddef.h>
+
+#include "runtime.h"
+#include "go-type.h"
+#include "mgc0.h"
+
+/* A pointer with a zero value.  */
+static void *zero_pointer;
+
+/* This file provides the type descriptor for the unsafe.Pointer type.
+   The unsafe package is defined by the compiler itself, which means
+   that there is no package to compile to define the type
+   descriptor.  */
+
+extern const struct __go_type_descriptor unsafe_Pointer
+  __asm__ (GOSYM_PREFIX "__go_tdn_unsafe.Pointer");
+
+extern const uintptr unsafe_Pointer_gc[]
+  __asm__ (GOSYM_PREFIX "__go_tdn_unsafe.Pointer$gc");
+
+/* Used to determine the field alignment.  */
+struct field_align
+{
+  char c;
+  void *p;
+};
+
+/* The reflection string.  */
+#define REFLECTION "unsafe.Pointer"
+static const String reflection_string =
+{
+  (const byte *) REFLECTION,
+  sizeof REFLECTION - 1
+};
+
+const uintptr unsafe_Pointer_gc[] = {sizeof(void*), GC_APTR, 0, GC_END};
+
+const struct __go_type_descriptor unsafe_Pointer =
+{
+  /* __code */
+  GO_UNSAFE_POINTER,
+  /* __align */
+  __alignof (void *),
+  /* __field_align */
+  offsetof (struct field_align, p) - 1,
+  /* __size */
+  sizeof (void *),
+  /* __hash */
+  78501163U,
+  /* __hashfn */
+  __go_type_hash_identity,
+  /* __equalfn */
+  __go_type_equal_identity,
+  /* __gc */
+  unsafe_Pointer_gc,
+  /* __reflection */
+  &reflection_string,
+  /* __uncommon */
+  NULL,
+  /* __pointer_to_this */
+  NULL,
+  /* __zero */
+  &zero_pointer
+};
+
+/* We also need the type descriptor for the pointer to unsafe.Pointer,
+   since any package which refers to that type descriptor will expect
+   it to be defined elsewhere.  */
+
+extern const struct __go_ptr_type pointer_unsafe_Pointer
+  __asm__ (GOSYM_PREFIX "__go_td_pN14_unsafe.Pointer");
+
+/* The reflection string.  */
+#define PREFLECTION "*unsafe.Pointer"
+static const String preflection_string =
+{
+  (const byte *) PREFLECTION,
+  sizeof PREFLECTION - 1,
+};
+
+const struct __go_ptr_type pointer_unsafe_Pointer =
+{
+  /* __common */
+  {
+    /* __code */
+    GO_PTR,
+    /* __align */
+    __alignof (void *),
+    /* __field_align */
+    offsetof (struct field_align, p) - 1,
+    /* __size */
+    sizeof (void *),
+    /* __hash */
+    1256018616U,
+    /* __hashfn */
+    __go_type_hash_identity,
+    /* __equalfn */
+    __go_type_equal_identity,
+    /* __gc */
+    unsafe_Pointer_gc,
+    /* __reflection */
+    &preflection_string,
+    /* __uncommon */
+    NULL,
+    /* __pointer_to_this */
+    NULL,
+    /* __zero */
+    &zero_pointer
+  },
+  /* __element_type */
+  &unsafe_Pointer
+};
diff --git a/third_party/gofrontend/libgo/runtime/go-unwind.c b/third_party/gofrontend/libgo/runtime/go-unwind.c
new file mode 100644
index 0000000..849256b
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-unwind.c
@@ -0,0 +1,443 @@
+/* go-unwind.c -- unwind the stack for panic/recover.
+
+   Copyright 2010 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 "config.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "unwind.h"
+#define NO_SIZE_OF_ENCODED_VALUE
+#include "unwind-pe.h"
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "go-defer.h"
+#include "go-panic.h"
+
+/* The code for a Go exception.  */
+
+#ifdef __ARM_EABI_UNWINDER__
+static const _Unwind_Exception_Class __go_exception_class =
+  { 'G', 'N', 'U', 'C', 'G', 'O', '\0', '\0' };
+#else
+static const _Unwind_Exception_Class __go_exception_class =
+  ((((((((_Unwind_Exception_Class) 'G' 
+         << 8 | (_Unwind_Exception_Class) 'N')
+        << 8 | (_Unwind_Exception_Class) 'U')
+       << 8 | (_Unwind_Exception_Class) 'C')
+      << 8 | (_Unwind_Exception_Class) 'G')
+     << 8 | (_Unwind_Exception_Class) 'O')
+    << 8 | (_Unwind_Exception_Class) '\0')
+   << 8 | (_Unwind_Exception_Class) '\0');
+#endif
+
+
+/* This function is called by exception handlers used when unwinding
+   the stack after a recovered panic.  The exception handler looks
+   like this:
+     __go_check_defer (frame);
+     return;
+   If we have not yet reached the frame we are looking for, we
+   continue unwinding.  */
+
+void
+__go_check_defer (_Bool *frame)
+{
+  G *g;
+  struct _Unwind_Exception *hdr;
+
+  g = runtime_g ();
+
+  if (g == NULL)
+    {
+      /* Some other language has thrown an exception.  We know there
+	 are no defer handlers, so there is nothing to do.  */
+    }
+  else if (g->is_foreign)
+    {
+      struct __go_panic_stack *n;
+      _Bool was_recovered;
+
+      /* Some other language has thrown an exception.  We need to run
+	 the local defer handlers.  If they call recover, we stop
+	 unwinding the stack here.  */
+
+      n = ((struct __go_panic_stack *)
+	   __go_alloc (sizeof (struct __go_panic_stack)));
+
+      n->__arg.__type_descriptor = NULL;
+      n->__arg.__object = NULL;
+      n->__was_recovered = 0;
+      n->__is_foreign = 1;
+      n->__next = g->panic;
+      g->panic = n;
+
+      while (1)
+	{
+	  struct __go_defer_stack *d;
+	  void (*pfn) (void *);
+
+	  d = g->defer;
+	  if (d == NULL || d->__frame != frame || d->__pfn == NULL)
+	    break;
+
+	  pfn = d->__pfn;
+	  g->defer = d->__next;
+
+	  (*pfn) (d->__arg);
+
+	  if (runtime_m () != NULL)
+	    runtime_freedefer (d);
+
+	  if (n->__was_recovered)
+	    {
+	      /* The recover function caught the panic thrown by some
+		 other language.  */
+	      break;
+	    }
+	}
+
+      was_recovered = n->__was_recovered;
+      g->panic = n->__next;
+      __go_free (n);
+
+      if (was_recovered)
+	{
+	  /* Just return and continue executing Go code.  */
+	  *frame = 1;
+	  return;
+	}
+
+      /* We are panicing through this function.  */
+      *frame = 0;
+    }
+  else if (g->defer != NULL
+	   && g->defer->__pfn == NULL
+	   && g->defer->__frame == frame)
+    {
+      struct __go_defer_stack *d;
+
+      /* This is the defer function which called recover.  Simply
+	 return to stop the stack unwind, and let the Go code continue
+	 to execute.  */
+      d = g->defer;
+      g->defer = d->__next;
+
+      if (runtime_m () != NULL)
+	runtime_freedefer (d);
+
+      /* We are returning from this function.  */
+      *frame = 1;
+
+      return;
+    }
+
+  /* This is some other defer function.  It was already run by the
+     call to panic, or just above.  Rethrow the exception.  */
+
+  hdr = (struct _Unwind_Exception *) g->exception;
+
+#ifdef LIBGO_SJLJ_EXCEPTIONS
+  _Unwind_SjLj_Resume_or_Rethrow (hdr);
+#else
+#if defined(_LIBUNWIND_STD_ABI)
+  _Unwind_RaiseException (hdr);
+#else
+  _Unwind_Resume_or_Rethrow (hdr);
+#endif
+#endif
+
+  /* Rethrowing the exception should not return.  */
+  abort();
+}
+
+/* Unwind function calls until we reach the one which used a defer
+   function which called recover.  Each function which uses a defer
+   statement will have an exception handler, as shown above.  */
+
+void
+__go_unwind_stack ()
+{
+  struct _Unwind_Exception *hdr;
+
+  hdr = ((struct _Unwind_Exception *)
+	 __go_alloc (sizeof (struct _Unwind_Exception)));
+  __builtin_memcpy (&hdr->exception_class, &__go_exception_class,
+		    sizeof hdr->exception_class);
+  hdr->exception_cleanup = NULL;
+
+  runtime_g ()->exception = hdr;
+
+#ifdef __USING_SJLJ_EXCEPTIONS__
+  _Unwind_SjLj_RaiseException (hdr);
+#else
+  _Unwind_RaiseException (hdr);
+#endif
+
+  /* Raising an exception should not return.  */
+  abort ();
+}
+
+/* The rest of this code is really similar to gcc/unwind-c.c and
+   libjava/exception.cc.  */
+
+typedef struct
+{
+  _Unwind_Ptr Start;
+  _Unwind_Ptr LPStart;
+  _Unwind_Ptr ttype_base;
+  const unsigned char *TType;
+  const unsigned char *action_table;
+  unsigned char ttype_encoding;
+  unsigned char call_site_encoding;
+} lsda_header_info;
+
+static const unsigned char *
+parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
+		   lsda_header_info *info)
+{
+  _uleb128_t tmp;
+  unsigned char lpstart_encoding;
+
+  info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
+
+  /* Find @LPStart, the base to which landing pad offsets are relative.  */
+  lpstart_encoding = *p++;
+  if (lpstart_encoding != DW_EH_PE_omit)
+    p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
+  else
+    info->LPStart = info->Start;
+
+  /* Find @TType, the base of the handler and exception spec type data.  */
+  info->ttype_encoding = *p++;
+  if (info->ttype_encoding != DW_EH_PE_omit)
+    {
+      p = read_uleb128 (p, &tmp);
+      info->TType = p + tmp;
+    }
+  else
+    info->TType = 0;
+
+  /* The encoding and length of the call-site table; the action table
+     immediately follows.  */
+  info->call_site_encoding = *p++;
+  p = read_uleb128 (p, &tmp);
+  info->action_table = p + tmp;
+
+  return p;
+}
+
+/* The personality function is invoked when unwinding the stack due to
+   a panic.  Its job is to find the cleanup and exception handlers to
+   run.  We can't split the stack here, because we won't be able to
+   unwind from that split.  */
+
+#ifdef __ARM_EABI_UNWINDER__
+/* ARM EABI personality routines must also unwind the stack.  */
+#define CONTINUE_UNWINDING \
+  do								\
+    {								\
+      if (__gnu_unwind_frame (ue_header, context) != _URC_OK)	\
+	return _URC_FAILURE;					\
+      return _URC_CONTINUE_UNWIND;				\
+    }								\
+  while (0)
+#else
+#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
+#endif
+
+#ifdef __USING_SJLJ_EXCEPTIONS__
+#define PERSONALITY_FUNCTION    __gccgo_personality_sj0
+#define __builtin_eh_return_data_regno(x) x
+#else
+#define PERSONALITY_FUNCTION    __gccgo_personality_v0
+#endif
+
+#ifdef __ARM_EABI_UNWINDER__
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *,
+		      struct _Unwind_Context *)
+  __attribute__ ((no_split_stack, flatten));
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (_Unwind_State state,
+		      struct _Unwind_Exception * ue_header,
+		      struct _Unwind_Context * context)
+#else
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
+		      struct _Unwind_Exception *, struct _Unwind_Context *)
+  __attribute__ ((no_split_stack, flatten));
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (int version,
+		      _Unwind_Action actions,
+		      _Unwind_Exception_Class exception_class,
+		      struct _Unwind_Exception *ue_header,
+		      struct _Unwind_Context *context)
+#endif
+{
+  lsda_header_info info;
+  const unsigned char *language_specific_data, *p, *action_record;
+  _Unwind_Ptr landing_pad, ip;
+  int ip_before_insn = 0;
+  _Bool is_foreign;
+  G *g;
+
+#ifdef __ARM_EABI_UNWINDER__
+  _Unwind_Action actions;
+
+  switch (state & _US_ACTION_MASK)
+    {
+    case _US_VIRTUAL_UNWIND_FRAME:
+      actions = _UA_SEARCH_PHASE;
+      break;
+
+    case _US_UNWIND_FRAME_STARTING:
+      actions = _UA_CLEANUP_PHASE;
+      if (!(state & _US_FORCE_UNWIND)
+	  && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13))
+	actions |= _UA_HANDLER_FRAME;
+      break;
+
+    case _US_UNWIND_FRAME_RESUME:
+      CONTINUE_UNWINDING;
+      break;
+
+    default:
+      abort();
+    }
+  actions |= state & _US_FORCE_UNWIND;
+
+  is_foreign = 0;
+
+  /* The dwarf unwinder assumes the context structure holds things like the
+     function and LSDA pointers.  The ARM implementation caches these in
+     the exception header (UCB).  To avoid rewriting everything we make the
+     virtual IP register point at the UCB.  */
+  ip = (_Unwind_Ptr) ue_header;
+  _Unwind_SetGR (context, 12, ip);
+#else
+  if (version != 1)
+    return _URC_FATAL_PHASE1_ERROR;
+
+  is_foreign = exception_class != __go_exception_class;
+#endif
+
+  language_specific_data = (const unsigned char *)
+    _Unwind_GetLanguageSpecificData (context);
+
+  /* If no LSDA, then there are no handlers or cleanups.  */
+  if (! language_specific_data)
+    CONTINUE_UNWINDING;
+
+  /* Parse the LSDA header.  */
+  p = parse_lsda_header (context, language_specific_data, &info);
+#ifdef HAVE_GETIPINFO
+  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
+#else
+  ip = _Unwind_GetIP (context);
+#endif
+  if (! ip_before_insn)
+    --ip;
+  landing_pad = 0;
+  action_record = NULL;
+
+#ifdef __USING_SJLJ_EXCEPTIONS__
+  /* The given "IP" is an index into the call-site table, with two
+     exceptions -- -1 means no-action, and 0 means terminate.  But
+     since we're using uleb128 values, we've not got random access
+     to the array.  */
+  if ((int) ip <= 0)
+    return _URC_CONTINUE_UNWIND;
+  else
+    {
+      _uleb128_t cs_lp, cs_action;
+      do
+	{
+	  p = read_uleb128 (p, &cs_lp);
+	  p = read_uleb128 (p, &cs_action);
+	}
+      while (--ip);
+
+      /* Can never have null landing pad for sjlj -- that would have
+	 been indicated by a -1 call site index.  */
+      landing_pad = (_Unwind_Ptr)cs_lp + 1;
+      if (cs_action)
+	action_record = info.action_table + cs_action - 1;
+      goto found_something;
+    }
+#else
+  /* Search the call-site table for the action associated with this IP.  */
+  while (p < info.action_table)
+    {
+      _Unwind_Ptr cs_start, cs_len, cs_lp;
+      _uleb128_t cs_action;
+
+      /* Note that all call-site encodings are "absolute" displacements.  */
+      p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
+      p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
+      p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
+      p = read_uleb128 (p, &cs_action);
+
+      /* The table is sorted, so if we've passed the ip, stop.  */
+      if (ip < info.Start + cs_start)
+	p = info.action_table;
+      else if (ip < info.Start + cs_start + cs_len)
+	{
+	  if (cs_lp)
+	    landing_pad = info.LPStart + cs_lp;
+	  if (cs_action)
+	    action_record = info.action_table + cs_action - 1;
+	  goto found_something;
+	}
+    }
+#endif
+
+  /* IP is not in table.  No associated cleanups.  */
+  CONTINUE_UNWINDING;
+
+ found_something:
+  if (landing_pad == 0)
+    {
+      /* IP is present, but has a null landing pad.
+	 No handler to be run.  */
+      CONTINUE_UNWINDING;
+    }
+
+  if (actions & _UA_SEARCH_PHASE)
+    {
+      if (action_record == 0)
+	{
+	  /* This indicates a cleanup rather than an exception
+	     handler.  */
+	  CONTINUE_UNWINDING;
+	}
+
+      return _URC_HANDLER_FOUND;
+    }
+
+  /* It's possible for g to be NULL here for an exception thrown by a
+     language other than Go.  */
+  g = runtime_g ();
+  if (g == NULL)
+    {
+      if (!is_foreign)
+	abort ();
+    }
+  else
+    {
+      g->exception = ue_header;
+      g->is_foreign = is_foreign;
+    }
+
+  _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
+		 (_Unwind_Ptr) ue_header);
+  _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0);
+  _Unwind_SetIP (context, landing_pad);
+  return _URC_INSTALL_CONTEXT;
+}
diff --git a/third_party/gofrontend/libgo/runtime/go-varargs.c b/third_party/gofrontend/libgo/runtime/go-varargs.c
new file mode 100644
index 0000000..705f55e
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/go-varargs.c
@@ -0,0 +1,53 @@
+/* go-varargs.c -- functions for calling C varargs functions.
+
+   Copyright 2013 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 "config.h"
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+/* The syscall package calls C functions.  The Go compiler can not
+   represent a C varargs functions.  On some systems it's important
+   that the declaration of a function match the call.  This function
+   holds non-varargs C functions that the Go code can call.  */
+
+int
+__go_open (char *path, int mode, mode_t perm)
+{
+  return open (path, mode, perm);
+}
+
+int
+__go_fcntl (int fd, int cmd, int arg)
+{
+  return fcntl (fd, cmd, arg);
+}
+
+int
+__go_fcntl_flock (int fd, int cmd, struct flock *arg)
+{
+  return fcntl (fd, cmd, arg);
+}
+
+#ifdef HAVE_OPEN64
+
+int
+__go_open64 (char *path, int mode, mode_t perm)
+{
+  return open64 (path, mode, perm);
+}
+
+#endif
+
+#ifdef HAVE_OPENAT
+
+int
+__go_openat (int fd, char *path, int flags, mode_t mode)
+{
+  return openat (fd, path, flags, mode);
+}
+
+#endif
diff --git a/third_party/gofrontend/libgo/runtime/goc2c.c b/third_party/gofrontend/libgo/runtime/goc2c.c
new file mode 100644
index 0000000..68281c3
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/goc2c.c
@@ -0,0 +1,689 @@
+// 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.
+
+// +build ignore
+
+/*
+ * Translate a .goc file into a .c file.  A .goc file is a combination
+ * of a limited form of Go with C.
+ */
+
+/*
+	package PACKAGENAME
+	{# line}
+	func NAME([NAME TYPE { , NAME TYPE }]) [(NAME TYPE { , NAME TYPE })] \{
+	  C code with proper brace nesting
+	\}
+*/
+
+/*
+ * We generate C code which implements the function such that it can
+ * be called from Go and executes the C code.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/* Package path to use.  */
+static const char *pkgpath;
+
+/* Package prefix to use.  */
+static const char *prefix;
+
+/* File and line number */
+static const char *file;
+static unsigned int lineno = 1;
+
+/* List of names and types.  */
+struct params {
+	struct params *next;
+	char *name;
+	char *type;
+};
+
+char *argv0;
+
+static void
+sysfatal(char *fmt, ...)
+{
+	char buf[256];
+	va_list arg;
+
+	va_start(arg, fmt);
+	vsnprintf(buf, sizeof buf, fmt, arg);
+	va_end(arg);
+
+	fprintf(stderr, "%s: %s\n", argv0 ? argv0 : "<prog>", buf);
+	exit(1);
+}
+
+/* Unexpected EOF.  */
+static void
+bad_eof(void)
+{
+	sysfatal("%s:%ud: unexpected EOF\n", file, lineno);
+}
+
+/* Out of memory.  */
+static void
+bad_mem(void)
+{
+	sysfatal("%s:%ud: out of memory\n", file, lineno);
+}
+
+/* Allocate memory without fail.  */
+static void *
+xmalloc(unsigned int size)
+{
+	void *ret = malloc(size);
+	if (ret == NULL)
+		bad_mem();
+	return ret;
+}
+
+/* Reallocate memory without fail.  */
+static void*
+xrealloc(void *buf, unsigned int size)
+{
+	void *ret = realloc(buf, size);
+	if (ret == NULL)
+		bad_mem();
+	return ret;
+}
+
+/* Copy a string into memory without fail.  */
+static char *
+xstrdup(const char *p)
+{
+	char *ret = xmalloc(strlen(p) + 1);
+	strcpy(ret, p);
+	return ret;
+}
+
+/* Free a list of parameters.  */
+static void
+free_params(struct params *p)
+{
+	while (p != NULL) {
+		struct params *next;
+
+		next = p->next;
+		free(p->name);
+		free(p->type);
+		free(p);
+		p = next;
+	}
+}
+
+/* Read a character, tracking lineno.  */
+static int
+getchar_update_lineno(void)
+{
+	int c;
+
+	c = getchar();
+	if (c == '\n')
+		++lineno;
+	return c;
+}
+
+/* Read a character, giving an error on EOF, tracking lineno.  */
+static int
+getchar_no_eof(void)
+{
+	int c;
+
+	c = getchar_update_lineno();
+	if (c == EOF)
+		bad_eof();
+	return c;
+}
+
+/* Read a character, skipping comments.  */
+static int
+getchar_skipping_comments(void)
+{
+	int c;
+
+	while (1) {
+		c = getchar_update_lineno();
+		if (c != '/')
+			return c;
+
+		c = getchar();
+		if (c == '/') {
+			do {
+				c = getchar_update_lineno();
+			} while (c != EOF && c != '\n');
+			return c;
+		} else if (c == '*') {
+			while (1) {
+				c = getchar_update_lineno();
+				if (c == EOF)
+					return EOF;
+				if (c == '*') {
+					do {
+						c = getchar_update_lineno();
+					} while (c == '*');
+					if (c == '/')
+						break;
+				}
+			}
+		} else {
+			ungetc(c, stdin);
+			return '/';
+		}
+	}
+}
+
+/*
+ * Read and return a token.  Tokens are string or character literals
+ * or else delimited by whitespace or by [(),{}].
+ * The latter are all returned as single characters.
+ */
+static char *
+read_token(void)
+{
+	int c, q;
+	char *buf;
+	unsigned int alc, off;
+	const char* delims = "(),{}";
+
+	while (1) {
+		c = getchar_skipping_comments();
+		if (c == EOF)
+			return NULL;
+		if (!isspace(c))
+			break;
+	}
+	alc = 16;
+	buf = xmalloc(alc + 1);
+	off = 0;
+	if(c == '"' || c == '\'') {
+		q = c;
+		buf[off] = c;
+		++off;
+		while (1) {
+			if (off+2 >= alc) { // room for c and maybe next char
+				alc *= 2;
+				buf = xrealloc(buf, alc + 1);
+			}
+			c = getchar_no_eof();
+			buf[off] = c;
+			++off;
+			if(c == q)
+				break;
+			if(c == '\\') {
+				buf[off] = getchar_no_eof();
+				++off;
+			}
+		}
+	} else if (strchr(delims, c) != NULL) {
+		buf[off] = c;
+		++off;
+	} else {
+		while (1) {
+			if (off >= alc) {
+				alc *= 2;
+				buf = xrealloc(buf, alc + 1);
+			}
+			buf[off] = c;
+			++off;
+			c = getchar_skipping_comments();
+			if (c == EOF)
+				break;
+			if (isspace(c) || strchr(delims, c) != NULL) {
+				if (c == '\n')
+					lineno--;
+				ungetc(c, stdin);
+				break;
+			}
+		}
+	}
+	buf[off] = '\0';
+	return buf;
+}
+
+/* Read a token, giving an error on EOF.  */
+static char *
+read_token_no_eof(void)
+{
+	char *token = read_token();
+	if (token == NULL)
+		bad_eof();
+	return token;
+}
+
+/* Read the package clause, and return the package name.  */
+static char *
+read_package(void)
+{
+	char *token;
+
+	token = read_token_no_eof();
+	if (token == NULL)
+		sysfatal("%s:%ud: no token\n", file, lineno);
+	if (strcmp(token, "package") != 0) {
+		sysfatal("%s:%ud: expected \"package\", got \"%s\"\n",
+			file, lineno, token);
+	}
+	return read_token_no_eof();
+}
+
+/* Read and copy preprocessor lines.  */
+static void
+read_preprocessor_lines(void)
+{
+	while (1) {
+		int c;
+
+		do {
+			c = getchar_skipping_comments();
+		} while (isspace(c));
+		if (c != '#') {
+			ungetc(c, stdin);
+			break;
+		}
+		putchar(c);
+		do {
+			c = getchar_update_lineno();
+			putchar(c);
+		} while (c != '\n');
+	}
+}
+
+/*
+ * Read a type in Go syntax and return a type in C syntax.  We only
+ * permit basic types and pointers.
+ */
+static char *
+read_type(void)
+{
+	char *p, *op, *q;
+	int pointer_count;
+	unsigned int len;
+
+	p = read_token_no_eof();
+	if (*p != '*') {
+		/* Convert the Go type "int" to the C type "intgo",
+		   and similarly for "uint".  */
+		if (strcmp(p, "int") == 0)
+			return xstrdup("intgo");
+		else if (strcmp(p, "uint") == 0)
+			return xstrdup("uintgo");
+		return p;
+	}
+	op = p;
+	pointer_count = 0;
+	while (*p == '*') {
+		++pointer_count;
+		++p;
+	}
+
+	/* Convert the Go type "int" to the C type "intgo", and
+	   similarly for "uint".  */
+	if (strcmp(p, "int") == 0)
+	  p = (char *) "intgo";
+	else if (strcmp(p, "uint") == 0)
+	  p = (char *) "uintgo";
+
+	len = strlen(p);
+	q = xmalloc(len + pointer_count + 1);
+	memcpy(q, p, len);
+	while (pointer_count > 0) {
+		q[len] = '*';
+		++len;
+		--pointer_count;
+	}
+	q[len] = '\0';
+	free(op);
+	return q;
+}
+
+/*
+ * Read a list of parameters.  Each parameter is a name and a type.
+ * The list ends with a ')'.  We have already read the '('.
+ */
+static struct params *
+read_params()
+{
+	char *token;
+	struct params *ret, **pp, *p;
+
+	ret = NULL;
+	pp = &ret;
+	token = read_token_no_eof();
+	if (strcmp(token, ")") != 0) {
+		while (1) {
+			p = xmalloc(sizeof(struct params));
+			p->name = token;
+			p->type = read_type();
+			p->next = NULL;
+			*pp = p;
+			pp = &p->next;
+
+			token = read_token_no_eof();
+			if (strcmp(token, ",") != 0)
+				break;
+			token = read_token_no_eof();
+		}
+	}
+	if (strcmp(token, ")") != 0) {
+		sysfatal("%s:%ud: expected '('\n",
+			file, lineno);
+	}
+	return ret;
+}
+
+/*
+ * Read a function header.  This reads up to and including the initial
+ * '{' character.  Returns 1 if it read a header, 0 at EOF.
+ */
+static int
+read_func_header(char **name, struct params **params, struct params **rets)
+{
+	int lastline;
+	char *token;
+
+	lastline = -1;
+	while (1) {
+		token = read_token();
+		if (token == NULL)
+			return 0;
+		if (strcmp(token, "func") == 0) {
+			if(lastline != -1)
+				printf("\n");
+			break;
+		}
+		if (lastline != lineno) {
+			if (lastline == lineno-1)
+				printf("\n");
+			else
+				printf("\n#line %d \"%s\"\n", lineno, file);
+			lastline = lineno;
+		}
+		printf("%s ", token);
+	}
+
+	*name = read_token_no_eof();
+
+	token = read_token();
+	if (token == NULL || strcmp(token, "(") != 0) {
+		sysfatal("%s:%ud: expected \"(\"\n",
+			file, lineno);
+	}
+	*params = read_params();
+
+	token = read_token();
+	if (token == NULL || strcmp(token, "(") != 0)
+		*rets = NULL;
+	else {
+		*rets = read_params();
+		token = read_token();
+	}
+	if (token == NULL || strcmp(token, "{") != 0) {
+		sysfatal("%s:%ud: expected \"{\"\n",
+			file, lineno);
+	}
+	return 1;
+}
+
+/* Write out parameters.  */
+static void
+write_params(struct params *params, int *first)
+{
+	struct params *p;
+
+	for (p = params; p != NULL; p = p->next) {
+		if (*first)
+			*first = 0;
+		else
+			printf(", ");
+		printf("%s %s", p->type, p->name);
+	}
+}
+
+/* Define the gcc function return type if necessary.  */
+static void
+define_gcc_return_type(char *package, char *name, struct params *rets)
+{
+	struct params *p;
+
+	if (rets == NULL || rets->next == NULL)
+		return;
+	printf("struct %s_%s_ret {\n", package, name);
+	for (p = rets; p != NULL; p = p->next)
+		printf("  %s %s;\n", p->type, p->name);
+	printf("};\n");
+}
+
+/* Write out the gcc function return type.  */
+static void
+write_gcc_return_type(char *package, char *name, struct params *rets)
+{
+	if (rets == NULL)
+		printf("void");
+	else if (rets->next == NULL)
+		printf("%s", rets->type);
+	else
+		printf("struct %s_%s_ret", package, name);
+}
+
+/* Write out a gcc function header.  */
+static void
+write_gcc_func_header(char *package, char *name, struct params *params,
+		      struct params *rets)
+{
+	int first;
+	struct params *p;
+
+	define_gcc_return_type(package, name, rets);
+	write_gcc_return_type(package, name, rets);
+	printf(" %s_%s(", package, name);
+	first = 1;
+	write_params(params, &first);
+	printf(") __asm__ (GOSYM_PREFIX \"");
+	if (pkgpath != NULL)
+	  printf("%s", pkgpath);
+	else if (prefix != NULL)
+	  printf("%s.%s", prefix, package);
+	else
+	  printf("%s", package);
+	printf(".%s\");\n", name);
+	write_gcc_return_type(package, name, rets);
+	printf(" %s_%s(", package, name);
+	first = 1;
+	write_params(params, &first);
+	printf(")\n{\n");
+	for (p = rets; p != NULL; p = p->next)
+		printf("  %s %s;\n", p->type, p->name);
+}
+
+/* Write out a gcc function trailer.  */
+static void
+write_gcc_func_trailer(char *package, char *name, struct params *rets)
+{
+	if (rets == NULL)
+		;
+	else if (rets->next == NULL)
+		printf("return %s;\n", rets->name);
+	else {
+		struct params *p;
+
+		printf("  {\n    struct %s_%s_ret __ret;\n", package, name);
+		for (p = rets; p != NULL; p = p->next)
+			printf("    __ret.%s = %s;\n", p->name, p->name);
+		printf("    return __ret;\n  }\n");
+	}
+	printf("}\n");
+}
+
+/* Write out a function header.  */
+static void
+write_func_header(char *package, char *name, struct params *params, 
+		  struct params *rets)
+{
+	write_gcc_func_header(package, name, params, rets);
+	printf("#line %d \"%s\"\n", lineno, file);
+}
+
+/* Write out a function trailer.  */
+static void
+write_func_trailer(char *package, char *name,
+		   struct params *rets)
+{
+	write_gcc_func_trailer(package, name, rets);
+}
+
+/*
+ * Read and write the body of the function, ending in an unnested }
+ * (which is read but not written).
+ */
+static void
+copy_body(void)
+{
+	int nesting = 0;
+	while (1) {
+		int c;
+
+		c = getchar_no_eof();
+		if (c == '}' && nesting == 0)
+			return;
+		putchar(c);
+		switch (c) {
+		default:
+			break;
+		case '{':
+			++nesting;
+			break;
+		case '}':
+			--nesting;
+			break;
+		case '/':
+			c = getchar_update_lineno();
+			putchar(c);
+			if (c == '/') {
+				do {
+					c = getchar_no_eof();
+					putchar(c);
+				} while (c != '\n');
+			} else if (c == '*') {
+				while (1) {
+					c = getchar_no_eof();
+					putchar(c);
+					if (c == '*') {
+						do {
+							c = getchar_no_eof();
+							putchar(c);
+						} while (c == '*');
+						if (c == '/')
+							break;
+					}
+				}
+			}
+			break;
+		case '"':
+		case '\'':
+			{
+				int delim = c;
+				do {
+					c = getchar_no_eof();
+					putchar(c);
+					if (c == '\\') {
+						c = getchar_no_eof();
+						putchar(c);
+						c = '\0';
+					}
+				} while (c != delim);
+			}
+			break;
+		}
+	}
+}
+
+/* Process the entire file.  */
+static void
+process_file(void)
+{
+	char *package, *name;
+	struct params *params, *rets;
+
+	package = read_package();
+	read_preprocessor_lines();
+	while (read_func_header(&name, &params, &rets)) {
+		char *p;
+		char *pkg;
+		char *nm;
+
+		p = strchr(name, '.');
+		if (p == NULL) {
+			pkg = package;
+			nm = name;
+		} else {
+			pkg = name;
+			nm = p + 1;
+			*p = '\0';
+		}
+		write_func_header(pkg, nm, params, rets);
+		copy_body();
+		write_func_trailer(pkg, nm, rets);
+		free(name);
+		free_params(params);
+		free_params(rets);
+	}
+	free(package);
+}
+
+static void
+usage(void)
+{
+	sysfatal("Usage: goc2c [--go-pkgpath PKGPATH] [--go-prefix PREFIX] [file]\n");
+}
+
+int
+main(int argc, char **argv)
+{
+	char *goarch;
+
+	argv0 = argv[0];
+	while(argc > 1 && argv[1][0] == '-') {
+		if(strcmp(argv[1], "-") == 0)
+			break;
+		if (strcmp(argv[1], "--go-pkgpath") == 0 && argc > 2) {
+			pkgpath = argv[2];
+			argc--;
+			argv++;
+		} else if (strcmp(argv[1], "--go-prefix") == 0 && argc > 2) {
+			prefix = argv[2];
+			argc--;
+			argv++;
+		} else
+			usage();
+		argc--;
+		argv++;
+	}
+
+	if(argc <= 1 || strcmp(argv[1], "-") == 0) {
+		file = "<stdin>";
+		process_file();
+		exit(0);
+	}
+
+	if(argc > 2)
+		usage();
+
+	file = argv[1];
+	if(freopen(file, "r", stdin) == 0) {
+		sysfatal("open %s: %r\n", file);
+	}
+
+	printf("// AUTO-GENERATED by autogen.sh; DO NOT EDIT\n\n");
+	process_file();
+	exit(0);
+}
diff --git a/third_party/gofrontend/libgo/runtime/heapdump.c b/third_party/gofrontend/libgo/runtime/heapdump.c
new file mode 100644
index 0000000..35990bb
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/heapdump.c
@@ -0,0 +1,776 @@
+// Copyright 2014 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.
+
+// Implementation of runtime/debug.WriteHeapDump.  Writes all
+// objects in the heap plus additional info (roots, threads,
+// finalizers, etc.) to a file.
+
+// The format of the dumped file is described at
+// http://code.google.com/p/go-wiki/wiki/heapdump13
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+#include "mgc0.h"
+#include "go-type.h"
+#include "go-defer.h"
+#include "go-panic.h"
+
+#define hash __hash
+#define KindNoPointers GO_NO_POINTERS
+
+enum {
+	FieldKindEol = 0,
+	FieldKindPtr = 1,
+	FieldKindString = 2,
+	FieldKindSlice = 3,
+	FieldKindIface = 4,
+	FieldKindEface = 5,
+
+	TagEOF = 0,
+	TagObject = 1,
+	TagOtherRoot = 2,
+	TagType = 3,
+	TagGoRoutine = 4,
+	TagStackFrame = 5,
+	TagParams = 6,
+	TagFinalizer = 7,
+	TagItab = 8,
+	TagOSThread = 9,
+	TagMemStats = 10,
+	TagQueuedFinalizer = 11,
+	TagData = 12,
+	TagBss = 13,
+	TagDefer = 14,
+	TagPanic = 15,
+	TagMemProf = 16,
+	TagAllocSample = 17,
+
+	TypeInfo_Conservative = 127,
+};
+
+// static uintptr* playgcprog(uintptr offset, uintptr *prog, void (*callback)(void*,uintptr,uintptr), void *arg);
+// static void dumpfields(uintptr *prog);
+static void dumpefacetypes(void *obj, uintptr size, const Type *type, uintptr kind);
+
+// fd to write the dump to.
+static uintptr dumpfd;
+
+// buffer of pending write data
+enum {
+	BufSize = 4096,
+};
+static byte buf[BufSize];
+static uintptr nbuf;
+
+static void
+hwrite(const byte *data, uintptr len)
+{
+	if(len + nbuf <= BufSize) {
+		runtime_memmove(buf + nbuf, data, len);
+		nbuf += len;
+		return;
+	}
+	runtime_write(dumpfd, buf, nbuf);
+	if(len >= BufSize) {
+		runtime_write(dumpfd, data, len);
+		nbuf = 0;
+	} else {
+		runtime_memmove(buf, data, len);
+		nbuf = len;
+	}
+}
+
+static void
+flush(void)
+{
+	runtime_write(dumpfd, buf, nbuf);
+	nbuf = 0;
+}
+
+// Cache of types that have been serialized already.
+// We use a type's hash field to pick a bucket.
+// Inside a bucket, we keep a list of types that
+// have been serialized so far, most recently used first.
+// Note: when a bucket overflows we may end up
+// serializing a type more than once.  That's ok.
+enum {
+	TypeCacheBuckets = 256, // must be a power of 2
+	TypeCacheAssoc = 4,
+};
+typedef struct TypeCacheBucket TypeCacheBucket;
+struct TypeCacheBucket {
+	const Type *t[TypeCacheAssoc];
+};
+static TypeCacheBucket typecache[TypeCacheBuckets];
+
+// dump a uint64 in a varint format parseable by encoding/binary
+static void
+dumpint(uint64 v)
+{
+	byte buf[10];
+	int32 n;
+	n = 0;
+	while(v >= 0x80) {
+		buf[n++] = v | 0x80;
+		v >>= 7;
+	}
+	buf[n++] = v;
+	hwrite(buf, n);
+}
+
+static void
+dumpbool(bool b)
+{
+	dumpint(b ? 1 : 0);
+}
+
+// dump varint uint64 length followed by memory contents
+static void
+dumpmemrange(const byte *data, uintptr len)
+{
+	dumpint(len);
+	hwrite(data, len);
+}
+
+static void
+dumpstr(String s)
+{
+	dumpmemrange(s.str, s.len);
+}
+
+static void
+dumpcstr(const int8 *c)
+{
+	dumpmemrange((const byte*)c, runtime_findnull((const byte*)c));
+}
+
+// dump information for a type
+static void
+dumptype(const Type *t)
+{
+	TypeCacheBucket *b;
+	int32 i, j;
+
+	if(t == nil) {
+		return;
+	}
+
+	// If we've definitely serialized the type before,
+	// no need to do it again.
+	b = &typecache[t->hash & (TypeCacheBuckets-1)];
+	if(t == b->t[0]) return;
+	for(i = 1; i < TypeCacheAssoc; i++) {
+		if(t == b->t[i]) {
+			// Move-to-front
+			for(j = i; j > 0; j--) {
+				b->t[j] = b->t[j-1];
+			}
+			b->t[0] = t;
+			return;
+		}
+	}
+	// Might not have been dumped yet.  Dump it and
+	// remember we did so.
+	for(j = TypeCacheAssoc-1; j > 0; j--) {
+		b->t[j] = b->t[j-1];
+	}
+	b->t[0] = t;
+	
+	// dump the type
+	dumpint(TagType);
+	dumpint((uintptr)t);
+	dumpint(t->__size);
+	if(t->__uncommon == nil || t->__uncommon->__pkg_path == nil || t->__uncommon->__name == nil) {
+		dumpstr(*t->__reflection);
+	} else {
+		dumpint(t->__uncommon->__pkg_path->len + 1 + t->__uncommon->__name->len);
+		hwrite(t->__uncommon->__pkg_path->str, t->__uncommon->__pkg_path->len);
+		hwrite((const byte*)".", 1);
+		hwrite(t->__uncommon->__name->str, t->__uncommon->__name->len);
+	}
+	dumpbool(t->__size > PtrSize || (t->__code & KindNoPointers) == 0);
+	// dumpfields((uintptr*)t->gc + 1);
+}
+
+// returns true if object is scannable
+static bool
+scannable(byte *obj)
+{
+	uintptr *b, off, shift;
+
+	off = (uintptr*)obj - (uintptr*)runtime_mheap.arena_start;  // word offset
+	b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+	shift = off % wordsPerBitmapWord;
+	return ((*b >> shift) & bitScan) != 0;
+}
+
+// dump an object
+static void
+dumpobj(byte *obj, uintptr size, const Type *type, uintptr kind)
+{
+	if(type != nil) {
+		dumptype(type);
+		dumpefacetypes(obj, size, type, kind);
+	}
+
+	dumpint(TagObject);
+	dumpint((uintptr)obj);
+	dumpint((uintptr)type);
+	dumpint(kind);
+	dumpmemrange(obj, size);
+}
+
+static void
+dumpotherroot(const char *description, byte *to)
+{
+	dumpint(TagOtherRoot);
+	dumpcstr((const int8 *)description);
+	dumpint((uintptr)to);
+}
+
+static void
+dumpfinalizer(byte *obj, FuncVal *fn, const FuncType* ft, const PtrType *ot)
+{
+	dumpint(TagFinalizer);
+	dumpint((uintptr)obj);
+	dumpint((uintptr)fn);
+	dumpint((uintptr)fn->fn);
+	dumpint((uintptr)ft);
+	dumpint((uintptr)ot);
+}
+
+typedef struct ChildInfo ChildInfo;
+struct ChildInfo {
+	// Information passed up from the callee frame about
+	// the layout of the outargs region.
+	uintptr argoff;     // where the arguments start in the frame
+	uintptr arglen;     // size of args region
+	BitVector args;    // if args.n >= 0, pointer map of args region
+
+	byte *sp;           // callee sp
+	uintptr depth;      // depth in call stack (0 == most recent)
+};
+
+static void
+dumpgoroutine(G *gp)
+{
+	// ChildInfo child;
+	Defer *d;
+	Panic *p;
+
+	dumpint(TagGoRoutine);
+	dumpint((uintptr)gp);
+	dumpint((uintptr)0);
+	dumpint(gp->goid);
+	dumpint(gp->gopc);
+	dumpint(gp->status);
+	dumpbool(gp->issystem);
+	dumpbool(gp->isbackground);
+	dumpint(gp->waitsince);
+	dumpcstr((const int8 *)gp->waitreason);
+	dumpint((uintptr)0);
+	dumpint((uintptr)gp->m);
+	dumpint((uintptr)gp->defer);
+	dumpint((uintptr)gp->panic);
+
+	// dump stack
+	// child.args.n = -1;
+	// child.arglen = 0;
+	// child.sp = nil;
+	// child.depth = 0;
+	// if(!ScanStackByFrames)
+	// 	runtime_throw("need frame info to dump stacks");
+	// runtime_gentraceback(pc, sp, lr, gp, 0, nil, 0x7fffffff, dumpframe, &child, false);
+
+	// dump defer & panic records
+	for(d = gp->defer; d != nil; d = d->__next) {
+		dumpint(TagDefer);
+		dumpint((uintptr)d);
+		dumpint((uintptr)gp);
+		dumpint((uintptr)d->__arg);
+		dumpint((uintptr)d->__frame);
+		dumpint((uintptr)d->__pfn);
+		dumpint((uintptr)0);
+		dumpint((uintptr)d->__next);
+	}
+	for (p = gp->panic; p != nil; p = p->__next) {
+		dumpint(TagPanic);
+		dumpint((uintptr)p);
+		dumpint((uintptr)gp);
+		dumpint((uintptr)p->__arg.__type_descriptor);
+		dumpint((uintptr)p->__arg.__object);
+		dumpint((uintptr)0);
+		dumpint((uintptr)p->__next);
+	}
+}
+
+static void
+dumpgs(void)
+{
+	G *gp;
+	uint32 i;
+
+	// goroutines & stacks
+	for(i = 0; i < runtime_allglen; i++) {
+		gp = runtime_allg[i];
+		switch(gp->status){
+		default:
+			runtime_printf("unexpected G.status %d\n", gp->status);
+			runtime_throw("mark - bad status");
+		case Gdead:
+			break;
+		case Grunnable:
+		case Gsyscall:
+		case Gwaiting:
+			dumpgoroutine(gp);
+			break;
+		}
+	}
+}
+
+static void
+finq_callback(FuncVal *fn, void *obj, const FuncType *ft, const PtrType *ot)
+{
+	dumpint(TagQueuedFinalizer);
+	dumpint((uintptr)obj);
+	dumpint((uintptr)fn);
+	dumpint((uintptr)fn->fn);
+	dumpint((uintptr)ft);
+	dumpint((uintptr)ot);
+}
+
+
+static void
+dumproots(void)
+{
+	MSpan *s, **allspans;
+	uint32 spanidx;
+	Special *sp;
+	SpecialFinalizer *spf;
+	byte *p;
+
+	// data segment
+	// dumpint(TagData);
+	// dumpint((uintptr)data);
+	// dumpmemrange(data, edata - data);
+	// dumpfields((uintptr*)gcdata + 1);
+
+	// bss segment
+	// dumpint(TagBss);
+	// dumpint((uintptr)bss);
+	// dumpmemrange(bss, ebss - bss);
+	// dumpfields((uintptr*)gcbss + 1);
+	
+	// MSpan.types
+	allspans = runtime_mheap.allspans;
+	for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) {
+		s = allspans[spanidx];
+		if(s->state == MSpanInUse) {
+			// The garbage collector ignores type pointers stored in MSpan.types:
+			//  - Compiler-generated types are stored outside of heap.
+			//  - The reflect package has runtime-generated types cached in its data structures.
+			//    The garbage collector relies on finding the references via that cache.
+			switch(s->types.compression) {
+			case MTypes_Empty:
+			case MTypes_Single:
+				break;
+			case MTypes_Words:
+			case MTypes_Bytes:
+				dumpotherroot("runtime type info", (byte*)s->types.data);
+				break;
+			}
+
+			// Finalizers
+			for(sp = s->specials; sp != nil; sp = sp->next) {
+				if(sp->kind != KindSpecialFinalizer)
+					continue;
+				spf = (SpecialFinalizer*)sp;
+				p = (byte*)((s->start << PageShift) + spf->special.offset);
+				dumpfinalizer(p, spf->fn, spf->ft, spf->ot);
+			}
+		}
+	}
+
+	// Finalizer queue
+	runtime_iterate_finq(finq_callback);
+}
+
+// Bit vector of free marks.
+// Needs to be as big as the largest number of objects per span.
+static byte hfree[PageSize/8];
+
+static void
+dumpobjs(void)
+{
+	uintptr i, j, size, n, off, shift, *bitp, bits, ti, kind;
+	MSpan *s;
+	MLink *l;
+	byte *p;
+	const Type *t;
+
+	for(i = 0; i < runtime_mheap.nspan; i++) {
+		s = runtime_mheap.allspans[i];
+		if(s->state != MSpanInUse)
+			continue;
+		p = (byte*)(s->start << PageShift);
+		size = s->elemsize;
+		n = (s->npages << PageShift) / size;
+		if(n > PageSize/8)
+			runtime_throw("free array doesn't have enough entries");
+		for(l = s->freelist; l != nil; l = l->next) {
+			hfree[((byte*)l - p) / size] = true;
+		}
+		for(j = 0; j < n; j++, p += size) {
+			if(hfree[j]) {
+				hfree[j] = false;
+				continue;
+			}
+			off = (uintptr*)p - (uintptr*)runtime_mheap.arena_start;
+			bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+			shift = off % wordsPerBitmapWord;
+			bits = *bitp >> shift;
+
+			// Skip FlagNoGC allocations (stacks)
+			if((bits & bitAllocated) == 0)
+				continue;
+
+			// extract type and kind
+			ti = runtime_gettype(p);
+			t = (Type*)(ti & ~(uintptr)(PtrSize-1));
+			kind = ti & (PtrSize-1);
+			
+			// dump it
+			if(kind == TypeInfo_Chan)
+				t = ((const ChanType*)t)->__element_type; // use element type for chan encoding
+			if(t == nil && scannable(p))
+				kind = TypeInfo_Conservative; // special kind for conservatively scanned objects
+			dumpobj(p, size, t, kind);
+		}
+	}
+}
+
+static void
+dumpparams(void)
+{
+	byte *x;
+
+	dumpint(TagParams);
+	x = (byte*)1;
+	if(*(byte*)&x == 1)
+		dumpbool(false); // little-endian ptrs
+	else
+		dumpbool(true); // big-endian ptrs
+	dumpint(PtrSize);
+	dumpint(runtime_Hchansize);
+	dumpint((uintptr)runtime_mheap.arena_start);
+	dumpint((uintptr)runtime_mheap.arena_used);
+	dumpint(0);
+	dumpcstr((const int8 *)"");
+	dumpint(runtime_ncpu);
+}
+
+static void
+dumpms(void)
+{
+	M *mp;
+
+	for(mp = runtime_allm; mp != nil; mp = mp->alllink) {
+		dumpint(TagOSThread);
+		dumpint((uintptr)mp);
+		dumpint(mp->id);
+		dumpint(0);
+	}
+}
+
+static void
+dumpmemstats(void)
+{
+	int32 i;
+
+	dumpint(TagMemStats);
+	dumpint(mstats.alloc);
+	dumpint(mstats.total_alloc);
+	dumpint(mstats.sys);
+	dumpint(mstats.nlookup);
+	dumpint(mstats.nmalloc);
+	dumpint(mstats.nfree);
+	dumpint(mstats.heap_alloc);
+	dumpint(mstats.heap_sys);
+	dumpint(mstats.heap_idle);
+	dumpint(mstats.heap_inuse);
+	dumpint(mstats.heap_released);
+	dumpint(mstats.heap_objects);
+	dumpint(mstats.stacks_inuse);
+	dumpint(mstats.stacks_sys);
+	dumpint(mstats.mspan_inuse);
+	dumpint(mstats.mspan_sys);
+	dumpint(mstats.mcache_inuse);
+	dumpint(mstats.mcache_sys);
+	dumpint(mstats.buckhash_sys);
+	dumpint(mstats.gc_sys);
+	dumpint(mstats.other_sys);
+	dumpint(mstats.next_gc);
+	dumpint(mstats.last_gc);
+	dumpint(mstats.pause_total_ns);
+	for(i = 0; i < 256; i++)
+		dumpint(mstats.pause_ns[i]);
+	dumpint(mstats.numgc);
+}
+
+static void
+dumpmemprof_callback(Bucket *b, uintptr nstk, Location *stk, uintptr size, uintptr allocs, uintptr frees)
+{
+	uintptr i, pc;
+	byte buf[20];
+
+	dumpint(TagMemProf);
+	dumpint((uintptr)b);
+	dumpint(size);
+	dumpint(nstk);
+	for(i = 0; i < nstk; i++) {
+		pc = stk[i].pc;
+		if(stk[i].function.len == 0) {
+			runtime_snprintf(buf, sizeof(buf), "%X", (uint64)pc);
+			dumpcstr((int8*)buf);
+			dumpcstr((const int8*)"?");
+			dumpint(0);
+		} else {
+			dumpstr(stk[i].function);
+			dumpstr(stk[i].filename);
+			dumpint(stk[i].lineno);
+		}
+	}
+	dumpint(allocs);
+	dumpint(frees);
+}
+
+static void
+dumpmemprof(void)
+{
+	MSpan *s, **allspans;
+	uint32 spanidx;
+	Special *sp;
+	SpecialProfile *spp;
+	byte *p;
+
+	runtime_iterate_memprof(dumpmemprof_callback);
+
+	allspans = runtime_mheap.allspans;
+	for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) {
+		s = allspans[spanidx];
+		if(s->state != MSpanInUse)
+			continue;
+		for(sp = s->specials; sp != nil; sp = sp->next) {
+			if(sp->kind != KindSpecialProfile)
+				continue;
+			spp = (SpecialProfile*)sp;
+			p = (byte*)((s->start << PageShift) + spp->special.offset);
+			dumpint(TagAllocSample);
+			dumpint((uintptr)p);
+			dumpint((uintptr)spp->b);
+		}
+	}
+}
+
+static void
+mdump(G *gp)
+{
+	const byte *hdr;
+	uintptr i;
+	MSpan *s;
+
+	// make sure we're done sweeping
+	for(i = 0; i < runtime_mheap.nspan; i++) {
+		s = runtime_mheap.allspans[i];
+		if(s->state == MSpanInUse)
+			runtime_MSpan_EnsureSwept(s);
+	}
+
+	runtime_memclr((byte*)&typecache[0], sizeof(typecache));
+	hdr = (const byte*)"go1.3 heap dump\n";
+	hwrite(hdr, runtime_findnull(hdr));
+	dumpparams();
+	dumpobjs();
+	dumpgs();
+	dumpms();
+	dumproots();
+	dumpmemstats();
+	dumpmemprof();
+	dumpint(TagEOF);
+	flush();
+
+	gp->param = nil;
+	gp->status = Grunning;
+	runtime_gogo(gp);
+}
+
+void runtime_debug_WriteHeapDump(uintptr)
+  __asm__(GOSYM_PREFIX "runtime_debug.WriteHeapDump");
+
+void
+runtime_debug_WriteHeapDump(uintptr fd)
+{
+	M *m;
+	G *g;
+
+	// Stop the world.
+	runtime_semacquire(&runtime_worldsema, false);
+	m = runtime_m();
+	m->gcing = 1;
+	m->locks++;
+	runtime_stoptheworld();
+
+	// Update stats so we can dump them.
+	// As a side effect, flushes all the MCaches so the MSpan.freelist
+	// lists contain all the free objects.
+	runtime_updatememstats(nil);
+
+	// Set dump file.
+	dumpfd = fd;
+
+	// Call dump routine on M stack.
+	g = runtime_g();
+	g->status = Gwaiting;
+	g->waitreason = "dumping heap";
+	runtime_mcall(mdump);
+
+	// Reset dump file.
+	dumpfd = 0;
+
+	// Start up the world again.
+	m->gcing = 0;
+	runtime_semrelease(&runtime_worldsema);
+	runtime_starttheworld();
+	m->locks--;
+}
+
+// Runs the specified gc program.  Calls the callback for every
+// pointer-like field specified by the program and passes to the
+// callback the kind and offset of that field within the object.
+// offset is the offset in the object of the start of the program.
+// Returns a pointer to the opcode that ended the gc program (either
+// GC_END or GC_ARRAY_NEXT).
+/*
+static uintptr*
+playgcprog(uintptr offset, uintptr *prog, void (*callback)(void*,uintptr,uintptr), void *arg)
+{
+	uintptr len, elemsize, i, *end;
+
+	for(;;) {
+		switch(prog[0]) {
+		case GC_END:
+			return prog;
+		case GC_PTR:
+			callback(arg, FieldKindPtr, offset + prog[1]);
+			prog += 3;
+			break;
+		case GC_APTR:
+			callback(arg, FieldKindPtr, offset + prog[1]);
+			prog += 2;
+			break;
+		case GC_ARRAY_START:
+			len = prog[2];
+			elemsize = prog[3];
+			end = nil;
+			for(i = 0; i < len; i++) {
+				end = playgcprog(offset + prog[1] + i * elemsize, prog + 4, callback, arg);
+				if(end[0] != GC_ARRAY_NEXT)
+					runtime_throw("GC_ARRAY_START did not have matching GC_ARRAY_NEXT");
+			}
+			prog = end + 1;
+			break;
+		case GC_ARRAY_NEXT:
+			return prog;
+		case GC_CALL:
+			playgcprog(offset + prog[1], (uintptr*)((byte*)prog + *(int32*)&prog[2]), callback, arg);
+			prog += 3;
+			break;
+		case GC_CHAN_PTR:
+			callback(arg, FieldKindPtr, offset + prog[1]);
+			prog += 3;
+			break;
+		case GC_STRING:
+			callback(arg, FieldKindString, offset + prog[1]);
+			prog += 2;
+			break;
+		case GC_EFACE:
+			callback(arg, FieldKindEface, offset + prog[1]);
+			prog += 2;
+			break;
+		case GC_IFACE:
+			callback(arg, FieldKindIface, offset + prog[1]);
+			prog += 2;
+			break;
+		case GC_SLICE:
+			callback(arg, FieldKindSlice, offset + prog[1]);
+			prog += 3;
+			break;
+		case GC_REGION:
+			playgcprog(offset + prog[1], (uintptr*)prog[3] + 1, callback, arg);
+			prog += 4;
+			break;
+		default:
+			runtime_printf("%D\n", (uint64)prog[0]);
+			runtime_throw("bad gc op");
+		}
+	}
+}
+
+static void
+dump_callback(void *p, uintptr kind, uintptr offset)
+{
+	USED(&p);
+	dumpint(kind);
+	dumpint(offset);
+}
+
+// dumpint() the kind & offset of each field in an object.
+static void
+dumpfields(uintptr *prog)
+{
+	playgcprog(0, prog, dump_callback, nil);
+	dumpint(FieldKindEol);
+}
+
+static void
+dumpeface_callback(void *p, uintptr kind, uintptr offset)
+{
+	Eface *e;
+
+	if(kind != FieldKindEface)
+		return;
+	e = (Eface*)((byte*)p + offset);
+	dumptype(e->__type_descriptor);
+}
+*/
+
+// The heap dump reader needs to be able to disambiguate
+// Eface entries.  So it needs to know every type that might
+// appear in such an entry.  The following two routines accomplish
+// that.
+
+// Dump all the types that appear in the type field of
+// any Eface contained in obj.
+static void
+dumpefacetypes(void *obj __attribute__ ((unused)), uintptr size, const Type *type, uintptr kind)
+{
+	uintptr i;
+
+	switch(kind) {
+	case TypeInfo_SingleObject:
+		//playgcprog(0, (uintptr*)type->gc + 1, dumpeface_callback, obj);
+		break;
+	case TypeInfo_Array:
+		for(i = 0; i <= size - type->__size; i += type->__size)
+			//playgcprog(i, (uintptr*)type->gc + 1, dumpeface_callback, obj);
+		break;
+	case TypeInfo_Chan:
+		if(type->__size == 0) // channels may have zero-sized objects in them
+			break;
+		for(i = runtime_Hchansize; i <= size - type->__size; i += type->__size)
+			//playgcprog(i, (uintptr*)type->gc + 1, dumpeface_callback, obj);
+		break;
+	}
+}
diff --git a/third_party/gofrontend/libgo/runtime/interface.h b/third_party/gofrontend/libgo/runtime/interface.h
new file mode 100644
index 0000000..f3068a6
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/interface.h
@@ -0,0 +1,57 @@
+/* interface.h -- the interface type for Go.
+
+   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.  */
+
+#ifndef LIBGO_INTERFACE_H
+#define LIBGO_INTERFACE_H
+
+struct __go_type_descriptor;
+
+/* A variable of interface type is an instance of this struct, if the
+   interface has any methods.  */
+
+struct __go_interface
+{
+  /* A pointer to the interface method table.  The first pointer is
+     the type descriptor of the object.  Subsequent pointers are
+     pointers to functions.  This is effectively the vtable for this
+     interface.  The function pointers are in the same order as the
+     list in the internal representation of the interface, which sorts
+     them by name.  */
+  const void **__methods;
+
+  /* The object.  If the object is a pointer--if the type descriptor
+     code is GO_PTR or GO_UNSAFE_POINTER--then this field is the value
+     of the object itself.  Otherwise this is a pointer to memory
+     which holds the value.  */
+  void *__object;
+};
+
+/* A variable of an empty interface type is an instance of this
+   struct.  */
+
+struct __go_empty_interface
+{
+  /* The type descriptor of the object.  */
+  const struct __go_type_descriptor *__type_descriptor;
+
+  /* The object.  This is the same as __go_interface above.  */
+  void *__object;
+};
+
+extern void *
+__go_convert_interface (const struct __go_type_descriptor *,
+			const struct __go_type_descriptor *);
+
+extern void *
+__go_convert_interface_2 (const struct __go_type_descriptor *,
+			  const struct __go_type_descriptor *,
+			  _Bool may_fail);
+
+extern _Bool
+__go_can_convert_to_interface(const struct __go_type_descriptor *,
+			      const struct __go_type_descriptor *);
+
+#endif /* !defined(LIBGO_INTERFACE_H) */
diff --git a/third_party/gofrontend/libgo/runtime/lfstack.goc b/third_party/gofrontend/libgo/runtime/lfstack.goc
new file mode 100644
index 0000000..060a0cc
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/lfstack.goc
@@ -0,0 +1,79 @@
+// 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.
+
+// Lock-free stack.
+
+package runtime
+#include "runtime.h"
+#include "arch.h"
+
+#if __SIZEOF_POINTER__ == 8
+// Amd64 uses 48-bit virtual addresses, 47-th bit is used as kernel/user flag.
+// So we use 17msb of pointers as ABA counter.
+# define PTR_BITS 47
+#else
+# define PTR_BITS 32
+#endif
+#define PTR_MASK ((1ull<<PTR_BITS)-1)
+#define CNT_MASK (0ull-1)
+
+#if __SIZEOF_POINTER__ == 8 && (defined(__sparc__) || (defined(__sun__) && defined(__amd64__)))
+// SPARC64 and Solaris on AMD64 uses all 64 bits of virtual addresses.
+// Use low-order three bits as ABA counter.
+// http://docs.oracle.com/cd/E19120-01/open.solaris/816-5138/6mba6ua5p/index.html
+#undef PTR_BITS
+#undef CNT_MASK
+#undef PTR_MASK
+#define PTR_BITS 0
+#define CNT_MASK 7
+#define PTR_MASK ((0ull-1)<<3)
+#endif
+
+void
+runtime_lfstackpush(uint64 *head, LFNode *node)
+{
+	uint64 old, new;
+
+	if((uintptr)node != ((uintptr)node&PTR_MASK)) {
+		runtime_printf("p=%p\n", node);
+		runtime_throw("runtime_lfstackpush: invalid pointer");
+	}
+
+	node->pushcnt++;
+	new = (uint64)(uintptr)node|(((uint64)node->pushcnt&CNT_MASK)<<PTR_BITS);
+	for(;;) {
+		old = runtime_atomicload64(head);
+		node->next = (LFNode*)(uintptr)(old&PTR_MASK);
+		if(runtime_cas64(head, old, new))
+			break;
+	}
+}
+
+LFNode*
+runtime_lfstackpop(uint64 *head)
+{
+	LFNode *node, *node2;
+	uint64 old, new;
+
+	for(;;) {
+		old = runtime_atomicload64(head);
+		if(old == 0)
+			return nil;
+		node = (LFNode*)(uintptr)(old&PTR_MASK);
+		node2 = runtime_atomicloadp(&node->next);
+		new = 0;
+		if(node2 != nil)
+			new = (uint64)(uintptr)node2|(((uint64)node2->pushcnt&CNT_MASK)<<PTR_BITS);
+		if(runtime_cas64(head, old, new))
+			return node;
+	}
+}
+
+func lfstackpush_go(head *uint64, node *LFNode) {
+	runtime_lfstackpush(head, node);
+}
+
+func lfstackpop_go(head *uint64) (node *LFNode) {
+	node = runtime_lfstackpop(head);
+}
diff --git a/third_party/gofrontend/libgo/runtime/lock_futex.c b/third_party/gofrontend/libgo/runtime/lock_futex.c
new file mode 100644
index 0000000..33ef073
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/lock_futex.c
@@ -0,0 +1,204 @@
+// 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.
+
+// +build dragonfly freebsd linux
+
+#include "runtime.h"
+
+// This implementation depends on OS-specific implementations of
+//
+//	runtime_futexsleep(uint32 *addr, uint32 val, int64 ns)
+//		Atomically,
+//			if(*addr == val) sleep
+//		Might be woken up spuriously; that's allowed.
+//		Don't sleep longer than ns; ns < 0 means forever.
+//
+//	runtime_futexwakeup(uint32 *addr, uint32 cnt)
+//		If any procs are sleeping on addr, wake up at most cnt.
+
+enum
+{
+	MUTEX_UNLOCKED = 0,
+	MUTEX_LOCKED = 1,
+	MUTEX_SLEEPING = 2,
+
+	ACTIVE_SPIN = 4,
+	ACTIVE_SPIN_CNT = 30,
+	PASSIVE_SPIN = 1,
+};
+
+// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
+// MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
+// Note that there can be spinning threads during all states - they do not
+// affect mutex's state.
+void
+runtime_lock(Lock *l)
+{
+	uint32 i, v, wait, spin;
+
+	if(runtime_m()->locks++ < 0)
+		runtime_throw("runtime_lock: lock count");
+
+	// Speculative grab for lock.
+	v = runtime_xchg((uint32*)&l->key, MUTEX_LOCKED);
+	if(v == MUTEX_UNLOCKED)
+		return;
+
+	// wait is either MUTEX_LOCKED or MUTEX_SLEEPING
+	// depending on whether there is a thread sleeping
+	// on this mutex.  If we ever change l->key from
+	// MUTEX_SLEEPING to some other value, we must be
+	// careful to change it back to MUTEX_SLEEPING before
+	// returning, to ensure that the sleeping thread gets
+	// its wakeup call.
+	wait = v;
+
+	// On uniprocessor's, no point spinning.
+	// On multiprocessors, spin for ACTIVE_SPIN attempts.
+	spin = 0;
+	if(runtime_ncpu > 1)
+		spin = ACTIVE_SPIN;
+
+	for(;;) {
+		// Try for lock, spinning.
+		for(i = 0; i < spin; i++) {
+			while(l->key == MUTEX_UNLOCKED)
+				if(runtime_cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
+					return;
+			runtime_procyield(ACTIVE_SPIN_CNT);
+		}
+
+		// Try for lock, rescheduling.
+		for(i=0; i < PASSIVE_SPIN; i++) {
+			while(l->key == MUTEX_UNLOCKED)
+				if(runtime_cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
+					return;
+			runtime_osyield();
+		}
+
+		// Sleep.
+		v = runtime_xchg((uint32*)&l->key, MUTEX_SLEEPING);
+		if(v == MUTEX_UNLOCKED)
+			return;
+		wait = MUTEX_SLEEPING;
+		runtime_futexsleep((uint32*)&l->key, MUTEX_SLEEPING, -1);
+	}
+}
+
+void
+runtime_unlock(Lock *l)
+{
+	uint32 v;
+
+	v = runtime_xchg((uint32*)&l->key, MUTEX_UNLOCKED);
+	if(v == MUTEX_UNLOCKED)
+		runtime_throw("unlock of unlocked lock");
+	if(v == MUTEX_SLEEPING)
+		runtime_futexwakeup((uint32*)&l->key, 1);
+
+	if(--runtime_m()->locks < 0)
+		runtime_throw("runtime_unlock: lock count");
+}
+
+// One-time notifications.
+void
+runtime_noteclear(Note *n)
+{
+	n->key = 0;
+}
+
+void
+runtime_notewakeup(Note *n)
+{
+	uint32 old;
+
+	old = runtime_xchg((uint32*)&n->key, 1);
+	if(old != 0) {
+		runtime_printf("notewakeup - double wakeup (%d)\n", old);
+		runtime_throw("notewakeup - double wakeup");
+	}
+	runtime_futexwakeup((uint32*)&n->key, 1);
+}
+
+void
+runtime_notesleep(Note *n)
+{
+	M *m = runtime_m();
+
+  /* For gccgo it's OK to sleep in non-g0, and it happens in
+     stoptheworld because we have not implemented preemption.
+
+	if(runtime_g() != runtime_m()->g0)
+		runtime_throw("notesleep not on g0");
+  */
+	while(runtime_atomicload((uint32*)&n->key) == 0) {
+		m->blocked = true;
+		runtime_futexsleep((uint32*)&n->key, 0, -1);
+		m->blocked = false;
+	}
+}
+
+static bool
+notetsleep(Note *n, int64 ns, int64 deadline, int64 now)
+{
+	M *m = runtime_m();
+
+	// Conceptually, deadline and now are local variables.
+	// They are passed as arguments so that the space for them
+	// does not count against our nosplit stack sequence.
+
+	if(ns < 0) {
+		while(runtime_atomicload((uint32*)&n->key) == 0) {
+			m->blocked = true;
+			runtime_futexsleep((uint32*)&n->key, 0, -1);
+			m->blocked = false;
+		}
+		return true;
+	}
+
+	if(runtime_atomicload((uint32*)&n->key) != 0)
+		return true;
+
+	deadline = runtime_nanotime() + ns;
+	for(;;) {
+		m->blocked = true;
+		runtime_futexsleep((uint32*)&n->key, 0, ns);
+		m->blocked = false;
+		if(runtime_atomicload((uint32*)&n->key) != 0)
+			break;
+		now = runtime_nanotime();
+		if(now >= deadline)
+			break;
+		ns = deadline - now;
+	}
+	return runtime_atomicload((uint32*)&n->key) != 0;
+}
+
+bool
+runtime_notetsleep(Note *n, int64 ns)
+{
+	bool res;
+
+	if(runtime_g() != runtime_m()->g0 && !runtime_m()->gcing)
+		runtime_throw("notetsleep not on g0");
+
+	res = notetsleep(n, ns, 0, 0);
+	return res;
+}
+
+// same as runtime_notetsleep, but called on user g (not g0)
+// calls only nosplit functions between entersyscallblock/exitsyscall
+bool
+runtime_notetsleepg(Note *n, int64 ns)
+{
+	bool res;
+
+	if(runtime_g() == runtime_m()->g0)
+		runtime_throw("notetsleepg on g0");
+
+	runtime_entersyscallblock();
+	res = notetsleep(n, ns, 0, 0);
+	runtime_exitsyscall();
+	return res;
+}
diff --git a/third_party/gofrontend/libgo/runtime/lock_sema.c b/third_party/gofrontend/libgo/runtime/lock_sema.c
new file mode 100644
index 0000000..ef611fb
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/lock_sema.c
@@ -0,0 +1,281 @@
+// 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.
+
+// +build darwin nacl netbsd openbsd plan9 solaris windows
+
+#include "runtime.h"
+
+// This implementation depends on OS-specific implementations of
+//
+//	uintptr runtime_semacreate(void)
+//		Create a semaphore, which will be assigned to m->waitsema.
+//		The zero value is treated as absence of any semaphore,
+//		so be sure to return a non-zero value.
+//
+//	int32 runtime_semasleep(int64 ns)
+//		If ns < 0, acquire m->waitsema and return 0.
+//		If ns >= 0, try to acquire m->waitsema for at most ns nanoseconds.
+//		Return 0 if the semaphore was acquired, -1 if interrupted or timed out.
+//
+//	int32 runtime_semawakeup(M *mp)
+//		Wake up mp, which is or will soon be sleeping on mp->waitsema.
+//
+
+enum
+{
+	LOCKED = 1,
+
+	ACTIVE_SPIN = 4,
+	ACTIVE_SPIN_CNT = 30,
+	PASSIVE_SPIN = 1,
+};
+
+void
+runtime_lock(Lock *l)
+{
+	M *m;
+	uintptr v;
+	uint32 i, spin;
+
+	m = runtime_m();
+	if(m->locks++ < 0)
+		runtime_throw("runtime_lock: lock count");
+
+	// Speculative grab for lock.
+	if(runtime_casp((void**)&l->key, nil, (void*)LOCKED))
+		return;
+
+	if(m->waitsema == 0)
+		m->waitsema = runtime_semacreate();
+
+	// On uniprocessor's, no point spinning.
+	// On multiprocessors, spin for ACTIVE_SPIN attempts.
+	spin = 0;
+	if(runtime_ncpu > 1)
+		spin = ACTIVE_SPIN;
+
+	for(i=0;; i++) {
+		v = (uintptr)runtime_atomicloadp((void**)&l->key);
+		if((v&LOCKED) == 0) {
+unlocked:
+			if(runtime_casp((void**)&l->key, (void*)v, (void*)(v|LOCKED)))
+				return;
+			i = 0;
+		}
+		if(i<spin)
+			runtime_procyield(ACTIVE_SPIN_CNT);
+		else if(i<spin+PASSIVE_SPIN)
+			runtime_osyield();
+		else {
+			// Someone else has it.
+			// l->waitm points to a linked list of M's waiting
+			// for this lock, chained through m->nextwaitm.
+			// Queue this M.
+			for(;;) {
+				m->nextwaitm = (void*)(v&~LOCKED);
+				if(runtime_casp((void**)&l->key, (void*)v, (void*)((uintptr)m|LOCKED)))
+					break;
+				v = (uintptr)runtime_atomicloadp((void**)&l->key);
+				if((v&LOCKED) == 0)
+					goto unlocked;
+			}
+			if(v&LOCKED) {
+				// Queued.  Wait.
+				runtime_semasleep(-1);
+				i = 0;
+			}
+		}
+	}
+}
+
+void
+runtime_unlock(Lock *l)
+{
+	uintptr v;
+	M *mp;
+
+	for(;;) {
+		v = (uintptr)runtime_atomicloadp((void**)&l->key);
+		if(v == LOCKED) {
+			if(runtime_casp((void**)&l->key, (void*)LOCKED, nil))
+				break;
+		} else {
+			// Other M's are waiting for the lock.
+			// Dequeue an M.
+			mp = (void*)(v&~LOCKED);
+			if(runtime_casp((void**)&l->key, (void*)v, mp->nextwaitm)) {
+				// Dequeued an M.  Wake it.
+				runtime_semawakeup(mp);
+				break;
+			}
+		}
+	}
+
+	if(--runtime_m()->locks < 0)
+		runtime_throw("runtime_unlock: lock count");
+}
+
+// One-time notifications.
+void
+runtime_noteclear(Note *n)
+{
+	n->key = 0;
+}
+
+void
+runtime_notewakeup(Note *n)
+{
+	M *mp;
+
+	do
+		mp = runtime_atomicloadp((void**)&n->key);
+	while(!runtime_casp((void**)&n->key, mp, (void*)LOCKED));
+
+	// Successfully set waitm to LOCKED.
+	// What was it before?
+	if(mp == nil) {
+		// Nothing was waiting.  Done.
+	} else if(mp == (M*)LOCKED) {
+		// Two notewakeups!  Not allowed.
+		runtime_throw("notewakeup - double wakeup");
+	} else {
+		// Must be the waiting m.  Wake it up.
+		runtime_semawakeup(mp);
+	}
+}
+
+void
+runtime_notesleep(Note *n)
+{
+	M *m;
+
+	m = runtime_m();
+
+  /* For gccgo it's OK to sleep in non-g0, and it happens in
+     stoptheworld because we have not implemented preemption.
+
+	if(runtime_g() != m->g0)
+		runtime_throw("notesleep not on g0");
+  */
+
+	if(m->waitsema == 0)
+		m->waitsema = runtime_semacreate();
+	if(!runtime_casp((void**)&n->key, nil, m)) {  // must be LOCKED (got wakeup)
+		if(n->key != LOCKED)
+			runtime_throw("notesleep - waitm out of sync");
+		return;
+	}
+	// Queued.  Sleep.
+	m->blocked = true;
+	runtime_semasleep(-1);
+	m->blocked = false;
+}
+
+static bool
+notetsleep(Note *n, int64 ns, int64 deadline, M *mp)
+{
+	M *m;
+
+	m = runtime_m();
+
+	// Conceptually, deadline and mp are local variables.
+	// They are passed as arguments so that the space for them
+	// does not count against our nosplit stack sequence.
+
+	// Register for wakeup on n->waitm.
+	if(!runtime_casp((void**)&n->key, nil, m)) {  // must be LOCKED (got wakeup already)
+		if(n->key != LOCKED)
+			runtime_throw("notetsleep - waitm out of sync");
+		return true;
+	}
+
+	if(ns < 0) {
+		// Queued.  Sleep.
+		m->blocked = true;
+		runtime_semasleep(-1);
+		m->blocked = false;
+		return true;
+	}
+
+	deadline = runtime_nanotime() + ns;
+	for(;;) {
+		// Registered.  Sleep.
+		m->blocked = true;
+		if(runtime_semasleep(ns) >= 0) {
+			m->blocked = false;
+			// Acquired semaphore, semawakeup unregistered us.
+			// Done.
+			return true;
+		}
+		m->blocked = false;
+
+		// Interrupted or timed out.  Still registered.  Semaphore not acquired.
+		ns = deadline - runtime_nanotime();
+		if(ns <= 0)
+			break;
+		// Deadline hasn't arrived.  Keep sleeping.
+	}
+
+	// Deadline arrived.  Still registered.  Semaphore not acquired.
+	// Want to give up and return, but have to unregister first,
+	// so that any notewakeup racing with the return does not
+	// try to grant us the semaphore when we don't expect it.
+	for(;;) {
+		mp = runtime_atomicloadp((void**)&n->key);
+		if(mp == m) {
+			// No wakeup yet; unregister if possible.
+			if(runtime_casp((void**)&n->key, mp, nil))
+				return false;
+		} else if(mp == (M*)LOCKED) {
+			// Wakeup happened so semaphore is available.
+			// Grab it to avoid getting out of sync.
+			m->blocked = true;
+			if(runtime_semasleep(-1) < 0)
+				runtime_throw("runtime: unable to acquire - semaphore out of sync");
+			m->blocked = false;
+			return true;
+		} else
+			runtime_throw("runtime: unexpected waitm - semaphore out of sync");
+	}
+}
+
+bool
+runtime_notetsleep(Note *n, int64 ns)
+{
+	M *m;
+	bool res;
+
+	m = runtime_m();
+
+	if(runtime_g() != m->g0 && !m->gcing)
+		runtime_throw("notetsleep not on g0");
+
+	if(m->waitsema == 0)
+		m->waitsema = runtime_semacreate();
+
+	res = notetsleep(n, ns, 0, nil);
+	return res;
+}
+
+// same as runtime_notetsleep, but called on user g (not g0)
+// calls only nosplit functions between entersyscallblock/exitsyscall
+bool
+runtime_notetsleepg(Note *n, int64 ns)
+{
+	M *m;
+	bool res;
+
+	m = runtime_m();
+
+	if(runtime_g() == m->g0)
+		runtime_throw("notetsleepg on g0");
+
+	if(m->waitsema == 0)
+		m->waitsema = runtime_semacreate();
+
+	runtime_entersyscallblock();
+	res = notetsleep(n, ns, 0, nil);
+	runtime_exitsyscall();
+	return res;
+}
diff --git a/third_party/gofrontend/libgo/runtime/malloc.goc b/third_party/gofrontend/libgo/runtime/malloc.goc
new file mode 100644
index 0000000..b2c4eea
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/malloc.goc
@@ -0,0 +1,1007 @@
+// 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.
+
+// See malloc.h for overview.
+//
+// TODO(rsc): double-check stats.
+
+package runtime
+#include <stddef.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "go-alloc.h"
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+#include "interface.h"
+#include "go-type.h"
+#include "race.h"
+
+// Map gccgo field names to gc field names.
+// Eface aka __go_empty_interface.
+#define type __type_descriptor
+// Type aka __go_type_descriptor
+#define kind __code
+#define string __reflection
+#define KindPtr GO_PTR
+#define KindNoPointers GO_NO_POINTERS
+
+// GCCGO SPECIFIC CHANGE
+//
+// There is a long comment in runtime_mallocinit about where to put the heap
+// on a 64-bit system.  It makes assumptions that are not valid on linux/arm64
+// -- it assumes user space can choose the lower 47 bits of a pointer, but on
+// linux/arm64 we can only choose the lower 39 bits.  This means the heap is
+// roughly a quarter of the available address space and we cannot choose a bit
+// pattern that all pointers will have -- luckily the GC is mostly precise
+// these days so this doesn't matter all that much.  The kernel (as of 3.13)
+// will allocate address space starting either down from 0x7fffffffff or up
+// from 0x2000000000, so we put the heap roughly in the middle of these two
+// addresses to minimize the chance that a non-heap allocation will get in the
+// way of the heap.
+//
+// This all means that there isn't much point in trying 256 different
+// locations for the heap on such systems.
+#ifdef __aarch64__
+#define HeapBase(i) ((void*)(uintptr)(0x40ULL<<32))
+#define HeapBaseOptions 1
+#else
+#define HeapBase(i) ((void*)(uintptr)(i<<40|0x00c0ULL<<32))
+#define HeapBaseOptions 0x80
+#endif
+// END GCCGO SPECIFIC CHANGE
+
+// Mark mheap as 'no pointers', it does not contain interesting pointers but occupies ~45K.
+MHeap runtime_mheap;
+MStats mstats;
+
+int32	runtime_checking;
+
+extern MStats mstats;	// defined in zruntime_def_$GOOS_$GOARCH.go
+
+extern volatile intgo runtime_MemProfileRate
+  __asm__ (GOSYM_PREFIX "runtime.MemProfileRate");
+
+static MSpan* largealloc(uint32, uintptr*);
+static void profilealloc(void *v, uintptr size);
+static void settype(MSpan *s, void *v, uintptr typ);
+
+// Allocate an object of at least size bytes.
+// Small objects are allocated from the per-thread cache's free lists.
+// Large objects (> 32 kB) are allocated straight from the heap.
+// If the block will be freed with runtime_free(), typ must be 0.
+void*
+runtime_mallocgc(uintptr size, uintptr typ, uint32 flag)
+{
+	M *m;
+	G *g;
+	int32 sizeclass;
+	uintptr tinysize, size1;
+	intgo rate;
+	MCache *c;
+	MSpan *s;
+	MLink *v, *next;
+	byte *tiny;
+	bool incallback;
+	void *closure;
+
+	if(size == 0) {
+		// All 0-length allocations use this pointer.
+		// The language does not require the allocations to
+		// have distinct values.
+		return &runtime_zerobase;
+	}
+
+	m = runtime_m();
+	g = runtime_g();
+
+	// We should not be called in between __go_set_closure and the
+	// actual function call, but cope with it if we are.
+	closure = g->closure;
+
+	incallback = false;
+	if(m->mcache == nil && g->ncgo > 0) {
+		// For gccgo this case can occur when a cgo or SWIG function
+		// has an interface return type and the function
+		// returns a non-pointer, so memory allocation occurs
+		// after syscall.Cgocall but before syscall.CgocallDone.
+		// We treat it as a callback.
+		runtime_exitsyscall();
+		m = runtime_m();
+		incallback = true;
+		flag |= FlagNoInvokeGC;
+	}
+
+	if(runtime_gcwaiting() && g != m->g0 && m->locks == 0 && !(flag & FlagNoInvokeGC)) {
+		runtime_gosched();
+		m = runtime_m();
+	}
+	if(m->mallocing)
+		runtime_throw("malloc/free - deadlock");
+	// Disable preemption during settype.
+	// We can not use m->mallocing for this, because settype calls mallocgc.
+	m->locks++;
+	m->mallocing = 1;
+
+	if(DebugTypeAtBlockEnd)
+		size += sizeof(uintptr);
+
+	c = m->mcache;
+	if(!runtime_debug.efence && size <= MaxSmallSize) {
+		if((flag&(FlagNoScan|FlagNoGC)) == FlagNoScan && size < TinySize) {
+			// Tiny allocator.
+			//
+			// Tiny allocator combines several tiny allocation requests
+			// into a single memory block. The resulting memory block
+			// is freed when all subobjects are unreachable. The subobjects
+			// must be FlagNoScan (don't have pointers), this ensures that
+			// the amount of potentially wasted memory is bounded.
+			//
+			// Size of the memory block used for combining (TinySize) is tunable.
+			// Current setting is 16 bytes, which relates to 2x worst case memory
+			// wastage (when all but one subobjects are unreachable).
+			// 8 bytes would result in no wastage at all, but provides less
+			// opportunities for combining.
+			// 32 bytes provides more opportunities for combining,
+			// but can lead to 4x worst case wastage.
+			// The best case winning is 8x regardless of block size.
+			//
+			// Objects obtained from tiny allocator must not be freed explicitly.
+			// So when an object will be freed explicitly, we ensure that
+			// its size >= TinySize.
+			//
+			// SetFinalizer has a special case for objects potentially coming
+			// from tiny allocator, it such case it allows to set finalizers
+			// for an inner byte of a memory block.
+			//
+			// The main targets of tiny allocator are small strings and
+			// standalone escaping variables. On a json benchmark
+			// the allocator reduces number of allocations by ~12% and
+			// reduces heap size by ~20%.
+
+			tinysize = c->tinysize;
+			if(size <= tinysize) {
+				tiny = c->tiny;
+				// Align tiny pointer for required (conservative) alignment.
+				if((size&7) == 0)
+					tiny = (byte*)ROUND((uintptr)tiny, 8);
+				else if((size&3) == 0)
+					tiny = (byte*)ROUND((uintptr)tiny, 4);
+				else if((size&1) == 0)
+					tiny = (byte*)ROUND((uintptr)tiny, 2);
+				size1 = size + (tiny - c->tiny);
+				if(size1 <= tinysize) {
+					// The object fits into existing tiny block.
+					v = (MLink*)tiny;
+					c->tiny += size1;
+					c->tinysize -= size1;
+					m->mallocing = 0;
+					m->locks--;
+					if(incallback)
+						runtime_entersyscall();
+					g->closure = closure;
+					return v;
+				}
+			}
+			// Allocate a new TinySize block.
+			s = c->alloc[TinySizeClass];
+			if(s->freelist == nil)
+				s = runtime_MCache_Refill(c, TinySizeClass);
+			v = s->freelist;
+			next = v->next;
+			s->freelist = next;
+			s->ref++;
+			if(next != nil)  // prefetching nil leads to a DTLB miss
+				PREFETCH(next);
+			((uint64*)v)[0] = 0;
+			((uint64*)v)[1] = 0;
+			// See if we need to replace the existing tiny block with the new one
+			// based on amount of remaining free space.
+			if(TinySize-size > tinysize) {
+				c->tiny = (byte*)v + size;
+				c->tinysize = TinySize - size;
+			}
+			size = TinySize;
+			goto done;
+		}
+		// Allocate from mcache free lists.
+		// Inlined version of SizeToClass().
+		if(size <= 1024-8)
+			sizeclass = runtime_size_to_class8[(size+7)>>3];
+		else
+			sizeclass = runtime_size_to_class128[(size-1024+127) >> 7];
+		size = runtime_class_to_size[sizeclass];
+		s = c->alloc[sizeclass];
+		if(s->freelist == nil)
+			s = runtime_MCache_Refill(c, sizeclass);
+		v = s->freelist;
+		next = v->next;
+		s->freelist = next;
+		s->ref++;
+		if(next != nil)  // prefetching nil leads to a DTLB miss
+			PREFETCH(next);
+		if(!(flag & FlagNoZero)) {
+			v->next = nil;
+			// block is zeroed iff second word is zero ...
+			if(size > 2*sizeof(uintptr) && ((uintptr*)v)[1] != 0)
+				runtime_memclr((byte*)v, size);
+		}
+	done:
+		c->local_cachealloc += size;
+	} else {
+		// Allocate directly from heap.
+		s = largealloc(flag, &size);
+		v = (void*)(s->start << PageShift);
+	}
+
+	if(flag & FlagNoGC)
+		runtime_marknogc(v);
+	else if(!(flag & FlagNoScan))
+		runtime_markscan(v);
+
+	if(DebugTypeAtBlockEnd)
+		*(uintptr*)((uintptr)v+size-sizeof(uintptr)) = typ;
+
+	m->mallocing = 0;
+	// TODO: save type even if FlagNoScan?  Potentially expensive but might help
+	// heap profiling/tracing.
+	if(UseSpanType && !(flag & FlagNoScan) && typ != 0)
+		settype(s, v, typ);
+
+	if(raceenabled)
+		runtime_racemalloc(v, size);
+
+	if(runtime_debug.allocfreetrace)
+		runtime_tracealloc(v, size, typ);
+
+	if(!(flag & FlagNoProfiling) && (rate = runtime_MemProfileRate) > 0) {
+		if(size < (uintptr)rate && size < (uintptr)(uint32)c->next_sample)
+			c->next_sample -= size;
+		else
+			profilealloc(v, size);
+	}
+
+	m->locks--;
+
+	if(!(flag & FlagNoInvokeGC) && mstats.heap_alloc >= mstats.next_gc)
+		runtime_gc(0);
+
+	if(incallback)
+		runtime_entersyscall();
+
+	g->closure = closure;
+
+	return v;
+}
+
+static MSpan*
+largealloc(uint32 flag, uintptr *sizep)
+{
+	uintptr npages, size;
+	MSpan *s;
+	void *v;
+
+	// Allocate directly from heap.
+	size = *sizep;
+	if(size + PageSize < size)
+		runtime_throw("out of memory");
+	npages = size >> PageShift;
+	if((size & PageMask) != 0)
+		npages++;
+	s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1, !(flag & FlagNoZero));
+	if(s == nil)
+		runtime_throw("out of memory");
+	s->limit = (byte*)(s->start<<PageShift) + size;
+	*sizep = npages<<PageShift;
+	v = (void*)(s->start << PageShift);
+	// setup for mark sweep
+	runtime_markspan(v, 0, 0, true);
+	return s;
+}
+
+static void
+profilealloc(void *v, uintptr size)
+{
+	uintptr rate;
+	int32 next;
+	MCache *c;
+
+	c = runtime_m()->mcache;
+	rate = runtime_MemProfileRate;
+	if(size < rate) {
+		// pick next profile time
+		// If you change this, also change allocmcache.
+		if(rate > 0x3fffffff)	// make 2*rate not overflow
+			rate = 0x3fffffff;
+		next = runtime_fastrand1() % (2*rate);
+		// Subtract the "remainder" of the current allocation.
+		// Otherwise objects that are close in size to sampling rate
+		// will be under-sampled, because we consistently discard this remainder.
+		next -= (size - c->next_sample);
+		if(next < 0)
+			next = 0;
+		c->next_sample = next;
+	}
+	runtime_MProf_Malloc(v, size);
+}
+
+void*
+__go_alloc(uintptr size)
+{
+	return runtime_mallocgc(size, 0, FlagNoInvokeGC);
+}
+
+// Free the object whose base pointer is v.
+void
+__go_free(void *v)
+{
+	M *m;
+	int32 sizeclass;
+	MSpan *s;
+	MCache *c;
+	uintptr size;
+
+	if(v == nil)
+		return;
+	
+	// If you change this also change mgc0.c:/^sweep,
+	// which has a copy of the guts of free.
+
+	m = runtime_m();
+	if(m->mallocing)
+		runtime_throw("malloc/free - deadlock");
+	m->mallocing = 1;
+
+	if(!runtime_mlookup(v, nil, nil, &s)) {
+		runtime_printf("free %p: not an allocated block\n", v);
+		runtime_throw("free runtime_mlookup");
+	}
+	size = s->elemsize;
+	sizeclass = s->sizeclass;
+	// Objects that are smaller than TinySize can be allocated using tiny alloc,
+	// if then such object is combined with an object with finalizer, we will crash.
+	if(size < TinySize)
+		runtime_throw("freeing too small block");
+
+	if(runtime_debug.allocfreetrace)
+		runtime_tracefree(v, size);
+
+	// Ensure that the span is swept.
+	// If we free into an unswept span, we will corrupt GC bitmaps.
+	runtime_MSpan_EnsureSwept(s);
+
+	if(s->specials != nil)
+		runtime_freeallspecials(s, v, size);
+
+	c = m->mcache;
+	if(sizeclass == 0) {
+		// Large object.
+		s->needzero = 1;
+		// Must mark v freed before calling unmarkspan and MHeap_Free:
+		// they might coalesce v into other spans and change the bitmap further.
+		runtime_markfreed(v);
+		runtime_unmarkspan(v, 1<<PageShift);
+		// NOTE(rsc,dvyukov): The original implementation of efence
+		// in CL 22060046 used SysFree instead of SysFault, so that
+		// the operating system would eventually give the memory
+		// back to us again, so that an efence program could run
+		// longer without running out of memory. Unfortunately,
+		// calling SysFree here without any kind of adjustment of the
+		// heap data structures means that when the memory does
+		// come back to us, we have the wrong metadata for it, either in
+		// the MSpan structures or in the garbage collection bitmap.
+		// Using SysFault here means that the program will run out of
+		// memory fairly quickly in efence mode, but at least it won't
+		// have mysterious crashes due to confused memory reuse.
+		// It should be possible to switch back to SysFree if we also 
+		// implement and then call some kind of MHeap_DeleteSpan.
+		if(runtime_debug.efence)
+			runtime_SysFault((void*)(s->start<<PageShift), size);
+		else
+			runtime_MHeap_Free(&runtime_mheap, s, 1);
+		c->local_nlargefree++;
+		c->local_largefree += size;
+	} else {
+		// Small object.
+		if(size > 2*sizeof(uintptr))
+			((uintptr*)v)[1] = (uintptr)0xfeedfeedfeedfeedll;	// mark as "needs to be zeroed"
+		else if(size > sizeof(uintptr))
+			((uintptr*)v)[1] = 0;
+		// Must mark v freed before calling MCache_Free:
+		// it might coalesce v and other blocks into a bigger span
+		// and change the bitmap further.
+		c->local_nsmallfree[sizeclass]++;
+		c->local_cachealloc -= size;
+		if(c->alloc[sizeclass] == s) {
+			// We own the span, so we can just add v to the freelist
+			runtime_markfreed(v);
+			((MLink*)v)->next = s->freelist;
+			s->freelist = v;
+			s->ref--;
+		} else {
+			// Someone else owns this span.  Add to free queue.
+			runtime_MCache_Free(c, v, sizeclass, size);
+		}
+	}
+	m->mallocing = 0;
+}
+
+int32
+runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
+{
+	M *m;
+	uintptr n, i;
+	byte *p;
+	MSpan *s;
+
+	m = runtime_m();
+
+	m->mcache->local_nlookup++;
+	if (sizeof(void*) == 4 && m->mcache->local_nlookup >= (1<<30)) {
+		// purge cache stats to prevent overflow
+		runtime_lock(&runtime_mheap.lock);
+		runtime_purgecachedstats(m->mcache);
+		runtime_unlock(&runtime_mheap.lock);
+	}
+
+	s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
+	if(sp)
+		*sp = s;
+	if(s == nil) {
+		runtime_checkfreed(v, 1);
+		if(base)
+			*base = nil;
+		if(size)
+			*size = 0;
+		return 0;
+	}
+
+	p = (byte*)((uintptr)s->start<<PageShift);
+	if(s->sizeclass == 0) {
+		// Large object.
+		if(base)
+			*base = p;
+		if(size)
+			*size = s->npages<<PageShift;
+		return 1;
+	}
+
+	n = s->elemsize;
+	if(base) {
+		i = ((byte*)v - p)/n;
+		*base = p + i*n;
+	}
+	if(size)
+		*size = n;
+
+	return 1;
+}
+
+void
+runtime_purgecachedstats(MCache *c)
+{
+	MHeap *h;
+	int32 i;
+
+	// Protected by either heap or GC lock.
+	h = &runtime_mheap;
+	mstats.heap_alloc += c->local_cachealloc;
+	c->local_cachealloc = 0;
+	mstats.nlookup += c->local_nlookup;
+	c->local_nlookup = 0;
+	h->largefree += c->local_largefree;
+	c->local_largefree = 0;
+	h->nlargefree += c->local_nlargefree;
+	c->local_nlargefree = 0;
+	for(i=0; i<(int32)nelem(c->local_nsmallfree); i++) {
+		h->nsmallfree[i] += c->local_nsmallfree[i];
+		c->local_nsmallfree[i] = 0;
+	}
+}
+
+extern uintptr runtime_sizeof_C_MStats
+  __asm__ (GOSYM_PREFIX "runtime.Sizeof_C_MStats");
+
+// Size of the trailing by_size array differs between Go and C,
+// NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
+// sizeof_C_MStats is what C thinks about size of Go struct.
+
+// Initialized in mallocinit because it's defined in go/runtime/mem.go.
+
+#define MaxArena32 (2U<<30)
+
+void
+runtime_mallocinit(void)
+{
+	byte *p, *p1;
+	uintptr arena_size, bitmap_size, spans_size, p_size;
+	extern byte _end[];
+	uintptr limit;
+	uint64 i;
+	bool reserved;
+
+	runtime_sizeof_C_MStats = sizeof(MStats) - (NumSizeClasses - 61) * sizeof(mstats.by_size[0]);
+
+	p = nil;
+	p_size = 0;
+	arena_size = 0;
+	bitmap_size = 0;
+	spans_size = 0;
+	reserved = false;
+
+	// for 64-bit build
+	USED(p);
+	USED(p_size);
+	USED(arena_size);
+	USED(bitmap_size);
+	USED(spans_size);
+
+	runtime_InitSizes();
+
+	if(runtime_class_to_size[TinySizeClass] != TinySize)
+		runtime_throw("bad TinySizeClass");
+
+	// limit = runtime_memlimit();
+	// See https://code.google.com/p/go/issues/detail?id=5049
+	// TODO(rsc): Fix after 1.1.
+	limit = 0;
+
+	// Set up the allocation arena, a contiguous area of memory where
+	// allocated data will be found.  The arena begins with a bitmap large
+	// enough to hold 4 bits per allocated word.
+	if(sizeof(void*) == 8 && (limit == 0 || limit > (1<<30))) {
+		// On a 64-bit machine, allocate from a single contiguous reservation.
+		// 128 GB (MaxMem) should be big enough for now.
+		//
+		// The code will work with the reservation at any address, but ask
+		// SysReserve to use 0x0000XXc000000000 if possible (XX=00...7f).
+		// Allocating a 128 GB region takes away 37 bits, and the amd64
+		// doesn't let us choose the top 17 bits, so that leaves the 11 bits
+		// in the middle of 0x00c0 for us to choose.  Choosing 0x00c0 means
+		// that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x00df.
+		// In little-endian, that's c0 00, c1 00, ..., df 00. None of those are valid
+		// UTF-8 sequences, and they are otherwise as far away from 
+		// ff (likely a common byte) as possible.  If that fails, we try other 0xXXc0
+		// addresses.  An earlier attempt to use 0x11f8 caused out of memory errors
+		// on OS X during thread allocations.  0x00c0 causes conflicts with
+		// AddressSanitizer which reserves all memory up to 0x0100.
+		// These choices are both for debuggability and to reduce the
+		// odds of the conservative garbage collector not collecting memory
+		// because some non-pointer block of memory had a bit pattern
+		// that matched a memory address.
+		//
+		// Actually we reserve 136 GB (because the bitmap ends up being 8 GB)
+		// but it hardly matters: e0 00 is not valid UTF-8 either.
+		//
+		// If this fails we fall back to the 32 bit memory mechanism
+		arena_size = MaxMem;
+		bitmap_size = arena_size / (sizeof(void*)*8/4);
+		spans_size = arena_size / PageSize * sizeof(runtime_mheap.spans[0]);
+		spans_size = ROUND(spans_size, PageSize);
+		for(i = 0; i < HeapBaseOptions; i++) {
+			p = HeapBase(i);
+			p_size = bitmap_size + spans_size + arena_size + PageSize;
+			p = runtime_SysReserve(p, p_size, &reserved);
+			if(p != nil)
+				break;
+		}
+	}
+	if (p == nil) {
+		// On a 32-bit machine, we can't typically get away
+		// with a giant virtual address space reservation.
+		// Instead we map the memory information bitmap
+		// immediately after the data segment, large enough
+		// to handle another 2GB of mappings (256 MB),
+		// along with a reservation for another 512 MB of memory.
+		// When that gets used up, we'll start asking the kernel
+		// for any memory anywhere and hope it's in the 2GB
+		// following the bitmap (presumably the executable begins
+		// near the bottom of memory, so we'll have to use up
+		// most of memory before the kernel resorts to giving out
+		// memory before the beginning of the text segment).
+		//
+		// Alternatively we could reserve 512 MB bitmap, enough
+		// for 4GB of mappings, and then accept any memory the
+		// kernel threw at us, but normally that's a waste of 512 MB
+		// of address space, which is probably too much in a 32-bit world.
+		bitmap_size = MaxArena32 / (sizeof(void*)*8/4);
+		arena_size = 512<<20;
+		spans_size = MaxArena32 / PageSize * sizeof(runtime_mheap.spans[0]);
+		if(limit > 0 && arena_size+bitmap_size+spans_size > limit) {
+			bitmap_size = (limit / 9) & ~((1<<PageShift) - 1);
+			arena_size = bitmap_size * 8;
+			spans_size = arena_size / PageSize * sizeof(runtime_mheap.spans[0]);
+		}
+		spans_size = ROUND(spans_size, PageSize);
+
+		// SysReserve treats the address we ask for, end, as a hint,
+		// not as an absolute requirement.  If we ask for the end
+		// of the data segment but the operating system requires
+		// a little more space before we can start allocating, it will
+		// give out a slightly higher pointer.  Except QEMU, which
+		// is buggy, as usual: it won't adjust the pointer upward.
+		// So adjust it upward a little bit ourselves: 1/4 MB to get
+		// away from the running binary image and then round up
+		// to a MB boundary.
+		p = (byte*)ROUND((uintptr)_end + (1<<18), 1<<20);
+		p_size = bitmap_size + spans_size + arena_size + PageSize;
+		p = runtime_SysReserve(p, p_size, &reserved);
+		if(p == nil)
+			runtime_throw("runtime: cannot reserve arena virtual address space");
+	}
+
+	// PageSize can be larger than OS definition of page size,
+	// so SysReserve can give us a PageSize-unaligned pointer.
+	// To overcome this we ask for PageSize more and round up the pointer.
+	p1 = (byte*)ROUND((uintptr)p, PageSize);
+
+	runtime_mheap.spans = (MSpan**)p1;
+	runtime_mheap.bitmap = p1 + spans_size;
+	runtime_mheap.arena_start = p1 + spans_size + bitmap_size;
+	runtime_mheap.arena_used = runtime_mheap.arena_start;
+	runtime_mheap.arena_end = p + p_size;
+	runtime_mheap.arena_reserved = reserved;
+
+	if(((uintptr)runtime_mheap.arena_start & (PageSize-1)) != 0)
+		runtime_throw("misrounded allocation in mallocinit");
+
+	// Initialize the rest of the allocator.	
+	runtime_MHeap_Init(&runtime_mheap);
+	runtime_m()->mcache = runtime_allocmcache();
+
+	// See if it works.
+	runtime_free(runtime_malloc(TinySize));
+}
+
+void*
+runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
+{
+	byte *p, *p_end;
+	uintptr p_size;
+	bool reserved;
+
+
+	if(n > (uintptr)(h->arena_end - h->arena_used)) {
+		// We are in 32-bit mode, maybe we didn't use all possible address space yet.
+		// Reserve some more space.
+		byte *new_end;
+
+		p_size = ROUND(n + PageSize, 256<<20);
+		new_end = h->arena_end + p_size;
+		if(new_end <= h->arena_start + MaxArena32) {
+			// TODO: It would be bad if part of the arena
+			// is reserved and part is not.
+			p = runtime_SysReserve(h->arena_end, p_size, &reserved);
+			if(p == h->arena_end) {
+				h->arena_end = new_end;
+				h->arena_reserved = reserved;
+			}
+			else if(p+p_size <= h->arena_start + MaxArena32) {
+				// Keep everything page-aligned.
+				// Our pages are bigger than hardware pages.
+				h->arena_end = p+p_size;
+				h->arena_used = p + (-(uintptr)p&(PageSize-1));
+				h->arena_reserved = reserved;
+			} else {
+				uint64 stat;
+				stat = 0;
+				runtime_SysFree(p, p_size, &stat);
+			}
+		}
+	}
+	if(n <= (uintptr)(h->arena_end - h->arena_used)) {
+		// Keep taking from our reservation.
+		p = h->arena_used;
+		runtime_SysMap(p, n, h->arena_reserved, &mstats.heap_sys);
+		h->arena_used += n;
+		runtime_MHeap_MapBits(h);
+		runtime_MHeap_MapSpans(h);
+		if(raceenabled)
+			runtime_racemapshadow(p, n);
+		
+		if(((uintptr)p & (PageSize-1)) != 0)
+			runtime_throw("misrounded allocation in MHeap_SysAlloc");
+		return p;
+	}
+	
+	// If using 64-bit, our reservation is all we have.
+	if((uintptr)(h->arena_end - h->arena_start) >= MaxArena32)
+		return nil;
+
+	// On 32-bit, once the reservation is gone we can
+	// try to get memory at a location chosen by the OS
+	// and hope that it is in the range we allocated bitmap for.
+	p_size = ROUND(n, PageSize) + PageSize;
+	p = runtime_SysAlloc(p_size, &mstats.heap_sys);
+	if(p == nil)
+		return nil;
+
+	if(p < h->arena_start || (uintptr)(p+p_size - h->arena_start) >= MaxArena32) {
+		runtime_printf("runtime: memory allocated by OS (%p) not in usable range [%p,%p)\n",
+			p, h->arena_start, h->arena_start+MaxArena32);
+		runtime_SysFree(p, p_size, &mstats.heap_sys);
+		return nil;
+	}
+	
+	p_end = p + p_size;
+	p += -(uintptr)p & (PageSize-1);
+	if(p+n > h->arena_used) {
+		h->arena_used = p+n;
+		if(p_end > h->arena_end)
+			h->arena_end = p_end;
+		runtime_MHeap_MapBits(h);
+		runtime_MHeap_MapSpans(h);
+		if(raceenabled)
+			runtime_racemapshadow(p, n);
+	}
+	
+	if(((uintptr)p & (PageSize-1)) != 0)
+		runtime_throw("misrounded allocation in MHeap_SysAlloc");
+	return p;
+}
+
+static struct
+{
+	Lock	lock;
+	byte*	pos;
+	byte*	end;
+} persistent;
+
+enum
+{
+	PersistentAllocChunk	= 256<<10,
+	PersistentAllocMaxBlock	= 64<<10,  // VM reservation granularity is 64K on windows
+};
+
+// Wrapper around SysAlloc that can allocate small chunks.
+// There is no associated free operation.
+// Intended for things like function/type/debug-related persistent data.
+// If align is 0, uses default align (currently 8).
+void*
+runtime_persistentalloc(uintptr size, uintptr align, uint64 *stat)
+{
+	byte *p;
+
+	if(align != 0) {
+		if(align&(align-1))
+			runtime_throw("persistentalloc: align is not a power of 2");
+		if(align > PageSize)
+			runtime_throw("persistentalloc: align is too large");
+	} else
+		align = 8;
+	if(size >= PersistentAllocMaxBlock)
+		return runtime_SysAlloc(size, stat);
+	runtime_lock(&persistent.lock);
+	persistent.pos = (byte*)ROUND((uintptr)persistent.pos, align);
+	if(persistent.pos + size > persistent.end) {
+		persistent.pos = runtime_SysAlloc(PersistentAllocChunk, &mstats.other_sys);
+		if(persistent.pos == nil) {
+			runtime_unlock(&persistent.lock);
+			runtime_throw("runtime: cannot allocate memory");
+		}
+		persistent.end = persistent.pos + PersistentAllocChunk;
+	}
+	p = persistent.pos;
+	persistent.pos += size;
+	runtime_unlock(&persistent.lock);
+	if(stat != &mstats.other_sys) {
+		// reaccount the allocation against provided stat
+		runtime_xadd64(stat, size);
+		runtime_xadd64(&mstats.other_sys, -(uint64)size);
+	}
+	return p;
+}
+
+static void
+settype(MSpan *s, void *v, uintptr typ)
+{
+	uintptr size, ofs, j, t;
+	uintptr ntypes, nbytes2, nbytes3;
+	uintptr *data2;
+	byte *data3;
+
+	if(s->sizeclass == 0) {
+		s->types.compression = MTypes_Single;
+		s->types.data = typ;
+		return;
+	}
+	size = s->elemsize;
+	ofs = ((uintptr)v - (s->start<<PageShift)) / size;
+
+	switch(s->types.compression) {
+	case MTypes_Empty:
+		ntypes = (s->npages << PageShift) / size;
+		nbytes3 = 8*sizeof(uintptr) + 1*ntypes;
+		data3 = runtime_mallocgc(nbytes3, 0, FlagNoProfiling|FlagNoScan|FlagNoInvokeGC);
+		s->types.compression = MTypes_Bytes;
+		s->types.data = (uintptr)data3;
+		((uintptr*)data3)[1] = typ;
+		data3[8*sizeof(uintptr) + ofs] = 1;
+		break;
+		
+	case MTypes_Words:
+		((uintptr*)s->types.data)[ofs] = typ;
+		break;
+		
+	case MTypes_Bytes:
+		data3 = (byte*)s->types.data;
+		for(j=1; j<8; j++) {
+			if(((uintptr*)data3)[j] == typ) {
+				break;
+			}
+			if(((uintptr*)data3)[j] == 0) {
+				((uintptr*)data3)[j] = typ;
+				break;
+			}
+		}
+		if(j < 8) {
+			data3[8*sizeof(uintptr) + ofs] = j;
+		} else {
+			ntypes = (s->npages << PageShift) / size;
+			nbytes2 = ntypes * sizeof(uintptr);
+			data2 = runtime_mallocgc(nbytes2, 0, FlagNoProfiling|FlagNoScan|FlagNoInvokeGC);
+			s->types.compression = MTypes_Words;
+			s->types.data = (uintptr)data2;
+			
+			// Move the contents of data3 to data2. Then deallocate data3.
+			for(j=0; j<ntypes; j++) {
+				t = data3[8*sizeof(uintptr) + j];
+				t = ((uintptr*)data3)[t];
+				data2[j] = t;
+			}
+			data2[ofs] = typ;
+		}
+		break;
+	}
+}
+
+uintptr
+runtime_gettype(void *v)
+{
+	MSpan *s;
+	uintptr t, ofs;
+	byte *data;
+
+	s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
+	if(s != nil) {
+		t = 0;
+		switch(s->types.compression) {
+		case MTypes_Empty:
+			break;
+		case MTypes_Single:
+			t = s->types.data;
+			break;
+		case MTypes_Words:
+			ofs = (uintptr)v - (s->start<<PageShift);
+			t = ((uintptr*)s->types.data)[ofs/s->elemsize];
+			break;
+		case MTypes_Bytes:
+			ofs = (uintptr)v - (s->start<<PageShift);
+			data = (byte*)s->types.data;
+			t = data[8*sizeof(uintptr) + ofs/s->elemsize];
+			t = ((uintptr*)data)[t];
+			break;
+		default:
+			runtime_throw("runtime_gettype: invalid compression kind");
+		}
+		if(0) {
+			runtime_printf("%p -> %d,%X\n", v, (int32)s->types.compression, (int64)t);
+		}
+		return t;
+	}
+	return 0;
+}
+
+// Runtime stubs.
+
+void*
+runtime_mal(uintptr n)
+{
+	return runtime_mallocgc(n, 0, 0);
+}
+
+func new(typ *Type) (ret *uint8) {
+	ret = runtime_mallocgc(typ->__size, (uintptr)typ | TypeInfo_SingleObject, typ->kind&KindNoPointers ? FlagNoScan : 0);
+}
+
+static void*
+cnew(const Type *typ, intgo n, int32 objtyp)
+{
+	if((objtyp&(PtrSize-1)) != objtyp)
+		runtime_throw("runtime: invalid objtyp");
+	if(n < 0 || (typ->__size > 0 && (uintptr)n > (MaxMem/typ->__size)))
+		runtime_panicstring("runtime: allocation size out of range");
+	return runtime_mallocgc(typ->__size*n, (uintptr)typ | objtyp, typ->kind&KindNoPointers ? FlagNoScan : 0);
+}
+
+// same as runtime_new, but callable from C
+void*
+runtime_cnew(const Type *typ)
+{
+	return cnew(typ, 1, TypeInfo_SingleObject);
+}
+
+void*
+runtime_cnewarray(const Type *typ, intgo n)
+{
+	return cnew(typ, n, TypeInfo_Array);
+}
+
+func GC() {
+	runtime_gc(2);  // force GC and do eager sweep
+}
+
+func SetFinalizer(obj Eface, finalizer Eface) {
+	byte *base;
+	uintptr size;
+	const FuncType *ft;
+	const Type *fint;
+	const PtrType *ot;
+
+	if(obj.__type_descriptor == nil) {
+		runtime_printf("runtime.SetFinalizer: first argument is nil interface\n");
+		goto throw;
+	}
+	if(obj.__type_descriptor->__code != GO_PTR) {
+		runtime_printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.__type_descriptor->__reflection);
+		goto throw;
+	}
+	ot = (const PtrType*)obj.type;
+	// As an implementation detail we do not run finalizers for zero-sized objects,
+	// because we use &runtime_zerobase for all such allocations.
+	if(ot->__element_type != nil && ot->__element_type->__size == 0)
+		return;
+	// The following check is required for cases when a user passes a pointer to composite literal,
+	// but compiler makes it a pointer to global. For example:
+	//	var Foo = &Object{}
+	//	func main() {
+	//		runtime.SetFinalizer(Foo, nil)
+	//	}
+	// See issue 7656.
+	if((byte*)obj.__object < runtime_mheap.arena_start || runtime_mheap.arena_used <= (byte*)obj.__object)
+		return;
+	if(!runtime_mlookup(obj.__object, &base, &size, nil) || obj.__object != base) {
+		// As an implementation detail we allow to set finalizers for an inner byte
+		// of an object if it could come from tiny alloc (see mallocgc for details).
+		if(ot->__element_type == nil || (ot->__element_type->__code&KindNoPointers) == 0 || ot->__element_type->__size >= TinySize) {
+			runtime_printf("runtime.SetFinalizer: pointer not at beginning of allocated block (%p)\n", obj.__object);
+			goto throw;
+		}
+	}
+	if(finalizer.__type_descriptor != nil) {
+		runtime_createfing();
+		if(finalizer.__type_descriptor->__code != GO_FUNC)
+			goto badfunc;
+		ft = (const FuncType*)finalizer.__type_descriptor;
+		if(ft->__dotdotdot || ft->__in.__count != 1)
+			goto badfunc;
+		fint = *(Type**)ft->__in.__values;
+		if(__go_type_descriptors_equal(fint, obj.__type_descriptor)) {
+			// ok - same type
+		} else if(fint->__code == GO_PTR && (fint->__uncommon == nil || fint->__uncommon->__name == nil || obj.type->__uncommon == nil || obj.type->__uncommon->__name == nil) && __go_type_descriptors_equal(((const PtrType*)fint)->__element_type, ((const PtrType*)obj.type)->__element_type)) {
+			// ok - not same type, but both pointers,
+			// one or the other is unnamed, and same element type, so assignable.
+		} else if(fint->kind == GO_INTERFACE && ((const InterfaceType*)fint)->__methods.__count == 0) {
+			// ok - satisfies empty interface
+		} else if(fint->kind == GO_INTERFACE && __go_convert_interface_2(fint, obj.__type_descriptor, 1) != nil) {
+			// ok - satisfies non-empty interface
+		} else
+			goto badfunc;
+
+		ot = (const PtrType*)obj.__type_descriptor;
+		if(!runtime_addfinalizer(obj.__object, *(FuncVal**)finalizer.__object, ft, ot)) {
+			runtime_printf("runtime.SetFinalizer: finalizer already set\n");
+			goto throw;
+		}
+	} else {
+		// NOTE: asking to remove a finalizer when there currently isn't one set is OK.
+		runtime_removefinalizer(obj.__object);
+	}
+	return;
+
+badfunc:
+	runtime_printf("runtime.SetFinalizer: cannot pass %S to finalizer %S\n", *obj.__type_descriptor->__reflection, *finalizer.__type_descriptor->__reflection);
+throw:
+	runtime_throw("runtime.SetFinalizer");
+}
diff --git a/third_party/gofrontend/libgo/runtime/malloc.h b/third_party/gofrontend/libgo/runtime/malloc.h
new file mode 100644
index 0000000..b2a6e19
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/malloc.h
@@ -0,0 +1,658 @@
+// 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.
+
+// Memory allocator, based on tcmalloc.
+// http://goog-perftools.sourceforge.net/doc/tcmalloc.html
+
+// The main allocator works in runs of pages.
+// Small allocation sizes (up to and including 32 kB) are
+// rounded to one of about 100 size classes, each of which
+// has its own free list of objects of exactly that size.
+// Any free page of memory can be split into a set of objects
+// of one size class, which are then managed using free list
+// allocators.
+//
+// The allocator's data structures are:
+//
+//	FixAlloc: a free-list allocator for fixed-size objects,
+//		used to manage storage used by the allocator.
+//	MHeap: the malloc heap, managed at page (4096-byte) granularity.
+//	MSpan: a run of pages managed by the MHeap.
+//	MCentral: a shared free list for a given size class.
+//	MCache: a per-thread (in Go, per-P) cache for small objects.
+//	MStats: allocation statistics.
+//
+// Allocating a small object proceeds up a hierarchy of caches:
+//
+//	1. Round the size up to one of the small size classes
+//	   and look in the corresponding MCache free list.
+//	   If the list is not empty, allocate an object from it.
+//	   This can all be done without acquiring a lock.
+//
+//	2. If the MCache free list is empty, replenish it by
+//	   taking a bunch of objects from the MCentral free list.
+//	   Moving a bunch amortizes the cost of acquiring the MCentral lock.
+//
+//	3. If the MCentral free list is empty, replenish it by
+//	   allocating a run of pages from the MHeap and then
+//	   chopping that memory into a objects of the given size.
+//	   Allocating many objects amortizes the cost of locking
+//	   the heap.
+//
+//	4. If the MHeap is empty or has no page runs large enough,
+//	   allocate a new group of pages (at least 1MB) from the
+//	   operating system.  Allocating a large run of pages
+//	   amortizes the cost of talking to the operating system.
+//
+// Freeing a small object proceeds up the same hierarchy:
+//
+//	1. Look up the size class for the object and add it to
+//	   the MCache free list.
+//
+//	2. If the MCache free list is too long or the MCache has
+//	   too much memory, return some to the MCentral free lists.
+//
+//	3. If all the objects in a given span have returned to
+//	   the MCentral list, return that span to the page heap.
+//
+//	4. If the heap has too much memory, return some to the
+//	   operating system.
+//
+//	TODO(rsc): Step 4 is not implemented.
+//
+// Allocating and freeing a large object uses the page heap
+// directly, bypassing the MCache and MCentral free lists.
+//
+// The small objects on the MCache and MCentral free lists
+// may or may not be zeroed.  They are zeroed if and only if
+// the second word of the object is zero.  A span in the
+// page heap is zeroed unless s->needzero is set. When a span
+// is allocated to break into small objects, it is zeroed if needed
+// and s->needzero is set. There are two main benefits to delaying the
+// zeroing this way:
+//
+//	1. stack frames allocated from the small object lists
+//	   or the page heap can avoid zeroing altogether.
+//	2. the cost of zeroing when reusing a small object is
+//	   charged to the mutator, not the garbage collector.
+//
+// This C code was written with an eye toward translating to Go
+// in the future.  Methods have the form Type_Method(Type *t, ...).
+
+typedef struct MCentral	MCentral;
+typedef struct MHeap	MHeap;
+typedef struct MSpan	MSpan;
+typedef struct MStats	MStats;
+typedef struct MLink	MLink;
+typedef struct MTypes	MTypes;
+typedef struct GCStats	GCStats;
+
+enum
+{
+	PageShift	= 13,
+	PageSize	= 1<<PageShift,
+	PageMask	= PageSize - 1,
+};
+typedef	uintptr	PageID;		// address >> PageShift
+
+enum
+{
+	// Computed constant.  The definition of MaxSmallSize and the
+	// algorithm in msize.c produce some number of different allocation
+	// size classes.  NumSizeClasses is that number.  It's needed here
+	// because there are static arrays of this length; when msize runs its
+	// size choosing algorithm it double-checks that NumSizeClasses agrees.
+	NumSizeClasses = 67,
+
+	// Tunable constants.
+	MaxSmallSize = 32<<10,
+
+	// Tiny allocator parameters, see "Tiny allocator" comment in malloc.goc.
+	TinySize = 16,
+	TinySizeClass = 2,
+
+	FixAllocChunk = 16<<10,		// Chunk size for FixAlloc
+	MaxMHeapList = 1<<(20 - PageShift),	// Maximum page length for fixed-size list in MHeap.
+	HeapAllocChunk = 1<<20,		// Chunk size for heap growth
+
+	// Number of bits in page to span calculations (4k pages).
+	// On Windows 64-bit we limit the arena to 32GB or 35 bits (see below for reason).
+	// On other 64-bit platforms, we limit the arena to 128GB, or 37 bits.
+	// On 32-bit, we don't bother limiting anything, so we use the full 32-bit address.
+#if __SIZEOF_POINTER__ == 8
+#ifdef GOOS_windows
+	// Windows counts memory used by page table into committed memory
+	// of the process, so we can't reserve too much memory.
+	// See http://golang.org/issue/5402 and http://golang.org/issue/5236.
+	MHeapMap_Bits = 35 - PageShift,
+#else
+	MHeapMap_Bits = 37 - PageShift,
+#endif
+#else
+	MHeapMap_Bits = 32 - PageShift,
+#endif
+
+	// Max number of threads to run garbage collection.
+	// 2, 3, and 4 are all plausible maximums depending
+	// on the hardware details of the machine.  The garbage
+	// collector scales well to 8 cpus.
+	MaxGcproc = 8,
+};
+
+// Maximum memory allocation size, a hint for callers.
+// This must be a #define instead of an enum because it
+// is so large.
+#if __SIZEOF_POINTER__ == 8
+#define	MaxMem	(1ULL<<(MHeapMap_Bits+PageShift))	/* 128 GB or 32 GB */
+#else
+#define	MaxMem	((uintptr)-1)
+#endif
+
+// A generic linked list of blocks.  (Typically the block is bigger than sizeof(MLink).)
+struct MLink
+{
+	MLink *next;
+};
+
+// SysAlloc obtains a large chunk of zeroed memory from the
+// operating system, typically on the order of a hundred kilobytes
+// or a megabyte.
+// NOTE: SysAlloc returns OS-aligned memory, but the heap allocator
+// may use larger alignment, so the caller must be careful to realign the
+// memory obtained by SysAlloc.
+//
+// SysUnused notifies the operating system that the contents
+// of the memory region are no longer needed and can be reused
+// for other purposes.
+// SysUsed notifies the operating system that the contents
+// of the memory region are needed again.
+//
+// SysFree returns it unconditionally; this is only used if
+// an out-of-memory error has been detected midway through
+// an allocation.  It is okay if SysFree is a no-op.
+//
+// SysReserve reserves address space without allocating memory.
+// If the pointer passed to it is non-nil, the caller wants the
+// reservation there, but SysReserve can still choose another
+// location if that one is unavailable.  On some systems and in some
+// cases SysReserve will simply check that the address space is
+// available and not actually reserve it.  If SysReserve returns
+// non-nil, it sets *reserved to true if the address space is
+// reserved, false if it has merely been checked.
+// NOTE: SysReserve returns OS-aligned memory, but the heap allocator
+// may use larger alignment, so the caller must be careful to realign the
+// memory obtained by SysAlloc.
+//
+// SysMap maps previously reserved address space for use.
+// The reserved argument is true if the address space was really
+// reserved, not merely checked.
+//
+// SysFault marks a (already SysAlloc'd) region to fault
+// if accessed.  Used only for debugging the runtime.
+
+void*	runtime_SysAlloc(uintptr nbytes, uint64 *stat);
+void	runtime_SysFree(void *v, uintptr nbytes, uint64 *stat);
+void	runtime_SysUnused(void *v, uintptr nbytes);
+void	runtime_SysUsed(void *v, uintptr nbytes);
+void	runtime_SysMap(void *v, uintptr nbytes, bool reserved, uint64 *stat);
+void*	runtime_SysReserve(void *v, uintptr nbytes, bool *reserved);
+void	runtime_SysFault(void *v, uintptr nbytes);
+
+// FixAlloc is a simple free-list allocator for fixed size objects.
+// Malloc uses a FixAlloc wrapped around SysAlloc to manages its
+// MCache and MSpan objects.
+//
+// Memory returned by FixAlloc_Alloc is not zeroed.
+// The caller is responsible for locking around FixAlloc calls.
+// Callers can keep state in the object but the first word is
+// smashed by freeing and reallocating.
+struct FixAlloc
+{
+	uintptr	size;
+	void	(*first)(void *arg, byte *p);	// called first time p is returned
+	void*	arg;
+	MLink*	list;
+	byte*	chunk;
+	uint32	nchunk;
+	uintptr	inuse;	// in-use bytes now
+	uint64*	stat;
+};
+
+void	runtime_FixAlloc_Init(FixAlloc *f, uintptr size, void (*first)(void*, byte*), void *arg, uint64 *stat);
+void*	runtime_FixAlloc_Alloc(FixAlloc *f);
+void	runtime_FixAlloc_Free(FixAlloc *f, void *p);
+
+
+// Statistics.
+// Shared with Go: if you edit this structure, also edit type MemStats in mem.go.
+struct MStats
+{
+	// General statistics.
+	uint64	alloc;		// bytes allocated and still in use
+	uint64	total_alloc;	// bytes allocated (even if freed)
+	uint64	sys;		// bytes obtained from system (should be sum of xxx_sys below, no locking, approximate)
+	uint64	nlookup;	// number of pointer lookups
+	uint64	nmalloc;	// number of mallocs
+	uint64	nfree;  // number of frees
+
+	// Statistics about malloc heap.
+	// protected by mheap.Lock
+	uint64	heap_alloc;	// bytes allocated and still in use
+	uint64	heap_sys;	// bytes obtained from system
+	uint64	heap_idle;	// bytes in idle spans
+	uint64	heap_inuse;	// bytes in non-idle spans
+	uint64	heap_released;	// bytes released to the OS
+	uint64	heap_objects;	// total number of allocated objects
+
+	// Statistics about allocation of low-level fixed-size structures.
+	// Protected by FixAlloc locks.
+	uint64	stacks_inuse;	// bootstrap stacks
+	uint64	stacks_sys;
+	uint64	mspan_inuse;	// MSpan structures
+	uint64	mspan_sys;
+	uint64	mcache_inuse;	// MCache structures
+	uint64	mcache_sys;
+	uint64	buckhash_sys;	// profiling bucket hash table
+	uint64	gc_sys;
+	uint64	other_sys;
+
+	// Statistics about garbage collector.
+	// Protected by mheap or stopping the world during GC.
+	uint64	next_gc;	// next GC (in heap_alloc time)
+	uint64  last_gc;	// last GC (in absolute time)
+	uint64	pause_total_ns;
+	uint64	pause_ns[256];
+	uint32	numgc;
+	bool	enablegc;
+	bool	debuggc;
+
+	// Statistics about allocation size classes.
+	struct {
+		uint32 size;
+		uint64 nmalloc;
+		uint64 nfree;
+	} by_size[NumSizeClasses];
+};
+
+extern MStats mstats
+  __asm__ (GOSYM_PREFIX "runtime.memStats");
+void	runtime_updatememstats(GCStats *stats);
+
+// Size classes.  Computed and initialized by InitSizes.
+//
+// SizeToClass(0 <= n <= MaxSmallSize) returns the size class,
+//	1 <= sizeclass < NumSizeClasses, for n.
+//	Size class 0 is reserved to mean "not small".
+//
+// class_to_size[i] = largest size in class i
+// class_to_allocnpages[i] = number of pages to allocate when
+//	making new objects in class i
+
+int32	runtime_SizeToClass(int32);
+uintptr	runtime_roundupsize(uintptr);
+extern	int32	runtime_class_to_size[NumSizeClasses];
+extern	int32	runtime_class_to_allocnpages[NumSizeClasses];
+extern	int8	runtime_size_to_class8[1024/8 + 1];
+extern	int8	runtime_size_to_class128[(MaxSmallSize-1024)/128 + 1];
+extern	void	runtime_InitSizes(void);
+
+
+typedef struct MCacheList MCacheList;
+struct MCacheList
+{
+	MLink *list;
+	uint32 nlist;
+};
+
+// Per-thread (in Go, per-P) cache for small objects.
+// No locking needed because it is per-thread (per-P).
+struct MCache
+{
+	// The following members are accessed on every malloc,
+	// so they are grouped here for better caching.
+	int32 next_sample;		// trigger heap sample after allocating this many bytes
+	intptr local_cachealloc;	// bytes allocated (or freed) from cache since last lock of heap
+	// Allocator cache for tiny objects w/o pointers.
+	// See "Tiny allocator" comment in malloc.goc.
+	byte*	tiny;
+	uintptr	tinysize;
+	// The rest is not accessed on every malloc.
+	MSpan*	alloc[NumSizeClasses];	// spans to allocate from
+	MCacheList free[NumSizeClasses];// lists of explicitly freed objects
+	// Local allocator stats, flushed during GC.
+	uintptr local_nlookup;		// number of pointer lookups
+	uintptr local_largefree;	// bytes freed for large objects (>MaxSmallSize)
+	uintptr local_nlargefree;	// number of frees for large objects (>MaxSmallSize)
+	uintptr local_nsmallfree[NumSizeClasses];	// number of frees for small objects (<=MaxSmallSize)
+};
+
+MSpan*	runtime_MCache_Refill(MCache *c, int32 sizeclass);
+void	runtime_MCache_Free(MCache *c, MLink *p, int32 sizeclass, uintptr size);
+void	runtime_MCache_ReleaseAll(MCache *c);
+
+// MTypes describes the types of blocks allocated within a span.
+// The compression field describes the layout of the data.
+//
+// MTypes_Empty:
+//     All blocks are free, or no type information is available for
+//     allocated blocks.
+//     The data field has no meaning.
+// MTypes_Single:
+//     The span contains just one block.
+//     The data field holds the type information.
+//     The sysalloc field has no meaning.
+// MTypes_Words:
+//     The span contains multiple blocks.
+//     The data field points to an array of type [NumBlocks]uintptr,
+//     and each element of the array holds the type of the corresponding
+//     block.
+// MTypes_Bytes:
+//     The span contains at most seven different types of blocks.
+//     The data field points to the following structure:
+//         struct {
+//             type  [8]uintptr       // type[0] is always 0
+//             index [NumBlocks]byte
+//         }
+//     The type of the i-th block is: data.type[data.index[i]]
+enum
+{
+	MTypes_Empty = 0,
+	MTypes_Single = 1,
+	MTypes_Words = 2,
+	MTypes_Bytes = 3,
+};
+struct MTypes
+{
+	byte	compression;	// one of MTypes_*
+	uintptr	data;
+};
+
+enum
+{
+	KindSpecialFinalizer = 1,
+	KindSpecialProfile = 2,
+	// Note: The finalizer special must be first because if we're freeing
+	// an object, a finalizer special will cause the freeing operation
+	// to abort, and we want to keep the other special records around
+	// if that happens.
+};
+
+typedef struct Special Special;
+struct Special
+{
+	Special*	next;	// linked list in span
+	uint16		offset;	// span offset of object
+	byte		kind;	// kind of Special
+};
+
+// The described object has a finalizer set for it.
+typedef struct SpecialFinalizer SpecialFinalizer;
+struct SpecialFinalizer
+{
+	Special		special;
+	FuncVal*	fn;
+	const FuncType*	ft;
+	const PtrType*	ot;
+};
+
+// The described object is being heap profiled.
+typedef struct Bucket Bucket; // from mprof.goc
+typedef struct SpecialProfile SpecialProfile;
+struct SpecialProfile
+{
+	Special	special;
+	Bucket*	b;
+};
+
+// An MSpan is a run of pages.
+enum
+{
+	MSpanInUse = 0,
+	MSpanFree,
+	MSpanListHead,
+	MSpanDead,
+};
+struct MSpan
+{
+	MSpan	*next;		// in a span linked list
+	MSpan	*prev;		// in a span linked list
+	PageID	start;		// starting page number
+	uintptr	npages;		// number of pages in span
+	MLink	*freelist;	// list of free objects
+	// sweep generation:
+	// if sweepgen == h->sweepgen - 2, the span needs sweeping
+	// if sweepgen == h->sweepgen - 1, the span is currently being swept
+	// if sweepgen == h->sweepgen, the span is swept and ready to use
+	// h->sweepgen is incremented by 2 after every GC
+	uint32	sweepgen;
+	uint16	ref;		// capacity - number of objects in freelist
+	uint8	sizeclass;	// size class
+	bool	incache;	// being used by an MCache
+	uint8	state;		// MSpanInUse etc
+	uint8	needzero;	// needs to be zeroed before allocation
+	uintptr	elemsize;	// computed from sizeclass or from npages
+	int64   unusedsince;	// First time spotted by GC in MSpanFree state
+	uintptr npreleased;	// number of pages released to the OS
+	byte	*limit;		// end of data in span
+	MTypes	types;		// types of allocated objects in this span
+	Lock	specialLock;	// guards specials list
+	Special	*specials;	// linked list of special records sorted by offset.
+	MLink	*freebuf;	// objects freed explicitly, not incorporated into freelist yet
+};
+
+void	runtime_MSpan_Init(MSpan *span, PageID start, uintptr npages);
+void	runtime_MSpan_EnsureSwept(MSpan *span);
+bool	runtime_MSpan_Sweep(MSpan *span);
+
+// Every MSpan is in one doubly-linked list,
+// either one of the MHeap's free lists or one of the
+// MCentral's span lists.  We use empty MSpan structures as list heads.
+void	runtime_MSpanList_Init(MSpan *list);
+bool	runtime_MSpanList_IsEmpty(MSpan *list);
+void	runtime_MSpanList_Insert(MSpan *list, MSpan *span);
+void	runtime_MSpanList_InsertBack(MSpan *list, MSpan *span);
+void	runtime_MSpanList_Remove(MSpan *span);	// from whatever list it is in
+
+
+// Central list of free objects of a given size.
+struct MCentral
+{
+	Lock  lock;
+	int32 sizeclass;
+	MSpan nonempty;	// list of spans with a free object
+	MSpan empty;	// list of spans with no free objects (or cached in an MCache)
+	int32 nfree;	// # of objects available in nonempty spans
+};
+
+void	runtime_MCentral_Init(MCentral *c, int32 sizeclass);
+MSpan*	runtime_MCentral_CacheSpan(MCentral *c);
+void	runtime_MCentral_UncacheSpan(MCentral *c, MSpan *s);
+bool	runtime_MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end);
+void	runtime_MCentral_FreeList(MCentral *c, MLink *start); // TODO: need this?
+
+// Main malloc heap.
+// The heap itself is the "free[]" and "large" arrays,
+// but all the other global data is here too.
+struct MHeap
+{
+	Lock lock;
+	MSpan free[MaxMHeapList];	// free lists of given length
+	MSpan freelarge;		// free lists length >= MaxMHeapList
+	MSpan busy[MaxMHeapList];	// busy lists of large objects of given length
+	MSpan busylarge;		// busy lists of large objects length >= MaxMHeapList
+	MSpan **allspans;		// all spans out there
+	MSpan **sweepspans;		// copy of allspans referenced by sweeper
+	uint32	nspan;
+	uint32	nspancap;
+	uint32	sweepgen;		// sweep generation, see comment in MSpan
+	uint32	sweepdone;		// all spans are swept
+
+	// span lookup
+	MSpan**	spans;
+	uintptr	spans_mapped;
+
+	// range of addresses we might see in the heap
+	byte *bitmap;
+	uintptr bitmap_mapped;
+	byte *arena_start;
+	byte *arena_used;
+	byte *arena_end;
+	bool arena_reserved;
+
+	// central free lists for small size classes.
+	// the padding makes sure that the MCentrals are
+	// spaced CacheLineSize bytes apart, so that each MCentral.Lock
+	// gets its own cache line.
+	struct {
+		MCentral mcentral;
+		byte pad[64];
+	} central[NumSizeClasses];
+
+	FixAlloc spanalloc;	// allocator for Span*
+	FixAlloc cachealloc;	// allocator for MCache*
+	FixAlloc specialfinalizeralloc;	// allocator for SpecialFinalizer*
+	FixAlloc specialprofilealloc;	// allocator for SpecialProfile*
+	Lock speciallock; // lock for sepcial record allocators.
+
+	// Malloc stats.
+	uint64 largefree;	// bytes freed for large objects (>MaxSmallSize)
+	uint64 nlargefree;	// number of frees for large objects (>MaxSmallSize)
+	uint64 nsmallfree[NumSizeClasses];	// number of frees for small objects (<=MaxSmallSize)
+};
+extern MHeap runtime_mheap;
+
+void	runtime_MHeap_Init(MHeap *h);
+MSpan*	runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large, bool needzero);
+void	runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct);
+MSpan*	runtime_MHeap_Lookup(MHeap *h, void *v);
+MSpan*	runtime_MHeap_LookupMaybe(MHeap *h, void *v);
+void	runtime_MGetSizeClassInfo(int32 sizeclass, uintptr *size, int32 *npages, int32 *nobj);
+void*	runtime_MHeap_SysAlloc(MHeap *h, uintptr n);
+void	runtime_MHeap_MapBits(MHeap *h);
+void	runtime_MHeap_MapSpans(MHeap *h);
+void	runtime_MHeap_Scavenger(void*);
+void	runtime_MHeap_SplitSpan(MHeap *h, MSpan *s);
+
+void*	runtime_mallocgc(uintptr size, uintptr typ, uint32 flag);
+void*	runtime_persistentalloc(uintptr size, uintptr align, uint64 *stat);
+int32	runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **s);
+void	runtime_gc(int32 force);
+uintptr	runtime_sweepone(void);
+void	runtime_markscan(void *v);
+void	runtime_marknogc(void *v);
+void	runtime_checkallocated(void *v, uintptr n);
+void	runtime_markfreed(void *v);
+void	runtime_checkfreed(void *v, uintptr n);
+extern	int32	runtime_checking;
+void	runtime_markspan(void *v, uintptr size, uintptr n, bool leftover);
+void	runtime_unmarkspan(void *v, uintptr size);
+void	runtime_purgecachedstats(MCache*);
+void*	runtime_cnew(const Type*);
+void*	runtime_cnewarray(const Type*, intgo);
+void	runtime_tracealloc(void*, uintptr, uintptr);
+void	runtime_tracefree(void*, uintptr);
+void	runtime_tracegc(void);
+
+uintptr	runtime_gettype(void*);
+
+enum
+{
+	// flags to malloc
+	FlagNoScan	= 1<<0,	// GC doesn't have to scan object
+	FlagNoProfiling	= 1<<1,	// must not profile
+	FlagNoGC	= 1<<2,	// must not free or scan for pointers
+	FlagNoZero	= 1<<3, // don't zero memory
+	FlagNoInvokeGC	= 1<<4, // don't invoke GC
+};
+
+typedef struct Obj Obj;
+struct Obj
+{
+	byte	*p;	// data pointer
+	uintptr	n;	// size of data in bytes
+	uintptr	ti;	// type info
+};
+
+void	runtime_MProf_Malloc(void*, uintptr);
+void	runtime_MProf_Free(Bucket*, uintptr, bool);
+void	runtime_MProf_GC(void);
+void	runtime_iterate_memprof(void (*callback)(Bucket*, uintptr, Location*, uintptr, uintptr, uintptr));
+int32	runtime_gcprocs(void);
+void	runtime_helpgc(int32 nproc);
+void	runtime_gchelper(void);
+void	runtime_createfing(void);
+G*	runtime_wakefing(void);
+extern bool	runtime_fingwait;
+extern bool	runtime_fingwake;
+
+void	runtime_setprofilebucket(void *p, Bucket *b);
+
+struct __go_func_type;
+struct __go_ptr_type;
+bool	runtime_addfinalizer(void *p, FuncVal *fn, const struct __go_func_type*, const struct __go_ptr_type*);
+void	runtime_removefinalizer(void*);
+void	runtime_queuefinalizer(void *p, FuncVal *fn, const struct __go_func_type *ft, const struct __go_ptr_type *ot);
+
+void	runtime_freeallspecials(MSpan *span, void *p, uintptr size);
+bool	runtime_freespecial(Special *s, void *p, uintptr size, bool freed);
+
+enum
+{
+	TypeInfo_SingleObject = 0,
+	TypeInfo_Array = 1,
+	TypeInfo_Chan = 2,
+
+	// Enables type information at the end of blocks allocated from heap	
+	DebugTypeAtBlockEnd = 0,
+};
+
+// Information from the compiler about the layout of stack frames.
+typedef struct BitVector BitVector;
+struct BitVector
+{
+	int32 n; // # of bits
+	uint32 *data;
+};
+typedef struct StackMap StackMap;
+struct StackMap
+{
+	int32 n; // number of bitmaps
+	int32 nbit; // number of bits in each bitmap
+	uint32 data[];
+};
+enum {
+	// Pointer map
+	BitsPerPointer = 2,
+	BitsDead = 0,
+	BitsScalar = 1,
+	BitsPointer = 2,
+	BitsMultiWord = 3,
+	// BitsMultiWord will be set for the first word of a multi-word item.
+	// When it is set, one of the following will be set for the second word.
+	BitsString = 0,
+	BitsSlice = 1,
+	BitsIface = 2,
+	BitsEface = 3,
+};
+// Returns pointer map data for the given stackmap index
+// (the index is encoded in PCDATA_StackMapIndex).
+BitVector	runtime_stackmapdata(StackMap *stackmap, int32 n);
+
+// defined in mgc0.go
+void	runtime_gc_m_ptr(Eface*);
+void	runtime_gc_g_ptr(Eface*);
+void	runtime_gc_itab_ptr(Eface*);
+
+void	runtime_memorydump(void);
+int32	runtime_setgcpercent(int32);
+
+// Value we use to mark dead pointers when GODEBUG=gcdead=1.
+#define PoisonGC ((uintptr)0xf969696969696969ULL)
+#define PoisonStack ((uintptr)0x6868686868686868ULL)
+
+struct Workbuf;
+void	runtime_MProf_Mark(struct Workbuf**, void (*)(struct Workbuf**, Obj));
+void	runtime_proc_scan(struct Workbuf**, void (*)(struct Workbuf**, Obj));
+void	runtime_time_scan(struct Workbuf**, void (*)(struct Workbuf**, Obj));
+void	runtime_netpoll_scan(struct Workbuf**, void (*)(struct Workbuf**, Obj));
diff --git a/third_party/gofrontend/libgo/runtime/map.goc b/third_party/gofrontend/libgo/runtime/map.goc
new file mode 100644
index 0000000..e4b8456
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/map.goc
@@ -0,0 +1,72 @@
+// Copyright 2010 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 runtime
+#include "runtime.h"
+#include "map.h"
+
+typedef struct __go_map Hmap;
+typedef struct __go_hash_iter hiter;
+
+/* Access a value in a map, returning a value and a presence indicator.  */
+
+func mapaccess2(t *MapType, h *Hmap, key *byte, val *byte) (present bool) {
+	byte *mapval;
+	size_t valsize;
+
+	mapval = __go_map_index(h, key, 0);
+	valsize = t->__val_type->__size;
+	if (mapval == nil) {
+		__builtin_memset(val, 0, valsize);
+		present = 0;
+	} else {
+		__builtin_memcpy(val, mapval, valsize);
+		present = 1;
+	}
+}
+
+/* Optionally assign a value to a map (m[k] = v, p).  */
+
+func mapassign2(h *Hmap, key *byte, val *byte, p bool) {
+	if (!p) {
+		__go_map_delete(h, key);
+	} else {
+		byte *mapval;
+		size_t valsize;
+
+		mapval = __go_map_index(h, key, 1);
+		valsize = h->__descriptor->__map_descriptor->__val_type->__size;
+		__builtin_memcpy(mapval, val, valsize);
+	}
+}
+
+/* Delete a key from a map.  */
+
+func mapdelete(h *Hmap, key *byte) {
+	__go_map_delete(h, key);
+}
+
+/* Initialize a range over a map.  */
+
+func mapiterinit(h *Hmap, it *hiter) {
+	__go_mapiterinit(h, it);
+}
+
+/* Move to the next iteration, updating *HITER.  */
+
+func mapiternext(it *hiter) {
+	__go_mapiternext(it);
+}
+
+/* Get the key of the current iteration.  */
+
+func mapiter1(it *hiter, key *byte) {
+	__go_mapiter1(it, key);
+}
+
+/* Get the key and value of the current iteration.  */
+
+func mapiter2(it *hiter, key *byte, val *byte) {
+	__go_mapiter2(it, key, val);
+}
diff --git a/third_party/gofrontend/libgo/runtime/map.h b/third_party/gofrontend/libgo/runtime/map.h
new file mode 100644
index 0000000..0c587bb
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/map.h
@@ -0,0 +1,87 @@
+/* map.h -- the map type for Go.
+
+   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.  */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "go-type.h"
+
+/* A map descriptor is what we need to manipulate the map.  This is
+   constant for a given map type.  */
+
+struct __go_map_descriptor
+{
+  /* A pointer to the type descriptor for the type of the map itself.  */
+  const struct __go_map_type *__map_descriptor;
+
+  /* A map entry is a struct with three fields:
+       map_entry_type *next_entry;
+       key_type key;
+       value_type value;
+     This is the size of that struct.  */
+  uintptr_t __entry_size;
+
+  /* The offset of the key field in a map entry struct.  */
+  uintptr_t __key_offset;
+
+  /* The offset of the value field in a map entry struct (the value
+     field immediately follows the key field, but there may be some
+     bytes inserted for alignment).  */
+  uintptr_t __val_offset;
+};
+
+struct __go_map
+{
+  /* The constant descriptor for this map.  */
+  const struct __go_map_descriptor *__descriptor;
+
+  /* The number of elements in the hash table.  */
+  uintptr_t __element_count;
+
+  /* The number of entries in the __buckets array.  */
+  uintptr_t __bucket_count;
+
+  /* Each bucket is a pointer to a linked list of map entries.  */
+  void **__buckets;
+};
+
+/* For a map iteration the compiled code will use a pointer to an
+   iteration structure.  The iteration structure will be allocated on
+   the stack.  The Go code must allocate at least enough space.  */
+
+struct __go_hash_iter
+{
+  /* A pointer to the current entry.  This will be set to NULL when
+     the range has completed.  The Go will test this field, so it must
+     be the first one in the structure.  */
+  const void *entry;
+  /* The map we are iterating over.  */
+  const struct __go_map *map;
+  /* A pointer to the next entry in the current bucket.  This permits
+     deleting the current entry.  This will be NULL when we have seen
+     all the entries in the current bucket.  */
+  const void *next_entry;
+  /* The bucket index of the current and next entry.  */
+  uintptr_t bucket;
+};
+
+extern struct __go_map *__go_new_map (const struct __go_map_descriptor *,
+				      uintptr_t);
+
+extern uintptr_t __go_map_next_prime (uintptr_t);
+
+extern void *__go_map_index (struct __go_map *, const void *, _Bool);
+
+extern void __go_map_delete (struct __go_map *, const void *);
+
+extern void __go_mapiterinit (const struct __go_map *, struct __go_hash_iter *);
+
+extern void __go_mapiternext (struct __go_hash_iter *);
+
+extern void __go_mapiter1 (struct __go_hash_iter *it, unsigned char *key);
+
+extern void __go_mapiter2 (struct __go_hash_iter *it, unsigned char *key,
+			   unsigned char *val);
diff --git a/third_party/gofrontend/libgo/runtime/mcache.c b/third_party/gofrontend/libgo/runtime/mcache.c
new file mode 100644
index 0000000..178831d
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/mcache.c
@@ -0,0 +1,131 @@
+// 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.
+
+// Per-P malloc cache for small objects.
+//
+// See malloc.h for an overview.
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+extern volatile intgo runtime_MemProfileRate
+  __asm__ (GOSYM_PREFIX "runtime.MemProfileRate");
+
+// dummy MSpan that contains no free objects.
+static MSpan emptymspan;
+
+MCache*
+runtime_allocmcache(void)
+{
+	intgo rate;
+	MCache *c;
+	int32 i;
+
+	runtime_lock(&runtime_mheap.lock);
+	c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc);
+	runtime_unlock(&runtime_mheap.lock);
+	runtime_memclr((byte*)c, sizeof(*c));
+	for(i = 0; i < NumSizeClasses; i++)
+		c->alloc[i] = &emptymspan;
+
+	// Set first allocation sample size.
+	rate = runtime_MemProfileRate;
+	if(rate > 0x3fffffff)	// make 2*rate not overflow
+		rate = 0x3fffffff;
+	if(rate != 0)
+		c->next_sample = runtime_fastrand1() % (2*rate);
+
+	return c;
+}
+
+void
+runtime_freemcache(MCache *c)
+{
+	runtime_MCache_ReleaseAll(c);
+	runtime_lock(&runtime_mheap.lock);
+	runtime_purgecachedstats(c);
+	runtime_FixAlloc_Free(&runtime_mheap.cachealloc, c);
+	runtime_unlock(&runtime_mheap.lock);
+}
+
+// Gets a span that has a free object in it and assigns it
+// to be the cached span for the given sizeclass.  Returns this span.
+MSpan*
+runtime_MCache_Refill(MCache *c, int32 sizeclass)
+{
+	MCacheList *l;
+	MSpan *s;
+
+	runtime_m()->locks++;
+	// Return the current cached span to the central lists.
+	s = c->alloc[sizeclass];
+	if(s->freelist != nil)
+		runtime_throw("refill on a nonempty span");
+	if(s != &emptymspan)
+		runtime_MCentral_UncacheSpan(&runtime_mheap.central[sizeclass].mcentral, s);
+
+	// Push any explicitly freed objects to the central lists.
+	// Not required, but it seems like a good time to do it.
+	l = &c->free[sizeclass];
+	if(l->nlist > 0) {
+		runtime_MCentral_FreeList(&runtime_mheap.central[sizeclass].mcentral, l->list);
+		l->list = nil;
+		l->nlist = 0;
+	}
+
+	// Get a new cached span from the central lists.
+	s = runtime_MCentral_CacheSpan(&runtime_mheap.central[sizeclass].mcentral);
+	if(s == nil)
+		runtime_throw("out of memory");
+	if(s->freelist == nil) {
+		runtime_printf("%d %d\n", s->ref, (int32)((s->npages << PageShift) / s->elemsize));
+		runtime_throw("empty span");
+	}
+	c->alloc[sizeclass] = s;
+	runtime_m()->locks--;
+	return s;
+}
+
+void
+runtime_MCache_Free(MCache *c, MLink *p, int32 sizeclass, uintptr size)
+{
+	MCacheList *l;
+
+	// Put on free list.
+	l = &c->free[sizeclass];
+	p->next = l->list;
+	l->list = p;
+	l->nlist++;
+
+	// We transfer a span at a time from MCentral to MCache,
+	// so we'll do the same in the other direction.
+	if(l->nlist >= (runtime_class_to_allocnpages[sizeclass]<<PageShift)/size) {
+		runtime_MCentral_FreeList(&runtime_mheap.central[sizeclass].mcentral, l->list);
+		l->list = nil;
+		l->nlist = 0;
+	}
+}
+
+void
+runtime_MCache_ReleaseAll(MCache *c)
+{
+	int32 i;
+	MSpan *s;
+	MCacheList *l;
+
+	for(i=0; i<NumSizeClasses; i++) {
+		s = c->alloc[i];
+		if(s != &emptymspan) {
+			runtime_MCentral_UncacheSpan(&runtime_mheap.central[i].mcentral, s);
+			c->alloc[i] = &emptymspan;
+		}
+		l = &c->free[i];
+		if(l->nlist > 0) {
+			runtime_MCentral_FreeList(&runtime_mheap.central[i].mcentral, l->list);
+			l->list = nil;
+			l->nlist = 0;
+		}
+	}
+}
diff --git a/third_party/gofrontend/libgo/runtime/mcentral.c b/third_party/gofrontend/libgo/runtime/mcentral.c
new file mode 100644
index 0000000..0106fe5
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/mcentral.c
@@ -0,0 +1,307 @@
+// 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.
+
+// Central free lists.
+//
+// See malloc.h for an overview.
+//
+// The MCentral doesn't actually contain the list of free objects; the MSpan does.
+// Each MCentral is two lists of MSpans: those with free objects (c->nonempty)
+// and those that are completely allocated (c->empty).
+//
+// TODO(rsc): tcmalloc uses a "transfer cache" to split the list
+// into sections of class_to_transfercount[sizeclass] objects
+// so that it is faster to move those lists between MCaches and MCentrals.
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+static bool MCentral_Grow(MCentral *c);
+static void MCentral_Free(MCentral *c, MLink *v);
+static void MCentral_ReturnToHeap(MCentral *c, MSpan *s);
+
+// Initialize a single central free list.
+void
+runtime_MCentral_Init(MCentral *c, int32 sizeclass)
+{
+	c->sizeclass = sizeclass;
+	runtime_MSpanList_Init(&c->nonempty);
+	runtime_MSpanList_Init(&c->empty);
+}
+
+// Allocate a span to use in an MCache.
+MSpan*
+runtime_MCentral_CacheSpan(MCentral *c)
+{
+	MSpan *s;
+	int32 cap, n;
+	uint32 sg;
+
+	runtime_lock(&c->lock);
+	sg = runtime_mheap.sweepgen;
+retry:
+	for(s = c->nonempty.next; s != &c->nonempty; s = s->next) {
+		if(s->sweepgen == sg-2 && runtime_cas(&s->sweepgen, sg-2, sg-1)) {
+			runtime_unlock(&c->lock);
+			runtime_MSpan_Sweep(s);
+			runtime_lock(&c->lock);
+			// the span could have been moved to heap, retry
+			goto retry;
+		}
+		if(s->sweepgen == sg-1) {
+			// the span is being swept by background sweeper, skip
+			continue;
+		}
+		// we have a nonempty span that does not require sweeping, allocate from it
+		goto havespan;
+	}
+
+	for(s = c->empty.next; s != &c->empty; s = s->next) {
+		if(s->sweepgen == sg-2 && runtime_cas(&s->sweepgen, sg-2, sg-1)) {
+			// we have an empty span that requires sweeping,
+			// sweep it and see if we can free some space in it
+			runtime_MSpanList_Remove(s);
+			// swept spans are at the end of the list
+			runtime_MSpanList_InsertBack(&c->empty, s);
+			runtime_unlock(&c->lock);
+			runtime_MSpan_Sweep(s);
+			runtime_lock(&c->lock);
+			// the span could be moved to nonempty or heap, retry
+			goto retry;
+		}
+		if(s->sweepgen == sg-1) {
+			// the span is being swept by background sweeper, skip
+			continue;
+		}
+		// already swept empty span,
+		// all subsequent ones must also be either swept or in process of sweeping
+		break;
+	}
+
+	// Replenish central list if empty.
+	if(!MCentral_Grow(c)) {
+		runtime_unlock(&c->lock);
+		return nil;
+	}
+	goto retry;
+
+havespan:
+	cap = (s->npages << PageShift) / s->elemsize;
+	n = cap - s->ref;
+	if(n == 0)
+		runtime_throw("empty span");
+	if(s->freelist == nil)
+		runtime_throw("freelist empty");
+	c->nfree -= n;
+	runtime_MSpanList_Remove(s);
+	runtime_MSpanList_InsertBack(&c->empty, s);
+	s->incache = true;
+	runtime_unlock(&c->lock);
+	return s;
+}
+
+// Return span from an MCache.
+void
+runtime_MCentral_UncacheSpan(MCentral *c, MSpan *s)
+{
+	MLink *v;
+	int32 cap, n;
+
+	runtime_lock(&c->lock);
+
+	s->incache = false;
+
+	// Move any explicitly freed items from the freebuf to the freelist.
+	while((v = s->freebuf) != nil) {
+		s->freebuf = v->next;
+		runtime_markfreed(v);
+		v->next = s->freelist;
+		s->freelist = v;
+		s->ref--;
+	}
+
+	if(s->ref == 0) {
+		// Free back to heap.  Unlikely, but possible.
+		MCentral_ReturnToHeap(c, s); // unlocks c
+		return;
+	}
+	
+	cap = (s->npages << PageShift) / s->elemsize;
+	n = cap - s->ref;
+	if(n > 0) {
+		c->nfree += n;
+		runtime_MSpanList_Remove(s);
+		runtime_MSpanList_Insert(&c->nonempty, s);
+	}
+	runtime_unlock(&c->lock);
+}
+
+// Free the list of objects back into the central free list c.
+// Called from runtime_free.
+void
+runtime_MCentral_FreeList(MCentral *c, MLink *start)
+{
+	MLink *next;
+
+	runtime_lock(&c->lock);
+	for(; start != nil; start = next) {
+		next = start->next;
+		MCentral_Free(c, start);
+	}
+	runtime_unlock(&c->lock);
+}
+
+// Helper: free one object back into the central free list.
+// Caller must hold lock on c on entry.  Holds lock on exit.
+static void
+MCentral_Free(MCentral *c, MLink *v)
+{
+	MSpan *s;
+
+	// Find span for v.
+	s = runtime_MHeap_Lookup(&runtime_mheap, v);
+	if(s == nil || s->ref == 0)
+		runtime_throw("invalid free");
+	if(s->sweepgen != runtime_mheap.sweepgen)
+		runtime_throw("free into unswept span");
+	
+	// If the span is currently being used unsynchronized by an MCache,
+	// we can't modify the freelist.  Add to the freebuf instead.  The
+	// items will get moved to the freelist when the span is returned
+	// by the MCache.
+	if(s->incache) {
+		v->next = s->freebuf;
+		s->freebuf = v;
+		return;
+	}
+
+	// Move span to nonempty if necessary.
+	if(s->freelist == nil) {
+		runtime_MSpanList_Remove(s);
+		runtime_MSpanList_Insert(&c->nonempty, s);
+	}
+
+	// Add the object to span's free list.
+	runtime_markfreed(v);
+	v->next = s->freelist;
+	s->freelist = v;
+	s->ref--;
+	c->nfree++;
+
+	// If s is completely freed, return it to the heap.
+	if(s->ref == 0) {
+		MCentral_ReturnToHeap(c, s); // unlocks c
+		runtime_lock(&c->lock);
+	}
+}
+
+// Free n objects from a span s back into the central free list c.
+// Called during sweep.
+// Returns true if the span was returned to heap.  Sets sweepgen to
+// the latest generation.
+bool
+runtime_MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end)
+{
+	if(s->incache)
+		runtime_throw("freespan into cached span");
+	runtime_lock(&c->lock);
+
+	// Move to nonempty if necessary.
+	if(s->freelist == nil) {
+		runtime_MSpanList_Remove(s);
+		runtime_MSpanList_Insert(&c->nonempty, s);
+	}
+
+	// Add the objects back to s's free list.
+	end->next = s->freelist;
+	s->freelist = start;
+	s->ref -= n;
+	c->nfree += n;
+	
+	// delay updating sweepgen until here.  This is the signal that
+	// the span may be used in an MCache, so it must come after the
+	// linked list operations above (actually, just after the
+	// lock of c above.)
+	runtime_atomicstore(&s->sweepgen, runtime_mheap.sweepgen);
+
+	if(s->ref != 0) {
+		runtime_unlock(&c->lock);
+		return false;
+	}
+
+	// s is completely freed, return it to the heap.
+	MCentral_ReturnToHeap(c, s); // unlocks c
+	return true;
+}
+
+void
+runtime_MGetSizeClassInfo(int32 sizeclass, uintptr *sizep, int32 *npagesp, int32 *nobj)
+{
+	int32 size;
+	int32 npages;
+
+	npages = runtime_class_to_allocnpages[sizeclass];
+	size = runtime_class_to_size[sizeclass];
+	*npagesp = npages;
+	*sizep = size;
+	*nobj = (npages << PageShift) / size;
+}
+
+// Fetch a new span from the heap and
+// carve into objects for the free list.
+static bool
+MCentral_Grow(MCentral *c)
+{
+	int32 i, n, npages;
+	uintptr size;
+	MLink **tailp, *v;
+	byte *p;
+	MSpan *s;
+
+	runtime_unlock(&c->lock);
+	runtime_MGetSizeClassInfo(c->sizeclass, &size, &npages, &n);
+	s = runtime_MHeap_Alloc(&runtime_mheap, npages, c->sizeclass, 0, 1);
+	if(s == nil) {
+		// TODO(rsc): Log out of memory
+		runtime_lock(&c->lock);
+		return false;
+	}
+
+	// Carve span into sequence of blocks.
+	tailp = &s->freelist;
+	p = (byte*)(s->start << PageShift);
+	s->limit = p + size*n;
+	for(i=0; i<n; i++) {
+		v = (MLink*)p;
+		*tailp = v;
+		tailp = &v->next;
+		p += size;
+	}
+	*tailp = nil;
+	runtime_markspan((byte*)(s->start<<PageShift), size, n, size*n < (s->npages<<PageShift));
+
+	runtime_lock(&c->lock);
+	c->nfree += n;
+	runtime_MSpanList_Insert(&c->nonempty, s);
+	return true;
+}
+
+// Return s to the heap.  s must be unused (s->ref == 0).  Unlocks c.
+static void
+MCentral_ReturnToHeap(MCentral *c, MSpan *s)
+{
+	int32 size;
+
+	size = runtime_class_to_size[c->sizeclass];
+	runtime_MSpanList_Remove(s);
+	s->needzero = 1;
+	s->freelist = nil;
+	if(s->ref != 0)
+		runtime_throw("ref wrong");
+	c->nfree -= (s->npages << PageShift) / size;
+	runtime_unlock(&c->lock);
+	runtime_unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift);
+	runtime_MHeap_Free(&runtime_mheap, s, 0);
+}
diff --git a/third_party/gofrontend/libgo/runtime/mem.c b/third_party/gofrontend/libgo/runtime/mem.c
new file mode 100644
index 0000000..6312480
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/mem.c
@@ -0,0 +1,230 @@
+/* Defining _XOPEN_SOURCE hides the declaration of madvise() on Solaris <
+   11 and the MADV_DONTNEED definition on IRIX 6.5.  */
+#undef _XOPEN_SOURCE
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+#ifndef MAP_ANON
+#ifdef MAP_ANONYMOUS
+#define MAP_ANON MAP_ANONYMOUS
+#else
+#define USE_DEV_ZERO
+#define MAP_ANON 0
+#endif
+#endif
+
+#ifndef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+
+#ifdef USE_DEV_ZERO
+static int dev_zero = -1;
+#endif
+
+static int32
+addrspace_free(void *v __attribute__ ((unused)), uintptr n __attribute__ ((unused)))
+{
+#ifdef HAVE_MINCORE
+	size_t page_size = getpagesize();
+	int32 errval;
+	uintptr chunk;
+	uintptr off;
+	
+	// NOTE: vec must be just 1 byte long here.
+	// Mincore returns ENOMEM if any of the pages are unmapped,
+	// but we want to know that all of the pages are unmapped.
+	// To make these the same, we can only ask about one page
+	// at a time. See golang.org/issue/7476.
+	static byte vec[1];
+
+	errno = 0;
+	for(off = 0; off < n; off += chunk) {
+		chunk = page_size * sizeof vec;
+		if(chunk > (n - off))
+			chunk = n - off;
+		errval = mincore((char*)v + off, chunk, (void*)vec);
+		// ENOMEM means unmapped, which is what we want.
+		// Anything else we assume means the pages are mapped.
+		if(errval == 0 || errno != ENOMEM)
+			return 0;
+	}
+#endif
+	return 1;
+}
+
+static void *
+mmap_fixed(byte *v, uintptr n, int32 prot, int32 flags, int32 fd, uint32 offset)
+{
+	void *p;
+
+	p = runtime_mmap((void *)v, n, prot, flags, fd, offset);
+	if(p != v && addrspace_free(v, n)) {
+		// On some systems, mmap ignores v without
+		// MAP_FIXED, so retry if the address space is free.
+		if(p != MAP_FAILED)
+			runtime_munmap(p, n);
+		p = runtime_mmap((void *)v, n, prot, flags|MAP_FIXED, fd, offset);
+	}
+	return p;
+}
+
+void*
+runtime_SysAlloc(uintptr n, uint64 *stat)
+{
+	void *p;
+	int fd = -1;
+
+#ifdef USE_DEV_ZERO
+	if (dev_zero == -1) {
+		dev_zero = open("/dev/zero", O_RDONLY);
+		if (dev_zero < 0) {
+			runtime_printf("open /dev/zero: errno=%d\n", errno);
+			exit(2);
+		}
+	}
+	fd = dev_zero;
+#endif
+
+	p = runtime_mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, fd, 0);
+	if (p == MAP_FAILED) {
+		if(errno == EACCES) {
+			runtime_printf("runtime: mmap: access denied\n");
+			runtime_printf("if you're running SELinux, enable execmem for this process.\n");
+			exit(2);
+		}
+		if(errno == EAGAIN) {
+			runtime_printf("runtime: mmap: too much locked memory (check 'ulimit -l').\n");
+			runtime_exit(2);
+		}
+		return nil;
+	}
+	runtime_xadd64(stat, n);
+	return p;
+}
+
+void
+runtime_SysUnused(void *v __attribute__ ((unused)), uintptr n __attribute__ ((unused)))
+{
+#ifdef MADV_DONTNEED
+	runtime_madvise(v, n, MADV_DONTNEED);
+#endif
+}
+
+void
+runtime_SysUsed(void *v, uintptr n)
+{
+	USED(v);
+	USED(n);
+}
+
+void
+runtime_SysFree(void *v, uintptr n, uint64 *stat)
+{
+	runtime_xadd64(stat, -(uint64)n);
+	runtime_munmap(v, n);
+}
+
+void
+runtime_SysFault(void *v, uintptr n)
+{
+	int fd = -1;
+
+#ifdef USE_DEV_ZERO
+	if (dev_zero == -1) {
+		dev_zero = open("/dev/zero", O_RDONLY);
+		if (dev_zero < 0) {
+			runtime_printf("open /dev/zero: errno=%d\n", errno);
+			exit(2);
+		}
+	}
+	fd = dev_zero;
+#endif
+
+	runtime_mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, fd, 0);
+}
+
+void*
+runtime_SysReserve(void *v, uintptr n, bool *reserved)
+{
+	int fd = -1;
+	void *p;
+
+#ifdef USE_DEV_ZERO
+	if (dev_zero == -1) {
+		dev_zero = open("/dev/zero", O_RDONLY);
+		if (dev_zero < 0) {
+			runtime_printf("open /dev/zero: errno=%d\n", errno);
+			exit(2);
+		}
+	}
+	fd = dev_zero;
+#endif
+
+	// On 64-bit, people with ulimit -v set complain if we reserve too
+	// much address space.  Instead, assume that the reservation is okay
+	// if we can reserve at least 64K and check the assumption in SysMap.
+	// Only user-mode Linux (UML) rejects these requests.
+	if(sizeof(void*) == 8 && (n >> 16) > 1LLU<<16) {
+		p = mmap_fixed(v, 64<<10, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0);
+		if (p != v) {
+			runtime_munmap(p, 64<<10);
+			return nil;
+		}
+		runtime_munmap(p, 64<<10);
+		*reserved = false;
+		return v;
+	}
+	
+	// Use the MAP_NORESERVE mmap() flag here because typically most of
+	// this reservation will never be used. It does not make sense
+	// reserve a huge amount of unneeded swap space. This is important on
+	// systems which do not overcommit memory by default.
+	p = runtime_mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, fd, 0);
+	if(p == MAP_FAILED)
+		return nil;
+	*reserved = true;
+	return p;
+}
+
+void
+runtime_SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
+{
+	void *p;
+	int fd = -1;
+	
+	runtime_xadd64(stat, n);
+
+#ifdef USE_DEV_ZERO
+	if (dev_zero == -1) {
+		dev_zero = open("/dev/zero", O_RDONLY);
+		if (dev_zero < 0) {
+			runtime_printf("open /dev/zero: errno=%d\n", errno);
+			exit(2);
+		}
+	}
+	fd = dev_zero;
+#endif
+
+	// On 64-bit, we don't actually have v reserved, so tread carefully.
+	if(!reserved) {
+		p = mmap_fixed(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, fd, 0);
+		if(p == MAP_FAILED && errno == ENOMEM)
+			runtime_throw("runtime: out of memory");
+		if(p != v) {
+			runtime_printf("runtime: address space conflict: map(%p) = %p\n", v, p);
+			runtime_throw("runtime: address space conflict");
+		}
+		return;
+	}
+
+	p = runtime_mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, fd, 0);
+	if(p == MAP_FAILED && errno == ENOMEM)
+		runtime_throw("runtime: out of memory");
+	if(p != v)
+		runtime_throw("runtime: cannot map pages in arena address space");
+}
diff --git a/third_party/gofrontend/libgo/runtime/mem_posix_memalign.c b/third_party/gofrontend/libgo/runtime/mem_posix_memalign.c
new file mode 100644
index 0000000..8acdf07
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/mem_posix_memalign.c
@@ -0,0 +1,48 @@
+#include <errno.h>
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+void*
+runtime_SysAlloc(uintptr n)
+{
+	void *p;
+
+	mstats.sys += n;
+	errno = posix_memalign(&p, PageSize, n);
+	if (errno > 0) {
+		perror("posix_memalign");
+		exit(2);
+	}
+	return p;
+}
+
+void
+runtime_SysUnused(void *v, uintptr n)
+{
+	USED(v);
+	USED(n);
+	// TODO(rsc): call madvise MADV_DONTNEED
+}
+
+void
+runtime_SysFree(void *v, uintptr n)
+{
+	mstats.sys -= n;
+	free(v);
+}
+
+void*
+runtime_SysReserve(void *v, uintptr n)
+{
+	USED(v);
+	return runtime_SysAlloc(n);
+}
+
+void
+runtime_SysMap(void *v, uintptr n)
+{
+	USED(v);
+	USED(n);
+}
diff --git a/third_party/gofrontend/libgo/runtime/mfixalloc.c b/third_party/gofrontend/libgo/runtime/mfixalloc.c
new file mode 100644
index 0000000..9d0b3bb
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/mfixalloc.c
@@ -0,0 +1,64 @@
+// 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.
+
+// Fixed-size object allocator.  Returned memory is not zeroed.
+//
+// See malloc.h for overview.
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+// Initialize f to allocate objects of the given size,
+// using the allocator to obtain chunks of memory.
+void
+runtime_FixAlloc_Init(FixAlloc *f, uintptr size, void (*first)(void*, byte*), void *arg, uint64 *stat)
+{
+	f->size = size;
+	f->first = first;
+	f->arg = arg;
+	f->list = nil;
+	f->chunk = nil;
+	f->nchunk = 0;
+	f->inuse = 0;
+	f->stat = stat;
+}
+
+void*
+runtime_FixAlloc_Alloc(FixAlloc *f)
+{
+	void *v;
+	
+	if(f->size == 0) {
+		runtime_printf("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n");
+		runtime_throw("runtime: internal error");
+	}
+
+	if(f->list) {
+		v = f->list;
+		f->list = *(void**)f->list;
+		f->inuse += f->size;
+		return v;
+	}
+	if(f->nchunk < f->size) {
+		f->chunk = runtime_persistentalloc(FixAllocChunk, 0, f->stat);
+		f->nchunk = FixAllocChunk;
+	}
+	v = f->chunk;
+	if(f->first)
+		f->first(f->arg, v);
+	f->chunk += f->size;
+	f->nchunk -= f->size;
+	f->inuse += f->size;
+	return v;
+}
+
+void
+runtime_FixAlloc_Free(FixAlloc *f, void *p)
+{
+	f->inuse -= f->size;
+	*(void**)p = f->list;
+	f->list = p;
+}
+
diff --git a/third_party/gofrontend/libgo/runtime/mgc0.c b/third_party/gofrontend/libgo/runtime/mgc0.c
new file mode 100644
index 0000000..3732b60
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/mgc0.c
@@ -0,0 +1,2751 @@
+// 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.
+
+// Garbage collector (GC).
+//
+// GC is:
+// - mark&sweep
+// - mostly precise (with the exception of some C-allocated objects, assembly frames/arguments, etc)
+// - parallel (up to MaxGcproc threads)
+// - partially concurrent (mark is stop-the-world, while sweep is concurrent)
+// - non-moving/non-compacting
+// - full (non-partial)
+//
+// GC rate.
+// Next GC is after we've allocated an extra amount of memory proportional to
+// the amount already in use. The proportion is controlled by GOGC environment variable
+// (100 by default). If GOGC=100 and we're using 4M, we'll GC again when we get to 8M
+// (this mark is tracked in next_gc variable). This keeps the GC cost in linear
+// proportion to the allocation cost. Adjusting GOGC just changes the linear constant
+// (and also the amount of extra memory used).
+//
+// Concurrent sweep.
+// The sweep phase proceeds concurrently with normal program execution.
+// The heap is swept span-by-span both lazily (when a goroutine needs another span)
+// and concurrently in a background goroutine (this helps programs that are not CPU bound).
+// However, at the end of the stop-the-world GC phase we don't know the size of the live heap,
+// and so next_gc calculation is tricky and happens as follows.
+// At the end of the stop-the-world phase next_gc is conservatively set based on total
+// heap size; all spans are marked as "needs sweeping".
+// Whenever a span is swept, next_gc is decremented by GOGC*newly_freed_memory.
+// The background sweeper goroutine simply sweeps spans one-by-one bringing next_gc
+// closer to the target value. However, this is not enough to avoid over-allocating memory.
+// Consider that a goroutine wants to allocate a new span for a large object and
+// there are no free swept spans, but there are small-object unswept spans.
+// If the goroutine naively allocates a new span, it can surpass the yet-unknown
+// target next_gc value. In order to prevent such cases (1) when a goroutine needs
+// to allocate a new small-object span, it sweeps small-object spans for the same
+// object size until it frees at least one object; (2) when a goroutine needs to
+// allocate large-object span from heap, it sweeps spans until it frees at least
+// that many pages into heap. Together these two measures ensure that we don't surpass
+// target next_gc value by a large margin. There is an exception: if a goroutine sweeps
+// and frees two nonadjacent one-page spans to the heap, it will allocate a new two-page span,
+// but there can still be other one-page unswept spans which could be combined into a two-page span.
+// It's critical to ensure that no operations proceed on unswept spans (that would corrupt
+// mark bits in GC bitmap). During GC all mcaches are flushed into the central cache,
+// so they are empty. When a goroutine grabs a new span into mcache, it sweeps it.
+// When a goroutine explicitly frees an object or sets a finalizer, it ensures that
+// the span is swept (either by sweeping it, or by waiting for the concurrent sweep to finish).
+// The finalizer goroutine is kicked off only when all spans are swept.
+// When the next GC starts, it sweeps all not-yet-swept spans (if any).
+
+#include <unistd.h>
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+#include "mgc0.h"
+#include "chan.h"
+#include "race.h"
+#include "go-type.h"
+
+// Map gccgo field names to gc field names.
+// Slice aka __go_open_array.
+#define array __values
+#define cap __capacity
+// Iface aka __go_interface
+#define tab __methods
+// Hmap aka __go_map
+typedef struct __go_map Hmap;
+// Type aka __go_type_descriptor
+#define string __reflection
+#define KindPtr GO_PTR
+#define KindNoPointers GO_NO_POINTERS
+// PtrType aka __go_ptr_type
+#define elem __element_type
+
+#ifdef USING_SPLIT_STACK
+
+extern void * __splitstack_find (void *, void *, size_t *, void **, void **,
+				 void **);
+
+extern void * __splitstack_find_context (void *context[10], size_t *, void **,
+					 void **, void **);
+
+#endif
+
+enum {
+	Debug = 0,
+	CollectStats = 0,
+	ConcurrentSweep = 1,
+
+	WorkbufSize	= 16*1024,
+	FinBlockSize	= 4*1024,
+
+	handoffThreshold = 4,
+	IntermediateBufferCapacity = 64,
+
+	// Bits in type information
+	PRECISE = 1,
+	LOOP = 2,
+	PC_BITS = PRECISE | LOOP,
+
+	RootData	= 0,
+	RootBss		= 1,
+	RootFinalizers	= 2,
+	RootSpanTypes	= 3,
+	RootFlushCaches = 4,
+	RootCount	= 5,
+};
+
+#define GcpercentUnknown (-2)
+
+// Initialized from $GOGC.  GOGC=off means no gc.
+static int32 gcpercent = GcpercentUnknown;
+
+static FuncVal* poolcleanup;
+
+void sync_runtime_registerPoolCleanup(FuncVal*)
+  __asm__ (GOSYM_PREFIX "sync.runtime_registerPoolCleanup");
+
+void
+sync_runtime_registerPoolCleanup(FuncVal *f)
+{
+	poolcleanup = f;
+}
+
+static void
+clearpools(void)
+{
+	P *p, **pp;
+	MCache *c;
+
+	// clear sync.Pool's
+	if(poolcleanup != nil) {
+		__go_set_closure(poolcleanup);
+		poolcleanup->fn();
+	}
+
+	for(pp=runtime_allp; (p=*pp) != nil; pp++) {
+		// clear tinyalloc pool
+		c = p->mcache;
+		if(c != nil) {
+			c->tiny = nil;
+			c->tinysize = 0;
+		}
+		// clear defer pools
+		p->deferpool = nil;
+	}
+}
+
+// Holding worldsema grants an M the right to try to stop the world.
+// The procedure is:
+//
+//	runtime_semacquire(&runtime_worldsema);
+//	m->gcing = 1;
+//	runtime_stoptheworld();
+//
+//	... do stuff ...
+//
+//	m->gcing = 0;
+//	runtime_semrelease(&runtime_worldsema);
+//	runtime_starttheworld();
+//
+uint32 runtime_worldsema = 1;
+
+typedef struct Workbuf Workbuf;
+struct Workbuf
+{
+#define SIZE (WorkbufSize-sizeof(LFNode)-sizeof(uintptr))
+	LFNode  node; // must be first
+	uintptr nobj;
+	Obj     obj[SIZE/sizeof(Obj) - 1];
+	uint8   _padding[SIZE%sizeof(Obj) + sizeof(Obj)];
+#undef SIZE
+};
+
+typedef struct Finalizer Finalizer;
+struct Finalizer
+{
+	FuncVal *fn;
+	void *arg;
+	const struct __go_func_type *ft;
+	const PtrType *ot;
+};
+
+typedef struct FinBlock FinBlock;
+struct FinBlock
+{
+	FinBlock *alllink;
+	FinBlock *next;
+	int32 cnt;
+	int32 cap;
+	Finalizer fin[1];
+};
+
+static Lock	finlock;	// protects the following variables
+static FinBlock	*finq;		// list of finalizers that are to be executed
+static FinBlock	*finc;		// cache of free blocks
+static FinBlock	*allfin;	// list of all blocks
+bool	runtime_fingwait;
+bool	runtime_fingwake;
+
+static Lock	gclock;
+static G*	fing;
+
+static void	runfinq(void*);
+static void	bgsweep(void*);
+static Workbuf* getempty(Workbuf*);
+static Workbuf* getfull(Workbuf*);
+static void	putempty(Workbuf*);
+static Workbuf* handoff(Workbuf*);
+static void	gchelperstart(void);
+static void	flushallmcaches(void);
+static void	addstackroots(G *gp, Workbuf **wbufp);
+
+static struct {
+	uint64	full;  // lock-free list of full blocks
+	uint64	empty; // lock-free list of empty blocks
+	byte	pad0[CacheLineSize]; // prevents false-sharing between full/empty and nproc/nwait
+	uint32	nproc;
+	int64	tstart;
+	volatile uint32	nwait;
+	volatile uint32	ndone;
+	Note	alldone;
+	ParFor	*markfor;
+
+	Lock	lock;
+	byte	*chunk;
+	uintptr	nchunk;
+} work __attribute__((aligned(8)));
+
+enum {
+	GC_DEFAULT_PTR = GC_NUM_INSTR,
+	GC_CHAN,
+
+	GC_NUM_INSTR2
+};
+
+static struct {
+	struct {
+		uint64 sum;
+		uint64 cnt;
+	} ptr;
+	uint64 nbytes;
+	struct {
+		uint64 sum;
+		uint64 cnt;
+		uint64 notype;
+		uint64 typelookup;
+	} obj;
+	uint64 rescan;
+	uint64 rescanbytes;
+	uint64 instr[GC_NUM_INSTR2];
+	uint64 putempty;
+	uint64 getfull;
+	struct {
+		uint64 foundbit;
+		uint64 foundword;
+		uint64 foundspan;
+	} flushptrbuf;
+	struct {
+		uint64 foundbit;
+		uint64 foundword;
+		uint64 foundspan;
+	} markonly;
+	uint32 nbgsweep;
+	uint32 npausesweep;
+} gcstats;
+
+// markonly marks an object. It returns true if the object
+// has been marked by this function, false otherwise.
+// This function doesn't append the object to any buffer.
+static bool
+markonly(const void *obj)
+{
+	byte *p;
+	uintptr *bitp, bits, shift, x, xbits, off, j;
+	MSpan *s;
+	PageID k;
+
+	// Words outside the arena cannot be pointers.
+	if((const byte*)obj < runtime_mheap.arena_start || (const byte*)obj >= runtime_mheap.arena_used)
+		return false;
+
+	// obj may be a pointer to a live object.
+	// Try to find the beginning of the object.
+
+	// Round down to word boundary.
+	obj = (const void*)((uintptr)obj & ~((uintptr)PtrSize-1));
+
+	// Find bits for this word.
+	off = (const uintptr*)obj - (uintptr*)runtime_mheap.arena_start;
+	bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+	shift = off % wordsPerBitmapWord;
+	xbits = *bitp;
+	bits = xbits >> shift;
+
+	// Pointing at the beginning of a block?
+	if((bits & (bitAllocated|bitBlockBoundary)) != 0) {
+		if(CollectStats)
+			runtime_xadd64(&gcstats.markonly.foundbit, 1);
+		goto found;
+	}
+
+	// Pointing just past the beginning?
+	// Scan backward a little to find a block boundary.
+	for(j=shift; j-->0; ) {
+		if(((xbits>>j) & (bitAllocated|bitBlockBoundary)) != 0) {
+			shift = j;
+			bits = xbits>>shift;
+			if(CollectStats)
+				runtime_xadd64(&gcstats.markonly.foundword, 1);
+			goto found;
+		}
+	}
+
+	// Otherwise consult span table to find beginning.
+	// (Manually inlined copy of MHeap_LookupMaybe.)
+	k = (uintptr)obj>>PageShift;
+	x = k;
+	x -= (uintptr)runtime_mheap.arena_start>>PageShift;
+	s = runtime_mheap.spans[x];
+	if(s == nil || k < s->start || (const byte*)obj >= s->limit || s->state != MSpanInUse)
+		return false;
+	p = (byte*)((uintptr)s->start<<PageShift);
+	if(s->sizeclass == 0) {
+		obj = p;
+	} else {
+		uintptr size = s->elemsize;
+		int32 i = ((const byte*)obj - p)/size;
+		obj = p+i*size;
+	}
+
+	// Now that we know the object header, reload bits.
+	off = (const uintptr*)obj - (uintptr*)runtime_mheap.arena_start;
+	bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+	shift = off % wordsPerBitmapWord;
+	xbits = *bitp;
+	bits = xbits >> shift;
+	if(CollectStats)
+		runtime_xadd64(&gcstats.markonly.foundspan, 1);
+
+found:
+	// Now we have bits, bitp, and shift correct for
+	// obj pointing at the base of the object.
+	// Only care about allocated and not marked.
+	if((bits & (bitAllocated|bitMarked)) != bitAllocated)
+		return false;
+	if(work.nproc == 1)
+		*bitp |= bitMarked<<shift;
+	else {
+		for(;;) {
+			x = *bitp;
+			if(x & (bitMarked<<shift))
+				return false;
+			if(runtime_casp((void**)bitp, (void*)x, (void*)(x|(bitMarked<<shift))))
+				break;
+		}
+	}
+
+	// The object is now marked
+	return true;
+}
+
+// PtrTarget is a structure used by intermediate buffers.
+// The intermediate buffers hold GC data before it
+// is moved/flushed to the work buffer (Workbuf).
+// The size of an intermediate buffer is very small,
+// such as 32 or 64 elements.
+typedef struct PtrTarget PtrTarget;
+struct PtrTarget
+{
+	void *p;
+	uintptr ti;
+};
+
+typedef	struct Scanbuf Scanbuf;
+struct	Scanbuf
+{
+	struct {
+		PtrTarget *begin;
+		PtrTarget *end;
+		PtrTarget *pos;
+	} ptr;
+	struct {
+		Obj *begin;
+		Obj *end;
+		Obj *pos;
+	} obj;
+	Workbuf *wbuf;
+	Obj *wp;
+	uintptr nobj;
+};
+
+typedef struct BufferList BufferList;
+struct BufferList
+{
+	PtrTarget ptrtarget[IntermediateBufferCapacity];
+	Obj obj[IntermediateBufferCapacity];
+	uint32 busy;
+	byte pad[CacheLineSize];
+};
+static BufferList bufferList[MaxGcproc];
+
+static void enqueue(Obj obj, Workbuf **_wbuf, Obj **_wp, uintptr *_nobj);
+
+// flushptrbuf moves data from the PtrTarget buffer to the work buffer.
+// The PtrTarget buffer contains blocks irrespective of whether the blocks have been marked or scanned,
+// while the work buffer contains blocks which have been marked
+// and are prepared to be scanned by the garbage collector.
+//
+// _wp, _wbuf, _nobj are input/output parameters and are specifying the work buffer.
+//
+// A simplified drawing explaining how the todo-list moves from a structure to another:
+//
+//     scanblock
+//  (find pointers)
+//    Obj ------> PtrTarget (pointer targets)
+//     ↑          |
+//     |          |
+//     `----------'
+//     flushptrbuf
+//  (find block start, mark and enqueue)
+static void
+flushptrbuf(Scanbuf *sbuf)
+{
+	byte *p, *arena_start, *obj;
+	uintptr size, *bitp, bits, shift, j, x, xbits, off, nobj, ti, n;
+	MSpan *s;
+	PageID k;
+	Obj *wp;
+	Workbuf *wbuf;
+	PtrTarget *ptrbuf;
+	PtrTarget *ptrbuf_end;
+
+	arena_start = runtime_mheap.arena_start;
+
+	wp = sbuf->wp;
+	wbuf = sbuf->wbuf;
+	nobj = sbuf->nobj;
+
+	ptrbuf = sbuf->ptr.begin;
+	ptrbuf_end = sbuf->ptr.pos;
+	n = ptrbuf_end - sbuf->ptr.begin;
+	sbuf->ptr.pos = sbuf->ptr.begin;
+
+	if(CollectStats) {
+		runtime_xadd64(&gcstats.ptr.sum, n);
+		runtime_xadd64(&gcstats.ptr.cnt, 1);
+	}
+
+	// If buffer is nearly full, get a new one.
+	if(wbuf == nil || nobj+n >= nelem(wbuf->obj)) {
+		if(wbuf != nil)
+			wbuf->nobj = nobj;
+		wbuf = getempty(wbuf);
+		wp = wbuf->obj;
+		nobj = 0;
+
+		if(n >= nelem(wbuf->obj))
+			runtime_throw("ptrbuf has to be smaller than WorkBuf");
+	}
+
+	while(ptrbuf < ptrbuf_end) {
+		obj = ptrbuf->p;
+		ti = ptrbuf->ti;
+		ptrbuf++;
+
+		// obj belongs to interval [mheap.arena_start, mheap.arena_used).
+		if(Debug > 1) {
+			if(obj < runtime_mheap.arena_start || obj >= runtime_mheap.arena_used)
+				runtime_throw("object is outside of mheap");
+		}
+
+		// obj may be a pointer to a live object.
+		// Try to find the beginning of the object.
+
+		// Round down to word boundary.
+		if(((uintptr)obj & ((uintptr)PtrSize-1)) != 0) {
+			obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
+			ti = 0;
+		}
+
+		// Find bits for this word.
+		off = (uintptr*)obj - (uintptr*)arena_start;
+		bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		xbits = *bitp;
+		bits = xbits >> shift;
+
+		// Pointing at the beginning of a block?
+		if((bits & (bitAllocated|bitBlockBoundary)) != 0) {
+			if(CollectStats)
+				runtime_xadd64(&gcstats.flushptrbuf.foundbit, 1);
+			goto found;
+		}
+
+		ti = 0;
+
+		// Pointing just past the beginning?
+		// Scan backward a little to find a block boundary.
+		for(j=shift; j-->0; ) {
+			if(((xbits>>j) & (bitAllocated|bitBlockBoundary)) != 0) {
+				obj = (byte*)obj - (shift-j)*PtrSize;
+				shift = j;
+				bits = xbits>>shift;
+				if(CollectStats)
+					runtime_xadd64(&gcstats.flushptrbuf.foundword, 1);
+				goto found;
+			}
+		}
+
+		// Otherwise consult span table to find beginning.
+		// (Manually inlined copy of MHeap_LookupMaybe.)
+		k = (uintptr)obj>>PageShift;
+		x = k;
+		x -= (uintptr)arena_start>>PageShift;
+		s = runtime_mheap.spans[x];
+		if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse)
+			continue;
+		p = (byte*)((uintptr)s->start<<PageShift);
+		if(s->sizeclass == 0) {
+			obj = p;
+		} else {
+			size = s->elemsize;
+			int32 i = ((byte*)obj - p)/size;
+			obj = p+i*size;
+		}
+
+		// Now that we know the object header, reload bits.
+		off = (uintptr*)obj - (uintptr*)arena_start;
+		bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		xbits = *bitp;
+		bits = xbits >> shift;
+		if(CollectStats)
+			runtime_xadd64(&gcstats.flushptrbuf.foundspan, 1);
+
+	found:
+		// Now we have bits, bitp, and shift correct for
+		// obj pointing at the base of the object.
+		// Only care about allocated and not marked.
+		if((bits & (bitAllocated|bitMarked)) != bitAllocated)
+			continue;
+		if(work.nproc == 1)
+			*bitp |= bitMarked<<shift;
+		else {
+			for(;;) {
+				x = *bitp;
+				if(x & (bitMarked<<shift))
+					goto continue_obj;
+				if(runtime_casp((void**)bitp, (void*)x, (void*)(x|(bitMarked<<shift))))
+					break;
+			}
+		}
+
+		// If object has no pointers, don't need to scan further.
+		if((bits & bitScan) == 0)
+			continue;
+
+		// Ask span about size class.
+		// (Manually inlined copy of MHeap_Lookup.)
+		x = (uintptr)obj >> PageShift;
+		x -= (uintptr)arena_start>>PageShift;
+		s = runtime_mheap.spans[x];
+
+		PREFETCH(obj);
+
+		*wp = (Obj){obj, s->elemsize, ti};
+		wp++;
+		nobj++;
+	continue_obj:;
+	}
+
+	// If another proc wants a pointer, give it some.
+	if(work.nwait > 0 && nobj > handoffThreshold && work.full == 0) {
+		wbuf->nobj = nobj;
+		wbuf = handoff(wbuf);
+		nobj = wbuf->nobj;
+		wp = wbuf->obj + nobj;
+	}
+
+	sbuf->wp = wp;
+	sbuf->wbuf = wbuf;
+	sbuf->nobj = nobj;
+}
+
+static void
+flushobjbuf(Scanbuf *sbuf)
+{
+	uintptr nobj, off;
+	Obj *wp, obj;
+	Workbuf *wbuf;
+	Obj *objbuf;
+	Obj *objbuf_end;
+
+	wp = sbuf->wp;
+	wbuf = sbuf->wbuf;
+	nobj = sbuf->nobj;
+
+	objbuf = sbuf->obj.begin;
+	objbuf_end = sbuf->obj.pos;
+	sbuf->obj.pos = sbuf->obj.begin;
+
+	while(objbuf < objbuf_end) {
+		obj = *objbuf++;
+
+		// Align obj.b to a word boundary.
+		off = (uintptr)obj.p & (PtrSize-1);
+		if(off != 0) {
+			obj.p += PtrSize - off;
+			obj.n -= PtrSize - off;
+			obj.ti = 0;
+		}
+
+		if(obj.p == nil || obj.n == 0)
+			continue;
+
+		// If buffer is full, get a new one.
+		if(wbuf == nil || nobj >= nelem(wbuf->obj)) {
+			if(wbuf != nil)
+				wbuf->nobj = nobj;
+			wbuf = getempty(wbuf);
+			wp = wbuf->obj;
+			nobj = 0;
+		}
+
+		*wp = obj;
+		wp++;
+		nobj++;
+	}
+
+	// If another proc wants a pointer, give it some.
+	if(work.nwait > 0 && nobj > handoffThreshold && work.full == 0) {
+		wbuf->nobj = nobj;
+		wbuf = handoff(wbuf);
+		nobj = wbuf->nobj;
+		wp = wbuf->obj + nobj;
+	}
+
+	sbuf->wp = wp;
+	sbuf->wbuf = wbuf;
+	sbuf->nobj = nobj;
+}
+
+// Program that scans the whole block and treats every block element as a potential pointer
+static uintptr defaultProg[2] = {PtrSize, GC_DEFAULT_PTR};
+
+// Hchan program
+static uintptr chanProg[2] = {0, GC_CHAN};
+
+// Local variables of a program fragment or loop
+typedef struct Frame Frame;
+struct Frame {
+	uintptr count, elemsize, b;
+	const uintptr *loop_or_ret;
+};
+
+// Sanity check for the derived type info objti.
+static void
+checkptr(void *obj, uintptr objti)
+{
+	uintptr *pc1, type, tisize, i, j, x;
+	const uintptr *pc2;
+	byte *objstart;
+	Type *t;
+	MSpan *s;
+
+	if(!Debug)
+		runtime_throw("checkptr is debug only");
+
+	if((byte*)obj < runtime_mheap.arena_start || (byte*)obj >= runtime_mheap.arena_used)
+		return;
+	type = runtime_gettype(obj);
+	t = (Type*)(type & ~(uintptr)(PtrSize-1));
+	if(t == nil)
+		return;
+	x = (uintptr)obj >> PageShift;
+	x -= (uintptr)(runtime_mheap.arena_start)>>PageShift;
+	s = runtime_mheap.spans[x];
+	objstart = (byte*)((uintptr)s->start<<PageShift);
+	if(s->sizeclass != 0) {
+		i = ((byte*)obj - objstart)/s->elemsize;
+		objstart += i*s->elemsize;
+	}
+	tisize = *(uintptr*)objti;
+	// Sanity check for object size: it should fit into the memory block.
+	if((byte*)obj + tisize > objstart + s->elemsize) {
+		runtime_printf("object of type '%S' at %p/%p does not fit in block %p/%p\n",
+			       *t->string, obj, tisize, objstart, s->elemsize);
+		runtime_throw("invalid gc type info");
+	}
+	if(obj != objstart)
+		return;
+	// If obj points to the beginning of the memory block,
+	// check type info as well.
+	if(t->string == nil ||
+		// Gob allocates unsafe pointers for indirection.
+		(runtime_strcmp((const char *)t->string->str, (const char*)"unsafe.Pointer") &&
+		// Runtime and gc think differently about closures.
+		 runtime_strstr((const char *)t->string->str, (const char*)"struct { F uintptr") != (const char *)t->string->str)) {
+		pc1 = (uintptr*)objti;
+		pc2 = (const uintptr*)t->__gc;
+		// A simple best-effort check until first GC_END.
+		for(j = 1; pc1[j] != GC_END && pc2[j] != GC_END; j++) {
+			if(pc1[j] != pc2[j]) {
+				runtime_printf("invalid gc type info for '%s', type info %p [%d]=%p, block info %p [%d]=%p\n",
+					       t->string ? (const int8*)t->string->str : (const int8*)"?", pc1, (int32)j, pc1[j], pc2, (int32)j, pc2[j]);
+				runtime_throw("invalid gc type info");
+			}
+		}
+	}
+}					
+
+// scanblock scans a block of n bytes starting at pointer b for references
+// to other objects, scanning any it finds recursively until there are no
+// unscanned objects left.  Instead of using an explicit recursion, it keeps
+// a work list in the Workbuf* structures and loops in the main function
+// body.  Keeping an explicit work list is easier on the stack allocator and
+// more efficient.
+static void
+scanblock(Workbuf *wbuf, bool keepworking)
+{
+	byte *b, *arena_start, *arena_used;
+	uintptr n, i, end_b, elemsize, size, ti, objti, count, type, nobj;
+	uintptr precise_type, nominal_size;
+	const uintptr *pc, *chan_ret;
+	uintptr chancap;
+	void *obj;
+	const Type *t, *et;
+	Slice *sliceptr;
+	String *stringptr;
+	Frame *stack_ptr, stack_top, stack[GC_STACK_CAPACITY+4];
+	BufferList *scanbuffers;
+	Scanbuf sbuf;
+	Eface *eface;
+	Iface *iface;
+	Hchan *chan;
+	const ChanType *chantype;
+	Obj *wp;
+
+	if(sizeof(Workbuf) % WorkbufSize != 0)
+		runtime_throw("scanblock: size of Workbuf is suboptimal");
+
+	// Memory arena parameters.
+	arena_start = runtime_mheap.arena_start;
+	arena_used = runtime_mheap.arena_used;
+
+	stack_ptr = stack+nelem(stack)-1;
+
+	precise_type = false;
+	nominal_size = 0;
+
+	if(wbuf) {
+		nobj = wbuf->nobj;
+		wp = &wbuf->obj[nobj];
+	} else {
+		nobj = 0;
+		wp = nil;
+	}
+
+	// Initialize sbuf
+	scanbuffers = &bufferList[runtime_m()->helpgc];
+
+	sbuf.ptr.begin = sbuf.ptr.pos = &scanbuffers->ptrtarget[0];
+	sbuf.ptr.end = sbuf.ptr.begin + nelem(scanbuffers->ptrtarget);
+
+	sbuf.obj.begin = sbuf.obj.pos = &scanbuffers->obj[0];
+	sbuf.obj.end = sbuf.obj.begin + nelem(scanbuffers->obj);
+
+	sbuf.wbuf = wbuf;
+	sbuf.wp = wp;
+	sbuf.nobj = nobj;
+
+	// (Silence the compiler)
+	chan = nil;
+	chantype = nil;
+	chan_ret = nil;
+
+	goto next_block;
+
+	for(;;) {
+		// Each iteration scans the block b of length n, queueing pointers in
+		// the work buffer.
+
+		if(CollectStats) {
+			runtime_xadd64(&gcstats.nbytes, n);
+			runtime_xadd64(&gcstats.obj.sum, sbuf.nobj);
+			runtime_xadd64(&gcstats.obj.cnt, 1);
+		}
+
+		if(ti != 0) {
+			if(Debug > 1) {
+				runtime_printf("scanblock %p %D ti %p\n", b, (int64)n, ti);
+			}
+			pc = (uintptr*)(ti & ~(uintptr)PC_BITS);
+			precise_type = (ti & PRECISE);
+			stack_top.elemsize = pc[0];
+			if(!precise_type)
+				nominal_size = pc[0];
+			if(ti & LOOP) {
+				stack_top.count = 0;	// 0 means an infinite number of iterations
+				stack_top.loop_or_ret = pc+1;
+			} else {
+				stack_top.count = 1;
+			}
+			if(Debug) {
+				// Simple sanity check for provided type info ti:
+				// The declared size of the object must be not larger than the actual size
+				// (it can be smaller due to inferior pointers).
+				// It's difficult to make a comprehensive check due to inferior pointers,
+				// reflection, gob, etc.
+				if(pc[0] > n) {
+					runtime_printf("invalid gc type info: type info size %p, block size %p\n", pc[0], n);
+					runtime_throw("invalid gc type info");
+				}
+			}
+		} else if(UseSpanType) {
+			if(CollectStats)
+				runtime_xadd64(&gcstats.obj.notype, 1);
+
+			type = runtime_gettype(b);
+			if(type != 0) {
+				if(CollectStats)
+					runtime_xadd64(&gcstats.obj.typelookup, 1);
+
+				t = (Type*)(type & ~(uintptr)(PtrSize-1));
+				switch(type & (PtrSize-1)) {
+				case TypeInfo_SingleObject:
+					pc = (const uintptr*)t->__gc;
+					precise_type = true;  // type information about 'b' is precise
+					stack_top.count = 1;
+					stack_top.elemsize = pc[0];
+					break;
+				case TypeInfo_Array:
+					pc = (const uintptr*)t->__gc;
+					if(pc[0] == 0)
+						goto next_block;
+					precise_type = true;  // type information about 'b' is precise
+					stack_top.count = 0;  // 0 means an infinite number of iterations
+					stack_top.elemsize = pc[0];
+					stack_top.loop_or_ret = pc+1;
+					break;
+				case TypeInfo_Chan:
+					chan = (Hchan*)b;
+					chantype = (const ChanType*)t;
+					chan_ret = nil;
+					pc = chanProg;
+					break;
+				default:
+					if(Debug > 1)
+						runtime_printf("scanblock %p %D type %p %S\n", b, (int64)n, type, *t->string);
+					runtime_throw("scanblock: invalid type");
+					return;
+				}
+				if(Debug > 1)
+					runtime_printf("scanblock %p %D type %p %S pc=%p\n", b, (int64)n, type, *t->string, pc);
+			} else {
+				pc = defaultProg;
+				if(Debug > 1)
+					runtime_printf("scanblock %p %D unknown type\n", b, (int64)n);
+			}
+		} else {
+			pc = defaultProg;
+			if(Debug > 1)
+				runtime_printf("scanblock %p %D no span types\n", b, (int64)n);
+		}
+
+		if(IgnorePreciseGC)
+			pc = defaultProg;
+
+		pc++;
+		stack_top.b = (uintptr)b;
+		end_b = (uintptr)b + n - PtrSize;
+
+	for(;;) {
+		if(CollectStats)
+			runtime_xadd64(&gcstats.instr[pc[0]], 1);
+
+		obj = nil;
+		objti = 0;
+		switch(pc[0]) {
+		case GC_PTR:
+			obj = *(void**)(stack_top.b + pc[1]);
+			objti = pc[2];
+			if(Debug > 2)
+				runtime_printf("gc_ptr @%p: %p ti=%p\n", stack_top.b+pc[1], obj, objti);
+			pc += 3;
+			if(Debug)
+				checkptr(obj, objti);
+			break;
+
+		case GC_SLICE:
+			sliceptr = (Slice*)(stack_top.b + pc[1]);
+			if(Debug > 2)
+				runtime_printf("gc_slice @%p: %p/%D/%D\n", sliceptr, sliceptr->array, (int64)sliceptr->__count, (int64)sliceptr->cap);
+			if(sliceptr->cap != 0) {
+				obj = sliceptr->array;
+				// Can't use slice element type for scanning,
+				// because if it points to an array embedded
+				// in the beginning of a struct,
+				// we will scan the whole struct as the slice.
+				// So just obtain type info from heap.
+			}
+			pc += 3;
+			break;
+
+		case GC_APTR:
+			obj = *(void**)(stack_top.b + pc[1]);
+			if(Debug > 2)
+				runtime_printf("gc_aptr @%p: %p\n", stack_top.b+pc[1], obj);
+			pc += 2;
+			break;
+
+		case GC_STRING:
+			stringptr = (String*)(stack_top.b + pc[1]);
+			if(Debug > 2)
+				runtime_printf("gc_string @%p: %p/%D\n", stack_top.b+pc[1], stringptr->str, (int64)stringptr->len);
+			if(stringptr->len != 0)
+				markonly(stringptr->str);
+			pc += 2;
+			continue;
+
+		case GC_EFACE:
+			eface = (Eface*)(stack_top.b + pc[1]);
+			pc += 2;
+			if(Debug > 2)
+				runtime_printf("gc_eface @%p: %p %p\n", stack_top.b+pc[1], eface->__type_descriptor, eface->__object);
+			if(eface->__type_descriptor == nil)
+				continue;
+
+			// eface->type
+			t = eface->__type_descriptor;
+			if((const byte*)t >= arena_start && (const byte*)t < arena_used) {
+				union { const Type *tc; Type *tr; } u;
+				u.tc = t;
+				*sbuf.ptr.pos++ = (PtrTarget){u.tr, 0};
+				if(sbuf.ptr.pos == sbuf.ptr.end)
+					flushptrbuf(&sbuf);
+			}
+
+			// eface->__object
+			if((byte*)eface->__object >= arena_start && (byte*)eface->__object < arena_used) {
+				if(__go_is_pointer_type(t)) {
+					if((t->__code & KindNoPointers))
+						continue;
+
+					obj = eface->__object;
+					if((t->__code & ~KindNoPointers) == KindPtr) {
+						// Only use type information if it is a pointer-containing type.
+						// This matches the GC programs written by cmd/gc/reflect.c's
+						// dgcsym1 in case TPTR32/case TPTR64. See rationale there.
+						et = ((const PtrType*)t)->elem;
+						if(!(et->__code & KindNoPointers))
+							objti = (uintptr)((const PtrType*)t)->elem->__gc;
+					}
+				} else {
+					obj = eface->__object;
+					objti = (uintptr)t->__gc;
+				}
+			}
+			break;
+
+		case GC_IFACE:
+			iface = (Iface*)(stack_top.b + pc[1]);
+			pc += 2;
+			if(Debug > 2)
+				runtime_printf("gc_iface @%p: %p/%p %p\n", stack_top.b+pc[1], iface->__methods[0], nil, iface->__object);
+			if(iface->tab == nil)
+				continue;
+			
+			// iface->tab
+			if((byte*)iface->tab >= arena_start && (byte*)iface->tab < arena_used) {
+				*sbuf.ptr.pos++ = (PtrTarget){iface->tab, 0};
+				if(sbuf.ptr.pos == sbuf.ptr.end)
+					flushptrbuf(&sbuf);
+			}
+
+			// iface->data
+			if((byte*)iface->__object >= arena_start && (byte*)iface->__object < arena_used) {
+				t = (const Type*)iface->tab[0];
+				if(__go_is_pointer_type(t)) {
+					if((t->__code & KindNoPointers))
+						continue;
+
+					obj = iface->__object;
+					if((t->__code & ~KindNoPointers) == KindPtr) {
+						// Only use type information if it is a pointer-containing type.
+						// This matches the GC programs written by cmd/gc/reflect.c's
+						// dgcsym1 in case TPTR32/case TPTR64. See rationale there.
+						et = ((const PtrType*)t)->elem;
+						if(!(et->__code & KindNoPointers))
+							objti = (uintptr)((const PtrType*)t)->elem->__gc;
+					}
+				} else {
+					obj = iface->__object;
+					objti = (uintptr)t->__gc;
+				}
+			}
+			break;
+
+		case GC_DEFAULT_PTR:
+			while(stack_top.b <= end_b) {
+				obj = *(byte**)stack_top.b;
+				if(Debug > 2)
+					runtime_printf("gc_default_ptr @%p: %p\n", stack_top.b, obj);
+				stack_top.b += PtrSize;
+				if((byte*)obj >= arena_start && (byte*)obj < arena_used) {
+					*sbuf.ptr.pos++ = (PtrTarget){obj, 0};
+					if(sbuf.ptr.pos == sbuf.ptr.end)
+						flushptrbuf(&sbuf);
+				}
+			}
+			goto next_block;
+
+		case GC_END:
+			if(--stack_top.count != 0) {
+				// Next iteration of a loop if possible.
+				stack_top.b += stack_top.elemsize;
+				if(stack_top.b + stack_top.elemsize <= end_b+PtrSize) {
+					pc = stack_top.loop_or_ret;
+					continue;
+				}
+				i = stack_top.b;
+			} else {
+				// Stack pop if possible.
+				if(stack_ptr+1 < stack+nelem(stack)) {
+					pc = stack_top.loop_or_ret;
+					stack_top = *(++stack_ptr);
+					continue;
+				}
+				i = (uintptr)b + nominal_size;
+			}
+			if(!precise_type) {
+				// Quickly scan [b+i,b+n) for possible pointers.
+				for(; i<=end_b; i+=PtrSize) {
+					if(*(byte**)i != nil) {
+						// Found a value that may be a pointer.
+						// Do a rescan of the entire block.
+						enqueue((Obj){b, n, 0}, &sbuf.wbuf, &sbuf.wp, &sbuf.nobj);
+						if(CollectStats) {
+							runtime_xadd64(&gcstats.rescan, 1);
+							runtime_xadd64(&gcstats.rescanbytes, n);
+						}
+						break;
+					}
+				}
+			}
+			goto next_block;
+
+		case GC_ARRAY_START:
+			i = stack_top.b + pc[1];
+			count = pc[2];
+			elemsize = pc[3];
+			pc += 4;
+
+			// Stack push.
+			*stack_ptr-- = stack_top;
+			stack_top = (Frame){count, elemsize, i, pc};
+			continue;
+
+		case GC_ARRAY_NEXT:
+			if(--stack_top.count != 0) {
+				stack_top.b += stack_top.elemsize;
+				pc = stack_top.loop_or_ret;
+			} else {
+				// Stack pop.
+				stack_top = *(++stack_ptr);
+				pc += 1;
+			}
+			continue;
+
+		case GC_CALL:
+			// Stack push.
+			*stack_ptr-- = stack_top;
+			stack_top = (Frame){1, 0, stack_top.b + pc[1], pc+3 /*return address*/};
+			pc = (const uintptr*)((const byte*)pc + *(const int32*)(pc+2));  // target of the CALL instruction
+			continue;
+
+		case GC_REGION:
+			obj = (void*)(stack_top.b + pc[1]);
+			size = pc[2];
+			objti = pc[3];
+			pc += 4;
+
+			if(Debug > 2)
+				runtime_printf("gc_region @%p: %D %p\n", stack_top.b+pc[1], (int64)size, objti);
+			*sbuf.obj.pos++ = (Obj){obj, size, objti};
+			if(sbuf.obj.pos == sbuf.obj.end)
+				flushobjbuf(&sbuf);
+			continue;
+
+		case GC_CHAN_PTR:
+			chan = *(Hchan**)(stack_top.b + pc[1]);
+			if(Debug > 2 && chan != nil)
+				runtime_printf("gc_chan_ptr @%p: %p/%D/%D %p\n", stack_top.b+pc[1], chan, (int64)chan->qcount, (int64)chan->dataqsiz, pc[2]);
+			if(chan == nil) {
+				pc += 3;
+				continue;
+			}
+			if(markonly(chan)) {
+				chantype = (ChanType*)pc[2];
+				if(!(chantype->elem->__code & KindNoPointers)) {
+					// Start chanProg.
+					chan_ret = pc+3;
+					pc = chanProg+1;
+					continue;
+				}
+			}
+			pc += 3;
+			continue;
+
+		case GC_CHAN:
+			// There are no heap pointers in struct Hchan,
+			// so we can ignore the leading sizeof(Hchan) bytes.
+			if(!(chantype->elem->__code & KindNoPointers)) {
+				// Channel's buffer follows Hchan immediately in memory.
+				// Size of buffer (cap(c)) is second int in the chan struct.
+				chancap = ((uintgo*)chan)[1];
+				if(chancap > 0) {
+					// TODO(atom): split into two chunks so that only the
+					// in-use part of the circular buffer is scanned.
+					// (Channel routines zero the unused part, so the current
+					// code does not lead to leaks, it's just a little inefficient.)
+					*sbuf.obj.pos++ = (Obj){(byte*)chan+runtime_Hchansize, chancap*chantype->elem->__size,
+						(uintptr)chantype->elem->__gc | PRECISE | LOOP};
+					if(sbuf.obj.pos == sbuf.obj.end)
+						flushobjbuf(&sbuf);
+				}
+			}
+			if(chan_ret == nil)
+				goto next_block;
+			pc = chan_ret;
+			continue;
+
+		default:
+			runtime_printf("runtime: invalid GC instruction %p at %p\n", pc[0], pc);
+			runtime_throw("scanblock: invalid GC instruction");
+			return;
+		}
+
+		if((byte*)obj >= arena_start && (byte*)obj < arena_used) {
+			*sbuf.ptr.pos++ = (PtrTarget){obj, objti};
+			if(sbuf.ptr.pos == sbuf.ptr.end)
+				flushptrbuf(&sbuf);
+		}
+	}
+
+	next_block:
+		// Done scanning [b, b+n).  Prepare for the next iteration of
+		// the loop by setting b, n, ti to the parameters for the next block.
+
+		if(sbuf.nobj == 0) {
+			flushptrbuf(&sbuf);
+			flushobjbuf(&sbuf);
+
+			if(sbuf.nobj == 0) {
+				if(!keepworking) {
+					if(sbuf.wbuf)
+						putempty(sbuf.wbuf);
+					return;
+				}
+				// Emptied our buffer: refill.
+				sbuf.wbuf = getfull(sbuf.wbuf);
+				if(sbuf.wbuf == nil)
+					return;
+				sbuf.nobj = sbuf.wbuf->nobj;
+				sbuf.wp = sbuf.wbuf->obj + sbuf.wbuf->nobj;
+			}
+		}
+
+		// Fetch b from the work buffer.
+		--sbuf.wp;
+		b = sbuf.wp->p;
+		n = sbuf.wp->n;
+		ti = sbuf.wp->ti;
+		sbuf.nobj--;
+	}
+}
+
+static struct root_list* roots;
+
+void
+__go_register_gc_roots (struct root_list* r)
+{
+	// FIXME: This needs locking if multiple goroutines can call
+	// dlopen simultaneously.
+	r->next = roots;
+	roots = r;
+}
+
+// Append obj to the work buffer.
+// _wbuf, _wp, _nobj are input/output parameters and are specifying the work buffer.
+static void
+enqueue(Obj obj, Workbuf **_wbuf, Obj **_wp, uintptr *_nobj)
+{
+	uintptr nobj, off;
+	Obj *wp;
+	Workbuf *wbuf;
+
+	if(Debug > 1)
+		runtime_printf("append obj(%p %D %p)\n", obj.p, (int64)obj.n, obj.ti);
+
+	// Align obj.b to a word boundary.
+	off = (uintptr)obj.p & (PtrSize-1);
+	if(off != 0) {
+		obj.p += PtrSize - off;
+		obj.n -= PtrSize - off;
+		obj.ti = 0;
+	}
+
+	if(obj.p == nil || obj.n == 0)
+		return;
+
+	// Load work buffer state
+	wp = *_wp;
+	wbuf = *_wbuf;
+	nobj = *_nobj;
+
+	// If another proc wants a pointer, give it some.
+	if(work.nwait > 0 && nobj > handoffThreshold && work.full == 0) {
+		wbuf->nobj = nobj;
+		wbuf = handoff(wbuf);
+		nobj = wbuf->nobj;
+		wp = wbuf->obj + nobj;
+	}
+
+	// If buffer is full, get a new one.
+	if(wbuf == nil || nobj >= nelem(wbuf->obj)) {
+		if(wbuf != nil)
+			wbuf->nobj = nobj;
+		wbuf = getempty(wbuf);
+		wp = wbuf->obj;
+		nobj = 0;
+	}
+
+	*wp = obj;
+	wp++;
+	nobj++;
+
+	// Save work buffer state
+	*_wp = wp;
+	*_wbuf = wbuf;
+	*_nobj = nobj;
+}
+
+static void
+enqueue1(Workbuf **wbufp, Obj obj)
+{
+	Workbuf *wbuf;
+
+	wbuf = *wbufp;
+	if(wbuf->nobj >= nelem(wbuf->obj))
+		*wbufp = wbuf = getempty(wbuf);
+	wbuf->obj[wbuf->nobj++] = obj;
+}
+
+static void
+markroot(ParFor *desc, uint32 i)
+{
+	Workbuf *wbuf;
+	FinBlock *fb;
+	MHeap *h;
+	MSpan **allspans, *s;
+	uint32 spanidx, sg;
+	G *gp;
+	void *p;
+
+	USED(&desc);
+	wbuf = getempty(nil);
+	// Note: if you add a case here, please also update heapdump.c:dumproots.
+	switch(i) {
+	case RootData:
+		// For gccgo this is both data and bss.
+		{
+			struct root_list *pl;
+
+			for(pl = roots; pl != nil; pl = pl->next) {
+				struct root *pr = &pl->roots[0];
+				while(1) {
+					void *decl = pr->decl;
+					if(decl == nil)
+						break;
+					enqueue1(&wbuf, (Obj){decl, pr->size, 0});
+					pr++;
+				}
+			}
+		}
+		break;
+
+	case RootBss:
+		// For gccgo we use this for all the other global roots.
+		enqueue1(&wbuf, (Obj){(byte*)&runtime_m0, sizeof runtime_m0, 0});
+		enqueue1(&wbuf, (Obj){(byte*)&runtime_g0, sizeof runtime_g0, 0});
+		enqueue1(&wbuf, (Obj){(byte*)&runtime_allg, sizeof runtime_allg, 0});
+		enqueue1(&wbuf, (Obj){(byte*)&runtime_allm, sizeof runtime_allm, 0});
+		enqueue1(&wbuf, (Obj){(byte*)&runtime_allp, sizeof runtime_allp, 0});
+		enqueue1(&wbuf, (Obj){(byte*)&work, sizeof work, 0});
+		runtime_proc_scan(&wbuf, enqueue1);
+		runtime_MProf_Mark(&wbuf, enqueue1);
+		runtime_time_scan(&wbuf, enqueue1);
+		runtime_netpoll_scan(&wbuf, enqueue1);
+		break;
+
+	case RootFinalizers:
+		for(fb=allfin; fb; fb=fb->alllink)
+			enqueue1(&wbuf, (Obj){(byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]), 0});
+		break;
+
+	case RootSpanTypes:
+		// mark span types and MSpan.specials (to walk spans only once)
+		h = &runtime_mheap;
+		sg = h->sweepgen;
+		allspans = h->allspans;
+		for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) {
+			Special *sp;
+			SpecialFinalizer *spf;
+
+			s = allspans[spanidx];
+			if(s->sweepgen != sg) {
+				runtime_printf("sweep %d %d\n", s->sweepgen, sg);
+				runtime_throw("gc: unswept span");
+			}
+			if(s->state != MSpanInUse)
+				continue;
+			// The garbage collector ignores type pointers stored in MSpan.types:
+			//  - Compiler-generated types are stored outside of heap.
+			//  - The reflect package has runtime-generated types cached in its data structures.
+			//    The garbage collector relies on finding the references via that cache.
+			if(s->types.compression == MTypes_Words || s->types.compression == MTypes_Bytes)
+				markonly((byte*)s->types.data);
+			for(sp = s->specials; sp != nil; sp = sp->next) {
+				if(sp->kind != KindSpecialFinalizer)
+					continue;
+				// don't mark finalized object, but scan it so we
+				// retain everything it points to.
+				spf = (SpecialFinalizer*)sp;
+				// A finalizer can be set for an inner byte of an object, find object beginning.
+				p = (void*)((s->start << PageShift) + spf->special.offset/s->elemsize*s->elemsize);
+				enqueue1(&wbuf, (Obj){p, s->elemsize, 0});
+				enqueue1(&wbuf, (Obj){(void*)&spf->fn, PtrSize, 0});
+				enqueue1(&wbuf, (Obj){(void*)&spf->ft, PtrSize, 0});
+				enqueue1(&wbuf, (Obj){(void*)&spf->ot, PtrSize, 0});
+			}
+		}
+		break;
+
+	case RootFlushCaches:
+		flushallmcaches();
+		break;
+
+	default:
+		// the rest is scanning goroutine stacks
+		if(i - RootCount >= runtime_allglen)
+			runtime_throw("markroot: bad index");
+		gp = runtime_allg[i - RootCount];
+		// remember when we've first observed the G blocked
+		// needed only to output in traceback
+		if((gp->status == Gwaiting || gp->status == Gsyscall) && gp->waitsince == 0)
+			gp->waitsince = work.tstart;
+		addstackroots(gp, &wbuf);
+		break;
+		
+	}
+
+	if(wbuf)
+		scanblock(wbuf, false);
+}
+
+// Get an empty work buffer off the work.empty list,
+// allocating new buffers as needed.
+static Workbuf*
+getempty(Workbuf *b)
+{
+	if(b != nil)
+		runtime_lfstackpush(&work.full, &b->node);
+	b = (Workbuf*)runtime_lfstackpop(&work.empty);
+	if(b == nil) {
+		// Need to allocate.
+		runtime_lock(&work.lock);
+		if(work.nchunk < sizeof *b) {
+			work.nchunk = 1<<20;
+			work.chunk = runtime_SysAlloc(work.nchunk, &mstats.gc_sys);
+			if(work.chunk == nil)
+				runtime_throw("runtime: cannot allocate memory");
+		}
+		b = (Workbuf*)work.chunk;
+		work.chunk += sizeof *b;
+		work.nchunk -= sizeof *b;
+		runtime_unlock(&work.lock);
+	}
+	b->nobj = 0;
+	return b;
+}
+
+static void
+putempty(Workbuf *b)
+{
+	if(CollectStats)
+		runtime_xadd64(&gcstats.putempty, 1);
+
+	runtime_lfstackpush(&work.empty, &b->node);
+}
+
+// Get a full work buffer off the work.full list, or return nil.
+static Workbuf*
+getfull(Workbuf *b)
+{
+	M *m;
+	int32 i;
+
+	if(CollectStats)
+		runtime_xadd64(&gcstats.getfull, 1);
+
+	if(b != nil)
+		runtime_lfstackpush(&work.empty, &b->node);
+	b = (Workbuf*)runtime_lfstackpop(&work.full);
+	if(b != nil || work.nproc == 1)
+		return b;
+
+	m = runtime_m();
+	runtime_xadd(&work.nwait, +1);
+	for(i=0;; i++) {
+		if(work.full != 0) {
+			runtime_xadd(&work.nwait, -1);
+			b = (Workbuf*)runtime_lfstackpop(&work.full);
+			if(b != nil)
+				return b;
+			runtime_xadd(&work.nwait, +1);
+		}
+		if(work.nwait == work.nproc)
+			return nil;
+		if(i < 10) {
+			m->gcstats.nprocyield++;
+			runtime_procyield(20);
+		} else if(i < 20) {
+			m->gcstats.nosyield++;
+			runtime_osyield();
+		} else {
+			m->gcstats.nsleep++;
+			runtime_usleep(100);
+		}
+	}
+}
+
+static Workbuf*
+handoff(Workbuf *b)
+{
+	M *m;
+	int32 n;
+	Workbuf *b1;
+
+	m = runtime_m();
+
+	// Make new buffer with half of b's pointers.
+	b1 = getempty(nil);
+	n = b->nobj/2;
+	b->nobj -= n;
+	b1->nobj = n;
+	runtime_memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]);
+	m->gcstats.nhandoff++;
+	m->gcstats.nhandoffcnt += n;
+
+	// Put b on full list - let first half of b get stolen.
+	runtime_lfstackpush(&work.full, &b->node);
+	return b1;
+}
+
+static void
+addstackroots(G *gp, Workbuf **wbufp)
+{
+	switch(gp->status){
+	default:
+		runtime_printf("unexpected G.status %d (goroutine %p %D)\n", gp->status, gp, gp->goid);
+		runtime_throw("mark - bad status");
+	case Gdead:
+		return;
+	case Grunning:
+		runtime_throw("mark - world not stopped");
+	case Grunnable:
+	case Gsyscall:
+	case Gwaiting:
+		break;
+	}
+
+#ifdef USING_SPLIT_STACK
+	M *mp;
+	void* sp;
+	size_t spsize;
+	void* next_segment;
+	void* next_sp;
+	void* initial_sp;
+
+	if(gp == runtime_g()) {
+		// Scanning our own stack.
+		sp = __splitstack_find(nil, nil, &spsize, &next_segment,
+				       &next_sp, &initial_sp);
+	} else if((mp = gp->m) != nil && mp->helpgc) {
+		// gchelper's stack is in active use and has no interesting pointers.
+		return;
+	} else {
+		// Scanning another goroutine's stack.
+		// The goroutine is usually asleep (the world is stopped).
+
+		// The exception is that if the goroutine is about to enter or might
+		// have just exited a system call, it may be executing code such
+		// as schedlock and may have needed to start a new stack segment.
+		// Use the stack segment and stack pointer at the time of
+		// the system call instead, since that won't change underfoot.
+		if(gp->gcstack != nil) {
+			sp = gp->gcstack;
+			spsize = gp->gcstack_size;
+			next_segment = gp->gcnext_segment;
+			next_sp = gp->gcnext_sp;
+			initial_sp = gp->gcinitial_sp;
+		} else {
+			sp = __splitstack_find_context(&gp->stack_context[0],
+						       &spsize, &next_segment,
+						       &next_sp, &initial_sp);
+		}
+	}
+	if(sp != nil) {
+		enqueue1(wbufp, (Obj){sp, spsize, 0});
+		while((sp = __splitstack_find(next_segment, next_sp,
+					      &spsize, &next_segment,
+					      &next_sp, &initial_sp)) != nil)
+			enqueue1(wbufp, (Obj){sp, spsize, 0});
+	}
+#else
+	M *mp;
+	byte* bottom;
+	byte* top;
+
+	if(gp == runtime_g()) {
+		// Scanning our own stack.
+		bottom = (byte*)&gp;
+	} else if((mp = gp->m) != nil && mp->helpgc) {
+		// gchelper's stack is in active use and has no interesting pointers.
+		return;
+	} else {
+		// Scanning another goroutine's stack.
+		// The goroutine is usually asleep (the world is stopped).
+		bottom = (byte*)gp->gcnext_sp;
+		if(bottom == nil)
+			return;
+	}
+	top = (byte*)gp->gcinitial_sp + gp->gcstack_size;
+	if(top > bottom)
+		enqueue1(wbufp, (Obj){bottom, top - bottom, 0});
+	else
+		enqueue1(wbufp, (Obj){top, bottom - top, 0});
+#endif
+}
+
+void
+runtime_queuefinalizer(void *p, FuncVal *fn, const FuncType *ft, const PtrType *ot)
+{
+	FinBlock *block;
+	Finalizer *f;
+
+	runtime_lock(&finlock);
+	if(finq == nil || finq->cnt == finq->cap) {
+		if(finc == nil) {
+			finc = runtime_persistentalloc(FinBlockSize, 0, &mstats.gc_sys);
+			finc->cap = (FinBlockSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1;
+			finc->alllink = allfin;
+			allfin = finc;
+		}
+		block = finc;
+		finc = block->next;
+		block->next = finq;
+		finq = block;
+	}
+	f = &finq->fin[finq->cnt];
+	finq->cnt++;
+	f->fn = fn;
+	f->ft = ft;
+	f->ot = ot;
+	f->arg = p;
+	runtime_fingwake = true;
+	runtime_unlock(&finlock);
+}
+
+void
+runtime_iterate_finq(void (*callback)(FuncVal*, void*, const FuncType*, const PtrType*))
+{
+	FinBlock *fb;
+	Finalizer *f;
+	int32 i;
+
+	for(fb = allfin; fb; fb = fb->alllink) {
+		for(i = 0; i < fb->cnt; i++) {
+			f = &fb->fin[i];
+			callback(f->fn, f->arg, f->ft, f->ot);
+		}
+	}
+}
+
+void
+runtime_MSpan_EnsureSwept(MSpan *s)
+{
+	M *m = runtime_m();
+	G *g = runtime_g();
+	uint32 sg;
+
+	// Caller must disable preemption.
+	// Otherwise when this function returns the span can become unswept again
+	// (if GC is triggered on another goroutine).
+	if(m->locks == 0 && m->mallocing == 0 && g != m->g0)
+		runtime_throw("MSpan_EnsureSwept: m is not locked");
+
+	sg = runtime_mheap.sweepgen;
+	if(runtime_atomicload(&s->sweepgen) == sg)
+		return;
+	if(runtime_cas(&s->sweepgen, sg-2, sg-1)) {
+		runtime_MSpan_Sweep(s);
+		return;
+	}
+	// unfortunate condition, and we don't have efficient means to wait
+	while(runtime_atomicload(&s->sweepgen) != sg)
+		runtime_osyield();  
+}
+
+// Sweep frees or collects finalizers for blocks not marked in the mark phase.
+// It clears the mark bits in preparation for the next GC round.
+// Returns true if the span was returned to heap.
+bool
+runtime_MSpan_Sweep(MSpan *s)
+{
+	M *m;
+	int32 cl, n, npages, nfree;
+	uintptr size, off, *bitp, shift, bits;
+	uint32 sweepgen;
+	byte *p;
+	MCache *c;
+	byte *arena_start;
+	MLink head, *end;
+	byte *type_data;
+	byte compression;
+	uintptr type_data_inc;
+	MLink *x;
+	Special *special, **specialp, *y;
+	bool res, sweepgenset;
+
+	m = runtime_m();
+
+	// It's critical that we enter this function with preemption disabled,
+	// GC must not start while we are in the middle of this function.
+	if(m->locks == 0 && m->mallocing == 0 && runtime_g() != m->g0)
+		runtime_throw("MSpan_Sweep: m is not locked");
+	sweepgen = runtime_mheap.sweepgen;
+	if(s->state != MSpanInUse || s->sweepgen != sweepgen-1) {
+		runtime_printf("MSpan_Sweep: state=%d sweepgen=%d mheap.sweepgen=%d\n",
+			s->state, s->sweepgen, sweepgen);
+		runtime_throw("MSpan_Sweep: bad span state");
+	}
+	arena_start = runtime_mheap.arena_start;
+	cl = s->sizeclass;
+	size = s->elemsize;
+	if(cl == 0) {
+		n = 1;
+	} else {
+		// Chunk full of small blocks.
+		npages = runtime_class_to_allocnpages[cl];
+		n = (npages << PageShift) / size;
+	}
+	res = false;
+	nfree = 0;
+	end = &head;
+	c = m->mcache;
+	sweepgenset = false;
+
+	// mark any free objects in this span so we don't collect them
+	for(x = s->freelist; x != nil; x = x->next) {
+		// This is markonly(x) but faster because we don't need
+		// atomic access and we're guaranteed to be pointing at
+		// the head of a valid object.
+		off = (uintptr*)x - (uintptr*)runtime_mheap.arena_start;
+		bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		*bitp |= bitMarked<<shift;
+	}
+
+	// Unlink & free special records for any objects we're about to free.
+	specialp = &s->specials;
+	special = *specialp;
+	while(special != nil) {
+		// A finalizer can be set for an inner byte of an object, find object beginning.
+		p = (byte*)(s->start << PageShift) + special->offset/size*size;
+		off = (uintptr*)p - (uintptr*)arena_start;
+		bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		bits = *bitp>>shift;
+		if((bits & (bitAllocated|bitMarked)) == bitAllocated) {
+			// Find the exact byte for which the special was setup
+			// (as opposed to object beginning).
+			p = (byte*)(s->start << PageShift) + special->offset;
+			// about to free object: splice out special record
+			y = special;
+			special = special->next;
+			*specialp = special;
+			if(!runtime_freespecial(y, p, size, false)) {
+				// stop freeing of object if it has a finalizer
+				*bitp |= bitMarked << shift;
+			}
+		} else {
+			// object is still live: keep special record
+			specialp = &special->next;
+			special = *specialp;
+		}
+	}
+
+	type_data = (byte*)s->types.data;
+	type_data_inc = sizeof(uintptr);
+	compression = s->types.compression;
+	switch(compression) {
+	case MTypes_Bytes:
+		type_data += 8*sizeof(uintptr);
+		type_data_inc = 1;
+		break;
+	}
+
+	// Sweep through n objects of given size starting at p.
+	// This thread owns the span now, so it can manipulate
+	// the block bitmap without atomic operations.
+	p = (byte*)(s->start << PageShift);
+	for(; n > 0; n--, p += size, type_data+=type_data_inc) {
+		off = (uintptr*)p - (uintptr*)arena_start;
+		bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		bits = *bitp>>shift;
+
+		if((bits & bitAllocated) == 0)
+			continue;
+
+		if((bits & bitMarked) != 0) {
+			*bitp &= ~(bitMarked<<shift);
+			continue;
+		}
+
+		if(runtime_debug.allocfreetrace)
+			runtime_tracefree(p, size);
+
+		// Clear mark and scan bits.
+		*bitp &= ~((bitScan|bitMarked)<<shift);
+
+		if(cl == 0) {
+			// Free large span.
+			runtime_unmarkspan(p, 1<<PageShift);
+			s->needzero = 1;
+			// important to set sweepgen before returning it to heap
+			runtime_atomicstore(&s->sweepgen, sweepgen);
+			sweepgenset = true;
+			// See note about SysFault vs SysFree in malloc.goc.
+			if(runtime_debug.efence)
+				runtime_SysFault(p, size);
+			else
+				runtime_MHeap_Free(&runtime_mheap, s, 1);
+			c->local_nlargefree++;
+			c->local_largefree += size;
+			runtime_xadd64(&mstats.next_gc, -(uint64)(size * (gcpercent + 100)/100));
+			res = true;
+		} else {
+			// Free small object.
+			switch(compression) {
+			case MTypes_Words:
+				*(uintptr*)type_data = 0;
+				break;
+			case MTypes_Bytes:
+				*(byte*)type_data = 0;
+				break;
+			}
+			if(size > 2*sizeof(uintptr))
+				((uintptr*)p)[1] = (uintptr)0xdeaddeaddeaddeadll;	// mark as "needs to be zeroed"
+			else if(size > sizeof(uintptr))
+				((uintptr*)p)[1] = 0;
+
+			end->next = (MLink*)p;
+			end = (MLink*)p;
+			nfree++;
+		}
+	}
+
+	// We need to set s->sweepgen = h->sweepgen only when all blocks are swept,
+	// because of the potential for a concurrent free/SetFinalizer.
+	// But we need to set it before we make the span available for allocation
+	// (return it to heap or mcentral), because allocation code assumes that a
+	// span is already swept if available for allocation.
+
+	if(!sweepgenset && nfree == 0) {
+		// The span must be in our exclusive ownership until we update sweepgen,
+		// check for potential races.
+		if(s->state != MSpanInUse || s->sweepgen != sweepgen-1) {
+			runtime_printf("MSpan_Sweep: state=%d sweepgen=%d mheap.sweepgen=%d\n",
+				s->state, s->sweepgen, sweepgen);
+			runtime_throw("MSpan_Sweep: bad span state after sweep");
+		}
+		runtime_atomicstore(&s->sweepgen, sweepgen);
+	}
+	if(nfree > 0) {
+		c->local_nsmallfree[cl] += nfree;
+		c->local_cachealloc -= nfree * size;
+		runtime_xadd64(&mstats.next_gc, -(uint64)(nfree * size * (gcpercent + 100)/100));
+		res = runtime_MCentral_FreeSpan(&runtime_mheap.central[cl].mcentral, s, nfree, head.next, end);
+		//MCentral_FreeSpan updates sweepgen
+	}
+	return res;
+}
+
+// State of background sweep.
+// Protected by gclock.
+static struct
+{
+	G*	g;
+	bool	parked;
+
+	MSpan**	spans;
+	uint32	nspan;
+	uint32	spanidx;
+} sweep;
+
+// background sweeping goroutine
+static void
+bgsweep(void* dummy __attribute__ ((unused)))
+{
+	runtime_g()->issystem = 1;
+	for(;;) {
+		while(runtime_sweepone() != (uintptr)-1) {
+			gcstats.nbgsweep++;
+			runtime_gosched();
+		}
+		runtime_lock(&gclock);
+		if(!runtime_mheap.sweepdone) {
+			// It's possible if GC has happened between sweepone has
+			// returned -1 and gclock lock.
+			runtime_unlock(&gclock);
+			continue;
+		}
+		sweep.parked = true;
+		runtime_g()->isbackground = true;
+		runtime_parkunlock(&gclock, "GC sweep wait");
+		runtime_g()->isbackground = false;
+	}
+}
+
+// sweeps one span
+// returns number of pages returned to heap, or -1 if there is nothing to sweep
+uintptr
+runtime_sweepone(void)
+{
+	M *m = runtime_m();
+	MSpan *s;
+	uint32 idx, sg;
+	uintptr npages;
+
+	// increment locks to ensure that the goroutine is not preempted
+	// in the middle of sweep thus leaving the span in an inconsistent state for next GC
+	m->locks++;
+	sg = runtime_mheap.sweepgen;
+	for(;;) {
+		idx = runtime_xadd(&sweep.spanidx, 1) - 1;
+		if(idx >= sweep.nspan) {
+			runtime_mheap.sweepdone = true;
+			m->locks--;
+			return (uintptr)-1;
+		}
+		s = sweep.spans[idx];
+		if(s->state != MSpanInUse) {
+			s->sweepgen = sg;
+			continue;
+		}
+		if(s->sweepgen != sg-2 || !runtime_cas(&s->sweepgen, sg-2, sg-1))
+			continue;
+		if(s->incache)
+			runtime_throw("sweep of incache span");
+		npages = s->npages;
+		if(!runtime_MSpan_Sweep(s))
+			npages = 0;
+		m->locks--;
+		return npages;
+	}
+}
+
+static void
+dumpspan(uint32 idx)
+{
+	int32 sizeclass, n, npages, i, column;
+	uintptr size;
+	byte *p;
+	byte *arena_start;
+	MSpan *s;
+	bool allocated;
+
+	s = runtime_mheap.allspans[idx];
+	if(s->state != MSpanInUse)
+		return;
+	arena_start = runtime_mheap.arena_start;
+	p = (byte*)(s->start << PageShift);
+	sizeclass = s->sizeclass;
+	size = s->elemsize;
+	if(sizeclass == 0) {
+		n = 1;
+	} else {
+		npages = runtime_class_to_allocnpages[sizeclass];
+		n = (npages << PageShift) / size;
+	}
+	
+	runtime_printf("%p .. %p:\n", p, p+n*size);
+	column = 0;
+	for(; n>0; n--, p+=size) {
+		uintptr off, *bitp, shift, bits;
+
+		off = (uintptr*)p - (uintptr*)arena_start;
+		bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		bits = *bitp>>shift;
+
+		allocated = ((bits & bitAllocated) != 0);
+
+		for(i=0; (uint32)i<size; i+=sizeof(void*)) {
+			if(column == 0) {
+				runtime_printf("\t");
+			}
+			if(i == 0) {
+				runtime_printf(allocated ? "(" : "[");
+				runtime_printf("%p: ", p+i);
+			} else {
+				runtime_printf(" ");
+			}
+
+			runtime_printf("%p", *(void**)(p+i));
+
+			if(i+sizeof(void*) >= size) {
+				runtime_printf(allocated ? ") " : "] ");
+			}
+
+			column++;
+			if(column == 8) {
+				runtime_printf("\n");
+				column = 0;
+			}
+		}
+	}
+	runtime_printf("\n");
+}
+
+// A debugging function to dump the contents of memory
+void
+runtime_memorydump(void)
+{
+	uint32 spanidx;
+
+	for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) {
+		dumpspan(spanidx);
+	}
+}
+
+void
+runtime_gchelper(void)
+{
+	uint32 nproc;
+
+	runtime_m()->traceback = 2;
+	gchelperstart();
+
+	// parallel mark for over gc roots
+	runtime_parfordo(work.markfor);
+
+	// help other threads scan secondary blocks
+	scanblock(nil, true);
+
+	bufferList[runtime_m()->helpgc].busy = 0;
+	nproc = work.nproc;  // work.nproc can change right after we increment work.ndone
+	if(runtime_xadd(&work.ndone, +1) == nproc-1)
+		runtime_notewakeup(&work.alldone);
+	runtime_m()->traceback = 0;
+}
+
+static void
+cachestats(void)
+{
+	MCache *c;
+	P *p, **pp;
+
+	for(pp=runtime_allp; (p=*pp) != nil; pp++) {
+		c = p->mcache;
+		if(c==nil)
+			continue;
+		runtime_purgecachedstats(c);
+	}
+}
+
+static void
+flushallmcaches(void)
+{
+	P *p, **pp;
+	MCache *c;
+
+	// Flush MCache's to MCentral.
+	for(pp=runtime_allp; (p=*pp) != nil; pp++) {
+		c = p->mcache;
+		if(c==nil)
+			continue;
+		runtime_MCache_ReleaseAll(c);
+	}
+}
+
+void
+runtime_updatememstats(GCStats *stats)
+{
+	M *mp;
+	MSpan *s;
+	uint32 i;
+	uint64 stacks_inuse, smallfree;
+	uint64 *src, *dst;
+
+	if(stats)
+		runtime_memclr((byte*)stats, sizeof(*stats));
+	stacks_inuse = 0;
+	for(mp=runtime_allm; mp; mp=mp->alllink) {
+		//stacks_inuse += mp->stackinuse*FixedStack;
+		if(stats) {
+			src = (uint64*)&mp->gcstats;
+			dst = (uint64*)stats;
+			for(i=0; i<sizeof(*stats)/sizeof(uint64); i++)
+				dst[i] += src[i];
+			runtime_memclr((byte*)&mp->gcstats, sizeof(mp->gcstats));
+		}
+	}
+	mstats.stacks_inuse = stacks_inuse;
+	mstats.mcache_inuse = runtime_mheap.cachealloc.inuse;
+	mstats.mspan_inuse = runtime_mheap.spanalloc.inuse;
+	mstats.sys = mstats.heap_sys + mstats.stacks_sys + mstats.mspan_sys +
+		mstats.mcache_sys + mstats.buckhash_sys + mstats.gc_sys + mstats.other_sys;
+	
+	// Calculate memory allocator stats.
+	// During program execution we only count number of frees and amount of freed memory.
+	// Current number of alive object in the heap and amount of alive heap memory
+	// are calculated by scanning all spans.
+	// Total number of mallocs is calculated as number of frees plus number of alive objects.
+	// Similarly, total amount of allocated memory is calculated as amount of freed memory
+	// plus amount of alive heap memory.
+	mstats.alloc = 0;
+	mstats.total_alloc = 0;
+	mstats.nmalloc = 0;
+	mstats.nfree = 0;
+	for(i = 0; i < nelem(mstats.by_size); i++) {
+		mstats.by_size[i].nmalloc = 0;
+		mstats.by_size[i].nfree = 0;
+	}
+
+	// Flush MCache's to MCentral.
+	flushallmcaches();
+
+	// Aggregate local stats.
+	cachestats();
+
+	// Scan all spans and count number of alive objects.
+	for(i = 0; i < runtime_mheap.nspan; i++) {
+		s = runtime_mheap.allspans[i];
+		if(s->state != MSpanInUse)
+			continue;
+		if(s->sizeclass == 0) {
+			mstats.nmalloc++;
+			mstats.alloc += s->elemsize;
+		} else {
+			mstats.nmalloc += s->ref;
+			mstats.by_size[s->sizeclass].nmalloc += s->ref;
+			mstats.alloc += s->ref*s->elemsize;
+		}
+	}
+
+	// Aggregate by size class.
+	smallfree = 0;
+	mstats.nfree = runtime_mheap.nlargefree;
+	for(i = 0; i < nelem(mstats.by_size); i++) {
+		mstats.nfree += runtime_mheap.nsmallfree[i];
+		mstats.by_size[i].nfree = runtime_mheap.nsmallfree[i];
+		mstats.by_size[i].nmalloc += runtime_mheap.nsmallfree[i];
+		smallfree += runtime_mheap.nsmallfree[i] * runtime_class_to_size[i];
+	}
+	mstats.nmalloc += mstats.nfree;
+
+	// Calculate derived stats.
+	mstats.total_alloc = mstats.alloc + runtime_mheap.largefree + smallfree;
+	mstats.heap_alloc = mstats.alloc;
+	mstats.heap_objects = mstats.nmalloc - mstats.nfree;
+}
+
+// Structure of arguments passed to function gc().
+// This allows the arguments to be passed via runtime_mcall.
+struct gc_args
+{
+	int64 start_time; // start time of GC in ns (just before stoptheworld)
+	bool  eagersweep;
+};
+
+static void gc(struct gc_args *args);
+static void mgc(G *gp);
+
+static int32
+readgogc(void)
+{
+	const byte *p;
+
+	p = runtime_getenv("GOGC");
+	if(p == nil || p[0] == '\0')
+		return 100;
+	if(runtime_strcmp((const char *)p, "off") == 0)
+		return -1;
+	return runtime_atoi(p);
+}
+
+// force = 1 - do GC regardless of current heap usage
+// force = 2 - go GC and eager sweep
+void
+runtime_gc(int32 force)
+{
+	M *m;
+	G *g;
+	struct gc_args a;
+	int32 i;
+
+	// The atomic operations are not atomic if the uint64s
+	// are not aligned on uint64 boundaries. This has been
+	// a problem in the past.
+	if((((uintptr)&work.empty) & 7) != 0)
+		runtime_throw("runtime: gc work buffer is misaligned");
+	if((((uintptr)&work.full) & 7) != 0)
+		runtime_throw("runtime: gc work buffer is misaligned");
+
+	// Make sure all registers are saved on stack so that
+	// scanstack sees them.
+	__builtin_unwind_init();
+
+	// The gc is turned off (via enablegc) until
+	// the bootstrap has completed.
+	// Also, malloc gets called in the guts
+	// of a number of libraries that might be
+	// holding locks.  To avoid priority inversion
+	// problems, don't bother trying to run gc
+	// while holding a lock.  The next mallocgc
+	// without a lock will do the gc instead.
+	m = runtime_m();
+	if(!mstats.enablegc || runtime_g() == m->g0 || m->locks > 0 || runtime_panicking)
+		return;
+
+	if(gcpercent == GcpercentUnknown) {	// first time through
+		runtime_lock(&runtime_mheap.lock);
+		if(gcpercent == GcpercentUnknown)
+			gcpercent = readgogc();
+		runtime_unlock(&runtime_mheap.lock);
+	}
+	if(gcpercent < 0)
+		return;
+
+	runtime_semacquire(&runtime_worldsema, false);
+	if(force==0 && mstats.heap_alloc < mstats.next_gc) {
+		// typically threads which lost the race to grab
+		// worldsema exit here when gc is done.
+		runtime_semrelease(&runtime_worldsema);
+		return;
+	}
+
+	// Ok, we're doing it!  Stop everybody else
+	a.start_time = runtime_nanotime();
+	a.eagersweep = force >= 2;
+	m->gcing = 1;
+	runtime_stoptheworld();
+	
+	clearpools();
+
+	// Run gc on the g0 stack.  We do this so that the g stack
+	// we're currently running on will no longer change.  Cuts
+	// the root set down a bit (g0 stacks are not scanned, and
+	// we don't need to scan gc's internal state).  Also an
+	// enabler for copyable stacks.
+	for(i = 0; i < (runtime_debug.gctrace > 1 ? 2 : 1); i++) {
+		if(i > 0)
+			a.start_time = runtime_nanotime();
+		// switch to g0, call gc(&a), then switch back
+		g = runtime_g();
+		g->param = &a;
+		g->status = Gwaiting;
+		g->waitreason = "garbage collection";
+		runtime_mcall(mgc);
+		m = runtime_m();
+	}
+
+	// all done
+	m->gcing = 0;
+	m->locks++;
+	runtime_semrelease(&runtime_worldsema);
+	runtime_starttheworld();
+	m->locks--;
+
+	// now that gc is done, kick off finalizer thread if needed
+	if(!ConcurrentSweep) {
+		// give the queued finalizers, if any, a chance to run
+		runtime_gosched();
+	} else {
+		// For gccgo, let other goroutines run.
+		runtime_gosched();
+	}
+}
+
+static void
+mgc(G *gp)
+{
+	gc(gp->param);
+	gp->param = nil;
+	gp->status = Grunning;
+	runtime_gogo(gp);
+}
+
+static void
+gc(struct gc_args *args)
+{
+	M *m;
+	int64 t0, t1, t2, t3, t4;
+	uint64 heap0, heap1, obj, ninstr;
+	GCStats stats;
+	uint32 i;
+	// Eface eface;
+
+	m = runtime_m();
+
+	if(runtime_debug.allocfreetrace)
+		runtime_tracegc();
+
+	m->traceback = 2;
+	t0 = args->start_time;
+	work.tstart = args->start_time; 
+
+	if(CollectStats)
+		runtime_memclr((byte*)&gcstats, sizeof(gcstats));
+
+	m->locks++;	// disable gc during mallocs in parforalloc
+	if(work.markfor == nil)
+		work.markfor = runtime_parforalloc(MaxGcproc);
+	m->locks--;
+
+	t1 = 0;
+	if(runtime_debug.gctrace)
+		t1 = runtime_nanotime();
+
+	// Sweep what is not sweeped by bgsweep.
+	while(runtime_sweepone() != (uintptr)-1)
+		gcstats.npausesweep++;
+
+	work.nwait = 0;
+	work.ndone = 0;
+	work.nproc = runtime_gcprocs();
+	runtime_parforsetup(work.markfor, work.nproc, RootCount + runtime_allglen, nil, false, markroot);
+	if(work.nproc > 1) {
+		runtime_noteclear(&work.alldone);
+		runtime_helpgc(work.nproc);
+	}
+
+	t2 = 0;
+	if(runtime_debug.gctrace)
+		t2 = runtime_nanotime();
+
+	gchelperstart();
+	runtime_parfordo(work.markfor);
+	scanblock(nil, true);
+
+	t3 = 0;
+	if(runtime_debug.gctrace)
+		t3 = runtime_nanotime();
+
+	bufferList[m->helpgc].busy = 0;
+	if(work.nproc > 1)
+		runtime_notesleep(&work.alldone);
+
+	cachestats();
+	// next_gc calculation is tricky with concurrent sweep since we don't know size of live heap
+	// estimate what was live heap size after previous GC (for tracing only)
+	heap0 = mstats.next_gc*100/(gcpercent+100);
+	// conservatively set next_gc to high value assuming that everything is live
+	// concurrent/lazy sweep will reduce this number while discovering new garbage
+	mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/100;
+
+	t4 = runtime_nanotime();
+	mstats.last_gc = runtime_unixnanotime();  // must be Unix time to make sense to user
+	mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = t4 - t0;
+	mstats.pause_total_ns += t4 - t0;
+	mstats.numgc++;
+	if(mstats.debuggc)
+		runtime_printf("pause %D\n", t4-t0);
+
+	if(runtime_debug.gctrace) {
+		heap1 = mstats.heap_alloc;
+		runtime_updatememstats(&stats);
+		if(heap1 != mstats.heap_alloc) {
+			runtime_printf("runtime: mstats skew: heap=%D/%D\n", heap1, mstats.heap_alloc);
+			runtime_throw("mstats skew");
+		}
+		obj = mstats.nmalloc - mstats.nfree;
+
+		stats.nprocyield += work.markfor->nprocyield;
+		stats.nosyield += work.markfor->nosyield;
+		stats.nsleep += work.markfor->nsleep;
+
+		runtime_printf("gc%d(%d): %D+%D+%D+%D us, %D -> %D MB, %D (%D-%D) objects,"
+				" %d/%d/%d sweeps,"
+				" %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\n",
+			mstats.numgc, work.nproc, (t1-t0)/1000, (t2-t1)/1000, (t3-t2)/1000, (t4-t3)/1000,
+			heap0>>20, heap1>>20, obj,
+			mstats.nmalloc, mstats.nfree,
+			sweep.nspan, gcstats.nbgsweep, gcstats.npausesweep,
+			stats.nhandoff, stats.nhandoffcnt,
+			work.markfor->nsteal, work.markfor->nstealcnt,
+			stats.nprocyield, stats.nosyield, stats.nsleep);
+		gcstats.nbgsweep = gcstats.npausesweep = 0;
+		if(CollectStats) {
+			runtime_printf("scan: %D bytes, %D objects, %D untyped, %D types from MSpan\n",
+				gcstats.nbytes, gcstats.obj.cnt, gcstats.obj.notype, gcstats.obj.typelookup);
+			if(gcstats.ptr.cnt != 0)
+				runtime_printf("avg ptrbufsize: %D (%D/%D)\n",
+					gcstats.ptr.sum/gcstats.ptr.cnt, gcstats.ptr.sum, gcstats.ptr.cnt);
+			if(gcstats.obj.cnt != 0)
+				runtime_printf("avg nobj: %D (%D/%D)\n",
+					gcstats.obj.sum/gcstats.obj.cnt, gcstats.obj.sum, gcstats.obj.cnt);
+			runtime_printf("rescans: %D, %D bytes\n", gcstats.rescan, gcstats.rescanbytes);
+
+			runtime_printf("instruction counts:\n");
+			ninstr = 0;
+			for(i=0; i<nelem(gcstats.instr); i++) {
+				runtime_printf("\t%d:\t%D\n", i, gcstats.instr[i]);
+				ninstr += gcstats.instr[i];
+			}
+			runtime_printf("\ttotal:\t%D\n", ninstr);
+
+			runtime_printf("putempty: %D, getfull: %D\n", gcstats.putempty, gcstats.getfull);
+
+			runtime_printf("markonly base lookup: bit %D word %D span %D\n", gcstats.markonly.foundbit, gcstats.markonly.foundword, gcstats.markonly.foundspan);
+			runtime_printf("flushptrbuf base lookup: bit %D word %D span %D\n", gcstats.flushptrbuf.foundbit, gcstats.flushptrbuf.foundword, gcstats.flushptrbuf.foundspan);
+		}
+	}
+
+	// We cache current runtime_mheap.allspans array in sweep.spans,
+	// because the former can be resized and freed.
+	// Otherwise we would need to take heap lock every time
+	// we want to convert span index to span pointer.
+
+	// Free the old cached array if necessary.
+	if(sweep.spans && sweep.spans != runtime_mheap.allspans)
+		runtime_SysFree(sweep.spans, sweep.nspan*sizeof(sweep.spans[0]), &mstats.other_sys);
+	// Cache the current array.
+	runtime_mheap.sweepspans = runtime_mheap.allspans;
+	runtime_mheap.sweepgen += 2;
+	runtime_mheap.sweepdone = false;
+	sweep.spans = runtime_mheap.allspans;
+	sweep.nspan = runtime_mheap.nspan;
+	sweep.spanidx = 0;
+
+	// Temporary disable concurrent sweep, because we see failures on builders.
+	if(ConcurrentSweep && !args->eagersweep) {
+		runtime_lock(&gclock);
+		if(sweep.g == nil)
+			sweep.g = __go_go(bgsweep, nil);
+		else if(sweep.parked) {
+			sweep.parked = false;
+			runtime_ready(sweep.g);
+		}
+		runtime_unlock(&gclock);
+	} else {
+		// Sweep all spans eagerly.
+		while(runtime_sweepone() != (uintptr)-1)
+			gcstats.npausesweep++;
+	}
+
+	runtime_MProf_GC();
+	m->traceback = 0;
+}
+
+extern uintptr runtime_sizeof_C_MStats
+  __asm__ (GOSYM_PREFIX "runtime.Sizeof_C_MStats");
+
+void runtime_ReadMemStats(MStats *)
+  __asm__ (GOSYM_PREFIX "runtime.ReadMemStats");
+
+void
+runtime_ReadMemStats(MStats *stats)
+{
+	M *m;
+
+	// Have to acquire worldsema to stop the world,
+	// because stoptheworld can only be used by
+	// one goroutine at a time, and there might be
+	// a pending garbage collection already calling it.
+	runtime_semacquire(&runtime_worldsema, false);
+	m = runtime_m();
+	m->gcing = 1;
+	runtime_stoptheworld();
+	runtime_updatememstats(nil);
+	// Size of the trailing by_size array differs between Go and C,
+	// NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
+	runtime_memmove(stats, &mstats, runtime_sizeof_C_MStats);
+	m->gcing = 0;
+	m->locks++;
+	runtime_semrelease(&runtime_worldsema);
+	runtime_starttheworld();
+	m->locks--;
+}
+
+void runtime_debug_readGCStats(Slice*)
+  __asm__("runtime_debug.readGCStats");
+
+void
+runtime_debug_readGCStats(Slice *pauses)
+{
+	uint64 *p;
+	uint32 i, n;
+
+	// Calling code in runtime/debug should make the slice large enough.
+	if((size_t)pauses->cap < nelem(mstats.pause_ns)+3)
+		runtime_throw("runtime: short slice passed to readGCStats");
+
+	// Pass back: pauses, last gc (absolute time), number of gc, total pause ns.
+	p = (uint64*)pauses->array;
+	runtime_lock(&runtime_mheap.lock);
+	n = mstats.numgc;
+	if(n > nelem(mstats.pause_ns))
+		n = nelem(mstats.pause_ns);
+	
+	// The pause buffer is circular. The most recent pause is at
+	// pause_ns[(numgc-1)%nelem(pause_ns)], and then backward
+	// from there to go back farther in time. We deliver the times
+	// most recent first (in p[0]).
+	for(i=0; i<n; i++)
+		p[i] = mstats.pause_ns[(mstats.numgc-1-i)%nelem(mstats.pause_ns)];
+
+	p[n] = mstats.last_gc;
+	p[n+1] = mstats.numgc;
+	p[n+2] = mstats.pause_total_ns;	
+	runtime_unlock(&runtime_mheap.lock);
+	pauses->__count = n+3;
+}
+
+int32
+runtime_setgcpercent(int32 in) {
+	int32 out;
+
+	runtime_lock(&runtime_mheap.lock);
+	if(gcpercent == GcpercentUnknown)
+		gcpercent = readgogc();
+	out = gcpercent;
+	if(in < 0)
+		in = -1;
+	gcpercent = in;
+	runtime_unlock(&runtime_mheap.lock);
+	return out;
+}
+
+static void
+gchelperstart(void)
+{
+	M *m;
+
+	m = runtime_m();
+	if(m->helpgc < 0 || m->helpgc >= MaxGcproc)
+		runtime_throw("gchelperstart: bad m->helpgc");
+	if(runtime_xchg(&bufferList[m->helpgc].busy, 1))
+		runtime_throw("gchelperstart: already busy");
+	if(runtime_g() != m->g0)
+		runtime_throw("gchelper not running on g0 stack");
+}
+
+static void
+runfinq(void* dummy __attribute__ ((unused)))
+{
+	Finalizer *f;
+	FinBlock *fb, *next;
+	uint32 i;
+	Eface ef;
+	Iface iface;
+
+	// This function blocks for long periods of time, and because it is written in C
+	// we have no liveness information. Zero everything so that uninitialized pointers
+	// do not cause memory leaks.
+	f = nil;
+	fb = nil;
+	next = nil;
+	i = 0;
+	ef.__type_descriptor = nil;
+	ef.__object = nil;
+	
+	// force flush to memory
+	USED(&f);
+	USED(&fb);
+	USED(&next);
+	USED(&i);
+	USED(&ef);
+
+	for(;;) {
+		runtime_lock(&finlock);
+		fb = finq;
+		finq = nil;
+		if(fb == nil) {
+			runtime_fingwait = true;
+			runtime_g()->isbackground = true;
+			runtime_parkunlock(&finlock, "finalizer wait");
+			runtime_g()->isbackground = false;
+			continue;
+		}
+		runtime_unlock(&finlock);
+		if(raceenabled)
+			runtime_racefingo();
+		for(; fb; fb=next) {
+			next = fb->next;
+			for(i=0; i<(uint32)fb->cnt; i++) {
+				const Type *fint;
+				void *param;
+
+				f = &fb->fin[i];
+				fint = ((const Type**)f->ft->__in.array)[0];
+				if(fint->__code == KindPtr) {
+					// direct use of pointer
+					param = &f->arg;
+				} else if(((const InterfaceType*)fint)->__methods.__count == 0) {
+					// convert to empty interface
+					ef.__type_descriptor = (const Type*)f->ot;
+					ef.__object = f->arg;
+					param = &ef;
+				} else {
+					// convert to interface with methods
+					iface.__methods = __go_convert_interface_2((const Type*)fint,
+										   (const Type*)f->ot,
+										   1);
+					iface.__object = f->arg;
+					if(iface.__methods == nil)
+						runtime_throw("invalid type conversion in runfinq");
+					param = &iface;
+				}
+				reflect_call(f->ft, f->fn, 0, 0, &param, nil);
+				f->fn = nil;
+				f->arg = nil;
+				f->ot = nil;
+			}
+			fb->cnt = 0;
+			runtime_lock(&finlock);
+			fb->next = finc;
+			finc = fb;
+			runtime_unlock(&finlock);
+		}
+
+		// Zero everything that's dead, to avoid memory leaks.
+		// See comment at top of function.
+		f = nil;
+		fb = nil;
+		next = nil;
+		i = 0;
+		ef.__type_descriptor = nil;
+		ef.__object = nil;
+		runtime_gc(1);	// trigger another gc to clean up the finalized objects, if possible
+	}
+}
+
+void
+runtime_createfing(void)
+{
+	if(fing != nil)
+		return;
+	// Here we use gclock instead of finlock,
+	// because newproc1 can allocate, which can cause on-demand span sweep,
+	// which can queue finalizers, which would deadlock.
+	runtime_lock(&gclock);
+	if(fing == nil)
+		fing = __go_go(runfinq, nil);
+	runtime_unlock(&gclock);
+}
+
+G*
+runtime_wakefing(void)
+{
+	G *res;
+
+	res = nil;
+	runtime_lock(&finlock);
+	if(runtime_fingwait && runtime_fingwake) {
+		runtime_fingwait = false;
+		runtime_fingwake = false;
+		res = fing;
+	}
+	runtime_unlock(&finlock);
+	return res;
+}
+
+void
+runtime_marknogc(void *v)
+{
+	uintptr *b, off, shift;
+
+	off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;  // word offset
+	b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+	shift = off % wordsPerBitmapWord;
+	*b = (*b & ~(bitAllocated<<shift)) | bitBlockBoundary<<shift;
+}
+
+void
+runtime_markscan(void *v)
+{
+	uintptr *b, off, shift;
+
+	off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;  // word offset
+	b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+	shift = off % wordsPerBitmapWord;
+	*b |= bitScan<<shift;
+}
+
+// mark the block at v as freed.
+void
+runtime_markfreed(void *v)
+{
+	uintptr *b, off, shift;
+
+	if(0)
+		runtime_printf("markfreed %p\n", v);
+
+	if((byte*)v > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start)
+		runtime_throw("markfreed: bad pointer");
+
+	off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;  // word offset
+	b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+	shift = off % wordsPerBitmapWord;
+	*b = (*b & ~(bitMask<<shift)) | (bitAllocated<<shift);
+}
+
+// check that the block at v of size n is marked freed.
+void
+runtime_checkfreed(void *v, uintptr n)
+{
+	uintptr *b, bits, off, shift;
+
+	if(!runtime_checking)
+		return;
+
+	if((byte*)v+n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start)
+		return;	// not allocated, so okay
+
+	off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;  // word offset
+	b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+	shift = off % wordsPerBitmapWord;
+
+	bits = *b>>shift;
+	if((bits & bitAllocated) != 0) {
+		runtime_printf("checkfreed %p+%p: off=%p have=%p\n",
+			v, n, off, bits & bitMask);
+		runtime_throw("checkfreed: not freed");
+	}
+}
+
+// mark the span of memory at v as having n blocks of the given size.
+// if leftover is true, there is left over space at the end of the span.
+void
+runtime_markspan(void *v, uintptr size, uintptr n, bool leftover)
+{
+	uintptr *b, *b0, off, shift, i, x;
+	byte *p;
+
+	if((byte*)v+size*n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start)
+		runtime_throw("markspan: bad pointer");
+
+	if(runtime_checking) {
+		// bits should be all zero at the start
+		off = (byte*)v + size - runtime_mheap.arena_start;
+		b = (uintptr*)(runtime_mheap.arena_start - off/wordsPerBitmapWord);
+		for(i = 0; i < size/PtrSize/wordsPerBitmapWord; i++) {
+			if(b[i] != 0)
+				runtime_throw("markspan: span bits not zero");
+		}
+	}
+
+	p = v;
+	if(leftover)	// mark a boundary just past end of last block too
+		n++;
+
+	b0 = nil;
+	x = 0;
+	for(; n-- > 0; p += size) {
+		// Okay to use non-atomic ops here, because we control
+		// the entire span, and each bitmap word has bits for only
+		// one span, so no other goroutines are changing these
+		// bitmap words.
+		off = (uintptr*)p - (uintptr*)runtime_mheap.arena_start;  // word offset
+		b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		if(b0 != b) {
+			if(b0 != nil)
+				*b0 = x;
+			b0 = b;
+			x = 0;
+		}
+		x |= bitAllocated<<shift;
+	}
+	*b0 = x;
+}
+
+// unmark the span of memory at v of length n bytes.
+void
+runtime_unmarkspan(void *v, uintptr n)
+{
+	uintptr *p, *b, off;
+
+	if((byte*)v+n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start)
+		runtime_throw("markspan: bad pointer");
+
+	p = v;
+	off = p - (uintptr*)runtime_mheap.arena_start;  // word offset
+	if(off % wordsPerBitmapWord != 0)
+		runtime_throw("markspan: unaligned pointer");
+	b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+	n /= PtrSize;
+	if(n%wordsPerBitmapWord != 0)
+		runtime_throw("unmarkspan: unaligned length");
+	// Okay to use non-atomic ops here, because we control
+	// the entire span, and each bitmap word has bits for only
+	// one span, so no other goroutines are changing these
+	// bitmap words.
+	n /= wordsPerBitmapWord;
+	while(n-- > 0)
+		*b-- = 0;
+}
+
+void
+runtime_MHeap_MapBits(MHeap *h)
+{
+	size_t page_size;
+
+	// Caller has added extra mappings to the arena.
+	// Add extra mappings of bitmap words as needed.
+	// We allocate extra bitmap pieces in chunks of bitmapChunk.
+	enum {
+		bitmapChunk = 8192
+	};
+	uintptr n;
+
+	n = (h->arena_used - h->arena_start) / wordsPerBitmapWord;
+	n = ROUND(n, bitmapChunk);
+	n = ROUND(n, PageSize);
+	page_size = getpagesize();
+	n = ROUND(n, page_size);
+	if(h->bitmap_mapped >= n)
+		return;
+
+	runtime_SysMap(h->arena_start - n, n - h->bitmap_mapped, h->arena_reserved, &mstats.gc_sys);
+	h->bitmap_mapped = n;
+}
diff --git a/third_party/gofrontend/libgo/runtime/mgc0.h b/third_party/gofrontend/libgo/runtime/mgc0.h
new file mode 100644
index 0000000..16000d1
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/mgc0.h
@@ -0,0 +1,87 @@
+// 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.
+
+// Garbage collector (GC)
+
+// GC instruction opcodes.
+//
+// The opcode of an instruction is followed by zero or more
+// arguments to the instruction.
+//
+// Meaning of arguments:
+//   off      Offset (in bytes) from the start of the current object
+//   objgc    Pointer to GC info of an object
+//   objgcrel Offset to GC info of an object
+//   len      Length of an array
+//   elemsize Size (in bytes) of an element
+//   size     Size (in bytes)
+//
+// NOTE: There is a copy of these in ../reflect/type.go.
+// They must be kept in sync.
+enum {
+	GC_END,         // End of object, loop or subroutine. Args: none
+	GC_PTR,         // A typed pointer. Args: (off, objgc)
+	GC_APTR,        // Pointer to an arbitrary object. Args: (off)
+	GC_ARRAY_START, // Start an array with a fixed length. Args: (off, len, elemsize)
+	GC_ARRAY_NEXT,  // The next element of an array. Args: none
+	GC_CALL,        // Call a subroutine. Args: (off, objgcrel)
+	GC_CHAN_PTR,    // Go channel. Args: (off, ChanType*)
+	GC_STRING,      // Go string. Args: (off)
+	GC_EFACE,       // interface{}. Args: (off)
+	GC_IFACE,       // interface{...}. Args: (off)
+	GC_SLICE,       // Go slice. Args: (off, objgc)
+	GC_REGION,      // A region/part of the current object. Args: (off, size, objgc)
+
+	GC_NUM_INSTR,   // Number of instruction opcodes
+};
+
+enum {
+	// Size of GC's fixed stack.
+	//
+	// The current GC implementation permits:
+	//  - at most 1 stack allocation because of GC_CALL
+	//  - at most GC_STACK_CAPACITY allocations because of GC_ARRAY_START
+	GC_STACK_CAPACITY = 8,	
+};
+
+enum {
+	ScanStackByFrames = 1,
+	IgnorePreciseGC = 0,
+
+	// Four bits per word (see #defines below).
+	wordsPerBitmapWord = sizeof(void*)*8/4,
+	bitShift = sizeof(void*)*8/4,
+};
+
+// Bits in per-word bitmap.
+// #defines because enum might not be able to hold the values.
+//
+// Each word in the bitmap describes wordsPerBitmapWord words
+// of heap memory.  There are 4 bitmap bits dedicated to each heap word,
+// so on a 64-bit system there is one bitmap word per 16 heap words.
+// The bits in the word are packed together by type first, then by
+// heap location, so each 64-bit bitmap word consists of, from top to bottom,
+// the 16 bitMarked bits for the corresponding heap words,
+// then the 16 bitScan/bitBlockBoundary bits, then the 16 bitAllocated bits.
+// This layout makes it easier to iterate over the bits of a given type.
+//
+// The bitmap starts at mheap.arena_start and extends *backward* from
+// there.  On a 64-bit system the off'th word in the arena is tracked by
+// the off/16+1'th word before mheap.arena_start.  (On a 32-bit system,
+// the only difference is that the divisor is 8.)
+//
+// To pull out the bits corresponding to a given pointer p, we use:
+//
+//	off = p - (uintptr*)mheap.arena_start;  // word offset
+//	b = (uintptr*)mheap.arena_start - off/wordsPerBitmapWord - 1;
+//	shift = off % wordsPerBitmapWord
+//	bits = *b >> shift;
+//	/* then test bits & bitAllocated, bits & bitMarked, etc. */
+//
+#define bitAllocated		((uintptr)1<<(bitShift*0))	/* block start; eligible for garbage collection */
+#define bitScan			((uintptr)1<<(bitShift*1))	/* when bitAllocated is set */
+#define bitMarked		((uintptr)1<<(bitShift*2))	/* when bitAllocated is set */
+#define bitBlockBoundary	((uintptr)1<<(bitShift*1))	/* when bitAllocated is NOT set - mark for FlagNoGC objects */
+
+#define bitMask (bitAllocated | bitScan | bitMarked)
diff --git a/third_party/gofrontend/libgo/runtime/mheap.c b/third_party/gofrontend/libgo/runtime/mheap.c
new file mode 100644
index 0000000..a4624fd
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/mheap.c
@@ -0,0 +1,950 @@
+// 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.
+
+// Page heap.
+//
+// See malloc.h for overview.
+//
+// When a MSpan is in the heap free list, state == MSpanFree
+// and heapmap(s->start) == span, heapmap(s->start+s->npages-1) == span.
+//
+// When a MSpan is allocated, state == MSpanInUse
+// and heapmap(i) == span for all s->start <= i < s->start+s->npages.
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+static MSpan *MHeap_AllocLocked(MHeap*, uintptr, int32);
+static bool MHeap_Grow(MHeap*, uintptr);
+static void MHeap_FreeLocked(MHeap*, MSpan*);
+static MSpan *MHeap_AllocLarge(MHeap*, uintptr);
+static MSpan *BestFit(MSpan*, uintptr, MSpan*);
+
+static void
+RecordSpan(void *vh, byte *p)
+{
+	MHeap *h;
+	MSpan *s;
+	MSpan **all;
+	uint32 cap;
+
+	h = vh;
+	s = (MSpan*)p;
+	if(h->nspan >= h->nspancap) {
+		cap = 64*1024/sizeof(all[0]);
+		if(cap < h->nspancap*3/2)
+			cap = h->nspancap*3/2;
+		all = (MSpan**)runtime_SysAlloc(cap*sizeof(all[0]), &mstats.other_sys);
+		if(all == nil)
+			runtime_throw("runtime: cannot allocate memory");
+		if(h->allspans) {
+			runtime_memmove(all, h->allspans, h->nspancap*sizeof(all[0]));
+			// Don't free the old array if it's referenced by sweep.
+			// See the comment in mgc0.c.
+			if(h->allspans != runtime_mheap.sweepspans)
+				runtime_SysFree(h->allspans, h->nspancap*sizeof(all[0]), &mstats.other_sys);
+		}
+		h->allspans = all;
+		h->nspancap = cap;
+	}
+	h->allspans[h->nspan++] = s;
+}
+
+// Initialize the heap; fetch memory using alloc.
+void
+runtime_MHeap_Init(MHeap *h)
+{
+	uint32 i;
+
+	runtime_FixAlloc_Init(&h->spanalloc, sizeof(MSpan), RecordSpan, h, &mstats.mspan_sys);
+	runtime_FixAlloc_Init(&h->cachealloc, sizeof(MCache), nil, nil, &mstats.mcache_sys);
+	runtime_FixAlloc_Init(&h->specialfinalizeralloc, sizeof(SpecialFinalizer), nil, nil, &mstats.other_sys);
+	runtime_FixAlloc_Init(&h->specialprofilealloc, sizeof(SpecialProfile), nil, nil, &mstats.other_sys);
+	// h->mapcache needs no init
+	for(i=0; i<nelem(h->free); i++) {
+		runtime_MSpanList_Init(&h->free[i]);
+		runtime_MSpanList_Init(&h->busy[i]);
+	}
+	runtime_MSpanList_Init(&h->freelarge);
+	runtime_MSpanList_Init(&h->busylarge);
+	for(i=0; i<nelem(h->central); i++)
+		runtime_MCentral_Init(&h->central[i].mcentral, i);
+}
+
+void
+runtime_MHeap_MapSpans(MHeap *h)
+{
+	uintptr pagesize;
+	uintptr n;
+
+	// Map spans array, PageSize at a time.
+	n = (uintptr)h->arena_used;
+	n -= (uintptr)h->arena_start;
+	n = n / PageSize * sizeof(h->spans[0]);
+	n = ROUND(n, PageSize);
+	pagesize = getpagesize();
+	n = ROUND(n, pagesize);
+	if(h->spans_mapped >= n)
+		return;
+	runtime_SysMap((byte*)h->spans + h->spans_mapped, n - h->spans_mapped, h->arena_reserved, &mstats.other_sys);
+	h->spans_mapped = n;
+}
+
+// Sweeps spans in list until reclaims at least npages into heap.
+// Returns the actual number of pages reclaimed.
+static uintptr
+MHeap_ReclaimList(MHeap *h, MSpan *list, uintptr npages)
+{
+	MSpan *s;
+	uintptr n;
+	uint32 sg;
+
+	n = 0;
+	sg = runtime_mheap.sweepgen;
+retry:
+	for(s = list->next; s != list; s = s->next) {
+		if(s->sweepgen == sg-2 && runtime_cas(&s->sweepgen, sg-2, sg-1)) {
+			runtime_MSpanList_Remove(s);
+			// swept spans are at the end of the list
+			runtime_MSpanList_InsertBack(list, s);
+			runtime_unlock(&h->lock);
+			n += runtime_MSpan_Sweep(s);
+			runtime_lock(&h->lock);
+			if(n >= npages)
+				return n;
+			// the span could have been moved elsewhere
+			goto retry;
+		}
+		if(s->sweepgen == sg-1) {
+			// the span is being sweept by background sweeper, skip
+			continue;
+		}
+		// already swept empty span,
+		// all subsequent ones must also be either swept or in process of sweeping
+		break;
+	}
+	return n;
+}
+
+// Sweeps and reclaims at least npage pages into heap.
+// Called before allocating npage pages.
+static void
+MHeap_Reclaim(MHeap *h, uintptr npage)
+{
+	uintptr reclaimed, n;
+
+	// First try to sweep busy spans with large objects of size >= npage,
+	// this has good chances of reclaiming the necessary space.
+	for(n=npage; n < nelem(h->busy); n++) {
+		if(MHeap_ReclaimList(h, &h->busy[n], npage))
+			return;  // Bingo!
+	}
+
+	// Then -- even larger objects.
+	if(MHeap_ReclaimList(h, &h->busylarge, npage))
+		return;  // Bingo!
+
+	// Now try smaller objects.
+	// One such object is not enough, so we need to reclaim several of them.
+	reclaimed = 0;
+	for(n=0; n < npage && n < nelem(h->busy); n++) {
+		reclaimed += MHeap_ReclaimList(h, &h->busy[n], npage-reclaimed);
+		if(reclaimed >= npage)
+			return;
+	}
+
+	// Now sweep everything that is not yet swept.
+	runtime_unlock(&h->lock);
+	for(;;) {
+		n = runtime_sweepone();
+		if(n == (uintptr)-1)  // all spans are swept
+			break;
+		reclaimed += n;
+		if(reclaimed >= npage)
+			break;
+	}
+	runtime_lock(&h->lock);
+}
+
+// Allocate a new span of npage pages from the heap
+// and record its size class in the HeapMap and HeapMapCache.
+MSpan*
+runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large, bool needzero)
+{
+	MSpan *s;
+
+	runtime_lock(&h->lock);
+	mstats.heap_alloc += runtime_m()->mcache->local_cachealloc;
+	runtime_m()->mcache->local_cachealloc = 0;
+	s = MHeap_AllocLocked(h, npage, sizeclass);
+	if(s != nil) {
+		mstats.heap_inuse += npage<<PageShift;
+		if(large) {
+			mstats.heap_objects++;
+			mstats.heap_alloc += npage<<PageShift;
+			// Swept spans are at the end of lists.
+			if(s->npages < nelem(h->free))
+				runtime_MSpanList_InsertBack(&h->busy[s->npages], s);
+			else
+				runtime_MSpanList_InsertBack(&h->busylarge, s);
+		}
+	}
+	runtime_unlock(&h->lock);
+	if(s != nil) {
+		if(needzero && s->needzero)
+			runtime_memclr((byte*)(s->start<<PageShift), s->npages<<PageShift);
+		s->needzero = 0;
+	}
+	return s;
+}
+
+static MSpan*
+MHeap_AllocLocked(MHeap *h, uintptr npage, int32 sizeclass)
+{
+	uintptr n;
+	MSpan *s, *t;
+	PageID p;
+
+	// To prevent excessive heap growth, before allocating n pages
+	// we need to sweep and reclaim at least n pages.
+	if(!h->sweepdone)
+		MHeap_Reclaim(h, npage);
+
+	// Try in fixed-size lists up to max.
+	for(n=npage; n < nelem(h->free); n++) {
+		if(!runtime_MSpanList_IsEmpty(&h->free[n])) {
+			s = h->free[n].next;
+			goto HaveSpan;
+		}
+	}
+
+	// Best fit in list of large spans.
+	if((s = MHeap_AllocLarge(h, npage)) == nil) {
+		if(!MHeap_Grow(h, npage))
+			return nil;
+		if((s = MHeap_AllocLarge(h, npage)) == nil)
+			return nil;
+	}
+
+HaveSpan:
+	// Mark span in use.
+	if(s->state != MSpanFree)
+		runtime_throw("MHeap_AllocLocked - MSpan not free");
+	if(s->npages < npage)
+		runtime_throw("MHeap_AllocLocked - bad npages");
+	runtime_MSpanList_Remove(s);
+	runtime_atomicstore(&s->sweepgen, h->sweepgen);
+	s->state = MSpanInUse;
+	mstats.heap_idle -= s->npages<<PageShift;
+	mstats.heap_released -= s->npreleased<<PageShift;
+	if(s->npreleased > 0)
+		runtime_SysUsed((void*)(s->start<<PageShift), s->npages<<PageShift);
+	s->npreleased = 0;
+
+	if(s->npages > npage) {
+		// Trim extra and put it back in the heap.
+		t = runtime_FixAlloc_Alloc(&h->spanalloc);
+		runtime_MSpan_Init(t, s->start + npage, s->npages - npage);
+		s->npages = npage;
+		p = t->start;
+		p -= ((uintptr)h->arena_start>>PageShift);
+		if(p > 0)
+			h->spans[p-1] = s;
+		h->spans[p] = t;
+		h->spans[p+t->npages-1] = t;
+		t->needzero = s->needzero;
+		runtime_atomicstore(&t->sweepgen, h->sweepgen);
+		t->state = MSpanInUse;
+		MHeap_FreeLocked(h, t);
+		t->unusedsince = s->unusedsince; // preserve age
+	}
+	s->unusedsince = 0;
+
+	// Record span info, because gc needs to be
+	// able to map interior pointer to containing span.
+	s->sizeclass = sizeclass;
+	s->elemsize = (sizeclass==0 ? s->npages<<PageShift : (uintptr)runtime_class_to_size[sizeclass]);
+	s->types.compression = MTypes_Empty;
+	p = s->start;
+	p -= ((uintptr)h->arena_start>>PageShift);
+	for(n=0; n<npage; n++)
+		h->spans[p+n] = s;
+	return s;
+}
+
+// Allocate a span of exactly npage pages from the list of large spans.
+static MSpan*
+MHeap_AllocLarge(MHeap *h, uintptr npage)
+{
+	return BestFit(&h->freelarge, npage, nil);
+}
+
+// Search list for smallest span with >= npage pages.
+// If there are multiple smallest spans, take the one
+// with the earliest starting address.
+static MSpan*
+BestFit(MSpan *list, uintptr npage, MSpan *best)
+{
+	MSpan *s;
+
+	for(s=list->next; s != list; s=s->next) {
+		if(s->npages < npage)
+			continue;
+		if(best == nil
+		|| s->npages < best->npages
+		|| (s->npages == best->npages && s->start < best->start))
+			best = s;
+	}
+	return best;
+}
+
+// Try to add at least npage pages of memory to the heap,
+// returning whether it worked.
+static bool
+MHeap_Grow(MHeap *h, uintptr npage)
+{
+	uintptr ask;
+	void *v;
+	MSpan *s;
+	PageID p;
+
+	// Ask for a big chunk, to reduce the number of mappings
+	// the operating system needs to track; also amortizes
+	// the overhead of an operating system mapping.
+	// Allocate a multiple of 64kB (16 pages).
+	npage = (npage+15)&~15;
+	ask = npage<<PageShift;
+	if(ask < HeapAllocChunk)
+		ask = HeapAllocChunk;
+
+	v = runtime_MHeap_SysAlloc(h, ask);
+	if(v == nil) {
+		if(ask > (npage<<PageShift)) {
+			ask = npage<<PageShift;
+			v = runtime_MHeap_SysAlloc(h, ask);
+		}
+		if(v == nil) {
+			runtime_printf("runtime: out of memory: cannot allocate %D-byte block (%D in use)\n", (uint64)ask, mstats.heap_sys);
+			return false;
+		}
+	}
+
+	// Create a fake "in use" span and free it, so that the
+	// right coalescing happens.
+	s = runtime_FixAlloc_Alloc(&h->spanalloc);
+	runtime_MSpan_Init(s, (uintptr)v>>PageShift, ask>>PageShift);
+	p = s->start;
+	p -= ((uintptr)h->arena_start>>PageShift);
+	h->spans[p] = s;
+	h->spans[p + s->npages - 1] = s;
+	runtime_atomicstore(&s->sweepgen, h->sweepgen);
+	s->state = MSpanInUse;
+	MHeap_FreeLocked(h, s);
+	return true;
+}
+
+// Look up the span at the given address.
+// Address is guaranteed to be in map
+// and is guaranteed to be start or end of span.
+MSpan*
+runtime_MHeap_Lookup(MHeap *h, void *v)
+{
+	uintptr p;
+	
+	p = (uintptr)v;
+	p -= (uintptr)h->arena_start;
+	return h->spans[p >> PageShift];
+}
+
+// Look up the span at the given address.
+// Address is *not* guaranteed to be in map
+// and may be anywhere in the span.
+// Map entries for the middle of a span are only
+// valid for allocated spans.  Free spans may have
+// other garbage in their middles, so we have to
+// check for that.
+MSpan*
+runtime_MHeap_LookupMaybe(MHeap *h, void *v)
+{
+	MSpan *s;
+	PageID p, q;
+
+	if((byte*)v < h->arena_start || (byte*)v >= h->arena_used)
+		return nil;
+	p = (uintptr)v>>PageShift;
+	q = p;
+	q -= (uintptr)h->arena_start >> PageShift;
+	s = h->spans[q];
+	if(s == nil || p < s->start || (byte*)v >= s->limit || s->state != MSpanInUse)
+		return nil;
+	return s;
+}
+
+// Free the span back into the heap.
+void
+runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct)
+{
+	runtime_lock(&h->lock);
+	mstats.heap_alloc += runtime_m()->mcache->local_cachealloc;
+	runtime_m()->mcache->local_cachealloc = 0;
+	mstats.heap_inuse -= s->npages<<PageShift;
+	if(acct) {
+		mstats.heap_alloc -= s->npages<<PageShift;
+		mstats.heap_objects--;
+	}
+	MHeap_FreeLocked(h, s);
+	runtime_unlock(&h->lock);
+}
+
+static void
+MHeap_FreeLocked(MHeap *h, MSpan *s)
+{
+	MSpan *t;
+	PageID p;
+
+	s->types.compression = MTypes_Empty;
+
+	if(s->state != MSpanInUse || s->ref != 0 || s->sweepgen != h->sweepgen) {
+		runtime_printf("MHeap_FreeLocked - span %p ptr %p state %d ref %d sweepgen %d/%d\n",
+			s, s->start<<PageShift, s->state, s->ref, s->sweepgen, h->sweepgen);
+		runtime_throw("MHeap_FreeLocked - invalid free");
+	}
+	mstats.heap_idle += s->npages<<PageShift;
+	s->state = MSpanFree;
+	runtime_MSpanList_Remove(s);
+	// Stamp newly unused spans. The scavenger will use that
+	// info to potentially give back some pages to the OS.
+	s->unusedsince = runtime_nanotime();
+	s->npreleased = 0;
+
+	// Coalesce with earlier, later spans.
+	p = s->start;
+	p -= (uintptr)h->arena_start >> PageShift;
+	if(p > 0 && (t = h->spans[p-1]) != nil && t->state != MSpanInUse) {
+		s->start = t->start;
+		s->npages += t->npages;
+		s->npreleased = t->npreleased; // absorb released pages
+		s->needzero |= t->needzero;
+		p -= t->npages;
+		h->spans[p] = s;
+		runtime_MSpanList_Remove(t);
+		t->state = MSpanDead;
+		runtime_FixAlloc_Free(&h->spanalloc, t);
+	}
+	if((p+s->npages)*sizeof(h->spans[0]) < h->spans_mapped && (t = h->spans[p+s->npages]) != nil && t->state != MSpanInUse) {
+		s->npages += t->npages;
+		s->npreleased += t->npreleased;
+		s->needzero |= t->needzero;
+		h->spans[p + s->npages - 1] = s;
+		runtime_MSpanList_Remove(t);
+		t->state = MSpanDead;
+		runtime_FixAlloc_Free(&h->spanalloc, t);
+	}
+
+	// Insert s into appropriate list.
+	if(s->npages < nelem(h->free))
+		runtime_MSpanList_Insert(&h->free[s->npages], s);
+	else
+		runtime_MSpanList_Insert(&h->freelarge, s);
+}
+
+static void
+forcegchelper(void *vnote)
+{
+	Note *note = (Note*)vnote;
+
+	runtime_gc(1);
+	runtime_notewakeup(note);
+}
+
+static uintptr
+scavengelist(MSpan *list, uint64 now, uint64 limit)
+{
+	uintptr released, sumreleased, start, end, pagesize;
+	MSpan *s;
+
+	if(runtime_MSpanList_IsEmpty(list))
+		return 0;
+
+	sumreleased = 0;
+	for(s=list->next; s != list; s=s->next) {
+		if((now - s->unusedsince) > limit && s->npreleased != s->npages) {
+			released = (s->npages - s->npreleased) << PageShift;
+			mstats.heap_released += released;
+			sumreleased += released;
+			s->npreleased = s->npages;
+
+			start = s->start << PageShift;
+			end = start + (s->npages << PageShift);
+
+			// Round start up and end down to ensure we
+			// are acting on entire pages.
+			pagesize = getpagesize();
+			start = ROUND(start, pagesize);
+			end &= ~(pagesize - 1);
+			if(end > start)
+				runtime_SysUnused((void*)start, end - start);
+		}
+	}
+	return sumreleased;
+}
+
+static void
+scavenge(int32 k, uint64 now, uint64 limit)
+{
+	uint32 i;
+	uintptr sumreleased;
+	MHeap *h;
+	
+	h = &runtime_mheap;
+	sumreleased = 0;
+	for(i=0; i < nelem(h->free); i++)
+		sumreleased += scavengelist(&h->free[i], now, limit);
+	sumreleased += scavengelist(&h->freelarge, now, limit);
+
+	if(runtime_debug.gctrace > 0) {
+		if(sumreleased > 0)
+			runtime_printf("scvg%d: %D MB released\n", k, (uint64)sumreleased>>20);
+		runtime_printf("scvg%d: inuse: %D, idle: %D, sys: %D, released: %D, consumed: %D (MB)\n",
+			k, mstats.heap_inuse>>20, mstats.heap_idle>>20, mstats.heap_sys>>20,
+			mstats.heap_released>>20, (mstats.heap_sys - mstats.heap_released)>>20);
+	}
+}
+
+// Release (part of) unused memory to OS.
+// Goroutine created at startup.
+// Loop forever.
+void
+runtime_MHeap_Scavenger(void* dummy)
+{
+	G *g;
+	MHeap *h;
+	uint64 tick, now, forcegc, limit;
+	int64 unixnow;
+	uint32 k;
+	Note note, *notep;
+
+	USED(dummy);
+
+	g = runtime_g();
+	g->issystem = true;
+	g->isbackground = true;
+
+	// If we go two minutes without a garbage collection, force one to run.
+	forcegc = 2*60*1e9;
+	// If a span goes unused for 5 minutes after a garbage collection,
+	// we hand it back to the operating system.
+	limit = 5*60*1e9;
+	// Make wake-up period small enough for the sampling to be correct.
+	if(forcegc < limit)
+		tick = forcegc/2;
+	else
+		tick = limit/2;
+
+	h = &runtime_mheap;
+	for(k=0;; k++) {
+		runtime_noteclear(&note);
+		runtime_notetsleepg(&note, tick);
+
+		runtime_lock(&h->lock);
+		unixnow = runtime_unixnanotime();
+		if(unixnow - mstats.last_gc > forcegc) {
+			runtime_unlock(&h->lock);
+			// The scavenger can not block other goroutines,
+			// otherwise deadlock detector can fire spuriously.
+			// GC blocks other goroutines via the runtime_worldsema.
+			runtime_noteclear(&note);
+			notep = &note;
+			__go_go(forcegchelper, (void*)notep);
+			runtime_notetsleepg(&note, -1);
+			if(runtime_debug.gctrace > 0)
+				runtime_printf("scvg%d: GC forced\n", k);
+			runtime_lock(&h->lock);
+		}
+		now = runtime_nanotime();
+		scavenge(k, now, limit);
+		runtime_unlock(&h->lock);
+	}
+}
+
+void runtime_debug_freeOSMemory(void) __asm__("runtime_debug.freeOSMemory");
+
+void
+runtime_debug_freeOSMemory(void)
+{
+	runtime_gc(2);  // force GC and do eager sweep
+	runtime_lock(&runtime_mheap.lock);
+	scavenge(-1, ~(uintptr)0, 0);
+	runtime_unlock(&runtime_mheap.lock);
+}
+
+// Initialize a new span with the given start and npages.
+void
+runtime_MSpan_Init(MSpan *span, PageID start, uintptr npages)
+{
+	span->next = nil;
+	span->prev = nil;
+	span->start = start;
+	span->npages = npages;
+	span->freelist = nil;
+	span->ref = 0;
+	span->sizeclass = 0;
+	span->incache = false;
+	span->elemsize = 0;
+	span->state = MSpanDead;
+	span->unusedsince = 0;
+	span->npreleased = 0;
+	span->types.compression = MTypes_Empty;
+	span->specialLock.key = 0;
+	span->specials = nil;
+	span->needzero = 0;
+	span->freebuf = nil;
+}
+
+// Initialize an empty doubly-linked list.
+void
+runtime_MSpanList_Init(MSpan *list)
+{
+	list->state = MSpanListHead;
+	list->next = list;
+	list->prev = list;
+}
+
+void
+runtime_MSpanList_Remove(MSpan *span)
+{
+	if(span->prev == nil && span->next == nil)
+		return;
+	span->prev->next = span->next;
+	span->next->prev = span->prev;
+	span->prev = nil;
+	span->next = nil;
+}
+
+bool
+runtime_MSpanList_IsEmpty(MSpan *list)
+{
+	return list->next == list;
+}
+
+void
+runtime_MSpanList_Insert(MSpan *list, MSpan *span)
+{
+	if(span->next != nil || span->prev != nil) {
+		runtime_printf("failed MSpanList_Insert %p %p %p\n", span, span->next, span->prev);
+		runtime_throw("MSpanList_Insert");
+	}
+	span->next = list->next;
+	span->prev = list;
+	span->next->prev = span;
+	span->prev->next = span;
+}
+
+void
+runtime_MSpanList_InsertBack(MSpan *list, MSpan *span)
+{
+	if(span->next != nil || span->prev != nil) {
+		runtime_printf("failed MSpanList_Insert %p %p %p\n", span, span->next, span->prev);
+		runtime_throw("MSpanList_Insert");
+	}
+	span->next = list;
+	span->prev = list->prev;
+	span->next->prev = span;
+	span->prev->next = span;
+}
+
+// Adds the special record s to the list of special records for
+// the object p.  All fields of s should be filled in except for
+// offset & next, which this routine will fill in.
+// Returns true if the special was successfully added, false otherwise.
+// (The add will fail only if a record with the same p and s->kind
+//  already exists.)
+static bool
+addspecial(void *p, Special *s)
+{
+	MSpan *span;
+	Special **t, *x;
+	uintptr offset;
+	byte kind;
+
+	span = runtime_MHeap_LookupMaybe(&runtime_mheap, p);
+	if(span == nil)
+		runtime_throw("addspecial on invalid pointer");
+
+	// Ensure that the span is swept.
+	// GC accesses specials list w/o locks. And it's just much safer.
+	runtime_m()->locks++;
+	runtime_MSpan_EnsureSwept(span);
+
+	offset = (uintptr)p - (span->start << PageShift);
+	kind = s->kind;
+
+	runtime_lock(&span->specialLock);
+
+	// Find splice point, check for existing record.
+	t = &span->specials;
+	while((x = *t) != nil) {
+		if(offset == x->offset && kind == x->kind) {
+			runtime_unlock(&span->specialLock);
+			runtime_m()->locks--;
+			return false; // already exists
+		}
+		if(offset < x->offset || (offset == x->offset && kind < x->kind))
+			break;
+		t = &x->next;
+	}
+	// Splice in record, fill in offset.
+	s->offset = offset;
+	s->next = x;
+	*t = s;
+	runtime_unlock(&span->specialLock);
+	runtime_m()->locks--;
+	return true;
+}
+
+// Removes the Special record of the given kind for the object p.
+// Returns the record if the record existed, nil otherwise.
+// The caller must FixAlloc_Free the result.
+static Special*
+removespecial(void *p, byte kind)
+{
+	MSpan *span;
+	Special *s, **t;
+	uintptr offset;
+
+	span = runtime_MHeap_LookupMaybe(&runtime_mheap, p);
+	if(span == nil)
+		runtime_throw("removespecial on invalid pointer");
+
+	// Ensure that the span is swept.
+	// GC accesses specials list w/o locks. And it's just much safer.
+	runtime_m()->locks++;
+	runtime_MSpan_EnsureSwept(span);
+
+	offset = (uintptr)p - (span->start << PageShift);
+
+	runtime_lock(&span->specialLock);
+	t = &span->specials;
+	while((s = *t) != nil) {
+		// This function is used for finalizers only, so we don't check for
+		// "interior" specials (p must be exactly equal to s->offset).
+		if(offset == s->offset && kind == s->kind) {
+			*t = s->next;
+			runtime_unlock(&span->specialLock);
+			runtime_m()->locks--;
+			return s;
+		}
+		t = &s->next;
+	}
+	runtime_unlock(&span->specialLock);
+	runtime_m()->locks--;
+	return nil;
+}
+
+// Adds a finalizer to the object p.  Returns true if it succeeded.
+bool
+runtime_addfinalizer(void *p, FuncVal *f, const FuncType *ft, const PtrType *ot)
+{
+	SpecialFinalizer *s;
+
+	runtime_lock(&runtime_mheap.speciallock);
+	s = runtime_FixAlloc_Alloc(&runtime_mheap.specialfinalizeralloc);
+	runtime_unlock(&runtime_mheap.speciallock);
+	s->special.kind = KindSpecialFinalizer;
+	s->fn = f;
+	s->ft = ft;
+	s->ot = ot;
+	if(addspecial(p, &s->special))
+		return true;
+
+	// There was an old finalizer
+	runtime_lock(&runtime_mheap.speciallock);
+	runtime_FixAlloc_Free(&runtime_mheap.specialfinalizeralloc, s);
+	runtime_unlock(&runtime_mheap.speciallock);
+	return false;
+}
+
+// Removes the finalizer (if any) from the object p.
+void
+runtime_removefinalizer(void *p)
+{
+	SpecialFinalizer *s;
+
+	s = (SpecialFinalizer*)removespecial(p, KindSpecialFinalizer);
+	if(s == nil)
+		return; // there wasn't a finalizer to remove
+	runtime_lock(&runtime_mheap.speciallock);
+	runtime_FixAlloc_Free(&runtime_mheap.specialfinalizeralloc, s);
+	runtime_unlock(&runtime_mheap.speciallock);
+}
+
+// Set the heap profile bucket associated with addr to b.
+void
+runtime_setprofilebucket(void *p, Bucket *b)
+{
+	SpecialProfile *s;
+
+	runtime_lock(&runtime_mheap.speciallock);
+	s = runtime_FixAlloc_Alloc(&runtime_mheap.specialprofilealloc);
+	runtime_unlock(&runtime_mheap.speciallock);
+	s->special.kind = KindSpecialProfile;
+	s->b = b;
+	if(!addspecial(p, &s->special))
+		runtime_throw("setprofilebucket: profile already set");
+}
+
+// Do whatever cleanup needs to be done to deallocate s.  It has
+// already been unlinked from the MSpan specials list.
+// Returns true if we should keep working on deallocating p.
+bool
+runtime_freespecial(Special *s, void *p, uintptr size, bool freed)
+{
+	SpecialFinalizer *sf;
+	SpecialProfile *sp;
+
+	switch(s->kind) {
+	case KindSpecialFinalizer:
+		sf = (SpecialFinalizer*)s;
+		runtime_queuefinalizer(p, sf->fn, sf->ft, sf->ot);
+		runtime_lock(&runtime_mheap.speciallock);
+		runtime_FixAlloc_Free(&runtime_mheap.specialfinalizeralloc, sf);
+		runtime_unlock(&runtime_mheap.speciallock);
+		return false; // don't free p until finalizer is done
+	case KindSpecialProfile:
+		sp = (SpecialProfile*)s;
+		runtime_MProf_Free(sp->b, size, freed);
+		runtime_lock(&runtime_mheap.speciallock);
+		runtime_FixAlloc_Free(&runtime_mheap.specialprofilealloc, sp);
+		runtime_unlock(&runtime_mheap.speciallock);
+		return true;
+	default:
+		runtime_throw("bad special kind");
+		return true;
+	}
+}
+
+// Free all special records for p.
+void
+runtime_freeallspecials(MSpan *span, void *p, uintptr size)
+{
+	Special *s, **t, *list;
+	uintptr offset;
+
+	if(span->sweepgen != runtime_mheap.sweepgen)
+		runtime_throw("runtime: freeallspecials: unswept span");
+	// first, collect all specials into the list; then, free them
+	// this is required to not cause deadlock between span->specialLock and proflock
+	list = nil;
+	offset = (uintptr)p - (span->start << PageShift);
+	runtime_lock(&span->specialLock);
+	t = &span->specials;
+	while((s = *t) != nil) {
+		if(offset + size <= s->offset)
+			break;
+		if(offset <= s->offset) {
+			*t = s->next;
+			s->next = list;
+			list = s;
+		} else
+			t = &s->next;
+	}
+	runtime_unlock(&span->specialLock);
+
+	while(list != nil) {
+		s = list;
+		list = s->next;
+		if(!runtime_freespecial(s, p, size, true))
+			runtime_throw("can't explicitly free an object with a finalizer");
+	}
+}
+
+// Split an allocated span into two equal parts.
+void
+runtime_MHeap_SplitSpan(MHeap *h, MSpan *s)
+{
+	MSpan *t;
+	MCentral *c;
+	uintptr i;
+	uintptr npages;
+	PageID p;
+
+	if(s->state != MSpanInUse)
+		runtime_throw("MHeap_SplitSpan on a free span");
+	if(s->sizeclass != 0 && s->ref != 1)
+		runtime_throw("MHeap_SplitSpan doesn't have an allocated object");
+	npages = s->npages;
+
+	// remove the span from whatever list it is in now
+	if(s->sizeclass > 0) {
+		// must be in h->central[x].empty
+		c = &h->central[s->sizeclass].mcentral;
+		runtime_lock(&c->lock);
+		runtime_MSpanList_Remove(s);
+		runtime_unlock(&c->lock);
+		runtime_lock(&h->lock);
+	} else {
+		// must be in h->busy/busylarge
+		runtime_lock(&h->lock);
+		runtime_MSpanList_Remove(s);
+	}
+	// heap is locked now
+
+	if(npages == 1) {
+		// convert span of 1 PageSize object to a span of 2 PageSize/2 objects.
+		s->ref = 2;
+		s->sizeclass = runtime_SizeToClass(PageSize/2);
+		s->elemsize = PageSize/2;
+	} else {
+		// convert span of n>1 pages into two spans of n/2 pages each.
+		if((s->npages & 1) != 0)
+			runtime_throw("MHeap_SplitSpan on an odd size span");
+
+		// compute position in h->spans
+		p = s->start;
+		p -= (uintptr)h->arena_start >> PageShift;
+
+		// Allocate a new span for the first half.
+		t = runtime_FixAlloc_Alloc(&h->spanalloc);
+		runtime_MSpan_Init(t, s->start, npages/2);
+		t->limit = (byte*)((t->start + npages/2) << PageShift);
+		t->state = MSpanInUse;
+		t->elemsize = npages << (PageShift - 1);
+		t->sweepgen = s->sweepgen;
+		if(t->elemsize <= MaxSmallSize) {
+			t->sizeclass = runtime_SizeToClass(t->elemsize);
+			t->ref = 1;
+		}
+
+		// the old span holds the second half.
+		s->start += npages/2;
+		s->npages = npages/2;
+		s->elemsize = npages << (PageShift - 1);
+		if(s->elemsize <= MaxSmallSize) {
+			s->sizeclass = runtime_SizeToClass(s->elemsize);
+			s->ref = 1;
+		}
+
+		// update span lookup table
+		for(i = p; i < p + npages/2; i++)
+			h->spans[i] = t;
+	}
+
+	// place the span into a new list
+	if(s->sizeclass > 0) {
+		runtime_unlock(&h->lock);
+		c = &h->central[s->sizeclass].mcentral;
+		runtime_lock(&c->lock);
+		// swept spans are at the end of the list
+		runtime_MSpanList_InsertBack(&c->empty, s);
+		runtime_unlock(&c->lock);
+	} else {
+		// Swept spans are at the end of lists.
+		if(s->npages < nelem(h->free))
+			runtime_MSpanList_InsertBack(&h->busy[s->npages], s);
+		else
+			runtime_MSpanList_InsertBack(&h->busylarge, s);
+		runtime_unlock(&h->lock);
+	}
+}
diff --git a/third_party/gofrontend/libgo/runtime/mprof.goc b/third_party/gofrontend/libgo/runtime/mprof.goc
new file mode 100644
index 0000000..d9c220b
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/mprof.goc
@@ -0,0 +1,564 @@
+// 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.
+
+// Malloc profiling.
+// Patterned after tcmalloc's algorithms; shorter code.
+
+package runtime
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+#include "defs.h"
+#include "go-type.h"
+#include "go-string.h"
+
+// NOTE(rsc): Everything here could use cas if contention became an issue.
+static Lock proflock;
+
+// All memory allocations are local and do not escape outside of the profiler.
+// The profiler is forbidden from referring to garbage-collected memory.
+
+enum { MProf, BProf };  // profile types
+
+// Per-call-stack profiling information.
+// Lookup by hashing call stack into a linked-list hash table.
+struct Bucket
+{
+	Bucket	*next;	// next in hash list
+	Bucket	*allnext;	// next in list of all mbuckets/bbuckets
+	int32	typ;
+	// Generally unions can break precise GC,
+	// this one is fine because it does not contain pointers.
+	union
+	{
+		struct  // typ == MProf
+		{
+			// The following complex 3-stage scheme of stats accumulation
+			// is required to obtain a consistent picture of mallocs and frees
+			// for some point in time.
+			// The problem is that mallocs come in real time, while frees
+			// come only after a GC during concurrent sweeping. So if we would
+			// naively count them, we would get a skew toward mallocs.
+			//
+			// Mallocs are accounted in recent stats.
+			// Explicit frees are accounted in recent stats.
+			// GC frees are accounted in prev stats.
+			// After GC prev stats are added to final stats and
+			// recent stats are moved into prev stats.
+			uintptr	allocs;
+			uintptr	frees;
+			uintptr	alloc_bytes;
+			uintptr	free_bytes;
+
+			uintptr	prev_allocs;  // since last but one till last gc
+			uintptr	prev_frees;
+			uintptr	prev_alloc_bytes;
+			uintptr	prev_free_bytes;
+
+			uintptr	recent_allocs;  // since last gc till now
+			uintptr	recent_frees;
+			uintptr	recent_alloc_bytes;
+			uintptr	recent_free_bytes;
+
+		};
+		struct  // typ == BProf
+		{
+			int64	count;
+			int64	cycles;
+		};
+	};
+	uintptr	hash;	// hash of size + stk
+	uintptr	size;
+	uintptr	nstk;
+	Location stk[1];
+};
+enum {
+	BuckHashSize = 179999,
+};
+static Bucket **buckhash;
+static Bucket *mbuckets;  // memory profile buckets
+static Bucket *bbuckets;  // blocking profile buckets
+static uintptr bucketmem;
+
+// Return the bucket for stk[0:nstk], allocating new bucket if needed.
+static Bucket*
+stkbucket(int32 typ, uintptr size, Location *stk, int32 nstk, bool alloc)
+{
+	int32 i, j;
+	uintptr h;
+	Bucket *b;
+
+	if(buckhash == nil) {
+		buckhash = runtime_SysAlloc(BuckHashSize*sizeof buckhash[0], &mstats.buckhash_sys);
+		if(buckhash == nil)
+			runtime_throw("runtime: cannot allocate memory");
+	}
+
+	// Hash stack.
+	h = 0;
+	for(i=0; i<nstk; i++) {
+		h += stk[i].pc;
+		h += h<<10;
+		h ^= h>>6;
+	}
+	// hash in size
+	h += size;
+	h += h<<10;
+	h ^= h>>6;
+	// finalize
+	h += h<<3;
+	h ^= h>>11;
+
+	i = h%BuckHashSize;
+	for(b = buckhash[i]; b; b=b->next) {
+		if(b->typ == typ && b->hash == h && b->size == size && b->nstk == (uintptr)nstk) {
+			for(j = 0; j < nstk; j++) {
+				if(b->stk[j].pc != stk[j].pc ||
+				   b->stk[j].lineno != stk[j].lineno ||
+				   !__go_strings_equal(b->stk[j].filename, stk[j].filename))
+					break;
+			}
+			if (j == nstk)
+				return b;
+		}
+	}
+
+	if(!alloc)
+		return nil;
+
+	b = runtime_persistentalloc(sizeof *b + nstk*sizeof stk[0], 0, &mstats.buckhash_sys);
+	bucketmem += sizeof *b + nstk*sizeof stk[0];
+	runtime_memmove(b->stk, stk, nstk*sizeof stk[0]);
+	b->typ = typ;
+	b->hash = h;
+	b->size = size;
+	b->nstk = nstk;
+	b->next = buckhash[i];
+	buckhash[i] = b;
+	if(typ == MProf) {
+		b->allnext = mbuckets;
+		mbuckets = b;
+	} else {
+		b->allnext = bbuckets;
+		bbuckets = b;
+	}
+	return b;
+}
+
+static void
+MProf_GC(void)
+{
+	Bucket *b;
+
+	for(b=mbuckets; b; b=b->allnext) {
+		b->allocs += b->prev_allocs;
+		b->frees += b->prev_frees;
+		b->alloc_bytes += b->prev_alloc_bytes;
+		b->free_bytes += b->prev_free_bytes;
+
+		b->prev_allocs = b->recent_allocs;
+		b->prev_frees = b->recent_frees;
+		b->prev_alloc_bytes = b->recent_alloc_bytes;
+		b->prev_free_bytes = b->recent_free_bytes;
+
+		b->recent_allocs = 0;
+		b->recent_frees = 0;
+		b->recent_alloc_bytes = 0;
+		b->recent_free_bytes = 0;
+	}
+}
+
+// Record that a gc just happened: all the 'recent' statistics are now real.
+void
+runtime_MProf_GC(void)
+{
+	runtime_lock(&proflock);
+	MProf_GC();
+	runtime_unlock(&proflock);
+}
+
+// Called by malloc to record a profiled block.
+void
+runtime_MProf_Malloc(void *p, uintptr size)
+{
+	Location stk[32];
+	Bucket *b;
+	int32 nstk;
+
+	nstk = runtime_callers(1, stk, nelem(stk), false);
+	runtime_lock(&proflock);
+	b = stkbucket(MProf, size, stk, nstk, true);
+	b->recent_allocs++;
+	b->recent_alloc_bytes += size;
+	runtime_unlock(&proflock);
+
+	// Setprofilebucket locks a bunch of other mutexes, so we call it outside of proflock.
+	// This reduces potential contention and chances of deadlocks.
+	// Since the object must be alive during call to MProf_Malloc,
+	// it's fine to do this non-atomically.
+	runtime_setprofilebucket(p, b);
+}
+
+// Called when freeing a profiled block.
+void
+runtime_MProf_Free(Bucket *b, uintptr size, bool freed)
+{
+	runtime_lock(&proflock);
+	if(freed) {
+		b->recent_frees++;
+		b->recent_free_bytes += size;
+	} else {
+		b->prev_frees++;
+		b->prev_free_bytes += size;
+	}
+	runtime_unlock(&proflock);
+}
+
+int64 runtime_blockprofilerate;  // in CPU ticks
+
+void runtime_SetBlockProfileRate(intgo) __asm__ (GOSYM_PREFIX "runtime.SetBlockProfileRate");
+
+void
+runtime_SetBlockProfileRate(intgo rate)
+{
+	int64 r;
+
+	if(rate <= 0)
+		r = 0;  // disable profiling
+	else {
+		// convert ns to cycles, use float64 to prevent overflow during multiplication
+		r = (float64)rate*runtime_tickspersecond()/(1000*1000*1000);
+		if(r == 0)
+			r = 1;
+	}
+	runtime_atomicstore64((uint64*)&runtime_blockprofilerate, r);
+}
+
+void
+runtime_blockevent(int64 cycles, int32 skip)
+{
+	int32 nstk;
+	int64 rate;
+	Location stk[32];
+	Bucket *b;
+
+	if(cycles <= 0)
+		return;
+	rate = runtime_atomicload64((uint64*)&runtime_blockprofilerate);
+	if(rate <= 0 || (rate > cycles && runtime_fastrand1()%rate > cycles))
+		return;
+
+	nstk = runtime_callers(skip, stk, nelem(stk), false);
+	runtime_lock(&proflock);
+	b = stkbucket(BProf, 0, stk, nstk, true);
+	b->count++;
+	b->cycles += cycles;
+	runtime_unlock(&proflock);
+}
+
+// Go interface to profile data.  (Declared in debug.go)
+
+// Must match MemProfileRecord in debug.go.
+typedef struct Record Record;
+struct Record {
+	int64 alloc_bytes, free_bytes;
+	int64 alloc_objects, free_objects;
+	uintptr stk[32];
+};
+
+// Write b's data to r.
+static void
+record(Record *r, Bucket *b)
+{
+	uint32 i;
+
+	r->alloc_bytes = b->alloc_bytes;
+	r->free_bytes = b->free_bytes;
+	r->alloc_objects = b->allocs;
+	r->free_objects = b->frees;
+	for(i=0; i<b->nstk && i<nelem(r->stk); i++)
+		r->stk[i] = b->stk[i].pc;
+	for(; i<nelem(r->stk); i++)
+		r->stk[i] = 0;
+}
+
+func MemProfile(p Slice, include_inuse_zero bool) (n int, ok bool) {
+	Bucket *b;
+	Record *r;
+	bool clear;
+
+	runtime_lock(&proflock);
+	n = 0;
+	clear = true;
+	for(b=mbuckets; b; b=b->allnext) {
+		if(include_inuse_zero || b->alloc_bytes != b->free_bytes)
+			n++;
+		if(b->allocs != 0 || b->frees != 0)
+			clear = false;
+	}
+	if(clear) {
+		// Absolutely no data, suggesting that a garbage collection
+		// has not yet happened. In order to allow profiling when
+		// garbage collection is disabled from the beginning of execution,
+		// accumulate stats as if a GC just happened, and recount buckets.
+		MProf_GC();
+		MProf_GC();
+		n = 0;
+		for(b=mbuckets; b; b=b->allnext)
+			if(include_inuse_zero || b->alloc_bytes != b->free_bytes)
+				n++;
+	}
+	ok = false;
+	if(n <= p.__count) {
+		ok = true;
+		r = (Record*)p.__values;
+		for(b=mbuckets; b; b=b->allnext)
+			if(include_inuse_zero || b->alloc_bytes != b->free_bytes)
+				record(r++, b);
+	}
+	runtime_unlock(&proflock);
+}
+
+void
+runtime_MProf_Mark(struct Workbuf **wbufp, void (*enqueue1)(struct Workbuf**, Obj))
+{
+	// buckhash is not allocated via mallocgc.
+	enqueue1(wbufp, (Obj){(byte*)&mbuckets, sizeof mbuckets, 0});
+	enqueue1(wbufp, (Obj){(byte*)&bbuckets, sizeof bbuckets, 0});
+}
+
+void
+runtime_iterate_memprof(void (*callback)(Bucket*, uintptr, Location*, uintptr, uintptr, uintptr))
+{
+	Bucket *b;
+
+	runtime_lock(&proflock);
+	for(b=mbuckets; b; b=b->allnext) {
+		callback(b, b->nstk, b->stk, b->size, b->allocs, b->frees);
+	}
+	runtime_unlock(&proflock);
+}
+
+// Must match BlockProfileRecord in debug.go.
+typedef struct BRecord BRecord;
+struct BRecord {
+	int64 count;
+	int64 cycles;
+	uintptr stk[32];
+};
+
+func BlockProfile(p Slice) (n int, ok bool) {
+	Bucket *b;
+	BRecord *r;
+	int32 i;
+
+	runtime_lock(&proflock);
+	n = 0;
+	for(b=bbuckets; b; b=b->allnext)
+		n++;
+	ok = false;
+	if(n <= p.__count) {
+		ok = true;
+		r = (BRecord*)p.__values;
+		for(b=bbuckets; b; b=b->allnext, r++) {
+			r->count = b->count;
+			r->cycles = b->cycles;
+			for(i=0; (uintptr)i<b->nstk && (uintptr)i<nelem(r->stk); i++)
+				r->stk[i] = b->stk[i].pc;
+			for(; (uintptr)i<nelem(r->stk); i++)
+				r->stk[i] = 0;			
+		}
+	}
+	runtime_unlock(&proflock);
+}
+
+// Must match StackRecord in debug.go.
+typedef struct TRecord TRecord;
+struct TRecord {
+	uintptr stk[32];
+};
+
+func ThreadCreateProfile(p Slice) (n int, ok bool) {
+	TRecord *r;
+	M *first, *mp;
+	int32 i;
+	
+	first = runtime_atomicloadp(&runtime_allm);
+	n = 0;
+	for(mp=first; mp; mp=mp->alllink)
+		n++;
+	ok = false;
+	if(n <= p.__count) {
+		ok = true;
+		r = (TRecord*)p.__values;
+		for(mp=first; mp; mp=mp->alllink) {
+			for(i = 0; (uintptr)i < nelem(r->stk); i++) {
+				r->stk[i] = mp->createstack[i].pc;
+			}
+			r++;
+		}
+	}
+}
+
+func Stack(b Slice, all bool) (n int) {
+	byte *pc, *sp;
+	bool enablegc;
+	
+	sp = runtime_getcallersp(&b);
+	pc = (byte*)(uintptr)runtime_getcallerpc(&b);
+
+	if(all) {
+		runtime_semacquire(&runtime_worldsema, false);
+		runtime_m()->gcing = 1;
+		runtime_stoptheworld();
+		enablegc = mstats.enablegc;
+		mstats.enablegc = false;
+	}
+
+	if(b.__count == 0)
+		n = 0;
+	else{
+		G* g = runtime_g();
+		g->writebuf = (byte*)b.__values;
+		g->writenbuf = b.__count;
+		USED(pc);
+		USED(sp);
+		runtime_goroutineheader(g);
+		runtime_traceback();
+		runtime_printcreatedby(g);
+		if(all)
+			runtime_tracebackothers(g);
+		n = b.__count - g->writenbuf;
+		g->writebuf = nil;
+		g->writenbuf = 0;
+	}
+	
+	if(all) {
+		runtime_m()->gcing = 0;
+		mstats.enablegc = enablegc;
+		runtime_semrelease(&runtime_worldsema);
+		runtime_starttheworld();
+	}
+}
+
+static void
+saveg(G *gp, TRecord *r)
+{
+	int32 n, i;
+	Location locstk[nelem(r->stk)];
+
+	if(gp == runtime_g()) {
+		n = runtime_callers(0, locstk, nelem(r->stk), false);
+		for(i = 0; i < n; i++)
+			r->stk[i] = locstk[i].pc;
+	}
+	else {
+		// FIXME: Not implemented.
+		n = 0;
+	}
+	if((size_t)n < nelem(r->stk))
+		r->stk[n] = 0;
+}
+
+func GoroutineProfile(b Slice) (n int, ok bool) {
+	uintptr i;
+	TRecord *r;
+	G *gp;
+	
+	ok = false;
+	n = runtime_gcount();
+	if(n <= b.__count) {
+		runtime_semacquire(&runtime_worldsema, false);
+		runtime_m()->gcing = 1;
+		runtime_stoptheworld();
+
+		n = runtime_gcount();
+		if(n <= b.__count) {
+			G* g = runtime_g();
+			ok = true;
+			r = (TRecord*)b.__values;
+			saveg(g, r++);
+			for(i = 0; i < runtime_allglen; i++) {
+				gp = runtime_allg[i];
+				if(gp == g || gp->status == Gdead)
+					continue;
+				saveg(gp, r++);
+			}
+		}
+	
+		runtime_m()->gcing = 0;
+		runtime_semrelease(&runtime_worldsema);
+		runtime_starttheworld();
+	}
+}
+
+// Tracing of alloc/free/gc.
+
+static Lock tracelock;
+
+static const char*
+typeinfoname(int32 typeinfo)
+{
+	if(typeinfo == TypeInfo_SingleObject)
+		return "single object";
+	else if(typeinfo == TypeInfo_Array)
+		return "array";
+	else if(typeinfo == TypeInfo_Chan)
+		return "channel";
+	runtime_throw("typinfoname: unknown type info");
+	return nil;
+}
+
+void
+runtime_tracealloc(void *p, uintptr size, uintptr typ)
+{
+	const char *name;
+	Type *type;
+
+	runtime_lock(&tracelock);
+	runtime_m()->traceback = 2;
+	type = (Type*)(typ & ~3);
+	name = typeinfoname(typ & 3);
+	if(type == nil)
+		runtime_printf("tracealloc(%p, %p, %s)\n", p, size, name);
+	else	
+		runtime_printf("tracealloc(%p, %p, %s of %S)\n", p, size, name, *type->__reflection);
+	if(runtime_m()->curg == nil || runtime_g() == runtime_m()->curg) {
+		runtime_goroutineheader(runtime_g());
+		runtime_traceback();
+	} else {
+		runtime_goroutineheader(runtime_m()->curg);
+		runtime_traceback();
+	}
+	runtime_printf("\n");
+	runtime_m()->traceback = 0;
+	runtime_unlock(&tracelock);
+}
+
+void
+runtime_tracefree(void *p, uintptr size)
+{
+	runtime_lock(&tracelock);
+	runtime_m()->traceback = 2;
+	runtime_printf("tracefree(%p, %p)\n", p, size);
+	runtime_goroutineheader(runtime_g());
+	runtime_traceback();
+	runtime_printf("\n");
+	runtime_m()->traceback = 0;
+	runtime_unlock(&tracelock);
+}
+
+void
+runtime_tracegc(void)
+{
+	runtime_lock(&tracelock);
+	runtime_m()->traceback = 2;
+	runtime_printf("tracegc()\n");
+	// running on m->g0 stack; show all non-g0 goroutines
+	runtime_tracebackothers(runtime_g());
+	runtime_printf("end tracegc\n");
+	runtime_printf("\n");
+	runtime_m()->traceback = 0;
+	runtime_unlock(&tracelock);
+}
diff --git a/third_party/gofrontend/libgo/runtime/msize.c b/third_party/gofrontend/libgo/runtime/msize.c
new file mode 100644
index 0000000..34509d0
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/msize.c
@@ -0,0 +1,175 @@
+// 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.
+
+// Malloc small size classes.
+//
+// See malloc.h for overview.
+//
+// The size classes are chosen so that rounding an allocation
+// request up to the next size class wastes at most 12.5% (1.125x).
+//
+// Each size class has its own page count that gets allocated
+// and chopped up when new objects of the size class are needed.
+// That page count is chosen so that chopping up the run of
+// pages into objects of the given size wastes at most 12.5% (1.125x)
+// of the memory.  It is not necessary that the cutoff here be
+// the same as above.
+//
+// The two sources of waste multiply, so the worst possible case
+// for the above constraints would be that allocations of some
+// size might have a 26.6% (1.266x) overhead.
+// In practice, only one of the wastes comes into play for a
+// given size (sizes < 512 waste mainly on the round-up,
+// sizes > 512 waste mainly on the page chopping).
+//
+// TODO(rsc): Compute max waste for any given size.
+
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+int32 runtime_class_to_size[NumSizeClasses];
+int32 runtime_class_to_allocnpages[NumSizeClasses];
+
+// The SizeToClass lookup is implemented using two arrays,
+// one mapping sizes <= 1024 to their class and one mapping
+// sizes >= 1024 and <= MaxSmallSize to their class.
+// All objects are 8-aligned, so the first array is indexed by
+// the size divided by 8 (rounded up).  Objects >= 1024 bytes
+// are 128-aligned, so the second array is indexed by the
+// size divided by 128 (rounded up).  The arrays are filled in
+// by InitSizes.
+
+int8 runtime_size_to_class8[1024/8 + 1];
+int8 runtime_size_to_class128[(MaxSmallSize-1024)/128 + 1];
+
+int32
+runtime_SizeToClass(int32 size)
+{
+	if(size > MaxSmallSize)
+		runtime_throw("SizeToClass - invalid size");
+	if(size > 1024-8)
+		return runtime_size_to_class128[(size-1024+127) >> 7];
+	return runtime_size_to_class8[(size+7)>>3];
+}
+
+void
+runtime_InitSizes(void)
+{
+	int32 align, sizeclass, size, nextsize, n;
+	uint32 i;
+	uintptr allocsize, npages;
+
+	// Initialize the runtime_class_to_size table (and choose class sizes in the process).
+	runtime_class_to_size[0] = 0;
+	sizeclass = 1;	// 0 means no class
+	align = 8;
+	for(size = align; size <= MaxSmallSize; size += align) {
+		if((size&(size-1)) == 0) {	// bump alignment once in a while
+			if(size >= 2048)
+				align = 256;
+			else if(size >= 128)
+				align = size / 8;
+			else if(size >= 16)
+				align = 16;	// required for x86 SSE instructions, if we want to use them
+		}
+		if((align&(align-1)) != 0)
+			runtime_throw("InitSizes - bug");
+
+		// Make the allocnpages big enough that
+		// the leftover is less than 1/8 of the total,
+		// so wasted space is at most 12.5%.
+		allocsize = PageSize;
+		while(allocsize%size > allocsize/8)
+			allocsize += PageSize;
+		npages = allocsize >> PageShift;
+
+		// If the previous sizeclass chose the same
+		// allocation size and fit the same number of
+		// objects into the page, we might as well
+		// use just this size instead of having two
+		// different sizes.
+		if(sizeclass > 1 &&
+			(int32)npages == runtime_class_to_allocnpages[sizeclass-1] &&
+			allocsize/size == allocsize/runtime_class_to_size[sizeclass-1]) {
+			runtime_class_to_size[sizeclass-1] = size;
+			continue;
+		}
+
+		runtime_class_to_allocnpages[sizeclass] = npages;
+		runtime_class_to_size[sizeclass] = size;
+		sizeclass++;
+	}
+	if(sizeclass != NumSizeClasses) {
+		runtime_printf("sizeclass=%d NumSizeClasses=%d\n", sizeclass, NumSizeClasses);
+		runtime_throw("InitSizes - bad NumSizeClasses");
+	}
+
+	// Initialize the size_to_class tables.
+	nextsize = 0;
+	for (sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) {
+		for(; nextsize < 1024 && nextsize <= runtime_class_to_size[sizeclass]; nextsize+=8)
+			runtime_size_to_class8[nextsize/8] = sizeclass;
+		if(nextsize >= 1024)
+			for(; nextsize <= runtime_class_to_size[sizeclass]; nextsize += 128)
+				runtime_size_to_class128[(nextsize-1024)/128] = sizeclass;
+	}
+
+	// Double-check SizeToClass.
+	if(0) {
+		for(n=0; n < MaxSmallSize; n++) {
+			sizeclass = runtime_SizeToClass(n);
+			if(sizeclass < 1 || sizeclass >= NumSizeClasses || runtime_class_to_size[sizeclass] < n) {
+				runtime_printf("size=%d sizeclass=%d runtime_class_to_size=%d\n", n, sizeclass, runtime_class_to_size[sizeclass]);
+				runtime_printf("incorrect SizeToClass");
+				goto dump;
+			}
+			if(sizeclass > 1 && runtime_class_to_size[sizeclass-1] >= n) {
+				runtime_printf("size=%d sizeclass=%d runtime_class_to_size=%d\n", n, sizeclass, runtime_class_to_size[sizeclass]);
+				runtime_printf("SizeToClass too big");
+				goto dump;
+			}
+		}
+	}
+
+	// Copy out for statistics table.
+	for(i=0; i<nelem(runtime_class_to_size); i++)
+		mstats.by_size[i].size = runtime_class_to_size[i];
+	return;
+
+dump:
+	if(1){
+		runtime_printf("NumSizeClasses=%d\n", NumSizeClasses);
+		runtime_printf("runtime_class_to_size:");
+		for(sizeclass=0; sizeclass<NumSizeClasses; sizeclass++)
+			runtime_printf(" %d", runtime_class_to_size[sizeclass]);
+		runtime_printf("\n\n");
+		runtime_printf("size_to_class8:");
+		for(i=0; i<nelem(runtime_size_to_class8); i++)
+			runtime_printf(" %d=>%d(%d)\n", i*8, runtime_size_to_class8[i],
+				runtime_class_to_size[runtime_size_to_class8[i]]);
+		runtime_printf("\n");
+		runtime_printf("size_to_class128:");
+		for(i=0; i<nelem(runtime_size_to_class128); i++)
+			runtime_printf(" %d=>%d(%d)\n", i*128, runtime_size_to_class128[i],
+				runtime_class_to_size[runtime_size_to_class128[i]]);
+		runtime_printf("\n");
+	}
+	runtime_throw("InitSizes failed");
+}
+
+// Returns size of the memory block that mallocgc will allocate if you ask for the size.
+uintptr
+runtime_roundupsize(uintptr size)
+{
+	if(size < MaxSmallSize) {
+		if(size <= 1024-8)
+			return runtime_class_to_size[runtime_size_to_class8[(size+7)>>3]];
+		else
+			return runtime_class_to_size[runtime_size_to_class128[(size-1024+127) >> 7]];
+	}
+	if(size + PageSize < size)
+		return size;
+	return ROUND(size, PageSize);
+}
diff --git a/third_party/gofrontend/libgo/runtime/netpoll.goc b/third_party/gofrontend/libgo/runtime/netpoll.goc
new file mode 100644
index 0000000..0808b27
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/netpoll.goc
@@ -0,0 +1,472 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package net
+
+#include "runtime.h"
+#include "defs.h"
+#include "arch.h"
+#include "malloc.h"
+
+// Map gccgo field names to gc field names.
+// Eface aka __go_empty_interface.
+#define type __type_descriptor
+#define data __object
+
+// Integrated network poller (platform-independent part).
+// A particular implementation (epoll/kqueue) must define the following functions:
+// void runtime_netpollinit(void);			// to initialize the poller
+// int32 runtime_netpollopen(uintptr fd, PollDesc *pd);	// to arm edge-triggered notifications
+							// and associate fd with pd.
+// An implementation must call the following function to denote that the pd is ready.
+// void runtime_netpollready(G **gpp, PollDesc *pd, int32 mode);
+
+// PollDesc contains 2 binary semaphores, rg and wg, to park reader and writer
+// goroutines respectively. The semaphore can be in the following states:
+// READY - io readiness notification is pending;
+//         a goroutine consumes the notification by changing the state to nil.
+// WAIT - a goroutine prepares to park on the semaphore, but not yet parked;
+//        the goroutine commits to park by changing the state to G pointer,
+//        or, alternatively, concurrent io notification changes the state to READY,
+//        or, alternatively, concurrent timeout/close changes the state to nil.
+// G pointer - the goroutine is blocked on the semaphore;
+//             io notification or timeout/close changes the state to READY or nil respectively
+//             and unparks the goroutine.
+// nil - nothing of the above.
+#define READY ((G*)1)
+#define WAIT  ((G*)2)
+
+enum
+{
+	PollBlockSize	= 4*1024,
+};
+
+struct PollDesc
+{
+	PollDesc* link;	// in pollcache, protected by pollcache.Lock
+
+	// The lock protects pollOpen, pollSetDeadline, pollUnblock and deadlineimpl operations.
+	// This fully covers seq, rt and wt variables. fd is constant throughout the PollDesc lifetime.
+	// pollReset, pollWait, pollWaitCanceled and runtime_netpollready (IO rediness notification)
+	// proceed w/o taking the lock. So closing, rg, rd, wg and wd are manipulated
+	// in a lock-free way by all operations.
+	Lock	lock;	// protectes the following fields
+	uintptr	fd;
+	bool	closing;
+	uintptr	seq;	// protects from stale timers and ready notifications
+	G*	rg;	// READY, WAIT, G waiting for read or nil
+	Timer	rt;	// read deadline timer (set if rt.fv != nil)
+	int64	rd;	// read deadline
+	G*	wg;	// READY, WAIT, G waiting for write or nil
+	Timer	wt;	// write deadline timer
+	int64	wd;	// write deadline
+	void*	user;	// user settable cookie
+};
+
+static struct
+{
+	Lock		lock;
+	PollDesc*	first;
+	// PollDesc objects must be type-stable,
+	// because we can get ready notification from epoll/kqueue
+	// after the descriptor is closed/reused.
+	// Stale notifications are detected using seq variable,
+	// seq is incremented when deadlines are changed or descriptor is reused.
+} pollcache;
+
+static bool	netpollblock(PollDesc*, int32, bool);
+static G*	netpollunblock(PollDesc*, int32, bool);
+static void	deadline(int64, Eface);
+static void	readDeadline(int64, Eface);
+static void	writeDeadline(int64, Eface);
+static PollDesc*	allocPollDesc(void);
+static intgo	checkerr(PollDesc *pd, int32 mode);
+
+static FuncVal deadlineFn	= {(void(*)(void))deadline};
+static FuncVal readDeadlineFn	= {(void(*)(void))readDeadline};
+static FuncVal writeDeadlineFn	= {(void(*)(void))writeDeadline};
+
+// runtimeNano returns the current value of the runtime clock in nanoseconds.
+func runtimeNano() (ns int64) {
+	ns = runtime_nanotime();
+}
+
+func runtime_pollServerInit() {
+	runtime_netpollinit();
+}
+
+func runtime_pollOpen(fd uintptr) (pd *PollDesc, errno int) {
+	pd = allocPollDesc();
+	runtime_lock(&pd->lock);
+	if(pd->wg != nil && pd->wg != READY)
+		runtime_throw("runtime_pollOpen: blocked write on free descriptor");
+	if(pd->rg != nil && pd->rg != READY)
+		runtime_throw("runtime_pollOpen: blocked read on free descriptor");
+	pd->fd = fd;
+	pd->closing = false;
+	pd->seq++;
+	pd->rg = nil;
+	pd->rd = 0;
+	pd->wg = nil;
+	pd->wd = 0;
+	runtime_unlock(&pd->lock);
+
+	errno = runtime_netpollopen(fd, pd);
+}
+
+func runtime_pollClose(pd *PollDesc) {
+	if(!pd->closing)
+		runtime_throw("runtime_pollClose: close w/o unblock");
+	if(pd->wg != nil && pd->wg != READY)
+		runtime_throw("runtime_pollClose: blocked write on closing descriptor");
+	if(pd->rg != nil && pd->rg != READY)
+		runtime_throw("runtime_pollClose: blocked read on closing descriptor");
+	runtime_netpollclose(pd->fd);
+	runtime_lock(&pollcache.lock);
+	pd->link = pollcache.first;
+	pollcache.first = pd;
+	runtime_unlock(&pollcache.lock);
+}
+
+func runtime_pollReset(pd *PollDesc, mode int) (err int) {
+	err = checkerr(pd, mode);
+	if(err)
+		goto ret;
+	if(mode == 'r')
+		pd->rg = nil;
+	else if(mode == 'w')
+		pd->wg = nil;
+ret:
+}
+
+func runtime_pollWait(pd *PollDesc, mode int) (err int) {
+	err = checkerr(pd, mode);
+	if(err == 0) {
+		// As for now only Solaris uses level-triggered IO.
+		if(Solaris)
+			runtime_netpollarm(pd, mode);
+		while(!netpollblock(pd, mode, false)) {
+			err = checkerr(pd, mode);
+			if(err != 0)
+				break;
+			// Can happen if timeout has fired and unblocked us,
+			// but before we had a chance to run, timeout has been reset.
+			// Pretend it has not happened and retry.
+		}
+	}
+}
+
+func runtime_pollWaitCanceled(pd *PollDesc, mode int) {
+	// This function is used only on windows after a failed attempt to cancel
+	// a pending async IO operation. Wait for ioready, ignore closing or timeouts.
+	while(!netpollblock(pd, mode, true))
+		;
+}
+
+func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
+	G *rg, *wg;
+
+	runtime_lock(&pd->lock);
+	if(pd->closing) {
+		runtime_unlock(&pd->lock);
+		return;
+	}
+	pd->seq++;  // invalidate current timers
+	// Reset current timers.
+	if(pd->rt.fv) {
+		runtime_deltimer(&pd->rt);
+		pd->rt.fv = nil;
+	}
+	if(pd->wt.fv) {
+		runtime_deltimer(&pd->wt);
+		pd->wt.fv = nil;
+	}
+	// Setup new timers.
+	if(d != 0 && d <= runtime_nanotime())
+		d = -1;
+	if(mode == 'r' || mode == 'r'+'w')
+		pd->rd = d;
+	if(mode == 'w' || mode == 'r'+'w')
+		pd->wd = d;
+	if(pd->rd > 0 && pd->rd == pd->wd) {
+		pd->rt.fv = &deadlineFn;
+		pd->rt.when = pd->rd;
+		// Copy current seq into the timer arg.
+		// Timer func will check the seq against current descriptor seq,
+		// if they differ the descriptor was reused or timers were reset.
+		pd->rt.arg.type = (Type*)pd->seq;
+		pd->rt.arg.data = pd;
+		runtime_addtimer(&pd->rt);
+	} else {
+		if(pd->rd > 0) {
+			pd->rt.fv = &readDeadlineFn;
+			pd->rt.when = pd->rd;
+			pd->rt.arg.type = (Type*)pd->seq;
+			pd->rt.arg.data = pd;
+			runtime_addtimer(&pd->rt);
+		}
+		if(pd->wd > 0) {
+			pd->wt.fv = &writeDeadlineFn;
+			pd->wt.when = pd->wd;
+			pd->wt.arg.type = (Type*)pd->seq;
+			pd->wt.arg.data = pd;
+			runtime_addtimer(&pd->wt);
+		}
+	}
+	// If we set the new deadline in the past, unblock currently pending IO if any.
+	rg = nil;
+	runtime_atomicstorep(&wg, nil);  // full memory barrier between stores to rd/wd and load of rg/wg in netpollunblock
+	if(pd->rd < 0)
+		rg = netpollunblock(pd, 'r', false);
+	if(pd->wd < 0)
+		wg = netpollunblock(pd, 'w', false);
+	runtime_unlock(&pd->lock);
+	if(rg)
+		runtime_ready(rg);
+	if(wg)
+		runtime_ready(wg);
+}
+
+func runtime_pollUnblock(pd *PollDesc) {
+	G *rg, *wg;
+
+	runtime_lock(&pd->lock);
+	if(pd->closing)
+		runtime_throw("runtime_pollUnblock: already closing");
+	pd->closing = true;
+	pd->seq++;
+	runtime_atomicstorep(&rg, nil);  // full memory barrier between store to closing and read of rg/wg in netpollunblock
+	rg = netpollunblock(pd, 'r', false);
+	wg = netpollunblock(pd, 'w', false);
+	if(pd->rt.fv) {
+		runtime_deltimer(&pd->rt);
+		pd->rt.fv = nil;
+	}
+	if(pd->wt.fv) {
+		runtime_deltimer(&pd->wt);
+		pd->wt.fv = nil;
+	}
+	runtime_unlock(&pd->lock);
+	if(rg)
+		runtime_ready(rg);
+	if(wg)
+		runtime_ready(wg);
+}
+
+uintptr
+runtime_netpollfd(PollDesc *pd)
+{
+	return pd->fd;
+}
+
+void**
+runtime_netpolluser(PollDesc *pd)
+{
+	return &pd->user;
+}
+
+bool
+runtime_netpollclosing(PollDesc *pd)
+{
+	return pd->closing;
+}
+
+void
+runtime_netpolllock(PollDesc *pd)
+{
+	runtime_lock(&pd->lock);
+}
+
+void
+runtime_netpollunlock(PollDesc *pd)
+{
+	runtime_unlock(&pd->lock);
+}
+
+// make pd ready, newly runnable goroutines (if any) are enqueued info gpp list
+void
+runtime_netpollready(G **gpp, PollDesc *pd, int32 mode)
+{
+	G *rg, *wg;
+
+	rg = wg = nil;
+	if(mode == 'r' || mode == 'r'+'w')
+		rg = netpollunblock(pd, 'r', true);
+	if(mode == 'w' || mode == 'r'+'w')
+		wg = netpollunblock(pd, 'w', true);
+	if(rg) {
+		rg->schedlink = *gpp;
+		*gpp = rg;
+	}
+	if(wg) {
+		wg->schedlink = *gpp;
+		*gpp = wg;
+	}
+}
+
+static intgo
+checkerr(PollDesc *pd, int32 mode)
+{
+	if(pd->closing)
+		return 1;  // errClosing
+	if((mode == 'r' && pd->rd < 0) || (mode == 'w' && pd->wd < 0))
+		return 2;  // errTimeout
+	return 0;
+}
+
+static bool
+blockcommit(G *gp, G **gpp)
+{
+	return runtime_casp(gpp, WAIT, gp);
+}
+
+// returns true if IO is ready, or false if timedout or closed
+// waitio - wait only for completed IO, ignore errors
+static bool
+netpollblock(PollDesc *pd, int32 mode, bool waitio)
+{
+	G **gpp, *old;
+
+	gpp = &pd->rg;
+	if(mode == 'w')
+		gpp = &pd->wg;
+
+	// set the gpp semaphore to WAIT
+	for(;;) {
+		old = *gpp;
+		if(old == READY) {
+			*gpp = nil;
+			return true;
+		}
+		if(old != nil)
+			runtime_throw("netpollblock: double wait");
+		if(runtime_casp(gpp, nil, WAIT))
+			break;
+	}
+
+	// need to recheck error states after setting gpp to WAIT
+	// this is necessary because runtime_pollUnblock/runtime_pollSetDeadline/deadlineimpl
+	// do the opposite: store to closing/rd/wd, membarrier, load of rg/wg
+	if(waitio || checkerr(pd, mode) == 0)
+		runtime_park((bool(*)(G*, void*))blockcommit, gpp, "IO wait");
+	// be careful to not lose concurrent READY notification
+	old = runtime_xchgp(gpp, nil);
+	if(old > WAIT)
+		runtime_throw("netpollblock: corrupted state");
+	return old == READY;
+}
+
+static G*
+netpollunblock(PollDesc *pd, int32 mode, bool ioready)
+{
+	G **gpp, *old, *new;
+
+	gpp = &pd->rg;
+	if(mode == 'w')
+		gpp = &pd->wg;
+
+	for(;;) {
+		old = *gpp;
+		if(old == READY)
+			return nil;
+		if(old == nil && !ioready) {
+			// Only set READY for ioready. runtime_pollWait
+			// will check for timeout/cancel before waiting.
+			return nil;
+		}
+		new = nil;
+		if(ioready)
+			new = READY;
+		if(runtime_casp(gpp, old, new))
+			break;
+	}
+	if(old > WAIT)
+		return old;  // must be G*
+	return nil;
+}
+
+static void
+deadlineimpl(int64 now, Eface arg, bool read, bool write)
+{
+	PollDesc *pd;
+	uint32 seq;
+	G *rg, *wg;
+
+	USED(now);
+	pd = (PollDesc*)arg.data;
+	// This is the seq when the timer was set.
+	// If it's stale, ignore the timer event.
+	seq = (uintptr)arg.type;
+	rg = wg = nil;
+	runtime_lock(&pd->lock);
+	if(seq != pd->seq) {
+		// The descriptor was reused or timers were reset.
+		runtime_unlock(&pd->lock);
+		return;
+	}
+	if(read) {
+		if(pd->rd <= 0 || pd->rt.fv == nil)
+			runtime_throw("deadlineimpl: inconsistent read deadline");
+		pd->rd = -1;
+		runtime_atomicstorep(&pd->rt.fv, nil);  // full memory barrier between store to rd and load of rg in netpollunblock
+		rg = netpollunblock(pd, 'r', false);
+	}
+	if(write) {
+		if(pd->wd <= 0 || (pd->wt.fv == nil && !read))
+			runtime_throw("deadlineimpl: inconsistent write deadline");
+		pd->wd = -1;
+		runtime_atomicstorep(&pd->wt.fv, nil);  // full memory barrier between store to wd and load of wg in netpollunblock
+		wg = netpollunblock(pd, 'w', false);
+	}
+	runtime_unlock(&pd->lock);
+	if(rg)
+		runtime_ready(rg);
+	if(wg)
+		runtime_ready(wg);
+}
+
+static void
+deadline(int64 now, Eface arg)
+{
+	deadlineimpl(now, arg, true, true);
+}
+
+static void
+readDeadline(int64 now, Eface arg)
+{
+	deadlineimpl(now, arg, true, false);
+}
+
+static void
+writeDeadline(int64 now, Eface arg)
+{
+	deadlineimpl(now, arg, false, true);
+}
+
+static PollDesc*
+allocPollDesc(void)
+{
+	PollDesc *pd;
+	uint32 i, n;
+
+	runtime_lock(&pollcache.lock);
+	if(pollcache.first == nil) {
+		n = PollBlockSize/sizeof(*pd);
+		if(n == 0)
+			n = 1;
+		// Must be in non-GC memory because can be referenced
+		// only from epoll/kqueue internals.
+		pd = runtime_persistentalloc(n*sizeof(*pd), 0, &mstats.other_sys);
+		for(i = 0; i < n; i++) {
+			pd[i].link = pollcache.first;
+			pollcache.first = &pd[i];
+		}
+	}
+	pd = pollcache.first;
+	pollcache.first = pd->link;
+	runtime_unlock(&pollcache.lock);
+	return pd;
+}
diff --git a/third_party/gofrontend/libgo/runtime/netpoll_epoll.c b/third_party/gofrontend/libgo/runtime/netpoll_epoll.c
new file mode 100644
index 0000000..1281f45
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/netpoll_epoll.c
@@ -0,0 +1,174 @@
+// Copyright 2013 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.
+
+// +build linux
+
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/epoll.h>
+
+#include "runtime.h"
+#include "defs.h"
+#include "malloc.h"
+
+#ifndef EPOLLRDHUP
+#define EPOLLRDHUP 0x2000
+#endif
+
+#ifndef EPOLL_CLOEXEC
+#define EPOLL_CLOEXEC 02000000
+#endif
+
+#ifndef HAVE_EPOLL_CREATE1
+extern int epoll_create1(int __flags);
+#endif
+
+typedef struct epoll_event EpollEvent;
+
+static int32
+runtime_epollcreate(int32 size)
+{
+	int r;
+
+	r = epoll_create(size);
+	if(r >= 0)
+		return r;
+	return - errno;
+}
+
+static int32
+runtime_epollcreate1(int32 flags)
+{
+	int r;
+
+	r = epoll_create1(flags);
+	if(r >= 0)
+		return r;
+	return - errno;
+}
+
+static int32
+runtime_epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev)
+{
+	int r;
+
+	r = epoll_ctl(epfd, op, fd, ev);
+	if(r >= 0)
+		return r;
+	return - errno;
+}
+
+static int32
+runtime_epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout)
+{
+	int r;
+
+	r = epoll_wait(epfd, ev, nev, timeout);
+	if(r >= 0)
+		return r;
+	return - errno;
+}
+
+static void
+runtime_closeonexec(int32 fd)
+{
+	fcntl(fd, F_SETFD, FD_CLOEXEC);
+}
+
+static int32 epfd = -1;  // epoll descriptor
+
+void
+runtime_netpollinit(void)
+{
+	epfd = runtime_epollcreate1(EPOLL_CLOEXEC);
+	if(epfd >= 0)
+		return;
+	epfd = runtime_epollcreate(1024);
+	if(epfd >= 0) {
+		runtime_closeonexec(epfd);
+		return;
+	}
+	runtime_printf("netpollinit: failed to create descriptor (%d)\n", -epfd);
+	runtime_throw("netpollinit: failed to create descriptor");
+}
+
+int32
+runtime_netpollopen(uintptr fd, PollDesc *pd)
+{
+	EpollEvent ev;
+	int32 res;
+
+	ev.events = EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET;
+	ev.data.ptr = (void*)pd;
+	res = runtime_epollctl(epfd, EPOLL_CTL_ADD, (int32)fd, &ev);
+	return -res;
+}
+
+int32
+runtime_netpollclose(uintptr fd)
+{
+	EpollEvent ev;
+	int32 res;
+
+	res = runtime_epollctl(epfd, EPOLL_CTL_DEL, (int32)fd, &ev);
+	return -res;
+}
+
+void
+runtime_netpollarm(PollDesc* pd, int32 mode)
+{
+	USED(pd);
+	USED(mode);
+	runtime_throw("unused");
+}
+
+// polls for ready network connections
+// returns list of goroutines that become runnable
+G*
+runtime_netpoll(bool block)
+{
+	static int32 lasterr;
+	EpollEvent events[128], *ev;
+	int32 n, i, waitms, mode;
+	G *gp;
+
+	if(epfd == -1)
+		return nil;
+	waitms = -1;
+	if(!block)
+		waitms = 0;
+retry:
+	n = runtime_epollwait(epfd, events, nelem(events), waitms);
+	if(n < 0) {
+		if(n != -EINTR && n != lasterr) {
+			lasterr = n;
+			runtime_printf("runtime: epollwait on fd %d failed with %d\n", epfd, -n);
+		}
+		goto retry;
+	}
+	gp = nil;
+	for(i = 0; i < n; i++) {
+		ev = &events[i];
+		if(ev->events == 0)
+			continue;
+		mode = 0;
+		if(ev->events & (EPOLLIN|EPOLLRDHUP|EPOLLHUP|EPOLLERR))
+			mode += 'r';
+		if(ev->events & (EPOLLOUT|EPOLLHUP|EPOLLERR))
+			mode += 'w';
+		if(mode)
+			runtime_netpollready(&gp, (void*)ev->data.ptr, mode);
+	}
+	if(block && gp == nil)
+		goto retry;
+	return gp;
+}
+
+void
+runtime_netpoll_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj))
+{
+	USED(wbufp);
+	USED(enqueue1);
+}
diff --git a/third_party/gofrontend/libgo/runtime/netpoll_kqueue.c b/third_party/gofrontend/libgo/runtime/netpoll_kqueue.c
new file mode 100644
index 0000000..5144a87
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/netpoll_kqueue.c
@@ -0,0 +1,118 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+#include "runtime.h"
+#include "defs.h"
+#include "malloc.h"
+
+// Integrated network poller (kqueue-based implementation).
+
+int32	runtime_kqueue(void);
+int32	runtime_kevent(int32, Kevent*, int32, Kevent*, int32, Timespec*);
+void	runtime_closeonexec(int32);
+
+static int32 kq = -1;
+
+void
+runtime_netpollinit(void)
+{
+	kq = runtime_kqueue();
+	if(kq < 0) {
+		runtime_printf("netpollinit: kqueue failed with %d\n", -kq);
+		runtime_throw("netpollinit: kqueue failed");
+	}
+	runtime_closeonexec(kq);
+}
+
+int32
+runtime_netpollopen(uintptr fd, PollDesc *pd)
+{
+	Kevent ev[2];
+	int32 n;
+
+	// Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
+	// for the whole fd lifetime.  The notifications are automatically unregistered
+	// when fd is closed.
+	ev[0].ident = (uint32)fd;
+	ev[0].filter = EVFILT_READ;
+	ev[0].flags = EV_ADD|EV_CLEAR;
+	ev[0].fflags = 0;
+	ev[0].data = 0;
+	ev[0].udata = (kevent_udata)pd;
+	ev[1] = ev[0];
+	ev[1].filter = EVFILT_WRITE;
+	n = runtime_kevent(kq, ev, 2, nil, 0, nil);
+	if(n < 0)
+		return -n;
+	return 0;
+}
+
+int32
+runtime_netpollclose(uintptr fd)
+{
+	// Don't need to unregister because calling close()
+	// on fd will remove any kevents that reference the descriptor.
+	USED(fd);
+	return 0;
+}
+
+void
+runtime_netpollarm(PollDesc* pd, int32 mode)
+{
+	USED(pd, mode);
+	runtime_throw("unused");
+}
+
+// Polls for ready network connections.
+// Returns list of goroutines that become runnable.
+G*
+runtime_netpoll(bool block)
+{
+	static int32 lasterr;
+	Kevent events[64], *ev;
+	Timespec ts, *tp;
+	int32 n, i, mode;
+	G *gp;
+
+	if(kq == -1)
+		return nil;
+	tp = nil;
+	if(!block) {
+		ts.tv_sec = 0;
+		ts.tv_nsec = 0;
+		tp = &ts;
+	}
+	gp = nil;
+retry:
+	n = runtime_kevent(kq, nil, 0, events, nelem(events), tp);
+	if(n < 0) {
+		if(n != -EINTR && n != lasterr) {
+			lasterr = n;
+			runtime_printf("runtime: kevent on fd %d failed with %d\n", kq, -n);
+		}
+		goto retry;
+	}
+	for(i = 0; i < n; i++) {
+		ev = &events[i];
+		mode = 0;
+		if(ev->filter == EVFILT_READ)
+			mode += 'r';
+		if(ev->filter == EVFILT_WRITE)
+			mode += 'w';
+		if(mode)
+			runtime_netpollready(&gp, (PollDesc*)ev->udata, mode);
+	}
+	if(block && gp == nil)
+		goto retry;
+	return gp;
+}
+
+void
+runtime_netpoll_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj))
+{
+	USED(wbufp);
+	USED(enqueue1);
+}
diff --git a/third_party/gofrontend/libgo/runtime/netpoll_select.c b/third_party/gofrontend/libgo/runtime/netpoll_select.c
new file mode 100644
index 0000000..b461335
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/netpoll_select.c
@@ -0,0 +1,252 @@
+// Copyright 2013 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.
+
+// +build solaris
+
+#include "config.h"
+
+#include <errno.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "runtime.h"
+#include "malloc.h"
+
+static Lock selectlock;
+static int rdwake;
+static int wrwake;
+static fd_set fds;
+static PollDesc **data;
+static int allocated;
+
+void
+runtime_netpollinit(void)
+{
+	int p[2];
+	int fl;
+
+	FD_ZERO(&fds);
+	allocated = 128;
+	data = runtime_mallocgc(allocated * sizeof(PollDesc *), 0,
+				FlagNoScan|FlagNoProfiling|FlagNoInvokeGC);
+
+	if(pipe(p) < 0)
+		runtime_throw("netpollinit: failed to create pipe");
+	rdwake = p[0];
+	wrwake = p[1];
+
+	fl = fcntl(rdwake, F_GETFL);
+	if(fl < 0)
+		runtime_throw("netpollinit: fcntl failed");
+	fl |= O_NONBLOCK;
+	if(fcntl(rdwake, F_SETFL, fl))
+		 runtime_throw("netpollinit: fcntl failed");
+	fcntl(rdwake, F_SETFD, FD_CLOEXEC);
+
+	fl = fcntl(wrwake, F_GETFL);
+	if(fl < 0)
+		runtime_throw("netpollinit: fcntl failed");
+	fl |= O_NONBLOCK;
+	if(fcntl(wrwake, F_SETFL, fl))
+		 runtime_throw("netpollinit: fcntl failed");
+	fcntl(wrwake, F_SETFD, FD_CLOEXEC);
+
+	FD_SET(rdwake, &fds);
+}
+
+int32
+runtime_netpollopen(uintptr fd, PollDesc *pd)
+{
+	byte b;
+
+	runtime_lock(&selectlock);
+
+	if((int)fd >= allocated) {
+		int c;
+		PollDesc **n;
+
+		c = allocated;
+
+		runtime_unlock(&selectlock);
+
+		while((int)fd >= c)
+			c *= 2;
+		n = runtime_mallocgc(c * sizeof(PollDesc *), 0,
+				     FlagNoScan|FlagNoProfiling|FlagNoInvokeGC);
+
+		runtime_lock(&selectlock);
+
+		if(c > allocated) {
+			__builtin_memcpy(n, data, allocated * sizeof(PollDesc *));
+			allocated = c;
+			data = n;
+		}
+	}
+	FD_SET(fd, &fds);
+	data[fd] = pd;
+
+	runtime_unlock(&selectlock);
+
+	b = 0;
+	write(wrwake, &b, sizeof b);
+
+	return 0;
+}
+
+int32
+runtime_netpollclose(uintptr fd)
+{
+	byte b;
+
+	runtime_lock(&selectlock);
+
+	FD_CLR(fd, &fds);
+	data[fd] = nil;
+
+	runtime_unlock(&selectlock);
+
+	b = 0;
+	write(wrwake, &b, sizeof b);
+
+	return 0;
+}
+
+/* Used to avoid using too much stack memory.  */
+static bool inuse;
+static fd_set grfds, gwfds, gefds, gtfds;
+
+G*
+runtime_netpoll(bool block)
+{
+	fd_set *prfds, *pwfds, *pefds, *ptfds;
+	bool allocatedfds;
+	struct timeval timeout;
+	struct timeval *pt;
+	int max, c, i;
+	G *gp;
+	int32 mode;
+	byte b;
+	struct stat st;
+
+ retry:
+	runtime_lock(&selectlock);
+
+	max = allocated;
+
+	if(max == 0) {
+		runtime_unlock(&selectlock);
+		return nil;
+	}
+
+	if(inuse) {
+		prfds = runtime_SysAlloc(4 * sizeof fds, &mstats.other_sys);
+		pwfds = prfds + 1;
+		pefds = pwfds + 1;
+		ptfds = pefds + 1;
+		allocatedfds = true;
+	} else {
+		prfds = &grfds;
+		pwfds = &gwfds;
+		pefds = &gefds;
+		ptfds = &gtfds;
+		inuse = true;
+		allocatedfds = false;
+	}
+
+	__builtin_memcpy(prfds, &fds, sizeof fds);
+
+	runtime_unlock(&selectlock);
+
+	__builtin_memcpy(pwfds, prfds, sizeof fds);
+	FD_CLR(rdwake, pwfds);
+	__builtin_memcpy(pefds, pwfds, sizeof fds);
+
+	__builtin_memcpy(ptfds, pwfds, sizeof fds);
+
+	__builtin_memset(&timeout, 0, sizeof timeout);
+	pt = &timeout;
+	if(block)
+		pt = nil;
+
+	c = select(max, prfds, pwfds, pefds, pt);
+	if(c < 0) {
+		if(errno == EBADF) {
+			// Some file descriptor has been closed.
+			// Check each one, and treat each closed
+			// descriptor as ready for read/write.
+			c = 0;
+			FD_ZERO(prfds);
+			FD_ZERO(pwfds);
+			FD_ZERO(pefds);
+			for(i = 0; i < max; i++) {
+				if(FD_ISSET(i, ptfds)
+				   && fstat(i, &st) < 0
+				   && errno == EBADF) {
+					FD_SET(i, prfds);
+					FD_SET(i, pwfds);
+					c += 2;
+				}
+			}
+		}
+		else {
+			if(errno != EINTR)
+				runtime_printf("runtime: select failed with %d\n", errno);
+			goto retry;
+		}
+	}
+	gp = nil;
+	for(i = 0; i < max && c > 0; i++) {
+		mode = 0;
+		if(FD_ISSET(i, prfds)) {
+			mode += 'r';
+			--c;
+		}
+		if(FD_ISSET(i, pwfds)) {
+			mode += 'w';
+			--c;
+		}
+		if(FD_ISSET(i, pefds)) {
+			mode = 'r' + 'w';
+			--c;
+		}
+		if(i == rdwake) {
+			while(read(rdwake, &b, sizeof b) > 0)
+				;
+			continue;
+		}
+		if(mode) {
+			PollDesc *pd;
+
+			runtime_lock(&selectlock);
+			pd = data[i];
+			runtime_unlock(&selectlock);
+			if(pd != nil)
+				runtime_netpollready(&gp, pd, mode);
+		}
+	}
+	if(block && gp == nil)
+		goto retry;
+
+	if(allocatedfds) {
+		runtime_SysFree(prfds, 4 * sizeof fds, &mstats.other_sys);
+	} else {
+		runtime_lock(&selectlock);
+		inuse = false;
+		runtime_unlock(&selectlock);
+	}
+
+	return gp;
+}
+
+void
+runtime_netpoll_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj))
+{
+	enqueue1(wbufp, (Obj){(byte*)&data, sizeof data, 0});
+}
diff --git a/third_party/gofrontend/libgo/runtime/netpoll_stub.c b/third_party/gofrontend/libgo/runtime/netpoll_stub.c
new file mode 100644
index 0000000..468a610
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/netpoll_stub.c
@@ -0,0 +1,26 @@
+// Copyright 2013 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.
+
+// +build plan9
+
+#include "runtime.h"
+#include "malloc.h"
+
+// Polls for ready network connections.
+// Returns list of goroutines that become runnable.
+G*
+runtime_netpoll(bool block)
+{
+	// Implementation for platforms that do not support
+	// integrated network poller.
+	USED(block);
+	return nil;
+}
+
+void
+runtime_netpoll_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj))
+{
+	USED(wbufp);
+	USED(addroot);
+}
diff --git a/third_party/gofrontend/libgo/runtime/panic.c b/third_party/gofrontend/libgo/runtime/panic.c
new file mode 100644
index 0000000..de000db
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/panic.c
@@ -0,0 +1,232 @@
+// 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 "runtime.h"
+#include "malloc.h"
+#include "go-defer.h"
+#include "go-panic.h"
+
+// Code related to defer, panic and recover.
+
+uint32 runtime_panicking;
+static Lock paniclk;
+
+// Allocate a Defer, usually using per-P pool.
+// Each defer must be released with freedefer.
+Defer*
+runtime_newdefer()
+{
+	Defer *d;
+	P *p;
+
+	d = nil;
+	p = runtime_m()->p;
+	d = p->deferpool;
+	if(d)
+		p->deferpool = d->__next;
+	if(d == nil) {
+		// deferpool is empty
+		d = runtime_malloc(sizeof(Defer));
+	}
+	return d;
+}
+
+// Free the given defer.
+// The defer cannot be used after this call.
+void
+runtime_freedefer(Defer *d)
+{
+	P *p;
+
+	if(d->__special)
+		return;
+	p = runtime_m()->p;
+	d->__next = p->deferpool;
+	p->deferpool = d;
+	// No need to wipe out pointers in argp/pc/fn/args,
+	// because we empty the pool before GC.
+}
+
+// Run all deferred functions for the current goroutine.
+// This is noinline for go_can_recover.
+static void __go_rundefer (void) __attribute__ ((noinline));
+static void
+__go_rundefer(void)
+{
+	G *g;
+	Defer *d;
+
+	g = runtime_g();
+	while((d = g->defer) != nil) {
+		void (*pfn)(void*);
+
+		g->defer = d->__next;
+		pfn = d->__pfn;
+		d->__pfn = nil;
+		if (pfn != nil)
+			(*pfn)(d->__arg);
+		runtime_freedefer(d);
+	}
+}
+
+void
+runtime_startpanic(void)
+{
+	M *m;
+
+	m = runtime_m();
+	if(runtime_mheap.cachealloc.size == 0) { // very early
+		runtime_printf("runtime: panic before malloc heap initialized\n");
+		m->mallocing = 1; // tell rest of panic not to try to malloc
+	} else if(m->mcache == nil) // can happen if called from signal handler or throw
+		m->mcache = runtime_allocmcache();
+	switch(m->dying) {
+	case 0:
+		m->dying = 1;
+		if(runtime_g() != nil)
+			runtime_g()->writebuf = nil;
+		runtime_xadd(&runtime_panicking, 1);
+		runtime_lock(&paniclk);
+		if(runtime_debug.schedtrace > 0 || runtime_debug.scheddetail > 0)
+			runtime_schedtrace(true);
+		runtime_freezetheworld();
+		return;
+	case 1:
+		// Something failed while panicing, probably the print of the
+		// argument to panic().  Just print a stack trace and exit.
+		m->dying = 2;
+		runtime_printf("panic during panic\n");
+		runtime_dopanic(0);
+		runtime_exit(3);
+	case 2:
+		// This is a genuine bug in the runtime, we couldn't even
+		// print the stack trace successfully.
+		m->dying = 3;
+		runtime_printf("stack trace unavailable\n");
+		runtime_exit(4);
+	default:
+		// Can't even print!  Just exit.
+		runtime_exit(5);
+	}
+}
+
+void
+runtime_dopanic(int32 unused __attribute__ ((unused)))
+{
+	G *g;
+	static bool didothers;
+	bool crash;
+	int32 t;
+
+	g = runtime_g();
+	if(g->sig != 0)
+		runtime_printf("[signal %x code=%p addr=%p]\n",
+			       g->sig, (void*)g->sigcode0, (void*)g->sigcode1);
+
+	if((t = runtime_gotraceback(&crash)) > 0){
+		if(g != runtime_m()->g0) {
+			runtime_printf("\n");
+			runtime_goroutineheader(g);
+			runtime_traceback();
+			runtime_printcreatedby(g);
+		} else if(t >= 2 || runtime_m()->throwing > 0) {
+			runtime_printf("\nruntime stack:\n");
+			runtime_traceback();
+		}
+		if(!didothers) {
+			didothers = true;
+			runtime_tracebackothers(g);
+		}
+	}
+	runtime_unlock(&paniclk);
+	if(runtime_xadd(&runtime_panicking, -1) != 0) {
+		// Some other m is panicking too.
+		// Let it print what it needs to print.
+		// Wait forever without chewing up cpu.
+		// It will exit when it's done.
+		static Lock deadlock;
+		runtime_lock(&deadlock);
+		runtime_lock(&deadlock);
+	}
+	
+	if(crash)
+		runtime_crash();
+
+	runtime_exit(2);
+}
+
+bool
+runtime_canpanic(G *gp)
+{
+	M *m = runtime_m();
+	byte g;
+
+	USED(&g);  // don't use global g, it points to gsignal
+
+	// Is it okay for gp to panic instead of crashing the program?
+	// Yes, as long as it is running Go code, not runtime code,
+	// and not stuck in a system call.
+	if(gp == nil || gp != m->curg)
+		return false;
+	if(m->locks-m->softfloat != 0 || m->mallocing != 0 || m->throwing != 0 || m->gcing != 0 || m->dying != 0)
+		return false;
+	if(gp->status != Grunning)
+		return false;
+#ifdef GOOS_windows
+	if(m->libcallsp != 0)
+		return false;
+#endif
+	return true;
+}
+
+void
+runtime_throw(const char *s)
+{
+	M *mp;
+
+	mp = runtime_m();
+	if(mp->throwing == 0)
+		mp->throwing = 1;
+	runtime_startpanic();
+	runtime_printf("fatal error: %s\n", s);
+	runtime_dopanic(0);
+	*(int32*)0 = 0;	// not reached
+	runtime_exit(1);	// even more not reached
+}
+
+void
+runtime_panicstring(const char *s)
+{
+	Eface err;
+
+	if(runtime_m()->mallocing) {
+		runtime_printf("panic: %s\n", s);
+		runtime_throw("panic during malloc");
+	}
+	if(runtime_m()->gcing) {
+		runtime_printf("panic: %s\n", s);
+		runtime_throw("panic during gc");
+	}
+	if(runtime_m()->locks) {
+		runtime_printf("panic: %s\n", s);
+		runtime_throw("panic holding locks");
+	}
+	runtime_newErrorCString(s, &err);
+	runtime_panic(err);
+}
+
+void runtime_Goexit (void) __asm__ (GOSYM_PREFIX "runtime.Goexit");
+
+void
+runtime_Goexit(void)
+{
+	__go_rundefer();
+	runtime_goexit();
+}
+
+void
+runtime_panicdivide(void)
+{
+	runtime_panicstring("integer divide by zero");
+}
diff --git a/third_party/gofrontend/libgo/runtime/parfor.c b/third_party/gofrontend/libgo/runtime/parfor.c
new file mode 100644
index 0000000..386faea
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/parfor.c
@@ -0,0 +1,199 @@
+// 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.
+
+// Parallel for algorithm.
+
+#include "runtime.h"
+#include "arch.h"
+
+struct ParForThread
+{
+	// the thread's iteration space [32lsb, 32msb)
+	uint64 pos;
+	// stats
+	uint64 nsteal;
+	uint64 nstealcnt;
+	uint64 nprocyield;
+	uint64 nosyield;
+	uint64 nsleep;
+	byte pad[CacheLineSize];
+};
+
+ParFor*
+runtime_parforalloc(uint32 nthrmax)
+{
+	ParFor *desc;
+
+	// The ParFor object is followed by CacheLineSize padding
+	// and then nthrmax ParForThread.
+	desc = (ParFor*)runtime_malloc(sizeof(ParFor) + CacheLineSize + nthrmax * sizeof(ParForThread));
+	desc->thr = (ParForThread*)((byte*)(desc+1) + CacheLineSize);
+	desc->nthrmax = nthrmax;
+	return desc;
+}
+
+void
+runtime_parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32))
+{
+	uint32 i, begin, end;
+	uint64 *pos;
+
+	if(desc == nil || nthr == 0 || nthr > desc->nthrmax || body == nil) {
+		runtime_printf("desc=%p nthr=%d count=%d body=%p\n", desc, nthr, n, body);
+		runtime_throw("parfor: invalid args");
+	}
+
+	desc->body = body;
+	desc->done = 0;
+	desc->nthr = nthr;
+	desc->thrseq = 0;
+	desc->cnt = n;
+	desc->ctx = ctx;
+	desc->wait = wait;
+	desc->nsteal = 0;
+	desc->nstealcnt = 0;
+	desc->nprocyield = 0;
+	desc->nosyield = 0;
+	desc->nsleep = 0;
+	for(i=0; i<nthr; i++) {
+		begin = (uint64)n*i / nthr;
+		end = (uint64)n*(i+1) / nthr;
+		pos = &desc->thr[i].pos;
+		if(((uintptr)pos & 7) != 0)
+			runtime_throw("parforsetup: pos is not aligned");
+		*pos = (uint64)begin | (((uint64)end)<<32);
+	}
+}
+
+void
+runtime_parfordo(ParFor *desc)
+{
+	ParForThread *me;
+	uint32 tid, begin, end, begin2, try, victim, i;
+	uint64 *mypos, *victimpos, pos, newpos;
+	void (*body)(ParFor*, uint32);
+	bool idle;
+
+	// Obtain 0-based thread index.
+	tid = runtime_xadd(&desc->thrseq, 1) - 1;
+	if(tid >= desc->nthr) {
+		runtime_printf("tid=%d nthr=%d\n", tid, desc->nthr);
+		runtime_throw("parfor: invalid tid");
+	}
+
+	// If single-threaded, just execute the for serially.
+	if(desc->nthr==1) {
+		for(i=0; i<desc->cnt; i++)
+			desc->body(desc, i);
+		return;
+	}
+
+	body = desc->body;
+	me = &desc->thr[tid];
+	mypos = &me->pos;
+	for(;;) {
+		for(;;) {
+			// While there is local work,
+			// bump low index and execute the iteration.
+			pos = runtime_xadd64(mypos, 1);
+			begin = (uint32)pos-1;
+			end = (uint32)(pos>>32);
+			if(begin < end) {
+				body(desc, begin);
+				continue;
+			}
+			break;
+		}
+
+		// Out of work, need to steal something.
+		idle = false;
+		for(try=0;; try++) {
+			// If we don't see any work for long enough,
+			// increment the done counter...
+			if(try > desc->nthr*4 && !idle) {
+				idle = true;
+				runtime_xadd(&desc->done, 1);
+			}
+			// ...if all threads have incremented the counter,
+			// we are done.
+			if(desc->done + !idle == desc->nthr) {
+				if(!idle)
+					runtime_xadd(&desc->done, 1);
+				goto exit;
+			}
+			// Choose a random victim for stealing.
+			victim = runtime_fastrand1() % (desc->nthr-1);
+			if(victim >= tid)
+				victim++;
+			victimpos = &desc->thr[victim].pos;
+			for(;;) {
+				// See if it has any work.
+				pos = runtime_atomicload64(victimpos);
+				begin = (uint32)pos;
+				end = (uint32)(pos>>32);
+				if(begin+1 >= end) {
+					begin = end = 0;
+					break;
+				}
+				if(idle) {
+					runtime_xadd(&desc->done, -1);
+					idle = false;
+				}
+				begin2 = begin + (end-begin)/2;
+				newpos = (uint64)begin | (uint64)begin2<<32;
+				if(runtime_cas64(victimpos, pos, newpos)) {
+					begin = begin2;
+					break;
+				}
+			}
+			if(begin < end) {
+				// Has successfully stolen some work.
+				if(idle)
+					runtime_throw("parfor: should not be idle");
+				runtime_atomicstore64(mypos, (uint64)begin | (uint64)end<<32);
+				me->nsteal++;
+				me->nstealcnt += end-begin;
+				break;
+			}
+			// Backoff.
+			if(try < desc->nthr) {
+				// nothing
+			} else if (try < 4*desc->nthr) {
+				me->nprocyield++;
+				runtime_procyield(20);
+			// If a caller asked not to wait for the others, exit now
+			// (assume that most work is already done at this point).
+			} else if (!desc->wait) {
+				if(!idle)
+					runtime_xadd(&desc->done, 1);
+				goto exit;
+			} else if (try < 6*desc->nthr) {
+				me->nosyield++;
+				runtime_osyield();
+			} else {
+				me->nsleep++;
+				runtime_usleep(1);
+			}
+		}
+	}
+exit:
+	runtime_xadd64(&desc->nsteal, me->nsteal);
+	runtime_xadd64(&desc->nstealcnt, me->nstealcnt);
+	runtime_xadd64(&desc->nprocyield, me->nprocyield);
+	runtime_xadd64(&desc->nosyield, me->nosyield);
+	runtime_xadd64(&desc->nsleep, me->nsleep);
+	me->nsteal = 0;
+	me->nstealcnt = 0;
+	me->nprocyield = 0;
+	me->nosyield = 0;
+	me->nsleep = 0;
+}
+
+// For testing from Go.
+void
+runtime_parforiters(ParFor *desc, uintptr tid, uintptr *start, uintptr *end)
+{
+	*start = (uint32)desc->thr[tid].pos;
+	*end = (uint32)(desc->thr[tid].pos>>32);
+}
diff --git a/third_party/gofrontend/libgo/runtime/print.c b/third_party/gofrontend/libgo/runtime/print.c
new file mode 100644
index 0000000..69b1f81
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/print.c
@@ -0,0 +1,372 @@
+// 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.
+
+#include <complex.h>
+#include <math.h>
+#include <stdarg.h>
+#include "runtime.h"
+#include "array.h"
+#include "go-type.h"
+
+//static Lock debuglock;
+
+// Clang requires this function to not be inlined (see below).
+static void go_vprintf(const char*, va_list)
+__attribute__((noinline));
+
+// write to goroutine-local buffer if diverting output,
+// or else standard error.
+static void
+gwrite(const void *v, intgo n)
+{
+	G* g = runtime_g();
+
+	if(g == nil || g->writebuf == nil) {
+		// Avoid -D_FORTIFY_SOURCE problems.
+		int rv __attribute__((unused));
+
+		rv = runtime_write(2, v, n);
+		return;
+	}
+
+	if(g->writenbuf == 0)
+		return;
+
+	if(n > g->writenbuf)
+		n = g->writenbuf;
+	runtime_memmove(g->writebuf, v, n);
+	g->writebuf += n;
+	g->writenbuf -= n;
+}
+
+void
+runtime_dump(byte *p, int32 n)
+{
+	int32 i;
+
+	for(i=0; i<n; i++) {
+		runtime_printpointer((byte*)(uintptr)(p[i]>>4));
+		runtime_printpointer((byte*)(uintptr)(p[i]&0xf));
+		if((i&15) == 15)
+			runtime_prints("\n");
+		else
+			runtime_prints(" ");
+	}
+	if(n & 15)
+		runtime_prints("\n");
+}
+
+void
+runtime_prints(const char *s)
+{
+	gwrite(s, runtime_findnull((const byte*)s));
+}
+
+#if defined (__clang__) && (defined (__i386__) || defined (__x86_64__))
+// LLVM's code generator does not currently support split stacks for vararg
+// functions, so we disable the feature for this function under Clang. This
+// appears to be OK as long as:
+// - this function only calls non-inlined, internal-linkage (hence no dynamic
+//   loader) functions compiled with split stacks (i.e. go_vprintf), which can
+//   allocate more stack space as required;
+// - this function itself does not occupy more than BACKOFF bytes of stack space
+//   (see libgcc/config/i386/morestack.S).
+// These conditions are currently known to be satisfied by Clang on x86-32 and
+// x86-64. Note that signal handlers receive slightly less stack space than they
+// would normally do if they happen to be called while this function is being
+// run. If this turns out to be a problem we could consider increasing BACKOFF.
+
+void
+runtime_printf(const char *s, ...)
+__attribute__((no_split_stack));
+
+int32
+runtime_snprintf(byte *buf, int32 n, const char *s, ...)
+__attribute__((no_split_stack));
+
+#endif
+
+void
+runtime_printf(const char *s, ...)
+{
+	va_list va;
+
+	va_start(va, s);
+	go_vprintf(s, va);
+	va_end(va);
+}
+
+int32
+runtime_snprintf(byte *buf, int32 n, const char *s, ...)
+{
+	G *g = runtime_g();
+	va_list va;
+	int32 m;
+
+	g->writebuf = buf;
+	g->writenbuf = n-1;
+	va_start(va, s);
+	go_vprintf(s, va);
+	va_end(va);
+	*g->writebuf = '\0';
+	m = g->writebuf - buf;
+	g->writenbuf = 0;
+	g->writebuf = nil;
+	return m;
+}
+
+// Very simple printf.  Only for debugging prints.
+// Do not add to this without checking with Rob.
+static void
+go_vprintf(const char *s, va_list va)
+{
+	const char *p, *lp;
+
+	//runtime_lock(&debuglock);
+
+	lp = p = s;
+	for(; *p; p++) {
+		if(*p != '%')
+			continue;
+		if(p > lp)
+			gwrite(lp, p-lp);
+		p++;
+		switch(*p) {
+		case 'a':
+			runtime_printslice(va_arg(va, Slice));
+			break;
+		case 'c':
+			runtime_printbyte(va_arg(va, int32));
+			break;
+		case 'd':
+			runtime_printint(va_arg(va, int32));
+			break;
+		case 'D':
+			runtime_printint(va_arg(va, int64));
+			break;
+		case 'e':
+			runtime_printeface(va_arg(va, Eface));
+			break;
+		case 'f':
+			runtime_printfloat(va_arg(va, float64));
+			break;
+		case 'C':
+			runtime_printcomplex(va_arg(va, complex double));
+			break;
+		case 'i':
+			runtime_printiface(va_arg(va, Iface));
+			break;
+		case 'p':
+			runtime_printpointer(va_arg(va, void*));
+			break;
+		case 's':
+			runtime_prints(va_arg(va, char*));
+			break;
+		case 'S':
+			runtime_printstring(va_arg(va, String));
+			break;
+		case 't':
+			runtime_printbool(va_arg(va, int));
+			break;
+		case 'U':
+			runtime_printuint(va_arg(va, uint64));
+			break;
+		case 'x':
+			runtime_printhex(va_arg(va, uint32));
+			break;
+		case 'X':
+			runtime_printhex(va_arg(va, uint64));
+			break;
+		}
+		lp = p+1;
+	}
+	if(p > lp)
+		gwrite(lp, p-lp);
+
+	//runtime_unlock(&debuglock);
+}
+
+void
+runtime_printpc(void *p __attribute__ ((unused)))
+{
+	runtime_prints("PC=");
+	runtime_printhex((uint64)(uintptr)runtime_getcallerpc(p));
+}
+
+void
+runtime_printbool(_Bool v)
+{
+	if(v) {
+		gwrite("true", 4);
+		return;
+	}
+	gwrite("false", 5);
+}
+
+void
+runtime_printbyte(int8 c)
+{
+	gwrite(&c, 1);
+}
+
+void
+runtime_printfloat(double v)
+{
+	byte buf[20];
+	int32 e, s, i, n;
+	float64 h;
+
+	if(ISNAN(v)) {
+		gwrite("NaN", 3);
+		return;
+	}
+	if(isinf(v)) {
+		if(signbit(v)) {
+			gwrite("-Inf", 4);
+		} else {
+			gwrite("+Inf", 4);
+		}
+		return;
+	}
+
+	n = 7;	// digits printed
+	e = 0;	// exp
+	s = 0;	// sign
+	if(v == 0) {
+		if(isinf(1/v) && 1/v < 0)
+			s = 1;
+	} else {
+		// sign
+		if(v < 0) {
+			v = -v;
+			s = 1;
+		}
+
+		// normalize
+		while(v >= 10) {
+			e++;
+			v /= 10;
+		}
+		while(v < 1) {
+			e--;
+			v *= 10;
+		}
+
+		// round
+		h = 5;
+		for(i=0; i<n; i++)
+			h /= 10;
+
+		v += h;
+		if(v >= 10) {
+			e++;
+			v /= 10;
+		}
+	}
+
+	// format +d.dddd+edd
+	buf[0] = '+';
+	if(s)
+		buf[0] = '-';
+	for(i=0; i<n; i++) {
+		s = v;
+		buf[i+2] = s+'0';
+		v -= s;
+		v *= 10.;
+	}
+	buf[1] = buf[2];
+	buf[2] = '.';
+
+	buf[n+2] = 'e';
+	buf[n+3] = '+';
+	if(e < 0) {
+		e = -e;
+		buf[n+3] = '-';
+	}
+
+	buf[n+4] = (e/100) + '0';
+	buf[n+5] = (e/10)%10 + '0';
+	buf[n+6] = (e%10) + '0';
+	gwrite(buf, n+7);
+}
+
+void
+runtime_printcomplex(complex double v)
+{
+	gwrite("(", 1);
+	runtime_printfloat(creal(v));
+	runtime_printfloat(cimag(v));
+	gwrite("i)", 2);
+}
+
+void
+runtime_printuint(uint64 v)
+{
+	byte buf[100];
+	int32 i;
+
+	for(i=nelem(buf)-1; i>0; i--) {
+		buf[i] = v%10 + '0';
+		if(v < 10)
+			break;
+		v = v/10;
+	}
+	gwrite(buf+i, nelem(buf)-i);
+}
+
+void
+runtime_printint(int64 v)
+{
+	if(v < 0) {
+		gwrite("-", 1);
+		v = -v;
+	}
+	runtime_printuint(v);
+}
+
+void
+runtime_printhex(uint64 v)
+{
+	static const char *dig = "0123456789abcdef";
+	byte buf[100];
+	int32 i;
+
+	i=nelem(buf);
+	for(; v>0; v/=16)
+		buf[--i] = dig[v%16];
+	if(i == nelem(buf))
+		buf[--i] = '0';
+	buf[--i] = 'x';
+	buf[--i] = '0';
+	gwrite(buf+i, nelem(buf)-i);
+}
+
+void
+runtime_printpointer(void *p)
+{
+	runtime_printhex((uintptr)p);
+}
+
+void
+runtime_printstring(String v)
+{
+	// if(v.len > runtime_maxstring) {
+	//	gwrite("[string too long]", 17);
+	//	return;
+	// }
+	if(v.len > 0)
+		gwrite(v.str, v.len);
+}
+
+void
+__go_print_space(void)
+{
+	gwrite(" ", 1);
+}
+
+void
+__go_print_nl(void)
+{
+	gwrite("\n", 1);
+}
diff --git a/third_party/gofrontend/libgo/runtime/proc.c b/third_party/gofrontend/libgo/runtime/proc.c
new file mode 100644
index 0000000..146f285
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/proc.c
@@ -0,0 +1,3344 @@
+// 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.
+
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include "config.h"
+
+#ifdef HAVE_DL_ITERATE_PHDR
+#include <link.h>
+#endif
+
+#include "runtime.h"
+#include "arch.h"
+#include "defs.h"
+#include "malloc.h"
+#include "race.h"
+#include "go-type.h"
+#include "go-defer.h"
+
+#ifdef USING_SPLIT_STACK
+
+/* FIXME: These are not declared anywhere.  */
+
+extern void __splitstack_getcontext(void *context[10]);
+
+extern void __splitstack_setcontext(void *context[10]);
+
+extern void *__splitstack_makecontext(size_t, void *context[10], size_t *);
+
+extern void * __splitstack_resetcontext(void *context[10], size_t *);
+
+extern void *__splitstack_find(void *, void *, size_t *, void **, void **,
+			       void **);
+
+extern void __splitstack_block_signals (int *, int *);
+
+extern void __splitstack_block_signals_context (void *context[10], int *,
+						int *);
+
+#endif
+
+#ifndef PTHREAD_STACK_MIN
+# define PTHREAD_STACK_MIN 8192
+#endif
+
+#if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK)
+# define StackMin PTHREAD_STACK_MIN
+#else
+# define StackMin 2 * 1024 * 1024
+#endif
+
+uintptr runtime_stacks_sys;
+
+static void gtraceback(G*);
+
+#ifdef __rtems__
+#define __thread
+#endif
+
+static __thread G *g;
+static __thread M *m;
+
+#ifndef SETCONTEXT_CLOBBERS_TLS
+
+static inline void
+initcontext(void)
+{
+}
+
+static inline void
+fixcontext(ucontext_t *c __attribute__ ((unused)))
+{
+}
+
+#else
+
+# if defined(__x86_64__) && defined(__sun__)
+
+// x86_64 Solaris 10 and 11 have a bug: setcontext switches the %fs
+// register to that of the thread which called getcontext.  The effect
+// is that the address of all __thread variables changes.  This bug
+// also affects pthread_self() and pthread_getspecific.  We work
+// around it by clobbering the context field directly to keep %fs the
+// same.
+
+static __thread greg_t fs;
+
+static inline void
+initcontext(void)
+{
+	ucontext_t c;
+
+	getcontext(&c);
+	fs = c.uc_mcontext.gregs[REG_FSBASE];
+}
+
+static inline void
+fixcontext(ucontext_t* c)
+{
+	c->uc_mcontext.gregs[REG_FSBASE] = fs;
+}
+
+# elif defined(__NetBSD__)
+
+// NetBSD has a bug: setcontext clobbers tlsbase, we need to save
+// and restore it ourselves.
+
+static __thread __greg_t tlsbase;
+
+static inline void
+initcontext(void)
+{
+	ucontext_t c;
+
+	getcontext(&c);
+	tlsbase = c.uc_mcontext._mc_tlsbase;
+}
+
+static inline void
+fixcontext(ucontext_t* c)
+{
+	c->uc_mcontext._mc_tlsbase = tlsbase;
+}
+
+# else
+
+#  error unknown case for SETCONTEXT_CLOBBERS_TLS
+
+# endif
+
+#endif
+
+// We can not always refer to the TLS variables directly.  The
+// compiler will call tls_get_addr to get the address of the variable,
+// and it may hold it in a register across a call to schedule.  When
+// we get back from the call we may be running in a different thread,
+// in which case the register now points to the TLS variable for a
+// different thread.  We use non-inlinable functions to avoid this
+// when necessary.
+
+G* runtime_g(void) __attribute__ ((noinline, no_split_stack));
+
+G*
+runtime_g(void)
+{
+	return g;
+}
+
+M* runtime_m(void) __attribute__ ((noinline, no_split_stack));
+
+M*
+runtime_m(void)
+{
+	return m;
+}
+
+// Set m and g.
+void
+runtime_setmg(M* mp, G* gp)
+{
+	m = mp;
+	g = gp;
+}
+
+// Start a new thread.
+static void
+runtime_newosproc(M *mp)
+{
+	pthread_attr_t attr;
+	sigset_t clear, old;
+	pthread_t tid;
+	int ret;
+
+	if(pthread_attr_init(&attr) != 0)
+		runtime_throw("pthread_attr_init");
+	if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
+		runtime_throw("pthread_attr_setdetachstate");
+
+	// Block signals during pthread_create so that the new thread
+	// starts with signals disabled.  It will enable them in minit.
+	sigfillset(&clear);
+
+#ifdef SIGTRAP
+	// Blocking SIGTRAP reportedly breaks gdb on Alpha GNU/Linux.
+	sigdelset(&clear, SIGTRAP);
+#endif
+
+	sigemptyset(&old);
+	pthread_sigmask(SIG_BLOCK, &clear, &old);
+	ret = pthread_create(&tid, &attr, runtime_mstart, mp);
+	pthread_sigmask(SIG_SETMASK, &old, nil);
+
+	if (ret != 0)
+		runtime_throw("pthread_create");
+}
+
+// First function run by a new goroutine.  This replaces gogocall.
+static void
+kickoff(void)
+{
+	void (*fn)(void*);
+
+	if(g->traceback != nil)
+		gtraceback(g);
+
+	fn = (void (*)(void*))(g->entry);
+	fn(g->param);
+	runtime_goexit();
+}
+
+// Switch context to a different goroutine.  This is like longjmp.
+void runtime_gogo(G*) __attribute__ ((noinline));
+void
+runtime_gogo(G* newg)
+{
+#ifdef USING_SPLIT_STACK
+	__splitstack_setcontext(&newg->stack_context[0]);
+#endif
+	g = newg;
+	newg->fromgogo = true;
+	fixcontext(&newg->context);
+	setcontext(&newg->context);
+	runtime_throw("gogo setcontext returned");
+}
+
+// Save context and call fn passing g as a parameter.  This is like
+// setjmp.  Because getcontext always returns 0, unlike setjmp, we use
+// g->fromgogo as a code.  It will be true if we got here via
+// setcontext.  g == nil the first time this is called in a new m.
+void runtime_mcall(void (*)(G*)) __attribute__ ((noinline));
+void
+runtime_mcall(void (*pfn)(G*))
+{
+	M *mp;
+	G *gp;
+
+	// Ensure that all registers are on the stack for the garbage
+	// collector.
+	__builtin_unwind_init();
+
+	mp = m;
+	gp = g;
+	if(gp == mp->g0)
+		runtime_throw("runtime: mcall called on m->g0 stack");
+
+	if(gp != nil) {
+
+#ifdef USING_SPLIT_STACK
+		__splitstack_getcontext(&g->stack_context[0]);
+#else
+		gp->gcnext_sp = &pfn;
+#endif
+		gp->fromgogo = false;
+		getcontext(&gp->context);
+
+		// When we return from getcontext, we may be running
+		// in a new thread.  That means that m and g may have
+		// changed.  They are global variables so we will
+		// reload them, but the addresses of m and g may be
+		// cached in our local stack frame, and those
+		// addresses may be wrong.  Call functions to reload
+		// the values for this thread.
+		mp = runtime_m();
+		gp = runtime_g();
+
+		if(gp->traceback != nil)
+			gtraceback(gp);
+	}
+	if (gp == nil || !gp->fromgogo) {
+#ifdef USING_SPLIT_STACK
+		__splitstack_setcontext(&mp->g0->stack_context[0]);
+#endif
+		mp->g0->entry = (byte*)pfn;
+		mp->g0->param = gp;
+
+		// It's OK to set g directly here because this case
+		// can not occur if we got here via a setcontext to
+		// the getcontext call just above.
+		g = mp->g0;
+
+		fixcontext(&mp->g0->context);
+		setcontext(&mp->g0->context);
+		runtime_throw("runtime: mcall function returned");
+	}
+}
+
+// Goroutine scheduler
+// The scheduler's job is to distribute ready-to-run goroutines over worker threads.
+//
+// The main concepts are:
+// G - goroutine.
+// M - worker thread, or machine.
+// P - processor, a resource that is required to execute Go code.
+//     M must have an associated P to execute Go code, however it can be
+//     blocked or in a syscall w/o an associated P.
+//
+// Design doc at http://golang.org/s/go11sched.
+
+typedef struct Sched Sched;
+struct Sched {
+	Lock	lock;
+
+	uint64	goidgen;
+	M*	midle;	 // idle m's waiting for work
+	int32	nmidle;	 // number of idle m's waiting for work
+	int32	nmidlelocked; // number of locked m's waiting for work
+	int32	mcount;	 // number of m's that have been created
+	int32	maxmcount;	// maximum number of m's allowed (or die)
+
+	P*	pidle;  // idle P's
+	uint32	npidle;
+	uint32	nmspinning;
+
+	// Global runnable queue.
+	G*	runqhead;
+	G*	runqtail;
+	int32	runqsize;
+
+	// Global cache of dead G's.
+	Lock	gflock;
+	G*	gfree;
+
+	uint32	gcwaiting;	// gc is waiting to run
+	int32	stopwait;
+	Note	stopnote;
+	uint32	sysmonwait;
+	Note	sysmonnote;
+	uint64	lastpoll;
+
+	int32	profilehz;	// cpu profiling rate
+};
+
+enum
+{
+	// The max value of GOMAXPROCS.
+	// There are no fundamental restrictions on the value.
+	MaxGomaxprocs = 1<<8,
+
+	// Number of goroutine ids to grab from runtime_sched.goidgen to local per-P cache at once.
+	// 16 seems to provide enough amortization, but other than that it's mostly arbitrary number.
+	GoidCacheBatch = 16,
+};
+
+Sched	runtime_sched;
+int32	runtime_gomaxprocs;
+uint32	runtime_needextram = 1;
+bool	runtime_iscgo = true;
+M	runtime_m0;
+G	runtime_g0;	// idle goroutine for m0
+G*	runtime_lastg;
+M*	runtime_allm;
+P**	runtime_allp;
+M*	runtime_extram;
+int8*	runtime_goos;
+int32	runtime_ncpu;
+bool	runtime_precisestack;
+static int32	newprocs;
+
+static	Lock allglock;	// the following vars are protected by this lock or by stoptheworld
+G**	runtime_allg;
+uintptr runtime_allglen;
+static	uintptr allgcap;
+
+void* runtime_mstart(void*);
+static void runqput(P*, G*);
+static G* runqget(P*);
+static bool runqputslow(P*, G*, uint32, uint32);
+static G* runqsteal(P*, P*);
+static void mput(M*);
+static M* mget(void);
+static void mcommoninit(M*);
+static void schedule(void);
+static void procresize(int32);
+static void acquirep(P*);
+static P* releasep(void);
+static void newm(void(*)(void), P*);
+static void stopm(void);
+static void startm(P*, bool);
+static void handoffp(P*);
+static void wakep(void);
+static void stoplockedm(void);
+static void startlockedm(G*);
+static void sysmon(void);
+static uint32 retake(int64);
+static void incidlelocked(int32);
+static void checkdead(void);
+static void exitsyscall0(G*);
+static void park0(G*);
+static void goexit0(G*);
+static void gfput(P*, G*);
+static G* gfget(P*);
+static void gfpurge(P*);
+static void globrunqput(G*);
+static void globrunqputbatch(G*, G*, int32);
+static G* globrunqget(P*, int32);
+static P* pidleget(void);
+static void pidleput(P*);
+static void injectglist(G*);
+static bool preemptall(void);
+static bool exitsyscallfast(void);
+static void allgadd(G*);
+
+// The bootstrap sequence is:
+//
+//	call osinit
+//	call schedinit
+//	make & queue new G
+//	call runtime_mstart
+//
+// The new G calls runtime_main.
+void
+runtime_schedinit(void)
+{
+	int32 n, procs;
+	const byte *p;
+	Eface i;
+
+	m = &runtime_m0;
+	g = &runtime_g0;
+	m->g0 = g;
+	m->curg = g;
+	g->m = m;
+
+	initcontext();
+
+	runtime_sched.maxmcount = 10000;
+	runtime_precisestack = 0;
+
+	// runtime_symtabinit();
+	runtime_mallocinit();
+	mcommoninit(m);
+	
+	// Initialize the itable value for newErrorCString,
+	// so that the next time it gets called, possibly
+	// in a fault during a garbage collection, it will not
+	// need to allocated memory.
+	runtime_newErrorCString(0, &i);
+	
+	// Initialize the cached gotraceback value, since
+	// gotraceback calls getenv, which mallocs on Plan 9.
+	runtime_gotraceback(nil);
+
+	runtime_goargs();
+	runtime_goenvs();
+	runtime_parsedebugvars();
+
+	runtime_sched.lastpoll = runtime_nanotime();
+	procs = 1;
+	p = runtime_getenv("GOMAXPROCS");
+	if(p != nil && (n = runtime_atoi(p)) > 0) {
+		if(n > MaxGomaxprocs)
+			n = MaxGomaxprocs;
+		procs = n;
+	}
+	runtime_allp = runtime_malloc((MaxGomaxprocs+1)*sizeof(runtime_allp[0]));
+	procresize(procs);
+
+	// Can not enable GC until all roots are registered.
+	// mstats.enablegc = 1;
+
+	// if(raceenabled)
+	//	g->racectx = runtime_raceinit();
+}
+
+extern void main_init(void) __asm__ (GOSYM_PREFIX "__go_init_main");
+extern void main_main(void) __asm__ (GOSYM_PREFIX "main.main");
+
+static void
+initDone(void *arg __attribute__ ((unused))) {
+	runtime_unlockOSThread();
+};
+
+// The main goroutine.
+// Note: C frames in general are not copyable during stack growth, for two reasons:
+//   1) We don't know where in a frame to find pointers to other stack locations.
+//   2) There's no guarantee that globals or heap values do not point into the frame.
+//
+// The C frame for runtime.main is copyable, because:
+//   1) There are no pointers to other stack locations in the frame
+//      (d.fn points at a global, d.link is nil, d.argp is -1).
+//   2) The only pointer into this frame is from the defer chain,
+//      which is explicitly handled during stack copying.
+void
+runtime_main(void* dummy __attribute__((unused)))
+{
+	Defer d;
+	_Bool frame;
+	
+	newm(sysmon, nil);
+
+	// Lock the main goroutine onto this, the main OS thread,
+	// during initialization.  Most programs won't care, but a few
+	// do require certain calls to be made by the main thread.
+	// Those can arrange for main.main to run in the main thread
+	// by calling runtime.LockOSThread during initialization
+	// to preserve the lock.
+	runtime_lockOSThread();
+	
+	// Defer unlock so that runtime.Goexit during init does the unlock too.
+	d.__pfn = initDone;
+	d.__next = g->defer;
+	d.__arg = (void*)-1;
+	d.__panic = g->panic;
+	d.__retaddr = nil;
+	d.__makefunc_can_recover = 0;
+	d.__frame = &frame;
+	d.__special = true;
+	g->defer = &d;
+
+	if(m != &runtime_m0)
+		runtime_throw("runtime_main not on m0");
+	__go_go(runtime_MHeap_Scavenger, nil);
+	main_init();
+
+	if(g->defer != &d || d.__pfn != initDone)
+		runtime_throw("runtime: bad defer entry after init");
+	g->defer = d.__next;
+	runtime_unlockOSThread();
+
+	// For gccgo we have to wait until after main is initialized
+	// to enable GC, because initializing main registers the GC
+	// roots.
+	mstats.enablegc = 1;
+
+	main_main();
+	if(raceenabled)
+		runtime_racefini();
+
+	// Make racy client program work: if panicking on
+	// another goroutine at the same time as main returns,
+	// let the other goroutine finish printing the panic trace.
+	// Once it does, it will exit. See issue 3934.
+	if(runtime_panicking)
+		runtime_park(nil, nil, "panicwait");
+
+	runtime_exit(0);
+	for(;;)
+		*(int32*)0 = 0;
+}
+
+void
+runtime_goroutineheader(G *gp)
+{
+	const char *status;
+	int64 waitfor;
+
+	switch(gp->status) {
+	case Gidle:
+		status = "idle";
+		break;
+	case Grunnable:
+		status = "runnable";
+		break;
+	case Grunning:
+		status = "running";
+		break;
+	case Gsyscall:
+		status = "syscall";
+		break;
+	case Gwaiting:
+		if(gp->waitreason)
+			status = gp->waitreason;
+		else
+			status = "waiting";
+		break;
+	default:
+		status = "???";
+		break;
+	}
+
+	// approx time the G is blocked, in minutes
+	waitfor = 0;
+	if((gp->status == Gwaiting || gp->status == Gsyscall) && gp->waitsince != 0)
+		waitfor = (runtime_nanotime() - gp->waitsince) / (60LL*1000*1000*1000);
+
+	if(waitfor < 1)
+		runtime_printf("goroutine %D [%s]:\n", gp->goid, status);
+	else
+		runtime_printf("goroutine %D [%s, %D minutes]:\n", gp->goid, status, waitfor);
+}
+
+void
+runtime_printcreatedby(G *g)
+{
+	if(g != nil && g->gopc != 0 && g->goid != 1) {
+		String fn;
+		String file;
+		intgo line;
+
+		if(__go_file_line(g->gopc - 1, &fn, &file, &line)) {
+			runtime_printf("created by %S\n", fn);
+			runtime_printf("\t%S:%D\n", file, (int64) line);
+		}
+	}
+}
+
+struct Traceback
+{
+	G* gp;
+	Location locbuf[TracebackMaxFrames];
+	int32 c;
+};
+
+void
+runtime_tracebackothers(G * volatile me)
+{
+	G * volatile gp;
+	Traceback tb;
+	int32 traceback;
+	volatile uintptr i;
+
+	tb.gp = me;
+	traceback = runtime_gotraceback(nil);
+	
+	// Show the current goroutine first, if we haven't already.
+	if((gp = m->curg) != nil && gp != me) {
+		runtime_printf("\n");
+		runtime_goroutineheader(gp);
+		gp->traceback = &tb;
+
+#ifdef USING_SPLIT_STACK
+		__splitstack_getcontext(&me->stack_context[0]);
+#endif
+		getcontext(&me->context);
+
+		if(gp->traceback != nil) {
+		  runtime_gogo(gp);
+		}
+
+		runtime_printtrace(tb.locbuf, tb.c, false);
+		runtime_printcreatedby(gp);
+	}
+
+	runtime_lock(&allglock);
+	for(i = 0; i < runtime_allglen; i++) {
+		gp = runtime_allg[i];
+		if(gp == me || gp == m->curg || gp->status == Gdead)
+			continue;
+		if(gp->issystem && traceback < 2)
+			continue;
+		runtime_printf("\n");
+		runtime_goroutineheader(gp);
+
+		// Our only mechanism for doing a stack trace is
+		// _Unwind_Backtrace.  And that only works for the
+		// current thread, not for other random goroutines.
+		// So we need to switch context to the goroutine, get
+		// the backtrace, and then switch back.
+
+		// This means that if g is running or in a syscall, we
+		// can't reliably print a stack trace.  FIXME.
+
+		if(gp->status == Grunning) {
+			runtime_printf("\tgoroutine running on other thread; stack unavailable\n");
+			runtime_printcreatedby(gp);
+		} else if(gp->status == Gsyscall) {
+			runtime_printf("\tgoroutine in C code; stack unavailable\n");
+			runtime_printcreatedby(gp);
+		} else {
+			gp->traceback = &tb;
+
+#ifdef USING_SPLIT_STACK
+			__splitstack_getcontext(&me->stack_context[0]);
+#endif
+			getcontext(&me->context);
+
+			if(gp->traceback != nil) {
+				runtime_gogo(gp);
+			}
+
+			runtime_printtrace(tb.locbuf, tb.c, false);
+			runtime_printcreatedby(gp);
+		}
+	}
+	runtime_unlock(&allglock);
+}
+
+static void
+checkmcount(void)
+{
+	// sched lock is held
+	if(runtime_sched.mcount > runtime_sched.maxmcount) {
+		runtime_printf("runtime: program exceeds %d-thread limit\n", runtime_sched.maxmcount);
+		runtime_throw("thread exhaustion");
+	}
+}
+
+// Do a stack trace of gp, and then restore the context to
+// gp->dotraceback.
+
+static void
+gtraceback(G* gp)
+{
+	Traceback* traceback;
+
+	traceback = gp->traceback;
+	gp->traceback = nil;
+	traceback->c = runtime_callers(1, traceback->locbuf,
+		sizeof traceback->locbuf / sizeof traceback->locbuf[0], false);
+	runtime_gogo(traceback->gp);
+}
+
+static void
+mcommoninit(M *mp)
+{
+	// If there is no mcache runtime_callers() will crash,
+	// and we are most likely in sysmon thread so the stack is senseless anyway.
+	if(m->mcache)
+		runtime_callers(1, mp->createstack, nelem(mp->createstack), false);
+
+	mp->fastrand = 0x49f6428aUL + mp->id + runtime_cputicks();
+
+	runtime_lock(&runtime_sched.lock);
+	mp->id = runtime_sched.mcount++;
+	checkmcount();
+	runtime_mpreinit(mp);
+
+	// Add to runtime_allm so garbage collector doesn't free m
+	// when it is just in a register or thread-local storage.
+	mp->alllink = runtime_allm;
+	// runtime_NumCgoCall() iterates over allm w/o schedlock,
+	// so we need to publish it safely.
+	runtime_atomicstorep(&runtime_allm, mp);
+	runtime_unlock(&runtime_sched.lock);
+}
+
+// Mark gp ready to run.
+void
+runtime_ready(G *gp)
+{
+	// Mark runnable.
+	m->locks++;  // disable preemption because it can be holding p in a local var
+	if(gp->status != Gwaiting) {
+		runtime_printf("goroutine %D has status %d\n", gp->goid, gp->status);
+		runtime_throw("bad g->status in ready");
+	}
+	gp->status = Grunnable;
+	runqput(m->p, gp);
+	if(runtime_atomicload(&runtime_sched.npidle) != 0 && runtime_atomicload(&runtime_sched.nmspinning) == 0)  // TODO: fast atomic
+		wakep();
+	m->locks--;
+}
+
+int32
+runtime_gcprocs(void)
+{
+	int32 n;
+
+	// Figure out how many CPUs to use during GC.
+	// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
+	runtime_lock(&runtime_sched.lock);
+	n = runtime_gomaxprocs;
+	if(n > runtime_ncpu)
+		n = runtime_ncpu > 0 ? runtime_ncpu : 1;
+	if(n > MaxGcproc)
+		n = MaxGcproc;
+	if(n > runtime_sched.nmidle+1) // one M is currently running
+		n = runtime_sched.nmidle+1;
+	runtime_unlock(&runtime_sched.lock);
+	return n;
+}
+
+static bool
+needaddgcproc(void)
+{
+	int32 n;
+
+	runtime_lock(&runtime_sched.lock);
+	n = runtime_gomaxprocs;
+	if(n > runtime_ncpu)
+		n = runtime_ncpu;
+	if(n > MaxGcproc)
+		n = MaxGcproc;
+	n -= runtime_sched.nmidle+1; // one M is currently running
+	runtime_unlock(&runtime_sched.lock);
+	return n > 0;
+}
+
+void
+runtime_helpgc(int32 nproc)
+{
+	M *mp;
+	int32 n, pos;
+
+	runtime_lock(&runtime_sched.lock);
+	pos = 0;
+	for(n = 1; n < nproc; n++) {  // one M is currently running
+		if(runtime_allp[pos]->mcache == m->mcache)
+			pos++;
+		mp = mget();
+		if(mp == nil)
+			runtime_throw("runtime_gcprocs inconsistency");
+		mp->helpgc = n;
+		mp->mcache = runtime_allp[pos]->mcache;
+		pos++;
+		runtime_notewakeup(&mp->park);
+	}
+	runtime_unlock(&runtime_sched.lock);
+}
+
+// Similar to stoptheworld but best-effort and can be called several times.
+// There is no reverse operation, used during crashing.
+// This function must not lock any mutexes.
+void
+runtime_freezetheworld(void)
+{
+	int32 i;
+
+	if(runtime_gomaxprocs == 1)
+		return;
+	// stopwait and preemption requests can be lost
+	// due to races with concurrently executing threads,
+	// so try several times
+	for(i = 0; i < 5; i++) {
+		// this should tell the scheduler to not start any new goroutines
+		runtime_sched.stopwait = 0x7fffffff;
+		runtime_atomicstore((uint32*)&runtime_sched.gcwaiting, 1);
+		// this should stop running goroutines
+		if(!preemptall())
+			break;  // no running goroutines
+		runtime_usleep(1000);
+	}
+	// to be sure
+	runtime_usleep(1000);
+	preemptall();
+	runtime_usleep(1000);
+}
+
+void
+runtime_stoptheworld(void)
+{
+	int32 i;
+	uint32 s;
+	P *p;
+	bool wait;
+
+	runtime_lock(&runtime_sched.lock);
+	runtime_sched.stopwait = runtime_gomaxprocs;
+	runtime_atomicstore((uint32*)&runtime_sched.gcwaiting, 1);
+	preemptall();
+	// stop current P
+	m->p->status = Pgcstop;
+	runtime_sched.stopwait--;
+	// try to retake all P's in Psyscall status
+	for(i = 0; i < runtime_gomaxprocs; i++) {
+		p = runtime_allp[i];
+		s = p->status;
+		if(s == Psyscall && runtime_cas(&p->status, s, Pgcstop))
+			runtime_sched.stopwait--;
+	}
+	// stop idle P's
+	while((p = pidleget()) != nil) {
+		p->status = Pgcstop;
+		runtime_sched.stopwait--;
+	}
+	wait = runtime_sched.stopwait > 0;
+	runtime_unlock(&runtime_sched.lock);
+
+	// wait for remaining P's to stop voluntarily
+	if(wait) {
+		runtime_notesleep(&runtime_sched.stopnote);
+		runtime_noteclear(&runtime_sched.stopnote);
+	}
+	if(runtime_sched.stopwait)
+		runtime_throw("stoptheworld: not stopped");
+	for(i = 0; i < runtime_gomaxprocs; i++) {
+		p = runtime_allp[i];
+		if(p->status != Pgcstop)
+			runtime_throw("stoptheworld: not stopped");
+	}
+}
+
+static void
+mhelpgc(void)
+{
+	m->helpgc = -1;
+}
+
+void
+runtime_starttheworld(void)
+{
+	P *p, *p1;
+	M *mp;
+	G *gp;
+	bool add;
+
+	m->locks++;  // disable preemption because it can be holding p in a local var
+	gp = runtime_netpoll(false);  // non-blocking
+	injectglist(gp);
+	add = needaddgcproc();
+	runtime_lock(&runtime_sched.lock);
+	if(newprocs) {
+		procresize(newprocs);
+		newprocs = 0;
+	} else
+		procresize(runtime_gomaxprocs);
+	runtime_sched.gcwaiting = 0;
+
+	p1 = nil;
+	while((p = pidleget()) != nil) {
+		// procresize() puts p's with work at the beginning of the list.
+		// Once we reach a p without a run queue, the rest don't have one either.
+		if(p->runqhead == p->runqtail) {
+			pidleput(p);
+			break;
+		}
+		p->m = mget();
+		p->link = p1;
+		p1 = p;
+	}
+	if(runtime_sched.sysmonwait) {
+		runtime_sched.sysmonwait = false;
+		runtime_notewakeup(&runtime_sched.sysmonnote);
+	}
+	runtime_unlock(&runtime_sched.lock);
+
+	while(p1) {
+		p = p1;
+		p1 = p1->link;
+		if(p->m) {
+			mp = p->m;
+			p->m = nil;
+			if(mp->nextp)
+				runtime_throw("starttheworld: inconsistent mp->nextp");
+			mp->nextp = p;
+			runtime_notewakeup(&mp->park);
+		} else {
+			// Start M to run P.  Do not start another M below.
+			newm(nil, p);
+			add = false;
+		}
+	}
+
+	if(add) {
+		// If GC could have used another helper proc, start one now,
+		// in the hope that it will be available next time.
+		// It would have been even better to start it before the collection,
+		// but doing so requires allocating memory, so it's tricky to
+		// coordinate.  This lazy approach works out in practice:
+		// we don't mind if the first couple gc rounds don't have quite
+		// the maximum number of procs.
+		newm(mhelpgc, nil);
+	}
+	m->locks--;
+}
+
+// Called to start an M.
+void*
+runtime_mstart(void* mp)
+{
+	m = (M*)mp;
+	g = m->g0;
+
+	initcontext();
+
+	g->entry = nil;
+	g->param = nil;
+
+	// Record top of stack for use by mcall.
+	// Once we call schedule we're never coming back,
+	// so other calls can reuse this stack space.
+#ifdef USING_SPLIT_STACK
+	__splitstack_getcontext(&g->stack_context[0]);
+#else
+	g->gcinitial_sp = &mp;
+	// Setting gcstack_size to 0 is a marker meaning that gcinitial_sp
+	// is the top of the stack, not the bottom.
+	g->gcstack_size = 0;
+	g->gcnext_sp = &mp;
+#endif
+	getcontext(&g->context);
+
+	if(g->entry != nil) {
+		// Got here from mcall.
+		void (*pfn)(G*) = (void (*)(G*))g->entry;
+		G* gp = (G*)g->param;
+		pfn(gp);
+		*(int*)0x21 = 0x21;
+	}
+	runtime_minit();
+
+#ifdef USING_SPLIT_STACK
+	{
+		int dont_block_signals = 0;
+		__splitstack_block_signals(&dont_block_signals, nil);
+	}
+#endif
+
+	// Install signal handlers; after minit so that minit can
+	// prepare the thread to be able to handle the signals.
+	if(m == &runtime_m0)
+		runtime_initsig();
+	
+	if(m->mstartfn)
+		m->mstartfn();
+
+	if(m->helpgc) {
+		m->helpgc = 0;
+		stopm();
+	} else if(m != &runtime_m0) {
+		acquirep(m->nextp);
+		m->nextp = nil;
+	}
+	schedule();
+
+	// TODO(brainman): This point is never reached, because scheduler
+	// does not release os threads at the moment. But once this path
+	// is enabled, we must remove our seh here.
+
+	return nil;
+}
+
+typedef struct CgoThreadStart CgoThreadStart;
+struct CgoThreadStart
+{
+	M *m;
+	G *g;
+	uintptr *tls;
+	void (*fn)(void);
+};
+
+// Allocate a new m unassociated with any thread.
+// Can use p for allocation context if needed.
+M*
+runtime_allocm(P *p, int32 stacksize, byte** ret_g0_stack, size_t* ret_g0_stacksize)
+{
+	M *mp;
+
+	m->locks++;  // disable GC because it can be called from sysmon
+	if(m->p == nil)
+		acquirep(p);  // temporarily borrow p for mallocs in this function
+#if 0
+	if(mtype == nil) {
+		Eface e;
+		runtime_gc_m_ptr(&e);
+		mtype = ((const PtrType*)e.__type_descriptor)->__element_type;
+	}
+#endif
+
+	mp = runtime_mal(sizeof *mp);
+	mcommoninit(mp);
+	mp->g0 = runtime_malg(stacksize, ret_g0_stack, ret_g0_stacksize);
+
+	if(p == m->p)
+		releasep();
+	m->locks--;
+
+	return mp;
+}
+
+static G*
+allocg(void)
+{
+	G *gp;
+	// static Type *gtype;
+	
+	// if(gtype == nil) {
+	// 	Eface e;
+	// 	runtime_gc_g_ptr(&e);
+	// 	gtype = ((PtrType*)e.__type_descriptor)->__element_type;
+	// }
+	// gp = runtime_cnew(gtype);
+	gp = runtime_malloc(sizeof(G));
+	return gp;
+}
+
+static M* lockextra(bool nilokay);
+static void unlockextra(M*);
+
+// needm is called when a cgo callback happens on a
+// thread without an m (a thread not created by Go).
+// In this case, needm is expected to find an m to use
+// and return with m, g initialized correctly.
+// Since m and g are not set now (likely nil, but see below)
+// needm is limited in what routines it can call. In particular
+// it can only call nosplit functions (textflag 7) and cannot
+// do any scheduling that requires an m.
+//
+// In order to avoid needing heavy lifting here, we adopt
+// the following strategy: there is a stack of available m's
+// that can be stolen. Using compare-and-swap
+// to pop from the stack has ABA races, so we simulate
+// a lock by doing an exchange (via casp) to steal the stack
+// head and replace the top pointer with MLOCKED (1).
+// This serves as a simple spin lock that we can use even
+// without an m. The thread that locks the stack in this way
+// unlocks the stack by storing a valid stack head pointer.
+//
+// In order to make sure that there is always an m structure
+// available to be stolen, we maintain the invariant that there
+// is always one more than needed. At the beginning of the
+// program (if cgo is in use) the list is seeded with a single m.
+// If needm finds that it has taken the last m off the list, its job
+// is - once it has installed its own m so that it can do things like
+// allocate memory - to create a spare m and put it on the list.
+//
+// Each of these extra m's also has a g0 and a curg that are
+// pressed into service as the scheduling stack and current
+// goroutine for the duration of the cgo callback.
+//
+// When the callback is done with the m, it calls dropm to
+// put the m back on the list.
+//
+// Unlike the gc toolchain, we start running on curg, since we are
+// just going to return and let the caller continue.
+void
+runtime_needm(void)
+{
+	M *mp;
+
+	if(runtime_needextram) {
+		// Can happen if C/C++ code calls Go from a global ctor.
+		// Can not throw, because scheduler is not initialized yet.
+		int rv __attribute__((unused));
+		rv = runtime_write(2, "fatal error: cgo callback before cgo call\n",
+			sizeof("fatal error: cgo callback before cgo call\n")-1);
+		runtime_exit(1);
+	}
+
+	// Lock extra list, take head, unlock popped list.
+	// nilokay=false is safe here because of the invariant above,
+	// that the extra list always contains or will soon contain
+	// at least one m.
+	mp = lockextra(false);
+
+	// Set needextram when we've just emptied the list,
+	// so that the eventual call into cgocallbackg will
+	// allocate a new m for the extra list. We delay the
+	// allocation until then so that it can be done
+	// after exitsyscall makes sure it is okay to be
+	// running at all (that is, there's no garbage collection
+	// running right now).
+	mp->needextram = mp->schedlink == nil;
+	unlockextra(mp->schedlink);
+
+	// Install m and g (= m->curg).
+	runtime_setmg(mp, mp->curg);
+
+	// Initialize g's context as in mstart.
+	initcontext();
+	g->status = Gsyscall;
+	g->entry = nil;
+	g->param = nil;
+#ifdef USING_SPLIT_STACK
+	__splitstack_getcontext(&g->stack_context[0]);
+#else
+	g->gcinitial_sp = &mp;
+	g->gcstack_size = 0;
+	g->gcnext_sp = &mp;
+#endif
+	getcontext(&g->context);
+
+	if(g->entry != nil) {
+		// Got here from mcall.
+		void (*pfn)(G*) = (void (*)(G*))g->entry;
+		G* gp = (G*)g->param;
+		pfn(gp);
+		*(int*)0x22 = 0x22;
+	}
+
+	// Initialize this thread to use the m.
+	runtime_minit();
+
+#ifdef USING_SPLIT_STACK
+	{
+		int dont_block_signals = 0;
+		__splitstack_block_signals(&dont_block_signals, nil);
+	}
+#endif
+}
+
+// newextram allocates an m and puts it on the extra list.
+// It is called with a working local m, so that it can do things
+// like call schedlock and allocate.
+void
+runtime_newextram(void)
+{
+	M *mp, *mnext;
+	G *gp;
+	byte *g0_sp, *sp;
+	size_t g0_spsize, spsize;
+
+	// Create extra goroutine locked to extra m.
+	// The goroutine is the context in which the cgo callback will run.
+	// The sched.pc will never be returned to, but setting it to
+	// runtime.goexit makes clear to the traceback routines where
+	// the goroutine stack ends.
+	mp = runtime_allocm(nil, StackMin, &g0_sp, &g0_spsize);
+	gp = runtime_malg(StackMin, &sp, &spsize);
+	gp->status = Gdead;
+	mp->curg = gp;
+	mp->locked = LockInternal;
+	mp->lockedg = gp;
+	gp->lockedm = mp;
+	gp->goid = runtime_xadd64(&runtime_sched.goidgen, 1);
+	// put on allg for garbage collector
+	allgadd(gp);
+
+	// The context for gp will be set up in runtime_needm.  But
+	// here we need to set up the context for g0.
+	getcontext(&mp->g0->context);
+	mp->g0->context.uc_stack.ss_sp = g0_sp;
+	mp->g0->context.uc_stack.ss_size = g0_spsize;
+	makecontext(&mp->g0->context, kickoff, 0);
+
+	// Add m to the extra list.
+	mnext = lockextra(true);
+	mp->schedlink = mnext;
+	unlockextra(mp);
+}
+
+// dropm is called when a cgo callback has called needm but is now
+// done with the callback and returning back into the non-Go thread.
+// It puts the current m back onto the extra list.
+//
+// The main expense here is the call to signalstack to release the
+// m's signal stack, and then the call to needm on the next callback
+// from this thread. It is tempting to try to save the m for next time,
+// which would eliminate both these costs, but there might not be
+// a next time: the current thread (which Go does not control) might exit.
+// If we saved the m for that thread, there would be an m leak each time
+// such a thread exited. Instead, we acquire and release an m on each
+// call. These should typically not be scheduling operations, just a few
+// atomics, so the cost should be small.
+//
+// TODO(rsc): An alternative would be to allocate a dummy pthread per-thread
+// variable using pthread_key_create. Unlike the pthread keys we already use
+// on OS X, this dummy key would never be read by Go code. It would exist
+// only so that we could register at thread-exit-time destructor.
+// That destructor would put the m back onto the extra list.
+// This is purely a performance optimization. The current version,
+// in which dropm happens on each cgo call, is still correct too.
+// We may have to keep the current version on systems with cgo
+// but without pthreads, like Windows.
+void
+runtime_dropm(void)
+{
+	M *mp, *mnext;
+
+	// Undo whatever initialization minit did during needm.
+	runtime_unminit();
+
+	// Clear m and g, and return m to the extra list.
+	// After the call to setmg we can only call nosplit functions.
+	mp = m;
+	runtime_setmg(nil, nil);
+
+	mp->curg->status = Gdead;
+
+	mnext = lockextra(true);
+	mp->schedlink = mnext;
+	unlockextra(mp);
+}
+
+#define MLOCKED ((M*)1)
+
+// lockextra locks the extra list and returns the list head.
+// The caller must unlock the list by storing a new list head
+// to runtime.extram. If nilokay is true, then lockextra will
+// return a nil list head if that's what it finds. If nilokay is false,
+// lockextra will keep waiting until the list head is no longer nil.
+static M*
+lockextra(bool nilokay)
+{
+	M *mp;
+	void (*yield)(void);
+
+	for(;;) {
+		mp = runtime_atomicloadp(&runtime_extram);
+		if(mp == MLOCKED) {
+			yield = runtime_osyield;
+			yield();
+			continue;
+		}
+		if(mp == nil && !nilokay) {
+			runtime_usleep(1);
+			continue;
+		}
+		if(!runtime_casp(&runtime_extram, mp, MLOCKED)) {
+			yield = runtime_osyield;
+			yield();
+			continue;
+		}
+		break;
+	}
+	return mp;
+}
+
+static void
+unlockextra(M *mp)
+{
+	runtime_atomicstorep(&runtime_extram, mp);
+}
+
+static int32
+countextra()
+{
+	M *mp, *mc;
+	int32 c;
+
+	for(;;) {
+		mp = runtime_atomicloadp(&runtime_extram);
+		if(mp == MLOCKED) {
+			runtime_osyield();
+			continue;
+		}
+		if(!runtime_casp(&runtime_extram, mp, MLOCKED)) {
+			runtime_osyield();
+			continue;
+		}
+		c = 0;
+		for(mc = mp; mc != nil; mc = mc->schedlink)
+			c++;
+		runtime_atomicstorep(&runtime_extram, mp);
+		return c;
+	}
+}
+
+// Create a new m.  It will start off with a call to fn, or else the scheduler.
+static void
+newm(void(*fn)(void), P *p)
+{
+	M *mp;
+
+	mp = runtime_allocm(p, -1, nil, nil);
+	mp->nextp = p;
+	mp->mstartfn = fn;
+
+	runtime_newosproc(mp);
+}
+
+// Stops execution of the current m until new work is available.
+// Returns with acquired P.
+static void
+stopm(void)
+{
+	if(m->locks)
+		runtime_throw("stopm holding locks");
+	if(m->p)
+		runtime_throw("stopm holding p");
+	if(m->spinning) {
+		m->spinning = false;
+		runtime_xadd(&runtime_sched.nmspinning, -1);
+	}
+
+retry:
+	runtime_lock(&runtime_sched.lock);
+	mput(m);
+	runtime_unlock(&runtime_sched.lock);
+	runtime_notesleep(&m->park);
+	runtime_noteclear(&m->park);
+	if(m->helpgc) {
+		runtime_gchelper();
+		m->helpgc = 0;
+		m->mcache = nil;
+		goto retry;
+	}
+	acquirep(m->nextp);
+	m->nextp = nil;
+}
+
+static void
+mspinning(void)
+{
+	m->spinning = true;
+}
+
+// Schedules some M to run the p (creates an M if necessary).
+// If p==nil, tries to get an idle P, if no idle P's does nothing.
+static void
+startm(P *p, bool spinning)
+{
+	M *mp;
+	void (*fn)(void);
+
+	runtime_lock(&runtime_sched.lock);
+	if(p == nil) {
+		p = pidleget();
+		if(p == nil) {
+			runtime_unlock(&runtime_sched.lock);
+			if(spinning)
+				runtime_xadd(&runtime_sched.nmspinning, -1);
+			return;
+		}
+	}
+	mp = mget();
+	runtime_unlock(&runtime_sched.lock);
+	if(mp == nil) {
+		fn = nil;
+		if(spinning)
+			fn = mspinning;
+		newm(fn, p);
+		return;
+	}
+	if(mp->spinning)
+		runtime_throw("startm: m is spinning");
+	if(mp->nextp)
+		runtime_throw("startm: m has p");
+	mp->spinning = spinning;
+	mp->nextp = p;
+	runtime_notewakeup(&mp->park);
+}
+
+// Hands off P from syscall or locked M.
+static void
+handoffp(P *p)
+{
+	// if it has local work, start it straight away
+	if(p->runqhead != p->runqtail || runtime_sched.runqsize) {
+		startm(p, false);
+		return;
+	}
+	// no local work, check that there are no spinning/idle M's,
+	// otherwise our help is not required
+	if(runtime_atomicload(&runtime_sched.nmspinning) + runtime_atomicload(&runtime_sched.npidle) == 0 &&  // TODO: fast atomic
+		runtime_cas(&runtime_sched.nmspinning, 0, 1)) {
+		startm(p, true);
+		return;
+	}
+	runtime_lock(&runtime_sched.lock);
+	if(runtime_sched.gcwaiting) {
+		p->status = Pgcstop;
+		if(--runtime_sched.stopwait == 0)
+			runtime_notewakeup(&runtime_sched.stopnote);
+		runtime_unlock(&runtime_sched.lock);
+		return;
+	}
+	if(runtime_sched.runqsize) {
+		runtime_unlock(&runtime_sched.lock);
+		startm(p, false);
+		return;
+	}
+	// If this is the last running P and nobody is polling network,
+	// need to wakeup another M to poll network.
+	if(runtime_sched.npidle == (uint32)runtime_gomaxprocs-1 && runtime_atomicload64(&runtime_sched.lastpoll) != 0) {
+		runtime_unlock(&runtime_sched.lock);
+		startm(p, false);
+		return;
+	}
+	pidleput(p);
+	runtime_unlock(&runtime_sched.lock);
+}
+
+// Tries to add one more P to execute G's.
+// Called when a G is made runnable (newproc, ready).
+static void
+wakep(void)
+{
+	// be conservative about spinning threads
+	if(!runtime_cas(&runtime_sched.nmspinning, 0, 1))
+		return;
+	startm(nil, true);
+}
+
+// Stops execution of the current m that is locked to a g until the g is runnable again.
+// Returns with acquired P.
+static void
+stoplockedm(void)
+{
+	P *p;
+
+	if(m->lockedg == nil || m->lockedg->lockedm != m)
+		runtime_throw("stoplockedm: inconsistent locking");
+	if(m->p) {
+		// Schedule another M to run this p.
+		p = releasep();
+		handoffp(p);
+	}
+	incidlelocked(1);
+	// Wait until another thread schedules lockedg again.
+	runtime_notesleep(&m->park);
+	runtime_noteclear(&m->park);
+	if(m->lockedg->status != Grunnable)
+		runtime_throw("stoplockedm: not runnable");
+	acquirep(m->nextp);
+	m->nextp = nil;
+}
+
+// Schedules the locked m to run the locked gp.
+static void
+startlockedm(G *gp)
+{
+	M *mp;
+	P *p;
+
+	mp = gp->lockedm;
+	if(mp == m)
+		runtime_throw("startlockedm: locked to me");
+	if(mp->nextp)
+		runtime_throw("startlockedm: m has p");
+	// directly handoff current P to the locked m
+	incidlelocked(-1);
+	p = releasep();
+	mp->nextp = p;
+	runtime_notewakeup(&mp->park);
+	stopm();
+}
+
+// Stops the current m for stoptheworld.
+// Returns when the world is restarted.
+static void
+gcstopm(void)
+{
+	P *p;
+
+	if(!runtime_sched.gcwaiting)
+		runtime_throw("gcstopm: not waiting for gc");
+	if(m->spinning) {
+		m->spinning = false;
+		runtime_xadd(&runtime_sched.nmspinning, -1);
+	}
+	p = releasep();
+	runtime_lock(&runtime_sched.lock);
+	p->status = Pgcstop;
+	if(--runtime_sched.stopwait == 0)
+		runtime_notewakeup(&runtime_sched.stopnote);
+	runtime_unlock(&runtime_sched.lock);
+	stopm();
+}
+
+// Schedules gp to run on the current M.
+// Never returns.
+static void
+execute(G *gp)
+{
+	int32 hz;
+
+	if(gp->status != Grunnable) {
+		runtime_printf("execute: bad g status %d\n", gp->status);
+		runtime_throw("execute: bad g status");
+	}
+	gp->status = Grunning;
+	gp->waitsince = 0;
+	m->p->schedtick++;
+	m->curg = gp;
+	gp->m = m;
+
+	// Check whether the profiler needs to be turned on or off.
+	hz = runtime_sched.profilehz;
+	if(m->profilehz != hz)
+		runtime_resetcpuprofiler(hz);
+
+	runtime_gogo(gp);
+}
+
+// Finds a runnable goroutine to execute.
+// Tries to steal from other P's, get g from global queue, poll network.
+static G*
+findrunnable(void)
+{
+	G *gp;
+	P *p;
+	int32 i;
+
+top:
+	if(runtime_sched.gcwaiting) {
+		gcstopm();
+		goto top;
+	}
+	if(runtime_fingwait && runtime_fingwake && (gp = runtime_wakefing()) != nil)
+		runtime_ready(gp);
+	// local runq
+	gp = runqget(m->p);
+	if(gp)
+		return gp;
+	// global runq
+	if(runtime_sched.runqsize) {
+		runtime_lock(&runtime_sched.lock);
+		gp = globrunqget(m->p, 0);
+		runtime_unlock(&runtime_sched.lock);
+		if(gp)
+			return gp;
+	}
+	// poll network
+	gp = runtime_netpoll(false);  // non-blocking
+	if(gp) {
+		injectglist(gp->schedlink);
+		gp->status = Grunnable;
+		return gp;
+	}
+	// If number of spinning M's >= number of busy P's, block.
+	// This is necessary to prevent excessive CPU consumption
+	// when GOMAXPROCS>>1 but the program parallelism is low.
+	if(!m->spinning && 2 * runtime_atomicload(&runtime_sched.nmspinning) >= runtime_gomaxprocs - runtime_atomicload(&runtime_sched.npidle))  // TODO: fast atomic
+		goto stop;
+	if(!m->spinning) {
+		m->spinning = true;
+		runtime_xadd(&runtime_sched.nmspinning, 1);
+	}
+	// random steal from other P's
+	for(i = 0; i < 2*runtime_gomaxprocs; i++) {
+		if(runtime_sched.gcwaiting)
+			goto top;
+		p = runtime_allp[runtime_fastrand1()%runtime_gomaxprocs];
+		if(p == m->p)
+			gp = runqget(p);
+		else
+			gp = runqsteal(m->p, p);
+		if(gp)
+			return gp;
+	}
+stop:
+	// return P and block
+	runtime_lock(&runtime_sched.lock);
+	if(runtime_sched.gcwaiting) {
+		runtime_unlock(&runtime_sched.lock);
+		goto top;
+	}
+	if(runtime_sched.runqsize) {
+		gp = globrunqget(m->p, 0);
+		runtime_unlock(&runtime_sched.lock);
+		return gp;
+	}
+	p = releasep();
+	pidleput(p);
+	runtime_unlock(&runtime_sched.lock);
+	if(m->spinning) {
+		m->spinning = false;
+		runtime_xadd(&runtime_sched.nmspinning, -1);
+	}
+	// check all runqueues once again
+	for(i = 0; i < runtime_gomaxprocs; i++) {
+		p = runtime_allp[i];
+		if(p && p->runqhead != p->runqtail) {
+			runtime_lock(&runtime_sched.lock);
+			p = pidleget();
+			runtime_unlock(&runtime_sched.lock);
+			if(p) {
+				acquirep(p);
+				goto top;
+			}
+			break;
+		}
+	}
+	// poll network
+	if(runtime_xchg64(&runtime_sched.lastpoll, 0) != 0) {
+		if(m->p)
+			runtime_throw("findrunnable: netpoll with p");
+		if(m->spinning)
+			runtime_throw("findrunnable: netpoll with spinning");
+		gp = runtime_netpoll(true);  // block until new work is available
+		runtime_atomicstore64(&runtime_sched.lastpoll, runtime_nanotime());
+		if(gp) {
+			runtime_lock(&runtime_sched.lock);
+			p = pidleget();
+			runtime_unlock(&runtime_sched.lock);
+			if(p) {
+				acquirep(p);
+				injectglist(gp->schedlink);
+				gp->status = Grunnable;
+				return gp;
+			}
+			injectglist(gp);
+		}
+	}
+	stopm();
+	goto top;
+}
+
+static void
+resetspinning(void)
+{
+	int32 nmspinning;
+
+	if(m->spinning) {
+		m->spinning = false;
+		nmspinning = runtime_xadd(&runtime_sched.nmspinning, -1);
+		if(nmspinning < 0)
+			runtime_throw("findrunnable: negative nmspinning");
+	} else
+		nmspinning = runtime_atomicload(&runtime_sched.nmspinning);
+
+	// M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
+	// so see if we need to wakeup another P here.
+	if (nmspinning == 0 && runtime_atomicload(&runtime_sched.npidle) > 0)
+		wakep();
+}
+
+// Injects the list of runnable G's into the scheduler.
+// Can run concurrently with GC.
+static void
+injectglist(G *glist)
+{
+	int32 n;
+	G *gp;
+
+	if(glist == nil)
+		return;
+	runtime_lock(&runtime_sched.lock);
+	for(n = 0; glist; n++) {
+		gp = glist;
+		glist = gp->schedlink;
+		gp->status = Grunnable;
+		globrunqput(gp);
+	}
+	runtime_unlock(&runtime_sched.lock);
+
+	for(; n && runtime_sched.npidle; n--)
+		startm(nil, false);
+}
+
+// One round of scheduler: find a runnable goroutine and execute it.
+// Never returns.
+static void
+schedule(void)
+{
+	G *gp;
+	uint32 tick;
+
+	if(m->locks)
+		runtime_throw("schedule: holding locks");
+
+top:
+	if(runtime_sched.gcwaiting) {
+		gcstopm();
+		goto top;
+	}
+
+	gp = nil;
+	// Check the global runnable queue once in a while to ensure fairness.
+	// Otherwise two goroutines can completely occupy the local runqueue
+	// by constantly respawning each other.
+	tick = m->p->schedtick;
+	// This is a fancy way to say tick%61==0,
+	// it uses 2 MUL instructions instead of a single DIV and so is faster on modern processors.
+	if(tick - (((uint64)tick*0x4325c53fu)>>36)*61 == 0 && runtime_sched.runqsize > 0) {
+		runtime_lock(&runtime_sched.lock);
+		gp = globrunqget(m->p, 1);
+		runtime_unlock(&runtime_sched.lock);
+		if(gp)
+			resetspinning();
+	}
+	if(gp == nil) {
+		gp = runqget(m->p);
+		if(gp && m->spinning)
+			runtime_throw("schedule: spinning with local work");
+	}
+	if(gp == nil) {
+		gp = findrunnable();  // blocks until work is available
+		resetspinning();
+	}
+
+	if(gp->lockedm) {
+		// Hands off own p to the locked m,
+		// then blocks waiting for a new p.
+		startlockedm(gp);
+		goto top;
+	}
+
+	execute(gp);
+}
+
+// Puts the current goroutine into a waiting state and calls unlockf.
+// If unlockf returns false, the goroutine is resumed.
+void
+runtime_park(bool(*unlockf)(G*, void*), void *lock, const char *reason)
+{
+	if(g->status != Grunning)
+		runtime_throw("bad g status");
+	m->waitlock = lock;
+	m->waitunlockf = unlockf;
+	g->waitreason = reason;
+	runtime_mcall(park0);
+}
+
+static bool
+parkunlock(G *gp, void *lock)
+{
+	USED(gp);
+	runtime_unlock(lock);
+	return true;
+}
+
+// Puts the current goroutine into a waiting state and unlocks the lock.
+// The goroutine can be made runnable again by calling runtime_ready(gp).
+void
+runtime_parkunlock(Lock *lock, const char *reason)
+{
+	runtime_park(parkunlock, lock, reason);
+}
+
+// runtime_park continuation on g0.
+static void
+park0(G *gp)
+{
+	bool ok;
+
+	gp->status = Gwaiting;
+	gp->m = nil;
+	m->curg = nil;
+	if(m->waitunlockf) {
+		ok = m->waitunlockf(gp, m->waitlock);
+		m->waitunlockf = nil;
+		m->waitlock = nil;
+		if(!ok) {
+			gp->status = Grunnable;
+			execute(gp);  // Schedule it back, never returns.
+		}
+	}
+	if(m->lockedg) {
+		stoplockedm();
+		execute(gp);  // Never returns.
+	}
+	schedule();
+}
+
+// Scheduler yield.
+void
+runtime_gosched(void)
+{
+	if(g->status != Grunning)
+		runtime_throw("bad g status");
+	runtime_mcall(runtime_gosched0);
+}
+
+// runtime_gosched continuation on g0.
+void
+runtime_gosched0(G *gp)
+{
+	gp->status = Grunnable;
+	gp->m = nil;
+	m->curg = nil;
+	runtime_lock(&runtime_sched.lock);
+	globrunqput(gp);
+	runtime_unlock(&runtime_sched.lock);
+	if(m->lockedg) {
+		stoplockedm();
+		execute(gp);  // Never returns.
+	}
+	schedule();
+}
+
+// Finishes execution of the current goroutine.
+// Need to mark it as nosplit, because it runs with sp > stackbase (as runtime_lessstack).
+// Since it does not return it does not matter.  But if it is preempted
+// at the split stack check, GC will complain about inconsistent sp.
+void runtime_goexit(void) __attribute__ ((noinline));
+void
+runtime_goexit(void)
+{
+	if(g->status != Grunning)
+		runtime_throw("bad g status");
+	if(raceenabled)
+		runtime_racegoend();
+	runtime_mcall(goexit0);
+}
+
+// runtime_goexit continuation on g0.
+static void
+goexit0(G *gp)
+{
+	gp->status = Gdead;
+	gp->entry = nil;
+	gp->m = nil;
+	gp->lockedm = nil;
+	gp->paniconfault = 0;
+	gp->defer = nil; // should be true already but just in case.
+	gp->panic = nil; // non-nil for Goexit during panic. points at stack-allocated data.
+	gp->writenbuf = 0;
+	gp->writebuf = nil;
+	gp->waitreason = nil;
+	gp->param = nil;
+	m->curg = nil;
+	m->lockedg = nil;
+	if(m->locked & ~LockExternal) {
+		runtime_printf("invalid m->locked = %d\n", m->locked);
+		runtime_throw("internal lockOSThread error");
+	}	
+	m->locked = 0;
+	gfput(m->p, gp);
+	schedule();
+}
+
+// The goroutine g is about to enter a system call.
+// Record that it's not using the cpu anymore.
+// This is called only from the go syscall library and cgocall,
+// not from the low-level system calls used by the runtime.
+//
+// Entersyscall cannot split the stack: the runtime_gosave must
+// make g->sched refer to the caller's stack segment, because
+// entersyscall is going to return immediately after.
+
+void runtime_entersyscall(void) __attribute__ ((no_split_stack));
+static void doentersyscall(void) __attribute__ ((no_split_stack, noinline));
+
+void
+runtime_entersyscall()
+{
+	// Save the registers in the g structure so that any pointers
+	// held in registers will be seen by the garbage collector.
+	getcontext(&g->gcregs);
+
+	// Do the work in a separate function, so that this function
+	// doesn't save any registers on its own stack.  If this
+	// function does save any registers, we might store the wrong
+	// value in the call to getcontext.
+	//
+	// FIXME: This assumes that we do not need to save any
+	// callee-saved registers to access the TLS variable g.  We
+	// don't want to put the ucontext_t on the stack because it is
+	// large and we can not split the stack here.
+	doentersyscall();
+}
+
+static void
+doentersyscall()
+{
+	// Disable preemption because during this function g is in Gsyscall status,
+	// but can have inconsistent g->sched, do not let GC observe it.
+	m->locks++;
+
+	// Leave SP around for GC and traceback.
+#ifdef USING_SPLIT_STACK
+	g->gcstack = __splitstack_find(nil, nil, &g->gcstack_size,
+				       &g->gcnext_segment, &g->gcnext_sp,
+				       &g->gcinitial_sp);
+#else
+	{
+		void *v;
+
+		g->gcnext_sp = (byte *) &v;
+	}
+#endif
+
+	g->status = Gsyscall;
+
+	if(runtime_atomicload(&runtime_sched.sysmonwait)) {  // TODO: fast atomic
+		runtime_lock(&runtime_sched.lock);
+		if(runtime_atomicload(&runtime_sched.sysmonwait)) {
+			runtime_atomicstore(&runtime_sched.sysmonwait, 0);
+			runtime_notewakeup(&runtime_sched.sysmonnote);
+		}
+		runtime_unlock(&runtime_sched.lock);
+	}
+
+	m->mcache = nil;
+	m->p->m = nil;
+	runtime_atomicstore(&m->p->status, Psyscall);
+	if(runtime_sched.gcwaiting) {
+		runtime_lock(&runtime_sched.lock);
+		if (runtime_sched.stopwait > 0 && runtime_cas(&m->p->status, Psyscall, Pgcstop)) {
+			if(--runtime_sched.stopwait == 0)
+				runtime_notewakeup(&runtime_sched.stopnote);
+		}
+		runtime_unlock(&runtime_sched.lock);
+	}
+
+	m->locks--;
+}
+
+// The same as runtime_entersyscall(), but with a hint that the syscall is blocking.
+void
+runtime_entersyscallblock(void)
+{
+	P *p;
+
+	m->locks++;  // see comment in entersyscall
+
+	// Leave SP around for GC and traceback.
+#ifdef USING_SPLIT_STACK
+	g->gcstack = __splitstack_find(nil, nil, &g->gcstack_size,
+				       &g->gcnext_segment, &g->gcnext_sp,
+				       &g->gcinitial_sp);
+#else
+	g->gcnext_sp = (byte *) &p;
+#endif
+
+	// Save the registers in the g structure so that any pointers
+	// held in registers will be seen by the garbage collector.
+	getcontext(&g->gcregs);
+
+	g->status = Gsyscall;
+
+	p = releasep();
+	handoffp(p);
+	if(g->isbackground)  // do not consider blocked scavenger for deadlock detection
+		incidlelocked(1);
+
+	m->locks--;
+}
+
+// The goroutine g exited its system call.
+// Arrange for it to run on a cpu again.
+// This is called only from the go syscall library, not
+// from the low-level system calls used by the runtime.
+void
+runtime_exitsyscall(void)
+{
+	G *gp;
+
+	m->locks++;  // see comment in entersyscall
+
+	gp = g;
+	if(gp->isbackground)  // do not consider blocked scavenger for deadlock detection
+		incidlelocked(-1);
+
+	g->waitsince = 0;
+	if(exitsyscallfast()) {
+		// There's a cpu for us, so we can run.
+		m->p->syscalltick++;
+		gp->status = Grunning;
+		// Garbage collector isn't running (since we are),
+		// so okay to clear gcstack and gcsp.
+#ifdef USING_SPLIT_STACK
+		gp->gcstack = nil;
+#endif
+		gp->gcnext_sp = nil;
+		runtime_memclr(&gp->gcregs, sizeof gp->gcregs);
+		m->locks--;
+		return;
+	}
+
+	m->locks--;
+
+	// Call the scheduler.
+	runtime_mcall(exitsyscall0);
+
+	// Scheduler returned, so we're allowed to run now.
+	// Delete the gcstack information that we left for
+	// the garbage collector during the system call.
+	// Must wait until now because until gosched returns
+	// we don't know for sure that the garbage collector
+	// is not running.
+#ifdef USING_SPLIT_STACK
+	gp->gcstack = nil;
+#endif
+	gp->gcnext_sp = nil;
+	runtime_memclr(&gp->gcregs, sizeof gp->gcregs);
+
+	// Don't refer to m again, we might be running on a different
+	// thread after returning from runtime_mcall.
+	runtime_m()->p->syscalltick++;
+}
+
+static bool
+exitsyscallfast(void)
+{
+	P *p;
+
+	// Freezetheworld sets stopwait but does not retake P's.
+	if(runtime_sched.stopwait) {
+		m->p = nil;
+		return false;
+	}
+
+	// Try to re-acquire the last P.
+	if(m->p && m->p->status == Psyscall && runtime_cas(&m->p->status, Psyscall, Prunning)) {
+		// There's a cpu for us, so we can run.
+		m->mcache = m->p->mcache;
+		m->p->m = m;
+		return true;
+	}
+	// Try to get any other idle P.
+	m->p = nil;
+	if(runtime_sched.pidle) {
+		runtime_lock(&runtime_sched.lock);
+		p = pidleget();
+		if(p && runtime_atomicload(&runtime_sched.sysmonwait)) {
+			runtime_atomicstore(&runtime_sched.sysmonwait, 0);
+			runtime_notewakeup(&runtime_sched.sysmonnote);
+		}
+		runtime_unlock(&runtime_sched.lock);
+		if(p) {
+			acquirep(p);
+			return true;
+		}
+	}
+	return false;
+}
+
+// runtime_exitsyscall slow path on g0.
+// Failed to acquire P, enqueue gp as runnable.
+static void
+exitsyscall0(G *gp)
+{
+	P *p;
+
+	gp->status = Grunnable;
+	gp->m = nil;
+	m->curg = nil;
+	runtime_lock(&runtime_sched.lock);
+	p = pidleget();
+	if(p == nil)
+		globrunqput(gp);
+	else if(runtime_atomicload(&runtime_sched.sysmonwait)) {
+		runtime_atomicstore(&runtime_sched.sysmonwait, 0);
+		runtime_notewakeup(&runtime_sched.sysmonnote);
+	}
+	runtime_unlock(&runtime_sched.lock);
+	if(p) {
+		acquirep(p);
+		execute(gp);  // Never returns.
+	}
+	if(m->lockedg) {
+		// Wait until another thread schedules gp and so m again.
+		stoplockedm();
+		execute(gp);  // Never returns.
+	}
+	stopm();
+	schedule();  // Never returns.
+}
+
+// Called from syscall package before fork.
+void syscall_runtime_BeforeFork(void)
+  __asm__(GOSYM_PREFIX "syscall.runtime_BeforeFork");
+void
+syscall_runtime_BeforeFork(void)
+{
+	// Fork can hang if preempted with signals frequently enough (see issue 5517).
+	// Ensure that we stay on the same M where we disable profiling.
+	runtime_m()->locks++;
+	if(runtime_m()->profilehz != 0)
+		runtime_resetcpuprofiler(0);
+}
+
+// Called from syscall package after fork in parent.
+void syscall_runtime_AfterFork(void)
+  __asm__(GOSYM_PREFIX "syscall.runtime_AfterFork");
+void
+syscall_runtime_AfterFork(void)
+{
+	int32 hz;
+
+	hz = runtime_sched.profilehz;
+	if(hz != 0)
+		runtime_resetcpuprofiler(hz);
+	runtime_m()->locks--;
+}
+
+// Allocate a new g, with a stack big enough for stacksize bytes.
+G*
+runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
+{
+	G *newg;
+
+	newg = allocg();
+	if(stacksize >= 0) {
+#if USING_SPLIT_STACK
+		int dont_block_signals = 0;
+
+		*ret_stack = __splitstack_makecontext(stacksize,
+						      &newg->stack_context[0],
+						      ret_stacksize);
+		__splitstack_block_signals_context(&newg->stack_context[0],
+						   &dont_block_signals, nil);
+#else
+		*ret_stack = runtime_mallocgc(stacksize, 0, FlagNoProfiling|FlagNoGC);
+		*ret_stacksize = stacksize;
+		newg->gcinitial_sp = *ret_stack;
+		newg->gcstack_size = stacksize;
+		runtime_xadd(&runtime_stacks_sys, stacksize);
+#endif
+	}
+	return newg;
+}
+
+/* For runtime package testing.  */
+
+
+// Create a new g running fn with siz bytes of arguments.
+// Put it on the queue of g's waiting to run.
+// The compiler turns a go statement into a call to this.
+// Cannot split the stack because it assumes that the arguments
+// are available sequentially after &fn; they would not be
+// copied if a stack split occurred.  It's OK for this to call
+// functions that split the stack.
+void runtime_testing_entersyscall(void)
+  __asm__ (GOSYM_PREFIX "runtime.entersyscall");
+void
+runtime_testing_entersyscall()
+{
+	runtime_entersyscall();
+}
+
+void runtime_testing_exitsyscall(void)
+  __asm__ (GOSYM_PREFIX "runtime.exitsyscall");
+
+void
+runtime_testing_exitsyscall()
+{
+	runtime_exitsyscall();
+}
+
+G*
+__go_go(void (*fn)(void*), void* arg)
+{
+	byte *sp;
+	size_t spsize;
+	G *newg;
+	P *p;
+
+//runtime_printf("newproc1 %p %p narg=%d nret=%d\n", fn->fn, argp, narg, nret);
+	if(fn == nil) {
+		m->throwing = -1;  // do not dump full stacks
+		runtime_throw("go of nil func value");
+	}
+	m->locks++;  // disable preemption because it can be holding p in a local var
+
+	p = m->p;
+	if((newg = gfget(p)) != nil) {
+#ifdef USING_SPLIT_STACK
+		int dont_block_signals = 0;
+
+		sp = __splitstack_resetcontext(&newg->stack_context[0],
+					       &spsize);
+		__splitstack_block_signals_context(&newg->stack_context[0],
+						   &dont_block_signals, nil);
+#else
+		sp = newg->gcinitial_sp;
+		spsize = newg->gcstack_size;
+		if(spsize == 0)
+			runtime_throw("bad spsize in __go_go");
+		newg->gcnext_sp = sp;
+#endif
+	} else {
+		newg = runtime_malg(StackMin, &sp, &spsize);
+		allgadd(newg);
+	}
+
+	newg->entry = (byte*)fn;
+	newg->param = arg;
+	newg->gopc = (uintptr)__builtin_return_address(0);
+	newg->status = Grunnable;
+	if(p->goidcache == p->goidcacheend) {
+		p->goidcache = runtime_xadd64(&runtime_sched.goidgen, GoidCacheBatch);
+		p->goidcacheend = p->goidcache + GoidCacheBatch;
+	}
+	newg->goid = p->goidcache++;
+
+	{
+		// Avoid warnings about variables clobbered by
+		// longjmp.
+		byte * volatile vsp = sp;
+		size_t volatile vspsize = spsize;
+		G * volatile vnewg = newg;
+
+		getcontext(&vnewg->context);
+		vnewg->context.uc_stack.ss_sp = vsp;
+#ifdef MAKECONTEXT_STACK_TOP
+		vnewg->context.uc_stack.ss_sp += vspsize;
+#endif
+		vnewg->context.uc_stack.ss_size = vspsize;
+		makecontext(&vnewg->context, kickoff, 0);
+
+		runqput(p, vnewg);
+
+		if(runtime_atomicload(&runtime_sched.npidle) != 0 && runtime_atomicload(&runtime_sched.nmspinning) == 0 && fn != runtime_main)  // TODO: fast atomic
+			wakep();
+		m->locks--;
+		return vnewg;
+	}
+}
+
+static void
+allgadd(G *gp)
+{
+	G **new;
+	uintptr cap;
+
+	runtime_lock(&allglock);
+	if(runtime_allglen >= allgcap) {
+		cap = 4096/sizeof(new[0]);
+		if(cap < 2*allgcap)
+			cap = 2*allgcap;
+		new = runtime_malloc(cap*sizeof(new[0]));
+		if(new == nil)
+			runtime_throw("runtime: cannot allocate memory");
+		if(runtime_allg != nil) {
+			runtime_memmove(new, runtime_allg, runtime_allglen*sizeof(new[0]));
+			runtime_free(runtime_allg);
+		}
+		runtime_allg = new;
+		allgcap = cap;
+	}
+	runtime_allg[runtime_allglen++] = gp;
+	runtime_unlock(&allglock);
+}
+
+// Put on gfree list.
+// If local list is too long, transfer a batch to the global list.
+static void
+gfput(P *p, G *gp)
+{
+	gp->schedlink = p->gfree;
+	p->gfree = gp;
+	p->gfreecnt++;
+	if(p->gfreecnt >= 64) {
+		runtime_lock(&runtime_sched.gflock);
+		while(p->gfreecnt >= 32) {
+			p->gfreecnt--;
+			gp = p->gfree;
+			p->gfree = gp->schedlink;
+			gp->schedlink = runtime_sched.gfree;
+			runtime_sched.gfree = gp;
+		}
+		runtime_unlock(&runtime_sched.gflock);
+	}
+}
+
+// Get from gfree list.
+// If local list is empty, grab a batch from global list.
+static G*
+gfget(P *p)
+{
+	G *gp;
+
+retry:
+	gp = p->gfree;
+	if(gp == nil && runtime_sched.gfree) {
+		runtime_lock(&runtime_sched.gflock);
+		while(p->gfreecnt < 32 && runtime_sched.gfree) {
+			p->gfreecnt++;
+			gp = runtime_sched.gfree;
+			runtime_sched.gfree = gp->schedlink;
+			gp->schedlink = p->gfree;
+			p->gfree = gp;
+		}
+		runtime_unlock(&runtime_sched.gflock);
+		goto retry;
+	}
+	if(gp) {
+		p->gfree = gp->schedlink;
+		p->gfreecnt--;
+	}
+	return gp;
+}
+
+// Purge all cached G's from gfree list to the global list.
+static void
+gfpurge(P *p)
+{
+	G *gp;
+
+	runtime_lock(&runtime_sched.gflock);
+	while(p->gfreecnt) {
+		p->gfreecnt--;
+		gp = p->gfree;
+		p->gfree = gp->schedlink;
+		gp->schedlink = runtime_sched.gfree;
+		runtime_sched.gfree = gp;
+	}
+	runtime_unlock(&runtime_sched.gflock);
+}
+
+void
+runtime_Breakpoint(void)
+{
+	runtime_breakpoint();
+}
+
+void runtime_Gosched (void) __asm__ (GOSYM_PREFIX "runtime.Gosched");
+
+void
+runtime_Gosched(void)
+{
+	runtime_gosched();
+}
+
+// Implementation of runtime.GOMAXPROCS.
+// delete when scheduler is even stronger
+int32
+runtime_gomaxprocsfunc(int32 n)
+{
+	int32 ret;
+
+	if(n > MaxGomaxprocs)
+		n = MaxGomaxprocs;
+	runtime_lock(&runtime_sched.lock);
+	ret = runtime_gomaxprocs;
+	if(n <= 0 || n == ret) {
+		runtime_unlock(&runtime_sched.lock);
+		return ret;
+	}
+	runtime_unlock(&runtime_sched.lock);
+
+	runtime_semacquire(&runtime_worldsema, false);
+	m->gcing = 1;
+	runtime_stoptheworld();
+	newprocs = n;
+	m->gcing = 0;
+	runtime_semrelease(&runtime_worldsema);
+	runtime_starttheworld();
+
+	return ret;
+}
+
+// lockOSThread is called by runtime.LockOSThread and runtime.lockOSThread below
+// after they modify m->locked. Do not allow preemption during this call,
+// or else the m might be different in this function than in the caller.
+static void
+lockOSThread(void)
+{
+	m->lockedg = g;
+	g->lockedm = m;
+}
+
+void	runtime_LockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.LockOSThread");
+void
+runtime_LockOSThread(void)
+{
+	m->locked |= LockExternal;
+	lockOSThread();
+}
+
+void
+runtime_lockOSThread(void)
+{
+	m->locked += LockInternal;
+	lockOSThread();
+}
+
+
+// unlockOSThread is called by runtime.UnlockOSThread and runtime.unlockOSThread below
+// after they update m->locked. Do not allow preemption during this call,
+// or else the m might be in different in this function than in the caller.
+static void
+unlockOSThread(void)
+{
+	if(m->locked != 0)
+		return;
+	m->lockedg = nil;
+	g->lockedm = nil;
+}
+
+void	runtime_UnlockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.UnlockOSThread");
+
+void
+runtime_UnlockOSThread(void)
+{
+	m->locked &= ~LockExternal;
+	unlockOSThread();
+}
+
+void
+runtime_unlockOSThread(void)
+{
+	if(m->locked < LockInternal)
+		runtime_throw("runtime: internal error: misuse of lockOSThread/unlockOSThread");
+	m->locked -= LockInternal;
+	unlockOSThread();
+}
+
+bool
+runtime_lockedOSThread(void)
+{
+	return g->lockedm != nil && m->lockedg != nil;
+}
+
+int32
+runtime_gcount(void)
+{
+	G *gp;
+	int32 n, s;
+	uintptr i;
+
+	n = 0;
+	runtime_lock(&allglock);
+	// TODO(dvyukov): runtime.NumGoroutine() is O(N).
+	// We do not want to increment/decrement centralized counter in newproc/goexit,
+	// just to make runtime.NumGoroutine() faster.
+	// Compromise solution is to introduce per-P counters of active goroutines.
+	for(i = 0; i < runtime_allglen; i++) {
+		gp = runtime_allg[i];
+		s = gp->status;
+		if(s == Grunnable || s == Grunning || s == Gsyscall || s == Gwaiting)
+			n++;
+	}
+	runtime_unlock(&allglock);
+	return n;
+}
+
+int32
+runtime_mcount(void)
+{
+	return runtime_sched.mcount;
+}
+
+static struct {
+	Lock lock;
+	void (*fn)(uintptr*, int32);
+	int32 hz;
+	uintptr pcbuf[TracebackMaxFrames];
+	Location locbuf[TracebackMaxFrames];
+} prof;
+
+static void System(void) {}
+static void GC(void) {}
+
+// Called if we receive a SIGPROF signal.
+void
+runtime_sigprof()
+{
+	M *mp = m;
+	int32 n, i;
+	bool traceback;
+
+	if(prof.fn == nil || prof.hz == 0)
+		return;
+
+	if(mp == nil)
+		return;
+
+	// Profiling runs concurrently with GC, so it must not allocate.
+	mp->mallocing++;
+
+	traceback = true;
+
+	if(mp->mcache == nil)
+		traceback = false;
+
+	runtime_lock(&prof.lock);
+	if(prof.fn == nil) {
+		runtime_unlock(&prof.lock);
+		mp->mallocing--;
+		return;
+	}
+	n = 0;
+
+	if(runtime_atomicload(&runtime_in_callers) > 0) {
+		// If SIGPROF arrived while already fetching runtime
+		// callers we can have trouble on older systems
+		// because the unwind library calls dl_iterate_phdr
+		// which was not recursive in the past.
+		traceback = false;
+	}
+
+	if(traceback) {
+		n = runtime_callers(0, prof.locbuf, nelem(prof.locbuf), false);
+		for(i = 0; i < n; i++)
+			prof.pcbuf[i] = prof.locbuf[i].pc;
+	}
+	if(!traceback || n <= 0) {
+		n = 2;
+		prof.pcbuf[0] = (uintptr)runtime_getcallerpc(&n);
+		if(mp->gcing || mp->helpgc)
+			prof.pcbuf[1] = (uintptr)GC;
+		else
+			prof.pcbuf[1] = (uintptr)System;
+	}
+	prof.fn(prof.pcbuf, n);
+	runtime_unlock(&prof.lock);
+	mp->mallocing--;
+}
+
+// Arrange to call fn with a traceback hz times a second.
+void
+runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
+{
+	// Force sane arguments.
+	if(hz < 0)
+		hz = 0;
+	if(hz == 0)
+		fn = nil;
+	if(fn == nil)
+		hz = 0;
+
+	// Disable preemption, otherwise we can be rescheduled to another thread
+	// that has profiling enabled.
+	m->locks++;
+
+	// Stop profiler on this thread so that it is safe to lock prof.
+	// if a profiling signal came in while we had prof locked,
+	// it would deadlock.
+	runtime_resetcpuprofiler(0);
+
+	runtime_lock(&prof.lock);
+	prof.fn = fn;
+	prof.hz = hz;
+	runtime_unlock(&prof.lock);
+	runtime_lock(&runtime_sched.lock);
+	runtime_sched.profilehz = hz;
+	runtime_unlock(&runtime_sched.lock);
+
+	if(hz != 0)
+		runtime_resetcpuprofiler(hz);
+
+	m->locks--;
+}
+
+// Change number of processors.  The world is stopped, sched is locked.
+static void
+procresize(int32 new)
+{
+	int32 i, old;
+	bool empty;
+	G *gp;
+	P *p;
+
+	old = runtime_gomaxprocs;
+	if(old < 0 || old > MaxGomaxprocs || new <= 0 || new >MaxGomaxprocs)
+		runtime_throw("procresize: invalid arg");
+	// initialize new P's
+	for(i = 0; i < new; i++) {
+		p = runtime_allp[i];
+		if(p == nil) {
+			p = (P*)runtime_mallocgc(sizeof(*p), 0, FlagNoInvokeGC);
+			p->id = i;
+			p->status = Pgcstop;
+			runtime_atomicstorep(&runtime_allp[i], p);
+		}
+		if(p->mcache == nil) {
+			if(old==0 && i==0)
+				p->mcache = m->mcache;  // bootstrap
+			else
+				p->mcache = runtime_allocmcache();
+		}
+	}
+
+	// redistribute runnable G's evenly
+	// collect all runnable goroutines in global queue preserving FIFO order
+	// FIFO order is required to ensure fairness even during frequent GCs
+	// see http://golang.org/issue/7126
+	empty = false;
+	while(!empty) {
+		empty = true;
+		for(i = 0; i < old; i++) {
+			p = runtime_allp[i];
+			if(p->runqhead == p->runqtail)
+				continue;
+			empty = false;
+			// pop from tail of local queue
+			p->runqtail--;
+			gp = p->runq[p->runqtail%nelem(p->runq)];
+			// push onto head of global queue
+			gp->schedlink = runtime_sched.runqhead;
+			runtime_sched.runqhead = gp;
+			if(runtime_sched.runqtail == nil)
+				runtime_sched.runqtail = gp;
+			runtime_sched.runqsize++;
+		}
+	}
+	// fill local queues with at most nelem(p->runq)/2 goroutines
+	// start at 1 because current M already executes some G and will acquire allp[0] below,
+	// so if we have a spare G we want to put it into allp[1].
+	for(i = 1; (uint32)i < (uint32)new * nelem(p->runq)/2 && runtime_sched.runqsize > 0; i++) {
+		gp = runtime_sched.runqhead;
+		runtime_sched.runqhead = gp->schedlink;
+		if(runtime_sched.runqhead == nil)
+			runtime_sched.runqtail = nil;
+		runtime_sched.runqsize--;
+		runqput(runtime_allp[i%new], gp);
+	}
+
+	// free unused P's
+	for(i = new; i < old; i++) {
+		p = runtime_allp[i];
+		runtime_freemcache(p->mcache);
+		p->mcache = nil;
+		gfpurge(p);
+		p->status = Pdead;
+		// can't free P itself because it can be referenced by an M in syscall
+	}
+
+	if(m->p)
+		m->p->m = nil;
+	m->p = nil;
+	m->mcache = nil;
+	p = runtime_allp[0];
+	p->m = nil;
+	p->status = Pidle;
+	acquirep(p);
+	for(i = new-1; i > 0; i--) {
+		p = runtime_allp[i];
+		p->status = Pidle;
+		pidleput(p);
+	}
+	runtime_atomicstore((uint32*)&runtime_gomaxprocs, new);
+}
+
+// Associate p and the current m.
+static void
+acquirep(P *p)
+{
+	if(m->p || m->mcache)
+		runtime_throw("acquirep: already in go");
+	if(p->m || p->status != Pidle) {
+		runtime_printf("acquirep: p->m=%p(%d) p->status=%d\n", p->m, p->m ? p->m->id : 0, p->status);
+		runtime_throw("acquirep: invalid p state");
+	}
+	m->mcache = p->mcache;
+	m->p = p;
+	p->m = m;
+	p->status = Prunning;
+}
+
+// Disassociate p and the current m.
+static P*
+releasep(void)
+{
+	P *p;
+
+	if(m->p == nil || m->mcache == nil)
+		runtime_throw("releasep: invalid arg");
+	p = m->p;
+	if(p->m != m || p->mcache != m->mcache || p->status != Prunning) {
+		runtime_printf("releasep: m=%p m->p=%p p->m=%p m->mcache=%p p->mcache=%p p->status=%d\n",
+			m, m->p, p->m, m->mcache, p->mcache, p->status);
+		runtime_throw("releasep: invalid p state");
+	}
+	m->p = nil;
+	m->mcache = nil;
+	p->m = nil;
+	p->status = Pidle;
+	return p;
+}
+
+static void
+incidlelocked(int32 v)
+{
+	runtime_lock(&runtime_sched.lock);
+	runtime_sched.nmidlelocked += v;
+	if(v > 0)
+		checkdead();
+	runtime_unlock(&runtime_sched.lock);
+}
+
+// Check for deadlock situation.
+// The check is based on number of running M's, if 0 -> deadlock.
+static void
+checkdead(void)
+{
+	G *gp;
+	int32 run, grunning, s;
+	uintptr i;
+
+	// -1 for sysmon
+	run = runtime_sched.mcount - runtime_sched.nmidle - runtime_sched.nmidlelocked - 1 - countextra();
+	if(run > 0)
+		return;
+	// If we are dying because of a signal caught on an already idle thread,
+	// freezetheworld will cause all running threads to block.
+	// And runtime will essentially enter into deadlock state,
+	// except that there is a thread that will call runtime_exit soon.
+	if(runtime_panicking > 0)
+		return;
+	if(run < 0) {
+		runtime_printf("runtime: checkdead: nmidle=%d nmidlelocked=%d mcount=%d\n",
+			runtime_sched.nmidle, runtime_sched.nmidlelocked, runtime_sched.mcount);
+		runtime_throw("checkdead: inconsistent counts");
+	}
+	grunning = 0;
+	runtime_lock(&allglock);
+	for(i = 0; i < runtime_allglen; i++) {
+		gp = runtime_allg[i];
+		if(gp->isbackground)
+			continue;
+		s = gp->status;
+		if(s == Gwaiting)
+			grunning++;
+		else if(s == Grunnable || s == Grunning || s == Gsyscall) {
+			runtime_unlock(&allglock);
+			runtime_printf("runtime: checkdead: find g %D in status %d\n", gp->goid, s);
+			runtime_throw("checkdead: runnable g");
+		}
+	}
+	runtime_unlock(&allglock);
+	if(grunning == 0)  // possible if main goroutine calls runtime_Goexit()
+		runtime_throw("no goroutines (main called runtime.Goexit) - deadlock!");
+	m->throwing = -1;  // do not dump full stacks
+	runtime_throw("all goroutines are asleep - deadlock!");
+}
+
+static void
+sysmon(void)
+{
+	uint32 idle, delay;
+	int64 now, lastpoll, lasttrace;
+	G *gp;
+
+	lasttrace = 0;
+	idle = 0;  // how many cycles in succession we had not wokeup somebody
+	delay = 0;
+	for(;;) {
+		if(idle == 0)  // start with 20us sleep...
+			delay = 20;
+		else if(idle > 50)  // start doubling the sleep after 1ms...
+			delay *= 2;
+		if(delay > 10*1000)  // up to 10ms
+			delay = 10*1000;
+		runtime_usleep(delay);
+		if(runtime_debug.schedtrace <= 0 &&
+			(runtime_sched.gcwaiting || runtime_atomicload(&runtime_sched.npidle) == (uint32)runtime_gomaxprocs)) {  // TODO: fast atomic
+			runtime_lock(&runtime_sched.lock);
+			if(runtime_atomicload(&runtime_sched.gcwaiting) || runtime_atomicload(&runtime_sched.npidle) == (uint32)runtime_gomaxprocs) {
+				runtime_atomicstore(&runtime_sched.sysmonwait, 1);
+				runtime_unlock(&runtime_sched.lock);
+				runtime_notesleep(&runtime_sched.sysmonnote);
+				runtime_noteclear(&runtime_sched.sysmonnote);
+				idle = 0;
+				delay = 20;
+			} else
+				runtime_unlock(&runtime_sched.lock);
+		}
+		// poll network if not polled for more than 10ms
+		lastpoll = runtime_atomicload64(&runtime_sched.lastpoll);
+		now = runtime_nanotime();
+		if(lastpoll != 0 && lastpoll + 10*1000*1000 < now) {
+			runtime_cas64(&runtime_sched.lastpoll, lastpoll, now);
+			gp = runtime_netpoll(false);  // non-blocking
+			if(gp) {
+				// Need to decrement number of idle locked M's
+				// (pretending that one more is running) before injectglist.
+				// Otherwise it can lead to the following situation:
+				// injectglist grabs all P's but before it starts M's to run the P's,
+				// another M returns from syscall, finishes running its G,
+				// observes that there is no work to do and no other running M's
+				// and reports deadlock.
+				incidlelocked(-1);
+				injectglist(gp);
+				incidlelocked(1);
+			}
+		}
+		// retake P's blocked in syscalls
+		// and preempt long running G's
+		if(retake(now))
+			idle = 0;
+		else
+			idle++;
+
+		if(runtime_debug.schedtrace > 0 && lasttrace + runtime_debug.schedtrace*1000000ll <= now) {
+			lasttrace = now;
+			runtime_schedtrace(runtime_debug.scheddetail);
+		}
+	}
+}
+
+typedef struct Pdesc Pdesc;
+struct Pdesc
+{
+	uint32	schedtick;
+	int64	schedwhen;
+	uint32	syscalltick;
+	int64	syscallwhen;
+};
+static Pdesc pdesc[MaxGomaxprocs];
+
+static uint32
+retake(int64 now)
+{
+	uint32 i, s, n;
+	int64 t;
+	P *p;
+	Pdesc *pd;
+
+	n = 0;
+	for(i = 0; i < (uint32)runtime_gomaxprocs; i++) {
+		p = runtime_allp[i];
+		if(p==nil)
+			continue;
+		pd = &pdesc[i];
+		s = p->status;
+		if(s == Psyscall) {
+			// Retake P from syscall if it's there for more than 1 sysmon tick (at least 20us).
+			t = p->syscalltick;
+			if(pd->syscalltick != t) {
+				pd->syscalltick = t;
+				pd->syscallwhen = now;
+				continue;
+			}
+			// On the one hand we don't want to retake Ps if there is no other work to do,
+			// but on the other hand we want to retake them eventually
+			// because they can prevent the sysmon thread from deep sleep.
+			if(p->runqhead == p->runqtail &&
+				runtime_atomicload(&runtime_sched.nmspinning) + runtime_atomicload(&runtime_sched.npidle) > 0 &&
+				pd->syscallwhen + 10*1000*1000 > now)
+				continue;
+			// Need to decrement number of idle locked M's
+			// (pretending that one more is running) before the CAS.
+			// Otherwise the M from which we retake can exit the syscall,
+			// increment nmidle and report deadlock.
+			incidlelocked(-1);
+			if(runtime_cas(&p->status, s, Pidle)) {
+				n++;
+				handoffp(p);
+			}
+			incidlelocked(1);
+		} else if(s == Prunning) {
+			// Preempt G if it's running for more than 10ms.
+			t = p->schedtick;
+			if(pd->schedtick != t) {
+				pd->schedtick = t;
+				pd->schedwhen = now;
+				continue;
+			}
+			if(pd->schedwhen + 10*1000*1000 > now)
+				continue;
+			// preemptone(p);
+		}
+	}
+	return n;
+}
+
+// Tell all goroutines that they have been preempted and they should stop.
+// This function is purely best-effort.  It can fail to inform a goroutine if a
+// processor just started running it.
+// No locks need to be held.
+// Returns true if preemption request was issued to at least one goroutine.
+static bool
+preemptall(void)
+{
+	return false;
+}
+
+void
+runtime_schedtrace(bool detailed)
+{
+	static int64 starttime;
+	int64 now;
+	int64 id1, id2, id3;
+	int32 i, t, h;
+	uintptr gi;
+	const char *fmt;
+	M *mp, *lockedm;
+	G *gp, *lockedg;
+	P *p;
+
+	now = runtime_nanotime();
+	if(starttime == 0)
+		starttime = now;
+
+	runtime_lock(&runtime_sched.lock);
+	runtime_printf("SCHED %Dms: gomaxprocs=%d idleprocs=%d threads=%d idlethreads=%d runqueue=%d",
+		(now-starttime)/1000000, runtime_gomaxprocs, runtime_sched.npidle, runtime_sched.mcount,
+		runtime_sched.nmidle, runtime_sched.runqsize);
+	if(detailed) {
+		runtime_printf(" gcwaiting=%d nmidlelocked=%d nmspinning=%d stopwait=%d sysmonwait=%d\n",
+			runtime_sched.gcwaiting, runtime_sched.nmidlelocked, runtime_sched.nmspinning,
+			runtime_sched.stopwait, runtime_sched.sysmonwait);
+	}
+	// We must be careful while reading data from P's, M's and G's.
+	// Even if we hold schedlock, most data can be changed concurrently.
+	// E.g. (p->m ? p->m->id : -1) can crash if p->m changes from non-nil to nil.
+	for(i = 0; i < runtime_gomaxprocs; i++) {
+		p = runtime_allp[i];
+		if(p == nil)
+			continue;
+		mp = p->m;
+		h = runtime_atomicload(&p->runqhead);
+		t = runtime_atomicload(&p->runqtail);
+		if(detailed)
+			runtime_printf("  P%d: status=%d schedtick=%d syscalltick=%d m=%d runqsize=%d gfreecnt=%d\n",
+				i, p->status, p->schedtick, p->syscalltick, mp ? mp->id : -1, t-h, p->gfreecnt);
+		else {
+			// In non-detailed mode format lengths of per-P run queues as:
+			// [len1 len2 len3 len4]
+			fmt = " %d";
+			if(runtime_gomaxprocs == 1)
+				fmt = " [%d]\n";
+			else if(i == 0)
+				fmt = " [%d";
+			else if(i == runtime_gomaxprocs-1)
+				fmt = " %d]\n";
+			runtime_printf(fmt, t-h);
+		}
+	}
+	if(!detailed) {
+		runtime_unlock(&runtime_sched.lock);
+		return;
+	}
+	for(mp = runtime_allm; mp; mp = mp->alllink) {
+		p = mp->p;
+		gp = mp->curg;
+		lockedg = mp->lockedg;
+		id1 = -1;
+		if(p)
+			id1 = p->id;
+		id2 = -1;
+		if(gp)
+			id2 = gp->goid;
+		id3 = -1;
+		if(lockedg)
+			id3 = lockedg->goid;
+		runtime_printf("  M%d: p=%D curg=%D mallocing=%d throwing=%d gcing=%d"
+			" locks=%d dying=%d helpgc=%d spinning=%d blocked=%d lockedg=%D\n",
+			mp->id, id1, id2,
+			mp->mallocing, mp->throwing, mp->gcing, mp->locks, mp->dying, mp->helpgc,
+			mp->spinning, m->blocked, id3);
+	}
+	runtime_lock(&allglock);
+	for(gi = 0; gi < runtime_allglen; gi++) {
+		gp = runtime_allg[gi];
+		mp = gp->m;
+		lockedm = gp->lockedm;
+		runtime_printf("  G%D: status=%d(%s) m=%d lockedm=%d\n",
+			gp->goid, gp->status, gp->waitreason, mp ? mp->id : -1,
+			lockedm ? lockedm->id : -1);
+	}
+	runtime_unlock(&allglock);
+	runtime_unlock(&runtime_sched.lock);
+}
+
+// Put mp on midle list.
+// Sched must be locked.
+static void
+mput(M *mp)
+{
+	mp->schedlink = runtime_sched.midle;
+	runtime_sched.midle = mp;
+	runtime_sched.nmidle++;
+	checkdead();
+}
+
+// Try to get an m from midle list.
+// Sched must be locked.
+static M*
+mget(void)
+{
+	M *mp;
+
+	if((mp = runtime_sched.midle) != nil){
+		runtime_sched.midle = mp->schedlink;
+		runtime_sched.nmidle--;
+	}
+	return mp;
+}
+
+// Put gp on the global runnable queue.
+// Sched must be locked.
+static void
+globrunqput(G *gp)
+{
+	gp->schedlink = nil;
+	if(runtime_sched.runqtail)
+		runtime_sched.runqtail->schedlink = gp;
+	else
+		runtime_sched.runqhead = gp;
+	runtime_sched.runqtail = gp;
+	runtime_sched.runqsize++;
+}
+
+// Put a batch of runnable goroutines on the global runnable queue.
+// Sched must be locked.
+static void
+globrunqputbatch(G *ghead, G *gtail, int32 n)
+{
+	gtail->schedlink = nil;
+	if(runtime_sched.runqtail)
+		runtime_sched.runqtail->schedlink = ghead;
+	else
+		runtime_sched.runqhead = ghead;
+	runtime_sched.runqtail = gtail;
+	runtime_sched.runqsize += n;
+}
+
+// Try get a batch of G's from the global runnable queue.
+// Sched must be locked.
+static G*
+globrunqget(P *p, int32 max)
+{
+	G *gp, *gp1;
+	int32 n;
+
+	if(runtime_sched.runqsize == 0)
+		return nil;
+	n = runtime_sched.runqsize/runtime_gomaxprocs+1;
+	if(n > runtime_sched.runqsize)
+		n = runtime_sched.runqsize;
+	if(max > 0 && n > max)
+		n = max;
+	if((uint32)n > nelem(p->runq)/2)
+		n = nelem(p->runq)/2;
+	runtime_sched.runqsize -= n;
+	if(runtime_sched.runqsize == 0)
+		runtime_sched.runqtail = nil;
+	gp = runtime_sched.runqhead;
+	runtime_sched.runqhead = gp->schedlink;
+	n--;
+	while(n--) {
+		gp1 = runtime_sched.runqhead;
+		runtime_sched.runqhead = gp1->schedlink;
+		runqput(p, gp1);
+	}
+	return gp;
+}
+
+// Put p to on pidle list.
+// Sched must be locked.
+static void
+pidleput(P *p)
+{
+	p->link = runtime_sched.pidle;
+	runtime_sched.pidle = p;
+	runtime_xadd(&runtime_sched.npidle, 1);  // TODO: fast atomic
+}
+
+// Try get a p from pidle list.
+// Sched must be locked.
+static P*
+pidleget(void)
+{
+	P *p;
+
+	p = runtime_sched.pidle;
+	if(p) {
+		runtime_sched.pidle = p->link;
+		runtime_xadd(&runtime_sched.npidle, -1);  // TODO: fast atomic
+	}
+	return p;
+}
+
+// Try to put g on local runnable queue.
+// If it's full, put onto global queue.
+// Executed only by the owner P.
+static void
+runqput(P *p, G *gp)
+{
+	uint32 h, t;
+
+retry:
+	h = runtime_atomicload(&p->runqhead);  // load-acquire, synchronize with consumers
+	t = p->runqtail;
+	if(t - h < nelem(p->runq)) {
+		p->runq[t%nelem(p->runq)] = gp;
+		runtime_atomicstore(&p->runqtail, t+1);  // store-release, makes the item available for consumption
+		return;
+	}
+	if(runqputslow(p, gp, h, t))
+		return;
+	// the queue is not full, now the put above must suceed
+	goto retry;
+}
+
+// Put g and a batch of work from local runnable queue on global queue.
+// Executed only by the owner P.
+static bool
+runqputslow(P *p, G *gp, uint32 h, uint32 t)
+{
+	G *batch[nelem(p->runq)/2+1];
+	uint32 n, i;
+
+	// First, grab a batch from local queue.
+	n = t-h;
+	n = n/2;
+	if(n != nelem(p->runq)/2)
+		runtime_throw("runqputslow: queue is not full");
+	for(i=0; i<n; i++)
+		batch[i] = p->runq[(h+i)%nelem(p->runq)];
+	if(!runtime_cas(&p->runqhead, h, h+n))  // cas-release, commits consume
+		return false;
+	batch[n] = gp;
+	// Link the goroutines.
+	for(i=0; i<n; i++)
+		batch[i]->schedlink = batch[i+1];
+	// Now put the batch on global queue.
+	runtime_lock(&runtime_sched.lock);
+	globrunqputbatch(batch[0], batch[n], n+1);
+	runtime_unlock(&runtime_sched.lock);
+	return true;
+}
+
+// Get g from local runnable queue.
+// Executed only by the owner P.
+static G*
+runqget(P *p)
+{
+	G *gp;
+	uint32 t, h;
+
+	for(;;) {
+		h = runtime_atomicload(&p->runqhead);  // load-acquire, synchronize with other consumers
+		t = p->runqtail;
+		if(t == h)
+			return nil;
+		gp = p->runq[h%nelem(p->runq)];
+		if(runtime_cas(&p->runqhead, h, h+1))  // cas-release, commits consume
+			return gp;
+	}
+}
+
+// Grabs a batch of goroutines from local runnable queue.
+// batch array must be of size nelem(p->runq)/2. Returns number of grabbed goroutines.
+// Can be executed by any P.
+static uint32
+runqgrab(P *p, G **batch)
+{
+	uint32 t, h, n, i;
+
+	for(;;) {
+		h = runtime_atomicload(&p->runqhead);  // load-acquire, synchronize with other consumers
+		t = runtime_atomicload(&p->runqtail);  // load-acquire, synchronize with the producer
+		n = t-h;
+		n = n - n/2;
+		if(n == 0)
+			break;
+		if(n > nelem(p->runq)/2)  // read inconsistent h and t
+			continue;
+		for(i=0; i<n; i++)
+			batch[i] = p->runq[(h+i)%nelem(p->runq)];
+		if(runtime_cas(&p->runqhead, h, h+n))  // cas-release, commits consume
+			break;
+	}
+	return n;
+}
+
+// Steal half of elements from local runnable queue of p2
+// and put onto local runnable queue of p.
+// Returns one of the stolen elements (or nil if failed).
+static G*
+runqsteal(P *p, P *p2)
+{
+	G *gp;
+	G *batch[nelem(p->runq)/2];
+	uint32 t, h, n, i;
+
+	n = runqgrab(p2, batch);
+	if(n == 0)
+		return nil;
+	n--;
+	gp = batch[n];
+	if(n == 0)
+		return gp;
+	h = runtime_atomicload(&p->runqhead);  // load-acquire, synchronize with consumers
+	t = p->runqtail;
+	if(t - h + n >= nelem(p->runq))
+		runtime_throw("runqsteal: runq overflow");
+	for(i=0; i<n; i++, t++)
+		p->runq[t%nelem(p->runq)] = batch[i];
+	runtime_atomicstore(&p->runqtail, t);  // store-release, makes the item available for consumption
+	return gp;
+}
+
+void runtime_testSchedLocalQueue(void)
+  __asm__("runtime.testSchedLocalQueue");
+
+void
+runtime_testSchedLocalQueue(void)
+{
+	P p;
+	G gs[nelem(p.runq)];
+	int32 i, j;
+
+	runtime_memclr((byte*)&p, sizeof(p));
+
+	for(i = 0; i < (int32)nelem(gs); i++) {
+		if(runqget(&p) != nil)
+			runtime_throw("runq is not empty initially");
+		for(j = 0; j < i; j++)
+			runqput(&p, &gs[i]);
+		for(j = 0; j < i; j++) {
+			if(runqget(&p) != &gs[i]) {
+				runtime_printf("bad element at iter %d/%d\n", i, j);
+				runtime_throw("bad element");
+			}
+		}
+		if(runqget(&p) != nil)
+			runtime_throw("runq is not empty afterwards");
+	}
+}
+
+void runtime_testSchedLocalQueueSteal(void)
+  __asm__("runtime.testSchedLocalQueueSteal");
+
+void
+runtime_testSchedLocalQueueSteal(void)
+{
+	P p1, p2;
+	G gs[nelem(p1.runq)], *gp;
+	int32 i, j, s;
+
+	runtime_memclr((byte*)&p1, sizeof(p1));
+	runtime_memclr((byte*)&p2, sizeof(p2));
+
+	for(i = 0; i < (int32)nelem(gs); i++) {
+		for(j = 0; j < i; j++) {
+			gs[j].sig = 0;
+			runqput(&p1, &gs[j]);
+		}
+		gp = runqsteal(&p2, &p1);
+		s = 0;
+		if(gp) {
+			s++;
+			gp->sig++;
+		}
+		while((gp = runqget(&p2)) != nil) {
+			s++;
+			gp->sig++;
+		}
+		while((gp = runqget(&p1)) != nil)
+			gp->sig++;
+		for(j = 0; j < i; j++) {
+			if(gs[j].sig != 1) {
+				runtime_printf("bad element %d(%d) at iter %d\n", j, gs[j].sig, i);
+				runtime_throw("bad element");
+			}
+		}
+		if(s != i/2 && s != i/2+1) {
+			runtime_printf("bad steal %d, want %d or %d, iter %d\n",
+				s, i/2, i/2+1, i);
+			runtime_throw("bad steal");
+		}
+	}
+}
+
+int32
+runtime_setmaxthreads(int32 in)
+{
+	int32 out;
+
+	runtime_lock(&runtime_sched.lock);
+	out = runtime_sched.maxmcount;
+	runtime_sched.maxmcount = in;
+	checkmcount();
+	runtime_unlock(&runtime_sched.lock);
+	return out;
+}
+
+void
+runtime_proc_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj))
+{
+	enqueue1(wbufp, (Obj){(byte*)&runtime_sched, sizeof runtime_sched, 0});
+}
+
+// When a function calls a closure, it passes the closure value to
+// __go_set_closure immediately before the function call.  When a
+// function uses a closure, it calls __go_get_closure immediately on
+// function entry.  This is a hack, but it will work on any system.
+// It would be better to use the static chain register when there is
+// one.  It is also worth considering expanding these functions
+// directly in the compiler.
+
+void
+__go_set_closure(void* v)
+{
+	g->closure = v;
+}
+
+void *
+__go_get_closure(void)
+{
+	return g->closure;
+}
+
+// Return whether we are waiting for a GC.  This gc toolchain uses
+// preemption instead.
+bool
+runtime_gcwaiting(void)
+{
+	return runtime_sched.gcwaiting;
+}
diff --git a/third_party/gofrontend/libgo/runtime/race.h b/third_party/gofrontend/libgo/runtime/race.h
new file mode 100644
index 0000000..0f4718a
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/race.h
@@ -0,0 +1,34 @@
+// 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.
+
+// Definitions related to data race detection.
+
+#ifdef RACE
+enum { raceenabled = 1 };
+#else
+enum { raceenabled = 0 };
+#endif
+
+// Initialize race detection subsystem.
+uintptr	runtime_raceinit(void);
+// Finalize race detection subsystem, does not return.
+void	runtime_racefini(void);
+
+void	runtime_racemapshadow(void *addr, uintptr size);
+void	runtime_racemalloc(void *p, uintptr sz);
+uintptr	runtime_racegostart(void *pc);
+void	runtime_racegoend(void);
+void	runtime_racewritepc(void *addr, void *callpc, void *pc);
+void	runtime_racereadpc(void *addr, void *callpc, void *pc);
+void	runtime_racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc);
+void	runtime_racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc);
+void	runtime_racereadobjectpc(void *addr, const Type *t, void *callpc, void *pc);
+void	runtime_racewriteobjectpc(void *addr, const Type *t, void *callpc, void *pc);
+void	runtime_racefingo(void);
+void	runtime_raceacquire(void *addr);
+void	runtime_raceacquireg(G *gp, void *addr);
+void	runtime_racerelease(void *addr);
+void	runtime_racereleaseg(G *gp, void *addr);
+void	runtime_racereleasemerge(void *addr);
+void	runtime_racereleasemergeg(G *gp, void *addr);
diff --git a/third_party/gofrontend/libgo/runtime/rdebug.goc b/third_party/gofrontend/libgo/runtime/rdebug.goc
new file mode 100644
index 0000000..63eb4dd
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/rdebug.goc
@@ -0,0 +1,26 @@
+// Copyright 2013 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 runtime_debug
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+func setMaxStack(in int) (out int) {
+	out = runtime_maxstacksize;
+	runtime_maxstacksize = in;
+}
+
+func setGCPercent(in int) (out int) {
+	out = runtime_setgcpercent(in);
+}
+
+func setMaxThreads(in int) (out int) {
+	out = runtime_setmaxthreads(in);
+}
+
+func SetPanicOnFault(enabled bool) (old bool) {
+	old = runtime_g()->paniconfault;
+	runtime_g()->paniconfault = enabled;
+}
diff --git a/third_party/gofrontend/libgo/runtime/reflect.goc b/third_party/gofrontend/libgo/runtime/reflect.goc
new file mode 100644
index 0000000..4e493ee
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/reflect.goc
@@ -0,0 +1,25 @@
+// Copyright 2010 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 reflect
+#include "runtime.h"
+#include "go-type.h"
+#include "interface.h"
+#include "go-panic.h"
+
+func ifaceE2I(inter *Type, e Eface, ret *Iface) {
+	const Type *t;
+	Eface err;
+
+	t = e.__type_descriptor;
+	if(t == nil) {
+		// explicit conversions require non-nil interface value.
+		runtime_newTypeAssertionError(
+			nil, nil, inter->__reflection,
+			nil, &err);
+		runtime_panic(err);
+	}
+	ret->__object = e.__object;
+	ret->__methods = __go_convert_interface(inter, t);
+}
diff --git a/third_party/gofrontend/libgo/runtime/rtems-task-variable-add.c b/third_party/gofrontend/libgo/runtime/rtems-task-variable-add.c
new file mode 100644
index 0000000..89dbb00
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/rtems-task-variable-add.c
@@ -0,0 +1,24 @@
+/* rtems-task-variable-add.c -- adding a task specific variable in RTEMS OS.
+
+   Copyright 2010 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 <rtems/error.h>
+#include <rtems/system.h>
+#include <rtems/rtems/tasks.h>
+
+#include "go-assert.h"
+
+/* RTEMS does not support GNU TLS extension __thread.  */
+void
+__wrap_rtems_task_variable_add (void **var)
+{
+  rtems_status_code sc = rtems_task_variable_add (RTEMS_SELF, var, NULL);
+  if (sc != RTEMS_SUCCESSFUL)
+    {
+      rtems_error (sc, "rtems_task_variable_add failed");
+      __go_assert (0);
+    }
+}
+
diff --git a/third_party/gofrontend/libgo/runtime/runtime.c b/third_party/gofrontend/libgo/runtime/runtime.c
new file mode 100644
index 0000000..496e77b
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/runtime.c
@@ -0,0 +1,382 @@
+// 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.
+
+#include <signal.h>
+#include <unistd.h>
+
+#include "config.h"
+
+#include "runtime.h"
+#include "arch.h"
+#include "array.h"
+
+enum {
+	maxround = sizeof(uintptr),
+};
+
+// Keep a cached value to make gotraceback fast,
+// since we call it on every call to gentraceback.
+// The cached value is a uint32 in which the low bit
+// is the "crash" setting and the top 31 bits are the
+// gotraceback value.
+static uint32 traceback_cache = ~(uint32)0;
+
+// The GOTRACEBACK environment variable controls the
+// behavior of a Go program that is crashing and exiting.
+//	GOTRACEBACK=0   suppress all tracebacks
+//	GOTRACEBACK=1   default behavior - show tracebacks but exclude runtime frames
+//	GOTRACEBACK=2   show tracebacks including runtime frames
+//	GOTRACEBACK=crash   show tracebacks including runtime frames, then crash (core dump etc)
+int32
+runtime_gotraceback(bool *crash)
+{
+	const byte *p;
+	uint32 x;
+
+	if(crash != nil)
+		*crash = false;
+	if(runtime_m()->traceback != 0)
+		return runtime_m()->traceback;
+	x = runtime_atomicload(&traceback_cache);
+	if(x == ~(uint32)0) {
+		p = runtime_getenv("GOTRACEBACK");
+		if(p == nil)
+			p = (const byte*)"";
+		if(p[0] == '\0')
+			x = 1<<1;
+		else if(runtime_strcmp((const char *)p, "crash") == 0)
+			x = (2<<1) | 1;
+		else
+			x = runtime_atoi(p)<<1;	
+		runtime_atomicstore(&traceback_cache, x);
+	}
+	if(crash != nil)
+		*crash = x&1;
+	return x>>1;
+}
+
+static int32	argc;
+static byte**	argv;
+
+extern Slice os_Args __asm__ (GOSYM_PREFIX "os.Args");
+extern Slice syscall_Envs __asm__ (GOSYM_PREFIX "syscall.Envs");
+
+void (*runtime_sysargs)(int32, uint8**);
+
+void
+runtime_args(int32 c, byte **v)
+{
+	argc = c;
+	argv = v;
+	if(runtime_sysargs != nil)
+		runtime_sysargs(c, v);
+}
+
+byte*
+runtime_progname()
+{
+  return argc == 0 ? nil : argv[0];
+}
+
+void
+runtime_goargs(void)
+{
+	String *s;
+	int32 i;
+
+	// for windows implementation see "os" package
+	if(Windows)
+		return;
+
+	s = runtime_malloc(argc*sizeof s[0]);
+	for(i=0; i<argc; i++)
+		s[i] = runtime_gostringnocopy((const byte*)argv[i]);
+	os_Args.__values = (void*)s;
+	os_Args.__count = argc;
+	os_Args.__capacity = argc;
+}
+
+void
+runtime_goenvs_unix(void)
+{
+	String *s;
+	int32 i, n;
+
+	for(n=0; argv[argc+1+n] != 0; n++)
+		;
+
+	s = runtime_malloc(n*sizeof s[0]);
+	for(i=0; i<n; i++)
+		s[i] = runtime_gostringnocopy(argv[argc+1+i]);
+	syscall_Envs.__values = (void*)s;
+	syscall_Envs.__count = n;
+	syscall_Envs.__capacity = n;
+}
+
+int32
+runtime_atoi(const byte *p)
+{
+	int32 n;
+
+	n = 0;
+	while('0' <= *p && *p <= '9')
+		n = n*10 + *p++ - '0';
+	return n;
+}
+
+static struct root_list runtime_roots =
+{ nil,
+  { { &syscall_Envs, sizeof syscall_Envs },
+    { &os_Args, sizeof os_Args },
+    { nil, 0 } },
+};
+
+static void
+TestAtomic64(void)
+{
+	uint64 z64, x64;
+
+	z64 = 42;
+	x64 = 0;
+	PREFETCH(&z64);
+	if(runtime_cas64(&z64, x64, 1))
+		runtime_throw("cas64 failed");
+	if(x64 != 0)
+		runtime_throw("cas64 failed");
+	x64 = 42;
+	if(!runtime_cas64(&z64, x64, 1))
+		runtime_throw("cas64 failed");
+	if(x64 != 42 || z64 != 1)
+		runtime_throw("cas64 failed");
+	if(runtime_atomicload64(&z64) != 1)
+		runtime_throw("load64 failed");
+	runtime_atomicstore64(&z64, (1ull<<40)+1);
+	if(runtime_atomicload64(&z64) != (1ull<<40)+1)
+		runtime_throw("store64 failed");
+	if(runtime_xadd64(&z64, (1ull<<40)+1) != (2ull<<40)+2)
+		runtime_throw("xadd64 failed");
+	if(runtime_atomicload64(&z64) != (2ull<<40)+2)
+		runtime_throw("xadd64 failed");
+	if(runtime_xchg64(&z64, (3ull<<40)+3) != (2ull<<40)+2)
+		runtime_throw("xchg64 failed");
+	if(runtime_atomicload64(&z64) != (3ull<<40)+3)
+		runtime_throw("xchg64 failed");
+}
+
+void
+runtime_check(void)
+{
+	__go_register_gc_roots(&runtime_roots);
+
+	TestAtomic64();
+}
+
+uint32
+runtime_fastrand1(void)
+{
+	M *m;
+	uint32 x;
+
+	m = runtime_m();
+	x = m->fastrand;
+	x += x;
+	if(x & 0x80000000L)
+		x ^= 0x88888eefUL;
+	m->fastrand = x;
+	return x;
+}
+
+int64
+runtime_cputicks(void)
+{
+#if defined(__386__) || defined(__x86_64__)
+  uint32 low, high;
+  asm("rdtsc" : "=a" (low), "=d" (high));
+  return (int64)(((uint64)high << 32) | (uint64)low);
+#elif defined (__s390__) || defined (__s390x__)
+  uint64 clock = 0;
+  /* stckf may not write the return variable in case of a clock error, so make
+     it read-write to prevent that the initialisation is optimised out.
+     Note: Targets below z9-109 will crash when executing store clock fast, i.e.
+     we don't support Go for machines older than that.  */
+  asm volatile(".insn s,0xb27c0000,%0" /* stckf */ : "+Q" (clock) : : "cc" );
+  return (int64)clock;
+#else
+  // FIXME: implement for other processors.
+  return 0;
+#endif
+}
+
+bool
+runtime_showframe(String s, bool current)
+{
+	static int32 traceback = -1;
+
+	if(current && runtime_m()->throwing > 0)
+		return 1;
+	if(traceback < 0)
+		traceback = runtime_gotraceback(nil);
+	return traceback > 1 || (__builtin_memchr(s.str, '.', s.len) != nil && __builtin_memcmp(s.str, "runtime.", 7) != 0);
+}
+
+static Lock ticksLock;
+static int64 ticks;
+
+int64
+runtime_tickspersecond(void)
+{
+	int64 res, t0, t1, c0, c1;
+
+	res = (int64)runtime_atomicload64((uint64*)&ticks);
+	if(res != 0)
+		return ticks;
+	runtime_lock(&ticksLock);
+	res = ticks;
+	if(res == 0) {
+		t0 = runtime_nanotime();
+		c0 = runtime_cputicks();
+		runtime_usleep(100*1000);
+		t1 = runtime_nanotime();
+		c1 = runtime_cputicks();
+		if(t1 == t0)
+			t1++;
+		res = (c1-c0)*1000*1000*1000/(t1-t0);
+		if(res == 0)
+			res++;
+		runtime_atomicstore64((uint64*)&ticks, res);
+	}
+	runtime_unlock(&ticksLock);
+	return res;
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+void
+runtime_mpreinit(M *mp)
+{
+	mp->gsignal = runtime_malg(32*1024, &mp->gsignalstack, &mp->gsignalstacksize);	// OS X wants >=8K, Linux >=2K
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+void
+runtime_minit(void)
+{
+	M* m;
+	sigset_t sigs;
+
+	// Initialize signal handling.
+	m = runtime_m();
+	runtime_signalstack(m->gsignalstack, m->gsignalstacksize);
+	if (sigemptyset(&sigs) != 0)
+		runtime_throw("sigemptyset");
+	pthread_sigmask(SIG_SETMASK, &sigs, nil);
+}
+
+// Called from dropm to undo the effect of an minit.
+void
+runtime_unminit(void)
+{
+	runtime_signalstack(nil, 0);
+}
+
+
+void
+runtime_signalstack(byte *p, int32 n)
+{
+	stack_t st;
+
+	st.ss_sp = p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
+	if(sigaltstack(&st, nil) < 0)
+		*(int *)0xf1 = 0xf1;
+}
+
+DebugVars	runtime_debug;
+
+static struct {
+	const char* name;
+	int32*	value;
+} dbgvar[] = {
+	{"allocfreetrace", &runtime_debug.allocfreetrace},
+	{"efence", &runtime_debug.efence},
+	{"gctrace", &runtime_debug.gctrace},
+	{"gcdead", &runtime_debug.gcdead},
+	{"scheddetail", &runtime_debug.scheddetail},
+	{"schedtrace", &runtime_debug.schedtrace},
+};
+
+void
+runtime_parsedebugvars(void)
+{
+	const byte *p;
+	intgo i, n;
+	bool tmp;
+	
+	// gotraceback caches the GOTRACEBACK setting in traceback_cache.
+	// gotraceback can be called before the environment is available.
+	// traceback_cache must be reset after the environment is made
+	// available, in order for the environment variable to take effect.
+	// The code is fixed differently in Go 1.4.
+	// This is a limited fix for Go 1.3.3.
+	traceback_cache = ~(uint32)0;
+	runtime_gotraceback(&tmp);
+
+	p = runtime_getenv("GODEBUG");
+	if(p == nil)
+		return;
+	for(;;) {
+		for(i=0; i<(intgo)nelem(dbgvar); i++) {
+			n = runtime_findnull((const byte*)dbgvar[i].name);
+			if(runtime_mcmp(p, dbgvar[i].name, n) == 0 && p[n] == '=')
+				*dbgvar[i].value = runtime_atoi(p+n+1);
+		}
+		p = (const byte *)runtime_strstr((const char *)p, ",");
+		if(p == nil)
+			break;
+		p++;
+	}
+}
+
+// Poor mans 64-bit division.
+// This is a very special function, do not use it if you are not sure what you are doing.
+// int64 division is lowered into _divv() call on 386, which does not fit into nosplit functions.
+// Handles overflow in a time-specific manner.
+int32
+runtime_timediv(int64 v, int32 div, int32 *rem)
+{
+	int32 res, bit;
+
+	if(v >= (int64)div*0x7fffffffLL) {
+		if(rem != nil)
+			*rem = 0;
+		return 0x7fffffff;
+	}
+	res = 0;
+	for(bit = 30; bit >= 0; bit--) {
+		if(v >= ((int64)div<<bit)) {
+			v = v - ((int64)div<<bit);
+			res += 1<<bit;
+		}
+	}
+	if(rem != nil)
+		*rem = v;
+	return res;
+}
+
+// Setting the max stack size doesn't really do anything for gccgo.
+
+uintptr runtime_maxstacksize = 1<<20; // enough until runtime.main sets it for real
+
+void memclrBytes(Slice)
+     __asm__ (GOSYM_PREFIX "runtime.memclrBytes");
+
+void
+memclrBytes(Slice s)
+{
+	runtime_memclr(s.__values, s.__count);
+}
diff --git a/third_party/gofrontend/libgo/runtime/runtime.h b/third_party/gofrontend/libgo/runtime/runtime.h
new file mode 100644
index 0000000..cd5a9c6
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/runtime.h
@@ -0,0 +1,852 @@
+// 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.
+
+#include "config.h"
+
+#include "go-assert.h"
+#include <complex.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <ucontext.h>
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include "interface.h"
+#include "go-alloc.h"
+
+#define _STRINGIFY2_(x) #x
+#define _STRINGIFY_(x) _STRINGIFY2_(x)
+#define GOSYM_PREFIX _STRINGIFY_(__USER_LABEL_PREFIX__)
+
+/* This file supports C files copied from the 6g runtime library.
+   This is a version of the 6g runtime.h rewritten for gccgo's version
+   of the code.  */
+
+typedef signed int   int8    __attribute__ ((mode (QI)));
+typedef unsigned int uint8   __attribute__ ((mode (QI)));
+typedef signed int   int16   __attribute__ ((mode (HI)));
+typedef unsigned int uint16  __attribute__ ((mode (HI)));
+typedef signed int   int32   __attribute__ ((mode (SI)));
+typedef unsigned int uint32  __attribute__ ((mode (SI)));
+typedef signed int   int64   __attribute__ ((mode (DI)));
+typedef unsigned int uint64  __attribute__ ((mode (DI)));
+typedef float        float32 __attribute__ ((mode (SF)));
+typedef double       float64 __attribute__ ((mode (DF)));
+typedef signed int   intptr __attribute__ ((mode (pointer)));
+typedef unsigned int uintptr __attribute__ ((mode (pointer)));
+
+typedef intptr		intgo; // Go's int
+typedef uintptr		uintgo; // Go's uint
+
+typedef uintptr		uintreg;
+
+/* Defined types.  */
+
+typedef	uint8			bool;
+typedef	uint8			byte;
+typedef	struct	Func		Func;
+typedef	struct	G		G;
+typedef	struct	Lock		Lock;
+typedef	struct	M		M;
+typedef	struct	P		P;
+typedef	struct	Note		Note;
+typedef	struct	String		String;
+typedef	struct	FuncVal		FuncVal;
+typedef	struct	SigTab		SigTab;
+typedef	struct	MCache		MCache;
+typedef struct	FixAlloc	FixAlloc;
+typedef	struct	Hchan		Hchan;
+typedef	struct	Timers		Timers;
+typedef	struct	Timer		Timer;
+typedef	struct	GCStats		GCStats;
+typedef	struct	LFNode		LFNode;
+typedef	struct	ParFor		ParFor;
+typedef	struct	ParForThread	ParForThread;
+typedef	struct	CgoMal		CgoMal;
+typedef	struct	PollDesc	PollDesc;
+typedef	struct	DebugVars	DebugVars;
+
+typedef	struct	__go_open_array		Slice;
+typedef struct	__go_interface		Iface;
+typedef	struct	__go_empty_interface	Eface;
+typedef	struct	__go_type_descriptor	Type;
+typedef	struct	__go_defer_stack	Defer;
+typedef	struct	__go_panic_stack	Panic;
+
+typedef struct	__go_ptr_type		PtrType;
+typedef struct	__go_func_type		FuncType;
+typedef struct	__go_interface_type	InterfaceType;
+typedef struct	__go_map_type		MapType;
+typedef struct	__go_channel_type	ChanType;
+
+typedef struct  Traceback	Traceback;
+
+typedef struct	Location	Location;
+
+/*
+ * Per-CPU declaration.
+ */
+extern M*	runtime_m(void);
+extern G*	runtime_g(void);
+
+extern M	runtime_m0;
+extern G	runtime_g0;
+
+/*
+ * defined constants
+ */
+enum
+{
+	// G status
+	//
+	// If you add to this list, add to the list
+	// of "okay during garbage collection" status
+	// in mgc0.c too.
+	Gidle,
+	Grunnable,
+	Grunning,
+	Gsyscall,
+	Gwaiting,
+	Gmoribund_unused,  // currently unused, but hardcoded in gdb scripts
+	Gdead,
+};
+enum
+{
+	// P status
+	Pidle,
+	Prunning,
+	Psyscall,
+	Pgcstop,
+	Pdead,
+};
+enum
+{
+	true	= 1,
+	false	= 0,
+};
+enum
+{
+	PtrSize = sizeof(void*),
+};
+enum
+{
+	// Per-M stack segment cache size.
+	StackCacheSize = 32,
+	// Global <-> per-M stack segment cache transfer batch size.
+	StackCacheBatch = 16,
+};
+/*
+ * structures
+ */
+struct	Lock
+{
+	// Futex-based impl treats it as uint32 key,
+	// while sema-based impl as M* waitm.
+	// Used to be a union, but unions break precise GC.
+	uintptr	key;
+};
+struct	Note
+{
+	// Futex-based impl treats it as uint32 key,
+	// while sema-based impl as M* waitm.
+	// Used to be a union, but unions break precise GC.
+	uintptr	key;
+};
+struct String
+{
+	const byte*	str;
+	intgo		len;
+};
+struct FuncVal
+{
+	void	(*fn)(void);
+	// variable-size, fn-specific data here
+};
+struct	GCStats
+{
+	// the struct must consist of only uint64's,
+	// because it is casted to uint64[].
+	uint64	nhandoff;
+	uint64	nhandoffcnt;
+	uint64	nprocyield;
+	uint64	nosyield;
+	uint64	nsleep;
+};
+
+// A location in the program, used for backtraces.
+struct	Location
+{
+	uintptr	pc;
+	String	filename;
+	String	function;
+	intgo	lineno;
+};
+
+struct	G
+{
+	void*	closure;	// Closure value.
+	Defer*	defer;
+	Panic*	panic;
+	void*	exception;	// current exception being thrown
+	bool	is_foreign;	// whether current exception from other language
+	void	*gcstack;	// if status==Gsyscall, gcstack = stackbase to use during gc
+	uintptr	gcstack_size;
+	void*	gcnext_segment;
+	void*	gcnext_sp;
+	void*	gcinitial_sp;
+	ucontext_t gcregs;
+	byte*	entry;		// initial function
+	void*	param;		// passed parameter on wakeup
+	bool	fromgogo;	// reached from gogo
+	int16	status;
+	uint32	selgen;		// valid sudog pointer
+	int64	goid;
+	int64	waitsince;	// approx time when the G become blocked
+	const char*	waitreason;	// if status==Gwaiting
+	G*	schedlink;
+	bool	ispanic;
+	bool	issystem;	// do not output in stack dump
+	bool	isbackground;	// ignore in deadlock detector
+	bool	paniconfault;	// panic (instead of crash) on unexpected fault address
+	M*	m;		// for debuggers, but offset not hard-coded
+	M*	lockedm;
+	int32	sig;
+	int32	writenbuf;
+	byte*	writebuf;
+	uintptr	sigcode0;
+	uintptr	sigcode1;
+	// uintptr	sigpc;
+	uintptr	gopc;	// pc of go statement that created this goroutine
+
+	int32	ncgo;
+	CgoMal*	cgomal;
+
+	Traceback* traceback;
+
+	ucontext_t	context;
+	void*		stack_context[10];
+};
+
+struct	M
+{
+	G*	g0;		// goroutine with scheduling stack
+	G*	gsignal;	// signal-handling G
+	byte*	gsignalstack;
+	size_t	gsignalstacksize;
+	void	(*mstartfn)(void);
+	G*	curg;		// current running goroutine
+	G*	caughtsig;	// goroutine running during fatal signal
+	P*	p;		// attached P for executing Go code (nil if not executing Go code)
+	P*	nextp;
+	int32	id;
+	int32	mallocing;
+	int32	throwing;
+	int32	gcing;
+	int32	locks;
+	int32	softfloat;
+	int32	dying;
+	int32	profilehz;
+	int32	helpgc;
+	bool	spinning;	// M is out of work and is actively looking for work
+	bool	blocked;	// M is blocked on a Note
+	uint32	fastrand;
+	uint64	ncgocall;	// number of cgo calls in total
+	int32	ncgo;		// number of cgo calls currently in progress
+	CgoMal*	cgomal;
+	Note	park;
+	M*	alllink;	// on allm
+	M*	schedlink;
+	MCache	*mcache;
+	G*	lockedg;
+	Location createstack[32];	// Stack that created this thread.
+	uint32	locked;	// tracking for LockOSThread
+	M*	nextwaitm;	// next M waiting for lock
+	uintptr	waitsema;	// semaphore for parking on locks
+	uint32	waitsemacount;
+	uint32	waitsemalock;
+	GCStats	gcstats;
+	bool	needextram;
+	bool	dropextram;	// for gccgo: drop after call is done.
+	uint8	traceback;
+	bool	(*waitunlockf)(G*, void*);
+	void*	waitlock;
+	uintptr	end[];
+};
+
+struct P
+{
+	Lock	lock;
+
+	int32	id;
+	uint32	status;		// one of Pidle/Prunning/...
+	P*	link;
+	uint32	schedtick;	// incremented on every scheduler call
+	uint32	syscalltick;	// incremented on every system call
+	M*	m;		// back-link to associated M (nil if idle)
+	MCache*	mcache;
+	Defer*	deferpool;	// pool of available Defer structs (see panic.c)
+
+	// Cache of goroutine ids, amortizes accesses to runtime_sched.goidgen.
+	uint64	goidcache;
+	uint64	goidcacheend;
+
+	// Queue of runnable goroutines.
+	uint32	runqhead;
+	uint32	runqtail;
+	G*	runq[256];
+
+	// Available G's (status == Gdead)
+	G*	gfree;
+	int32	gfreecnt;
+
+	byte	pad[64];
+};
+
+// The m->locked word holds two pieces of state counting active calls to LockOSThread/lockOSThread.
+// The low bit (LockExternal) is a boolean reporting whether any LockOSThread call is active.
+// External locks are not recursive; a second lock is silently ignored.
+// The upper bits of m->lockedcount record the nesting depth of calls to lockOSThread
+// (counting up by LockInternal), popped by unlockOSThread (counting down by LockInternal).
+// Internal locks can be recursive. For instance, a lock for cgo can occur while the main
+// goroutine is holding the lock during the initialization phase.
+enum
+{
+	LockExternal = 1,
+	LockInternal = 2,
+};
+
+struct	SigTab
+{
+	int32	sig;
+	int32	flags;
+};
+enum
+{
+	SigNotify = 1<<0,	// let signal.Notify have signal, even if from kernel
+	SigKill = 1<<1,		// if signal.Notify doesn't take it, exit quietly
+	SigThrow = 1<<2,	// if signal.Notify doesn't take it, exit loudly
+	SigPanic = 1<<3,	// if the signal is from the kernel, panic
+	SigDefault = 1<<4,	// if the signal isn't explicitly requested, don't monitor it
+	SigHandling = 1<<5,	// our signal handler is registered
+	SigIgnored = 1<<6,	// the signal was ignored before we registered for it
+	SigGoExit = 1<<7,	// cause all runtime procs to exit (only used on Plan 9).
+};
+
+// Layout of in-memory per-function information prepared by linker
+// See http://golang.org/s/go12symtab.
+// Keep in sync with linker and with ../../libmach/sym.c
+// and with package debug/gosym.
+struct	Func
+{
+	String	name;
+	uintptr	entry;	// entry pc
+};
+
+#ifdef GOOS_nacl
+enum {
+   NaCl = 1,
+};
+#else
+enum {
+   NaCl = 0,
+};
+#endif
+
+#ifdef GOOS_windows
+enum {
+   Windows = 1
+};
+#else
+enum {
+   Windows = 0
+};
+#endif
+#ifdef GOOS_solaris
+enum {
+   Solaris = 1
+};
+#else
+enum {
+   Solaris = 0
+};
+#endif
+
+struct	Timers
+{
+	Lock	lock;
+	G	*timerproc;
+	bool		sleeping;
+	bool		rescheduling;
+	Note	waitnote;
+	Timer	**t;
+	int32	len;
+	int32	cap;
+};
+
+// Package time knows the layout of this structure.
+// If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
+// For GOOS=nacl, package syscall knows the layout of this structure.
+// If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
+struct	Timer
+{
+	int32	i;	// heap index
+
+	// Timer wakes up at when, and then at when+period, ... (period > 0 only)
+	// each time calling f(now, arg) in the timer goroutine, so f must be
+	// a well-behaved function and not block.
+	int64	when;
+	int64	period;
+	FuncVal	*fv;
+	Eface	arg;
+};
+
+// Lock-free stack node.
+struct LFNode
+{
+	LFNode	*next;
+	uintptr	pushcnt;
+};
+
+// Parallel for descriptor.
+struct ParFor
+{
+	void (*body)(ParFor*, uint32);	// executed for each element
+	uint32 done;			// number of idle threads
+	uint32 nthr;			// total number of threads
+	uint32 nthrmax;			// maximum number of threads
+	uint32 thrseq;			// thread id sequencer
+	uint32 cnt;			// iteration space [0, cnt)
+	void *ctx;			// arbitrary user context
+	bool wait;			// if true, wait while all threads finish processing,
+					// otherwise parfor may return while other threads are still working
+	ParForThread *thr;		// array of thread descriptors
+	uint32 pad;			// to align ParForThread.pos for 64-bit atomic operations
+	// stats
+	uint64 nsteal;
+	uint64 nstealcnt;
+	uint64 nprocyield;
+	uint64 nosyield;
+	uint64 nsleep;
+};
+
+// Track memory allocated by code not written in Go during a cgo call,
+// so that the garbage collector can see them.
+struct CgoMal
+{
+	CgoMal	*next;
+	void	*alloc;
+};
+
+// Holds variables parsed from GODEBUG env var.
+struct DebugVars
+{
+	int32	allocfreetrace;
+	int32	efence;
+	int32	gctrace;
+	int32	gcdead;
+	int32	scheddetail;
+	int32	schedtrace;
+};
+
+extern bool runtime_precisestack;
+extern bool runtime_copystack;
+
+/*
+ * defined macros
+ *    you need super-gopher-guru privilege
+ *    to add this list.
+ */
+#define	nelem(x)	(sizeof(x)/sizeof((x)[0]))
+#define	nil		((void*)0)
+#define USED(v)		((void) v)
+#define	ROUND(x, n)	(((x)+(n)-1)&~(uintptr)((n)-1)) /* all-caps to mark as macro: it evaluates n twice */
+
+byte*	runtime_startup_random_data;
+uint32	runtime_startup_random_data_len;
+void	runtime_get_random_data(byte**, int32*);
+
+enum {
+	// hashinit wants this many random bytes
+	HashRandomBytes = 32
+};
+void	runtime_hashinit(void);
+
+void	runtime_traceback(void);
+void	runtime_tracebackothers(G*);
+enum
+{
+	// The maximum number of frames we print for a traceback
+	TracebackMaxFrames = 100,
+};
+
+/*
+ * external data
+ */
+extern	uintptr runtime_zerobase;
+extern	G**	runtime_allg;
+extern	uintptr runtime_allglen;
+extern	G*	runtime_lastg;
+extern	M*	runtime_allm;
+extern	P**	runtime_allp;
+extern	int32	runtime_gomaxprocs;
+extern	uint32	runtime_needextram;
+extern	uint32	runtime_panicking;
+extern	int8*	runtime_goos;
+extern	int32	runtime_ncpu;
+extern 	void	(*runtime_sysargs)(int32, uint8**);
+extern	uint32	runtime_Hchansize;
+extern	DebugVars	runtime_debug;
+extern	uintptr	runtime_maxstacksize;
+
+/*
+ * common functions and data
+ */
+#define runtime_strcmp(s1, s2) __builtin_strcmp((s1), (s2))
+#define runtime_strncmp(s1, s2, n) __builtin_strncmp((s1), (s2), (n))
+#define runtime_strstr(s1, s2) __builtin_strstr((s1), (s2))
+intgo	runtime_findnull(const byte*);
+intgo	runtime_findnullw(const uint16*);
+void	runtime_dump(byte*, int32);
+
+void	runtime_gogo(G*);
+struct __go_func_type;
+void	runtime_args(int32, byte**);
+void	runtime_osinit();
+void	runtime_goargs(void);
+void	runtime_goenvs(void);
+void	runtime_goenvs_unix(void);
+void	runtime_throw(const char*) __attribute__ ((noreturn));
+void	runtime_panicstring(const char*) __attribute__ ((noreturn));
+bool	runtime_canpanic(G*);
+void	runtime_prints(const char*);
+void	runtime_printf(const char*, ...);
+int32	runtime_snprintf(byte*, int32, const char*, ...);
+#define runtime_mcmp(a, b, s) __builtin_memcmp((a), (b), (s))
+#define runtime_memmove(a, b, s) __builtin_memmove((a), (b), (s))
+void*	runtime_mal(uintptr);
+String	runtime_gostring(const byte*);
+String	runtime_gostringnocopy(const byte*);
+void	runtime_schedinit(void);
+void	runtime_initsig(void);
+void	runtime_sigenable(uint32 sig);
+void	runtime_sigdisable(uint32 sig);
+int32	runtime_gotraceback(bool *crash);
+void	runtime_goroutineheader(G*);
+void	runtime_printtrace(Location*, int32, bool);
+#define runtime_open(p, f, m) open((p), (f), (m))
+#define runtime_read(d, v, n) read((d), (v), (n))
+#define runtime_write(d, v, n) write((d), (v), (n))
+#define runtime_close(d) close(d)
+void	runtime_ready(G*);
+const byte*	runtime_getenv(const char*);
+int32	runtime_atoi(const byte*);
+void*	runtime_mstart(void*);
+G*	runtime_malg(int32, byte**, size_t*);
+void	runtime_mpreinit(M*);
+void	runtime_minit(void);
+void	runtime_unminit(void);
+void	runtime_needm(void);
+void	runtime_dropm(void);
+void	runtime_signalstack(byte*, int32);
+MCache*	runtime_allocmcache(void);
+void	runtime_freemcache(MCache*);
+void	runtime_mallocinit(void);
+void	runtime_mprofinit(void);
+#define runtime_malloc(s) __go_alloc(s)
+#define runtime_free(p) __go_free(p)
+#define runtime_getcallersp(p) __builtin_frame_address(1)
+int32	runtime_mcount(void);
+int32	runtime_gcount(void);
+void	runtime_mcall(void(*)(G*));
+uint32	runtime_fastrand1(void);
+int32	runtime_timediv(int64, int32, int32*);
+int32	runtime_round2(int32 x); // round x up to a power of 2.
+
+// atomic operations
+#define runtime_cas(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
+#define runtime_cas64(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
+#define runtime_casp(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
+// Don't confuse with XADD x86 instruction,
+// this one is actually 'addx', that is, add-and-fetch.
+#define runtime_xadd(p, v) __sync_add_and_fetch (p, v)
+#define runtime_xadd64(p, v) __sync_add_and_fetch (p, v)
+#define runtime_xchg(p, v) __atomic_exchange_n (p, v, __ATOMIC_SEQ_CST)
+#define runtime_xchg64(p, v) __atomic_exchange_n (p, v, __ATOMIC_SEQ_CST)
+#define runtime_xchgp(p, v) __atomic_exchange_n (p, v, __ATOMIC_SEQ_CST)
+#define runtime_atomicload(p) __atomic_load_n (p, __ATOMIC_SEQ_CST)
+#define runtime_atomicstore(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST)
+#define runtime_atomicstore64(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST)
+#define runtime_atomicload64(p) __atomic_load_n (p, __ATOMIC_SEQ_CST)
+#define runtime_atomicloadp(p) __atomic_load_n (p, __ATOMIC_SEQ_CST)
+#define runtime_atomicstorep(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST)
+
+void runtime_setmg(M*, G*);
+void runtime_newextram(void);
+#define runtime_exit(s) exit(s)
+#define runtime_breakpoint() __builtin_trap()
+void	runtime_gosched(void);
+void	runtime_gosched0(G*);
+void	runtime_schedtrace(bool);
+void	runtime_park(bool(*)(G*, void*), void*, const char*);
+void	runtime_parkunlock(Lock*, const char*);
+void	runtime_tsleep(int64, const char*);
+M*	runtime_newm(void);
+void	runtime_goexit(void);
+void	runtime_entersyscall(void) __asm__ (GOSYM_PREFIX "syscall.Entersyscall");
+void	runtime_entersyscallblock(void);
+void	runtime_exitsyscall(void) __asm__ (GOSYM_PREFIX "syscall.Exitsyscall");
+G*	__go_go(void (*pfn)(void*), void*);
+void	siginit(void);
+bool	__go_sigsend(int32 sig);
+int32	runtime_callers(int32, Location*, int32, bool keep_callers);
+int64	runtime_nanotime(void);	// monotonic time
+int64	runtime_unixnanotime(void); // real time, can skip
+void	runtime_dopanic(int32) __attribute__ ((noreturn));
+void	runtime_startpanic(void);
+void	runtime_freezetheworld(void);
+void	runtime_unwindstack(G*, byte*);
+void	runtime_sigprof();
+void	runtime_resetcpuprofiler(int32);
+void	runtime_setcpuprofilerate(void(*)(uintptr*, int32), int32);
+void	runtime_usleep(uint32);
+int64	runtime_cputicks(void);
+int64	runtime_tickspersecond(void);
+void	runtime_blockevent(int64, int32);
+extern int64 runtime_blockprofilerate;
+void	runtime_addtimer(Timer*);
+bool	runtime_deltimer(Timer*);
+G*	runtime_netpoll(bool);
+void	runtime_netpollinit(void);
+int32	runtime_netpollopen(uintptr, PollDesc*);
+int32   runtime_netpollclose(uintptr);
+void	runtime_netpollready(G**, PollDesc*, int32);
+uintptr	runtime_netpollfd(PollDesc*);
+void	runtime_netpollarm(PollDesc*, int32);
+void**	runtime_netpolluser(PollDesc*);
+bool	runtime_netpollclosing(PollDesc*);
+void	runtime_netpolllock(PollDesc*);
+void	runtime_netpollunlock(PollDesc*);
+void	runtime_crash(void);
+void	runtime_parsedebugvars(void);
+void	_rt0_go(void);
+void*	runtime_funcdata(Func*, int32);
+int32	runtime_setmaxthreads(int32);
+G*	runtime_timejump(void);
+void	runtime_iterate_finq(void (*callback)(FuncVal*, void*, const FuncType*, const PtrType*));
+
+void	runtime_stoptheworld(void);
+void	runtime_starttheworld(void);
+extern uint32 runtime_worldsema;
+
+/*
+ * mutual exclusion locks.  in the uncontended case,
+ * as fast as spin locks (just a few user-level instructions),
+ * but on the contention path they sleep in the kernel.
+ * a zeroed Lock is unlocked (no need to initialize each lock).
+ */
+void	runtime_lock(Lock*);
+void	runtime_unlock(Lock*);
+
+/*
+ * sleep and wakeup on one-time events.
+ * before any calls to notesleep or notewakeup,
+ * must call noteclear to initialize the Note.
+ * then, exactly one thread can call notesleep
+ * and exactly one thread can call notewakeup (once).
+ * once notewakeup has been called, the notesleep
+ * will return.  future notesleep will return immediately.
+ * subsequent noteclear must be called only after
+ * previous notesleep has returned, e.g. it's disallowed
+ * to call noteclear straight after notewakeup.
+ *
+ * notetsleep is like notesleep but wakes up after
+ * a given number of nanoseconds even if the event
+ * has not yet happened.  if a goroutine uses notetsleep to
+ * wake up early, it must wait to call noteclear until it
+ * can be sure that no other goroutine is calling
+ * notewakeup.
+ *
+ * notesleep/notetsleep are generally called on g0,
+ * notetsleepg is similar to notetsleep but is called on user g.
+ */
+void	runtime_noteclear(Note*);
+void	runtime_notesleep(Note*);
+void	runtime_notewakeup(Note*);
+bool	runtime_notetsleep(Note*, int64);  // false - timeout
+bool	runtime_notetsleepg(Note*, int64);  // false - timeout
+
+/*
+ * low-level synchronization for implementing the above
+ */
+uintptr	runtime_semacreate(void);
+int32	runtime_semasleep(int64);
+void	runtime_semawakeup(M*);
+// or
+void	runtime_futexsleep(uint32*, uint32, int64);
+void	runtime_futexwakeup(uint32*, uint32);
+
+/*
+ * Lock-free stack.
+ * Initialize uint64 head to 0, compare with 0 to test for emptiness.
+ * The stack does not keep pointers to nodes,
+ * so they can be garbage collected if there are no other pointers to nodes.
+ */
+void	runtime_lfstackpush(uint64 *head, LFNode *node)
+  __asm__ (GOSYM_PREFIX "runtime.lfstackpush");
+LFNode*	runtime_lfstackpop(uint64 *head);
+
+/*
+ * Parallel for over [0, n).
+ * body() is executed for each iteration.
+ * nthr - total number of worker threads.
+ * ctx - arbitrary user context.
+ * if wait=true, threads return from parfor() when all work is done;
+ * otherwise, threads can return while other threads are still finishing processing.
+ */
+ParFor*	runtime_parforalloc(uint32 nthrmax);
+void	runtime_parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32));
+void	runtime_parfordo(ParFor *desc);
+void	runtime_parforiters(ParFor*, uintptr, uintptr*, uintptr*);
+
+/*
+ * low level C-called
+ */
+#define runtime_mmap mmap
+#define runtime_munmap munmap
+#define runtime_madvise madvise
+#define runtime_memclr(buf, size) __builtin_memset((buf), 0, (size))
+#define runtime_getcallerpc(p) __builtin_return_address(0)
+
+#ifdef __rtems__
+void __wrap_rtems_task_variable_add(void **);
+#endif
+
+/*
+ * Names generated by gccgo.
+ */
+#define runtime_printbool	__go_print_bool
+#define runtime_printfloat	__go_print_double
+#define runtime_printint	__go_print_int64
+#define runtime_printiface	__go_print_interface
+#define runtime_printeface	__go_print_empty_interface
+#define runtime_printstring	__go_print_string
+#define runtime_printpointer	__go_print_pointer
+#define runtime_printuint	__go_print_uint64
+#define runtime_printslice	__go_print_slice
+#define runtime_printcomplex	__go_print_complex
+
+/*
+ * runtime go-called
+ */
+void	runtime_printbool(_Bool);
+void	runtime_printbyte(int8);
+void	runtime_printfloat(double);
+void	runtime_printint(int64);
+void	runtime_printiface(Iface);
+void	runtime_printeface(Eface);
+void	runtime_printstring(String);
+void	runtime_printpc(void*);
+void	runtime_printpointer(void*);
+void	runtime_printuint(uint64);
+void	runtime_printhex(uint64);
+void	runtime_printslice(Slice);
+void	runtime_printcomplex(complex double);
+void reflect_call(const struct __go_func_type *, FuncVal *, _Bool, _Bool,
+		  void **, void **)
+  __asm__ (GOSYM_PREFIX "reflect.call");
+#define runtime_panic __go_panic
+
+/*
+ * runtime c-called (but written in Go)
+ */
+void	runtime_printany(Eface)
+     __asm__ (GOSYM_PREFIX "runtime.Printany");
+void	runtime_newTypeAssertionError(const String*, const String*, const String*, const String*, Eface*)
+     __asm__ (GOSYM_PREFIX "runtime.NewTypeAssertionError");
+void	runtime_newErrorString(String, Eface*)
+     __asm__ (GOSYM_PREFIX "runtime.NewErrorString");
+void	runtime_newErrorCString(const char*, Eface*)
+     __asm__ (GOSYM_PREFIX "runtime.NewErrorCString");
+
+/*
+ * wrapped for go users
+ */
+void	runtime_semacquire(uint32 volatile *, bool);
+void	runtime_semrelease(uint32 volatile *);
+int32	runtime_gomaxprocsfunc(int32 n);
+void	runtime_procyield(uint32);
+void	runtime_osyield(void);
+void	runtime_lockOSThread(void);
+void	runtime_unlockOSThread(void);
+bool	runtime_lockedOSThread(void);
+
+bool	runtime_showframe(String, bool);
+void	runtime_printcreatedby(G*);
+
+uintptr	runtime_memlimit(void);
+
+#define ISNAN(f) __builtin_isnan(f)
+
+enum
+{
+	UseSpanType = 1,
+};
+
+#define runtime_setitimer setitimer
+
+void	runtime_check(void);
+
+// A list of global variables that the garbage collector must scan.
+struct root_list {
+	struct root_list *next;
+	struct root {
+		void *decl;
+		size_t size;
+	} roots[];
+};
+
+void	__go_register_gc_roots(struct root_list*);
+
+// Size of stack space allocated using Go's allocator.
+// This will be 0 when using split stacks, as in that case
+// the stacks are allocated by the splitstack library.
+extern uintptr runtime_stacks_sys;
+
+struct backtrace_state;
+extern struct backtrace_state *__go_get_backtrace_state(void);
+extern _Bool __go_file_line(uintptr, String*, String*, intgo *);
+extern byte* runtime_progname();
+extern void runtime_main(void*);
+extern uint32 runtime_in_callers;
+
+int32 getproccount(void);
+
+#define PREFETCH(p) __builtin_prefetch(p)
+
+void	__go_set_closure(void*);
+void*	__go_get_closure(void);
+
+bool	runtime_gcwaiting(void);
+void	runtime_badsignal(int);
+Defer*	runtime_newdefer(void);
+void	runtime_freedefer(Defer*);
+
+struct time_now_ret
+{
+  int64_t sec;
+  int32_t nsec;
+};
+
+struct time_now_ret now() __asm__ (GOSYM_PREFIX "time.now")
+  __attribute__ ((no_split_stack));
diff --git a/third_party/gofrontend/libgo/runtime/runtime1.goc b/third_party/gofrontend/libgo/runtime/runtime1.goc
new file mode 100644
index 0000000..e643965
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/runtime1.goc
@@ -0,0 +1,76 @@
+// Copyright 2010 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 runtime
+#include "runtime.h"
+#include "arch.h"
+#include "go-type.h"
+
+func GOMAXPROCS(n int) (ret int) {
+	ret = runtime_gomaxprocsfunc(n);
+}
+
+func NumCPU() (ret int) {
+	ret = runtime_ncpu;
+}
+
+func NumCgoCall() (ret int64) {
+	M *mp;
+
+	ret = 0;
+	for(mp=runtime_atomicloadp(&runtime_allm); mp; mp=mp->alllink)
+		ret += mp->ncgocall;
+}
+
+func newParFor(nthrmax uint32) (desc *ParFor) {
+	desc = runtime_parforalloc(nthrmax);
+}
+
+func parForSetup(desc *ParFor, nthr uint32, n uint32, ctx *byte, wait bool, body *byte) {
+	runtime_parforsetup(desc, nthr, n, ctx, wait, *(void(**)(ParFor*, uint32))body);
+}
+
+func parForDo(desc *ParFor) {
+	runtime_parfordo(desc);
+}
+
+func parForIters(desc *ParFor, tid uintptr) (start uintptr, end uintptr) {
+	runtime_parforiters(desc, tid, &start, &end);
+}
+
+func typestring(e Eface) (s String) {
+	s = *e.__type_descriptor->__reflection;
+}
+
+func golockedOSThread() (ret bool) {
+	ret = runtime_lockedOSThread();
+}
+
+func NumGoroutine() (ret int) {
+	ret = runtime_gcount();
+}
+
+func getgoroot() (out String) {
+	const byte *p;
+
+	p = runtime_getenv("GOROOT");
+	out = runtime_gostringnocopy(p);
+}
+
+func runtime_pprof.runtime_cyclesPerSecond() (res int64) {
+	res = runtime_tickspersecond();
+}
+
+func sync.runtime_procPin() (p int) {
+	M *mp;
+
+	mp = runtime_m();
+	// Disable preemption.
+	mp->locks++;
+	p = mp->p->id;
+}
+
+func sync.runtime_procUnpin() {
+	runtime_m()->locks--;
+}
diff --git a/third_party/gofrontend/libgo/runtime/sema.goc b/third_party/gofrontend/libgo/runtime/sema.goc
new file mode 100644
index 0000000..877ee07
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/sema.goc
@@ -0,0 +1,299 @@
+// 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.
+
+// Semaphore implementation exposed to Go.
+// Intended use is provide a sleep and wakeup
+// primitive that can be used in the contended case
+// of other synchronization primitives.
+// Thus it targets the same goal as Linux's futex,
+// but it has much simpler semantics.
+//
+// That is, don't think of these as semaphores.
+// Think of them as a way to implement sleep and wakeup
+// such that every sleep is paired with a single wakeup,
+// even if, due to races, the wakeup happens before the sleep.
+//
+// See Mullender and Cox, ``Semaphores in Plan 9,''
+// http://swtch.com/semaphore.pdf
+
+package sync
+#include "runtime.h"
+#include "arch.h"
+
+typedef struct SemaWaiter SemaWaiter;
+struct SemaWaiter
+{
+	uint32 volatile*	addr;
+	G*	g;
+	int64	releasetime;
+	int32	nrelease;	// -1 for acquire
+	SemaWaiter*	prev;
+	SemaWaiter*	next;
+};
+
+typedef struct SemaRoot SemaRoot;
+struct SemaRoot
+{
+	Lock		lock;
+	SemaWaiter*	head;
+	SemaWaiter*	tail;
+	// Number of waiters. Read w/o the lock.
+	uint32 volatile	nwait;
+};
+
+// Prime to not correlate with any user patterns.
+#define SEMTABLESZ 251
+
+struct semtable
+{
+	SemaRoot root;
+	uint8 pad[CacheLineSize-sizeof(SemaRoot)];
+};
+static struct semtable semtable[SEMTABLESZ];
+
+static SemaRoot*
+semroot(uint32 volatile *addr)
+{
+	return &semtable[((uintptr)addr >> 3) % SEMTABLESZ].root;
+}
+
+static void
+semqueue(SemaRoot *root, uint32 volatile *addr, SemaWaiter *s)
+{
+	s->g = runtime_g();
+	s->addr = addr;
+	s->next = nil;
+	s->prev = root->tail;
+	if(root->tail)
+		root->tail->next = s;
+	else
+		root->head = s;
+	root->tail = s;
+}
+
+static void
+semdequeue(SemaRoot *root, SemaWaiter *s)
+{
+	if(s->next)
+		s->next->prev = s->prev;
+	else
+		root->tail = s->prev;
+	if(s->prev)
+		s->prev->next = s->next;
+	else
+		root->head = s->next;
+	s->prev = nil;
+	s->next = nil;
+}
+
+static int32
+cansemacquire(uint32 volatile *addr)
+{
+	uint32 v;
+
+	while((v = runtime_atomicload(addr)) > 0)
+		if(runtime_cas(addr, v, v-1))
+			return 1;
+	return 0;
+}
+
+void
+runtime_semacquire(uint32 volatile *addr, bool profile)
+{
+	SemaWaiter s;	// Needs to be allocated on stack, otherwise garbage collector could deallocate it
+	SemaRoot *root;
+	int64 t0;
+	
+	// Easy case.
+	if(cansemacquire(addr))
+		return;
+
+	// Harder case:
+	//	increment waiter count
+	//	try cansemacquire one more time, return if succeeded
+	//	enqueue itself as a waiter
+	//	sleep
+	//	(waiter descriptor is dequeued by signaler)
+	root = semroot(addr);
+	t0 = 0;
+	s.releasetime = 0;
+	if(profile && runtime_blockprofilerate > 0) {
+		t0 = runtime_cputicks();
+		s.releasetime = -1;
+	}
+	for(;;) {
+
+		runtime_lock(&root->lock);
+		// Add ourselves to nwait to disable "easy case" in semrelease.
+		runtime_xadd(&root->nwait, 1);
+		// Check cansemacquire to avoid missed wakeup.
+		if(cansemacquire(addr)) {
+			runtime_xadd(&root->nwait, -1);
+			runtime_unlock(&root->lock);
+			return;
+		}
+		// Any semrelease after the cansemacquire knows we're waiting
+		// (we set nwait above), so go to sleep.
+		semqueue(root, addr, &s);
+		runtime_parkunlock(&root->lock, "semacquire");
+		if(cansemacquire(addr)) {
+			if(t0)
+				runtime_blockevent(s.releasetime - t0, 3);
+			return;
+		}
+	}
+}
+
+void
+runtime_semrelease(uint32 volatile *addr)
+{
+	SemaWaiter *s;
+	SemaRoot *root;
+
+	root = semroot(addr);
+	runtime_xadd(addr, 1);
+
+	// Easy case: no waiters?
+	// This check must happen after the xadd, to avoid a missed wakeup
+	// (see loop in semacquire).
+	if(runtime_atomicload(&root->nwait) == 0)
+		return;
+
+	// Harder case: search for a waiter and wake it.
+	runtime_lock(&root->lock);
+	if(runtime_atomicload(&root->nwait) == 0) {
+		// The count is already consumed by another goroutine,
+		// so no need to wake up another goroutine.
+		runtime_unlock(&root->lock);
+		return;
+	}
+	for(s = root->head; s; s = s->next) {
+		if(s->addr == addr) {
+			runtime_xadd(&root->nwait, -1);
+			semdequeue(root, s);
+			break;
+		}
+	}
+	runtime_unlock(&root->lock);
+	if(s) {
+		if(s->releasetime)
+			s->releasetime = runtime_cputicks();
+		runtime_ready(s->g);
+	}
+}
+
+// TODO(dvyukov): move to netpoll.goc once it's used by all OSes.
+void net_runtime_Semacquire(uint32 *addr)
+  __asm__ (GOSYM_PREFIX "net.runtime_Semacquire");
+
+void net_runtime_Semacquire(uint32 *addr)
+{
+	runtime_semacquire(addr, true);
+}
+
+void net_runtime_Semrelease(uint32 *addr)
+  __asm__ (GOSYM_PREFIX "net.runtime_Semrelease");
+
+void net_runtime_Semrelease(uint32 *addr)
+{
+	runtime_semrelease(addr);
+}
+
+func runtime_Semacquire(addr *uint32) {
+	runtime_semacquire(addr, true);
+}
+
+func runtime_Semrelease(addr *uint32) {
+	runtime_semrelease(addr);
+}
+
+typedef struct SyncSema SyncSema;
+struct SyncSema
+{
+	Lock		lock;
+	SemaWaiter*	head;
+	SemaWaiter*	tail;
+};
+
+func runtime_Syncsemcheck(size uintptr) {
+	if(size != sizeof(SyncSema)) {
+		runtime_printf("bad SyncSema size: sync:%D runtime:%D\n", (int64)size, (int64)sizeof(SyncSema));
+		runtime_throw("bad SyncSema size");
+	}
+}
+
+// Syncsemacquire waits for a pairing Syncsemrelease on the same semaphore s.
+func runtime_Syncsemacquire(s *SyncSema) {
+	SemaWaiter w, *wake;
+	int64 t0;
+
+	w.g = runtime_g();
+	w.nrelease = -1;
+	w.next = nil;
+	w.releasetime = 0;
+	t0 = 0;
+	if(runtime_blockprofilerate > 0) {
+		t0 = runtime_cputicks();
+		w.releasetime = -1;
+	}
+
+	runtime_lock(&s->lock);
+	if(s->head && s->head->nrelease > 0) {
+		// have pending release, consume it
+		wake = nil;
+		s->head->nrelease--;
+		if(s->head->nrelease == 0) {
+			wake = s->head;
+			s->head = wake->next;
+			if(s->head == nil)
+				s->tail = nil;
+		}
+		runtime_unlock(&s->lock);
+		if(wake)
+			runtime_ready(wake->g);
+	} else {
+		// enqueue itself
+		if(s->tail == nil)
+			s->head = &w;
+		else
+			s->tail->next = &w;
+		s->tail = &w;
+		runtime_parkunlock(&s->lock, "semacquire");
+		if(t0)
+			runtime_blockevent(w.releasetime - t0, 2);
+	}
+}
+
+// Syncsemrelease waits for n pairing Syncsemacquire on the same semaphore s.
+func runtime_Syncsemrelease(s *SyncSema, n uint32) {
+	SemaWaiter w, *wake;
+
+	w.g = runtime_g();
+	w.nrelease = (int32)n;
+	w.next = nil;
+	w.releasetime = 0;
+
+	runtime_lock(&s->lock);
+	while(w.nrelease > 0 && s->head && s->head->nrelease < 0) {
+		// have pending acquire, satisfy it
+		wake = s->head;
+		s->head = wake->next;
+		if(s->head == nil)
+			s->tail = nil;
+		if(wake->releasetime)
+			wake->releasetime = runtime_cputicks();
+		runtime_ready(wake->g);
+		w.nrelease--;
+	}
+	if(w.nrelease > 0) {
+		// enqueue itself
+		if(s->tail == nil)
+			s->head = &w;
+		else
+			s->tail->next = &w;
+		s->tail = &w;
+		runtime_parkunlock(&s->lock, "semarelease");
+	} else
+		runtime_unlock(&s->lock);
+}
diff --git a/third_party/gofrontend/libgo/runtime/signal_unix.c b/third_party/gofrontend/libgo/runtime/signal_unix.c
new file mode 100644
index 0000000..66638de
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/signal_unix.c
@@ -0,0 +1,160 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+#include <sys/time.h>
+
+#include "runtime.h"
+#include "defs.h"
+#include "signal_unix.h"
+
+extern SigTab runtime_sigtab[];
+
+void
+runtime_initsig(void)
+{
+	int32 i;
+	SigTab *t;
+
+	// First call: basic setup.
+	for(i = 0; runtime_sigtab[i].sig != -1; i++) {
+		t = &runtime_sigtab[i];
+		if((t->flags == 0) || (t->flags & SigDefault))
+			continue;
+
+		// For some signals, we respect an inherited SIG_IGN handler
+		// rather than insist on installing our own default handler.
+		// Even these signals can be fetched using the os/signal package.
+		switch(t->sig) {
+		case SIGHUP:
+		case SIGINT:
+			if(runtime_getsig(i) == GO_SIG_IGN) {
+				t->flags = SigNotify | SigIgnored;
+				continue;
+			}
+		}
+
+		t->flags |= SigHandling;
+		runtime_setsig(i, runtime_sighandler, true);
+	}
+}
+
+void
+runtime_sigenable(uint32 sig)
+{
+	int32 i;
+	SigTab *t;
+
+	t = nil;
+	for(i = 0; runtime_sigtab[i].sig != -1; i++) {
+		if(runtime_sigtab[i].sig == (int32)sig) {
+			t = &runtime_sigtab[i];
+			break;
+		}
+	}
+
+	if(t == nil)
+		return;
+
+	if((t->flags & SigNotify) && !(t->flags & SigHandling)) {
+		t->flags |= SigHandling;
+		if(runtime_getsig(i) == GO_SIG_IGN)
+			t->flags |= SigIgnored;
+		runtime_setsig(i, runtime_sighandler, true);
+	}
+}
+
+void
+runtime_sigdisable(uint32 sig)
+{
+	int32 i;
+	SigTab *t;
+
+	t = nil;
+	for(i = 0; runtime_sigtab[i].sig != -1; i++) {
+		if(runtime_sigtab[i].sig == (int32)sig) {
+			t = &runtime_sigtab[i];
+			break;
+		}
+	}
+
+	if(t == nil)
+		return;
+
+	if((t->flags & SigNotify) && (t->flags & SigHandling)) {
+		t->flags &= ~SigHandling;
+		if(t->flags & SigIgnored)
+			runtime_setsig(i, GO_SIG_IGN, true);
+		else
+			runtime_setsig(i, GO_SIG_DFL, true);
+	}
+}
+
+void
+runtime_resetcpuprofiler(int32 hz)
+{
+	struct itimerval it;
+
+	runtime_memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime_setitimer(ITIMER_PROF, &it, nil);
+	} else {
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime_setitimer(ITIMER_PROF, &it, nil);
+	}
+	runtime_m()->profilehz = hz;
+}
+
+void
+os_sigpipe(void)
+{
+	int32 i;
+
+	for(i = 0; runtime_sigtab[i].sig != -1; i++)
+		if(runtime_sigtab[i].sig == SIGPIPE)
+			break;
+	runtime_setsig(i, GO_SIG_DFL, false);
+	runtime_raise(SIGPIPE);
+}
+
+void
+runtime_unblocksignals(void)
+{
+	sigset_t sigset_none;
+	sigemptyset(&sigset_none);
+	pthread_sigmask(SIG_SETMASK, &sigset_none, nil);
+}
+
+void
+runtime_crash(void)
+{
+	int32 i;
+
+#ifdef GOOS_darwin
+	// OS X core dumps are linear dumps of the mapped memory,
+	// from the first virtual byte to the last, with zeros in the gaps.
+	// Because of the way we arrange the address space on 64-bit systems,
+	// this means the OS X core file will be >128 GB and even on a zippy
+	// workstation can take OS X well over an hour to write (uninterruptible).
+	// Save users from making that mistake.
+	if(sizeof(void*) == 8)
+		return;
+#endif
+
+	runtime_unblocksignals();
+	for(i = 0; runtime_sigtab[i].sig != -1; i++)
+		if(runtime_sigtab[i].sig == SIGABRT)
+			break;
+	runtime_setsig(i, GO_SIG_DFL, false);
+	runtime_raise(SIGABRT);
+}
+
+void
+runtime_raise(int32 sig)
+{
+	raise(sig);
+}
diff --git a/third_party/gofrontend/libgo/runtime/signal_unix.h b/third_party/gofrontend/libgo/runtime/signal_unix.h
new file mode 100644
index 0000000..1c51740
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/signal_unix.h
@@ -0,0 +1,22 @@
+// Copyright 2013 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 <signal.h>
+
+#define GO_SIG_DFL ((void*)SIG_DFL)
+#define GO_SIG_IGN ((void*)SIG_IGN)
+
+#ifdef SA_SIGINFO
+typedef siginfo_t Siginfo;
+#else
+typedef void *Siginfo;
+#endif
+
+typedef void GoSighandler(int32, Siginfo*, void*, G*);
+void	runtime_setsig(int32, GoSighandler*, bool);
+GoSighandler* runtime_getsig(int32);
+
+void	runtime_sighandler(int32 sig, Siginfo *info, void *context, G *gp);
+void	runtime_raise(int32);
+
diff --git a/third_party/gofrontend/libgo/runtime/sigqueue.goc b/third_party/gofrontend/libgo/runtime/sigqueue.goc
new file mode 100644
index 0000000..7853598
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/sigqueue.goc
@@ -0,0 +1,164 @@
+// 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.
+
+// This file implements runtime support for signal handling.
+//
+// Most synchronization primitives are not available from
+// the signal handler (it cannot block, allocate memory, or use locks)
+// so the handler communicates with a processing goroutine
+// via struct sig, below.
+//
+// sigsend() is called by the signal handler to queue a new signal.
+// signal_recv() is called by the Go program to receive a newly queued signal.
+// Synchronization between sigsend() and signal_recv() is based on the sig.state
+// variable.  It can be in 3 states: 0, HASWAITER and HASSIGNAL.
+// HASWAITER means that signal_recv() is blocked on sig.Note and there are no
+// new pending signals.
+// HASSIGNAL means that sig.mask *may* contain new pending signals,
+// signal_recv() can't be blocked in this state.
+// 0 means that there are no new pending signals and signal_recv() is not blocked.
+// Transitions between states are done atomically with CAS.
+// When signal_recv() is unblocked, it resets sig.Note and rechecks sig.mask.
+// If several sigsend()'s and signal_recv() execute concurrently, it can lead to
+// unnecessary rechecks of sig.mask, but must not lead to missed signals
+// nor deadlocks.
+
+package signal
+#include "config.h"
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+#include "defs.h"
+
+static struct {
+	Note note;
+	uint32 mask[(NSIG+31)/32];
+	uint32 wanted[(NSIG+31)/32];
+	uint32 state;
+	bool inuse;
+} sig;
+
+enum {
+	HASWAITER = 1,
+	HASSIGNAL = 2,
+};
+
+// Called from sighandler to send a signal back out of the signal handling thread.
+bool
+__go_sigsend(int32 s)
+{
+	uint32 bit, mask, old, new;
+
+	if(!sig.inuse || s < 0 || (size_t)s >= 32*nelem(sig.wanted) || !(sig.wanted[s/32]&(1U<<(s&31))))
+		return false;
+	bit = 1 << (s&31);
+	for(;;) {
+		mask = sig.mask[s/32];
+		if(mask & bit)
+			break;		// signal already in queue
+		if(runtime_cas(&sig.mask[s/32], mask, mask|bit)) {
+			// Added to queue.
+			// Only send a wakeup if the receiver needs a kick.
+			for(;;) {
+				old = runtime_atomicload(&sig.state);
+				if(old == HASSIGNAL)
+					break;
+				if(old == HASWAITER)
+					new = 0;
+				else  // if(old == 0)
+					new = HASSIGNAL;
+				if(runtime_cas(&sig.state, old, new)) {
+					if (old == HASWAITER)
+						runtime_notewakeup(&sig.note);
+					break;
+				}
+			}
+			break;
+		}
+	}
+	return true;
+}
+
+// Called to receive the next queued signal.
+// Must only be called from a single goroutine at a time.
+func signal_recv() (m uint32) {
+	static uint32 recv[nelem(sig.mask)];
+	uint32 i, old, new;
+	
+	for(;;) {
+		// Serve from local copy if there are bits left.
+		for(i=0; i<NSIG; i++) {
+			if(recv[i/32]&(1U<<(i&31))) {
+				recv[i/32] ^= 1U<<(i&31);
+				m = i;
+				goto done;
+			}
+		}
+
+		// Check and update sig.state.
+		for(;;) {
+			old = runtime_atomicload(&sig.state);
+			if(old == HASWAITER)
+				runtime_throw("inconsistent state in signal_recv");
+			if(old == HASSIGNAL)
+				new = 0;
+			else  // if(old == 0)
+				new = HASWAITER;
+			if(runtime_cas(&sig.state, old, new)) {
+				if (new == HASWAITER) {
+					runtime_notetsleepg(&sig.note, -1);
+					runtime_noteclear(&sig.note);
+				}
+				break;
+			}
+		}
+
+		// Get a new local copy.
+		for(i=0; (size_t)i<nelem(sig.mask); i++) {
+			for(;;) {
+				m = sig.mask[i];
+				if(runtime_cas(&sig.mask[i], m, 0))
+					break;
+			}
+			recv[i] = m;
+		}
+	}
+
+done:;
+	// goc requires that we fall off the end of functions
+	// that return values instead of using our own return
+	// statements.
+}
+
+// Must only be called from a single goroutine at a time.
+func signal_enable(s uint32) {
+	if(!sig.inuse) {
+		// The first call to signal_enable is for us
+		// to use for initialization.  It does not pass
+		// signal information in m.
+		sig.inuse = true;	// enable reception of signals; cannot disable
+		runtime_noteclear(&sig.note);
+		return;
+	}
+	
+	if(s >= nelem(sig.wanted)*32)
+		return;
+	sig.wanted[s/32] |= 1U<<(s&31);
+	runtime_sigenable(s);
+}
+
+// Must only be called from a single goroutine at a time.
+func signal_disable(s uint32) {
+	if(s >= nelem(sig.wanted)*32)
+		return;
+	sig.wanted[s/32] &= ~(1U<<(s&31));
+	runtime_sigdisable(s);
+}
+
+// This runs on a foreign stack, without an m or a g.  No stack split.
+void
+runtime_badsignal(int sig)
+{
+	__go_sigsend(sig);
+}
diff --git a/third_party/gofrontend/libgo/runtime/string.goc b/third_party/gofrontend/libgo/runtime/string.goc
new file mode 100644
index 0000000..f656318
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/string.goc
@@ -0,0 +1,124 @@
+// Copyright 2009, 2010 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 runtime
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+#include "go-string.h"
+#include "race.h"
+
+#define charntorune(pv, str, len) __go_get_rune(str, len, pv)
+
+const String	runtime_emptystring;
+
+intgo
+runtime_findnull(const byte *s)
+{
+	if(s == nil)
+		return 0;
+	return __builtin_strlen((const char*) s);
+}
+
+intgo
+runtime_findnullw(const uint16 *s)
+{
+	intgo l;
+
+	if(s == nil)
+		return 0;
+	for(l=0; s[l]!=0; l++)
+		;
+	return l;
+}
+
+static String
+gostringsize(intgo l, byte** pmem)
+{
+	String s;
+	byte *mem;
+
+	if(l == 0) {
+		*pmem = nil;
+		return runtime_emptystring;
+	}
+	mem = runtime_mallocgc(l, 0, FlagNoScan|FlagNoZero);
+	s.str = mem;
+	s.len = l;
+	*pmem = mem;
+	return s;
+}
+
+String
+runtime_gostring(const byte *str)
+{
+	intgo l;
+	String s;
+	byte *mem;
+
+	l = runtime_findnull(str);
+	s = gostringsize(l, &mem);
+	runtime_memmove(mem, str, l);
+	return s;
+}
+
+String
+runtime_gostringnocopy(const byte *str)
+{
+	String s;
+	
+	s.str = str;
+	s.len = runtime_findnull(str);
+	return s;
+}
+
+func cstringToGo(str *byte) (s String) {
+	s = runtime_gostringnocopy(str);
+}
+
+enum
+{
+	Runeself	= 0x80,
+};
+
+func stringiter(s String, k int) (retk int) {
+	int32 l;
+
+	if(k >= s.len) {
+		// retk=0 is end of iteration
+		retk = 0;
+		goto out;
+	}
+
+	l = s.str[k];
+	if(l < Runeself) {
+		retk = k+1;
+		goto out;
+	}
+
+	// multi-char rune
+	retk = k + charntorune(&l, s.str+k, s.len-k);
+
+out:
+}
+
+func stringiter2(s String, k int) (retk int, retv int32) {
+	if(k >= s.len) {
+		// retk=0 is end of iteration
+		retk = 0;
+		retv = 0;
+		goto out;
+	}
+
+	retv = s.str[k];
+	if(retv < Runeself) {
+		retk = k+1;
+		goto out;
+	}
+
+	// multi-char rune
+	retk = k + charntorune(&retv, s.str+k, s.len-k);
+
+out:
+}
diff --git a/third_party/gofrontend/libgo/runtime/thread-linux.c b/third_party/gofrontend/libgo/runtime/thread-linux.c
new file mode 100644
index 0000000..ae56261
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/thread-linux.c
@@ -0,0 +1,83 @@
+// 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.
+
+#include "runtime.h"
+#include "defs.h"
+#include "signal_unix.h"
+
+// Linux futex.
+//
+//	futexsleep(uint32 *addr, uint32 val)
+//	futexwakeup(uint32 *addr)
+//
+// Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
+// Futexwakeup wakes up threads sleeping on addr.
+// Futexsleep is allowed to wake up spuriously.
+
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <syscall.h>
+#include <linux/futex.h>
+
+typedef struct timespec Timespec;
+
+// Atomically,
+//	if(*addr == val) sleep
+// Might be woken up spuriously; that's allowed.
+// Don't sleep longer than ns; ns < 0 means forever.
+void
+runtime_futexsleep(uint32 *addr, uint32 val, int64 ns)
+{
+	Timespec ts;
+	int32 nsec;
+
+	// Some Linux kernels have a bug where futex of
+	// FUTEX_WAIT returns an internal error code
+	// as an errno.  Libpthread ignores the return value
+	// here, and so can we: as it says a few lines up,
+	// spurious wakeups are allowed.
+
+	if(ns < 0) {
+		syscall(__NR_futex, addr, FUTEX_WAIT, val, nil, nil, 0);
+		return;
+	}
+	ts.tv_sec = runtime_timediv(ns, 1000000000LL, &nsec);
+	ts.tv_nsec = nsec;
+	syscall(__NR_futex, addr, FUTEX_WAIT, val, &ts, nil, 0);
+}
+
+// If any procs are sleeping on addr, wake up at most cnt.
+void
+runtime_futexwakeup(uint32 *addr, uint32 cnt)
+{
+	int64 ret;
+
+	ret = syscall(__NR_futex, addr, FUTEX_WAKE, cnt, nil, nil, 0);
+
+	if(ret >= 0)
+		return;
+
+	// I don't know that futex wakeup can return
+	// EAGAIN or EINTR, but if it does, it would be
+	// safe to loop and call futex again.
+	runtime_printf("futexwakeup addr=%p returned %D\n", addr, ret);
+	*(int32*)0x1006 = 0x1006;
+}
+
+void
+runtime_osinit(void)
+{
+	runtime_ncpu = getproccount();
+}
+
+void
+runtime_goenvs(void)
+{
+	runtime_goenvs_unix();
+}
diff --git a/third_party/gofrontend/libgo/runtime/thread-sema.c b/third_party/gofrontend/libgo/runtime/thread-sema.c
new file mode 100644
index 0000000..18827b0
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/thread-sema.c
@@ -0,0 +1,148 @@
+// 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.
+
+#include "config.h"
+#include "runtime.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <semaphore.h>
+
+/* If we don't have sem_timedwait, use pthread_cond_timedwait instead.
+   We don't always use condition variables because on some systems
+   pthread_mutex_lock and pthread_mutex_unlock must be called by the
+   same thread.  That is never true of semaphores.  */
+
+struct go_sem
+{
+  sem_t sem;
+
+#ifndef HAVE_SEM_TIMEDWAIT
+  int timedwait;
+  pthread_mutex_t mutex;
+  pthread_cond_t cond;
+#endif
+};
+
+/* Create a semaphore.  */
+
+uintptr
+runtime_semacreate(void)
+{
+  struct go_sem *p;
+
+  /* Call malloc rather than runtime_malloc.  This will allocate space
+     on the C heap.  We can't call runtime_malloc here because it
+     could cause a deadlock.  */
+  p = malloc (sizeof (struct go_sem));
+  if (sem_init (&p->sem, 0, 0) != 0)
+    runtime_throw ("sem_init");
+
+#ifndef HAVE_SEM_TIMEDWAIT
+  if (pthread_mutex_init (&p->mutex, NULL) != 0)
+    runtime_throw ("pthread_mutex_init");
+  if (pthread_cond_init (&p->cond, NULL) != 0)
+    runtime_throw ("pthread_cond_init");
+#endif
+
+  return (uintptr) p;
+}
+
+/* Acquire m->waitsema.  */
+
+int32
+runtime_semasleep (int64 ns)
+{
+  M *m;
+  struct go_sem *sem;
+  int r;
+
+  m = runtime_m ();
+  sem = (struct go_sem *) m->waitsema;
+  if (ns >= 0)
+    {
+      int64 abs;
+      struct timespec ts;
+      int err;
+
+      abs = ns + runtime_nanotime ();
+      ts.tv_sec = abs / 1000000000LL;
+      ts.tv_nsec = abs % 1000000000LL;
+
+      err = 0;
+
+#ifdef HAVE_SEM_TIMEDWAIT
+      r = sem_timedwait (&sem->sem, &ts);
+      if (r != 0)
+	err = errno;
+#else
+      if (pthread_mutex_lock (&sem->mutex) != 0)
+	runtime_throw ("pthread_mutex_lock");
+
+      while ((r = sem_trywait (&sem->sem)) != 0)
+	{
+	  r = pthread_cond_timedwait (&sem->cond, &sem->mutex, &ts);
+	  if (r != 0)
+	    {
+	      err = r;
+	      break;
+	    }
+	}
+
+      if (pthread_mutex_unlock (&sem->mutex) != 0)
+	runtime_throw ("pthread_mutex_unlock");
+#endif
+
+      if (err != 0)
+	{
+	  if (err == ETIMEDOUT || err == EAGAIN || err == EINTR)
+	    return -1;
+	  runtime_throw ("sema_timedwait");
+	}
+      return 0;
+    }
+
+  while (sem_wait (&sem->sem) != 0)
+    {
+      if (errno == EINTR)
+	continue;
+      runtime_throw ("sem_wait");
+    }
+
+  return 0;
+}
+
+/* Wake up mp->waitsema.  */
+
+void
+runtime_semawakeup (M *mp)
+{
+  struct go_sem *sem;
+
+  sem = (struct go_sem *) mp->waitsema;
+  if (sem_post (&sem->sem) != 0)
+    runtime_throw ("sem_post");
+
+#ifndef HAVE_SEM_TIMEDWAIT
+  if (pthread_mutex_lock (&sem->mutex) != 0)
+    runtime_throw ("pthread_mutex_lock");
+  if (pthread_cond_broadcast (&sem->cond) != 0)
+    runtime_throw ("pthread_cond_broadcast");
+  if (pthread_mutex_unlock (&sem->mutex) != 0)
+    runtime_throw ("pthread_mutex_unlock");
+#endif
+}
+
+void
+runtime_osinit (void)
+{
+  runtime_ncpu = getproccount();
+}
+
+void
+runtime_goenvs (void)
+{
+  runtime_goenvs_unix ();
+}
diff --git a/third_party/gofrontend/libgo/runtime/thread.c b/third_party/gofrontend/libgo/runtime/thread.c
new file mode 100644
index 0000000..83ee006
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/thread.c
@@ -0,0 +1,161 @@
+// Copyright 2010 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 <errno.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "runtime.h"
+#include "go-assert.h"
+
+/* For targets which don't have the required sync support.  Really
+   these should be provided by gcc itself.  FIXME.  */
+
+#if !defined (HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4) || !defined (HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8) || !defined (HAVE_SYNC_FETCH_AND_ADD_4) || !defined (HAVE_SYNC_ADD_AND_FETCH_8)
+
+static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#endif
+
+#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
+
+_Bool
+__sync_bool_compare_and_swap_4 (uint32*, uint32, uint32)
+  __attribute__ ((visibility ("hidden")));
+
+_Bool
+__sync_bool_compare_and_swap_4 (uint32* ptr, uint32 old, uint32 new)
+{
+  int i;
+  _Bool ret;
+
+  i = pthread_mutex_lock (&sync_lock);
+  __go_assert (i == 0);
+
+  if (*ptr != old)
+    ret = 0;
+  else
+    {
+      *ptr = new;
+      ret = 1;
+    }
+
+  i = pthread_mutex_unlock (&sync_lock);
+  __go_assert (i == 0);
+
+  return ret;
+}
+
+#endif
+
+#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8
+
+_Bool
+__sync_bool_compare_and_swap_8 (uint64*, uint64, uint64)
+  __attribute__ ((visibility ("hidden")));
+
+_Bool
+__sync_bool_compare_and_swap_8 (uint64* ptr, uint64 old, uint64 new)
+{
+  int i;
+  _Bool ret;
+
+  i = pthread_mutex_lock (&sync_lock);
+  __go_assert (i == 0);
+
+  if (*ptr != old)
+    ret = 0;
+  else
+    {
+      *ptr = new;
+      ret = 1;
+    }
+
+  i = pthread_mutex_unlock (&sync_lock);
+  __go_assert (i == 0);
+
+  return ret;
+}
+
+#endif
+
+#ifndef HAVE_SYNC_FETCH_AND_ADD_4
+
+uint32
+__sync_fetch_and_add_4 (uint32*, uint32)
+  __attribute__ ((visibility ("hidden")));
+
+uint32
+__sync_fetch_and_add_4 (uint32* ptr, uint32 add)
+{
+  int i;
+  uint32 ret;
+
+  i = pthread_mutex_lock (&sync_lock);
+  __go_assert (i == 0);
+
+  ret = *ptr;
+  *ptr += add;
+
+  i = pthread_mutex_unlock (&sync_lock);
+  __go_assert (i == 0);
+
+  return ret;
+}
+
+#endif
+
+#ifndef HAVE_SYNC_ADD_AND_FETCH_8
+
+uint64
+__sync_add_and_fetch_8 (uint64*, uint64)
+  __attribute__ ((visibility ("hidden")));
+
+uint64
+__sync_add_and_fetch_8 (uint64* ptr, uint64 add)
+{
+  int i;
+  uint64 ret;
+
+  i = pthread_mutex_lock (&sync_lock);
+  __go_assert (i == 0);
+
+  *ptr += add;
+  ret = *ptr;
+
+  i = pthread_mutex_unlock (&sync_lock);
+  __go_assert (i == 0);
+
+  return ret;
+}
+
+#endif
+
+uintptr
+runtime_memlimit(void)
+{
+	struct rlimit rl;
+	uintptr used;
+
+	if(getrlimit(RLIMIT_AS, &rl) != 0)
+		return 0;
+	if(rl.rlim_cur >= 0x7fffffff)
+		return 0;
+
+	// Estimate our VM footprint excluding the heap.
+	// Not an exact science: use size of binary plus
+	// some room for thread stacks.
+	used = (64<<20);
+	if(used >= rl.rlim_cur)
+		return 0;
+
+	// If there's not at least 16 MB left, we're probably
+	// not going to be able to do much.  Treat as no limit.
+	rl.rlim_cur -= used;
+	if(rl.rlim_cur < (16<<20))
+		return 0;
+
+	return rl.rlim_cur - used;
+}
diff --git a/third_party/gofrontend/libgo/runtime/time.goc b/third_party/gofrontend/libgo/runtime/time.goc
new file mode 100644
index 0000000..e300215
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/time.goc
@@ -0,0 +1,356 @@
+// 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.
+
+// Time-related runtime and pieces of package time.
+
+package time
+
+#include <sys/time.h>
+
+#include "runtime.h"
+#include "defs.h"
+#include "arch.h"
+#include "malloc.h"
+#include "race.h"
+
+enum {
+	debug = 0,
+};
+
+static Timers timers;
+static void addtimer(Timer*);
+static void dumptimers(const char*);
+
+// nacl fake time support. 
+int64 runtime_timens;
+
+// Package time APIs.
+// Godoc uses the comments in package time, not these.
+
+// time.now is implemented in assembly.
+
+// runtimeNano returns the current value of the runtime clock in nanoseconds.
+func runtimeNano() (ns int64) {
+	ns = runtime_nanotime();
+}
+
+// Sleep puts the current goroutine to sleep for at least ns nanoseconds.
+func Sleep(ns int64) {
+	runtime_tsleep(ns, "sleep");
+}
+
+// startTimer adds t to the timer heap.
+func startTimer(t *Timer) {
+	if(raceenabled)
+		runtime_racerelease(t);
+	runtime_addtimer(t);
+}
+
+// stopTimer removes t from the timer heap if it is there.
+// It returns true if t was removed, false if t wasn't even there.
+func stopTimer(t *Timer) (stopped bool) {
+	stopped = runtime_deltimer(t);
+}
+
+// C runtime.
+
+int64 runtime_unixnanotime(void)
+{
+	struct time_now_ret r;
+
+	r = now();
+	return r.sec*1000000000 + r.nsec;
+}
+
+static void timerproc(void*);
+static void siftup(int32);
+static void siftdown(int32);
+
+// Ready the goroutine e.data.
+static void
+ready(int64 now, Eface e)
+{
+	USED(now);
+
+	runtime_ready(e.__object);
+}
+
+static FuncVal readyv = {(void(*)(void))ready};
+
+// Put the current goroutine to sleep for ns nanoseconds.
+void
+runtime_tsleep(int64 ns, const char *reason)
+{
+	G* g;
+	Timer t;
+
+	g = runtime_g();
+
+	if(ns <= 0)
+		return;
+
+	t.when = runtime_nanotime() + ns;
+	t.period = 0;
+	t.fv = &readyv;
+	t.arg.__object = g;
+	runtime_lock(&timers.lock);
+	addtimer(&t);
+	runtime_parkunlock(&timers.lock, reason);
+}
+
+void
+runtime_addtimer(Timer *t)
+{
+	runtime_lock(&timers.lock);
+	addtimer(t);
+	runtime_unlock(&timers.lock);
+}
+
+// Add a timer to the heap and start or kick the timer proc
+// if the new timer is earlier than any of the others.
+static void
+addtimer(Timer *t)
+{
+	int32 n;
+	Timer **nt;
+
+	// when must never be negative; otherwise timerproc will overflow
+	// during its delta calculation and never expire other timers.
+	if(t->when < 0)
+		t->when = (int64)((1ULL<<63)-1);
+
+	if(timers.len >= timers.cap) {
+		// Grow slice.
+		n = 16;
+		if(n <= timers.cap)
+			n = timers.cap*3 / 2;
+		nt = runtime_malloc(n*sizeof nt[0]);
+		runtime_memmove(nt, timers.t, timers.len*sizeof nt[0]);
+		runtime_free(timers.t);
+		timers.t = nt;
+		timers.cap = n;
+	}
+	t->i = timers.len++;
+	timers.t[t->i] = t;
+	siftup(t->i);
+	if(t->i == 0) {
+		// siftup moved to top: new earliest deadline.
+		if(timers.sleeping) {
+			timers.sleeping = false;
+			runtime_notewakeup(&timers.waitnote);
+		}
+		if(timers.rescheduling) {
+			timers.rescheduling = false;
+			runtime_ready(timers.timerproc);
+		}
+	}
+	if(timers.timerproc == nil) {
+		timers.timerproc = __go_go(timerproc, nil);
+		timers.timerproc->issystem = true;
+	}
+	if(debug)
+		dumptimers("addtimer");
+}
+
+// Used to force a dereference before the lock is acquired.
+static int32 gi;
+
+// Delete timer t from the heap.
+// Do not need to update the timerproc:
+// if it wakes up early, no big deal.
+bool
+runtime_deltimer(Timer *t)
+{
+	int32 i;
+
+	// Dereference t so that any panic happens before the lock is held.
+	// Discard result, because t might be moving in the heap.
+	i = t->i;
+	gi = i;
+
+	runtime_lock(&timers.lock);
+
+	// t may not be registered anymore and may have
+	// a bogus i (typically 0, if generated by Go).
+	// Verify it before proceeding.
+	i = t->i;
+	if(i < 0 || i >= timers.len || timers.t[i] != t) {
+		runtime_unlock(&timers.lock);
+		return false;
+	}
+
+	timers.len--;
+	if(i == timers.len) {
+		timers.t[i] = nil;
+	} else {
+		timers.t[i] = timers.t[timers.len];
+		timers.t[timers.len] = nil;
+		timers.t[i]->i = i;
+		siftup(i);
+		siftdown(i);
+	}
+	if(debug)
+		dumptimers("deltimer");
+	runtime_unlock(&timers.lock);
+	return true;
+}
+
+// Timerproc runs the time-driven events.
+// It sleeps until the next event in the timers heap.
+// If addtimer inserts a new earlier event, addtimer
+// wakes timerproc early.
+static void
+timerproc(void* dummy __attribute__ ((unused)))
+{
+	int64 delta, now;
+	Timer *t;
+	FuncVal *fv;
+	void (*f)(int64, Eface);
+	Eface arg;
+
+	for(;;) {
+		runtime_lock(&timers.lock);
+		timers.sleeping = false;
+		now = runtime_nanotime();
+		for(;;) {
+			if(timers.len == 0) {
+				delta = -1;
+				break;
+			}
+			t = timers.t[0];
+			delta = t->when - now;
+			if(delta > 0)
+				break;
+			if(t->period > 0) {
+				// leave in heap but adjust next time to fire
+				t->when += t->period * (1 + -delta/t->period);
+				siftdown(0);
+			} else {
+				// remove from heap
+				timers.t[0] = timers.t[--timers.len];
+				timers.t[0]->i = 0;
+				siftdown(0);
+				t->i = -1;  // mark as removed
+			}
+			fv = t->fv;
+			f = (void*)t->fv->fn;
+			arg = t->arg;
+			runtime_unlock(&timers.lock);
+			if(raceenabled)
+				runtime_raceacquire(t);
+			__go_set_closure(fv);
+			f(now, arg);
+
+			// clear f and arg to avoid leak while sleeping for next timer
+			f = nil;
+			USED(f);
+			arg.__type_descriptor = nil;
+			arg.__object = nil;
+			USED(&arg);
+
+			runtime_lock(&timers.lock);
+		}
+		if(delta < 0) {
+			// No timers left - put goroutine to sleep.
+			timers.rescheduling = true;
+			runtime_g()->isbackground = true;
+			runtime_parkunlock(&timers.lock, "timer goroutine (idle)");
+			runtime_g()->isbackground = false;
+			continue;
+		}
+		// At least one timer pending.  Sleep until then.
+		timers.sleeping = true;
+		runtime_noteclear(&timers.waitnote);
+		runtime_unlock(&timers.lock);
+		runtime_notetsleepg(&timers.waitnote, delta);
+	}
+}
+
+// heap maintenance algorithms.
+
+static void
+siftup(int32 i)
+{
+	int32 p;
+	int64 when;
+	Timer **t, *tmp;
+
+	t = timers.t;
+	when = t[i]->when;
+	tmp = t[i];
+	while(i > 0) {
+		p = (i-1)/4;  // parent
+		if(when >= t[p]->when)
+			break;
+		t[i] = t[p];
+		t[i]->i = i;
+		t[p] = tmp;
+		tmp->i = p;
+		i = p;
+	}
+}
+
+static void
+siftdown(int32 i)
+{
+	int32 c, c3, len;
+	int64 when, w, w3;
+	Timer **t, *tmp;
+
+	t = timers.t;
+	len = timers.len;
+	when = t[i]->when;
+	tmp = t[i];
+	for(;;) {
+		c = i*4 + 1;  // left child
+		c3 = c + 2;  // mid child
+		if(c >= len) {
+			break;
+		}
+		w = t[c]->when;
+		if(c+1 < len && t[c+1]->when < w) {
+			w = t[c+1]->when;
+			c++;
+		}
+		if(c3 < len) {
+			w3 = t[c3]->when;
+			if(c3+1 < len && t[c3+1]->when < w3) {
+				w3 = t[c3+1]->when;
+				c3++;
+			}
+			if(w3 < w) {
+				w = w3;
+				c = c3;
+			}
+		}
+		if(w >= when)
+			break;
+		t[i] = t[c];
+		t[i]->i = i;
+		t[c] = tmp;
+		tmp->i = c;
+		i = c;
+	}
+}
+
+static void
+dumptimers(const char *msg)
+{
+	Timer *t;
+	int32 i;
+
+	runtime_printf("timers: %s\n", msg);
+	for(i = 0; i < timers.len; i++) {
+		t = timers.t[i];
+		runtime_printf("\t%d\t%p:\ti %d when %D period %D fn %p\n",
+				i, t, t->i, t->when, t->period, t->fv->fn);
+	}
+	runtime_printf("\n");
+}
+
+void
+runtime_time_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj))
+{
+	enqueue1(wbufp, (Obj){(byte*)&timers, sizeof timers, 0});
+}
diff --git a/third_party/gofrontend/libgo/runtime/yield.c b/third_party/gofrontend/libgo/runtime/yield.c
new file mode 100644
index 0000000..442d346
--- /dev/null
+++ b/third_party/gofrontend/libgo/runtime/yield.c
@@ -0,0 +1,56 @@
+// 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.
+
+#include "config.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sched.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#if defined (__i386__) || defined (__x86_64__)
+#include <xmmintrin.h>
+#endif
+
+#include "runtime.h"
+
+/* Spin wait.  */
+
+void
+runtime_procyield (uint32 cnt)
+{
+  volatile uint32 i;
+
+  for (i = 0; i < cnt; ++i)
+    {
+#if defined (__i386__) || defined (__x86_64__)
+      _mm_pause ();
+#endif
+    }
+}
+
+/* Ask the OS to reschedule this thread.  */
+
+void
+runtime_osyield (void)
+{
+  sched_yield ();
+}
+
+/* Sleep for some number of microseconds.  */
+
+void
+runtime_usleep (uint32 us)
+{
+  struct timeval tv;
+
+  tv.tv_sec = us / 1000000;
+  tv.tv_usec = us % 1000000;
+  select (0, NULL, NULL, NULL, &tv);
+}
diff --git a/third_party/gofrontend/libgo/testsuite/Makefile.am b/third_party/gofrontend/libgo/testsuite/Makefile.am
new file mode 100644
index 0000000..8c6249d
--- /dev/null
+++ b/third_party/gofrontend/libgo/testsuite/Makefile.am
@@ -0,0 +1,21 @@
+## Process this file with automake to produce Makefile.in.
+
+AUTOMAKE_OPTIONS = foreign dejagnu
+
+# Setup the testing framework, if you have one
+EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
+            echo $(top_builddir)/../expect/expect ; \
+          else echo expect ; fi`
+
+RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
+	       echo $(top_srcdir)/../dejagnu/runtest ; \
+	    else echo runtest; fi`
+
+# When running the tests we set GCC_EXEC_PREFIX to the install tree so that
+# files that have already been installed there will be found.  The -B option
+# overrides it, so use of GCC_EXEC_PREFIX will not result in using GCC files
+# from the install tree.
+
+AM_RUNTESTFLAGS = "TEST_GCC_EXEC_PREFIX=$(libdir)/gcc"
+
+CLEANFILES = *.log *.sum
diff --git a/third_party/gofrontend/libgo/testsuite/Makefile.in b/third_party/gofrontend/libgo/testsuite/Makefile.in
new file mode 100644
index 0000000..7f7fb74
--- /dev/null
+++ b/third_party/gofrontend/libgo/testsuite/Makefile.in
@@ -0,0 +1,423 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = testsuite
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
+	$(top_srcdir)/../config/lead-dot.m4 \
+	$(top_srcdir)/../config/multi.m4 \
+	$(top_srcdir)/../config/override.m4 \
+	$(top_srcdir)/../config/unwind_ipinfo.m4 \
+	$(top_srcdir)/config/go.m4 $(top_srcdir)/config/libtool.m4 \
+	$(top_srcdir)/config/ltoptions.m4 \
+	$(top_srcdir)/config/ltsugar.m4 \
+	$(top_srcdir)/config/ltversion.m4 \
+	$(top_srcdir)/config/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DEJATOOL = $(PACKAGE)
+RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GOARCH = @GOARCH@
+GOC = @GOC@
+GOCFLAGS = @GOCFLAGS@
+GOOS = @GOOS@
+GO_LIBCALL_OS_ARCH_FILE = @GO_LIBCALL_OS_ARCH_FILE@
+GO_LIBCALL_OS_FILE = @GO_LIBCALL_OS_FILE@
+GO_SYSCALL_OS_ARCH_FILE = @GO_SYSCALL_OS_ARCH_FILE@
+GO_SYSCALL_OS_FILE = @GO_SYSCALL_OS_FILE@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBATOMIC = @LIBATOMIC@
+LIBFFI = @LIBFFI@
+LIBFFIINCS = @LIBFFIINCS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MATH_FLAG = @MATH_FLAG@
+MATH_LIBS = @MATH_LIBS@
+MKDIR_P = @MKDIR_P@
+NET_LIBS = @NET_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJCOPY = @OBJCOPY@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OSCFLAGS = @OSCFLAGS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SIZEOF_STRUCT_EPOLL_EVENT = @SIZEOF_STRUCT_EPOLL_EVENT@
+SPLIT_STACK = @SPLIT_STACK@
+STRINGOPS_FLAG = @STRINGOPS_FLAG@
+STRIP = @STRIP@
+STRUCT_EPOLL_EVENT_FD_OFFSET = @STRUCT_EPOLL_EVENT_FD_OFFSET@
+USE_DEJAGNU = @USE_DEJAGNU@
+VERSION = @VERSION@
+WARN_FLAGS = @WARN_FLAGS@
+WERROR = @WERROR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
+exec_prefix = @exec_prefix@
+glibgo_toolexecdir = @glibgo_toolexecdir@
+glibgo_toolexeclibdir = @glibgo_toolexeclibdir@
+go_include = @go_include@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libtool_VERSION = @libtool_VERSION@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+nover_glibgo_toolexeclibdir = @nover_glibgo_toolexeclibdir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign dejagnu
+
+# Setup the testing framework, if you have one
+EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
+            echo $(top_builddir)/../expect/expect ; \
+          else echo expect ; fi`
+
+RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
+	       echo $(top_srcdir)/../dejagnu/runtest ; \
+	    else echo runtest; fi`
+
+
+# When running the tests we set GCC_EXEC_PREFIX to the install tree so that
+# files that have already been installed there will be found.  The -B option
+# overrides it, so use of GCC_EXEC_PREFIX will not result in using GCC files
+# from the install tree.
+AM_RUNTESTFLAGS = "TEST_GCC_EXEC_PREFIX=$(libdir)/gcc"
+CLEANFILES = *.log *.sum
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign testsuite/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+check-DEJAGNU: site.exp
+	srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \
+	EXPECT=$(EXPECT); export EXPECT; \
+	runtest=$(RUNTEST); \
+	if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+	  exit_status=0; l='$(DEJATOOL)'; for tool in $$l; do \
+	    if $$runtest $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \
+	    then :; else exit_status=1; fi; \
+	  done; \
+	else echo "WARNING: could not find \`runtest'" 1>&2; :;\
+	fi; \
+	exit $$exit_status
+site.exp: Makefile
+	@echo 'Making a new site.exp file...'
+	@echo '## these variables are automatically generated by make ##' >site.tmp
+	@echo '# Do not edit here.  If you wish to override these values' >>site.tmp
+	@echo '# edit the last section' >>site.tmp
+	@echo 'set srcdir $(srcdir)' >>site.tmp
+	@echo "set objdir `pwd`" >>site.tmp
+	@echo 'set build_alias "$(build_alias)"' >>site.tmp
+	@echo 'set build_triplet $(build_triplet)' >>site.tmp
+	@echo 'set host_alias "$(host_alias)"' >>site.tmp
+	@echo 'set host_triplet $(host_triplet)' >>site.tmp
+	@echo 'set target_alias "$(target_alias)"' >>site.tmp
+	@echo 'set target_triplet $(target_triplet)' >>site.tmp
+	@echo '## All variables above are generated by configure. Do Not Edit ##' >>site.tmp
+	@test ! -f site.exp || \
+	  sed '1,/^## All variables above are.*##/ d' site.exp >> site.tmp
+	@-rm -f site.bak
+	@test ! -f site.exp || mv site.exp site.bak
+	@mv site.tmp site.exp
+
+distclean-DEJAGNU:
+	-rm -f site.exp site.bak
+	-l='$(DEJATOOL)'; for tool in $$l; do \
+	  rm -f $$tool.sum $$tool.log; \
+	done
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-DEJAGNU distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: all all-am check check-DEJAGNU check-am clean clean-generic \
+	clean-libtool distclean distclean-DEJAGNU distclean-generic \
+	distclean-libtool dvi dvi-am html html-am info info-am install \
+	install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/third_party/gofrontend/libgo/testsuite/gotest b/third_party/gofrontend/libgo/testsuite/gotest
new file mode 100755
index 0000000..39beac3
--- /dev/null
+++ b/third_party/gofrontend/libgo/testsuite/gotest
@@ -0,0 +1,538 @@
+#!/bin/sh
+# 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.
+
+# Using all the *_test.go files in the current directory, write out a file
+# _testmain.go that runs all its tests. Compile everything and run the
+# tests.
+# If files are named on the command line, use them instead of *_test.go.
+
+# Makes egrep,grep work better in general if we put them
+# in ordinary C mode instead of what the current language is.
+unset LANG
+export LC_ALL=C
+export LC_CTYPE=C
+
+GC=${GC:-gccgo}
+GL=${GL:-${GC-gccgo}}
+GOLIBS=${GOLIBS:-}
+export GC GL GOLIBS
+
+NM=${NM:-nm}
+
+# srcdir is where the source files are found.  basedir is where the
+# source file paths are relative to.
+# gofiles are the test files.  pkgfiles are the source files.
+srcdir=.
+basedir=.
+gofiles=""
+pkgfiles=""
+loop=true
+keep=false
+pkgpath=
+prefix=
+dejagnu=no
+GOARCH=""
+timeout=240
+testname=""
+bench=""
+trace=false
+while $loop; do
+	case "x$1" in
+        x--srcdir)
+		srcdir=$2
+		shift
+		shift
+		;;
+	x--srcdir=*)
+		srcdir=`echo $1 | sed -e 's/^--srcdir=//'`
+		shift
+		;;
+        x--basedir)
+		basedir=$2
+		shift
+		shift
+		;;
+	x--basedir=*)
+		basedir=`echo $1 | sed -e 's/^--basedir=//'`
+		shift
+		;;
+	x--pkgpath)
+		pkgpath=$2
+		shift
+		shift
+		;;
+	x--pkgpath=*)
+		pkgpath=`echo $1 | sed -e 's/^--pkgpath=//'`
+		shift
+		;;
+	x--prefix)
+		prefix=$2
+		shift
+		shift
+		;;
+	x--prefix=*)
+		prefix=`echo $1 | sed -e 's/^--prefix=//'`
+		shift
+		;;
+	x--keep)
+		keep=true
+                shift
+		;;
+	x--pkgfiles)
+		pkgfiles=$2
+		shift
+		shift
+		;;
+	x--pkgfiles=*)
+		pkgfiles=`echo $1 | sed -e 's/^--pkgfiles=//'`
+		shift
+		;;
+	x--dejagnu)
+		dejagnu=$2
+		shift
+		shift
+		;;
+	x--dejagnu=*)
+		dejagnu=`echo $1 | sed -e 's/^--dejagnu=//'`
+		shift
+		;;
+	x--goarch)
+		GOARCH=$2
+		shift
+		shift
+		;;
+	x--goarch=*)
+		GOARCH=`echo $1 | sed -e 's/^--goarch=//'`
+		shift
+		;;
+	x--timeout)
+		timeout=$2
+		shift
+		shift
+		;;
+	x--timeout=*)
+		timeout=`echo $1 | sed -e 's/^--timeout=//'`
+		shift
+		;;
+	x--testname)
+		testname=$2
+		shift
+		shift
+		;;
+	x--testname=*)
+		testname=`echo $1 | sed -e 's/^--testname=//'`
+		shift
+		;;
+	x--bench)
+		bench=$2
+		shift
+		shift
+		;;
+	x--bench=*)
+		bench=`echo $1 | sed -e 's/^--bench=//'`
+		shift
+		;;
+	x--trace)
+		trace=true
+		shift
+		;;
+	x-*)
+		loop=false
+		;;
+	x)
+		loop=false
+		;;
+	*)
+		gofiles="$gofiles $1"
+		shift
+		;;
+	esac
+done
+
+DIR=gotest$$
+rm -rf $DIR
+mkdir $DIR
+
+cd $DIR
+mkdir test
+cd test
+
+if test $keep = false; then
+  trap "cd ../..; rm -rf $DIR" 0 1 2 3 14 15
+else
+  trap "cd ../..; echo Keeping $DIR" 0 1 2 3 14 15
+fi
+
+case "$srcdir" in
+	/*)
+		;;
+	*)
+		srcdir="../../$srcdir"
+                ;;
+esac
+
+SRCDIR=$srcdir
+export SRCDIR
+
+case "$basedir" in
+	/*)
+		;;
+	*)
+		basedir="../../$basedir"
+                ;;
+esac
+
+# Link all the files/directories in srcdir into our working directory,
+# so that the tests do not have to refer to srcdir to find test data.
+ln -s $srcdir/* .
+
+# Some tests refer to a ../testdata directory.
+if test -e $srcdir/../testdata; then
+  rm -f ../testdata
+  abssrcdir=`cd $srcdir && pwd`
+  ln -s $abssrcdir/../testdata ../testdata
+fi
+
+# Copy the .go files because io/utils_test.go expects a regular file.
+case "x$gofiles" in
+x)
+	case "x$pkgfiles" in
+	x)
+		for f in `cd $srcdir; ls *.go`; do
+		    rm -f $f;
+		    cp $srcdir/$f .
+		done
+		;;
+	*)
+		for f in $pkgfiles; do
+		    if test -f $basedir/$f; then
+			b=`basename $f`
+			rm -f $b
+			cp $basedir/$f $b
+		    elif test -f ../../$f; then
+			b=`basename $f`
+			rm -f $b
+			cp ../../$f $b
+		    else
+			echo "file $f not found" 1>&2
+			exit 1
+		    fi
+		done
+		for f in `cd $srcdir; ls *_test.go`; do
+		    rm -f $f
+		    cp $srcdir/$f .
+		done
+		;;
+	esac
+	;;
+*)
+	for f in $gofiles; do
+	    b=`basename $f`
+	    rm -f $b
+	    cp $basedir/$f $b
+	done
+	case "x$pkgfiles" in
+	x)
+		for f in `cd $srcdir; ls *.go | grep -v *_test.go`; do
+		    rm -f $f
+		    cp $srcdir/$f .
+		done
+		;;
+	*)
+		for f in $pkgfiles; do
+		    if test -f $basedir/$f; then
+			b=`basename $f`
+			rm -f $b
+			cp $basedir/$f $b
+		    elif test -f ../../$f; then
+			b=`basename $f`
+			rm -f $b
+			cp ../../$f $b
+		    else
+			echo "file $f not found" 1>&2
+			exit 1
+		    fi
+		done
+		;;
+	esac
+	;;
+esac
+
+# Some tests expect the _obj directory created by the gc Makefiles.
+mkdir _obj
+
+# Some tests expect the _test directory created by the gc Makefiles.
+mkdir _test
+
+case "x$gofiles" in
+x)
+	gofiles=`ls *_test.go 2>/dev/null`
+	;;
+*)
+	xgofiles=$gofiles
+	gofiles=
+	for f in $xgofiles; do
+	    gofiles="$gofiles `basename $f`"
+	done
+esac
+
+case "x$gofiles" in
+x)
+	echo 'no test files found' 1>&2
+	exit 1
+	;;
+esac
+
+# Run any commands given in sources, like
+#   // gotest: $GC foo.go
+# to build any test-only dependencies.
+holdGC="$GC"
+GC="$GC -g -c -I ."
+sed -n 's/^\/\/ gotest: //p' $gofiles | sh
+GC="$holdGC"
+
+case "x$pkgfiles" in
+x)
+	pkgbasefiles=`ls *.go | grep -v _test.go 2>/dev/null`
+	;;
+*)
+	for f in $pkgfiles; do
+	    pkgbasefiles="$pkgbasefiles `basename $f`"
+	done
+	;;
+esac
+
+case "x$pkgfiles" in
+x)
+	echo 'no source files found' 1>&2
+	exit 1
+	;;
+esac
+
+# Split $gofiles into external gofiles (those in *_test packages)
+# and internal ones (those in the main package).
+xgofiles=
+for f in $gofiles; do
+    package=`grep '^package[ 	]' $f | sed 1q`
+    case "$package" in
+    *_test)
+	xgofiles="$xgofiles $f"
+	;;
+    *)
+	ngofiles="$ngofiles $f"
+	;;
+    esac
+done
+gofiles=$ngofiles
+
+# External $O file
+xofile=""
+havex=false
+if [ "x$xgofiles" != "x" ]; then
+	xofile="_xtest_.o"
+	havex=true
+fi
+
+set -e
+
+package=`echo ${srcdir} | sed -e 's|^.*libgo/go/||'`
+
+pkgpatharg=
+xpkgpatharg=
+prefixarg=
+if test -n "$pkgpath"; then
+	pkgpatharg="-fgo-pkgpath=$pkgpath"
+	xpkgpatharg="-fgo-pkgpath=${pkgpath}_test"
+elif test -n "$prefix"; then
+	prefixarg="-fgo-prefix=$prefix"
+fi
+
+if test "$trace" = "true"; then
+  echo $GC -g $pkgpatharg $prefixarg -c -I . -fno-toplevel-reorder -o _gotest_.o $gofiles $pkgbasefiles
+fi
+$GC -g $pkgpatharg $prefixarg -c -I . -fno-toplevel-reorder -o _gotest_.o $gofiles $pkgbasefiles
+
+if $havex; then
+	mkdir -p `dirname $package`
+	cp _gotest_.o `dirname $package`/lib`basename $package`.a
+	if test "$trace" = "true"; then
+	    echo $GC -g $xpkgpatharg -c -I . -fno-toplevel-reorder -o $xofile $xgofiles
+	fi
+	$GC -g $xpkgpatharg -c -I . -fno-toplevel-reorder -o $xofile $xgofiles
+fi
+
+# They all compile; now generate the code to call them.
+
+testname() {
+	# Remove the package from the name used with the -test option.
+	echo $1 | sed 's/^.*\.//'
+}
+
+localname() {
+	# The package main has been renamed to __main__ when imported.
+	# Adjust its uses.
+	echo $1 | sed 's/^main\./__main__./'
+}
+
+{
+	text="T"
+	case "$GOARCH" in
+	ppc64) text="[TD]" ;;
+	esac
+
+	symtogo='sed -e s/_test/XXXtest/ -e s/.*_\([^_]*\.\)/\1/ -e s/XXXtest/_test/'
+
+	# test functions are named TestFoo
+	# the grep -v eliminates methods and other special names
+	# that have multiple dots.
+	pattern='Test([^a-z].*)?'
+	# The -p option tells GNU nm not to sort.
+	# The -v option tells Solaris nm to sort by value.
+	tests=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | grep -v '\..*\..*\.' | fgrep -v '$' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo)
+	if [ "x$tests" = x ]; then
+		echo 'gotest: warning: no tests matching '$pattern in _gotest_.o $xofile 1>&2
+		exit 2
+	fi
+	# benchmarks are named BenchmarkFoo.
+	pattern='Benchmark([^a-z].*)?'
+	benchmarks=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | grep -v '\..*\..*\.' | fgrep -v '$' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo)
+
+	# examples are named ExampleFoo
+	pattern='Example([^a-z].*)?'
+	examples=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | grep -v '\..*\..*\.' | fgrep -v '$' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo)
+
+	# package spec
+	echo 'package main'
+	echo
+	# imports
+	if echo "$tests" | egrep -v '_test\.' >/dev/null; then
+		echo 'import "./_gotest_"'
+	fi
+	if $havex; then
+		echo 'import "./_xtest_"'
+	fi
+	echo 'import "testing"'
+	echo 'import __regexp__ "regexp"' # rename in case tested package is called regexp
+	# test array
+	echo
+	echo 'var tests = []testing.InternalTest {'
+	for i in $tests
+	do
+		n=$(testname $i)
+		j=$(localname $i)
+		echo '	{"'$n'", '$j'},'
+	done
+	echo '}'
+
+	# benchmark array
+	# The comment makes the multiline declaration
+	# gofmt-safe even when there are no benchmarks.
+	echo 'var benchmarks = []testing.InternalBenchmark{ //'
+	for i in $benchmarks
+	do
+		n=$(testname $i)
+		j=$(localname $i)
+		echo '	{"'$n'", '$j'},'
+	done
+	echo '}'
+
+	# examples array
+	echo 'var examples = []testing.InternalExample{ //'
+	# This doesn't work because we don't pick up the output.
+	#for i in $examples
+	#do
+	#	n=$(testname $i)
+	#	j=$(localname $i)
+	#	echo '	{"'$n'", '$j', ""},'
+	#done
+	echo '}'
+
+	# body
+	echo \
+'
+var matchPat string
+var matchRe *__regexp__.Regexp
+
+func matchString(pat, str string) (result bool, err error) {
+	if matchRe == nil || matchPat != pat {
+		matchPat = pat
+		matchRe, err = __regexp__.Compile(matchPat)
+		if err != nil {
+			return
+		}
+	}
+	return matchRe.MatchString(str), nil
+}
+
+func main() {
+	testing.Main(matchString, tests, benchmarks, examples)
+}'
+}>_testmain.go
+
+case "x$dejagnu" in
+xno)
+	if test "$trace" = "true"; then
+	    echo ${GC} -g -c _testmain.go
+	fi
+	${GC} -g -c _testmain.go
+
+	if test "$trace" = "true"; then
+	    echo ${GL} *.o ${GOLIBS}
+	fi
+	${GL} *.o ${GOLIBS}
+
+	if test "$bench" = ""; then
+		if test "$trace" = "true"; then
+		    echo ./a.out -test.short -test.timeout=${timeout}s "$@"
+		fi
+		./a.out -test.short -test.timeout=${timeout}s "$@" &
+		pid=$!
+		(sleep `expr $timeout + 10`
+		    echo > gotest-timeout
+		    echo "timed out in gotest" 1>&2
+		    kill -9 $pid) &
+		alarmpid=$!
+		wait $pid
+		status=$?
+		if ! test -f gotest-timeout; then
+		    kill $alarmpid
+		fi
+	else
+		if test "$trace" = "true"; then
+		    echo ./a.out -test.run=^\$ -test.bench="${bench}" "$@"
+		fi
+		./a.out -test.run=^\$ -test.bench="${bench}" "$@"
+		status=$?
+	fi
+	exit $status
+	;;
+xyes)
+	rm -rf ../../testsuite/*.o
+	files=`echo *`
+	for f in $files; do
+		if test "$f" = "_obj" || test "$f" = "_test"; then
+			continue
+		fi
+		rm -rf ../../testsuite/$f
+		if test -f $f; then
+			cp $f ../../testsuite/
+		else
+			ln -s ../$DIR/test/$f ../../testsuite/
+		fi
+	done
+	cd ../../testsuite
+	rm -rf _obj _test
+	mkdir _obj _test
+	if test "$testname" != ""; then
+	    GOTESTNAME="$testname"
+	    export GOTESTNAME
+	fi
+	$MAKE check RUNTESTFLAGS="$RUNTESTFLAGS GOTEST_TMPDIR=$DIR/test"
+	# Useful when using make check-target-libgo
+	cat libgo.log >> libgo-all.log
+	cat libgo.sum >> libgo-all.sum
+	rm -rf $files
+	;;
+esac
diff --git a/third_party/gofrontend/ltmain.sh b/third_party/gofrontend/ltmain.sh
new file mode 100644
index 0000000..9503ec8
--- /dev/null
+++ b/third_party/gofrontend/ltmain.sh
@@ -0,0 +1,8636 @@
+# Generated from ltmain.m4sh.
+
+# libtool (GNU libtool 1.3134 2009-11-29) 2.2.7a
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
+# 2007, 2008, 2009 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname [OPTION]... [MODE-ARG]...
+#
+# Provide generalized library-building support services.
+#
+#       --config             show all configuration variables
+#       --debug              enable verbose shell tracing
+#   -n, --dry-run            display commands without modifying any files
+#       --features           display basic configuration information and exit
+#       --mode=MODE          use operation mode MODE
+#       --no-finish          let install mode avoid finish commands
+#       --preserve-dup-deps  don't remove duplicate dependency libraries
+#       --quiet, --silent    don't print informational messages
+#       --no-quiet, --no-silent
+#                            print informational messages (default)
+#       --tag=TAG            use configuration variables from tag TAG
+#   -v, --verbose            print more informational messages than default
+#       --no-verbose         don't print the extra informational messages
+#       --version            print version information
+#   -h, --help, --help-all   print short, long, or detailed help message
+#
+# MODE must be one of the following:
+#
+#         clean              remove files from the build directory
+#         compile            compile a source file into a libtool object
+#         execute            automatically set library path, then run a program
+#         finish             complete the installation of libtool libraries
+#         install            install libraries or executables
+#         link               create a library or an executable
+#         uninstall          remove libraries from an installed directory
+#
+# MODE-ARGS vary depending on the MODE.  When passed as first option,
+# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that.
+# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
+#
+# When reporting a bug, please describe a test case to reproduce it and
+# include the following information:
+#
+#         host-triplet:	$host
+#         shell:		$SHELL
+#         compiler:		$LTCC
+#         compiler flags:		$LTCFLAGS
+#         linker:		$LD (gnu? $with_gnu_ld)
+#         $progname:	(GNU libtool 1.3134 2009-11-29) 2.2.7a
+#         automake:	$automake_version
+#         autoconf:	$autoconf_version
+#
+# Report bugs to <bug-libtool@gnu.org>.
+
+PROGRAM=libtool
+PACKAGE=libtool
+VERSION=2.2.7a
+TIMESTAMP=" 1.3134 2009-11-29"
+package_revision=1.3134
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# NLS nuisances: We save the old values to restore during execute mode.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+lt_user_locale=
+lt_safe_locale=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+          save_$lt_var=\$$lt_var
+          $lt_var=C
+	  export $lt_var
+	  lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
+	  lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
+	fi"
+done
+
+$lt_unset CDPATH
+
+
+
+
+
+
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+
+
+: ${CP="cp -f"}
+: ${ECHO=$as_echo}
+: ${EGREP="/bin/grep -E"}
+: ${FGREP="/bin/grep -F"}
+: ${GREP="/bin/grep"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SED="/mount/endor/wildenhu/local-x86_64/bin/sed"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+: ${Xsed="$SED -e 1s/^X//"}
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77	  # $? = 77 is used to indicate a skipped test to automake.
+
+exit_status=$EXIT_SUCCESS
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" 	$lt_nl"
+
+dirname="s,/[^/]*$,,"
+basename="s,^.*/,,"
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+  func_basename_result=`$ECHO "${1}" | $SED -e "$basename"`
+}
+
+# Generated shell functions inserted here.
+
+# These SED scripts presuppose an absolute path with a trailing slash.
+pathcar='s,^/\([^/]*\).*$,\1,'
+pathcdr='s,^/[^/]*,,'
+removedotparts=':dotsl
+		s@/\./@/@g
+		t dotsl
+		s,/\.$,/,'
+collapseslashes='s@/\{1,\}@/@g'
+finalslash='s,/*$,/,'
+
+# func_normal_abspath PATH
+# Remove doubled-up and trailing slashes, "." path components,
+# and cancel out any ".." path components in PATH after making
+# it an absolute path.
+#             value returned in "$func_normal_abspath_result"
+func_normal_abspath ()
+{
+  # Start from root dir and reassemble the path.
+  func_normal_abspath_result=
+  func_normal_abspath_tpath=$1
+  func_normal_abspath_altnamespace=
+  case $func_normal_abspath_tpath in
+    "")
+      # Empty path, that just means $cwd.
+      func_stripname '' '/' "`pwd`"
+      func_normal_abspath_result=$func_stripname_result
+      return
+    ;;
+    # The next three entries are used to spot a run of precisely
+    # two leading slashes without using negated character classes;
+    # we take advantage of case's first-match behaviour.
+    ///*)
+      # Unusual form of absolute path, do nothing.
+    ;;
+    //*)
+      # Not necessarily an ordinary path; POSIX reserves leading '//'
+      # and for example Cygwin uses it to access remote file shares
+      # over CIFS/SMB, so we conserve a leading double slash if found.
+      func_normal_abspath_altnamespace=/
+    ;;
+    /*)
+      # Absolute path, do nothing.
+    ;;
+    *)
+      # Relative path, prepend $cwd.
+      func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
+    ;;
+  esac
+  # Cancel out all the simple stuff to save iterations.  We also want
+  # the path to end with a slash for ease of parsing, so make sure
+  # there is one (and only one) here.
+  func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"`
+  while :; do
+    # Processed it all yet?
+    if test "$func_normal_abspath_tpath" = / ; then
+      # If we ascended to the root using ".." the result may be empty now.
+      if test -z "$func_normal_abspath_result" ; then
+        func_normal_abspath_result=/
+      fi
+      break
+    fi
+    func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcar"`
+    func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcdr"`
+    # Figure out what to do with it
+    case $func_normal_abspath_tcomponent in
+      "")
+        # Trailing empty path component, ignore it.
+      ;;
+      ..)
+        # Parent dir; strip last assembled component from result.
+        func_dirname "$func_normal_abspath_result"
+        func_normal_abspath_result=$func_dirname_result
+      ;;
+      *)
+        # Actual path component, append it.
+        func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent
+      ;;
+    esac
+  done
+  # Restore leading double-slash if one was found on entry.
+  func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
+}
+
+# func_relative_path SRCDIR DSTDIR
+# generates a relative path from SRCDIR to DSTDIR, with a trailing
+# slash if non-empty, suitable for immediately appending a filename
+# without needing to append a separator.
+#             value returned in "$func_relative_path_result"
+func_relative_path ()
+{
+  func_relative_path_result=
+  func_normal_abspath "$1"
+  func_relative_path_tlibdir=$func_normal_abspath_result
+  func_normal_abspath "$2"
+  func_relative_path_tbindir=$func_normal_abspath_result
+
+  # Ascend the tree starting from libdir
+  while :; do
+    # check if we have found a prefix of bindir
+    case $func_relative_path_tbindir in
+      $func_relative_path_tlibdir)
+        # found an exact match
+        func_relative_path_tcancelled=
+        break
+        ;;
+      $func_relative_path_tlibdir*)
+        # found a matching prefix
+        func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
+        func_relative_path_tcancelled=$func_stripname_result
+        if test -z "$func_relative_path_result"; then
+          func_relative_path_result=.
+        fi
+        break
+        ;;
+      *)
+        func_dirname $func_relative_path_tlibdir
+        func_relative_path_tlibdir=${func_dirname_result}
+        if test "x$func_relative_path_tlibdir" = x ; then
+          # Have to descend all the way to the root!
+          func_relative_path_result=../$func_relative_path_result
+          func_relative_path_tcancelled=$func_relative_path_tbindir
+          break
+        fi
+        func_relative_path_result=../$func_relative_path_result
+        ;;
+    esac
+  done
+
+  # Now calculate path; take care to avoid doubling-up slashes.
+  func_stripname '' '/' "$func_relative_path_result"
+  func_relative_path_result=$func_stripname_result
+  func_stripname '/' '/' "$func_relative_path_tcancelled"
+  if test "x$func_stripname_result" != x ; then
+    func_relative_path_result=${func_relative_path_result}/${func_stripname_result}
+  fi
+
+  # Normalisation. If bindir is libdir, return empty string,
+  # else relative path ending with a slash; either way, target
+  # file name can be directly appended.
+  if test ! -z "$func_relative_path_result"; then
+    func_stripname './' '' "$func_relative_path_result/"
+    func_relative_path_result=$func_stripname_result
+  fi
+}
+
+# The name of this program:
+func_dirname_and_basename "$progpath"
+progname=$func_basename_result
+
+# Make sure we have an absolute path for reexecution:
+case $progpath in
+  [\\/]*|[A-Za-z]:\\*) ;;
+  *[\\/]*)
+     progdir=$func_dirname_result
+     progdir=`cd "$progdir" && pwd`
+     progpath="$progdir/$progname"
+     ;;
+  *)
+     save_IFS="$IFS"
+     IFS=:
+     for progdir in $PATH; do
+       IFS="$save_IFS"
+       test -x "$progdir/$progname" && break
+     done
+     IFS="$save_IFS"
+     test -n "$progdir" || progdir=`pwd`
+     progpath="$progdir/$progname"
+     ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Re-`\' parameter expansions in output of double_quote_subst that were
+# `\'-ed in input to the same.  If an odd number of `\' preceded a '$'
+# in input to double_quote_subst, that '$' was protected from expansion.
+# Since each input `\' is now two `\'s, look for any number of runs of
+# four `\'s followed by two `\'s and then a '$'.  `\' that '$'.
+bs='\\'
+bs2='\\\\'
+bs4='\\\\\\\\'
+dollar='\$'
+sed_double_backslash="\
+  s/$bs4/&\\
+/g
+  s/^$bs2$dollar/$bs&/
+  s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
+  s/\n//g"
+
+# Standard options:
+opt_dry_run=false
+opt_help=false
+opt_quiet=false
+opt_verbose=false
+opt_warning=:
+
+# func_echo arg...
+# Echo program name prefixed message, along with the current mode
+# name if it has been set yet.
+func_echo ()
+{
+    $ECHO "$progname${mode+: }$mode: $*"
+}
+
+# func_verbose arg...
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+    $opt_verbose && func_echo ${1+"$@"}
+
+    # A bug in bash halts the script if the last line of a function
+    # fails when set -e is in force, so we need another command to
+    # work around that:
+    :
+}
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*"
+}
+
+# func_error arg...
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+    $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2
+}
+
+# func_warning arg...
+# Echo program name prefixed warning message to standard error.
+func_warning ()
+{
+    $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2
+
+    # bash bug again:
+    :
+}
+
+# func_fatal_error arg...
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+    func_error ${1+"$@"}
+    exit $EXIT_FAILURE
+}
+
+# func_fatal_help arg...
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+    func_error ${1+"$@"}
+    func_fatal_error "$help"
+}
+help="Try \`$progname --help' for more information."  ## default
+
+
+# func_grep expression filename
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+    $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_mkdir_p directory-path
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+    my_directory_path="$1"
+    my_dir_list=
+
+    if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
+
+      # Protect directory names starting with `-'
+      case $my_directory_path in
+        -*) my_directory_path="./$my_directory_path" ;;
+      esac
+
+      # While some portion of DIR does not yet exist...
+      while test ! -d "$my_directory_path"; do
+        # ...make a list in topmost first order.  Use a colon delimited
+	# list incase some portion of path contains whitespace.
+        my_dir_list="$my_directory_path:$my_dir_list"
+
+        # If the last portion added has no slash in it, the list is done
+        case $my_directory_path in */*) ;; *) break ;; esac
+
+        # ...otherwise throw away the child directory and loop
+        my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"`
+      done
+      my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'`
+
+      save_mkdir_p_IFS="$IFS"; IFS=':'
+      for my_dir in $my_dir_list; do
+	IFS="$save_mkdir_p_IFS"
+        # mkdir can fail with a `File exist' error if two processes
+        # try to create one of the directories concurrently.  Don't
+        # stop in that case!
+        $MKDIR "$my_dir" 2>/dev/null || :
+      done
+      IFS="$save_mkdir_p_IFS"
+
+      # Bail out if we (or some other process) failed to create a directory.
+      test -d "$my_directory_path" || \
+        func_fatal_error "Failed to create \`$1'"
+    fi
+}
+
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$opt_dry_run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+        # Failing that, at least try and use $RANDOM to avoid a race
+        my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+        save_mktempdir_umask=`umask`
+        umask 0077
+        $MKDIR "$my_tmpdir"
+        umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || \
+        func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
+    fi
+
+    $ECHO "$my_tmpdir"
+}
+
+
+# func_quote_for_eval arg
+# Aesthetically quote ARG to be evaled later.
+# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
+# is double-quoted, suitable for a subsequent eval, whereas
+# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
+# which are still active within double quotes backslashified.
+func_quote_for_eval ()
+{
+    case $1 in
+      *[\\\`\"\$]*)
+	func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;;
+      *)
+        func_quote_for_eval_unquoted_result="$1" ;;
+    esac
+
+    case $func_quote_for_eval_unquoted_result in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting, command substitution and and variable
+      # expansion for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
+        ;;
+      *)
+        func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
+    esac
+}
+
+
+# func_quote_for_expand arg
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+    case $1 in
+      *[\\\`\"]*)
+	my_arg=`$ECHO "$1" | $SED \
+	    -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
+      *)
+        my_arg="$1" ;;
+    esac
+
+    case $my_arg in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting and command substitution for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        my_arg="\"$my_arg\""
+        ;;
+    esac
+
+    func_quote_for_expand_result="$my_arg"
+}
+
+
+# func_show_eval cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$my_cmd"
+      my_status=$?
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+# func_show_eval_locale cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.  Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$lt_user_locale
+	    $my_cmd"
+      my_status=$?
+      eval "$lt_safe_locale"
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+
+
+
+# func_version
+# Echo version message to standard output and exit.
+func_version ()
+{
+    $SED -n '/(C)/!b go
+	:more
+	/\./!{
+	  N
+	  s/\n# //
+	  b more
+	}
+	:go
+	/^# '$PROGRAM' (GNU /,/# warranty; / {
+        s/^# //
+	s/^# *$//
+        s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
+        p
+     }' < "$progpath"
+     exit $?
+}
+
+# func_usage
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+    $SED -n '/^# Usage:/,/^#  *-h/ {
+        s/^# //
+	s/^# *$//
+	s/\$progname/'$progname'/
+	p
+    }' < "$progpath"
+    echo
+    $ECHO "run \`$progname --help | more' for full usage"
+    exit $?
+}
+
+# func_help [NOEXIT]
+# Echo long help message to standard output and exit,
+# unless 'noexit' is passed as argument.
+func_help ()
+{
+    $SED -n '/^# Usage:/,/# Report bugs to/ {
+        s/^# //
+	s/^# *$//
+	s*\$progname*'$progname'*
+	s*\$host*'"$host"'*
+	s*\$SHELL*'"$SHELL"'*
+	s*\$LTCC*'"$LTCC"'*
+	s*\$LTCFLAGS*'"$LTCFLAGS"'*
+	s*\$LD*'"$LD"'*
+	s/\$with_gnu_ld/'"$with_gnu_ld"'/
+	s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/
+	s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/
+	p
+     }' < "$progpath"
+    ret=$?
+    if test -z "$1"; then
+      exit $ret
+    fi
+}
+
+# func_missing_arg argname
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+    func_error "missing argument for $1"
+    exit_cmd=exit
+}
+
+exit_cmd=:
+
+
+
+
+
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+# $mode is unset
+nonopt=
+execute_dlfiles=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+opt_dry_run=false
+opt_finish=:
+opt_duplicate_deps=false
+opt_silent=false
+opt_debug=:
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+# func_fatal_configuration arg...
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+    func_error ${1+"$@"}
+    func_error "See the $PACKAGE documentation for more information."
+    func_fatal_error "Fatal configuration error."
+}
+
+
+# func_config
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+    re_begincf='^# ### BEGIN LIBTOOL'
+    re_endcf='^# ### END LIBTOOL'
+
+    # Default configuration.
+    $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+    done
+
+    exit $?
+}
+
+# func_features
+# Display the features supported by this script.
+func_features ()
+{
+    echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      echo "enable shared libraries"
+    else
+      echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      echo "enable static libraries"
+    else
+      echo "disable static libraries"
+    fi
+
+    exit $?
+}
+
+# func_enable_tag tagname
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+  # Global variable:
+  tagname="$1"
+
+  re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+  re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+  sed_extractcf="/$re_begincf/,/$re_endcf/p"
+
+  # Validate tagname.
+  case $tagname in
+    *[!-_A-Za-z0-9,/]*)
+      func_fatal_error "invalid tag name: $tagname"
+      ;;
+  esac
+
+  # Don't test for the "default" C tag, as we know it's
+  # there but not specially marked.
+  case $tagname in
+    CC) ;;
+    *)
+      if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+	taglist="$taglist $tagname"
+
+	# Evaluate the configuration.  Be careful to quote the path
+	# and the sed script, to avoid splitting on whitespace, but
+	# also don't use non-portable quotes within backquotes within
+	# quotes we have to do it in 2 steps:
+	extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+	eval "$extractedcf"
+      else
+	func_error "ignoring unknown tag $tagname"
+      fi
+      ;;
+  esac
+}
+
+# Parse options once, thoroughly.  This comes as soon as possible in
+# the script to make things like `libtool --version' happen quickly.
+{
+
+  # Shorthand for --mode=foo, only valid as the first argument
+  case $1 in
+  clean|clea|cle|cl)
+    shift; set dummy --mode clean ${1+"$@"}; shift
+    ;;
+  compile|compil|compi|comp|com|co|c)
+    shift; set dummy --mode compile ${1+"$@"}; shift
+    ;;
+  execute|execut|execu|exec|exe|ex|e)
+    shift; set dummy --mode execute ${1+"$@"}; shift
+    ;;
+  finish|finis|fini|fin|fi|f)
+    shift; set dummy --mode finish ${1+"$@"}; shift
+    ;;
+  install|instal|insta|inst|ins|in|i)
+    shift; set dummy --mode install ${1+"$@"}; shift
+    ;;
+  link|lin|li|l)
+    shift; set dummy --mode link ${1+"$@"}; shift
+    ;;
+  uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+    shift; set dummy --mode uninstall ${1+"$@"}; shift
+    ;;
+  esac
+
+  # Parse non-mode specific arguments:
+  while test "$#" -gt 0; do
+    opt="$1"
+    shift
+
+    case $opt in
+      --config)		func_config					;;
+
+      --debug)		preserve_args="$preserve_args $opt"
+			func_echo "enabling shell trace mode"
+			opt_debug='set -x'
+			$opt_debug
+			;;
+
+      -dlopen)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			execute_dlfiles="$execute_dlfiles $1"
+			shift
+			;;
+
+      --dry-run | -n)	opt_dry_run=:					;;
+      --features)       func_features					;;
+      --finish)		mode="finish"					;;
+      --no-finish)	opt_finish=false				;;
+
+      --mode)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			case $1 in
+			  # Valid mode arguments:
+			  clean)	;;
+			  compile)	;;
+			  execute)	;;
+			  finish)	;;
+			  install)	;;
+			  link)		;;
+			  relink)	;;
+			  uninstall)	;;
+
+			  # Catch anything else as an error
+			  *) func_error "invalid argument for $opt"
+			     exit_cmd=exit
+			     break
+			     ;;
+		        esac
+
+			mode="$1"
+			shift
+			;;
+
+      --preserve-dup-deps)
+			opt_duplicate_deps=:				;;
+
+      --quiet|--silent)	preserve_args="$preserve_args $opt"
+			opt_silent=:
+			opt_verbose=false
+			;;
+
+      --no-quiet|--no-silent)
+			preserve_args="$preserve_args $opt"
+			opt_silent=false
+			;;
+
+      --verbose| -v)	preserve_args="$preserve_args $opt"
+			opt_silent=false
+			opt_verbose=:
+			;;
+
+      --no-verbose)	preserve_args="$preserve_args $opt"
+			opt_verbose=false
+			;;
+
+      --tag)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			preserve_args="$preserve_args $opt $1"
+			func_enable_tag "$1"	# tagname is set here
+			shift
+			;;
+
+      # Separate optargs to long options:
+      -dlopen=*|--mode=*|--tag=*)
+			func_opt_split "$opt"
+			set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"}
+			shift
+			;;
+
+      -\?|-h)		func_usage					;;
+      --help)		opt_help=:					;;
+      --help-all)	opt_help=': help-all'				;;
+      --version)	func_version					;;
+
+      -*)		func_fatal_help "unrecognized option \`$opt'"	;;
+
+      *)		nonopt="$opt"
+			break
+			;;
+    esac
+  done
+
+
+  case $host in
+    *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* )
+      # don't eliminate duplications in $postdeps and $predeps
+      opt_duplicate_compiler_generated_deps=:
+      ;;
+    *)
+      opt_duplicate_compiler_generated_deps=$opt_duplicate_deps
+      ;;
+  esac
+
+  # Having warned about all mis-specified options, bail out if
+  # anything was wrong.
+  $exit_cmd $EXIT_FAILURE
+}
+
+# func_check_version_match
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+  if test "$package_revision" != "$macro_revision"; then
+    if test "$VERSION" != "$macro_version"; then
+      if test -z "$macro_version"; then
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      else
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      fi
+    else
+      cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+    fi
+
+    exit $EXIT_MISMATCH
+  fi
+}
+
+
+## ----------- ##
+##    Main.    ##
+## ----------- ##
+
+$opt_help || {
+  # Sanity checks first:
+  func_check_version_match
+
+  if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+    func_fatal_configuration "not configured to build any kind of library"
+  fi
+
+  test -z "$mode" && func_fatal_error "error: you must specify a MODE."
+
+
+  # Darwin sucks
+  eval "std_shrext=\"$shrext_cmds\""
+
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    func_error "unrecognized option \`-dlopen'"
+    $ECHO "$help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$progname --help --mode=$mode' for more information."
+}
+
+
+# func_lalib_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+    test -f "$1" &&
+      $SED -e 4q "$1" 2>/dev/null \
+        | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs.  To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway.  Works if `file' does not exist.
+func_lalib_unsafe_p ()
+{
+    lalib_p=no
+    if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+	for lalib_p_l in 1 2 3 4
+	do
+	    read lalib_p_line
+	    case "$lalib_p_line" in
+		\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+	    esac
+	done
+	exec 0<&5 5<&-
+    fi
+    test "$lalib_p" = yes
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+    func_lalib_p "$1"
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+    func_ltwrapper_exec_suffix=
+    case $1 in
+    *.exe) ;;
+    *) func_ltwrapper_exec_suffix=.exe ;;
+    esac
+    $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+    func_ltwrapper_scriptname_result=""
+    if func_ltwrapper_executable_p "$1"; then
+	func_dirname_and_basename "$1" "" "."
+	func_stripname '' '.exe' "$func_basename_result"
+	func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
+    fi
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+    func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+    $opt_debug
+    save_ifs=$IFS; IFS='~'
+    for cmd in $1; do
+      IFS=$save_ifs
+      eval "cmd=\"$cmd\""
+      func_show_eval "$cmd" "${2-:}"
+    done
+    IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)!  Also, sourcing
+# `FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+    $opt_debug
+    case $1 in
+    */* | *\\*)	. "$1" ;;
+    *)		. "./$1" ;;
+    esac
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    $opt_debug
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+        func_quote_for_eval "$arg"
+	CC_quoted="$CC_quoted $func_quote_for_eval_result"
+      done
+      CC_expanded=`func_echo_all $CC`
+      CC_quoted_expanded=`func_echo_all $CC_quoted`
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+      " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+	    CC_quoted=
+	    for arg in $CC; do
+	      # Double-quote args containing other shell metacharacters.
+	      func_quote_for_eval "$arg"
+	      CC_quoted="$CC_quoted $func_quote_for_eval_result"
+	    done
+	    CC_expanded=`func_echo_all $CC`
+	    CC_quoted_expanded=`func_echo_all $CC_quoted`
+	    case "$@ " in
+	    " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+	    " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
+	      # The compiler in the base compile command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  func_echo "unable to infer tagged configuration"
+	  func_fatal_error "specify a tag with \`--tag'"
+#	else
+#	  func_verbose "using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+    write_libobj=${1}
+    if test "$build_libtool_libs" = yes; then
+      write_lobj=\'${2}\'
+    else
+      write_lobj=none
+    fi
+
+    if test "$build_old_libs" = yes; then
+      write_oldobj=\'${3}\'
+    else
+      write_oldobj=none
+    fi
+
+    $opt_dry_run || {
+      cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "${write_libobj}"
+    }
+}
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+    $opt_debug
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+    pie_flag=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+	# do not "continue".  Instead, add this to base_compile
+	lastarg="$arg"
+	arg_mode=normal
+	;;
+
+      target )
+	libobj="$arg"
+	arg_mode=normal
+	continue
+	;;
+
+      normal )
+	# Accept any command-line options.
+	case $arg in
+	-o)
+	  test -n "$libobj" && \
+	    func_fatal_error "you cannot specify \`-o' more than once"
+	  arg_mode=target
+	  continue
+	  ;;
+
+	-pie | -fpie | -fPIE)
+          pie_flag="$pie_flag $arg"
+	  continue
+	  ;;
+
+	-shared | -static | -prefer-pic | -prefer-non-pic)
+	  later="$later $arg"
+	  continue
+	  ;;
+
+	-no-suppress)
+	  suppress_opt=no
+	  continue
+	  ;;
+
+	-Xcompiler)
+	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
+	  continue      #  The current "srcfile" will either be retained or
+	  ;;            #  replaced later.  I would guess that would be a bug.
+
+	-Wc,*)
+	  func_stripname '-Wc,' '' "$arg"
+	  args=$func_stripname_result
+	  lastarg=
+	  save_ifs="$IFS"; IFS=','
+	  for arg in $args; do
+	    IFS="$save_ifs"
+	    func_quote_for_eval "$arg"
+	    lastarg="$lastarg $func_quote_for_eval_result"
+	  done
+	  IFS="$save_ifs"
+	  func_stripname ' ' '' "$lastarg"
+	  lastarg=$func_stripname_result
+
+	  # Add the arguments to base_compile.
+	  base_compile="$base_compile $lastarg"
+	  continue
+	  ;;
+
+	*)
+	  # Accept the current argument as the source file.
+	  # The previous "srcfile" becomes the current argument.
+	  #
+	  lastarg="$srcfile"
+	  srcfile="$arg"
+	  ;;
+	esac  #  case $arg
+	;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      func_quote_for_eval "$lastarg"
+      base_compile="$base_compile $func_quote_for_eval_result"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      func_fatal_error "you must specify an argument for -Xcompile"
+      ;;
+    target)
+      func_fatal_error "you must specify a target with \`-o'"
+      ;;
+    *)
+      # Get the name of the library object.
+      test -z "$libobj" && {
+	func_basename "$srcfile"
+	libobj="$func_basename_result"
+      }
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    case $libobj in
+    *.[cCFSifmso] | \
+    *.ada | *.adb | *.ads | *.asm | \
+    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+    *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup)
+      func_xform "$libobj"
+      libobj=$func_xform_result
+      ;;
+    esac
+
+    case $libobj in
+    *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+    *)
+      func_fatal_error "cannot determine name of library object from \`$libobj'"
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	continue
+	;;
+
+      -static)
+	build_libtool_libs=no
+	build_old_libs=yes
+	continue
+	;;
+
+      -prefer-pic)
+	pic_mode=yes
+	continue
+	;;
+
+      -prefer-non-pic)
+	pic_mode=no
+	continue
+	;;
+      esac
+    done
+
+    func_quote_for_eval "$libobj"
+    test "X$libobj" != "X$func_quote_for_eval_result" \
+      && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
+      && func_warning "libobj name \`$libobj' may not contain shell special characters."
+    func_dirname_and_basename "$obj" "/" ""
+    objname="$func_basename_result"
+    xdir="$func_dirname_result"
+    lobj=${xdir}$objdir/$objname
+
+    test -z "$base_compile" && \
+      func_fatal_help "you must specify a compilation command"
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2* | cegcc*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+	$ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+      removelist="$removelist $output_obj"
+      $ECHO "$srcfile" > "$lockfile"
+    fi
+
+    $opt_dry_run || $RM $removelist
+    removelist="$removelist $lockfile"
+    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+    if test -n "$fix_srcfile_path"; then
+      eval "srcfile=\"$fix_srcfile_path\""
+    fi
+    func_quote_for_eval "$srcfile"
+    qsrcfile=$func_quote_for_eval_result
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+	command="$base_compile $qsrcfile $pic_flag"
+      else
+	# Don't build PIC code
+	command="$base_compile $qsrcfile"
+      fi
+
+      func_mkdir_p "$xdir$objdir"
+
+      if test -z "$output_obj"; then
+	# Place PIC objects in $objdir
+	command="$command -o $lobj"
+      fi
+
+      func_show_eval_locale "$command"	\
+          'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+	func_show_eval '$MV "$output_obj" "$lobj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+	suppress_output=' >/dev/null 2>&1'
+      fi
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+	# Don't build PIC code
+	command="$base_compile $qsrcfile$pie_flag"
+      else
+	command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+	command="$command -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      func_show_eval_locale "$command" \
+        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+	func_show_eval '$MV "$output_obj" "$obj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+    fi
+
+    $opt_dry_run || {
+      func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+      # Unlock the critical section if it was locked
+      if test "$need_locks" != no; then
+	removelist=$lockfile
+        $RM "$lockfile"
+      fi
+    }
+
+    exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+  test "$mode" = compile && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+    # We need to display help for each of the modes.
+    case $mode in
+      "")
+        # Generic help is extracted from the usage comments
+        # at the start of this file.
+        func_help
+        ;;
+
+      clean)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      compile)
+      $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -no-suppress      do not suppress compiler output for multiple passes
+  -prefer-pic       try to building PIC objects only
+  -prefer-non-pic   try to building non-PIC objects only
+  -shared           do not build a \`.o' file suitable for static linking
+  -static           only build a \`.o' file suitable for static linking
+  -Wc,FLAG          pass FLAG directly to the compiler
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+        ;;
+
+      execute)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+        ;;
+
+      finish)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+        ;;
+
+      install)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+  -inst-prefix-dir PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+        ;;
+
+      link)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -bindir BINDIR    specify path to binaries directory (for systems where
+                    libraries must be found in the PATH setting at runtime)
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -shared           only do dynamic linking of libtool libraries
+  -shrext SUFFIX    override the standard shared library file extension
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+  -weak LIBNAME     declare that the target provides the LIBNAME interface
+  -Wc,FLAG
+  -Xcompiler FLAG   pass linker-specific FLAG directly to the compiler
+  -Wl,FLAG
+  -Xlinker FLAG     pass linker-specific FLAG directly to the linker
+  -XCClinker FLAG   pass link-specific FLAG to the compiler driver (CC)
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+        ;;
+
+      uninstall)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      *)
+        func_fatal_help "invalid operation mode \`$mode'"
+        ;;
+    esac
+
+    echo
+    $ECHO "Try \`$progname --help' for more information about other modes."
+}
+
+# Now that we've collected a possible --mode arg, show help if necessary
+if $opt_help; then
+  if test "$opt_help" = :; then
+    func_mode_help
+  else
+    {
+      func_help noexit
+      for mode in compile link execute install finish uninstall clean; do
+	func_mode_help
+      done
+    } | sed -n '1p; 2,$s/^Usage:/  or: /p'
+    {
+      func_help noexit
+      for mode in compile link execute install finish uninstall clean; do
+	echo
+	func_mode_help
+      done
+    } |
+    sed '1d
+      /^When reporting/,/^Report/{
+	H
+	d
+      }
+      $x
+      /information about other modes/d
+      /more detailed .*MODE/d
+      s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
+  fi
+  exit $?
+fi
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+    $opt_debug
+    # The first argument is the command name.
+    cmd="$nonopt"
+    test -z "$cmd" && \
+      func_fatal_help "you must specify a COMMAND"
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      test -f "$file" \
+	|| func_fatal_help "\`$file' is not a file"
+
+      dir=
+      case $file in
+      *.la)
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$lib' is not a valid libtool archive"
+
+	# Read the libtool library.
+	dlname=
+	library_names=
+	func_source "$file"
+
+	# Skip this library if it cannot be dlopened.
+	if test -z "$dlname"; then
+	  # Warn if it was a shared library.
+	  test -n "$library_names" && \
+	    func_warning "\`$file' was not linked with \`-export-dynamic'"
+	  continue
+	fi
+
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+
+	if test -f "$dir/$objdir/$dlname"; then
+	  dir="$dir/$objdir"
+	else
+	  if test ! -f "$dir/$dlname"; then
+	    func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
+	  fi
+	fi
+	;;
+
+      *.lo)
+	# Just add the directory containing the .lo file.
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+	;;
+
+      *)
+	func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
+	continue
+	;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval test -z \"\$$shlibpath_var\"; then
+	eval $shlibpath_var=\$dir
+      else
+	eval $shlibpath_var=\$dir:\$$shlibpath_var
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -* | *.la | *.lo ) ;;
+      *)
+	# Do a test to see if this is really a libtool program.
+	if func_ltwrapper_script_p "$file"; then
+	  func_source "$file"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	elif func_ltwrapper_executable_p "$file"; then
+	  func_ltwrapper_scriptname "$file"
+	  func_source "$func_ltwrapper_scriptname_result"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	fi
+	;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      func_quote_for_eval "$file"
+      args="$args $func_quote_for_eval_result"
+    done
+
+    if test "X$opt_dry_run" = Xfalse; then
+      if test -n "$shlibpath_var"; then
+	# Export the shlibpath_var.
+	eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+	eval "if test \"\${save_$lt_var+set}\" = set; then
+                $lt_var=\$save_$lt_var; export $lt_var
+	      else
+		$lt_unset $lt_var
+	      fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+	eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+	echo "export $shlibpath_var"
+      fi
+      $ECHO "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$mode" = execute && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+    $opt_debug
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+	libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+	if test -n "$finish_cmds"; then
+	  # Do each command in the finish commands.
+	  func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+	fi
+	if test -n "$finish_eval"; then
+	  # Do the single finish_eval.
+	  eval cmds=\"$finish_eval\"
+	  $opt_dry_run || eval "$cmds" || admincmds="$admincmds
+       $cmds"
+	fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    $opt_silent && exit $EXIT_SUCCESS
+
+    echo "----------------------------------------------------------------------"
+    echo "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      $ECHO "   $libdir"
+    done
+    echo
+    echo "If you ever happen to want to link against installed libraries"
+    echo "in a given directory, LIBDIR, you must either use libtool, and"
+    echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    echo "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      echo "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+      echo "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval "flag=\"$hardcode_libdir_flag_spec\""
+
+      $ECHO "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      $ECHO "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    echo
+
+    echo "See any operating system documentation about shared libraries for"
+    case $host in
+      solaris2.[6789]|solaris2.1[0-9])
+        echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+	echo "pages."
+	;;
+      *)
+        echo "more information, such as the ld(1) and ld.so(8) manual pages."
+        ;;
+    esac
+    echo "----------------------------------------------------------------------"
+    exit $EXIT_SUCCESS
+}
+
+test "$mode" = finish && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+    $opt_debug
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       case $nonopt in *shtool*) :;; *) false;; esac; then
+      # Aesthetically quote it.
+      func_quote_for_eval "$nonopt"
+      install_prog="$func_quote_for_eval_result "
+      arg=$1
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    func_quote_for_eval "$arg"
+    install_prog="$install_prog$func_quote_for_eval_result"
+    install_shared_prog=$install_prog
+    case " $install_prog " in
+      *[\\\ /]cp\ *) install_cp=: ;;
+      *) install_cp=false ;;
+    esac
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    no_mode=:
+    for arg
+    do
+      arg2=
+      if test -n "$dest"; then
+	files="$files $dest"
+	dest=$arg
+	continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f)
+	if $install_cp; then :; else
+	  prev=$arg
+	fi
+	;;
+      -g | -m | -o)
+	prev=$arg
+	;;
+      -s)
+	stripme=" -s"
+	continue
+	;;
+      -*)
+	;;
+      *)
+	# If the previous option needed an argument, then skip it.
+	if test -n "$prev"; then
+	  if test "x$prev" = x-m && test -n "$install_override_mode"; then
+	    arg2=$install_override_mode
+	    no_mode=false
+	  fi
+	  prev=
+	else
+	  dest=$arg
+	  continue
+	fi
+	;;
+      esac
+
+      # Aesthetically quote the argument.
+      func_quote_for_eval "$arg"
+      install_prog="$install_prog $func_quote_for_eval_result"
+      if test -n "$arg2"; then
+	func_quote_for_eval "$arg2"
+      fi
+      install_shared_prog="$install_shared_prog $func_quote_for_eval_result"
+    done
+
+    test -z "$install_prog" && \
+      func_fatal_help "you must specify an install program"
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prev' option requires an argument"
+
+    if test -n "$install_override_mode" && $no_mode; then
+      if $install_cp; then :; else
+	func_quote_for_eval "$install_override_mode"
+	install_shared_prog="$install_shared_prog -m $func_quote_for_eval_result"
+      fi
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+	func_fatal_help "no file or destination specified"
+      else
+	func_fatal_help "you must specify a destination"
+      fi
+    fi
+
+    # Strip any trailing slash from the destination.
+    func_stripname '' '/' "$dest"
+    dest=$func_stripname_result
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      func_dirname_and_basename "$dest" "" "."
+      destdir="$func_dirname_result"
+      destname="$func_basename_result"
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files; shift
+      test "$#" -gt 1 && \
+	func_fatal_help "\`$dest' is not a directory"
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+	case $file in
+	*.lo) ;;
+	*)
+	  func_fatal_help "\`$destdir' must be an absolute directory name"
+	  ;;
+	esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+	# Do the static libraries later.
+	staticlibs="$staticlibs $file"
+	;;
+
+      *.la)
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$file' is not a valid libtool archive"
+
+	library_names=
+	old_library=
+	relink_command=
+	func_source "$file"
+
+	# Add the libdir to current_libdirs if it is the destination.
+	if test "X$destdir" = "X$libdir"; then
+	  case "$current_libdirs " in
+	  *" $libdir "*) ;;
+	  *) current_libdirs="$current_libdirs $libdir" ;;
+	  esac
+	else
+	  # Note the libdir as a future libdir.
+	  case "$future_libdirs " in
+	  *" $libdir "*) ;;
+	  *) future_libdirs="$future_libdirs $libdir" ;;
+	  esac
+	fi
+
+	func_dirname "$file" "/" ""
+	dir="$func_dirname_result"
+	dir="$dir$objdir"
+
+	if test -n "$relink_command"; then
+	  # Determine the prefix the user has applied to our future dir.
+	  inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
+
+	  # Don't allow the user to place us outside of our expected
+	  # location b/c this prevents finding dependent libraries that
+	  # are installed to the same prefix.
+	  # At present, this check doesn't affect windows .dll's that
+	  # are installed into $libdir/../bin (currently, that works fine)
+	  # but it's something to keep an eye on.
+	  test "$inst_prefix_dir" = "$destdir" && \
+	    func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+	  if test -n "$inst_prefix_dir"; then
+	    # Stick the inst_prefix_dir data into the link command.
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	  else
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+	  fi
+
+	  func_warning "relinking \`$file'"
+	  func_show_eval "$relink_command" \
+	    'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+	fi
+
+	# See the names of the shared library.
+	set dummy $library_names; shift
+	if test -n "$1"; then
+	  realname="$1"
+	  shift
+
+	  srcname="$realname"
+	  test -n "$relink_command" && srcname="$realname"T
+
+	  # Install the shared library and build the symlinks.
+	  func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
+	      'exit $?'
+	  tstripme="$stripme"
+	  case $host_os in
+	  cygwin* | mingw* | pw32* | cegcc*)
+	    case $realname in
+	    *.dll.a)
+	      tstripme=""
+	      ;;
+	    esac
+	    ;;
+	  esac
+	  if test -n "$tstripme" && test -n "$striplib"; then
+	    func_show_eval "$striplib $destdir/$realname" 'exit $?'
+	  fi
+
+	  if test "$#" -gt 0; then
+	    # Delete the old symlinks, and create new ones.
+	    # Try `ln -sf' first, because the `ln' binary might depend on
+	    # the symlink we replace!  Solaris /bin/ln does not understand -f,
+	    # so we also need to try rm && ln -s.
+	    for linkname
+	    do
+	      test "$linkname" != "$realname" \
+		&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+	    done
+	  fi
+
+	  # Do each command in the postinstall commands.
+	  lib="$destdir/$realname"
+	  func_execute_cmds "$postinstall_cmds" 'exit $?'
+	fi
+
+	# Install the pseudo-library for information purposes.
+	func_basename "$file"
+	name="$func_basename_result"
+	instname="$dir/$name"i
+	func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+	# Maybe install the static library, too.
+	test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+	;;
+
+      *.lo)
+	# Install (i.e. copy) a libtool object.
+
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# Deduce the name of the destination old-style object file.
+	case $destfile in
+	*.lo)
+	  func_lo2o "$destfile"
+	  staticdest=$func_lo2o_result
+	  ;;
+	*.$objext)
+	  staticdest="$destfile"
+	  destfile=
+	  ;;
+	*)
+	  func_fatal_help "cannot copy a libtool object to \`$destfile'"
+	  ;;
+	esac
+
+	# Install the libtool object if requested.
+	test -n "$destfile" && \
+	  func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+	# Install the old object if enabled.
+	if test "$build_old_libs" = yes; then
+	  # Deduce the name of the old-style object file.
+	  func_lo2o "$file"
+	  staticobj=$func_lo2o_result
+	  func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+	fi
+	exit $EXIT_SUCCESS
+	;;
+
+      *)
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# If the file is missing, and there is a .exe on the end, strip it
+	# because it is most likely a libtool script we actually want to
+	# install
+	stripped_ext=""
+	case $file in
+	  *.exe)
+	    if test ! -f "$file"; then
+	      func_stripname '' '.exe' "$file"
+	      file=$func_stripname_result
+	      stripped_ext=".exe"
+	    fi
+	    ;;
+	esac
+
+	# Do a test to see if this is really a libtool program.
+	case $host in
+	*cygwin* | *mingw*)
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      wrapper=$func_ltwrapper_scriptname_result
+	    else
+	      func_stripname '' '.exe' "$file"
+	      wrapper=$func_stripname_result
+	    fi
+	    ;;
+	*)
+	    wrapper=$file
+	    ;;
+	esac
+	if func_ltwrapper_script_p "$wrapper"; then
+	  notinst_deplibs=
+	  relink_command=
+
+	  func_source "$wrapper"
+
+	  # Check the variables that should have been set.
+	  test -z "$generated_by_libtool_version" && \
+	    func_fatal_error "invalid libtool wrapper script \`$wrapper'"
+
+	  finalize=yes
+	  for lib in $notinst_deplibs; do
+	    # Check to see that each library is installed.
+	    libdir=
+	    if test -f "$lib"; then
+	      func_source "$lib"
+	    fi
+	    libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test
+	    if test -n "$libdir" && test ! -f "$libfile"; then
+	      func_warning "\`$lib' has not been installed in \`$libdir'"
+	      finalize=no
+	    fi
+	  done
+
+	  relink_command=
+	  func_source "$wrapper"
+
+	  outputname=
+	  if test "$fast_install" = no && test -n "$relink_command"; then
+	    $opt_dry_run || {
+	      if test "$finalize" = yes; then
+	        tmpdir=`func_mktempdir`
+		func_basename "$file$stripped_ext"
+		file="$func_basename_result"
+	        outputname="$tmpdir/$file"
+	        # Replace the output file specification.
+	        relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
+
+	        $opt_silent || {
+	          func_quote_for_expand "$relink_command"
+		  eval "func_echo $func_quote_for_expand_result"
+	        }
+	        if eval "$relink_command"; then :
+	          else
+		  func_error "error: relink \`$file' with the above command before installing it"
+		  $opt_dry_run || ${RM}r "$tmpdir"
+		  continue
+	        fi
+	        file="$outputname"
+	      else
+	        func_warning "cannot relink \`$file'"
+	      fi
+	    }
+	  else
+	    # Install the binary that we compiled earlier.
+	    file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
+	  fi
+	fi
+
+	# remove .exe since cygwin /usr/bin/install will append another
+	# one anyway
+	case $install_prog,$host in
+	*/usr/bin/install*,*cygwin*)
+	  case $file:$destfile in
+	  *.exe:*.exe)
+	    # this is ok
+	    ;;
+	  *.exe:*)
+	    destfile=$destfile.exe
+	    ;;
+	  *:*.exe)
+	    func_stripname '' '.exe' "$destfile"
+	    destfile=$func_stripname_result
+	    ;;
+	  esac
+	  ;;
+	esac
+	func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+	$opt_dry_run || if test -n "$outputname"; then
+	  ${RM}r "$tmpdir"
+	fi
+	;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      func_basename "$file"
+      name="$func_basename_result"
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+	func_show_eval "$old_striplib $oldlib" 'exit $?'
+      fi
+
+      # Do each command in the postinstall commands.
+      func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+    done
+
+    test -n "$future_libdirs" && \
+      func_warning "remember to run \`$progname --finish$future_libdirs'"
+
+    if test -n "$current_libdirs" && $opt_finish; then
+      # Maybe just do a dry run.
+      $opt_dry_run && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$mode" = install && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+    $opt_debug
+    my_outputname="$1"
+    my_originator="$2"
+    my_pic_p="${3-no}"
+    my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
+    my_dlsyms=
+
+    if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+      if test -n "$NM" && test -n "$global_symbol_pipe"; then
+	my_dlsyms="${my_outputname}S.c"
+      else
+	func_error "not configured to extract global symbols from dlpreopened files"
+      fi
+    fi
+
+    if test -n "$my_dlsyms"; then
+      case $my_dlsyms in
+      "") ;;
+      *.c)
+	# Discover the nlist of each of the dlfiles.
+	nlist="$output_objdir/${my_outputname}.nm"
+
+	func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+	# Parse the name list into a source file.
+	func_verbose "creating $output_objdir/$my_dlsyms"
+
+	$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#endif
+
+/* External symbol declarations for the compiler. */\
+"
+
+	if test "$dlself" = yes; then
+	  func_verbose "generating symbol list for \`$output'"
+
+	  $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+	  # Add our own program objects to the symbol list.
+	  progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	  for progfile in $progfiles; do
+	    func_verbose "extracting global C symbols from \`$progfile'"
+	    $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'"
+	  done
+
+	  if test -n "$exclude_expsyms"; then
+	    $opt_dry_run || {
+	      $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	      $MV "$nlist"T "$nlist"
+	    }
+	  fi
+
+	  if test -n "$export_symbols_regex"; then
+	    $opt_dry_run || {
+	      $EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T
+	      $MV "$nlist"T "$nlist"
+	    }
+	  fi
+
+	  # Prepare the list of exported symbols
+	  if test -z "$export_symbols"; then
+	    export_symbols="$output_objdir/$outputname.exp"
+	    $opt_dry_run || {
+	      $RM $export_symbols
+	      ${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' < "$nlist" > "$export_symbols"
+	      case $host in
+	      *cygwin* | *mingw* | *cegcc* )
+                echo EXPORTS > "$output_objdir/$outputname.def"
+                cat "$export_symbols" >> "$output_objdir/$outputname.def"
+	        ;;
+	      esac
+	    }
+	  else
+	    $opt_dry_run || {
+	      ${SED} -e 's/\([].[*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/' < "$export_symbols" > "$output_objdir/$outputname.exp"
+	      $GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T
+	      $MV "$nlist"T "$nlist"
+	      case $host in
+	        *cygwin* | *mingw* | *cegcc* )
+	          echo EXPORTS > "$output_objdir/$outputname.def"
+	          cat "$nlist" >> "$output_objdir/$outputname.def"
+	          ;;
+	      esac
+	    }
+	  fi
+	fi
+
+	for dlprefile in $dlprefiles; do
+	  func_verbose "extracting global C symbols from \`$dlprefile'"
+	  func_basename "$dlprefile"
+	  name="$func_basename_result"
+	  $opt_dry_run || {
+	    $ECHO ": $name " >> "$nlist"
+	    eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	  }
+	done
+
+	$opt_dry_run || {
+	  # Make sure we have at least an empty file.
+	  test -f "$nlist" || : > "$nlist"
+
+	  if test -n "$exclude_expsyms"; then
+	    $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	    $MV "$nlist"T "$nlist"
+	  fi
+
+	  # Try sorting and uniquifying the output.
+	  if $GREP -v "^: " < "$nlist" |
+	      if sort -k 3 </dev/null >/dev/null 2>&1; then
+		sort -k 3
+	      else
+		sort +2
+	      fi |
+	      uniq > "$nlist"S; then
+	    :
+	  else
+	    $GREP -v "^: " < "$nlist" > "$nlist"S
+	  fi
+
+	  if test -f "$nlist"S; then
+	    eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+	  else
+	    echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
+	  fi
+
+	  echo >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols.  */
+typedef struct {
+  const char *name;
+  void *address;
+} lt_dlsymlist;
+"
+	  case $host in
+	  *cygwin* | *mingw* | *cegcc* )
+	    echo >> "$output_objdir/$my_dlsyms" "\
+/* DATA imports from DLLs on WIN32 con't be const, because
+   runtime relocations are performed -- see ld's documentation
+   on pseudo-relocs.  */"
+	    lt_dlsym_const= ;;
+	  *osf5*)
+	    echo >> "$output_objdir/$my_dlsyms" "\
+/* This system does not cope well with relocations in const data */"
+	    lt_dlsym_const= ;;
+	  *)
+	    lt_dlsym_const=const ;;
+	  esac
+
+	  echo >> "$output_objdir/$my_dlsyms" "\
+extern $lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];
+$lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{\
+  { \"$my_originator\", (void *) 0 },"
+
+	  case $need_lib_prefix in
+	  no)
+	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  *)
+	    eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  esac
+	  echo >> "$output_objdir/$my_dlsyms" "\
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+	} # !$opt_dry_run
+
+	pic_flag_for_symtable=
+	case "$compile_command " in
+	*" -static "*) ;;
+	*)
+	  case $host in
+	  # compiling the symbol table file with pic_flag works around
+	  # a FreeBSD bug that causes programs to crash when -lm is
+	  # linked before any other PIC object.  But we must not use
+	  # pic_flag when linking with -static.  The problem exists in
+	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+	  *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+	    pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+	  *-*-hpux*)
+	    pic_flag_for_symtable=" $pic_flag"  ;;
+	  *)
+	    if test "X$my_pic_p" != Xno; then
+	      pic_flag_for_symtable=" $pic_flag"
+	    fi
+	    ;;
+	  esac
+	  ;;
+	esac
+	symtab_cflags=
+	for arg in $LTCFLAGS; do
+	  case $arg in
+	  -pie | -fpie | -fPIE) ;;
+	  *) symtab_cflags="$symtab_cflags $arg" ;;
+	  esac
+	done
+
+	# Now compile the dynamic symbol file.
+	func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+	# Clean up the generated files.
+	func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
+
+	# Transform the symbol file into the correct name.
+	symfileobj="$output_objdir/${my_outputname}S.$objext"
+	case $host in
+	*cygwin* | *mingw* | *cegcc* )
+	  if test -f "$output_objdir/$my_outputname.def"; then
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	  else
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  fi
+	  ;;
+	*)
+	  compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  ;;
+	esac
+	;;
+      *)
+	func_fatal_error "unknown suffix for \`$my_dlsyms'"
+	;;
+      esac
+    else
+      # We keep going just in case the user didn't refer to
+      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+      # really was required.
+
+      # Nullify the symbol file.
+      compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
+      finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
+    fi
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+# Despite the name, also deal with 64 bit binaries.
+func_win32_libid ()
+{
+  $opt_debug
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    if $OBJDUMP -f "$1" | $SED -e '10q' 2>/dev/null |
+       $EGREP 'file format (pe-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+      win32_nmres=`$NM -f posix -A "$1" |
+	$SED -n -e '
+	    1,100{
+		/ I /{
+		    s,.*,import,
+		    p
+		    q
+		}
+	    }'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $ECHO "$win32_libid_type"
+}
+
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    $opt_debug
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+    if test "$lock_old_archive_extraction" = yes; then
+      lockfile=$f_ex_an_ar_oldlib.lock
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    fi
+    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
+		   'stat=$?; rm -f "$lockfile"; exit $stat'
+    if test "$lock_old_archive_extraction" = yes; then
+      $opt_dry_run || rm -f "$lockfile"
+    fi
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+    fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    $opt_debug
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+	[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+	*) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      func_basename "$my_xlib"
+      my_xlib="$func_basename_result"
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+	*" $my_xlib_u "*)
+	  func_arith $extracted_serial + 1
+	  extracted_serial=$func_arith_result
+	  my_xlib_u=lt$extracted_serial-$my_xlib ;;
+	*) break ;;
+	esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      func_mkdir_p "$my_xdir"
+
+      case $host in
+      *-darwin*)
+	func_verbose "Extracting $my_xabs"
+	# Do not bother doing anything if just a dry run
+	$opt_dry_run || {
+	  darwin_orig_dir=`pwd`
+	  cd $my_xdir || exit $?
+	  darwin_archive=$my_xabs
+	  darwin_curdir=`pwd`
+	  darwin_base_archive=`basename "$darwin_archive"`
+	  darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+	  if test -n "$darwin_arches"; then
+	    darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+	    darwin_arch=
+	    func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+	    for darwin_arch in  $darwin_arches ; do
+	      func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+	      cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+	      cd "$darwin_curdir"
+	      $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+	    done # $darwin_arches
+            ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
+	    darwin_file=
+	    darwin_files=
+	    for darwin_file in $darwin_filelist; do
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+	      $LIPO -create -output "$darwin_file" $darwin_files
+	    done # $darwin_filelist
+	    $RM -rf unfat-$$
+	    cd "$darwin_orig_dir"
+	  else
+	    cd $darwin_orig_dir
+	    func_extract_an_archive "$my_xdir" "$my_xabs"
+	  fi # $darwin_arches
+	} # !$opt_dry_run
+	;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+	;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+
+    func_extract_archives_result="$my_oldobjs"
+}
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable.  Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take.  If 'yes', then the emitted script
+# will assume that the directory in which it is stored is
+# the $objdir directory.  This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+	func_emit_wrapper_arg1=${1-no}
+
+	$ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='$macro_version'
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$ECHO are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    file=\"\$0\""
+
+    qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
+    $ECHO "\
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+    ECHO=\"$qECHO\"
+  fi\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
+  done
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
+  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+    # special case for '.'
+    if test \"\$thisdir\" = \".\"; then
+      thisdir=\`pwd\`
+    fi
+    # remove .libs from thisdir
+    case \"\$thisdir\" in
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    $objdir )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+	if test "$fast_install" = yes; then
+	  $ECHO "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" ||
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $MKDIR \"\$progdir\"
+    else
+      $RM \"\$progdir/\$file\"
+    fi"
+
+	  $ECHO "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \"\$relink_command\" 2>&1\`; then :
+      else
+	$ECHO \"\$relink_command_output\" >&2
+	$RM \"\$progdir/\$file\"
+	exit 1
+      fi
+    fi
+
+    $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $RM \"\$progdir/\$program\";
+      $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $RM \"\$progdir/\$file\"
+  fi"
+	else
+	  $ECHO "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+	fi
+
+	$ECHO "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+	# Export our shlibpath_var if we have one.
+	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+	  $ECHO "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+	fi
+
+	# fixup the dll searchpath if we need to.
+	if test -n "$dllsearchpath"; then
+	  $ECHO "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+	fi
+
+	$ECHO "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+	case $host in
+	# Backslashes separate directories on plain windows
+	*-*-mingw | *-*-os2* | *-cegcc*)
+	  $ECHO "\
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+	  ;;
+
+	*)
+	  $ECHO "\
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+	  ;;
+	esac
+	$ECHO "\
+      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+    \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+}
+
+
+# func_to_host_path arg
+#
+# Convert paths to host format when used with build tools.
+# Intended for use with "native" mingw (where libtool itself
+# is running under the msys shell), or in the following cross-
+# build environments:
+#    $build          $host
+#    mingw (msys)    mingw  [e.g. native]
+#    cygwin          mingw
+#    *nix + wine     mingw
+# where wine is equipped with the `winepath' executable.
+# In the native mingw case, the (msys) shell automatically
+# converts paths for any non-msys applications it launches,
+# but that facility isn't available from inside the cwrapper.
+# Similar accommodations are necessary for $host mingw and
+# $build cygwin.  Calling this function does no harm for other
+# $host/$build combinations not listed above.
+#
+# ARG is the path (on $build) that should be converted to
+# the proper representation for $host. The result is stored
+# in $func_to_host_path_result.
+func_to_host_path ()
+{
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    case $host in
+      *mingw* )
+        lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+        case $build in
+          *mingw* ) # actually, msys
+            # awkward: cmd appends spaces to result
+            func_to_host_path_result=`( cmd //c echo "$1" ) 2>/dev/null |
+              $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"`
+            ;;
+          *cygwin* )
+            func_to_host_path_result=`cygpath -w "$1" |
+	      $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          * )
+            # Unfortunately, winepath does not exit with a non-zero
+            # error code, so we are forced to check the contents of
+            # stdout. On the other hand, if the command is not
+            # found, the shell will set an exit code of 127 and print
+            # *an error message* to stdout. So we must check for both
+            # error code of zero AND non-empty stdout, which explains
+            # the odd construction:
+            func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null`
+            if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then
+              func_to_host_path_result=`$ECHO "$func_to_host_path_tmp1" |
+                $SED -e "$lt_sed_naive_backslashify"`
+            else
+              # Allow warning below.
+              func_to_host_path_result=
+            fi
+            ;;
+        esac
+        if test -z "$func_to_host_path_result" ; then
+          func_error "Could not determine host path corresponding to"
+          func_error "  \`$1'"
+          func_error "Continuing, but uninstalled executables may not work."
+          # Fallback:
+          func_to_host_path_result="$1"
+        fi
+        ;;
+    esac
+  fi
+}
+# end: func_to_host_path
+
+# func_to_host_pathlist arg
+#
+# Convert pathlists to host format when used with build tools.
+# See func_to_host_path(), above. This function supports the
+# following $build/$host combinations (but does no harm for
+# combinations not listed here):
+#    $build          $host
+#    mingw (msys)    mingw  [e.g. native]
+#    cygwin          mingw
+#    *nix + wine     mingw
+#
+# Path separators are also converted from $build format to
+# $host format. If ARG begins or ends with a path separator
+# character, it is preserved (but converted to $host format)
+# on output.
+#
+# ARG is a pathlist (on $build) that should be converted to
+# the proper representation on $host. The result is stored
+# in $func_to_host_pathlist_result.
+func_to_host_pathlist ()
+{
+  func_to_host_pathlist_result="$1"
+  if test -n "$1"; then
+    case $host in
+      *mingw* )
+        lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+        # Remove leading and trailing path separator characters from
+        # ARG. msys behavior is inconsistent here, cygpath turns them
+        # into '.;' and ';.', and winepath ignores them completely.
+	func_stripname : : "$1"
+        func_to_host_pathlist_tmp1=$func_stripname_result
+        case $build in
+          *mingw* ) # Actually, msys.
+            # Awkward: cmd appends spaces to result.
+            func_to_host_pathlist_result=`
+	      ( cmd //c echo "$func_to_host_pathlist_tmp1" ) 2>/dev/null |
+	      $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"`
+            ;;
+          *cygwin* )
+            func_to_host_pathlist_result=`cygpath -w -p "$func_to_host_pathlist_tmp1" |
+              $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          * )
+            # unfortunately, winepath doesn't convert pathlists
+            func_to_host_pathlist_result=""
+            func_to_host_pathlist_oldIFS=$IFS
+            IFS=:
+            for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do
+              IFS=$func_to_host_pathlist_oldIFS
+              if test -n "$func_to_host_pathlist_f" ; then
+                func_to_host_path "$func_to_host_pathlist_f"
+                if test -n "$func_to_host_path_result" ; then
+                  if test -z "$func_to_host_pathlist_result" ; then
+                    func_to_host_pathlist_result="$func_to_host_path_result"
+                  else
+                    func_append func_to_host_pathlist_result ";$func_to_host_path_result"
+                  fi
+                fi
+              fi
+            done
+            IFS=$func_to_host_pathlist_oldIFS
+            ;;
+        esac
+        if test -z "$func_to_host_pathlist_result"; then
+          func_error "Could not determine the host path(s) corresponding to"
+          func_error "  \`$1'"
+          func_error "Continuing, but uninstalled executables may not work."
+          # Fallback. This may break if $1 contains DOS-style drive
+          # specifications. The fix is not to complicate the expression
+          # below, but for the user to provide a working wine installation
+          # with winepath so that path translation in the cross-to-mingw
+          # case works properly.
+          lt_replace_pathsep_nix_to_dos="s|:|;|g"
+          func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\
+            $SED -e "$lt_replace_pathsep_nix_to_dos"`
+        fi
+        # Now, add the leading and trailing path separators back
+        case "$1" in
+          :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result"
+            ;;
+        esac
+        case "$1" in
+          *: ) func_append func_to_host_pathlist_result ";"
+            ;;
+        esac
+        ;;
+    esac
+  fi
+}
+# end: func_to_host_pathlist
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+	cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "$SHELL $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+	    cat <<"EOF"
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* declarations of non-ANSI functions */
+#if defined(__MINGW32__)
+# ifdef __STRICT_ANSI__
+int _putenv (const char *);
+# endif
+#elif defined(__CYGWIN__)
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+/* #elif defined (other platforms) ... */
+#endif
+
+/* portability defines, excluding path handling macros */
+#if defined(_MSC_VER)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+# define S_IXUSR _S_IEXEC
+# ifndef _INTPTR_T_DEFINED
+#  define _INTPTR_T_DEFINED
+#  define intptr_t int
+# endif
+#elif defined(__MINGW32__)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+#elif defined(__CYGWIN__)
+# define HAVE_SETENV
+# define FOPEN_WB "wb"
+/* #elif defined (other platforms) ... */
+#endif
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+/* path handling portability macros */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+#undef LTWRAPPER_DEBUGPRINTF
+#if defined LT_DEBUGWRAPPER
+# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args
+static void
+ltwrapper_debugprintf (const char *fmt, ...)
+{
+    va_list args;
+    va_start (args, fmt);
+    (void) vfprintf (stderr, fmt, args);
+    va_end (args);
+}
+#else
+# define LTWRAPPER_DEBUGPRINTF(args)
+#endif
+
+const char *program_name = NULL;
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+char **prepare_spawn (char **argv);
+void lt_dump_script (FILE *f);
+EOF
+
+	    cat <<EOF
+const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+	    if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+              func_to_host_pathlist "$temp_rpath"
+	      cat <<EOF
+const char * LIB_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * LIB_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test -n "$dllsearchpath"; then
+              func_to_host_pathlist "$dllsearchpath:"
+	      cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test "$fast_install" = yes; then
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+	    else
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+	    fi
+
+
+	    cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX         "--lt-"
+#define LTWRAPPER_OPTION_PREFIX_LENGTH  5
+
+static const size_t opt_prefix_len         = LTWRAPPER_OPTION_PREFIX_LENGTH;
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+
+static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int  newargc;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *actual_cwrapper_name;
+  char *target_name;
+  char *lt_argv_zero;
+  intptr_t rval = 127;
+
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) argv[0]      : %s\n", argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
+
+  /* very simple arg parsing; don't want to rely on getopt */
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], dumpscript_opt) == 0)
+	{
+EOF
+	    case "$host" in
+	      *mingw* | *cygwin* )
+		# make stdout use "unix" line endings
+		echo "          setmode(1,_O_BINARY);"
+		;;
+	      esac
+
+	    cat <<"EOF"
+	  lt_dump_script (stdout);
+	  return 0;
+	}
+    }
+
+  newargz = XMALLOC (char *, argc + 1);
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal ("Couldn't find %s", argv[0]);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
+			  tmp_pathspec));
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
+			  actual_cwrapper_path));
+  XFREE (tmp_pathspec);
+
+  actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+  /* wrapper name transforms */
+  strendzap (actual_cwrapper_name, ".exe");
+  tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+  XFREE (actual_cwrapper_name);
+  actual_cwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  /* target_name transforms -- use actual target program name; might have lt- prefix */
+  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+  strendzap (target_name, ".exe");
+  tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+  XFREE (target_name);
+  target_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
+			  target_name));
+EOF
+
+	    cat <<EOF
+  newargz[0] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+		    strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+  strcpy (newargz[0], actual_cwrapper_path);
+  strcat (newargz[0], "$objdir");
+  strcat (newargz[0], "/");
+EOF
+
+	    cat <<"EOF"
+  /* stop here, and copy so we don't have to do this twice */
+  tmp_pathspec = xstrdup (newargz[0]);
+
+  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+  strcat (newargz[0], actual_cwrapper_name);
+
+  /* DO want the lt- prefix here if it exists, so use target_name */
+  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+  XFREE (tmp_pathspec);
+  tmp_pathspec = NULL;
+EOF
+
+	    case $host_os in
+	      mingw*)
+	    cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[0], '\\')) != NULL)
+      {
+	*p = '/';
+      }
+    while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+      {
+	*p = '/';
+      }
+  }
+EOF
+	    ;;
+	    esac
+
+	    cat <<"EOF"
+  XFREE (target_name);
+  XFREE (actual_cwrapper_path);
+  XFREE (actual_cwrapper_name);
+
+  lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+  lt_setenv ("DUALCASE", "1");  /* for MSK sh */
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+
+  newargc=0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal ("Unrecognized option in %s namespace: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
+    }
+  newargz[++newargc] = NULL;
+
+  LTWRAPPER_DEBUGPRINTF     (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>")));
+  for (i = 0; i < newargc; i++)
+    {
+      LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d]   : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>")));
+    }
+
+EOF
+
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+  /* execv doesn't actually work on mingw as expected on unix */
+  newargz = prepare_spawn (newargz);
+  rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+  if (rval == -1)
+    {
+      /* failed to start process */
+      LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno));
+      return 127;
+    }
+  return rval;
+EOF
+		;;
+	      *)
+		cat <<"EOF"
+  execv (lt_argv_zero, newargz);
+  return rval; /* =127, but avoids unused variable warning */
+EOF
+		;;
+	    esac
+
+	    cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+  void *p = (void *) malloc (num);
+  if (!p)
+    lt_fatal ("Memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+			  string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable (const char *path)
+{
+  struct stat st;
+
+  LTWRAPPER_DEBUGPRINTF (("(check_executable)  : %s\n",
+			  path ? (*path ? path : "EMPTY!") : "NULL!"));
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0)
+      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+    return 1;
+  else
+    return 0;
+}
+
+int
+make_executable (const char *path)
+{
+  int rval = 0;
+  struct stat st;
+
+  LTWRAPPER_DEBUGPRINTF (("(make_executable)   : %s\n",
+			  path ? (*path ? path : "EMPTY!") : "NULL!"));
+  if ((!path) || (!*path))
+    return 0;
+
+  if (stat (path, &st) >= 0)
+    {
+      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+    }
+  return rval;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise
+   Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+  int has_slash = 0;
+  const char *p;
+  const char *p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char *concat_name;
+
+  LTWRAPPER_DEBUGPRINTF (("(find_executable)   : %s\n",
+			  wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"));
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable (concat_name))
+	return concat_name;
+      XFREE (concat_name);
+    }
+  else
+    {
+#endif
+      if (IS_DIR_SEPARATOR (wrapper[0]))
+	{
+	  concat_name = xstrdup (wrapper);
+	  if (check_executable (concat_name))
+	    return concat_name;
+	  XFREE (concat_name);
+	}
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+    }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+      {
+	has_slash = 1;
+	break;
+      }
+  if (!has_slash)
+    {
+      /* no slashes; search PATH */
+      const char *path = getenv ("PATH");
+      if (path != NULL)
+	{
+	  for (p = path; *p; p = p_next)
+	    {
+	      const char *q;
+	      size_t p_len;
+	      for (q = p; *q; q++)
+		if (IS_PATH_SEPARATOR (*q))
+		  break;
+	      p_len = q - p;
+	      p_next = (*q == '\0' ? q : q + 1);
+	      if (p_len == 0)
+		{
+		  /* empty path: current directory */
+		  if (getcwd (tmp, LT_PATHMAX) == NULL)
+		    lt_fatal ("getcwd failed");
+		  tmp_len = strlen (tmp);
+		  concat_name =
+		    XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, tmp, tmp_len);
+		  concat_name[tmp_len] = '/';
+		  strcpy (concat_name + tmp_len + 1, wrapper);
+		}
+	      else
+		{
+		  concat_name =
+		    XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, p, p_len);
+		  concat_name[p_len] = '/';
+		  strcpy (concat_name + p_len + 1, wrapper);
+		}
+	      if (check_executable (concat_name))
+		return concat_name;
+	      XFREE (concat_name);
+	    }
+	}
+      /* not found in PATH; assume curdir */
+    }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal ("getcwd failed");
+  tmp_len = strlen (tmp);
+  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable (concat_name))
+    return concat_name;
+  XFREE (concat_name);
+  return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+  return xstrdup (pathspec);
+#else
+  char buf[LT_PATHMAX];
+  struct stat s;
+  char *tmp_pathspec = xstrdup (pathspec);
+  char *p;
+  int has_symlinks = 0;
+  while (strlen (tmp_pathspec) && !has_symlinks)
+    {
+      LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n",
+			      tmp_pathspec));
+      if (lstat (tmp_pathspec, &s) == 0)
+	{
+	  if (S_ISLNK (s.st_mode) != 0)
+	    {
+	      has_symlinks = 1;
+	      break;
+	    }
+
+	  /* search backwards for last DIR_SEPARATOR */
+	  p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+	  while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    p--;
+	  if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    {
+	      /* no more DIR_SEPARATORS left */
+	      break;
+	    }
+	  *p = '\0';
+	}
+      else
+	{
+	  char *errstr = strerror (errno);
+	  lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr);
+	}
+    }
+  XFREE (tmp_pathspec);
+
+  if (!has_symlinks)
+    {
+      return xstrdup (pathspec);
+    }
+
+  tmp_pathspec = realpath (pathspec, buf);
+  if (tmp_pathspec == 0)
+    {
+      lt_fatal ("Could not follow symlinks for %s", pathspec);
+    }
+  return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert (str != NULL);
+  assert (pat != NULL);
+
+  len = strlen (str);
+  patlen = strlen (pat);
+
+  if (patlen <= len)
+    {
+      str += len - patlen;
+      if (strcmp (str, pat) == 0)
+	*str = '\0';
+    }
+  return str;
+}
+
+static void
+lt_error_core (int exit_status, const char *mode,
+	       const char *message, va_list ap)
+{
+  fprintf (stderr, "%s: %s: ", program_name, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  va_end (ap);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+  {
+#ifdef HAVE_SETENV
+    /* always make a copy, for consistency with !HAVE_SETENV */
+    char *str = xstrdup (value);
+    setenv (name, str, 1);
+#else
+    int len = strlen (name) + 1 + strlen (value) + 1;
+    char *str = XMALLOC (char, len);
+    sprintf (str, "%s=%s", name, value);
+    if (putenv (str) != EXIT_SUCCESS)
+      {
+        XFREE (str);
+      }
+#endif
+  }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+  char *new_value;
+  if (orig_value && *orig_value)
+    {
+      int orig_value_len = strlen (orig_value);
+      int add_len = strlen (add);
+      new_value = XMALLOC (char, add_len + orig_value_len + 1);
+      if (to_end)
+        {
+          strcpy (new_value, orig_value);
+          strcpy (new_value + orig_value_len, add);
+        }
+      else
+        {
+          strcpy (new_value, add);
+          strcpy (new_value + add_len, orig_value);
+        }
+    }
+  else
+    {
+      new_value = xstrdup (add);
+    }
+  return new_value;
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      /* some systems can't cope with a ':'-terminated path #' */
+      int len = strlen (new_value);
+      while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+        {
+          new_value[len-1] = '\0';
+        }
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+EOF
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+
+/* Prepares an argument vector before calling spawn().
+   Note that spawn() does not by itself call the command interpreter
+     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+         GetVersionEx(&v);
+         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+      }) ? "cmd.exe" : "command.com").
+   Instead it simply concatenates the arguments, separated by ' ', and calls
+   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
+   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+   special way:
+   - Space and tab are interpreted as delimiters. They are not treated as
+     delimiters if they are surrounded by double quotes: "...".
+   - Unescaped double quotes are removed from the input. Their only effect is
+     that within double quotes, space and tab are treated like normal
+     characters.
+   - Backslashes not followed by double quotes are not special.
+   - But 2*n+1 backslashes followed by a double quote become
+     n backslashes followed by a double quote (n >= 0):
+       \" -> "
+       \\\" -> \"
+       \\\\\" -> \\"
+ */
+#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+char **
+prepare_spawn (char **argv)
+{
+  size_t argc;
+  char **new_argv;
+  size_t i;
+
+  /* Count number of arguments.  */
+  for (argc = 0; argv[argc] != NULL; argc++)
+    ;
+
+  /* Allocate new argument vector.  */
+  new_argv = XMALLOC (char *, argc + 1);
+
+  /* Put quoted arguments into the new argument vector.  */
+  for (i = 0; i < argc; i++)
+    {
+      const char *string = argv[i];
+
+      if (string[0] == '\0')
+	new_argv[i] = xstrdup ("\"\"");
+      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+	{
+	  int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+	  size_t length;
+	  unsigned int backslashes;
+	  const char *s;
+	  char *quoted_string;
+	  char *p;
+
+	  length = 0;
+	  backslashes = 0;
+	  if (quote_around)
+	    length++;
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		length += backslashes + 1;
+	      length++;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    length += backslashes + 1;
+
+	  quoted_string = XMALLOC (char, length + 1);
+
+	  p = quoted_string;
+	  backslashes = 0;
+	  if (quote_around)
+	    *p++ = '"';
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		{
+		  unsigned int j;
+		  for (j = backslashes + 1; j > 0; j--)
+		    *p++ = '\\';
+		}
+	      *p++ = c;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    {
+	      unsigned int j;
+	      for (j = backslashes; j > 0; j--)
+		*p++ = '\\';
+	      *p++ = '"';
+	    }
+	  *p = '\0';
+
+	  new_argv[i] = quoted_string;
+	}
+      else
+	new_argv[i] = (char *) string;
+    }
+  new_argv[argc] = NULL;
+
+  return new_argv;
+}
+EOF
+		;;
+	    esac
+
+            cat <<"EOF"
+void lt_dump_script (FILE* f)
+{
+EOF
+	    func_emit_wrapper yes |
+              $SED -e 's/\([\\"]\)/\\\1/g' \
+	           -e 's/^/  fputs ("/' -e 's/$/\\n", f);/'
+
+            cat <<"EOF"
+}
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_win32_import_lib_p ARG
+# True if ARG is an import lib, as indicated by $file_magic_cmd
+func_win32_import_lib_p ()
+{
+    $opt_debug
+    case `eval "$file_magic_cmd \"\$1\" 2>/dev/null" | $SED -e 10q` in
+    *import*) : ;;
+    *) false ;;
+    esac
+}
+
+# func_mode_link arg...
+func_mode_link ()
+{
+    $opt_debug
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args=$nonopt
+    base_compile="$nonopt $@"
+    compile_command=$nonopt
+    finalize_command=$nonopt
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+    new_inherited_linker_flags=
+
+    avoid_version=no
+    bindir=
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+    weak_libs=
+    single_module="${wl}-single_module"
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	break
+	;;
+      -all-static | -static | -static-libtool-libs)
+	case $arg in
+	-all-static)
+	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+	    func_warning "complete static linking is impossible in this configuration"
+	  fi
+	  if test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	-static)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=built
+	  ;;
+	-static-libtool-libs)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	esac
+	build_libtool_libs=no
+	build_old_libs=yes
+	break
+	;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      func_quote_for_eval "$arg"
+      qarg=$func_quote_for_eval_unquoted_result
+      func_append libtool_args " $func_quote_for_eval_result"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+	case $prev in
+	output)
+	  func_append compile_command " @OUTPUT@"
+	  func_append finalize_command " @OUTPUT@"
+	  ;;
+	esac
+
+	case $prev in
+	bindir)
+	  bindir="$arg"
+	  prev=
+	  continue
+	  ;;
+	dlfiles|dlprefiles)
+	  if test "$preload" = no; then
+	    # Add the symbol object into the linking commands.
+	    func_append compile_command " @SYMFILE@"
+	    func_append finalize_command " @SYMFILE@"
+	    preload=yes
+	  fi
+	  case $arg in
+	  *.la | *.lo) ;;  # We handle these cases below.
+	  force)
+	    if test "$dlself" = no; then
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  self)
+	    if test "$prev" = dlprefiles; then
+	      dlself=yes
+	    elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+	      dlself=yes
+	    else
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  *)
+	    if test "$prev" = dlfiles; then
+	      dlfiles="$dlfiles $arg"
+	    else
+	      dlprefiles="$dlprefiles $arg"
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  esac
+	  ;;
+	expsyms)
+	  export_symbols="$arg"
+	  test -f "$arg" \
+	    || func_fatal_error "symbol file \`$arg' does not exist"
+	  prev=
+	  continue
+	  ;;
+	expsyms_regex)
+	  export_symbols_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	framework)
+	  case $host in
+	    *-*-darwin*)
+	      case "$deplibs " in
+		*" $qarg.ltframework "*) ;;
+		*) deplibs="$deplibs $qarg.ltframework" # this is fixed later
+		   ;;
+	      esac
+	      ;;
+	  esac
+	  prev=
+	  continue
+	  ;;
+	inst_prefix)
+	  inst_prefix_dir="$arg"
+	  prev=
+	  continue
+	  ;;
+	objectlist)
+	  if test -f "$arg"; then
+	    save_arg=$arg
+	    moreargs=
+	    for fil in `cat "$save_arg"`
+	    do
+#	      moreargs="$moreargs $fil"
+	      arg=$fil
+	      # A libtool-controlled object.
+
+	      # Check to see that this really is a libtool object.
+	      if func_lalib_unsafe_p "$arg"; then
+		pic_object=
+		non_pic_object=
+
+		# Read the .lo file
+		func_source "$arg"
+
+		if test -z "$pic_object" ||
+		   test -z "$non_pic_object" ||
+		   test "$pic_object" = none &&
+		   test "$non_pic_object" = none; then
+		  func_fatal_error "cannot find name of object for \`$arg'"
+		fi
+
+		# Extract subdirectory from the argument.
+		func_dirname "$arg" "/" ""
+		xdir="$func_dirname_result"
+
+		if test "$pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  pic_object="$xdir$pic_object"
+
+		  if test "$prev" = dlfiles; then
+		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		      dlfiles="$dlfiles $pic_object"
+		      prev=
+		      continue
+		    else
+		      # If libtool objects are unsupported, then we need to preload.
+		      prev=dlprefiles
+		    fi
+		  fi
+
+		  # CHECK ME:  I think I busted this.  -Ossama
+		  if test "$prev" = dlprefiles; then
+		    # Preload the old-style object.
+		    dlprefiles="$dlprefiles $pic_object"
+		    prev=
+		  fi
+
+		  # A PIC object.
+		  func_append libobjs " $pic_object"
+		  arg="$pic_object"
+		fi
+
+		# Non-PIC object.
+		if test "$non_pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  non_pic_object="$xdir$non_pic_object"
+
+		  # A standard non-PIC object
+		  func_append non_pic_objects " $non_pic_object"
+		  if test -z "$pic_object" || test "$pic_object" = none ; then
+		    arg="$non_pic_object"
+		  fi
+		else
+		  # If the PIC object exists, use it instead.
+		  # $xdir was prepended to $pic_object above.
+		  non_pic_object="$pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+		fi
+	      else
+		# Only an error if not doing a dry-run.
+		if $opt_dry_run; then
+		  # Extract subdirectory from the argument.
+		  func_dirname "$arg" "/" ""
+		  xdir="$func_dirname_result"
+
+		  func_lo2o "$arg"
+		  pic_object=$xdir$objdir/$func_lo2o_result
+		  non_pic_object=$xdir$func_lo2o_result
+		  func_append libobjs " $pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+	        else
+		  func_fatal_error "\`$arg' is not a valid libtool object"
+		fi
+	      fi
+	    done
+	  else
+	    func_fatal_error "link input file \`$arg' does not exist"
+	  fi
+	  arg=$save_arg
+	  prev=
+	  continue
+	  ;;
+	precious_regex)
+	  precious_files_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	release)
+	  release="-$arg"
+	  prev=
+	  continue
+	  ;;
+	rpath | xrpath)
+	  # We need an absolute path.
+	  case $arg in
+	  [\\/]* | [A-Za-z]:[\\/]*) ;;
+	  *)
+	    func_fatal_error "only absolute run-paths are allowed"
+	    ;;
+	  esac
+	  if test "$prev" = rpath; then
+	    case "$rpath " in
+	    *" $arg "*) ;;
+	    *) rpath="$rpath $arg" ;;
+	    esac
+	  else
+	    case "$xrpath " in
+	    *" $arg "*) ;;
+	    *) xrpath="$xrpath $arg" ;;
+	    esac
+	  fi
+	  prev=
+	  continue
+	  ;;
+	shrext)
+	  shrext_cmds="$arg"
+	  prev=
+	  continue
+	  ;;
+	weak)
+	  weak_libs="$weak_libs $arg"
+	  prev=
+	  continue
+	  ;;
+	xcclinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xcompiler)
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xlinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $wl$qarg"
+	  prev=
+	  func_append compile_command " $wl$qarg"
+	  func_append finalize_command " $wl$qarg"
+	  continue
+	  ;;
+	*)
+	  eval "$prev=\"\$arg\""
+	  prev=
+	  continue
+	  ;;
+	esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+	if test -n "$link_static_flag"; then
+	  # See comment for -static flag below, for more details.
+	  func_append compile_command " $link_static_flag"
+	  func_append finalize_command " $link_static_flag"
+	fi
+	continue
+	;;
+
+      -allow-undefined)
+	# FIXME: remove this flag sometime in the future.
+	func_fatal_error "\`-allow-undefined' must not be used because it is the default"
+	;;
+
+      -avoid-version)
+	avoid_version=yes
+	continue
+	;;
+
+      -bindir)
+	prev=bindir
+	continue
+	;;
+
+      -dlopen)
+	prev=dlfiles
+	continue
+	;;
+
+      -dlpreopen)
+	prev=dlprefiles
+	continue
+	;;
+
+      -export-dynamic)
+	export_dynamic=yes
+	continue
+	;;
+
+      -export-symbols | -export-symbols-regex)
+	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	  func_fatal_error "more than one -exported-symbols argument is not allowed"
+	fi
+	if test "X$arg" = "X-export-symbols"; then
+	  prev=expsyms
+	else
+	  prev=expsyms_regex
+	fi
+	continue
+	;;
+
+      -framework)
+	prev=framework
+	continue
+	;;
+
+      -inst-prefix-dir)
+	prev=inst_prefix
+	continue
+	;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+	case $with_gcc/$host in
+	no/*-*-irix* | /*-*-irix*)
+	  func_append compile_command " $arg"
+	  func_append finalize_command " $arg"
+	  ;;
+	esac
+	continue
+	;;
+
+      -L*)
+	func_stripname '-L' '' "$arg"
+	dir=$func_stripname_result
+	if test -z "$dir"; then
+	  if test "$#" -gt 0; then
+	    func_fatal_error "require no space between \`-L' and \`$1'"
+	  else
+	    func_fatal_error "need path for \`-L' option"
+	  fi
+	fi
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  absdir=`cd "$dir" && pwd`
+	  test -z "$absdir" && \
+	    func_fatal_error "cannot determine absolute directory name of \`$dir'"
+	  dir="$absdir"
+	  ;;
+	esac
+	case "$deplibs " in
+	*" -L$dir "*) ;;
+	*)
+	  deplibs="$deplibs -L$dir"
+	  lib_search_path="$lib_search_path $dir"
+	  ;;
+	esac
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$dir:"*) ;;
+	  ::) dllsearchpath=$dir;;
+	  *) dllsearchpath="$dllsearchpath:$dir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  esac
+	  ;;
+	esac
+	continue
+	;;
+
+      -l*)
+	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
+	    # These systems don't actually have a C or math library (as such)
+	    continue
+	    ;;
+	  *-*-os2*)
+	    # These systems don't actually have a C library (as such)
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C and math libraries are in the System framework
+	    deplibs="$deplibs System.ltframework"
+	    continue
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-linux*)
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  esac
+	elif test "X$arg" = "X-lc_r"; then
+	 case $host in
+	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	   # Do not include libc_r directly, use -pthread flag.
+	   continue
+	   ;;
+	 esac
+	fi
+	deplibs="$deplibs $arg"
+	continue
+	;;
+
+      -module)
+	module=yes
+	continue
+	;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      # Darwin uses the -arch flag to determine output architecture.
+      -model|-arch|-isysroot)
+	compiler_flags="$compiler_flags $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	prev=xcompiler
+	continue
+	;;
+
+      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+	compiler_flags="$compiler_flags $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	case "$new_inherited_linker_flags " in
+	    *" $arg "*) ;;
+	    * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;;
+	esac
+	continue
+	;;
+
+      -multi_module)
+	single_module="${wl}-multi_module"
+	continue
+	;;
+
+      -no-fast-install)
+	fast_install=no
+	continue
+	;;
+
+      -no-install)
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+	  # The PATH hackery in wrapper scripts is required on Windows
+	  # and Darwin in order for the loader to find any dlls it needs.
+	  func_warning "\`-no-install' is ignored for $host"
+	  func_warning "assuming \`-no-fast-install' instead"
+	  fast_install=no
+	  ;;
+	*) no_install=yes ;;
+	esac
+	continue
+	;;
+
+      -no-undefined)
+	allow_undefined=no
+	continue
+	;;
+
+      -objectlist)
+	prev=objectlist
+	continue
+	;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+	prev=precious_regex
+	continue
+	;;
+
+      -release)
+	prev=release
+	continue
+	;;
+
+      -rpath)
+	prev=rpath
+	continue
+	;;
+
+      -R)
+	prev=xrpath
+	continue
+	;;
+
+      -R*)
+	func_stripname '-R' '' "$arg"
+	dir=$func_stripname_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  func_fatal_error "only absolute run-paths are allowed"
+	  ;;
+	esac
+	case "$xrpath " in
+	*" $dir "*) ;;
+	*) xrpath="$xrpath $dir" ;;
+	esac
+	continue
+	;;
+
+      -shared)
+	# The effects of -shared are defined in a previous loop.
+	continue
+	;;
+
+      -shrext)
+	prev=shrext
+	continue
+	;;
+
+      -static | -static-libtool-libs)
+	# The effects of -static are defined in a previous loop.
+	# We used to do the same as -all-static on platforms that
+	# didn't have a PIC flag, but the assumption that the effects
+	# would be equivalent was wrong.  It would break on at least
+	# Digital Unix and AIX.
+	continue
+	;;
+
+      -thread-safe)
+	thread_safe=yes
+	continue
+	;;
+
+      -version-info)
+	prev=vinfo
+	continue
+	;;
+
+      -version-number)
+	prev=vinfo
+	vinfo_number=yes
+	continue
+	;;
+
+      -weak)
+        prev=weak
+	continue
+	;;
+
+      -Wc,*)
+	func_stripname '-Wc,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  arg="$arg $func_quote_for_eval_result"
+	  compiler_flags="$compiler_flags $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Wl,*)
+	func_stripname '-Wl,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  arg="$arg $wl$func_quote_for_eval_result"
+	  compiler_flags="$compiler_flags $wl$func_quote_for_eval_result"
+	  linker_flags="$linker_flags $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Xcompiler)
+	prev=xcompiler
+	continue
+	;;
+
+      -Xlinker)
+	prev=xlinker
+	continue
+	;;
+
+      -XCClinker)
+	prev=xcclinker
+	continue
+	;;
+
+      # -msg_* for osf cc
+      -msg_*)
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+      # -r[0-9][0-9]* specifies the processor on the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+      # +DA*, +DD* enable 64-bit mode on the HP compiler
+      # -q* pass through compiler args for the IBM compiler
+      # -m*, -t[45]*, -txscale* pass through architecture-specific
+      # compiler args for GCC
+      # -F/path gives path to uninstalled frameworks, gcc on darwin
+      # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
+      # @file GCC response files
+      # -tp=* Portland pgcc target processor selection
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+        func_append compile_command " $arg"
+        func_append finalize_command " $arg"
+        compiler_flags="$compiler_flags $arg"
+        continue
+        ;;
+
+      # Some other compiler flag.
+      -* | +*)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      *.$objext)
+	# A standard object.
+	objs="$objs $arg"
+	;;
+
+      *.lo)
+	# A libtool-controlled object.
+
+	# Check to see that this really is a libtool object.
+	if func_lalib_unsafe_p "$arg"; then
+	  pic_object=
+	  non_pic_object=
+
+	  # Read the .lo file
+	  func_source "$arg"
+
+	  if test -z "$pic_object" ||
+	     test -z "$non_pic_object" ||
+	     test "$pic_object" = none &&
+	     test "$non_pic_object" = none; then
+	    func_fatal_error "cannot find name of object for \`$arg'"
+	  fi
+
+	  # Extract subdirectory from the argument.
+	  func_dirname "$arg" "/" ""
+	  xdir="$func_dirname_result"
+
+	  if test "$pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    pic_object="$xdir$pic_object"
+
+	    if test "$prev" = dlfiles; then
+	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		dlfiles="$dlfiles $pic_object"
+		prev=
+		continue
+	      else
+		# If libtool objects are unsupported, then we need to preload.
+		prev=dlprefiles
+	      fi
+	    fi
+
+	    # CHECK ME:  I think I busted this.  -Ossama
+	    if test "$prev" = dlprefiles; then
+	      # Preload the old-style object.
+	      dlprefiles="$dlprefiles $pic_object"
+	      prev=
+	    fi
+
+	    # A PIC object.
+	    func_append libobjs " $pic_object"
+	    arg="$pic_object"
+	  fi
+
+	  # Non-PIC object.
+	  if test "$non_pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    non_pic_object="$xdir$non_pic_object"
+
+	    # A standard non-PIC object
+	    func_append non_pic_objects " $non_pic_object"
+	    if test -z "$pic_object" || test "$pic_object" = none ; then
+	      arg="$non_pic_object"
+	    fi
+	  else
+	    # If the PIC object exists, use it instead.
+	    # $xdir was prepended to $pic_object above.
+	    non_pic_object="$pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  fi
+	else
+	  # Only an error if not doing a dry-run.
+	  if $opt_dry_run; then
+	    # Extract subdirectory from the argument.
+	    func_dirname "$arg" "/" ""
+	    xdir="$func_dirname_result"
+
+	    func_lo2o "$arg"
+	    pic_object=$xdir$objdir/$func_lo2o_result
+	    non_pic_object=$xdir$func_lo2o_result
+	    func_append libobjs " $pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  else
+	    func_fatal_error "\`$arg' is not a valid libtool object"
+	  fi
+	fi
+	;;
+
+      *.$libext)
+	# An archive.
+	deplibs="$deplibs $arg"
+	old_deplibs="$old_deplibs $arg"
+	continue
+	;;
+
+      *.la)
+	# A libtool-controlled library.
+
+	if test "$prev" = dlfiles; then
+	  # This library was specified with -dlopen.
+	  dlfiles="$dlfiles $arg"
+	  prev=
+	elif test "$prev" = dlprefiles; then
+	  # The library was specified with -dlpreopen.
+	  dlprefiles="$dlprefiles $arg"
+	  prev=
+	else
+	  deplibs="$deplibs $arg"
+	fi
+	continue
+	;;
+
+      # Some other compiler argument.
+      *)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+      fi
+    done # argument parsing loop
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prevarg' option requires an argument"
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval "arg=\"$export_dynamic_flag_spec\""
+      func_append compile_command " $arg"
+      func_append finalize_command " $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    func_basename "$output"
+    outputname="$func_basename_result"
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval "sys_lib_search_path=\"$sys_lib_search_path_spec\""
+    eval "sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\""
+
+    func_dirname "$output" "/" ""
+    output_objdir="$func_dirname_result$objdir"
+    # Create the object directory.
+    func_mkdir_p "$output_objdir"
+
+    # Determine the type of output
+    case $output in
+    "")
+      func_fatal_help "you must specify an output file"
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if $opt_duplicate_deps ; then
+	case "$libs " in
+	*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	esac
+      fi
+      libs="$libs $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if $opt_duplicate_compiler_generated_deps; then
+	for pre_post_dep in $predeps $postdeps; do
+	  case "$pre_post_deps " in
+	  *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+	  esac
+	  pre_post_deps="$pre_post_deps $pre_post_dep"
+	done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+
+    case $linkmode in
+    lib)
+	passes="conv dlpreopen link"
+	for file in $dlfiles $dlprefiles; do
+	  case $file in
+	  *.la) ;;
+	  *)
+	    func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
+	    ;;
+	  esac
+	done
+	;;
+    prog)
+	compile_deplibs=
+	finalize_deplibs=
+	alldeplibs=no
+	newdlfiles=
+	newdlprefiles=
+	passes="conv scan dlopen dlpreopen link"
+	;;
+    *)  passes="conv"
+	;;
+    esac
+
+    for pass in $passes; do
+      # The preopen pass in lib mode reverses $deplibs; put it back here
+      # so that -L comes before libs that need it for instance...
+      if test "$linkmode,$pass" = "lib,link"; then
+	## FIXME: Find the place where the list is rebuilt in the wrong
+	##        order, and fix it there properly
+        tmp_deplibs=
+	for deplib in $deplibs; do
+	  tmp_deplibs="$deplib $tmp_deplibs"
+	done
+	deplibs="$tmp_deplibs"
+      fi
+
+      if test "$linkmode,$pass" = "lib,link" ||
+	 test "$linkmode,$pass" = "prog,scan"; then
+	libs="$deplibs"
+	deplibs=
+      fi
+      if test "$linkmode" = prog; then
+	case $pass in
+	dlopen) libs="$dlfiles" ;;
+	dlpreopen) libs="$dlprefiles" ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+	esac
+      fi
+      if test "$linkmode,$pass" = "lib,dlpreopen"; then
+	# Collect and forward deplibs of preopened libtool libs
+	for lib in $dlprefiles; do
+	  # Ignore non-libtool-libs
+	  dependency_libs=
+	  case $lib in
+	  *.la)	func_source "$lib" ;;
+	  esac
+
+	  # Collect preopened libtool deplibs, except any this library
+	  # has declared as weak libs
+	  for deplib in $dependency_libs; do
+	    func_basename "$deplib"
+            deplib_base=$func_basename_result
+	    case " $weak_libs " in
+	    *" $deplib_base "*) ;;
+	    *) deplibs="$deplibs $deplib" ;;
+	    esac
+	  done
+	done
+	libs="$dlprefiles"
+      fi
+      if test "$pass" = dlopen; then
+	# Collect dlpreopened libraries
+	save_deplibs="$deplibs"
+	deplibs=
+      fi
+
+      for deplib in $libs; do
+	lib=
+	found=no
+	case $deplib in
+	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    compiler_flags="$compiler_flags $deplib"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-l*)
+	  if test "$linkmode" != lib && test "$linkmode" != prog; then
+	    func_warning "\`-l' is ignored for archives/objects"
+	    continue
+	  fi
+	  func_stripname '-l' '' "$deplib"
+	  name=$func_stripname_result
+	  if test "$linkmode" = lib; then
+	    searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+	  else
+	    searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+	  fi
+	  for searchdir in $searchdirs; do
+	    for search_ext in .la $std_shrext .so .a; do
+	      # Search the libtool library
+	      lib="$searchdir/lib${name}${search_ext}"
+	      if test -f "$lib"; then
+		if test "$search_ext" = ".la"; then
+		  found=yes
+		else
+		  found=no
+		fi
+		break 2
+	      fi
+	    done
+	  done
+	  if test "$found" != yes; then
+	    # deplib doesn't seem to be a libtool library
+	    if test "$linkmode,$pass" = "prog,link"; then
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      deplibs="$deplib $deplibs"
+	      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    continue
+	  else # deplib is a libtool library
+	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+	    # We need to do some special things here, and not later.
+	    if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	      case " $predeps $postdeps " in
+	      *" $deplib "*)
+		if func_lalib_p "$lib"; then
+		  library_names=
+		  old_library=
+		  func_source "$lib"
+		  for l in $old_library $library_names; do
+		    ll="$l"
+		  done
+		  if test "X$ll" = "X$old_library" ; then # only static version available
+		    found=no
+		    func_dirname "$lib" "" "."
+		    ladir="$func_dirname_result"
+		    lib=$ladir/$old_library
+		    if test "$linkmode,$pass" = "prog,link"; then
+		      compile_deplibs="$deplib $compile_deplibs"
+		      finalize_deplibs="$deplib $finalize_deplibs"
+		    else
+		      deplibs="$deplib $deplibs"
+		      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+		    fi
+		    continue
+		  fi
+		fi
+		;;
+	      *) ;;
+	      esac
+	    fi
+	  fi
+	  ;; # -l
+	*.ltframework)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    deplibs="$deplib $deplibs"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-L*)
+	  case $linkmode in
+	  lib)
+	    deplibs="$deplib $deplibs"
+	    test "$pass" = conv && continue
+	    newdependency_libs="$deplib $newdependency_libs"
+	    func_stripname '-L' '' "$deplib"
+	    newlib_search_path="$newlib_search_path $func_stripname_result"
+	    ;;
+	  prog)
+	    if test "$pass" = conv; then
+	      deplibs="$deplib $deplibs"
+	      continue
+	    fi
+	    if test "$pass" = scan; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    func_stripname '-L' '' "$deplib"
+	    newlib_search_path="$newlib_search_path $func_stripname_result"
+	    ;;
+	  *)
+	    func_warning "\`-L' is ignored for archives/objects"
+	    ;;
+	  esac # linkmode
+	  continue
+	  ;; # -L
+	-R*)
+	  if test "$pass" = link; then
+	    func_stripname '-R' '' "$deplib"
+	    dir=$func_stripname_result
+	    # Make sure the xrpath contains only unique directories.
+	    case "$xrpath " in
+	    *" $dir "*) ;;
+	    *) xrpath="$xrpath $dir" ;;
+	    esac
+	  fi
+	  deplibs="$deplib $deplibs"
+	  continue
+	  ;;
+	*.la) lib="$deplib" ;;
+	*.$libext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	    continue
+	  fi
+	  case $linkmode in
+	  lib)
+	    # Linking convenience modules into shared libraries is allowed,
+	    # but linking other static libraries is non-portable.
+	    case " $dlpreconveniencelibs " in
+	    *" $deplib "*) ;;
+	    *)
+	      valid_a_lib=no
+	      case $deplibs_check_method in
+		match_pattern*)
+		  set dummy $deplibs_check_method; shift
+		  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+		  if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
+		    | $EGREP "$match_pattern_regex" > /dev/null; then
+		    valid_a_lib=yes
+		  fi
+		;;
+		pass_all)
+		  valid_a_lib=yes
+		;;
+	      esac
+	      if test "$valid_a_lib" != yes; then
+		echo
+		$ECHO "*** Warning: Trying to link with static lib archive $deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because the file extensions .$libext of this argument makes me believe"
+		echo "*** that it is just a static archive that I should not use here."
+	      else
+		echo
+		$ECHO "*** Warning: Linking the shared library $output against the"
+		$ECHO "*** static library $deplib is not portable!"
+		deplibs="$deplib $deplibs"
+	      fi
+	      ;;
+	    esac
+	    continue
+	    ;;
+	  prog)
+	    if test "$pass" != link; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    continue
+	    ;;
+	  esac # linkmode
+	  ;; # *.$libext
+	*.lo | *.$objext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	  elif test "$linkmode" = prog; then
+	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	      # If there is no dlopen support or we're linking statically,
+	      # we need to preload.
+	      newdlprefiles="$newdlprefiles $deplib"
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      newdlfiles="$newdlfiles $deplib"
+	    fi
+	  fi
+	  continue
+	  ;;
+	%DEPLIBS%)
+	  alldeplibs=yes
+	  continue
+	  ;;
+	esac # case $deplib
+
+	if test "$found" = yes || test -f "$lib"; then :
+	else
+	  func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
+	fi
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$lib" \
+	  || func_fatal_error "\`$lib' is not a valid libtool archive"
+
+	func_dirname "$lib" "" "."
+	ladir="$func_dirname_result"
+
+	dlname=
+	dlopen=
+	dlpreopen=
+	libdir=
+	library_names=
+	old_library=
+	inherited_linker_flags=
+	# If the library was installed with an old release of libtool,
+	# it will not redefine variables installed, or shouldnotlink
+	installed=yes
+	shouldnotlink=no
+	avoidtemprpath=
+
+
+	# Read the .la file
+	func_source "$lib"
+
+	# Convert "-framework foo" to "foo.ltframework"
+	if test -n "$inherited_linker_flags"; then
+	  tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
+	  for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+	    case " $new_inherited_linker_flags " in
+	      *" $tmp_inherited_linker_flag "*) ;;
+	      *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";;
+	    esac
+	  done
+	fi
+	dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	if test "$linkmode,$pass" = "lib,link" ||
+	   test "$linkmode,$pass" = "prog,scan" ||
+	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+	  test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+	  test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+	fi
+
+	if test "$pass" = conv; then
+	  # Only check for convenience libraries
+	  deplibs="$lib $deplibs"
+	  if test -z "$libdir"; then
+	    if test -z "$old_library"; then
+	      func_fatal_error "cannot find name of link library for \`$lib'"
+	    fi
+	    # It is a libtool convenience library, so add in its objects.
+	    convenience="$convenience $ladir/$objdir/$old_library"
+	    old_convenience="$old_convenience $ladir/$objdir/$old_library"
+	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
+	    func_fatal_error "\`$lib' is not a convenience library"
+	  fi
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    deplibs="$deplib $deplibs"
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+	  continue
+	fi # $pass = conv
+
+
+	# Get the name of the library we link against.
+	linklib=
+	for l in $old_library $library_names; do
+	  linklib="$l"
+	done
+	if test -z "$linklib"; then
+	  func_fatal_error "cannot find name of link library for \`$lib'"
+	fi
+
+	# This library was specified with -dlopen.
+	if test "$pass" = dlopen; then
+	  if test -z "$libdir"; then
+	    func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
+	  fi
+	  if test -z "$dlname" ||
+	     test "$dlopen_support" != yes ||
+	     test "$build_libtool_libs" = no; then
+	    # If there is no dlname, no dlopen support or we're linking
+	    # statically, we need to preload.  We also need to preload any
+	    # dependent libraries so libltdl's deplib preloader doesn't
+	    # bomb out in the load deplibs phase.
+	    dlprefiles="$dlprefiles $lib $dependency_libs"
+	  else
+	    newdlfiles="$newdlfiles $lib"
+	  fi
+	  continue
+	fi # $pass = dlopen
+
+	# We need an absolute path.
+	case $ladir in
+	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+	*)
+	  abs_ladir=`cd "$ladir" && pwd`
+	  if test -z "$abs_ladir"; then
+	    func_warning "cannot determine absolute directory name of \`$ladir'"
+	    func_warning "passing it literally to the linker, although it might fail"
+	    abs_ladir="$ladir"
+	  fi
+	  ;;
+	esac
+	func_basename "$lib"
+	laname="$func_basename_result"
+
+	# Find the relevant object directory and library name.
+	if test "X$installed" = Xyes; then
+	  if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    func_warning "library \`$lib' was moved."
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    libdir="$abs_ladir"
+	  else
+	    dir="$libdir"
+	    absdir="$libdir"
+	  fi
+	  test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+	else
+	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  else
+	    dir="$ladir/$objdir"
+	    absdir="$abs_ladir/$objdir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  fi
+	fi # $installed = yes
+	func_stripname 'lib' '.la' "$laname"
+	name=$func_stripname_result
+
+	# This library was specified with -dlpreopen.
+	if test "$pass" = dlpreopen; then
+	  if test -z "$libdir" && test "$linkmode" = prog; then
+	    func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
+	  fi
+	  # Prefer using a static library (so that no silly _DYNAMIC symbols
+	  # are required to link).
+	  if test -n "$old_library"; then
+	    newdlprefiles="$newdlprefiles $dir/$old_library"
+	    # Keep a list of preopened convenience libraries to check
+	    # that they are being used correctly in the link pass.
+	    test -z "$libdir" && \
+		dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library"
+	  # Otherwise, use the dlname, so that lt_dlopen finds it.
+	  elif test -n "$dlname"; then
+	    newdlprefiles="$newdlprefiles $dir/$dlname"
+	  else
+	    newdlprefiles="$newdlprefiles $dir/$linklib"
+	  fi
+	fi # $pass = dlpreopen
+
+	if test -z "$libdir"; then
+	  # Link the convenience library
+	  if test "$linkmode" = lib; then
+	    deplibs="$dir/$old_library $deplibs"
+	  elif test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$dir/$old_library $compile_deplibs"
+	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
+	  else
+	    deplibs="$lib $deplibs" # used for prog,scan pass
+	  fi
+	  continue
+	fi
+
+
+	if test "$linkmode" = prog && test "$pass" != link; then
+	  newlib_search_path="$newlib_search_path $ladir"
+	  deplibs="$lib $deplibs"
+
+	  linkalldeplibs=no
+	  if test "$link_all_deplibs" != no || test -z "$library_names" ||
+	     test "$build_libtool_libs" = no; then
+	    linkalldeplibs=yes
+	  fi
+
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    case $deplib in
+	    -L*) func_stripname '-L' '' "$deplib"
+	         newlib_search_path="$newlib_search_path $func_stripname_result"
+		 ;;
+	    esac
+	    # Need to link against all dependency_libs?
+	    if test "$linkalldeplibs" = yes; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      # Need to hardcode shared library paths
+	      # or/and link against static libraries
+	      newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done # for deplib
+	  continue
+	fi # $linkmode = prog...
+
+	if test "$linkmode,$pass" = "prog,link"; then
+	  if test -n "$library_names" &&
+	     { { test "$prefer_static_libs" = no ||
+	         test "$prefer_static_libs,$installed" = "built,yes"; } ||
+	       test -z "$old_library"; }; then
+	    # We need to hardcode the library path
+	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+	      # Make sure the rpath contains only unique directories.
+	      case "$temp_rpath:" in
+	      *"$absdir:"*) ;;
+	      *) temp_rpath="$temp_rpath$absdir:" ;;
+	      esac
+	    fi
+
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi # $linkmode,$pass = prog,link...
+
+	  if test "$alldeplibs" = yes &&
+	     { test "$deplibs_check_method" = pass_all ||
+	       { test "$build_libtool_libs" = yes &&
+		 test -n "$library_names"; }; }; then
+	    # We only need to search for static libraries
+	    continue
+	  fi
+	fi
+
+	link_static=no # Whether the deplib will be linked statically
+	use_static_libs=$prefer_static_libs
+	if test "$use_static_libs" = built && test "$installed" = yes; then
+	  use_static_libs=no
+	fi
+	if test -n "$library_names" &&
+	   { test "$use_static_libs" = no || test -z "$old_library"; }; then
+	  case $host in
+	  *cygwin* | *mingw* | *cegcc*)
+	      # No point in relinking DLLs because paths are not encoded
+	      notinst_deplibs="$notinst_deplibs $lib"
+	      need_relink=no
+	    ;;
+	  *)
+	    if test "$installed" = no; then
+	      notinst_deplibs="$notinst_deplibs $lib"
+	      need_relink=yes
+	    fi
+	    ;;
+	  esac
+	  # This is a shared library
+
+	  # Warn about portability, can't link against -module's on some
+	  # systems (darwin).  Don't bleat about dlopened modules though!
+	  dlopenmodule=""
+	  for dlpremoduletest in $dlprefiles; do
+	    if test "X$dlpremoduletest" = "X$lib"; then
+	      dlopenmodule="$dlpremoduletest"
+	      break
+	    fi
+	  done
+	  if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
+	    echo
+	    if test "$linkmode" = prog; then
+	      $ECHO "*** Warning: Linking the executable $output against the loadable module"
+	    else
+	      $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+	    fi
+	    $ECHO "*** $linklib is not portable!"
+	  fi
+	  if test "$linkmode" = lib &&
+	     test "$hardcode_into_libs" = yes; then
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi
+
+	  if test -n "$old_archive_from_expsyms_cmds"; then
+	    # figure out the soname
+	    set dummy $library_names
+	    shift
+	    realname="$1"
+	    shift
+	    eval "libname=\"$libname_spec\""
+	    # use dlname if we got it. it's perfectly good, no?
+	    if test -n "$dlname"; then
+	      soname="$dlname"
+	    elif test -n "$soname_spec"; then
+	      # bleh windows
+	      case $host in
+	      *cygwin* | mingw* | *cegcc*)
+	        func_arith $current - $age
+		major=$func_arith_result
+		versuffix="-$major"
+		;;
+	      esac
+	      eval "soname=\"$soname_spec\""
+	    else
+	      soname="$realname"
+	    fi
+
+	    # Make a new name for the extract_expsyms_cmds to use
+	    soroot="$soname"
+	    func_basename "$soroot"
+	    soname="$func_basename_result"
+	    func_stripname 'lib' '.dll' "$soname"
+	    newlib=libimp-$func_stripname_result.a
+
+	    # If the library has no export list, then create one now
+	    if test -f "$output_objdir/$soname-def"; then :
+	    else
+	      func_verbose "extracting exported symbol list from \`$soname'"
+	      func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+	    fi
+
+	    # Create $newlib
+	    if test -f "$output_objdir/$newlib"; then :; else
+	      func_verbose "generating import library for \`$soname'"
+	      func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+	    fi
+	    # make sure the library variables are pointing to the new library
+	    dir=$output_objdir
+	    linklib=$newlib
+	  fi # test -n "$old_archive_from_expsyms_cmds"
+
+	  if test "$linkmode" = prog || test "$mode" != relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    lib_linked=yes
+	    case $hardcode_action in
+	    immediate | unsupported)
+	      if test "$hardcode_direct" = no; then
+		add="$dir/$linklib"
+		case $host in
+		  *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+		  *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+		  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+		    *-*-unixware7*) add_dir="-L$dir" ;;
+		  *-*-darwin* )
+		    # if the lib is a (non-dlopened) module then we can not
+		    # link against it, someone is ignoring the earlier warnings
+		    if /usr/bin/file -L $add 2> /dev/null |
+			 $GREP ": [^:]* bundle" >/dev/null ; then
+		      if test "X$dlopenmodule" != "X$lib"; then
+			$ECHO "*** Warning: lib $linklib is a module, not a shared library"
+			if test -z "$old_library" ; then
+			  echo
+			  echo "*** And there doesn't seem to be a static archive available"
+			  echo "*** The link will probably fail, sorry"
+			else
+			  add="$dir/$old_library"
+			fi
+		      elif test -n "$old_library"; then
+			add="$dir/$old_library"
+		      fi
+		    fi
+		esac
+	      elif test "$hardcode_minus_L" = no; then
+		case $host in
+		*-*-sunos*) add_shlibpath="$dir" ;;
+		esac
+		add_dir="-L$dir"
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = no; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    relink)
+	      if test "$hardcode_direct" = yes &&
+	         test "$hardcode_direct_absolute" = no; then
+		add="$dir/$linklib"
+	      elif test "$hardcode_minus_L" = yes; then
+		add_dir="-L$absdir"
+		# Try looking first in the location we're being installed to.
+		if test -n "$inst_prefix_dir"; then
+		  case $libdir in
+		    [\\/]*)
+		      add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		      ;;
+		  esac
+		fi
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = yes; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    *) lib_linked=no ;;
+	    esac
+
+	    if test "$lib_linked" != yes; then
+	      func_fatal_configuration "unsupported hardcode properties"
+	    fi
+
+	    if test -n "$add_shlibpath"; then
+	      case :$compile_shlibpath: in
+	      *":$add_shlibpath:"*) ;;
+	      *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+	      esac
+	    fi
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	      if test "$hardcode_direct" != yes &&
+		 test "$hardcode_minus_L" != yes &&
+		 test "$hardcode_shlibpath_var" = yes; then
+		case :$finalize_shlibpath: in
+		*":$libdir:"*) ;;
+		*) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+		esac
+	      fi
+	    fi
+	  fi
+
+	  if test "$linkmode" = prog || test "$mode" = relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    # Finalize command for both is simple: just hardcode it.
+	    if test "$hardcode_direct" = yes &&
+	       test "$hardcode_direct_absolute" = no; then
+	      add="$libdir/$linklib"
+	    elif test "$hardcode_minus_L" = yes; then
+	      add_dir="-L$libdir"
+	      add="-l$name"
+	    elif test "$hardcode_shlibpath_var" = yes; then
+	      case :$finalize_shlibpath: in
+	      *":$libdir:"*) ;;
+	      *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+	      esac
+	      add="-l$name"
+	    elif test "$hardcode_automatic" = yes; then
+	      if test -n "$inst_prefix_dir" &&
+		 test -f "$inst_prefix_dir$libdir/$linklib" ; then
+		add="$inst_prefix_dir$libdir/$linklib"
+	      else
+		add="$libdir/$linklib"
+	      fi
+	    else
+	      # We cannot seem to hardcode it, guess we'll fake it.
+	      add_dir="-L$libdir"
+	      # Try looking first in the location we're being installed to.
+	      if test -n "$inst_prefix_dir"; then
+		case $libdir in
+		  [\\/]*)
+		    add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		    ;;
+		esac
+	      fi
+	      add="-l$name"
+	    fi
+
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	    fi
+	  fi
+	elif test "$linkmode" = prog; then
+	  # Here we assume that one of hardcode_direct or hardcode_minus_L
+	  # is not unsupported.  This is valid on all known static and
+	  # shared platforms.
+	  if test "$hardcode_direct" != unsupported; then
+	    test -n "$old_library" && linklib="$old_library"
+	    compile_deplibs="$dir/$linklib $compile_deplibs"
+	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
+	  else
+	    compile_deplibs="-l$name -L$dir $compile_deplibs"
+	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+	  fi
+	elif test "$build_libtool_libs" = yes; then
+	  # Not a shared library
+	  if test "$deplibs_check_method" != pass_all; then
+	    # We're trying link a shared library against a static one
+	    # but the system doesn't support it.
+
+	    # Just print a warning and add the library to dependency_libs so
+	    # that the program can be linked against the static library.
+	    echo
+	    $ECHO "*** Warning: This system can not link to static lib archive $lib."
+	    echo "*** I have the capability to make that library automatically link in when"
+	    echo "*** you link to this library.  But I can only do this if you have a"
+	    echo "*** shared version of the library, which you do not appear to have."
+	    if test "$module" = yes; then
+	      echo "*** But as you try to build a module library, libtool will still create "
+	      echo "*** a static module, that should work as long as the dlopening application"
+	      echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+	      if test -z "$global_symbol_pipe"; then
+		echo
+		echo "*** However, this would only work if libtool was able to extract symbol"
+		echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+		echo "*** not find such a program.  So, this module is probably useless."
+		echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	      fi
+	      if test "$build_old_libs" = no; then
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  else
+	    deplibs="$dir/$old_library $deplibs"
+	    link_static=yes
+	  fi
+	fi # link shared/static library?
+
+	if test "$linkmode" = lib; then
+	  if test -n "$dependency_libs" &&
+	     { test "$hardcode_into_libs" != yes ||
+	       test "$build_old_libs" = yes ||
+	       test "$link_static" = yes; }; then
+	    # Extract -R from dependency_libs
+	    temp_deplibs=
+	    for libdir in $dependency_libs; do
+	      case $libdir in
+	      -R*) func_stripname '-R' '' "$libdir"
+	           temp_xrpath=$func_stripname_result
+		   case " $xrpath " in
+		   *" $temp_xrpath "*) ;;
+		   *) xrpath="$xrpath $temp_xrpath";;
+		   esac;;
+	      *) temp_deplibs="$temp_deplibs $libdir";;
+	      esac
+	    done
+	    dependency_libs="$temp_deplibs"
+	  fi
+
+	  newlib_search_path="$newlib_search_path $absdir"
+	  # Link against this library
+	  test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+	  # ... and its dependency_libs
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    newdependency_libs="$deplib $newdependency_libs"
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+
+	  if test "$link_all_deplibs" != no; then
+	    # Add the search paths of all dependency libraries
+	    for deplib in $dependency_libs; do
+	      path=
+	      case $deplib in
+	      -L*) path="$deplib" ;;
+	      *.la)
+	        func_dirname "$deplib" "" "."
+		dir="$func_dirname_result"
+		# We need an absolute path.
+		case $dir in
+		[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+		*)
+		  absdir=`cd "$dir" && pwd`
+		  if test -z "$absdir"; then
+		    func_warning "cannot determine absolute directory name of \`$dir'"
+		    absdir="$dir"
+		  fi
+		  ;;
+		esac
+		if $GREP "^installed=no" $deplib > /dev/null; then
+		case $host in
+		*-*-darwin*)
+		  depdepl=
+		  deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+		  if test -n "$deplibrary_names" ; then
+		    for tmp in $deplibrary_names ; do
+		      depdepl=$tmp
+		    done
+		    if test -f "$absdir/$objdir/$depdepl" ; then
+		      depdepl="$absdir/$objdir/$depdepl"
+		      darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+                      if test -z "$darwin_install_name"; then
+                          darwin_install_name=`${OTOOL64} -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
+                      fi
+		      compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+		      linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}"
+		      path=
+		    fi
+		  fi
+		  ;;
+		*)
+		  path="-L$absdir/$objdir"
+		  ;;
+		esac
+		else
+		  libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		  test -z "$libdir" && \
+		    func_fatal_error "\`$deplib' is not a valid libtool archive"
+		  test "$absdir" != "$libdir" && \
+		    func_warning "\`$deplib' seems to be moved"
+
+		  path="-L$absdir"
+		fi
+		;;
+	      esac
+	      case " $deplibs " in
+	      *" $path "*) ;;
+	      *) deplibs="$path $deplibs" ;;
+	      esac
+	    done
+	  fi # link_all_deplibs != no
+	fi # linkmode = lib
+      done # for deplib in $libs
+      if test "$pass" = link; then
+	if test "$linkmode" = "prog"; then
+	  compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+	  finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+	else
+	  compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	fi
+      fi
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+	# Link the dlpreopened libraries before other libraries
+	for deplib in $save_deplibs; do
+	  deplibs="$deplib $deplibs"
+	done
+      fi
+      if test "$pass" != dlopen; then
+	if test "$pass" != conv; then
+	  # Make sure lib_search_path contains only unique directories.
+	  lib_search_path=
+	  for dir in $newlib_search_path; do
+	    case "$lib_search_path " in
+	    *" $dir "*) ;;
+	    *) lib_search_path="$lib_search_path $dir" ;;
+	    esac
+	  done
+	  newlib_search_path=
+	fi
+
+	if test "$linkmode,$pass" != "prog,link"; then
+	  vars="deplibs"
+	else
+	  vars="compile_deplibs finalize_deplibs"
+	fi
+	for var in $vars dependency_libs; do
+	  # Add libraries to $var in reverse order
+	  eval tmp_libs=\$$var
+	  new_libs=
+	  for deplib in $tmp_libs; do
+	    # FIXME: Pedantically, this is the right thing to do, so
+	    #        that some nasty dependency loop isn't accidentally
+	    #        broken:
+	    #new_libs="$deplib $new_libs"
+	    # Pragmatically, this seems to cause very few problems in
+	    # practice:
+	    case $deplib in
+	    -L*) new_libs="$deplib $new_libs" ;;
+	    -R*) ;;
+	    *)
+	      # And here is the reason: when a library appears more
+	      # than once as an explicit dependence of a library, or
+	      # is implicitly linked in more than once by the
+	      # compiler, it is considered special, and multiple
+	      # occurrences thereof are not removed.  Compare this
+	      # with having the same library being listed as a
+	      # dependency of multiple other libraries: in this case,
+	      # we know (pedantically, we assume) the library does not
+	      # need to be listed more than once, so we keep only the
+	      # last copy.  This is not always right, but it is rare
+	      # enough that we require users that really mean to play
+	      # such unportable linking tricks to link the library
+	      # using -Wl,-lname, so that libtool does not consider it
+	      # for duplicate removal.
+	      case " $specialdeplibs " in
+	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
+	      *)
+		case " $new_libs " in
+		*" $deplib "*) ;;
+		*) new_libs="$deplib $new_libs" ;;
+		esac
+		;;
+	      esac
+	      ;;
+	    esac
+	  done
+	  tmp_libs=
+	  for deplib in $new_libs; do
+	    case $deplib in
+	    -L*)
+	      case " $tmp_libs " in
+	      *" $deplib "*) ;;
+	      *) tmp_libs="$tmp_libs $deplib" ;;
+	      esac
+	      ;;
+	    *) tmp_libs="$tmp_libs $deplib" ;;
+	    esac
+	  done
+	  eval $var=\$tmp_libs
+	done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+	case " $predeps $postdeps $compiler_lib_search_path " in
+	*" $i "*)
+	  i=""
+	  ;;
+	esac
+	if test -n "$i" ; then
+	  tmp_libs="$tmp_libs $i"
+	fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+    fi
+    if test "$linkmode" = prog || test "$linkmode" = lib; then
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for archives"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for archives" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for archives"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for archives"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info/-version-number' is ignored for archives"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for archives"
+
+      test -n "$export_symbols$export_symbols_regex" && \
+	func_warning "\`-export-symbols' is ignored for archives"
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs="$objs$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+	func_stripname 'lib' '.la' "$outputname"
+	name=$func_stripname_result
+	eval "shared_ext=\"$shrext_cmds\""
+	eval "libname=\"$libname_spec\""
+	;;
+      *)
+	test "$module" = no && \
+	  func_fatal_help "libtool library \`$output' must begin with \`lib'"
+
+	if test "$need_lib_prefix" != no; then
+	  # Add the "lib" prefix for modules if required
+	  func_stripname '' '.la' "$outputname"
+	  name=$func_stripname_result
+	  eval "shared_ext=\"$shrext_cmds\""
+	  eval "libname=\"$libname_spec\""
+	else
+	  func_stripname '' '.la' "$outputname"
+	  libname=$func_stripname_result
+	fi
+	;;
+      esac
+
+      if test -n "$objs"; then
+	if test "$deplibs_check_method" != pass_all; then
+	  func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
+	else
+	  echo
+	  $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+	  $ECHO "*** objects $objs is not portable!"
+	  libobjs="$libobjs $objs"
+	fi
+      fi
+
+      test "$dlself" != no && \
+	func_warning "\`-dlopen self' is ignored for libtool libraries"
+
+      set dummy $rpath
+      shift
+      test "$#" -gt 1 && \
+	func_warning "ignoring multiple \`-rpath's for a libtool library"
+
+      install_libdir="$1"
+
+      oldlibs=
+      if test -z "$rpath"; then
+	if test "$build_libtool_libs" = yes; then
+	  # Building a libtool convenience library.
+	  # Some compilers have problems with a `.al' extension so
+	  # convenience libraries should have the same extension an
+	  # archive normally would.
+	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
+	  build_libtool_libs=convenience
+	  build_old_libs=yes
+	fi
+
+	test -n "$vinfo" && \
+	  func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
+
+	test -n "$release" && \
+	  func_warning "\`-release' is ignored for convenience libraries"
+      else
+
+	# Parse the version information argument.
+	save_ifs="$IFS"; IFS=':'
+	set dummy $vinfo 0 0 0
+	shift
+	IFS="$save_ifs"
+
+	test -n "$7" && \
+	  func_fatal_help "too many parameters to \`-version-info'"
+
+	# convert absolute version numbers to libtool ages
+	# this retains compatibility with .la files and attempts
+	# to make the code below a bit more comprehensible
+
+	case $vinfo_number in
+	yes)
+	  number_major="$1"
+	  number_minor="$2"
+	  number_revision="$3"
+	  #
+	  # There are really only two kinds -- those that
+	  # use the current revision as the major version
+	  # and those that subtract age and use age as
+	  # a minor version.  But, then there is irix
+	  # which has an extra 1 added just for fun
+	  #
+	  case $version_type in
+	  darwin|linux|osf|windows|none)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_revision"
+	    ;;
+	  freebsd-aout|freebsd-elf|qnx|sunos)
+	    current="$number_major"
+	    revision="$number_minor"
+	    age="0"
+	    ;;
+	  irix|nonstopux)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_minor"
+	    lt_irix_increment=no
+	    ;;
+	  esac
+	  ;;
+	no)
+	  current="$1"
+	  revision="$2"
+	  age="$3"
+	  ;;
+	esac
+
+	# Check that each of the things are valid numbers.
+	case $current in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "CURRENT \`$current' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $revision in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "REVISION \`$revision' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $age in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "AGE \`$age' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	if test "$age" -gt "$current"; then
+	  func_error "AGE \`$age' is greater than the current interface number \`$current'"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	fi
+
+	# Calculate the version variables.
+	major=
+	versuffix=
+	verstring=
+	case $version_type in
+	none) ;;
+
+	darwin)
+	  # Like Linux, but with the current version available in
+	  # verstring for coding it into the library header
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  # Darwin ld doesn't like 0 for these options...
+	  func_arith $current + 1
+	  minor_current=$func_arith_result
+	  xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+	  ;;
+
+	freebsd-aout)
+	  major=".$current"
+	  versuffix=".$current.$revision";
+	  ;;
+
+	freebsd-elf)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	irix | nonstopux)
+	  if test "X$lt_irix_increment" = "Xno"; then
+	    func_arith $current - $age
+	  else
+	    func_arith $current - $age + 1
+	  fi
+	  major=$func_arith_result
+
+	  case $version_type in
+	    nonstopux) verstring_prefix=nonstopux ;;
+	    *)         verstring_prefix=sgi ;;
+	  esac
+	  verstring="$verstring_prefix$major.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$revision
+	  while test "$loop" -ne 0; do
+	    func_arith $revision - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring_prefix$major.$iface:$verstring"
+	  done
+
+	  # Before this point, $major must not contain `.'.
+	  major=.$major
+	  versuffix="$major.$revision"
+	  ;;
+
+	linux)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  ;;
+
+	osf)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix=".$current.$age.$revision"
+	  verstring="$current.$age.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$age
+	  while test "$loop" -ne 0; do
+	    func_arith $current - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring:${iface}.0"
+	  done
+
+	  # Make executables depend on our current version.
+	  verstring="$verstring:${current}.0"
+	  ;;
+
+	qnx)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	sunos)
+	  major=".$current"
+	  versuffix=".$current.$revision"
+	  ;;
+
+	windows)
+	  # Use '-' rather than '.', since we only want one
+	  # extension on DOS 8.3 filesystems.
+	  func_arith $current - $age
+	  major=$func_arith_result
+	  versuffix="-$major"
+	  ;;
+
+	*)
+	  func_fatal_configuration "unknown library version type \`$version_type'"
+	  ;;
+	esac
+
+	# Clear the version info if we defaulted, and they specified a release.
+	if test -z "$vinfo" && test -n "$release"; then
+	  major=
+	  case $version_type in
+	  darwin)
+	    # we can't check for "0.0" in archive_cmds due to quoting
+	    # problems, so we reset it completely
+	    verstring=
+	    ;;
+	  *)
+	    verstring="0.0"
+	    ;;
+	  esac
+	  if test "$need_version" = no; then
+	    versuffix=
+	  else
+	    versuffix=".0.0"
+	  fi
+	fi
+
+	# Remove version info from name if versioning should be avoided
+	if test "$avoid_version" = yes && test "$need_version" = no; then
+	  major=
+	  versuffix=
+	  verstring=""
+	fi
+
+	# Check to see if the archive will have undefined symbols.
+	if test "$allow_undefined" = yes; then
+	  if test "$allow_undefined_flag" = unsupported; then
+	    func_warning "undefined symbols not allowed in $host shared libraries"
+	    build_libtool_libs=no
+	    build_old_libs=yes
+	  fi
+	else
+	  # Don't allow undefined symbols.
+	  allow_undefined_flag="$no_undefined_flag"
+	fi
+
+      fi
+
+      func_generate_dlsyms "$libname" "$libname" "yes"
+      libobjs="$libobjs $symfileobj"
+      test "X$libobjs" = "X " && libobjs=
+
+      if test "$mode" != relink; then
+	# Remove our outputs, but don't remove object files since they
+	# may have been created when compiling PIC objects.
+	removelist=
+	tempremovelist=`$ECHO "$output_objdir/*"`
+	for p in $tempremovelist; do
+	  case $p in
+	    *.$objext | *.gcno)
+	       ;;
+	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+	       if test "X$precious_files_regex" != "X"; then
+		 if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+		 then
+		   continue
+		 fi
+	       fi
+	       removelist="$removelist $p"
+	       ;;
+	    *) ;;
+	  esac
+	done
+	test -n "$removelist" && \
+	  func_show_eval "${RM}r \$removelist"
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+	oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+	# Transform .lo files to .o files.
+	oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #	lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
+      #	deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
+      #	dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	temp_xrpath=
+	for libdir in $xrpath; do
+	  temp_xrpath="$temp_xrpath -R$libdir"
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+	if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+	  dependency_libs="$temp_xrpath $dependency_libs"
+	fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+	case " $dlprefiles $dlfiles " in
+	*" $lib "*) ;;
+	*) dlfiles="$dlfiles $lib" ;;
+	esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+	case "$dlprefiles " in
+	*" $lib "*) ;;
+	*) dlprefiles="$dlprefiles $lib" ;;
+	esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+	if test -n "$rpath"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
+	    # these systems don't actually have a c library (as such)!
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C library is in the System framework
+	    deplibs="$deplibs System.ltframework"
+	    ;;
+	  *-*-netbsd*)
+	    # Don't link with libc until the a.out ld.so is fixed.
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    ;;
+	  *)
+	    # Add libc to deplibs on all other systems if necessary.
+	    if test "$build_libtool_need_lc" = "yes"; then
+	      deplibs="$deplibs -lc"
+	    fi
+	    ;;
+	  esac
+	fi
+
+	# Transform deplibs into only deplibs that can be linked in shared.
+	name_save=$name
+	libname_save=$libname
+	release_save=$release
+	versuffix_save=$versuffix
+	major_save=$major
+	# I'm not sure if I'm treating the release correctly.  I think
+	# release should show up in the -l (ie -lgmp5) so we don't want to
+	# add it in twice.  Is that correct?
+	release=""
+	versuffix=""
+	major=""
+	newdeplibs=
+	droppeddeps=no
+	case $deplibs_check_method in
+	pass_all)
+	  # Don't check for shared/static.  Everything works.
+	  # This might be a little naive.  We might want to check
+	  # whether the library exists or not.  But this is on
+	  # osf3 & osf4 and I'm not really sure... Just
+	  # implementing what was already the behavior.
+	  newdeplibs=$deplibs
+	  ;;
+	test_compile)
+	  # This code stresses the "libraries are programs" paradigm to its
+	  # limits. Maybe even breaks it.  We compile a program, linking it
+	  # against the deplibs as a proxy for the library.  Then we can check
+	  # whether they linked in statically or dynamically with ldd.
+	  $opt_dry_run || $RM conftest.c
+	  cat > conftest.c <<EOF
+	  int main() { return 0; }
+EOF
+	  $opt_dry_run || $RM conftest
+	  if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+	    ldd_output=`ldd conftest`
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		  case " $predeps $postdeps " in
+		  *" $i "*)
+		    newdeplibs="$newdeplibs $i"
+		    i=""
+		    ;;
+		  esac
+		fi
+		if test -n "$i" ; then
+		  eval "libname=\"$libname_spec\""
+		  eval "deplib_matches=\"$library_names_spec\""
+		  set dummy $deplib_matches; shift
+		  deplib_match=$1
+		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		    newdeplibs="$newdeplibs $i"
+		  else
+		    droppeddeps=yes
+		    echo
+		    $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		    echo "*** I have the capability to make that library automatically link in when"
+		    echo "*** you link to this library.  But I can only do this if you have a"
+		    echo "*** shared version of the library, which I believe you do not have"
+		    echo "*** because a test_compile did reveal that the linker did not use it for"
+		    echo "*** its dynamic dependency list that programs get resolved with at runtime."
+		  fi
+		fi
+		;;
+	      *)
+		newdeplibs="$newdeplibs $i"
+		;;
+	      esac
+	    done
+	  else
+	    # Error occurred in the first compile.  Let's try to salvage
+	    # the situation: Compile a separate program for each library.
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		$opt_dry_run || $RM conftest
+		if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+		  ldd_output=`ldd conftest`
+		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		    case " $predeps $postdeps " in
+		    *" $i "*)
+		      newdeplibs="$newdeplibs $i"
+		      i=""
+		      ;;
+		    esac
+		  fi
+		  if test -n "$i" ; then
+		    eval "libname=\"$libname_spec\""
+		    eval "deplib_matches=\"$library_names_spec\""
+		    set dummy $deplib_matches; shift
+		    deplib_match=$1
+		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		      newdeplibs="$newdeplibs $i"
+		    else
+		      droppeddeps=yes
+		      echo
+		      $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		      echo "*** I have the capability to make that library automatically link in when"
+		      echo "*** you link to this library.  But I can only do this if you have a"
+		      echo "*** shared version of the library, which you do not appear to have"
+		      echo "*** because a test_compile did reveal that the linker did not use this one"
+		      echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+		    fi
+		  fi
+		else
+		  droppeddeps=yes
+		  echo
+		  $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+		  echo "*** make it link in!  You will probably need to install it or some"
+		  echo "*** library that it depends on before this library will be fully"
+		  echo "*** functional.  Installing it before continuing would be even better."
+		fi
+		;;
+	      *)
+		newdeplibs="$newdeplibs $i"
+		;;
+	      esac
+	    done
+	  fi
+	  ;;
+	file_magic*)
+	  set dummy $deplibs_check_method; shift
+	  file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		eval "libname=\"$libname_spec\""
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		      # Follow soft links.
+		      if ls -lLd "$potent_lib" 2>/dev/null |
+			 $GREP " -> " >/dev/null; then
+			continue
+		      fi
+		      # The statement above tries to avoid entering an
+		      # endless loop below, in case of cyclic links.
+		      # We might still enter an endless loop, since a link
+		      # loop can be closed while we follow links,
+		      # but so what?
+		      potlib="$potent_lib"
+		      while test -h "$potlib" 2>/dev/null; do
+			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+			case $potliblink in
+			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+			*) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";;
+			esac
+		      done
+		      if eval "$file_magic_cmd \"\$potlib\"" 2>/dev/null |
+			 $SED -e 10q |
+			 $EGREP "$file_magic_regex" > /dev/null; then
+			newdeplibs="$newdeplibs $a_deplib"
+			a_deplib=""
+			break 2
+		      fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		echo
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a file magic. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	match_pattern*)
+	  set dummy $deplibs_check_method; shift
+	  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		eval "libname=\"$libname_spec\""
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		    potlib="$potent_lib" # see symlink-check above in file_magic test
+		    if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
+		       $EGREP "$match_pattern_regex" > /dev/null; then
+		      newdeplibs="$newdeplibs $a_deplib"
+		      a_deplib=""
+		      break 2
+		    fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		echo
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a regex pattern. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	none | unknown | *)
+	  newdeplibs=""
+	  tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
+	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	    for i in $predeps $postdeps ; do
+	      # can't use Xsed below, because $i might contain '/'
+	      tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"`
+	    done
+	  fi
+	  case $tmp_deplibs in
+	  *[!\	\ ]*)
+	    echo
+	    if test "X$deplibs_check_method" = "Xnone"; then
+	      echo "*** Warning: inter-library dependencies are not supported in this platform."
+	    else
+	      echo "*** Warning: inter-library dependencies are not known to be supported."
+	    fi
+	    echo "*** All declared inter-library dependencies are being dropped."
+	    droppeddeps=yes
+	    ;;
+	  esac
+	  ;;
+	esac
+	versuffix=$versuffix_save
+	major=$major_save
+	release=$release_save
+	libname=$libname_save
+	name=$name_save
+
+	case $host in
+	*-*-rhapsody* | *-*-darwin1.[012])
+	  # On Rhapsody replace the C library with the System framework
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
+	  ;;
+	esac
+
+	if test "$droppeddeps" = yes; then
+	  if test "$module" = yes; then
+	    echo
+	    echo "*** Warning: libtool could not satisfy all declared inter-library"
+	    $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
+	    echo "*** a static module, that should work as long as the dlopening"
+	    echo "*** application is linked with the -dlopen flag."
+	    if test -z "$global_symbol_pipe"; then
+	      echo
+	      echo "*** However, this would only work if libtool was able to extract symbol"
+	      echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+	      echo "*** not find such a program.  So, this module is probably useless."
+	      echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	    fi
+	    if test "$build_old_libs" = no; then
+	      oldlibs="$output_objdir/$libname.$libext"
+	      build_libtool_libs=module
+	      build_old_libs=yes
+	    else
+	      build_libtool_libs=no
+	    fi
+	  else
+	    echo "*** The inter-library dependencies that have been dropped here will be"
+	    echo "*** automatically added whenever a program is linked with this library"
+	    echo "*** or is declared to -dlopen it."
+
+	    if test "$allow_undefined" = no; then
+	      echo
+	      echo "*** Since this library must not contain undefined symbols,"
+	      echo "*** because either the platform does not support them or"
+	      echo "*** it was explicitly requested with -no-undefined,"
+	      echo "*** libtool will only create a static version of it."
+	      if test "$build_old_libs" = no; then
+		oldlibs="$output_objdir/$libname.$libext"
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  fi
+	fi
+	# Done checking deplibs!
+	deplibs=$newdeplibs
+      fi
+      # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+      case $host in
+	*-*-darwin*)
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  ;;
+      esac
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs="$new_libs -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs="$new_libs $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs="$new_libs $deplib" ;;
+	esac
+      done
+      deplibs="$new_libs"
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+	if test "$hardcode_into_libs" = yes; then
+	  # Hardcode the library paths
+	  hardcode_libdirs=
+	  dep_rpath=
+	  rpath="$finalize_rpath"
+	  test "$mode" != relink && rpath="$compile_rpath$rpath"
+	  for libdir in $rpath; do
+	    if test -n "$hardcode_libdir_flag_spec"; then
+	      if test -n "$hardcode_libdir_separator"; then
+		if test -z "$hardcode_libdirs"; then
+		  hardcode_libdirs="$libdir"
+		else
+		  # Just accumulate the unique libdirs.
+		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		    ;;
+		  *)
+		    hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		    ;;
+		  esac
+		fi
+	      else
+		eval "flag=\"$hardcode_libdir_flag_spec\""
+		dep_rpath="$dep_rpath $flag"
+	      fi
+	    elif test -n "$runpath_var"; then
+	      case "$perm_rpath " in
+	      *" $libdir "*) ;;
+	      *) perm_rpath="$perm_rpath $libdir" ;;
+	      esac
+	    fi
+	  done
+	  # Substitute the hardcoded libdirs into the rpath.
+	  if test -n "$hardcode_libdir_separator" &&
+	     test -n "$hardcode_libdirs"; then
+	    libdir="$hardcode_libdirs"
+	    if test -n "$hardcode_libdir_flag_spec_ld"; then
+	      eval "dep_rpath=\"$hardcode_libdir_flag_spec_ld\""
+	    else
+	      eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
+	    fi
+	  fi
+	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
+	    # We should set the runpath_var.
+	    rpath=
+	    for dir in $perm_rpath; do
+	      rpath="$rpath$dir:"
+	    done
+	    eval $runpath_var=\$rpath\$$runpath_var
+	    export $runpath_var
+	  fi
+	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+	fi
+
+	shlibpath="$finalize_shlibpath"
+	test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+	if test -n "$shlibpath"; then
+	  eval $shlibpath_var=\$shlibpath\$$shlibpath_var
+	  export $shlibpath_var
+	fi
+
+	# Get the real and link names of the library.
+	eval "shared_ext=\"$shrext_cmds\""
+	eval "library_names=\"$library_names_spec\""
+	set dummy $library_names
+	shift
+	realname="$1"
+	shift
+
+	if test -n "$soname_spec"; then
+	  eval "soname=\"$soname_spec\""
+	else
+	  soname="$realname"
+	fi
+	if test -z "$dlname"; then
+	  dlname=$soname
+	fi
+
+	lib="$output_objdir/$realname"
+	linknames=
+	for link
+	do
+	  linknames="$linknames $link"
+	done
+
+	# Use standard objects if they are pic
+	test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	test "X$libobjs" = "X " && libobjs=
+
+	delfiles=
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+	  export_symbols="$output_objdir/$libname.uexp"
+	  delfiles="$delfiles $export_symbols"
+	fi
+
+	orig_export_symbols=
+	case $host_os in
+	cygwin* | mingw* | cegcc*)
+	  if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+	    # exporting using user supplied symfile
+	    if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
+	      # and it's NOT already a .def file. Must figure out
+	      # which of the given symbols are data symbols and tag
+	      # them as such. So, trigger use of export_symbols_cmds.
+	      # export_symbols gets reassigned inside the "prepare
+	      # the list of exported symbols" if statement, so the
+	      # include_expsyms logic still works.
+	      orig_export_symbols="$export_symbols"
+	      export_symbols=
+	      always_export_symbols=yes
+	    fi
+	  fi
+	  ;;
+	esac
+
+	# Prepare the list of exported symbols
+	if test -z "$export_symbols"; then
+	  if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+	    func_verbose "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $opt_dry_run || $RM $export_symbols
+	    cmds=$export_symbols_cmds
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $cmds; do
+	      IFS="$save_ifs"
+	      eval "cmd=\"$cmd\""
+	      func_len " $cmd"
+	      len=$func_len_result
+	      if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+		func_show_eval "$cmd" 'exit $?'
+		skipped_export=false
+	      else
+		# The command line is too long to execute in one step.
+		func_verbose "using reloadable object file for export list..."
+		skipped_export=:
+		# Break out early, otherwise skipped_export may be
+		# set to false by a later but shorter cmd.
+		break
+	      fi
+	    done
+	    IFS="$save_ifs"
+	    if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+	fi
+
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  tmp_export_symbols="$export_symbols"
+	  test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	  $opt_dry_run || $ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"
+	fi
+
+	if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
+	  # The given exports_symbols file has to be filtered, so filter it.
+	  func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	  # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	  # 's' commands which not all seds can handle. GNU sed should be fine
+	  # though. Also, the filter scales superlinearly with the number of
+	  # global variables. join(1) would be nice here, but unfortunately
+	  # isn't a blessed tool.
+	  $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	  delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+	  export_symbols=$output_objdir/$libname.def
+	  $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	fi
+
+	tmp_deplibs=
+	for test_deplib in $deplibs; do
+	  case " $convenience " in
+	  *" $test_deplib "*) ;;
+	  *)
+	    tmp_deplibs="$tmp_deplibs $test_deplib"
+	    ;;
+	  esac
+	done
+	deplibs="$tmp_deplibs"
+
+	if test -n "$convenience"; then
+	  if test -n "$whole_archive_flag_spec" &&
+	    test "$compiler_needs_object" = yes &&
+	    test -z "$libobjs"; then
+	    # extract the archives, so we have objects to list.
+	    # TODO: could optimize this to just extract one archive.
+	    whole_archive_flag_spec=
+	  fi
+	  if test -n "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	    eval "libobjs=\"\$libobjs $whole_archive_flag_spec\""
+	    test "X$libobjs" = "X " && libobjs=
+	  else
+	    gentop="$output_objdir/${outputname}x"
+	    generated="$generated $gentop"
+
+	    func_extract_archives $gentop $convenience
+	    libobjs="$libobjs $func_extract_archives_result"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	fi
+
+	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+	  eval "flag=\"$thread_safe_flag_spec\""
+	  linker_flags="$linker_flags $flag"
+	fi
+
+	# Make a backup of the uninstalled library when relinking
+	if test "$mode" = relink; then
+	  $opt_dry_run || (cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U) || exit $?
+	fi
+
+	# Do each of the archive commands.
+	if test "$module" = yes && test -n "$module_cmds" ; then
+	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	    eval "test_cmds=\"$module_expsym_cmds\""
+	    cmds=$module_expsym_cmds
+	  else
+	    eval "test_cmds=\"$module_cmds\""
+	    cmds=$module_cmds
+	  fi
+	else
+	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	    eval "test_cmds=\"$archive_expsym_cmds\""
+	    cmds=$archive_expsym_cmds
+	  else
+	    eval "test_cmds=\"$archive_cmds\""
+	    cmds=$archive_cmds
+	  fi
+	fi
+
+	if test "X$skipped_export" != "X:" &&
+	   func_len " $test_cmds" &&
+	   len=$func_len_result &&
+	   test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
+	else
+	  # The command line is too long to link in one step, link piecewise
+	  # or, if using GNU ld and skipped_export is not :, use a linker
+	  # script.
+
+	  # Save the value of $output and $libobjs because we want to
+	  # use them later.  If we have whole_archive_flag_spec, we
+	  # want to use save_libobjs as it was before
+	  # whole_archive_flag_spec was expanded, because we can't
+	  # assume the linker understands whole_archive_flag_spec.
+	  # This may have to be revisited, in case too many
+	  # convenience libraries get linked in and end up exceeding
+	  # the spec.
+	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	  fi
+	  save_output=$output
+	  func_basename "$output"
+	  output_la=$func_basename_result
+
+	  # Clear the reloadable object creation command queue and
+	  # initialize k to one.
+	  test_cmds=
+	  concat_cmds=
+	  objlist=
+	  last_robj=
+	  k=1
+
+	  if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
+	    output=${output_objdir}/${output_la}.lnkscript
+	    func_verbose "creating GNU ld script: $output"
+	    echo 'INPUT (' > $output
+	    for obj in $save_libobjs
+	    do
+	      $ECHO "$obj" >> $output
+	    done
+	    echo ')' >> $output
+	    delfiles="$delfiles $output"
+	  elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
+	    output=${output_objdir}/${output_la}.lnk
+	    func_verbose "creating linker input file list: $output"
+	    : > $output
+	    set x $save_libobjs
+	    shift
+	    firstobj=
+	    if test "$compiler_needs_object" = yes; then
+	      firstobj="$1 "
+	      shift
+	    fi
+	    for obj
+	    do
+	      $ECHO "$obj" >> $output
+	    done
+	    delfiles="$delfiles $output"
+	    output=$firstobj\"$file_list_spec$output\"
+	  else
+	    if test -n "$save_libobjs"; then
+	      func_verbose "creating reloadable object files..."
+	      output=$output_objdir/$output_la-${k}.$objext
+	      eval "test_cmds=\"$reload_cmds\""
+	      func_len " $test_cmds"
+	      len0=$func_len_result
+	      len=$len0
+
+	      # Loop over the list of objects to be linked.
+	      for obj in $save_libobjs
+	      do
+		func_len " $obj"
+		func_arith $len + $func_len_result
+		len=$func_arith_result
+		if test "X$objlist" = X ||
+		   test "$len" -lt "$max_cmd_len"; then
+		  func_append objlist " $obj"
+		else
+		  # The command $test_cmds is almost too long, add a
+		  # command to the queue.
+		  if test "$k" -eq 1 ; then
+		    # The first file doesn't have a previous command to add.
+		    reload_objs=$objlist
+		    eval "concat_cmds=\"$reload_cmds\""
+		  else
+		    # All subsequent reloadable object files will link in
+		    # the last one created.
+		    reload_objs="$objlist $last_robj"
+		    eval "concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\""
+		  fi
+		  last_robj=$output_objdir/$output_la-${k}.$objext
+		  func_arith $k + 1
+		  k=$func_arith_result
+		  output=$output_objdir/$output_la-${k}.$objext
+		  objlist=" $obj"
+		  func_len " $last_robj"
+		  func_arith $len0 + $func_len_result
+		  len=$func_arith_result
+		fi
+	      done
+	      # Handle the remaining objects by creating one last
+	      # reloadable object file.  All subsequent reloadable object
+	      # files will link in the last one created.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      reload_objs="$objlist $last_robj"
+	      eval "concat_cmds=\"\${concat_cmds}$reload_cmds\""
+	      if test -n "$last_robj"; then
+	        eval "concat_cmds=\"\${concat_cmds}~\$RM $last_robj\""
+	      fi
+	      delfiles="$delfiles $output"
+
+	    else
+	      output=
+	    fi
+
+	    if ${skipped_export-false}; then
+	      func_verbose "generating symbol list for \`$libname.la'"
+	      export_symbols="$output_objdir/$libname.exp"
+	      $opt_dry_run || $RM $export_symbols
+	      libobjs=$output
+	      # Append the command to create the export file.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval "concat_cmds=\"\$concat_cmds$export_symbols_cmds\""
+	      if test -n "$last_robj"; then
+		eval "concat_cmds=\"\$concat_cmds~\$RM $last_robj\""
+	      fi
+	    fi
+
+	    test -n "$save_libobjs" &&
+	      func_verbose "creating a temporary reloadable object file: $output"
+
+	    # Loop through the commands generated above and execute them.
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $concat_cmds; do
+	      IFS="$save_ifs"
+	      $opt_silent || {
+		  func_quote_for_expand "$cmd"
+		  eval "func_echo $func_quote_for_expand_result"
+	      }
+	      $opt_dry_run || eval "$cmd" || {
+		lt_exit=$?
+
+		# Restore the uninstalled library and exit
+		if test "$mode" = relink; then
+		  ( cd "$output_objdir" && \
+		    $RM "${realname}T" && \
+		    $MV "${realname}U" "$realname" )
+		fi
+
+		exit $lt_exit
+	      }
+	    done
+	    IFS="$save_ifs"
+
+	    if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+
+          if ${skipped_export-false}; then
+	    if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	      tmp_export_symbols="$export_symbols"
+	      test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	      $opt_dry_run || $ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"
+	    fi
+
+	    if test -n "$orig_export_symbols"; then
+	      # The given exports_symbols file has to be filtered, so filter it.
+	      func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	      # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	      # 's' commands which not all seds can handle. GNU sed should be fine
+	      # though. Also, the filter scales superlinearly with the number of
+	      # global variables. join(1) would be nice here, but unfortunately
+	      # isn't a blessed tool.
+	      $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	      delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+	      export_symbols=$output_objdir/$libname.def
+	      $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	    fi
+	  fi
+
+	  libobjs=$output
+	  # Restore the value of output.
+	  output=$save_output
+
+	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+	    eval "libobjs=\"\$libobjs $whole_archive_flag_spec\""
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	  # Expand the library linking commands again to reset the
+	  # value of $libobjs for piecewise linking.
+
+	  # Do each of the archive commands.
+	  if test "$module" = yes && test -n "$module_cmds" ; then
+	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	      cmds=$module_expsym_cmds
+	    else
+	      cmds=$module_cmds
+	    fi
+	  else
+	    if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	      cmds=$archive_expsym_cmds
+	    else
+	      cmds=$archive_cmds
+	    fi
+	  fi
+	fi
+
+	if test -n "$delfiles"; then
+	  # Append the command to remove temporary files to $cmds.
+	  eval "cmds=\"\$cmds~\$RM $delfiles\""
+	fi
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  libobjs="$libobjs $func_extract_archives_result"
+	  test "X$libobjs" = "X " && libobjs=
+	fi
+
+	save_ifs="$IFS"; IFS='~'
+	for cmd in $cmds; do
+	  IFS="$save_ifs"
+	  eval "cmd=\"$cmd\""
+	  $opt_silent || {
+	    func_quote_for_expand "$cmd"
+	    eval "func_echo $func_quote_for_expand_result"
+	  }
+	  $opt_dry_run || eval "$cmd" || {
+	    lt_exit=$?
+
+	    # Restore the uninstalled library and exit
+	    if test "$mode" = relink; then
+	      ( cd "$output_objdir" && \
+	        $RM "${realname}T" && \
+		$MV "${realname}U" "$realname" )
+	    fi
+
+	    exit $lt_exit
+	  }
+	done
+	IFS="$save_ifs"
+
+	# Restore the uninstalled library and exit
+	if test "$mode" = relink; then
+	  $opt_dry_run || (cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname) || exit $?
+
+	  if test -n "$convenience"; then
+	    if test -z "$whole_archive_flag_spec"; then
+	      func_show_eval '${RM}r "$gentop"'
+	    fi
+	  fi
+
+	  exit $EXIT_SUCCESS
+	fi
+
+	# Create links to the real library.
+	for linkname in $linknames; do
+	  if test "$realname" != "$linkname"; then
+	    func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+	  fi
+	done
+
+	# If -module or -export-dynamic was specified, set the dlname.
+	if test "$module" = yes || test "$export_dynamic" = yes; then
+	  # On all known operating systems, these are identical.
+	  dlname="$soname"
+	fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for objects"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for objects" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for objects"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for objects"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for objects"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for objects"
+
+      case $output in
+      *.lo)
+	test -n "$objs$old_deplibs" && \
+	  func_fatal_error "cannot build library object \`$output' from non-libtool objects"
+
+	libobj=$output
+	func_lo2o "$libobj"
+	obj=$func_lo2o_result
+	;;
+      *)
+	libobj=
+	obj="$output"
+	;;
+      esac
+
+      # Delete the old objects.
+      $opt_dry_run || $RM $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
+      wl=
+
+      if test -n "$convenience"; then
+	if test -n "$whole_archive_flag_spec"; then
+	  eval "tmp_whole_archive_flags=\"$whole_archive_flag_spec\""
+	  reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
+	else
+	  gentop="$output_objdir/${obj}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $convenience
+	  reload_conv_objs="$reload_objs $func_extract_archives_result"
+	fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      func_execute_cmds "$reload_cmds" 'exit $?'
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	# Create an invalid libtool object if no PIC, so that we don't
+	# accidentally link it into a program.
+	# $show "echo timestamp > $libobj"
+	# $opt_dry_run || echo timestamp > $libobj || exit $?
+	exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+	# Only do commands if we really have different PIC objects.
+	reload_objs="$libobjs $reload_conv_objs"
+	output="$libobj"
+	func_execute_cmds "$reload_cmds" 'exit $?'
+      fi
+
+      if test -n "$gentop"; then
+	func_show_eval '${RM}r "$gentop"'
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+	*cygwin*) func_stripname '' '.exe' "$output"
+	          output=$func_stripname_result.exe;;
+      esac
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for programs"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for programs"
+
+      test "$preload" = yes \
+        && test "$dlopen_support" = unknown \
+	&& test "$dlopen_self" = unknown \
+	&& test "$dlopen_self_static" = unknown && \
+	  func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+	# On Rhapsody replace the C library is the System framework
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	;;
+      esac
+
+      case $host in
+      *-*-darwin*)
+	# Don't allow lazy linking, it breaks C++ global constructors
+	# But is supposedly fixed on 10.4 or later (yay!).
+	if test "$tagname" = CXX ; then
+	  case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+	    10.[0123])
+	      compile_command="$compile_command ${wl}-bind_at_load"
+	      finalize_command="$finalize_command ${wl}-bind_at_load"
+	    ;;
+	  esac
+	fi
+	# Time to change all our "foo.ltframework" stuff back to "-framework foo"
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $compile_deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs="$new_libs -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $compile_deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs="$new_libs $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs="$new_libs $deplib" ;;
+	esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      compile_command="$compile_command $compile_deplibs"
+      finalize_command="$finalize_command $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	for libdir in $rpath $xrpath; do
+	  # This is the magic to use -rpath.
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval "flag=\"$hardcode_libdir_flag_spec\""
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) perm_rpath="$perm_rpath $libdir" ;;
+	  esac
+	fi
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$libdir:"*) ;;
+	  ::) dllsearchpath=$libdir;;
+	  *) dllsearchpath="$dllsearchpath:$libdir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  esac
+	  ;;
+	esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval "rpath=\" $hardcode_libdir_flag_spec\""
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval "flag=\"$hardcode_libdir_flag_spec\""
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$finalize_perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+	  esac
+	fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval "rpath=\" $hardcode_libdir_flag_spec\""
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+	# Transform all the library objects into standard objects.
+	compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+      fi
+
+      func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
+
+      # template prelinking step
+      if test -n "$prelink_cmds"; then
+	func_execute_cmds "$prelink_cmds" 'exit $?'
+      fi
+
+      wrappers_required=yes
+      case $host in
+      *cegcc* | *mingw32ce*)
+        # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+        wrappers_required=no
+        ;;
+      *cygwin* | *mingw* )
+        if test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      *)
+        if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      esac
+      if test "$wrappers_required" = no; then
+	# Replace the output file specification.
+	compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+	link_command="$compile_command$compile_rpath"
+
+	# We have no uninstalled library dependencies, so finalize right now.
+	exit_status=0
+	func_show_eval "$link_command" 'exit_status=$?'
+
+	# Delete the generated files.
+	if test -f "$output_objdir/${outputname}S.${objext}"; then
+	  func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
+	fi
+
+	exit $exit_status
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+	if test -n "$perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+	if test -n "$finalize_perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $finalize_perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+      fi
+
+      if test "$no_install" = yes; then
+	# We don't need to create a wrapper script.
+	link_command="$compile_var$compile_command$compile_rpath"
+	# Replace the output file specification.
+	link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+	# Delete the old output file.
+	$opt_dry_run || $RM $output
+	# Link the executable and exit
+	func_show_eval "$link_command" 'exit $?'
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+	# Fast installation is not supported
+	link_command="$compile_var$compile_command$compile_rpath"
+	relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+	func_warning "this platform does not like uninstalled shared libraries"
+	func_warning "\`$output' will be relinked during installation"
+      else
+	if test "$fast_install" != no; then
+	  link_command="$finalize_var$compile_command$finalize_rpath"
+	  if test "$fast_install" = yes; then
+	    relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
+	  else
+	    # fast_install is set to needless
+	    relink_command=
+	  fi
+	else
+	  link_command="$compile_var$compile_command$compile_rpath"
+	  relink_command="$finalize_var$finalize_command$finalize_rpath"
+	fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      func_show_eval "$link_command" 'exit $?'
+
+      # Now create the wrapper script.
+      func_verbose "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+	# Preserve any variables that may affect compiler behavior
+	for var in $variables_saved_for_relink; do
+	  if eval test -z \"\${$var+set}\"; then
+	    relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	  elif eval var_value=\$$var; test -z "$var_value"; then
+	    relink_command="$var=; export $var; $relink_command"
+	  else
+	    func_quote_for_eval "$var_value"
+	    relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	  fi
+	done
+	relink_command="(cd `pwd`; $relink_command)"
+	relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if not in dry run mode.
+      $opt_dry_run || {
+	# win32 will think the script is a binary if it has
+	# a .exe suffix, so we strip it off here.
+	case $output in
+	  *.exe) func_stripname '' '.exe' "$output"
+	         output=$func_stripname_result ;;
+	esac
+	# test for cygwin because mv fails w/o .exe extensions
+	case $host in
+	  *cygwin*)
+	    exeext=.exe
+	    func_stripname '' '.exe' "$outputname"
+	    outputname=$func_stripname_result ;;
+	  *) exeext= ;;
+	esac
+	case $host in
+	  *cygwin* | *mingw* )
+	    func_dirname_and_basename "$output" "" "."
+	    output_name=$func_basename_result
+	    output_path=$func_dirname_result
+	    cwrappersource="$output_path/$objdir/lt-$output_name.c"
+	    cwrapper="$output_path/$output_name.exe"
+	    $RM $cwrappersource $cwrapper
+	    trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_cwrapperexe_src > $cwrappersource
+
+	    # The wrapper executable is built using the $host compiler,
+	    # because it contains $host paths and files. If cross-
+	    # compiling, it, like the target executable, must be
+	    # executed on the $host or under an emulation environment.
+	    $opt_dry_run || {
+	      $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+	      $STRIP $cwrapper
+	    }
+
+	    # Now, create the wrapper script for func_source use:
+	    func_ltwrapper_scriptname $cwrapper
+	    $RM $func_ltwrapper_scriptname_result
+	    trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+	    $opt_dry_run || {
+	      # note: this script will not be executed, so do not chmod.
+	      if test "x$build" = "x$host" ; then
+		$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+	      else
+		func_emit_wrapper no > $func_ltwrapper_scriptname_result
+	      fi
+	    }
+	  ;;
+	  * )
+	    $RM $output
+	    trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_wrapper no > $output
+	    chmod +x $output
+	  ;;
+	esac
+      }
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+	oldobjs="$libobjs_save $symfileobj"
+	addlibs="$convenience"
+	build_libtool_libs=no
+      else
+	if test "$build_libtool_libs" = module; then
+	  oldobjs="$libobjs_save"
+	  build_libtool_libs=no
+	else
+	  oldobjs="$old_deplibs $non_pic_objects"
+	  if test "$preload" = yes && test -f "$symfileobj"; then
+	    oldobjs="$oldobjs $symfileobj"
+	  fi
+	fi
+	addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+	gentop="$output_objdir/${outputname}x"
+	generated="$generated $gentop"
+
+	func_extract_archives $gentop $addlibs
+	oldobjs="$oldobjs $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+	cmds=$old_archive_from_new_cmds
+      else
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  oldobjs="$oldobjs $func_extract_archives_result"
+	fi
+
+	# POSIX demands no paths to be encoded in archives.  We have
+	# to avoid creating archives with duplicate basenames if we
+	# might have to extract them afterwards, e.g., when creating a
+	# static archive out of a convenience library, or when linking
+	# the entirety of a libtool archive into another (currently
+	# not supported by libtool).
+	if (for obj in $oldobjs
+	    do
+	      func_basename "$obj"
+	      $ECHO "$func_basename_result"
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	  :
+	else
+	  echo "copying selected object files to avoid basename conflicts..."
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+	  func_mkdir_p "$gentop"
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  counter=1
+	  for obj in $save_oldobjs
+	  do
+	    func_basename "$obj"
+	    objbase="$func_basename_result"
+	    case " $oldobjs " in
+	    " ") oldobjs=$obj ;;
+	    *[\ /]"$objbase "*)
+	      while :; do
+		# Make sure we don't pick an alternate name that also
+		# overlaps.
+		newobj=lt$counter-$objbase
+		func_arith $counter + 1
+		counter=$func_arith_result
+		case " $oldobjs " in
+		*[\ /]"$newobj "*) ;;
+		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
+		esac
+	      done
+	      func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+	      oldobjs="$oldobjs $gentop/$newobj"
+	      ;;
+	    *) oldobjs="$oldobjs $obj" ;;
+	    esac
+	  done
+	fi
+	eval "cmds=\"$old_archive_cmds\""
+
+	func_len " $cmds"
+	len=$func_len_result
+	if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  cmds=$old_archive_cmds
+	else
+	  # the command line is too long to link in one step, link in parts
+	  func_verbose "using piecewise archive linking..."
+	  save_RANLIB=$RANLIB
+	  RANLIB=:
+	  objlist=
+	  concat_cmds=
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  # Is there a better way of finding the last object in the list?
+	  for obj in $save_oldobjs
+	  do
+	    last_oldobj=$obj
+	  done
+	  eval "test_cmds=\"$old_archive_cmds\""
+	  func_len " $test_cmds"
+	  len0=$func_len_result
+	  len=$len0
+	  for obj in $save_oldobjs
+	  do
+	    func_len " $obj"
+	    func_arith $len + $func_len_result
+	    len=$func_arith_result
+	    func_append objlist " $obj"
+	    if test "$len" -lt "$max_cmd_len"; then
+	      :
+	    else
+	      # the above command should be used before it gets too long
+	      oldobjs=$objlist
+	      if test "$obj" = "$last_oldobj" ; then
+		RANLIB=$save_RANLIB
+	      fi
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval "concat_cmds=\"\${concat_cmds}$old_archive_cmds\""
+	      objlist=
+	      len=$len0
+	    fi
+	  done
+	  RANLIB=$save_RANLIB
+	  oldobjs=$objlist
+	  if test "X$oldobjs" = "X" ; then
+	    eval "cmds=\"\$concat_cmds\""
+	  else
+	    eval "cmds=\"\$concat_cmds~\$old_archive_cmds\""
+	  fi
+	fi
+      fi
+      func_execute_cmds "$cmds" 'exit $?'
+    done
+
+    test -n "$generated" && \
+      func_show_eval "${RM}r$generated"
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      func_verbose "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+	if eval test -z \"\${$var+set}\"; then
+	  relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	elif eval var_value=\$$var; test -z "$var_value"; then
+	  relink_command="$var=; export $var; $relink_command"
+	else
+	  func_quote_for_eval "$var_value"
+	  relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+	relink_command=
+      fi
+
+      # Only create the output if not a dry run.
+      $opt_dry_run || {
+	for installed in no yes; do
+	  if test "$installed" = yes; then
+	    if test -z "$install_libdir"; then
+	      break
+	    fi
+	    output="$output_objdir/$outputname"i
+	    # Replace all uninstalled libtool libraries with the installed ones
+	    newdependency_libs=
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      *.la)
+		func_basename "$deplib"
+		name="$func_basename_result"
+		libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$deplib' is not a valid libtool archive"
+		newdependency_libs="$newdependency_libs $libdir/$name"
+		;;
+	      *) newdependency_libs="$newdependency_libs $deplib" ;;
+	      esac
+	    done
+	    dependency_libs="$newdependency_libs"
+	    newdlfiles=
+
+	    for lib in $dlfiles; do
+	      case $lib in
+	      *.la)
+	        func_basename "$lib"
+		name="$func_basename_result"
+		libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		newdlfiles="$newdlfiles $libdir/$name"
+		;;
+	      *) newdlfiles="$newdlfiles $lib" ;;
+	      esac
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+	      *.la)
+		# Only pass preopened files to the pseudo-archive (for
+		# eventual linking with the app. that links it) if we
+		# didn't already link the preopened objects directly into
+		# the library:
+		func_basename "$lib"
+		name="$func_basename_result"
+		libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		newdlprefiles="$newdlprefiles $libdir/$name"
+		;;
+	      esac
+	    done
+	    dlprefiles="$newdlprefiles"
+	  else
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlfiles="$newdlfiles $abs"
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlprefiles="$newdlprefiles $abs"
+	    done
+	    dlprefiles="$newdlprefiles"
+	  fi
+	  $RM $output
+	  # place dlname in correct position for cygwin
+	  # In fact, it would be nice if we could use this code for all target
+	  # systems that can't hard-code library paths into their executables
+	  # and that have no shared library path variable independent of PATH,
+	  # but it turns out we can't easily determine that from inspecting
+	  # libtool variables, so we have to hard-code the OSs to which it
+	  # applies here; at the moment, that means platforms that use the PE
+	  # object format with DLL files.  See the long comment at the top of
+	  # tests/bindir.at for full details.
+	  tdlname=$dlname
+	  case $host,$output,$installed,$module,$dlname in
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
+	      # If a -bindir argument was supplied, place the dll there.
+	      if test "x$bindir" != x ;
+	      then
+		func_relative_path "$install_libdir" "$bindir"
+		tdlname=$func_relative_path_result$dlname
+	      else
+		# Otherwise fall back on heuristic.
+		tdlname=../bin/$dlname
+	      fi
+	      ;;
+	  esac
+	  $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+	  if test "$installed" = no && test "$need_relink" = yes; then
+	    $ECHO >> $output "\
+relink_command=\"$relink_command\""
+	  fi
+	done
+      }
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+}
+
+{ test "$mode" = link || test "$mode" = relink; } &&
+    func_mode_link ${1+"$@"}
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+    $opt_debug
+    RM="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) RM="$RM $arg"; rmforce=yes ;;
+      -*) RM="$RM $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    test -z "$RM" && \
+      func_fatal_help "you must specify an RM program"
+
+    rmdirs=
+
+    origobjdir="$objdir"
+    for file in $files; do
+      func_dirname "$file" "" "."
+      dir="$func_dirname_result"
+      if test "X$dir" = X.; then
+	objdir="$origobjdir"
+      else
+	objdir="$dir/$origobjdir"
+      fi
+      func_basename "$file"
+      name="$func_basename_result"
+      test "$mode" = uninstall && objdir="$dir"
+
+      # Remember objdir for removal later, being careful to avoid duplicates
+      if test "$mode" = clean; then
+	case " $rmdirs " in
+	  *" $objdir "*) ;;
+	  *) rmdirs="$rmdirs $objdir" ;;
+	esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if { test -L "$file"; } >/dev/null 2>&1 ||
+	 { test -h "$file"; } >/dev/null 2>&1 ||
+	 test -f "$file"; then
+	:
+      elif test -d "$file"; then
+	exit_status=1
+	continue
+      elif test "$rmforce" = yes; then
+	continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+	# Possibly a libtool archive, so verify it.
+	if func_lalib_p "$file"; then
+	  func_source $dir/$name
+
+	  # Delete the libtool libraries and symlinks.
+	  for n in $library_names; do
+	    rmfiles="$rmfiles $objdir/$n"
+	  done
+	  test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+	  case "$mode" in
+	  clean)
+	    case "  $library_names " in
+	    # "  " in the beginning catches empty $dlname
+	    *" $dlname "*) ;;
+	    *) rmfiles="$rmfiles $objdir/$dlname" ;;
+	    esac
+	    test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+	    ;;
+	  uninstall)
+	    if test -n "$library_names"; then
+	      # Do each command in the postuninstall commands.
+	      func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+
+	    if test -n "$old_library"; then
+	      # Do each command in the old_postuninstall commands.
+	      func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+	    # FIXME: should reinstall the best remaining shared library.
+	    ;;
+	  esac
+	fi
+	;;
+
+      *.lo)
+	# Possibly a libtool object, so verify it.
+	if func_lalib_p "$file"; then
+
+	  # Read the .lo file
+	  func_source $dir/$name
+
+	  # Add PIC object to the list of files to remove.
+	  if test -n "$pic_object" &&
+	     test "$pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$pic_object"
+	  fi
+
+	  # Add non-PIC object to the list of files to remove.
+	  if test -n "$non_pic_object" &&
+	     test "$non_pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$non_pic_object"
+	  fi
+	fi
+	;;
+
+      *)
+	if test "$mode" = clean ; then
+	  noexename=$name
+	  case $file in
+	  *.exe)
+	    func_stripname '' '.exe' "$file"
+	    file=$func_stripname_result
+	    func_stripname '' '.exe' "$name"
+	    noexename=$func_stripname_result
+	    # $file with .exe has already been added to rmfiles,
+	    # add $file without .exe
+	    rmfiles="$rmfiles $file"
+	    ;;
+	  esac
+	  # Do a test to see if this is a libtool program.
+	  if func_ltwrapper_p "$file"; then
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      relink_command=
+	      func_source $func_ltwrapper_scriptname_result
+	      rmfiles="$rmfiles $func_ltwrapper_scriptname_result"
+	    else
+	      relink_command=
+	      func_source $dir/$noexename
+	    fi
+
+	    # note $name still contains .exe if it was in $file originally
+	    # as does the version of $file that was added into $rmfiles
+	    rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+	    if test "$fast_install" = yes && test -n "$relink_command"; then
+	      rmfiles="$rmfiles $objdir/lt-$name"
+	    fi
+	    if test "X$noexename" != "X$name" ; then
+	      rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+	    fi
+	  fi
+	fi
+	;;
+      esac
+      func_show_eval "$RM $rmfiles" 'exit_status=1'
+    done
+    objdir="$origobjdir"
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+	func_show_eval "rmdir $dir >/dev/null 2>&1"
+      fi
+    done
+
+    exit $exit_status
+}
+
+{ test "$mode" = uninstall || test "$mode" = clean; } &&
+    func_mode_uninstall ${1+"$@"}
+
+test -z "$mode" && {
+  help="$generic_help"
+  func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+  func_fatal_help "invalid operation mode \`$mode'"
+
+if test -n "$exec_cmd"; then
+  eval exec "$exec_cmd"
+  exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
+# vi:sw=2
+
diff --git a/third_party/gofrontend/missing b/third_party/gofrontend/missing
new file mode 100644
index 0000000..28055d2
--- /dev/null
+++ b/third_party/gofrontend/missing
@@ -0,0 +1,376 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+# 2008, 2009 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  # Exit code 63 means version mismatch.  This often happens
+  # when the user try to use an ancient version of a tool on
+  # a file that requires a minimum version.  In this case we
+  # we should proceed has if the program had been absent, or
+  # if --run hadn't been passed.
+  if test $? = 63; then
+    run=:
+    msg="probably too old"
+  fi
+  ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  autom4te     touch the output file, or create a stub one
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
+\`g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# normalize program name to check for.
+program=`echo "$1" | sed '
+  s/^gnu-//; t
+  s/^gnu//; t
+  s/^g//; t'`
+
+# Now exit if we have it, but it failed.  Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).  This is about non-GNU programs, so use $1 not
+# $program.
+case $1 in
+  lex*|yacc*)
+    # Not GNU programs, they don't have --version.
+    ;;
+
+  tar*)
+    if test -n "$run"; then
+       echo 1>&2 "ERROR: \`tar' requires --run"
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       exit 1
+    fi
+    ;;
+
+  *)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       # Could not run --version or --help.  This is probably someone
+       # running `$TOOL --version' or `$TOOL --help' to check whether
+       # $TOOL exists and not knowing $TOOL uses missing.
+       exit 1
+    fi
+    ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $program in
+  aclocal*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case $f in
+      *:*) touch_files="$touch_files "`echo "$f" |
+				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+	   sed 's/\.am$/.in/' |
+	   while read f; do touch "$f"; done
+    ;;
+
+  autom4te*)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.
+         You can get \`$1' as part of \`Autoconf' from any GNU
+         archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo "#! /bin/sh"
+	echo "# Created by GNU Automake missing as a replacement of"
+	echo "#  $ $@"
+	echo "exit 0"
+	chmod +x $file
+	exit 1
+    fi
+    ;;
+
+  bison*|yacc*)
+    echo 1>&2 "\
+WARNING: \`$1' $msg.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+	case $LASTARG in
+	*.y)
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" y.tab.c
+	    fi
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" y.tab.h
+	    fi
+	  ;;
+	esac
+    fi
+    if test ! -f y.tab.h; then
+	echo >y.tab.h
+    fi
+    if test ! -f y.tab.c; then
+	echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex*|flex*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+	case $LASTARG in
+	*.l)
+	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" lex.yy.c
+	    fi
+	  ;;
+	esac
+    fi
+    if test ! -f lex.yy.c; then
+	echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+	 you modified a dependency of a manual page.  You may need the
+	 \`Help2man' package in order for those modifications to take
+	 effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo ".ab help2man is required to generate this page"
+	exit $?
+    fi
+    ;;
+
+  makeinfo*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    # The file to touch is that specified with -o ...
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -z "$file"; then
+      # ... or it is the one specified with @setfilename ...
+      infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '
+	/^@setfilename/{
+	  s/.* \([^ ]*\) *$/\1/
+	  p
+	  q
+	}' $infile`
+      # ... or it is derived from the source name (dir/f.texi becomes f.info)
+      test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+    fi
+    # If the file does not exist, the user really needs makeinfo;
+    # let's fail without touching anything.
+    test -f $file || exit 1
+    touch $file
+    ;;
+
+  tar*)
+    shift
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar "$@" && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar "$@" && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+	case $firstarg in
+	*o*)
+	    firstarg=`echo "$firstarg" | sed s/o//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+	case $firstarg in
+	*h*)
+	    firstarg=`echo "$firstarg" | sed s/h//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequisites for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/third_party/gofrontend/move-if-change b/third_party/gofrontend/move-if-change
new file mode 100755
index 0000000..1b8bac6
--- /dev/null
+++ b/third_party/gofrontend/move-if-change
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+
+# The mvifdiff.sh script works like the mv(1) command, except
+# that it does not touch the destination file if its contents
+# are the same as the source file.
+
+if cmp -s "$1" "$2" ; then
+  rm "$1"
+else
+  mv "$1" "$2"
+fi